From 644b04d0e18fcb105b5ac7f394390e3fd8363883 Mon Sep 17 00:00:00 2001 From: Douglas Stebila Date: Sat, 18 Mar 2023 11:10:29 -0400 Subject: [PATCH 01/10] Switch to new PQClean commit for SPHINCS+ and remove old patch file --- .../copy_from_upstream/copy_from_upstream.yml | 52 +- .../patches/pqclean-sphincs.patch | 2928 ----------------- 2 files changed, 26 insertions(+), 2954 deletions(-) delete mode 100644 scripts/copy_from_upstream/patches/pqclean-sphincs.patch diff --git a/scripts/copy_from_upstream/copy_from_upstream.yml b/scripts/copy_from_upstream/copy_from_upstream.yml index 4d4354800b..acd4ed707b 100644 --- a/scripts/copy_from_upstream/copy_from_upstream.yml +++ b/scripts/copy_from_upstream/copy_from_upstream.yml @@ -3,12 +3,12 @@ upstreams: name: pqclean git_url: https://github.com/PQClean/PQClean.git git_branch: master - git_commit: 245c95cd1ec326f8f38e26cb17a28832701ba17b + git_commit: c1b19a865de329e87e9b3e9152362fcb709da8ab kem_meta_path: 'crypto_kem/{pqclean_scheme}/META.yml' sig_meta_path: 'crypto_sign/{pqclean_scheme}/META.yml' kem_scheme_path: 'crypto_kem/{pqclean_scheme}' sig_scheme_path: 'crypto_sign/{pqclean_scheme}' - patches: [pqclean-sphincs.patch, pqclean-kyber-armneon-shake.patch, pqclean-kyber-arm-macos-gcc-fix.patch, pqclean-dilithium-arm-randomized-signing.patch] + patches: [pqclean-kyber-armneon-shake.patch, pqclean-kyber-arm-macos-gcc-fix.patch, pqclean-dilithium-arm-randomized-signing.patch] - name: pqcrystals-kyber git_url: https://github.com/pq-crystals/kyber.git @@ -243,121 +243,121 @@ sigs: signed_msg_order: sig_then_msg - scheme: sha256_128f_robust - pqclean_scheme: sphincs-sha256-128f-robust + pqclean_scheme: sphincs-sha2-128f-robust pretty_name_full: SPHINCS+-SHA256-128f-robust signed_msg_order: sig_then_msg - scheme: sha256_128f_simple - pqclean_scheme: sphincs-sha256-128f-simple + pqclean_scheme: sphincs-sha2-128f-simple pretty_name_full: SPHINCS+-SHA256-128f-simple signed_msg_order: sig_then_msg - scheme: sha256_128s_robust - pqclean_scheme: sphincs-sha256-128s-robust + pqclean_scheme: sphincs-sha2-128s-robust pretty_name_full: SPHINCS+-SHA256-128s-robust signed_msg_order: sig_then_msg - scheme: sha256_128s_simple - pqclean_scheme: sphincs-sha256-128s-simple + pqclean_scheme: sphincs-sha2-128s-simple pretty_name_full: SPHINCS+-SHA256-128s-simple signed_msg_order: sig_then_msg - scheme: sha256_192f_robust - pqclean_scheme: sphincs-sha256-192f-robust + pqclean_scheme: sphincs-sha2-192f-robust pretty_name_full: SPHINCS+-SHA256-192f-robust signed_msg_order: sig_then_msg - scheme: sha256_192f_simple - pqclean_scheme: sphincs-sha256-192f-simple + pqclean_scheme: sphincs-sha2-192f-simple pretty_name_full: SPHINCS+-SHA256-192f-simple signed_msg_order: sig_then_msg - scheme: sha256_192s_robust - pqclean_scheme: sphincs-sha256-192s-robust + pqclean_scheme: sphincs-sha2-192s-robust pretty_name_full: SPHINCS+-SHA256-192s-robust signed_msg_order: sig_then_msg - scheme: sha256_192s_simple - pqclean_scheme: sphincs-sha256-192s-simple + pqclean_scheme: sphincs-sha2-192s-simple pretty_name_full: SPHINCS+-SHA256-192s-simple signed_msg_order: sig_then_msg - scheme: sha256_256f_robust - pqclean_scheme: sphincs-sha256-256f-robust + pqclean_scheme: sphincs-sha2-256f-robust pretty_name_full: SPHINCS+-SHA256-256f-robust signed_msg_order: sig_then_msg - scheme: sha256_256f_simple - pqclean_scheme: sphincs-sha256-256f-simple + pqclean_scheme: sphincs-sha2-256f-simple pretty_name_full: SPHINCS+-SHA256-256f-simple signed_msg_order: sig_then_msg - scheme: sha256_256s_robust - pqclean_scheme: sphincs-sha256-256s-robust + pqclean_scheme: sphincs-sha2-256s-robust pretty_name_full: SPHINCS+-SHA256-256s-robust signed_msg_order: sig_then_msg - scheme: sha256_256s_simple - pqclean_scheme: sphincs-sha256-256s-simple + pqclean_scheme: sphincs-sha2-256s-simple pretty_name_full: SPHINCS+-SHA256-256s-simple signed_msg_order: sig_then_msg - scheme: shake256_128f_robust - pqclean_scheme: sphincs-shake256-128f-robust + pqclean_scheme: sphincs-shake-128f-robust pretty_name_full: SPHINCS+-SHAKE256-128f-robust signed_msg_order: sig_then_msg - scheme: shake256_128f_simple - pqclean_scheme: sphincs-shake256-128f-simple + pqclean_scheme: sphincs-shake-128f-simple pretty_name_full: SPHINCS+-SHAKE256-128f-simple signed_msg_order: sig_then_msg - scheme: shake256_128s_robust - pqclean_scheme: sphincs-shake256-128s-robust + pqclean_scheme: sphincs-shake-128s-robust pretty_name_full: SPHINCS+-SHAKE256-128s-robust signed_msg_order: sig_then_msg - scheme: shake256_128s_simple - pqclean_scheme: sphincs-shake256-128s-simple + pqclean_scheme: sphincs-shake-128s-simple pretty_name_full: SPHINCS+-SHAKE256-128s-simple signed_msg_order: sig_then_msg - scheme: shake256_192f_robust - pqclean_scheme: sphincs-shake256-192f-robust + pqclean_scheme: sphincs-shake-192f-robust pretty_name_full: SPHINCS+-SHAKE256-192f-robust signed_msg_order: sig_then_msg - scheme: shake256_192f_simple - pqclean_scheme: sphincs-shake256-192f-simple + pqclean_scheme: sphincs-shake-192f-simple pretty_name_full: SPHINCS+-SHAKE256-192f-simple signed_msg_order: sig_then_msg - scheme: shake256_192s_robust - pqclean_scheme: sphincs-shake256-192s-robust + pqclean_scheme: sphincs-shake-192s-robust pretty_name_full: SPHINCS+-SHAKE256-192s-robust signed_msg_order: sig_then_msg - scheme: shake256_192s_simple - pqclean_scheme: sphincs-shake256-192s-simple + pqclean_scheme: sphincs-shake-192s-simple pretty_name_full: SPHINCS+-SHAKE256-192s-simple signed_msg_order: sig_then_msg - scheme: shake256_256f_robust - pqclean_scheme: sphincs-shake256-256f-robust + pqclean_scheme: sphincs-shake-256f-robust pretty_name_full: SPHINCS+-SHAKE256-256f-robust signed_msg_order: sig_then_msg - scheme: shake256_256f_simple - pqclean_scheme: sphincs-shake256-256f-simple + pqclean_scheme: sphincs-shake-256f-simple pretty_name_full: SPHINCS+-SHAKE256-256f-simple signed_msg_order: sig_then_msg - scheme: shake256_256s_robust - pqclean_scheme: sphincs-shake256-256s-robust + pqclean_scheme: sphincs-shake-256s-robust pretty_name_full: SPHINCS+-SHAKE256-256s-robust signed_msg_order: sig_then_msg - scheme: shake256_256s_simple - pqclean_scheme: sphincs-shake256-256s-simple + pqclean_scheme: sphincs-shake-256s-simple pretty_name_full: SPHINCS+-SHAKE256-256s-simple signed_msg_order: sig_then_msg diff --git a/scripts/copy_from_upstream/patches/pqclean-sphincs.patch b/scripts/copy_from_upstream/patches/pqclean-sphincs.patch deleted file mode 100644 index 466c45da2e..0000000000 --- a/scripts/copy_from_upstream/patches/pqclean-sphincs.patch +++ /dev/null @@ -1,2928 +0,0 @@ -diff --git a/crypto_sign/sphincs-shake256-128f-robust/avx2/fips202x4.c b/crypto_sign/sphincs-shake256-128f-robust/avx2/fips202x4.c -deleted file mode 100644 -index ed4fe62..0000000 ---- a/crypto_sign/sphincs-shake256-128f-robust/avx2/fips202x4.c -+++ /dev/null -@@ -1,205 +0,0 @@ --#include --#include --#include -- --#include "fips202.h" --#include "fips202x4.h" -- --#define NROUNDS 24 --#define ROL(a, offset) (((a) << (offset)) ^ ((a) >> (64-(offset)))) -- --static uint64_t load64(const unsigned char *x) { -- unsigned long long r = 0, i; -- -- for (i = 0; i < 8; ++i) { -- r |= (unsigned long long)x[i] << 8 * i; -- } -- return r; --} -- --static void store64(uint8_t *x, uint64_t u) { -- unsigned int i; -- -- for (i = 0; i < 8; ++i) { -- x[i] = (uint8_t)u; -- u >>= 8; -- } --} -- --/* Use implementation from the Keccak Code Package */ --extern void KeccakP1600times4_PermuteAll_24rounds(__m256i *s); --#define KeccakF1600_StatePermute4x KeccakP1600times4_PermuteAll_24rounds -- --static void keccak_absorb4x(__m256i *s, -- unsigned int r, -- const unsigned char *m0, -- const unsigned char *m1, -- const unsigned char *m2, -- const unsigned char *m3, -- size_t mlen, -- unsigned char p) { -- unsigned char t0[200] = {0}; -- unsigned char t1[200] = {0}; -- unsigned char t2[200] = {0}; -- unsigned char t3[200] = {0}; -- -- unsigned long long *ss = (unsigned long long *)s; -- -- -- while (mlen >= r) { -- for (size_t i = 0; i < r / 8; ++i) { -- ss[4 * i + 0] ^= load64(m0 + 8 * i); -- ss[4 * i + 1] ^= load64(m1 + 8 * i); -- ss[4 * i + 2] ^= load64(m2 + 8 * i); -- ss[4 * i + 3] ^= load64(m3 + 8 * i); -- } -- -- KeccakF1600_StatePermute4x(s); -- mlen -= r; -- m0 += r; -- m1 += r; -- m2 += r; -- m3 += r; -- } -- -- memcpy(t0, m0, mlen); -- memcpy(t1, m1, mlen); -- memcpy(t2, m2, mlen); -- memcpy(t3, m3, mlen); -- -- t0[mlen] = p; -- t1[mlen] = p; -- t2[mlen] = p; -- t3[mlen] = p; -- -- t0[r - 1] |= 128; -- t1[r - 1] |= 128; -- t2[r - 1] |= 128; -- t3[r - 1] |= 128; -- -- for (size_t i = 0; i < r / 8; ++i) { -- ss[4 * i + 0] ^= load64(t0 + 8 * i); -- ss[4 * i + 1] ^= load64(t1 + 8 * i); -- ss[4 * i + 2] ^= load64(t2 + 8 * i); -- ss[4 * i + 3] ^= load64(t3 + 8 * i); -- } --} -- -- --static void keccak_squeezeblocks4x(unsigned char *h0, -- unsigned char *h1, -- unsigned char *h2, -- unsigned char *h3, -- unsigned long long int nblocks, -- __m256i *s, -- unsigned int r) { -- unsigned int i; -- -- unsigned long long *ss = (unsigned long long *)s; -- -- while (nblocks > 0) { -- KeccakF1600_StatePermute4x(s); -- for (i = 0; i < (r >> 3); i++) { -- store64(h0 + 8 * i, ss[4 * i + 0]); -- store64(h1 + 8 * i, ss[4 * i + 1]); -- store64(h2 + 8 * i, ss[4 * i + 2]); -- store64(h3 + 8 * i, ss[4 * i + 3]); -- } -- h0 += r; -- h1 += r; -- h2 += r; -- h3 += r; -- nblocks--; -- } --} -- -- -- --void PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_shake128x4(unsigned char *out0, -- unsigned char *out1, -- unsigned char *out2, -- unsigned char *out3, -- unsigned long long outlen, -- unsigned char *in0, -- unsigned char *in1, -- unsigned char *in2, -- unsigned char *in3, -- unsigned long long inlen) { -- __m256i s[25]; -- unsigned char t0[SHAKE128_RATE]; -- unsigned char t1[SHAKE128_RATE]; -- unsigned char t2[SHAKE128_RATE]; -- unsigned char t3[SHAKE128_RATE]; -- unsigned int i; -- -- /* zero state */ -- for (i = 0; i < 25; i++) { -- s[i] = _mm256_xor_si256(s[i], s[i]); -- } -- -- /* absorb 4 message of identical length in parallel */ -- keccak_absorb4x(s, SHAKE128_RATE, in0, in1, in2, in3, (size_t)inlen, 0x1F); -- -- /* Squeeze output */ -- keccak_squeezeblocks4x(out0, out1, out2, out3, outlen / SHAKE128_RATE, s, SHAKE128_RATE); -- -- out0 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; -- out1 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; -- out2 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; -- out3 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; -- -- if (outlen % SHAKE128_RATE) { -- keccak_squeezeblocks4x(t0, t1, t2, t3, 1, s, SHAKE128_RATE); -- for (i = 0; i < outlen % SHAKE128_RATE; i++) { -- out0[i] = t0[i]; -- out1[i] = t1[i]; -- out2[i] = t2[i]; -- out3[i] = t3[i]; -- } -- } --} -- -- --void PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_shake256x4(unsigned char *out0, -- unsigned char *out1, -- unsigned char *out2, -- unsigned char *out3, -- unsigned long long outlen, -- unsigned char *in0, -- unsigned char *in1, -- unsigned char *in2, -- unsigned char *in3, -- unsigned long long inlen) { -- __m256i s[25]; -- unsigned char t0[SHAKE256_RATE]; -- unsigned char t1[SHAKE256_RATE]; -- unsigned char t2[SHAKE256_RATE]; -- unsigned char t3[SHAKE256_RATE]; -- unsigned int i; -- -- /* zero state */ -- for (i = 0; i < 25; i++) { -- s[i] = _mm256_xor_si256(s[i], s[i]); -- } -- -- /* absorb 4 message of identical length in parallel */ -- keccak_absorb4x(s, SHAKE256_RATE, in0, in1, in2, in3, (size_t)inlen, 0x1F); -- -- /* Squeeze output */ -- keccak_squeezeblocks4x(out0, out1, out2, out3, outlen / SHAKE256_RATE, s, SHAKE256_RATE); -- -- out0 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; -- out1 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; -- out2 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; -- out3 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; -- -- if (outlen % SHAKE256_RATE) { -- keccak_squeezeblocks4x(t0, t1, t2, t3, 1, s, SHAKE256_RATE); -- for (i = 0; i < outlen % SHAKE256_RATE; i++) { -- out0[i] = t0[i]; -- out1[i] = t1[i]; -- out2[i] = t2[i]; -- out3[i] = t3[i]; -- } -- } --} -diff --git a/crypto_sign/sphincs-shake256-128f-robust/avx2/fips202x4.h b/crypto_sign/sphincs-shake256-128f-robust/avx2/fips202x4.h -deleted file mode 100644 -index 7d01578..0000000 ---- a/crypto_sign/sphincs-shake256-128f-robust/avx2/fips202x4.h -+++ /dev/null -@@ -1,27 +0,0 @@ --#ifndef PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_FIPS202X4_H --#define PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_FIPS202X4_H -- --#include -- --void PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_shake128x4(unsigned char *out0, -- unsigned char *out1, -- unsigned char *out2, -- unsigned char *out3, -- unsigned long long outlen, -- unsigned char *in0, -- unsigned char *in1, -- unsigned char *in2, -- unsigned char *in3, unsigned long long inlen); -- --void PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_shake256x4(unsigned char *out0, -- unsigned char *out1, -- unsigned char *out2, -- unsigned char *out3, -- unsigned long long outlen, -- unsigned char *in0, -- unsigned char *in1, -- unsigned char *in2, -- unsigned char *in3, -- unsigned long long inlen); -- --#endif -diff --git a/crypto_sign/sphincs-shake256-128f-simple/avx2/fips202x4.c b/crypto_sign/sphincs-shake256-128f-simple/avx2/fips202x4.c -deleted file mode 100644 -index 3f1a5e0..0000000 ---- a/crypto_sign/sphincs-shake256-128f-simple/avx2/fips202x4.c -+++ /dev/null -@@ -1,205 +0,0 @@ --#include --#include --#include -- --#include "fips202.h" --#include "fips202x4.h" -- --#define NROUNDS 24 --#define ROL(a, offset) (((a) << (offset)) ^ ((a) >> (64-(offset)))) -- --static uint64_t load64(const unsigned char *x) { -- unsigned long long r = 0, i; -- -- for (i = 0; i < 8; ++i) { -- r |= (unsigned long long)x[i] << 8 * i; -- } -- return r; --} -- --static void store64(uint8_t *x, uint64_t u) { -- unsigned int i; -- -- for (i = 0; i < 8; ++i) { -- x[i] = (uint8_t)u; -- u >>= 8; -- } --} -- --/* Use implementation from the Keccak Code Package */ --extern void KeccakP1600times4_PermuteAll_24rounds(__m256i *s); --#define KeccakF1600_StatePermute4x KeccakP1600times4_PermuteAll_24rounds -- --static void keccak_absorb4x(__m256i *s, -- unsigned int r, -- const unsigned char *m0, -- const unsigned char *m1, -- const unsigned char *m2, -- const unsigned char *m3, -- size_t mlen, -- unsigned char p) { -- unsigned char t0[200] = {0}; -- unsigned char t1[200] = {0}; -- unsigned char t2[200] = {0}; -- unsigned char t3[200] = {0}; -- -- unsigned long long *ss = (unsigned long long *)s; -- -- -- while (mlen >= r) { -- for (size_t i = 0; i < r / 8; ++i) { -- ss[4 * i + 0] ^= load64(m0 + 8 * i); -- ss[4 * i + 1] ^= load64(m1 + 8 * i); -- ss[4 * i + 2] ^= load64(m2 + 8 * i); -- ss[4 * i + 3] ^= load64(m3 + 8 * i); -- } -- -- KeccakF1600_StatePermute4x(s); -- mlen -= r; -- m0 += r; -- m1 += r; -- m2 += r; -- m3 += r; -- } -- -- memcpy(t0, m0, mlen); -- memcpy(t1, m1, mlen); -- memcpy(t2, m2, mlen); -- memcpy(t3, m3, mlen); -- -- t0[mlen] = p; -- t1[mlen] = p; -- t2[mlen] = p; -- t3[mlen] = p; -- -- t0[r - 1] |= 128; -- t1[r - 1] |= 128; -- t2[r - 1] |= 128; -- t3[r - 1] |= 128; -- -- for (size_t i = 0; i < r / 8; ++i) { -- ss[4 * i + 0] ^= load64(t0 + 8 * i); -- ss[4 * i + 1] ^= load64(t1 + 8 * i); -- ss[4 * i + 2] ^= load64(t2 + 8 * i); -- ss[4 * i + 3] ^= load64(t3 + 8 * i); -- } --} -- -- --static void keccak_squeezeblocks4x(unsigned char *h0, -- unsigned char *h1, -- unsigned char *h2, -- unsigned char *h3, -- unsigned long long int nblocks, -- __m256i *s, -- unsigned int r) { -- unsigned int i; -- -- unsigned long long *ss = (unsigned long long *)s; -- -- while (nblocks > 0) { -- KeccakF1600_StatePermute4x(s); -- for (i = 0; i < (r >> 3); i++) { -- store64(h0 + 8 * i, ss[4 * i + 0]); -- store64(h1 + 8 * i, ss[4 * i + 1]); -- store64(h2 + 8 * i, ss[4 * i + 2]); -- store64(h3 + 8 * i, ss[4 * i + 3]); -- } -- h0 += r; -- h1 += r; -- h2 += r; -- h3 += r; -- nblocks--; -- } --} -- -- -- --void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_shake128x4(unsigned char *out0, -- unsigned char *out1, -- unsigned char *out2, -- unsigned char *out3, -- unsigned long long outlen, -- unsigned char *in0, -- unsigned char *in1, -- unsigned char *in2, -- unsigned char *in3, -- unsigned long long inlen) { -- __m256i s[25]; -- unsigned char t0[SHAKE128_RATE]; -- unsigned char t1[SHAKE128_RATE]; -- unsigned char t2[SHAKE128_RATE]; -- unsigned char t3[SHAKE128_RATE]; -- unsigned int i; -- -- /* zero state */ -- for (i = 0; i < 25; i++) { -- s[i] = _mm256_xor_si256(s[i], s[i]); -- } -- -- /* absorb 4 message of identical length in parallel */ -- keccak_absorb4x(s, SHAKE128_RATE, in0, in1, in2, in3, (size_t)inlen, 0x1F); -- -- /* Squeeze output */ -- keccak_squeezeblocks4x(out0, out1, out2, out3, outlen / SHAKE128_RATE, s, SHAKE128_RATE); -- -- out0 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; -- out1 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; -- out2 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; -- out3 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; -- -- if (outlen % SHAKE128_RATE) { -- keccak_squeezeblocks4x(t0, t1, t2, t3, 1, s, SHAKE128_RATE); -- for (i = 0; i < outlen % SHAKE128_RATE; i++) { -- out0[i] = t0[i]; -- out1[i] = t1[i]; -- out2[i] = t2[i]; -- out3[i] = t3[i]; -- } -- } --} -- -- --void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_shake256x4(unsigned char *out0, -- unsigned char *out1, -- unsigned char *out2, -- unsigned char *out3, -- unsigned long long outlen, -- unsigned char *in0, -- unsigned char *in1, -- unsigned char *in2, -- unsigned char *in3, -- unsigned long long inlen) { -- __m256i s[25]; -- unsigned char t0[SHAKE256_RATE]; -- unsigned char t1[SHAKE256_RATE]; -- unsigned char t2[SHAKE256_RATE]; -- unsigned char t3[SHAKE256_RATE]; -- unsigned int i; -- -- /* zero state */ -- for (i = 0; i < 25; i++) { -- s[i] = _mm256_xor_si256(s[i], s[i]); -- } -- -- /* absorb 4 message of identical length in parallel */ -- keccak_absorb4x(s, SHAKE256_RATE, in0, in1, in2, in3, (size_t)inlen, 0x1F); -- -- /* Squeeze output */ -- keccak_squeezeblocks4x(out0, out1, out2, out3, outlen / SHAKE256_RATE, s, SHAKE256_RATE); -- -- out0 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; -- out1 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; -- out2 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; -- out3 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; -- -- if (outlen % SHAKE256_RATE) { -- keccak_squeezeblocks4x(t0, t1, t2, t3, 1, s, SHAKE256_RATE); -- for (i = 0; i < outlen % SHAKE256_RATE; i++) { -- out0[i] = t0[i]; -- out1[i] = t1[i]; -- out2[i] = t2[i]; -- out3[i] = t3[i]; -- } -- } --} -diff --git a/crypto_sign/sphincs-shake256-128f-simple/avx2/fips202x4.h b/crypto_sign/sphincs-shake256-128f-simple/avx2/fips202x4.h -deleted file mode 100644 -index a68603b..0000000 ---- a/crypto_sign/sphincs-shake256-128f-simple/avx2/fips202x4.h -+++ /dev/null -@@ -1,27 +0,0 @@ --#ifndef PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_FIPS202X4_H --#define PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_FIPS202X4_H -- --#include -- --void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_shake128x4(unsigned char *out0, -- unsigned char *out1, -- unsigned char *out2, -- unsigned char *out3, -- unsigned long long outlen, -- unsigned char *in0, -- unsigned char *in1, -- unsigned char *in2, -- unsigned char *in3, unsigned long long inlen); -- --void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_shake256x4(unsigned char *out0, -- unsigned char *out1, -- unsigned char *out2, -- unsigned char *out3, -- unsigned long long outlen, -- unsigned char *in0, -- unsigned char *in1, -- unsigned char *in2, -- unsigned char *in3, -- unsigned long long inlen); -- --#endif -diff --git a/crypto_sign/sphincs-shake256-128s-robust/avx2/fips202x4.c b/crypto_sign/sphincs-shake256-128s-robust/avx2/fips202x4.c -deleted file mode 100644 -index b23ebc6..0000000 ---- a/crypto_sign/sphincs-shake256-128s-robust/avx2/fips202x4.c -+++ /dev/null -@@ -1,205 +0,0 @@ --#include --#include --#include -- --#include "fips202.h" --#include "fips202x4.h" -- --#define NROUNDS 24 --#define ROL(a, offset) (((a) << (offset)) ^ ((a) >> (64-(offset)))) -- --static uint64_t load64(const unsigned char *x) { -- unsigned long long r = 0, i; -- -- for (i = 0; i < 8; ++i) { -- r |= (unsigned long long)x[i] << 8 * i; -- } -- return r; --} -- --static void store64(uint8_t *x, uint64_t u) { -- unsigned int i; -- -- for (i = 0; i < 8; ++i) { -- x[i] = (uint8_t)u; -- u >>= 8; -- } --} -- --/* Use implementation from the Keccak Code Package */ --extern void KeccakP1600times4_PermuteAll_24rounds(__m256i *s); --#define KeccakF1600_StatePermute4x KeccakP1600times4_PermuteAll_24rounds -- --static void keccak_absorb4x(__m256i *s, -- unsigned int r, -- const unsigned char *m0, -- const unsigned char *m1, -- const unsigned char *m2, -- const unsigned char *m3, -- size_t mlen, -- unsigned char p) { -- unsigned char t0[200] = {0}; -- unsigned char t1[200] = {0}; -- unsigned char t2[200] = {0}; -- unsigned char t3[200] = {0}; -- -- unsigned long long *ss = (unsigned long long *)s; -- -- -- while (mlen >= r) { -- for (size_t i = 0; i < r / 8; ++i) { -- ss[4 * i + 0] ^= load64(m0 + 8 * i); -- ss[4 * i + 1] ^= load64(m1 + 8 * i); -- ss[4 * i + 2] ^= load64(m2 + 8 * i); -- ss[4 * i + 3] ^= load64(m3 + 8 * i); -- } -- -- KeccakF1600_StatePermute4x(s); -- mlen -= r; -- m0 += r; -- m1 += r; -- m2 += r; -- m3 += r; -- } -- -- memcpy(t0, m0, mlen); -- memcpy(t1, m1, mlen); -- memcpy(t2, m2, mlen); -- memcpy(t3, m3, mlen); -- -- t0[mlen] = p; -- t1[mlen] = p; -- t2[mlen] = p; -- t3[mlen] = p; -- -- t0[r - 1] |= 128; -- t1[r - 1] |= 128; -- t2[r - 1] |= 128; -- t3[r - 1] |= 128; -- -- for (size_t i = 0; i < r / 8; ++i) { -- ss[4 * i + 0] ^= load64(t0 + 8 * i); -- ss[4 * i + 1] ^= load64(t1 + 8 * i); -- ss[4 * i + 2] ^= load64(t2 + 8 * i); -- ss[4 * i + 3] ^= load64(t3 + 8 * i); -- } --} -- -- --static void keccak_squeezeblocks4x(unsigned char *h0, -- unsigned char *h1, -- unsigned char *h2, -- unsigned char *h3, -- unsigned long long int nblocks, -- __m256i *s, -- unsigned int r) { -- unsigned int i; -- -- unsigned long long *ss = (unsigned long long *)s; -- -- while (nblocks > 0) { -- KeccakF1600_StatePermute4x(s); -- for (i = 0; i < (r >> 3); i++) { -- store64(h0 + 8 * i, ss[4 * i + 0]); -- store64(h1 + 8 * i, ss[4 * i + 1]); -- store64(h2 + 8 * i, ss[4 * i + 2]); -- store64(h3 + 8 * i, ss[4 * i + 3]); -- } -- h0 += r; -- h1 += r; -- h2 += r; -- h3 += r; -- nblocks--; -- } --} -- -- -- --void PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_shake128x4(unsigned char *out0, -- unsigned char *out1, -- unsigned char *out2, -- unsigned char *out3, -- unsigned long long outlen, -- unsigned char *in0, -- unsigned char *in1, -- unsigned char *in2, -- unsigned char *in3, -- unsigned long long inlen) { -- __m256i s[25]; -- unsigned char t0[SHAKE128_RATE]; -- unsigned char t1[SHAKE128_RATE]; -- unsigned char t2[SHAKE128_RATE]; -- unsigned char t3[SHAKE128_RATE]; -- unsigned int i; -- -- /* zero state */ -- for (i = 0; i < 25; i++) { -- s[i] = _mm256_xor_si256(s[i], s[i]); -- } -- -- /* absorb 4 message of identical length in parallel */ -- keccak_absorb4x(s, SHAKE128_RATE, in0, in1, in2, in3, (size_t)inlen, 0x1F); -- -- /* Squeeze output */ -- keccak_squeezeblocks4x(out0, out1, out2, out3, outlen / SHAKE128_RATE, s, SHAKE128_RATE); -- -- out0 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; -- out1 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; -- out2 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; -- out3 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; -- -- if (outlen % SHAKE128_RATE) { -- keccak_squeezeblocks4x(t0, t1, t2, t3, 1, s, SHAKE128_RATE); -- for (i = 0; i < outlen % SHAKE128_RATE; i++) { -- out0[i] = t0[i]; -- out1[i] = t1[i]; -- out2[i] = t2[i]; -- out3[i] = t3[i]; -- } -- } --} -- -- --void PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_shake256x4(unsigned char *out0, -- unsigned char *out1, -- unsigned char *out2, -- unsigned char *out3, -- unsigned long long outlen, -- unsigned char *in0, -- unsigned char *in1, -- unsigned char *in2, -- unsigned char *in3, -- unsigned long long inlen) { -- __m256i s[25]; -- unsigned char t0[SHAKE256_RATE]; -- unsigned char t1[SHAKE256_RATE]; -- unsigned char t2[SHAKE256_RATE]; -- unsigned char t3[SHAKE256_RATE]; -- unsigned int i; -- -- /* zero state */ -- for (i = 0; i < 25; i++) { -- s[i] = _mm256_xor_si256(s[i], s[i]); -- } -- -- /* absorb 4 message of identical length in parallel */ -- keccak_absorb4x(s, SHAKE256_RATE, in0, in1, in2, in3, (size_t)inlen, 0x1F); -- -- /* Squeeze output */ -- keccak_squeezeblocks4x(out0, out1, out2, out3, outlen / SHAKE256_RATE, s, SHAKE256_RATE); -- -- out0 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; -- out1 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; -- out2 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; -- out3 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; -- -- if (outlen % SHAKE256_RATE) { -- keccak_squeezeblocks4x(t0, t1, t2, t3, 1, s, SHAKE256_RATE); -- for (i = 0; i < outlen % SHAKE256_RATE; i++) { -- out0[i] = t0[i]; -- out1[i] = t1[i]; -- out2[i] = t2[i]; -- out3[i] = t3[i]; -- } -- } --} -diff --git a/crypto_sign/sphincs-shake256-128s-robust/avx2/fips202x4.h b/crypto_sign/sphincs-shake256-128s-robust/avx2/fips202x4.h -deleted file mode 100644 -index fd35c87..0000000 ---- a/crypto_sign/sphincs-shake256-128s-robust/avx2/fips202x4.h -+++ /dev/null -@@ -1,27 +0,0 @@ --#ifndef PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_FIPS202X4_H --#define PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_FIPS202X4_H -- --#include -- --void PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_shake128x4(unsigned char *out0, -- unsigned char *out1, -- unsigned char *out2, -- unsigned char *out3, -- unsigned long long outlen, -- unsigned char *in0, -- unsigned char *in1, -- unsigned char *in2, -- unsigned char *in3, unsigned long long inlen); -- --void PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_shake256x4(unsigned char *out0, -- unsigned char *out1, -- unsigned char *out2, -- unsigned char *out3, -- unsigned long long outlen, -- unsigned char *in0, -- unsigned char *in1, -- unsigned char *in2, -- unsigned char *in3, -- unsigned long long inlen); -- --#endif -diff --git a/crypto_sign/sphincs-shake256-128s-simple/avx2/fips202x4.c b/crypto_sign/sphincs-shake256-128s-simple/avx2/fips202x4.c -deleted file mode 100644 -index 58f98b3..0000000 ---- a/crypto_sign/sphincs-shake256-128s-simple/avx2/fips202x4.c -+++ /dev/null -@@ -1,205 +0,0 @@ --#include --#include --#include -- --#include "fips202.h" --#include "fips202x4.h" -- --#define NROUNDS 24 --#define ROL(a, offset) (((a) << (offset)) ^ ((a) >> (64-(offset)))) -- --static uint64_t load64(const unsigned char *x) { -- unsigned long long r = 0, i; -- -- for (i = 0; i < 8; ++i) { -- r |= (unsigned long long)x[i] << 8 * i; -- } -- return r; --} -- --static void store64(uint8_t *x, uint64_t u) { -- unsigned int i; -- -- for (i = 0; i < 8; ++i) { -- x[i] = (uint8_t)u; -- u >>= 8; -- } --} -- --/* Use implementation from the Keccak Code Package */ --extern void KeccakP1600times4_PermuteAll_24rounds(__m256i *s); --#define KeccakF1600_StatePermute4x KeccakP1600times4_PermuteAll_24rounds -- --static void keccak_absorb4x(__m256i *s, -- unsigned int r, -- const unsigned char *m0, -- const unsigned char *m1, -- const unsigned char *m2, -- const unsigned char *m3, -- size_t mlen, -- unsigned char p) { -- unsigned char t0[200] = {0}; -- unsigned char t1[200] = {0}; -- unsigned char t2[200] = {0}; -- unsigned char t3[200] = {0}; -- -- unsigned long long *ss = (unsigned long long *)s; -- -- -- while (mlen >= r) { -- for (size_t i = 0; i < r / 8; ++i) { -- ss[4 * i + 0] ^= load64(m0 + 8 * i); -- ss[4 * i + 1] ^= load64(m1 + 8 * i); -- ss[4 * i + 2] ^= load64(m2 + 8 * i); -- ss[4 * i + 3] ^= load64(m3 + 8 * i); -- } -- -- KeccakF1600_StatePermute4x(s); -- mlen -= r; -- m0 += r; -- m1 += r; -- m2 += r; -- m3 += r; -- } -- -- memcpy(t0, m0, mlen); -- memcpy(t1, m1, mlen); -- memcpy(t2, m2, mlen); -- memcpy(t3, m3, mlen); -- -- t0[mlen] = p; -- t1[mlen] = p; -- t2[mlen] = p; -- t3[mlen] = p; -- -- t0[r - 1] |= 128; -- t1[r - 1] |= 128; -- t2[r - 1] |= 128; -- t3[r - 1] |= 128; -- -- for (size_t i = 0; i < r / 8; ++i) { -- ss[4 * i + 0] ^= load64(t0 + 8 * i); -- ss[4 * i + 1] ^= load64(t1 + 8 * i); -- ss[4 * i + 2] ^= load64(t2 + 8 * i); -- ss[4 * i + 3] ^= load64(t3 + 8 * i); -- } --} -- -- --static void keccak_squeezeblocks4x(unsigned char *h0, -- unsigned char *h1, -- unsigned char *h2, -- unsigned char *h3, -- unsigned long long int nblocks, -- __m256i *s, -- unsigned int r) { -- unsigned int i; -- -- unsigned long long *ss = (unsigned long long *)s; -- -- while (nblocks > 0) { -- KeccakF1600_StatePermute4x(s); -- for (i = 0; i < (r >> 3); i++) { -- store64(h0 + 8 * i, ss[4 * i + 0]); -- store64(h1 + 8 * i, ss[4 * i + 1]); -- store64(h2 + 8 * i, ss[4 * i + 2]); -- store64(h3 + 8 * i, ss[4 * i + 3]); -- } -- h0 += r; -- h1 += r; -- h2 += r; -- h3 += r; -- nblocks--; -- } --} -- -- -- --void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_shake128x4(unsigned char *out0, -- unsigned char *out1, -- unsigned char *out2, -- unsigned char *out3, -- unsigned long long outlen, -- unsigned char *in0, -- unsigned char *in1, -- unsigned char *in2, -- unsigned char *in3, -- unsigned long long inlen) { -- __m256i s[25]; -- unsigned char t0[SHAKE128_RATE]; -- unsigned char t1[SHAKE128_RATE]; -- unsigned char t2[SHAKE128_RATE]; -- unsigned char t3[SHAKE128_RATE]; -- unsigned int i; -- -- /* zero state */ -- for (i = 0; i < 25; i++) { -- s[i] = _mm256_xor_si256(s[i], s[i]); -- } -- -- /* absorb 4 message of identical length in parallel */ -- keccak_absorb4x(s, SHAKE128_RATE, in0, in1, in2, in3, (size_t)inlen, 0x1F); -- -- /* Squeeze output */ -- keccak_squeezeblocks4x(out0, out1, out2, out3, outlen / SHAKE128_RATE, s, SHAKE128_RATE); -- -- out0 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; -- out1 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; -- out2 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; -- out3 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; -- -- if (outlen % SHAKE128_RATE) { -- keccak_squeezeblocks4x(t0, t1, t2, t3, 1, s, SHAKE128_RATE); -- for (i = 0; i < outlen % SHAKE128_RATE; i++) { -- out0[i] = t0[i]; -- out1[i] = t1[i]; -- out2[i] = t2[i]; -- out3[i] = t3[i]; -- } -- } --} -- -- --void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_shake256x4(unsigned char *out0, -- unsigned char *out1, -- unsigned char *out2, -- unsigned char *out3, -- unsigned long long outlen, -- unsigned char *in0, -- unsigned char *in1, -- unsigned char *in2, -- unsigned char *in3, -- unsigned long long inlen) { -- __m256i s[25]; -- unsigned char t0[SHAKE256_RATE]; -- unsigned char t1[SHAKE256_RATE]; -- unsigned char t2[SHAKE256_RATE]; -- unsigned char t3[SHAKE256_RATE]; -- unsigned int i; -- -- /* zero state */ -- for (i = 0; i < 25; i++) { -- s[i] = _mm256_xor_si256(s[i], s[i]); -- } -- -- /* absorb 4 message of identical length in parallel */ -- keccak_absorb4x(s, SHAKE256_RATE, in0, in1, in2, in3, (size_t)inlen, 0x1F); -- -- /* Squeeze output */ -- keccak_squeezeblocks4x(out0, out1, out2, out3, outlen / SHAKE256_RATE, s, SHAKE256_RATE); -- -- out0 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; -- out1 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; -- out2 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; -- out3 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; -- -- if (outlen % SHAKE256_RATE) { -- keccak_squeezeblocks4x(t0, t1, t2, t3, 1, s, SHAKE256_RATE); -- for (i = 0; i < outlen % SHAKE256_RATE; i++) { -- out0[i] = t0[i]; -- out1[i] = t1[i]; -- out2[i] = t2[i]; -- out3[i] = t3[i]; -- } -- } --} -diff --git a/crypto_sign/sphincs-shake256-128s-simple/avx2/fips202x4.h b/crypto_sign/sphincs-shake256-128s-simple/avx2/fips202x4.h -deleted file mode 100644 -index 30b7349..0000000 ---- a/crypto_sign/sphincs-shake256-128s-simple/avx2/fips202x4.h -+++ /dev/null -@@ -1,27 +0,0 @@ --#ifndef PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_FIPS202X4_H --#define PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_FIPS202X4_H -- --#include -- --void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_shake128x4(unsigned char *out0, -- unsigned char *out1, -- unsigned char *out2, -- unsigned char *out3, -- unsigned long long outlen, -- unsigned char *in0, -- unsigned char *in1, -- unsigned char *in2, -- unsigned char *in3, unsigned long long inlen); -- --void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_shake256x4(unsigned char *out0, -- unsigned char *out1, -- unsigned char *out2, -- unsigned char *out3, -- unsigned long long outlen, -- unsigned char *in0, -- unsigned char *in1, -- unsigned char *in2, -- unsigned char *in3, -- unsigned long long inlen); -- --#endif -diff --git a/crypto_sign/sphincs-shake256-192f-robust/avx2/fips202x4.c b/crypto_sign/sphincs-shake256-192f-robust/avx2/fips202x4.c -deleted file mode 100644 -index 3138800..0000000 ---- a/crypto_sign/sphincs-shake256-192f-robust/avx2/fips202x4.c -+++ /dev/null -@@ -1,205 +0,0 @@ --#include --#include --#include -- --#include "fips202.h" --#include "fips202x4.h" -- --#define NROUNDS 24 --#define ROL(a, offset) (((a) << (offset)) ^ ((a) >> (64-(offset)))) -- --static uint64_t load64(const unsigned char *x) { -- unsigned long long r = 0, i; -- -- for (i = 0; i < 8; ++i) { -- r |= (unsigned long long)x[i] << 8 * i; -- } -- return r; --} -- --static void store64(uint8_t *x, uint64_t u) { -- unsigned int i; -- -- for (i = 0; i < 8; ++i) { -- x[i] = (uint8_t)u; -- u >>= 8; -- } --} -- --/* Use implementation from the Keccak Code Package */ --extern void KeccakP1600times4_PermuteAll_24rounds(__m256i *s); --#define KeccakF1600_StatePermute4x KeccakP1600times4_PermuteAll_24rounds -- --static void keccak_absorb4x(__m256i *s, -- unsigned int r, -- const unsigned char *m0, -- const unsigned char *m1, -- const unsigned char *m2, -- const unsigned char *m3, -- size_t mlen, -- unsigned char p) { -- unsigned char t0[200] = {0}; -- unsigned char t1[200] = {0}; -- unsigned char t2[200] = {0}; -- unsigned char t3[200] = {0}; -- -- unsigned long long *ss = (unsigned long long *)s; -- -- -- while (mlen >= r) { -- for (size_t i = 0; i < r / 8; ++i) { -- ss[4 * i + 0] ^= load64(m0 + 8 * i); -- ss[4 * i + 1] ^= load64(m1 + 8 * i); -- ss[4 * i + 2] ^= load64(m2 + 8 * i); -- ss[4 * i + 3] ^= load64(m3 + 8 * i); -- } -- -- KeccakF1600_StatePermute4x(s); -- mlen -= r; -- m0 += r; -- m1 += r; -- m2 += r; -- m3 += r; -- } -- -- memcpy(t0, m0, mlen); -- memcpy(t1, m1, mlen); -- memcpy(t2, m2, mlen); -- memcpy(t3, m3, mlen); -- -- t0[mlen] = p; -- t1[mlen] = p; -- t2[mlen] = p; -- t3[mlen] = p; -- -- t0[r - 1] |= 128; -- t1[r - 1] |= 128; -- t2[r - 1] |= 128; -- t3[r - 1] |= 128; -- -- for (size_t i = 0; i < r / 8; ++i) { -- ss[4 * i + 0] ^= load64(t0 + 8 * i); -- ss[4 * i + 1] ^= load64(t1 + 8 * i); -- ss[4 * i + 2] ^= load64(t2 + 8 * i); -- ss[4 * i + 3] ^= load64(t3 + 8 * i); -- } --} -- -- --static void keccak_squeezeblocks4x(unsigned char *h0, -- unsigned char *h1, -- unsigned char *h2, -- unsigned char *h3, -- unsigned long long int nblocks, -- __m256i *s, -- unsigned int r) { -- unsigned int i; -- -- unsigned long long *ss = (unsigned long long *)s; -- -- while (nblocks > 0) { -- KeccakF1600_StatePermute4x(s); -- for (i = 0; i < (r >> 3); i++) { -- store64(h0 + 8 * i, ss[4 * i + 0]); -- store64(h1 + 8 * i, ss[4 * i + 1]); -- store64(h2 + 8 * i, ss[4 * i + 2]); -- store64(h3 + 8 * i, ss[4 * i + 3]); -- } -- h0 += r; -- h1 += r; -- h2 += r; -- h3 += r; -- nblocks--; -- } --} -- -- -- --void PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_shake128x4(unsigned char *out0, -- unsigned char *out1, -- unsigned char *out2, -- unsigned char *out3, -- unsigned long long outlen, -- unsigned char *in0, -- unsigned char *in1, -- unsigned char *in2, -- unsigned char *in3, -- unsigned long long inlen) { -- __m256i s[25]; -- unsigned char t0[SHAKE128_RATE]; -- unsigned char t1[SHAKE128_RATE]; -- unsigned char t2[SHAKE128_RATE]; -- unsigned char t3[SHAKE128_RATE]; -- unsigned int i; -- -- /* zero state */ -- for (i = 0; i < 25; i++) { -- s[i] = _mm256_xor_si256(s[i], s[i]); -- } -- -- /* absorb 4 message of identical length in parallel */ -- keccak_absorb4x(s, SHAKE128_RATE, in0, in1, in2, in3, (size_t)inlen, 0x1F); -- -- /* Squeeze output */ -- keccak_squeezeblocks4x(out0, out1, out2, out3, outlen / SHAKE128_RATE, s, SHAKE128_RATE); -- -- out0 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; -- out1 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; -- out2 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; -- out3 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; -- -- if (outlen % SHAKE128_RATE) { -- keccak_squeezeblocks4x(t0, t1, t2, t3, 1, s, SHAKE128_RATE); -- for (i = 0; i < outlen % SHAKE128_RATE; i++) { -- out0[i] = t0[i]; -- out1[i] = t1[i]; -- out2[i] = t2[i]; -- out3[i] = t3[i]; -- } -- } --} -- -- --void PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_shake256x4(unsigned char *out0, -- unsigned char *out1, -- unsigned char *out2, -- unsigned char *out3, -- unsigned long long outlen, -- unsigned char *in0, -- unsigned char *in1, -- unsigned char *in2, -- unsigned char *in3, -- unsigned long long inlen) { -- __m256i s[25]; -- unsigned char t0[SHAKE256_RATE]; -- unsigned char t1[SHAKE256_RATE]; -- unsigned char t2[SHAKE256_RATE]; -- unsigned char t3[SHAKE256_RATE]; -- unsigned int i; -- -- /* zero state */ -- for (i = 0; i < 25; i++) { -- s[i] = _mm256_xor_si256(s[i], s[i]); -- } -- -- /* absorb 4 message of identical length in parallel */ -- keccak_absorb4x(s, SHAKE256_RATE, in0, in1, in2, in3, (size_t)inlen, 0x1F); -- -- /* Squeeze output */ -- keccak_squeezeblocks4x(out0, out1, out2, out3, outlen / SHAKE256_RATE, s, SHAKE256_RATE); -- -- out0 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; -- out1 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; -- out2 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; -- out3 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; -- -- if (outlen % SHAKE256_RATE) { -- keccak_squeezeblocks4x(t0, t1, t2, t3, 1, s, SHAKE256_RATE); -- for (i = 0; i < outlen % SHAKE256_RATE; i++) { -- out0[i] = t0[i]; -- out1[i] = t1[i]; -- out2[i] = t2[i]; -- out3[i] = t3[i]; -- } -- } --} -diff --git a/crypto_sign/sphincs-shake256-192f-robust/avx2/fips202x4.h b/crypto_sign/sphincs-shake256-192f-robust/avx2/fips202x4.h -deleted file mode 100644 -index 936fa6f..0000000 ---- a/crypto_sign/sphincs-shake256-192f-robust/avx2/fips202x4.h -+++ /dev/null -@@ -1,27 +0,0 @@ --#ifndef PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_FIPS202X4_H --#define PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_FIPS202X4_H -- --#include -- --void PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_shake128x4(unsigned char *out0, -- unsigned char *out1, -- unsigned char *out2, -- unsigned char *out3, -- unsigned long long outlen, -- unsigned char *in0, -- unsigned char *in1, -- unsigned char *in2, -- unsigned char *in3, unsigned long long inlen); -- --void PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_shake256x4(unsigned char *out0, -- unsigned char *out1, -- unsigned char *out2, -- unsigned char *out3, -- unsigned long long outlen, -- unsigned char *in0, -- unsigned char *in1, -- unsigned char *in2, -- unsigned char *in3, -- unsigned long long inlen); -- --#endif -diff --git a/crypto_sign/sphincs-shake256-192f-simple/avx2/fips202x4.c b/crypto_sign/sphincs-shake256-192f-simple/avx2/fips202x4.c -deleted file mode 100644 -index 01dbf7d..0000000 ---- a/crypto_sign/sphincs-shake256-192f-simple/avx2/fips202x4.c -+++ /dev/null -@@ -1,205 +0,0 @@ --#include --#include --#include -- --#include "fips202.h" --#include "fips202x4.h" -- --#define NROUNDS 24 --#define ROL(a, offset) (((a) << (offset)) ^ ((a) >> (64-(offset)))) -- --static uint64_t load64(const unsigned char *x) { -- unsigned long long r = 0, i; -- -- for (i = 0; i < 8; ++i) { -- r |= (unsigned long long)x[i] << 8 * i; -- } -- return r; --} -- --static void store64(uint8_t *x, uint64_t u) { -- unsigned int i; -- -- for (i = 0; i < 8; ++i) { -- x[i] = (uint8_t)u; -- u >>= 8; -- } --} -- --/* Use implementation from the Keccak Code Package */ --extern void KeccakP1600times4_PermuteAll_24rounds(__m256i *s); --#define KeccakF1600_StatePermute4x KeccakP1600times4_PermuteAll_24rounds -- --static void keccak_absorb4x(__m256i *s, -- unsigned int r, -- const unsigned char *m0, -- const unsigned char *m1, -- const unsigned char *m2, -- const unsigned char *m3, -- size_t mlen, -- unsigned char p) { -- unsigned char t0[200] = {0}; -- unsigned char t1[200] = {0}; -- unsigned char t2[200] = {0}; -- unsigned char t3[200] = {0}; -- -- unsigned long long *ss = (unsigned long long *)s; -- -- -- while (mlen >= r) { -- for (size_t i = 0; i < r / 8; ++i) { -- ss[4 * i + 0] ^= load64(m0 + 8 * i); -- ss[4 * i + 1] ^= load64(m1 + 8 * i); -- ss[4 * i + 2] ^= load64(m2 + 8 * i); -- ss[4 * i + 3] ^= load64(m3 + 8 * i); -- } -- -- KeccakF1600_StatePermute4x(s); -- mlen -= r; -- m0 += r; -- m1 += r; -- m2 += r; -- m3 += r; -- } -- -- memcpy(t0, m0, mlen); -- memcpy(t1, m1, mlen); -- memcpy(t2, m2, mlen); -- memcpy(t3, m3, mlen); -- -- t0[mlen] = p; -- t1[mlen] = p; -- t2[mlen] = p; -- t3[mlen] = p; -- -- t0[r - 1] |= 128; -- t1[r - 1] |= 128; -- t2[r - 1] |= 128; -- t3[r - 1] |= 128; -- -- for (size_t i = 0; i < r / 8; ++i) { -- ss[4 * i + 0] ^= load64(t0 + 8 * i); -- ss[4 * i + 1] ^= load64(t1 + 8 * i); -- ss[4 * i + 2] ^= load64(t2 + 8 * i); -- ss[4 * i + 3] ^= load64(t3 + 8 * i); -- } --} -- -- --static void keccak_squeezeblocks4x(unsigned char *h0, -- unsigned char *h1, -- unsigned char *h2, -- unsigned char *h3, -- unsigned long long int nblocks, -- __m256i *s, -- unsigned int r) { -- unsigned int i; -- -- unsigned long long *ss = (unsigned long long *)s; -- -- while (nblocks > 0) { -- KeccakF1600_StatePermute4x(s); -- for (i = 0; i < (r >> 3); i++) { -- store64(h0 + 8 * i, ss[4 * i + 0]); -- store64(h1 + 8 * i, ss[4 * i + 1]); -- store64(h2 + 8 * i, ss[4 * i + 2]); -- store64(h3 + 8 * i, ss[4 * i + 3]); -- } -- h0 += r; -- h1 += r; -- h2 += r; -- h3 += r; -- nblocks--; -- } --} -- -- -- --void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_shake128x4(unsigned char *out0, -- unsigned char *out1, -- unsigned char *out2, -- unsigned char *out3, -- unsigned long long outlen, -- unsigned char *in0, -- unsigned char *in1, -- unsigned char *in2, -- unsigned char *in3, -- unsigned long long inlen) { -- __m256i s[25]; -- unsigned char t0[SHAKE128_RATE]; -- unsigned char t1[SHAKE128_RATE]; -- unsigned char t2[SHAKE128_RATE]; -- unsigned char t3[SHAKE128_RATE]; -- unsigned int i; -- -- /* zero state */ -- for (i = 0; i < 25; i++) { -- s[i] = _mm256_xor_si256(s[i], s[i]); -- } -- -- /* absorb 4 message of identical length in parallel */ -- keccak_absorb4x(s, SHAKE128_RATE, in0, in1, in2, in3, (size_t)inlen, 0x1F); -- -- /* Squeeze output */ -- keccak_squeezeblocks4x(out0, out1, out2, out3, outlen / SHAKE128_RATE, s, SHAKE128_RATE); -- -- out0 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; -- out1 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; -- out2 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; -- out3 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; -- -- if (outlen % SHAKE128_RATE) { -- keccak_squeezeblocks4x(t0, t1, t2, t3, 1, s, SHAKE128_RATE); -- for (i = 0; i < outlen % SHAKE128_RATE; i++) { -- out0[i] = t0[i]; -- out1[i] = t1[i]; -- out2[i] = t2[i]; -- out3[i] = t3[i]; -- } -- } --} -- -- --void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_shake256x4(unsigned char *out0, -- unsigned char *out1, -- unsigned char *out2, -- unsigned char *out3, -- unsigned long long outlen, -- unsigned char *in0, -- unsigned char *in1, -- unsigned char *in2, -- unsigned char *in3, -- unsigned long long inlen) { -- __m256i s[25]; -- unsigned char t0[SHAKE256_RATE]; -- unsigned char t1[SHAKE256_RATE]; -- unsigned char t2[SHAKE256_RATE]; -- unsigned char t3[SHAKE256_RATE]; -- unsigned int i; -- -- /* zero state */ -- for (i = 0; i < 25; i++) { -- s[i] = _mm256_xor_si256(s[i], s[i]); -- } -- -- /* absorb 4 message of identical length in parallel */ -- keccak_absorb4x(s, SHAKE256_RATE, in0, in1, in2, in3, (size_t)inlen, 0x1F); -- -- /* Squeeze output */ -- keccak_squeezeblocks4x(out0, out1, out2, out3, outlen / SHAKE256_RATE, s, SHAKE256_RATE); -- -- out0 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; -- out1 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; -- out2 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; -- out3 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; -- -- if (outlen % SHAKE256_RATE) { -- keccak_squeezeblocks4x(t0, t1, t2, t3, 1, s, SHAKE256_RATE); -- for (i = 0; i < outlen % SHAKE256_RATE; i++) { -- out0[i] = t0[i]; -- out1[i] = t1[i]; -- out2[i] = t2[i]; -- out3[i] = t3[i]; -- } -- } --} -diff --git a/crypto_sign/sphincs-shake256-192f-simple/avx2/fips202x4.h b/crypto_sign/sphincs-shake256-192f-simple/avx2/fips202x4.h -deleted file mode 100644 -index c400b86..0000000 ---- a/crypto_sign/sphincs-shake256-192f-simple/avx2/fips202x4.h -+++ /dev/null -@@ -1,27 +0,0 @@ --#ifndef PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_FIPS202X4_H --#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_FIPS202X4_H -- --#include -- --void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_shake128x4(unsigned char *out0, -- unsigned char *out1, -- unsigned char *out2, -- unsigned char *out3, -- unsigned long long outlen, -- unsigned char *in0, -- unsigned char *in1, -- unsigned char *in2, -- unsigned char *in3, unsigned long long inlen); -- --void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_shake256x4(unsigned char *out0, -- unsigned char *out1, -- unsigned char *out2, -- unsigned char *out3, -- unsigned long long outlen, -- unsigned char *in0, -- unsigned char *in1, -- unsigned char *in2, -- unsigned char *in3, -- unsigned long long inlen); -- --#endif -diff --git a/crypto_sign/sphincs-shake256-192s-robust/avx2/fips202x4.c b/crypto_sign/sphincs-shake256-192s-robust/avx2/fips202x4.c -deleted file mode 100644 -index 8f33cfa..0000000 ---- a/crypto_sign/sphincs-shake256-192s-robust/avx2/fips202x4.c -+++ /dev/null -@@ -1,205 +0,0 @@ --#include --#include --#include -- --#include "fips202.h" --#include "fips202x4.h" -- --#define NROUNDS 24 --#define ROL(a, offset) (((a) << (offset)) ^ ((a) >> (64-(offset)))) -- --static uint64_t load64(const unsigned char *x) { -- unsigned long long r = 0, i; -- -- for (i = 0; i < 8; ++i) { -- r |= (unsigned long long)x[i] << 8 * i; -- } -- return r; --} -- --static void store64(uint8_t *x, uint64_t u) { -- unsigned int i; -- -- for (i = 0; i < 8; ++i) { -- x[i] = (uint8_t)u; -- u >>= 8; -- } --} -- --/* Use implementation from the Keccak Code Package */ --extern void KeccakP1600times4_PermuteAll_24rounds(__m256i *s); --#define KeccakF1600_StatePermute4x KeccakP1600times4_PermuteAll_24rounds -- --static void keccak_absorb4x(__m256i *s, -- unsigned int r, -- const unsigned char *m0, -- const unsigned char *m1, -- const unsigned char *m2, -- const unsigned char *m3, -- size_t mlen, -- unsigned char p) { -- unsigned char t0[200] = {0}; -- unsigned char t1[200] = {0}; -- unsigned char t2[200] = {0}; -- unsigned char t3[200] = {0}; -- -- unsigned long long *ss = (unsigned long long *)s; -- -- -- while (mlen >= r) { -- for (size_t i = 0; i < r / 8; ++i) { -- ss[4 * i + 0] ^= load64(m0 + 8 * i); -- ss[4 * i + 1] ^= load64(m1 + 8 * i); -- ss[4 * i + 2] ^= load64(m2 + 8 * i); -- ss[4 * i + 3] ^= load64(m3 + 8 * i); -- } -- -- KeccakF1600_StatePermute4x(s); -- mlen -= r; -- m0 += r; -- m1 += r; -- m2 += r; -- m3 += r; -- } -- -- memcpy(t0, m0, mlen); -- memcpy(t1, m1, mlen); -- memcpy(t2, m2, mlen); -- memcpy(t3, m3, mlen); -- -- t0[mlen] = p; -- t1[mlen] = p; -- t2[mlen] = p; -- t3[mlen] = p; -- -- t0[r - 1] |= 128; -- t1[r - 1] |= 128; -- t2[r - 1] |= 128; -- t3[r - 1] |= 128; -- -- for (size_t i = 0; i < r / 8; ++i) { -- ss[4 * i + 0] ^= load64(t0 + 8 * i); -- ss[4 * i + 1] ^= load64(t1 + 8 * i); -- ss[4 * i + 2] ^= load64(t2 + 8 * i); -- ss[4 * i + 3] ^= load64(t3 + 8 * i); -- } --} -- -- --static void keccak_squeezeblocks4x(unsigned char *h0, -- unsigned char *h1, -- unsigned char *h2, -- unsigned char *h3, -- unsigned long long int nblocks, -- __m256i *s, -- unsigned int r) { -- unsigned int i; -- -- unsigned long long *ss = (unsigned long long *)s; -- -- while (nblocks > 0) { -- KeccakF1600_StatePermute4x(s); -- for (i = 0; i < (r >> 3); i++) { -- store64(h0 + 8 * i, ss[4 * i + 0]); -- store64(h1 + 8 * i, ss[4 * i + 1]); -- store64(h2 + 8 * i, ss[4 * i + 2]); -- store64(h3 + 8 * i, ss[4 * i + 3]); -- } -- h0 += r; -- h1 += r; -- h2 += r; -- h3 += r; -- nblocks--; -- } --} -- -- -- --void PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_shake128x4(unsigned char *out0, -- unsigned char *out1, -- unsigned char *out2, -- unsigned char *out3, -- unsigned long long outlen, -- unsigned char *in0, -- unsigned char *in1, -- unsigned char *in2, -- unsigned char *in3, -- unsigned long long inlen) { -- __m256i s[25]; -- unsigned char t0[SHAKE128_RATE]; -- unsigned char t1[SHAKE128_RATE]; -- unsigned char t2[SHAKE128_RATE]; -- unsigned char t3[SHAKE128_RATE]; -- unsigned int i; -- -- /* zero state */ -- for (i = 0; i < 25; i++) { -- s[i] = _mm256_xor_si256(s[i], s[i]); -- } -- -- /* absorb 4 message of identical length in parallel */ -- keccak_absorb4x(s, SHAKE128_RATE, in0, in1, in2, in3, (size_t)inlen, 0x1F); -- -- /* Squeeze output */ -- keccak_squeezeblocks4x(out0, out1, out2, out3, outlen / SHAKE128_RATE, s, SHAKE128_RATE); -- -- out0 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; -- out1 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; -- out2 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; -- out3 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; -- -- if (outlen % SHAKE128_RATE) { -- keccak_squeezeblocks4x(t0, t1, t2, t3, 1, s, SHAKE128_RATE); -- for (i = 0; i < outlen % SHAKE128_RATE; i++) { -- out0[i] = t0[i]; -- out1[i] = t1[i]; -- out2[i] = t2[i]; -- out3[i] = t3[i]; -- } -- } --} -- -- --void PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_shake256x4(unsigned char *out0, -- unsigned char *out1, -- unsigned char *out2, -- unsigned char *out3, -- unsigned long long outlen, -- unsigned char *in0, -- unsigned char *in1, -- unsigned char *in2, -- unsigned char *in3, -- unsigned long long inlen) { -- __m256i s[25]; -- unsigned char t0[SHAKE256_RATE]; -- unsigned char t1[SHAKE256_RATE]; -- unsigned char t2[SHAKE256_RATE]; -- unsigned char t3[SHAKE256_RATE]; -- unsigned int i; -- -- /* zero state */ -- for (i = 0; i < 25; i++) { -- s[i] = _mm256_xor_si256(s[i], s[i]); -- } -- -- /* absorb 4 message of identical length in parallel */ -- keccak_absorb4x(s, SHAKE256_RATE, in0, in1, in2, in3, (size_t)inlen, 0x1F); -- -- /* Squeeze output */ -- keccak_squeezeblocks4x(out0, out1, out2, out3, outlen / SHAKE256_RATE, s, SHAKE256_RATE); -- -- out0 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; -- out1 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; -- out2 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; -- out3 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; -- -- if (outlen % SHAKE256_RATE) { -- keccak_squeezeblocks4x(t0, t1, t2, t3, 1, s, SHAKE256_RATE); -- for (i = 0; i < outlen % SHAKE256_RATE; i++) { -- out0[i] = t0[i]; -- out1[i] = t1[i]; -- out2[i] = t2[i]; -- out3[i] = t3[i]; -- } -- } --} -diff --git a/crypto_sign/sphincs-shake256-192s-robust/avx2/fips202x4.h b/crypto_sign/sphincs-shake256-192s-robust/avx2/fips202x4.h -deleted file mode 100644 -index 409f9f0..0000000 ---- a/crypto_sign/sphincs-shake256-192s-robust/avx2/fips202x4.h -+++ /dev/null -@@ -1,27 +0,0 @@ --#ifndef PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_FIPS202X4_H --#define PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_FIPS202X4_H -- --#include -- --void PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_shake128x4(unsigned char *out0, -- unsigned char *out1, -- unsigned char *out2, -- unsigned char *out3, -- unsigned long long outlen, -- unsigned char *in0, -- unsigned char *in1, -- unsigned char *in2, -- unsigned char *in3, unsigned long long inlen); -- --void PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_shake256x4(unsigned char *out0, -- unsigned char *out1, -- unsigned char *out2, -- unsigned char *out3, -- unsigned long long outlen, -- unsigned char *in0, -- unsigned char *in1, -- unsigned char *in2, -- unsigned char *in3, -- unsigned long long inlen); -- --#endif -diff --git a/crypto_sign/sphincs-shake256-192s-simple/avx2/fips202x4.c b/crypto_sign/sphincs-shake256-192s-simple/avx2/fips202x4.c -deleted file mode 100644 -index b34d28c..0000000 ---- a/crypto_sign/sphincs-shake256-192s-simple/avx2/fips202x4.c -+++ /dev/null -@@ -1,205 +0,0 @@ --#include --#include --#include -- --#include "fips202.h" --#include "fips202x4.h" -- --#define NROUNDS 24 --#define ROL(a, offset) (((a) << (offset)) ^ ((a) >> (64-(offset)))) -- --static uint64_t load64(const unsigned char *x) { -- unsigned long long r = 0, i; -- -- for (i = 0; i < 8; ++i) { -- r |= (unsigned long long)x[i] << 8 * i; -- } -- return r; --} -- --static void store64(uint8_t *x, uint64_t u) { -- unsigned int i; -- -- for (i = 0; i < 8; ++i) { -- x[i] = (uint8_t)u; -- u >>= 8; -- } --} -- --/* Use implementation from the Keccak Code Package */ --extern void KeccakP1600times4_PermuteAll_24rounds(__m256i *s); --#define KeccakF1600_StatePermute4x KeccakP1600times4_PermuteAll_24rounds -- --static void keccak_absorb4x(__m256i *s, -- unsigned int r, -- const unsigned char *m0, -- const unsigned char *m1, -- const unsigned char *m2, -- const unsigned char *m3, -- size_t mlen, -- unsigned char p) { -- unsigned char t0[200] = {0}; -- unsigned char t1[200] = {0}; -- unsigned char t2[200] = {0}; -- unsigned char t3[200] = {0}; -- -- unsigned long long *ss = (unsigned long long *)s; -- -- -- while (mlen >= r) { -- for (size_t i = 0; i < r / 8; ++i) { -- ss[4 * i + 0] ^= load64(m0 + 8 * i); -- ss[4 * i + 1] ^= load64(m1 + 8 * i); -- ss[4 * i + 2] ^= load64(m2 + 8 * i); -- ss[4 * i + 3] ^= load64(m3 + 8 * i); -- } -- -- KeccakF1600_StatePermute4x(s); -- mlen -= r; -- m0 += r; -- m1 += r; -- m2 += r; -- m3 += r; -- } -- -- memcpy(t0, m0, mlen); -- memcpy(t1, m1, mlen); -- memcpy(t2, m2, mlen); -- memcpy(t3, m3, mlen); -- -- t0[mlen] = p; -- t1[mlen] = p; -- t2[mlen] = p; -- t3[mlen] = p; -- -- t0[r - 1] |= 128; -- t1[r - 1] |= 128; -- t2[r - 1] |= 128; -- t3[r - 1] |= 128; -- -- for (size_t i = 0; i < r / 8; ++i) { -- ss[4 * i + 0] ^= load64(t0 + 8 * i); -- ss[4 * i + 1] ^= load64(t1 + 8 * i); -- ss[4 * i + 2] ^= load64(t2 + 8 * i); -- ss[4 * i + 3] ^= load64(t3 + 8 * i); -- } --} -- -- --static void keccak_squeezeblocks4x(unsigned char *h0, -- unsigned char *h1, -- unsigned char *h2, -- unsigned char *h3, -- unsigned long long int nblocks, -- __m256i *s, -- unsigned int r) { -- unsigned int i; -- -- unsigned long long *ss = (unsigned long long *)s; -- -- while (nblocks > 0) { -- KeccakF1600_StatePermute4x(s); -- for (i = 0; i < (r >> 3); i++) { -- store64(h0 + 8 * i, ss[4 * i + 0]); -- store64(h1 + 8 * i, ss[4 * i + 1]); -- store64(h2 + 8 * i, ss[4 * i + 2]); -- store64(h3 + 8 * i, ss[4 * i + 3]); -- } -- h0 += r; -- h1 += r; -- h2 += r; -- h3 += r; -- nblocks--; -- } --} -- -- -- --void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_shake128x4(unsigned char *out0, -- unsigned char *out1, -- unsigned char *out2, -- unsigned char *out3, -- unsigned long long outlen, -- unsigned char *in0, -- unsigned char *in1, -- unsigned char *in2, -- unsigned char *in3, -- unsigned long long inlen) { -- __m256i s[25]; -- unsigned char t0[SHAKE128_RATE]; -- unsigned char t1[SHAKE128_RATE]; -- unsigned char t2[SHAKE128_RATE]; -- unsigned char t3[SHAKE128_RATE]; -- unsigned int i; -- -- /* zero state */ -- for (i = 0; i < 25; i++) { -- s[i] = _mm256_xor_si256(s[i], s[i]); -- } -- -- /* absorb 4 message of identical length in parallel */ -- keccak_absorb4x(s, SHAKE128_RATE, in0, in1, in2, in3, (size_t)inlen, 0x1F); -- -- /* Squeeze output */ -- keccak_squeezeblocks4x(out0, out1, out2, out3, outlen / SHAKE128_RATE, s, SHAKE128_RATE); -- -- out0 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; -- out1 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; -- out2 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; -- out3 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; -- -- if (outlen % SHAKE128_RATE) { -- keccak_squeezeblocks4x(t0, t1, t2, t3, 1, s, SHAKE128_RATE); -- for (i = 0; i < outlen % SHAKE128_RATE; i++) { -- out0[i] = t0[i]; -- out1[i] = t1[i]; -- out2[i] = t2[i]; -- out3[i] = t3[i]; -- } -- } --} -- -- --void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_shake256x4(unsigned char *out0, -- unsigned char *out1, -- unsigned char *out2, -- unsigned char *out3, -- unsigned long long outlen, -- unsigned char *in0, -- unsigned char *in1, -- unsigned char *in2, -- unsigned char *in3, -- unsigned long long inlen) { -- __m256i s[25]; -- unsigned char t0[SHAKE256_RATE]; -- unsigned char t1[SHAKE256_RATE]; -- unsigned char t2[SHAKE256_RATE]; -- unsigned char t3[SHAKE256_RATE]; -- unsigned int i; -- -- /* zero state */ -- for (i = 0; i < 25; i++) { -- s[i] = _mm256_xor_si256(s[i], s[i]); -- } -- -- /* absorb 4 message of identical length in parallel */ -- keccak_absorb4x(s, SHAKE256_RATE, in0, in1, in2, in3, (size_t)inlen, 0x1F); -- -- /* Squeeze output */ -- keccak_squeezeblocks4x(out0, out1, out2, out3, outlen / SHAKE256_RATE, s, SHAKE256_RATE); -- -- out0 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; -- out1 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; -- out2 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; -- out3 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; -- -- if (outlen % SHAKE256_RATE) { -- keccak_squeezeblocks4x(t0, t1, t2, t3, 1, s, SHAKE256_RATE); -- for (i = 0; i < outlen % SHAKE256_RATE; i++) { -- out0[i] = t0[i]; -- out1[i] = t1[i]; -- out2[i] = t2[i]; -- out3[i] = t3[i]; -- } -- } --} -diff --git a/crypto_sign/sphincs-shake256-192s-simple/avx2/fips202x4.h b/crypto_sign/sphincs-shake256-192s-simple/avx2/fips202x4.h -deleted file mode 100644 -index 1fe7acd..0000000 ---- a/crypto_sign/sphincs-shake256-192s-simple/avx2/fips202x4.h -+++ /dev/null -@@ -1,27 +0,0 @@ --#ifndef PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_FIPS202X4_H --#define PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_FIPS202X4_H -- --#include -- --void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_shake128x4(unsigned char *out0, -- unsigned char *out1, -- unsigned char *out2, -- unsigned char *out3, -- unsigned long long outlen, -- unsigned char *in0, -- unsigned char *in1, -- unsigned char *in2, -- unsigned char *in3, unsigned long long inlen); -- --void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_shake256x4(unsigned char *out0, -- unsigned char *out1, -- unsigned char *out2, -- unsigned char *out3, -- unsigned long long outlen, -- unsigned char *in0, -- unsigned char *in1, -- unsigned char *in2, -- unsigned char *in3, -- unsigned long long inlen); -- --#endif -diff --git a/crypto_sign/sphincs-shake256-256f-robust/avx2/fips202x4.c b/crypto_sign/sphincs-shake256-256f-robust/avx2/fips202x4.c -deleted file mode 100644 -index e1a01a9..0000000 ---- a/crypto_sign/sphincs-shake256-256f-robust/avx2/fips202x4.c -+++ /dev/null -@@ -1,205 +0,0 @@ --#include --#include --#include -- --#include "fips202.h" --#include "fips202x4.h" -- --#define NROUNDS 24 --#define ROL(a, offset) (((a) << (offset)) ^ ((a) >> (64-(offset)))) -- --static uint64_t load64(const unsigned char *x) { -- unsigned long long r = 0, i; -- -- for (i = 0; i < 8; ++i) { -- r |= (unsigned long long)x[i] << 8 * i; -- } -- return r; --} -- --static void store64(uint8_t *x, uint64_t u) { -- unsigned int i; -- -- for (i = 0; i < 8; ++i) { -- x[i] = (uint8_t)u; -- u >>= 8; -- } --} -- --/* Use implementation from the Keccak Code Package */ --extern void KeccakP1600times4_PermuteAll_24rounds(__m256i *s); --#define KeccakF1600_StatePermute4x KeccakP1600times4_PermuteAll_24rounds -- --static void keccak_absorb4x(__m256i *s, -- unsigned int r, -- const unsigned char *m0, -- const unsigned char *m1, -- const unsigned char *m2, -- const unsigned char *m3, -- size_t mlen, -- unsigned char p) { -- unsigned char t0[200] = {0}; -- unsigned char t1[200] = {0}; -- unsigned char t2[200] = {0}; -- unsigned char t3[200] = {0}; -- -- unsigned long long *ss = (unsigned long long *)s; -- -- -- while (mlen >= r) { -- for (size_t i = 0; i < r / 8; ++i) { -- ss[4 * i + 0] ^= load64(m0 + 8 * i); -- ss[4 * i + 1] ^= load64(m1 + 8 * i); -- ss[4 * i + 2] ^= load64(m2 + 8 * i); -- ss[4 * i + 3] ^= load64(m3 + 8 * i); -- } -- -- KeccakF1600_StatePermute4x(s); -- mlen -= r; -- m0 += r; -- m1 += r; -- m2 += r; -- m3 += r; -- } -- -- memcpy(t0, m0, mlen); -- memcpy(t1, m1, mlen); -- memcpy(t2, m2, mlen); -- memcpy(t3, m3, mlen); -- -- t0[mlen] = p; -- t1[mlen] = p; -- t2[mlen] = p; -- t3[mlen] = p; -- -- t0[r - 1] |= 128; -- t1[r - 1] |= 128; -- t2[r - 1] |= 128; -- t3[r - 1] |= 128; -- -- for (size_t i = 0; i < r / 8; ++i) { -- ss[4 * i + 0] ^= load64(t0 + 8 * i); -- ss[4 * i + 1] ^= load64(t1 + 8 * i); -- ss[4 * i + 2] ^= load64(t2 + 8 * i); -- ss[4 * i + 3] ^= load64(t3 + 8 * i); -- } --} -- -- --static void keccak_squeezeblocks4x(unsigned char *h0, -- unsigned char *h1, -- unsigned char *h2, -- unsigned char *h3, -- unsigned long long int nblocks, -- __m256i *s, -- unsigned int r) { -- unsigned int i; -- -- unsigned long long *ss = (unsigned long long *)s; -- -- while (nblocks > 0) { -- KeccakF1600_StatePermute4x(s); -- for (i = 0; i < (r >> 3); i++) { -- store64(h0 + 8 * i, ss[4 * i + 0]); -- store64(h1 + 8 * i, ss[4 * i + 1]); -- store64(h2 + 8 * i, ss[4 * i + 2]); -- store64(h3 + 8 * i, ss[4 * i + 3]); -- } -- h0 += r; -- h1 += r; -- h2 += r; -- h3 += r; -- nblocks--; -- } --} -- -- -- --void PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_shake128x4(unsigned char *out0, -- unsigned char *out1, -- unsigned char *out2, -- unsigned char *out3, -- unsigned long long outlen, -- unsigned char *in0, -- unsigned char *in1, -- unsigned char *in2, -- unsigned char *in3, -- unsigned long long inlen) { -- __m256i s[25]; -- unsigned char t0[SHAKE128_RATE]; -- unsigned char t1[SHAKE128_RATE]; -- unsigned char t2[SHAKE128_RATE]; -- unsigned char t3[SHAKE128_RATE]; -- unsigned int i; -- -- /* zero state */ -- for (i = 0; i < 25; i++) { -- s[i] = _mm256_xor_si256(s[i], s[i]); -- } -- -- /* absorb 4 message of identical length in parallel */ -- keccak_absorb4x(s, SHAKE128_RATE, in0, in1, in2, in3, (size_t)inlen, 0x1F); -- -- /* Squeeze output */ -- keccak_squeezeblocks4x(out0, out1, out2, out3, outlen / SHAKE128_RATE, s, SHAKE128_RATE); -- -- out0 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; -- out1 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; -- out2 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; -- out3 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; -- -- if (outlen % SHAKE128_RATE) { -- keccak_squeezeblocks4x(t0, t1, t2, t3, 1, s, SHAKE128_RATE); -- for (i = 0; i < outlen % SHAKE128_RATE; i++) { -- out0[i] = t0[i]; -- out1[i] = t1[i]; -- out2[i] = t2[i]; -- out3[i] = t3[i]; -- } -- } --} -- -- --void PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_shake256x4(unsigned char *out0, -- unsigned char *out1, -- unsigned char *out2, -- unsigned char *out3, -- unsigned long long outlen, -- unsigned char *in0, -- unsigned char *in1, -- unsigned char *in2, -- unsigned char *in3, -- unsigned long long inlen) { -- __m256i s[25]; -- unsigned char t0[SHAKE256_RATE]; -- unsigned char t1[SHAKE256_RATE]; -- unsigned char t2[SHAKE256_RATE]; -- unsigned char t3[SHAKE256_RATE]; -- unsigned int i; -- -- /* zero state */ -- for (i = 0; i < 25; i++) { -- s[i] = _mm256_xor_si256(s[i], s[i]); -- } -- -- /* absorb 4 message of identical length in parallel */ -- keccak_absorb4x(s, SHAKE256_RATE, in0, in1, in2, in3, (size_t)inlen, 0x1F); -- -- /* Squeeze output */ -- keccak_squeezeblocks4x(out0, out1, out2, out3, outlen / SHAKE256_RATE, s, SHAKE256_RATE); -- -- out0 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; -- out1 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; -- out2 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; -- out3 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; -- -- if (outlen % SHAKE256_RATE) { -- keccak_squeezeblocks4x(t0, t1, t2, t3, 1, s, SHAKE256_RATE); -- for (i = 0; i < outlen % SHAKE256_RATE; i++) { -- out0[i] = t0[i]; -- out1[i] = t1[i]; -- out2[i] = t2[i]; -- out3[i] = t3[i]; -- } -- } --} -diff --git a/crypto_sign/sphincs-shake256-256f-robust/avx2/fips202x4.h b/crypto_sign/sphincs-shake256-256f-robust/avx2/fips202x4.h -deleted file mode 100644 -index dbe65cc..0000000 ---- a/crypto_sign/sphincs-shake256-256f-robust/avx2/fips202x4.h -+++ /dev/null -@@ -1,27 +0,0 @@ --#ifndef PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_FIPS202X4_H --#define PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_FIPS202X4_H -- --#include -- --void PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_shake128x4(unsigned char *out0, -- unsigned char *out1, -- unsigned char *out2, -- unsigned char *out3, -- unsigned long long outlen, -- unsigned char *in0, -- unsigned char *in1, -- unsigned char *in2, -- unsigned char *in3, unsigned long long inlen); -- --void PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_shake256x4(unsigned char *out0, -- unsigned char *out1, -- unsigned char *out2, -- unsigned char *out3, -- unsigned long long outlen, -- unsigned char *in0, -- unsigned char *in1, -- unsigned char *in2, -- unsigned char *in3, -- unsigned long long inlen); -- --#endif -diff --git a/crypto_sign/sphincs-shake256-256f-simple/avx2/fips202x4.c b/crypto_sign/sphincs-shake256-256f-simple/avx2/fips202x4.c -deleted file mode 100644 -index 3cfeadc..0000000 ---- a/crypto_sign/sphincs-shake256-256f-simple/avx2/fips202x4.c -+++ /dev/null -@@ -1,205 +0,0 @@ --#include --#include --#include -- --#include "fips202.h" --#include "fips202x4.h" -- --#define NROUNDS 24 --#define ROL(a, offset) (((a) << (offset)) ^ ((a) >> (64-(offset)))) -- --static uint64_t load64(const unsigned char *x) { -- unsigned long long r = 0, i; -- -- for (i = 0; i < 8; ++i) { -- r |= (unsigned long long)x[i] << 8 * i; -- } -- return r; --} -- --static void store64(uint8_t *x, uint64_t u) { -- unsigned int i; -- -- for (i = 0; i < 8; ++i) { -- x[i] = (uint8_t)u; -- u >>= 8; -- } --} -- --/* Use implementation from the Keccak Code Package */ --extern void KeccakP1600times4_PermuteAll_24rounds(__m256i *s); --#define KeccakF1600_StatePermute4x KeccakP1600times4_PermuteAll_24rounds -- --static void keccak_absorb4x(__m256i *s, -- unsigned int r, -- const unsigned char *m0, -- const unsigned char *m1, -- const unsigned char *m2, -- const unsigned char *m3, -- size_t mlen, -- unsigned char p) { -- unsigned char t0[200] = {0}; -- unsigned char t1[200] = {0}; -- unsigned char t2[200] = {0}; -- unsigned char t3[200] = {0}; -- -- unsigned long long *ss = (unsigned long long *)s; -- -- -- while (mlen >= r) { -- for (size_t i = 0; i < r / 8; ++i) { -- ss[4 * i + 0] ^= load64(m0 + 8 * i); -- ss[4 * i + 1] ^= load64(m1 + 8 * i); -- ss[4 * i + 2] ^= load64(m2 + 8 * i); -- ss[4 * i + 3] ^= load64(m3 + 8 * i); -- } -- -- KeccakF1600_StatePermute4x(s); -- mlen -= r; -- m0 += r; -- m1 += r; -- m2 += r; -- m3 += r; -- } -- -- memcpy(t0, m0, mlen); -- memcpy(t1, m1, mlen); -- memcpy(t2, m2, mlen); -- memcpy(t3, m3, mlen); -- -- t0[mlen] = p; -- t1[mlen] = p; -- t2[mlen] = p; -- t3[mlen] = p; -- -- t0[r - 1] |= 128; -- t1[r - 1] |= 128; -- t2[r - 1] |= 128; -- t3[r - 1] |= 128; -- -- for (size_t i = 0; i < r / 8; ++i) { -- ss[4 * i + 0] ^= load64(t0 + 8 * i); -- ss[4 * i + 1] ^= load64(t1 + 8 * i); -- ss[4 * i + 2] ^= load64(t2 + 8 * i); -- ss[4 * i + 3] ^= load64(t3 + 8 * i); -- } --} -- -- --static void keccak_squeezeblocks4x(unsigned char *h0, -- unsigned char *h1, -- unsigned char *h2, -- unsigned char *h3, -- unsigned long long int nblocks, -- __m256i *s, -- unsigned int r) { -- unsigned int i; -- -- unsigned long long *ss = (unsigned long long *)s; -- -- while (nblocks > 0) { -- KeccakF1600_StatePermute4x(s); -- for (i = 0; i < (r >> 3); i++) { -- store64(h0 + 8 * i, ss[4 * i + 0]); -- store64(h1 + 8 * i, ss[4 * i + 1]); -- store64(h2 + 8 * i, ss[4 * i + 2]); -- store64(h3 + 8 * i, ss[4 * i + 3]); -- } -- h0 += r; -- h1 += r; -- h2 += r; -- h3 += r; -- nblocks--; -- } --} -- -- -- --void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_shake128x4(unsigned char *out0, -- unsigned char *out1, -- unsigned char *out2, -- unsigned char *out3, -- unsigned long long outlen, -- unsigned char *in0, -- unsigned char *in1, -- unsigned char *in2, -- unsigned char *in3, -- unsigned long long inlen) { -- __m256i s[25]; -- unsigned char t0[SHAKE128_RATE]; -- unsigned char t1[SHAKE128_RATE]; -- unsigned char t2[SHAKE128_RATE]; -- unsigned char t3[SHAKE128_RATE]; -- unsigned int i; -- -- /* zero state */ -- for (i = 0; i < 25; i++) { -- s[i] = _mm256_xor_si256(s[i], s[i]); -- } -- -- /* absorb 4 message of identical length in parallel */ -- keccak_absorb4x(s, SHAKE128_RATE, in0, in1, in2, in3, (size_t)inlen, 0x1F); -- -- /* Squeeze output */ -- keccak_squeezeblocks4x(out0, out1, out2, out3, outlen / SHAKE128_RATE, s, SHAKE128_RATE); -- -- out0 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; -- out1 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; -- out2 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; -- out3 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; -- -- if (outlen % SHAKE128_RATE) { -- keccak_squeezeblocks4x(t0, t1, t2, t3, 1, s, SHAKE128_RATE); -- for (i = 0; i < outlen % SHAKE128_RATE; i++) { -- out0[i] = t0[i]; -- out1[i] = t1[i]; -- out2[i] = t2[i]; -- out3[i] = t3[i]; -- } -- } --} -- -- --void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_shake256x4(unsigned char *out0, -- unsigned char *out1, -- unsigned char *out2, -- unsigned char *out3, -- unsigned long long outlen, -- unsigned char *in0, -- unsigned char *in1, -- unsigned char *in2, -- unsigned char *in3, -- unsigned long long inlen) { -- __m256i s[25]; -- unsigned char t0[SHAKE256_RATE]; -- unsigned char t1[SHAKE256_RATE]; -- unsigned char t2[SHAKE256_RATE]; -- unsigned char t3[SHAKE256_RATE]; -- unsigned int i; -- -- /* zero state */ -- for (i = 0; i < 25; i++) { -- s[i] = _mm256_xor_si256(s[i], s[i]); -- } -- -- /* absorb 4 message of identical length in parallel */ -- keccak_absorb4x(s, SHAKE256_RATE, in0, in1, in2, in3, (size_t)inlen, 0x1F); -- -- /* Squeeze output */ -- keccak_squeezeblocks4x(out0, out1, out2, out3, outlen / SHAKE256_RATE, s, SHAKE256_RATE); -- -- out0 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; -- out1 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; -- out2 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; -- out3 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; -- -- if (outlen % SHAKE256_RATE) { -- keccak_squeezeblocks4x(t0, t1, t2, t3, 1, s, SHAKE256_RATE); -- for (i = 0; i < outlen % SHAKE256_RATE; i++) { -- out0[i] = t0[i]; -- out1[i] = t1[i]; -- out2[i] = t2[i]; -- out3[i] = t3[i]; -- } -- } --} -diff --git a/crypto_sign/sphincs-shake256-256f-simple/avx2/fips202x4.h b/crypto_sign/sphincs-shake256-256f-simple/avx2/fips202x4.h -deleted file mode 100644 -index e628d87..0000000 ---- a/crypto_sign/sphincs-shake256-256f-simple/avx2/fips202x4.h -+++ /dev/null -@@ -1,27 +0,0 @@ --#ifndef PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_FIPS202X4_H --#define PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_FIPS202X4_H -- --#include -- --void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_shake128x4(unsigned char *out0, -- unsigned char *out1, -- unsigned char *out2, -- unsigned char *out3, -- unsigned long long outlen, -- unsigned char *in0, -- unsigned char *in1, -- unsigned char *in2, -- unsigned char *in3, unsigned long long inlen); -- --void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_shake256x4(unsigned char *out0, -- unsigned char *out1, -- unsigned char *out2, -- unsigned char *out3, -- unsigned long long outlen, -- unsigned char *in0, -- unsigned char *in1, -- unsigned char *in2, -- unsigned char *in3, -- unsigned long long inlen); -- --#endif -diff --git a/crypto_sign/sphincs-shake256-256s-robust/avx2/fips202x4.c b/crypto_sign/sphincs-shake256-256s-robust/avx2/fips202x4.c -deleted file mode 100644 -index 0684756..0000000 ---- a/crypto_sign/sphincs-shake256-256s-robust/avx2/fips202x4.c -+++ /dev/null -@@ -1,205 +0,0 @@ --#include --#include --#include -- --#include "fips202.h" --#include "fips202x4.h" -- --#define NROUNDS 24 --#define ROL(a, offset) (((a) << (offset)) ^ ((a) >> (64-(offset)))) -- --static uint64_t load64(const unsigned char *x) { -- unsigned long long r = 0, i; -- -- for (i = 0; i < 8; ++i) { -- r |= (unsigned long long)x[i] << 8 * i; -- } -- return r; --} -- --static void store64(uint8_t *x, uint64_t u) { -- unsigned int i; -- -- for (i = 0; i < 8; ++i) { -- x[i] = (uint8_t)u; -- u >>= 8; -- } --} -- --/* Use implementation from the Keccak Code Package */ --extern void KeccakP1600times4_PermuteAll_24rounds(__m256i *s); --#define KeccakF1600_StatePermute4x KeccakP1600times4_PermuteAll_24rounds -- --static void keccak_absorb4x(__m256i *s, -- unsigned int r, -- const unsigned char *m0, -- const unsigned char *m1, -- const unsigned char *m2, -- const unsigned char *m3, -- size_t mlen, -- unsigned char p) { -- unsigned char t0[200] = {0}; -- unsigned char t1[200] = {0}; -- unsigned char t2[200] = {0}; -- unsigned char t3[200] = {0}; -- -- unsigned long long *ss = (unsigned long long *)s; -- -- -- while (mlen >= r) { -- for (size_t i = 0; i < r / 8; ++i) { -- ss[4 * i + 0] ^= load64(m0 + 8 * i); -- ss[4 * i + 1] ^= load64(m1 + 8 * i); -- ss[4 * i + 2] ^= load64(m2 + 8 * i); -- ss[4 * i + 3] ^= load64(m3 + 8 * i); -- } -- -- KeccakF1600_StatePermute4x(s); -- mlen -= r; -- m0 += r; -- m1 += r; -- m2 += r; -- m3 += r; -- } -- -- memcpy(t0, m0, mlen); -- memcpy(t1, m1, mlen); -- memcpy(t2, m2, mlen); -- memcpy(t3, m3, mlen); -- -- t0[mlen] = p; -- t1[mlen] = p; -- t2[mlen] = p; -- t3[mlen] = p; -- -- t0[r - 1] |= 128; -- t1[r - 1] |= 128; -- t2[r - 1] |= 128; -- t3[r - 1] |= 128; -- -- for (size_t i = 0; i < r / 8; ++i) { -- ss[4 * i + 0] ^= load64(t0 + 8 * i); -- ss[4 * i + 1] ^= load64(t1 + 8 * i); -- ss[4 * i + 2] ^= load64(t2 + 8 * i); -- ss[4 * i + 3] ^= load64(t3 + 8 * i); -- } --} -- -- --static void keccak_squeezeblocks4x(unsigned char *h0, -- unsigned char *h1, -- unsigned char *h2, -- unsigned char *h3, -- unsigned long long int nblocks, -- __m256i *s, -- unsigned int r) { -- unsigned int i; -- -- unsigned long long *ss = (unsigned long long *)s; -- -- while (nblocks > 0) { -- KeccakF1600_StatePermute4x(s); -- for (i = 0; i < (r >> 3); i++) { -- store64(h0 + 8 * i, ss[4 * i + 0]); -- store64(h1 + 8 * i, ss[4 * i + 1]); -- store64(h2 + 8 * i, ss[4 * i + 2]); -- store64(h3 + 8 * i, ss[4 * i + 3]); -- } -- h0 += r; -- h1 += r; -- h2 += r; -- h3 += r; -- nblocks--; -- } --} -- -- -- --void PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_shake128x4(unsigned char *out0, -- unsigned char *out1, -- unsigned char *out2, -- unsigned char *out3, -- unsigned long long outlen, -- unsigned char *in0, -- unsigned char *in1, -- unsigned char *in2, -- unsigned char *in3, -- unsigned long long inlen) { -- __m256i s[25]; -- unsigned char t0[SHAKE128_RATE]; -- unsigned char t1[SHAKE128_RATE]; -- unsigned char t2[SHAKE128_RATE]; -- unsigned char t3[SHAKE128_RATE]; -- unsigned int i; -- -- /* zero state */ -- for (i = 0; i < 25; i++) { -- s[i] = _mm256_xor_si256(s[i], s[i]); -- } -- -- /* absorb 4 message of identical length in parallel */ -- keccak_absorb4x(s, SHAKE128_RATE, in0, in1, in2, in3, (size_t)inlen, 0x1F); -- -- /* Squeeze output */ -- keccak_squeezeblocks4x(out0, out1, out2, out3, outlen / SHAKE128_RATE, s, SHAKE128_RATE); -- -- out0 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; -- out1 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; -- out2 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; -- out3 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; -- -- if (outlen % SHAKE128_RATE) { -- keccak_squeezeblocks4x(t0, t1, t2, t3, 1, s, SHAKE128_RATE); -- for (i = 0; i < outlen % SHAKE128_RATE; i++) { -- out0[i] = t0[i]; -- out1[i] = t1[i]; -- out2[i] = t2[i]; -- out3[i] = t3[i]; -- } -- } --} -- -- --void PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_shake256x4(unsigned char *out0, -- unsigned char *out1, -- unsigned char *out2, -- unsigned char *out3, -- unsigned long long outlen, -- unsigned char *in0, -- unsigned char *in1, -- unsigned char *in2, -- unsigned char *in3, -- unsigned long long inlen) { -- __m256i s[25]; -- unsigned char t0[SHAKE256_RATE]; -- unsigned char t1[SHAKE256_RATE]; -- unsigned char t2[SHAKE256_RATE]; -- unsigned char t3[SHAKE256_RATE]; -- unsigned int i; -- -- /* zero state */ -- for (i = 0; i < 25; i++) { -- s[i] = _mm256_xor_si256(s[i], s[i]); -- } -- -- /* absorb 4 message of identical length in parallel */ -- keccak_absorb4x(s, SHAKE256_RATE, in0, in1, in2, in3, (size_t)inlen, 0x1F); -- -- /* Squeeze output */ -- keccak_squeezeblocks4x(out0, out1, out2, out3, outlen / SHAKE256_RATE, s, SHAKE256_RATE); -- -- out0 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; -- out1 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; -- out2 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; -- out3 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; -- -- if (outlen % SHAKE256_RATE) { -- keccak_squeezeblocks4x(t0, t1, t2, t3, 1, s, SHAKE256_RATE); -- for (i = 0; i < outlen % SHAKE256_RATE; i++) { -- out0[i] = t0[i]; -- out1[i] = t1[i]; -- out2[i] = t2[i]; -- out3[i] = t3[i]; -- } -- } --} -diff --git a/crypto_sign/sphincs-shake256-256s-robust/avx2/fips202x4.h b/crypto_sign/sphincs-shake256-256s-robust/avx2/fips202x4.h -deleted file mode 100644 -index daa02fe..0000000 ---- a/crypto_sign/sphincs-shake256-256s-robust/avx2/fips202x4.h -+++ /dev/null -@@ -1,27 +0,0 @@ --#ifndef PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_FIPS202X4_H --#define PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_FIPS202X4_H -- --#include -- --void PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_shake128x4(unsigned char *out0, -- unsigned char *out1, -- unsigned char *out2, -- unsigned char *out3, -- unsigned long long outlen, -- unsigned char *in0, -- unsigned char *in1, -- unsigned char *in2, -- unsigned char *in3, unsigned long long inlen); -- --void PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_shake256x4(unsigned char *out0, -- unsigned char *out1, -- unsigned char *out2, -- unsigned char *out3, -- unsigned long long outlen, -- unsigned char *in0, -- unsigned char *in1, -- unsigned char *in2, -- unsigned char *in3, -- unsigned long long inlen); -- --#endif -diff --git a/crypto_sign/sphincs-shake256-256s-simple/avx2/fips202x4.c b/crypto_sign/sphincs-shake256-256s-simple/avx2/fips202x4.c -deleted file mode 100644 -index 18061a7..0000000 ---- a/crypto_sign/sphincs-shake256-256s-simple/avx2/fips202x4.c -+++ /dev/null -@@ -1,205 +0,0 @@ --#include --#include --#include -- --#include "fips202.h" --#include "fips202x4.h" -- --#define NROUNDS 24 --#define ROL(a, offset) (((a) << (offset)) ^ ((a) >> (64-(offset)))) -- --static uint64_t load64(const unsigned char *x) { -- unsigned long long r = 0, i; -- -- for (i = 0; i < 8; ++i) { -- r |= (unsigned long long)x[i] << 8 * i; -- } -- return r; --} -- --static void store64(uint8_t *x, uint64_t u) { -- unsigned int i; -- -- for (i = 0; i < 8; ++i) { -- x[i] = (uint8_t)u; -- u >>= 8; -- } --} -- --/* Use implementation from the Keccak Code Package */ --extern void KeccakP1600times4_PermuteAll_24rounds(__m256i *s); --#define KeccakF1600_StatePermute4x KeccakP1600times4_PermuteAll_24rounds -- --static void keccak_absorb4x(__m256i *s, -- unsigned int r, -- const unsigned char *m0, -- const unsigned char *m1, -- const unsigned char *m2, -- const unsigned char *m3, -- size_t mlen, -- unsigned char p) { -- unsigned char t0[200] = {0}; -- unsigned char t1[200] = {0}; -- unsigned char t2[200] = {0}; -- unsigned char t3[200] = {0}; -- -- unsigned long long *ss = (unsigned long long *)s; -- -- -- while (mlen >= r) { -- for (size_t i = 0; i < r / 8; ++i) { -- ss[4 * i + 0] ^= load64(m0 + 8 * i); -- ss[4 * i + 1] ^= load64(m1 + 8 * i); -- ss[4 * i + 2] ^= load64(m2 + 8 * i); -- ss[4 * i + 3] ^= load64(m3 + 8 * i); -- } -- -- KeccakF1600_StatePermute4x(s); -- mlen -= r; -- m0 += r; -- m1 += r; -- m2 += r; -- m3 += r; -- } -- -- memcpy(t0, m0, mlen); -- memcpy(t1, m1, mlen); -- memcpy(t2, m2, mlen); -- memcpy(t3, m3, mlen); -- -- t0[mlen] = p; -- t1[mlen] = p; -- t2[mlen] = p; -- t3[mlen] = p; -- -- t0[r - 1] |= 128; -- t1[r - 1] |= 128; -- t2[r - 1] |= 128; -- t3[r - 1] |= 128; -- -- for (size_t i = 0; i < r / 8; ++i) { -- ss[4 * i + 0] ^= load64(t0 + 8 * i); -- ss[4 * i + 1] ^= load64(t1 + 8 * i); -- ss[4 * i + 2] ^= load64(t2 + 8 * i); -- ss[4 * i + 3] ^= load64(t3 + 8 * i); -- } --} -- -- --static void keccak_squeezeblocks4x(unsigned char *h0, -- unsigned char *h1, -- unsigned char *h2, -- unsigned char *h3, -- unsigned long long int nblocks, -- __m256i *s, -- unsigned int r) { -- unsigned int i; -- -- unsigned long long *ss = (unsigned long long *)s; -- -- while (nblocks > 0) { -- KeccakF1600_StatePermute4x(s); -- for (i = 0; i < (r >> 3); i++) { -- store64(h0 + 8 * i, ss[4 * i + 0]); -- store64(h1 + 8 * i, ss[4 * i + 1]); -- store64(h2 + 8 * i, ss[4 * i + 2]); -- store64(h3 + 8 * i, ss[4 * i + 3]); -- } -- h0 += r; -- h1 += r; -- h2 += r; -- h3 += r; -- nblocks--; -- } --} -- -- -- --void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_shake128x4(unsigned char *out0, -- unsigned char *out1, -- unsigned char *out2, -- unsigned char *out3, -- unsigned long long outlen, -- unsigned char *in0, -- unsigned char *in1, -- unsigned char *in2, -- unsigned char *in3, -- unsigned long long inlen) { -- __m256i s[25]; -- unsigned char t0[SHAKE128_RATE]; -- unsigned char t1[SHAKE128_RATE]; -- unsigned char t2[SHAKE128_RATE]; -- unsigned char t3[SHAKE128_RATE]; -- unsigned int i; -- -- /* zero state */ -- for (i = 0; i < 25; i++) { -- s[i] = _mm256_xor_si256(s[i], s[i]); -- } -- -- /* absorb 4 message of identical length in parallel */ -- keccak_absorb4x(s, SHAKE128_RATE, in0, in1, in2, in3, (size_t)inlen, 0x1F); -- -- /* Squeeze output */ -- keccak_squeezeblocks4x(out0, out1, out2, out3, outlen / SHAKE128_RATE, s, SHAKE128_RATE); -- -- out0 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; -- out1 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; -- out2 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; -- out3 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; -- -- if (outlen % SHAKE128_RATE) { -- keccak_squeezeblocks4x(t0, t1, t2, t3, 1, s, SHAKE128_RATE); -- for (i = 0; i < outlen % SHAKE128_RATE; i++) { -- out0[i] = t0[i]; -- out1[i] = t1[i]; -- out2[i] = t2[i]; -- out3[i] = t3[i]; -- } -- } --} -- -- --void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_shake256x4(unsigned char *out0, -- unsigned char *out1, -- unsigned char *out2, -- unsigned char *out3, -- unsigned long long outlen, -- unsigned char *in0, -- unsigned char *in1, -- unsigned char *in2, -- unsigned char *in3, -- unsigned long long inlen) { -- __m256i s[25]; -- unsigned char t0[SHAKE256_RATE]; -- unsigned char t1[SHAKE256_RATE]; -- unsigned char t2[SHAKE256_RATE]; -- unsigned char t3[SHAKE256_RATE]; -- unsigned int i; -- -- /* zero state */ -- for (i = 0; i < 25; i++) { -- s[i] = _mm256_xor_si256(s[i], s[i]); -- } -- -- /* absorb 4 message of identical length in parallel */ -- keccak_absorb4x(s, SHAKE256_RATE, in0, in1, in2, in3, (size_t)inlen, 0x1F); -- -- /* Squeeze output */ -- keccak_squeezeblocks4x(out0, out1, out2, out3, outlen / SHAKE256_RATE, s, SHAKE256_RATE); -- -- out0 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; -- out1 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; -- out2 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; -- out3 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; -- -- if (outlen % SHAKE256_RATE) { -- keccak_squeezeblocks4x(t0, t1, t2, t3, 1, s, SHAKE256_RATE); -- for (i = 0; i < outlen % SHAKE256_RATE; i++) { -- out0[i] = t0[i]; -- out1[i] = t1[i]; -- out2[i] = t2[i]; -- out3[i] = t3[i]; -- } -- } --} -diff --git a/crypto_sign/sphincs-shake256-256s-simple/avx2/fips202x4.h b/crypto_sign/sphincs-shake256-256s-simple/avx2/fips202x4.h -deleted file mode 100644 -index ebcd58d..0000000 ---- a/crypto_sign/sphincs-shake256-256s-simple/avx2/fips202x4.h -+++ /dev/null -@@ -1,27 +0,0 @@ --#ifndef PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_FIPS202X4_H --#define PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_FIPS202X4_H -- --#include -- --void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_shake128x4(unsigned char *out0, -- unsigned char *out1, -- unsigned char *out2, -- unsigned char *out3, -- unsigned long long outlen, -- unsigned char *in0, -- unsigned char *in1, -- unsigned char *in2, -- unsigned char *in3, unsigned long long inlen); -- --void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_shake256x4(unsigned char *out0, -- unsigned char *out1, -- unsigned char *out2, -- unsigned char *out3, -- unsigned long long outlen, -- unsigned char *in0, -- unsigned char *in1, -- unsigned char *in2, -- unsigned char *in3, -- unsigned long long inlen); -- --#endif From 1832a7e8092a8e7f30e450ec3d784053dcbfa7db Mon Sep 17 00:00:00 2001 From: Douglas Stebila Date: Sat, 18 Mar 2023 11:10:42 -0400 Subject: [PATCH 02/10] Run copy_from_upstream --- .CMake/alg_support.cmake | 72 +++ docs/algorithms/kem/classic_mceliece.md | 2 +- docs/algorithms/kem/classic_mceliece.yml | 2 +- docs/algorithms/kem/hqc.md | 2 +- docs/algorithms/kem/hqc.yml | 2 +- docs/algorithms/kem/kyber.md | 2 +- docs/algorithms/kem/kyber.yml | 2 +- docs/algorithms/sig/dilithium.md | 2 +- docs/algorithms/sig/dilithium.yml | 2 +- docs/algorithms/sig/falcon.md | 2 +- docs/algorithms/sig/falcon.yml | 2 +- docs/algorithms/sig/sphincs.md | 20 +- docs/algorithms/sig/sphincs.yml | 21 +- docs/cbom.json | 46 +- src/oqsconfig.h.cmake | 12 + src/sig/sphincs/CMakeLists.txt | 336 ++++++++----- .../address.c | 111 +++-- .../address.h | 60 +-- .../api.h | 40 +- .../context.h | 22 + .../context_haraka.c | 11 + .../fors.c | 228 +++++---- .../fors.h | 30 +- .../haraka.c | 351 +++++--------- .../haraka.h | 73 ++- .../haraka_offsets.h | 21 + .../harakax4.h | 36 ++ .../hash.h | 39 +- .../hash_haraka.c | 105 ++--- .../hash_harakax4.c | 36 +- .../hash_state.h | 26 - .../hashx4.h | 21 +- .../merkle.c | 64 +++ .../merkle.h | 21 + .../nistapi.h | 87 ++++ .../params.h | 61 +-- .../sign.c | 363 +++++--------- .../thash.h | 29 +- .../thash_haraka_robust.c | 85 +--- .../thash_haraka_robustx4.c | 163 +++---- .../thashx4.h | 33 +- .../utils.c | 165 +++---- .../utils.h | 70 ++- .../utilsx4.c | 216 +++++---- .../utilsx4.h | 44 +- .../wots.c | 337 +++++++------ .../wots.h | 44 +- .../wotsx4.h | 41 ++ .../address.c | 111 +++-- .../address.h | 60 +-- .../api.h | 40 +- .../context.h | 24 + .../context_haraka.c | 11 + .../fors.c | 169 ++++--- .../fors.h | 30 +- .../haraka.c | 148 ++---- .../haraka.h | 56 +-- .../haraka_offsets.h | 21 + .../hash.h | 39 +- .../hash_haraka.c | 105 ++--- .../hash_state.h | 26 - .../merkle.c | 59 +++ .../merkle.h | 21 + .../nistapi.h | 87 ++++ .../params.h | 61 +-- .../sign.c | 310 +++++------- .../thash.h | 29 +- .../thash_haraka_robust.c | 85 +--- .../utils.c | 165 +++---- .../utils.h | 70 ++- .../utilsx1.c | 100 ++++ .../utilsx1.h | 27 ++ .../wots.c | 125 ++--- .../wots.h | 44 +- .../wotsx1.c | 76 +++ .../wotsx1.h | 39 ++ .../address.c | 111 +++-- .../address.h | 60 +-- .../api.h | 40 +- .../context.h | 22 + .../context_haraka.c | 11 + .../fors.c | 228 +++++---- .../fors.h | 30 +- .../haraka.c | 351 +++++--------- .../haraka.h | 73 ++- .../haraka_offsets.h | 21 + .../harakax4.h | 36 ++ .../hash.h | 39 +- .../hash_haraka.c | 105 ++--- .../hash_harakax4.c | 36 +- .../hash_state.h | 26 - .../hashx4.h | 21 +- .../merkle.c | 64 +++ .../merkle.h | 21 + .../nistapi.h | 87 ++++ .../params.h | 61 +-- .../sign.c | 363 +++++--------- .../thash.h | 29 +- .../thash_haraka_simple.c | 73 +-- .../thash_haraka_simplex4.c | 111 ++--- .../thashx4.h | 33 +- .../utils.c | 165 +++---- .../utils.h | 70 ++- .../utilsx4.c | 216 +++++---- .../utilsx4.h | 44 +- .../wots.c | 337 +++++++------ .../wots.h | 44 +- .../wotsx4.h | 41 ++ .../address.c | 111 +++-- .../address.h | 60 +-- .../api.h | 40 +- .../context.h | 24 + .../context_haraka.c | 11 + .../fors.c | 169 ++++--- .../fors.h | 30 +- .../haraka.c | 148 ++---- .../haraka.h | 56 +-- .../haraka_offsets.h | 21 + .../hash.h | 39 +- .../hash_haraka.c | 105 ++--- .../hash_state.h | 26 - .../merkle.c | 59 +++ .../merkle.h | 21 + .../nistapi.h | 87 ++++ .../params.h | 61 +-- .../sign.c | 310 +++++------- .../thash.h | 29 +- .../thash_haraka_simple.c | 73 +-- .../utils.c | 165 +++---- .../utils.h | 70 ++- .../utilsx1.c | 100 ++++ .../utilsx1.h | 27 ++ .../wots.c | 125 ++--- .../wots.h | 44 +- .../wotsx1.c | 76 +++ .../wotsx1.h | 39 ++ .../address.c | 115 +++-- .../address.h | 60 +-- .../api.h | 40 +- .../context.h | 22 + .../context_haraka.c | 11 + .../fors.c | 228 +++++---- .../fors.h | 30 +- .../haraka.c | 351 +++++--------- .../haraka.h | 73 ++- .../haraka_offsets.h | 21 + .../harakax4.h | 36 ++ .../hash.h | 39 +- .../hash_haraka.c | 105 ++--- .../hash_harakax4.c | 36 +- .../hash_state.h | 26 - .../hashx4.h | 21 +- .../merkle.c | 64 +++ .../merkle.h | 21 + .../nistapi.h | 87 ++++ .../params.h | 61 +-- .../sign.c | 363 +++++--------- .../thash.h | 29 +- .../thash_haraka_robust.c | 85 +--- .../thash_haraka_robustx4.c | 163 +++---- .../thashx4.h | 33 +- .../utils.c | 165 +++---- .../utils.h | 70 ++- .../utilsx4.c | 216 +++++---- .../utilsx4.h | 44 +- .../wots.c | 337 +++++++------ .../wots.h | 44 +- .../wotsx4.h | 41 ++ .../address.c | 115 +++-- .../address.h | 60 +-- .../api.h | 40 +- .../context.h | 24 + .../context_haraka.c | 11 + .../fors.c | 169 ++++--- .../fors.h | 30 +- .../haraka.c | 148 ++---- .../haraka.h | 56 +-- .../haraka_offsets.h | 21 + .../hash.h | 39 +- .../hash_haraka.c | 105 ++--- .../hash_state.h | 26 - .../merkle.c | 59 +++ .../merkle.h | 21 + .../nistapi.h | 87 ++++ .../params.h | 61 +-- .../sign.c | 310 +++++------- .../thash.h | 29 +- .../thash_haraka_robust.c | 85 +--- .../utils.c | 165 +++---- .../utils.h | 70 ++- .../utilsx1.c | 100 ++++ .../utilsx1.h | 27 ++ .../wots.c | 125 ++--- .../wots.h | 44 +- .../wotsx1.c | 76 +++ .../wotsx1.h | 39 ++ .../address.c | 115 +++-- .../address.h | 60 +-- .../api.h | 40 +- .../context.h | 22 + .../context_haraka.c | 11 + .../fors.c | 228 +++++---- .../fors.h | 30 +- .../haraka.c | 351 +++++--------- .../haraka.h | 73 ++- .../haraka_offsets.h | 21 + .../harakax4.h | 36 ++ .../hash.h | 39 +- .../hash_haraka.c | 105 ++--- .../hash_harakax4.c | 36 +- .../hash_state.h | 26 - .../hashx4.h | 21 +- .../merkle.c | 64 +++ .../merkle.h | 21 + .../nistapi.h | 87 ++++ .../params.h | 61 +-- .../sign.c | 363 +++++--------- .../thash.h | 29 +- .../thash_haraka_simple.c | 73 +-- .../thash_haraka_simplex4.c | 111 ++--- .../thashx4.h | 33 +- .../utils.c | 165 +++---- .../utils.h | 70 ++- .../utilsx4.c | 216 +++++---- .../utilsx4.h | 44 +- .../wots.c | 337 +++++++------ .../wots.h | 44 +- .../wotsx4.h | 41 ++ .../address.c | 115 +++-- .../address.h | 60 +-- .../api.h | 40 +- .../context.h | 24 + .../context_haraka.c | 11 + .../fors.c | 169 ++++--- .../fors.h | 30 +- .../haraka.c | 148 ++---- .../haraka.h | 56 +-- .../haraka_offsets.h | 21 + .../hash.h | 39 +- .../hash_haraka.c | 105 ++--- .../hash_state.h | 26 - .../merkle.c | 59 +++ .../merkle.h | 21 + .../nistapi.h | 87 ++++ .../params.h | 61 +-- .../sign.c | 310 +++++------- .../thash.h | 29 +- .../thash_haraka_simple.c | 73 +-- .../utils.c | 165 +++---- .../utils.h | 70 ++- .../utilsx1.c | 100 ++++ .../utilsx1.h | 27 ++ .../wots.c | 125 ++--- .../wots.h | 44 +- .../wotsx1.c | 76 +++ .../wotsx1.h | 39 ++ .../address.c | 111 +++-- .../address.h | 60 +-- .../api.h | 40 +- .../context.h | 22 + .../context_haraka.c | 11 + .../fors.c | 228 +++++---- .../fors.h | 30 +- .../haraka.c | 351 +++++--------- .../haraka.h | 73 ++- .../haraka_offsets.h | 21 + .../harakax4.h | 36 ++ .../hash.h | 39 +- .../hash_haraka.c | 105 ++--- .../hash_harakax4.c | 36 +- .../hash_state.h | 26 - .../hashx4.h | 21 +- .../merkle.c | 64 +++ .../merkle.h | 21 + .../nistapi.h | 87 ++++ .../params.h | 61 +-- .../sign.c | 363 +++++--------- .../thash.h | 29 +- .../thash_haraka_robust.c | 85 +--- .../thash_haraka_robustx4.c | 163 +++---- .../thashx4.h | 33 +- .../utils.c | 165 +++---- .../utils.h | 70 ++- .../utilsx4.c | 216 +++++---- .../utilsx4.h | 44 +- .../wots.c | 337 +++++++------ .../wots.h | 44 +- .../wotsx4.h | 41 ++ .../address.c | 111 +++-- .../address.h | 60 +-- .../api.h | 40 +- .../context.h | 24 + .../context_haraka.c | 11 + .../fors.c | 169 ++++--- .../fors.h | 30 +- .../haraka.c | 148 ++---- .../haraka.h | 56 +-- .../haraka_offsets.h | 21 + .../hash.h | 39 +- .../hash_haraka.c | 105 ++--- .../hash_state.h | 26 - .../merkle.c | 59 +++ .../merkle.h | 21 + .../nistapi.h | 87 ++++ .../params.h | 61 +-- .../sign.c | 310 +++++------- .../thash.h | 29 +- .../thash_haraka_robust.c | 85 +--- .../utils.c | 165 +++---- .../utils.h | 70 ++- .../utilsx1.c | 100 ++++ .../utilsx1.h | 27 ++ .../wots.c | 125 ++--- .../wots.h | 44 +- .../wotsx1.c | 76 +++ .../wotsx1.h | 39 ++ .../address.c | 111 +++-- .../address.h | 60 +-- .../api.h | 40 +- .../context.h | 22 + .../context_haraka.c | 11 + .../fors.c | 228 +++++---- .../fors.h | 30 +- .../haraka.c | 351 +++++--------- .../haraka.h | 73 ++- .../haraka_offsets.h | 21 + .../harakax4.h | 36 ++ .../hash.h | 39 +- .../hash_haraka.c | 105 ++--- .../hash_harakax4.c | 36 +- .../hash_state.h | 26 - .../hashx4.h | 21 +- .../merkle.c | 64 +++ .../merkle.h | 21 + .../nistapi.h | 87 ++++ .../params.h | 61 +-- .../sign.c | 363 +++++--------- .../thash.h | 29 +- .../thash_haraka_simple.c | 73 +-- .../thash_haraka_simplex4.c | 111 ++--- .../thashx4.h | 33 +- .../utils.c | 165 +++---- .../utils.h | 70 ++- .../utilsx4.c | 216 +++++---- .../utilsx4.h | 44 +- .../wots.c | 337 +++++++------ .../wots.h | 44 +- .../wotsx4.h | 41 ++ .../address.c | 111 +++-- .../address.h | 60 +-- .../api.h | 40 +- .../context.h | 24 + .../context_haraka.c | 11 + .../fors.c | 169 ++++--- .../fors.h | 30 +- .../haraka.c | 148 ++---- .../haraka.h | 56 +-- .../haraka_offsets.h | 21 + .../hash.h | 39 +- .../hash_haraka.c | 105 ++--- .../hash_state.h | 26 - .../merkle.c | 59 +++ .../merkle.h | 21 + .../nistapi.h | 87 ++++ .../params.h | 61 +-- .../sign.c | 310 +++++------- .../thash.h | 29 +- .../thash_haraka_simple.c | 73 +-- .../utils.c | 165 +++---- .../utils.h | 70 ++- .../utilsx1.c | 100 ++++ .../utilsx1.h | 27 ++ .../wots.c | 125 ++--- .../wots.h | 44 +- .../wotsx1.c | 76 +++ .../wotsx1.h | 39 ++ .../address.c | 115 +++-- .../address.h | 60 +-- .../api.h | 40 +- .../context.h | 22 + .../context_haraka.c | 11 + .../fors.c | 228 +++++---- .../fors.h | 30 +- .../haraka.c | 351 +++++--------- .../haraka.h | 73 ++- .../haraka_offsets.h | 21 + .../harakax4.h | 36 ++ .../hash.h | 39 +- .../hash_haraka.c | 105 ++--- .../hash_harakax4.c | 36 +- .../hash_state.h | 26 - .../hashx4.h | 21 +- .../merkle.c | 64 +++ .../merkle.h | 21 + .../nistapi.h | 87 ++++ .../params.h | 61 +-- .../sign.c | 363 +++++--------- .../thash.h | 29 +- .../thash_haraka_robust.c | 85 +--- .../thash_haraka_robustx4.c | 163 +++---- .../thashx4.h | 33 +- .../utils.c | 165 +++---- .../utils.h | 70 ++- .../utilsx4.c | 216 +++++---- .../utilsx4.h | 44 +- .../wots.c | 337 +++++++------ .../wots.h | 44 +- .../wotsx4.h | 41 ++ .../address.c | 115 +++-- .../address.h | 60 +-- .../api.h | 40 +- .../context.h | 24 + .../context_haraka.c | 11 + .../fors.c | 169 ++++--- .../fors.h | 30 +- .../haraka.c | 148 ++---- .../haraka.h | 56 +-- .../haraka_offsets.h | 21 + .../hash.h | 39 +- .../hash_haraka.c | 105 ++--- .../hash_state.h | 26 - .../merkle.c | 59 +++ .../merkle.h | 21 + .../nistapi.h | 87 ++++ .../params.h | 61 +-- .../sign.c | 310 +++++------- .../thash.h | 29 +- .../thash_haraka_robust.c | 85 +--- .../utils.c | 165 +++---- .../utils.h | 70 ++- .../utilsx1.c | 100 ++++ .../utilsx1.h | 27 ++ .../wots.c | 125 ++--- .../wots.h | 44 +- .../wotsx1.c | 76 +++ .../wotsx1.h | 39 ++ .../address.c | 115 +++-- .../address.h | 60 +-- .../api.h | 40 +- .../context.h | 22 + .../context_haraka.c | 11 + .../fors.c | 228 +++++---- .../fors.h | 30 +- .../haraka.c | 351 +++++--------- .../haraka.h | 73 ++- .../haraka_offsets.h | 21 + .../harakax4.h | 36 ++ .../hash.h | 39 +- .../hash_haraka.c | 105 ++--- .../hash_harakax4.c | 36 +- .../hash_state.h | 26 - .../hashx4.h | 21 +- .../merkle.c | 64 +++ .../merkle.h | 21 + .../nistapi.h | 87 ++++ .../params.h | 61 +-- .../sign.c | 363 +++++--------- .../thash.h | 29 +- .../thash_haraka_simple.c | 73 +-- .../thash_haraka_simplex4.c | 111 ++--- .../thashx4.h | 33 +- .../utils.c | 165 +++---- .../utils.h | 70 ++- .../utilsx4.c | 216 +++++---- .../utilsx4.h | 44 +- .../wots.c | 337 +++++++------ .../wots.h | 44 +- .../wotsx4.h | 41 ++ .../address.c | 115 +++-- .../address.h | 60 +-- .../api.h | 40 +- .../context.h | 24 + .../context_haraka.c | 11 + .../fors.c | 169 ++++--- .../fors.h | 30 +- .../haraka.c | 148 ++---- .../haraka.h | 56 +-- .../haraka_offsets.h | 21 + .../hash.h | 39 +- .../hash_haraka.c | 105 ++--- .../hash_state.h | 26 - .../merkle.c | 59 +++ .../merkle.h | 21 + .../nistapi.h | 87 ++++ .../params.h | 61 +-- .../sign.c | 310 +++++------- .../thash.h | 29 +- .../thash_haraka_simple.c | 73 +-- .../utils.c | 165 +++---- .../utils.h | 70 ++- .../utilsx1.c | 100 ++++ .../utilsx1.h | 27 ++ .../wots.c | 125 ++--- .../wots.h | 44 +- .../wotsx1.c | 76 +++ .../wotsx1.h | 39 ++ .../address.c | 111 +++-- .../address.h | 60 +-- .../api.h | 40 +- .../context.h | 22 + .../context_haraka.c | 11 + .../fors.c | 228 +++++---- .../fors.h | 30 +- .../haraka.c | 351 +++++--------- .../haraka.h | 73 ++- .../haraka_offsets.h | 21 + .../harakax4.h | 36 ++ .../hash.h | 39 +- .../hash_haraka.c | 105 ++--- .../hash_harakax4.c | 36 +- .../hash_state.h | 26 - .../hashx4.h | 21 +- .../merkle.c | 64 +++ .../merkle.h | 21 + .../nistapi.h | 87 ++++ .../params.h | 61 +-- .../sign.c | 363 +++++--------- .../thash.h | 29 +- .../thash_haraka_robust.c | 85 +--- .../thash_haraka_robustx4.c | 163 +++---- .../thashx4.h | 33 +- .../utils.c | 165 +++---- .../utils.h | 70 ++- .../utilsx4.c | 216 +++++---- .../utilsx4.h | 44 +- .../wots.c | 337 +++++++------ .../wots.h | 44 +- .../wotsx4.h | 41 ++ .../address.c | 111 +++-- .../address.h | 60 +-- .../api.h | 40 +- .../context.h | 24 + .../context_haraka.c | 11 + .../fors.c | 169 ++++--- .../fors.h | 30 +- .../haraka.c | 148 ++---- .../haraka.h | 56 +-- .../haraka_offsets.h | 21 + .../hash.h | 39 +- .../hash_haraka.c | 105 ++--- .../hash_state.h | 26 - .../merkle.c | 59 +++ .../merkle.h | 21 + .../nistapi.h | 87 ++++ .../params.h | 61 +-- .../sign.c | 310 +++++------- .../thash.h | 29 +- .../thash_haraka_robust.c | 85 +--- .../utils.c | 165 +++---- .../utils.h | 70 ++- .../utilsx1.c | 100 ++++ .../utilsx1.h | 27 ++ .../wots.c | 125 ++--- .../wots.h | 44 +- .../wotsx1.c | 76 +++ .../wotsx1.h | 39 ++ .../address.c | 111 +++-- .../address.h | 60 +-- .../api.h | 40 +- .../context.h | 22 + .../context_haraka.c | 11 + .../fors.c | 228 +++++---- .../fors.h | 30 +- .../haraka.c | 351 +++++--------- .../haraka.h | 73 ++- .../haraka_offsets.h | 21 + .../harakax4.h | 36 ++ .../hash.h | 39 +- .../hash_haraka.c | 105 ++--- .../hash_harakax4.c | 36 +- .../hash_state.h | 26 - .../hashx4.h | 21 +- .../merkle.c | 64 +++ .../merkle.h | 21 + .../nistapi.h | 87 ++++ .../params.h | 61 +-- .../sign.c | 363 +++++--------- .../thash.h | 29 +- .../thash_haraka_simple.c | 73 +-- .../thash_haraka_simplex4.c | 111 ++--- .../thashx4.h | 33 +- .../utils.c | 165 +++---- .../utils.h | 70 ++- .../utilsx4.c | 216 +++++---- .../utilsx4.h | 44 +- .../wots.c | 337 +++++++------ .../wots.h | 44 +- .../wotsx4.h | 41 ++ .../address.c | 111 +++-- .../address.h | 60 +-- .../api.h | 40 +- .../context.h | 24 + .../context_haraka.c | 11 + .../fors.c | 169 ++++--- .../fors.h | 30 +- .../haraka.c | 148 ++---- .../haraka.h | 56 +-- .../haraka_offsets.h | 21 + .../hash.h | 39 +- .../hash_haraka.c | 105 ++--- .../hash_state.h | 26 - .../merkle.c | 59 +++ .../merkle.h | 21 + .../nistapi.h | 87 ++++ .../params.h | 61 +-- .../sign.c | 310 +++++------- .../thash.h | 29 +- .../thash_haraka_simple.c | 73 +-- .../utils.c | 165 +++---- .../utils.h | 70 ++- .../utilsx1.c | 100 ++++ .../utilsx1.h | 27 ++ .../wots.c | 125 ++--- .../wots.h | 44 +- .../wotsx1.c | 76 +++ .../wotsx1.h | 39 ++ .../address.c | 111 +++-- .../address.h | 60 +-- .../api.h | 40 +- .../context.h | 22 + .../context_haraka.c | 11 + .../fors.c | 228 +++++---- .../fors.h | 30 +- .../haraka.c | 351 +++++--------- .../haraka.h | 73 ++- .../haraka_offsets.h | 21 + .../harakax4.h | 36 ++ .../hash.h | 39 +- .../hash_haraka.c | 105 ++--- .../hash_harakax4.c | 36 +- .../hash_state.h | 26 - .../hashx4.h | 21 +- .../merkle.c | 64 +++ .../merkle.h | 21 + .../nistapi.h | 87 ++++ .../params.h | 61 +-- .../sign.c | 363 +++++--------- .../thash.h | 29 +- .../thash_haraka_robust.c | 85 +--- .../thash_haraka_robustx4.c | 163 +++---- .../thashx4.h | 33 +- .../utils.c | 165 +++---- .../utils.h | 70 ++- .../utilsx4.c | 216 +++++---- .../utilsx4.h | 44 +- .../wots.c | 337 +++++++------ .../wots.h | 44 +- .../wotsx4.h | 41 ++ .../address.c | 111 +++-- .../address.h | 60 +-- .../api.h | 40 +- .../context.h | 24 + .../context_haraka.c | 11 + .../fors.c | 169 ++++--- .../fors.h | 30 +- .../haraka.c | 148 ++---- .../haraka.h | 56 +-- .../haraka_offsets.h | 21 + .../hash.h | 39 +- .../hash_haraka.c | 105 ++--- .../hash_state.h | 26 - .../merkle.c | 59 +++ .../merkle.h | 21 + .../nistapi.h | 87 ++++ .../params.h | 61 +-- .../sign.c | 310 +++++------- .../thash.h | 29 +- .../thash_haraka_robust.c | 85 +--- .../utils.c | 165 +++---- .../utils.h | 70 ++- .../utilsx1.c | 100 ++++ .../utilsx1.h | 27 ++ .../wots.c | 125 ++--- .../wots.h | 44 +- .../wotsx1.c | 76 +++ .../wotsx1.h | 39 ++ .../address.c | 111 +++-- .../address.h | 60 +-- .../api.h | 40 +- .../context.h | 22 + .../context_haraka.c | 11 + .../fors.c | 228 +++++---- .../fors.h | 30 +- .../haraka.c | 351 +++++--------- .../haraka.h | 73 ++- .../haraka_offsets.h | 21 + .../harakax4.h | 36 ++ .../hash.h | 39 +- .../hash_haraka.c | 105 ++--- .../hash_harakax4.c | 36 +- .../hash_state.h | 26 - .../hashx4.h | 21 +- .../merkle.c | 64 +++ .../merkle.h | 21 + .../nistapi.h | 87 ++++ .../params.h | 61 +-- .../sign.c | 363 +++++--------- .../thash.h | 29 +- .../thash_haraka_simple.c | 73 +-- .../thash_haraka_simplex4.c | 111 ++--- .../thashx4.h | 33 +- .../utils.c | 165 +++---- .../utils.h | 70 ++- .../utilsx4.c | 216 +++++---- .../utilsx4.h | 44 +- .../wots.c | 337 +++++++------ .../wots.h | 44 +- .../wotsx4.h | 41 ++ .../address.c | 111 +++-- .../address.h | 60 +-- .../api.h | 40 +- .../context.h | 24 + .../context_haraka.c | 11 + .../fors.c | 169 ++++--- .../fors.h | 30 +- .../haraka.c | 148 ++---- .../haraka.h | 56 +-- .../haraka_offsets.h | 21 + .../hash.h | 39 +- .../hash_haraka.c | 105 ++--- .../hash_state.h | 26 - .../merkle.c | 59 +++ .../merkle.h | 21 + .../nistapi.h | 87 ++++ .../params.h | 61 +-- .../sign.c | 310 +++++------- .../thash.h | 29 +- .../thash_haraka_simple.c | 73 +-- .../utils.c | 165 +++---- .../utils.h | 70 ++- .../utilsx1.c | 100 ++++ .../utilsx1.h | 27 ++ .../wots.c | 125 ++--- .../wots.h | 44 +- .../wotsx1.c | 76 +++ .../wotsx1.h | 39 ++ .../LICENSE | 116 +++++ .../address.c | 91 ++++ .../address.h | 52 ++ .../api.h | 77 +++ .../context.h | 26 + .../context_sha2.c | 44 ++ .../fors.c | 226 +++++++++ .../fors.h | 32 ++ .../hash.h | 37 ++ .../hash_sha2.c | 219 +++++++++ .../hash_sha2x8.c | 75 +++ .../hashx8.h | 20 + .../merkle.c | 65 +++ .../merkle.h | 21 + .../nistapi.h | 87 ++++ .../params.h | 61 +++ .../sha256avx.c | 357 ++++++++++++++ .../sha256avx.h | 44 ++ .../sha256x8.c | 185 ++++++++ .../sha256x8.h | 64 +++ .../sha2_offsets.h | 27 ++ .../sign.c | 286 +++++++++++ .../thash.h | 13 + .../thash_sha2_robust.c | 39 ++ .../thash_sha2_robustx8.c | 121 +++++ .../thashx8.h | 28 ++ .../utils.c | 148 ++++++ .../utils.h | 58 +++ .../utilsx8.c | 146 ++++++ .../utilsx8.h | 29 ++ .../wots.c | 291 ++++++++++++ .../wots.h | 25 + .../wotsx8.h | 42 ++ .../LICENSE | 116 +++++ .../address.c | 91 ++++ .../address.h | 52 ++ .../api.h | 77 +++ .../context.h | 26 + .../context_sha2.c | 33 ++ .../fors.c | 156 ++++++ .../fors.h | 32 ++ .../hash.h | 37 ++ .../hash_sha2.c | 219 +++++++++ .../merkle.c | 59 +++ .../merkle.h | 21 + .../nistapi.h | 87 ++++ .../params.h | 61 +++ .../sha2_offsets.h | 27 ++ .../sign.c | 286 +++++++++++ .../thash.h | 13 + .../thash_sha2_robust.c | 39 ++ .../utils.c | 148 ++++++ .../utils.h | 58 +++ .../utilsx1.c | 100 ++++ .../utilsx1.h | 27 ++ .../wots.c | 108 +++++ .../wots.h | 25 + .../wotsx1.c | 76 +++ .../wotsx1.h | 39 ++ .../LICENSE | 116 +++++ .../address.c | 91 ++++ .../address.h | 52 ++ .../api.h | 77 +++ .../context.h | 26 + .../context_sha2.c | 44 ++ .../fors.c | 226 +++++++++ .../fors.h | 32 ++ .../hash.h | 37 ++ .../hash_sha2.c | 219 +++++++++ .../hash_sha2x8.c | 75 +++ .../hashx8.h | 20 + .../merkle.c | 65 +++ .../merkle.h | 21 + .../nistapi.h | 87 ++++ .../params.h | 61 +++ .../sha256avx.c | 357 ++++++++++++++ .../sha256avx.h | 44 ++ .../sha256x8.c | 185 ++++++++ .../sha256x8.h | 64 +++ .../sha2_offsets.h | 27 ++ .../sign.c | 286 +++++++++++ .../thash.h | 13 + .../thash_sha2_simple.c | 32 ++ .../thash_sha2_simplex8.c | 96 ++++ .../thashx8.h | 28 ++ .../utils.c | 148 ++++++ .../utils.h | 58 +++ .../utilsx8.c | 146 ++++++ .../utilsx8.h | 29 ++ .../wots.c | 291 ++++++++++++ .../wots.h | 25 + .../wotsx8.h | 42 ++ .../LICENSE | 116 +++++ .../address.c | 91 ++++ .../address.h | 52 ++ .../api.h | 77 +++ .../context.h | 26 + .../context_sha2.c | 33 ++ .../fors.c | 156 ++++++ .../fors.h | 32 ++ .../hash.h | 37 ++ .../hash_sha2.c | 219 +++++++++ .../merkle.c | 59 +++ .../merkle.h | 21 + .../nistapi.h | 87 ++++ .../params.h | 61 +++ .../sha2_offsets.h | 27 ++ .../sign.c | 286 +++++++++++ .../thash.h | 13 + .../thash_sha2_simple.c | 32 ++ .../utils.c | 148 ++++++ .../utils.h | 58 +++ .../utilsx1.c | 100 ++++ .../utilsx1.h | 27 ++ .../wots.c | 108 +++++ .../wots.h | 25 + .../wotsx1.c | 76 +++ .../wotsx1.h | 39 ++ .../LICENSE | 116 +++++ .../address.c | 95 ++++ .../address.h | 52 ++ .../api.h | 77 +++ .../context.h | 26 + .../context_sha2.c | 44 ++ .../fors.c | 226 +++++++++ .../fors.h | 32 ++ .../hash.h | 37 ++ .../hash_sha2.c | 219 +++++++++ .../hash_sha2x8.c | 75 +++ .../hashx8.h | 20 + .../merkle.c | 65 +++ .../merkle.h | 21 + .../nistapi.h | 87 ++++ .../params.h | 61 +++ .../sha256avx.c | 357 ++++++++++++++ .../sha256avx.h | 44 ++ .../sha256x8.c | 185 ++++++++ .../sha256x8.h | 64 +++ .../sha2_offsets.h | 27 ++ .../sign.c | 286 +++++++++++ .../thash.h | 13 + .../thash_sha2_robust.c | 39 ++ .../thash_sha2_robustx8.c | 121 +++++ .../thashx8.h | 28 ++ .../utils.c | 148 ++++++ .../utils.h | 58 +++ .../utilsx8.c | 146 ++++++ .../utilsx8.h | 29 ++ .../wots.c | 291 ++++++++++++ .../wots.h | 25 + .../wotsx8.h | 42 ++ .../LICENSE | 116 +++++ .../address.c | 95 ++++ .../address.h | 52 ++ .../api.h | 77 +++ .../context.h | 26 + .../context_sha2.c | 33 ++ .../fors.c | 156 ++++++ .../fors.h | 32 ++ .../hash.h | 37 ++ .../hash_sha2.c | 219 +++++++++ .../merkle.c | 59 +++ .../merkle.h | 21 + .../nistapi.h | 87 ++++ .../params.h | 61 +++ .../sha2_offsets.h | 27 ++ .../sign.c | 286 +++++++++++ .../thash.h | 13 + .../thash_sha2_robust.c | 39 ++ .../utils.c | 148 ++++++ .../utils.h | 58 +++ .../utilsx1.c | 100 ++++ .../utilsx1.h | 27 ++ .../wots.c | 108 +++++ .../wots.h | 25 + .../wotsx1.c | 76 +++ .../wotsx1.h | 39 ++ .../LICENSE | 116 +++++ .../address.c | 95 ++++ .../address.h | 52 ++ .../api.h | 77 +++ .../context.h | 26 + .../context_sha2.c | 44 ++ .../fors.c | 226 +++++++++ .../fors.h | 32 ++ .../hash.h | 37 ++ .../hash_sha2.c | 219 +++++++++ .../hash_sha2x8.c | 75 +++ .../hashx8.h | 20 + .../merkle.c | 65 +++ .../merkle.h | 21 + .../nistapi.h | 87 ++++ .../params.h | 61 +++ .../sha256avx.c | 357 ++++++++++++++ .../sha256avx.h | 44 ++ .../sha256x8.c | 185 ++++++++ .../sha256x8.h | 64 +++ .../sha2_offsets.h | 27 ++ .../sign.c | 286 +++++++++++ .../thash.h | 13 + .../thash_sha2_simple.c | 32 ++ .../thash_sha2_simplex8.c | 96 ++++ .../thashx8.h | 28 ++ .../utils.c | 148 ++++++ .../utils.h | 58 +++ .../utilsx8.c | 146 ++++++ .../utilsx8.h | 29 ++ .../wots.c | 291 ++++++++++++ .../wots.h | 25 + .../wotsx8.h | 42 ++ .../LICENSE | 116 +++++ .../address.c | 95 ++++ .../address.h | 52 ++ .../api.h | 77 +++ .../context.h | 26 + .../context_sha2.c | 33 ++ .../fors.c | 156 ++++++ .../fors.h | 32 ++ .../hash.h | 37 ++ .../hash_sha2.c | 219 +++++++++ .../merkle.c | 59 +++ .../merkle.h | 21 + .../nistapi.h | 87 ++++ .../params.h | 61 +++ .../sha2_offsets.h | 27 ++ .../sign.c | 286 +++++++++++ .../thash.h | 13 + .../thash_sha2_simple.c | 32 ++ .../utils.c | 148 ++++++ .../utils.h | 58 +++ .../utilsx1.c | 100 ++++ .../utilsx1.h | 27 ++ .../wots.c | 108 +++++ .../wots.h | 25 + .../wotsx1.c | 76 +++ .../wotsx1.h | 39 ++ .../LICENSE | 116 +++++ .../address.c | 91 ++++ .../address.h | 52 ++ .../api.h | 77 +++ .../context.h | 29 ++ .../context_sha2.c | 56 +++ .../fors.c | 226 +++++++++ .../fors.h | 32 ++ .../hash.h | 37 ++ .../hash_sha2.c | 219 +++++++++ .../hash_sha2x8.c | 75 +++ .../hashx8.h | 20 + .../merkle.c | 65 +++ .../merkle.h | 21 + .../nistapi.h | 87 ++++ .../params.h | 61 +++ .../sha256avx.c | 357 ++++++++++++++ .../sha256avx.h | 44 ++ .../sha256x8.c | 185 ++++++++ .../sha256x8.h | 64 +++ .../sha2_offsets.h | 27 ++ .../sha512x4.c | 446 ++++++++++++++++++ .../sha512x4.h | 58 +++ .../sign.c | 286 +++++++++++ .../thash.h | 13 + .../thash_sha2_robust.c | 68 +++ .../thash_sha2_robustx8.c | 268 +++++++++++ .../thashx8.h | 28 ++ .../utils.c | 148 ++++++ .../utils.h | 58 +++ .../utilsx8.c | 146 ++++++ .../utilsx8.h | 29 ++ .../wots.c | 291 ++++++++++++ .../wots.h | 25 + .../wotsx8.h | 42 ++ .../LICENSE | 116 +++++ .../address.c | 91 ++++ .../address.h | 52 ++ .../api.h | 77 +++ .../context.h | 28 ++ .../context_sha2.c | 36 ++ .../fors.c | 156 ++++++ .../fors.h | 32 ++ .../hash.h | 37 ++ .../hash_sha2.c | 219 +++++++++ .../merkle.c | 59 +++ .../merkle.h | 21 + .../nistapi.h | 87 ++++ .../params.h | 61 +++ .../sha2_offsets.h | 27 ++ .../sign.c | 286 +++++++++++ .../thash.h | 13 + .../thash_sha2_robust.c | 68 +++ .../utils.c | 148 ++++++ .../utils.h | 58 +++ .../utilsx1.c | 100 ++++ .../utilsx1.h | 27 ++ .../wots.c | 108 +++++ .../wots.h | 25 + .../wotsx1.c | 76 +++ .../wotsx1.h | 39 ++ .../LICENSE | 116 +++++ .../address.c | 91 ++++ .../address.h | 52 ++ .../api.h | 77 +++ .../context.h | 29 ++ .../context_sha2.c | 56 +++ .../fors.c | 226 +++++++++ .../fors.h | 32 ++ .../hash.h | 37 ++ .../hash_sha2.c | 219 +++++++++ .../hash_sha2x8.c | 75 +++ .../hashx8.h | 20 + .../merkle.c | 65 +++ .../merkle.h | 21 + .../nistapi.h | 87 ++++ .../params.h | 61 +++ .../sha256avx.c | 357 ++++++++++++++ .../sha256avx.h | 44 ++ .../sha256x8.c | 185 ++++++++ .../sha256x8.h | 64 +++ .../sha2_offsets.h | 27 ++ .../sha512x4.c | 446 ++++++++++++++++++ .../sha512x4.h | 58 +++ .../sign.c | 286 +++++++++++ .../thash.h | 13 + .../thash_sha2_simple.c | 53 +++ .../thash_sha2_simplex8.c | 212 +++++++++ .../thashx8.h | 28 ++ .../utils.c | 148 ++++++ .../utils.h | 58 +++ .../utilsx8.c | 146 ++++++ .../utilsx8.h | 29 ++ .../wots.c | 291 ++++++++++++ .../wots.h | 25 + .../wotsx8.h | 42 ++ .../LICENSE | 116 +++++ .../address.c | 91 ++++ .../address.h | 52 ++ .../api.h | 77 +++ .../context.h | 28 ++ .../context_sha2.c | 36 ++ .../fors.c | 156 ++++++ .../fors.h | 32 ++ .../hash.h | 37 ++ .../hash_sha2.c | 219 +++++++++ .../merkle.c | 59 +++ .../merkle.h | 21 + .../nistapi.h | 87 ++++ .../params.h | 61 +++ .../sha2_offsets.h | 27 ++ .../sign.c | 286 +++++++++++ .../thash.h | 13 + .../thash_sha2_simple.c | 53 +++ .../utils.c | 148 ++++++ .../utils.h | 58 +++ .../utilsx1.c | 100 ++++ .../utilsx1.h | 27 ++ .../wots.c | 108 +++++ .../wots.h | 25 + .../wotsx1.c | 76 +++ .../wotsx1.h | 39 ++ .../LICENSE | 116 +++++ .../address.c | 95 ++++ .../address.h | 52 ++ .../api.h | 77 +++ .../context.h | 29 ++ .../context_sha2.c | 56 +++ .../fors.c | 226 +++++++++ .../fors.h | 32 ++ .../hash.h | 37 ++ .../hash_sha2.c | 219 +++++++++ .../hash_sha2x8.c | 75 +++ .../hashx8.h | 20 + .../merkle.c | 65 +++ .../merkle.h | 21 + .../nistapi.h | 87 ++++ .../params.h | 61 +++ .../sha256avx.c | 357 ++++++++++++++ .../sha256avx.h | 44 ++ .../sha256x8.c | 185 ++++++++ .../sha256x8.h | 64 +++ .../sha2_offsets.h | 27 ++ .../sha512x4.c | 446 ++++++++++++++++++ .../sha512x4.h | 58 +++ .../sign.c | 286 +++++++++++ .../thash.h | 13 + .../thash_sha2_robust.c | 68 +++ .../thash_sha2_robustx8.c | 268 +++++++++++ .../thashx8.h | 28 ++ .../utils.c | 148 ++++++ .../utils.h | 58 +++ .../utilsx8.c | 146 ++++++ .../utilsx8.h | 29 ++ .../wots.c | 291 ++++++++++++ .../wots.h | 25 + .../wotsx8.h | 42 ++ .../LICENSE | 116 +++++ .../address.c | 95 ++++ .../address.h | 52 ++ .../api.h | 77 +++ .../context.h | 28 ++ .../context_sha2.c | 36 ++ .../fors.c | 156 ++++++ .../fors.h | 32 ++ .../hash.h | 37 ++ .../hash_sha2.c | 219 +++++++++ .../merkle.c | 59 +++ .../merkle.h | 21 + .../nistapi.h | 87 ++++ .../params.h | 61 +++ .../sha2_offsets.h | 27 ++ .../sign.c | 286 +++++++++++ .../thash.h | 13 + .../thash_sha2_robust.c | 68 +++ .../utils.c | 148 ++++++ .../utils.h | 58 +++ .../utilsx1.c | 100 ++++ .../utilsx1.h | 27 ++ .../wots.c | 108 +++++ .../wots.h | 25 + .../wotsx1.c | 76 +++ .../wotsx1.h | 39 ++ .../LICENSE | 116 +++++ .../address.c | 95 ++++ .../address.h | 52 ++ .../api.h | 77 +++ .../context.h | 29 ++ .../context_sha2.c | 56 +++ .../fors.c | 226 +++++++++ .../fors.h | 32 ++ .../hash.h | 37 ++ .../hash_sha2.c | 219 +++++++++ .../hash_sha2x8.c | 75 +++ .../hashx8.h | 20 + .../merkle.c | 65 +++ .../merkle.h | 21 + .../nistapi.h | 87 ++++ .../params.h | 61 +++ .../sha256avx.c | 357 ++++++++++++++ .../sha256avx.h | 44 ++ .../sha256x8.c | 185 ++++++++ .../sha256x8.h | 64 +++ .../sha2_offsets.h | 27 ++ .../sha512x4.c | 446 ++++++++++++++++++ .../sha512x4.h | 58 +++ .../sign.c | 286 +++++++++++ .../thash.h | 13 + .../thash_sha2_simple.c | 53 +++ .../thash_sha2_simplex8.c | 212 +++++++++ .../thashx8.h | 28 ++ .../utils.c | 148 ++++++ .../utils.h | 58 +++ .../utilsx8.c | 146 ++++++ .../utilsx8.h | 29 ++ .../wots.c | 291 ++++++++++++ .../wots.h | 25 + .../wotsx8.h | 42 ++ .../LICENSE | 116 +++++ .../address.c | 95 ++++ .../address.h | 52 ++ .../api.h | 77 +++ .../context.h | 28 ++ .../context_sha2.c | 36 ++ .../fors.c | 156 ++++++ .../fors.h | 32 ++ .../hash.h | 37 ++ .../hash_sha2.c | 219 +++++++++ .../merkle.c | 59 +++ .../merkle.h | 21 + .../nistapi.h | 87 ++++ .../params.h | 61 +++ .../sha2_offsets.h | 27 ++ .../sign.c | 286 +++++++++++ .../thash.h | 13 + .../thash_sha2_simple.c | 53 +++ .../utils.c | 148 ++++++ .../utils.h | 58 +++ .../utilsx1.c | 100 ++++ .../utilsx1.h | 27 ++ .../wots.c | 108 +++++ .../wots.h | 25 + .../wotsx1.c | 76 +++ .../wotsx1.h | 39 ++ .../LICENSE | 116 +++++ .../address.c | 91 ++++ .../address.h | 52 ++ .../api.h | 77 +++ .../context.h | 29 ++ .../context_sha2.c | 56 +++ .../fors.c | 226 +++++++++ .../fors.h | 32 ++ .../hash.h | 37 ++ .../hash_sha2.c | 219 +++++++++ .../hash_sha2x8.c | 75 +++ .../hashx8.h | 20 + .../merkle.c | 65 +++ .../merkle.h | 21 + .../nistapi.h | 87 ++++ .../params.h | 61 +++ .../sha256avx.c | 357 ++++++++++++++ .../sha256avx.h | 44 ++ .../sha256x8.c | 185 ++++++++ .../sha256x8.h | 64 +++ .../sha2_offsets.h | 27 ++ .../sha512x4.c | 446 ++++++++++++++++++ .../sha512x4.h | 58 +++ .../sign.c | 286 +++++++++++ .../thash.h | 13 + .../thash_sha2_robust.c | 68 +++ .../thash_sha2_robustx8.c | 268 +++++++++++ .../thashx8.h | 28 ++ .../utils.c | 148 ++++++ .../utils.h | 58 +++ .../utilsx8.c | 146 ++++++ .../utilsx8.h | 29 ++ .../wots.c | 291 ++++++++++++ .../wots.h | 25 + .../wotsx8.h | 42 ++ .../LICENSE | 116 +++++ .../address.c | 91 ++++ .../address.h | 52 ++ .../api.h | 77 +++ .../context.h | 28 ++ .../context_sha2.c | 36 ++ .../fors.c | 156 ++++++ .../fors.h | 32 ++ .../hash.h | 37 ++ .../hash_sha2.c | 219 +++++++++ .../merkle.c | 59 +++ .../merkle.h | 21 + .../nistapi.h | 87 ++++ .../params.h | 61 +++ .../sha2_offsets.h | 27 ++ .../sign.c | 286 +++++++++++ .../thash.h | 13 + .../thash_sha2_robust.c | 68 +++ .../utils.c | 148 ++++++ .../utils.h | 58 +++ .../utilsx1.c | 100 ++++ .../utilsx1.h | 27 ++ .../wots.c | 108 +++++ .../wots.h | 25 + .../wotsx1.c | 76 +++ .../wotsx1.h | 39 ++ .../LICENSE | 116 +++++ .../address.c | 91 ++++ .../address.h | 52 ++ .../api.h | 77 +++ .../context.h | 29 ++ .../context_sha2.c | 56 +++ .../fors.c | 226 +++++++++ .../fors.h | 32 ++ .../hash.h | 37 ++ .../hash_sha2.c | 219 +++++++++ .../hash_sha2x8.c | 75 +++ .../hashx8.h | 20 + .../merkle.c | 65 +++ .../merkle.h | 21 + .../nistapi.h | 87 ++++ .../params.h | 61 +++ .../sha256avx.c | 357 ++++++++++++++ .../sha256avx.h | 44 ++ .../sha256x8.c | 185 ++++++++ .../sha256x8.h | 64 +++ .../sha2_offsets.h | 27 ++ .../sha512x4.c | 446 ++++++++++++++++++ .../sha512x4.h | 58 +++ .../sign.c | 286 +++++++++++ .../thash.h | 13 + .../thash_sha2_simple.c | 53 +++ .../thash_sha2_simplex8.c | 212 +++++++++ .../thashx8.h | 28 ++ .../utils.c | 148 ++++++ .../utils.h | 58 +++ .../utilsx8.c | 146 ++++++ .../utilsx8.h | 29 ++ .../wots.c | 291 ++++++++++++ .../wots.h | 25 + .../wotsx8.h | 42 ++ .../LICENSE | 116 +++++ .../address.c | 91 ++++ .../address.h | 52 ++ .../api.h | 77 +++ .../context.h | 28 ++ .../context_sha2.c | 36 ++ .../fors.c | 156 ++++++ .../fors.h | 32 ++ .../hash.h | 37 ++ .../hash_sha2.c | 219 +++++++++ .../merkle.c | 59 +++ .../merkle.h | 21 + .../nistapi.h | 87 ++++ .../params.h | 61 +++ .../sha2_offsets.h | 27 ++ .../sign.c | 286 +++++++++++ .../thash.h | 13 + .../thash_sha2_simple.c | 53 +++ .../utils.c | 148 ++++++ .../utils.h | 58 +++ .../utilsx1.c | 100 ++++ .../utilsx1.h | 27 ++ .../wots.c | 108 +++++ .../wots.h | 25 + .../wotsx1.c | 76 +++ .../wotsx1.h | 39 ++ .../LICENSE | 116 +++++ .../address.c | 91 ++++ .../address.h | 52 ++ .../api.h | 77 +++ .../context.h | 29 ++ .../context_sha2.c | 56 +++ .../fors.c | 226 +++++++++ .../fors.h | 32 ++ .../hash.h | 37 ++ .../hash_sha2.c | 219 +++++++++ .../hash_sha2x8.c | 75 +++ .../hashx8.h | 20 + .../merkle.c | 65 +++ .../merkle.h | 21 + .../nistapi.h | 87 ++++ .../params.h | 61 +++ .../sha256avx.c | 357 ++++++++++++++ .../sha256avx.h | 44 ++ .../sha256x8.c | 185 ++++++++ .../sha256x8.h | 64 +++ .../sha2_offsets.h | 27 ++ .../sha512x4.c | 446 ++++++++++++++++++ .../sha512x4.h | 58 +++ .../sign.c | 286 +++++++++++ .../thash.h | 13 + .../thash_sha2_robust.c | 68 +++ .../thash_sha2_robustx8.c | 268 +++++++++++ .../thashx8.h | 28 ++ .../utils.c | 148 ++++++ .../utils.h | 58 +++ .../utilsx8.c | 146 ++++++ .../utilsx8.h | 29 ++ .../wots.c | 291 ++++++++++++ .../wots.h | 25 + .../wotsx8.h | 42 ++ .../LICENSE | 116 +++++ .../address.c | 91 ++++ .../address.h | 52 ++ .../api.h | 77 +++ .../context.h | 28 ++ .../context_sha2.c | 36 ++ .../fors.c | 156 ++++++ .../fors.h | 32 ++ .../hash.h | 37 ++ .../hash_sha2.c | 219 +++++++++ .../merkle.c | 59 +++ .../merkle.h | 21 + .../nistapi.h | 87 ++++ .../params.h | 61 +++ .../sha2_offsets.h | 27 ++ .../sign.c | 286 +++++++++++ .../thash.h | 13 + .../thash_sha2_robust.c | 68 +++ .../utils.c | 148 ++++++ .../utils.h | 58 +++ .../utilsx1.c | 100 ++++ .../utilsx1.h | 27 ++ .../wots.c | 108 +++++ .../wots.h | 25 + .../wotsx1.c | 76 +++ .../wotsx1.h | 39 ++ .../LICENSE | 116 +++++ .../address.c | 91 ++++ .../address.h | 52 ++ .../api.h | 77 +++ .../context.h | 29 ++ .../context_sha2.c | 56 +++ .../fors.c | 226 +++++++++ .../fors.h | 32 ++ .../hash.h | 37 ++ .../hash_sha2.c | 219 +++++++++ .../hash_sha2x8.c | 75 +++ .../hashx8.h | 20 + .../merkle.c | 65 +++ .../merkle.h | 21 + .../nistapi.h | 87 ++++ .../params.h | 61 +++ .../sha256avx.c | 357 ++++++++++++++ .../sha256avx.h | 44 ++ .../sha256x8.c | 185 ++++++++ .../sha256x8.h | 64 +++ .../sha2_offsets.h | 27 ++ .../sha512x4.c | 446 ++++++++++++++++++ .../sha512x4.h | 58 +++ .../sign.c | 286 +++++++++++ .../thash.h | 13 + .../thash_sha2_simple.c | 53 +++ .../thash_sha2_simplex8.c | 212 +++++++++ .../thashx8.h | 28 ++ .../utils.c | 148 ++++++ .../utils.h | 58 +++ .../utilsx8.c | 146 ++++++ .../utilsx8.h | 29 ++ .../wots.c | 291 ++++++++++++ .../wots.h | 25 + .../wotsx8.h | 42 ++ .../LICENSE | 116 +++++ .../address.c | 91 ++++ .../address.h | 52 ++ .../api.h | 77 +++ .../context.h | 28 ++ .../context_sha2.c | 36 ++ .../fors.c | 156 ++++++ .../fors.h | 32 ++ .../hash.h | 37 ++ .../hash_sha2.c | 219 +++++++++ .../merkle.c | 59 +++ .../merkle.h | 21 + .../nistapi.h | 87 ++++ .../params.h | 61 +++ .../sha2_offsets.h | 27 ++ .../sign.c | 286 +++++++++++ .../thash.h | 13 + .../thash_sha2_simple.c | 53 +++ .../utils.c | 148 ++++++ .../utils.h | 58 +++ .../utilsx1.c | 100 ++++ .../utilsx1.h | 27 ++ .../wots.c | 108 +++++ .../wots.h | 25 + .../wotsx1.c | 76 +++ .../wotsx1.h | 39 ++ .../LICENSE | 116 +++++ .../address.c | 91 ++++ .../address.h | 52 ++ .../api.h | 77 +++ .../context.h | 19 + .../context_shake.c | 12 + .../f1600x2.h | 11 + .../f1600x2.s | 143 ++++++ .../f1600x2_const.c | 30 ++ .../fips202x2.c | 148 ++++++ .../fips202x2.h | 24 + .../fors.c | 191 ++++++++ .../fors.h | 32 ++ .../hash.h | 28 ++ .../hash_shake.c | 83 ++++ .../hash_shakex2.c | 52 ++ .../hashx2.h | 14 + .../merkle.c | 64 +++ .../merkle.h | 21 + .../nistapi.h | 87 ++++ .../params.h | 56 +++ .../shake_offsets.h | 21 + .../sign.c | 286 +++++++++++ .../thash.h | 13 + .../thash_shake_robustx2.c | 112 +++++ .../thashx2.h | 16 + .../utils.c | 148 ++++++ .../utils.h | 58 +++ .../utilsx2.c | 130 +++++ .../utilsx2.h | 30 ++ .../wots.c | 259 ++++++++++ .../wots.h | 25 + .../wotsx2.h | 40 ++ .../LICENSE | 116 +++++ .../address.c | 91 ++++ .../address.h | 52 ++ .../api.h | 77 +++ .../context.h | 19 + .../context_shake.c | 12 + .../fips202x4.c | 210 +++++++++ .../fips202x4.h | 28 ++ .../fors.c | 202 ++++++++ .../fors.h | 32 ++ .../hash.h | 28 ++ .../hash_shake.c | 83 ++++ .../hash_shakex4.c | 64 +++ .../hashx4.h | 17 + .../merkle.c | 64 +++ .../merkle.h | 21 + .../nistapi.h | 87 ++++ .../params.h | 56 +++ .../shake_offsets.h | 21 + .../sign.c | 286 +++++++++++ .../thash.h | 13 + .../thash_shake_robust.c | 31 ++ .../thash_shake_robustx4.c | 131 +++++ .../thashx4.h | 20 + .../utils.c | 148 ++++++ .../utils.h | 58 +++ .../utilsx4.c | 138 ++++++ .../utilsx4.h | 30 ++ .../wots.c | 269 +++++++++++ .../wots.h | 25 + .../wotsx4.h | 41 ++ .../LICENSE | 116 +++++ .../address.c | 91 ++++ .../address.h | 52 ++ .../api.h | 77 +++ .../context.h | 22 + .../context_shake.c | 12 + .../fors.c | 156 ++++++ .../fors.h | 32 ++ .../hash.h | 28 ++ .../hash_shake.c | 83 ++++ .../merkle.c | 59 +++ .../merkle.h | 21 + .../nistapi.h | 87 ++++ .../params.h | 56 +++ .../shake_offsets.h | 21 + .../sign.c | 286 +++++++++++ .../thash.h | 13 + .../thash_shake_robust.c | 31 ++ .../utils.c | 148 ++++++ .../utils.h | 58 +++ .../utilsx1.c | 100 ++++ .../utilsx1.h | 27 ++ .../wots.c | 108 +++++ .../wots.h | 25 + .../wotsx1.c | 76 +++ .../wotsx1.h | 39 ++ .../LICENSE | 116 +++++ .../address.c | 91 ++++ .../address.h | 52 ++ .../api.h | 77 +++ .../context.h | 19 + .../context_shake.c | 12 + .../f1600x2.h | 11 + .../f1600x2.s | 143 ++++++ .../f1600x2_const.c | 30 ++ .../fips202x2.c | 148 ++++++ .../fips202x2.h | 24 + .../fors.c | 191 ++++++++ .../fors.h | 32 ++ .../hash.h | 28 ++ .../hash_shake.c | 83 ++++ .../hash_shakex2.c | 52 ++ .../hashx2.h | 14 + .../merkle.c | 64 +++ .../merkle.h | 21 + .../nistapi.h | 87 ++++ .../params.h | 56 +++ .../shake_offsets.h | 21 + .../sign.c | 286 +++++++++++ .../thash.h | 13 + .../thash_shake_simplex2.c | 83 ++++ .../thashx2.h | 16 + .../utils.c | 148 ++++++ .../utils.h | 58 +++ .../utilsx2.c | 130 +++++ .../utilsx2.h | 30 ++ .../wots.c | 259 ++++++++++ .../wots.h | 25 + .../wotsx2.h | 40 ++ .../LICENSE | 116 +++++ .../address.c | 91 ++++ .../address.h | 52 ++ .../api.h | 77 +++ .../context.h | 19 + .../context_shake.c | 12 + .../fips202x4.c | 210 +++++++++ .../fips202x4.h | 28 ++ .../fors.c | 202 ++++++++ .../fors.h | 32 ++ .../hash.h | 28 ++ .../hash_shake.c | 83 ++++ .../hash_shakex4.c | 64 +++ .../hashx4.h | 17 + .../merkle.c | 64 +++ .../merkle.h | 21 + .../nistapi.h | 87 ++++ .../params.h | 56 +++ .../shake_offsets.h | 21 + .../sign.c | 286 +++++++++++ .../thash.h | 13 + .../thash_shake_simple.c | 24 + .../thash_shake_simplex4.c | 98 ++++ .../thashx4.h | 20 + .../utils.c | 148 ++++++ .../utils.h | 58 +++ .../utilsx4.c | 138 ++++++ .../utilsx4.h | 30 ++ .../wots.c | 269 +++++++++++ .../wots.h | 25 + .../wotsx4.h | 41 ++ .../LICENSE | 116 +++++ .../address.c | 91 ++++ .../address.h | 52 ++ .../api.h | 77 +++ .../context.h | 22 + .../context_shake.c | 12 + .../fors.c | 156 ++++++ .../fors.h | 32 ++ .../hash.h | 28 ++ .../hash_shake.c | 83 ++++ .../merkle.c | 59 +++ .../merkle.h | 21 + .../nistapi.h | 87 ++++ .../params.h | 56 +++ .../shake_offsets.h | 21 + .../sign.c | 286 +++++++++++ .../thash.h | 13 + .../thash_shake_simple.c | 24 + .../utils.c | 148 ++++++ .../utils.h | 58 +++ .../utilsx1.c | 100 ++++ .../utilsx1.h | 27 ++ .../wots.c | 108 +++++ .../wots.h | 25 + .../wotsx1.c | 76 +++ .../wotsx1.h | 39 ++ .../LICENSE | 116 +++++ .../address.c | 95 ++++ .../address.h | 52 ++ .../api.h | 77 +++ .../context.h | 19 + .../context_shake.c | 12 + .../f1600x2.h | 11 + .../f1600x2.s | 143 ++++++ .../f1600x2_const.c | 30 ++ .../fips202x2.c | 148 ++++++ .../fips202x2.h | 24 + .../fors.c | 191 ++++++++ .../fors.h | 32 ++ .../hash.h | 28 ++ .../hash_shake.c | 83 ++++ .../hash_shakex2.c | 52 ++ .../hashx2.h | 14 + .../merkle.c | 64 +++ .../merkle.h | 21 + .../nistapi.h | 87 ++++ .../params.h | 56 +++ .../shake_offsets.h | 21 + .../sign.c | 286 +++++++++++ .../thash.h | 13 + .../thash_shake_robustx2.c | 112 +++++ .../thashx2.h | 16 + .../utils.c | 148 ++++++ .../utils.h | 58 +++ .../utilsx2.c | 130 +++++ .../utilsx2.h | 30 ++ .../wots.c | 259 ++++++++++ .../wots.h | 25 + .../wotsx2.h | 40 ++ .../LICENSE | 116 +++++ .../address.c | 95 ++++ .../address.h | 52 ++ .../api.h | 77 +++ .../context.h | 19 + .../context_shake.c | 12 + .../fips202x4.c | 210 +++++++++ .../fips202x4.h | 28 ++ .../fors.c | 202 ++++++++ .../fors.h | 32 ++ .../hash.h | 28 ++ .../hash_shake.c | 83 ++++ .../hash_shakex4.c | 64 +++ .../hashx4.h | 17 + .../merkle.c | 64 +++ .../merkle.h | 21 + .../nistapi.h | 87 ++++ .../params.h | 56 +++ .../shake_offsets.h | 21 + .../sign.c | 286 +++++++++++ .../thash.h | 13 + .../thash_shake_robust.c | 31 ++ .../thash_shake_robustx4.c | 131 +++++ .../thashx4.h | 20 + .../utils.c | 148 ++++++ .../utils.h | 58 +++ .../utilsx4.c | 138 ++++++ .../utilsx4.h | 30 ++ .../wots.c | 269 +++++++++++ .../wots.h | 25 + .../wotsx4.h | 41 ++ .../LICENSE | 116 +++++ .../address.c | 95 ++++ .../address.h | 52 ++ .../api.h | 77 +++ .../context.h | 22 + .../context_shake.c | 12 + .../fors.c | 156 ++++++ .../fors.h | 32 ++ .../hash.h | 28 ++ .../hash_shake.c | 83 ++++ .../merkle.c | 59 +++ .../merkle.h | 21 + .../nistapi.h | 87 ++++ .../params.h | 56 +++ .../shake_offsets.h | 21 + .../sign.c | 286 +++++++++++ .../thash.h | 13 + .../thash_shake_robust.c | 31 ++ .../utils.c | 148 ++++++ .../utils.h | 58 +++ .../utilsx1.c | 100 ++++ .../utilsx1.h | 27 ++ .../wots.c | 108 +++++ .../wots.h | 25 + .../wotsx1.c | 76 +++ .../wotsx1.h | 39 ++ .../LICENSE | 116 +++++ .../address.c | 95 ++++ .../address.h | 52 ++ .../api.h | 77 +++ .../context.h | 19 + .../context_shake.c | 12 + .../f1600x2.h | 11 + .../f1600x2.s | 143 ++++++ .../f1600x2_const.c | 30 ++ .../fips202x2.c | 148 ++++++ .../fips202x2.h | 24 + .../fors.c | 191 ++++++++ .../fors.h | 32 ++ .../hash.h | 28 ++ .../hash_shake.c | 83 ++++ .../hash_shakex2.c | 52 ++ .../hashx2.h | 14 + .../merkle.c | 64 +++ .../merkle.h | 21 + .../nistapi.h | 87 ++++ .../params.h | 56 +++ .../shake_offsets.h | 21 + .../sign.c | 286 +++++++++++ .../thash.h | 13 + .../thash_shake_simplex2.c | 83 ++++ .../thashx2.h | 16 + .../utils.c | 148 ++++++ .../utils.h | 58 +++ .../utilsx2.c | 130 +++++ .../utilsx2.h | 30 ++ .../wots.c | 259 ++++++++++ .../wots.h | 25 + .../wotsx2.h | 40 ++ .../LICENSE | 116 +++++ .../address.c | 95 ++++ .../address.h | 52 ++ .../api.h | 77 +++ .../context.h | 19 + .../context_shake.c | 12 + .../fips202x4.c | 210 +++++++++ .../fips202x4.h | 28 ++ .../fors.c | 202 ++++++++ .../fors.h | 32 ++ .../hash.h | 28 ++ .../hash_shake.c | 83 ++++ .../hash_shakex4.c | 64 +++ .../hashx4.h | 17 + .../merkle.c | 64 +++ .../merkle.h | 21 + .../nistapi.h | 87 ++++ .../params.h | 56 +++ .../shake_offsets.h | 21 + .../sign.c | 286 +++++++++++ .../thash.h | 13 + .../thash_shake_simple.c | 24 + .../thash_shake_simplex4.c | 98 ++++ .../thashx4.h | 20 + .../utils.c | 148 ++++++ .../utils.h | 58 +++ .../utilsx4.c | 138 ++++++ .../utilsx4.h | 30 ++ .../wots.c | 269 +++++++++++ .../wots.h | 25 + .../wotsx4.h | 41 ++ .../LICENSE | 116 +++++ .../address.c | 95 ++++ .../address.h | 52 ++ .../api.h | 77 +++ .../context.h | 22 + .../context_shake.c | 12 + .../fors.c | 156 ++++++ .../fors.h | 32 ++ .../hash.h | 28 ++ .../hash_shake.c | 83 ++++ .../merkle.c | 59 +++ .../merkle.h | 21 + .../nistapi.h | 87 ++++ .../params.h | 56 +++ .../shake_offsets.h | 21 + .../sign.c | 286 +++++++++++ .../thash.h | 13 + .../thash_shake_simple.c | 24 + .../utils.c | 148 ++++++ .../utils.h | 58 +++ .../utilsx1.c | 100 ++++ .../utilsx1.h | 27 ++ .../wots.c | 108 +++++ .../wots.h | 25 + .../wotsx1.c | 76 +++ .../wotsx1.h | 39 ++ .../LICENSE | 116 +++++ .../address.c | 91 ++++ .../address.h | 52 ++ .../api.h | 77 +++ .../context.h | 19 + .../context_shake.c | 12 + .../f1600x2.h | 11 + .../f1600x2.s | 143 ++++++ .../f1600x2_const.c | 30 ++ .../fips202x2.c | 148 ++++++ .../fips202x2.h | 24 + .../fors.c | 191 ++++++++ .../fors.h | 32 ++ .../hash.h | 28 ++ .../hash_shake.c | 83 ++++ .../hash_shakex2.c | 52 ++ .../hashx2.h | 14 + .../merkle.c | 64 +++ .../merkle.h | 21 + .../nistapi.h | 87 ++++ .../params.h | 56 +++ .../shake_offsets.h | 21 + .../sign.c | 286 +++++++++++ .../thash.h | 13 + .../thash_shake_robustx2.c | 112 +++++ .../thashx2.h | 16 + .../utils.c | 148 ++++++ .../utils.h | 58 +++ .../utilsx2.c | 130 +++++ .../utilsx2.h | 30 ++ .../wots.c | 259 ++++++++++ .../wots.h | 25 + .../wotsx2.h | 40 ++ .../LICENSE | 116 +++++ .../address.c | 91 ++++ .../address.h | 52 ++ .../api.h | 77 +++ .../context.h | 19 + .../context_shake.c | 12 + .../fips202x4.c | 210 +++++++++ .../fips202x4.h | 28 ++ .../fors.c | 202 ++++++++ .../fors.h | 32 ++ .../hash.h | 28 ++ .../hash_shake.c | 83 ++++ .../hash_shakex4.c | 64 +++ .../hashx4.h | 17 + .../merkle.c | 64 +++ .../merkle.h | 21 + .../nistapi.h | 87 ++++ .../params.h | 56 +++ .../shake_offsets.h | 21 + .../sign.c | 286 +++++++++++ .../thash.h | 13 + .../thash_shake_robust.c | 31 ++ .../thash_shake_robustx4.c | 131 +++++ .../thashx4.h | 20 + .../utils.c | 148 ++++++ .../utils.h | 58 +++ .../utilsx4.c | 138 ++++++ .../utilsx4.h | 30 ++ .../wots.c | 269 +++++++++++ .../wots.h | 25 + .../wotsx4.h | 41 ++ .../LICENSE | 116 +++++ .../address.c | 91 ++++ .../address.h | 52 ++ .../api.h | 77 +++ .../context.h | 22 + .../context_shake.c | 12 + .../fors.c | 156 ++++++ .../fors.h | 32 ++ .../hash.h | 28 ++ .../hash_shake.c | 83 ++++ .../merkle.c | 59 +++ .../merkle.h | 21 + .../nistapi.h | 87 ++++ .../params.h | 56 +++ .../shake_offsets.h | 21 + .../sign.c | 286 +++++++++++ .../thash.h | 13 + .../thash_shake_robust.c | 31 ++ .../utils.c | 148 ++++++ .../utils.h | 58 +++ .../utilsx1.c | 100 ++++ .../utilsx1.h | 27 ++ .../wots.c | 108 +++++ .../wots.h | 25 + .../wotsx1.c | 76 +++ .../wotsx1.h | 39 ++ .../LICENSE | 116 +++++ .../address.c | 91 ++++ .../address.h | 52 ++ .../api.h | 77 +++ .../context.h | 19 + .../context_shake.c | 12 + .../f1600x2.h | 11 + .../f1600x2.s | 143 ++++++ .../f1600x2_const.c | 30 ++ .../fips202x2.c | 148 ++++++ .../fips202x2.h | 24 + .../fors.c | 191 ++++++++ .../fors.h | 32 ++ .../hash.h | 28 ++ .../hash_shake.c | 83 ++++ .../hash_shakex2.c | 52 ++ .../hashx2.h | 14 + .../merkle.c | 64 +++ .../merkle.h | 21 + .../nistapi.h | 87 ++++ .../params.h | 56 +++ .../shake_offsets.h | 21 + .../sign.c | 286 +++++++++++ .../thash.h | 13 + .../thash_shake_simplex2.c | 83 ++++ .../thashx2.h | 16 + .../utils.c | 148 ++++++ .../utils.h | 58 +++ .../utilsx2.c | 130 +++++ .../utilsx2.h | 30 ++ .../wots.c | 259 ++++++++++ .../wots.h | 25 + .../wotsx2.h | 40 ++ .../LICENSE | 116 +++++ .../address.c | 91 ++++ .../address.h | 52 ++ .../api.h | 77 +++ .../context.h | 19 + .../context_shake.c | 12 + .../fips202x4.c | 210 +++++++++ .../fips202x4.h | 28 ++ .../fors.c | 202 ++++++++ .../fors.h | 32 ++ .../hash.h | 28 ++ .../hash_shake.c | 83 ++++ .../hash_shakex4.c | 64 +++ .../hashx4.h | 17 + .../merkle.c | 64 +++ .../merkle.h | 21 + .../nistapi.h | 87 ++++ .../params.h | 56 +++ .../shake_offsets.h | 21 + .../sign.c | 286 +++++++++++ .../thash.h | 13 + .../thash_shake_simple.c | 24 + .../thash_shake_simplex4.c | 98 ++++ .../thashx4.h | 20 + .../utils.c | 148 ++++++ .../utils.h | 58 +++ .../utilsx4.c | 138 ++++++ .../utilsx4.h | 30 ++ .../wots.c | 269 +++++++++++ .../wots.h | 25 + .../wotsx4.h | 41 ++ .../LICENSE | 116 +++++ .../address.c | 91 ++++ .../address.h | 52 ++ .../api.h | 77 +++ .../context.h | 22 + .../context_shake.c | 12 + .../fors.c | 156 ++++++ .../fors.h | 32 ++ .../hash.h | 28 ++ .../hash_shake.c | 83 ++++ .../merkle.c | 59 +++ .../merkle.h | 21 + .../nistapi.h | 87 ++++ .../params.h | 56 +++ .../shake_offsets.h | 21 + .../sign.c | 286 +++++++++++ .../thash.h | 13 + .../thash_shake_simple.c | 24 + .../utils.c | 148 ++++++ .../utils.h | 58 +++ .../utilsx1.c | 100 ++++ .../utilsx1.h | 27 ++ .../wots.c | 108 +++++ .../wots.h | 25 + .../wotsx1.c | 76 +++ .../wotsx1.h | 39 ++ .../LICENSE | 116 +++++ .../address.c | 95 ++++ .../address.h | 52 ++ .../api.h | 77 +++ .../context.h | 19 + .../context_shake.c | 12 + .../f1600x2.h | 11 + .../f1600x2.s | 143 ++++++ .../f1600x2_const.c | 30 ++ .../fips202x2.c | 148 ++++++ .../fips202x2.h | 24 + .../fors.c | 191 ++++++++ .../fors.h | 32 ++ .../hash.h | 28 ++ .../hash_shake.c | 83 ++++ .../hash_shakex2.c | 52 ++ .../hashx2.h | 14 + .../merkle.c | 64 +++ .../merkle.h | 21 + .../nistapi.h | 87 ++++ .../params.h | 56 +++ .../shake_offsets.h | 21 + .../sign.c | 286 +++++++++++ .../thash.h | 13 + .../thash_shake_robustx2.c | 112 +++++ .../thashx2.h | 16 + .../utils.c | 148 ++++++ .../utils.h | 58 +++ .../utilsx2.c | 130 +++++ .../utilsx2.h | 30 ++ .../wots.c | 259 ++++++++++ .../wots.h | 25 + .../wotsx2.h | 40 ++ .../LICENSE | 116 +++++ .../address.c | 95 ++++ .../address.h | 52 ++ .../api.h | 77 +++ .../context.h | 19 + .../context_shake.c | 12 + .../fips202x4.c | 210 +++++++++ .../fips202x4.h | 28 ++ .../fors.c | 202 ++++++++ .../fors.h | 32 ++ .../hash.h | 28 ++ .../hash_shake.c | 83 ++++ .../hash_shakex4.c | 64 +++ .../hashx4.h | 17 + .../merkle.c | 64 +++ .../merkle.h | 21 + .../nistapi.h | 87 ++++ .../params.h | 56 +++ .../shake_offsets.h | 21 + .../sign.c | 286 +++++++++++ .../thash.h | 13 + .../thash_shake_robust.c | 31 ++ .../thash_shake_robustx4.c | 131 +++++ .../thashx4.h | 20 + .../utils.c | 148 ++++++ .../utils.h | 58 +++ .../utilsx4.c | 138 ++++++ .../utilsx4.h | 30 ++ .../wots.c | 269 +++++++++++ .../wots.h | 25 + .../wotsx4.h | 41 ++ .../LICENSE | 116 +++++ .../address.c | 95 ++++ .../address.h | 52 ++ .../api.h | 77 +++ .../context.h | 22 + .../context_shake.c | 12 + .../fors.c | 156 ++++++ .../fors.h | 32 ++ .../hash.h | 28 ++ .../hash_shake.c | 83 ++++ .../merkle.c | 59 +++ .../merkle.h | 21 + .../nistapi.h | 87 ++++ .../params.h | 56 +++ .../shake_offsets.h | 21 + .../sign.c | 286 +++++++++++ .../thash.h | 13 + .../thash_shake_robust.c | 31 ++ .../utils.c | 148 ++++++ .../utils.h | 58 +++ .../utilsx1.c | 100 ++++ .../utilsx1.h | 27 ++ .../wots.c | 108 +++++ .../wots.h | 25 + .../wotsx1.c | 76 +++ .../wotsx1.h | 39 ++ .../LICENSE | 116 +++++ .../address.c | 95 ++++ .../address.h | 52 ++ .../api.h | 77 +++ .../context.h | 19 + .../context_shake.c | 12 + .../f1600x2.h | 11 + .../f1600x2.s | 143 ++++++ .../f1600x2_const.c | 30 ++ .../fips202x2.c | 148 ++++++ .../fips202x2.h | 24 + .../fors.c | 191 ++++++++ .../fors.h | 32 ++ .../hash.h | 28 ++ .../hash_shake.c | 83 ++++ .../hash_shakex2.c | 52 ++ .../hashx2.h | 14 + .../merkle.c | 64 +++ .../merkle.h | 21 + .../nistapi.h | 87 ++++ .../params.h | 56 +++ .../shake_offsets.h | 21 + .../sign.c | 286 +++++++++++ .../thash.h | 13 + .../thash_shake_simplex2.c | 83 ++++ .../thashx2.h | 16 + .../utils.c | 148 ++++++ .../utils.h | 58 +++ .../utilsx2.c | 130 +++++ .../utilsx2.h | 30 ++ .../wots.c | 259 ++++++++++ .../wots.h | 25 + .../wotsx2.h | 40 ++ .../LICENSE | 116 +++++ .../address.c | 95 ++++ .../address.h | 52 ++ .../api.h | 77 +++ .../context.h | 19 + .../context_shake.c | 12 + .../fips202x4.c | 210 +++++++++ .../fips202x4.h | 28 ++ .../fors.c | 202 ++++++++ .../fors.h | 32 ++ .../hash.h | 28 ++ .../hash_shake.c | 83 ++++ .../hash_shakex4.c | 64 +++ .../hashx4.h | 17 + .../merkle.c | 64 +++ .../merkle.h | 21 + .../nistapi.h | 87 ++++ .../params.h | 56 +++ .../shake_offsets.h | 21 + .../sign.c | 286 +++++++++++ .../thash.h | 13 + .../thash_shake_simple.c | 24 + .../thash_shake_simplex4.c | 98 ++++ .../thashx4.h | 20 + .../utils.c | 148 ++++++ .../utils.h | 58 +++ .../utilsx4.c | 138 ++++++ .../utilsx4.h | 30 ++ .../wots.c | 269 +++++++++++ .../wots.h | 25 + .../wotsx4.h | 41 ++ .../LICENSE | 116 +++++ .../address.c | 95 ++++ .../address.h | 52 ++ .../api.h | 77 +++ .../context.h | 22 + .../context_shake.c | 12 + .../fors.c | 156 ++++++ .../fors.h | 32 ++ .../hash.h | 28 ++ .../hash_shake.c | 83 ++++ .../merkle.c | 59 +++ .../merkle.h | 21 + .../nistapi.h | 87 ++++ .../params.h | 56 +++ .../shake_offsets.h | 21 + .../sign.c | 286 +++++++++++ .../thash.h | 13 + .../thash_shake_simple.c | 24 + .../utils.c | 148 ++++++ .../utils.h | 58 +++ .../utilsx1.c | 100 ++++ .../utilsx1.h | 27 ++ .../wots.c | 108 +++++ .../wots.h | 25 + .../wotsx1.c | 76 +++ .../wotsx1.h | 39 ++ .../LICENSE | 116 +++++ .../address.c | 91 ++++ .../address.h | 52 ++ .../api.h | 77 +++ .../context.h | 19 + .../context_shake.c | 12 + .../f1600x2.h | 11 + .../f1600x2.s | 143 ++++++ .../f1600x2_const.c | 30 ++ .../fips202x2.c | 148 ++++++ .../fips202x2.h | 24 + .../fors.c | 191 ++++++++ .../fors.h | 32 ++ .../hash.h | 28 ++ .../hash_shake.c | 83 ++++ .../hash_shakex2.c | 52 ++ .../hashx2.h | 14 + .../merkle.c | 64 +++ .../merkle.h | 21 + .../nistapi.h | 87 ++++ .../params.h | 56 +++ .../shake_offsets.h | 21 + .../sign.c | 286 +++++++++++ .../thash.h | 13 + .../thash_shake_robustx2.c | 112 +++++ .../thashx2.h | 16 + .../utils.c | 148 ++++++ .../utils.h | 58 +++ .../utilsx2.c | 130 +++++ .../utilsx2.h | 30 ++ .../wots.c | 259 ++++++++++ .../wots.h | 25 + .../wotsx2.h | 40 ++ .../LICENSE | 116 +++++ .../address.c | 91 ++++ .../address.h | 52 ++ .../api.h | 77 +++ .../context.h | 19 + .../context_shake.c | 12 + .../fips202x4.c | 210 +++++++++ .../fips202x4.h | 28 ++ .../fors.c | 202 ++++++++ .../fors.h | 32 ++ .../hash.h | 28 ++ .../hash_shake.c | 83 ++++ .../hash_shakex4.c | 64 +++ .../hashx4.h | 17 + .../merkle.c | 64 +++ .../merkle.h | 21 + .../nistapi.h | 87 ++++ .../params.h | 56 +++ .../shake_offsets.h | 21 + .../sign.c | 286 +++++++++++ .../thash.h | 13 + .../thash_shake_robust.c | 31 ++ .../thash_shake_robustx4.c | 131 +++++ .../thashx4.h | 20 + .../utils.c | 148 ++++++ .../utils.h | 58 +++ .../utilsx4.c | 138 ++++++ .../utilsx4.h | 30 ++ .../wots.c | 269 +++++++++++ .../wots.h | 25 + .../wotsx4.h | 41 ++ .../LICENSE | 116 +++++ .../address.c | 91 ++++ .../address.h | 52 ++ .../api.h | 77 +++ .../context.h | 22 + .../context_shake.c | 12 + .../fors.c | 156 ++++++ .../fors.h | 32 ++ .../hash.h | 28 ++ .../hash_shake.c | 83 ++++ .../merkle.c | 59 +++ .../merkle.h | 21 + .../nistapi.h | 87 ++++ .../params.h | 56 +++ .../shake_offsets.h | 21 + .../sign.c | 286 +++++++++++ .../thash.h | 13 + .../thash_shake_robust.c | 31 ++ .../utils.c | 148 ++++++ .../utils.h | 58 +++ .../utilsx1.c | 100 ++++ .../utilsx1.h | 27 ++ .../wots.c | 108 +++++ .../wots.h | 25 + .../wotsx1.c | 76 +++ .../wotsx1.h | 39 ++ .../LICENSE | 116 +++++ .../address.c | 91 ++++ .../address.h | 52 ++ .../api.h | 77 +++ .../context.h | 19 + .../context_shake.c | 12 + .../f1600x2.h | 11 + .../f1600x2.s | 143 ++++++ .../f1600x2_const.c | 30 ++ .../fips202x2.c | 148 ++++++ .../fips202x2.h | 24 + .../fors.c | 191 ++++++++ .../fors.h | 32 ++ .../hash.h | 28 ++ .../hash_shake.c | 83 ++++ .../hash_shakex2.c | 52 ++ .../hashx2.h | 14 + .../merkle.c | 64 +++ .../merkle.h | 21 + .../nistapi.h | 87 ++++ .../params.h | 56 +++ .../shake_offsets.h | 21 + .../sign.c | 286 +++++++++++ .../thash.h | 13 + .../thash_shake_simplex2.c | 83 ++++ .../thashx2.h | 16 + .../utils.c | 148 ++++++ .../utils.h | 58 +++ .../utilsx2.c | 130 +++++ .../utilsx2.h | 30 ++ .../wots.c | 259 ++++++++++ .../wots.h | 25 + .../wotsx2.h | 40 ++ .../LICENSE | 116 +++++ .../address.c | 91 ++++ .../address.h | 52 ++ .../api.h | 77 +++ .../context.h | 19 + .../context_shake.c | 12 + .../fips202x4.c | 210 +++++++++ .../fips202x4.h | 28 ++ .../fors.c | 202 ++++++++ .../fors.h | 32 ++ .../hash.h | 28 ++ .../hash_shake.c | 83 ++++ .../hash_shakex4.c | 64 +++ .../hashx4.h | 17 + .../merkle.c | 64 +++ .../merkle.h | 21 + .../nistapi.h | 87 ++++ .../params.h | 56 +++ .../shake_offsets.h | 21 + .../sign.c | 286 +++++++++++ .../thash.h | 13 + .../thash_shake_simple.c | 24 + .../thash_shake_simplex4.c | 98 ++++ .../thashx4.h | 20 + .../utils.c | 148 ++++++ .../utils.h | 58 +++ .../utilsx4.c | 138 ++++++ .../utilsx4.h | 30 ++ .../wots.c | 269 +++++++++++ .../wots.h | 25 + .../wotsx4.h | 41 ++ .../LICENSE | 116 +++++ .../address.c | 91 ++++ .../address.h | 52 ++ .../api.h | 77 +++ .../context.h | 22 + .../context_shake.c | 12 + .../fors.c | 156 ++++++ .../fors.h | 32 ++ .../hash.h | 28 ++ .../hash_shake.c | 83 ++++ .../merkle.c | 59 +++ .../merkle.h | 21 + .../nistapi.h | 87 ++++ .../params.h | 56 +++ .../shake_offsets.h | 21 + .../sign.c | 286 +++++++++++ .../thash.h | 13 + .../thash_shake_simple.c | 24 + .../utils.c | 148 ++++++ .../utils.h | 58 +++ .../utilsx1.c | 100 ++++ .../utilsx1.h | 27 ++ .../wots.c | 108 +++++ .../wots.h | 25 + .../wotsx1.c | 76 +++ .../wotsx1.h | 39 ++ .../LICENSE | 116 +++++ .../address.c | 91 ++++ .../address.h | 52 ++ .../api.h | 77 +++ .../context.h | 19 + .../context_shake.c | 12 + .../f1600x2.h | 11 + .../f1600x2.s | 143 ++++++ .../f1600x2_const.c | 30 ++ .../fips202x2.c | 148 ++++++ .../fips202x2.h | 24 + .../fors.c | 191 ++++++++ .../fors.h | 32 ++ .../hash.h | 28 ++ .../hash_shake.c | 83 ++++ .../hash_shakex2.c | 52 ++ .../hashx2.h | 14 + .../merkle.c | 64 +++ .../merkle.h | 21 + .../nistapi.h | 87 ++++ .../params.h | 56 +++ .../shake_offsets.h | 21 + .../sign.c | 286 +++++++++++ .../thash.h | 13 + .../thash_shake_robustx2.c | 112 +++++ .../thashx2.h | 16 + .../utils.c | 148 ++++++ .../utils.h | 58 +++ .../utilsx2.c | 130 +++++ .../utilsx2.h | 30 ++ .../wots.c | 259 ++++++++++ .../wots.h | 25 + .../wotsx2.h | 40 ++ .../LICENSE | 116 +++++ .../address.c | 91 ++++ .../address.h | 52 ++ .../api.h | 77 +++ .../context.h | 19 + .../context_shake.c | 12 + .../fips202x4.c | 210 +++++++++ .../fips202x4.h | 28 ++ .../fors.c | 202 ++++++++ .../fors.h | 32 ++ .../hash.h | 28 ++ .../hash_shake.c | 83 ++++ .../hash_shakex4.c | 64 +++ .../hashx4.h | 17 + .../merkle.c | 64 +++ .../merkle.h | 21 + .../nistapi.h | 87 ++++ .../params.h | 56 +++ .../shake_offsets.h | 21 + .../sign.c | 286 +++++++++++ .../thash.h | 13 + .../thash_shake_robust.c | 31 ++ .../thash_shake_robustx4.c | 131 +++++ .../thashx4.h | 20 + .../utils.c | 148 ++++++ .../utils.h | 58 +++ .../utilsx4.c | 138 ++++++ .../utilsx4.h | 30 ++ .../wots.c | 269 +++++++++++ .../wots.h | 25 + .../wotsx4.h | 41 ++ .../LICENSE | 116 +++++ .../address.c | 91 ++++ .../address.h | 52 ++ .../api.h | 77 +++ .../context.h | 22 + .../context_shake.c | 12 + .../fors.c | 156 ++++++ .../fors.h | 32 ++ .../hash.h | 28 ++ .../hash_shake.c | 83 ++++ .../merkle.c | 59 +++ .../merkle.h | 21 + .../nistapi.h | 87 ++++ .../params.h | 56 +++ .../shake_offsets.h | 21 + .../sign.c | 286 +++++++++++ .../thash.h | 13 + .../thash_shake_robust.c | 31 ++ .../utils.c | 148 ++++++ .../utils.h | 58 +++ .../utilsx1.c | 100 ++++ .../utilsx1.h | 27 ++ .../wots.c | 108 +++++ .../wots.h | 25 + .../wotsx1.c | 76 +++ .../wotsx1.h | 39 ++ .../LICENSE | 116 +++++ .../address.c | 91 ++++ .../address.h | 52 ++ .../api.h | 77 +++ .../context.h | 19 + .../context_shake.c | 12 + .../f1600x2.h | 11 + .../f1600x2.s | 143 ++++++ .../f1600x2_const.c | 30 ++ .../fips202x2.c | 148 ++++++ .../fips202x2.h | 24 + .../fors.c | 191 ++++++++ .../fors.h | 32 ++ .../hash.h | 28 ++ .../hash_shake.c | 83 ++++ .../hash_shakex2.c | 52 ++ .../hashx2.h | 14 + .../merkle.c | 64 +++ .../merkle.h | 21 + .../nistapi.h | 87 ++++ .../params.h | 56 +++ .../shake_offsets.h | 21 + .../sign.c | 286 +++++++++++ .../thash.h | 13 + .../thash_shake_simplex2.c | 83 ++++ .../thashx2.h | 16 + .../utils.c | 148 ++++++ .../utils.h | 58 +++ .../utilsx2.c | 130 +++++ .../utilsx2.h | 30 ++ .../wots.c | 259 ++++++++++ .../wots.h | 25 + .../wotsx2.h | 40 ++ .../LICENSE | 116 +++++ .../address.c | 91 ++++ .../address.h | 52 ++ .../api.h | 77 +++ .../context.h | 19 + .../context_shake.c | 12 + .../fips202x4.c | 210 +++++++++ .../fips202x4.h | 28 ++ .../fors.c | 202 ++++++++ .../fors.h | 32 ++ .../hash.h | 28 ++ .../hash_shake.c | 83 ++++ .../hash_shakex4.c | 64 +++ .../hashx4.h | 17 + .../merkle.c | 64 +++ .../merkle.h | 21 + .../nistapi.h | 87 ++++ .../params.h | 56 +++ .../shake_offsets.h | 21 + .../sign.c | 286 +++++++++++ .../thash.h | 13 + .../thash_shake_simple.c | 24 + .../thash_shake_simplex4.c | 98 ++++ .../thashx4.h | 20 + .../utils.c | 148 ++++++ .../utils.h | 58 +++ .../utilsx4.c | 138 ++++++ .../utilsx4.h | 30 ++ .../wots.c | 269 +++++++++++ .../wots.h | 25 + .../wotsx4.h | 41 ++ .../LICENSE | 116 +++++ .../address.c | 91 ++++ .../address.h | 52 ++ .../api.h | 77 +++ .../context.h | 22 + .../context_shake.c | 12 + .../fors.c | 156 ++++++ .../fors.h | 32 ++ .../hash.h | 28 ++ .../hash_shake.c | 83 ++++ .../merkle.c | 59 +++ .../merkle.h | 21 + .../nistapi.h | 87 ++++ .../params.h | 56 +++ .../shake_offsets.h | 21 + .../sign.c | 286 +++++++++++ .../thash.h | 13 + .../thash_shake_simple.c | 24 + .../utils.c | 148 ++++++ .../utils.h | 58 +++ .../utilsx1.c | 100 ++++ .../utilsx1.h | 27 ++ .../wots.c | 108 +++++ .../wots.h | 25 + .../wotsx1.c | 76 +++ .../wotsx1.h | 39 ++ .../sphincs/sig_sphincs_haraka_128f_robust.c | 2 +- .../sphincs/sig_sphincs_haraka_128f_simple.c | 2 +- .../sphincs/sig_sphincs_haraka_128s_robust.c | 2 +- .../sphincs/sig_sphincs_haraka_128s_simple.c | 2 +- .../sphincs/sig_sphincs_haraka_192f_robust.c | 4 +- .../sphincs/sig_sphincs_haraka_192f_simple.c | 4 +- .../sphincs/sig_sphincs_haraka_192s_robust.c | 4 +- .../sphincs/sig_sphincs_haraka_192s_simple.c | 4 +- .../sphincs/sig_sphincs_haraka_256f_robust.c | 4 +- .../sphincs/sig_sphincs_haraka_256f_simple.c | 4 +- .../sphincs/sig_sphincs_haraka_256s_robust.c | 4 +- .../sphincs/sig_sphincs_haraka_256s_simple.c | 4 +- .../sphincs/sig_sphincs_sha256_128f_robust.c | 32 +- .../sphincs/sig_sphincs_sha256_128f_simple.c | 32 +- .../sphincs/sig_sphincs_sha256_128s_robust.c | 32 +- .../sphincs/sig_sphincs_sha256_128s_simple.c | 32 +- .../sphincs/sig_sphincs_sha256_192f_robust.c | 32 +- .../sphincs/sig_sphincs_sha256_192f_simple.c | 32 +- .../sphincs/sig_sphincs_sha256_192s_robust.c | 32 +- .../sphincs/sig_sphincs_sha256_192s_simple.c | 32 +- .../sphincs/sig_sphincs_sha256_256f_robust.c | 32 +- .../sphincs/sig_sphincs_sha256_256f_simple.c | 32 +- .../sphincs/sig_sphincs_sha256_256s_robust.c | 32 +- .../sphincs/sig_sphincs_sha256_256s_simple.c | 32 +- .../sig_sphincs_shake256_128f_robust.c | 68 ++- .../sig_sphincs_shake256_128f_simple.c | 68 ++- .../sig_sphincs_shake256_128s_robust.c | 68 ++- .../sig_sphincs_shake256_128s_simple.c | 68 ++- .../sig_sphincs_shake256_192f_robust.c | 68 ++- .../sig_sphincs_shake256_192f_simple.c | 68 ++- .../sig_sphincs_shake256_192s_robust.c | 68 ++- .../sig_sphincs_shake256_192s_simple.c | 68 ++- .../sig_sphincs_shake256_256f_robust.c | 68 ++- .../sig_sphincs_shake256_256f_simple.c | 68 ++- .../sig_sphincs_shake256_256s_robust.c | 68 ++- .../sig_sphincs_shake256_256s_simple.c | 68 ++- tests/KATs/sig/kats.json | 72 +-- 2577 files changed, 180880 insertions(+), 30997 deletions(-) create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/context.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/context_haraka.c create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/haraka_offsets.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/harakax4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/hash_state.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/merkle.c create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/merkle.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/nistapi.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/wotsx4.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/context.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/context_haraka.c create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/haraka_offsets.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/hash_state.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/merkle.c create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/merkle.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/nistapi.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/utilsx1.c create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/utilsx1.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/wotsx1.c create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/wotsx1.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/context.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/context_haraka.c create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/haraka_offsets.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/harakax4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/hash_state.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/merkle.c create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/merkle.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/nistapi.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/wotsx4.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/context.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/context_haraka.c create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/haraka_offsets.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/hash_state.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/merkle.c create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/merkle.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/nistapi.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/utilsx1.c create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/utilsx1.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/wotsx1.c create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/wotsx1.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/context.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/context_haraka.c create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/haraka_offsets.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/harakax4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/hash_state.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/merkle.c create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/merkle.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/nistapi.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/wotsx4.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/context.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/context_haraka.c create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/haraka_offsets.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/hash_state.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/merkle.c create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/merkle.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/nistapi.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/utilsx1.c create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/utilsx1.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/wotsx1.c create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/wotsx1.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/context.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/context_haraka.c create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/haraka_offsets.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/harakax4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/hash_state.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/merkle.c create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/merkle.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/nistapi.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/wotsx4.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/context.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/context_haraka.c create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/haraka_offsets.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/hash_state.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/merkle.c create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/merkle.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/nistapi.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/utilsx1.c create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/utilsx1.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/wotsx1.c create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/wotsx1.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/context.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/context_haraka.c create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/haraka_offsets.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/harakax4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/hash_state.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/merkle.c create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/merkle.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/nistapi.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/wotsx4.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/context.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/context_haraka.c create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/haraka_offsets.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/hash_state.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/merkle.c create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/merkle.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/nistapi.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/utilsx1.c create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/utilsx1.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/wotsx1.c create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/wotsx1.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/context.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/context_haraka.c create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/haraka_offsets.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/harakax4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/hash_state.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/merkle.c create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/merkle.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/nistapi.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/wotsx4.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/context.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/context_haraka.c create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/haraka_offsets.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/hash_state.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/merkle.c create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/merkle.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/nistapi.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/utilsx1.c create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/utilsx1.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/wotsx1.c create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/wotsx1.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/context.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/context_haraka.c create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/haraka_offsets.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/harakax4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/hash_state.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/merkle.c create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/merkle.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/nistapi.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/wotsx4.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/context.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/context_haraka.c create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/haraka_offsets.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/hash_state.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/merkle.c create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/merkle.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/nistapi.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/utilsx1.c create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/utilsx1.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/wotsx1.c create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/wotsx1.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/context.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/context_haraka.c create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/haraka_offsets.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/harakax4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/hash_state.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/merkle.c create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/merkle.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/nistapi.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/wotsx4.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/context.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/context_haraka.c create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/haraka_offsets.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/hash_state.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/merkle.c create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/merkle.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/nistapi.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/utilsx1.c create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/utilsx1.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/wotsx1.c create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/wotsx1.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/context.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/context_haraka.c create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/haraka_offsets.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/harakax4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/hash_state.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/merkle.c create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/merkle.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/nistapi.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/wotsx4.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/context.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/context_haraka.c create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/haraka_offsets.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/hash_state.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/merkle.c create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/merkle.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/nistapi.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/utilsx1.c create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/utilsx1.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/wotsx1.c create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/wotsx1.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/context.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/context_haraka.c create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/haraka_offsets.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/harakax4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/hash_state.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/merkle.c create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/merkle.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/nistapi.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/wotsx4.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/context.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/context_haraka.c create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/haraka_offsets.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/hash_state.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/merkle.c create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/merkle.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/nistapi.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/utilsx1.c create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/utilsx1.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/wotsx1.c create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/wotsx1.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/context.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/context_haraka.c create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/haraka_offsets.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/harakax4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/hash_state.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/merkle.c create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/merkle.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/nistapi.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/wotsx4.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/context.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/context_haraka.c create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/haraka_offsets.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/hash_state.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/merkle.c create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/merkle.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/nistapi.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/utilsx1.c create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/utilsx1.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/wotsx1.c create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/wotsx1.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/context.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/context_haraka.c create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/haraka_offsets.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/harakax4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/hash_state.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/merkle.c create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/merkle.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/nistapi.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/wotsx4.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/context.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/context_haraka.c create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/haraka_offsets.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/hash_state.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/merkle.c create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/merkle.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/nistapi.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/utilsx1.c create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/utilsx1.h create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/wotsx1.c create mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/wotsx1.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/LICENSE create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/address.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/address.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/api.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/context.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/context_sha2.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/fors.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/fors.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/hash.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/hash_sha2.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/hash_sha2x8.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/hashx8.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/merkle.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/merkle.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/nistapi.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/params.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/sha256avx.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/sha256avx.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/sha256x8.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/sha256x8.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/sha2_offsets.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/sign.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/thash.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/thash_sha2_robust.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/thash_sha2_robustx8.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/thashx8.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/utils.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/utils.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/utilsx8.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/utilsx8.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/wots.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/wots.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/wotsx8.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/LICENSE create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/address.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/address.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/api.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/context.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/context_sha2.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/fors.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/fors.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/hash.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/hash_sha2.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/merkle.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/merkle.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/nistapi.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/params.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/sha2_offsets.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/sign.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/thash.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/thash_sha2_robust.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/utils.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/utils.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/utilsx1.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/utilsx1.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/wots.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/wots.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/wotsx1.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/wotsx1.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/LICENSE create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/address.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/address.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/api.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/context.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/context_sha2.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/fors.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/fors.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/hash.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/hash_sha2.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/hash_sha2x8.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/hashx8.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/merkle.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/merkle.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/nistapi.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/params.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/sha256avx.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/sha256avx.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/sha256x8.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/sha256x8.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/sha2_offsets.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/sign.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/thash.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/thash_sha2_simple.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/thash_sha2_simplex8.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/thashx8.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/utils.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/utils.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/utilsx8.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/utilsx8.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/wots.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/wots.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/wotsx8.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_clean/LICENSE create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_clean/address.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_clean/address.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_clean/api.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_clean/context.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_clean/context_sha2.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_clean/fors.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_clean/fors.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_clean/hash.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_clean/hash_sha2.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_clean/merkle.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_clean/merkle.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_clean/nistapi.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_clean/params.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_clean/sha2_offsets.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_clean/sign.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_clean/thash.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_clean/thash_sha2_simple.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_clean/utils.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_clean/utils.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_clean/utilsx1.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_clean/utilsx1.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_clean/wots.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_clean/wots.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_clean/wotsx1.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_clean/wotsx1.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/LICENSE create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/address.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/address.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/api.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/context.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/context_sha2.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/fors.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/fors.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/hash.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/hash_sha2.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/hash_sha2x8.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/hashx8.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/merkle.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/merkle.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/nistapi.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/params.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/sha256avx.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/sha256avx.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/sha256x8.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/sha256x8.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/sha2_offsets.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/sign.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/thash.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/thash_sha2_robust.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/thash_sha2_robustx8.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/thashx8.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/utils.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/utils.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/utilsx8.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/utilsx8.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/wots.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/wots.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/wotsx8.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/LICENSE create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/address.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/address.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/api.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/context.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/context_sha2.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/fors.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/fors.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/hash.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/hash_sha2.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/merkle.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/merkle.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/nistapi.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/params.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/sha2_offsets.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/sign.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/thash.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/thash_sha2_robust.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/utils.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/utils.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/utilsx1.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/utilsx1.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/wots.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/wots.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/wotsx1.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/wotsx1.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/LICENSE create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/address.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/address.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/api.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/context.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/context_sha2.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/fors.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/fors.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/hash.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/hash_sha2.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/hash_sha2x8.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/hashx8.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/merkle.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/merkle.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/nistapi.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/params.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/sha256avx.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/sha256avx.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/sha256x8.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/sha256x8.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/sha2_offsets.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/sign.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/thash.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/thash_sha2_simple.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/thash_sha2_simplex8.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/thashx8.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/utils.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/utils.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/utilsx8.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/utilsx8.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/wots.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/wots.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/wotsx8.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_clean/LICENSE create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_clean/address.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_clean/address.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_clean/api.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_clean/context.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_clean/context_sha2.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_clean/fors.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_clean/fors.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_clean/hash.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_clean/hash_sha2.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_clean/merkle.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_clean/merkle.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_clean/nistapi.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_clean/params.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_clean/sha2_offsets.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_clean/sign.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_clean/thash.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_clean/thash_sha2_simple.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_clean/utils.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_clean/utils.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_clean/utilsx1.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_clean/utilsx1.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_clean/wots.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_clean/wots.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_clean/wotsx1.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_clean/wotsx1.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/LICENSE create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/address.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/address.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/api.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/context.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/context_sha2.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/fors.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/fors.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/hash.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/hash_sha2.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/hash_sha2x8.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/hashx8.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/merkle.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/merkle.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/nistapi.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/params.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/sha256avx.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/sha256avx.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/sha256x8.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/sha256x8.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/sha2_offsets.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/sha512x4.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/sha512x4.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/sign.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/thash.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/thash_sha2_robust.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/thash_sha2_robustx8.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/thashx8.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/utils.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/utils.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/utilsx8.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/utilsx8.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/wots.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/wots.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/wotsx8.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/LICENSE create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/address.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/address.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/api.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/context.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/context_sha2.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/fors.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/fors.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/hash.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/hash_sha2.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/merkle.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/merkle.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/nistapi.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/params.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/sha2_offsets.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/sign.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/thash.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/thash_sha2_robust.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/utils.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/utils.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/utilsx1.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/utilsx1.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/wots.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/wots.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/wotsx1.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/wotsx1.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/LICENSE create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/address.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/address.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/api.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/context.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/context_sha2.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/fors.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/fors.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/hash.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/hash_sha2.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/hash_sha2x8.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/hashx8.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/merkle.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/merkle.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/nistapi.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/params.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/sha256avx.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/sha256avx.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/sha256x8.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/sha256x8.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/sha2_offsets.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/sha512x4.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/sha512x4.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/sign.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/thash.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/thash_sha2_simple.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/thash_sha2_simplex8.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/thashx8.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/utils.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/utils.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/utilsx8.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/utilsx8.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/wots.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/wots.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/wotsx8.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_clean/LICENSE create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_clean/address.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_clean/address.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_clean/api.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_clean/context.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_clean/context_sha2.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_clean/fors.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_clean/fors.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_clean/hash.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_clean/hash_sha2.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_clean/merkle.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_clean/merkle.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_clean/nistapi.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_clean/params.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_clean/sha2_offsets.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_clean/sign.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_clean/thash.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_clean/thash_sha2_simple.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_clean/utils.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_clean/utils.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_clean/utilsx1.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_clean/utilsx1.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_clean/wots.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_clean/wots.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_clean/wotsx1.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_clean/wotsx1.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/LICENSE create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/address.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/address.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/api.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/context.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/context_sha2.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/fors.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/fors.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/hash.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/hash_sha2.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/hash_sha2x8.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/hashx8.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/merkle.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/merkle.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/nistapi.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/params.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/sha256avx.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/sha256avx.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/sha256x8.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/sha256x8.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/sha2_offsets.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/sha512x4.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/sha512x4.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/sign.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/thash.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/thash_sha2_robust.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/thash_sha2_robustx8.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/thashx8.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/utils.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/utils.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/utilsx8.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/utilsx8.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/wots.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/wots.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/wotsx8.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/LICENSE create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/address.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/address.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/api.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/context.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/context_sha2.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/fors.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/fors.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/hash.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/hash_sha2.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/merkle.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/merkle.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/nistapi.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/params.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/sha2_offsets.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/sign.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/thash.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/thash_sha2_robust.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/utils.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/utils.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/utilsx1.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/utilsx1.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/wots.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/wots.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/wotsx1.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/wotsx1.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/LICENSE create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/address.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/address.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/api.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/context.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/context_sha2.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/fors.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/fors.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/hash.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/hash_sha2.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/hash_sha2x8.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/hashx8.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/merkle.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/merkle.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/nistapi.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/params.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/sha256avx.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/sha256avx.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/sha256x8.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/sha256x8.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/sha2_offsets.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/sha512x4.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/sha512x4.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/sign.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/thash.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/thash_sha2_simple.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/thash_sha2_simplex8.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/thashx8.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/utils.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/utils.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/utilsx8.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/utilsx8.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/wots.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/wots.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/wotsx8.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_clean/LICENSE create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_clean/address.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_clean/address.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_clean/api.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_clean/context.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_clean/context_sha2.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_clean/fors.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_clean/fors.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_clean/hash.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_clean/hash_sha2.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_clean/merkle.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_clean/merkle.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_clean/nistapi.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_clean/params.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_clean/sha2_offsets.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_clean/sign.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_clean/thash.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_clean/thash_sha2_simple.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_clean/utils.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_clean/utils.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_clean/utilsx1.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_clean/utilsx1.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_clean/wots.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_clean/wots.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_clean/wotsx1.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_clean/wotsx1.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/LICENSE create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/address.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/address.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/api.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/context.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/context_sha2.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/fors.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/fors.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/hash.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/hash_sha2.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/hash_sha2x8.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/hashx8.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/merkle.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/merkle.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/nistapi.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/params.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/sha256avx.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/sha256avx.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/sha256x8.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/sha256x8.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/sha2_offsets.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/sha512x4.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/sha512x4.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/sign.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/thash.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/thash_sha2_robust.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/thash_sha2_robustx8.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/thashx8.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/utils.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/utils.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/utilsx8.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/utilsx8.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/wots.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/wots.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/wotsx8.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/LICENSE create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/address.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/address.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/api.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/context.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/context_sha2.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/fors.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/fors.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/hash.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/hash_sha2.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/merkle.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/merkle.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/nistapi.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/params.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/sha2_offsets.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/sign.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/thash.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/thash_sha2_robust.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/utils.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/utils.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/utilsx1.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/utilsx1.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/wots.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/wots.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/wotsx1.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/wotsx1.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/LICENSE create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/address.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/address.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/api.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/context.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/context_sha2.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/fors.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/fors.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/hash.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/hash_sha2.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/hash_sha2x8.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/hashx8.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/merkle.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/merkle.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/nistapi.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/params.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/sha256avx.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/sha256avx.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/sha256x8.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/sha256x8.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/sha2_offsets.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/sha512x4.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/sha512x4.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/sign.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/thash.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/thash_sha2_simple.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/thash_sha2_simplex8.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/thashx8.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/utils.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/utils.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/utilsx8.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/utilsx8.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/wots.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/wots.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/wotsx8.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_clean/LICENSE create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_clean/address.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_clean/address.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_clean/api.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_clean/context.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_clean/context_sha2.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_clean/fors.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_clean/fors.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_clean/hash.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_clean/hash_sha2.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_clean/merkle.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_clean/merkle.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_clean/nistapi.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_clean/params.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_clean/sha2_offsets.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_clean/sign.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_clean/thash.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_clean/thash_sha2_simple.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_clean/utils.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_clean/utils.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_clean/utilsx1.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_clean/utilsx1.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_clean/wots.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_clean/wots.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_clean/wotsx1.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_clean/wotsx1.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/LICENSE create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/address.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/address.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/api.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/context.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/context_sha2.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/fors.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/fors.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/hash.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/hash_sha2.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/hash_sha2x8.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/hashx8.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/merkle.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/merkle.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/nistapi.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/params.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/sha256avx.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/sha256avx.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/sha256x8.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/sha256x8.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/sha2_offsets.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/sha512x4.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/sha512x4.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/sign.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/thash.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/thash_sha2_robust.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/thash_sha2_robustx8.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/thashx8.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/utils.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/utils.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/utilsx8.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/utilsx8.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/wots.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/wots.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/wotsx8.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/LICENSE create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/address.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/address.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/api.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/context.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/context_sha2.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/fors.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/fors.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/hash.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/hash_sha2.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/merkle.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/merkle.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/nistapi.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/params.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/sha2_offsets.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/sign.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/thash.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/thash_sha2_robust.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/utils.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/utils.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/utilsx1.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/utilsx1.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/wots.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/wots.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/wotsx1.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/wotsx1.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/LICENSE create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/address.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/address.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/api.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/context.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/context_sha2.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/fors.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/fors.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/hash.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/hash_sha2.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/hash_sha2x8.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/hashx8.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/merkle.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/merkle.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/nistapi.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/params.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/sha256avx.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/sha256avx.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/sha256x8.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/sha256x8.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/sha2_offsets.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/sha512x4.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/sha512x4.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/sign.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/thash.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/thash_sha2_simple.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/thash_sha2_simplex8.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/thashx8.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/utils.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/utils.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/utilsx8.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/utilsx8.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/wots.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/wots.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/wotsx8.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_clean/LICENSE create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_clean/address.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_clean/address.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_clean/api.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_clean/context.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_clean/context_sha2.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_clean/fors.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_clean/fors.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_clean/hash.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_clean/hash_sha2.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_clean/merkle.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_clean/merkle.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_clean/nistapi.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_clean/params.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_clean/sha2_offsets.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_clean/sign.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_clean/thash.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_clean/thash_sha2_simple.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_clean/utils.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_clean/utils.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_clean/utilsx1.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_clean/utilsx1.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_clean/wots.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_clean/wots.h create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_clean/wotsx1.c create mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_clean/wotsx1.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/LICENSE create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/address.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/address.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/api.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/context.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/context_shake.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/f1600x2.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/f1600x2.s create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/f1600x2_const.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/fips202x2.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/fips202x2.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/fors.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/fors.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/hash.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/hash_shake.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/hash_shakex2.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/hashx2.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/merkle.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/merkle.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/nistapi.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/params.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/shake_offsets.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/sign.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/thash.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/thash_shake_robustx2.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/thashx2.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/utils.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/utils.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/utilsx2.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/utilsx2.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/wots.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/wots.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/wotsx2.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/LICENSE create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/address.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/address.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/api.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/context.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/context_shake.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/fips202x4.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/fips202x4.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/fors.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/fors.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/hash.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/hash_shake.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/hash_shakex4.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/hashx4.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/merkle.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/merkle.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/nistapi.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/params.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/shake_offsets.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/sign.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/thash.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/thash_shake_robust.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/thash_shake_robustx4.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/thashx4.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/utils.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/utils.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/utilsx4.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/utilsx4.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/wots.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/wots.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/wotsx4.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/LICENSE create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/address.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/address.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/api.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/context.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/context_shake.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/fors.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/fors.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/hash.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/hash_shake.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/merkle.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/merkle.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/nistapi.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/params.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/shake_offsets.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/sign.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/thash.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/thash_shake_robust.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/utils.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/utils.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/utilsx1.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/utilsx1.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/wots.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/wots.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/wotsx1.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/wotsx1.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/LICENSE create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/address.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/address.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/api.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/context.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/context_shake.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/f1600x2.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/f1600x2.s create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/f1600x2_const.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/fips202x2.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/fips202x2.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/fors.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/fors.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/hash.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/hash_shake.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/hash_shakex2.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/hashx2.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/merkle.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/merkle.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/nistapi.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/params.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/shake_offsets.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/sign.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/thash.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/thash_shake_simplex2.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/thashx2.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/utils.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/utils.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/utilsx2.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/utilsx2.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/wots.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/wots.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/wotsx2.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/LICENSE create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/address.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/address.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/api.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/context.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/context_shake.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/fips202x4.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/fips202x4.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/fors.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/fors.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/hash.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/hash_shake.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/hash_shakex4.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/hashx4.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/merkle.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/merkle.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/nistapi.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/params.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/shake_offsets.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/sign.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/thash.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/thash_shake_simple.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/thash_shake_simplex4.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/thashx4.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/utils.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/utils.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/utilsx4.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/utilsx4.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/wots.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/wots.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/wotsx4.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-simple_clean/LICENSE create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-simple_clean/address.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-simple_clean/address.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-simple_clean/api.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-simple_clean/context.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-simple_clean/context_shake.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-simple_clean/fors.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-simple_clean/fors.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-simple_clean/hash.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-simple_clean/hash_shake.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-simple_clean/merkle.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-simple_clean/merkle.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-simple_clean/nistapi.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-simple_clean/params.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-simple_clean/shake_offsets.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-simple_clean/sign.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-simple_clean/thash.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-simple_clean/thash_shake_simple.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-simple_clean/utils.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-simple_clean/utils.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-simple_clean/utilsx1.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-simple_clean/utilsx1.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-simple_clean/wots.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-simple_clean/wots.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-simple_clean/wotsx1.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-simple_clean/wotsx1.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/LICENSE create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/address.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/address.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/api.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/context.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/context_shake.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/f1600x2.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/f1600x2.s create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/f1600x2_const.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/fips202x2.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/fips202x2.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/fors.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/fors.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/hash.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/hash_shake.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/hash_shakex2.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/hashx2.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/merkle.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/merkle.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/nistapi.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/params.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/shake_offsets.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/sign.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/thash.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/thash_shake_robustx2.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/thashx2.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/utils.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/utils.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/utilsx2.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/utilsx2.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/wots.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/wots.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/wotsx2.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/LICENSE create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/address.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/address.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/api.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/context.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/context_shake.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/fips202x4.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/fips202x4.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/fors.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/fors.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/hash.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/hash_shake.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/hash_shakex4.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/hashx4.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/merkle.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/merkle.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/nistapi.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/params.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/shake_offsets.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/sign.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/thash.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/thash_shake_robust.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/thash_shake_robustx4.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/thashx4.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/utils.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/utils.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/utilsx4.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/utilsx4.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/wots.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/wots.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/wotsx4.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/LICENSE create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/address.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/address.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/api.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/context.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/context_shake.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/fors.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/fors.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/hash.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/hash_shake.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/merkle.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/merkle.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/nistapi.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/params.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/shake_offsets.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/sign.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/thash.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/thash_shake_robust.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/utils.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/utils.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/utilsx1.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/utilsx1.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/wots.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/wots.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/wotsx1.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/wotsx1.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/LICENSE create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/address.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/address.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/api.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/context.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/context_shake.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/f1600x2.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/f1600x2.s create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/f1600x2_const.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/fips202x2.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/fips202x2.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/fors.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/fors.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/hash.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/hash_shake.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/hash_shakex2.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/hashx2.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/merkle.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/merkle.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/nistapi.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/params.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/shake_offsets.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/sign.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/thash.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/thash_shake_simplex2.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/thashx2.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/utils.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/utils.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/utilsx2.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/utilsx2.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/wots.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/wots.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/wotsx2.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/LICENSE create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/address.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/address.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/api.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/context.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/context_shake.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/fips202x4.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/fips202x4.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/fors.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/fors.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/hash.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/hash_shake.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/hash_shakex4.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/hashx4.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/merkle.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/merkle.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/nistapi.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/params.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/shake_offsets.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/sign.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/thash.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/thash_shake_simple.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/thash_shake_simplex4.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/thashx4.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/utils.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/utils.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/utilsx4.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/utilsx4.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/wots.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/wots.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/wotsx4.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-simple_clean/LICENSE create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-simple_clean/address.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-simple_clean/address.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-simple_clean/api.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-simple_clean/context.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-simple_clean/context_shake.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-simple_clean/fors.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-simple_clean/fors.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-simple_clean/hash.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-simple_clean/hash_shake.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-simple_clean/merkle.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-simple_clean/merkle.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-simple_clean/nistapi.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-simple_clean/params.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-simple_clean/shake_offsets.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-simple_clean/sign.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-simple_clean/thash.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-simple_clean/thash_shake_simple.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-simple_clean/utils.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-simple_clean/utils.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-simple_clean/utilsx1.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-simple_clean/utilsx1.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-simple_clean/wots.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-simple_clean/wots.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-simple_clean/wotsx1.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-simple_clean/wotsx1.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/LICENSE create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/address.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/address.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/api.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/context.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/context_shake.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/f1600x2.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/f1600x2.s create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/f1600x2_const.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/fips202x2.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/fips202x2.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/fors.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/fors.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/hash.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/hash_shake.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/hash_shakex2.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/hashx2.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/merkle.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/merkle.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/nistapi.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/params.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/shake_offsets.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/sign.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/thash.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/thash_shake_robustx2.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/thashx2.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/utils.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/utils.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/utilsx2.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/utilsx2.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/wots.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/wots.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/wotsx2.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/LICENSE create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/address.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/address.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/api.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/context.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/context_shake.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/fips202x4.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/fips202x4.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/fors.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/fors.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/hash.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/hash_shake.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/hash_shakex4.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/hashx4.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/merkle.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/merkle.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/nistapi.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/params.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/shake_offsets.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/sign.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/thash.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/thash_shake_robust.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/thash_shake_robustx4.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/thashx4.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/utils.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/utils.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/utilsx4.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/utilsx4.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/wots.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/wots.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/wotsx4.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/LICENSE create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/address.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/address.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/api.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/context.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/context_shake.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/fors.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/fors.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/hash.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/hash_shake.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/merkle.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/merkle.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/nistapi.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/params.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/shake_offsets.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/sign.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/thash.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/thash_shake_robust.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/utils.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/utils.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/utilsx1.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/utilsx1.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/wots.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/wots.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/wotsx1.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/wotsx1.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/LICENSE create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/address.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/address.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/api.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/context.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/context_shake.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/f1600x2.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/f1600x2.s create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/f1600x2_const.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/fips202x2.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/fips202x2.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/fors.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/fors.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/hash.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/hash_shake.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/hash_shakex2.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/hashx2.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/merkle.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/merkle.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/nistapi.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/params.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/shake_offsets.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/sign.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/thash.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/thash_shake_simplex2.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/thashx2.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/utils.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/utils.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/utilsx2.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/utilsx2.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/wots.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/wots.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/wotsx2.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/LICENSE create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/address.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/address.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/api.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/context.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/context_shake.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/fips202x4.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/fips202x4.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/fors.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/fors.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/hash.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/hash_shake.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/hash_shakex4.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/hashx4.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/merkle.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/merkle.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/nistapi.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/params.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/shake_offsets.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/sign.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/thash.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/thash_shake_simple.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/thash_shake_simplex4.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/thashx4.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/utils.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/utils.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/utilsx4.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/utilsx4.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/wots.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/wots.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/wotsx4.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-simple_clean/LICENSE create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-simple_clean/address.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-simple_clean/address.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-simple_clean/api.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-simple_clean/context.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-simple_clean/context_shake.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-simple_clean/fors.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-simple_clean/fors.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-simple_clean/hash.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-simple_clean/hash_shake.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-simple_clean/merkle.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-simple_clean/merkle.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-simple_clean/nistapi.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-simple_clean/params.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-simple_clean/shake_offsets.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-simple_clean/sign.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-simple_clean/thash.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-simple_clean/thash_shake_simple.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-simple_clean/utils.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-simple_clean/utils.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-simple_clean/utilsx1.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-simple_clean/utilsx1.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-simple_clean/wots.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-simple_clean/wots.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-simple_clean/wotsx1.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-simple_clean/wotsx1.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/LICENSE create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/address.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/address.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/api.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/context.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/context_shake.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/f1600x2.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/f1600x2.s create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/f1600x2_const.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/fips202x2.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/fips202x2.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/fors.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/fors.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/hash.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/hash_shake.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/hash_shakex2.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/hashx2.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/merkle.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/merkle.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/nistapi.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/params.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/shake_offsets.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/sign.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/thash.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/thash_shake_robustx2.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/thashx2.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/utils.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/utils.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/utilsx2.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/utilsx2.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/wots.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/wots.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/wotsx2.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/LICENSE create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/address.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/address.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/api.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/context.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/context_shake.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/fips202x4.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/fips202x4.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/fors.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/fors.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/hash.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/hash_shake.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/hash_shakex4.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/hashx4.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/merkle.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/merkle.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/nistapi.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/params.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/shake_offsets.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/sign.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/thash.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/thash_shake_robust.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/thash_shake_robustx4.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/thashx4.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/utils.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/utils.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/utilsx4.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/utilsx4.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/wots.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/wots.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/wotsx4.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/LICENSE create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/address.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/address.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/api.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/context.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/context_shake.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/fors.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/fors.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/hash.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/hash_shake.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/merkle.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/merkle.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/nistapi.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/params.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/shake_offsets.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/sign.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/thash.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/thash_shake_robust.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/utils.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/utils.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/utilsx1.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/utilsx1.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/wots.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/wots.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/wotsx1.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/wotsx1.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/LICENSE create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/address.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/address.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/api.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/context.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/context_shake.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/f1600x2.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/f1600x2.s create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/f1600x2_const.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/fips202x2.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/fips202x2.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/fors.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/fors.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/hash.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/hash_shake.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/hash_shakex2.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/hashx2.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/merkle.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/merkle.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/nistapi.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/params.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/shake_offsets.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/sign.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/thash.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/thash_shake_simplex2.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/thashx2.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/utils.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/utils.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/utilsx2.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/utilsx2.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/wots.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/wots.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/wotsx2.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/LICENSE create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/address.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/address.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/api.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/context.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/context_shake.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/fips202x4.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/fips202x4.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/fors.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/fors.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/hash.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/hash_shake.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/hash_shakex4.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/hashx4.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/merkle.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/merkle.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/nistapi.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/params.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/shake_offsets.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/sign.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/thash.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/thash_shake_simple.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/thash_shake_simplex4.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/thashx4.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/utils.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/utils.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/utilsx4.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/utilsx4.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/wots.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/wots.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/wotsx4.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-simple_clean/LICENSE create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-simple_clean/address.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-simple_clean/address.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-simple_clean/api.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-simple_clean/context.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-simple_clean/context_shake.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-simple_clean/fors.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-simple_clean/fors.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-simple_clean/hash.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-simple_clean/hash_shake.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-simple_clean/merkle.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-simple_clean/merkle.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-simple_clean/nistapi.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-simple_clean/params.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-simple_clean/shake_offsets.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-simple_clean/sign.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-simple_clean/thash.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-simple_clean/thash_shake_simple.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-simple_clean/utils.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-simple_clean/utils.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-simple_clean/utilsx1.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-simple_clean/utilsx1.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-simple_clean/wots.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-simple_clean/wots.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-simple_clean/wotsx1.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-simple_clean/wotsx1.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/LICENSE create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/address.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/address.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/api.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/context.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/context_shake.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/f1600x2.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/f1600x2.s create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/f1600x2_const.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/fips202x2.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/fips202x2.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/fors.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/fors.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/hash.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/hash_shake.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/hash_shakex2.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/hashx2.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/merkle.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/merkle.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/nistapi.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/params.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/shake_offsets.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/sign.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/thash.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/thash_shake_robustx2.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/thashx2.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/utils.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/utils.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/utilsx2.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/utilsx2.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/wots.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/wots.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/wotsx2.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/LICENSE create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/address.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/address.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/api.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/context.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/context_shake.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/fips202x4.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/fips202x4.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/fors.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/fors.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/hash.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/hash_shake.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/hash_shakex4.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/hashx4.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/merkle.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/merkle.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/nistapi.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/params.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/shake_offsets.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/sign.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/thash.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/thash_shake_robust.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/thash_shake_robustx4.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/thashx4.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/utils.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/utils.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/utilsx4.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/utilsx4.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/wots.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/wots.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/wotsx4.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/LICENSE create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/address.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/address.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/api.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/context.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/context_shake.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/fors.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/fors.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/hash.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/hash_shake.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/merkle.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/merkle.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/nistapi.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/params.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/shake_offsets.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/sign.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/thash.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/thash_shake_robust.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/utils.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/utils.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/utilsx1.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/utilsx1.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/wots.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/wots.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/wotsx1.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/wotsx1.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/LICENSE create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/address.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/address.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/api.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/context.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/context_shake.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/f1600x2.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/f1600x2.s create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/f1600x2_const.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/fips202x2.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/fips202x2.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/fors.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/fors.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/hash.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/hash_shake.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/hash_shakex2.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/hashx2.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/merkle.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/merkle.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/nistapi.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/params.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/shake_offsets.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/sign.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/thash.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/thash_shake_simplex2.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/thashx2.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/utils.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/utils.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/utilsx2.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/utilsx2.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/wots.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/wots.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/wotsx2.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/LICENSE create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/address.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/address.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/api.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/context.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/context_shake.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/fips202x4.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/fips202x4.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/fors.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/fors.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/hash.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/hash_shake.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/hash_shakex4.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/hashx4.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/merkle.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/merkle.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/nistapi.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/params.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/shake_offsets.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/sign.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/thash.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/thash_shake_simple.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/thash_shake_simplex4.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/thashx4.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/utils.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/utils.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/utilsx4.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/utilsx4.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/wots.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/wots.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/wotsx4.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-simple_clean/LICENSE create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-simple_clean/address.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-simple_clean/address.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-simple_clean/api.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-simple_clean/context.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-simple_clean/context_shake.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-simple_clean/fors.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-simple_clean/fors.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-simple_clean/hash.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-simple_clean/hash_shake.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-simple_clean/merkle.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-simple_clean/merkle.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-simple_clean/nistapi.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-simple_clean/params.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-simple_clean/shake_offsets.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-simple_clean/sign.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-simple_clean/thash.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-simple_clean/thash_shake_simple.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-simple_clean/utils.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-simple_clean/utils.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-simple_clean/utilsx1.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-simple_clean/utilsx1.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-simple_clean/wots.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-simple_clean/wots.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-simple_clean/wotsx1.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-simple_clean/wotsx1.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/LICENSE create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/address.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/address.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/api.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/context.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/context_shake.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/f1600x2.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/f1600x2.s create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/f1600x2_const.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/fips202x2.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/fips202x2.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/fors.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/fors.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/hash.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/hash_shake.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/hash_shakex2.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/hashx2.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/merkle.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/merkle.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/nistapi.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/params.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/shake_offsets.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/sign.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/thash.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/thash_shake_robustx2.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/thashx2.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/utils.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/utils.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/utilsx2.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/utilsx2.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/wots.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/wots.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/wotsx2.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/LICENSE create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/address.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/address.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/api.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/context.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/context_shake.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/fips202x4.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/fips202x4.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/fors.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/fors.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/hash.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/hash_shake.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/hash_shakex4.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/hashx4.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/merkle.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/merkle.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/nistapi.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/params.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/shake_offsets.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/sign.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/thash.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/thash_shake_robust.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/thash_shake_robustx4.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/thashx4.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/utils.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/utils.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/utilsx4.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/utilsx4.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/wots.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/wots.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/wotsx4.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/LICENSE create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/address.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/address.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/api.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/context.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/context_shake.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/fors.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/fors.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/hash.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/hash_shake.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/merkle.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/merkle.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/nistapi.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/params.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/shake_offsets.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/sign.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/thash.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/thash_shake_robust.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/utils.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/utils.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/utilsx1.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/utilsx1.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/wots.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/wots.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/wotsx1.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/wotsx1.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/LICENSE create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/address.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/address.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/api.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/context.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/context_shake.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/f1600x2.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/f1600x2.s create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/f1600x2_const.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/fips202x2.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/fips202x2.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/fors.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/fors.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/hash.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/hash_shake.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/hash_shakex2.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/hashx2.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/merkle.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/merkle.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/nistapi.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/params.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/shake_offsets.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/sign.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/thash.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/thash_shake_simplex2.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/thashx2.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/utils.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/utils.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/utilsx2.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/utilsx2.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/wots.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/wots.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/wotsx2.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/LICENSE create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/address.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/address.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/api.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/context.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/context_shake.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/fips202x4.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/fips202x4.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/fors.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/fors.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/hash.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/hash_shake.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/hash_shakex4.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/hashx4.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/merkle.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/merkle.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/nistapi.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/params.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/shake_offsets.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/sign.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/thash.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/thash_shake_simple.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/thash_shake_simplex4.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/thashx4.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/utils.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/utils.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/utilsx4.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/utilsx4.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/wots.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/wots.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/wotsx4.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-simple_clean/LICENSE create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-simple_clean/address.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-simple_clean/address.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-simple_clean/api.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-simple_clean/context.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-simple_clean/context_shake.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-simple_clean/fors.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-simple_clean/fors.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-simple_clean/hash.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-simple_clean/hash_shake.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-simple_clean/merkle.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-simple_clean/merkle.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-simple_clean/nistapi.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-simple_clean/params.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-simple_clean/shake_offsets.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-simple_clean/sign.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-simple_clean/thash.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-simple_clean/thash_shake_simple.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-simple_clean/utils.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-simple_clean/utils.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-simple_clean/utilsx1.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-simple_clean/utilsx1.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-simple_clean/wots.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-simple_clean/wots.h create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-simple_clean/wotsx1.c create mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-simple_clean/wotsx1.h diff --git a/.CMake/alg_support.cmake b/.CMake/alg_support.cmake index e84582643c..48b39c9dbc 100644 --- a/.CMake/alg_support.cmake +++ b/.CMake/alg_support.cmake @@ -471,61 +471,133 @@ if(OQS_DIST_X86_64_BUILD OR (OQS_USE_AVX2_INSTRUCTIONS)) cmake_dependent_option(OQS_ENABLE_SIG_sphincs_shake256_128f_robust_avx2 "" ON "OQS_ENABLE_SIG_sphincs_shake256_128f_robust" OFF) endif() +if(CMAKE_SYSTEM_NAME MATCHES "Linux|Darwin") +if(OQS_DIST_ARM64_V8_BUILD OR (OQS_USE_ARM_NEON_INSTRUCTIONS AND OQS_USE_SHA3_INSTRUCTIONS)) + cmake_dependent_option(OQS_ENABLE_SIG_sphincs_shake256_128f_robust_aarch64 "" ON "OQS_ENABLE_SIG_sphincs_shake256_128f_robust" OFF) +endif() +endif() + cmake_dependent_option(OQS_ENABLE_SIG_sphincs_shake256_128f_simple "" ON "OQS_ENABLE_SIG_SPHINCS" OFF) if(OQS_DIST_X86_64_BUILD OR (OQS_USE_AVX2_INSTRUCTIONS)) cmake_dependent_option(OQS_ENABLE_SIG_sphincs_shake256_128f_simple_avx2 "" ON "OQS_ENABLE_SIG_sphincs_shake256_128f_simple" OFF) endif() +if(CMAKE_SYSTEM_NAME MATCHES "Linux|Darwin") +if(OQS_DIST_ARM64_V8_BUILD OR (OQS_USE_ARM_NEON_INSTRUCTIONS AND OQS_USE_SHA3_INSTRUCTIONS)) + cmake_dependent_option(OQS_ENABLE_SIG_sphincs_shake256_128f_simple_aarch64 "" ON "OQS_ENABLE_SIG_sphincs_shake256_128f_simple" OFF) +endif() +endif() + cmake_dependent_option(OQS_ENABLE_SIG_sphincs_shake256_128s_robust "" ON "OQS_ENABLE_SIG_SPHINCS" OFF) if(OQS_DIST_X86_64_BUILD OR (OQS_USE_AVX2_INSTRUCTIONS)) cmake_dependent_option(OQS_ENABLE_SIG_sphincs_shake256_128s_robust_avx2 "" ON "OQS_ENABLE_SIG_sphincs_shake256_128s_robust" OFF) endif() +if(CMAKE_SYSTEM_NAME MATCHES "Linux|Darwin") +if(OQS_DIST_ARM64_V8_BUILD OR (OQS_USE_ARM_NEON_INSTRUCTIONS AND OQS_USE_SHA3_INSTRUCTIONS)) + cmake_dependent_option(OQS_ENABLE_SIG_sphincs_shake256_128s_robust_aarch64 "" ON "OQS_ENABLE_SIG_sphincs_shake256_128s_robust" OFF) +endif() +endif() + cmake_dependent_option(OQS_ENABLE_SIG_sphincs_shake256_128s_simple "" ON "OQS_ENABLE_SIG_SPHINCS" OFF) if(OQS_DIST_X86_64_BUILD OR (OQS_USE_AVX2_INSTRUCTIONS)) cmake_dependent_option(OQS_ENABLE_SIG_sphincs_shake256_128s_simple_avx2 "" ON "OQS_ENABLE_SIG_sphincs_shake256_128s_simple" OFF) endif() +if(CMAKE_SYSTEM_NAME MATCHES "Linux|Darwin") +if(OQS_DIST_ARM64_V8_BUILD OR (OQS_USE_ARM_NEON_INSTRUCTIONS AND OQS_USE_SHA3_INSTRUCTIONS)) + cmake_dependent_option(OQS_ENABLE_SIG_sphincs_shake256_128s_simple_aarch64 "" ON "OQS_ENABLE_SIG_sphincs_shake256_128s_simple" OFF) +endif() +endif() + cmake_dependent_option(OQS_ENABLE_SIG_sphincs_shake256_192f_robust "" ON "OQS_ENABLE_SIG_SPHINCS" OFF) if(OQS_DIST_X86_64_BUILD OR (OQS_USE_AVX2_INSTRUCTIONS)) cmake_dependent_option(OQS_ENABLE_SIG_sphincs_shake256_192f_robust_avx2 "" ON "OQS_ENABLE_SIG_sphincs_shake256_192f_robust" OFF) endif() +if(CMAKE_SYSTEM_NAME MATCHES "Linux|Darwin") +if(OQS_DIST_ARM64_V8_BUILD OR (OQS_USE_ARM_NEON_INSTRUCTIONS AND OQS_USE_SHA3_INSTRUCTIONS)) + cmake_dependent_option(OQS_ENABLE_SIG_sphincs_shake256_192f_robust_aarch64 "" ON "OQS_ENABLE_SIG_sphincs_shake256_192f_robust" OFF) +endif() +endif() + cmake_dependent_option(OQS_ENABLE_SIG_sphincs_shake256_192f_simple "" ON "OQS_ENABLE_SIG_SPHINCS" OFF) if(OQS_DIST_X86_64_BUILD OR (OQS_USE_AVX2_INSTRUCTIONS)) cmake_dependent_option(OQS_ENABLE_SIG_sphincs_shake256_192f_simple_avx2 "" ON "OQS_ENABLE_SIG_sphincs_shake256_192f_simple" OFF) endif() +if(CMAKE_SYSTEM_NAME MATCHES "Linux|Darwin") +if(OQS_DIST_ARM64_V8_BUILD OR (OQS_USE_ARM_NEON_INSTRUCTIONS AND OQS_USE_SHA3_INSTRUCTIONS)) + cmake_dependent_option(OQS_ENABLE_SIG_sphincs_shake256_192f_simple_aarch64 "" ON "OQS_ENABLE_SIG_sphincs_shake256_192f_simple" OFF) +endif() +endif() + cmake_dependent_option(OQS_ENABLE_SIG_sphincs_shake256_192s_robust "" ON "OQS_ENABLE_SIG_SPHINCS" OFF) if(OQS_DIST_X86_64_BUILD OR (OQS_USE_AVX2_INSTRUCTIONS)) cmake_dependent_option(OQS_ENABLE_SIG_sphincs_shake256_192s_robust_avx2 "" ON "OQS_ENABLE_SIG_sphincs_shake256_192s_robust" OFF) endif() +if(CMAKE_SYSTEM_NAME MATCHES "Linux|Darwin") +if(OQS_DIST_ARM64_V8_BUILD OR (OQS_USE_ARM_NEON_INSTRUCTIONS AND OQS_USE_SHA3_INSTRUCTIONS)) + cmake_dependent_option(OQS_ENABLE_SIG_sphincs_shake256_192s_robust_aarch64 "" ON "OQS_ENABLE_SIG_sphincs_shake256_192s_robust" OFF) +endif() +endif() + cmake_dependent_option(OQS_ENABLE_SIG_sphincs_shake256_192s_simple "" ON "OQS_ENABLE_SIG_SPHINCS" OFF) if(OQS_DIST_X86_64_BUILD OR (OQS_USE_AVX2_INSTRUCTIONS)) cmake_dependent_option(OQS_ENABLE_SIG_sphincs_shake256_192s_simple_avx2 "" ON "OQS_ENABLE_SIG_sphincs_shake256_192s_simple" OFF) endif() +if(CMAKE_SYSTEM_NAME MATCHES "Linux|Darwin") +if(OQS_DIST_ARM64_V8_BUILD OR (OQS_USE_ARM_NEON_INSTRUCTIONS AND OQS_USE_SHA3_INSTRUCTIONS)) + cmake_dependent_option(OQS_ENABLE_SIG_sphincs_shake256_192s_simple_aarch64 "" ON "OQS_ENABLE_SIG_sphincs_shake256_192s_simple" OFF) +endif() +endif() + cmake_dependent_option(OQS_ENABLE_SIG_sphincs_shake256_256f_robust "" ON "OQS_ENABLE_SIG_SPHINCS" OFF) if(OQS_DIST_X86_64_BUILD OR (OQS_USE_AVX2_INSTRUCTIONS)) cmake_dependent_option(OQS_ENABLE_SIG_sphincs_shake256_256f_robust_avx2 "" ON "OQS_ENABLE_SIG_sphincs_shake256_256f_robust" OFF) endif() +if(CMAKE_SYSTEM_NAME MATCHES "Linux|Darwin") +if(OQS_DIST_ARM64_V8_BUILD OR (OQS_USE_ARM_NEON_INSTRUCTIONS AND OQS_USE_SHA3_INSTRUCTIONS)) + cmake_dependent_option(OQS_ENABLE_SIG_sphincs_shake256_256f_robust_aarch64 "" ON "OQS_ENABLE_SIG_sphincs_shake256_256f_robust" OFF) +endif() +endif() + cmake_dependent_option(OQS_ENABLE_SIG_sphincs_shake256_256f_simple "" ON "OQS_ENABLE_SIG_SPHINCS" OFF) if(OQS_DIST_X86_64_BUILD OR (OQS_USE_AVX2_INSTRUCTIONS)) cmake_dependent_option(OQS_ENABLE_SIG_sphincs_shake256_256f_simple_avx2 "" ON "OQS_ENABLE_SIG_sphincs_shake256_256f_simple" OFF) endif() +if(CMAKE_SYSTEM_NAME MATCHES "Linux|Darwin") +if(OQS_DIST_ARM64_V8_BUILD OR (OQS_USE_ARM_NEON_INSTRUCTIONS AND OQS_USE_SHA3_INSTRUCTIONS)) + cmake_dependent_option(OQS_ENABLE_SIG_sphincs_shake256_256f_simple_aarch64 "" ON "OQS_ENABLE_SIG_sphincs_shake256_256f_simple" OFF) +endif() +endif() + cmake_dependent_option(OQS_ENABLE_SIG_sphincs_shake256_256s_robust "" ON "OQS_ENABLE_SIG_SPHINCS" OFF) if(OQS_DIST_X86_64_BUILD OR (OQS_USE_AVX2_INSTRUCTIONS)) cmake_dependent_option(OQS_ENABLE_SIG_sphincs_shake256_256s_robust_avx2 "" ON "OQS_ENABLE_SIG_sphincs_shake256_256s_robust" OFF) endif() +if(CMAKE_SYSTEM_NAME MATCHES "Linux|Darwin") +if(OQS_DIST_ARM64_V8_BUILD OR (OQS_USE_ARM_NEON_INSTRUCTIONS AND OQS_USE_SHA3_INSTRUCTIONS)) + cmake_dependent_option(OQS_ENABLE_SIG_sphincs_shake256_256s_robust_aarch64 "" ON "OQS_ENABLE_SIG_sphincs_shake256_256s_robust" OFF) +endif() +endif() + cmake_dependent_option(OQS_ENABLE_SIG_sphincs_shake256_256s_simple "" ON "OQS_ENABLE_SIG_SPHINCS" OFF) if(OQS_DIST_X86_64_BUILD OR (OQS_USE_AVX2_INSTRUCTIONS)) cmake_dependent_option(OQS_ENABLE_SIG_sphincs_shake256_256s_simple_avx2 "" ON "OQS_ENABLE_SIG_sphincs_shake256_256s_simple" OFF) endif() +if(CMAKE_SYSTEM_NAME MATCHES "Linux|Darwin") +if(OQS_DIST_ARM64_V8_BUILD OR (OQS_USE_ARM_NEON_INSTRUCTIONS AND OQS_USE_SHA3_INSTRUCTIONS)) + cmake_dependent_option(OQS_ENABLE_SIG_sphincs_shake256_256s_simple_aarch64 "" ON "OQS_ENABLE_SIG_sphincs_shake256_256s_simple" OFF) +endif() +endif() + ##### OQS_COPY_FROM_UPSTREAM_FRAGMENT_ADD_ENABLE_BY_ALG_END if((OQS_MINIMAL_BUILD STREQUAL "ON")) diff --git a/docs/algorithms/kem/classic_mceliece.md b/docs/algorithms/kem/classic_mceliece.md index 40716950c2..fa94c471db 100644 --- a/docs/algorithms/kem/classic_mceliece.md +++ b/docs/algorithms/kem/classic_mceliece.md @@ -6,7 +6,7 @@ - **Authors' website**: https://classic.mceliece.org - **Specification version**: SUPERCOP-20191221. - **Primary Source**: - - **Source**: https://github.com/PQClean/PQClean/commit/245c95cd1ec326f8f38e26cb17a28832701ba17b + - **Source**: https://github.com/PQClean/PQClean/commit/c1b19a865de329e87e9b3e9152362fcb709da8ab - **Implementation license (SPDX-Identifier)**: Public domain - **Ancestors of primary source**: - SUPERCOP-20191221 "vec" and "avx" implementations diff --git a/docs/algorithms/kem/classic_mceliece.yml b/docs/algorithms/kem/classic_mceliece.yml index b5489f3d94..48b320fb30 100644 --- a/docs/algorithms/kem/classic_mceliece.yml +++ b/docs/algorithms/kem/classic_mceliece.yml @@ -372,4 +372,4 @@ parameter-sets: auxiliary-submitters: [] primary-upstream: spdx-license-identifier: Public domain - source: https://github.com/PQClean/PQClean/commit/245c95cd1ec326f8f38e26cb17a28832701ba17b + source: https://github.com/PQClean/PQClean/commit/c1b19a865de329e87e9b3e9152362fcb709da8ab diff --git a/docs/algorithms/kem/hqc.md b/docs/algorithms/kem/hqc.md index 5d81ece24b..66ade0b9fc 100644 --- a/docs/algorithms/kem/hqc.md +++ b/docs/algorithms/kem/hqc.md @@ -6,7 +6,7 @@ - **Authors' website**: https://pqc-hqc.org/ - **Specification version**: NIST Round 3 submission. - **Primary Source**: - - **Source**: https://github.com/PQClean/PQClean/commit/245c95cd1ec326f8f38e26cb17a28832701ba17b + - **Source**: https://github.com/PQClean/PQClean/commit/c1b19a865de329e87e9b3e9152362fcb709da8ab - **Implementation license (SPDX-Identifier)**: Public domain - **Ancestors of primary source**: - https://github.com/jschanck/package-pqclean/tree/29f79e72/hqc, which takes it from: diff --git a/docs/algorithms/kem/hqc.yml b/docs/algorithms/kem/hqc.yml index 81d3a3899b..2c671d2a2c 100644 --- a/docs/algorithms/kem/hqc.yml +++ b/docs/algorithms/kem/hqc.yml @@ -125,4 +125,4 @@ parameter-sets: upstream: primary-upstream primary-upstream: spdx-license-identifier: Public domain - source: https://github.com/PQClean/PQClean/commit/245c95cd1ec326f8f38e26cb17a28832701ba17b + source: https://github.com/PQClean/PQClean/commit/c1b19a865de329e87e9b3e9152362fcb709da8ab diff --git a/docs/algorithms/kem/kyber.md b/docs/algorithms/kem/kyber.md index be05b6b372..6266d7a10c 100644 --- a/docs/algorithms/kem/kyber.md +++ b/docs/algorithms/kem/kyber.md @@ -11,7 +11,7 @@ - **Implementation license (SPDX-Identifier)**: CC0-1.0 or Apache-2.0 - **Optimized Implementation sources**: https://github.com/pq-crystals/kyber/commit/518de2414a85052bb91349bcbcc347f391292d5b with copy_from_upstream patches - **pqclean-aarch64**: - - **Source**: https://github.com/PQClean/PQClean/commit/245c95cd1ec326f8f38e26cb17a28832701ba17b with copy_from_upstream patches + - **Source**: https://github.com/PQClean/PQClean/commit/c1b19a865de329e87e9b3e9152362fcb709da8ab with copy_from_upstream patches - **Implementation license (SPDX-Identifier)**: CC0-1.0 diff --git a/docs/algorithms/kem/kyber.yml b/docs/algorithms/kem/kyber.yml index 91b58a96d7..a76ebcf9df 100644 --- a/docs/algorithms/kem/kyber.yml +++ b/docs/algorithms/kem/kyber.yml @@ -22,7 +22,7 @@ primary-upstream: spdx-license-identifier: CC0-1.0 or Apache-2.0 optimized-upstreams: pqclean-aarch64: - source: https://github.com/PQClean/PQClean/commit/245c95cd1ec326f8f38e26cb17a28832701ba17b + source: https://github.com/PQClean/PQClean/commit/c1b19a865de329e87e9b3e9152362fcb709da8ab with copy_from_upstream patches spdx-license-identifier: CC0-1.0 parameter-sets: diff --git a/docs/algorithms/sig/dilithium.md b/docs/algorithms/sig/dilithium.md index f741004b4e..ebbedc4f01 100644 --- a/docs/algorithms/sig/dilithium.md +++ b/docs/algorithms/sig/dilithium.md @@ -11,7 +11,7 @@ - **Implementation license (SPDX-Identifier)**: CC0-1.0 or Apache-2.0 - **Optimized Implementation sources**: https://github.com/pq-crystals/dilithium/commit/3e9b9f1412f6c7435dbeb4e10692ea58f181ee51 with copy_from_upstream patches - **pqclean-aarch64**: - - **Source**: https://github.com/PQClean/PQClean/commit/245c95cd1ec326f8f38e26cb17a28832701ba17b with copy_from_upstream patches + - **Source**: https://github.com/PQClean/PQClean/commit/c1b19a865de329e87e9b3e9152362fcb709da8ab with copy_from_upstream patches - **Implementation license (SPDX-Identifier)**: CC0-1.0 diff --git a/docs/algorithms/sig/dilithium.yml b/docs/algorithms/sig/dilithium.yml index ceb560be91..f16e2e3c41 100644 --- a/docs/algorithms/sig/dilithium.yml +++ b/docs/algorithms/sig/dilithium.yml @@ -20,7 +20,7 @@ primary-upstream: spdx-license-identifier: CC0-1.0 or Apache-2.0 optimized-upstreams: pqclean-aarch64: - source: https://github.com/PQClean/PQClean/commit/245c95cd1ec326f8f38e26cb17a28832701ba17b + source: https://github.com/PQClean/PQClean/commit/c1b19a865de329e87e9b3e9152362fcb709da8ab with copy_from_upstream patches spdx-license-identifier: CC0-1.0 parameter-sets: diff --git a/docs/algorithms/sig/falcon.md b/docs/algorithms/sig/falcon.md index 6e5fec8a26..63b6525d3a 100644 --- a/docs/algorithms/sig/falcon.md +++ b/docs/algorithms/sig/falcon.md @@ -7,7 +7,7 @@ - **Authors' website**: https://falcon-sign.info - **Specification version**: 20211101. - **Primary Source**: - - **Source**: https://github.com/PQClean/PQClean/commit/245c95cd1ec326f8f38e26cb17a28832701ba17b + - **Source**: https://github.com/PQClean/PQClean/commit/c1b19a865de329e87e9b3e9152362fcb709da8ab - **Implementation license (SPDX-Identifier)**: MIT diff --git a/docs/algorithms/sig/falcon.yml b/docs/algorithms/sig/falcon.yml index f6c74c3cf7..83dcae4291 100644 --- a/docs/algorithms/sig/falcon.yml +++ b/docs/algorithms/sig/falcon.yml @@ -18,7 +18,7 @@ website: https://falcon-sign.info nist-round: 3 spec-version: 20211101 primary-upstream: - source: https://github.com/PQClean/PQClean/commit/245c95cd1ec326f8f38e26cb17a28832701ba17b + source: https://github.com/PQClean/PQClean/commit/c1b19a865de329e87e9b3e9152362fcb709da8ab spdx-license-identifier: MIT upstream-ancestors: - https://www.falcon-sign.info diff --git a/docs/algorithms/sig/sphincs.md b/docs/algorithms/sig/sphincs.md index 3c9fd15e9f..5b89a70575 100644 --- a/docs/algorithms/sig/sphincs.md +++ b/docs/algorithms/sig/sphincs.md @@ -3,11 +3,11 @@ - **Algorithm type**: Digital signature scheme. - **Main cryptographic assumption**: hash-based signatures. - **Principal submitters**: Andreas Hülsing. -- **Auxiliary submitters**: Jean-Philippe Aumasson, Daniel J. Bernstein,, Christoph Dobraunig, Maria Eichlseder, Scott Fluhrer, Stefan-Lukas Gazdag, Panos Kampanakis, Stefan Kölbl, Tanja Lange, Martin M. Lauridsen, Florian Mendel, Ruben Niederhagen, Christian Rechberger, Joost Rijneveld, Peter Schwabe. +- **Auxiliary submitters**: Jean-Philippe Aumasson, Daniel J. Bernstein,, Ward Beullens, Christoph Dobraunig, Maria Eichlseder, Scott Fluhrer, Stefan-Lukas Gazdag, Panos Kampanakis, Stefan Kölbl, Tanja Lange, Martin M. Lauridsen, Florian Mendel, Ruben Niederhagen, Christian Rechberger, Joost Rijneveld, Peter Schwabe, Bas Westerbaan. - **Authors' website**: https://sphincs.org/ - **Specification version**: NIST Round 3 submission. - **Primary Source**: - - **Source**: https://github.com/PQClean/PQClean/commit/245c95cd1ec326f8f38e26cb17a28832701ba17b with copy_from_upstream patches + - **Source**: https://github.com/PQClean/PQClean/commit/c1b19a865de329e87e9b3e9152362fcb709da8ab - **Implementation license (SPDX-Identifier)**: CC0-1.0 @@ -23,14 +23,14 @@ | SPHINCS+-Haraka-128f-simple | EUF-CMA | 1 | 32 | 64 | 17088 | | SPHINCS+-Haraka-128s-robust | EUF-CMA | 1 | 32 | 64 | 7856 | | SPHINCS+-Haraka-128s-simple | EUF-CMA | 1 | 32 | 64 | 7856 | -| SPHINCS+-Haraka-192f-robust | EUF-CMA | 3 | 48 | 96 | 35664 | -| SPHINCS+-Haraka-192f-simple | EUF-CMA | 3 | 48 | 96 | 35664 | -| SPHINCS+-Haraka-192s-robust | EUF-CMA | 3 | 48 | 96 | 16224 | -| SPHINCS+-Haraka-192s-simple | EUF-CMA | 3 | 48 | 96 | 16224 | -| SPHINCS+-Haraka-256f-robust | EUF-CMA | 5 | 64 | 128 | 49856 | -| SPHINCS+-Haraka-256f-simple | EUF-CMA | 5 | 64 | 128 | 49856 | -| SPHINCS+-Haraka-256s-robust | EUF-CMA | 5 | 64 | 128 | 29792 | -| SPHINCS+-Haraka-256s-simple | EUF-CMA | 5 | 64 | 128 | 29792 | +| SPHINCS+-Haraka-192f-robust | EUF-CMA | 2 | 48 | 96 | 35664 | +| SPHINCS+-Haraka-192f-simple | EUF-CMA | 2 | 48 | 96 | 35664 | +| SPHINCS+-Haraka-192s-robust | EUF-CMA | 2 | 48 | 96 | 16224 | +| SPHINCS+-Haraka-192s-simple | EUF-CMA | 2 | 48 | 96 | 16224 | +| SPHINCS+-Haraka-256f-robust | EUF-CMA | 2 | 64 | 128 | 49856 | +| SPHINCS+-Haraka-256f-simple | EUF-CMA | 2 | 64 | 128 | 49856 | +| SPHINCS+-Haraka-256s-robust | EUF-CMA | 2 | 64 | 128 | 29792 | +| SPHINCS+-Haraka-256s-simple | EUF-CMA | 2 | 64 | 128 | 29792 | | SPHINCS+-SHA256-128f-robust | EUF-CMA | 1 | 32 | 64 | 17088 | | SPHINCS+-SHA256-128f-simple | EUF-CMA | 1 | 32 | 64 | 17088 | | SPHINCS+-SHA256-128s-robust | EUF-CMA | 1 | 32 | 64 | 7856 | diff --git a/docs/algorithms/sig/sphincs.yml b/docs/algorithms/sig/sphincs.yml index 49a6d65eab..d4d1c904a2 100644 --- a/docs/algorithms/sig/sphincs.yml +++ b/docs/algorithms/sig/sphincs.yml @@ -5,6 +5,7 @@ principal-submitters: auxiliary-submitters: - Jean-Philippe Aumasson - Daniel J. Bernstein, +- Ward Beullens - Christoph Dobraunig - Maria Eichlseder - Scott Fluhrer @@ -18,14 +19,14 @@ auxiliary-submitters: - Christian Rechberger - Joost Rijneveld - Peter Schwabe +- Bas Westerbaan crypto-assumption: hash-based signatures website: https://sphincs.org/ nist-round: 3 spec-version: NIST Round 3 submission spdx-license-identifier: CC0-1.0 primary-upstream: - source: https://github.com/PQClean/PQClean/commit/245c95cd1ec326f8f38e26cb17a28832701ba17b - with copy_from_upstream patches + source: https://github.com/PQClean/PQClean/commit/c1b19a865de329e87e9b3e9152362fcb709da8ab spdx-license-identifier: CC0-1.0 upstream-ancestors: - https://github.com/sphincs/sphincsplus @@ -141,7 +142,7 @@ parameter-sets: no-secret-dependent-branching-checked-by-valgrind: true large-stack-usage: false - name: SPHINCS+-Haraka-192f-robust - claimed-nist-level: 3 + claimed-nist-level: 2 claimed-security: EUF-CMA length-public-key: 48 length-secret-key: 96 @@ -168,7 +169,7 @@ parameter-sets: no-secret-dependent-branching-checked-by-valgrind: true large-stack-usage: false - name: SPHINCS+-Haraka-192f-simple - claimed-nist-level: 3 + claimed-nist-level: 2 claimed-security: EUF-CMA length-public-key: 48 length-secret-key: 96 @@ -195,7 +196,7 @@ parameter-sets: no-secret-dependent-branching-checked-by-valgrind: true large-stack-usage: false - name: SPHINCS+-Haraka-192s-robust - claimed-nist-level: 3 + claimed-nist-level: 2 claimed-security: EUF-CMA length-public-key: 48 length-secret-key: 96 @@ -222,7 +223,7 @@ parameter-sets: no-secret-dependent-branching-checked-by-valgrind: true large-stack-usage: false - name: SPHINCS+-Haraka-192s-simple - claimed-nist-level: 3 + claimed-nist-level: 2 claimed-security: EUF-CMA length-public-key: 48 length-secret-key: 96 @@ -249,7 +250,7 @@ parameter-sets: no-secret-dependent-branching-checked-by-valgrind: true large-stack-usage: false - name: SPHINCS+-Haraka-256f-robust - claimed-nist-level: 5 + claimed-nist-level: 2 claimed-security: EUF-CMA length-public-key: 64 length-secret-key: 128 @@ -276,7 +277,7 @@ parameter-sets: no-secret-dependent-branching-checked-by-valgrind: true large-stack-usage: false - name: SPHINCS+-Haraka-256f-simple - claimed-nist-level: 5 + claimed-nist-level: 2 claimed-security: EUF-CMA length-public-key: 64 length-secret-key: 128 @@ -303,7 +304,7 @@ parameter-sets: no-secret-dependent-branching-checked-by-valgrind: true large-stack-usage: false - name: SPHINCS+-Haraka-256s-robust - claimed-nist-level: 5 + claimed-nist-level: 2 claimed-security: EUF-CMA length-public-key: 64 length-secret-key: 128 @@ -330,7 +331,7 @@ parameter-sets: no-secret-dependent-branching-checked-by-valgrind: true large-stack-usage: false - name: SPHINCS+-Haraka-256s-simple - claimed-nist-level: 5 + claimed-nist-level: 2 claimed-security: EUF-CMA length-public-key: 64 length-secret-key: 128 diff --git a/docs/cbom.json b/docs/cbom.json index 88cbddd77c..297c9e3678 100644 --- a/docs/cbom.json +++ b/docs/cbom.json @@ -1,23 +1,23 @@ { "bomFormat": "CBOM", "specVersion": "1.4-cbom-1.0", - "serialNumber": "urn:uuid:ac72fb7e-1016-4cd9-925b-72df28c22f74", + "serialNumber": "urn:uuid:46ad14ba-31d7-42ad-83c8-08c1755261c7", "version": 1, "metadata": { - "timestamp": "2023-03-06T16:07:06.998705", + "timestamp": "2023-03-18T11:09:37.700416", "component": { "type": "library", - "bom-ref": "pkg:github/open-quantum-safe/liboqs@f49e57f71cf550b7ba7ed3ec94cb4f99e41a6d8c", + "bom-ref": "pkg:github/open-quantum-safe/liboqs@d61d81c526da8bb62e363f5a75191689572151cb", "name": "liboqs", - "version": "f49e57f71cf550b7ba7ed3ec94cb4f99e41a6d8c" + "version": "d61d81c526da8bb62e363f5a75191689572151cb" } }, "components": [ { "type": "library", - "bom-ref": "pkg:github/open-quantum-safe/liboqs@f49e57f71cf550b7ba7ed3ec94cb4f99e41a6d8c", + "bom-ref": "pkg:github/open-quantum-safe/liboqs@d61d81c526da8bb62e363f5a75191689572151cb", "name": "liboqs", - "version": "f49e57f71cf550b7ba7ed3ec94cb4f99e41a6d8c" + "version": "d61d81c526da8bb62e363f5a75191689572151cb" }, { "type": "crypto-asset", @@ -1736,7 +1736,7 @@ ], "implementationPlatform": "generic" }, - "nistQuantumSecurityLevel": 3 + "nistQuantumSecurityLevel": 2 } }, { @@ -1756,7 +1756,7 @@ ], "implementationPlatform": "x86_64" }, - "nistQuantumSecurityLevel": 3 + "nistQuantumSecurityLevel": 2 } }, { @@ -1776,7 +1776,7 @@ ], "implementationPlatform": "generic" }, - "nistQuantumSecurityLevel": 3 + "nistQuantumSecurityLevel": 2 } }, { @@ -1796,7 +1796,7 @@ ], "implementationPlatform": "x86_64" }, - "nistQuantumSecurityLevel": 3 + "nistQuantumSecurityLevel": 2 } }, { @@ -1816,7 +1816,7 @@ ], "implementationPlatform": "generic" }, - "nistQuantumSecurityLevel": 3 + "nistQuantumSecurityLevel": 2 } }, { @@ -1836,7 +1836,7 @@ ], "implementationPlatform": "x86_64" }, - "nistQuantumSecurityLevel": 3 + "nistQuantumSecurityLevel": 2 } }, { @@ -1856,7 +1856,7 @@ ], "implementationPlatform": "generic" }, - "nistQuantumSecurityLevel": 3 + "nistQuantumSecurityLevel": 2 } }, { @@ -1876,7 +1876,7 @@ ], "implementationPlatform": "x86_64" }, - "nistQuantumSecurityLevel": 3 + "nistQuantumSecurityLevel": 2 } }, { @@ -1896,7 +1896,7 @@ ], "implementationPlatform": "generic" }, - "nistQuantumSecurityLevel": 5 + "nistQuantumSecurityLevel": 2 } }, { @@ -1916,7 +1916,7 @@ ], "implementationPlatform": "x86_64" }, - "nistQuantumSecurityLevel": 5 + "nistQuantumSecurityLevel": 2 } }, { @@ -1936,7 +1936,7 @@ ], "implementationPlatform": "generic" }, - "nistQuantumSecurityLevel": 5 + "nistQuantumSecurityLevel": 2 } }, { @@ -1956,7 +1956,7 @@ ], "implementationPlatform": "x86_64" }, - "nistQuantumSecurityLevel": 5 + "nistQuantumSecurityLevel": 2 } }, { @@ -1976,7 +1976,7 @@ ], "implementationPlatform": "generic" }, - "nistQuantumSecurityLevel": 5 + "nistQuantumSecurityLevel": 2 } }, { @@ -1996,7 +1996,7 @@ ], "implementationPlatform": "x86_64" }, - "nistQuantumSecurityLevel": 5 + "nistQuantumSecurityLevel": 2 } }, { @@ -2016,7 +2016,7 @@ ], "implementationPlatform": "generic" }, - "nistQuantumSecurityLevel": 5 + "nistQuantumSecurityLevel": 2 } }, { @@ -2036,7 +2036,7 @@ ], "implementationPlatform": "x86_64" }, - "nistQuantumSecurityLevel": 5 + "nistQuantumSecurityLevel": 2 } }, { @@ -3028,7 +3028,7 @@ ], "dependencies": [ { - "ref": "pkg:github/open-quantum-safe/liboqs@f49e57f71cf550b7ba7ed3ec94cb4f99e41a6d8c", + "ref": "pkg:github/open-quantum-safe/liboqs@d61d81c526da8bb62e363f5a75191689572151cb", "dependsOn": [ "alg:BIKE-L1:x86_64", "alg:BIKE-L3:x86_64", diff --git a/src/oqsconfig.h.cmake b/src/oqsconfig.h.cmake index 1011742dcd..bedf439852 100644 --- a/src/oqsconfig.h.cmake +++ b/src/oqsconfig.h.cmake @@ -190,26 +190,38 @@ #cmakedefine OQS_ENABLE_SIG_sphincs_sha256_256s_simple_avx2 1 #cmakedefine OQS_ENABLE_SIG_sphincs_shake256_128f_robust 1 #cmakedefine OQS_ENABLE_SIG_sphincs_shake256_128f_robust_avx2 1 +#cmakedefine OQS_ENABLE_SIG_sphincs_shake256_128f_robust_aarch64 1 #cmakedefine OQS_ENABLE_SIG_sphincs_shake256_128f_simple 1 #cmakedefine OQS_ENABLE_SIG_sphincs_shake256_128f_simple_avx2 1 +#cmakedefine OQS_ENABLE_SIG_sphincs_shake256_128f_simple_aarch64 1 #cmakedefine OQS_ENABLE_SIG_sphincs_shake256_128s_robust 1 #cmakedefine OQS_ENABLE_SIG_sphincs_shake256_128s_robust_avx2 1 +#cmakedefine OQS_ENABLE_SIG_sphincs_shake256_128s_robust_aarch64 1 #cmakedefine OQS_ENABLE_SIG_sphincs_shake256_128s_simple 1 #cmakedefine OQS_ENABLE_SIG_sphincs_shake256_128s_simple_avx2 1 +#cmakedefine OQS_ENABLE_SIG_sphincs_shake256_128s_simple_aarch64 1 #cmakedefine OQS_ENABLE_SIG_sphincs_shake256_192f_robust 1 #cmakedefine OQS_ENABLE_SIG_sphincs_shake256_192f_robust_avx2 1 +#cmakedefine OQS_ENABLE_SIG_sphincs_shake256_192f_robust_aarch64 1 #cmakedefine OQS_ENABLE_SIG_sphincs_shake256_192f_simple 1 #cmakedefine OQS_ENABLE_SIG_sphincs_shake256_192f_simple_avx2 1 +#cmakedefine OQS_ENABLE_SIG_sphincs_shake256_192f_simple_aarch64 1 #cmakedefine OQS_ENABLE_SIG_sphincs_shake256_192s_robust 1 #cmakedefine OQS_ENABLE_SIG_sphincs_shake256_192s_robust_avx2 1 +#cmakedefine OQS_ENABLE_SIG_sphincs_shake256_192s_robust_aarch64 1 #cmakedefine OQS_ENABLE_SIG_sphincs_shake256_192s_simple 1 #cmakedefine OQS_ENABLE_SIG_sphincs_shake256_192s_simple_avx2 1 +#cmakedefine OQS_ENABLE_SIG_sphincs_shake256_192s_simple_aarch64 1 #cmakedefine OQS_ENABLE_SIG_sphincs_shake256_256f_robust 1 #cmakedefine OQS_ENABLE_SIG_sphincs_shake256_256f_robust_avx2 1 +#cmakedefine OQS_ENABLE_SIG_sphincs_shake256_256f_robust_aarch64 1 #cmakedefine OQS_ENABLE_SIG_sphincs_shake256_256f_simple 1 #cmakedefine OQS_ENABLE_SIG_sphincs_shake256_256f_simple_avx2 1 +#cmakedefine OQS_ENABLE_SIG_sphincs_shake256_256f_simple_aarch64 1 #cmakedefine OQS_ENABLE_SIG_sphincs_shake256_256s_robust 1 #cmakedefine OQS_ENABLE_SIG_sphincs_shake256_256s_robust_avx2 1 +#cmakedefine OQS_ENABLE_SIG_sphincs_shake256_256s_robust_aarch64 1 #cmakedefine OQS_ENABLE_SIG_sphincs_shake256_256s_simple 1 #cmakedefine OQS_ENABLE_SIG_sphincs_shake256_256s_simple_avx2 1 +#cmakedefine OQS_ENABLE_SIG_sphincs_shake256_256s_simple_aarch64 1 ///// OQS_COPY_FROM_UPSTREAM_FRAGMENT_ADD_ALG_ENABLE_DEFINES_END diff --git a/src/sig/sphincs/CMakeLists.txt b/src/sig/sphincs/CMakeLists.txt index a760214c2f..85e70ff235 100644 --- a/src/sig/sphincs/CMakeLists.txt +++ b/src/sig/sphincs/CMakeLists.txt @@ -6,14 +6,14 @@ set(_SPHINCS_OBJS "") if(OQS_ENABLE_SIG_sphincs_haraka_128f_robust) - add_library(sphincs_haraka_128f_robust_clean OBJECT sig_sphincs_haraka_128f_robust.c pqclean_sphincs-haraka-128f-robust_clean/address.c pqclean_sphincs-haraka-128f-robust_clean/fors.c pqclean_sphincs-haraka-128f-robust_clean/haraka.c pqclean_sphincs-haraka-128f-robust_clean/hash_haraka.c pqclean_sphincs-haraka-128f-robust_clean/sign.c pqclean_sphincs-haraka-128f-robust_clean/thash_haraka_robust.c pqclean_sphincs-haraka-128f-robust_clean/utils.c pqclean_sphincs-haraka-128f-robust_clean/wots.c) + add_library(sphincs_haraka_128f_robust_clean OBJECT sig_sphincs_haraka_128f_robust.c pqclean_sphincs-haraka-128f-robust_clean/address.c pqclean_sphincs-haraka-128f-robust_clean/context_haraka.c pqclean_sphincs-haraka-128f-robust_clean/fors.c pqclean_sphincs-haraka-128f-robust_clean/haraka.c pqclean_sphincs-haraka-128f-robust_clean/hash_haraka.c pqclean_sphincs-haraka-128f-robust_clean/merkle.c pqclean_sphincs-haraka-128f-robust_clean/sign.c pqclean_sphincs-haraka-128f-robust_clean/thash_haraka_robust.c pqclean_sphincs-haraka-128f-robust_clean/utils.c pqclean_sphincs-haraka-128f-robust_clean/utilsx1.c pqclean_sphincs-haraka-128f-robust_clean/wots.c pqclean_sphincs-haraka-128f-robust_clean/wotsx1.c) target_include_directories(sphincs_haraka_128f_robust_clean PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-haraka-128f-robust_clean) target_include_directories(sphincs_haraka_128f_robust_clean PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) endif() if(OQS_ENABLE_SIG_sphincs_haraka_128f_robust_aesni) - add_library(sphincs_haraka_128f_robust_aesni OBJECT pqclean_sphincs-haraka-128f-robust_aesni/address.c pqclean_sphincs-haraka-128f-robust_aesni/fors.c pqclean_sphincs-haraka-128f-robust_aesni/haraka.c pqclean_sphincs-haraka-128f-robust_aesni/hash_haraka.c pqclean_sphincs-haraka-128f-robust_aesni/hash_harakax4.c pqclean_sphincs-haraka-128f-robust_aesni/sign.c pqclean_sphincs-haraka-128f-robust_aesni/thash_haraka_robust.c pqclean_sphincs-haraka-128f-robust_aesni/thash_haraka_robustx4.c pqclean_sphincs-haraka-128f-robust_aesni/utils.c pqclean_sphincs-haraka-128f-robust_aesni/utilsx4.c pqclean_sphincs-haraka-128f-robust_aesni/wots.c) + add_library(sphincs_haraka_128f_robust_aesni OBJECT pqclean_sphincs-haraka-128f-robust_aesni/address.c pqclean_sphincs-haraka-128f-robust_aesni/context_haraka.c pqclean_sphincs-haraka-128f-robust_aesni/fors.c pqclean_sphincs-haraka-128f-robust_aesni/haraka.c pqclean_sphincs-haraka-128f-robust_aesni/hash_haraka.c pqclean_sphincs-haraka-128f-robust_aesni/hash_harakax4.c pqclean_sphincs-haraka-128f-robust_aesni/merkle.c pqclean_sphincs-haraka-128f-robust_aesni/sign.c pqclean_sphincs-haraka-128f-robust_aesni/thash_haraka_robust.c pqclean_sphincs-haraka-128f-robust_aesni/thash_haraka_robustx4.c pqclean_sphincs-haraka-128f-robust_aesni/utils.c pqclean_sphincs-haraka-128f-robust_aesni/utilsx4.c pqclean_sphincs-haraka-128f-robust_aesni/wots.c) target_include_directories(sphincs_haraka_128f_robust_aesni PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-haraka-128f-robust_aesni) target_include_directories(sphincs_haraka_128f_robust_aesni PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) target_compile_options(sphincs_haraka_128f_robust_aesni PRIVATE -maes) @@ -21,14 +21,14 @@ if(OQS_ENABLE_SIG_sphincs_haraka_128f_robust_aesni) endif() if(OQS_ENABLE_SIG_sphincs_haraka_128f_simple) - add_library(sphincs_haraka_128f_simple_clean OBJECT sig_sphincs_haraka_128f_simple.c pqclean_sphincs-haraka-128f-simple_clean/address.c pqclean_sphincs-haraka-128f-simple_clean/fors.c pqclean_sphincs-haraka-128f-simple_clean/haraka.c pqclean_sphincs-haraka-128f-simple_clean/hash_haraka.c pqclean_sphincs-haraka-128f-simple_clean/sign.c pqclean_sphincs-haraka-128f-simple_clean/thash_haraka_simple.c pqclean_sphincs-haraka-128f-simple_clean/utils.c pqclean_sphincs-haraka-128f-simple_clean/wots.c) + add_library(sphincs_haraka_128f_simple_clean OBJECT sig_sphincs_haraka_128f_simple.c pqclean_sphincs-haraka-128f-simple_clean/address.c pqclean_sphincs-haraka-128f-simple_clean/context_haraka.c pqclean_sphincs-haraka-128f-simple_clean/fors.c pqclean_sphincs-haraka-128f-simple_clean/haraka.c pqclean_sphincs-haraka-128f-simple_clean/hash_haraka.c pqclean_sphincs-haraka-128f-simple_clean/merkle.c pqclean_sphincs-haraka-128f-simple_clean/sign.c pqclean_sphincs-haraka-128f-simple_clean/thash_haraka_simple.c pqclean_sphincs-haraka-128f-simple_clean/utils.c pqclean_sphincs-haraka-128f-simple_clean/utilsx1.c pqclean_sphincs-haraka-128f-simple_clean/wots.c pqclean_sphincs-haraka-128f-simple_clean/wotsx1.c) target_include_directories(sphincs_haraka_128f_simple_clean PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-haraka-128f-simple_clean) target_include_directories(sphincs_haraka_128f_simple_clean PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) endif() if(OQS_ENABLE_SIG_sphincs_haraka_128f_simple_aesni) - add_library(sphincs_haraka_128f_simple_aesni OBJECT pqclean_sphincs-haraka-128f-simple_aesni/address.c pqclean_sphincs-haraka-128f-simple_aesni/fors.c pqclean_sphincs-haraka-128f-simple_aesni/haraka.c pqclean_sphincs-haraka-128f-simple_aesni/hash_haraka.c pqclean_sphincs-haraka-128f-simple_aesni/hash_harakax4.c pqclean_sphincs-haraka-128f-simple_aesni/sign.c pqclean_sphincs-haraka-128f-simple_aesni/thash_haraka_simple.c pqclean_sphincs-haraka-128f-simple_aesni/thash_haraka_simplex4.c pqclean_sphincs-haraka-128f-simple_aesni/utils.c pqclean_sphincs-haraka-128f-simple_aesni/utilsx4.c pqclean_sphincs-haraka-128f-simple_aesni/wots.c) + add_library(sphincs_haraka_128f_simple_aesni OBJECT pqclean_sphincs-haraka-128f-simple_aesni/address.c pqclean_sphincs-haraka-128f-simple_aesni/context_haraka.c pqclean_sphincs-haraka-128f-simple_aesni/fors.c pqclean_sphincs-haraka-128f-simple_aesni/haraka.c pqclean_sphincs-haraka-128f-simple_aesni/hash_haraka.c pqclean_sphincs-haraka-128f-simple_aesni/hash_harakax4.c pqclean_sphincs-haraka-128f-simple_aesni/merkle.c pqclean_sphincs-haraka-128f-simple_aesni/sign.c pqclean_sphincs-haraka-128f-simple_aesni/thash_haraka_simple.c pqclean_sphincs-haraka-128f-simple_aesni/thash_haraka_simplex4.c pqclean_sphincs-haraka-128f-simple_aesni/utils.c pqclean_sphincs-haraka-128f-simple_aesni/utilsx4.c pqclean_sphincs-haraka-128f-simple_aesni/wots.c) target_include_directories(sphincs_haraka_128f_simple_aesni PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-haraka-128f-simple_aesni) target_include_directories(sphincs_haraka_128f_simple_aesni PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) target_compile_options(sphincs_haraka_128f_simple_aesni PRIVATE -maes) @@ -36,14 +36,14 @@ if(OQS_ENABLE_SIG_sphincs_haraka_128f_simple_aesni) endif() if(OQS_ENABLE_SIG_sphincs_haraka_128s_robust) - add_library(sphincs_haraka_128s_robust_clean OBJECT sig_sphincs_haraka_128s_robust.c pqclean_sphincs-haraka-128s-robust_clean/address.c pqclean_sphincs-haraka-128s-robust_clean/fors.c pqclean_sphincs-haraka-128s-robust_clean/haraka.c pqclean_sphincs-haraka-128s-robust_clean/hash_haraka.c pqclean_sphincs-haraka-128s-robust_clean/sign.c pqclean_sphincs-haraka-128s-robust_clean/thash_haraka_robust.c pqclean_sphincs-haraka-128s-robust_clean/utils.c pqclean_sphincs-haraka-128s-robust_clean/wots.c) + add_library(sphincs_haraka_128s_robust_clean OBJECT sig_sphincs_haraka_128s_robust.c pqclean_sphincs-haraka-128s-robust_clean/address.c pqclean_sphincs-haraka-128s-robust_clean/context_haraka.c pqclean_sphincs-haraka-128s-robust_clean/fors.c pqclean_sphincs-haraka-128s-robust_clean/haraka.c pqclean_sphincs-haraka-128s-robust_clean/hash_haraka.c pqclean_sphincs-haraka-128s-robust_clean/merkle.c pqclean_sphincs-haraka-128s-robust_clean/sign.c pqclean_sphincs-haraka-128s-robust_clean/thash_haraka_robust.c pqclean_sphincs-haraka-128s-robust_clean/utils.c pqclean_sphincs-haraka-128s-robust_clean/utilsx1.c pqclean_sphincs-haraka-128s-robust_clean/wots.c pqclean_sphincs-haraka-128s-robust_clean/wotsx1.c) target_include_directories(sphincs_haraka_128s_robust_clean PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-haraka-128s-robust_clean) target_include_directories(sphincs_haraka_128s_robust_clean PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) endif() if(OQS_ENABLE_SIG_sphincs_haraka_128s_robust_aesni) - add_library(sphincs_haraka_128s_robust_aesni OBJECT pqclean_sphincs-haraka-128s-robust_aesni/address.c pqclean_sphincs-haraka-128s-robust_aesni/fors.c pqclean_sphincs-haraka-128s-robust_aesni/haraka.c pqclean_sphincs-haraka-128s-robust_aesni/hash_haraka.c pqclean_sphincs-haraka-128s-robust_aesni/hash_harakax4.c pqclean_sphincs-haraka-128s-robust_aesni/sign.c pqclean_sphincs-haraka-128s-robust_aesni/thash_haraka_robust.c pqclean_sphincs-haraka-128s-robust_aesni/thash_haraka_robustx4.c pqclean_sphincs-haraka-128s-robust_aesni/utils.c pqclean_sphincs-haraka-128s-robust_aesni/utilsx4.c pqclean_sphincs-haraka-128s-robust_aesni/wots.c) + add_library(sphincs_haraka_128s_robust_aesni OBJECT pqclean_sphincs-haraka-128s-robust_aesni/address.c pqclean_sphincs-haraka-128s-robust_aesni/context_haraka.c pqclean_sphincs-haraka-128s-robust_aesni/fors.c pqclean_sphincs-haraka-128s-robust_aesni/haraka.c pqclean_sphincs-haraka-128s-robust_aesni/hash_haraka.c pqclean_sphincs-haraka-128s-robust_aesni/hash_harakax4.c pqclean_sphincs-haraka-128s-robust_aesni/merkle.c pqclean_sphincs-haraka-128s-robust_aesni/sign.c pqclean_sphincs-haraka-128s-robust_aesni/thash_haraka_robust.c pqclean_sphincs-haraka-128s-robust_aesni/thash_haraka_robustx4.c pqclean_sphincs-haraka-128s-robust_aesni/utils.c pqclean_sphincs-haraka-128s-robust_aesni/utilsx4.c pqclean_sphincs-haraka-128s-robust_aesni/wots.c) target_include_directories(sphincs_haraka_128s_robust_aesni PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-haraka-128s-robust_aesni) target_include_directories(sphincs_haraka_128s_robust_aesni PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) target_compile_options(sphincs_haraka_128s_robust_aesni PRIVATE -maes) @@ -51,14 +51,14 @@ if(OQS_ENABLE_SIG_sphincs_haraka_128s_robust_aesni) endif() if(OQS_ENABLE_SIG_sphincs_haraka_128s_simple) - add_library(sphincs_haraka_128s_simple_clean OBJECT sig_sphincs_haraka_128s_simple.c pqclean_sphincs-haraka-128s-simple_clean/address.c pqclean_sphincs-haraka-128s-simple_clean/fors.c pqclean_sphincs-haraka-128s-simple_clean/haraka.c pqclean_sphincs-haraka-128s-simple_clean/hash_haraka.c pqclean_sphincs-haraka-128s-simple_clean/sign.c pqclean_sphincs-haraka-128s-simple_clean/thash_haraka_simple.c pqclean_sphincs-haraka-128s-simple_clean/utils.c pqclean_sphincs-haraka-128s-simple_clean/wots.c) + add_library(sphincs_haraka_128s_simple_clean OBJECT sig_sphincs_haraka_128s_simple.c pqclean_sphincs-haraka-128s-simple_clean/address.c pqclean_sphincs-haraka-128s-simple_clean/context_haraka.c pqclean_sphincs-haraka-128s-simple_clean/fors.c pqclean_sphincs-haraka-128s-simple_clean/haraka.c pqclean_sphincs-haraka-128s-simple_clean/hash_haraka.c pqclean_sphincs-haraka-128s-simple_clean/merkle.c pqclean_sphincs-haraka-128s-simple_clean/sign.c pqclean_sphincs-haraka-128s-simple_clean/thash_haraka_simple.c pqclean_sphincs-haraka-128s-simple_clean/utils.c pqclean_sphincs-haraka-128s-simple_clean/utilsx1.c pqclean_sphincs-haraka-128s-simple_clean/wots.c pqclean_sphincs-haraka-128s-simple_clean/wotsx1.c) target_include_directories(sphincs_haraka_128s_simple_clean PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-haraka-128s-simple_clean) target_include_directories(sphincs_haraka_128s_simple_clean PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) endif() if(OQS_ENABLE_SIG_sphincs_haraka_128s_simple_aesni) - add_library(sphincs_haraka_128s_simple_aesni OBJECT pqclean_sphincs-haraka-128s-simple_aesni/address.c pqclean_sphincs-haraka-128s-simple_aesni/fors.c pqclean_sphincs-haraka-128s-simple_aesni/haraka.c pqclean_sphincs-haraka-128s-simple_aesni/hash_haraka.c pqclean_sphincs-haraka-128s-simple_aesni/hash_harakax4.c pqclean_sphincs-haraka-128s-simple_aesni/sign.c pqclean_sphincs-haraka-128s-simple_aesni/thash_haraka_simple.c pqclean_sphincs-haraka-128s-simple_aesni/thash_haraka_simplex4.c pqclean_sphincs-haraka-128s-simple_aesni/utils.c pqclean_sphincs-haraka-128s-simple_aesni/utilsx4.c pqclean_sphincs-haraka-128s-simple_aesni/wots.c) + add_library(sphincs_haraka_128s_simple_aesni OBJECT pqclean_sphincs-haraka-128s-simple_aesni/address.c pqclean_sphincs-haraka-128s-simple_aesni/context_haraka.c pqclean_sphincs-haraka-128s-simple_aesni/fors.c pqclean_sphincs-haraka-128s-simple_aesni/haraka.c pqclean_sphincs-haraka-128s-simple_aesni/hash_haraka.c pqclean_sphincs-haraka-128s-simple_aesni/hash_harakax4.c pqclean_sphincs-haraka-128s-simple_aesni/merkle.c pqclean_sphincs-haraka-128s-simple_aesni/sign.c pqclean_sphincs-haraka-128s-simple_aesni/thash_haraka_simple.c pqclean_sphincs-haraka-128s-simple_aesni/thash_haraka_simplex4.c pqclean_sphincs-haraka-128s-simple_aesni/utils.c pqclean_sphincs-haraka-128s-simple_aesni/utilsx4.c pqclean_sphincs-haraka-128s-simple_aesni/wots.c) target_include_directories(sphincs_haraka_128s_simple_aesni PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-haraka-128s-simple_aesni) target_include_directories(sphincs_haraka_128s_simple_aesni PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) target_compile_options(sphincs_haraka_128s_simple_aesni PRIVATE -maes) @@ -66,14 +66,14 @@ if(OQS_ENABLE_SIG_sphincs_haraka_128s_simple_aesni) endif() if(OQS_ENABLE_SIG_sphincs_haraka_192f_robust) - add_library(sphincs_haraka_192f_robust_clean OBJECT sig_sphincs_haraka_192f_robust.c pqclean_sphincs-haraka-192f-robust_clean/address.c pqclean_sphincs-haraka-192f-robust_clean/fors.c pqclean_sphincs-haraka-192f-robust_clean/haraka.c pqclean_sphincs-haraka-192f-robust_clean/hash_haraka.c pqclean_sphincs-haraka-192f-robust_clean/sign.c pqclean_sphincs-haraka-192f-robust_clean/thash_haraka_robust.c pqclean_sphincs-haraka-192f-robust_clean/utils.c pqclean_sphincs-haraka-192f-robust_clean/wots.c) + add_library(sphincs_haraka_192f_robust_clean OBJECT sig_sphincs_haraka_192f_robust.c pqclean_sphincs-haraka-192f-robust_clean/address.c pqclean_sphincs-haraka-192f-robust_clean/context_haraka.c pqclean_sphincs-haraka-192f-robust_clean/fors.c pqclean_sphincs-haraka-192f-robust_clean/haraka.c pqclean_sphincs-haraka-192f-robust_clean/hash_haraka.c pqclean_sphincs-haraka-192f-robust_clean/merkle.c pqclean_sphincs-haraka-192f-robust_clean/sign.c pqclean_sphincs-haraka-192f-robust_clean/thash_haraka_robust.c pqclean_sphincs-haraka-192f-robust_clean/utils.c pqclean_sphincs-haraka-192f-robust_clean/utilsx1.c pqclean_sphincs-haraka-192f-robust_clean/wots.c pqclean_sphincs-haraka-192f-robust_clean/wotsx1.c) target_include_directories(sphincs_haraka_192f_robust_clean PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-haraka-192f-robust_clean) target_include_directories(sphincs_haraka_192f_robust_clean PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) endif() if(OQS_ENABLE_SIG_sphincs_haraka_192f_robust_aesni) - add_library(sphincs_haraka_192f_robust_aesni OBJECT pqclean_sphincs-haraka-192f-robust_aesni/address.c pqclean_sphincs-haraka-192f-robust_aesni/fors.c pqclean_sphincs-haraka-192f-robust_aesni/haraka.c pqclean_sphincs-haraka-192f-robust_aesni/hash_haraka.c pqclean_sphincs-haraka-192f-robust_aesni/hash_harakax4.c pqclean_sphincs-haraka-192f-robust_aesni/sign.c pqclean_sphincs-haraka-192f-robust_aesni/thash_haraka_robust.c pqclean_sphincs-haraka-192f-robust_aesni/thash_haraka_robustx4.c pqclean_sphincs-haraka-192f-robust_aesni/utils.c pqclean_sphincs-haraka-192f-robust_aesni/utilsx4.c pqclean_sphincs-haraka-192f-robust_aesni/wots.c) + add_library(sphincs_haraka_192f_robust_aesni OBJECT pqclean_sphincs-haraka-192f-robust_aesni/address.c pqclean_sphincs-haraka-192f-robust_aesni/context_haraka.c pqclean_sphincs-haraka-192f-robust_aesni/fors.c pqclean_sphincs-haraka-192f-robust_aesni/haraka.c pqclean_sphincs-haraka-192f-robust_aesni/hash_haraka.c pqclean_sphincs-haraka-192f-robust_aesni/hash_harakax4.c pqclean_sphincs-haraka-192f-robust_aesni/merkle.c pqclean_sphincs-haraka-192f-robust_aesni/sign.c pqclean_sphincs-haraka-192f-robust_aesni/thash_haraka_robust.c pqclean_sphincs-haraka-192f-robust_aesni/thash_haraka_robustx4.c pqclean_sphincs-haraka-192f-robust_aesni/utils.c pqclean_sphincs-haraka-192f-robust_aesni/utilsx4.c pqclean_sphincs-haraka-192f-robust_aesni/wots.c) target_include_directories(sphincs_haraka_192f_robust_aesni PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-haraka-192f-robust_aesni) target_include_directories(sphincs_haraka_192f_robust_aesni PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) target_compile_options(sphincs_haraka_192f_robust_aesni PRIVATE -maes) @@ -81,14 +81,14 @@ if(OQS_ENABLE_SIG_sphincs_haraka_192f_robust_aesni) endif() if(OQS_ENABLE_SIG_sphincs_haraka_192f_simple) - add_library(sphincs_haraka_192f_simple_clean OBJECT sig_sphincs_haraka_192f_simple.c pqclean_sphincs-haraka-192f-simple_clean/address.c pqclean_sphincs-haraka-192f-simple_clean/fors.c pqclean_sphincs-haraka-192f-simple_clean/haraka.c pqclean_sphincs-haraka-192f-simple_clean/hash_haraka.c pqclean_sphincs-haraka-192f-simple_clean/sign.c pqclean_sphincs-haraka-192f-simple_clean/thash_haraka_simple.c pqclean_sphincs-haraka-192f-simple_clean/utils.c pqclean_sphincs-haraka-192f-simple_clean/wots.c) + add_library(sphincs_haraka_192f_simple_clean OBJECT sig_sphincs_haraka_192f_simple.c pqclean_sphincs-haraka-192f-simple_clean/address.c pqclean_sphincs-haraka-192f-simple_clean/context_haraka.c pqclean_sphincs-haraka-192f-simple_clean/fors.c pqclean_sphincs-haraka-192f-simple_clean/haraka.c pqclean_sphincs-haraka-192f-simple_clean/hash_haraka.c pqclean_sphincs-haraka-192f-simple_clean/merkle.c pqclean_sphincs-haraka-192f-simple_clean/sign.c pqclean_sphincs-haraka-192f-simple_clean/thash_haraka_simple.c pqclean_sphincs-haraka-192f-simple_clean/utils.c pqclean_sphincs-haraka-192f-simple_clean/utilsx1.c pqclean_sphincs-haraka-192f-simple_clean/wots.c pqclean_sphincs-haraka-192f-simple_clean/wotsx1.c) target_include_directories(sphincs_haraka_192f_simple_clean PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-haraka-192f-simple_clean) target_include_directories(sphincs_haraka_192f_simple_clean PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) endif() if(OQS_ENABLE_SIG_sphincs_haraka_192f_simple_aesni) - add_library(sphincs_haraka_192f_simple_aesni OBJECT pqclean_sphincs-haraka-192f-simple_aesni/address.c pqclean_sphincs-haraka-192f-simple_aesni/fors.c pqclean_sphincs-haraka-192f-simple_aesni/haraka.c pqclean_sphincs-haraka-192f-simple_aesni/hash_haraka.c pqclean_sphincs-haraka-192f-simple_aesni/hash_harakax4.c pqclean_sphincs-haraka-192f-simple_aesni/sign.c pqclean_sphincs-haraka-192f-simple_aesni/thash_haraka_simple.c pqclean_sphincs-haraka-192f-simple_aesni/thash_haraka_simplex4.c pqclean_sphincs-haraka-192f-simple_aesni/utils.c pqclean_sphincs-haraka-192f-simple_aesni/utilsx4.c pqclean_sphincs-haraka-192f-simple_aesni/wots.c) + add_library(sphincs_haraka_192f_simple_aesni OBJECT pqclean_sphincs-haraka-192f-simple_aesni/address.c pqclean_sphincs-haraka-192f-simple_aesni/context_haraka.c pqclean_sphincs-haraka-192f-simple_aesni/fors.c pqclean_sphincs-haraka-192f-simple_aesni/haraka.c pqclean_sphincs-haraka-192f-simple_aesni/hash_haraka.c pqclean_sphincs-haraka-192f-simple_aesni/hash_harakax4.c pqclean_sphincs-haraka-192f-simple_aesni/merkle.c pqclean_sphincs-haraka-192f-simple_aesni/sign.c pqclean_sphincs-haraka-192f-simple_aesni/thash_haraka_simple.c pqclean_sphincs-haraka-192f-simple_aesni/thash_haraka_simplex4.c pqclean_sphincs-haraka-192f-simple_aesni/utils.c pqclean_sphincs-haraka-192f-simple_aesni/utilsx4.c pqclean_sphincs-haraka-192f-simple_aesni/wots.c) target_include_directories(sphincs_haraka_192f_simple_aesni PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-haraka-192f-simple_aesni) target_include_directories(sphincs_haraka_192f_simple_aesni PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) target_compile_options(sphincs_haraka_192f_simple_aesni PRIVATE -maes) @@ -96,14 +96,14 @@ if(OQS_ENABLE_SIG_sphincs_haraka_192f_simple_aesni) endif() if(OQS_ENABLE_SIG_sphincs_haraka_192s_robust) - add_library(sphincs_haraka_192s_robust_clean OBJECT sig_sphincs_haraka_192s_robust.c pqclean_sphincs-haraka-192s-robust_clean/address.c pqclean_sphincs-haraka-192s-robust_clean/fors.c pqclean_sphincs-haraka-192s-robust_clean/haraka.c pqclean_sphincs-haraka-192s-robust_clean/hash_haraka.c pqclean_sphincs-haraka-192s-robust_clean/sign.c pqclean_sphincs-haraka-192s-robust_clean/thash_haraka_robust.c pqclean_sphincs-haraka-192s-robust_clean/utils.c pqclean_sphincs-haraka-192s-robust_clean/wots.c) + add_library(sphincs_haraka_192s_robust_clean OBJECT sig_sphincs_haraka_192s_robust.c pqclean_sphincs-haraka-192s-robust_clean/address.c pqclean_sphincs-haraka-192s-robust_clean/context_haraka.c pqclean_sphincs-haraka-192s-robust_clean/fors.c pqclean_sphincs-haraka-192s-robust_clean/haraka.c pqclean_sphincs-haraka-192s-robust_clean/hash_haraka.c pqclean_sphincs-haraka-192s-robust_clean/merkle.c pqclean_sphincs-haraka-192s-robust_clean/sign.c pqclean_sphincs-haraka-192s-robust_clean/thash_haraka_robust.c pqclean_sphincs-haraka-192s-robust_clean/utils.c pqclean_sphincs-haraka-192s-robust_clean/utilsx1.c pqclean_sphincs-haraka-192s-robust_clean/wots.c pqclean_sphincs-haraka-192s-robust_clean/wotsx1.c) target_include_directories(sphincs_haraka_192s_robust_clean PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-haraka-192s-robust_clean) target_include_directories(sphincs_haraka_192s_robust_clean PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) endif() if(OQS_ENABLE_SIG_sphincs_haraka_192s_robust_aesni) - add_library(sphincs_haraka_192s_robust_aesni OBJECT pqclean_sphincs-haraka-192s-robust_aesni/address.c pqclean_sphincs-haraka-192s-robust_aesni/fors.c pqclean_sphincs-haraka-192s-robust_aesni/haraka.c pqclean_sphincs-haraka-192s-robust_aesni/hash_haraka.c pqclean_sphincs-haraka-192s-robust_aesni/hash_harakax4.c pqclean_sphincs-haraka-192s-robust_aesni/sign.c pqclean_sphincs-haraka-192s-robust_aesni/thash_haraka_robust.c pqclean_sphincs-haraka-192s-robust_aesni/thash_haraka_robustx4.c pqclean_sphincs-haraka-192s-robust_aesni/utils.c pqclean_sphincs-haraka-192s-robust_aesni/utilsx4.c pqclean_sphincs-haraka-192s-robust_aesni/wots.c) + add_library(sphincs_haraka_192s_robust_aesni OBJECT pqclean_sphincs-haraka-192s-robust_aesni/address.c pqclean_sphincs-haraka-192s-robust_aesni/context_haraka.c pqclean_sphincs-haraka-192s-robust_aesni/fors.c pqclean_sphincs-haraka-192s-robust_aesni/haraka.c pqclean_sphincs-haraka-192s-robust_aesni/hash_haraka.c pqclean_sphincs-haraka-192s-robust_aesni/hash_harakax4.c pqclean_sphincs-haraka-192s-robust_aesni/merkle.c pqclean_sphincs-haraka-192s-robust_aesni/sign.c pqclean_sphincs-haraka-192s-robust_aesni/thash_haraka_robust.c pqclean_sphincs-haraka-192s-robust_aesni/thash_haraka_robustx4.c pqclean_sphincs-haraka-192s-robust_aesni/utils.c pqclean_sphincs-haraka-192s-robust_aesni/utilsx4.c pqclean_sphincs-haraka-192s-robust_aesni/wots.c) target_include_directories(sphincs_haraka_192s_robust_aesni PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-haraka-192s-robust_aesni) target_include_directories(sphincs_haraka_192s_robust_aesni PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) target_compile_options(sphincs_haraka_192s_robust_aesni PRIVATE -maes) @@ -111,14 +111,14 @@ if(OQS_ENABLE_SIG_sphincs_haraka_192s_robust_aesni) endif() if(OQS_ENABLE_SIG_sphincs_haraka_192s_simple) - add_library(sphincs_haraka_192s_simple_clean OBJECT sig_sphincs_haraka_192s_simple.c pqclean_sphincs-haraka-192s-simple_clean/address.c pqclean_sphincs-haraka-192s-simple_clean/fors.c pqclean_sphincs-haraka-192s-simple_clean/haraka.c pqclean_sphincs-haraka-192s-simple_clean/hash_haraka.c pqclean_sphincs-haraka-192s-simple_clean/sign.c pqclean_sphincs-haraka-192s-simple_clean/thash_haraka_simple.c pqclean_sphincs-haraka-192s-simple_clean/utils.c pqclean_sphincs-haraka-192s-simple_clean/wots.c) + add_library(sphincs_haraka_192s_simple_clean OBJECT sig_sphincs_haraka_192s_simple.c pqclean_sphincs-haraka-192s-simple_clean/address.c pqclean_sphincs-haraka-192s-simple_clean/context_haraka.c pqclean_sphincs-haraka-192s-simple_clean/fors.c pqclean_sphincs-haraka-192s-simple_clean/haraka.c pqclean_sphincs-haraka-192s-simple_clean/hash_haraka.c pqclean_sphincs-haraka-192s-simple_clean/merkle.c pqclean_sphincs-haraka-192s-simple_clean/sign.c pqclean_sphincs-haraka-192s-simple_clean/thash_haraka_simple.c pqclean_sphincs-haraka-192s-simple_clean/utils.c pqclean_sphincs-haraka-192s-simple_clean/utilsx1.c pqclean_sphincs-haraka-192s-simple_clean/wots.c pqclean_sphincs-haraka-192s-simple_clean/wotsx1.c) target_include_directories(sphincs_haraka_192s_simple_clean PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-haraka-192s-simple_clean) target_include_directories(sphincs_haraka_192s_simple_clean PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) endif() if(OQS_ENABLE_SIG_sphincs_haraka_192s_simple_aesni) - add_library(sphincs_haraka_192s_simple_aesni OBJECT pqclean_sphincs-haraka-192s-simple_aesni/address.c pqclean_sphincs-haraka-192s-simple_aesni/fors.c pqclean_sphincs-haraka-192s-simple_aesni/haraka.c pqclean_sphincs-haraka-192s-simple_aesni/hash_haraka.c pqclean_sphincs-haraka-192s-simple_aesni/hash_harakax4.c pqclean_sphincs-haraka-192s-simple_aesni/sign.c pqclean_sphincs-haraka-192s-simple_aesni/thash_haraka_simple.c pqclean_sphincs-haraka-192s-simple_aesni/thash_haraka_simplex4.c pqclean_sphincs-haraka-192s-simple_aesni/utils.c pqclean_sphincs-haraka-192s-simple_aesni/utilsx4.c pqclean_sphincs-haraka-192s-simple_aesni/wots.c) + add_library(sphincs_haraka_192s_simple_aesni OBJECT pqclean_sphincs-haraka-192s-simple_aesni/address.c pqclean_sphincs-haraka-192s-simple_aesni/context_haraka.c pqclean_sphincs-haraka-192s-simple_aesni/fors.c pqclean_sphincs-haraka-192s-simple_aesni/haraka.c pqclean_sphincs-haraka-192s-simple_aesni/hash_haraka.c pqclean_sphincs-haraka-192s-simple_aesni/hash_harakax4.c pqclean_sphincs-haraka-192s-simple_aesni/merkle.c pqclean_sphincs-haraka-192s-simple_aesni/sign.c pqclean_sphincs-haraka-192s-simple_aesni/thash_haraka_simple.c pqclean_sphincs-haraka-192s-simple_aesni/thash_haraka_simplex4.c pqclean_sphincs-haraka-192s-simple_aesni/utils.c pqclean_sphincs-haraka-192s-simple_aesni/utilsx4.c pqclean_sphincs-haraka-192s-simple_aesni/wots.c) target_include_directories(sphincs_haraka_192s_simple_aesni PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-haraka-192s-simple_aesni) target_include_directories(sphincs_haraka_192s_simple_aesni PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) target_compile_options(sphincs_haraka_192s_simple_aesni PRIVATE -maes) @@ -126,14 +126,14 @@ if(OQS_ENABLE_SIG_sphincs_haraka_192s_simple_aesni) endif() if(OQS_ENABLE_SIG_sphincs_haraka_256f_robust) - add_library(sphincs_haraka_256f_robust_clean OBJECT sig_sphincs_haraka_256f_robust.c pqclean_sphincs-haraka-256f-robust_clean/address.c pqclean_sphincs-haraka-256f-robust_clean/fors.c pqclean_sphincs-haraka-256f-robust_clean/haraka.c pqclean_sphincs-haraka-256f-robust_clean/hash_haraka.c pqclean_sphincs-haraka-256f-robust_clean/sign.c pqclean_sphincs-haraka-256f-robust_clean/thash_haraka_robust.c pqclean_sphincs-haraka-256f-robust_clean/utils.c pqclean_sphincs-haraka-256f-robust_clean/wots.c) + add_library(sphincs_haraka_256f_robust_clean OBJECT sig_sphincs_haraka_256f_robust.c pqclean_sphincs-haraka-256f-robust_clean/address.c pqclean_sphincs-haraka-256f-robust_clean/context_haraka.c pqclean_sphincs-haraka-256f-robust_clean/fors.c pqclean_sphincs-haraka-256f-robust_clean/haraka.c pqclean_sphincs-haraka-256f-robust_clean/hash_haraka.c pqclean_sphincs-haraka-256f-robust_clean/merkle.c pqclean_sphincs-haraka-256f-robust_clean/sign.c pqclean_sphincs-haraka-256f-robust_clean/thash_haraka_robust.c pqclean_sphincs-haraka-256f-robust_clean/utils.c pqclean_sphincs-haraka-256f-robust_clean/utilsx1.c pqclean_sphincs-haraka-256f-robust_clean/wots.c pqclean_sphincs-haraka-256f-robust_clean/wotsx1.c) target_include_directories(sphincs_haraka_256f_robust_clean PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-haraka-256f-robust_clean) target_include_directories(sphincs_haraka_256f_robust_clean PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) endif() if(OQS_ENABLE_SIG_sphincs_haraka_256f_robust_aesni) - add_library(sphincs_haraka_256f_robust_aesni OBJECT pqclean_sphincs-haraka-256f-robust_aesni/address.c pqclean_sphincs-haraka-256f-robust_aesni/fors.c pqclean_sphincs-haraka-256f-robust_aesni/haraka.c pqclean_sphincs-haraka-256f-robust_aesni/hash_haraka.c pqclean_sphincs-haraka-256f-robust_aesni/hash_harakax4.c pqclean_sphincs-haraka-256f-robust_aesni/sign.c pqclean_sphincs-haraka-256f-robust_aesni/thash_haraka_robust.c pqclean_sphincs-haraka-256f-robust_aesni/thash_haraka_robustx4.c pqclean_sphincs-haraka-256f-robust_aesni/utils.c pqclean_sphincs-haraka-256f-robust_aesni/utilsx4.c pqclean_sphincs-haraka-256f-robust_aesni/wots.c) + add_library(sphincs_haraka_256f_robust_aesni OBJECT pqclean_sphincs-haraka-256f-robust_aesni/address.c pqclean_sphincs-haraka-256f-robust_aesni/context_haraka.c pqclean_sphincs-haraka-256f-robust_aesni/fors.c pqclean_sphincs-haraka-256f-robust_aesni/haraka.c pqclean_sphincs-haraka-256f-robust_aesni/hash_haraka.c pqclean_sphincs-haraka-256f-robust_aesni/hash_harakax4.c pqclean_sphincs-haraka-256f-robust_aesni/merkle.c pqclean_sphincs-haraka-256f-robust_aesni/sign.c pqclean_sphincs-haraka-256f-robust_aesni/thash_haraka_robust.c pqclean_sphincs-haraka-256f-robust_aesni/thash_haraka_robustx4.c pqclean_sphincs-haraka-256f-robust_aesni/utils.c pqclean_sphincs-haraka-256f-robust_aesni/utilsx4.c pqclean_sphincs-haraka-256f-robust_aesni/wots.c) target_include_directories(sphincs_haraka_256f_robust_aesni PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-haraka-256f-robust_aesni) target_include_directories(sphincs_haraka_256f_robust_aesni PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) target_compile_options(sphincs_haraka_256f_robust_aesni PRIVATE -maes) @@ -141,14 +141,14 @@ if(OQS_ENABLE_SIG_sphincs_haraka_256f_robust_aesni) endif() if(OQS_ENABLE_SIG_sphincs_haraka_256f_simple) - add_library(sphincs_haraka_256f_simple_clean OBJECT sig_sphincs_haraka_256f_simple.c pqclean_sphincs-haraka-256f-simple_clean/address.c pqclean_sphincs-haraka-256f-simple_clean/fors.c pqclean_sphincs-haraka-256f-simple_clean/haraka.c pqclean_sphincs-haraka-256f-simple_clean/hash_haraka.c pqclean_sphincs-haraka-256f-simple_clean/sign.c pqclean_sphincs-haraka-256f-simple_clean/thash_haraka_simple.c pqclean_sphincs-haraka-256f-simple_clean/utils.c pqclean_sphincs-haraka-256f-simple_clean/wots.c) + add_library(sphincs_haraka_256f_simple_clean OBJECT sig_sphincs_haraka_256f_simple.c pqclean_sphincs-haraka-256f-simple_clean/address.c pqclean_sphincs-haraka-256f-simple_clean/context_haraka.c pqclean_sphincs-haraka-256f-simple_clean/fors.c pqclean_sphincs-haraka-256f-simple_clean/haraka.c pqclean_sphincs-haraka-256f-simple_clean/hash_haraka.c pqclean_sphincs-haraka-256f-simple_clean/merkle.c pqclean_sphincs-haraka-256f-simple_clean/sign.c pqclean_sphincs-haraka-256f-simple_clean/thash_haraka_simple.c pqclean_sphincs-haraka-256f-simple_clean/utils.c pqclean_sphincs-haraka-256f-simple_clean/utilsx1.c pqclean_sphincs-haraka-256f-simple_clean/wots.c pqclean_sphincs-haraka-256f-simple_clean/wotsx1.c) target_include_directories(sphincs_haraka_256f_simple_clean PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-haraka-256f-simple_clean) target_include_directories(sphincs_haraka_256f_simple_clean PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) endif() if(OQS_ENABLE_SIG_sphincs_haraka_256f_simple_aesni) - add_library(sphincs_haraka_256f_simple_aesni OBJECT pqclean_sphincs-haraka-256f-simple_aesni/address.c pqclean_sphincs-haraka-256f-simple_aesni/fors.c pqclean_sphincs-haraka-256f-simple_aesni/haraka.c pqclean_sphincs-haraka-256f-simple_aesni/hash_haraka.c pqclean_sphincs-haraka-256f-simple_aesni/hash_harakax4.c pqclean_sphincs-haraka-256f-simple_aesni/sign.c pqclean_sphincs-haraka-256f-simple_aesni/thash_haraka_simple.c pqclean_sphincs-haraka-256f-simple_aesni/thash_haraka_simplex4.c pqclean_sphincs-haraka-256f-simple_aesni/utils.c pqclean_sphincs-haraka-256f-simple_aesni/utilsx4.c pqclean_sphincs-haraka-256f-simple_aesni/wots.c) + add_library(sphincs_haraka_256f_simple_aesni OBJECT pqclean_sphincs-haraka-256f-simple_aesni/address.c pqclean_sphincs-haraka-256f-simple_aesni/context_haraka.c pqclean_sphincs-haraka-256f-simple_aesni/fors.c pqclean_sphincs-haraka-256f-simple_aesni/haraka.c pqclean_sphincs-haraka-256f-simple_aesni/hash_haraka.c pqclean_sphincs-haraka-256f-simple_aesni/hash_harakax4.c pqclean_sphincs-haraka-256f-simple_aesni/merkle.c pqclean_sphincs-haraka-256f-simple_aesni/sign.c pqclean_sphincs-haraka-256f-simple_aesni/thash_haraka_simple.c pqclean_sphincs-haraka-256f-simple_aesni/thash_haraka_simplex4.c pqclean_sphincs-haraka-256f-simple_aesni/utils.c pqclean_sphincs-haraka-256f-simple_aesni/utilsx4.c pqclean_sphincs-haraka-256f-simple_aesni/wots.c) target_include_directories(sphincs_haraka_256f_simple_aesni PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-haraka-256f-simple_aesni) target_include_directories(sphincs_haraka_256f_simple_aesni PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) target_compile_options(sphincs_haraka_256f_simple_aesni PRIVATE -maes) @@ -156,14 +156,14 @@ if(OQS_ENABLE_SIG_sphincs_haraka_256f_simple_aesni) endif() if(OQS_ENABLE_SIG_sphincs_haraka_256s_robust) - add_library(sphincs_haraka_256s_robust_clean OBJECT sig_sphincs_haraka_256s_robust.c pqclean_sphincs-haraka-256s-robust_clean/address.c pqclean_sphincs-haraka-256s-robust_clean/fors.c pqclean_sphincs-haraka-256s-robust_clean/haraka.c pqclean_sphincs-haraka-256s-robust_clean/hash_haraka.c pqclean_sphincs-haraka-256s-robust_clean/sign.c pqclean_sphincs-haraka-256s-robust_clean/thash_haraka_robust.c pqclean_sphincs-haraka-256s-robust_clean/utils.c pqclean_sphincs-haraka-256s-robust_clean/wots.c) + add_library(sphincs_haraka_256s_robust_clean OBJECT sig_sphincs_haraka_256s_robust.c pqclean_sphincs-haraka-256s-robust_clean/address.c pqclean_sphincs-haraka-256s-robust_clean/context_haraka.c pqclean_sphincs-haraka-256s-robust_clean/fors.c pqclean_sphincs-haraka-256s-robust_clean/haraka.c pqclean_sphincs-haraka-256s-robust_clean/hash_haraka.c pqclean_sphincs-haraka-256s-robust_clean/merkle.c pqclean_sphincs-haraka-256s-robust_clean/sign.c pqclean_sphincs-haraka-256s-robust_clean/thash_haraka_robust.c pqclean_sphincs-haraka-256s-robust_clean/utils.c pqclean_sphincs-haraka-256s-robust_clean/utilsx1.c pqclean_sphincs-haraka-256s-robust_clean/wots.c pqclean_sphincs-haraka-256s-robust_clean/wotsx1.c) target_include_directories(sphincs_haraka_256s_robust_clean PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-haraka-256s-robust_clean) target_include_directories(sphincs_haraka_256s_robust_clean PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) endif() if(OQS_ENABLE_SIG_sphincs_haraka_256s_robust_aesni) - add_library(sphincs_haraka_256s_robust_aesni OBJECT pqclean_sphincs-haraka-256s-robust_aesni/address.c pqclean_sphincs-haraka-256s-robust_aesni/fors.c pqclean_sphincs-haraka-256s-robust_aesni/haraka.c pqclean_sphincs-haraka-256s-robust_aesni/hash_haraka.c pqclean_sphincs-haraka-256s-robust_aesni/hash_harakax4.c pqclean_sphincs-haraka-256s-robust_aesni/sign.c pqclean_sphincs-haraka-256s-robust_aesni/thash_haraka_robust.c pqclean_sphincs-haraka-256s-robust_aesni/thash_haraka_robustx4.c pqclean_sphincs-haraka-256s-robust_aesni/utils.c pqclean_sphincs-haraka-256s-robust_aesni/utilsx4.c pqclean_sphincs-haraka-256s-robust_aesni/wots.c) + add_library(sphincs_haraka_256s_robust_aesni OBJECT pqclean_sphincs-haraka-256s-robust_aesni/address.c pqclean_sphincs-haraka-256s-robust_aesni/context_haraka.c pqclean_sphincs-haraka-256s-robust_aesni/fors.c pqclean_sphincs-haraka-256s-robust_aesni/haraka.c pqclean_sphincs-haraka-256s-robust_aesni/hash_haraka.c pqclean_sphincs-haraka-256s-robust_aesni/hash_harakax4.c pqclean_sphincs-haraka-256s-robust_aesni/merkle.c pqclean_sphincs-haraka-256s-robust_aesni/sign.c pqclean_sphincs-haraka-256s-robust_aesni/thash_haraka_robust.c pqclean_sphincs-haraka-256s-robust_aesni/thash_haraka_robustx4.c pqclean_sphincs-haraka-256s-robust_aesni/utils.c pqclean_sphincs-haraka-256s-robust_aesni/utilsx4.c pqclean_sphincs-haraka-256s-robust_aesni/wots.c) target_include_directories(sphincs_haraka_256s_robust_aesni PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-haraka-256s-robust_aesni) target_include_directories(sphincs_haraka_256s_robust_aesni PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) target_compile_options(sphincs_haraka_256s_robust_aesni PRIVATE -maes) @@ -171,14 +171,14 @@ if(OQS_ENABLE_SIG_sphincs_haraka_256s_robust_aesni) endif() if(OQS_ENABLE_SIG_sphincs_haraka_256s_simple) - add_library(sphincs_haraka_256s_simple_clean OBJECT sig_sphincs_haraka_256s_simple.c pqclean_sphincs-haraka-256s-simple_clean/address.c pqclean_sphincs-haraka-256s-simple_clean/fors.c pqclean_sphincs-haraka-256s-simple_clean/haraka.c pqclean_sphincs-haraka-256s-simple_clean/hash_haraka.c pqclean_sphincs-haraka-256s-simple_clean/sign.c pqclean_sphincs-haraka-256s-simple_clean/thash_haraka_simple.c pqclean_sphincs-haraka-256s-simple_clean/utils.c pqclean_sphincs-haraka-256s-simple_clean/wots.c) + add_library(sphincs_haraka_256s_simple_clean OBJECT sig_sphincs_haraka_256s_simple.c pqclean_sphincs-haraka-256s-simple_clean/address.c pqclean_sphincs-haraka-256s-simple_clean/context_haraka.c pqclean_sphincs-haraka-256s-simple_clean/fors.c pqclean_sphincs-haraka-256s-simple_clean/haraka.c pqclean_sphincs-haraka-256s-simple_clean/hash_haraka.c pqclean_sphincs-haraka-256s-simple_clean/merkle.c pqclean_sphincs-haraka-256s-simple_clean/sign.c pqclean_sphincs-haraka-256s-simple_clean/thash_haraka_simple.c pqclean_sphincs-haraka-256s-simple_clean/utils.c pqclean_sphincs-haraka-256s-simple_clean/utilsx1.c pqclean_sphincs-haraka-256s-simple_clean/wots.c pqclean_sphincs-haraka-256s-simple_clean/wotsx1.c) target_include_directories(sphincs_haraka_256s_simple_clean PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-haraka-256s-simple_clean) target_include_directories(sphincs_haraka_256s_simple_clean PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) endif() if(OQS_ENABLE_SIG_sphincs_haraka_256s_simple_aesni) - add_library(sphincs_haraka_256s_simple_aesni OBJECT pqclean_sphincs-haraka-256s-simple_aesni/address.c pqclean_sphincs-haraka-256s-simple_aesni/fors.c pqclean_sphincs-haraka-256s-simple_aesni/haraka.c pqclean_sphincs-haraka-256s-simple_aesni/hash_haraka.c pqclean_sphincs-haraka-256s-simple_aesni/hash_harakax4.c pqclean_sphincs-haraka-256s-simple_aesni/sign.c pqclean_sphincs-haraka-256s-simple_aesni/thash_haraka_simple.c pqclean_sphincs-haraka-256s-simple_aesni/thash_haraka_simplex4.c pqclean_sphincs-haraka-256s-simple_aesni/utils.c pqclean_sphincs-haraka-256s-simple_aesni/utilsx4.c pqclean_sphincs-haraka-256s-simple_aesni/wots.c) + add_library(sphincs_haraka_256s_simple_aesni OBJECT pqclean_sphincs-haraka-256s-simple_aesni/address.c pqclean_sphincs-haraka-256s-simple_aesni/context_haraka.c pqclean_sphincs-haraka-256s-simple_aesni/fors.c pqclean_sphincs-haraka-256s-simple_aesni/haraka.c pqclean_sphincs-haraka-256s-simple_aesni/hash_haraka.c pqclean_sphincs-haraka-256s-simple_aesni/hash_harakax4.c pqclean_sphincs-haraka-256s-simple_aesni/merkle.c pqclean_sphincs-haraka-256s-simple_aesni/sign.c pqclean_sphincs-haraka-256s-simple_aesni/thash_haraka_simple.c pqclean_sphincs-haraka-256s-simple_aesni/thash_haraka_simplex4.c pqclean_sphincs-haraka-256s-simple_aesni/utils.c pqclean_sphincs-haraka-256s-simple_aesni/utilsx4.c pqclean_sphincs-haraka-256s-simple_aesni/wots.c) target_include_directories(sphincs_haraka_256s_simple_aesni PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-haraka-256s-simple_aesni) target_include_directories(sphincs_haraka_256s_simple_aesni PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) target_compile_options(sphincs_haraka_256s_simple_aesni PRIVATE -maes) @@ -186,363 +186,459 @@ if(OQS_ENABLE_SIG_sphincs_haraka_256s_simple_aesni) endif() if(OQS_ENABLE_SIG_sphincs_sha256_128f_robust) - add_library(sphincs_sha256_128f_robust_clean OBJECT sig_sphincs_sha256_128f_robust.c pqclean_sphincs-sha256-128f-robust_clean/address.c pqclean_sphincs-sha256-128f-robust_clean/fors.c pqclean_sphincs-sha256-128f-robust_clean/hash_sha256.c pqclean_sphincs-sha256-128f-robust_clean/sha256.c pqclean_sphincs-sha256-128f-robust_clean/sign.c pqclean_sphincs-sha256-128f-robust_clean/thash_sha256_robust.c pqclean_sphincs-sha256-128f-robust_clean/utils.c pqclean_sphincs-sha256-128f-robust_clean/wots.c) - target_include_directories(sphincs_sha256_128f_robust_clean PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-sha256-128f-robust_clean) + add_library(sphincs_sha256_128f_robust_clean OBJECT sig_sphincs_sha256_128f_robust.c pqclean_sphincs-sha2-128f-robust_clean/address.c pqclean_sphincs-sha2-128f-robust_clean/context_sha2.c pqclean_sphincs-sha2-128f-robust_clean/fors.c pqclean_sphincs-sha2-128f-robust_clean/hash_sha2.c pqclean_sphincs-sha2-128f-robust_clean/merkle.c pqclean_sphincs-sha2-128f-robust_clean/sign.c pqclean_sphincs-sha2-128f-robust_clean/thash_sha2_robust.c pqclean_sphincs-sha2-128f-robust_clean/utils.c pqclean_sphincs-sha2-128f-robust_clean/utilsx1.c pqclean_sphincs-sha2-128f-robust_clean/wots.c pqclean_sphincs-sha2-128f-robust_clean/wotsx1.c) + target_include_directories(sphincs_sha256_128f_robust_clean PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-sha2-128f-robust_clean) target_include_directories(sphincs_sha256_128f_robust_clean PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) endif() if(OQS_ENABLE_SIG_sphincs_sha256_128f_robust_avx2) - add_library(sphincs_sha256_128f_robust_avx2 OBJECT pqclean_sphincs-sha256-128f-robust_avx2/address.c pqclean_sphincs-sha256-128f-robust_avx2/fors.c pqclean_sphincs-sha256-128f-robust_avx2/hash_sha256.c pqclean_sphincs-sha256-128f-robust_avx2/hash_sha256x8.c pqclean_sphincs-sha256-128f-robust_avx2/sha256.c pqclean_sphincs-sha256-128f-robust_avx2/sha256avx.c pqclean_sphincs-sha256-128f-robust_avx2/sha256x8.c pqclean_sphincs-sha256-128f-robust_avx2/sign.c pqclean_sphincs-sha256-128f-robust_avx2/thash_sha256_robust.c pqclean_sphincs-sha256-128f-robust_avx2/thash_sha256_robustx8.c pqclean_sphincs-sha256-128f-robust_avx2/utils.c pqclean_sphincs-sha256-128f-robust_avx2/utilsx8.c pqclean_sphincs-sha256-128f-robust_avx2/wots.c) - target_include_directories(sphincs_sha256_128f_robust_avx2 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-sha256-128f-robust_avx2) + add_library(sphincs_sha256_128f_robust_avx2 OBJECT pqclean_sphincs-sha2-128f-robust_avx2/address.c pqclean_sphincs-sha2-128f-robust_avx2/context_sha2.c pqclean_sphincs-sha2-128f-robust_avx2/fors.c pqclean_sphincs-sha2-128f-robust_avx2/hash_sha2.c pqclean_sphincs-sha2-128f-robust_avx2/hash_sha2x8.c pqclean_sphincs-sha2-128f-robust_avx2/merkle.c pqclean_sphincs-sha2-128f-robust_avx2/sha256avx.c pqclean_sphincs-sha2-128f-robust_avx2/sha256x8.c pqclean_sphincs-sha2-128f-robust_avx2/sign.c pqclean_sphincs-sha2-128f-robust_avx2/thash_sha2_robust.c pqclean_sphincs-sha2-128f-robust_avx2/thash_sha2_robustx8.c pqclean_sphincs-sha2-128f-robust_avx2/utils.c pqclean_sphincs-sha2-128f-robust_avx2/utilsx8.c pqclean_sphincs-sha2-128f-robust_avx2/wots.c) + target_include_directories(sphincs_sha256_128f_robust_avx2 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-sha2-128f-robust_avx2) target_include_directories(sphincs_sha256_128f_robust_avx2 PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) target_compile_options(sphincs_sha256_128f_robust_avx2 PRIVATE -mavx2) set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) endif() if(OQS_ENABLE_SIG_sphincs_sha256_128f_simple) - add_library(sphincs_sha256_128f_simple_clean OBJECT sig_sphincs_sha256_128f_simple.c pqclean_sphincs-sha256-128f-simple_clean/address.c pqclean_sphincs-sha256-128f-simple_clean/fors.c pqclean_sphincs-sha256-128f-simple_clean/hash_sha256.c pqclean_sphincs-sha256-128f-simple_clean/sha256.c pqclean_sphincs-sha256-128f-simple_clean/sign.c pqclean_sphincs-sha256-128f-simple_clean/thash_sha256_simple.c pqclean_sphincs-sha256-128f-simple_clean/utils.c pqclean_sphincs-sha256-128f-simple_clean/wots.c) - target_include_directories(sphincs_sha256_128f_simple_clean PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-sha256-128f-simple_clean) + add_library(sphincs_sha256_128f_simple_clean OBJECT sig_sphincs_sha256_128f_simple.c pqclean_sphincs-sha2-128f-simple_clean/address.c pqclean_sphincs-sha2-128f-simple_clean/context_sha2.c pqclean_sphincs-sha2-128f-simple_clean/fors.c pqclean_sphincs-sha2-128f-simple_clean/hash_sha2.c pqclean_sphincs-sha2-128f-simple_clean/merkle.c pqclean_sphincs-sha2-128f-simple_clean/sign.c pqclean_sphincs-sha2-128f-simple_clean/thash_sha2_simple.c pqclean_sphincs-sha2-128f-simple_clean/utils.c pqclean_sphincs-sha2-128f-simple_clean/utilsx1.c pqclean_sphincs-sha2-128f-simple_clean/wots.c pqclean_sphincs-sha2-128f-simple_clean/wotsx1.c) + target_include_directories(sphincs_sha256_128f_simple_clean PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-sha2-128f-simple_clean) target_include_directories(sphincs_sha256_128f_simple_clean PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) endif() if(OQS_ENABLE_SIG_sphincs_sha256_128f_simple_avx2) - add_library(sphincs_sha256_128f_simple_avx2 OBJECT pqclean_sphincs-sha256-128f-simple_avx2/address.c pqclean_sphincs-sha256-128f-simple_avx2/fors.c pqclean_sphincs-sha256-128f-simple_avx2/hash_sha256.c pqclean_sphincs-sha256-128f-simple_avx2/hash_sha256x8.c pqclean_sphincs-sha256-128f-simple_avx2/sha256.c pqclean_sphincs-sha256-128f-simple_avx2/sha256avx.c pqclean_sphincs-sha256-128f-simple_avx2/sha256x8.c pqclean_sphincs-sha256-128f-simple_avx2/sign.c pqclean_sphincs-sha256-128f-simple_avx2/thash_sha256_simple.c pqclean_sphincs-sha256-128f-simple_avx2/thash_sha256_simplex8.c pqclean_sphincs-sha256-128f-simple_avx2/utils.c pqclean_sphincs-sha256-128f-simple_avx2/utilsx8.c pqclean_sphincs-sha256-128f-simple_avx2/wots.c) - target_include_directories(sphincs_sha256_128f_simple_avx2 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-sha256-128f-simple_avx2) + add_library(sphincs_sha256_128f_simple_avx2 OBJECT pqclean_sphincs-sha2-128f-simple_avx2/address.c pqclean_sphincs-sha2-128f-simple_avx2/context_sha2.c pqclean_sphincs-sha2-128f-simple_avx2/fors.c pqclean_sphincs-sha2-128f-simple_avx2/hash_sha2.c pqclean_sphincs-sha2-128f-simple_avx2/hash_sha2x8.c pqclean_sphincs-sha2-128f-simple_avx2/merkle.c pqclean_sphincs-sha2-128f-simple_avx2/sha256avx.c pqclean_sphincs-sha2-128f-simple_avx2/sha256x8.c pqclean_sphincs-sha2-128f-simple_avx2/sign.c pqclean_sphincs-sha2-128f-simple_avx2/thash_sha2_simple.c pqclean_sphincs-sha2-128f-simple_avx2/thash_sha2_simplex8.c pqclean_sphincs-sha2-128f-simple_avx2/utils.c pqclean_sphincs-sha2-128f-simple_avx2/utilsx8.c pqclean_sphincs-sha2-128f-simple_avx2/wots.c) + target_include_directories(sphincs_sha256_128f_simple_avx2 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-sha2-128f-simple_avx2) target_include_directories(sphincs_sha256_128f_simple_avx2 PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) target_compile_options(sphincs_sha256_128f_simple_avx2 PRIVATE -mavx2) set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) endif() if(OQS_ENABLE_SIG_sphincs_sha256_128s_robust) - add_library(sphincs_sha256_128s_robust_clean OBJECT sig_sphincs_sha256_128s_robust.c pqclean_sphincs-sha256-128s-robust_clean/address.c pqclean_sphincs-sha256-128s-robust_clean/fors.c pqclean_sphincs-sha256-128s-robust_clean/hash_sha256.c pqclean_sphincs-sha256-128s-robust_clean/sha256.c pqclean_sphincs-sha256-128s-robust_clean/sign.c pqclean_sphincs-sha256-128s-robust_clean/thash_sha256_robust.c pqclean_sphincs-sha256-128s-robust_clean/utils.c pqclean_sphincs-sha256-128s-robust_clean/wots.c) - target_include_directories(sphincs_sha256_128s_robust_clean PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-sha256-128s-robust_clean) + add_library(sphincs_sha256_128s_robust_clean OBJECT sig_sphincs_sha256_128s_robust.c pqclean_sphincs-sha2-128s-robust_clean/address.c pqclean_sphincs-sha2-128s-robust_clean/context_sha2.c pqclean_sphincs-sha2-128s-robust_clean/fors.c pqclean_sphincs-sha2-128s-robust_clean/hash_sha2.c pqclean_sphincs-sha2-128s-robust_clean/merkle.c pqclean_sphincs-sha2-128s-robust_clean/sign.c pqclean_sphincs-sha2-128s-robust_clean/thash_sha2_robust.c pqclean_sphincs-sha2-128s-robust_clean/utils.c pqclean_sphincs-sha2-128s-robust_clean/utilsx1.c pqclean_sphincs-sha2-128s-robust_clean/wots.c pqclean_sphincs-sha2-128s-robust_clean/wotsx1.c) + target_include_directories(sphincs_sha256_128s_robust_clean PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-sha2-128s-robust_clean) target_include_directories(sphincs_sha256_128s_robust_clean PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) endif() if(OQS_ENABLE_SIG_sphincs_sha256_128s_robust_avx2) - add_library(sphincs_sha256_128s_robust_avx2 OBJECT pqclean_sphincs-sha256-128s-robust_avx2/address.c pqclean_sphincs-sha256-128s-robust_avx2/fors.c pqclean_sphincs-sha256-128s-robust_avx2/hash_sha256.c pqclean_sphincs-sha256-128s-robust_avx2/hash_sha256x8.c pqclean_sphincs-sha256-128s-robust_avx2/sha256.c pqclean_sphincs-sha256-128s-robust_avx2/sha256avx.c pqclean_sphincs-sha256-128s-robust_avx2/sha256x8.c pqclean_sphincs-sha256-128s-robust_avx2/sign.c pqclean_sphincs-sha256-128s-robust_avx2/thash_sha256_robust.c pqclean_sphincs-sha256-128s-robust_avx2/thash_sha256_robustx8.c pqclean_sphincs-sha256-128s-robust_avx2/utils.c pqclean_sphincs-sha256-128s-robust_avx2/utilsx8.c pqclean_sphincs-sha256-128s-robust_avx2/wots.c) - target_include_directories(sphincs_sha256_128s_robust_avx2 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-sha256-128s-robust_avx2) + add_library(sphincs_sha256_128s_robust_avx2 OBJECT pqclean_sphincs-sha2-128s-robust_avx2/address.c pqclean_sphincs-sha2-128s-robust_avx2/context_sha2.c pqclean_sphincs-sha2-128s-robust_avx2/fors.c pqclean_sphincs-sha2-128s-robust_avx2/hash_sha2.c pqclean_sphincs-sha2-128s-robust_avx2/hash_sha2x8.c pqclean_sphincs-sha2-128s-robust_avx2/merkle.c pqclean_sphincs-sha2-128s-robust_avx2/sha256avx.c pqclean_sphincs-sha2-128s-robust_avx2/sha256x8.c pqclean_sphincs-sha2-128s-robust_avx2/sign.c pqclean_sphincs-sha2-128s-robust_avx2/thash_sha2_robust.c pqclean_sphincs-sha2-128s-robust_avx2/thash_sha2_robustx8.c pqclean_sphincs-sha2-128s-robust_avx2/utils.c pqclean_sphincs-sha2-128s-robust_avx2/utilsx8.c pqclean_sphincs-sha2-128s-robust_avx2/wots.c) + target_include_directories(sphincs_sha256_128s_robust_avx2 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-sha2-128s-robust_avx2) target_include_directories(sphincs_sha256_128s_robust_avx2 PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) target_compile_options(sphincs_sha256_128s_robust_avx2 PRIVATE -mavx2) set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) endif() if(OQS_ENABLE_SIG_sphincs_sha256_128s_simple) - add_library(sphincs_sha256_128s_simple_clean OBJECT sig_sphincs_sha256_128s_simple.c pqclean_sphincs-sha256-128s-simple_clean/address.c pqclean_sphincs-sha256-128s-simple_clean/fors.c pqclean_sphincs-sha256-128s-simple_clean/hash_sha256.c pqclean_sphincs-sha256-128s-simple_clean/sha256.c pqclean_sphincs-sha256-128s-simple_clean/sign.c pqclean_sphincs-sha256-128s-simple_clean/thash_sha256_simple.c pqclean_sphincs-sha256-128s-simple_clean/utils.c pqclean_sphincs-sha256-128s-simple_clean/wots.c) - target_include_directories(sphincs_sha256_128s_simple_clean PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-sha256-128s-simple_clean) + add_library(sphincs_sha256_128s_simple_clean OBJECT sig_sphincs_sha256_128s_simple.c pqclean_sphincs-sha2-128s-simple_clean/address.c pqclean_sphincs-sha2-128s-simple_clean/context_sha2.c pqclean_sphincs-sha2-128s-simple_clean/fors.c pqclean_sphincs-sha2-128s-simple_clean/hash_sha2.c pqclean_sphincs-sha2-128s-simple_clean/merkle.c pqclean_sphincs-sha2-128s-simple_clean/sign.c pqclean_sphincs-sha2-128s-simple_clean/thash_sha2_simple.c pqclean_sphincs-sha2-128s-simple_clean/utils.c pqclean_sphincs-sha2-128s-simple_clean/utilsx1.c pqclean_sphincs-sha2-128s-simple_clean/wots.c pqclean_sphincs-sha2-128s-simple_clean/wotsx1.c) + target_include_directories(sphincs_sha256_128s_simple_clean PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-sha2-128s-simple_clean) target_include_directories(sphincs_sha256_128s_simple_clean PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) endif() if(OQS_ENABLE_SIG_sphincs_sha256_128s_simple_avx2) - add_library(sphincs_sha256_128s_simple_avx2 OBJECT pqclean_sphincs-sha256-128s-simple_avx2/address.c pqclean_sphincs-sha256-128s-simple_avx2/fors.c pqclean_sphincs-sha256-128s-simple_avx2/hash_sha256.c pqclean_sphincs-sha256-128s-simple_avx2/hash_sha256x8.c pqclean_sphincs-sha256-128s-simple_avx2/sha256.c pqclean_sphincs-sha256-128s-simple_avx2/sha256avx.c pqclean_sphincs-sha256-128s-simple_avx2/sha256x8.c pqclean_sphincs-sha256-128s-simple_avx2/sign.c pqclean_sphincs-sha256-128s-simple_avx2/thash_sha256_simple.c pqclean_sphincs-sha256-128s-simple_avx2/thash_sha256_simplex8.c pqclean_sphincs-sha256-128s-simple_avx2/utils.c pqclean_sphincs-sha256-128s-simple_avx2/utilsx8.c pqclean_sphincs-sha256-128s-simple_avx2/wots.c) - target_include_directories(sphincs_sha256_128s_simple_avx2 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-sha256-128s-simple_avx2) + add_library(sphincs_sha256_128s_simple_avx2 OBJECT pqclean_sphincs-sha2-128s-simple_avx2/address.c pqclean_sphincs-sha2-128s-simple_avx2/context_sha2.c pqclean_sphincs-sha2-128s-simple_avx2/fors.c pqclean_sphincs-sha2-128s-simple_avx2/hash_sha2.c pqclean_sphincs-sha2-128s-simple_avx2/hash_sha2x8.c pqclean_sphincs-sha2-128s-simple_avx2/merkle.c pqclean_sphincs-sha2-128s-simple_avx2/sha256avx.c pqclean_sphincs-sha2-128s-simple_avx2/sha256x8.c pqclean_sphincs-sha2-128s-simple_avx2/sign.c pqclean_sphincs-sha2-128s-simple_avx2/thash_sha2_simple.c pqclean_sphincs-sha2-128s-simple_avx2/thash_sha2_simplex8.c pqclean_sphincs-sha2-128s-simple_avx2/utils.c pqclean_sphincs-sha2-128s-simple_avx2/utilsx8.c pqclean_sphincs-sha2-128s-simple_avx2/wots.c) + target_include_directories(sphincs_sha256_128s_simple_avx2 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-sha2-128s-simple_avx2) target_include_directories(sphincs_sha256_128s_simple_avx2 PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) target_compile_options(sphincs_sha256_128s_simple_avx2 PRIVATE -mavx2) set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) endif() if(OQS_ENABLE_SIG_sphincs_sha256_192f_robust) - add_library(sphincs_sha256_192f_robust_clean OBJECT sig_sphincs_sha256_192f_robust.c pqclean_sphincs-sha256-192f-robust_clean/address.c pqclean_sphincs-sha256-192f-robust_clean/fors.c pqclean_sphincs-sha256-192f-robust_clean/hash_sha256.c pqclean_sphincs-sha256-192f-robust_clean/sha256.c pqclean_sphincs-sha256-192f-robust_clean/sign.c pqclean_sphincs-sha256-192f-robust_clean/thash_sha256_robust.c pqclean_sphincs-sha256-192f-robust_clean/utils.c pqclean_sphincs-sha256-192f-robust_clean/wots.c) - target_include_directories(sphincs_sha256_192f_robust_clean PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-sha256-192f-robust_clean) + add_library(sphincs_sha256_192f_robust_clean OBJECT sig_sphincs_sha256_192f_robust.c pqclean_sphincs-sha2-192f-robust_clean/address.c pqclean_sphincs-sha2-192f-robust_clean/context_sha2.c pqclean_sphincs-sha2-192f-robust_clean/fors.c pqclean_sphincs-sha2-192f-robust_clean/hash_sha2.c pqclean_sphincs-sha2-192f-robust_clean/merkle.c pqclean_sphincs-sha2-192f-robust_clean/sign.c pqclean_sphincs-sha2-192f-robust_clean/thash_sha2_robust.c pqclean_sphincs-sha2-192f-robust_clean/utils.c pqclean_sphincs-sha2-192f-robust_clean/utilsx1.c pqclean_sphincs-sha2-192f-robust_clean/wots.c pqclean_sphincs-sha2-192f-robust_clean/wotsx1.c) + target_include_directories(sphincs_sha256_192f_robust_clean PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-sha2-192f-robust_clean) target_include_directories(sphincs_sha256_192f_robust_clean PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) endif() if(OQS_ENABLE_SIG_sphincs_sha256_192f_robust_avx2) - add_library(sphincs_sha256_192f_robust_avx2 OBJECT pqclean_sphincs-sha256-192f-robust_avx2/address.c pqclean_sphincs-sha256-192f-robust_avx2/fors.c pqclean_sphincs-sha256-192f-robust_avx2/hash_sha256.c pqclean_sphincs-sha256-192f-robust_avx2/hash_sha256x8.c pqclean_sphincs-sha256-192f-robust_avx2/sha256.c pqclean_sphincs-sha256-192f-robust_avx2/sha256avx.c pqclean_sphincs-sha256-192f-robust_avx2/sha256x8.c pqclean_sphincs-sha256-192f-robust_avx2/sign.c pqclean_sphincs-sha256-192f-robust_avx2/thash_sha256_robust.c pqclean_sphincs-sha256-192f-robust_avx2/thash_sha256_robustx8.c pqclean_sphincs-sha256-192f-robust_avx2/utils.c pqclean_sphincs-sha256-192f-robust_avx2/utilsx8.c pqclean_sphincs-sha256-192f-robust_avx2/wots.c) - target_include_directories(sphincs_sha256_192f_robust_avx2 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-sha256-192f-robust_avx2) + add_library(sphincs_sha256_192f_robust_avx2 OBJECT pqclean_sphincs-sha2-192f-robust_avx2/address.c pqclean_sphincs-sha2-192f-robust_avx2/context_sha2.c pqclean_sphincs-sha2-192f-robust_avx2/fors.c pqclean_sphincs-sha2-192f-robust_avx2/hash_sha2.c pqclean_sphincs-sha2-192f-robust_avx2/hash_sha2x8.c pqclean_sphincs-sha2-192f-robust_avx2/merkle.c pqclean_sphincs-sha2-192f-robust_avx2/sha256avx.c pqclean_sphincs-sha2-192f-robust_avx2/sha256x8.c pqclean_sphincs-sha2-192f-robust_avx2/sha512x4.c pqclean_sphincs-sha2-192f-robust_avx2/sign.c pqclean_sphincs-sha2-192f-robust_avx2/thash_sha2_robust.c pqclean_sphincs-sha2-192f-robust_avx2/thash_sha2_robustx8.c pqclean_sphincs-sha2-192f-robust_avx2/utils.c pqclean_sphincs-sha2-192f-robust_avx2/utilsx8.c pqclean_sphincs-sha2-192f-robust_avx2/wots.c) + target_include_directories(sphincs_sha256_192f_robust_avx2 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-sha2-192f-robust_avx2) target_include_directories(sphincs_sha256_192f_robust_avx2 PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) target_compile_options(sphincs_sha256_192f_robust_avx2 PRIVATE -mavx2) set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) endif() if(OQS_ENABLE_SIG_sphincs_sha256_192f_simple) - add_library(sphincs_sha256_192f_simple_clean OBJECT sig_sphincs_sha256_192f_simple.c pqclean_sphincs-sha256-192f-simple_clean/address.c pqclean_sphincs-sha256-192f-simple_clean/fors.c pqclean_sphincs-sha256-192f-simple_clean/hash_sha256.c pqclean_sphincs-sha256-192f-simple_clean/sha256.c pqclean_sphincs-sha256-192f-simple_clean/sign.c pqclean_sphincs-sha256-192f-simple_clean/thash_sha256_simple.c pqclean_sphincs-sha256-192f-simple_clean/utils.c pqclean_sphincs-sha256-192f-simple_clean/wots.c) - target_include_directories(sphincs_sha256_192f_simple_clean PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-sha256-192f-simple_clean) + add_library(sphincs_sha256_192f_simple_clean OBJECT sig_sphincs_sha256_192f_simple.c pqclean_sphincs-sha2-192f-simple_clean/address.c pqclean_sphincs-sha2-192f-simple_clean/context_sha2.c pqclean_sphincs-sha2-192f-simple_clean/fors.c pqclean_sphincs-sha2-192f-simple_clean/hash_sha2.c pqclean_sphincs-sha2-192f-simple_clean/merkle.c pqclean_sphincs-sha2-192f-simple_clean/sign.c pqclean_sphincs-sha2-192f-simple_clean/thash_sha2_simple.c pqclean_sphincs-sha2-192f-simple_clean/utils.c pqclean_sphincs-sha2-192f-simple_clean/utilsx1.c pqclean_sphincs-sha2-192f-simple_clean/wots.c pqclean_sphincs-sha2-192f-simple_clean/wotsx1.c) + target_include_directories(sphincs_sha256_192f_simple_clean PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-sha2-192f-simple_clean) target_include_directories(sphincs_sha256_192f_simple_clean PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) endif() if(OQS_ENABLE_SIG_sphincs_sha256_192f_simple_avx2) - add_library(sphincs_sha256_192f_simple_avx2 OBJECT pqclean_sphincs-sha256-192f-simple_avx2/address.c pqclean_sphincs-sha256-192f-simple_avx2/fors.c pqclean_sphincs-sha256-192f-simple_avx2/hash_sha256.c pqclean_sphincs-sha256-192f-simple_avx2/hash_sha256x8.c pqclean_sphincs-sha256-192f-simple_avx2/sha256.c pqclean_sphincs-sha256-192f-simple_avx2/sha256avx.c pqclean_sphincs-sha256-192f-simple_avx2/sha256x8.c pqclean_sphincs-sha256-192f-simple_avx2/sign.c pqclean_sphincs-sha256-192f-simple_avx2/thash_sha256_simple.c pqclean_sphincs-sha256-192f-simple_avx2/thash_sha256_simplex8.c pqclean_sphincs-sha256-192f-simple_avx2/utils.c pqclean_sphincs-sha256-192f-simple_avx2/utilsx8.c pqclean_sphincs-sha256-192f-simple_avx2/wots.c) - target_include_directories(sphincs_sha256_192f_simple_avx2 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-sha256-192f-simple_avx2) + add_library(sphincs_sha256_192f_simple_avx2 OBJECT pqclean_sphincs-sha2-192f-simple_avx2/address.c pqclean_sphincs-sha2-192f-simple_avx2/context_sha2.c pqclean_sphincs-sha2-192f-simple_avx2/fors.c pqclean_sphincs-sha2-192f-simple_avx2/hash_sha2.c pqclean_sphincs-sha2-192f-simple_avx2/hash_sha2x8.c pqclean_sphincs-sha2-192f-simple_avx2/merkle.c pqclean_sphincs-sha2-192f-simple_avx2/sha256avx.c pqclean_sphincs-sha2-192f-simple_avx2/sha256x8.c pqclean_sphincs-sha2-192f-simple_avx2/sha512x4.c pqclean_sphincs-sha2-192f-simple_avx2/sign.c pqclean_sphincs-sha2-192f-simple_avx2/thash_sha2_simple.c pqclean_sphincs-sha2-192f-simple_avx2/thash_sha2_simplex8.c pqclean_sphincs-sha2-192f-simple_avx2/utils.c pqclean_sphincs-sha2-192f-simple_avx2/utilsx8.c pqclean_sphincs-sha2-192f-simple_avx2/wots.c) + target_include_directories(sphincs_sha256_192f_simple_avx2 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-sha2-192f-simple_avx2) target_include_directories(sphincs_sha256_192f_simple_avx2 PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) target_compile_options(sphincs_sha256_192f_simple_avx2 PRIVATE -mavx2) set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) endif() if(OQS_ENABLE_SIG_sphincs_sha256_192s_robust) - add_library(sphincs_sha256_192s_robust_clean OBJECT sig_sphincs_sha256_192s_robust.c pqclean_sphincs-sha256-192s-robust_clean/address.c pqclean_sphincs-sha256-192s-robust_clean/fors.c pqclean_sphincs-sha256-192s-robust_clean/hash_sha256.c pqclean_sphincs-sha256-192s-robust_clean/sha256.c pqclean_sphincs-sha256-192s-robust_clean/sign.c pqclean_sphincs-sha256-192s-robust_clean/thash_sha256_robust.c pqclean_sphincs-sha256-192s-robust_clean/utils.c pqclean_sphincs-sha256-192s-robust_clean/wots.c) - target_include_directories(sphincs_sha256_192s_robust_clean PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-sha256-192s-robust_clean) + add_library(sphincs_sha256_192s_robust_clean OBJECT sig_sphincs_sha256_192s_robust.c pqclean_sphincs-sha2-192s-robust_clean/address.c pqclean_sphincs-sha2-192s-robust_clean/context_sha2.c pqclean_sphincs-sha2-192s-robust_clean/fors.c pqclean_sphincs-sha2-192s-robust_clean/hash_sha2.c pqclean_sphincs-sha2-192s-robust_clean/merkle.c pqclean_sphincs-sha2-192s-robust_clean/sign.c pqclean_sphincs-sha2-192s-robust_clean/thash_sha2_robust.c pqclean_sphincs-sha2-192s-robust_clean/utils.c pqclean_sphincs-sha2-192s-robust_clean/utilsx1.c pqclean_sphincs-sha2-192s-robust_clean/wots.c pqclean_sphincs-sha2-192s-robust_clean/wotsx1.c) + target_include_directories(sphincs_sha256_192s_robust_clean PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-sha2-192s-robust_clean) target_include_directories(sphincs_sha256_192s_robust_clean PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) endif() if(OQS_ENABLE_SIG_sphincs_sha256_192s_robust_avx2) - add_library(sphincs_sha256_192s_robust_avx2 OBJECT pqclean_sphincs-sha256-192s-robust_avx2/address.c pqclean_sphincs-sha256-192s-robust_avx2/fors.c pqclean_sphincs-sha256-192s-robust_avx2/hash_sha256.c pqclean_sphincs-sha256-192s-robust_avx2/hash_sha256x8.c pqclean_sphincs-sha256-192s-robust_avx2/sha256.c pqclean_sphincs-sha256-192s-robust_avx2/sha256avx.c pqclean_sphincs-sha256-192s-robust_avx2/sha256x8.c pqclean_sphincs-sha256-192s-robust_avx2/sign.c pqclean_sphincs-sha256-192s-robust_avx2/thash_sha256_robust.c pqclean_sphincs-sha256-192s-robust_avx2/thash_sha256_robustx8.c pqclean_sphincs-sha256-192s-robust_avx2/utils.c pqclean_sphincs-sha256-192s-robust_avx2/utilsx8.c pqclean_sphincs-sha256-192s-robust_avx2/wots.c) - target_include_directories(sphincs_sha256_192s_robust_avx2 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-sha256-192s-robust_avx2) + add_library(sphincs_sha256_192s_robust_avx2 OBJECT pqclean_sphincs-sha2-192s-robust_avx2/address.c pqclean_sphincs-sha2-192s-robust_avx2/context_sha2.c pqclean_sphincs-sha2-192s-robust_avx2/fors.c pqclean_sphincs-sha2-192s-robust_avx2/hash_sha2.c pqclean_sphincs-sha2-192s-robust_avx2/hash_sha2x8.c pqclean_sphincs-sha2-192s-robust_avx2/merkle.c pqclean_sphincs-sha2-192s-robust_avx2/sha256avx.c pqclean_sphincs-sha2-192s-robust_avx2/sha256x8.c pqclean_sphincs-sha2-192s-robust_avx2/sha512x4.c pqclean_sphincs-sha2-192s-robust_avx2/sign.c pqclean_sphincs-sha2-192s-robust_avx2/thash_sha2_robust.c pqclean_sphincs-sha2-192s-robust_avx2/thash_sha2_robustx8.c pqclean_sphincs-sha2-192s-robust_avx2/utils.c pqclean_sphincs-sha2-192s-robust_avx2/utilsx8.c pqclean_sphincs-sha2-192s-robust_avx2/wots.c) + target_include_directories(sphincs_sha256_192s_robust_avx2 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-sha2-192s-robust_avx2) target_include_directories(sphincs_sha256_192s_robust_avx2 PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) target_compile_options(sphincs_sha256_192s_robust_avx2 PRIVATE -mavx2) set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) endif() if(OQS_ENABLE_SIG_sphincs_sha256_192s_simple) - add_library(sphincs_sha256_192s_simple_clean OBJECT sig_sphincs_sha256_192s_simple.c pqclean_sphincs-sha256-192s-simple_clean/address.c pqclean_sphincs-sha256-192s-simple_clean/fors.c pqclean_sphincs-sha256-192s-simple_clean/hash_sha256.c pqclean_sphincs-sha256-192s-simple_clean/sha256.c pqclean_sphincs-sha256-192s-simple_clean/sign.c pqclean_sphincs-sha256-192s-simple_clean/thash_sha256_simple.c pqclean_sphincs-sha256-192s-simple_clean/utils.c pqclean_sphincs-sha256-192s-simple_clean/wots.c) - target_include_directories(sphincs_sha256_192s_simple_clean PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-sha256-192s-simple_clean) + add_library(sphincs_sha256_192s_simple_clean OBJECT sig_sphincs_sha256_192s_simple.c pqclean_sphincs-sha2-192s-simple_clean/address.c pqclean_sphincs-sha2-192s-simple_clean/context_sha2.c pqclean_sphincs-sha2-192s-simple_clean/fors.c pqclean_sphincs-sha2-192s-simple_clean/hash_sha2.c pqclean_sphincs-sha2-192s-simple_clean/merkle.c pqclean_sphincs-sha2-192s-simple_clean/sign.c pqclean_sphincs-sha2-192s-simple_clean/thash_sha2_simple.c pqclean_sphincs-sha2-192s-simple_clean/utils.c pqclean_sphincs-sha2-192s-simple_clean/utilsx1.c pqclean_sphincs-sha2-192s-simple_clean/wots.c pqclean_sphincs-sha2-192s-simple_clean/wotsx1.c) + target_include_directories(sphincs_sha256_192s_simple_clean PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-sha2-192s-simple_clean) target_include_directories(sphincs_sha256_192s_simple_clean PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) endif() if(OQS_ENABLE_SIG_sphincs_sha256_192s_simple_avx2) - add_library(sphincs_sha256_192s_simple_avx2 OBJECT pqclean_sphincs-sha256-192s-simple_avx2/address.c pqclean_sphincs-sha256-192s-simple_avx2/fors.c pqclean_sphincs-sha256-192s-simple_avx2/hash_sha256.c pqclean_sphincs-sha256-192s-simple_avx2/hash_sha256x8.c pqclean_sphincs-sha256-192s-simple_avx2/sha256.c pqclean_sphincs-sha256-192s-simple_avx2/sha256avx.c pqclean_sphincs-sha256-192s-simple_avx2/sha256x8.c pqclean_sphincs-sha256-192s-simple_avx2/sign.c pqclean_sphincs-sha256-192s-simple_avx2/thash_sha256_simple.c pqclean_sphincs-sha256-192s-simple_avx2/thash_sha256_simplex8.c pqclean_sphincs-sha256-192s-simple_avx2/utils.c pqclean_sphincs-sha256-192s-simple_avx2/utilsx8.c pqclean_sphincs-sha256-192s-simple_avx2/wots.c) - target_include_directories(sphincs_sha256_192s_simple_avx2 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-sha256-192s-simple_avx2) + add_library(sphincs_sha256_192s_simple_avx2 OBJECT pqclean_sphincs-sha2-192s-simple_avx2/address.c pqclean_sphincs-sha2-192s-simple_avx2/context_sha2.c pqclean_sphincs-sha2-192s-simple_avx2/fors.c pqclean_sphincs-sha2-192s-simple_avx2/hash_sha2.c pqclean_sphincs-sha2-192s-simple_avx2/hash_sha2x8.c pqclean_sphincs-sha2-192s-simple_avx2/merkle.c pqclean_sphincs-sha2-192s-simple_avx2/sha256avx.c pqclean_sphincs-sha2-192s-simple_avx2/sha256x8.c pqclean_sphincs-sha2-192s-simple_avx2/sha512x4.c pqclean_sphincs-sha2-192s-simple_avx2/sign.c pqclean_sphincs-sha2-192s-simple_avx2/thash_sha2_simple.c pqclean_sphincs-sha2-192s-simple_avx2/thash_sha2_simplex8.c pqclean_sphincs-sha2-192s-simple_avx2/utils.c pqclean_sphincs-sha2-192s-simple_avx2/utilsx8.c pqclean_sphincs-sha2-192s-simple_avx2/wots.c) + target_include_directories(sphincs_sha256_192s_simple_avx2 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-sha2-192s-simple_avx2) target_include_directories(sphincs_sha256_192s_simple_avx2 PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) target_compile_options(sphincs_sha256_192s_simple_avx2 PRIVATE -mavx2) set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) endif() if(OQS_ENABLE_SIG_sphincs_sha256_256f_robust) - add_library(sphincs_sha256_256f_robust_clean OBJECT sig_sphincs_sha256_256f_robust.c pqclean_sphincs-sha256-256f-robust_clean/address.c pqclean_sphincs-sha256-256f-robust_clean/fors.c pqclean_sphincs-sha256-256f-robust_clean/hash_sha256.c pqclean_sphincs-sha256-256f-robust_clean/sha256.c pqclean_sphincs-sha256-256f-robust_clean/sign.c pqclean_sphincs-sha256-256f-robust_clean/thash_sha256_robust.c pqclean_sphincs-sha256-256f-robust_clean/utils.c pqclean_sphincs-sha256-256f-robust_clean/wots.c) - target_include_directories(sphincs_sha256_256f_robust_clean PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-sha256-256f-robust_clean) + add_library(sphincs_sha256_256f_robust_clean OBJECT sig_sphincs_sha256_256f_robust.c pqclean_sphincs-sha2-256f-robust_clean/address.c pqclean_sphincs-sha2-256f-robust_clean/context_sha2.c pqclean_sphincs-sha2-256f-robust_clean/fors.c pqclean_sphincs-sha2-256f-robust_clean/hash_sha2.c pqclean_sphincs-sha2-256f-robust_clean/merkle.c pqclean_sphincs-sha2-256f-robust_clean/sign.c pqclean_sphincs-sha2-256f-robust_clean/thash_sha2_robust.c pqclean_sphincs-sha2-256f-robust_clean/utils.c pqclean_sphincs-sha2-256f-robust_clean/utilsx1.c pqclean_sphincs-sha2-256f-robust_clean/wots.c pqclean_sphincs-sha2-256f-robust_clean/wotsx1.c) + target_include_directories(sphincs_sha256_256f_robust_clean PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-sha2-256f-robust_clean) target_include_directories(sphincs_sha256_256f_robust_clean PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) endif() if(OQS_ENABLE_SIG_sphincs_sha256_256f_robust_avx2) - add_library(sphincs_sha256_256f_robust_avx2 OBJECT pqclean_sphincs-sha256-256f-robust_avx2/address.c pqclean_sphincs-sha256-256f-robust_avx2/fors.c pqclean_sphincs-sha256-256f-robust_avx2/hash_sha256.c pqclean_sphincs-sha256-256f-robust_avx2/hash_sha256x8.c pqclean_sphincs-sha256-256f-robust_avx2/sha256.c pqclean_sphincs-sha256-256f-robust_avx2/sha256avx.c pqclean_sphincs-sha256-256f-robust_avx2/sha256x8.c pqclean_sphincs-sha256-256f-robust_avx2/sign.c pqclean_sphincs-sha256-256f-robust_avx2/thash_sha256_robust.c pqclean_sphincs-sha256-256f-robust_avx2/thash_sha256_robustx8.c pqclean_sphincs-sha256-256f-robust_avx2/utils.c pqclean_sphincs-sha256-256f-robust_avx2/utilsx8.c pqclean_sphincs-sha256-256f-robust_avx2/wots.c) - target_include_directories(sphincs_sha256_256f_robust_avx2 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-sha256-256f-robust_avx2) + add_library(sphincs_sha256_256f_robust_avx2 OBJECT pqclean_sphincs-sha2-256f-robust_avx2/address.c pqclean_sphincs-sha2-256f-robust_avx2/context_sha2.c pqclean_sphincs-sha2-256f-robust_avx2/fors.c pqclean_sphincs-sha2-256f-robust_avx2/hash_sha2.c pqclean_sphincs-sha2-256f-robust_avx2/hash_sha2x8.c pqclean_sphincs-sha2-256f-robust_avx2/merkle.c pqclean_sphincs-sha2-256f-robust_avx2/sha256avx.c pqclean_sphincs-sha2-256f-robust_avx2/sha256x8.c pqclean_sphincs-sha2-256f-robust_avx2/sha512x4.c pqclean_sphincs-sha2-256f-robust_avx2/sign.c pqclean_sphincs-sha2-256f-robust_avx2/thash_sha2_robust.c pqclean_sphincs-sha2-256f-robust_avx2/thash_sha2_robustx8.c pqclean_sphincs-sha2-256f-robust_avx2/utils.c pqclean_sphincs-sha2-256f-robust_avx2/utilsx8.c pqclean_sphincs-sha2-256f-robust_avx2/wots.c) + target_include_directories(sphincs_sha256_256f_robust_avx2 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-sha2-256f-robust_avx2) target_include_directories(sphincs_sha256_256f_robust_avx2 PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) target_compile_options(sphincs_sha256_256f_robust_avx2 PRIVATE -mavx2) set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) endif() if(OQS_ENABLE_SIG_sphincs_sha256_256f_simple) - add_library(sphincs_sha256_256f_simple_clean OBJECT sig_sphincs_sha256_256f_simple.c pqclean_sphincs-sha256-256f-simple_clean/address.c pqclean_sphincs-sha256-256f-simple_clean/fors.c pqclean_sphincs-sha256-256f-simple_clean/hash_sha256.c pqclean_sphincs-sha256-256f-simple_clean/sha256.c pqclean_sphincs-sha256-256f-simple_clean/sign.c pqclean_sphincs-sha256-256f-simple_clean/thash_sha256_simple.c pqclean_sphincs-sha256-256f-simple_clean/utils.c pqclean_sphincs-sha256-256f-simple_clean/wots.c) - target_include_directories(sphincs_sha256_256f_simple_clean PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-sha256-256f-simple_clean) + add_library(sphincs_sha256_256f_simple_clean OBJECT sig_sphincs_sha256_256f_simple.c pqclean_sphincs-sha2-256f-simple_clean/address.c pqclean_sphincs-sha2-256f-simple_clean/context_sha2.c pqclean_sphincs-sha2-256f-simple_clean/fors.c pqclean_sphincs-sha2-256f-simple_clean/hash_sha2.c pqclean_sphincs-sha2-256f-simple_clean/merkle.c pqclean_sphincs-sha2-256f-simple_clean/sign.c pqclean_sphincs-sha2-256f-simple_clean/thash_sha2_simple.c pqclean_sphincs-sha2-256f-simple_clean/utils.c pqclean_sphincs-sha2-256f-simple_clean/utilsx1.c pqclean_sphincs-sha2-256f-simple_clean/wots.c pqclean_sphincs-sha2-256f-simple_clean/wotsx1.c) + target_include_directories(sphincs_sha256_256f_simple_clean PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-sha2-256f-simple_clean) target_include_directories(sphincs_sha256_256f_simple_clean PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) endif() if(OQS_ENABLE_SIG_sphincs_sha256_256f_simple_avx2) - add_library(sphincs_sha256_256f_simple_avx2 OBJECT pqclean_sphincs-sha256-256f-simple_avx2/address.c pqclean_sphincs-sha256-256f-simple_avx2/fors.c pqclean_sphincs-sha256-256f-simple_avx2/hash_sha256.c pqclean_sphincs-sha256-256f-simple_avx2/hash_sha256x8.c pqclean_sphincs-sha256-256f-simple_avx2/sha256.c pqclean_sphincs-sha256-256f-simple_avx2/sha256avx.c pqclean_sphincs-sha256-256f-simple_avx2/sha256x8.c pqclean_sphincs-sha256-256f-simple_avx2/sign.c pqclean_sphincs-sha256-256f-simple_avx2/thash_sha256_simple.c pqclean_sphincs-sha256-256f-simple_avx2/thash_sha256_simplex8.c pqclean_sphincs-sha256-256f-simple_avx2/utils.c pqclean_sphincs-sha256-256f-simple_avx2/utilsx8.c pqclean_sphincs-sha256-256f-simple_avx2/wots.c) - target_include_directories(sphincs_sha256_256f_simple_avx2 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-sha256-256f-simple_avx2) + add_library(sphincs_sha256_256f_simple_avx2 OBJECT pqclean_sphincs-sha2-256f-simple_avx2/address.c pqclean_sphincs-sha2-256f-simple_avx2/context_sha2.c pqclean_sphincs-sha2-256f-simple_avx2/fors.c pqclean_sphincs-sha2-256f-simple_avx2/hash_sha2.c pqclean_sphincs-sha2-256f-simple_avx2/hash_sha2x8.c pqclean_sphincs-sha2-256f-simple_avx2/merkle.c pqclean_sphincs-sha2-256f-simple_avx2/sha256avx.c pqclean_sphincs-sha2-256f-simple_avx2/sha256x8.c pqclean_sphincs-sha2-256f-simple_avx2/sha512x4.c pqclean_sphincs-sha2-256f-simple_avx2/sign.c pqclean_sphincs-sha2-256f-simple_avx2/thash_sha2_simple.c pqclean_sphincs-sha2-256f-simple_avx2/thash_sha2_simplex8.c pqclean_sphincs-sha2-256f-simple_avx2/utils.c pqclean_sphincs-sha2-256f-simple_avx2/utilsx8.c pqclean_sphincs-sha2-256f-simple_avx2/wots.c) + target_include_directories(sphincs_sha256_256f_simple_avx2 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-sha2-256f-simple_avx2) target_include_directories(sphincs_sha256_256f_simple_avx2 PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) target_compile_options(sphincs_sha256_256f_simple_avx2 PRIVATE -mavx2) set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) endif() if(OQS_ENABLE_SIG_sphincs_sha256_256s_robust) - add_library(sphincs_sha256_256s_robust_clean OBJECT sig_sphincs_sha256_256s_robust.c pqclean_sphincs-sha256-256s-robust_clean/address.c pqclean_sphincs-sha256-256s-robust_clean/fors.c pqclean_sphincs-sha256-256s-robust_clean/hash_sha256.c pqclean_sphincs-sha256-256s-robust_clean/sha256.c pqclean_sphincs-sha256-256s-robust_clean/sign.c pqclean_sphincs-sha256-256s-robust_clean/thash_sha256_robust.c pqclean_sphincs-sha256-256s-robust_clean/utils.c pqclean_sphincs-sha256-256s-robust_clean/wots.c) - target_include_directories(sphincs_sha256_256s_robust_clean PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-sha256-256s-robust_clean) + add_library(sphincs_sha256_256s_robust_clean OBJECT sig_sphincs_sha256_256s_robust.c pqclean_sphincs-sha2-256s-robust_clean/address.c pqclean_sphincs-sha2-256s-robust_clean/context_sha2.c pqclean_sphincs-sha2-256s-robust_clean/fors.c pqclean_sphincs-sha2-256s-robust_clean/hash_sha2.c pqclean_sphincs-sha2-256s-robust_clean/merkle.c pqclean_sphincs-sha2-256s-robust_clean/sign.c pqclean_sphincs-sha2-256s-robust_clean/thash_sha2_robust.c pqclean_sphincs-sha2-256s-robust_clean/utils.c pqclean_sphincs-sha2-256s-robust_clean/utilsx1.c pqclean_sphincs-sha2-256s-robust_clean/wots.c pqclean_sphincs-sha2-256s-robust_clean/wotsx1.c) + target_include_directories(sphincs_sha256_256s_robust_clean PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-sha2-256s-robust_clean) target_include_directories(sphincs_sha256_256s_robust_clean PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) endif() if(OQS_ENABLE_SIG_sphincs_sha256_256s_robust_avx2) - add_library(sphincs_sha256_256s_robust_avx2 OBJECT pqclean_sphincs-sha256-256s-robust_avx2/address.c pqclean_sphincs-sha256-256s-robust_avx2/fors.c pqclean_sphincs-sha256-256s-robust_avx2/hash_sha256.c pqclean_sphincs-sha256-256s-robust_avx2/hash_sha256x8.c pqclean_sphincs-sha256-256s-robust_avx2/sha256.c pqclean_sphincs-sha256-256s-robust_avx2/sha256avx.c pqclean_sphincs-sha256-256s-robust_avx2/sha256x8.c pqclean_sphincs-sha256-256s-robust_avx2/sign.c pqclean_sphincs-sha256-256s-robust_avx2/thash_sha256_robust.c pqclean_sphincs-sha256-256s-robust_avx2/thash_sha256_robustx8.c pqclean_sphincs-sha256-256s-robust_avx2/utils.c pqclean_sphincs-sha256-256s-robust_avx2/utilsx8.c pqclean_sphincs-sha256-256s-robust_avx2/wots.c) - target_include_directories(sphincs_sha256_256s_robust_avx2 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-sha256-256s-robust_avx2) + add_library(sphincs_sha256_256s_robust_avx2 OBJECT pqclean_sphincs-sha2-256s-robust_avx2/address.c pqclean_sphincs-sha2-256s-robust_avx2/context_sha2.c pqclean_sphincs-sha2-256s-robust_avx2/fors.c pqclean_sphincs-sha2-256s-robust_avx2/hash_sha2.c pqclean_sphincs-sha2-256s-robust_avx2/hash_sha2x8.c pqclean_sphincs-sha2-256s-robust_avx2/merkle.c pqclean_sphincs-sha2-256s-robust_avx2/sha256avx.c pqclean_sphincs-sha2-256s-robust_avx2/sha256x8.c pqclean_sphincs-sha2-256s-robust_avx2/sha512x4.c pqclean_sphincs-sha2-256s-robust_avx2/sign.c pqclean_sphincs-sha2-256s-robust_avx2/thash_sha2_robust.c pqclean_sphincs-sha2-256s-robust_avx2/thash_sha2_robustx8.c pqclean_sphincs-sha2-256s-robust_avx2/utils.c pqclean_sphincs-sha2-256s-robust_avx2/utilsx8.c pqclean_sphincs-sha2-256s-robust_avx2/wots.c) + target_include_directories(sphincs_sha256_256s_robust_avx2 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-sha2-256s-robust_avx2) target_include_directories(sphincs_sha256_256s_robust_avx2 PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) target_compile_options(sphincs_sha256_256s_robust_avx2 PRIVATE -mavx2) set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) endif() if(OQS_ENABLE_SIG_sphincs_sha256_256s_simple) - add_library(sphincs_sha256_256s_simple_clean OBJECT sig_sphincs_sha256_256s_simple.c pqclean_sphincs-sha256-256s-simple_clean/address.c pqclean_sphincs-sha256-256s-simple_clean/fors.c pqclean_sphincs-sha256-256s-simple_clean/hash_sha256.c pqclean_sphincs-sha256-256s-simple_clean/sha256.c pqclean_sphincs-sha256-256s-simple_clean/sign.c pqclean_sphincs-sha256-256s-simple_clean/thash_sha256_simple.c pqclean_sphincs-sha256-256s-simple_clean/utils.c pqclean_sphincs-sha256-256s-simple_clean/wots.c) - target_include_directories(sphincs_sha256_256s_simple_clean PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-sha256-256s-simple_clean) + add_library(sphincs_sha256_256s_simple_clean OBJECT sig_sphincs_sha256_256s_simple.c pqclean_sphincs-sha2-256s-simple_clean/address.c pqclean_sphincs-sha2-256s-simple_clean/context_sha2.c pqclean_sphincs-sha2-256s-simple_clean/fors.c pqclean_sphincs-sha2-256s-simple_clean/hash_sha2.c pqclean_sphincs-sha2-256s-simple_clean/merkle.c pqclean_sphincs-sha2-256s-simple_clean/sign.c pqclean_sphincs-sha2-256s-simple_clean/thash_sha2_simple.c pqclean_sphincs-sha2-256s-simple_clean/utils.c pqclean_sphincs-sha2-256s-simple_clean/utilsx1.c pqclean_sphincs-sha2-256s-simple_clean/wots.c pqclean_sphincs-sha2-256s-simple_clean/wotsx1.c) + target_include_directories(sphincs_sha256_256s_simple_clean PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-sha2-256s-simple_clean) target_include_directories(sphincs_sha256_256s_simple_clean PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) endif() if(OQS_ENABLE_SIG_sphincs_sha256_256s_simple_avx2) - add_library(sphincs_sha256_256s_simple_avx2 OBJECT pqclean_sphincs-sha256-256s-simple_avx2/address.c pqclean_sphincs-sha256-256s-simple_avx2/fors.c pqclean_sphincs-sha256-256s-simple_avx2/hash_sha256.c pqclean_sphincs-sha256-256s-simple_avx2/hash_sha256x8.c pqclean_sphincs-sha256-256s-simple_avx2/sha256.c pqclean_sphincs-sha256-256s-simple_avx2/sha256avx.c pqclean_sphincs-sha256-256s-simple_avx2/sha256x8.c pqclean_sphincs-sha256-256s-simple_avx2/sign.c pqclean_sphincs-sha256-256s-simple_avx2/thash_sha256_simple.c pqclean_sphincs-sha256-256s-simple_avx2/thash_sha256_simplex8.c pqclean_sphincs-sha256-256s-simple_avx2/utils.c pqclean_sphincs-sha256-256s-simple_avx2/utilsx8.c pqclean_sphincs-sha256-256s-simple_avx2/wots.c) - target_include_directories(sphincs_sha256_256s_simple_avx2 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-sha256-256s-simple_avx2) + add_library(sphincs_sha256_256s_simple_avx2 OBJECT pqclean_sphincs-sha2-256s-simple_avx2/address.c pqclean_sphincs-sha2-256s-simple_avx2/context_sha2.c pqclean_sphincs-sha2-256s-simple_avx2/fors.c pqclean_sphincs-sha2-256s-simple_avx2/hash_sha2.c pqclean_sphincs-sha2-256s-simple_avx2/hash_sha2x8.c pqclean_sphincs-sha2-256s-simple_avx2/merkle.c pqclean_sphincs-sha2-256s-simple_avx2/sha256avx.c pqclean_sphincs-sha2-256s-simple_avx2/sha256x8.c pqclean_sphincs-sha2-256s-simple_avx2/sha512x4.c pqclean_sphincs-sha2-256s-simple_avx2/sign.c pqclean_sphincs-sha2-256s-simple_avx2/thash_sha2_simple.c pqclean_sphincs-sha2-256s-simple_avx2/thash_sha2_simplex8.c pqclean_sphincs-sha2-256s-simple_avx2/utils.c pqclean_sphincs-sha2-256s-simple_avx2/utilsx8.c pqclean_sphincs-sha2-256s-simple_avx2/wots.c) + target_include_directories(sphincs_sha256_256s_simple_avx2 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-sha2-256s-simple_avx2) target_include_directories(sphincs_sha256_256s_simple_avx2 PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) target_compile_options(sphincs_sha256_256s_simple_avx2 PRIVATE -mavx2) set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) endif() if(OQS_ENABLE_SIG_sphincs_shake256_128f_robust) - add_library(sphincs_shake256_128f_robust_clean OBJECT sig_sphincs_shake256_128f_robust.c pqclean_sphincs-shake256-128f-robust_clean/address.c pqclean_sphincs-shake256-128f-robust_clean/fors.c pqclean_sphincs-shake256-128f-robust_clean/hash_shake256.c pqclean_sphincs-shake256-128f-robust_clean/sign.c pqclean_sphincs-shake256-128f-robust_clean/thash_shake256_robust.c pqclean_sphincs-shake256-128f-robust_clean/utils.c pqclean_sphincs-shake256-128f-robust_clean/wots.c) - target_include_directories(sphincs_shake256_128f_robust_clean PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-shake256-128f-robust_clean) + add_library(sphincs_shake256_128f_robust_clean OBJECT sig_sphincs_shake256_128f_robust.c pqclean_sphincs-shake-128f-robust_clean/address.c pqclean_sphincs-shake-128f-robust_clean/context_shake.c pqclean_sphincs-shake-128f-robust_clean/fors.c pqclean_sphincs-shake-128f-robust_clean/hash_shake.c pqclean_sphincs-shake-128f-robust_clean/merkle.c pqclean_sphincs-shake-128f-robust_clean/sign.c pqclean_sphincs-shake-128f-robust_clean/thash_shake_robust.c pqclean_sphincs-shake-128f-robust_clean/utils.c pqclean_sphincs-shake-128f-robust_clean/utilsx1.c pqclean_sphincs-shake-128f-robust_clean/wots.c pqclean_sphincs-shake-128f-robust_clean/wotsx1.c) + target_include_directories(sphincs_shake256_128f_robust_clean PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-shake-128f-robust_clean) target_include_directories(sphincs_shake256_128f_robust_clean PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) endif() if(OQS_ENABLE_SIG_sphincs_shake256_128f_robust_avx2) - add_library(sphincs_shake256_128f_robust_avx2 OBJECT pqclean_sphincs-shake256-128f-robust_avx2/address.c pqclean_sphincs-shake256-128f-robust_avx2/fors.c pqclean_sphincs-shake256-128f-robust_avx2/hash_shake256.c pqclean_sphincs-shake256-128f-robust_avx2/hash_shake256x4.c pqclean_sphincs-shake256-128f-robust_avx2/sign.c pqclean_sphincs-shake256-128f-robust_avx2/thash_shake256_robust.c pqclean_sphincs-shake256-128f-robust_avx2/thash_shake256_robustx4.c pqclean_sphincs-shake256-128f-robust_avx2/utils.c pqclean_sphincs-shake256-128f-robust_avx2/utilsx4.c pqclean_sphincs-shake256-128f-robust_avx2/wots.c) - target_include_directories(sphincs_shake256_128f_robust_avx2 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-shake256-128f-robust_avx2) + add_library(sphincs_shake256_128f_robust_avx2 OBJECT pqclean_sphincs-shake-128f-robust_avx2/address.c pqclean_sphincs-shake-128f-robust_avx2/context_shake.c pqclean_sphincs-shake-128f-robust_avx2/fips202x4.c pqclean_sphincs-shake-128f-robust_avx2/fors.c pqclean_sphincs-shake-128f-robust_avx2/hash_shake.c pqclean_sphincs-shake-128f-robust_avx2/hash_shakex4.c pqclean_sphincs-shake-128f-robust_avx2/merkle.c pqclean_sphincs-shake-128f-robust_avx2/sign.c pqclean_sphincs-shake-128f-robust_avx2/thash_shake_robust.c pqclean_sphincs-shake-128f-robust_avx2/thash_shake_robustx4.c pqclean_sphincs-shake-128f-robust_avx2/utils.c pqclean_sphincs-shake-128f-robust_avx2/utilsx4.c pqclean_sphincs-shake-128f-robust_avx2/wots.c) + target_include_directories(sphincs_shake256_128f_robust_avx2 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-shake-128f-robust_avx2) target_include_directories(sphincs_shake256_128f_robust_avx2 PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) target_compile_options(sphincs_shake256_128f_robust_avx2 PRIVATE -mavx2) set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) endif() +if(OQS_ENABLE_SIG_sphincs_shake256_128f_robust_aarch64) + add_library(sphincs_shake256_128f_robust_aarch64 OBJECT pqclean_sphincs-shake-128f-robust_aarch64/address.c pqclean_sphincs-shake-128f-robust_aarch64/context_shake.c pqclean_sphincs-shake-128f-robust_aarch64/f1600x2.s pqclean_sphincs-shake-128f-robust_aarch64/f1600x2_const.c pqclean_sphincs-shake-128f-robust_aarch64/fips202x2.c pqclean_sphincs-shake-128f-robust_aarch64/fors.c pqclean_sphincs-shake-128f-robust_aarch64/hash_shake.c pqclean_sphincs-shake-128f-robust_aarch64/hash_shakex2.c pqclean_sphincs-shake-128f-robust_aarch64/merkle.c pqclean_sphincs-shake-128f-robust_aarch64/sign.c pqclean_sphincs-shake-128f-robust_aarch64/thash_shake_robustx2.c pqclean_sphincs-shake-128f-robust_aarch64/utils.c pqclean_sphincs-shake-128f-robust_aarch64/utilsx2.c pqclean_sphincs-shake-128f-robust_aarch64/wots.c) + target_include_directories(sphincs_shake256_128f_robust_aarch64 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-shake-128f-robust_aarch64) + target_include_directories(sphincs_shake256_128f_robust_aarch64 PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) + target_compile_options(sphincs_shake256_128f_robust_aarch64 PRIVATE -msha3) + set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) +endif() + if(OQS_ENABLE_SIG_sphincs_shake256_128f_simple) - add_library(sphincs_shake256_128f_simple_clean OBJECT sig_sphincs_shake256_128f_simple.c pqclean_sphincs-shake256-128f-simple_clean/address.c pqclean_sphincs-shake256-128f-simple_clean/fors.c pqclean_sphincs-shake256-128f-simple_clean/hash_shake256.c pqclean_sphincs-shake256-128f-simple_clean/sign.c pqclean_sphincs-shake256-128f-simple_clean/thash_shake256_simple.c pqclean_sphincs-shake256-128f-simple_clean/utils.c pqclean_sphincs-shake256-128f-simple_clean/wots.c) - target_include_directories(sphincs_shake256_128f_simple_clean PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-shake256-128f-simple_clean) + add_library(sphincs_shake256_128f_simple_clean OBJECT sig_sphincs_shake256_128f_simple.c pqclean_sphincs-shake-128f-simple_clean/address.c pqclean_sphincs-shake-128f-simple_clean/context_shake.c pqclean_sphincs-shake-128f-simple_clean/fors.c pqclean_sphincs-shake-128f-simple_clean/hash_shake.c pqclean_sphincs-shake-128f-simple_clean/merkle.c pqclean_sphincs-shake-128f-simple_clean/sign.c pqclean_sphincs-shake-128f-simple_clean/thash_shake_simple.c pqclean_sphincs-shake-128f-simple_clean/utils.c pqclean_sphincs-shake-128f-simple_clean/utilsx1.c pqclean_sphincs-shake-128f-simple_clean/wots.c pqclean_sphincs-shake-128f-simple_clean/wotsx1.c) + target_include_directories(sphincs_shake256_128f_simple_clean PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-shake-128f-simple_clean) target_include_directories(sphincs_shake256_128f_simple_clean PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) endif() if(OQS_ENABLE_SIG_sphincs_shake256_128f_simple_avx2) - add_library(sphincs_shake256_128f_simple_avx2 OBJECT pqclean_sphincs-shake256-128f-simple_avx2/address.c pqclean_sphincs-shake256-128f-simple_avx2/fors.c pqclean_sphincs-shake256-128f-simple_avx2/hash_shake256.c pqclean_sphincs-shake256-128f-simple_avx2/hash_shake256x4.c pqclean_sphincs-shake256-128f-simple_avx2/sign.c pqclean_sphincs-shake256-128f-simple_avx2/thash_shake256_simple.c pqclean_sphincs-shake256-128f-simple_avx2/thash_shake256_simplex4.c pqclean_sphincs-shake256-128f-simple_avx2/utils.c pqclean_sphincs-shake256-128f-simple_avx2/utilsx4.c pqclean_sphincs-shake256-128f-simple_avx2/wots.c) - target_include_directories(sphincs_shake256_128f_simple_avx2 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-shake256-128f-simple_avx2) + add_library(sphincs_shake256_128f_simple_avx2 OBJECT pqclean_sphincs-shake-128f-simple_avx2/address.c pqclean_sphincs-shake-128f-simple_avx2/context_shake.c pqclean_sphincs-shake-128f-simple_avx2/fips202x4.c pqclean_sphincs-shake-128f-simple_avx2/fors.c pqclean_sphincs-shake-128f-simple_avx2/hash_shake.c pqclean_sphincs-shake-128f-simple_avx2/hash_shakex4.c pqclean_sphincs-shake-128f-simple_avx2/merkle.c pqclean_sphincs-shake-128f-simple_avx2/sign.c pqclean_sphincs-shake-128f-simple_avx2/thash_shake_simple.c pqclean_sphincs-shake-128f-simple_avx2/thash_shake_simplex4.c pqclean_sphincs-shake-128f-simple_avx2/utils.c pqclean_sphincs-shake-128f-simple_avx2/utilsx4.c pqclean_sphincs-shake-128f-simple_avx2/wots.c) + target_include_directories(sphincs_shake256_128f_simple_avx2 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-shake-128f-simple_avx2) target_include_directories(sphincs_shake256_128f_simple_avx2 PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) target_compile_options(sphincs_shake256_128f_simple_avx2 PRIVATE -mavx2) set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) endif() +if(OQS_ENABLE_SIG_sphincs_shake256_128f_simple_aarch64) + add_library(sphincs_shake256_128f_simple_aarch64 OBJECT pqclean_sphincs-shake-128f-simple_aarch64/address.c pqclean_sphincs-shake-128f-simple_aarch64/context_shake.c pqclean_sphincs-shake-128f-simple_aarch64/f1600x2.s pqclean_sphincs-shake-128f-simple_aarch64/f1600x2_const.c pqclean_sphincs-shake-128f-simple_aarch64/fips202x2.c pqclean_sphincs-shake-128f-simple_aarch64/fors.c pqclean_sphincs-shake-128f-simple_aarch64/hash_shake.c pqclean_sphincs-shake-128f-simple_aarch64/hash_shakex2.c pqclean_sphincs-shake-128f-simple_aarch64/merkle.c pqclean_sphincs-shake-128f-simple_aarch64/sign.c pqclean_sphincs-shake-128f-simple_aarch64/thash_shake_simplex2.c pqclean_sphincs-shake-128f-simple_aarch64/utils.c pqclean_sphincs-shake-128f-simple_aarch64/utilsx2.c pqclean_sphincs-shake-128f-simple_aarch64/wots.c) + target_include_directories(sphincs_shake256_128f_simple_aarch64 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-shake-128f-simple_aarch64) + target_include_directories(sphincs_shake256_128f_simple_aarch64 PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) + target_compile_options(sphincs_shake256_128f_simple_aarch64 PRIVATE -msha3) + set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) +endif() + if(OQS_ENABLE_SIG_sphincs_shake256_128s_robust) - add_library(sphincs_shake256_128s_robust_clean OBJECT sig_sphincs_shake256_128s_robust.c pqclean_sphincs-shake256-128s-robust_clean/address.c pqclean_sphincs-shake256-128s-robust_clean/fors.c pqclean_sphincs-shake256-128s-robust_clean/hash_shake256.c pqclean_sphincs-shake256-128s-robust_clean/sign.c pqclean_sphincs-shake256-128s-robust_clean/thash_shake256_robust.c pqclean_sphincs-shake256-128s-robust_clean/utils.c pqclean_sphincs-shake256-128s-robust_clean/wots.c) - target_include_directories(sphincs_shake256_128s_robust_clean PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-shake256-128s-robust_clean) + add_library(sphincs_shake256_128s_robust_clean OBJECT sig_sphincs_shake256_128s_robust.c pqclean_sphincs-shake-128s-robust_clean/address.c pqclean_sphincs-shake-128s-robust_clean/context_shake.c pqclean_sphincs-shake-128s-robust_clean/fors.c pqclean_sphincs-shake-128s-robust_clean/hash_shake.c pqclean_sphincs-shake-128s-robust_clean/merkle.c pqclean_sphincs-shake-128s-robust_clean/sign.c pqclean_sphincs-shake-128s-robust_clean/thash_shake_robust.c pqclean_sphincs-shake-128s-robust_clean/utils.c pqclean_sphincs-shake-128s-robust_clean/utilsx1.c pqclean_sphincs-shake-128s-robust_clean/wots.c pqclean_sphincs-shake-128s-robust_clean/wotsx1.c) + target_include_directories(sphincs_shake256_128s_robust_clean PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-shake-128s-robust_clean) target_include_directories(sphincs_shake256_128s_robust_clean PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) endif() if(OQS_ENABLE_SIG_sphincs_shake256_128s_robust_avx2) - add_library(sphincs_shake256_128s_robust_avx2 OBJECT pqclean_sphincs-shake256-128s-robust_avx2/address.c pqclean_sphincs-shake256-128s-robust_avx2/fors.c pqclean_sphincs-shake256-128s-robust_avx2/hash_shake256.c pqclean_sphincs-shake256-128s-robust_avx2/hash_shake256x4.c pqclean_sphincs-shake256-128s-robust_avx2/sign.c pqclean_sphincs-shake256-128s-robust_avx2/thash_shake256_robust.c pqclean_sphincs-shake256-128s-robust_avx2/thash_shake256_robustx4.c pqclean_sphincs-shake256-128s-robust_avx2/utils.c pqclean_sphincs-shake256-128s-robust_avx2/utilsx4.c pqclean_sphincs-shake256-128s-robust_avx2/wots.c) - target_include_directories(sphincs_shake256_128s_robust_avx2 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-shake256-128s-robust_avx2) + add_library(sphincs_shake256_128s_robust_avx2 OBJECT pqclean_sphincs-shake-128s-robust_avx2/address.c pqclean_sphincs-shake-128s-robust_avx2/context_shake.c pqclean_sphincs-shake-128s-robust_avx2/fips202x4.c pqclean_sphincs-shake-128s-robust_avx2/fors.c pqclean_sphincs-shake-128s-robust_avx2/hash_shake.c pqclean_sphincs-shake-128s-robust_avx2/hash_shakex4.c pqclean_sphincs-shake-128s-robust_avx2/merkle.c pqclean_sphincs-shake-128s-robust_avx2/sign.c pqclean_sphincs-shake-128s-robust_avx2/thash_shake_robust.c pqclean_sphincs-shake-128s-robust_avx2/thash_shake_robustx4.c pqclean_sphincs-shake-128s-robust_avx2/utils.c pqclean_sphincs-shake-128s-robust_avx2/utilsx4.c pqclean_sphincs-shake-128s-robust_avx2/wots.c) + target_include_directories(sphincs_shake256_128s_robust_avx2 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-shake-128s-robust_avx2) target_include_directories(sphincs_shake256_128s_robust_avx2 PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) target_compile_options(sphincs_shake256_128s_robust_avx2 PRIVATE -mavx2) set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) endif() +if(OQS_ENABLE_SIG_sphincs_shake256_128s_robust_aarch64) + add_library(sphincs_shake256_128s_robust_aarch64 OBJECT pqclean_sphincs-shake-128s-robust_aarch64/address.c pqclean_sphincs-shake-128s-robust_aarch64/context_shake.c pqclean_sphincs-shake-128s-robust_aarch64/f1600x2.s pqclean_sphincs-shake-128s-robust_aarch64/f1600x2_const.c pqclean_sphincs-shake-128s-robust_aarch64/fips202x2.c pqclean_sphincs-shake-128s-robust_aarch64/fors.c pqclean_sphincs-shake-128s-robust_aarch64/hash_shake.c pqclean_sphincs-shake-128s-robust_aarch64/hash_shakex2.c pqclean_sphincs-shake-128s-robust_aarch64/merkle.c pqclean_sphincs-shake-128s-robust_aarch64/sign.c pqclean_sphincs-shake-128s-robust_aarch64/thash_shake_robustx2.c pqclean_sphincs-shake-128s-robust_aarch64/utils.c pqclean_sphincs-shake-128s-robust_aarch64/utilsx2.c pqclean_sphincs-shake-128s-robust_aarch64/wots.c) + target_include_directories(sphincs_shake256_128s_robust_aarch64 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-shake-128s-robust_aarch64) + target_include_directories(sphincs_shake256_128s_robust_aarch64 PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) + target_compile_options(sphincs_shake256_128s_robust_aarch64 PRIVATE -msha3) + set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) +endif() + if(OQS_ENABLE_SIG_sphincs_shake256_128s_simple) - add_library(sphincs_shake256_128s_simple_clean OBJECT sig_sphincs_shake256_128s_simple.c pqclean_sphincs-shake256-128s-simple_clean/address.c pqclean_sphincs-shake256-128s-simple_clean/fors.c pqclean_sphincs-shake256-128s-simple_clean/hash_shake256.c pqclean_sphincs-shake256-128s-simple_clean/sign.c pqclean_sphincs-shake256-128s-simple_clean/thash_shake256_simple.c pqclean_sphincs-shake256-128s-simple_clean/utils.c pqclean_sphincs-shake256-128s-simple_clean/wots.c) - target_include_directories(sphincs_shake256_128s_simple_clean PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-shake256-128s-simple_clean) + add_library(sphincs_shake256_128s_simple_clean OBJECT sig_sphincs_shake256_128s_simple.c pqclean_sphincs-shake-128s-simple_clean/address.c pqclean_sphincs-shake-128s-simple_clean/context_shake.c pqclean_sphincs-shake-128s-simple_clean/fors.c pqclean_sphincs-shake-128s-simple_clean/hash_shake.c pqclean_sphincs-shake-128s-simple_clean/merkle.c pqclean_sphincs-shake-128s-simple_clean/sign.c pqclean_sphincs-shake-128s-simple_clean/thash_shake_simple.c pqclean_sphincs-shake-128s-simple_clean/utils.c pqclean_sphincs-shake-128s-simple_clean/utilsx1.c pqclean_sphincs-shake-128s-simple_clean/wots.c pqclean_sphincs-shake-128s-simple_clean/wotsx1.c) + target_include_directories(sphincs_shake256_128s_simple_clean PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-shake-128s-simple_clean) target_include_directories(sphincs_shake256_128s_simple_clean PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) endif() if(OQS_ENABLE_SIG_sphincs_shake256_128s_simple_avx2) - add_library(sphincs_shake256_128s_simple_avx2 OBJECT pqclean_sphincs-shake256-128s-simple_avx2/address.c pqclean_sphincs-shake256-128s-simple_avx2/fors.c pqclean_sphincs-shake256-128s-simple_avx2/hash_shake256.c pqclean_sphincs-shake256-128s-simple_avx2/hash_shake256x4.c pqclean_sphincs-shake256-128s-simple_avx2/sign.c pqclean_sphincs-shake256-128s-simple_avx2/thash_shake256_simple.c pqclean_sphincs-shake256-128s-simple_avx2/thash_shake256_simplex4.c pqclean_sphincs-shake256-128s-simple_avx2/utils.c pqclean_sphincs-shake256-128s-simple_avx2/utilsx4.c pqclean_sphincs-shake256-128s-simple_avx2/wots.c) - target_include_directories(sphincs_shake256_128s_simple_avx2 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-shake256-128s-simple_avx2) + add_library(sphincs_shake256_128s_simple_avx2 OBJECT pqclean_sphincs-shake-128s-simple_avx2/address.c pqclean_sphincs-shake-128s-simple_avx2/context_shake.c pqclean_sphincs-shake-128s-simple_avx2/fips202x4.c pqclean_sphincs-shake-128s-simple_avx2/fors.c pqclean_sphincs-shake-128s-simple_avx2/hash_shake.c pqclean_sphincs-shake-128s-simple_avx2/hash_shakex4.c pqclean_sphincs-shake-128s-simple_avx2/merkle.c pqclean_sphincs-shake-128s-simple_avx2/sign.c pqclean_sphincs-shake-128s-simple_avx2/thash_shake_simple.c pqclean_sphincs-shake-128s-simple_avx2/thash_shake_simplex4.c pqclean_sphincs-shake-128s-simple_avx2/utils.c pqclean_sphincs-shake-128s-simple_avx2/utilsx4.c pqclean_sphincs-shake-128s-simple_avx2/wots.c) + target_include_directories(sphincs_shake256_128s_simple_avx2 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-shake-128s-simple_avx2) target_include_directories(sphincs_shake256_128s_simple_avx2 PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) target_compile_options(sphincs_shake256_128s_simple_avx2 PRIVATE -mavx2) set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) endif() +if(OQS_ENABLE_SIG_sphincs_shake256_128s_simple_aarch64) + add_library(sphincs_shake256_128s_simple_aarch64 OBJECT pqclean_sphincs-shake-128s-simple_aarch64/address.c pqclean_sphincs-shake-128s-simple_aarch64/context_shake.c pqclean_sphincs-shake-128s-simple_aarch64/f1600x2.s pqclean_sphincs-shake-128s-simple_aarch64/f1600x2_const.c pqclean_sphincs-shake-128s-simple_aarch64/fips202x2.c pqclean_sphincs-shake-128s-simple_aarch64/fors.c pqclean_sphincs-shake-128s-simple_aarch64/hash_shake.c pqclean_sphincs-shake-128s-simple_aarch64/hash_shakex2.c pqclean_sphincs-shake-128s-simple_aarch64/merkle.c pqclean_sphincs-shake-128s-simple_aarch64/sign.c pqclean_sphincs-shake-128s-simple_aarch64/thash_shake_simplex2.c pqclean_sphincs-shake-128s-simple_aarch64/utils.c pqclean_sphincs-shake-128s-simple_aarch64/utilsx2.c pqclean_sphincs-shake-128s-simple_aarch64/wots.c) + target_include_directories(sphincs_shake256_128s_simple_aarch64 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-shake-128s-simple_aarch64) + target_include_directories(sphincs_shake256_128s_simple_aarch64 PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) + target_compile_options(sphincs_shake256_128s_simple_aarch64 PRIVATE -msha3) + set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) +endif() + if(OQS_ENABLE_SIG_sphincs_shake256_192f_robust) - add_library(sphincs_shake256_192f_robust_clean OBJECT sig_sphincs_shake256_192f_robust.c pqclean_sphincs-shake256-192f-robust_clean/address.c pqclean_sphincs-shake256-192f-robust_clean/fors.c pqclean_sphincs-shake256-192f-robust_clean/hash_shake256.c pqclean_sphincs-shake256-192f-robust_clean/sign.c pqclean_sphincs-shake256-192f-robust_clean/thash_shake256_robust.c pqclean_sphincs-shake256-192f-robust_clean/utils.c pqclean_sphincs-shake256-192f-robust_clean/wots.c) - target_include_directories(sphincs_shake256_192f_robust_clean PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-shake256-192f-robust_clean) + add_library(sphincs_shake256_192f_robust_clean OBJECT sig_sphincs_shake256_192f_robust.c pqclean_sphincs-shake-192f-robust_clean/address.c pqclean_sphincs-shake-192f-robust_clean/context_shake.c pqclean_sphincs-shake-192f-robust_clean/fors.c pqclean_sphincs-shake-192f-robust_clean/hash_shake.c pqclean_sphincs-shake-192f-robust_clean/merkle.c pqclean_sphincs-shake-192f-robust_clean/sign.c pqclean_sphincs-shake-192f-robust_clean/thash_shake_robust.c pqclean_sphincs-shake-192f-robust_clean/utils.c pqclean_sphincs-shake-192f-robust_clean/utilsx1.c pqclean_sphincs-shake-192f-robust_clean/wots.c pqclean_sphincs-shake-192f-robust_clean/wotsx1.c) + target_include_directories(sphincs_shake256_192f_robust_clean PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-shake-192f-robust_clean) target_include_directories(sphincs_shake256_192f_robust_clean PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) endif() if(OQS_ENABLE_SIG_sphincs_shake256_192f_robust_avx2) - add_library(sphincs_shake256_192f_robust_avx2 OBJECT pqclean_sphincs-shake256-192f-robust_avx2/address.c pqclean_sphincs-shake256-192f-robust_avx2/fors.c pqclean_sphincs-shake256-192f-robust_avx2/hash_shake256.c pqclean_sphincs-shake256-192f-robust_avx2/hash_shake256x4.c pqclean_sphincs-shake256-192f-robust_avx2/sign.c pqclean_sphincs-shake256-192f-robust_avx2/thash_shake256_robust.c pqclean_sphincs-shake256-192f-robust_avx2/thash_shake256_robustx4.c pqclean_sphincs-shake256-192f-robust_avx2/utils.c pqclean_sphincs-shake256-192f-robust_avx2/utilsx4.c pqclean_sphincs-shake256-192f-robust_avx2/wots.c) - target_include_directories(sphincs_shake256_192f_robust_avx2 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-shake256-192f-robust_avx2) + add_library(sphincs_shake256_192f_robust_avx2 OBJECT pqclean_sphincs-shake-192f-robust_avx2/address.c pqclean_sphincs-shake-192f-robust_avx2/context_shake.c pqclean_sphincs-shake-192f-robust_avx2/fips202x4.c pqclean_sphincs-shake-192f-robust_avx2/fors.c pqclean_sphincs-shake-192f-robust_avx2/hash_shake.c pqclean_sphincs-shake-192f-robust_avx2/hash_shakex4.c pqclean_sphincs-shake-192f-robust_avx2/merkle.c pqclean_sphincs-shake-192f-robust_avx2/sign.c pqclean_sphincs-shake-192f-robust_avx2/thash_shake_robust.c pqclean_sphincs-shake-192f-robust_avx2/thash_shake_robustx4.c pqclean_sphincs-shake-192f-robust_avx2/utils.c pqclean_sphincs-shake-192f-robust_avx2/utilsx4.c pqclean_sphincs-shake-192f-robust_avx2/wots.c) + target_include_directories(sphincs_shake256_192f_robust_avx2 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-shake-192f-robust_avx2) target_include_directories(sphincs_shake256_192f_robust_avx2 PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) target_compile_options(sphincs_shake256_192f_robust_avx2 PRIVATE -mavx2) set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) endif() +if(OQS_ENABLE_SIG_sphincs_shake256_192f_robust_aarch64) + add_library(sphincs_shake256_192f_robust_aarch64 OBJECT pqclean_sphincs-shake-192f-robust_aarch64/address.c pqclean_sphincs-shake-192f-robust_aarch64/context_shake.c pqclean_sphincs-shake-192f-robust_aarch64/f1600x2.s pqclean_sphincs-shake-192f-robust_aarch64/f1600x2_const.c pqclean_sphincs-shake-192f-robust_aarch64/fips202x2.c pqclean_sphincs-shake-192f-robust_aarch64/fors.c pqclean_sphincs-shake-192f-robust_aarch64/hash_shake.c pqclean_sphincs-shake-192f-robust_aarch64/hash_shakex2.c pqclean_sphincs-shake-192f-robust_aarch64/merkle.c pqclean_sphincs-shake-192f-robust_aarch64/sign.c pqclean_sphincs-shake-192f-robust_aarch64/thash_shake_robustx2.c pqclean_sphincs-shake-192f-robust_aarch64/utils.c pqclean_sphincs-shake-192f-robust_aarch64/utilsx2.c pqclean_sphincs-shake-192f-robust_aarch64/wots.c) + target_include_directories(sphincs_shake256_192f_robust_aarch64 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-shake-192f-robust_aarch64) + target_include_directories(sphincs_shake256_192f_robust_aarch64 PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) + target_compile_options(sphincs_shake256_192f_robust_aarch64 PRIVATE -msha3) + set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) +endif() + if(OQS_ENABLE_SIG_sphincs_shake256_192f_simple) - add_library(sphincs_shake256_192f_simple_clean OBJECT sig_sphincs_shake256_192f_simple.c pqclean_sphincs-shake256-192f-simple_clean/address.c pqclean_sphincs-shake256-192f-simple_clean/fors.c pqclean_sphincs-shake256-192f-simple_clean/hash_shake256.c pqclean_sphincs-shake256-192f-simple_clean/sign.c pqclean_sphincs-shake256-192f-simple_clean/thash_shake256_simple.c pqclean_sphincs-shake256-192f-simple_clean/utils.c pqclean_sphincs-shake256-192f-simple_clean/wots.c) - target_include_directories(sphincs_shake256_192f_simple_clean PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-shake256-192f-simple_clean) + add_library(sphincs_shake256_192f_simple_clean OBJECT sig_sphincs_shake256_192f_simple.c pqclean_sphincs-shake-192f-simple_clean/address.c pqclean_sphincs-shake-192f-simple_clean/context_shake.c pqclean_sphincs-shake-192f-simple_clean/fors.c pqclean_sphincs-shake-192f-simple_clean/hash_shake.c pqclean_sphincs-shake-192f-simple_clean/merkle.c pqclean_sphincs-shake-192f-simple_clean/sign.c pqclean_sphincs-shake-192f-simple_clean/thash_shake_simple.c pqclean_sphincs-shake-192f-simple_clean/utils.c pqclean_sphincs-shake-192f-simple_clean/utilsx1.c pqclean_sphincs-shake-192f-simple_clean/wots.c pqclean_sphincs-shake-192f-simple_clean/wotsx1.c) + target_include_directories(sphincs_shake256_192f_simple_clean PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-shake-192f-simple_clean) target_include_directories(sphincs_shake256_192f_simple_clean PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) endif() if(OQS_ENABLE_SIG_sphincs_shake256_192f_simple_avx2) - add_library(sphincs_shake256_192f_simple_avx2 OBJECT pqclean_sphincs-shake256-192f-simple_avx2/address.c pqclean_sphincs-shake256-192f-simple_avx2/fors.c pqclean_sphincs-shake256-192f-simple_avx2/hash_shake256.c pqclean_sphincs-shake256-192f-simple_avx2/hash_shake256x4.c pqclean_sphincs-shake256-192f-simple_avx2/sign.c pqclean_sphincs-shake256-192f-simple_avx2/thash_shake256_simple.c pqclean_sphincs-shake256-192f-simple_avx2/thash_shake256_simplex4.c pqclean_sphincs-shake256-192f-simple_avx2/utils.c pqclean_sphincs-shake256-192f-simple_avx2/utilsx4.c pqclean_sphincs-shake256-192f-simple_avx2/wots.c) - target_include_directories(sphincs_shake256_192f_simple_avx2 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-shake256-192f-simple_avx2) + add_library(sphincs_shake256_192f_simple_avx2 OBJECT pqclean_sphincs-shake-192f-simple_avx2/address.c pqclean_sphincs-shake-192f-simple_avx2/context_shake.c pqclean_sphincs-shake-192f-simple_avx2/fips202x4.c pqclean_sphincs-shake-192f-simple_avx2/fors.c pqclean_sphincs-shake-192f-simple_avx2/hash_shake.c pqclean_sphincs-shake-192f-simple_avx2/hash_shakex4.c pqclean_sphincs-shake-192f-simple_avx2/merkle.c pqclean_sphincs-shake-192f-simple_avx2/sign.c pqclean_sphincs-shake-192f-simple_avx2/thash_shake_simple.c pqclean_sphincs-shake-192f-simple_avx2/thash_shake_simplex4.c pqclean_sphincs-shake-192f-simple_avx2/utils.c pqclean_sphincs-shake-192f-simple_avx2/utilsx4.c pqclean_sphincs-shake-192f-simple_avx2/wots.c) + target_include_directories(sphincs_shake256_192f_simple_avx2 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-shake-192f-simple_avx2) target_include_directories(sphincs_shake256_192f_simple_avx2 PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) target_compile_options(sphincs_shake256_192f_simple_avx2 PRIVATE -mavx2) set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) endif() +if(OQS_ENABLE_SIG_sphincs_shake256_192f_simple_aarch64) + add_library(sphincs_shake256_192f_simple_aarch64 OBJECT pqclean_sphincs-shake-192f-simple_aarch64/address.c pqclean_sphincs-shake-192f-simple_aarch64/context_shake.c pqclean_sphincs-shake-192f-simple_aarch64/f1600x2.s pqclean_sphincs-shake-192f-simple_aarch64/f1600x2_const.c pqclean_sphincs-shake-192f-simple_aarch64/fips202x2.c pqclean_sphincs-shake-192f-simple_aarch64/fors.c pqclean_sphincs-shake-192f-simple_aarch64/hash_shake.c pqclean_sphincs-shake-192f-simple_aarch64/hash_shakex2.c pqclean_sphincs-shake-192f-simple_aarch64/merkle.c pqclean_sphincs-shake-192f-simple_aarch64/sign.c pqclean_sphincs-shake-192f-simple_aarch64/thash_shake_simplex2.c pqclean_sphincs-shake-192f-simple_aarch64/utils.c pqclean_sphincs-shake-192f-simple_aarch64/utilsx2.c pqclean_sphincs-shake-192f-simple_aarch64/wots.c) + target_include_directories(sphincs_shake256_192f_simple_aarch64 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-shake-192f-simple_aarch64) + target_include_directories(sphincs_shake256_192f_simple_aarch64 PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) + target_compile_options(sphincs_shake256_192f_simple_aarch64 PRIVATE -msha3) + set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) +endif() + if(OQS_ENABLE_SIG_sphincs_shake256_192s_robust) - add_library(sphincs_shake256_192s_robust_clean OBJECT sig_sphincs_shake256_192s_robust.c pqclean_sphincs-shake256-192s-robust_clean/address.c pqclean_sphincs-shake256-192s-robust_clean/fors.c pqclean_sphincs-shake256-192s-robust_clean/hash_shake256.c pqclean_sphincs-shake256-192s-robust_clean/sign.c pqclean_sphincs-shake256-192s-robust_clean/thash_shake256_robust.c pqclean_sphincs-shake256-192s-robust_clean/utils.c pqclean_sphincs-shake256-192s-robust_clean/wots.c) - target_include_directories(sphincs_shake256_192s_robust_clean PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-shake256-192s-robust_clean) + add_library(sphincs_shake256_192s_robust_clean OBJECT sig_sphincs_shake256_192s_robust.c pqclean_sphincs-shake-192s-robust_clean/address.c pqclean_sphincs-shake-192s-robust_clean/context_shake.c pqclean_sphincs-shake-192s-robust_clean/fors.c pqclean_sphincs-shake-192s-robust_clean/hash_shake.c pqclean_sphincs-shake-192s-robust_clean/merkle.c pqclean_sphincs-shake-192s-robust_clean/sign.c pqclean_sphincs-shake-192s-robust_clean/thash_shake_robust.c pqclean_sphincs-shake-192s-robust_clean/utils.c pqclean_sphincs-shake-192s-robust_clean/utilsx1.c pqclean_sphincs-shake-192s-robust_clean/wots.c pqclean_sphincs-shake-192s-robust_clean/wotsx1.c) + target_include_directories(sphincs_shake256_192s_robust_clean PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-shake-192s-robust_clean) target_include_directories(sphincs_shake256_192s_robust_clean PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) endif() if(OQS_ENABLE_SIG_sphincs_shake256_192s_robust_avx2) - add_library(sphincs_shake256_192s_robust_avx2 OBJECT pqclean_sphincs-shake256-192s-robust_avx2/address.c pqclean_sphincs-shake256-192s-robust_avx2/fors.c pqclean_sphincs-shake256-192s-robust_avx2/hash_shake256.c pqclean_sphincs-shake256-192s-robust_avx2/hash_shake256x4.c pqclean_sphincs-shake256-192s-robust_avx2/sign.c pqclean_sphincs-shake256-192s-robust_avx2/thash_shake256_robust.c pqclean_sphincs-shake256-192s-robust_avx2/thash_shake256_robustx4.c pqclean_sphincs-shake256-192s-robust_avx2/utils.c pqclean_sphincs-shake256-192s-robust_avx2/utilsx4.c pqclean_sphincs-shake256-192s-robust_avx2/wots.c) - target_include_directories(sphincs_shake256_192s_robust_avx2 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-shake256-192s-robust_avx2) + add_library(sphincs_shake256_192s_robust_avx2 OBJECT pqclean_sphincs-shake-192s-robust_avx2/address.c pqclean_sphincs-shake-192s-robust_avx2/context_shake.c pqclean_sphincs-shake-192s-robust_avx2/fips202x4.c pqclean_sphincs-shake-192s-robust_avx2/fors.c pqclean_sphincs-shake-192s-robust_avx2/hash_shake.c pqclean_sphincs-shake-192s-robust_avx2/hash_shakex4.c pqclean_sphincs-shake-192s-robust_avx2/merkle.c pqclean_sphincs-shake-192s-robust_avx2/sign.c pqclean_sphincs-shake-192s-robust_avx2/thash_shake_robust.c pqclean_sphincs-shake-192s-robust_avx2/thash_shake_robustx4.c pqclean_sphincs-shake-192s-robust_avx2/utils.c pqclean_sphincs-shake-192s-robust_avx2/utilsx4.c pqclean_sphincs-shake-192s-robust_avx2/wots.c) + target_include_directories(sphincs_shake256_192s_robust_avx2 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-shake-192s-robust_avx2) target_include_directories(sphincs_shake256_192s_robust_avx2 PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) target_compile_options(sphincs_shake256_192s_robust_avx2 PRIVATE -mavx2) set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) endif() +if(OQS_ENABLE_SIG_sphincs_shake256_192s_robust_aarch64) + add_library(sphincs_shake256_192s_robust_aarch64 OBJECT pqclean_sphincs-shake-192s-robust_aarch64/address.c pqclean_sphincs-shake-192s-robust_aarch64/context_shake.c pqclean_sphincs-shake-192s-robust_aarch64/f1600x2.s pqclean_sphincs-shake-192s-robust_aarch64/f1600x2_const.c pqclean_sphincs-shake-192s-robust_aarch64/fips202x2.c pqclean_sphincs-shake-192s-robust_aarch64/fors.c pqclean_sphincs-shake-192s-robust_aarch64/hash_shake.c pqclean_sphincs-shake-192s-robust_aarch64/hash_shakex2.c pqclean_sphincs-shake-192s-robust_aarch64/merkle.c pqclean_sphincs-shake-192s-robust_aarch64/sign.c pqclean_sphincs-shake-192s-robust_aarch64/thash_shake_robustx2.c pqclean_sphincs-shake-192s-robust_aarch64/utils.c pqclean_sphincs-shake-192s-robust_aarch64/utilsx2.c pqclean_sphincs-shake-192s-robust_aarch64/wots.c) + target_include_directories(sphincs_shake256_192s_robust_aarch64 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-shake-192s-robust_aarch64) + target_include_directories(sphincs_shake256_192s_robust_aarch64 PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) + target_compile_options(sphincs_shake256_192s_robust_aarch64 PRIVATE -msha3) + set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) +endif() + if(OQS_ENABLE_SIG_sphincs_shake256_192s_simple) - add_library(sphincs_shake256_192s_simple_clean OBJECT sig_sphincs_shake256_192s_simple.c pqclean_sphincs-shake256-192s-simple_clean/address.c pqclean_sphincs-shake256-192s-simple_clean/fors.c pqclean_sphincs-shake256-192s-simple_clean/hash_shake256.c pqclean_sphincs-shake256-192s-simple_clean/sign.c pqclean_sphincs-shake256-192s-simple_clean/thash_shake256_simple.c pqclean_sphincs-shake256-192s-simple_clean/utils.c pqclean_sphincs-shake256-192s-simple_clean/wots.c) - target_include_directories(sphincs_shake256_192s_simple_clean PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-shake256-192s-simple_clean) + add_library(sphincs_shake256_192s_simple_clean OBJECT sig_sphincs_shake256_192s_simple.c pqclean_sphincs-shake-192s-simple_clean/address.c pqclean_sphincs-shake-192s-simple_clean/context_shake.c pqclean_sphincs-shake-192s-simple_clean/fors.c pqclean_sphincs-shake-192s-simple_clean/hash_shake.c pqclean_sphincs-shake-192s-simple_clean/merkle.c pqclean_sphincs-shake-192s-simple_clean/sign.c pqclean_sphincs-shake-192s-simple_clean/thash_shake_simple.c pqclean_sphincs-shake-192s-simple_clean/utils.c pqclean_sphincs-shake-192s-simple_clean/utilsx1.c pqclean_sphincs-shake-192s-simple_clean/wots.c pqclean_sphincs-shake-192s-simple_clean/wotsx1.c) + target_include_directories(sphincs_shake256_192s_simple_clean PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-shake-192s-simple_clean) target_include_directories(sphincs_shake256_192s_simple_clean PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) endif() if(OQS_ENABLE_SIG_sphincs_shake256_192s_simple_avx2) - add_library(sphincs_shake256_192s_simple_avx2 OBJECT pqclean_sphincs-shake256-192s-simple_avx2/address.c pqclean_sphincs-shake256-192s-simple_avx2/fors.c pqclean_sphincs-shake256-192s-simple_avx2/hash_shake256.c pqclean_sphincs-shake256-192s-simple_avx2/hash_shake256x4.c pqclean_sphincs-shake256-192s-simple_avx2/sign.c pqclean_sphincs-shake256-192s-simple_avx2/thash_shake256_simple.c pqclean_sphincs-shake256-192s-simple_avx2/thash_shake256_simplex4.c pqclean_sphincs-shake256-192s-simple_avx2/utils.c pqclean_sphincs-shake256-192s-simple_avx2/utilsx4.c pqclean_sphincs-shake256-192s-simple_avx2/wots.c) - target_include_directories(sphincs_shake256_192s_simple_avx2 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-shake256-192s-simple_avx2) + add_library(sphincs_shake256_192s_simple_avx2 OBJECT pqclean_sphincs-shake-192s-simple_avx2/address.c pqclean_sphincs-shake-192s-simple_avx2/context_shake.c pqclean_sphincs-shake-192s-simple_avx2/fips202x4.c pqclean_sphincs-shake-192s-simple_avx2/fors.c pqclean_sphincs-shake-192s-simple_avx2/hash_shake.c pqclean_sphincs-shake-192s-simple_avx2/hash_shakex4.c pqclean_sphincs-shake-192s-simple_avx2/merkle.c pqclean_sphincs-shake-192s-simple_avx2/sign.c pqclean_sphincs-shake-192s-simple_avx2/thash_shake_simple.c pqclean_sphincs-shake-192s-simple_avx2/thash_shake_simplex4.c pqclean_sphincs-shake-192s-simple_avx2/utils.c pqclean_sphincs-shake-192s-simple_avx2/utilsx4.c pqclean_sphincs-shake-192s-simple_avx2/wots.c) + target_include_directories(sphincs_shake256_192s_simple_avx2 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-shake-192s-simple_avx2) target_include_directories(sphincs_shake256_192s_simple_avx2 PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) target_compile_options(sphincs_shake256_192s_simple_avx2 PRIVATE -mavx2) set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) endif() +if(OQS_ENABLE_SIG_sphincs_shake256_192s_simple_aarch64) + add_library(sphincs_shake256_192s_simple_aarch64 OBJECT pqclean_sphincs-shake-192s-simple_aarch64/address.c pqclean_sphincs-shake-192s-simple_aarch64/context_shake.c pqclean_sphincs-shake-192s-simple_aarch64/f1600x2.s pqclean_sphincs-shake-192s-simple_aarch64/f1600x2_const.c pqclean_sphincs-shake-192s-simple_aarch64/fips202x2.c pqclean_sphincs-shake-192s-simple_aarch64/fors.c pqclean_sphincs-shake-192s-simple_aarch64/hash_shake.c pqclean_sphincs-shake-192s-simple_aarch64/hash_shakex2.c pqclean_sphincs-shake-192s-simple_aarch64/merkle.c pqclean_sphincs-shake-192s-simple_aarch64/sign.c pqclean_sphincs-shake-192s-simple_aarch64/thash_shake_simplex2.c pqclean_sphincs-shake-192s-simple_aarch64/utils.c pqclean_sphincs-shake-192s-simple_aarch64/utilsx2.c pqclean_sphincs-shake-192s-simple_aarch64/wots.c) + target_include_directories(sphincs_shake256_192s_simple_aarch64 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-shake-192s-simple_aarch64) + target_include_directories(sphincs_shake256_192s_simple_aarch64 PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) + target_compile_options(sphincs_shake256_192s_simple_aarch64 PRIVATE -msha3) + set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) +endif() + if(OQS_ENABLE_SIG_sphincs_shake256_256f_robust) - add_library(sphincs_shake256_256f_robust_clean OBJECT sig_sphincs_shake256_256f_robust.c pqclean_sphincs-shake256-256f-robust_clean/address.c pqclean_sphincs-shake256-256f-robust_clean/fors.c pqclean_sphincs-shake256-256f-robust_clean/hash_shake256.c pqclean_sphincs-shake256-256f-robust_clean/sign.c pqclean_sphincs-shake256-256f-robust_clean/thash_shake256_robust.c pqclean_sphincs-shake256-256f-robust_clean/utils.c pqclean_sphincs-shake256-256f-robust_clean/wots.c) - target_include_directories(sphincs_shake256_256f_robust_clean PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-shake256-256f-robust_clean) + add_library(sphincs_shake256_256f_robust_clean OBJECT sig_sphincs_shake256_256f_robust.c pqclean_sphincs-shake-256f-robust_clean/address.c pqclean_sphincs-shake-256f-robust_clean/context_shake.c pqclean_sphincs-shake-256f-robust_clean/fors.c pqclean_sphincs-shake-256f-robust_clean/hash_shake.c pqclean_sphincs-shake-256f-robust_clean/merkle.c pqclean_sphincs-shake-256f-robust_clean/sign.c pqclean_sphincs-shake-256f-robust_clean/thash_shake_robust.c pqclean_sphincs-shake-256f-robust_clean/utils.c pqclean_sphincs-shake-256f-robust_clean/utilsx1.c pqclean_sphincs-shake-256f-robust_clean/wots.c pqclean_sphincs-shake-256f-robust_clean/wotsx1.c) + target_include_directories(sphincs_shake256_256f_robust_clean PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-shake-256f-robust_clean) target_include_directories(sphincs_shake256_256f_robust_clean PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) endif() if(OQS_ENABLE_SIG_sphincs_shake256_256f_robust_avx2) - add_library(sphincs_shake256_256f_robust_avx2 OBJECT pqclean_sphincs-shake256-256f-robust_avx2/address.c pqclean_sphincs-shake256-256f-robust_avx2/fors.c pqclean_sphincs-shake256-256f-robust_avx2/hash_shake256.c pqclean_sphincs-shake256-256f-robust_avx2/hash_shake256x4.c pqclean_sphincs-shake256-256f-robust_avx2/sign.c pqclean_sphincs-shake256-256f-robust_avx2/thash_shake256_robust.c pqclean_sphincs-shake256-256f-robust_avx2/thash_shake256_robustx4.c pqclean_sphincs-shake256-256f-robust_avx2/utils.c pqclean_sphincs-shake256-256f-robust_avx2/utilsx4.c pqclean_sphincs-shake256-256f-robust_avx2/wots.c) - target_include_directories(sphincs_shake256_256f_robust_avx2 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-shake256-256f-robust_avx2) + add_library(sphincs_shake256_256f_robust_avx2 OBJECT pqclean_sphincs-shake-256f-robust_avx2/address.c pqclean_sphincs-shake-256f-robust_avx2/context_shake.c pqclean_sphincs-shake-256f-robust_avx2/fips202x4.c pqclean_sphincs-shake-256f-robust_avx2/fors.c pqclean_sphincs-shake-256f-robust_avx2/hash_shake.c pqclean_sphincs-shake-256f-robust_avx2/hash_shakex4.c pqclean_sphincs-shake-256f-robust_avx2/merkle.c pqclean_sphincs-shake-256f-robust_avx2/sign.c pqclean_sphincs-shake-256f-robust_avx2/thash_shake_robust.c pqclean_sphincs-shake-256f-robust_avx2/thash_shake_robustx4.c pqclean_sphincs-shake-256f-robust_avx2/utils.c pqclean_sphincs-shake-256f-robust_avx2/utilsx4.c pqclean_sphincs-shake-256f-robust_avx2/wots.c) + target_include_directories(sphincs_shake256_256f_robust_avx2 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-shake-256f-robust_avx2) target_include_directories(sphincs_shake256_256f_robust_avx2 PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) target_compile_options(sphincs_shake256_256f_robust_avx2 PRIVATE -mavx2) set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) endif() +if(OQS_ENABLE_SIG_sphincs_shake256_256f_robust_aarch64) + add_library(sphincs_shake256_256f_robust_aarch64 OBJECT pqclean_sphincs-shake-256f-robust_aarch64/address.c pqclean_sphincs-shake-256f-robust_aarch64/context_shake.c pqclean_sphincs-shake-256f-robust_aarch64/f1600x2.s pqclean_sphincs-shake-256f-robust_aarch64/f1600x2_const.c pqclean_sphincs-shake-256f-robust_aarch64/fips202x2.c pqclean_sphincs-shake-256f-robust_aarch64/fors.c pqclean_sphincs-shake-256f-robust_aarch64/hash_shake.c pqclean_sphincs-shake-256f-robust_aarch64/hash_shakex2.c pqclean_sphincs-shake-256f-robust_aarch64/merkle.c pqclean_sphincs-shake-256f-robust_aarch64/sign.c pqclean_sphincs-shake-256f-robust_aarch64/thash_shake_robustx2.c pqclean_sphincs-shake-256f-robust_aarch64/utils.c pqclean_sphincs-shake-256f-robust_aarch64/utilsx2.c pqclean_sphincs-shake-256f-robust_aarch64/wots.c) + target_include_directories(sphincs_shake256_256f_robust_aarch64 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-shake-256f-robust_aarch64) + target_include_directories(sphincs_shake256_256f_robust_aarch64 PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) + target_compile_options(sphincs_shake256_256f_robust_aarch64 PRIVATE -msha3) + set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) +endif() + if(OQS_ENABLE_SIG_sphincs_shake256_256f_simple) - add_library(sphincs_shake256_256f_simple_clean OBJECT sig_sphincs_shake256_256f_simple.c pqclean_sphincs-shake256-256f-simple_clean/address.c pqclean_sphincs-shake256-256f-simple_clean/fors.c pqclean_sphincs-shake256-256f-simple_clean/hash_shake256.c pqclean_sphincs-shake256-256f-simple_clean/sign.c pqclean_sphincs-shake256-256f-simple_clean/thash_shake256_simple.c pqclean_sphincs-shake256-256f-simple_clean/utils.c pqclean_sphincs-shake256-256f-simple_clean/wots.c) - target_include_directories(sphincs_shake256_256f_simple_clean PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-shake256-256f-simple_clean) + add_library(sphincs_shake256_256f_simple_clean OBJECT sig_sphincs_shake256_256f_simple.c pqclean_sphincs-shake-256f-simple_clean/address.c pqclean_sphincs-shake-256f-simple_clean/context_shake.c pqclean_sphincs-shake-256f-simple_clean/fors.c pqclean_sphincs-shake-256f-simple_clean/hash_shake.c pqclean_sphincs-shake-256f-simple_clean/merkle.c pqclean_sphincs-shake-256f-simple_clean/sign.c pqclean_sphincs-shake-256f-simple_clean/thash_shake_simple.c pqclean_sphincs-shake-256f-simple_clean/utils.c pqclean_sphincs-shake-256f-simple_clean/utilsx1.c pqclean_sphincs-shake-256f-simple_clean/wots.c pqclean_sphincs-shake-256f-simple_clean/wotsx1.c) + target_include_directories(sphincs_shake256_256f_simple_clean PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-shake-256f-simple_clean) target_include_directories(sphincs_shake256_256f_simple_clean PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) endif() if(OQS_ENABLE_SIG_sphincs_shake256_256f_simple_avx2) - add_library(sphincs_shake256_256f_simple_avx2 OBJECT pqclean_sphincs-shake256-256f-simple_avx2/address.c pqclean_sphincs-shake256-256f-simple_avx2/fors.c pqclean_sphincs-shake256-256f-simple_avx2/hash_shake256.c pqclean_sphincs-shake256-256f-simple_avx2/hash_shake256x4.c pqclean_sphincs-shake256-256f-simple_avx2/sign.c pqclean_sphincs-shake256-256f-simple_avx2/thash_shake256_simple.c pqclean_sphincs-shake256-256f-simple_avx2/thash_shake256_simplex4.c pqclean_sphincs-shake256-256f-simple_avx2/utils.c pqclean_sphincs-shake256-256f-simple_avx2/utilsx4.c pqclean_sphincs-shake256-256f-simple_avx2/wots.c) - target_include_directories(sphincs_shake256_256f_simple_avx2 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-shake256-256f-simple_avx2) + add_library(sphincs_shake256_256f_simple_avx2 OBJECT pqclean_sphincs-shake-256f-simple_avx2/address.c pqclean_sphincs-shake-256f-simple_avx2/context_shake.c pqclean_sphincs-shake-256f-simple_avx2/fips202x4.c pqclean_sphincs-shake-256f-simple_avx2/fors.c pqclean_sphincs-shake-256f-simple_avx2/hash_shake.c pqclean_sphincs-shake-256f-simple_avx2/hash_shakex4.c pqclean_sphincs-shake-256f-simple_avx2/merkle.c pqclean_sphincs-shake-256f-simple_avx2/sign.c pqclean_sphincs-shake-256f-simple_avx2/thash_shake_simple.c pqclean_sphincs-shake-256f-simple_avx2/thash_shake_simplex4.c pqclean_sphincs-shake-256f-simple_avx2/utils.c pqclean_sphincs-shake-256f-simple_avx2/utilsx4.c pqclean_sphincs-shake-256f-simple_avx2/wots.c) + target_include_directories(sphincs_shake256_256f_simple_avx2 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-shake-256f-simple_avx2) target_include_directories(sphincs_shake256_256f_simple_avx2 PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) target_compile_options(sphincs_shake256_256f_simple_avx2 PRIVATE -mavx2) set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) endif() +if(OQS_ENABLE_SIG_sphincs_shake256_256f_simple_aarch64) + add_library(sphincs_shake256_256f_simple_aarch64 OBJECT pqclean_sphincs-shake-256f-simple_aarch64/address.c pqclean_sphincs-shake-256f-simple_aarch64/context_shake.c pqclean_sphincs-shake-256f-simple_aarch64/f1600x2.s pqclean_sphincs-shake-256f-simple_aarch64/f1600x2_const.c pqclean_sphincs-shake-256f-simple_aarch64/fips202x2.c pqclean_sphincs-shake-256f-simple_aarch64/fors.c pqclean_sphincs-shake-256f-simple_aarch64/hash_shake.c pqclean_sphincs-shake-256f-simple_aarch64/hash_shakex2.c pqclean_sphincs-shake-256f-simple_aarch64/merkle.c pqclean_sphincs-shake-256f-simple_aarch64/sign.c pqclean_sphincs-shake-256f-simple_aarch64/thash_shake_simplex2.c pqclean_sphincs-shake-256f-simple_aarch64/utils.c pqclean_sphincs-shake-256f-simple_aarch64/utilsx2.c pqclean_sphincs-shake-256f-simple_aarch64/wots.c) + target_include_directories(sphincs_shake256_256f_simple_aarch64 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-shake-256f-simple_aarch64) + target_include_directories(sphincs_shake256_256f_simple_aarch64 PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) + target_compile_options(sphincs_shake256_256f_simple_aarch64 PRIVATE -msha3) + set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) +endif() + if(OQS_ENABLE_SIG_sphincs_shake256_256s_robust) - add_library(sphincs_shake256_256s_robust_clean OBJECT sig_sphincs_shake256_256s_robust.c pqclean_sphincs-shake256-256s-robust_clean/address.c pqclean_sphincs-shake256-256s-robust_clean/fors.c pqclean_sphincs-shake256-256s-robust_clean/hash_shake256.c pqclean_sphincs-shake256-256s-robust_clean/sign.c pqclean_sphincs-shake256-256s-robust_clean/thash_shake256_robust.c pqclean_sphincs-shake256-256s-robust_clean/utils.c pqclean_sphincs-shake256-256s-robust_clean/wots.c) - target_include_directories(sphincs_shake256_256s_robust_clean PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-shake256-256s-robust_clean) + add_library(sphincs_shake256_256s_robust_clean OBJECT sig_sphincs_shake256_256s_robust.c pqclean_sphincs-shake-256s-robust_clean/address.c pqclean_sphincs-shake-256s-robust_clean/context_shake.c pqclean_sphincs-shake-256s-robust_clean/fors.c pqclean_sphincs-shake-256s-robust_clean/hash_shake.c pqclean_sphincs-shake-256s-robust_clean/merkle.c pqclean_sphincs-shake-256s-robust_clean/sign.c pqclean_sphincs-shake-256s-robust_clean/thash_shake_robust.c pqclean_sphincs-shake-256s-robust_clean/utils.c pqclean_sphincs-shake-256s-robust_clean/utilsx1.c pqclean_sphincs-shake-256s-robust_clean/wots.c pqclean_sphincs-shake-256s-robust_clean/wotsx1.c) + target_include_directories(sphincs_shake256_256s_robust_clean PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-shake-256s-robust_clean) target_include_directories(sphincs_shake256_256s_robust_clean PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) endif() if(OQS_ENABLE_SIG_sphincs_shake256_256s_robust_avx2) - add_library(sphincs_shake256_256s_robust_avx2 OBJECT pqclean_sphincs-shake256-256s-robust_avx2/address.c pqclean_sphincs-shake256-256s-robust_avx2/fors.c pqclean_sphincs-shake256-256s-robust_avx2/hash_shake256.c pqclean_sphincs-shake256-256s-robust_avx2/hash_shake256x4.c pqclean_sphincs-shake256-256s-robust_avx2/sign.c pqclean_sphincs-shake256-256s-robust_avx2/thash_shake256_robust.c pqclean_sphincs-shake256-256s-robust_avx2/thash_shake256_robustx4.c pqclean_sphincs-shake256-256s-robust_avx2/utils.c pqclean_sphincs-shake256-256s-robust_avx2/utilsx4.c pqclean_sphincs-shake256-256s-robust_avx2/wots.c) - target_include_directories(sphincs_shake256_256s_robust_avx2 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-shake256-256s-robust_avx2) + add_library(sphincs_shake256_256s_robust_avx2 OBJECT pqclean_sphincs-shake-256s-robust_avx2/address.c pqclean_sphincs-shake-256s-robust_avx2/context_shake.c pqclean_sphincs-shake-256s-robust_avx2/fips202x4.c pqclean_sphincs-shake-256s-robust_avx2/fors.c pqclean_sphincs-shake-256s-robust_avx2/hash_shake.c pqclean_sphincs-shake-256s-robust_avx2/hash_shakex4.c pqclean_sphincs-shake-256s-robust_avx2/merkle.c pqclean_sphincs-shake-256s-robust_avx2/sign.c pqclean_sphincs-shake-256s-robust_avx2/thash_shake_robust.c pqclean_sphincs-shake-256s-robust_avx2/thash_shake_robustx4.c pqclean_sphincs-shake-256s-robust_avx2/utils.c pqclean_sphincs-shake-256s-robust_avx2/utilsx4.c pqclean_sphincs-shake-256s-robust_avx2/wots.c) + target_include_directories(sphincs_shake256_256s_robust_avx2 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-shake-256s-robust_avx2) target_include_directories(sphincs_shake256_256s_robust_avx2 PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) target_compile_options(sphincs_shake256_256s_robust_avx2 PRIVATE -mavx2) set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) endif() +if(OQS_ENABLE_SIG_sphincs_shake256_256s_robust_aarch64) + add_library(sphincs_shake256_256s_robust_aarch64 OBJECT pqclean_sphincs-shake-256s-robust_aarch64/address.c pqclean_sphincs-shake-256s-robust_aarch64/context_shake.c pqclean_sphincs-shake-256s-robust_aarch64/f1600x2.s pqclean_sphincs-shake-256s-robust_aarch64/f1600x2_const.c pqclean_sphincs-shake-256s-robust_aarch64/fips202x2.c pqclean_sphincs-shake-256s-robust_aarch64/fors.c pqclean_sphincs-shake-256s-robust_aarch64/hash_shake.c pqclean_sphincs-shake-256s-robust_aarch64/hash_shakex2.c pqclean_sphincs-shake-256s-robust_aarch64/merkle.c pqclean_sphincs-shake-256s-robust_aarch64/sign.c pqclean_sphincs-shake-256s-robust_aarch64/thash_shake_robustx2.c pqclean_sphincs-shake-256s-robust_aarch64/utils.c pqclean_sphincs-shake-256s-robust_aarch64/utilsx2.c pqclean_sphincs-shake-256s-robust_aarch64/wots.c) + target_include_directories(sphincs_shake256_256s_robust_aarch64 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-shake-256s-robust_aarch64) + target_include_directories(sphincs_shake256_256s_robust_aarch64 PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) + target_compile_options(sphincs_shake256_256s_robust_aarch64 PRIVATE -msha3) + set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) +endif() + if(OQS_ENABLE_SIG_sphincs_shake256_256s_simple) - add_library(sphincs_shake256_256s_simple_clean OBJECT sig_sphincs_shake256_256s_simple.c pqclean_sphincs-shake256-256s-simple_clean/address.c pqclean_sphincs-shake256-256s-simple_clean/fors.c pqclean_sphincs-shake256-256s-simple_clean/hash_shake256.c pqclean_sphincs-shake256-256s-simple_clean/sign.c pqclean_sphincs-shake256-256s-simple_clean/thash_shake256_simple.c pqclean_sphincs-shake256-256s-simple_clean/utils.c pqclean_sphincs-shake256-256s-simple_clean/wots.c) - target_include_directories(sphincs_shake256_256s_simple_clean PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-shake256-256s-simple_clean) + add_library(sphincs_shake256_256s_simple_clean OBJECT sig_sphincs_shake256_256s_simple.c pqclean_sphincs-shake-256s-simple_clean/address.c pqclean_sphincs-shake-256s-simple_clean/context_shake.c pqclean_sphincs-shake-256s-simple_clean/fors.c pqclean_sphincs-shake-256s-simple_clean/hash_shake.c pqclean_sphincs-shake-256s-simple_clean/merkle.c pqclean_sphincs-shake-256s-simple_clean/sign.c pqclean_sphincs-shake-256s-simple_clean/thash_shake_simple.c pqclean_sphincs-shake-256s-simple_clean/utils.c pqclean_sphincs-shake-256s-simple_clean/utilsx1.c pqclean_sphincs-shake-256s-simple_clean/wots.c pqclean_sphincs-shake-256s-simple_clean/wotsx1.c) + target_include_directories(sphincs_shake256_256s_simple_clean PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-shake-256s-simple_clean) target_include_directories(sphincs_shake256_256s_simple_clean PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) endif() if(OQS_ENABLE_SIG_sphincs_shake256_256s_simple_avx2) - add_library(sphincs_shake256_256s_simple_avx2 OBJECT pqclean_sphincs-shake256-256s-simple_avx2/address.c pqclean_sphincs-shake256-256s-simple_avx2/fors.c pqclean_sphincs-shake256-256s-simple_avx2/hash_shake256.c pqclean_sphincs-shake256-256s-simple_avx2/hash_shake256x4.c pqclean_sphincs-shake256-256s-simple_avx2/sign.c pqclean_sphincs-shake256-256s-simple_avx2/thash_shake256_simple.c pqclean_sphincs-shake256-256s-simple_avx2/thash_shake256_simplex4.c pqclean_sphincs-shake256-256s-simple_avx2/utils.c pqclean_sphincs-shake256-256s-simple_avx2/utilsx4.c pqclean_sphincs-shake256-256s-simple_avx2/wots.c) - target_include_directories(sphincs_shake256_256s_simple_avx2 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-shake256-256s-simple_avx2) + add_library(sphincs_shake256_256s_simple_avx2 OBJECT pqclean_sphincs-shake-256s-simple_avx2/address.c pqclean_sphincs-shake-256s-simple_avx2/context_shake.c pqclean_sphincs-shake-256s-simple_avx2/fips202x4.c pqclean_sphincs-shake-256s-simple_avx2/fors.c pqclean_sphincs-shake-256s-simple_avx2/hash_shake.c pqclean_sphincs-shake-256s-simple_avx2/hash_shakex4.c pqclean_sphincs-shake-256s-simple_avx2/merkle.c pqclean_sphincs-shake-256s-simple_avx2/sign.c pqclean_sphincs-shake-256s-simple_avx2/thash_shake_simple.c pqclean_sphincs-shake-256s-simple_avx2/thash_shake_simplex4.c pqclean_sphincs-shake-256s-simple_avx2/utils.c pqclean_sphincs-shake-256s-simple_avx2/utilsx4.c pqclean_sphincs-shake-256s-simple_avx2/wots.c) + target_include_directories(sphincs_shake256_256s_simple_avx2 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-shake-256s-simple_avx2) target_include_directories(sphincs_shake256_256s_simple_avx2 PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) target_compile_options(sphincs_shake256_256s_simple_avx2 PRIVATE -mavx2) set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) endif() +if(OQS_ENABLE_SIG_sphincs_shake256_256s_simple_aarch64) + add_library(sphincs_shake256_256s_simple_aarch64 OBJECT pqclean_sphincs-shake-256s-simple_aarch64/address.c pqclean_sphincs-shake-256s-simple_aarch64/context_shake.c pqclean_sphincs-shake-256s-simple_aarch64/f1600x2.s pqclean_sphincs-shake-256s-simple_aarch64/f1600x2_const.c pqclean_sphincs-shake-256s-simple_aarch64/fips202x2.c pqclean_sphincs-shake-256s-simple_aarch64/fors.c pqclean_sphincs-shake-256s-simple_aarch64/hash_shake.c pqclean_sphincs-shake-256s-simple_aarch64/hash_shakex2.c pqclean_sphincs-shake-256s-simple_aarch64/merkle.c pqclean_sphincs-shake-256s-simple_aarch64/sign.c pqclean_sphincs-shake-256s-simple_aarch64/thash_shake_simplex2.c pqclean_sphincs-shake-256s-simple_aarch64/utils.c pqclean_sphincs-shake-256s-simple_aarch64/utilsx2.c pqclean_sphincs-shake-256s-simple_aarch64/wots.c) + target_include_directories(sphincs_shake256_256s_simple_aarch64 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-shake-256s-simple_aarch64) + target_include_directories(sphincs_shake256_256s_simple_aarch64 PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) + target_compile_options(sphincs_shake256_256s_simple_aarch64 PRIVATE -msha3) + set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) +endif() + set(SPHINCS_OBJS ${_SPHINCS_OBJS} PARENT_SCOPE) diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/address.c b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/address.c index acaca75ef8..b956e9cb29 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/address.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/address.c @@ -1,78 +1,91 @@ #include +#include #include "address.h" #include "params.h" #include "utils.h" -void PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]) { - int i; - - for (i = 0; i < 8; i++) { - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_ull_to_bytes( - bytes + i * 4, 4, addr[i]); - } -} - -void PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_set_layer_addr( - uint32_t addr[8], uint32_t layer) { - addr[0] = layer; +/* + * Specify which level of Merkle tree (the "layer") we're working on + */ +void set_layer_addr(uint32_t addr[8], uint32_t layer) { + ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; } -void PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_set_tree_addr( - uint32_t addr[8], uint64_t tree) { - addr[1] = 0; - addr[2] = (uint32_t) (tree >> 32); - addr[3] = (uint32_t) tree; +/* + * Specify which Merkle tree within the level (the "tree address") we're working on + */ +void set_tree_addr(uint32_t addr[8], uint64_t tree) { + ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); } -void PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_set_type( - uint32_t addr[8], uint32_t type) { - addr[4] = type; +/* + * Specify the reason we'll use this address structure for, that is, what + * hash will we compute with it. This is used so that unrelated types of + * hashes don't accidentally get the same address structure. The type will be + * one of the SPX_ADDR_TYPE constants + */ +void set_type(uint32_t addr[8], uint32_t type) { + ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; } -void PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; +/* + * Copy the layer and tree fields of the address structure. This is used + * when we're doing multiple types of hashes within the same Merkle tree + */ +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); } /* These functions are used for OTS addresses. */ -void PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_set_keypair_addr( - uint32_t addr[8], uint32_t keypair) { - addr[5] = keypair; +/* + * Specify which Merkle leaf we're working on; that is, which OTS keypair + * we're talking about. + */ +void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { + ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; } -void PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; - out[5] = in[5]; +/* + * Copy the layer, tree and keypair fields of the address structure. This is + * used when we're doing multiple things within the same OTS keypair + */ +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); + ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; } -void PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_set_chain_addr( - uint32_t addr[8], uint32_t chain) { - addr[6] = chain; +/* + * Specify which Merkle chain within the OTS we're working with + * (the chain address) + */ +void set_chain_addr(uint32_t addr[8], uint32_t chain) { + ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; } -void PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_set_hash_addr( - uint32_t addr[8], uint32_t hash) { - addr[7] = hash; +/* + * Specify where in the Merkle chain we are +* (the hash address) + */ +void set_hash_addr(uint32_t addr[8], uint32_t hash) { + ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; } /* These functions are used for all hash tree addresses (including FORS). */ -void PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_set_tree_height( - uint32_t addr[8], uint32_t tree_height) { - addr[6] = tree_height; +/* + * Specify the height of the node in the Merkle/FORS tree we are in + * (the tree height) + */ +void set_tree_height(uint32_t addr[8], uint32_t tree_height) { + ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; } -void PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_set_tree_index( - uint32_t addr[8], uint32_t tree_index) { - addr[7] = tree_index; +/* + * Specify the distance from the left edge of the node in the Merkle/FORS tree + * (the tree index) + */ +void set_tree_index(uint32_t addr[8], uint32_t tree_index) { + u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/address.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/address.h index 8003a25e8b..24a84eb40c 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/address.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/address.h @@ -1,50 +1,52 @@ -#ifndef PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_ADDRESS_H -#define PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_ADDRESS_H +#ifndef SPX_ADDRESS_H +#define SPX_ADDRESS_H #include -#define PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_ADDR_TYPE_WOTS 0 -#define PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_ADDR_TYPE_WOTSPK 1 -#define PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_ADDR_TYPE_HASHTREE 2 -#define PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_ADDR_TYPE_FORSTREE 3 -#define PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_ADDR_TYPE_FORSPK 4 +#include "params.h" -void PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]); +/* The hash types that are passed to set_type */ +#define SPX_ADDR_TYPE_WOTS 0 +#define SPX_ADDR_TYPE_WOTSPK 1 +#define SPX_ADDR_TYPE_HASHTREE 2 +#define SPX_ADDR_TYPE_FORSTREE 3 +#define SPX_ADDR_TYPE_FORSPK 4 +#define SPX_ADDR_TYPE_WOTSPRF 5 +#define SPX_ADDR_TYPE_FORSPRF 6 -void PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_set_layer_addr( - uint32_t addr[8], uint32_t layer); +#define set_layer_addr SPX_NAMESPACE(set_layer_addr) +void set_layer_addr(uint32_t addr[8], uint32_t layer); -void PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_set_tree_addr( - uint32_t addr[8], uint64_t tree); +#define set_tree_addr SPX_NAMESPACE(set_tree_addr) +void set_tree_addr(uint32_t addr[8], uint64_t tree); -void PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_set_type( - uint32_t addr[8], uint32_t type); +#define set_type SPX_NAMESPACE(set_type) +void set_type(uint32_t addr[8], uint32_t type); /* Copies the layer and tree part of one address into the other */ -void PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]); +#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); /* These functions are used for WOTS and FORS addresses. */ -void PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_set_keypair_addr( - uint32_t addr[8], uint32_t keypair); +#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) +void set_keypair_addr(uint32_t addr[8], uint32_t keypair); -void PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_set_chain_addr( - uint32_t addr[8], uint32_t chain); +#define set_chain_addr SPX_NAMESPACE(set_chain_addr) +void set_chain_addr(uint32_t addr[8], uint32_t chain); -void PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_set_hash_addr( - uint32_t addr[8], uint32_t hash); +#define set_hash_addr SPX_NAMESPACE(set_hash_addr) +void set_hash_addr(uint32_t addr[8], uint32_t hash); -void PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]); +#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); /* These functions are used for all hash tree addresses (including FORS). */ -void PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_set_tree_height( - uint32_t addr[8], uint32_t tree_height); +#define set_tree_height SPX_NAMESPACE(set_tree_height) +void set_tree_height(uint32_t addr[8], uint32_t tree_height); -void PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_set_tree_index( - uint32_t addr[8], uint32_t tree_index); +#define set_tree_index SPX_NAMESPACE(set_tree_index) +void set_tree_index(uint32_t addr[8], uint32_t tree_index); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/api.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/api.h index a5919f14f6..5eabcbd2d7 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/api.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/api.h @@ -4,15 +4,13 @@ #include #include - - -#define PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_CRYPTO_ALGNAME "SPHINCS+" +#define PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_CRYPTO_ALGNAME "SPHINCS+-haraka-128f-robust" #define PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_CRYPTO_SECRETKEYBYTES 64 #define PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_CRYPTO_PUBLICKEYBYTES 32 -#define PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_CRYPTO_BYTES 17088 -#define PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_CRYPTO_SEEDBYTES 48 +#define PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_CRYPTO_BYTES 17088 +#define PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_CRYPTO_SEEDBYTES 48 /* * Returns the length of a secret key, in bytes @@ -39,43 +37,41 @@ size_t PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_crypto_sign_seedbytes(void); * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] * Format pk: [root || PUB_SEED] */ -int PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed); +int PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); /* * Generates a SPHINCS+ key pair. * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] * Format pk: [root || PUB_SEED] */ -int PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk); +int PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); /** * Returns an array containing a detached signature. */ -int PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk); +int PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); /** * Verifies a detached signature and message under a given public key. */ -int PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk); +int PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, + const uint8_t *pk); /** * Returns an array containing the signature followed by the message. */ -int PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk); +int PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); /** * Verifies a given signature-message pair under a given public key. */ -int PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk); - +int PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/context.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/context.h new file mode 100644 index 0000000000..f03446b9cb --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/context.h @@ -0,0 +1,22 @@ +#ifndef SPX_CONTEXT_H +#define SPX_CONTEXT_H + +#include + +#include "immintrin.h" +#include "params.h" + +typedef struct { + uint8_t pub_seed[SPX_N]; + uint8_t sk_seed[SPX_N]; + + __m128i rc[40]; +} spx_ctx; + +#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) +void initialize_hash_function(spx_ctx *ctx); + +#define free_hash_function SPX_NAMESPACE(free_hash_function) +void free_hash_function(spx_ctx *ctx); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/context_haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/context_haraka.c new file mode 100644 index 0000000000..f1cd7e3664 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/context_haraka.c @@ -0,0 +1,11 @@ +#include "context.h" +#include "haraka.h" + +void initialize_hash_function(spx_ctx *ctx) { + tweak_constants(ctx); +} + +// we don't support heap-based haraka right now +void free_hash_function(spx_ctx *ctx) { + (void)ctx; // suppress unused variable warnings +} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/fors.c b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/fors.c index 032b0f5f77..f1b0639cfc 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/fors.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/fors.c @@ -2,8 +2,9 @@ #include #include -#include "address.h" #include "fors.h" + +#include "address.h" #include "hash.h" #include "hashx4.h" #include "thash.h" @@ -11,19 +12,24 @@ #include "utils.h" #include "utilsx4.h" +static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + prf_addr(sk, ctx, fors_leaf_addr); +} + static void fors_gen_skx4(unsigned char *sk0, unsigned char *sk1, unsigned char *sk2, - unsigned char *sk3, const unsigned char *sk_seed, - uint32_t fors_leaf_addrx4[4 * 8], - const hash_state *state_seeded) { - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_prf_addrx4(sk0, sk1, sk2, sk3, sk_seed, fors_leaf_addrx4, state_seeded); + unsigned char *sk3, const spx_ctx *ctx, + uint32_t fors_leaf_addrx4[4 * 8]) { + prf_addrx4(sk0, sk1, sk2, sk3, + ctx, fors_leaf_addrx4); } static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, - const unsigned char *pub_seed, - uint32_t fors_leaf_addr[8], const hash_state *state_seeded) { - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_thash_1(leaf, sk, pub_seed, fors_leaf_addr, state_seeded); + const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + thash(leaf, sk, 1, ctx, fors_leaf_addr); } static void fors_sk_to_leafx4(unsigned char *leaf0, @@ -34,57 +40,64 @@ static void fors_sk_to_leafx4(unsigned char *leaf0, const unsigned char *sk1, const unsigned char *sk2, const unsigned char *sk3, - const unsigned char *pub_seed, - uint32_t fors_leaf_addrx4[4 * 8], - const hash_state *state_seeded) { - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_thashx4_1(leaf0, leaf1, leaf2, leaf3, - sk0, sk1, sk2, sk3, pub_seed, fors_leaf_addrx4, state_seeded); + const spx_ctx *ctx, + uint32_t fors_leaf_addrx4[4 * 8]) { + thashx4(leaf0, leaf1, leaf2, leaf3, + sk0, sk1, sk2, sk3, + 1, ctx, fors_leaf_addrx4); } -static void fors_gen_leafx4(unsigned char *leaf0, - unsigned char *leaf1, - unsigned char *leaf2, - unsigned char *leaf3, - const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx0, - uint32_t addr_idx1, - uint32_t addr_idx2, - uint32_t addr_idx3, - const uint32_t fors_tree_addr[8], - const hash_state *state_seeded) { - uint32_t fors_leaf_addrx4[4 * 8] = {0}; +struct fors_gen_leaf_info { + uint32_t leaf_addrx[4 * 8]; +}; + +static void fors_gen_leafx4(unsigned char *leaf, + const spx_ctx *ctx, + uint32_t addr_idx, void *info) { + struct fors_gen_leaf_info *fors_info = info; + uint32_t *fors_leaf_addrx4 = fors_info->leaf_addrx; unsigned int j; - /* Only copy the parts that must be kept in fors_leaf_addrx4. */ + /* Only set the parts that the caller doesn't set */ for (j = 0; j < 4; j++) { - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_copy_keypair_addr(fors_leaf_addrx4 + j * 8, fors_tree_addr); - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_set_type(fors_leaf_addrx4 + j * 8, PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_ADDR_TYPE_FORSTREE); + set_tree_index(fors_leaf_addrx4 + j * 8, addr_idx + j); + set_type(fors_leaf_addrx4 + j * 8, SPX_ADDR_TYPE_FORSPRF); } - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_set_tree_index(fors_leaf_addrx4 + 0 * 8, addr_idx0); - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_set_tree_index(fors_leaf_addrx4 + 1 * 8, addr_idx1); - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_set_tree_index(fors_leaf_addrx4 + 2 * 8, addr_idx2); - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_set_tree_index(fors_leaf_addrx4 + 3 * 8, addr_idx3); + fors_gen_skx4(leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + leaf + 2 * SPX_N, + leaf + 3 * SPX_N, + ctx, fors_leaf_addrx4); + + for (j = 0; j < 4; j++) { + set_type(fors_leaf_addrx4 + j * 8, SPX_ADDR_TYPE_FORSTREE); + } - fors_gen_skx4(leaf0, leaf1, leaf2, leaf3, sk_seed, fors_leaf_addrx4, state_seeded); - fors_sk_to_leafx4(leaf0, leaf1, leaf2, leaf3, - leaf0, leaf1, leaf2, leaf3, pub_seed, fors_leaf_addrx4, state_seeded); + fors_sk_to_leafx4(leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + leaf + 2 * SPX_N, + leaf + 3 * SPX_N, + leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + leaf + 2 * SPX_N, + leaf + 3 * SPX_N, + ctx, fors_leaf_addrx4); } /** - * Interprets m as PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_FORS_HEIGHT-bit unsigned integers. - * Assumes m contains at least PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_FORS_TREES bits. - * Assumes indices has space for PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_FORS_TREES integers. + * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + * Assumes indices has space for SPX_FORS_TREES integers. */ static void message_to_indices(uint32_t *indices, const unsigned char *m) { unsigned int i, j; unsigned int offset = 0; - for (i = 0; i < PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_FORS_TREES; i++) { + for (i = 0; i < SPX_FORS_TREES; i++) { indices[i] = 0; - for (j = 0; j < PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_FORS_HEIGHT; j++) { - indices[i] ^= (((uint32_t)m[offset >> 3] >> (offset & 0x7)) & 0x1) << j; + for (j = 0; j < SPX_FORS_HEIGHT; j++) { + indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); offset++; } } @@ -92,68 +105,53 @@ static void message_to_indices(uint32_t *indices, const unsigned char *m) { /** * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_FORS_TREES bits. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. */ -void PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *state_seeded) { - /* Round up to multiple of 4 to prevent out-of-bounds for x4 parallelism */ - uint32_t indices[(PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_FORS_TREES + 3) & ~3] = {0}; - unsigned char roots[((PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_FORS_TREES + 3) & ~3) * PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N]; - /* Sign to a buffer, since we may not have a nice multiple of 4 and would - otherwise overrun the signature. */ - unsigned char sigbufx4[4 * PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N * (1 + PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_FORS_HEIGHT)]; - uint32_t fors_tree_addrx4[4 * 8] = {0}; +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + uint32_t fors_tree_addr[4 * 8] = {0}; + struct fors_gen_leaf_info fors_info = {0}; + uint32_t *fors_leaf_addr = fors_info.leaf_addrx; uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset[4] = {0}; - unsigned int i, j; + uint32_t idx_offset; + unsigned int i; - for (j = 0; j < 4; j++) { - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_copy_keypair_addr(fors_tree_addrx4 + j * 8, fors_addr); - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_set_type(fors_tree_addrx4 + j * 8, PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_ADDR_TYPE_FORSTREE); + for (i = 0; i < 4; i++) { + copy_keypair_addr(fors_tree_addr + 8 * i, fors_addr); + set_type(fors_tree_addr + 8 * i, SPX_ADDR_TYPE_FORSTREE); + copy_keypair_addr(fors_leaf_addr + 8 * i, fors_addr); } - - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_copy_keypair_addr(fors_pk_addr, fors_addr); - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_set_type(fors_pk_addr, PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_ADDR_TYPE_FORSPK); + copy_keypair_addr(fors_pk_addr, fors_addr); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); message_to_indices(indices, m); - for (i = 0; i < ((PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_FORS_TREES + 3) & ~0x3); i += 4) { - for (j = 0; j < 4; j++) { - if (i + j < PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_FORS_TREES) { - idx_offset[j] = (i + j) * (1 << PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_FORS_HEIGHT); + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_set_tree_height(fors_tree_addrx4 + j * 8, 0); - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_set_tree_index(fors_tree_addrx4 + j * 8, - indices[i + j] + idx_offset[j]); - } - } + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); - /* Include the secret key part that produces the selected leaf nodes. */ - fors_gen_skx4(sigbufx4 + 0 * PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N, - sigbufx4 + 1 * PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N, - sigbufx4 + 2 * PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N, - sigbufx4 + 3 * PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N, - sk_seed, fors_tree_addrx4, state_seeded); - - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_treehashx4_FORS_HEIGHT(roots + i * PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N, sigbufx4 + 4 * PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N, sk_seed, pub_seed, - &indices[i], idx_offset, fors_gen_leafx4, fors_tree_addrx4, - state_seeded); - - for (j = 0; j < 4; j++) { - if (i + j < PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_FORS_TREES) { - memcpy(sig, sigbufx4 + j * PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N, PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N); - memcpy(sig + PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N, - sigbufx4 + 4 * PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N + j * PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N * PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_FORS_HEIGHT, - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N * PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_FORS_HEIGHT); - sig += PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N * (1 + PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_FORS_HEIGHT); - } - } + /* Include the secret key part that produces the selected leaf node. */ + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); + fors_gen_sk(sig, ctx, fors_tree_addr); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + sig += SPX_N; + + /* Compute the authentication path for this leaf node. */ + treehashx4(roots + i * SPX_N, sig, ctx, + indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx4, + fors_tree_addr, &fors_info); + + sig += SPX_N * SPX_FORS_HEIGHT; } /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_thash_FORS_TREES(pk, roots, pub_seed, fors_pk_addr, state_seeded); + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); } /** @@ -161,46 +159,44 @@ void PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_fors_sign(unsigned char *sig, unsigne * This can be used for verification by comparing to a known public key, or to * subsequently verify a signature on the derived public key. The latter is the * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_FORS_TREES bits. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. */ -void PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, - const uint32_t fors_addr[8], - const hash_state *state_seeded) { - uint32_t indices[PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_FORS_TREES]; - unsigned char roots[PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_FORS_TREES * PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N]; - unsigned char leaf[PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N]; +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + unsigned char leaf[SPX_N]; uint32_t fors_tree_addr[8] = {0}; uint32_t fors_pk_addr[8] = {0}; uint32_t idx_offset; unsigned int i; - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_copy_keypair_addr(fors_tree_addr, fors_addr); - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_copy_keypair_addr(fors_pk_addr, fors_addr); + copy_keypair_addr(fors_tree_addr, fors_addr); + copy_keypair_addr(fors_pk_addr, fors_addr); - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_set_type(fors_tree_addr, PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_set_type(fors_pk_addr, PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_ADDR_TYPE_FORSPK); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); message_to_indices(indices, m); - for (i = 0; i < PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_FORS_TREES; i++) { - idx_offset = i * (1 << PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_FORS_HEIGHT); + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_set_tree_height(fors_tree_addr, 0); - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_set_tree_index(fors_tree_addr, indices[i] + idx_offset); + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); /* Derive the leaf from the included secret key part. */ - fors_sk_to_leaf(leaf, sig, pub_seed, fors_tree_addr, state_seeded); - sig += PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N; + fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); + sig += SPX_N; /* Derive the corresponding root node of this tree. */ - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_compute_root(roots + i * PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N, leaf, indices[i], idx_offset, - sig, PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_FORS_HEIGHT, pub_seed, fors_tree_addr, - state_seeded); - sig += PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N * PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_FORS_HEIGHT; + compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, + sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); + sig += SPX_N * SPX_FORS_HEIGHT; } /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_thash_FORS_TREES(pk, roots, pub_seed, fors_pk_addr, state_seeded); + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/fors.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/fors.h index 00cd71bc44..509140a178 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/fors.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/fors.h @@ -1,32 +1,32 @@ -#ifndef PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_FORS_H -#define PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_FORS_H +#ifndef SPX_FORS_H +#define SPX_FORS_H #include -#include "hash_state.h" +#include "context.h" #include "params.h" /** * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_FORS_TREES bits. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. */ -void PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_fors_sign( - unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *hash_state_seeded); +#define fors_sign SPX_NAMESPACE(fors_sign) +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); /** * Derives the FORS public key from a signature. * This can be used for verification by comparing to a known public key, or to * subsequently verify a signature on the derived public key. The latter is the * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_FORS_TREES bits. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. */ -void PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_fors_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, const uint32_t fors_addr[8], - const hash_state *hash_state_seeded); +#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/haraka.c index c2ab26b334..b414b691d7 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/haraka.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/haraka.c @@ -8,10 +8,12 @@ Plain C implementation of the Haraka256 and Haraka512 permutations. #include #include "haraka.h" +#include "harakax4.h" +#include "utils.h" #define HARAKAS_RATE 32 -#define u64 uint64_t +#define u64 unsigned long #define u128 __m128i #define LOAD(src) _mm_loadu_si128((u128 *)(src)) @@ -20,7 +22,7 @@ Plain C implementation of the Haraka256 and Haraka512 permutations. #define XOR128(a, b) _mm_xor_si128(a, b) #define AES2(s0, s1, rci) \ - (s0) = _mm_aesenc_si128(s0, *(rci)); \ + s0 = _mm_aesenc_si128(s0, *(rci)); \ (s1) = _mm_aesenc_si128(s1, *((rci) + 1)); \ (s0) = _mm_aesenc_si128(s0, *((rci) + 2)); \ (s1) = _mm_aesenc_si128(s1, *((rci) + 3)); @@ -32,7 +34,7 @@ Plain C implementation of the Haraka256 and Haraka512 permutations. AES2((s3)[0], (s3)[1], rci); #define AES4(s0, s1, s2, s3, rci) \ - (s0) = _mm_aesenc_si128(s0, *(rci)); \ + s0 = _mm_aesenc_si128(s0, *(rci)); \ (s1) = _mm_aesenc_si128(s1, *((rci) + 1)); \ (s2) = _mm_aesenc_si128(s2, *((rci) + 2)); \ (s3) = _mm_aesenc_si128(s3, *((rci) + 3)); \ @@ -68,17 +70,17 @@ Plain C implementation of the Haraka256 and Haraka512 permutations. _mm_storeu_si128((u128 *)((out) + 16), \ _mm_castpd_si128(_mm_shuffle_pd(_mm_castsi128_pd(s2), _mm_castsi128_pd(s3), 0))); -static void load_haraka_constants(u128 rc[40]) { - rc[ 0] = _mm_set_epi32((int)0x0684704c, (int)0xe620c00a, (int)0xb2c5fef0, (int)0x75817b9d); - rc[ 1] = _mm_set_epi32((int)0x8b66b4e1, (int)0x88f3a06b, (int)0x640f6ba4, (int)0x2f08f717); - rc[ 2] = _mm_set_epi32((int)0x3402de2d, (int)0x53f28498, (int)0xcf029d60, (int)0x9f029114); - rc[ 3] = _mm_set_epi32((int)0x0ed6eae6, (int)0x2e7b4f08, (int)0xbbf3bcaf, (int)0xfd5b4f79); - rc[ 4] = _mm_set_epi32((int)0xcbcfb0cb, (int)0x4872448b, (int)0x79eecd1c, (int)0xbe397044); - rc[ 5] = _mm_set_epi32((int)0x7eeacdee, (int)0x6e9032b7, (int)0x8d5335ed, (int)0x2b8a057b); - rc[ 6] = _mm_set_epi32((int)0x67c28f43, (int)0x5e2e7cd0, (int)0xe2412761, (int)0xda4fef1b); - rc[ 7] = _mm_set_epi32((int)0x2924d9b0, (int)0xafcacc07, (int)0x675ffde2, (int)0x1fc70b3b); - rc[ 8] = _mm_set_epi32((int)0xab4d63f1, (int)0xe6867fe9, (int)0xecdb8fca, (int)0xb9d465ee); - rc[ 9] = _mm_set_epi32((int)0x1c30bf84, (int)0xd4b7cd64, (int)0x5b2a404f, (int)0xad037e33); +static void load_haraka_constants(u128 *rc) { + rc[0] = _mm_set_epi32((int)0x0684704c, (int)0xe620c00a, (int)0xb2c5fef0, (int)0x75817b9d); + rc[1] = _mm_set_epi32((int)0x8b66b4e1, (int)0x88f3a06b, (int)0x640f6ba4, (int)0x2f08f717); + rc[2] = _mm_set_epi32((int)0x3402de2d, (int)0x53f28498, (int)0xcf029d60, (int)0x9f029114); + rc[3] = _mm_set_epi32((int)0x0ed6eae6, (int)0x2e7b4f08, (int)0xbbf3bcaf, (int)0xfd5b4f79); + rc[4] = _mm_set_epi32((int)0xcbcfb0cb, (int)0x4872448b, (int)0x79eecd1c, (int)0xbe397044); + rc[5] = _mm_set_epi32((int)0x7eeacdee, (int)0x6e9032b7, (int)0x8d5335ed, (int)0x2b8a057b); + rc[6] = _mm_set_epi32((int)0x67c28f43, (int)0x5e2e7cd0, (int)0xe2412761, (int)0xda4fef1b); + rc[7] = _mm_set_epi32((int)0x2924d9b0, (int)0xafcacc07, (int)0x675ffde2, (int)0x1fc70b3b); + rc[8] = _mm_set_epi32((int)0xab4d63f1, (int)0xe6867fe9, (int)0xecdb8fca, (int)0xb9d465ee); + rc[9] = _mm_set_epi32((int)0x1c30bf84, (int)0xd4b7cd64, (int)0x5b2a404f, (int)0xad037e33); rc[10] = _mm_set_epi32((int)0xb2cc0bb9, (int)0x941723bf, (int)0x69028b2e, (int)0x8df69800); rc[11] = _mm_set_epi32((int)0xfa0478a6, (int)0xde6f5572, (int)0x4aaa9ec8, (int)0x5c9d2d8a); rc[12] = _mm_set_epi32((int)0xdfb49f2b, (int)0x6b772a12, (int)0x0efa4f2e, (int)0x29129fd4); @@ -111,77 +113,65 @@ static void load_haraka_constants(u128 rc[40]) { rc[39] = _mm_set_epi32((int)0x756acc03, (int)0x02288288, (int)0x4ad6bdfd, (int)0xe9c59da1); } -void PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_tweak_constants( - harakactx *state, - const unsigned char *pk_seed, const unsigned char *sk_seed, - unsigned long long seed_length) { +void tweak_constants(spx_ctx *ctx) { int i; unsigned char buf[40 * 16]; /* Use the standard constants to generate tweaked ones. */ - load_haraka_constants(state->rc); - - /* Constants for sk.seed */ - if (sk_seed != NULL) { - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_haraka_S(buf, 40 * 16, sk_seed, seed_length, state); - /* Tweak constants with the pub_seed */ - for (i = 0; i < 40; i++) { - state->rc_sseed[i] = LOAD(buf + i * 16); - } - } + load_haraka_constants(ctx->rc); /* Constants for pk.seed */ - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_haraka_S(buf, 40 * 16, pk_seed, seed_length, state); + haraka_S(buf, 40 * 16, ctx->pub_seed, SPX_N, ctx); /* Tweak constants with the pub_seed */ for (i = 0; i < 40; i++) { - state->rc[i] = LOAD(buf + i * 16); + ctx->rc[i] = LOAD(buf + i * 16); } } -static void haraka_S_absorb(unsigned char *s, +static void haraka_S_absorb(unsigned char *s, unsigned int r, const unsigned char *m, unsigned long long mlen, - unsigned char p, - const harakactx *state) { + unsigned char p, const spx_ctx *ctx) { unsigned long long i; - unsigned char t[HARAKAS_RATE]; + PQCLEAN_VLA(unsigned char, t, r); - while (mlen >= HARAKAS_RATE) { + while (mlen >= r) { // XOR block to state STORE(s, XOR128(LOAD(s), LOAD(m))); STORE(s + 16, XOR128(LOAD(s + 16), LOAD(m + 16))); - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_haraka512_perm(s, s, state); - mlen -= HARAKAS_RATE; - m += HARAKAS_RATE; + haraka512_perm(s, s, ctx); + mlen -= r; + m += r; } - for (i = 0; i < HARAKAS_RATE; ++i) { + for (i = 0; i < r; ++i) { t[i] = 0; } for (i = 0; i < mlen; ++i) { t[i] = m[i]; } t[i] = p; - t[HARAKAS_RATE - 1] |= 128; + t[r - 1] |= 128; STORE(s, XOR128(LOAD(s), LOAD(t))); STORE(s + 16, XOR128(LOAD(s + 16), LOAD(t + 16))); } static void haraka_S_absorb4x(unsigned char *s, + unsigned int r, const unsigned char *m0, const unsigned char *m1, const unsigned char *m2, const unsigned char *m3, unsigned long long int mlen, unsigned char p, - const harakactx *state) { + const spx_ctx *ctx) { unsigned long long i; - unsigned char t0[HARAKAS_RATE]; - unsigned char t1[HARAKAS_RATE]; - unsigned char t2[HARAKAS_RATE]; - unsigned char t3[HARAKAS_RATE]; + PQCLEAN_VLA(unsigned char, t0, r); + PQCLEAN_VLA(unsigned char, t1, r); + PQCLEAN_VLA(unsigned char, t2, r); + PQCLEAN_VLA(unsigned char, t3, r); - while (mlen >= HARAKAS_RATE) { + while (mlen >= r) { // XOR block to state STORE(s, XOR128(LOAD(s), LOAD(m0))); STORE(s + 16, XOR128(LOAD(s + 16), LOAD(m0 + 16))); @@ -192,15 +182,15 @@ static void haraka_S_absorb4x(unsigned char *s, STORE(s + 192, XOR128(LOAD(s + 192), LOAD(m3))); STORE(s + 208, XOR128(LOAD(s + 208), LOAD(m3 + 16))); - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_haraka512_perm_x4(s, s, state); - mlen -= HARAKAS_RATE; - m0 += HARAKAS_RATE; - m1 += HARAKAS_RATE; - m2 += HARAKAS_RATE; - m3 += HARAKAS_RATE; + haraka512_perm_x4(s, s, ctx); + mlen -= r; + m0 += r; + m1 += r; + m2 += r; + m3 += r; } - for (i = 0; i < HARAKAS_RATE; ++i) { + for (i = 0; i < r; ++i) { t0[i] = 0; t1[i] = 0; t2[i] = 0; @@ -218,10 +208,10 @@ static void haraka_S_absorb4x(unsigned char *s, t2[i] = p; t3[i] = p; - t0[HARAKAS_RATE - 1] |= 128; - t1[HARAKAS_RATE - 1] |= 128; - t2[HARAKAS_RATE - 1] |= 128; - t3[HARAKAS_RATE - 1] |= 128; + t0[r - 1] |= 128; + t1[r - 1] |= 128; + t2[r - 1] |= 128; + t3[r - 1] |= 128; STORE(s, XOR128(LOAD(s), LOAD(t0))); STORE(s + 16, XOR128(LOAD(s + 16), LOAD(t0 + 16))); @@ -234,9 +224,10 @@ static void haraka_S_absorb4x(unsigned char *s, } static void haraka_S_squeezeblocks(unsigned char *h, unsigned long long nblocks, - unsigned char *s, unsigned int r, const harakactx *state) { + unsigned char *s, unsigned int r, + const spx_ctx *ctx) { while (nblocks > 0) { - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_haraka512_perm(s, s, state); + haraka512_perm(s, s, ctx); STORE(h, LOAD(s)); STORE(h + 16, LOAD(s + 16)); h += r; @@ -251,9 +242,9 @@ static void haraka_S_squeezeblocks4x(unsigned char *h0, unsigned long long nblocks, unsigned char *s, unsigned int r, - const harakactx *state) { + const spx_ctx *ctx) { while (nblocks > 0) { - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_haraka512_perm_x4(s, s, state); + haraka512_perm_x4(s, s, ctx); STORE(h0, LOAD(s)); STORE(h0 + 16, LOAD(s + 16)); STORE(h1, LOAD(s + 64)); @@ -270,7 +261,7 @@ static void haraka_S_squeezeblocks4x(unsigned char *h0, } } -void PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_haraka_S_inc_init(uint8_t *s_inc) { +void haraka_S_inc_init(uint8_t *s_inc) { size_t i; for (i = 0; i < 64; i++) { @@ -279,7 +270,8 @@ void PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_haraka_S_inc_init(uint8_t *s_inc) { s_inc[64] = 0; } -void PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, const harakactx *state) { +void haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, + const spx_ctx *ctx) { size_t i; /* Recall that s_inc[64] is the non-absorbed bytes xored into the state */ @@ -293,16 +285,16 @@ void PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_haraka_S_inc_absorb(uint8_t *s_inc, c m += HARAKAS_RATE - s_inc[64]; s_inc[64] = 0; - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_haraka512_perm(s_inc, s_inc, state); + haraka512_perm(s_inc, s_inc, ctx); } for (i = 0; i < mlen; i++) { s_inc[s_inc[64] + i] ^= m[i]; } - s_inc[64] = (uint8_t)(s_inc[64] + mlen); + s_inc[64] += (uint8_t)mlen; } -void PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_haraka_S_inc_finalize(uint8_t *s_inc) { +void haraka_S_inc_finalize(uint8_t *s_inc) { /* After haraka_S_inc_absorb, we are guaranteed that s_inc[64] < HARAKAS_RATE, so we can always use one more byte for p in the current state. */ s_inc[s_inc[64]] ^= 0x1F; @@ -310,22 +302,23 @@ void PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_haraka_S_inc_finalize(uint8_t *s_inc) s_inc[64] = 0; } -void PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, const harakactx *state) { +void haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, + const spx_ctx *ctx) { size_t i; /* First consume any bytes we still have sitting around */ for (i = 0; i < outlen && i < s_inc[64]; i++) { /* There are s_inc[64] bytes left, so r - s_inc[64] is the first available byte. We consume from there, i.e., up to r. */ - out[i] = (uint8_t)s_inc[(HARAKAS_RATE - s_inc[64] + (uint8_t)i)]; + out[i] = (uint8_t)s_inc[(HARAKAS_RATE - s_inc[64] + i)]; } out += i; outlen -= i; - s_inc[64] = (uint8_t)(s_inc[64] - i); + s_inc[64] -= (uint8_t)i; /* Then squeeze the remaining necessary blocks */ while (outlen > 0) { - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_haraka512_perm(s_inc, s_inc, state); + haraka512_perm(s_inc, s_inc, ctx); for (i = 0; i < outlen && i < HARAKAS_RATE; i++) { out[i] = s_inc[i]; @@ -336,8 +329,9 @@ void PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_haraka_S_inc_squeeze(uint8_t *out, si } } -void PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_haraka_S(unsigned char *out, unsigned long long outlen, - const unsigned char *in, unsigned long long inlen, const harakactx *state) { +void haraka_S(unsigned char *out, unsigned long long outlen, + const unsigned char *in, unsigned long long inlen, + const spx_ctx *ctx) { unsigned long long i; unsigned char s[64]; unsigned char d[32]; @@ -345,30 +339,30 @@ void PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_haraka_S(unsigned char *out, unsigned for (i = 0; i < 64; i++) { s[i] = 0; } - haraka_S_absorb(s, in, inlen, 0x1F, state); + haraka_S_absorb(s, HARAKAS_RATE, in, inlen, 0x1F, ctx); - haraka_S_squeezeblocks(out, outlen / HARAKAS_RATE, s, HARAKAS_RATE, state); + haraka_S_squeezeblocks(out, outlen / HARAKAS_RATE, s, HARAKAS_RATE, ctx); out += (outlen / HARAKAS_RATE) * HARAKAS_RATE; if (outlen % HARAKAS_RATE) { - haraka_S_squeezeblocks(d, 1, s, HARAKAS_RATE, state); + haraka_S_squeezeblocks(d, 1, s, HARAKAS_RATE, ctx); for (i = 0; i < outlen % HARAKAS_RATE; i++) { out[i] = d[i]; } } } -void PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_haraka_Sx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned long long outlen, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - unsigned long long inlen, - const harakactx *state) { +void haraka_Sx4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned long long outlen, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + unsigned long long inlen, + const spx_ctx *ctx) { unsigned long long i; unsigned char s[64 * 4]; unsigned char d0[32]; @@ -379,16 +373,17 @@ void PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_haraka_Sx4(unsigned char *out0, for (i = 0; i < 64 * 4; i++) { s[i] = 0; } - haraka_S_absorb4x(s, in0, in1, in2, in3, inlen, 0x1F, state); + haraka_S_absorb4x(s, HARAKAS_RATE, in0, in1, in2, in3, inlen, 0x1F, ctx); - haraka_S_squeezeblocks4x(out0, out1, out2, out3, outlen / HARAKAS_RATE, s, HARAKAS_RATE, state); + haraka_S_squeezeblocks4x(out0, out1, out2, out3, outlen / HARAKAS_RATE, s, + HARAKAS_RATE, ctx); out0 += (outlen / HARAKAS_RATE) * HARAKAS_RATE; out1 += (outlen / HARAKAS_RATE) * HARAKAS_RATE; out2 += (outlen / HARAKAS_RATE) * HARAKAS_RATE; out3 += (outlen / HARAKAS_RATE) * HARAKAS_RATE; if (outlen % HARAKAS_RATE) { - haraka_S_squeezeblocks4x(d0, d1, d2, d3, 1, s, HARAKAS_RATE, state); + haraka_S_squeezeblocks4x(d0, d1, d2, d3, 1, s, HARAKAS_RATE, ctx); for (i = 0; i < outlen % HARAKAS_RATE; i++) { out0[i] = d0[i]; out1[i] = d1[i]; @@ -398,7 +393,8 @@ void PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_haraka_Sx4(unsigned char *out0, } } -void PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_haraka512_perm(unsigned char *out, const unsigned char *in, const harakactx *state) { +void haraka512_perm(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx) { u128 s[4], tmp; s[0] = LOAD(in); @@ -406,19 +402,19 @@ void PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_haraka512_perm(unsigned char *out, co s[2] = LOAD(in + 32); s[3] = LOAD(in + 48); - AES4(s[0], s[1], s[2], s[3], state->rc); + AES4(s[0], s[1], s[2], s[3], ctx->rc); MIX4(s[0], s[1], s[2], s[3]); - AES4(s[0], s[1], s[2], s[3], state->rc + 8); + AES4(s[0], s[1], s[2], s[3], ctx->rc + 8); MIX4(s[0], s[1], s[2], s[3]); - AES4(s[0], s[1], s[2], s[3], state->rc + 16); + AES4(s[0], s[1], s[2], s[3], ctx->rc + 16); MIX4(s[0], s[1], s[2], s[3]); - AES4(s[0], s[1], s[2], s[3], state->rc + 24); + AES4(s[0], s[1], s[2], s[3], ctx->rc + 24); MIX4(s[0], s[1], s[2], s[3]); - AES4(s[0], s[1], s[2], s[3], state->rc + 32); + AES4(s[0], s[1], s[2], s[3], ctx->rc + 32); MIX4(s[0], s[1], s[2], s[3]); STORE(out, s[0]); @@ -427,7 +423,8 @@ void PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_haraka512_perm(unsigned char *out, co STORE(out + 48, s[3]); } -void PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_haraka512_perm_x4(unsigned char *out, const unsigned char *in, const harakactx *state) { +void haraka512_perm_x4(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx) { u128 s[4][4], tmp; s[0][0] = LOAD(in); @@ -447,31 +444,31 @@ void PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_haraka512_perm_x4(unsigned char *out, s[3][2] = LOAD(in + 224); s[3][3] = LOAD(in + 240); - AES4_4x(s[0], s[1], s[2], s[3], state->rc); + AES4_4x(s[0], s[1], s[2], s[3], ctx->rc); MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - AES4_4x(s[0], s[1], s[2], s[3], state->rc + 8); + AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 8); MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - AES4_4x(s[0], s[1], s[2], s[3], state->rc + 16); + AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 16); MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - AES4_4x(s[0], s[1], s[2], s[3], state->rc + 24); + AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 24); MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - AES4_4x(s[0], s[1], s[2], s[3], state->rc + 32); + AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 32); MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); @@ -495,7 +492,8 @@ void PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_haraka512_perm_x4(unsigned char *out, STORE(out + 240, s[3][3]); } -void PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_haraka512(unsigned char *out, const unsigned char *in, const harakactx *state) { +void haraka512(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx) { u128 s[4], tmp; s[0] = LOAD(in); @@ -503,19 +501,19 @@ void PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_haraka512(unsigned char *out, const u s[2] = LOAD(in + 32); s[3] = LOAD(in + 48); - AES4(s[0], s[1], s[2], s[3], state->rc); + AES4(s[0], s[1], s[2], s[3], ctx->rc); MIX4(s[0], s[1], s[2], s[3]); - AES4(s[0], s[1], s[2], s[3], state->rc + 8); + AES4(s[0], s[1], s[2], s[3], ctx->rc + 8); MIX4(s[0], s[1], s[2], s[3]); - AES4(s[0], s[1], s[2], s[3], state->rc + 16); + AES4(s[0], s[1], s[2], s[3], ctx->rc + 16); MIX4(s[0], s[1], s[2], s[3]); - AES4(s[0], s[1], s[2], s[3], state->rc + 24); + AES4(s[0], s[1], s[2], s[3], ctx->rc + 24); MIX4(s[0], s[1], s[2], s[3]); - AES4(s[0], s[1], s[2], s[3], state->rc + 32); + AES4(s[0], s[1], s[2], s[3], ctx->rc + 32); MIX4(s[0], s[1], s[2], s[3]); s[0] = XOR128(s[0], LOAD(in)); @@ -527,7 +525,8 @@ void PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_haraka512(unsigned char *out, const u TRUNCSTORE(out, s[0], s[1], s[2], s[3]); } -void PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_haraka512x4(unsigned char *out, const unsigned char *in, const harakactx *state) { +void haraka512x4(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx) { u128 s[4][4], tmp; s[0][0] = LOAD(in); @@ -547,31 +546,31 @@ void PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_haraka512x4(unsigned char *out, const s[3][2] = LOAD(in + 224); s[3][3] = LOAD(in + 240); - AES4_4x(s[0], s[1], s[2], s[3], state->rc); + AES4_4x(s[0], s[1], s[2], s[3], ctx->rc); MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - AES4_4x(s[0], s[1], s[2], s[3], state->rc + 8); + AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 8); MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - AES4_4x(s[0], s[1], s[2], s[3], state->rc + 16); + AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 16); MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - AES4_4x(s[0], s[1], s[2], s[3], state->rc + 24); + AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 24); MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - AES4_4x(s[0], s[1], s[2], s[3], state->rc + 32); + AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 32); MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); @@ -600,25 +599,26 @@ void PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_haraka512x4(unsigned char *out, const TRUNCSTORE((out + 96), s[3][0], s[3][1], s[3][2], s[3][3]); } -void PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_haraka256(unsigned char *out, const unsigned char *in, const harakactx *state) { +void haraka256(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx) { u128 s[2], tmp; s[0] = LOAD(in); s[1] = LOAD(in + 16); - AES2(s[0], s[1], state->rc); + AES2(s[0], s[1], ctx->rc); MIX2(s[0], s[1]); - AES2(s[0], s[1], state->rc + 4); + AES2(s[0], s[1], ctx->rc + 4); MIX2(s[0], s[1]); - AES2(s[0], s[1], state->rc + 8); + AES2(s[0], s[1], ctx->rc + 8); MIX2(s[0], s[1]); - AES2(s[0], s[1], state->rc + 12); + AES2(s[0], s[1], ctx->rc + 12); MIX2(s[0], s[1]); - AES2(s[0], s[1], state->rc + 16); + AES2(s[0], s[1], ctx->rc + 16); MIX2(s[0], s[1]); s[0] = XOR128(s[0], LOAD(in)); @@ -628,7 +628,8 @@ void PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_haraka256(unsigned char *out, const u STORE(out + 16, s[1]); } -void PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_haraka256x4(unsigned char *out, const unsigned char *in, const harakactx *state) { +void haraka256x4(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx) { u128 s[4][2], tmp; s[0][0] = LOAD(in); @@ -641,7 +642,7 @@ void PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_haraka256x4(unsigned char *out, const s[3][1] = LOAD(in + 112); // Round 1 - AES2_4x(s[0], s[1], s[2], s[3], state->rc); + AES2_4x(s[0], s[1], s[2], s[3], ctx->rc); MIX2(s[0][0], s[0][1]); MIX2(s[1][0], s[1][1]); @@ -649,7 +650,7 @@ void PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_haraka256x4(unsigned char *out, const MIX2(s[3][0], s[3][1]); // Round 2 - AES2_4x(s[0], s[1], s[2], s[3], state->rc + 4); + AES2_4x(s[0], s[1], s[2], s[3], ctx->rc + 4); MIX2(s[0][0], s[0][1]); MIX2(s[1][0], s[1][1]); @@ -657,7 +658,7 @@ void PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_haraka256x4(unsigned char *out, const MIX2(s[3][0], s[3][1]); // Round 3 - AES2_4x(s[0], s[1], s[2], s[3], state->rc + 8); + AES2_4x(s[0], s[1], s[2], s[3], ctx->rc + 8); MIX2(s[0][0], s[0][1]); MIX2(s[1][0], s[1][1]); @@ -665,7 +666,7 @@ void PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_haraka256x4(unsigned char *out, const MIX2(s[3][0], s[3][1]); // Round 4 - AES2_4x(s[0], s[1], s[2], s[3], state->rc + 12); + AES2_4x(s[0], s[1], s[2], s[3], ctx->rc + 12); MIX2(s[0][0], s[0][1]); MIX2(s[1][0], s[1][1]); @@ -673,7 +674,7 @@ void PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_haraka256x4(unsigned char *out, const MIX2(s[3][0], s[3][1]); // Round 5 - AES2_4x(s[0], s[1], s[2], s[3], state->rc + 16); + AES2_4x(s[0], s[1], s[2], s[3], ctx->rc + 16); MIX2(s[0][0], s[0][1]); MIX2(s[1][0], s[1][1]); @@ -699,103 +700,3 @@ void PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_haraka256x4(unsigned char *out, const STORE(out + 96, s[3][0]); STORE(out + 112, s[3][1]); } - -void PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_haraka256_sk(unsigned char *out, const unsigned char *in, const harakactx *state) { - u128 s[2], tmp; - - s[0] = LOAD(in); - s[1] = LOAD(in + 16); - - AES2(s[0], s[1], state->rc_sseed); - MIX2(s[0], s[1]); - - AES2(s[0], s[1], state->rc_sseed + 4); - MIX2(s[0], s[1]); - - AES2(s[0], s[1], state->rc_sseed + 8); - MIX2(s[0], s[1]); - - AES2(s[0], s[1], state->rc_sseed + 12); - MIX2(s[0], s[1]); - - AES2(s[0], s[1], state->rc_sseed + 16); - MIX2(s[0], s[1]); - - s[0] = XOR128(s[0], LOAD(in)); - s[1] = XOR128(s[1], LOAD(in + 16)); - - STORE(out, s[0]); - STORE(out + 16, s[1]); -} - -void PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_haraka256_skx4(unsigned char *out, const unsigned char *in, const harakactx *state) { - u128 s[4][2], tmp; - - s[0][0] = LOAD(in); - s[0][1] = LOAD(in + 16); - s[1][0] = LOAD(in + 32); - s[1][1] = LOAD(in + 48); - s[2][0] = LOAD(in + 64); - s[2][1] = LOAD(in + 80); - s[3][0] = LOAD(in + 96); - s[3][1] = LOAD(in + 112); - - // Round 1 - AES2_4x(s[0], s[1], s[2], s[3], state->rc_sseed); - - MIX2(s[0][0], s[0][1]); - MIX2(s[1][0], s[1][1]); - MIX2(s[2][0], s[2][1]); - MIX2(s[3][0], s[3][1]); - - // Round 2 - AES2_4x(s[0], s[1], s[2], s[3], state->rc_sseed + 4); - - MIX2(s[0][0], s[0][1]); - MIX2(s[1][0], s[1][1]); - MIX2(s[2][0], s[2][1]); - MIX2(s[3][0], s[3][1]); - - // Round 3 - AES2_4x(s[0], s[1], s[2], s[3], state->rc_sseed + 8); - - MIX2(s[0][0], s[0][1]); - MIX2(s[1][0], s[1][1]); - MIX2(s[2][0], s[2][1]); - MIX2(s[3][0], s[3][1]); - - // Round 4 - AES2_4x(s[0], s[1], s[2], s[3], state->rc_sseed + 12); - - MIX2(s[0][0], s[0][1]); - MIX2(s[1][0], s[1][1]); - MIX2(s[2][0], s[2][1]); - MIX2(s[3][0], s[3][1]); - - // Round 5 - AES2_4x(s[0], s[1], s[2], s[3], state->rc_sseed + 16); - - MIX2(s[0][0], s[0][1]); - MIX2(s[1][0], s[1][1]); - MIX2(s[2][0], s[2][1]); - MIX2(s[3][0], s[3][1]); - - // Feed Forward - s[0][0] = XOR128(s[0][0], LOAD(in)); - s[0][1] = XOR128(s[0][1], LOAD(in + 16)); - s[1][0] = XOR128(s[1][0], LOAD(in + 32)); - s[1][1] = XOR128(s[1][1], LOAD(in + 48)); - s[2][0] = XOR128(s[2][0], LOAD(in + 64)); - s[2][1] = XOR128(s[2][1], LOAD(in + 80)); - s[3][0] = XOR128(s[3][0], LOAD(in + 96)); - s[3][1] = XOR128(s[3][1], LOAD(in + 112)); - - STORE(out, s[0][0]); - STORE(out + 16, s[0][1]); - STORE(out + 32, s[1][0]); - STORE(out + 48, s[1][1]); - STORE(out + 64, s[2][0]); - STORE(out + 80, s[2][1]); - STORE(out + 96, s[3][0]); - STORE(out + 112, s[3][1]); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/haraka.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/haraka.h index 228cacda3e..737cb6065f 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/haraka.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/haraka.h @@ -1,57 +1,42 @@ -#ifndef PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_HARAKA_H -#define PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_HARAKA_H +#ifndef SPX_HARAKA_H +#define SPX_HARAKA_H -#include -#include -#include - -typedef struct { - __m128i rc[40]; - __m128i rc_sseed[40]; -} harakactx; +#include "context.h" +#include "params.h" /* Tweak constants with seed */ -void PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_tweak_constants( - harakactx *state, - const unsigned char *pk_seed, const unsigned char *sk_seed, - unsigned long long seed_length); +#define tweak_constants SPX_NAMESPACE(tweak_constants) +void tweak_constants(spx_ctx *ctx); /* Haraka Sponge */ -void PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_haraka_S_inc_init(uint8_t *s_inc); -void PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, const harakactx *state); -void PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_haraka_S_inc_finalize(uint8_t *s_inc); -void PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, const harakactx *state); -void PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_haraka_S( - unsigned char *out, unsigned long long outlen, - const unsigned char *in, unsigned long long inlen, const harakactx *state); -void PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_haraka_Sx4( - unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned long long outlen, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - unsigned long long inlen, - const harakactx *state); - +#define haraka_S_inc_init SPX_NAMESPACE(haraka_S_inc_init) +void haraka_S_inc_init(uint8_t *s_inc); +#define haraka_S_inc_absorb SPX_NAMESPACE(haraka_S_inc_absorb) +void haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, + const spx_ctx *ctx); +#define haraka_S_inc_finalize SPX_NAMESPACE(haraka_S_inc_finalize) +void haraka_S_inc_finalize(uint8_t *s_inc); +#define haraka_S_inc_squeeze SPX_NAMESPACE(haraka_S_inc_squeeze) +void haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, + const spx_ctx *ctx); +#define haraka_S SPX_NAMESPACE(haraka_S) +void haraka_S(unsigned char *out, unsigned long long outlen, + const unsigned char *in, unsigned long long inlen, + const spx_ctx *ctx); /* Applies the 512-bit Haraka permutation to in. */ -void PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_haraka512_perm(unsigned char *out, const unsigned char *in, const harakactx *state); -void PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_haraka512_perm_x4(unsigned char *out, const unsigned char *in, const harakactx *state); +#define haraka512_perm SPX_NAMESPACE(haraka512_perm) +void haraka512_perm(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx); /* Implementation of Haraka-512 */ -void PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_haraka512(unsigned char *out, const unsigned char *in, const harakactx *state); -void PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_haraka512x4(unsigned char *out, const unsigned char *in, const harakactx *state); +#define haraka512 SPX_NAMESPACE(haraka512) +void haraka512(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx); /* Implementation of Haraka-256 */ -void PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_haraka256(unsigned char *out, const unsigned char *in, const harakactx *state); -void PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_haraka256x4(unsigned char *out, const unsigned char *in, const harakactx *state); - -/* Implementation of Haraka-256 using sk.seed constants */ -void PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_haraka256_sk(unsigned char *out, const unsigned char *in, const harakactx *state); -void PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_haraka256_skx4(unsigned char *out, const unsigned char *in, const harakactx *state); +#define haraka256 SPX_NAMESPACE(haraka256) +void haraka256(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/haraka_offsets.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/haraka_offsets.h new file mode 100644 index 0000000000..7c062272a0 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/haraka_offsets.h @@ -0,0 +1,21 @@ +#ifndef HARAKA_OFFSETS_H_ +#define HARAKA_OFFSETS_H_ + +/* + * Offsets of various fields in the address structure when we use Haraka as + * the Sphincs+ hash function + */ + +#define SPX_OFFSET_LAYER 3 /* The byte used to specify the Merkle tree layer */ +#define SPX_OFFSET_TREE 8 /* The start of the 8 byte field used to specify the tree */ +#define SPX_OFFSET_TYPE 19 /* The byte used to specify the hash type (reason) */ +#define SPX_OFFSET_KP_ADDR2 22 /* The high byte used to specify the key pair (which one-time signature) */ +#define SPX_OFFSET_KP_ADDR1 23 /* The low byte used to specify the key pair */ +#define SPX_OFFSET_CHAIN_ADDR 27 /* The byte used to specify the chain address (which Winternitz chain) */ +#define SPX_OFFSET_HASH_ADDR 31 /* The byte used to specify the hash address (where in the Winternitz chain) */ +#define SPX_OFFSET_TREE_HGT 27 /* The byte used to specify the height of this node in the FORS or Merkle tree */ +#define SPX_OFFSET_TREE_INDEX 28 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ + +#define SPX_HARAKA 1 + +#endif /* HARAKA_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/harakax4.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/harakax4.h new file mode 100644 index 0000000000..eadc69aa48 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/harakax4.h @@ -0,0 +1,36 @@ +#ifndef SPX_HARAKAX4_H +#define SPX_HARAKAX4_H + +#include "context.h" +#include "params.h" + +/* Haraka Sponge */ +#define haraka_Sx4 SPX_NAMESPACE(haraka_Sx4) +void haraka_Sx4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned long long outlen, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + unsigned long long inlen, + const spx_ctx *ctx); + +/* Applies the 512-bit Haraka permutation x4 to in. */ +#define haraka512_perm_x4 SPX_NAMESPACE(haraka512_perm_x4) +void haraka512_perm_x4(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx); + +/* Implementation of Haraka-512 x4*/ +#define haraka512x4 SPX_NAMESPACE(haraka512x4) +void haraka512x4(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx); + +/* Implementation of Haraka-256 x4 */ +#define haraka256x4 SPX_NAMESPACE(haraka256x4) +void haraka256x4(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/hash.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/hash.h index d4ea571718..f7c87d4c3c 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/hash.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/hash.h @@ -1,31 +1,28 @@ -#ifndef PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_HASH_H -#define PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_HASH_H - -#include "hash_state.h" +#ifndef SPX_HASH_H +#define SPX_HASH_H #include #include -void PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_initialize_hash_function( - hash_state *hash_state_seeded, - const unsigned char *pub_seed, const unsigned char *sk_seed); +#include "context.h" +#include "params.h" + +#define prf_addr SPX_NAMESPACE(prf_addr) +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]); -void PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_destroy_hash_function(hash_state *hash_state_seeded); +#define gen_message_random SPX_NAMESPACE(gen_message_random) +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); -void PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded); +#define hash_message SPX_NAMESPACE(hash_message) +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); -void PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); -void PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/hash_haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/hash_haraka.c index 309737fda7..750a67423b 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/hash_haraka.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/hash_haraka.c @@ -2,58 +2,44 @@ #include #include "address.h" -#include "haraka.h" -#include "hash.h" #include "params.h" #include "utils.h" -void PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_initialize_hash_function( - hash_state *hash_state_seeded, - const unsigned char *pub_seed, const unsigned char *sk_seed) { - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_tweak_constants(hash_state_seeded, pub_seed, sk_seed, PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N); -} - -/* The haraka implementation is stack based and won't be replaced in PQClean/OQS, - so we don't need to do anything */ -void PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_destroy_hash_function( - hash_state *hash_state_seeded) { // NOLINT(readability-non-const-parameter) - (void)hash_state_seeded; -} +#include "haraka.h" +#include "hash.h" /* - * Computes PRF(key, addr), given a secret key of PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N bytes and an address + * Computes PRF(key, addr), given a secret key of SPX_N bytes and an address */ -void PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded) { - unsigned char buf[PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_ADDR_BYTES]; - /* Since PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N may be smaller than 32, we need a temporary buffer. */ +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]) { + /* Since SPX_N may be smaller than 32, we need temporary buffers. */ unsigned char outbuf[32]; + unsigned char buf[64] = {0}; - (void)key; /* Suppress an 'unused parameter' warning. */ + memcpy(buf, addr, SPX_ADDR_BYTES); + memcpy(buf + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_addr_to_bytes(buf, addr); - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_haraka256_sk(outbuf, buf, hash_state_seeded); - memcpy(out, outbuf, PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N); + haraka512(outbuf, (const void *)buf, ctx); + memcpy(out, outbuf, SPX_N); } /** * Computes the message-dependent randomness R, using a secret seed and an * optional randomization value as well as the message. */ -void PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded) { +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { uint8_t s_inc[65]; - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_haraka_S_inc_init(s_inc); - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_haraka_S_inc_absorb(s_inc, sk_prf, PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_haraka_S_inc_absorb(s_inc, optrand, PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_haraka_S_inc_absorb(s_inc, m, mlen, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_haraka_S_inc_finalize(s_inc); - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_haraka_S_inc_squeeze(R, PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N, s_inc, hash_state_seeded); + haraka_S_inc_init(s_inc); + haraka_S_inc_absorb(s_inc, sk_prf, SPX_N, ctx); + haraka_S_inc_absorb(s_inc, optrand, SPX_N, ctx); + haraka_S_inc_absorb(s_inc, m, mlen, ctx); + haraka_S_inc_finalize(s_inc); + haraka_S_inc_squeeze(R, SPX_N, s_inc, ctx); } /** @@ -61,36 +47,35 @@ void PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_gen_message_random( * Outputs the message digest and the index of the leaf. The index is split in * the tree index and the leaf index, for convenient copying to an address. */ -void PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded) { -#define PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_TREE_BITS (PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_TREE_HEIGHT * (PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_D - 1)) -#define PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_TREE_BYTES ((PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_TREE_BITS + 7) / 8) -#define PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_LEAF_BITS PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_TREE_HEIGHT -#define PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_LEAF_BYTES ((PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_LEAF_BITS + 7) / 8) -#define PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_DGST_BYTES (PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_FORS_MSG_BYTES + PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_TREE_BYTES + PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_LEAF_BYTES) +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { +#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) +#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) +#define SPX_LEAF_BITS SPX_TREE_HEIGHT +#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) +#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) - unsigned char buf[PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_DGST_BYTES]; + unsigned char buf[SPX_DGST_BYTES]; unsigned char *bufp = buf; uint8_t s_inc[65]; - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_haraka_S_inc_init(s_inc); - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_haraka_S_inc_absorb(s_inc, R, PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_haraka_S_inc_absorb(s_inc, pk + PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N, PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_haraka_S_inc_absorb(s_inc, m, mlen, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_haraka_S_inc_finalize(s_inc); - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_haraka_S_inc_squeeze(buf, PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_DGST_BYTES, s_inc, hash_state_seeded); + haraka_S_inc_init(s_inc); + haraka_S_inc_absorb(s_inc, R, SPX_N, ctx); + haraka_S_inc_absorb(s_inc, pk + SPX_N, SPX_N, ctx); // Only absorb root part of pk + haraka_S_inc_absorb(s_inc, m, mlen, ctx); + haraka_S_inc_finalize(s_inc); + haraka_S_inc_squeeze(buf, SPX_DGST_BYTES, s_inc, ctx); + + memcpy(digest, bufp, SPX_FORS_MSG_BYTES); + bufp += SPX_FORS_MSG_BYTES; - memcpy(digest, bufp, PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_FORS_MSG_BYTES); - bufp += PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_FORS_MSG_BYTES; - *tree = PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_bytes_to_ull(bufp, PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_TREE_BYTES); - *tree &= (~(uint64_t)0) >> (64 - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_TREE_BITS); - bufp += PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_TREE_BYTES; + *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); + *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); + bufp += SPX_TREE_BYTES; - *leaf_idx = (uint32_t)PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_bytes_to_ull( - bufp, PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_LEAF_BYTES); - *leaf_idx &= (~(uint32_t)0) >> (32 - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_LEAF_BITS); + *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); + *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/hash_harakax4.c b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/hash_harakax4.c index 7f8cf5a9ab..cfa5162d79 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/hash_harakax4.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/hash_harakax4.c @@ -2,36 +2,34 @@ #include #include "address.h" -#include "haraka.h" -#include "hash_state.h" +#include "harakax4.h" #include "hashx4.h" #include "params.h" /* * 4-way parallel version of prf_addr; takes 4x as much input and output */ -void PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_prf_addrx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const unsigned char *key, - const uint32_t addrx4[4 * 8], - const hash_state *state_seeded) { - unsigned char bufx4[4 * PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_ADDR_BYTES]; - /* Since PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N may be smaller than 32, we need a temporary buffer. */ +#define prf_addrx4 SPX_NAMESPACE(prf_addrx4) +void prf_addrx4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const spx_ctx *ctx, + const uint32_t addrx4[4 * 8]) { + unsigned char bufx4[4 * 64] = {0}; + /* Since SPX_N may be smaller than 32, we need temporary buffers. */ unsigned char outbuf[4 * 32]; unsigned int i; - (void)key; /* Suppress an 'unused parameter' warning. */ - for (i = 0; i < 4; i++) { - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_addr_to_bytes(bufx4 + i * PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_ADDR_BYTES, addrx4 + i * 8); + memcpy(bufx4 + i * 64, addrx4 + i * 8, SPX_ADDR_BYTES); + memcpy(bufx4 + i * 64 + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); } - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_haraka256_skx4(outbuf, bufx4, state_seeded); + haraka512x4(outbuf, bufx4, ctx); - memcpy(out0, outbuf, PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N); - memcpy(out1, outbuf + 32, PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N); - memcpy(out2, outbuf + 64, PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N); - memcpy(out3, outbuf + 96, PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N); + memcpy(out0, outbuf, SPX_N); + memcpy(out1, outbuf + 32, SPX_N); + memcpy(out2, outbuf + 64, SPX_N); + memcpy(out3, outbuf + 96, SPX_N); } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/hash_state.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/hash_state.h deleted file mode 100644 index 55b40bdb06..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/hash_state.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_HASH_STATE_H -#define PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_HASH_STATE_H - -/** - * Defines the type of the hash function state. - * - * Don't be fooled into thinking this instance of SPHINCS+ isn't stateless! - * - * From Section 7.2.2 from the SPHINCS+ round-2 specification: - * - * Each of the instances of the tweakable hash function take PK.seed as its - * first input, which is constant for a given key pair – and, thus, across - * a single signature. This leads to a lot of redundant computation. To remedy - * this, we pad PK.seed to the length of a full 64-byte SHA-256 input block. - * Because of the Merkle-DamgÃ¥rd construction that underlies SHA-256, this - * allows for reuse of the intermediate SHA-256 state after the initial call to - * the compression function which improves performance. - * - * We pass this hash state around in functions, because otherwise we need to - * have a global variable. - */ - -#include "haraka.h" -#define hash_state harakactx - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/hashx4.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/hashx4.h index 14f2ffbaea..3751a0ebd0 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/hashx4.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/hashx4.h @@ -1,16 +1,17 @@ -#ifndef PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_HASHX4_H -#define PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_HASHX4_H +#ifndef SPX_HASHX4_H +#define SPX_HASHX4_H #include -#include "hash_state.h" +#include "context.h" +#include "params.h" -void PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_prf_addrx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const unsigned char *key, - const uint32_t addrx4[4 * 8], - const hash_state *state_seeded); +#define prf_addrx4 SPX_NAMESPACE(prf_addrx4) +void prf_addrx4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const spx_ctx *ctx, + const uint32_t addrx4[4 * 8]); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/merkle.c b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/merkle.c new file mode 100644 index 0000000000..f57811c1ac --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/merkle.c @@ -0,0 +1,64 @@ +#include +#include + +#include "merkle.h" + +#include "address.h" +#include "params.h" +#include "utils.h" +#include "utilsx4.h" +#include "wots.h" +#include "wotsx4.h" + +/* + * This generates a Merkle signature (WOTS signature followed by the Merkle + * authentication path). + */ +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf) { + unsigned char *auth_path = sig + SPX_WOTS_BYTES; + uint32_t tree_addrx4[4 * 8] = { 0 }; + int j; + struct leaf_info_x4 info = { 0 }; + unsigned steps[ SPX_WOTS_LEN ]; + + info.wots_sig = sig; + chain_lengths(steps, root); + info.wots_steps = steps; + + for (j = 0; j < 4; j++) { + set_type(&tree_addrx4[8 * j], SPX_ADDR_TYPE_HASHTREE); + set_type(&info.leaf_addr[8 * j], SPX_ADDR_TYPE_WOTS); + set_type(&info.pk_addr[8 * j], SPX_ADDR_TYPE_WOTSPK); + copy_subtree_addr(&tree_addrx4[8 * j], tree_addr); + copy_subtree_addr(&info.leaf_addr[8 * j], wots_addr); + copy_subtree_addr(&info.pk_addr[8 * j], wots_addr); + } + + info.wots_sign_leaf = idx_leaf; + + treehashx4(root, auth_path, ctx, + idx_leaf, 0, + SPX_TREE_HEIGHT, + wots_gen_leafx4, + tree_addrx4, &info); +} + +/* Compute root node of the top-most subtree. */ +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { + /* We do not need the auth path in key generation, but it simplifies the + code to have just one treehash routine that computes both root and path + in one function. */ + unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; + uint32_t top_tree_addr[8] = {0}; + uint32_t wots_addr[8] = {0}; + + set_layer_addr(top_tree_addr, SPX_D - 1); + set_layer_addr(wots_addr, SPX_D - 1); + + merkle_sign(auth_path, root, ctx, + wots_addr, top_tree_addr, + ~0U /* ~0 means "don't bother generating an auth path */ ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/merkle.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/merkle.h new file mode 100644 index 0000000000..769cf2e970 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/merkle.h @@ -0,0 +1,21 @@ +#ifndef MERKLE_H_ +#define MERKLE_H_ + +#include + +#include "context.h" +#include "params.h" + +/* Generate a Merkle signature (WOTS signature followed by the Merkle */ +/* authentication path) */ +#define merkle_sign SPX_NAMESPACE(merkle_sign) +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf); + +/* Compute the root node of the top-most subtree. */ +#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); + +#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/nistapi.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/nistapi.h new file mode 100644 index 0000000000..3cb71afad4 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/nistapi.h @@ -0,0 +1,87 @@ +#ifndef SPX_API_H +#define SPX_API_H + +#include +#include + +#include "params.h" + +#define CRYPTO_ALGNAME "SPHINCS+" + +#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES +#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES +#define CRYPTO_BYTES SPX_BYTES +#define CRYPTO_SEEDBYTES (3*SPX_N) + +/* + * Returns the length of a secret key, in bytes + */ +#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) +size_t crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) +size_t crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) +size_t crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) +size_t crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +#define crypto_sign SPX_NAMESPACE(crypto_sign) +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/params.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/params.h index 1b2ce946f3..8cc6b09402 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/params.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/params.h @@ -1,53 +1,56 @@ -#ifndef PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_PARAMS_H -#define PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_PARAMS_H +#ifndef SPX_PARAMS_H +#define SPX_PARAMS_H + +#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_##s /* Hash output length in bytes. */ -#define PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N 16 +#define SPX_N 16 /* Height of the hypertree. */ -#define PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_FULL_HEIGHT 66 +#define SPX_FULL_HEIGHT 66 /* Number of subtree layer. */ -#define PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_D 22 +#define SPX_D 22 /* FORS tree dimensions. */ -#define PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_FORS_HEIGHT 6 -#define PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_FORS_TREES 33 +#define SPX_FORS_HEIGHT 6 +#define SPX_FORS_TREES 33 /* Winternitz parameter, */ -#define PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_WOTS_W 16 +#define SPX_WOTS_W 16 /* The hash function is defined by linking a different hash.c file, as opposed to setting a #define constant. */ /* For clarity */ -#define PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_ADDR_BYTES 32 +#define SPX_ADDR_BYTES 32 /* WOTS parameters. */ -#define PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_WOTS_LOGW 4 +#define SPX_WOTS_LOGW 4 -#define PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_WOTS_LEN1 (8 * PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N / PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_WOTS_LOGW) +#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) -/* PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#define PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_WOTS_LEN2 3 +/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ +#define SPX_WOTS_LEN2 3 -#define PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_WOTS_LEN (PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_WOTS_LEN1 + PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_WOTS_LEN2) -#define PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_WOTS_BYTES (PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_WOTS_LEN * PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N) -#define PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_WOTS_PK_BYTES PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_WOTS_BYTES +#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) +#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) +#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES /* Subtree size. */ -#define PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_TREE_HEIGHT (PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_FULL_HEIGHT / PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_D) +#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) + +//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT +// #error SPX_D should always divide SPX_FULL_HEIGHT +//#endif /* FORS parameters. */ -#define PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_FORS_MSG_BYTES ((PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_FORS_TREES + 7) / 8) -#define PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_FORS_BYTES ((PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_FORS_HEIGHT + 1) * PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_FORS_TREES * PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N) -#define PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_FORS_PK_BYTES PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N +#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) +#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) +#define SPX_FORS_PK_BYTES SPX_N /* Resulting SPX sizes. */ -#define PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_BYTES (PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N + PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_FORS_BYTES + PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_D * PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_WOTS_BYTES +\ - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_FULL_HEIGHT * PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N) -#define PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_PK_BYTES (2 * PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N) -#define PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_SK_BYTES (2 * PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N + PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_PK_BYTES) - -/* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ -#define PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_OPTRAND_BYTES 32 +#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ + SPX_FULL_HEIGHT * SPX_N) +#define SPX_PK_BYTES (2 * SPX_N) +#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) + +#include "haraka_offsets.h" #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/sign.c b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/sign.c index 31a652025d..9d0c7d1b22 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/sign.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/sign.c @@ -1,76 +1,45 @@ -#include #include #include #include #include "address.h" -#include "api.h" +#include "context.h" #include "fors.h" #include "hash.h" -#include "hash_state.h" +#include "merkle.h" +#include "nistapi.h" #include "params.h" #include "randombytes.h" #include "thash.h" #include "utils.h" #include "wots.h" - -/** - * Computes the leaf at a given address. First generates the WOTS key pair, - * then computes leaf by hashing horizontally. - */ -static void wots_gen_leaf(unsigned char *leaf, const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx, const uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - unsigned char pk[PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_WOTS_BYTES]; - uint32_t wots_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_set_type( - wots_addr, PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_set_type( - wots_pk_addr, PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_ADDR_TYPE_WOTSPK); - - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_set_keypair_addr( - wots_addr, addr_idx); - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_wots_gen_pk( - pk, sk_seed, pub_seed, wots_addr, hash_state_seeded); - - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_copy_keypair_addr( - wots_pk_addr, wots_addr); - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_thash_WOTS_LEN( - leaf, pk, pub_seed, wots_pk_addr, hash_state_seeded); -} - /* * Returns the length of a secret key, in bytes */ -size_t PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_crypto_sign_secretkeybytes(void) { - return PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_CRYPTO_SECRETKEYBYTES; +size_t crypto_sign_secretkeybytes(void) { + return CRYPTO_SECRETKEYBYTES; } /* * Returns the length of a public key, in bytes */ -size_t PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_crypto_sign_publickeybytes(void) { - return PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_CRYPTO_PUBLICKEYBYTES; +size_t crypto_sign_publickeybytes(void) { + return CRYPTO_PUBLICKEYBYTES; } /* * Returns the length of a signature, in bytes */ -size_t PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_crypto_sign_bytes(void) { - return PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_CRYPTO_BYTES; +size_t crypto_sign_bytes(void) { + return CRYPTO_BYTES; } /* * Returns the length of the seed required to generate a key pair, in bytes */ -size_t PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_crypto_sign_seedbytes(void) { - return PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_CRYPTO_SEEDBYTES; +size_t crypto_sign_seedbytes(void) { + return CRYPTO_SEEDBYTES; } /* @@ -78,35 +47,29 @@ size_t PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_crypto_sign_seedbytes(void) { * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] * Format pk: [PUB_SEED || root] */ -int PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed) { - /* We do not need the auth path in key generation, but it simplifies the - code to have just one treehash routine that computes both root and path - in one function. */ - unsigned char auth_path[PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_TREE_HEIGHT * PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N]; - uint32_t top_tree_addr[8] = {0}; - hash_state hash_state_seeded; - - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_set_layer_addr( - top_tree_addr, PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_D - 1); - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_set_type( - top_tree_addr, PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_ADDR_TYPE_HASHTREE); +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed) { + spx_ctx ctx; /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ - memcpy(sk, seed, PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_CRYPTO_SEEDBYTES); + memcpy(sk, seed, CRYPTO_SEEDBYTES); + + memcpy(pk, sk + 2 * SPX_N, SPX_N); - memcpy(pk, sk + 2 * PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N, PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N); + memcpy(ctx.pub_seed, pk, SPX_N); + memcpy(ctx.sk_seed, sk, SPX_N); /* This hook allows the hash function instantiation to do whatever preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_initialize_hash_function(&hash_state_seeded, pk, sk); + initialize_hash_function(&ctx); /* Compute root node of the top-most subtree. */ - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_treehash_TREE_HEIGHT( - sk + 3 * PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N, auth_path, sk, sk + 2 * PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N, 0, 0, - wots_gen_leaf, top_tree_addr, &hash_state_seeded); + merkle_gen_root(sk + 3 * SPX_N, &ctx); - memcpy(pk + PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N, sk + 3 * PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N, PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N); + // cleanup + free_hash_function(&ctx); + + memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); return 0; } @@ -116,31 +79,10 @@ int PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_crypto_sign_seed_keypair( * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] * Format pk: [PUB_SEED || root] */ -int PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk) { - - // guarantee alignment of pk - union { - __m128 _x[PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_CRYPTO_PUBLICKEYBYTES / 16]; - uint8_t pk[PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_CRYPTO_PUBLICKEYBYTES]; - } aligned_pk; - - // guarantee alignment of sk - union { - __m128 _x[PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_CRYPTO_SECRETKEYBYTES / 16]; - uint8_t sk[PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_CRYPTO_SECRETKEYBYTES]; - } aligned_sk; - - union { - __m128 _x[PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_CRYPTO_SEEDBYTES / 16]; - uint8_t seed[PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_CRYPTO_SEEDBYTES]; - } aligned_seed; - randombytes(aligned_seed.seed, PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_CRYPTO_SEEDBYTES); - - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_crypto_sign_seed_keypair( - aligned_pk.pk, aligned_sk.sk, aligned_seed.seed); - memcpy(pk, aligned_pk.pk, PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_CRYPTO_PUBLICKEYBYTES); - memcpy(sk, aligned_sk.sk, PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_CRYPTO_SECRETKEYBYTES); +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { + uint8_t seed[CRYPTO_SEEDBYTES]; + randombytes(seed, CRYPTO_SEEDBYTES); + crypto_sign_seed_keypair(pk, sk, seed); return 0; } @@ -148,101 +90,68 @@ int PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_crypto_sign_keypair( /** * Returns an array containing a detached signature. */ -int PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - // guarantee alignment of sk - union { - __m128 *_x; - uint8_t sk[PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_CRYPTO_SECRETKEYBYTES]; - } aligned_sk; - memcpy(aligned_sk.sk, sk, PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_CRYPTO_SECRETKEYBYTES); - sk = aligned_sk.sk; - - // guarantee alignment of sig - union { - __m128 *_x; - uint8_t sig[PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_BYTES]; - } aligned_sig; - uint8_t *orig_sig = sig; - sig = (uint8_t *)aligned_sig.sig; - - const unsigned char *sk_seed = sk; - const unsigned char *sk_prf = sk + PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N; - const unsigned char *pk = sk + 2 * PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N; - const unsigned char *pub_seed = pk; - - unsigned char optrand[PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N]; - unsigned char mhash[PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_FORS_MSG_BYTES]; - unsigned char root[PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N]; +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk) { + spx_ctx ctx; + + const uint8_t *sk_prf = sk + SPX_N; + const uint8_t *pk = sk + 2 * SPX_N; + + uint8_t optrand[SPX_N]; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t root[SPX_N]; uint32_t i; uint64_t tree; uint32_t idx_leaf; uint32_t wots_addr[8] = {0}; uint32_t tree_addr[8] = {0}; - hash_state hash_state_seeded; + memcpy(ctx.sk_seed, sk, SPX_N); + memcpy(ctx.pub_seed, pk, SPX_N); /* This hook allows the hash function instantiation to do whatever preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_initialize_hash_function( - &hash_state_seeded, - pub_seed, sk_seed); + initialize_hash_function(&ctx); - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_set_type( - wots_addr, PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_set_type( - tree_addr, PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_ADDR_TYPE_HASHTREE); + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); /* Optionally, signing can be made non-deterministic using optrand. This can help counter side-channel attacks that would benefit from getting a large number of traces when the signer uses the same nodes. */ - randombytes(optrand, PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N); + randombytes(optrand, SPX_N); /* Compute the digest randomization value. */ - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_gen_message_random( - sig, sk_prf, optrand, m, mlen, &hash_state_seeded); + gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); /* Derive the message digest and leaf index from R, PK and M. */ - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N; + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_set_keypair_addr( - wots_addr, idx_leaf); + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); /* Sign the message hash using FORS. */ - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_fors_sign( - sig, root, mhash, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_FORS_BYTES; - - for (i = 0; i < PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_D; i++) { - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_set_tree_addr(tree_addr, tree); - - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_set_keypair_addr( - wots_addr, idx_leaf); - - /* Compute a WOTS signature. */ - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_wots_sign( - sig, root, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_WOTS_BYTES; - - /* Compute the authentication path for the used WOTS leaf. */ - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_treehash_TREE_HEIGHT( - root, sig, sk_seed, pub_seed, idx_leaf, 0, - wots_gen_leaf, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_TREE_HEIGHT * PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N; + fors_sign(sig, root, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); + sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_TREE_HEIGHT; + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; } - memcpy(orig_sig, aligned_sig.sig, PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_BYTES); - *siglen = PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_BYTES; + free_hash_function(&ctx); + + *siglen = SPX_BYTES; return 0; } @@ -250,23 +159,14 @@ int PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_crypto_sign_signature( /** * Verifies a detached signature and message under a given public key. */ -int PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk) { - // guarantee alignment of pk - union { - __m128 *_x; - uint8_t pk[PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_CRYPTO_PUBLICKEYBYTES]; - } aligned_pk; - memcpy(aligned_pk.pk, pk, PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_CRYPTO_PUBLICKEYBYTES); - pk = aligned_pk.pk; - - const unsigned char *pub_seed = pk; - const unsigned char *pub_root = pk + PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N; - unsigned char mhash[PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_FORS_MSG_BYTES]; - unsigned char wots_pk[PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_WOTS_BYTES]; - unsigned char root[PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N]; - unsigned char leaf[PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N]; +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk) { + spx_ctx ctx; + const uint8_t *pub_root = pk + SPX_N; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t wots_pk[SPX_WOTS_BYTES]; + uint8_t root[SPX_N]; + uint8_t leaf[SPX_N]; unsigned int i; uint64_t tree; uint32_t idx_leaf; @@ -274,77 +174,66 @@ int PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_crypto_sign_verify( uint32_t tree_addr[8] = {0}; uint32_t wots_pk_addr[8] = {0}; - hash_state hash_state_seeded; - - if (siglen != PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_BYTES) { + if (siglen != SPX_BYTES) { return -1; } + memcpy(ctx.pub_seed, pk, SPX_N); + /* This hook allows the hash function instantiation to do whatever preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_initialize_hash_function( - &hash_state_seeded, - pub_seed, NULL); + initialize_hash_function(&ctx); - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_set_type( - wots_addr, PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_set_type( - tree_addr, PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_ADDR_TYPE_HASHTREE); - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_set_type( - wots_pk_addr, PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_ADDR_TYPE_WOTSPK); + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); /* Derive the message digest and leaf index from R || PK || M. */ - /* The additional PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N is a result of the hash domain separator. */ - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N; + /* The additional SPX_N is a result of the hash domain separator. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; /* Layer correctly defaults to 0, so no need to set_layer_addr */ - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_set_keypair_addr( - wots_addr, idx_leaf); + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_fors_pk_from_sig( - root, sig, mhash, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_FORS_BYTES; + fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; /* For each subtree.. */ - for (i = 0; i < PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_D; i++) { - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_set_tree_addr(tree_addr, tree); + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_set_keypair_addr( - wots_addr, idx_leaf); + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_copy_keypair_addr( - wots_pk_addr, wots_addr); + copy_keypair_addr(wots_pk_addr, wots_addr); /* The WOTS public key is only correct if the signature was correct. */ /* Initially, root is the FORS pk, but on subsequent iterations it is the root of the subtree below the currently processed subtree. */ - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_wots_pk_from_sig( - wots_pk, sig, root, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_WOTS_BYTES; + wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); + sig += SPX_WOTS_BYTES; /* Compute the leaf node using the WOTS public key. */ - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_thash_WOTS_LEN( - leaf, wots_pk, pub_seed, wots_pk_addr, &hash_state_seeded); + thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); /* Compute the root node of this subtree. */ - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_compute_root( - root, leaf, idx_leaf, 0, sig, PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_TREE_HEIGHT, - pub_seed, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_TREE_HEIGHT * PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N; + compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, + &ctx, tree_addr); + sig += SPX_TREE_HEIGHT * SPX_N; /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_TREE_HEIGHT; + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; } + // cleanup + free_hash_function(&ctx); + /* Check if the root node equals the root node in the public key. */ - if (memcmp(root, pub_root, PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N) != 0) { + if (memcmp(root, pub_root, SPX_N) != 0) { return -1; } @@ -355,15 +244,14 @@ int PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_crypto_sign_verify( /** * Returns an array containing the signature followed by the message. */ -int PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk) { size_t siglen; - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_crypto_sign_signature( - sm, &siglen, m, mlen, sk); + crypto_sign_signature(sm, &siglen, m, mlen, sk); - memmove(sm + PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_BYTES, m, mlen); + memmove(sm + SPX_BYTES, m, mlen); *smlen = siglen + mlen; return 0; @@ -372,38 +260,27 @@ int PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_crypto_sign( /** * Verifies a given signature-message pair under a given public key. */ -int PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk) { - - // guarantee alignment of pk - union { - __m128 *_x; - uint8_t pk[PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_CRYPTO_PUBLICKEYBYTES]; - } aligned_pk; - memcpy(aligned_pk.pk, pk, PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_CRYPTO_PUBLICKEYBYTES); - pk = aligned_pk.pk; - - +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk) { /* The API caller does not necessarily know what size a signature should be - but SPHINCS+ signatures are always exactly PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_BYTES. */ - if (smlen < PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_BYTES) { + but SPHINCS+ signatures are always exactly SPX_BYTES. */ + if (smlen < SPX_BYTES) { memset(m, 0, smlen); *mlen = 0; return -1; } - *mlen = smlen - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_BYTES; + *mlen = smlen - SPX_BYTES; - if (PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_crypto_sign_verify( - sm, PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_BYTES, sm + PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_BYTES, *mlen, pk)) { + if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { memset(m, 0, smlen); *mlen = 0; return -1; } /* If verification was successful, move the message to the right place. */ - memmove(m, sm + PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_BYTES, *mlen); + memmove(m, sm + SPX_BYTES, *mlen); return 0; } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/thash.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/thash.h index d52a30548d..8687ccfb4d 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/thash.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/thash.h @@ -1,28 +1,13 @@ -#ifndef PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_THASH_H -#define PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_THASH_H +#ifndef SPX_THASH_H +#define SPX_THASH_H -#include "hash_state.h" +#include "context.h" +#include "params.h" #include -void PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); +#define thash SPX_NAMESPACE(thash) +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/thash_haraka_robust.c b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/thash_haraka_robust.c index f14713bc50..109502cbc2 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/thash_haraka_robust.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/thash_haraka_robust.c @@ -2,93 +2,44 @@ #include #include "address.h" -#include "hash_state.h" #include "params.h" #include "thash.h" +#include "utils.h" #include "haraka.h" /** - * Takes an array of inblocks concatenated arrays of PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N bytes. + * Takes an array of inblocks concatenated arrays of SPX_N bytes. */ -static void PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_thash( - unsigned char *out, unsigned char *buf, - const unsigned char *in, unsigned int inblocks, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char *bitmask = buf + PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_ADDR_BYTES; +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]) { + PQCLEAN_VLA(uint8_t, buf, SPX_ADDR_BYTES + inblocks * SPX_N); + PQCLEAN_VLA(uint8_t, bitmask, inblocks * SPX_N); unsigned char outbuf[32]; unsigned char buf_tmp[64]; unsigned int i; - (void)pub_seed; /* Suppress an 'unused parameter' warning. */ - if (inblocks == 1) { /* F function */ - /* Since PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N may be smaller than 32, we need a temporary buffer. */ + /* Since SPX_N may be smaller than 32, we need a temporary buffer. */ memset(buf_tmp, 0, 64); - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_addr_to_bytes(buf_tmp, addr); + memcpy(buf_tmp, addr, 32); - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_haraka256(outbuf, buf_tmp, hash_state_seeded); - for (i = 0; i < inblocks * PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N; i++) { - buf_tmp[PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_ADDR_BYTES + i] = in[i] ^ outbuf[i]; + haraka256(outbuf, buf_tmp, ctx); + for (i = 0; i < inblocks * SPX_N; i++) { + buf_tmp[SPX_ADDR_BYTES + i] = in[i] ^ outbuf[i]; } - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_haraka512(outbuf, buf_tmp, hash_state_seeded); - memcpy(out, outbuf, PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N); + haraka512(outbuf, buf_tmp, ctx); + memcpy(out, outbuf, SPX_N); } else { /* All other tweakable hashes*/ - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_addr_to_bytes(buf, addr); - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_haraka_S( - bitmask, inblocks * PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N, buf, PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_ADDR_BYTES, hash_state_seeded); + memcpy(buf, addr, 32); + haraka_S(bitmask, inblocks * SPX_N, buf, SPX_ADDR_BYTES, ctx); - for (i = 0; i < inblocks * PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N; i++) { - buf[PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_ADDR_BYTES + i] = in[i] ^ bitmask[i]; + for (i = 0; i < inblocks * SPX_N; i++) { + buf[SPX_ADDR_BYTES + i] = in[i] ^ bitmask[i]; } - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_haraka_S( - out, PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N, buf, PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N, hash_state_seeded); + haraka_S(out, SPX_N, buf, SPX_ADDR_BYTES + inblocks * SPX_N, ctx); } } - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_ADDR_BYTES + 1 * PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N]; - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_thash( - out, buf, in, 1, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_ADDR_BYTES + 2 * PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N]; - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_thash( - out, buf, in, 2, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_ADDR_BYTES + PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_WOTS_LEN * PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N]; - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_thash( - out, buf, in, PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_WOTS_LEN, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_ADDR_BYTES + PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_FORS_TREES * PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N]; - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_thash( - out, buf, in, PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_FORS_TREES, pub_seed, addr, hash_state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/thash_haraka_robustx4.c b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/thash_haraka_robustx4.c index 15f2c6d86e..100808a3a5 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/thash_haraka_robustx4.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/thash_haraka_robustx4.c @@ -2,91 +2,92 @@ #include #include "address.h" -#include "haraka.h" #include "params.h" #include "thashx4.h" +#include "harakax4.h" + +#include "utils.h" + /** * 4-way parallel version of thash; takes 4x as much input and output */ -#define thashx4_variant(name, inblocks) \ - void PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_thashx4_##name(unsigned char *out0, unsigned char *out1, unsigned char *out2, \ - unsigned char *out3, const unsigned char *in0, \ - const unsigned char *in1, const unsigned char *in2, \ - const unsigned char *in3, const unsigned char *pub_seed, \ - uint32_t addrx4[4 * 8], const harakactx *state) { \ - unsigned char buf0[PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_ADDR_BYTES + (inblocks)*PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N]; \ - unsigned char buf1[PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_ADDR_BYTES + (inblocks)*PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N]; \ - unsigned char buf2[PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_ADDR_BYTES + (inblocks)*PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N]; \ - unsigned char buf3[PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_ADDR_BYTES + (inblocks)*PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N]; \ - unsigned char bitmask0[(inblocks)*PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N]; \ - unsigned char bitmask1[(inblocks)*PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N]; \ - unsigned char bitmask2[(inblocks)*PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N]; \ - unsigned char bitmask3[(inblocks)*PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N]; \ - unsigned char outbuf[32 * 4]; \ - unsigned char buf_tmp[64 * 4]; \ - unsigned int i; \ - \ - (void)pub_seed; /* Suppress an 'unused parameter' warning. */ \ - \ - if ((inblocks) == 1) { \ - memset(buf_tmp, 0, 64 * 4); \ - \ - /* Generate masks first in buffer */ \ - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_addr_to_bytes(buf_tmp, addrx4 + 0 * 8); \ - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_addr_to_bytes(buf_tmp + 32, addrx4 + 1 * 8); \ - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_addr_to_bytes(buf_tmp + 64, addrx4 + 2 * 8); \ - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_addr_to_bytes(buf_tmp + 96, addrx4 + 3 * 8); \ - \ - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_haraka256x4(outbuf, buf_tmp, state); \ - \ - /* move addresses to make room for inputs; zero old values */ \ - memcpy(buf_tmp + 192, buf_tmp + 96, PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_ADDR_BYTES); \ - memcpy(buf_tmp + 128, buf_tmp + 64, PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_ADDR_BYTES); \ - memcpy(buf_tmp + 64, buf_tmp + 32, PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_ADDR_BYTES); \ - /* skip memcpy(buf_tmp, buf_tmp, PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_ADDR_BYTES); already in place */ \ - \ - /* skip memset(buf_tmp, 0, PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_ADDR_BYTES); remained untouched */ \ - memset(buf_tmp + 32, 0, PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_ADDR_BYTES); \ - /* skip memset(buf_tmp + 64, 0, PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_ADDR_BYTES); contains addr1 */ \ - memset(buf_tmp + 96, 0, PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_ADDR_BYTES); \ - \ - for (i = 0; i < PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N; i++) { \ - buf_tmp[PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_ADDR_BYTES + i] = in0[i] ^ outbuf[i]; \ - buf_tmp[PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_ADDR_BYTES + i + 64] = in1[i] ^ outbuf[i + 32]; \ - buf_tmp[PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_ADDR_BYTES + i + 128] = in2[i] ^ outbuf[i + 64]; \ - buf_tmp[PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_ADDR_BYTES + i + 192] = in3[i] ^ outbuf[i + 96]; \ - } \ - \ - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_haraka512x4(outbuf, buf_tmp, state); \ - \ - memcpy(out0, outbuf, PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N); \ - memcpy(out1, outbuf + 32, PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N); \ - memcpy(out2, outbuf + 64, PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N); \ - memcpy(out3, outbuf + 96, PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N); \ - } else { \ - /* All other tweakable hashes*/ \ - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_addr_to_bytes(buf0, addrx4 + 0 * 8); \ - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_addr_to_bytes(buf1, addrx4 + 1 * 8); \ - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_addr_to_bytes(buf2, addrx4 + 2 * 8); \ - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_addr_to_bytes(buf3, addrx4 + 3 * 8); \ - \ - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_haraka_Sx4(bitmask0, bitmask1, bitmask2, bitmask3, (inblocks)*PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N, buf0, buf1, \ - buf2, buf3, PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_ADDR_BYTES, state); \ - \ - for (i = 0; i < (inblocks)*PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N; i++) { \ - buf0[PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_ADDR_BYTES + i] = in0[i] ^ bitmask0[i]; \ - buf1[PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_ADDR_BYTES + i] = in1[i] ^ bitmask1[i]; \ - buf2[PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_ADDR_BYTES + i] = in2[i] ^ bitmask2[i]; \ - buf3[PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_ADDR_BYTES + i] = in3[i] ^ bitmask3[i]; \ - } \ - \ - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_haraka_Sx4(out0, out1, out2, out3, PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N, buf0, buf1, buf2, buf3, \ - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_ADDR_BYTES + (inblocks)*PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N, state); \ - } \ - } +#define thashx4 SPX_NAMESPACE(thashx4) +void thashx4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addrx4[4 * 8]) { + PQCLEAN_VLA(unsigned char, buf0, SPX_ADDR_BYTES + inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, buf1, SPX_ADDR_BYTES + inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, buf2, SPX_ADDR_BYTES + inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, buf3, SPX_ADDR_BYTES + inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, bitmask0, inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, bitmask1, inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, bitmask2, inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, bitmask3, inblocks * SPX_N); + unsigned char outbuf[32 * 4]; + unsigned char buf_tmp[64 * 4]; + unsigned int i; + + if (inblocks == 1) { + memset(buf_tmp, 0, 64 * 4); + + // Generate masks first in buffer + memcpy(buf_tmp, addrx4 + 0 * 8, 32); + memcpy(buf_tmp + 32, addrx4 + 1 * 8, 32); + memcpy(buf_tmp + 64, addrx4 + 2 * 8, 32); + memcpy(buf_tmp + 96, addrx4 + 3 * 8, 32); + + haraka256x4(outbuf, buf_tmp, ctx); + + /* move addresses to make room for inputs; zero old values */ + memcpy(buf_tmp + 192, buf_tmp + 96, SPX_ADDR_BYTES); + memcpy(buf_tmp + 128, buf_tmp + 64, SPX_ADDR_BYTES); + memcpy(buf_tmp + 64, buf_tmp + 32, SPX_ADDR_BYTES); + /* skip memcpy(buf_tmp, buf_tmp, SPX_ADDR_BYTES); already in place */ -thashx4_variant(1, 1) -thashx4_variant(2, 2) -thashx4_variant(WOTS_LEN, PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_WOTS_LEN) -thashx4_variant(FORS_TREES, PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_FORS_TREES) + /* skip memset(buf_tmp, 0, SPX_ADDR_BYTES); remained untouched */ + memset(buf_tmp + 32, 0, SPX_ADDR_BYTES); + /* skip memset(buf_tmp + 64, 0, SPX_ADDR_BYTES); contains addr1 */ + memset(buf_tmp + 96, 0, SPX_ADDR_BYTES); + + for (i = 0; i < SPX_N; i++) { + buf_tmp[SPX_ADDR_BYTES + i] = in0[i] ^ outbuf[i]; + buf_tmp[SPX_ADDR_BYTES + i + 64] = in1[i] ^ outbuf[i + 32]; + buf_tmp[SPX_ADDR_BYTES + i + 128] = in2[i] ^ outbuf[i + 64]; + buf_tmp[SPX_ADDR_BYTES + i + 192] = in3[i] ^ outbuf[i + 96]; + } + + haraka512x4(outbuf, buf_tmp, ctx); + + memcpy(out0, outbuf, SPX_N); + memcpy(out1, outbuf + 32, SPX_N); + memcpy(out2, outbuf + 64, SPX_N); + memcpy(out3, outbuf + 96, SPX_N); + } else { + /* All other tweakable hashes*/ + memcpy(buf0, addrx4 + 0 * 8, 32); + memcpy(buf1, addrx4 + 1 * 8, 32); + memcpy(buf2, addrx4 + 2 * 8, 32); + memcpy(buf3, addrx4 + 3 * 8, 32); + + haraka_Sx4(bitmask0, bitmask1, bitmask2, bitmask3, inblocks * SPX_N, + buf0, buf1, buf2, buf3, SPX_ADDR_BYTES, ctx); + + for (i = 0; i < inblocks * SPX_N; i++) { + buf0[SPX_ADDR_BYTES + i] = in0[i] ^ bitmask0[i]; + buf1[SPX_ADDR_BYTES + i] = in1[i] ^ bitmask1[i]; + buf2[SPX_ADDR_BYTES + i] = in2[i] ^ bitmask2[i]; + buf3[SPX_ADDR_BYTES + i] = in3[i] ^ bitmask3[i]; + } + + haraka_Sx4(out0, out1, out2, out3, SPX_N, + buf0, buf1, buf2, buf3, SPX_ADDR_BYTES + inblocks * SPX_N, + ctx); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/thashx4.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/thashx4.h index c3c535a5af..64798a3727 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/thashx4.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/thashx4.h @@ -1,25 +1,20 @@ -#ifndef PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_THASHX4_H -#define PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_THASHX4_H +#ifndef SPX_THASHX4_H +#define SPX_THASHX4_H #include -#include "hash_state.h" +#include "context.h" +#include "params.h" -#define thashx4_header(inblocks) \ - void PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_thashx4_##inblocks(unsigned char *out0, \ - unsigned char *out1, \ - unsigned char *out2, \ - unsigned char *out3, \ - const unsigned char *in0, \ - const unsigned char *in1, \ - const unsigned char *in2, \ - const unsigned char *in3, \ - const unsigned char *pub_seed, uint32_t addrx4[4*8], \ - const hash_state *state_seeded) - -thashx4_header(1); -thashx4_header(2); -thashx4_header(WOTS_LEN); -thashx4_header(FORS_TREES); +#define thashx4 SPX_NAMESPACE(thashx4) +void thashx4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addrx4[4 * 8]); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/utils.c b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/utils.c index ad1d423936..177b541fb9 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/utils.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/utils.c @@ -1,34 +1,41 @@ -#include #include +#include "utils.h" + #include "address.h" #include "hash.h" -#include "hash_state.h" #include "params.h" #include "thash.h" -#include "utils.h" /** * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. */ -void PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in) { +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in) { + int i; /* Iterate over out in decreasing order, for big-endianness. */ - for (size_t i = outlen; i > 0; i--) { - out[i - 1] = in & 0xff; + for (i = (signed int)outlen - 1; i >= 0; i--) { + out[i] = in & 0xff; in = in >> 8; } } +void u32_to_bytes(unsigned char *out, uint32_t in) { + out[0] = (unsigned char)(in >> 24); + out[1] = (unsigned char)(in >> 16); + out[2] = (unsigned char)(in >> 8); + out[3] = (unsigned char)in; +} + /** * Converts the inlen bytes in 'in' from big-endian byte order to an integer. */ -unsigned long long PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_bytes_to_ull( - const unsigned char *in, size_t inlen) { +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { unsigned long long retval = 0; + unsigned int i; - for (size_t i = 0; i < inlen; i++) { + for (i = 0; i < inlen; i++) { retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); } return retval; @@ -38,94 +45,80 @@ unsigned long long PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_bytes_to_ull( * Computes a root node given a leaf and an auth path. * Expects address to be complete other than the tree_height and tree_index. */ -void PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]) { uint32_t i; - unsigned char buffer[2 * PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N]; + unsigned char buffer[2 * SPX_N]; /* If leaf_idx is odd (last bit = 1), current path element is a right child and auth_path has to go left. Otherwise it is the other way around. */ if (leaf_idx & 1) { - memcpy(buffer + PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N, leaf, PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N); + memcpy(buffer + SPX_N, leaf, SPX_N); + memcpy(buffer, auth_path, SPX_N); } else { - memcpy(buffer, leaf, PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N); - memcpy(buffer + PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N, auth_path, PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N); + memcpy(buffer, leaf, SPX_N); + memcpy(buffer + SPX_N, auth_path, SPX_N); } - auth_path += PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N; + auth_path += SPX_N; for (i = 0; i < tree_height - 1; i++) { leaf_idx >>= 1; idx_offset >>= 1; /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_set_tree_height(addr, i + 1); - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_set_tree_index( - addr, leaf_idx + idx_offset); + set_tree_height(addr, i + 1); + set_tree_index(addr, leaf_idx + idx_offset); /* Pick the right or left neighbor, depending on parity of the node. */ if (leaf_idx & 1) { - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_thash_2( - buffer + PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N); + thash(buffer + SPX_N, buffer, 2, ctx, addr); + memcpy(buffer, auth_path, SPX_N); } else { - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_thash_2( - buffer, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer + PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N, auth_path, PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N); + thash(buffer, buffer, 2, ctx, addr); + memcpy(buffer + SPX_N, auth_path, SPX_N); } - auth_path += PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N; + auth_path += SPX_N; } /* The last iteration is exceptional; we do not copy an auth_path node. */ leaf_idx >>= 1; idx_offset >>= 1; - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_set_tree_height(addr, tree_height); - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_set_tree_index( - addr, leaf_idx + idx_offset); - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_thash_2( - root, buffer, pub_seed, addr, hash_state_seeded); + set_tree_height(addr, tree_height); + set_tree_index(addr, leaf_idx + idx_offset); + thash(root, buffer, 2, ctx, addr); } /** * For a given leaf index, computes the authentication path and the resulting * root node using Merkle's TreeHash algorithm. * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_ADDR_TYPE_FORSTREE). + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). * Applies the offset idx_offset to indices before building addresses, so that * it is possible to continue counting indices across trees. */ -static void PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_treehash( - unsigned char *root, unsigned char *auth_path, - unsigned char *stack, unsigned int *heights, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - +void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx * /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]) { + PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); + PQCLEAN_VLA(unsigned int, heights, tree_height + 1); unsigned int offset = 0; uint32_t idx; uint32_t tree_idx; for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { /* Add the next leaf node to the stack. */ - gen_leaf(stack + offset * PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N, - sk_seed, pub_seed, idx + idx_offset, tree_addr, - hash_state_seeded); + gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); offset++; heights[offset - 1] = 0; /* If this is a node we need for the auth path.. */ if ((leaf_idx ^ 0x1) == idx) { - memcpy(auth_path, stack + (offset - 1)*PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N, PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N); + memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); } /* While the top-most nodes are of equal height.. */ @@ -134,66 +127,22 @@ static void PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_treehash( tree_idx = (idx >> (heights[offset - 1] + 1)); /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_set_tree_height( - tree_addr, heights[offset - 1] + 1); - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_set_tree_index( - tree_addr, tree_idx + (idx_offset >> (heights[offset - 1] + 1))); + set_tree_height(tree_addr, heights[offset - 1] + 1); + set_tree_index(tree_addr, + tree_idx + (idx_offset >> (heights[offset - 1] + 1))); /* Hash the top-most nodes from the stack together. */ - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_thash_2( - stack + (offset - 2)*PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N, stack + (offset - 2)*PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N, - pub_seed, tree_addr, hash_state_seeded); + thash(stack + (offset - 2)*SPX_N, + stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); offset--; /* Note that the top-most node is now one layer higher. */ heights[offset - 1]++; /* If this is a node we need for the auth path.. */ if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_path + heights[offset - 1]*PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N, - stack + (offset - 1)*PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N, PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N); + memcpy(auth_path + heights[offset - 1]*SPX_N, + stack + (offset - 1)*SPX_N, SPX_N); } } } - memcpy(root, stack, PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N); -} - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_FORS_HEIGHT + 1)*PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N]; - unsigned int heights[PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_FORS_HEIGHT + 1]; - - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_FORS_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_TREE_HEIGHT + 1)*PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N]; - unsigned int heights[PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_TREE_HEIGHT + 1]; - - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_TREE_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); + memcpy(root, stack, SPX_N); } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/utils.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/utils.h index 4e496ff3a1..64f5d5a53a 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/utils.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/utils.h @@ -1,64 +1,58 @@ -#ifndef PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_UTILS_H -#define PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_UTILS_H +#ifndef SPX_UTILS_H +#define SPX_UTILS_H -#include "hash_state.h" -#include "params.h" -#include #include +#include "compat.h" +#include "context.h" +#include "params.h" + + +/* To support MSVC use alloca() instead of VLAs. See #20. */ + + /** * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. */ -void PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in); +#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in); +#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) +void u32_to_bytes(unsigned char *out, uint32_t in); /** * Converts the inlen bytes in 'in' from big-endian byte order to an integer. */ -unsigned long long PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_bytes_to_ull( - const unsigned char *in, size_t inlen); +#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); /** * Computes a root node given a leaf and an auth path. * Expects address to be complete other than the tree_height and tree_index. */ -void PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); +#define compute_root SPX_NAMESPACE(compute_root) +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]); /** * For a given leaf index, computes the authentication path and the resulting * root node using Merkle's TreeHash algorithm. * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_ADDR_TYPE_FORSTREE). + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). * Applies the offset idx_offset to indices before building addresses, so that * it is possible to continue counting indices across trees. */ -void PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); +#define treehash SPX_NAMESPACE(treehash) +void treehash(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx *ctx /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]); -void PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/utilsx4.c b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/utilsx4.c index c51f342ca4..1638677194 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/utilsx4.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/utilsx4.c @@ -1,98 +1,138 @@ +#include + +#include "utilsx4.h" + #include "address.h" #include "params.h" #include "thashx4.h" #include "utils.h" -#include "utilsx4.h" -#include - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. +/* + * Generate the entire Merkle tree, computing the authentication path for leaf_idx, + * and the resulting root node using Merkle's TreeHash algorithm. * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_ADDR_TYPE_FORSTREE). + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) + * + * This expects tree_addrx4 to be initialized to 4 parallel addr structures for + * the Merkle tree nodes + * * Applies the offset idx_offset to indices before building addresses, so that * it is possible to continue counting indices across trees. + * + * This works by using the standard Merkle tree building algorithm, except + * that each 'node' tracked is actually 4 consecutive nodes in the real tree. + * When we combine two logical nodes ABCD and WXYZ, we perform the H + * operation on adjacent real nodes, forming the parent logical node + * (AB)(CD)(WX)(YZ) + * + * When we get to the top two levels of the real tree (where there is only + * one logical node), we continue this operation two more times; the right + * most real node will by the actual root (and the other 3 nodes will be + * garbage). We follow the same thashx4 logic so that the 'extract + * authentication path components' part of the loop is still executed (and + * to simplify the code somewhat) + * + * This currently assumes tree_height >= 2; I suspect that doing an adjusting + * idx, addr_idx on the gen_leafx4 call if tree_height < 2 would fix it; since + * we don't actually use such short trees, I haven't bothered */ -#define treehashx4_variant(name, tree_height) \ - void PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_treehashx4_##name( \ - unsigned char *rootx4, unsigned char *auth_pathx4, const unsigned char *sk_seed, \ - const unsigned char *pub_seed, const uint32_t leaf_idx[4], uint32_t idx_offset[4], \ - void (*gen_leafx4)(unsigned char * /* leaf0 */, unsigned char * /* leaf1 */, \ - unsigned char * /* leaf2 */, unsigned char * /* leaf3 */, \ - const unsigned char * /* sk_seed */, \ - const unsigned char * /* pub_seed */, uint32_t /* addr_idx0 */, \ - uint32_t /* addr_idx1 */, uint32_t /* addr_idx2 */, \ - uint32_t /* addr_idx3 */, const uint32_t[8] /* tree_addr */, \ - const hash_state * /* state_seeded */), \ - uint32_t tree_addrx4[4 * 8], const hash_state *state_seeded) { \ - unsigned char stackx4[4 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N]; \ - unsigned int heights[(tree_height) + 1]; \ - unsigned int offset = 0; \ - uint32_t idx; \ - uint32_t tree_idx; \ - unsigned int j; \ - \ - for (idx = 0; idx < (uint32_t)(1 << (tree_height)); idx++) { \ - /* Add the next leaf node to the stack. */ \ - gen_leafx4(stackx4 + 0 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N + offset * PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N, \ - stackx4 + 1 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N + offset * PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N, \ - stackx4 + 2 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N + offset * PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N, \ - stackx4 + 3 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N + offset * PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N, sk_seed, \ - pub_seed, idx + idx_offset[0], idx + idx_offset[1], idx + idx_offset[2], \ - idx + idx_offset[3], tree_addrx4, state_seeded); \ - offset++; \ - heights[offset - 1] = 0; \ - \ - /* If this is a node we need for the auth path.. */ \ - for (j = 0; j < 4; j++) { \ - if ((leaf_idx[j] ^ 0x1) == idx) { \ - memcpy(auth_pathx4 + j * (tree_height)*PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N, \ - stackx4 + j * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N + (offset - 1) * PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N, \ - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N); \ - } \ - } \ - \ - /* While the top-most nodes are of equal height.. */ \ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { \ - /* Compute index of the new node, in the next layer. */ \ - tree_idx = (idx >> (heights[offset - 1] + 1)); \ - \ - /* Set the address of the node we're creating. */ \ - for (j = 0; j < 4; j++) { \ - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_set_tree_height(tree_addrx4 + j * 8, heights[offset - 1] + 1); \ - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_set_tree_index(tree_addrx4 + j * 8, \ - tree_idx + (idx_offset[j] >> (heights[offset - 1] + 1))); \ - } \ - /* Hash the top-most nodes from the stack together. */ \ - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_thashx4_2(stackx4 + 0 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N + (offset - 2) * PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N, \ - stackx4 + 1 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N + (offset - 2) * PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N, \ - stackx4 + 2 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N + (offset - 2) * PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N, \ - stackx4 + 3 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N + (offset - 2) * PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N, \ - stackx4 + 0 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N + (offset - 2) * PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N, \ - stackx4 + 1 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N + (offset - 2) * PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N, \ - stackx4 + 2 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N + (offset - 2) * PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N, \ - stackx4 + 3 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N + (offset - 2) * PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N, \ - pub_seed, tree_addrx4, state_seeded); \ - offset--; \ - /* Note that the top-most node is now one layer higher. */ \ - heights[offset - 1]++; \ - \ - /* If this is a node we need for the auth path.. */ \ - for (j = 0; j < 4; j++) { \ - if (((leaf_idx[j] >> heights[offset - 1]) ^ 0x1) == tree_idx) { \ - memcpy(auth_pathx4 + j * (tree_height)*PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N + \ - heights[offset - 1] * PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N, \ - stackx4 + j * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N + (offset - 1) * PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N, \ - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N); \ - } \ - } \ - } \ - } \ - \ - for (j = 0; j < 4; j++) { \ - memcpy(rootx4 + j * PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N, stackx4 + j * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N, PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N); \ - } \ - } +void treehashx4(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, + uint32_t tree_height, + void (*gen_leafx4)( + unsigned char * /* Where to write the leaves */, + const spx_ctx *, + uint32_t idx, void *info), + uint32_t tree_addrx4[4 * 8], + void *info) { + /* This is where we keep the intermediate nodes */ + PQCLEAN_VLA(unsigned char, stackx4, tree_height * 4 * SPX_N); + uint32_t left_adj = 0, prev_left_adj = 0; /* When we're doing the top 3 */ + /* levels, the left-most part of the tree isn't at the beginning */ + /* of current[]. These give the offset of the actual start */ + + uint32_t idx; + uint32_t max_idx = (1U << (tree_height - 2)) - 1; + for (idx = 0;; idx++) { + unsigned char current[4 * SPX_N]; /* Current logical node */ + gen_leafx4( current, ctx, 4 * idx + idx_offset, + info ); -treehashx4_variant(FORS_HEIGHT, PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_FORS_HEIGHT) + /* Now combine the freshly generated right node with previously */ + /* generated left ones */ + uint32_t internal_idx_offset = idx_offset; + uint32_t internal_idx = idx; + uint32_t internal_leaf = leaf_idx; + uint32_t h; /* The height we are in the Merkle tree */ + for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { + + /* Special processing if we're at the top of the tree */ + if (h >= tree_height - 2) { + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[3 * SPX_N], SPX_N ); + return; + } + /* The tree indexing logic is a bit off in this case */ + /* Adjust it so that the left-most node of the part of */ + /* the tree that we're processing has index 0 */ + prev_left_adj = left_adj; + left_adj = 4U - (1 << (tree_height - h - 1)); + } + + /* Check if we hit the top of the tree */ + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[3 * SPX_N], SPX_N ); + return; + } + + /* + * Check if one of the nodes we have is a part of the + * authentication path; if it is, write it out + */ + if ((((internal_idx << 2) ^ internal_leaf) & ~0x3U) == 0) { + memcpy( &auth_path[ h * SPX_N ], + ¤t[(((internal_leaf & 3) ^ 1) + prev_left_adj) * SPX_N], + SPX_N ); + } + + /* + * Check if we're at a left child; if so, stop going up the stack + * Exception: if we've reached the end of the tree, keep on going + * (so we combine the last 4 nodes into the one root node in two + * more iterations) + */ + if ((internal_idx & 1) == 0 && idx < max_idx) { + break; + } + + /* Ok, we're at a right node (or doing the top 3 levels) */ + /* Now combine the left and right logical nodes together */ + + /* Set the address of the node we're creating. */ + unsigned int j; + internal_idx_offset >>= 1; + for (j = 0; j < 4; j++) { + set_tree_height(tree_addrx4 + j * 8, h + 1); + set_tree_index(tree_addrx4 + j * 8, + (4 / 2) * (internal_idx & ~1U) + j - left_adj + internal_idx_offset ); + } + unsigned char *left = &stackx4[h * 4 * SPX_N]; + thashx4( ¤t[0 * SPX_N], + ¤t[1 * SPX_N], + ¤t[2 * SPX_N], + ¤t[3 * SPX_N], + &left [0 * SPX_N], + &left [2 * SPX_N], + ¤t[0 * SPX_N], + ¤t[2 * SPX_N], + 2, ctx, tree_addrx4); + } + + /* We've hit a left child; save the current for when we get the */ + /* corresponding right right */ + memcpy( &stackx4[h * 4 * SPX_N], current, 4 * SPX_N); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/utilsx4.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/utilsx4.h index 4b57bfe8cd..facb874b18 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/utilsx4.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/utilsx4.h @@ -1,38 +1,30 @@ -#ifndef PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_UTILSX4_H -#define PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_UTILSX4_H - -#include "hash_state.h" -#include "params.h" +#ifndef SPX_UTILSX4_H +#define SPX_UTILSX4_H #include +#include "context.h" +#include "params.h" + /** * For a given leaf index, computes the authentication path and the resulting * root node using Merkle's TreeHash algorithm. * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_ADDR_TYPE_FORSTREE). + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). * Applies the offset idx_offset to indices before building addresses, so that * it is possible to continue counting indices across trees. + * + * This implementation uses AVX to compute internal nodes 4 at a time (in + * parallel) */ -void PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_treehashx4_FORS_HEIGHT(unsigned char *rootx4, - unsigned char *auth_pathx4, - const unsigned char *sk_seed, - const unsigned char *pub_seed, - const uint32_t leaf_idx[4], - uint32_t idx_offset[4], - void (*gen_leafx4)(unsigned char * /* leaf0 */, - unsigned char * /* leaf1 */, - unsigned char * /* leaf2 */, - unsigned char * /* leaf3 */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx0 */, - uint32_t /* addr_idx1 */, - uint32_t /* addr_idx2 */, - uint32_t /* addr_idx3 */, - const uint32_t[8] /* tree_addr */, - const hash_state * /* state_seeded */), - uint32_t tree_addrx4[4 * 8], - const hash_state *state_seeded); +#define treehashx4 SPX_NAMESPACE(treehashx4) +void treehashx4(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leafx4)( + unsigned char * /* Where to write the leaves */, + const spx_ctx * /* ctx */, + uint32_t addr_idx, void *info), + uint32_t tree_addrx4[4 * 8], void *info); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/wots.c b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/wots.c index 6bbdaf6bb1..4d5041ce05 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/wots.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/wots.c @@ -1,106 +1,104 @@ #include #include +#include "wots.h" + #include "address.h" #include "hash.h" -#include "hash_state.h" #include "hashx4.h" #include "params.h" #include "thash.h" #include "thashx4.h" #include "utils.h" -#include "wots.h" +#include "utilsx4.h" +#include "wotsx4.h" // TODO clarify address expectations, and make them more uniform. // TODO i.e. do we expect types to be set already? // TODO and do we expect modifications or copies? /** - * Computes the starting value for a chain, i.e. the secret key. - * Expects the address to be complete up to the chain address. - */ -static void wots_gen_sk(unsigned char *sk, const unsigned char *sk_seed, - uint32_t wots_addr[8], const hash_state *state_seeded) { - /* Make sure that the hash address is actually zeroed. */ - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_set_hash_addr(wots_addr, 0); - - /* Generate sk element. */ - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_prf_addr(sk, sk_seed, wots_addr, state_seeded); -} - -/** - * 4-way parallel version of wots_gen_sk; expects 4x as much space in sk + * Computes up the chains */ -static void wots_gen_skx4(unsigned char *skx4, const unsigned char *sk_seed, - uint32_t wots_addrx4[4 * 8], const hash_state *state_seeded) { - unsigned int j; - - /* Make sure that the hash address is actually zeroed. */ +static void gen_chains( + unsigned char *out, + const unsigned char *in, + unsigned int start[SPX_WOTS_LEN], + const unsigned int steps[SPX_WOTS_LEN], + const spx_ctx *ctx, + uint32_t addr[8]) { + uint32_t i, j, k, idx, watching; + int done; + unsigned char empty[SPX_N]; + unsigned char *bufs[4]; + uint32_t addrs[8 * 4]; + + int l; + uint16_t counts[SPX_WOTS_W] = { 0 }; + uint16_t idxs[SPX_WOTS_LEN]; + uint16_t total, newTotal; + + /* set addrs = {addr, addr, addr, addr} */ for (j = 0; j < 4; j++) { - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_set_hash_addr(wots_addrx4 + j * 8, 0); + memcpy(addrs + j * 8, addr, sizeof(uint32_t) * 8); } - /* Generate sk element. */ - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_prf_addrx4(skx4 + 0 * PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N, - skx4 + 1 * PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N, - skx4 + 2 * PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N, - skx4 + 3 * PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N, - sk_seed, wots_addrx4, - state_seeded); -} - -/** - * Computes the chaining function. - * out and in have to be n-byte arrays. - * - * Interprets in as start-th value of the chain. - * addr has to contain the address of the chain. - */ -static void gen_chain(unsigned char *out, const unsigned char *in, - unsigned int start, unsigned int steps, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *state_seeded) { - uint32_t i; - /* Initialize out with the value at position 'start'. */ - memcpy(out, in, PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N); + memcpy(out, in, SPX_WOTS_LEN * SPX_N); - /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_WOTS_W; i++) { - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_set_hash_addr(addr, i); - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_thash_1(out, out, pub_seed, addr, state_seeded); + /* Sort the chains in reverse order by steps using counting sort. */ + for (i = 0; i < SPX_WOTS_LEN; i++) { + counts[steps[i]]++; + } + total = 0; + for (l = SPX_WOTS_W - 1; l >= 0; l--) { + newTotal = counts[l] + total; + counts[l] = total; + total = newTotal; + } + for (i = 0; i < SPX_WOTS_LEN; i++) { + idxs[counts[steps[i]]] = (uint16_t)i; + counts[steps[i]]++; } -} -/** - * 4-way parallel version of gen_chain; expects 4x as much space in out, and - * 4x as much space in inx4. Assumes start and step identical across chains. - */ -static void gen_chainx4(unsigned char *outx4, const unsigned char *inx4, - unsigned int start, unsigned int steps, - const unsigned char *pub_seed, uint32_t addrx4[4 * 8], - const hash_state *state_seeded) { - uint32_t i; - unsigned int j; + /* We got our work cut out for us: do it! */ + for (i = 0; i < SPX_WOTS_LEN; i += 4) { + for (j = 0; j < 4 && i + j < SPX_WOTS_LEN; j++) { + idx = idxs[i + j]; + set_chain_addr(addrs + j * 8, idx); + bufs[j] = out + SPX_N * idx; + } - /* Initialize outx4 with the value at position 'start'. */ - memcpy(outx4, inx4, 4 * PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N); + /* As the chains are sorted in reverse order, we know that the first + * chain is the longest and the last one is the shortest. We keep + * an eye on whether the last chain is done and then on the one before, + * et cetera. */ + watching = 3; + done = 0; + while (i + watching >= SPX_WOTS_LEN) { + bufs[watching] = &empty[0]; + watching--; + } - /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_WOTS_W; i++) { - for (j = 0; j < 4; j++) { - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_set_hash_addr(addrx4 + j * 8, i); + for (k = 0;; k++) { + while (k == steps[idxs[i + watching]]) { + bufs[watching] = &empty[0]; + if (watching == 0) { + done = 1; + break; + } + watching--; + } + if (done) { + break; + } + for (j = 0; j < watching + 1; j++) { + set_hash_addr(addrs + j * 8, k + start[idxs[i + j]]); + } + + thashx4(bufs[0], bufs[1], bufs[2], bufs[3], + bufs[0], bufs[1], bufs[2], bufs[3], 1, ctx, addrs); } - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_thashx4_1(outx4 + 0 * PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N, - outx4 + 1 * PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N, - outx4 + 2 * PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N, - outx4 + 3 * PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N, - outx4 + 0 * PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N, - outx4 + 1 * PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N, - outx4 + 2 * PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N, - outx4 + 3 * PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N, - pub_seed, addrx4, - state_seeded); } } @@ -109,7 +107,8 @@ static void gen_chainx4(unsigned char *outx4, const unsigned char *inx4, * Interprets an array of bytes as integers in base w. * This only works when log_w is a divisor of 8. */ -static void base_w(unsigned int *output, const int out_len, const unsigned char *input) { +static void base_w(unsigned int *output, const int out_len, + const unsigned char *input) { int in = 0; int out = 0; unsigned char total = 0; @@ -122,119 +121,149 @@ static void base_w(unsigned int *output, const int out_len, const unsigned char in++; bits += 8; } - bits -= PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_WOTS_LOGW; - output[out] = (unsigned int)(total >> bits) & (PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_WOTS_W - 1); + bits -= SPX_WOTS_LOGW; + output[out] = (total >> bits) & (SPX_WOTS_W - 1); out++; } } /* Computes the WOTS+ checksum over a message (in base_w). */ -static void wots_checksum(unsigned int *csum_base_w, const unsigned int *msg_base_w) { +static void wots_checksum(unsigned int *csum_base_w, + const unsigned int *msg_base_w) { unsigned int csum = 0; - unsigned char csum_bytes[(PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_WOTS_LEN2 * PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_WOTS_LOGW + 7) / 8]; + unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; unsigned int i; /* Compute checksum. */ - for (i = 0; i < PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_WOTS_LEN1; i++) { - csum += PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_WOTS_W - 1 - msg_base_w[i]; + for (i = 0; i < SPX_WOTS_LEN1; i++) { + csum += SPX_WOTS_W - 1 - msg_base_w[i]; } /* Convert checksum to base_w. */ /* Make sure expected empty zero bits are the least significant bits. */ - csum = csum << (8 - ((PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_WOTS_LEN2 * PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_WOTS_LOGW) % 8)); - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); - base_w(csum_base_w, PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_WOTS_LEN2, csum_bytes); + csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); + ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); + base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); } /* Takes a message and derives the matching chain lengths. */ -static void chain_lengths(unsigned int *lengths, const unsigned char *msg) { - base_w(lengths, PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_WOTS_LEN1, msg); - wots_checksum(lengths + PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_WOTS_LEN1, lengths); +void chain_lengths(unsigned int *lengths, const unsigned char *msg) { + base_w(lengths, SPX_WOTS_LEN1, msg); + wots_checksum(lengths + SPX_WOTS_LEN1, lengths); } /** - * WOTS key generation. Takes a 32 byte sk_seed, expands it to WOTS private key - * elements and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. * * Writes the computed public key to 'pk'. */ -void PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_wots_gen_pk(unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *state_seeded) { +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]) { + unsigned int steps[SPX_WOTS_LEN]; + unsigned int start[SPX_WOTS_LEN]; uint32_t i; - unsigned int j; - uint32_t addrx4[4 * 8]; - unsigned char pkbuf[4 * PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N]; + chain_lengths(start, msg); - for (j = 0; j < 4; j++) { - memcpy(addrx4 + j * 8, addr, sizeof(uint32_t) * 8); - } - - /* The last iteration typically does not have complete set of 4 chains, - but because we use pkbuf, this is not an issue -- we still do as many - in parallel as possible. */ - for (i = 0; i < ((PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_WOTS_LEN + 3) & ~0x3); i += 4) { - for (j = 0; j < 4; j++) { - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_set_chain_addr(addrx4 + j * 8, i + j); - } - wots_gen_skx4(pkbuf, sk_seed, addrx4, state_seeded); - gen_chainx4(pkbuf, pkbuf, 0, PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_WOTS_W - 1, pub_seed, addrx4, state_seeded); - for (j = 0; j < 4; j++) { - if (i + j < PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_WOTS_LEN) { - memcpy(pk + (i + j)*PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N, pkbuf + j * PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N, PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N); - } - } + for (i = 0; i < SPX_WOTS_LEN; i++) { + steps[i] = SPX_WOTS_W - 1 - start[i]; } - // Get rid of unused argument variable. - (void)state_seeded; + gen_chains(pk, sig, start, steps, ctx, addr); } -/** - * Takes a n-byte message and the 32-byte sk_see to compute a signature 'sig'. +/* + * This generates 4 sequential WOTS public keys + * It also generates the WOTS signature if leaf_info indicates + * that we're signing with one of these WOTS keys */ -void PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_wots_sign(unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); +void wots_gen_leafx4(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info) { + struct leaf_info_x4 *info = v_info; + uint32_t *leaf_addr = info->leaf_addr; + uint32_t *pk_addr = info->pk_addr; + unsigned int i, j, k; + unsigned char pk_buffer[ 4 * SPX_WOTS_BYTES ]; + unsigned wots_offset = SPX_WOTS_BYTES; + unsigned char *buffer; + uint32_t wots_k_mask; + unsigned wots_sign_index; + + if (((leaf_idx ^ info->wots_sign_leaf) & ~3U) == 0) { + /* We're traversing the leaf that's signing; generate the WOTS */ + /* signature */ + wots_k_mask = 0; + wots_sign_index = info->wots_sign_leaf & 3; /* Which of of the 4 */ + /* 4 slots do the signatures come from */ + } else { + /* Nope, we're just generating pk's; turn off the signature logic */ + wots_k_mask = (uint32_t)~0; + wots_sign_index = 0; + } - for (i = 0; i < PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_WOTS_LEN; i++) { - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_set_chain_addr(addr, i); - wots_gen_sk(sig + i * PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N, sk_seed, addr, state_seeded); - gen_chain(sig + i * PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N, sig + i * PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N, 0, lengths[i], pub_seed, addr, state_seeded); + for (j = 0; j < 4; j++) { + set_keypair_addr( leaf_addr + j * 8, leaf_idx + j ); + set_keypair_addr( pk_addr + j * 8, leaf_idx + j ); } - // avoid unused argument - (void)state_seeded; -} + for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { + uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k to */ + /* the step if we're generating a signature, ~0 if we're not */ -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_WOTS_LEN]; - uint32_t i; + /* Start with the secret seed */ + for (j = 0; j < 4; j++) { + set_chain_addr(leaf_addr + j * 8, i); + set_hash_addr(leaf_addr + j * 8, 0); + set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTSPRF); + } + prf_addrx4(buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + buffer + 2 * wots_offset, + buffer + 3 * wots_offset, + ctx, leaf_addr); - chain_lengths(lengths, msg); + for (j = 0; j < 4; j++) { + set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTS); + } + + /* Iterate down the WOTS chain */ + for (k = 0;; k++) { + /* Check if one of the values we have needs to be saved as a */ + /* part of the WOTS signature */ + if (k == wots_k) { + memcpy( info->wots_sig + i * SPX_N, + buffer + wots_sign_index * wots_offset, SPX_N ); + } - for (i = 0; i < PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_WOTS_LEN; i++) { - PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_set_chain_addr(addr, i); - gen_chain(pk + i * PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N, sig + i * PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_N, - lengths[i], PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_WOTS_W - 1 - lengths[i], pub_seed, addr, - state_seeded); + /* Check if we hit the top of the chain */ + if (k == SPX_WOTS_W - 1) { + break; + } + + /* Iterate one step on all 4 chains */ + for (j = 0; j < 4; j++) { + set_hash_addr(leaf_addr + j * 8, k); + } + thashx4(buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + buffer + 2 * wots_offset, + buffer + 3 * wots_offset, + buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + buffer + 2 * wots_offset, + buffer + 3 * wots_offset, 1, ctx, leaf_addr); + } } - // avoid unused argument - (void)state_seeded; + /* Do the final thash to generate the public keys */ + thashx4(dest + 0 * SPX_N, + dest + 1 * SPX_N, + dest + 2 * SPX_N, + dest + 3 * SPX_N, + pk_buffer + 0 * wots_offset, + pk_buffer + 1 * wots_offset, + pk_buffer + 2 * wots_offset, + pk_buffer + 3 * wots_offset, SPX_WOTS_LEN, ctx, pk_addr); } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/wots.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/wots.h index 1b5908d806..4e7692eeef 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/wots.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/wots.h @@ -1,41 +1,25 @@ -#ifndef PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_WOTS_H -#define PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_WOTS_H +#ifndef SPX_WOTS_H +#define SPX_WOTS_H -#include "hash_state.h" -#include "params.h" #include -/** - * WOTS key generation. Takes a 32 byte seed for the private key, expands it to - * a full WOTS private key and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_wots_gen_pk( - unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -/** - * Takes a n-byte message and the 32-byte seed for the private key to compute a - * signature that is placed at 'sig'. - */ -void PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_wots_sign( - unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *hash_state_seeded); +#include "context.h" +#include "params.h" /** * Takes a WOTS signature and an n-byte message, computes a WOTS public key. * * Writes the computed public key to 'pk'. */ -void PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_wots_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); +#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]); + +/* + * Compute the chain lengths needed for a given message hash + */ +#define chain_lengths SPX_NAMESPACE(chain_lengths) +void chain_lengths(unsigned int *lengths, const unsigned char *msg); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/wotsx4.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/wotsx4.h new file mode 100644 index 0000000000..cd634f1743 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/wotsx4.h @@ -0,0 +1,41 @@ +#ifndef WOTSX4_H_ +#define WOTSX4_H_ + +#include + +#include "params.h" + +/* + * This is here to provide an interface to the internal wots_gen_leafx4 + * routine. While this routine is not referenced in the package outside of + * wots.c, it is called from the stand-alone benchmark code to characterize + * the performance + */ +struct leaf_info_x4 { + unsigned char *wots_sig; + uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ + uint32_t *wots_steps; + uint32_t leaf_addr[4 * 8]; + uint32_t pk_addr[4 * 8]; +}; + +/* Macro to set the leaf_info to something 'benign', that is, it would */ +/* run with the same time as it does during the real signing process */ +/* Used only by the benchmark code */ +#define INITIALIZE_LEAF_INFO_X4(info, addr, step_buffer) { \ + (info).wots_sig = 0; \ + (info).wots_sign_leaf = ~0; \ + (info).wots_steps = step_buffer; \ + int i; \ + for (i=0; i<4; i++) { \ + memcpy( &(info).leaf_addr[8*i], addr, 32 ); \ + memcpy( &(info).pk_addr[8*i], addr, 32 ); \ + } \ + } + +#define wots_gen_leafx4 SPX_NAMESPACE(wots_gen_leafx4) +void wots_gen_leafx4(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info); + +#endif /* WOTSX4_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/address.c b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/address.c index 76591a0389..b956e9cb29 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/address.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/address.c @@ -1,78 +1,91 @@ #include +#include #include "address.h" #include "params.h" #include "utils.h" -void PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]) { - int i; - - for (i = 0; i < 8; i++) { - PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_ull_to_bytes( - bytes + i * 4, 4, addr[i]); - } -} - -void PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_set_layer_addr( - uint32_t addr[8], uint32_t layer) { - addr[0] = layer; +/* + * Specify which level of Merkle tree (the "layer") we're working on + */ +void set_layer_addr(uint32_t addr[8], uint32_t layer) { + ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; } -void PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_set_tree_addr( - uint32_t addr[8], uint64_t tree) { - addr[1] = 0; - addr[2] = (uint32_t) (tree >> 32); - addr[3] = (uint32_t) tree; +/* + * Specify which Merkle tree within the level (the "tree address") we're working on + */ +void set_tree_addr(uint32_t addr[8], uint64_t tree) { + ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); } -void PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_set_type( - uint32_t addr[8], uint32_t type) { - addr[4] = type; +/* + * Specify the reason we'll use this address structure for, that is, what + * hash will we compute with it. This is used so that unrelated types of + * hashes don't accidentally get the same address structure. The type will be + * one of the SPX_ADDR_TYPE constants + */ +void set_type(uint32_t addr[8], uint32_t type) { + ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; } -void PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; +/* + * Copy the layer and tree fields of the address structure. This is used + * when we're doing multiple types of hashes within the same Merkle tree + */ +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); } /* These functions are used for OTS addresses. */ -void PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_set_keypair_addr( - uint32_t addr[8], uint32_t keypair) { - addr[5] = keypair; +/* + * Specify which Merkle leaf we're working on; that is, which OTS keypair + * we're talking about. + */ +void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { + ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; } -void PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; - out[5] = in[5]; +/* + * Copy the layer, tree and keypair fields of the address structure. This is + * used when we're doing multiple things within the same OTS keypair + */ +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); + ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; } -void PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_set_chain_addr( - uint32_t addr[8], uint32_t chain) { - addr[6] = chain; +/* + * Specify which Merkle chain within the OTS we're working with + * (the chain address) + */ +void set_chain_addr(uint32_t addr[8], uint32_t chain) { + ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; } -void PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_set_hash_addr( - uint32_t addr[8], uint32_t hash) { - addr[7] = hash; +/* + * Specify where in the Merkle chain we are +* (the hash address) + */ +void set_hash_addr(uint32_t addr[8], uint32_t hash) { + ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; } /* These functions are used for all hash tree addresses (including FORS). */ -void PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_set_tree_height( - uint32_t addr[8], uint32_t tree_height) { - addr[6] = tree_height; +/* + * Specify the height of the node in the Merkle/FORS tree we are in + * (the tree height) + */ +void set_tree_height(uint32_t addr[8], uint32_t tree_height) { + ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; } -void PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_set_tree_index( - uint32_t addr[8], uint32_t tree_index) { - addr[7] = tree_index; +/* + * Specify the distance from the left edge of the node in the Merkle/FORS tree + * (the tree index) + */ +void set_tree_index(uint32_t addr[8], uint32_t tree_index) { + u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/address.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/address.h index 5de3f3cec8..24a84eb40c 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/address.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/address.h @@ -1,50 +1,52 @@ -#ifndef PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_ADDRESS_H -#define PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_ADDRESS_H +#ifndef SPX_ADDRESS_H +#define SPX_ADDRESS_H #include -#define PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_ADDR_TYPE_WOTS 0 -#define PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_ADDR_TYPE_WOTSPK 1 -#define PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_ADDR_TYPE_HASHTREE 2 -#define PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_ADDR_TYPE_FORSTREE 3 -#define PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_ADDR_TYPE_FORSPK 4 +#include "params.h" -void PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]); +/* The hash types that are passed to set_type */ +#define SPX_ADDR_TYPE_WOTS 0 +#define SPX_ADDR_TYPE_WOTSPK 1 +#define SPX_ADDR_TYPE_HASHTREE 2 +#define SPX_ADDR_TYPE_FORSTREE 3 +#define SPX_ADDR_TYPE_FORSPK 4 +#define SPX_ADDR_TYPE_WOTSPRF 5 +#define SPX_ADDR_TYPE_FORSPRF 6 -void PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_set_layer_addr( - uint32_t addr[8], uint32_t layer); +#define set_layer_addr SPX_NAMESPACE(set_layer_addr) +void set_layer_addr(uint32_t addr[8], uint32_t layer); -void PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_set_tree_addr( - uint32_t addr[8], uint64_t tree); +#define set_tree_addr SPX_NAMESPACE(set_tree_addr) +void set_tree_addr(uint32_t addr[8], uint64_t tree); -void PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_set_type( - uint32_t addr[8], uint32_t type); +#define set_type SPX_NAMESPACE(set_type) +void set_type(uint32_t addr[8], uint32_t type); /* Copies the layer and tree part of one address into the other */ -void PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]); +#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); /* These functions are used for WOTS and FORS addresses. */ -void PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_set_keypair_addr( - uint32_t addr[8], uint32_t keypair); +#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) +void set_keypair_addr(uint32_t addr[8], uint32_t keypair); -void PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_set_chain_addr( - uint32_t addr[8], uint32_t chain); +#define set_chain_addr SPX_NAMESPACE(set_chain_addr) +void set_chain_addr(uint32_t addr[8], uint32_t chain); -void PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_set_hash_addr( - uint32_t addr[8], uint32_t hash); +#define set_hash_addr SPX_NAMESPACE(set_hash_addr) +void set_hash_addr(uint32_t addr[8], uint32_t hash); -void PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]); +#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); /* These functions are used for all hash tree addresses (including FORS). */ -void PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_set_tree_height( - uint32_t addr[8], uint32_t tree_height); +#define set_tree_height SPX_NAMESPACE(set_tree_height) +void set_tree_height(uint32_t addr[8], uint32_t tree_height); -void PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_set_tree_index( - uint32_t addr[8], uint32_t tree_index); +#define set_tree_index SPX_NAMESPACE(set_tree_index) +void set_tree_index(uint32_t addr[8], uint32_t tree_index); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/api.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/api.h index 581ad5ad0b..b84a77dc3b 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/api.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/api.h @@ -4,15 +4,13 @@ #include #include - - -#define PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_CRYPTO_ALGNAME "SPHINCS+" +#define PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_CRYPTO_ALGNAME "SPHINCS+-haraka-128f-robust" #define PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_CRYPTO_SECRETKEYBYTES 64 #define PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_CRYPTO_PUBLICKEYBYTES 32 -#define PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_CRYPTO_BYTES 17088 -#define PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_CRYPTO_SEEDBYTES 48 +#define PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_CRYPTO_BYTES 17088 +#define PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_CRYPTO_SEEDBYTES 48 /* * Returns the length of a secret key, in bytes @@ -39,43 +37,41 @@ size_t PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_crypto_sign_seedbytes(void); * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] * Format pk: [root || PUB_SEED] */ -int PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed); +int PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); /* * Generates a SPHINCS+ key pair. * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] * Format pk: [root || PUB_SEED] */ -int PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk); +int PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); /** * Returns an array containing a detached signature. */ -int PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk); +int PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); /** * Verifies a detached signature and message under a given public key. */ -int PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk); +int PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, + const uint8_t *pk); /** * Returns an array containing the signature followed by the message. */ -int PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk); +int PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); /** * Verifies a given signature-message pair under a given public key. */ -int PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk); - +int PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/context.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/context.h new file mode 100644 index 0000000000..600dfb73c7 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/context.h @@ -0,0 +1,24 @@ +#ifndef SPX_CONTEXT_H +#define SPX_CONTEXT_H + +#include +#include + +#include "params.h" + +typedef struct { + uint8_t pub_seed[SPX_N]; + uint8_t sk_seed[SPX_N]; + + + uint64_t tweaked512_rc64[10][8]; + uint32_t tweaked256_rc32[10][8]; +} spx_ctx; + +#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) +void initialize_hash_function(spx_ctx *ctx); + +#define free_hash_function SPX_NAMESPACE(free_hash_function) +void free_hash_function(spx_ctx *ctx); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/context_haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/context_haraka.c new file mode 100644 index 0000000000..f1cd7e3664 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/context_haraka.c @@ -0,0 +1,11 @@ +#include "context.h" +#include "haraka.h" + +void initialize_hash_function(spx_ctx *ctx) { + tweak_constants(ctx); +} + +// we don't support heap-based haraka right now +void free_hash_function(spx_ctx *ctx) { + (void)ctx; // suppress unused variable warnings +} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/fors.c b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/fors.c index e3fdf6a6c0..96ca72e986 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/fors.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/fors.c @@ -2,58 +2,58 @@ #include #include -#include "address.h" #include "fors.h" + +#include "address.h" #include "hash.h" -#include "hash_state.h" #include "thash.h" #include "utils.h" +#include "utilsx1.h" -static void fors_gen_sk(unsigned char *sk, const unsigned char *sk_seed, - uint32_t fors_leaf_addr[8], const hash_state *hash_state_seeded) { - PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_prf_addr( - sk, sk_seed, fors_leaf_addr, hash_state_seeded); +static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + prf_addr(sk, ctx, fors_leaf_addr); } static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, - const unsigned char *pub_seed, - uint32_t fors_leaf_addr[8], - const hash_state *hash_state_seeded) { - PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_thash_1( - leaf, sk, pub_seed, fors_leaf_addr, hash_state_seeded); + const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + thash(leaf, sk, 1, ctx, fors_leaf_addr); } -static void fors_gen_leaf(unsigned char *leaf, const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx, const uint32_t fors_tree_addr[8], - const hash_state *hash_state_seeded) { - uint32_t fors_leaf_addr[8] = {0}; - - /* Only copy the parts that must be kept in fors_leaf_addr. */ - PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_copy_keypair_addr( - fors_leaf_addr, fors_tree_addr); - PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_set_type( - fors_leaf_addr, PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_set_tree_index( - fors_leaf_addr, addr_idx); - - fors_gen_sk(leaf, sk_seed, fors_leaf_addr, hash_state_seeded); - fors_sk_to_leaf(leaf, leaf, pub_seed, fors_leaf_addr, hash_state_seeded); +struct fors_gen_leaf_info { + uint32_t leaf_addrx[8]; +}; + +static void fors_gen_leafx1(unsigned char *leaf, + const spx_ctx *ctx, + uint32_t addr_idx, void *info) { + struct fors_gen_leaf_info *fors_info = info; + uint32_t *fors_leaf_addr = fors_info->leaf_addrx; + + /* Only set the parts that the caller doesn't set */ + set_tree_index(fors_leaf_addr, addr_idx); + set_type(fors_leaf_addr, SPX_ADDR_TYPE_FORSPRF); + fors_gen_sk(leaf, ctx, fors_leaf_addr); + + set_type(fors_leaf_addr, SPX_ADDR_TYPE_FORSTREE); + fors_sk_to_leaf(leaf, leaf, + ctx, fors_leaf_addr); } /** - * Interprets m as PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_FORS_HEIGHT-bit unsigned integers. - * Assumes m contains at least PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_FORS_TREES bits. - * Assumes indices has space for PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_FORS_TREES integers. + * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + * Assumes indices has space for SPX_FORS_TREES integers. */ static void message_to_indices(uint32_t *indices, const unsigned char *m) { unsigned int i, j; unsigned int offset = 0; - for (i = 0; i < PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_FORS_TREES; i++) { + for (i = 0; i < SPX_FORS_TREES; i++) { indices[i] = 0; - for (j = 0; j < PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_FORS_HEIGHT; j++) { - indices[i] ^= (((uint32_t)m[offset >> 3] >> (offset & 0x7)) & 0x1) << j; + for (j = 0; j < SPX_FORS_HEIGHT; j++) { + indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); offset++; } } @@ -61,55 +61,51 @@ static void message_to_indices(uint32_t *indices, const unsigned char *m) { /** * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_FORS_TREES bits. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. */ -void PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_fors_sign( - unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *hash_state_seeded) { - uint32_t indices[PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_FORS_TREES]; - unsigned char roots[PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_FORS_TREES * PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_N]; +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; uint32_t fors_tree_addr[8] = {0}; + struct fors_gen_leaf_info fors_info = {0}; + uint32_t *fors_leaf_addr = fors_info.leaf_addrx; uint32_t fors_pk_addr[8] = {0}; uint32_t idx_offset; unsigned int i; - PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_copy_keypair_addr( - fors_tree_addr, fors_addr); - PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_copy_keypair_addr( - fors_pk_addr, fors_addr); + copy_keypair_addr(fors_tree_addr, fors_addr); + copy_keypair_addr(fors_leaf_addr, fors_addr); - PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_set_type( - fors_tree_addr, PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_set_type( - fors_pk_addr, PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_ADDR_TYPE_FORSPK); + copy_keypair_addr(fors_pk_addr, fors_addr); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); message_to_indices(indices, m); - for (i = 0; i < PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_FORS_TREES; i++) { - idx_offset = i * (1 << PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_FORS_HEIGHT); + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); - PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_set_tree_height( - fors_tree_addr, 0); - PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_set_tree_index( - fors_tree_addr, indices[i] + idx_offset); + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); /* Include the secret key part that produces the selected leaf node. */ - fors_gen_sk(sig, sk_seed, fors_tree_addr, hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_N; + fors_gen_sk(sig, ctx, fors_tree_addr); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + sig += SPX_N; /* Compute the authentication path for this leaf node. */ - PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_treehash_FORS_HEIGHT( - roots + i * PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_N, sig, sk_seed, pub_seed, - indices[i], idx_offset, fors_gen_leaf, fors_tree_addr, - hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_N * PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_FORS_HEIGHT; + treehashx1(roots + i * SPX_N, sig, ctx, + indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx1, + fors_tree_addr, &fors_info); + + sig += SPX_N * SPX_FORS_HEIGHT; } /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_thash_FORS_TREES( - pk, roots, pub_seed, fors_pk_addr, hash_state_seeded); + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); } /** @@ -117,45 +113,44 @@ void PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_fors_sign( * This can be used for verification by comparing to a known public key, or to * subsequently verify a signature on the derived public key. The latter is the * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_FORS_TREES bits. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. */ -void PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_fors_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, const uint32_t fors_addr[8], - const hash_state *hash_state_seeded) { - uint32_t indices[PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_FORS_TREES]; - unsigned char roots[PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_FORS_TREES * PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_N]; - unsigned char leaf[PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_N]; +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + unsigned char leaf[SPX_N]; uint32_t fors_tree_addr[8] = {0}; uint32_t fors_pk_addr[8] = {0}; uint32_t idx_offset; unsigned int i; - PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_copy_keypair_addr(fors_tree_addr, fors_addr); - PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_copy_keypair_addr(fors_pk_addr, fors_addr); + copy_keypair_addr(fors_tree_addr, fors_addr); + copy_keypair_addr(fors_pk_addr, fors_addr); - PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_set_type(fors_tree_addr, PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_set_type(fors_pk_addr, PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_ADDR_TYPE_FORSPK); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); message_to_indices(indices, m); - for (i = 0; i < PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_FORS_TREES; i++) { - idx_offset = i * (1 << PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_FORS_HEIGHT); + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); - PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_set_tree_height(fors_tree_addr, 0); - PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_set_tree_index(fors_tree_addr, indices[i] + idx_offset); + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); /* Derive the leaf from the included secret key part. */ - fors_sk_to_leaf(leaf, sig, pub_seed, fors_tree_addr, hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_N; + fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); + sig += SPX_N; /* Derive the corresponding root node of this tree. */ - PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_compute_root(roots + i * PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_N, leaf, indices[i], idx_offset, sig, - PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_FORS_HEIGHT, pub_seed, fors_tree_addr, hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_N * PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_FORS_HEIGHT; + compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, + sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); + sig += SPX_N * SPX_FORS_HEIGHT; } /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_thash_FORS_TREES(pk, roots, pub_seed, fors_pk_addr, hash_state_seeded); + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/fors.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/fors.h index 841087c172..509140a178 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/fors.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/fors.h @@ -1,32 +1,32 @@ -#ifndef PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_FORS_H -#define PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_FORS_H +#ifndef SPX_FORS_H +#define SPX_FORS_H #include -#include "hash_state.h" +#include "context.h" #include "params.h" /** * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_FORS_TREES bits. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. */ -void PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_fors_sign( - unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *hash_state_seeded); +#define fors_sign SPX_NAMESPACE(fors_sign) +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); /** * Derives the FORS public key from a signature. * This can be used for verification by comparing to a known public key, or to * subsequently verify a signature on the derived public key. The latter is the * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_FORS_TREES bits. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. */ -void PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_fors_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, const uint32_t fors_addr[8], - const hash_state *hash_state_seeded); +#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/haraka.c index 85808f71f6..a4944913b5 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/haraka.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/haraka.c @@ -6,12 +6,13 @@ * by Thomas Pornin */ -#include #include +#include #include #include #include "haraka.h" +#include "utils.h" #define HARAKAS_RATE 32 @@ -656,76 +657,62 @@ static void interleave_constant32(uint32_t *out, const unsigned char *in) { br_aes_ct_ortho(out); } -void PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_tweak_constants( - harakactx *state, - const unsigned char *pk_seed, const unsigned char *sk_seed, - unsigned long long seed_length) { +void tweak_constants(spx_ctx *ctx) { unsigned char buf[40 * 16]; int i; /* Use the standard constants to generate tweaked ones. */ - memcpy((uint8_t *)state->tweaked512_rc64, (uint8_t *)haraka512_rc64, 40 * 16); - - /* Constants for sk.seed */ - if (sk_seed != NULL) { - PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_haraka_S( - buf, 40 * 16, sk_seed, seed_length, state); - - /* Interleave constants */ - for (i = 0; i < 10; i++) { - interleave_constant32(state->tweaked256_rc32_sseed[i], buf + 32 * i); - } - } + memcpy((uint8_t *)ctx->tweaked512_rc64, (uint8_t *)haraka512_rc64, 40 * 16); /* Constants for pk.seed */ - PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_haraka_S( - buf, 40 * 16, pk_seed, seed_length, state); + haraka_S(buf, 40 * 16, ctx->pub_seed, SPX_N, ctx); for (i = 0; i < 10; i++) { - interleave_constant32(state->tweaked256_rc32[i], buf + 32 * i); - interleave_constant(state->tweaked512_rc64[i], buf + 64 * i); + interleave_constant32(ctx->tweaked256_rc32[i], buf + 32 * i); + interleave_constant(ctx->tweaked512_rc64[i], buf + 64 * i); } } -static void haraka_S_absorb(unsigned char *s, +static void haraka_S_absorb(unsigned char *s, unsigned int r, const unsigned char *m, unsigned long long mlen, - unsigned char p, const harakactx *state) { + unsigned char p, const spx_ctx *ctx) { unsigned long long i; - unsigned char t[HARAKAS_RATE]; + PQCLEAN_VLA(uint8_t, t, r); - while (mlen >= HARAKAS_RATE) { + while (mlen >= r) { /* XOR block to state */ - for (i = 0; i < HARAKAS_RATE; ++i) { + for (i = 0; i < r; ++i) { s[i] ^= m[i]; } - PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_haraka512_perm(s, s, state); - mlen -= HARAKAS_RATE; - m += HARAKAS_RATE; + haraka512_perm(s, s, ctx); + mlen -= r; + m += r; } - for (i = 0; i < HARAKAS_RATE; ++i) { + for (i = 0; i < r; ++i) { t[i] = 0; } for (i = 0; i < mlen; ++i) { t[i] = m[i]; } t[i] = p; - t[HARAKAS_RATE - 1] |= 128; - for (i = 0; i < HARAKAS_RATE; ++i) { + t[r - 1] |= 128; + for (i = 0; i < r; ++i) { s[i] ^= t[i]; } } static void haraka_S_squeezeblocks(unsigned char *h, unsigned long long nblocks, - unsigned char *s, const harakactx *state) { + unsigned char *s, unsigned int r, + const spx_ctx *ctx) { while (nblocks > 0) { - PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_haraka512_perm(s, s, state); + haraka512_perm(s, s, ctx); memcpy(h, s, HARAKAS_RATE); - h += HARAKAS_RATE; + h += r; nblocks--; } } -void PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_haraka_S_inc_init(uint8_t *s_inc) { +void haraka_S_inc_init(uint8_t *s_inc) { size_t i; for (i = 0; i < 64; i++) { @@ -734,7 +721,8 @@ void PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_haraka_S_inc_init(uint8_t *s_inc) { s_inc[64] = 0; } -void PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, const harakactx *state) { +void haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, + const spx_ctx *ctx) { size_t i; /* Recall that s_inc[64] is the non-absorbed bytes xored into the state */ @@ -745,19 +733,19 @@ void PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_haraka_S_inc_absorb(uint8_t *s_inc, c s_inc[s_inc[64] + i] ^= m[i]; } mlen -= (size_t)(HARAKAS_RATE - s_inc[64]); - m += HARAKAS_RATE - s_inc[64]; + m += HARAKAS_RATE - (uint8_t)s_inc[64]; s_inc[64] = 0; - PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_haraka512_perm(s_inc, s_inc, state); + haraka512_perm(s_inc, s_inc, ctx); } for (i = 0; i < mlen; i++) { s_inc[s_inc[64] + i] ^= m[i]; } - s_inc[64] = (uint8_t)(mlen + s_inc[64]); + s_inc[64] += (uint8_t)mlen; } -void PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_haraka_S_inc_finalize(uint8_t *s_inc) { +void haraka_S_inc_finalize(uint8_t *s_inc) { /* After haraka_S_inc_absorb, we are guaranteed that s_inc[64] < HARAKAS_RATE, so we can always use one more byte for p in the current state. */ s_inc[s_inc[64]] ^= 0x1F; @@ -765,22 +753,23 @@ void PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_haraka_S_inc_finalize(uint8_t *s_inc) s_inc[64] = 0; } -void PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, const harakactx *state) { - uint8_t i; +void haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, + const spx_ctx *ctx) { + size_t i; /* First consume any bytes we still have sitting around */ for (i = 0; i < outlen && i < s_inc[64]; i++) { /* There are s_inc[64] bytes left, so r - s_inc[64] is the first available byte. We consume from there, i.e., up to r. */ - out[i] = s_inc[(HARAKAS_RATE - s_inc[64] + i)]; + out[i] = (uint8_t)s_inc[(HARAKAS_RATE - s_inc[64] + i)]; } out += i; outlen -= i; - s_inc[64] = (uint8_t)(s_inc[64] - i); + s_inc[64] -= (uint8_t)i; /* Then squeeze the remaining necessary blocks */ while (outlen > 0) { - PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_haraka512_perm(s_inc, s_inc, state); + haraka512_perm(s_inc, s_inc, ctx); for (i = 0; i < outlen && i < HARAKAS_RATE; i++) { out[i] = s_inc[i]; @@ -791,7 +780,9 @@ void PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_haraka_S_inc_squeeze(uint8_t *out, si } } -void PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_haraka_S(unsigned char *out, unsigned long long outlen, const unsigned char *in, unsigned long long inlen, const harakactx *state) { +void haraka_S(unsigned char *out, unsigned long long outlen, + const unsigned char *in, unsigned long long inlen, + const spx_ctx *ctx) { unsigned long long i; unsigned char s[64]; unsigned char d[32]; @@ -799,20 +790,21 @@ void PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_haraka_S(unsigned char *out, unsigned for (i = 0; i < 64; i++) { s[i] = 0; } - haraka_S_absorb(s, in, inlen, 0x1F, state); + haraka_S_absorb(s, 32, in, inlen, 0x1F, ctx); - haraka_S_squeezeblocks(out, outlen / 32, s, state); + haraka_S_squeezeblocks(out, outlen / 32, s, 32, ctx); out += (outlen / 32) * 32; if (outlen % 32) { - haraka_S_squeezeblocks(d, 1, s, state); + haraka_S_squeezeblocks(d, 1, s, 32, ctx); for (i = 0; i < outlen % 32; i++) { out[i] = d[i]; } } } -void PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_haraka512_perm(unsigned char *out, const unsigned char *in, const harakactx *state) { +void haraka512_perm(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx) { uint32_t w[16]; uint64_t q[8], tmp_q; unsigned int i, j; @@ -829,7 +821,7 @@ void PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_haraka512_perm(unsigned char *out, co br_aes_ct64_bitslice_Sbox(q); shift_rows(q); mix_columns(q); - add_round_key(q, state->tweaked512_rc64[2 * i + j]); + add_round_key(q, ctx->tweaked512_rc64[2 * i + j]); } /* Mix states */ for (j = 0; j < 8; j++) { @@ -857,12 +849,12 @@ void PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_haraka512_perm(unsigned char *out, co br_range_enc32le(out, w, 16); } -void PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_haraka512(unsigned char *out, const unsigned char *in, const harakactx *state) { +void haraka512(unsigned char *out, const unsigned char *in, const spx_ctx *ctx) { int i; unsigned char buf[64]; - PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_haraka512_perm(buf, in, state); + haraka512_perm(buf, in, ctx); /* Feed-forward */ for (i = 0; i < 64; i++) { buf[i] = buf[i] ^ in[i]; @@ -876,50 +868,8 @@ void PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_haraka512(unsigned char *out, const u } -void PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_haraka256(unsigned char *out, const unsigned char *in, const harakactx *state) { - uint32_t q[8], tmp_q; - int i, j; - - for (i = 0; i < 4; i++) { - q[2 * i] = br_dec32le(in + 4 * i); - q[2 * i + 1] = br_dec32le(in + 4 * i + 16); - } - br_aes_ct_ortho(q); - - /* AES rounds */ - for (i = 0; i < 5; i++) { - for (j = 0; j < 2; j++) { - br_aes_ct_bitslice_Sbox(q); - shift_rows32(q); - mix_columns32(q); - add_round_key32(q, state->tweaked256_rc32[2 * i + j]); - } - - /* Mix states */ - for (j = 0; j < 8; j++) { - tmp_q = q[j]; - q[j] = (tmp_q & 0x81818181) | - (tmp_q & 0x02020202) << 1 | - (tmp_q & 0x04040404) << 2 | - (tmp_q & 0x08080808) << 3 | - (tmp_q & 0x10101010) >> 3 | - (tmp_q & 0x20202020) >> 2 | - (tmp_q & 0x40404040) >> 1; - } - } - - br_aes_ct_ortho(q); - for (i = 0; i < 4; i++) { - br_enc32le(out + 4 * i, q[2 * i]); - br_enc32le(out + 4 * i + 16, q[2 * i + 1]); - } - - for (i = 0; i < 32; i++) { - out[i] ^= in[i]; - } -} - -void PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_haraka256_sk(unsigned char *out, const unsigned char *in, const harakactx *state) { +void haraka256(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx) { uint32_t q[8], tmp_q; int i, j; @@ -935,7 +885,7 @@ void PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_haraka256_sk(unsigned char *out, cons br_aes_ct_bitslice_Sbox(q); shift_rows32(q); mix_columns32(q); - add_round_key32(q, state->tweaked256_rc32_sseed[2 * i + j]); + add_round_key32(q, ctx->tweaked256_rc32[2 * i + j]); } /* Mix states */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/haraka.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/haraka.h index 68db29ffdd..737cb6065f 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/haraka.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/haraka.h @@ -1,40 +1,42 @@ -#ifndef PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_HARAKA_H -#define PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_HARAKA_H +#ifndef SPX_HARAKA_H +#define SPX_HARAKA_H -#include -#include - -typedef struct { - uint64_t tweaked512_rc64[10][8]; - uint32_t tweaked256_rc32[10][8]; - uint32_t tweaked256_rc32_sseed[10][8]; -} harakactx; +#include "context.h" +#include "params.h" /* Tweak constants with seed */ -void PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_tweak_constants( - harakactx *state, - const unsigned char *pk_seed, const unsigned char *sk_seed, - unsigned long long seed_length); +#define tweak_constants SPX_NAMESPACE(tweak_constants) +void tweak_constants(spx_ctx *ctx); /* Haraka Sponge */ -void PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_haraka_S_inc_init(uint8_t *s_inc); -void PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, const harakactx *state); -void PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_haraka_S_inc_finalize(uint8_t *s_inc); -void PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, const harakactx *state); -void PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_haraka_S( - unsigned char *out, unsigned long long outlen, - const unsigned char *in, unsigned long long inlen, const harakactx *state); +#define haraka_S_inc_init SPX_NAMESPACE(haraka_S_inc_init) +void haraka_S_inc_init(uint8_t *s_inc); +#define haraka_S_inc_absorb SPX_NAMESPACE(haraka_S_inc_absorb) +void haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, + const spx_ctx *ctx); +#define haraka_S_inc_finalize SPX_NAMESPACE(haraka_S_inc_finalize) +void haraka_S_inc_finalize(uint8_t *s_inc); +#define haraka_S_inc_squeeze SPX_NAMESPACE(haraka_S_inc_squeeze) +void haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, + const spx_ctx *ctx); +#define haraka_S SPX_NAMESPACE(haraka_S) +void haraka_S(unsigned char *out, unsigned long long outlen, + const unsigned char *in, unsigned long long inlen, + const spx_ctx *ctx); /* Applies the 512-bit Haraka permutation to in. */ -void PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_haraka512_perm(unsigned char *out, const unsigned char *in, const harakactx *state); +#define haraka512_perm SPX_NAMESPACE(haraka512_perm) +void haraka512_perm(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx); /* Implementation of Haraka-512 */ -void PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_haraka512(unsigned char *out, const unsigned char *in, const harakactx *state); +#define haraka512 SPX_NAMESPACE(haraka512) +void haraka512(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx); /* Implementation of Haraka-256 */ -void PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_haraka256(unsigned char *out, const unsigned char *in, const harakactx *state); - -/* Implementation of Haraka-256 using sk.seed constants */ -void PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_haraka256_sk(unsigned char *out, const unsigned char *in, const harakactx *state); +#define haraka256 SPX_NAMESPACE(haraka256) +void haraka256(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/haraka_offsets.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/haraka_offsets.h new file mode 100644 index 0000000000..7c062272a0 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/haraka_offsets.h @@ -0,0 +1,21 @@ +#ifndef HARAKA_OFFSETS_H_ +#define HARAKA_OFFSETS_H_ + +/* + * Offsets of various fields in the address structure when we use Haraka as + * the Sphincs+ hash function + */ + +#define SPX_OFFSET_LAYER 3 /* The byte used to specify the Merkle tree layer */ +#define SPX_OFFSET_TREE 8 /* The start of the 8 byte field used to specify the tree */ +#define SPX_OFFSET_TYPE 19 /* The byte used to specify the hash type (reason) */ +#define SPX_OFFSET_KP_ADDR2 22 /* The high byte used to specify the key pair (which one-time signature) */ +#define SPX_OFFSET_KP_ADDR1 23 /* The low byte used to specify the key pair */ +#define SPX_OFFSET_CHAIN_ADDR 27 /* The byte used to specify the chain address (which Winternitz chain) */ +#define SPX_OFFSET_HASH_ADDR 31 /* The byte used to specify the hash address (where in the Winternitz chain) */ +#define SPX_OFFSET_TREE_HGT 27 /* The byte used to specify the height of this node in the FORS or Merkle tree */ +#define SPX_OFFSET_TREE_INDEX 28 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ + +#define SPX_HARAKA 1 + +#endif /* HARAKA_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/hash.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/hash.h index f7c1f53a4d..f7c87d4c3c 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/hash.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/hash.h @@ -1,31 +1,28 @@ -#ifndef PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_HASH_H -#define PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_HASH_H - -#include "hash_state.h" +#ifndef SPX_HASH_H +#define SPX_HASH_H #include #include -void PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_initialize_hash_function( - hash_state *hash_state_seeded, - const unsigned char *pub_seed, const unsigned char *sk_seed); +#include "context.h" +#include "params.h" + +#define prf_addr SPX_NAMESPACE(prf_addr) +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]); -void PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_destroy_hash_function(hash_state *hash_state_seeded); +#define gen_message_random SPX_NAMESPACE(gen_message_random) +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); -void PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded); +#define hash_message SPX_NAMESPACE(hash_message) +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); -void PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); -void PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/hash_haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/hash_haraka.c index 325b54ff32..750a67423b 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/hash_haraka.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/hash_haraka.c @@ -2,58 +2,44 @@ #include #include "address.h" -#include "haraka.h" -#include "hash.h" #include "params.h" #include "utils.h" -void PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_initialize_hash_function( - hash_state *hash_state_seeded, - const unsigned char *pub_seed, const unsigned char *sk_seed) { - PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_tweak_constants(hash_state_seeded, pub_seed, sk_seed, PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_N); -} - -/* The haraka implementation is stack based and won't be replaced in PQClean/OQS, - so we don't need to do anything */ -void PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_destroy_hash_function( - hash_state *hash_state_seeded) { // NOLINT(readability-non-const-parameter) - (void)hash_state_seeded; -} +#include "haraka.h" +#include "hash.h" /* - * Computes PRF(key, addr), given a secret key of PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_N bytes and an address + * Computes PRF(key, addr), given a secret key of SPX_N bytes and an address */ -void PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded) { - unsigned char buf[PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_ADDR_BYTES]; - /* Since PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_N may be smaller than 32, we need a temporary buffer. */ +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]) { + /* Since SPX_N may be smaller than 32, we need temporary buffers. */ unsigned char outbuf[32]; + unsigned char buf[64] = {0}; - (void)key; /* Suppress an 'unused parameter' warning. */ + memcpy(buf, addr, SPX_ADDR_BYTES); + memcpy(buf + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); - PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_addr_to_bytes(buf, addr); - PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_haraka256_sk(outbuf, buf, hash_state_seeded); - memcpy(out, outbuf, PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_N); + haraka512(outbuf, (const void *)buf, ctx); + memcpy(out, outbuf, SPX_N); } /** * Computes the message-dependent randomness R, using a secret seed and an * optional randomization value as well as the message. */ -void PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded) { +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { uint8_t s_inc[65]; - PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_haraka_S_inc_init(s_inc); - PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_haraka_S_inc_absorb(s_inc, sk_prf, PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_N, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_haraka_S_inc_absorb(s_inc, optrand, PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_N, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_haraka_S_inc_absorb(s_inc, m, mlen, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_haraka_S_inc_finalize(s_inc); - PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_haraka_S_inc_squeeze(R, PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_N, s_inc, hash_state_seeded); + haraka_S_inc_init(s_inc); + haraka_S_inc_absorb(s_inc, sk_prf, SPX_N, ctx); + haraka_S_inc_absorb(s_inc, optrand, SPX_N, ctx); + haraka_S_inc_absorb(s_inc, m, mlen, ctx); + haraka_S_inc_finalize(s_inc); + haraka_S_inc_squeeze(R, SPX_N, s_inc, ctx); } /** @@ -61,36 +47,35 @@ void PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_gen_message_random( * Outputs the message digest and the index of the leaf. The index is split in * the tree index and the leaf index, for convenient copying to an address. */ -void PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded) { -#define PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_TREE_BITS (PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_TREE_HEIGHT * (PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_D - 1)) -#define PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_TREE_BYTES ((PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_TREE_BITS + 7) / 8) -#define PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_LEAF_BITS PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_TREE_HEIGHT -#define PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_LEAF_BYTES ((PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_LEAF_BITS + 7) / 8) -#define PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_DGST_BYTES (PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_FORS_MSG_BYTES + PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_TREE_BYTES + PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_LEAF_BYTES) +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { +#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) +#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) +#define SPX_LEAF_BITS SPX_TREE_HEIGHT +#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) +#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) - unsigned char buf[PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_DGST_BYTES]; + unsigned char buf[SPX_DGST_BYTES]; unsigned char *bufp = buf; uint8_t s_inc[65]; - PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_haraka_S_inc_init(s_inc); - PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_haraka_S_inc_absorb(s_inc, R, PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_N, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_haraka_S_inc_absorb(s_inc, pk + PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_N, PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_N, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_haraka_S_inc_absorb(s_inc, m, mlen, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_haraka_S_inc_finalize(s_inc); - PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_haraka_S_inc_squeeze(buf, PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_DGST_BYTES, s_inc, hash_state_seeded); + haraka_S_inc_init(s_inc); + haraka_S_inc_absorb(s_inc, R, SPX_N, ctx); + haraka_S_inc_absorb(s_inc, pk + SPX_N, SPX_N, ctx); // Only absorb root part of pk + haraka_S_inc_absorb(s_inc, m, mlen, ctx); + haraka_S_inc_finalize(s_inc); + haraka_S_inc_squeeze(buf, SPX_DGST_BYTES, s_inc, ctx); + + memcpy(digest, bufp, SPX_FORS_MSG_BYTES); + bufp += SPX_FORS_MSG_BYTES; - memcpy(digest, bufp, PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_FORS_MSG_BYTES); - bufp += PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_FORS_MSG_BYTES; - *tree = PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_bytes_to_ull(bufp, PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_TREE_BYTES); - *tree &= (~(uint64_t)0) >> (64 - PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_TREE_BITS); - bufp += PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_TREE_BYTES; + *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); + *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); + bufp += SPX_TREE_BYTES; - *leaf_idx = (uint32_t)PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_bytes_to_ull( - bufp, PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_LEAF_BYTES); - *leaf_idx &= (~(uint32_t)0) >> (32 - PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_LEAF_BITS); + *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); + *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/hash_state.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/hash_state.h deleted file mode 100644 index 5adb1d9a22..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/hash_state.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef SPX_HASH_STATE_H -#define SPX_HASH_STATE_H - -/** - * Defines the type of the hash function state. - * - * Don't be fooled into thinking this instance of SPHINCS+ isn't stateless! - * - * From Section 7.2.2 from the SPHINCS+ round-2 specification: - * - * Each of the instances of the tweakable hash function take PK.seed as its - * first input, which is constant for a given key pair – and, thus, across - * a single signature. This leads to a lot of redundant computation. To remedy - * this, we pad PK.seed to the length of a full 64-byte SHA-256 input block. - * Because of the Merkle-DamgÃ¥rd construction that underlies SHA-256, this - * allows for reuse of the intermediate SHA-256 state after the initial call to - * the compression function which improves performance. - * - * We pass this hash state around in functions, because otherwise we need to - * have a global variable. - */ - -#include "haraka.h" -#define hash_state harakactx - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/merkle.c b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/merkle.c new file mode 100644 index 0000000000..0c1479fd93 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/merkle.c @@ -0,0 +1,59 @@ +#include +#include + +#include "address.h" +#include "merkle.h" +#include "params.h" +#include "utils.h" +#include "utilsx1.h" +#include "wots.h" +#include "wotsx1.h" + +/* + * This generates a Merkle signature (WOTS signature followed by the Merkle + * authentication path). This is in this file because most of the complexity + * is involved with the WOTS signature; the Merkle authentication path logic + * is mostly hidden in treehashx4 + */ +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf) { + unsigned char *auth_path = sig + SPX_WOTS_BYTES; + struct leaf_info_x1 info = { 0 }; + unsigned steps[ SPX_WOTS_LEN ]; + + info.wots_sig = sig; + chain_lengths(steps, root); + info.wots_steps = steps; + + set_type(&tree_addr[0], SPX_ADDR_TYPE_HASHTREE); + set_type(&info.pk_addr[0], SPX_ADDR_TYPE_WOTSPK); + copy_subtree_addr(&info.leaf_addr[0], wots_addr); + copy_subtree_addr(&info.pk_addr[0], wots_addr); + + info.wots_sign_leaf = idx_leaf; + + treehashx1(root, auth_path, ctx, + idx_leaf, 0, + SPX_TREE_HEIGHT, + wots_gen_leafx1, + tree_addr, &info); +} + +/* Compute root node of the top-most subtree. */ +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { + /* We do not need the auth path in key generation, but it simplifies the + code to have just one treehash routine that computes both root and path + in one function. */ + unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; + uint32_t top_tree_addr[8] = {0}; + uint32_t wots_addr[8] = {0}; + + set_layer_addr(top_tree_addr, SPX_D - 1); + set_layer_addr(wots_addr, SPX_D - 1); + + merkle_sign(auth_path, root, ctx, + wots_addr, top_tree_addr, + (uint32_t)~0 /* ~0 means "don't bother generating an auth path */ ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/merkle.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/merkle.h new file mode 100644 index 0000000000..769cf2e970 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/merkle.h @@ -0,0 +1,21 @@ +#ifndef MERKLE_H_ +#define MERKLE_H_ + +#include + +#include "context.h" +#include "params.h" + +/* Generate a Merkle signature (WOTS signature followed by the Merkle */ +/* authentication path) */ +#define merkle_sign SPX_NAMESPACE(merkle_sign) +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf); + +/* Compute the root node of the top-most subtree. */ +#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); + +#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/nistapi.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/nistapi.h new file mode 100644 index 0000000000..3cb71afad4 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/nistapi.h @@ -0,0 +1,87 @@ +#ifndef SPX_API_H +#define SPX_API_H + +#include +#include + +#include "params.h" + +#define CRYPTO_ALGNAME "SPHINCS+" + +#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES +#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES +#define CRYPTO_BYTES SPX_BYTES +#define CRYPTO_SEEDBYTES (3*SPX_N) + +/* + * Returns the length of a secret key, in bytes + */ +#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) +size_t crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) +size_t crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) +size_t crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) +size_t crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +#define crypto_sign SPX_NAMESPACE(crypto_sign) +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/params.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/params.h index ec4b39be00..870e9ce136 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/params.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/params.h @@ -1,53 +1,56 @@ -#ifndef PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_PARAMS_H -#define PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_PARAMS_H +#ifndef SPX_PARAMS_H +#define SPX_PARAMS_H + +#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_##s /* Hash output length in bytes. */ -#define PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_N 16 +#define SPX_N 16 /* Height of the hypertree. */ -#define PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_FULL_HEIGHT 66 +#define SPX_FULL_HEIGHT 66 /* Number of subtree layer. */ -#define PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_D 22 +#define SPX_D 22 /* FORS tree dimensions. */ -#define PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_FORS_HEIGHT 6 -#define PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_FORS_TREES 33 +#define SPX_FORS_HEIGHT 6 +#define SPX_FORS_TREES 33 /* Winternitz parameter, */ -#define PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_WOTS_W 16 +#define SPX_WOTS_W 16 /* The hash function is defined by linking a different hash.c file, as opposed to setting a #define constant. */ /* For clarity */ -#define PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_ADDR_BYTES 32 +#define SPX_ADDR_BYTES 32 /* WOTS parameters. */ -#define PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_WOTS_LOGW 4 +#define SPX_WOTS_LOGW 4 -#define PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_WOTS_LEN1 (8 * PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_N / PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_WOTS_LOGW) +#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) -/* PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#define PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_WOTS_LEN2 3 +/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ +#define SPX_WOTS_LEN2 3 -#define PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_WOTS_LEN (PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_WOTS_LEN1 + PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_WOTS_LEN2) -#define PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_WOTS_BYTES (PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_WOTS_LEN * PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_N) -#define PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_WOTS_PK_BYTES PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_WOTS_BYTES +#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) +#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) +#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES /* Subtree size. */ -#define PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_TREE_HEIGHT (PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_FULL_HEIGHT / PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_D) +#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) + +//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT +// #error SPX_D should always divide SPX_FULL_HEIGHT +//#endif /* FORS parameters. */ -#define PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_FORS_MSG_BYTES ((PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_FORS_TREES + 7) / 8) -#define PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_FORS_BYTES ((PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_FORS_HEIGHT + 1) * PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_FORS_TREES * PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_N) -#define PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_FORS_PK_BYTES PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_N +#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) +#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) +#define SPX_FORS_PK_BYTES SPX_N /* Resulting SPX sizes. */ -#define PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_BYTES (PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_N + PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_FORS_BYTES + PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_D * PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_WOTS_BYTES +\ - PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_FULL_HEIGHT * PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_N) -#define PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_PK_BYTES (2 * PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_N) -#define PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_SK_BYTES (2 * PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_N + PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_PK_BYTES) - -/* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ -#define PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_OPTRAND_BYTES 32 +#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ + SPX_FULL_HEIGHT * SPX_N) +#define SPX_PK_BYTES (2 * SPX_N) +#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) + +#include "haraka_offsets.h" #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/sign.c b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/sign.c index 635c3b9b09..9d0c7d1b22 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/sign.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/sign.c @@ -3,72 +3,43 @@ #include #include "address.h" -#include "api.h" +#include "context.h" #include "fors.h" #include "hash.h" -#include "hash_state.h" +#include "merkle.h" +#include "nistapi.h" #include "params.h" #include "randombytes.h" #include "thash.h" #include "utils.h" #include "wots.h" -/** - * Computes the leaf at a given address. First generates the WOTS key pair, - * then computes leaf by hashing horizontally. - */ -static void wots_gen_leaf(unsigned char *leaf, const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx, const uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - unsigned char pk[PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_WOTS_BYTES]; - uint32_t wots_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_set_type( - wots_addr, PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_set_type( - wots_pk_addr, PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_ADDR_TYPE_WOTSPK); - - PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_set_keypair_addr( - wots_addr, addr_idx); - PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_wots_gen_pk( - pk, sk_seed, pub_seed, wots_addr, hash_state_seeded); - - PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_copy_keypair_addr( - wots_pk_addr, wots_addr); - PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_thash_WOTS_LEN( - leaf, pk, pub_seed, wots_pk_addr, hash_state_seeded); -} - /* * Returns the length of a secret key, in bytes */ -size_t PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_crypto_sign_secretkeybytes(void) { - return PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_CRYPTO_SECRETKEYBYTES; +size_t crypto_sign_secretkeybytes(void) { + return CRYPTO_SECRETKEYBYTES; } /* * Returns the length of a public key, in bytes */ -size_t PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_crypto_sign_publickeybytes(void) { - return PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_CRYPTO_PUBLICKEYBYTES; +size_t crypto_sign_publickeybytes(void) { + return CRYPTO_PUBLICKEYBYTES; } /* * Returns the length of a signature, in bytes */ -size_t PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_crypto_sign_bytes(void) { - return PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_CRYPTO_BYTES; +size_t crypto_sign_bytes(void) { + return CRYPTO_BYTES; } /* * Returns the length of the seed required to generate a key pair, in bytes */ -size_t PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_crypto_sign_seedbytes(void) { - return PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_CRYPTO_SEEDBYTES; +size_t crypto_sign_seedbytes(void) { + return CRYPTO_SEEDBYTES; } /* @@ -76,37 +47,30 @@ size_t PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_crypto_sign_seedbytes(void) { * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] * Format pk: [PUB_SEED || root] */ -int PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed) { - /* We do not need the auth path in key generation, but it simplifies the - code to have just one treehash routine that computes both root and path - in one function. */ - unsigned char auth_path[PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_TREE_HEIGHT * PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_N]; - uint32_t top_tree_addr[8] = {0}; - hash_state hash_state_seeded; - - PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_set_layer_addr( - top_tree_addr, PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_D - 1); - PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_set_type( - top_tree_addr, PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_ADDR_TYPE_HASHTREE); +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed) { + spx_ctx ctx; /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ - memcpy(sk, seed, PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_CRYPTO_SEEDBYTES); + memcpy(sk, seed, CRYPTO_SEEDBYTES); - memcpy(pk, sk + 2 * PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_N, PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_N); + memcpy(pk, sk + 2 * SPX_N, SPX_N); + + memcpy(ctx.pub_seed, pk, SPX_N); + memcpy(ctx.sk_seed, sk, SPX_N); /* This hook allows the hash function instantiation to do whatever preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_initialize_hash_function(&hash_state_seeded, pk, sk); + initialize_hash_function(&ctx); /* Compute root node of the top-most subtree. */ - PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_treehash_TREE_HEIGHT( - sk + 3 * PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_N, auth_path, sk, sk + 2 * PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_N, 0, 0, - wots_gen_leaf, top_tree_addr, &hash_state_seeded); + merkle_gen_root(sk + 3 * SPX_N, &ctx); + + // cleanup + free_hash_function(&ctx); - memcpy(pk + PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_N, sk + 3 * PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_N, PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_N); + memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); - PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_destroy_hash_function(&hash_state_seeded); return 0; } @@ -115,12 +79,10 @@ int PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_crypto_sign_seed_keypair( * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] * Format pk: [PUB_SEED || root] */ -int PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk) { - unsigned char seed[PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_CRYPTO_SEEDBYTES]; - randombytes(seed, PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_CRYPTO_SEEDBYTES); - PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_crypto_sign_seed_keypair( - pk, sk, seed); +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { + uint8_t seed[CRYPTO_SEEDBYTES]; + randombytes(seed, CRYPTO_SEEDBYTES); + crypto_sign_seed_keypair(pk, sk, seed); return 0; } @@ -128,101 +90,83 @@ int PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_crypto_sign_keypair( /** * Returns an array containing a detached signature. */ -int PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - const unsigned char *sk_seed = sk; - const unsigned char *sk_prf = sk + PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_N; - const unsigned char *pk = sk + 2 * PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_N; - const unsigned char *pub_seed = pk; - - unsigned char optrand[PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_N]; - unsigned char mhash[PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_FORS_MSG_BYTES]; - unsigned char root[PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_N]; +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk) { + spx_ctx ctx; + + const uint8_t *sk_prf = sk + SPX_N; + const uint8_t *pk = sk + 2 * SPX_N; + + uint8_t optrand[SPX_N]; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t root[SPX_N]; uint32_t i; uint64_t tree; uint32_t idx_leaf; uint32_t wots_addr[8] = {0}; uint32_t tree_addr[8] = {0}; - hash_state hash_state_seeded; + memcpy(ctx.sk_seed, sk, SPX_N); + memcpy(ctx.pub_seed, pk, SPX_N); /* This hook allows the hash function instantiation to do whatever preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_initialize_hash_function( - &hash_state_seeded, - pub_seed, sk_seed); + initialize_hash_function(&ctx); - PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_set_type( - wots_addr, PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_set_type( - tree_addr, PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_ADDR_TYPE_HASHTREE); + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); /* Optionally, signing can be made non-deterministic using optrand. This can help counter side-channel attacks that would benefit from getting a large number of traces when the signer uses the same nodes. */ - randombytes(optrand, PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_N); + randombytes(optrand, SPX_N); /* Compute the digest randomization value. */ - PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_gen_message_random( - sig, sk_prf, optrand, m, mlen, &hash_state_seeded); + gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); /* Derive the message digest and leaf index from R, PK and M. */ - PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_N; + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; - PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); /* Sign the message hash using FORS. */ - PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_fors_sign( - sig, root, mhash, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_FORS_BYTES; - - for (i = 0; i < PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_D; i++) { - PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_set_tree_addr(tree_addr, tree); - - PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); - - /* Compute a WOTS signature. */ - PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_wots_sign( - sig, root, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_WOTS_BYTES; - - /* Compute the authentication path for the used WOTS leaf. */ - PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_treehash_TREE_HEIGHT( - root, sig, sk_seed, pub_seed, idx_leaf, 0, - wots_gen_leaf, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_TREE_HEIGHT * PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_N; + fors_sign(sig, root, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); + sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_TREE_HEIGHT; + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; } - *siglen = PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_BYTES; + free_hash_function(&ctx); + + *siglen = SPX_BYTES; - PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_destroy_hash_function(&hash_state_seeded); return 0; } /** * Verifies a detached signature and message under a given public key. */ -int PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk) { - const unsigned char *pub_seed = pk; - const unsigned char *pub_root = pk + PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_N; - unsigned char mhash[PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_FORS_MSG_BYTES]; - unsigned char wots_pk[PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_WOTS_BYTES]; - unsigned char root[PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_N]; - unsigned char leaf[PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_N]; +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk) { + spx_ctx ctx; + const uint8_t *pub_root = pk + SPX_N; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t wots_pk[SPX_WOTS_BYTES]; + uint8_t root[SPX_N]; + uint8_t leaf[SPX_N]; unsigned int i; uint64_t tree; uint32_t idx_leaf; @@ -230,78 +174,66 @@ int PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_crypto_sign_verify( uint32_t tree_addr[8] = {0}; uint32_t wots_pk_addr[8] = {0}; - hash_state hash_state_seeded; - - if (siglen != PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_BYTES) { + if (siglen != SPX_BYTES) { return -1; } + memcpy(ctx.pub_seed, pk, SPX_N); + /* This hook allows the hash function instantiation to do whatever preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_initialize_hash_function( - &hash_state_seeded, - pub_seed, NULL); + initialize_hash_function(&ctx); - PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_set_type( - wots_addr, PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_set_type( - tree_addr, PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_ADDR_TYPE_HASHTREE); - PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_set_type( - wots_pk_addr, PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_ADDR_TYPE_WOTSPK); + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); /* Derive the message digest and leaf index from R || PK || M. */ - /* The additional PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_N is a result of the hash domain separator. */ - PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_N; + /* The additional SPX_N is a result of the hash domain separator. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; /* Layer correctly defaults to 0, so no need to set_layer_addr */ - PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); - PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_fors_pk_from_sig( - root, sig, mhash, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_FORS_BYTES; + fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; /* For each subtree.. */ - for (i = 0; i < PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_D; i++) { - PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_set_tree_addr(tree_addr, tree); + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); - PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); - PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_copy_keypair_addr( - wots_pk_addr, wots_addr); + copy_keypair_addr(wots_pk_addr, wots_addr); /* The WOTS public key is only correct if the signature was correct. */ /* Initially, root is the FORS pk, but on subsequent iterations it is the root of the subtree below the currently processed subtree. */ - PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_wots_pk_from_sig( - wots_pk, sig, root, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_WOTS_BYTES; + wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); + sig += SPX_WOTS_BYTES; /* Compute the leaf node using the WOTS public key. */ - PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_thash_WOTS_LEN( - leaf, wots_pk, pub_seed, wots_pk_addr, &hash_state_seeded); + thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); /* Compute the root node of this subtree. */ - PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_compute_root( - root, leaf, idx_leaf, 0, sig, PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_TREE_HEIGHT, - pub_seed, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_TREE_HEIGHT * PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_N; + compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, + &ctx, tree_addr); + sig += SPX_TREE_HEIGHT * SPX_N; /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_TREE_HEIGHT; + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; } - PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_destroy_hash_function(&hash_state_seeded); + // cleanup + free_hash_function(&ctx); + /* Check if the root node equals the root node in the public key. */ - if (memcmp(root, pub_root, PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_N) != 0) { + if (memcmp(root, pub_root, SPX_N) != 0) { return -1; } @@ -312,15 +244,14 @@ int PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_crypto_sign_verify( /** * Returns an array containing the signature followed by the message. */ -int PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk) { size_t siglen; - PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_crypto_sign_signature( - sm, &siglen, m, mlen, sk); + crypto_sign_signature(sm, &siglen, m, mlen, sk); - memmove(sm + PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_BYTES, m, mlen); + memmove(sm + SPX_BYTES, m, mlen); *smlen = siglen + mlen; return 0; @@ -329,28 +260,27 @@ int PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_crypto_sign( /** * Verifies a given signature-message pair under a given public key. */ -int PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk) { +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk) { /* The API caller does not necessarily know what size a signature should be - but SPHINCS+ signatures are always exactly PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_BYTES. */ - if (smlen < PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_BYTES) { + but SPHINCS+ signatures are always exactly SPX_BYTES. */ + if (smlen < SPX_BYTES) { memset(m, 0, smlen); *mlen = 0; return -1; } - *mlen = smlen - PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_BYTES; + *mlen = smlen - SPX_BYTES; - if (PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_crypto_sign_verify( - sm, PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_BYTES, sm + PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_BYTES, *mlen, pk)) { + if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { memset(m, 0, smlen); *mlen = 0; return -1; } /* If verification was successful, move the message to the right place. */ - memmove(m, sm + PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_BYTES, *mlen); + memmove(m, sm + SPX_BYTES, *mlen); return 0; } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/thash.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/thash.h index 21eaec4aca..8687ccfb4d 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/thash.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/thash.h @@ -1,28 +1,13 @@ -#ifndef PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_THASH_H -#define PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_THASH_H +#ifndef SPX_THASH_H +#define SPX_THASH_H -#include "hash_state.h" +#include "context.h" +#include "params.h" #include -void PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); +#define thash SPX_NAMESPACE(thash) +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/thash_haraka_robust.c b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/thash_haraka_robust.c index 2c458a4af1..109502cbc2 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/thash_haraka_robust.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/thash_haraka_robust.c @@ -2,93 +2,44 @@ #include #include "address.h" -#include "hash_state.h" #include "params.h" #include "thash.h" +#include "utils.h" #include "haraka.h" /** - * Takes an array of inblocks concatenated arrays of PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_N bytes. + * Takes an array of inblocks concatenated arrays of SPX_N bytes. */ -static void PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_thash( - unsigned char *out, unsigned char *buf, - const unsigned char *in, unsigned int inblocks, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char *bitmask = buf + PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_ADDR_BYTES; +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]) { + PQCLEAN_VLA(uint8_t, buf, SPX_ADDR_BYTES + inblocks * SPX_N); + PQCLEAN_VLA(uint8_t, bitmask, inblocks * SPX_N); unsigned char outbuf[32]; unsigned char buf_tmp[64]; unsigned int i; - (void)pub_seed; /* Suppress an 'unused parameter' warning. */ - if (inblocks == 1) { /* F function */ - /* Since PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_N may be smaller than 32, we need a temporary buffer. */ + /* Since SPX_N may be smaller than 32, we need a temporary buffer. */ memset(buf_tmp, 0, 64); - PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_addr_to_bytes(buf_tmp, addr); + memcpy(buf_tmp, addr, 32); - PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_haraka256(outbuf, buf_tmp, hash_state_seeded); - for (i = 0; i < inblocks * PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_N; i++) { - buf_tmp[PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_ADDR_BYTES + i] = in[i] ^ outbuf[i]; + haraka256(outbuf, buf_tmp, ctx); + for (i = 0; i < inblocks * SPX_N; i++) { + buf_tmp[SPX_ADDR_BYTES + i] = in[i] ^ outbuf[i]; } - PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_haraka512(outbuf, buf_tmp, hash_state_seeded); - memcpy(out, outbuf, PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_N); + haraka512(outbuf, buf_tmp, ctx); + memcpy(out, outbuf, SPX_N); } else { /* All other tweakable hashes*/ - PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_addr_to_bytes(buf, addr); - PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_haraka_S( - bitmask, inblocks * PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_N, buf, PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_ADDR_BYTES, hash_state_seeded); + memcpy(buf, addr, 32); + haraka_S(bitmask, inblocks * SPX_N, buf, SPX_ADDR_BYTES, ctx); - for (i = 0; i < inblocks * PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_N; i++) { - buf[PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_ADDR_BYTES + i] = in[i] ^ bitmask[i]; + for (i = 0; i < inblocks * SPX_N; i++) { + buf[SPX_ADDR_BYTES + i] = in[i] ^ bitmask[i]; } - PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_haraka_S( - out, PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_N, buf, PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_N, hash_state_seeded); + haraka_S(out, SPX_N, buf, SPX_ADDR_BYTES + inblocks * SPX_N, ctx); } } - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_ADDR_BYTES + 1 * PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_N]; - PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_thash( - out, buf, in, 1, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_ADDR_BYTES + 2 * PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_N]; - PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_thash( - out, buf, in, 2, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_ADDR_BYTES + PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_WOTS_LEN * PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_N]; - PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_thash( - out, buf, in, PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_WOTS_LEN, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_ADDR_BYTES + PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_FORS_TREES * PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_N]; - PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_thash( - out, buf, in, PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_FORS_TREES, pub_seed, addr, hash_state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/utils.c b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/utils.c index 99e0fc2460..177b541fb9 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/utils.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/utils.c @@ -1,34 +1,41 @@ -#include #include +#include "utils.h" + #include "address.h" #include "hash.h" -#include "hash_state.h" #include "params.h" #include "thash.h" -#include "utils.h" /** * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. */ -void PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in) { +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in) { + int i; /* Iterate over out in decreasing order, for big-endianness. */ - for (size_t i = outlen; i > 0; i--) { - out[i - 1] = in & 0xff; + for (i = (signed int)outlen - 1; i >= 0; i--) { + out[i] = in & 0xff; in = in >> 8; } } +void u32_to_bytes(unsigned char *out, uint32_t in) { + out[0] = (unsigned char)(in >> 24); + out[1] = (unsigned char)(in >> 16); + out[2] = (unsigned char)(in >> 8); + out[3] = (unsigned char)in; +} + /** * Converts the inlen bytes in 'in' from big-endian byte order to an integer. */ -unsigned long long PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_bytes_to_ull( - const unsigned char *in, size_t inlen) { +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { unsigned long long retval = 0; + unsigned int i; - for (size_t i = 0; i < inlen; i++) { + for (i = 0; i < inlen; i++) { retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); } return retval; @@ -38,94 +45,80 @@ unsigned long long PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_bytes_to_ull( * Computes a root node given a leaf and an auth path. * Expects address to be complete other than the tree_height and tree_index. */ -void PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]) { uint32_t i; - unsigned char buffer[2 * PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_N]; + unsigned char buffer[2 * SPX_N]; /* If leaf_idx is odd (last bit = 1), current path element is a right child and auth_path has to go left. Otherwise it is the other way around. */ if (leaf_idx & 1) { - memcpy(buffer + PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_N, leaf, PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_N); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_N); + memcpy(buffer + SPX_N, leaf, SPX_N); + memcpy(buffer, auth_path, SPX_N); } else { - memcpy(buffer, leaf, PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_N); - memcpy(buffer + PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_N, auth_path, PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_N); + memcpy(buffer, leaf, SPX_N); + memcpy(buffer + SPX_N, auth_path, SPX_N); } - auth_path += PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_N; + auth_path += SPX_N; for (i = 0; i < tree_height - 1; i++) { leaf_idx >>= 1; idx_offset >>= 1; /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_set_tree_height(addr, i + 1); - PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_set_tree_index( - addr, leaf_idx + idx_offset); + set_tree_height(addr, i + 1); + set_tree_index(addr, leaf_idx + idx_offset); /* Pick the right or left neighbor, depending on parity of the node. */ if (leaf_idx & 1) { - PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_thash_2( - buffer + PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_N, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_N); + thash(buffer + SPX_N, buffer, 2, ctx, addr); + memcpy(buffer, auth_path, SPX_N); } else { - PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_thash_2( - buffer, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer + PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_N, auth_path, PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_N); + thash(buffer, buffer, 2, ctx, addr); + memcpy(buffer + SPX_N, auth_path, SPX_N); } - auth_path += PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_N; + auth_path += SPX_N; } /* The last iteration is exceptional; we do not copy an auth_path node. */ leaf_idx >>= 1; idx_offset >>= 1; - PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_set_tree_height(addr, tree_height); - PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_set_tree_index( - addr, leaf_idx + idx_offset); - PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_thash_2( - root, buffer, pub_seed, addr, hash_state_seeded); + set_tree_height(addr, tree_height); + set_tree_index(addr, leaf_idx + idx_offset); + thash(root, buffer, 2, ctx, addr); } /** * For a given leaf index, computes the authentication path and the resulting * root node using Merkle's TreeHash algorithm. * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_ADDR_TYPE_FORSTREE). + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). * Applies the offset idx_offset to indices before building addresses, so that * it is possible to continue counting indices across trees. */ -static void PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_treehash( - unsigned char *root, unsigned char *auth_path, - unsigned char *stack, unsigned int *heights, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - +void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx * /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]) { + PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); + PQCLEAN_VLA(unsigned int, heights, tree_height + 1); unsigned int offset = 0; uint32_t idx; uint32_t tree_idx; for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { /* Add the next leaf node to the stack. */ - gen_leaf(stack + offset * PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_N, - sk_seed, pub_seed, idx + idx_offset, tree_addr, - hash_state_seeded); + gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); offset++; heights[offset - 1] = 0; /* If this is a node we need for the auth path.. */ if ((leaf_idx ^ 0x1) == idx) { - memcpy(auth_path, stack + (offset - 1)*PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_N, PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_N); + memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); } /* While the top-most nodes are of equal height.. */ @@ -134,66 +127,22 @@ static void PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_treehash( tree_idx = (idx >> (heights[offset - 1] + 1)); /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_set_tree_height( - tree_addr, heights[offset - 1] + 1); - PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_set_tree_index( - tree_addr, tree_idx + (idx_offset >> (heights[offset - 1] + 1))); + set_tree_height(tree_addr, heights[offset - 1] + 1); + set_tree_index(tree_addr, + tree_idx + (idx_offset >> (heights[offset - 1] + 1))); /* Hash the top-most nodes from the stack together. */ - PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_thash_2( - stack + (offset - 2)*PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_N, stack + (offset - 2)*PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_N, - pub_seed, tree_addr, hash_state_seeded); + thash(stack + (offset - 2)*SPX_N, + stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); offset--; /* Note that the top-most node is now one layer higher. */ heights[offset - 1]++; /* If this is a node we need for the auth path.. */ if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_path + heights[offset - 1]*PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_N, - stack + (offset - 1)*PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_N, PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_N); + memcpy(auth_path + heights[offset - 1]*SPX_N, + stack + (offset - 1)*SPX_N, SPX_N); } } } - memcpy(root, stack, PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_N); -} - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_FORS_HEIGHT + 1)*PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_N]; - unsigned int heights[PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_FORS_HEIGHT + 1]; - - PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_FORS_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_TREE_HEIGHT + 1)*PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_N]; - unsigned int heights[PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_TREE_HEIGHT + 1]; - - PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_TREE_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); + memcpy(root, stack, SPX_N); } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/utils.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/utils.h index ae73fd7d57..64f5d5a53a 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/utils.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/utils.h @@ -1,64 +1,58 @@ -#ifndef PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_UTILS_H -#define PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_UTILS_H +#ifndef SPX_UTILS_H +#define SPX_UTILS_H -#include "hash_state.h" -#include "params.h" -#include #include +#include "compat.h" +#include "context.h" +#include "params.h" + + +/* To support MSVC use alloca() instead of VLAs. See #20. */ + + /** * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. */ -void PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in); +#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in); +#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) +void u32_to_bytes(unsigned char *out, uint32_t in); /** * Converts the inlen bytes in 'in' from big-endian byte order to an integer. */ -unsigned long long PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_bytes_to_ull( - const unsigned char *in, size_t inlen); +#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); /** * Computes a root node given a leaf and an auth path. * Expects address to be complete other than the tree_height and tree_index. */ -void PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); +#define compute_root SPX_NAMESPACE(compute_root) +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]); /** * For a given leaf index, computes the authentication path and the resulting * root node using Merkle's TreeHash algorithm. * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_ADDR_TYPE_FORSTREE). + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). * Applies the offset idx_offset to indices before building addresses, so that * it is possible to continue counting indices across trees. */ -void PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); +#define treehash SPX_NAMESPACE(treehash) +void treehash(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx *ctx /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]); -void PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/utilsx1.c b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/utilsx1.c new file mode 100644 index 0000000000..fccb69b35d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/utilsx1.c @@ -0,0 +1,100 @@ +#include + +#include "utilsx1.h" + +#include "address.h" +#include "params.h" +#include "thash.h" +#include "utils.h" + +/* + * Generate the entire Merkle tree, computing the authentication path for + * leaf_idx, and the resulting root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) + * + * This expects tree_addr to be initialized to the addr structures for the + * Merkle tree nodes + * + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + * + * This works by using the standard Merkle tree building algorithm, + */ +void treehashx1(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, + uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* Where to write the leaves */, + const spx_ctx * /* ctx */, + uint32_t idx, void *info), + uint32_t tree_addr[8], + void *info) { + /* This is where we keep the intermediate nodes */ + PQCLEAN_VLA(uint8_t, stack, tree_height * SPX_N); + + uint32_t idx; + uint32_t max_idx = (uint32_t)((1 << tree_height) - 1); + for (idx = 0;; idx++) { + unsigned char current[2 * SPX_N]; /* Current logical node is at */ + /* index[SPX_N]. We do this to minimize the number of copies */ + /* needed during a thash */ + gen_leaf( ¤t[SPX_N], ctx, idx + idx_offset, + info ); + + /* Now combine the freshly generated right node with previously */ + /* generated left ones */ + uint32_t internal_idx_offset = idx_offset; + uint32_t internal_idx = idx; + uint32_t internal_leaf = leaf_idx; + uint32_t h; /* The height we are in the Merkle tree */ + for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { + + /* Check if we hit the top of the tree */ + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[SPX_N], SPX_N ); + return; + } + + /* + * Check if the node we have is a part of the + * authentication path; if it is, write it out + */ + if ((internal_idx ^ internal_leaf) == 0x01) { + memcpy( &auth_path[ h * SPX_N ], + ¤t[SPX_N], + SPX_N ); + } + + /* + * Check if we're at a left child; if so, stop going up the stack + * Exception: if we've reached the end of the tree, keep on going + * (so we combine the last 4 nodes into the one root node in two + * more iterations) + */ + if ((internal_idx & 1) == 0 && idx < max_idx) { + break; + } + + /* Ok, we're at a right node */ + /* Now combine the left and right logical nodes together */ + + /* Set the address of the node we're creating. */ + internal_idx_offset >>= 1; + set_tree_height(tree_addr, h + 1); + set_tree_index(tree_addr, internal_idx / 2 + internal_idx_offset ); + + unsigned char *left = &stack[h * SPX_N]; + memcpy( ¤t[0], left, SPX_N ); + thash( ¤t[1 * SPX_N], + ¤t[0 * SPX_N], + 2, ctx, tree_addr); + } + + /* We've hit a left child; save the current for when we get the */ + /* corresponding right right */ + memcpy( &stack[h * SPX_N], ¤t[SPX_N], SPX_N); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/utilsx1.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/utilsx1.h new file mode 100644 index 0000000000..e911d17d53 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/utilsx1.h @@ -0,0 +1,27 @@ +#ifndef SPX_UTILSX4_H +#define SPX_UTILSX4_H + +#include + +#include "context.h" +#include "params.h" + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +#define treehashx1 SPX_NAMESPACE(treehashx1) +void treehashx1(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* Where to write the leaf */, + const spx_ctx * /* ctx */, + uint32_t addr_idx, void *info), + uint32_t tree_addrx4[8], void *info); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/wots.c b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/wots.c index 4cb53a3e8c..249717aaa8 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/wots.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/wots.c @@ -1,32 +1,20 @@ #include #include +#include "wots.h" +#include "wotsx1.h" + #include "address.h" #include "hash.h" -#include "hash_state.h" #include "params.h" #include "thash.h" #include "utils.h" -#include "wots.h" +#include "utilsx1.h" // TODO clarify address expectations, and make them more uniform. // TODO i.e. do we expect types to be set already? // TODO and do we expect modifications or copies? -/** - * Computes the starting value for a chain, i.e. the secret key. - * Expects the address to be complete up to the chain address. - */ -static void wots_gen_sk(unsigned char *sk, const unsigned char *sk_seed, - uint32_t wots_addr[8], - const hash_state *hash_state_seeded) { - /* Make sure that the hash address is actually zeroed. */ - PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_set_hash_addr(wots_addr, 0); - - /* Generate sk element. */ - PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_prf_addr(sk, sk_seed, wots_addr, hash_state_seeded); -} - /** * Computes the chaining function. * out and in have to be n-byte arrays. @@ -36,18 +24,16 @@ static void wots_gen_sk(unsigned char *sk, const unsigned char *sk_seed, */ static void gen_chain(unsigned char *out, const unsigned char *in, unsigned int start, unsigned int steps, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { + const spx_ctx *ctx, uint32_t addr[8]) { uint32_t i; /* Initialize out with the value at position 'start'. */ - memcpy(out, in, PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_N); + memcpy(out, in, SPX_N); /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_WOTS_W; i++) { - PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_set_hash_addr(addr, i); - PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_thash_1( - out, out, pub_seed, addr, hash_state_seeded); + for (i = start; i < (start + steps) && i < SPX_WOTS_W; i++) { + set_hash_addr(addr, i); + thash(out, out, 1, ctx, addr); } } @@ -56,13 +42,13 @@ static void gen_chain(unsigned char *out, const unsigned char *in, * Interprets an array of bytes as integers in base w. * This only works when log_w is a divisor of 8. */ -static void base_w(unsigned int *output, const size_t out_len, +static void base_w(unsigned int *output, const int out_len, const unsigned char *input) { - size_t in = 0; - size_t out = 0; + int in = 0; + int out = 0; unsigned char total = 0; - unsigned int bits = 0; - size_t consumed; + int bits = 0; + int consumed; for (consumed = 0; consumed < out_len; consumed++) { if (bits == 0) { @@ -70,8 +56,8 @@ static void base_w(unsigned int *output, const size_t out_len, in++; bits += 8; } - bits -= PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_WOTS_LOGW; - output[out] = (unsigned int)((total >> bits) & (PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_WOTS_W - 1)); + bits -= SPX_WOTS_LOGW; + output[out] = (total >> bits) & (SPX_WOTS_W - 1); out++; } } @@ -80,67 +66,25 @@ static void base_w(unsigned int *output, const size_t out_len, static void wots_checksum(unsigned int *csum_base_w, const unsigned int *msg_base_w) { unsigned int csum = 0; - unsigned char csum_bytes[(PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_WOTS_LEN2 * PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_WOTS_LOGW + 7) / 8]; + unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; unsigned int i; /* Compute checksum. */ - for (i = 0; i < PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_WOTS_LEN1; i++) { - csum += PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_WOTS_W - 1 - msg_base_w[i]; + for (i = 0; i < SPX_WOTS_LEN1; i++) { + csum += SPX_WOTS_W - 1 - msg_base_w[i]; } /* Convert checksum to base_w. */ /* Make sure expected empty zero bits are the least significant bits. */ - csum = csum << (8 - ((PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_WOTS_LEN2 * PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_WOTS_LOGW) % 8)); - PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_ull_to_bytes( - csum_bytes, sizeof(csum_bytes), csum); - base_w(csum_base_w, PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_WOTS_LEN2, csum_bytes); + csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); + ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); + base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); } /* Takes a message and derives the matching chain lengths. */ -static void chain_lengths(unsigned int *lengths, const unsigned char *msg) { - base_w(lengths, PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_WOTS_LEN1, msg); - wots_checksum(lengths + PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_WOTS_LEN1, lengths); -} - -/** - * WOTS key generation. Takes a 32 byte sk_seed, expands it to WOTS private key - * elements and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_wots_gen_pk( - unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - uint32_t i; - - for (i = 0; i < PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_WOTS_LEN; i++) { - PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_set_chain_addr(addr, i); - wots_gen_sk(pk + i * PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_N, sk_seed, addr, hash_state_seeded); - gen_chain(pk + i * PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_N, pk + i * PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_N, - 0, PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_WOTS_W - 1, pub_seed, addr, hash_state_seeded); - } -} - -/** - * Takes a n-byte message and the 32-byte sk_see to compute a signature 'sig'. - */ -void PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_wots_sign( - unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *hash_state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_WOTS_LEN; i++) { - PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_set_chain_addr(addr, i); - wots_gen_sk(sig + i * PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_N, sk_seed, addr, hash_state_seeded); - gen_chain(sig + i * PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_N, sig + i * PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_N, 0, lengths[i], pub_seed, addr, hash_state_seeded); - } +void chain_lengths(unsigned int *lengths, const unsigned char *msg) { + base_w(lengths, SPX_WOTS_LEN1, msg); + wots_checksum(lengths + SPX_WOTS_LEN1, lengths); } /** @@ -148,20 +92,17 @@ void PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_wots_sign( * * Writes the computed public key to 'pk'. */ -void PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_wots_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_WOTS_LEN]; +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]) { + unsigned int lengths[SPX_WOTS_LEN]; uint32_t i; chain_lengths(lengths, msg); - for (i = 0; i < PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_WOTS_LEN; i++) { - PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_set_chain_addr(addr, i); - gen_chain(pk + i * PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_N, sig + i * PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_N, - lengths[i], PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_WOTS_W - 1 - lengths[i], pub_seed, addr, - hash_state_seeded); + for (i = 0; i < SPX_WOTS_LEN; i++) { + set_chain_addr(addr, i); + gen_chain(pk + i * SPX_N, sig + i * SPX_N, + lengths[i], SPX_WOTS_W - 1 - lengths[i], ctx, addr); } } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/wots.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/wots.h index cb7a296bf0..4e7692eeef 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/wots.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/wots.h @@ -1,41 +1,25 @@ -#ifndef PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_WOTS_H -#define PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_WOTS_H +#ifndef SPX_WOTS_H +#define SPX_WOTS_H -#include "hash_state.h" -#include "params.h" #include -/** - * WOTS key generation. Takes a 32 byte seed for the private key, expands it to - * a full WOTS private key and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_wots_gen_pk( - unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -/** - * Takes a n-byte message and the 32-byte seed for the private key to compute a - * signature that is placed at 'sig'. - */ -void PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_wots_sign( - unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *hash_state_seeded); +#include "context.h" +#include "params.h" /** * Takes a WOTS signature and an n-byte message, computes a WOTS public key. * * Writes the computed public key to 'pk'. */ -void PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_wots_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); +#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]); + +/* + * Compute the chain lengths needed for a given message hash + */ +#define chain_lengths SPX_NAMESPACE(chain_lengths) +void chain_lengths(unsigned int *lengths, const unsigned char *msg); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/wotsx1.c b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/wotsx1.c new file mode 100644 index 0000000000..3adec78dfb --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/wotsx1.c @@ -0,0 +1,76 @@ +#include +#include + +#include "wots.h" +#include "wotsx1.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "thash.h" +#include "utils.h" + +/* + * This generates a WOTS public key + * It also generates the WOTS signature if leaf_info indicates + * that we're signing with this WOTS key + */ +void wots_gen_leafx1(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info) { + struct leaf_info_x1 *info = v_info; + uint32_t *leaf_addr = info->leaf_addr; + uint32_t *pk_addr = info->pk_addr; + unsigned int i, k; + unsigned char pk_buffer[ SPX_WOTS_BYTES ]; + unsigned char *buffer; + uint32_t wots_k_mask; + + if (leaf_idx == info->wots_sign_leaf) { + /* We're traversing the leaf that's signing; generate the WOTS */ + /* signature */ + wots_k_mask = 0; + } else { + /* Nope, we're just generating pk's; turn off the signature logic */ + wots_k_mask = (uint32_t)~0; + } + + set_keypair_addr( leaf_addr, leaf_idx ); + set_keypair_addr( pk_addr, leaf_idx ); + + for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { + uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k to */ + /* the step if we're generating a signature, ~0 if we're not */ + + /* Start with the secret seed */ + set_chain_addr(leaf_addr, i); + set_hash_addr(leaf_addr, 0); + set_type(leaf_addr, SPX_ADDR_TYPE_WOTSPRF); + + prf_addr(buffer, ctx, leaf_addr); + + set_type(leaf_addr, SPX_ADDR_TYPE_WOTS); + + /* Iterate down the WOTS chain */ + for (k = 0;; k++) { + /* Check if this is the value that needs to be saved as a */ + /* part of the WOTS signature */ + if (k == wots_k) { + memcpy( info->wots_sig + i * SPX_N, buffer, SPX_N ); + } + + /* Check if we hit the top of the chain */ + if (k == SPX_WOTS_W - 1) { + break; + } + + /* Iterate one step on the chain */ + set_hash_addr(leaf_addr, k); + + thash(buffer, buffer, 1, ctx, leaf_addr); + } + } + + /* Do the final thash to generate the public keys */ + thash(dest, pk_buffer, SPX_WOTS_LEN, ctx, pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/wotsx1.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/wotsx1.h new file mode 100644 index 0000000000..e617929f96 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/wotsx1.h @@ -0,0 +1,39 @@ +#ifndef WOTSX1_H_ +#define WOTSX1_H_ + +#include + +#include "context.h" +#include "params.h" + +/* + * This is here to provide an interface to the internal wots_gen_leafx1 + * routine. While this routine is not referenced in the package outside of + * wots.c, it is called from the stand-alone benchmark code to characterize + * the performance + */ +struct leaf_info_x1 { + unsigned char *wots_sig; + uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ + uint32_t *wots_steps; + uint32_t leaf_addr[8]; + uint32_t pk_addr[8]; +}; + +/* Macro to set the leaf_info to something 'benign', that is, it would */ +/* run with the same time as it does during the real signing process */ +/* Used only by the benchmark code */ +#define INITIALIZE_LEAF_INFO_X1(info, addr, step_buffer) { \ + (info).wots_sig = 0; \ + (info).wots_sign_leaf = ~0; \ + (info).wots_steps = step_buffer; \ + memcpy( &(info).leaf_addr[0], (addr), 32 ); \ + memcpy( &(info).pk_addr[0], (addr), 32 ); \ + } + +#define wots_gen_leafx1 SPX_NAMESPACE(wots_gen_leafx1) +void wots_gen_leafx1(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info); + +#endif /* WOTSX1_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/address.c b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/address.c index 9e365ff3a0..b956e9cb29 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/address.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/address.c @@ -1,78 +1,91 @@ #include +#include #include "address.h" #include "params.h" #include "utils.h" -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]) { - int i; - - for (i = 0; i < 8; i++) { - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_ull_to_bytes( - bytes + i * 4, 4, addr[i]); - } -} - -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_set_layer_addr( - uint32_t addr[8], uint32_t layer) { - addr[0] = layer; +/* + * Specify which level of Merkle tree (the "layer") we're working on + */ +void set_layer_addr(uint32_t addr[8], uint32_t layer) { + ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; } -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_set_tree_addr( - uint32_t addr[8], uint64_t tree) { - addr[1] = 0; - addr[2] = (uint32_t) (tree >> 32); - addr[3] = (uint32_t) tree; +/* + * Specify which Merkle tree within the level (the "tree address") we're working on + */ +void set_tree_addr(uint32_t addr[8], uint64_t tree) { + ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); } -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_set_type( - uint32_t addr[8], uint32_t type) { - addr[4] = type; +/* + * Specify the reason we'll use this address structure for, that is, what + * hash will we compute with it. This is used so that unrelated types of + * hashes don't accidentally get the same address structure. The type will be + * one of the SPX_ADDR_TYPE constants + */ +void set_type(uint32_t addr[8], uint32_t type) { + ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; } -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; +/* + * Copy the layer and tree fields of the address structure. This is used + * when we're doing multiple types of hashes within the same Merkle tree + */ +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); } /* These functions are used for OTS addresses. */ -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_set_keypair_addr( - uint32_t addr[8], uint32_t keypair) { - addr[5] = keypair; +/* + * Specify which Merkle leaf we're working on; that is, which OTS keypair + * we're talking about. + */ +void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { + ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; } -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; - out[5] = in[5]; +/* + * Copy the layer, tree and keypair fields of the address structure. This is + * used when we're doing multiple things within the same OTS keypair + */ +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); + ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; } -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_set_chain_addr( - uint32_t addr[8], uint32_t chain) { - addr[6] = chain; +/* + * Specify which Merkle chain within the OTS we're working with + * (the chain address) + */ +void set_chain_addr(uint32_t addr[8], uint32_t chain) { + ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; } -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_set_hash_addr( - uint32_t addr[8], uint32_t hash) { - addr[7] = hash; +/* + * Specify where in the Merkle chain we are +* (the hash address) + */ +void set_hash_addr(uint32_t addr[8], uint32_t hash) { + ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; } /* These functions are used for all hash tree addresses (including FORS). */ -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_set_tree_height( - uint32_t addr[8], uint32_t tree_height) { - addr[6] = tree_height; +/* + * Specify the height of the node in the Merkle/FORS tree we are in + * (the tree height) + */ +void set_tree_height(uint32_t addr[8], uint32_t tree_height) { + ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; } -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_set_tree_index( - uint32_t addr[8], uint32_t tree_index) { - addr[7] = tree_index; +/* + * Specify the distance from the left edge of the node in the Merkle/FORS tree + * (the tree index) + */ +void set_tree_index(uint32_t addr[8], uint32_t tree_index) { + u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/address.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/address.h index ca0cbdeda4..24a84eb40c 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/address.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/address.h @@ -1,50 +1,52 @@ -#ifndef PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_ADDRESS_H -#define PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_ADDRESS_H +#ifndef SPX_ADDRESS_H +#define SPX_ADDRESS_H #include -#define PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_ADDR_TYPE_WOTS 0 -#define PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_ADDR_TYPE_WOTSPK 1 -#define PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_ADDR_TYPE_HASHTREE 2 -#define PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_ADDR_TYPE_FORSTREE 3 -#define PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_ADDR_TYPE_FORSPK 4 +#include "params.h" -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]); +/* The hash types that are passed to set_type */ +#define SPX_ADDR_TYPE_WOTS 0 +#define SPX_ADDR_TYPE_WOTSPK 1 +#define SPX_ADDR_TYPE_HASHTREE 2 +#define SPX_ADDR_TYPE_FORSTREE 3 +#define SPX_ADDR_TYPE_FORSPK 4 +#define SPX_ADDR_TYPE_WOTSPRF 5 +#define SPX_ADDR_TYPE_FORSPRF 6 -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_set_layer_addr( - uint32_t addr[8], uint32_t layer); +#define set_layer_addr SPX_NAMESPACE(set_layer_addr) +void set_layer_addr(uint32_t addr[8], uint32_t layer); -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_set_tree_addr( - uint32_t addr[8], uint64_t tree); +#define set_tree_addr SPX_NAMESPACE(set_tree_addr) +void set_tree_addr(uint32_t addr[8], uint64_t tree); -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_set_type( - uint32_t addr[8], uint32_t type); +#define set_type SPX_NAMESPACE(set_type) +void set_type(uint32_t addr[8], uint32_t type); /* Copies the layer and tree part of one address into the other */ -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]); +#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); /* These functions are used for WOTS and FORS addresses. */ -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_set_keypair_addr( - uint32_t addr[8], uint32_t keypair); +#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) +void set_keypair_addr(uint32_t addr[8], uint32_t keypair); -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_set_chain_addr( - uint32_t addr[8], uint32_t chain); +#define set_chain_addr SPX_NAMESPACE(set_chain_addr) +void set_chain_addr(uint32_t addr[8], uint32_t chain); -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_set_hash_addr( - uint32_t addr[8], uint32_t hash); +#define set_hash_addr SPX_NAMESPACE(set_hash_addr) +void set_hash_addr(uint32_t addr[8], uint32_t hash); -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]); +#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); /* These functions are used for all hash tree addresses (including FORS). */ -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_set_tree_height( - uint32_t addr[8], uint32_t tree_height); +#define set_tree_height SPX_NAMESPACE(set_tree_height) +void set_tree_height(uint32_t addr[8], uint32_t tree_height); -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_set_tree_index( - uint32_t addr[8], uint32_t tree_index); +#define set_tree_index SPX_NAMESPACE(set_tree_index) +void set_tree_index(uint32_t addr[8], uint32_t tree_index); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/api.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/api.h index eb2090e02e..fa22fa775b 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/api.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/api.h @@ -4,15 +4,13 @@ #include #include - - -#define PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_CRYPTO_ALGNAME "SPHINCS+" +#define PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_CRYPTO_ALGNAME "SPHINCS+-haraka-128f-simple" #define PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_CRYPTO_SECRETKEYBYTES 64 #define PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_CRYPTO_PUBLICKEYBYTES 32 -#define PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_CRYPTO_BYTES 17088 -#define PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_CRYPTO_SEEDBYTES 48 +#define PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_CRYPTO_BYTES 17088 +#define PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_CRYPTO_SEEDBYTES 48 /* * Returns the length of a secret key, in bytes @@ -39,43 +37,41 @@ size_t PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_crypto_sign_seedbytes(void); * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] * Format pk: [root || PUB_SEED] */ -int PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed); +int PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); /* * Generates a SPHINCS+ key pair. * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] * Format pk: [root || PUB_SEED] */ -int PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk); +int PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); /** * Returns an array containing a detached signature. */ -int PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk); +int PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); /** * Verifies a detached signature and message under a given public key. */ -int PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk); +int PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, + const uint8_t *pk); /** * Returns an array containing the signature followed by the message. */ -int PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk); +int PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); /** * Verifies a given signature-message pair under a given public key. */ -int PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk); - +int PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/context.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/context.h new file mode 100644 index 0000000000..f03446b9cb --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/context.h @@ -0,0 +1,22 @@ +#ifndef SPX_CONTEXT_H +#define SPX_CONTEXT_H + +#include + +#include "immintrin.h" +#include "params.h" + +typedef struct { + uint8_t pub_seed[SPX_N]; + uint8_t sk_seed[SPX_N]; + + __m128i rc[40]; +} spx_ctx; + +#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) +void initialize_hash_function(spx_ctx *ctx); + +#define free_hash_function SPX_NAMESPACE(free_hash_function) +void free_hash_function(spx_ctx *ctx); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/context_haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/context_haraka.c new file mode 100644 index 0000000000..f1cd7e3664 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/context_haraka.c @@ -0,0 +1,11 @@ +#include "context.h" +#include "haraka.h" + +void initialize_hash_function(spx_ctx *ctx) { + tweak_constants(ctx); +} + +// we don't support heap-based haraka right now +void free_hash_function(spx_ctx *ctx) { + (void)ctx; // suppress unused variable warnings +} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/fors.c b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/fors.c index a7c64f0887..f1b0639cfc 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/fors.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/fors.c @@ -2,8 +2,9 @@ #include #include -#include "address.h" #include "fors.h" + +#include "address.h" #include "hash.h" #include "hashx4.h" #include "thash.h" @@ -11,19 +12,24 @@ #include "utils.h" #include "utilsx4.h" +static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + prf_addr(sk, ctx, fors_leaf_addr); +} + static void fors_gen_skx4(unsigned char *sk0, unsigned char *sk1, unsigned char *sk2, - unsigned char *sk3, const unsigned char *sk_seed, - uint32_t fors_leaf_addrx4[4 * 8], - const hash_state *state_seeded) { - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_prf_addrx4(sk0, sk1, sk2, sk3, sk_seed, fors_leaf_addrx4, state_seeded); + unsigned char *sk3, const spx_ctx *ctx, + uint32_t fors_leaf_addrx4[4 * 8]) { + prf_addrx4(sk0, sk1, sk2, sk3, + ctx, fors_leaf_addrx4); } static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, - const unsigned char *pub_seed, - uint32_t fors_leaf_addr[8], const hash_state *state_seeded) { - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_thash_1(leaf, sk, pub_seed, fors_leaf_addr, state_seeded); + const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + thash(leaf, sk, 1, ctx, fors_leaf_addr); } static void fors_sk_to_leafx4(unsigned char *leaf0, @@ -34,57 +40,64 @@ static void fors_sk_to_leafx4(unsigned char *leaf0, const unsigned char *sk1, const unsigned char *sk2, const unsigned char *sk3, - const unsigned char *pub_seed, - uint32_t fors_leaf_addrx4[4 * 8], - const hash_state *state_seeded) { - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_thashx4_1(leaf0, leaf1, leaf2, leaf3, - sk0, sk1, sk2, sk3, pub_seed, fors_leaf_addrx4, state_seeded); + const spx_ctx *ctx, + uint32_t fors_leaf_addrx4[4 * 8]) { + thashx4(leaf0, leaf1, leaf2, leaf3, + sk0, sk1, sk2, sk3, + 1, ctx, fors_leaf_addrx4); } -static void fors_gen_leafx4(unsigned char *leaf0, - unsigned char *leaf1, - unsigned char *leaf2, - unsigned char *leaf3, - const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx0, - uint32_t addr_idx1, - uint32_t addr_idx2, - uint32_t addr_idx3, - const uint32_t fors_tree_addr[8], - const hash_state *state_seeded) { - uint32_t fors_leaf_addrx4[4 * 8] = {0}; +struct fors_gen_leaf_info { + uint32_t leaf_addrx[4 * 8]; +}; + +static void fors_gen_leafx4(unsigned char *leaf, + const spx_ctx *ctx, + uint32_t addr_idx, void *info) { + struct fors_gen_leaf_info *fors_info = info; + uint32_t *fors_leaf_addrx4 = fors_info->leaf_addrx; unsigned int j; - /* Only copy the parts that must be kept in fors_leaf_addrx4. */ + /* Only set the parts that the caller doesn't set */ for (j = 0; j < 4; j++) { - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_copy_keypair_addr(fors_leaf_addrx4 + j * 8, fors_tree_addr); - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_set_type(fors_leaf_addrx4 + j * 8, PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_ADDR_TYPE_FORSTREE); + set_tree_index(fors_leaf_addrx4 + j * 8, addr_idx + j); + set_type(fors_leaf_addrx4 + j * 8, SPX_ADDR_TYPE_FORSPRF); } - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_set_tree_index(fors_leaf_addrx4 + 0 * 8, addr_idx0); - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_set_tree_index(fors_leaf_addrx4 + 1 * 8, addr_idx1); - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_set_tree_index(fors_leaf_addrx4 + 2 * 8, addr_idx2); - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_set_tree_index(fors_leaf_addrx4 + 3 * 8, addr_idx3); + fors_gen_skx4(leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + leaf + 2 * SPX_N, + leaf + 3 * SPX_N, + ctx, fors_leaf_addrx4); + + for (j = 0; j < 4; j++) { + set_type(fors_leaf_addrx4 + j * 8, SPX_ADDR_TYPE_FORSTREE); + } - fors_gen_skx4(leaf0, leaf1, leaf2, leaf3, sk_seed, fors_leaf_addrx4, state_seeded); - fors_sk_to_leafx4(leaf0, leaf1, leaf2, leaf3, - leaf0, leaf1, leaf2, leaf3, pub_seed, fors_leaf_addrx4, state_seeded); + fors_sk_to_leafx4(leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + leaf + 2 * SPX_N, + leaf + 3 * SPX_N, + leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + leaf + 2 * SPX_N, + leaf + 3 * SPX_N, + ctx, fors_leaf_addrx4); } /** - * Interprets m as PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_FORS_HEIGHT-bit unsigned integers. - * Assumes m contains at least PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_FORS_TREES bits. - * Assumes indices has space for PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_FORS_TREES integers. + * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + * Assumes indices has space for SPX_FORS_TREES integers. */ static void message_to_indices(uint32_t *indices, const unsigned char *m) { unsigned int i, j; unsigned int offset = 0; - for (i = 0; i < PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_FORS_TREES; i++) { + for (i = 0; i < SPX_FORS_TREES; i++) { indices[i] = 0; - for (j = 0; j < PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_FORS_HEIGHT; j++) { - indices[i] ^= (((uint32_t)m[offset >> 3] >> (offset & 0x7)) & 0x1) << j; + for (j = 0; j < SPX_FORS_HEIGHT; j++) { + indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); offset++; } } @@ -92,68 +105,53 @@ static void message_to_indices(uint32_t *indices, const unsigned char *m) { /** * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_FORS_TREES bits. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. */ -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *state_seeded) { - /* Round up to multiple of 4 to prevent out-of-bounds for x4 parallelism */ - uint32_t indices[(PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_FORS_TREES + 3) & ~3] = {0}; - unsigned char roots[((PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_FORS_TREES + 3) & ~3) * PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N]; - /* Sign to a buffer, since we may not have a nice multiple of 4 and would - otherwise overrun the signature. */ - unsigned char sigbufx4[4 * PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N * (1 + PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_FORS_HEIGHT)]; - uint32_t fors_tree_addrx4[4 * 8] = {0}; +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + uint32_t fors_tree_addr[4 * 8] = {0}; + struct fors_gen_leaf_info fors_info = {0}; + uint32_t *fors_leaf_addr = fors_info.leaf_addrx; uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset[4] = {0}; - unsigned int i, j; + uint32_t idx_offset; + unsigned int i; - for (j = 0; j < 4; j++) { - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_copy_keypair_addr(fors_tree_addrx4 + j * 8, fors_addr); - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_set_type(fors_tree_addrx4 + j * 8, PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_ADDR_TYPE_FORSTREE); + for (i = 0; i < 4; i++) { + copy_keypair_addr(fors_tree_addr + 8 * i, fors_addr); + set_type(fors_tree_addr + 8 * i, SPX_ADDR_TYPE_FORSTREE); + copy_keypair_addr(fors_leaf_addr + 8 * i, fors_addr); } - - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_copy_keypair_addr(fors_pk_addr, fors_addr); - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_set_type(fors_pk_addr, PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_ADDR_TYPE_FORSPK); + copy_keypair_addr(fors_pk_addr, fors_addr); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); message_to_indices(indices, m); - for (i = 0; i < ((PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_FORS_TREES + 3) & ~0x3); i += 4) { - for (j = 0; j < 4; j++) { - if (i + j < PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_FORS_TREES) { - idx_offset[j] = (i + j) * (1 << PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_FORS_HEIGHT); + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_set_tree_height(fors_tree_addrx4 + j * 8, 0); - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_set_tree_index(fors_tree_addrx4 + j * 8, - indices[i + j] + idx_offset[j]); - } - } + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); - /* Include the secret key part that produces the selected leaf nodes. */ - fors_gen_skx4(sigbufx4 + 0 * PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N, - sigbufx4 + 1 * PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N, - sigbufx4 + 2 * PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N, - sigbufx4 + 3 * PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N, - sk_seed, fors_tree_addrx4, state_seeded); - - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_treehashx4_FORS_HEIGHT(roots + i * PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N, sigbufx4 + 4 * PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N, sk_seed, pub_seed, - &indices[i], idx_offset, fors_gen_leafx4, fors_tree_addrx4, - state_seeded); - - for (j = 0; j < 4; j++) { - if (i + j < PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_FORS_TREES) { - memcpy(sig, sigbufx4 + j * PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N, PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N); - memcpy(sig + PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N, - sigbufx4 + 4 * PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N + j * PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N * PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_FORS_HEIGHT, - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N * PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_FORS_HEIGHT); - sig += PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N * (1 + PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_FORS_HEIGHT); - } - } + /* Include the secret key part that produces the selected leaf node. */ + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); + fors_gen_sk(sig, ctx, fors_tree_addr); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + sig += SPX_N; + + /* Compute the authentication path for this leaf node. */ + treehashx4(roots + i * SPX_N, sig, ctx, + indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx4, + fors_tree_addr, &fors_info); + + sig += SPX_N * SPX_FORS_HEIGHT; } /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_thash_FORS_TREES(pk, roots, pub_seed, fors_pk_addr, state_seeded); + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); } /** @@ -161,46 +159,44 @@ void PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_fors_sign(unsigned char *sig, unsigne * This can be used for verification by comparing to a known public key, or to * subsequently verify a signature on the derived public key. The latter is the * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_FORS_TREES bits. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. */ -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, - const uint32_t fors_addr[8], - const hash_state *state_seeded) { - uint32_t indices[PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_FORS_TREES]; - unsigned char roots[PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_FORS_TREES * PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N]; - unsigned char leaf[PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N]; +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + unsigned char leaf[SPX_N]; uint32_t fors_tree_addr[8] = {0}; uint32_t fors_pk_addr[8] = {0}; uint32_t idx_offset; unsigned int i; - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_copy_keypair_addr(fors_tree_addr, fors_addr); - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_copy_keypair_addr(fors_pk_addr, fors_addr); + copy_keypair_addr(fors_tree_addr, fors_addr); + copy_keypair_addr(fors_pk_addr, fors_addr); - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_set_type(fors_tree_addr, PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_set_type(fors_pk_addr, PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_ADDR_TYPE_FORSPK); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); message_to_indices(indices, m); - for (i = 0; i < PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_FORS_TREES; i++) { - idx_offset = i * (1 << PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_FORS_HEIGHT); + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_set_tree_height(fors_tree_addr, 0); - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_set_tree_index(fors_tree_addr, indices[i] + idx_offset); + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); /* Derive the leaf from the included secret key part. */ - fors_sk_to_leaf(leaf, sig, pub_seed, fors_tree_addr, state_seeded); - sig += PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N; + fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); + sig += SPX_N; /* Derive the corresponding root node of this tree. */ - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_compute_root(roots + i * PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N, leaf, indices[i], idx_offset, - sig, PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_FORS_HEIGHT, pub_seed, fors_tree_addr, - state_seeded); - sig += PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N * PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_FORS_HEIGHT; + compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, + sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); + sig += SPX_N * SPX_FORS_HEIGHT; } /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_thash_FORS_TREES(pk, roots, pub_seed, fors_pk_addr, state_seeded); + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/fors.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/fors.h index ca4efdf428..509140a178 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/fors.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/fors.h @@ -1,32 +1,32 @@ -#ifndef PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_FORS_H -#define PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_FORS_H +#ifndef SPX_FORS_H +#define SPX_FORS_H #include -#include "hash_state.h" +#include "context.h" #include "params.h" /** * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_FORS_TREES bits. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. */ -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_fors_sign( - unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *hash_state_seeded); +#define fors_sign SPX_NAMESPACE(fors_sign) +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); /** * Derives the FORS public key from a signature. * This can be used for verification by comparing to a known public key, or to * subsequently verify a signature on the derived public key. The latter is the * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_FORS_TREES bits. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. */ -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_fors_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, const uint32_t fors_addr[8], - const hash_state *hash_state_seeded); +#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/haraka.c index 58fd053c1d..b414b691d7 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/haraka.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/haraka.c @@ -8,10 +8,12 @@ Plain C implementation of the Haraka256 and Haraka512 permutations. #include #include "haraka.h" +#include "harakax4.h" +#include "utils.h" #define HARAKAS_RATE 32 -#define u64 uint64_t +#define u64 unsigned long #define u128 __m128i #define LOAD(src) _mm_loadu_si128((u128 *)(src)) @@ -20,7 +22,7 @@ Plain C implementation of the Haraka256 and Haraka512 permutations. #define XOR128(a, b) _mm_xor_si128(a, b) #define AES2(s0, s1, rci) \ - (s0) = _mm_aesenc_si128(s0, *(rci)); \ + s0 = _mm_aesenc_si128(s0, *(rci)); \ (s1) = _mm_aesenc_si128(s1, *((rci) + 1)); \ (s0) = _mm_aesenc_si128(s0, *((rci) + 2)); \ (s1) = _mm_aesenc_si128(s1, *((rci) + 3)); @@ -32,7 +34,7 @@ Plain C implementation of the Haraka256 and Haraka512 permutations. AES2((s3)[0], (s3)[1], rci); #define AES4(s0, s1, s2, s3, rci) \ - (s0) = _mm_aesenc_si128(s0, *(rci)); \ + s0 = _mm_aesenc_si128(s0, *(rci)); \ (s1) = _mm_aesenc_si128(s1, *((rci) + 1)); \ (s2) = _mm_aesenc_si128(s2, *((rci) + 2)); \ (s3) = _mm_aesenc_si128(s3, *((rci) + 3)); \ @@ -68,17 +70,17 @@ Plain C implementation of the Haraka256 and Haraka512 permutations. _mm_storeu_si128((u128 *)((out) + 16), \ _mm_castpd_si128(_mm_shuffle_pd(_mm_castsi128_pd(s2), _mm_castsi128_pd(s3), 0))); -static void load_haraka_constants(u128 rc[40]) { - rc[ 0] = _mm_set_epi32((int)0x0684704c, (int)0xe620c00a, (int)0xb2c5fef0, (int)0x75817b9d); - rc[ 1] = _mm_set_epi32((int)0x8b66b4e1, (int)0x88f3a06b, (int)0x640f6ba4, (int)0x2f08f717); - rc[ 2] = _mm_set_epi32((int)0x3402de2d, (int)0x53f28498, (int)0xcf029d60, (int)0x9f029114); - rc[ 3] = _mm_set_epi32((int)0x0ed6eae6, (int)0x2e7b4f08, (int)0xbbf3bcaf, (int)0xfd5b4f79); - rc[ 4] = _mm_set_epi32((int)0xcbcfb0cb, (int)0x4872448b, (int)0x79eecd1c, (int)0xbe397044); - rc[ 5] = _mm_set_epi32((int)0x7eeacdee, (int)0x6e9032b7, (int)0x8d5335ed, (int)0x2b8a057b); - rc[ 6] = _mm_set_epi32((int)0x67c28f43, (int)0x5e2e7cd0, (int)0xe2412761, (int)0xda4fef1b); - rc[ 7] = _mm_set_epi32((int)0x2924d9b0, (int)0xafcacc07, (int)0x675ffde2, (int)0x1fc70b3b); - rc[ 8] = _mm_set_epi32((int)0xab4d63f1, (int)0xe6867fe9, (int)0xecdb8fca, (int)0xb9d465ee); - rc[ 9] = _mm_set_epi32((int)0x1c30bf84, (int)0xd4b7cd64, (int)0x5b2a404f, (int)0xad037e33); +static void load_haraka_constants(u128 *rc) { + rc[0] = _mm_set_epi32((int)0x0684704c, (int)0xe620c00a, (int)0xb2c5fef0, (int)0x75817b9d); + rc[1] = _mm_set_epi32((int)0x8b66b4e1, (int)0x88f3a06b, (int)0x640f6ba4, (int)0x2f08f717); + rc[2] = _mm_set_epi32((int)0x3402de2d, (int)0x53f28498, (int)0xcf029d60, (int)0x9f029114); + rc[3] = _mm_set_epi32((int)0x0ed6eae6, (int)0x2e7b4f08, (int)0xbbf3bcaf, (int)0xfd5b4f79); + rc[4] = _mm_set_epi32((int)0xcbcfb0cb, (int)0x4872448b, (int)0x79eecd1c, (int)0xbe397044); + rc[5] = _mm_set_epi32((int)0x7eeacdee, (int)0x6e9032b7, (int)0x8d5335ed, (int)0x2b8a057b); + rc[6] = _mm_set_epi32((int)0x67c28f43, (int)0x5e2e7cd0, (int)0xe2412761, (int)0xda4fef1b); + rc[7] = _mm_set_epi32((int)0x2924d9b0, (int)0xafcacc07, (int)0x675ffde2, (int)0x1fc70b3b); + rc[8] = _mm_set_epi32((int)0xab4d63f1, (int)0xe6867fe9, (int)0xecdb8fca, (int)0xb9d465ee); + rc[9] = _mm_set_epi32((int)0x1c30bf84, (int)0xd4b7cd64, (int)0x5b2a404f, (int)0xad037e33); rc[10] = _mm_set_epi32((int)0xb2cc0bb9, (int)0x941723bf, (int)0x69028b2e, (int)0x8df69800); rc[11] = _mm_set_epi32((int)0xfa0478a6, (int)0xde6f5572, (int)0x4aaa9ec8, (int)0x5c9d2d8a); rc[12] = _mm_set_epi32((int)0xdfb49f2b, (int)0x6b772a12, (int)0x0efa4f2e, (int)0x29129fd4); @@ -111,77 +113,65 @@ static void load_haraka_constants(u128 rc[40]) { rc[39] = _mm_set_epi32((int)0x756acc03, (int)0x02288288, (int)0x4ad6bdfd, (int)0xe9c59da1); } -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_tweak_constants( - harakactx *state, - const unsigned char *pk_seed, const unsigned char *sk_seed, - unsigned long long seed_length) { +void tweak_constants(spx_ctx *ctx) { int i; unsigned char buf[40 * 16]; /* Use the standard constants to generate tweaked ones. */ - load_haraka_constants(state->rc); - - /* Constants for sk.seed */ - if (sk_seed != NULL) { - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_haraka_S(buf, 40 * 16, sk_seed, seed_length, state); - /* Tweak constants with the pub_seed */ - for (i = 0; i < 40; i++) { - state->rc_sseed[i] = LOAD(buf + i * 16); - } - } + load_haraka_constants(ctx->rc); /* Constants for pk.seed */ - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_haraka_S(buf, 40 * 16, pk_seed, seed_length, state); + haraka_S(buf, 40 * 16, ctx->pub_seed, SPX_N, ctx); /* Tweak constants with the pub_seed */ for (i = 0; i < 40; i++) { - state->rc[i] = LOAD(buf + i * 16); + ctx->rc[i] = LOAD(buf + i * 16); } } -static void haraka_S_absorb(unsigned char *s, +static void haraka_S_absorb(unsigned char *s, unsigned int r, const unsigned char *m, unsigned long long mlen, - unsigned char p, - const harakactx *state) { + unsigned char p, const spx_ctx *ctx) { unsigned long long i; - unsigned char t[HARAKAS_RATE]; + PQCLEAN_VLA(unsigned char, t, r); - while (mlen >= HARAKAS_RATE) { + while (mlen >= r) { // XOR block to state STORE(s, XOR128(LOAD(s), LOAD(m))); STORE(s + 16, XOR128(LOAD(s + 16), LOAD(m + 16))); - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_haraka512_perm(s, s, state); - mlen -= HARAKAS_RATE; - m += HARAKAS_RATE; + haraka512_perm(s, s, ctx); + mlen -= r; + m += r; } - for (i = 0; i < HARAKAS_RATE; ++i) { + for (i = 0; i < r; ++i) { t[i] = 0; } for (i = 0; i < mlen; ++i) { t[i] = m[i]; } t[i] = p; - t[HARAKAS_RATE - 1] |= 128; + t[r - 1] |= 128; STORE(s, XOR128(LOAD(s), LOAD(t))); STORE(s + 16, XOR128(LOAD(s + 16), LOAD(t + 16))); } static void haraka_S_absorb4x(unsigned char *s, + unsigned int r, const unsigned char *m0, const unsigned char *m1, const unsigned char *m2, const unsigned char *m3, unsigned long long int mlen, unsigned char p, - const harakactx *state) { + const spx_ctx *ctx) { unsigned long long i; - unsigned char t0[HARAKAS_RATE]; - unsigned char t1[HARAKAS_RATE]; - unsigned char t2[HARAKAS_RATE]; - unsigned char t3[HARAKAS_RATE]; + PQCLEAN_VLA(unsigned char, t0, r); + PQCLEAN_VLA(unsigned char, t1, r); + PQCLEAN_VLA(unsigned char, t2, r); + PQCLEAN_VLA(unsigned char, t3, r); - while (mlen >= HARAKAS_RATE) { + while (mlen >= r) { // XOR block to state STORE(s, XOR128(LOAD(s), LOAD(m0))); STORE(s + 16, XOR128(LOAD(s + 16), LOAD(m0 + 16))); @@ -192,15 +182,15 @@ static void haraka_S_absorb4x(unsigned char *s, STORE(s + 192, XOR128(LOAD(s + 192), LOAD(m3))); STORE(s + 208, XOR128(LOAD(s + 208), LOAD(m3 + 16))); - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_haraka512_perm_x4(s, s, state); - mlen -= HARAKAS_RATE; - m0 += HARAKAS_RATE; - m1 += HARAKAS_RATE; - m2 += HARAKAS_RATE; - m3 += HARAKAS_RATE; + haraka512_perm_x4(s, s, ctx); + mlen -= r; + m0 += r; + m1 += r; + m2 += r; + m3 += r; } - for (i = 0; i < HARAKAS_RATE; ++i) { + for (i = 0; i < r; ++i) { t0[i] = 0; t1[i] = 0; t2[i] = 0; @@ -218,10 +208,10 @@ static void haraka_S_absorb4x(unsigned char *s, t2[i] = p; t3[i] = p; - t0[HARAKAS_RATE - 1] |= 128; - t1[HARAKAS_RATE - 1] |= 128; - t2[HARAKAS_RATE - 1] |= 128; - t3[HARAKAS_RATE - 1] |= 128; + t0[r - 1] |= 128; + t1[r - 1] |= 128; + t2[r - 1] |= 128; + t3[r - 1] |= 128; STORE(s, XOR128(LOAD(s), LOAD(t0))); STORE(s + 16, XOR128(LOAD(s + 16), LOAD(t0 + 16))); @@ -234,9 +224,10 @@ static void haraka_S_absorb4x(unsigned char *s, } static void haraka_S_squeezeblocks(unsigned char *h, unsigned long long nblocks, - unsigned char *s, unsigned int r, const harakactx *state) { + unsigned char *s, unsigned int r, + const spx_ctx *ctx) { while (nblocks > 0) { - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_haraka512_perm(s, s, state); + haraka512_perm(s, s, ctx); STORE(h, LOAD(s)); STORE(h + 16, LOAD(s + 16)); h += r; @@ -251,9 +242,9 @@ static void haraka_S_squeezeblocks4x(unsigned char *h0, unsigned long long nblocks, unsigned char *s, unsigned int r, - const harakactx *state) { + const spx_ctx *ctx) { while (nblocks > 0) { - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_haraka512_perm_x4(s, s, state); + haraka512_perm_x4(s, s, ctx); STORE(h0, LOAD(s)); STORE(h0 + 16, LOAD(s + 16)); STORE(h1, LOAD(s + 64)); @@ -270,7 +261,7 @@ static void haraka_S_squeezeblocks4x(unsigned char *h0, } } -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_haraka_S_inc_init(uint8_t *s_inc) { +void haraka_S_inc_init(uint8_t *s_inc) { size_t i; for (i = 0; i < 64; i++) { @@ -279,7 +270,8 @@ void PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_haraka_S_inc_init(uint8_t *s_inc) { s_inc[64] = 0; } -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, const harakactx *state) { +void haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, + const spx_ctx *ctx) { size_t i; /* Recall that s_inc[64] is the non-absorbed bytes xored into the state */ @@ -293,16 +285,16 @@ void PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_haraka_S_inc_absorb(uint8_t *s_inc, c m += HARAKAS_RATE - s_inc[64]; s_inc[64] = 0; - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_haraka512_perm(s_inc, s_inc, state); + haraka512_perm(s_inc, s_inc, ctx); } for (i = 0; i < mlen; i++) { s_inc[s_inc[64] + i] ^= m[i]; } - s_inc[64] = (uint8_t)(s_inc[64] + mlen); + s_inc[64] += (uint8_t)mlen; } -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_haraka_S_inc_finalize(uint8_t *s_inc) { +void haraka_S_inc_finalize(uint8_t *s_inc) { /* After haraka_S_inc_absorb, we are guaranteed that s_inc[64] < HARAKAS_RATE, so we can always use one more byte for p in the current state. */ s_inc[s_inc[64]] ^= 0x1F; @@ -310,22 +302,23 @@ void PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_haraka_S_inc_finalize(uint8_t *s_inc) s_inc[64] = 0; } -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, const harakactx *state) { +void haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, + const spx_ctx *ctx) { size_t i; /* First consume any bytes we still have sitting around */ for (i = 0; i < outlen && i < s_inc[64]; i++) { /* There are s_inc[64] bytes left, so r - s_inc[64] is the first available byte. We consume from there, i.e., up to r. */ - out[i] = (uint8_t)s_inc[(HARAKAS_RATE - s_inc[64] + (uint8_t)i)]; + out[i] = (uint8_t)s_inc[(HARAKAS_RATE - s_inc[64] + i)]; } out += i; outlen -= i; - s_inc[64] = (uint8_t)(s_inc[64] - i); + s_inc[64] -= (uint8_t)i; /* Then squeeze the remaining necessary blocks */ while (outlen > 0) { - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_haraka512_perm(s_inc, s_inc, state); + haraka512_perm(s_inc, s_inc, ctx); for (i = 0; i < outlen && i < HARAKAS_RATE; i++) { out[i] = s_inc[i]; @@ -336,8 +329,9 @@ void PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_haraka_S_inc_squeeze(uint8_t *out, si } } -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_haraka_S(unsigned char *out, unsigned long long outlen, - const unsigned char *in, unsigned long long inlen, const harakactx *state) { +void haraka_S(unsigned char *out, unsigned long long outlen, + const unsigned char *in, unsigned long long inlen, + const spx_ctx *ctx) { unsigned long long i; unsigned char s[64]; unsigned char d[32]; @@ -345,30 +339,30 @@ void PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_haraka_S(unsigned char *out, unsigned for (i = 0; i < 64; i++) { s[i] = 0; } - haraka_S_absorb(s, in, inlen, 0x1F, state); + haraka_S_absorb(s, HARAKAS_RATE, in, inlen, 0x1F, ctx); - haraka_S_squeezeblocks(out, outlen / HARAKAS_RATE, s, HARAKAS_RATE, state); + haraka_S_squeezeblocks(out, outlen / HARAKAS_RATE, s, HARAKAS_RATE, ctx); out += (outlen / HARAKAS_RATE) * HARAKAS_RATE; if (outlen % HARAKAS_RATE) { - haraka_S_squeezeblocks(d, 1, s, HARAKAS_RATE, state); + haraka_S_squeezeblocks(d, 1, s, HARAKAS_RATE, ctx); for (i = 0; i < outlen % HARAKAS_RATE; i++) { out[i] = d[i]; } } } -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_haraka_Sx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned long long outlen, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - unsigned long long inlen, - const harakactx *state) { +void haraka_Sx4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned long long outlen, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + unsigned long long inlen, + const spx_ctx *ctx) { unsigned long long i; unsigned char s[64 * 4]; unsigned char d0[32]; @@ -379,16 +373,17 @@ void PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_haraka_Sx4(unsigned char *out0, for (i = 0; i < 64 * 4; i++) { s[i] = 0; } - haraka_S_absorb4x(s, in0, in1, in2, in3, inlen, 0x1F, state); + haraka_S_absorb4x(s, HARAKAS_RATE, in0, in1, in2, in3, inlen, 0x1F, ctx); - haraka_S_squeezeblocks4x(out0, out1, out2, out3, outlen / HARAKAS_RATE, s, HARAKAS_RATE, state); + haraka_S_squeezeblocks4x(out0, out1, out2, out3, outlen / HARAKAS_RATE, s, + HARAKAS_RATE, ctx); out0 += (outlen / HARAKAS_RATE) * HARAKAS_RATE; out1 += (outlen / HARAKAS_RATE) * HARAKAS_RATE; out2 += (outlen / HARAKAS_RATE) * HARAKAS_RATE; out3 += (outlen / HARAKAS_RATE) * HARAKAS_RATE; if (outlen % HARAKAS_RATE) { - haraka_S_squeezeblocks4x(d0, d1, d2, d3, 1, s, HARAKAS_RATE, state); + haraka_S_squeezeblocks4x(d0, d1, d2, d3, 1, s, HARAKAS_RATE, ctx); for (i = 0; i < outlen % HARAKAS_RATE; i++) { out0[i] = d0[i]; out1[i] = d1[i]; @@ -398,7 +393,8 @@ void PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_haraka_Sx4(unsigned char *out0, } } -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_haraka512_perm(unsigned char *out, const unsigned char *in, const harakactx *state) { +void haraka512_perm(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx) { u128 s[4], tmp; s[0] = LOAD(in); @@ -406,19 +402,19 @@ void PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_haraka512_perm(unsigned char *out, co s[2] = LOAD(in + 32); s[3] = LOAD(in + 48); - AES4(s[0], s[1], s[2], s[3], state->rc); + AES4(s[0], s[1], s[2], s[3], ctx->rc); MIX4(s[0], s[1], s[2], s[3]); - AES4(s[0], s[1], s[2], s[3], state->rc + 8); + AES4(s[0], s[1], s[2], s[3], ctx->rc + 8); MIX4(s[0], s[1], s[2], s[3]); - AES4(s[0], s[1], s[2], s[3], state->rc + 16); + AES4(s[0], s[1], s[2], s[3], ctx->rc + 16); MIX4(s[0], s[1], s[2], s[3]); - AES4(s[0], s[1], s[2], s[3], state->rc + 24); + AES4(s[0], s[1], s[2], s[3], ctx->rc + 24); MIX4(s[0], s[1], s[2], s[3]); - AES4(s[0], s[1], s[2], s[3], state->rc + 32); + AES4(s[0], s[1], s[2], s[3], ctx->rc + 32); MIX4(s[0], s[1], s[2], s[3]); STORE(out, s[0]); @@ -427,7 +423,8 @@ void PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_haraka512_perm(unsigned char *out, co STORE(out + 48, s[3]); } -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_haraka512_perm_x4(unsigned char *out, const unsigned char *in, const harakactx *state) { +void haraka512_perm_x4(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx) { u128 s[4][4], tmp; s[0][0] = LOAD(in); @@ -447,31 +444,31 @@ void PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_haraka512_perm_x4(unsigned char *out, s[3][2] = LOAD(in + 224); s[3][3] = LOAD(in + 240); - AES4_4x(s[0], s[1], s[2], s[3], state->rc); + AES4_4x(s[0], s[1], s[2], s[3], ctx->rc); MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - AES4_4x(s[0], s[1], s[2], s[3], state->rc + 8); + AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 8); MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - AES4_4x(s[0], s[1], s[2], s[3], state->rc + 16); + AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 16); MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - AES4_4x(s[0], s[1], s[2], s[3], state->rc + 24); + AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 24); MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - AES4_4x(s[0], s[1], s[2], s[3], state->rc + 32); + AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 32); MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); @@ -495,7 +492,8 @@ void PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_haraka512_perm_x4(unsigned char *out, STORE(out + 240, s[3][3]); } -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_haraka512(unsigned char *out, const unsigned char *in, const harakactx *state) { +void haraka512(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx) { u128 s[4], tmp; s[0] = LOAD(in); @@ -503,19 +501,19 @@ void PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_haraka512(unsigned char *out, const u s[2] = LOAD(in + 32); s[3] = LOAD(in + 48); - AES4(s[0], s[1], s[2], s[3], state->rc); + AES4(s[0], s[1], s[2], s[3], ctx->rc); MIX4(s[0], s[1], s[2], s[3]); - AES4(s[0], s[1], s[2], s[3], state->rc + 8); + AES4(s[0], s[1], s[2], s[3], ctx->rc + 8); MIX4(s[0], s[1], s[2], s[3]); - AES4(s[0], s[1], s[2], s[3], state->rc + 16); + AES4(s[0], s[1], s[2], s[3], ctx->rc + 16); MIX4(s[0], s[1], s[2], s[3]); - AES4(s[0], s[1], s[2], s[3], state->rc + 24); + AES4(s[0], s[1], s[2], s[3], ctx->rc + 24); MIX4(s[0], s[1], s[2], s[3]); - AES4(s[0], s[1], s[2], s[3], state->rc + 32); + AES4(s[0], s[1], s[2], s[3], ctx->rc + 32); MIX4(s[0], s[1], s[2], s[3]); s[0] = XOR128(s[0], LOAD(in)); @@ -527,7 +525,8 @@ void PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_haraka512(unsigned char *out, const u TRUNCSTORE(out, s[0], s[1], s[2], s[3]); } -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_haraka512x4(unsigned char *out, const unsigned char *in, const harakactx *state) { +void haraka512x4(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx) { u128 s[4][4], tmp; s[0][0] = LOAD(in); @@ -547,31 +546,31 @@ void PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_haraka512x4(unsigned char *out, const s[3][2] = LOAD(in + 224); s[3][3] = LOAD(in + 240); - AES4_4x(s[0], s[1], s[2], s[3], state->rc); + AES4_4x(s[0], s[1], s[2], s[3], ctx->rc); MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - AES4_4x(s[0], s[1], s[2], s[3], state->rc + 8); + AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 8); MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - AES4_4x(s[0], s[1], s[2], s[3], state->rc + 16); + AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 16); MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - AES4_4x(s[0], s[1], s[2], s[3], state->rc + 24); + AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 24); MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - AES4_4x(s[0], s[1], s[2], s[3], state->rc + 32); + AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 32); MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); @@ -600,25 +599,26 @@ void PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_haraka512x4(unsigned char *out, const TRUNCSTORE((out + 96), s[3][0], s[3][1], s[3][2], s[3][3]); } -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_haraka256(unsigned char *out, const unsigned char *in, const harakactx *state) { +void haraka256(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx) { u128 s[2], tmp; s[0] = LOAD(in); s[1] = LOAD(in + 16); - AES2(s[0], s[1], state->rc); + AES2(s[0], s[1], ctx->rc); MIX2(s[0], s[1]); - AES2(s[0], s[1], state->rc + 4); + AES2(s[0], s[1], ctx->rc + 4); MIX2(s[0], s[1]); - AES2(s[0], s[1], state->rc + 8); + AES2(s[0], s[1], ctx->rc + 8); MIX2(s[0], s[1]); - AES2(s[0], s[1], state->rc + 12); + AES2(s[0], s[1], ctx->rc + 12); MIX2(s[0], s[1]); - AES2(s[0], s[1], state->rc + 16); + AES2(s[0], s[1], ctx->rc + 16); MIX2(s[0], s[1]); s[0] = XOR128(s[0], LOAD(in)); @@ -628,7 +628,8 @@ void PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_haraka256(unsigned char *out, const u STORE(out + 16, s[1]); } -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_haraka256x4(unsigned char *out, const unsigned char *in, const harakactx *state) { +void haraka256x4(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx) { u128 s[4][2], tmp; s[0][0] = LOAD(in); @@ -641,7 +642,7 @@ void PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_haraka256x4(unsigned char *out, const s[3][1] = LOAD(in + 112); // Round 1 - AES2_4x(s[0], s[1], s[2], s[3], state->rc); + AES2_4x(s[0], s[1], s[2], s[3], ctx->rc); MIX2(s[0][0], s[0][1]); MIX2(s[1][0], s[1][1]); @@ -649,7 +650,7 @@ void PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_haraka256x4(unsigned char *out, const MIX2(s[3][0], s[3][1]); // Round 2 - AES2_4x(s[0], s[1], s[2], s[3], state->rc + 4); + AES2_4x(s[0], s[1], s[2], s[3], ctx->rc + 4); MIX2(s[0][0], s[0][1]); MIX2(s[1][0], s[1][1]); @@ -657,7 +658,7 @@ void PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_haraka256x4(unsigned char *out, const MIX2(s[3][0], s[3][1]); // Round 3 - AES2_4x(s[0], s[1], s[2], s[3], state->rc + 8); + AES2_4x(s[0], s[1], s[2], s[3], ctx->rc + 8); MIX2(s[0][0], s[0][1]); MIX2(s[1][0], s[1][1]); @@ -665,7 +666,7 @@ void PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_haraka256x4(unsigned char *out, const MIX2(s[3][0], s[3][1]); // Round 4 - AES2_4x(s[0], s[1], s[2], s[3], state->rc + 12); + AES2_4x(s[0], s[1], s[2], s[3], ctx->rc + 12); MIX2(s[0][0], s[0][1]); MIX2(s[1][0], s[1][1]); @@ -673,7 +674,7 @@ void PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_haraka256x4(unsigned char *out, const MIX2(s[3][0], s[3][1]); // Round 5 - AES2_4x(s[0], s[1], s[2], s[3], state->rc + 16); + AES2_4x(s[0], s[1], s[2], s[3], ctx->rc + 16); MIX2(s[0][0], s[0][1]); MIX2(s[1][0], s[1][1]); @@ -699,103 +700,3 @@ void PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_haraka256x4(unsigned char *out, const STORE(out + 96, s[3][0]); STORE(out + 112, s[3][1]); } - -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_haraka256_sk(unsigned char *out, const unsigned char *in, const harakactx *state) { - u128 s[2], tmp; - - s[0] = LOAD(in); - s[1] = LOAD(in + 16); - - AES2(s[0], s[1], state->rc_sseed); - MIX2(s[0], s[1]); - - AES2(s[0], s[1], state->rc_sseed + 4); - MIX2(s[0], s[1]); - - AES2(s[0], s[1], state->rc_sseed + 8); - MIX2(s[0], s[1]); - - AES2(s[0], s[1], state->rc_sseed + 12); - MIX2(s[0], s[1]); - - AES2(s[0], s[1], state->rc_sseed + 16); - MIX2(s[0], s[1]); - - s[0] = XOR128(s[0], LOAD(in)); - s[1] = XOR128(s[1], LOAD(in + 16)); - - STORE(out, s[0]); - STORE(out + 16, s[1]); -} - -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_haraka256_skx4(unsigned char *out, const unsigned char *in, const harakactx *state) { - u128 s[4][2], tmp; - - s[0][0] = LOAD(in); - s[0][1] = LOAD(in + 16); - s[1][0] = LOAD(in + 32); - s[1][1] = LOAD(in + 48); - s[2][0] = LOAD(in + 64); - s[2][1] = LOAD(in + 80); - s[3][0] = LOAD(in + 96); - s[3][1] = LOAD(in + 112); - - // Round 1 - AES2_4x(s[0], s[1], s[2], s[3], state->rc_sseed); - - MIX2(s[0][0], s[0][1]); - MIX2(s[1][0], s[1][1]); - MIX2(s[2][0], s[2][1]); - MIX2(s[3][0], s[3][1]); - - // Round 2 - AES2_4x(s[0], s[1], s[2], s[3], state->rc_sseed + 4); - - MIX2(s[0][0], s[0][1]); - MIX2(s[1][0], s[1][1]); - MIX2(s[2][0], s[2][1]); - MIX2(s[3][0], s[3][1]); - - // Round 3 - AES2_4x(s[0], s[1], s[2], s[3], state->rc_sseed + 8); - - MIX2(s[0][0], s[0][1]); - MIX2(s[1][0], s[1][1]); - MIX2(s[2][0], s[2][1]); - MIX2(s[3][0], s[3][1]); - - // Round 4 - AES2_4x(s[0], s[1], s[2], s[3], state->rc_sseed + 12); - - MIX2(s[0][0], s[0][1]); - MIX2(s[1][0], s[1][1]); - MIX2(s[2][0], s[2][1]); - MIX2(s[3][0], s[3][1]); - - // Round 5 - AES2_4x(s[0], s[1], s[2], s[3], state->rc_sseed + 16); - - MIX2(s[0][0], s[0][1]); - MIX2(s[1][0], s[1][1]); - MIX2(s[2][0], s[2][1]); - MIX2(s[3][0], s[3][1]); - - // Feed Forward - s[0][0] = XOR128(s[0][0], LOAD(in)); - s[0][1] = XOR128(s[0][1], LOAD(in + 16)); - s[1][0] = XOR128(s[1][0], LOAD(in + 32)); - s[1][1] = XOR128(s[1][1], LOAD(in + 48)); - s[2][0] = XOR128(s[2][0], LOAD(in + 64)); - s[2][1] = XOR128(s[2][1], LOAD(in + 80)); - s[3][0] = XOR128(s[3][0], LOAD(in + 96)); - s[3][1] = XOR128(s[3][1], LOAD(in + 112)); - - STORE(out, s[0][0]); - STORE(out + 16, s[0][1]); - STORE(out + 32, s[1][0]); - STORE(out + 48, s[1][1]); - STORE(out + 64, s[2][0]); - STORE(out + 80, s[2][1]); - STORE(out + 96, s[3][0]); - STORE(out + 112, s[3][1]); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/haraka.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/haraka.h index 501adc1c21..737cb6065f 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/haraka.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/haraka.h @@ -1,57 +1,42 @@ -#ifndef PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_HARAKA_H -#define PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_HARAKA_H +#ifndef SPX_HARAKA_H +#define SPX_HARAKA_H -#include -#include -#include - -typedef struct { - __m128i rc[40]; - __m128i rc_sseed[40]; -} harakactx; +#include "context.h" +#include "params.h" /* Tweak constants with seed */ -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_tweak_constants( - harakactx *state, - const unsigned char *pk_seed, const unsigned char *sk_seed, - unsigned long long seed_length); +#define tweak_constants SPX_NAMESPACE(tweak_constants) +void tweak_constants(spx_ctx *ctx); /* Haraka Sponge */ -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_haraka_S_inc_init(uint8_t *s_inc); -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, const harakactx *state); -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_haraka_S_inc_finalize(uint8_t *s_inc); -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, const harakactx *state); -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_haraka_S( - unsigned char *out, unsigned long long outlen, - const unsigned char *in, unsigned long long inlen, const harakactx *state); -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_haraka_Sx4( - unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned long long outlen, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - unsigned long long inlen, - const harakactx *state); - +#define haraka_S_inc_init SPX_NAMESPACE(haraka_S_inc_init) +void haraka_S_inc_init(uint8_t *s_inc); +#define haraka_S_inc_absorb SPX_NAMESPACE(haraka_S_inc_absorb) +void haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, + const spx_ctx *ctx); +#define haraka_S_inc_finalize SPX_NAMESPACE(haraka_S_inc_finalize) +void haraka_S_inc_finalize(uint8_t *s_inc); +#define haraka_S_inc_squeeze SPX_NAMESPACE(haraka_S_inc_squeeze) +void haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, + const spx_ctx *ctx); +#define haraka_S SPX_NAMESPACE(haraka_S) +void haraka_S(unsigned char *out, unsigned long long outlen, + const unsigned char *in, unsigned long long inlen, + const spx_ctx *ctx); /* Applies the 512-bit Haraka permutation to in. */ -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_haraka512_perm(unsigned char *out, const unsigned char *in, const harakactx *state); -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_haraka512_perm_x4(unsigned char *out, const unsigned char *in, const harakactx *state); +#define haraka512_perm SPX_NAMESPACE(haraka512_perm) +void haraka512_perm(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx); /* Implementation of Haraka-512 */ -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_haraka512(unsigned char *out, const unsigned char *in, const harakactx *state); -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_haraka512x4(unsigned char *out, const unsigned char *in, const harakactx *state); +#define haraka512 SPX_NAMESPACE(haraka512) +void haraka512(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx); /* Implementation of Haraka-256 */ -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_haraka256(unsigned char *out, const unsigned char *in, const harakactx *state); -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_haraka256x4(unsigned char *out, const unsigned char *in, const harakactx *state); - -/* Implementation of Haraka-256 using sk.seed constants */ -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_haraka256_sk(unsigned char *out, const unsigned char *in, const harakactx *state); -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_haraka256_skx4(unsigned char *out, const unsigned char *in, const harakactx *state); +#define haraka256 SPX_NAMESPACE(haraka256) +void haraka256(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/haraka_offsets.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/haraka_offsets.h new file mode 100644 index 0000000000..7c062272a0 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/haraka_offsets.h @@ -0,0 +1,21 @@ +#ifndef HARAKA_OFFSETS_H_ +#define HARAKA_OFFSETS_H_ + +/* + * Offsets of various fields in the address structure when we use Haraka as + * the Sphincs+ hash function + */ + +#define SPX_OFFSET_LAYER 3 /* The byte used to specify the Merkle tree layer */ +#define SPX_OFFSET_TREE 8 /* The start of the 8 byte field used to specify the tree */ +#define SPX_OFFSET_TYPE 19 /* The byte used to specify the hash type (reason) */ +#define SPX_OFFSET_KP_ADDR2 22 /* The high byte used to specify the key pair (which one-time signature) */ +#define SPX_OFFSET_KP_ADDR1 23 /* The low byte used to specify the key pair */ +#define SPX_OFFSET_CHAIN_ADDR 27 /* The byte used to specify the chain address (which Winternitz chain) */ +#define SPX_OFFSET_HASH_ADDR 31 /* The byte used to specify the hash address (where in the Winternitz chain) */ +#define SPX_OFFSET_TREE_HGT 27 /* The byte used to specify the height of this node in the FORS or Merkle tree */ +#define SPX_OFFSET_TREE_INDEX 28 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ + +#define SPX_HARAKA 1 + +#endif /* HARAKA_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/harakax4.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/harakax4.h new file mode 100644 index 0000000000..eadc69aa48 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/harakax4.h @@ -0,0 +1,36 @@ +#ifndef SPX_HARAKAX4_H +#define SPX_HARAKAX4_H + +#include "context.h" +#include "params.h" + +/* Haraka Sponge */ +#define haraka_Sx4 SPX_NAMESPACE(haraka_Sx4) +void haraka_Sx4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned long long outlen, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + unsigned long long inlen, + const spx_ctx *ctx); + +/* Applies the 512-bit Haraka permutation x4 to in. */ +#define haraka512_perm_x4 SPX_NAMESPACE(haraka512_perm_x4) +void haraka512_perm_x4(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx); + +/* Implementation of Haraka-512 x4*/ +#define haraka512x4 SPX_NAMESPACE(haraka512x4) +void haraka512x4(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx); + +/* Implementation of Haraka-256 x4 */ +#define haraka256x4 SPX_NAMESPACE(haraka256x4) +void haraka256x4(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/hash.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/hash.h index 58b3e24006..f7c87d4c3c 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/hash.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/hash.h @@ -1,31 +1,28 @@ -#ifndef PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_HASH_H -#define PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_HASH_H - -#include "hash_state.h" +#ifndef SPX_HASH_H +#define SPX_HASH_H #include #include -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_initialize_hash_function( - hash_state *hash_state_seeded, - const unsigned char *pub_seed, const unsigned char *sk_seed); +#include "context.h" +#include "params.h" + +#define prf_addr SPX_NAMESPACE(prf_addr) +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]); -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_destroy_hash_function(hash_state *hash_state_seeded); +#define gen_message_random SPX_NAMESPACE(gen_message_random) +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded); +#define hash_message SPX_NAMESPACE(hash_message) +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/hash_haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/hash_haraka.c index f568a97e37..750a67423b 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/hash_haraka.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/hash_haraka.c @@ -2,58 +2,44 @@ #include #include "address.h" -#include "haraka.h" -#include "hash.h" #include "params.h" #include "utils.h" -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_initialize_hash_function( - hash_state *hash_state_seeded, - const unsigned char *pub_seed, const unsigned char *sk_seed) { - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_tweak_constants(hash_state_seeded, pub_seed, sk_seed, PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N); -} - -/* The haraka implementation is stack based and won't be replaced in PQClean/OQS, - so we don't need to do anything */ -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_destroy_hash_function( - hash_state *hash_state_seeded) { // NOLINT(readability-non-const-parameter) - (void)hash_state_seeded; -} +#include "haraka.h" +#include "hash.h" /* - * Computes PRF(key, addr), given a secret key of PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N bytes and an address + * Computes PRF(key, addr), given a secret key of SPX_N bytes and an address */ -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded) { - unsigned char buf[PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_ADDR_BYTES]; - /* Since PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N may be smaller than 32, we need a temporary buffer. */ +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]) { + /* Since SPX_N may be smaller than 32, we need temporary buffers. */ unsigned char outbuf[32]; + unsigned char buf[64] = {0}; - (void)key; /* Suppress an 'unused parameter' warning. */ + memcpy(buf, addr, SPX_ADDR_BYTES); + memcpy(buf + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_addr_to_bytes(buf, addr); - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_haraka256_sk(outbuf, buf, hash_state_seeded); - memcpy(out, outbuf, PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N); + haraka512(outbuf, (const void *)buf, ctx); + memcpy(out, outbuf, SPX_N); } /** * Computes the message-dependent randomness R, using a secret seed and an * optional randomization value as well as the message. */ -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded) { +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { uint8_t s_inc[65]; - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_haraka_S_inc_init(s_inc); - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_haraka_S_inc_absorb(s_inc, sk_prf, PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_haraka_S_inc_absorb(s_inc, optrand, PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_haraka_S_inc_absorb(s_inc, m, mlen, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_haraka_S_inc_finalize(s_inc); - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_haraka_S_inc_squeeze(R, PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N, s_inc, hash_state_seeded); + haraka_S_inc_init(s_inc); + haraka_S_inc_absorb(s_inc, sk_prf, SPX_N, ctx); + haraka_S_inc_absorb(s_inc, optrand, SPX_N, ctx); + haraka_S_inc_absorb(s_inc, m, mlen, ctx); + haraka_S_inc_finalize(s_inc); + haraka_S_inc_squeeze(R, SPX_N, s_inc, ctx); } /** @@ -61,36 +47,35 @@ void PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_gen_message_random( * Outputs the message digest and the index of the leaf. The index is split in * the tree index and the leaf index, for convenient copying to an address. */ -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded) { -#define PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_TREE_BITS (PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_TREE_HEIGHT * (PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_D - 1)) -#define PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_TREE_BYTES ((PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_TREE_BITS + 7) / 8) -#define PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_LEAF_BITS PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_TREE_HEIGHT -#define PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_LEAF_BYTES ((PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_LEAF_BITS + 7) / 8) -#define PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_DGST_BYTES (PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_FORS_MSG_BYTES + PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_TREE_BYTES + PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_LEAF_BYTES) +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { +#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) +#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) +#define SPX_LEAF_BITS SPX_TREE_HEIGHT +#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) +#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) - unsigned char buf[PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_DGST_BYTES]; + unsigned char buf[SPX_DGST_BYTES]; unsigned char *bufp = buf; uint8_t s_inc[65]; - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_haraka_S_inc_init(s_inc); - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_haraka_S_inc_absorb(s_inc, R, PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_haraka_S_inc_absorb(s_inc, pk + PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N, PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_haraka_S_inc_absorb(s_inc, m, mlen, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_haraka_S_inc_finalize(s_inc); - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_haraka_S_inc_squeeze(buf, PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_DGST_BYTES, s_inc, hash_state_seeded); + haraka_S_inc_init(s_inc); + haraka_S_inc_absorb(s_inc, R, SPX_N, ctx); + haraka_S_inc_absorb(s_inc, pk + SPX_N, SPX_N, ctx); // Only absorb root part of pk + haraka_S_inc_absorb(s_inc, m, mlen, ctx); + haraka_S_inc_finalize(s_inc); + haraka_S_inc_squeeze(buf, SPX_DGST_BYTES, s_inc, ctx); + + memcpy(digest, bufp, SPX_FORS_MSG_BYTES); + bufp += SPX_FORS_MSG_BYTES; - memcpy(digest, bufp, PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_FORS_MSG_BYTES); - bufp += PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_FORS_MSG_BYTES; - *tree = PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_bytes_to_ull(bufp, PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_TREE_BYTES); - *tree &= (~(uint64_t)0) >> (64 - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_TREE_BITS); - bufp += PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_TREE_BYTES; + *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); + *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); + bufp += SPX_TREE_BYTES; - *leaf_idx = (uint32_t)PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_bytes_to_ull( - bufp, PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_LEAF_BYTES); - *leaf_idx &= (~(uint32_t)0) >> (32 - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_LEAF_BITS); + *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); + *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/hash_harakax4.c b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/hash_harakax4.c index 54befaf5e4..cfa5162d79 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/hash_harakax4.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/hash_harakax4.c @@ -2,36 +2,34 @@ #include #include "address.h" -#include "haraka.h" -#include "hash_state.h" +#include "harakax4.h" #include "hashx4.h" #include "params.h" /* * 4-way parallel version of prf_addr; takes 4x as much input and output */ -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_prf_addrx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const unsigned char *key, - const uint32_t addrx4[4 * 8], - const hash_state *state_seeded) { - unsigned char bufx4[4 * PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_ADDR_BYTES]; - /* Since PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N may be smaller than 32, we need a temporary buffer. */ +#define prf_addrx4 SPX_NAMESPACE(prf_addrx4) +void prf_addrx4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const spx_ctx *ctx, + const uint32_t addrx4[4 * 8]) { + unsigned char bufx4[4 * 64] = {0}; + /* Since SPX_N may be smaller than 32, we need temporary buffers. */ unsigned char outbuf[4 * 32]; unsigned int i; - (void)key; /* Suppress an 'unused parameter' warning. */ - for (i = 0; i < 4; i++) { - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_addr_to_bytes(bufx4 + i * PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_ADDR_BYTES, addrx4 + i * 8); + memcpy(bufx4 + i * 64, addrx4 + i * 8, SPX_ADDR_BYTES); + memcpy(bufx4 + i * 64 + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); } - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_haraka256_skx4(outbuf, bufx4, state_seeded); + haraka512x4(outbuf, bufx4, ctx); - memcpy(out0, outbuf, PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N); - memcpy(out1, outbuf + 32, PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N); - memcpy(out2, outbuf + 64, PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N); - memcpy(out3, outbuf + 96, PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N); + memcpy(out0, outbuf, SPX_N); + memcpy(out1, outbuf + 32, SPX_N); + memcpy(out2, outbuf + 64, SPX_N); + memcpy(out3, outbuf + 96, SPX_N); } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/hash_state.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/hash_state.h deleted file mode 100644 index cf3aca0811..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/hash_state.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_HASH_STATE_H -#define PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_HASH_STATE_H - -/** - * Defines the type of the hash function state. - * - * Don't be fooled into thinking this instance of SPHINCS+ isn't stateless! - * - * From Section 7.2.2 from the SPHINCS+ round-2 specification: - * - * Each of the instances of the tweakable hash function take PK.seed as its - * first input, which is constant for a given key pair – and, thus, across - * a single signature. This leads to a lot of redundant computation. To remedy - * this, we pad PK.seed to the length of a full 64-byte SHA-256 input block. - * Because of the Merkle-DamgÃ¥rd construction that underlies SHA-256, this - * allows for reuse of the intermediate SHA-256 state after the initial call to - * the compression function which improves performance. - * - * We pass this hash state around in functions, because otherwise we need to - * have a global variable. - */ - -#include "haraka.h" -#define hash_state harakactx - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/hashx4.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/hashx4.h index f3a7406190..3751a0ebd0 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/hashx4.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/hashx4.h @@ -1,16 +1,17 @@ -#ifndef PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_HASHX4_H -#define PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_HASHX4_H +#ifndef SPX_HASHX4_H +#define SPX_HASHX4_H #include -#include "hash_state.h" +#include "context.h" +#include "params.h" -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_prf_addrx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const unsigned char *key, - const uint32_t addrx4[4 * 8], - const hash_state *state_seeded); +#define prf_addrx4 SPX_NAMESPACE(prf_addrx4) +void prf_addrx4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const spx_ctx *ctx, + const uint32_t addrx4[4 * 8]); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/merkle.c b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/merkle.c new file mode 100644 index 0000000000..f57811c1ac --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/merkle.c @@ -0,0 +1,64 @@ +#include +#include + +#include "merkle.h" + +#include "address.h" +#include "params.h" +#include "utils.h" +#include "utilsx4.h" +#include "wots.h" +#include "wotsx4.h" + +/* + * This generates a Merkle signature (WOTS signature followed by the Merkle + * authentication path). + */ +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf) { + unsigned char *auth_path = sig + SPX_WOTS_BYTES; + uint32_t tree_addrx4[4 * 8] = { 0 }; + int j; + struct leaf_info_x4 info = { 0 }; + unsigned steps[ SPX_WOTS_LEN ]; + + info.wots_sig = sig; + chain_lengths(steps, root); + info.wots_steps = steps; + + for (j = 0; j < 4; j++) { + set_type(&tree_addrx4[8 * j], SPX_ADDR_TYPE_HASHTREE); + set_type(&info.leaf_addr[8 * j], SPX_ADDR_TYPE_WOTS); + set_type(&info.pk_addr[8 * j], SPX_ADDR_TYPE_WOTSPK); + copy_subtree_addr(&tree_addrx4[8 * j], tree_addr); + copy_subtree_addr(&info.leaf_addr[8 * j], wots_addr); + copy_subtree_addr(&info.pk_addr[8 * j], wots_addr); + } + + info.wots_sign_leaf = idx_leaf; + + treehashx4(root, auth_path, ctx, + idx_leaf, 0, + SPX_TREE_HEIGHT, + wots_gen_leafx4, + tree_addrx4, &info); +} + +/* Compute root node of the top-most subtree. */ +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { + /* We do not need the auth path in key generation, but it simplifies the + code to have just one treehash routine that computes both root and path + in one function. */ + unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; + uint32_t top_tree_addr[8] = {0}; + uint32_t wots_addr[8] = {0}; + + set_layer_addr(top_tree_addr, SPX_D - 1); + set_layer_addr(wots_addr, SPX_D - 1); + + merkle_sign(auth_path, root, ctx, + wots_addr, top_tree_addr, + ~0U /* ~0 means "don't bother generating an auth path */ ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/merkle.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/merkle.h new file mode 100644 index 0000000000..769cf2e970 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/merkle.h @@ -0,0 +1,21 @@ +#ifndef MERKLE_H_ +#define MERKLE_H_ + +#include + +#include "context.h" +#include "params.h" + +/* Generate a Merkle signature (WOTS signature followed by the Merkle */ +/* authentication path) */ +#define merkle_sign SPX_NAMESPACE(merkle_sign) +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf); + +/* Compute the root node of the top-most subtree. */ +#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); + +#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/nistapi.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/nistapi.h new file mode 100644 index 0000000000..3cb71afad4 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/nistapi.h @@ -0,0 +1,87 @@ +#ifndef SPX_API_H +#define SPX_API_H + +#include +#include + +#include "params.h" + +#define CRYPTO_ALGNAME "SPHINCS+" + +#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES +#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES +#define CRYPTO_BYTES SPX_BYTES +#define CRYPTO_SEEDBYTES (3*SPX_N) + +/* + * Returns the length of a secret key, in bytes + */ +#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) +size_t crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) +size_t crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) +size_t crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) +size_t crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +#define crypto_sign SPX_NAMESPACE(crypto_sign) +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/params.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/params.h index 2f7fb17b52..c9502e4a8b 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/params.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/params.h @@ -1,53 +1,56 @@ -#ifndef PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_PARAMS_H -#define PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_PARAMS_H +#ifndef SPX_PARAMS_H +#define SPX_PARAMS_H + +#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_##s /* Hash output length in bytes. */ -#define PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N 16 +#define SPX_N 16 /* Height of the hypertree. */ -#define PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_FULL_HEIGHT 66 +#define SPX_FULL_HEIGHT 66 /* Number of subtree layer. */ -#define PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_D 22 +#define SPX_D 22 /* FORS tree dimensions. */ -#define PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_FORS_HEIGHT 6 -#define PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_FORS_TREES 33 +#define SPX_FORS_HEIGHT 6 +#define SPX_FORS_TREES 33 /* Winternitz parameter, */ -#define PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_WOTS_W 16 +#define SPX_WOTS_W 16 /* The hash function is defined by linking a different hash.c file, as opposed to setting a #define constant. */ /* For clarity */ -#define PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_ADDR_BYTES 32 +#define SPX_ADDR_BYTES 32 /* WOTS parameters. */ -#define PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_WOTS_LOGW 4 +#define SPX_WOTS_LOGW 4 -#define PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_WOTS_LEN1 (8 * PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N / PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_WOTS_LOGW) +#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) -/* PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#define PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_WOTS_LEN2 3 +/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ +#define SPX_WOTS_LEN2 3 -#define PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_WOTS_LEN (PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_WOTS_LEN1 + PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_WOTS_LEN2) -#define PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_WOTS_BYTES (PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_WOTS_LEN * PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N) -#define PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_WOTS_PK_BYTES PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_WOTS_BYTES +#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) +#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) +#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES /* Subtree size. */ -#define PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_TREE_HEIGHT (PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_FULL_HEIGHT / PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_D) +#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) + +//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT +// #error SPX_D should always divide SPX_FULL_HEIGHT +//#endif /* FORS parameters. */ -#define PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_FORS_MSG_BYTES ((PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_FORS_TREES + 7) / 8) -#define PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_FORS_BYTES ((PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_FORS_HEIGHT + 1) * PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_FORS_TREES * PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N) -#define PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_FORS_PK_BYTES PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N +#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) +#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) +#define SPX_FORS_PK_BYTES SPX_N /* Resulting SPX sizes. */ -#define PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_BYTES (PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N + PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_FORS_BYTES + PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_D * PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_WOTS_BYTES +\ - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_FULL_HEIGHT * PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N) -#define PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_PK_BYTES (2 * PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N) -#define PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_SK_BYTES (2 * PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N + PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_PK_BYTES) - -/* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ -#define PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_OPTRAND_BYTES 32 +#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ + SPX_FULL_HEIGHT * SPX_N) +#define SPX_PK_BYTES (2 * SPX_N) +#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) + +#include "haraka_offsets.h" #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/sign.c b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/sign.c index 8ab3fbbb20..9d0c7d1b22 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/sign.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/sign.c @@ -1,76 +1,45 @@ -#include #include #include #include #include "address.h" -#include "api.h" +#include "context.h" #include "fors.h" #include "hash.h" -#include "hash_state.h" +#include "merkle.h" +#include "nistapi.h" #include "params.h" #include "randombytes.h" #include "thash.h" #include "utils.h" #include "wots.h" - -/** - * Computes the leaf at a given address. First generates the WOTS key pair, - * then computes leaf by hashing horizontally. - */ -static void wots_gen_leaf(unsigned char *leaf, const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx, const uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - unsigned char pk[PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_WOTS_BYTES]; - uint32_t wots_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_set_type( - wots_addr, PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_set_type( - wots_pk_addr, PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_ADDR_TYPE_WOTSPK); - - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_set_keypair_addr( - wots_addr, addr_idx); - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_wots_gen_pk( - pk, sk_seed, pub_seed, wots_addr, hash_state_seeded); - - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_copy_keypair_addr( - wots_pk_addr, wots_addr); - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_thash_WOTS_LEN( - leaf, pk, pub_seed, wots_pk_addr, hash_state_seeded); -} - /* * Returns the length of a secret key, in bytes */ -size_t PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_crypto_sign_secretkeybytes(void) { - return PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_CRYPTO_SECRETKEYBYTES; +size_t crypto_sign_secretkeybytes(void) { + return CRYPTO_SECRETKEYBYTES; } /* * Returns the length of a public key, in bytes */ -size_t PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_crypto_sign_publickeybytes(void) { - return PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_CRYPTO_PUBLICKEYBYTES; +size_t crypto_sign_publickeybytes(void) { + return CRYPTO_PUBLICKEYBYTES; } /* * Returns the length of a signature, in bytes */ -size_t PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_crypto_sign_bytes(void) { - return PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_CRYPTO_BYTES; +size_t crypto_sign_bytes(void) { + return CRYPTO_BYTES; } /* * Returns the length of the seed required to generate a key pair, in bytes */ -size_t PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_crypto_sign_seedbytes(void) { - return PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_CRYPTO_SEEDBYTES; +size_t crypto_sign_seedbytes(void) { + return CRYPTO_SEEDBYTES; } /* @@ -78,35 +47,29 @@ size_t PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_crypto_sign_seedbytes(void) { * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] * Format pk: [PUB_SEED || root] */ -int PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed) { - /* We do not need the auth path in key generation, but it simplifies the - code to have just one treehash routine that computes both root and path - in one function. */ - unsigned char auth_path[PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_TREE_HEIGHT * PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N]; - uint32_t top_tree_addr[8] = {0}; - hash_state hash_state_seeded; - - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_set_layer_addr( - top_tree_addr, PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_D - 1); - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_set_type( - top_tree_addr, PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_ADDR_TYPE_HASHTREE); +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed) { + spx_ctx ctx; /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ - memcpy(sk, seed, PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_CRYPTO_SEEDBYTES); + memcpy(sk, seed, CRYPTO_SEEDBYTES); + + memcpy(pk, sk + 2 * SPX_N, SPX_N); - memcpy(pk, sk + 2 * PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N, PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N); + memcpy(ctx.pub_seed, pk, SPX_N); + memcpy(ctx.sk_seed, sk, SPX_N); /* This hook allows the hash function instantiation to do whatever preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_initialize_hash_function(&hash_state_seeded, pk, sk); + initialize_hash_function(&ctx); /* Compute root node of the top-most subtree. */ - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_treehash_TREE_HEIGHT( - sk + 3 * PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N, auth_path, sk, sk + 2 * PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N, 0, 0, - wots_gen_leaf, top_tree_addr, &hash_state_seeded); + merkle_gen_root(sk + 3 * SPX_N, &ctx); - memcpy(pk + PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N, sk + 3 * PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N, PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N); + // cleanup + free_hash_function(&ctx); + + memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); return 0; } @@ -116,31 +79,10 @@ int PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_crypto_sign_seed_keypair( * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] * Format pk: [PUB_SEED || root] */ -int PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk) { - - // guarantee alignment of pk - union { - __m128 _x[PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_CRYPTO_PUBLICKEYBYTES / 16]; - uint8_t pk[PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_CRYPTO_PUBLICKEYBYTES]; - } aligned_pk; - - // guarantee alignment of sk - union { - __m128 _x[PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_CRYPTO_SECRETKEYBYTES / 16]; - uint8_t sk[PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_CRYPTO_SECRETKEYBYTES]; - } aligned_sk; - - union { - __m128 _x[PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_CRYPTO_SEEDBYTES / 16]; - uint8_t seed[PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_CRYPTO_SEEDBYTES]; - } aligned_seed; - randombytes(aligned_seed.seed, PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_CRYPTO_SEEDBYTES); - - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_crypto_sign_seed_keypair( - aligned_pk.pk, aligned_sk.sk, aligned_seed.seed); - memcpy(pk, aligned_pk.pk, PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_CRYPTO_PUBLICKEYBYTES); - memcpy(sk, aligned_sk.sk, PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_CRYPTO_SECRETKEYBYTES); +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { + uint8_t seed[CRYPTO_SEEDBYTES]; + randombytes(seed, CRYPTO_SEEDBYTES); + crypto_sign_seed_keypair(pk, sk, seed); return 0; } @@ -148,101 +90,68 @@ int PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_crypto_sign_keypair( /** * Returns an array containing a detached signature. */ -int PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - // guarantee alignment of sk - union { - __m128 *_x; - uint8_t sk[PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_CRYPTO_SECRETKEYBYTES]; - } aligned_sk; - memcpy(aligned_sk.sk, sk, PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_CRYPTO_SECRETKEYBYTES); - sk = aligned_sk.sk; - - // guarantee alignment of sig - union { - __m128 *_x; - uint8_t sig[PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_BYTES]; - } aligned_sig; - uint8_t *orig_sig = sig; - sig = (uint8_t *)aligned_sig.sig; - - const unsigned char *sk_seed = sk; - const unsigned char *sk_prf = sk + PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N; - const unsigned char *pk = sk + 2 * PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N; - const unsigned char *pub_seed = pk; - - unsigned char optrand[PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N]; - unsigned char mhash[PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_FORS_MSG_BYTES]; - unsigned char root[PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N]; +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk) { + spx_ctx ctx; + + const uint8_t *sk_prf = sk + SPX_N; + const uint8_t *pk = sk + 2 * SPX_N; + + uint8_t optrand[SPX_N]; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t root[SPX_N]; uint32_t i; uint64_t tree; uint32_t idx_leaf; uint32_t wots_addr[8] = {0}; uint32_t tree_addr[8] = {0}; - hash_state hash_state_seeded; + memcpy(ctx.sk_seed, sk, SPX_N); + memcpy(ctx.pub_seed, pk, SPX_N); /* This hook allows the hash function instantiation to do whatever preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_initialize_hash_function( - &hash_state_seeded, - pub_seed, sk_seed); + initialize_hash_function(&ctx); - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_set_type( - wots_addr, PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_set_type( - tree_addr, PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_ADDR_TYPE_HASHTREE); + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); /* Optionally, signing can be made non-deterministic using optrand. This can help counter side-channel attacks that would benefit from getting a large number of traces when the signer uses the same nodes. */ - randombytes(optrand, PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N); + randombytes(optrand, SPX_N); /* Compute the digest randomization value. */ - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_gen_message_random( - sig, sk_prf, optrand, m, mlen, &hash_state_seeded); + gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); /* Derive the message digest and leaf index from R, PK and M. */ - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N; + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_set_keypair_addr( - wots_addr, idx_leaf); + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); /* Sign the message hash using FORS. */ - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_fors_sign( - sig, root, mhash, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_FORS_BYTES; - - for (i = 0; i < PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_D; i++) { - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_set_tree_addr(tree_addr, tree); - - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_set_keypair_addr( - wots_addr, idx_leaf); - - /* Compute a WOTS signature. */ - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_wots_sign( - sig, root, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_WOTS_BYTES; - - /* Compute the authentication path for the used WOTS leaf. */ - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_treehash_TREE_HEIGHT( - root, sig, sk_seed, pub_seed, idx_leaf, 0, - wots_gen_leaf, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_TREE_HEIGHT * PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N; + fors_sign(sig, root, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); + sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_TREE_HEIGHT; + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; } - memcpy(orig_sig, aligned_sig.sig, PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_BYTES); - *siglen = PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_BYTES; + free_hash_function(&ctx); + + *siglen = SPX_BYTES; return 0; } @@ -250,23 +159,14 @@ int PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_crypto_sign_signature( /** * Verifies a detached signature and message under a given public key. */ -int PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk) { - // guarantee alignment of pk - union { - __m128 *_x; - uint8_t pk[PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_CRYPTO_PUBLICKEYBYTES]; - } aligned_pk; - memcpy(aligned_pk.pk, pk, PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_CRYPTO_PUBLICKEYBYTES); - pk = aligned_pk.pk; - - const unsigned char *pub_seed = pk; - const unsigned char *pub_root = pk + PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N; - unsigned char mhash[PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_FORS_MSG_BYTES]; - unsigned char wots_pk[PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_WOTS_BYTES]; - unsigned char root[PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N]; - unsigned char leaf[PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N]; +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk) { + spx_ctx ctx; + const uint8_t *pub_root = pk + SPX_N; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t wots_pk[SPX_WOTS_BYTES]; + uint8_t root[SPX_N]; + uint8_t leaf[SPX_N]; unsigned int i; uint64_t tree; uint32_t idx_leaf; @@ -274,77 +174,66 @@ int PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_crypto_sign_verify( uint32_t tree_addr[8] = {0}; uint32_t wots_pk_addr[8] = {0}; - hash_state hash_state_seeded; - - if (siglen != PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_BYTES) { + if (siglen != SPX_BYTES) { return -1; } + memcpy(ctx.pub_seed, pk, SPX_N); + /* This hook allows the hash function instantiation to do whatever preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_initialize_hash_function( - &hash_state_seeded, - pub_seed, NULL); + initialize_hash_function(&ctx); - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_set_type( - wots_addr, PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_set_type( - tree_addr, PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_ADDR_TYPE_HASHTREE); - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_set_type( - wots_pk_addr, PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_ADDR_TYPE_WOTSPK); + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); /* Derive the message digest and leaf index from R || PK || M. */ - /* The additional PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N is a result of the hash domain separator. */ - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N; + /* The additional SPX_N is a result of the hash domain separator. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; /* Layer correctly defaults to 0, so no need to set_layer_addr */ - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_set_keypair_addr( - wots_addr, idx_leaf); + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_fors_pk_from_sig( - root, sig, mhash, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_FORS_BYTES; + fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; /* For each subtree.. */ - for (i = 0; i < PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_D; i++) { - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_set_tree_addr(tree_addr, tree); + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_set_keypair_addr( - wots_addr, idx_leaf); + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_copy_keypair_addr( - wots_pk_addr, wots_addr); + copy_keypair_addr(wots_pk_addr, wots_addr); /* The WOTS public key is only correct if the signature was correct. */ /* Initially, root is the FORS pk, but on subsequent iterations it is the root of the subtree below the currently processed subtree. */ - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_wots_pk_from_sig( - wots_pk, sig, root, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_WOTS_BYTES; + wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); + sig += SPX_WOTS_BYTES; /* Compute the leaf node using the WOTS public key. */ - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_thash_WOTS_LEN( - leaf, wots_pk, pub_seed, wots_pk_addr, &hash_state_seeded); + thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); /* Compute the root node of this subtree. */ - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_compute_root( - root, leaf, idx_leaf, 0, sig, PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_TREE_HEIGHT, - pub_seed, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_TREE_HEIGHT * PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N; + compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, + &ctx, tree_addr); + sig += SPX_TREE_HEIGHT * SPX_N; /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_TREE_HEIGHT; + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; } + // cleanup + free_hash_function(&ctx); + /* Check if the root node equals the root node in the public key. */ - if (memcmp(root, pub_root, PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N) != 0) { + if (memcmp(root, pub_root, SPX_N) != 0) { return -1; } @@ -355,15 +244,14 @@ int PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_crypto_sign_verify( /** * Returns an array containing the signature followed by the message. */ -int PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk) { size_t siglen; - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_crypto_sign_signature( - sm, &siglen, m, mlen, sk); + crypto_sign_signature(sm, &siglen, m, mlen, sk); - memmove(sm + PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_BYTES, m, mlen); + memmove(sm + SPX_BYTES, m, mlen); *smlen = siglen + mlen; return 0; @@ -372,38 +260,27 @@ int PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_crypto_sign( /** * Verifies a given signature-message pair under a given public key. */ -int PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk) { - - // guarantee alignment of pk - union { - __m128 *_x; - uint8_t pk[PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_CRYPTO_PUBLICKEYBYTES]; - } aligned_pk; - memcpy(aligned_pk.pk, pk, PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_CRYPTO_PUBLICKEYBYTES); - pk = aligned_pk.pk; - - +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk) { /* The API caller does not necessarily know what size a signature should be - but SPHINCS+ signatures are always exactly PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_BYTES. */ - if (smlen < PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_BYTES) { + but SPHINCS+ signatures are always exactly SPX_BYTES. */ + if (smlen < SPX_BYTES) { memset(m, 0, smlen); *mlen = 0; return -1; } - *mlen = smlen - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_BYTES; + *mlen = smlen - SPX_BYTES; - if (PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_crypto_sign_verify( - sm, PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_BYTES, sm + PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_BYTES, *mlen, pk)) { + if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { memset(m, 0, smlen); *mlen = 0; return -1; } /* If verification was successful, move the message to the right place. */ - memmove(m, sm + PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_BYTES, *mlen); + memmove(m, sm + SPX_BYTES, *mlen); return 0; } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/thash.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/thash.h index 8825a01989..8687ccfb4d 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/thash.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/thash.h @@ -1,28 +1,13 @@ -#ifndef PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_THASH_H -#define PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_THASH_H +#ifndef SPX_THASH_H +#define SPX_THASH_H -#include "hash_state.h" +#include "context.h" +#include "params.h" #include -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); +#define thash SPX_NAMESPACE(thash) +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/thash_haraka_simple.c b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/thash_haraka_simple.c index 6ef2b75eda..207777bf8d 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/thash_haraka_simple.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/thash_haraka_simple.c @@ -4,80 +4,33 @@ #include "address.h" #include "params.h" #include "thash.h" +#include "utils.h" #include "haraka.h" /** - * Takes an array of inblocks concatenated arrays of PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N bytes. + * Takes an array of inblocks concatenated arrays of SPX_N bytes. */ -static void PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_thash( - unsigned char *out, unsigned char *buf, - const unsigned char *in, unsigned int inblocks, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]) { + PQCLEAN_VLA(uint8_t, buf, SPX_ADDR_BYTES + inblocks * SPX_N); unsigned char outbuf[32]; unsigned char buf_tmp[64]; - (void)pub_seed; /* Suppress an 'unused parameter' warning. */ - if (inblocks == 1) { /* F function */ - /* Since PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N may be smaller than 32, we need a temporary buffer. */ + /* Since SPX_N may be smaller than 32, we need a temporary buffer. */ memset(buf_tmp, 0, 64); - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_addr_to_bytes(buf_tmp, addr); - memcpy(buf_tmp + PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_ADDR_BYTES, in, PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N); + memcpy(buf_tmp, addr, 32); + memcpy(buf_tmp + SPX_ADDR_BYTES, in, SPX_N); - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_haraka512(outbuf, buf_tmp, hash_state_seeded); - memcpy(out, outbuf, PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N); + haraka512(outbuf, buf_tmp, ctx); + memcpy(out, outbuf, SPX_N); } else { /* All other tweakable hashes*/ - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_addr_to_bytes(buf, addr); - memcpy(buf + PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_ADDR_BYTES, in, inblocks * PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N); + memcpy(buf, addr, 32); + memcpy(buf + SPX_ADDR_BYTES, in, inblocks * SPX_N); - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_haraka_S( - out, PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N, buf, PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N, hash_state_seeded); + haraka_S(out, SPX_N, buf, SPX_ADDR_BYTES + inblocks * SPX_N, ctx); } } - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_ADDR_BYTES + 1 * PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N]; - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_thash( - out, buf, in, 1, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_ADDR_BYTES + 2 * PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N]; - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_thash( - out, buf, in, 2, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_ADDR_BYTES + PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_WOTS_LEN * PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N]; - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_thash( - out, buf, in, PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_WOTS_LEN, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_ADDR_BYTES + PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_FORS_TREES * PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N]; - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_thash( - out, buf, in, PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_FORS_TREES, pub_seed, addr, hash_state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/thash_haraka_simplex4.c b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/thash_haraka_simplex4.c index aade6da1a4..2ee763d7d9 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/thash_haraka_simplex4.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/thash_haraka_simplex4.c @@ -2,65 +2,66 @@ #include #include "address.h" -#include "haraka.h" #include "params.h" #include "thashx4.h" +#include "harakax4.h" + +#include "utils.h" + /** * 4-way parallel version of thash; takes 4x as much input and output */ -#define thashx4_variant(name, inblocks) \ - void PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_thashx4_##name(unsigned char *out0, unsigned char *out1, unsigned char *out2, \ - unsigned char *out3, const unsigned char *in0, \ - const unsigned char *in1, const unsigned char *in2, \ - const unsigned char *in3, const unsigned char *pub_seed, \ - uint32_t addrx4[4 * 8], const harakactx *state) { \ - unsigned char buf0[PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_ADDR_BYTES + (inblocks)*PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N]; \ - unsigned char buf1[PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_ADDR_BYTES + (inblocks)*PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N]; \ - unsigned char buf2[PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_ADDR_BYTES + (inblocks)*PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N]; \ - unsigned char buf3[PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_ADDR_BYTES + (inblocks)*PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N]; \ - unsigned char outbuf[32 * 4]; \ - unsigned char buf_tmp[64 * 4]; \ - \ - (void)pub_seed; /* Suppress an 'unused parameter' warning. */ \ - \ - if ((inblocks) == 1) { \ - memset(buf_tmp, 0, 64 * 4); \ - \ - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_addr_to_bytes(buf_tmp, addrx4 + 0 * 8); \ - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_addr_to_bytes(buf_tmp + 64, addrx4 + 1 * 8); \ - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_addr_to_bytes(buf_tmp + 128, addrx4 + 2 * 8); \ - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_addr_to_bytes(buf_tmp + 192, addrx4 + 3 * 8); \ - \ - memcpy(buf_tmp + PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_ADDR_BYTES, in0, PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N); \ - memcpy(buf_tmp + PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_ADDR_BYTES + 64, in1, PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N); \ - memcpy(buf_tmp + PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_ADDR_BYTES + 128, in2, PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N); \ - memcpy(buf_tmp + PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_ADDR_BYTES + 192, in3, PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N); \ - \ - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_haraka512x4(outbuf, buf_tmp, state); \ - \ - memcpy(out0, outbuf, PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N); \ - memcpy(out1, outbuf + 32, PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N); \ - memcpy(out2, outbuf + 64, PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N); \ - memcpy(out3, outbuf + 96, PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N); \ - } else { \ - /* All other tweakable hashes*/ \ - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_addr_to_bytes(buf0, addrx4 + 0 * 8); \ - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_addr_to_bytes(buf1, addrx4 + 1 * 8); \ - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_addr_to_bytes(buf2, addrx4 + 2 * 8); \ - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_addr_to_bytes(buf3, addrx4 + 3 * 8); \ - \ - memcpy(buf0 + PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_ADDR_BYTES, in0, (inblocks)*PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N); \ - memcpy(buf1 + PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_ADDR_BYTES, in1, (inblocks)*PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N); \ - memcpy(buf2 + PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_ADDR_BYTES, in2, (inblocks)*PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N); \ - memcpy(buf3 + PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_ADDR_BYTES, in3, (inblocks)*PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N); \ - \ - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_haraka_Sx4(out0, out1, out2, out3, PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N, buf0, buf1, buf2, buf3, \ - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_ADDR_BYTES + (inblocks)*PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N, state); \ - } \ - } +#define thashx4 SPX_NAMESPACE(thashx4) +void thashx4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addrx4[4 * 8]) { + PQCLEAN_VLA(unsigned char, buf0, SPX_ADDR_BYTES + inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, buf1, SPX_ADDR_BYTES + inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, buf2, SPX_ADDR_BYTES + inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, buf3, SPX_ADDR_BYTES + inblocks * SPX_N); + unsigned char outbuf[32 * 4]; + unsigned char buf_tmp[64 * 4]; + + if (inblocks == 1) { + memset(buf_tmp, 0, 64 * 4); + + memcpy(buf_tmp, addrx4 + 0 * 8, 32); + memcpy(buf_tmp + 64, addrx4 + 1 * 8, 32); + memcpy(buf_tmp + 128, addrx4 + 2 * 8, 32); + memcpy(buf_tmp + 192, addrx4 + 3 * 8, 32); -thashx4_variant(1, 1) -thashx4_variant(2, 2) -thashx4_variant(WOTS_LEN, PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_WOTS_LEN) -thashx4_variant(FORS_TREES, PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_FORS_TREES) + memcpy(buf_tmp + SPX_ADDR_BYTES, in0, SPX_N); + memcpy(buf_tmp + SPX_ADDR_BYTES + 64, in1, SPX_N); + memcpy(buf_tmp + SPX_ADDR_BYTES + 128, in2, SPX_N); + memcpy(buf_tmp + SPX_ADDR_BYTES + 192, in3, SPX_N); + + haraka512x4(outbuf, buf_tmp, ctx); + + memcpy(out0, outbuf, SPX_N); + memcpy(out1, outbuf + 32, SPX_N); + memcpy(out2, outbuf + 64, SPX_N); + memcpy(out3, outbuf + 96, SPX_N); + } else { + /* All other tweakable hashes*/ + memcpy(buf0, addrx4 + 0 * 8, 32); + memcpy(buf1, addrx4 + 1 * 8, 32); + memcpy(buf2, addrx4 + 2 * 8, 32); + memcpy(buf3, addrx4 + 3 * 8, 32); + + memcpy(buf0 + SPX_ADDR_BYTES, in0, inblocks * SPX_N); + memcpy(buf1 + SPX_ADDR_BYTES, in1, inblocks * SPX_N); + memcpy(buf2 + SPX_ADDR_BYTES, in2, inblocks * SPX_N); + memcpy(buf3 + SPX_ADDR_BYTES, in3, inblocks * SPX_N); + + haraka_Sx4(out0, out1, out2, out3, SPX_N, + buf0, buf1, buf2, buf3, SPX_ADDR_BYTES + inblocks * SPX_N, + ctx); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/thashx4.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/thashx4.h index 0f45b95851..64798a3727 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/thashx4.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/thashx4.h @@ -1,25 +1,20 @@ -#ifndef PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_THASHX4_H -#define PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_THASHX4_H +#ifndef SPX_THASHX4_H +#define SPX_THASHX4_H #include -#include "hash_state.h" +#include "context.h" +#include "params.h" -#define thashx4_header(inblocks) \ - void PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_thashx4_##inblocks(unsigned char *out0, \ - unsigned char *out1, \ - unsigned char *out2, \ - unsigned char *out3, \ - const unsigned char *in0, \ - const unsigned char *in1, \ - const unsigned char *in2, \ - const unsigned char *in3, \ - const unsigned char *pub_seed, uint32_t addrx4[4*8], \ - const hash_state *state_seeded) - -thashx4_header(1); -thashx4_header(2); -thashx4_header(WOTS_LEN); -thashx4_header(FORS_TREES); +#define thashx4 SPX_NAMESPACE(thashx4) +void thashx4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addrx4[4 * 8]); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/utils.c b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/utils.c index 0d1b0b49cd..177b541fb9 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/utils.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/utils.c @@ -1,34 +1,41 @@ -#include #include +#include "utils.h" + #include "address.h" #include "hash.h" -#include "hash_state.h" #include "params.h" #include "thash.h" -#include "utils.h" /** * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. */ -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in) { +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in) { + int i; /* Iterate over out in decreasing order, for big-endianness. */ - for (size_t i = outlen; i > 0; i--) { - out[i - 1] = in & 0xff; + for (i = (signed int)outlen - 1; i >= 0; i--) { + out[i] = in & 0xff; in = in >> 8; } } +void u32_to_bytes(unsigned char *out, uint32_t in) { + out[0] = (unsigned char)(in >> 24); + out[1] = (unsigned char)(in >> 16); + out[2] = (unsigned char)(in >> 8); + out[3] = (unsigned char)in; +} + /** * Converts the inlen bytes in 'in' from big-endian byte order to an integer. */ -unsigned long long PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_bytes_to_ull( - const unsigned char *in, size_t inlen) { +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { unsigned long long retval = 0; + unsigned int i; - for (size_t i = 0; i < inlen; i++) { + for (i = 0; i < inlen; i++) { retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); } return retval; @@ -38,94 +45,80 @@ unsigned long long PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_bytes_to_ull( * Computes a root node given a leaf and an auth path. * Expects address to be complete other than the tree_height and tree_index. */ -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]) { uint32_t i; - unsigned char buffer[2 * PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N]; + unsigned char buffer[2 * SPX_N]; /* If leaf_idx is odd (last bit = 1), current path element is a right child and auth_path has to go left. Otherwise it is the other way around. */ if (leaf_idx & 1) { - memcpy(buffer + PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N, leaf, PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N); + memcpy(buffer + SPX_N, leaf, SPX_N); + memcpy(buffer, auth_path, SPX_N); } else { - memcpy(buffer, leaf, PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N); - memcpy(buffer + PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N, auth_path, PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N); + memcpy(buffer, leaf, SPX_N); + memcpy(buffer + SPX_N, auth_path, SPX_N); } - auth_path += PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N; + auth_path += SPX_N; for (i = 0; i < tree_height - 1; i++) { leaf_idx >>= 1; idx_offset >>= 1; /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_set_tree_height(addr, i + 1); - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_set_tree_index( - addr, leaf_idx + idx_offset); + set_tree_height(addr, i + 1); + set_tree_index(addr, leaf_idx + idx_offset); /* Pick the right or left neighbor, depending on parity of the node. */ if (leaf_idx & 1) { - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_thash_2( - buffer + PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N); + thash(buffer + SPX_N, buffer, 2, ctx, addr); + memcpy(buffer, auth_path, SPX_N); } else { - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_thash_2( - buffer, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer + PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N, auth_path, PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N); + thash(buffer, buffer, 2, ctx, addr); + memcpy(buffer + SPX_N, auth_path, SPX_N); } - auth_path += PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N; + auth_path += SPX_N; } /* The last iteration is exceptional; we do not copy an auth_path node. */ leaf_idx >>= 1; idx_offset >>= 1; - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_set_tree_height(addr, tree_height); - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_set_tree_index( - addr, leaf_idx + idx_offset); - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_thash_2( - root, buffer, pub_seed, addr, hash_state_seeded); + set_tree_height(addr, tree_height); + set_tree_index(addr, leaf_idx + idx_offset); + thash(root, buffer, 2, ctx, addr); } /** * For a given leaf index, computes the authentication path and the resulting * root node using Merkle's TreeHash algorithm. * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_ADDR_TYPE_FORSTREE). + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). * Applies the offset idx_offset to indices before building addresses, so that * it is possible to continue counting indices across trees. */ -static void PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_treehash( - unsigned char *root, unsigned char *auth_path, - unsigned char *stack, unsigned int *heights, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - +void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx * /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]) { + PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); + PQCLEAN_VLA(unsigned int, heights, tree_height + 1); unsigned int offset = 0; uint32_t idx; uint32_t tree_idx; for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { /* Add the next leaf node to the stack. */ - gen_leaf(stack + offset * PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N, - sk_seed, pub_seed, idx + idx_offset, tree_addr, - hash_state_seeded); + gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); offset++; heights[offset - 1] = 0; /* If this is a node we need for the auth path.. */ if ((leaf_idx ^ 0x1) == idx) { - memcpy(auth_path, stack + (offset - 1)*PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N, PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N); + memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); } /* While the top-most nodes are of equal height.. */ @@ -134,66 +127,22 @@ static void PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_treehash( tree_idx = (idx >> (heights[offset - 1] + 1)); /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_set_tree_height( - tree_addr, heights[offset - 1] + 1); - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_set_tree_index( - tree_addr, tree_idx + (idx_offset >> (heights[offset - 1] + 1))); + set_tree_height(tree_addr, heights[offset - 1] + 1); + set_tree_index(tree_addr, + tree_idx + (idx_offset >> (heights[offset - 1] + 1))); /* Hash the top-most nodes from the stack together. */ - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_thash_2( - stack + (offset - 2)*PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N, stack + (offset - 2)*PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N, - pub_seed, tree_addr, hash_state_seeded); + thash(stack + (offset - 2)*SPX_N, + stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); offset--; /* Note that the top-most node is now one layer higher. */ heights[offset - 1]++; /* If this is a node we need for the auth path.. */ if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_path + heights[offset - 1]*PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N, - stack + (offset - 1)*PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N, PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N); + memcpy(auth_path + heights[offset - 1]*SPX_N, + stack + (offset - 1)*SPX_N, SPX_N); } } } - memcpy(root, stack, PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N); -} - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_FORS_HEIGHT + 1)*PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N]; - unsigned int heights[PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_FORS_HEIGHT + 1]; - - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_FORS_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_TREE_HEIGHT + 1)*PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N]; - unsigned int heights[PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_TREE_HEIGHT + 1]; - - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_TREE_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); + memcpy(root, stack, SPX_N); } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/utils.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/utils.h index f241c10aa4..64f5d5a53a 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/utils.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/utils.h @@ -1,64 +1,58 @@ -#ifndef PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_UTILS_H -#define PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_UTILS_H +#ifndef SPX_UTILS_H +#define SPX_UTILS_H -#include "hash_state.h" -#include "params.h" -#include #include +#include "compat.h" +#include "context.h" +#include "params.h" + + +/* To support MSVC use alloca() instead of VLAs. See #20. */ + + /** * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. */ -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in); +#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in); +#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) +void u32_to_bytes(unsigned char *out, uint32_t in); /** * Converts the inlen bytes in 'in' from big-endian byte order to an integer. */ -unsigned long long PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_bytes_to_ull( - const unsigned char *in, size_t inlen); +#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); /** * Computes a root node given a leaf and an auth path. * Expects address to be complete other than the tree_height and tree_index. */ -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); +#define compute_root SPX_NAMESPACE(compute_root) +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]); /** * For a given leaf index, computes the authentication path and the resulting * root node using Merkle's TreeHash algorithm. * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_ADDR_TYPE_FORSTREE). + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). * Applies the offset idx_offset to indices before building addresses, so that * it is possible to continue counting indices across trees. */ -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); +#define treehash SPX_NAMESPACE(treehash) +void treehash(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx *ctx /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]); -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/utilsx4.c b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/utilsx4.c index 9d67f76575..1638677194 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/utilsx4.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/utilsx4.c @@ -1,98 +1,138 @@ +#include + +#include "utilsx4.h" + #include "address.h" #include "params.h" #include "thashx4.h" #include "utils.h" -#include "utilsx4.h" -#include - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. +/* + * Generate the entire Merkle tree, computing the authentication path for leaf_idx, + * and the resulting root node using Merkle's TreeHash algorithm. * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_ADDR_TYPE_FORSTREE). + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) + * + * This expects tree_addrx4 to be initialized to 4 parallel addr structures for + * the Merkle tree nodes + * * Applies the offset idx_offset to indices before building addresses, so that * it is possible to continue counting indices across trees. + * + * This works by using the standard Merkle tree building algorithm, except + * that each 'node' tracked is actually 4 consecutive nodes in the real tree. + * When we combine two logical nodes ABCD and WXYZ, we perform the H + * operation on adjacent real nodes, forming the parent logical node + * (AB)(CD)(WX)(YZ) + * + * When we get to the top two levels of the real tree (where there is only + * one logical node), we continue this operation two more times; the right + * most real node will by the actual root (and the other 3 nodes will be + * garbage). We follow the same thashx4 logic so that the 'extract + * authentication path components' part of the loop is still executed (and + * to simplify the code somewhat) + * + * This currently assumes tree_height >= 2; I suspect that doing an adjusting + * idx, addr_idx on the gen_leafx4 call if tree_height < 2 would fix it; since + * we don't actually use such short trees, I haven't bothered */ -#define treehashx4_variant(name, tree_height) \ - void PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_treehashx4_##name( \ - unsigned char *rootx4, unsigned char *auth_pathx4, const unsigned char *sk_seed, \ - const unsigned char *pub_seed, const uint32_t leaf_idx[4], uint32_t idx_offset[4], \ - void (*gen_leafx4)(unsigned char * /* leaf0 */, unsigned char * /* leaf1 */, \ - unsigned char * /* leaf2 */, unsigned char * /* leaf3 */, \ - const unsigned char * /* sk_seed */, \ - const unsigned char * /* pub_seed */, uint32_t /* addr_idx0 */, \ - uint32_t /* addr_idx1 */, uint32_t /* addr_idx2 */, \ - uint32_t /* addr_idx3 */, const uint32_t[8] /* tree_addr */, \ - const hash_state * /* state_seeded */), \ - uint32_t tree_addrx4[4 * 8], const hash_state *state_seeded) { \ - unsigned char stackx4[4 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N]; \ - unsigned int heights[(tree_height) + 1]; \ - unsigned int offset = 0; \ - uint32_t idx; \ - uint32_t tree_idx; \ - unsigned int j; \ - \ - for (idx = 0; idx < (uint32_t)(1 << (tree_height)); idx++) { \ - /* Add the next leaf node to the stack. */ \ - gen_leafx4(stackx4 + 0 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N + offset * PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N, \ - stackx4 + 1 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N + offset * PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N, \ - stackx4 + 2 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N + offset * PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N, \ - stackx4 + 3 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N + offset * PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N, sk_seed, \ - pub_seed, idx + idx_offset[0], idx + idx_offset[1], idx + idx_offset[2], \ - idx + idx_offset[3], tree_addrx4, state_seeded); \ - offset++; \ - heights[offset - 1] = 0; \ - \ - /* If this is a node we need for the auth path.. */ \ - for (j = 0; j < 4; j++) { \ - if ((leaf_idx[j] ^ 0x1) == idx) { \ - memcpy(auth_pathx4 + j * (tree_height)*PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N, \ - stackx4 + j * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N + (offset - 1) * PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N, \ - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N); \ - } \ - } \ - \ - /* While the top-most nodes are of equal height.. */ \ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { \ - /* Compute index of the new node, in the next layer. */ \ - tree_idx = (idx >> (heights[offset - 1] + 1)); \ - \ - /* Set the address of the node we're creating. */ \ - for (j = 0; j < 4; j++) { \ - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_set_tree_height(tree_addrx4 + j * 8, heights[offset - 1] + 1); \ - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_set_tree_index(tree_addrx4 + j * 8, \ - tree_idx + (idx_offset[j] >> (heights[offset - 1] + 1))); \ - } \ - /* Hash the top-most nodes from the stack together. */ \ - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_thashx4_2(stackx4 + 0 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N + (offset - 2) * PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N, \ - stackx4 + 1 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N + (offset - 2) * PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N, \ - stackx4 + 2 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N + (offset - 2) * PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N, \ - stackx4 + 3 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N + (offset - 2) * PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N, \ - stackx4 + 0 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N + (offset - 2) * PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N, \ - stackx4 + 1 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N + (offset - 2) * PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N, \ - stackx4 + 2 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N + (offset - 2) * PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N, \ - stackx4 + 3 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N + (offset - 2) * PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N, \ - pub_seed, tree_addrx4, state_seeded); \ - offset--; \ - /* Note that the top-most node is now one layer higher. */ \ - heights[offset - 1]++; \ - \ - /* If this is a node we need for the auth path.. */ \ - for (j = 0; j < 4; j++) { \ - if (((leaf_idx[j] >> heights[offset - 1]) ^ 0x1) == tree_idx) { \ - memcpy(auth_pathx4 + j * (tree_height)*PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N + \ - heights[offset - 1] * PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N, \ - stackx4 + j * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N + (offset - 1) * PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N, \ - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N); \ - } \ - } \ - } \ - } \ - \ - for (j = 0; j < 4; j++) { \ - memcpy(rootx4 + j * PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N, stackx4 + j * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N, PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N); \ - } \ - } +void treehashx4(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, + uint32_t tree_height, + void (*gen_leafx4)( + unsigned char * /* Where to write the leaves */, + const spx_ctx *, + uint32_t idx, void *info), + uint32_t tree_addrx4[4 * 8], + void *info) { + /* This is where we keep the intermediate nodes */ + PQCLEAN_VLA(unsigned char, stackx4, tree_height * 4 * SPX_N); + uint32_t left_adj = 0, prev_left_adj = 0; /* When we're doing the top 3 */ + /* levels, the left-most part of the tree isn't at the beginning */ + /* of current[]. These give the offset of the actual start */ + + uint32_t idx; + uint32_t max_idx = (1U << (tree_height - 2)) - 1; + for (idx = 0;; idx++) { + unsigned char current[4 * SPX_N]; /* Current logical node */ + gen_leafx4( current, ctx, 4 * idx + idx_offset, + info ); -treehashx4_variant(FORS_HEIGHT, PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_FORS_HEIGHT) + /* Now combine the freshly generated right node with previously */ + /* generated left ones */ + uint32_t internal_idx_offset = idx_offset; + uint32_t internal_idx = idx; + uint32_t internal_leaf = leaf_idx; + uint32_t h; /* The height we are in the Merkle tree */ + for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { + + /* Special processing if we're at the top of the tree */ + if (h >= tree_height - 2) { + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[3 * SPX_N], SPX_N ); + return; + } + /* The tree indexing logic is a bit off in this case */ + /* Adjust it so that the left-most node of the part of */ + /* the tree that we're processing has index 0 */ + prev_left_adj = left_adj; + left_adj = 4U - (1 << (tree_height - h - 1)); + } + + /* Check if we hit the top of the tree */ + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[3 * SPX_N], SPX_N ); + return; + } + + /* + * Check if one of the nodes we have is a part of the + * authentication path; if it is, write it out + */ + if ((((internal_idx << 2) ^ internal_leaf) & ~0x3U) == 0) { + memcpy( &auth_path[ h * SPX_N ], + ¤t[(((internal_leaf & 3) ^ 1) + prev_left_adj) * SPX_N], + SPX_N ); + } + + /* + * Check if we're at a left child; if so, stop going up the stack + * Exception: if we've reached the end of the tree, keep on going + * (so we combine the last 4 nodes into the one root node in two + * more iterations) + */ + if ((internal_idx & 1) == 0 && idx < max_idx) { + break; + } + + /* Ok, we're at a right node (or doing the top 3 levels) */ + /* Now combine the left and right logical nodes together */ + + /* Set the address of the node we're creating. */ + unsigned int j; + internal_idx_offset >>= 1; + for (j = 0; j < 4; j++) { + set_tree_height(tree_addrx4 + j * 8, h + 1); + set_tree_index(tree_addrx4 + j * 8, + (4 / 2) * (internal_idx & ~1U) + j - left_adj + internal_idx_offset ); + } + unsigned char *left = &stackx4[h * 4 * SPX_N]; + thashx4( ¤t[0 * SPX_N], + ¤t[1 * SPX_N], + ¤t[2 * SPX_N], + ¤t[3 * SPX_N], + &left [0 * SPX_N], + &left [2 * SPX_N], + ¤t[0 * SPX_N], + ¤t[2 * SPX_N], + 2, ctx, tree_addrx4); + } + + /* We've hit a left child; save the current for when we get the */ + /* corresponding right right */ + memcpy( &stackx4[h * 4 * SPX_N], current, 4 * SPX_N); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/utilsx4.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/utilsx4.h index b3ed7b875d..facb874b18 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/utilsx4.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/utilsx4.h @@ -1,38 +1,30 @@ -#ifndef PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_UTILSX4_H -#define PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_UTILSX4_H - -#include "hash_state.h" -#include "params.h" +#ifndef SPX_UTILSX4_H +#define SPX_UTILSX4_H #include +#include "context.h" +#include "params.h" + /** * For a given leaf index, computes the authentication path and the resulting * root node using Merkle's TreeHash algorithm. * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_ADDR_TYPE_FORSTREE). + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). * Applies the offset idx_offset to indices before building addresses, so that * it is possible to continue counting indices across trees. + * + * This implementation uses AVX to compute internal nodes 4 at a time (in + * parallel) */ -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_treehashx4_FORS_HEIGHT(unsigned char *rootx4, - unsigned char *auth_pathx4, - const unsigned char *sk_seed, - const unsigned char *pub_seed, - const uint32_t leaf_idx[4], - uint32_t idx_offset[4], - void (*gen_leafx4)(unsigned char * /* leaf0 */, - unsigned char * /* leaf1 */, - unsigned char * /* leaf2 */, - unsigned char * /* leaf3 */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx0 */, - uint32_t /* addr_idx1 */, - uint32_t /* addr_idx2 */, - uint32_t /* addr_idx3 */, - const uint32_t[8] /* tree_addr */, - const hash_state * /* state_seeded */), - uint32_t tree_addrx4[4 * 8], - const hash_state *state_seeded); +#define treehashx4 SPX_NAMESPACE(treehashx4) +void treehashx4(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leafx4)( + unsigned char * /* Where to write the leaves */, + const spx_ctx * /* ctx */, + uint32_t addr_idx, void *info), + uint32_t tree_addrx4[4 * 8], void *info); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/wots.c b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/wots.c index 6eb6bd4d20..4d5041ce05 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/wots.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/wots.c @@ -1,106 +1,104 @@ #include #include +#include "wots.h" + #include "address.h" #include "hash.h" -#include "hash_state.h" #include "hashx4.h" #include "params.h" #include "thash.h" #include "thashx4.h" #include "utils.h" -#include "wots.h" +#include "utilsx4.h" +#include "wotsx4.h" // TODO clarify address expectations, and make them more uniform. // TODO i.e. do we expect types to be set already? // TODO and do we expect modifications or copies? /** - * Computes the starting value for a chain, i.e. the secret key. - * Expects the address to be complete up to the chain address. - */ -static void wots_gen_sk(unsigned char *sk, const unsigned char *sk_seed, - uint32_t wots_addr[8], const hash_state *state_seeded) { - /* Make sure that the hash address is actually zeroed. */ - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_set_hash_addr(wots_addr, 0); - - /* Generate sk element. */ - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_prf_addr(sk, sk_seed, wots_addr, state_seeded); -} - -/** - * 4-way parallel version of wots_gen_sk; expects 4x as much space in sk + * Computes up the chains */ -static void wots_gen_skx4(unsigned char *skx4, const unsigned char *sk_seed, - uint32_t wots_addrx4[4 * 8], const hash_state *state_seeded) { - unsigned int j; - - /* Make sure that the hash address is actually zeroed. */ +static void gen_chains( + unsigned char *out, + const unsigned char *in, + unsigned int start[SPX_WOTS_LEN], + const unsigned int steps[SPX_WOTS_LEN], + const spx_ctx *ctx, + uint32_t addr[8]) { + uint32_t i, j, k, idx, watching; + int done; + unsigned char empty[SPX_N]; + unsigned char *bufs[4]; + uint32_t addrs[8 * 4]; + + int l; + uint16_t counts[SPX_WOTS_W] = { 0 }; + uint16_t idxs[SPX_WOTS_LEN]; + uint16_t total, newTotal; + + /* set addrs = {addr, addr, addr, addr} */ for (j = 0; j < 4; j++) { - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_set_hash_addr(wots_addrx4 + j * 8, 0); + memcpy(addrs + j * 8, addr, sizeof(uint32_t) * 8); } - /* Generate sk element. */ - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_prf_addrx4(skx4 + 0 * PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N, - skx4 + 1 * PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N, - skx4 + 2 * PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N, - skx4 + 3 * PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N, - sk_seed, wots_addrx4, - state_seeded); -} - -/** - * Computes the chaining function. - * out and in have to be n-byte arrays. - * - * Interprets in as start-th value of the chain. - * addr has to contain the address of the chain. - */ -static void gen_chain(unsigned char *out, const unsigned char *in, - unsigned int start, unsigned int steps, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *state_seeded) { - uint32_t i; - /* Initialize out with the value at position 'start'. */ - memcpy(out, in, PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N); + memcpy(out, in, SPX_WOTS_LEN * SPX_N); - /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_WOTS_W; i++) { - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_set_hash_addr(addr, i); - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_thash_1(out, out, pub_seed, addr, state_seeded); + /* Sort the chains in reverse order by steps using counting sort. */ + for (i = 0; i < SPX_WOTS_LEN; i++) { + counts[steps[i]]++; + } + total = 0; + for (l = SPX_WOTS_W - 1; l >= 0; l--) { + newTotal = counts[l] + total; + counts[l] = total; + total = newTotal; + } + for (i = 0; i < SPX_WOTS_LEN; i++) { + idxs[counts[steps[i]]] = (uint16_t)i; + counts[steps[i]]++; } -} -/** - * 4-way parallel version of gen_chain; expects 4x as much space in out, and - * 4x as much space in inx4. Assumes start and step identical across chains. - */ -static void gen_chainx4(unsigned char *outx4, const unsigned char *inx4, - unsigned int start, unsigned int steps, - const unsigned char *pub_seed, uint32_t addrx4[4 * 8], - const hash_state *state_seeded) { - uint32_t i; - unsigned int j; + /* We got our work cut out for us: do it! */ + for (i = 0; i < SPX_WOTS_LEN; i += 4) { + for (j = 0; j < 4 && i + j < SPX_WOTS_LEN; j++) { + idx = idxs[i + j]; + set_chain_addr(addrs + j * 8, idx); + bufs[j] = out + SPX_N * idx; + } - /* Initialize outx4 with the value at position 'start'. */ - memcpy(outx4, inx4, 4 * PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N); + /* As the chains are sorted in reverse order, we know that the first + * chain is the longest and the last one is the shortest. We keep + * an eye on whether the last chain is done and then on the one before, + * et cetera. */ + watching = 3; + done = 0; + while (i + watching >= SPX_WOTS_LEN) { + bufs[watching] = &empty[0]; + watching--; + } - /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_WOTS_W; i++) { - for (j = 0; j < 4; j++) { - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_set_hash_addr(addrx4 + j * 8, i); + for (k = 0;; k++) { + while (k == steps[idxs[i + watching]]) { + bufs[watching] = &empty[0]; + if (watching == 0) { + done = 1; + break; + } + watching--; + } + if (done) { + break; + } + for (j = 0; j < watching + 1; j++) { + set_hash_addr(addrs + j * 8, k + start[idxs[i + j]]); + } + + thashx4(bufs[0], bufs[1], bufs[2], bufs[3], + bufs[0], bufs[1], bufs[2], bufs[3], 1, ctx, addrs); } - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_thashx4_1(outx4 + 0 * PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N, - outx4 + 1 * PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N, - outx4 + 2 * PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N, - outx4 + 3 * PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N, - outx4 + 0 * PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N, - outx4 + 1 * PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N, - outx4 + 2 * PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N, - outx4 + 3 * PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N, - pub_seed, addrx4, - state_seeded); } } @@ -109,7 +107,8 @@ static void gen_chainx4(unsigned char *outx4, const unsigned char *inx4, * Interprets an array of bytes as integers in base w. * This only works when log_w is a divisor of 8. */ -static void base_w(unsigned int *output, const int out_len, const unsigned char *input) { +static void base_w(unsigned int *output, const int out_len, + const unsigned char *input) { int in = 0; int out = 0; unsigned char total = 0; @@ -122,119 +121,149 @@ static void base_w(unsigned int *output, const int out_len, const unsigned char in++; bits += 8; } - bits -= PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_WOTS_LOGW; - output[out] = (unsigned int)(total >> bits) & (PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_WOTS_W - 1); + bits -= SPX_WOTS_LOGW; + output[out] = (total >> bits) & (SPX_WOTS_W - 1); out++; } } /* Computes the WOTS+ checksum over a message (in base_w). */ -static void wots_checksum(unsigned int *csum_base_w, const unsigned int *msg_base_w) { +static void wots_checksum(unsigned int *csum_base_w, + const unsigned int *msg_base_w) { unsigned int csum = 0; - unsigned char csum_bytes[(PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_WOTS_LEN2 * PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_WOTS_LOGW + 7) / 8]; + unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; unsigned int i; /* Compute checksum. */ - for (i = 0; i < PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_WOTS_LEN1; i++) { - csum += PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_WOTS_W - 1 - msg_base_w[i]; + for (i = 0; i < SPX_WOTS_LEN1; i++) { + csum += SPX_WOTS_W - 1 - msg_base_w[i]; } /* Convert checksum to base_w. */ /* Make sure expected empty zero bits are the least significant bits. */ - csum = csum << (8 - ((PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_WOTS_LEN2 * PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_WOTS_LOGW) % 8)); - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); - base_w(csum_base_w, PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_WOTS_LEN2, csum_bytes); + csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); + ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); + base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); } /* Takes a message and derives the matching chain lengths. */ -static void chain_lengths(unsigned int *lengths, const unsigned char *msg) { - base_w(lengths, PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_WOTS_LEN1, msg); - wots_checksum(lengths + PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_WOTS_LEN1, lengths); +void chain_lengths(unsigned int *lengths, const unsigned char *msg) { + base_w(lengths, SPX_WOTS_LEN1, msg); + wots_checksum(lengths + SPX_WOTS_LEN1, lengths); } /** - * WOTS key generation. Takes a 32 byte sk_seed, expands it to WOTS private key - * elements and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. * * Writes the computed public key to 'pk'. */ -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_wots_gen_pk(unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *state_seeded) { +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]) { + unsigned int steps[SPX_WOTS_LEN]; + unsigned int start[SPX_WOTS_LEN]; uint32_t i; - unsigned int j; - uint32_t addrx4[4 * 8]; - unsigned char pkbuf[4 * PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N]; + chain_lengths(start, msg); - for (j = 0; j < 4; j++) { - memcpy(addrx4 + j * 8, addr, sizeof(uint32_t) * 8); - } - - /* The last iteration typically does not have complete set of 4 chains, - but because we use pkbuf, this is not an issue -- we still do as many - in parallel as possible. */ - for (i = 0; i < ((PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_WOTS_LEN + 3) & ~0x3); i += 4) { - for (j = 0; j < 4; j++) { - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_set_chain_addr(addrx4 + j * 8, i + j); - } - wots_gen_skx4(pkbuf, sk_seed, addrx4, state_seeded); - gen_chainx4(pkbuf, pkbuf, 0, PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_WOTS_W - 1, pub_seed, addrx4, state_seeded); - for (j = 0; j < 4; j++) { - if (i + j < PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_WOTS_LEN) { - memcpy(pk + (i + j)*PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N, pkbuf + j * PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N, PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N); - } - } + for (i = 0; i < SPX_WOTS_LEN; i++) { + steps[i] = SPX_WOTS_W - 1 - start[i]; } - // Get rid of unused argument variable. - (void)state_seeded; + gen_chains(pk, sig, start, steps, ctx, addr); } -/** - * Takes a n-byte message and the 32-byte sk_see to compute a signature 'sig'. +/* + * This generates 4 sequential WOTS public keys + * It also generates the WOTS signature if leaf_info indicates + * that we're signing with one of these WOTS keys */ -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_wots_sign(unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); +void wots_gen_leafx4(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info) { + struct leaf_info_x4 *info = v_info; + uint32_t *leaf_addr = info->leaf_addr; + uint32_t *pk_addr = info->pk_addr; + unsigned int i, j, k; + unsigned char pk_buffer[ 4 * SPX_WOTS_BYTES ]; + unsigned wots_offset = SPX_WOTS_BYTES; + unsigned char *buffer; + uint32_t wots_k_mask; + unsigned wots_sign_index; + + if (((leaf_idx ^ info->wots_sign_leaf) & ~3U) == 0) { + /* We're traversing the leaf that's signing; generate the WOTS */ + /* signature */ + wots_k_mask = 0; + wots_sign_index = info->wots_sign_leaf & 3; /* Which of of the 4 */ + /* 4 slots do the signatures come from */ + } else { + /* Nope, we're just generating pk's; turn off the signature logic */ + wots_k_mask = (uint32_t)~0; + wots_sign_index = 0; + } - for (i = 0; i < PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_WOTS_LEN; i++) { - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_set_chain_addr(addr, i); - wots_gen_sk(sig + i * PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N, sk_seed, addr, state_seeded); - gen_chain(sig + i * PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N, sig + i * PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N, 0, lengths[i], pub_seed, addr, state_seeded); + for (j = 0; j < 4; j++) { + set_keypair_addr( leaf_addr + j * 8, leaf_idx + j ); + set_keypair_addr( pk_addr + j * 8, leaf_idx + j ); } - // avoid unused argument - (void)state_seeded; -} + for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { + uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k to */ + /* the step if we're generating a signature, ~0 if we're not */ -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_WOTS_LEN]; - uint32_t i; + /* Start with the secret seed */ + for (j = 0; j < 4; j++) { + set_chain_addr(leaf_addr + j * 8, i); + set_hash_addr(leaf_addr + j * 8, 0); + set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTSPRF); + } + prf_addrx4(buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + buffer + 2 * wots_offset, + buffer + 3 * wots_offset, + ctx, leaf_addr); - chain_lengths(lengths, msg); + for (j = 0; j < 4; j++) { + set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTS); + } + + /* Iterate down the WOTS chain */ + for (k = 0;; k++) { + /* Check if one of the values we have needs to be saved as a */ + /* part of the WOTS signature */ + if (k == wots_k) { + memcpy( info->wots_sig + i * SPX_N, + buffer + wots_sign_index * wots_offset, SPX_N ); + } - for (i = 0; i < PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_WOTS_LEN; i++) { - PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_set_chain_addr(addr, i); - gen_chain(pk + i * PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N, sig + i * PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_N, - lengths[i], PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_WOTS_W - 1 - lengths[i], pub_seed, addr, - state_seeded); + /* Check if we hit the top of the chain */ + if (k == SPX_WOTS_W - 1) { + break; + } + + /* Iterate one step on all 4 chains */ + for (j = 0; j < 4; j++) { + set_hash_addr(leaf_addr + j * 8, k); + } + thashx4(buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + buffer + 2 * wots_offset, + buffer + 3 * wots_offset, + buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + buffer + 2 * wots_offset, + buffer + 3 * wots_offset, 1, ctx, leaf_addr); + } } - // avoid unused argument - (void)state_seeded; + /* Do the final thash to generate the public keys */ + thashx4(dest + 0 * SPX_N, + dest + 1 * SPX_N, + dest + 2 * SPX_N, + dest + 3 * SPX_N, + pk_buffer + 0 * wots_offset, + pk_buffer + 1 * wots_offset, + pk_buffer + 2 * wots_offset, + pk_buffer + 3 * wots_offset, SPX_WOTS_LEN, ctx, pk_addr); } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/wots.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/wots.h index b0eebb9fd6..4e7692eeef 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/wots.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/wots.h @@ -1,41 +1,25 @@ -#ifndef PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_WOTS_H -#define PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_WOTS_H +#ifndef SPX_WOTS_H +#define SPX_WOTS_H -#include "hash_state.h" -#include "params.h" #include -/** - * WOTS key generation. Takes a 32 byte seed for the private key, expands it to - * a full WOTS private key and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_wots_gen_pk( - unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -/** - * Takes a n-byte message and the 32-byte seed for the private key to compute a - * signature that is placed at 'sig'. - */ -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_wots_sign( - unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *hash_state_seeded); +#include "context.h" +#include "params.h" /** * Takes a WOTS signature and an n-byte message, computes a WOTS public key. * * Writes the computed public key to 'pk'. */ -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_wots_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); +#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]); + +/* + * Compute the chain lengths needed for a given message hash + */ +#define chain_lengths SPX_NAMESPACE(chain_lengths) +void chain_lengths(unsigned int *lengths, const unsigned char *msg); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/wotsx4.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/wotsx4.h new file mode 100644 index 0000000000..cd634f1743 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/wotsx4.h @@ -0,0 +1,41 @@ +#ifndef WOTSX4_H_ +#define WOTSX4_H_ + +#include + +#include "params.h" + +/* + * This is here to provide an interface to the internal wots_gen_leafx4 + * routine. While this routine is not referenced in the package outside of + * wots.c, it is called from the stand-alone benchmark code to characterize + * the performance + */ +struct leaf_info_x4 { + unsigned char *wots_sig; + uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ + uint32_t *wots_steps; + uint32_t leaf_addr[4 * 8]; + uint32_t pk_addr[4 * 8]; +}; + +/* Macro to set the leaf_info to something 'benign', that is, it would */ +/* run with the same time as it does during the real signing process */ +/* Used only by the benchmark code */ +#define INITIALIZE_LEAF_INFO_X4(info, addr, step_buffer) { \ + (info).wots_sig = 0; \ + (info).wots_sign_leaf = ~0; \ + (info).wots_steps = step_buffer; \ + int i; \ + for (i=0; i<4; i++) { \ + memcpy( &(info).leaf_addr[8*i], addr, 32 ); \ + memcpy( &(info).pk_addr[8*i], addr, 32 ); \ + } \ + } + +#define wots_gen_leafx4 SPX_NAMESPACE(wots_gen_leafx4) +void wots_gen_leafx4(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info); + +#endif /* WOTSX4_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/address.c b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/address.c index ce8106a5b5..b956e9cb29 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/address.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/address.c @@ -1,78 +1,91 @@ #include +#include #include "address.h" #include "params.h" #include "utils.h" -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]) { - int i; - - for (i = 0; i < 8; i++) { - PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_ull_to_bytes( - bytes + i * 4, 4, addr[i]); - } -} - -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_set_layer_addr( - uint32_t addr[8], uint32_t layer) { - addr[0] = layer; +/* + * Specify which level of Merkle tree (the "layer") we're working on + */ +void set_layer_addr(uint32_t addr[8], uint32_t layer) { + ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; } -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_set_tree_addr( - uint32_t addr[8], uint64_t tree) { - addr[1] = 0; - addr[2] = (uint32_t) (tree >> 32); - addr[3] = (uint32_t) tree; +/* + * Specify which Merkle tree within the level (the "tree address") we're working on + */ +void set_tree_addr(uint32_t addr[8], uint64_t tree) { + ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); } -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_set_type( - uint32_t addr[8], uint32_t type) { - addr[4] = type; +/* + * Specify the reason we'll use this address structure for, that is, what + * hash will we compute with it. This is used so that unrelated types of + * hashes don't accidentally get the same address structure. The type will be + * one of the SPX_ADDR_TYPE constants + */ +void set_type(uint32_t addr[8], uint32_t type) { + ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; } -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; +/* + * Copy the layer and tree fields of the address structure. This is used + * when we're doing multiple types of hashes within the same Merkle tree + */ +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); } /* These functions are used for OTS addresses. */ -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_set_keypair_addr( - uint32_t addr[8], uint32_t keypair) { - addr[5] = keypair; +/* + * Specify which Merkle leaf we're working on; that is, which OTS keypair + * we're talking about. + */ +void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { + ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; } -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; - out[5] = in[5]; +/* + * Copy the layer, tree and keypair fields of the address structure. This is + * used when we're doing multiple things within the same OTS keypair + */ +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); + ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; } -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_set_chain_addr( - uint32_t addr[8], uint32_t chain) { - addr[6] = chain; +/* + * Specify which Merkle chain within the OTS we're working with + * (the chain address) + */ +void set_chain_addr(uint32_t addr[8], uint32_t chain) { + ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; } -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_set_hash_addr( - uint32_t addr[8], uint32_t hash) { - addr[7] = hash; +/* + * Specify where in the Merkle chain we are +* (the hash address) + */ +void set_hash_addr(uint32_t addr[8], uint32_t hash) { + ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; } /* These functions are used for all hash tree addresses (including FORS). */ -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_set_tree_height( - uint32_t addr[8], uint32_t tree_height) { - addr[6] = tree_height; +/* + * Specify the height of the node in the Merkle/FORS tree we are in + * (the tree height) + */ +void set_tree_height(uint32_t addr[8], uint32_t tree_height) { + ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; } -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_set_tree_index( - uint32_t addr[8], uint32_t tree_index) { - addr[7] = tree_index; +/* + * Specify the distance from the left edge of the node in the Merkle/FORS tree + * (the tree index) + */ +void set_tree_index(uint32_t addr[8], uint32_t tree_index) { + u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/address.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/address.h index 22b0e4ee21..24a84eb40c 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/address.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/address.h @@ -1,50 +1,52 @@ -#ifndef PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_ADDRESS_H -#define PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_ADDRESS_H +#ifndef SPX_ADDRESS_H +#define SPX_ADDRESS_H #include -#define PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_ADDR_TYPE_WOTS 0 -#define PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_ADDR_TYPE_WOTSPK 1 -#define PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_ADDR_TYPE_HASHTREE 2 -#define PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_ADDR_TYPE_FORSTREE 3 -#define PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_ADDR_TYPE_FORSPK 4 +#include "params.h" -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]); +/* The hash types that are passed to set_type */ +#define SPX_ADDR_TYPE_WOTS 0 +#define SPX_ADDR_TYPE_WOTSPK 1 +#define SPX_ADDR_TYPE_HASHTREE 2 +#define SPX_ADDR_TYPE_FORSTREE 3 +#define SPX_ADDR_TYPE_FORSPK 4 +#define SPX_ADDR_TYPE_WOTSPRF 5 +#define SPX_ADDR_TYPE_FORSPRF 6 -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_set_layer_addr( - uint32_t addr[8], uint32_t layer); +#define set_layer_addr SPX_NAMESPACE(set_layer_addr) +void set_layer_addr(uint32_t addr[8], uint32_t layer); -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_set_tree_addr( - uint32_t addr[8], uint64_t tree); +#define set_tree_addr SPX_NAMESPACE(set_tree_addr) +void set_tree_addr(uint32_t addr[8], uint64_t tree); -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_set_type( - uint32_t addr[8], uint32_t type); +#define set_type SPX_NAMESPACE(set_type) +void set_type(uint32_t addr[8], uint32_t type); /* Copies the layer and tree part of one address into the other */ -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]); +#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); /* These functions are used for WOTS and FORS addresses. */ -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_set_keypair_addr( - uint32_t addr[8], uint32_t keypair); +#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) +void set_keypair_addr(uint32_t addr[8], uint32_t keypair); -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_set_chain_addr( - uint32_t addr[8], uint32_t chain); +#define set_chain_addr SPX_NAMESPACE(set_chain_addr) +void set_chain_addr(uint32_t addr[8], uint32_t chain); -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_set_hash_addr( - uint32_t addr[8], uint32_t hash); +#define set_hash_addr SPX_NAMESPACE(set_hash_addr) +void set_hash_addr(uint32_t addr[8], uint32_t hash); -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]); +#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); /* These functions are used for all hash tree addresses (including FORS). */ -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_set_tree_height( - uint32_t addr[8], uint32_t tree_height); +#define set_tree_height SPX_NAMESPACE(set_tree_height) +void set_tree_height(uint32_t addr[8], uint32_t tree_height); -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_set_tree_index( - uint32_t addr[8], uint32_t tree_index); +#define set_tree_index SPX_NAMESPACE(set_tree_index) +void set_tree_index(uint32_t addr[8], uint32_t tree_index); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/api.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/api.h index 0b14992b7d..93bf33c9b3 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/api.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/api.h @@ -4,15 +4,13 @@ #include #include - - -#define PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_CRYPTO_ALGNAME "SPHINCS+" +#define PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_CRYPTO_ALGNAME "SPHINCS+-haraka-128f-simple" #define PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_CRYPTO_SECRETKEYBYTES 64 #define PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_CRYPTO_PUBLICKEYBYTES 32 -#define PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_CRYPTO_BYTES 17088 -#define PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_CRYPTO_SEEDBYTES 48 +#define PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_CRYPTO_BYTES 17088 +#define PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_CRYPTO_SEEDBYTES 48 /* * Returns the length of a secret key, in bytes @@ -39,43 +37,41 @@ size_t PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_crypto_sign_seedbytes(void); * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] * Format pk: [root || PUB_SEED] */ -int PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed); +int PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); /* * Generates a SPHINCS+ key pair. * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] * Format pk: [root || PUB_SEED] */ -int PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk); +int PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); /** * Returns an array containing a detached signature. */ -int PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk); +int PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); /** * Verifies a detached signature and message under a given public key. */ -int PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk); +int PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, + const uint8_t *pk); /** * Returns an array containing the signature followed by the message. */ -int PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk); +int PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); /** * Verifies a given signature-message pair under a given public key. */ -int PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk); - +int PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/context.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/context.h new file mode 100644 index 0000000000..600dfb73c7 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/context.h @@ -0,0 +1,24 @@ +#ifndef SPX_CONTEXT_H +#define SPX_CONTEXT_H + +#include +#include + +#include "params.h" + +typedef struct { + uint8_t pub_seed[SPX_N]; + uint8_t sk_seed[SPX_N]; + + + uint64_t tweaked512_rc64[10][8]; + uint32_t tweaked256_rc32[10][8]; +} spx_ctx; + +#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) +void initialize_hash_function(spx_ctx *ctx); + +#define free_hash_function SPX_NAMESPACE(free_hash_function) +void free_hash_function(spx_ctx *ctx); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/context_haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/context_haraka.c new file mode 100644 index 0000000000..f1cd7e3664 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/context_haraka.c @@ -0,0 +1,11 @@ +#include "context.h" +#include "haraka.h" + +void initialize_hash_function(spx_ctx *ctx) { + tweak_constants(ctx); +} + +// we don't support heap-based haraka right now +void free_hash_function(spx_ctx *ctx) { + (void)ctx; // suppress unused variable warnings +} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/fors.c b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/fors.c index 9554ae72c3..96ca72e986 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/fors.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/fors.c @@ -2,58 +2,58 @@ #include #include -#include "address.h" #include "fors.h" + +#include "address.h" #include "hash.h" -#include "hash_state.h" #include "thash.h" #include "utils.h" +#include "utilsx1.h" -static void fors_gen_sk(unsigned char *sk, const unsigned char *sk_seed, - uint32_t fors_leaf_addr[8], const hash_state *hash_state_seeded) { - PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_prf_addr( - sk, sk_seed, fors_leaf_addr, hash_state_seeded); +static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + prf_addr(sk, ctx, fors_leaf_addr); } static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, - const unsigned char *pub_seed, - uint32_t fors_leaf_addr[8], - const hash_state *hash_state_seeded) { - PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_thash_1( - leaf, sk, pub_seed, fors_leaf_addr, hash_state_seeded); + const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + thash(leaf, sk, 1, ctx, fors_leaf_addr); } -static void fors_gen_leaf(unsigned char *leaf, const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx, const uint32_t fors_tree_addr[8], - const hash_state *hash_state_seeded) { - uint32_t fors_leaf_addr[8] = {0}; - - /* Only copy the parts that must be kept in fors_leaf_addr. */ - PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_copy_keypair_addr( - fors_leaf_addr, fors_tree_addr); - PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_set_type( - fors_leaf_addr, PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_set_tree_index( - fors_leaf_addr, addr_idx); - - fors_gen_sk(leaf, sk_seed, fors_leaf_addr, hash_state_seeded); - fors_sk_to_leaf(leaf, leaf, pub_seed, fors_leaf_addr, hash_state_seeded); +struct fors_gen_leaf_info { + uint32_t leaf_addrx[8]; +}; + +static void fors_gen_leafx1(unsigned char *leaf, + const spx_ctx *ctx, + uint32_t addr_idx, void *info) { + struct fors_gen_leaf_info *fors_info = info; + uint32_t *fors_leaf_addr = fors_info->leaf_addrx; + + /* Only set the parts that the caller doesn't set */ + set_tree_index(fors_leaf_addr, addr_idx); + set_type(fors_leaf_addr, SPX_ADDR_TYPE_FORSPRF); + fors_gen_sk(leaf, ctx, fors_leaf_addr); + + set_type(fors_leaf_addr, SPX_ADDR_TYPE_FORSTREE); + fors_sk_to_leaf(leaf, leaf, + ctx, fors_leaf_addr); } /** - * Interprets m as PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_FORS_HEIGHT-bit unsigned integers. - * Assumes m contains at least PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_FORS_TREES bits. - * Assumes indices has space for PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_FORS_TREES integers. + * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + * Assumes indices has space for SPX_FORS_TREES integers. */ static void message_to_indices(uint32_t *indices, const unsigned char *m) { unsigned int i, j; unsigned int offset = 0; - for (i = 0; i < PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_FORS_TREES; i++) { + for (i = 0; i < SPX_FORS_TREES; i++) { indices[i] = 0; - for (j = 0; j < PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_FORS_HEIGHT; j++) { - indices[i] ^= (((uint32_t)m[offset >> 3] >> (offset & 0x7)) & 0x1) << j; + for (j = 0; j < SPX_FORS_HEIGHT; j++) { + indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); offset++; } } @@ -61,55 +61,51 @@ static void message_to_indices(uint32_t *indices, const unsigned char *m) { /** * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_FORS_TREES bits. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. */ -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_fors_sign( - unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *hash_state_seeded) { - uint32_t indices[PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_FORS_TREES]; - unsigned char roots[PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_FORS_TREES * PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_N]; +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; uint32_t fors_tree_addr[8] = {0}; + struct fors_gen_leaf_info fors_info = {0}; + uint32_t *fors_leaf_addr = fors_info.leaf_addrx; uint32_t fors_pk_addr[8] = {0}; uint32_t idx_offset; unsigned int i; - PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_copy_keypair_addr( - fors_tree_addr, fors_addr); - PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_copy_keypair_addr( - fors_pk_addr, fors_addr); + copy_keypair_addr(fors_tree_addr, fors_addr); + copy_keypair_addr(fors_leaf_addr, fors_addr); - PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_set_type( - fors_tree_addr, PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_set_type( - fors_pk_addr, PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_ADDR_TYPE_FORSPK); + copy_keypair_addr(fors_pk_addr, fors_addr); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); message_to_indices(indices, m); - for (i = 0; i < PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_FORS_TREES; i++) { - idx_offset = i * (1 << PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_FORS_HEIGHT); + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); - PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_set_tree_height( - fors_tree_addr, 0); - PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_set_tree_index( - fors_tree_addr, indices[i] + idx_offset); + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); /* Include the secret key part that produces the selected leaf node. */ - fors_gen_sk(sig, sk_seed, fors_tree_addr, hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_N; + fors_gen_sk(sig, ctx, fors_tree_addr); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + sig += SPX_N; /* Compute the authentication path for this leaf node. */ - PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_treehash_FORS_HEIGHT( - roots + i * PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_N, sig, sk_seed, pub_seed, - indices[i], idx_offset, fors_gen_leaf, fors_tree_addr, - hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_N * PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_FORS_HEIGHT; + treehashx1(roots + i * SPX_N, sig, ctx, + indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx1, + fors_tree_addr, &fors_info); + + sig += SPX_N * SPX_FORS_HEIGHT; } /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_thash_FORS_TREES( - pk, roots, pub_seed, fors_pk_addr, hash_state_seeded); + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); } /** @@ -117,45 +113,44 @@ void PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_fors_sign( * This can be used for verification by comparing to a known public key, or to * subsequently verify a signature on the derived public key. The latter is the * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_FORS_TREES bits. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. */ -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_fors_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, const uint32_t fors_addr[8], - const hash_state *hash_state_seeded) { - uint32_t indices[PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_FORS_TREES]; - unsigned char roots[PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_FORS_TREES * PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_N]; - unsigned char leaf[PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_N]; +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + unsigned char leaf[SPX_N]; uint32_t fors_tree_addr[8] = {0}; uint32_t fors_pk_addr[8] = {0}; uint32_t idx_offset; unsigned int i; - PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_copy_keypair_addr(fors_tree_addr, fors_addr); - PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_copy_keypair_addr(fors_pk_addr, fors_addr); + copy_keypair_addr(fors_tree_addr, fors_addr); + copy_keypair_addr(fors_pk_addr, fors_addr); - PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_set_type(fors_tree_addr, PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_set_type(fors_pk_addr, PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_ADDR_TYPE_FORSPK); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); message_to_indices(indices, m); - for (i = 0; i < PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_FORS_TREES; i++) { - idx_offset = i * (1 << PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_FORS_HEIGHT); + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); - PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_set_tree_height(fors_tree_addr, 0); - PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_set_tree_index(fors_tree_addr, indices[i] + idx_offset); + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); /* Derive the leaf from the included secret key part. */ - fors_sk_to_leaf(leaf, sig, pub_seed, fors_tree_addr, hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_N; + fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); + sig += SPX_N; /* Derive the corresponding root node of this tree. */ - PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_compute_root(roots + i * PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_N, leaf, indices[i], idx_offset, sig, - PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_FORS_HEIGHT, pub_seed, fors_tree_addr, hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_N * PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_FORS_HEIGHT; + compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, + sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); + sig += SPX_N * SPX_FORS_HEIGHT; } /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_thash_FORS_TREES(pk, roots, pub_seed, fors_pk_addr, hash_state_seeded); + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/fors.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/fors.h index 952c94c2b5..509140a178 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/fors.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/fors.h @@ -1,32 +1,32 @@ -#ifndef PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_FORS_H -#define PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_FORS_H +#ifndef SPX_FORS_H +#define SPX_FORS_H #include -#include "hash_state.h" +#include "context.h" #include "params.h" /** * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_FORS_TREES bits. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. */ -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_fors_sign( - unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *hash_state_seeded); +#define fors_sign SPX_NAMESPACE(fors_sign) +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); /** * Derives the FORS public key from a signature. * This can be used for verification by comparing to a known public key, or to * subsequently verify a signature on the derived public key. The latter is the * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_FORS_TREES bits. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. */ -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_fors_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, const uint32_t fors_addr[8], - const hash_state *hash_state_seeded); +#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/haraka.c index 1f54d8e035..a4944913b5 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/haraka.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/haraka.c @@ -6,12 +6,13 @@ * by Thomas Pornin */ -#include #include +#include #include #include #include "haraka.h" +#include "utils.h" #define HARAKAS_RATE 32 @@ -656,76 +657,62 @@ static void interleave_constant32(uint32_t *out, const unsigned char *in) { br_aes_ct_ortho(out); } -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_tweak_constants( - harakactx *state, - const unsigned char *pk_seed, const unsigned char *sk_seed, - unsigned long long seed_length) { +void tweak_constants(spx_ctx *ctx) { unsigned char buf[40 * 16]; int i; /* Use the standard constants to generate tweaked ones. */ - memcpy((uint8_t *)state->tweaked512_rc64, (uint8_t *)haraka512_rc64, 40 * 16); - - /* Constants for sk.seed */ - if (sk_seed != NULL) { - PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_haraka_S( - buf, 40 * 16, sk_seed, seed_length, state); - - /* Interleave constants */ - for (i = 0; i < 10; i++) { - interleave_constant32(state->tweaked256_rc32_sseed[i], buf + 32 * i); - } - } + memcpy((uint8_t *)ctx->tweaked512_rc64, (uint8_t *)haraka512_rc64, 40 * 16); /* Constants for pk.seed */ - PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_haraka_S( - buf, 40 * 16, pk_seed, seed_length, state); + haraka_S(buf, 40 * 16, ctx->pub_seed, SPX_N, ctx); for (i = 0; i < 10; i++) { - interleave_constant32(state->tweaked256_rc32[i], buf + 32 * i); - interleave_constant(state->tweaked512_rc64[i], buf + 64 * i); + interleave_constant32(ctx->tweaked256_rc32[i], buf + 32 * i); + interleave_constant(ctx->tweaked512_rc64[i], buf + 64 * i); } } -static void haraka_S_absorb(unsigned char *s, +static void haraka_S_absorb(unsigned char *s, unsigned int r, const unsigned char *m, unsigned long long mlen, - unsigned char p, const harakactx *state) { + unsigned char p, const spx_ctx *ctx) { unsigned long long i; - unsigned char t[HARAKAS_RATE]; + PQCLEAN_VLA(uint8_t, t, r); - while (mlen >= HARAKAS_RATE) { + while (mlen >= r) { /* XOR block to state */ - for (i = 0; i < HARAKAS_RATE; ++i) { + for (i = 0; i < r; ++i) { s[i] ^= m[i]; } - PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_haraka512_perm(s, s, state); - mlen -= HARAKAS_RATE; - m += HARAKAS_RATE; + haraka512_perm(s, s, ctx); + mlen -= r; + m += r; } - for (i = 0; i < HARAKAS_RATE; ++i) { + for (i = 0; i < r; ++i) { t[i] = 0; } for (i = 0; i < mlen; ++i) { t[i] = m[i]; } t[i] = p; - t[HARAKAS_RATE - 1] |= 128; - for (i = 0; i < HARAKAS_RATE; ++i) { + t[r - 1] |= 128; + for (i = 0; i < r; ++i) { s[i] ^= t[i]; } } static void haraka_S_squeezeblocks(unsigned char *h, unsigned long long nblocks, - unsigned char *s, const harakactx *state) { + unsigned char *s, unsigned int r, + const spx_ctx *ctx) { while (nblocks > 0) { - PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_haraka512_perm(s, s, state); + haraka512_perm(s, s, ctx); memcpy(h, s, HARAKAS_RATE); - h += HARAKAS_RATE; + h += r; nblocks--; } } -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_haraka_S_inc_init(uint8_t *s_inc) { +void haraka_S_inc_init(uint8_t *s_inc) { size_t i; for (i = 0; i < 64; i++) { @@ -734,7 +721,8 @@ void PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_haraka_S_inc_init(uint8_t *s_inc) { s_inc[64] = 0; } -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, const harakactx *state) { +void haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, + const spx_ctx *ctx) { size_t i; /* Recall that s_inc[64] is the non-absorbed bytes xored into the state */ @@ -745,19 +733,19 @@ void PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_haraka_S_inc_absorb(uint8_t *s_inc, c s_inc[s_inc[64] + i] ^= m[i]; } mlen -= (size_t)(HARAKAS_RATE - s_inc[64]); - m += HARAKAS_RATE - s_inc[64]; + m += HARAKAS_RATE - (uint8_t)s_inc[64]; s_inc[64] = 0; - PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_haraka512_perm(s_inc, s_inc, state); + haraka512_perm(s_inc, s_inc, ctx); } for (i = 0; i < mlen; i++) { s_inc[s_inc[64] + i] ^= m[i]; } - s_inc[64] = (uint8_t)(mlen + s_inc[64]); + s_inc[64] += (uint8_t)mlen; } -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_haraka_S_inc_finalize(uint8_t *s_inc) { +void haraka_S_inc_finalize(uint8_t *s_inc) { /* After haraka_S_inc_absorb, we are guaranteed that s_inc[64] < HARAKAS_RATE, so we can always use one more byte for p in the current state. */ s_inc[s_inc[64]] ^= 0x1F; @@ -765,22 +753,23 @@ void PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_haraka_S_inc_finalize(uint8_t *s_inc) s_inc[64] = 0; } -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, const harakactx *state) { - uint8_t i; +void haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, + const spx_ctx *ctx) { + size_t i; /* First consume any bytes we still have sitting around */ for (i = 0; i < outlen && i < s_inc[64]; i++) { /* There are s_inc[64] bytes left, so r - s_inc[64] is the first available byte. We consume from there, i.e., up to r. */ - out[i] = s_inc[(HARAKAS_RATE - s_inc[64] + i)]; + out[i] = (uint8_t)s_inc[(HARAKAS_RATE - s_inc[64] + i)]; } out += i; outlen -= i; - s_inc[64] = (uint8_t)(s_inc[64] - i); + s_inc[64] -= (uint8_t)i; /* Then squeeze the remaining necessary blocks */ while (outlen > 0) { - PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_haraka512_perm(s_inc, s_inc, state); + haraka512_perm(s_inc, s_inc, ctx); for (i = 0; i < outlen && i < HARAKAS_RATE; i++) { out[i] = s_inc[i]; @@ -791,7 +780,9 @@ void PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_haraka_S_inc_squeeze(uint8_t *out, si } } -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_haraka_S(unsigned char *out, unsigned long long outlen, const unsigned char *in, unsigned long long inlen, const harakactx *state) { +void haraka_S(unsigned char *out, unsigned long long outlen, + const unsigned char *in, unsigned long long inlen, + const spx_ctx *ctx) { unsigned long long i; unsigned char s[64]; unsigned char d[32]; @@ -799,20 +790,21 @@ void PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_haraka_S(unsigned char *out, unsigned for (i = 0; i < 64; i++) { s[i] = 0; } - haraka_S_absorb(s, in, inlen, 0x1F, state); + haraka_S_absorb(s, 32, in, inlen, 0x1F, ctx); - haraka_S_squeezeblocks(out, outlen / 32, s, state); + haraka_S_squeezeblocks(out, outlen / 32, s, 32, ctx); out += (outlen / 32) * 32; if (outlen % 32) { - haraka_S_squeezeblocks(d, 1, s, state); + haraka_S_squeezeblocks(d, 1, s, 32, ctx); for (i = 0; i < outlen % 32; i++) { out[i] = d[i]; } } } -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_haraka512_perm(unsigned char *out, const unsigned char *in, const harakactx *state) { +void haraka512_perm(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx) { uint32_t w[16]; uint64_t q[8], tmp_q; unsigned int i, j; @@ -829,7 +821,7 @@ void PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_haraka512_perm(unsigned char *out, co br_aes_ct64_bitslice_Sbox(q); shift_rows(q); mix_columns(q); - add_round_key(q, state->tweaked512_rc64[2 * i + j]); + add_round_key(q, ctx->tweaked512_rc64[2 * i + j]); } /* Mix states */ for (j = 0; j < 8; j++) { @@ -857,12 +849,12 @@ void PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_haraka512_perm(unsigned char *out, co br_range_enc32le(out, w, 16); } -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_haraka512(unsigned char *out, const unsigned char *in, const harakactx *state) { +void haraka512(unsigned char *out, const unsigned char *in, const spx_ctx *ctx) { int i; unsigned char buf[64]; - PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_haraka512_perm(buf, in, state); + haraka512_perm(buf, in, ctx); /* Feed-forward */ for (i = 0; i < 64; i++) { buf[i] = buf[i] ^ in[i]; @@ -876,50 +868,8 @@ void PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_haraka512(unsigned char *out, const u } -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_haraka256(unsigned char *out, const unsigned char *in, const harakactx *state) { - uint32_t q[8], tmp_q; - int i, j; - - for (i = 0; i < 4; i++) { - q[2 * i] = br_dec32le(in + 4 * i); - q[2 * i + 1] = br_dec32le(in + 4 * i + 16); - } - br_aes_ct_ortho(q); - - /* AES rounds */ - for (i = 0; i < 5; i++) { - for (j = 0; j < 2; j++) { - br_aes_ct_bitslice_Sbox(q); - shift_rows32(q); - mix_columns32(q); - add_round_key32(q, state->tweaked256_rc32[2 * i + j]); - } - - /* Mix states */ - for (j = 0; j < 8; j++) { - tmp_q = q[j]; - q[j] = (tmp_q & 0x81818181) | - (tmp_q & 0x02020202) << 1 | - (tmp_q & 0x04040404) << 2 | - (tmp_q & 0x08080808) << 3 | - (tmp_q & 0x10101010) >> 3 | - (tmp_q & 0x20202020) >> 2 | - (tmp_q & 0x40404040) >> 1; - } - } - - br_aes_ct_ortho(q); - for (i = 0; i < 4; i++) { - br_enc32le(out + 4 * i, q[2 * i]); - br_enc32le(out + 4 * i + 16, q[2 * i + 1]); - } - - for (i = 0; i < 32; i++) { - out[i] ^= in[i]; - } -} - -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_haraka256_sk(unsigned char *out, const unsigned char *in, const harakactx *state) { +void haraka256(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx) { uint32_t q[8], tmp_q; int i, j; @@ -935,7 +885,7 @@ void PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_haraka256_sk(unsigned char *out, cons br_aes_ct_bitslice_Sbox(q); shift_rows32(q); mix_columns32(q); - add_round_key32(q, state->tweaked256_rc32_sseed[2 * i + j]); + add_round_key32(q, ctx->tweaked256_rc32[2 * i + j]); } /* Mix states */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/haraka.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/haraka.h index 149d639934..737cb6065f 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/haraka.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/haraka.h @@ -1,40 +1,42 @@ -#ifndef PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_HARAKA_H -#define PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_HARAKA_H +#ifndef SPX_HARAKA_H +#define SPX_HARAKA_H -#include -#include - -typedef struct { - uint64_t tweaked512_rc64[10][8]; - uint32_t tweaked256_rc32[10][8]; - uint32_t tweaked256_rc32_sseed[10][8]; -} harakactx; +#include "context.h" +#include "params.h" /* Tweak constants with seed */ -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_tweak_constants( - harakactx *state, - const unsigned char *pk_seed, const unsigned char *sk_seed, - unsigned long long seed_length); +#define tweak_constants SPX_NAMESPACE(tweak_constants) +void tweak_constants(spx_ctx *ctx); /* Haraka Sponge */ -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_haraka_S_inc_init(uint8_t *s_inc); -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, const harakactx *state); -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_haraka_S_inc_finalize(uint8_t *s_inc); -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, const harakactx *state); -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_haraka_S( - unsigned char *out, unsigned long long outlen, - const unsigned char *in, unsigned long long inlen, const harakactx *state); +#define haraka_S_inc_init SPX_NAMESPACE(haraka_S_inc_init) +void haraka_S_inc_init(uint8_t *s_inc); +#define haraka_S_inc_absorb SPX_NAMESPACE(haraka_S_inc_absorb) +void haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, + const spx_ctx *ctx); +#define haraka_S_inc_finalize SPX_NAMESPACE(haraka_S_inc_finalize) +void haraka_S_inc_finalize(uint8_t *s_inc); +#define haraka_S_inc_squeeze SPX_NAMESPACE(haraka_S_inc_squeeze) +void haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, + const spx_ctx *ctx); +#define haraka_S SPX_NAMESPACE(haraka_S) +void haraka_S(unsigned char *out, unsigned long long outlen, + const unsigned char *in, unsigned long long inlen, + const spx_ctx *ctx); /* Applies the 512-bit Haraka permutation to in. */ -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_haraka512_perm(unsigned char *out, const unsigned char *in, const harakactx *state); +#define haraka512_perm SPX_NAMESPACE(haraka512_perm) +void haraka512_perm(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx); /* Implementation of Haraka-512 */ -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_haraka512(unsigned char *out, const unsigned char *in, const harakactx *state); +#define haraka512 SPX_NAMESPACE(haraka512) +void haraka512(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx); /* Implementation of Haraka-256 */ -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_haraka256(unsigned char *out, const unsigned char *in, const harakactx *state); - -/* Implementation of Haraka-256 using sk.seed constants */ -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_haraka256_sk(unsigned char *out, const unsigned char *in, const harakactx *state); +#define haraka256 SPX_NAMESPACE(haraka256) +void haraka256(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/haraka_offsets.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/haraka_offsets.h new file mode 100644 index 0000000000..7c062272a0 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/haraka_offsets.h @@ -0,0 +1,21 @@ +#ifndef HARAKA_OFFSETS_H_ +#define HARAKA_OFFSETS_H_ + +/* + * Offsets of various fields in the address structure when we use Haraka as + * the Sphincs+ hash function + */ + +#define SPX_OFFSET_LAYER 3 /* The byte used to specify the Merkle tree layer */ +#define SPX_OFFSET_TREE 8 /* The start of the 8 byte field used to specify the tree */ +#define SPX_OFFSET_TYPE 19 /* The byte used to specify the hash type (reason) */ +#define SPX_OFFSET_KP_ADDR2 22 /* The high byte used to specify the key pair (which one-time signature) */ +#define SPX_OFFSET_KP_ADDR1 23 /* The low byte used to specify the key pair */ +#define SPX_OFFSET_CHAIN_ADDR 27 /* The byte used to specify the chain address (which Winternitz chain) */ +#define SPX_OFFSET_HASH_ADDR 31 /* The byte used to specify the hash address (where in the Winternitz chain) */ +#define SPX_OFFSET_TREE_HGT 27 /* The byte used to specify the height of this node in the FORS or Merkle tree */ +#define SPX_OFFSET_TREE_INDEX 28 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ + +#define SPX_HARAKA 1 + +#endif /* HARAKA_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/hash.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/hash.h index 09f673ea19..f7c87d4c3c 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/hash.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/hash.h @@ -1,31 +1,28 @@ -#ifndef PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_HASH_H -#define PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_HASH_H - -#include "hash_state.h" +#ifndef SPX_HASH_H +#define SPX_HASH_H #include #include -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_initialize_hash_function( - hash_state *hash_state_seeded, - const unsigned char *pub_seed, const unsigned char *sk_seed); +#include "context.h" +#include "params.h" + +#define prf_addr SPX_NAMESPACE(prf_addr) +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]); -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_destroy_hash_function(hash_state *hash_state_seeded); +#define gen_message_random SPX_NAMESPACE(gen_message_random) +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded); +#define hash_message SPX_NAMESPACE(hash_message) +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/hash_haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/hash_haraka.c index c58594b1be..750a67423b 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/hash_haraka.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/hash_haraka.c @@ -2,58 +2,44 @@ #include #include "address.h" -#include "haraka.h" -#include "hash.h" #include "params.h" #include "utils.h" -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_initialize_hash_function( - hash_state *hash_state_seeded, - const unsigned char *pub_seed, const unsigned char *sk_seed) { - PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_tweak_constants(hash_state_seeded, pub_seed, sk_seed, PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_N); -} - -/* The haraka implementation is stack based and won't be replaced in PQClean/OQS, - so we don't need to do anything */ -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_destroy_hash_function( - hash_state *hash_state_seeded) { // NOLINT(readability-non-const-parameter) - (void)hash_state_seeded; -} +#include "haraka.h" +#include "hash.h" /* - * Computes PRF(key, addr), given a secret key of PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_N bytes and an address + * Computes PRF(key, addr), given a secret key of SPX_N bytes and an address */ -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded) { - unsigned char buf[PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_ADDR_BYTES]; - /* Since PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_N may be smaller than 32, we need a temporary buffer. */ +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]) { + /* Since SPX_N may be smaller than 32, we need temporary buffers. */ unsigned char outbuf[32]; + unsigned char buf[64] = {0}; - (void)key; /* Suppress an 'unused parameter' warning. */ + memcpy(buf, addr, SPX_ADDR_BYTES); + memcpy(buf + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); - PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_addr_to_bytes(buf, addr); - PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_haraka256_sk(outbuf, buf, hash_state_seeded); - memcpy(out, outbuf, PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_N); + haraka512(outbuf, (const void *)buf, ctx); + memcpy(out, outbuf, SPX_N); } /** * Computes the message-dependent randomness R, using a secret seed and an * optional randomization value as well as the message. */ -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded) { +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { uint8_t s_inc[65]; - PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_haraka_S_inc_init(s_inc); - PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_haraka_S_inc_absorb(s_inc, sk_prf, PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_N, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_haraka_S_inc_absorb(s_inc, optrand, PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_N, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_haraka_S_inc_absorb(s_inc, m, mlen, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_haraka_S_inc_finalize(s_inc); - PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_haraka_S_inc_squeeze(R, PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_N, s_inc, hash_state_seeded); + haraka_S_inc_init(s_inc); + haraka_S_inc_absorb(s_inc, sk_prf, SPX_N, ctx); + haraka_S_inc_absorb(s_inc, optrand, SPX_N, ctx); + haraka_S_inc_absorb(s_inc, m, mlen, ctx); + haraka_S_inc_finalize(s_inc); + haraka_S_inc_squeeze(R, SPX_N, s_inc, ctx); } /** @@ -61,36 +47,35 @@ void PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_gen_message_random( * Outputs the message digest and the index of the leaf. The index is split in * the tree index and the leaf index, for convenient copying to an address. */ -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded) { -#define PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_TREE_BITS (PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_TREE_HEIGHT * (PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_D - 1)) -#define PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_TREE_BYTES ((PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_TREE_BITS + 7) / 8) -#define PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_LEAF_BITS PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_TREE_HEIGHT -#define PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_LEAF_BYTES ((PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_LEAF_BITS + 7) / 8) -#define PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_DGST_BYTES (PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_FORS_MSG_BYTES + PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_TREE_BYTES + PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_LEAF_BYTES) +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { +#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) +#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) +#define SPX_LEAF_BITS SPX_TREE_HEIGHT +#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) +#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) - unsigned char buf[PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_DGST_BYTES]; + unsigned char buf[SPX_DGST_BYTES]; unsigned char *bufp = buf; uint8_t s_inc[65]; - PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_haraka_S_inc_init(s_inc); - PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_haraka_S_inc_absorb(s_inc, R, PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_N, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_haraka_S_inc_absorb(s_inc, pk + PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_N, PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_N, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_haraka_S_inc_absorb(s_inc, m, mlen, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_haraka_S_inc_finalize(s_inc); - PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_haraka_S_inc_squeeze(buf, PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_DGST_BYTES, s_inc, hash_state_seeded); + haraka_S_inc_init(s_inc); + haraka_S_inc_absorb(s_inc, R, SPX_N, ctx); + haraka_S_inc_absorb(s_inc, pk + SPX_N, SPX_N, ctx); // Only absorb root part of pk + haraka_S_inc_absorb(s_inc, m, mlen, ctx); + haraka_S_inc_finalize(s_inc); + haraka_S_inc_squeeze(buf, SPX_DGST_BYTES, s_inc, ctx); + + memcpy(digest, bufp, SPX_FORS_MSG_BYTES); + bufp += SPX_FORS_MSG_BYTES; - memcpy(digest, bufp, PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_FORS_MSG_BYTES); - bufp += PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_FORS_MSG_BYTES; - *tree = PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_bytes_to_ull(bufp, PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_TREE_BYTES); - *tree &= (~(uint64_t)0) >> (64 - PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_TREE_BITS); - bufp += PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_TREE_BYTES; + *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); + *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); + bufp += SPX_TREE_BYTES; - *leaf_idx = (uint32_t)PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_bytes_to_ull( - bufp, PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_LEAF_BYTES); - *leaf_idx &= (~(uint32_t)0) >> (32 - PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_LEAF_BITS); + *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); + *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/hash_state.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/hash_state.h deleted file mode 100644 index 5adb1d9a22..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/hash_state.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef SPX_HASH_STATE_H -#define SPX_HASH_STATE_H - -/** - * Defines the type of the hash function state. - * - * Don't be fooled into thinking this instance of SPHINCS+ isn't stateless! - * - * From Section 7.2.2 from the SPHINCS+ round-2 specification: - * - * Each of the instances of the tweakable hash function take PK.seed as its - * first input, which is constant for a given key pair – and, thus, across - * a single signature. This leads to a lot of redundant computation. To remedy - * this, we pad PK.seed to the length of a full 64-byte SHA-256 input block. - * Because of the Merkle-DamgÃ¥rd construction that underlies SHA-256, this - * allows for reuse of the intermediate SHA-256 state after the initial call to - * the compression function which improves performance. - * - * We pass this hash state around in functions, because otherwise we need to - * have a global variable. - */ - -#include "haraka.h" -#define hash_state harakactx - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/merkle.c b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/merkle.c new file mode 100644 index 0000000000..0c1479fd93 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/merkle.c @@ -0,0 +1,59 @@ +#include +#include + +#include "address.h" +#include "merkle.h" +#include "params.h" +#include "utils.h" +#include "utilsx1.h" +#include "wots.h" +#include "wotsx1.h" + +/* + * This generates a Merkle signature (WOTS signature followed by the Merkle + * authentication path). This is in this file because most of the complexity + * is involved with the WOTS signature; the Merkle authentication path logic + * is mostly hidden in treehashx4 + */ +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf) { + unsigned char *auth_path = sig + SPX_WOTS_BYTES; + struct leaf_info_x1 info = { 0 }; + unsigned steps[ SPX_WOTS_LEN ]; + + info.wots_sig = sig; + chain_lengths(steps, root); + info.wots_steps = steps; + + set_type(&tree_addr[0], SPX_ADDR_TYPE_HASHTREE); + set_type(&info.pk_addr[0], SPX_ADDR_TYPE_WOTSPK); + copy_subtree_addr(&info.leaf_addr[0], wots_addr); + copy_subtree_addr(&info.pk_addr[0], wots_addr); + + info.wots_sign_leaf = idx_leaf; + + treehashx1(root, auth_path, ctx, + idx_leaf, 0, + SPX_TREE_HEIGHT, + wots_gen_leafx1, + tree_addr, &info); +} + +/* Compute root node of the top-most subtree. */ +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { + /* We do not need the auth path in key generation, but it simplifies the + code to have just one treehash routine that computes both root and path + in one function. */ + unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; + uint32_t top_tree_addr[8] = {0}; + uint32_t wots_addr[8] = {0}; + + set_layer_addr(top_tree_addr, SPX_D - 1); + set_layer_addr(wots_addr, SPX_D - 1); + + merkle_sign(auth_path, root, ctx, + wots_addr, top_tree_addr, + (uint32_t)~0 /* ~0 means "don't bother generating an auth path */ ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/merkle.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/merkle.h new file mode 100644 index 0000000000..769cf2e970 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/merkle.h @@ -0,0 +1,21 @@ +#ifndef MERKLE_H_ +#define MERKLE_H_ + +#include + +#include "context.h" +#include "params.h" + +/* Generate a Merkle signature (WOTS signature followed by the Merkle */ +/* authentication path) */ +#define merkle_sign SPX_NAMESPACE(merkle_sign) +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf); + +/* Compute the root node of the top-most subtree. */ +#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); + +#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/nistapi.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/nistapi.h new file mode 100644 index 0000000000..3cb71afad4 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/nistapi.h @@ -0,0 +1,87 @@ +#ifndef SPX_API_H +#define SPX_API_H + +#include +#include + +#include "params.h" + +#define CRYPTO_ALGNAME "SPHINCS+" + +#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES +#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES +#define CRYPTO_BYTES SPX_BYTES +#define CRYPTO_SEEDBYTES (3*SPX_N) + +/* + * Returns the length of a secret key, in bytes + */ +#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) +size_t crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) +size_t crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) +size_t crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) +size_t crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +#define crypto_sign SPX_NAMESPACE(crypto_sign) +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/params.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/params.h index 6f17b1f7af..2ca67d3cf2 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/params.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/params.h @@ -1,53 +1,56 @@ -#ifndef PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_PARAMS_H -#define PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_PARAMS_H +#ifndef SPX_PARAMS_H +#define SPX_PARAMS_H + +#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_##s /* Hash output length in bytes. */ -#define PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_N 16 +#define SPX_N 16 /* Height of the hypertree. */ -#define PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_FULL_HEIGHT 66 +#define SPX_FULL_HEIGHT 66 /* Number of subtree layer. */ -#define PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_D 22 +#define SPX_D 22 /* FORS tree dimensions. */ -#define PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_FORS_HEIGHT 6 -#define PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_FORS_TREES 33 +#define SPX_FORS_HEIGHT 6 +#define SPX_FORS_TREES 33 /* Winternitz parameter, */ -#define PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_WOTS_W 16 +#define SPX_WOTS_W 16 /* The hash function is defined by linking a different hash.c file, as opposed to setting a #define constant. */ /* For clarity */ -#define PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_ADDR_BYTES 32 +#define SPX_ADDR_BYTES 32 /* WOTS parameters. */ -#define PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_WOTS_LOGW 4 +#define SPX_WOTS_LOGW 4 -#define PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_WOTS_LEN1 (8 * PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_N / PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_WOTS_LOGW) +#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) -/* PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#define PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_WOTS_LEN2 3 +/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ +#define SPX_WOTS_LEN2 3 -#define PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_WOTS_LEN (PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_WOTS_LEN1 + PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_WOTS_LEN2) -#define PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_WOTS_BYTES (PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_WOTS_LEN * PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_N) -#define PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_WOTS_PK_BYTES PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_WOTS_BYTES +#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) +#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) +#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES /* Subtree size. */ -#define PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_TREE_HEIGHT (PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_FULL_HEIGHT / PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_D) +#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) + +//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT +// #error SPX_D should always divide SPX_FULL_HEIGHT +//#endif /* FORS parameters. */ -#define PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_FORS_MSG_BYTES ((PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_FORS_TREES + 7) / 8) -#define PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_FORS_BYTES ((PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_FORS_HEIGHT + 1) * PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_FORS_TREES * PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_N) -#define PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_FORS_PK_BYTES PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_N +#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) +#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) +#define SPX_FORS_PK_BYTES SPX_N /* Resulting SPX sizes. */ -#define PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_BYTES (PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_N + PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_FORS_BYTES + PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_D * PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_WOTS_BYTES +\ - PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_FULL_HEIGHT * PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_N) -#define PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_PK_BYTES (2 * PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_N) -#define PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_SK_BYTES (2 * PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_N + PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_PK_BYTES) - -/* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ -#define PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_OPTRAND_BYTES 32 +#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ + SPX_FULL_HEIGHT * SPX_N) +#define SPX_PK_BYTES (2 * SPX_N) +#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) + +#include "haraka_offsets.h" #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/sign.c b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/sign.c index 67b1b9cea4..9d0c7d1b22 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/sign.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/sign.c @@ -3,72 +3,43 @@ #include #include "address.h" -#include "api.h" +#include "context.h" #include "fors.h" #include "hash.h" -#include "hash_state.h" +#include "merkle.h" +#include "nistapi.h" #include "params.h" #include "randombytes.h" #include "thash.h" #include "utils.h" #include "wots.h" -/** - * Computes the leaf at a given address. First generates the WOTS key pair, - * then computes leaf by hashing horizontally. - */ -static void wots_gen_leaf(unsigned char *leaf, const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx, const uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - unsigned char pk[PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_WOTS_BYTES]; - uint32_t wots_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_set_type( - wots_addr, PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_set_type( - wots_pk_addr, PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_ADDR_TYPE_WOTSPK); - - PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_set_keypair_addr( - wots_addr, addr_idx); - PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_wots_gen_pk( - pk, sk_seed, pub_seed, wots_addr, hash_state_seeded); - - PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_copy_keypair_addr( - wots_pk_addr, wots_addr); - PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_thash_WOTS_LEN( - leaf, pk, pub_seed, wots_pk_addr, hash_state_seeded); -} - /* * Returns the length of a secret key, in bytes */ -size_t PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_crypto_sign_secretkeybytes(void) { - return PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_CRYPTO_SECRETKEYBYTES; +size_t crypto_sign_secretkeybytes(void) { + return CRYPTO_SECRETKEYBYTES; } /* * Returns the length of a public key, in bytes */ -size_t PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_crypto_sign_publickeybytes(void) { - return PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_CRYPTO_PUBLICKEYBYTES; +size_t crypto_sign_publickeybytes(void) { + return CRYPTO_PUBLICKEYBYTES; } /* * Returns the length of a signature, in bytes */ -size_t PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_crypto_sign_bytes(void) { - return PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_CRYPTO_BYTES; +size_t crypto_sign_bytes(void) { + return CRYPTO_BYTES; } /* * Returns the length of the seed required to generate a key pair, in bytes */ -size_t PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_crypto_sign_seedbytes(void) { - return PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_CRYPTO_SEEDBYTES; +size_t crypto_sign_seedbytes(void) { + return CRYPTO_SEEDBYTES; } /* @@ -76,37 +47,30 @@ size_t PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_crypto_sign_seedbytes(void) { * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] * Format pk: [PUB_SEED || root] */ -int PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed) { - /* We do not need the auth path in key generation, but it simplifies the - code to have just one treehash routine that computes both root and path - in one function. */ - unsigned char auth_path[PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_TREE_HEIGHT * PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_N]; - uint32_t top_tree_addr[8] = {0}; - hash_state hash_state_seeded; - - PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_set_layer_addr( - top_tree_addr, PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_D - 1); - PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_set_type( - top_tree_addr, PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_ADDR_TYPE_HASHTREE); +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed) { + spx_ctx ctx; /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ - memcpy(sk, seed, PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_CRYPTO_SEEDBYTES); + memcpy(sk, seed, CRYPTO_SEEDBYTES); - memcpy(pk, sk + 2 * PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_N, PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_N); + memcpy(pk, sk + 2 * SPX_N, SPX_N); + + memcpy(ctx.pub_seed, pk, SPX_N); + memcpy(ctx.sk_seed, sk, SPX_N); /* This hook allows the hash function instantiation to do whatever preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_initialize_hash_function(&hash_state_seeded, pk, sk); + initialize_hash_function(&ctx); /* Compute root node of the top-most subtree. */ - PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_treehash_TREE_HEIGHT( - sk + 3 * PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_N, auth_path, sk, sk + 2 * PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_N, 0, 0, - wots_gen_leaf, top_tree_addr, &hash_state_seeded); + merkle_gen_root(sk + 3 * SPX_N, &ctx); + + // cleanup + free_hash_function(&ctx); - memcpy(pk + PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_N, sk + 3 * PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_N, PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_N); + memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); - PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_destroy_hash_function(&hash_state_seeded); return 0; } @@ -115,12 +79,10 @@ int PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_crypto_sign_seed_keypair( * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] * Format pk: [PUB_SEED || root] */ -int PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk) { - unsigned char seed[PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_CRYPTO_SEEDBYTES]; - randombytes(seed, PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_CRYPTO_SEEDBYTES); - PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_crypto_sign_seed_keypair( - pk, sk, seed); +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { + uint8_t seed[CRYPTO_SEEDBYTES]; + randombytes(seed, CRYPTO_SEEDBYTES); + crypto_sign_seed_keypair(pk, sk, seed); return 0; } @@ -128,101 +90,83 @@ int PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_crypto_sign_keypair( /** * Returns an array containing a detached signature. */ -int PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - const unsigned char *sk_seed = sk; - const unsigned char *sk_prf = sk + PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_N; - const unsigned char *pk = sk + 2 * PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_N; - const unsigned char *pub_seed = pk; - - unsigned char optrand[PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_N]; - unsigned char mhash[PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_FORS_MSG_BYTES]; - unsigned char root[PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_N]; +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk) { + spx_ctx ctx; + + const uint8_t *sk_prf = sk + SPX_N; + const uint8_t *pk = sk + 2 * SPX_N; + + uint8_t optrand[SPX_N]; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t root[SPX_N]; uint32_t i; uint64_t tree; uint32_t idx_leaf; uint32_t wots_addr[8] = {0}; uint32_t tree_addr[8] = {0}; - hash_state hash_state_seeded; + memcpy(ctx.sk_seed, sk, SPX_N); + memcpy(ctx.pub_seed, pk, SPX_N); /* This hook allows the hash function instantiation to do whatever preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_initialize_hash_function( - &hash_state_seeded, - pub_seed, sk_seed); + initialize_hash_function(&ctx); - PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_set_type( - wots_addr, PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_set_type( - tree_addr, PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_ADDR_TYPE_HASHTREE); + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); /* Optionally, signing can be made non-deterministic using optrand. This can help counter side-channel attacks that would benefit from getting a large number of traces when the signer uses the same nodes. */ - randombytes(optrand, PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_N); + randombytes(optrand, SPX_N); /* Compute the digest randomization value. */ - PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_gen_message_random( - sig, sk_prf, optrand, m, mlen, &hash_state_seeded); + gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); /* Derive the message digest and leaf index from R, PK and M. */ - PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_N; + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; - PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); /* Sign the message hash using FORS. */ - PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_fors_sign( - sig, root, mhash, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_FORS_BYTES; - - for (i = 0; i < PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_D; i++) { - PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_set_tree_addr(tree_addr, tree); - - PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); - - /* Compute a WOTS signature. */ - PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_wots_sign( - sig, root, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_WOTS_BYTES; - - /* Compute the authentication path for the used WOTS leaf. */ - PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_treehash_TREE_HEIGHT( - root, sig, sk_seed, pub_seed, idx_leaf, 0, - wots_gen_leaf, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_TREE_HEIGHT * PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_N; + fors_sign(sig, root, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); + sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_TREE_HEIGHT; + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; } - *siglen = PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_BYTES; + free_hash_function(&ctx); + + *siglen = SPX_BYTES; - PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_destroy_hash_function(&hash_state_seeded); return 0; } /** * Verifies a detached signature and message under a given public key. */ -int PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk) { - const unsigned char *pub_seed = pk; - const unsigned char *pub_root = pk + PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_N; - unsigned char mhash[PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_FORS_MSG_BYTES]; - unsigned char wots_pk[PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_WOTS_BYTES]; - unsigned char root[PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_N]; - unsigned char leaf[PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_N]; +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk) { + spx_ctx ctx; + const uint8_t *pub_root = pk + SPX_N; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t wots_pk[SPX_WOTS_BYTES]; + uint8_t root[SPX_N]; + uint8_t leaf[SPX_N]; unsigned int i; uint64_t tree; uint32_t idx_leaf; @@ -230,78 +174,66 @@ int PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_crypto_sign_verify( uint32_t tree_addr[8] = {0}; uint32_t wots_pk_addr[8] = {0}; - hash_state hash_state_seeded; - - if (siglen != PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_BYTES) { + if (siglen != SPX_BYTES) { return -1; } + memcpy(ctx.pub_seed, pk, SPX_N); + /* This hook allows the hash function instantiation to do whatever preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_initialize_hash_function( - &hash_state_seeded, - pub_seed, NULL); + initialize_hash_function(&ctx); - PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_set_type( - wots_addr, PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_set_type( - tree_addr, PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_ADDR_TYPE_HASHTREE); - PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_set_type( - wots_pk_addr, PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_ADDR_TYPE_WOTSPK); + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); /* Derive the message digest and leaf index from R || PK || M. */ - /* The additional PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_N is a result of the hash domain separator. */ - PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_N; + /* The additional SPX_N is a result of the hash domain separator. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; /* Layer correctly defaults to 0, so no need to set_layer_addr */ - PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); - PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_fors_pk_from_sig( - root, sig, mhash, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_FORS_BYTES; + fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; /* For each subtree.. */ - for (i = 0; i < PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_D; i++) { - PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_set_tree_addr(tree_addr, tree); + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); - PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); - PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_copy_keypair_addr( - wots_pk_addr, wots_addr); + copy_keypair_addr(wots_pk_addr, wots_addr); /* The WOTS public key is only correct if the signature was correct. */ /* Initially, root is the FORS pk, but on subsequent iterations it is the root of the subtree below the currently processed subtree. */ - PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_wots_pk_from_sig( - wots_pk, sig, root, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_WOTS_BYTES; + wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); + sig += SPX_WOTS_BYTES; /* Compute the leaf node using the WOTS public key. */ - PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_thash_WOTS_LEN( - leaf, wots_pk, pub_seed, wots_pk_addr, &hash_state_seeded); + thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); /* Compute the root node of this subtree. */ - PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_compute_root( - root, leaf, idx_leaf, 0, sig, PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_TREE_HEIGHT, - pub_seed, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_TREE_HEIGHT * PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_N; + compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, + &ctx, tree_addr); + sig += SPX_TREE_HEIGHT * SPX_N; /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_TREE_HEIGHT; + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; } - PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_destroy_hash_function(&hash_state_seeded); + // cleanup + free_hash_function(&ctx); + /* Check if the root node equals the root node in the public key. */ - if (memcmp(root, pub_root, PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_N) != 0) { + if (memcmp(root, pub_root, SPX_N) != 0) { return -1; } @@ -312,15 +244,14 @@ int PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_crypto_sign_verify( /** * Returns an array containing the signature followed by the message. */ -int PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk) { size_t siglen; - PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_crypto_sign_signature( - sm, &siglen, m, mlen, sk); + crypto_sign_signature(sm, &siglen, m, mlen, sk); - memmove(sm + PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_BYTES, m, mlen); + memmove(sm + SPX_BYTES, m, mlen); *smlen = siglen + mlen; return 0; @@ -329,28 +260,27 @@ int PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_crypto_sign( /** * Verifies a given signature-message pair under a given public key. */ -int PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk) { +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk) { /* The API caller does not necessarily know what size a signature should be - but SPHINCS+ signatures are always exactly PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_BYTES. */ - if (smlen < PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_BYTES) { + but SPHINCS+ signatures are always exactly SPX_BYTES. */ + if (smlen < SPX_BYTES) { memset(m, 0, smlen); *mlen = 0; return -1; } - *mlen = smlen - PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_BYTES; + *mlen = smlen - SPX_BYTES; - if (PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_crypto_sign_verify( - sm, PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_BYTES, sm + PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_BYTES, *mlen, pk)) { + if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { memset(m, 0, smlen); *mlen = 0; return -1; } /* If verification was successful, move the message to the right place. */ - memmove(m, sm + PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_BYTES, *mlen); + memmove(m, sm + SPX_BYTES, *mlen); return 0; } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/thash.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/thash.h index 77cbb36437..8687ccfb4d 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/thash.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/thash.h @@ -1,28 +1,13 @@ -#ifndef PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_THASH_H -#define PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_THASH_H +#ifndef SPX_THASH_H +#define SPX_THASH_H -#include "hash_state.h" +#include "context.h" +#include "params.h" #include -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); +#define thash SPX_NAMESPACE(thash) +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/thash_haraka_simple.c b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/thash_haraka_simple.c index d51a717ea0..207777bf8d 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/thash_haraka_simple.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/thash_haraka_simple.c @@ -4,80 +4,33 @@ #include "address.h" #include "params.h" #include "thash.h" +#include "utils.h" #include "haraka.h" /** - * Takes an array of inblocks concatenated arrays of PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_N bytes. + * Takes an array of inblocks concatenated arrays of SPX_N bytes. */ -static void PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_thash( - unsigned char *out, unsigned char *buf, - const unsigned char *in, unsigned int inblocks, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]) { + PQCLEAN_VLA(uint8_t, buf, SPX_ADDR_BYTES + inblocks * SPX_N); unsigned char outbuf[32]; unsigned char buf_tmp[64]; - (void)pub_seed; /* Suppress an 'unused parameter' warning. */ - if (inblocks == 1) { /* F function */ - /* Since PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_N may be smaller than 32, we need a temporary buffer. */ + /* Since SPX_N may be smaller than 32, we need a temporary buffer. */ memset(buf_tmp, 0, 64); - PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_addr_to_bytes(buf_tmp, addr); - memcpy(buf_tmp + PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_ADDR_BYTES, in, PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_N); + memcpy(buf_tmp, addr, 32); + memcpy(buf_tmp + SPX_ADDR_BYTES, in, SPX_N); - PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_haraka512(outbuf, buf_tmp, hash_state_seeded); - memcpy(out, outbuf, PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_N); + haraka512(outbuf, buf_tmp, ctx); + memcpy(out, outbuf, SPX_N); } else { /* All other tweakable hashes*/ - PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_addr_to_bytes(buf, addr); - memcpy(buf + PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_ADDR_BYTES, in, inblocks * PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_N); + memcpy(buf, addr, 32); + memcpy(buf + SPX_ADDR_BYTES, in, inblocks * SPX_N); - PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_haraka_S( - out, PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_N, buf, PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_N, hash_state_seeded); + haraka_S(out, SPX_N, buf, SPX_ADDR_BYTES + inblocks * SPX_N, ctx); } } - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_ADDR_BYTES + 1 * PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_N]; - PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_thash( - out, buf, in, 1, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_ADDR_BYTES + 2 * PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_N]; - PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_thash( - out, buf, in, 2, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_ADDR_BYTES + PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_WOTS_LEN * PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_N]; - PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_thash( - out, buf, in, PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_WOTS_LEN, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_ADDR_BYTES + PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_FORS_TREES * PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_N]; - PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_thash( - out, buf, in, PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_FORS_TREES, pub_seed, addr, hash_state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/utils.c b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/utils.c index 6edbd13756..177b541fb9 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/utils.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/utils.c @@ -1,34 +1,41 @@ -#include #include +#include "utils.h" + #include "address.h" #include "hash.h" -#include "hash_state.h" #include "params.h" #include "thash.h" -#include "utils.h" /** * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. */ -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in) { +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in) { + int i; /* Iterate over out in decreasing order, for big-endianness. */ - for (size_t i = outlen; i > 0; i--) { - out[i - 1] = in & 0xff; + for (i = (signed int)outlen - 1; i >= 0; i--) { + out[i] = in & 0xff; in = in >> 8; } } +void u32_to_bytes(unsigned char *out, uint32_t in) { + out[0] = (unsigned char)(in >> 24); + out[1] = (unsigned char)(in >> 16); + out[2] = (unsigned char)(in >> 8); + out[3] = (unsigned char)in; +} + /** * Converts the inlen bytes in 'in' from big-endian byte order to an integer. */ -unsigned long long PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_bytes_to_ull( - const unsigned char *in, size_t inlen) { +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { unsigned long long retval = 0; + unsigned int i; - for (size_t i = 0; i < inlen; i++) { + for (i = 0; i < inlen; i++) { retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); } return retval; @@ -38,94 +45,80 @@ unsigned long long PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_bytes_to_ull( * Computes a root node given a leaf and an auth path. * Expects address to be complete other than the tree_height and tree_index. */ -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]) { uint32_t i; - unsigned char buffer[2 * PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_N]; + unsigned char buffer[2 * SPX_N]; /* If leaf_idx is odd (last bit = 1), current path element is a right child and auth_path has to go left. Otherwise it is the other way around. */ if (leaf_idx & 1) { - memcpy(buffer + PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_N, leaf, PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_N); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_N); + memcpy(buffer + SPX_N, leaf, SPX_N); + memcpy(buffer, auth_path, SPX_N); } else { - memcpy(buffer, leaf, PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_N); - memcpy(buffer + PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_N, auth_path, PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_N); + memcpy(buffer, leaf, SPX_N); + memcpy(buffer + SPX_N, auth_path, SPX_N); } - auth_path += PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_N; + auth_path += SPX_N; for (i = 0; i < tree_height - 1; i++) { leaf_idx >>= 1; idx_offset >>= 1; /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_set_tree_height(addr, i + 1); - PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_set_tree_index( - addr, leaf_idx + idx_offset); + set_tree_height(addr, i + 1); + set_tree_index(addr, leaf_idx + idx_offset); /* Pick the right or left neighbor, depending on parity of the node. */ if (leaf_idx & 1) { - PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_thash_2( - buffer + PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_N, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_N); + thash(buffer + SPX_N, buffer, 2, ctx, addr); + memcpy(buffer, auth_path, SPX_N); } else { - PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_thash_2( - buffer, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer + PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_N, auth_path, PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_N); + thash(buffer, buffer, 2, ctx, addr); + memcpy(buffer + SPX_N, auth_path, SPX_N); } - auth_path += PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_N; + auth_path += SPX_N; } /* The last iteration is exceptional; we do not copy an auth_path node. */ leaf_idx >>= 1; idx_offset >>= 1; - PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_set_tree_height(addr, tree_height); - PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_set_tree_index( - addr, leaf_idx + idx_offset); - PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_thash_2( - root, buffer, pub_seed, addr, hash_state_seeded); + set_tree_height(addr, tree_height); + set_tree_index(addr, leaf_idx + idx_offset); + thash(root, buffer, 2, ctx, addr); } /** * For a given leaf index, computes the authentication path and the resulting * root node using Merkle's TreeHash algorithm. * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_ADDR_TYPE_FORSTREE). + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). * Applies the offset idx_offset to indices before building addresses, so that * it is possible to continue counting indices across trees. */ -static void PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_treehash( - unsigned char *root, unsigned char *auth_path, - unsigned char *stack, unsigned int *heights, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - +void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx * /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]) { + PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); + PQCLEAN_VLA(unsigned int, heights, tree_height + 1); unsigned int offset = 0; uint32_t idx; uint32_t tree_idx; for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { /* Add the next leaf node to the stack. */ - gen_leaf(stack + offset * PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_N, - sk_seed, pub_seed, idx + idx_offset, tree_addr, - hash_state_seeded); + gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); offset++; heights[offset - 1] = 0; /* If this is a node we need for the auth path.. */ if ((leaf_idx ^ 0x1) == idx) { - memcpy(auth_path, stack + (offset - 1)*PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_N, PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_N); + memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); } /* While the top-most nodes are of equal height.. */ @@ -134,66 +127,22 @@ static void PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_treehash( tree_idx = (idx >> (heights[offset - 1] + 1)); /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_set_tree_height( - tree_addr, heights[offset - 1] + 1); - PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_set_tree_index( - tree_addr, tree_idx + (idx_offset >> (heights[offset - 1] + 1))); + set_tree_height(tree_addr, heights[offset - 1] + 1); + set_tree_index(tree_addr, + tree_idx + (idx_offset >> (heights[offset - 1] + 1))); /* Hash the top-most nodes from the stack together. */ - PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_thash_2( - stack + (offset - 2)*PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_N, stack + (offset - 2)*PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_N, - pub_seed, tree_addr, hash_state_seeded); + thash(stack + (offset - 2)*SPX_N, + stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); offset--; /* Note that the top-most node is now one layer higher. */ heights[offset - 1]++; /* If this is a node we need for the auth path.. */ if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_path + heights[offset - 1]*PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_N, - stack + (offset - 1)*PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_N, PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_N); + memcpy(auth_path + heights[offset - 1]*SPX_N, + stack + (offset - 1)*SPX_N, SPX_N); } } } - memcpy(root, stack, PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_N); -} - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_FORS_HEIGHT + 1)*PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_N]; - unsigned int heights[PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_FORS_HEIGHT + 1]; - - PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_FORS_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_TREE_HEIGHT + 1)*PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_N]; - unsigned int heights[PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_TREE_HEIGHT + 1]; - - PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_TREE_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); + memcpy(root, stack, SPX_N); } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/utils.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/utils.h index a3814bae0a..64f5d5a53a 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/utils.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/utils.h @@ -1,64 +1,58 @@ -#ifndef PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_UTILS_H -#define PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_UTILS_H +#ifndef SPX_UTILS_H +#define SPX_UTILS_H -#include "hash_state.h" -#include "params.h" -#include #include +#include "compat.h" +#include "context.h" +#include "params.h" + + +/* To support MSVC use alloca() instead of VLAs. See #20. */ + + /** * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. */ -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in); +#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in); +#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) +void u32_to_bytes(unsigned char *out, uint32_t in); /** * Converts the inlen bytes in 'in' from big-endian byte order to an integer. */ -unsigned long long PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_bytes_to_ull( - const unsigned char *in, size_t inlen); +#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); /** * Computes a root node given a leaf and an auth path. * Expects address to be complete other than the tree_height and tree_index. */ -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); +#define compute_root SPX_NAMESPACE(compute_root) +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]); /** * For a given leaf index, computes the authentication path and the resulting * root node using Merkle's TreeHash algorithm. * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_ADDR_TYPE_FORSTREE). + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). * Applies the offset idx_offset to indices before building addresses, so that * it is possible to continue counting indices across trees. */ -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); +#define treehash SPX_NAMESPACE(treehash) +void treehash(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx *ctx /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]); -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/utilsx1.c b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/utilsx1.c new file mode 100644 index 0000000000..fccb69b35d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/utilsx1.c @@ -0,0 +1,100 @@ +#include + +#include "utilsx1.h" + +#include "address.h" +#include "params.h" +#include "thash.h" +#include "utils.h" + +/* + * Generate the entire Merkle tree, computing the authentication path for + * leaf_idx, and the resulting root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) + * + * This expects tree_addr to be initialized to the addr structures for the + * Merkle tree nodes + * + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + * + * This works by using the standard Merkle tree building algorithm, + */ +void treehashx1(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, + uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* Where to write the leaves */, + const spx_ctx * /* ctx */, + uint32_t idx, void *info), + uint32_t tree_addr[8], + void *info) { + /* This is where we keep the intermediate nodes */ + PQCLEAN_VLA(uint8_t, stack, tree_height * SPX_N); + + uint32_t idx; + uint32_t max_idx = (uint32_t)((1 << tree_height) - 1); + for (idx = 0;; idx++) { + unsigned char current[2 * SPX_N]; /* Current logical node is at */ + /* index[SPX_N]. We do this to minimize the number of copies */ + /* needed during a thash */ + gen_leaf( ¤t[SPX_N], ctx, idx + idx_offset, + info ); + + /* Now combine the freshly generated right node with previously */ + /* generated left ones */ + uint32_t internal_idx_offset = idx_offset; + uint32_t internal_idx = idx; + uint32_t internal_leaf = leaf_idx; + uint32_t h; /* The height we are in the Merkle tree */ + for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { + + /* Check if we hit the top of the tree */ + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[SPX_N], SPX_N ); + return; + } + + /* + * Check if the node we have is a part of the + * authentication path; if it is, write it out + */ + if ((internal_idx ^ internal_leaf) == 0x01) { + memcpy( &auth_path[ h * SPX_N ], + ¤t[SPX_N], + SPX_N ); + } + + /* + * Check if we're at a left child; if so, stop going up the stack + * Exception: if we've reached the end of the tree, keep on going + * (so we combine the last 4 nodes into the one root node in two + * more iterations) + */ + if ((internal_idx & 1) == 0 && idx < max_idx) { + break; + } + + /* Ok, we're at a right node */ + /* Now combine the left and right logical nodes together */ + + /* Set the address of the node we're creating. */ + internal_idx_offset >>= 1; + set_tree_height(tree_addr, h + 1); + set_tree_index(tree_addr, internal_idx / 2 + internal_idx_offset ); + + unsigned char *left = &stack[h * SPX_N]; + memcpy( ¤t[0], left, SPX_N ); + thash( ¤t[1 * SPX_N], + ¤t[0 * SPX_N], + 2, ctx, tree_addr); + } + + /* We've hit a left child; save the current for when we get the */ + /* corresponding right right */ + memcpy( &stack[h * SPX_N], ¤t[SPX_N], SPX_N); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/utilsx1.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/utilsx1.h new file mode 100644 index 0000000000..e911d17d53 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/utilsx1.h @@ -0,0 +1,27 @@ +#ifndef SPX_UTILSX4_H +#define SPX_UTILSX4_H + +#include + +#include "context.h" +#include "params.h" + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +#define treehashx1 SPX_NAMESPACE(treehashx1) +void treehashx1(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* Where to write the leaf */, + const spx_ctx * /* ctx */, + uint32_t addr_idx, void *info), + uint32_t tree_addrx4[8], void *info); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/wots.c b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/wots.c index af3d72bbda..249717aaa8 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/wots.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/wots.c @@ -1,32 +1,20 @@ #include #include +#include "wots.h" +#include "wotsx1.h" + #include "address.h" #include "hash.h" -#include "hash_state.h" #include "params.h" #include "thash.h" #include "utils.h" -#include "wots.h" +#include "utilsx1.h" // TODO clarify address expectations, and make them more uniform. // TODO i.e. do we expect types to be set already? // TODO and do we expect modifications or copies? -/** - * Computes the starting value for a chain, i.e. the secret key. - * Expects the address to be complete up to the chain address. - */ -static void wots_gen_sk(unsigned char *sk, const unsigned char *sk_seed, - uint32_t wots_addr[8], - const hash_state *hash_state_seeded) { - /* Make sure that the hash address is actually zeroed. */ - PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_set_hash_addr(wots_addr, 0); - - /* Generate sk element. */ - PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_prf_addr(sk, sk_seed, wots_addr, hash_state_seeded); -} - /** * Computes the chaining function. * out and in have to be n-byte arrays. @@ -36,18 +24,16 @@ static void wots_gen_sk(unsigned char *sk, const unsigned char *sk_seed, */ static void gen_chain(unsigned char *out, const unsigned char *in, unsigned int start, unsigned int steps, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { + const spx_ctx *ctx, uint32_t addr[8]) { uint32_t i; /* Initialize out with the value at position 'start'. */ - memcpy(out, in, PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_N); + memcpy(out, in, SPX_N); /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_WOTS_W; i++) { - PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_set_hash_addr(addr, i); - PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_thash_1( - out, out, pub_seed, addr, hash_state_seeded); + for (i = start; i < (start + steps) && i < SPX_WOTS_W; i++) { + set_hash_addr(addr, i); + thash(out, out, 1, ctx, addr); } } @@ -56,13 +42,13 @@ static void gen_chain(unsigned char *out, const unsigned char *in, * Interprets an array of bytes as integers in base w. * This only works when log_w is a divisor of 8. */ -static void base_w(unsigned int *output, const size_t out_len, +static void base_w(unsigned int *output, const int out_len, const unsigned char *input) { - size_t in = 0; - size_t out = 0; + int in = 0; + int out = 0; unsigned char total = 0; - unsigned int bits = 0; - size_t consumed; + int bits = 0; + int consumed; for (consumed = 0; consumed < out_len; consumed++) { if (bits == 0) { @@ -70,8 +56,8 @@ static void base_w(unsigned int *output, const size_t out_len, in++; bits += 8; } - bits -= PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_WOTS_LOGW; - output[out] = (unsigned int)((total >> bits) & (PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_WOTS_W - 1)); + bits -= SPX_WOTS_LOGW; + output[out] = (total >> bits) & (SPX_WOTS_W - 1); out++; } } @@ -80,67 +66,25 @@ static void base_w(unsigned int *output, const size_t out_len, static void wots_checksum(unsigned int *csum_base_w, const unsigned int *msg_base_w) { unsigned int csum = 0; - unsigned char csum_bytes[(PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_WOTS_LEN2 * PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_WOTS_LOGW + 7) / 8]; + unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; unsigned int i; /* Compute checksum. */ - for (i = 0; i < PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_WOTS_LEN1; i++) { - csum += PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_WOTS_W - 1 - msg_base_w[i]; + for (i = 0; i < SPX_WOTS_LEN1; i++) { + csum += SPX_WOTS_W - 1 - msg_base_w[i]; } /* Convert checksum to base_w. */ /* Make sure expected empty zero bits are the least significant bits. */ - csum = csum << (8 - ((PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_WOTS_LEN2 * PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_WOTS_LOGW) % 8)); - PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_ull_to_bytes( - csum_bytes, sizeof(csum_bytes), csum); - base_w(csum_base_w, PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_WOTS_LEN2, csum_bytes); + csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); + ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); + base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); } /* Takes a message and derives the matching chain lengths. */ -static void chain_lengths(unsigned int *lengths, const unsigned char *msg) { - base_w(lengths, PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_WOTS_LEN1, msg); - wots_checksum(lengths + PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_WOTS_LEN1, lengths); -} - -/** - * WOTS key generation. Takes a 32 byte sk_seed, expands it to WOTS private key - * elements and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_wots_gen_pk( - unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - uint32_t i; - - for (i = 0; i < PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_WOTS_LEN; i++) { - PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_set_chain_addr(addr, i); - wots_gen_sk(pk + i * PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_N, sk_seed, addr, hash_state_seeded); - gen_chain(pk + i * PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_N, pk + i * PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_N, - 0, PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_WOTS_W - 1, pub_seed, addr, hash_state_seeded); - } -} - -/** - * Takes a n-byte message and the 32-byte sk_see to compute a signature 'sig'. - */ -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_wots_sign( - unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *hash_state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_WOTS_LEN; i++) { - PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_set_chain_addr(addr, i); - wots_gen_sk(sig + i * PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_N, sk_seed, addr, hash_state_seeded); - gen_chain(sig + i * PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_N, sig + i * PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_N, 0, lengths[i], pub_seed, addr, hash_state_seeded); - } +void chain_lengths(unsigned int *lengths, const unsigned char *msg) { + base_w(lengths, SPX_WOTS_LEN1, msg); + wots_checksum(lengths + SPX_WOTS_LEN1, lengths); } /** @@ -148,20 +92,17 @@ void PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_wots_sign( * * Writes the computed public key to 'pk'. */ -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_wots_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_WOTS_LEN]; +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]) { + unsigned int lengths[SPX_WOTS_LEN]; uint32_t i; chain_lengths(lengths, msg); - for (i = 0; i < PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_WOTS_LEN; i++) { - PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_set_chain_addr(addr, i); - gen_chain(pk + i * PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_N, sig + i * PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_N, - lengths[i], PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_WOTS_W - 1 - lengths[i], pub_seed, addr, - hash_state_seeded); + for (i = 0; i < SPX_WOTS_LEN; i++) { + set_chain_addr(addr, i); + gen_chain(pk + i * SPX_N, sig + i * SPX_N, + lengths[i], SPX_WOTS_W - 1 - lengths[i], ctx, addr); } } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/wots.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/wots.h index 2b1092d09c..4e7692eeef 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/wots.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/wots.h @@ -1,41 +1,25 @@ -#ifndef PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_WOTS_H -#define PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_WOTS_H +#ifndef SPX_WOTS_H +#define SPX_WOTS_H -#include "hash_state.h" -#include "params.h" #include -/** - * WOTS key generation. Takes a 32 byte seed for the private key, expands it to - * a full WOTS private key and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_wots_gen_pk( - unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -/** - * Takes a n-byte message and the 32-byte seed for the private key to compute a - * signature that is placed at 'sig'. - */ -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_wots_sign( - unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *hash_state_seeded); +#include "context.h" +#include "params.h" /** * Takes a WOTS signature and an n-byte message, computes a WOTS public key. * * Writes the computed public key to 'pk'. */ -void PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_wots_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); +#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]); + +/* + * Compute the chain lengths needed for a given message hash + */ +#define chain_lengths SPX_NAMESPACE(chain_lengths) +void chain_lengths(unsigned int *lengths, const unsigned char *msg); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/wotsx1.c b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/wotsx1.c new file mode 100644 index 0000000000..3adec78dfb --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/wotsx1.c @@ -0,0 +1,76 @@ +#include +#include + +#include "wots.h" +#include "wotsx1.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "thash.h" +#include "utils.h" + +/* + * This generates a WOTS public key + * It also generates the WOTS signature if leaf_info indicates + * that we're signing with this WOTS key + */ +void wots_gen_leafx1(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info) { + struct leaf_info_x1 *info = v_info; + uint32_t *leaf_addr = info->leaf_addr; + uint32_t *pk_addr = info->pk_addr; + unsigned int i, k; + unsigned char pk_buffer[ SPX_WOTS_BYTES ]; + unsigned char *buffer; + uint32_t wots_k_mask; + + if (leaf_idx == info->wots_sign_leaf) { + /* We're traversing the leaf that's signing; generate the WOTS */ + /* signature */ + wots_k_mask = 0; + } else { + /* Nope, we're just generating pk's; turn off the signature logic */ + wots_k_mask = (uint32_t)~0; + } + + set_keypair_addr( leaf_addr, leaf_idx ); + set_keypair_addr( pk_addr, leaf_idx ); + + for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { + uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k to */ + /* the step if we're generating a signature, ~0 if we're not */ + + /* Start with the secret seed */ + set_chain_addr(leaf_addr, i); + set_hash_addr(leaf_addr, 0); + set_type(leaf_addr, SPX_ADDR_TYPE_WOTSPRF); + + prf_addr(buffer, ctx, leaf_addr); + + set_type(leaf_addr, SPX_ADDR_TYPE_WOTS); + + /* Iterate down the WOTS chain */ + for (k = 0;; k++) { + /* Check if this is the value that needs to be saved as a */ + /* part of the WOTS signature */ + if (k == wots_k) { + memcpy( info->wots_sig + i * SPX_N, buffer, SPX_N ); + } + + /* Check if we hit the top of the chain */ + if (k == SPX_WOTS_W - 1) { + break; + } + + /* Iterate one step on the chain */ + set_hash_addr(leaf_addr, k); + + thash(buffer, buffer, 1, ctx, leaf_addr); + } + } + + /* Do the final thash to generate the public keys */ + thash(dest, pk_buffer, SPX_WOTS_LEN, ctx, pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/wotsx1.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/wotsx1.h new file mode 100644 index 0000000000..e617929f96 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/wotsx1.h @@ -0,0 +1,39 @@ +#ifndef WOTSX1_H_ +#define WOTSX1_H_ + +#include + +#include "context.h" +#include "params.h" + +/* + * This is here to provide an interface to the internal wots_gen_leafx1 + * routine. While this routine is not referenced in the package outside of + * wots.c, it is called from the stand-alone benchmark code to characterize + * the performance + */ +struct leaf_info_x1 { + unsigned char *wots_sig; + uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ + uint32_t *wots_steps; + uint32_t leaf_addr[8]; + uint32_t pk_addr[8]; +}; + +/* Macro to set the leaf_info to something 'benign', that is, it would */ +/* run with the same time as it does during the real signing process */ +/* Used only by the benchmark code */ +#define INITIALIZE_LEAF_INFO_X1(info, addr, step_buffer) { \ + (info).wots_sig = 0; \ + (info).wots_sign_leaf = ~0; \ + (info).wots_steps = step_buffer; \ + memcpy( &(info).leaf_addr[0], (addr), 32 ); \ + memcpy( &(info).pk_addr[0], (addr), 32 ); \ + } + +#define wots_gen_leafx1 SPX_NAMESPACE(wots_gen_leafx1) +void wots_gen_leafx1(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info); + +#endif /* WOTSX1_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/address.c b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/address.c index d3a28e4d84..d49d9f3b6b 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/address.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/address.c @@ -1,78 +1,95 @@ #include +#include #include "address.h" #include "params.h" #include "utils.h" -void PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]) { - int i; - - for (i = 0; i < 8; i++) { - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_ull_to_bytes( - bytes + i * 4, 4, addr[i]); - } -} - -void PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_set_layer_addr( - uint32_t addr[8], uint32_t layer) { - addr[0] = layer; +/* + * Specify which level of Merkle tree (the "layer") we're working on + */ +void set_layer_addr(uint32_t addr[8], uint32_t layer) { + ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; } -void PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_set_tree_addr( - uint32_t addr[8], uint64_t tree) { - addr[1] = 0; - addr[2] = (uint32_t) (tree >> 32); - addr[3] = (uint32_t) tree; +/* + * Specify which Merkle tree within the level (the "tree address") we're working on + */ +void set_tree_addr(uint32_t addr[8], uint64_t tree) { + ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); } -void PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_set_type( - uint32_t addr[8], uint32_t type) { - addr[4] = type; +/* + * Specify the reason we'll use this address structure for, that is, what + * hash will we compute with it. This is used so that unrelated types of + * hashes don't accidentally get the same address structure. The type will be + * one of the SPX_ADDR_TYPE constants + */ +void set_type(uint32_t addr[8], uint32_t type) { + ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; } -void PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; +/* + * Copy the layer and tree fields of the address structure. This is used + * when we're doing multiple types of hashes within the same Merkle tree + */ +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); } /* These functions are used for OTS addresses. */ -void PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_set_keypair_addr( - uint32_t addr[8], uint32_t keypair) { - addr[5] = keypair; +/* + * Specify which Merkle leaf we're working on; that is, which OTS keypair + * we're talking about. + */ +void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { + /* We have > 256 OTS at the bottom of the Merkle tree; to specify */ + /* which one, we'd need to express it in two bytes */ + ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR2] = (unsigned char)(keypair >> 8); + ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; } -void PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; - out[5] = in[5]; +/* + * Copy the layer, tree and keypair fields of the address structure. This is + * used when we're doing multiple things within the same OTS keypair + */ +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); + ((unsigned char *)out)[SPX_OFFSET_KP_ADDR2] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR2]; + ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; } -void PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_set_chain_addr( - uint32_t addr[8], uint32_t chain) { - addr[6] = chain; +/* + * Specify which Merkle chain within the OTS we're working with + * (the chain address) + */ +void set_chain_addr(uint32_t addr[8], uint32_t chain) { + ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; } -void PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_set_hash_addr( - uint32_t addr[8], uint32_t hash) { - addr[7] = hash; +/* + * Specify where in the Merkle chain we are +* (the hash address) + */ +void set_hash_addr(uint32_t addr[8], uint32_t hash) { + ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; } /* These functions are used for all hash tree addresses (including FORS). */ -void PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_set_tree_height( - uint32_t addr[8], uint32_t tree_height) { - addr[6] = tree_height; +/* + * Specify the height of the node in the Merkle/FORS tree we are in + * (the tree height) + */ +void set_tree_height(uint32_t addr[8], uint32_t tree_height) { + ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; } -void PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_set_tree_index( - uint32_t addr[8], uint32_t tree_index) { - addr[7] = tree_index; +/* + * Specify the distance from the left edge of the node in the Merkle/FORS tree + * (the tree index) + */ +void set_tree_index(uint32_t addr[8], uint32_t tree_index) { + u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/address.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/address.h index 1524734934..24a84eb40c 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/address.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/address.h @@ -1,50 +1,52 @@ -#ifndef PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_ADDRESS_H -#define PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_ADDRESS_H +#ifndef SPX_ADDRESS_H +#define SPX_ADDRESS_H #include -#define PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_ADDR_TYPE_WOTS 0 -#define PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_ADDR_TYPE_WOTSPK 1 -#define PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_ADDR_TYPE_HASHTREE 2 -#define PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_ADDR_TYPE_FORSTREE 3 -#define PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_ADDR_TYPE_FORSPK 4 +#include "params.h" -void PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]); +/* The hash types that are passed to set_type */ +#define SPX_ADDR_TYPE_WOTS 0 +#define SPX_ADDR_TYPE_WOTSPK 1 +#define SPX_ADDR_TYPE_HASHTREE 2 +#define SPX_ADDR_TYPE_FORSTREE 3 +#define SPX_ADDR_TYPE_FORSPK 4 +#define SPX_ADDR_TYPE_WOTSPRF 5 +#define SPX_ADDR_TYPE_FORSPRF 6 -void PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_set_layer_addr( - uint32_t addr[8], uint32_t layer); +#define set_layer_addr SPX_NAMESPACE(set_layer_addr) +void set_layer_addr(uint32_t addr[8], uint32_t layer); -void PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_set_tree_addr( - uint32_t addr[8], uint64_t tree); +#define set_tree_addr SPX_NAMESPACE(set_tree_addr) +void set_tree_addr(uint32_t addr[8], uint64_t tree); -void PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_set_type( - uint32_t addr[8], uint32_t type); +#define set_type SPX_NAMESPACE(set_type) +void set_type(uint32_t addr[8], uint32_t type); /* Copies the layer and tree part of one address into the other */ -void PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]); +#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); /* These functions are used for WOTS and FORS addresses. */ -void PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_set_keypair_addr( - uint32_t addr[8], uint32_t keypair); +#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) +void set_keypair_addr(uint32_t addr[8], uint32_t keypair); -void PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_set_chain_addr( - uint32_t addr[8], uint32_t chain); +#define set_chain_addr SPX_NAMESPACE(set_chain_addr) +void set_chain_addr(uint32_t addr[8], uint32_t chain); -void PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_set_hash_addr( - uint32_t addr[8], uint32_t hash); +#define set_hash_addr SPX_NAMESPACE(set_hash_addr) +void set_hash_addr(uint32_t addr[8], uint32_t hash); -void PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]); +#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); /* These functions are used for all hash tree addresses (including FORS). */ -void PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_set_tree_height( - uint32_t addr[8], uint32_t tree_height); +#define set_tree_height SPX_NAMESPACE(set_tree_height) +void set_tree_height(uint32_t addr[8], uint32_t tree_height); -void PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_set_tree_index( - uint32_t addr[8], uint32_t tree_index); +#define set_tree_index SPX_NAMESPACE(set_tree_index) +void set_tree_index(uint32_t addr[8], uint32_t tree_index); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/api.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/api.h index bdf18264f3..4c0ed0f9f3 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/api.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/api.h @@ -4,15 +4,13 @@ #include #include - - -#define PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_CRYPTO_ALGNAME "SPHINCS+" +#define PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_CRYPTO_ALGNAME "SPHINCS+-haraka-128s-robust" #define PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_CRYPTO_SECRETKEYBYTES 64 #define PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_CRYPTO_PUBLICKEYBYTES 32 -#define PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_CRYPTO_BYTES 7856 -#define PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_CRYPTO_SEEDBYTES 48 +#define PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_CRYPTO_BYTES 7856 +#define PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_CRYPTO_SEEDBYTES 48 /* * Returns the length of a secret key, in bytes @@ -39,43 +37,41 @@ size_t PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_crypto_sign_seedbytes(void); * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] * Format pk: [root || PUB_SEED] */ -int PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed); +int PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); /* * Generates a SPHINCS+ key pair. * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] * Format pk: [root || PUB_SEED] */ -int PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk); +int PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); /** * Returns an array containing a detached signature. */ -int PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk); +int PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); /** * Verifies a detached signature and message under a given public key. */ -int PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk); +int PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, + const uint8_t *pk); /** * Returns an array containing the signature followed by the message. */ -int PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk); +int PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); /** * Verifies a given signature-message pair under a given public key. */ -int PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk); - +int PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/context.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/context.h new file mode 100644 index 0000000000..f03446b9cb --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/context.h @@ -0,0 +1,22 @@ +#ifndef SPX_CONTEXT_H +#define SPX_CONTEXT_H + +#include + +#include "immintrin.h" +#include "params.h" + +typedef struct { + uint8_t pub_seed[SPX_N]; + uint8_t sk_seed[SPX_N]; + + __m128i rc[40]; +} spx_ctx; + +#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) +void initialize_hash_function(spx_ctx *ctx); + +#define free_hash_function SPX_NAMESPACE(free_hash_function) +void free_hash_function(spx_ctx *ctx); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/context_haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/context_haraka.c new file mode 100644 index 0000000000..f1cd7e3664 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/context_haraka.c @@ -0,0 +1,11 @@ +#include "context.h" +#include "haraka.h" + +void initialize_hash_function(spx_ctx *ctx) { + tweak_constants(ctx); +} + +// we don't support heap-based haraka right now +void free_hash_function(spx_ctx *ctx) { + (void)ctx; // suppress unused variable warnings +} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/fors.c b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/fors.c index 9b8e500f66..f1b0639cfc 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/fors.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/fors.c @@ -2,8 +2,9 @@ #include #include -#include "address.h" #include "fors.h" + +#include "address.h" #include "hash.h" #include "hashx4.h" #include "thash.h" @@ -11,19 +12,24 @@ #include "utils.h" #include "utilsx4.h" +static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + prf_addr(sk, ctx, fors_leaf_addr); +} + static void fors_gen_skx4(unsigned char *sk0, unsigned char *sk1, unsigned char *sk2, - unsigned char *sk3, const unsigned char *sk_seed, - uint32_t fors_leaf_addrx4[4 * 8], - const hash_state *state_seeded) { - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_prf_addrx4(sk0, sk1, sk2, sk3, sk_seed, fors_leaf_addrx4, state_seeded); + unsigned char *sk3, const spx_ctx *ctx, + uint32_t fors_leaf_addrx4[4 * 8]) { + prf_addrx4(sk0, sk1, sk2, sk3, + ctx, fors_leaf_addrx4); } static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, - const unsigned char *pub_seed, - uint32_t fors_leaf_addr[8], const hash_state *state_seeded) { - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_thash_1(leaf, sk, pub_seed, fors_leaf_addr, state_seeded); + const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + thash(leaf, sk, 1, ctx, fors_leaf_addr); } static void fors_sk_to_leafx4(unsigned char *leaf0, @@ -34,57 +40,64 @@ static void fors_sk_to_leafx4(unsigned char *leaf0, const unsigned char *sk1, const unsigned char *sk2, const unsigned char *sk3, - const unsigned char *pub_seed, - uint32_t fors_leaf_addrx4[4 * 8], - const hash_state *state_seeded) { - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_thashx4_1(leaf0, leaf1, leaf2, leaf3, - sk0, sk1, sk2, sk3, pub_seed, fors_leaf_addrx4, state_seeded); + const spx_ctx *ctx, + uint32_t fors_leaf_addrx4[4 * 8]) { + thashx4(leaf0, leaf1, leaf2, leaf3, + sk0, sk1, sk2, sk3, + 1, ctx, fors_leaf_addrx4); } -static void fors_gen_leafx4(unsigned char *leaf0, - unsigned char *leaf1, - unsigned char *leaf2, - unsigned char *leaf3, - const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx0, - uint32_t addr_idx1, - uint32_t addr_idx2, - uint32_t addr_idx3, - const uint32_t fors_tree_addr[8], - const hash_state *state_seeded) { - uint32_t fors_leaf_addrx4[4 * 8] = {0}; +struct fors_gen_leaf_info { + uint32_t leaf_addrx[4 * 8]; +}; + +static void fors_gen_leafx4(unsigned char *leaf, + const spx_ctx *ctx, + uint32_t addr_idx, void *info) { + struct fors_gen_leaf_info *fors_info = info; + uint32_t *fors_leaf_addrx4 = fors_info->leaf_addrx; unsigned int j; - /* Only copy the parts that must be kept in fors_leaf_addrx4. */ + /* Only set the parts that the caller doesn't set */ for (j = 0; j < 4; j++) { - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_copy_keypair_addr(fors_leaf_addrx4 + j * 8, fors_tree_addr); - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_set_type(fors_leaf_addrx4 + j * 8, PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_ADDR_TYPE_FORSTREE); + set_tree_index(fors_leaf_addrx4 + j * 8, addr_idx + j); + set_type(fors_leaf_addrx4 + j * 8, SPX_ADDR_TYPE_FORSPRF); } - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_set_tree_index(fors_leaf_addrx4 + 0 * 8, addr_idx0); - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_set_tree_index(fors_leaf_addrx4 + 1 * 8, addr_idx1); - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_set_tree_index(fors_leaf_addrx4 + 2 * 8, addr_idx2); - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_set_tree_index(fors_leaf_addrx4 + 3 * 8, addr_idx3); + fors_gen_skx4(leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + leaf + 2 * SPX_N, + leaf + 3 * SPX_N, + ctx, fors_leaf_addrx4); + + for (j = 0; j < 4; j++) { + set_type(fors_leaf_addrx4 + j * 8, SPX_ADDR_TYPE_FORSTREE); + } - fors_gen_skx4(leaf0, leaf1, leaf2, leaf3, sk_seed, fors_leaf_addrx4, state_seeded); - fors_sk_to_leafx4(leaf0, leaf1, leaf2, leaf3, - leaf0, leaf1, leaf2, leaf3, pub_seed, fors_leaf_addrx4, state_seeded); + fors_sk_to_leafx4(leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + leaf + 2 * SPX_N, + leaf + 3 * SPX_N, + leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + leaf + 2 * SPX_N, + leaf + 3 * SPX_N, + ctx, fors_leaf_addrx4); } /** - * Interprets m as PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_FORS_HEIGHT-bit unsigned integers. - * Assumes m contains at least PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_FORS_TREES bits. - * Assumes indices has space for PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_FORS_TREES integers. + * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + * Assumes indices has space for SPX_FORS_TREES integers. */ static void message_to_indices(uint32_t *indices, const unsigned char *m) { unsigned int i, j; unsigned int offset = 0; - for (i = 0; i < PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_FORS_TREES; i++) { + for (i = 0; i < SPX_FORS_TREES; i++) { indices[i] = 0; - for (j = 0; j < PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_FORS_HEIGHT; j++) { - indices[i] ^= (((uint32_t)m[offset >> 3] >> (offset & 0x7)) & 0x1) << j; + for (j = 0; j < SPX_FORS_HEIGHT; j++) { + indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); offset++; } } @@ -92,68 +105,53 @@ static void message_to_indices(uint32_t *indices, const unsigned char *m) { /** * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_FORS_TREES bits. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. */ -void PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *state_seeded) { - /* Round up to multiple of 4 to prevent out-of-bounds for x4 parallelism */ - uint32_t indices[(PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_FORS_TREES + 3) & ~3] = {0}; - unsigned char roots[((PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_FORS_TREES + 3) & ~3) * PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N]; - /* Sign to a buffer, since we may not have a nice multiple of 4 and would - otherwise overrun the signature. */ - unsigned char sigbufx4[4 * PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N * (1 + PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_FORS_HEIGHT)]; - uint32_t fors_tree_addrx4[4 * 8] = {0}; +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + uint32_t fors_tree_addr[4 * 8] = {0}; + struct fors_gen_leaf_info fors_info = {0}; + uint32_t *fors_leaf_addr = fors_info.leaf_addrx; uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset[4] = {0}; - unsigned int i, j; + uint32_t idx_offset; + unsigned int i; - for (j = 0; j < 4; j++) { - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_copy_keypair_addr(fors_tree_addrx4 + j * 8, fors_addr); - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_set_type(fors_tree_addrx4 + j * 8, PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_ADDR_TYPE_FORSTREE); + for (i = 0; i < 4; i++) { + copy_keypair_addr(fors_tree_addr + 8 * i, fors_addr); + set_type(fors_tree_addr + 8 * i, SPX_ADDR_TYPE_FORSTREE); + copy_keypair_addr(fors_leaf_addr + 8 * i, fors_addr); } - - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_copy_keypair_addr(fors_pk_addr, fors_addr); - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_set_type(fors_pk_addr, PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_ADDR_TYPE_FORSPK); + copy_keypair_addr(fors_pk_addr, fors_addr); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); message_to_indices(indices, m); - for (i = 0; i < ((PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_FORS_TREES + 3) & ~0x3); i += 4) { - for (j = 0; j < 4; j++) { - if (i + j < PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_FORS_TREES) { - idx_offset[j] = (i + j) * (1 << PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_FORS_HEIGHT); + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_set_tree_height(fors_tree_addrx4 + j * 8, 0); - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_set_tree_index(fors_tree_addrx4 + j * 8, - indices[i + j] + idx_offset[j]); - } - } + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); - /* Include the secret key part that produces the selected leaf nodes. */ - fors_gen_skx4(sigbufx4 + 0 * PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N, - sigbufx4 + 1 * PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N, - sigbufx4 + 2 * PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N, - sigbufx4 + 3 * PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N, - sk_seed, fors_tree_addrx4, state_seeded); - - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_treehashx4_FORS_HEIGHT(roots + i * PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N, sigbufx4 + 4 * PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N, sk_seed, pub_seed, - &indices[i], idx_offset, fors_gen_leafx4, fors_tree_addrx4, - state_seeded); - - for (j = 0; j < 4; j++) { - if (i + j < PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_FORS_TREES) { - memcpy(sig, sigbufx4 + j * PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N, PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N); - memcpy(sig + PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N, - sigbufx4 + 4 * PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N + j * PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N * PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_FORS_HEIGHT, - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N * PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_FORS_HEIGHT); - sig += PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N * (1 + PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_FORS_HEIGHT); - } - } + /* Include the secret key part that produces the selected leaf node. */ + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); + fors_gen_sk(sig, ctx, fors_tree_addr); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + sig += SPX_N; + + /* Compute the authentication path for this leaf node. */ + treehashx4(roots + i * SPX_N, sig, ctx, + indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx4, + fors_tree_addr, &fors_info); + + sig += SPX_N * SPX_FORS_HEIGHT; } /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_thash_FORS_TREES(pk, roots, pub_seed, fors_pk_addr, state_seeded); + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); } /** @@ -161,46 +159,44 @@ void PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_fors_sign(unsigned char *sig, unsigne * This can be used for verification by comparing to a known public key, or to * subsequently verify a signature on the derived public key. The latter is the * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_FORS_TREES bits. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. */ -void PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, - const uint32_t fors_addr[8], - const hash_state *state_seeded) { - uint32_t indices[PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_FORS_TREES]; - unsigned char roots[PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_FORS_TREES * PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N]; - unsigned char leaf[PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N]; +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + unsigned char leaf[SPX_N]; uint32_t fors_tree_addr[8] = {0}; uint32_t fors_pk_addr[8] = {0}; uint32_t idx_offset; unsigned int i; - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_copy_keypair_addr(fors_tree_addr, fors_addr); - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_copy_keypair_addr(fors_pk_addr, fors_addr); + copy_keypair_addr(fors_tree_addr, fors_addr); + copy_keypair_addr(fors_pk_addr, fors_addr); - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_set_type(fors_tree_addr, PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_set_type(fors_pk_addr, PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_ADDR_TYPE_FORSPK); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); message_to_indices(indices, m); - for (i = 0; i < PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_FORS_TREES; i++) { - idx_offset = i * (1 << PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_FORS_HEIGHT); + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_set_tree_height(fors_tree_addr, 0); - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_set_tree_index(fors_tree_addr, indices[i] + idx_offset); + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); /* Derive the leaf from the included secret key part. */ - fors_sk_to_leaf(leaf, sig, pub_seed, fors_tree_addr, state_seeded); - sig += PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N; + fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); + sig += SPX_N; /* Derive the corresponding root node of this tree. */ - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_compute_root(roots + i * PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N, leaf, indices[i], idx_offset, - sig, PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_FORS_HEIGHT, pub_seed, fors_tree_addr, - state_seeded); - sig += PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N * PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_FORS_HEIGHT; + compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, + sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); + sig += SPX_N * SPX_FORS_HEIGHT; } /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_thash_FORS_TREES(pk, roots, pub_seed, fors_pk_addr, state_seeded); + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/fors.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/fors.h index bc9e2d7694..509140a178 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/fors.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/fors.h @@ -1,32 +1,32 @@ -#ifndef PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_FORS_H -#define PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_FORS_H +#ifndef SPX_FORS_H +#define SPX_FORS_H #include -#include "hash_state.h" +#include "context.h" #include "params.h" /** * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_FORS_TREES bits. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. */ -void PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_fors_sign( - unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *hash_state_seeded); +#define fors_sign SPX_NAMESPACE(fors_sign) +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); /** * Derives the FORS public key from a signature. * This can be used for verification by comparing to a known public key, or to * subsequently verify a signature on the derived public key. The latter is the * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_FORS_TREES bits. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. */ -void PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_fors_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, const uint32_t fors_addr[8], - const hash_state *hash_state_seeded); +#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/haraka.c index 0c866b321d..b414b691d7 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/haraka.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/haraka.c @@ -8,10 +8,12 @@ Plain C implementation of the Haraka256 and Haraka512 permutations. #include #include "haraka.h" +#include "harakax4.h" +#include "utils.h" #define HARAKAS_RATE 32 -#define u64 uint64_t +#define u64 unsigned long #define u128 __m128i #define LOAD(src) _mm_loadu_si128((u128 *)(src)) @@ -20,7 +22,7 @@ Plain C implementation of the Haraka256 and Haraka512 permutations. #define XOR128(a, b) _mm_xor_si128(a, b) #define AES2(s0, s1, rci) \ - (s0) = _mm_aesenc_si128(s0, *(rci)); \ + s0 = _mm_aesenc_si128(s0, *(rci)); \ (s1) = _mm_aesenc_si128(s1, *((rci) + 1)); \ (s0) = _mm_aesenc_si128(s0, *((rci) + 2)); \ (s1) = _mm_aesenc_si128(s1, *((rci) + 3)); @@ -32,7 +34,7 @@ Plain C implementation of the Haraka256 and Haraka512 permutations. AES2((s3)[0], (s3)[1], rci); #define AES4(s0, s1, s2, s3, rci) \ - (s0) = _mm_aesenc_si128(s0, *(rci)); \ + s0 = _mm_aesenc_si128(s0, *(rci)); \ (s1) = _mm_aesenc_si128(s1, *((rci) + 1)); \ (s2) = _mm_aesenc_si128(s2, *((rci) + 2)); \ (s3) = _mm_aesenc_si128(s3, *((rci) + 3)); \ @@ -68,17 +70,17 @@ Plain C implementation of the Haraka256 and Haraka512 permutations. _mm_storeu_si128((u128 *)((out) + 16), \ _mm_castpd_si128(_mm_shuffle_pd(_mm_castsi128_pd(s2), _mm_castsi128_pd(s3), 0))); -static void load_haraka_constants(u128 rc[40]) { - rc[ 0] = _mm_set_epi32((int)0x0684704c, (int)0xe620c00a, (int)0xb2c5fef0, (int)0x75817b9d); - rc[ 1] = _mm_set_epi32((int)0x8b66b4e1, (int)0x88f3a06b, (int)0x640f6ba4, (int)0x2f08f717); - rc[ 2] = _mm_set_epi32((int)0x3402de2d, (int)0x53f28498, (int)0xcf029d60, (int)0x9f029114); - rc[ 3] = _mm_set_epi32((int)0x0ed6eae6, (int)0x2e7b4f08, (int)0xbbf3bcaf, (int)0xfd5b4f79); - rc[ 4] = _mm_set_epi32((int)0xcbcfb0cb, (int)0x4872448b, (int)0x79eecd1c, (int)0xbe397044); - rc[ 5] = _mm_set_epi32((int)0x7eeacdee, (int)0x6e9032b7, (int)0x8d5335ed, (int)0x2b8a057b); - rc[ 6] = _mm_set_epi32((int)0x67c28f43, (int)0x5e2e7cd0, (int)0xe2412761, (int)0xda4fef1b); - rc[ 7] = _mm_set_epi32((int)0x2924d9b0, (int)0xafcacc07, (int)0x675ffde2, (int)0x1fc70b3b); - rc[ 8] = _mm_set_epi32((int)0xab4d63f1, (int)0xe6867fe9, (int)0xecdb8fca, (int)0xb9d465ee); - rc[ 9] = _mm_set_epi32((int)0x1c30bf84, (int)0xd4b7cd64, (int)0x5b2a404f, (int)0xad037e33); +static void load_haraka_constants(u128 *rc) { + rc[0] = _mm_set_epi32((int)0x0684704c, (int)0xe620c00a, (int)0xb2c5fef0, (int)0x75817b9d); + rc[1] = _mm_set_epi32((int)0x8b66b4e1, (int)0x88f3a06b, (int)0x640f6ba4, (int)0x2f08f717); + rc[2] = _mm_set_epi32((int)0x3402de2d, (int)0x53f28498, (int)0xcf029d60, (int)0x9f029114); + rc[3] = _mm_set_epi32((int)0x0ed6eae6, (int)0x2e7b4f08, (int)0xbbf3bcaf, (int)0xfd5b4f79); + rc[4] = _mm_set_epi32((int)0xcbcfb0cb, (int)0x4872448b, (int)0x79eecd1c, (int)0xbe397044); + rc[5] = _mm_set_epi32((int)0x7eeacdee, (int)0x6e9032b7, (int)0x8d5335ed, (int)0x2b8a057b); + rc[6] = _mm_set_epi32((int)0x67c28f43, (int)0x5e2e7cd0, (int)0xe2412761, (int)0xda4fef1b); + rc[7] = _mm_set_epi32((int)0x2924d9b0, (int)0xafcacc07, (int)0x675ffde2, (int)0x1fc70b3b); + rc[8] = _mm_set_epi32((int)0xab4d63f1, (int)0xe6867fe9, (int)0xecdb8fca, (int)0xb9d465ee); + rc[9] = _mm_set_epi32((int)0x1c30bf84, (int)0xd4b7cd64, (int)0x5b2a404f, (int)0xad037e33); rc[10] = _mm_set_epi32((int)0xb2cc0bb9, (int)0x941723bf, (int)0x69028b2e, (int)0x8df69800); rc[11] = _mm_set_epi32((int)0xfa0478a6, (int)0xde6f5572, (int)0x4aaa9ec8, (int)0x5c9d2d8a); rc[12] = _mm_set_epi32((int)0xdfb49f2b, (int)0x6b772a12, (int)0x0efa4f2e, (int)0x29129fd4); @@ -111,77 +113,65 @@ static void load_haraka_constants(u128 rc[40]) { rc[39] = _mm_set_epi32((int)0x756acc03, (int)0x02288288, (int)0x4ad6bdfd, (int)0xe9c59da1); } -void PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_tweak_constants( - harakactx *state, - const unsigned char *pk_seed, const unsigned char *sk_seed, - unsigned long long seed_length) { +void tweak_constants(spx_ctx *ctx) { int i; unsigned char buf[40 * 16]; /* Use the standard constants to generate tweaked ones. */ - load_haraka_constants(state->rc); - - /* Constants for sk.seed */ - if (sk_seed != NULL) { - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_haraka_S(buf, 40 * 16, sk_seed, seed_length, state); - /* Tweak constants with the pub_seed */ - for (i = 0; i < 40; i++) { - state->rc_sseed[i] = LOAD(buf + i * 16); - } - } + load_haraka_constants(ctx->rc); /* Constants for pk.seed */ - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_haraka_S(buf, 40 * 16, pk_seed, seed_length, state); + haraka_S(buf, 40 * 16, ctx->pub_seed, SPX_N, ctx); /* Tweak constants with the pub_seed */ for (i = 0; i < 40; i++) { - state->rc[i] = LOAD(buf + i * 16); + ctx->rc[i] = LOAD(buf + i * 16); } } -static void haraka_S_absorb(unsigned char *s, +static void haraka_S_absorb(unsigned char *s, unsigned int r, const unsigned char *m, unsigned long long mlen, - unsigned char p, - const harakactx *state) { + unsigned char p, const spx_ctx *ctx) { unsigned long long i; - unsigned char t[HARAKAS_RATE]; + PQCLEAN_VLA(unsigned char, t, r); - while (mlen >= HARAKAS_RATE) { + while (mlen >= r) { // XOR block to state STORE(s, XOR128(LOAD(s), LOAD(m))); STORE(s + 16, XOR128(LOAD(s + 16), LOAD(m + 16))); - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_haraka512_perm(s, s, state); - mlen -= HARAKAS_RATE; - m += HARAKAS_RATE; + haraka512_perm(s, s, ctx); + mlen -= r; + m += r; } - for (i = 0; i < HARAKAS_RATE; ++i) { + for (i = 0; i < r; ++i) { t[i] = 0; } for (i = 0; i < mlen; ++i) { t[i] = m[i]; } t[i] = p; - t[HARAKAS_RATE - 1] |= 128; + t[r - 1] |= 128; STORE(s, XOR128(LOAD(s), LOAD(t))); STORE(s + 16, XOR128(LOAD(s + 16), LOAD(t + 16))); } static void haraka_S_absorb4x(unsigned char *s, + unsigned int r, const unsigned char *m0, const unsigned char *m1, const unsigned char *m2, const unsigned char *m3, unsigned long long int mlen, unsigned char p, - const harakactx *state) { + const spx_ctx *ctx) { unsigned long long i; - unsigned char t0[HARAKAS_RATE]; - unsigned char t1[HARAKAS_RATE]; - unsigned char t2[HARAKAS_RATE]; - unsigned char t3[HARAKAS_RATE]; + PQCLEAN_VLA(unsigned char, t0, r); + PQCLEAN_VLA(unsigned char, t1, r); + PQCLEAN_VLA(unsigned char, t2, r); + PQCLEAN_VLA(unsigned char, t3, r); - while (mlen >= HARAKAS_RATE) { + while (mlen >= r) { // XOR block to state STORE(s, XOR128(LOAD(s), LOAD(m0))); STORE(s + 16, XOR128(LOAD(s + 16), LOAD(m0 + 16))); @@ -192,15 +182,15 @@ static void haraka_S_absorb4x(unsigned char *s, STORE(s + 192, XOR128(LOAD(s + 192), LOAD(m3))); STORE(s + 208, XOR128(LOAD(s + 208), LOAD(m3 + 16))); - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_haraka512_perm_x4(s, s, state); - mlen -= HARAKAS_RATE; - m0 += HARAKAS_RATE; - m1 += HARAKAS_RATE; - m2 += HARAKAS_RATE; - m3 += HARAKAS_RATE; + haraka512_perm_x4(s, s, ctx); + mlen -= r; + m0 += r; + m1 += r; + m2 += r; + m3 += r; } - for (i = 0; i < HARAKAS_RATE; ++i) { + for (i = 0; i < r; ++i) { t0[i] = 0; t1[i] = 0; t2[i] = 0; @@ -218,10 +208,10 @@ static void haraka_S_absorb4x(unsigned char *s, t2[i] = p; t3[i] = p; - t0[HARAKAS_RATE - 1] |= 128; - t1[HARAKAS_RATE - 1] |= 128; - t2[HARAKAS_RATE - 1] |= 128; - t3[HARAKAS_RATE - 1] |= 128; + t0[r - 1] |= 128; + t1[r - 1] |= 128; + t2[r - 1] |= 128; + t3[r - 1] |= 128; STORE(s, XOR128(LOAD(s), LOAD(t0))); STORE(s + 16, XOR128(LOAD(s + 16), LOAD(t0 + 16))); @@ -234,9 +224,10 @@ static void haraka_S_absorb4x(unsigned char *s, } static void haraka_S_squeezeblocks(unsigned char *h, unsigned long long nblocks, - unsigned char *s, unsigned int r, const harakactx *state) { + unsigned char *s, unsigned int r, + const spx_ctx *ctx) { while (nblocks > 0) { - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_haraka512_perm(s, s, state); + haraka512_perm(s, s, ctx); STORE(h, LOAD(s)); STORE(h + 16, LOAD(s + 16)); h += r; @@ -251,9 +242,9 @@ static void haraka_S_squeezeblocks4x(unsigned char *h0, unsigned long long nblocks, unsigned char *s, unsigned int r, - const harakactx *state) { + const spx_ctx *ctx) { while (nblocks > 0) { - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_haraka512_perm_x4(s, s, state); + haraka512_perm_x4(s, s, ctx); STORE(h0, LOAD(s)); STORE(h0 + 16, LOAD(s + 16)); STORE(h1, LOAD(s + 64)); @@ -270,7 +261,7 @@ static void haraka_S_squeezeblocks4x(unsigned char *h0, } } -void PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_haraka_S_inc_init(uint8_t *s_inc) { +void haraka_S_inc_init(uint8_t *s_inc) { size_t i; for (i = 0; i < 64; i++) { @@ -279,7 +270,8 @@ void PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_haraka_S_inc_init(uint8_t *s_inc) { s_inc[64] = 0; } -void PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, const harakactx *state) { +void haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, + const spx_ctx *ctx) { size_t i; /* Recall that s_inc[64] is the non-absorbed bytes xored into the state */ @@ -293,16 +285,16 @@ void PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_haraka_S_inc_absorb(uint8_t *s_inc, c m += HARAKAS_RATE - s_inc[64]; s_inc[64] = 0; - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_haraka512_perm(s_inc, s_inc, state); + haraka512_perm(s_inc, s_inc, ctx); } for (i = 0; i < mlen; i++) { s_inc[s_inc[64] + i] ^= m[i]; } - s_inc[64] = (uint8_t)(s_inc[64] + mlen); + s_inc[64] += (uint8_t)mlen; } -void PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_haraka_S_inc_finalize(uint8_t *s_inc) { +void haraka_S_inc_finalize(uint8_t *s_inc) { /* After haraka_S_inc_absorb, we are guaranteed that s_inc[64] < HARAKAS_RATE, so we can always use one more byte for p in the current state. */ s_inc[s_inc[64]] ^= 0x1F; @@ -310,22 +302,23 @@ void PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_haraka_S_inc_finalize(uint8_t *s_inc) s_inc[64] = 0; } -void PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, const harakactx *state) { +void haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, + const spx_ctx *ctx) { size_t i; /* First consume any bytes we still have sitting around */ for (i = 0; i < outlen && i < s_inc[64]; i++) { /* There are s_inc[64] bytes left, so r - s_inc[64] is the first available byte. We consume from there, i.e., up to r. */ - out[i] = (uint8_t)s_inc[(HARAKAS_RATE - s_inc[64] + (uint8_t)i)]; + out[i] = (uint8_t)s_inc[(HARAKAS_RATE - s_inc[64] + i)]; } out += i; outlen -= i; - s_inc[64] = (uint8_t)(s_inc[64] - i); + s_inc[64] -= (uint8_t)i; /* Then squeeze the remaining necessary blocks */ while (outlen > 0) { - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_haraka512_perm(s_inc, s_inc, state); + haraka512_perm(s_inc, s_inc, ctx); for (i = 0; i < outlen && i < HARAKAS_RATE; i++) { out[i] = s_inc[i]; @@ -336,8 +329,9 @@ void PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_haraka_S_inc_squeeze(uint8_t *out, si } } -void PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_haraka_S(unsigned char *out, unsigned long long outlen, - const unsigned char *in, unsigned long long inlen, const harakactx *state) { +void haraka_S(unsigned char *out, unsigned long long outlen, + const unsigned char *in, unsigned long long inlen, + const spx_ctx *ctx) { unsigned long long i; unsigned char s[64]; unsigned char d[32]; @@ -345,30 +339,30 @@ void PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_haraka_S(unsigned char *out, unsigned for (i = 0; i < 64; i++) { s[i] = 0; } - haraka_S_absorb(s, in, inlen, 0x1F, state); + haraka_S_absorb(s, HARAKAS_RATE, in, inlen, 0x1F, ctx); - haraka_S_squeezeblocks(out, outlen / HARAKAS_RATE, s, HARAKAS_RATE, state); + haraka_S_squeezeblocks(out, outlen / HARAKAS_RATE, s, HARAKAS_RATE, ctx); out += (outlen / HARAKAS_RATE) * HARAKAS_RATE; if (outlen % HARAKAS_RATE) { - haraka_S_squeezeblocks(d, 1, s, HARAKAS_RATE, state); + haraka_S_squeezeblocks(d, 1, s, HARAKAS_RATE, ctx); for (i = 0; i < outlen % HARAKAS_RATE; i++) { out[i] = d[i]; } } } -void PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_haraka_Sx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned long long outlen, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - unsigned long long inlen, - const harakactx *state) { +void haraka_Sx4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned long long outlen, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + unsigned long long inlen, + const spx_ctx *ctx) { unsigned long long i; unsigned char s[64 * 4]; unsigned char d0[32]; @@ -379,16 +373,17 @@ void PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_haraka_Sx4(unsigned char *out0, for (i = 0; i < 64 * 4; i++) { s[i] = 0; } - haraka_S_absorb4x(s, in0, in1, in2, in3, inlen, 0x1F, state); + haraka_S_absorb4x(s, HARAKAS_RATE, in0, in1, in2, in3, inlen, 0x1F, ctx); - haraka_S_squeezeblocks4x(out0, out1, out2, out3, outlen / HARAKAS_RATE, s, HARAKAS_RATE, state); + haraka_S_squeezeblocks4x(out0, out1, out2, out3, outlen / HARAKAS_RATE, s, + HARAKAS_RATE, ctx); out0 += (outlen / HARAKAS_RATE) * HARAKAS_RATE; out1 += (outlen / HARAKAS_RATE) * HARAKAS_RATE; out2 += (outlen / HARAKAS_RATE) * HARAKAS_RATE; out3 += (outlen / HARAKAS_RATE) * HARAKAS_RATE; if (outlen % HARAKAS_RATE) { - haraka_S_squeezeblocks4x(d0, d1, d2, d3, 1, s, HARAKAS_RATE, state); + haraka_S_squeezeblocks4x(d0, d1, d2, d3, 1, s, HARAKAS_RATE, ctx); for (i = 0; i < outlen % HARAKAS_RATE; i++) { out0[i] = d0[i]; out1[i] = d1[i]; @@ -398,7 +393,8 @@ void PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_haraka_Sx4(unsigned char *out0, } } -void PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_haraka512_perm(unsigned char *out, const unsigned char *in, const harakactx *state) { +void haraka512_perm(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx) { u128 s[4], tmp; s[0] = LOAD(in); @@ -406,19 +402,19 @@ void PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_haraka512_perm(unsigned char *out, co s[2] = LOAD(in + 32); s[3] = LOAD(in + 48); - AES4(s[0], s[1], s[2], s[3], state->rc); + AES4(s[0], s[1], s[2], s[3], ctx->rc); MIX4(s[0], s[1], s[2], s[3]); - AES4(s[0], s[1], s[2], s[3], state->rc + 8); + AES4(s[0], s[1], s[2], s[3], ctx->rc + 8); MIX4(s[0], s[1], s[2], s[3]); - AES4(s[0], s[1], s[2], s[3], state->rc + 16); + AES4(s[0], s[1], s[2], s[3], ctx->rc + 16); MIX4(s[0], s[1], s[2], s[3]); - AES4(s[0], s[1], s[2], s[3], state->rc + 24); + AES4(s[0], s[1], s[2], s[3], ctx->rc + 24); MIX4(s[0], s[1], s[2], s[3]); - AES4(s[0], s[1], s[2], s[3], state->rc + 32); + AES4(s[0], s[1], s[2], s[3], ctx->rc + 32); MIX4(s[0], s[1], s[2], s[3]); STORE(out, s[0]); @@ -427,7 +423,8 @@ void PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_haraka512_perm(unsigned char *out, co STORE(out + 48, s[3]); } -void PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_haraka512_perm_x4(unsigned char *out, const unsigned char *in, const harakactx *state) { +void haraka512_perm_x4(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx) { u128 s[4][4], tmp; s[0][0] = LOAD(in); @@ -447,31 +444,31 @@ void PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_haraka512_perm_x4(unsigned char *out, s[3][2] = LOAD(in + 224); s[3][3] = LOAD(in + 240); - AES4_4x(s[0], s[1], s[2], s[3], state->rc); + AES4_4x(s[0], s[1], s[2], s[3], ctx->rc); MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - AES4_4x(s[0], s[1], s[2], s[3], state->rc + 8); + AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 8); MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - AES4_4x(s[0], s[1], s[2], s[3], state->rc + 16); + AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 16); MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - AES4_4x(s[0], s[1], s[2], s[3], state->rc + 24); + AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 24); MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - AES4_4x(s[0], s[1], s[2], s[3], state->rc + 32); + AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 32); MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); @@ -495,7 +492,8 @@ void PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_haraka512_perm_x4(unsigned char *out, STORE(out + 240, s[3][3]); } -void PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_haraka512(unsigned char *out, const unsigned char *in, const harakactx *state) { +void haraka512(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx) { u128 s[4], tmp; s[0] = LOAD(in); @@ -503,19 +501,19 @@ void PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_haraka512(unsigned char *out, const u s[2] = LOAD(in + 32); s[3] = LOAD(in + 48); - AES4(s[0], s[1], s[2], s[3], state->rc); + AES4(s[0], s[1], s[2], s[3], ctx->rc); MIX4(s[0], s[1], s[2], s[3]); - AES4(s[0], s[1], s[2], s[3], state->rc + 8); + AES4(s[0], s[1], s[2], s[3], ctx->rc + 8); MIX4(s[0], s[1], s[2], s[3]); - AES4(s[0], s[1], s[2], s[3], state->rc + 16); + AES4(s[0], s[1], s[2], s[3], ctx->rc + 16); MIX4(s[0], s[1], s[2], s[3]); - AES4(s[0], s[1], s[2], s[3], state->rc + 24); + AES4(s[0], s[1], s[2], s[3], ctx->rc + 24); MIX4(s[0], s[1], s[2], s[3]); - AES4(s[0], s[1], s[2], s[3], state->rc + 32); + AES4(s[0], s[1], s[2], s[3], ctx->rc + 32); MIX4(s[0], s[1], s[2], s[3]); s[0] = XOR128(s[0], LOAD(in)); @@ -527,7 +525,8 @@ void PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_haraka512(unsigned char *out, const u TRUNCSTORE(out, s[0], s[1], s[2], s[3]); } -void PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_haraka512x4(unsigned char *out, const unsigned char *in, const harakactx *state) { +void haraka512x4(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx) { u128 s[4][4], tmp; s[0][0] = LOAD(in); @@ -547,31 +546,31 @@ void PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_haraka512x4(unsigned char *out, const s[3][2] = LOAD(in + 224); s[3][3] = LOAD(in + 240); - AES4_4x(s[0], s[1], s[2], s[3], state->rc); + AES4_4x(s[0], s[1], s[2], s[3], ctx->rc); MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - AES4_4x(s[0], s[1], s[2], s[3], state->rc + 8); + AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 8); MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - AES4_4x(s[0], s[1], s[2], s[3], state->rc + 16); + AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 16); MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - AES4_4x(s[0], s[1], s[2], s[3], state->rc + 24); + AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 24); MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - AES4_4x(s[0], s[1], s[2], s[3], state->rc + 32); + AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 32); MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); @@ -600,25 +599,26 @@ void PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_haraka512x4(unsigned char *out, const TRUNCSTORE((out + 96), s[3][0], s[3][1], s[3][2], s[3][3]); } -void PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_haraka256(unsigned char *out, const unsigned char *in, const harakactx *state) { +void haraka256(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx) { u128 s[2], tmp; s[0] = LOAD(in); s[1] = LOAD(in + 16); - AES2(s[0], s[1], state->rc); + AES2(s[0], s[1], ctx->rc); MIX2(s[0], s[1]); - AES2(s[0], s[1], state->rc + 4); + AES2(s[0], s[1], ctx->rc + 4); MIX2(s[0], s[1]); - AES2(s[0], s[1], state->rc + 8); + AES2(s[0], s[1], ctx->rc + 8); MIX2(s[0], s[1]); - AES2(s[0], s[1], state->rc + 12); + AES2(s[0], s[1], ctx->rc + 12); MIX2(s[0], s[1]); - AES2(s[0], s[1], state->rc + 16); + AES2(s[0], s[1], ctx->rc + 16); MIX2(s[0], s[1]); s[0] = XOR128(s[0], LOAD(in)); @@ -628,7 +628,8 @@ void PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_haraka256(unsigned char *out, const u STORE(out + 16, s[1]); } -void PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_haraka256x4(unsigned char *out, const unsigned char *in, const harakactx *state) { +void haraka256x4(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx) { u128 s[4][2], tmp; s[0][0] = LOAD(in); @@ -641,7 +642,7 @@ void PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_haraka256x4(unsigned char *out, const s[3][1] = LOAD(in + 112); // Round 1 - AES2_4x(s[0], s[1], s[2], s[3], state->rc); + AES2_4x(s[0], s[1], s[2], s[3], ctx->rc); MIX2(s[0][0], s[0][1]); MIX2(s[1][0], s[1][1]); @@ -649,7 +650,7 @@ void PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_haraka256x4(unsigned char *out, const MIX2(s[3][0], s[3][1]); // Round 2 - AES2_4x(s[0], s[1], s[2], s[3], state->rc + 4); + AES2_4x(s[0], s[1], s[2], s[3], ctx->rc + 4); MIX2(s[0][0], s[0][1]); MIX2(s[1][0], s[1][1]); @@ -657,7 +658,7 @@ void PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_haraka256x4(unsigned char *out, const MIX2(s[3][0], s[3][1]); // Round 3 - AES2_4x(s[0], s[1], s[2], s[3], state->rc + 8); + AES2_4x(s[0], s[1], s[2], s[3], ctx->rc + 8); MIX2(s[0][0], s[0][1]); MIX2(s[1][0], s[1][1]); @@ -665,7 +666,7 @@ void PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_haraka256x4(unsigned char *out, const MIX2(s[3][0], s[3][1]); // Round 4 - AES2_4x(s[0], s[1], s[2], s[3], state->rc + 12); + AES2_4x(s[0], s[1], s[2], s[3], ctx->rc + 12); MIX2(s[0][0], s[0][1]); MIX2(s[1][0], s[1][1]); @@ -673,7 +674,7 @@ void PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_haraka256x4(unsigned char *out, const MIX2(s[3][0], s[3][1]); // Round 5 - AES2_4x(s[0], s[1], s[2], s[3], state->rc + 16); + AES2_4x(s[0], s[1], s[2], s[3], ctx->rc + 16); MIX2(s[0][0], s[0][1]); MIX2(s[1][0], s[1][1]); @@ -699,103 +700,3 @@ void PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_haraka256x4(unsigned char *out, const STORE(out + 96, s[3][0]); STORE(out + 112, s[3][1]); } - -void PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_haraka256_sk(unsigned char *out, const unsigned char *in, const harakactx *state) { - u128 s[2], tmp; - - s[0] = LOAD(in); - s[1] = LOAD(in + 16); - - AES2(s[0], s[1], state->rc_sseed); - MIX2(s[0], s[1]); - - AES2(s[0], s[1], state->rc_sseed + 4); - MIX2(s[0], s[1]); - - AES2(s[0], s[1], state->rc_sseed + 8); - MIX2(s[0], s[1]); - - AES2(s[0], s[1], state->rc_sseed + 12); - MIX2(s[0], s[1]); - - AES2(s[0], s[1], state->rc_sseed + 16); - MIX2(s[0], s[1]); - - s[0] = XOR128(s[0], LOAD(in)); - s[1] = XOR128(s[1], LOAD(in + 16)); - - STORE(out, s[0]); - STORE(out + 16, s[1]); -} - -void PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_haraka256_skx4(unsigned char *out, const unsigned char *in, const harakactx *state) { - u128 s[4][2], tmp; - - s[0][0] = LOAD(in); - s[0][1] = LOAD(in + 16); - s[1][0] = LOAD(in + 32); - s[1][1] = LOAD(in + 48); - s[2][0] = LOAD(in + 64); - s[2][1] = LOAD(in + 80); - s[3][0] = LOAD(in + 96); - s[3][1] = LOAD(in + 112); - - // Round 1 - AES2_4x(s[0], s[1], s[2], s[3], state->rc_sseed); - - MIX2(s[0][0], s[0][1]); - MIX2(s[1][0], s[1][1]); - MIX2(s[2][0], s[2][1]); - MIX2(s[3][0], s[3][1]); - - // Round 2 - AES2_4x(s[0], s[1], s[2], s[3], state->rc_sseed + 4); - - MIX2(s[0][0], s[0][1]); - MIX2(s[1][0], s[1][1]); - MIX2(s[2][0], s[2][1]); - MIX2(s[3][0], s[3][1]); - - // Round 3 - AES2_4x(s[0], s[1], s[2], s[3], state->rc_sseed + 8); - - MIX2(s[0][0], s[0][1]); - MIX2(s[1][0], s[1][1]); - MIX2(s[2][0], s[2][1]); - MIX2(s[3][0], s[3][1]); - - // Round 4 - AES2_4x(s[0], s[1], s[2], s[3], state->rc_sseed + 12); - - MIX2(s[0][0], s[0][1]); - MIX2(s[1][0], s[1][1]); - MIX2(s[2][0], s[2][1]); - MIX2(s[3][0], s[3][1]); - - // Round 5 - AES2_4x(s[0], s[1], s[2], s[3], state->rc_sseed + 16); - - MIX2(s[0][0], s[0][1]); - MIX2(s[1][0], s[1][1]); - MIX2(s[2][0], s[2][1]); - MIX2(s[3][0], s[3][1]); - - // Feed Forward - s[0][0] = XOR128(s[0][0], LOAD(in)); - s[0][1] = XOR128(s[0][1], LOAD(in + 16)); - s[1][0] = XOR128(s[1][0], LOAD(in + 32)); - s[1][1] = XOR128(s[1][1], LOAD(in + 48)); - s[2][0] = XOR128(s[2][0], LOAD(in + 64)); - s[2][1] = XOR128(s[2][1], LOAD(in + 80)); - s[3][0] = XOR128(s[3][0], LOAD(in + 96)); - s[3][1] = XOR128(s[3][1], LOAD(in + 112)); - - STORE(out, s[0][0]); - STORE(out + 16, s[0][1]); - STORE(out + 32, s[1][0]); - STORE(out + 48, s[1][1]); - STORE(out + 64, s[2][0]); - STORE(out + 80, s[2][1]); - STORE(out + 96, s[3][0]); - STORE(out + 112, s[3][1]); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/haraka.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/haraka.h index c664af0244..737cb6065f 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/haraka.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/haraka.h @@ -1,57 +1,42 @@ -#ifndef PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_HARAKA_H -#define PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_HARAKA_H +#ifndef SPX_HARAKA_H +#define SPX_HARAKA_H -#include -#include -#include - -typedef struct { - __m128i rc[40]; - __m128i rc_sseed[40]; -} harakactx; +#include "context.h" +#include "params.h" /* Tweak constants with seed */ -void PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_tweak_constants( - harakactx *state, - const unsigned char *pk_seed, const unsigned char *sk_seed, - unsigned long long seed_length); +#define tweak_constants SPX_NAMESPACE(tweak_constants) +void tweak_constants(spx_ctx *ctx); /* Haraka Sponge */ -void PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_haraka_S_inc_init(uint8_t *s_inc); -void PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, const harakactx *state); -void PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_haraka_S_inc_finalize(uint8_t *s_inc); -void PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, const harakactx *state); -void PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_haraka_S( - unsigned char *out, unsigned long long outlen, - const unsigned char *in, unsigned long long inlen, const harakactx *state); -void PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_haraka_Sx4( - unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned long long outlen, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - unsigned long long inlen, - const harakactx *state); - +#define haraka_S_inc_init SPX_NAMESPACE(haraka_S_inc_init) +void haraka_S_inc_init(uint8_t *s_inc); +#define haraka_S_inc_absorb SPX_NAMESPACE(haraka_S_inc_absorb) +void haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, + const spx_ctx *ctx); +#define haraka_S_inc_finalize SPX_NAMESPACE(haraka_S_inc_finalize) +void haraka_S_inc_finalize(uint8_t *s_inc); +#define haraka_S_inc_squeeze SPX_NAMESPACE(haraka_S_inc_squeeze) +void haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, + const spx_ctx *ctx); +#define haraka_S SPX_NAMESPACE(haraka_S) +void haraka_S(unsigned char *out, unsigned long long outlen, + const unsigned char *in, unsigned long long inlen, + const spx_ctx *ctx); /* Applies the 512-bit Haraka permutation to in. */ -void PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_haraka512_perm(unsigned char *out, const unsigned char *in, const harakactx *state); -void PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_haraka512_perm_x4(unsigned char *out, const unsigned char *in, const harakactx *state); +#define haraka512_perm SPX_NAMESPACE(haraka512_perm) +void haraka512_perm(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx); /* Implementation of Haraka-512 */ -void PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_haraka512(unsigned char *out, const unsigned char *in, const harakactx *state); -void PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_haraka512x4(unsigned char *out, const unsigned char *in, const harakactx *state); +#define haraka512 SPX_NAMESPACE(haraka512) +void haraka512(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx); /* Implementation of Haraka-256 */ -void PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_haraka256(unsigned char *out, const unsigned char *in, const harakactx *state); -void PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_haraka256x4(unsigned char *out, const unsigned char *in, const harakactx *state); - -/* Implementation of Haraka-256 using sk.seed constants */ -void PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_haraka256_sk(unsigned char *out, const unsigned char *in, const harakactx *state); -void PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_haraka256_skx4(unsigned char *out, const unsigned char *in, const harakactx *state); +#define haraka256 SPX_NAMESPACE(haraka256) +void haraka256(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/haraka_offsets.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/haraka_offsets.h new file mode 100644 index 0000000000..7c062272a0 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/haraka_offsets.h @@ -0,0 +1,21 @@ +#ifndef HARAKA_OFFSETS_H_ +#define HARAKA_OFFSETS_H_ + +/* + * Offsets of various fields in the address structure when we use Haraka as + * the Sphincs+ hash function + */ + +#define SPX_OFFSET_LAYER 3 /* The byte used to specify the Merkle tree layer */ +#define SPX_OFFSET_TREE 8 /* The start of the 8 byte field used to specify the tree */ +#define SPX_OFFSET_TYPE 19 /* The byte used to specify the hash type (reason) */ +#define SPX_OFFSET_KP_ADDR2 22 /* The high byte used to specify the key pair (which one-time signature) */ +#define SPX_OFFSET_KP_ADDR1 23 /* The low byte used to specify the key pair */ +#define SPX_OFFSET_CHAIN_ADDR 27 /* The byte used to specify the chain address (which Winternitz chain) */ +#define SPX_OFFSET_HASH_ADDR 31 /* The byte used to specify the hash address (where in the Winternitz chain) */ +#define SPX_OFFSET_TREE_HGT 27 /* The byte used to specify the height of this node in the FORS or Merkle tree */ +#define SPX_OFFSET_TREE_INDEX 28 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ + +#define SPX_HARAKA 1 + +#endif /* HARAKA_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/harakax4.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/harakax4.h new file mode 100644 index 0000000000..eadc69aa48 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/harakax4.h @@ -0,0 +1,36 @@ +#ifndef SPX_HARAKAX4_H +#define SPX_HARAKAX4_H + +#include "context.h" +#include "params.h" + +/* Haraka Sponge */ +#define haraka_Sx4 SPX_NAMESPACE(haraka_Sx4) +void haraka_Sx4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned long long outlen, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + unsigned long long inlen, + const spx_ctx *ctx); + +/* Applies the 512-bit Haraka permutation x4 to in. */ +#define haraka512_perm_x4 SPX_NAMESPACE(haraka512_perm_x4) +void haraka512_perm_x4(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx); + +/* Implementation of Haraka-512 x4*/ +#define haraka512x4 SPX_NAMESPACE(haraka512x4) +void haraka512x4(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx); + +/* Implementation of Haraka-256 x4 */ +#define haraka256x4 SPX_NAMESPACE(haraka256x4) +void haraka256x4(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/hash.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/hash.h index 11bf995dca..f7c87d4c3c 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/hash.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/hash.h @@ -1,31 +1,28 @@ -#ifndef PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_HASH_H -#define PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_HASH_H - -#include "hash_state.h" +#ifndef SPX_HASH_H +#define SPX_HASH_H #include #include -void PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_initialize_hash_function( - hash_state *hash_state_seeded, - const unsigned char *pub_seed, const unsigned char *sk_seed); +#include "context.h" +#include "params.h" + +#define prf_addr SPX_NAMESPACE(prf_addr) +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]); -void PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_destroy_hash_function(hash_state *hash_state_seeded); +#define gen_message_random SPX_NAMESPACE(gen_message_random) +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); -void PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded); +#define hash_message SPX_NAMESPACE(hash_message) +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); -void PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); -void PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/hash_haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/hash_haraka.c index 65e6d4635d..750a67423b 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/hash_haraka.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/hash_haraka.c @@ -2,58 +2,44 @@ #include #include "address.h" -#include "haraka.h" -#include "hash.h" #include "params.h" #include "utils.h" -void PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_initialize_hash_function( - hash_state *hash_state_seeded, - const unsigned char *pub_seed, const unsigned char *sk_seed) { - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_tweak_constants(hash_state_seeded, pub_seed, sk_seed, PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N); -} - -/* The haraka implementation is stack based and won't be replaced in PQClean/OQS, - so we don't need to do anything */ -void PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_destroy_hash_function( - hash_state *hash_state_seeded) { // NOLINT(readability-non-const-parameter) - (void)hash_state_seeded; -} +#include "haraka.h" +#include "hash.h" /* - * Computes PRF(key, addr), given a secret key of PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N bytes and an address + * Computes PRF(key, addr), given a secret key of SPX_N bytes and an address */ -void PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded) { - unsigned char buf[PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_ADDR_BYTES]; - /* Since PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N may be smaller than 32, we need a temporary buffer. */ +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]) { + /* Since SPX_N may be smaller than 32, we need temporary buffers. */ unsigned char outbuf[32]; + unsigned char buf[64] = {0}; - (void)key; /* Suppress an 'unused parameter' warning. */ + memcpy(buf, addr, SPX_ADDR_BYTES); + memcpy(buf + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_addr_to_bytes(buf, addr); - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_haraka256_sk(outbuf, buf, hash_state_seeded); - memcpy(out, outbuf, PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N); + haraka512(outbuf, (const void *)buf, ctx); + memcpy(out, outbuf, SPX_N); } /** * Computes the message-dependent randomness R, using a secret seed and an * optional randomization value as well as the message. */ -void PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded) { +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { uint8_t s_inc[65]; - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_haraka_S_inc_init(s_inc); - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_haraka_S_inc_absorb(s_inc, sk_prf, PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_haraka_S_inc_absorb(s_inc, optrand, PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_haraka_S_inc_absorb(s_inc, m, mlen, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_haraka_S_inc_finalize(s_inc); - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_haraka_S_inc_squeeze(R, PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N, s_inc, hash_state_seeded); + haraka_S_inc_init(s_inc); + haraka_S_inc_absorb(s_inc, sk_prf, SPX_N, ctx); + haraka_S_inc_absorb(s_inc, optrand, SPX_N, ctx); + haraka_S_inc_absorb(s_inc, m, mlen, ctx); + haraka_S_inc_finalize(s_inc); + haraka_S_inc_squeeze(R, SPX_N, s_inc, ctx); } /** @@ -61,36 +47,35 @@ void PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_gen_message_random( * Outputs the message digest and the index of the leaf. The index is split in * the tree index and the leaf index, for convenient copying to an address. */ -void PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded) { -#define PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_TREE_BITS (PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_TREE_HEIGHT * (PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_D - 1)) -#define PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_TREE_BYTES ((PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_TREE_BITS + 7) / 8) -#define PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_LEAF_BITS PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_TREE_HEIGHT -#define PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_LEAF_BYTES ((PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_LEAF_BITS + 7) / 8) -#define PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_DGST_BYTES (PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_FORS_MSG_BYTES + PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_TREE_BYTES + PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_LEAF_BYTES) +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { +#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) +#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) +#define SPX_LEAF_BITS SPX_TREE_HEIGHT +#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) +#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) - unsigned char buf[PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_DGST_BYTES]; + unsigned char buf[SPX_DGST_BYTES]; unsigned char *bufp = buf; uint8_t s_inc[65]; - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_haraka_S_inc_init(s_inc); - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_haraka_S_inc_absorb(s_inc, R, PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_haraka_S_inc_absorb(s_inc, pk + PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N, PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_haraka_S_inc_absorb(s_inc, m, mlen, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_haraka_S_inc_finalize(s_inc); - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_haraka_S_inc_squeeze(buf, PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_DGST_BYTES, s_inc, hash_state_seeded); + haraka_S_inc_init(s_inc); + haraka_S_inc_absorb(s_inc, R, SPX_N, ctx); + haraka_S_inc_absorb(s_inc, pk + SPX_N, SPX_N, ctx); // Only absorb root part of pk + haraka_S_inc_absorb(s_inc, m, mlen, ctx); + haraka_S_inc_finalize(s_inc); + haraka_S_inc_squeeze(buf, SPX_DGST_BYTES, s_inc, ctx); + + memcpy(digest, bufp, SPX_FORS_MSG_BYTES); + bufp += SPX_FORS_MSG_BYTES; - memcpy(digest, bufp, PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_FORS_MSG_BYTES); - bufp += PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_FORS_MSG_BYTES; - *tree = PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_bytes_to_ull(bufp, PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_TREE_BYTES); - *tree &= (~(uint64_t)0) >> (64 - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_TREE_BITS); - bufp += PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_TREE_BYTES; + *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); + *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); + bufp += SPX_TREE_BYTES; - *leaf_idx = (uint32_t)PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_bytes_to_ull( - bufp, PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_LEAF_BYTES); - *leaf_idx &= (~(uint32_t)0) >> (32 - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_LEAF_BITS); + *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); + *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/hash_harakax4.c b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/hash_harakax4.c index 0573a557e3..cfa5162d79 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/hash_harakax4.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/hash_harakax4.c @@ -2,36 +2,34 @@ #include #include "address.h" -#include "haraka.h" -#include "hash_state.h" +#include "harakax4.h" #include "hashx4.h" #include "params.h" /* * 4-way parallel version of prf_addr; takes 4x as much input and output */ -void PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_prf_addrx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const unsigned char *key, - const uint32_t addrx4[4 * 8], - const hash_state *state_seeded) { - unsigned char bufx4[4 * PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_ADDR_BYTES]; - /* Since PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N may be smaller than 32, we need a temporary buffer. */ +#define prf_addrx4 SPX_NAMESPACE(prf_addrx4) +void prf_addrx4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const spx_ctx *ctx, + const uint32_t addrx4[4 * 8]) { + unsigned char bufx4[4 * 64] = {0}; + /* Since SPX_N may be smaller than 32, we need temporary buffers. */ unsigned char outbuf[4 * 32]; unsigned int i; - (void)key; /* Suppress an 'unused parameter' warning. */ - for (i = 0; i < 4; i++) { - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_addr_to_bytes(bufx4 + i * PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_ADDR_BYTES, addrx4 + i * 8); + memcpy(bufx4 + i * 64, addrx4 + i * 8, SPX_ADDR_BYTES); + memcpy(bufx4 + i * 64 + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); } - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_haraka256_skx4(outbuf, bufx4, state_seeded); + haraka512x4(outbuf, bufx4, ctx); - memcpy(out0, outbuf, PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N); - memcpy(out1, outbuf + 32, PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N); - memcpy(out2, outbuf + 64, PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N); - memcpy(out3, outbuf + 96, PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N); + memcpy(out0, outbuf, SPX_N); + memcpy(out1, outbuf + 32, SPX_N); + memcpy(out2, outbuf + 64, SPX_N); + memcpy(out3, outbuf + 96, SPX_N); } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/hash_state.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/hash_state.h deleted file mode 100644 index edb46eace6..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/hash_state.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_HASH_STATE_H -#define PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_HASH_STATE_H - -/** - * Defines the type of the hash function state. - * - * Don't be fooled into thinking this instance of SPHINCS+ isn't stateless! - * - * From Section 7.2.2 from the SPHINCS+ round-2 specification: - * - * Each of the instances of the tweakable hash function take PK.seed as its - * first input, which is constant for a given key pair – and, thus, across - * a single signature. This leads to a lot of redundant computation. To remedy - * this, we pad PK.seed to the length of a full 64-byte SHA-256 input block. - * Because of the Merkle-DamgÃ¥rd construction that underlies SHA-256, this - * allows for reuse of the intermediate SHA-256 state after the initial call to - * the compression function which improves performance. - * - * We pass this hash state around in functions, because otherwise we need to - * have a global variable. - */ - -#include "haraka.h" -#define hash_state harakactx - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/hashx4.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/hashx4.h index 7f6ce54ea4..3751a0ebd0 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/hashx4.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/hashx4.h @@ -1,16 +1,17 @@ -#ifndef PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_HASHX4_H -#define PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_HASHX4_H +#ifndef SPX_HASHX4_H +#define SPX_HASHX4_H #include -#include "hash_state.h" +#include "context.h" +#include "params.h" -void PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_prf_addrx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const unsigned char *key, - const uint32_t addrx4[4 * 8], - const hash_state *state_seeded); +#define prf_addrx4 SPX_NAMESPACE(prf_addrx4) +void prf_addrx4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const spx_ctx *ctx, + const uint32_t addrx4[4 * 8]); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/merkle.c b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/merkle.c new file mode 100644 index 0000000000..f57811c1ac --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/merkle.c @@ -0,0 +1,64 @@ +#include +#include + +#include "merkle.h" + +#include "address.h" +#include "params.h" +#include "utils.h" +#include "utilsx4.h" +#include "wots.h" +#include "wotsx4.h" + +/* + * This generates a Merkle signature (WOTS signature followed by the Merkle + * authentication path). + */ +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf) { + unsigned char *auth_path = sig + SPX_WOTS_BYTES; + uint32_t tree_addrx4[4 * 8] = { 0 }; + int j; + struct leaf_info_x4 info = { 0 }; + unsigned steps[ SPX_WOTS_LEN ]; + + info.wots_sig = sig; + chain_lengths(steps, root); + info.wots_steps = steps; + + for (j = 0; j < 4; j++) { + set_type(&tree_addrx4[8 * j], SPX_ADDR_TYPE_HASHTREE); + set_type(&info.leaf_addr[8 * j], SPX_ADDR_TYPE_WOTS); + set_type(&info.pk_addr[8 * j], SPX_ADDR_TYPE_WOTSPK); + copy_subtree_addr(&tree_addrx4[8 * j], tree_addr); + copy_subtree_addr(&info.leaf_addr[8 * j], wots_addr); + copy_subtree_addr(&info.pk_addr[8 * j], wots_addr); + } + + info.wots_sign_leaf = idx_leaf; + + treehashx4(root, auth_path, ctx, + idx_leaf, 0, + SPX_TREE_HEIGHT, + wots_gen_leafx4, + tree_addrx4, &info); +} + +/* Compute root node of the top-most subtree. */ +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { + /* We do not need the auth path in key generation, but it simplifies the + code to have just one treehash routine that computes both root and path + in one function. */ + unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; + uint32_t top_tree_addr[8] = {0}; + uint32_t wots_addr[8] = {0}; + + set_layer_addr(top_tree_addr, SPX_D - 1); + set_layer_addr(wots_addr, SPX_D - 1); + + merkle_sign(auth_path, root, ctx, + wots_addr, top_tree_addr, + ~0U /* ~0 means "don't bother generating an auth path */ ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/merkle.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/merkle.h new file mode 100644 index 0000000000..769cf2e970 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/merkle.h @@ -0,0 +1,21 @@ +#ifndef MERKLE_H_ +#define MERKLE_H_ + +#include + +#include "context.h" +#include "params.h" + +/* Generate a Merkle signature (WOTS signature followed by the Merkle */ +/* authentication path) */ +#define merkle_sign SPX_NAMESPACE(merkle_sign) +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf); + +/* Compute the root node of the top-most subtree. */ +#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); + +#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/nistapi.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/nistapi.h new file mode 100644 index 0000000000..3cb71afad4 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/nistapi.h @@ -0,0 +1,87 @@ +#ifndef SPX_API_H +#define SPX_API_H + +#include +#include + +#include "params.h" + +#define CRYPTO_ALGNAME "SPHINCS+" + +#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES +#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES +#define CRYPTO_BYTES SPX_BYTES +#define CRYPTO_SEEDBYTES (3*SPX_N) + +/* + * Returns the length of a secret key, in bytes + */ +#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) +size_t crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) +size_t crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) +size_t crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) +size_t crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +#define crypto_sign SPX_NAMESPACE(crypto_sign) +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/params.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/params.h index 4008d557a6..4e1e7f0bb6 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/params.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/params.h @@ -1,53 +1,56 @@ -#ifndef PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_PARAMS_H -#define PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_PARAMS_H +#ifndef SPX_PARAMS_H +#define SPX_PARAMS_H + +#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_##s /* Hash output length in bytes. */ -#define PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N 16 +#define SPX_N 16 /* Height of the hypertree. */ -#define PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_FULL_HEIGHT 63 +#define SPX_FULL_HEIGHT 63 /* Number of subtree layer. */ -#define PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_D 7 +#define SPX_D 7 /* FORS tree dimensions. */ -#define PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_FORS_HEIGHT 12 -#define PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_FORS_TREES 14 +#define SPX_FORS_HEIGHT 12 +#define SPX_FORS_TREES 14 /* Winternitz parameter, */ -#define PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_WOTS_W 16 +#define SPX_WOTS_W 16 /* The hash function is defined by linking a different hash.c file, as opposed to setting a #define constant. */ /* For clarity */ -#define PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_ADDR_BYTES 32 +#define SPX_ADDR_BYTES 32 /* WOTS parameters. */ -#define PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_WOTS_LOGW 4 +#define SPX_WOTS_LOGW 4 -#define PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_WOTS_LEN1 (8 * PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N / PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_WOTS_LOGW) +#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) -/* PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#define PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_WOTS_LEN2 3 +/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ +#define SPX_WOTS_LEN2 3 -#define PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_WOTS_LEN (PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_WOTS_LEN1 + PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_WOTS_LEN2) -#define PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_WOTS_BYTES (PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_WOTS_LEN * PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N) -#define PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_WOTS_PK_BYTES PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_WOTS_BYTES +#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) +#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) +#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES /* Subtree size. */ -#define PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_TREE_HEIGHT (PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_FULL_HEIGHT / PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_D) +#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) + +//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT +// #error SPX_D should always divide SPX_FULL_HEIGHT +//#endif /* FORS parameters. */ -#define PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_FORS_MSG_BYTES ((PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_FORS_TREES + 7) / 8) -#define PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_FORS_BYTES ((PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_FORS_HEIGHT + 1) * PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_FORS_TREES * PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N) -#define PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_FORS_PK_BYTES PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N +#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) +#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) +#define SPX_FORS_PK_BYTES SPX_N /* Resulting SPX sizes. */ -#define PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_BYTES (PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N + PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_FORS_BYTES + PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_D * PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_WOTS_BYTES +\ - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_FULL_HEIGHT * PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N) -#define PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_PK_BYTES (2 * PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N) -#define PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_SK_BYTES (2 * PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N + PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_PK_BYTES) - -/* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ -#define PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_OPTRAND_BYTES 32 +#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ + SPX_FULL_HEIGHT * SPX_N) +#define SPX_PK_BYTES (2 * SPX_N) +#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) + +#include "haraka_offsets.h" #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/sign.c b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/sign.c index f1a3af6a4c..9d0c7d1b22 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/sign.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/sign.c @@ -1,76 +1,45 @@ -#include #include #include #include #include "address.h" -#include "api.h" +#include "context.h" #include "fors.h" #include "hash.h" -#include "hash_state.h" +#include "merkle.h" +#include "nistapi.h" #include "params.h" #include "randombytes.h" #include "thash.h" #include "utils.h" #include "wots.h" - -/** - * Computes the leaf at a given address. First generates the WOTS key pair, - * then computes leaf by hashing horizontally. - */ -static void wots_gen_leaf(unsigned char *leaf, const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx, const uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - unsigned char pk[PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_WOTS_BYTES]; - uint32_t wots_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_set_type( - wots_addr, PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_set_type( - wots_pk_addr, PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_ADDR_TYPE_WOTSPK); - - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_set_keypair_addr( - wots_addr, addr_idx); - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_wots_gen_pk( - pk, sk_seed, pub_seed, wots_addr, hash_state_seeded); - - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_copy_keypair_addr( - wots_pk_addr, wots_addr); - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_thash_WOTS_LEN( - leaf, pk, pub_seed, wots_pk_addr, hash_state_seeded); -} - /* * Returns the length of a secret key, in bytes */ -size_t PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_crypto_sign_secretkeybytes(void) { - return PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_CRYPTO_SECRETKEYBYTES; +size_t crypto_sign_secretkeybytes(void) { + return CRYPTO_SECRETKEYBYTES; } /* * Returns the length of a public key, in bytes */ -size_t PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_crypto_sign_publickeybytes(void) { - return PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_CRYPTO_PUBLICKEYBYTES; +size_t crypto_sign_publickeybytes(void) { + return CRYPTO_PUBLICKEYBYTES; } /* * Returns the length of a signature, in bytes */ -size_t PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_crypto_sign_bytes(void) { - return PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_CRYPTO_BYTES; +size_t crypto_sign_bytes(void) { + return CRYPTO_BYTES; } /* * Returns the length of the seed required to generate a key pair, in bytes */ -size_t PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_crypto_sign_seedbytes(void) { - return PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_CRYPTO_SEEDBYTES; +size_t crypto_sign_seedbytes(void) { + return CRYPTO_SEEDBYTES; } /* @@ -78,35 +47,29 @@ size_t PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_crypto_sign_seedbytes(void) { * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] * Format pk: [PUB_SEED || root] */ -int PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed) { - /* We do not need the auth path in key generation, but it simplifies the - code to have just one treehash routine that computes both root and path - in one function. */ - unsigned char auth_path[PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_TREE_HEIGHT * PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N]; - uint32_t top_tree_addr[8] = {0}; - hash_state hash_state_seeded; - - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_set_layer_addr( - top_tree_addr, PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_D - 1); - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_set_type( - top_tree_addr, PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_ADDR_TYPE_HASHTREE); +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed) { + spx_ctx ctx; /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ - memcpy(sk, seed, PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_CRYPTO_SEEDBYTES); + memcpy(sk, seed, CRYPTO_SEEDBYTES); + + memcpy(pk, sk + 2 * SPX_N, SPX_N); - memcpy(pk, sk + 2 * PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N, PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N); + memcpy(ctx.pub_seed, pk, SPX_N); + memcpy(ctx.sk_seed, sk, SPX_N); /* This hook allows the hash function instantiation to do whatever preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_initialize_hash_function(&hash_state_seeded, pk, sk); + initialize_hash_function(&ctx); /* Compute root node of the top-most subtree. */ - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_treehash_TREE_HEIGHT( - sk + 3 * PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N, auth_path, sk, sk + 2 * PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N, 0, 0, - wots_gen_leaf, top_tree_addr, &hash_state_seeded); + merkle_gen_root(sk + 3 * SPX_N, &ctx); - memcpy(pk + PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N, sk + 3 * PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N, PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N); + // cleanup + free_hash_function(&ctx); + + memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); return 0; } @@ -116,31 +79,10 @@ int PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_crypto_sign_seed_keypair( * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] * Format pk: [PUB_SEED || root] */ -int PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk) { - - // guarantee alignment of pk - union { - __m128 _x[PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_CRYPTO_PUBLICKEYBYTES / 16]; - uint8_t pk[PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_CRYPTO_PUBLICKEYBYTES]; - } aligned_pk; - - // guarantee alignment of sk - union { - __m128 _x[PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_CRYPTO_SECRETKEYBYTES / 16]; - uint8_t sk[PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_CRYPTO_SECRETKEYBYTES]; - } aligned_sk; - - union { - __m128 _x[PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_CRYPTO_SEEDBYTES / 16]; - uint8_t seed[PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_CRYPTO_SEEDBYTES]; - } aligned_seed; - randombytes(aligned_seed.seed, PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_CRYPTO_SEEDBYTES); - - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_crypto_sign_seed_keypair( - aligned_pk.pk, aligned_sk.sk, aligned_seed.seed); - memcpy(pk, aligned_pk.pk, PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_CRYPTO_PUBLICKEYBYTES); - memcpy(sk, aligned_sk.sk, PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_CRYPTO_SECRETKEYBYTES); +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { + uint8_t seed[CRYPTO_SEEDBYTES]; + randombytes(seed, CRYPTO_SEEDBYTES); + crypto_sign_seed_keypair(pk, sk, seed); return 0; } @@ -148,101 +90,68 @@ int PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_crypto_sign_keypair( /** * Returns an array containing a detached signature. */ -int PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - // guarantee alignment of sk - union { - __m128 *_x; - uint8_t sk[PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_CRYPTO_SECRETKEYBYTES]; - } aligned_sk; - memcpy(aligned_sk.sk, sk, PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_CRYPTO_SECRETKEYBYTES); - sk = aligned_sk.sk; - - // guarantee alignment of sig - union { - __m128 *_x; - uint8_t sig[PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_BYTES]; - } aligned_sig; - uint8_t *orig_sig = sig; - sig = (uint8_t *)aligned_sig.sig; - - const unsigned char *sk_seed = sk; - const unsigned char *sk_prf = sk + PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N; - const unsigned char *pk = sk + 2 * PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N; - const unsigned char *pub_seed = pk; - - unsigned char optrand[PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N]; - unsigned char mhash[PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_FORS_MSG_BYTES]; - unsigned char root[PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N]; +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk) { + spx_ctx ctx; + + const uint8_t *sk_prf = sk + SPX_N; + const uint8_t *pk = sk + 2 * SPX_N; + + uint8_t optrand[SPX_N]; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t root[SPX_N]; uint32_t i; uint64_t tree; uint32_t idx_leaf; uint32_t wots_addr[8] = {0}; uint32_t tree_addr[8] = {0}; - hash_state hash_state_seeded; + memcpy(ctx.sk_seed, sk, SPX_N); + memcpy(ctx.pub_seed, pk, SPX_N); /* This hook allows the hash function instantiation to do whatever preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_initialize_hash_function( - &hash_state_seeded, - pub_seed, sk_seed); + initialize_hash_function(&ctx); - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_set_type( - wots_addr, PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_set_type( - tree_addr, PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_ADDR_TYPE_HASHTREE); + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); /* Optionally, signing can be made non-deterministic using optrand. This can help counter side-channel attacks that would benefit from getting a large number of traces when the signer uses the same nodes. */ - randombytes(optrand, PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N); + randombytes(optrand, SPX_N); /* Compute the digest randomization value. */ - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_gen_message_random( - sig, sk_prf, optrand, m, mlen, &hash_state_seeded); + gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); /* Derive the message digest and leaf index from R, PK and M. */ - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N; + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_set_keypair_addr( - wots_addr, idx_leaf); + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); /* Sign the message hash using FORS. */ - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_fors_sign( - sig, root, mhash, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_FORS_BYTES; - - for (i = 0; i < PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_D; i++) { - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_set_tree_addr(tree_addr, tree); - - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_set_keypair_addr( - wots_addr, idx_leaf); - - /* Compute a WOTS signature. */ - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_wots_sign( - sig, root, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_WOTS_BYTES; - - /* Compute the authentication path for the used WOTS leaf. */ - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_treehash_TREE_HEIGHT( - root, sig, sk_seed, pub_seed, idx_leaf, 0, - wots_gen_leaf, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_TREE_HEIGHT * PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N; + fors_sign(sig, root, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); + sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_TREE_HEIGHT; + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; } - memcpy(orig_sig, aligned_sig.sig, PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_BYTES); - *siglen = PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_BYTES; + free_hash_function(&ctx); + + *siglen = SPX_BYTES; return 0; } @@ -250,23 +159,14 @@ int PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_crypto_sign_signature( /** * Verifies a detached signature and message under a given public key. */ -int PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk) { - // guarantee alignment of pk - union { - __m128 *_x; - uint8_t pk[PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_CRYPTO_PUBLICKEYBYTES]; - } aligned_pk; - memcpy(aligned_pk.pk, pk, PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_CRYPTO_PUBLICKEYBYTES); - pk = aligned_pk.pk; - - const unsigned char *pub_seed = pk; - const unsigned char *pub_root = pk + PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N; - unsigned char mhash[PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_FORS_MSG_BYTES]; - unsigned char wots_pk[PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_WOTS_BYTES]; - unsigned char root[PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N]; - unsigned char leaf[PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N]; +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk) { + spx_ctx ctx; + const uint8_t *pub_root = pk + SPX_N; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t wots_pk[SPX_WOTS_BYTES]; + uint8_t root[SPX_N]; + uint8_t leaf[SPX_N]; unsigned int i; uint64_t tree; uint32_t idx_leaf; @@ -274,77 +174,66 @@ int PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_crypto_sign_verify( uint32_t tree_addr[8] = {0}; uint32_t wots_pk_addr[8] = {0}; - hash_state hash_state_seeded; - - if (siglen != PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_BYTES) { + if (siglen != SPX_BYTES) { return -1; } + memcpy(ctx.pub_seed, pk, SPX_N); + /* This hook allows the hash function instantiation to do whatever preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_initialize_hash_function( - &hash_state_seeded, - pub_seed, NULL); + initialize_hash_function(&ctx); - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_set_type( - wots_addr, PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_set_type( - tree_addr, PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_ADDR_TYPE_HASHTREE); - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_set_type( - wots_pk_addr, PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_ADDR_TYPE_WOTSPK); + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); /* Derive the message digest and leaf index from R || PK || M. */ - /* The additional PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N is a result of the hash domain separator. */ - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N; + /* The additional SPX_N is a result of the hash domain separator. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; /* Layer correctly defaults to 0, so no need to set_layer_addr */ - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_set_keypair_addr( - wots_addr, idx_leaf); + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_fors_pk_from_sig( - root, sig, mhash, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_FORS_BYTES; + fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; /* For each subtree.. */ - for (i = 0; i < PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_D; i++) { - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_set_tree_addr(tree_addr, tree); + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_set_keypair_addr( - wots_addr, idx_leaf); + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_copy_keypair_addr( - wots_pk_addr, wots_addr); + copy_keypair_addr(wots_pk_addr, wots_addr); /* The WOTS public key is only correct if the signature was correct. */ /* Initially, root is the FORS pk, but on subsequent iterations it is the root of the subtree below the currently processed subtree. */ - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_wots_pk_from_sig( - wots_pk, sig, root, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_WOTS_BYTES; + wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); + sig += SPX_WOTS_BYTES; /* Compute the leaf node using the WOTS public key. */ - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_thash_WOTS_LEN( - leaf, wots_pk, pub_seed, wots_pk_addr, &hash_state_seeded); + thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); /* Compute the root node of this subtree. */ - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_compute_root( - root, leaf, idx_leaf, 0, sig, PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_TREE_HEIGHT, - pub_seed, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_TREE_HEIGHT * PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N; + compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, + &ctx, tree_addr); + sig += SPX_TREE_HEIGHT * SPX_N; /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_TREE_HEIGHT; + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; } + // cleanup + free_hash_function(&ctx); + /* Check if the root node equals the root node in the public key. */ - if (memcmp(root, pub_root, PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N) != 0) { + if (memcmp(root, pub_root, SPX_N) != 0) { return -1; } @@ -355,15 +244,14 @@ int PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_crypto_sign_verify( /** * Returns an array containing the signature followed by the message. */ -int PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk) { size_t siglen; - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_crypto_sign_signature( - sm, &siglen, m, mlen, sk); + crypto_sign_signature(sm, &siglen, m, mlen, sk); - memmove(sm + PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_BYTES, m, mlen); + memmove(sm + SPX_BYTES, m, mlen); *smlen = siglen + mlen; return 0; @@ -372,38 +260,27 @@ int PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_crypto_sign( /** * Verifies a given signature-message pair under a given public key. */ -int PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk) { - - // guarantee alignment of pk - union { - __m128 *_x; - uint8_t pk[PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_CRYPTO_PUBLICKEYBYTES]; - } aligned_pk; - memcpy(aligned_pk.pk, pk, PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_CRYPTO_PUBLICKEYBYTES); - pk = aligned_pk.pk; - - +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk) { /* The API caller does not necessarily know what size a signature should be - but SPHINCS+ signatures are always exactly PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_BYTES. */ - if (smlen < PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_BYTES) { + but SPHINCS+ signatures are always exactly SPX_BYTES. */ + if (smlen < SPX_BYTES) { memset(m, 0, smlen); *mlen = 0; return -1; } - *mlen = smlen - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_BYTES; + *mlen = smlen - SPX_BYTES; - if (PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_crypto_sign_verify( - sm, PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_BYTES, sm + PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_BYTES, *mlen, pk)) { + if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { memset(m, 0, smlen); *mlen = 0; return -1; } /* If verification was successful, move the message to the right place. */ - memmove(m, sm + PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_BYTES, *mlen); + memmove(m, sm + SPX_BYTES, *mlen); return 0; } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/thash.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/thash.h index 38669a30c3..8687ccfb4d 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/thash.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/thash.h @@ -1,28 +1,13 @@ -#ifndef PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_THASH_H -#define PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_THASH_H +#ifndef SPX_THASH_H +#define SPX_THASH_H -#include "hash_state.h" +#include "context.h" +#include "params.h" #include -void PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); +#define thash SPX_NAMESPACE(thash) +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/thash_haraka_robust.c b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/thash_haraka_robust.c index f1b380e613..109502cbc2 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/thash_haraka_robust.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/thash_haraka_robust.c @@ -2,93 +2,44 @@ #include #include "address.h" -#include "hash_state.h" #include "params.h" #include "thash.h" +#include "utils.h" #include "haraka.h" /** - * Takes an array of inblocks concatenated arrays of PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N bytes. + * Takes an array of inblocks concatenated arrays of SPX_N bytes. */ -static void PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_thash( - unsigned char *out, unsigned char *buf, - const unsigned char *in, unsigned int inblocks, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char *bitmask = buf + PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_ADDR_BYTES; +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]) { + PQCLEAN_VLA(uint8_t, buf, SPX_ADDR_BYTES + inblocks * SPX_N); + PQCLEAN_VLA(uint8_t, bitmask, inblocks * SPX_N); unsigned char outbuf[32]; unsigned char buf_tmp[64]; unsigned int i; - (void)pub_seed; /* Suppress an 'unused parameter' warning. */ - if (inblocks == 1) { /* F function */ - /* Since PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N may be smaller than 32, we need a temporary buffer. */ + /* Since SPX_N may be smaller than 32, we need a temporary buffer. */ memset(buf_tmp, 0, 64); - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_addr_to_bytes(buf_tmp, addr); + memcpy(buf_tmp, addr, 32); - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_haraka256(outbuf, buf_tmp, hash_state_seeded); - for (i = 0; i < inblocks * PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N; i++) { - buf_tmp[PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_ADDR_BYTES + i] = in[i] ^ outbuf[i]; + haraka256(outbuf, buf_tmp, ctx); + for (i = 0; i < inblocks * SPX_N; i++) { + buf_tmp[SPX_ADDR_BYTES + i] = in[i] ^ outbuf[i]; } - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_haraka512(outbuf, buf_tmp, hash_state_seeded); - memcpy(out, outbuf, PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N); + haraka512(outbuf, buf_tmp, ctx); + memcpy(out, outbuf, SPX_N); } else { /* All other tweakable hashes*/ - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_addr_to_bytes(buf, addr); - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_haraka_S( - bitmask, inblocks * PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N, buf, PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_ADDR_BYTES, hash_state_seeded); + memcpy(buf, addr, 32); + haraka_S(bitmask, inblocks * SPX_N, buf, SPX_ADDR_BYTES, ctx); - for (i = 0; i < inblocks * PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N; i++) { - buf[PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_ADDR_BYTES + i] = in[i] ^ bitmask[i]; + for (i = 0; i < inblocks * SPX_N; i++) { + buf[SPX_ADDR_BYTES + i] = in[i] ^ bitmask[i]; } - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_haraka_S( - out, PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N, buf, PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N, hash_state_seeded); + haraka_S(out, SPX_N, buf, SPX_ADDR_BYTES + inblocks * SPX_N, ctx); } } - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_ADDR_BYTES + 1 * PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N]; - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_thash( - out, buf, in, 1, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_ADDR_BYTES + 2 * PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N]; - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_thash( - out, buf, in, 2, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_ADDR_BYTES + PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_WOTS_LEN * PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N]; - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_thash( - out, buf, in, PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_WOTS_LEN, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_ADDR_BYTES + PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_FORS_TREES * PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N]; - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_thash( - out, buf, in, PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_FORS_TREES, pub_seed, addr, hash_state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/thash_haraka_robustx4.c b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/thash_haraka_robustx4.c index 7f488d8ce1..100808a3a5 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/thash_haraka_robustx4.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/thash_haraka_robustx4.c @@ -2,91 +2,92 @@ #include #include "address.h" -#include "haraka.h" #include "params.h" #include "thashx4.h" +#include "harakax4.h" + +#include "utils.h" + /** * 4-way parallel version of thash; takes 4x as much input and output */ -#define thashx4_variant(name, inblocks) \ - void PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_thashx4_##name(unsigned char *out0, unsigned char *out1, unsigned char *out2, \ - unsigned char *out3, const unsigned char *in0, \ - const unsigned char *in1, const unsigned char *in2, \ - const unsigned char *in3, const unsigned char *pub_seed, \ - uint32_t addrx4[4 * 8], const harakactx *state) { \ - unsigned char buf0[PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_ADDR_BYTES + (inblocks)*PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N]; \ - unsigned char buf1[PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_ADDR_BYTES + (inblocks)*PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N]; \ - unsigned char buf2[PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_ADDR_BYTES + (inblocks)*PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N]; \ - unsigned char buf3[PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_ADDR_BYTES + (inblocks)*PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N]; \ - unsigned char bitmask0[(inblocks)*PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N]; \ - unsigned char bitmask1[(inblocks)*PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N]; \ - unsigned char bitmask2[(inblocks)*PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N]; \ - unsigned char bitmask3[(inblocks)*PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N]; \ - unsigned char outbuf[32 * 4]; \ - unsigned char buf_tmp[64 * 4]; \ - unsigned int i; \ - \ - (void)pub_seed; /* Suppress an 'unused parameter' warning. */ \ - \ - if ((inblocks) == 1) { \ - memset(buf_tmp, 0, 64 * 4); \ - \ - /* Generate masks first in buffer */ \ - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_addr_to_bytes(buf_tmp, addrx4 + 0 * 8); \ - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_addr_to_bytes(buf_tmp + 32, addrx4 + 1 * 8); \ - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_addr_to_bytes(buf_tmp + 64, addrx4 + 2 * 8); \ - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_addr_to_bytes(buf_tmp + 96, addrx4 + 3 * 8); \ - \ - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_haraka256x4(outbuf, buf_tmp, state); \ - \ - /* move addresses to make room for inputs; zero old values */ \ - memcpy(buf_tmp + 192, buf_tmp + 96, PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_ADDR_BYTES); \ - memcpy(buf_tmp + 128, buf_tmp + 64, PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_ADDR_BYTES); \ - memcpy(buf_tmp + 64, buf_tmp + 32, PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_ADDR_BYTES); \ - /* skip memcpy(buf_tmp, buf_tmp, PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_ADDR_BYTES); already in place */ \ - \ - /* skip memset(buf_tmp, 0, PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_ADDR_BYTES); remained untouched */ \ - memset(buf_tmp + 32, 0, PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_ADDR_BYTES); \ - /* skip memset(buf_tmp + 64, 0, PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_ADDR_BYTES); contains addr1 */ \ - memset(buf_tmp + 96, 0, PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_ADDR_BYTES); \ - \ - for (i = 0; i < PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N; i++) { \ - buf_tmp[PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_ADDR_BYTES + i] = in0[i] ^ outbuf[i]; \ - buf_tmp[PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_ADDR_BYTES + i + 64] = in1[i] ^ outbuf[i + 32]; \ - buf_tmp[PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_ADDR_BYTES + i + 128] = in2[i] ^ outbuf[i + 64]; \ - buf_tmp[PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_ADDR_BYTES + i + 192] = in3[i] ^ outbuf[i + 96]; \ - } \ - \ - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_haraka512x4(outbuf, buf_tmp, state); \ - \ - memcpy(out0, outbuf, PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N); \ - memcpy(out1, outbuf + 32, PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N); \ - memcpy(out2, outbuf + 64, PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N); \ - memcpy(out3, outbuf + 96, PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N); \ - } else { \ - /* All other tweakable hashes*/ \ - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_addr_to_bytes(buf0, addrx4 + 0 * 8); \ - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_addr_to_bytes(buf1, addrx4 + 1 * 8); \ - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_addr_to_bytes(buf2, addrx4 + 2 * 8); \ - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_addr_to_bytes(buf3, addrx4 + 3 * 8); \ - \ - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_haraka_Sx4(bitmask0, bitmask1, bitmask2, bitmask3, (inblocks)*PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N, buf0, buf1, \ - buf2, buf3, PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_ADDR_BYTES, state); \ - \ - for (i = 0; i < (inblocks)*PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N; i++) { \ - buf0[PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_ADDR_BYTES + i] = in0[i] ^ bitmask0[i]; \ - buf1[PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_ADDR_BYTES + i] = in1[i] ^ bitmask1[i]; \ - buf2[PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_ADDR_BYTES + i] = in2[i] ^ bitmask2[i]; \ - buf3[PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_ADDR_BYTES + i] = in3[i] ^ bitmask3[i]; \ - } \ - \ - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_haraka_Sx4(out0, out1, out2, out3, PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N, buf0, buf1, buf2, buf3, \ - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_ADDR_BYTES + (inblocks)*PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N, state); \ - } \ - } +#define thashx4 SPX_NAMESPACE(thashx4) +void thashx4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addrx4[4 * 8]) { + PQCLEAN_VLA(unsigned char, buf0, SPX_ADDR_BYTES + inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, buf1, SPX_ADDR_BYTES + inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, buf2, SPX_ADDR_BYTES + inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, buf3, SPX_ADDR_BYTES + inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, bitmask0, inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, bitmask1, inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, bitmask2, inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, bitmask3, inblocks * SPX_N); + unsigned char outbuf[32 * 4]; + unsigned char buf_tmp[64 * 4]; + unsigned int i; + + if (inblocks == 1) { + memset(buf_tmp, 0, 64 * 4); + + // Generate masks first in buffer + memcpy(buf_tmp, addrx4 + 0 * 8, 32); + memcpy(buf_tmp + 32, addrx4 + 1 * 8, 32); + memcpy(buf_tmp + 64, addrx4 + 2 * 8, 32); + memcpy(buf_tmp + 96, addrx4 + 3 * 8, 32); + + haraka256x4(outbuf, buf_tmp, ctx); + + /* move addresses to make room for inputs; zero old values */ + memcpy(buf_tmp + 192, buf_tmp + 96, SPX_ADDR_BYTES); + memcpy(buf_tmp + 128, buf_tmp + 64, SPX_ADDR_BYTES); + memcpy(buf_tmp + 64, buf_tmp + 32, SPX_ADDR_BYTES); + /* skip memcpy(buf_tmp, buf_tmp, SPX_ADDR_BYTES); already in place */ -thashx4_variant(1, 1) -thashx4_variant(2, 2) -thashx4_variant(WOTS_LEN, PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_WOTS_LEN) -thashx4_variant(FORS_TREES, PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_FORS_TREES) + /* skip memset(buf_tmp, 0, SPX_ADDR_BYTES); remained untouched */ + memset(buf_tmp + 32, 0, SPX_ADDR_BYTES); + /* skip memset(buf_tmp + 64, 0, SPX_ADDR_BYTES); contains addr1 */ + memset(buf_tmp + 96, 0, SPX_ADDR_BYTES); + + for (i = 0; i < SPX_N; i++) { + buf_tmp[SPX_ADDR_BYTES + i] = in0[i] ^ outbuf[i]; + buf_tmp[SPX_ADDR_BYTES + i + 64] = in1[i] ^ outbuf[i + 32]; + buf_tmp[SPX_ADDR_BYTES + i + 128] = in2[i] ^ outbuf[i + 64]; + buf_tmp[SPX_ADDR_BYTES + i + 192] = in3[i] ^ outbuf[i + 96]; + } + + haraka512x4(outbuf, buf_tmp, ctx); + + memcpy(out0, outbuf, SPX_N); + memcpy(out1, outbuf + 32, SPX_N); + memcpy(out2, outbuf + 64, SPX_N); + memcpy(out3, outbuf + 96, SPX_N); + } else { + /* All other tweakable hashes*/ + memcpy(buf0, addrx4 + 0 * 8, 32); + memcpy(buf1, addrx4 + 1 * 8, 32); + memcpy(buf2, addrx4 + 2 * 8, 32); + memcpy(buf3, addrx4 + 3 * 8, 32); + + haraka_Sx4(bitmask0, bitmask1, bitmask2, bitmask3, inblocks * SPX_N, + buf0, buf1, buf2, buf3, SPX_ADDR_BYTES, ctx); + + for (i = 0; i < inblocks * SPX_N; i++) { + buf0[SPX_ADDR_BYTES + i] = in0[i] ^ bitmask0[i]; + buf1[SPX_ADDR_BYTES + i] = in1[i] ^ bitmask1[i]; + buf2[SPX_ADDR_BYTES + i] = in2[i] ^ bitmask2[i]; + buf3[SPX_ADDR_BYTES + i] = in3[i] ^ bitmask3[i]; + } + + haraka_Sx4(out0, out1, out2, out3, SPX_N, + buf0, buf1, buf2, buf3, SPX_ADDR_BYTES + inblocks * SPX_N, + ctx); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/thashx4.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/thashx4.h index 016967e4c2..64798a3727 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/thashx4.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/thashx4.h @@ -1,25 +1,20 @@ -#ifndef PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_THASHX4_H -#define PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_THASHX4_H +#ifndef SPX_THASHX4_H +#define SPX_THASHX4_H #include -#include "hash_state.h" +#include "context.h" +#include "params.h" -#define thashx4_header(inblocks) \ - void PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_thashx4_##inblocks(unsigned char *out0, \ - unsigned char *out1, \ - unsigned char *out2, \ - unsigned char *out3, \ - const unsigned char *in0, \ - const unsigned char *in1, \ - const unsigned char *in2, \ - const unsigned char *in3, \ - const unsigned char *pub_seed, uint32_t addrx4[4*8], \ - const hash_state *state_seeded) - -thashx4_header(1); -thashx4_header(2); -thashx4_header(WOTS_LEN); -thashx4_header(FORS_TREES); +#define thashx4 SPX_NAMESPACE(thashx4) +void thashx4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addrx4[4 * 8]); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/utils.c b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/utils.c index 8e502ee1c8..177b541fb9 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/utils.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/utils.c @@ -1,34 +1,41 @@ -#include #include +#include "utils.h" + #include "address.h" #include "hash.h" -#include "hash_state.h" #include "params.h" #include "thash.h" -#include "utils.h" /** * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. */ -void PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in) { +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in) { + int i; /* Iterate over out in decreasing order, for big-endianness. */ - for (size_t i = outlen; i > 0; i--) { - out[i - 1] = in & 0xff; + for (i = (signed int)outlen - 1; i >= 0; i--) { + out[i] = in & 0xff; in = in >> 8; } } +void u32_to_bytes(unsigned char *out, uint32_t in) { + out[0] = (unsigned char)(in >> 24); + out[1] = (unsigned char)(in >> 16); + out[2] = (unsigned char)(in >> 8); + out[3] = (unsigned char)in; +} + /** * Converts the inlen bytes in 'in' from big-endian byte order to an integer. */ -unsigned long long PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_bytes_to_ull( - const unsigned char *in, size_t inlen) { +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { unsigned long long retval = 0; + unsigned int i; - for (size_t i = 0; i < inlen; i++) { + for (i = 0; i < inlen; i++) { retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); } return retval; @@ -38,94 +45,80 @@ unsigned long long PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_bytes_to_ull( * Computes a root node given a leaf and an auth path. * Expects address to be complete other than the tree_height and tree_index. */ -void PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]) { uint32_t i; - unsigned char buffer[2 * PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N]; + unsigned char buffer[2 * SPX_N]; /* If leaf_idx is odd (last bit = 1), current path element is a right child and auth_path has to go left. Otherwise it is the other way around. */ if (leaf_idx & 1) { - memcpy(buffer + PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N, leaf, PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N); + memcpy(buffer + SPX_N, leaf, SPX_N); + memcpy(buffer, auth_path, SPX_N); } else { - memcpy(buffer, leaf, PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N); - memcpy(buffer + PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N, auth_path, PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N); + memcpy(buffer, leaf, SPX_N); + memcpy(buffer + SPX_N, auth_path, SPX_N); } - auth_path += PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N; + auth_path += SPX_N; for (i = 0; i < tree_height - 1; i++) { leaf_idx >>= 1; idx_offset >>= 1; /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_set_tree_height(addr, i + 1); - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_set_tree_index( - addr, leaf_idx + idx_offset); + set_tree_height(addr, i + 1); + set_tree_index(addr, leaf_idx + idx_offset); /* Pick the right or left neighbor, depending on parity of the node. */ if (leaf_idx & 1) { - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_thash_2( - buffer + PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N); + thash(buffer + SPX_N, buffer, 2, ctx, addr); + memcpy(buffer, auth_path, SPX_N); } else { - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_thash_2( - buffer, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer + PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N, auth_path, PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N); + thash(buffer, buffer, 2, ctx, addr); + memcpy(buffer + SPX_N, auth_path, SPX_N); } - auth_path += PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N; + auth_path += SPX_N; } /* The last iteration is exceptional; we do not copy an auth_path node. */ leaf_idx >>= 1; idx_offset >>= 1; - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_set_tree_height(addr, tree_height); - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_set_tree_index( - addr, leaf_idx + idx_offset); - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_thash_2( - root, buffer, pub_seed, addr, hash_state_seeded); + set_tree_height(addr, tree_height); + set_tree_index(addr, leaf_idx + idx_offset); + thash(root, buffer, 2, ctx, addr); } /** * For a given leaf index, computes the authentication path and the resulting * root node using Merkle's TreeHash algorithm. * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_ADDR_TYPE_FORSTREE). + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). * Applies the offset idx_offset to indices before building addresses, so that * it is possible to continue counting indices across trees. */ -static void PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_treehash( - unsigned char *root, unsigned char *auth_path, - unsigned char *stack, unsigned int *heights, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - +void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx * /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]) { + PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); + PQCLEAN_VLA(unsigned int, heights, tree_height + 1); unsigned int offset = 0; uint32_t idx; uint32_t tree_idx; for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { /* Add the next leaf node to the stack. */ - gen_leaf(stack + offset * PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N, - sk_seed, pub_seed, idx + idx_offset, tree_addr, - hash_state_seeded); + gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); offset++; heights[offset - 1] = 0; /* If this is a node we need for the auth path.. */ if ((leaf_idx ^ 0x1) == idx) { - memcpy(auth_path, stack + (offset - 1)*PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N, PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N); + memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); } /* While the top-most nodes are of equal height.. */ @@ -134,66 +127,22 @@ static void PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_treehash( tree_idx = (idx >> (heights[offset - 1] + 1)); /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_set_tree_height( - tree_addr, heights[offset - 1] + 1); - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_set_tree_index( - tree_addr, tree_idx + (idx_offset >> (heights[offset - 1] + 1))); + set_tree_height(tree_addr, heights[offset - 1] + 1); + set_tree_index(tree_addr, + tree_idx + (idx_offset >> (heights[offset - 1] + 1))); /* Hash the top-most nodes from the stack together. */ - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_thash_2( - stack + (offset - 2)*PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N, stack + (offset - 2)*PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N, - pub_seed, tree_addr, hash_state_seeded); + thash(stack + (offset - 2)*SPX_N, + stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); offset--; /* Note that the top-most node is now one layer higher. */ heights[offset - 1]++; /* If this is a node we need for the auth path.. */ if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_path + heights[offset - 1]*PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N, - stack + (offset - 1)*PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N, PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N); + memcpy(auth_path + heights[offset - 1]*SPX_N, + stack + (offset - 1)*SPX_N, SPX_N); } } } - memcpy(root, stack, PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N); -} - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_FORS_HEIGHT + 1)*PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N]; - unsigned int heights[PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_FORS_HEIGHT + 1]; - - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_FORS_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_TREE_HEIGHT + 1)*PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N]; - unsigned int heights[PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_TREE_HEIGHT + 1]; - - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_TREE_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); + memcpy(root, stack, SPX_N); } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/utils.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/utils.h index 0a24863390..64f5d5a53a 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/utils.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/utils.h @@ -1,64 +1,58 @@ -#ifndef PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_UTILS_H -#define PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_UTILS_H +#ifndef SPX_UTILS_H +#define SPX_UTILS_H -#include "hash_state.h" -#include "params.h" -#include #include +#include "compat.h" +#include "context.h" +#include "params.h" + + +/* To support MSVC use alloca() instead of VLAs. See #20. */ + + /** * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. */ -void PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in); +#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in); +#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) +void u32_to_bytes(unsigned char *out, uint32_t in); /** * Converts the inlen bytes in 'in' from big-endian byte order to an integer. */ -unsigned long long PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_bytes_to_ull( - const unsigned char *in, size_t inlen); +#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); /** * Computes a root node given a leaf and an auth path. * Expects address to be complete other than the tree_height and tree_index. */ -void PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); +#define compute_root SPX_NAMESPACE(compute_root) +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]); /** * For a given leaf index, computes the authentication path and the resulting * root node using Merkle's TreeHash algorithm. * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_ADDR_TYPE_FORSTREE). + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). * Applies the offset idx_offset to indices before building addresses, so that * it is possible to continue counting indices across trees. */ -void PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); +#define treehash SPX_NAMESPACE(treehash) +void treehash(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx *ctx /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]); -void PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/utilsx4.c b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/utilsx4.c index bd94d9c9d1..1638677194 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/utilsx4.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/utilsx4.c @@ -1,98 +1,138 @@ +#include + +#include "utilsx4.h" + #include "address.h" #include "params.h" #include "thashx4.h" #include "utils.h" -#include "utilsx4.h" -#include - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. +/* + * Generate the entire Merkle tree, computing the authentication path for leaf_idx, + * and the resulting root node using Merkle's TreeHash algorithm. * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_ADDR_TYPE_FORSTREE). + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) + * + * This expects tree_addrx4 to be initialized to 4 parallel addr structures for + * the Merkle tree nodes + * * Applies the offset idx_offset to indices before building addresses, so that * it is possible to continue counting indices across trees. + * + * This works by using the standard Merkle tree building algorithm, except + * that each 'node' tracked is actually 4 consecutive nodes in the real tree. + * When we combine two logical nodes ABCD and WXYZ, we perform the H + * operation on adjacent real nodes, forming the parent logical node + * (AB)(CD)(WX)(YZ) + * + * When we get to the top two levels of the real tree (where there is only + * one logical node), we continue this operation two more times; the right + * most real node will by the actual root (and the other 3 nodes will be + * garbage). We follow the same thashx4 logic so that the 'extract + * authentication path components' part of the loop is still executed (and + * to simplify the code somewhat) + * + * This currently assumes tree_height >= 2; I suspect that doing an adjusting + * idx, addr_idx on the gen_leafx4 call if tree_height < 2 would fix it; since + * we don't actually use such short trees, I haven't bothered */ -#define treehashx4_variant(name, tree_height) \ - void PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_treehashx4_##name( \ - unsigned char *rootx4, unsigned char *auth_pathx4, const unsigned char *sk_seed, \ - const unsigned char *pub_seed, const uint32_t leaf_idx[4], uint32_t idx_offset[4], \ - void (*gen_leafx4)(unsigned char * /* leaf0 */, unsigned char * /* leaf1 */, \ - unsigned char * /* leaf2 */, unsigned char * /* leaf3 */, \ - const unsigned char * /* sk_seed */, \ - const unsigned char * /* pub_seed */, uint32_t /* addr_idx0 */, \ - uint32_t /* addr_idx1 */, uint32_t /* addr_idx2 */, \ - uint32_t /* addr_idx3 */, const uint32_t[8] /* tree_addr */, \ - const hash_state * /* state_seeded */), \ - uint32_t tree_addrx4[4 * 8], const hash_state *state_seeded) { \ - unsigned char stackx4[4 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N]; \ - unsigned int heights[(tree_height) + 1]; \ - unsigned int offset = 0; \ - uint32_t idx; \ - uint32_t tree_idx; \ - unsigned int j; \ - \ - for (idx = 0; idx < (uint32_t)(1 << (tree_height)); idx++) { \ - /* Add the next leaf node to the stack. */ \ - gen_leafx4(stackx4 + 0 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N + offset * PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N, \ - stackx4 + 1 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N + offset * PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N, \ - stackx4 + 2 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N + offset * PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N, \ - stackx4 + 3 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N + offset * PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N, sk_seed, \ - pub_seed, idx + idx_offset[0], idx + idx_offset[1], idx + idx_offset[2], \ - idx + idx_offset[3], tree_addrx4, state_seeded); \ - offset++; \ - heights[offset - 1] = 0; \ - \ - /* If this is a node we need for the auth path.. */ \ - for (j = 0; j < 4; j++) { \ - if ((leaf_idx[j] ^ 0x1) == idx) { \ - memcpy(auth_pathx4 + j * (tree_height)*PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N, \ - stackx4 + j * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N + (offset - 1) * PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N, \ - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N); \ - } \ - } \ - \ - /* While the top-most nodes are of equal height.. */ \ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { \ - /* Compute index of the new node, in the next layer. */ \ - tree_idx = (idx >> (heights[offset - 1] + 1)); \ - \ - /* Set the address of the node we're creating. */ \ - for (j = 0; j < 4; j++) { \ - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_set_tree_height(tree_addrx4 + j * 8, heights[offset - 1] + 1); \ - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_set_tree_index(tree_addrx4 + j * 8, \ - tree_idx + (idx_offset[j] >> (heights[offset - 1] + 1))); \ - } \ - /* Hash the top-most nodes from the stack together. */ \ - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_thashx4_2(stackx4 + 0 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N + (offset - 2) * PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N, \ - stackx4 + 1 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N + (offset - 2) * PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N, \ - stackx4 + 2 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N + (offset - 2) * PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N, \ - stackx4 + 3 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N + (offset - 2) * PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N, \ - stackx4 + 0 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N + (offset - 2) * PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N, \ - stackx4 + 1 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N + (offset - 2) * PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N, \ - stackx4 + 2 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N + (offset - 2) * PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N, \ - stackx4 + 3 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N + (offset - 2) * PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N, \ - pub_seed, tree_addrx4, state_seeded); \ - offset--; \ - /* Note that the top-most node is now one layer higher. */ \ - heights[offset - 1]++; \ - \ - /* If this is a node we need for the auth path.. */ \ - for (j = 0; j < 4; j++) { \ - if (((leaf_idx[j] >> heights[offset - 1]) ^ 0x1) == tree_idx) { \ - memcpy(auth_pathx4 + j * (tree_height)*PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N + \ - heights[offset - 1] * PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N, \ - stackx4 + j * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N + (offset - 1) * PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N, \ - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N); \ - } \ - } \ - } \ - } \ - \ - for (j = 0; j < 4; j++) { \ - memcpy(rootx4 + j * PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N, stackx4 + j * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N, PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N); \ - } \ - } +void treehashx4(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, + uint32_t tree_height, + void (*gen_leafx4)( + unsigned char * /* Where to write the leaves */, + const spx_ctx *, + uint32_t idx, void *info), + uint32_t tree_addrx4[4 * 8], + void *info) { + /* This is where we keep the intermediate nodes */ + PQCLEAN_VLA(unsigned char, stackx4, tree_height * 4 * SPX_N); + uint32_t left_adj = 0, prev_left_adj = 0; /* When we're doing the top 3 */ + /* levels, the left-most part of the tree isn't at the beginning */ + /* of current[]. These give the offset of the actual start */ + + uint32_t idx; + uint32_t max_idx = (1U << (tree_height - 2)) - 1; + for (idx = 0;; idx++) { + unsigned char current[4 * SPX_N]; /* Current logical node */ + gen_leafx4( current, ctx, 4 * idx + idx_offset, + info ); -treehashx4_variant(FORS_HEIGHT, PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_FORS_HEIGHT) + /* Now combine the freshly generated right node with previously */ + /* generated left ones */ + uint32_t internal_idx_offset = idx_offset; + uint32_t internal_idx = idx; + uint32_t internal_leaf = leaf_idx; + uint32_t h; /* The height we are in the Merkle tree */ + for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { + + /* Special processing if we're at the top of the tree */ + if (h >= tree_height - 2) { + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[3 * SPX_N], SPX_N ); + return; + } + /* The tree indexing logic is a bit off in this case */ + /* Adjust it so that the left-most node of the part of */ + /* the tree that we're processing has index 0 */ + prev_left_adj = left_adj; + left_adj = 4U - (1 << (tree_height - h - 1)); + } + + /* Check if we hit the top of the tree */ + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[3 * SPX_N], SPX_N ); + return; + } + + /* + * Check if one of the nodes we have is a part of the + * authentication path; if it is, write it out + */ + if ((((internal_idx << 2) ^ internal_leaf) & ~0x3U) == 0) { + memcpy( &auth_path[ h * SPX_N ], + ¤t[(((internal_leaf & 3) ^ 1) + prev_left_adj) * SPX_N], + SPX_N ); + } + + /* + * Check if we're at a left child; if so, stop going up the stack + * Exception: if we've reached the end of the tree, keep on going + * (so we combine the last 4 nodes into the one root node in two + * more iterations) + */ + if ((internal_idx & 1) == 0 && idx < max_idx) { + break; + } + + /* Ok, we're at a right node (or doing the top 3 levels) */ + /* Now combine the left and right logical nodes together */ + + /* Set the address of the node we're creating. */ + unsigned int j; + internal_idx_offset >>= 1; + for (j = 0; j < 4; j++) { + set_tree_height(tree_addrx4 + j * 8, h + 1); + set_tree_index(tree_addrx4 + j * 8, + (4 / 2) * (internal_idx & ~1U) + j - left_adj + internal_idx_offset ); + } + unsigned char *left = &stackx4[h * 4 * SPX_N]; + thashx4( ¤t[0 * SPX_N], + ¤t[1 * SPX_N], + ¤t[2 * SPX_N], + ¤t[3 * SPX_N], + &left [0 * SPX_N], + &left [2 * SPX_N], + ¤t[0 * SPX_N], + ¤t[2 * SPX_N], + 2, ctx, tree_addrx4); + } + + /* We've hit a left child; save the current for when we get the */ + /* corresponding right right */ + memcpy( &stackx4[h * 4 * SPX_N], current, 4 * SPX_N); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/utilsx4.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/utilsx4.h index 158ef5ed3b..facb874b18 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/utilsx4.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/utilsx4.h @@ -1,38 +1,30 @@ -#ifndef PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_UTILSX4_H -#define PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_UTILSX4_H - -#include "hash_state.h" -#include "params.h" +#ifndef SPX_UTILSX4_H +#define SPX_UTILSX4_H #include +#include "context.h" +#include "params.h" + /** * For a given leaf index, computes the authentication path and the resulting * root node using Merkle's TreeHash algorithm. * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_ADDR_TYPE_FORSTREE). + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). * Applies the offset idx_offset to indices before building addresses, so that * it is possible to continue counting indices across trees. + * + * This implementation uses AVX to compute internal nodes 4 at a time (in + * parallel) */ -void PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_treehashx4_FORS_HEIGHT(unsigned char *rootx4, - unsigned char *auth_pathx4, - const unsigned char *sk_seed, - const unsigned char *pub_seed, - const uint32_t leaf_idx[4], - uint32_t idx_offset[4], - void (*gen_leafx4)(unsigned char * /* leaf0 */, - unsigned char * /* leaf1 */, - unsigned char * /* leaf2 */, - unsigned char * /* leaf3 */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx0 */, - uint32_t /* addr_idx1 */, - uint32_t /* addr_idx2 */, - uint32_t /* addr_idx3 */, - const uint32_t[8] /* tree_addr */, - const hash_state * /* state_seeded */), - uint32_t tree_addrx4[4 * 8], - const hash_state *state_seeded); +#define treehashx4 SPX_NAMESPACE(treehashx4) +void treehashx4(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leafx4)( + unsigned char * /* Where to write the leaves */, + const spx_ctx * /* ctx */, + uint32_t addr_idx, void *info), + uint32_t tree_addrx4[4 * 8], void *info); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/wots.c b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/wots.c index 674c4d2b83..4d5041ce05 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/wots.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/wots.c @@ -1,106 +1,104 @@ #include #include +#include "wots.h" + #include "address.h" #include "hash.h" -#include "hash_state.h" #include "hashx4.h" #include "params.h" #include "thash.h" #include "thashx4.h" #include "utils.h" -#include "wots.h" +#include "utilsx4.h" +#include "wotsx4.h" // TODO clarify address expectations, and make them more uniform. // TODO i.e. do we expect types to be set already? // TODO and do we expect modifications or copies? /** - * Computes the starting value for a chain, i.e. the secret key. - * Expects the address to be complete up to the chain address. - */ -static void wots_gen_sk(unsigned char *sk, const unsigned char *sk_seed, - uint32_t wots_addr[8], const hash_state *state_seeded) { - /* Make sure that the hash address is actually zeroed. */ - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_set_hash_addr(wots_addr, 0); - - /* Generate sk element. */ - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_prf_addr(sk, sk_seed, wots_addr, state_seeded); -} - -/** - * 4-way parallel version of wots_gen_sk; expects 4x as much space in sk + * Computes up the chains */ -static void wots_gen_skx4(unsigned char *skx4, const unsigned char *sk_seed, - uint32_t wots_addrx4[4 * 8], const hash_state *state_seeded) { - unsigned int j; - - /* Make sure that the hash address is actually zeroed. */ +static void gen_chains( + unsigned char *out, + const unsigned char *in, + unsigned int start[SPX_WOTS_LEN], + const unsigned int steps[SPX_WOTS_LEN], + const spx_ctx *ctx, + uint32_t addr[8]) { + uint32_t i, j, k, idx, watching; + int done; + unsigned char empty[SPX_N]; + unsigned char *bufs[4]; + uint32_t addrs[8 * 4]; + + int l; + uint16_t counts[SPX_WOTS_W] = { 0 }; + uint16_t idxs[SPX_WOTS_LEN]; + uint16_t total, newTotal; + + /* set addrs = {addr, addr, addr, addr} */ for (j = 0; j < 4; j++) { - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_set_hash_addr(wots_addrx4 + j * 8, 0); + memcpy(addrs + j * 8, addr, sizeof(uint32_t) * 8); } - /* Generate sk element. */ - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_prf_addrx4(skx4 + 0 * PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N, - skx4 + 1 * PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N, - skx4 + 2 * PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N, - skx4 + 3 * PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N, - sk_seed, wots_addrx4, - state_seeded); -} - -/** - * Computes the chaining function. - * out and in have to be n-byte arrays. - * - * Interprets in as start-th value of the chain. - * addr has to contain the address of the chain. - */ -static void gen_chain(unsigned char *out, const unsigned char *in, - unsigned int start, unsigned int steps, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *state_seeded) { - uint32_t i; - /* Initialize out with the value at position 'start'. */ - memcpy(out, in, PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N); + memcpy(out, in, SPX_WOTS_LEN * SPX_N); - /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_WOTS_W; i++) { - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_set_hash_addr(addr, i); - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_thash_1(out, out, pub_seed, addr, state_seeded); + /* Sort the chains in reverse order by steps using counting sort. */ + for (i = 0; i < SPX_WOTS_LEN; i++) { + counts[steps[i]]++; + } + total = 0; + for (l = SPX_WOTS_W - 1; l >= 0; l--) { + newTotal = counts[l] + total; + counts[l] = total; + total = newTotal; + } + for (i = 0; i < SPX_WOTS_LEN; i++) { + idxs[counts[steps[i]]] = (uint16_t)i; + counts[steps[i]]++; } -} -/** - * 4-way parallel version of gen_chain; expects 4x as much space in out, and - * 4x as much space in inx4. Assumes start and step identical across chains. - */ -static void gen_chainx4(unsigned char *outx4, const unsigned char *inx4, - unsigned int start, unsigned int steps, - const unsigned char *pub_seed, uint32_t addrx4[4 * 8], - const hash_state *state_seeded) { - uint32_t i; - unsigned int j; + /* We got our work cut out for us: do it! */ + for (i = 0; i < SPX_WOTS_LEN; i += 4) { + for (j = 0; j < 4 && i + j < SPX_WOTS_LEN; j++) { + idx = idxs[i + j]; + set_chain_addr(addrs + j * 8, idx); + bufs[j] = out + SPX_N * idx; + } - /* Initialize outx4 with the value at position 'start'. */ - memcpy(outx4, inx4, 4 * PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N); + /* As the chains are sorted in reverse order, we know that the first + * chain is the longest and the last one is the shortest. We keep + * an eye on whether the last chain is done and then on the one before, + * et cetera. */ + watching = 3; + done = 0; + while (i + watching >= SPX_WOTS_LEN) { + bufs[watching] = &empty[0]; + watching--; + } - /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_WOTS_W; i++) { - for (j = 0; j < 4; j++) { - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_set_hash_addr(addrx4 + j * 8, i); + for (k = 0;; k++) { + while (k == steps[idxs[i + watching]]) { + bufs[watching] = &empty[0]; + if (watching == 0) { + done = 1; + break; + } + watching--; + } + if (done) { + break; + } + for (j = 0; j < watching + 1; j++) { + set_hash_addr(addrs + j * 8, k + start[idxs[i + j]]); + } + + thashx4(bufs[0], bufs[1], bufs[2], bufs[3], + bufs[0], bufs[1], bufs[2], bufs[3], 1, ctx, addrs); } - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_thashx4_1(outx4 + 0 * PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N, - outx4 + 1 * PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N, - outx4 + 2 * PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N, - outx4 + 3 * PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N, - outx4 + 0 * PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N, - outx4 + 1 * PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N, - outx4 + 2 * PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N, - outx4 + 3 * PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N, - pub_seed, addrx4, - state_seeded); } } @@ -109,7 +107,8 @@ static void gen_chainx4(unsigned char *outx4, const unsigned char *inx4, * Interprets an array of bytes as integers in base w. * This only works when log_w is a divisor of 8. */ -static void base_w(unsigned int *output, const int out_len, const unsigned char *input) { +static void base_w(unsigned int *output, const int out_len, + const unsigned char *input) { int in = 0; int out = 0; unsigned char total = 0; @@ -122,119 +121,149 @@ static void base_w(unsigned int *output, const int out_len, const unsigned char in++; bits += 8; } - bits -= PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_WOTS_LOGW; - output[out] = (unsigned int)(total >> bits) & (PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_WOTS_W - 1); + bits -= SPX_WOTS_LOGW; + output[out] = (total >> bits) & (SPX_WOTS_W - 1); out++; } } /* Computes the WOTS+ checksum over a message (in base_w). */ -static void wots_checksum(unsigned int *csum_base_w, const unsigned int *msg_base_w) { +static void wots_checksum(unsigned int *csum_base_w, + const unsigned int *msg_base_w) { unsigned int csum = 0; - unsigned char csum_bytes[(PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_WOTS_LEN2 * PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_WOTS_LOGW + 7) / 8]; + unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; unsigned int i; /* Compute checksum. */ - for (i = 0; i < PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_WOTS_LEN1; i++) { - csum += PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_WOTS_W - 1 - msg_base_w[i]; + for (i = 0; i < SPX_WOTS_LEN1; i++) { + csum += SPX_WOTS_W - 1 - msg_base_w[i]; } /* Convert checksum to base_w. */ /* Make sure expected empty zero bits are the least significant bits. */ - csum = csum << (8 - ((PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_WOTS_LEN2 * PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_WOTS_LOGW) % 8)); - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); - base_w(csum_base_w, PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_WOTS_LEN2, csum_bytes); + csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); + ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); + base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); } /* Takes a message and derives the matching chain lengths. */ -static void chain_lengths(unsigned int *lengths, const unsigned char *msg) { - base_w(lengths, PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_WOTS_LEN1, msg); - wots_checksum(lengths + PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_WOTS_LEN1, lengths); +void chain_lengths(unsigned int *lengths, const unsigned char *msg) { + base_w(lengths, SPX_WOTS_LEN1, msg); + wots_checksum(lengths + SPX_WOTS_LEN1, lengths); } /** - * WOTS key generation. Takes a 32 byte sk_seed, expands it to WOTS private key - * elements and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. * * Writes the computed public key to 'pk'. */ -void PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_wots_gen_pk(unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *state_seeded) { +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]) { + unsigned int steps[SPX_WOTS_LEN]; + unsigned int start[SPX_WOTS_LEN]; uint32_t i; - unsigned int j; - uint32_t addrx4[4 * 8]; - unsigned char pkbuf[4 * PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N]; + chain_lengths(start, msg); - for (j = 0; j < 4; j++) { - memcpy(addrx4 + j * 8, addr, sizeof(uint32_t) * 8); - } - - /* The last iteration typically does not have complete set of 4 chains, - but because we use pkbuf, this is not an issue -- we still do as many - in parallel as possible. */ - for (i = 0; i < ((PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_WOTS_LEN + 3) & ~0x3); i += 4) { - for (j = 0; j < 4; j++) { - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_set_chain_addr(addrx4 + j * 8, i + j); - } - wots_gen_skx4(pkbuf, sk_seed, addrx4, state_seeded); - gen_chainx4(pkbuf, pkbuf, 0, PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_WOTS_W - 1, pub_seed, addrx4, state_seeded); - for (j = 0; j < 4; j++) { - if (i + j < PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_WOTS_LEN) { - memcpy(pk + (i + j)*PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N, pkbuf + j * PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N, PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N); - } - } + for (i = 0; i < SPX_WOTS_LEN; i++) { + steps[i] = SPX_WOTS_W - 1 - start[i]; } - // Get rid of unused argument variable. - (void)state_seeded; + gen_chains(pk, sig, start, steps, ctx, addr); } -/** - * Takes a n-byte message and the 32-byte sk_see to compute a signature 'sig'. +/* + * This generates 4 sequential WOTS public keys + * It also generates the WOTS signature if leaf_info indicates + * that we're signing with one of these WOTS keys */ -void PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_wots_sign(unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); +void wots_gen_leafx4(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info) { + struct leaf_info_x4 *info = v_info; + uint32_t *leaf_addr = info->leaf_addr; + uint32_t *pk_addr = info->pk_addr; + unsigned int i, j, k; + unsigned char pk_buffer[ 4 * SPX_WOTS_BYTES ]; + unsigned wots_offset = SPX_WOTS_BYTES; + unsigned char *buffer; + uint32_t wots_k_mask; + unsigned wots_sign_index; + + if (((leaf_idx ^ info->wots_sign_leaf) & ~3U) == 0) { + /* We're traversing the leaf that's signing; generate the WOTS */ + /* signature */ + wots_k_mask = 0; + wots_sign_index = info->wots_sign_leaf & 3; /* Which of of the 4 */ + /* 4 slots do the signatures come from */ + } else { + /* Nope, we're just generating pk's; turn off the signature logic */ + wots_k_mask = (uint32_t)~0; + wots_sign_index = 0; + } - for (i = 0; i < PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_WOTS_LEN; i++) { - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_set_chain_addr(addr, i); - wots_gen_sk(sig + i * PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N, sk_seed, addr, state_seeded); - gen_chain(sig + i * PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N, sig + i * PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N, 0, lengths[i], pub_seed, addr, state_seeded); + for (j = 0; j < 4; j++) { + set_keypair_addr( leaf_addr + j * 8, leaf_idx + j ); + set_keypair_addr( pk_addr + j * 8, leaf_idx + j ); } - // avoid unused argument - (void)state_seeded; -} + for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { + uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k to */ + /* the step if we're generating a signature, ~0 if we're not */ -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_WOTS_LEN]; - uint32_t i; + /* Start with the secret seed */ + for (j = 0; j < 4; j++) { + set_chain_addr(leaf_addr + j * 8, i); + set_hash_addr(leaf_addr + j * 8, 0); + set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTSPRF); + } + prf_addrx4(buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + buffer + 2 * wots_offset, + buffer + 3 * wots_offset, + ctx, leaf_addr); - chain_lengths(lengths, msg); + for (j = 0; j < 4; j++) { + set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTS); + } + + /* Iterate down the WOTS chain */ + for (k = 0;; k++) { + /* Check if one of the values we have needs to be saved as a */ + /* part of the WOTS signature */ + if (k == wots_k) { + memcpy( info->wots_sig + i * SPX_N, + buffer + wots_sign_index * wots_offset, SPX_N ); + } - for (i = 0; i < PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_WOTS_LEN; i++) { - PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_set_chain_addr(addr, i); - gen_chain(pk + i * PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N, sig + i * PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_N, - lengths[i], PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_WOTS_W - 1 - lengths[i], pub_seed, addr, - state_seeded); + /* Check if we hit the top of the chain */ + if (k == SPX_WOTS_W - 1) { + break; + } + + /* Iterate one step on all 4 chains */ + for (j = 0; j < 4; j++) { + set_hash_addr(leaf_addr + j * 8, k); + } + thashx4(buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + buffer + 2 * wots_offset, + buffer + 3 * wots_offset, + buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + buffer + 2 * wots_offset, + buffer + 3 * wots_offset, 1, ctx, leaf_addr); + } } - // avoid unused argument - (void)state_seeded; + /* Do the final thash to generate the public keys */ + thashx4(dest + 0 * SPX_N, + dest + 1 * SPX_N, + dest + 2 * SPX_N, + dest + 3 * SPX_N, + pk_buffer + 0 * wots_offset, + pk_buffer + 1 * wots_offset, + pk_buffer + 2 * wots_offset, + pk_buffer + 3 * wots_offset, SPX_WOTS_LEN, ctx, pk_addr); } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/wots.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/wots.h index 168bf0765a..4e7692eeef 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/wots.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/wots.h @@ -1,41 +1,25 @@ -#ifndef PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_WOTS_H -#define PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_WOTS_H +#ifndef SPX_WOTS_H +#define SPX_WOTS_H -#include "hash_state.h" -#include "params.h" #include -/** - * WOTS key generation. Takes a 32 byte seed for the private key, expands it to - * a full WOTS private key and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_wots_gen_pk( - unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -/** - * Takes a n-byte message and the 32-byte seed for the private key to compute a - * signature that is placed at 'sig'. - */ -void PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_wots_sign( - unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *hash_state_seeded); +#include "context.h" +#include "params.h" /** * Takes a WOTS signature and an n-byte message, computes a WOTS public key. * * Writes the computed public key to 'pk'. */ -void PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_wots_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); +#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]); + +/* + * Compute the chain lengths needed for a given message hash + */ +#define chain_lengths SPX_NAMESPACE(chain_lengths) +void chain_lengths(unsigned int *lengths, const unsigned char *msg); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/wotsx4.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/wotsx4.h new file mode 100644 index 0000000000..cd634f1743 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/wotsx4.h @@ -0,0 +1,41 @@ +#ifndef WOTSX4_H_ +#define WOTSX4_H_ + +#include + +#include "params.h" + +/* + * This is here to provide an interface to the internal wots_gen_leafx4 + * routine. While this routine is not referenced in the package outside of + * wots.c, it is called from the stand-alone benchmark code to characterize + * the performance + */ +struct leaf_info_x4 { + unsigned char *wots_sig; + uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ + uint32_t *wots_steps; + uint32_t leaf_addr[4 * 8]; + uint32_t pk_addr[4 * 8]; +}; + +/* Macro to set the leaf_info to something 'benign', that is, it would */ +/* run with the same time as it does during the real signing process */ +/* Used only by the benchmark code */ +#define INITIALIZE_LEAF_INFO_X4(info, addr, step_buffer) { \ + (info).wots_sig = 0; \ + (info).wots_sign_leaf = ~0; \ + (info).wots_steps = step_buffer; \ + int i; \ + for (i=0; i<4; i++) { \ + memcpy( &(info).leaf_addr[8*i], addr, 32 ); \ + memcpy( &(info).pk_addr[8*i], addr, 32 ); \ + } \ + } + +#define wots_gen_leafx4 SPX_NAMESPACE(wots_gen_leafx4) +void wots_gen_leafx4(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info); + +#endif /* WOTSX4_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/address.c b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/address.c index 495d9451e8..d49d9f3b6b 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/address.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/address.c @@ -1,78 +1,95 @@ #include +#include #include "address.h" #include "params.h" #include "utils.h" -void PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]) { - int i; - - for (i = 0; i < 8; i++) { - PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_ull_to_bytes( - bytes + i * 4, 4, addr[i]); - } -} - -void PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_set_layer_addr( - uint32_t addr[8], uint32_t layer) { - addr[0] = layer; +/* + * Specify which level of Merkle tree (the "layer") we're working on + */ +void set_layer_addr(uint32_t addr[8], uint32_t layer) { + ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; } -void PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_set_tree_addr( - uint32_t addr[8], uint64_t tree) { - addr[1] = 0; - addr[2] = (uint32_t) (tree >> 32); - addr[3] = (uint32_t) tree; +/* + * Specify which Merkle tree within the level (the "tree address") we're working on + */ +void set_tree_addr(uint32_t addr[8], uint64_t tree) { + ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); } -void PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_set_type( - uint32_t addr[8], uint32_t type) { - addr[4] = type; +/* + * Specify the reason we'll use this address structure for, that is, what + * hash will we compute with it. This is used so that unrelated types of + * hashes don't accidentally get the same address structure. The type will be + * one of the SPX_ADDR_TYPE constants + */ +void set_type(uint32_t addr[8], uint32_t type) { + ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; } -void PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; +/* + * Copy the layer and tree fields of the address structure. This is used + * when we're doing multiple types of hashes within the same Merkle tree + */ +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); } /* These functions are used for OTS addresses. */ -void PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_set_keypair_addr( - uint32_t addr[8], uint32_t keypair) { - addr[5] = keypair; +/* + * Specify which Merkle leaf we're working on; that is, which OTS keypair + * we're talking about. + */ +void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { + /* We have > 256 OTS at the bottom of the Merkle tree; to specify */ + /* which one, we'd need to express it in two bytes */ + ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR2] = (unsigned char)(keypair >> 8); + ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; } -void PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; - out[5] = in[5]; +/* + * Copy the layer, tree and keypair fields of the address structure. This is + * used when we're doing multiple things within the same OTS keypair + */ +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); + ((unsigned char *)out)[SPX_OFFSET_KP_ADDR2] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR2]; + ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; } -void PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_set_chain_addr( - uint32_t addr[8], uint32_t chain) { - addr[6] = chain; +/* + * Specify which Merkle chain within the OTS we're working with + * (the chain address) + */ +void set_chain_addr(uint32_t addr[8], uint32_t chain) { + ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; } -void PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_set_hash_addr( - uint32_t addr[8], uint32_t hash) { - addr[7] = hash; +/* + * Specify where in the Merkle chain we are +* (the hash address) + */ +void set_hash_addr(uint32_t addr[8], uint32_t hash) { + ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; } /* These functions are used for all hash tree addresses (including FORS). */ -void PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_set_tree_height( - uint32_t addr[8], uint32_t tree_height) { - addr[6] = tree_height; +/* + * Specify the height of the node in the Merkle/FORS tree we are in + * (the tree height) + */ +void set_tree_height(uint32_t addr[8], uint32_t tree_height) { + ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; } -void PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_set_tree_index( - uint32_t addr[8], uint32_t tree_index) { - addr[7] = tree_index; +/* + * Specify the distance from the left edge of the node in the Merkle/FORS tree + * (the tree index) + */ +void set_tree_index(uint32_t addr[8], uint32_t tree_index) { + u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/address.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/address.h index b58addbb0c..24a84eb40c 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/address.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/address.h @@ -1,50 +1,52 @@ -#ifndef PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_ADDRESS_H -#define PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_ADDRESS_H +#ifndef SPX_ADDRESS_H +#define SPX_ADDRESS_H #include -#define PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_ADDR_TYPE_WOTS 0 -#define PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_ADDR_TYPE_WOTSPK 1 -#define PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_ADDR_TYPE_HASHTREE 2 -#define PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_ADDR_TYPE_FORSTREE 3 -#define PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_ADDR_TYPE_FORSPK 4 +#include "params.h" -void PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]); +/* The hash types that are passed to set_type */ +#define SPX_ADDR_TYPE_WOTS 0 +#define SPX_ADDR_TYPE_WOTSPK 1 +#define SPX_ADDR_TYPE_HASHTREE 2 +#define SPX_ADDR_TYPE_FORSTREE 3 +#define SPX_ADDR_TYPE_FORSPK 4 +#define SPX_ADDR_TYPE_WOTSPRF 5 +#define SPX_ADDR_TYPE_FORSPRF 6 -void PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_set_layer_addr( - uint32_t addr[8], uint32_t layer); +#define set_layer_addr SPX_NAMESPACE(set_layer_addr) +void set_layer_addr(uint32_t addr[8], uint32_t layer); -void PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_set_tree_addr( - uint32_t addr[8], uint64_t tree); +#define set_tree_addr SPX_NAMESPACE(set_tree_addr) +void set_tree_addr(uint32_t addr[8], uint64_t tree); -void PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_set_type( - uint32_t addr[8], uint32_t type); +#define set_type SPX_NAMESPACE(set_type) +void set_type(uint32_t addr[8], uint32_t type); /* Copies the layer and tree part of one address into the other */ -void PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]); +#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); /* These functions are used for WOTS and FORS addresses. */ -void PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_set_keypair_addr( - uint32_t addr[8], uint32_t keypair); +#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) +void set_keypair_addr(uint32_t addr[8], uint32_t keypair); -void PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_set_chain_addr( - uint32_t addr[8], uint32_t chain); +#define set_chain_addr SPX_NAMESPACE(set_chain_addr) +void set_chain_addr(uint32_t addr[8], uint32_t chain); -void PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_set_hash_addr( - uint32_t addr[8], uint32_t hash); +#define set_hash_addr SPX_NAMESPACE(set_hash_addr) +void set_hash_addr(uint32_t addr[8], uint32_t hash); -void PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]); +#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); /* These functions are used for all hash tree addresses (including FORS). */ -void PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_set_tree_height( - uint32_t addr[8], uint32_t tree_height); +#define set_tree_height SPX_NAMESPACE(set_tree_height) +void set_tree_height(uint32_t addr[8], uint32_t tree_height); -void PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_set_tree_index( - uint32_t addr[8], uint32_t tree_index); +#define set_tree_index SPX_NAMESPACE(set_tree_index) +void set_tree_index(uint32_t addr[8], uint32_t tree_index); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/api.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/api.h index fc12fc00d4..43aa4622f3 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/api.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/api.h @@ -4,15 +4,13 @@ #include #include - - -#define PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_CRYPTO_ALGNAME "SPHINCS+" +#define PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_CRYPTO_ALGNAME "SPHINCS+-haraka-128s-robust" #define PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_CRYPTO_SECRETKEYBYTES 64 #define PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_CRYPTO_PUBLICKEYBYTES 32 -#define PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_CRYPTO_BYTES 7856 -#define PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_CRYPTO_SEEDBYTES 48 +#define PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_CRYPTO_BYTES 7856 +#define PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_CRYPTO_SEEDBYTES 48 /* * Returns the length of a secret key, in bytes @@ -39,43 +37,41 @@ size_t PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_crypto_sign_seedbytes(void); * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] * Format pk: [root || PUB_SEED] */ -int PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed); +int PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); /* * Generates a SPHINCS+ key pair. * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] * Format pk: [root || PUB_SEED] */ -int PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk); +int PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); /** * Returns an array containing a detached signature. */ -int PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk); +int PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); /** * Verifies a detached signature and message under a given public key. */ -int PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk); +int PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, + const uint8_t *pk); /** * Returns an array containing the signature followed by the message. */ -int PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk); +int PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); /** * Verifies a given signature-message pair under a given public key. */ -int PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk); - +int PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/context.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/context.h new file mode 100644 index 0000000000..600dfb73c7 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/context.h @@ -0,0 +1,24 @@ +#ifndef SPX_CONTEXT_H +#define SPX_CONTEXT_H + +#include +#include + +#include "params.h" + +typedef struct { + uint8_t pub_seed[SPX_N]; + uint8_t sk_seed[SPX_N]; + + + uint64_t tweaked512_rc64[10][8]; + uint32_t tweaked256_rc32[10][8]; +} spx_ctx; + +#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) +void initialize_hash_function(spx_ctx *ctx); + +#define free_hash_function SPX_NAMESPACE(free_hash_function) +void free_hash_function(spx_ctx *ctx); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/context_haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/context_haraka.c new file mode 100644 index 0000000000..f1cd7e3664 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/context_haraka.c @@ -0,0 +1,11 @@ +#include "context.h" +#include "haraka.h" + +void initialize_hash_function(spx_ctx *ctx) { + tweak_constants(ctx); +} + +// we don't support heap-based haraka right now +void free_hash_function(spx_ctx *ctx) { + (void)ctx; // suppress unused variable warnings +} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/fors.c b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/fors.c index 8f2bd1503d..96ca72e986 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/fors.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/fors.c @@ -2,58 +2,58 @@ #include #include -#include "address.h" #include "fors.h" + +#include "address.h" #include "hash.h" -#include "hash_state.h" #include "thash.h" #include "utils.h" +#include "utilsx1.h" -static void fors_gen_sk(unsigned char *sk, const unsigned char *sk_seed, - uint32_t fors_leaf_addr[8], const hash_state *hash_state_seeded) { - PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_prf_addr( - sk, sk_seed, fors_leaf_addr, hash_state_seeded); +static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + prf_addr(sk, ctx, fors_leaf_addr); } static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, - const unsigned char *pub_seed, - uint32_t fors_leaf_addr[8], - const hash_state *hash_state_seeded) { - PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_thash_1( - leaf, sk, pub_seed, fors_leaf_addr, hash_state_seeded); + const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + thash(leaf, sk, 1, ctx, fors_leaf_addr); } -static void fors_gen_leaf(unsigned char *leaf, const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx, const uint32_t fors_tree_addr[8], - const hash_state *hash_state_seeded) { - uint32_t fors_leaf_addr[8] = {0}; - - /* Only copy the parts that must be kept in fors_leaf_addr. */ - PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_copy_keypair_addr( - fors_leaf_addr, fors_tree_addr); - PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_set_type( - fors_leaf_addr, PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_set_tree_index( - fors_leaf_addr, addr_idx); - - fors_gen_sk(leaf, sk_seed, fors_leaf_addr, hash_state_seeded); - fors_sk_to_leaf(leaf, leaf, pub_seed, fors_leaf_addr, hash_state_seeded); +struct fors_gen_leaf_info { + uint32_t leaf_addrx[8]; +}; + +static void fors_gen_leafx1(unsigned char *leaf, + const spx_ctx *ctx, + uint32_t addr_idx, void *info) { + struct fors_gen_leaf_info *fors_info = info; + uint32_t *fors_leaf_addr = fors_info->leaf_addrx; + + /* Only set the parts that the caller doesn't set */ + set_tree_index(fors_leaf_addr, addr_idx); + set_type(fors_leaf_addr, SPX_ADDR_TYPE_FORSPRF); + fors_gen_sk(leaf, ctx, fors_leaf_addr); + + set_type(fors_leaf_addr, SPX_ADDR_TYPE_FORSTREE); + fors_sk_to_leaf(leaf, leaf, + ctx, fors_leaf_addr); } /** - * Interprets m as PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_FORS_HEIGHT-bit unsigned integers. - * Assumes m contains at least PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_FORS_TREES bits. - * Assumes indices has space for PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_FORS_TREES integers. + * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + * Assumes indices has space for SPX_FORS_TREES integers. */ static void message_to_indices(uint32_t *indices, const unsigned char *m) { unsigned int i, j; unsigned int offset = 0; - for (i = 0; i < PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_FORS_TREES; i++) { + for (i = 0; i < SPX_FORS_TREES; i++) { indices[i] = 0; - for (j = 0; j < PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_FORS_HEIGHT; j++) { - indices[i] ^= (((uint32_t)m[offset >> 3] >> (offset & 0x7)) & 0x1) << j; + for (j = 0; j < SPX_FORS_HEIGHT; j++) { + indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); offset++; } } @@ -61,55 +61,51 @@ static void message_to_indices(uint32_t *indices, const unsigned char *m) { /** * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_FORS_TREES bits. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. */ -void PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_fors_sign( - unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *hash_state_seeded) { - uint32_t indices[PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_FORS_TREES]; - unsigned char roots[PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_FORS_TREES * PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_N]; +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; uint32_t fors_tree_addr[8] = {0}; + struct fors_gen_leaf_info fors_info = {0}; + uint32_t *fors_leaf_addr = fors_info.leaf_addrx; uint32_t fors_pk_addr[8] = {0}; uint32_t idx_offset; unsigned int i; - PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_copy_keypair_addr( - fors_tree_addr, fors_addr); - PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_copy_keypair_addr( - fors_pk_addr, fors_addr); + copy_keypair_addr(fors_tree_addr, fors_addr); + copy_keypair_addr(fors_leaf_addr, fors_addr); - PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_set_type( - fors_tree_addr, PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_set_type( - fors_pk_addr, PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_ADDR_TYPE_FORSPK); + copy_keypair_addr(fors_pk_addr, fors_addr); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); message_to_indices(indices, m); - for (i = 0; i < PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_FORS_TREES; i++) { - idx_offset = i * (1 << PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_FORS_HEIGHT); + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); - PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_set_tree_height( - fors_tree_addr, 0); - PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_set_tree_index( - fors_tree_addr, indices[i] + idx_offset); + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); /* Include the secret key part that produces the selected leaf node. */ - fors_gen_sk(sig, sk_seed, fors_tree_addr, hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_N; + fors_gen_sk(sig, ctx, fors_tree_addr); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + sig += SPX_N; /* Compute the authentication path for this leaf node. */ - PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_treehash_FORS_HEIGHT( - roots + i * PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_N, sig, sk_seed, pub_seed, - indices[i], idx_offset, fors_gen_leaf, fors_tree_addr, - hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_N * PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_FORS_HEIGHT; + treehashx1(roots + i * SPX_N, sig, ctx, + indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx1, + fors_tree_addr, &fors_info); + + sig += SPX_N * SPX_FORS_HEIGHT; } /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_thash_FORS_TREES( - pk, roots, pub_seed, fors_pk_addr, hash_state_seeded); + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); } /** @@ -117,45 +113,44 @@ void PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_fors_sign( * This can be used for verification by comparing to a known public key, or to * subsequently verify a signature on the derived public key. The latter is the * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_FORS_TREES bits. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. */ -void PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_fors_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, const uint32_t fors_addr[8], - const hash_state *hash_state_seeded) { - uint32_t indices[PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_FORS_TREES]; - unsigned char roots[PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_FORS_TREES * PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_N]; - unsigned char leaf[PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_N]; +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + unsigned char leaf[SPX_N]; uint32_t fors_tree_addr[8] = {0}; uint32_t fors_pk_addr[8] = {0}; uint32_t idx_offset; unsigned int i; - PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_copy_keypair_addr(fors_tree_addr, fors_addr); - PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_copy_keypair_addr(fors_pk_addr, fors_addr); + copy_keypair_addr(fors_tree_addr, fors_addr); + copy_keypair_addr(fors_pk_addr, fors_addr); - PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_set_type(fors_tree_addr, PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_set_type(fors_pk_addr, PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_ADDR_TYPE_FORSPK); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); message_to_indices(indices, m); - for (i = 0; i < PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_FORS_TREES; i++) { - idx_offset = i * (1 << PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_FORS_HEIGHT); + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); - PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_set_tree_height(fors_tree_addr, 0); - PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_set_tree_index(fors_tree_addr, indices[i] + idx_offset); + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); /* Derive the leaf from the included secret key part. */ - fors_sk_to_leaf(leaf, sig, pub_seed, fors_tree_addr, hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_N; + fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); + sig += SPX_N; /* Derive the corresponding root node of this tree. */ - PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_compute_root(roots + i * PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_N, leaf, indices[i], idx_offset, sig, - PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_FORS_HEIGHT, pub_seed, fors_tree_addr, hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_N * PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_FORS_HEIGHT; + compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, + sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); + sig += SPX_N * SPX_FORS_HEIGHT; } /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_thash_FORS_TREES(pk, roots, pub_seed, fors_pk_addr, hash_state_seeded); + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/fors.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/fors.h index 58c25b1389..509140a178 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/fors.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/fors.h @@ -1,32 +1,32 @@ -#ifndef PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_FORS_H -#define PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_FORS_H +#ifndef SPX_FORS_H +#define SPX_FORS_H #include -#include "hash_state.h" +#include "context.h" #include "params.h" /** * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_FORS_TREES bits. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. */ -void PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_fors_sign( - unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *hash_state_seeded); +#define fors_sign SPX_NAMESPACE(fors_sign) +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); /** * Derives the FORS public key from a signature. * This can be used for verification by comparing to a known public key, or to * subsequently verify a signature on the derived public key. The latter is the * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_FORS_TREES bits. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. */ -void PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_fors_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, const uint32_t fors_addr[8], - const hash_state *hash_state_seeded); +#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/haraka.c index 26a2794679..a4944913b5 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/haraka.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/haraka.c @@ -6,12 +6,13 @@ * by Thomas Pornin */ -#include #include +#include #include #include #include "haraka.h" +#include "utils.h" #define HARAKAS_RATE 32 @@ -656,76 +657,62 @@ static void interleave_constant32(uint32_t *out, const unsigned char *in) { br_aes_ct_ortho(out); } -void PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_tweak_constants( - harakactx *state, - const unsigned char *pk_seed, const unsigned char *sk_seed, - unsigned long long seed_length) { +void tweak_constants(spx_ctx *ctx) { unsigned char buf[40 * 16]; int i; /* Use the standard constants to generate tweaked ones. */ - memcpy((uint8_t *)state->tweaked512_rc64, (uint8_t *)haraka512_rc64, 40 * 16); - - /* Constants for sk.seed */ - if (sk_seed != NULL) { - PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_haraka_S( - buf, 40 * 16, sk_seed, seed_length, state); - - /* Interleave constants */ - for (i = 0; i < 10; i++) { - interleave_constant32(state->tweaked256_rc32_sseed[i], buf + 32 * i); - } - } + memcpy((uint8_t *)ctx->tweaked512_rc64, (uint8_t *)haraka512_rc64, 40 * 16); /* Constants for pk.seed */ - PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_haraka_S( - buf, 40 * 16, pk_seed, seed_length, state); + haraka_S(buf, 40 * 16, ctx->pub_seed, SPX_N, ctx); for (i = 0; i < 10; i++) { - interleave_constant32(state->tweaked256_rc32[i], buf + 32 * i); - interleave_constant(state->tweaked512_rc64[i], buf + 64 * i); + interleave_constant32(ctx->tweaked256_rc32[i], buf + 32 * i); + interleave_constant(ctx->tweaked512_rc64[i], buf + 64 * i); } } -static void haraka_S_absorb(unsigned char *s, +static void haraka_S_absorb(unsigned char *s, unsigned int r, const unsigned char *m, unsigned long long mlen, - unsigned char p, const harakactx *state) { + unsigned char p, const spx_ctx *ctx) { unsigned long long i; - unsigned char t[HARAKAS_RATE]; + PQCLEAN_VLA(uint8_t, t, r); - while (mlen >= HARAKAS_RATE) { + while (mlen >= r) { /* XOR block to state */ - for (i = 0; i < HARAKAS_RATE; ++i) { + for (i = 0; i < r; ++i) { s[i] ^= m[i]; } - PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_haraka512_perm(s, s, state); - mlen -= HARAKAS_RATE; - m += HARAKAS_RATE; + haraka512_perm(s, s, ctx); + mlen -= r; + m += r; } - for (i = 0; i < HARAKAS_RATE; ++i) { + for (i = 0; i < r; ++i) { t[i] = 0; } for (i = 0; i < mlen; ++i) { t[i] = m[i]; } t[i] = p; - t[HARAKAS_RATE - 1] |= 128; - for (i = 0; i < HARAKAS_RATE; ++i) { + t[r - 1] |= 128; + for (i = 0; i < r; ++i) { s[i] ^= t[i]; } } static void haraka_S_squeezeblocks(unsigned char *h, unsigned long long nblocks, - unsigned char *s, const harakactx *state) { + unsigned char *s, unsigned int r, + const spx_ctx *ctx) { while (nblocks > 0) { - PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_haraka512_perm(s, s, state); + haraka512_perm(s, s, ctx); memcpy(h, s, HARAKAS_RATE); - h += HARAKAS_RATE; + h += r; nblocks--; } } -void PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_haraka_S_inc_init(uint8_t *s_inc) { +void haraka_S_inc_init(uint8_t *s_inc) { size_t i; for (i = 0; i < 64; i++) { @@ -734,7 +721,8 @@ void PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_haraka_S_inc_init(uint8_t *s_inc) { s_inc[64] = 0; } -void PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, const harakactx *state) { +void haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, + const spx_ctx *ctx) { size_t i; /* Recall that s_inc[64] is the non-absorbed bytes xored into the state */ @@ -745,19 +733,19 @@ void PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_haraka_S_inc_absorb(uint8_t *s_inc, c s_inc[s_inc[64] + i] ^= m[i]; } mlen -= (size_t)(HARAKAS_RATE - s_inc[64]); - m += HARAKAS_RATE - s_inc[64]; + m += HARAKAS_RATE - (uint8_t)s_inc[64]; s_inc[64] = 0; - PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_haraka512_perm(s_inc, s_inc, state); + haraka512_perm(s_inc, s_inc, ctx); } for (i = 0; i < mlen; i++) { s_inc[s_inc[64] + i] ^= m[i]; } - s_inc[64] = (uint8_t)(mlen + s_inc[64]); + s_inc[64] += (uint8_t)mlen; } -void PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_haraka_S_inc_finalize(uint8_t *s_inc) { +void haraka_S_inc_finalize(uint8_t *s_inc) { /* After haraka_S_inc_absorb, we are guaranteed that s_inc[64] < HARAKAS_RATE, so we can always use one more byte for p in the current state. */ s_inc[s_inc[64]] ^= 0x1F; @@ -765,22 +753,23 @@ void PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_haraka_S_inc_finalize(uint8_t *s_inc) s_inc[64] = 0; } -void PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, const harakactx *state) { - uint8_t i; +void haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, + const spx_ctx *ctx) { + size_t i; /* First consume any bytes we still have sitting around */ for (i = 0; i < outlen && i < s_inc[64]; i++) { /* There are s_inc[64] bytes left, so r - s_inc[64] is the first available byte. We consume from there, i.e., up to r. */ - out[i] = s_inc[(HARAKAS_RATE - s_inc[64] + i)]; + out[i] = (uint8_t)s_inc[(HARAKAS_RATE - s_inc[64] + i)]; } out += i; outlen -= i; - s_inc[64] = (uint8_t)(s_inc[64] - i); + s_inc[64] -= (uint8_t)i; /* Then squeeze the remaining necessary blocks */ while (outlen > 0) { - PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_haraka512_perm(s_inc, s_inc, state); + haraka512_perm(s_inc, s_inc, ctx); for (i = 0; i < outlen && i < HARAKAS_RATE; i++) { out[i] = s_inc[i]; @@ -791,7 +780,9 @@ void PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_haraka_S_inc_squeeze(uint8_t *out, si } } -void PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_haraka_S(unsigned char *out, unsigned long long outlen, const unsigned char *in, unsigned long long inlen, const harakactx *state) { +void haraka_S(unsigned char *out, unsigned long long outlen, + const unsigned char *in, unsigned long long inlen, + const spx_ctx *ctx) { unsigned long long i; unsigned char s[64]; unsigned char d[32]; @@ -799,20 +790,21 @@ void PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_haraka_S(unsigned char *out, unsigned for (i = 0; i < 64; i++) { s[i] = 0; } - haraka_S_absorb(s, in, inlen, 0x1F, state); + haraka_S_absorb(s, 32, in, inlen, 0x1F, ctx); - haraka_S_squeezeblocks(out, outlen / 32, s, state); + haraka_S_squeezeblocks(out, outlen / 32, s, 32, ctx); out += (outlen / 32) * 32; if (outlen % 32) { - haraka_S_squeezeblocks(d, 1, s, state); + haraka_S_squeezeblocks(d, 1, s, 32, ctx); for (i = 0; i < outlen % 32; i++) { out[i] = d[i]; } } } -void PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_haraka512_perm(unsigned char *out, const unsigned char *in, const harakactx *state) { +void haraka512_perm(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx) { uint32_t w[16]; uint64_t q[8], tmp_q; unsigned int i, j; @@ -829,7 +821,7 @@ void PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_haraka512_perm(unsigned char *out, co br_aes_ct64_bitslice_Sbox(q); shift_rows(q); mix_columns(q); - add_round_key(q, state->tweaked512_rc64[2 * i + j]); + add_round_key(q, ctx->tweaked512_rc64[2 * i + j]); } /* Mix states */ for (j = 0; j < 8; j++) { @@ -857,12 +849,12 @@ void PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_haraka512_perm(unsigned char *out, co br_range_enc32le(out, w, 16); } -void PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_haraka512(unsigned char *out, const unsigned char *in, const harakactx *state) { +void haraka512(unsigned char *out, const unsigned char *in, const spx_ctx *ctx) { int i; unsigned char buf[64]; - PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_haraka512_perm(buf, in, state); + haraka512_perm(buf, in, ctx); /* Feed-forward */ for (i = 0; i < 64; i++) { buf[i] = buf[i] ^ in[i]; @@ -876,50 +868,8 @@ void PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_haraka512(unsigned char *out, const u } -void PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_haraka256(unsigned char *out, const unsigned char *in, const harakactx *state) { - uint32_t q[8], tmp_q; - int i, j; - - for (i = 0; i < 4; i++) { - q[2 * i] = br_dec32le(in + 4 * i); - q[2 * i + 1] = br_dec32le(in + 4 * i + 16); - } - br_aes_ct_ortho(q); - - /* AES rounds */ - for (i = 0; i < 5; i++) { - for (j = 0; j < 2; j++) { - br_aes_ct_bitslice_Sbox(q); - shift_rows32(q); - mix_columns32(q); - add_round_key32(q, state->tweaked256_rc32[2 * i + j]); - } - - /* Mix states */ - for (j = 0; j < 8; j++) { - tmp_q = q[j]; - q[j] = (tmp_q & 0x81818181) | - (tmp_q & 0x02020202) << 1 | - (tmp_q & 0x04040404) << 2 | - (tmp_q & 0x08080808) << 3 | - (tmp_q & 0x10101010) >> 3 | - (tmp_q & 0x20202020) >> 2 | - (tmp_q & 0x40404040) >> 1; - } - } - - br_aes_ct_ortho(q); - for (i = 0; i < 4; i++) { - br_enc32le(out + 4 * i, q[2 * i]); - br_enc32le(out + 4 * i + 16, q[2 * i + 1]); - } - - for (i = 0; i < 32; i++) { - out[i] ^= in[i]; - } -} - -void PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_haraka256_sk(unsigned char *out, const unsigned char *in, const harakactx *state) { +void haraka256(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx) { uint32_t q[8], tmp_q; int i, j; @@ -935,7 +885,7 @@ void PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_haraka256_sk(unsigned char *out, cons br_aes_ct_bitslice_Sbox(q); shift_rows32(q); mix_columns32(q); - add_round_key32(q, state->tweaked256_rc32_sseed[2 * i + j]); + add_round_key32(q, ctx->tweaked256_rc32[2 * i + j]); } /* Mix states */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/haraka.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/haraka.h index 0c9b45eaf6..737cb6065f 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/haraka.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/haraka.h @@ -1,40 +1,42 @@ -#ifndef PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_HARAKA_H -#define PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_HARAKA_H +#ifndef SPX_HARAKA_H +#define SPX_HARAKA_H -#include -#include - -typedef struct { - uint64_t tweaked512_rc64[10][8]; - uint32_t tweaked256_rc32[10][8]; - uint32_t tweaked256_rc32_sseed[10][8]; -} harakactx; +#include "context.h" +#include "params.h" /* Tweak constants with seed */ -void PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_tweak_constants( - harakactx *state, - const unsigned char *pk_seed, const unsigned char *sk_seed, - unsigned long long seed_length); +#define tweak_constants SPX_NAMESPACE(tweak_constants) +void tweak_constants(spx_ctx *ctx); /* Haraka Sponge */ -void PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_haraka_S_inc_init(uint8_t *s_inc); -void PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, const harakactx *state); -void PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_haraka_S_inc_finalize(uint8_t *s_inc); -void PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, const harakactx *state); -void PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_haraka_S( - unsigned char *out, unsigned long long outlen, - const unsigned char *in, unsigned long long inlen, const harakactx *state); +#define haraka_S_inc_init SPX_NAMESPACE(haraka_S_inc_init) +void haraka_S_inc_init(uint8_t *s_inc); +#define haraka_S_inc_absorb SPX_NAMESPACE(haraka_S_inc_absorb) +void haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, + const spx_ctx *ctx); +#define haraka_S_inc_finalize SPX_NAMESPACE(haraka_S_inc_finalize) +void haraka_S_inc_finalize(uint8_t *s_inc); +#define haraka_S_inc_squeeze SPX_NAMESPACE(haraka_S_inc_squeeze) +void haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, + const spx_ctx *ctx); +#define haraka_S SPX_NAMESPACE(haraka_S) +void haraka_S(unsigned char *out, unsigned long long outlen, + const unsigned char *in, unsigned long long inlen, + const spx_ctx *ctx); /* Applies the 512-bit Haraka permutation to in. */ -void PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_haraka512_perm(unsigned char *out, const unsigned char *in, const harakactx *state); +#define haraka512_perm SPX_NAMESPACE(haraka512_perm) +void haraka512_perm(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx); /* Implementation of Haraka-512 */ -void PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_haraka512(unsigned char *out, const unsigned char *in, const harakactx *state); +#define haraka512 SPX_NAMESPACE(haraka512) +void haraka512(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx); /* Implementation of Haraka-256 */ -void PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_haraka256(unsigned char *out, const unsigned char *in, const harakactx *state); - -/* Implementation of Haraka-256 using sk.seed constants */ -void PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_haraka256_sk(unsigned char *out, const unsigned char *in, const harakactx *state); +#define haraka256 SPX_NAMESPACE(haraka256) +void haraka256(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/haraka_offsets.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/haraka_offsets.h new file mode 100644 index 0000000000..7c062272a0 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/haraka_offsets.h @@ -0,0 +1,21 @@ +#ifndef HARAKA_OFFSETS_H_ +#define HARAKA_OFFSETS_H_ + +/* + * Offsets of various fields in the address structure when we use Haraka as + * the Sphincs+ hash function + */ + +#define SPX_OFFSET_LAYER 3 /* The byte used to specify the Merkle tree layer */ +#define SPX_OFFSET_TREE 8 /* The start of the 8 byte field used to specify the tree */ +#define SPX_OFFSET_TYPE 19 /* The byte used to specify the hash type (reason) */ +#define SPX_OFFSET_KP_ADDR2 22 /* The high byte used to specify the key pair (which one-time signature) */ +#define SPX_OFFSET_KP_ADDR1 23 /* The low byte used to specify the key pair */ +#define SPX_OFFSET_CHAIN_ADDR 27 /* The byte used to specify the chain address (which Winternitz chain) */ +#define SPX_OFFSET_HASH_ADDR 31 /* The byte used to specify the hash address (where in the Winternitz chain) */ +#define SPX_OFFSET_TREE_HGT 27 /* The byte used to specify the height of this node in the FORS or Merkle tree */ +#define SPX_OFFSET_TREE_INDEX 28 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ + +#define SPX_HARAKA 1 + +#endif /* HARAKA_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/hash.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/hash.h index c7d076f955..f7c87d4c3c 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/hash.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/hash.h @@ -1,31 +1,28 @@ -#ifndef PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_HASH_H -#define PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_HASH_H - -#include "hash_state.h" +#ifndef SPX_HASH_H +#define SPX_HASH_H #include #include -void PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_initialize_hash_function( - hash_state *hash_state_seeded, - const unsigned char *pub_seed, const unsigned char *sk_seed); +#include "context.h" +#include "params.h" + +#define prf_addr SPX_NAMESPACE(prf_addr) +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]); -void PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_destroy_hash_function(hash_state *hash_state_seeded); +#define gen_message_random SPX_NAMESPACE(gen_message_random) +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); -void PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded); +#define hash_message SPX_NAMESPACE(hash_message) +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); -void PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); -void PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/hash_haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/hash_haraka.c index b3c7ba562a..750a67423b 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/hash_haraka.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/hash_haraka.c @@ -2,58 +2,44 @@ #include #include "address.h" -#include "haraka.h" -#include "hash.h" #include "params.h" #include "utils.h" -void PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_initialize_hash_function( - hash_state *hash_state_seeded, - const unsigned char *pub_seed, const unsigned char *sk_seed) { - PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_tweak_constants(hash_state_seeded, pub_seed, sk_seed, PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_N); -} - -/* The haraka implementation is stack based and won't be replaced in PQClean/OQS, - so we don't need to do anything */ -void PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_destroy_hash_function( - hash_state *hash_state_seeded) { // NOLINT(readability-non-const-parameter) - (void)hash_state_seeded; -} +#include "haraka.h" +#include "hash.h" /* - * Computes PRF(key, addr), given a secret key of PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_N bytes and an address + * Computes PRF(key, addr), given a secret key of SPX_N bytes and an address */ -void PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded) { - unsigned char buf[PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_ADDR_BYTES]; - /* Since PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_N may be smaller than 32, we need a temporary buffer. */ +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]) { + /* Since SPX_N may be smaller than 32, we need temporary buffers. */ unsigned char outbuf[32]; + unsigned char buf[64] = {0}; - (void)key; /* Suppress an 'unused parameter' warning. */ + memcpy(buf, addr, SPX_ADDR_BYTES); + memcpy(buf + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); - PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_addr_to_bytes(buf, addr); - PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_haraka256_sk(outbuf, buf, hash_state_seeded); - memcpy(out, outbuf, PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_N); + haraka512(outbuf, (const void *)buf, ctx); + memcpy(out, outbuf, SPX_N); } /** * Computes the message-dependent randomness R, using a secret seed and an * optional randomization value as well as the message. */ -void PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded) { +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { uint8_t s_inc[65]; - PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_haraka_S_inc_init(s_inc); - PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_haraka_S_inc_absorb(s_inc, sk_prf, PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_N, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_haraka_S_inc_absorb(s_inc, optrand, PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_N, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_haraka_S_inc_absorb(s_inc, m, mlen, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_haraka_S_inc_finalize(s_inc); - PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_haraka_S_inc_squeeze(R, PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_N, s_inc, hash_state_seeded); + haraka_S_inc_init(s_inc); + haraka_S_inc_absorb(s_inc, sk_prf, SPX_N, ctx); + haraka_S_inc_absorb(s_inc, optrand, SPX_N, ctx); + haraka_S_inc_absorb(s_inc, m, mlen, ctx); + haraka_S_inc_finalize(s_inc); + haraka_S_inc_squeeze(R, SPX_N, s_inc, ctx); } /** @@ -61,36 +47,35 @@ void PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_gen_message_random( * Outputs the message digest and the index of the leaf. The index is split in * the tree index and the leaf index, for convenient copying to an address. */ -void PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded) { -#define PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_TREE_BITS (PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_TREE_HEIGHT * (PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_D - 1)) -#define PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_TREE_BYTES ((PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_TREE_BITS + 7) / 8) -#define PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_LEAF_BITS PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_TREE_HEIGHT -#define PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_LEAF_BYTES ((PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_LEAF_BITS + 7) / 8) -#define PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_DGST_BYTES (PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_FORS_MSG_BYTES + PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_TREE_BYTES + PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_LEAF_BYTES) +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { +#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) +#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) +#define SPX_LEAF_BITS SPX_TREE_HEIGHT +#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) +#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) - unsigned char buf[PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_DGST_BYTES]; + unsigned char buf[SPX_DGST_BYTES]; unsigned char *bufp = buf; uint8_t s_inc[65]; - PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_haraka_S_inc_init(s_inc); - PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_haraka_S_inc_absorb(s_inc, R, PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_N, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_haraka_S_inc_absorb(s_inc, pk + PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_N, PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_N, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_haraka_S_inc_absorb(s_inc, m, mlen, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_haraka_S_inc_finalize(s_inc); - PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_haraka_S_inc_squeeze(buf, PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_DGST_BYTES, s_inc, hash_state_seeded); + haraka_S_inc_init(s_inc); + haraka_S_inc_absorb(s_inc, R, SPX_N, ctx); + haraka_S_inc_absorb(s_inc, pk + SPX_N, SPX_N, ctx); // Only absorb root part of pk + haraka_S_inc_absorb(s_inc, m, mlen, ctx); + haraka_S_inc_finalize(s_inc); + haraka_S_inc_squeeze(buf, SPX_DGST_BYTES, s_inc, ctx); + + memcpy(digest, bufp, SPX_FORS_MSG_BYTES); + bufp += SPX_FORS_MSG_BYTES; - memcpy(digest, bufp, PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_FORS_MSG_BYTES); - bufp += PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_FORS_MSG_BYTES; - *tree = PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_bytes_to_ull(bufp, PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_TREE_BYTES); - *tree &= (~(uint64_t)0) >> (64 - PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_TREE_BITS); - bufp += PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_TREE_BYTES; + *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); + *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); + bufp += SPX_TREE_BYTES; - *leaf_idx = (uint32_t)PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_bytes_to_ull( - bufp, PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_LEAF_BYTES); - *leaf_idx &= (~(uint32_t)0) >> (32 - PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_LEAF_BITS); + *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); + *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/hash_state.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/hash_state.h deleted file mode 100644 index 5adb1d9a22..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/hash_state.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef SPX_HASH_STATE_H -#define SPX_HASH_STATE_H - -/** - * Defines the type of the hash function state. - * - * Don't be fooled into thinking this instance of SPHINCS+ isn't stateless! - * - * From Section 7.2.2 from the SPHINCS+ round-2 specification: - * - * Each of the instances of the tweakable hash function take PK.seed as its - * first input, which is constant for a given key pair – and, thus, across - * a single signature. This leads to a lot of redundant computation. To remedy - * this, we pad PK.seed to the length of a full 64-byte SHA-256 input block. - * Because of the Merkle-DamgÃ¥rd construction that underlies SHA-256, this - * allows for reuse of the intermediate SHA-256 state after the initial call to - * the compression function which improves performance. - * - * We pass this hash state around in functions, because otherwise we need to - * have a global variable. - */ - -#include "haraka.h" -#define hash_state harakactx - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/merkle.c b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/merkle.c new file mode 100644 index 0000000000..0c1479fd93 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/merkle.c @@ -0,0 +1,59 @@ +#include +#include + +#include "address.h" +#include "merkle.h" +#include "params.h" +#include "utils.h" +#include "utilsx1.h" +#include "wots.h" +#include "wotsx1.h" + +/* + * This generates a Merkle signature (WOTS signature followed by the Merkle + * authentication path). This is in this file because most of the complexity + * is involved with the WOTS signature; the Merkle authentication path logic + * is mostly hidden in treehashx4 + */ +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf) { + unsigned char *auth_path = sig + SPX_WOTS_BYTES; + struct leaf_info_x1 info = { 0 }; + unsigned steps[ SPX_WOTS_LEN ]; + + info.wots_sig = sig; + chain_lengths(steps, root); + info.wots_steps = steps; + + set_type(&tree_addr[0], SPX_ADDR_TYPE_HASHTREE); + set_type(&info.pk_addr[0], SPX_ADDR_TYPE_WOTSPK); + copy_subtree_addr(&info.leaf_addr[0], wots_addr); + copy_subtree_addr(&info.pk_addr[0], wots_addr); + + info.wots_sign_leaf = idx_leaf; + + treehashx1(root, auth_path, ctx, + idx_leaf, 0, + SPX_TREE_HEIGHT, + wots_gen_leafx1, + tree_addr, &info); +} + +/* Compute root node of the top-most subtree. */ +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { + /* We do not need the auth path in key generation, but it simplifies the + code to have just one treehash routine that computes both root and path + in one function. */ + unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; + uint32_t top_tree_addr[8] = {0}; + uint32_t wots_addr[8] = {0}; + + set_layer_addr(top_tree_addr, SPX_D - 1); + set_layer_addr(wots_addr, SPX_D - 1); + + merkle_sign(auth_path, root, ctx, + wots_addr, top_tree_addr, + (uint32_t)~0 /* ~0 means "don't bother generating an auth path */ ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/merkle.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/merkle.h new file mode 100644 index 0000000000..769cf2e970 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/merkle.h @@ -0,0 +1,21 @@ +#ifndef MERKLE_H_ +#define MERKLE_H_ + +#include + +#include "context.h" +#include "params.h" + +/* Generate a Merkle signature (WOTS signature followed by the Merkle */ +/* authentication path) */ +#define merkle_sign SPX_NAMESPACE(merkle_sign) +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf); + +/* Compute the root node of the top-most subtree. */ +#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); + +#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/nistapi.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/nistapi.h new file mode 100644 index 0000000000..3cb71afad4 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/nistapi.h @@ -0,0 +1,87 @@ +#ifndef SPX_API_H +#define SPX_API_H + +#include +#include + +#include "params.h" + +#define CRYPTO_ALGNAME "SPHINCS+" + +#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES +#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES +#define CRYPTO_BYTES SPX_BYTES +#define CRYPTO_SEEDBYTES (3*SPX_N) + +/* + * Returns the length of a secret key, in bytes + */ +#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) +size_t crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) +size_t crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) +size_t crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) +size_t crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +#define crypto_sign SPX_NAMESPACE(crypto_sign) +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/params.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/params.h index 70f544aba6..417aa923a8 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/params.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/params.h @@ -1,53 +1,56 @@ -#ifndef PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_PARAMS_H -#define PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_PARAMS_H +#ifndef SPX_PARAMS_H +#define SPX_PARAMS_H + +#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_##s /* Hash output length in bytes. */ -#define PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_N 16 +#define SPX_N 16 /* Height of the hypertree. */ -#define PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_FULL_HEIGHT 63 +#define SPX_FULL_HEIGHT 63 /* Number of subtree layer. */ -#define PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_D 7 +#define SPX_D 7 /* FORS tree dimensions. */ -#define PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_FORS_HEIGHT 12 -#define PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_FORS_TREES 14 +#define SPX_FORS_HEIGHT 12 +#define SPX_FORS_TREES 14 /* Winternitz parameter, */ -#define PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_WOTS_W 16 +#define SPX_WOTS_W 16 /* The hash function is defined by linking a different hash.c file, as opposed to setting a #define constant. */ /* For clarity */ -#define PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_ADDR_BYTES 32 +#define SPX_ADDR_BYTES 32 /* WOTS parameters. */ -#define PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_WOTS_LOGW 4 +#define SPX_WOTS_LOGW 4 -#define PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_WOTS_LEN1 (8 * PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_N / PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_WOTS_LOGW) +#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) -/* PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#define PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_WOTS_LEN2 3 +/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ +#define SPX_WOTS_LEN2 3 -#define PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_WOTS_LEN (PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_WOTS_LEN1 + PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_WOTS_LEN2) -#define PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_WOTS_BYTES (PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_WOTS_LEN * PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_N) -#define PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_WOTS_PK_BYTES PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_WOTS_BYTES +#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) +#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) +#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES /* Subtree size. */ -#define PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_TREE_HEIGHT (PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_FULL_HEIGHT / PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_D) +#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) + +//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT +// #error SPX_D should always divide SPX_FULL_HEIGHT +//#endif /* FORS parameters. */ -#define PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_FORS_MSG_BYTES ((PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_FORS_TREES + 7) / 8) -#define PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_FORS_BYTES ((PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_FORS_HEIGHT + 1) * PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_FORS_TREES * PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_N) -#define PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_FORS_PK_BYTES PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_N +#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) +#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) +#define SPX_FORS_PK_BYTES SPX_N /* Resulting SPX sizes. */ -#define PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_BYTES (PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_N + PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_FORS_BYTES + PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_D * PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_WOTS_BYTES +\ - PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_FULL_HEIGHT * PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_N) -#define PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_PK_BYTES (2 * PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_N) -#define PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_SK_BYTES (2 * PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_N + PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_PK_BYTES) - -/* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ -#define PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_OPTRAND_BYTES 32 +#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ + SPX_FULL_HEIGHT * SPX_N) +#define SPX_PK_BYTES (2 * SPX_N) +#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) + +#include "haraka_offsets.h" #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/sign.c b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/sign.c index 1db675a214..9d0c7d1b22 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/sign.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/sign.c @@ -3,72 +3,43 @@ #include #include "address.h" -#include "api.h" +#include "context.h" #include "fors.h" #include "hash.h" -#include "hash_state.h" +#include "merkle.h" +#include "nistapi.h" #include "params.h" #include "randombytes.h" #include "thash.h" #include "utils.h" #include "wots.h" -/** - * Computes the leaf at a given address. First generates the WOTS key pair, - * then computes leaf by hashing horizontally. - */ -static void wots_gen_leaf(unsigned char *leaf, const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx, const uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - unsigned char pk[PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_WOTS_BYTES]; - uint32_t wots_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_set_type( - wots_addr, PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_set_type( - wots_pk_addr, PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_ADDR_TYPE_WOTSPK); - - PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_set_keypair_addr( - wots_addr, addr_idx); - PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_wots_gen_pk( - pk, sk_seed, pub_seed, wots_addr, hash_state_seeded); - - PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_copy_keypair_addr( - wots_pk_addr, wots_addr); - PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_thash_WOTS_LEN( - leaf, pk, pub_seed, wots_pk_addr, hash_state_seeded); -} - /* * Returns the length of a secret key, in bytes */ -size_t PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_crypto_sign_secretkeybytes(void) { - return PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_CRYPTO_SECRETKEYBYTES; +size_t crypto_sign_secretkeybytes(void) { + return CRYPTO_SECRETKEYBYTES; } /* * Returns the length of a public key, in bytes */ -size_t PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_crypto_sign_publickeybytes(void) { - return PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_CRYPTO_PUBLICKEYBYTES; +size_t crypto_sign_publickeybytes(void) { + return CRYPTO_PUBLICKEYBYTES; } /* * Returns the length of a signature, in bytes */ -size_t PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_crypto_sign_bytes(void) { - return PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_CRYPTO_BYTES; +size_t crypto_sign_bytes(void) { + return CRYPTO_BYTES; } /* * Returns the length of the seed required to generate a key pair, in bytes */ -size_t PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_crypto_sign_seedbytes(void) { - return PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_CRYPTO_SEEDBYTES; +size_t crypto_sign_seedbytes(void) { + return CRYPTO_SEEDBYTES; } /* @@ -76,37 +47,30 @@ size_t PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_crypto_sign_seedbytes(void) { * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] * Format pk: [PUB_SEED || root] */ -int PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed) { - /* We do not need the auth path in key generation, but it simplifies the - code to have just one treehash routine that computes both root and path - in one function. */ - unsigned char auth_path[PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_TREE_HEIGHT * PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_N]; - uint32_t top_tree_addr[8] = {0}; - hash_state hash_state_seeded; - - PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_set_layer_addr( - top_tree_addr, PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_D - 1); - PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_set_type( - top_tree_addr, PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_ADDR_TYPE_HASHTREE); +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed) { + spx_ctx ctx; /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ - memcpy(sk, seed, PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_CRYPTO_SEEDBYTES); + memcpy(sk, seed, CRYPTO_SEEDBYTES); - memcpy(pk, sk + 2 * PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_N, PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_N); + memcpy(pk, sk + 2 * SPX_N, SPX_N); + + memcpy(ctx.pub_seed, pk, SPX_N); + memcpy(ctx.sk_seed, sk, SPX_N); /* This hook allows the hash function instantiation to do whatever preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_initialize_hash_function(&hash_state_seeded, pk, sk); + initialize_hash_function(&ctx); /* Compute root node of the top-most subtree. */ - PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_treehash_TREE_HEIGHT( - sk + 3 * PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_N, auth_path, sk, sk + 2 * PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_N, 0, 0, - wots_gen_leaf, top_tree_addr, &hash_state_seeded); + merkle_gen_root(sk + 3 * SPX_N, &ctx); + + // cleanup + free_hash_function(&ctx); - memcpy(pk + PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_N, sk + 3 * PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_N, PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_N); + memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); - PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_destroy_hash_function(&hash_state_seeded); return 0; } @@ -115,12 +79,10 @@ int PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_crypto_sign_seed_keypair( * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] * Format pk: [PUB_SEED || root] */ -int PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk) { - unsigned char seed[PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_CRYPTO_SEEDBYTES]; - randombytes(seed, PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_CRYPTO_SEEDBYTES); - PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_crypto_sign_seed_keypair( - pk, sk, seed); +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { + uint8_t seed[CRYPTO_SEEDBYTES]; + randombytes(seed, CRYPTO_SEEDBYTES); + crypto_sign_seed_keypair(pk, sk, seed); return 0; } @@ -128,101 +90,83 @@ int PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_crypto_sign_keypair( /** * Returns an array containing a detached signature. */ -int PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - const unsigned char *sk_seed = sk; - const unsigned char *sk_prf = sk + PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_N; - const unsigned char *pk = sk + 2 * PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_N; - const unsigned char *pub_seed = pk; - - unsigned char optrand[PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_N]; - unsigned char mhash[PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_FORS_MSG_BYTES]; - unsigned char root[PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_N]; +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk) { + spx_ctx ctx; + + const uint8_t *sk_prf = sk + SPX_N; + const uint8_t *pk = sk + 2 * SPX_N; + + uint8_t optrand[SPX_N]; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t root[SPX_N]; uint32_t i; uint64_t tree; uint32_t idx_leaf; uint32_t wots_addr[8] = {0}; uint32_t tree_addr[8] = {0}; - hash_state hash_state_seeded; + memcpy(ctx.sk_seed, sk, SPX_N); + memcpy(ctx.pub_seed, pk, SPX_N); /* This hook allows the hash function instantiation to do whatever preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_initialize_hash_function( - &hash_state_seeded, - pub_seed, sk_seed); + initialize_hash_function(&ctx); - PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_set_type( - wots_addr, PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_set_type( - tree_addr, PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_ADDR_TYPE_HASHTREE); + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); /* Optionally, signing can be made non-deterministic using optrand. This can help counter side-channel attacks that would benefit from getting a large number of traces when the signer uses the same nodes. */ - randombytes(optrand, PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_N); + randombytes(optrand, SPX_N); /* Compute the digest randomization value. */ - PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_gen_message_random( - sig, sk_prf, optrand, m, mlen, &hash_state_seeded); + gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); /* Derive the message digest and leaf index from R, PK and M. */ - PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_N; + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; - PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); /* Sign the message hash using FORS. */ - PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_fors_sign( - sig, root, mhash, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_FORS_BYTES; - - for (i = 0; i < PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_D; i++) { - PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_set_tree_addr(tree_addr, tree); - - PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); - - /* Compute a WOTS signature. */ - PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_wots_sign( - sig, root, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_WOTS_BYTES; - - /* Compute the authentication path for the used WOTS leaf. */ - PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_treehash_TREE_HEIGHT( - root, sig, sk_seed, pub_seed, idx_leaf, 0, - wots_gen_leaf, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_TREE_HEIGHT * PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_N; + fors_sign(sig, root, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); + sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_TREE_HEIGHT; + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; } - *siglen = PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_BYTES; + free_hash_function(&ctx); + + *siglen = SPX_BYTES; - PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_destroy_hash_function(&hash_state_seeded); return 0; } /** * Verifies a detached signature and message under a given public key. */ -int PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk) { - const unsigned char *pub_seed = pk; - const unsigned char *pub_root = pk + PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_N; - unsigned char mhash[PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_FORS_MSG_BYTES]; - unsigned char wots_pk[PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_WOTS_BYTES]; - unsigned char root[PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_N]; - unsigned char leaf[PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_N]; +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk) { + spx_ctx ctx; + const uint8_t *pub_root = pk + SPX_N; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t wots_pk[SPX_WOTS_BYTES]; + uint8_t root[SPX_N]; + uint8_t leaf[SPX_N]; unsigned int i; uint64_t tree; uint32_t idx_leaf; @@ -230,78 +174,66 @@ int PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_crypto_sign_verify( uint32_t tree_addr[8] = {0}; uint32_t wots_pk_addr[8] = {0}; - hash_state hash_state_seeded; - - if (siglen != PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_BYTES) { + if (siglen != SPX_BYTES) { return -1; } + memcpy(ctx.pub_seed, pk, SPX_N); + /* This hook allows the hash function instantiation to do whatever preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_initialize_hash_function( - &hash_state_seeded, - pub_seed, NULL); + initialize_hash_function(&ctx); - PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_set_type( - wots_addr, PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_set_type( - tree_addr, PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_ADDR_TYPE_HASHTREE); - PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_set_type( - wots_pk_addr, PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_ADDR_TYPE_WOTSPK); + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); /* Derive the message digest and leaf index from R || PK || M. */ - /* The additional PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_N is a result of the hash domain separator. */ - PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_N; + /* The additional SPX_N is a result of the hash domain separator. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; /* Layer correctly defaults to 0, so no need to set_layer_addr */ - PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); - PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_fors_pk_from_sig( - root, sig, mhash, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_FORS_BYTES; + fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; /* For each subtree.. */ - for (i = 0; i < PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_D; i++) { - PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_set_tree_addr(tree_addr, tree); + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); - PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); - PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_copy_keypair_addr( - wots_pk_addr, wots_addr); + copy_keypair_addr(wots_pk_addr, wots_addr); /* The WOTS public key is only correct if the signature was correct. */ /* Initially, root is the FORS pk, but on subsequent iterations it is the root of the subtree below the currently processed subtree. */ - PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_wots_pk_from_sig( - wots_pk, sig, root, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_WOTS_BYTES; + wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); + sig += SPX_WOTS_BYTES; /* Compute the leaf node using the WOTS public key. */ - PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_thash_WOTS_LEN( - leaf, wots_pk, pub_seed, wots_pk_addr, &hash_state_seeded); + thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); /* Compute the root node of this subtree. */ - PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_compute_root( - root, leaf, idx_leaf, 0, sig, PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_TREE_HEIGHT, - pub_seed, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_TREE_HEIGHT * PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_N; + compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, + &ctx, tree_addr); + sig += SPX_TREE_HEIGHT * SPX_N; /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_TREE_HEIGHT; + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; } - PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_destroy_hash_function(&hash_state_seeded); + // cleanup + free_hash_function(&ctx); + /* Check if the root node equals the root node in the public key. */ - if (memcmp(root, pub_root, PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_N) != 0) { + if (memcmp(root, pub_root, SPX_N) != 0) { return -1; } @@ -312,15 +244,14 @@ int PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_crypto_sign_verify( /** * Returns an array containing the signature followed by the message. */ -int PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk) { size_t siglen; - PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_crypto_sign_signature( - sm, &siglen, m, mlen, sk); + crypto_sign_signature(sm, &siglen, m, mlen, sk); - memmove(sm + PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_BYTES, m, mlen); + memmove(sm + SPX_BYTES, m, mlen); *smlen = siglen + mlen; return 0; @@ -329,28 +260,27 @@ int PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_crypto_sign( /** * Verifies a given signature-message pair under a given public key. */ -int PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk) { +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk) { /* The API caller does not necessarily know what size a signature should be - but SPHINCS+ signatures are always exactly PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_BYTES. */ - if (smlen < PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_BYTES) { + but SPHINCS+ signatures are always exactly SPX_BYTES. */ + if (smlen < SPX_BYTES) { memset(m, 0, smlen); *mlen = 0; return -1; } - *mlen = smlen - PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_BYTES; + *mlen = smlen - SPX_BYTES; - if (PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_crypto_sign_verify( - sm, PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_BYTES, sm + PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_BYTES, *mlen, pk)) { + if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { memset(m, 0, smlen); *mlen = 0; return -1; } /* If verification was successful, move the message to the right place. */ - memmove(m, sm + PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_BYTES, *mlen); + memmove(m, sm + SPX_BYTES, *mlen); return 0; } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/thash.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/thash.h index c5a7eb200e..8687ccfb4d 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/thash.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/thash.h @@ -1,28 +1,13 @@ -#ifndef PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_THASH_H -#define PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_THASH_H +#ifndef SPX_THASH_H +#define SPX_THASH_H -#include "hash_state.h" +#include "context.h" +#include "params.h" #include -void PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); +#define thash SPX_NAMESPACE(thash) +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/thash_haraka_robust.c b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/thash_haraka_robust.c index f54180a90b..109502cbc2 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/thash_haraka_robust.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/thash_haraka_robust.c @@ -2,93 +2,44 @@ #include #include "address.h" -#include "hash_state.h" #include "params.h" #include "thash.h" +#include "utils.h" #include "haraka.h" /** - * Takes an array of inblocks concatenated arrays of PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_N bytes. + * Takes an array of inblocks concatenated arrays of SPX_N bytes. */ -static void PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_thash( - unsigned char *out, unsigned char *buf, - const unsigned char *in, unsigned int inblocks, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char *bitmask = buf + PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_ADDR_BYTES; +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]) { + PQCLEAN_VLA(uint8_t, buf, SPX_ADDR_BYTES + inblocks * SPX_N); + PQCLEAN_VLA(uint8_t, bitmask, inblocks * SPX_N); unsigned char outbuf[32]; unsigned char buf_tmp[64]; unsigned int i; - (void)pub_seed; /* Suppress an 'unused parameter' warning. */ - if (inblocks == 1) { /* F function */ - /* Since PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_N may be smaller than 32, we need a temporary buffer. */ + /* Since SPX_N may be smaller than 32, we need a temporary buffer. */ memset(buf_tmp, 0, 64); - PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_addr_to_bytes(buf_tmp, addr); + memcpy(buf_tmp, addr, 32); - PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_haraka256(outbuf, buf_tmp, hash_state_seeded); - for (i = 0; i < inblocks * PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_N; i++) { - buf_tmp[PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_ADDR_BYTES + i] = in[i] ^ outbuf[i]; + haraka256(outbuf, buf_tmp, ctx); + for (i = 0; i < inblocks * SPX_N; i++) { + buf_tmp[SPX_ADDR_BYTES + i] = in[i] ^ outbuf[i]; } - PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_haraka512(outbuf, buf_tmp, hash_state_seeded); - memcpy(out, outbuf, PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_N); + haraka512(outbuf, buf_tmp, ctx); + memcpy(out, outbuf, SPX_N); } else { /* All other tweakable hashes*/ - PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_addr_to_bytes(buf, addr); - PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_haraka_S( - bitmask, inblocks * PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_N, buf, PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_ADDR_BYTES, hash_state_seeded); + memcpy(buf, addr, 32); + haraka_S(bitmask, inblocks * SPX_N, buf, SPX_ADDR_BYTES, ctx); - for (i = 0; i < inblocks * PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_N; i++) { - buf[PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_ADDR_BYTES + i] = in[i] ^ bitmask[i]; + for (i = 0; i < inblocks * SPX_N; i++) { + buf[SPX_ADDR_BYTES + i] = in[i] ^ bitmask[i]; } - PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_haraka_S( - out, PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_N, buf, PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_N, hash_state_seeded); + haraka_S(out, SPX_N, buf, SPX_ADDR_BYTES + inblocks * SPX_N, ctx); } } - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_ADDR_BYTES + 1 * PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_N]; - PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_thash( - out, buf, in, 1, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_ADDR_BYTES + 2 * PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_N]; - PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_thash( - out, buf, in, 2, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_ADDR_BYTES + PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_WOTS_LEN * PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_N]; - PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_thash( - out, buf, in, PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_WOTS_LEN, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_ADDR_BYTES + PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_FORS_TREES * PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_N]; - PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_thash( - out, buf, in, PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_FORS_TREES, pub_seed, addr, hash_state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/utils.c b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/utils.c index 888ea83fd7..177b541fb9 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/utils.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/utils.c @@ -1,34 +1,41 @@ -#include #include +#include "utils.h" + #include "address.h" #include "hash.h" -#include "hash_state.h" #include "params.h" #include "thash.h" -#include "utils.h" /** * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. */ -void PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in) { +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in) { + int i; /* Iterate over out in decreasing order, for big-endianness. */ - for (size_t i = outlen; i > 0; i--) { - out[i - 1] = in & 0xff; + for (i = (signed int)outlen - 1; i >= 0; i--) { + out[i] = in & 0xff; in = in >> 8; } } +void u32_to_bytes(unsigned char *out, uint32_t in) { + out[0] = (unsigned char)(in >> 24); + out[1] = (unsigned char)(in >> 16); + out[2] = (unsigned char)(in >> 8); + out[3] = (unsigned char)in; +} + /** * Converts the inlen bytes in 'in' from big-endian byte order to an integer. */ -unsigned long long PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_bytes_to_ull( - const unsigned char *in, size_t inlen) { +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { unsigned long long retval = 0; + unsigned int i; - for (size_t i = 0; i < inlen; i++) { + for (i = 0; i < inlen; i++) { retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); } return retval; @@ -38,94 +45,80 @@ unsigned long long PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_bytes_to_ull( * Computes a root node given a leaf and an auth path. * Expects address to be complete other than the tree_height and tree_index. */ -void PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]) { uint32_t i; - unsigned char buffer[2 * PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_N]; + unsigned char buffer[2 * SPX_N]; /* If leaf_idx is odd (last bit = 1), current path element is a right child and auth_path has to go left. Otherwise it is the other way around. */ if (leaf_idx & 1) { - memcpy(buffer + PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_N, leaf, PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_N); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_N); + memcpy(buffer + SPX_N, leaf, SPX_N); + memcpy(buffer, auth_path, SPX_N); } else { - memcpy(buffer, leaf, PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_N); - memcpy(buffer + PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_N, auth_path, PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_N); + memcpy(buffer, leaf, SPX_N); + memcpy(buffer + SPX_N, auth_path, SPX_N); } - auth_path += PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_N; + auth_path += SPX_N; for (i = 0; i < tree_height - 1; i++) { leaf_idx >>= 1; idx_offset >>= 1; /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_set_tree_height(addr, i + 1); - PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_set_tree_index( - addr, leaf_idx + idx_offset); + set_tree_height(addr, i + 1); + set_tree_index(addr, leaf_idx + idx_offset); /* Pick the right or left neighbor, depending on parity of the node. */ if (leaf_idx & 1) { - PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_thash_2( - buffer + PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_N, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_N); + thash(buffer + SPX_N, buffer, 2, ctx, addr); + memcpy(buffer, auth_path, SPX_N); } else { - PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_thash_2( - buffer, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer + PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_N, auth_path, PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_N); + thash(buffer, buffer, 2, ctx, addr); + memcpy(buffer + SPX_N, auth_path, SPX_N); } - auth_path += PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_N; + auth_path += SPX_N; } /* The last iteration is exceptional; we do not copy an auth_path node. */ leaf_idx >>= 1; idx_offset >>= 1; - PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_set_tree_height(addr, tree_height); - PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_set_tree_index( - addr, leaf_idx + idx_offset); - PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_thash_2( - root, buffer, pub_seed, addr, hash_state_seeded); + set_tree_height(addr, tree_height); + set_tree_index(addr, leaf_idx + idx_offset); + thash(root, buffer, 2, ctx, addr); } /** * For a given leaf index, computes the authentication path and the resulting * root node using Merkle's TreeHash algorithm. * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_ADDR_TYPE_FORSTREE). + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). * Applies the offset idx_offset to indices before building addresses, so that * it is possible to continue counting indices across trees. */ -static void PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_treehash( - unsigned char *root, unsigned char *auth_path, - unsigned char *stack, unsigned int *heights, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - +void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx * /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]) { + PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); + PQCLEAN_VLA(unsigned int, heights, tree_height + 1); unsigned int offset = 0; uint32_t idx; uint32_t tree_idx; for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { /* Add the next leaf node to the stack. */ - gen_leaf(stack + offset * PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_N, - sk_seed, pub_seed, idx + idx_offset, tree_addr, - hash_state_seeded); + gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); offset++; heights[offset - 1] = 0; /* If this is a node we need for the auth path.. */ if ((leaf_idx ^ 0x1) == idx) { - memcpy(auth_path, stack + (offset - 1)*PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_N, PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_N); + memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); } /* While the top-most nodes are of equal height.. */ @@ -134,66 +127,22 @@ static void PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_treehash( tree_idx = (idx >> (heights[offset - 1] + 1)); /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_set_tree_height( - tree_addr, heights[offset - 1] + 1); - PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_set_tree_index( - tree_addr, tree_idx + (idx_offset >> (heights[offset - 1] + 1))); + set_tree_height(tree_addr, heights[offset - 1] + 1); + set_tree_index(tree_addr, + tree_idx + (idx_offset >> (heights[offset - 1] + 1))); /* Hash the top-most nodes from the stack together. */ - PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_thash_2( - stack + (offset - 2)*PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_N, stack + (offset - 2)*PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_N, - pub_seed, tree_addr, hash_state_seeded); + thash(stack + (offset - 2)*SPX_N, + stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); offset--; /* Note that the top-most node is now one layer higher. */ heights[offset - 1]++; /* If this is a node we need for the auth path.. */ if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_path + heights[offset - 1]*PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_N, - stack + (offset - 1)*PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_N, PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_N); + memcpy(auth_path + heights[offset - 1]*SPX_N, + stack + (offset - 1)*SPX_N, SPX_N); } } } - memcpy(root, stack, PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_N); -} - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_FORS_HEIGHT + 1)*PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_N]; - unsigned int heights[PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_FORS_HEIGHT + 1]; - - PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_FORS_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_TREE_HEIGHT + 1)*PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_N]; - unsigned int heights[PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_TREE_HEIGHT + 1]; - - PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_TREE_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); + memcpy(root, stack, SPX_N); } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/utils.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/utils.h index e85ca45868..64f5d5a53a 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/utils.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/utils.h @@ -1,64 +1,58 @@ -#ifndef PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_UTILS_H -#define PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_UTILS_H +#ifndef SPX_UTILS_H +#define SPX_UTILS_H -#include "hash_state.h" -#include "params.h" -#include #include +#include "compat.h" +#include "context.h" +#include "params.h" + + +/* To support MSVC use alloca() instead of VLAs. See #20. */ + + /** * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. */ -void PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in); +#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in); +#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) +void u32_to_bytes(unsigned char *out, uint32_t in); /** * Converts the inlen bytes in 'in' from big-endian byte order to an integer. */ -unsigned long long PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_bytes_to_ull( - const unsigned char *in, size_t inlen); +#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); /** * Computes a root node given a leaf and an auth path. * Expects address to be complete other than the tree_height and tree_index. */ -void PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); +#define compute_root SPX_NAMESPACE(compute_root) +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]); /** * For a given leaf index, computes the authentication path and the resulting * root node using Merkle's TreeHash algorithm. * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_ADDR_TYPE_FORSTREE). + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). * Applies the offset idx_offset to indices before building addresses, so that * it is possible to continue counting indices across trees. */ -void PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); +#define treehash SPX_NAMESPACE(treehash) +void treehash(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx *ctx /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]); -void PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/utilsx1.c b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/utilsx1.c new file mode 100644 index 0000000000..fccb69b35d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/utilsx1.c @@ -0,0 +1,100 @@ +#include + +#include "utilsx1.h" + +#include "address.h" +#include "params.h" +#include "thash.h" +#include "utils.h" + +/* + * Generate the entire Merkle tree, computing the authentication path for + * leaf_idx, and the resulting root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) + * + * This expects tree_addr to be initialized to the addr structures for the + * Merkle tree nodes + * + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + * + * This works by using the standard Merkle tree building algorithm, + */ +void treehashx1(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, + uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* Where to write the leaves */, + const spx_ctx * /* ctx */, + uint32_t idx, void *info), + uint32_t tree_addr[8], + void *info) { + /* This is where we keep the intermediate nodes */ + PQCLEAN_VLA(uint8_t, stack, tree_height * SPX_N); + + uint32_t idx; + uint32_t max_idx = (uint32_t)((1 << tree_height) - 1); + for (idx = 0;; idx++) { + unsigned char current[2 * SPX_N]; /* Current logical node is at */ + /* index[SPX_N]. We do this to minimize the number of copies */ + /* needed during a thash */ + gen_leaf( ¤t[SPX_N], ctx, idx + idx_offset, + info ); + + /* Now combine the freshly generated right node with previously */ + /* generated left ones */ + uint32_t internal_idx_offset = idx_offset; + uint32_t internal_idx = idx; + uint32_t internal_leaf = leaf_idx; + uint32_t h; /* The height we are in the Merkle tree */ + for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { + + /* Check if we hit the top of the tree */ + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[SPX_N], SPX_N ); + return; + } + + /* + * Check if the node we have is a part of the + * authentication path; if it is, write it out + */ + if ((internal_idx ^ internal_leaf) == 0x01) { + memcpy( &auth_path[ h * SPX_N ], + ¤t[SPX_N], + SPX_N ); + } + + /* + * Check if we're at a left child; if so, stop going up the stack + * Exception: if we've reached the end of the tree, keep on going + * (so we combine the last 4 nodes into the one root node in two + * more iterations) + */ + if ((internal_idx & 1) == 0 && idx < max_idx) { + break; + } + + /* Ok, we're at a right node */ + /* Now combine the left and right logical nodes together */ + + /* Set the address of the node we're creating. */ + internal_idx_offset >>= 1; + set_tree_height(tree_addr, h + 1); + set_tree_index(tree_addr, internal_idx / 2 + internal_idx_offset ); + + unsigned char *left = &stack[h * SPX_N]; + memcpy( ¤t[0], left, SPX_N ); + thash( ¤t[1 * SPX_N], + ¤t[0 * SPX_N], + 2, ctx, tree_addr); + } + + /* We've hit a left child; save the current for when we get the */ + /* corresponding right right */ + memcpy( &stack[h * SPX_N], ¤t[SPX_N], SPX_N); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/utilsx1.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/utilsx1.h new file mode 100644 index 0000000000..e911d17d53 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/utilsx1.h @@ -0,0 +1,27 @@ +#ifndef SPX_UTILSX4_H +#define SPX_UTILSX4_H + +#include + +#include "context.h" +#include "params.h" + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +#define treehashx1 SPX_NAMESPACE(treehashx1) +void treehashx1(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* Where to write the leaf */, + const spx_ctx * /* ctx */, + uint32_t addr_idx, void *info), + uint32_t tree_addrx4[8], void *info); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/wots.c b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/wots.c index de43b7f381..249717aaa8 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/wots.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/wots.c @@ -1,32 +1,20 @@ #include #include +#include "wots.h" +#include "wotsx1.h" + #include "address.h" #include "hash.h" -#include "hash_state.h" #include "params.h" #include "thash.h" #include "utils.h" -#include "wots.h" +#include "utilsx1.h" // TODO clarify address expectations, and make them more uniform. // TODO i.e. do we expect types to be set already? // TODO and do we expect modifications or copies? -/** - * Computes the starting value for a chain, i.e. the secret key. - * Expects the address to be complete up to the chain address. - */ -static void wots_gen_sk(unsigned char *sk, const unsigned char *sk_seed, - uint32_t wots_addr[8], - const hash_state *hash_state_seeded) { - /* Make sure that the hash address is actually zeroed. */ - PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_set_hash_addr(wots_addr, 0); - - /* Generate sk element. */ - PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_prf_addr(sk, sk_seed, wots_addr, hash_state_seeded); -} - /** * Computes the chaining function. * out and in have to be n-byte arrays. @@ -36,18 +24,16 @@ static void wots_gen_sk(unsigned char *sk, const unsigned char *sk_seed, */ static void gen_chain(unsigned char *out, const unsigned char *in, unsigned int start, unsigned int steps, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { + const spx_ctx *ctx, uint32_t addr[8]) { uint32_t i; /* Initialize out with the value at position 'start'. */ - memcpy(out, in, PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_N); + memcpy(out, in, SPX_N); /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_WOTS_W; i++) { - PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_set_hash_addr(addr, i); - PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_thash_1( - out, out, pub_seed, addr, hash_state_seeded); + for (i = start; i < (start + steps) && i < SPX_WOTS_W; i++) { + set_hash_addr(addr, i); + thash(out, out, 1, ctx, addr); } } @@ -56,13 +42,13 @@ static void gen_chain(unsigned char *out, const unsigned char *in, * Interprets an array of bytes as integers in base w. * This only works when log_w is a divisor of 8. */ -static void base_w(unsigned int *output, const size_t out_len, +static void base_w(unsigned int *output, const int out_len, const unsigned char *input) { - size_t in = 0; - size_t out = 0; + int in = 0; + int out = 0; unsigned char total = 0; - unsigned int bits = 0; - size_t consumed; + int bits = 0; + int consumed; for (consumed = 0; consumed < out_len; consumed++) { if (bits == 0) { @@ -70,8 +56,8 @@ static void base_w(unsigned int *output, const size_t out_len, in++; bits += 8; } - bits -= PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_WOTS_LOGW; - output[out] = (unsigned int)((total >> bits) & (PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_WOTS_W - 1)); + bits -= SPX_WOTS_LOGW; + output[out] = (total >> bits) & (SPX_WOTS_W - 1); out++; } } @@ -80,67 +66,25 @@ static void base_w(unsigned int *output, const size_t out_len, static void wots_checksum(unsigned int *csum_base_w, const unsigned int *msg_base_w) { unsigned int csum = 0; - unsigned char csum_bytes[(PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_WOTS_LEN2 * PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_WOTS_LOGW + 7) / 8]; + unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; unsigned int i; /* Compute checksum. */ - for (i = 0; i < PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_WOTS_LEN1; i++) { - csum += PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_WOTS_W - 1 - msg_base_w[i]; + for (i = 0; i < SPX_WOTS_LEN1; i++) { + csum += SPX_WOTS_W - 1 - msg_base_w[i]; } /* Convert checksum to base_w. */ /* Make sure expected empty zero bits are the least significant bits. */ - csum = csum << (8 - ((PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_WOTS_LEN2 * PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_WOTS_LOGW) % 8)); - PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_ull_to_bytes( - csum_bytes, sizeof(csum_bytes), csum); - base_w(csum_base_w, PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_WOTS_LEN2, csum_bytes); + csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); + ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); + base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); } /* Takes a message and derives the matching chain lengths. */ -static void chain_lengths(unsigned int *lengths, const unsigned char *msg) { - base_w(lengths, PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_WOTS_LEN1, msg); - wots_checksum(lengths + PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_WOTS_LEN1, lengths); -} - -/** - * WOTS key generation. Takes a 32 byte sk_seed, expands it to WOTS private key - * elements and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_wots_gen_pk( - unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - uint32_t i; - - for (i = 0; i < PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_WOTS_LEN; i++) { - PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_set_chain_addr(addr, i); - wots_gen_sk(pk + i * PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_N, sk_seed, addr, hash_state_seeded); - gen_chain(pk + i * PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_N, pk + i * PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_N, - 0, PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_WOTS_W - 1, pub_seed, addr, hash_state_seeded); - } -} - -/** - * Takes a n-byte message and the 32-byte sk_see to compute a signature 'sig'. - */ -void PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_wots_sign( - unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *hash_state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_WOTS_LEN; i++) { - PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_set_chain_addr(addr, i); - wots_gen_sk(sig + i * PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_N, sk_seed, addr, hash_state_seeded); - gen_chain(sig + i * PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_N, sig + i * PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_N, 0, lengths[i], pub_seed, addr, hash_state_seeded); - } +void chain_lengths(unsigned int *lengths, const unsigned char *msg) { + base_w(lengths, SPX_WOTS_LEN1, msg); + wots_checksum(lengths + SPX_WOTS_LEN1, lengths); } /** @@ -148,20 +92,17 @@ void PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_wots_sign( * * Writes the computed public key to 'pk'. */ -void PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_wots_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_WOTS_LEN]; +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]) { + unsigned int lengths[SPX_WOTS_LEN]; uint32_t i; chain_lengths(lengths, msg); - for (i = 0; i < PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_WOTS_LEN; i++) { - PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_set_chain_addr(addr, i); - gen_chain(pk + i * PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_N, sig + i * PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_N, - lengths[i], PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_WOTS_W - 1 - lengths[i], pub_seed, addr, - hash_state_seeded); + for (i = 0; i < SPX_WOTS_LEN; i++) { + set_chain_addr(addr, i); + gen_chain(pk + i * SPX_N, sig + i * SPX_N, + lengths[i], SPX_WOTS_W - 1 - lengths[i], ctx, addr); } } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/wots.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/wots.h index b98dd23aa3..4e7692eeef 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/wots.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/wots.h @@ -1,41 +1,25 @@ -#ifndef PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_WOTS_H -#define PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_WOTS_H +#ifndef SPX_WOTS_H +#define SPX_WOTS_H -#include "hash_state.h" -#include "params.h" #include -/** - * WOTS key generation. Takes a 32 byte seed for the private key, expands it to - * a full WOTS private key and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_wots_gen_pk( - unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -/** - * Takes a n-byte message and the 32-byte seed for the private key to compute a - * signature that is placed at 'sig'. - */ -void PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_wots_sign( - unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *hash_state_seeded); +#include "context.h" +#include "params.h" /** * Takes a WOTS signature and an n-byte message, computes a WOTS public key. * * Writes the computed public key to 'pk'. */ -void PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_wots_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); +#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]); + +/* + * Compute the chain lengths needed for a given message hash + */ +#define chain_lengths SPX_NAMESPACE(chain_lengths) +void chain_lengths(unsigned int *lengths, const unsigned char *msg); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/wotsx1.c b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/wotsx1.c new file mode 100644 index 0000000000..3adec78dfb --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/wotsx1.c @@ -0,0 +1,76 @@ +#include +#include + +#include "wots.h" +#include "wotsx1.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "thash.h" +#include "utils.h" + +/* + * This generates a WOTS public key + * It also generates the WOTS signature if leaf_info indicates + * that we're signing with this WOTS key + */ +void wots_gen_leafx1(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info) { + struct leaf_info_x1 *info = v_info; + uint32_t *leaf_addr = info->leaf_addr; + uint32_t *pk_addr = info->pk_addr; + unsigned int i, k; + unsigned char pk_buffer[ SPX_WOTS_BYTES ]; + unsigned char *buffer; + uint32_t wots_k_mask; + + if (leaf_idx == info->wots_sign_leaf) { + /* We're traversing the leaf that's signing; generate the WOTS */ + /* signature */ + wots_k_mask = 0; + } else { + /* Nope, we're just generating pk's; turn off the signature logic */ + wots_k_mask = (uint32_t)~0; + } + + set_keypair_addr( leaf_addr, leaf_idx ); + set_keypair_addr( pk_addr, leaf_idx ); + + for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { + uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k to */ + /* the step if we're generating a signature, ~0 if we're not */ + + /* Start with the secret seed */ + set_chain_addr(leaf_addr, i); + set_hash_addr(leaf_addr, 0); + set_type(leaf_addr, SPX_ADDR_TYPE_WOTSPRF); + + prf_addr(buffer, ctx, leaf_addr); + + set_type(leaf_addr, SPX_ADDR_TYPE_WOTS); + + /* Iterate down the WOTS chain */ + for (k = 0;; k++) { + /* Check if this is the value that needs to be saved as a */ + /* part of the WOTS signature */ + if (k == wots_k) { + memcpy( info->wots_sig + i * SPX_N, buffer, SPX_N ); + } + + /* Check if we hit the top of the chain */ + if (k == SPX_WOTS_W - 1) { + break; + } + + /* Iterate one step on the chain */ + set_hash_addr(leaf_addr, k); + + thash(buffer, buffer, 1, ctx, leaf_addr); + } + } + + /* Do the final thash to generate the public keys */ + thash(dest, pk_buffer, SPX_WOTS_LEN, ctx, pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/wotsx1.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/wotsx1.h new file mode 100644 index 0000000000..e617929f96 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/wotsx1.h @@ -0,0 +1,39 @@ +#ifndef WOTSX1_H_ +#define WOTSX1_H_ + +#include + +#include "context.h" +#include "params.h" + +/* + * This is here to provide an interface to the internal wots_gen_leafx1 + * routine. While this routine is not referenced in the package outside of + * wots.c, it is called from the stand-alone benchmark code to characterize + * the performance + */ +struct leaf_info_x1 { + unsigned char *wots_sig; + uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ + uint32_t *wots_steps; + uint32_t leaf_addr[8]; + uint32_t pk_addr[8]; +}; + +/* Macro to set the leaf_info to something 'benign', that is, it would */ +/* run with the same time as it does during the real signing process */ +/* Used only by the benchmark code */ +#define INITIALIZE_LEAF_INFO_X1(info, addr, step_buffer) { \ + (info).wots_sig = 0; \ + (info).wots_sign_leaf = ~0; \ + (info).wots_steps = step_buffer; \ + memcpy( &(info).leaf_addr[0], (addr), 32 ); \ + memcpy( &(info).pk_addr[0], (addr), 32 ); \ + } + +#define wots_gen_leafx1 SPX_NAMESPACE(wots_gen_leafx1) +void wots_gen_leafx1(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info); + +#endif /* WOTSX1_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/address.c b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/address.c index b32f359345..d49d9f3b6b 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/address.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/address.c @@ -1,78 +1,95 @@ #include +#include #include "address.h" #include "params.h" #include "utils.h" -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]) { - int i; - - for (i = 0; i < 8; i++) { - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_ull_to_bytes( - bytes + i * 4, 4, addr[i]); - } -} - -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_set_layer_addr( - uint32_t addr[8], uint32_t layer) { - addr[0] = layer; +/* + * Specify which level of Merkle tree (the "layer") we're working on + */ +void set_layer_addr(uint32_t addr[8], uint32_t layer) { + ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; } -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_set_tree_addr( - uint32_t addr[8], uint64_t tree) { - addr[1] = 0; - addr[2] = (uint32_t) (tree >> 32); - addr[3] = (uint32_t) tree; +/* + * Specify which Merkle tree within the level (the "tree address") we're working on + */ +void set_tree_addr(uint32_t addr[8], uint64_t tree) { + ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); } -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_set_type( - uint32_t addr[8], uint32_t type) { - addr[4] = type; +/* + * Specify the reason we'll use this address structure for, that is, what + * hash will we compute with it. This is used so that unrelated types of + * hashes don't accidentally get the same address structure. The type will be + * one of the SPX_ADDR_TYPE constants + */ +void set_type(uint32_t addr[8], uint32_t type) { + ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; } -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; +/* + * Copy the layer and tree fields of the address structure. This is used + * when we're doing multiple types of hashes within the same Merkle tree + */ +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); } /* These functions are used for OTS addresses. */ -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_set_keypair_addr( - uint32_t addr[8], uint32_t keypair) { - addr[5] = keypair; +/* + * Specify which Merkle leaf we're working on; that is, which OTS keypair + * we're talking about. + */ +void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { + /* We have > 256 OTS at the bottom of the Merkle tree; to specify */ + /* which one, we'd need to express it in two bytes */ + ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR2] = (unsigned char)(keypair >> 8); + ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; } -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; - out[5] = in[5]; +/* + * Copy the layer, tree and keypair fields of the address structure. This is + * used when we're doing multiple things within the same OTS keypair + */ +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); + ((unsigned char *)out)[SPX_OFFSET_KP_ADDR2] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR2]; + ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; } -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_set_chain_addr( - uint32_t addr[8], uint32_t chain) { - addr[6] = chain; +/* + * Specify which Merkle chain within the OTS we're working with + * (the chain address) + */ +void set_chain_addr(uint32_t addr[8], uint32_t chain) { + ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; } -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_set_hash_addr( - uint32_t addr[8], uint32_t hash) { - addr[7] = hash; +/* + * Specify where in the Merkle chain we are +* (the hash address) + */ +void set_hash_addr(uint32_t addr[8], uint32_t hash) { + ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; } /* These functions are used for all hash tree addresses (including FORS). */ -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_set_tree_height( - uint32_t addr[8], uint32_t tree_height) { - addr[6] = tree_height; +/* + * Specify the height of the node in the Merkle/FORS tree we are in + * (the tree height) + */ +void set_tree_height(uint32_t addr[8], uint32_t tree_height) { + ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; } -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_set_tree_index( - uint32_t addr[8], uint32_t tree_index) { - addr[7] = tree_index; +/* + * Specify the distance from the left edge of the node in the Merkle/FORS tree + * (the tree index) + */ +void set_tree_index(uint32_t addr[8], uint32_t tree_index) { + u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/address.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/address.h index 306112a395..24a84eb40c 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/address.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/address.h @@ -1,50 +1,52 @@ -#ifndef PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_ADDRESS_H -#define PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_ADDRESS_H +#ifndef SPX_ADDRESS_H +#define SPX_ADDRESS_H #include -#define PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_ADDR_TYPE_WOTS 0 -#define PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_ADDR_TYPE_WOTSPK 1 -#define PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_ADDR_TYPE_HASHTREE 2 -#define PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_ADDR_TYPE_FORSTREE 3 -#define PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_ADDR_TYPE_FORSPK 4 +#include "params.h" -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]); +/* The hash types that are passed to set_type */ +#define SPX_ADDR_TYPE_WOTS 0 +#define SPX_ADDR_TYPE_WOTSPK 1 +#define SPX_ADDR_TYPE_HASHTREE 2 +#define SPX_ADDR_TYPE_FORSTREE 3 +#define SPX_ADDR_TYPE_FORSPK 4 +#define SPX_ADDR_TYPE_WOTSPRF 5 +#define SPX_ADDR_TYPE_FORSPRF 6 -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_set_layer_addr( - uint32_t addr[8], uint32_t layer); +#define set_layer_addr SPX_NAMESPACE(set_layer_addr) +void set_layer_addr(uint32_t addr[8], uint32_t layer); -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_set_tree_addr( - uint32_t addr[8], uint64_t tree); +#define set_tree_addr SPX_NAMESPACE(set_tree_addr) +void set_tree_addr(uint32_t addr[8], uint64_t tree); -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_set_type( - uint32_t addr[8], uint32_t type); +#define set_type SPX_NAMESPACE(set_type) +void set_type(uint32_t addr[8], uint32_t type); /* Copies the layer and tree part of one address into the other */ -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]); +#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); /* These functions are used for WOTS and FORS addresses. */ -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_set_keypair_addr( - uint32_t addr[8], uint32_t keypair); +#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) +void set_keypair_addr(uint32_t addr[8], uint32_t keypair); -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_set_chain_addr( - uint32_t addr[8], uint32_t chain); +#define set_chain_addr SPX_NAMESPACE(set_chain_addr) +void set_chain_addr(uint32_t addr[8], uint32_t chain); -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_set_hash_addr( - uint32_t addr[8], uint32_t hash); +#define set_hash_addr SPX_NAMESPACE(set_hash_addr) +void set_hash_addr(uint32_t addr[8], uint32_t hash); -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]); +#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); /* These functions are used for all hash tree addresses (including FORS). */ -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_set_tree_height( - uint32_t addr[8], uint32_t tree_height); +#define set_tree_height SPX_NAMESPACE(set_tree_height) +void set_tree_height(uint32_t addr[8], uint32_t tree_height); -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_set_tree_index( - uint32_t addr[8], uint32_t tree_index); +#define set_tree_index SPX_NAMESPACE(set_tree_index) +void set_tree_index(uint32_t addr[8], uint32_t tree_index); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/api.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/api.h index 32ca77c648..f292697e93 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/api.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/api.h @@ -4,15 +4,13 @@ #include #include - - -#define PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_CRYPTO_ALGNAME "SPHINCS+" +#define PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_CRYPTO_ALGNAME "SPHINCS+-haraka-128s-simple" #define PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_CRYPTO_SECRETKEYBYTES 64 #define PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_CRYPTO_PUBLICKEYBYTES 32 -#define PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_CRYPTO_BYTES 7856 -#define PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_CRYPTO_SEEDBYTES 48 +#define PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_CRYPTO_BYTES 7856 +#define PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_CRYPTO_SEEDBYTES 48 /* * Returns the length of a secret key, in bytes @@ -39,43 +37,41 @@ size_t PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_crypto_sign_seedbytes(void); * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] * Format pk: [root || PUB_SEED] */ -int PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed); +int PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); /* * Generates a SPHINCS+ key pair. * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] * Format pk: [root || PUB_SEED] */ -int PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk); +int PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); /** * Returns an array containing a detached signature. */ -int PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk); +int PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); /** * Verifies a detached signature and message under a given public key. */ -int PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk); +int PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, + const uint8_t *pk); /** * Returns an array containing the signature followed by the message. */ -int PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk); +int PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); /** * Verifies a given signature-message pair under a given public key. */ -int PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk); - +int PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/context.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/context.h new file mode 100644 index 0000000000..f03446b9cb --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/context.h @@ -0,0 +1,22 @@ +#ifndef SPX_CONTEXT_H +#define SPX_CONTEXT_H + +#include + +#include "immintrin.h" +#include "params.h" + +typedef struct { + uint8_t pub_seed[SPX_N]; + uint8_t sk_seed[SPX_N]; + + __m128i rc[40]; +} spx_ctx; + +#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) +void initialize_hash_function(spx_ctx *ctx); + +#define free_hash_function SPX_NAMESPACE(free_hash_function) +void free_hash_function(spx_ctx *ctx); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/context_haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/context_haraka.c new file mode 100644 index 0000000000..f1cd7e3664 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/context_haraka.c @@ -0,0 +1,11 @@ +#include "context.h" +#include "haraka.h" + +void initialize_hash_function(spx_ctx *ctx) { + tweak_constants(ctx); +} + +// we don't support heap-based haraka right now +void free_hash_function(spx_ctx *ctx) { + (void)ctx; // suppress unused variable warnings +} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/fors.c b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/fors.c index 5d97baf2d4..f1b0639cfc 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/fors.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/fors.c @@ -2,8 +2,9 @@ #include #include -#include "address.h" #include "fors.h" + +#include "address.h" #include "hash.h" #include "hashx4.h" #include "thash.h" @@ -11,19 +12,24 @@ #include "utils.h" #include "utilsx4.h" +static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + prf_addr(sk, ctx, fors_leaf_addr); +} + static void fors_gen_skx4(unsigned char *sk0, unsigned char *sk1, unsigned char *sk2, - unsigned char *sk3, const unsigned char *sk_seed, - uint32_t fors_leaf_addrx4[4 * 8], - const hash_state *state_seeded) { - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_prf_addrx4(sk0, sk1, sk2, sk3, sk_seed, fors_leaf_addrx4, state_seeded); + unsigned char *sk3, const spx_ctx *ctx, + uint32_t fors_leaf_addrx4[4 * 8]) { + prf_addrx4(sk0, sk1, sk2, sk3, + ctx, fors_leaf_addrx4); } static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, - const unsigned char *pub_seed, - uint32_t fors_leaf_addr[8], const hash_state *state_seeded) { - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_thash_1(leaf, sk, pub_seed, fors_leaf_addr, state_seeded); + const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + thash(leaf, sk, 1, ctx, fors_leaf_addr); } static void fors_sk_to_leafx4(unsigned char *leaf0, @@ -34,57 +40,64 @@ static void fors_sk_to_leafx4(unsigned char *leaf0, const unsigned char *sk1, const unsigned char *sk2, const unsigned char *sk3, - const unsigned char *pub_seed, - uint32_t fors_leaf_addrx4[4 * 8], - const hash_state *state_seeded) { - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_thashx4_1(leaf0, leaf1, leaf2, leaf3, - sk0, sk1, sk2, sk3, pub_seed, fors_leaf_addrx4, state_seeded); + const spx_ctx *ctx, + uint32_t fors_leaf_addrx4[4 * 8]) { + thashx4(leaf0, leaf1, leaf2, leaf3, + sk0, sk1, sk2, sk3, + 1, ctx, fors_leaf_addrx4); } -static void fors_gen_leafx4(unsigned char *leaf0, - unsigned char *leaf1, - unsigned char *leaf2, - unsigned char *leaf3, - const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx0, - uint32_t addr_idx1, - uint32_t addr_idx2, - uint32_t addr_idx3, - const uint32_t fors_tree_addr[8], - const hash_state *state_seeded) { - uint32_t fors_leaf_addrx4[4 * 8] = {0}; +struct fors_gen_leaf_info { + uint32_t leaf_addrx[4 * 8]; +}; + +static void fors_gen_leafx4(unsigned char *leaf, + const spx_ctx *ctx, + uint32_t addr_idx, void *info) { + struct fors_gen_leaf_info *fors_info = info; + uint32_t *fors_leaf_addrx4 = fors_info->leaf_addrx; unsigned int j; - /* Only copy the parts that must be kept in fors_leaf_addrx4. */ + /* Only set the parts that the caller doesn't set */ for (j = 0; j < 4; j++) { - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_copy_keypair_addr(fors_leaf_addrx4 + j * 8, fors_tree_addr); - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_set_type(fors_leaf_addrx4 + j * 8, PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_ADDR_TYPE_FORSTREE); + set_tree_index(fors_leaf_addrx4 + j * 8, addr_idx + j); + set_type(fors_leaf_addrx4 + j * 8, SPX_ADDR_TYPE_FORSPRF); } - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_set_tree_index(fors_leaf_addrx4 + 0 * 8, addr_idx0); - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_set_tree_index(fors_leaf_addrx4 + 1 * 8, addr_idx1); - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_set_tree_index(fors_leaf_addrx4 + 2 * 8, addr_idx2); - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_set_tree_index(fors_leaf_addrx4 + 3 * 8, addr_idx3); + fors_gen_skx4(leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + leaf + 2 * SPX_N, + leaf + 3 * SPX_N, + ctx, fors_leaf_addrx4); + + for (j = 0; j < 4; j++) { + set_type(fors_leaf_addrx4 + j * 8, SPX_ADDR_TYPE_FORSTREE); + } - fors_gen_skx4(leaf0, leaf1, leaf2, leaf3, sk_seed, fors_leaf_addrx4, state_seeded); - fors_sk_to_leafx4(leaf0, leaf1, leaf2, leaf3, - leaf0, leaf1, leaf2, leaf3, pub_seed, fors_leaf_addrx4, state_seeded); + fors_sk_to_leafx4(leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + leaf + 2 * SPX_N, + leaf + 3 * SPX_N, + leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + leaf + 2 * SPX_N, + leaf + 3 * SPX_N, + ctx, fors_leaf_addrx4); } /** - * Interprets m as PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_FORS_HEIGHT-bit unsigned integers. - * Assumes m contains at least PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_FORS_TREES bits. - * Assumes indices has space for PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_FORS_TREES integers. + * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + * Assumes indices has space for SPX_FORS_TREES integers. */ static void message_to_indices(uint32_t *indices, const unsigned char *m) { unsigned int i, j; unsigned int offset = 0; - for (i = 0; i < PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_FORS_TREES; i++) { + for (i = 0; i < SPX_FORS_TREES; i++) { indices[i] = 0; - for (j = 0; j < PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_FORS_HEIGHT; j++) { - indices[i] ^= (((uint32_t)m[offset >> 3] >> (offset & 0x7)) & 0x1) << j; + for (j = 0; j < SPX_FORS_HEIGHT; j++) { + indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); offset++; } } @@ -92,68 +105,53 @@ static void message_to_indices(uint32_t *indices, const unsigned char *m) { /** * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_FORS_TREES bits. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. */ -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *state_seeded) { - /* Round up to multiple of 4 to prevent out-of-bounds for x4 parallelism */ - uint32_t indices[(PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_FORS_TREES + 3) & ~3] = {0}; - unsigned char roots[((PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_FORS_TREES + 3) & ~3) * PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N]; - /* Sign to a buffer, since we may not have a nice multiple of 4 and would - otherwise overrun the signature. */ - unsigned char sigbufx4[4 * PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N * (1 + PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_FORS_HEIGHT)]; - uint32_t fors_tree_addrx4[4 * 8] = {0}; +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + uint32_t fors_tree_addr[4 * 8] = {0}; + struct fors_gen_leaf_info fors_info = {0}; + uint32_t *fors_leaf_addr = fors_info.leaf_addrx; uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset[4] = {0}; - unsigned int i, j; + uint32_t idx_offset; + unsigned int i; - for (j = 0; j < 4; j++) { - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_copy_keypair_addr(fors_tree_addrx4 + j * 8, fors_addr); - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_set_type(fors_tree_addrx4 + j * 8, PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_ADDR_TYPE_FORSTREE); + for (i = 0; i < 4; i++) { + copy_keypair_addr(fors_tree_addr + 8 * i, fors_addr); + set_type(fors_tree_addr + 8 * i, SPX_ADDR_TYPE_FORSTREE); + copy_keypair_addr(fors_leaf_addr + 8 * i, fors_addr); } - - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_copy_keypair_addr(fors_pk_addr, fors_addr); - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_set_type(fors_pk_addr, PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_ADDR_TYPE_FORSPK); + copy_keypair_addr(fors_pk_addr, fors_addr); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); message_to_indices(indices, m); - for (i = 0; i < ((PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_FORS_TREES + 3) & ~0x3); i += 4) { - for (j = 0; j < 4; j++) { - if (i + j < PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_FORS_TREES) { - idx_offset[j] = (i + j) * (1 << PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_FORS_HEIGHT); + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_set_tree_height(fors_tree_addrx4 + j * 8, 0); - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_set_tree_index(fors_tree_addrx4 + j * 8, - indices[i + j] + idx_offset[j]); - } - } + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); - /* Include the secret key part that produces the selected leaf nodes. */ - fors_gen_skx4(sigbufx4 + 0 * PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N, - sigbufx4 + 1 * PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N, - sigbufx4 + 2 * PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N, - sigbufx4 + 3 * PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N, - sk_seed, fors_tree_addrx4, state_seeded); - - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_treehashx4_FORS_HEIGHT(roots + i * PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N, sigbufx4 + 4 * PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N, sk_seed, pub_seed, - &indices[i], idx_offset, fors_gen_leafx4, fors_tree_addrx4, - state_seeded); - - for (j = 0; j < 4; j++) { - if (i + j < PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_FORS_TREES) { - memcpy(sig, sigbufx4 + j * PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N, PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N); - memcpy(sig + PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N, - sigbufx4 + 4 * PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N + j * PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N * PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_FORS_HEIGHT, - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N * PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_FORS_HEIGHT); - sig += PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N * (1 + PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_FORS_HEIGHT); - } - } + /* Include the secret key part that produces the selected leaf node. */ + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); + fors_gen_sk(sig, ctx, fors_tree_addr); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + sig += SPX_N; + + /* Compute the authentication path for this leaf node. */ + treehashx4(roots + i * SPX_N, sig, ctx, + indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx4, + fors_tree_addr, &fors_info); + + sig += SPX_N * SPX_FORS_HEIGHT; } /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_thash_FORS_TREES(pk, roots, pub_seed, fors_pk_addr, state_seeded); + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); } /** @@ -161,46 +159,44 @@ void PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_fors_sign(unsigned char *sig, unsigne * This can be used for verification by comparing to a known public key, or to * subsequently verify a signature on the derived public key. The latter is the * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_FORS_TREES bits. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. */ -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, - const uint32_t fors_addr[8], - const hash_state *state_seeded) { - uint32_t indices[PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_FORS_TREES]; - unsigned char roots[PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_FORS_TREES * PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N]; - unsigned char leaf[PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N]; +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + unsigned char leaf[SPX_N]; uint32_t fors_tree_addr[8] = {0}; uint32_t fors_pk_addr[8] = {0}; uint32_t idx_offset; unsigned int i; - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_copy_keypair_addr(fors_tree_addr, fors_addr); - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_copy_keypair_addr(fors_pk_addr, fors_addr); + copy_keypair_addr(fors_tree_addr, fors_addr); + copy_keypair_addr(fors_pk_addr, fors_addr); - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_set_type(fors_tree_addr, PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_set_type(fors_pk_addr, PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_ADDR_TYPE_FORSPK); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); message_to_indices(indices, m); - for (i = 0; i < PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_FORS_TREES; i++) { - idx_offset = i * (1 << PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_FORS_HEIGHT); + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_set_tree_height(fors_tree_addr, 0); - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_set_tree_index(fors_tree_addr, indices[i] + idx_offset); + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); /* Derive the leaf from the included secret key part. */ - fors_sk_to_leaf(leaf, sig, pub_seed, fors_tree_addr, state_seeded); - sig += PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N; + fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); + sig += SPX_N; /* Derive the corresponding root node of this tree. */ - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_compute_root(roots + i * PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N, leaf, indices[i], idx_offset, - sig, PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_FORS_HEIGHT, pub_seed, fors_tree_addr, - state_seeded); - sig += PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N * PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_FORS_HEIGHT; + compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, + sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); + sig += SPX_N * SPX_FORS_HEIGHT; } /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_thash_FORS_TREES(pk, roots, pub_seed, fors_pk_addr, state_seeded); + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/fors.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/fors.h index 79ff829d32..509140a178 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/fors.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/fors.h @@ -1,32 +1,32 @@ -#ifndef PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_FORS_H -#define PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_FORS_H +#ifndef SPX_FORS_H +#define SPX_FORS_H #include -#include "hash_state.h" +#include "context.h" #include "params.h" /** * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_FORS_TREES bits. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. */ -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_fors_sign( - unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *hash_state_seeded); +#define fors_sign SPX_NAMESPACE(fors_sign) +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); /** * Derives the FORS public key from a signature. * This can be used for verification by comparing to a known public key, or to * subsequently verify a signature on the derived public key. The latter is the * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_FORS_TREES bits. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. */ -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_fors_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, const uint32_t fors_addr[8], - const hash_state *hash_state_seeded); +#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/haraka.c index 1cd9801e86..b414b691d7 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/haraka.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/haraka.c @@ -8,10 +8,12 @@ Plain C implementation of the Haraka256 and Haraka512 permutations. #include #include "haraka.h" +#include "harakax4.h" +#include "utils.h" #define HARAKAS_RATE 32 -#define u64 uint64_t +#define u64 unsigned long #define u128 __m128i #define LOAD(src) _mm_loadu_si128((u128 *)(src)) @@ -20,7 +22,7 @@ Plain C implementation of the Haraka256 and Haraka512 permutations. #define XOR128(a, b) _mm_xor_si128(a, b) #define AES2(s0, s1, rci) \ - (s0) = _mm_aesenc_si128(s0, *(rci)); \ + s0 = _mm_aesenc_si128(s0, *(rci)); \ (s1) = _mm_aesenc_si128(s1, *((rci) + 1)); \ (s0) = _mm_aesenc_si128(s0, *((rci) + 2)); \ (s1) = _mm_aesenc_si128(s1, *((rci) + 3)); @@ -32,7 +34,7 @@ Plain C implementation of the Haraka256 and Haraka512 permutations. AES2((s3)[0], (s3)[1], rci); #define AES4(s0, s1, s2, s3, rci) \ - (s0) = _mm_aesenc_si128(s0, *(rci)); \ + s0 = _mm_aesenc_si128(s0, *(rci)); \ (s1) = _mm_aesenc_si128(s1, *((rci) + 1)); \ (s2) = _mm_aesenc_si128(s2, *((rci) + 2)); \ (s3) = _mm_aesenc_si128(s3, *((rci) + 3)); \ @@ -68,17 +70,17 @@ Plain C implementation of the Haraka256 and Haraka512 permutations. _mm_storeu_si128((u128 *)((out) + 16), \ _mm_castpd_si128(_mm_shuffle_pd(_mm_castsi128_pd(s2), _mm_castsi128_pd(s3), 0))); -static void load_haraka_constants(u128 rc[40]) { - rc[ 0] = _mm_set_epi32((int)0x0684704c, (int)0xe620c00a, (int)0xb2c5fef0, (int)0x75817b9d); - rc[ 1] = _mm_set_epi32((int)0x8b66b4e1, (int)0x88f3a06b, (int)0x640f6ba4, (int)0x2f08f717); - rc[ 2] = _mm_set_epi32((int)0x3402de2d, (int)0x53f28498, (int)0xcf029d60, (int)0x9f029114); - rc[ 3] = _mm_set_epi32((int)0x0ed6eae6, (int)0x2e7b4f08, (int)0xbbf3bcaf, (int)0xfd5b4f79); - rc[ 4] = _mm_set_epi32((int)0xcbcfb0cb, (int)0x4872448b, (int)0x79eecd1c, (int)0xbe397044); - rc[ 5] = _mm_set_epi32((int)0x7eeacdee, (int)0x6e9032b7, (int)0x8d5335ed, (int)0x2b8a057b); - rc[ 6] = _mm_set_epi32((int)0x67c28f43, (int)0x5e2e7cd0, (int)0xe2412761, (int)0xda4fef1b); - rc[ 7] = _mm_set_epi32((int)0x2924d9b0, (int)0xafcacc07, (int)0x675ffde2, (int)0x1fc70b3b); - rc[ 8] = _mm_set_epi32((int)0xab4d63f1, (int)0xe6867fe9, (int)0xecdb8fca, (int)0xb9d465ee); - rc[ 9] = _mm_set_epi32((int)0x1c30bf84, (int)0xd4b7cd64, (int)0x5b2a404f, (int)0xad037e33); +static void load_haraka_constants(u128 *rc) { + rc[0] = _mm_set_epi32((int)0x0684704c, (int)0xe620c00a, (int)0xb2c5fef0, (int)0x75817b9d); + rc[1] = _mm_set_epi32((int)0x8b66b4e1, (int)0x88f3a06b, (int)0x640f6ba4, (int)0x2f08f717); + rc[2] = _mm_set_epi32((int)0x3402de2d, (int)0x53f28498, (int)0xcf029d60, (int)0x9f029114); + rc[3] = _mm_set_epi32((int)0x0ed6eae6, (int)0x2e7b4f08, (int)0xbbf3bcaf, (int)0xfd5b4f79); + rc[4] = _mm_set_epi32((int)0xcbcfb0cb, (int)0x4872448b, (int)0x79eecd1c, (int)0xbe397044); + rc[5] = _mm_set_epi32((int)0x7eeacdee, (int)0x6e9032b7, (int)0x8d5335ed, (int)0x2b8a057b); + rc[6] = _mm_set_epi32((int)0x67c28f43, (int)0x5e2e7cd0, (int)0xe2412761, (int)0xda4fef1b); + rc[7] = _mm_set_epi32((int)0x2924d9b0, (int)0xafcacc07, (int)0x675ffde2, (int)0x1fc70b3b); + rc[8] = _mm_set_epi32((int)0xab4d63f1, (int)0xe6867fe9, (int)0xecdb8fca, (int)0xb9d465ee); + rc[9] = _mm_set_epi32((int)0x1c30bf84, (int)0xd4b7cd64, (int)0x5b2a404f, (int)0xad037e33); rc[10] = _mm_set_epi32((int)0xb2cc0bb9, (int)0x941723bf, (int)0x69028b2e, (int)0x8df69800); rc[11] = _mm_set_epi32((int)0xfa0478a6, (int)0xde6f5572, (int)0x4aaa9ec8, (int)0x5c9d2d8a); rc[12] = _mm_set_epi32((int)0xdfb49f2b, (int)0x6b772a12, (int)0x0efa4f2e, (int)0x29129fd4); @@ -111,77 +113,65 @@ static void load_haraka_constants(u128 rc[40]) { rc[39] = _mm_set_epi32((int)0x756acc03, (int)0x02288288, (int)0x4ad6bdfd, (int)0xe9c59da1); } -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_tweak_constants( - harakactx *state, - const unsigned char *pk_seed, const unsigned char *sk_seed, - unsigned long long seed_length) { +void tweak_constants(spx_ctx *ctx) { int i; unsigned char buf[40 * 16]; /* Use the standard constants to generate tweaked ones. */ - load_haraka_constants(state->rc); - - /* Constants for sk.seed */ - if (sk_seed != NULL) { - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_haraka_S(buf, 40 * 16, sk_seed, seed_length, state); - /* Tweak constants with the pub_seed */ - for (i = 0; i < 40; i++) { - state->rc_sseed[i] = LOAD(buf + i * 16); - } - } + load_haraka_constants(ctx->rc); /* Constants for pk.seed */ - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_haraka_S(buf, 40 * 16, pk_seed, seed_length, state); + haraka_S(buf, 40 * 16, ctx->pub_seed, SPX_N, ctx); /* Tweak constants with the pub_seed */ for (i = 0; i < 40; i++) { - state->rc[i] = LOAD(buf + i * 16); + ctx->rc[i] = LOAD(buf + i * 16); } } -static void haraka_S_absorb(unsigned char *s, +static void haraka_S_absorb(unsigned char *s, unsigned int r, const unsigned char *m, unsigned long long mlen, - unsigned char p, - const harakactx *state) { + unsigned char p, const spx_ctx *ctx) { unsigned long long i; - unsigned char t[HARAKAS_RATE]; + PQCLEAN_VLA(unsigned char, t, r); - while (mlen >= HARAKAS_RATE) { + while (mlen >= r) { // XOR block to state STORE(s, XOR128(LOAD(s), LOAD(m))); STORE(s + 16, XOR128(LOAD(s + 16), LOAD(m + 16))); - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_haraka512_perm(s, s, state); - mlen -= HARAKAS_RATE; - m += HARAKAS_RATE; + haraka512_perm(s, s, ctx); + mlen -= r; + m += r; } - for (i = 0; i < HARAKAS_RATE; ++i) { + for (i = 0; i < r; ++i) { t[i] = 0; } for (i = 0; i < mlen; ++i) { t[i] = m[i]; } t[i] = p; - t[HARAKAS_RATE - 1] |= 128; + t[r - 1] |= 128; STORE(s, XOR128(LOAD(s), LOAD(t))); STORE(s + 16, XOR128(LOAD(s + 16), LOAD(t + 16))); } static void haraka_S_absorb4x(unsigned char *s, + unsigned int r, const unsigned char *m0, const unsigned char *m1, const unsigned char *m2, const unsigned char *m3, unsigned long long int mlen, unsigned char p, - const harakactx *state) { + const spx_ctx *ctx) { unsigned long long i; - unsigned char t0[HARAKAS_RATE]; - unsigned char t1[HARAKAS_RATE]; - unsigned char t2[HARAKAS_RATE]; - unsigned char t3[HARAKAS_RATE]; + PQCLEAN_VLA(unsigned char, t0, r); + PQCLEAN_VLA(unsigned char, t1, r); + PQCLEAN_VLA(unsigned char, t2, r); + PQCLEAN_VLA(unsigned char, t3, r); - while (mlen >= HARAKAS_RATE) { + while (mlen >= r) { // XOR block to state STORE(s, XOR128(LOAD(s), LOAD(m0))); STORE(s + 16, XOR128(LOAD(s + 16), LOAD(m0 + 16))); @@ -192,15 +182,15 @@ static void haraka_S_absorb4x(unsigned char *s, STORE(s + 192, XOR128(LOAD(s + 192), LOAD(m3))); STORE(s + 208, XOR128(LOAD(s + 208), LOAD(m3 + 16))); - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_haraka512_perm_x4(s, s, state); - mlen -= HARAKAS_RATE; - m0 += HARAKAS_RATE; - m1 += HARAKAS_RATE; - m2 += HARAKAS_RATE; - m3 += HARAKAS_RATE; + haraka512_perm_x4(s, s, ctx); + mlen -= r; + m0 += r; + m1 += r; + m2 += r; + m3 += r; } - for (i = 0; i < HARAKAS_RATE; ++i) { + for (i = 0; i < r; ++i) { t0[i] = 0; t1[i] = 0; t2[i] = 0; @@ -218,10 +208,10 @@ static void haraka_S_absorb4x(unsigned char *s, t2[i] = p; t3[i] = p; - t0[HARAKAS_RATE - 1] |= 128; - t1[HARAKAS_RATE - 1] |= 128; - t2[HARAKAS_RATE - 1] |= 128; - t3[HARAKAS_RATE - 1] |= 128; + t0[r - 1] |= 128; + t1[r - 1] |= 128; + t2[r - 1] |= 128; + t3[r - 1] |= 128; STORE(s, XOR128(LOAD(s), LOAD(t0))); STORE(s + 16, XOR128(LOAD(s + 16), LOAD(t0 + 16))); @@ -234,9 +224,10 @@ static void haraka_S_absorb4x(unsigned char *s, } static void haraka_S_squeezeblocks(unsigned char *h, unsigned long long nblocks, - unsigned char *s, unsigned int r, const harakactx *state) { + unsigned char *s, unsigned int r, + const spx_ctx *ctx) { while (nblocks > 0) { - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_haraka512_perm(s, s, state); + haraka512_perm(s, s, ctx); STORE(h, LOAD(s)); STORE(h + 16, LOAD(s + 16)); h += r; @@ -251,9 +242,9 @@ static void haraka_S_squeezeblocks4x(unsigned char *h0, unsigned long long nblocks, unsigned char *s, unsigned int r, - const harakactx *state) { + const spx_ctx *ctx) { while (nblocks > 0) { - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_haraka512_perm_x4(s, s, state); + haraka512_perm_x4(s, s, ctx); STORE(h0, LOAD(s)); STORE(h0 + 16, LOAD(s + 16)); STORE(h1, LOAD(s + 64)); @@ -270,7 +261,7 @@ static void haraka_S_squeezeblocks4x(unsigned char *h0, } } -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_haraka_S_inc_init(uint8_t *s_inc) { +void haraka_S_inc_init(uint8_t *s_inc) { size_t i; for (i = 0; i < 64; i++) { @@ -279,7 +270,8 @@ void PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_haraka_S_inc_init(uint8_t *s_inc) { s_inc[64] = 0; } -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, const harakactx *state) { +void haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, + const spx_ctx *ctx) { size_t i; /* Recall that s_inc[64] is the non-absorbed bytes xored into the state */ @@ -293,16 +285,16 @@ void PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_haraka_S_inc_absorb(uint8_t *s_inc, c m += HARAKAS_RATE - s_inc[64]; s_inc[64] = 0; - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_haraka512_perm(s_inc, s_inc, state); + haraka512_perm(s_inc, s_inc, ctx); } for (i = 0; i < mlen; i++) { s_inc[s_inc[64] + i] ^= m[i]; } - s_inc[64] = (uint8_t)(s_inc[64] + mlen); + s_inc[64] += (uint8_t)mlen; } -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_haraka_S_inc_finalize(uint8_t *s_inc) { +void haraka_S_inc_finalize(uint8_t *s_inc) { /* After haraka_S_inc_absorb, we are guaranteed that s_inc[64] < HARAKAS_RATE, so we can always use one more byte for p in the current state. */ s_inc[s_inc[64]] ^= 0x1F; @@ -310,22 +302,23 @@ void PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_haraka_S_inc_finalize(uint8_t *s_inc) s_inc[64] = 0; } -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, const harakactx *state) { +void haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, + const spx_ctx *ctx) { size_t i; /* First consume any bytes we still have sitting around */ for (i = 0; i < outlen && i < s_inc[64]; i++) { /* There are s_inc[64] bytes left, so r - s_inc[64] is the first available byte. We consume from there, i.e., up to r. */ - out[i] = (uint8_t)s_inc[(HARAKAS_RATE - s_inc[64] + (uint8_t)i)]; + out[i] = (uint8_t)s_inc[(HARAKAS_RATE - s_inc[64] + i)]; } out += i; outlen -= i; - s_inc[64] = (uint8_t)(s_inc[64] - i); + s_inc[64] -= (uint8_t)i; /* Then squeeze the remaining necessary blocks */ while (outlen > 0) { - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_haraka512_perm(s_inc, s_inc, state); + haraka512_perm(s_inc, s_inc, ctx); for (i = 0; i < outlen && i < HARAKAS_RATE; i++) { out[i] = s_inc[i]; @@ -336,8 +329,9 @@ void PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_haraka_S_inc_squeeze(uint8_t *out, si } } -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_haraka_S(unsigned char *out, unsigned long long outlen, - const unsigned char *in, unsigned long long inlen, const harakactx *state) { +void haraka_S(unsigned char *out, unsigned long long outlen, + const unsigned char *in, unsigned long long inlen, + const spx_ctx *ctx) { unsigned long long i; unsigned char s[64]; unsigned char d[32]; @@ -345,30 +339,30 @@ void PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_haraka_S(unsigned char *out, unsigned for (i = 0; i < 64; i++) { s[i] = 0; } - haraka_S_absorb(s, in, inlen, 0x1F, state); + haraka_S_absorb(s, HARAKAS_RATE, in, inlen, 0x1F, ctx); - haraka_S_squeezeblocks(out, outlen / HARAKAS_RATE, s, HARAKAS_RATE, state); + haraka_S_squeezeblocks(out, outlen / HARAKAS_RATE, s, HARAKAS_RATE, ctx); out += (outlen / HARAKAS_RATE) * HARAKAS_RATE; if (outlen % HARAKAS_RATE) { - haraka_S_squeezeblocks(d, 1, s, HARAKAS_RATE, state); + haraka_S_squeezeblocks(d, 1, s, HARAKAS_RATE, ctx); for (i = 0; i < outlen % HARAKAS_RATE; i++) { out[i] = d[i]; } } } -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_haraka_Sx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned long long outlen, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - unsigned long long inlen, - const harakactx *state) { +void haraka_Sx4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned long long outlen, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + unsigned long long inlen, + const spx_ctx *ctx) { unsigned long long i; unsigned char s[64 * 4]; unsigned char d0[32]; @@ -379,16 +373,17 @@ void PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_haraka_Sx4(unsigned char *out0, for (i = 0; i < 64 * 4; i++) { s[i] = 0; } - haraka_S_absorb4x(s, in0, in1, in2, in3, inlen, 0x1F, state); + haraka_S_absorb4x(s, HARAKAS_RATE, in0, in1, in2, in3, inlen, 0x1F, ctx); - haraka_S_squeezeblocks4x(out0, out1, out2, out3, outlen / HARAKAS_RATE, s, HARAKAS_RATE, state); + haraka_S_squeezeblocks4x(out0, out1, out2, out3, outlen / HARAKAS_RATE, s, + HARAKAS_RATE, ctx); out0 += (outlen / HARAKAS_RATE) * HARAKAS_RATE; out1 += (outlen / HARAKAS_RATE) * HARAKAS_RATE; out2 += (outlen / HARAKAS_RATE) * HARAKAS_RATE; out3 += (outlen / HARAKAS_RATE) * HARAKAS_RATE; if (outlen % HARAKAS_RATE) { - haraka_S_squeezeblocks4x(d0, d1, d2, d3, 1, s, HARAKAS_RATE, state); + haraka_S_squeezeblocks4x(d0, d1, d2, d3, 1, s, HARAKAS_RATE, ctx); for (i = 0; i < outlen % HARAKAS_RATE; i++) { out0[i] = d0[i]; out1[i] = d1[i]; @@ -398,7 +393,8 @@ void PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_haraka_Sx4(unsigned char *out0, } } -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_haraka512_perm(unsigned char *out, const unsigned char *in, const harakactx *state) { +void haraka512_perm(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx) { u128 s[4], tmp; s[0] = LOAD(in); @@ -406,19 +402,19 @@ void PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_haraka512_perm(unsigned char *out, co s[2] = LOAD(in + 32); s[3] = LOAD(in + 48); - AES4(s[0], s[1], s[2], s[3], state->rc); + AES4(s[0], s[1], s[2], s[3], ctx->rc); MIX4(s[0], s[1], s[2], s[3]); - AES4(s[0], s[1], s[2], s[3], state->rc + 8); + AES4(s[0], s[1], s[2], s[3], ctx->rc + 8); MIX4(s[0], s[1], s[2], s[3]); - AES4(s[0], s[1], s[2], s[3], state->rc + 16); + AES4(s[0], s[1], s[2], s[3], ctx->rc + 16); MIX4(s[0], s[1], s[2], s[3]); - AES4(s[0], s[1], s[2], s[3], state->rc + 24); + AES4(s[0], s[1], s[2], s[3], ctx->rc + 24); MIX4(s[0], s[1], s[2], s[3]); - AES4(s[0], s[1], s[2], s[3], state->rc + 32); + AES4(s[0], s[1], s[2], s[3], ctx->rc + 32); MIX4(s[0], s[1], s[2], s[3]); STORE(out, s[0]); @@ -427,7 +423,8 @@ void PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_haraka512_perm(unsigned char *out, co STORE(out + 48, s[3]); } -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_haraka512_perm_x4(unsigned char *out, const unsigned char *in, const harakactx *state) { +void haraka512_perm_x4(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx) { u128 s[4][4], tmp; s[0][0] = LOAD(in); @@ -447,31 +444,31 @@ void PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_haraka512_perm_x4(unsigned char *out, s[3][2] = LOAD(in + 224); s[3][3] = LOAD(in + 240); - AES4_4x(s[0], s[1], s[2], s[3], state->rc); + AES4_4x(s[0], s[1], s[2], s[3], ctx->rc); MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - AES4_4x(s[0], s[1], s[2], s[3], state->rc + 8); + AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 8); MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - AES4_4x(s[0], s[1], s[2], s[3], state->rc + 16); + AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 16); MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - AES4_4x(s[0], s[1], s[2], s[3], state->rc + 24); + AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 24); MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - AES4_4x(s[0], s[1], s[2], s[3], state->rc + 32); + AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 32); MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); @@ -495,7 +492,8 @@ void PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_haraka512_perm_x4(unsigned char *out, STORE(out + 240, s[3][3]); } -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_haraka512(unsigned char *out, const unsigned char *in, const harakactx *state) { +void haraka512(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx) { u128 s[4], tmp; s[0] = LOAD(in); @@ -503,19 +501,19 @@ void PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_haraka512(unsigned char *out, const u s[2] = LOAD(in + 32); s[3] = LOAD(in + 48); - AES4(s[0], s[1], s[2], s[3], state->rc); + AES4(s[0], s[1], s[2], s[3], ctx->rc); MIX4(s[0], s[1], s[2], s[3]); - AES4(s[0], s[1], s[2], s[3], state->rc + 8); + AES4(s[0], s[1], s[2], s[3], ctx->rc + 8); MIX4(s[0], s[1], s[2], s[3]); - AES4(s[0], s[1], s[2], s[3], state->rc + 16); + AES4(s[0], s[1], s[2], s[3], ctx->rc + 16); MIX4(s[0], s[1], s[2], s[3]); - AES4(s[0], s[1], s[2], s[3], state->rc + 24); + AES4(s[0], s[1], s[2], s[3], ctx->rc + 24); MIX4(s[0], s[1], s[2], s[3]); - AES4(s[0], s[1], s[2], s[3], state->rc + 32); + AES4(s[0], s[1], s[2], s[3], ctx->rc + 32); MIX4(s[0], s[1], s[2], s[3]); s[0] = XOR128(s[0], LOAD(in)); @@ -527,7 +525,8 @@ void PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_haraka512(unsigned char *out, const u TRUNCSTORE(out, s[0], s[1], s[2], s[3]); } -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_haraka512x4(unsigned char *out, const unsigned char *in, const harakactx *state) { +void haraka512x4(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx) { u128 s[4][4], tmp; s[0][0] = LOAD(in); @@ -547,31 +546,31 @@ void PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_haraka512x4(unsigned char *out, const s[3][2] = LOAD(in + 224); s[3][3] = LOAD(in + 240); - AES4_4x(s[0], s[1], s[2], s[3], state->rc); + AES4_4x(s[0], s[1], s[2], s[3], ctx->rc); MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - AES4_4x(s[0], s[1], s[2], s[3], state->rc + 8); + AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 8); MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - AES4_4x(s[0], s[1], s[2], s[3], state->rc + 16); + AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 16); MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - AES4_4x(s[0], s[1], s[2], s[3], state->rc + 24); + AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 24); MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - AES4_4x(s[0], s[1], s[2], s[3], state->rc + 32); + AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 32); MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); @@ -600,25 +599,26 @@ void PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_haraka512x4(unsigned char *out, const TRUNCSTORE((out + 96), s[3][0], s[3][1], s[3][2], s[3][3]); } -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_haraka256(unsigned char *out, const unsigned char *in, const harakactx *state) { +void haraka256(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx) { u128 s[2], tmp; s[0] = LOAD(in); s[1] = LOAD(in + 16); - AES2(s[0], s[1], state->rc); + AES2(s[0], s[1], ctx->rc); MIX2(s[0], s[1]); - AES2(s[0], s[1], state->rc + 4); + AES2(s[0], s[1], ctx->rc + 4); MIX2(s[0], s[1]); - AES2(s[0], s[1], state->rc + 8); + AES2(s[0], s[1], ctx->rc + 8); MIX2(s[0], s[1]); - AES2(s[0], s[1], state->rc + 12); + AES2(s[0], s[1], ctx->rc + 12); MIX2(s[0], s[1]); - AES2(s[0], s[1], state->rc + 16); + AES2(s[0], s[1], ctx->rc + 16); MIX2(s[0], s[1]); s[0] = XOR128(s[0], LOAD(in)); @@ -628,7 +628,8 @@ void PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_haraka256(unsigned char *out, const u STORE(out + 16, s[1]); } -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_haraka256x4(unsigned char *out, const unsigned char *in, const harakactx *state) { +void haraka256x4(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx) { u128 s[4][2], tmp; s[0][0] = LOAD(in); @@ -641,7 +642,7 @@ void PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_haraka256x4(unsigned char *out, const s[3][1] = LOAD(in + 112); // Round 1 - AES2_4x(s[0], s[1], s[2], s[3], state->rc); + AES2_4x(s[0], s[1], s[2], s[3], ctx->rc); MIX2(s[0][0], s[0][1]); MIX2(s[1][0], s[1][1]); @@ -649,7 +650,7 @@ void PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_haraka256x4(unsigned char *out, const MIX2(s[3][0], s[3][1]); // Round 2 - AES2_4x(s[0], s[1], s[2], s[3], state->rc + 4); + AES2_4x(s[0], s[1], s[2], s[3], ctx->rc + 4); MIX2(s[0][0], s[0][1]); MIX2(s[1][0], s[1][1]); @@ -657,7 +658,7 @@ void PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_haraka256x4(unsigned char *out, const MIX2(s[3][0], s[3][1]); // Round 3 - AES2_4x(s[0], s[1], s[2], s[3], state->rc + 8); + AES2_4x(s[0], s[1], s[2], s[3], ctx->rc + 8); MIX2(s[0][0], s[0][1]); MIX2(s[1][0], s[1][1]); @@ -665,7 +666,7 @@ void PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_haraka256x4(unsigned char *out, const MIX2(s[3][0], s[3][1]); // Round 4 - AES2_4x(s[0], s[1], s[2], s[3], state->rc + 12); + AES2_4x(s[0], s[1], s[2], s[3], ctx->rc + 12); MIX2(s[0][0], s[0][1]); MIX2(s[1][0], s[1][1]); @@ -673,7 +674,7 @@ void PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_haraka256x4(unsigned char *out, const MIX2(s[3][0], s[3][1]); // Round 5 - AES2_4x(s[0], s[1], s[2], s[3], state->rc + 16); + AES2_4x(s[0], s[1], s[2], s[3], ctx->rc + 16); MIX2(s[0][0], s[0][1]); MIX2(s[1][0], s[1][1]); @@ -699,103 +700,3 @@ void PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_haraka256x4(unsigned char *out, const STORE(out + 96, s[3][0]); STORE(out + 112, s[3][1]); } - -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_haraka256_sk(unsigned char *out, const unsigned char *in, const harakactx *state) { - u128 s[2], tmp; - - s[0] = LOAD(in); - s[1] = LOAD(in + 16); - - AES2(s[0], s[1], state->rc_sseed); - MIX2(s[0], s[1]); - - AES2(s[0], s[1], state->rc_sseed + 4); - MIX2(s[0], s[1]); - - AES2(s[0], s[1], state->rc_sseed + 8); - MIX2(s[0], s[1]); - - AES2(s[0], s[1], state->rc_sseed + 12); - MIX2(s[0], s[1]); - - AES2(s[0], s[1], state->rc_sseed + 16); - MIX2(s[0], s[1]); - - s[0] = XOR128(s[0], LOAD(in)); - s[1] = XOR128(s[1], LOAD(in + 16)); - - STORE(out, s[0]); - STORE(out + 16, s[1]); -} - -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_haraka256_skx4(unsigned char *out, const unsigned char *in, const harakactx *state) { - u128 s[4][2], tmp; - - s[0][0] = LOAD(in); - s[0][1] = LOAD(in + 16); - s[1][0] = LOAD(in + 32); - s[1][1] = LOAD(in + 48); - s[2][0] = LOAD(in + 64); - s[2][1] = LOAD(in + 80); - s[3][0] = LOAD(in + 96); - s[3][1] = LOAD(in + 112); - - // Round 1 - AES2_4x(s[0], s[1], s[2], s[3], state->rc_sseed); - - MIX2(s[0][0], s[0][1]); - MIX2(s[1][0], s[1][1]); - MIX2(s[2][0], s[2][1]); - MIX2(s[3][0], s[3][1]); - - // Round 2 - AES2_4x(s[0], s[1], s[2], s[3], state->rc_sseed + 4); - - MIX2(s[0][0], s[0][1]); - MIX2(s[1][0], s[1][1]); - MIX2(s[2][0], s[2][1]); - MIX2(s[3][0], s[3][1]); - - // Round 3 - AES2_4x(s[0], s[1], s[2], s[3], state->rc_sseed + 8); - - MIX2(s[0][0], s[0][1]); - MIX2(s[1][0], s[1][1]); - MIX2(s[2][0], s[2][1]); - MIX2(s[3][0], s[3][1]); - - // Round 4 - AES2_4x(s[0], s[1], s[2], s[3], state->rc_sseed + 12); - - MIX2(s[0][0], s[0][1]); - MIX2(s[1][0], s[1][1]); - MIX2(s[2][0], s[2][1]); - MIX2(s[3][0], s[3][1]); - - // Round 5 - AES2_4x(s[0], s[1], s[2], s[3], state->rc_sseed + 16); - - MIX2(s[0][0], s[0][1]); - MIX2(s[1][0], s[1][1]); - MIX2(s[2][0], s[2][1]); - MIX2(s[3][0], s[3][1]); - - // Feed Forward - s[0][0] = XOR128(s[0][0], LOAD(in)); - s[0][1] = XOR128(s[0][1], LOAD(in + 16)); - s[1][0] = XOR128(s[1][0], LOAD(in + 32)); - s[1][1] = XOR128(s[1][1], LOAD(in + 48)); - s[2][0] = XOR128(s[2][0], LOAD(in + 64)); - s[2][1] = XOR128(s[2][1], LOAD(in + 80)); - s[3][0] = XOR128(s[3][0], LOAD(in + 96)); - s[3][1] = XOR128(s[3][1], LOAD(in + 112)); - - STORE(out, s[0][0]); - STORE(out + 16, s[0][1]); - STORE(out + 32, s[1][0]); - STORE(out + 48, s[1][1]); - STORE(out + 64, s[2][0]); - STORE(out + 80, s[2][1]); - STORE(out + 96, s[3][0]); - STORE(out + 112, s[3][1]); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/haraka.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/haraka.h index 5d991745c6..737cb6065f 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/haraka.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/haraka.h @@ -1,57 +1,42 @@ -#ifndef PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_HARAKA_H -#define PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_HARAKA_H +#ifndef SPX_HARAKA_H +#define SPX_HARAKA_H -#include -#include -#include - -typedef struct { - __m128i rc[40]; - __m128i rc_sseed[40]; -} harakactx; +#include "context.h" +#include "params.h" /* Tweak constants with seed */ -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_tweak_constants( - harakactx *state, - const unsigned char *pk_seed, const unsigned char *sk_seed, - unsigned long long seed_length); +#define tweak_constants SPX_NAMESPACE(tweak_constants) +void tweak_constants(spx_ctx *ctx); /* Haraka Sponge */ -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_haraka_S_inc_init(uint8_t *s_inc); -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, const harakactx *state); -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_haraka_S_inc_finalize(uint8_t *s_inc); -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, const harakactx *state); -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_haraka_S( - unsigned char *out, unsigned long long outlen, - const unsigned char *in, unsigned long long inlen, const harakactx *state); -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_haraka_Sx4( - unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned long long outlen, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - unsigned long long inlen, - const harakactx *state); - +#define haraka_S_inc_init SPX_NAMESPACE(haraka_S_inc_init) +void haraka_S_inc_init(uint8_t *s_inc); +#define haraka_S_inc_absorb SPX_NAMESPACE(haraka_S_inc_absorb) +void haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, + const spx_ctx *ctx); +#define haraka_S_inc_finalize SPX_NAMESPACE(haraka_S_inc_finalize) +void haraka_S_inc_finalize(uint8_t *s_inc); +#define haraka_S_inc_squeeze SPX_NAMESPACE(haraka_S_inc_squeeze) +void haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, + const spx_ctx *ctx); +#define haraka_S SPX_NAMESPACE(haraka_S) +void haraka_S(unsigned char *out, unsigned long long outlen, + const unsigned char *in, unsigned long long inlen, + const spx_ctx *ctx); /* Applies the 512-bit Haraka permutation to in. */ -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_haraka512_perm(unsigned char *out, const unsigned char *in, const harakactx *state); -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_haraka512_perm_x4(unsigned char *out, const unsigned char *in, const harakactx *state); +#define haraka512_perm SPX_NAMESPACE(haraka512_perm) +void haraka512_perm(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx); /* Implementation of Haraka-512 */ -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_haraka512(unsigned char *out, const unsigned char *in, const harakactx *state); -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_haraka512x4(unsigned char *out, const unsigned char *in, const harakactx *state); +#define haraka512 SPX_NAMESPACE(haraka512) +void haraka512(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx); /* Implementation of Haraka-256 */ -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_haraka256(unsigned char *out, const unsigned char *in, const harakactx *state); -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_haraka256x4(unsigned char *out, const unsigned char *in, const harakactx *state); - -/* Implementation of Haraka-256 using sk.seed constants */ -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_haraka256_sk(unsigned char *out, const unsigned char *in, const harakactx *state); -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_haraka256_skx4(unsigned char *out, const unsigned char *in, const harakactx *state); +#define haraka256 SPX_NAMESPACE(haraka256) +void haraka256(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/haraka_offsets.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/haraka_offsets.h new file mode 100644 index 0000000000..7c062272a0 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/haraka_offsets.h @@ -0,0 +1,21 @@ +#ifndef HARAKA_OFFSETS_H_ +#define HARAKA_OFFSETS_H_ + +/* + * Offsets of various fields in the address structure when we use Haraka as + * the Sphincs+ hash function + */ + +#define SPX_OFFSET_LAYER 3 /* The byte used to specify the Merkle tree layer */ +#define SPX_OFFSET_TREE 8 /* The start of the 8 byte field used to specify the tree */ +#define SPX_OFFSET_TYPE 19 /* The byte used to specify the hash type (reason) */ +#define SPX_OFFSET_KP_ADDR2 22 /* The high byte used to specify the key pair (which one-time signature) */ +#define SPX_OFFSET_KP_ADDR1 23 /* The low byte used to specify the key pair */ +#define SPX_OFFSET_CHAIN_ADDR 27 /* The byte used to specify the chain address (which Winternitz chain) */ +#define SPX_OFFSET_HASH_ADDR 31 /* The byte used to specify the hash address (where in the Winternitz chain) */ +#define SPX_OFFSET_TREE_HGT 27 /* The byte used to specify the height of this node in the FORS or Merkle tree */ +#define SPX_OFFSET_TREE_INDEX 28 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ + +#define SPX_HARAKA 1 + +#endif /* HARAKA_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/harakax4.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/harakax4.h new file mode 100644 index 0000000000..eadc69aa48 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/harakax4.h @@ -0,0 +1,36 @@ +#ifndef SPX_HARAKAX4_H +#define SPX_HARAKAX4_H + +#include "context.h" +#include "params.h" + +/* Haraka Sponge */ +#define haraka_Sx4 SPX_NAMESPACE(haraka_Sx4) +void haraka_Sx4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned long long outlen, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + unsigned long long inlen, + const spx_ctx *ctx); + +/* Applies the 512-bit Haraka permutation x4 to in. */ +#define haraka512_perm_x4 SPX_NAMESPACE(haraka512_perm_x4) +void haraka512_perm_x4(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx); + +/* Implementation of Haraka-512 x4*/ +#define haraka512x4 SPX_NAMESPACE(haraka512x4) +void haraka512x4(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx); + +/* Implementation of Haraka-256 x4 */ +#define haraka256x4 SPX_NAMESPACE(haraka256x4) +void haraka256x4(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/hash.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/hash.h index 45aaca687d..f7c87d4c3c 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/hash.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/hash.h @@ -1,31 +1,28 @@ -#ifndef PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_HASH_H -#define PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_HASH_H - -#include "hash_state.h" +#ifndef SPX_HASH_H +#define SPX_HASH_H #include #include -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_initialize_hash_function( - hash_state *hash_state_seeded, - const unsigned char *pub_seed, const unsigned char *sk_seed); +#include "context.h" +#include "params.h" + +#define prf_addr SPX_NAMESPACE(prf_addr) +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]); -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_destroy_hash_function(hash_state *hash_state_seeded); +#define gen_message_random SPX_NAMESPACE(gen_message_random) +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded); +#define hash_message SPX_NAMESPACE(hash_message) +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/hash_haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/hash_haraka.c index ffc4f9563d..750a67423b 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/hash_haraka.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/hash_haraka.c @@ -2,58 +2,44 @@ #include #include "address.h" -#include "haraka.h" -#include "hash.h" #include "params.h" #include "utils.h" -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_initialize_hash_function( - hash_state *hash_state_seeded, - const unsigned char *pub_seed, const unsigned char *sk_seed) { - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_tweak_constants(hash_state_seeded, pub_seed, sk_seed, PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N); -} - -/* The haraka implementation is stack based and won't be replaced in PQClean/OQS, - so we don't need to do anything */ -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_destroy_hash_function( - hash_state *hash_state_seeded) { // NOLINT(readability-non-const-parameter) - (void)hash_state_seeded; -} +#include "haraka.h" +#include "hash.h" /* - * Computes PRF(key, addr), given a secret key of PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N bytes and an address + * Computes PRF(key, addr), given a secret key of SPX_N bytes and an address */ -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded) { - unsigned char buf[PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_ADDR_BYTES]; - /* Since PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N may be smaller than 32, we need a temporary buffer. */ +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]) { + /* Since SPX_N may be smaller than 32, we need temporary buffers. */ unsigned char outbuf[32]; + unsigned char buf[64] = {0}; - (void)key; /* Suppress an 'unused parameter' warning. */ + memcpy(buf, addr, SPX_ADDR_BYTES); + memcpy(buf + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_addr_to_bytes(buf, addr); - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_haraka256_sk(outbuf, buf, hash_state_seeded); - memcpy(out, outbuf, PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N); + haraka512(outbuf, (const void *)buf, ctx); + memcpy(out, outbuf, SPX_N); } /** * Computes the message-dependent randomness R, using a secret seed and an * optional randomization value as well as the message. */ -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded) { +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { uint8_t s_inc[65]; - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_haraka_S_inc_init(s_inc); - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_haraka_S_inc_absorb(s_inc, sk_prf, PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_haraka_S_inc_absorb(s_inc, optrand, PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_haraka_S_inc_absorb(s_inc, m, mlen, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_haraka_S_inc_finalize(s_inc); - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_haraka_S_inc_squeeze(R, PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N, s_inc, hash_state_seeded); + haraka_S_inc_init(s_inc); + haraka_S_inc_absorb(s_inc, sk_prf, SPX_N, ctx); + haraka_S_inc_absorb(s_inc, optrand, SPX_N, ctx); + haraka_S_inc_absorb(s_inc, m, mlen, ctx); + haraka_S_inc_finalize(s_inc); + haraka_S_inc_squeeze(R, SPX_N, s_inc, ctx); } /** @@ -61,36 +47,35 @@ void PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_gen_message_random( * Outputs the message digest and the index of the leaf. The index is split in * the tree index and the leaf index, for convenient copying to an address. */ -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded) { -#define PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_TREE_BITS (PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_TREE_HEIGHT * (PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_D - 1)) -#define PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_TREE_BYTES ((PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_TREE_BITS + 7) / 8) -#define PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_LEAF_BITS PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_TREE_HEIGHT -#define PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_LEAF_BYTES ((PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_LEAF_BITS + 7) / 8) -#define PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_DGST_BYTES (PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_FORS_MSG_BYTES + PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_TREE_BYTES + PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_LEAF_BYTES) +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { +#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) +#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) +#define SPX_LEAF_BITS SPX_TREE_HEIGHT +#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) +#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) - unsigned char buf[PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_DGST_BYTES]; + unsigned char buf[SPX_DGST_BYTES]; unsigned char *bufp = buf; uint8_t s_inc[65]; - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_haraka_S_inc_init(s_inc); - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_haraka_S_inc_absorb(s_inc, R, PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_haraka_S_inc_absorb(s_inc, pk + PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N, PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_haraka_S_inc_absorb(s_inc, m, mlen, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_haraka_S_inc_finalize(s_inc); - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_haraka_S_inc_squeeze(buf, PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_DGST_BYTES, s_inc, hash_state_seeded); + haraka_S_inc_init(s_inc); + haraka_S_inc_absorb(s_inc, R, SPX_N, ctx); + haraka_S_inc_absorb(s_inc, pk + SPX_N, SPX_N, ctx); // Only absorb root part of pk + haraka_S_inc_absorb(s_inc, m, mlen, ctx); + haraka_S_inc_finalize(s_inc); + haraka_S_inc_squeeze(buf, SPX_DGST_BYTES, s_inc, ctx); + + memcpy(digest, bufp, SPX_FORS_MSG_BYTES); + bufp += SPX_FORS_MSG_BYTES; - memcpy(digest, bufp, PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_FORS_MSG_BYTES); - bufp += PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_FORS_MSG_BYTES; - *tree = PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_bytes_to_ull(bufp, PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_TREE_BYTES); - *tree &= (~(uint64_t)0) >> (64 - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_TREE_BITS); - bufp += PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_TREE_BYTES; + *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); + *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); + bufp += SPX_TREE_BYTES; - *leaf_idx = (uint32_t)PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_bytes_to_ull( - bufp, PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_LEAF_BYTES); - *leaf_idx &= (~(uint32_t)0) >> (32 - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_LEAF_BITS); + *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); + *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/hash_harakax4.c b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/hash_harakax4.c index 764de98cc5..cfa5162d79 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/hash_harakax4.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/hash_harakax4.c @@ -2,36 +2,34 @@ #include #include "address.h" -#include "haraka.h" -#include "hash_state.h" +#include "harakax4.h" #include "hashx4.h" #include "params.h" /* * 4-way parallel version of prf_addr; takes 4x as much input and output */ -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_prf_addrx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const unsigned char *key, - const uint32_t addrx4[4 * 8], - const hash_state *state_seeded) { - unsigned char bufx4[4 * PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_ADDR_BYTES]; - /* Since PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N may be smaller than 32, we need a temporary buffer. */ +#define prf_addrx4 SPX_NAMESPACE(prf_addrx4) +void prf_addrx4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const spx_ctx *ctx, + const uint32_t addrx4[4 * 8]) { + unsigned char bufx4[4 * 64] = {0}; + /* Since SPX_N may be smaller than 32, we need temporary buffers. */ unsigned char outbuf[4 * 32]; unsigned int i; - (void)key; /* Suppress an 'unused parameter' warning. */ - for (i = 0; i < 4; i++) { - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_addr_to_bytes(bufx4 + i * PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_ADDR_BYTES, addrx4 + i * 8); + memcpy(bufx4 + i * 64, addrx4 + i * 8, SPX_ADDR_BYTES); + memcpy(bufx4 + i * 64 + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); } - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_haraka256_skx4(outbuf, bufx4, state_seeded); + haraka512x4(outbuf, bufx4, ctx); - memcpy(out0, outbuf, PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N); - memcpy(out1, outbuf + 32, PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N); - memcpy(out2, outbuf + 64, PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N); - memcpy(out3, outbuf + 96, PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N); + memcpy(out0, outbuf, SPX_N); + memcpy(out1, outbuf + 32, SPX_N); + memcpy(out2, outbuf + 64, SPX_N); + memcpy(out3, outbuf + 96, SPX_N); } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/hash_state.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/hash_state.h deleted file mode 100644 index 9a55b78cb4..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/hash_state.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_HASH_STATE_H -#define PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_HASH_STATE_H - -/** - * Defines the type of the hash function state. - * - * Don't be fooled into thinking this instance of SPHINCS+ isn't stateless! - * - * From Section 7.2.2 from the SPHINCS+ round-2 specification: - * - * Each of the instances of the tweakable hash function take PK.seed as its - * first input, which is constant for a given key pair – and, thus, across - * a single signature. This leads to a lot of redundant computation. To remedy - * this, we pad PK.seed to the length of a full 64-byte SHA-256 input block. - * Because of the Merkle-DamgÃ¥rd construction that underlies SHA-256, this - * allows for reuse of the intermediate SHA-256 state after the initial call to - * the compression function which improves performance. - * - * We pass this hash state around in functions, because otherwise we need to - * have a global variable. - */ - -#include "haraka.h" -#define hash_state harakactx - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/hashx4.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/hashx4.h index 837008009a..3751a0ebd0 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/hashx4.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/hashx4.h @@ -1,16 +1,17 @@ -#ifndef PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_HASHX4_H -#define PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_HASHX4_H +#ifndef SPX_HASHX4_H +#define SPX_HASHX4_H #include -#include "hash_state.h" +#include "context.h" +#include "params.h" -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_prf_addrx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const unsigned char *key, - const uint32_t addrx4[4 * 8], - const hash_state *state_seeded); +#define prf_addrx4 SPX_NAMESPACE(prf_addrx4) +void prf_addrx4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const spx_ctx *ctx, + const uint32_t addrx4[4 * 8]); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/merkle.c b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/merkle.c new file mode 100644 index 0000000000..f57811c1ac --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/merkle.c @@ -0,0 +1,64 @@ +#include +#include + +#include "merkle.h" + +#include "address.h" +#include "params.h" +#include "utils.h" +#include "utilsx4.h" +#include "wots.h" +#include "wotsx4.h" + +/* + * This generates a Merkle signature (WOTS signature followed by the Merkle + * authentication path). + */ +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf) { + unsigned char *auth_path = sig + SPX_WOTS_BYTES; + uint32_t tree_addrx4[4 * 8] = { 0 }; + int j; + struct leaf_info_x4 info = { 0 }; + unsigned steps[ SPX_WOTS_LEN ]; + + info.wots_sig = sig; + chain_lengths(steps, root); + info.wots_steps = steps; + + for (j = 0; j < 4; j++) { + set_type(&tree_addrx4[8 * j], SPX_ADDR_TYPE_HASHTREE); + set_type(&info.leaf_addr[8 * j], SPX_ADDR_TYPE_WOTS); + set_type(&info.pk_addr[8 * j], SPX_ADDR_TYPE_WOTSPK); + copy_subtree_addr(&tree_addrx4[8 * j], tree_addr); + copy_subtree_addr(&info.leaf_addr[8 * j], wots_addr); + copy_subtree_addr(&info.pk_addr[8 * j], wots_addr); + } + + info.wots_sign_leaf = idx_leaf; + + treehashx4(root, auth_path, ctx, + idx_leaf, 0, + SPX_TREE_HEIGHT, + wots_gen_leafx4, + tree_addrx4, &info); +} + +/* Compute root node of the top-most subtree. */ +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { + /* We do not need the auth path in key generation, but it simplifies the + code to have just one treehash routine that computes both root and path + in one function. */ + unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; + uint32_t top_tree_addr[8] = {0}; + uint32_t wots_addr[8] = {0}; + + set_layer_addr(top_tree_addr, SPX_D - 1); + set_layer_addr(wots_addr, SPX_D - 1); + + merkle_sign(auth_path, root, ctx, + wots_addr, top_tree_addr, + ~0U /* ~0 means "don't bother generating an auth path */ ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/merkle.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/merkle.h new file mode 100644 index 0000000000..769cf2e970 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/merkle.h @@ -0,0 +1,21 @@ +#ifndef MERKLE_H_ +#define MERKLE_H_ + +#include + +#include "context.h" +#include "params.h" + +/* Generate a Merkle signature (WOTS signature followed by the Merkle */ +/* authentication path) */ +#define merkle_sign SPX_NAMESPACE(merkle_sign) +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf); + +/* Compute the root node of the top-most subtree. */ +#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); + +#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/nistapi.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/nistapi.h new file mode 100644 index 0000000000..3cb71afad4 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/nistapi.h @@ -0,0 +1,87 @@ +#ifndef SPX_API_H +#define SPX_API_H + +#include +#include + +#include "params.h" + +#define CRYPTO_ALGNAME "SPHINCS+" + +#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES +#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES +#define CRYPTO_BYTES SPX_BYTES +#define CRYPTO_SEEDBYTES (3*SPX_N) + +/* + * Returns the length of a secret key, in bytes + */ +#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) +size_t crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) +size_t crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) +size_t crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) +size_t crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +#define crypto_sign SPX_NAMESPACE(crypto_sign) +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/params.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/params.h index 378e1329ad..1de64f01ac 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/params.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/params.h @@ -1,53 +1,56 @@ -#ifndef PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_PARAMS_H -#define PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_PARAMS_H +#ifndef SPX_PARAMS_H +#define SPX_PARAMS_H + +#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_##s /* Hash output length in bytes. */ -#define PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N 16 +#define SPX_N 16 /* Height of the hypertree. */ -#define PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_FULL_HEIGHT 63 +#define SPX_FULL_HEIGHT 63 /* Number of subtree layer. */ -#define PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_D 7 +#define SPX_D 7 /* FORS tree dimensions. */ -#define PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_FORS_HEIGHT 12 -#define PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_FORS_TREES 14 +#define SPX_FORS_HEIGHT 12 +#define SPX_FORS_TREES 14 /* Winternitz parameter, */ -#define PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_WOTS_W 16 +#define SPX_WOTS_W 16 /* The hash function is defined by linking a different hash.c file, as opposed to setting a #define constant. */ /* For clarity */ -#define PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_ADDR_BYTES 32 +#define SPX_ADDR_BYTES 32 /* WOTS parameters. */ -#define PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_WOTS_LOGW 4 +#define SPX_WOTS_LOGW 4 -#define PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_WOTS_LEN1 (8 * PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N / PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_WOTS_LOGW) +#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) -/* PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#define PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_WOTS_LEN2 3 +/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ +#define SPX_WOTS_LEN2 3 -#define PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_WOTS_LEN (PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_WOTS_LEN1 + PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_WOTS_LEN2) -#define PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_WOTS_BYTES (PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_WOTS_LEN * PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N) -#define PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_WOTS_PK_BYTES PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_WOTS_BYTES +#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) +#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) +#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES /* Subtree size. */ -#define PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_TREE_HEIGHT (PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_FULL_HEIGHT / PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_D) +#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) + +//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT +// #error SPX_D should always divide SPX_FULL_HEIGHT +//#endif /* FORS parameters. */ -#define PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_FORS_MSG_BYTES ((PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_FORS_TREES + 7) / 8) -#define PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_FORS_BYTES ((PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_FORS_HEIGHT + 1) * PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_FORS_TREES * PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N) -#define PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_FORS_PK_BYTES PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N +#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) +#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) +#define SPX_FORS_PK_BYTES SPX_N /* Resulting SPX sizes. */ -#define PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_BYTES (PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N + PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_FORS_BYTES + PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_D * PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_WOTS_BYTES +\ - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_FULL_HEIGHT * PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N) -#define PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_PK_BYTES (2 * PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N) -#define PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_SK_BYTES (2 * PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N + PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_PK_BYTES) - -/* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ -#define PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_OPTRAND_BYTES 32 +#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ + SPX_FULL_HEIGHT * SPX_N) +#define SPX_PK_BYTES (2 * SPX_N) +#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) + +#include "haraka_offsets.h" #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/sign.c b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/sign.c index ff294b241a..9d0c7d1b22 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/sign.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/sign.c @@ -1,76 +1,45 @@ -#include #include #include #include #include "address.h" -#include "api.h" +#include "context.h" #include "fors.h" #include "hash.h" -#include "hash_state.h" +#include "merkle.h" +#include "nistapi.h" #include "params.h" #include "randombytes.h" #include "thash.h" #include "utils.h" #include "wots.h" - -/** - * Computes the leaf at a given address. First generates the WOTS key pair, - * then computes leaf by hashing horizontally. - */ -static void wots_gen_leaf(unsigned char *leaf, const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx, const uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - unsigned char pk[PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_WOTS_BYTES]; - uint32_t wots_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_set_type( - wots_addr, PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_set_type( - wots_pk_addr, PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_ADDR_TYPE_WOTSPK); - - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_set_keypair_addr( - wots_addr, addr_idx); - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_wots_gen_pk( - pk, sk_seed, pub_seed, wots_addr, hash_state_seeded); - - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_copy_keypair_addr( - wots_pk_addr, wots_addr); - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_thash_WOTS_LEN( - leaf, pk, pub_seed, wots_pk_addr, hash_state_seeded); -} - /* * Returns the length of a secret key, in bytes */ -size_t PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_crypto_sign_secretkeybytes(void) { - return PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_CRYPTO_SECRETKEYBYTES; +size_t crypto_sign_secretkeybytes(void) { + return CRYPTO_SECRETKEYBYTES; } /* * Returns the length of a public key, in bytes */ -size_t PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_crypto_sign_publickeybytes(void) { - return PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_CRYPTO_PUBLICKEYBYTES; +size_t crypto_sign_publickeybytes(void) { + return CRYPTO_PUBLICKEYBYTES; } /* * Returns the length of a signature, in bytes */ -size_t PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_crypto_sign_bytes(void) { - return PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_CRYPTO_BYTES; +size_t crypto_sign_bytes(void) { + return CRYPTO_BYTES; } /* * Returns the length of the seed required to generate a key pair, in bytes */ -size_t PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_crypto_sign_seedbytes(void) { - return PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_CRYPTO_SEEDBYTES; +size_t crypto_sign_seedbytes(void) { + return CRYPTO_SEEDBYTES; } /* @@ -78,35 +47,29 @@ size_t PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_crypto_sign_seedbytes(void) { * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] * Format pk: [PUB_SEED || root] */ -int PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed) { - /* We do not need the auth path in key generation, but it simplifies the - code to have just one treehash routine that computes both root and path - in one function. */ - unsigned char auth_path[PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_TREE_HEIGHT * PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N]; - uint32_t top_tree_addr[8] = {0}; - hash_state hash_state_seeded; - - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_set_layer_addr( - top_tree_addr, PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_D - 1); - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_set_type( - top_tree_addr, PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_ADDR_TYPE_HASHTREE); +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed) { + spx_ctx ctx; /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ - memcpy(sk, seed, PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_CRYPTO_SEEDBYTES); + memcpy(sk, seed, CRYPTO_SEEDBYTES); + + memcpy(pk, sk + 2 * SPX_N, SPX_N); - memcpy(pk, sk + 2 * PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N, PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N); + memcpy(ctx.pub_seed, pk, SPX_N); + memcpy(ctx.sk_seed, sk, SPX_N); /* This hook allows the hash function instantiation to do whatever preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_initialize_hash_function(&hash_state_seeded, pk, sk); + initialize_hash_function(&ctx); /* Compute root node of the top-most subtree. */ - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_treehash_TREE_HEIGHT( - sk + 3 * PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N, auth_path, sk, sk + 2 * PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N, 0, 0, - wots_gen_leaf, top_tree_addr, &hash_state_seeded); + merkle_gen_root(sk + 3 * SPX_N, &ctx); - memcpy(pk + PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N, sk + 3 * PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N, PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N); + // cleanup + free_hash_function(&ctx); + + memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); return 0; } @@ -116,31 +79,10 @@ int PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_crypto_sign_seed_keypair( * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] * Format pk: [PUB_SEED || root] */ -int PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk) { - - // guarantee alignment of pk - union { - __m128 _x[PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_CRYPTO_PUBLICKEYBYTES / 16]; - uint8_t pk[PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_CRYPTO_PUBLICKEYBYTES]; - } aligned_pk; - - // guarantee alignment of sk - union { - __m128 _x[PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_CRYPTO_SECRETKEYBYTES / 16]; - uint8_t sk[PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_CRYPTO_SECRETKEYBYTES]; - } aligned_sk; - - union { - __m128 _x[PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_CRYPTO_SEEDBYTES / 16]; - uint8_t seed[PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_CRYPTO_SEEDBYTES]; - } aligned_seed; - randombytes(aligned_seed.seed, PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_CRYPTO_SEEDBYTES); - - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_crypto_sign_seed_keypair( - aligned_pk.pk, aligned_sk.sk, aligned_seed.seed); - memcpy(pk, aligned_pk.pk, PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_CRYPTO_PUBLICKEYBYTES); - memcpy(sk, aligned_sk.sk, PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_CRYPTO_SECRETKEYBYTES); +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { + uint8_t seed[CRYPTO_SEEDBYTES]; + randombytes(seed, CRYPTO_SEEDBYTES); + crypto_sign_seed_keypair(pk, sk, seed); return 0; } @@ -148,101 +90,68 @@ int PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_crypto_sign_keypair( /** * Returns an array containing a detached signature. */ -int PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - // guarantee alignment of sk - union { - __m128 *_x; - uint8_t sk[PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_CRYPTO_SECRETKEYBYTES]; - } aligned_sk; - memcpy(aligned_sk.sk, sk, PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_CRYPTO_SECRETKEYBYTES); - sk = aligned_sk.sk; - - // guarantee alignment of sig - union { - __m128 *_x; - uint8_t sig[PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_BYTES]; - } aligned_sig; - uint8_t *orig_sig = sig; - sig = (uint8_t *)aligned_sig.sig; - - const unsigned char *sk_seed = sk; - const unsigned char *sk_prf = sk + PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N; - const unsigned char *pk = sk + 2 * PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N; - const unsigned char *pub_seed = pk; - - unsigned char optrand[PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N]; - unsigned char mhash[PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_FORS_MSG_BYTES]; - unsigned char root[PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N]; +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk) { + spx_ctx ctx; + + const uint8_t *sk_prf = sk + SPX_N; + const uint8_t *pk = sk + 2 * SPX_N; + + uint8_t optrand[SPX_N]; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t root[SPX_N]; uint32_t i; uint64_t tree; uint32_t idx_leaf; uint32_t wots_addr[8] = {0}; uint32_t tree_addr[8] = {0}; - hash_state hash_state_seeded; + memcpy(ctx.sk_seed, sk, SPX_N); + memcpy(ctx.pub_seed, pk, SPX_N); /* This hook allows the hash function instantiation to do whatever preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_initialize_hash_function( - &hash_state_seeded, - pub_seed, sk_seed); + initialize_hash_function(&ctx); - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_set_type( - wots_addr, PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_set_type( - tree_addr, PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_ADDR_TYPE_HASHTREE); + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); /* Optionally, signing can be made non-deterministic using optrand. This can help counter side-channel attacks that would benefit from getting a large number of traces when the signer uses the same nodes. */ - randombytes(optrand, PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N); + randombytes(optrand, SPX_N); /* Compute the digest randomization value. */ - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_gen_message_random( - sig, sk_prf, optrand, m, mlen, &hash_state_seeded); + gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); /* Derive the message digest and leaf index from R, PK and M. */ - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N; + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_set_keypair_addr( - wots_addr, idx_leaf); + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); /* Sign the message hash using FORS. */ - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_fors_sign( - sig, root, mhash, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_FORS_BYTES; - - for (i = 0; i < PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_D; i++) { - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_set_tree_addr(tree_addr, tree); - - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_set_keypair_addr( - wots_addr, idx_leaf); - - /* Compute a WOTS signature. */ - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_wots_sign( - sig, root, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_WOTS_BYTES; - - /* Compute the authentication path for the used WOTS leaf. */ - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_treehash_TREE_HEIGHT( - root, sig, sk_seed, pub_seed, idx_leaf, 0, - wots_gen_leaf, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_TREE_HEIGHT * PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N; + fors_sign(sig, root, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); + sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_TREE_HEIGHT; + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; } - memcpy(orig_sig, aligned_sig.sig, PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_BYTES); - *siglen = PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_BYTES; + free_hash_function(&ctx); + + *siglen = SPX_BYTES; return 0; } @@ -250,23 +159,14 @@ int PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_crypto_sign_signature( /** * Verifies a detached signature and message under a given public key. */ -int PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk) { - // guarantee alignment of pk - union { - __m128 *_x; - uint8_t pk[PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_CRYPTO_PUBLICKEYBYTES]; - } aligned_pk; - memcpy(aligned_pk.pk, pk, PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_CRYPTO_PUBLICKEYBYTES); - pk = aligned_pk.pk; - - const unsigned char *pub_seed = pk; - const unsigned char *pub_root = pk + PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N; - unsigned char mhash[PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_FORS_MSG_BYTES]; - unsigned char wots_pk[PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_WOTS_BYTES]; - unsigned char root[PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N]; - unsigned char leaf[PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N]; +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk) { + spx_ctx ctx; + const uint8_t *pub_root = pk + SPX_N; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t wots_pk[SPX_WOTS_BYTES]; + uint8_t root[SPX_N]; + uint8_t leaf[SPX_N]; unsigned int i; uint64_t tree; uint32_t idx_leaf; @@ -274,77 +174,66 @@ int PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_crypto_sign_verify( uint32_t tree_addr[8] = {0}; uint32_t wots_pk_addr[8] = {0}; - hash_state hash_state_seeded; - - if (siglen != PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_BYTES) { + if (siglen != SPX_BYTES) { return -1; } + memcpy(ctx.pub_seed, pk, SPX_N); + /* This hook allows the hash function instantiation to do whatever preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_initialize_hash_function( - &hash_state_seeded, - pub_seed, NULL); + initialize_hash_function(&ctx); - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_set_type( - wots_addr, PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_set_type( - tree_addr, PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_ADDR_TYPE_HASHTREE); - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_set_type( - wots_pk_addr, PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_ADDR_TYPE_WOTSPK); + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); /* Derive the message digest and leaf index from R || PK || M. */ - /* The additional PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N is a result of the hash domain separator. */ - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N; + /* The additional SPX_N is a result of the hash domain separator. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; /* Layer correctly defaults to 0, so no need to set_layer_addr */ - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_set_keypair_addr( - wots_addr, idx_leaf); + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_fors_pk_from_sig( - root, sig, mhash, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_FORS_BYTES; + fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; /* For each subtree.. */ - for (i = 0; i < PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_D; i++) { - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_set_tree_addr(tree_addr, tree); + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_set_keypair_addr( - wots_addr, idx_leaf); + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_copy_keypair_addr( - wots_pk_addr, wots_addr); + copy_keypair_addr(wots_pk_addr, wots_addr); /* The WOTS public key is only correct if the signature was correct. */ /* Initially, root is the FORS pk, but on subsequent iterations it is the root of the subtree below the currently processed subtree. */ - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_wots_pk_from_sig( - wots_pk, sig, root, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_WOTS_BYTES; + wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); + sig += SPX_WOTS_BYTES; /* Compute the leaf node using the WOTS public key. */ - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_thash_WOTS_LEN( - leaf, wots_pk, pub_seed, wots_pk_addr, &hash_state_seeded); + thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); /* Compute the root node of this subtree. */ - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_compute_root( - root, leaf, idx_leaf, 0, sig, PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_TREE_HEIGHT, - pub_seed, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_TREE_HEIGHT * PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N; + compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, + &ctx, tree_addr); + sig += SPX_TREE_HEIGHT * SPX_N; /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_TREE_HEIGHT; + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; } + // cleanup + free_hash_function(&ctx); + /* Check if the root node equals the root node in the public key. */ - if (memcmp(root, pub_root, PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N) != 0) { + if (memcmp(root, pub_root, SPX_N) != 0) { return -1; } @@ -355,15 +244,14 @@ int PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_crypto_sign_verify( /** * Returns an array containing the signature followed by the message. */ -int PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk) { size_t siglen; - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_crypto_sign_signature( - sm, &siglen, m, mlen, sk); + crypto_sign_signature(sm, &siglen, m, mlen, sk); - memmove(sm + PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_BYTES, m, mlen); + memmove(sm + SPX_BYTES, m, mlen); *smlen = siglen + mlen; return 0; @@ -372,38 +260,27 @@ int PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_crypto_sign( /** * Verifies a given signature-message pair under a given public key. */ -int PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk) { - - // guarantee alignment of pk - union { - __m128 *_x; - uint8_t pk[PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_CRYPTO_PUBLICKEYBYTES]; - } aligned_pk; - memcpy(aligned_pk.pk, pk, PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_CRYPTO_PUBLICKEYBYTES); - pk = aligned_pk.pk; - - +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk) { /* The API caller does not necessarily know what size a signature should be - but SPHINCS+ signatures are always exactly PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_BYTES. */ - if (smlen < PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_BYTES) { + but SPHINCS+ signatures are always exactly SPX_BYTES. */ + if (smlen < SPX_BYTES) { memset(m, 0, smlen); *mlen = 0; return -1; } - *mlen = smlen - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_BYTES; + *mlen = smlen - SPX_BYTES; - if (PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_crypto_sign_verify( - sm, PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_BYTES, sm + PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_BYTES, *mlen, pk)) { + if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { memset(m, 0, smlen); *mlen = 0; return -1; } /* If verification was successful, move the message to the right place. */ - memmove(m, sm + PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_BYTES, *mlen); + memmove(m, sm + SPX_BYTES, *mlen); return 0; } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/thash.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/thash.h index 25ace05311..8687ccfb4d 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/thash.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/thash.h @@ -1,28 +1,13 @@ -#ifndef PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_THASH_H -#define PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_THASH_H +#ifndef SPX_THASH_H +#define SPX_THASH_H -#include "hash_state.h" +#include "context.h" +#include "params.h" #include -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); +#define thash SPX_NAMESPACE(thash) +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/thash_haraka_simple.c b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/thash_haraka_simple.c index d59464a74b..207777bf8d 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/thash_haraka_simple.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/thash_haraka_simple.c @@ -4,80 +4,33 @@ #include "address.h" #include "params.h" #include "thash.h" +#include "utils.h" #include "haraka.h" /** - * Takes an array of inblocks concatenated arrays of PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N bytes. + * Takes an array of inblocks concatenated arrays of SPX_N bytes. */ -static void PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_thash( - unsigned char *out, unsigned char *buf, - const unsigned char *in, unsigned int inblocks, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]) { + PQCLEAN_VLA(uint8_t, buf, SPX_ADDR_BYTES + inblocks * SPX_N); unsigned char outbuf[32]; unsigned char buf_tmp[64]; - (void)pub_seed; /* Suppress an 'unused parameter' warning. */ - if (inblocks == 1) { /* F function */ - /* Since PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N may be smaller than 32, we need a temporary buffer. */ + /* Since SPX_N may be smaller than 32, we need a temporary buffer. */ memset(buf_tmp, 0, 64); - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_addr_to_bytes(buf_tmp, addr); - memcpy(buf_tmp + PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_ADDR_BYTES, in, PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N); + memcpy(buf_tmp, addr, 32); + memcpy(buf_tmp + SPX_ADDR_BYTES, in, SPX_N); - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_haraka512(outbuf, buf_tmp, hash_state_seeded); - memcpy(out, outbuf, PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N); + haraka512(outbuf, buf_tmp, ctx); + memcpy(out, outbuf, SPX_N); } else { /* All other tweakable hashes*/ - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_addr_to_bytes(buf, addr); - memcpy(buf + PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_ADDR_BYTES, in, inblocks * PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N); + memcpy(buf, addr, 32); + memcpy(buf + SPX_ADDR_BYTES, in, inblocks * SPX_N); - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_haraka_S( - out, PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N, buf, PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N, hash_state_seeded); + haraka_S(out, SPX_N, buf, SPX_ADDR_BYTES + inblocks * SPX_N, ctx); } } - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_ADDR_BYTES + 1 * PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N]; - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_thash( - out, buf, in, 1, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_ADDR_BYTES + 2 * PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N]; - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_thash( - out, buf, in, 2, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_ADDR_BYTES + PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_WOTS_LEN * PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N]; - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_thash( - out, buf, in, PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_WOTS_LEN, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_ADDR_BYTES + PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_FORS_TREES * PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N]; - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_thash( - out, buf, in, PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_FORS_TREES, pub_seed, addr, hash_state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/thash_haraka_simplex4.c b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/thash_haraka_simplex4.c index ab46d997c9..2ee763d7d9 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/thash_haraka_simplex4.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/thash_haraka_simplex4.c @@ -2,65 +2,66 @@ #include #include "address.h" -#include "haraka.h" #include "params.h" #include "thashx4.h" +#include "harakax4.h" + +#include "utils.h" + /** * 4-way parallel version of thash; takes 4x as much input and output */ -#define thashx4_variant(name, inblocks) \ - void PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_thashx4_##name(unsigned char *out0, unsigned char *out1, unsigned char *out2, \ - unsigned char *out3, const unsigned char *in0, \ - const unsigned char *in1, const unsigned char *in2, \ - const unsigned char *in3, const unsigned char *pub_seed, \ - uint32_t addrx4[4 * 8], const harakactx *state) { \ - unsigned char buf0[PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_ADDR_BYTES + (inblocks)*PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N]; \ - unsigned char buf1[PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_ADDR_BYTES + (inblocks)*PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N]; \ - unsigned char buf2[PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_ADDR_BYTES + (inblocks)*PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N]; \ - unsigned char buf3[PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_ADDR_BYTES + (inblocks)*PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N]; \ - unsigned char outbuf[32 * 4]; \ - unsigned char buf_tmp[64 * 4]; \ - \ - (void)pub_seed; /* Suppress an 'unused parameter' warning. */ \ - \ - if ((inblocks) == 1) { \ - memset(buf_tmp, 0, 64 * 4); \ - \ - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_addr_to_bytes(buf_tmp, addrx4 + 0 * 8); \ - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_addr_to_bytes(buf_tmp + 64, addrx4 + 1 * 8); \ - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_addr_to_bytes(buf_tmp + 128, addrx4 + 2 * 8); \ - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_addr_to_bytes(buf_tmp + 192, addrx4 + 3 * 8); \ - \ - memcpy(buf_tmp + PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_ADDR_BYTES, in0, PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N); \ - memcpy(buf_tmp + PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_ADDR_BYTES + 64, in1, PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N); \ - memcpy(buf_tmp + PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_ADDR_BYTES + 128, in2, PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N); \ - memcpy(buf_tmp + PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_ADDR_BYTES + 192, in3, PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N); \ - \ - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_haraka512x4(outbuf, buf_tmp, state); \ - \ - memcpy(out0, outbuf, PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N); \ - memcpy(out1, outbuf + 32, PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N); \ - memcpy(out2, outbuf + 64, PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N); \ - memcpy(out3, outbuf + 96, PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N); \ - } else { \ - /* All other tweakable hashes*/ \ - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_addr_to_bytes(buf0, addrx4 + 0 * 8); \ - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_addr_to_bytes(buf1, addrx4 + 1 * 8); \ - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_addr_to_bytes(buf2, addrx4 + 2 * 8); \ - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_addr_to_bytes(buf3, addrx4 + 3 * 8); \ - \ - memcpy(buf0 + PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_ADDR_BYTES, in0, (inblocks)*PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N); \ - memcpy(buf1 + PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_ADDR_BYTES, in1, (inblocks)*PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N); \ - memcpy(buf2 + PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_ADDR_BYTES, in2, (inblocks)*PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N); \ - memcpy(buf3 + PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_ADDR_BYTES, in3, (inblocks)*PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N); \ - \ - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_haraka_Sx4(out0, out1, out2, out3, PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N, buf0, buf1, buf2, buf3, \ - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_ADDR_BYTES + (inblocks)*PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N, state); \ - } \ - } +#define thashx4 SPX_NAMESPACE(thashx4) +void thashx4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addrx4[4 * 8]) { + PQCLEAN_VLA(unsigned char, buf0, SPX_ADDR_BYTES + inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, buf1, SPX_ADDR_BYTES + inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, buf2, SPX_ADDR_BYTES + inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, buf3, SPX_ADDR_BYTES + inblocks * SPX_N); + unsigned char outbuf[32 * 4]; + unsigned char buf_tmp[64 * 4]; + + if (inblocks == 1) { + memset(buf_tmp, 0, 64 * 4); + + memcpy(buf_tmp, addrx4 + 0 * 8, 32); + memcpy(buf_tmp + 64, addrx4 + 1 * 8, 32); + memcpy(buf_tmp + 128, addrx4 + 2 * 8, 32); + memcpy(buf_tmp + 192, addrx4 + 3 * 8, 32); -thashx4_variant(1, 1) -thashx4_variant(2, 2) -thashx4_variant(WOTS_LEN, PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_WOTS_LEN) -thashx4_variant(FORS_TREES, PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_FORS_TREES) + memcpy(buf_tmp + SPX_ADDR_BYTES, in0, SPX_N); + memcpy(buf_tmp + SPX_ADDR_BYTES + 64, in1, SPX_N); + memcpy(buf_tmp + SPX_ADDR_BYTES + 128, in2, SPX_N); + memcpy(buf_tmp + SPX_ADDR_BYTES + 192, in3, SPX_N); + + haraka512x4(outbuf, buf_tmp, ctx); + + memcpy(out0, outbuf, SPX_N); + memcpy(out1, outbuf + 32, SPX_N); + memcpy(out2, outbuf + 64, SPX_N); + memcpy(out3, outbuf + 96, SPX_N); + } else { + /* All other tweakable hashes*/ + memcpy(buf0, addrx4 + 0 * 8, 32); + memcpy(buf1, addrx4 + 1 * 8, 32); + memcpy(buf2, addrx4 + 2 * 8, 32); + memcpy(buf3, addrx4 + 3 * 8, 32); + + memcpy(buf0 + SPX_ADDR_BYTES, in0, inblocks * SPX_N); + memcpy(buf1 + SPX_ADDR_BYTES, in1, inblocks * SPX_N); + memcpy(buf2 + SPX_ADDR_BYTES, in2, inblocks * SPX_N); + memcpy(buf3 + SPX_ADDR_BYTES, in3, inblocks * SPX_N); + + haraka_Sx4(out0, out1, out2, out3, SPX_N, + buf0, buf1, buf2, buf3, SPX_ADDR_BYTES + inblocks * SPX_N, + ctx); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/thashx4.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/thashx4.h index cda376e785..64798a3727 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/thashx4.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/thashx4.h @@ -1,25 +1,20 @@ -#ifndef PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_THASHX4_H -#define PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_THASHX4_H +#ifndef SPX_THASHX4_H +#define SPX_THASHX4_H #include -#include "hash_state.h" +#include "context.h" +#include "params.h" -#define thashx4_header(inblocks) \ - void PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_thashx4_##inblocks(unsigned char *out0, \ - unsigned char *out1, \ - unsigned char *out2, \ - unsigned char *out3, \ - const unsigned char *in0, \ - const unsigned char *in1, \ - const unsigned char *in2, \ - const unsigned char *in3, \ - const unsigned char *pub_seed, uint32_t addrx4[4*8], \ - const hash_state *state_seeded) - -thashx4_header(1); -thashx4_header(2); -thashx4_header(WOTS_LEN); -thashx4_header(FORS_TREES); +#define thashx4 SPX_NAMESPACE(thashx4) +void thashx4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addrx4[4 * 8]); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/utils.c b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/utils.c index 18fdf707fa..177b541fb9 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/utils.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/utils.c @@ -1,34 +1,41 @@ -#include #include +#include "utils.h" + #include "address.h" #include "hash.h" -#include "hash_state.h" #include "params.h" #include "thash.h" -#include "utils.h" /** * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. */ -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in) { +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in) { + int i; /* Iterate over out in decreasing order, for big-endianness. */ - for (size_t i = outlen; i > 0; i--) { - out[i - 1] = in & 0xff; + for (i = (signed int)outlen - 1; i >= 0; i--) { + out[i] = in & 0xff; in = in >> 8; } } +void u32_to_bytes(unsigned char *out, uint32_t in) { + out[0] = (unsigned char)(in >> 24); + out[1] = (unsigned char)(in >> 16); + out[2] = (unsigned char)(in >> 8); + out[3] = (unsigned char)in; +} + /** * Converts the inlen bytes in 'in' from big-endian byte order to an integer. */ -unsigned long long PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_bytes_to_ull( - const unsigned char *in, size_t inlen) { +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { unsigned long long retval = 0; + unsigned int i; - for (size_t i = 0; i < inlen; i++) { + for (i = 0; i < inlen; i++) { retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); } return retval; @@ -38,94 +45,80 @@ unsigned long long PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_bytes_to_ull( * Computes a root node given a leaf and an auth path. * Expects address to be complete other than the tree_height and tree_index. */ -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]) { uint32_t i; - unsigned char buffer[2 * PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N]; + unsigned char buffer[2 * SPX_N]; /* If leaf_idx is odd (last bit = 1), current path element is a right child and auth_path has to go left. Otherwise it is the other way around. */ if (leaf_idx & 1) { - memcpy(buffer + PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N, leaf, PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N); + memcpy(buffer + SPX_N, leaf, SPX_N); + memcpy(buffer, auth_path, SPX_N); } else { - memcpy(buffer, leaf, PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N); - memcpy(buffer + PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N, auth_path, PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N); + memcpy(buffer, leaf, SPX_N); + memcpy(buffer + SPX_N, auth_path, SPX_N); } - auth_path += PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N; + auth_path += SPX_N; for (i = 0; i < tree_height - 1; i++) { leaf_idx >>= 1; idx_offset >>= 1; /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_set_tree_height(addr, i + 1); - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_set_tree_index( - addr, leaf_idx + idx_offset); + set_tree_height(addr, i + 1); + set_tree_index(addr, leaf_idx + idx_offset); /* Pick the right or left neighbor, depending on parity of the node. */ if (leaf_idx & 1) { - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_thash_2( - buffer + PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N); + thash(buffer + SPX_N, buffer, 2, ctx, addr); + memcpy(buffer, auth_path, SPX_N); } else { - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_thash_2( - buffer, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer + PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N, auth_path, PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N); + thash(buffer, buffer, 2, ctx, addr); + memcpy(buffer + SPX_N, auth_path, SPX_N); } - auth_path += PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N; + auth_path += SPX_N; } /* The last iteration is exceptional; we do not copy an auth_path node. */ leaf_idx >>= 1; idx_offset >>= 1; - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_set_tree_height(addr, tree_height); - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_set_tree_index( - addr, leaf_idx + idx_offset); - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_thash_2( - root, buffer, pub_seed, addr, hash_state_seeded); + set_tree_height(addr, tree_height); + set_tree_index(addr, leaf_idx + idx_offset); + thash(root, buffer, 2, ctx, addr); } /** * For a given leaf index, computes the authentication path and the resulting * root node using Merkle's TreeHash algorithm. * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_ADDR_TYPE_FORSTREE). + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). * Applies the offset idx_offset to indices before building addresses, so that * it is possible to continue counting indices across trees. */ -static void PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_treehash( - unsigned char *root, unsigned char *auth_path, - unsigned char *stack, unsigned int *heights, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - +void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx * /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]) { + PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); + PQCLEAN_VLA(unsigned int, heights, tree_height + 1); unsigned int offset = 0; uint32_t idx; uint32_t tree_idx; for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { /* Add the next leaf node to the stack. */ - gen_leaf(stack + offset * PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N, - sk_seed, pub_seed, idx + idx_offset, tree_addr, - hash_state_seeded); + gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); offset++; heights[offset - 1] = 0; /* If this is a node we need for the auth path.. */ if ((leaf_idx ^ 0x1) == idx) { - memcpy(auth_path, stack + (offset - 1)*PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N, PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N); + memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); } /* While the top-most nodes are of equal height.. */ @@ -134,66 +127,22 @@ static void PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_treehash( tree_idx = (idx >> (heights[offset - 1] + 1)); /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_set_tree_height( - tree_addr, heights[offset - 1] + 1); - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_set_tree_index( - tree_addr, tree_idx + (idx_offset >> (heights[offset - 1] + 1))); + set_tree_height(tree_addr, heights[offset - 1] + 1); + set_tree_index(tree_addr, + tree_idx + (idx_offset >> (heights[offset - 1] + 1))); /* Hash the top-most nodes from the stack together. */ - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_thash_2( - stack + (offset - 2)*PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N, stack + (offset - 2)*PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N, - pub_seed, tree_addr, hash_state_seeded); + thash(stack + (offset - 2)*SPX_N, + stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); offset--; /* Note that the top-most node is now one layer higher. */ heights[offset - 1]++; /* If this is a node we need for the auth path.. */ if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_path + heights[offset - 1]*PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N, - stack + (offset - 1)*PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N, PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N); + memcpy(auth_path + heights[offset - 1]*SPX_N, + stack + (offset - 1)*SPX_N, SPX_N); } } } - memcpy(root, stack, PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N); -} - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_FORS_HEIGHT + 1)*PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N]; - unsigned int heights[PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_FORS_HEIGHT + 1]; - - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_FORS_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_TREE_HEIGHT + 1)*PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N]; - unsigned int heights[PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_TREE_HEIGHT + 1]; - - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_TREE_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); + memcpy(root, stack, SPX_N); } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/utils.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/utils.h index b9d80c718d..64f5d5a53a 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/utils.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/utils.h @@ -1,64 +1,58 @@ -#ifndef PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_UTILS_H -#define PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_UTILS_H +#ifndef SPX_UTILS_H +#define SPX_UTILS_H -#include "hash_state.h" -#include "params.h" -#include #include +#include "compat.h" +#include "context.h" +#include "params.h" + + +/* To support MSVC use alloca() instead of VLAs. See #20. */ + + /** * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. */ -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in); +#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in); +#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) +void u32_to_bytes(unsigned char *out, uint32_t in); /** * Converts the inlen bytes in 'in' from big-endian byte order to an integer. */ -unsigned long long PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_bytes_to_ull( - const unsigned char *in, size_t inlen); +#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); /** * Computes a root node given a leaf and an auth path. * Expects address to be complete other than the tree_height and tree_index. */ -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); +#define compute_root SPX_NAMESPACE(compute_root) +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]); /** * For a given leaf index, computes the authentication path and the resulting * root node using Merkle's TreeHash algorithm. * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_ADDR_TYPE_FORSTREE). + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). * Applies the offset idx_offset to indices before building addresses, so that * it is possible to continue counting indices across trees. */ -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); +#define treehash SPX_NAMESPACE(treehash) +void treehash(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx *ctx /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]); -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/utilsx4.c b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/utilsx4.c index c0bae15c4e..1638677194 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/utilsx4.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/utilsx4.c @@ -1,98 +1,138 @@ +#include + +#include "utilsx4.h" + #include "address.h" #include "params.h" #include "thashx4.h" #include "utils.h" -#include "utilsx4.h" -#include - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. +/* + * Generate the entire Merkle tree, computing the authentication path for leaf_idx, + * and the resulting root node using Merkle's TreeHash algorithm. * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_ADDR_TYPE_FORSTREE). + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) + * + * This expects tree_addrx4 to be initialized to 4 parallel addr structures for + * the Merkle tree nodes + * * Applies the offset idx_offset to indices before building addresses, so that * it is possible to continue counting indices across trees. + * + * This works by using the standard Merkle tree building algorithm, except + * that each 'node' tracked is actually 4 consecutive nodes in the real tree. + * When we combine two logical nodes ABCD and WXYZ, we perform the H + * operation on adjacent real nodes, forming the parent logical node + * (AB)(CD)(WX)(YZ) + * + * When we get to the top two levels of the real tree (where there is only + * one logical node), we continue this operation two more times; the right + * most real node will by the actual root (and the other 3 nodes will be + * garbage). We follow the same thashx4 logic so that the 'extract + * authentication path components' part of the loop is still executed (and + * to simplify the code somewhat) + * + * This currently assumes tree_height >= 2; I suspect that doing an adjusting + * idx, addr_idx on the gen_leafx4 call if tree_height < 2 would fix it; since + * we don't actually use such short trees, I haven't bothered */ -#define treehashx4_variant(name, tree_height) \ - void PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_treehashx4_##name( \ - unsigned char *rootx4, unsigned char *auth_pathx4, const unsigned char *sk_seed, \ - const unsigned char *pub_seed, const uint32_t leaf_idx[4], uint32_t idx_offset[4], \ - void (*gen_leafx4)(unsigned char * /* leaf0 */, unsigned char * /* leaf1 */, \ - unsigned char * /* leaf2 */, unsigned char * /* leaf3 */, \ - const unsigned char * /* sk_seed */, \ - const unsigned char * /* pub_seed */, uint32_t /* addr_idx0 */, \ - uint32_t /* addr_idx1 */, uint32_t /* addr_idx2 */, \ - uint32_t /* addr_idx3 */, const uint32_t[8] /* tree_addr */, \ - const hash_state * /* state_seeded */), \ - uint32_t tree_addrx4[4 * 8], const hash_state *state_seeded) { \ - unsigned char stackx4[4 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N]; \ - unsigned int heights[(tree_height) + 1]; \ - unsigned int offset = 0; \ - uint32_t idx; \ - uint32_t tree_idx; \ - unsigned int j; \ - \ - for (idx = 0; idx < (uint32_t)(1 << (tree_height)); idx++) { \ - /* Add the next leaf node to the stack. */ \ - gen_leafx4(stackx4 + 0 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N + offset * PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N, \ - stackx4 + 1 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N + offset * PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N, \ - stackx4 + 2 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N + offset * PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N, \ - stackx4 + 3 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N + offset * PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N, sk_seed, \ - pub_seed, idx + idx_offset[0], idx + idx_offset[1], idx + idx_offset[2], \ - idx + idx_offset[3], tree_addrx4, state_seeded); \ - offset++; \ - heights[offset - 1] = 0; \ - \ - /* If this is a node we need for the auth path.. */ \ - for (j = 0; j < 4; j++) { \ - if ((leaf_idx[j] ^ 0x1) == idx) { \ - memcpy(auth_pathx4 + j * (tree_height)*PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N, \ - stackx4 + j * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N + (offset - 1) * PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N, \ - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N); \ - } \ - } \ - \ - /* While the top-most nodes are of equal height.. */ \ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { \ - /* Compute index of the new node, in the next layer. */ \ - tree_idx = (idx >> (heights[offset - 1] + 1)); \ - \ - /* Set the address of the node we're creating. */ \ - for (j = 0; j < 4; j++) { \ - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_set_tree_height(tree_addrx4 + j * 8, heights[offset - 1] + 1); \ - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_set_tree_index(tree_addrx4 + j * 8, \ - tree_idx + (idx_offset[j] >> (heights[offset - 1] + 1))); \ - } \ - /* Hash the top-most nodes from the stack together. */ \ - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_thashx4_2(stackx4 + 0 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N + (offset - 2) * PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N, \ - stackx4 + 1 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N + (offset - 2) * PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N, \ - stackx4 + 2 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N + (offset - 2) * PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N, \ - stackx4 + 3 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N + (offset - 2) * PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N, \ - stackx4 + 0 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N + (offset - 2) * PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N, \ - stackx4 + 1 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N + (offset - 2) * PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N, \ - stackx4 + 2 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N + (offset - 2) * PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N, \ - stackx4 + 3 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N + (offset - 2) * PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N, \ - pub_seed, tree_addrx4, state_seeded); \ - offset--; \ - /* Note that the top-most node is now one layer higher. */ \ - heights[offset - 1]++; \ - \ - /* If this is a node we need for the auth path.. */ \ - for (j = 0; j < 4; j++) { \ - if (((leaf_idx[j] >> heights[offset - 1]) ^ 0x1) == tree_idx) { \ - memcpy(auth_pathx4 + j * (tree_height)*PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N + \ - heights[offset - 1] * PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N, \ - stackx4 + j * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N + (offset - 1) * PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N, \ - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N); \ - } \ - } \ - } \ - } \ - \ - for (j = 0; j < 4; j++) { \ - memcpy(rootx4 + j * PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N, stackx4 + j * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N, PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N); \ - } \ - } +void treehashx4(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, + uint32_t tree_height, + void (*gen_leafx4)( + unsigned char * /* Where to write the leaves */, + const spx_ctx *, + uint32_t idx, void *info), + uint32_t tree_addrx4[4 * 8], + void *info) { + /* This is where we keep the intermediate nodes */ + PQCLEAN_VLA(unsigned char, stackx4, tree_height * 4 * SPX_N); + uint32_t left_adj = 0, prev_left_adj = 0; /* When we're doing the top 3 */ + /* levels, the left-most part of the tree isn't at the beginning */ + /* of current[]. These give the offset of the actual start */ + + uint32_t idx; + uint32_t max_idx = (1U << (tree_height - 2)) - 1; + for (idx = 0;; idx++) { + unsigned char current[4 * SPX_N]; /* Current logical node */ + gen_leafx4( current, ctx, 4 * idx + idx_offset, + info ); -treehashx4_variant(FORS_HEIGHT, PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_FORS_HEIGHT) + /* Now combine the freshly generated right node with previously */ + /* generated left ones */ + uint32_t internal_idx_offset = idx_offset; + uint32_t internal_idx = idx; + uint32_t internal_leaf = leaf_idx; + uint32_t h; /* The height we are in the Merkle tree */ + for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { + + /* Special processing if we're at the top of the tree */ + if (h >= tree_height - 2) { + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[3 * SPX_N], SPX_N ); + return; + } + /* The tree indexing logic is a bit off in this case */ + /* Adjust it so that the left-most node of the part of */ + /* the tree that we're processing has index 0 */ + prev_left_adj = left_adj; + left_adj = 4U - (1 << (tree_height - h - 1)); + } + + /* Check if we hit the top of the tree */ + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[3 * SPX_N], SPX_N ); + return; + } + + /* + * Check if one of the nodes we have is a part of the + * authentication path; if it is, write it out + */ + if ((((internal_idx << 2) ^ internal_leaf) & ~0x3U) == 0) { + memcpy( &auth_path[ h * SPX_N ], + ¤t[(((internal_leaf & 3) ^ 1) + prev_left_adj) * SPX_N], + SPX_N ); + } + + /* + * Check if we're at a left child; if so, stop going up the stack + * Exception: if we've reached the end of the tree, keep on going + * (so we combine the last 4 nodes into the one root node in two + * more iterations) + */ + if ((internal_idx & 1) == 0 && idx < max_idx) { + break; + } + + /* Ok, we're at a right node (or doing the top 3 levels) */ + /* Now combine the left and right logical nodes together */ + + /* Set the address of the node we're creating. */ + unsigned int j; + internal_idx_offset >>= 1; + for (j = 0; j < 4; j++) { + set_tree_height(tree_addrx4 + j * 8, h + 1); + set_tree_index(tree_addrx4 + j * 8, + (4 / 2) * (internal_idx & ~1U) + j - left_adj + internal_idx_offset ); + } + unsigned char *left = &stackx4[h * 4 * SPX_N]; + thashx4( ¤t[0 * SPX_N], + ¤t[1 * SPX_N], + ¤t[2 * SPX_N], + ¤t[3 * SPX_N], + &left [0 * SPX_N], + &left [2 * SPX_N], + ¤t[0 * SPX_N], + ¤t[2 * SPX_N], + 2, ctx, tree_addrx4); + } + + /* We've hit a left child; save the current for when we get the */ + /* corresponding right right */ + memcpy( &stackx4[h * 4 * SPX_N], current, 4 * SPX_N); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/utilsx4.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/utilsx4.h index 009906c4f3..facb874b18 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/utilsx4.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/utilsx4.h @@ -1,38 +1,30 @@ -#ifndef PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_UTILSX4_H -#define PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_UTILSX4_H - -#include "hash_state.h" -#include "params.h" +#ifndef SPX_UTILSX4_H +#define SPX_UTILSX4_H #include +#include "context.h" +#include "params.h" + /** * For a given leaf index, computes the authentication path and the resulting * root node using Merkle's TreeHash algorithm. * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_ADDR_TYPE_FORSTREE). + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). * Applies the offset idx_offset to indices before building addresses, so that * it is possible to continue counting indices across trees. + * + * This implementation uses AVX to compute internal nodes 4 at a time (in + * parallel) */ -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_treehashx4_FORS_HEIGHT(unsigned char *rootx4, - unsigned char *auth_pathx4, - const unsigned char *sk_seed, - const unsigned char *pub_seed, - const uint32_t leaf_idx[4], - uint32_t idx_offset[4], - void (*gen_leafx4)(unsigned char * /* leaf0 */, - unsigned char * /* leaf1 */, - unsigned char * /* leaf2 */, - unsigned char * /* leaf3 */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx0 */, - uint32_t /* addr_idx1 */, - uint32_t /* addr_idx2 */, - uint32_t /* addr_idx3 */, - const uint32_t[8] /* tree_addr */, - const hash_state * /* state_seeded */), - uint32_t tree_addrx4[4 * 8], - const hash_state *state_seeded); +#define treehashx4 SPX_NAMESPACE(treehashx4) +void treehashx4(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leafx4)( + unsigned char * /* Where to write the leaves */, + const spx_ctx * /* ctx */, + uint32_t addr_idx, void *info), + uint32_t tree_addrx4[4 * 8], void *info); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/wots.c b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/wots.c index 5be2d22db6..4d5041ce05 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/wots.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/wots.c @@ -1,106 +1,104 @@ #include #include +#include "wots.h" + #include "address.h" #include "hash.h" -#include "hash_state.h" #include "hashx4.h" #include "params.h" #include "thash.h" #include "thashx4.h" #include "utils.h" -#include "wots.h" +#include "utilsx4.h" +#include "wotsx4.h" // TODO clarify address expectations, and make them more uniform. // TODO i.e. do we expect types to be set already? // TODO and do we expect modifications or copies? /** - * Computes the starting value for a chain, i.e. the secret key. - * Expects the address to be complete up to the chain address. - */ -static void wots_gen_sk(unsigned char *sk, const unsigned char *sk_seed, - uint32_t wots_addr[8], const hash_state *state_seeded) { - /* Make sure that the hash address is actually zeroed. */ - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_set_hash_addr(wots_addr, 0); - - /* Generate sk element. */ - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_prf_addr(sk, sk_seed, wots_addr, state_seeded); -} - -/** - * 4-way parallel version of wots_gen_sk; expects 4x as much space in sk + * Computes up the chains */ -static void wots_gen_skx4(unsigned char *skx4, const unsigned char *sk_seed, - uint32_t wots_addrx4[4 * 8], const hash_state *state_seeded) { - unsigned int j; - - /* Make sure that the hash address is actually zeroed. */ +static void gen_chains( + unsigned char *out, + const unsigned char *in, + unsigned int start[SPX_WOTS_LEN], + const unsigned int steps[SPX_WOTS_LEN], + const spx_ctx *ctx, + uint32_t addr[8]) { + uint32_t i, j, k, idx, watching; + int done; + unsigned char empty[SPX_N]; + unsigned char *bufs[4]; + uint32_t addrs[8 * 4]; + + int l; + uint16_t counts[SPX_WOTS_W] = { 0 }; + uint16_t idxs[SPX_WOTS_LEN]; + uint16_t total, newTotal; + + /* set addrs = {addr, addr, addr, addr} */ for (j = 0; j < 4; j++) { - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_set_hash_addr(wots_addrx4 + j * 8, 0); + memcpy(addrs + j * 8, addr, sizeof(uint32_t) * 8); } - /* Generate sk element. */ - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_prf_addrx4(skx4 + 0 * PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N, - skx4 + 1 * PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N, - skx4 + 2 * PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N, - skx4 + 3 * PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N, - sk_seed, wots_addrx4, - state_seeded); -} - -/** - * Computes the chaining function. - * out and in have to be n-byte arrays. - * - * Interprets in as start-th value of the chain. - * addr has to contain the address of the chain. - */ -static void gen_chain(unsigned char *out, const unsigned char *in, - unsigned int start, unsigned int steps, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *state_seeded) { - uint32_t i; - /* Initialize out with the value at position 'start'. */ - memcpy(out, in, PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N); + memcpy(out, in, SPX_WOTS_LEN * SPX_N); - /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_WOTS_W; i++) { - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_set_hash_addr(addr, i); - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_thash_1(out, out, pub_seed, addr, state_seeded); + /* Sort the chains in reverse order by steps using counting sort. */ + for (i = 0; i < SPX_WOTS_LEN; i++) { + counts[steps[i]]++; + } + total = 0; + for (l = SPX_WOTS_W - 1; l >= 0; l--) { + newTotal = counts[l] + total; + counts[l] = total; + total = newTotal; + } + for (i = 0; i < SPX_WOTS_LEN; i++) { + idxs[counts[steps[i]]] = (uint16_t)i; + counts[steps[i]]++; } -} -/** - * 4-way parallel version of gen_chain; expects 4x as much space in out, and - * 4x as much space in inx4. Assumes start and step identical across chains. - */ -static void gen_chainx4(unsigned char *outx4, const unsigned char *inx4, - unsigned int start, unsigned int steps, - const unsigned char *pub_seed, uint32_t addrx4[4 * 8], - const hash_state *state_seeded) { - uint32_t i; - unsigned int j; + /* We got our work cut out for us: do it! */ + for (i = 0; i < SPX_WOTS_LEN; i += 4) { + for (j = 0; j < 4 && i + j < SPX_WOTS_LEN; j++) { + idx = idxs[i + j]; + set_chain_addr(addrs + j * 8, idx); + bufs[j] = out + SPX_N * idx; + } - /* Initialize outx4 with the value at position 'start'. */ - memcpy(outx4, inx4, 4 * PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N); + /* As the chains are sorted in reverse order, we know that the first + * chain is the longest and the last one is the shortest. We keep + * an eye on whether the last chain is done and then on the one before, + * et cetera. */ + watching = 3; + done = 0; + while (i + watching >= SPX_WOTS_LEN) { + bufs[watching] = &empty[0]; + watching--; + } - /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_WOTS_W; i++) { - for (j = 0; j < 4; j++) { - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_set_hash_addr(addrx4 + j * 8, i); + for (k = 0;; k++) { + while (k == steps[idxs[i + watching]]) { + bufs[watching] = &empty[0]; + if (watching == 0) { + done = 1; + break; + } + watching--; + } + if (done) { + break; + } + for (j = 0; j < watching + 1; j++) { + set_hash_addr(addrs + j * 8, k + start[idxs[i + j]]); + } + + thashx4(bufs[0], bufs[1], bufs[2], bufs[3], + bufs[0], bufs[1], bufs[2], bufs[3], 1, ctx, addrs); } - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_thashx4_1(outx4 + 0 * PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N, - outx4 + 1 * PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N, - outx4 + 2 * PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N, - outx4 + 3 * PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N, - outx4 + 0 * PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N, - outx4 + 1 * PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N, - outx4 + 2 * PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N, - outx4 + 3 * PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N, - pub_seed, addrx4, - state_seeded); } } @@ -109,7 +107,8 @@ static void gen_chainx4(unsigned char *outx4, const unsigned char *inx4, * Interprets an array of bytes as integers in base w. * This only works when log_w is a divisor of 8. */ -static void base_w(unsigned int *output, const int out_len, const unsigned char *input) { +static void base_w(unsigned int *output, const int out_len, + const unsigned char *input) { int in = 0; int out = 0; unsigned char total = 0; @@ -122,119 +121,149 @@ static void base_w(unsigned int *output, const int out_len, const unsigned char in++; bits += 8; } - bits -= PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_WOTS_LOGW; - output[out] = (unsigned int)(total >> bits) & (PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_WOTS_W - 1); + bits -= SPX_WOTS_LOGW; + output[out] = (total >> bits) & (SPX_WOTS_W - 1); out++; } } /* Computes the WOTS+ checksum over a message (in base_w). */ -static void wots_checksum(unsigned int *csum_base_w, const unsigned int *msg_base_w) { +static void wots_checksum(unsigned int *csum_base_w, + const unsigned int *msg_base_w) { unsigned int csum = 0; - unsigned char csum_bytes[(PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_WOTS_LEN2 * PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_WOTS_LOGW + 7) / 8]; + unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; unsigned int i; /* Compute checksum. */ - for (i = 0; i < PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_WOTS_LEN1; i++) { - csum += PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_WOTS_W - 1 - msg_base_w[i]; + for (i = 0; i < SPX_WOTS_LEN1; i++) { + csum += SPX_WOTS_W - 1 - msg_base_w[i]; } /* Convert checksum to base_w. */ /* Make sure expected empty zero bits are the least significant bits. */ - csum = csum << (8 - ((PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_WOTS_LEN2 * PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_WOTS_LOGW) % 8)); - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); - base_w(csum_base_w, PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_WOTS_LEN2, csum_bytes); + csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); + ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); + base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); } /* Takes a message and derives the matching chain lengths. */ -static void chain_lengths(unsigned int *lengths, const unsigned char *msg) { - base_w(lengths, PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_WOTS_LEN1, msg); - wots_checksum(lengths + PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_WOTS_LEN1, lengths); +void chain_lengths(unsigned int *lengths, const unsigned char *msg) { + base_w(lengths, SPX_WOTS_LEN1, msg); + wots_checksum(lengths + SPX_WOTS_LEN1, lengths); } /** - * WOTS key generation. Takes a 32 byte sk_seed, expands it to WOTS private key - * elements and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. * * Writes the computed public key to 'pk'. */ -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_wots_gen_pk(unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *state_seeded) { +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]) { + unsigned int steps[SPX_WOTS_LEN]; + unsigned int start[SPX_WOTS_LEN]; uint32_t i; - unsigned int j; - uint32_t addrx4[4 * 8]; - unsigned char pkbuf[4 * PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N]; + chain_lengths(start, msg); - for (j = 0; j < 4; j++) { - memcpy(addrx4 + j * 8, addr, sizeof(uint32_t) * 8); - } - - /* The last iteration typically does not have complete set of 4 chains, - but because we use pkbuf, this is not an issue -- we still do as many - in parallel as possible. */ - for (i = 0; i < ((PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_WOTS_LEN + 3) & ~0x3); i += 4) { - for (j = 0; j < 4; j++) { - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_set_chain_addr(addrx4 + j * 8, i + j); - } - wots_gen_skx4(pkbuf, sk_seed, addrx4, state_seeded); - gen_chainx4(pkbuf, pkbuf, 0, PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_WOTS_W - 1, pub_seed, addrx4, state_seeded); - for (j = 0; j < 4; j++) { - if (i + j < PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_WOTS_LEN) { - memcpy(pk + (i + j)*PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N, pkbuf + j * PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N, PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N); - } - } + for (i = 0; i < SPX_WOTS_LEN; i++) { + steps[i] = SPX_WOTS_W - 1 - start[i]; } - // Get rid of unused argument variable. - (void)state_seeded; + gen_chains(pk, sig, start, steps, ctx, addr); } -/** - * Takes a n-byte message and the 32-byte sk_see to compute a signature 'sig'. +/* + * This generates 4 sequential WOTS public keys + * It also generates the WOTS signature if leaf_info indicates + * that we're signing with one of these WOTS keys */ -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_wots_sign(unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); +void wots_gen_leafx4(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info) { + struct leaf_info_x4 *info = v_info; + uint32_t *leaf_addr = info->leaf_addr; + uint32_t *pk_addr = info->pk_addr; + unsigned int i, j, k; + unsigned char pk_buffer[ 4 * SPX_WOTS_BYTES ]; + unsigned wots_offset = SPX_WOTS_BYTES; + unsigned char *buffer; + uint32_t wots_k_mask; + unsigned wots_sign_index; + + if (((leaf_idx ^ info->wots_sign_leaf) & ~3U) == 0) { + /* We're traversing the leaf that's signing; generate the WOTS */ + /* signature */ + wots_k_mask = 0; + wots_sign_index = info->wots_sign_leaf & 3; /* Which of of the 4 */ + /* 4 slots do the signatures come from */ + } else { + /* Nope, we're just generating pk's; turn off the signature logic */ + wots_k_mask = (uint32_t)~0; + wots_sign_index = 0; + } - for (i = 0; i < PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_WOTS_LEN; i++) { - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_set_chain_addr(addr, i); - wots_gen_sk(sig + i * PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N, sk_seed, addr, state_seeded); - gen_chain(sig + i * PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N, sig + i * PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N, 0, lengths[i], pub_seed, addr, state_seeded); + for (j = 0; j < 4; j++) { + set_keypair_addr( leaf_addr + j * 8, leaf_idx + j ); + set_keypair_addr( pk_addr + j * 8, leaf_idx + j ); } - // avoid unused argument - (void)state_seeded; -} + for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { + uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k to */ + /* the step if we're generating a signature, ~0 if we're not */ -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_WOTS_LEN]; - uint32_t i; + /* Start with the secret seed */ + for (j = 0; j < 4; j++) { + set_chain_addr(leaf_addr + j * 8, i); + set_hash_addr(leaf_addr + j * 8, 0); + set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTSPRF); + } + prf_addrx4(buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + buffer + 2 * wots_offset, + buffer + 3 * wots_offset, + ctx, leaf_addr); - chain_lengths(lengths, msg); + for (j = 0; j < 4; j++) { + set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTS); + } + + /* Iterate down the WOTS chain */ + for (k = 0;; k++) { + /* Check if one of the values we have needs to be saved as a */ + /* part of the WOTS signature */ + if (k == wots_k) { + memcpy( info->wots_sig + i * SPX_N, + buffer + wots_sign_index * wots_offset, SPX_N ); + } - for (i = 0; i < PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_WOTS_LEN; i++) { - PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_set_chain_addr(addr, i); - gen_chain(pk + i * PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N, sig + i * PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_N, - lengths[i], PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_WOTS_W - 1 - lengths[i], pub_seed, addr, - state_seeded); + /* Check if we hit the top of the chain */ + if (k == SPX_WOTS_W - 1) { + break; + } + + /* Iterate one step on all 4 chains */ + for (j = 0; j < 4; j++) { + set_hash_addr(leaf_addr + j * 8, k); + } + thashx4(buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + buffer + 2 * wots_offset, + buffer + 3 * wots_offset, + buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + buffer + 2 * wots_offset, + buffer + 3 * wots_offset, 1, ctx, leaf_addr); + } } - // avoid unused argument - (void)state_seeded; + /* Do the final thash to generate the public keys */ + thashx4(dest + 0 * SPX_N, + dest + 1 * SPX_N, + dest + 2 * SPX_N, + dest + 3 * SPX_N, + pk_buffer + 0 * wots_offset, + pk_buffer + 1 * wots_offset, + pk_buffer + 2 * wots_offset, + pk_buffer + 3 * wots_offset, SPX_WOTS_LEN, ctx, pk_addr); } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/wots.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/wots.h index a94cadb60f..4e7692eeef 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/wots.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/wots.h @@ -1,41 +1,25 @@ -#ifndef PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_WOTS_H -#define PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_WOTS_H +#ifndef SPX_WOTS_H +#define SPX_WOTS_H -#include "hash_state.h" -#include "params.h" #include -/** - * WOTS key generation. Takes a 32 byte seed for the private key, expands it to - * a full WOTS private key and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_wots_gen_pk( - unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -/** - * Takes a n-byte message and the 32-byte seed for the private key to compute a - * signature that is placed at 'sig'. - */ -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_wots_sign( - unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *hash_state_seeded); +#include "context.h" +#include "params.h" /** * Takes a WOTS signature and an n-byte message, computes a WOTS public key. * * Writes the computed public key to 'pk'. */ -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_wots_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); +#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]); + +/* + * Compute the chain lengths needed for a given message hash + */ +#define chain_lengths SPX_NAMESPACE(chain_lengths) +void chain_lengths(unsigned int *lengths, const unsigned char *msg); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/wotsx4.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/wotsx4.h new file mode 100644 index 0000000000..cd634f1743 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/wotsx4.h @@ -0,0 +1,41 @@ +#ifndef WOTSX4_H_ +#define WOTSX4_H_ + +#include + +#include "params.h" + +/* + * This is here to provide an interface to the internal wots_gen_leafx4 + * routine. While this routine is not referenced in the package outside of + * wots.c, it is called from the stand-alone benchmark code to characterize + * the performance + */ +struct leaf_info_x4 { + unsigned char *wots_sig; + uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ + uint32_t *wots_steps; + uint32_t leaf_addr[4 * 8]; + uint32_t pk_addr[4 * 8]; +}; + +/* Macro to set the leaf_info to something 'benign', that is, it would */ +/* run with the same time as it does during the real signing process */ +/* Used only by the benchmark code */ +#define INITIALIZE_LEAF_INFO_X4(info, addr, step_buffer) { \ + (info).wots_sig = 0; \ + (info).wots_sign_leaf = ~0; \ + (info).wots_steps = step_buffer; \ + int i; \ + for (i=0; i<4; i++) { \ + memcpy( &(info).leaf_addr[8*i], addr, 32 ); \ + memcpy( &(info).pk_addr[8*i], addr, 32 ); \ + } \ + } + +#define wots_gen_leafx4 SPX_NAMESPACE(wots_gen_leafx4) +void wots_gen_leafx4(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info); + +#endif /* WOTSX4_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/address.c b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/address.c index 7c4de6f4f0..d49d9f3b6b 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/address.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/address.c @@ -1,78 +1,95 @@ #include +#include #include "address.h" #include "params.h" #include "utils.h" -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]) { - int i; - - for (i = 0; i < 8; i++) { - PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_ull_to_bytes( - bytes + i * 4, 4, addr[i]); - } -} - -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_set_layer_addr( - uint32_t addr[8], uint32_t layer) { - addr[0] = layer; +/* + * Specify which level of Merkle tree (the "layer") we're working on + */ +void set_layer_addr(uint32_t addr[8], uint32_t layer) { + ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; } -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_set_tree_addr( - uint32_t addr[8], uint64_t tree) { - addr[1] = 0; - addr[2] = (uint32_t) (tree >> 32); - addr[3] = (uint32_t) tree; +/* + * Specify which Merkle tree within the level (the "tree address") we're working on + */ +void set_tree_addr(uint32_t addr[8], uint64_t tree) { + ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); } -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_set_type( - uint32_t addr[8], uint32_t type) { - addr[4] = type; +/* + * Specify the reason we'll use this address structure for, that is, what + * hash will we compute with it. This is used so that unrelated types of + * hashes don't accidentally get the same address structure. The type will be + * one of the SPX_ADDR_TYPE constants + */ +void set_type(uint32_t addr[8], uint32_t type) { + ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; } -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; +/* + * Copy the layer and tree fields of the address structure. This is used + * when we're doing multiple types of hashes within the same Merkle tree + */ +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); } /* These functions are used for OTS addresses. */ -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_set_keypair_addr( - uint32_t addr[8], uint32_t keypair) { - addr[5] = keypair; +/* + * Specify which Merkle leaf we're working on; that is, which OTS keypair + * we're talking about. + */ +void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { + /* We have > 256 OTS at the bottom of the Merkle tree; to specify */ + /* which one, we'd need to express it in two bytes */ + ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR2] = (unsigned char)(keypair >> 8); + ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; } -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; - out[5] = in[5]; +/* + * Copy the layer, tree and keypair fields of the address structure. This is + * used when we're doing multiple things within the same OTS keypair + */ +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); + ((unsigned char *)out)[SPX_OFFSET_KP_ADDR2] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR2]; + ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; } -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_set_chain_addr( - uint32_t addr[8], uint32_t chain) { - addr[6] = chain; +/* + * Specify which Merkle chain within the OTS we're working with + * (the chain address) + */ +void set_chain_addr(uint32_t addr[8], uint32_t chain) { + ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; } -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_set_hash_addr( - uint32_t addr[8], uint32_t hash) { - addr[7] = hash; +/* + * Specify where in the Merkle chain we are +* (the hash address) + */ +void set_hash_addr(uint32_t addr[8], uint32_t hash) { + ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; } /* These functions are used for all hash tree addresses (including FORS). */ -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_set_tree_height( - uint32_t addr[8], uint32_t tree_height) { - addr[6] = tree_height; +/* + * Specify the height of the node in the Merkle/FORS tree we are in + * (the tree height) + */ +void set_tree_height(uint32_t addr[8], uint32_t tree_height) { + ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; } -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_set_tree_index( - uint32_t addr[8], uint32_t tree_index) { - addr[7] = tree_index; +/* + * Specify the distance from the left edge of the node in the Merkle/FORS tree + * (the tree index) + */ +void set_tree_index(uint32_t addr[8], uint32_t tree_index) { + u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/address.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/address.h index 28a1355554..24a84eb40c 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/address.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/address.h @@ -1,50 +1,52 @@ -#ifndef PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_ADDRESS_H -#define PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_ADDRESS_H +#ifndef SPX_ADDRESS_H +#define SPX_ADDRESS_H #include -#define PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_ADDR_TYPE_WOTS 0 -#define PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_ADDR_TYPE_WOTSPK 1 -#define PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_ADDR_TYPE_HASHTREE 2 -#define PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_ADDR_TYPE_FORSTREE 3 -#define PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_ADDR_TYPE_FORSPK 4 +#include "params.h" -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]); +/* The hash types that are passed to set_type */ +#define SPX_ADDR_TYPE_WOTS 0 +#define SPX_ADDR_TYPE_WOTSPK 1 +#define SPX_ADDR_TYPE_HASHTREE 2 +#define SPX_ADDR_TYPE_FORSTREE 3 +#define SPX_ADDR_TYPE_FORSPK 4 +#define SPX_ADDR_TYPE_WOTSPRF 5 +#define SPX_ADDR_TYPE_FORSPRF 6 -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_set_layer_addr( - uint32_t addr[8], uint32_t layer); +#define set_layer_addr SPX_NAMESPACE(set_layer_addr) +void set_layer_addr(uint32_t addr[8], uint32_t layer); -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_set_tree_addr( - uint32_t addr[8], uint64_t tree); +#define set_tree_addr SPX_NAMESPACE(set_tree_addr) +void set_tree_addr(uint32_t addr[8], uint64_t tree); -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_set_type( - uint32_t addr[8], uint32_t type); +#define set_type SPX_NAMESPACE(set_type) +void set_type(uint32_t addr[8], uint32_t type); /* Copies the layer and tree part of one address into the other */ -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]); +#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); /* These functions are used for WOTS and FORS addresses. */ -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_set_keypair_addr( - uint32_t addr[8], uint32_t keypair); +#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) +void set_keypair_addr(uint32_t addr[8], uint32_t keypair); -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_set_chain_addr( - uint32_t addr[8], uint32_t chain); +#define set_chain_addr SPX_NAMESPACE(set_chain_addr) +void set_chain_addr(uint32_t addr[8], uint32_t chain); -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_set_hash_addr( - uint32_t addr[8], uint32_t hash); +#define set_hash_addr SPX_NAMESPACE(set_hash_addr) +void set_hash_addr(uint32_t addr[8], uint32_t hash); -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]); +#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); /* These functions are used for all hash tree addresses (including FORS). */ -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_set_tree_height( - uint32_t addr[8], uint32_t tree_height); +#define set_tree_height SPX_NAMESPACE(set_tree_height) +void set_tree_height(uint32_t addr[8], uint32_t tree_height); -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_set_tree_index( - uint32_t addr[8], uint32_t tree_index); +#define set_tree_index SPX_NAMESPACE(set_tree_index) +void set_tree_index(uint32_t addr[8], uint32_t tree_index); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/api.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/api.h index 679b1c28ec..0942113fbd 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/api.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/api.h @@ -4,15 +4,13 @@ #include #include - - -#define PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_CRYPTO_ALGNAME "SPHINCS+" +#define PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_CRYPTO_ALGNAME "SPHINCS+-haraka-128s-simple" #define PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_CRYPTO_SECRETKEYBYTES 64 #define PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_CRYPTO_PUBLICKEYBYTES 32 -#define PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_CRYPTO_BYTES 7856 -#define PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_CRYPTO_SEEDBYTES 48 +#define PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_CRYPTO_BYTES 7856 +#define PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_CRYPTO_SEEDBYTES 48 /* * Returns the length of a secret key, in bytes @@ -39,43 +37,41 @@ size_t PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_crypto_sign_seedbytes(void); * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] * Format pk: [root || PUB_SEED] */ -int PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed); +int PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); /* * Generates a SPHINCS+ key pair. * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] * Format pk: [root || PUB_SEED] */ -int PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk); +int PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); /** * Returns an array containing a detached signature. */ -int PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk); +int PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); /** * Verifies a detached signature and message under a given public key. */ -int PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk); +int PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, + const uint8_t *pk); /** * Returns an array containing the signature followed by the message. */ -int PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk); +int PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); /** * Verifies a given signature-message pair under a given public key. */ -int PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk); - +int PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/context.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/context.h new file mode 100644 index 0000000000..600dfb73c7 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/context.h @@ -0,0 +1,24 @@ +#ifndef SPX_CONTEXT_H +#define SPX_CONTEXT_H + +#include +#include + +#include "params.h" + +typedef struct { + uint8_t pub_seed[SPX_N]; + uint8_t sk_seed[SPX_N]; + + + uint64_t tweaked512_rc64[10][8]; + uint32_t tweaked256_rc32[10][8]; +} spx_ctx; + +#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) +void initialize_hash_function(spx_ctx *ctx); + +#define free_hash_function SPX_NAMESPACE(free_hash_function) +void free_hash_function(spx_ctx *ctx); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/context_haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/context_haraka.c new file mode 100644 index 0000000000..f1cd7e3664 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/context_haraka.c @@ -0,0 +1,11 @@ +#include "context.h" +#include "haraka.h" + +void initialize_hash_function(spx_ctx *ctx) { + tweak_constants(ctx); +} + +// we don't support heap-based haraka right now +void free_hash_function(spx_ctx *ctx) { + (void)ctx; // suppress unused variable warnings +} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/fors.c b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/fors.c index 5f61d47802..96ca72e986 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/fors.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/fors.c @@ -2,58 +2,58 @@ #include #include -#include "address.h" #include "fors.h" + +#include "address.h" #include "hash.h" -#include "hash_state.h" #include "thash.h" #include "utils.h" +#include "utilsx1.h" -static void fors_gen_sk(unsigned char *sk, const unsigned char *sk_seed, - uint32_t fors_leaf_addr[8], const hash_state *hash_state_seeded) { - PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_prf_addr( - sk, sk_seed, fors_leaf_addr, hash_state_seeded); +static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + prf_addr(sk, ctx, fors_leaf_addr); } static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, - const unsigned char *pub_seed, - uint32_t fors_leaf_addr[8], - const hash_state *hash_state_seeded) { - PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_thash_1( - leaf, sk, pub_seed, fors_leaf_addr, hash_state_seeded); + const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + thash(leaf, sk, 1, ctx, fors_leaf_addr); } -static void fors_gen_leaf(unsigned char *leaf, const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx, const uint32_t fors_tree_addr[8], - const hash_state *hash_state_seeded) { - uint32_t fors_leaf_addr[8] = {0}; - - /* Only copy the parts that must be kept in fors_leaf_addr. */ - PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_copy_keypair_addr( - fors_leaf_addr, fors_tree_addr); - PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_set_type( - fors_leaf_addr, PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_set_tree_index( - fors_leaf_addr, addr_idx); - - fors_gen_sk(leaf, sk_seed, fors_leaf_addr, hash_state_seeded); - fors_sk_to_leaf(leaf, leaf, pub_seed, fors_leaf_addr, hash_state_seeded); +struct fors_gen_leaf_info { + uint32_t leaf_addrx[8]; +}; + +static void fors_gen_leafx1(unsigned char *leaf, + const spx_ctx *ctx, + uint32_t addr_idx, void *info) { + struct fors_gen_leaf_info *fors_info = info; + uint32_t *fors_leaf_addr = fors_info->leaf_addrx; + + /* Only set the parts that the caller doesn't set */ + set_tree_index(fors_leaf_addr, addr_idx); + set_type(fors_leaf_addr, SPX_ADDR_TYPE_FORSPRF); + fors_gen_sk(leaf, ctx, fors_leaf_addr); + + set_type(fors_leaf_addr, SPX_ADDR_TYPE_FORSTREE); + fors_sk_to_leaf(leaf, leaf, + ctx, fors_leaf_addr); } /** - * Interprets m as PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_FORS_HEIGHT-bit unsigned integers. - * Assumes m contains at least PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_FORS_TREES bits. - * Assumes indices has space for PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_FORS_TREES integers. + * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + * Assumes indices has space for SPX_FORS_TREES integers. */ static void message_to_indices(uint32_t *indices, const unsigned char *m) { unsigned int i, j; unsigned int offset = 0; - for (i = 0; i < PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_FORS_TREES; i++) { + for (i = 0; i < SPX_FORS_TREES; i++) { indices[i] = 0; - for (j = 0; j < PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_FORS_HEIGHT; j++) { - indices[i] ^= (((uint32_t)m[offset >> 3] >> (offset & 0x7)) & 0x1) << j; + for (j = 0; j < SPX_FORS_HEIGHT; j++) { + indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); offset++; } } @@ -61,55 +61,51 @@ static void message_to_indices(uint32_t *indices, const unsigned char *m) { /** * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_FORS_TREES bits. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. */ -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_fors_sign( - unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *hash_state_seeded) { - uint32_t indices[PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_FORS_TREES]; - unsigned char roots[PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_FORS_TREES * PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_N]; +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; uint32_t fors_tree_addr[8] = {0}; + struct fors_gen_leaf_info fors_info = {0}; + uint32_t *fors_leaf_addr = fors_info.leaf_addrx; uint32_t fors_pk_addr[8] = {0}; uint32_t idx_offset; unsigned int i; - PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_copy_keypair_addr( - fors_tree_addr, fors_addr); - PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_copy_keypair_addr( - fors_pk_addr, fors_addr); + copy_keypair_addr(fors_tree_addr, fors_addr); + copy_keypair_addr(fors_leaf_addr, fors_addr); - PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_set_type( - fors_tree_addr, PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_set_type( - fors_pk_addr, PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_ADDR_TYPE_FORSPK); + copy_keypair_addr(fors_pk_addr, fors_addr); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); message_to_indices(indices, m); - for (i = 0; i < PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_FORS_TREES; i++) { - idx_offset = i * (1 << PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_FORS_HEIGHT); + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); - PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_set_tree_height( - fors_tree_addr, 0); - PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_set_tree_index( - fors_tree_addr, indices[i] + idx_offset); + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); /* Include the secret key part that produces the selected leaf node. */ - fors_gen_sk(sig, sk_seed, fors_tree_addr, hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_N; + fors_gen_sk(sig, ctx, fors_tree_addr); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + sig += SPX_N; /* Compute the authentication path for this leaf node. */ - PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_treehash_FORS_HEIGHT( - roots + i * PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_N, sig, sk_seed, pub_seed, - indices[i], idx_offset, fors_gen_leaf, fors_tree_addr, - hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_N * PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_FORS_HEIGHT; + treehashx1(roots + i * SPX_N, sig, ctx, + indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx1, + fors_tree_addr, &fors_info); + + sig += SPX_N * SPX_FORS_HEIGHT; } /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_thash_FORS_TREES( - pk, roots, pub_seed, fors_pk_addr, hash_state_seeded); + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); } /** @@ -117,45 +113,44 @@ void PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_fors_sign( * This can be used for verification by comparing to a known public key, or to * subsequently verify a signature on the derived public key. The latter is the * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_FORS_TREES bits. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. */ -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_fors_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, const uint32_t fors_addr[8], - const hash_state *hash_state_seeded) { - uint32_t indices[PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_FORS_TREES]; - unsigned char roots[PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_FORS_TREES * PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_N]; - unsigned char leaf[PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_N]; +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + unsigned char leaf[SPX_N]; uint32_t fors_tree_addr[8] = {0}; uint32_t fors_pk_addr[8] = {0}; uint32_t idx_offset; unsigned int i; - PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_copy_keypair_addr(fors_tree_addr, fors_addr); - PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_copy_keypair_addr(fors_pk_addr, fors_addr); + copy_keypair_addr(fors_tree_addr, fors_addr); + copy_keypair_addr(fors_pk_addr, fors_addr); - PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_set_type(fors_tree_addr, PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_set_type(fors_pk_addr, PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_ADDR_TYPE_FORSPK); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); message_to_indices(indices, m); - for (i = 0; i < PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_FORS_TREES; i++) { - idx_offset = i * (1 << PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_FORS_HEIGHT); + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); - PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_set_tree_height(fors_tree_addr, 0); - PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_set_tree_index(fors_tree_addr, indices[i] + idx_offset); + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); /* Derive the leaf from the included secret key part. */ - fors_sk_to_leaf(leaf, sig, pub_seed, fors_tree_addr, hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_N; + fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); + sig += SPX_N; /* Derive the corresponding root node of this tree. */ - PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_compute_root(roots + i * PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_N, leaf, indices[i], idx_offset, sig, - PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_FORS_HEIGHT, pub_seed, fors_tree_addr, hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_N * PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_FORS_HEIGHT; + compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, + sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); + sig += SPX_N * SPX_FORS_HEIGHT; } /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_thash_FORS_TREES(pk, roots, pub_seed, fors_pk_addr, hash_state_seeded); + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/fors.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/fors.h index 8d988d4aec..509140a178 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/fors.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/fors.h @@ -1,32 +1,32 @@ -#ifndef PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_FORS_H -#define PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_FORS_H +#ifndef SPX_FORS_H +#define SPX_FORS_H #include -#include "hash_state.h" +#include "context.h" #include "params.h" /** * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_FORS_TREES bits. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. */ -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_fors_sign( - unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *hash_state_seeded); +#define fors_sign SPX_NAMESPACE(fors_sign) +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); /** * Derives the FORS public key from a signature. * This can be used for verification by comparing to a known public key, or to * subsequently verify a signature on the derived public key. The latter is the * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_FORS_TREES bits. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. */ -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_fors_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, const uint32_t fors_addr[8], - const hash_state *hash_state_seeded); +#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/haraka.c index f1531dd6a6..a4944913b5 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/haraka.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/haraka.c @@ -6,12 +6,13 @@ * by Thomas Pornin */ -#include #include +#include #include #include #include "haraka.h" +#include "utils.h" #define HARAKAS_RATE 32 @@ -656,76 +657,62 @@ static void interleave_constant32(uint32_t *out, const unsigned char *in) { br_aes_ct_ortho(out); } -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_tweak_constants( - harakactx *state, - const unsigned char *pk_seed, const unsigned char *sk_seed, - unsigned long long seed_length) { +void tweak_constants(spx_ctx *ctx) { unsigned char buf[40 * 16]; int i; /* Use the standard constants to generate tweaked ones. */ - memcpy((uint8_t *)state->tweaked512_rc64, (uint8_t *)haraka512_rc64, 40 * 16); - - /* Constants for sk.seed */ - if (sk_seed != NULL) { - PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_haraka_S( - buf, 40 * 16, sk_seed, seed_length, state); - - /* Interleave constants */ - for (i = 0; i < 10; i++) { - interleave_constant32(state->tweaked256_rc32_sseed[i], buf + 32 * i); - } - } + memcpy((uint8_t *)ctx->tweaked512_rc64, (uint8_t *)haraka512_rc64, 40 * 16); /* Constants for pk.seed */ - PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_haraka_S( - buf, 40 * 16, pk_seed, seed_length, state); + haraka_S(buf, 40 * 16, ctx->pub_seed, SPX_N, ctx); for (i = 0; i < 10; i++) { - interleave_constant32(state->tweaked256_rc32[i], buf + 32 * i); - interleave_constant(state->tweaked512_rc64[i], buf + 64 * i); + interleave_constant32(ctx->tweaked256_rc32[i], buf + 32 * i); + interleave_constant(ctx->tweaked512_rc64[i], buf + 64 * i); } } -static void haraka_S_absorb(unsigned char *s, +static void haraka_S_absorb(unsigned char *s, unsigned int r, const unsigned char *m, unsigned long long mlen, - unsigned char p, const harakactx *state) { + unsigned char p, const spx_ctx *ctx) { unsigned long long i; - unsigned char t[HARAKAS_RATE]; + PQCLEAN_VLA(uint8_t, t, r); - while (mlen >= HARAKAS_RATE) { + while (mlen >= r) { /* XOR block to state */ - for (i = 0; i < HARAKAS_RATE; ++i) { + for (i = 0; i < r; ++i) { s[i] ^= m[i]; } - PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_haraka512_perm(s, s, state); - mlen -= HARAKAS_RATE; - m += HARAKAS_RATE; + haraka512_perm(s, s, ctx); + mlen -= r; + m += r; } - for (i = 0; i < HARAKAS_RATE; ++i) { + for (i = 0; i < r; ++i) { t[i] = 0; } for (i = 0; i < mlen; ++i) { t[i] = m[i]; } t[i] = p; - t[HARAKAS_RATE - 1] |= 128; - for (i = 0; i < HARAKAS_RATE; ++i) { + t[r - 1] |= 128; + for (i = 0; i < r; ++i) { s[i] ^= t[i]; } } static void haraka_S_squeezeblocks(unsigned char *h, unsigned long long nblocks, - unsigned char *s, const harakactx *state) { + unsigned char *s, unsigned int r, + const spx_ctx *ctx) { while (nblocks > 0) { - PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_haraka512_perm(s, s, state); + haraka512_perm(s, s, ctx); memcpy(h, s, HARAKAS_RATE); - h += HARAKAS_RATE; + h += r; nblocks--; } } -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_haraka_S_inc_init(uint8_t *s_inc) { +void haraka_S_inc_init(uint8_t *s_inc) { size_t i; for (i = 0; i < 64; i++) { @@ -734,7 +721,8 @@ void PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_haraka_S_inc_init(uint8_t *s_inc) { s_inc[64] = 0; } -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, const harakactx *state) { +void haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, + const spx_ctx *ctx) { size_t i; /* Recall that s_inc[64] is the non-absorbed bytes xored into the state */ @@ -745,19 +733,19 @@ void PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_haraka_S_inc_absorb(uint8_t *s_inc, c s_inc[s_inc[64] + i] ^= m[i]; } mlen -= (size_t)(HARAKAS_RATE - s_inc[64]); - m += HARAKAS_RATE - s_inc[64]; + m += HARAKAS_RATE - (uint8_t)s_inc[64]; s_inc[64] = 0; - PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_haraka512_perm(s_inc, s_inc, state); + haraka512_perm(s_inc, s_inc, ctx); } for (i = 0; i < mlen; i++) { s_inc[s_inc[64] + i] ^= m[i]; } - s_inc[64] = (uint8_t)(mlen + s_inc[64]); + s_inc[64] += (uint8_t)mlen; } -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_haraka_S_inc_finalize(uint8_t *s_inc) { +void haraka_S_inc_finalize(uint8_t *s_inc) { /* After haraka_S_inc_absorb, we are guaranteed that s_inc[64] < HARAKAS_RATE, so we can always use one more byte for p in the current state. */ s_inc[s_inc[64]] ^= 0x1F; @@ -765,22 +753,23 @@ void PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_haraka_S_inc_finalize(uint8_t *s_inc) s_inc[64] = 0; } -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, const harakactx *state) { - uint8_t i; +void haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, + const spx_ctx *ctx) { + size_t i; /* First consume any bytes we still have sitting around */ for (i = 0; i < outlen && i < s_inc[64]; i++) { /* There are s_inc[64] bytes left, so r - s_inc[64] is the first available byte. We consume from there, i.e., up to r. */ - out[i] = s_inc[(HARAKAS_RATE - s_inc[64] + i)]; + out[i] = (uint8_t)s_inc[(HARAKAS_RATE - s_inc[64] + i)]; } out += i; outlen -= i; - s_inc[64] = (uint8_t)(s_inc[64] - i); + s_inc[64] -= (uint8_t)i; /* Then squeeze the remaining necessary blocks */ while (outlen > 0) { - PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_haraka512_perm(s_inc, s_inc, state); + haraka512_perm(s_inc, s_inc, ctx); for (i = 0; i < outlen && i < HARAKAS_RATE; i++) { out[i] = s_inc[i]; @@ -791,7 +780,9 @@ void PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_haraka_S_inc_squeeze(uint8_t *out, si } } -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_haraka_S(unsigned char *out, unsigned long long outlen, const unsigned char *in, unsigned long long inlen, const harakactx *state) { +void haraka_S(unsigned char *out, unsigned long long outlen, + const unsigned char *in, unsigned long long inlen, + const spx_ctx *ctx) { unsigned long long i; unsigned char s[64]; unsigned char d[32]; @@ -799,20 +790,21 @@ void PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_haraka_S(unsigned char *out, unsigned for (i = 0; i < 64; i++) { s[i] = 0; } - haraka_S_absorb(s, in, inlen, 0x1F, state); + haraka_S_absorb(s, 32, in, inlen, 0x1F, ctx); - haraka_S_squeezeblocks(out, outlen / 32, s, state); + haraka_S_squeezeblocks(out, outlen / 32, s, 32, ctx); out += (outlen / 32) * 32; if (outlen % 32) { - haraka_S_squeezeblocks(d, 1, s, state); + haraka_S_squeezeblocks(d, 1, s, 32, ctx); for (i = 0; i < outlen % 32; i++) { out[i] = d[i]; } } } -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_haraka512_perm(unsigned char *out, const unsigned char *in, const harakactx *state) { +void haraka512_perm(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx) { uint32_t w[16]; uint64_t q[8], tmp_q; unsigned int i, j; @@ -829,7 +821,7 @@ void PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_haraka512_perm(unsigned char *out, co br_aes_ct64_bitslice_Sbox(q); shift_rows(q); mix_columns(q); - add_round_key(q, state->tweaked512_rc64[2 * i + j]); + add_round_key(q, ctx->tweaked512_rc64[2 * i + j]); } /* Mix states */ for (j = 0; j < 8; j++) { @@ -857,12 +849,12 @@ void PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_haraka512_perm(unsigned char *out, co br_range_enc32le(out, w, 16); } -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_haraka512(unsigned char *out, const unsigned char *in, const harakactx *state) { +void haraka512(unsigned char *out, const unsigned char *in, const spx_ctx *ctx) { int i; unsigned char buf[64]; - PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_haraka512_perm(buf, in, state); + haraka512_perm(buf, in, ctx); /* Feed-forward */ for (i = 0; i < 64; i++) { buf[i] = buf[i] ^ in[i]; @@ -876,50 +868,8 @@ void PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_haraka512(unsigned char *out, const u } -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_haraka256(unsigned char *out, const unsigned char *in, const harakactx *state) { - uint32_t q[8], tmp_q; - int i, j; - - for (i = 0; i < 4; i++) { - q[2 * i] = br_dec32le(in + 4 * i); - q[2 * i + 1] = br_dec32le(in + 4 * i + 16); - } - br_aes_ct_ortho(q); - - /* AES rounds */ - for (i = 0; i < 5; i++) { - for (j = 0; j < 2; j++) { - br_aes_ct_bitslice_Sbox(q); - shift_rows32(q); - mix_columns32(q); - add_round_key32(q, state->tweaked256_rc32[2 * i + j]); - } - - /* Mix states */ - for (j = 0; j < 8; j++) { - tmp_q = q[j]; - q[j] = (tmp_q & 0x81818181) | - (tmp_q & 0x02020202) << 1 | - (tmp_q & 0x04040404) << 2 | - (tmp_q & 0x08080808) << 3 | - (tmp_q & 0x10101010) >> 3 | - (tmp_q & 0x20202020) >> 2 | - (tmp_q & 0x40404040) >> 1; - } - } - - br_aes_ct_ortho(q); - for (i = 0; i < 4; i++) { - br_enc32le(out + 4 * i, q[2 * i]); - br_enc32le(out + 4 * i + 16, q[2 * i + 1]); - } - - for (i = 0; i < 32; i++) { - out[i] ^= in[i]; - } -} - -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_haraka256_sk(unsigned char *out, const unsigned char *in, const harakactx *state) { +void haraka256(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx) { uint32_t q[8], tmp_q; int i, j; @@ -935,7 +885,7 @@ void PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_haraka256_sk(unsigned char *out, cons br_aes_ct_bitslice_Sbox(q); shift_rows32(q); mix_columns32(q); - add_round_key32(q, state->tweaked256_rc32_sseed[2 * i + j]); + add_round_key32(q, ctx->tweaked256_rc32[2 * i + j]); } /* Mix states */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/haraka.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/haraka.h index a740b00903..737cb6065f 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/haraka.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/haraka.h @@ -1,40 +1,42 @@ -#ifndef PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_HARAKA_H -#define PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_HARAKA_H +#ifndef SPX_HARAKA_H +#define SPX_HARAKA_H -#include -#include - -typedef struct { - uint64_t tweaked512_rc64[10][8]; - uint32_t tweaked256_rc32[10][8]; - uint32_t tweaked256_rc32_sseed[10][8]; -} harakactx; +#include "context.h" +#include "params.h" /* Tweak constants with seed */ -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_tweak_constants( - harakactx *state, - const unsigned char *pk_seed, const unsigned char *sk_seed, - unsigned long long seed_length); +#define tweak_constants SPX_NAMESPACE(tweak_constants) +void tweak_constants(spx_ctx *ctx); /* Haraka Sponge */ -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_haraka_S_inc_init(uint8_t *s_inc); -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, const harakactx *state); -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_haraka_S_inc_finalize(uint8_t *s_inc); -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, const harakactx *state); -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_haraka_S( - unsigned char *out, unsigned long long outlen, - const unsigned char *in, unsigned long long inlen, const harakactx *state); +#define haraka_S_inc_init SPX_NAMESPACE(haraka_S_inc_init) +void haraka_S_inc_init(uint8_t *s_inc); +#define haraka_S_inc_absorb SPX_NAMESPACE(haraka_S_inc_absorb) +void haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, + const spx_ctx *ctx); +#define haraka_S_inc_finalize SPX_NAMESPACE(haraka_S_inc_finalize) +void haraka_S_inc_finalize(uint8_t *s_inc); +#define haraka_S_inc_squeeze SPX_NAMESPACE(haraka_S_inc_squeeze) +void haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, + const spx_ctx *ctx); +#define haraka_S SPX_NAMESPACE(haraka_S) +void haraka_S(unsigned char *out, unsigned long long outlen, + const unsigned char *in, unsigned long long inlen, + const spx_ctx *ctx); /* Applies the 512-bit Haraka permutation to in. */ -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_haraka512_perm(unsigned char *out, const unsigned char *in, const harakactx *state); +#define haraka512_perm SPX_NAMESPACE(haraka512_perm) +void haraka512_perm(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx); /* Implementation of Haraka-512 */ -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_haraka512(unsigned char *out, const unsigned char *in, const harakactx *state); +#define haraka512 SPX_NAMESPACE(haraka512) +void haraka512(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx); /* Implementation of Haraka-256 */ -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_haraka256(unsigned char *out, const unsigned char *in, const harakactx *state); - -/* Implementation of Haraka-256 using sk.seed constants */ -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_haraka256_sk(unsigned char *out, const unsigned char *in, const harakactx *state); +#define haraka256 SPX_NAMESPACE(haraka256) +void haraka256(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/haraka_offsets.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/haraka_offsets.h new file mode 100644 index 0000000000..7c062272a0 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/haraka_offsets.h @@ -0,0 +1,21 @@ +#ifndef HARAKA_OFFSETS_H_ +#define HARAKA_OFFSETS_H_ + +/* + * Offsets of various fields in the address structure when we use Haraka as + * the Sphincs+ hash function + */ + +#define SPX_OFFSET_LAYER 3 /* The byte used to specify the Merkle tree layer */ +#define SPX_OFFSET_TREE 8 /* The start of the 8 byte field used to specify the tree */ +#define SPX_OFFSET_TYPE 19 /* The byte used to specify the hash type (reason) */ +#define SPX_OFFSET_KP_ADDR2 22 /* The high byte used to specify the key pair (which one-time signature) */ +#define SPX_OFFSET_KP_ADDR1 23 /* The low byte used to specify the key pair */ +#define SPX_OFFSET_CHAIN_ADDR 27 /* The byte used to specify the chain address (which Winternitz chain) */ +#define SPX_OFFSET_HASH_ADDR 31 /* The byte used to specify the hash address (where in the Winternitz chain) */ +#define SPX_OFFSET_TREE_HGT 27 /* The byte used to specify the height of this node in the FORS or Merkle tree */ +#define SPX_OFFSET_TREE_INDEX 28 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ + +#define SPX_HARAKA 1 + +#endif /* HARAKA_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/hash.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/hash.h index f50e7bf2eb..f7c87d4c3c 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/hash.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/hash.h @@ -1,31 +1,28 @@ -#ifndef PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_HASH_H -#define PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_HASH_H - -#include "hash_state.h" +#ifndef SPX_HASH_H +#define SPX_HASH_H #include #include -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_initialize_hash_function( - hash_state *hash_state_seeded, - const unsigned char *pub_seed, const unsigned char *sk_seed); +#include "context.h" +#include "params.h" + +#define prf_addr SPX_NAMESPACE(prf_addr) +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]); -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_destroy_hash_function(hash_state *hash_state_seeded); +#define gen_message_random SPX_NAMESPACE(gen_message_random) +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded); +#define hash_message SPX_NAMESPACE(hash_message) +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/hash_haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/hash_haraka.c index 325a72ea11..750a67423b 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/hash_haraka.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/hash_haraka.c @@ -2,58 +2,44 @@ #include #include "address.h" -#include "haraka.h" -#include "hash.h" #include "params.h" #include "utils.h" -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_initialize_hash_function( - hash_state *hash_state_seeded, - const unsigned char *pub_seed, const unsigned char *sk_seed) { - PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_tweak_constants(hash_state_seeded, pub_seed, sk_seed, PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_N); -} - -/* The haraka implementation is stack based and won't be replaced in PQClean/OQS, - so we don't need to do anything */ -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_destroy_hash_function( - hash_state *hash_state_seeded) { // NOLINT(readability-non-const-parameter) - (void)hash_state_seeded; -} +#include "haraka.h" +#include "hash.h" /* - * Computes PRF(key, addr), given a secret key of PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_N bytes and an address + * Computes PRF(key, addr), given a secret key of SPX_N bytes and an address */ -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded) { - unsigned char buf[PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_ADDR_BYTES]; - /* Since PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_N may be smaller than 32, we need a temporary buffer. */ +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]) { + /* Since SPX_N may be smaller than 32, we need temporary buffers. */ unsigned char outbuf[32]; + unsigned char buf[64] = {0}; - (void)key; /* Suppress an 'unused parameter' warning. */ + memcpy(buf, addr, SPX_ADDR_BYTES); + memcpy(buf + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); - PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_addr_to_bytes(buf, addr); - PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_haraka256_sk(outbuf, buf, hash_state_seeded); - memcpy(out, outbuf, PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_N); + haraka512(outbuf, (const void *)buf, ctx); + memcpy(out, outbuf, SPX_N); } /** * Computes the message-dependent randomness R, using a secret seed and an * optional randomization value as well as the message. */ -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded) { +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { uint8_t s_inc[65]; - PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_haraka_S_inc_init(s_inc); - PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_haraka_S_inc_absorb(s_inc, sk_prf, PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_N, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_haraka_S_inc_absorb(s_inc, optrand, PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_N, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_haraka_S_inc_absorb(s_inc, m, mlen, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_haraka_S_inc_finalize(s_inc); - PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_haraka_S_inc_squeeze(R, PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_N, s_inc, hash_state_seeded); + haraka_S_inc_init(s_inc); + haraka_S_inc_absorb(s_inc, sk_prf, SPX_N, ctx); + haraka_S_inc_absorb(s_inc, optrand, SPX_N, ctx); + haraka_S_inc_absorb(s_inc, m, mlen, ctx); + haraka_S_inc_finalize(s_inc); + haraka_S_inc_squeeze(R, SPX_N, s_inc, ctx); } /** @@ -61,36 +47,35 @@ void PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_gen_message_random( * Outputs the message digest and the index of the leaf. The index is split in * the tree index and the leaf index, for convenient copying to an address. */ -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded) { -#define PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_TREE_BITS (PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_TREE_HEIGHT * (PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_D - 1)) -#define PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_TREE_BYTES ((PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_TREE_BITS + 7) / 8) -#define PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_LEAF_BITS PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_TREE_HEIGHT -#define PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_LEAF_BYTES ((PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_LEAF_BITS + 7) / 8) -#define PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_DGST_BYTES (PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_FORS_MSG_BYTES + PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_TREE_BYTES + PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_LEAF_BYTES) +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { +#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) +#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) +#define SPX_LEAF_BITS SPX_TREE_HEIGHT +#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) +#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) - unsigned char buf[PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_DGST_BYTES]; + unsigned char buf[SPX_DGST_BYTES]; unsigned char *bufp = buf; uint8_t s_inc[65]; - PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_haraka_S_inc_init(s_inc); - PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_haraka_S_inc_absorb(s_inc, R, PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_N, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_haraka_S_inc_absorb(s_inc, pk + PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_N, PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_N, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_haraka_S_inc_absorb(s_inc, m, mlen, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_haraka_S_inc_finalize(s_inc); - PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_haraka_S_inc_squeeze(buf, PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_DGST_BYTES, s_inc, hash_state_seeded); + haraka_S_inc_init(s_inc); + haraka_S_inc_absorb(s_inc, R, SPX_N, ctx); + haraka_S_inc_absorb(s_inc, pk + SPX_N, SPX_N, ctx); // Only absorb root part of pk + haraka_S_inc_absorb(s_inc, m, mlen, ctx); + haraka_S_inc_finalize(s_inc); + haraka_S_inc_squeeze(buf, SPX_DGST_BYTES, s_inc, ctx); + + memcpy(digest, bufp, SPX_FORS_MSG_BYTES); + bufp += SPX_FORS_MSG_BYTES; - memcpy(digest, bufp, PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_FORS_MSG_BYTES); - bufp += PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_FORS_MSG_BYTES; - *tree = PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_bytes_to_ull(bufp, PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_TREE_BYTES); - *tree &= (~(uint64_t)0) >> (64 - PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_TREE_BITS); - bufp += PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_TREE_BYTES; + *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); + *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); + bufp += SPX_TREE_BYTES; - *leaf_idx = (uint32_t)PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_bytes_to_ull( - bufp, PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_LEAF_BYTES); - *leaf_idx &= (~(uint32_t)0) >> (32 - PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_LEAF_BITS); + *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); + *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/hash_state.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/hash_state.h deleted file mode 100644 index 5adb1d9a22..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/hash_state.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef SPX_HASH_STATE_H -#define SPX_HASH_STATE_H - -/** - * Defines the type of the hash function state. - * - * Don't be fooled into thinking this instance of SPHINCS+ isn't stateless! - * - * From Section 7.2.2 from the SPHINCS+ round-2 specification: - * - * Each of the instances of the tweakable hash function take PK.seed as its - * first input, which is constant for a given key pair – and, thus, across - * a single signature. This leads to a lot of redundant computation. To remedy - * this, we pad PK.seed to the length of a full 64-byte SHA-256 input block. - * Because of the Merkle-DamgÃ¥rd construction that underlies SHA-256, this - * allows for reuse of the intermediate SHA-256 state after the initial call to - * the compression function which improves performance. - * - * We pass this hash state around in functions, because otherwise we need to - * have a global variable. - */ - -#include "haraka.h" -#define hash_state harakactx - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/merkle.c b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/merkle.c new file mode 100644 index 0000000000..0c1479fd93 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/merkle.c @@ -0,0 +1,59 @@ +#include +#include + +#include "address.h" +#include "merkle.h" +#include "params.h" +#include "utils.h" +#include "utilsx1.h" +#include "wots.h" +#include "wotsx1.h" + +/* + * This generates a Merkle signature (WOTS signature followed by the Merkle + * authentication path). This is in this file because most of the complexity + * is involved with the WOTS signature; the Merkle authentication path logic + * is mostly hidden in treehashx4 + */ +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf) { + unsigned char *auth_path = sig + SPX_WOTS_BYTES; + struct leaf_info_x1 info = { 0 }; + unsigned steps[ SPX_WOTS_LEN ]; + + info.wots_sig = sig; + chain_lengths(steps, root); + info.wots_steps = steps; + + set_type(&tree_addr[0], SPX_ADDR_TYPE_HASHTREE); + set_type(&info.pk_addr[0], SPX_ADDR_TYPE_WOTSPK); + copy_subtree_addr(&info.leaf_addr[0], wots_addr); + copy_subtree_addr(&info.pk_addr[0], wots_addr); + + info.wots_sign_leaf = idx_leaf; + + treehashx1(root, auth_path, ctx, + idx_leaf, 0, + SPX_TREE_HEIGHT, + wots_gen_leafx1, + tree_addr, &info); +} + +/* Compute root node of the top-most subtree. */ +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { + /* We do not need the auth path in key generation, but it simplifies the + code to have just one treehash routine that computes both root and path + in one function. */ + unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; + uint32_t top_tree_addr[8] = {0}; + uint32_t wots_addr[8] = {0}; + + set_layer_addr(top_tree_addr, SPX_D - 1); + set_layer_addr(wots_addr, SPX_D - 1); + + merkle_sign(auth_path, root, ctx, + wots_addr, top_tree_addr, + (uint32_t)~0 /* ~0 means "don't bother generating an auth path */ ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/merkle.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/merkle.h new file mode 100644 index 0000000000..769cf2e970 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/merkle.h @@ -0,0 +1,21 @@ +#ifndef MERKLE_H_ +#define MERKLE_H_ + +#include + +#include "context.h" +#include "params.h" + +/* Generate a Merkle signature (WOTS signature followed by the Merkle */ +/* authentication path) */ +#define merkle_sign SPX_NAMESPACE(merkle_sign) +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf); + +/* Compute the root node of the top-most subtree. */ +#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); + +#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/nistapi.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/nistapi.h new file mode 100644 index 0000000000..3cb71afad4 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/nistapi.h @@ -0,0 +1,87 @@ +#ifndef SPX_API_H +#define SPX_API_H + +#include +#include + +#include "params.h" + +#define CRYPTO_ALGNAME "SPHINCS+" + +#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES +#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES +#define CRYPTO_BYTES SPX_BYTES +#define CRYPTO_SEEDBYTES (3*SPX_N) + +/* + * Returns the length of a secret key, in bytes + */ +#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) +size_t crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) +size_t crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) +size_t crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) +size_t crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +#define crypto_sign SPX_NAMESPACE(crypto_sign) +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/params.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/params.h index 7130d0a7cd..be1249e8af 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/params.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/params.h @@ -1,53 +1,56 @@ -#ifndef PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_PARAMS_H -#define PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_PARAMS_H +#ifndef SPX_PARAMS_H +#define SPX_PARAMS_H + +#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_##s /* Hash output length in bytes. */ -#define PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_N 16 +#define SPX_N 16 /* Height of the hypertree. */ -#define PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_FULL_HEIGHT 63 +#define SPX_FULL_HEIGHT 63 /* Number of subtree layer. */ -#define PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_D 7 +#define SPX_D 7 /* FORS tree dimensions. */ -#define PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_FORS_HEIGHT 12 -#define PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_FORS_TREES 14 +#define SPX_FORS_HEIGHT 12 +#define SPX_FORS_TREES 14 /* Winternitz parameter, */ -#define PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_WOTS_W 16 +#define SPX_WOTS_W 16 /* The hash function is defined by linking a different hash.c file, as opposed to setting a #define constant. */ /* For clarity */ -#define PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_ADDR_BYTES 32 +#define SPX_ADDR_BYTES 32 /* WOTS parameters. */ -#define PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_WOTS_LOGW 4 +#define SPX_WOTS_LOGW 4 -#define PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_WOTS_LEN1 (8 * PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_N / PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_WOTS_LOGW) +#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) -/* PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#define PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_WOTS_LEN2 3 +/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ +#define SPX_WOTS_LEN2 3 -#define PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_WOTS_LEN (PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_WOTS_LEN1 + PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_WOTS_LEN2) -#define PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_WOTS_BYTES (PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_WOTS_LEN * PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_N) -#define PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_WOTS_PK_BYTES PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_WOTS_BYTES +#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) +#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) +#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES /* Subtree size. */ -#define PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_TREE_HEIGHT (PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_FULL_HEIGHT / PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_D) +#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) + +//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT +// #error SPX_D should always divide SPX_FULL_HEIGHT +//#endif /* FORS parameters. */ -#define PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_FORS_MSG_BYTES ((PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_FORS_TREES + 7) / 8) -#define PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_FORS_BYTES ((PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_FORS_HEIGHT + 1) * PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_FORS_TREES * PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_N) -#define PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_FORS_PK_BYTES PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_N +#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) +#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) +#define SPX_FORS_PK_BYTES SPX_N /* Resulting SPX sizes. */ -#define PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_BYTES (PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_N + PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_FORS_BYTES + PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_D * PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_WOTS_BYTES +\ - PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_FULL_HEIGHT * PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_N) -#define PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_PK_BYTES (2 * PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_N) -#define PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_SK_BYTES (2 * PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_N + PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_PK_BYTES) - -/* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ -#define PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_OPTRAND_BYTES 32 +#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ + SPX_FULL_HEIGHT * SPX_N) +#define SPX_PK_BYTES (2 * SPX_N) +#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) + +#include "haraka_offsets.h" #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/sign.c b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/sign.c index 89225a1d70..9d0c7d1b22 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/sign.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/sign.c @@ -3,72 +3,43 @@ #include #include "address.h" -#include "api.h" +#include "context.h" #include "fors.h" #include "hash.h" -#include "hash_state.h" +#include "merkle.h" +#include "nistapi.h" #include "params.h" #include "randombytes.h" #include "thash.h" #include "utils.h" #include "wots.h" -/** - * Computes the leaf at a given address. First generates the WOTS key pair, - * then computes leaf by hashing horizontally. - */ -static void wots_gen_leaf(unsigned char *leaf, const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx, const uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - unsigned char pk[PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_WOTS_BYTES]; - uint32_t wots_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_set_type( - wots_addr, PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_set_type( - wots_pk_addr, PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_ADDR_TYPE_WOTSPK); - - PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_set_keypair_addr( - wots_addr, addr_idx); - PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_wots_gen_pk( - pk, sk_seed, pub_seed, wots_addr, hash_state_seeded); - - PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_copy_keypair_addr( - wots_pk_addr, wots_addr); - PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_thash_WOTS_LEN( - leaf, pk, pub_seed, wots_pk_addr, hash_state_seeded); -} - /* * Returns the length of a secret key, in bytes */ -size_t PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_crypto_sign_secretkeybytes(void) { - return PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_CRYPTO_SECRETKEYBYTES; +size_t crypto_sign_secretkeybytes(void) { + return CRYPTO_SECRETKEYBYTES; } /* * Returns the length of a public key, in bytes */ -size_t PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_crypto_sign_publickeybytes(void) { - return PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_CRYPTO_PUBLICKEYBYTES; +size_t crypto_sign_publickeybytes(void) { + return CRYPTO_PUBLICKEYBYTES; } /* * Returns the length of a signature, in bytes */ -size_t PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_crypto_sign_bytes(void) { - return PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_CRYPTO_BYTES; +size_t crypto_sign_bytes(void) { + return CRYPTO_BYTES; } /* * Returns the length of the seed required to generate a key pair, in bytes */ -size_t PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_crypto_sign_seedbytes(void) { - return PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_CRYPTO_SEEDBYTES; +size_t crypto_sign_seedbytes(void) { + return CRYPTO_SEEDBYTES; } /* @@ -76,37 +47,30 @@ size_t PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_crypto_sign_seedbytes(void) { * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] * Format pk: [PUB_SEED || root] */ -int PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed) { - /* We do not need the auth path in key generation, but it simplifies the - code to have just one treehash routine that computes both root and path - in one function. */ - unsigned char auth_path[PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_TREE_HEIGHT * PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_N]; - uint32_t top_tree_addr[8] = {0}; - hash_state hash_state_seeded; - - PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_set_layer_addr( - top_tree_addr, PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_D - 1); - PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_set_type( - top_tree_addr, PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_ADDR_TYPE_HASHTREE); +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed) { + spx_ctx ctx; /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ - memcpy(sk, seed, PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_CRYPTO_SEEDBYTES); + memcpy(sk, seed, CRYPTO_SEEDBYTES); - memcpy(pk, sk + 2 * PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_N, PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_N); + memcpy(pk, sk + 2 * SPX_N, SPX_N); + + memcpy(ctx.pub_seed, pk, SPX_N); + memcpy(ctx.sk_seed, sk, SPX_N); /* This hook allows the hash function instantiation to do whatever preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_initialize_hash_function(&hash_state_seeded, pk, sk); + initialize_hash_function(&ctx); /* Compute root node of the top-most subtree. */ - PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_treehash_TREE_HEIGHT( - sk + 3 * PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_N, auth_path, sk, sk + 2 * PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_N, 0, 0, - wots_gen_leaf, top_tree_addr, &hash_state_seeded); + merkle_gen_root(sk + 3 * SPX_N, &ctx); + + // cleanup + free_hash_function(&ctx); - memcpy(pk + PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_N, sk + 3 * PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_N, PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_N); + memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); - PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_destroy_hash_function(&hash_state_seeded); return 0; } @@ -115,12 +79,10 @@ int PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_crypto_sign_seed_keypair( * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] * Format pk: [PUB_SEED || root] */ -int PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk) { - unsigned char seed[PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_CRYPTO_SEEDBYTES]; - randombytes(seed, PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_CRYPTO_SEEDBYTES); - PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_crypto_sign_seed_keypair( - pk, sk, seed); +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { + uint8_t seed[CRYPTO_SEEDBYTES]; + randombytes(seed, CRYPTO_SEEDBYTES); + crypto_sign_seed_keypair(pk, sk, seed); return 0; } @@ -128,101 +90,83 @@ int PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_crypto_sign_keypair( /** * Returns an array containing a detached signature. */ -int PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - const unsigned char *sk_seed = sk; - const unsigned char *sk_prf = sk + PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_N; - const unsigned char *pk = sk + 2 * PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_N; - const unsigned char *pub_seed = pk; - - unsigned char optrand[PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_N]; - unsigned char mhash[PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_FORS_MSG_BYTES]; - unsigned char root[PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_N]; +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk) { + spx_ctx ctx; + + const uint8_t *sk_prf = sk + SPX_N; + const uint8_t *pk = sk + 2 * SPX_N; + + uint8_t optrand[SPX_N]; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t root[SPX_N]; uint32_t i; uint64_t tree; uint32_t idx_leaf; uint32_t wots_addr[8] = {0}; uint32_t tree_addr[8] = {0}; - hash_state hash_state_seeded; + memcpy(ctx.sk_seed, sk, SPX_N); + memcpy(ctx.pub_seed, pk, SPX_N); /* This hook allows the hash function instantiation to do whatever preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_initialize_hash_function( - &hash_state_seeded, - pub_seed, sk_seed); + initialize_hash_function(&ctx); - PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_set_type( - wots_addr, PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_set_type( - tree_addr, PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_ADDR_TYPE_HASHTREE); + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); /* Optionally, signing can be made non-deterministic using optrand. This can help counter side-channel attacks that would benefit from getting a large number of traces when the signer uses the same nodes. */ - randombytes(optrand, PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_N); + randombytes(optrand, SPX_N); /* Compute the digest randomization value. */ - PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_gen_message_random( - sig, sk_prf, optrand, m, mlen, &hash_state_seeded); + gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); /* Derive the message digest and leaf index from R, PK and M. */ - PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_N; + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; - PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); /* Sign the message hash using FORS. */ - PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_fors_sign( - sig, root, mhash, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_FORS_BYTES; - - for (i = 0; i < PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_D; i++) { - PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_set_tree_addr(tree_addr, tree); - - PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); - - /* Compute a WOTS signature. */ - PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_wots_sign( - sig, root, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_WOTS_BYTES; - - /* Compute the authentication path for the used WOTS leaf. */ - PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_treehash_TREE_HEIGHT( - root, sig, sk_seed, pub_seed, idx_leaf, 0, - wots_gen_leaf, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_TREE_HEIGHT * PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_N; + fors_sign(sig, root, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); + sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_TREE_HEIGHT; + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; } - *siglen = PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_BYTES; + free_hash_function(&ctx); + + *siglen = SPX_BYTES; - PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_destroy_hash_function(&hash_state_seeded); return 0; } /** * Verifies a detached signature and message under a given public key. */ -int PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk) { - const unsigned char *pub_seed = pk; - const unsigned char *pub_root = pk + PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_N; - unsigned char mhash[PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_FORS_MSG_BYTES]; - unsigned char wots_pk[PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_WOTS_BYTES]; - unsigned char root[PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_N]; - unsigned char leaf[PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_N]; +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk) { + spx_ctx ctx; + const uint8_t *pub_root = pk + SPX_N; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t wots_pk[SPX_WOTS_BYTES]; + uint8_t root[SPX_N]; + uint8_t leaf[SPX_N]; unsigned int i; uint64_t tree; uint32_t idx_leaf; @@ -230,78 +174,66 @@ int PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_crypto_sign_verify( uint32_t tree_addr[8] = {0}; uint32_t wots_pk_addr[8] = {0}; - hash_state hash_state_seeded; - - if (siglen != PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_BYTES) { + if (siglen != SPX_BYTES) { return -1; } + memcpy(ctx.pub_seed, pk, SPX_N); + /* This hook allows the hash function instantiation to do whatever preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_initialize_hash_function( - &hash_state_seeded, - pub_seed, NULL); + initialize_hash_function(&ctx); - PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_set_type( - wots_addr, PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_set_type( - tree_addr, PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_ADDR_TYPE_HASHTREE); - PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_set_type( - wots_pk_addr, PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_ADDR_TYPE_WOTSPK); + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); /* Derive the message digest and leaf index from R || PK || M. */ - /* The additional PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_N is a result of the hash domain separator. */ - PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_N; + /* The additional SPX_N is a result of the hash domain separator. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; /* Layer correctly defaults to 0, so no need to set_layer_addr */ - PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); - PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_fors_pk_from_sig( - root, sig, mhash, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_FORS_BYTES; + fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; /* For each subtree.. */ - for (i = 0; i < PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_D; i++) { - PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_set_tree_addr(tree_addr, tree); + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); - PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); - PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_copy_keypair_addr( - wots_pk_addr, wots_addr); + copy_keypair_addr(wots_pk_addr, wots_addr); /* The WOTS public key is only correct if the signature was correct. */ /* Initially, root is the FORS pk, but on subsequent iterations it is the root of the subtree below the currently processed subtree. */ - PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_wots_pk_from_sig( - wots_pk, sig, root, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_WOTS_BYTES; + wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); + sig += SPX_WOTS_BYTES; /* Compute the leaf node using the WOTS public key. */ - PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_thash_WOTS_LEN( - leaf, wots_pk, pub_seed, wots_pk_addr, &hash_state_seeded); + thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); /* Compute the root node of this subtree. */ - PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_compute_root( - root, leaf, idx_leaf, 0, sig, PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_TREE_HEIGHT, - pub_seed, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_TREE_HEIGHT * PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_N; + compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, + &ctx, tree_addr); + sig += SPX_TREE_HEIGHT * SPX_N; /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_TREE_HEIGHT; + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; } - PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_destroy_hash_function(&hash_state_seeded); + // cleanup + free_hash_function(&ctx); + /* Check if the root node equals the root node in the public key. */ - if (memcmp(root, pub_root, PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_N) != 0) { + if (memcmp(root, pub_root, SPX_N) != 0) { return -1; } @@ -312,15 +244,14 @@ int PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_crypto_sign_verify( /** * Returns an array containing the signature followed by the message. */ -int PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk) { size_t siglen; - PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_crypto_sign_signature( - sm, &siglen, m, mlen, sk); + crypto_sign_signature(sm, &siglen, m, mlen, sk); - memmove(sm + PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_BYTES, m, mlen); + memmove(sm + SPX_BYTES, m, mlen); *smlen = siglen + mlen; return 0; @@ -329,28 +260,27 @@ int PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_crypto_sign( /** * Verifies a given signature-message pair under a given public key. */ -int PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk) { +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk) { /* The API caller does not necessarily know what size a signature should be - but SPHINCS+ signatures are always exactly PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_BYTES. */ - if (smlen < PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_BYTES) { + but SPHINCS+ signatures are always exactly SPX_BYTES. */ + if (smlen < SPX_BYTES) { memset(m, 0, smlen); *mlen = 0; return -1; } - *mlen = smlen - PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_BYTES; + *mlen = smlen - SPX_BYTES; - if (PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_crypto_sign_verify( - sm, PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_BYTES, sm + PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_BYTES, *mlen, pk)) { + if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { memset(m, 0, smlen); *mlen = 0; return -1; } /* If verification was successful, move the message to the right place. */ - memmove(m, sm + PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_BYTES, *mlen); + memmove(m, sm + SPX_BYTES, *mlen); return 0; } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/thash.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/thash.h index bc97601a70..8687ccfb4d 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/thash.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/thash.h @@ -1,28 +1,13 @@ -#ifndef PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_THASH_H -#define PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_THASH_H +#ifndef SPX_THASH_H +#define SPX_THASH_H -#include "hash_state.h" +#include "context.h" +#include "params.h" #include -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); +#define thash SPX_NAMESPACE(thash) +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/thash_haraka_simple.c b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/thash_haraka_simple.c index 295fceb522..207777bf8d 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/thash_haraka_simple.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/thash_haraka_simple.c @@ -4,80 +4,33 @@ #include "address.h" #include "params.h" #include "thash.h" +#include "utils.h" #include "haraka.h" /** - * Takes an array of inblocks concatenated arrays of PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_N bytes. + * Takes an array of inblocks concatenated arrays of SPX_N bytes. */ -static void PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_thash( - unsigned char *out, unsigned char *buf, - const unsigned char *in, unsigned int inblocks, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]) { + PQCLEAN_VLA(uint8_t, buf, SPX_ADDR_BYTES + inblocks * SPX_N); unsigned char outbuf[32]; unsigned char buf_tmp[64]; - (void)pub_seed; /* Suppress an 'unused parameter' warning. */ - if (inblocks == 1) { /* F function */ - /* Since PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_N may be smaller than 32, we need a temporary buffer. */ + /* Since SPX_N may be smaller than 32, we need a temporary buffer. */ memset(buf_tmp, 0, 64); - PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_addr_to_bytes(buf_tmp, addr); - memcpy(buf_tmp + PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_ADDR_BYTES, in, PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_N); + memcpy(buf_tmp, addr, 32); + memcpy(buf_tmp + SPX_ADDR_BYTES, in, SPX_N); - PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_haraka512(outbuf, buf_tmp, hash_state_seeded); - memcpy(out, outbuf, PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_N); + haraka512(outbuf, buf_tmp, ctx); + memcpy(out, outbuf, SPX_N); } else { /* All other tweakable hashes*/ - PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_addr_to_bytes(buf, addr); - memcpy(buf + PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_ADDR_BYTES, in, inblocks * PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_N); + memcpy(buf, addr, 32); + memcpy(buf + SPX_ADDR_BYTES, in, inblocks * SPX_N); - PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_haraka_S( - out, PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_N, buf, PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_N, hash_state_seeded); + haraka_S(out, SPX_N, buf, SPX_ADDR_BYTES + inblocks * SPX_N, ctx); } } - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_ADDR_BYTES + 1 * PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_N]; - PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_thash( - out, buf, in, 1, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_ADDR_BYTES + 2 * PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_N]; - PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_thash( - out, buf, in, 2, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_ADDR_BYTES + PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_WOTS_LEN * PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_N]; - PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_thash( - out, buf, in, PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_WOTS_LEN, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_ADDR_BYTES + PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_FORS_TREES * PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_N]; - PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_thash( - out, buf, in, PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_FORS_TREES, pub_seed, addr, hash_state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/utils.c b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/utils.c index f53ba464cf..177b541fb9 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/utils.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/utils.c @@ -1,34 +1,41 @@ -#include #include +#include "utils.h" + #include "address.h" #include "hash.h" -#include "hash_state.h" #include "params.h" #include "thash.h" -#include "utils.h" /** * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. */ -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in) { +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in) { + int i; /* Iterate over out in decreasing order, for big-endianness. */ - for (size_t i = outlen; i > 0; i--) { - out[i - 1] = in & 0xff; + for (i = (signed int)outlen - 1; i >= 0; i--) { + out[i] = in & 0xff; in = in >> 8; } } +void u32_to_bytes(unsigned char *out, uint32_t in) { + out[0] = (unsigned char)(in >> 24); + out[1] = (unsigned char)(in >> 16); + out[2] = (unsigned char)(in >> 8); + out[3] = (unsigned char)in; +} + /** * Converts the inlen bytes in 'in' from big-endian byte order to an integer. */ -unsigned long long PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_bytes_to_ull( - const unsigned char *in, size_t inlen) { +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { unsigned long long retval = 0; + unsigned int i; - for (size_t i = 0; i < inlen; i++) { + for (i = 0; i < inlen; i++) { retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); } return retval; @@ -38,94 +45,80 @@ unsigned long long PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_bytes_to_ull( * Computes a root node given a leaf and an auth path. * Expects address to be complete other than the tree_height and tree_index. */ -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]) { uint32_t i; - unsigned char buffer[2 * PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_N]; + unsigned char buffer[2 * SPX_N]; /* If leaf_idx is odd (last bit = 1), current path element is a right child and auth_path has to go left. Otherwise it is the other way around. */ if (leaf_idx & 1) { - memcpy(buffer + PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_N, leaf, PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_N); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_N); + memcpy(buffer + SPX_N, leaf, SPX_N); + memcpy(buffer, auth_path, SPX_N); } else { - memcpy(buffer, leaf, PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_N); - memcpy(buffer + PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_N, auth_path, PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_N); + memcpy(buffer, leaf, SPX_N); + memcpy(buffer + SPX_N, auth_path, SPX_N); } - auth_path += PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_N; + auth_path += SPX_N; for (i = 0; i < tree_height - 1; i++) { leaf_idx >>= 1; idx_offset >>= 1; /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_set_tree_height(addr, i + 1); - PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_set_tree_index( - addr, leaf_idx + idx_offset); + set_tree_height(addr, i + 1); + set_tree_index(addr, leaf_idx + idx_offset); /* Pick the right or left neighbor, depending on parity of the node. */ if (leaf_idx & 1) { - PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_thash_2( - buffer + PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_N, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_N); + thash(buffer + SPX_N, buffer, 2, ctx, addr); + memcpy(buffer, auth_path, SPX_N); } else { - PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_thash_2( - buffer, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer + PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_N, auth_path, PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_N); + thash(buffer, buffer, 2, ctx, addr); + memcpy(buffer + SPX_N, auth_path, SPX_N); } - auth_path += PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_N; + auth_path += SPX_N; } /* The last iteration is exceptional; we do not copy an auth_path node. */ leaf_idx >>= 1; idx_offset >>= 1; - PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_set_tree_height(addr, tree_height); - PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_set_tree_index( - addr, leaf_idx + idx_offset); - PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_thash_2( - root, buffer, pub_seed, addr, hash_state_seeded); + set_tree_height(addr, tree_height); + set_tree_index(addr, leaf_idx + idx_offset); + thash(root, buffer, 2, ctx, addr); } /** * For a given leaf index, computes the authentication path and the resulting * root node using Merkle's TreeHash algorithm. * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_ADDR_TYPE_FORSTREE). + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). * Applies the offset idx_offset to indices before building addresses, so that * it is possible to continue counting indices across trees. */ -static void PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_treehash( - unsigned char *root, unsigned char *auth_path, - unsigned char *stack, unsigned int *heights, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - +void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx * /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]) { + PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); + PQCLEAN_VLA(unsigned int, heights, tree_height + 1); unsigned int offset = 0; uint32_t idx; uint32_t tree_idx; for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { /* Add the next leaf node to the stack. */ - gen_leaf(stack + offset * PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_N, - sk_seed, pub_seed, idx + idx_offset, tree_addr, - hash_state_seeded); + gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); offset++; heights[offset - 1] = 0; /* If this is a node we need for the auth path.. */ if ((leaf_idx ^ 0x1) == idx) { - memcpy(auth_path, stack + (offset - 1)*PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_N, PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_N); + memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); } /* While the top-most nodes are of equal height.. */ @@ -134,66 +127,22 @@ static void PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_treehash( tree_idx = (idx >> (heights[offset - 1] + 1)); /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_set_tree_height( - tree_addr, heights[offset - 1] + 1); - PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_set_tree_index( - tree_addr, tree_idx + (idx_offset >> (heights[offset - 1] + 1))); + set_tree_height(tree_addr, heights[offset - 1] + 1); + set_tree_index(tree_addr, + tree_idx + (idx_offset >> (heights[offset - 1] + 1))); /* Hash the top-most nodes from the stack together. */ - PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_thash_2( - stack + (offset - 2)*PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_N, stack + (offset - 2)*PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_N, - pub_seed, tree_addr, hash_state_seeded); + thash(stack + (offset - 2)*SPX_N, + stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); offset--; /* Note that the top-most node is now one layer higher. */ heights[offset - 1]++; /* If this is a node we need for the auth path.. */ if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_path + heights[offset - 1]*PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_N, - stack + (offset - 1)*PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_N, PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_N); + memcpy(auth_path + heights[offset - 1]*SPX_N, + stack + (offset - 1)*SPX_N, SPX_N); } } } - memcpy(root, stack, PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_N); -} - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_FORS_HEIGHT + 1)*PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_N]; - unsigned int heights[PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_FORS_HEIGHT + 1]; - - PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_FORS_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_TREE_HEIGHT + 1)*PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_N]; - unsigned int heights[PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_TREE_HEIGHT + 1]; - - PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_TREE_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); + memcpy(root, stack, SPX_N); } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/utils.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/utils.h index 7d6ba13dc9..64f5d5a53a 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/utils.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/utils.h @@ -1,64 +1,58 @@ -#ifndef PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_UTILS_H -#define PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_UTILS_H +#ifndef SPX_UTILS_H +#define SPX_UTILS_H -#include "hash_state.h" -#include "params.h" -#include #include +#include "compat.h" +#include "context.h" +#include "params.h" + + +/* To support MSVC use alloca() instead of VLAs. See #20. */ + + /** * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. */ -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in); +#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in); +#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) +void u32_to_bytes(unsigned char *out, uint32_t in); /** * Converts the inlen bytes in 'in' from big-endian byte order to an integer. */ -unsigned long long PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_bytes_to_ull( - const unsigned char *in, size_t inlen); +#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); /** * Computes a root node given a leaf and an auth path. * Expects address to be complete other than the tree_height and tree_index. */ -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); +#define compute_root SPX_NAMESPACE(compute_root) +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]); /** * For a given leaf index, computes the authentication path and the resulting * root node using Merkle's TreeHash algorithm. * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_ADDR_TYPE_FORSTREE). + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). * Applies the offset idx_offset to indices before building addresses, so that * it is possible to continue counting indices across trees. */ -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); +#define treehash SPX_NAMESPACE(treehash) +void treehash(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx *ctx /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]); -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/utilsx1.c b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/utilsx1.c new file mode 100644 index 0000000000..fccb69b35d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/utilsx1.c @@ -0,0 +1,100 @@ +#include + +#include "utilsx1.h" + +#include "address.h" +#include "params.h" +#include "thash.h" +#include "utils.h" + +/* + * Generate the entire Merkle tree, computing the authentication path for + * leaf_idx, and the resulting root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) + * + * This expects tree_addr to be initialized to the addr structures for the + * Merkle tree nodes + * + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + * + * This works by using the standard Merkle tree building algorithm, + */ +void treehashx1(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, + uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* Where to write the leaves */, + const spx_ctx * /* ctx */, + uint32_t idx, void *info), + uint32_t tree_addr[8], + void *info) { + /* This is where we keep the intermediate nodes */ + PQCLEAN_VLA(uint8_t, stack, tree_height * SPX_N); + + uint32_t idx; + uint32_t max_idx = (uint32_t)((1 << tree_height) - 1); + for (idx = 0;; idx++) { + unsigned char current[2 * SPX_N]; /* Current logical node is at */ + /* index[SPX_N]. We do this to minimize the number of copies */ + /* needed during a thash */ + gen_leaf( ¤t[SPX_N], ctx, idx + idx_offset, + info ); + + /* Now combine the freshly generated right node with previously */ + /* generated left ones */ + uint32_t internal_idx_offset = idx_offset; + uint32_t internal_idx = idx; + uint32_t internal_leaf = leaf_idx; + uint32_t h; /* The height we are in the Merkle tree */ + for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { + + /* Check if we hit the top of the tree */ + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[SPX_N], SPX_N ); + return; + } + + /* + * Check if the node we have is a part of the + * authentication path; if it is, write it out + */ + if ((internal_idx ^ internal_leaf) == 0x01) { + memcpy( &auth_path[ h * SPX_N ], + ¤t[SPX_N], + SPX_N ); + } + + /* + * Check if we're at a left child; if so, stop going up the stack + * Exception: if we've reached the end of the tree, keep on going + * (so we combine the last 4 nodes into the one root node in two + * more iterations) + */ + if ((internal_idx & 1) == 0 && idx < max_idx) { + break; + } + + /* Ok, we're at a right node */ + /* Now combine the left and right logical nodes together */ + + /* Set the address of the node we're creating. */ + internal_idx_offset >>= 1; + set_tree_height(tree_addr, h + 1); + set_tree_index(tree_addr, internal_idx / 2 + internal_idx_offset ); + + unsigned char *left = &stack[h * SPX_N]; + memcpy( ¤t[0], left, SPX_N ); + thash( ¤t[1 * SPX_N], + ¤t[0 * SPX_N], + 2, ctx, tree_addr); + } + + /* We've hit a left child; save the current for when we get the */ + /* corresponding right right */ + memcpy( &stack[h * SPX_N], ¤t[SPX_N], SPX_N); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/utilsx1.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/utilsx1.h new file mode 100644 index 0000000000..e911d17d53 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/utilsx1.h @@ -0,0 +1,27 @@ +#ifndef SPX_UTILSX4_H +#define SPX_UTILSX4_H + +#include + +#include "context.h" +#include "params.h" + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +#define treehashx1 SPX_NAMESPACE(treehashx1) +void treehashx1(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* Where to write the leaf */, + const spx_ctx * /* ctx */, + uint32_t addr_idx, void *info), + uint32_t tree_addrx4[8], void *info); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/wots.c b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/wots.c index 9ec8b0b663..249717aaa8 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/wots.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/wots.c @@ -1,32 +1,20 @@ #include #include +#include "wots.h" +#include "wotsx1.h" + #include "address.h" #include "hash.h" -#include "hash_state.h" #include "params.h" #include "thash.h" #include "utils.h" -#include "wots.h" +#include "utilsx1.h" // TODO clarify address expectations, and make them more uniform. // TODO i.e. do we expect types to be set already? // TODO and do we expect modifications or copies? -/** - * Computes the starting value for a chain, i.e. the secret key. - * Expects the address to be complete up to the chain address. - */ -static void wots_gen_sk(unsigned char *sk, const unsigned char *sk_seed, - uint32_t wots_addr[8], - const hash_state *hash_state_seeded) { - /* Make sure that the hash address is actually zeroed. */ - PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_set_hash_addr(wots_addr, 0); - - /* Generate sk element. */ - PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_prf_addr(sk, sk_seed, wots_addr, hash_state_seeded); -} - /** * Computes the chaining function. * out and in have to be n-byte arrays. @@ -36,18 +24,16 @@ static void wots_gen_sk(unsigned char *sk, const unsigned char *sk_seed, */ static void gen_chain(unsigned char *out, const unsigned char *in, unsigned int start, unsigned int steps, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { + const spx_ctx *ctx, uint32_t addr[8]) { uint32_t i; /* Initialize out with the value at position 'start'. */ - memcpy(out, in, PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_N); + memcpy(out, in, SPX_N); /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_WOTS_W; i++) { - PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_set_hash_addr(addr, i); - PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_thash_1( - out, out, pub_seed, addr, hash_state_seeded); + for (i = start; i < (start + steps) && i < SPX_WOTS_W; i++) { + set_hash_addr(addr, i); + thash(out, out, 1, ctx, addr); } } @@ -56,13 +42,13 @@ static void gen_chain(unsigned char *out, const unsigned char *in, * Interprets an array of bytes as integers in base w. * This only works when log_w is a divisor of 8. */ -static void base_w(unsigned int *output, const size_t out_len, +static void base_w(unsigned int *output, const int out_len, const unsigned char *input) { - size_t in = 0; - size_t out = 0; + int in = 0; + int out = 0; unsigned char total = 0; - unsigned int bits = 0; - size_t consumed; + int bits = 0; + int consumed; for (consumed = 0; consumed < out_len; consumed++) { if (bits == 0) { @@ -70,8 +56,8 @@ static void base_w(unsigned int *output, const size_t out_len, in++; bits += 8; } - bits -= PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_WOTS_LOGW; - output[out] = (unsigned int)((total >> bits) & (PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_WOTS_W - 1)); + bits -= SPX_WOTS_LOGW; + output[out] = (total >> bits) & (SPX_WOTS_W - 1); out++; } } @@ -80,67 +66,25 @@ static void base_w(unsigned int *output, const size_t out_len, static void wots_checksum(unsigned int *csum_base_w, const unsigned int *msg_base_w) { unsigned int csum = 0; - unsigned char csum_bytes[(PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_WOTS_LEN2 * PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_WOTS_LOGW + 7) / 8]; + unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; unsigned int i; /* Compute checksum. */ - for (i = 0; i < PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_WOTS_LEN1; i++) { - csum += PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_WOTS_W - 1 - msg_base_w[i]; + for (i = 0; i < SPX_WOTS_LEN1; i++) { + csum += SPX_WOTS_W - 1 - msg_base_w[i]; } /* Convert checksum to base_w. */ /* Make sure expected empty zero bits are the least significant bits. */ - csum = csum << (8 - ((PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_WOTS_LEN2 * PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_WOTS_LOGW) % 8)); - PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_ull_to_bytes( - csum_bytes, sizeof(csum_bytes), csum); - base_w(csum_base_w, PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_WOTS_LEN2, csum_bytes); + csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); + ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); + base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); } /* Takes a message and derives the matching chain lengths. */ -static void chain_lengths(unsigned int *lengths, const unsigned char *msg) { - base_w(lengths, PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_WOTS_LEN1, msg); - wots_checksum(lengths + PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_WOTS_LEN1, lengths); -} - -/** - * WOTS key generation. Takes a 32 byte sk_seed, expands it to WOTS private key - * elements and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_wots_gen_pk( - unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - uint32_t i; - - for (i = 0; i < PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_WOTS_LEN; i++) { - PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_set_chain_addr(addr, i); - wots_gen_sk(pk + i * PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_N, sk_seed, addr, hash_state_seeded); - gen_chain(pk + i * PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_N, pk + i * PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_N, - 0, PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_WOTS_W - 1, pub_seed, addr, hash_state_seeded); - } -} - -/** - * Takes a n-byte message and the 32-byte sk_see to compute a signature 'sig'. - */ -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_wots_sign( - unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *hash_state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_WOTS_LEN; i++) { - PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_set_chain_addr(addr, i); - wots_gen_sk(sig + i * PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_N, sk_seed, addr, hash_state_seeded); - gen_chain(sig + i * PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_N, sig + i * PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_N, 0, lengths[i], pub_seed, addr, hash_state_seeded); - } +void chain_lengths(unsigned int *lengths, const unsigned char *msg) { + base_w(lengths, SPX_WOTS_LEN1, msg); + wots_checksum(lengths + SPX_WOTS_LEN1, lengths); } /** @@ -148,20 +92,17 @@ void PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_wots_sign( * * Writes the computed public key to 'pk'. */ -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_wots_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_WOTS_LEN]; +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]) { + unsigned int lengths[SPX_WOTS_LEN]; uint32_t i; chain_lengths(lengths, msg); - for (i = 0; i < PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_WOTS_LEN; i++) { - PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_set_chain_addr(addr, i); - gen_chain(pk + i * PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_N, sig + i * PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_N, - lengths[i], PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_WOTS_W - 1 - lengths[i], pub_seed, addr, - hash_state_seeded); + for (i = 0; i < SPX_WOTS_LEN; i++) { + set_chain_addr(addr, i); + gen_chain(pk + i * SPX_N, sig + i * SPX_N, + lengths[i], SPX_WOTS_W - 1 - lengths[i], ctx, addr); } } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/wots.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/wots.h index 6455e15c18..4e7692eeef 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/wots.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/wots.h @@ -1,41 +1,25 @@ -#ifndef PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_WOTS_H -#define PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_WOTS_H +#ifndef SPX_WOTS_H +#define SPX_WOTS_H -#include "hash_state.h" -#include "params.h" #include -/** - * WOTS key generation. Takes a 32 byte seed for the private key, expands it to - * a full WOTS private key and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_wots_gen_pk( - unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -/** - * Takes a n-byte message and the 32-byte seed for the private key to compute a - * signature that is placed at 'sig'. - */ -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_wots_sign( - unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *hash_state_seeded); +#include "context.h" +#include "params.h" /** * Takes a WOTS signature and an n-byte message, computes a WOTS public key. * * Writes the computed public key to 'pk'. */ -void PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_wots_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); +#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]); + +/* + * Compute the chain lengths needed for a given message hash + */ +#define chain_lengths SPX_NAMESPACE(chain_lengths) +void chain_lengths(unsigned int *lengths, const unsigned char *msg); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/wotsx1.c b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/wotsx1.c new file mode 100644 index 0000000000..3adec78dfb --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/wotsx1.c @@ -0,0 +1,76 @@ +#include +#include + +#include "wots.h" +#include "wotsx1.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "thash.h" +#include "utils.h" + +/* + * This generates a WOTS public key + * It also generates the WOTS signature if leaf_info indicates + * that we're signing with this WOTS key + */ +void wots_gen_leafx1(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info) { + struct leaf_info_x1 *info = v_info; + uint32_t *leaf_addr = info->leaf_addr; + uint32_t *pk_addr = info->pk_addr; + unsigned int i, k; + unsigned char pk_buffer[ SPX_WOTS_BYTES ]; + unsigned char *buffer; + uint32_t wots_k_mask; + + if (leaf_idx == info->wots_sign_leaf) { + /* We're traversing the leaf that's signing; generate the WOTS */ + /* signature */ + wots_k_mask = 0; + } else { + /* Nope, we're just generating pk's; turn off the signature logic */ + wots_k_mask = (uint32_t)~0; + } + + set_keypair_addr( leaf_addr, leaf_idx ); + set_keypair_addr( pk_addr, leaf_idx ); + + for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { + uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k to */ + /* the step if we're generating a signature, ~0 if we're not */ + + /* Start with the secret seed */ + set_chain_addr(leaf_addr, i); + set_hash_addr(leaf_addr, 0); + set_type(leaf_addr, SPX_ADDR_TYPE_WOTSPRF); + + prf_addr(buffer, ctx, leaf_addr); + + set_type(leaf_addr, SPX_ADDR_TYPE_WOTS); + + /* Iterate down the WOTS chain */ + for (k = 0;; k++) { + /* Check if this is the value that needs to be saved as a */ + /* part of the WOTS signature */ + if (k == wots_k) { + memcpy( info->wots_sig + i * SPX_N, buffer, SPX_N ); + } + + /* Check if we hit the top of the chain */ + if (k == SPX_WOTS_W - 1) { + break; + } + + /* Iterate one step on the chain */ + set_hash_addr(leaf_addr, k); + + thash(buffer, buffer, 1, ctx, leaf_addr); + } + } + + /* Do the final thash to generate the public keys */ + thash(dest, pk_buffer, SPX_WOTS_LEN, ctx, pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/wotsx1.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/wotsx1.h new file mode 100644 index 0000000000..e617929f96 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/wotsx1.h @@ -0,0 +1,39 @@ +#ifndef WOTSX1_H_ +#define WOTSX1_H_ + +#include + +#include "context.h" +#include "params.h" + +/* + * This is here to provide an interface to the internal wots_gen_leafx1 + * routine. While this routine is not referenced in the package outside of + * wots.c, it is called from the stand-alone benchmark code to characterize + * the performance + */ +struct leaf_info_x1 { + unsigned char *wots_sig; + uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ + uint32_t *wots_steps; + uint32_t leaf_addr[8]; + uint32_t pk_addr[8]; +}; + +/* Macro to set the leaf_info to something 'benign', that is, it would */ +/* run with the same time as it does during the real signing process */ +/* Used only by the benchmark code */ +#define INITIALIZE_LEAF_INFO_X1(info, addr, step_buffer) { \ + (info).wots_sig = 0; \ + (info).wots_sign_leaf = ~0; \ + (info).wots_steps = step_buffer; \ + memcpy( &(info).leaf_addr[0], (addr), 32 ); \ + memcpy( &(info).pk_addr[0], (addr), 32 ); \ + } + +#define wots_gen_leafx1 SPX_NAMESPACE(wots_gen_leafx1) +void wots_gen_leafx1(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info); + +#endif /* WOTSX1_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/address.c b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/address.c index e40ab3e182..b956e9cb29 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/address.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/address.c @@ -1,78 +1,91 @@ #include +#include #include "address.h" #include "params.h" #include "utils.h" -void PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]) { - int i; - - for (i = 0; i < 8; i++) { - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_ull_to_bytes( - bytes + i * 4, 4, addr[i]); - } -} - -void PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_set_layer_addr( - uint32_t addr[8], uint32_t layer) { - addr[0] = layer; +/* + * Specify which level of Merkle tree (the "layer") we're working on + */ +void set_layer_addr(uint32_t addr[8], uint32_t layer) { + ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; } -void PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_set_tree_addr( - uint32_t addr[8], uint64_t tree) { - addr[1] = 0; - addr[2] = (uint32_t) (tree >> 32); - addr[3] = (uint32_t) tree; +/* + * Specify which Merkle tree within the level (the "tree address") we're working on + */ +void set_tree_addr(uint32_t addr[8], uint64_t tree) { + ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); } -void PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_set_type( - uint32_t addr[8], uint32_t type) { - addr[4] = type; +/* + * Specify the reason we'll use this address structure for, that is, what + * hash will we compute with it. This is used so that unrelated types of + * hashes don't accidentally get the same address structure. The type will be + * one of the SPX_ADDR_TYPE constants + */ +void set_type(uint32_t addr[8], uint32_t type) { + ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; } -void PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; +/* + * Copy the layer and tree fields of the address structure. This is used + * when we're doing multiple types of hashes within the same Merkle tree + */ +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); } /* These functions are used for OTS addresses. */ -void PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_set_keypair_addr( - uint32_t addr[8], uint32_t keypair) { - addr[5] = keypair; +/* + * Specify which Merkle leaf we're working on; that is, which OTS keypair + * we're talking about. + */ +void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { + ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; } -void PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; - out[5] = in[5]; +/* + * Copy the layer, tree and keypair fields of the address structure. This is + * used when we're doing multiple things within the same OTS keypair + */ +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); + ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; } -void PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_set_chain_addr( - uint32_t addr[8], uint32_t chain) { - addr[6] = chain; +/* + * Specify which Merkle chain within the OTS we're working with + * (the chain address) + */ +void set_chain_addr(uint32_t addr[8], uint32_t chain) { + ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; } -void PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_set_hash_addr( - uint32_t addr[8], uint32_t hash) { - addr[7] = hash; +/* + * Specify where in the Merkle chain we are +* (the hash address) + */ +void set_hash_addr(uint32_t addr[8], uint32_t hash) { + ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; } /* These functions are used for all hash tree addresses (including FORS). */ -void PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_set_tree_height( - uint32_t addr[8], uint32_t tree_height) { - addr[6] = tree_height; +/* + * Specify the height of the node in the Merkle/FORS tree we are in + * (the tree height) + */ +void set_tree_height(uint32_t addr[8], uint32_t tree_height) { + ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; } -void PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_set_tree_index( - uint32_t addr[8], uint32_t tree_index) { - addr[7] = tree_index; +/* + * Specify the distance from the left edge of the node in the Merkle/FORS tree + * (the tree index) + */ +void set_tree_index(uint32_t addr[8], uint32_t tree_index) { + u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/address.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/address.h index bf73cc57bc..24a84eb40c 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/address.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/address.h @@ -1,50 +1,52 @@ -#ifndef PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_ADDRESS_H -#define PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_ADDRESS_H +#ifndef SPX_ADDRESS_H +#define SPX_ADDRESS_H #include -#define PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_ADDR_TYPE_WOTS 0 -#define PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_ADDR_TYPE_WOTSPK 1 -#define PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_ADDR_TYPE_HASHTREE 2 -#define PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_ADDR_TYPE_FORSTREE 3 -#define PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_ADDR_TYPE_FORSPK 4 +#include "params.h" -void PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]); +/* The hash types that are passed to set_type */ +#define SPX_ADDR_TYPE_WOTS 0 +#define SPX_ADDR_TYPE_WOTSPK 1 +#define SPX_ADDR_TYPE_HASHTREE 2 +#define SPX_ADDR_TYPE_FORSTREE 3 +#define SPX_ADDR_TYPE_FORSPK 4 +#define SPX_ADDR_TYPE_WOTSPRF 5 +#define SPX_ADDR_TYPE_FORSPRF 6 -void PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_set_layer_addr( - uint32_t addr[8], uint32_t layer); +#define set_layer_addr SPX_NAMESPACE(set_layer_addr) +void set_layer_addr(uint32_t addr[8], uint32_t layer); -void PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_set_tree_addr( - uint32_t addr[8], uint64_t tree); +#define set_tree_addr SPX_NAMESPACE(set_tree_addr) +void set_tree_addr(uint32_t addr[8], uint64_t tree); -void PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_set_type( - uint32_t addr[8], uint32_t type); +#define set_type SPX_NAMESPACE(set_type) +void set_type(uint32_t addr[8], uint32_t type); /* Copies the layer and tree part of one address into the other */ -void PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]); +#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); /* These functions are used for WOTS and FORS addresses. */ -void PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_set_keypair_addr( - uint32_t addr[8], uint32_t keypair); +#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) +void set_keypair_addr(uint32_t addr[8], uint32_t keypair); -void PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_set_chain_addr( - uint32_t addr[8], uint32_t chain); +#define set_chain_addr SPX_NAMESPACE(set_chain_addr) +void set_chain_addr(uint32_t addr[8], uint32_t chain); -void PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_set_hash_addr( - uint32_t addr[8], uint32_t hash); +#define set_hash_addr SPX_NAMESPACE(set_hash_addr) +void set_hash_addr(uint32_t addr[8], uint32_t hash); -void PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]); +#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); /* These functions are used for all hash tree addresses (including FORS). */ -void PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_set_tree_height( - uint32_t addr[8], uint32_t tree_height); +#define set_tree_height SPX_NAMESPACE(set_tree_height) +void set_tree_height(uint32_t addr[8], uint32_t tree_height); -void PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_set_tree_index( - uint32_t addr[8], uint32_t tree_index); +#define set_tree_index SPX_NAMESPACE(set_tree_index) +void set_tree_index(uint32_t addr[8], uint32_t tree_index); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/api.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/api.h index da73bc178a..3c18614b37 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/api.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/api.h @@ -4,15 +4,13 @@ #include #include - - -#define PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_CRYPTO_ALGNAME "SPHINCS+" +#define PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_CRYPTO_ALGNAME "SPHINCS+-haraka-192f-robust" #define PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_CRYPTO_SECRETKEYBYTES 96 #define PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_CRYPTO_PUBLICKEYBYTES 48 -#define PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_CRYPTO_BYTES 35664 -#define PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_CRYPTO_SEEDBYTES 72 +#define PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_CRYPTO_BYTES 35664 +#define PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_CRYPTO_SEEDBYTES 72 /* * Returns the length of a secret key, in bytes @@ -39,43 +37,41 @@ size_t PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_crypto_sign_seedbytes(void); * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] * Format pk: [root || PUB_SEED] */ -int PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed); +int PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); /* * Generates a SPHINCS+ key pair. * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] * Format pk: [root || PUB_SEED] */ -int PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk); +int PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); /** * Returns an array containing a detached signature. */ -int PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk); +int PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); /** * Verifies a detached signature and message under a given public key. */ -int PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk); +int PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, + const uint8_t *pk); /** * Returns an array containing the signature followed by the message. */ -int PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk); +int PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); /** * Verifies a given signature-message pair under a given public key. */ -int PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk); - +int PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/context.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/context.h new file mode 100644 index 0000000000..f03446b9cb --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/context.h @@ -0,0 +1,22 @@ +#ifndef SPX_CONTEXT_H +#define SPX_CONTEXT_H + +#include + +#include "immintrin.h" +#include "params.h" + +typedef struct { + uint8_t pub_seed[SPX_N]; + uint8_t sk_seed[SPX_N]; + + __m128i rc[40]; +} spx_ctx; + +#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) +void initialize_hash_function(spx_ctx *ctx); + +#define free_hash_function SPX_NAMESPACE(free_hash_function) +void free_hash_function(spx_ctx *ctx); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/context_haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/context_haraka.c new file mode 100644 index 0000000000..f1cd7e3664 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/context_haraka.c @@ -0,0 +1,11 @@ +#include "context.h" +#include "haraka.h" + +void initialize_hash_function(spx_ctx *ctx) { + tweak_constants(ctx); +} + +// we don't support heap-based haraka right now +void free_hash_function(spx_ctx *ctx) { + (void)ctx; // suppress unused variable warnings +} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/fors.c b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/fors.c index 4ac8d3f6de..f1b0639cfc 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/fors.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/fors.c @@ -2,8 +2,9 @@ #include #include -#include "address.h" #include "fors.h" + +#include "address.h" #include "hash.h" #include "hashx4.h" #include "thash.h" @@ -11,19 +12,24 @@ #include "utils.h" #include "utilsx4.h" +static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + prf_addr(sk, ctx, fors_leaf_addr); +} + static void fors_gen_skx4(unsigned char *sk0, unsigned char *sk1, unsigned char *sk2, - unsigned char *sk3, const unsigned char *sk_seed, - uint32_t fors_leaf_addrx4[4 * 8], - const hash_state *state_seeded) { - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_prf_addrx4(sk0, sk1, sk2, sk3, sk_seed, fors_leaf_addrx4, state_seeded); + unsigned char *sk3, const spx_ctx *ctx, + uint32_t fors_leaf_addrx4[4 * 8]) { + prf_addrx4(sk0, sk1, sk2, sk3, + ctx, fors_leaf_addrx4); } static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, - const unsigned char *pub_seed, - uint32_t fors_leaf_addr[8], const hash_state *state_seeded) { - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_thash_1(leaf, sk, pub_seed, fors_leaf_addr, state_seeded); + const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + thash(leaf, sk, 1, ctx, fors_leaf_addr); } static void fors_sk_to_leafx4(unsigned char *leaf0, @@ -34,57 +40,64 @@ static void fors_sk_to_leafx4(unsigned char *leaf0, const unsigned char *sk1, const unsigned char *sk2, const unsigned char *sk3, - const unsigned char *pub_seed, - uint32_t fors_leaf_addrx4[4 * 8], - const hash_state *state_seeded) { - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_thashx4_1(leaf0, leaf1, leaf2, leaf3, - sk0, sk1, sk2, sk3, pub_seed, fors_leaf_addrx4, state_seeded); + const spx_ctx *ctx, + uint32_t fors_leaf_addrx4[4 * 8]) { + thashx4(leaf0, leaf1, leaf2, leaf3, + sk0, sk1, sk2, sk3, + 1, ctx, fors_leaf_addrx4); } -static void fors_gen_leafx4(unsigned char *leaf0, - unsigned char *leaf1, - unsigned char *leaf2, - unsigned char *leaf3, - const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx0, - uint32_t addr_idx1, - uint32_t addr_idx2, - uint32_t addr_idx3, - const uint32_t fors_tree_addr[8], - const hash_state *state_seeded) { - uint32_t fors_leaf_addrx4[4 * 8] = {0}; +struct fors_gen_leaf_info { + uint32_t leaf_addrx[4 * 8]; +}; + +static void fors_gen_leafx4(unsigned char *leaf, + const spx_ctx *ctx, + uint32_t addr_idx, void *info) { + struct fors_gen_leaf_info *fors_info = info; + uint32_t *fors_leaf_addrx4 = fors_info->leaf_addrx; unsigned int j; - /* Only copy the parts that must be kept in fors_leaf_addrx4. */ + /* Only set the parts that the caller doesn't set */ for (j = 0; j < 4; j++) { - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_copy_keypair_addr(fors_leaf_addrx4 + j * 8, fors_tree_addr); - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_set_type(fors_leaf_addrx4 + j * 8, PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_ADDR_TYPE_FORSTREE); + set_tree_index(fors_leaf_addrx4 + j * 8, addr_idx + j); + set_type(fors_leaf_addrx4 + j * 8, SPX_ADDR_TYPE_FORSPRF); } - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_set_tree_index(fors_leaf_addrx4 + 0 * 8, addr_idx0); - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_set_tree_index(fors_leaf_addrx4 + 1 * 8, addr_idx1); - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_set_tree_index(fors_leaf_addrx4 + 2 * 8, addr_idx2); - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_set_tree_index(fors_leaf_addrx4 + 3 * 8, addr_idx3); + fors_gen_skx4(leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + leaf + 2 * SPX_N, + leaf + 3 * SPX_N, + ctx, fors_leaf_addrx4); + + for (j = 0; j < 4; j++) { + set_type(fors_leaf_addrx4 + j * 8, SPX_ADDR_TYPE_FORSTREE); + } - fors_gen_skx4(leaf0, leaf1, leaf2, leaf3, sk_seed, fors_leaf_addrx4, state_seeded); - fors_sk_to_leafx4(leaf0, leaf1, leaf2, leaf3, - leaf0, leaf1, leaf2, leaf3, pub_seed, fors_leaf_addrx4, state_seeded); + fors_sk_to_leafx4(leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + leaf + 2 * SPX_N, + leaf + 3 * SPX_N, + leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + leaf + 2 * SPX_N, + leaf + 3 * SPX_N, + ctx, fors_leaf_addrx4); } /** - * Interprets m as PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_FORS_HEIGHT-bit unsigned integers. - * Assumes m contains at least PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_FORS_TREES bits. - * Assumes indices has space for PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_FORS_TREES integers. + * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + * Assumes indices has space for SPX_FORS_TREES integers. */ static void message_to_indices(uint32_t *indices, const unsigned char *m) { unsigned int i, j; unsigned int offset = 0; - for (i = 0; i < PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_FORS_TREES; i++) { + for (i = 0; i < SPX_FORS_TREES; i++) { indices[i] = 0; - for (j = 0; j < PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_FORS_HEIGHT; j++) { - indices[i] ^= (((uint32_t)m[offset >> 3] >> (offset & 0x7)) & 0x1) << j; + for (j = 0; j < SPX_FORS_HEIGHT; j++) { + indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); offset++; } } @@ -92,68 +105,53 @@ static void message_to_indices(uint32_t *indices, const unsigned char *m) { /** * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_FORS_TREES bits. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. */ -void PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *state_seeded) { - /* Round up to multiple of 4 to prevent out-of-bounds for x4 parallelism */ - uint32_t indices[(PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_FORS_TREES + 3) & ~3] = {0}; - unsigned char roots[((PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_FORS_TREES + 3) & ~3) * PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N]; - /* Sign to a buffer, since we may not have a nice multiple of 4 and would - otherwise overrun the signature. */ - unsigned char sigbufx4[4 * PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N * (1 + PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_FORS_HEIGHT)]; - uint32_t fors_tree_addrx4[4 * 8] = {0}; +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + uint32_t fors_tree_addr[4 * 8] = {0}; + struct fors_gen_leaf_info fors_info = {0}; + uint32_t *fors_leaf_addr = fors_info.leaf_addrx; uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset[4] = {0}; - unsigned int i, j; + uint32_t idx_offset; + unsigned int i; - for (j = 0; j < 4; j++) { - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_copy_keypair_addr(fors_tree_addrx4 + j * 8, fors_addr); - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_set_type(fors_tree_addrx4 + j * 8, PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_ADDR_TYPE_FORSTREE); + for (i = 0; i < 4; i++) { + copy_keypair_addr(fors_tree_addr + 8 * i, fors_addr); + set_type(fors_tree_addr + 8 * i, SPX_ADDR_TYPE_FORSTREE); + copy_keypair_addr(fors_leaf_addr + 8 * i, fors_addr); } - - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_copy_keypair_addr(fors_pk_addr, fors_addr); - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_set_type(fors_pk_addr, PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_ADDR_TYPE_FORSPK); + copy_keypair_addr(fors_pk_addr, fors_addr); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); message_to_indices(indices, m); - for (i = 0; i < ((PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_FORS_TREES + 3) & ~0x3); i += 4) { - for (j = 0; j < 4; j++) { - if (i + j < PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_FORS_TREES) { - idx_offset[j] = (i + j) * (1 << PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_FORS_HEIGHT); + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_set_tree_height(fors_tree_addrx4 + j * 8, 0); - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_set_tree_index(fors_tree_addrx4 + j * 8, - indices[i + j] + idx_offset[j]); - } - } + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); - /* Include the secret key part that produces the selected leaf nodes. */ - fors_gen_skx4(sigbufx4 + 0 * PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N, - sigbufx4 + 1 * PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N, - sigbufx4 + 2 * PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N, - sigbufx4 + 3 * PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N, - sk_seed, fors_tree_addrx4, state_seeded); - - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_treehashx4_FORS_HEIGHT(roots + i * PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N, sigbufx4 + 4 * PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N, sk_seed, pub_seed, - &indices[i], idx_offset, fors_gen_leafx4, fors_tree_addrx4, - state_seeded); - - for (j = 0; j < 4; j++) { - if (i + j < PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_FORS_TREES) { - memcpy(sig, sigbufx4 + j * PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N, PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N); - memcpy(sig + PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N, - sigbufx4 + 4 * PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N + j * PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N * PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_FORS_HEIGHT, - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N * PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_FORS_HEIGHT); - sig += PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N * (1 + PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_FORS_HEIGHT); - } - } + /* Include the secret key part that produces the selected leaf node. */ + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); + fors_gen_sk(sig, ctx, fors_tree_addr); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + sig += SPX_N; + + /* Compute the authentication path for this leaf node. */ + treehashx4(roots + i * SPX_N, sig, ctx, + indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx4, + fors_tree_addr, &fors_info); + + sig += SPX_N * SPX_FORS_HEIGHT; } /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_thash_FORS_TREES(pk, roots, pub_seed, fors_pk_addr, state_seeded); + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); } /** @@ -161,46 +159,44 @@ void PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_fors_sign(unsigned char *sig, unsigne * This can be used for verification by comparing to a known public key, or to * subsequently verify a signature on the derived public key. The latter is the * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_FORS_TREES bits. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. */ -void PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, - const uint32_t fors_addr[8], - const hash_state *state_seeded) { - uint32_t indices[PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_FORS_TREES]; - unsigned char roots[PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_FORS_TREES * PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N]; - unsigned char leaf[PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N]; +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + unsigned char leaf[SPX_N]; uint32_t fors_tree_addr[8] = {0}; uint32_t fors_pk_addr[8] = {0}; uint32_t idx_offset; unsigned int i; - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_copy_keypair_addr(fors_tree_addr, fors_addr); - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_copy_keypair_addr(fors_pk_addr, fors_addr); + copy_keypair_addr(fors_tree_addr, fors_addr); + copy_keypair_addr(fors_pk_addr, fors_addr); - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_set_type(fors_tree_addr, PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_set_type(fors_pk_addr, PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_ADDR_TYPE_FORSPK); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); message_to_indices(indices, m); - for (i = 0; i < PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_FORS_TREES; i++) { - idx_offset = i * (1 << PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_FORS_HEIGHT); + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_set_tree_height(fors_tree_addr, 0); - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_set_tree_index(fors_tree_addr, indices[i] + idx_offset); + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); /* Derive the leaf from the included secret key part. */ - fors_sk_to_leaf(leaf, sig, pub_seed, fors_tree_addr, state_seeded); - sig += PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N; + fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); + sig += SPX_N; /* Derive the corresponding root node of this tree. */ - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_compute_root(roots + i * PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N, leaf, indices[i], idx_offset, - sig, PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_FORS_HEIGHT, pub_seed, fors_tree_addr, - state_seeded); - sig += PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N * PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_FORS_HEIGHT; + compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, + sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); + sig += SPX_N * SPX_FORS_HEIGHT; } /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_thash_FORS_TREES(pk, roots, pub_seed, fors_pk_addr, state_seeded); + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/fors.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/fors.h index 52a51e0950..509140a178 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/fors.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/fors.h @@ -1,32 +1,32 @@ -#ifndef PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_FORS_H -#define PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_FORS_H +#ifndef SPX_FORS_H +#define SPX_FORS_H #include -#include "hash_state.h" +#include "context.h" #include "params.h" /** * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_FORS_TREES bits. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. */ -void PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_fors_sign( - unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *hash_state_seeded); +#define fors_sign SPX_NAMESPACE(fors_sign) +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); /** * Derives the FORS public key from a signature. * This can be used for verification by comparing to a known public key, or to * subsequently verify a signature on the derived public key. The latter is the * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_FORS_TREES bits. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. */ -void PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_fors_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, const uint32_t fors_addr[8], - const hash_state *hash_state_seeded); +#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/haraka.c index 2489d3e818..b414b691d7 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/haraka.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/haraka.c @@ -8,10 +8,12 @@ Plain C implementation of the Haraka256 and Haraka512 permutations. #include #include "haraka.h" +#include "harakax4.h" +#include "utils.h" #define HARAKAS_RATE 32 -#define u64 uint64_t +#define u64 unsigned long #define u128 __m128i #define LOAD(src) _mm_loadu_si128((u128 *)(src)) @@ -20,7 +22,7 @@ Plain C implementation of the Haraka256 and Haraka512 permutations. #define XOR128(a, b) _mm_xor_si128(a, b) #define AES2(s0, s1, rci) \ - (s0) = _mm_aesenc_si128(s0, *(rci)); \ + s0 = _mm_aesenc_si128(s0, *(rci)); \ (s1) = _mm_aesenc_si128(s1, *((rci) + 1)); \ (s0) = _mm_aesenc_si128(s0, *((rci) + 2)); \ (s1) = _mm_aesenc_si128(s1, *((rci) + 3)); @@ -32,7 +34,7 @@ Plain C implementation of the Haraka256 and Haraka512 permutations. AES2((s3)[0], (s3)[1], rci); #define AES4(s0, s1, s2, s3, rci) \ - (s0) = _mm_aesenc_si128(s0, *(rci)); \ + s0 = _mm_aesenc_si128(s0, *(rci)); \ (s1) = _mm_aesenc_si128(s1, *((rci) + 1)); \ (s2) = _mm_aesenc_si128(s2, *((rci) + 2)); \ (s3) = _mm_aesenc_si128(s3, *((rci) + 3)); \ @@ -68,17 +70,17 @@ Plain C implementation of the Haraka256 and Haraka512 permutations. _mm_storeu_si128((u128 *)((out) + 16), \ _mm_castpd_si128(_mm_shuffle_pd(_mm_castsi128_pd(s2), _mm_castsi128_pd(s3), 0))); -static void load_haraka_constants(u128 rc[40]) { - rc[ 0] = _mm_set_epi32((int)0x0684704c, (int)0xe620c00a, (int)0xb2c5fef0, (int)0x75817b9d); - rc[ 1] = _mm_set_epi32((int)0x8b66b4e1, (int)0x88f3a06b, (int)0x640f6ba4, (int)0x2f08f717); - rc[ 2] = _mm_set_epi32((int)0x3402de2d, (int)0x53f28498, (int)0xcf029d60, (int)0x9f029114); - rc[ 3] = _mm_set_epi32((int)0x0ed6eae6, (int)0x2e7b4f08, (int)0xbbf3bcaf, (int)0xfd5b4f79); - rc[ 4] = _mm_set_epi32((int)0xcbcfb0cb, (int)0x4872448b, (int)0x79eecd1c, (int)0xbe397044); - rc[ 5] = _mm_set_epi32((int)0x7eeacdee, (int)0x6e9032b7, (int)0x8d5335ed, (int)0x2b8a057b); - rc[ 6] = _mm_set_epi32((int)0x67c28f43, (int)0x5e2e7cd0, (int)0xe2412761, (int)0xda4fef1b); - rc[ 7] = _mm_set_epi32((int)0x2924d9b0, (int)0xafcacc07, (int)0x675ffde2, (int)0x1fc70b3b); - rc[ 8] = _mm_set_epi32((int)0xab4d63f1, (int)0xe6867fe9, (int)0xecdb8fca, (int)0xb9d465ee); - rc[ 9] = _mm_set_epi32((int)0x1c30bf84, (int)0xd4b7cd64, (int)0x5b2a404f, (int)0xad037e33); +static void load_haraka_constants(u128 *rc) { + rc[0] = _mm_set_epi32((int)0x0684704c, (int)0xe620c00a, (int)0xb2c5fef0, (int)0x75817b9d); + rc[1] = _mm_set_epi32((int)0x8b66b4e1, (int)0x88f3a06b, (int)0x640f6ba4, (int)0x2f08f717); + rc[2] = _mm_set_epi32((int)0x3402de2d, (int)0x53f28498, (int)0xcf029d60, (int)0x9f029114); + rc[3] = _mm_set_epi32((int)0x0ed6eae6, (int)0x2e7b4f08, (int)0xbbf3bcaf, (int)0xfd5b4f79); + rc[4] = _mm_set_epi32((int)0xcbcfb0cb, (int)0x4872448b, (int)0x79eecd1c, (int)0xbe397044); + rc[5] = _mm_set_epi32((int)0x7eeacdee, (int)0x6e9032b7, (int)0x8d5335ed, (int)0x2b8a057b); + rc[6] = _mm_set_epi32((int)0x67c28f43, (int)0x5e2e7cd0, (int)0xe2412761, (int)0xda4fef1b); + rc[7] = _mm_set_epi32((int)0x2924d9b0, (int)0xafcacc07, (int)0x675ffde2, (int)0x1fc70b3b); + rc[8] = _mm_set_epi32((int)0xab4d63f1, (int)0xe6867fe9, (int)0xecdb8fca, (int)0xb9d465ee); + rc[9] = _mm_set_epi32((int)0x1c30bf84, (int)0xd4b7cd64, (int)0x5b2a404f, (int)0xad037e33); rc[10] = _mm_set_epi32((int)0xb2cc0bb9, (int)0x941723bf, (int)0x69028b2e, (int)0x8df69800); rc[11] = _mm_set_epi32((int)0xfa0478a6, (int)0xde6f5572, (int)0x4aaa9ec8, (int)0x5c9d2d8a); rc[12] = _mm_set_epi32((int)0xdfb49f2b, (int)0x6b772a12, (int)0x0efa4f2e, (int)0x29129fd4); @@ -111,77 +113,65 @@ static void load_haraka_constants(u128 rc[40]) { rc[39] = _mm_set_epi32((int)0x756acc03, (int)0x02288288, (int)0x4ad6bdfd, (int)0xe9c59da1); } -void PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_tweak_constants( - harakactx *state, - const unsigned char *pk_seed, const unsigned char *sk_seed, - unsigned long long seed_length) { +void tweak_constants(spx_ctx *ctx) { int i; unsigned char buf[40 * 16]; /* Use the standard constants to generate tweaked ones. */ - load_haraka_constants(state->rc); - - /* Constants for sk.seed */ - if (sk_seed != NULL) { - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_haraka_S(buf, 40 * 16, sk_seed, seed_length, state); - /* Tweak constants with the pub_seed */ - for (i = 0; i < 40; i++) { - state->rc_sseed[i] = LOAD(buf + i * 16); - } - } + load_haraka_constants(ctx->rc); /* Constants for pk.seed */ - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_haraka_S(buf, 40 * 16, pk_seed, seed_length, state); + haraka_S(buf, 40 * 16, ctx->pub_seed, SPX_N, ctx); /* Tweak constants with the pub_seed */ for (i = 0; i < 40; i++) { - state->rc[i] = LOAD(buf + i * 16); + ctx->rc[i] = LOAD(buf + i * 16); } } -static void haraka_S_absorb(unsigned char *s, +static void haraka_S_absorb(unsigned char *s, unsigned int r, const unsigned char *m, unsigned long long mlen, - unsigned char p, - const harakactx *state) { + unsigned char p, const spx_ctx *ctx) { unsigned long long i; - unsigned char t[HARAKAS_RATE]; + PQCLEAN_VLA(unsigned char, t, r); - while (mlen >= HARAKAS_RATE) { + while (mlen >= r) { // XOR block to state STORE(s, XOR128(LOAD(s), LOAD(m))); STORE(s + 16, XOR128(LOAD(s + 16), LOAD(m + 16))); - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_haraka512_perm(s, s, state); - mlen -= HARAKAS_RATE; - m += HARAKAS_RATE; + haraka512_perm(s, s, ctx); + mlen -= r; + m += r; } - for (i = 0; i < HARAKAS_RATE; ++i) { + for (i = 0; i < r; ++i) { t[i] = 0; } for (i = 0; i < mlen; ++i) { t[i] = m[i]; } t[i] = p; - t[HARAKAS_RATE - 1] |= 128; + t[r - 1] |= 128; STORE(s, XOR128(LOAD(s), LOAD(t))); STORE(s + 16, XOR128(LOAD(s + 16), LOAD(t + 16))); } static void haraka_S_absorb4x(unsigned char *s, + unsigned int r, const unsigned char *m0, const unsigned char *m1, const unsigned char *m2, const unsigned char *m3, unsigned long long int mlen, unsigned char p, - const harakactx *state) { + const spx_ctx *ctx) { unsigned long long i; - unsigned char t0[HARAKAS_RATE]; - unsigned char t1[HARAKAS_RATE]; - unsigned char t2[HARAKAS_RATE]; - unsigned char t3[HARAKAS_RATE]; + PQCLEAN_VLA(unsigned char, t0, r); + PQCLEAN_VLA(unsigned char, t1, r); + PQCLEAN_VLA(unsigned char, t2, r); + PQCLEAN_VLA(unsigned char, t3, r); - while (mlen >= HARAKAS_RATE) { + while (mlen >= r) { // XOR block to state STORE(s, XOR128(LOAD(s), LOAD(m0))); STORE(s + 16, XOR128(LOAD(s + 16), LOAD(m0 + 16))); @@ -192,15 +182,15 @@ static void haraka_S_absorb4x(unsigned char *s, STORE(s + 192, XOR128(LOAD(s + 192), LOAD(m3))); STORE(s + 208, XOR128(LOAD(s + 208), LOAD(m3 + 16))); - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_haraka512_perm_x4(s, s, state); - mlen -= HARAKAS_RATE; - m0 += HARAKAS_RATE; - m1 += HARAKAS_RATE; - m2 += HARAKAS_RATE; - m3 += HARAKAS_RATE; + haraka512_perm_x4(s, s, ctx); + mlen -= r; + m0 += r; + m1 += r; + m2 += r; + m3 += r; } - for (i = 0; i < HARAKAS_RATE; ++i) { + for (i = 0; i < r; ++i) { t0[i] = 0; t1[i] = 0; t2[i] = 0; @@ -218,10 +208,10 @@ static void haraka_S_absorb4x(unsigned char *s, t2[i] = p; t3[i] = p; - t0[HARAKAS_RATE - 1] |= 128; - t1[HARAKAS_RATE - 1] |= 128; - t2[HARAKAS_RATE - 1] |= 128; - t3[HARAKAS_RATE - 1] |= 128; + t0[r - 1] |= 128; + t1[r - 1] |= 128; + t2[r - 1] |= 128; + t3[r - 1] |= 128; STORE(s, XOR128(LOAD(s), LOAD(t0))); STORE(s + 16, XOR128(LOAD(s + 16), LOAD(t0 + 16))); @@ -234,9 +224,10 @@ static void haraka_S_absorb4x(unsigned char *s, } static void haraka_S_squeezeblocks(unsigned char *h, unsigned long long nblocks, - unsigned char *s, unsigned int r, const harakactx *state) { + unsigned char *s, unsigned int r, + const spx_ctx *ctx) { while (nblocks > 0) { - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_haraka512_perm(s, s, state); + haraka512_perm(s, s, ctx); STORE(h, LOAD(s)); STORE(h + 16, LOAD(s + 16)); h += r; @@ -251,9 +242,9 @@ static void haraka_S_squeezeblocks4x(unsigned char *h0, unsigned long long nblocks, unsigned char *s, unsigned int r, - const harakactx *state) { + const spx_ctx *ctx) { while (nblocks > 0) { - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_haraka512_perm_x4(s, s, state); + haraka512_perm_x4(s, s, ctx); STORE(h0, LOAD(s)); STORE(h0 + 16, LOAD(s + 16)); STORE(h1, LOAD(s + 64)); @@ -270,7 +261,7 @@ static void haraka_S_squeezeblocks4x(unsigned char *h0, } } -void PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_haraka_S_inc_init(uint8_t *s_inc) { +void haraka_S_inc_init(uint8_t *s_inc) { size_t i; for (i = 0; i < 64; i++) { @@ -279,7 +270,8 @@ void PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_haraka_S_inc_init(uint8_t *s_inc) { s_inc[64] = 0; } -void PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, const harakactx *state) { +void haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, + const spx_ctx *ctx) { size_t i; /* Recall that s_inc[64] is the non-absorbed bytes xored into the state */ @@ -293,16 +285,16 @@ void PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_haraka_S_inc_absorb(uint8_t *s_inc, c m += HARAKAS_RATE - s_inc[64]; s_inc[64] = 0; - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_haraka512_perm(s_inc, s_inc, state); + haraka512_perm(s_inc, s_inc, ctx); } for (i = 0; i < mlen; i++) { s_inc[s_inc[64] + i] ^= m[i]; } - s_inc[64] = (uint8_t)(s_inc[64] + mlen); + s_inc[64] += (uint8_t)mlen; } -void PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_haraka_S_inc_finalize(uint8_t *s_inc) { +void haraka_S_inc_finalize(uint8_t *s_inc) { /* After haraka_S_inc_absorb, we are guaranteed that s_inc[64] < HARAKAS_RATE, so we can always use one more byte for p in the current state. */ s_inc[s_inc[64]] ^= 0x1F; @@ -310,22 +302,23 @@ void PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_haraka_S_inc_finalize(uint8_t *s_inc) s_inc[64] = 0; } -void PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, const harakactx *state) { +void haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, + const spx_ctx *ctx) { size_t i; /* First consume any bytes we still have sitting around */ for (i = 0; i < outlen && i < s_inc[64]; i++) { /* There are s_inc[64] bytes left, so r - s_inc[64] is the first available byte. We consume from there, i.e., up to r. */ - out[i] = (uint8_t)s_inc[(HARAKAS_RATE - s_inc[64] + (uint8_t)i)]; + out[i] = (uint8_t)s_inc[(HARAKAS_RATE - s_inc[64] + i)]; } out += i; outlen -= i; - s_inc[64] = (uint8_t)(s_inc[64] - i); + s_inc[64] -= (uint8_t)i; /* Then squeeze the remaining necessary blocks */ while (outlen > 0) { - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_haraka512_perm(s_inc, s_inc, state); + haraka512_perm(s_inc, s_inc, ctx); for (i = 0; i < outlen && i < HARAKAS_RATE; i++) { out[i] = s_inc[i]; @@ -336,8 +329,9 @@ void PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_haraka_S_inc_squeeze(uint8_t *out, si } } -void PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_haraka_S(unsigned char *out, unsigned long long outlen, - const unsigned char *in, unsigned long long inlen, const harakactx *state) { +void haraka_S(unsigned char *out, unsigned long long outlen, + const unsigned char *in, unsigned long long inlen, + const spx_ctx *ctx) { unsigned long long i; unsigned char s[64]; unsigned char d[32]; @@ -345,30 +339,30 @@ void PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_haraka_S(unsigned char *out, unsigned for (i = 0; i < 64; i++) { s[i] = 0; } - haraka_S_absorb(s, in, inlen, 0x1F, state); + haraka_S_absorb(s, HARAKAS_RATE, in, inlen, 0x1F, ctx); - haraka_S_squeezeblocks(out, outlen / HARAKAS_RATE, s, HARAKAS_RATE, state); + haraka_S_squeezeblocks(out, outlen / HARAKAS_RATE, s, HARAKAS_RATE, ctx); out += (outlen / HARAKAS_RATE) * HARAKAS_RATE; if (outlen % HARAKAS_RATE) { - haraka_S_squeezeblocks(d, 1, s, HARAKAS_RATE, state); + haraka_S_squeezeblocks(d, 1, s, HARAKAS_RATE, ctx); for (i = 0; i < outlen % HARAKAS_RATE; i++) { out[i] = d[i]; } } } -void PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_haraka_Sx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned long long outlen, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - unsigned long long inlen, - const harakactx *state) { +void haraka_Sx4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned long long outlen, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + unsigned long long inlen, + const spx_ctx *ctx) { unsigned long long i; unsigned char s[64 * 4]; unsigned char d0[32]; @@ -379,16 +373,17 @@ void PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_haraka_Sx4(unsigned char *out0, for (i = 0; i < 64 * 4; i++) { s[i] = 0; } - haraka_S_absorb4x(s, in0, in1, in2, in3, inlen, 0x1F, state); + haraka_S_absorb4x(s, HARAKAS_RATE, in0, in1, in2, in3, inlen, 0x1F, ctx); - haraka_S_squeezeblocks4x(out0, out1, out2, out3, outlen / HARAKAS_RATE, s, HARAKAS_RATE, state); + haraka_S_squeezeblocks4x(out0, out1, out2, out3, outlen / HARAKAS_RATE, s, + HARAKAS_RATE, ctx); out0 += (outlen / HARAKAS_RATE) * HARAKAS_RATE; out1 += (outlen / HARAKAS_RATE) * HARAKAS_RATE; out2 += (outlen / HARAKAS_RATE) * HARAKAS_RATE; out3 += (outlen / HARAKAS_RATE) * HARAKAS_RATE; if (outlen % HARAKAS_RATE) { - haraka_S_squeezeblocks4x(d0, d1, d2, d3, 1, s, HARAKAS_RATE, state); + haraka_S_squeezeblocks4x(d0, d1, d2, d3, 1, s, HARAKAS_RATE, ctx); for (i = 0; i < outlen % HARAKAS_RATE; i++) { out0[i] = d0[i]; out1[i] = d1[i]; @@ -398,7 +393,8 @@ void PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_haraka_Sx4(unsigned char *out0, } } -void PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_haraka512_perm(unsigned char *out, const unsigned char *in, const harakactx *state) { +void haraka512_perm(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx) { u128 s[4], tmp; s[0] = LOAD(in); @@ -406,19 +402,19 @@ void PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_haraka512_perm(unsigned char *out, co s[2] = LOAD(in + 32); s[3] = LOAD(in + 48); - AES4(s[0], s[1], s[2], s[3], state->rc); + AES4(s[0], s[1], s[2], s[3], ctx->rc); MIX4(s[0], s[1], s[2], s[3]); - AES4(s[0], s[1], s[2], s[3], state->rc + 8); + AES4(s[0], s[1], s[2], s[3], ctx->rc + 8); MIX4(s[0], s[1], s[2], s[3]); - AES4(s[0], s[1], s[2], s[3], state->rc + 16); + AES4(s[0], s[1], s[2], s[3], ctx->rc + 16); MIX4(s[0], s[1], s[2], s[3]); - AES4(s[0], s[1], s[2], s[3], state->rc + 24); + AES4(s[0], s[1], s[2], s[3], ctx->rc + 24); MIX4(s[0], s[1], s[2], s[3]); - AES4(s[0], s[1], s[2], s[3], state->rc + 32); + AES4(s[0], s[1], s[2], s[3], ctx->rc + 32); MIX4(s[0], s[1], s[2], s[3]); STORE(out, s[0]); @@ -427,7 +423,8 @@ void PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_haraka512_perm(unsigned char *out, co STORE(out + 48, s[3]); } -void PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_haraka512_perm_x4(unsigned char *out, const unsigned char *in, const harakactx *state) { +void haraka512_perm_x4(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx) { u128 s[4][4], tmp; s[0][0] = LOAD(in); @@ -447,31 +444,31 @@ void PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_haraka512_perm_x4(unsigned char *out, s[3][2] = LOAD(in + 224); s[3][3] = LOAD(in + 240); - AES4_4x(s[0], s[1], s[2], s[3], state->rc); + AES4_4x(s[0], s[1], s[2], s[3], ctx->rc); MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - AES4_4x(s[0], s[1], s[2], s[3], state->rc + 8); + AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 8); MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - AES4_4x(s[0], s[1], s[2], s[3], state->rc + 16); + AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 16); MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - AES4_4x(s[0], s[1], s[2], s[3], state->rc + 24); + AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 24); MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - AES4_4x(s[0], s[1], s[2], s[3], state->rc + 32); + AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 32); MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); @@ -495,7 +492,8 @@ void PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_haraka512_perm_x4(unsigned char *out, STORE(out + 240, s[3][3]); } -void PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_haraka512(unsigned char *out, const unsigned char *in, const harakactx *state) { +void haraka512(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx) { u128 s[4], tmp; s[0] = LOAD(in); @@ -503,19 +501,19 @@ void PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_haraka512(unsigned char *out, const u s[2] = LOAD(in + 32); s[3] = LOAD(in + 48); - AES4(s[0], s[1], s[2], s[3], state->rc); + AES4(s[0], s[1], s[2], s[3], ctx->rc); MIX4(s[0], s[1], s[2], s[3]); - AES4(s[0], s[1], s[2], s[3], state->rc + 8); + AES4(s[0], s[1], s[2], s[3], ctx->rc + 8); MIX4(s[0], s[1], s[2], s[3]); - AES4(s[0], s[1], s[2], s[3], state->rc + 16); + AES4(s[0], s[1], s[2], s[3], ctx->rc + 16); MIX4(s[0], s[1], s[2], s[3]); - AES4(s[0], s[1], s[2], s[3], state->rc + 24); + AES4(s[0], s[1], s[2], s[3], ctx->rc + 24); MIX4(s[0], s[1], s[2], s[3]); - AES4(s[0], s[1], s[2], s[3], state->rc + 32); + AES4(s[0], s[1], s[2], s[3], ctx->rc + 32); MIX4(s[0], s[1], s[2], s[3]); s[0] = XOR128(s[0], LOAD(in)); @@ -527,7 +525,8 @@ void PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_haraka512(unsigned char *out, const u TRUNCSTORE(out, s[0], s[1], s[2], s[3]); } -void PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_haraka512x4(unsigned char *out, const unsigned char *in, const harakactx *state) { +void haraka512x4(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx) { u128 s[4][4], tmp; s[0][0] = LOAD(in); @@ -547,31 +546,31 @@ void PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_haraka512x4(unsigned char *out, const s[3][2] = LOAD(in + 224); s[3][3] = LOAD(in + 240); - AES4_4x(s[0], s[1], s[2], s[3], state->rc); + AES4_4x(s[0], s[1], s[2], s[3], ctx->rc); MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - AES4_4x(s[0], s[1], s[2], s[3], state->rc + 8); + AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 8); MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - AES4_4x(s[0], s[1], s[2], s[3], state->rc + 16); + AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 16); MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - AES4_4x(s[0], s[1], s[2], s[3], state->rc + 24); + AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 24); MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - AES4_4x(s[0], s[1], s[2], s[3], state->rc + 32); + AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 32); MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); @@ -600,25 +599,26 @@ void PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_haraka512x4(unsigned char *out, const TRUNCSTORE((out + 96), s[3][0], s[3][1], s[3][2], s[3][3]); } -void PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_haraka256(unsigned char *out, const unsigned char *in, const harakactx *state) { +void haraka256(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx) { u128 s[2], tmp; s[0] = LOAD(in); s[1] = LOAD(in + 16); - AES2(s[0], s[1], state->rc); + AES2(s[0], s[1], ctx->rc); MIX2(s[0], s[1]); - AES2(s[0], s[1], state->rc + 4); + AES2(s[0], s[1], ctx->rc + 4); MIX2(s[0], s[1]); - AES2(s[0], s[1], state->rc + 8); + AES2(s[0], s[1], ctx->rc + 8); MIX2(s[0], s[1]); - AES2(s[0], s[1], state->rc + 12); + AES2(s[0], s[1], ctx->rc + 12); MIX2(s[0], s[1]); - AES2(s[0], s[1], state->rc + 16); + AES2(s[0], s[1], ctx->rc + 16); MIX2(s[0], s[1]); s[0] = XOR128(s[0], LOAD(in)); @@ -628,7 +628,8 @@ void PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_haraka256(unsigned char *out, const u STORE(out + 16, s[1]); } -void PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_haraka256x4(unsigned char *out, const unsigned char *in, const harakactx *state) { +void haraka256x4(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx) { u128 s[4][2], tmp; s[0][0] = LOAD(in); @@ -641,7 +642,7 @@ void PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_haraka256x4(unsigned char *out, const s[3][1] = LOAD(in + 112); // Round 1 - AES2_4x(s[0], s[1], s[2], s[3], state->rc); + AES2_4x(s[0], s[1], s[2], s[3], ctx->rc); MIX2(s[0][0], s[0][1]); MIX2(s[1][0], s[1][1]); @@ -649,7 +650,7 @@ void PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_haraka256x4(unsigned char *out, const MIX2(s[3][0], s[3][1]); // Round 2 - AES2_4x(s[0], s[1], s[2], s[3], state->rc + 4); + AES2_4x(s[0], s[1], s[2], s[3], ctx->rc + 4); MIX2(s[0][0], s[0][1]); MIX2(s[1][0], s[1][1]); @@ -657,7 +658,7 @@ void PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_haraka256x4(unsigned char *out, const MIX2(s[3][0], s[3][1]); // Round 3 - AES2_4x(s[0], s[1], s[2], s[3], state->rc + 8); + AES2_4x(s[0], s[1], s[2], s[3], ctx->rc + 8); MIX2(s[0][0], s[0][1]); MIX2(s[1][0], s[1][1]); @@ -665,7 +666,7 @@ void PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_haraka256x4(unsigned char *out, const MIX2(s[3][0], s[3][1]); // Round 4 - AES2_4x(s[0], s[1], s[2], s[3], state->rc + 12); + AES2_4x(s[0], s[1], s[2], s[3], ctx->rc + 12); MIX2(s[0][0], s[0][1]); MIX2(s[1][0], s[1][1]); @@ -673,7 +674,7 @@ void PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_haraka256x4(unsigned char *out, const MIX2(s[3][0], s[3][1]); // Round 5 - AES2_4x(s[0], s[1], s[2], s[3], state->rc + 16); + AES2_4x(s[0], s[1], s[2], s[3], ctx->rc + 16); MIX2(s[0][0], s[0][1]); MIX2(s[1][0], s[1][1]); @@ -699,103 +700,3 @@ void PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_haraka256x4(unsigned char *out, const STORE(out + 96, s[3][0]); STORE(out + 112, s[3][1]); } - -void PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_haraka256_sk(unsigned char *out, const unsigned char *in, const harakactx *state) { - u128 s[2], tmp; - - s[0] = LOAD(in); - s[1] = LOAD(in + 16); - - AES2(s[0], s[1], state->rc_sseed); - MIX2(s[0], s[1]); - - AES2(s[0], s[1], state->rc_sseed + 4); - MIX2(s[0], s[1]); - - AES2(s[0], s[1], state->rc_sseed + 8); - MIX2(s[0], s[1]); - - AES2(s[0], s[1], state->rc_sseed + 12); - MIX2(s[0], s[1]); - - AES2(s[0], s[1], state->rc_sseed + 16); - MIX2(s[0], s[1]); - - s[0] = XOR128(s[0], LOAD(in)); - s[1] = XOR128(s[1], LOAD(in + 16)); - - STORE(out, s[0]); - STORE(out + 16, s[1]); -} - -void PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_haraka256_skx4(unsigned char *out, const unsigned char *in, const harakactx *state) { - u128 s[4][2], tmp; - - s[0][0] = LOAD(in); - s[0][1] = LOAD(in + 16); - s[1][0] = LOAD(in + 32); - s[1][1] = LOAD(in + 48); - s[2][0] = LOAD(in + 64); - s[2][1] = LOAD(in + 80); - s[3][0] = LOAD(in + 96); - s[3][1] = LOAD(in + 112); - - // Round 1 - AES2_4x(s[0], s[1], s[2], s[3], state->rc_sseed); - - MIX2(s[0][0], s[0][1]); - MIX2(s[1][0], s[1][1]); - MIX2(s[2][0], s[2][1]); - MIX2(s[3][0], s[3][1]); - - // Round 2 - AES2_4x(s[0], s[1], s[2], s[3], state->rc_sseed + 4); - - MIX2(s[0][0], s[0][1]); - MIX2(s[1][0], s[1][1]); - MIX2(s[2][0], s[2][1]); - MIX2(s[3][0], s[3][1]); - - // Round 3 - AES2_4x(s[0], s[1], s[2], s[3], state->rc_sseed + 8); - - MIX2(s[0][0], s[0][1]); - MIX2(s[1][0], s[1][1]); - MIX2(s[2][0], s[2][1]); - MIX2(s[3][0], s[3][1]); - - // Round 4 - AES2_4x(s[0], s[1], s[2], s[3], state->rc_sseed + 12); - - MIX2(s[0][0], s[0][1]); - MIX2(s[1][0], s[1][1]); - MIX2(s[2][0], s[2][1]); - MIX2(s[3][0], s[3][1]); - - // Round 5 - AES2_4x(s[0], s[1], s[2], s[3], state->rc_sseed + 16); - - MIX2(s[0][0], s[0][1]); - MIX2(s[1][0], s[1][1]); - MIX2(s[2][0], s[2][1]); - MIX2(s[3][0], s[3][1]); - - // Feed Forward - s[0][0] = XOR128(s[0][0], LOAD(in)); - s[0][1] = XOR128(s[0][1], LOAD(in + 16)); - s[1][0] = XOR128(s[1][0], LOAD(in + 32)); - s[1][1] = XOR128(s[1][1], LOAD(in + 48)); - s[2][0] = XOR128(s[2][0], LOAD(in + 64)); - s[2][1] = XOR128(s[2][1], LOAD(in + 80)); - s[3][0] = XOR128(s[3][0], LOAD(in + 96)); - s[3][1] = XOR128(s[3][1], LOAD(in + 112)); - - STORE(out, s[0][0]); - STORE(out + 16, s[0][1]); - STORE(out + 32, s[1][0]); - STORE(out + 48, s[1][1]); - STORE(out + 64, s[2][0]); - STORE(out + 80, s[2][1]); - STORE(out + 96, s[3][0]); - STORE(out + 112, s[3][1]); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/haraka.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/haraka.h index 9c2a8dede1..737cb6065f 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/haraka.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/haraka.h @@ -1,57 +1,42 @@ -#ifndef PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_HARAKA_H -#define PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_HARAKA_H +#ifndef SPX_HARAKA_H +#define SPX_HARAKA_H -#include -#include -#include - -typedef struct { - __m128i rc[40]; - __m128i rc_sseed[40]; -} harakactx; +#include "context.h" +#include "params.h" /* Tweak constants with seed */ -void PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_tweak_constants( - harakactx *state, - const unsigned char *pk_seed, const unsigned char *sk_seed, - unsigned long long seed_length); +#define tweak_constants SPX_NAMESPACE(tweak_constants) +void tweak_constants(spx_ctx *ctx); /* Haraka Sponge */ -void PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_haraka_S_inc_init(uint8_t *s_inc); -void PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, const harakactx *state); -void PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_haraka_S_inc_finalize(uint8_t *s_inc); -void PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, const harakactx *state); -void PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_haraka_S( - unsigned char *out, unsigned long long outlen, - const unsigned char *in, unsigned long long inlen, const harakactx *state); -void PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_haraka_Sx4( - unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned long long outlen, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - unsigned long long inlen, - const harakactx *state); - +#define haraka_S_inc_init SPX_NAMESPACE(haraka_S_inc_init) +void haraka_S_inc_init(uint8_t *s_inc); +#define haraka_S_inc_absorb SPX_NAMESPACE(haraka_S_inc_absorb) +void haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, + const spx_ctx *ctx); +#define haraka_S_inc_finalize SPX_NAMESPACE(haraka_S_inc_finalize) +void haraka_S_inc_finalize(uint8_t *s_inc); +#define haraka_S_inc_squeeze SPX_NAMESPACE(haraka_S_inc_squeeze) +void haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, + const spx_ctx *ctx); +#define haraka_S SPX_NAMESPACE(haraka_S) +void haraka_S(unsigned char *out, unsigned long long outlen, + const unsigned char *in, unsigned long long inlen, + const spx_ctx *ctx); /* Applies the 512-bit Haraka permutation to in. */ -void PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_haraka512_perm(unsigned char *out, const unsigned char *in, const harakactx *state); -void PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_haraka512_perm_x4(unsigned char *out, const unsigned char *in, const harakactx *state); +#define haraka512_perm SPX_NAMESPACE(haraka512_perm) +void haraka512_perm(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx); /* Implementation of Haraka-512 */ -void PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_haraka512(unsigned char *out, const unsigned char *in, const harakactx *state); -void PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_haraka512x4(unsigned char *out, const unsigned char *in, const harakactx *state); +#define haraka512 SPX_NAMESPACE(haraka512) +void haraka512(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx); /* Implementation of Haraka-256 */ -void PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_haraka256(unsigned char *out, const unsigned char *in, const harakactx *state); -void PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_haraka256x4(unsigned char *out, const unsigned char *in, const harakactx *state); - -/* Implementation of Haraka-256 using sk.seed constants */ -void PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_haraka256_sk(unsigned char *out, const unsigned char *in, const harakactx *state); -void PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_haraka256_skx4(unsigned char *out, const unsigned char *in, const harakactx *state); +#define haraka256 SPX_NAMESPACE(haraka256) +void haraka256(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/haraka_offsets.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/haraka_offsets.h new file mode 100644 index 0000000000..7c062272a0 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/haraka_offsets.h @@ -0,0 +1,21 @@ +#ifndef HARAKA_OFFSETS_H_ +#define HARAKA_OFFSETS_H_ + +/* + * Offsets of various fields in the address structure when we use Haraka as + * the Sphincs+ hash function + */ + +#define SPX_OFFSET_LAYER 3 /* The byte used to specify the Merkle tree layer */ +#define SPX_OFFSET_TREE 8 /* The start of the 8 byte field used to specify the tree */ +#define SPX_OFFSET_TYPE 19 /* The byte used to specify the hash type (reason) */ +#define SPX_OFFSET_KP_ADDR2 22 /* The high byte used to specify the key pair (which one-time signature) */ +#define SPX_OFFSET_KP_ADDR1 23 /* The low byte used to specify the key pair */ +#define SPX_OFFSET_CHAIN_ADDR 27 /* The byte used to specify the chain address (which Winternitz chain) */ +#define SPX_OFFSET_HASH_ADDR 31 /* The byte used to specify the hash address (where in the Winternitz chain) */ +#define SPX_OFFSET_TREE_HGT 27 /* The byte used to specify the height of this node in the FORS or Merkle tree */ +#define SPX_OFFSET_TREE_INDEX 28 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ + +#define SPX_HARAKA 1 + +#endif /* HARAKA_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/harakax4.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/harakax4.h new file mode 100644 index 0000000000..eadc69aa48 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/harakax4.h @@ -0,0 +1,36 @@ +#ifndef SPX_HARAKAX4_H +#define SPX_HARAKAX4_H + +#include "context.h" +#include "params.h" + +/* Haraka Sponge */ +#define haraka_Sx4 SPX_NAMESPACE(haraka_Sx4) +void haraka_Sx4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned long long outlen, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + unsigned long long inlen, + const spx_ctx *ctx); + +/* Applies the 512-bit Haraka permutation x4 to in. */ +#define haraka512_perm_x4 SPX_NAMESPACE(haraka512_perm_x4) +void haraka512_perm_x4(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx); + +/* Implementation of Haraka-512 x4*/ +#define haraka512x4 SPX_NAMESPACE(haraka512x4) +void haraka512x4(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx); + +/* Implementation of Haraka-256 x4 */ +#define haraka256x4 SPX_NAMESPACE(haraka256x4) +void haraka256x4(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/hash.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/hash.h index d788d481ed..f7c87d4c3c 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/hash.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/hash.h @@ -1,31 +1,28 @@ -#ifndef PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_HASH_H -#define PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_HASH_H - -#include "hash_state.h" +#ifndef SPX_HASH_H +#define SPX_HASH_H #include #include -void PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_initialize_hash_function( - hash_state *hash_state_seeded, - const unsigned char *pub_seed, const unsigned char *sk_seed); +#include "context.h" +#include "params.h" + +#define prf_addr SPX_NAMESPACE(prf_addr) +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]); -void PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_destroy_hash_function(hash_state *hash_state_seeded); +#define gen_message_random SPX_NAMESPACE(gen_message_random) +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); -void PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded); +#define hash_message SPX_NAMESPACE(hash_message) +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); -void PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); -void PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/hash_haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/hash_haraka.c index cb88f1f42a..750a67423b 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/hash_haraka.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/hash_haraka.c @@ -2,58 +2,44 @@ #include #include "address.h" -#include "haraka.h" -#include "hash.h" #include "params.h" #include "utils.h" -void PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_initialize_hash_function( - hash_state *hash_state_seeded, - const unsigned char *pub_seed, const unsigned char *sk_seed) { - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_tweak_constants(hash_state_seeded, pub_seed, sk_seed, PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N); -} - -/* The haraka implementation is stack based and won't be replaced in PQClean/OQS, - so we don't need to do anything */ -void PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_destroy_hash_function( - hash_state *hash_state_seeded) { // NOLINT(readability-non-const-parameter) - (void)hash_state_seeded; -} +#include "haraka.h" +#include "hash.h" /* - * Computes PRF(key, addr), given a secret key of PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N bytes and an address + * Computes PRF(key, addr), given a secret key of SPX_N bytes and an address */ -void PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded) { - unsigned char buf[PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_ADDR_BYTES]; - /* Since PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N may be smaller than 32, we need a temporary buffer. */ +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]) { + /* Since SPX_N may be smaller than 32, we need temporary buffers. */ unsigned char outbuf[32]; + unsigned char buf[64] = {0}; - (void)key; /* Suppress an 'unused parameter' warning. */ + memcpy(buf, addr, SPX_ADDR_BYTES); + memcpy(buf + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_addr_to_bytes(buf, addr); - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_haraka256_sk(outbuf, buf, hash_state_seeded); - memcpy(out, outbuf, PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N); + haraka512(outbuf, (const void *)buf, ctx); + memcpy(out, outbuf, SPX_N); } /** * Computes the message-dependent randomness R, using a secret seed and an * optional randomization value as well as the message. */ -void PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded) { +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { uint8_t s_inc[65]; - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_haraka_S_inc_init(s_inc); - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_haraka_S_inc_absorb(s_inc, sk_prf, PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_haraka_S_inc_absorb(s_inc, optrand, PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_haraka_S_inc_absorb(s_inc, m, mlen, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_haraka_S_inc_finalize(s_inc); - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_haraka_S_inc_squeeze(R, PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N, s_inc, hash_state_seeded); + haraka_S_inc_init(s_inc); + haraka_S_inc_absorb(s_inc, sk_prf, SPX_N, ctx); + haraka_S_inc_absorb(s_inc, optrand, SPX_N, ctx); + haraka_S_inc_absorb(s_inc, m, mlen, ctx); + haraka_S_inc_finalize(s_inc); + haraka_S_inc_squeeze(R, SPX_N, s_inc, ctx); } /** @@ -61,36 +47,35 @@ void PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_gen_message_random( * Outputs the message digest and the index of the leaf. The index is split in * the tree index and the leaf index, for convenient copying to an address. */ -void PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded) { -#define PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_TREE_BITS (PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_TREE_HEIGHT * (PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_D - 1)) -#define PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_TREE_BYTES ((PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_TREE_BITS + 7) / 8) -#define PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_LEAF_BITS PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_TREE_HEIGHT -#define PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_LEAF_BYTES ((PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_LEAF_BITS + 7) / 8) -#define PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_DGST_BYTES (PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_FORS_MSG_BYTES + PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_TREE_BYTES + PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_LEAF_BYTES) +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { +#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) +#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) +#define SPX_LEAF_BITS SPX_TREE_HEIGHT +#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) +#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) - unsigned char buf[PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_DGST_BYTES]; + unsigned char buf[SPX_DGST_BYTES]; unsigned char *bufp = buf; uint8_t s_inc[65]; - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_haraka_S_inc_init(s_inc); - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_haraka_S_inc_absorb(s_inc, R, PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_haraka_S_inc_absorb(s_inc, pk + PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N, PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_haraka_S_inc_absorb(s_inc, m, mlen, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_haraka_S_inc_finalize(s_inc); - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_haraka_S_inc_squeeze(buf, PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_DGST_BYTES, s_inc, hash_state_seeded); + haraka_S_inc_init(s_inc); + haraka_S_inc_absorb(s_inc, R, SPX_N, ctx); + haraka_S_inc_absorb(s_inc, pk + SPX_N, SPX_N, ctx); // Only absorb root part of pk + haraka_S_inc_absorb(s_inc, m, mlen, ctx); + haraka_S_inc_finalize(s_inc); + haraka_S_inc_squeeze(buf, SPX_DGST_BYTES, s_inc, ctx); + + memcpy(digest, bufp, SPX_FORS_MSG_BYTES); + bufp += SPX_FORS_MSG_BYTES; - memcpy(digest, bufp, PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_FORS_MSG_BYTES); - bufp += PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_FORS_MSG_BYTES; - *tree = PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_bytes_to_ull(bufp, PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_TREE_BYTES); - *tree &= (~(uint64_t)0) >> (64 - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_TREE_BITS); - bufp += PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_TREE_BYTES; + *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); + *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); + bufp += SPX_TREE_BYTES; - *leaf_idx = (uint32_t)PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_bytes_to_ull( - bufp, PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_LEAF_BYTES); - *leaf_idx &= (~(uint32_t)0) >> (32 - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_LEAF_BITS); + *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); + *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/hash_harakax4.c b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/hash_harakax4.c index 77b4eb1e4d..cfa5162d79 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/hash_harakax4.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/hash_harakax4.c @@ -2,36 +2,34 @@ #include #include "address.h" -#include "haraka.h" -#include "hash_state.h" +#include "harakax4.h" #include "hashx4.h" #include "params.h" /* * 4-way parallel version of prf_addr; takes 4x as much input and output */ -void PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_prf_addrx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const unsigned char *key, - const uint32_t addrx4[4 * 8], - const hash_state *state_seeded) { - unsigned char bufx4[4 * PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_ADDR_BYTES]; - /* Since PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N may be smaller than 32, we need a temporary buffer. */ +#define prf_addrx4 SPX_NAMESPACE(prf_addrx4) +void prf_addrx4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const spx_ctx *ctx, + const uint32_t addrx4[4 * 8]) { + unsigned char bufx4[4 * 64] = {0}; + /* Since SPX_N may be smaller than 32, we need temporary buffers. */ unsigned char outbuf[4 * 32]; unsigned int i; - (void)key; /* Suppress an 'unused parameter' warning. */ - for (i = 0; i < 4; i++) { - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_addr_to_bytes(bufx4 + i * PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_ADDR_BYTES, addrx4 + i * 8); + memcpy(bufx4 + i * 64, addrx4 + i * 8, SPX_ADDR_BYTES); + memcpy(bufx4 + i * 64 + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); } - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_haraka256_skx4(outbuf, bufx4, state_seeded); + haraka512x4(outbuf, bufx4, ctx); - memcpy(out0, outbuf, PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N); - memcpy(out1, outbuf + 32, PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N); - memcpy(out2, outbuf + 64, PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N); - memcpy(out3, outbuf + 96, PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N); + memcpy(out0, outbuf, SPX_N); + memcpy(out1, outbuf + 32, SPX_N); + memcpy(out2, outbuf + 64, SPX_N); + memcpy(out3, outbuf + 96, SPX_N); } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/hash_state.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/hash_state.h deleted file mode 100644 index 81ba3aea9a..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/hash_state.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_HASH_STATE_H -#define PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_HASH_STATE_H - -/** - * Defines the type of the hash function state. - * - * Don't be fooled into thinking this instance of SPHINCS+ isn't stateless! - * - * From Section 7.2.2 from the SPHINCS+ round-2 specification: - * - * Each of the instances of the tweakable hash function take PK.seed as its - * first input, which is constant for a given key pair – and, thus, across - * a single signature. This leads to a lot of redundant computation. To remedy - * this, we pad PK.seed to the length of a full 64-byte SHA-256 input block. - * Because of the Merkle-DamgÃ¥rd construction that underlies SHA-256, this - * allows for reuse of the intermediate SHA-256 state after the initial call to - * the compression function which improves performance. - * - * We pass this hash state around in functions, because otherwise we need to - * have a global variable. - */ - -#include "haraka.h" -#define hash_state harakactx - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/hashx4.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/hashx4.h index a4c75c3968..3751a0ebd0 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/hashx4.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/hashx4.h @@ -1,16 +1,17 @@ -#ifndef PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_HASHX4_H -#define PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_HASHX4_H +#ifndef SPX_HASHX4_H +#define SPX_HASHX4_H #include -#include "hash_state.h" +#include "context.h" +#include "params.h" -void PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_prf_addrx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const unsigned char *key, - const uint32_t addrx4[4 * 8], - const hash_state *state_seeded); +#define prf_addrx4 SPX_NAMESPACE(prf_addrx4) +void prf_addrx4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const spx_ctx *ctx, + const uint32_t addrx4[4 * 8]); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/merkle.c b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/merkle.c new file mode 100644 index 0000000000..f57811c1ac --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/merkle.c @@ -0,0 +1,64 @@ +#include +#include + +#include "merkle.h" + +#include "address.h" +#include "params.h" +#include "utils.h" +#include "utilsx4.h" +#include "wots.h" +#include "wotsx4.h" + +/* + * This generates a Merkle signature (WOTS signature followed by the Merkle + * authentication path). + */ +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf) { + unsigned char *auth_path = sig + SPX_WOTS_BYTES; + uint32_t tree_addrx4[4 * 8] = { 0 }; + int j; + struct leaf_info_x4 info = { 0 }; + unsigned steps[ SPX_WOTS_LEN ]; + + info.wots_sig = sig; + chain_lengths(steps, root); + info.wots_steps = steps; + + for (j = 0; j < 4; j++) { + set_type(&tree_addrx4[8 * j], SPX_ADDR_TYPE_HASHTREE); + set_type(&info.leaf_addr[8 * j], SPX_ADDR_TYPE_WOTS); + set_type(&info.pk_addr[8 * j], SPX_ADDR_TYPE_WOTSPK); + copy_subtree_addr(&tree_addrx4[8 * j], tree_addr); + copy_subtree_addr(&info.leaf_addr[8 * j], wots_addr); + copy_subtree_addr(&info.pk_addr[8 * j], wots_addr); + } + + info.wots_sign_leaf = idx_leaf; + + treehashx4(root, auth_path, ctx, + idx_leaf, 0, + SPX_TREE_HEIGHT, + wots_gen_leafx4, + tree_addrx4, &info); +} + +/* Compute root node of the top-most subtree. */ +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { + /* We do not need the auth path in key generation, but it simplifies the + code to have just one treehash routine that computes both root and path + in one function. */ + unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; + uint32_t top_tree_addr[8] = {0}; + uint32_t wots_addr[8] = {0}; + + set_layer_addr(top_tree_addr, SPX_D - 1); + set_layer_addr(wots_addr, SPX_D - 1); + + merkle_sign(auth_path, root, ctx, + wots_addr, top_tree_addr, + ~0U /* ~0 means "don't bother generating an auth path */ ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/merkle.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/merkle.h new file mode 100644 index 0000000000..769cf2e970 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/merkle.h @@ -0,0 +1,21 @@ +#ifndef MERKLE_H_ +#define MERKLE_H_ + +#include + +#include "context.h" +#include "params.h" + +/* Generate a Merkle signature (WOTS signature followed by the Merkle */ +/* authentication path) */ +#define merkle_sign SPX_NAMESPACE(merkle_sign) +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf); + +/* Compute the root node of the top-most subtree. */ +#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); + +#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/nistapi.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/nistapi.h new file mode 100644 index 0000000000..3cb71afad4 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/nistapi.h @@ -0,0 +1,87 @@ +#ifndef SPX_API_H +#define SPX_API_H + +#include +#include + +#include "params.h" + +#define CRYPTO_ALGNAME "SPHINCS+" + +#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES +#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES +#define CRYPTO_BYTES SPX_BYTES +#define CRYPTO_SEEDBYTES (3*SPX_N) + +/* + * Returns the length of a secret key, in bytes + */ +#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) +size_t crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) +size_t crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) +size_t crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) +size_t crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +#define crypto_sign SPX_NAMESPACE(crypto_sign) +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/params.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/params.h index 1fb3fc9f75..8188bbdd3b 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/params.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/params.h @@ -1,53 +1,56 @@ -#ifndef PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_PARAMS_H -#define PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_PARAMS_H +#ifndef SPX_PARAMS_H +#define SPX_PARAMS_H + +#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_##s /* Hash output length in bytes. */ -#define PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N 24 +#define SPX_N 24 /* Height of the hypertree. */ -#define PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_FULL_HEIGHT 66 +#define SPX_FULL_HEIGHT 66 /* Number of subtree layer. */ -#define PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_D 22 +#define SPX_D 22 /* FORS tree dimensions. */ -#define PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_FORS_HEIGHT 8 -#define PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_FORS_TREES 33 +#define SPX_FORS_HEIGHT 8 +#define SPX_FORS_TREES 33 /* Winternitz parameter, */ -#define PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_WOTS_W 16 +#define SPX_WOTS_W 16 /* The hash function is defined by linking a different hash.c file, as opposed to setting a #define constant. */ /* For clarity */ -#define PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_ADDR_BYTES 32 +#define SPX_ADDR_BYTES 32 /* WOTS parameters. */ -#define PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_WOTS_LOGW 4 +#define SPX_WOTS_LOGW 4 -#define PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_WOTS_LEN1 (8 * PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N / PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_WOTS_LOGW) +#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) -/* PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#define PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_WOTS_LEN2 3 +/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ +#define SPX_WOTS_LEN2 3 -#define PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_WOTS_LEN (PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_WOTS_LEN1 + PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_WOTS_LEN2) -#define PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_WOTS_BYTES (PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_WOTS_LEN * PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N) -#define PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_WOTS_PK_BYTES PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_WOTS_BYTES +#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) +#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) +#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES /* Subtree size. */ -#define PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_TREE_HEIGHT (PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_FULL_HEIGHT / PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_D) +#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) + +//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT +// #error SPX_D should always divide SPX_FULL_HEIGHT +//#endif /* FORS parameters. */ -#define PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_FORS_MSG_BYTES ((PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_FORS_TREES + 7) / 8) -#define PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_FORS_BYTES ((PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_FORS_HEIGHT + 1) * PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_FORS_TREES * PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N) -#define PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_FORS_PK_BYTES PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N +#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) +#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) +#define SPX_FORS_PK_BYTES SPX_N /* Resulting SPX sizes. */ -#define PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_BYTES (PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N + PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_FORS_BYTES + PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_D * PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_WOTS_BYTES +\ - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_FULL_HEIGHT * PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N) -#define PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_PK_BYTES (2 * PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N) -#define PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_SK_BYTES (2 * PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N + PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_PK_BYTES) - -/* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ -#define PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_OPTRAND_BYTES 32 +#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ + SPX_FULL_HEIGHT * SPX_N) +#define SPX_PK_BYTES (2 * SPX_N) +#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) + +#include "haraka_offsets.h" #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/sign.c b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/sign.c index 5b5c495644..9d0c7d1b22 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/sign.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/sign.c @@ -1,76 +1,45 @@ -#include #include #include #include #include "address.h" -#include "api.h" +#include "context.h" #include "fors.h" #include "hash.h" -#include "hash_state.h" +#include "merkle.h" +#include "nistapi.h" #include "params.h" #include "randombytes.h" #include "thash.h" #include "utils.h" #include "wots.h" - -/** - * Computes the leaf at a given address. First generates the WOTS key pair, - * then computes leaf by hashing horizontally. - */ -static void wots_gen_leaf(unsigned char *leaf, const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx, const uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - unsigned char pk[PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_WOTS_BYTES]; - uint32_t wots_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_set_type( - wots_addr, PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_set_type( - wots_pk_addr, PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_ADDR_TYPE_WOTSPK); - - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_set_keypair_addr( - wots_addr, addr_idx); - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_wots_gen_pk( - pk, sk_seed, pub_seed, wots_addr, hash_state_seeded); - - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_copy_keypair_addr( - wots_pk_addr, wots_addr); - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_thash_WOTS_LEN( - leaf, pk, pub_seed, wots_pk_addr, hash_state_seeded); -} - /* * Returns the length of a secret key, in bytes */ -size_t PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_crypto_sign_secretkeybytes(void) { - return PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_CRYPTO_SECRETKEYBYTES; +size_t crypto_sign_secretkeybytes(void) { + return CRYPTO_SECRETKEYBYTES; } /* * Returns the length of a public key, in bytes */ -size_t PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_crypto_sign_publickeybytes(void) { - return PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_CRYPTO_PUBLICKEYBYTES; +size_t crypto_sign_publickeybytes(void) { + return CRYPTO_PUBLICKEYBYTES; } /* * Returns the length of a signature, in bytes */ -size_t PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_crypto_sign_bytes(void) { - return PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_CRYPTO_BYTES; +size_t crypto_sign_bytes(void) { + return CRYPTO_BYTES; } /* * Returns the length of the seed required to generate a key pair, in bytes */ -size_t PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_crypto_sign_seedbytes(void) { - return PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_CRYPTO_SEEDBYTES; +size_t crypto_sign_seedbytes(void) { + return CRYPTO_SEEDBYTES; } /* @@ -78,35 +47,29 @@ size_t PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_crypto_sign_seedbytes(void) { * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] * Format pk: [PUB_SEED || root] */ -int PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed) { - /* We do not need the auth path in key generation, but it simplifies the - code to have just one treehash routine that computes both root and path - in one function. */ - unsigned char auth_path[PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_TREE_HEIGHT * PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N]; - uint32_t top_tree_addr[8] = {0}; - hash_state hash_state_seeded; - - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_set_layer_addr( - top_tree_addr, PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_D - 1); - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_set_type( - top_tree_addr, PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_ADDR_TYPE_HASHTREE); +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed) { + spx_ctx ctx; /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ - memcpy(sk, seed, PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_CRYPTO_SEEDBYTES); + memcpy(sk, seed, CRYPTO_SEEDBYTES); + + memcpy(pk, sk + 2 * SPX_N, SPX_N); - memcpy(pk, sk + 2 * PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N, PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N); + memcpy(ctx.pub_seed, pk, SPX_N); + memcpy(ctx.sk_seed, sk, SPX_N); /* This hook allows the hash function instantiation to do whatever preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_initialize_hash_function(&hash_state_seeded, pk, sk); + initialize_hash_function(&ctx); /* Compute root node of the top-most subtree. */ - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_treehash_TREE_HEIGHT( - sk + 3 * PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N, auth_path, sk, sk + 2 * PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N, 0, 0, - wots_gen_leaf, top_tree_addr, &hash_state_seeded); + merkle_gen_root(sk + 3 * SPX_N, &ctx); - memcpy(pk + PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N, sk + 3 * PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N, PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N); + // cleanup + free_hash_function(&ctx); + + memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); return 0; } @@ -116,31 +79,10 @@ int PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_crypto_sign_seed_keypair( * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] * Format pk: [PUB_SEED || root] */ -int PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk) { - - // guarantee alignment of pk - union { - __m128 _x[PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_CRYPTO_PUBLICKEYBYTES / 16]; - uint8_t pk[PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_CRYPTO_PUBLICKEYBYTES]; - } aligned_pk; - - // guarantee alignment of sk - union { - __m128 _x[PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_CRYPTO_SECRETKEYBYTES / 16]; - uint8_t sk[PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_CRYPTO_SECRETKEYBYTES]; - } aligned_sk; - - union { - __m128 _x[PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_CRYPTO_SEEDBYTES / 16]; - uint8_t seed[PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_CRYPTO_SEEDBYTES]; - } aligned_seed; - randombytes(aligned_seed.seed, PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_CRYPTO_SEEDBYTES); - - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_crypto_sign_seed_keypair( - aligned_pk.pk, aligned_sk.sk, aligned_seed.seed); - memcpy(pk, aligned_pk.pk, PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_CRYPTO_PUBLICKEYBYTES); - memcpy(sk, aligned_sk.sk, PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_CRYPTO_SECRETKEYBYTES); +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { + uint8_t seed[CRYPTO_SEEDBYTES]; + randombytes(seed, CRYPTO_SEEDBYTES); + crypto_sign_seed_keypair(pk, sk, seed); return 0; } @@ -148,101 +90,68 @@ int PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_crypto_sign_keypair( /** * Returns an array containing a detached signature. */ -int PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - // guarantee alignment of sk - union { - __m128 *_x; - uint8_t sk[PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_CRYPTO_SECRETKEYBYTES]; - } aligned_sk; - memcpy(aligned_sk.sk, sk, PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_CRYPTO_SECRETKEYBYTES); - sk = aligned_sk.sk; - - // guarantee alignment of sig - union { - __m128 *_x; - uint8_t sig[PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_BYTES]; - } aligned_sig; - uint8_t *orig_sig = sig; - sig = (uint8_t *)aligned_sig.sig; - - const unsigned char *sk_seed = sk; - const unsigned char *sk_prf = sk + PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N; - const unsigned char *pk = sk + 2 * PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N; - const unsigned char *pub_seed = pk; - - unsigned char optrand[PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N]; - unsigned char mhash[PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_FORS_MSG_BYTES]; - unsigned char root[PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N]; +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk) { + spx_ctx ctx; + + const uint8_t *sk_prf = sk + SPX_N; + const uint8_t *pk = sk + 2 * SPX_N; + + uint8_t optrand[SPX_N]; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t root[SPX_N]; uint32_t i; uint64_t tree; uint32_t idx_leaf; uint32_t wots_addr[8] = {0}; uint32_t tree_addr[8] = {0}; - hash_state hash_state_seeded; + memcpy(ctx.sk_seed, sk, SPX_N); + memcpy(ctx.pub_seed, pk, SPX_N); /* This hook allows the hash function instantiation to do whatever preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_initialize_hash_function( - &hash_state_seeded, - pub_seed, sk_seed); + initialize_hash_function(&ctx); - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_set_type( - wots_addr, PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_set_type( - tree_addr, PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_ADDR_TYPE_HASHTREE); + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); /* Optionally, signing can be made non-deterministic using optrand. This can help counter side-channel attacks that would benefit from getting a large number of traces when the signer uses the same nodes. */ - randombytes(optrand, PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N); + randombytes(optrand, SPX_N); /* Compute the digest randomization value. */ - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_gen_message_random( - sig, sk_prf, optrand, m, mlen, &hash_state_seeded); + gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); /* Derive the message digest and leaf index from R, PK and M. */ - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N; + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_set_keypair_addr( - wots_addr, idx_leaf); + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); /* Sign the message hash using FORS. */ - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_fors_sign( - sig, root, mhash, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_FORS_BYTES; - - for (i = 0; i < PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_D; i++) { - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_set_tree_addr(tree_addr, tree); - - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_set_keypair_addr( - wots_addr, idx_leaf); - - /* Compute a WOTS signature. */ - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_wots_sign( - sig, root, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_WOTS_BYTES; - - /* Compute the authentication path for the used WOTS leaf. */ - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_treehash_TREE_HEIGHT( - root, sig, sk_seed, pub_seed, idx_leaf, 0, - wots_gen_leaf, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_TREE_HEIGHT * PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N; + fors_sign(sig, root, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); + sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_TREE_HEIGHT; + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; } - memcpy(orig_sig, aligned_sig.sig, PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_BYTES); - *siglen = PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_BYTES; + free_hash_function(&ctx); + + *siglen = SPX_BYTES; return 0; } @@ -250,23 +159,14 @@ int PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_crypto_sign_signature( /** * Verifies a detached signature and message under a given public key. */ -int PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk) { - // guarantee alignment of pk - union { - __m128 *_x; - uint8_t pk[PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_CRYPTO_PUBLICKEYBYTES]; - } aligned_pk; - memcpy(aligned_pk.pk, pk, PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_CRYPTO_PUBLICKEYBYTES); - pk = aligned_pk.pk; - - const unsigned char *pub_seed = pk; - const unsigned char *pub_root = pk + PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N; - unsigned char mhash[PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_FORS_MSG_BYTES]; - unsigned char wots_pk[PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_WOTS_BYTES]; - unsigned char root[PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N]; - unsigned char leaf[PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N]; +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk) { + spx_ctx ctx; + const uint8_t *pub_root = pk + SPX_N; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t wots_pk[SPX_WOTS_BYTES]; + uint8_t root[SPX_N]; + uint8_t leaf[SPX_N]; unsigned int i; uint64_t tree; uint32_t idx_leaf; @@ -274,77 +174,66 @@ int PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_crypto_sign_verify( uint32_t tree_addr[8] = {0}; uint32_t wots_pk_addr[8] = {0}; - hash_state hash_state_seeded; - - if (siglen != PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_BYTES) { + if (siglen != SPX_BYTES) { return -1; } + memcpy(ctx.pub_seed, pk, SPX_N); + /* This hook allows the hash function instantiation to do whatever preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_initialize_hash_function( - &hash_state_seeded, - pub_seed, NULL); + initialize_hash_function(&ctx); - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_set_type( - wots_addr, PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_set_type( - tree_addr, PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_ADDR_TYPE_HASHTREE); - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_set_type( - wots_pk_addr, PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_ADDR_TYPE_WOTSPK); + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); /* Derive the message digest and leaf index from R || PK || M. */ - /* The additional PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N is a result of the hash domain separator. */ - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N; + /* The additional SPX_N is a result of the hash domain separator. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; /* Layer correctly defaults to 0, so no need to set_layer_addr */ - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_set_keypair_addr( - wots_addr, idx_leaf); + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_fors_pk_from_sig( - root, sig, mhash, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_FORS_BYTES; + fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; /* For each subtree.. */ - for (i = 0; i < PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_D; i++) { - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_set_tree_addr(tree_addr, tree); + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_set_keypair_addr( - wots_addr, idx_leaf); + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_copy_keypair_addr( - wots_pk_addr, wots_addr); + copy_keypair_addr(wots_pk_addr, wots_addr); /* The WOTS public key is only correct if the signature was correct. */ /* Initially, root is the FORS pk, but on subsequent iterations it is the root of the subtree below the currently processed subtree. */ - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_wots_pk_from_sig( - wots_pk, sig, root, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_WOTS_BYTES; + wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); + sig += SPX_WOTS_BYTES; /* Compute the leaf node using the WOTS public key. */ - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_thash_WOTS_LEN( - leaf, wots_pk, pub_seed, wots_pk_addr, &hash_state_seeded); + thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); /* Compute the root node of this subtree. */ - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_compute_root( - root, leaf, idx_leaf, 0, sig, PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_TREE_HEIGHT, - pub_seed, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_TREE_HEIGHT * PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N; + compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, + &ctx, tree_addr); + sig += SPX_TREE_HEIGHT * SPX_N; /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_TREE_HEIGHT; + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; } + // cleanup + free_hash_function(&ctx); + /* Check if the root node equals the root node in the public key. */ - if (memcmp(root, pub_root, PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N) != 0) { + if (memcmp(root, pub_root, SPX_N) != 0) { return -1; } @@ -355,15 +244,14 @@ int PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_crypto_sign_verify( /** * Returns an array containing the signature followed by the message. */ -int PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk) { size_t siglen; - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_crypto_sign_signature( - sm, &siglen, m, mlen, sk); + crypto_sign_signature(sm, &siglen, m, mlen, sk); - memmove(sm + PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_BYTES, m, mlen); + memmove(sm + SPX_BYTES, m, mlen); *smlen = siglen + mlen; return 0; @@ -372,38 +260,27 @@ int PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_crypto_sign( /** * Verifies a given signature-message pair under a given public key. */ -int PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk) { - - // guarantee alignment of pk - union { - __m128 *_x; - uint8_t pk[PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_CRYPTO_PUBLICKEYBYTES]; - } aligned_pk; - memcpy(aligned_pk.pk, pk, PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_CRYPTO_PUBLICKEYBYTES); - pk = aligned_pk.pk; - - +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk) { /* The API caller does not necessarily know what size a signature should be - but SPHINCS+ signatures are always exactly PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_BYTES. */ - if (smlen < PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_BYTES) { + but SPHINCS+ signatures are always exactly SPX_BYTES. */ + if (smlen < SPX_BYTES) { memset(m, 0, smlen); *mlen = 0; return -1; } - *mlen = smlen - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_BYTES; + *mlen = smlen - SPX_BYTES; - if (PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_crypto_sign_verify( - sm, PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_BYTES, sm + PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_BYTES, *mlen, pk)) { + if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { memset(m, 0, smlen); *mlen = 0; return -1; } /* If verification was successful, move the message to the right place. */ - memmove(m, sm + PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_BYTES, *mlen); + memmove(m, sm + SPX_BYTES, *mlen); return 0; } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/thash.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/thash.h index 018da6fccc..8687ccfb4d 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/thash.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/thash.h @@ -1,28 +1,13 @@ -#ifndef PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_THASH_H -#define PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_THASH_H +#ifndef SPX_THASH_H +#define SPX_THASH_H -#include "hash_state.h" +#include "context.h" +#include "params.h" #include -void PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); +#define thash SPX_NAMESPACE(thash) +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/thash_haraka_robust.c b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/thash_haraka_robust.c index ea24bc37d9..109502cbc2 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/thash_haraka_robust.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/thash_haraka_robust.c @@ -2,93 +2,44 @@ #include #include "address.h" -#include "hash_state.h" #include "params.h" #include "thash.h" +#include "utils.h" #include "haraka.h" /** - * Takes an array of inblocks concatenated arrays of PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N bytes. + * Takes an array of inblocks concatenated arrays of SPX_N bytes. */ -static void PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_thash( - unsigned char *out, unsigned char *buf, - const unsigned char *in, unsigned int inblocks, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char *bitmask = buf + PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_ADDR_BYTES; +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]) { + PQCLEAN_VLA(uint8_t, buf, SPX_ADDR_BYTES + inblocks * SPX_N); + PQCLEAN_VLA(uint8_t, bitmask, inblocks * SPX_N); unsigned char outbuf[32]; unsigned char buf_tmp[64]; unsigned int i; - (void)pub_seed; /* Suppress an 'unused parameter' warning. */ - if (inblocks == 1) { /* F function */ - /* Since PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N may be smaller than 32, we need a temporary buffer. */ + /* Since SPX_N may be smaller than 32, we need a temporary buffer. */ memset(buf_tmp, 0, 64); - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_addr_to_bytes(buf_tmp, addr); + memcpy(buf_tmp, addr, 32); - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_haraka256(outbuf, buf_tmp, hash_state_seeded); - for (i = 0; i < inblocks * PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N; i++) { - buf_tmp[PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_ADDR_BYTES + i] = in[i] ^ outbuf[i]; + haraka256(outbuf, buf_tmp, ctx); + for (i = 0; i < inblocks * SPX_N; i++) { + buf_tmp[SPX_ADDR_BYTES + i] = in[i] ^ outbuf[i]; } - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_haraka512(outbuf, buf_tmp, hash_state_seeded); - memcpy(out, outbuf, PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N); + haraka512(outbuf, buf_tmp, ctx); + memcpy(out, outbuf, SPX_N); } else { /* All other tweakable hashes*/ - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_addr_to_bytes(buf, addr); - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_haraka_S( - bitmask, inblocks * PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N, buf, PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_ADDR_BYTES, hash_state_seeded); + memcpy(buf, addr, 32); + haraka_S(bitmask, inblocks * SPX_N, buf, SPX_ADDR_BYTES, ctx); - for (i = 0; i < inblocks * PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N; i++) { - buf[PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_ADDR_BYTES + i] = in[i] ^ bitmask[i]; + for (i = 0; i < inblocks * SPX_N; i++) { + buf[SPX_ADDR_BYTES + i] = in[i] ^ bitmask[i]; } - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_haraka_S( - out, PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N, buf, PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N, hash_state_seeded); + haraka_S(out, SPX_N, buf, SPX_ADDR_BYTES + inblocks * SPX_N, ctx); } } - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_ADDR_BYTES + 1 * PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N]; - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_thash( - out, buf, in, 1, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_ADDR_BYTES + 2 * PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N]; - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_thash( - out, buf, in, 2, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_ADDR_BYTES + PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_WOTS_LEN * PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N]; - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_thash( - out, buf, in, PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_WOTS_LEN, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_ADDR_BYTES + PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_FORS_TREES * PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N]; - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_thash( - out, buf, in, PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_FORS_TREES, pub_seed, addr, hash_state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/thash_haraka_robustx4.c b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/thash_haraka_robustx4.c index df971993a7..100808a3a5 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/thash_haraka_robustx4.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/thash_haraka_robustx4.c @@ -2,91 +2,92 @@ #include #include "address.h" -#include "haraka.h" #include "params.h" #include "thashx4.h" +#include "harakax4.h" + +#include "utils.h" + /** * 4-way parallel version of thash; takes 4x as much input and output */ -#define thashx4_variant(name, inblocks) \ - void PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_thashx4_##name(unsigned char *out0, unsigned char *out1, unsigned char *out2, \ - unsigned char *out3, const unsigned char *in0, \ - const unsigned char *in1, const unsigned char *in2, \ - const unsigned char *in3, const unsigned char *pub_seed, \ - uint32_t addrx4[4 * 8], const harakactx *state) { \ - unsigned char buf0[PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_ADDR_BYTES + (inblocks)*PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N]; \ - unsigned char buf1[PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_ADDR_BYTES + (inblocks)*PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N]; \ - unsigned char buf2[PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_ADDR_BYTES + (inblocks)*PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N]; \ - unsigned char buf3[PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_ADDR_BYTES + (inblocks)*PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N]; \ - unsigned char bitmask0[(inblocks)*PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N]; \ - unsigned char bitmask1[(inblocks)*PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N]; \ - unsigned char bitmask2[(inblocks)*PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N]; \ - unsigned char bitmask3[(inblocks)*PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N]; \ - unsigned char outbuf[32 * 4]; \ - unsigned char buf_tmp[64 * 4]; \ - unsigned int i; \ - \ - (void)pub_seed; /* Suppress an 'unused parameter' warning. */ \ - \ - if ((inblocks) == 1) { \ - memset(buf_tmp, 0, 64 * 4); \ - \ - /* Generate masks first in buffer */ \ - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_addr_to_bytes(buf_tmp, addrx4 + 0 * 8); \ - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_addr_to_bytes(buf_tmp + 32, addrx4 + 1 * 8); \ - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_addr_to_bytes(buf_tmp + 64, addrx4 + 2 * 8); \ - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_addr_to_bytes(buf_tmp + 96, addrx4 + 3 * 8); \ - \ - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_haraka256x4(outbuf, buf_tmp, state); \ - \ - /* move addresses to make room for inputs; zero old values */ \ - memcpy(buf_tmp + 192, buf_tmp + 96, PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_ADDR_BYTES); \ - memcpy(buf_tmp + 128, buf_tmp + 64, PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_ADDR_BYTES); \ - memcpy(buf_tmp + 64, buf_tmp + 32, PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_ADDR_BYTES); \ - /* skip memcpy(buf_tmp, buf_tmp, PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_ADDR_BYTES); already in place */ \ - \ - /* skip memset(buf_tmp, 0, PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_ADDR_BYTES); remained untouched */ \ - memset(buf_tmp + 32, 0, PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_ADDR_BYTES); \ - /* skip memset(buf_tmp + 64, 0, PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_ADDR_BYTES); contains addr1 */ \ - memset(buf_tmp + 96, 0, PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_ADDR_BYTES); \ - \ - for (i = 0; i < PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N; i++) { \ - buf_tmp[PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_ADDR_BYTES + i] = in0[i] ^ outbuf[i]; \ - buf_tmp[PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_ADDR_BYTES + i + 64] = in1[i] ^ outbuf[i + 32]; \ - buf_tmp[PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_ADDR_BYTES + i + 128] = in2[i] ^ outbuf[i + 64]; \ - buf_tmp[PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_ADDR_BYTES + i + 192] = in3[i] ^ outbuf[i + 96]; \ - } \ - \ - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_haraka512x4(outbuf, buf_tmp, state); \ - \ - memcpy(out0, outbuf, PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N); \ - memcpy(out1, outbuf + 32, PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N); \ - memcpy(out2, outbuf + 64, PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N); \ - memcpy(out3, outbuf + 96, PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N); \ - } else { \ - /* All other tweakable hashes*/ \ - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_addr_to_bytes(buf0, addrx4 + 0 * 8); \ - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_addr_to_bytes(buf1, addrx4 + 1 * 8); \ - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_addr_to_bytes(buf2, addrx4 + 2 * 8); \ - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_addr_to_bytes(buf3, addrx4 + 3 * 8); \ - \ - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_haraka_Sx4(bitmask0, bitmask1, bitmask2, bitmask3, (inblocks)*PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N, buf0, buf1, \ - buf2, buf3, PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_ADDR_BYTES, state); \ - \ - for (i = 0; i < (inblocks)*PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N; i++) { \ - buf0[PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_ADDR_BYTES + i] = in0[i] ^ bitmask0[i]; \ - buf1[PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_ADDR_BYTES + i] = in1[i] ^ bitmask1[i]; \ - buf2[PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_ADDR_BYTES + i] = in2[i] ^ bitmask2[i]; \ - buf3[PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_ADDR_BYTES + i] = in3[i] ^ bitmask3[i]; \ - } \ - \ - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_haraka_Sx4(out0, out1, out2, out3, PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N, buf0, buf1, buf2, buf3, \ - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_ADDR_BYTES + (inblocks)*PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N, state); \ - } \ - } +#define thashx4 SPX_NAMESPACE(thashx4) +void thashx4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addrx4[4 * 8]) { + PQCLEAN_VLA(unsigned char, buf0, SPX_ADDR_BYTES + inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, buf1, SPX_ADDR_BYTES + inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, buf2, SPX_ADDR_BYTES + inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, buf3, SPX_ADDR_BYTES + inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, bitmask0, inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, bitmask1, inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, bitmask2, inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, bitmask3, inblocks * SPX_N); + unsigned char outbuf[32 * 4]; + unsigned char buf_tmp[64 * 4]; + unsigned int i; + + if (inblocks == 1) { + memset(buf_tmp, 0, 64 * 4); + + // Generate masks first in buffer + memcpy(buf_tmp, addrx4 + 0 * 8, 32); + memcpy(buf_tmp + 32, addrx4 + 1 * 8, 32); + memcpy(buf_tmp + 64, addrx4 + 2 * 8, 32); + memcpy(buf_tmp + 96, addrx4 + 3 * 8, 32); + + haraka256x4(outbuf, buf_tmp, ctx); + + /* move addresses to make room for inputs; zero old values */ + memcpy(buf_tmp + 192, buf_tmp + 96, SPX_ADDR_BYTES); + memcpy(buf_tmp + 128, buf_tmp + 64, SPX_ADDR_BYTES); + memcpy(buf_tmp + 64, buf_tmp + 32, SPX_ADDR_BYTES); + /* skip memcpy(buf_tmp, buf_tmp, SPX_ADDR_BYTES); already in place */ -thashx4_variant(1, 1) -thashx4_variant(2, 2) -thashx4_variant(WOTS_LEN, PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_WOTS_LEN) -thashx4_variant(FORS_TREES, PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_FORS_TREES) + /* skip memset(buf_tmp, 0, SPX_ADDR_BYTES); remained untouched */ + memset(buf_tmp + 32, 0, SPX_ADDR_BYTES); + /* skip memset(buf_tmp + 64, 0, SPX_ADDR_BYTES); contains addr1 */ + memset(buf_tmp + 96, 0, SPX_ADDR_BYTES); + + for (i = 0; i < SPX_N; i++) { + buf_tmp[SPX_ADDR_BYTES + i] = in0[i] ^ outbuf[i]; + buf_tmp[SPX_ADDR_BYTES + i + 64] = in1[i] ^ outbuf[i + 32]; + buf_tmp[SPX_ADDR_BYTES + i + 128] = in2[i] ^ outbuf[i + 64]; + buf_tmp[SPX_ADDR_BYTES + i + 192] = in3[i] ^ outbuf[i + 96]; + } + + haraka512x4(outbuf, buf_tmp, ctx); + + memcpy(out0, outbuf, SPX_N); + memcpy(out1, outbuf + 32, SPX_N); + memcpy(out2, outbuf + 64, SPX_N); + memcpy(out3, outbuf + 96, SPX_N); + } else { + /* All other tweakable hashes*/ + memcpy(buf0, addrx4 + 0 * 8, 32); + memcpy(buf1, addrx4 + 1 * 8, 32); + memcpy(buf2, addrx4 + 2 * 8, 32); + memcpy(buf3, addrx4 + 3 * 8, 32); + + haraka_Sx4(bitmask0, bitmask1, bitmask2, bitmask3, inblocks * SPX_N, + buf0, buf1, buf2, buf3, SPX_ADDR_BYTES, ctx); + + for (i = 0; i < inblocks * SPX_N; i++) { + buf0[SPX_ADDR_BYTES + i] = in0[i] ^ bitmask0[i]; + buf1[SPX_ADDR_BYTES + i] = in1[i] ^ bitmask1[i]; + buf2[SPX_ADDR_BYTES + i] = in2[i] ^ bitmask2[i]; + buf3[SPX_ADDR_BYTES + i] = in3[i] ^ bitmask3[i]; + } + + haraka_Sx4(out0, out1, out2, out3, SPX_N, + buf0, buf1, buf2, buf3, SPX_ADDR_BYTES + inblocks * SPX_N, + ctx); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/thashx4.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/thashx4.h index bb29a996f1..64798a3727 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/thashx4.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/thashx4.h @@ -1,25 +1,20 @@ -#ifndef PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_THASHX4_H -#define PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_THASHX4_H +#ifndef SPX_THASHX4_H +#define SPX_THASHX4_H #include -#include "hash_state.h" +#include "context.h" +#include "params.h" -#define thashx4_header(inblocks) \ - void PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_thashx4_##inblocks(unsigned char *out0, \ - unsigned char *out1, \ - unsigned char *out2, \ - unsigned char *out3, \ - const unsigned char *in0, \ - const unsigned char *in1, \ - const unsigned char *in2, \ - const unsigned char *in3, \ - const unsigned char *pub_seed, uint32_t addrx4[4*8], \ - const hash_state *state_seeded) - -thashx4_header(1); -thashx4_header(2); -thashx4_header(WOTS_LEN); -thashx4_header(FORS_TREES); +#define thashx4 SPX_NAMESPACE(thashx4) +void thashx4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addrx4[4 * 8]); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/utils.c b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/utils.c index 214f1c9515..177b541fb9 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/utils.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/utils.c @@ -1,34 +1,41 @@ -#include #include +#include "utils.h" + #include "address.h" #include "hash.h" -#include "hash_state.h" #include "params.h" #include "thash.h" -#include "utils.h" /** * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. */ -void PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in) { +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in) { + int i; /* Iterate over out in decreasing order, for big-endianness. */ - for (size_t i = outlen; i > 0; i--) { - out[i - 1] = in & 0xff; + for (i = (signed int)outlen - 1; i >= 0; i--) { + out[i] = in & 0xff; in = in >> 8; } } +void u32_to_bytes(unsigned char *out, uint32_t in) { + out[0] = (unsigned char)(in >> 24); + out[1] = (unsigned char)(in >> 16); + out[2] = (unsigned char)(in >> 8); + out[3] = (unsigned char)in; +} + /** * Converts the inlen bytes in 'in' from big-endian byte order to an integer. */ -unsigned long long PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_bytes_to_ull( - const unsigned char *in, size_t inlen) { +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { unsigned long long retval = 0; + unsigned int i; - for (size_t i = 0; i < inlen; i++) { + for (i = 0; i < inlen; i++) { retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); } return retval; @@ -38,94 +45,80 @@ unsigned long long PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_bytes_to_ull( * Computes a root node given a leaf and an auth path. * Expects address to be complete other than the tree_height and tree_index. */ -void PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]) { uint32_t i; - unsigned char buffer[2 * PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N]; + unsigned char buffer[2 * SPX_N]; /* If leaf_idx is odd (last bit = 1), current path element is a right child and auth_path has to go left. Otherwise it is the other way around. */ if (leaf_idx & 1) { - memcpy(buffer + PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N, leaf, PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N); + memcpy(buffer + SPX_N, leaf, SPX_N); + memcpy(buffer, auth_path, SPX_N); } else { - memcpy(buffer, leaf, PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N); - memcpy(buffer + PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N, auth_path, PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N); + memcpy(buffer, leaf, SPX_N); + memcpy(buffer + SPX_N, auth_path, SPX_N); } - auth_path += PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N; + auth_path += SPX_N; for (i = 0; i < tree_height - 1; i++) { leaf_idx >>= 1; idx_offset >>= 1; /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_set_tree_height(addr, i + 1); - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_set_tree_index( - addr, leaf_idx + idx_offset); + set_tree_height(addr, i + 1); + set_tree_index(addr, leaf_idx + idx_offset); /* Pick the right or left neighbor, depending on parity of the node. */ if (leaf_idx & 1) { - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_thash_2( - buffer + PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N); + thash(buffer + SPX_N, buffer, 2, ctx, addr); + memcpy(buffer, auth_path, SPX_N); } else { - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_thash_2( - buffer, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer + PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N, auth_path, PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N); + thash(buffer, buffer, 2, ctx, addr); + memcpy(buffer + SPX_N, auth_path, SPX_N); } - auth_path += PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N; + auth_path += SPX_N; } /* The last iteration is exceptional; we do not copy an auth_path node. */ leaf_idx >>= 1; idx_offset >>= 1; - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_set_tree_height(addr, tree_height); - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_set_tree_index( - addr, leaf_idx + idx_offset); - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_thash_2( - root, buffer, pub_seed, addr, hash_state_seeded); + set_tree_height(addr, tree_height); + set_tree_index(addr, leaf_idx + idx_offset); + thash(root, buffer, 2, ctx, addr); } /** * For a given leaf index, computes the authentication path and the resulting * root node using Merkle's TreeHash algorithm. * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_ADDR_TYPE_FORSTREE). + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). * Applies the offset idx_offset to indices before building addresses, so that * it is possible to continue counting indices across trees. */ -static void PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_treehash( - unsigned char *root, unsigned char *auth_path, - unsigned char *stack, unsigned int *heights, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - +void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx * /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]) { + PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); + PQCLEAN_VLA(unsigned int, heights, tree_height + 1); unsigned int offset = 0; uint32_t idx; uint32_t tree_idx; for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { /* Add the next leaf node to the stack. */ - gen_leaf(stack + offset * PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N, - sk_seed, pub_seed, idx + idx_offset, tree_addr, - hash_state_seeded); + gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); offset++; heights[offset - 1] = 0; /* If this is a node we need for the auth path.. */ if ((leaf_idx ^ 0x1) == idx) { - memcpy(auth_path, stack + (offset - 1)*PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N, PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N); + memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); } /* While the top-most nodes are of equal height.. */ @@ -134,66 +127,22 @@ static void PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_treehash( tree_idx = (idx >> (heights[offset - 1] + 1)); /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_set_tree_height( - tree_addr, heights[offset - 1] + 1); - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_set_tree_index( - tree_addr, tree_idx + (idx_offset >> (heights[offset - 1] + 1))); + set_tree_height(tree_addr, heights[offset - 1] + 1); + set_tree_index(tree_addr, + tree_idx + (idx_offset >> (heights[offset - 1] + 1))); /* Hash the top-most nodes from the stack together. */ - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_thash_2( - stack + (offset - 2)*PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N, stack + (offset - 2)*PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N, - pub_seed, tree_addr, hash_state_seeded); + thash(stack + (offset - 2)*SPX_N, + stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); offset--; /* Note that the top-most node is now one layer higher. */ heights[offset - 1]++; /* If this is a node we need for the auth path.. */ if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_path + heights[offset - 1]*PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N, - stack + (offset - 1)*PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N, PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N); + memcpy(auth_path + heights[offset - 1]*SPX_N, + stack + (offset - 1)*SPX_N, SPX_N); } } } - memcpy(root, stack, PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N); -} - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_FORS_HEIGHT + 1)*PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N]; - unsigned int heights[PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_FORS_HEIGHT + 1]; - - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_FORS_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_TREE_HEIGHT + 1)*PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N]; - unsigned int heights[PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_TREE_HEIGHT + 1]; - - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_TREE_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); + memcpy(root, stack, SPX_N); } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/utils.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/utils.h index 24d3ee4f51..64f5d5a53a 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/utils.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/utils.h @@ -1,64 +1,58 @@ -#ifndef PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_UTILS_H -#define PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_UTILS_H +#ifndef SPX_UTILS_H +#define SPX_UTILS_H -#include "hash_state.h" -#include "params.h" -#include #include +#include "compat.h" +#include "context.h" +#include "params.h" + + +/* To support MSVC use alloca() instead of VLAs. See #20. */ + + /** * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. */ -void PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in); +#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in); +#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) +void u32_to_bytes(unsigned char *out, uint32_t in); /** * Converts the inlen bytes in 'in' from big-endian byte order to an integer. */ -unsigned long long PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_bytes_to_ull( - const unsigned char *in, size_t inlen); +#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); /** * Computes a root node given a leaf and an auth path. * Expects address to be complete other than the tree_height and tree_index. */ -void PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); +#define compute_root SPX_NAMESPACE(compute_root) +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]); /** * For a given leaf index, computes the authentication path and the resulting * root node using Merkle's TreeHash algorithm. * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_ADDR_TYPE_FORSTREE). + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). * Applies the offset idx_offset to indices before building addresses, so that * it is possible to continue counting indices across trees. */ -void PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); +#define treehash SPX_NAMESPACE(treehash) +void treehash(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx *ctx /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]); -void PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/utilsx4.c b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/utilsx4.c index b7401addd6..1638677194 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/utilsx4.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/utilsx4.c @@ -1,98 +1,138 @@ +#include + +#include "utilsx4.h" + #include "address.h" #include "params.h" #include "thashx4.h" #include "utils.h" -#include "utilsx4.h" -#include - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. +/* + * Generate the entire Merkle tree, computing the authentication path for leaf_idx, + * and the resulting root node using Merkle's TreeHash algorithm. * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_ADDR_TYPE_FORSTREE). + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) + * + * This expects tree_addrx4 to be initialized to 4 parallel addr structures for + * the Merkle tree nodes + * * Applies the offset idx_offset to indices before building addresses, so that * it is possible to continue counting indices across trees. + * + * This works by using the standard Merkle tree building algorithm, except + * that each 'node' tracked is actually 4 consecutive nodes in the real tree. + * When we combine two logical nodes ABCD and WXYZ, we perform the H + * operation on adjacent real nodes, forming the parent logical node + * (AB)(CD)(WX)(YZ) + * + * When we get to the top two levels of the real tree (where there is only + * one logical node), we continue this operation two more times; the right + * most real node will by the actual root (and the other 3 nodes will be + * garbage). We follow the same thashx4 logic so that the 'extract + * authentication path components' part of the loop is still executed (and + * to simplify the code somewhat) + * + * This currently assumes tree_height >= 2; I suspect that doing an adjusting + * idx, addr_idx on the gen_leafx4 call if tree_height < 2 would fix it; since + * we don't actually use such short trees, I haven't bothered */ -#define treehashx4_variant(name, tree_height) \ - void PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_treehashx4_##name( \ - unsigned char *rootx4, unsigned char *auth_pathx4, const unsigned char *sk_seed, \ - const unsigned char *pub_seed, const uint32_t leaf_idx[4], uint32_t idx_offset[4], \ - void (*gen_leafx4)(unsigned char * /* leaf0 */, unsigned char * /* leaf1 */, \ - unsigned char * /* leaf2 */, unsigned char * /* leaf3 */, \ - const unsigned char * /* sk_seed */, \ - const unsigned char * /* pub_seed */, uint32_t /* addr_idx0 */, \ - uint32_t /* addr_idx1 */, uint32_t /* addr_idx2 */, \ - uint32_t /* addr_idx3 */, const uint32_t[8] /* tree_addr */, \ - const hash_state * /* state_seeded */), \ - uint32_t tree_addrx4[4 * 8], const hash_state *state_seeded) { \ - unsigned char stackx4[4 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N]; \ - unsigned int heights[(tree_height) + 1]; \ - unsigned int offset = 0; \ - uint32_t idx; \ - uint32_t tree_idx; \ - unsigned int j; \ - \ - for (idx = 0; idx < (uint32_t)(1 << (tree_height)); idx++) { \ - /* Add the next leaf node to the stack. */ \ - gen_leafx4(stackx4 + 0 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N + offset * PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N, \ - stackx4 + 1 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N + offset * PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N, \ - stackx4 + 2 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N + offset * PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N, \ - stackx4 + 3 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N + offset * PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N, sk_seed, \ - pub_seed, idx + idx_offset[0], idx + idx_offset[1], idx + idx_offset[2], \ - idx + idx_offset[3], tree_addrx4, state_seeded); \ - offset++; \ - heights[offset - 1] = 0; \ - \ - /* If this is a node we need for the auth path.. */ \ - for (j = 0; j < 4; j++) { \ - if ((leaf_idx[j] ^ 0x1) == idx) { \ - memcpy(auth_pathx4 + j * (tree_height)*PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N, \ - stackx4 + j * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N + (offset - 1) * PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N, \ - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N); \ - } \ - } \ - \ - /* While the top-most nodes are of equal height.. */ \ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { \ - /* Compute index of the new node, in the next layer. */ \ - tree_idx = (idx >> (heights[offset - 1] + 1)); \ - \ - /* Set the address of the node we're creating. */ \ - for (j = 0; j < 4; j++) { \ - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_set_tree_height(tree_addrx4 + j * 8, heights[offset - 1] + 1); \ - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_set_tree_index(tree_addrx4 + j * 8, \ - tree_idx + (idx_offset[j] >> (heights[offset - 1] + 1))); \ - } \ - /* Hash the top-most nodes from the stack together. */ \ - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_thashx4_2(stackx4 + 0 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N + (offset - 2) * PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N, \ - stackx4 + 1 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N + (offset - 2) * PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N, \ - stackx4 + 2 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N + (offset - 2) * PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N, \ - stackx4 + 3 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N + (offset - 2) * PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N, \ - stackx4 + 0 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N + (offset - 2) * PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N, \ - stackx4 + 1 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N + (offset - 2) * PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N, \ - stackx4 + 2 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N + (offset - 2) * PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N, \ - stackx4 + 3 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N + (offset - 2) * PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N, \ - pub_seed, tree_addrx4, state_seeded); \ - offset--; \ - /* Note that the top-most node is now one layer higher. */ \ - heights[offset - 1]++; \ - \ - /* If this is a node we need for the auth path.. */ \ - for (j = 0; j < 4; j++) { \ - if (((leaf_idx[j] >> heights[offset - 1]) ^ 0x1) == tree_idx) { \ - memcpy(auth_pathx4 + j * (tree_height)*PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N + \ - heights[offset - 1] * PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N, \ - stackx4 + j * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N + (offset - 1) * PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N, \ - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N); \ - } \ - } \ - } \ - } \ - \ - for (j = 0; j < 4; j++) { \ - memcpy(rootx4 + j * PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N, stackx4 + j * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N, PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N); \ - } \ - } +void treehashx4(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, + uint32_t tree_height, + void (*gen_leafx4)( + unsigned char * /* Where to write the leaves */, + const spx_ctx *, + uint32_t idx, void *info), + uint32_t tree_addrx4[4 * 8], + void *info) { + /* This is where we keep the intermediate nodes */ + PQCLEAN_VLA(unsigned char, stackx4, tree_height * 4 * SPX_N); + uint32_t left_adj = 0, prev_left_adj = 0; /* When we're doing the top 3 */ + /* levels, the left-most part of the tree isn't at the beginning */ + /* of current[]. These give the offset of the actual start */ + + uint32_t idx; + uint32_t max_idx = (1U << (tree_height - 2)) - 1; + for (idx = 0;; idx++) { + unsigned char current[4 * SPX_N]; /* Current logical node */ + gen_leafx4( current, ctx, 4 * idx + idx_offset, + info ); -treehashx4_variant(FORS_HEIGHT, PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_FORS_HEIGHT) + /* Now combine the freshly generated right node with previously */ + /* generated left ones */ + uint32_t internal_idx_offset = idx_offset; + uint32_t internal_idx = idx; + uint32_t internal_leaf = leaf_idx; + uint32_t h; /* The height we are in the Merkle tree */ + for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { + + /* Special processing if we're at the top of the tree */ + if (h >= tree_height - 2) { + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[3 * SPX_N], SPX_N ); + return; + } + /* The tree indexing logic is a bit off in this case */ + /* Adjust it so that the left-most node of the part of */ + /* the tree that we're processing has index 0 */ + prev_left_adj = left_adj; + left_adj = 4U - (1 << (tree_height - h - 1)); + } + + /* Check if we hit the top of the tree */ + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[3 * SPX_N], SPX_N ); + return; + } + + /* + * Check if one of the nodes we have is a part of the + * authentication path; if it is, write it out + */ + if ((((internal_idx << 2) ^ internal_leaf) & ~0x3U) == 0) { + memcpy( &auth_path[ h * SPX_N ], + ¤t[(((internal_leaf & 3) ^ 1) + prev_left_adj) * SPX_N], + SPX_N ); + } + + /* + * Check if we're at a left child; if so, stop going up the stack + * Exception: if we've reached the end of the tree, keep on going + * (so we combine the last 4 nodes into the one root node in two + * more iterations) + */ + if ((internal_idx & 1) == 0 && idx < max_idx) { + break; + } + + /* Ok, we're at a right node (or doing the top 3 levels) */ + /* Now combine the left and right logical nodes together */ + + /* Set the address of the node we're creating. */ + unsigned int j; + internal_idx_offset >>= 1; + for (j = 0; j < 4; j++) { + set_tree_height(tree_addrx4 + j * 8, h + 1); + set_tree_index(tree_addrx4 + j * 8, + (4 / 2) * (internal_idx & ~1U) + j - left_adj + internal_idx_offset ); + } + unsigned char *left = &stackx4[h * 4 * SPX_N]; + thashx4( ¤t[0 * SPX_N], + ¤t[1 * SPX_N], + ¤t[2 * SPX_N], + ¤t[3 * SPX_N], + &left [0 * SPX_N], + &left [2 * SPX_N], + ¤t[0 * SPX_N], + ¤t[2 * SPX_N], + 2, ctx, tree_addrx4); + } + + /* We've hit a left child; save the current for when we get the */ + /* corresponding right right */ + memcpy( &stackx4[h * 4 * SPX_N], current, 4 * SPX_N); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/utilsx4.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/utilsx4.h index 6d583840c9..facb874b18 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/utilsx4.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/utilsx4.h @@ -1,38 +1,30 @@ -#ifndef PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_UTILSX4_H -#define PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_UTILSX4_H - -#include "hash_state.h" -#include "params.h" +#ifndef SPX_UTILSX4_H +#define SPX_UTILSX4_H #include +#include "context.h" +#include "params.h" + /** * For a given leaf index, computes the authentication path and the resulting * root node using Merkle's TreeHash algorithm. * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_ADDR_TYPE_FORSTREE). + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). * Applies the offset idx_offset to indices before building addresses, so that * it is possible to continue counting indices across trees. + * + * This implementation uses AVX to compute internal nodes 4 at a time (in + * parallel) */ -void PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_treehashx4_FORS_HEIGHT(unsigned char *rootx4, - unsigned char *auth_pathx4, - const unsigned char *sk_seed, - const unsigned char *pub_seed, - const uint32_t leaf_idx[4], - uint32_t idx_offset[4], - void (*gen_leafx4)(unsigned char * /* leaf0 */, - unsigned char * /* leaf1 */, - unsigned char * /* leaf2 */, - unsigned char * /* leaf3 */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx0 */, - uint32_t /* addr_idx1 */, - uint32_t /* addr_idx2 */, - uint32_t /* addr_idx3 */, - const uint32_t[8] /* tree_addr */, - const hash_state * /* state_seeded */), - uint32_t tree_addrx4[4 * 8], - const hash_state *state_seeded); +#define treehashx4 SPX_NAMESPACE(treehashx4) +void treehashx4(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leafx4)( + unsigned char * /* Where to write the leaves */, + const spx_ctx * /* ctx */, + uint32_t addr_idx, void *info), + uint32_t tree_addrx4[4 * 8], void *info); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/wots.c b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/wots.c index be0b623386..4d5041ce05 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/wots.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/wots.c @@ -1,106 +1,104 @@ #include #include +#include "wots.h" + #include "address.h" #include "hash.h" -#include "hash_state.h" #include "hashx4.h" #include "params.h" #include "thash.h" #include "thashx4.h" #include "utils.h" -#include "wots.h" +#include "utilsx4.h" +#include "wotsx4.h" // TODO clarify address expectations, and make them more uniform. // TODO i.e. do we expect types to be set already? // TODO and do we expect modifications or copies? /** - * Computes the starting value for a chain, i.e. the secret key. - * Expects the address to be complete up to the chain address. - */ -static void wots_gen_sk(unsigned char *sk, const unsigned char *sk_seed, - uint32_t wots_addr[8], const hash_state *state_seeded) { - /* Make sure that the hash address is actually zeroed. */ - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_set_hash_addr(wots_addr, 0); - - /* Generate sk element. */ - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_prf_addr(sk, sk_seed, wots_addr, state_seeded); -} - -/** - * 4-way parallel version of wots_gen_sk; expects 4x as much space in sk + * Computes up the chains */ -static void wots_gen_skx4(unsigned char *skx4, const unsigned char *sk_seed, - uint32_t wots_addrx4[4 * 8], const hash_state *state_seeded) { - unsigned int j; - - /* Make sure that the hash address is actually zeroed. */ +static void gen_chains( + unsigned char *out, + const unsigned char *in, + unsigned int start[SPX_WOTS_LEN], + const unsigned int steps[SPX_WOTS_LEN], + const spx_ctx *ctx, + uint32_t addr[8]) { + uint32_t i, j, k, idx, watching; + int done; + unsigned char empty[SPX_N]; + unsigned char *bufs[4]; + uint32_t addrs[8 * 4]; + + int l; + uint16_t counts[SPX_WOTS_W] = { 0 }; + uint16_t idxs[SPX_WOTS_LEN]; + uint16_t total, newTotal; + + /* set addrs = {addr, addr, addr, addr} */ for (j = 0; j < 4; j++) { - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_set_hash_addr(wots_addrx4 + j * 8, 0); + memcpy(addrs + j * 8, addr, sizeof(uint32_t) * 8); } - /* Generate sk element. */ - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_prf_addrx4(skx4 + 0 * PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N, - skx4 + 1 * PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N, - skx4 + 2 * PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N, - skx4 + 3 * PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N, - sk_seed, wots_addrx4, - state_seeded); -} - -/** - * Computes the chaining function. - * out and in have to be n-byte arrays. - * - * Interprets in as start-th value of the chain. - * addr has to contain the address of the chain. - */ -static void gen_chain(unsigned char *out, const unsigned char *in, - unsigned int start, unsigned int steps, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *state_seeded) { - uint32_t i; - /* Initialize out with the value at position 'start'. */ - memcpy(out, in, PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N); + memcpy(out, in, SPX_WOTS_LEN * SPX_N); - /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_WOTS_W; i++) { - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_set_hash_addr(addr, i); - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_thash_1(out, out, pub_seed, addr, state_seeded); + /* Sort the chains in reverse order by steps using counting sort. */ + for (i = 0; i < SPX_WOTS_LEN; i++) { + counts[steps[i]]++; + } + total = 0; + for (l = SPX_WOTS_W - 1; l >= 0; l--) { + newTotal = counts[l] + total; + counts[l] = total; + total = newTotal; + } + for (i = 0; i < SPX_WOTS_LEN; i++) { + idxs[counts[steps[i]]] = (uint16_t)i; + counts[steps[i]]++; } -} -/** - * 4-way parallel version of gen_chain; expects 4x as much space in out, and - * 4x as much space in inx4. Assumes start and step identical across chains. - */ -static void gen_chainx4(unsigned char *outx4, const unsigned char *inx4, - unsigned int start, unsigned int steps, - const unsigned char *pub_seed, uint32_t addrx4[4 * 8], - const hash_state *state_seeded) { - uint32_t i; - unsigned int j; + /* We got our work cut out for us: do it! */ + for (i = 0; i < SPX_WOTS_LEN; i += 4) { + for (j = 0; j < 4 && i + j < SPX_WOTS_LEN; j++) { + idx = idxs[i + j]; + set_chain_addr(addrs + j * 8, idx); + bufs[j] = out + SPX_N * idx; + } - /* Initialize outx4 with the value at position 'start'. */ - memcpy(outx4, inx4, 4 * PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N); + /* As the chains are sorted in reverse order, we know that the first + * chain is the longest and the last one is the shortest. We keep + * an eye on whether the last chain is done and then on the one before, + * et cetera. */ + watching = 3; + done = 0; + while (i + watching >= SPX_WOTS_LEN) { + bufs[watching] = &empty[0]; + watching--; + } - /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_WOTS_W; i++) { - for (j = 0; j < 4; j++) { - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_set_hash_addr(addrx4 + j * 8, i); + for (k = 0;; k++) { + while (k == steps[idxs[i + watching]]) { + bufs[watching] = &empty[0]; + if (watching == 0) { + done = 1; + break; + } + watching--; + } + if (done) { + break; + } + for (j = 0; j < watching + 1; j++) { + set_hash_addr(addrs + j * 8, k + start[idxs[i + j]]); + } + + thashx4(bufs[0], bufs[1], bufs[2], bufs[3], + bufs[0], bufs[1], bufs[2], bufs[3], 1, ctx, addrs); } - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_thashx4_1(outx4 + 0 * PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N, - outx4 + 1 * PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N, - outx4 + 2 * PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N, - outx4 + 3 * PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N, - outx4 + 0 * PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N, - outx4 + 1 * PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N, - outx4 + 2 * PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N, - outx4 + 3 * PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N, - pub_seed, addrx4, - state_seeded); } } @@ -109,7 +107,8 @@ static void gen_chainx4(unsigned char *outx4, const unsigned char *inx4, * Interprets an array of bytes as integers in base w. * This only works when log_w is a divisor of 8. */ -static void base_w(unsigned int *output, const int out_len, const unsigned char *input) { +static void base_w(unsigned int *output, const int out_len, + const unsigned char *input) { int in = 0; int out = 0; unsigned char total = 0; @@ -122,119 +121,149 @@ static void base_w(unsigned int *output, const int out_len, const unsigned char in++; bits += 8; } - bits -= PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_WOTS_LOGW; - output[out] = (unsigned int)(total >> bits) & (PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_WOTS_W - 1); + bits -= SPX_WOTS_LOGW; + output[out] = (total >> bits) & (SPX_WOTS_W - 1); out++; } } /* Computes the WOTS+ checksum over a message (in base_w). */ -static void wots_checksum(unsigned int *csum_base_w, const unsigned int *msg_base_w) { +static void wots_checksum(unsigned int *csum_base_w, + const unsigned int *msg_base_w) { unsigned int csum = 0; - unsigned char csum_bytes[(PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_WOTS_LEN2 * PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_WOTS_LOGW + 7) / 8]; + unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; unsigned int i; /* Compute checksum. */ - for (i = 0; i < PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_WOTS_LEN1; i++) { - csum += PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_WOTS_W - 1 - msg_base_w[i]; + for (i = 0; i < SPX_WOTS_LEN1; i++) { + csum += SPX_WOTS_W - 1 - msg_base_w[i]; } /* Convert checksum to base_w. */ /* Make sure expected empty zero bits are the least significant bits. */ - csum = csum << (8 - ((PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_WOTS_LEN2 * PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_WOTS_LOGW) % 8)); - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); - base_w(csum_base_w, PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_WOTS_LEN2, csum_bytes); + csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); + ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); + base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); } /* Takes a message and derives the matching chain lengths. */ -static void chain_lengths(unsigned int *lengths, const unsigned char *msg) { - base_w(lengths, PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_WOTS_LEN1, msg); - wots_checksum(lengths + PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_WOTS_LEN1, lengths); +void chain_lengths(unsigned int *lengths, const unsigned char *msg) { + base_w(lengths, SPX_WOTS_LEN1, msg); + wots_checksum(lengths + SPX_WOTS_LEN1, lengths); } /** - * WOTS key generation. Takes a 32 byte sk_seed, expands it to WOTS private key - * elements and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. * * Writes the computed public key to 'pk'. */ -void PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_wots_gen_pk(unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *state_seeded) { +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]) { + unsigned int steps[SPX_WOTS_LEN]; + unsigned int start[SPX_WOTS_LEN]; uint32_t i; - unsigned int j; - uint32_t addrx4[4 * 8]; - unsigned char pkbuf[4 * PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N]; + chain_lengths(start, msg); - for (j = 0; j < 4; j++) { - memcpy(addrx4 + j * 8, addr, sizeof(uint32_t) * 8); - } - - /* The last iteration typically does not have complete set of 4 chains, - but because we use pkbuf, this is not an issue -- we still do as many - in parallel as possible. */ - for (i = 0; i < ((PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_WOTS_LEN + 3) & ~0x3); i += 4) { - for (j = 0; j < 4; j++) { - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_set_chain_addr(addrx4 + j * 8, i + j); - } - wots_gen_skx4(pkbuf, sk_seed, addrx4, state_seeded); - gen_chainx4(pkbuf, pkbuf, 0, PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_WOTS_W - 1, pub_seed, addrx4, state_seeded); - for (j = 0; j < 4; j++) { - if (i + j < PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_WOTS_LEN) { - memcpy(pk + (i + j)*PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N, pkbuf + j * PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N, PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N); - } - } + for (i = 0; i < SPX_WOTS_LEN; i++) { + steps[i] = SPX_WOTS_W - 1 - start[i]; } - // Get rid of unused argument variable. - (void)state_seeded; + gen_chains(pk, sig, start, steps, ctx, addr); } -/** - * Takes a n-byte message and the 32-byte sk_see to compute a signature 'sig'. +/* + * This generates 4 sequential WOTS public keys + * It also generates the WOTS signature if leaf_info indicates + * that we're signing with one of these WOTS keys */ -void PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_wots_sign(unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); +void wots_gen_leafx4(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info) { + struct leaf_info_x4 *info = v_info; + uint32_t *leaf_addr = info->leaf_addr; + uint32_t *pk_addr = info->pk_addr; + unsigned int i, j, k; + unsigned char pk_buffer[ 4 * SPX_WOTS_BYTES ]; + unsigned wots_offset = SPX_WOTS_BYTES; + unsigned char *buffer; + uint32_t wots_k_mask; + unsigned wots_sign_index; + + if (((leaf_idx ^ info->wots_sign_leaf) & ~3U) == 0) { + /* We're traversing the leaf that's signing; generate the WOTS */ + /* signature */ + wots_k_mask = 0; + wots_sign_index = info->wots_sign_leaf & 3; /* Which of of the 4 */ + /* 4 slots do the signatures come from */ + } else { + /* Nope, we're just generating pk's; turn off the signature logic */ + wots_k_mask = (uint32_t)~0; + wots_sign_index = 0; + } - for (i = 0; i < PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_WOTS_LEN; i++) { - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_set_chain_addr(addr, i); - wots_gen_sk(sig + i * PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N, sk_seed, addr, state_seeded); - gen_chain(sig + i * PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N, sig + i * PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N, 0, lengths[i], pub_seed, addr, state_seeded); + for (j = 0; j < 4; j++) { + set_keypair_addr( leaf_addr + j * 8, leaf_idx + j ); + set_keypair_addr( pk_addr + j * 8, leaf_idx + j ); } - // avoid unused argument - (void)state_seeded; -} + for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { + uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k to */ + /* the step if we're generating a signature, ~0 if we're not */ -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_WOTS_LEN]; - uint32_t i; + /* Start with the secret seed */ + for (j = 0; j < 4; j++) { + set_chain_addr(leaf_addr + j * 8, i); + set_hash_addr(leaf_addr + j * 8, 0); + set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTSPRF); + } + prf_addrx4(buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + buffer + 2 * wots_offset, + buffer + 3 * wots_offset, + ctx, leaf_addr); - chain_lengths(lengths, msg); + for (j = 0; j < 4; j++) { + set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTS); + } + + /* Iterate down the WOTS chain */ + for (k = 0;; k++) { + /* Check if one of the values we have needs to be saved as a */ + /* part of the WOTS signature */ + if (k == wots_k) { + memcpy( info->wots_sig + i * SPX_N, + buffer + wots_sign_index * wots_offset, SPX_N ); + } - for (i = 0; i < PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_WOTS_LEN; i++) { - PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_set_chain_addr(addr, i); - gen_chain(pk + i * PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N, sig + i * PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_N, - lengths[i], PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_WOTS_W - 1 - lengths[i], pub_seed, addr, - state_seeded); + /* Check if we hit the top of the chain */ + if (k == SPX_WOTS_W - 1) { + break; + } + + /* Iterate one step on all 4 chains */ + for (j = 0; j < 4; j++) { + set_hash_addr(leaf_addr + j * 8, k); + } + thashx4(buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + buffer + 2 * wots_offset, + buffer + 3 * wots_offset, + buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + buffer + 2 * wots_offset, + buffer + 3 * wots_offset, 1, ctx, leaf_addr); + } } - // avoid unused argument - (void)state_seeded; + /* Do the final thash to generate the public keys */ + thashx4(dest + 0 * SPX_N, + dest + 1 * SPX_N, + dest + 2 * SPX_N, + dest + 3 * SPX_N, + pk_buffer + 0 * wots_offset, + pk_buffer + 1 * wots_offset, + pk_buffer + 2 * wots_offset, + pk_buffer + 3 * wots_offset, SPX_WOTS_LEN, ctx, pk_addr); } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/wots.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/wots.h index 96ac86d367..4e7692eeef 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/wots.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/wots.h @@ -1,41 +1,25 @@ -#ifndef PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_WOTS_H -#define PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_WOTS_H +#ifndef SPX_WOTS_H +#define SPX_WOTS_H -#include "hash_state.h" -#include "params.h" #include -/** - * WOTS key generation. Takes a 32 byte seed for the private key, expands it to - * a full WOTS private key and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_wots_gen_pk( - unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -/** - * Takes a n-byte message and the 32-byte seed for the private key to compute a - * signature that is placed at 'sig'. - */ -void PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_wots_sign( - unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *hash_state_seeded); +#include "context.h" +#include "params.h" /** * Takes a WOTS signature and an n-byte message, computes a WOTS public key. * * Writes the computed public key to 'pk'. */ -void PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_wots_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); +#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]); + +/* + * Compute the chain lengths needed for a given message hash + */ +#define chain_lengths SPX_NAMESPACE(chain_lengths) +void chain_lengths(unsigned int *lengths, const unsigned char *msg); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/wotsx4.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/wotsx4.h new file mode 100644 index 0000000000..cd634f1743 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/wotsx4.h @@ -0,0 +1,41 @@ +#ifndef WOTSX4_H_ +#define WOTSX4_H_ + +#include + +#include "params.h" + +/* + * This is here to provide an interface to the internal wots_gen_leafx4 + * routine. While this routine is not referenced in the package outside of + * wots.c, it is called from the stand-alone benchmark code to characterize + * the performance + */ +struct leaf_info_x4 { + unsigned char *wots_sig; + uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ + uint32_t *wots_steps; + uint32_t leaf_addr[4 * 8]; + uint32_t pk_addr[4 * 8]; +}; + +/* Macro to set the leaf_info to something 'benign', that is, it would */ +/* run with the same time as it does during the real signing process */ +/* Used only by the benchmark code */ +#define INITIALIZE_LEAF_INFO_X4(info, addr, step_buffer) { \ + (info).wots_sig = 0; \ + (info).wots_sign_leaf = ~0; \ + (info).wots_steps = step_buffer; \ + int i; \ + for (i=0; i<4; i++) { \ + memcpy( &(info).leaf_addr[8*i], addr, 32 ); \ + memcpy( &(info).pk_addr[8*i], addr, 32 ); \ + } \ + } + +#define wots_gen_leafx4 SPX_NAMESPACE(wots_gen_leafx4) +void wots_gen_leafx4(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info); + +#endif /* WOTSX4_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/address.c b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/address.c index 7bd831e806..b956e9cb29 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/address.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/address.c @@ -1,78 +1,91 @@ #include +#include #include "address.h" #include "params.h" #include "utils.h" -void PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]) { - int i; - - for (i = 0; i < 8; i++) { - PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_ull_to_bytes( - bytes + i * 4, 4, addr[i]); - } -} - -void PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_set_layer_addr( - uint32_t addr[8], uint32_t layer) { - addr[0] = layer; +/* + * Specify which level of Merkle tree (the "layer") we're working on + */ +void set_layer_addr(uint32_t addr[8], uint32_t layer) { + ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; } -void PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_set_tree_addr( - uint32_t addr[8], uint64_t tree) { - addr[1] = 0; - addr[2] = (uint32_t) (tree >> 32); - addr[3] = (uint32_t) tree; +/* + * Specify which Merkle tree within the level (the "tree address") we're working on + */ +void set_tree_addr(uint32_t addr[8], uint64_t tree) { + ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); } -void PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_set_type( - uint32_t addr[8], uint32_t type) { - addr[4] = type; +/* + * Specify the reason we'll use this address structure for, that is, what + * hash will we compute with it. This is used so that unrelated types of + * hashes don't accidentally get the same address structure. The type will be + * one of the SPX_ADDR_TYPE constants + */ +void set_type(uint32_t addr[8], uint32_t type) { + ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; } -void PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; +/* + * Copy the layer and tree fields of the address structure. This is used + * when we're doing multiple types of hashes within the same Merkle tree + */ +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); } /* These functions are used for OTS addresses. */ -void PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_set_keypair_addr( - uint32_t addr[8], uint32_t keypair) { - addr[5] = keypair; +/* + * Specify which Merkle leaf we're working on; that is, which OTS keypair + * we're talking about. + */ +void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { + ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; } -void PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; - out[5] = in[5]; +/* + * Copy the layer, tree and keypair fields of the address structure. This is + * used when we're doing multiple things within the same OTS keypair + */ +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); + ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; } -void PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_set_chain_addr( - uint32_t addr[8], uint32_t chain) { - addr[6] = chain; +/* + * Specify which Merkle chain within the OTS we're working with + * (the chain address) + */ +void set_chain_addr(uint32_t addr[8], uint32_t chain) { + ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; } -void PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_set_hash_addr( - uint32_t addr[8], uint32_t hash) { - addr[7] = hash; +/* + * Specify where in the Merkle chain we are +* (the hash address) + */ +void set_hash_addr(uint32_t addr[8], uint32_t hash) { + ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; } /* These functions are used for all hash tree addresses (including FORS). */ -void PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_set_tree_height( - uint32_t addr[8], uint32_t tree_height) { - addr[6] = tree_height; +/* + * Specify the height of the node in the Merkle/FORS tree we are in + * (the tree height) + */ +void set_tree_height(uint32_t addr[8], uint32_t tree_height) { + ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; } -void PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_set_tree_index( - uint32_t addr[8], uint32_t tree_index) { - addr[7] = tree_index; +/* + * Specify the distance from the left edge of the node in the Merkle/FORS tree + * (the tree index) + */ +void set_tree_index(uint32_t addr[8], uint32_t tree_index) { + u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/address.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/address.h index 3c816a16a4..24a84eb40c 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/address.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/address.h @@ -1,50 +1,52 @@ -#ifndef PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_ADDRESS_H -#define PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_ADDRESS_H +#ifndef SPX_ADDRESS_H +#define SPX_ADDRESS_H #include -#define PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_ADDR_TYPE_WOTS 0 -#define PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_ADDR_TYPE_WOTSPK 1 -#define PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_ADDR_TYPE_HASHTREE 2 -#define PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_ADDR_TYPE_FORSTREE 3 -#define PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_ADDR_TYPE_FORSPK 4 +#include "params.h" -void PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]); +/* The hash types that are passed to set_type */ +#define SPX_ADDR_TYPE_WOTS 0 +#define SPX_ADDR_TYPE_WOTSPK 1 +#define SPX_ADDR_TYPE_HASHTREE 2 +#define SPX_ADDR_TYPE_FORSTREE 3 +#define SPX_ADDR_TYPE_FORSPK 4 +#define SPX_ADDR_TYPE_WOTSPRF 5 +#define SPX_ADDR_TYPE_FORSPRF 6 -void PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_set_layer_addr( - uint32_t addr[8], uint32_t layer); +#define set_layer_addr SPX_NAMESPACE(set_layer_addr) +void set_layer_addr(uint32_t addr[8], uint32_t layer); -void PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_set_tree_addr( - uint32_t addr[8], uint64_t tree); +#define set_tree_addr SPX_NAMESPACE(set_tree_addr) +void set_tree_addr(uint32_t addr[8], uint64_t tree); -void PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_set_type( - uint32_t addr[8], uint32_t type); +#define set_type SPX_NAMESPACE(set_type) +void set_type(uint32_t addr[8], uint32_t type); /* Copies the layer and tree part of one address into the other */ -void PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]); +#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); /* These functions are used for WOTS and FORS addresses. */ -void PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_set_keypair_addr( - uint32_t addr[8], uint32_t keypair); +#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) +void set_keypair_addr(uint32_t addr[8], uint32_t keypair); -void PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_set_chain_addr( - uint32_t addr[8], uint32_t chain); +#define set_chain_addr SPX_NAMESPACE(set_chain_addr) +void set_chain_addr(uint32_t addr[8], uint32_t chain); -void PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_set_hash_addr( - uint32_t addr[8], uint32_t hash); +#define set_hash_addr SPX_NAMESPACE(set_hash_addr) +void set_hash_addr(uint32_t addr[8], uint32_t hash); -void PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]); +#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); /* These functions are used for all hash tree addresses (including FORS). */ -void PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_set_tree_height( - uint32_t addr[8], uint32_t tree_height); +#define set_tree_height SPX_NAMESPACE(set_tree_height) +void set_tree_height(uint32_t addr[8], uint32_t tree_height); -void PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_set_tree_index( - uint32_t addr[8], uint32_t tree_index); +#define set_tree_index SPX_NAMESPACE(set_tree_index) +void set_tree_index(uint32_t addr[8], uint32_t tree_index); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/api.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/api.h index 4f02c3730e..c41e8717a3 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/api.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/api.h @@ -4,15 +4,13 @@ #include #include - - -#define PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_CRYPTO_ALGNAME "SPHINCS+" +#define PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_CRYPTO_ALGNAME "SPHINCS+-haraka-192f-robust" #define PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_CRYPTO_SECRETKEYBYTES 96 #define PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_CRYPTO_PUBLICKEYBYTES 48 -#define PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_CRYPTO_BYTES 35664 -#define PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_CRYPTO_SEEDBYTES 72 +#define PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_CRYPTO_BYTES 35664 +#define PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_CRYPTO_SEEDBYTES 72 /* * Returns the length of a secret key, in bytes @@ -39,43 +37,41 @@ size_t PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_crypto_sign_seedbytes(void); * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] * Format pk: [root || PUB_SEED] */ -int PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed); +int PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); /* * Generates a SPHINCS+ key pair. * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] * Format pk: [root || PUB_SEED] */ -int PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk); +int PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); /** * Returns an array containing a detached signature. */ -int PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk); +int PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); /** * Verifies a detached signature and message under a given public key. */ -int PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk); +int PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, + const uint8_t *pk); /** * Returns an array containing the signature followed by the message. */ -int PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk); +int PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); /** * Verifies a given signature-message pair under a given public key. */ -int PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk); - +int PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/context.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/context.h new file mode 100644 index 0000000000..600dfb73c7 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/context.h @@ -0,0 +1,24 @@ +#ifndef SPX_CONTEXT_H +#define SPX_CONTEXT_H + +#include +#include + +#include "params.h" + +typedef struct { + uint8_t pub_seed[SPX_N]; + uint8_t sk_seed[SPX_N]; + + + uint64_t tweaked512_rc64[10][8]; + uint32_t tweaked256_rc32[10][8]; +} spx_ctx; + +#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) +void initialize_hash_function(spx_ctx *ctx); + +#define free_hash_function SPX_NAMESPACE(free_hash_function) +void free_hash_function(spx_ctx *ctx); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/context_haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/context_haraka.c new file mode 100644 index 0000000000..f1cd7e3664 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/context_haraka.c @@ -0,0 +1,11 @@ +#include "context.h" +#include "haraka.h" + +void initialize_hash_function(spx_ctx *ctx) { + tweak_constants(ctx); +} + +// we don't support heap-based haraka right now +void free_hash_function(spx_ctx *ctx) { + (void)ctx; // suppress unused variable warnings +} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/fors.c b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/fors.c index e6c68b7613..96ca72e986 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/fors.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/fors.c @@ -2,58 +2,58 @@ #include #include -#include "address.h" #include "fors.h" + +#include "address.h" #include "hash.h" -#include "hash_state.h" #include "thash.h" #include "utils.h" +#include "utilsx1.h" -static void fors_gen_sk(unsigned char *sk, const unsigned char *sk_seed, - uint32_t fors_leaf_addr[8], const hash_state *hash_state_seeded) { - PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_prf_addr( - sk, sk_seed, fors_leaf_addr, hash_state_seeded); +static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + prf_addr(sk, ctx, fors_leaf_addr); } static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, - const unsigned char *pub_seed, - uint32_t fors_leaf_addr[8], - const hash_state *hash_state_seeded) { - PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_thash_1( - leaf, sk, pub_seed, fors_leaf_addr, hash_state_seeded); + const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + thash(leaf, sk, 1, ctx, fors_leaf_addr); } -static void fors_gen_leaf(unsigned char *leaf, const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx, const uint32_t fors_tree_addr[8], - const hash_state *hash_state_seeded) { - uint32_t fors_leaf_addr[8] = {0}; - - /* Only copy the parts that must be kept in fors_leaf_addr. */ - PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_copy_keypair_addr( - fors_leaf_addr, fors_tree_addr); - PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_set_type( - fors_leaf_addr, PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_set_tree_index( - fors_leaf_addr, addr_idx); - - fors_gen_sk(leaf, sk_seed, fors_leaf_addr, hash_state_seeded); - fors_sk_to_leaf(leaf, leaf, pub_seed, fors_leaf_addr, hash_state_seeded); +struct fors_gen_leaf_info { + uint32_t leaf_addrx[8]; +}; + +static void fors_gen_leafx1(unsigned char *leaf, + const spx_ctx *ctx, + uint32_t addr_idx, void *info) { + struct fors_gen_leaf_info *fors_info = info; + uint32_t *fors_leaf_addr = fors_info->leaf_addrx; + + /* Only set the parts that the caller doesn't set */ + set_tree_index(fors_leaf_addr, addr_idx); + set_type(fors_leaf_addr, SPX_ADDR_TYPE_FORSPRF); + fors_gen_sk(leaf, ctx, fors_leaf_addr); + + set_type(fors_leaf_addr, SPX_ADDR_TYPE_FORSTREE); + fors_sk_to_leaf(leaf, leaf, + ctx, fors_leaf_addr); } /** - * Interprets m as PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_FORS_HEIGHT-bit unsigned integers. - * Assumes m contains at least PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_FORS_TREES bits. - * Assumes indices has space for PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_FORS_TREES integers. + * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + * Assumes indices has space for SPX_FORS_TREES integers. */ static void message_to_indices(uint32_t *indices, const unsigned char *m) { unsigned int i, j; unsigned int offset = 0; - for (i = 0; i < PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_FORS_TREES; i++) { + for (i = 0; i < SPX_FORS_TREES; i++) { indices[i] = 0; - for (j = 0; j < PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_FORS_HEIGHT; j++) { - indices[i] ^= (((uint32_t)m[offset >> 3] >> (offset & 0x7)) & 0x1) << j; + for (j = 0; j < SPX_FORS_HEIGHT; j++) { + indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); offset++; } } @@ -61,55 +61,51 @@ static void message_to_indices(uint32_t *indices, const unsigned char *m) { /** * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_FORS_TREES bits. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. */ -void PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_fors_sign( - unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *hash_state_seeded) { - uint32_t indices[PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_FORS_TREES]; - unsigned char roots[PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_FORS_TREES * PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_N]; +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; uint32_t fors_tree_addr[8] = {0}; + struct fors_gen_leaf_info fors_info = {0}; + uint32_t *fors_leaf_addr = fors_info.leaf_addrx; uint32_t fors_pk_addr[8] = {0}; uint32_t idx_offset; unsigned int i; - PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_copy_keypair_addr( - fors_tree_addr, fors_addr); - PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_copy_keypair_addr( - fors_pk_addr, fors_addr); + copy_keypair_addr(fors_tree_addr, fors_addr); + copy_keypair_addr(fors_leaf_addr, fors_addr); - PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_set_type( - fors_tree_addr, PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_set_type( - fors_pk_addr, PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_ADDR_TYPE_FORSPK); + copy_keypair_addr(fors_pk_addr, fors_addr); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); message_to_indices(indices, m); - for (i = 0; i < PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_FORS_TREES; i++) { - idx_offset = i * (1 << PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_FORS_HEIGHT); + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); - PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_set_tree_height( - fors_tree_addr, 0); - PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_set_tree_index( - fors_tree_addr, indices[i] + idx_offset); + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); /* Include the secret key part that produces the selected leaf node. */ - fors_gen_sk(sig, sk_seed, fors_tree_addr, hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_N; + fors_gen_sk(sig, ctx, fors_tree_addr); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + sig += SPX_N; /* Compute the authentication path for this leaf node. */ - PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_treehash_FORS_HEIGHT( - roots + i * PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_N, sig, sk_seed, pub_seed, - indices[i], idx_offset, fors_gen_leaf, fors_tree_addr, - hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_N * PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_FORS_HEIGHT; + treehashx1(roots + i * SPX_N, sig, ctx, + indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx1, + fors_tree_addr, &fors_info); + + sig += SPX_N * SPX_FORS_HEIGHT; } /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_thash_FORS_TREES( - pk, roots, pub_seed, fors_pk_addr, hash_state_seeded); + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); } /** @@ -117,45 +113,44 @@ void PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_fors_sign( * This can be used for verification by comparing to a known public key, or to * subsequently verify a signature on the derived public key. The latter is the * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_FORS_TREES bits. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. */ -void PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_fors_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, const uint32_t fors_addr[8], - const hash_state *hash_state_seeded) { - uint32_t indices[PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_FORS_TREES]; - unsigned char roots[PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_FORS_TREES * PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_N]; - unsigned char leaf[PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_N]; +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + unsigned char leaf[SPX_N]; uint32_t fors_tree_addr[8] = {0}; uint32_t fors_pk_addr[8] = {0}; uint32_t idx_offset; unsigned int i; - PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_copy_keypair_addr(fors_tree_addr, fors_addr); - PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_copy_keypair_addr(fors_pk_addr, fors_addr); + copy_keypair_addr(fors_tree_addr, fors_addr); + copy_keypair_addr(fors_pk_addr, fors_addr); - PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_set_type(fors_tree_addr, PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_set_type(fors_pk_addr, PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_ADDR_TYPE_FORSPK); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); message_to_indices(indices, m); - for (i = 0; i < PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_FORS_TREES; i++) { - idx_offset = i * (1 << PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_FORS_HEIGHT); + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); - PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_set_tree_height(fors_tree_addr, 0); - PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_set_tree_index(fors_tree_addr, indices[i] + idx_offset); + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); /* Derive the leaf from the included secret key part. */ - fors_sk_to_leaf(leaf, sig, pub_seed, fors_tree_addr, hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_N; + fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); + sig += SPX_N; /* Derive the corresponding root node of this tree. */ - PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_compute_root(roots + i * PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_N, leaf, indices[i], idx_offset, sig, - PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_FORS_HEIGHT, pub_seed, fors_tree_addr, hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_N * PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_FORS_HEIGHT; + compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, + sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); + sig += SPX_N * SPX_FORS_HEIGHT; } /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_thash_FORS_TREES(pk, roots, pub_seed, fors_pk_addr, hash_state_seeded); + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/fors.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/fors.h index ee47e0573f..509140a178 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/fors.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/fors.h @@ -1,32 +1,32 @@ -#ifndef PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_FORS_H -#define PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_FORS_H +#ifndef SPX_FORS_H +#define SPX_FORS_H #include -#include "hash_state.h" +#include "context.h" #include "params.h" /** * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_FORS_TREES bits. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. */ -void PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_fors_sign( - unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *hash_state_seeded); +#define fors_sign SPX_NAMESPACE(fors_sign) +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); /** * Derives the FORS public key from a signature. * This can be used for verification by comparing to a known public key, or to * subsequently verify a signature on the derived public key. The latter is the * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_FORS_TREES bits. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. */ -void PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_fors_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, const uint32_t fors_addr[8], - const hash_state *hash_state_seeded); +#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/haraka.c index ab227774f9..a4944913b5 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/haraka.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/haraka.c @@ -6,12 +6,13 @@ * by Thomas Pornin */ -#include #include +#include #include #include #include "haraka.h" +#include "utils.h" #define HARAKAS_RATE 32 @@ -656,76 +657,62 @@ static void interleave_constant32(uint32_t *out, const unsigned char *in) { br_aes_ct_ortho(out); } -void PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_tweak_constants( - harakactx *state, - const unsigned char *pk_seed, const unsigned char *sk_seed, - unsigned long long seed_length) { +void tweak_constants(spx_ctx *ctx) { unsigned char buf[40 * 16]; int i; /* Use the standard constants to generate tweaked ones. */ - memcpy((uint8_t *)state->tweaked512_rc64, (uint8_t *)haraka512_rc64, 40 * 16); - - /* Constants for sk.seed */ - if (sk_seed != NULL) { - PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_haraka_S( - buf, 40 * 16, sk_seed, seed_length, state); - - /* Interleave constants */ - for (i = 0; i < 10; i++) { - interleave_constant32(state->tweaked256_rc32_sseed[i], buf + 32 * i); - } - } + memcpy((uint8_t *)ctx->tweaked512_rc64, (uint8_t *)haraka512_rc64, 40 * 16); /* Constants for pk.seed */ - PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_haraka_S( - buf, 40 * 16, pk_seed, seed_length, state); + haraka_S(buf, 40 * 16, ctx->pub_seed, SPX_N, ctx); for (i = 0; i < 10; i++) { - interleave_constant32(state->tweaked256_rc32[i], buf + 32 * i); - interleave_constant(state->tweaked512_rc64[i], buf + 64 * i); + interleave_constant32(ctx->tweaked256_rc32[i], buf + 32 * i); + interleave_constant(ctx->tweaked512_rc64[i], buf + 64 * i); } } -static void haraka_S_absorb(unsigned char *s, +static void haraka_S_absorb(unsigned char *s, unsigned int r, const unsigned char *m, unsigned long long mlen, - unsigned char p, const harakactx *state) { + unsigned char p, const spx_ctx *ctx) { unsigned long long i; - unsigned char t[HARAKAS_RATE]; + PQCLEAN_VLA(uint8_t, t, r); - while (mlen >= HARAKAS_RATE) { + while (mlen >= r) { /* XOR block to state */ - for (i = 0; i < HARAKAS_RATE; ++i) { + for (i = 0; i < r; ++i) { s[i] ^= m[i]; } - PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_haraka512_perm(s, s, state); - mlen -= HARAKAS_RATE; - m += HARAKAS_RATE; + haraka512_perm(s, s, ctx); + mlen -= r; + m += r; } - for (i = 0; i < HARAKAS_RATE; ++i) { + for (i = 0; i < r; ++i) { t[i] = 0; } for (i = 0; i < mlen; ++i) { t[i] = m[i]; } t[i] = p; - t[HARAKAS_RATE - 1] |= 128; - for (i = 0; i < HARAKAS_RATE; ++i) { + t[r - 1] |= 128; + for (i = 0; i < r; ++i) { s[i] ^= t[i]; } } static void haraka_S_squeezeblocks(unsigned char *h, unsigned long long nblocks, - unsigned char *s, const harakactx *state) { + unsigned char *s, unsigned int r, + const spx_ctx *ctx) { while (nblocks > 0) { - PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_haraka512_perm(s, s, state); + haraka512_perm(s, s, ctx); memcpy(h, s, HARAKAS_RATE); - h += HARAKAS_RATE; + h += r; nblocks--; } } -void PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_haraka_S_inc_init(uint8_t *s_inc) { +void haraka_S_inc_init(uint8_t *s_inc) { size_t i; for (i = 0; i < 64; i++) { @@ -734,7 +721,8 @@ void PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_haraka_S_inc_init(uint8_t *s_inc) { s_inc[64] = 0; } -void PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, const harakactx *state) { +void haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, + const spx_ctx *ctx) { size_t i; /* Recall that s_inc[64] is the non-absorbed bytes xored into the state */ @@ -745,19 +733,19 @@ void PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_haraka_S_inc_absorb(uint8_t *s_inc, c s_inc[s_inc[64] + i] ^= m[i]; } mlen -= (size_t)(HARAKAS_RATE - s_inc[64]); - m += HARAKAS_RATE - s_inc[64]; + m += HARAKAS_RATE - (uint8_t)s_inc[64]; s_inc[64] = 0; - PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_haraka512_perm(s_inc, s_inc, state); + haraka512_perm(s_inc, s_inc, ctx); } for (i = 0; i < mlen; i++) { s_inc[s_inc[64] + i] ^= m[i]; } - s_inc[64] = (uint8_t)(mlen + s_inc[64]); + s_inc[64] += (uint8_t)mlen; } -void PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_haraka_S_inc_finalize(uint8_t *s_inc) { +void haraka_S_inc_finalize(uint8_t *s_inc) { /* After haraka_S_inc_absorb, we are guaranteed that s_inc[64] < HARAKAS_RATE, so we can always use one more byte for p in the current state. */ s_inc[s_inc[64]] ^= 0x1F; @@ -765,22 +753,23 @@ void PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_haraka_S_inc_finalize(uint8_t *s_inc) s_inc[64] = 0; } -void PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, const harakactx *state) { - uint8_t i; +void haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, + const spx_ctx *ctx) { + size_t i; /* First consume any bytes we still have sitting around */ for (i = 0; i < outlen && i < s_inc[64]; i++) { /* There are s_inc[64] bytes left, so r - s_inc[64] is the first available byte. We consume from there, i.e., up to r. */ - out[i] = s_inc[(HARAKAS_RATE - s_inc[64] + i)]; + out[i] = (uint8_t)s_inc[(HARAKAS_RATE - s_inc[64] + i)]; } out += i; outlen -= i; - s_inc[64] = (uint8_t)(s_inc[64] - i); + s_inc[64] -= (uint8_t)i; /* Then squeeze the remaining necessary blocks */ while (outlen > 0) { - PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_haraka512_perm(s_inc, s_inc, state); + haraka512_perm(s_inc, s_inc, ctx); for (i = 0; i < outlen && i < HARAKAS_RATE; i++) { out[i] = s_inc[i]; @@ -791,7 +780,9 @@ void PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_haraka_S_inc_squeeze(uint8_t *out, si } } -void PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_haraka_S(unsigned char *out, unsigned long long outlen, const unsigned char *in, unsigned long long inlen, const harakactx *state) { +void haraka_S(unsigned char *out, unsigned long long outlen, + const unsigned char *in, unsigned long long inlen, + const spx_ctx *ctx) { unsigned long long i; unsigned char s[64]; unsigned char d[32]; @@ -799,20 +790,21 @@ void PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_haraka_S(unsigned char *out, unsigned for (i = 0; i < 64; i++) { s[i] = 0; } - haraka_S_absorb(s, in, inlen, 0x1F, state); + haraka_S_absorb(s, 32, in, inlen, 0x1F, ctx); - haraka_S_squeezeblocks(out, outlen / 32, s, state); + haraka_S_squeezeblocks(out, outlen / 32, s, 32, ctx); out += (outlen / 32) * 32; if (outlen % 32) { - haraka_S_squeezeblocks(d, 1, s, state); + haraka_S_squeezeblocks(d, 1, s, 32, ctx); for (i = 0; i < outlen % 32; i++) { out[i] = d[i]; } } } -void PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_haraka512_perm(unsigned char *out, const unsigned char *in, const harakactx *state) { +void haraka512_perm(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx) { uint32_t w[16]; uint64_t q[8], tmp_q; unsigned int i, j; @@ -829,7 +821,7 @@ void PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_haraka512_perm(unsigned char *out, co br_aes_ct64_bitslice_Sbox(q); shift_rows(q); mix_columns(q); - add_round_key(q, state->tweaked512_rc64[2 * i + j]); + add_round_key(q, ctx->tweaked512_rc64[2 * i + j]); } /* Mix states */ for (j = 0; j < 8; j++) { @@ -857,12 +849,12 @@ void PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_haraka512_perm(unsigned char *out, co br_range_enc32le(out, w, 16); } -void PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_haraka512(unsigned char *out, const unsigned char *in, const harakactx *state) { +void haraka512(unsigned char *out, const unsigned char *in, const spx_ctx *ctx) { int i; unsigned char buf[64]; - PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_haraka512_perm(buf, in, state); + haraka512_perm(buf, in, ctx); /* Feed-forward */ for (i = 0; i < 64; i++) { buf[i] = buf[i] ^ in[i]; @@ -876,50 +868,8 @@ void PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_haraka512(unsigned char *out, const u } -void PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_haraka256(unsigned char *out, const unsigned char *in, const harakactx *state) { - uint32_t q[8], tmp_q; - int i, j; - - for (i = 0; i < 4; i++) { - q[2 * i] = br_dec32le(in + 4 * i); - q[2 * i + 1] = br_dec32le(in + 4 * i + 16); - } - br_aes_ct_ortho(q); - - /* AES rounds */ - for (i = 0; i < 5; i++) { - for (j = 0; j < 2; j++) { - br_aes_ct_bitslice_Sbox(q); - shift_rows32(q); - mix_columns32(q); - add_round_key32(q, state->tweaked256_rc32[2 * i + j]); - } - - /* Mix states */ - for (j = 0; j < 8; j++) { - tmp_q = q[j]; - q[j] = (tmp_q & 0x81818181) | - (tmp_q & 0x02020202) << 1 | - (tmp_q & 0x04040404) << 2 | - (tmp_q & 0x08080808) << 3 | - (tmp_q & 0x10101010) >> 3 | - (tmp_q & 0x20202020) >> 2 | - (tmp_q & 0x40404040) >> 1; - } - } - - br_aes_ct_ortho(q); - for (i = 0; i < 4; i++) { - br_enc32le(out + 4 * i, q[2 * i]); - br_enc32le(out + 4 * i + 16, q[2 * i + 1]); - } - - for (i = 0; i < 32; i++) { - out[i] ^= in[i]; - } -} - -void PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_haraka256_sk(unsigned char *out, const unsigned char *in, const harakactx *state) { +void haraka256(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx) { uint32_t q[8], tmp_q; int i, j; @@ -935,7 +885,7 @@ void PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_haraka256_sk(unsigned char *out, cons br_aes_ct_bitslice_Sbox(q); shift_rows32(q); mix_columns32(q); - add_round_key32(q, state->tweaked256_rc32_sseed[2 * i + j]); + add_round_key32(q, ctx->tweaked256_rc32[2 * i + j]); } /* Mix states */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/haraka.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/haraka.h index b5b19f506a..737cb6065f 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/haraka.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/haraka.h @@ -1,40 +1,42 @@ -#ifndef PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_HARAKA_H -#define PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_HARAKA_H +#ifndef SPX_HARAKA_H +#define SPX_HARAKA_H -#include -#include - -typedef struct { - uint64_t tweaked512_rc64[10][8]; - uint32_t tweaked256_rc32[10][8]; - uint32_t tweaked256_rc32_sseed[10][8]; -} harakactx; +#include "context.h" +#include "params.h" /* Tweak constants with seed */ -void PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_tweak_constants( - harakactx *state, - const unsigned char *pk_seed, const unsigned char *sk_seed, - unsigned long long seed_length); +#define tweak_constants SPX_NAMESPACE(tweak_constants) +void tweak_constants(spx_ctx *ctx); /* Haraka Sponge */ -void PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_haraka_S_inc_init(uint8_t *s_inc); -void PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, const harakactx *state); -void PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_haraka_S_inc_finalize(uint8_t *s_inc); -void PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, const harakactx *state); -void PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_haraka_S( - unsigned char *out, unsigned long long outlen, - const unsigned char *in, unsigned long long inlen, const harakactx *state); +#define haraka_S_inc_init SPX_NAMESPACE(haraka_S_inc_init) +void haraka_S_inc_init(uint8_t *s_inc); +#define haraka_S_inc_absorb SPX_NAMESPACE(haraka_S_inc_absorb) +void haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, + const spx_ctx *ctx); +#define haraka_S_inc_finalize SPX_NAMESPACE(haraka_S_inc_finalize) +void haraka_S_inc_finalize(uint8_t *s_inc); +#define haraka_S_inc_squeeze SPX_NAMESPACE(haraka_S_inc_squeeze) +void haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, + const spx_ctx *ctx); +#define haraka_S SPX_NAMESPACE(haraka_S) +void haraka_S(unsigned char *out, unsigned long long outlen, + const unsigned char *in, unsigned long long inlen, + const spx_ctx *ctx); /* Applies the 512-bit Haraka permutation to in. */ -void PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_haraka512_perm(unsigned char *out, const unsigned char *in, const harakactx *state); +#define haraka512_perm SPX_NAMESPACE(haraka512_perm) +void haraka512_perm(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx); /* Implementation of Haraka-512 */ -void PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_haraka512(unsigned char *out, const unsigned char *in, const harakactx *state); +#define haraka512 SPX_NAMESPACE(haraka512) +void haraka512(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx); /* Implementation of Haraka-256 */ -void PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_haraka256(unsigned char *out, const unsigned char *in, const harakactx *state); - -/* Implementation of Haraka-256 using sk.seed constants */ -void PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_haraka256_sk(unsigned char *out, const unsigned char *in, const harakactx *state); +#define haraka256 SPX_NAMESPACE(haraka256) +void haraka256(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/haraka_offsets.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/haraka_offsets.h new file mode 100644 index 0000000000..7c062272a0 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/haraka_offsets.h @@ -0,0 +1,21 @@ +#ifndef HARAKA_OFFSETS_H_ +#define HARAKA_OFFSETS_H_ + +/* + * Offsets of various fields in the address structure when we use Haraka as + * the Sphincs+ hash function + */ + +#define SPX_OFFSET_LAYER 3 /* The byte used to specify the Merkle tree layer */ +#define SPX_OFFSET_TREE 8 /* The start of the 8 byte field used to specify the tree */ +#define SPX_OFFSET_TYPE 19 /* The byte used to specify the hash type (reason) */ +#define SPX_OFFSET_KP_ADDR2 22 /* The high byte used to specify the key pair (which one-time signature) */ +#define SPX_OFFSET_KP_ADDR1 23 /* The low byte used to specify the key pair */ +#define SPX_OFFSET_CHAIN_ADDR 27 /* The byte used to specify the chain address (which Winternitz chain) */ +#define SPX_OFFSET_HASH_ADDR 31 /* The byte used to specify the hash address (where in the Winternitz chain) */ +#define SPX_OFFSET_TREE_HGT 27 /* The byte used to specify the height of this node in the FORS or Merkle tree */ +#define SPX_OFFSET_TREE_INDEX 28 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ + +#define SPX_HARAKA 1 + +#endif /* HARAKA_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/hash.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/hash.h index 16e3ecce6e..f7c87d4c3c 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/hash.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/hash.h @@ -1,31 +1,28 @@ -#ifndef PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_HASH_H -#define PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_HASH_H - -#include "hash_state.h" +#ifndef SPX_HASH_H +#define SPX_HASH_H #include #include -void PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_initialize_hash_function( - hash_state *hash_state_seeded, - const unsigned char *pub_seed, const unsigned char *sk_seed); +#include "context.h" +#include "params.h" + +#define prf_addr SPX_NAMESPACE(prf_addr) +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]); -void PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_destroy_hash_function(hash_state *hash_state_seeded); +#define gen_message_random SPX_NAMESPACE(gen_message_random) +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); -void PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded); +#define hash_message SPX_NAMESPACE(hash_message) +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); -void PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); -void PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/hash_haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/hash_haraka.c index 265a7b434a..750a67423b 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/hash_haraka.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/hash_haraka.c @@ -2,58 +2,44 @@ #include #include "address.h" -#include "haraka.h" -#include "hash.h" #include "params.h" #include "utils.h" -void PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_initialize_hash_function( - hash_state *hash_state_seeded, - const unsigned char *pub_seed, const unsigned char *sk_seed) { - PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_tweak_constants(hash_state_seeded, pub_seed, sk_seed, PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_N); -} - -/* The haraka implementation is stack based and won't be replaced in PQClean/OQS, - so we don't need to do anything */ -void PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_destroy_hash_function( - hash_state *hash_state_seeded) { // NOLINT(readability-non-const-parameter) - (void)hash_state_seeded; -} +#include "haraka.h" +#include "hash.h" /* - * Computes PRF(key, addr), given a secret key of PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_N bytes and an address + * Computes PRF(key, addr), given a secret key of SPX_N bytes and an address */ -void PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded) { - unsigned char buf[PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_ADDR_BYTES]; - /* Since PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_N may be smaller than 32, we need a temporary buffer. */ +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]) { + /* Since SPX_N may be smaller than 32, we need temporary buffers. */ unsigned char outbuf[32]; + unsigned char buf[64] = {0}; - (void)key; /* Suppress an 'unused parameter' warning. */ + memcpy(buf, addr, SPX_ADDR_BYTES); + memcpy(buf + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); - PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_addr_to_bytes(buf, addr); - PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_haraka256_sk(outbuf, buf, hash_state_seeded); - memcpy(out, outbuf, PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_N); + haraka512(outbuf, (const void *)buf, ctx); + memcpy(out, outbuf, SPX_N); } /** * Computes the message-dependent randomness R, using a secret seed and an * optional randomization value as well as the message. */ -void PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded) { +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { uint8_t s_inc[65]; - PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_haraka_S_inc_init(s_inc); - PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_haraka_S_inc_absorb(s_inc, sk_prf, PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_N, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_haraka_S_inc_absorb(s_inc, optrand, PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_N, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_haraka_S_inc_absorb(s_inc, m, mlen, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_haraka_S_inc_finalize(s_inc); - PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_haraka_S_inc_squeeze(R, PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_N, s_inc, hash_state_seeded); + haraka_S_inc_init(s_inc); + haraka_S_inc_absorb(s_inc, sk_prf, SPX_N, ctx); + haraka_S_inc_absorb(s_inc, optrand, SPX_N, ctx); + haraka_S_inc_absorb(s_inc, m, mlen, ctx); + haraka_S_inc_finalize(s_inc); + haraka_S_inc_squeeze(R, SPX_N, s_inc, ctx); } /** @@ -61,36 +47,35 @@ void PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_gen_message_random( * Outputs the message digest and the index of the leaf. The index is split in * the tree index and the leaf index, for convenient copying to an address. */ -void PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded) { -#define PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_TREE_BITS (PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_TREE_HEIGHT * (PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_D - 1)) -#define PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_TREE_BYTES ((PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_TREE_BITS + 7) / 8) -#define PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_LEAF_BITS PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_TREE_HEIGHT -#define PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_LEAF_BYTES ((PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_LEAF_BITS + 7) / 8) -#define PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_DGST_BYTES (PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_FORS_MSG_BYTES + PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_TREE_BYTES + PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_LEAF_BYTES) +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { +#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) +#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) +#define SPX_LEAF_BITS SPX_TREE_HEIGHT +#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) +#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) - unsigned char buf[PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_DGST_BYTES]; + unsigned char buf[SPX_DGST_BYTES]; unsigned char *bufp = buf; uint8_t s_inc[65]; - PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_haraka_S_inc_init(s_inc); - PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_haraka_S_inc_absorb(s_inc, R, PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_N, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_haraka_S_inc_absorb(s_inc, pk + PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_N, PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_N, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_haraka_S_inc_absorb(s_inc, m, mlen, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_haraka_S_inc_finalize(s_inc); - PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_haraka_S_inc_squeeze(buf, PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_DGST_BYTES, s_inc, hash_state_seeded); + haraka_S_inc_init(s_inc); + haraka_S_inc_absorb(s_inc, R, SPX_N, ctx); + haraka_S_inc_absorb(s_inc, pk + SPX_N, SPX_N, ctx); // Only absorb root part of pk + haraka_S_inc_absorb(s_inc, m, mlen, ctx); + haraka_S_inc_finalize(s_inc); + haraka_S_inc_squeeze(buf, SPX_DGST_BYTES, s_inc, ctx); + + memcpy(digest, bufp, SPX_FORS_MSG_BYTES); + bufp += SPX_FORS_MSG_BYTES; - memcpy(digest, bufp, PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_FORS_MSG_BYTES); - bufp += PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_FORS_MSG_BYTES; - *tree = PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_bytes_to_ull(bufp, PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_TREE_BYTES); - *tree &= (~(uint64_t)0) >> (64 - PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_TREE_BITS); - bufp += PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_TREE_BYTES; + *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); + *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); + bufp += SPX_TREE_BYTES; - *leaf_idx = (uint32_t)PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_bytes_to_ull( - bufp, PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_LEAF_BYTES); - *leaf_idx &= (~(uint32_t)0) >> (32 - PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_LEAF_BITS); + *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); + *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/hash_state.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/hash_state.h deleted file mode 100644 index 5adb1d9a22..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/hash_state.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef SPX_HASH_STATE_H -#define SPX_HASH_STATE_H - -/** - * Defines the type of the hash function state. - * - * Don't be fooled into thinking this instance of SPHINCS+ isn't stateless! - * - * From Section 7.2.2 from the SPHINCS+ round-2 specification: - * - * Each of the instances of the tweakable hash function take PK.seed as its - * first input, which is constant for a given key pair – and, thus, across - * a single signature. This leads to a lot of redundant computation. To remedy - * this, we pad PK.seed to the length of a full 64-byte SHA-256 input block. - * Because of the Merkle-DamgÃ¥rd construction that underlies SHA-256, this - * allows for reuse of the intermediate SHA-256 state after the initial call to - * the compression function which improves performance. - * - * We pass this hash state around in functions, because otherwise we need to - * have a global variable. - */ - -#include "haraka.h" -#define hash_state harakactx - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/merkle.c b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/merkle.c new file mode 100644 index 0000000000..0c1479fd93 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/merkle.c @@ -0,0 +1,59 @@ +#include +#include + +#include "address.h" +#include "merkle.h" +#include "params.h" +#include "utils.h" +#include "utilsx1.h" +#include "wots.h" +#include "wotsx1.h" + +/* + * This generates a Merkle signature (WOTS signature followed by the Merkle + * authentication path). This is in this file because most of the complexity + * is involved with the WOTS signature; the Merkle authentication path logic + * is mostly hidden in treehashx4 + */ +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf) { + unsigned char *auth_path = sig + SPX_WOTS_BYTES; + struct leaf_info_x1 info = { 0 }; + unsigned steps[ SPX_WOTS_LEN ]; + + info.wots_sig = sig; + chain_lengths(steps, root); + info.wots_steps = steps; + + set_type(&tree_addr[0], SPX_ADDR_TYPE_HASHTREE); + set_type(&info.pk_addr[0], SPX_ADDR_TYPE_WOTSPK); + copy_subtree_addr(&info.leaf_addr[0], wots_addr); + copy_subtree_addr(&info.pk_addr[0], wots_addr); + + info.wots_sign_leaf = idx_leaf; + + treehashx1(root, auth_path, ctx, + idx_leaf, 0, + SPX_TREE_HEIGHT, + wots_gen_leafx1, + tree_addr, &info); +} + +/* Compute root node of the top-most subtree. */ +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { + /* We do not need the auth path in key generation, but it simplifies the + code to have just one treehash routine that computes both root and path + in one function. */ + unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; + uint32_t top_tree_addr[8] = {0}; + uint32_t wots_addr[8] = {0}; + + set_layer_addr(top_tree_addr, SPX_D - 1); + set_layer_addr(wots_addr, SPX_D - 1); + + merkle_sign(auth_path, root, ctx, + wots_addr, top_tree_addr, + (uint32_t)~0 /* ~0 means "don't bother generating an auth path */ ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/merkle.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/merkle.h new file mode 100644 index 0000000000..769cf2e970 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/merkle.h @@ -0,0 +1,21 @@ +#ifndef MERKLE_H_ +#define MERKLE_H_ + +#include + +#include "context.h" +#include "params.h" + +/* Generate a Merkle signature (WOTS signature followed by the Merkle */ +/* authentication path) */ +#define merkle_sign SPX_NAMESPACE(merkle_sign) +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf); + +/* Compute the root node of the top-most subtree. */ +#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); + +#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/nistapi.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/nistapi.h new file mode 100644 index 0000000000..3cb71afad4 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/nistapi.h @@ -0,0 +1,87 @@ +#ifndef SPX_API_H +#define SPX_API_H + +#include +#include + +#include "params.h" + +#define CRYPTO_ALGNAME "SPHINCS+" + +#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES +#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES +#define CRYPTO_BYTES SPX_BYTES +#define CRYPTO_SEEDBYTES (3*SPX_N) + +/* + * Returns the length of a secret key, in bytes + */ +#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) +size_t crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) +size_t crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) +size_t crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) +size_t crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +#define crypto_sign SPX_NAMESPACE(crypto_sign) +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/params.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/params.h index ec201a1f81..b4f8c6e933 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/params.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/params.h @@ -1,53 +1,56 @@ -#ifndef PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_PARAMS_H -#define PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_PARAMS_H +#ifndef SPX_PARAMS_H +#define SPX_PARAMS_H + +#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_##s /* Hash output length in bytes. */ -#define PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_N 24 +#define SPX_N 24 /* Height of the hypertree. */ -#define PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_FULL_HEIGHT 66 +#define SPX_FULL_HEIGHT 66 /* Number of subtree layer. */ -#define PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_D 22 +#define SPX_D 22 /* FORS tree dimensions. */ -#define PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_FORS_HEIGHT 8 -#define PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_FORS_TREES 33 +#define SPX_FORS_HEIGHT 8 +#define SPX_FORS_TREES 33 /* Winternitz parameter, */ -#define PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_WOTS_W 16 +#define SPX_WOTS_W 16 /* The hash function is defined by linking a different hash.c file, as opposed to setting a #define constant. */ /* For clarity */ -#define PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_ADDR_BYTES 32 +#define SPX_ADDR_BYTES 32 /* WOTS parameters. */ -#define PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_WOTS_LOGW 4 +#define SPX_WOTS_LOGW 4 -#define PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_WOTS_LEN1 (8 * PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_N / PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_WOTS_LOGW) +#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) -/* PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#define PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_WOTS_LEN2 3 +/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ +#define SPX_WOTS_LEN2 3 -#define PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_WOTS_LEN (PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_WOTS_LEN1 + PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_WOTS_LEN2) -#define PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_WOTS_BYTES (PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_WOTS_LEN * PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_N) -#define PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_WOTS_PK_BYTES PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_WOTS_BYTES +#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) +#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) +#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES /* Subtree size. */ -#define PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_TREE_HEIGHT (PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_FULL_HEIGHT / PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_D) +#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) + +//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT +// #error SPX_D should always divide SPX_FULL_HEIGHT +//#endif /* FORS parameters. */ -#define PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_FORS_MSG_BYTES ((PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_FORS_TREES + 7) / 8) -#define PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_FORS_BYTES ((PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_FORS_HEIGHT + 1) * PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_FORS_TREES * PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_N) -#define PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_FORS_PK_BYTES PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_N +#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) +#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) +#define SPX_FORS_PK_BYTES SPX_N /* Resulting SPX sizes. */ -#define PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_BYTES (PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_N + PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_FORS_BYTES + PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_D * PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_WOTS_BYTES +\ - PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_FULL_HEIGHT * PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_N) -#define PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_PK_BYTES (2 * PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_N) -#define PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_SK_BYTES (2 * PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_N + PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_PK_BYTES) - -/* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ -#define PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_OPTRAND_BYTES 32 +#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ + SPX_FULL_HEIGHT * SPX_N) +#define SPX_PK_BYTES (2 * SPX_N) +#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) + +#include "haraka_offsets.h" #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/sign.c b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/sign.c index 965559a20a..9d0c7d1b22 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/sign.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/sign.c @@ -3,72 +3,43 @@ #include #include "address.h" -#include "api.h" +#include "context.h" #include "fors.h" #include "hash.h" -#include "hash_state.h" +#include "merkle.h" +#include "nistapi.h" #include "params.h" #include "randombytes.h" #include "thash.h" #include "utils.h" #include "wots.h" -/** - * Computes the leaf at a given address. First generates the WOTS key pair, - * then computes leaf by hashing horizontally. - */ -static void wots_gen_leaf(unsigned char *leaf, const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx, const uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - unsigned char pk[PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_WOTS_BYTES]; - uint32_t wots_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_set_type( - wots_addr, PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_set_type( - wots_pk_addr, PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_ADDR_TYPE_WOTSPK); - - PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_set_keypair_addr( - wots_addr, addr_idx); - PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_wots_gen_pk( - pk, sk_seed, pub_seed, wots_addr, hash_state_seeded); - - PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_copy_keypair_addr( - wots_pk_addr, wots_addr); - PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_thash_WOTS_LEN( - leaf, pk, pub_seed, wots_pk_addr, hash_state_seeded); -} - /* * Returns the length of a secret key, in bytes */ -size_t PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_crypto_sign_secretkeybytes(void) { - return PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_CRYPTO_SECRETKEYBYTES; +size_t crypto_sign_secretkeybytes(void) { + return CRYPTO_SECRETKEYBYTES; } /* * Returns the length of a public key, in bytes */ -size_t PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_crypto_sign_publickeybytes(void) { - return PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_CRYPTO_PUBLICKEYBYTES; +size_t crypto_sign_publickeybytes(void) { + return CRYPTO_PUBLICKEYBYTES; } /* * Returns the length of a signature, in bytes */ -size_t PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_crypto_sign_bytes(void) { - return PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_CRYPTO_BYTES; +size_t crypto_sign_bytes(void) { + return CRYPTO_BYTES; } /* * Returns the length of the seed required to generate a key pair, in bytes */ -size_t PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_crypto_sign_seedbytes(void) { - return PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_CRYPTO_SEEDBYTES; +size_t crypto_sign_seedbytes(void) { + return CRYPTO_SEEDBYTES; } /* @@ -76,37 +47,30 @@ size_t PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_crypto_sign_seedbytes(void) { * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] * Format pk: [PUB_SEED || root] */ -int PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed) { - /* We do not need the auth path in key generation, but it simplifies the - code to have just one treehash routine that computes both root and path - in one function. */ - unsigned char auth_path[PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_TREE_HEIGHT * PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_N]; - uint32_t top_tree_addr[8] = {0}; - hash_state hash_state_seeded; - - PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_set_layer_addr( - top_tree_addr, PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_D - 1); - PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_set_type( - top_tree_addr, PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_ADDR_TYPE_HASHTREE); +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed) { + spx_ctx ctx; /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ - memcpy(sk, seed, PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_CRYPTO_SEEDBYTES); + memcpy(sk, seed, CRYPTO_SEEDBYTES); - memcpy(pk, sk + 2 * PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_N, PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_N); + memcpy(pk, sk + 2 * SPX_N, SPX_N); + + memcpy(ctx.pub_seed, pk, SPX_N); + memcpy(ctx.sk_seed, sk, SPX_N); /* This hook allows the hash function instantiation to do whatever preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_initialize_hash_function(&hash_state_seeded, pk, sk); + initialize_hash_function(&ctx); /* Compute root node of the top-most subtree. */ - PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_treehash_TREE_HEIGHT( - sk + 3 * PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_N, auth_path, sk, sk + 2 * PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_N, 0, 0, - wots_gen_leaf, top_tree_addr, &hash_state_seeded); + merkle_gen_root(sk + 3 * SPX_N, &ctx); + + // cleanup + free_hash_function(&ctx); - memcpy(pk + PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_N, sk + 3 * PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_N, PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_N); + memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); - PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_destroy_hash_function(&hash_state_seeded); return 0; } @@ -115,12 +79,10 @@ int PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_crypto_sign_seed_keypair( * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] * Format pk: [PUB_SEED || root] */ -int PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk) { - unsigned char seed[PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_CRYPTO_SEEDBYTES]; - randombytes(seed, PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_CRYPTO_SEEDBYTES); - PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_crypto_sign_seed_keypair( - pk, sk, seed); +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { + uint8_t seed[CRYPTO_SEEDBYTES]; + randombytes(seed, CRYPTO_SEEDBYTES); + crypto_sign_seed_keypair(pk, sk, seed); return 0; } @@ -128,101 +90,83 @@ int PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_crypto_sign_keypair( /** * Returns an array containing a detached signature. */ -int PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - const unsigned char *sk_seed = sk; - const unsigned char *sk_prf = sk + PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_N; - const unsigned char *pk = sk + 2 * PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_N; - const unsigned char *pub_seed = pk; - - unsigned char optrand[PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_N]; - unsigned char mhash[PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_FORS_MSG_BYTES]; - unsigned char root[PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_N]; +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk) { + spx_ctx ctx; + + const uint8_t *sk_prf = sk + SPX_N; + const uint8_t *pk = sk + 2 * SPX_N; + + uint8_t optrand[SPX_N]; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t root[SPX_N]; uint32_t i; uint64_t tree; uint32_t idx_leaf; uint32_t wots_addr[8] = {0}; uint32_t tree_addr[8] = {0}; - hash_state hash_state_seeded; + memcpy(ctx.sk_seed, sk, SPX_N); + memcpy(ctx.pub_seed, pk, SPX_N); /* This hook allows the hash function instantiation to do whatever preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_initialize_hash_function( - &hash_state_seeded, - pub_seed, sk_seed); + initialize_hash_function(&ctx); - PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_set_type( - wots_addr, PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_set_type( - tree_addr, PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_ADDR_TYPE_HASHTREE); + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); /* Optionally, signing can be made non-deterministic using optrand. This can help counter side-channel attacks that would benefit from getting a large number of traces when the signer uses the same nodes. */ - randombytes(optrand, PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_N); + randombytes(optrand, SPX_N); /* Compute the digest randomization value. */ - PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_gen_message_random( - sig, sk_prf, optrand, m, mlen, &hash_state_seeded); + gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); /* Derive the message digest and leaf index from R, PK and M. */ - PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_N; + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; - PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); /* Sign the message hash using FORS. */ - PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_fors_sign( - sig, root, mhash, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_FORS_BYTES; - - for (i = 0; i < PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_D; i++) { - PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_set_tree_addr(tree_addr, tree); - - PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); - - /* Compute a WOTS signature. */ - PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_wots_sign( - sig, root, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_WOTS_BYTES; - - /* Compute the authentication path for the used WOTS leaf. */ - PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_treehash_TREE_HEIGHT( - root, sig, sk_seed, pub_seed, idx_leaf, 0, - wots_gen_leaf, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_TREE_HEIGHT * PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_N; + fors_sign(sig, root, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); + sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_TREE_HEIGHT; + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; } - *siglen = PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_BYTES; + free_hash_function(&ctx); + + *siglen = SPX_BYTES; - PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_destroy_hash_function(&hash_state_seeded); return 0; } /** * Verifies a detached signature and message under a given public key. */ -int PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk) { - const unsigned char *pub_seed = pk; - const unsigned char *pub_root = pk + PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_N; - unsigned char mhash[PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_FORS_MSG_BYTES]; - unsigned char wots_pk[PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_WOTS_BYTES]; - unsigned char root[PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_N]; - unsigned char leaf[PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_N]; +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk) { + spx_ctx ctx; + const uint8_t *pub_root = pk + SPX_N; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t wots_pk[SPX_WOTS_BYTES]; + uint8_t root[SPX_N]; + uint8_t leaf[SPX_N]; unsigned int i; uint64_t tree; uint32_t idx_leaf; @@ -230,78 +174,66 @@ int PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_crypto_sign_verify( uint32_t tree_addr[8] = {0}; uint32_t wots_pk_addr[8] = {0}; - hash_state hash_state_seeded; - - if (siglen != PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_BYTES) { + if (siglen != SPX_BYTES) { return -1; } + memcpy(ctx.pub_seed, pk, SPX_N); + /* This hook allows the hash function instantiation to do whatever preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_initialize_hash_function( - &hash_state_seeded, - pub_seed, NULL); + initialize_hash_function(&ctx); - PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_set_type( - wots_addr, PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_set_type( - tree_addr, PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_ADDR_TYPE_HASHTREE); - PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_set_type( - wots_pk_addr, PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_ADDR_TYPE_WOTSPK); + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); /* Derive the message digest and leaf index from R || PK || M. */ - /* The additional PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_N is a result of the hash domain separator. */ - PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_N; + /* The additional SPX_N is a result of the hash domain separator. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; /* Layer correctly defaults to 0, so no need to set_layer_addr */ - PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); - PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_fors_pk_from_sig( - root, sig, mhash, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_FORS_BYTES; + fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; /* For each subtree.. */ - for (i = 0; i < PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_D; i++) { - PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_set_tree_addr(tree_addr, tree); + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); - PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); - PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_copy_keypair_addr( - wots_pk_addr, wots_addr); + copy_keypair_addr(wots_pk_addr, wots_addr); /* The WOTS public key is only correct if the signature was correct. */ /* Initially, root is the FORS pk, but on subsequent iterations it is the root of the subtree below the currently processed subtree. */ - PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_wots_pk_from_sig( - wots_pk, sig, root, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_WOTS_BYTES; + wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); + sig += SPX_WOTS_BYTES; /* Compute the leaf node using the WOTS public key. */ - PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_thash_WOTS_LEN( - leaf, wots_pk, pub_seed, wots_pk_addr, &hash_state_seeded); + thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); /* Compute the root node of this subtree. */ - PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_compute_root( - root, leaf, idx_leaf, 0, sig, PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_TREE_HEIGHT, - pub_seed, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_TREE_HEIGHT * PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_N; + compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, + &ctx, tree_addr); + sig += SPX_TREE_HEIGHT * SPX_N; /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_TREE_HEIGHT; + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; } - PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_destroy_hash_function(&hash_state_seeded); + // cleanup + free_hash_function(&ctx); + /* Check if the root node equals the root node in the public key. */ - if (memcmp(root, pub_root, PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_N) != 0) { + if (memcmp(root, pub_root, SPX_N) != 0) { return -1; } @@ -312,15 +244,14 @@ int PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_crypto_sign_verify( /** * Returns an array containing the signature followed by the message. */ -int PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk) { size_t siglen; - PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_crypto_sign_signature( - sm, &siglen, m, mlen, sk); + crypto_sign_signature(sm, &siglen, m, mlen, sk); - memmove(sm + PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_BYTES, m, mlen); + memmove(sm + SPX_BYTES, m, mlen); *smlen = siglen + mlen; return 0; @@ -329,28 +260,27 @@ int PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_crypto_sign( /** * Verifies a given signature-message pair under a given public key. */ -int PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk) { +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk) { /* The API caller does not necessarily know what size a signature should be - but SPHINCS+ signatures are always exactly PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_BYTES. */ - if (smlen < PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_BYTES) { + but SPHINCS+ signatures are always exactly SPX_BYTES. */ + if (smlen < SPX_BYTES) { memset(m, 0, smlen); *mlen = 0; return -1; } - *mlen = smlen - PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_BYTES; + *mlen = smlen - SPX_BYTES; - if (PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_crypto_sign_verify( - sm, PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_BYTES, sm + PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_BYTES, *mlen, pk)) { + if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { memset(m, 0, smlen); *mlen = 0; return -1; } /* If verification was successful, move the message to the right place. */ - memmove(m, sm + PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_BYTES, *mlen); + memmove(m, sm + SPX_BYTES, *mlen); return 0; } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/thash.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/thash.h index dc6ac5b286..8687ccfb4d 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/thash.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/thash.h @@ -1,28 +1,13 @@ -#ifndef PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_THASH_H -#define PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_THASH_H +#ifndef SPX_THASH_H +#define SPX_THASH_H -#include "hash_state.h" +#include "context.h" +#include "params.h" #include -void PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); +#define thash SPX_NAMESPACE(thash) +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/thash_haraka_robust.c b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/thash_haraka_robust.c index bebcfc338b..109502cbc2 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/thash_haraka_robust.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/thash_haraka_robust.c @@ -2,93 +2,44 @@ #include #include "address.h" -#include "hash_state.h" #include "params.h" #include "thash.h" +#include "utils.h" #include "haraka.h" /** - * Takes an array of inblocks concatenated arrays of PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_N bytes. + * Takes an array of inblocks concatenated arrays of SPX_N bytes. */ -static void PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_thash( - unsigned char *out, unsigned char *buf, - const unsigned char *in, unsigned int inblocks, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char *bitmask = buf + PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_ADDR_BYTES; +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]) { + PQCLEAN_VLA(uint8_t, buf, SPX_ADDR_BYTES + inblocks * SPX_N); + PQCLEAN_VLA(uint8_t, bitmask, inblocks * SPX_N); unsigned char outbuf[32]; unsigned char buf_tmp[64]; unsigned int i; - (void)pub_seed; /* Suppress an 'unused parameter' warning. */ - if (inblocks == 1) { /* F function */ - /* Since PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_N may be smaller than 32, we need a temporary buffer. */ + /* Since SPX_N may be smaller than 32, we need a temporary buffer. */ memset(buf_tmp, 0, 64); - PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_addr_to_bytes(buf_tmp, addr); + memcpy(buf_tmp, addr, 32); - PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_haraka256(outbuf, buf_tmp, hash_state_seeded); - for (i = 0; i < inblocks * PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_N; i++) { - buf_tmp[PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_ADDR_BYTES + i] = in[i] ^ outbuf[i]; + haraka256(outbuf, buf_tmp, ctx); + for (i = 0; i < inblocks * SPX_N; i++) { + buf_tmp[SPX_ADDR_BYTES + i] = in[i] ^ outbuf[i]; } - PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_haraka512(outbuf, buf_tmp, hash_state_seeded); - memcpy(out, outbuf, PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_N); + haraka512(outbuf, buf_tmp, ctx); + memcpy(out, outbuf, SPX_N); } else { /* All other tweakable hashes*/ - PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_addr_to_bytes(buf, addr); - PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_haraka_S( - bitmask, inblocks * PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_N, buf, PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_ADDR_BYTES, hash_state_seeded); + memcpy(buf, addr, 32); + haraka_S(bitmask, inblocks * SPX_N, buf, SPX_ADDR_BYTES, ctx); - for (i = 0; i < inblocks * PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_N; i++) { - buf[PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_ADDR_BYTES + i] = in[i] ^ bitmask[i]; + for (i = 0; i < inblocks * SPX_N; i++) { + buf[SPX_ADDR_BYTES + i] = in[i] ^ bitmask[i]; } - PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_haraka_S( - out, PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_N, buf, PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_N, hash_state_seeded); + haraka_S(out, SPX_N, buf, SPX_ADDR_BYTES + inblocks * SPX_N, ctx); } } - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_ADDR_BYTES + 1 * PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_N]; - PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_thash( - out, buf, in, 1, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_ADDR_BYTES + 2 * PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_N]; - PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_thash( - out, buf, in, 2, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_ADDR_BYTES + PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_WOTS_LEN * PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_N]; - PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_thash( - out, buf, in, PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_WOTS_LEN, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_ADDR_BYTES + PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_FORS_TREES * PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_N]; - PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_thash( - out, buf, in, PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_FORS_TREES, pub_seed, addr, hash_state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/utils.c b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/utils.c index 8bf3a679ac..177b541fb9 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/utils.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/utils.c @@ -1,34 +1,41 @@ -#include #include +#include "utils.h" + #include "address.h" #include "hash.h" -#include "hash_state.h" #include "params.h" #include "thash.h" -#include "utils.h" /** * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. */ -void PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in) { +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in) { + int i; /* Iterate over out in decreasing order, for big-endianness. */ - for (size_t i = outlen; i > 0; i--) { - out[i - 1] = in & 0xff; + for (i = (signed int)outlen - 1; i >= 0; i--) { + out[i] = in & 0xff; in = in >> 8; } } +void u32_to_bytes(unsigned char *out, uint32_t in) { + out[0] = (unsigned char)(in >> 24); + out[1] = (unsigned char)(in >> 16); + out[2] = (unsigned char)(in >> 8); + out[3] = (unsigned char)in; +} + /** * Converts the inlen bytes in 'in' from big-endian byte order to an integer. */ -unsigned long long PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_bytes_to_ull( - const unsigned char *in, size_t inlen) { +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { unsigned long long retval = 0; + unsigned int i; - for (size_t i = 0; i < inlen; i++) { + for (i = 0; i < inlen; i++) { retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); } return retval; @@ -38,94 +45,80 @@ unsigned long long PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_bytes_to_ull( * Computes a root node given a leaf and an auth path. * Expects address to be complete other than the tree_height and tree_index. */ -void PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]) { uint32_t i; - unsigned char buffer[2 * PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_N]; + unsigned char buffer[2 * SPX_N]; /* If leaf_idx is odd (last bit = 1), current path element is a right child and auth_path has to go left. Otherwise it is the other way around. */ if (leaf_idx & 1) { - memcpy(buffer + PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_N, leaf, PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_N); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_N); + memcpy(buffer + SPX_N, leaf, SPX_N); + memcpy(buffer, auth_path, SPX_N); } else { - memcpy(buffer, leaf, PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_N); - memcpy(buffer + PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_N, auth_path, PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_N); + memcpy(buffer, leaf, SPX_N); + memcpy(buffer + SPX_N, auth_path, SPX_N); } - auth_path += PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_N; + auth_path += SPX_N; for (i = 0; i < tree_height - 1; i++) { leaf_idx >>= 1; idx_offset >>= 1; /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_set_tree_height(addr, i + 1); - PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_set_tree_index( - addr, leaf_idx + idx_offset); + set_tree_height(addr, i + 1); + set_tree_index(addr, leaf_idx + idx_offset); /* Pick the right or left neighbor, depending on parity of the node. */ if (leaf_idx & 1) { - PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_thash_2( - buffer + PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_N, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_N); + thash(buffer + SPX_N, buffer, 2, ctx, addr); + memcpy(buffer, auth_path, SPX_N); } else { - PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_thash_2( - buffer, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer + PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_N, auth_path, PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_N); + thash(buffer, buffer, 2, ctx, addr); + memcpy(buffer + SPX_N, auth_path, SPX_N); } - auth_path += PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_N; + auth_path += SPX_N; } /* The last iteration is exceptional; we do not copy an auth_path node. */ leaf_idx >>= 1; idx_offset >>= 1; - PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_set_tree_height(addr, tree_height); - PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_set_tree_index( - addr, leaf_idx + idx_offset); - PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_thash_2( - root, buffer, pub_seed, addr, hash_state_seeded); + set_tree_height(addr, tree_height); + set_tree_index(addr, leaf_idx + idx_offset); + thash(root, buffer, 2, ctx, addr); } /** * For a given leaf index, computes the authentication path and the resulting * root node using Merkle's TreeHash algorithm. * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_ADDR_TYPE_FORSTREE). + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). * Applies the offset idx_offset to indices before building addresses, so that * it is possible to continue counting indices across trees. */ -static void PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_treehash( - unsigned char *root, unsigned char *auth_path, - unsigned char *stack, unsigned int *heights, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - +void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx * /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]) { + PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); + PQCLEAN_VLA(unsigned int, heights, tree_height + 1); unsigned int offset = 0; uint32_t idx; uint32_t tree_idx; for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { /* Add the next leaf node to the stack. */ - gen_leaf(stack + offset * PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_N, - sk_seed, pub_seed, idx + idx_offset, tree_addr, - hash_state_seeded); + gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); offset++; heights[offset - 1] = 0; /* If this is a node we need for the auth path.. */ if ((leaf_idx ^ 0x1) == idx) { - memcpy(auth_path, stack + (offset - 1)*PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_N, PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_N); + memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); } /* While the top-most nodes are of equal height.. */ @@ -134,66 +127,22 @@ static void PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_treehash( tree_idx = (idx >> (heights[offset - 1] + 1)); /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_set_tree_height( - tree_addr, heights[offset - 1] + 1); - PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_set_tree_index( - tree_addr, tree_idx + (idx_offset >> (heights[offset - 1] + 1))); + set_tree_height(tree_addr, heights[offset - 1] + 1); + set_tree_index(tree_addr, + tree_idx + (idx_offset >> (heights[offset - 1] + 1))); /* Hash the top-most nodes from the stack together. */ - PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_thash_2( - stack + (offset - 2)*PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_N, stack + (offset - 2)*PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_N, - pub_seed, tree_addr, hash_state_seeded); + thash(stack + (offset - 2)*SPX_N, + stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); offset--; /* Note that the top-most node is now one layer higher. */ heights[offset - 1]++; /* If this is a node we need for the auth path.. */ if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_path + heights[offset - 1]*PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_N, - stack + (offset - 1)*PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_N, PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_N); + memcpy(auth_path + heights[offset - 1]*SPX_N, + stack + (offset - 1)*SPX_N, SPX_N); } } } - memcpy(root, stack, PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_N); -} - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_FORS_HEIGHT + 1)*PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_N]; - unsigned int heights[PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_FORS_HEIGHT + 1]; - - PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_FORS_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_TREE_HEIGHT + 1)*PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_N]; - unsigned int heights[PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_TREE_HEIGHT + 1]; - - PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_TREE_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); + memcpy(root, stack, SPX_N); } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/utils.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/utils.h index 3c8bd7e401..64f5d5a53a 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/utils.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/utils.h @@ -1,64 +1,58 @@ -#ifndef PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_UTILS_H -#define PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_UTILS_H +#ifndef SPX_UTILS_H +#define SPX_UTILS_H -#include "hash_state.h" -#include "params.h" -#include #include +#include "compat.h" +#include "context.h" +#include "params.h" + + +/* To support MSVC use alloca() instead of VLAs. See #20. */ + + /** * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. */ -void PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in); +#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in); +#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) +void u32_to_bytes(unsigned char *out, uint32_t in); /** * Converts the inlen bytes in 'in' from big-endian byte order to an integer. */ -unsigned long long PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_bytes_to_ull( - const unsigned char *in, size_t inlen); +#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); /** * Computes a root node given a leaf and an auth path. * Expects address to be complete other than the tree_height and tree_index. */ -void PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); +#define compute_root SPX_NAMESPACE(compute_root) +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]); /** * For a given leaf index, computes the authentication path and the resulting * root node using Merkle's TreeHash algorithm. * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_ADDR_TYPE_FORSTREE). + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). * Applies the offset idx_offset to indices before building addresses, so that * it is possible to continue counting indices across trees. */ -void PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); +#define treehash SPX_NAMESPACE(treehash) +void treehash(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx *ctx /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]); -void PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/utilsx1.c b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/utilsx1.c new file mode 100644 index 0000000000..fccb69b35d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/utilsx1.c @@ -0,0 +1,100 @@ +#include + +#include "utilsx1.h" + +#include "address.h" +#include "params.h" +#include "thash.h" +#include "utils.h" + +/* + * Generate the entire Merkle tree, computing the authentication path for + * leaf_idx, and the resulting root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) + * + * This expects tree_addr to be initialized to the addr structures for the + * Merkle tree nodes + * + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + * + * This works by using the standard Merkle tree building algorithm, + */ +void treehashx1(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, + uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* Where to write the leaves */, + const spx_ctx * /* ctx */, + uint32_t idx, void *info), + uint32_t tree_addr[8], + void *info) { + /* This is where we keep the intermediate nodes */ + PQCLEAN_VLA(uint8_t, stack, tree_height * SPX_N); + + uint32_t idx; + uint32_t max_idx = (uint32_t)((1 << tree_height) - 1); + for (idx = 0;; idx++) { + unsigned char current[2 * SPX_N]; /* Current logical node is at */ + /* index[SPX_N]. We do this to minimize the number of copies */ + /* needed during a thash */ + gen_leaf( ¤t[SPX_N], ctx, idx + idx_offset, + info ); + + /* Now combine the freshly generated right node with previously */ + /* generated left ones */ + uint32_t internal_idx_offset = idx_offset; + uint32_t internal_idx = idx; + uint32_t internal_leaf = leaf_idx; + uint32_t h; /* The height we are in the Merkle tree */ + for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { + + /* Check if we hit the top of the tree */ + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[SPX_N], SPX_N ); + return; + } + + /* + * Check if the node we have is a part of the + * authentication path; if it is, write it out + */ + if ((internal_idx ^ internal_leaf) == 0x01) { + memcpy( &auth_path[ h * SPX_N ], + ¤t[SPX_N], + SPX_N ); + } + + /* + * Check if we're at a left child; if so, stop going up the stack + * Exception: if we've reached the end of the tree, keep on going + * (so we combine the last 4 nodes into the one root node in two + * more iterations) + */ + if ((internal_idx & 1) == 0 && idx < max_idx) { + break; + } + + /* Ok, we're at a right node */ + /* Now combine the left and right logical nodes together */ + + /* Set the address of the node we're creating. */ + internal_idx_offset >>= 1; + set_tree_height(tree_addr, h + 1); + set_tree_index(tree_addr, internal_idx / 2 + internal_idx_offset ); + + unsigned char *left = &stack[h * SPX_N]; + memcpy( ¤t[0], left, SPX_N ); + thash( ¤t[1 * SPX_N], + ¤t[0 * SPX_N], + 2, ctx, tree_addr); + } + + /* We've hit a left child; save the current for when we get the */ + /* corresponding right right */ + memcpy( &stack[h * SPX_N], ¤t[SPX_N], SPX_N); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/utilsx1.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/utilsx1.h new file mode 100644 index 0000000000..e911d17d53 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/utilsx1.h @@ -0,0 +1,27 @@ +#ifndef SPX_UTILSX4_H +#define SPX_UTILSX4_H + +#include + +#include "context.h" +#include "params.h" + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +#define treehashx1 SPX_NAMESPACE(treehashx1) +void treehashx1(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* Where to write the leaf */, + const spx_ctx * /* ctx */, + uint32_t addr_idx, void *info), + uint32_t tree_addrx4[8], void *info); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/wots.c b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/wots.c index bcbab8443d..249717aaa8 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/wots.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/wots.c @@ -1,32 +1,20 @@ #include #include +#include "wots.h" +#include "wotsx1.h" + #include "address.h" #include "hash.h" -#include "hash_state.h" #include "params.h" #include "thash.h" #include "utils.h" -#include "wots.h" +#include "utilsx1.h" // TODO clarify address expectations, and make them more uniform. // TODO i.e. do we expect types to be set already? // TODO and do we expect modifications or copies? -/** - * Computes the starting value for a chain, i.e. the secret key. - * Expects the address to be complete up to the chain address. - */ -static void wots_gen_sk(unsigned char *sk, const unsigned char *sk_seed, - uint32_t wots_addr[8], - const hash_state *hash_state_seeded) { - /* Make sure that the hash address is actually zeroed. */ - PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_set_hash_addr(wots_addr, 0); - - /* Generate sk element. */ - PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_prf_addr(sk, sk_seed, wots_addr, hash_state_seeded); -} - /** * Computes the chaining function. * out and in have to be n-byte arrays. @@ -36,18 +24,16 @@ static void wots_gen_sk(unsigned char *sk, const unsigned char *sk_seed, */ static void gen_chain(unsigned char *out, const unsigned char *in, unsigned int start, unsigned int steps, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { + const spx_ctx *ctx, uint32_t addr[8]) { uint32_t i; /* Initialize out with the value at position 'start'. */ - memcpy(out, in, PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_N); + memcpy(out, in, SPX_N); /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_WOTS_W; i++) { - PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_set_hash_addr(addr, i); - PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_thash_1( - out, out, pub_seed, addr, hash_state_seeded); + for (i = start; i < (start + steps) && i < SPX_WOTS_W; i++) { + set_hash_addr(addr, i); + thash(out, out, 1, ctx, addr); } } @@ -56,13 +42,13 @@ static void gen_chain(unsigned char *out, const unsigned char *in, * Interprets an array of bytes as integers in base w. * This only works when log_w is a divisor of 8. */ -static void base_w(unsigned int *output, const size_t out_len, +static void base_w(unsigned int *output, const int out_len, const unsigned char *input) { - size_t in = 0; - size_t out = 0; + int in = 0; + int out = 0; unsigned char total = 0; - unsigned int bits = 0; - size_t consumed; + int bits = 0; + int consumed; for (consumed = 0; consumed < out_len; consumed++) { if (bits == 0) { @@ -70,8 +56,8 @@ static void base_w(unsigned int *output, const size_t out_len, in++; bits += 8; } - bits -= PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_WOTS_LOGW; - output[out] = (unsigned int)((total >> bits) & (PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_WOTS_W - 1)); + bits -= SPX_WOTS_LOGW; + output[out] = (total >> bits) & (SPX_WOTS_W - 1); out++; } } @@ -80,67 +66,25 @@ static void base_w(unsigned int *output, const size_t out_len, static void wots_checksum(unsigned int *csum_base_w, const unsigned int *msg_base_w) { unsigned int csum = 0; - unsigned char csum_bytes[(PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_WOTS_LEN2 * PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_WOTS_LOGW + 7) / 8]; + unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; unsigned int i; /* Compute checksum. */ - for (i = 0; i < PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_WOTS_LEN1; i++) { - csum += PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_WOTS_W - 1 - msg_base_w[i]; + for (i = 0; i < SPX_WOTS_LEN1; i++) { + csum += SPX_WOTS_W - 1 - msg_base_w[i]; } /* Convert checksum to base_w. */ /* Make sure expected empty zero bits are the least significant bits. */ - csum = csum << (8 - ((PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_WOTS_LEN2 * PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_WOTS_LOGW) % 8)); - PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_ull_to_bytes( - csum_bytes, sizeof(csum_bytes), csum); - base_w(csum_base_w, PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_WOTS_LEN2, csum_bytes); + csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); + ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); + base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); } /* Takes a message and derives the matching chain lengths. */ -static void chain_lengths(unsigned int *lengths, const unsigned char *msg) { - base_w(lengths, PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_WOTS_LEN1, msg); - wots_checksum(lengths + PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_WOTS_LEN1, lengths); -} - -/** - * WOTS key generation. Takes a 32 byte sk_seed, expands it to WOTS private key - * elements and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_wots_gen_pk( - unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - uint32_t i; - - for (i = 0; i < PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_WOTS_LEN; i++) { - PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_set_chain_addr(addr, i); - wots_gen_sk(pk + i * PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_N, sk_seed, addr, hash_state_seeded); - gen_chain(pk + i * PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_N, pk + i * PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_N, - 0, PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_WOTS_W - 1, pub_seed, addr, hash_state_seeded); - } -} - -/** - * Takes a n-byte message and the 32-byte sk_see to compute a signature 'sig'. - */ -void PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_wots_sign( - unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *hash_state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_WOTS_LEN; i++) { - PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_set_chain_addr(addr, i); - wots_gen_sk(sig + i * PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_N, sk_seed, addr, hash_state_seeded); - gen_chain(sig + i * PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_N, sig + i * PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_N, 0, lengths[i], pub_seed, addr, hash_state_seeded); - } +void chain_lengths(unsigned int *lengths, const unsigned char *msg) { + base_w(lengths, SPX_WOTS_LEN1, msg); + wots_checksum(lengths + SPX_WOTS_LEN1, lengths); } /** @@ -148,20 +92,17 @@ void PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_wots_sign( * * Writes the computed public key to 'pk'. */ -void PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_wots_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_WOTS_LEN]; +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]) { + unsigned int lengths[SPX_WOTS_LEN]; uint32_t i; chain_lengths(lengths, msg); - for (i = 0; i < PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_WOTS_LEN; i++) { - PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_set_chain_addr(addr, i); - gen_chain(pk + i * PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_N, sig + i * PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_N, - lengths[i], PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_WOTS_W - 1 - lengths[i], pub_seed, addr, - hash_state_seeded); + for (i = 0; i < SPX_WOTS_LEN; i++) { + set_chain_addr(addr, i); + gen_chain(pk + i * SPX_N, sig + i * SPX_N, + lengths[i], SPX_WOTS_W - 1 - lengths[i], ctx, addr); } } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/wots.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/wots.h index cf94e14aa3..4e7692eeef 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/wots.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/wots.h @@ -1,41 +1,25 @@ -#ifndef PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_WOTS_H -#define PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_WOTS_H +#ifndef SPX_WOTS_H +#define SPX_WOTS_H -#include "hash_state.h" -#include "params.h" #include -/** - * WOTS key generation. Takes a 32 byte seed for the private key, expands it to - * a full WOTS private key and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_wots_gen_pk( - unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -/** - * Takes a n-byte message and the 32-byte seed for the private key to compute a - * signature that is placed at 'sig'. - */ -void PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_wots_sign( - unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *hash_state_seeded); +#include "context.h" +#include "params.h" /** * Takes a WOTS signature and an n-byte message, computes a WOTS public key. * * Writes the computed public key to 'pk'. */ -void PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_wots_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); +#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]); + +/* + * Compute the chain lengths needed for a given message hash + */ +#define chain_lengths SPX_NAMESPACE(chain_lengths) +void chain_lengths(unsigned int *lengths, const unsigned char *msg); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/wotsx1.c b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/wotsx1.c new file mode 100644 index 0000000000..3adec78dfb --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/wotsx1.c @@ -0,0 +1,76 @@ +#include +#include + +#include "wots.h" +#include "wotsx1.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "thash.h" +#include "utils.h" + +/* + * This generates a WOTS public key + * It also generates the WOTS signature if leaf_info indicates + * that we're signing with this WOTS key + */ +void wots_gen_leafx1(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info) { + struct leaf_info_x1 *info = v_info; + uint32_t *leaf_addr = info->leaf_addr; + uint32_t *pk_addr = info->pk_addr; + unsigned int i, k; + unsigned char pk_buffer[ SPX_WOTS_BYTES ]; + unsigned char *buffer; + uint32_t wots_k_mask; + + if (leaf_idx == info->wots_sign_leaf) { + /* We're traversing the leaf that's signing; generate the WOTS */ + /* signature */ + wots_k_mask = 0; + } else { + /* Nope, we're just generating pk's; turn off the signature logic */ + wots_k_mask = (uint32_t)~0; + } + + set_keypair_addr( leaf_addr, leaf_idx ); + set_keypair_addr( pk_addr, leaf_idx ); + + for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { + uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k to */ + /* the step if we're generating a signature, ~0 if we're not */ + + /* Start with the secret seed */ + set_chain_addr(leaf_addr, i); + set_hash_addr(leaf_addr, 0); + set_type(leaf_addr, SPX_ADDR_TYPE_WOTSPRF); + + prf_addr(buffer, ctx, leaf_addr); + + set_type(leaf_addr, SPX_ADDR_TYPE_WOTS); + + /* Iterate down the WOTS chain */ + for (k = 0;; k++) { + /* Check if this is the value that needs to be saved as a */ + /* part of the WOTS signature */ + if (k == wots_k) { + memcpy( info->wots_sig + i * SPX_N, buffer, SPX_N ); + } + + /* Check if we hit the top of the chain */ + if (k == SPX_WOTS_W - 1) { + break; + } + + /* Iterate one step on the chain */ + set_hash_addr(leaf_addr, k); + + thash(buffer, buffer, 1, ctx, leaf_addr); + } + } + + /* Do the final thash to generate the public keys */ + thash(dest, pk_buffer, SPX_WOTS_LEN, ctx, pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/wotsx1.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/wotsx1.h new file mode 100644 index 0000000000..e617929f96 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/wotsx1.h @@ -0,0 +1,39 @@ +#ifndef WOTSX1_H_ +#define WOTSX1_H_ + +#include + +#include "context.h" +#include "params.h" + +/* + * This is here to provide an interface to the internal wots_gen_leafx1 + * routine. While this routine is not referenced in the package outside of + * wots.c, it is called from the stand-alone benchmark code to characterize + * the performance + */ +struct leaf_info_x1 { + unsigned char *wots_sig; + uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ + uint32_t *wots_steps; + uint32_t leaf_addr[8]; + uint32_t pk_addr[8]; +}; + +/* Macro to set the leaf_info to something 'benign', that is, it would */ +/* run with the same time as it does during the real signing process */ +/* Used only by the benchmark code */ +#define INITIALIZE_LEAF_INFO_X1(info, addr, step_buffer) { \ + (info).wots_sig = 0; \ + (info).wots_sign_leaf = ~0; \ + (info).wots_steps = step_buffer; \ + memcpy( &(info).leaf_addr[0], (addr), 32 ); \ + memcpy( &(info).pk_addr[0], (addr), 32 ); \ + } + +#define wots_gen_leafx1 SPX_NAMESPACE(wots_gen_leafx1) +void wots_gen_leafx1(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info); + +#endif /* WOTSX1_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/address.c b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/address.c index 3ba23d4590..b956e9cb29 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/address.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/address.c @@ -1,78 +1,91 @@ #include +#include #include "address.h" #include "params.h" #include "utils.h" -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]) { - int i; - - for (i = 0; i < 8; i++) { - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_ull_to_bytes( - bytes + i * 4, 4, addr[i]); - } -} - -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_set_layer_addr( - uint32_t addr[8], uint32_t layer) { - addr[0] = layer; +/* + * Specify which level of Merkle tree (the "layer") we're working on + */ +void set_layer_addr(uint32_t addr[8], uint32_t layer) { + ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; } -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_set_tree_addr( - uint32_t addr[8], uint64_t tree) { - addr[1] = 0; - addr[2] = (uint32_t) (tree >> 32); - addr[3] = (uint32_t) tree; +/* + * Specify which Merkle tree within the level (the "tree address") we're working on + */ +void set_tree_addr(uint32_t addr[8], uint64_t tree) { + ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); } -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_set_type( - uint32_t addr[8], uint32_t type) { - addr[4] = type; +/* + * Specify the reason we'll use this address structure for, that is, what + * hash will we compute with it. This is used so that unrelated types of + * hashes don't accidentally get the same address structure. The type will be + * one of the SPX_ADDR_TYPE constants + */ +void set_type(uint32_t addr[8], uint32_t type) { + ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; } -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; +/* + * Copy the layer and tree fields of the address structure. This is used + * when we're doing multiple types of hashes within the same Merkle tree + */ +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); } /* These functions are used for OTS addresses. */ -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_set_keypair_addr( - uint32_t addr[8], uint32_t keypair) { - addr[5] = keypair; +/* + * Specify which Merkle leaf we're working on; that is, which OTS keypair + * we're talking about. + */ +void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { + ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; } -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; - out[5] = in[5]; +/* + * Copy the layer, tree and keypair fields of the address structure. This is + * used when we're doing multiple things within the same OTS keypair + */ +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); + ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; } -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_set_chain_addr( - uint32_t addr[8], uint32_t chain) { - addr[6] = chain; +/* + * Specify which Merkle chain within the OTS we're working with + * (the chain address) + */ +void set_chain_addr(uint32_t addr[8], uint32_t chain) { + ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; } -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_set_hash_addr( - uint32_t addr[8], uint32_t hash) { - addr[7] = hash; +/* + * Specify where in the Merkle chain we are +* (the hash address) + */ +void set_hash_addr(uint32_t addr[8], uint32_t hash) { + ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; } /* These functions are used for all hash tree addresses (including FORS). */ -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_set_tree_height( - uint32_t addr[8], uint32_t tree_height) { - addr[6] = tree_height; +/* + * Specify the height of the node in the Merkle/FORS tree we are in + * (the tree height) + */ +void set_tree_height(uint32_t addr[8], uint32_t tree_height) { + ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; } -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_set_tree_index( - uint32_t addr[8], uint32_t tree_index) { - addr[7] = tree_index; +/* + * Specify the distance from the left edge of the node in the Merkle/FORS tree + * (the tree index) + */ +void set_tree_index(uint32_t addr[8], uint32_t tree_index) { + u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/address.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/address.h index f5a85216b5..24a84eb40c 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/address.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/address.h @@ -1,50 +1,52 @@ -#ifndef PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_ADDRESS_H -#define PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_ADDRESS_H +#ifndef SPX_ADDRESS_H +#define SPX_ADDRESS_H #include -#define PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_ADDR_TYPE_WOTS 0 -#define PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_ADDR_TYPE_WOTSPK 1 -#define PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_ADDR_TYPE_HASHTREE 2 -#define PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_ADDR_TYPE_FORSTREE 3 -#define PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_ADDR_TYPE_FORSPK 4 +#include "params.h" -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]); +/* The hash types that are passed to set_type */ +#define SPX_ADDR_TYPE_WOTS 0 +#define SPX_ADDR_TYPE_WOTSPK 1 +#define SPX_ADDR_TYPE_HASHTREE 2 +#define SPX_ADDR_TYPE_FORSTREE 3 +#define SPX_ADDR_TYPE_FORSPK 4 +#define SPX_ADDR_TYPE_WOTSPRF 5 +#define SPX_ADDR_TYPE_FORSPRF 6 -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_set_layer_addr( - uint32_t addr[8], uint32_t layer); +#define set_layer_addr SPX_NAMESPACE(set_layer_addr) +void set_layer_addr(uint32_t addr[8], uint32_t layer); -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_set_tree_addr( - uint32_t addr[8], uint64_t tree); +#define set_tree_addr SPX_NAMESPACE(set_tree_addr) +void set_tree_addr(uint32_t addr[8], uint64_t tree); -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_set_type( - uint32_t addr[8], uint32_t type); +#define set_type SPX_NAMESPACE(set_type) +void set_type(uint32_t addr[8], uint32_t type); /* Copies the layer and tree part of one address into the other */ -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]); +#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); /* These functions are used for WOTS and FORS addresses. */ -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_set_keypair_addr( - uint32_t addr[8], uint32_t keypair); +#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) +void set_keypair_addr(uint32_t addr[8], uint32_t keypair); -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_set_chain_addr( - uint32_t addr[8], uint32_t chain); +#define set_chain_addr SPX_NAMESPACE(set_chain_addr) +void set_chain_addr(uint32_t addr[8], uint32_t chain); -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_set_hash_addr( - uint32_t addr[8], uint32_t hash); +#define set_hash_addr SPX_NAMESPACE(set_hash_addr) +void set_hash_addr(uint32_t addr[8], uint32_t hash); -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]); +#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); /* These functions are used for all hash tree addresses (including FORS). */ -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_set_tree_height( - uint32_t addr[8], uint32_t tree_height); +#define set_tree_height SPX_NAMESPACE(set_tree_height) +void set_tree_height(uint32_t addr[8], uint32_t tree_height); -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_set_tree_index( - uint32_t addr[8], uint32_t tree_index); +#define set_tree_index SPX_NAMESPACE(set_tree_index) +void set_tree_index(uint32_t addr[8], uint32_t tree_index); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/api.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/api.h index 4d8824170e..1d3e324184 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/api.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/api.h @@ -4,15 +4,13 @@ #include #include - - -#define PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_CRYPTO_ALGNAME "SPHINCS+" +#define PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_CRYPTO_ALGNAME "SPHINCS+-haraka-192f-simple" #define PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_CRYPTO_SECRETKEYBYTES 96 #define PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_CRYPTO_PUBLICKEYBYTES 48 -#define PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_CRYPTO_BYTES 35664 -#define PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_CRYPTO_SEEDBYTES 72 +#define PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_CRYPTO_BYTES 35664 +#define PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_CRYPTO_SEEDBYTES 72 /* * Returns the length of a secret key, in bytes @@ -39,43 +37,41 @@ size_t PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_crypto_sign_seedbytes(void); * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] * Format pk: [root || PUB_SEED] */ -int PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed); +int PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); /* * Generates a SPHINCS+ key pair. * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] * Format pk: [root || PUB_SEED] */ -int PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk); +int PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); /** * Returns an array containing a detached signature. */ -int PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk); +int PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); /** * Verifies a detached signature and message under a given public key. */ -int PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk); +int PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, + const uint8_t *pk); /** * Returns an array containing the signature followed by the message. */ -int PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk); +int PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); /** * Verifies a given signature-message pair under a given public key. */ -int PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk); - +int PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/context.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/context.h new file mode 100644 index 0000000000..f03446b9cb --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/context.h @@ -0,0 +1,22 @@ +#ifndef SPX_CONTEXT_H +#define SPX_CONTEXT_H + +#include + +#include "immintrin.h" +#include "params.h" + +typedef struct { + uint8_t pub_seed[SPX_N]; + uint8_t sk_seed[SPX_N]; + + __m128i rc[40]; +} spx_ctx; + +#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) +void initialize_hash_function(spx_ctx *ctx); + +#define free_hash_function SPX_NAMESPACE(free_hash_function) +void free_hash_function(spx_ctx *ctx); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/context_haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/context_haraka.c new file mode 100644 index 0000000000..f1cd7e3664 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/context_haraka.c @@ -0,0 +1,11 @@ +#include "context.h" +#include "haraka.h" + +void initialize_hash_function(spx_ctx *ctx) { + tweak_constants(ctx); +} + +// we don't support heap-based haraka right now +void free_hash_function(spx_ctx *ctx) { + (void)ctx; // suppress unused variable warnings +} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/fors.c b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/fors.c index 4da07fc794..f1b0639cfc 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/fors.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/fors.c @@ -2,8 +2,9 @@ #include #include -#include "address.h" #include "fors.h" + +#include "address.h" #include "hash.h" #include "hashx4.h" #include "thash.h" @@ -11,19 +12,24 @@ #include "utils.h" #include "utilsx4.h" +static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + prf_addr(sk, ctx, fors_leaf_addr); +} + static void fors_gen_skx4(unsigned char *sk0, unsigned char *sk1, unsigned char *sk2, - unsigned char *sk3, const unsigned char *sk_seed, - uint32_t fors_leaf_addrx4[4 * 8], - const hash_state *state_seeded) { - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_prf_addrx4(sk0, sk1, sk2, sk3, sk_seed, fors_leaf_addrx4, state_seeded); + unsigned char *sk3, const spx_ctx *ctx, + uint32_t fors_leaf_addrx4[4 * 8]) { + prf_addrx4(sk0, sk1, sk2, sk3, + ctx, fors_leaf_addrx4); } static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, - const unsigned char *pub_seed, - uint32_t fors_leaf_addr[8], const hash_state *state_seeded) { - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_thash_1(leaf, sk, pub_seed, fors_leaf_addr, state_seeded); + const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + thash(leaf, sk, 1, ctx, fors_leaf_addr); } static void fors_sk_to_leafx4(unsigned char *leaf0, @@ -34,57 +40,64 @@ static void fors_sk_to_leafx4(unsigned char *leaf0, const unsigned char *sk1, const unsigned char *sk2, const unsigned char *sk3, - const unsigned char *pub_seed, - uint32_t fors_leaf_addrx4[4 * 8], - const hash_state *state_seeded) { - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_thashx4_1(leaf0, leaf1, leaf2, leaf3, - sk0, sk1, sk2, sk3, pub_seed, fors_leaf_addrx4, state_seeded); + const spx_ctx *ctx, + uint32_t fors_leaf_addrx4[4 * 8]) { + thashx4(leaf0, leaf1, leaf2, leaf3, + sk0, sk1, sk2, sk3, + 1, ctx, fors_leaf_addrx4); } -static void fors_gen_leafx4(unsigned char *leaf0, - unsigned char *leaf1, - unsigned char *leaf2, - unsigned char *leaf3, - const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx0, - uint32_t addr_idx1, - uint32_t addr_idx2, - uint32_t addr_idx3, - const uint32_t fors_tree_addr[8], - const hash_state *state_seeded) { - uint32_t fors_leaf_addrx4[4 * 8] = {0}; +struct fors_gen_leaf_info { + uint32_t leaf_addrx[4 * 8]; +}; + +static void fors_gen_leafx4(unsigned char *leaf, + const spx_ctx *ctx, + uint32_t addr_idx, void *info) { + struct fors_gen_leaf_info *fors_info = info; + uint32_t *fors_leaf_addrx4 = fors_info->leaf_addrx; unsigned int j; - /* Only copy the parts that must be kept in fors_leaf_addrx4. */ + /* Only set the parts that the caller doesn't set */ for (j = 0; j < 4; j++) { - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_copy_keypair_addr(fors_leaf_addrx4 + j * 8, fors_tree_addr); - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_set_type(fors_leaf_addrx4 + j * 8, PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_ADDR_TYPE_FORSTREE); + set_tree_index(fors_leaf_addrx4 + j * 8, addr_idx + j); + set_type(fors_leaf_addrx4 + j * 8, SPX_ADDR_TYPE_FORSPRF); } - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_set_tree_index(fors_leaf_addrx4 + 0 * 8, addr_idx0); - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_set_tree_index(fors_leaf_addrx4 + 1 * 8, addr_idx1); - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_set_tree_index(fors_leaf_addrx4 + 2 * 8, addr_idx2); - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_set_tree_index(fors_leaf_addrx4 + 3 * 8, addr_idx3); + fors_gen_skx4(leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + leaf + 2 * SPX_N, + leaf + 3 * SPX_N, + ctx, fors_leaf_addrx4); + + for (j = 0; j < 4; j++) { + set_type(fors_leaf_addrx4 + j * 8, SPX_ADDR_TYPE_FORSTREE); + } - fors_gen_skx4(leaf0, leaf1, leaf2, leaf3, sk_seed, fors_leaf_addrx4, state_seeded); - fors_sk_to_leafx4(leaf0, leaf1, leaf2, leaf3, - leaf0, leaf1, leaf2, leaf3, pub_seed, fors_leaf_addrx4, state_seeded); + fors_sk_to_leafx4(leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + leaf + 2 * SPX_N, + leaf + 3 * SPX_N, + leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + leaf + 2 * SPX_N, + leaf + 3 * SPX_N, + ctx, fors_leaf_addrx4); } /** - * Interprets m as PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_FORS_HEIGHT-bit unsigned integers. - * Assumes m contains at least PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_FORS_TREES bits. - * Assumes indices has space for PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_FORS_TREES integers. + * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + * Assumes indices has space for SPX_FORS_TREES integers. */ static void message_to_indices(uint32_t *indices, const unsigned char *m) { unsigned int i, j; unsigned int offset = 0; - for (i = 0; i < PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_FORS_TREES; i++) { + for (i = 0; i < SPX_FORS_TREES; i++) { indices[i] = 0; - for (j = 0; j < PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_FORS_HEIGHT; j++) { - indices[i] ^= (((uint32_t)m[offset >> 3] >> (offset & 0x7)) & 0x1) << j; + for (j = 0; j < SPX_FORS_HEIGHT; j++) { + indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); offset++; } } @@ -92,68 +105,53 @@ static void message_to_indices(uint32_t *indices, const unsigned char *m) { /** * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_FORS_TREES bits. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. */ -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *state_seeded) { - /* Round up to multiple of 4 to prevent out-of-bounds for x4 parallelism */ - uint32_t indices[(PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_FORS_TREES + 3) & ~3] = {0}; - unsigned char roots[((PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_FORS_TREES + 3) & ~3) * PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N]; - /* Sign to a buffer, since we may not have a nice multiple of 4 and would - otherwise overrun the signature. */ - unsigned char sigbufx4[4 * PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N * (1 + PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_FORS_HEIGHT)]; - uint32_t fors_tree_addrx4[4 * 8] = {0}; +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + uint32_t fors_tree_addr[4 * 8] = {0}; + struct fors_gen_leaf_info fors_info = {0}; + uint32_t *fors_leaf_addr = fors_info.leaf_addrx; uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset[4] = {0}; - unsigned int i, j; + uint32_t idx_offset; + unsigned int i; - for (j = 0; j < 4; j++) { - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_copy_keypair_addr(fors_tree_addrx4 + j * 8, fors_addr); - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_set_type(fors_tree_addrx4 + j * 8, PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_ADDR_TYPE_FORSTREE); + for (i = 0; i < 4; i++) { + copy_keypair_addr(fors_tree_addr + 8 * i, fors_addr); + set_type(fors_tree_addr + 8 * i, SPX_ADDR_TYPE_FORSTREE); + copy_keypair_addr(fors_leaf_addr + 8 * i, fors_addr); } - - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_copy_keypair_addr(fors_pk_addr, fors_addr); - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_set_type(fors_pk_addr, PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_ADDR_TYPE_FORSPK); + copy_keypair_addr(fors_pk_addr, fors_addr); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); message_to_indices(indices, m); - for (i = 0; i < ((PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_FORS_TREES + 3) & ~0x3); i += 4) { - for (j = 0; j < 4; j++) { - if (i + j < PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_FORS_TREES) { - idx_offset[j] = (i + j) * (1 << PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_FORS_HEIGHT); + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_set_tree_height(fors_tree_addrx4 + j * 8, 0); - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_set_tree_index(fors_tree_addrx4 + j * 8, - indices[i + j] + idx_offset[j]); - } - } + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); - /* Include the secret key part that produces the selected leaf nodes. */ - fors_gen_skx4(sigbufx4 + 0 * PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N, - sigbufx4 + 1 * PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N, - sigbufx4 + 2 * PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N, - sigbufx4 + 3 * PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N, - sk_seed, fors_tree_addrx4, state_seeded); - - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_treehashx4_FORS_HEIGHT(roots + i * PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N, sigbufx4 + 4 * PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N, sk_seed, pub_seed, - &indices[i], idx_offset, fors_gen_leafx4, fors_tree_addrx4, - state_seeded); - - for (j = 0; j < 4; j++) { - if (i + j < PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_FORS_TREES) { - memcpy(sig, sigbufx4 + j * PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N, PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N); - memcpy(sig + PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N, - sigbufx4 + 4 * PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N + j * PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N * PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_FORS_HEIGHT, - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N * PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_FORS_HEIGHT); - sig += PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N * (1 + PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_FORS_HEIGHT); - } - } + /* Include the secret key part that produces the selected leaf node. */ + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); + fors_gen_sk(sig, ctx, fors_tree_addr); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + sig += SPX_N; + + /* Compute the authentication path for this leaf node. */ + treehashx4(roots + i * SPX_N, sig, ctx, + indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx4, + fors_tree_addr, &fors_info); + + sig += SPX_N * SPX_FORS_HEIGHT; } /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_thash_FORS_TREES(pk, roots, pub_seed, fors_pk_addr, state_seeded); + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); } /** @@ -161,46 +159,44 @@ void PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_fors_sign(unsigned char *sig, unsigne * This can be used for verification by comparing to a known public key, or to * subsequently verify a signature on the derived public key. The latter is the * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_FORS_TREES bits. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. */ -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, - const uint32_t fors_addr[8], - const hash_state *state_seeded) { - uint32_t indices[PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_FORS_TREES]; - unsigned char roots[PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_FORS_TREES * PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N]; - unsigned char leaf[PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N]; +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + unsigned char leaf[SPX_N]; uint32_t fors_tree_addr[8] = {0}; uint32_t fors_pk_addr[8] = {0}; uint32_t idx_offset; unsigned int i; - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_copy_keypair_addr(fors_tree_addr, fors_addr); - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_copy_keypair_addr(fors_pk_addr, fors_addr); + copy_keypair_addr(fors_tree_addr, fors_addr); + copy_keypair_addr(fors_pk_addr, fors_addr); - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_set_type(fors_tree_addr, PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_set_type(fors_pk_addr, PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_ADDR_TYPE_FORSPK); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); message_to_indices(indices, m); - for (i = 0; i < PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_FORS_TREES; i++) { - idx_offset = i * (1 << PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_FORS_HEIGHT); + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_set_tree_height(fors_tree_addr, 0); - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_set_tree_index(fors_tree_addr, indices[i] + idx_offset); + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); /* Derive the leaf from the included secret key part. */ - fors_sk_to_leaf(leaf, sig, pub_seed, fors_tree_addr, state_seeded); - sig += PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N; + fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); + sig += SPX_N; /* Derive the corresponding root node of this tree. */ - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_compute_root(roots + i * PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N, leaf, indices[i], idx_offset, - sig, PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_FORS_HEIGHT, pub_seed, fors_tree_addr, - state_seeded); - sig += PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N * PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_FORS_HEIGHT; + compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, + sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); + sig += SPX_N * SPX_FORS_HEIGHT; } /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_thash_FORS_TREES(pk, roots, pub_seed, fors_pk_addr, state_seeded); + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/fors.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/fors.h index d1a29b6e37..509140a178 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/fors.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/fors.h @@ -1,32 +1,32 @@ -#ifndef PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_FORS_H -#define PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_FORS_H +#ifndef SPX_FORS_H +#define SPX_FORS_H #include -#include "hash_state.h" +#include "context.h" #include "params.h" /** * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_FORS_TREES bits. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. */ -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_fors_sign( - unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *hash_state_seeded); +#define fors_sign SPX_NAMESPACE(fors_sign) +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); /** * Derives the FORS public key from a signature. * This can be used for verification by comparing to a known public key, or to * subsequently verify a signature on the derived public key. The latter is the * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_FORS_TREES bits. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. */ -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_fors_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, const uint32_t fors_addr[8], - const hash_state *hash_state_seeded); +#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/haraka.c index 68b2ce04c3..b414b691d7 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/haraka.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/haraka.c @@ -8,10 +8,12 @@ Plain C implementation of the Haraka256 and Haraka512 permutations. #include #include "haraka.h" +#include "harakax4.h" +#include "utils.h" #define HARAKAS_RATE 32 -#define u64 uint64_t +#define u64 unsigned long #define u128 __m128i #define LOAD(src) _mm_loadu_si128((u128 *)(src)) @@ -20,7 +22,7 @@ Plain C implementation of the Haraka256 and Haraka512 permutations. #define XOR128(a, b) _mm_xor_si128(a, b) #define AES2(s0, s1, rci) \ - (s0) = _mm_aesenc_si128(s0, *(rci)); \ + s0 = _mm_aesenc_si128(s0, *(rci)); \ (s1) = _mm_aesenc_si128(s1, *((rci) + 1)); \ (s0) = _mm_aesenc_si128(s0, *((rci) + 2)); \ (s1) = _mm_aesenc_si128(s1, *((rci) + 3)); @@ -32,7 +34,7 @@ Plain C implementation of the Haraka256 and Haraka512 permutations. AES2((s3)[0], (s3)[1], rci); #define AES4(s0, s1, s2, s3, rci) \ - (s0) = _mm_aesenc_si128(s0, *(rci)); \ + s0 = _mm_aesenc_si128(s0, *(rci)); \ (s1) = _mm_aesenc_si128(s1, *((rci) + 1)); \ (s2) = _mm_aesenc_si128(s2, *((rci) + 2)); \ (s3) = _mm_aesenc_si128(s3, *((rci) + 3)); \ @@ -68,17 +70,17 @@ Plain C implementation of the Haraka256 and Haraka512 permutations. _mm_storeu_si128((u128 *)((out) + 16), \ _mm_castpd_si128(_mm_shuffle_pd(_mm_castsi128_pd(s2), _mm_castsi128_pd(s3), 0))); -static void load_haraka_constants(u128 rc[40]) { - rc[ 0] = _mm_set_epi32((int)0x0684704c, (int)0xe620c00a, (int)0xb2c5fef0, (int)0x75817b9d); - rc[ 1] = _mm_set_epi32((int)0x8b66b4e1, (int)0x88f3a06b, (int)0x640f6ba4, (int)0x2f08f717); - rc[ 2] = _mm_set_epi32((int)0x3402de2d, (int)0x53f28498, (int)0xcf029d60, (int)0x9f029114); - rc[ 3] = _mm_set_epi32((int)0x0ed6eae6, (int)0x2e7b4f08, (int)0xbbf3bcaf, (int)0xfd5b4f79); - rc[ 4] = _mm_set_epi32((int)0xcbcfb0cb, (int)0x4872448b, (int)0x79eecd1c, (int)0xbe397044); - rc[ 5] = _mm_set_epi32((int)0x7eeacdee, (int)0x6e9032b7, (int)0x8d5335ed, (int)0x2b8a057b); - rc[ 6] = _mm_set_epi32((int)0x67c28f43, (int)0x5e2e7cd0, (int)0xe2412761, (int)0xda4fef1b); - rc[ 7] = _mm_set_epi32((int)0x2924d9b0, (int)0xafcacc07, (int)0x675ffde2, (int)0x1fc70b3b); - rc[ 8] = _mm_set_epi32((int)0xab4d63f1, (int)0xe6867fe9, (int)0xecdb8fca, (int)0xb9d465ee); - rc[ 9] = _mm_set_epi32((int)0x1c30bf84, (int)0xd4b7cd64, (int)0x5b2a404f, (int)0xad037e33); +static void load_haraka_constants(u128 *rc) { + rc[0] = _mm_set_epi32((int)0x0684704c, (int)0xe620c00a, (int)0xb2c5fef0, (int)0x75817b9d); + rc[1] = _mm_set_epi32((int)0x8b66b4e1, (int)0x88f3a06b, (int)0x640f6ba4, (int)0x2f08f717); + rc[2] = _mm_set_epi32((int)0x3402de2d, (int)0x53f28498, (int)0xcf029d60, (int)0x9f029114); + rc[3] = _mm_set_epi32((int)0x0ed6eae6, (int)0x2e7b4f08, (int)0xbbf3bcaf, (int)0xfd5b4f79); + rc[4] = _mm_set_epi32((int)0xcbcfb0cb, (int)0x4872448b, (int)0x79eecd1c, (int)0xbe397044); + rc[5] = _mm_set_epi32((int)0x7eeacdee, (int)0x6e9032b7, (int)0x8d5335ed, (int)0x2b8a057b); + rc[6] = _mm_set_epi32((int)0x67c28f43, (int)0x5e2e7cd0, (int)0xe2412761, (int)0xda4fef1b); + rc[7] = _mm_set_epi32((int)0x2924d9b0, (int)0xafcacc07, (int)0x675ffde2, (int)0x1fc70b3b); + rc[8] = _mm_set_epi32((int)0xab4d63f1, (int)0xe6867fe9, (int)0xecdb8fca, (int)0xb9d465ee); + rc[9] = _mm_set_epi32((int)0x1c30bf84, (int)0xd4b7cd64, (int)0x5b2a404f, (int)0xad037e33); rc[10] = _mm_set_epi32((int)0xb2cc0bb9, (int)0x941723bf, (int)0x69028b2e, (int)0x8df69800); rc[11] = _mm_set_epi32((int)0xfa0478a6, (int)0xde6f5572, (int)0x4aaa9ec8, (int)0x5c9d2d8a); rc[12] = _mm_set_epi32((int)0xdfb49f2b, (int)0x6b772a12, (int)0x0efa4f2e, (int)0x29129fd4); @@ -111,77 +113,65 @@ static void load_haraka_constants(u128 rc[40]) { rc[39] = _mm_set_epi32((int)0x756acc03, (int)0x02288288, (int)0x4ad6bdfd, (int)0xe9c59da1); } -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_tweak_constants( - harakactx *state, - const unsigned char *pk_seed, const unsigned char *sk_seed, - unsigned long long seed_length) { +void tweak_constants(spx_ctx *ctx) { int i; unsigned char buf[40 * 16]; /* Use the standard constants to generate tweaked ones. */ - load_haraka_constants(state->rc); - - /* Constants for sk.seed */ - if (sk_seed != NULL) { - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_haraka_S(buf, 40 * 16, sk_seed, seed_length, state); - /* Tweak constants with the pub_seed */ - for (i = 0; i < 40; i++) { - state->rc_sseed[i] = LOAD(buf + i * 16); - } - } + load_haraka_constants(ctx->rc); /* Constants for pk.seed */ - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_haraka_S(buf, 40 * 16, pk_seed, seed_length, state); + haraka_S(buf, 40 * 16, ctx->pub_seed, SPX_N, ctx); /* Tweak constants with the pub_seed */ for (i = 0; i < 40; i++) { - state->rc[i] = LOAD(buf + i * 16); + ctx->rc[i] = LOAD(buf + i * 16); } } -static void haraka_S_absorb(unsigned char *s, +static void haraka_S_absorb(unsigned char *s, unsigned int r, const unsigned char *m, unsigned long long mlen, - unsigned char p, - const harakactx *state) { + unsigned char p, const spx_ctx *ctx) { unsigned long long i; - unsigned char t[HARAKAS_RATE]; + PQCLEAN_VLA(unsigned char, t, r); - while (mlen >= HARAKAS_RATE) { + while (mlen >= r) { // XOR block to state STORE(s, XOR128(LOAD(s), LOAD(m))); STORE(s + 16, XOR128(LOAD(s + 16), LOAD(m + 16))); - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_haraka512_perm(s, s, state); - mlen -= HARAKAS_RATE; - m += HARAKAS_RATE; + haraka512_perm(s, s, ctx); + mlen -= r; + m += r; } - for (i = 0; i < HARAKAS_RATE; ++i) { + for (i = 0; i < r; ++i) { t[i] = 0; } for (i = 0; i < mlen; ++i) { t[i] = m[i]; } t[i] = p; - t[HARAKAS_RATE - 1] |= 128; + t[r - 1] |= 128; STORE(s, XOR128(LOAD(s), LOAD(t))); STORE(s + 16, XOR128(LOAD(s + 16), LOAD(t + 16))); } static void haraka_S_absorb4x(unsigned char *s, + unsigned int r, const unsigned char *m0, const unsigned char *m1, const unsigned char *m2, const unsigned char *m3, unsigned long long int mlen, unsigned char p, - const harakactx *state) { + const spx_ctx *ctx) { unsigned long long i; - unsigned char t0[HARAKAS_RATE]; - unsigned char t1[HARAKAS_RATE]; - unsigned char t2[HARAKAS_RATE]; - unsigned char t3[HARAKAS_RATE]; + PQCLEAN_VLA(unsigned char, t0, r); + PQCLEAN_VLA(unsigned char, t1, r); + PQCLEAN_VLA(unsigned char, t2, r); + PQCLEAN_VLA(unsigned char, t3, r); - while (mlen >= HARAKAS_RATE) { + while (mlen >= r) { // XOR block to state STORE(s, XOR128(LOAD(s), LOAD(m0))); STORE(s + 16, XOR128(LOAD(s + 16), LOAD(m0 + 16))); @@ -192,15 +182,15 @@ static void haraka_S_absorb4x(unsigned char *s, STORE(s + 192, XOR128(LOAD(s + 192), LOAD(m3))); STORE(s + 208, XOR128(LOAD(s + 208), LOAD(m3 + 16))); - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_haraka512_perm_x4(s, s, state); - mlen -= HARAKAS_RATE; - m0 += HARAKAS_RATE; - m1 += HARAKAS_RATE; - m2 += HARAKAS_RATE; - m3 += HARAKAS_RATE; + haraka512_perm_x4(s, s, ctx); + mlen -= r; + m0 += r; + m1 += r; + m2 += r; + m3 += r; } - for (i = 0; i < HARAKAS_RATE; ++i) { + for (i = 0; i < r; ++i) { t0[i] = 0; t1[i] = 0; t2[i] = 0; @@ -218,10 +208,10 @@ static void haraka_S_absorb4x(unsigned char *s, t2[i] = p; t3[i] = p; - t0[HARAKAS_RATE - 1] |= 128; - t1[HARAKAS_RATE - 1] |= 128; - t2[HARAKAS_RATE - 1] |= 128; - t3[HARAKAS_RATE - 1] |= 128; + t0[r - 1] |= 128; + t1[r - 1] |= 128; + t2[r - 1] |= 128; + t3[r - 1] |= 128; STORE(s, XOR128(LOAD(s), LOAD(t0))); STORE(s + 16, XOR128(LOAD(s + 16), LOAD(t0 + 16))); @@ -234,9 +224,10 @@ static void haraka_S_absorb4x(unsigned char *s, } static void haraka_S_squeezeblocks(unsigned char *h, unsigned long long nblocks, - unsigned char *s, unsigned int r, const harakactx *state) { + unsigned char *s, unsigned int r, + const spx_ctx *ctx) { while (nblocks > 0) { - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_haraka512_perm(s, s, state); + haraka512_perm(s, s, ctx); STORE(h, LOAD(s)); STORE(h + 16, LOAD(s + 16)); h += r; @@ -251,9 +242,9 @@ static void haraka_S_squeezeblocks4x(unsigned char *h0, unsigned long long nblocks, unsigned char *s, unsigned int r, - const harakactx *state) { + const spx_ctx *ctx) { while (nblocks > 0) { - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_haraka512_perm_x4(s, s, state); + haraka512_perm_x4(s, s, ctx); STORE(h0, LOAD(s)); STORE(h0 + 16, LOAD(s + 16)); STORE(h1, LOAD(s + 64)); @@ -270,7 +261,7 @@ static void haraka_S_squeezeblocks4x(unsigned char *h0, } } -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_haraka_S_inc_init(uint8_t *s_inc) { +void haraka_S_inc_init(uint8_t *s_inc) { size_t i; for (i = 0; i < 64; i++) { @@ -279,7 +270,8 @@ void PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_haraka_S_inc_init(uint8_t *s_inc) { s_inc[64] = 0; } -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, const harakactx *state) { +void haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, + const spx_ctx *ctx) { size_t i; /* Recall that s_inc[64] is the non-absorbed bytes xored into the state */ @@ -293,16 +285,16 @@ void PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_haraka_S_inc_absorb(uint8_t *s_inc, c m += HARAKAS_RATE - s_inc[64]; s_inc[64] = 0; - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_haraka512_perm(s_inc, s_inc, state); + haraka512_perm(s_inc, s_inc, ctx); } for (i = 0; i < mlen; i++) { s_inc[s_inc[64] + i] ^= m[i]; } - s_inc[64] = (uint8_t)(s_inc[64] + mlen); + s_inc[64] += (uint8_t)mlen; } -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_haraka_S_inc_finalize(uint8_t *s_inc) { +void haraka_S_inc_finalize(uint8_t *s_inc) { /* After haraka_S_inc_absorb, we are guaranteed that s_inc[64] < HARAKAS_RATE, so we can always use one more byte for p in the current state. */ s_inc[s_inc[64]] ^= 0x1F; @@ -310,22 +302,23 @@ void PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_haraka_S_inc_finalize(uint8_t *s_inc) s_inc[64] = 0; } -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, const harakactx *state) { +void haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, + const spx_ctx *ctx) { size_t i; /* First consume any bytes we still have sitting around */ for (i = 0; i < outlen && i < s_inc[64]; i++) { /* There are s_inc[64] bytes left, so r - s_inc[64] is the first available byte. We consume from there, i.e., up to r. */ - out[i] = (uint8_t)s_inc[(HARAKAS_RATE - s_inc[64] + (uint8_t)i)]; + out[i] = (uint8_t)s_inc[(HARAKAS_RATE - s_inc[64] + i)]; } out += i; outlen -= i; - s_inc[64] = (uint8_t)(s_inc[64] - i); + s_inc[64] -= (uint8_t)i; /* Then squeeze the remaining necessary blocks */ while (outlen > 0) { - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_haraka512_perm(s_inc, s_inc, state); + haraka512_perm(s_inc, s_inc, ctx); for (i = 0; i < outlen && i < HARAKAS_RATE; i++) { out[i] = s_inc[i]; @@ -336,8 +329,9 @@ void PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_haraka_S_inc_squeeze(uint8_t *out, si } } -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_haraka_S(unsigned char *out, unsigned long long outlen, - const unsigned char *in, unsigned long long inlen, const harakactx *state) { +void haraka_S(unsigned char *out, unsigned long long outlen, + const unsigned char *in, unsigned long long inlen, + const spx_ctx *ctx) { unsigned long long i; unsigned char s[64]; unsigned char d[32]; @@ -345,30 +339,30 @@ void PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_haraka_S(unsigned char *out, unsigned for (i = 0; i < 64; i++) { s[i] = 0; } - haraka_S_absorb(s, in, inlen, 0x1F, state); + haraka_S_absorb(s, HARAKAS_RATE, in, inlen, 0x1F, ctx); - haraka_S_squeezeblocks(out, outlen / HARAKAS_RATE, s, HARAKAS_RATE, state); + haraka_S_squeezeblocks(out, outlen / HARAKAS_RATE, s, HARAKAS_RATE, ctx); out += (outlen / HARAKAS_RATE) * HARAKAS_RATE; if (outlen % HARAKAS_RATE) { - haraka_S_squeezeblocks(d, 1, s, HARAKAS_RATE, state); + haraka_S_squeezeblocks(d, 1, s, HARAKAS_RATE, ctx); for (i = 0; i < outlen % HARAKAS_RATE; i++) { out[i] = d[i]; } } } -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_haraka_Sx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned long long outlen, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - unsigned long long inlen, - const harakactx *state) { +void haraka_Sx4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned long long outlen, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + unsigned long long inlen, + const spx_ctx *ctx) { unsigned long long i; unsigned char s[64 * 4]; unsigned char d0[32]; @@ -379,16 +373,17 @@ void PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_haraka_Sx4(unsigned char *out0, for (i = 0; i < 64 * 4; i++) { s[i] = 0; } - haraka_S_absorb4x(s, in0, in1, in2, in3, inlen, 0x1F, state); + haraka_S_absorb4x(s, HARAKAS_RATE, in0, in1, in2, in3, inlen, 0x1F, ctx); - haraka_S_squeezeblocks4x(out0, out1, out2, out3, outlen / HARAKAS_RATE, s, HARAKAS_RATE, state); + haraka_S_squeezeblocks4x(out0, out1, out2, out3, outlen / HARAKAS_RATE, s, + HARAKAS_RATE, ctx); out0 += (outlen / HARAKAS_RATE) * HARAKAS_RATE; out1 += (outlen / HARAKAS_RATE) * HARAKAS_RATE; out2 += (outlen / HARAKAS_RATE) * HARAKAS_RATE; out3 += (outlen / HARAKAS_RATE) * HARAKAS_RATE; if (outlen % HARAKAS_RATE) { - haraka_S_squeezeblocks4x(d0, d1, d2, d3, 1, s, HARAKAS_RATE, state); + haraka_S_squeezeblocks4x(d0, d1, d2, d3, 1, s, HARAKAS_RATE, ctx); for (i = 0; i < outlen % HARAKAS_RATE; i++) { out0[i] = d0[i]; out1[i] = d1[i]; @@ -398,7 +393,8 @@ void PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_haraka_Sx4(unsigned char *out0, } } -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_haraka512_perm(unsigned char *out, const unsigned char *in, const harakactx *state) { +void haraka512_perm(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx) { u128 s[4], tmp; s[0] = LOAD(in); @@ -406,19 +402,19 @@ void PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_haraka512_perm(unsigned char *out, co s[2] = LOAD(in + 32); s[3] = LOAD(in + 48); - AES4(s[0], s[1], s[2], s[3], state->rc); + AES4(s[0], s[1], s[2], s[3], ctx->rc); MIX4(s[0], s[1], s[2], s[3]); - AES4(s[0], s[1], s[2], s[3], state->rc + 8); + AES4(s[0], s[1], s[2], s[3], ctx->rc + 8); MIX4(s[0], s[1], s[2], s[3]); - AES4(s[0], s[1], s[2], s[3], state->rc + 16); + AES4(s[0], s[1], s[2], s[3], ctx->rc + 16); MIX4(s[0], s[1], s[2], s[3]); - AES4(s[0], s[1], s[2], s[3], state->rc + 24); + AES4(s[0], s[1], s[2], s[3], ctx->rc + 24); MIX4(s[0], s[1], s[2], s[3]); - AES4(s[0], s[1], s[2], s[3], state->rc + 32); + AES4(s[0], s[1], s[2], s[3], ctx->rc + 32); MIX4(s[0], s[1], s[2], s[3]); STORE(out, s[0]); @@ -427,7 +423,8 @@ void PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_haraka512_perm(unsigned char *out, co STORE(out + 48, s[3]); } -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_haraka512_perm_x4(unsigned char *out, const unsigned char *in, const harakactx *state) { +void haraka512_perm_x4(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx) { u128 s[4][4], tmp; s[0][0] = LOAD(in); @@ -447,31 +444,31 @@ void PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_haraka512_perm_x4(unsigned char *out, s[3][2] = LOAD(in + 224); s[3][3] = LOAD(in + 240); - AES4_4x(s[0], s[1], s[2], s[3], state->rc); + AES4_4x(s[0], s[1], s[2], s[3], ctx->rc); MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - AES4_4x(s[0], s[1], s[2], s[3], state->rc + 8); + AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 8); MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - AES4_4x(s[0], s[1], s[2], s[3], state->rc + 16); + AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 16); MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - AES4_4x(s[0], s[1], s[2], s[3], state->rc + 24); + AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 24); MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - AES4_4x(s[0], s[1], s[2], s[3], state->rc + 32); + AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 32); MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); @@ -495,7 +492,8 @@ void PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_haraka512_perm_x4(unsigned char *out, STORE(out + 240, s[3][3]); } -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_haraka512(unsigned char *out, const unsigned char *in, const harakactx *state) { +void haraka512(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx) { u128 s[4], tmp; s[0] = LOAD(in); @@ -503,19 +501,19 @@ void PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_haraka512(unsigned char *out, const u s[2] = LOAD(in + 32); s[3] = LOAD(in + 48); - AES4(s[0], s[1], s[2], s[3], state->rc); + AES4(s[0], s[1], s[2], s[3], ctx->rc); MIX4(s[0], s[1], s[2], s[3]); - AES4(s[0], s[1], s[2], s[3], state->rc + 8); + AES4(s[0], s[1], s[2], s[3], ctx->rc + 8); MIX4(s[0], s[1], s[2], s[3]); - AES4(s[0], s[1], s[2], s[3], state->rc + 16); + AES4(s[0], s[1], s[2], s[3], ctx->rc + 16); MIX4(s[0], s[1], s[2], s[3]); - AES4(s[0], s[1], s[2], s[3], state->rc + 24); + AES4(s[0], s[1], s[2], s[3], ctx->rc + 24); MIX4(s[0], s[1], s[2], s[3]); - AES4(s[0], s[1], s[2], s[3], state->rc + 32); + AES4(s[0], s[1], s[2], s[3], ctx->rc + 32); MIX4(s[0], s[1], s[2], s[3]); s[0] = XOR128(s[0], LOAD(in)); @@ -527,7 +525,8 @@ void PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_haraka512(unsigned char *out, const u TRUNCSTORE(out, s[0], s[1], s[2], s[3]); } -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_haraka512x4(unsigned char *out, const unsigned char *in, const harakactx *state) { +void haraka512x4(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx) { u128 s[4][4], tmp; s[0][0] = LOAD(in); @@ -547,31 +546,31 @@ void PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_haraka512x4(unsigned char *out, const s[3][2] = LOAD(in + 224); s[3][3] = LOAD(in + 240); - AES4_4x(s[0], s[1], s[2], s[3], state->rc); + AES4_4x(s[0], s[1], s[2], s[3], ctx->rc); MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - AES4_4x(s[0], s[1], s[2], s[3], state->rc + 8); + AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 8); MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - AES4_4x(s[0], s[1], s[2], s[3], state->rc + 16); + AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 16); MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - AES4_4x(s[0], s[1], s[2], s[3], state->rc + 24); + AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 24); MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - AES4_4x(s[0], s[1], s[2], s[3], state->rc + 32); + AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 32); MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); @@ -600,25 +599,26 @@ void PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_haraka512x4(unsigned char *out, const TRUNCSTORE((out + 96), s[3][0], s[3][1], s[3][2], s[3][3]); } -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_haraka256(unsigned char *out, const unsigned char *in, const harakactx *state) { +void haraka256(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx) { u128 s[2], tmp; s[0] = LOAD(in); s[1] = LOAD(in + 16); - AES2(s[0], s[1], state->rc); + AES2(s[0], s[1], ctx->rc); MIX2(s[0], s[1]); - AES2(s[0], s[1], state->rc + 4); + AES2(s[0], s[1], ctx->rc + 4); MIX2(s[0], s[1]); - AES2(s[0], s[1], state->rc + 8); + AES2(s[0], s[1], ctx->rc + 8); MIX2(s[0], s[1]); - AES2(s[0], s[1], state->rc + 12); + AES2(s[0], s[1], ctx->rc + 12); MIX2(s[0], s[1]); - AES2(s[0], s[1], state->rc + 16); + AES2(s[0], s[1], ctx->rc + 16); MIX2(s[0], s[1]); s[0] = XOR128(s[0], LOAD(in)); @@ -628,7 +628,8 @@ void PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_haraka256(unsigned char *out, const u STORE(out + 16, s[1]); } -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_haraka256x4(unsigned char *out, const unsigned char *in, const harakactx *state) { +void haraka256x4(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx) { u128 s[4][2], tmp; s[0][0] = LOAD(in); @@ -641,7 +642,7 @@ void PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_haraka256x4(unsigned char *out, const s[3][1] = LOAD(in + 112); // Round 1 - AES2_4x(s[0], s[1], s[2], s[3], state->rc); + AES2_4x(s[0], s[1], s[2], s[3], ctx->rc); MIX2(s[0][0], s[0][1]); MIX2(s[1][0], s[1][1]); @@ -649,7 +650,7 @@ void PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_haraka256x4(unsigned char *out, const MIX2(s[3][0], s[3][1]); // Round 2 - AES2_4x(s[0], s[1], s[2], s[3], state->rc + 4); + AES2_4x(s[0], s[1], s[2], s[3], ctx->rc + 4); MIX2(s[0][0], s[0][1]); MIX2(s[1][0], s[1][1]); @@ -657,7 +658,7 @@ void PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_haraka256x4(unsigned char *out, const MIX2(s[3][0], s[3][1]); // Round 3 - AES2_4x(s[0], s[1], s[2], s[3], state->rc + 8); + AES2_4x(s[0], s[1], s[2], s[3], ctx->rc + 8); MIX2(s[0][0], s[0][1]); MIX2(s[1][0], s[1][1]); @@ -665,7 +666,7 @@ void PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_haraka256x4(unsigned char *out, const MIX2(s[3][0], s[3][1]); // Round 4 - AES2_4x(s[0], s[1], s[2], s[3], state->rc + 12); + AES2_4x(s[0], s[1], s[2], s[3], ctx->rc + 12); MIX2(s[0][0], s[0][1]); MIX2(s[1][0], s[1][1]); @@ -673,7 +674,7 @@ void PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_haraka256x4(unsigned char *out, const MIX2(s[3][0], s[3][1]); // Round 5 - AES2_4x(s[0], s[1], s[2], s[3], state->rc + 16); + AES2_4x(s[0], s[1], s[2], s[3], ctx->rc + 16); MIX2(s[0][0], s[0][1]); MIX2(s[1][0], s[1][1]); @@ -699,103 +700,3 @@ void PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_haraka256x4(unsigned char *out, const STORE(out + 96, s[3][0]); STORE(out + 112, s[3][1]); } - -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_haraka256_sk(unsigned char *out, const unsigned char *in, const harakactx *state) { - u128 s[2], tmp; - - s[0] = LOAD(in); - s[1] = LOAD(in + 16); - - AES2(s[0], s[1], state->rc_sseed); - MIX2(s[0], s[1]); - - AES2(s[0], s[1], state->rc_sseed + 4); - MIX2(s[0], s[1]); - - AES2(s[0], s[1], state->rc_sseed + 8); - MIX2(s[0], s[1]); - - AES2(s[0], s[1], state->rc_sseed + 12); - MIX2(s[0], s[1]); - - AES2(s[0], s[1], state->rc_sseed + 16); - MIX2(s[0], s[1]); - - s[0] = XOR128(s[0], LOAD(in)); - s[1] = XOR128(s[1], LOAD(in + 16)); - - STORE(out, s[0]); - STORE(out + 16, s[1]); -} - -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_haraka256_skx4(unsigned char *out, const unsigned char *in, const harakactx *state) { - u128 s[4][2], tmp; - - s[0][0] = LOAD(in); - s[0][1] = LOAD(in + 16); - s[1][0] = LOAD(in + 32); - s[1][1] = LOAD(in + 48); - s[2][0] = LOAD(in + 64); - s[2][1] = LOAD(in + 80); - s[3][0] = LOAD(in + 96); - s[3][1] = LOAD(in + 112); - - // Round 1 - AES2_4x(s[0], s[1], s[2], s[3], state->rc_sseed); - - MIX2(s[0][0], s[0][1]); - MIX2(s[1][0], s[1][1]); - MIX2(s[2][0], s[2][1]); - MIX2(s[3][0], s[3][1]); - - // Round 2 - AES2_4x(s[0], s[1], s[2], s[3], state->rc_sseed + 4); - - MIX2(s[0][0], s[0][1]); - MIX2(s[1][0], s[1][1]); - MIX2(s[2][0], s[2][1]); - MIX2(s[3][0], s[3][1]); - - // Round 3 - AES2_4x(s[0], s[1], s[2], s[3], state->rc_sseed + 8); - - MIX2(s[0][0], s[0][1]); - MIX2(s[1][0], s[1][1]); - MIX2(s[2][0], s[2][1]); - MIX2(s[3][0], s[3][1]); - - // Round 4 - AES2_4x(s[0], s[1], s[2], s[3], state->rc_sseed + 12); - - MIX2(s[0][0], s[0][1]); - MIX2(s[1][0], s[1][1]); - MIX2(s[2][0], s[2][1]); - MIX2(s[3][0], s[3][1]); - - // Round 5 - AES2_4x(s[0], s[1], s[2], s[3], state->rc_sseed + 16); - - MIX2(s[0][0], s[0][1]); - MIX2(s[1][0], s[1][1]); - MIX2(s[2][0], s[2][1]); - MIX2(s[3][0], s[3][1]); - - // Feed Forward - s[0][0] = XOR128(s[0][0], LOAD(in)); - s[0][1] = XOR128(s[0][1], LOAD(in + 16)); - s[1][0] = XOR128(s[1][0], LOAD(in + 32)); - s[1][1] = XOR128(s[1][1], LOAD(in + 48)); - s[2][0] = XOR128(s[2][0], LOAD(in + 64)); - s[2][1] = XOR128(s[2][1], LOAD(in + 80)); - s[3][0] = XOR128(s[3][0], LOAD(in + 96)); - s[3][1] = XOR128(s[3][1], LOAD(in + 112)); - - STORE(out, s[0][0]); - STORE(out + 16, s[0][1]); - STORE(out + 32, s[1][0]); - STORE(out + 48, s[1][1]); - STORE(out + 64, s[2][0]); - STORE(out + 80, s[2][1]); - STORE(out + 96, s[3][0]); - STORE(out + 112, s[3][1]); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/haraka.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/haraka.h index 5ff3f7de08..737cb6065f 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/haraka.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/haraka.h @@ -1,57 +1,42 @@ -#ifndef PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_HARAKA_H -#define PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_HARAKA_H +#ifndef SPX_HARAKA_H +#define SPX_HARAKA_H -#include -#include -#include - -typedef struct { - __m128i rc[40]; - __m128i rc_sseed[40]; -} harakactx; +#include "context.h" +#include "params.h" /* Tweak constants with seed */ -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_tweak_constants( - harakactx *state, - const unsigned char *pk_seed, const unsigned char *sk_seed, - unsigned long long seed_length); +#define tweak_constants SPX_NAMESPACE(tweak_constants) +void tweak_constants(spx_ctx *ctx); /* Haraka Sponge */ -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_haraka_S_inc_init(uint8_t *s_inc); -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, const harakactx *state); -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_haraka_S_inc_finalize(uint8_t *s_inc); -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, const harakactx *state); -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_haraka_S( - unsigned char *out, unsigned long long outlen, - const unsigned char *in, unsigned long long inlen, const harakactx *state); -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_haraka_Sx4( - unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned long long outlen, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - unsigned long long inlen, - const harakactx *state); - +#define haraka_S_inc_init SPX_NAMESPACE(haraka_S_inc_init) +void haraka_S_inc_init(uint8_t *s_inc); +#define haraka_S_inc_absorb SPX_NAMESPACE(haraka_S_inc_absorb) +void haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, + const spx_ctx *ctx); +#define haraka_S_inc_finalize SPX_NAMESPACE(haraka_S_inc_finalize) +void haraka_S_inc_finalize(uint8_t *s_inc); +#define haraka_S_inc_squeeze SPX_NAMESPACE(haraka_S_inc_squeeze) +void haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, + const spx_ctx *ctx); +#define haraka_S SPX_NAMESPACE(haraka_S) +void haraka_S(unsigned char *out, unsigned long long outlen, + const unsigned char *in, unsigned long long inlen, + const spx_ctx *ctx); /* Applies the 512-bit Haraka permutation to in. */ -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_haraka512_perm(unsigned char *out, const unsigned char *in, const harakactx *state); -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_haraka512_perm_x4(unsigned char *out, const unsigned char *in, const harakactx *state); +#define haraka512_perm SPX_NAMESPACE(haraka512_perm) +void haraka512_perm(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx); /* Implementation of Haraka-512 */ -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_haraka512(unsigned char *out, const unsigned char *in, const harakactx *state); -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_haraka512x4(unsigned char *out, const unsigned char *in, const harakactx *state); +#define haraka512 SPX_NAMESPACE(haraka512) +void haraka512(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx); /* Implementation of Haraka-256 */ -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_haraka256(unsigned char *out, const unsigned char *in, const harakactx *state); -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_haraka256x4(unsigned char *out, const unsigned char *in, const harakactx *state); - -/* Implementation of Haraka-256 using sk.seed constants */ -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_haraka256_sk(unsigned char *out, const unsigned char *in, const harakactx *state); -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_haraka256_skx4(unsigned char *out, const unsigned char *in, const harakactx *state); +#define haraka256 SPX_NAMESPACE(haraka256) +void haraka256(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/haraka_offsets.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/haraka_offsets.h new file mode 100644 index 0000000000..7c062272a0 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/haraka_offsets.h @@ -0,0 +1,21 @@ +#ifndef HARAKA_OFFSETS_H_ +#define HARAKA_OFFSETS_H_ + +/* + * Offsets of various fields in the address structure when we use Haraka as + * the Sphincs+ hash function + */ + +#define SPX_OFFSET_LAYER 3 /* The byte used to specify the Merkle tree layer */ +#define SPX_OFFSET_TREE 8 /* The start of the 8 byte field used to specify the tree */ +#define SPX_OFFSET_TYPE 19 /* The byte used to specify the hash type (reason) */ +#define SPX_OFFSET_KP_ADDR2 22 /* The high byte used to specify the key pair (which one-time signature) */ +#define SPX_OFFSET_KP_ADDR1 23 /* The low byte used to specify the key pair */ +#define SPX_OFFSET_CHAIN_ADDR 27 /* The byte used to specify the chain address (which Winternitz chain) */ +#define SPX_OFFSET_HASH_ADDR 31 /* The byte used to specify the hash address (where in the Winternitz chain) */ +#define SPX_OFFSET_TREE_HGT 27 /* The byte used to specify the height of this node in the FORS or Merkle tree */ +#define SPX_OFFSET_TREE_INDEX 28 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ + +#define SPX_HARAKA 1 + +#endif /* HARAKA_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/harakax4.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/harakax4.h new file mode 100644 index 0000000000..eadc69aa48 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/harakax4.h @@ -0,0 +1,36 @@ +#ifndef SPX_HARAKAX4_H +#define SPX_HARAKAX4_H + +#include "context.h" +#include "params.h" + +/* Haraka Sponge */ +#define haraka_Sx4 SPX_NAMESPACE(haraka_Sx4) +void haraka_Sx4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned long long outlen, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + unsigned long long inlen, + const spx_ctx *ctx); + +/* Applies the 512-bit Haraka permutation x4 to in. */ +#define haraka512_perm_x4 SPX_NAMESPACE(haraka512_perm_x4) +void haraka512_perm_x4(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx); + +/* Implementation of Haraka-512 x4*/ +#define haraka512x4 SPX_NAMESPACE(haraka512x4) +void haraka512x4(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx); + +/* Implementation of Haraka-256 x4 */ +#define haraka256x4 SPX_NAMESPACE(haraka256x4) +void haraka256x4(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/hash.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/hash.h index 842f54a190..f7c87d4c3c 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/hash.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/hash.h @@ -1,31 +1,28 @@ -#ifndef PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_HASH_H -#define PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_HASH_H - -#include "hash_state.h" +#ifndef SPX_HASH_H +#define SPX_HASH_H #include #include -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_initialize_hash_function( - hash_state *hash_state_seeded, - const unsigned char *pub_seed, const unsigned char *sk_seed); +#include "context.h" +#include "params.h" + +#define prf_addr SPX_NAMESPACE(prf_addr) +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]); -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_destroy_hash_function(hash_state *hash_state_seeded); +#define gen_message_random SPX_NAMESPACE(gen_message_random) +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded); +#define hash_message SPX_NAMESPACE(hash_message) +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/hash_haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/hash_haraka.c index ba3f3a4675..750a67423b 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/hash_haraka.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/hash_haraka.c @@ -2,58 +2,44 @@ #include #include "address.h" -#include "haraka.h" -#include "hash.h" #include "params.h" #include "utils.h" -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_initialize_hash_function( - hash_state *hash_state_seeded, - const unsigned char *pub_seed, const unsigned char *sk_seed) { - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_tweak_constants(hash_state_seeded, pub_seed, sk_seed, PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N); -} - -/* The haraka implementation is stack based and won't be replaced in PQClean/OQS, - so we don't need to do anything */ -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_destroy_hash_function( - hash_state *hash_state_seeded) { // NOLINT(readability-non-const-parameter) - (void)hash_state_seeded; -} +#include "haraka.h" +#include "hash.h" /* - * Computes PRF(key, addr), given a secret key of PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N bytes and an address + * Computes PRF(key, addr), given a secret key of SPX_N bytes and an address */ -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded) { - unsigned char buf[PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_ADDR_BYTES]; - /* Since PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N may be smaller than 32, we need a temporary buffer. */ +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]) { + /* Since SPX_N may be smaller than 32, we need temporary buffers. */ unsigned char outbuf[32]; + unsigned char buf[64] = {0}; - (void)key; /* Suppress an 'unused parameter' warning. */ + memcpy(buf, addr, SPX_ADDR_BYTES); + memcpy(buf + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_addr_to_bytes(buf, addr); - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_haraka256_sk(outbuf, buf, hash_state_seeded); - memcpy(out, outbuf, PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N); + haraka512(outbuf, (const void *)buf, ctx); + memcpy(out, outbuf, SPX_N); } /** * Computes the message-dependent randomness R, using a secret seed and an * optional randomization value as well as the message. */ -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded) { +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { uint8_t s_inc[65]; - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_haraka_S_inc_init(s_inc); - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_haraka_S_inc_absorb(s_inc, sk_prf, PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_haraka_S_inc_absorb(s_inc, optrand, PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_haraka_S_inc_absorb(s_inc, m, mlen, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_haraka_S_inc_finalize(s_inc); - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_haraka_S_inc_squeeze(R, PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N, s_inc, hash_state_seeded); + haraka_S_inc_init(s_inc); + haraka_S_inc_absorb(s_inc, sk_prf, SPX_N, ctx); + haraka_S_inc_absorb(s_inc, optrand, SPX_N, ctx); + haraka_S_inc_absorb(s_inc, m, mlen, ctx); + haraka_S_inc_finalize(s_inc); + haraka_S_inc_squeeze(R, SPX_N, s_inc, ctx); } /** @@ -61,36 +47,35 @@ void PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_gen_message_random( * Outputs the message digest and the index of the leaf. The index is split in * the tree index and the leaf index, for convenient copying to an address. */ -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded) { -#define PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_TREE_BITS (PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_TREE_HEIGHT * (PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_D - 1)) -#define PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_TREE_BYTES ((PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_TREE_BITS + 7) / 8) -#define PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_LEAF_BITS PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_TREE_HEIGHT -#define PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_LEAF_BYTES ((PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_LEAF_BITS + 7) / 8) -#define PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_DGST_BYTES (PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_FORS_MSG_BYTES + PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_TREE_BYTES + PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_LEAF_BYTES) +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { +#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) +#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) +#define SPX_LEAF_BITS SPX_TREE_HEIGHT +#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) +#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) - unsigned char buf[PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_DGST_BYTES]; + unsigned char buf[SPX_DGST_BYTES]; unsigned char *bufp = buf; uint8_t s_inc[65]; - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_haraka_S_inc_init(s_inc); - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_haraka_S_inc_absorb(s_inc, R, PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_haraka_S_inc_absorb(s_inc, pk + PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N, PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_haraka_S_inc_absorb(s_inc, m, mlen, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_haraka_S_inc_finalize(s_inc); - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_haraka_S_inc_squeeze(buf, PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_DGST_BYTES, s_inc, hash_state_seeded); + haraka_S_inc_init(s_inc); + haraka_S_inc_absorb(s_inc, R, SPX_N, ctx); + haraka_S_inc_absorb(s_inc, pk + SPX_N, SPX_N, ctx); // Only absorb root part of pk + haraka_S_inc_absorb(s_inc, m, mlen, ctx); + haraka_S_inc_finalize(s_inc); + haraka_S_inc_squeeze(buf, SPX_DGST_BYTES, s_inc, ctx); + + memcpy(digest, bufp, SPX_FORS_MSG_BYTES); + bufp += SPX_FORS_MSG_BYTES; - memcpy(digest, bufp, PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_FORS_MSG_BYTES); - bufp += PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_FORS_MSG_BYTES; - *tree = PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_bytes_to_ull(bufp, PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_TREE_BYTES); - *tree &= (~(uint64_t)0) >> (64 - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_TREE_BITS); - bufp += PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_TREE_BYTES; + *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); + *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); + bufp += SPX_TREE_BYTES; - *leaf_idx = (uint32_t)PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_bytes_to_ull( - bufp, PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_LEAF_BYTES); - *leaf_idx &= (~(uint32_t)0) >> (32 - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_LEAF_BITS); + *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); + *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/hash_harakax4.c b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/hash_harakax4.c index 38c2c2a9e0..cfa5162d79 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/hash_harakax4.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/hash_harakax4.c @@ -2,36 +2,34 @@ #include #include "address.h" -#include "haraka.h" -#include "hash_state.h" +#include "harakax4.h" #include "hashx4.h" #include "params.h" /* * 4-way parallel version of prf_addr; takes 4x as much input and output */ -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_prf_addrx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const unsigned char *key, - const uint32_t addrx4[4 * 8], - const hash_state *state_seeded) { - unsigned char bufx4[4 * PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_ADDR_BYTES]; - /* Since PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N may be smaller than 32, we need a temporary buffer. */ +#define prf_addrx4 SPX_NAMESPACE(prf_addrx4) +void prf_addrx4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const spx_ctx *ctx, + const uint32_t addrx4[4 * 8]) { + unsigned char bufx4[4 * 64] = {0}; + /* Since SPX_N may be smaller than 32, we need temporary buffers. */ unsigned char outbuf[4 * 32]; unsigned int i; - (void)key; /* Suppress an 'unused parameter' warning. */ - for (i = 0; i < 4; i++) { - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_addr_to_bytes(bufx4 + i * PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_ADDR_BYTES, addrx4 + i * 8); + memcpy(bufx4 + i * 64, addrx4 + i * 8, SPX_ADDR_BYTES); + memcpy(bufx4 + i * 64 + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); } - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_haraka256_skx4(outbuf, bufx4, state_seeded); + haraka512x4(outbuf, bufx4, ctx); - memcpy(out0, outbuf, PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N); - memcpy(out1, outbuf + 32, PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N); - memcpy(out2, outbuf + 64, PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N); - memcpy(out3, outbuf + 96, PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N); + memcpy(out0, outbuf, SPX_N); + memcpy(out1, outbuf + 32, SPX_N); + memcpy(out2, outbuf + 64, SPX_N); + memcpy(out3, outbuf + 96, SPX_N); } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/hash_state.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/hash_state.h deleted file mode 100644 index 5dd7bb1453..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/hash_state.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_HASH_STATE_H -#define PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_HASH_STATE_H - -/** - * Defines the type of the hash function state. - * - * Don't be fooled into thinking this instance of SPHINCS+ isn't stateless! - * - * From Section 7.2.2 from the SPHINCS+ round-2 specification: - * - * Each of the instances of the tweakable hash function take PK.seed as its - * first input, which is constant for a given key pair – and, thus, across - * a single signature. This leads to a lot of redundant computation. To remedy - * this, we pad PK.seed to the length of a full 64-byte SHA-256 input block. - * Because of the Merkle-DamgÃ¥rd construction that underlies SHA-256, this - * allows for reuse of the intermediate SHA-256 state after the initial call to - * the compression function which improves performance. - * - * We pass this hash state around in functions, because otherwise we need to - * have a global variable. - */ - -#include "haraka.h" -#define hash_state harakactx - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/hashx4.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/hashx4.h index 1afb5848b1..3751a0ebd0 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/hashx4.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/hashx4.h @@ -1,16 +1,17 @@ -#ifndef PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_HASHX4_H -#define PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_HASHX4_H +#ifndef SPX_HASHX4_H +#define SPX_HASHX4_H #include -#include "hash_state.h" +#include "context.h" +#include "params.h" -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_prf_addrx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const unsigned char *key, - const uint32_t addrx4[4 * 8], - const hash_state *state_seeded); +#define prf_addrx4 SPX_NAMESPACE(prf_addrx4) +void prf_addrx4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const spx_ctx *ctx, + const uint32_t addrx4[4 * 8]); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/merkle.c b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/merkle.c new file mode 100644 index 0000000000..f57811c1ac --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/merkle.c @@ -0,0 +1,64 @@ +#include +#include + +#include "merkle.h" + +#include "address.h" +#include "params.h" +#include "utils.h" +#include "utilsx4.h" +#include "wots.h" +#include "wotsx4.h" + +/* + * This generates a Merkle signature (WOTS signature followed by the Merkle + * authentication path). + */ +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf) { + unsigned char *auth_path = sig + SPX_WOTS_BYTES; + uint32_t tree_addrx4[4 * 8] = { 0 }; + int j; + struct leaf_info_x4 info = { 0 }; + unsigned steps[ SPX_WOTS_LEN ]; + + info.wots_sig = sig; + chain_lengths(steps, root); + info.wots_steps = steps; + + for (j = 0; j < 4; j++) { + set_type(&tree_addrx4[8 * j], SPX_ADDR_TYPE_HASHTREE); + set_type(&info.leaf_addr[8 * j], SPX_ADDR_TYPE_WOTS); + set_type(&info.pk_addr[8 * j], SPX_ADDR_TYPE_WOTSPK); + copy_subtree_addr(&tree_addrx4[8 * j], tree_addr); + copy_subtree_addr(&info.leaf_addr[8 * j], wots_addr); + copy_subtree_addr(&info.pk_addr[8 * j], wots_addr); + } + + info.wots_sign_leaf = idx_leaf; + + treehashx4(root, auth_path, ctx, + idx_leaf, 0, + SPX_TREE_HEIGHT, + wots_gen_leafx4, + tree_addrx4, &info); +} + +/* Compute root node of the top-most subtree. */ +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { + /* We do not need the auth path in key generation, but it simplifies the + code to have just one treehash routine that computes both root and path + in one function. */ + unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; + uint32_t top_tree_addr[8] = {0}; + uint32_t wots_addr[8] = {0}; + + set_layer_addr(top_tree_addr, SPX_D - 1); + set_layer_addr(wots_addr, SPX_D - 1); + + merkle_sign(auth_path, root, ctx, + wots_addr, top_tree_addr, + ~0U /* ~0 means "don't bother generating an auth path */ ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/merkle.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/merkle.h new file mode 100644 index 0000000000..769cf2e970 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/merkle.h @@ -0,0 +1,21 @@ +#ifndef MERKLE_H_ +#define MERKLE_H_ + +#include + +#include "context.h" +#include "params.h" + +/* Generate a Merkle signature (WOTS signature followed by the Merkle */ +/* authentication path) */ +#define merkle_sign SPX_NAMESPACE(merkle_sign) +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf); + +/* Compute the root node of the top-most subtree. */ +#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); + +#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/nistapi.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/nistapi.h new file mode 100644 index 0000000000..3cb71afad4 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/nistapi.h @@ -0,0 +1,87 @@ +#ifndef SPX_API_H +#define SPX_API_H + +#include +#include + +#include "params.h" + +#define CRYPTO_ALGNAME "SPHINCS+" + +#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES +#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES +#define CRYPTO_BYTES SPX_BYTES +#define CRYPTO_SEEDBYTES (3*SPX_N) + +/* + * Returns the length of a secret key, in bytes + */ +#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) +size_t crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) +size_t crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) +size_t crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) +size_t crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +#define crypto_sign SPX_NAMESPACE(crypto_sign) +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/params.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/params.h index f1863ed346..916a7b09f6 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/params.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/params.h @@ -1,53 +1,56 @@ -#ifndef PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_PARAMS_H -#define PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_PARAMS_H +#ifndef SPX_PARAMS_H +#define SPX_PARAMS_H + +#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_##s /* Hash output length in bytes. */ -#define PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N 24 +#define SPX_N 24 /* Height of the hypertree. */ -#define PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_FULL_HEIGHT 66 +#define SPX_FULL_HEIGHT 66 /* Number of subtree layer. */ -#define PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_D 22 +#define SPX_D 22 /* FORS tree dimensions. */ -#define PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_FORS_HEIGHT 8 -#define PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_FORS_TREES 33 +#define SPX_FORS_HEIGHT 8 +#define SPX_FORS_TREES 33 /* Winternitz parameter, */ -#define PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_WOTS_W 16 +#define SPX_WOTS_W 16 /* The hash function is defined by linking a different hash.c file, as opposed to setting a #define constant. */ /* For clarity */ -#define PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_ADDR_BYTES 32 +#define SPX_ADDR_BYTES 32 /* WOTS parameters. */ -#define PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_WOTS_LOGW 4 +#define SPX_WOTS_LOGW 4 -#define PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_WOTS_LEN1 (8 * PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N / PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_WOTS_LOGW) +#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) -/* PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#define PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_WOTS_LEN2 3 +/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ +#define SPX_WOTS_LEN2 3 -#define PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_WOTS_LEN (PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_WOTS_LEN1 + PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_WOTS_LEN2) -#define PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_WOTS_BYTES (PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_WOTS_LEN * PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N) -#define PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_WOTS_PK_BYTES PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_WOTS_BYTES +#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) +#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) +#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES /* Subtree size. */ -#define PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_TREE_HEIGHT (PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_FULL_HEIGHT / PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_D) +#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) + +//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT +// #error SPX_D should always divide SPX_FULL_HEIGHT +//#endif /* FORS parameters. */ -#define PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_FORS_MSG_BYTES ((PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_FORS_TREES + 7) / 8) -#define PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_FORS_BYTES ((PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_FORS_HEIGHT + 1) * PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_FORS_TREES * PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N) -#define PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_FORS_PK_BYTES PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N +#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) +#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) +#define SPX_FORS_PK_BYTES SPX_N /* Resulting SPX sizes. */ -#define PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_BYTES (PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N + PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_FORS_BYTES + PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_D * PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_WOTS_BYTES +\ - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_FULL_HEIGHT * PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N) -#define PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_PK_BYTES (2 * PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N) -#define PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_SK_BYTES (2 * PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N + PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_PK_BYTES) - -/* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ -#define PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_OPTRAND_BYTES 32 +#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ + SPX_FULL_HEIGHT * SPX_N) +#define SPX_PK_BYTES (2 * SPX_N) +#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) + +#include "haraka_offsets.h" #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/sign.c b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/sign.c index 9d4e48ab5f..9d0c7d1b22 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/sign.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/sign.c @@ -1,76 +1,45 @@ -#include #include #include #include #include "address.h" -#include "api.h" +#include "context.h" #include "fors.h" #include "hash.h" -#include "hash_state.h" +#include "merkle.h" +#include "nistapi.h" #include "params.h" #include "randombytes.h" #include "thash.h" #include "utils.h" #include "wots.h" - -/** - * Computes the leaf at a given address. First generates the WOTS key pair, - * then computes leaf by hashing horizontally. - */ -static void wots_gen_leaf(unsigned char *leaf, const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx, const uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - unsigned char pk[PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_WOTS_BYTES]; - uint32_t wots_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_set_type( - wots_addr, PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_set_type( - wots_pk_addr, PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_ADDR_TYPE_WOTSPK); - - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_set_keypair_addr( - wots_addr, addr_idx); - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_wots_gen_pk( - pk, sk_seed, pub_seed, wots_addr, hash_state_seeded); - - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_copy_keypair_addr( - wots_pk_addr, wots_addr); - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_thash_WOTS_LEN( - leaf, pk, pub_seed, wots_pk_addr, hash_state_seeded); -} - /* * Returns the length of a secret key, in bytes */ -size_t PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_crypto_sign_secretkeybytes(void) { - return PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_CRYPTO_SECRETKEYBYTES; +size_t crypto_sign_secretkeybytes(void) { + return CRYPTO_SECRETKEYBYTES; } /* * Returns the length of a public key, in bytes */ -size_t PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_crypto_sign_publickeybytes(void) { - return PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_CRYPTO_PUBLICKEYBYTES; +size_t crypto_sign_publickeybytes(void) { + return CRYPTO_PUBLICKEYBYTES; } /* * Returns the length of a signature, in bytes */ -size_t PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_crypto_sign_bytes(void) { - return PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_CRYPTO_BYTES; +size_t crypto_sign_bytes(void) { + return CRYPTO_BYTES; } /* * Returns the length of the seed required to generate a key pair, in bytes */ -size_t PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_crypto_sign_seedbytes(void) { - return PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_CRYPTO_SEEDBYTES; +size_t crypto_sign_seedbytes(void) { + return CRYPTO_SEEDBYTES; } /* @@ -78,35 +47,29 @@ size_t PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_crypto_sign_seedbytes(void) { * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] * Format pk: [PUB_SEED || root] */ -int PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed) { - /* We do not need the auth path in key generation, but it simplifies the - code to have just one treehash routine that computes both root and path - in one function. */ - unsigned char auth_path[PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_TREE_HEIGHT * PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N]; - uint32_t top_tree_addr[8] = {0}; - hash_state hash_state_seeded; - - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_set_layer_addr( - top_tree_addr, PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_D - 1); - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_set_type( - top_tree_addr, PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_ADDR_TYPE_HASHTREE); +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed) { + spx_ctx ctx; /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ - memcpy(sk, seed, PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_CRYPTO_SEEDBYTES); + memcpy(sk, seed, CRYPTO_SEEDBYTES); + + memcpy(pk, sk + 2 * SPX_N, SPX_N); - memcpy(pk, sk + 2 * PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N, PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N); + memcpy(ctx.pub_seed, pk, SPX_N); + memcpy(ctx.sk_seed, sk, SPX_N); /* This hook allows the hash function instantiation to do whatever preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_initialize_hash_function(&hash_state_seeded, pk, sk); + initialize_hash_function(&ctx); /* Compute root node of the top-most subtree. */ - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_treehash_TREE_HEIGHT( - sk + 3 * PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N, auth_path, sk, sk + 2 * PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N, 0, 0, - wots_gen_leaf, top_tree_addr, &hash_state_seeded); + merkle_gen_root(sk + 3 * SPX_N, &ctx); - memcpy(pk + PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N, sk + 3 * PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N, PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N); + // cleanup + free_hash_function(&ctx); + + memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); return 0; } @@ -116,31 +79,10 @@ int PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_crypto_sign_seed_keypair( * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] * Format pk: [PUB_SEED || root] */ -int PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk) { - - // guarantee alignment of pk - union { - __m128 _x[PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_CRYPTO_PUBLICKEYBYTES / 16]; - uint8_t pk[PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_CRYPTO_PUBLICKEYBYTES]; - } aligned_pk; - - // guarantee alignment of sk - union { - __m128 _x[PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_CRYPTO_SECRETKEYBYTES / 16]; - uint8_t sk[PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_CRYPTO_SECRETKEYBYTES]; - } aligned_sk; - - union { - __m128 _x[PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_CRYPTO_SEEDBYTES / 16]; - uint8_t seed[PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_CRYPTO_SEEDBYTES]; - } aligned_seed; - randombytes(aligned_seed.seed, PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_CRYPTO_SEEDBYTES); - - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_crypto_sign_seed_keypair( - aligned_pk.pk, aligned_sk.sk, aligned_seed.seed); - memcpy(pk, aligned_pk.pk, PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_CRYPTO_PUBLICKEYBYTES); - memcpy(sk, aligned_sk.sk, PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_CRYPTO_SECRETKEYBYTES); +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { + uint8_t seed[CRYPTO_SEEDBYTES]; + randombytes(seed, CRYPTO_SEEDBYTES); + crypto_sign_seed_keypair(pk, sk, seed); return 0; } @@ -148,101 +90,68 @@ int PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_crypto_sign_keypair( /** * Returns an array containing a detached signature. */ -int PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - // guarantee alignment of sk - union { - __m128 *_x; - uint8_t sk[PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_CRYPTO_SECRETKEYBYTES]; - } aligned_sk; - memcpy(aligned_sk.sk, sk, PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_CRYPTO_SECRETKEYBYTES); - sk = aligned_sk.sk; - - // guarantee alignment of sig - union { - __m128 *_x; - uint8_t sig[PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_BYTES]; - } aligned_sig; - uint8_t *orig_sig = sig; - sig = (uint8_t *)aligned_sig.sig; - - const unsigned char *sk_seed = sk; - const unsigned char *sk_prf = sk + PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N; - const unsigned char *pk = sk + 2 * PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N; - const unsigned char *pub_seed = pk; - - unsigned char optrand[PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N]; - unsigned char mhash[PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_FORS_MSG_BYTES]; - unsigned char root[PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N]; +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk) { + spx_ctx ctx; + + const uint8_t *sk_prf = sk + SPX_N; + const uint8_t *pk = sk + 2 * SPX_N; + + uint8_t optrand[SPX_N]; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t root[SPX_N]; uint32_t i; uint64_t tree; uint32_t idx_leaf; uint32_t wots_addr[8] = {0}; uint32_t tree_addr[8] = {0}; - hash_state hash_state_seeded; + memcpy(ctx.sk_seed, sk, SPX_N); + memcpy(ctx.pub_seed, pk, SPX_N); /* This hook allows the hash function instantiation to do whatever preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_initialize_hash_function( - &hash_state_seeded, - pub_seed, sk_seed); + initialize_hash_function(&ctx); - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_set_type( - wots_addr, PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_set_type( - tree_addr, PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_ADDR_TYPE_HASHTREE); + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); /* Optionally, signing can be made non-deterministic using optrand. This can help counter side-channel attacks that would benefit from getting a large number of traces when the signer uses the same nodes. */ - randombytes(optrand, PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N); + randombytes(optrand, SPX_N); /* Compute the digest randomization value. */ - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_gen_message_random( - sig, sk_prf, optrand, m, mlen, &hash_state_seeded); + gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); /* Derive the message digest and leaf index from R, PK and M. */ - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N; + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_set_keypair_addr( - wots_addr, idx_leaf); + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); /* Sign the message hash using FORS. */ - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_fors_sign( - sig, root, mhash, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_FORS_BYTES; - - for (i = 0; i < PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_D; i++) { - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_set_tree_addr(tree_addr, tree); - - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_set_keypair_addr( - wots_addr, idx_leaf); - - /* Compute a WOTS signature. */ - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_wots_sign( - sig, root, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_WOTS_BYTES; - - /* Compute the authentication path for the used WOTS leaf. */ - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_treehash_TREE_HEIGHT( - root, sig, sk_seed, pub_seed, idx_leaf, 0, - wots_gen_leaf, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_TREE_HEIGHT * PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N; + fors_sign(sig, root, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); + sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_TREE_HEIGHT; + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; } - memcpy(orig_sig, aligned_sig.sig, PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_BYTES); - *siglen = PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_BYTES; + free_hash_function(&ctx); + + *siglen = SPX_BYTES; return 0; } @@ -250,23 +159,14 @@ int PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_crypto_sign_signature( /** * Verifies a detached signature and message under a given public key. */ -int PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk) { - // guarantee alignment of pk - union { - __m128 *_x; - uint8_t pk[PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_CRYPTO_PUBLICKEYBYTES]; - } aligned_pk; - memcpy(aligned_pk.pk, pk, PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_CRYPTO_PUBLICKEYBYTES); - pk = aligned_pk.pk; - - const unsigned char *pub_seed = pk; - const unsigned char *pub_root = pk + PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N; - unsigned char mhash[PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_FORS_MSG_BYTES]; - unsigned char wots_pk[PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_WOTS_BYTES]; - unsigned char root[PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N]; - unsigned char leaf[PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N]; +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk) { + spx_ctx ctx; + const uint8_t *pub_root = pk + SPX_N; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t wots_pk[SPX_WOTS_BYTES]; + uint8_t root[SPX_N]; + uint8_t leaf[SPX_N]; unsigned int i; uint64_t tree; uint32_t idx_leaf; @@ -274,77 +174,66 @@ int PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_crypto_sign_verify( uint32_t tree_addr[8] = {0}; uint32_t wots_pk_addr[8] = {0}; - hash_state hash_state_seeded; - - if (siglen != PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_BYTES) { + if (siglen != SPX_BYTES) { return -1; } + memcpy(ctx.pub_seed, pk, SPX_N); + /* This hook allows the hash function instantiation to do whatever preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_initialize_hash_function( - &hash_state_seeded, - pub_seed, NULL); + initialize_hash_function(&ctx); - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_set_type( - wots_addr, PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_set_type( - tree_addr, PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_ADDR_TYPE_HASHTREE); - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_set_type( - wots_pk_addr, PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_ADDR_TYPE_WOTSPK); + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); /* Derive the message digest and leaf index from R || PK || M. */ - /* The additional PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N is a result of the hash domain separator. */ - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N; + /* The additional SPX_N is a result of the hash domain separator. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; /* Layer correctly defaults to 0, so no need to set_layer_addr */ - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_set_keypair_addr( - wots_addr, idx_leaf); + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_fors_pk_from_sig( - root, sig, mhash, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_FORS_BYTES; + fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; /* For each subtree.. */ - for (i = 0; i < PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_D; i++) { - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_set_tree_addr(tree_addr, tree); + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_set_keypair_addr( - wots_addr, idx_leaf); + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_copy_keypair_addr( - wots_pk_addr, wots_addr); + copy_keypair_addr(wots_pk_addr, wots_addr); /* The WOTS public key is only correct if the signature was correct. */ /* Initially, root is the FORS pk, but on subsequent iterations it is the root of the subtree below the currently processed subtree. */ - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_wots_pk_from_sig( - wots_pk, sig, root, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_WOTS_BYTES; + wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); + sig += SPX_WOTS_BYTES; /* Compute the leaf node using the WOTS public key. */ - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_thash_WOTS_LEN( - leaf, wots_pk, pub_seed, wots_pk_addr, &hash_state_seeded); + thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); /* Compute the root node of this subtree. */ - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_compute_root( - root, leaf, idx_leaf, 0, sig, PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_TREE_HEIGHT, - pub_seed, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_TREE_HEIGHT * PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N; + compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, + &ctx, tree_addr); + sig += SPX_TREE_HEIGHT * SPX_N; /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_TREE_HEIGHT; + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; } + // cleanup + free_hash_function(&ctx); + /* Check if the root node equals the root node in the public key. */ - if (memcmp(root, pub_root, PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N) != 0) { + if (memcmp(root, pub_root, SPX_N) != 0) { return -1; } @@ -355,15 +244,14 @@ int PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_crypto_sign_verify( /** * Returns an array containing the signature followed by the message. */ -int PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk) { size_t siglen; - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_crypto_sign_signature( - sm, &siglen, m, mlen, sk); + crypto_sign_signature(sm, &siglen, m, mlen, sk); - memmove(sm + PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_BYTES, m, mlen); + memmove(sm + SPX_BYTES, m, mlen); *smlen = siglen + mlen; return 0; @@ -372,38 +260,27 @@ int PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_crypto_sign( /** * Verifies a given signature-message pair under a given public key. */ -int PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk) { - - // guarantee alignment of pk - union { - __m128 *_x; - uint8_t pk[PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_CRYPTO_PUBLICKEYBYTES]; - } aligned_pk; - memcpy(aligned_pk.pk, pk, PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_CRYPTO_PUBLICKEYBYTES); - pk = aligned_pk.pk; - - +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk) { /* The API caller does not necessarily know what size a signature should be - but SPHINCS+ signatures are always exactly PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_BYTES. */ - if (smlen < PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_BYTES) { + but SPHINCS+ signatures are always exactly SPX_BYTES. */ + if (smlen < SPX_BYTES) { memset(m, 0, smlen); *mlen = 0; return -1; } - *mlen = smlen - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_BYTES; + *mlen = smlen - SPX_BYTES; - if (PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_crypto_sign_verify( - sm, PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_BYTES, sm + PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_BYTES, *mlen, pk)) { + if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { memset(m, 0, smlen); *mlen = 0; return -1; } /* If verification was successful, move the message to the right place. */ - memmove(m, sm + PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_BYTES, *mlen); + memmove(m, sm + SPX_BYTES, *mlen); return 0; } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/thash.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/thash.h index b9e3f7f5b5..8687ccfb4d 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/thash.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/thash.h @@ -1,28 +1,13 @@ -#ifndef PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_THASH_H -#define PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_THASH_H +#ifndef SPX_THASH_H +#define SPX_THASH_H -#include "hash_state.h" +#include "context.h" +#include "params.h" #include -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); +#define thash SPX_NAMESPACE(thash) +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/thash_haraka_simple.c b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/thash_haraka_simple.c index b84c8d1652..207777bf8d 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/thash_haraka_simple.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/thash_haraka_simple.c @@ -4,80 +4,33 @@ #include "address.h" #include "params.h" #include "thash.h" +#include "utils.h" #include "haraka.h" /** - * Takes an array of inblocks concatenated arrays of PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N bytes. + * Takes an array of inblocks concatenated arrays of SPX_N bytes. */ -static void PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_thash( - unsigned char *out, unsigned char *buf, - const unsigned char *in, unsigned int inblocks, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]) { + PQCLEAN_VLA(uint8_t, buf, SPX_ADDR_BYTES + inblocks * SPX_N); unsigned char outbuf[32]; unsigned char buf_tmp[64]; - (void)pub_seed; /* Suppress an 'unused parameter' warning. */ - if (inblocks == 1) { /* F function */ - /* Since PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N may be smaller than 32, we need a temporary buffer. */ + /* Since SPX_N may be smaller than 32, we need a temporary buffer. */ memset(buf_tmp, 0, 64); - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_addr_to_bytes(buf_tmp, addr); - memcpy(buf_tmp + PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_ADDR_BYTES, in, PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N); + memcpy(buf_tmp, addr, 32); + memcpy(buf_tmp + SPX_ADDR_BYTES, in, SPX_N); - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_haraka512(outbuf, buf_tmp, hash_state_seeded); - memcpy(out, outbuf, PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N); + haraka512(outbuf, buf_tmp, ctx); + memcpy(out, outbuf, SPX_N); } else { /* All other tweakable hashes*/ - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_addr_to_bytes(buf, addr); - memcpy(buf + PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_ADDR_BYTES, in, inblocks * PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N); + memcpy(buf, addr, 32); + memcpy(buf + SPX_ADDR_BYTES, in, inblocks * SPX_N); - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_haraka_S( - out, PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N, buf, PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N, hash_state_seeded); + haraka_S(out, SPX_N, buf, SPX_ADDR_BYTES + inblocks * SPX_N, ctx); } } - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_ADDR_BYTES + 1 * PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N]; - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_thash( - out, buf, in, 1, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_ADDR_BYTES + 2 * PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N]; - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_thash( - out, buf, in, 2, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_ADDR_BYTES + PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_WOTS_LEN * PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N]; - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_thash( - out, buf, in, PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_WOTS_LEN, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_ADDR_BYTES + PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_FORS_TREES * PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N]; - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_thash( - out, buf, in, PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_FORS_TREES, pub_seed, addr, hash_state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/thash_haraka_simplex4.c b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/thash_haraka_simplex4.c index e2e53c6114..2ee763d7d9 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/thash_haraka_simplex4.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/thash_haraka_simplex4.c @@ -2,65 +2,66 @@ #include #include "address.h" -#include "haraka.h" #include "params.h" #include "thashx4.h" +#include "harakax4.h" + +#include "utils.h" + /** * 4-way parallel version of thash; takes 4x as much input and output */ -#define thashx4_variant(name, inblocks) \ - void PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_thashx4_##name(unsigned char *out0, unsigned char *out1, unsigned char *out2, \ - unsigned char *out3, const unsigned char *in0, \ - const unsigned char *in1, const unsigned char *in2, \ - const unsigned char *in3, const unsigned char *pub_seed, \ - uint32_t addrx4[4 * 8], const harakactx *state) { \ - unsigned char buf0[PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_ADDR_BYTES + (inblocks)*PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N]; \ - unsigned char buf1[PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_ADDR_BYTES + (inblocks)*PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N]; \ - unsigned char buf2[PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_ADDR_BYTES + (inblocks)*PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N]; \ - unsigned char buf3[PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_ADDR_BYTES + (inblocks)*PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N]; \ - unsigned char outbuf[32 * 4]; \ - unsigned char buf_tmp[64 * 4]; \ - \ - (void)pub_seed; /* Suppress an 'unused parameter' warning. */ \ - \ - if ((inblocks) == 1) { \ - memset(buf_tmp, 0, 64 * 4); \ - \ - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_addr_to_bytes(buf_tmp, addrx4 + 0 * 8); \ - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_addr_to_bytes(buf_tmp + 64, addrx4 + 1 * 8); \ - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_addr_to_bytes(buf_tmp + 128, addrx4 + 2 * 8); \ - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_addr_to_bytes(buf_tmp + 192, addrx4 + 3 * 8); \ - \ - memcpy(buf_tmp + PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_ADDR_BYTES, in0, PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N); \ - memcpy(buf_tmp + PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_ADDR_BYTES + 64, in1, PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N); \ - memcpy(buf_tmp + PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_ADDR_BYTES + 128, in2, PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N); \ - memcpy(buf_tmp + PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_ADDR_BYTES + 192, in3, PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N); \ - \ - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_haraka512x4(outbuf, buf_tmp, state); \ - \ - memcpy(out0, outbuf, PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N); \ - memcpy(out1, outbuf + 32, PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N); \ - memcpy(out2, outbuf + 64, PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N); \ - memcpy(out3, outbuf + 96, PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N); \ - } else { \ - /* All other tweakable hashes*/ \ - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_addr_to_bytes(buf0, addrx4 + 0 * 8); \ - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_addr_to_bytes(buf1, addrx4 + 1 * 8); \ - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_addr_to_bytes(buf2, addrx4 + 2 * 8); \ - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_addr_to_bytes(buf3, addrx4 + 3 * 8); \ - \ - memcpy(buf0 + PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_ADDR_BYTES, in0, (inblocks)*PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N); \ - memcpy(buf1 + PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_ADDR_BYTES, in1, (inblocks)*PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N); \ - memcpy(buf2 + PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_ADDR_BYTES, in2, (inblocks)*PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N); \ - memcpy(buf3 + PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_ADDR_BYTES, in3, (inblocks)*PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N); \ - \ - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_haraka_Sx4(out0, out1, out2, out3, PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N, buf0, buf1, buf2, buf3, \ - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_ADDR_BYTES + (inblocks)*PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N, state); \ - } \ - } +#define thashx4 SPX_NAMESPACE(thashx4) +void thashx4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addrx4[4 * 8]) { + PQCLEAN_VLA(unsigned char, buf0, SPX_ADDR_BYTES + inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, buf1, SPX_ADDR_BYTES + inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, buf2, SPX_ADDR_BYTES + inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, buf3, SPX_ADDR_BYTES + inblocks * SPX_N); + unsigned char outbuf[32 * 4]; + unsigned char buf_tmp[64 * 4]; + + if (inblocks == 1) { + memset(buf_tmp, 0, 64 * 4); + + memcpy(buf_tmp, addrx4 + 0 * 8, 32); + memcpy(buf_tmp + 64, addrx4 + 1 * 8, 32); + memcpy(buf_tmp + 128, addrx4 + 2 * 8, 32); + memcpy(buf_tmp + 192, addrx4 + 3 * 8, 32); -thashx4_variant(1, 1) -thashx4_variant(2, 2) -thashx4_variant(WOTS_LEN, PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_WOTS_LEN) -thashx4_variant(FORS_TREES, PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_FORS_TREES) + memcpy(buf_tmp + SPX_ADDR_BYTES, in0, SPX_N); + memcpy(buf_tmp + SPX_ADDR_BYTES + 64, in1, SPX_N); + memcpy(buf_tmp + SPX_ADDR_BYTES + 128, in2, SPX_N); + memcpy(buf_tmp + SPX_ADDR_BYTES + 192, in3, SPX_N); + + haraka512x4(outbuf, buf_tmp, ctx); + + memcpy(out0, outbuf, SPX_N); + memcpy(out1, outbuf + 32, SPX_N); + memcpy(out2, outbuf + 64, SPX_N); + memcpy(out3, outbuf + 96, SPX_N); + } else { + /* All other tweakable hashes*/ + memcpy(buf0, addrx4 + 0 * 8, 32); + memcpy(buf1, addrx4 + 1 * 8, 32); + memcpy(buf2, addrx4 + 2 * 8, 32); + memcpy(buf3, addrx4 + 3 * 8, 32); + + memcpy(buf0 + SPX_ADDR_BYTES, in0, inblocks * SPX_N); + memcpy(buf1 + SPX_ADDR_BYTES, in1, inblocks * SPX_N); + memcpy(buf2 + SPX_ADDR_BYTES, in2, inblocks * SPX_N); + memcpy(buf3 + SPX_ADDR_BYTES, in3, inblocks * SPX_N); + + haraka_Sx4(out0, out1, out2, out3, SPX_N, + buf0, buf1, buf2, buf3, SPX_ADDR_BYTES + inblocks * SPX_N, + ctx); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/thashx4.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/thashx4.h index efe575a631..64798a3727 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/thashx4.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/thashx4.h @@ -1,25 +1,20 @@ -#ifndef PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_THASHX4_H -#define PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_THASHX4_H +#ifndef SPX_THASHX4_H +#define SPX_THASHX4_H #include -#include "hash_state.h" +#include "context.h" +#include "params.h" -#define thashx4_header(inblocks) \ - void PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_thashx4_##inblocks(unsigned char *out0, \ - unsigned char *out1, \ - unsigned char *out2, \ - unsigned char *out3, \ - const unsigned char *in0, \ - const unsigned char *in1, \ - const unsigned char *in2, \ - const unsigned char *in3, \ - const unsigned char *pub_seed, uint32_t addrx4[4*8], \ - const hash_state *state_seeded) - -thashx4_header(1); -thashx4_header(2); -thashx4_header(WOTS_LEN); -thashx4_header(FORS_TREES); +#define thashx4 SPX_NAMESPACE(thashx4) +void thashx4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addrx4[4 * 8]); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/utils.c b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/utils.c index 4381d53d4d..177b541fb9 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/utils.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/utils.c @@ -1,34 +1,41 @@ -#include #include +#include "utils.h" + #include "address.h" #include "hash.h" -#include "hash_state.h" #include "params.h" #include "thash.h" -#include "utils.h" /** * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. */ -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in) { +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in) { + int i; /* Iterate over out in decreasing order, for big-endianness. */ - for (size_t i = outlen; i > 0; i--) { - out[i - 1] = in & 0xff; + for (i = (signed int)outlen - 1; i >= 0; i--) { + out[i] = in & 0xff; in = in >> 8; } } +void u32_to_bytes(unsigned char *out, uint32_t in) { + out[0] = (unsigned char)(in >> 24); + out[1] = (unsigned char)(in >> 16); + out[2] = (unsigned char)(in >> 8); + out[3] = (unsigned char)in; +} + /** * Converts the inlen bytes in 'in' from big-endian byte order to an integer. */ -unsigned long long PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_bytes_to_ull( - const unsigned char *in, size_t inlen) { +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { unsigned long long retval = 0; + unsigned int i; - for (size_t i = 0; i < inlen; i++) { + for (i = 0; i < inlen; i++) { retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); } return retval; @@ -38,94 +45,80 @@ unsigned long long PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_bytes_to_ull( * Computes a root node given a leaf and an auth path. * Expects address to be complete other than the tree_height and tree_index. */ -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]) { uint32_t i; - unsigned char buffer[2 * PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N]; + unsigned char buffer[2 * SPX_N]; /* If leaf_idx is odd (last bit = 1), current path element is a right child and auth_path has to go left. Otherwise it is the other way around. */ if (leaf_idx & 1) { - memcpy(buffer + PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N, leaf, PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N); + memcpy(buffer + SPX_N, leaf, SPX_N); + memcpy(buffer, auth_path, SPX_N); } else { - memcpy(buffer, leaf, PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N); - memcpy(buffer + PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N, auth_path, PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N); + memcpy(buffer, leaf, SPX_N); + memcpy(buffer + SPX_N, auth_path, SPX_N); } - auth_path += PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N; + auth_path += SPX_N; for (i = 0; i < tree_height - 1; i++) { leaf_idx >>= 1; idx_offset >>= 1; /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_set_tree_height(addr, i + 1); - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_set_tree_index( - addr, leaf_idx + idx_offset); + set_tree_height(addr, i + 1); + set_tree_index(addr, leaf_idx + idx_offset); /* Pick the right or left neighbor, depending on parity of the node. */ if (leaf_idx & 1) { - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_thash_2( - buffer + PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N); + thash(buffer + SPX_N, buffer, 2, ctx, addr); + memcpy(buffer, auth_path, SPX_N); } else { - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_thash_2( - buffer, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer + PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N, auth_path, PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N); + thash(buffer, buffer, 2, ctx, addr); + memcpy(buffer + SPX_N, auth_path, SPX_N); } - auth_path += PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N; + auth_path += SPX_N; } /* The last iteration is exceptional; we do not copy an auth_path node. */ leaf_idx >>= 1; idx_offset >>= 1; - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_set_tree_height(addr, tree_height); - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_set_tree_index( - addr, leaf_idx + idx_offset); - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_thash_2( - root, buffer, pub_seed, addr, hash_state_seeded); + set_tree_height(addr, tree_height); + set_tree_index(addr, leaf_idx + idx_offset); + thash(root, buffer, 2, ctx, addr); } /** * For a given leaf index, computes the authentication path and the resulting * root node using Merkle's TreeHash algorithm. * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_ADDR_TYPE_FORSTREE). + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). * Applies the offset idx_offset to indices before building addresses, so that * it is possible to continue counting indices across trees. */ -static void PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_treehash( - unsigned char *root, unsigned char *auth_path, - unsigned char *stack, unsigned int *heights, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - +void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx * /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]) { + PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); + PQCLEAN_VLA(unsigned int, heights, tree_height + 1); unsigned int offset = 0; uint32_t idx; uint32_t tree_idx; for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { /* Add the next leaf node to the stack. */ - gen_leaf(stack + offset * PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N, - sk_seed, pub_seed, idx + idx_offset, tree_addr, - hash_state_seeded); + gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); offset++; heights[offset - 1] = 0; /* If this is a node we need for the auth path.. */ if ((leaf_idx ^ 0x1) == idx) { - memcpy(auth_path, stack + (offset - 1)*PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N, PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N); + memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); } /* While the top-most nodes are of equal height.. */ @@ -134,66 +127,22 @@ static void PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_treehash( tree_idx = (idx >> (heights[offset - 1] + 1)); /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_set_tree_height( - tree_addr, heights[offset - 1] + 1); - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_set_tree_index( - tree_addr, tree_idx + (idx_offset >> (heights[offset - 1] + 1))); + set_tree_height(tree_addr, heights[offset - 1] + 1); + set_tree_index(tree_addr, + tree_idx + (idx_offset >> (heights[offset - 1] + 1))); /* Hash the top-most nodes from the stack together. */ - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_thash_2( - stack + (offset - 2)*PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N, stack + (offset - 2)*PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N, - pub_seed, tree_addr, hash_state_seeded); + thash(stack + (offset - 2)*SPX_N, + stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); offset--; /* Note that the top-most node is now one layer higher. */ heights[offset - 1]++; /* If this is a node we need for the auth path.. */ if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_path + heights[offset - 1]*PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N, - stack + (offset - 1)*PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N, PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N); + memcpy(auth_path + heights[offset - 1]*SPX_N, + stack + (offset - 1)*SPX_N, SPX_N); } } } - memcpy(root, stack, PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N); -} - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_FORS_HEIGHT + 1)*PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N]; - unsigned int heights[PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_FORS_HEIGHT + 1]; - - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_FORS_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_TREE_HEIGHT + 1)*PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N]; - unsigned int heights[PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_TREE_HEIGHT + 1]; - - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_TREE_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); + memcpy(root, stack, SPX_N); } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/utils.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/utils.h index a60cae019c..64f5d5a53a 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/utils.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/utils.h @@ -1,64 +1,58 @@ -#ifndef PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_UTILS_H -#define PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_UTILS_H +#ifndef SPX_UTILS_H +#define SPX_UTILS_H -#include "hash_state.h" -#include "params.h" -#include #include +#include "compat.h" +#include "context.h" +#include "params.h" + + +/* To support MSVC use alloca() instead of VLAs. See #20. */ + + /** * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. */ -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in); +#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in); +#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) +void u32_to_bytes(unsigned char *out, uint32_t in); /** * Converts the inlen bytes in 'in' from big-endian byte order to an integer. */ -unsigned long long PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_bytes_to_ull( - const unsigned char *in, size_t inlen); +#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); /** * Computes a root node given a leaf and an auth path. * Expects address to be complete other than the tree_height and tree_index. */ -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); +#define compute_root SPX_NAMESPACE(compute_root) +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]); /** * For a given leaf index, computes the authentication path and the resulting * root node using Merkle's TreeHash algorithm. * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_ADDR_TYPE_FORSTREE). + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). * Applies the offset idx_offset to indices before building addresses, so that * it is possible to continue counting indices across trees. */ -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); +#define treehash SPX_NAMESPACE(treehash) +void treehash(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx *ctx /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]); -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/utilsx4.c b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/utilsx4.c index 2d63e028d3..1638677194 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/utilsx4.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/utilsx4.c @@ -1,98 +1,138 @@ +#include + +#include "utilsx4.h" + #include "address.h" #include "params.h" #include "thashx4.h" #include "utils.h" -#include "utilsx4.h" -#include - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. +/* + * Generate the entire Merkle tree, computing the authentication path for leaf_idx, + * and the resulting root node using Merkle's TreeHash algorithm. * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_ADDR_TYPE_FORSTREE). + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) + * + * This expects tree_addrx4 to be initialized to 4 parallel addr structures for + * the Merkle tree nodes + * * Applies the offset idx_offset to indices before building addresses, so that * it is possible to continue counting indices across trees. + * + * This works by using the standard Merkle tree building algorithm, except + * that each 'node' tracked is actually 4 consecutive nodes in the real tree. + * When we combine two logical nodes ABCD and WXYZ, we perform the H + * operation on adjacent real nodes, forming the parent logical node + * (AB)(CD)(WX)(YZ) + * + * When we get to the top two levels of the real tree (where there is only + * one logical node), we continue this operation two more times; the right + * most real node will by the actual root (and the other 3 nodes will be + * garbage). We follow the same thashx4 logic so that the 'extract + * authentication path components' part of the loop is still executed (and + * to simplify the code somewhat) + * + * This currently assumes tree_height >= 2; I suspect that doing an adjusting + * idx, addr_idx on the gen_leafx4 call if tree_height < 2 would fix it; since + * we don't actually use such short trees, I haven't bothered */ -#define treehashx4_variant(name, tree_height) \ - void PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_treehashx4_##name( \ - unsigned char *rootx4, unsigned char *auth_pathx4, const unsigned char *sk_seed, \ - const unsigned char *pub_seed, const uint32_t leaf_idx[4], uint32_t idx_offset[4], \ - void (*gen_leafx4)(unsigned char * /* leaf0 */, unsigned char * /* leaf1 */, \ - unsigned char * /* leaf2 */, unsigned char * /* leaf3 */, \ - const unsigned char * /* sk_seed */, \ - const unsigned char * /* pub_seed */, uint32_t /* addr_idx0 */, \ - uint32_t /* addr_idx1 */, uint32_t /* addr_idx2 */, \ - uint32_t /* addr_idx3 */, const uint32_t[8] /* tree_addr */, \ - const hash_state * /* state_seeded */), \ - uint32_t tree_addrx4[4 * 8], const hash_state *state_seeded) { \ - unsigned char stackx4[4 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N]; \ - unsigned int heights[(tree_height) + 1]; \ - unsigned int offset = 0; \ - uint32_t idx; \ - uint32_t tree_idx; \ - unsigned int j; \ - \ - for (idx = 0; idx < (uint32_t)(1 << (tree_height)); idx++) { \ - /* Add the next leaf node to the stack. */ \ - gen_leafx4(stackx4 + 0 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N + offset * PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N, \ - stackx4 + 1 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N + offset * PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N, \ - stackx4 + 2 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N + offset * PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N, \ - stackx4 + 3 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N + offset * PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N, sk_seed, \ - pub_seed, idx + idx_offset[0], idx + idx_offset[1], idx + idx_offset[2], \ - idx + idx_offset[3], tree_addrx4, state_seeded); \ - offset++; \ - heights[offset - 1] = 0; \ - \ - /* If this is a node we need for the auth path.. */ \ - for (j = 0; j < 4; j++) { \ - if ((leaf_idx[j] ^ 0x1) == idx) { \ - memcpy(auth_pathx4 + j * (tree_height)*PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N, \ - stackx4 + j * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N + (offset - 1) * PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N, \ - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N); \ - } \ - } \ - \ - /* While the top-most nodes are of equal height.. */ \ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { \ - /* Compute index of the new node, in the next layer. */ \ - tree_idx = (idx >> (heights[offset - 1] + 1)); \ - \ - /* Set the address of the node we're creating. */ \ - for (j = 0; j < 4; j++) { \ - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_set_tree_height(tree_addrx4 + j * 8, heights[offset - 1] + 1); \ - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_set_tree_index(tree_addrx4 + j * 8, \ - tree_idx + (idx_offset[j] >> (heights[offset - 1] + 1))); \ - } \ - /* Hash the top-most nodes from the stack together. */ \ - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_thashx4_2(stackx4 + 0 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N + (offset - 2) * PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N, \ - stackx4 + 1 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N + (offset - 2) * PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N, \ - stackx4 + 2 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N + (offset - 2) * PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N, \ - stackx4 + 3 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N + (offset - 2) * PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N, \ - stackx4 + 0 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N + (offset - 2) * PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N, \ - stackx4 + 1 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N + (offset - 2) * PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N, \ - stackx4 + 2 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N + (offset - 2) * PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N, \ - stackx4 + 3 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N + (offset - 2) * PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N, \ - pub_seed, tree_addrx4, state_seeded); \ - offset--; \ - /* Note that the top-most node is now one layer higher. */ \ - heights[offset - 1]++; \ - \ - /* If this is a node we need for the auth path.. */ \ - for (j = 0; j < 4; j++) { \ - if (((leaf_idx[j] >> heights[offset - 1]) ^ 0x1) == tree_idx) { \ - memcpy(auth_pathx4 + j * (tree_height)*PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N + \ - heights[offset - 1] * PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N, \ - stackx4 + j * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N + (offset - 1) * PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N, \ - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N); \ - } \ - } \ - } \ - } \ - \ - for (j = 0; j < 4; j++) { \ - memcpy(rootx4 + j * PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N, stackx4 + j * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N, PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N); \ - } \ - } +void treehashx4(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, + uint32_t tree_height, + void (*gen_leafx4)( + unsigned char * /* Where to write the leaves */, + const spx_ctx *, + uint32_t idx, void *info), + uint32_t tree_addrx4[4 * 8], + void *info) { + /* This is where we keep the intermediate nodes */ + PQCLEAN_VLA(unsigned char, stackx4, tree_height * 4 * SPX_N); + uint32_t left_adj = 0, prev_left_adj = 0; /* When we're doing the top 3 */ + /* levels, the left-most part of the tree isn't at the beginning */ + /* of current[]. These give the offset of the actual start */ + + uint32_t idx; + uint32_t max_idx = (1U << (tree_height - 2)) - 1; + for (idx = 0;; idx++) { + unsigned char current[4 * SPX_N]; /* Current logical node */ + gen_leafx4( current, ctx, 4 * idx + idx_offset, + info ); -treehashx4_variant(FORS_HEIGHT, PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_FORS_HEIGHT) + /* Now combine the freshly generated right node with previously */ + /* generated left ones */ + uint32_t internal_idx_offset = idx_offset; + uint32_t internal_idx = idx; + uint32_t internal_leaf = leaf_idx; + uint32_t h; /* The height we are in the Merkle tree */ + for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { + + /* Special processing if we're at the top of the tree */ + if (h >= tree_height - 2) { + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[3 * SPX_N], SPX_N ); + return; + } + /* The tree indexing logic is a bit off in this case */ + /* Adjust it so that the left-most node of the part of */ + /* the tree that we're processing has index 0 */ + prev_left_adj = left_adj; + left_adj = 4U - (1 << (tree_height - h - 1)); + } + + /* Check if we hit the top of the tree */ + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[3 * SPX_N], SPX_N ); + return; + } + + /* + * Check if one of the nodes we have is a part of the + * authentication path; if it is, write it out + */ + if ((((internal_idx << 2) ^ internal_leaf) & ~0x3U) == 0) { + memcpy( &auth_path[ h * SPX_N ], + ¤t[(((internal_leaf & 3) ^ 1) + prev_left_adj) * SPX_N], + SPX_N ); + } + + /* + * Check if we're at a left child; if so, stop going up the stack + * Exception: if we've reached the end of the tree, keep on going + * (so we combine the last 4 nodes into the one root node in two + * more iterations) + */ + if ((internal_idx & 1) == 0 && idx < max_idx) { + break; + } + + /* Ok, we're at a right node (or doing the top 3 levels) */ + /* Now combine the left and right logical nodes together */ + + /* Set the address of the node we're creating. */ + unsigned int j; + internal_idx_offset >>= 1; + for (j = 0; j < 4; j++) { + set_tree_height(tree_addrx4 + j * 8, h + 1); + set_tree_index(tree_addrx4 + j * 8, + (4 / 2) * (internal_idx & ~1U) + j - left_adj + internal_idx_offset ); + } + unsigned char *left = &stackx4[h * 4 * SPX_N]; + thashx4( ¤t[0 * SPX_N], + ¤t[1 * SPX_N], + ¤t[2 * SPX_N], + ¤t[3 * SPX_N], + &left [0 * SPX_N], + &left [2 * SPX_N], + ¤t[0 * SPX_N], + ¤t[2 * SPX_N], + 2, ctx, tree_addrx4); + } + + /* We've hit a left child; save the current for when we get the */ + /* corresponding right right */ + memcpy( &stackx4[h * 4 * SPX_N], current, 4 * SPX_N); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/utilsx4.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/utilsx4.h index 3bdd6b82ee..facb874b18 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/utilsx4.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/utilsx4.h @@ -1,38 +1,30 @@ -#ifndef PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_UTILSX4_H -#define PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_UTILSX4_H - -#include "hash_state.h" -#include "params.h" +#ifndef SPX_UTILSX4_H +#define SPX_UTILSX4_H #include +#include "context.h" +#include "params.h" + /** * For a given leaf index, computes the authentication path and the resulting * root node using Merkle's TreeHash algorithm. * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_ADDR_TYPE_FORSTREE). + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). * Applies the offset idx_offset to indices before building addresses, so that * it is possible to continue counting indices across trees. + * + * This implementation uses AVX to compute internal nodes 4 at a time (in + * parallel) */ -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_treehashx4_FORS_HEIGHT(unsigned char *rootx4, - unsigned char *auth_pathx4, - const unsigned char *sk_seed, - const unsigned char *pub_seed, - const uint32_t leaf_idx[4], - uint32_t idx_offset[4], - void (*gen_leafx4)(unsigned char * /* leaf0 */, - unsigned char * /* leaf1 */, - unsigned char * /* leaf2 */, - unsigned char * /* leaf3 */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx0 */, - uint32_t /* addr_idx1 */, - uint32_t /* addr_idx2 */, - uint32_t /* addr_idx3 */, - const uint32_t[8] /* tree_addr */, - const hash_state * /* state_seeded */), - uint32_t tree_addrx4[4 * 8], - const hash_state *state_seeded); +#define treehashx4 SPX_NAMESPACE(treehashx4) +void treehashx4(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leafx4)( + unsigned char * /* Where to write the leaves */, + const spx_ctx * /* ctx */, + uint32_t addr_idx, void *info), + uint32_t tree_addrx4[4 * 8], void *info); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/wots.c b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/wots.c index e68a1d962e..4d5041ce05 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/wots.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/wots.c @@ -1,106 +1,104 @@ #include #include +#include "wots.h" + #include "address.h" #include "hash.h" -#include "hash_state.h" #include "hashx4.h" #include "params.h" #include "thash.h" #include "thashx4.h" #include "utils.h" -#include "wots.h" +#include "utilsx4.h" +#include "wotsx4.h" // TODO clarify address expectations, and make them more uniform. // TODO i.e. do we expect types to be set already? // TODO and do we expect modifications or copies? /** - * Computes the starting value for a chain, i.e. the secret key. - * Expects the address to be complete up to the chain address. - */ -static void wots_gen_sk(unsigned char *sk, const unsigned char *sk_seed, - uint32_t wots_addr[8], const hash_state *state_seeded) { - /* Make sure that the hash address is actually zeroed. */ - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_set_hash_addr(wots_addr, 0); - - /* Generate sk element. */ - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_prf_addr(sk, sk_seed, wots_addr, state_seeded); -} - -/** - * 4-way parallel version of wots_gen_sk; expects 4x as much space in sk + * Computes up the chains */ -static void wots_gen_skx4(unsigned char *skx4, const unsigned char *sk_seed, - uint32_t wots_addrx4[4 * 8], const hash_state *state_seeded) { - unsigned int j; - - /* Make sure that the hash address is actually zeroed. */ +static void gen_chains( + unsigned char *out, + const unsigned char *in, + unsigned int start[SPX_WOTS_LEN], + const unsigned int steps[SPX_WOTS_LEN], + const spx_ctx *ctx, + uint32_t addr[8]) { + uint32_t i, j, k, idx, watching; + int done; + unsigned char empty[SPX_N]; + unsigned char *bufs[4]; + uint32_t addrs[8 * 4]; + + int l; + uint16_t counts[SPX_WOTS_W] = { 0 }; + uint16_t idxs[SPX_WOTS_LEN]; + uint16_t total, newTotal; + + /* set addrs = {addr, addr, addr, addr} */ for (j = 0; j < 4; j++) { - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_set_hash_addr(wots_addrx4 + j * 8, 0); + memcpy(addrs + j * 8, addr, sizeof(uint32_t) * 8); } - /* Generate sk element. */ - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_prf_addrx4(skx4 + 0 * PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N, - skx4 + 1 * PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N, - skx4 + 2 * PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N, - skx4 + 3 * PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N, - sk_seed, wots_addrx4, - state_seeded); -} - -/** - * Computes the chaining function. - * out and in have to be n-byte arrays. - * - * Interprets in as start-th value of the chain. - * addr has to contain the address of the chain. - */ -static void gen_chain(unsigned char *out, const unsigned char *in, - unsigned int start, unsigned int steps, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *state_seeded) { - uint32_t i; - /* Initialize out with the value at position 'start'. */ - memcpy(out, in, PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N); + memcpy(out, in, SPX_WOTS_LEN * SPX_N); - /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_WOTS_W; i++) { - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_set_hash_addr(addr, i); - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_thash_1(out, out, pub_seed, addr, state_seeded); + /* Sort the chains in reverse order by steps using counting sort. */ + for (i = 0; i < SPX_WOTS_LEN; i++) { + counts[steps[i]]++; + } + total = 0; + for (l = SPX_WOTS_W - 1; l >= 0; l--) { + newTotal = counts[l] + total; + counts[l] = total; + total = newTotal; + } + for (i = 0; i < SPX_WOTS_LEN; i++) { + idxs[counts[steps[i]]] = (uint16_t)i; + counts[steps[i]]++; } -} -/** - * 4-way parallel version of gen_chain; expects 4x as much space in out, and - * 4x as much space in inx4. Assumes start and step identical across chains. - */ -static void gen_chainx4(unsigned char *outx4, const unsigned char *inx4, - unsigned int start, unsigned int steps, - const unsigned char *pub_seed, uint32_t addrx4[4 * 8], - const hash_state *state_seeded) { - uint32_t i; - unsigned int j; + /* We got our work cut out for us: do it! */ + for (i = 0; i < SPX_WOTS_LEN; i += 4) { + for (j = 0; j < 4 && i + j < SPX_WOTS_LEN; j++) { + idx = idxs[i + j]; + set_chain_addr(addrs + j * 8, idx); + bufs[j] = out + SPX_N * idx; + } - /* Initialize outx4 with the value at position 'start'. */ - memcpy(outx4, inx4, 4 * PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N); + /* As the chains are sorted in reverse order, we know that the first + * chain is the longest and the last one is the shortest. We keep + * an eye on whether the last chain is done and then on the one before, + * et cetera. */ + watching = 3; + done = 0; + while (i + watching >= SPX_WOTS_LEN) { + bufs[watching] = &empty[0]; + watching--; + } - /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_WOTS_W; i++) { - for (j = 0; j < 4; j++) { - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_set_hash_addr(addrx4 + j * 8, i); + for (k = 0;; k++) { + while (k == steps[idxs[i + watching]]) { + bufs[watching] = &empty[0]; + if (watching == 0) { + done = 1; + break; + } + watching--; + } + if (done) { + break; + } + for (j = 0; j < watching + 1; j++) { + set_hash_addr(addrs + j * 8, k + start[idxs[i + j]]); + } + + thashx4(bufs[0], bufs[1], bufs[2], bufs[3], + bufs[0], bufs[1], bufs[2], bufs[3], 1, ctx, addrs); } - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_thashx4_1(outx4 + 0 * PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N, - outx4 + 1 * PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N, - outx4 + 2 * PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N, - outx4 + 3 * PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N, - outx4 + 0 * PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N, - outx4 + 1 * PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N, - outx4 + 2 * PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N, - outx4 + 3 * PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N, - pub_seed, addrx4, - state_seeded); } } @@ -109,7 +107,8 @@ static void gen_chainx4(unsigned char *outx4, const unsigned char *inx4, * Interprets an array of bytes as integers in base w. * This only works when log_w is a divisor of 8. */ -static void base_w(unsigned int *output, const int out_len, const unsigned char *input) { +static void base_w(unsigned int *output, const int out_len, + const unsigned char *input) { int in = 0; int out = 0; unsigned char total = 0; @@ -122,119 +121,149 @@ static void base_w(unsigned int *output, const int out_len, const unsigned char in++; bits += 8; } - bits -= PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_WOTS_LOGW; - output[out] = (unsigned int)(total >> bits) & (PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_WOTS_W - 1); + bits -= SPX_WOTS_LOGW; + output[out] = (total >> bits) & (SPX_WOTS_W - 1); out++; } } /* Computes the WOTS+ checksum over a message (in base_w). */ -static void wots_checksum(unsigned int *csum_base_w, const unsigned int *msg_base_w) { +static void wots_checksum(unsigned int *csum_base_w, + const unsigned int *msg_base_w) { unsigned int csum = 0; - unsigned char csum_bytes[(PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_WOTS_LEN2 * PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_WOTS_LOGW + 7) / 8]; + unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; unsigned int i; /* Compute checksum. */ - for (i = 0; i < PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_WOTS_LEN1; i++) { - csum += PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_WOTS_W - 1 - msg_base_w[i]; + for (i = 0; i < SPX_WOTS_LEN1; i++) { + csum += SPX_WOTS_W - 1 - msg_base_w[i]; } /* Convert checksum to base_w. */ /* Make sure expected empty zero bits are the least significant bits. */ - csum = csum << (8 - ((PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_WOTS_LEN2 * PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_WOTS_LOGW) % 8)); - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); - base_w(csum_base_w, PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_WOTS_LEN2, csum_bytes); + csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); + ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); + base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); } /* Takes a message and derives the matching chain lengths. */ -static void chain_lengths(unsigned int *lengths, const unsigned char *msg) { - base_w(lengths, PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_WOTS_LEN1, msg); - wots_checksum(lengths + PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_WOTS_LEN1, lengths); +void chain_lengths(unsigned int *lengths, const unsigned char *msg) { + base_w(lengths, SPX_WOTS_LEN1, msg); + wots_checksum(lengths + SPX_WOTS_LEN1, lengths); } /** - * WOTS key generation. Takes a 32 byte sk_seed, expands it to WOTS private key - * elements and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. * * Writes the computed public key to 'pk'. */ -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_wots_gen_pk(unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *state_seeded) { +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]) { + unsigned int steps[SPX_WOTS_LEN]; + unsigned int start[SPX_WOTS_LEN]; uint32_t i; - unsigned int j; - uint32_t addrx4[4 * 8]; - unsigned char pkbuf[4 * PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N]; + chain_lengths(start, msg); - for (j = 0; j < 4; j++) { - memcpy(addrx4 + j * 8, addr, sizeof(uint32_t) * 8); - } - - /* The last iteration typically does not have complete set of 4 chains, - but because we use pkbuf, this is not an issue -- we still do as many - in parallel as possible. */ - for (i = 0; i < ((PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_WOTS_LEN + 3) & ~0x3); i += 4) { - for (j = 0; j < 4; j++) { - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_set_chain_addr(addrx4 + j * 8, i + j); - } - wots_gen_skx4(pkbuf, sk_seed, addrx4, state_seeded); - gen_chainx4(pkbuf, pkbuf, 0, PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_WOTS_W - 1, pub_seed, addrx4, state_seeded); - for (j = 0; j < 4; j++) { - if (i + j < PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_WOTS_LEN) { - memcpy(pk + (i + j)*PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N, pkbuf + j * PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N, PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N); - } - } + for (i = 0; i < SPX_WOTS_LEN; i++) { + steps[i] = SPX_WOTS_W - 1 - start[i]; } - // Get rid of unused argument variable. - (void)state_seeded; + gen_chains(pk, sig, start, steps, ctx, addr); } -/** - * Takes a n-byte message and the 32-byte sk_see to compute a signature 'sig'. +/* + * This generates 4 sequential WOTS public keys + * It also generates the WOTS signature if leaf_info indicates + * that we're signing with one of these WOTS keys */ -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_wots_sign(unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); +void wots_gen_leafx4(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info) { + struct leaf_info_x4 *info = v_info; + uint32_t *leaf_addr = info->leaf_addr; + uint32_t *pk_addr = info->pk_addr; + unsigned int i, j, k; + unsigned char pk_buffer[ 4 * SPX_WOTS_BYTES ]; + unsigned wots_offset = SPX_WOTS_BYTES; + unsigned char *buffer; + uint32_t wots_k_mask; + unsigned wots_sign_index; + + if (((leaf_idx ^ info->wots_sign_leaf) & ~3U) == 0) { + /* We're traversing the leaf that's signing; generate the WOTS */ + /* signature */ + wots_k_mask = 0; + wots_sign_index = info->wots_sign_leaf & 3; /* Which of of the 4 */ + /* 4 slots do the signatures come from */ + } else { + /* Nope, we're just generating pk's; turn off the signature logic */ + wots_k_mask = (uint32_t)~0; + wots_sign_index = 0; + } - for (i = 0; i < PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_WOTS_LEN; i++) { - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_set_chain_addr(addr, i); - wots_gen_sk(sig + i * PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N, sk_seed, addr, state_seeded); - gen_chain(sig + i * PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N, sig + i * PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N, 0, lengths[i], pub_seed, addr, state_seeded); + for (j = 0; j < 4; j++) { + set_keypair_addr( leaf_addr + j * 8, leaf_idx + j ); + set_keypair_addr( pk_addr + j * 8, leaf_idx + j ); } - // avoid unused argument - (void)state_seeded; -} + for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { + uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k to */ + /* the step if we're generating a signature, ~0 if we're not */ -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_WOTS_LEN]; - uint32_t i; + /* Start with the secret seed */ + for (j = 0; j < 4; j++) { + set_chain_addr(leaf_addr + j * 8, i); + set_hash_addr(leaf_addr + j * 8, 0); + set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTSPRF); + } + prf_addrx4(buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + buffer + 2 * wots_offset, + buffer + 3 * wots_offset, + ctx, leaf_addr); - chain_lengths(lengths, msg); + for (j = 0; j < 4; j++) { + set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTS); + } + + /* Iterate down the WOTS chain */ + for (k = 0;; k++) { + /* Check if one of the values we have needs to be saved as a */ + /* part of the WOTS signature */ + if (k == wots_k) { + memcpy( info->wots_sig + i * SPX_N, + buffer + wots_sign_index * wots_offset, SPX_N ); + } - for (i = 0; i < PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_WOTS_LEN; i++) { - PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_set_chain_addr(addr, i); - gen_chain(pk + i * PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N, sig + i * PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_N, - lengths[i], PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_WOTS_W - 1 - lengths[i], pub_seed, addr, - state_seeded); + /* Check if we hit the top of the chain */ + if (k == SPX_WOTS_W - 1) { + break; + } + + /* Iterate one step on all 4 chains */ + for (j = 0; j < 4; j++) { + set_hash_addr(leaf_addr + j * 8, k); + } + thashx4(buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + buffer + 2 * wots_offset, + buffer + 3 * wots_offset, + buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + buffer + 2 * wots_offset, + buffer + 3 * wots_offset, 1, ctx, leaf_addr); + } } - // avoid unused argument - (void)state_seeded; + /* Do the final thash to generate the public keys */ + thashx4(dest + 0 * SPX_N, + dest + 1 * SPX_N, + dest + 2 * SPX_N, + dest + 3 * SPX_N, + pk_buffer + 0 * wots_offset, + pk_buffer + 1 * wots_offset, + pk_buffer + 2 * wots_offset, + pk_buffer + 3 * wots_offset, SPX_WOTS_LEN, ctx, pk_addr); } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/wots.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/wots.h index 72a8b982be..4e7692eeef 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/wots.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/wots.h @@ -1,41 +1,25 @@ -#ifndef PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_WOTS_H -#define PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_WOTS_H +#ifndef SPX_WOTS_H +#define SPX_WOTS_H -#include "hash_state.h" -#include "params.h" #include -/** - * WOTS key generation. Takes a 32 byte seed for the private key, expands it to - * a full WOTS private key and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_wots_gen_pk( - unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -/** - * Takes a n-byte message and the 32-byte seed for the private key to compute a - * signature that is placed at 'sig'. - */ -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_wots_sign( - unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *hash_state_seeded); +#include "context.h" +#include "params.h" /** * Takes a WOTS signature and an n-byte message, computes a WOTS public key. * * Writes the computed public key to 'pk'. */ -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_wots_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); +#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]); + +/* + * Compute the chain lengths needed for a given message hash + */ +#define chain_lengths SPX_NAMESPACE(chain_lengths) +void chain_lengths(unsigned int *lengths, const unsigned char *msg); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/wotsx4.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/wotsx4.h new file mode 100644 index 0000000000..cd634f1743 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/wotsx4.h @@ -0,0 +1,41 @@ +#ifndef WOTSX4_H_ +#define WOTSX4_H_ + +#include + +#include "params.h" + +/* + * This is here to provide an interface to the internal wots_gen_leafx4 + * routine. While this routine is not referenced in the package outside of + * wots.c, it is called from the stand-alone benchmark code to characterize + * the performance + */ +struct leaf_info_x4 { + unsigned char *wots_sig; + uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ + uint32_t *wots_steps; + uint32_t leaf_addr[4 * 8]; + uint32_t pk_addr[4 * 8]; +}; + +/* Macro to set the leaf_info to something 'benign', that is, it would */ +/* run with the same time as it does during the real signing process */ +/* Used only by the benchmark code */ +#define INITIALIZE_LEAF_INFO_X4(info, addr, step_buffer) { \ + (info).wots_sig = 0; \ + (info).wots_sign_leaf = ~0; \ + (info).wots_steps = step_buffer; \ + int i; \ + for (i=0; i<4; i++) { \ + memcpy( &(info).leaf_addr[8*i], addr, 32 ); \ + memcpy( &(info).pk_addr[8*i], addr, 32 ); \ + } \ + } + +#define wots_gen_leafx4 SPX_NAMESPACE(wots_gen_leafx4) +void wots_gen_leafx4(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info); + +#endif /* WOTSX4_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/address.c b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/address.c index cdee97b6d0..b956e9cb29 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/address.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/address.c @@ -1,78 +1,91 @@ #include +#include #include "address.h" #include "params.h" #include "utils.h" -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]) { - int i; - - for (i = 0; i < 8; i++) { - PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_ull_to_bytes( - bytes + i * 4, 4, addr[i]); - } -} - -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_set_layer_addr( - uint32_t addr[8], uint32_t layer) { - addr[0] = layer; +/* + * Specify which level of Merkle tree (the "layer") we're working on + */ +void set_layer_addr(uint32_t addr[8], uint32_t layer) { + ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; } -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_set_tree_addr( - uint32_t addr[8], uint64_t tree) { - addr[1] = 0; - addr[2] = (uint32_t) (tree >> 32); - addr[3] = (uint32_t) tree; +/* + * Specify which Merkle tree within the level (the "tree address") we're working on + */ +void set_tree_addr(uint32_t addr[8], uint64_t tree) { + ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); } -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_set_type( - uint32_t addr[8], uint32_t type) { - addr[4] = type; +/* + * Specify the reason we'll use this address structure for, that is, what + * hash will we compute with it. This is used so that unrelated types of + * hashes don't accidentally get the same address structure. The type will be + * one of the SPX_ADDR_TYPE constants + */ +void set_type(uint32_t addr[8], uint32_t type) { + ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; } -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; +/* + * Copy the layer and tree fields of the address structure. This is used + * when we're doing multiple types of hashes within the same Merkle tree + */ +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); } /* These functions are used for OTS addresses. */ -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_set_keypair_addr( - uint32_t addr[8], uint32_t keypair) { - addr[5] = keypair; +/* + * Specify which Merkle leaf we're working on; that is, which OTS keypair + * we're talking about. + */ +void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { + ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; } -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; - out[5] = in[5]; +/* + * Copy the layer, tree and keypair fields of the address structure. This is + * used when we're doing multiple things within the same OTS keypair + */ +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); + ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; } -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_set_chain_addr( - uint32_t addr[8], uint32_t chain) { - addr[6] = chain; +/* + * Specify which Merkle chain within the OTS we're working with + * (the chain address) + */ +void set_chain_addr(uint32_t addr[8], uint32_t chain) { + ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; } -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_set_hash_addr( - uint32_t addr[8], uint32_t hash) { - addr[7] = hash; +/* + * Specify where in the Merkle chain we are +* (the hash address) + */ +void set_hash_addr(uint32_t addr[8], uint32_t hash) { + ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; } /* These functions are used for all hash tree addresses (including FORS). */ -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_set_tree_height( - uint32_t addr[8], uint32_t tree_height) { - addr[6] = tree_height; +/* + * Specify the height of the node in the Merkle/FORS tree we are in + * (the tree height) + */ +void set_tree_height(uint32_t addr[8], uint32_t tree_height) { + ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; } -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_set_tree_index( - uint32_t addr[8], uint32_t tree_index) { - addr[7] = tree_index; +/* + * Specify the distance from the left edge of the node in the Merkle/FORS tree + * (the tree index) + */ +void set_tree_index(uint32_t addr[8], uint32_t tree_index) { + u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/address.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/address.h index 0e3072850e..24a84eb40c 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/address.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/address.h @@ -1,50 +1,52 @@ -#ifndef PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_ADDRESS_H -#define PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_ADDRESS_H +#ifndef SPX_ADDRESS_H +#define SPX_ADDRESS_H #include -#define PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_ADDR_TYPE_WOTS 0 -#define PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_ADDR_TYPE_WOTSPK 1 -#define PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_ADDR_TYPE_HASHTREE 2 -#define PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_ADDR_TYPE_FORSTREE 3 -#define PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_ADDR_TYPE_FORSPK 4 +#include "params.h" -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]); +/* The hash types that are passed to set_type */ +#define SPX_ADDR_TYPE_WOTS 0 +#define SPX_ADDR_TYPE_WOTSPK 1 +#define SPX_ADDR_TYPE_HASHTREE 2 +#define SPX_ADDR_TYPE_FORSTREE 3 +#define SPX_ADDR_TYPE_FORSPK 4 +#define SPX_ADDR_TYPE_WOTSPRF 5 +#define SPX_ADDR_TYPE_FORSPRF 6 -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_set_layer_addr( - uint32_t addr[8], uint32_t layer); +#define set_layer_addr SPX_NAMESPACE(set_layer_addr) +void set_layer_addr(uint32_t addr[8], uint32_t layer); -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_set_tree_addr( - uint32_t addr[8], uint64_t tree); +#define set_tree_addr SPX_NAMESPACE(set_tree_addr) +void set_tree_addr(uint32_t addr[8], uint64_t tree); -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_set_type( - uint32_t addr[8], uint32_t type); +#define set_type SPX_NAMESPACE(set_type) +void set_type(uint32_t addr[8], uint32_t type); /* Copies the layer and tree part of one address into the other */ -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]); +#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); /* These functions are used for WOTS and FORS addresses. */ -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_set_keypair_addr( - uint32_t addr[8], uint32_t keypair); +#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) +void set_keypair_addr(uint32_t addr[8], uint32_t keypair); -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_set_chain_addr( - uint32_t addr[8], uint32_t chain); +#define set_chain_addr SPX_NAMESPACE(set_chain_addr) +void set_chain_addr(uint32_t addr[8], uint32_t chain); -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_set_hash_addr( - uint32_t addr[8], uint32_t hash); +#define set_hash_addr SPX_NAMESPACE(set_hash_addr) +void set_hash_addr(uint32_t addr[8], uint32_t hash); -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]); +#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); /* These functions are used for all hash tree addresses (including FORS). */ -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_set_tree_height( - uint32_t addr[8], uint32_t tree_height); +#define set_tree_height SPX_NAMESPACE(set_tree_height) +void set_tree_height(uint32_t addr[8], uint32_t tree_height); -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_set_tree_index( - uint32_t addr[8], uint32_t tree_index); +#define set_tree_index SPX_NAMESPACE(set_tree_index) +void set_tree_index(uint32_t addr[8], uint32_t tree_index); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/api.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/api.h index 6a866100b7..dae709471f 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/api.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/api.h @@ -4,15 +4,13 @@ #include #include - - -#define PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_CRYPTO_ALGNAME "SPHINCS+" +#define PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_CRYPTO_ALGNAME "SPHINCS+-haraka-192f-simple" #define PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_CRYPTO_SECRETKEYBYTES 96 #define PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_CRYPTO_PUBLICKEYBYTES 48 -#define PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_CRYPTO_BYTES 35664 -#define PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_CRYPTO_SEEDBYTES 72 +#define PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_CRYPTO_BYTES 35664 +#define PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_CRYPTO_SEEDBYTES 72 /* * Returns the length of a secret key, in bytes @@ -39,43 +37,41 @@ size_t PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_crypto_sign_seedbytes(void); * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] * Format pk: [root || PUB_SEED] */ -int PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed); +int PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); /* * Generates a SPHINCS+ key pair. * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] * Format pk: [root || PUB_SEED] */ -int PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk); +int PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); /** * Returns an array containing a detached signature. */ -int PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk); +int PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); /** * Verifies a detached signature and message under a given public key. */ -int PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk); +int PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, + const uint8_t *pk); /** * Returns an array containing the signature followed by the message. */ -int PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk); +int PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); /** * Verifies a given signature-message pair under a given public key. */ -int PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk); - +int PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/context.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/context.h new file mode 100644 index 0000000000..600dfb73c7 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/context.h @@ -0,0 +1,24 @@ +#ifndef SPX_CONTEXT_H +#define SPX_CONTEXT_H + +#include +#include + +#include "params.h" + +typedef struct { + uint8_t pub_seed[SPX_N]; + uint8_t sk_seed[SPX_N]; + + + uint64_t tweaked512_rc64[10][8]; + uint32_t tweaked256_rc32[10][8]; +} spx_ctx; + +#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) +void initialize_hash_function(spx_ctx *ctx); + +#define free_hash_function SPX_NAMESPACE(free_hash_function) +void free_hash_function(spx_ctx *ctx); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/context_haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/context_haraka.c new file mode 100644 index 0000000000..f1cd7e3664 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/context_haraka.c @@ -0,0 +1,11 @@ +#include "context.h" +#include "haraka.h" + +void initialize_hash_function(spx_ctx *ctx) { + tweak_constants(ctx); +} + +// we don't support heap-based haraka right now +void free_hash_function(spx_ctx *ctx) { + (void)ctx; // suppress unused variable warnings +} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/fors.c b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/fors.c index 5fd6c0582d..96ca72e986 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/fors.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/fors.c @@ -2,58 +2,58 @@ #include #include -#include "address.h" #include "fors.h" + +#include "address.h" #include "hash.h" -#include "hash_state.h" #include "thash.h" #include "utils.h" +#include "utilsx1.h" -static void fors_gen_sk(unsigned char *sk, const unsigned char *sk_seed, - uint32_t fors_leaf_addr[8], const hash_state *hash_state_seeded) { - PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_prf_addr( - sk, sk_seed, fors_leaf_addr, hash_state_seeded); +static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + prf_addr(sk, ctx, fors_leaf_addr); } static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, - const unsigned char *pub_seed, - uint32_t fors_leaf_addr[8], - const hash_state *hash_state_seeded) { - PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_thash_1( - leaf, sk, pub_seed, fors_leaf_addr, hash_state_seeded); + const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + thash(leaf, sk, 1, ctx, fors_leaf_addr); } -static void fors_gen_leaf(unsigned char *leaf, const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx, const uint32_t fors_tree_addr[8], - const hash_state *hash_state_seeded) { - uint32_t fors_leaf_addr[8] = {0}; - - /* Only copy the parts that must be kept in fors_leaf_addr. */ - PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_copy_keypair_addr( - fors_leaf_addr, fors_tree_addr); - PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_set_type( - fors_leaf_addr, PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_set_tree_index( - fors_leaf_addr, addr_idx); - - fors_gen_sk(leaf, sk_seed, fors_leaf_addr, hash_state_seeded); - fors_sk_to_leaf(leaf, leaf, pub_seed, fors_leaf_addr, hash_state_seeded); +struct fors_gen_leaf_info { + uint32_t leaf_addrx[8]; +}; + +static void fors_gen_leafx1(unsigned char *leaf, + const spx_ctx *ctx, + uint32_t addr_idx, void *info) { + struct fors_gen_leaf_info *fors_info = info; + uint32_t *fors_leaf_addr = fors_info->leaf_addrx; + + /* Only set the parts that the caller doesn't set */ + set_tree_index(fors_leaf_addr, addr_idx); + set_type(fors_leaf_addr, SPX_ADDR_TYPE_FORSPRF); + fors_gen_sk(leaf, ctx, fors_leaf_addr); + + set_type(fors_leaf_addr, SPX_ADDR_TYPE_FORSTREE); + fors_sk_to_leaf(leaf, leaf, + ctx, fors_leaf_addr); } /** - * Interprets m as PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_FORS_HEIGHT-bit unsigned integers. - * Assumes m contains at least PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_FORS_TREES bits. - * Assumes indices has space for PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_FORS_TREES integers. + * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + * Assumes indices has space for SPX_FORS_TREES integers. */ static void message_to_indices(uint32_t *indices, const unsigned char *m) { unsigned int i, j; unsigned int offset = 0; - for (i = 0; i < PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_FORS_TREES; i++) { + for (i = 0; i < SPX_FORS_TREES; i++) { indices[i] = 0; - for (j = 0; j < PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_FORS_HEIGHT; j++) { - indices[i] ^= (((uint32_t)m[offset >> 3] >> (offset & 0x7)) & 0x1) << j; + for (j = 0; j < SPX_FORS_HEIGHT; j++) { + indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); offset++; } } @@ -61,55 +61,51 @@ static void message_to_indices(uint32_t *indices, const unsigned char *m) { /** * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_FORS_TREES bits. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. */ -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_fors_sign( - unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *hash_state_seeded) { - uint32_t indices[PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_FORS_TREES]; - unsigned char roots[PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_FORS_TREES * PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_N]; +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; uint32_t fors_tree_addr[8] = {0}; + struct fors_gen_leaf_info fors_info = {0}; + uint32_t *fors_leaf_addr = fors_info.leaf_addrx; uint32_t fors_pk_addr[8] = {0}; uint32_t idx_offset; unsigned int i; - PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_copy_keypair_addr( - fors_tree_addr, fors_addr); - PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_copy_keypair_addr( - fors_pk_addr, fors_addr); + copy_keypair_addr(fors_tree_addr, fors_addr); + copy_keypair_addr(fors_leaf_addr, fors_addr); - PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_set_type( - fors_tree_addr, PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_set_type( - fors_pk_addr, PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_ADDR_TYPE_FORSPK); + copy_keypair_addr(fors_pk_addr, fors_addr); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); message_to_indices(indices, m); - for (i = 0; i < PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_FORS_TREES; i++) { - idx_offset = i * (1 << PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_FORS_HEIGHT); + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); - PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_set_tree_height( - fors_tree_addr, 0); - PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_set_tree_index( - fors_tree_addr, indices[i] + idx_offset); + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); /* Include the secret key part that produces the selected leaf node. */ - fors_gen_sk(sig, sk_seed, fors_tree_addr, hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_N; + fors_gen_sk(sig, ctx, fors_tree_addr); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + sig += SPX_N; /* Compute the authentication path for this leaf node. */ - PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_treehash_FORS_HEIGHT( - roots + i * PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_N, sig, sk_seed, pub_seed, - indices[i], idx_offset, fors_gen_leaf, fors_tree_addr, - hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_N * PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_FORS_HEIGHT; + treehashx1(roots + i * SPX_N, sig, ctx, + indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx1, + fors_tree_addr, &fors_info); + + sig += SPX_N * SPX_FORS_HEIGHT; } /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_thash_FORS_TREES( - pk, roots, pub_seed, fors_pk_addr, hash_state_seeded); + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); } /** @@ -117,45 +113,44 @@ void PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_fors_sign( * This can be used for verification by comparing to a known public key, or to * subsequently verify a signature on the derived public key. The latter is the * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_FORS_TREES bits. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. */ -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_fors_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, const uint32_t fors_addr[8], - const hash_state *hash_state_seeded) { - uint32_t indices[PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_FORS_TREES]; - unsigned char roots[PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_FORS_TREES * PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_N]; - unsigned char leaf[PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_N]; +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + unsigned char leaf[SPX_N]; uint32_t fors_tree_addr[8] = {0}; uint32_t fors_pk_addr[8] = {0}; uint32_t idx_offset; unsigned int i; - PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_copy_keypair_addr(fors_tree_addr, fors_addr); - PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_copy_keypair_addr(fors_pk_addr, fors_addr); + copy_keypair_addr(fors_tree_addr, fors_addr); + copy_keypair_addr(fors_pk_addr, fors_addr); - PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_set_type(fors_tree_addr, PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_set_type(fors_pk_addr, PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_ADDR_TYPE_FORSPK); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); message_to_indices(indices, m); - for (i = 0; i < PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_FORS_TREES; i++) { - idx_offset = i * (1 << PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_FORS_HEIGHT); + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); - PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_set_tree_height(fors_tree_addr, 0); - PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_set_tree_index(fors_tree_addr, indices[i] + idx_offset); + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); /* Derive the leaf from the included secret key part. */ - fors_sk_to_leaf(leaf, sig, pub_seed, fors_tree_addr, hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_N; + fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); + sig += SPX_N; /* Derive the corresponding root node of this tree. */ - PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_compute_root(roots + i * PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_N, leaf, indices[i], idx_offset, sig, - PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_FORS_HEIGHT, pub_seed, fors_tree_addr, hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_N * PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_FORS_HEIGHT; + compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, + sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); + sig += SPX_N * SPX_FORS_HEIGHT; } /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_thash_FORS_TREES(pk, roots, pub_seed, fors_pk_addr, hash_state_seeded); + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/fors.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/fors.h index d1cfe5169c..509140a178 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/fors.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/fors.h @@ -1,32 +1,32 @@ -#ifndef PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_FORS_H -#define PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_FORS_H +#ifndef SPX_FORS_H +#define SPX_FORS_H #include -#include "hash_state.h" +#include "context.h" #include "params.h" /** * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_FORS_TREES bits. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. */ -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_fors_sign( - unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *hash_state_seeded); +#define fors_sign SPX_NAMESPACE(fors_sign) +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); /** * Derives the FORS public key from a signature. * This can be used for verification by comparing to a known public key, or to * subsequently verify a signature on the derived public key. The latter is the * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_FORS_TREES bits. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. */ -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_fors_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, const uint32_t fors_addr[8], - const hash_state *hash_state_seeded); +#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/haraka.c index ffb2f99e9f..a4944913b5 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/haraka.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/haraka.c @@ -6,12 +6,13 @@ * by Thomas Pornin */ -#include #include +#include #include #include #include "haraka.h" +#include "utils.h" #define HARAKAS_RATE 32 @@ -656,76 +657,62 @@ static void interleave_constant32(uint32_t *out, const unsigned char *in) { br_aes_ct_ortho(out); } -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_tweak_constants( - harakactx *state, - const unsigned char *pk_seed, const unsigned char *sk_seed, - unsigned long long seed_length) { +void tweak_constants(spx_ctx *ctx) { unsigned char buf[40 * 16]; int i; /* Use the standard constants to generate tweaked ones. */ - memcpy((uint8_t *)state->tweaked512_rc64, (uint8_t *)haraka512_rc64, 40 * 16); - - /* Constants for sk.seed */ - if (sk_seed != NULL) { - PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_haraka_S( - buf, 40 * 16, sk_seed, seed_length, state); - - /* Interleave constants */ - for (i = 0; i < 10; i++) { - interleave_constant32(state->tweaked256_rc32_sseed[i], buf + 32 * i); - } - } + memcpy((uint8_t *)ctx->tweaked512_rc64, (uint8_t *)haraka512_rc64, 40 * 16); /* Constants for pk.seed */ - PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_haraka_S( - buf, 40 * 16, pk_seed, seed_length, state); + haraka_S(buf, 40 * 16, ctx->pub_seed, SPX_N, ctx); for (i = 0; i < 10; i++) { - interleave_constant32(state->tweaked256_rc32[i], buf + 32 * i); - interleave_constant(state->tweaked512_rc64[i], buf + 64 * i); + interleave_constant32(ctx->tweaked256_rc32[i], buf + 32 * i); + interleave_constant(ctx->tweaked512_rc64[i], buf + 64 * i); } } -static void haraka_S_absorb(unsigned char *s, +static void haraka_S_absorb(unsigned char *s, unsigned int r, const unsigned char *m, unsigned long long mlen, - unsigned char p, const harakactx *state) { + unsigned char p, const spx_ctx *ctx) { unsigned long long i; - unsigned char t[HARAKAS_RATE]; + PQCLEAN_VLA(uint8_t, t, r); - while (mlen >= HARAKAS_RATE) { + while (mlen >= r) { /* XOR block to state */ - for (i = 0; i < HARAKAS_RATE; ++i) { + for (i = 0; i < r; ++i) { s[i] ^= m[i]; } - PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_haraka512_perm(s, s, state); - mlen -= HARAKAS_RATE; - m += HARAKAS_RATE; + haraka512_perm(s, s, ctx); + mlen -= r; + m += r; } - for (i = 0; i < HARAKAS_RATE; ++i) { + for (i = 0; i < r; ++i) { t[i] = 0; } for (i = 0; i < mlen; ++i) { t[i] = m[i]; } t[i] = p; - t[HARAKAS_RATE - 1] |= 128; - for (i = 0; i < HARAKAS_RATE; ++i) { + t[r - 1] |= 128; + for (i = 0; i < r; ++i) { s[i] ^= t[i]; } } static void haraka_S_squeezeblocks(unsigned char *h, unsigned long long nblocks, - unsigned char *s, const harakactx *state) { + unsigned char *s, unsigned int r, + const spx_ctx *ctx) { while (nblocks > 0) { - PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_haraka512_perm(s, s, state); + haraka512_perm(s, s, ctx); memcpy(h, s, HARAKAS_RATE); - h += HARAKAS_RATE; + h += r; nblocks--; } } -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_haraka_S_inc_init(uint8_t *s_inc) { +void haraka_S_inc_init(uint8_t *s_inc) { size_t i; for (i = 0; i < 64; i++) { @@ -734,7 +721,8 @@ void PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_haraka_S_inc_init(uint8_t *s_inc) { s_inc[64] = 0; } -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, const harakactx *state) { +void haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, + const spx_ctx *ctx) { size_t i; /* Recall that s_inc[64] is the non-absorbed bytes xored into the state */ @@ -745,19 +733,19 @@ void PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_haraka_S_inc_absorb(uint8_t *s_inc, c s_inc[s_inc[64] + i] ^= m[i]; } mlen -= (size_t)(HARAKAS_RATE - s_inc[64]); - m += HARAKAS_RATE - s_inc[64]; + m += HARAKAS_RATE - (uint8_t)s_inc[64]; s_inc[64] = 0; - PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_haraka512_perm(s_inc, s_inc, state); + haraka512_perm(s_inc, s_inc, ctx); } for (i = 0; i < mlen; i++) { s_inc[s_inc[64] + i] ^= m[i]; } - s_inc[64] = (uint8_t)(mlen + s_inc[64]); + s_inc[64] += (uint8_t)mlen; } -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_haraka_S_inc_finalize(uint8_t *s_inc) { +void haraka_S_inc_finalize(uint8_t *s_inc) { /* After haraka_S_inc_absorb, we are guaranteed that s_inc[64] < HARAKAS_RATE, so we can always use one more byte for p in the current state. */ s_inc[s_inc[64]] ^= 0x1F; @@ -765,22 +753,23 @@ void PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_haraka_S_inc_finalize(uint8_t *s_inc) s_inc[64] = 0; } -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, const harakactx *state) { - uint8_t i; +void haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, + const spx_ctx *ctx) { + size_t i; /* First consume any bytes we still have sitting around */ for (i = 0; i < outlen && i < s_inc[64]; i++) { /* There are s_inc[64] bytes left, so r - s_inc[64] is the first available byte. We consume from there, i.e., up to r. */ - out[i] = s_inc[(HARAKAS_RATE - s_inc[64] + i)]; + out[i] = (uint8_t)s_inc[(HARAKAS_RATE - s_inc[64] + i)]; } out += i; outlen -= i; - s_inc[64] = (uint8_t)(s_inc[64] - i); + s_inc[64] -= (uint8_t)i; /* Then squeeze the remaining necessary blocks */ while (outlen > 0) { - PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_haraka512_perm(s_inc, s_inc, state); + haraka512_perm(s_inc, s_inc, ctx); for (i = 0; i < outlen && i < HARAKAS_RATE; i++) { out[i] = s_inc[i]; @@ -791,7 +780,9 @@ void PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_haraka_S_inc_squeeze(uint8_t *out, si } } -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_haraka_S(unsigned char *out, unsigned long long outlen, const unsigned char *in, unsigned long long inlen, const harakactx *state) { +void haraka_S(unsigned char *out, unsigned long long outlen, + const unsigned char *in, unsigned long long inlen, + const spx_ctx *ctx) { unsigned long long i; unsigned char s[64]; unsigned char d[32]; @@ -799,20 +790,21 @@ void PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_haraka_S(unsigned char *out, unsigned for (i = 0; i < 64; i++) { s[i] = 0; } - haraka_S_absorb(s, in, inlen, 0x1F, state); + haraka_S_absorb(s, 32, in, inlen, 0x1F, ctx); - haraka_S_squeezeblocks(out, outlen / 32, s, state); + haraka_S_squeezeblocks(out, outlen / 32, s, 32, ctx); out += (outlen / 32) * 32; if (outlen % 32) { - haraka_S_squeezeblocks(d, 1, s, state); + haraka_S_squeezeblocks(d, 1, s, 32, ctx); for (i = 0; i < outlen % 32; i++) { out[i] = d[i]; } } } -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_haraka512_perm(unsigned char *out, const unsigned char *in, const harakactx *state) { +void haraka512_perm(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx) { uint32_t w[16]; uint64_t q[8], tmp_q; unsigned int i, j; @@ -829,7 +821,7 @@ void PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_haraka512_perm(unsigned char *out, co br_aes_ct64_bitslice_Sbox(q); shift_rows(q); mix_columns(q); - add_round_key(q, state->tweaked512_rc64[2 * i + j]); + add_round_key(q, ctx->tweaked512_rc64[2 * i + j]); } /* Mix states */ for (j = 0; j < 8; j++) { @@ -857,12 +849,12 @@ void PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_haraka512_perm(unsigned char *out, co br_range_enc32le(out, w, 16); } -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_haraka512(unsigned char *out, const unsigned char *in, const harakactx *state) { +void haraka512(unsigned char *out, const unsigned char *in, const spx_ctx *ctx) { int i; unsigned char buf[64]; - PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_haraka512_perm(buf, in, state); + haraka512_perm(buf, in, ctx); /* Feed-forward */ for (i = 0; i < 64; i++) { buf[i] = buf[i] ^ in[i]; @@ -876,50 +868,8 @@ void PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_haraka512(unsigned char *out, const u } -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_haraka256(unsigned char *out, const unsigned char *in, const harakactx *state) { - uint32_t q[8], tmp_q; - int i, j; - - for (i = 0; i < 4; i++) { - q[2 * i] = br_dec32le(in + 4 * i); - q[2 * i + 1] = br_dec32le(in + 4 * i + 16); - } - br_aes_ct_ortho(q); - - /* AES rounds */ - for (i = 0; i < 5; i++) { - for (j = 0; j < 2; j++) { - br_aes_ct_bitslice_Sbox(q); - shift_rows32(q); - mix_columns32(q); - add_round_key32(q, state->tweaked256_rc32[2 * i + j]); - } - - /* Mix states */ - for (j = 0; j < 8; j++) { - tmp_q = q[j]; - q[j] = (tmp_q & 0x81818181) | - (tmp_q & 0x02020202) << 1 | - (tmp_q & 0x04040404) << 2 | - (tmp_q & 0x08080808) << 3 | - (tmp_q & 0x10101010) >> 3 | - (tmp_q & 0x20202020) >> 2 | - (tmp_q & 0x40404040) >> 1; - } - } - - br_aes_ct_ortho(q); - for (i = 0; i < 4; i++) { - br_enc32le(out + 4 * i, q[2 * i]); - br_enc32le(out + 4 * i + 16, q[2 * i + 1]); - } - - for (i = 0; i < 32; i++) { - out[i] ^= in[i]; - } -} - -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_haraka256_sk(unsigned char *out, const unsigned char *in, const harakactx *state) { +void haraka256(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx) { uint32_t q[8], tmp_q; int i, j; @@ -935,7 +885,7 @@ void PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_haraka256_sk(unsigned char *out, cons br_aes_ct_bitslice_Sbox(q); shift_rows32(q); mix_columns32(q); - add_round_key32(q, state->tweaked256_rc32_sseed[2 * i + j]); + add_round_key32(q, ctx->tweaked256_rc32[2 * i + j]); } /* Mix states */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/haraka.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/haraka.h index cd8c98d0b1..737cb6065f 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/haraka.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/haraka.h @@ -1,40 +1,42 @@ -#ifndef PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_HARAKA_H -#define PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_HARAKA_H +#ifndef SPX_HARAKA_H +#define SPX_HARAKA_H -#include -#include - -typedef struct { - uint64_t tweaked512_rc64[10][8]; - uint32_t tweaked256_rc32[10][8]; - uint32_t tweaked256_rc32_sseed[10][8]; -} harakactx; +#include "context.h" +#include "params.h" /* Tweak constants with seed */ -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_tweak_constants( - harakactx *state, - const unsigned char *pk_seed, const unsigned char *sk_seed, - unsigned long long seed_length); +#define tweak_constants SPX_NAMESPACE(tweak_constants) +void tweak_constants(spx_ctx *ctx); /* Haraka Sponge */ -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_haraka_S_inc_init(uint8_t *s_inc); -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, const harakactx *state); -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_haraka_S_inc_finalize(uint8_t *s_inc); -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, const harakactx *state); -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_haraka_S( - unsigned char *out, unsigned long long outlen, - const unsigned char *in, unsigned long long inlen, const harakactx *state); +#define haraka_S_inc_init SPX_NAMESPACE(haraka_S_inc_init) +void haraka_S_inc_init(uint8_t *s_inc); +#define haraka_S_inc_absorb SPX_NAMESPACE(haraka_S_inc_absorb) +void haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, + const spx_ctx *ctx); +#define haraka_S_inc_finalize SPX_NAMESPACE(haraka_S_inc_finalize) +void haraka_S_inc_finalize(uint8_t *s_inc); +#define haraka_S_inc_squeeze SPX_NAMESPACE(haraka_S_inc_squeeze) +void haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, + const spx_ctx *ctx); +#define haraka_S SPX_NAMESPACE(haraka_S) +void haraka_S(unsigned char *out, unsigned long long outlen, + const unsigned char *in, unsigned long long inlen, + const spx_ctx *ctx); /* Applies the 512-bit Haraka permutation to in. */ -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_haraka512_perm(unsigned char *out, const unsigned char *in, const harakactx *state); +#define haraka512_perm SPX_NAMESPACE(haraka512_perm) +void haraka512_perm(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx); /* Implementation of Haraka-512 */ -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_haraka512(unsigned char *out, const unsigned char *in, const harakactx *state); +#define haraka512 SPX_NAMESPACE(haraka512) +void haraka512(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx); /* Implementation of Haraka-256 */ -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_haraka256(unsigned char *out, const unsigned char *in, const harakactx *state); - -/* Implementation of Haraka-256 using sk.seed constants */ -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_haraka256_sk(unsigned char *out, const unsigned char *in, const harakactx *state); +#define haraka256 SPX_NAMESPACE(haraka256) +void haraka256(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/haraka_offsets.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/haraka_offsets.h new file mode 100644 index 0000000000..7c062272a0 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/haraka_offsets.h @@ -0,0 +1,21 @@ +#ifndef HARAKA_OFFSETS_H_ +#define HARAKA_OFFSETS_H_ + +/* + * Offsets of various fields in the address structure when we use Haraka as + * the Sphincs+ hash function + */ + +#define SPX_OFFSET_LAYER 3 /* The byte used to specify the Merkle tree layer */ +#define SPX_OFFSET_TREE 8 /* The start of the 8 byte field used to specify the tree */ +#define SPX_OFFSET_TYPE 19 /* The byte used to specify the hash type (reason) */ +#define SPX_OFFSET_KP_ADDR2 22 /* The high byte used to specify the key pair (which one-time signature) */ +#define SPX_OFFSET_KP_ADDR1 23 /* The low byte used to specify the key pair */ +#define SPX_OFFSET_CHAIN_ADDR 27 /* The byte used to specify the chain address (which Winternitz chain) */ +#define SPX_OFFSET_HASH_ADDR 31 /* The byte used to specify the hash address (where in the Winternitz chain) */ +#define SPX_OFFSET_TREE_HGT 27 /* The byte used to specify the height of this node in the FORS or Merkle tree */ +#define SPX_OFFSET_TREE_INDEX 28 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ + +#define SPX_HARAKA 1 + +#endif /* HARAKA_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/hash.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/hash.h index e156b81110..f7c87d4c3c 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/hash.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/hash.h @@ -1,31 +1,28 @@ -#ifndef PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_HASH_H -#define PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_HASH_H - -#include "hash_state.h" +#ifndef SPX_HASH_H +#define SPX_HASH_H #include #include -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_initialize_hash_function( - hash_state *hash_state_seeded, - const unsigned char *pub_seed, const unsigned char *sk_seed); +#include "context.h" +#include "params.h" + +#define prf_addr SPX_NAMESPACE(prf_addr) +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]); -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_destroy_hash_function(hash_state *hash_state_seeded); +#define gen_message_random SPX_NAMESPACE(gen_message_random) +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded); +#define hash_message SPX_NAMESPACE(hash_message) +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/hash_haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/hash_haraka.c index 85c4bb2f54..750a67423b 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/hash_haraka.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/hash_haraka.c @@ -2,58 +2,44 @@ #include #include "address.h" -#include "haraka.h" -#include "hash.h" #include "params.h" #include "utils.h" -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_initialize_hash_function( - hash_state *hash_state_seeded, - const unsigned char *pub_seed, const unsigned char *sk_seed) { - PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_tweak_constants(hash_state_seeded, pub_seed, sk_seed, PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_N); -} - -/* The haraka implementation is stack based and won't be replaced in PQClean/OQS, - so we don't need to do anything */ -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_destroy_hash_function( - hash_state *hash_state_seeded) { // NOLINT(readability-non-const-parameter) - (void)hash_state_seeded; -} +#include "haraka.h" +#include "hash.h" /* - * Computes PRF(key, addr), given a secret key of PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_N bytes and an address + * Computes PRF(key, addr), given a secret key of SPX_N bytes and an address */ -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded) { - unsigned char buf[PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_ADDR_BYTES]; - /* Since PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_N may be smaller than 32, we need a temporary buffer. */ +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]) { + /* Since SPX_N may be smaller than 32, we need temporary buffers. */ unsigned char outbuf[32]; + unsigned char buf[64] = {0}; - (void)key; /* Suppress an 'unused parameter' warning. */ + memcpy(buf, addr, SPX_ADDR_BYTES); + memcpy(buf + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); - PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_addr_to_bytes(buf, addr); - PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_haraka256_sk(outbuf, buf, hash_state_seeded); - memcpy(out, outbuf, PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_N); + haraka512(outbuf, (const void *)buf, ctx); + memcpy(out, outbuf, SPX_N); } /** * Computes the message-dependent randomness R, using a secret seed and an * optional randomization value as well as the message. */ -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded) { +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { uint8_t s_inc[65]; - PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_haraka_S_inc_init(s_inc); - PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_haraka_S_inc_absorb(s_inc, sk_prf, PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_N, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_haraka_S_inc_absorb(s_inc, optrand, PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_N, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_haraka_S_inc_absorb(s_inc, m, mlen, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_haraka_S_inc_finalize(s_inc); - PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_haraka_S_inc_squeeze(R, PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_N, s_inc, hash_state_seeded); + haraka_S_inc_init(s_inc); + haraka_S_inc_absorb(s_inc, sk_prf, SPX_N, ctx); + haraka_S_inc_absorb(s_inc, optrand, SPX_N, ctx); + haraka_S_inc_absorb(s_inc, m, mlen, ctx); + haraka_S_inc_finalize(s_inc); + haraka_S_inc_squeeze(R, SPX_N, s_inc, ctx); } /** @@ -61,36 +47,35 @@ void PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_gen_message_random( * Outputs the message digest and the index of the leaf. The index is split in * the tree index and the leaf index, for convenient copying to an address. */ -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded) { -#define PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_TREE_BITS (PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_TREE_HEIGHT * (PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_D - 1)) -#define PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_TREE_BYTES ((PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_TREE_BITS + 7) / 8) -#define PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_LEAF_BITS PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_TREE_HEIGHT -#define PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_LEAF_BYTES ((PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_LEAF_BITS + 7) / 8) -#define PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_DGST_BYTES (PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_FORS_MSG_BYTES + PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_TREE_BYTES + PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_LEAF_BYTES) +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { +#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) +#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) +#define SPX_LEAF_BITS SPX_TREE_HEIGHT +#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) +#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) - unsigned char buf[PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_DGST_BYTES]; + unsigned char buf[SPX_DGST_BYTES]; unsigned char *bufp = buf; uint8_t s_inc[65]; - PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_haraka_S_inc_init(s_inc); - PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_haraka_S_inc_absorb(s_inc, R, PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_N, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_haraka_S_inc_absorb(s_inc, pk + PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_N, PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_N, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_haraka_S_inc_absorb(s_inc, m, mlen, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_haraka_S_inc_finalize(s_inc); - PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_haraka_S_inc_squeeze(buf, PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_DGST_BYTES, s_inc, hash_state_seeded); + haraka_S_inc_init(s_inc); + haraka_S_inc_absorb(s_inc, R, SPX_N, ctx); + haraka_S_inc_absorb(s_inc, pk + SPX_N, SPX_N, ctx); // Only absorb root part of pk + haraka_S_inc_absorb(s_inc, m, mlen, ctx); + haraka_S_inc_finalize(s_inc); + haraka_S_inc_squeeze(buf, SPX_DGST_BYTES, s_inc, ctx); + + memcpy(digest, bufp, SPX_FORS_MSG_BYTES); + bufp += SPX_FORS_MSG_BYTES; - memcpy(digest, bufp, PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_FORS_MSG_BYTES); - bufp += PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_FORS_MSG_BYTES; - *tree = PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_bytes_to_ull(bufp, PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_TREE_BYTES); - *tree &= (~(uint64_t)0) >> (64 - PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_TREE_BITS); - bufp += PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_TREE_BYTES; + *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); + *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); + bufp += SPX_TREE_BYTES; - *leaf_idx = (uint32_t)PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_bytes_to_ull( - bufp, PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_LEAF_BYTES); - *leaf_idx &= (~(uint32_t)0) >> (32 - PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_LEAF_BITS); + *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); + *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/hash_state.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/hash_state.h deleted file mode 100644 index 5adb1d9a22..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/hash_state.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef SPX_HASH_STATE_H -#define SPX_HASH_STATE_H - -/** - * Defines the type of the hash function state. - * - * Don't be fooled into thinking this instance of SPHINCS+ isn't stateless! - * - * From Section 7.2.2 from the SPHINCS+ round-2 specification: - * - * Each of the instances of the tweakable hash function take PK.seed as its - * first input, which is constant for a given key pair – and, thus, across - * a single signature. This leads to a lot of redundant computation. To remedy - * this, we pad PK.seed to the length of a full 64-byte SHA-256 input block. - * Because of the Merkle-DamgÃ¥rd construction that underlies SHA-256, this - * allows for reuse of the intermediate SHA-256 state after the initial call to - * the compression function which improves performance. - * - * We pass this hash state around in functions, because otherwise we need to - * have a global variable. - */ - -#include "haraka.h" -#define hash_state harakactx - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/merkle.c b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/merkle.c new file mode 100644 index 0000000000..0c1479fd93 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/merkle.c @@ -0,0 +1,59 @@ +#include +#include + +#include "address.h" +#include "merkle.h" +#include "params.h" +#include "utils.h" +#include "utilsx1.h" +#include "wots.h" +#include "wotsx1.h" + +/* + * This generates a Merkle signature (WOTS signature followed by the Merkle + * authentication path). This is in this file because most of the complexity + * is involved with the WOTS signature; the Merkle authentication path logic + * is mostly hidden in treehashx4 + */ +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf) { + unsigned char *auth_path = sig + SPX_WOTS_BYTES; + struct leaf_info_x1 info = { 0 }; + unsigned steps[ SPX_WOTS_LEN ]; + + info.wots_sig = sig; + chain_lengths(steps, root); + info.wots_steps = steps; + + set_type(&tree_addr[0], SPX_ADDR_TYPE_HASHTREE); + set_type(&info.pk_addr[0], SPX_ADDR_TYPE_WOTSPK); + copy_subtree_addr(&info.leaf_addr[0], wots_addr); + copy_subtree_addr(&info.pk_addr[0], wots_addr); + + info.wots_sign_leaf = idx_leaf; + + treehashx1(root, auth_path, ctx, + idx_leaf, 0, + SPX_TREE_HEIGHT, + wots_gen_leafx1, + tree_addr, &info); +} + +/* Compute root node of the top-most subtree. */ +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { + /* We do not need the auth path in key generation, but it simplifies the + code to have just one treehash routine that computes both root and path + in one function. */ + unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; + uint32_t top_tree_addr[8] = {0}; + uint32_t wots_addr[8] = {0}; + + set_layer_addr(top_tree_addr, SPX_D - 1); + set_layer_addr(wots_addr, SPX_D - 1); + + merkle_sign(auth_path, root, ctx, + wots_addr, top_tree_addr, + (uint32_t)~0 /* ~0 means "don't bother generating an auth path */ ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/merkle.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/merkle.h new file mode 100644 index 0000000000..769cf2e970 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/merkle.h @@ -0,0 +1,21 @@ +#ifndef MERKLE_H_ +#define MERKLE_H_ + +#include + +#include "context.h" +#include "params.h" + +/* Generate a Merkle signature (WOTS signature followed by the Merkle */ +/* authentication path) */ +#define merkle_sign SPX_NAMESPACE(merkle_sign) +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf); + +/* Compute the root node of the top-most subtree. */ +#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); + +#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/nistapi.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/nistapi.h new file mode 100644 index 0000000000..3cb71afad4 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/nistapi.h @@ -0,0 +1,87 @@ +#ifndef SPX_API_H +#define SPX_API_H + +#include +#include + +#include "params.h" + +#define CRYPTO_ALGNAME "SPHINCS+" + +#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES +#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES +#define CRYPTO_BYTES SPX_BYTES +#define CRYPTO_SEEDBYTES (3*SPX_N) + +/* + * Returns the length of a secret key, in bytes + */ +#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) +size_t crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) +size_t crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) +size_t crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) +size_t crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +#define crypto_sign SPX_NAMESPACE(crypto_sign) +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/params.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/params.h index 69d43e0c11..ffaa5ef9ed 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/params.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/params.h @@ -1,53 +1,56 @@ -#ifndef PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_PARAMS_H -#define PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_PARAMS_H +#ifndef SPX_PARAMS_H +#define SPX_PARAMS_H + +#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_##s /* Hash output length in bytes. */ -#define PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_N 24 +#define SPX_N 24 /* Height of the hypertree. */ -#define PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_FULL_HEIGHT 66 +#define SPX_FULL_HEIGHT 66 /* Number of subtree layer. */ -#define PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_D 22 +#define SPX_D 22 /* FORS tree dimensions. */ -#define PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_FORS_HEIGHT 8 -#define PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_FORS_TREES 33 +#define SPX_FORS_HEIGHT 8 +#define SPX_FORS_TREES 33 /* Winternitz parameter, */ -#define PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_WOTS_W 16 +#define SPX_WOTS_W 16 /* The hash function is defined by linking a different hash.c file, as opposed to setting a #define constant. */ /* For clarity */ -#define PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_ADDR_BYTES 32 +#define SPX_ADDR_BYTES 32 /* WOTS parameters. */ -#define PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_WOTS_LOGW 4 +#define SPX_WOTS_LOGW 4 -#define PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_WOTS_LEN1 (8 * PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_N / PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_WOTS_LOGW) +#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) -/* PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#define PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_WOTS_LEN2 3 +/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ +#define SPX_WOTS_LEN2 3 -#define PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_WOTS_LEN (PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_WOTS_LEN1 + PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_WOTS_LEN2) -#define PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_WOTS_BYTES (PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_WOTS_LEN * PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_N) -#define PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_WOTS_PK_BYTES PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_WOTS_BYTES +#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) +#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) +#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES /* Subtree size. */ -#define PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_TREE_HEIGHT (PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_FULL_HEIGHT / PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_D) +#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) + +//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT +// #error SPX_D should always divide SPX_FULL_HEIGHT +//#endif /* FORS parameters. */ -#define PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_FORS_MSG_BYTES ((PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_FORS_TREES + 7) / 8) -#define PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_FORS_BYTES ((PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_FORS_HEIGHT + 1) * PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_FORS_TREES * PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_N) -#define PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_FORS_PK_BYTES PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_N +#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) +#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) +#define SPX_FORS_PK_BYTES SPX_N /* Resulting SPX sizes. */ -#define PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_BYTES (PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_N + PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_FORS_BYTES + PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_D * PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_WOTS_BYTES +\ - PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_FULL_HEIGHT * PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_N) -#define PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_PK_BYTES (2 * PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_N) -#define PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_SK_BYTES (2 * PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_N + PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_PK_BYTES) - -/* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ -#define PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_OPTRAND_BYTES 32 +#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ + SPX_FULL_HEIGHT * SPX_N) +#define SPX_PK_BYTES (2 * SPX_N) +#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) + +#include "haraka_offsets.h" #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/sign.c b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/sign.c index eba10555e3..9d0c7d1b22 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/sign.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/sign.c @@ -3,72 +3,43 @@ #include #include "address.h" -#include "api.h" +#include "context.h" #include "fors.h" #include "hash.h" -#include "hash_state.h" +#include "merkle.h" +#include "nistapi.h" #include "params.h" #include "randombytes.h" #include "thash.h" #include "utils.h" #include "wots.h" -/** - * Computes the leaf at a given address. First generates the WOTS key pair, - * then computes leaf by hashing horizontally. - */ -static void wots_gen_leaf(unsigned char *leaf, const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx, const uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - unsigned char pk[PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_WOTS_BYTES]; - uint32_t wots_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_set_type( - wots_addr, PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_set_type( - wots_pk_addr, PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_ADDR_TYPE_WOTSPK); - - PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_set_keypair_addr( - wots_addr, addr_idx); - PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_wots_gen_pk( - pk, sk_seed, pub_seed, wots_addr, hash_state_seeded); - - PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_copy_keypair_addr( - wots_pk_addr, wots_addr); - PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_thash_WOTS_LEN( - leaf, pk, pub_seed, wots_pk_addr, hash_state_seeded); -} - /* * Returns the length of a secret key, in bytes */ -size_t PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_crypto_sign_secretkeybytes(void) { - return PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_CRYPTO_SECRETKEYBYTES; +size_t crypto_sign_secretkeybytes(void) { + return CRYPTO_SECRETKEYBYTES; } /* * Returns the length of a public key, in bytes */ -size_t PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_crypto_sign_publickeybytes(void) { - return PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_CRYPTO_PUBLICKEYBYTES; +size_t crypto_sign_publickeybytes(void) { + return CRYPTO_PUBLICKEYBYTES; } /* * Returns the length of a signature, in bytes */ -size_t PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_crypto_sign_bytes(void) { - return PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_CRYPTO_BYTES; +size_t crypto_sign_bytes(void) { + return CRYPTO_BYTES; } /* * Returns the length of the seed required to generate a key pair, in bytes */ -size_t PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_crypto_sign_seedbytes(void) { - return PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_CRYPTO_SEEDBYTES; +size_t crypto_sign_seedbytes(void) { + return CRYPTO_SEEDBYTES; } /* @@ -76,37 +47,30 @@ size_t PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_crypto_sign_seedbytes(void) { * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] * Format pk: [PUB_SEED || root] */ -int PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed) { - /* We do not need the auth path in key generation, but it simplifies the - code to have just one treehash routine that computes both root and path - in one function. */ - unsigned char auth_path[PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_TREE_HEIGHT * PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_N]; - uint32_t top_tree_addr[8] = {0}; - hash_state hash_state_seeded; - - PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_set_layer_addr( - top_tree_addr, PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_D - 1); - PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_set_type( - top_tree_addr, PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_ADDR_TYPE_HASHTREE); +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed) { + spx_ctx ctx; /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ - memcpy(sk, seed, PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_CRYPTO_SEEDBYTES); + memcpy(sk, seed, CRYPTO_SEEDBYTES); - memcpy(pk, sk + 2 * PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_N, PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_N); + memcpy(pk, sk + 2 * SPX_N, SPX_N); + + memcpy(ctx.pub_seed, pk, SPX_N); + memcpy(ctx.sk_seed, sk, SPX_N); /* This hook allows the hash function instantiation to do whatever preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_initialize_hash_function(&hash_state_seeded, pk, sk); + initialize_hash_function(&ctx); /* Compute root node of the top-most subtree. */ - PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_treehash_TREE_HEIGHT( - sk + 3 * PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_N, auth_path, sk, sk + 2 * PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_N, 0, 0, - wots_gen_leaf, top_tree_addr, &hash_state_seeded); + merkle_gen_root(sk + 3 * SPX_N, &ctx); + + // cleanup + free_hash_function(&ctx); - memcpy(pk + PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_N, sk + 3 * PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_N, PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_N); + memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); - PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_destroy_hash_function(&hash_state_seeded); return 0; } @@ -115,12 +79,10 @@ int PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_crypto_sign_seed_keypair( * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] * Format pk: [PUB_SEED || root] */ -int PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk) { - unsigned char seed[PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_CRYPTO_SEEDBYTES]; - randombytes(seed, PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_CRYPTO_SEEDBYTES); - PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_crypto_sign_seed_keypair( - pk, sk, seed); +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { + uint8_t seed[CRYPTO_SEEDBYTES]; + randombytes(seed, CRYPTO_SEEDBYTES); + crypto_sign_seed_keypair(pk, sk, seed); return 0; } @@ -128,101 +90,83 @@ int PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_crypto_sign_keypair( /** * Returns an array containing a detached signature. */ -int PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - const unsigned char *sk_seed = sk; - const unsigned char *sk_prf = sk + PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_N; - const unsigned char *pk = sk + 2 * PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_N; - const unsigned char *pub_seed = pk; - - unsigned char optrand[PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_N]; - unsigned char mhash[PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_FORS_MSG_BYTES]; - unsigned char root[PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_N]; +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk) { + spx_ctx ctx; + + const uint8_t *sk_prf = sk + SPX_N; + const uint8_t *pk = sk + 2 * SPX_N; + + uint8_t optrand[SPX_N]; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t root[SPX_N]; uint32_t i; uint64_t tree; uint32_t idx_leaf; uint32_t wots_addr[8] = {0}; uint32_t tree_addr[8] = {0}; - hash_state hash_state_seeded; + memcpy(ctx.sk_seed, sk, SPX_N); + memcpy(ctx.pub_seed, pk, SPX_N); /* This hook allows the hash function instantiation to do whatever preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_initialize_hash_function( - &hash_state_seeded, - pub_seed, sk_seed); + initialize_hash_function(&ctx); - PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_set_type( - wots_addr, PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_set_type( - tree_addr, PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_ADDR_TYPE_HASHTREE); + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); /* Optionally, signing can be made non-deterministic using optrand. This can help counter side-channel attacks that would benefit from getting a large number of traces when the signer uses the same nodes. */ - randombytes(optrand, PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_N); + randombytes(optrand, SPX_N); /* Compute the digest randomization value. */ - PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_gen_message_random( - sig, sk_prf, optrand, m, mlen, &hash_state_seeded); + gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); /* Derive the message digest and leaf index from R, PK and M. */ - PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_N; + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; - PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); /* Sign the message hash using FORS. */ - PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_fors_sign( - sig, root, mhash, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_FORS_BYTES; - - for (i = 0; i < PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_D; i++) { - PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_set_tree_addr(tree_addr, tree); - - PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); - - /* Compute a WOTS signature. */ - PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_wots_sign( - sig, root, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_WOTS_BYTES; - - /* Compute the authentication path for the used WOTS leaf. */ - PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_treehash_TREE_HEIGHT( - root, sig, sk_seed, pub_seed, idx_leaf, 0, - wots_gen_leaf, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_TREE_HEIGHT * PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_N; + fors_sign(sig, root, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); + sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_TREE_HEIGHT; + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; } - *siglen = PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_BYTES; + free_hash_function(&ctx); + + *siglen = SPX_BYTES; - PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_destroy_hash_function(&hash_state_seeded); return 0; } /** * Verifies a detached signature and message under a given public key. */ -int PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk) { - const unsigned char *pub_seed = pk; - const unsigned char *pub_root = pk + PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_N; - unsigned char mhash[PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_FORS_MSG_BYTES]; - unsigned char wots_pk[PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_WOTS_BYTES]; - unsigned char root[PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_N]; - unsigned char leaf[PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_N]; +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk) { + spx_ctx ctx; + const uint8_t *pub_root = pk + SPX_N; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t wots_pk[SPX_WOTS_BYTES]; + uint8_t root[SPX_N]; + uint8_t leaf[SPX_N]; unsigned int i; uint64_t tree; uint32_t idx_leaf; @@ -230,78 +174,66 @@ int PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_crypto_sign_verify( uint32_t tree_addr[8] = {0}; uint32_t wots_pk_addr[8] = {0}; - hash_state hash_state_seeded; - - if (siglen != PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_BYTES) { + if (siglen != SPX_BYTES) { return -1; } + memcpy(ctx.pub_seed, pk, SPX_N); + /* This hook allows the hash function instantiation to do whatever preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_initialize_hash_function( - &hash_state_seeded, - pub_seed, NULL); + initialize_hash_function(&ctx); - PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_set_type( - wots_addr, PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_set_type( - tree_addr, PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_ADDR_TYPE_HASHTREE); - PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_set_type( - wots_pk_addr, PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_ADDR_TYPE_WOTSPK); + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); /* Derive the message digest and leaf index from R || PK || M. */ - /* The additional PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_N is a result of the hash domain separator. */ - PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_N; + /* The additional SPX_N is a result of the hash domain separator. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; /* Layer correctly defaults to 0, so no need to set_layer_addr */ - PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); - PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_fors_pk_from_sig( - root, sig, mhash, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_FORS_BYTES; + fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; /* For each subtree.. */ - for (i = 0; i < PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_D; i++) { - PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_set_tree_addr(tree_addr, tree); + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); - PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); - PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_copy_keypair_addr( - wots_pk_addr, wots_addr); + copy_keypair_addr(wots_pk_addr, wots_addr); /* The WOTS public key is only correct if the signature was correct. */ /* Initially, root is the FORS pk, but on subsequent iterations it is the root of the subtree below the currently processed subtree. */ - PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_wots_pk_from_sig( - wots_pk, sig, root, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_WOTS_BYTES; + wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); + sig += SPX_WOTS_BYTES; /* Compute the leaf node using the WOTS public key. */ - PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_thash_WOTS_LEN( - leaf, wots_pk, pub_seed, wots_pk_addr, &hash_state_seeded); + thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); /* Compute the root node of this subtree. */ - PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_compute_root( - root, leaf, idx_leaf, 0, sig, PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_TREE_HEIGHT, - pub_seed, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_TREE_HEIGHT * PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_N; + compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, + &ctx, tree_addr); + sig += SPX_TREE_HEIGHT * SPX_N; /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_TREE_HEIGHT; + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; } - PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_destroy_hash_function(&hash_state_seeded); + // cleanup + free_hash_function(&ctx); + /* Check if the root node equals the root node in the public key. */ - if (memcmp(root, pub_root, PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_N) != 0) { + if (memcmp(root, pub_root, SPX_N) != 0) { return -1; } @@ -312,15 +244,14 @@ int PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_crypto_sign_verify( /** * Returns an array containing the signature followed by the message. */ -int PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk) { size_t siglen; - PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_crypto_sign_signature( - sm, &siglen, m, mlen, sk); + crypto_sign_signature(sm, &siglen, m, mlen, sk); - memmove(sm + PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_BYTES, m, mlen); + memmove(sm + SPX_BYTES, m, mlen); *smlen = siglen + mlen; return 0; @@ -329,28 +260,27 @@ int PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_crypto_sign( /** * Verifies a given signature-message pair under a given public key. */ -int PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk) { +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk) { /* The API caller does not necessarily know what size a signature should be - but SPHINCS+ signatures are always exactly PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_BYTES. */ - if (smlen < PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_BYTES) { + but SPHINCS+ signatures are always exactly SPX_BYTES. */ + if (smlen < SPX_BYTES) { memset(m, 0, smlen); *mlen = 0; return -1; } - *mlen = smlen - PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_BYTES; + *mlen = smlen - SPX_BYTES; - if (PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_crypto_sign_verify( - sm, PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_BYTES, sm + PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_BYTES, *mlen, pk)) { + if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { memset(m, 0, smlen); *mlen = 0; return -1; } /* If verification was successful, move the message to the right place. */ - memmove(m, sm + PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_BYTES, *mlen); + memmove(m, sm + SPX_BYTES, *mlen); return 0; } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/thash.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/thash.h index f1a704d209..8687ccfb4d 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/thash.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/thash.h @@ -1,28 +1,13 @@ -#ifndef PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_THASH_H -#define PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_THASH_H +#ifndef SPX_THASH_H +#define SPX_THASH_H -#include "hash_state.h" +#include "context.h" +#include "params.h" #include -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); +#define thash SPX_NAMESPACE(thash) +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/thash_haraka_simple.c b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/thash_haraka_simple.c index 7be07c39a4..207777bf8d 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/thash_haraka_simple.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/thash_haraka_simple.c @@ -4,80 +4,33 @@ #include "address.h" #include "params.h" #include "thash.h" +#include "utils.h" #include "haraka.h" /** - * Takes an array of inblocks concatenated arrays of PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_N bytes. + * Takes an array of inblocks concatenated arrays of SPX_N bytes. */ -static void PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_thash( - unsigned char *out, unsigned char *buf, - const unsigned char *in, unsigned int inblocks, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]) { + PQCLEAN_VLA(uint8_t, buf, SPX_ADDR_BYTES + inblocks * SPX_N); unsigned char outbuf[32]; unsigned char buf_tmp[64]; - (void)pub_seed; /* Suppress an 'unused parameter' warning. */ - if (inblocks == 1) { /* F function */ - /* Since PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_N may be smaller than 32, we need a temporary buffer. */ + /* Since SPX_N may be smaller than 32, we need a temporary buffer. */ memset(buf_tmp, 0, 64); - PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_addr_to_bytes(buf_tmp, addr); - memcpy(buf_tmp + PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_ADDR_BYTES, in, PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_N); + memcpy(buf_tmp, addr, 32); + memcpy(buf_tmp + SPX_ADDR_BYTES, in, SPX_N); - PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_haraka512(outbuf, buf_tmp, hash_state_seeded); - memcpy(out, outbuf, PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_N); + haraka512(outbuf, buf_tmp, ctx); + memcpy(out, outbuf, SPX_N); } else { /* All other tweakable hashes*/ - PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_addr_to_bytes(buf, addr); - memcpy(buf + PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_ADDR_BYTES, in, inblocks * PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_N); + memcpy(buf, addr, 32); + memcpy(buf + SPX_ADDR_BYTES, in, inblocks * SPX_N); - PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_haraka_S( - out, PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_N, buf, PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_N, hash_state_seeded); + haraka_S(out, SPX_N, buf, SPX_ADDR_BYTES + inblocks * SPX_N, ctx); } } - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_ADDR_BYTES + 1 * PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_N]; - PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_thash( - out, buf, in, 1, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_ADDR_BYTES + 2 * PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_N]; - PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_thash( - out, buf, in, 2, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_ADDR_BYTES + PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_WOTS_LEN * PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_N]; - PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_thash( - out, buf, in, PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_WOTS_LEN, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_ADDR_BYTES + PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_FORS_TREES * PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_N]; - PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_thash( - out, buf, in, PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_FORS_TREES, pub_seed, addr, hash_state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/utils.c b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/utils.c index 69a328d9a3..177b541fb9 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/utils.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/utils.c @@ -1,34 +1,41 @@ -#include #include +#include "utils.h" + #include "address.h" #include "hash.h" -#include "hash_state.h" #include "params.h" #include "thash.h" -#include "utils.h" /** * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. */ -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in) { +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in) { + int i; /* Iterate over out in decreasing order, for big-endianness. */ - for (size_t i = outlen; i > 0; i--) { - out[i - 1] = in & 0xff; + for (i = (signed int)outlen - 1; i >= 0; i--) { + out[i] = in & 0xff; in = in >> 8; } } +void u32_to_bytes(unsigned char *out, uint32_t in) { + out[0] = (unsigned char)(in >> 24); + out[1] = (unsigned char)(in >> 16); + out[2] = (unsigned char)(in >> 8); + out[3] = (unsigned char)in; +} + /** * Converts the inlen bytes in 'in' from big-endian byte order to an integer. */ -unsigned long long PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_bytes_to_ull( - const unsigned char *in, size_t inlen) { +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { unsigned long long retval = 0; + unsigned int i; - for (size_t i = 0; i < inlen; i++) { + for (i = 0; i < inlen; i++) { retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); } return retval; @@ -38,94 +45,80 @@ unsigned long long PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_bytes_to_ull( * Computes a root node given a leaf and an auth path. * Expects address to be complete other than the tree_height and tree_index. */ -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]) { uint32_t i; - unsigned char buffer[2 * PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_N]; + unsigned char buffer[2 * SPX_N]; /* If leaf_idx is odd (last bit = 1), current path element is a right child and auth_path has to go left. Otherwise it is the other way around. */ if (leaf_idx & 1) { - memcpy(buffer + PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_N, leaf, PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_N); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_N); + memcpy(buffer + SPX_N, leaf, SPX_N); + memcpy(buffer, auth_path, SPX_N); } else { - memcpy(buffer, leaf, PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_N); - memcpy(buffer + PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_N, auth_path, PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_N); + memcpy(buffer, leaf, SPX_N); + memcpy(buffer + SPX_N, auth_path, SPX_N); } - auth_path += PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_N; + auth_path += SPX_N; for (i = 0; i < tree_height - 1; i++) { leaf_idx >>= 1; idx_offset >>= 1; /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_set_tree_height(addr, i + 1); - PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_set_tree_index( - addr, leaf_idx + idx_offset); + set_tree_height(addr, i + 1); + set_tree_index(addr, leaf_idx + idx_offset); /* Pick the right or left neighbor, depending on parity of the node. */ if (leaf_idx & 1) { - PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_thash_2( - buffer + PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_N, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_N); + thash(buffer + SPX_N, buffer, 2, ctx, addr); + memcpy(buffer, auth_path, SPX_N); } else { - PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_thash_2( - buffer, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer + PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_N, auth_path, PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_N); + thash(buffer, buffer, 2, ctx, addr); + memcpy(buffer + SPX_N, auth_path, SPX_N); } - auth_path += PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_N; + auth_path += SPX_N; } /* The last iteration is exceptional; we do not copy an auth_path node. */ leaf_idx >>= 1; idx_offset >>= 1; - PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_set_tree_height(addr, tree_height); - PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_set_tree_index( - addr, leaf_idx + idx_offset); - PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_thash_2( - root, buffer, pub_seed, addr, hash_state_seeded); + set_tree_height(addr, tree_height); + set_tree_index(addr, leaf_idx + idx_offset); + thash(root, buffer, 2, ctx, addr); } /** * For a given leaf index, computes the authentication path and the resulting * root node using Merkle's TreeHash algorithm. * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_ADDR_TYPE_FORSTREE). + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). * Applies the offset idx_offset to indices before building addresses, so that * it is possible to continue counting indices across trees. */ -static void PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_treehash( - unsigned char *root, unsigned char *auth_path, - unsigned char *stack, unsigned int *heights, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - +void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx * /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]) { + PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); + PQCLEAN_VLA(unsigned int, heights, tree_height + 1); unsigned int offset = 0; uint32_t idx; uint32_t tree_idx; for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { /* Add the next leaf node to the stack. */ - gen_leaf(stack + offset * PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_N, - sk_seed, pub_seed, idx + idx_offset, tree_addr, - hash_state_seeded); + gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); offset++; heights[offset - 1] = 0; /* If this is a node we need for the auth path.. */ if ((leaf_idx ^ 0x1) == idx) { - memcpy(auth_path, stack + (offset - 1)*PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_N, PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_N); + memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); } /* While the top-most nodes are of equal height.. */ @@ -134,66 +127,22 @@ static void PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_treehash( tree_idx = (idx >> (heights[offset - 1] + 1)); /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_set_tree_height( - tree_addr, heights[offset - 1] + 1); - PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_set_tree_index( - tree_addr, tree_idx + (idx_offset >> (heights[offset - 1] + 1))); + set_tree_height(tree_addr, heights[offset - 1] + 1); + set_tree_index(tree_addr, + tree_idx + (idx_offset >> (heights[offset - 1] + 1))); /* Hash the top-most nodes from the stack together. */ - PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_thash_2( - stack + (offset - 2)*PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_N, stack + (offset - 2)*PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_N, - pub_seed, tree_addr, hash_state_seeded); + thash(stack + (offset - 2)*SPX_N, + stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); offset--; /* Note that the top-most node is now one layer higher. */ heights[offset - 1]++; /* If this is a node we need for the auth path.. */ if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_path + heights[offset - 1]*PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_N, - stack + (offset - 1)*PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_N, PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_N); + memcpy(auth_path + heights[offset - 1]*SPX_N, + stack + (offset - 1)*SPX_N, SPX_N); } } } - memcpy(root, stack, PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_N); -} - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_FORS_HEIGHT + 1)*PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_N]; - unsigned int heights[PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_FORS_HEIGHT + 1]; - - PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_FORS_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_TREE_HEIGHT + 1)*PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_N]; - unsigned int heights[PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_TREE_HEIGHT + 1]; - - PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_TREE_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); + memcpy(root, stack, SPX_N); } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/utils.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/utils.h index 759ddc8862..64f5d5a53a 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/utils.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/utils.h @@ -1,64 +1,58 @@ -#ifndef PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_UTILS_H -#define PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_UTILS_H +#ifndef SPX_UTILS_H +#define SPX_UTILS_H -#include "hash_state.h" -#include "params.h" -#include #include +#include "compat.h" +#include "context.h" +#include "params.h" + + +/* To support MSVC use alloca() instead of VLAs. See #20. */ + + /** * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. */ -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in); +#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in); +#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) +void u32_to_bytes(unsigned char *out, uint32_t in); /** * Converts the inlen bytes in 'in' from big-endian byte order to an integer. */ -unsigned long long PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_bytes_to_ull( - const unsigned char *in, size_t inlen); +#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); /** * Computes a root node given a leaf and an auth path. * Expects address to be complete other than the tree_height and tree_index. */ -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); +#define compute_root SPX_NAMESPACE(compute_root) +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]); /** * For a given leaf index, computes the authentication path and the resulting * root node using Merkle's TreeHash algorithm. * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_ADDR_TYPE_FORSTREE). + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). * Applies the offset idx_offset to indices before building addresses, so that * it is possible to continue counting indices across trees. */ -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); +#define treehash SPX_NAMESPACE(treehash) +void treehash(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx *ctx /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]); -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/utilsx1.c b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/utilsx1.c new file mode 100644 index 0000000000..fccb69b35d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/utilsx1.c @@ -0,0 +1,100 @@ +#include + +#include "utilsx1.h" + +#include "address.h" +#include "params.h" +#include "thash.h" +#include "utils.h" + +/* + * Generate the entire Merkle tree, computing the authentication path for + * leaf_idx, and the resulting root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) + * + * This expects tree_addr to be initialized to the addr structures for the + * Merkle tree nodes + * + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + * + * This works by using the standard Merkle tree building algorithm, + */ +void treehashx1(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, + uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* Where to write the leaves */, + const spx_ctx * /* ctx */, + uint32_t idx, void *info), + uint32_t tree_addr[8], + void *info) { + /* This is where we keep the intermediate nodes */ + PQCLEAN_VLA(uint8_t, stack, tree_height * SPX_N); + + uint32_t idx; + uint32_t max_idx = (uint32_t)((1 << tree_height) - 1); + for (idx = 0;; idx++) { + unsigned char current[2 * SPX_N]; /* Current logical node is at */ + /* index[SPX_N]. We do this to minimize the number of copies */ + /* needed during a thash */ + gen_leaf( ¤t[SPX_N], ctx, idx + idx_offset, + info ); + + /* Now combine the freshly generated right node with previously */ + /* generated left ones */ + uint32_t internal_idx_offset = idx_offset; + uint32_t internal_idx = idx; + uint32_t internal_leaf = leaf_idx; + uint32_t h; /* The height we are in the Merkle tree */ + for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { + + /* Check if we hit the top of the tree */ + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[SPX_N], SPX_N ); + return; + } + + /* + * Check if the node we have is a part of the + * authentication path; if it is, write it out + */ + if ((internal_idx ^ internal_leaf) == 0x01) { + memcpy( &auth_path[ h * SPX_N ], + ¤t[SPX_N], + SPX_N ); + } + + /* + * Check if we're at a left child; if so, stop going up the stack + * Exception: if we've reached the end of the tree, keep on going + * (so we combine the last 4 nodes into the one root node in two + * more iterations) + */ + if ((internal_idx & 1) == 0 && idx < max_idx) { + break; + } + + /* Ok, we're at a right node */ + /* Now combine the left and right logical nodes together */ + + /* Set the address of the node we're creating. */ + internal_idx_offset >>= 1; + set_tree_height(tree_addr, h + 1); + set_tree_index(tree_addr, internal_idx / 2 + internal_idx_offset ); + + unsigned char *left = &stack[h * SPX_N]; + memcpy( ¤t[0], left, SPX_N ); + thash( ¤t[1 * SPX_N], + ¤t[0 * SPX_N], + 2, ctx, tree_addr); + } + + /* We've hit a left child; save the current for when we get the */ + /* corresponding right right */ + memcpy( &stack[h * SPX_N], ¤t[SPX_N], SPX_N); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/utilsx1.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/utilsx1.h new file mode 100644 index 0000000000..e911d17d53 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/utilsx1.h @@ -0,0 +1,27 @@ +#ifndef SPX_UTILSX4_H +#define SPX_UTILSX4_H + +#include + +#include "context.h" +#include "params.h" + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +#define treehashx1 SPX_NAMESPACE(treehashx1) +void treehashx1(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* Where to write the leaf */, + const spx_ctx * /* ctx */, + uint32_t addr_idx, void *info), + uint32_t tree_addrx4[8], void *info); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/wots.c b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/wots.c index 2cdae33231..249717aaa8 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/wots.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/wots.c @@ -1,32 +1,20 @@ #include #include +#include "wots.h" +#include "wotsx1.h" + #include "address.h" #include "hash.h" -#include "hash_state.h" #include "params.h" #include "thash.h" #include "utils.h" -#include "wots.h" +#include "utilsx1.h" // TODO clarify address expectations, and make them more uniform. // TODO i.e. do we expect types to be set already? // TODO and do we expect modifications or copies? -/** - * Computes the starting value for a chain, i.e. the secret key. - * Expects the address to be complete up to the chain address. - */ -static void wots_gen_sk(unsigned char *sk, const unsigned char *sk_seed, - uint32_t wots_addr[8], - const hash_state *hash_state_seeded) { - /* Make sure that the hash address is actually zeroed. */ - PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_set_hash_addr(wots_addr, 0); - - /* Generate sk element. */ - PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_prf_addr(sk, sk_seed, wots_addr, hash_state_seeded); -} - /** * Computes the chaining function. * out and in have to be n-byte arrays. @@ -36,18 +24,16 @@ static void wots_gen_sk(unsigned char *sk, const unsigned char *sk_seed, */ static void gen_chain(unsigned char *out, const unsigned char *in, unsigned int start, unsigned int steps, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { + const spx_ctx *ctx, uint32_t addr[8]) { uint32_t i; /* Initialize out with the value at position 'start'. */ - memcpy(out, in, PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_N); + memcpy(out, in, SPX_N); /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_WOTS_W; i++) { - PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_set_hash_addr(addr, i); - PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_thash_1( - out, out, pub_seed, addr, hash_state_seeded); + for (i = start; i < (start + steps) && i < SPX_WOTS_W; i++) { + set_hash_addr(addr, i); + thash(out, out, 1, ctx, addr); } } @@ -56,13 +42,13 @@ static void gen_chain(unsigned char *out, const unsigned char *in, * Interprets an array of bytes as integers in base w. * This only works when log_w is a divisor of 8. */ -static void base_w(unsigned int *output, const size_t out_len, +static void base_w(unsigned int *output, const int out_len, const unsigned char *input) { - size_t in = 0; - size_t out = 0; + int in = 0; + int out = 0; unsigned char total = 0; - unsigned int bits = 0; - size_t consumed; + int bits = 0; + int consumed; for (consumed = 0; consumed < out_len; consumed++) { if (bits == 0) { @@ -70,8 +56,8 @@ static void base_w(unsigned int *output, const size_t out_len, in++; bits += 8; } - bits -= PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_WOTS_LOGW; - output[out] = (unsigned int)((total >> bits) & (PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_WOTS_W - 1)); + bits -= SPX_WOTS_LOGW; + output[out] = (total >> bits) & (SPX_WOTS_W - 1); out++; } } @@ -80,67 +66,25 @@ static void base_w(unsigned int *output, const size_t out_len, static void wots_checksum(unsigned int *csum_base_w, const unsigned int *msg_base_w) { unsigned int csum = 0; - unsigned char csum_bytes[(PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_WOTS_LEN2 * PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_WOTS_LOGW + 7) / 8]; + unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; unsigned int i; /* Compute checksum. */ - for (i = 0; i < PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_WOTS_LEN1; i++) { - csum += PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_WOTS_W - 1 - msg_base_w[i]; + for (i = 0; i < SPX_WOTS_LEN1; i++) { + csum += SPX_WOTS_W - 1 - msg_base_w[i]; } /* Convert checksum to base_w. */ /* Make sure expected empty zero bits are the least significant bits. */ - csum = csum << (8 - ((PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_WOTS_LEN2 * PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_WOTS_LOGW) % 8)); - PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_ull_to_bytes( - csum_bytes, sizeof(csum_bytes), csum); - base_w(csum_base_w, PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_WOTS_LEN2, csum_bytes); + csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); + ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); + base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); } /* Takes a message and derives the matching chain lengths. */ -static void chain_lengths(unsigned int *lengths, const unsigned char *msg) { - base_w(lengths, PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_WOTS_LEN1, msg); - wots_checksum(lengths + PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_WOTS_LEN1, lengths); -} - -/** - * WOTS key generation. Takes a 32 byte sk_seed, expands it to WOTS private key - * elements and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_wots_gen_pk( - unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - uint32_t i; - - for (i = 0; i < PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_WOTS_LEN; i++) { - PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_set_chain_addr(addr, i); - wots_gen_sk(pk + i * PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_N, sk_seed, addr, hash_state_seeded); - gen_chain(pk + i * PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_N, pk + i * PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_N, - 0, PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_WOTS_W - 1, pub_seed, addr, hash_state_seeded); - } -} - -/** - * Takes a n-byte message and the 32-byte sk_see to compute a signature 'sig'. - */ -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_wots_sign( - unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *hash_state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_WOTS_LEN; i++) { - PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_set_chain_addr(addr, i); - wots_gen_sk(sig + i * PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_N, sk_seed, addr, hash_state_seeded); - gen_chain(sig + i * PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_N, sig + i * PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_N, 0, lengths[i], pub_seed, addr, hash_state_seeded); - } +void chain_lengths(unsigned int *lengths, const unsigned char *msg) { + base_w(lengths, SPX_WOTS_LEN1, msg); + wots_checksum(lengths + SPX_WOTS_LEN1, lengths); } /** @@ -148,20 +92,17 @@ void PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_wots_sign( * * Writes the computed public key to 'pk'. */ -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_wots_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_WOTS_LEN]; +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]) { + unsigned int lengths[SPX_WOTS_LEN]; uint32_t i; chain_lengths(lengths, msg); - for (i = 0; i < PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_WOTS_LEN; i++) { - PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_set_chain_addr(addr, i); - gen_chain(pk + i * PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_N, sig + i * PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_N, - lengths[i], PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_WOTS_W - 1 - lengths[i], pub_seed, addr, - hash_state_seeded); + for (i = 0; i < SPX_WOTS_LEN; i++) { + set_chain_addr(addr, i); + gen_chain(pk + i * SPX_N, sig + i * SPX_N, + lengths[i], SPX_WOTS_W - 1 - lengths[i], ctx, addr); } } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/wots.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/wots.h index 92655c93c7..4e7692eeef 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/wots.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/wots.h @@ -1,41 +1,25 @@ -#ifndef PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_WOTS_H -#define PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_WOTS_H +#ifndef SPX_WOTS_H +#define SPX_WOTS_H -#include "hash_state.h" -#include "params.h" #include -/** - * WOTS key generation. Takes a 32 byte seed for the private key, expands it to - * a full WOTS private key and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_wots_gen_pk( - unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -/** - * Takes a n-byte message and the 32-byte seed for the private key to compute a - * signature that is placed at 'sig'. - */ -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_wots_sign( - unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *hash_state_seeded); +#include "context.h" +#include "params.h" /** * Takes a WOTS signature and an n-byte message, computes a WOTS public key. * * Writes the computed public key to 'pk'. */ -void PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_wots_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); +#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]); + +/* + * Compute the chain lengths needed for a given message hash + */ +#define chain_lengths SPX_NAMESPACE(chain_lengths) +void chain_lengths(unsigned int *lengths, const unsigned char *msg); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/wotsx1.c b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/wotsx1.c new file mode 100644 index 0000000000..3adec78dfb --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/wotsx1.c @@ -0,0 +1,76 @@ +#include +#include + +#include "wots.h" +#include "wotsx1.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "thash.h" +#include "utils.h" + +/* + * This generates a WOTS public key + * It also generates the WOTS signature if leaf_info indicates + * that we're signing with this WOTS key + */ +void wots_gen_leafx1(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info) { + struct leaf_info_x1 *info = v_info; + uint32_t *leaf_addr = info->leaf_addr; + uint32_t *pk_addr = info->pk_addr; + unsigned int i, k; + unsigned char pk_buffer[ SPX_WOTS_BYTES ]; + unsigned char *buffer; + uint32_t wots_k_mask; + + if (leaf_idx == info->wots_sign_leaf) { + /* We're traversing the leaf that's signing; generate the WOTS */ + /* signature */ + wots_k_mask = 0; + } else { + /* Nope, we're just generating pk's; turn off the signature logic */ + wots_k_mask = (uint32_t)~0; + } + + set_keypair_addr( leaf_addr, leaf_idx ); + set_keypair_addr( pk_addr, leaf_idx ); + + for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { + uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k to */ + /* the step if we're generating a signature, ~0 if we're not */ + + /* Start with the secret seed */ + set_chain_addr(leaf_addr, i); + set_hash_addr(leaf_addr, 0); + set_type(leaf_addr, SPX_ADDR_TYPE_WOTSPRF); + + prf_addr(buffer, ctx, leaf_addr); + + set_type(leaf_addr, SPX_ADDR_TYPE_WOTS); + + /* Iterate down the WOTS chain */ + for (k = 0;; k++) { + /* Check if this is the value that needs to be saved as a */ + /* part of the WOTS signature */ + if (k == wots_k) { + memcpy( info->wots_sig + i * SPX_N, buffer, SPX_N ); + } + + /* Check if we hit the top of the chain */ + if (k == SPX_WOTS_W - 1) { + break; + } + + /* Iterate one step on the chain */ + set_hash_addr(leaf_addr, k); + + thash(buffer, buffer, 1, ctx, leaf_addr); + } + } + + /* Do the final thash to generate the public keys */ + thash(dest, pk_buffer, SPX_WOTS_LEN, ctx, pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/wotsx1.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/wotsx1.h new file mode 100644 index 0000000000..e617929f96 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/wotsx1.h @@ -0,0 +1,39 @@ +#ifndef WOTSX1_H_ +#define WOTSX1_H_ + +#include + +#include "context.h" +#include "params.h" + +/* + * This is here to provide an interface to the internal wots_gen_leafx1 + * routine. While this routine is not referenced in the package outside of + * wots.c, it is called from the stand-alone benchmark code to characterize + * the performance + */ +struct leaf_info_x1 { + unsigned char *wots_sig; + uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ + uint32_t *wots_steps; + uint32_t leaf_addr[8]; + uint32_t pk_addr[8]; +}; + +/* Macro to set the leaf_info to something 'benign', that is, it would */ +/* run with the same time as it does during the real signing process */ +/* Used only by the benchmark code */ +#define INITIALIZE_LEAF_INFO_X1(info, addr, step_buffer) { \ + (info).wots_sig = 0; \ + (info).wots_sign_leaf = ~0; \ + (info).wots_steps = step_buffer; \ + memcpy( &(info).leaf_addr[0], (addr), 32 ); \ + memcpy( &(info).pk_addr[0], (addr), 32 ); \ + } + +#define wots_gen_leafx1 SPX_NAMESPACE(wots_gen_leafx1) +void wots_gen_leafx1(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info); + +#endif /* WOTSX1_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/address.c b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/address.c index 7545f3d060..d49d9f3b6b 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/address.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/address.c @@ -1,78 +1,95 @@ #include +#include #include "address.h" #include "params.h" #include "utils.h" -void PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]) { - int i; - - for (i = 0; i < 8; i++) { - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_ull_to_bytes( - bytes + i * 4, 4, addr[i]); - } -} - -void PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_set_layer_addr( - uint32_t addr[8], uint32_t layer) { - addr[0] = layer; +/* + * Specify which level of Merkle tree (the "layer") we're working on + */ +void set_layer_addr(uint32_t addr[8], uint32_t layer) { + ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; } -void PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_set_tree_addr( - uint32_t addr[8], uint64_t tree) { - addr[1] = 0; - addr[2] = (uint32_t) (tree >> 32); - addr[3] = (uint32_t) tree; +/* + * Specify which Merkle tree within the level (the "tree address") we're working on + */ +void set_tree_addr(uint32_t addr[8], uint64_t tree) { + ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); } -void PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_set_type( - uint32_t addr[8], uint32_t type) { - addr[4] = type; +/* + * Specify the reason we'll use this address structure for, that is, what + * hash will we compute with it. This is used so that unrelated types of + * hashes don't accidentally get the same address structure. The type will be + * one of the SPX_ADDR_TYPE constants + */ +void set_type(uint32_t addr[8], uint32_t type) { + ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; } -void PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; +/* + * Copy the layer and tree fields of the address structure. This is used + * when we're doing multiple types of hashes within the same Merkle tree + */ +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); } /* These functions are used for OTS addresses. */ -void PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_set_keypair_addr( - uint32_t addr[8], uint32_t keypair) { - addr[5] = keypair; +/* + * Specify which Merkle leaf we're working on; that is, which OTS keypair + * we're talking about. + */ +void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { + /* We have > 256 OTS at the bottom of the Merkle tree; to specify */ + /* which one, we'd need to express it in two bytes */ + ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR2] = (unsigned char)(keypair >> 8); + ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; } -void PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; - out[5] = in[5]; +/* + * Copy the layer, tree and keypair fields of the address structure. This is + * used when we're doing multiple things within the same OTS keypair + */ +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); + ((unsigned char *)out)[SPX_OFFSET_KP_ADDR2] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR2]; + ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; } -void PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_set_chain_addr( - uint32_t addr[8], uint32_t chain) { - addr[6] = chain; +/* + * Specify which Merkle chain within the OTS we're working with + * (the chain address) + */ +void set_chain_addr(uint32_t addr[8], uint32_t chain) { + ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; } -void PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_set_hash_addr( - uint32_t addr[8], uint32_t hash) { - addr[7] = hash; +/* + * Specify where in the Merkle chain we are +* (the hash address) + */ +void set_hash_addr(uint32_t addr[8], uint32_t hash) { + ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; } /* These functions are used for all hash tree addresses (including FORS). */ -void PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_set_tree_height( - uint32_t addr[8], uint32_t tree_height) { - addr[6] = tree_height; +/* + * Specify the height of the node in the Merkle/FORS tree we are in + * (the tree height) + */ +void set_tree_height(uint32_t addr[8], uint32_t tree_height) { + ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; } -void PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_set_tree_index( - uint32_t addr[8], uint32_t tree_index) { - addr[7] = tree_index; +/* + * Specify the distance from the left edge of the node in the Merkle/FORS tree + * (the tree index) + */ +void set_tree_index(uint32_t addr[8], uint32_t tree_index) { + u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/address.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/address.h index 8c7e2d0e88..24a84eb40c 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/address.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/address.h @@ -1,50 +1,52 @@ -#ifndef PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_ADDRESS_H -#define PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_ADDRESS_H +#ifndef SPX_ADDRESS_H +#define SPX_ADDRESS_H #include -#define PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_ADDR_TYPE_WOTS 0 -#define PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_ADDR_TYPE_WOTSPK 1 -#define PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_ADDR_TYPE_HASHTREE 2 -#define PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_ADDR_TYPE_FORSTREE 3 -#define PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_ADDR_TYPE_FORSPK 4 +#include "params.h" -void PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]); +/* The hash types that are passed to set_type */ +#define SPX_ADDR_TYPE_WOTS 0 +#define SPX_ADDR_TYPE_WOTSPK 1 +#define SPX_ADDR_TYPE_HASHTREE 2 +#define SPX_ADDR_TYPE_FORSTREE 3 +#define SPX_ADDR_TYPE_FORSPK 4 +#define SPX_ADDR_TYPE_WOTSPRF 5 +#define SPX_ADDR_TYPE_FORSPRF 6 -void PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_set_layer_addr( - uint32_t addr[8], uint32_t layer); +#define set_layer_addr SPX_NAMESPACE(set_layer_addr) +void set_layer_addr(uint32_t addr[8], uint32_t layer); -void PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_set_tree_addr( - uint32_t addr[8], uint64_t tree); +#define set_tree_addr SPX_NAMESPACE(set_tree_addr) +void set_tree_addr(uint32_t addr[8], uint64_t tree); -void PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_set_type( - uint32_t addr[8], uint32_t type); +#define set_type SPX_NAMESPACE(set_type) +void set_type(uint32_t addr[8], uint32_t type); /* Copies the layer and tree part of one address into the other */ -void PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]); +#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); /* These functions are used for WOTS and FORS addresses. */ -void PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_set_keypair_addr( - uint32_t addr[8], uint32_t keypair); +#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) +void set_keypair_addr(uint32_t addr[8], uint32_t keypair); -void PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_set_chain_addr( - uint32_t addr[8], uint32_t chain); +#define set_chain_addr SPX_NAMESPACE(set_chain_addr) +void set_chain_addr(uint32_t addr[8], uint32_t chain); -void PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_set_hash_addr( - uint32_t addr[8], uint32_t hash); +#define set_hash_addr SPX_NAMESPACE(set_hash_addr) +void set_hash_addr(uint32_t addr[8], uint32_t hash); -void PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]); +#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); /* These functions are used for all hash tree addresses (including FORS). */ -void PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_set_tree_height( - uint32_t addr[8], uint32_t tree_height); +#define set_tree_height SPX_NAMESPACE(set_tree_height) +void set_tree_height(uint32_t addr[8], uint32_t tree_height); -void PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_set_tree_index( - uint32_t addr[8], uint32_t tree_index); +#define set_tree_index SPX_NAMESPACE(set_tree_index) +void set_tree_index(uint32_t addr[8], uint32_t tree_index); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/api.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/api.h index e2b3525593..b435391496 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/api.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/api.h @@ -4,15 +4,13 @@ #include #include - - -#define PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_CRYPTO_ALGNAME "SPHINCS+" +#define PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_CRYPTO_ALGNAME "SPHINCS+-haraka-192s-robust" #define PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_CRYPTO_SECRETKEYBYTES 96 #define PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_CRYPTO_PUBLICKEYBYTES 48 -#define PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_CRYPTO_BYTES 16224 -#define PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_CRYPTO_SEEDBYTES 72 +#define PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_CRYPTO_BYTES 16224 +#define PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_CRYPTO_SEEDBYTES 72 /* * Returns the length of a secret key, in bytes @@ -39,43 +37,41 @@ size_t PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_crypto_sign_seedbytes(void); * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] * Format pk: [root || PUB_SEED] */ -int PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed); +int PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); /* * Generates a SPHINCS+ key pair. * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] * Format pk: [root || PUB_SEED] */ -int PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk); +int PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); /** * Returns an array containing a detached signature. */ -int PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk); +int PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); /** * Verifies a detached signature and message under a given public key. */ -int PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk); +int PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, + const uint8_t *pk); /** * Returns an array containing the signature followed by the message. */ -int PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk); +int PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); /** * Verifies a given signature-message pair under a given public key. */ -int PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk); - +int PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/context.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/context.h new file mode 100644 index 0000000000..f03446b9cb --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/context.h @@ -0,0 +1,22 @@ +#ifndef SPX_CONTEXT_H +#define SPX_CONTEXT_H + +#include + +#include "immintrin.h" +#include "params.h" + +typedef struct { + uint8_t pub_seed[SPX_N]; + uint8_t sk_seed[SPX_N]; + + __m128i rc[40]; +} spx_ctx; + +#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) +void initialize_hash_function(spx_ctx *ctx); + +#define free_hash_function SPX_NAMESPACE(free_hash_function) +void free_hash_function(spx_ctx *ctx); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/context_haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/context_haraka.c new file mode 100644 index 0000000000..f1cd7e3664 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/context_haraka.c @@ -0,0 +1,11 @@ +#include "context.h" +#include "haraka.h" + +void initialize_hash_function(spx_ctx *ctx) { + tweak_constants(ctx); +} + +// we don't support heap-based haraka right now +void free_hash_function(spx_ctx *ctx) { + (void)ctx; // suppress unused variable warnings +} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/fors.c b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/fors.c index 3dbed0b0ed..f1b0639cfc 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/fors.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/fors.c @@ -2,8 +2,9 @@ #include #include -#include "address.h" #include "fors.h" + +#include "address.h" #include "hash.h" #include "hashx4.h" #include "thash.h" @@ -11,19 +12,24 @@ #include "utils.h" #include "utilsx4.h" +static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + prf_addr(sk, ctx, fors_leaf_addr); +} + static void fors_gen_skx4(unsigned char *sk0, unsigned char *sk1, unsigned char *sk2, - unsigned char *sk3, const unsigned char *sk_seed, - uint32_t fors_leaf_addrx4[4 * 8], - const hash_state *state_seeded) { - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_prf_addrx4(sk0, sk1, sk2, sk3, sk_seed, fors_leaf_addrx4, state_seeded); + unsigned char *sk3, const spx_ctx *ctx, + uint32_t fors_leaf_addrx4[4 * 8]) { + prf_addrx4(sk0, sk1, sk2, sk3, + ctx, fors_leaf_addrx4); } static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, - const unsigned char *pub_seed, - uint32_t fors_leaf_addr[8], const hash_state *state_seeded) { - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_thash_1(leaf, sk, pub_seed, fors_leaf_addr, state_seeded); + const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + thash(leaf, sk, 1, ctx, fors_leaf_addr); } static void fors_sk_to_leafx4(unsigned char *leaf0, @@ -34,57 +40,64 @@ static void fors_sk_to_leafx4(unsigned char *leaf0, const unsigned char *sk1, const unsigned char *sk2, const unsigned char *sk3, - const unsigned char *pub_seed, - uint32_t fors_leaf_addrx4[4 * 8], - const hash_state *state_seeded) { - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_thashx4_1(leaf0, leaf1, leaf2, leaf3, - sk0, sk1, sk2, sk3, pub_seed, fors_leaf_addrx4, state_seeded); + const spx_ctx *ctx, + uint32_t fors_leaf_addrx4[4 * 8]) { + thashx4(leaf0, leaf1, leaf2, leaf3, + sk0, sk1, sk2, sk3, + 1, ctx, fors_leaf_addrx4); } -static void fors_gen_leafx4(unsigned char *leaf0, - unsigned char *leaf1, - unsigned char *leaf2, - unsigned char *leaf3, - const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx0, - uint32_t addr_idx1, - uint32_t addr_idx2, - uint32_t addr_idx3, - const uint32_t fors_tree_addr[8], - const hash_state *state_seeded) { - uint32_t fors_leaf_addrx4[4 * 8] = {0}; +struct fors_gen_leaf_info { + uint32_t leaf_addrx[4 * 8]; +}; + +static void fors_gen_leafx4(unsigned char *leaf, + const spx_ctx *ctx, + uint32_t addr_idx, void *info) { + struct fors_gen_leaf_info *fors_info = info; + uint32_t *fors_leaf_addrx4 = fors_info->leaf_addrx; unsigned int j; - /* Only copy the parts that must be kept in fors_leaf_addrx4. */ + /* Only set the parts that the caller doesn't set */ for (j = 0; j < 4; j++) { - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_copy_keypair_addr(fors_leaf_addrx4 + j * 8, fors_tree_addr); - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_set_type(fors_leaf_addrx4 + j * 8, PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_ADDR_TYPE_FORSTREE); + set_tree_index(fors_leaf_addrx4 + j * 8, addr_idx + j); + set_type(fors_leaf_addrx4 + j * 8, SPX_ADDR_TYPE_FORSPRF); } - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_set_tree_index(fors_leaf_addrx4 + 0 * 8, addr_idx0); - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_set_tree_index(fors_leaf_addrx4 + 1 * 8, addr_idx1); - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_set_tree_index(fors_leaf_addrx4 + 2 * 8, addr_idx2); - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_set_tree_index(fors_leaf_addrx4 + 3 * 8, addr_idx3); + fors_gen_skx4(leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + leaf + 2 * SPX_N, + leaf + 3 * SPX_N, + ctx, fors_leaf_addrx4); + + for (j = 0; j < 4; j++) { + set_type(fors_leaf_addrx4 + j * 8, SPX_ADDR_TYPE_FORSTREE); + } - fors_gen_skx4(leaf0, leaf1, leaf2, leaf3, sk_seed, fors_leaf_addrx4, state_seeded); - fors_sk_to_leafx4(leaf0, leaf1, leaf2, leaf3, - leaf0, leaf1, leaf2, leaf3, pub_seed, fors_leaf_addrx4, state_seeded); + fors_sk_to_leafx4(leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + leaf + 2 * SPX_N, + leaf + 3 * SPX_N, + leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + leaf + 2 * SPX_N, + leaf + 3 * SPX_N, + ctx, fors_leaf_addrx4); } /** - * Interprets m as PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_FORS_HEIGHT-bit unsigned integers. - * Assumes m contains at least PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_FORS_TREES bits. - * Assumes indices has space for PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_FORS_TREES integers. + * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + * Assumes indices has space for SPX_FORS_TREES integers. */ static void message_to_indices(uint32_t *indices, const unsigned char *m) { unsigned int i, j; unsigned int offset = 0; - for (i = 0; i < PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_FORS_TREES; i++) { + for (i = 0; i < SPX_FORS_TREES; i++) { indices[i] = 0; - for (j = 0; j < PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_FORS_HEIGHT; j++) { - indices[i] ^= (((uint32_t)m[offset >> 3] >> (offset & 0x7)) & 0x1) << j; + for (j = 0; j < SPX_FORS_HEIGHT; j++) { + indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); offset++; } } @@ -92,68 +105,53 @@ static void message_to_indices(uint32_t *indices, const unsigned char *m) { /** * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_FORS_TREES bits. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. */ -void PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *state_seeded) { - /* Round up to multiple of 4 to prevent out-of-bounds for x4 parallelism */ - uint32_t indices[(PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_FORS_TREES + 3) & ~3] = {0}; - unsigned char roots[((PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_FORS_TREES + 3) & ~3) * PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N]; - /* Sign to a buffer, since we may not have a nice multiple of 4 and would - otherwise overrun the signature. */ - unsigned char sigbufx4[4 * PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N * (1 + PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_FORS_HEIGHT)]; - uint32_t fors_tree_addrx4[4 * 8] = {0}; +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + uint32_t fors_tree_addr[4 * 8] = {0}; + struct fors_gen_leaf_info fors_info = {0}; + uint32_t *fors_leaf_addr = fors_info.leaf_addrx; uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset[4] = {0}; - unsigned int i, j; + uint32_t idx_offset; + unsigned int i; - for (j = 0; j < 4; j++) { - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_copy_keypair_addr(fors_tree_addrx4 + j * 8, fors_addr); - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_set_type(fors_tree_addrx4 + j * 8, PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_ADDR_TYPE_FORSTREE); + for (i = 0; i < 4; i++) { + copy_keypair_addr(fors_tree_addr + 8 * i, fors_addr); + set_type(fors_tree_addr + 8 * i, SPX_ADDR_TYPE_FORSTREE); + copy_keypair_addr(fors_leaf_addr + 8 * i, fors_addr); } - - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_copy_keypair_addr(fors_pk_addr, fors_addr); - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_set_type(fors_pk_addr, PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_ADDR_TYPE_FORSPK); + copy_keypair_addr(fors_pk_addr, fors_addr); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); message_to_indices(indices, m); - for (i = 0; i < ((PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_FORS_TREES + 3) & ~0x3); i += 4) { - for (j = 0; j < 4; j++) { - if (i + j < PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_FORS_TREES) { - idx_offset[j] = (i + j) * (1 << PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_FORS_HEIGHT); + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_set_tree_height(fors_tree_addrx4 + j * 8, 0); - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_set_tree_index(fors_tree_addrx4 + j * 8, - indices[i + j] + idx_offset[j]); - } - } + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); - /* Include the secret key part that produces the selected leaf nodes. */ - fors_gen_skx4(sigbufx4 + 0 * PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N, - sigbufx4 + 1 * PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N, - sigbufx4 + 2 * PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N, - sigbufx4 + 3 * PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N, - sk_seed, fors_tree_addrx4, state_seeded); - - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_treehashx4_FORS_HEIGHT(roots + i * PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N, sigbufx4 + 4 * PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N, sk_seed, pub_seed, - &indices[i], idx_offset, fors_gen_leafx4, fors_tree_addrx4, - state_seeded); - - for (j = 0; j < 4; j++) { - if (i + j < PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_FORS_TREES) { - memcpy(sig, sigbufx4 + j * PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N, PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N); - memcpy(sig + PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N, - sigbufx4 + 4 * PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N + j * PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N * PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_FORS_HEIGHT, - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N * PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_FORS_HEIGHT); - sig += PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N * (1 + PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_FORS_HEIGHT); - } - } + /* Include the secret key part that produces the selected leaf node. */ + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); + fors_gen_sk(sig, ctx, fors_tree_addr); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + sig += SPX_N; + + /* Compute the authentication path for this leaf node. */ + treehashx4(roots + i * SPX_N, sig, ctx, + indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx4, + fors_tree_addr, &fors_info); + + sig += SPX_N * SPX_FORS_HEIGHT; } /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_thash_FORS_TREES(pk, roots, pub_seed, fors_pk_addr, state_seeded); + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); } /** @@ -161,46 +159,44 @@ void PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_fors_sign(unsigned char *sig, unsigne * This can be used for verification by comparing to a known public key, or to * subsequently verify a signature on the derived public key. The latter is the * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_FORS_TREES bits. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. */ -void PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, - const uint32_t fors_addr[8], - const hash_state *state_seeded) { - uint32_t indices[PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_FORS_TREES]; - unsigned char roots[PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_FORS_TREES * PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N]; - unsigned char leaf[PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N]; +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + unsigned char leaf[SPX_N]; uint32_t fors_tree_addr[8] = {0}; uint32_t fors_pk_addr[8] = {0}; uint32_t idx_offset; unsigned int i; - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_copy_keypair_addr(fors_tree_addr, fors_addr); - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_copy_keypair_addr(fors_pk_addr, fors_addr); + copy_keypair_addr(fors_tree_addr, fors_addr); + copy_keypair_addr(fors_pk_addr, fors_addr); - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_set_type(fors_tree_addr, PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_set_type(fors_pk_addr, PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_ADDR_TYPE_FORSPK); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); message_to_indices(indices, m); - for (i = 0; i < PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_FORS_TREES; i++) { - idx_offset = i * (1 << PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_FORS_HEIGHT); + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_set_tree_height(fors_tree_addr, 0); - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_set_tree_index(fors_tree_addr, indices[i] + idx_offset); + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); /* Derive the leaf from the included secret key part. */ - fors_sk_to_leaf(leaf, sig, pub_seed, fors_tree_addr, state_seeded); - sig += PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N; + fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); + sig += SPX_N; /* Derive the corresponding root node of this tree. */ - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_compute_root(roots + i * PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N, leaf, indices[i], idx_offset, - sig, PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_FORS_HEIGHT, pub_seed, fors_tree_addr, - state_seeded); - sig += PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N * PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_FORS_HEIGHT; + compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, + sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); + sig += SPX_N * SPX_FORS_HEIGHT; } /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_thash_FORS_TREES(pk, roots, pub_seed, fors_pk_addr, state_seeded); + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/fors.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/fors.h index 7e493afea7..509140a178 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/fors.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/fors.h @@ -1,32 +1,32 @@ -#ifndef PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_FORS_H -#define PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_FORS_H +#ifndef SPX_FORS_H +#define SPX_FORS_H #include -#include "hash_state.h" +#include "context.h" #include "params.h" /** * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_FORS_TREES bits. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. */ -void PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_fors_sign( - unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *hash_state_seeded); +#define fors_sign SPX_NAMESPACE(fors_sign) +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); /** * Derives the FORS public key from a signature. * This can be used for verification by comparing to a known public key, or to * subsequently verify a signature on the derived public key. The latter is the * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_FORS_TREES bits. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. */ -void PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_fors_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, const uint32_t fors_addr[8], - const hash_state *hash_state_seeded); +#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/haraka.c index 6186398bf2..b414b691d7 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/haraka.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/haraka.c @@ -8,10 +8,12 @@ Plain C implementation of the Haraka256 and Haraka512 permutations. #include #include "haraka.h" +#include "harakax4.h" +#include "utils.h" #define HARAKAS_RATE 32 -#define u64 uint64_t +#define u64 unsigned long #define u128 __m128i #define LOAD(src) _mm_loadu_si128((u128 *)(src)) @@ -20,7 +22,7 @@ Plain C implementation of the Haraka256 and Haraka512 permutations. #define XOR128(a, b) _mm_xor_si128(a, b) #define AES2(s0, s1, rci) \ - (s0) = _mm_aesenc_si128(s0, *(rci)); \ + s0 = _mm_aesenc_si128(s0, *(rci)); \ (s1) = _mm_aesenc_si128(s1, *((rci) + 1)); \ (s0) = _mm_aesenc_si128(s0, *((rci) + 2)); \ (s1) = _mm_aesenc_si128(s1, *((rci) + 3)); @@ -32,7 +34,7 @@ Plain C implementation of the Haraka256 and Haraka512 permutations. AES2((s3)[0], (s3)[1], rci); #define AES4(s0, s1, s2, s3, rci) \ - (s0) = _mm_aesenc_si128(s0, *(rci)); \ + s0 = _mm_aesenc_si128(s0, *(rci)); \ (s1) = _mm_aesenc_si128(s1, *((rci) + 1)); \ (s2) = _mm_aesenc_si128(s2, *((rci) + 2)); \ (s3) = _mm_aesenc_si128(s3, *((rci) + 3)); \ @@ -68,17 +70,17 @@ Plain C implementation of the Haraka256 and Haraka512 permutations. _mm_storeu_si128((u128 *)((out) + 16), \ _mm_castpd_si128(_mm_shuffle_pd(_mm_castsi128_pd(s2), _mm_castsi128_pd(s3), 0))); -static void load_haraka_constants(u128 rc[40]) { - rc[ 0] = _mm_set_epi32((int)0x0684704c, (int)0xe620c00a, (int)0xb2c5fef0, (int)0x75817b9d); - rc[ 1] = _mm_set_epi32((int)0x8b66b4e1, (int)0x88f3a06b, (int)0x640f6ba4, (int)0x2f08f717); - rc[ 2] = _mm_set_epi32((int)0x3402de2d, (int)0x53f28498, (int)0xcf029d60, (int)0x9f029114); - rc[ 3] = _mm_set_epi32((int)0x0ed6eae6, (int)0x2e7b4f08, (int)0xbbf3bcaf, (int)0xfd5b4f79); - rc[ 4] = _mm_set_epi32((int)0xcbcfb0cb, (int)0x4872448b, (int)0x79eecd1c, (int)0xbe397044); - rc[ 5] = _mm_set_epi32((int)0x7eeacdee, (int)0x6e9032b7, (int)0x8d5335ed, (int)0x2b8a057b); - rc[ 6] = _mm_set_epi32((int)0x67c28f43, (int)0x5e2e7cd0, (int)0xe2412761, (int)0xda4fef1b); - rc[ 7] = _mm_set_epi32((int)0x2924d9b0, (int)0xafcacc07, (int)0x675ffde2, (int)0x1fc70b3b); - rc[ 8] = _mm_set_epi32((int)0xab4d63f1, (int)0xe6867fe9, (int)0xecdb8fca, (int)0xb9d465ee); - rc[ 9] = _mm_set_epi32((int)0x1c30bf84, (int)0xd4b7cd64, (int)0x5b2a404f, (int)0xad037e33); +static void load_haraka_constants(u128 *rc) { + rc[0] = _mm_set_epi32((int)0x0684704c, (int)0xe620c00a, (int)0xb2c5fef0, (int)0x75817b9d); + rc[1] = _mm_set_epi32((int)0x8b66b4e1, (int)0x88f3a06b, (int)0x640f6ba4, (int)0x2f08f717); + rc[2] = _mm_set_epi32((int)0x3402de2d, (int)0x53f28498, (int)0xcf029d60, (int)0x9f029114); + rc[3] = _mm_set_epi32((int)0x0ed6eae6, (int)0x2e7b4f08, (int)0xbbf3bcaf, (int)0xfd5b4f79); + rc[4] = _mm_set_epi32((int)0xcbcfb0cb, (int)0x4872448b, (int)0x79eecd1c, (int)0xbe397044); + rc[5] = _mm_set_epi32((int)0x7eeacdee, (int)0x6e9032b7, (int)0x8d5335ed, (int)0x2b8a057b); + rc[6] = _mm_set_epi32((int)0x67c28f43, (int)0x5e2e7cd0, (int)0xe2412761, (int)0xda4fef1b); + rc[7] = _mm_set_epi32((int)0x2924d9b0, (int)0xafcacc07, (int)0x675ffde2, (int)0x1fc70b3b); + rc[8] = _mm_set_epi32((int)0xab4d63f1, (int)0xe6867fe9, (int)0xecdb8fca, (int)0xb9d465ee); + rc[9] = _mm_set_epi32((int)0x1c30bf84, (int)0xd4b7cd64, (int)0x5b2a404f, (int)0xad037e33); rc[10] = _mm_set_epi32((int)0xb2cc0bb9, (int)0x941723bf, (int)0x69028b2e, (int)0x8df69800); rc[11] = _mm_set_epi32((int)0xfa0478a6, (int)0xde6f5572, (int)0x4aaa9ec8, (int)0x5c9d2d8a); rc[12] = _mm_set_epi32((int)0xdfb49f2b, (int)0x6b772a12, (int)0x0efa4f2e, (int)0x29129fd4); @@ -111,77 +113,65 @@ static void load_haraka_constants(u128 rc[40]) { rc[39] = _mm_set_epi32((int)0x756acc03, (int)0x02288288, (int)0x4ad6bdfd, (int)0xe9c59da1); } -void PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_tweak_constants( - harakactx *state, - const unsigned char *pk_seed, const unsigned char *sk_seed, - unsigned long long seed_length) { +void tweak_constants(spx_ctx *ctx) { int i; unsigned char buf[40 * 16]; /* Use the standard constants to generate tweaked ones. */ - load_haraka_constants(state->rc); - - /* Constants for sk.seed */ - if (sk_seed != NULL) { - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_haraka_S(buf, 40 * 16, sk_seed, seed_length, state); - /* Tweak constants with the pub_seed */ - for (i = 0; i < 40; i++) { - state->rc_sseed[i] = LOAD(buf + i * 16); - } - } + load_haraka_constants(ctx->rc); /* Constants for pk.seed */ - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_haraka_S(buf, 40 * 16, pk_seed, seed_length, state); + haraka_S(buf, 40 * 16, ctx->pub_seed, SPX_N, ctx); /* Tweak constants with the pub_seed */ for (i = 0; i < 40; i++) { - state->rc[i] = LOAD(buf + i * 16); + ctx->rc[i] = LOAD(buf + i * 16); } } -static void haraka_S_absorb(unsigned char *s, +static void haraka_S_absorb(unsigned char *s, unsigned int r, const unsigned char *m, unsigned long long mlen, - unsigned char p, - const harakactx *state) { + unsigned char p, const spx_ctx *ctx) { unsigned long long i; - unsigned char t[HARAKAS_RATE]; + PQCLEAN_VLA(unsigned char, t, r); - while (mlen >= HARAKAS_RATE) { + while (mlen >= r) { // XOR block to state STORE(s, XOR128(LOAD(s), LOAD(m))); STORE(s + 16, XOR128(LOAD(s + 16), LOAD(m + 16))); - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_haraka512_perm(s, s, state); - mlen -= HARAKAS_RATE; - m += HARAKAS_RATE; + haraka512_perm(s, s, ctx); + mlen -= r; + m += r; } - for (i = 0; i < HARAKAS_RATE; ++i) { + for (i = 0; i < r; ++i) { t[i] = 0; } for (i = 0; i < mlen; ++i) { t[i] = m[i]; } t[i] = p; - t[HARAKAS_RATE - 1] |= 128; + t[r - 1] |= 128; STORE(s, XOR128(LOAD(s), LOAD(t))); STORE(s + 16, XOR128(LOAD(s + 16), LOAD(t + 16))); } static void haraka_S_absorb4x(unsigned char *s, + unsigned int r, const unsigned char *m0, const unsigned char *m1, const unsigned char *m2, const unsigned char *m3, unsigned long long int mlen, unsigned char p, - const harakactx *state) { + const spx_ctx *ctx) { unsigned long long i; - unsigned char t0[HARAKAS_RATE]; - unsigned char t1[HARAKAS_RATE]; - unsigned char t2[HARAKAS_RATE]; - unsigned char t3[HARAKAS_RATE]; + PQCLEAN_VLA(unsigned char, t0, r); + PQCLEAN_VLA(unsigned char, t1, r); + PQCLEAN_VLA(unsigned char, t2, r); + PQCLEAN_VLA(unsigned char, t3, r); - while (mlen >= HARAKAS_RATE) { + while (mlen >= r) { // XOR block to state STORE(s, XOR128(LOAD(s), LOAD(m0))); STORE(s + 16, XOR128(LOAD(s + 16), LOAD(m0 + 16))); @@ -192,15 +182,15 @@ static void haraka_S_absorb4x(unsigned char *s, STORE(s + 192, XOR128(LOAD(s + 192), LOAD(m3))); STORE(s + 208, XOR128(LOAD(s + 208), LOAD(m3 + 16))); - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_haraka512_perm_x4(s, s, state); - mlen -= HARAKAS_RATE; - m0 += HARAKAS_RATE; - m1 += HARAKAS_RATE; - m2 += HARAKAS_RATE; - m3 += HARAKAS_RATE; + haraka512_perm_x4(s, s, ctx); + mlen -= r; + m0 += r; + m1 += r; + m2 += r; + m3 += r; } - for (i = 0; i < HARAKAS_RATE; ++i) { + for (i = 0; i < r; ++i) { t0[i] = 0; t1[i] = 0; t2[i] = 0; @@ -218,10 +208,10 @@ static void haraka_S_absorb4x(unsigned char *s, t2[i] = p; t3[i] = p; - t0[HARAKAS_RATE - 1] |= 128; - t1[HARAKAS_RATE - 1] |= 128; - t2[HARAKAS_RATE - 1] |= 128; - t3[HARAKAS_RATE - 1] |= 128; + t0[r - 1] |= 128; + t1[r - 1] |= 128; + t2[r - 1] |= 128; + t3[r - 1] |= 128; STORE(s, XOR128(LOAD(s), LOAD(t0))); STORE(s + 16, XOR128(LOAD(s + 16), LOAD(t0 + 16))); @@ -234,9 +224,10 @@ static void haraka_S_absorb4x(unsigned char *s, } static void haraka_S_squeezeblocks(unsigned char *h, unsigned long long nblocks, - unsigned char *s, unsigned int r, const harakactx *state) { + unsigned char *s, unsigned int r, + const spx_ctx *ctx) { while (nblocks > 0) { - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_haraka512_perm(s, s, state); + haraka512_perm(s, s, ctx); STORE(h, LOAD(s)); STORE(h + 16, LOAD(s + 16)); h += r; @@ -251,9 +242,9 @@ static void haraka_S_squeezeblocks4x(unsigned char *h0, unsigned long long nblocks, unsigned char *s, unsigned int r, - const harakactx *state) { + const spx_ctx *ctx) { while (nblocks > 0) { - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_haraka512_perm_x4(s, s, state); + haraka512_perm_x4(s, s, ctx); STORE(h0, LOAD(s)); STORE(h0 + 16, LOAD(s + 16)); STORE(h1, LOAD(s + 64)); @@ -270,7 +261,7 @@ static void haraka_S_squeezeblocks4x(unsigned char *h0, } } -void PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_haraka_S_inc_init(uint8_t *s_inc) { +void haraka_S_inc_init(uint8_t *s_inc) { size_t i; for (i = 0; i < 64; i++) { @@ -279,7 +270,8 @@ void PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_haraka_S_inc_init(uint8_t *s_inc) { s_inc[64] = 0; } -void PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, const harakactx *state) { +void haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, + const spx_ctx *ctx) { size_t i; /* Recall that s_inc[64] is the non-absorbed bytes xored into the state */ @@ -293,16 +285,16 @@ void PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_haraka_S_inc_absorb(uint8_t *s_inc, c m += HARAKAS_RATE - s_inc[64]; s_inc[64] = 0; - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_haraka512_perm(s_inc, s_inc, state); + haraka512_perm(s_inc, s_inc, ctx); } for (i = 0; i < mlen; i++) { s_inc[s_inc[64] + i] ^= m[i]; } - s_inc[64] = (uint8_t)(s_inc[64] + mlen); + s_inc[64] += (uint8_t)mlen; } -void PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_haraka_S_inc_finalize(uint8_t *s_inc) { +void haraka_S_inc_finalize(uint8_t *s_inc) { /* After haraka_S_inc_absorb, we are guaranteed that s_inc[64] < HARAKAS_RATE, so we can always use one more byte for p in the current state. */ s_inc[s_inc[64]] ^= 0x1F; @@ -310,22 +302,23 @@ void PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_haraka_S_inc_finalize(uint8_t *s_inc) s_inc[64] = 0; } -void PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, const harakactx *state) { +void haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, + const spx_ctx *ctx) { size_t i; /* First consume any bytes we still have sitting around */ for (i = 0; i < outlen && i < s_inc[64]; i++) { /* There are s_inc[64] bytes left, so r - s_inc[64] is the first available byte. We consume from there, i.e., up to r. */ - out[i] = (uint8_t)s_inc[(HARAKAS_RATE - s_inc[64] + (uint8_t)i)]; + out[i] = (uint8_t)s_inc[(HARAKAS_RATE - s_inc[64] + i)]; } out += i; outlen -= i; - s_inc[64] = (uint8_t)(s_inc[64] - i); + s_inc[64] -= (uint8_t)i; /* Then squeeze the remaining necessary blocks */ while (outlen > 0) { - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_haraka512_perm(s_inc, s_inc, state); + haraka512_perm(s_inc, s_inc, ctx); for (i = 0; i < outlen && i < HARAKAS_RATE; i++) { out[i] = s_inc[i]; @@ -336,8 +329,9 @@ void PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_haraka_S_inc_squeeze(uint8_t *out, si } } -void PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_haraka_S(unsigned char *out, unsigned long long outlen, - const unsigned char *in, unsigned long long inlen, const harakactx *state) { +void haraka_S(unsigned char *out, unsigned long long outlen, + const unsigned char *in, unsigned long long inlen, + const spx_ctx *ctx) { unsigned long long i; unsigned char s[64]; unsigned char d[32]; @@ -345,30 +339,30 @@ void PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_haraka_S(unsigned char *out, unsigned for (i = 0; i < 64; i++) { s[i] = 0; } - haraka_S_absorb(s, in, inlen, 0x1F, state); + haraka_S_absorb(s, HARAKAS_RATE, in, inlen, 0x1F, ctx); - haraka_S_squeezeblocks(out, outlen / HARAKAS_RATE, s, HARAKAS_RATE, state); + haraka_S_squeezeblocks(out, outlen / HARAKAS_RATE, s, HARAKAS_RATE, ctx); out += (outlen / HARAKAS_RATE) * HARAKAS_RATE; if (outlen % HARAKAS_RATE) { - haraka_S_squeezeblocks(d, 1, s, HARAKAS_RATE, state); + haraka_S_squeezeblocks(d, 1, s, HARAKAS_RATE, ctx); for (i = 0; i < outlen % HARAKAS_RATE; i++) { out[i] = d[i]; } } } -void PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_haraka_Sx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned long long outlen, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - unsigned long long inlen, - const harakactx *state) { +void haraka_Sx4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned long long outlen, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + unsigned long long inlen, + const spx_ctx *ctx) { unsigned long long i; unsigned char s[64 * 4]; unsigned char d0[32]; @@ -379,16 +373,17 @@ void PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_haraka_Sx4(unsigned char *out0, for (i = 0; i < 64 * 4; i++) { s[i] = 0; } - haraka_S_absorb4x(s, in0, in1, in2, in3, inlen, 0x1F, state); + haraka_S_absorb4x(s, HARAKAS_RATE, in0, in1, in2, in3, inlen, 0x1F, ctx); - haraka_S_squeezeblocks4x(out0, out1, out2, out3, outlen / HARAKAS_RATE, s, HARAKAS_RATE, state); + haraka_S_squeezeblocks4x(out0, out1, out2, out3, outlen / HARAKAS_RATE, s, + HARAKAS_RATE, ctx); out0 += (outlen / HARAKAS_RATE) * HARAKAS_RATE; out1 += (outlen / HARAKAS_RATE) * HARAKAS_RATE; out2 += (outlen / HARAKAS_RATE) * HARAKAS_RATE; out3 += (outlen / HARAKAS_RATE) * HARAKAS_RATE; if (outlen % HARAKAS_RATE) { - haraka_S_squeezeblocks4x(d0, d1, d2, d3, 1, s, HARAKAS_RATE, state); + haraka_S_squeezeblocks4x(d0, d1, d2, d3, 1, s, HARAKAS_RATE, ctx); for (i = 0; i < outlen % HARAKAS_RATE; i++) { out0[i] = d0[i]; out1[i] = d1[i]; @@ -398,7 +393,8 @@ void PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_haraka_Sx4(unsigned char *out0, } } -void PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_haraka512_perm(unsigned char *out, const unsigned char *in, const harakactx *state) { +void haraka512_perm(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx) { u128 s[4], tmp; s[0] = LOAD(in); @@ -406,19 +402,19 @@ void PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_haraka512_perm(unsigned char *out, co s[2] = LOAD(in + 32); s[3] = LOAD(in + 48); - AES4(s[0], s[1], s[2], s[3], state->rc); + AES4(s[0], s[1], s[2], s[3], ctx->rc); MIX4(s[0], s[1], s[2], s[3]); - AES4(s[0], s[1], s[2], s[3], state->rc + 8); + AES4(s[0], s[1], s[2], s[3], ctx->rc + 8); MIX4(s[0], s[1], s[2], s[3]); - AES4(s[0], s[1], s[2], s[3], state->rc + 16); + AES4(s[0], s[1], s[2], s[3], ctx->rc + 16); MIX4(s[0], s[1], s[2], s[3]); - AES4(s[0], s[1], s[2], s[3], state->rc + 24); + AES4(s[0], s[1], s[2], s[3], ctx->rc + 24); MIX4(s[0], s[1], s[2], s[3]); - AES4(s[0], s[1], s[2], s[3], state->rc + 32); + AES4(s[0], s[1], s[2], s[3], ctx->rc + 32); MIX4(s[0], s[1], s[2], s[3]); STORE(out, s[0]); @@ -427,7 +423,8 @@ void PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_haraka512_perm(unsigned char *out, co STORE(out + 48, s[3]); } -void PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_haraka512_perm_x4(unsigned char *out, const unsigned char *in, const harakactx *state) { +void haraka512_perm_x4(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx) { u128 s[4][4], tmp; s[0][0] = LOAD(in); @@ -447,31 +444,31 @@ void PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_haraka512_perm_x4(unsigned char *out, s[3][2] = LOAD(in + 224); s[3][3] = LOAD(in + 240); - AES4_4x(s[0], s[1], s[2], s[3], state->rc); + AES4_4x(s[0], s[1], s[2], s[3], ctx->rc); MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - AES4_4x(s[0], s[1], s[2], s[3], state->rc + 8); + AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 8); MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - AES4_4x(s[0], s[1], s[2], s[3], state->rc + 16); + AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 16); MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - AES4_4x(s[0], s[1], s[2], s[3], state->rc + 24); + AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 24); MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - AES4_4x(s[0], s[1], s[2], s[3], state->rc + 32); + AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 32); MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); @@ -495,7 +492,8 @@ void PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_haraka512_perm_x4(unsigned char *out, STORE(out + 240, s[3][3]); } -void PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_haraka512(unsigned char *out, const unsigned char *in, const harakactx *state) { +void haraka512(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx) { u128 s[4], tmp; s[0] = LOAD(in); @@ -503,19 +501,19 @@ void PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_haraka512(unsigned char *out, const u s[2] = LOAD(in + 32); s[3] = LOAD(in + 48); - AES4(s[0], s[1], s[2], s[3], state->rc); + AES4(s[0], s[1], s[2], s[3], ctx->rc); MIX4(s[0], s[1], s[2], s[3]); - AES4(s[0], s[1], s[2], s[3], state->rc + 8); + AES4(s[0], s[1], s[2], s[3], ctx->rc + 8); MIX4(s[0], s[1], s[2], s[3]); - AES4(s[0], s[1], s[2], s[3], state->rc + 16); + AES4(s[0], s[1], s[2], s[3], ctx->rc + 16); MIX4(s[0], s[1], s[2], s[3]); - AES4(s[0], s[1], s[2], s[3], state->rc + 24); + AES4(s[0], s[1], s[2], s[3], ctx->rc + 24); MIX4(s[0], s[1], s[2], s[3]); - AES4(s[0], s[1], s[2], s[3], state->rc + 32); + AES4(s[0], s[1], s[2], s[3], ctx->rc + 32); MIX4(s[0], s[1], s[2], s[3]); s[0] = XOR128(s[0], LOAD(in)); @@ -527,7 +525,8 @@ void PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_haraka512(unsigned char *out, const u TRUNCSTORE(out, s[0], s[1], s[2], s[3]); } -void PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_haraka512x4(unsigned char *out, const unsigned char *in, const harakactx *state) { +void haraka512x4(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx) { u128 s[4][4], tmp; s[0][0] = LOAD(in); @@ -547,31 +546,31 @@ void PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_haraka512x4(unsigned char *out, const s[3][2] = LOAD(in + 224); s[3][3] = LOAD(in + 240); - AES4_4x(s[0], s[1], s[2], s[3], state->rc); + AES4_4x(s[0], s[1], s[2], s[3], ctx->rc); MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - AES4_4x(s[0], s[1], s[2], s[3], state->rc + 8); + AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 8); MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - AES4_4x(s[0], s[1], s[2], s[3], state->rc + 16); + AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 16); MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - AES4_4x(s[0], s[1], s[2], s[3], state->rc + 24); + AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 24); MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - AES4_4x(s[0], s[1], s[2], s[3], state->rc + 32); + AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 32); MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); @@ -600,25 +599,26 @@ void PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_haraka512x4(unsigned char *out, const TRUNCSTORE((out + 96), s[3][0], s[3][1], s[3][2], s[3][3]); } -void PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_haraka256(unsigned char *out, const unsigned char *in, const harakactx *state) { +void haraka256(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx) { u128 s[2], tmp; s[0] = LOAD(in); s[1] = LOAD(in + 16); - AES2(s[0], s[1], state->rc); + AES2(s[0], s[1], ctx->rc); MIX2(s[0], s[1]); - AES2(s[0], s[1], state->rc + 4); + AES2(s[0], s[1], ctx->rc + 4); MIX2(s[0], s[1]); - AES2(s[0], s[1], state->rc + 8); + AES2(s[0], s[1], ctx->rc + 8); MIX2(s[0], s[1]); - AES2(s[0], s[1], state->rc + 12); + AES2(s[0], s[1], ctx->rc + 12); MIX2(s[0], s[1]); - AES2(s[0], s[1], state->rc + 16); + AES2(s[0], s[1], ctx->rc + 16); MIX2(s[0], s[1]); s[0] = XOR128(s[0], LOAD(in)); @@ -628,7 +628,8 @@ void PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_haraka256(unsigned char *out, const u STORE(out + 16, s[1]); } -void PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_haraka256x4(unsigned char *out, const unsigned char *in, const harakactx *state) { +void haraka256x4(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx) { u128 s[4][2], tmp; s[0][0] = LOAD(in); @@ -641,7 +642,7 @@ void PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_haraka256x4(unsigned char *out, const s[3][1] = LOAD(in + 112); // Round 1 - AES2_4x(s[0], s[1], s[2], s[3], state->rc); + AES2_4x(s[0], s[1], s[2], s[3], ctx->rc); MIX2(s[0][0], s[0][1]); MIX2(s[1][0], s[1][1]); @@ -649,7 +650,7 @@ void PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_haraka256x4(unsigned char *out, const MIX2(s[3][0], s[3][1]); // Round 2 - AES2_4x(s[0], s[1], s[2], s[3], state->rc + 4); + AES2_4x(s[0], s[1], s[2], s[3], ctx->rc + 4); MIX2(s[0][0], s[0][1]); MIX2(s[1][0], s[1][1]); @@ -657,7 +658,7 @@ void PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_haraka256x4(unsigned char *out, const MIX2(s[3][0], s[3][1]); // Round 3 - AES2_4x(s[0], s[1], s[2], s[3], state->rc + 8); + AES2_4x(s[0], s[1], s[2], s[3], ctx->rc + 8); MIX2(s[0][0], s[0][1]); MIX2(s[1][0], s[1][1]); @@ -665,7 +666,7 @@ void PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_haraka256x4(unsigned char *out, const MIX2(s[3][0], s[3][1]); // Round 4 - AES2_4x(s[0], s[1], s[2], s[3], state->rc + 12); + AES2_4x(s[0], s[1], s[2], s[3], ctx->rc + 12); MIX2(s[0][0], s[0][1]); MIX2(s[1][0], s[1][1]); @@ -673,7 +674,7 @@ void PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_haraka256x4(unsigned char *out, const MIX2(s[3][0], s[3][1]); // Round 5 - AES2_4x(s[0], s[1], s[2], s[3], state->rc + 16); + AES2_4x(s[0], s[1], s[2], s[3], ctx->rc + 16); MIX2(s[0][0], s[0][1]); MIX2(s[1][0], s[1][1]); @@ -699,103 +700,3 @@ void PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_haraka256x4(unsigned char *out, const STORE(out + 96, s[3][0]); STORE(out + 112, s[3][1]); } - -void PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_haraka256_sk(unsigned char *out, const unsigned char *in, const harakactx *state) { - u128 s[2], tmp; - - s[0] = LOAD(in); - s[1] = LOAD(in + 16); - - AES2(s[0], s[1], state->rc_sseed); - MIX2(s[0], s[1]); - - AES2(s[0], s[1], state->rc_sseed + 4); - MIX2(s[0], s[1]); - - AES2(s[0], s[1], state->rc_sseed + 8); - MIX2(s[0], s[1]); - - AES2(s[0], s[1], state->rc_sseed + 12); - MIX2(s[0], s[1]); - - AES2(s[0], s[1], state->rc_sseed + 16); - MIX2(s[0], s[1]); - - s[0] = XOR128(s[0], LOAD(in)); - s[1] = XOR128(s[1], LOAD(in + 16)); - - STORE(out, s[0]); - STORE(out + 16, s[1]); -} - -void PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_haraka256_skx4(unsigned char *out, const unsigned char *in, const harakactx *state) { - u128 s[4][2], tmp; - - s[0][0] = LOAD(in); - s[0][1] = LOAD(in + 16); - s[1][0] = LOAD(in + 32); - s[1][1] = LOAD(in + 48); - s[2][0] = LOAD(in + 64); - s[2][1] = LOAD(in + 80); - s[3][0] = LOAD(in + 96); - s[3][1] = LOAD(in + 112); - - // Round 1 - AES2_4x(s[0], s[1], s[2], s[3], state->rc_sseed); - - MIX2(s[0][0], s[0][1]); - MIX2(s[1][0], s[1][1]); - MIX2(s[2][0], s[2][1]); - MIX2(s[3][0], s[3][1]); - - // Round 2 - AES2_4x(s[0], s[1], s[2], s[3], state->rc_sseed + 4); - - MIX2(s[0][0], s[0][1]); - MIX2(s[1][0], s[1][1]); - MIX2(s[2][0], s[2][1]); - MIX2(s[3][0], s[3][1]); - - // Round 3 - AES2_4x(s[0], s[1], s[2], s[3], state->rc_sseed + 8); - - MIX2(s[0][0], s[0][1]); - MIX2(s[1][0], s[1][1]); - MIX2(s[2][0], s[2][1]); - MIX2(s[3][0], s[3][1]); - - // Round 4 - AES2_4x(s[0], s[1], s[2], s[3], state->rc_sseed + 12); - - MIX2(s[0][0], s[0][1]); - MIX2(s[1][0], s[1][1]); - MIX2(s[2][0], s[2][1]); - MIX2(s[3][0], s[3][1]); - - // Round 5 - AES2_4x(s[0], s[1], s[2], s[3], state->rc_sseed + 16); - - MIX2(s[0][0], s[0][1]); - MIX2(s[1][0], s[1][1]); - MIX2(s[2][0], s[2][1]); - MIX2(s[3][0], s[3][1]); - - // Feed Forward - s[0][0] = XOR128(s[0][0], LOAD(in)); - s[0][1] = XOR128(s[0][1], LOAD(in + 16)); - s[1][0] = XOR128(s[1][0], LOAD(in + 32)); - s[1][1] = XOR128(s[1][1], LOAD(in + 48)); - s[2][0] = XOR128(s[2][0], LOAD(in + 64)); - s[2][1] = XOR128(s[2][1], LOAD(in + 80)); - s[3][0] = XOR128(s[3][0], LOAD(in + 96)); - s[3][1] = XOR128(s[3][1], LOAD(in + 112)); - - STORE(out, s[0][0]); - STORE(out + 16, s[0][1]); - STORE(out + 32, s[1][0]); - STORE(out + 48, s[1][1]); - STORE(out + 64, s[2][0]); - STORE(out + 80, s[2][1]); - STORE(out + 96, s[3][0]); - STORE(out + 112, s[3][1]); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/haraka.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/haraka.h index 44abbc7811..737cb6065f 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/haraka.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/haraka.h @@ -1,57 +1,42 @@ -#ifndef PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_HARAKA_H -#define PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_HARAKA_H +#ifndef SPX_HARAKA_H +#define SPX_HARAKA_H -#include -#include -#include - -typedef struct { - __m128i rc[40]; - __m128i rc_sseed[40]; -} harakactx; +#include "context.h" +#include "params.h" /* Tweak constants with seed */ -void PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_tweak_constants( - harakactx *state, - const unsigned char *pk_seed, const unsigned char *sk_seed, - unsigned long long seed_length); +#define tweak_constants SPX_NAMESPACE(tweak_constants) +void tweak_constants(spx_ctx *ctx); /* Haraka Sponge */ -void PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_haraka_S_inc_init(uint8_t *s_inc); -void PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, const harakactx *state); -void PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_haraka_S_inc_finalize(uint8_t *s_inc); -void PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, const harakactx *state); -void PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_haraka_S( - unsigned char *out, unsigned long long outlen, - const unsigned char *in, unsigned long long inlen, const harakactx *state); -void PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_haraka_Sx4( - unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned long long outlen, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - unsigned long long inlen, - const harakactx *state); - +#define haraka_S_inc_init SPX_NAMESPACE(haraka_S_inc_init) +void haraka_S_inc_init(uint8_t *s_inc); +#define haraka_S_inc_absorb SPX_NAMESPACE(haraka_S_inc_absorb) +void haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, + const spx_ctx *ctx); +#define haraka_S_inc_finalize SPX_NAMESPACE(haraka_S_inc_finalize) +void haraka_S_inc_finalize(uint8_t *s_inc); +#define haraka_S_inc_squeeze SPX_NAMESPACE(haraka_S_inc_squeeze) +void haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, + const spx_ctx *ctx); +#define haraka_S SPX_NAMESPACE(haraka_S) +void haraka_S(unsigned char *out, unsigned long long outlen, + const unsigned char *in, unsigned long long inlen, + const spx_ctx *ctx); /* Applies the 512-bit Haraka permutation to in. */ -void PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_haraka512_perm(unsigned char *out, const unsigned char *in, const harakactx *state); -void PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_haraka512_perm_x4(unsigned char *out, const unsigned char *in, const harakactx *state); +#define haraka512_perm SPX_NAMESPACE(haraka512_perm) +void haraka512_perm(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx); /* Implementation of Haraka-512 */ -void PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_haraka512(unsigned char *out, const unsigned char *in, const harakactx *state); -void PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_haraka512x4(unsigned char *out, const unsigned char *in, const harakactx *state); +#define haraka512 SPX_NAMESPACE(haraka512) +void haraka512(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx); /* Implementation of Haraka-256 */ -void PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_haraka256(unsigned char *out, const unsigned char *in, const harakactx *state); -void PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_haraka256x4(unsigned char *out, const unsigned char *in, const harakactx *state); - -/* Implementation of Haraka-256 using sk.seed constants */ -void PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_haraka256_sk(unsigned char *out, const unsigned char *in, const harakactx *state); -void PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_haraka256_skx4(unsigned char *out, const unsigned char *in, const harakactx *state); +#define haraka256 SPX_NAMESPACE(haraka256) +void haraka256(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/haraka_offsets.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/haraka_offsets.h new file mode 100644 index 0000000000..7c062272a0 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/haraka_offsets.h @@ -0,0 +1,21 @@ +#ifndef HARAKA_OFFSETS_H_ +#define HARAKA_OFFSETS_H_ + +/* + * Offsets of various fields in the address structure when we use Haraka as + * the Sphincs+ hash function + */ + +#define SPX_OFFSET_LAYER 3 /* The byte used to specify the Merkle tree layer */ +#define SPX_OFFSET_TREE 8 /* The start of the 8 byte field used to specify the tree */ +#define SPX_OFFSET_TYPE 19 /* The byte used to specify the hash type (reason) */ +#define SPX_OFFSET_KP_ADDR2 22 /* The high byte used to specify the key pair (which one-time signature) */ +#define SPX_OFFSET_KP_ADDR1 23 /* The low byte used to specify the key pair */ +#define SPX_OFFSET_CHAIN_ADDR 27 /* The byte used to specify the chain address (which Winternitz chain) */ +#define SPX_OFFSET_HASH_ADDR 31 /* The byte used to specify the hash address (where in the Winternitz chain) */ +#define SPX_OFFSET_TREE_HGT 27 /* The byte used to specify the height of this node in the FORS or Merkle tree */ +#define SPX_OFFSET_TREE_INDEX 28 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ + +#define SPX_HARAKA 1 + +#endif /* HARAKA_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/harakax4.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/harakax4.h new file mode 100644 index 0000000000..eadc69aa48 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/harakax4.h @@ -0,0 +1,36 @@ +#ifndef SPX_HARAKAX4_H +#define SPX_HARAKAX4_H + +#include "context.h" +#include "params.h" + +/* Haraka Sponge */ +#define haraka_Sx4 SPX_NAMESPACE(haraka_Sx4) +void haraka_Sx4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned long long outlen, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + unsigned long long inlen, + const spx_ctx *ctx); + +/* Applies the 512-bit Haraka permutation x4 to in. */ +#define haraka512_perm_x4 SPX_NAMESPACE(haraka512_perm_x4) +void haraka512_perm_x4(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx); + +/* Implementation of Haraka-512 x4*/ +#define haraka512x4 SPX_NAMESPACE(haraka512x4) +void haraka512x4(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx); + +/* Implementation of Haraka-256 x4 */ +#define haraka256x4 SPX_NAMESPACE(haraka256x4) +void haraka256x4(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/hash.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/hash.h index 4b4fa01669..f7c87d4c3c 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/hash.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/hash.h @@ -1,31 +1,28 @@ -#ifndef PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_HASH_H -#define PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_HASH_H - -#include "hash_state.h" +#ifndef SPX_HASH_H +#define SPX_HASH_H #include #include -void PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_initialize_hash_function( - hash_state *hash_state_seeded, - const unsigned char *pub_seed, const unsigned char *sk_seed); +#include "context.h" +#include "params.h" + +#define prf_addr SPX_NAMESPACE(prf_addr) +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]); -void PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_destroy_hash_function(hash_state *hash_state_seeded); +#define gen_message_random SPX_NAMESPACE(gen_message_random) +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); -void PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded); +#define hash_message SPX_NAMESPACE(hash_message) +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); -void PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); -void PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/hash_haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/hash_haraka.c index 0a204c3888..750a67423b 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/hash_haraka.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/hash_haraka.c @@ -2,58 +2,44 @@ #include #include "address.h" -#include "haraka.h" -#include "hash.h" #include "params.h" #include "utils.h" -void PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_initialize_hash_function( - hash_state *hash_state_seeded, - const unsigned char *pub_seed, const unsigned char *sk_seed) { - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_tweak_constants(hash_state_seeded, pub_seed, sk_seed, PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N); -} - -/* The haraka implementation is stack based and won't be replaced in PQClean/OQS, - so we don't need to do anything */ -void PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_destroy_hash_function( - hash_state *hash_state_seeded) { // NOLINT(readability-non-const-parameter) - (void)hash_state_seeded; -} +#include "haraka.h" +#include "hash.h" /* - * Computes PRF(key, addr), given a secret key of PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N bytes and an address + * Computes PRF(key, addr), given a secret key of SPX_N bytes and an address */ -void PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded) { - unsigned char buf[PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_ADDR_BYTES]; - /* Since PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N may be smaller than 32, we need a temporary buffer. */ +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]) { + /* Since SPX_N may be smaller than 32, we need temporary buffers. */ unsigned char outbuf[32]; + unsigned char buf[64] = {0}; - (void)key; /* Suppress an 'unused parameter' warning. */ + memcpy(buf, addr, SPX_ADDR_BYTES); + memcpy(buf + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_addr_to_bytes(buf, addr); - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_haraka256_sk(outbuf, buf, hash_state_seeded); - memcpy(out, outbuf, PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N); + haraka512(outbuf, (const void *)buf, ctx); + memcpy(out, outbuf, SPX_N); } /** * Computes the message-dependent randomness R, using a secret seed and an * optional randomization value as well as the message. */ -void PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded) { +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { uint8_t s_inc[65]; - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_haraka_S_inc_init(s_inc); - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_haraka_S_inc_absorb(s_inc, sk_prf, PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_haraka_S_inc_absorb(s_inc, optrand, PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_haraka_S_inc_absorb(s_inc, m, mlen, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_haraka_S_inc_finalize(s_inc); - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_haraka_S_inc_squeeze(R, PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N, s_inc, hash_state_seeded); + haraka_S_inc_init(s_inc); + haraka_S_inc_absorb(s_inc, sk_prf, SPX_N, ctx); + haraka_S_inc_absorb(s_inc, optrand, SPX_N, ctx); + haraka_S_inc_absorb(s_inc, m, mlen, ctx); + haraka_S_inc_finalize(s_inc); + haraka_S_inc_squeeze(R, SPX_N, s_inc, ctx); } /** @@ -61,36 +47,35 @@ void PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_gen_message_random( * Outputs the message digest and the index of the leaf. The index is split in * the tree index and the leaf index, for convenient copying to an address. */ -void PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded) { -#define PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_TREE_BITS (PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_TREE_HEIGHT * (PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_D - 1)) -#define PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_TREE_BYTES ((PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_TREE_BITS + 7) / 8) -#define PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_LEAF_BITS PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_TREE_HEIGHT -#define PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_LEAF_BYTES ((PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_LEAF_BITS + 7) / 8) -#define PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_DGST_BYTES (PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_FORS_MSG_BYTES + PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_TREE_BYTES + PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_LEAF_BYTES) +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { +#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) +#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) +#define SPX_LEAF_BITS SPX_TREE_HEIGHT +#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) +#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) - unsigned char buf[PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_DGST_BYTES]; + unsigned char buf[SPX_DGST_BYTES]; unsigned char *bufp = buf; uint8_t s_inc[65]; - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_haraka_S_inc_init(s_inc); - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_haraka_S_inc_absorb(s_inc, R, PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_haraka_S_inc_absorb(s_inc, pk + PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N, PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_haraka_S_inc_absorb(s_inc, m, mlen, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_haraka_S_inc_finalize(s_inc); - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_haraka_S_inc_squeeze(buf, PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_DGST_BYTES, s_inc, hash_state_seeded); + haraka_S_inc_init(s_inc); + haraka_S_inc_absorb(s_inc, R, SPX_N, ctx); + haraka_S_inc_absorb(s_inc, pk + SPX_N, SPX_N, ctx); // Only absorb root part of pk + haraka_S_inc_absorb(s_inc, m, mlen, ctx); + haraka_S_inc_finalize(s_inc); + haraka_S_inc_squeeze(buf, SPX_DGST_BYTES, s_inc, ctx); + + memcpy(digest, bufp, SPX_FORS_MSG_BYTES); + bufp += SPX_FORS_MSG_BYTES; - memcpy(digest, bufp, PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_FORS_MSG_BYTES); - bufp += PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_FORS_MSG_BYTES; - *tree = PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_bytes_to_ull(bufp, PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_TREE_BYTES); - *tree &= (~(uint64_t)0) >> (64 - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_TREE_BITS); - bufp += PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_TREE_BYTES; + *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); + *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); + bufp += SPX_TREE_BYTES; - *leaf_idx = (uint32_t)PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_bytes_to_ull( - bufp, PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_LEAF_BYTES); - *leaf_idx &= (~(uint32_t)0) >> (32 - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_LEAF_BITS); + *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); + *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/hash_harakax4.c b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/hash_harakax4.c index 1de7243fc9..cfa5162d79 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/hash_harakax4.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/hash_harakax4.c @@ -2,36 +2,34 @@ #include #include "address.h" -#include "haraka.h" -#include "hash_state.h" +#include "harakax4.h" #include "hashx4.h" #include "params.h" /* * 4-way parallel version of prf_addr; takes 4x as much input and output */ -void PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_prf_addrx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const unsigned char *key, - const uint32_t addrx4[4 * 8], - const hash_state *state_seeded) { - unsigned char bufx4[4 * PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_ADDR_BYTES]; - /* Since PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N may be smaller than 32, we need a temporary buffer. */ +#define prf_addrx4 SPX_NAMESPACE(prf_addrx4) +void prf_addrx4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const spx_ctx *ctx, + const uint32_t addrx4[4 * 8]) { + unsigned char bufx4[4 * 64] = {0}; + /* Since SPX_N may be smaller than 32, we need temporary buffers. */ unsigned char outbuf[4 * 32]; unsigned int i; - (void)key; /* Suppress an 'unused parameter' warning. */ - for (i = 0; i < 4; i++) { - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_addr_to_bytes(bufx4 + i * PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_ADDR_BYTES, addrx4 + i * 8); + memcpy(bufx4 + i * 64, addrx4 + i * 8, SPX_ADDR_BYTES); + memcpy(bufx4 + i * 64 + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); } - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_haraka256_skx4(outbuf, bufx4, state_seeded); + haraka512x4(outbuf, bufx4, ctx); - memcpy(out0, outbuf, PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N); - memcpy(out1, outbuf + 32, PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N); - memcpy(out2, outbuf + 64, PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N); - memcpy(out3, outbuf + 96, PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N); + memcpy(out0, outbuf, SPX_N); + memcpy(out1, outbuf + 32, SPX_N); + memcpy(out2, outbuf + 64, SPX_N); + memcpy(out3, outbuf + 96, SPX_N); } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/hash_state.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/hash_state.h deleted file mode 100644 index ed3c6fddbc..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/hash_state.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_HASH_STATE_H -#define PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_HASH_STATE_H - -/** - * Defines the type of the hash function state. - * - * Don't be fooled into thinking this instance of SPHINCS+ isn't stateless! - * - * From Section 7.2.2 from the SPHINCS+ round-2 specification: - * - * Each of the instances of the tweakable hash function take PK.seed as its - * first input, which is constant for a given key pair – and, thus, across - * a single signature. This leads to a lot of redundant computation. To remedy - * this, we pad PK.seed to the length of a full 64-byte SHA-256 input block. - * Because of the Merkle-DamgÃ¥rd construction that underlies SHA-256, this - * allows for reuse of the intermediate SHA-256 state after the initial call to - * the compression function which improves performance. - * - * We pass this hash state around in functions, because otherwise we need to - * have a global variable. - */ - -#include "haraka.h" -#define hash_state harakactx - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/hashx4.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/hashx4.h index 801e689929..3751a0ebd0 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/hashx4.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/hashx4.h @@ -1,16 +1,17 @@ -#ifndef PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_HASHX4_H -#define PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_HASHX4_H +#ifndef SPX_HASHX4_H +#define SPX_HASHX4_H #include -#include "hash_state.h" +#include "context.h" +#include "params.h" -void PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_prf_addrx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const unsigned char *key, - const uint32_t addrx4[4 * 8], - const hash_state *state_seeded); +#define prf_addrx4 SPX_NAMESPACE(prf_addrx4) +void prf_addrx4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const spx_ctx *ctx, + const uint32_t addrx4[4 * 8]); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/merkle.c b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/merkle.c new file mode 100644 index 0000000000..f57811c1ac --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/merkle.c @@ -0,0 +1,64 @@ +#include +#include + +#include "merkle.h" + +#include "address.h" +#include "params.h" +#include "utils.h" +#include "utilsx4.h" +#include "wots.h" +#include "wotsx4.h" + +/* + * This generates a Merkle signature (WOTS signature followed by the Merkle + * authentication path). + */ +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf) { + unsigned char *auth_path = sig + SPX_WOTS_BYTES; + uint32_t tree_addrx4[4 * 8] = { 0 }; + int j; + struct leaf_info_x4 info = { 0 }; + unsigned steps[ SPX_WOTS_LEN ]; + + info.wots_sig = sig; + chain_lengths(steps, root); + info.wots_steps = steps; + + for (j = 0; j < 4; j++) { + set_type(&tree_addrx4[8 * j], SPX_ADDR_TYPE_HASHTREE); + set_type(&info.leaf_addr[8 * j], SPX_ADDR_TYPE_WOTS); + set_type(&info.pk_addr[8 * j], SPX_ADDR_TYPE_WOTSPK); + copy_subtree_addr(&tree_addrx4[8 * j], tree_addr); + copy_subtree_addr(&info.leaf_addr[8 * j], wots_addr); + copy_subtree_addr(&info.pk_addr[8 * j], wots_addr); + } + + info.wots_sign_leaf = idx_leaf; + + treehashx4(root, auth_path, ctx, + idx_leaf, 0, + SPX_TREE_HEIGHT, + wots_gen_leafx4, + tree_addrx4, &info); +} + +/* Compute root node of the top-most subtree. */ +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { + /* We do not need the auth path in key generation, but it simplifies the + code to have just one treehash routine that computes both root and path + in one function. */ + unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; + uint32_t top_tree_addr[8] = {0}; + uint32_t wots_addr[8] = {0}; + + set_layer_addr(top_tree_addr, SPX_D - 1); + set_layer_addr(wots_addr, SPX_D - 1); + + merkle_sign(auth_path, root, ctx, + wots_addr, top_tree_addr, + ~0U /* ~0 means "don't bother generating an auth path */ ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/merkle.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/merkle.h new file mode 100644 index 0000000000..769cf2e970 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/merkle.h @@ -0,0 +1,21 @@ +#ifndef MERKLE_H_ +#define MERKLE_H_ + +#include + +#include "context.h" +#include "params.h" + +/* Generate a Merkle signature (WOTS signature followed by the Merkle */ +/* authentication path) */ +#define merkle_sign SPX_NAMESPACE(merkle_sign) +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf); + +/* Compute the root node of the top-most subtree. */ +#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); + +#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/nistapi.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/nistapi.h new file mode 100644 index 0000000000..3cb71afad4 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/nistapi.h @@ -0,0 +1,87 @@ +#ifndef SPX_API_H +#define SPX_API_H + +#include +#include + +#include "params.h" + +#define CRYPTO_ALGNAME "SPHINCS+" + +#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES +#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES +#define CRYPTO_BYTES SPX_BYTES +#define CRYPTO_SEEDBYTES (3*SPX_N) + +/* + * Returns the length of a secret key, in bytes + */ +#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) +size_t crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) +size_t crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) +size_t crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) +size_t crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +#define crypto_sign SPX_NAMESPACE(crypto_sign) +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/params.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/params.h index b33b0c10a1..b8ad803e37 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/params.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/params.h @@ -1,53 +1,56 @@ -#ifndef PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_PARAMS_H -#define PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_PARAMS_H +#ifndef SPX_PARAMS_H +#define SPX_PARAMS_H + +#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_##s /* Hash output length in bytes. */ -#define PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N 24 +#define SPX_N 24 /* Height of the hypertree. */ -#define PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_FULL_HEIGHT 63 +#define SPX_FULL_HEIGHT 63 /* Number of subtree layer. */ -#define PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_D 7 +#define SPX_D 7 /* FORS tree dimensions. */ -#define PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_FORS_HEIGHT 14 -#define PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_FORS_TREES 17 +#define SPX_FORS_HEIGHT 14 +#define SPX_FORS_TREES 17 /* Winternitz parameter, */ -#define PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_WOTS_W 16 +#define SPX_WOTS_W 16 /* The hash function is defined by linking a different hash.c file, as opposed to setting a #define constant. */ /* For clarity */ -#define PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_ADDR_BYTES 32 +#define SPX_ADDR_BYTES 32 /* WOTS parameters. */ -#define PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_WOTS_LOGW 4 +#define SPX_WOTS_LOGW 4 -#define PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_WOTS_LEN1 (8 * PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N / PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_WOTS_LOGW) +#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) -/* PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#define PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_WOTS_LEN2 3 +/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ +#define SPX_WOTS_LEN2 3 -#define PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_WOTS_LEN (PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_WOTS_LEN1 + PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_WOTS_LEN2) -#define PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_WOTS_BYTES (PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_WOTS_LEN * PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N) -#define PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_WOTS_PK_BYTES PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_WOTS_BYTES +#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) +#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) +#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES /* Subtree size. */ -#define PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_TREE_HEIGHT (PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_FULL_HEIGHT / PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_D) +#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) + +//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT +// #error SPX_D should always divide SPX_FULL_HEIGHT +//#endif /* FORS parameters. */ -#define PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_FORS_MSG_BYTES ((PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_FORS_TREES + 7) / 8) -#define PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_FORS_BYTES ((PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_FORS_HEIGHT + 1) * PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_FORS_TREES * PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N) -#define PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_FORS_PK_BYTES PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N +#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) +#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) +#define SPX_FORS_PK_BYTES SPX_N /* Resulting SPX sizes. */ -#define PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_BYTES (PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N + PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_FORS_BYTES + PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_D * PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_WOTS_BYTES +\ - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_FULL_HEIGHT * PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N) -#define PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_PK_BYTES (2 * PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N) -#define PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_SK_BYTES (2 * PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N + PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_PK_BYTES) - -/* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ -#define PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_OPTRAND_BYTES 32 +#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ + SPX_FULL_HEIGHT * SPX_N) +#define SPX_PK_BYTES (2 * SPX_N) +#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) + +#include "haraka_offsets.h" #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/sign.c b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/sign.c index 68db93dd62..9d0c7d1b22 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/sign.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/sign.c @@ -1,76 +1,45 @@ -#include #include #include #include #include "address.h" -#include "api.h" +#include "context.h" #include "fors.h" #include "hash.h" -#include "hash_state.h" +#include "merkle.h" +#include "nistapi.h" #include "params.h" #include "randombytes.h" #include "thash.h" #include "utils.h" #include "wots.h" - -/** - * Computes the leaf at a given address. First generates the WOTS key pair, - * then computes leaf by hashing horizontally. - */ -static void wots_gen_leaf(unsigned char *leaf, const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx, const uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - unsigned char pk[PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_WOTS_BYTES]; - uint32_t wots_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_set_type( - wots_addr, PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_set_type( - wots_pk_addr, PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_ADDR_TYPE_WOTSPK); - - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_set_keypair_addr( - wots_addr, addr_idx); - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_wots_gen_pk( - pk, sk_seed, pub_seed, wots_addr, hash_state_seeded); - - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_copy_keypair_addr( - wots_pk_addr, wots_addr); - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_thash_WOTS_LEN( - leaf, pk, pub_seed, wots_pk_addr, hash_state_seeded); -} - /* * Returns the length of a secret key, in bytes */ -size_t PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_crypto_sign_secretkeybytes(void) { - return PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_CRYPTO_SECRETKEYBYTES; +size_t crypto_sign_secretkeybytes(void) { + return CRYPTO_SECRETKEYBYTES; } /* * Returns the length of a public key, in bytes */ -size_t PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_crypto_sign_publickeybytes(void) { - return PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_CRYPTO_PUBLICKEYBYTES; +size_t crypto_sign_publickeybytes(void) { + return CRYPTO_PUBLICKEYBYTES; } /* * Returns the length of a signature, in bytes */ -size_t PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_crypto_sign_bytes(void) { - return PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_CRYPTO_BYTES; +size_t crypto_sign_bytes(void) { + return CRYPTO_BYTES; } /* * Returns the length of the seed required to generate a key pair, in bytes */ -size_t PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_crypto_sign_seedbytes(void) { - return PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_CRYPTO_SEEDBYTES; +size_t crypto_sign_seedbytes(void) { + return CRYPTO_SEEDBYTES; } /* @@ -78,35 +47,29 @@ size_t PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_crypto_sign_seedbytes(void) { * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] * Format pk: [PUB_SEED || root] */ -int PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed) { - /* We do not need the auth path in key generation, but it simplifies the - code to have just one treehash routine that computes both root and path - in one function. */ - unsigned char auth_path[PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_TREE_HEIGHT * PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N]; - uint32_t top_tree_addr[8] = {0}; - hash_state hash_state_seeded; - - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_set_layer_addr( - top_tree_addr, PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_D - 1); - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_set_type( - top_tree_addr, PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_ADDR_TYPE_HASHTREE); +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed) { + spx_ctx ctx; /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ - memcpy(sk, seed, PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_CRYPTO_SEEDBYTES); + memcpy(sk, seed, CRYPTO_SEEDBYTES); + + memcpy(pk, sk + 2 * SPX_N, SPX_N); - memcpy(pk, sk + 2 * PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N, PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N); + memcpy(ctx.pub_seed, pk, SPX_N); + memcpy(ctx.sk_seed, sk, SPX_N); /* This hook allows the hash function instantiation to do whatever preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_initialize_hash_function(&hash_state_seeded, pk, sk); + initialize_hash_function(&ctx); /* Compute root node of the top-most subtree. */ - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_treehash_TREE_HEIGHT( - sk + 3 * PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N, auth_path, sk, sk + 2 * PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N, 0, 0, - wots_gen_leaf, top_tree_addr, &hash_state_seeded); + merkle_gen_root(sk + 3 * SPX_N, &ctx); - memcpy(pk + PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N, sk + 3 * PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N, PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N); + // cleanup + free_hash_function(&ctx); + + memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); return 0; } @@ -116,31 +79,10 @@ int PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_crypto_sign_seed_keypair( * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] * Format pk: [PUB_SEED || root] */ -int PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk) { - - // guarantee alignment of pk - union { - __m128 _x[PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_CRYPTO_PUBLICKEYBYTES / 16]; - uint8_t pk[PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_CRYPTO_PUBLICKEYBYTES]; - } aligned_pk; - - // guarantee alignment of sk - union { - __m128 _x[PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_CRYPTO_SECRETKEYBYTES / 16]; - uint8_t sk[PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_CRYPTO_SECRETKEYBYTES]; - } aligned_sk; - - union { - __m128 _x[PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_CRYPTO_SEEDBYTES / 16]; - uint8_t seed[PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_CRYPTO_SEEDBYTES]; - } aligned_seed; - randombytes(aligned_seed.seed, PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_CRYPTO_SEEDBYTES); - - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_crypto_sign_seed_keypair( - aligned_pk.pk, aligned_sk.sk, aligned_seed.seed); - memcpy(pk, aligned_pk.pk, PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_CRYPTO_PUBLICKEYBYTES); - memcpy(sk, aligned_sk.sk, PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_CRYPTO_SECRETKEYBYTES); +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { + uint8_t seed[CRYPTO_SEEDBYTES]; + randombytes(seed, CRYPTO_SEEDBYTES); + crypto_sign_seed_keypair(pk, sk, seed); return 0; } @@ -148,101 +90,68 @@ int PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_crypto_sign_keypair( /** * Returns an array containing a detached signature. */ -int PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - // guarantee alignment of sk - union { - __m128 *_x; - uint8_t sk[PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_CRYPTO_SECRETKEYBYTES]; - } aligned_sk; - memcpy(aligned_sk.sk, sk, PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_CRYPTO_SECRETKEYBYTES); - sk = aligned_sk.sk; - - // guarantee alignment of sig - union { - __m128 *_x; - uint8_t sig[PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_BYTES]; - } aligned_sig; - uint8_t *orig_sig = sig; - sig = (uint8_t *)aligned_sig.sig; - - const unsigned char *sk_seed = sk; - const unsigned char *sk_prf = sk + PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N; - const unsigned char *pk = sk + 2 * PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N; - const unsigned char *pub_seed = pk; - - unsigned char optrand[PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N]; - unsigned char mhash[PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_FORS_MSG_BYTES]; - unsigned char root[PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N]; +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk) { + spx_ctx ctx; + + const uint8_t *sk_prf = sk + SPX_N; + const uint8_t *pk = sk + 2 * SPX_N; + + uint8_t optrand[SPX_N]; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t root[SPX_N]; uint32_t i; uint64_t tree; uint32_t idx_leaf; uint32_t wots_addr[8] = {0}; uint32_t tree_addr[8] = {0}; - hash_state hash_state_seeded; + memcpy(ctx.sk_seed, sk, SPX_N); + memcpy(ctx.pub_seed, pk, SPX_N); /* This hook allows the hash function instantiation to do whatever preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_initialize_hash_function( - &hash_state_seeded, - pub_seed, sk_seed); + initialize_hash_function(&ctx); - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_set_type( - wots_addr, PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_set_type( - tree_addr, PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_ADDR_TYPE_HASHTREE); + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); /* Optionally, signing can be made non-deterministic using optrand. This can help counter side-channel attacks that would benefit from getting a large number of traces when the signer uses the same nodes. */ - randombytes(optrand, PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N); + randombytes(optrand, SPX_N); /* Compute the digest randomization value. */ - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_gen_message_random( - sig, sk_prf, optrand, m, mlen, &hash_state_seeded); + gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); /* Derive the message digest and leaf index from R, PK and M. */ - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N; + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_set_keypair_addr( - wots_addr, idx_leaf); + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); /* Sign the message hash using FORS. */ - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_fors_sign( - sig, root, mhash, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_FORS_BYTES; - - for (i = 0; i < PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_D; i++) { - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_set_tree_addr(tree_addr, tree); - - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_set_keypair_addr( - wots_addr, idx_leaf); - - /* Compute a WOTS signature. */ - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_wots_sign( - sig, root, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_WOTS_BYTES; - - /* Compute the authentication path for the used WOTS leaf. */ - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_treehash_TREE_HEIGHT( - root, sig, sk_seed, pub_seed, idx_leaf, 0, - wots_gen_leaf, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_TREE_HEIGHT * PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N; + fors_sign(sig, root, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); + sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_TREE_HEIGHT; + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; } - memcpy(orig_sig, aligned_sig.sig, PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_BYTES); - *siglen = PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_BYTES; + free_hash_function(&ctx); + + *siglen = SPX_BYTES; return 0; } @@ -250,23 +159,14 @@ int PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_crypto_sign_signature( /** * Verifies a detached signature and message under a given public key. */ -int PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk) { - // guarantee alignment of pk - union { - __m128 *_x; - uint8_t pk[PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_CRYPTO_PUBLICKEYBYTES]; - } aligned_pk; - memcpy(aligned_pk.pk, pk, PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_CRYPTO_PUBLICKEYBYTES); - pk = aligned_pk.pk; - - const unsigned char *pub_seed = pk; - const unsigned char *pub_root = pk + PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N; - unsigned char mhash[PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_FORS_MSG_BYTES]; - unsigned char wots_pk[PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_WOTS_BYTES]; - unsigned char root[PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N]; - unsigned char leaf[PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N]; +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk) { + spx_ctx ctx; + const uint8_t *pub_root = pk + SPX_N; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t wots_pk[SPX_WOTS_BYTES]; + uint8_t root[SPX_N]; + uint8_t leaf[SPX_N]; unsigned int i; uint64_t tree; uint32_t idx_leaf; @@ -274,77 +174,66 @@ int PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_crypto_sign_verify( uint32_t tree_addr[8] = {0}; uint32_t wots_pk_addr[8] = {0}; - hash_state hash_state_seeded; - - if (siglen != PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_BYTES) { + if (siglen != SPX_BYTES) { return -1; } + memcpy(ctx.pub_seed, pk, SPX_N); + /* This hook allows the hash function instantiation to do whatever preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_initialize_hash_function( - &hash_state_seeded, - pub_seed, NULL); + initialize_hash_function(&ctx); - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_set_type( - wots_addr, PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_set_type( - tree_addr, PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_ADDR_TYPE_HASHTREE); - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_set_type( - wots_pk_addr, PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_ADDR_TYPE_WOTSPK); + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); /* Derive the message digest and leaf index from R || PK || M. */ - /* The additional PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N is a result of the hash domain separator. */ - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N; + /* The additional SPX_N is a result of the hash domain separator. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; /* Layer correctly defaults to 0, so no need to set_layer_addr */ - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_set_keypair_addr( - wots_addr, idx_leaf); + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_fors_pk_from_sig( - root, sig, mhash, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_FORS_BYTES; + fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; /* For each subtree.. */ - for (i = 0; i < PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_D; i++) { - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_set_tree_addr(tree_addr, tree); + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_set_keypair_addr( - wots_addr, idx_leaf); + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_copy_keypair_addr( - wots_pk_addr, wots_addr); + copy_keypair_addr(wots_pk_addr, wots_addr); /* The WOTS public key is only correct if the signature was correct. */ /* Initially, root is the FORS pk, but on subsequent iterations it is the root of the subtree below the currently processed subtree. */ - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_wots_pk_from_sig( - wots_pk, sig, root, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_WOTS_BYTES; + wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); + sig += SPX_WOTS_BYTES; /* Compute the leaf node using the WOTS public key. */ - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_thash_WOTS_LEN( - leaf, wots_pk, pub_seed, wots_pk_addr, &hash_state_seeded); + thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); /* Compute the root node of this subtree. */ - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_compute_root( - root, leaf, idx_leaf, 0, sig, PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_TREE_HEIGHT, - pub_seed, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_TREE_HEIGHT * PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N; + compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, + &ctx, tree_addr); + sig += SPX_TREE_HEIGHT * SPX_N; /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_TREE_HEIGHT; + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; } + // cleanup + free_hash_function(&ctx); + /* Check if the root node equals the root node in the public key. */ - if (memcmp(root, pub_root, PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N) != 0) { + if (memcmp(root, pub_root, SPX_N) != 0) { return -1; } @@ -355,15 +244,14 @@ int PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_crypto_sign_verify( /** * Returns an array containing the signature followed by the message. */ -int PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk) { size_t siglen; - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_crypto_sign_signature( - sm, &siglen, m, mlen, sk); + crypto_sign_signature(sm, &siglen, m, mlen, sk); - memmove(sm + PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_BYTES, m, mlen); + memmove(sm + SPX_BYTES, m, mlen); *smlen = siglen + mlen; return 0; @@ -372,38 +260,27 @@ int PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_crypto_sign( /** * Verifies a given signature-message pair under a given public key. */ -int PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk) { - - // guarantee alignment of pk - union { - __m128 *_x; - uint8_t pk[PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_CRYPTO_PUBLICKEYBYTES]; - } aligned_pk; - memcpy(aligned_pk.pk, pk, PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_CRYPTO_PUBLICKEYBYTES); - pk = aligned_pk.pk; - - +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk) { /* The API caller does not necessarily know what size a signature should be - but SPHINCS+ signatures are always exactly PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_BYTES. */ - if (smlen < PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_BYTES) { + but SPHINCS+ signatures are always exactly SPX_BYTES. */ + if (smlen < SPX_BYTES) { memset(m, 0, smlen); *mlen = 0; return -1; } - *mlen = smlen - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_BYTES; + *mlen = smlen - SPX_BYTES; - if (PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_crypto_sign_verify( - sm, PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_BYTES, sm + PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_BYTES, *mlen, pk)) { + if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { memset(m, 0, smlen); *mlen = 0; return -1; } /* If verification was successful, move the message to the right place. */ - memmove(m, sm + PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_BYTES, *mlen); + memmove(m, sm + SPX_BYTES, *mlen); return 0; } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/thash.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/thash.h index 469836cf8a..8687ccfb4d 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/thash.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/thash.h @@ -1,28 +1,13 @@ -#ifndef PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_THASH_H -#define PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_THASH_H +#ifndef SPX_THASH_H +#define SPX_THASH_H -#include "hash_state.h" +#include "context.h" +#include "params.h" #include -void PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); +#define thash SPX_NAMESPACE(thash) +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/thash_haraka_robust.c b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/thash_haraka_robust.c index 8224bef830..109502cbc2 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/thash_haraka_robust.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/thash_haraka_robust.c @@ -2,93 +2,44 @@ #include #include "address.h" -#include "hash_state.h" #include "params.h" #include "thash.h" +#include "utils.h" #include "haraka.h" /** - * Takes an array of inblocks concatenated arrays of PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N bytes. + * Takes an array of inblocks concatenated arrays of SPX_N bytes. */ -static void PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_thash( - unsigned char *out, unsigned char *buf, - const unsigned char *in, unsigned int inblocks, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char *bitmask = buf + PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_ADDR_BYTES; +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]) { + PQCLEAN_VLA(uint8_t, buf, SPX_ADDR_BYTES + inblocks * SPX_N); + PQCLEAN_VLA(uint8_t, bitmask, inblocks * SPX_N); unsigned char outbuf[32]; unsigned char buf_tmp[64]; unsigned int i; - (void)pub_seed; /* Suppress an 'unused parameter' warning. */ - if (inblocks == 1) { /* F function */ - /* Since PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N may be smaller than 32, we need a temporary buffer. */ + /* Since SPX_N may be smaller than 32, we need a temporary buffer. */ memset(buf_tmp, 0, 64); - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_addr_to_bytes(buf_tmp, addr); + memcpy(buf_tmp, addr, 32); - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_haraka256(outbuf, buf_tmp, hash_state_seeded); - for (i = 0; i < inblocks * PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N; i++) { - buf_tmp[PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_ADDR_BYTES + i] = in[i] ^ outbuf[i]; + haraka256(outbuf, buf_tmp, ctx); + for (i = 0; i < inblocks * SPX_N; i++) { + buf_tmp[SPX_ADDR_BYTES + i] = in[i] ^ outbuf[i]; } - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_haraka512(outbuf, buf_tmp, hash_state_seeded); - memcpy(out, outbuf, PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N); + haraka512(outbuf, buf_tmp, ctx); + memcpy(out, outbuf, SPX_N); } else { /* All other tweakable hashes*/ - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_addr_to_bytes(buf, addr); - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_haraka_S( - bitmask, inblocks * PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N, buf, PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_ADDR_BYTES, hash_state_seeded); + memcpy(buf, addr, 32); + haraka_S(bitmask, inblocks * SPX_N, buf, SPX_ADDR_BYTES, ctx); - for (i = 0; i < inblocks * PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N; i++) { - buf[PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_ADDR_BYTES + i] = in[i] ^ bitmask[i]; + for (i = 0; i < inblocks * SPX_N; i++) { + buf[SPX_ADDR_BYTES + i] = in[i] ^ bitmask[i]; } - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_haraka_S( - out, PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N, buf, PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N, hash_state_seeded); + haraka_S(out, SPX_N, buf, SPX_ADDR_BYTES + inblocks * SPX_N, ctx); } } - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_ADDR_BYTES + 1 * PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N]; - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_thash( - out, buf, in, 1, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_ADDR_BYTES + 2 * PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N]; - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_thash( - out, buf, in, 2, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_ADDR_BYTES + PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_WOTS_LEN * PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N]; - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_thash( - out, buf, in, PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_WOTS_LEN, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_ADDR_BYTES + PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_FORS_TREES * PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N]; - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_thash( - out, buf, in, PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_FORS_TREES, pub_seed, addr, hash_state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/thash_haraka_robustx4.c b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/thash_haraka_robustx4.c index c27ed57c25..100808a3a5 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/thash_haraka_robustx4.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/thash_haraka_robustx4.c @@ -2,91 +2,92 @@ #include #include "address.h" -#include "haraka.h" #include "params.h" #include "thashx4.h" +#include "harakax4.h" + +#include "utils.h" + /** * 4-way parallel version of thash; takes 4x as much input and output */ -#define thashx4_variant(name, inblocks) \ - void PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_thashx4_##name(unsigned char *out0, unsigned char *out1, unsigned char *out2, \ - unsigned char *out3, const unsigned char *in0, \ - const unsigned char *in1, const unsigned char *in2, \ - const unsigned char *in3, const unsigned char *pub_seed, \ - uint32_t addrx4[4 * 8], const harakactx *state) { \ - unsigned char buf0[PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_ADDR_BYTES + (inblocks)*PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N]; \ - unsigned char buf1[PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_ADDR_BYTES + (inblocks)*PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N]; \ - unsigned char buf2[PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_ADDR_BYTES + (inblocks)*PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N]; \ - unsigned char buf3[PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_ADDR_BYTES + (inblocks)*PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N]; \ - unsigned char bitmask0[(inblocks)*PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N]; \ - unsigned char bitmask1[(inblocks)*PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N]; \ - unsigned char bitmask2[(inblocks)*PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N]; \ - unsigned char bitmask3[(inblocks)*PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N]; \ - unsigned char outbuf[32 * 4]; \ - unsigned char buf_tmp[64 * 4]; \ - unsigned int i; \ - \ - (void)pub_seed; /* Suppress an 'unused parameter' warning. */ \ - \ - if ((inblocks) == 1) { \ - memset(buf_tmp, 0, 64 * 4); \ - \ - /* Generate masks first in buffer */ \ - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_addr_to_bytes(buf_tmp, addrx4 + 0 * 8); \ - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_addr_to_bytes(buf_tmp + 32, addrx4 + 1 * 8); \ - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_addr_to_bytes(buf_tmp + 64, addrx4 + 2 * 8); \ - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_addr_to_bytes(buf_tmp + 96, addrx4 + 3 * 8); \ - \ - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_haraka256x4(outbuf, buf_tmp, state); \ - \ - /* move addresses to make room for inputs; zero old values */ \ - memcpy(buf_tmp + 192, buf_tmp + 96, PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_ADDR_BYTES); \ - memcpy(buf_tmp + 128, buf_tmp + 64, PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_ADDR_BYTES); \ - memcpy(buf_tmp + 64, buf_tmp + 32, PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_ADDR_BYTES); \ - /* skip memcpy(buf_tmp, buf_tmp, PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_ADDR_BYTES); already in place */ \ - \ - /* skip memset(buf_tmp, 0, PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_ADDR_BYTES); remained untouched */ \ - memset(buf_tmp + 32, 0, PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_ADDR_BYTES); \ - /* skip memset(buf_tmp + 64, 0, PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_ADDR_BYTES); contains addr1 */ \ - memset(buf_tmp + 96, 0, PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_ADDR_BYTES); \ - \ - for (i = 0; i < PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N; i++) { \ - buf_tmp[PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_ADDR_BYTES + i] = in0[i] ^ outbuf[i]; \ - buf_tmp[PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_ADDR_BYTES + i + 64] = in1[i] ^ outbuf[i + 32]; \ - buf_tmp[PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_ADDR_BYTES + i + 128] = in2[i] ^ outbuf[i + 64]; \ - buf_tmp[PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_ADDR_BYTES + i + 192] = in3[i] ^ outbuf[i + 96]; \ - } \ - \ - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_haraka512x4(outbuf, buf_tmp, state); \ - \ - memcpy(out0, outbuf, PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N); \ - memcpy(out1, outbuf + 32, PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N); \ - memcpy(out2, outbuf + 64, PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N); \ - memcpy(out3, outbuf + 96, PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N); \ - } else { \ - /* All other tweakable hashes*/ \ - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_addr_to_bytes(buf0, addrx4 + 0 * 8); \ - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_addr_to_bytes(buf1, addrx4 + 1 * 8); \ - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_addr_to_bytes(buf2, addrx4 + 2 * 8); \ - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_addr_to_bytes(buf3, addrx4 + 3 * 8); \ - \ - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_haraka_Sx4(bitmask0, bitmask1, bitmask2, bitmask3, (inblocks)*PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N, buf0, buf1, \ - buf2, buf3, PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_ADDR_BYTES, state); \ - \ - for (i = 0; i < (inblocks)*PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N; i++) { \ - buf0[PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_ADDR_BYTES + i] = in0[i] ^ bitmask0[i]; \ - buf1[PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_ADDR_BYTES + i] = in1[i] ^ bitmask1[i]; \ - buf2[PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_ADDR_BYTES + i] = in2[i] ^ bitmask2[i]; \ - buf3[PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_ADDR_BYTES + i] = in3[i] ^ bitmask3[i]; \ - } \ - \ - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_haraka_Sx4(out0, out1, out2, out3, PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N, buf0, buf1, buf2, buf3, \ - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_ADDR_BYTES + (inblocks)*PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N, state); \ - } \ - } +#define thashx4 SPX_NAMESPACE(thashx4) +void thashx4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addrx4[4 * 8]) { + PQCLEAN_VLA(unsigned char, buf0, SPX_ADDR_BYTES + inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, buf1, SPX_ADDR_BYTES + inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, buf2, SPX_ADDR_BYTES + inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, buf3, SPX_ADDR_BYTES + inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, bitmask0, inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, bitmask1, inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, bitmask2, inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, bitmask3, inblocks * SPX_N); + unsigned char outbuf[32 * 4]; + unsigned char buf_tmp[64 * 4]; + unsigned int i; + + if (inblocks == 1) { + memset(buf_tmp, 0, 64 * 4); + + // Generate masks first in buffer + memcpy(buf_tmp, addrx4 + 0 * 8, 32); + memcpy(buf_tmp + 32, addrx4 + 1 * 8, 32); + memcpy(buf_tmp + 64, addrx4 + 2 * 8, 32); + memcpy(buf_tmp + 96, addrx4 + 3 * 8, 32); + + haraka256x4(outbuf, buf_tmp, ctx); + + /* move addresses to make room for inputs; zero old values */ + memcpy(buf_tmp + 192, buf_tmp + 96, SPX_ADDR_BYTES); + memcpy(buf_tmp + 128, buf_tmp + 64, SPX_ADDR_BYTES); + memcpy(buf_tmp + 64, buf_tmp + 32, SPX_ADDR_BYTES); + /* skip memcpy(buf_tmp, buf_tmp, SPX_ADDR_BYTES); already in place */ -thashx4_variant(1, 1) -thashx4_variant(2, 2) -thashx4_variant(WOTS_LEN, PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_WOTS_LEN) -thashx4_variant(FORS_TREES, PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_FORS_TREES) + /* skip memset(buf_tmp, 0, SPX_ADDR_BYTES); remained untouched */ + memset(buf_tmp + 32, 0, SPX_ADDR_BYTES); + /* skip memset(buf_tmp + 64, 0, SPX_ADDR_BYTES); contains addr1 */ + memset(buf_tmp + 96, 0, SPX_ADDR_BYTES); + + for (i = 0; i < SPX_N; i++) { + buf_tmp[SPX_ADDR_BYTES + i] = in0[i] ^ outbuf[i]; + buf_tmp[SPX_ADDR_BYTES + i + 64] = in1[i] ^ outbuf[i + 32]; + buf_tmp[SPX_ADDR_BYTES + i + 128] = in2[i] ^ outbuf[i + 64]; + buf_tmp[SPX_ADDR_BYTES + i + 192] = in3[i] ^ outbuf[i + 96]; + } + + haraka512x4(outbuf, buf_tmp, ctx); + + memcpy(out0, outbuf, SPX_N); + memcpy(out1, outbuf + 32, SPX_N); + memcpy(out2, outbuf + 64, SPX_N); + memcpy(out3, outbuf + 96, SPX_N); + } else { + /* All other tweakable hashes*/ + memcpy(buf0, addrx4 + 0 * 8, 32); + memcpy(buf1, addrx4 + 1 * 8, 32); + memcpy(buf2, addrx4 + 2 * 8, 32); + memcpy(buf3, addrx4 + 3 * 8, 32); + + haraka_Sx4(bitmask0, bitmask1, bitmask2, bitmask3, inblocks * SPX_N, + buf0, buf1, buf2, buf3, SPX_ADDR_BYTES, ctx); + + for (i = 0; i < inblocks * SPX_N; i++) { + buf0[SPX_ADDR_BYTES + i] = in0[i] ^ bitmask0[i]; + buf1[SPX_ADDR_BYTES + i] = in1[i] ^ bitmask1[i]; + buf2[SPX_ADDR_BYTES + i] = in2[i] ^ bitmask2[i]; + buf3[SPX_ADDR_BYTES + i] = in3[i] ^ bitmask3[i]; + } + + haraka_Sx4(out0, out1, out2, out3, SPX_N, + buf0, buf1, buf2, buf3, SPX_ADDR_BYTES + inblocks * SPX_N, + ctx); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/thashx4.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/thashx4.h index a63aa23502..64798a3727 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/thashx4.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/thashx4.h @@ -1,25 +1,20 @@ -#ifndef PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_THASHX4_H -#define PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_THASHX4_H +#ifndef SPX_THASHX4_H +#define SPX_THASHX4_H #include -#include "hash_state.h" +#include "context.h" +#include "params.h" -#define thashx4_header(inblocks) \ - void PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_thashx4_##inblocks(unsigned char *out0, \ - unsigned char *out1, \ - unsigned char *out2, \ - unsigned char *out3, \ - const unsigned char *in0, \ - const unsigned char *in1, \ - const unsigned char *in2, \ - const unsigned char *in3, \ - const unsigned char *pub_seed, uint32_t addrx4[4*8], \ - const hash_state *state_seeded) - -thashx4_header(1); -thashx4_header(2); -thashx4_header(WOTS_LEN); -thashx4_header(FORS_TREES); +#define thashx4 SPX_NAMESPACE(thashx4) +void thashx4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addrx4[4 * 8]); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/utils.c b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/utils.c index b6e9bad95e..177b541fb9 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/utils.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/utils.c @@ -1,34 +1,41 @@ -#include #include +#include "utils.h" + #include "address.h" #include "hash.h" -#include "hash_state.h" #include "params.h" #include "thash.h" -#include "utils.h" /** * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. */ -void PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in) { +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in) { + int i; /* Iterate over out in decreasing order, for big-endianness. */ - for (size_t i = outlen; i > 0; i--) { - out[i - 1] = in & 0xff; + for (i = (signed int)outlen - 1; i >= 0; i--) { + out[i] = in & 0xff; in = in >> 8; } } +void u32_to_bytes(unsigned char *out, uint32_t in) { + out[0] = (unsigned char)(in >> 24); + out[1] = (unsigned char)(in >> 16); + out[2] = (unsigned char)(in >> 8); + out[3] = (unsigned char)in; +} + /** * Converts the inlen bytes in 'in' from big-endian byte order to an integer. */ -unsigned long long PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_bytes_to_ull( - const unsigned char *in, size_t inlen) { +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { unsigned long long retval = 0; + unsigned int i; - for (size_t i = 0; i < inlen; i++) { + for (i = 0; i < inlen; i++) { retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); } return retval; @@ -38,94 +45,80 @@ unsigned long long PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_bytes_to_ull( * Computes a root node given a leaf and an auth path. * Expects address to be complete other than the tree_height and tree_index. */ -void PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]) { uint32_t i; - unsigned char buffer[2 * PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N]; + unsigned char buffer[2 * SPX_N]; /* If leaf_idx is odd (last bit = 1), current path element is a right child and auth_path has to go left. Otherwise it is the other way around. */ if (leaf_idx & 1) { - memcpy(buffer + PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N, leaf, PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N); + memcpy(buffer + SPX_N, leaf, SPX_N); + memcpy(buffer, auth_path, SPX_N); } else { - memcpy(buffer, leaf, PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N); - memcpy(buffer + PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N, auth_path, PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N); + memcpy(buffer, leaf, SPX_N); + memcpy(buffer + SPX_N, auth_path, SPX_N); } - auth_path += PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N; + auth_path += SPX_N; for (i = 0; i < tree_height - 1; i++) { leaf_idx >>= 1; idx_offset >>= 1; /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_set_tree_height(addr, i + 1); - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_set_tree_index( - addr, leaf_idx + idx_offset); + set_tree_height(addr, i + 1); + set_tree_index(addr, leaf_idx + idx_offset); /* Pick the right or left neighbor, depending on parity of the node. */ if (leaf_idx & 1) { - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_thash_2( - buffer + PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N); + thash(buffer + SPX_N, buffer, 2, ctx, addr); + memcpy(buffer, auth_path, SPX_N); } else { - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_thash_2( - buffer, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer + PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N, auth_path, PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N); + thash(buffer, buffer, 2, ctx, addr); + memcpy(buffer + SPX_N, auth_path, SPX_N); } - auth_path += PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N; + auth_path += SPX_N; } /* The last iteration is exceptional; we do not copy an auth_path node. */ leaf_idx >>= 1; idx_offset >>= 1; - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_set_tree_height(addr, tree_height); - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_set_tree_index( - addr, leaf_idx + idx_offset); - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_thash_2( - root, buffer, pub_seed, addr, hash_state_seeded); + set_tree_height(addr, tree_height); + set_tree_index(addr, leaf_idx + idx_offset); + thash(root, buffer, 2, ctx, addr); } /** * For a given leaf index, computes the authentication path and the resulting * root node using Merkle's TreeHash algorithm. * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_ADDR_TYPE_FORSTREE). + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). * Applies the offset idx_offset to indices before building addresses, so that * it is possible to continue counting indices across trees. */ -static void PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_treehash( - unsigned char *root, unsigned char *auth_path, - unsigned char *stack, unsigned int *heights, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - +void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx * /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]) { + PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); + PQCLEAN_VLA(unsigned int, heights, tree_height + 1); unsigned int offset = 0; uint32_t idx; uint32_t tree_idx; for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { /* Add the next leaf node to the stack. */ - gen_leaf(stack + offset * PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N, - sk_seed, pub_seed, idx + idx_offset, tree_addr, - hash_state_seeded); + gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); offset++; heights[offset - 1] = 0; /* If this is a node we need for the auth path.. */ if ((leaf_idx ^ 0x1) == idx) { - memcpy(auth_path, stack + (offset - 1)*PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N, PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N); + memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); } /* While the top-most nodes are of equal height.. */ @@ -134,66 +127,22 @@ static void PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_treehash( tree_idx = (idx >> (heights[offset - 1] + 1)); /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_set_tree_height( - tree_addr, heights[offset - 1] + 1); - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_set_tree_index( - tree_addr, tree_idx + (idx_offset >> (heights[offset - 1] + 1))); + set_tree_height(tree_addr, heights[offset - 1] + 1); + set_tree_index(tree_addr, + tree_idx + (idx_offset >> (heights[offset - 1] + 1))); /* Hash the top-most nodes from the stack together. */ - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_thash_2( - stack + (offset - 2)*PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N, stack + (offset - 2)*PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N, - pub_seed, tree_addr, hash_state_seeded); + thash(stack + (offset - 2)*SPX_N, + stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); offset--; /* Note that the top-most node is now one layer higher. */ heights[offset - 1]++; /* If this is a node we need for the auth path.. */ if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_path + heights[offset - 1]*PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N, - stack + (offset - 1)*PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N, PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N); + memcpy(auth_path + heights[offset - 1]*SPX_N, + stack + (offset - 1)*SPX_N, SPX_N); } } } - memcpy(root, stack, PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N); -} - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_FORS_HEIGHT + 1)*PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N]; - unsigned int heights[PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_FORS_HEIGHT + 1]; - - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_FORS_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_TREE_HEIGHT + 1)*PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N]; - unsigned int heights[PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_TREE_HEIGHT + 1]; - - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_TREE_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); + memcpy(root, stack, SPX_N); } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/utils.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/utils.h index 7715b4ec6a..64f5d5a53a 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/utils.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/utils.h @@ -1,64 +1,58 @@ -#ifndef PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_UTILS_H -#define PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_UTILS_H +#ifndef SPX_UTILS_H +#define SPX_UTILS_H -#include "hash_state.h" -#include "params.h" -#include #include +#include "compat.h" +#include "context.h" +#include "params.h" + + +/* To support MSVC use alloca() instead of VLAs. See #20. */ + + /** * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. */ -void PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in); +#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in); +#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) +void u32_to_bytes(unsigned char *out, uint32_t in); /** * Converts the inlen bytes in 'in' from big-endian byte order to an integer. */ -unsigned long long PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_bytes_to_ull( - const unsigned char *in, size_t inlen); +#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); /** * Computes a root node given a leaf and an auth path. * Expects address to be complete other than the tree_height and tree_index. */ -void PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); +#define compute_root SPX_NAMESPACE(compute_root) +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]); /** * For a given leaf index, computes the authentication path and the resulting * root node using Merkle's TreeHash algorithm. * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_ADDR_TYPE_FORSTREE). + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). * Applies the offset idx_offset to indices before building addresses, so that * it is possible to continue counting indices across trees. */ -void PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); +#define treehash SPX_NAMESPACE(treehash) +void treehash(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx *ctx /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]); -void PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/utilsx4.c b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/utilsx4.c index c7f91266d8..1638677194 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/utilsx4.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/utilsx4.c @@ -1,98 +1,138 @@ +#include + +#include "utilsx4.h" + #include "address.h" #include "params.h" #include "thashx4.h" #include "utils.h" -#include "utilsx4.h" -#include - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. +/* + * Generate the entire Merkle tree, computing the authentication path for leaf_idx, + * and the resulting root node using Merkle's TreeHash algorithm. * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_ADDR_TYPE_FORSTREE). + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) + * + * This expects tree_addrx4 to be initialized to 4 parallel addr structures for + * the Merkle tree nodes + * * Applies the offset idx_offset to indices before building addresses, so that * it is possible to continue counting indices across trees. + * + * This works by using the standard Merkle tree building algorithm, except + * that each 'node' tracked is actually 4 consecutive nodes in the real tree. + * When we combine two logical nodes ABCD and WXYZ, we perform the H + * operation on adjacent real nodes, forming the parent logical node + * (AB)(CD)(WX)(YZ) + * + * When we get to the top two levels of the real tree (where there is only + * one logical node), we continue this operation two more times; the right + * most real node will by the actual root (and the other 3 nodes will be + * garbage). We follow the same thashx4 logic so that the 'extract + * authentication path components' part of the loop is still executed (and + * to simplify the code somewhat) + * + * This currently assumes tree_height >= 2; I suspect that doing an adjusting + * idx, addr_idx on the gen_leafx4 call if tree_height < 2 would fix it; since + * we don't actually use such short trees, I haven't bothered */ -#define treehashx4_variant(name, tree_height) \ - void PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_treehashx4_##name( \ - unsigned char *rootx4, unsigned char *auth_pathx4, const unsigned char *sk_seed, \ - const unsigned char *pub_seed, const uint32_t leaf_idx[4], uint32_t idx_offset[4], \ - void (*gen_leafx4)(unsigned char * /* leaf0 */, unsigned char * /* leaf1 */, \ - unsigned char * /* leaf2 */, unsigned char * /* leaf3 */, \ - const unsigned char * /* sk_seed */, \ - const unsigned char * /* pub_seed */, uint32_t /* addr_idx0 */, \ - uint32_t /* addr_idx1 */, uint32_t /* addr_idx2 */, \ - uint32_t /* addr_idx3 */, const uint32_t[8] /* tree_addr */, \ - const hash_state * /* state_seeded */), \ - uint32_t tree_addrx4[4 * 8], const hash_state *state_seeded) { \ - unsigned char stackx4[4 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N]; \ - unsigned int heights[(tree_height) + 1]; \ - unsigned int offset = 0; \ - uint32_t idx; \ - uint32_t tree_idx; \ - unsigned int j; \ - \ - for (idx = 0; idx < (uint32_t)(1 << (tree_height)); idx++) { \ - /* Add the next leaf node to the stack. */ \ - gen_leafx4(stackx4 + 0 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N + offset * PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N, \ - stackx4 + 1 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N + offset * PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N, \ - stackx4 + 2 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N + offset * PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N, \ - stackx4 + 3 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N + offset * PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N, sk_seed, \ - pub_seed, idx + idx_offset[0], idx + idx_offset[1], idx + idx_offset[2], \ - idx + idx_offset[3], tree_addrx4, state_seeded); \ - offset++; \ - heights[offset - 1] = 0; \ - \ - /* If this is a node we need for the auth path.. */ \ - for (j = 0; j < 4; j++) { \ - if ((leaf_idx[j] ^ 0x1) == idx) { \ - memcpy(auth_pathx4 + j * (tree_height)*PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N, \ - stackx4 + j * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N + (offset - 1) * PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N, \ - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N); \ - } \ - } \ - \ - /* While the top-most nodes are of equal height.. */ \ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { \ - /* Compute index of the new node, in the next layer. */ \ - tree_idx = (idx >> (heights[offset - 1] + 1)); \ - \ - /* Set the address of the node we're creating. */ \ - for (j = 0; j < 4; j++) { \ - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_set_tree_height(tree_addrx4 + j * 8, heights[offset - 1] + 1); \ - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_set_tree_index(tree_addrx4 + j * 8, \ - tree_idx + (idx_offset[j] >> (heights[offset - 1] + 1))); \ - } \ - /* Hash the top-most nodes from the stack together. */ \ - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_thashx4_2(stackx4 + 0 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N + (offset - 2) * PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N, \ - stackx4 + 1 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N + (offset - 2) * PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N, \ - stackx4 + 2 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N + (offset - 2) * PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N, \ - stackx4 + 3 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N + (offset - 2) * PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N, \ - stackx4 + 0 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N + (offset - 2) * PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N, \ - stackx4 + 1 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N + (offset - 2) * PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N, \ - stackx4 + 2 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N + (offset - 2) * PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N, \ - stackx4 + 3 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N + (offset - 2) * PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N, \ - pub_seed, tree_addrx4, state_seeded); \ - offset--; \ - /* Note that the top-most node is now one layer higher. */ \ - heights[offset - 1]++; \ - \ - /* If this is a node we need for the auth path.. */ \ - for (j = 0; j < 4; j++) { \ - if (((leaf_idx[j] >> heights[offset - 1]) ^ 0x1) == tree_idx) { \ - memcpy(auth_pathx4 + j * (tree_height)*PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N + \ - heights[offset - 1] * PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N, \ - stackx4 + j * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N + (offset - 1) * PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N, \ - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N); \ - } \ - } \ - } \ - } \ - \ - for (j = 0; j < 4; j++) { \ - memcpy(rootx4 + j * PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N, stackx4 + j * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N, PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N); \ - } \ - } +void treehashx4(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, + uint32_t tree_height, + void (*gen_leafx4)( + unsigned char * /* Where to write the leaves */, + const spx_ctx *, + uint32_t idx, void *info), + uint32_t tree_addrx4[4 * 8], + void *info) { + /* This is where we keep the intermediate nodes */ + PQCLEAN_VLA(unsigned char, stackx4, tree_height * 4 * SPX_N); + uint32_t left_adj = 0, prev_left_adj = 0; /* When we're doing the top 3 */ + /* levels, the left-most part of the tree isn't at the beginning */ + /* of current[]. These give the offset of the actual start */ + + uint32_t idx; + uint32_t max_idx = (1U << (tree_height - 2)) - 1; + for (idx = 0;; idx++) { + unsigned char current[4 * SPX_N]; /* Current logical node */ + gen_leafx4( current, ctx, 4 * idx + idx_offset, + info ); -treehashx4_variant(FORS_HEIGHT, PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_FORS_HEIGHT) + /* Now combine the freshly generated right node with previously */ + /* generated left ones */ + uint32_t internal_idx_offset = idx_offset; + uint32_t internal_idx = idx; + uint32_t internal_leaf = leaf_idx; + uint32_t h; /* The height we are in the Merkle tree */ + for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { + + /* Special processing if we're at the top of the tree */ + if (h >= tree_height - 2) { + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[3 * SPX_N], SPX_N ); + return; + } + /* The tree indexing logic is a bit off in this case */ + /* Adjust it so that the left-most node of the part of */ + /* the tree that we're processing has index 0 */ + prev_left_adj = left_adj; + left_adj = 4U - (1 << (tree_height - h - 1)); + } + + /* Check if we hit the top of the tree */ + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[3 * SPX_N], SPX_N ); + return; + } + + /* + * Check if one of the nodes we have is a part of the + * authentication path; if it is, write it out + */ + if ((((internal_idx << 2) ^ internal_leaf) & ~0x3U) == 0) { + memcpy( &auth_path[ h * SPX_N ], + ¤t[(((internal_leaf & 3) ^ 1) + prev_left_adj) * SPX_N], + SPX_N ); + } + + /* + * Check if we're at a left child; if so, stop going up the stack + * Exception: if we've reached the end of the tree, keep on going + * (so we combine the last 4 nodes into the one root node in two + * more iterations) + */ + if ((internal_idx & 1) == 0 && idx < max_idx) { + break; + } + + /* Ok, we're at a right node (or doing the top 3 levels) */ + /* Now combine the left and right logical nodes together */ + + /* Set the address of the node we're creating. */ + unsigned int j; + internal_idx_offset >>= 1; + for (j = 0; j < 4; j++) { + set_tree_height(tree_addrx4 + j * 8, h + 1); + set_tree_index(tree_addrx4 + j * 8, + (4 / 2) * (internal_idx & ~1U) + j - left_adj + internal_idx_offset ); + } + unsigned char *left = &stackx4[h * 4 * SPX_N]; + thashx4( ¤t[0 * SPX_N], + ¤t[1 * SPX_N], + ¤t[2 * SPX_N], + ¤t[3 * SPX_N], + &left [0 * SPX_N], + &left [2 * SPX_N], + ¤t[0 * SPX_N], + ¤t[2 * SPX_N], + 2, ctx, tree_addrx4); + } + + /* We've hit a left child; save the current for when we get the */ + /* corresponding right right */ + memcpy( &stackx4[h * 4 * SPX_N], current, 4 * SPX_N); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/utilsx4.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/utilsx4.h index bd61e7e461..facb874b18 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/utilsx4.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/utilsx4.h @@ -1,38 +1,30 @@ -#ifndef PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_UTILSX4_H -#define PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_UTILSX4_H - -#include "hash_state.h" -#include "params.h" +#ifndef SPX_UTILSX4_H +#define SPX_UTILSX4_H #include +#include "context.h" +#include "params.h" + /** * For a given leaf index, computes the authentication path and the resulting * root node using Merkle's TreeHash algorithm. * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_ADDR_TYPE_FORSTREE). + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). * Applies the offset idx_offset to indices before building addresses, so that * it is possible to continue counting indices across trees. + * + * This implementation uses AVX to compute internal nodes 4 at a time (in + * parallel) */ -void PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_treehashx4_FORS_HEIGHT(unsigned char *rootx4, - unsigned char *auth_pathx4, - const unsigned char *sk_seed, - const unsigned char *pub_seed, - const uint32_t leaf_idx[4], - uint32_t idx_offset[4], - void (*gen_leafx4)(unsigned char * /* leaf0 */, - unsigned char * /* leaf1 */, - unsigned char * /* leaf2 */, - unsigned char * /* leaf3 */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx0 */, - uint32_t /* addr_idx1 */, - uint32_t /* addr_idx2 */, - uint32_t /* addr_idx3 */, - const uint32_t[8] /* tree_addr */, - const hash_state * /* state_seeded */), - uint32_t tree_addrx4[4 * 8], - const hash_state *state_seeded); +#define treehashx4 SPX_NAMESPACE(treehashx4) +void treehashx4(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leafx4)( + unsigned char * /* Where to write the leaves */, + const spx_ctx * /* ctx */, + uint32_t addr_idx, void *info), + uint32_t tree_addrx4[4 * 8], void *info); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/wots.c b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/wots.c index 396e6435d5..4d5041ce05 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/wots.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/wots.c @@ -1,106 +1,104 @@ #include #include +#include "wots.h" + #include "address.h" #include "hash.h" -#include "hash_state.h" #include "hashx4.h" #include "params.h" #include "thash.h" #include "thashx4.h" #include "utils.h" -#include "wots.h" +#include "utilsx4.h" +#include "wotsx4.h" // TODO clarify address expectations, and make them more uniform. // TODO i.e. do we expect types to be set already? // TODO and do we expect modifications or copies? /** - * Computes the starting value for a chain, i.e. the secret key. - * Expects the address to be complete up to the chain address. - */ -static void wots_gen_sk(unsigned char *sk, const unsigned char *sk_seed, - uint32_t wots_addr[8], const hash_state *state_seeded) { - /* Make sure that the hash address is actually zeroed. */ - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_set_hash_addr(wots_addr, 0); - - /* Generate sk element. */ - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_prf_addr(sk, sk_seed, wots_addr, state_seeded); -} - -/** - * 4-way parallel version of wots_gen_sk; expects 4x as much space in sk + * Computes up the chains */ -static void wots_gen_skx4(unsigned char *skx4, const unsigned char *sk_seed, - uint32_t wots_addrx4[4 * 8], const hash_state *state_seeded) { - unsigned int j; - - /* Make sure that the hash address is actually zeroed. */ +static void gen_chains( + unsigned char *out, + const unsigned char *in, + unsigned int start[SPX_WOTS_LEN], + const unsigned int steps[SPX_WOTS_LEN], + const spx_ctx *ctx, + uint32_t addr[8]) { + uint32_t i, j, k, idx, watching; + int done; + unsigned char empty[SPX_N]; + unsigned char *bufs[4]; + uint32_t addrs[8 * 4]; + + int l; + uint16_t counts[SPX_WOTS_W] = { 0 }; + uint16_t idxs[SPX_WOTS_LEN]; + uint16_t total, newTotal; + + /* set addrs = {addr, addr, addr, addr} */ for (j = 0; j < 4; j++) { - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_set_hash_addr(wots_addrx4 + j * 8, 0); + memcpy(addrs + j * 8, addr, sizeof(uint32_t) * 8); } - /* Generate sk element. */ - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_prf_addrx4(skx4 + 0 * PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N, - skx4 + 1 * PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N, - skx4 + 2 * PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N, - skx4 + 3 * PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N, - sk_seed, wots_addrx4, - state_seeded); -} - -/** - * Computes the chaining function. - * out and in have to be n-byte arrays. - * - * Interprets in as start-th value of the chain. - * addr has to contain the address of the chain. - */ -static void gen_chain(unsigned char *out, const unsigned char *in, - unsigned int start, unsigned int steps, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *state_seeded) { - uint32_t i; - /* Initialize out with the value at position 'start'. */ - memcpy(out, in, PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N); + memcpy(out, in, SPX_WOTS_LEN * SPX_N); - /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_WOTS_W; i++) { - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_set_hash_addr(addr, i); - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_thash_1(out, out, pub_seed, addr, state_seeded); + /* Sort the chains in reverse order by steps using counting sort. */ + for (i = 0; i < SPX_WOTS_LEN; i++) { + counts[steps[i]]++; + } + total = 0; + for (l = SPX_WOTS_W - 1; l >= 0; l--) { + newTotal = counts[l] + total; + counts[l] = total; + total = newTotal; + } + for (i = 0; i < SPX_WOTS_LEN; i++) { + idxs[counts[steps[i]]] = (uint16_t)i; + counts[steps[i]]++; } -} -/** - * 4-way parallel version of gen_chain; expects 4x as much space in out, and - * 4x as much space in inx4. Assumes start and step identical across chains. - */ -static void gen_chainx4(unsigned char *outx4, const unsigned char *inx4, - unsigned int start, unsigned int steps, - const unsigned char *pub_seed, uint32_t addrx4[4 * 8], - const hash_state *state_seeded) { - uint32_t i; - unsigned int j; + /* We got our work cut out for us: do it! */ + for (i = 0; i < SPX_WOTS_LEN; i += 4) { + for (j = 0; j < 4 && i + j < SPX_WOTS_LEN; j++) { + idx = idxs[i + j]; + set_chain_addr(addrs + j * 8, idx); + bufs[j] = out + SPX_N * idx; + } - /* Initialize outx4 with the value at position 'start'. */ - memcpy(outx4, inx4, 4 * PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N); + /* As the chains are sorted in reverse order, we know that the first + * chain is the longest and the last one is the shortest. We keep + * an eye on whether the last chain is done and then on the one before, + * et cetera. */ + watching = 3; + done = 0; + while (i + watching >= SPX_WOTS_LEN) { + bufs[watching] = &empty[0]; + watching--; + } - /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_WOTS_W; i++) { - for (j = 0; j < 4; j++) { - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_set_hash_addr(addrx4 + j * 8, i); + for (k = 0;; k++) { + while (k == steps[idxs[i + watching]]) { + bufs[watching] = &empty[0]; + if (watching == 0) { + done = 1; + break; + } + watching--; + } + if (done) { + break; + } + for (j = 0; j < watching + 1; j++) { + set_hash_addr(addrs + j * 8, k + start[idxs[i + j]]); + } + + thashx4(bufs[0], bufs[1], bufs[2], bufs[3], + bufs[0], bufs[1], bufs[2], bufs[3], 1, ctx, addrs); } - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_thashx4_1(outx4 + 0 * PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N, - outx4 + 1 * PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N, - outx4 + 2 * PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N, - outx4 + 3 * PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N, - outx4 + 0 * PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N, - outx4 + 1 * PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N, - outx4 + 2 * PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N, - outx4 + 3 * PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N, - pub_seed, addrx4, - state_seeded); } } @@ -109,7 +107,8 @@ static void gen_chainx4(unsigned char *outx4, const unsigned char *inx4, * Interprets an array of bytes as integers in base w. * This only works when log_w is a divisor of 8. */ -static void base_w(unsigned int *output, const int out_len, const unsigned char *input) { +static void base_w(unsigned int *output, const int out_len, + const unsigned char *input) { int in = 0; int out = 0; unsigned char total = 0; @@ -122,119 +121,149 @@ static void base_w(unsigned int *output, const int out_len, const unsigned char in++; bits += 8; } - bits -= PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_WOTS_LOGW; - output[out] = (unsigned int)(total >> bits) & (PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_WOTS_W - 1); + bits -= SPX_WOTS_LOGW; + output[out] = (total >> bits) & (SPX_WOTS_W - 1); out++; } } /* Computes the WOTS+ checksum over a message (in base_w). */ -static void wots_checksum(unsigned int *csum_base_w, const unsigned int *msg_base_w) { +static void wots_checksum(unsigned int *csum_base_w, + const unsigned int *msg_base_w) { unsigned int csum = 0; - unsigned char csum_bytes[(PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_WOTS_LEN2 * PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_WOTS_LOGW + 7) / 8]; + unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; unsigned int i; /* Compute checksum. */ - for (i = 0; i < PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_WOTS_LEN1; i++) { - csum += PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_WOTS_W - 1 - msg_base_w[i]; + for (i = 0; i < SPX_WOTS_LEN1; i++) { + csum += SPX_WOTS_W - 1 - msg_base_w[i]; } /* Convert checksum to base_w. */ /* Make sure expected empty zero bits are the least significant bits. */ - csum = csum << (8 - ((PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_WOTS_LEN2 * PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_WOTS_LOGW) % 8)); - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); - base_w(csum_base_w, PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_WOTS_LEN2, csum_bytes); + csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); + ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); + base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); } /* Takes a message and derives the matching chain lengths. */ -static void chain_lengths(unsigned int *lengths, const unsigned char *msg) { - base_w(lengths, PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_WOTS_LEN1, msg); - wots_checksum(lengths + PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_WOTS_LEN1, lengths); +void chain_lengths(unsigned int *lengths, const unsigned char *msg) { + base_w(lengths, SPX_WOTS_LEN1, msg); + wots_checksum(lengths + SPX_WOTS_LEN1, lengths); } /** - * WOTS key generation. Takes a 32 byte sk_seed, expands it to WOTS private key - * elements and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. * * Writes the computed public key to 'pk'. */ -void PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_wots_gen_pk(unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *state_seeded) { +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]) { + unsigned int steps[SPX_WOTS_LEN]; + unsigned int start[SPX_WOTS_LEN]; uint32_t i; - unsigned int j; - uint32_t addrx4[4 * 8]; - unsigned char pkbuf[4 * PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N]; + chain_lengths(start, msg); - for (j = 0; j < 4; j++) { - memcpy(addrx4 + j * 8, addr, sizeof(uint32_t) * 8); - } - - /* The last iteration typically does not have complete set of 4 chains, - but because we use pkbuf, this is not an issue -- we still do as many - in parallel as possible. */ - for (i = 0; i < ((PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_WOTS_LEN + 3) & ~0x3); i += 4) { - for (j = 0; j < 4; j++) { - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_set_chain_addr(addrx4 + j * 8, i + j); - } - wots_gen_skx4(pkbuf, sk_seed, addrx4, state_seeded); - gen_chainx4(pkbuf, pkbuf, 0, PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_WOTS_W - 1, pub_seed, addrx4, state_seeded); - for (j = 0; j < 4; j++) { - if (i + j < PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_WOTS_LEN) { - memcpy(pk + (i + j)*PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N, pkbuf + j * PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N, PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N); - } - } + for (i = 0; i < SPX_WOTS_LEN; i++) { + steps[i] = SPX_WOTS_W - 1 - start[i]; } - // Get rid of unused argument variable. - (void)state_seeded; + gen_chains(pk, sig, start, steps, ctx, addr); } -/** - * Takes a n-byte message and the 32-byte sk_see to compute a signature 'sig'. +/* + * This generates 4 sequential WOTS public keys + * It also generates the WOTS signature if leaf_info indicates + * that we're signing with one of these WOTS keys */ -void PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_wots_sign(unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); +void wots_gen_leafx4(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info) { + struct leaf_info_x4 *info = v_info; + uint32_t *leaf_addr = info->leaf_addr; + uint32_t *pk_addr = info->pk_addr; + unsigned int i, j, k; + unsigned char pk_buffer[ 4 * SPX_WOTS_BYTES ]; + unsigned wots_offset = SPX_WOTS_BYTES; + unsigned char *buffer; + uint32_t wots_k_mask; + unsigned wots_sign_index; + + if (((leaf_idx ^ info->wots_sign_leaf) & ~3U) == 0) { + /* We're traversing the leaf that's signing; generate the WOTS */ + /* signature */ + wots_k_mask = 0; + wots_sign_index = info->wots_sign_leaf & 3; /* Which of of the 4 */ + /* 4 slots do the signatures come from */ + } else { + /* Nope, we're just generating pk's; turn off the signature logic */ + wots_k_mask = (uint32_t)~0; + wots_sign_index = 0; + } - for (i = 0; i < PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_WOTS_LEN; i++) { - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_set_chain_addr(addr, i); - wots_gen_sk(sig + i * PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N, sk_seed, addr, state_seeded); - gen_chain(sig + i * PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N, sig + i * PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N, 0, lengths[i], pub_seed, addr, state_seeded); + for (j = 0; j < 4; j++) { + set_keypair_addr( leaf_addr + j * 8, leaf_idx + j ); + set_keypair_addr( pk_addr + j * 8, leaf_idx + j ); } - // avoid unused argument - (void)state_seeded; -} + for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { + uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k to */ + /* the step if we're generating a signature, ~0 if we're not */ -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_WOTS_LEN]; - uint32_t i; + /* Start with the secret seed */ + for (j = 0; j < 4; j++) { + set_chain_addr(leaf_addr + j * 8, i); + set_hash_addr(leaf_addr + j * 8, 0); + set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTSPRF); + } + prf_addrx4(buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + buffer + 2 * wots_offset, + buffer + 3 * wots_offset, + ctx, leaf_addr); - chain_lengths(lengths, msg); + for (j = 0; j < 4; j++) { + set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTS); + } + + /* Iterate down the WOTS chain */ + for (k = 0;; k++) { + /* Check if one of the values we have needs to be saved as a */ + /* part of the WOTS signature */ + if (k == wots_k) { + memcpy( info->wots_sig + i * SPX_N, + buffer + wots_sign_index * wots_offset, SPX_N ); + } - for (i = 0; i < PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_WOTS_LEN; i++) { - PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_set_chain_addr(addr, i); - gen_chain(pk + i * PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N, sig + i * PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_N, - lengths[i], PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_WOTS_W - 1 - lengths[i], pub_seed, addr, - state_seeded); + /* Check if we hit the top of the chain */ + if (k == SPX_WOTS_W - 1) { + break; + } + + /* Iterate one step on all 4 chains */ + for (j = 0; j < 4; j++) { + set_hash_addr(leaf_addr + j * 8, k); + } + thashx4(buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + buffer + 2 * wots_offset, + buffer + 3 * wots_offset, + buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + buffer + 2 * wots_offset, + buffer + 3 * wots_offset, 1, ctx, leaf_addr); + } } - // avoid unused argument - (void)state_seeded; + /* Do the final thash to generate the public keys */ + thashx4(dest + 0 * SPX_N, + dest + 1 * SPX_N, + dest + 2 * SPX_N, + dest + 3 * SPX_N, + pk_buffer + 0 * wots_offset, + pk_buffer + 1 * wots_offset, + pk_buffer + 2 * wots_offset, + pk_buffer + 3 * wots_offset, SPX_WOTS_LEN, ctx, pk_addr); } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/wots.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/wots.h index eab26dd9e1..4e7692eeef 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/wots.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/wots.h @@ -1,41 +1,25 @@ -#ifndef PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_WOTS_H -#define PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_WOTS_H +#ifndef SPX_WOTS_H +#define SPX_WOTS_H -#include "hash_state.h" -#include "params.h" #include -/** - * WOTS key generation. Takes a 32 byte seed for the private key, expands it to - * a full WOTS private key and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_wots_gen_pk( - unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -/** - * Takes a n-byte message and the 32-byte seed for the private key to compute a - * signature that is placed at 'sig'. - */ -void PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_wots_sign( - unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *hash_state_seeded); +#include "context.h" +#include "params.h" /** * Takes a WOTS signature and an n-byte message, computes a WOTS public key. * * Writes the computed public key to 'pk'. */ -void PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_wots_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); +#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]); + +/* + * Compute the chain lengths needed for a given message hash + */ +#define chain_lengths SPX_NAMESPACE(chain_lengths) +void chain_lengths(unsigned int *lengths, const unsigned char *msg); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/wotsx4.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/wotsx4.h new file mode 100644 index 0000000000..cd634f1743 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/wotsx4.h @@ -0,0 +1,41 @@ +#ifndef WOTSX4_H_ +#define WOTSX4_H_ + +#include + +#include "params.h" + +/* + * This is here to provide an interface to the internal wots_gen_leafx4 + * routine. While this routine is not referenced in the package outside of + * wots.c, it is called from the stand-alone benchmark code to characterize + * the performance + */ +struct leaf_info_x4 { + unsigned char *wots_sig; + uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ + uint32_t *wots_steps; + uint32_t leaf_addr[4 * 8]; + uint32_t pk_addr[4 * 8]; +}; + +/* Macro to set the leaf_info to something 'benign', that is, it would */ +/* run with the same time as it does during the real signing process */ +/* Used only by the benchmark code */ +#define INITIALIZE_LEAF_INFO_X4(info, addr, step_buffer) { \ + (info).wots_sig = 0; \ + (info).wots_sign_leaf = ~0; \ + (info).wots_steps = step_buffer; \ + int i; \ + for (i=0; i<4; i++) { \ + memcpy( &(info).leaf_addr[8*i], addr, 32 ); \ + memcpy( &(info).pk_addr[8*i], addr, 32 ); \ + } \ + } + +#define wots_gen_leafx4 SPX_NAMESPACE(wots_gen_leafx4) +void wots_gen_leafx4(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info); + +#endif /* WOTSX4_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/address.c b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/address.c index b97822db32..d49d9f3b6b 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/address.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/address.c @@ -1,78 +1,95 @@ #include +#include #include "address.h" #include "params.h" #include "utils.h" -void PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]) { - int i; - - for (i = 0; i < 8; i++) { - PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_ull_to_bytes( - bytes + i * 4, 4, addr[i]); - } -} - -void PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_set_layer_addr( - uint32_t addr[8], uint32_t layer) { - addr[0] = layer; +/* + * Specify which level of Merkle tree (the "layer") we're working on + */ +void set_layer_addr(uint32_t addr[8], uint32_t layer) { + ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; } -void PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_set_tree_addr( - uint32_t addr[8], uint64_t tree) { - addr[1] = 0; - addr[2] = (uint32_t) (tree >> 32); - addr[3] = (uint32_t) tree; +/* + * Specify which Merkle tree within the level (the "tree address") we're working on + */ +void set_tree_addr(uint32_t addr[8], uint64_t tree) { + ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); } -void PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_set_type( - uint32_t addr[8], uint32_t type) { - addr[4] = type; +/* + * Specify the reason we'll use this address structure for, that is, what + * hash will we compute with it. This is used so that unrelated types of + * hashes don't accidentally get the same address structure. The type will be + * one of the SPX_ADDR_TYPE constants + */ +void set_type(uint32_t addr[8], uint32_t type) { + ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; } -void PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; +/* + * Copy the layer and tree fields of the address structure. This is used + * when we're doing multiple types of hashes within the same Merkle tree + */ +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); } /* These functions are used for OTS addresses. */ -void PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_set_keypair_addr( - uint32_t addr[8], uint32_t keypair) { - addr[5] = keypair; +/* + * Specify which Merkle leaf we're working on; that is, which OTS keypair + * we're talking about. + */ +void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { + /* We have > 256 OTS at the bottom of the Merkle tree; to specify */ + /* which one, we'd need to express it in two bytes */ + ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR2] = (unsigned char)(keypair >> 8); + ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; } -void PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; - out[5] = in[5]; +/* + * Copy the layer, tree and keypair fields of the address structure. This is + * used when we're doing multiple things within the same OTS keypair + */ +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); + ((unsigned char *)out)[SPX_OFFSET_KP_ADDR2] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR2]; + ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; } -void PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_set_chain_addr( - uint32_t addr[8], uint32_t chain) { - addr[6] = chain; +/* + * Specify which Merkle chain within the OTS we're working with + * (the chain address) + */ +void set_chain_addr(uint32_t addr[8], uint32_t chain) { + ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; } -void PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_set_hash_addr( - uint32_t addr[8], uint32_t hash) { - addr[7] = hash; +/* + * Specify where in the Merkle chain we are +* (the hash address) + */ +void set_hash_addr(uint32_t addr[8], uint32_t hash) { + ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; } /* These functions are used for all hash tree addresses (including FORS). */ -void PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_set_tree_height( - uint32_t addr[8], uint32_t tree_height) { - addr[6] = tree_height; +/* + * Specify the height of the node in the Merkle/FORS tree we are in + * (the tree height) + */ +void set_tree_height(uint32_t addr[8], uint32_t tree_height) { + ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; } -void PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_set_tree_index( - uint32_t addr[8], uint32_t tree_index) { - addr[7] = tree_index; +/* + * Specify the distance from the left edge of the node in the Merkle/FORS tree + * (the tree index) + */ +void set_tree_index(uint32_t addr[8], uint32_t tree_index) { + u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/address.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/address.h index d5b18e2c74..24a84eb40c 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/address.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/address.h @@ -1,50 +1,52 @@ -#ifndef PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_ADDRESS_H -#define PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_ADDRESS_H +#ifndef SPX_ADDRESS_H +#define SPX_ADDRESS_H #include -#define PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_ADDR_TYPE_WOTS 0 -#define PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_ADDR_TYPE_WOTSPK 1 -#define PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_ADDR_TYPE_HASHTREE 2 -#define PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_ADDR_TYPE_FORSTREE 3 -#define PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_ADDR_TYPE_FORSPK 4 +#include "params.h" -void PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]); +/* The hash types that are passed to set_type */ +#define SPX_ADDR_TYPE_WOTS 0 +#define SPX_ADDR_TYPE_WOTSPK 1 +#define SPX_ADDR_TYPE_HASHTREE 2 +#define SPX_ADDR_TYPE_FORSTREE 3 +#define SPX_ADDR_TYPE_FORSPK 4 +#define SPX_ADDR_TYPE_WOTSPRF 5 +#define SPX_ADDR_TYPE_FORSPRF 6 -void PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_set_layer_addr( - uint32_t addr[8], uint32_t layer); +#define set_layer_addr SPX_NAMESPACE(set_layer_addr) +void set_layer_addr(uint32_t addr[8], uint32_t layer); -void PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_set_tree_addr( - uint32_t addr[8], uint64_t tree); +#define set_tree_addr SPX_NAMESPACE(set_tree_addr) +void set_tree_addr(uint32_t addr[8], uint64_t tree); -void PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_set_type( - uint32_t addr[8], uint32_t type); +#define set_type SPX_NAMESPACE(set_type) +void set_type(uint32_t addr[8], uint32_t type); /* Copies the layer and tree part of one address into the other */ -void PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]); +#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); /* These functions are used for WOTS and FORS addresses. */ -void PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_set_keypair_addr( - uint32_t addr[8], uint32_t keypair); +#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) +void set_keypair_addr(uint32_t addr[8], uint32_t keypair); -void PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_set_chain_addr( - uint32_t addr[8], uint32_t chain); +#define set_chain_addr SPX_NAMESPACE(set_chain_addr) +void set_chain_addr(uint32_t addr[8], uint32_t chain); -void PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_set_hash_addr( - uint32_t addr[8], uint32_t hash); +#define set_hash_addr SPX_NAMESPACE(set_hash_addr) +void set_hash_addr(uint32_t addr[8], uint32_t hash); -void PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]); +#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); /* These functions are used for all hash tree addresses (including FORS). */ -void PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_set_tree_height( - uint32_t addr[8], uint32_t tree_height); +#define set_tree_height SPX_NAMESPACE(set_tree_height) +void set_tree_height(uint32_t addr[8], uint32_t tree_height); -void PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_set_tree_index( - uint32_t addr[8], uint32_t tree_index); +#define set_tree_index SPX_NAMESPACE(set_tree_index) +void set_tree_index(uint32_t addr[8], uint32_t tree_index); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/api.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/api.h index 94aa4e1ba6..feebb2d510 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/api.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/api.h @@ -4,15 +4,13 @@ #include #include - - -#define PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_CRYPTO_ALGNAME "SPHINCS+" +#define PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_CRYPTO_ALGNAME "SPHINCS+-haraka-192s-robust" #define PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_CRYPTO_SECRETKEYBYTES 96 #define PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_CRYPTO_PUBLICKEYBYTES 48 -#define PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_CRYPTO_BYTES 16224 -#define PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_CRYPTO_SEEDBYTES 72 +#define PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_CRYPTO_BYTES 16224 +#define PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_CRYPTO_SEEDBYTES 72 /* * Returns the length of a secret key, in bytes @@ -39,43 +37,41 @@ size_t PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_crypto_sign_seedbytes(void); * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] * Format pk: [root || PUB_SEED] */ -int PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed); +int PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); /* * Generates a SPHINCS+ key pair. * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] * Format pk: [root || PUB_SEED] */ -int PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk); +int PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); /** * Returns an array containing a detached signature. */ -int PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk); +int PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); /** * Verifies a detached signature and message under a given public key. */ -int PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk); +int PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, + const uint8_t *pk); /** * Returns an array containing the signature followed by the message. */ -int PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk); +int PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); /** * Verifies a given signature-message pair under a given public key. */ -int PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk); - +int PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/context.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/context.h new file mode 100644 index 0000000000..600dfb73c7 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/context.h @@ -0,0 +1,24 @@ +#ifndef SPX_CONTEXT_H +#define SPX_CONTEXT_H + +#include +#include + +#include "params.h" + +typedef struct { + uint8_t pub_seed[SPX_N]; + uint8_t sk_seed[SPX_N]; + + + uint64_t tweaked512_rc64[10][8]; + uint32_t tweaked256_rc32[10][8]; +} spx_ctx; + +#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) +void initialize_hash_function(spx_ctx *ctx); + +#define free_hash_function SPX_NAMESPACE(free_hash_function) +void free_hash_function(spx_ctx *ctx); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/context_haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/context_haraka.c new file mode 100644 index 0000000000..f1cd7e3664 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/context_haraka.c @@ -0,0 +1,11 @@ +#include "context.h" +#include "haraka.h" + +void initialize_hash_function(spx_ctx *ctx) { + tweak_constants(ctx); +} + +// we don't support heap-based haraka right now +void free_hash_function(spx_ctx *ctx) { + (void)ctx; // suppress unused variable warnings +} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/fors.c b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/fors.c index 3866d53982..96ca72e986 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/fors.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/fors.c @@ -2,58 +2,58 @@ #include #include -#include "address.h" #include "fors.h" + +#include "address.h" #include "hash.h" -#include "hash_state.h" #include "thash.h" #include "utils.h" +#include "utilsx1.h" -static void fors_gen_sk(unsigned char *sk, const unsigned char *sk_seed, - uint32_t fors_leaf_addr[8], const hash_state *hash_state_seeded) { - PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_prf_addr( - sk, sk_seed, fors_leaf_addr, hash_state_seeded); +static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + prf_addr(sk, ctx, fors_leaf_addr); } static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, - const unsigned char *pub_seed, - uint32_t fors_leaf_addr[8], - const hash_state *hash_state_seeded) { - PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_thash_1( - leaf, sk, pub_seed, fors_leaf_addr, hash_state_seeded); + const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + thash(leaf, sk, 1, ctx, fors_leaf_addr); } -static void fors_gen_leaf(unsigned char *leaf, const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx, const uint32_t fors_tree_addr[8], - const hash_state *hash_state_seeded) { - uint32_t fors_leaf_addr[8] = {0}; - - /* Only copy the parts that must be kept in fors_leaf_addr. */ - PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_copy_keypair_addr( - fors_leaf_addr, fors_tree_addr); - PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_set_type( - fors_leaf_addr, PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_set_tree_index( - fors_leaf_addr, addr_idx); - - fors_gen_sk(leaf, sk_seed, fors_leaf_addr, hash_state_seeded); - fors_sk_to_leaf(leaf, leaf, pub_seed, fors_leaf_addr, hash_state_seeded); +struct fors_gen_leaf_info { + uint32_t leaf_addrx[8]; +}; + +static void fors_gen_leafx1(unsigned char *leaf, + const spx_ctx *ctx, + uint32_t addr_idx, void *info) { + struct fors_gen_leaf_info *fors_info = info; + uint32_t *fors_leaf_addr = fors_info->leaf_addrx; + + /* Only set the parts that the caller doesn't set */ + set_tree_index(fors_leaf_addr, addr_idx); + set_type(fors_leaf_addr, SPX_ADDR_TYPE_FORSPRF); + fors_gen_sk(leaf, ctx, fors_leaf_addr); + + set_type(fors_leaf_addr, SPX_ADDR_TYPE_FORSTREE); + fors_sk_to_leaf(leaf, leaf, + ctx, fors_leaf_addr); } /** - * Interprets m as PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_FORS_HEIGHT-bit unsigned integers. - * Assumes m contains at least PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_FORS_TREES bits. - * Assumes indices has space for PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_FORS_TREES integers. + * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + * Assumes indices has space for SPX_FORS_TREES integers. */ static void message_to_indices(uint32_t *indices, const unsigned char *m) { unsigned int i, j; unsigned int offset = 0; - for (i = 0; i < PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_FORS_TREES; i++) { + for (i = 0; i < SPX_FORS_TREES; i++) { indices[i] = 0; - for (j = 0; j < PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_FORS_HEIGHT; j++) { - indices[i] ^= (((uint32_t)m[offset >> 3] >> (offset & 0x7)) & 0x1) << j; + for (j = 0; j < SPX_FORS_HEIGHT; j++) { + indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); offset++; } } @@ -61,55 +61,51 @@ static void message_to_indices(uint32_t *indices, const unsigned char *m) { /** * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_FORS_TREES bits. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. */ -void PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_fors_sign( - unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *hash_state_seeded) { - uint32_t indices[PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_FORS_TREES]; - unsigned char roots[PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_FORS_TREES * PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_N]; +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; uint32_t fors_tree_addr[8] = {0}; + struct fors_gen_leaf_info fors_info = {0}; + uint32_t *fors_leaf_addr = fors_info.leaf_addrx; uint32_t fors_pk_addr[8] = {0}; uint32_t idx_offset; unsigned int i; - PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_copy_keypair_addr( - fors_tree_addr, fors_addr); - PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_copy_keypair_addr( - fors_pk_addr, fors_addr); + copy_keypair_addr(fors_tree_addr, fors_addr); + copy_keypair_addr(fors_leaf_addr, fors_addr); - PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_set_type( - fors_tree_addr, PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_set_type( - fors_pk_addr, PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_ADDR_TYPE_FORSPK); + copy_keypair_addr(fors_pk_addr, fors_addr); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); message_to_indices(indices, m); - for (i = 0; i < PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_FORS_TREES; i++) { - idx_offset = i * (1 << PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_FORS_HEIGHT); + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); - PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_set_tree_height( - fors_tree_addr, 0); - PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_set_tree_index( - fors_tree_addr, indices[i] + idx_offset); + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); /* Include the secret key part that produces the selected leaf node. */ - fors_gen_sk(sig, sk_seed, fors_tree_addr, hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_N; + fors_gen_sk(sig, ctx, fors_tree_addr); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + sig += SPX_N; /* Compute the authentication path for this leaf node. */ - PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_treehash_FORS_HEIGHT( - roots + i * PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_N, sig, sk_seed, pub_seed, - indices[i], idx_offset, fors_gen_leaf, fors_tree_addr, - hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_N * PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_FORS_HEIGHT; + treehashx1(roots + i * SPX_N, sig, ctx, + indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx1, + fors_tree_addr, &fors_info); + + sig += SPX_N * SPX_FORS_HEIGHT; } /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_thash_FORS_TREES( - pk, roots, pub_seed, fors_pk_addr, hash_state_seeded); + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); } /** @@ -117,45 +113,44 @@ void PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_fors_sign( * This can be used for verification by comparing to a known public key, or to * subsequently verify a signature on the derived public key. The latter is the * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_FORS_TREES bits. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. */ -void PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_fors_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, const uint32_t fors_addr[8], - const hash_state *hash_state_seeded) { - uint32_t indices[PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_FORS_TREES]; - unsigned char roots[PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_FORS_TREES * PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_N]; - unsigned char leaf[PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_N]; +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + unsigned char leaf[SPX_N]; uint32_t fors_tree_addr[8] = {0}; uint32_t fors_pk_addr[8] = {0}; uint32_t idx_offset; unsigned int i; - PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_copy_keypair_addr(fors_tree_addr, fors_addr); - PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_copy_keypair_addr(fors_pk_addr, fors_addr); + copy_keypair_addr(fors_tree_addr, fors_addr); + copy_keypair_addr(fors_pk_addr, fors_addr); - PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_set_type(fors_tree_addr, PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_set_type(fors_pk_addr, PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_ADDR_TYPE_FORSPK); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); message_to_indices(indices, m); - for (i = 0; i < PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_FORS_TREES; i++) { - idx_offset = i * (1 << PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_FORS_HEIGHT); + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); - PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_set_tree_height(fors_tree_addr, 0); - PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_set_tree_index(fors_tree_addr, indices[i] + idx_offset); + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); /* Derive the leaf from the included secret key part. */ - fors_sk_to_leaf(leaf, sig, pub_seed, fors_tree_addr, hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_N; + fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); + sig += SPX_N; /* Derive the corresponding root node of this tree. */ - PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_compute_root(roots + i * PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_N, leaf, indices[i], idx_offset, sig, - PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_FORS_HEIGHT, pub_seed, fors_tree_addr, hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_N * PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_FORS_HEIGHT; + compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, + sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); + sig += SPX_N * SPX_FORS_HEIGHT; } /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_thash_FORS_TREES(pk, roots, pub_seed, fors_pk_addr, hash_state_seeded); + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/fors.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/fors.h index 2cbb3f8de9..509140a178 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/fors.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/fors.h @@ -1,32 +1,32 @@ -#ifndef PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_FORS_H -#define PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_FORS_H +#ifndef SPX_FORS_H +#define SPX_FORS_H #include -#include "hash_state.h" +#include "context.h" #include "params.h" /** * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_FORS_TREES bits. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. */ -void PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_fors_sign( - unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *hash_state_seeded); +#define fors_sign SPX_NAMESPACE(fors_sign) +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); /** * Derives the FORS public key from a signature. * This can be used for verification by comparing to a known public key, or to * subsequently verify a signature on the derived public key. The latter is the * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_FORS_TREES bits. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. */ -void PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_fors_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, const uint32_t fors_addr[8], - const hash_state *hash_state_seeded); +#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/haraka.c index 68eb00a61d..a4944913b5 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/haraka.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/haraka.c @@ -6,12 +6,13 @@ * by Thomas Pornin */ -#include #include +#include #include #include #include "haraka.h" +#include "utils.h" #define HARAKAS_RATE 32 @@ -656,76 +657,62 @@ static void interleave_constant32(uint32_t *out, const unsigned char *in) { br_aes_ct_ortho(out); } -void PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_tweak_constants( - harakactx *state, - const unsigned char *pk_seed, const unsigned char *sk_seed, - unsigned long long seed_length) { +void tweak_constants(spx_ctx *ctx) { unsigned char buf[40 * 16]; int i; /* Use the standard constants to generate tweaked ones. */ - memcpy((uint8_t *)state->tweaked512_rc64, (uint8_t *)haraka512_rc64, 40 * 16); - - /* Constants for sk.seed */ - if (sk_seed != NULL) { - PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_haraka_S( - buf, 40 * 16, sk_seed, seed_length, state); - - /* Interleave constants */ - for (i = 0; i < 10; i++) { - interleave_constant32(state->tweaked256_rc32_sseed[i], buf + 32 * i); - } - } + memcpy((uint8_t *)ctx->tweaked512_rc64, (uint8_t *)haraka512_rc64, 40 * 16); /* Constants for pk.seed */ - PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_haraka_S( - buf, 40 * 16, pk_seed, seed_length, state); + haraka_S(buf, 40 * 16, ctx->pub_seed, SPX_N, ctx); for (i = 0; i < 10; i++) { - interleave_constant32(state->tweaked256_rc32[i], buf + 32 * i); - interleave_constant(state->tweaked512_rc64[i], buf + 64 * i); + interleave_constant32(ctx->tweaked256_rc32[i], buf + 32 * i); + interleave_constant(ctx->tweaked512_rc64[i], buf + 64 * i); } } -static void haraka_S_absorb(unsigned char *s, +static void haraka_S_absorb(unsigned char *s, unsigned int r, const unsigned char *m, unsigned long long mlen, - unsigned char p, const harakactx *state) { + unsigned char p, const spx_ctx *ctx) { unsigned long long i; - unsigned char t[HARAKAS_RATE]; + PQCLEAN_VLA(uint8_t, t, r); - while (mlen >= HARAKAS_RATE) { + while (mlen >= r) { /* XOR block to state */ - for (i = 0; i < HARAKAS_RATE; ++i) { + for (i = 0; i < r; ++i) { s[i] ^= m[i]; } - PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_haraka512_perm(s, s, state); - mlen -= HARAKAS_RATE; - m += HARAKAS_RATE; + haraka512_perm(s, s, ctx); + mlen -= r; + m += r; } - for (i = 0; i < HARAKAS_RATE; ++i) { + for (i = 0; i < r; ++i) { t[i] = 0; } for (i = 0; i < mlen; ++i) { t[i] = m[i]; } t[i] = p; - t[HARAKAS_RATE - 1] |= 128; - for (i = 0; i < HARAKAS_RATE; ++i) { + t[r - 1] |= 128; + for (i = 0; i < r; ++i) { s[i] ^= t[i]; } } static void haraka_S_squeezeblocks(unsigned char *h, unsigned long long nblocks, - unsigned char *s, const harakactx *state) { + unsigned char *s, unsigned int r, + const spx_ctx *ctx) { while (nblocks > 0) { - PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_haraka512_perm(s, s, state); + haraka512_perm(s, s, ctx); memcpy(h, s, HARAKAS_RATE); - h += HARAKAS_RATE; + h += r; nblocks--; } } -void PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_haraka_S_inc_init(uint8_t *s_inc) { +void haraka_S_inc_init(uint8_t *s_inc) { size_t i; for (i = 0; i < 64; i++) { @@ -734,7 +721,8 @@ void PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_haraka_S_inc_init(uint8_t *s_inc) { s_inc[64] = 0; } -void PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, const harakactx *state) { +void haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, + const spx_ctx *ctx) { size_t i; /* Recall that s_inc[64] is the non-absorbed bytes xored into the state */ @@ -745,19 +733,19 @@ void PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_haraka_S_inc_absorb(uint8_t *s_inc, c s_inc[s_inc[64] + i] ^= m[i]; } mlen -= (size_t)(HARAKAS_RATE - s_inc[64]); - m += HARAKAS_RATE - s_inc[64]; + m += HARAKAS_RATE - (uint8_t)s_inc[64]; s_inc[64] = 0; - PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_haraka512_perm(s_inc, s_inc, state); + haraka512_perm(s_inc, s_inc, ctx); } for (i = 0; i < mlen; i++) { s_inc[s_inc[64] + i] ^= m[i]; } - s_inc[64] = (uint8_t)(mlen + s_inc[64]); + s_inc[64] += (uint8_t)mlen; } -void PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_haraka_S_inc_finalize(uint8_t *s_inc) { +void haraka_S_inc_finalize(uint8_t *s_inc) { /* After haraka_S_inc_absorb, we are guaranteed that s_inc[64] < HARAKAS_RATE, so we can always use one more byte for p in the current state. */ s_inc[s_inc[64]] ^= 0x1F; @@ -765,22 +753,23 @@ void PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_haraka_S_inc_finalize(uint8_t *s_inc) s_inc[64] = 0; } -void PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, const harakactx *state) { - uint8_t i; +void haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, + const spx_ctx *ctx) { + size_t i; /* First consume any bytes we still have sitting around */ for (i = 0; i < outlen && i < s_inc[64]; i++) { /* There are s_inc[64] bytes left, so r - s_inc[64] is the first available byte. We consume from there, i.e., up to r. */ - out[i] = s_inc[(HARAKAS_RATE - s_inc[64] + i)]; + out[i] = (uint8_t)s_inc[(HARAKAS_RATE - s_inc[64] + i)]; } out += i; outlen -= i; - s_inc[64] = (uint8_t)(s_inc[64] - i); + s_inc[64] -= (uint8_t)i; /* Then squeeze the remaining necessary blocks */ while (outlen > 0) { - PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_haraka512_perm(s_inc, s_inc, state); + haraka512_perm(s_inc, s_inc, ctx); for (i = 0; i < outlen && i < HARAKAS_RATE; i++) { out[i] = s_inc[i]; @@ -791,7 +780,9 @@ void PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_haraka_S_inc_squeeze(uint8_t *out, si } } -void PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_haraka_S(unsigned char *out, unsigned long long outlen, const unsigned char *in, unsigned long long inlen, const harakactx *state) { +void haraka_S(unsigned char *out, unsigned long long outlen, + const unsigned char *in, unsigned long long inlen, + const spx_ctx *ctx) { unsigned long long i; unsigned char s[64]; unsigned char d[32]; @@ -799,20 +790,21 @@ void PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_haraka_S(unsigned char *out, unsigned for (i = 0; i < 64; i++) { s[i] = 0; } - haraka_S_absorb(s, in, inlen, 0x1F, state); + haraka_S_absorb(s, 32, in, inlen, 0x1F, ctx); - haraka_S_squeezeblocks(out, outlen / 32, s, state); + haraka_S_squeezeblocks(out, outlen / 32, s, 32, ctx); out += (outlen / 32) * 32; if (outlen % 32) { - haraka_S_squeezeblocks(d, 1, s, state); + haraka_S_squeezeblocks(d, 1, s, 32, ctx); for (i = 0; i < outlen % 32; i++) { out[i] = d[i]; } } } -void PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_haraka512_perm(unsigned char *out, const unsigned char *in, const harakactx *state) { +void haraka512_perm(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx) { uint32_t w[16]; uint64_t q[8], tmp_q; unsigned int i, j; @@ -829,7 +821,7 @@ void PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_haraka512_perm(unsigned char *out, co br_aes_ct64_bitslice_Sbox(q); shift_rows(q); mix_columns(q); - add_round_key(q, state->tweaked512_rc64[2 * i + j]); + add_round_key(q, ctx->tweaked512_rc64[2 * i + j]); } /* Mix states */ for (j = 0; j < 8; j++) { @@ -857,12 +849,12 @@ void PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_haraka512_perm(unsigned char *out, co br_range_enc32le(out, w, 16); } -void PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_haraka512(unsigned char *out, const unsigned char *in, const harakactx *state) { +void haraka512(unsigned char *out, const unsigned char *in, const spx_ctx *ctx) { int i; unsigned char buf[64]; - PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_haraka512_perm(buf, in, state); + haraka512_perm(buf, in, ctx); /* Feed-forward */ for (i = 0; i < 64; i++) { buf[i] = buf[i] ^ in[i]; @@ -876,50 +868,8 @@ void PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_haraka512(unsigned char *out, const u } -void PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_haraka256(unsigned char *out, const unsigned char *in, const harakactx *state) { - uint32_t q[8], tmp_q; - int i, j; - - for (i = 0; i < 4; i++) { - q[2 * i] = br_dec32le(in + 4 * i); - q[2 * i + 1] = br_dec32le(in + 4 * i + 16); - } - br_aes_ct_ortho(q); - - /* AES rounds */ - for (i = 0; i < 5; i++) { - for (j = 0; j < 2; j++) { - br_aes_ct_bitslice_Sbox(q); - shift_rows32(q); - mix_columns32(q); - add_round_key32(q, state->tweaked256_rc32[2 * i + j]); - } - - /* Mix states */ - for (j = 0; j < 8; j++) { - tmp_q = q[j]; - q[j] = (tmp_q & 0x81818181) | - (tmp_q & 0x02020202) << 1 | - (tmp_q & 0x04040404) << 2 | - (tmp_q & 0x08080808) << 3 | - (tmp_q & 0x10101010) >> 3 | - (tmp_q & 0x20202020) >> 2 | - (tmp_q & 0x40404040) >> 1; - } - } - - br_aes_ct_ortho(q); - for (i = 0; i < 4; i++) { - br_enc32le(out + 4 * i, q[2 * i]); - br_enc32le(out + 4 * i + 16, q[2 * i + 1]); - } - - for (i = 0; i < 32; i++) { - out[i] ^= in[i]; - } -} - -void PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_haraka256_sk(unsigned char *out, const unsigned char *in, const harakactx *state) { +void haraka256(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx) { uint32_t q[8], tmp_q; int i, j; @@ -935,7 +885,7 @@ void PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_haraka256_sk(unsigned char *out, cons br_aes_ct_bitslice_Sbox(q); shift_rows32(q); mix_columns32(q); - add_round_key32(q, state->tweaked256_rc32_sseed[2 * i + j]); + add_round_key32(q, ctx->tweaked256_rc32[2 * i + j]); } /* Mix states */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/haraka.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/haraka.h index f546667144..737cb6065f 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/haraka.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/haraka.h @@ -1,40 +1,42 @@ -#ifndef PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_HARAKA_H -#define PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_HARAKA_H +#ifndef SPX_HARAKA_H +#define SPX_HARAKA_H -#include -#include - -typedef struct { - uint64_t tweaked512_rc64[10][8]; - uint32_t tweaked256_rc32[10][8]; - uint32_t tweaked256_rc32_sseed[10][8]; -} harakactx; +#include "context.h" +#include "params.h" /* Tweak constants with seed */ -void PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_tweak_constants( - harakactx *state, - const unsigned char *pk_seed, const unsigned char *sk_seed, - unsigned long long seed_length); +#define tweak_constants SPX_NAMESPACE(tweak_constants) +void tweak_constants(spx_ctx *ctx); /* Haraka Sponge */ -void PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_haraka_S_inc_init(uint8_t *s_inc); -void PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, const harakactx *state); -void PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_haraka_S_inc_finalize(uint8_t *s_inc); -void PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, const harakactx *state); -void PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_haraka_S( - unsigned char *out, unsigned long long outlen, - const unsigned char *in, unsigned long long inlen, const harakactx *state); +#define haraka_S_inc_init SPX_NAMESPACE(haraka_S_inc_init) +void haraka_S_inc_init(uint8_t *s_inc); +#define haraka_S_inc_absorb SPX_NAMESPACE(haraka_S_inc_absorb) +void haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, + const spx_ctx *ctx); +#define haraka_S_inc_finalize SPX_NAMESPACE(haraka_S_inc_finalize) +void haraka_S_inc_finalize(uint8_t *s_inc); +#define haraka_S_inc_squeeze SPX_NAMESPACE(haraka_S_inc_squeeze) +void haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, + const spx_ctx *ctx); +#define haraka_S SPX_NAMESPACE(haraka_S) +void haraka_S(unsigned char *out, unsigned long long outlen, + const unsigned char *in, unsigned long long inlen, + const spx_ctx *ctx); /* Applies the 512-bit Haraka permutation to in. */ -void PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_haraka512_perm(unsigned char *out, const unsigned char *in, const harakactx *state); +#define haraka512_perm SPX_NAMESPACE(haraka512_perm) +void haraka512_perm(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx); /* Implementation of Haraka-512 */ -void PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_haraka512(unsigned char *out, const unsigned char *in, const harakactx *state); +#define haraka512 SPX_NAMESPACE(haraka512) +void haraka512(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx); /* Implementation of Haraka-256 */ -void PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_haraka256(unsigned char *out, const unsigned char *in, const harakactx *state); - -/* Implementation of Haraka-256 using sk.seed constants */ -void PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_haraka256_sk(unsigned char *out, const unsigned char *in, const harakactx *state); +#define haraka256 SPX_NAMESPACE(haraka256) +void haraka256(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/haraka_offsets.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/haraka_offsets.h new file mode 100644 index 0000000000..7c062272a0 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/haraka_offsets.h @@ -0,0 +1,21 @@ +#ifndef HARAKA_OFFSETS_H_ +#define HARAKA_OFFSETS_H_ + +/* + * Offsets of various fields in the address structure when we use Haraka as + * the Sphincs+ hash function + */ + +#define SPX_OFFSET_LAYER 3 /* The byte used to specify the Merkle tree layer */ +#define SPX_OFFSET_TREE 8 /* The start of the 8 byte field used to specify the tree */ +#define SPX_OFFSET_TYPE 19 /* The byte used to specify the hash type (reason) */ +#define SPX_OFFSET_KP_ADDR2 22 /* The high byte used to specify the key pair (which one-time signature) */ +#define SPX_OFFSET_KP_ADDR1 23 /* The low byte used to specify the key pair */ +#define SPX_OFFSET_CHAIN_ADDR 27 /* The byte used to specify the chain address (which Winternitz chain) */ +#define SPX_OFFSET_HASH_ADDR 31 /* The byte used to specify the hash address (where in the Winternitz chain) */ +#define SPX_OFFSET_TREE_HGT 27 /* The byte used to specify the height of this node in the FORS or Merkle tree */ +#define SPX_OFFSET_TREE_INDEX 28 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ + +#define SPX_HARAKA 1 + +#endif /* HARAKA_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/hash.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/hash.h index 2c281c6366..f7c87d4c3c 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/hash.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/hash.h @@ -1,31 +1,28 @@ -#ifndef PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_HASH_H -#define PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_HASH_H - -#include "hash_state.h" +#ifndef SPX_HASH_H +#define SPX_HASH_H #include #include -void PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_initialize_hash_function( - hash_state *hash_state_seeded, - const unsigned char *pub_seed, const unsigned char *sk_seed); +#include "context.h" +#include "params.h" + +#define prf_addr SPX_NAMESPACE(prf_addr) +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]); -void PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_destroy_hash_function(hash_state *hash_state_seeded); +#define gen_message_random SPX_NAMESPACE(gen_message_random) +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); -void PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded); +#define hash_message SPX_NAMESPACE(hash_message) +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); -void PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); -void PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/hash_haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/hash_haraka.c index 568f5e0b9f..750a67423b 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/hash_haraka.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/hash_haraka.c @@ -2,58 +2,44 @@ #include #include "address.h" -#include "haraka.h" -#include "hash.h" #include "params.h" #include "utils.h" -void PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_initialize_hash_function( - hash_state *hash_state_seeded, - const unsigned char *pub_seed, const unsigned char *sk_seed) { - PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_tweak_constants(hash_state_seeded, pub_seed, sk_seed, PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_N); -} - -/* The haraka implementation is stack based and won't be replaced in PQClean/OQS, - so we don't need to do anything */ -void PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_destroy_hash_function( - hash_state *hash_state_seeded) { // NOLINT(readability-non-const-parameter) - (void)hash_state_seeded; -} +#include "haraka.h" +#include "hash.h" /* - * Computes PRF(key, addr), given a secret key of PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_N bytes and an address + * Computes PRF(key, addr), given a secret key of SPX_N bytes and an address */ -void PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded) { - unsigned char buf[PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_ADDR_BYTES]; - /* Since PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_N may be smaller than 32, we need a temporary buffer. */ +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]) { + /* Since SPX_N may be smaller than 32, we need temporary buffers. */ unsigned char outbuf[32]; + unsigned char buf[64] = {0}; - (void)key; /* Suppress an 'unused parameter' warning. */ + memcpy(buf, addr, SPX_ADDR_BYTES); + memcpy(buf + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); - PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_addr_to_bytes(buf, addr); - PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_haraka256_sk(outbuf, buf, hash_state_seeded); - memcpy(out, outbuf, PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_N); + haraka512(outbuf, (const void *)buf, ctx); + memcpy(out, outbuf, SPX_N); } /** * Computes the message-dependent randomness R, using a secret seed and an * optional randomization value as well as the message. */ -void PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded) { +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { uint8_t s_inc[65]; - PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_haraka_S_inc_init(s_inc); - PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_haraka_S_inc_absorb(s_inc, sk_prf, PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_N, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_haraka_S_inc_absorb(s_inc, optrand, PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_N, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_haraka_S_inc_absorb(s_inc, m, mlen, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_haraka_S_inc_finalize(s_inc); - PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_haraka_S_inc_squeeze(R, PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_N, s_inc, hash_state_seeded); + haraka_S_inc_init(s_inc); + haraka_S_inc_absorb(s_inc, sk_prf, SPX_N, ctx); + haraka_S_inc_absorb(s_inc, optrand, SPX_N, ctx); + haraka_S_inc_absorb(s_inc, m, mlen, ctx); + haraka_S_inc_finalize(s_inc); + haraka_S_inc_squeeze(R, SPX_N, s_inc, ctx); } /** @@ -61,36 +47,35 @@ void PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_gen_message_random( * Outputs the message digest and the index of the leaf. The index is split in * the tree index and the leaf index, for convenient copying to an address. */ -void PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded) { -#define PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_TREE_BITS (PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_TREE_HEIGHT * (PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_D - 1)) -#define PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_TREE_BYTES ((PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_TREE_BITS + 7) / 8) -#define PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_LEAF_BITS PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_TREE_HEIGHT -#define PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_LEAF_BYTES ((PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_LEAF_BITS + 7) / 8) -#define PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_DGST_BYTES (PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_FORS_MSG_BYTES + PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_TREE_BYTES + PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_LEAF_BYTES) +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { +#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) +#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) +#define SPX_LEAF_BITS SPX_TREE_HEIGHT +#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) +#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) - unsigned char buf[PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_DGST_BYTES]; + unsigned char buf[SPX_DGST_BYTES]; unsigned char *bufp = buf; uint8_t s_inc[65]; - PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_haraka_S_inc_init(s_inc); - PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_haraka_S_inc_absorb(s_inc, R, PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_N, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_haraka_S_inc_absorb(s_inc, pk + PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_N, PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_N, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_haraka_S_inc_absorb(s_inc, m, mlen, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_haraka_S_inc_finalize(s_inc); - PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_haraka_S_inc_squeeze(buf, PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_DGST_BYTES, s_inc, hash_state_seeded); + haraka_S_inc_init(s_inc); + haraka_S_inc_absorb(s_inc, R, SPX_N, ctx); + haraka_S_inc_absorb(s_inc, pk + SPX_N, SPX_N, ctx); // Only absorb root part of pk + haraka_S_inc_absorb(s_inc, m, mlen, ctx); + haraka_S_inc_finalize(s_inc); + haraka_S_inc_squeeze(buf, SPX_DGST_BYTES, s_inc, ctx); + + memcpy(digest, bufp, SPX_FORS_MSG_BYTES); + bufp += SPX_FORS_MSG_BYTES; - memcpy(digest, bufp, PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_FORS_MSG_BYTES); - bufp += PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_FORS_MSG_BYTES; - *tree = PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_bytes_to_ull(bufp, PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_TREE_BYTES); - *tree &= (~(uint64_t)0) >> (64 - PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_TREE_BITS); - bufp += PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_TREE_BYTES; + *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); + *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); + bufp += SPX_TREE_BYTES; - *leaf_idx = (uint32_t)PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_bytes_to_ull( - bufp, PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_LEAF_BYTES); - *leaf_idx &= (~(uint32_t)0) >> (32 - PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_LEAF_BITS); + *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); + *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/hash_state.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/hash_state.h deleted file mode 100644 index 5adb1d9a22..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/hash_state.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef SPX_HASH_STATE_H -#define SPX_HASH_STATE_H - -/** - * Defines the type of the hash function state. - * - * Don't be fooled into thinking this instance of SPHINCS+ isn't stateless! - * - * From Section 7.2.2 from the SPHINCS+ round-2 specification: - * - * Each of the instances of the tweakable hash function take PK.seed as its - * first input, which is constant for a given key pair – and, thus, across - * a single signature. This leads to a lot of redundant computation. To remedy - * this, we pad PK.seed to the length of a full 64-byte SHA-256 input block. - * Because of the Merkle-DamgÃ¥rd construction that underlies SHA-256, this - * allows for reuse of the intermediate SHA-256 state after the initial call to - * the compression function which improves performance. - * - * We pass this hash state around in functions, because otherwise we need to - * have a global variable. - */ - -#include "haraka.h" -#define hash_state harakactx - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/merkle.c b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/merkle.c new file mode 100644 index 0000000000..0c1479fd93 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/merkle.c @@ -0,0 +1,59 @@ +#include +#include + +#include "address.h" +#include "merkle.h" +#include "params.h" +#include "utils.h" +#include "utilsx1.h" +#include "wots.h" +#include "wotsx1.h" + +/* + * This generates a Merkle signature (WOTS signature followed by the Merkle + * authentication path). This is in this file because most of the complexity + * is involved with the WOTS signature; the Merkle authentication path logic + * is mostly hidden in treehashx4 + */ +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf) { + unsigned char *auth_path = sig + SPX_WOTS_BYTES; + struct leaf_info_x1 info = { 0 }; + unsigned steps[ SPX_WOTS_LEN ]; + + info.wots_sig = sig; + chain_lengths(steps, root); + info.wots_steps = steps; + + set_type(&tree_addr[0], SPX_ADDR_TYPE_HASHTREE); + set_type(&info.pk_addr[0], SPX_ADDR_TYPE_WOTSPK); + copy_subtree_addr(&info.leaf_addr[0], wots_addr); + copy_subtree_addr(&info.pk_addr[0], wots_addr); + + info.wots_sign_leaf = idx_leaf; + + treehashx1(root, auth_path, ctx, + idx_leaf, 0, + SPX_TREE_HEIGHT, + wots_gen_leafx1, + tree_addr, &info); +} + +/* Compute root node of the top-most subtree. */ +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { + /* We do not need the auth path in key generation, but it simplifies the + code to have just one treehash routine that computes both root and path + in one function. */ + unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; + uint32_t top_tree_addr[8] = {0}; + uint32_t wots_addr[8] = {0}; + + set_layer_addr(top_tree_addr, SPX_D - 1); + set_layer_addr(wots_addr, SPX_D - 1); + + merkle_sign(auth_path, root, ctx, + wots_addr, top_tree_addr, + (uint32_t)~0 /* ~0 means "don't bother generating an auth path */ ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/merkle.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/merkle.h new file mode 100644 index 0000000000..769cf2e970 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/merkle.h @@ -0,0 +1,21 @@ +#ifndef MERKLE_H_ +#define MERKLE_H_ + +#include + +#include "context.h" +#include "params.h" + +/* Generate a Merkle signature (WOTS signature followed by the Merkle */ +/* authentication path) */ +#define merkle_sign SPX_NAMESPACE(merkle_sign) +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf); + +/* Compute the root node of the top-most subtree. */ +#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); + +#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/nistapi.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/nistapi.h new file mode 100644 index 0000000000..3cb71afad4 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/nistapi.h @@ -0,0 +1,87 @@ +#ifndef SPX_API_H +#define SPX_API_H + +#include +#include + +#include "params.h" + +#define CRYPTO_ALGNAME "SPHINCS+" + +#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES +#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES +#define CRYPTO_BYTES SPX_BYTES +#define CRYPTO_SEEDBYTES (3*SPX_N) + +/* + * Returns the length of a secret key, in bytes + */ +#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) +size_t crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) +size_t crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) +size_t crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) +size_t crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +#define crypto_sign SPX_NAMESPACE(crypto_sign) +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/params.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/params.h index 92f4fca298..b07e7b3c0d 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/params.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/params.h @@ -1,53 +1,56 @@ -#ifndef PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_PARAMS_H -#define PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_PARAMS_H +#ifndef SPX_PARAMS_H +#define SPX_PARAMS_H + +#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_##s /* Hash output length in bytes. */ -#define PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_N 24 +#define SPX_N 24 /* Height of the hypertree. */ -#define PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_FULL_HEIGHT 63 +#define SPX_FULL_HEIGHT 63 /* Number of subtree layer. */ -#define PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_D 7 +#define SPX_D 7 /* FORS tree dimensions. */ -#define PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_FORS_HEIGHT 14 -#define PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_FORS_TREES 17 +#define SPX_FORS_HEIGHT 14 +#define SPX_FORS_TREES 17 /* Winternitz parameter, */ -#define PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_WOTS_W 16 +#define SPX_WOTS_W 16 /* The hash function is defined by linking a different hash.c file, as opposed to setting a #define constant. */ /* For clarity */ -#define PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_ADDR_BYTES 32 +#define SPX_ADDR_BYTES 32 /* WOTS parameters. */ -#define PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_WOTS_LOGW 4 +#define SPX_WOTS_LOGW 4 -#define PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_WOTS_LEN1 (8 * PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_N / PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_WOTS_LOGW) +#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) -/* PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#define PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_WOTS_LEN2 3 +/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ +#define SPX_WOTS_LEN2 3 -#define PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_WOTS_LEN (PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_WOTS_LEN1 + PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_WOTS_LEN2) -#define PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_WOTS_BYTES (PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_WOTS_LEN * PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_N) -#define PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_WOTS_PK_BYTES PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_WOTS_BYTES +#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) +#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) +#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES /* Subtree size. */ -#define PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_TREE_HEIGHT (PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_FULL_HEIGHT / PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_D) +#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) + +//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT +// #error SPX_D should always divide SPX_FULL_HEIGHT +//#endif /* FORS parameters. */ -#define PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_FORS_MSG_BYTES ((PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_FORS_TREES + 7) / 8) -#define PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_FORS_BYTES ((PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_FORS_HEIGHT + 1) * PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_FORS_TREES * PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_N) -#define PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_FORS_PK_BYTES PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_N +#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) +#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) +#define SPX_FORS_PK_BYTES SPX_N /* Resulting SPX sizes. */ -#define PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_BYTES (PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_N + PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_FORS_BYTES + PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_D * PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_WOTS_BYTES +\ - PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_FULL_HEIGHT * PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_N) -#define PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_PK_BYTES (2 * PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_N) -#define PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_SK_BYTES (2 * PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_N + PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_PK_BYTES) - -/* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ -#define PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_OPTRAND_BYTES 32 +#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ + SPX_FULL_HEIGHT * SPX_N) +#define SPX_PK_BYTES (2 * SPX_N) +#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) + +#include "haraka_offsets.h" #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/sign.c b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/sign.c index 9a75d304da..9d0c7d1b22 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/sign.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/sign.c @@ -3,72 +3,43 @@ #include #include "address.h" -#include "api.h" +#include "context.h" #include "fors.h" #include "hash.h" -#include "hash_state.h" +#include "merkle.h" +#include "nistapi.h" #include "params.h" #include "randombytes.h" #include "thash.h" #include "utils.h" #include "wots.h" -/** - * Computes the leaf at a given address. First generates the WOTS key pair, - * then computes leaf by hashing horizontally. - */ -static void wots_gen_leaf(unsigned char *leaf, const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx, const uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - unsigned char pk[PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_WOTS_BYTES]; - uint32_t wots_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_set_type( - wots_addr, PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_set_type( - wots_pk_addr, PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_ADDR_TYPE_WOTSPK); - - PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_set_keypair_addr( - wots_addr, addr_idx); - PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_wots_gen_pk( - pk, sk_seed, pub_seed, wots_addr, hash_state_seeded); - - PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_copy_keypair_addr( - wots_pk_addr, wots_addr); - PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_thash_WOTS_LEN( - leaf, pk, pub_seed, wots_pk_addr, hash_state_seeded); -} - /* * Returns the length of a secret key, in bytes */ -size_t PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_crypto_sign_secretkeybytes(void) { - return PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_CRYPTO_SECRETKEYBYTES; +size_t crypto_sign_secretkeybytes(void) { + return CRYPTO_SECRETKEYBYTES; } /* * Returns the length of a public key, in bytes */ -size_t PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_crypto_sign_publickeybytes(void) { - return PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_CRYPTO_PUBLICKEYBYTES; +size_t crypto_sign_publickeybytes(void) { + return CRYPTO_PUBLICKEYBYTES; } /* * Returns the length of a signature, in bytes */ -size_t PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_crypto_sign_bytes(void) { - return PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_CRYPTO_BYTES; +size_t crypto_sign_bytes(void) { + return CRYPTO_BYTES; } /* * Returns the length of the seed required to generate a key pair, in bytes */ -size_t PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_crypto_sign_seedbytes(void) { - return PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_CRYPTO_SEEDBYTES; +size_t crypto_sign_seedbytes(void) { + return CRYPTO_SEEDBYTES; } /* @@ -76,37 +47,30 @@ size_t PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_crypto_sign_seedbytes(void) { * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] * Format pk: [PUB_SEED || root] */ -int PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed) { - /* We do not need the auth path in key generation, but it simplifies the - code to have just one treehash routine that computes both root and path - in one function. */ - unsigned char auth_path[PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_TREE_HEIGHT * PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_N]; - uint32_t top_tree_addr[8] = {0}; - hash_state hash_state_seeded; - - PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_set_layer_addr( - top_tree_addr, PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_D - 1); - PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_set_type( - top_tree_addr, PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_ADDR_TYPE_HASHTREE); +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed) { + spx_ctx ctx; /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ - memcpy(sk, seed, PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_CRYPTO_SEEDBYTES); + memcpy(sk, seed, CRYPTO_SEEDBYTES); - memcpy(pk, sk + 2 * PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_N, PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_N); + memcpy(pk, sk + 2 * SPX_N, SPX_N); + + memcpy(ctx.pub_seed, pk, SPX_N); + memcpy(ctx.sk_seed, sk, SPX_N); /* This hook allows the hash function instantiation to do whatever preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_initialize_hash_function(&hash_state_seeded, pk, sk); + initialize_hash_function(&ctx); /* Compute root node of the top-most subtree. */ - PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_treehash_TREE_HEIGHT( - sk + 3 * PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_N, auth_path, sk, sk + 2 * PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_N, 0, 0, - wots_gen_leaf, top_tree_addr, &hash_state_seeded); + merkle_gen_root(sk + 3 * SPX_N, &ctx); + + // cleanup + free_hash_function(&ctx); - memcpy(pk + PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_N, sk + 3 * PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_N, PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_N); + memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); - PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_destroy_hash_function(&hash_state_seeded); return 0; } @@ -115,12 +79,10 @@ int PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_crypto_sign_seed_keypair( * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] * Format pk: [PUB_SEED || root] */ -int PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk) { - unsigned char seed[PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_CRYPTO_SEEDBYTES]; - randombytes(seed, PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_CRYPTO_SEEDBYTES); - PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_crypto_sign_seed_keypair( - pk, sk, seed); +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { + uint8_t seed[CRYPTO_SEEDBYTES]; + randombytes(seed, CRYPTO_SEEDBYTES); + crypto_sign_seed_keypair(pk, sk, seed); return 0; } @@ -128,101 +90,83 @@ int PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_crypto_sign_keypair( /** * Returns an array containing a detached signature. */ -int PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - const unsigned char *sk_seed = sk; - const unsigned char *sk_prf = sk + PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_N; - const unsigned char *pk = sk + 2 * PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_N; - const unsigned char *pub_seed = pk; - - unsigned char optrand[PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_N]; - unsigned char mhash[PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_FORS_MSG_BYTES]; - unsigned char root[PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_N]; +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk) { + spx_ctx ctx; + + const uint8_t *sk_prf = sk + SPX_N; + const uint8_t *pk = sk + 2 * SPX_N; + + uint8_t optrand[SPX_N]; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t root[SPX_N]; uint32_t i; uint64_t tree; uint32_t idx_leaf; uint32_t wots_addr[8] = {0}; uint32_t tree_addr[8] = {0}; - hash_state hash_state_seeded; + memcpy(ctx.sk_seed, sk, SPX_N); + memcpy(ctx.pub_seed, pk, SPX_N); /* This hook allows the hash function instantiation to do whatever preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_initialize_hash_function( - &hash_state_seeded, - pub_seed, sk_seed); + initialize_hash_function(&ctx); - PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_set_type( - wots_addr, PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_set_type( - tree_addr, PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_ADDR_TYPE_HASHTREE); + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); /* Optionally, signing can be made non-deterministic using optrand. This can help counter side-channel attacks that would benefit from getting a large number of traces when the signer uses the same nodes. */ - randombytes(optrand, PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_N); + randombytes(optrand, SPX_N); /* Compute the digest randomization value. */ - PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_gen_message_random( - sig, sk_prf, optrand, m, mlen, &hash_state_seeded); + gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); /* Derive the message digest and leaf index from R, PK and M. */ - PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_N; + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; - PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); /* Sign the message hash using FORS. */ - PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_fors_sign( - sig, root, mhash, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_FORS_BYTES; - - for (i = 0; i < PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_D; i++) { - PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_set_tree_addr(tree_addr, tree); - - PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); - - /* Compute a WOTS signature. */ - PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_wots_sign( - sig, root, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_WOTS_BYTES; - - /* Compute the authentication path for the used WOTS leaf. */ - PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_treehash_TREE_HEIGHT( - root, sig, sk_seed, pub_seed, idx_leaf, 0, - wots_gen_leaf, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_TREE_HEIGHT * PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_N; + fors_sign(sig, root, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); + sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_TREE_HEIGHT; + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; } - *siglen = PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_BYTES; + free_hash_function(&ctx); + + *siglen = SPX_BYTES; - PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_destroy_hash_function(&hash_state_seeded); return 0; } /** * Verifies a detached signature and message under a given public key. */ -int PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk) { - const unsigned char *pub_seed = pk; - const unsigned char *pub_root = pk + PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_N; - unsigned char mhash[PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_FORS_MSG_BYTES]; - unsigned char wots_pk[PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_WOTS_BYTES]; - unsigned char root[PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_N]; - unsigned char leaf[PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_N]; +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk) { + spx_ctx ctx; + const uint8_t *pub_root = pk + SPX_N; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t wots_pk[SPX_WOTS_BYTES]; + uint8_t root[SPX_N]; + uint8_t leaf[SPX_N]; unsigned int i; uint64_t tree; uint32_t idx_leaf; @@ -230,78 +174,66 @@ int PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_crypto_sign_verify( uint32_t tree_addr[8] = {0}; uint32_t wots_pk_addr[8] = {0}; - hash_state hash_state_seeded; - - if (siglen != PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_BYTES) { + if (siglen != SPX_BYTES) { return -1; } + memcpy(ctx.pub_seed, pk, SPX_N); + /* This hook allows the hash function instantiation to do whatever preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_initialize_hash_function( - &hash_state_seeded, - pub_seed, NULL); + initialize_hash_function(&ctx); - PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_set_type( - wots_addr, PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_set_type( - tree_addr, PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_ADDR_TYPE_HASHTREE); - PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_set_type( - wots_pk_addr, PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_ADDR_TYPE_WOTSPK); + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); /* Derive the message digest and leaf index from R || PK || M. */ - /* The additional PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_N is a result of the hash domain separator. */ - PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_N; + /* The additional SPX_N is a result of the hash domain separator. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; /* Layer correctly defaults to 0, so no need to set_layer_addr */ - PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); - PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_fors_pk_from_sig( - root, sig, mhash, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_FORS_BYTES; + fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; /* For each subtree.. */ - for (i = 0; i < PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_D; i++) { - PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_set_tree_addr(tree_addr, tree); + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); - PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); - PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_copy_keypair_addr( - wots_pk_addr, wots_addr); + copy_keypair_addr(wots_pk_addr, wots_addr); /* The WOTS public key is only correct if the signature was correct. */ /* Initially, root is the FORS pk, but on subsequent iterations it is the root of the subtree below the currently processed subtree. */ - PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_wots_pk_from_sig( - wots_pk, sig, root, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_WOTS_BYTES; + wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); + sig += SPX_WOTS_BYTES; /* Compute the leaf node using the WOTS public key. */ - PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_thash_WOTS_LEN( - leaf, wots_pk, pub_seed, wots_pk_addr, &hash_state_seeded); + thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); /* Compute the root node of this subtree. */ - PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_compute_root( - root, leaf, idx_leaf, 0, sig, PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_TREE_HEIGHT, - pub_seed, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_TREE_HEIGHT * PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_N; + compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, + &ctx, tree_addr); + sig += SPX_TREE_HEIGHT * SPX_N; /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_TREE_HEIGHT; + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; } - PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_destroy_hash_function(&hash_state_seeded); + // cleanup + free_hash_function(&ctx); + /* Check if the root node equals the root node in the public key. */ - if (memcmp(root, pub_root, PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_N) != 0) { + if (memcmp(root, pub_root, SPX_N) != 0) { return -1; } @@ -312,15 +244,14 @@ int PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_crypto_sign_verify( /** * Returns an array containing the signature followed by the message. */ -int PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk) { size_t siglen; - PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_crypto_sign_signature( - sm, &siglen, m, mlen, sk); + crypto_sign_signature(sm, &siglen, m, mlen, sk); - memmove(sm + PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_BYTES, m, mlen); + memmove(sm + SPX_BYTES, m, mlen); *smlen = siglen + mlen; return 0; @@ -329,28 +260,27 @@ int PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_crypto_sign( /** * Verifies a given signature-message pair under a given public key. */ -int PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk) { +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk) { /* The API caller does not necessarily know what size a signature should be - but SPHINCS+ signatures are always exactly PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_BYTES. */ - if (smlen < PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_BYTES) { + but SPHINCS+ signatures are always exactly SPX_BYTES. */ + if (smlen < SPX_BYTES) { memset(m, 0, smlen); *mlen = 0; return -1; } - *mlen = smlen - PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_BYTES; + *mlen = smlen - SPX_BYTES; - if (PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_crypto_sign_verify( - sm, PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_BYTES, sm + PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_BYTES, *mlen, pk)) { + if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { memset(m, 0, smlen); *mlen = 0; return -1; } /* If verification was successful, move the message to the right place. */ - memmove(m, sm + PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_BYTES, *mlen); + memmove(m, sm + SPX_BYTES, *mlen); return 0; } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/thash.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/thash.h index def093746f..8687ccfb4d 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/thash.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/thash.h @@ -1,28 +1,13 @@ -#ifndef PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_THASH_H -#define PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_THASH_H +#ifndef SPX_THASH_H +#define SPX_THASH_H -#include "hash_state.h" +#include "context.h" +#include "params.h" #include -void PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); +#define thash SPX_NAMESPACE(thash) +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/thash_haraka_robust.c b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/thash_haraka_robust.c index 95d77365ec..109502cbc2 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/thash_haraka_robust.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/thash_haraka_robust.c @@ -2,93 +2,44 @@ #include #include "address.h" -#include "hash_state.h" #include "params.h" #include "thash.h" +#include "utils.h" #include "haraka.h" /** - * Takes an array of inblocks concatenated arrays of PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_N bytes. + * Takes an array of inblocks concatenated arrays of SPX_N bytes. */ -static void PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_thash( - unsigned char *out, unsigned char *buf, - const unsigned char *in, unsigned int inblocks, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char *bitmask = buf + PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_ADDR_BYTES; +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]) { + PQCLEAN_VLA(uint8_t, buf, SPX_ADDR_BYTES + inblocks * SPX_N); + PQCLEAN_VLA(uint8_t, bitmask, inblocks * SPX_N); unsigned char outbuf[32]; unsigned char buf_tmp[64]; unsigned int i; - (void)pub_seed; /* Suppress an 'unused parameter' warning. */ - if (inblocks == 1) { /* F function */ - /* Since PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_N may be smaller than 32, we need a temporary buffer. */ + /* Since SPX_N may be smaller than 32, we need a temporary buffer. */ memset(buf_tmp, 0, 64); - PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_addr_to_bytes(buf_tmp, addr); + memcpy(buf_tmp, addr, 32); - PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_haraka256(outbuf, buf_tmp, hash_state_seeded); - for (i = 0; i < inblocks * PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_N; i++) { - buf_tmp[PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_ADDR_BYTES + i] = in[i] ^ outbuf[i]; + haraka256(outbuf, buf_tmp, ctx); + for (i = 0; i < inblocks * SPX_N; i++) { + buf_tmp[SPX_ADDR_BYTES + i] = in[i] ^ outbuf[i]; } - PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_haraka512(outbuf, buf_tmp, hash_state_seeded); - memcpy(out, outbuf, PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_N); + haraka512(outbuf, buf_tmp, ctx); + memcpy(out, outbuf, SPX_N); } else { /* All other tweakable hashes*/ - PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_addr_to_bytes(buf, addr); - PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_haraka_S( - bitmask, inblocks * PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_N, buf, PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_ADDR_BYTES, hash_state_seeded); + memcpy(buf, addr, 32); + haraka_S(bitmask, inblocks * SPX_N, buf, SPX_ADDR_BYTES, ctx); - for (i = 0; i < inblocks * PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_N; i++) { - buf[PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_ADDR_BYTES + i] = in[i] ^ bitmask[i]; + for (i = 0; i < inblocks * SPX_N; i++) { + buf[SPX_ADDR_BYTES + i] = in[i] ^ bitmask[i]; } - PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_haraka_S( - out, PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_N, buf, PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_N, hash_state_seeded); + haraka_S(out, SPX_N, buf, SPX_ADDR_BYTES + inblocks * SPX_N, ctx); } } - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_ADDR_BYTES + 1 * PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_N]; - PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_thash( - out, buf, in, 1, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_ADDR_BYTES + 2 * PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_N]; - PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_thash( - out, buf, in, 2, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_ADDR_BYTES + PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_WOTS_LEN * PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_N]; - PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_thash( - out, buf, in, PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_WOTS_LEN, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_ADDR_BYTES + PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_FORS_TREES * PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_N]; - PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_thash( - out, buf, in, PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_FORS_TREES, pub_seed, addr, hash_state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/utils.c b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/utils.c index 5de9d48259..177b541fb9 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/utils.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/utils.c @@ -1,34 +1,41 @@ -#include #include +#include "utils.h" + #include "address.h" #include "hash.h" -#include "hash_state.h" #include "params.h" #include "thash.h" -#include "utils.h" /** * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. */ -void PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in) { +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in) { + int i; /* Iterate over out in decreasing order, for big-endianness. */ - for (size_t i = outlen; i > 0; i--) { - out[i - 1] = in & 0xff; + for (i = (signed int)outlen - 1; i >= 0; i--) { + out[i] = in & 0xff; in = in >> 8; } } +void u32_to_bytes(unsigned char *out, uint32_t in) { + out[0] = (unsigned char)(in >> 24); + out[1] = (unsigned char)(in >> 16); + out[2] = (unsigned char)(in >> 8); + out[3] = (unsigned char)in; +} + /** * Converts the inlen bytes in 'in' from big-endian byte order to an integer. */ -unsigned long long PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_bytes_to_ull( - const unsigned char *in, size_t inlen) { +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { unsigned long long retval = 0; + unsigned int i; - for (size_t i = 0; i < inlen; i++) { + for (i = 0; i < inlen; i++) { retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); } return retval; @@ -38,94 +45,80 @@ unsigned long long PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_bytes_to_ull( * Computes a root node given a leaf and an auth path. * Expects address to be complete other than the tree_height and tree_index. */ -void PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]) { uint32_t i; - unsigned char buffer[2 * PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_N]; + unsigned char buffer[2 * SPX_N]; /* If leaf_idx is odd (last bit = 1), current path element is a right child and auth_path has to go left. Otherwise it is the other way around. */ if (leaf_idx & 1) { - memcpy(buffer + PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_N, leaf, PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_N); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_N); + memcpy(buffer + SPX_N, leaf, SPX_N); + memcpy(buffer, auth_path, SPX_N); } else { - memcpy(buffer, leaf, PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_N); - memcpy(buffer + PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_N, auth_path, PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_N); + memcpy(buffer, leaf, SPX_N); + memcpy(buffer + SPX_N, auth_path, SPX_N); } - auth_path += PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_N; + auth_path += SPX_N; for (i = 0; i < tree_height - 1; i++) { leaf_idx >>= 1; idx_offset >>= 1; /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_set_tree_height(addr, i + 1); - PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_set_tree_index( - addr, leaf_idx + idx_offset); + set_tree_height(addr, i + 1); + set_tree_index(addr, leaf_idx + idx_offset); /* Pick the right or left neighbor, depending on parity of the node. */ if (leaf_idx & 1) { - PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_thash_2( - buffer + PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_N, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_N); + thash(buffer + SPX_N, buffer, 2, ctx, addr); + memcpy(buffer, auth_path, SPX_N); } else { - PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_thash_2( - buffer, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer + PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_N, auth_path, PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_N); + thash(buffer, buffer, 2, ctx, addr); + memcpy(buffer + SPX_N, auth_path, SPX_N); } - auth_path += PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_N; + auth_path += SPX_N; } /* The last iteration is exceptional; we do not copy an auth_path node. */ leaf_idx >>= 1; idx_offset >>= 1; - PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_set_tree_height(addr, tree_height); - PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_set_tree_index( - addr, leaf_idx + idx_offset); - PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_thash_2( - root, buffer, pub_seed, addr, hash_state_seeded); + set_tree_height(addr, tree_height); + set_tree_index(addr, leaf_idx + idx_offset); + thash(root, buffer, 2, ctx, addr); } /** * For a given leaf index, computes the authentication path and the resulting * root node using Merkle's TreeHash algorithm. * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_ADDR_TYPE_FORSTREE). + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). * Applies the offset idx_offset to indices before building addresses, so that * it is possible to continue counting indices across trees. */ -static void PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_treehash( - unsigned char *root, unsigned char *auth_path, - unsigned char *stack, unsigned int *heights, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - +void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx * /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]) { + PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); + PQCLEAN_VLA(unsigned int, heights, tree_height + 1); unsigned int offset = 0; uint32_t idx; uint32_t tree_idx; for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { /* Add the next leaf node to the stack. */ - gen_leaf(stack + offset * PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_N, - sk_seed, pub_seed, idx + idx_offset, tree_addr, - hash_state_seeded); + gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); offset++; heights[offset - 1] = 0; /* If this is a node we need for the auth path.. */ if ((leaf_idx ^ 0x1) == idx) { - memcpy(auth_path, stack + (offset - 1)*PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_N, PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_N); + memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); } /* While the top-most nodes are of equal height.. */ @@ -134,66 +127,22 @@ static void PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_treehash( tree_idx = (idx >> (heights[offset - 1] + 1)); /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_set_tree_height( - tree_addr, heights[offset - 1] + 1); - PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_set_tree_index( - tree_addr, tree_idx + (idx_offset >> (heights[offset - 1] + 1))); + set_tree_height(tree_addr, heights[offset - 1] + 1); + set_tree_index(tree_addr, + tree_idx + (idx_offset >> (heights[offset - 1] + 1))); /* Hash the top-most nodes from the stack together. */ - PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_thash_2( - stack + (offset - 2)*PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_N, stack + (offset - 2)*PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_N, - pub_seed, tree_addr, hash_state_seeded); + thash(stack + (offset - 2)*SPX_N, + stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); offset--; /* Note that the top-most node is now one layer higher. */ heights[offset - 1]++; /* If this is a node we need for the auth path.. */ if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_path + heights[offset - 1]*PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_N, - stack + (offset - 1)*PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_N, PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_N); + memcpy(auth_path + heights[offset - 1]*SPX_N, + stack + (offset - 1)*SPX_N, SPX_N); } } } - memcpy(root, stack, PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_N); -} - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_FORS_HEIGHT + 1)*PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_N]; - unsigned int heights[PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_FORS_HEIGHT + 1]; - - PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_FORS_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_TREE_HEIGHT + 1)*PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_N]; - unsigned int heights[PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_TREE_HEIGHT + 1]; - - PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_TREE_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); + memcpy(root, stack, SPX_N); } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/utils.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/utils.h index b0392a367d..64f5d5a53a 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/utils.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/utils.h @@ -1,64 +1,58 @@ -#ifndef PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_UTILS_H -#define PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_UTILS_H +#ifndef SPX_UTILS_H +#define SPX_UTILS_H -#include "hash_state.h" -#include "params.h" -#include #include +#include "compat.h" +#include "context.h" +#include "params.h" + + +/* To support MSVC use alloca() instead of VLAs. See #20. */ + + /** * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. */ -void PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in); +#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in); +#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) +void u32_to_bytes(unsigned char *out, uint32_t in); /** * Converts the inlen bytes in 'in' from big-endian byte order to an integer. */ -unsigned long long PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_bytes_to_ull( - const unsigned char *in, size_t inlen); +#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); /** * Computes a root node given a leaf and an auth path. * Expects address to be complete other than the tree_height and tree_index. */ -void PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); +#define compute_root SPX_NAMESPACE(compute_root) +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]); /** * For a given leaf index, computes the authentication path and the resulting * root node using Merkle's TreeHash algorithm. * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_ADDR_TYPE_FORSTREE). + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). * Applies the offset idx_offset to indices before building addresses, so that * it is possible to continue counting indices across trees. */ -void PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); +#define treehash SPX_NAMESPACE(treehash) +void treehash(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx *ctx /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]); -void PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/utilsx1.c b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/utilsx1.c new file mode 100644 index 0000000000..fccb69b35d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/utilsx1.c @@ -0,0 +1,100 @@ +#include + +#include "utilsx1.h" + +#include "address.h" +#include "params.h" +#include "thash.h" +#include "utils.h" + +/* + * Generate the entire Merkle tree, computing the authentication path for + * leaf_idx, and the resulting root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) + * + * This expects tree_addr to be initialized to the addr structures for the + * Merkle tree nodes + * + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + * + * This works by using the standard Merkle tree building algorithm, + */ +void treehashx1(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, + uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* Where to write the leaves */, + const spx_ctx * /* ctx */, + uint32_t idx, void *info), + uint32_t tree_addr[8], + void *info) { + /* This is where we keep the intermediate nodes */ + PQCLEAN_VLA(uint8_t, stack, tree_height * SPX_N); + + uint32_t idx; + uint32_t max_idx = (uint32_t)((1 << tree_height) - 1); + for (idx = 0;; idx++) { + unsigned char current[2 * SPX_N]; /* Current logical node is at */ + /* index[SPX_N]. We do this to minimize the number of copies */ + /* needed during a thash */ + gen_leaf( ¤t[SPX_N], ctx, idx + idx_offset, + info ); + + /* Now combine the freshly generated right node with previously */ + /* generated left ones */ + uint32_t internal_idx_offset = idx_offset; + uint32_t internal_idx = idx; + uint32_t internal_leaf = leaf_idx; + uint32_t h; /* The height we are in the Merkle tree */ + for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { + + /* Check if we hit the top of the tree */ + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[SPX_N], SPX_N ); + return; + } + + /* + * Check if the node we have is a part of the + * authentication path; if it is, write it out + */ + if ((internal_idx ^ internal_leaf) == 0x01) { + memcpy( &auth_path[ h * SPX_N ], + ¤t[SPX_N], + SPX_N ); + } + + /* + * Check if we're at a left child; if so, stop going up the stack + * Exception: if we've reached the end of the tree, keep on going + * (so we combine the last 4 nodes into the one root node in two + * more iterations) + */ + if ((internal_idx & 1) == 0 && idx < max_idx) { + break; + } + + /* Ok, we're at a right node */ + /* Now combine the left and right logical nodes together */ + + /* Set the address of the node we're creating. */ + internal_idx_offset >>= 1; + set_tree_height(tree_addr, h + 1); + set_tree_index(tree_addr, internal_idx / 2 + internal_idx_offset ); + + unsigned char *left = &stack[h * SPX_N]; + memcpy( ¤t[0], left, SPX_N ); + thash( ¤t[1 * SPX_N], + ¤t[0 * SPX_N], + 2, ctx, tree_addr); + } + + /* We've hit a left child; save the current for when we get the */ + /* corresponding right right */ + memcpy( &stack[h * SPX_N], ¤t[SPX_N], SPX_N); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/utilsx1.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/utilsx1.h new file mode 100644 index 0000000000..e911d17d53 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/utilsx1.h @@ -0,0 +1,27 @@ +#ifndef SPX_UTILSX4_H +#define SPX_UTILSX4_H + +#include + +#include "context.h" +#include "params.h" + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +#define treehashx1 SPX_NAMESPACE(treehashx1) +void treehashx1(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* Where to write the leaf */, + const spx_ctx * /* ctx */, + uint32_t addr_idx, void *info), + uint32_t tree_addrx4[8], void *info); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/wots.c b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/wots.c index 38a67e42bf..249717aaa8 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/wots.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/wots.c @@ -1,32 +1,20 @@ #include #include +#include "wots.h" +#include "wotsx1.h" + #include "address.h" #include "hash.h" -#include "hash_state.h" #include "params.h" #include "thash.h" #include "utils.h" -#include "wots.h" +#include "utilsx1.h" // TODO clarify address expectations, and make them more uniform. // TODO i.e. do we expect types to be set already? // TODO and do we expect modifications or copies? -/** - * Computes the starting value for a chain, i.e. the secret key. - * Expects the address to be complete up to the chain address. - */ -static void wots_gen_sk(unsigned char *sk, const unsigned char *sk_seed, - uint32_t wots_addr[8], - const hash_state *hash_state_seeded) { - /* Make sure that the hash address is actually zeroed. */ - PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_set_hash_addr(wots_addr, 0); - - /* Generate sk element. */ - PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_prf_addr(sk, sk_seed, wots_addr, hash_state_seeded); -} - /** * Computes the chaining function. * out and in have to be n-byte arrays. @@ -36,18 +24,16 @@ static void wots_gen_sk(unsigned char *sk, const unsigned char *sk_seed, */ static void gen_chain(unsigned char *out, const unsigned char *in, unsigned int start, unsigned int steps, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { + const spx_ctx *ctx, uint32_t addr[8]) { uint32_t i; /* Initialize out with the value at position 'start'. */ - memcpy(out, in, PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_N); + memcpy(out, in, SPX_N); /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_WOTS_W; i++) { - PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_set_hash_addr(addr, i); - PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_thash_1( - out, out, pub_seed, addr, hash_state_seeded); + for (i = start; i < (start + steps) && i < SPX_WOTS_W; i++) { + set_hash_addr(addr, i); + thash(out, out, 1, ctx, addr); } } @@ -56,13 +42,13 @@ static void gen_chain(unsigned char *out, const unsigned char *in, * Interprets an array of bytes as integers in base w. * This only works when log_w is a divisor of 8. */ -static void base_w(unsigned int *output, const size_t out_len, +static void base_w(unsigned int *output, const int out_len, const unsigned char *input) { - size_t in = 0; - size_t out = 0; + int in = 0; + int out = 0; unsigned char total = 0; - unsigned int bits = 0; - size_t consumed; + int bits = 0; + int consumed; for (consumed = 0; consumed < out_len; consumed++) { if (bits == 0) { @@ -70,8 +56,8 @@ static void base_w(unsigned int *output, const size_t out_len, in++; bits += 8; } - bits -= PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_WOTS_LOGW; - output[out] = (unsigned int)((total >> bits) & (PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_WOTS_W - 1)); + bits -= SPX_WOTS_LOGW; + output[out] = (total >> bits) & (SPX_WOTS_W - 1); out++; } } @@ -80,67 +66,25 @@ static void base_w(unsigned int *output, const size_t out_len, static void wots_checksum(unsigned int *csum_base_w, const unsigned int *msg_base_w) { unsigned int csum = 0; - unsigned char csum_bytes[(PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_WOTS_LEN2 * PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_WOTS_LOGW + 7) / 8]; + unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; unsigned int i; /* Compute checksum. */ - for (i = 0; i < PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_WOTS_LEN1; i++) { - csum += PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_WOTS_W - 1 - msg_base_w[i]; + for (i = 0; i < SPX_WOTS_LEN1; i++) { + csum += SPX_WOTS_W - 1 - msg_base_w[i]; } /* Convert checksum to base_w. */ /* Make sure expected empty zero bits are the least significant bits. */ - csum = csum << (8 - ((PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_WOTS_LEN2 * PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_WOTS_LOGW) % 8)); - PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_ull_to_bytes( - csum_bytes, sizeof(csum_bytes), csum); - base_w(csum_base_w, PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_WOTS_LEN2, csum_bytes); + csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); + ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); + base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); } /* Takes a message and derives the matching chain lengths. */ -static void chain_lengths(unsigned int *lengths, const unsigned char *msg) { - base_w(lengths, PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_WOTS_LEN1, msg); - wots_checksum(lengths + PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_WOTS_LEN1, lengths); -} - -/** - * WOTS key generation. Takes a 32 byte sk_seed, expands it to WOTS private key - * elements and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_wots_gen_pk( - unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - uint32_t i; - - for (i = 0; i < PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_WOTS_LEN; i++) { - PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_set_chain_addr(addr, i); - wots_gen_sk(pk + i * PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_N, sk_seed, addr, hash_state_seeded); - gen_chain(pk + i * PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_N, pk + i * PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_N, - 0, PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_WOTS_W - 1, pub_seed, addr, hash_state_seeded); - } -} - -/** - * Takes a n-byte message and the 32-byte sk_see to compute a signature 'sig'. - */ -void PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_wots_sign( - unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *hash_state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_WOTS_LEN; i++) { - PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_set_chain_addr(addr, i); - wots_gen_sk(sig + i * PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_N, sk_seed, addr, hash_state_seeded); - gen_chain(sig + i * PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_N, sig + i * PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_N, 0, lengths[i], pub_seed, addr, hash_state_seeded); - } +void chain_lengths(unsigned int *lengths, const unsigned char *msg) { + base_w(lengths, SPX_WOTS_LEN1, msg); + wots_checksum(lengths + SPX_WOTS_LEN1, lengths); } /** @@ -148,20 +92,17 @@ void PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_wots_sign( * * Writes the computed public key to 'pk'. */ -void PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_wots_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_WOTS_LEN]; +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]) { + unsigned int lengths[SPX_WOTS_LEN]; uint32_t i; chain_lengths(lengths, msg); - for (i = 0; i < PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_WOTS_LEN; i++) { - PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_set_chain_addr(addr, i); - gen_chain(pk + i * PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_N, sig + i * PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_N, - lengths[i], PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_WOTS_W - 1 - lengths[i], pub_seed, addr, - hash_state_seeded); + for (i = 0; i < SPX_WOTS_LEN; i++) { + set_chain_addr(addr, i); + gen_chain(pk + i * SPX_N, sig + i * SPX_N, + lengths[i], SPX_WOTS_W - 1 - lengths[i], ctx, addr); } } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/wots.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/wots.h index 90780e62c9..4e7692eeef 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/wots.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/wots.h @@ -1,41 +1,25 @@ -#ifndef PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_WOTS_H -#define PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_WOTS_H +#ifndef SPX_WOTS_H +#define SPX_WOTS_H -#include "hash_state.h" -#include "params.h" #include -/** - * WOTS key generation. Takes a 32 byte seed for the private key, expands it to - * a full WOTS private key and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_wots_gen_pk( - unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -/** - * Takes a n-byte message and the 32-byte seed for the private key to compute a - * signature that is placed at 'sig'. - */ -void PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_wots_sign( - unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *hash_state_seeded); +#include "context.h" +#include "params.h" /** * Takes a WOTS signature and an n-byte message, computes a WOTS public key. * * Writes the computed public key to 'pk'. */ -void PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_wots_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); +#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]); + +/* + * Compute the chain lengths needed for a given message hash + */ +#define chain_lengths SPX_NAMESPACE(chain_lengths) +void chain_lengths(unsigned int *lengths, const unsigned char *msg); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/wotsx1.c b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/wotsx1.c new file mode 100644 index 0000000000..3adec78dfb --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/wotsx1.c @@ -0,0 +1,76 @@ +#include +#include + +#include "wots.h" +#include "wotsx1.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "thash.h" +#include "utils.h" + +/* + * This generates a WOTS public key + * It also generates the WOTS signature if leaf_info indicates + * that we're signing with this WOTS key + */ +void wots_gen_leafx1(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info) { + struct leaf_info_x1 *info = v_info; + uint32_t *leaf_addr = info->leaf_addr; + uint32_t *pk_addr = info->pk_addr; + unsigned int i, k; + unsigned char pk_buffer[ SPX_WOTS_BYTES ]; + unsigned char *buffer; + uint32_t wots_k_mask; + + if (leaf_idx == info->wots_sign_leaf) { + /* We're traversing the leaf that's signing; generate the WOTS */ + /* signature */ + wots_k_mask = 0; + } else { + /* Nope, we're just generating pk's; turn off the signature logic */ + wots_k_mask = (uint32_t)~0; + } + + set_keypair_addr( leaf_addr, leaf_idx ); + set_keypair_addr( pk_addr, leaf_idx ); + + for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { + uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k to */ + /* the step if we're generating a signature, ~0 if we're not */ + + /* Start with the secret seed */ + set_chain_addr(leaf_addr, i); + set_hash_addr(leaf_addr, 0); + set_type(leaf_addr, SPX_ADDR_TYPE_WOTSPRF); + + prf_addr(buffer, ctx, leaf_addr); + + set_type(leaf_addr, SPX_ADDR_TYPE_WOTS); + + /* Iterate down the WOTS chain */ + for (k = 0;; k++) { + /* Check if this is the value that needs to be saved as a */ + /* part of the WOTS signature */ + if (k == wots_k) { + memcpy( info->wots_sig + i * SPX_N, buffer, SPX_N ); + } + + /* Check if we hit the top of the chain */ + if (k == SPX_WOTS_W - 1) { + break; + } + + /* Iterate one step on the chain */ + set_hash_addr(leaf_addr, k); + + thash(buffer, buffer, 1, ctx, leaf_addr); + } + } + + /* Do the final thash to generate the public keys */ + thash(dest, pk_buffer, SPX_WOTS_LEN, ctx, pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/wotsx1.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/wotsx1.h new file mode 100644 index 0000000000..e617929f96 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/wotsx1.h @@ -0,0 +1,39 @@ +#ifndef WOTSX1_H_ +#define WOTSX1_H_ + +#include + +#include "context.h" +#include "params.h" + +/* + * This is here to provide an interface to the internal wots_gen_leafx1 + * routine. While this routine is not referenced in the package outside of + * wots.c, it is called from the stand-alone benchmark code to characterize + * the performance + */ +struct leaf_info_x1 { + unsigned char *wots_sig; + uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ + uint32_t *wots_steps; + uint32_t leaf_addr[8]; + uint32_t pk_addr[8]; +}; + +/* Macro to set the leaf_info to something 'benign', that is, it would */ +/* run with the same time as it does during the real signing process */ +/* Used only by the benchmark code */ +#define INITIALIZE_LEAF_INFO_X1(info, addr, step_buffer) { \ + (info).wots_sig = 0; \ + (info).wots_sign_leaf = ~0; \ + (info).wots_steps = step_buffer; \ + memcpy( &(info).leaf_addr[0], (addr), 32 ); \ + memcpy( &(info).pk_addr[0], (addr), 32 ); \ + } + +#define wots_gen_leafx1 SPX_NAMESPACE(wots_gen_leafx1) +void wots_gen_leafx1(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info); + +#endif /* WOTSX1_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/address.c b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/address.c index e3c8ca09c7..d49d9f3b6b 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/address.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/address.c @@ -1,78 +1,95 @@ #include +#include #include "address.h" #include "params.h" #include "utils.h" -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]) { - int i; - - for (i = 0; i < 8; i++) { - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_ull_to_bytes( - bytes + i * 4, 4, addr[i]); - } -} - -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_set_layer_addr( - uint32_t addr[8], uint32_t layer) { - addr[0] = layer; +/* + * Specify which level of Merkle tree (the "layer") we're working on + */ +void set_layer_addr(uint32_t addr[8], uint32_t layer) { + ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; } -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_set_tree_addr( - uint32_t addr[8], uint64_t tree) { - addr[1] = 0; - addr[2] = (uint32_t) (tree >> 32); - addr[3] = (uint32_t) tree; +/* + * Specify which Merkle tree within the level (the "tree address") we're working on + */ +void set_tree_addr(uint32_t addr[8], uint64_t tree) { + ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); } -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_set_type( - uint32_t addr[8], uint32_t type) { - addr[4] = type; +/* + * Specify the reason we'll use this address structure for, that is, what + * hash will we compute with it. This is used so that unrelated types of + * hashes don't accidentally get the same address structure. The type will be + * one of the SPX_ADDR_TYPE constants + */ +void set_type(uint32_t addr[8], uint32_t type) { + ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; } -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; +/* + * Copy the layer and tree fields of the address structure. This is used + * when we're doing multiple types of hashes within the same Merkle tree + */ +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); } /* These functions are used for OTS addresses. */ -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_set_keypair_addr( - uint32_t addr[8], uint32_t keypair) { - addr[5] = keypair; +/* + * Specify which Merkle leaf we're working on; that is, which OTS keypair + * we're talking about. + */ +void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { + /* We have > 256 OTS at the bottom of the Merkle tree; to specify */ + /* which one, we'd need to express it in two bytes */ + ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR2] = (unsigned char)(keypair >> 8); + ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; } -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; - out[5] = in[5]; +/* + * Copy the layer, tree and keypair fields of the address structure. This is + * used when we're doing multiple things within the same OTS keypair + */ +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); + ((unsigned char *)out)[SPX_OFFSET_KP_ADDR2] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR2]; + ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; } -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_set_chain_addr( - uint32_t addr[8], uint32_t chain) { - addr[6] = chain; +/* + * Specify which Merkle chain within the OTS we're working with + * (the chain address) + */ +void set_chain_addr(uint32_t addr[8], uint32_t chain) { + ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; } -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_set_hash_addr( - uint32_t addr[8], uint32_t hash) { - addr[7] = hash; +/* + * Specify where in the Merkle chain we are +* (the hash address) + */ +void set_hash_addr(uint32_t addr[8], uint32_t hash) { + ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; } /* These functions are used for all hash tree addresses (including FORS). */ -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_set_tree_height( - uint32_t addr[8], uint32_t tree_height) { - addr[6] = tree_height; +/* + * Specify the height of the node in the Merkle/FORS tree we are in + * (the tree height) + */ +void set_tree_height(uint32_t addr[8], uint32_t tree_height) { + ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; } -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_set_tree_index( - uint32_t addr[8], uint32_t tree_index) { - addr[7] = tree_index; +/* + * Specify the distance from the left edge of the node in the Merkle/FORS tree + * (the tree index) + */ +void set_tree_index(uint32_t addr[8], uint32_t tree_index) { + u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/address.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/address.h index d8817d1141..24a84eb40c 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/address.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/address.h @@ -1,50 +1,52 @@ -#ifndef PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_ADDRESS_H -#define PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_ADDRESS_H +#ifndef SPX_ADDRESS_H +#define SPX_ADDRESS_H #include -#define PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_ADDR_TYPE_WOTS 0 -#define PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_ADDR_TYPE_WOTSPK 1 -#define PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_ADDR_TYPE_HASHTREE 2 -#define PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_ADDR_TYPE_FORSTREE 3 -#define PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_ADDR_TYPE_FORSPK 4 +#include "params.h" -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]); +/* The hash types that are passed to set_type */ +#define SPX_ADDR_TYPE_WOTS 0 +#define SPX_ADDR_TYPE_WOTSPK 1 +#define SPX_ADDR_TYPE_HASHTREE 2 +#define SPX_ADDR_TYPE_FORSTREE 3 +#define SPX_ADDR_TYPE_FORSPK 4 +#define SPX_ADDR_TYPE_WOTSPRF 5 +#define SPX_ADDR_TYPE_FORSPRF 6 -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_set_layer_addr( - uint32_t addr[8], uint32_t layer); +#define set_layer_addr SPX_NAMESPACE(set_layer_addr) +void set_layer_addr(uint32_t addr[8], uint32_t layer); -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_set_tree_addr( - uint32_t addr[8], uint64_t tree); +#define set_tree_addr SPX_NAMESPACE(set_tree_addr) +void set_tree_addr(uint32_t addr[8], uint64_t tree); -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_set_type( - uint32_t addr[8], uint32_t type); +#define set_type SPX_NAMESPACE(set_type) +void set_type(uint32_t addr[8], uint32_t type); /* Copies the layer and tree part of one address into the other */ -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]); +#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); /* These functions are used for WOTS and FORS addresses. */ -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_set_keypair_addr( - uint32_t addr[8], uint32_t keypair); +#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) +void set_keypair_addr(uint32_t addr[8], uint32_t keypair); -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_set_chain_addr( - uint32_t addr[8], uint32_t chain); +#define set_chain_addr SPX_NAMESPACE(set_chain_addr) +void set_chain_addr(uint32_t addr[8], uint32_t chain); -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_set_hash_addr( - uint32_t addr[8], uint32_t hash); +#define set_hash_addr SPX_NAMESPACE(set_hash_addr) +void set_hash_addr(uint32_t addr[8], uint32_t hash); -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]); +#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); /* These functions are used for all hash tree addresses (including FORS). */ -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_set_tree_height( - uint32_t addr[8], uint32_t tree_height); +#define set_tree_height SPX_NAMESPACE(set_tree_height) +void set_tree_height(uint32_t addr[8], uint32_t tree_height); -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_set_tree_index( - uint32_t addr[8], uint32_t tree_index); +#define set_tree_index SPX_NAMESPACE(set_tree_index) +void set_tree_index(uint32_t addr[8], uint32_t tree_index); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/api.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/api.h index a82f2f2752..c715a93959 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/api.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/api.h @@ -4,15 +4,13 @@ #include #include - - -#define PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_CRYPTO_ALGNAME "SPHINCS+" +#define PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_CRYPTO_ALGNAME "SPHINCS+-haraka-192s-simple" #define PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_CRYPTO_SECRETKEYBYTES 96 #define PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_CRYPTO_PUBLICKEYBYTES 48 -#define PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_CRYPTO_BYTES 16224 -#define PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_CRYPTO_SEEDBYTES 72 +#define PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_CRYPTO_BYTES 16224 +#define PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_CRYPTO_SEEDBYTES 72 /* * Returns the length of a secret key, in bytes @@ -39,43 +37,41 @@ size_t PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_crypto_sign_seedbytes(void); * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] * Format pk: [root || PUB_SEED] */ -int PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed); +int PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); /* * Generates a SPHINCS+ key pair. * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] * Format pk: [root || PUB_SEED] */ -int PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk); +int PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); /** * Returns an array containing a detached signature. */ -int PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk); +int PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); /** * Verifies a detached signature and message under a given public key. */ -int PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk); +int PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, + const uint8_t *pk); /** * Returns an array containing the signature followed by the message. */ -int PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk); +int PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); /** * Verifies a given signature-message pair under a given public key. */ -int PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk); - +int PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/context.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/context.h new file mode 100644 index 0000000000..f03446b9cb --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/context.h @@ -0,0 +1,22 @@ +#ifndef SPX_CONTEXT_H +#define SPX_CONTEXT_H + +#include + +#include "immintrin.h" +#include "params.h" + +typedef struct { + uint8_t pub_seed[SPX_N]; + uint8_t sk_seed[SPX_N]; + + __m128i rc[40]; +} spx_ctx; + +#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) +void initialize_hash_function(spx_ctx *ctx); + +#define free_hash_function SPX_NAMESPACE(free_hash_function) +void free_hash_function(spx_ctx *ctx); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/context_haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/context_haraka.c new file mode 100644 index 0000000000..f1cd7e3664 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/context_haraka.c @@ -0,0 +1,11 @@ +#include "context.h" +#include "haraka.h" + +void initialize_hash_function(spx_ctx *ctx) { + tweak_constants(ctx); +} + +// we don't support heap-based haraka right now +void free_hash_function(spx_ctx *ctx) { + (void)ctx; // suppress unused variable warnings +} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/fors.c b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/fors.c index 0f1380d137..f1b0639cfc 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/fors.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/fors.c @@ -2,8 +2,9 @@ #include #include -#include "address.h" #include "fors.h" + +#include "address.h" #include "hash.h" #include "hashx4.h" #include "thash.h" @@ -11,19 +12,24 @@ #include "utils.h" #include "utilsx4.h" +static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + prf_addr(sk, ctx, fors_leaf_addr); +} + static void fors_gen_skx4(unsigned char *sk0, unsigned char *sk1, unsigned char *sk2, - unsigned char *sk3, const unsigned char *sk_seed, - uint32_t fors_leaf_addrx4[4 * 8], - const hash_state *state_seeded) { - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_prf_addrx4(sk0, sk1, sk2, sk3, sk_seed, fors_leaf_addrx4, state_seeded); + unsigned char *sk3, const spx_ctx *ctx, + uint32_t fors_leaf_addrx4[4 * 8]) { + prf_addrx4(sk0, sk1, sk2, sk3, + ctx, fors_leaf_addrx4); } static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, - const unsigned char *pub_seed, - uint32_t fors_leaf_addr[8], const hash_state *state_seeded) { - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_thash_1(leaf, sk, pub_seed, fors_leaf_addr, state_seeded); + const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + thash(leaf, sk, 1, ctx, fors_leaf_addr); } static void fors_sk_to_leafx4(unsigned char *leaf0, @@ -34,57 +40,64 @@ static void fors_sk_to_leafx4(unsigned char *leaf0, const unsigned char *sk1, const unsigned char *sk2, const unsigned char *sk3, - const unsigned char *pub_seed, - uint32_t fors_leaf_addrx4[4 * 8], - const hash_state *state_seeded) { - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_thashx4_1(leaf0, leaf1, leaf2, leaf3, - sk0, sk1, sk2, sk3, pub_seed, fors_leaf_addrx4, state_seeded); + const spx_ctx *ctx, + uint32_t fors_leaf_addrx4[4 * 8]) { + thashx4(leaf0, leaf1, leaf2, leaf3, + sk0, sk1, sk2, sk3, + 1, ctx, fors_leaf_addrx4); } -static void fors_gen_leafx4(unsigned char *leaf0, - unsigned char *leaf1, - unsigned char *leaf2, - unsigned char *leaf3, - const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx0, - uint32_t addr_idx1, - uint32_t addr_idx2, - uint32_t addr_idx3, - const uint32_t fors_tree_addr[8], - const hash_state *state_seeded) { - uint32_t fors_leaf_addrx4[4 * 8] = {0}; +struct fors_gen_leaf_info { + uint32_t leaf_addrx[4 * 8]; +}; + +static void fors_gen_leafx4(unsigned char *leaf, + const spx_ctx *ctx, + uint32_t addr_idx, void *info) { + struct fors_gen_leaf_info *fors_info = info; + uint32_t *fors_leaf_addrx4 = fors_info->leaf_addrx; unsigned int j; - /* Only copy the parts that must be kept in fors_leaf_addrx4. */ + /* Only set the parts that the caller doesn't set */ for (j = 0; j < 4; j++) { - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_copy_keypair_addr(fors_leaf_addrx4 + j * 8, fors_tree_addr); - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_set_type(fors_leaf_addrx4 + j * 8, PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_ADDR_TYPE_FORSTREE); + set_tree_index(fors_leaf_addrx4 + j * 8, addr_idx + j); + set_type(fors_leaf_addrx4 + j * 8, SPX_ADDR_TYPE_FORSPRF); } - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_set_tree_index(fors_leaf_addrx4 + 0 * 8, addr_idx0); - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_set_tree_index(fors_leaf_addrx4 + 1 * 8, addr_idx1); - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_set_tree_index(fors_leaf_addrx4 + 2 * 8, addr_idx2); - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_set_tree_index(fors_leaf_addrx4 + 3 * 8, addr_idx3); + fors_gen_skx4(leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + leaf + 2 * SPX_N, + leaf + 3 * SPX_N, + ctx, fors_leaf_addrx4); + + for (j = 0; j < 4; j++) { + set_type(fors_leaf_addrx4 + j * 8, SPX_ADDR_TYPE_FORSTREE); + } - fors_gen_skx4(leaf0, leaf1, leaf2, leaf3, sk_seed, fors_leaf_addrx4, state_seeded); - fors_sk_to_leafx4(leaf0, leaf1, leaf2, leaf3, - leaf0, leaf1, leaf2, leaf3, pub_seed, fors_leaf_addrx4, state_seeded); + fors_sk_to_leafx4(leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + leaf + 2 * SPX_N, + leaf + 3 * SPX_N, + leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + leaf + 2 * SPX_N, + leaf + 3 * SPX_N, + ctx, fors_leaf_addrx4); } /** - * Interprets m as PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_FORS_HEIGHT-bit unsigned integers. - * Assumes m contains at least PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_FORS_TREES bits. - * Assumes indices has space for PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_FORS_TREES integers. + * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + * Assumes indices has space for SPX_FORS_TREES integers. */ static void message_to_indices(uint32_t *indices, const unsigned char *m) { unsigned int i, j; unsigned int offset = 0; - for (i = 0; i < PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_FORS_TREES; i++) { + for (i = 0; i < SPX_FORS_TREES; i++) { indices[i] = 0; - for (j = 0; j < PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_FORS_HEIGHT; j++) { - indices[i] ^= (((uint32_t)m[offset >> 3] >> (offset & 0x7)) & 0x1) << j; + for (j = 0; j < SPX_FORS_HEIGHT; j++) { + indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); offset++; } } @@ -92,68 +105,53 @@ static void message_to_indices(uint32_t *indices, const unsigned char *m) { /** * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_FORS_TREES bits. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. */ -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *state_seeded) { - /* Round up to multiple of 4 to prevent out-of-bounds for x4 parallelism */ - uint32_t indices[(PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_FORS_TREES + 3) & ~3] = {0}; - unsigned char roots[((PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_FORS_TREES + 3) & ~3) * PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N]; - /* Sign to a buffer, since we may not have a nice multiple of 4 and would - otherwise overrun the signature. */ - unsigned char sigbufx4[4 * PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N * (1 + PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_FORS_HEIGHT)]; - uint32_t fors_tree_addrx4[4 * 8] = {0}; +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + uint32_t fors_tree_addr[4 * 8] = {0}; + struct fors_gen_leaf_info fors_info = {0}; + uint32_t *fors_leaf_addr = fors_info.leaf_addrx; uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset[4] = {0}; - unsigned int i, j; + uint32_t idx_offset; + unsigned int i; - for (j = 0; j < 4; j++) { - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_copy_keypair_addr(fors_tree_addrx4 + j * 8, fors_addr); - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_set_type(fors_tree_addrx4 + j * 8, PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_ADDR_TYPE_FORSTREE); + for (i = 0; i < 4; i++) { + copy_keypair_addr(fors_tree_addr + 8 * i, fors_addr); + set_type(fors_tree_addr + 8 * i, SPX_ADDR_TYPE_FORSTREE); + copy_keypair_addr(fors_leaf_addr + 8 * i, fors_addr); } - - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_copy_keypair_addr(fors_pk_addr, fors_addr); - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_set_type(fors_pk_addr, PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_ADDR_TYPE_FORSPK); + copy_keypair_addr(fors_pk_addr, fors_addr); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); message_to_indices(indices, m); - for (i = 0; i < ((PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_FORS_TREES + 3) & ~0x3); i += 4) { - for (j = 0; j < 4; j++) { - if (i + j < PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_FORS_TREES) { - idx_offset[j] = (i + j) * (1 << PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_FORS_HEIGHT); + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_set_tree_height(fors_tree_addrx4 + j * 8, 0); - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_set_tree_index(fors_tree_addrx4 + j * 8, - indices[i + j] + idx_offset[j]); - } - } + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); - /* Include the secret key part that produces the selected leaf nodes. */ - fors_gen_skx4(sigbufx4 + 0 * PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N, - sigbufx4 + 1 * PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N, - sigbufx4 + 2 * PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N, - sigbufx4 + 3 * PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N, - sk_seed, fors_tree_addrx4, state_seeded); - - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_treehashx4_FORS_HEIGHT(roots + i * PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N, sigbufx4 + 4 * PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N, sk_seed, pub_seed, - &indices[i], idx_offset, fors_gen_leafx4, fors_tree_addrx4, - state_seeded); - - for (j = 0; j < 4; j++) { - if (i + j < PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_FORS_TREES) { - memcpy(sig, sigbufx4 + j * PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N, PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N); - memcpy(sig + PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N, - sigbufx4 + 4 * PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N + j * PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N * PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_FORS_HEIGHT, - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N * PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_FORS_HEIGHT); - sig += PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N * (1 + PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_FORS_HEIGHT); - } - } + /* Include the secret key part that produces the selected leaf node. */ + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); + fors_gen_sk(sig, ctx, fors_tree_addr); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + sig += SPX_N; + + /* Compute the authentication path for this leaf node. */ + treehashx4(roots + i * SPX_N, sig, ctx, + indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx4, + fors_tree_addr, &fors_info); + + sig += SPX_N * SPX_FORS_HEIGHT; } /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_thash_FORS_TREES(pk, roots, pub_seed, fors_pk_addr, state_seeded); + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); } /** @@ -161,46 +159,44 @@ void PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_fors_sign(unsigned char *sig, unsigne * This can be used for verification by comparing to a known public key, or to * subsequently verify a signature on the derived public key. The latter is the * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_FORS_TREES bits. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. */ -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, - const uint32_t fors_addr[8], - const hash_state *state_seeded) { - uint32_t indices[PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_FORS_TREES]; - unsigned char roots[PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_FORS_TREES * PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N]; - unsigned char leaf[PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N]; +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + unsigned char leaf[SPX_N]; uint32_t fors_tree_addr[8] = {0}; uint32_t fors_pk_addr[8] = {0}; uint32_t idx_offset; unsigned int i; - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_copy_keypair_addr(fors_tree_addr, fors_addr); - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_copy_keypair_addr(fors_pk_addr, fors_addr); + copy_keypair_addr(fors_tree_addr, fors_addr); + copy_keypair_addr(fors_pk_addr, fors_addr); - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_set_type(fors_tree_addr, PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_set_type(fors_pk_addr, PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_ADDR_TYPE_FORSPK); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); message_to_indices(indices, m); - for (i = 0; i < PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_FORS_TREES; i++) { - idx_offset = i * (1 << PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_FORS_HEIGHT); + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_set_tree_height(fors_tree_addr, 0); - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_set_tree_index(fors_tree_addr, indices[i] + idx_offset); + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); /* Derive the leaf from the included secret key part. */ - fors_sk_to_leaf(leaf, sig, pub_seed, fors_tree_addr, state_seeded); - sig += PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N; + fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); + sig += SPX_N; /* Derive the corresponding root node of this tree. */ - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_compute_root(roots + i * PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N, leaf, indices[i], idx_offset, - sig, PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_FORS_HEIGHT, pub_seed, fors_tree_addr, - state_seeded); - sig += PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N * PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_FORS_HEIGHT; + compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, + sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); + sig += SPX_N * SPX_FORS_HEIGHT; } /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_thash_FORS_TREES(pk, roots, pub_seed, fors_pk_addr, state_seeded); + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/fors.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/fors.h index e111b6be6a..509140a178 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/fors.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/fors.h @@ -1,32 +1,32 @@ -#ifndef PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_FORS_H -#define PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_FORS_H +#ifndef SPX_FORS_H +#define SPX_FORS_H #include -#include "hash_state.h" +#include "context.h" #include "params.h" /** * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_FORS_TREES bits. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. */ -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_fors_sign( - unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *hash_state_seeded); +#define fors_sign SPX_NAMESPACE(fors_sign) +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); /** * Derives the FORS public key from a signature. * This can be used for verification by comparing to a known public key, or to * subsequently verify a signature on the derived public key. The latter is the * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_FORS_TREES bits. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. */ -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_fors_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, const uint32_t fors_addr[8], - const hash_state *hash_state_seeded); +#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/haraka.c index 2716548146..b414b691d7 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/haraka.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/haraka.c @@ -8,10 +8,12 @@ Plain C implementation of the Haraka256 and Haraka512 permutations. #include #include "haraka.h" +#include "harakax4.h" +#include "utils.h" #define HARAKAS_RATE 32 -#define u64 uint64_t +#define u64 unsigned long #define u128 __m128i #define LOAD(src) _mm_loadu_si128((u128 *)(src)) @@ -20,7 +22,7 @@ Plain C implementation of the Haraka256 and Haraka512 permutations. #define XOR128(a, b) _mm_xor_si128(a, b) #define AES2(s0, s1, rci) \ - (s0) = _mm_aesenc_si128(s0, *(rci)); \ + s0 = _mm_aesenc_si128(s0, *(rci)); \ (s1) = _mm_aesenc_si128(s1, *((rci) + 1)); \ (s0) = _mm_aesenc_si128(s0, *((rci) + 2)); \ (s1) = _mm_aesenc_si128(s1, *((rci) + 3)); @@ -32,7 +34,7 @@ Plain C implementation of the Haraka256 and Haraka512 permutations. AES2((s3)[0], (s3)[1], rci); #define AES4(s0, s1, s2, s3, rci) \ - (s0) = _mm_aesenc_si128(s0, *(rci)); \ + s0 = _mm_aesenc_si128(s0, *(rci)); \ (s1) = _mm_aesenc_si128(s1, *((rci) + 1)); \ (s2) = _mm_aesenc_si128(s2, *((rci) + 2)); \ (s3) = _mm_aesenc_si128(s3, *((rci) + 3)); \ @@ -68,17 +70,17 @@ Plain C implementation of the Haraka256 and Haraka512 permutations. _mm_storeu_si128((u128 *)((out) + 16), \ _mm_castpd_si128(_mm_shuffle_pd(_mm_castsi128_pd(s2), _mm_castsi128_pd(s3), 0))); -static void load_haraka_constants(u128 rc[40]) { - rc[ 0] = _mm_set_epi32((int)0x0684704c, (int)0xe620c00a, (int)0xb2c5fef0, (int)0x75817b9d); - rc[ 1] = _mm_set_epi32((int)0x8b66b4e1, (int)0x88f3a06b, (int)0x640f6ba4, (int)0x2f08f717); - rc[ 2] = _mm_set_epi32((int)0x3402de2d, (int)0x53f28498, (int)0xcf029d60, (int)0x9f029114); - rc[ 3] = _mm_set_epi32((int)0x0ed6eae6, (int)0x2e7b4f08, (int)0xbbf3bcaf, (int)0xfd5b4f79); - rc[ 4] = _mm_set_epi32((int)0xcbcfb0cb, (int)0x4872448b, (int)0x79eecd1c, (int)0xbe397044); - rc[ 5] = _mm_set_epi32((int)0x7eeacdee, (int)0x6e9032b7, (int)0x8d5335ed, (int)0x2b8a057b); - rc[ 6] = _mm_set_epi32((int)0x67c28f43, (int)0x5e2e7cd0, (int)0xe2412761, (int)0xda4fef1b); - rc[ 7] = _mm_set_epi32((int)0x2924d9b0, (int)0xafcacc07, (int)0x675ffde2, (int)0x1fc70b3b); - rc[ 8] = _mm_set_epi32((int)0xab4d63f1, (int)0xe6867fe9, (int)0xecdb8fca, (int)0xb9d465ee); - rc[ 9] = _mm_set_epi32((int)0x1c30bf84, (int)0xd4b7cd64, (int)0x5b2a404f, (int)0xad037e33); +static void load_haraka_constants(u128 *rc) { + rc[0] = _mm_set_epi32((int)0x0684704c, (int)0xe620c00a, (int)0xb2c5fef0, (int)0x75817b9d); + rc[1] = _mm_set_epi32((int)0x8b66b4e1, (int)0x88f3a06b, (int)0x640f6ba4, (int)0x2f08f717); + rc[2] = _mm_set_epi32((int)0x3402de2d, (int)0x53f28498, (int)0xcf029d60, (int)0x9f029114); + rc[3] = _mm_set_epi32((int)0x0ed6eae6, (int)0x2e7b4f08, (int)0xbbf3bcaf, (int)0xfd5b4f79); + rc[4] = _mm_set_epi32((int)0xcbcfb0cb, (int)0x4872448b, (int)0x79eecd1c, (int)0xbe397044); + rc[5] = _mm_set_epi32((int)0x7eeacdee, (int)0x6e9032b7, (int)0x8d5335ed, (int)0x2b8a057b); + rc[6] = _mm_set_epi32((int)0x67c28f43, (int)0x5e2e7cd0, (int)0xe2412761, (int)0xda4fef1b); + rc[7] = _mm_set_epi32((int)0x2924d9b0, (int)0xafcacc07, (int)0x675ffde2, (int)0x1fc70b3b); + rc[8] = _mm_set_epi32((int)0xab4d63f1, (int)0xe6867fe9, (int)0xecdb8fca, (int)0xb9d465ee); + rc[9] = _mm_set_epi32((int)0x1c30bf84, (int)0xd4b7cd64, (int)0x5b2a404f, (int)0xad037e33); rc[10] = _mm_set_epi32((int)0xb2cc0bb9, (int)0x941723bf, (int)0x69028b2e, (int)0x8df69800); rc[11] = _mm_set_epi32((int)0xfa0478a6, (int)0xde6f5572, (int)0x4aaa9ec8, (int)0x5c9d2d8a); rc[12] = _mm_set_epi32((int)0xdfb49f2b, (int)0x6b772a12, (int)0x0efa4f2e, (int)0x29129fd4); @@ -111,77 +113,65 @@ static void load_haraka_constants(u128 rc[40]) { rc[39] = _mm_set_epi32((int)0x756acc03, (int)0x02288288, (int)0x4ad6bdfd, (int)0xe9c59da1); } -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_tweak_constants( - harakactx *state, - const unsigned char *pk_seed, const unsigned char *sk_seed, - unsigned long long seed_length) { +void tweak_constants(spx_ctx *ctx) { int i; unsigned char buf[40 * 16]; /* Use the standard constants to generate tweaked ones. */ - load_haraka_constants(state->rc); - - /* Constants for sk.seed */ - if (sk_seed != NULL) { - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_haraka_S(buf, 40 * 16, sk_seed, seed_length, state); - /* Tweak constants with the pub_seed */ - for (i = 0; i < 40; i++) { - state->rc_sseed[i] = LOAD(buf + i * 16); - } - } + load_haraka_constants(ctx->rc); /* Constants for pk.seed */ - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_haraka_S(buf, 40 * 16, pk_seed, seed_length, state); + haraka_S(buf, 40 * 16, ctx->pub_seed, SPX_N, ctx); /* Tweak constants with the pub_seed */ for (i = 0; i < 40; i++) { - state->rc[i] = LOAD(buf + i * 16); + ctx->rc[i] = LOAD(buf + i * 16); } } -static void haraka_S_absorb(unsigned char *s, +static void haraka_S_absorb(unsigned char *s, unsigned int r, const unsigned char *m, unsigned long long mlen, - unsigned char p, - const harakactx *state) { + unsigned char p, const spx_ctx *ctx) { unsigned long long i; - unsigned char t[HARAKAS_RATE]; + PQCLEAN_VLA(unsigned char, t, r); - while (mlen >= HARAKAS_RATE) { + while (mlen >= r) { // XOR block to state STORE(s, XOR128(LOAD(s), LOAD(m))); STORE(s + 16, XOR128(LOAD(s + 16), LOAD(m + 16))); - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_haraka512_perm(s, s, state); - mlen -= HARAKAS_RATE; - m += HARAKAS_RATE; + haraka512_perm(s, s, ctx); + mlen -= r; + m += r; } - for (i = 0; i < HARAKAS_RATE; ++i) { + for (i = 0; i < r; ++i) { t[i] = 0; } for (i = 0; i < mlen; ++i) { t[i] = m[i]; } t[i] = p; - t[HARAKAS_RATE - 1] |= 128; + t[r - 1] |= 128; STORE(s, XOR128(LOAD(s), LOAD(t))); STORE(s + 16, XOR128(LOAD(s + 16), LOAD(t + 16))); } static void haraka_S_absorb4x(unsigned char *s, + unsigned int r, const unsigned char *m0, const unsigned char *m1, const unsigned char *m2, const unsigned char *m3, unsigned long long int mlen, unsigned char p, - const harakactx *state) { + const spx_ctx *ctx) { unsigned long long i; - unsigned char t0[HARAKAS_RATE]; - unsigned char t1[HARAKAS_RATE]; - unsigned char t2[HARAKAS_RATE]; - unsigned char t3[HARAKAS_RATE]; + PQCLEAN_VLA(unsigned char, t0, r); + PQCLEAN_VLA(unsigned char, t1, r); + PQCLEAN_VLA(unsigned char, t2, r); + PQCLEAN_VLA(unsigned char, t3, r); - while (mlen >= HARAKAS_RATE) { + while (mlen >= r) { // XOR block to state STORE(s, XOR128(LOAD(s), LOAD(m0))); STORE(s + 16, XOR128(LOAD(s + 16), LOAD(m0 + 16))); @@ -192,15 +182,15 @@ static void haraka_S_absorb4x(unsigned char *s, STORE(s + 192, XOR128(LOAD(s + 192), LOAD(m3))); STORE(s + 208, XOR128(LOAD(s + 208), LOAD(m3 + 16))); - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_haraka512_perm_x4(s, s, state); - mlen -= HARAKAS_RATE; - m0 += HARAKAS_RATE; - m1 += HARAKAS_RATE; - m2 += HARAKAS_RATE; - m3 += HARAKAS_RATE; + haraka512_perm_x4(s, s, ctx); + mlen -= r; + m0 += r; + m1 += r; + m2 += r; + m3 += r; } - for (i = 0; i < HARAKAS_RATE; ++i) { + for (i = 0; i < r; ++i) { t0[i] = 0; t1[i] = 0; t2[i] = 0; @@ -218,10 +208,10 @@ static void haraka_S_absorb4x(unsigned char *s, t2[i] = p; t3[i] = p; - t0[HARAKAS_RATE - 1] |= 128; - t1[HARAKAS_RATE - 1] |= 128; - t2[HARAKAS_RATE - 1] |= 128; - t3[HARAKAS_RATE - 1] |= 128; + t0[r - 1] |= 128; + t1[r - 1] |= 128; + t2[r - 1] |= 128; + t3[r - 1] |= 128; STORE(s, XOR128(LOAD(s), LOAD(t0))); STORE(s + 16, XOR128(LOAD(s + 16), LOAD(t0 + 16))); @@ -234,9 +224,10 @@ static void haraka_S_absorb4x(unsigned char *s, } static void haraka_S_squeezeblocks(unsigned char *h, unsigned long long nblocks, - unsigned char *s, unsigned int r, const harakactx *state) { + unsigned char *s, unsigned int r, + const spx_ctx *ctx) { while (nblocks > 0) { - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_haraka512_perm(s, s, state); + haraka512_perm(s, s, ctx); STORE(h, LOAD(s)); STORE(h + 16, LOAD(s + 16)); h += r; @@ -251,9 +242,9 @@ static void haraka_S_squeezeblocks4x(unsigned char *h0, unsigned long long nblocks, unsigned char *s, unsigned int r, - const harakactx *state) { + const spx_ctx *ctx) { while (nblocks > 0) { - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_haraka512_perm_x4(s, s, state); + haraka512_perm_x4(s, s, ctx); STORE(h0, LOAD(s)); STORE(h0 + 16, LOAD(s + 16)); STORE(h1, LOAD(s + 64)); @@ -270,7 +261,7 @@ static void haraka_S_squeezeblocks4x(unsigned char *h0, } } -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_haraka_S_inc_init(uint8_t *s_inc) { +void haraka_S_inc_init(uint8_t *s_inc) { size_t i; for (i = 0; i < 64; i++) { @@ -279,7 +270,8 @@ void PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_haraka_S_inc_init(uint8_t *s_inc) { s_inc[64] = 0; } -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, const harakactx *state) { +void haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, + const spx_ctx *ctx) { size_t i; /* Recall that s_inc[64] is the non-absorbed bytes xored into the state */ @@ -293,16 +285,16 @@ void PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_haraka_S_inc_absorb(uint8_t *s_inc, c m += HARAKAS_RATE - s_inc[64]; s_inc[64] = 0; - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_haraka512_perm(s_inc, s_inc, state); + haraka512_perm(s_inc, s_inc, ctx); } for (i = 0; i < mlen; i++) { s_inc[s_inc[64] + i] ^= m[i]; } - s_inc[64] = (uint8_t)(s_inc[64] + mlen); + s_inc[64] += (uint8_t)mlen; } -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_haraka_S_inc_finalize(uint8_t *s_inc) { +void haraka_S_inc_finalize(uint8_t *s_inc) { /* After haraka_S_inc_absorb, we are guaranteed that s_inc[64] < HARAKAS_RATE, so we can always use one more byte for p in the current state. */ s_inc[s_inc[64]] ^= 0x1F; @@ -310,22 +302,23 @@ void PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_haraka_S_inc_finalize(uint8_t *s_inc) s_inc[64] = 0; } -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, const harakactx *state) { +void haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, + const spx_ctx *ctx) { size_t i; /* First consume any bytes we still have sitting around */ for (i = 0; i < outlen && i < s_inc[64]; i++) { /* There are s_inc[64] bytes left, so r - s_inc[64] is the first available byte. We consume from there, i.e., up to r. */ - out[i] = (uint8_t)s_inc[(HARAKAS_RATE - s_inc[64] + (uint8_t)i)]; + out[i] = (uint8_t)s_inc[(HARAKAS_RATE - s_inc[64] + i)]; } out += i; outlen -= i; - s_inc[64] = (uint8_t)(s_inc[64] - i); + s_inc[64] -= (uint8_t)i; /* Then squeeze the remaining necessary blocks */ while (outlen > 0) { - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_haraka512_perm(s_inc, s_inc, state); + haraka512_perm(s_inc, s_inc, ctx); for (i = 0; i < outlen && i < HARAKAS_RATE; i++) { out[i] = s_inc[i]; @@ -336,8 +329,9 @@ void PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_haraka_S_inc_squeeze(uint8_t *out, si } } -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_haraka_S(unsigned char *out, unsigned long long outlen, - const unsigned char *in, unsigned long long inlen, const harakactx *state) { +void haraka_S(unsigned char *out, unsigned long long outlen, + const unsigned char *in, unsigned long long inlen, + const spx_ctx *ctx) { unsigned long long i; unsigned char s[64]; unsigned char d[32]; @@ -345,30 +339,30 @@ void PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_haraka_S(unsigned char *out, unsigned for (i = 0; i < 64; i++) { s[i] = 0; } - haraka_S_absorb(s, in, inlen, 0x1F, state); + haraka_S_absorb(s, HARAKAS_RATE, in, inlen, 0x1F, ctx); - haraka_S_squeezeblocks(out, outlen / HARAKAS_RATE, s, HARAKAS_RATE, state); + haraka_S_squeezeblocks(out, outlen / HARAKAS_RATE, s, HARAKAS_RATE, ctx); out += (outlen / HARAKAS_RATE) * HARAKAS_RATE; if (outlen % HARAKAS_RATE) { - haraka_S_squeezeblocks(d, 1, s, HARAKAS_RATE, state); + haraka_S_squeezeblocks(d, 1, s, HARAKAS_RATE, ctx); for (i = 0; i < outlen % HARAKAS_RATE; i++) { out[i] = d[i]; } } } -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_haraka_Sx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned long long outlen, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - unsigned long long inlen, - const harakactx *state) { +void haraka_Sx4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned long long outlen, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + unsigned long long inlen, + const spx_ctx *ctx) { unsigned long long i; unsigned char s[64 * 4]; unsigned char d0[32]; @@ -379,16 +373,17 @@ void PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_haraka_Sx4(unsigned char *out0, for (i = 0; i < 64 * 4; i++) { s[i] = 0; } - haraka_S_absorb4x(s, in0, in1, in2, in3, inlen, 0x1F, state); + haraka_S_absorb4x(s, HARAKAS_RATE, in0, in1, in2, in3, inlen, 0x1F, ctx); - haraka_S_squeezeblocks4x(out0, out1, out2, out3, outlen / HARAKAS_RATE, s, HARAKAS_RATE, state); + haraka_S_squeezeblocks4x(out0, out1, out2, out3, outlen / HARAKAS_RATE, s, + HARAKAS_RATE, ctx); out0 += (outlen / HARAKAS_RATE) * HARAKAS_RATE; out1 += (outlen / HARAKAS_RATE) * HARAKAS_RATE; out2 += (outlen / HARAKAS_RATE) * HARAKAS_RATE; out3 += (outlen / HARAKAS_RATE) * HARAKAS_RATE; if (outlen % HARAKAS_RATE) { - haraka_S_squeezeblocks4x(d0, d1, d2, d3, 1, s, HARAKAS_RATE, state); + haraka_S_squeezeblocks4x(d0, d1, d2, d3, 1, s, HARAKAS_RATE, ctx); for (i = 0; i < outlen % HARAKAS_RATE; i++) { out0[i] = d0[i]; out1[i] = d1[i]; @@ -398,7 +393,8 @@ void PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_haraka_Sx4(unsigned char *out0, } } -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_haraka512_perm(unsigned char *out, const unsigned char *in, const harakactx *state) { +void haraka512_perm(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx) { u128 s[4], tmp; s[0] = LOAD(in); @@ -406,19 +402,19 @@ void PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_haraka512_perm(unsigned char *out, co s[2] = LOAD(in + 32); s[3] = LOAD(in + 48); - AES4(s[0], s[1], s[2], s[3], state->rc); + AES4(s[0], s[1], s[2], s[3], ctx->rc); MIX4(s[0], s[1], s[2], s[3]); - AES4(s[0], s[1], s[2], s[3], state->rc + 8); + AES4(s[0], s[1], s[2], s[3], ctx->rc + 8); MIX4(s[0], s[1], s[2], s[3]); - AES4(s[0], s[1], s[2], s[3], state->rc + 16); + AES4(s[0], s[1], s[2], s[3], ctx->rc + 16); MIX4(s[0], s[1], s[2], s[3]); - AES4(s[0], s[1], s[2], s[3], state->rc + 24); + AES4(s[0], s[1], s[2], s[3], ctx->rc + 24); MIX4(s[0], s[1], s[2], s[3]); - AES4(s[0], s[1], s[2], s[3], state->rc + 32); + AES4(s[0], s[1], s[2], s[3], ctx->rc + 32); MIX4(s[0], s[1], s[2], s[3]); STORE(out, s[0]); @@ -427,7 +423,8 @@ void PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_haraka512_perm(unsigned char *out, co STORE(out + 48, s[3]); } -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_haraka512_perm_x4(unsigned char *out, const unsigned char *in, const harakactx *state) { +void haraka512_perm_x4(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx) { u128 s[4][4], tmp; s[0][0] = LOAD(in); @@ -447,31 +444,31 @@ void PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_haraka512_perm_x4(unsigned char *out, s[3][2] = LOAD(in + 224); s[3][3] = LOAD(in + 240); - AES4_4x(s[0], s[1], s[2], s[3], state->rc); + AES4_4x(s[0], s[1], s[2], s[3], ctx->rc); MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - AES4_4x(s[0], s[1], s[2], s[3], state->rc + 8); + AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 8); MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - AES4_4x(s[0], s[1], s[2], s[3], state->rc + 16); + AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 16); MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - AES4_4x(s[0], s[1], s[2], s[3], state->rc + 24); + AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 24); MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - AES4_4x(s[0], s[1], s[2], s[3], state->rc + 32); + AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 32); MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); @@ -495,7 +492,8 @@ void PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_haraka512_perm_x4(unsigned char *out, STORE(out + 240, s[3][3]); } -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_haraka512(unsigned char *out, const unsigned char *in, const harakactx *state) { +void haraka512(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx) { u128 s[4], tmp; s[0] = LOAD(in); @@ -503,19 +501,19 @@ void PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_haraka512(unsigned char *out, const u s[2] = LOAD(in + 32); s[3] = LOAD(in + 48); - AES4(s[0], s[1], s[2], s[3], state->rc); + AES4(s[0], s[1], s[2], s[3], ctx->rc); MIX4(s[0], s[1], s[2], s[3]); - AES4(s[0], s[1], s[2], s[3], state->rc + 8); + AES4(s[0], s[1], s[2], s[3], ctx->rc + 8); MIX4(s[0], s[1], s[2], s[3]); - AES4(s[0], s[1], s[2], s[3], state->rc + 16); + AES4(s[0], s[1], s[2], s[3], ctx->rc + 16); MIX4(s[0], s[1], s[2], s[3]); - AES4(s[0], s[1], s[2], s[3], state->rc + 24); + AES4(s[0], s[1], s[2], s[3], ctx->rc + 24); MIX4(s[0], s[1], s[2], s[3]); - AES4(s[0], s[1], s[2], s[3], state->rc + 32); + AES4(s[0], s[1], s[2], s[3], ctx->rc + 32); MIX4(s[0], s[1], s[2], s[3]); s[0] = XOR128(s[0], LOAD(in)); @@ -527,7 +525,8 @@ void PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_haraka512(unsigned char *out, const u TRUNCSTORE(out, s[0], s[1], s[2], s[3]); } -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_haraka512x4(unsigned char *out, const unsigned char *in, const harakactx *state) { +void haraka512x4(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx) { u128 s[4][4], tmp; s[0][0] = LOAD(in); @@ -547,31 +546,31 @@ void PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_haraka512x4(unsigned char *out, const s[3][2] = LOAD(in + 224); s[3][3] = LOAD(in + 240); - AES4_4x(s[0], s[1], s[2], s[3], state->rc); + AES4_4x(s[0], s[1], s[2], s[3], ctx->rc); MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - AES4_4x(s[0], s[1], s[2], s[3], state->rc + 8); + AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 8); MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - AES4_4x(s[0], s[1], s[2], s[3], state->rc + 16); + AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 16); MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - AES4_4x(s[0], s[1], s[2], s[3], state->rc + 24); + AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 24); MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - AES4_4x(s[0], s[1], s[2], s[3], state->rc + 32); + AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 32); MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); @@ -600,25 +599,26 @@ void PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_haraka512x4(unsigned char *out, const TRUNCSTORE((out + 96), s[3][0], s[3][1], s[3][2], s[3][3]); } -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_haraka256(unsigned char *out, const unsigned char *in, const harakactx *state) { +void haraka256(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx) { u128 s[2], tmp; s[0] = LOAD(in); s[1] = LOAD(in + 16); - AES2(s[0], s[1], state->rc); + AES2(s[0], s[1], ctx->rc); MIX2(s[0], s[1]); - AES2(s[0], s[1], state->rc + 4); + AES2(s[0], s[1], ctx->rc + 4); MIX2(s[0], s[1]); - AES2(s[0], s[1], state->rc + 8); + AES2(s[0], s[1], ctx->rc + 8); MIX2(s[0], s[1]); - AES2(s[0], s[1], state->rc + 12); + AES2(s[0], s[1], ctx->rc + 12); MIX2(s[0], s[1]); - AES2(s[0], s[1], state->rc + 16); + AES2(s[0], s[1], ctx->rc + 16); MIX2(s[0], s[1]); s[0] = XOR128(s[0], LOAD(in)); @@ -628,7 +628,8 @@ void PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_haraka256(unsigned char *out, const u STORE(out + 16, s[1]); } -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_haraka256x4(unsigned char *out, const unsigned char *in, const harakactx *state) { +void haraka256x4(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx) { u128 s[4][2], tmp; s[0][0] = LOAD(in); @@ -641,7 +642,7 @@ void PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_haraka256x4(unsigned char *out, const s[3][1] = LOAD(in + 112); // Round 1 - AES2_4x(s[0], s[1], s[2], s[3], state->rc); + AES2_4x(s[0], s[1], s[2], s[3], ctx->rc); MIX2(s[0][0], s[0][1]); MIX2(s[1][0], s[1][1]); @@ -649,7 +650,7 @@ void PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_haraka256x4(unsigned char *out, const MIX2(s[3][0], s[3][1]); // Round 2 - AES2_4x(s[0], s[1], s[2], s[3], state->rc + 4); + AES2_4x(s[0], s[1], s[2], s[3], ctx->rc + 4); MIX2(s[0][0], s[0][1]); MIX2(s[1][0], s[1][1]); @@ -657,7 +658,7 @@ void PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_haraka256x4(unsigned char *out, const MIX2(s[3][0], s[3][1]); // Round 3 - AES2_4x(s[0], s[1], s[2], s[3], state->rc + 8); + AES2_4x(s[0], s[1], s[2], s[3], ctx->rc + 8); MIX2(s[0][0], s[0][1]); MIX2(s[1][0], s[1][1]); @@ -665,7 +666,7 @@ void PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_haraka256x4(unsigned char *out, const MIX2(s[3][0], s[3][1]); // Round 4 - AES2_4x(s[0], s[1], s[2], s[3], state->rc + 12); + AES2_4x(s[0], s[1], s[2], s[3], ctx->rc + 12); MIX2(s[0][0], s[0][1]); MIX2(s[1][0], s[1][1]); @@ -673,7 +674,7 @@ void PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_haraka256x4(unsigned char *out, const MIX2(s[3][0], s[3][1]); // Round 5 - AES2_4x(s[0], s[1], s[2], s[3], state->rc + 16); + AES2_4x(s[0], s[1], s[2], s[3], ctx->rc + 16); MIX2(s[0][0], s[0][1]); MIX2(s[1][0], s[1][1]); @@ -699,103 +700,3 @@ void PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_haraka256x4(unsigned char *out, const STORE(out + 96, s[3][0]); STORE(out + 112, s[3][1]); } - -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_haraka256_sk(unsigned char *out, const unsigned char *in, const harakactx *state) { - u128 s[2], tmp; - - s[0] = LOAD(in); - s[1] = LOAD(in + 16); - - AES2(s[0], s[1], state->rc_sseed); - MIX2(s[0], s[1]); - - AES2(s[0], s[1], state->rc_sseed + 4); - MIX2(s[0], s[1]); - - AES2(s[0], s[1], state->rc_sseed + 8); - MIX2(s[0], s[1]); - - AES2(s[0], s[1], state->rc_sseed + 12); - MIX2(s[0], s[1]); - - AES2(s[0], s[1], state->rc_sseed + 16); - MIX2(s[0], s[1]); - - s[0] = XOR128(s[0], LOAD(in)); - s[1] = XOR128(s[1], LOAD(in + 16)); - - STORE(out, s[0]); - STORE(out + 16, s[1]); -} - -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_haraka256_skx4(unsigned char *out, const unsigned char *in, const harakactx *state) { - u128 s[4][2], tmp; - - s[0][0] = LOAD(in); - s[0][1] = LOAD(in + 16); - s[1][0] = LOAD(in + 32); - s[1][1] = LOAD(in + 48); - s[2][0] = LOAD(in + 64); - s[2][1] = LOAD(in + 80); - s[3][0] = LOAD(in + 96); - s[3][1] = LOAD(in + 112); - - // Round 1 - AES2_4x(s[0], s[1], s[2], s[3], state->rc_sseed); - - MIX2(s[0][0], s[0][1]); - MIX2(s[1][0], s[1][1]); - MIX2(s[2][0], s[2][1]); - MIX2(s[3][0], s[3][1]); - - // Round 2 - AES2_4x(s[0], s[1], s[2], s[3], state->rc_sseed + 4); - - MIX2(s[0][0], s[0][1]); - MIX2(s[1][0], s[1][1]); - MIX2(s[2][0], s[2][1]); - MIX2(s[3][0], s[3][1]); - - // Round 3 - AES2_4x(s[0], s[1], s[2], s[3], state->rc_sseed + 8); - - MIX2(s[0][0], s[0][1]); - MIX2(s[1][0], s[1][1]); - MIX2(s[2][0], s[2][1]); - MIX2(s[3][0], s[3][1]); - - // Round 4 - AES2_4x(s[0], s[1], s[2], s[3], state->rc_sseed + 12); - - MIX2(s[0][0], s[0][1]); - MIX2(s[1][0], s[1][1]); - MIX2(s[2][0], s[2][1]); - MIX2(s[3][0], s[3][1]); - - // Round 5 - AES2_4x(s[0], s[1], s[2], s[3], state->rc_sseed + 16); - - MIX2(s[0][0], s[0][1]); - MIX2(s[1][0], s[1][1]); - MIX2(s[2][0], s[2][1]); - MIX2(s[3][0], s[3][1]); - - // Feed Forward - s[0][0] = XOR128(s[0][0], LOAD(in)); - s[0][1] = XOR128(s[0][1], LOAD(in + 16)); - s[1][0] = XOR128(s[1][0], LOAD(in + 32)); - s[1][1] = XOR128(s[1][1], LOAD(in + 48)); - s[2][0] = XOR128(s[2][0], LOAD(in + 64)); - s[2][1] = XOR128(s[2][1], LOAD(in + 80)); - s[3][0] = XOR128(s[3][0], LOAD(in + 96)); - s[3][1] = XOR128(s[3][1], LOAD(in + 112)); - - STORE(out, s[0][0]); - STORE(out + 16, s[0][1]); - STORE(out + 32, s[1][0]); - STORE(out + 48, s[1][1]); - STORE(out + 64, s[2][0]); - STORE(out + 80, s[2][1]); - STORE(out + 96, s[3][0]); - STORE(out + 112, s[3][1]); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/haraka.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/haraka.h index e0838b743f..737cb6065f 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/haraka.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/haraka.h @@ -1,57 +1,42 @@ -#ifndef PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_HARAKA_H -#define PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_HARAKA_H +#ifndef SPX_HARAKA_H +#define SPX_HARAKA_H -#include -#include -#include - -typedef struct { - __m128i rc[40]; - __m128i rc_sseed[40]; -} harakactx; +#include "context.h" +#include "params.h" /* Tweak constants with seed */ -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_tweak_constants( - harakactx *state, - const unsigned char *pk_seed, const unsigned char *sk_seed, - unsigned long long seed_length); +#define tweak_constants SPX_NAMESPACE(tweak_constants) +void tweak_constants(spx_ctx *ctx); /* Haraka Sponge */ -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_haraka_S_inc_init(uint8_t *s_inc); -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, const harakactx *state); -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_haraka_S_inc_finalize(uint8_t *s_inc); -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, const harakactx *state); -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_haraka_S( - unsigned char *out, unsigned long long outlen, - const unsigned char *in, unsigned long long inlen, const harakactx *state); -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_haraka_Sx4( - unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned long long outlen, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - unsigned long long inlen, - const harakactx *state); - +#define haraka_S_inc_init SPX_NAMESPACE(haraka_S_inc_init) +void haraka_S_inc_init(uint8_t *s_inc); +#define haraka_S_inc_absorb SPX_NAMESPACE(haraka_S_inc_absorb) +void haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, + const spx_ctx *ctx); +#define haraka_S_inc_finalize SPX_NAMESPACE(haraka_S_inc_finalize) +void haraka_S_inc_finalize(uint8_t *s_inc); +#define haraka_S_inc_squeeze SPX_NAMESPACE(haraka_S_inc_squeeze) +void haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, + const spx_ctx *ctx); +#define haraka_S SPX_NAMESPACE(haraka_S) +void haraka_S(unsigned char *out, unsigned long long outlen, + const unsigned char *in, unsigned long long inlen, + const spx_ctx *ctx); /* Applies the 512-bit Haraka permutation to in. */ -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_haraka512_perm(unsigned char *out, const unsigned char *in, const harakactx *state); -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_haraka512_perm_x4(unsigned char *out, const unsigned char *in, const harakactx *state); +#define haraka512_perm SPX_NAMESPACE(haraka512_perm) +void haraka512_perm(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx); /* Implementation of Haraka-512 */ -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_haraka512(unsigned char *out, const unsigned char *in, const harakactx *state); -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_haraka512x4(unsigned char *out, const unsigned char *in, const harakactx *state); +#define haraka512 SPX_NAMESPACE(haraka512) +void haraka512(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx); /* Implementation of Haraka-256 */ -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_haraka256(unsigned char *out, const unsigned char *in, const harakactx *state); -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_haraka256x4(unsigned char *out, const unsigned char *in, const harakactx *state); - -/* Implementation of Haraka-256 using sk.seed constants */ -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_haraka256_sk(unsigned char *out, const unsigned char *in, const harakactx *state); -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_haraka256_skx4(unsigned char *out, const unsigned char *in, const harakactx *state); +#define haraka256 SPX_NAMESPACE(haraka256) +void haraka256(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/haraka_offsets.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/haraka_offsets.h new file mode 100644 index 0000000000..7c062272a0 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/haraka_offsets.h @@ -0,0 +1,21 @@ +#ifndef HARAKA_OFFSETS_H_ +#define HARAKA_OFFSETS_H_ + +/* + * Offsets of various fields in the address structure when we use Haraka as + * the Sphincs+ hash function + */ + +#define SPX_OFFSET_LAYER 3 /* The byte used to specify the Merkle tree layer */ +#define SPX_OFFSET_TREE 8 /* The start of the 8 byte field used to specify the tree */ +#define SPX_OFFSET_TYPE 19 /* The byte used to specify the hash type (reason) */ +#define SPX_OFFSET_KP_ADDR2 22 /* The high byte used to specify the key pair (which one-time signature) */ +#define SPX_OFFSET_KP_ADDR1 23 /* The low byte used to specify the key pair */ +#define SPX_OFFSET_CHAIN_ADDR 27 /* The byte used to specify the chain address (which Winternitz chain) */ +#define SPX_OFFSET_HASH_ADDR 31 /* The byte used to specify the hash address (where in the Winternitz chain) */ +#define SPX_OFFSET_TREE_HGT 27 /* The byte used to specify the height of this node in the FORS or Merkle tree */ +#define SPX_OFFSET_TREE_INDEX 28 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ + +#define SPX_HARAKA 1 + +#endif /* HARAKA_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/harakax4.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/harakax4.h new file mode 100644 index 0000000000..eadc69aa48 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/harakax4.h @@ -0,0 +1,36 @@ +#ifndef SPX_HARAKAX4_H +#define SPX_HARAKAX4_H + +#include "context.h" +#include "params.h" + +/* Haraka Sponge */ +#define haraka_Sx4 SPX_NAMESPACE(haraka_Sx4) +void haraka_Sx4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned long long outlen, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + unsigned long long inlen, + const spx_ctx *ctx); + +/* Applies the 512-bit Haraka permutation x4 to in. */ +#define haraka512_perm_x4 SPX_NAMESPACE(haraka512_perm_x4) +void haraka512_perm_x4(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx); + +/* Implementation of Haraka-512 x4*/ +#define haraka512x4 SPX_NAMESPACE(haraka512x4) +void haraka512x4(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx); + +/* Implementation of Haraka-256 x4 */ +#define haraka256x4 SPX_NAMESPACE(haraka256x4) +void haraka256x4(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/hash.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/hash.h index 9c0f69279e..f7c87d4c3c 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/hash.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/hash.h @@ -1,31 +1,28 @@ -#ifndef PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_HASH_H -#define PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_HASH_H - -#include "hash_state.h" +#ifndef SPX_HASH_H +#define SPX_HASH_H #include #include -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_initialize_hash_function( - hash_state *hash_state_seeded, - const unsigned char *pub_seed, const unsigned char *sk_seed); +#include "context.h" +#include "params.h" + +#define prf_addr SPX_NAMESPACE(prf_addr) +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]); -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_destroy_hash_function(hash_state *hash_state_seeded); +#define gen_message_random SPX_NAMESPACE(gen_message_random) +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded); +#define hash_message SPX_NAMESPACE(hash_message) +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/hash_haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/hash_haraka.c index b5b7e6b2d1..750a67423b 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/hash_haraka.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/hash_haraka.c @@ -2,58 +2,44 @@ #include #include "address.h" -#include "haraka.h" -#include "hash.h" #include "params.h" #include "utils.h" -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_initialize_hash_function( - hash_state *hash_state_seeded, - const unsigned char *pub_seed, const unsigned char *sk_seed) { - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_tweak_constants(hash_state_seeded, pub_seed, sk_seed, PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N); -} - -/* The haraka implementation is stack based and won't be replaced in PQClean/OQS, - so we don't need to do anything */ -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_destroy_hash_function( - hash_state *hash_state_seeded) { // NOLINT(readability-non-const-parameter) - (void)hash_state_seeded; -} +#include "haraka.h" +#include "hash.h" /* - * Computes PRF(key, addr), given a secret key of PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N bytes and an address + * Computes PRF(key, addr), given a secret key of SPX_N bytes and an address */ -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded) { - unsigned char buf[PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_ADDR_BYTES]; - /* Since PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N may be smaller than 32, we need a temporary buffer. */ +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]) { + /* Since SPX_N may be smaller than 32, we need temporary buffers. */ unsigned char outbuf[32]; + unsigned char buf[64] = {0}; - (void)key; /* Suppress an 'unused parameter' warning. */ + memcpy(buf, addr, SPX_ADDR_BYTES); + memcpy(buf + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_addr_to_bytes(buf, addr); - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_haraka256_sk(outbuf, buf, hash_state_seeded); - memcpy(out, outbuf, PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N); + haraka512(outbuf, (const void *)buf, ctx); + memcpy(out, outbuf, SPX_N); } /** * Computes the message-dependent randomness R, using a secret seed and an * optional randomization value as well as the message. */ -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded) { +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { uint8_t s_inc[65]; - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_haraka_S_inc_init(s_inc); - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_haraka_S_inc_absorb(s_inc, sk_prf, PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_haraka_S_inc_absorb(s_inc, optrand, PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_haraka_S_inc_absorb(s_inc, m, mlen, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_haraka_S_inc_finalize(s_inc); - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_haraka_S_inc_squeeze(R, PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N, s_inc, hash_state_seeded); + haraka_S_inc_init(s_inc); + haraka_S_inc_absorb(s_inc, sk_prf, SPX_N, ctx); + haraka_S_inc_absorb(s_inc, optrand, SPX_N, ctx); + haraka_S_inc_absorb(s_inc, m, mlen, ctx); + haraka_S_inc_finalize(s_inc); + haraka_S_inc_squeeze(R, SPX_N, s_inc, ctx); } /** @@ -61,36 +47,35 @@ void PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_gen_message_random( * Outputs the message digest and the index of the leaf. The index is split in * the tree index and the leaf index, for convenient copying to an address. */ -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded) { -#define PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_TREE_BITS (PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_TREE_HEIGHT * (PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_D - 1)) -#define PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_TREE_BYTES ((PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_TREE_BITS + 7) / 8) -#define PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_LEAF_BITS PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_TREE_HEIGHT -#define PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_LEAF_BYTES ((PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_LEAF_BITS + 7) / 8) -#define PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_DGST_BYTES (PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_FORS_MSG_BYTES + PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_TREE_BYTES + PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_LEAF_BYTES) +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { +#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) +#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) +#define SPX_LEAF_BITS SPX_TREE_HEIGHT +#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) +#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) - unsigned char buf[PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_DGST_BYTES]; + unsigned char buf[SPX_DGST_BYTES]; unsigned char *bufp = buf; uint8_t s_inc[65]; - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_haraka_S_inc_init(s_inc); - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_haraka_S_inc_absorb(s_inc, R, PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_haraka_S_inc_absorb(s_inc, pk + PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N, PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_haraka_S_inc_absorb(s_inc, m, mlen, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_haraka_S_inc_finalize(s_inc); - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_haraka_S_inc_squeeze(buf, PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_DGST_BYTES, s_inc, hash_state_seeded); + haraka_S_inc_init(s_inc); + haraka_S_inc_absorb(s_inc, R, SPX_N, ctx); + haraka_S_inc_absorb(s_inc, pk + SPX_N, SPX_N, ctx); // Only absorb root part of pk + haraka_S_inc_absorb(s_inc, m, mlen, ctx); + haraka_S_inc_finalize(s_inc); + haraka_S_inc_squeeze(buf, SPX_DGST_BYTES, s_inc, ctx); + + memcpy(digest, bufp, SPX_FORS_MSG_BYTES); + bufp += SPX_FORS_MSG_BYTES; - memcpy(digest, bufp, PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_FORS_MSG_BYTES); - bufp += PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_FORS_MSG_BYTES; - *tree = PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_bytes_to_ull(bufp, PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_TREE_BYTES); - *tree &= (~(uint64_t)0) >> (64 - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_TREE_BITS); - bufp += PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_TREE_BYTES; + *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); + *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); + bufp += SPX_TREE_BYTES; - *leaf_idx = (uint32_t)PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_bytes_to_ull( - bufp, PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_LEAF_BYTES); - *leaf_idx &= (~(uint32_t)0) >> (32 - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_LEAF_BITS); + *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); + *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/hash_harakax4.c b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/hash_harakax4.c index 7a289dcf8a..cfa5162d79 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/hash_harakax4.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/hash_harakax4.c @@ -2,36 +2,34 @@ #include #include "address.h" -#include "haraka.h" -#include "hash_state.h" +#include "harakax4.h" #include "hashx4.h" #include "params.h" /* * 4-way parallel version of prf_addr; takes 4x as much input and output */ -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_prf_addrx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const unsigned char *key, - const uint32_t addrx4[4 * 8], - const hash_state *state_seeded) { - unsigned char bufx4[4 * PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_ADDR_BYTES]; - /* Since PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N may be smaller than 32, we need a temporary buffer. */ +#define prf_addrx4 SPX_NAMESPACE(prf_addrx4) +void prf_addrx4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const spx_ctx *ctx, + const uint32_t addrx4[4 * 8]) { + unsigned char bufx4[4 * 64] = {0}; + /* Since SPX_N may be smaller than 32, we need temporary buffers. */ unsigned char outbuf[4 * 32]; unsigned int i; - (void)key; /* Suppress an 'unused parameter' warning. */ - for (i = 0; i < 4; i++) { - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_addr_to_bytes(bufx4 + i * PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_ADDR_BYTES, addrx4 + i * 8); + memcpy(bufx4 + i * 64, addrx4 + i * 8, SPX_ADDR_BYTES); + memcpy(bufx4 + i * 64 + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); } - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_haraka256_skx4(outbuf, bufx4, state_seeded); + haraka512x4(outbuf, bufx4, ctx); - memcpy(out0, outbuf, PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N); - memcpy(out1, outbuf + 32, PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N); - memcpy(out2, outbuf + 64, PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N); - memcpy(out3, outbuf + 96, PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N); + memcpy(out0, outbuf, SPX_N); + memcpy(out1, outbuf + 32, SPX_N); + memcpy(out2, outbuf + 64, SPX_N); + memcpy(out3, outbuf + 96, SPX_N); } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/hash_state.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/hash_state.h deleted file mode 100644 index db7b3e5ba8..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/hash_state.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_HASH_STATE_H -#define PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_HASH_STATE_H - -/** - * Defines the type of the hash function state. - * - * Don't be fooled into thinking this instance of SPHINCS+ isn't stateless! - * - * From Section 7.2.2 from the SPHINCS+ round-2 specification: - * - * Each of the instances of the tweakable hash function take PK.seed as its - * first input, which is constant for a given key pair – and, thus, across - * a single signature. This leads to a lot of redundant computation. To remedy - * this, we pad PK.seed to the length of a full 64-byte SHA-256 input block. - * Because of the Merkle-DamgÃ¥rd construction that underlies SHA-256, this - * allows for reuse of the intermediate SHA-256 state after the initial call to - * the compression function which improves performance. - * - * We pass this hash state around in functions, because otherwise we need to - * have a global variable. - */ - -#include "haraka.h" -#define hash_state harakactx - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/hashx4.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/hashx4.h index 7e381cd317..3751a0ebd0 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/hashx4.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/hashx4.h @@ -1,16 +1,17 @@ -#ifndef PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_HASHX4_H -#define PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_HASHX4_H +#ifndef SPX_HASHX4_H +#define SPX_HASHX4_H #include -#include "hash_state.h" +#include "context.h" +#include "params.h" -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_prf_addrx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const unsigned char *key, - const uint32_t addrx4[4 * 8], - const hash_state *state_seeded); +#define prf_addrx4 SPX_NAMESPACE(prf_addrx4) +void prf_addrx4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const spx_ctx *ctx, + const uint32_t addrx4[4 * 8]); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/merkle.c b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/merkle.c new file mode 100644 index 0000000000..f57811c1ac --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/merkle.c @@ -0,0 +1,64 @@ +#include +#include + +#include "merkle.h" + +#include "address.h" +#include "params.h" +#include "utils.h" +#include "utilsx4.h" +#include "wots.h" +#include "wotsx4.h" + +/* + * This generates a Merkle signature (WOTS signature followed by the Merkle + * authentication path). + */ +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf) { + unsigned char *auth_path = sig + SPX_WOTS_BYTES; + uint32_t tree_addrx4[4 * 8] = { 0 }; + int j; + struct leaf_info_x4 info = { 0 }; + unsigned steps[ SPX_WOTS_LEN ]; + + info.wots_sig = sig; + chain_lengths(steps, root); + info.wots_steps = steps; + + for (j = 0; j < 4; j++) { + set_type(&tree_addrx4[8 * j], SPX_ADDR_TYPE_HASHTREE); + set_type(&info.leaf_addr[8 * j], SPX_ADDR_TYPE_WOTS); + set_type(&info.pk_addr[8 * j], SPX_ADDR_TYPE_WOTSPK); + copy_subtree_addr(&tree_addrx4[8 * j], tree_addr); + copy_subtree_addr(&info.leaf_addr[8 * j], wots_addr); + copy_subtree_addr(&info.pk_addr[8 * j], wots_addr); + } + + info.wots_sign_leaf = idx_leaf; + + treehashx4(root, auth_path, ctx, + idx_leaf, 0, + SPX_TREE_HEIGHT, + wots_gen_leafx4, + tree_addrx4, &info); +} + +/* Compute root node of the top-most subtree. */ +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { + /* We do not need the auth path in key generation, but it simplifies the + code to have just one treehash routine that computes both root and path + in one function. */ + unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; + uint32_t top_tree_addr[8] = {0}; + uint32_t wots_addr[8] = {0}; + + set_layer_addr(top_tree_addr, SPX_D - 1); + set_layer_addr(wots_addr, SPX_D - 1); + + merkle_sign(auth_path, root, ctx, + wots_addr, top_tree_addr, + ~0U /* ~0 means "don't bother generating an auth path */ ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/merkle.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/merkle.h new file mode 100644 index 0000000000..769cf2e970 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/merkle.h @@ -0,0 +1,21 @@ +#ifndef MERKLE_H_ +#define MERKLE_H_ + +#include + +#include "context.h" +#include "params.h" + +/* Generate a Merkle signature (WOTS signature followed by the Merkle */ +/* authentication path) */ +#define merkle_sign SPX_NAMESPACE(merkle_sign) +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf); + +/* Compute the root node of the top-most subtree. */ +#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); + +#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/nistapi.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/nistapi.h new file mode 100644 index 0000000000..3cb71afad4 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/nistapi.h @@ -0,0 +1,87 @@ +#ifndef SPX_API_H +#define SPX_API_H + +#include +#include + +#include "params.h" + +#define CRYPTO_ALGNAME "SPHINCS+" + +#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES +#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES +#define CRYPTO_BYTES SPX_BYTES +#define CRYPTO_SEEDBYTES (3*SPX_N) + +/* + * Returns the length of a secret key, in bytes + */ +#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) +size_t crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) +size_t crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) +size_t crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) +size_t crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +#define crypto_sign SPX_NAMESPACE(crypto_sign) +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/params.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/params.h index cfea7f491c..f6cad0d391 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/params.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/params.h @@ -1,53 +1,56 @@ -#ifndef PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_PARAMS_H -#define PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_PARAMS_H +#ifndef SPX_PARAMS_H +#define SPX_PARAMS_H + +#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_##s /* Hash output length in bytes. */ -#define PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N 24 +#define SPX_N 24 /* Height of the hypertree. */ -#define PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_FULL_HEIGHT 63 +#define SPX_FULL_HEIGHT 63 /* Number of subtree layer. */ -#define PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_D 7 +#define SPX_D 7 /* FORS tree dimensions. */ -#define PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_FORS_HEIGHT 14 -#define PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_FORS_TREES 17 +#define SPX_FORS_HEIGHT 14 +#define SPX_FORS_TREES 17 /* Winternitz parameter, */ -#define PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_WOTS_W 16 +#define SPX_WOTS_W 16 /* The hash function is defined by linking a different hash.c file, as opposed to setting a #define constant. */ /* For clarity */ -#define PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_ADDR_BYTES 32 +#define SPX_ADDR_BYTES 32 /* WOTS parameters. */ -#define PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_WOTS_LOGW 4 +#define SPX_WOTS_LOGW 4 -#define PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_WOTS_LEN1 (8 * PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N / PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_WOTS_LOGW) +#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) -/* PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#define PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_WOTS_LEN2 3 +/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ +#define SPX_WOTS_LEN2 3 -#define PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_WOTS_LEN (PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_WOTS_LEN1 + PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_WOTS_LEN2) -#define PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_WOTS_BYTES (PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_WOTS_LEN * PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N) -#define PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_WOTS_PK_BYTES PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_WOTS_BYTES +#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) +#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) +#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES /* Subtree size. */ -#define PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_TREE_HEIGHT (PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_FULL_HEIGHT / PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_D) +#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) + +//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT +// #error SPX_D should always divide SPX_FULL_HEIGHT +//#endif /* FORS parameters. */ -#define PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_FORS_MSG_BYTES ((PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_FORS_TREES + 7) / 8) -#define PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_FORS_BYTES ((PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_FORS_HEIGHT + 1) * PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_FORS_TREES * PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N) -#define PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_FORS_PK_BYTES PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N +#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) +#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) +#define SPX_FORS_PK_BYTES SPX_N /* Resulting SPX sizes. */ -#define PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_BYTES (PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N + PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_FORS_BYTES + PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_D * PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_WOTS_BYTES +\ - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_FULL_HEIGHT * PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N) -#define PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_PK_BYTES (2 * PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N) -#define PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_SK_BYTES (2 * PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N + PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_PK_BYTES) - -/* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ -#define PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_OPTRAND_BYTES 32 +#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ + SPX_FULL_HEIGHT * SPX_N) +#define SPX_PK_BYTES (2 * SPX_N) +#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) + +#include "haraka_offsets.h" #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/sign.c b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/sign.c index 6a274b42b1..9d0c7d1b22 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/sign.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/sign.c @@ -1,76 +1,45 @@ -#include #include #include #include #include "address.h" -#include "api.h" +#include "context.h" #include "fors.h" #include "hash.h" -#include "hash_state.h" +#include "merkle.h" +#include "nistapi.h" #include "params.h" #include "randombytes.h" #include "thash.h" #include "utils.h" #include "wots.h" - -/** - * Computes the leaf at a given address. First generates the WOTS key pair, - * then computes leaf by hashing horizontally. - */ -static void wots_gen_leaf(unsigned char *leaf, const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx, const uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - unsigned char pk[PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_WOTS_BYTES]; - uint32_t wots_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_set_type( - wots_addr, PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_set_type( - wots_pk_addr, PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_ADDR_TYPE_WOTSPK); - - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_set_keypair_addr( - wots_addr, addr_idx); - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_wots_gen_pk( - pk, sk_seed, pub_seed, wots_addr, hash_state_seeded); - - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_copy_keypair_addr( - wots_pk_addr, wots_addr); - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_thash_WOTS_LEN( - leaf, pk, pub_seed, wots_pk_addr, hash_state_seeded); -} - /* * Returns the length of a secret key, in bytes */ -size_t PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_crypto_sign_secretkeybytes(void) { - return PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_CRYPTO_SECRETKEYBYTES; +size_t crypto_sign_secretkeybytes(void) { + return CRYPTO_SECRETKEYBYTES; } /* * Returns the length of a public key, in bytes */ -size_t PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_crypto_sign_publickeybytes(void) { - return PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_CRYPTO_PUBLICKEYBYTES; +size_t crypto_sign_publickeybytes(void) { + return CRYPTO_PUBLICKEYBYTES; } /* * Returns the length of a signature, in bytes */ -size_t PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_crypto_sign_bytes(void) { - return PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_CRYPTO_BYTES; +size_t crypto_sign_bytes(void) { + return CRYPTO_BYTES; } /* * Returns the length of the seed required to generate a key pair, in bytes */ -size_t PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_crypto_sign_seedbytes(void) { - return PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_CRYPTO_SEEDBYTES; +size_t crypto_sign_seedbytes(void) { + return CRYPTO_SEEDBYTES; } /* @@ -78,35 +47,29 @@ size_t PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_crypto_sign_seedbytes(void) { * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] * Format pk: [PUB_SEED || root] */ -int PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed) { - /* We do not need the auth path in key generation, but it simplifies the - code to have just one treehash routine that computes both root and path - in one function. */ - unsigned char auth_path[PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_TREE_HEIGHT * PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N]; - uint32_t top_tree_addr[8] = {0}; - hash_state hash_state_seeded; - - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_set_layer_addr( - top_tree_addr, PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_D - 1); - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_set_type( - top_tree_addr, PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_ADDR_TYPE_HASHTREE); +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed) { + spx_ctx ctx; /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ - memcpy(sk, seed, PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_CRYPTO_SEEDBYTES); + memcpy(sk, seed, CRYPTO_SEEDBYTES); + + memcpy(pk, sk + 2 * SPX_N, SPX_N); - memcpy(pk, sk + 2 * PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N, PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N); + memcpy(ctx.pub_seed, pk, SPX_N); + memcpy(ctx.sk_seed, sk, SPX_N); /* This hook allows the hash function instantiation to do whatever preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_initialize_hash_function(&hash_state_seeded, pk, sk); + initialize_hash_function(&ctx); /* Compute root node of the top-most subtree. */ - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_treehash_TREE_HEIGHT( - sk + 3 * PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N, auth_path, sk, sk + 2 * PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N, 0, 0, - wots_gen_leaf, top_tree_addr, &hash_state_seeded); + merkle_gen_root(sk + 3 * SPX_N, &ctx); - memcpy(pk + PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N, sk + 3 * PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N, PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N); + // cleanup + free_hash_function(&ctx); + + memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); return 0; } @@ -116,31 +79,10 @@ int PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_crypto_sign_seed_keypair( * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] * Format pk: [PUB_SEED || root] */ -int PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk) { - - // guarantee alignment of pk - union { - __m128 _x[PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_CRYPTO_PUBLICKEYBYTES / 16]; - uint8_t pk[PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_CRYPTO_PUBLICKEYBYTES]; - } aligned_pk; - - // guarantee alignment of sk - union { - __m128 _x[PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_CRYPTO_SECRETKEYBYTES / 16]; - uint8_t sk[PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_CRYPTO_SECRETKEYBYTES]; - } aligned_sk; - - union { - __m128 _x[PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_CRYPTO_SEEDBYTES / 16]; - uint8_t seed[PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_CRYPTO_SEEDBYTES]; - } aligned_seed; - randombytes(aligned_seed.seed, PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_CRYPTO_SEEDBYTES); - - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_crypto_sign_seed_keypair( - aligned_pk.pk, aligned_sk.sk, aligned_seed.seed); - memcpy(pk, aligned_pk.pk, PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_CRYPTO_PUBLICKEYBYTES); - memcpy(sk, aligned_sk.sk, PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_CRYPTO_SECRETKEYBYTES); +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { + uint8_t seed[CRYPTO_SEEDBYTES]; + randombytes(seed, CRYPTO_SEEDBYTES); + crypto_sign_seed_keypair(pk, sk, seed); return 0; } @@ -148,101 +90,68 @@ int PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_crypto_sign_keypair( /** * Returns an array containing a detached signature. */ -int PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - // guarantee alignment of sk - union { - __m128 *_x; - uint8_t sk[PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_CRYPTO_SECRETKEYBYTES]; - } aligned_sk; - memcpy(aligned_sk.sk, sk, PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_CRYPTO_SECRETKEYBYTES); - sk = aligned_sk.sk; - - // guarantee alignment of sig - union { - __m128 *_x; - uint8_t sig[PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_BYTES]; - } aligned_sig; - uint8_t *orig_sig = sig; - sig = (uint8_t *)aligned_sig.sig; - - const unsigned char *sk_seed = sk; - const unsigned char *sk_prf = sk + PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N; - const unsigned char *pk = sk + 2 * PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N; - const unsigned char *pub_seed = pk; - - unsigned char optrand[PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N]; - unsigned char mhash[PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_FORS_MSG_BYTES]; - unsigned char root[PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N]; +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk) { + spx_ctx ctx; + + const uint8_t *sk_prf = sk + SPX_N; + const uint8_t *pk = sk + 2 * SPX_N; + + uint8_t optrand[SPX_N]; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t root[SPX_N]; uint32_t i; uint64_t tree; uint32_t idx_leaf; uint32_t wots_addr[8] = {0}; uint32_t tree_addr[8] = {0}; - hash_state hash_state_seeded; + memcpy(ctx.sk_seed, sk, SPX_N); + memcpy(ctx.pub_seed, pk, SPX_N); /* This hook allows the hash function instantiation to do whatever preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_initialize_hash_function( - &hash_state_seeded, - pub_seed, sk_seed); + initialize_hash_function(&ctx); - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_set_type( - wots_addr, PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_set_type( - tree_addr, PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_ADDR_TYPE_HASHTREE); + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); /* Optionally, signing can be made non-deterministic using optrand. This can help counter side-channel attacks that would benefit from getting a large number of traces when the signer uses the same nodes. */ - randombytes(optrand, PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N); + randombytes(optrand, SPX_N); /* Compute the digest randomization value. */ - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_gen_message_random( - sig, sk_prf, optrand, m, mlen, &hash_state_seeded); + gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); /* Derive the message digest and leaf index from R, PK and M. */ - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N; + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_set_keypair_addr( - wots_addr, idx_leaf); + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); /* Sign the message hash using FORS. */ - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_fors_sign( - sig, root, mhash, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_FORS_BYTES; - - for (i = 0; i < PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_D; i++) { - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_set_tree_addr(tree_addr, tree); - - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_set_keypair_addr( - wots_addr, idx_leaf); - - /* Compute a WOTS signature. */ - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_wots_sign( - sig, root, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_WOTS_BYTES; - - /* Compute the authentication path for the used WOTS leaf. */ - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_treehash_TREE_HEIGHT( - root, sig, sk_seed, pub_seed, idx_leaf, 0, - wots_gen_leaf, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_TREE_HEIGHT * PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N; + fors_sign(sig, root, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); + sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_TREE_HEIGHT; + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; } - memcpy(orig_sig, aligned_sig.sig, PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_BYTES); - *siglen = PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_BYTES; + free_hash_function(&ctx); + + *siglen = SPX_BYTES; return 0; } @@ -250,23 +159,14 @@ int PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_crypto_sign_signature( /** * Verifies a detached signature and message under a given public key. */ -int PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk) { - // guarantee alignment of pk - union { - __m128 *_x; - uint8_t pk[PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_CRYPTO_PUBLICKEYBYTES]; - } aligned_pk; - memcpy(aligned_pk.pk, pk, PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_CRYPTO_PUBLICKEYBYTES); - pk = aligned_pk.pk; - - const unsigned char *pub_seed = pk; - const unsigned char *pub_root = pk + PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N; - unsigned char mhash[PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_FORS_MSG_BYTES]; - unsigned char wots_pk[PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_WOTS_BYTES]; - unsigned char root[PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N]; - unsigned char leaf[PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N]; +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk) { + spx_ctx ctx; + const uint8_t *pub_root = pk + SPX_N; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t wots_pk[SPX_WOTS_BYTES]; + uint8_t root[SPX_N]; + uint8_t leaf[SPX_N]; unsigned int i; uint64_t tree; uint32_t idx_leaf; @@ -274,77 +174,66 @@ int PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_crypto_sign_verify( uint32_t tree_addr[8] = {0}; uint32_t wots_pk_addr[8] = {0}; - hash_state hash_state_seeded; - - if (siglen != PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_BYTES) { + if (siglen != SPX_BYTES) { return -1; } + memcpy(ctx.pub_seed, pk, SPX_N); + /* This hook allows the hash function instantiation to do whatever preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_initialize_hash_function( - &hash_state_seeded, - pub_seed, NULL); + initialize_hash_function(&ctx); - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_set_type( - wots_addr, PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_set_type( - tree_addr, PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_ADDR_TYPE_HASHTREE); - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_set_type( - wots_pk_addr, PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_ADDR_TYPE_WOTSPK); + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); /* Derive the message digest and leaf index from R || PK || M. */ - /* The additional PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N is a result of the hash domain separator. */ - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N; + /* The additional SPX_N is a result of the hash domain separator. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; /* Layer correctly defaults to 0, so no need to set_layer_addr */ - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_set_keypair_addr( - wots_addr, idx_leaf); + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_fors_pk_from_sig( - root, sig, mhash, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_FORS_BYTES; + fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; /* For each subtree.. */ - for (i = 0; i < PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_D; i++) { - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_set_tree_addr(tree_addr, tree); + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_set_keypair_addr( - wots_addr, idx_leaf); + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_copy_keypair_addr( - wots_pk_addr, wots_addr); + copy_keypair_addr(wots_pk_addr, wots_addr); /* The WOTS public key is only correct if the signature was correct. */ /* Initially, root is the FORS pk, but on subsequent iterations it is the root of the subtree below the currently processed subtree. */ - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_wots_pk_from_sig( - wots_pk, sig, root, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_WOTS_BYTES; + wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); + sig += SPX_WOTS_BYTES; /* Compute the leaf node using the WOTS public key. */ - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_thash_WOTS_LEN( - leaf, wots_pk, pub_seed, wots_pk_addr, &hash_state_seeded); + thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); /* Compute the root node of this subtree. */ - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_compute_root( - root, leaf, idx_leaf, 0, sig, PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_TREE_HEIGHT, - pub_seed, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_TREE_HEIGHT * PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N; + compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, + &ctx, tree_addr); + sig += SPX_TREE_HEIGHT * SPX_N; /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_TREE_HEIGHT; + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; } + // cleanup + free_hash_function(&ctx); + /* Check if the root node equals the root node in the public key. */ - if (memcmp(root, pub_root, PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N) != 0) { + if (memcmp(root, pub_root, SPX_N) != 0) { return -1; } @@ -355,15 +244,14 @@ int PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_crypto_sign_verify( /** * Returns an array containing the signature followed by the message. */ -int PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk) { size_t siglen; - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_crypto_sign_signature( - sm, &siglen, m, mlen, sk); + crypto_sign_signature(sm, &siglen, m, mlen, sk); - memmove(sm + PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_BYTES, m, mlen); + memmove(sm + SPX_BYTES, m, mlen); *smlen = siglen + mlen; return 0; @@ -372,38 +260,27 @@ int PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_crypto_sign( /** * Verifies a given signature-message pair under a given public key. */ -int PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk) { - - // guarantee alignment of pk - union { - __m128 *_x; - uint8_t pk[PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_CRYPTO_PUBLICKEYBYTES]; - } aligned_pk; - memcpy(aligned_pk.pk, pk, PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_CRYPTO_PUBLICKEYBYTES); - pk = aligned_pk.pk; - - +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk) { /* The API caller does not necessarily know what size a signature should be - but SPHINCS+ signatures are always exactly PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_BYTES. */ - if (smlen < PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_BYTES) { + but SPHINCS+ signatures are always exactly SPX_BYTES. */ + if (smlen < SPX_BYTES) { memset(m, 0, smlen); *mlen = 0; return -1; } - *mlen = smlen - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_BYTES; + *mlen = smlen - SPX_BYTES; - if (PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_crypto_sign_verify( - sm, PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_BYTES, sm + PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_BYTES, *mlen, pk)) { + if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { memset(m, 0, smlen); *mlen = 0; return -1; } /* If verification was successful, move the message to the right place. */ - memmove(m, sm + PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_BYTES, *mlen); + memmove(m, sm + SPX_BYTES, *mlen); return 0; } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/thash.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/thash.h index d1068ee574..8687ccfb4d 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/thash.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/thash.h @@ -1,28 +1,13 @@ -#ifndef PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_THASH_H -#define PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_THASH_H +#ifndef SPX_THASH_H +#define SPX_THASH_H -#include "hash_state.h" +#include "context.h" +#include "params.h" #include -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); +#define thash SPX_NAMESPACE(thash) +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/thash_haraka_simple.c b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/thash_haraka_simple.c index 99c6c4d132..207777bf8d 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/thash_haraka_simple.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/thash_haraka_simple.c @@ -4,80 +4,33 @@ #include "address.h" #include "params.h" #include "thash.h" +#include "utils.h" #include "haraka.h" /** - * Takes an array of inblocks concatenated arrays of PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N bytes. + * Takes an array of inblocks concatenated arrays of SPX_N bytes. */ -static void PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_thash( - unsigned char *out, unsigned char *buf, - const unsigned char *in, unsigned int inblocks, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]) { + PQCLEAN_VLA(uint8_t, buf, SPX_ADDR_BYTES + inblocks * SPX_N); unsigned char outbuf[32]; unsigned char buf_tmp[64]; - (void)pub_seed; /* Suppress an 'unused parameter' warning. */ - if (inblocks == 1) { /* F function */ - /* Since PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N may be smaller than 32, we need a temporary buffer. */ + /* Since SPX_N may be smaller than 32, we need a temporary buffer. */ memset(buf_tmp, 0, 64); - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_addr_to_bytes(buf_tmp, addr); - memcpy(buf_tmp + PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_ADDR_BYTES, in, PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N); + memcpy(buf_tmp, addr, 32); + memcpy(buf_tmp + SPX_ADDR_BYTES, in, SPX_N); - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_haraka512(outbuf, buf_tmp, hash_state_seeded); - memcpy(out, outbuf, PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N); + haraka512(outbuf, buf_tmp, ctx); + memcpy(out, outbuf, SPX_N); } else { /* All other tweakable hashes*/ - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_addr_to_bytes(buf, addr); - memcpy(buf + PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_ADDR_BYTES, in, inblocks * PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N); + memcpy(buf, addr, 32); + memcpy(buf + SPX_ADDR_BYTES, in, inblocks * SPX_N); - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_haraka_S( - out, PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N, buf, PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N, hash_state_seeded); + haraka_S(out, SPX_N, buf, SPX_ADDR_BYTES + inblocks * SPX_N, ctx); } } - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_ADDR_BYTES + 1 * PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N]; - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_thash( - out, buf, in, 1, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_ADDR_BYTES + 2 * PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N]; - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_thash( - out, buf, in, 2, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_ADDR_BYTES + PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_WOTS_LEN * PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N]; - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_thash( - out, buf, in, PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_WOTS_LEN, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_ADDR_BYTES + PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_FORS_TREES * PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N]; - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_thash( - out, buf, in, PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_FORS_TREES, pub_seed, addr, hash_state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/thash_haraka_simplex4.c b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/thash_haraka_simplex4.c index cd3a89cce1..2ee763d7d9 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/thash_haraka_simplex4.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/thash_haraka_simplex4.c @@ -2,65 +2,66 @@ #include #include "address.h" -#include "haraka.h" #include "params.h" #include "thashx4.h" +#include "harakax4.h" + +#include "utils.h" + /** * 4-way parallel version of thash; takes 4x as much input and output */ -#define thashx4_variant(name, inblocks) \ - void PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_thashx4_##name(unsigned char *out0, unsigned char *out1, unsigned char *out2, \ - unsigned char *out3, const unsigned char *in0, \ - const unsigned char *in1, const unsigned char *in2, \ - const unsigned char *in3, const unsigned char *pub_seed, \ - uint32_t addrx4[4 * 8], const harakactx *state) { \ - unsigned char buf0[PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_ADDR_BYTES + (inblocks)*PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N]; \ - unsigned char buf1[PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_ADDR_BYTES + (inblocks)*PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N]; \ - unsigned char buf2[PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_ADDR_BYTES + (inblocks)*PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N]; \ - unsigned char buf3[PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_ADDR_BYTES + (inblocks)*PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N]; \ - unsigned char outbuf[32 * 4]; \ - unsigned char buf_tmp[64 * 4]; \ - \ - (void)pub_seed; /* Suppress an 'unused parameter' warning. */ \ - \ - if ((inblocks) == 1) { \ - memset(buf_tmp, 0, 64 * 4); \ - \ - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_addr_to_bytes(buf_tmp, addrx4 + 0 * 8); \ - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_addr_to_bytes(buf_tmp + 64, addrx4 + 1 * 8); \ - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_addr_to_bytes(buf_tmp + 128, addrx4 + 2 * 8); \ - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_addr_to_bytes(buf_tmp + 192, addrx4 + 3 * 8); \ - \ - memcpy(buf_tmp + PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_ADDR_BYTES, in0, PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N); \ - memcpy(buf_tmp + PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_ADDR_BYTES + 64, in1, PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N); \ - memcpy(buf_tmp + PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_ADDR_BYTES + 128, in2, PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N); \ - memcpy(buf_tmp + PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_ADDR_BYTES + 192, in3, PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N); \ - \ - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_haraka512x4(outbuf, buf_tmp, state); \ - \ - memcpy(out0, outbuf, PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N); \ - memcpy(out1, outbuf + 32, PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N); \ - memcpy(out2, outbuf + 64, PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N); \ - memcpy(out3, outbuf + 96, PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N); \ - } else { \ - /* All other tweakable hashes*/ \ - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_addr_to_bytes(buf0, addrx4 + 0 * 8); \ - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_addr_to_bytes(buf1, addrx4 + 1 * 8); \ - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_addr_to_bytes(buf2, addrx4 + 2 * 8); \ - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_addr_to_bytes(buf3, addrx4 + 3 * 8); \ - \ - memcpy(buf0 + PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_ADDR_BYTES, in0, (inblocks)*PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N); \ - memcpy(buf1 + PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_ADDR_BYTES, in1, (inblocks)*PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N); \ - memcpy(buf2 + PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_ADDR_BYTES, in2, (inblocks)*PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N); \ - memcpy(buf3 + PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_ADDR_BYTES, in3, (inblocks)*PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N); \ - \ - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_haraka_Sx4(out0, out1, out2, out3, PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N, buf0, buf1, buf2, buf3, \ - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_ADDR_BYTES + (inblocks)*PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N, state); \ - } \ - } +#define thashx4 SPX_NAMESPACE(thashx4) +void thashx4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addrx4[4 * 8]) { + PQCLEAN_VLA(unsigned char, buf0, SPX_ADDR_BYTES + inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, buf1, SPX_ADDR_BYTES + inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, buf2, SPX_ADDR_BYTES + inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, buf3, SPX_ADDR_BYTES + inblocks * SPX_N); + unsigned char outbuf[32 * 4]; + unsigned char buf_tmp[64 * 4]; + + if (inblocks == 1) { + memset(buf_tmp, 0, 64 * 4); + + memcpy(buf_tmp, addrx4 + 0 * 8, 32); + memcpy(buf_tmp + 64, addrx4 + 1 * 8, 32); + memcpy(buf_tmp + 128, addrx4 + 2 * 8, 32); + memcpy(buf_tmp + 192, addrx4 + 3 * 8, 32); -thashx4_variant(1, 1) -thashx4_variant(2, 2) -thashx4_variant(WOTS_LEN, PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_WOTS_LEN) -thashx4_variant(FORS_TREES, PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_FORS_TREES) + memcpy(buf_tmp + SPX_ADDR_BYTES, in0, SPX_N); + memcpy(buf_tmp + SPX_ADDR_BYTES + 64, in1, SPX_N); + memcpy(buf_tmp + SPX_ADDR_BYTES + 128, in2, SPX_N); + memcpy(buf_tmp + SPX_ADDR_BYTES + 192, in3, SPX_N); + + haraka512x4(outbuf, buf_tmp, ctx); + + memcpy(out0, outbuf, SPX_N); + memcpy(out1, outbuf + 32, SPX_N); + memcpy(out2, outbuf + 64, SPX_N); + memcpy(out3, outbuf + 96, SPX_N); + } else { + /* All other tweakable hashes*/ + memcpy(buf0, addrx4 + 0 * 8, 32); + memcpy(buf1, addrx4 + 1 * 8, 32); + memcpy(buf2, addrx4 + 2 * 8, 32); + memcpy(buf3, addrx4 + 3 * 8, 32); + + memcpy(buf0 + SPX_ADDR_BYTES, in0, inblocks * SPX_N); + memcpy(buf1 + SPX_ADDR_BYTES, in1, inblocks * SPX_N); + memcpy(buf2 + SPX_ADDR_BYTES, in2, inblocks * SPX_N); + memcpy(buf3 + SPX_ADDR_BYTES, in3, inblocks * SPX_N); + + haraka_Sx4(out0, out1, out2, out3, SPX_N, + buf0, buf1, buf2, buf3, SPX_ADDR_BYTES + inblocks * SPX_N, + ctx); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/thashx4.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/thashx4.h index 780d967ed4..64798a3727 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/thashx4.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/thashx4.h @@ -1,25 +1,20 @@ -#ifndef PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_THASHX4_H -#define PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_THASHX4_H +#ifndef SPX_THASHX4_H +#define SPX_THASHX4_H #include -#include "hash_state.h" +#include "context.h" +#include "params.h" -#define thashx4_header(inblocks) \ - void PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_thashx4_##inblocks(unsigned char *out0, \ - unsigned char *out1, \ - unsigned char *out2, \ - unsigned char *out3, \ - const unsigned char *in0, \ - const unsigned char *in1, \ - const unsigned char *in2, \ - const unsigned char *in3, \ - const unsigned char *pub_seed, uint32_t addrx4[4*8], \ - const hash_state *state_seeded) - -thashx4_header(1); -thashx4_header(2); -thashx4_header(WOTS_LEN); -thashx4_header(FORS_TREES); +#define thashx4 SPX_NAMESPACE(thashx4) +void thashx4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addrx4[4 * 8]); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/utils.c b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/utils.c index a082354188..177b541fb9 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/utils.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/utils.c @@ -1,34 +1,41 @@ -#include #include +#include "utils.h" + #include "address.h" #include "hash.h" -#include "hash_state.h" #include "params.h" #include "thash.h" -#include "utils.h" /** * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. */ -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in) { +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in) { + int i; /* Iterate over out in decreasing order, for big-endianness. */ - for (size_t i = outlen; i > 0; i--) { - out[i - 1] = in & 0xff; + for (i = (signed int)outlen - 1; i >= 0; i--) { + out[i] = in & 0xff; in = in >> 8; } } +void u32_to_bytes(unsigned char *out, uint32_t in) { + out[0] = (unsigned char)(in >> 24); + out[1] = (unsigned char)(in >> 16); + out[2] = (unsigned char)(in >> 8); + out[3] = (unsigned char)in; +} + /** * Converts the inlen bytes in 'in' from big-endian byte order to an integer. */ -unsigned long long PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_bytes_to_ull( - const unsigned char *in, size_t inlen) { +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { unsigned long long retval = 0; + unsigned int i; - for (size_t i = 0; i < inlen; i++) { + for (i = 0; i < inlen; i++) { retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); } return retval; @@ -38,94 +45,80 @@ unsigned long long PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_bytes_to_ull( * Computes a root node given a leaf and an auth path. * Expects address to be complete other than the tree_height and tree_index. */ -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]) { uint32_t i; - unsigned char buffer[2 * PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N]; + unsigned char buffer[2 * SPX_N]; /* If leaf_idx is odd (last bit = 1), current path element is a right child and auth_path has to go left. Otherwise it is the other way around. */ if (leaf_idx & 1) { - memcpy(buffer + PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N, leaf, PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N); + memcpy(buffer + SPX_N, leaf, SPX_N); + memcpy(buffer, auth_path, SPX_N); } else { - memcpy(buffer, leaf, PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N); - memcpy(buffer + PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N, auth_path, PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N); + memcpy(buffer, leaf, SPX_N); + memcpy(buffer + SPX_N, auth_path, SPX_N); } - auth_path += PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N; + auth_path += SPX_N; for (i = 0; i < tree_height - 1; i++) { leaf_idx >>= 1; idx_offset >>= 1; /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_set_tree_height(addr, i + 1); - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_set_tree_index( - addr, leaf_idx + idx_offset); + set_tree_height(addr, i + 1); + set_tree_index(addr, leaf_idx + idx_offset); /* Pick the right or left neighbor, depending on parity of the node. */ if (leaf_idx & 1) { - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_thash_2( - buffer + PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N); + thash(buffer + SPX_N, buffer, 2, ctx, addr); + memcpy(buffer, auth_path, SPX_N); } else { - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_thash_2( - buffer, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer + PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N, auth_path, PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N); + thash(buffer, buffer, 2, ctx, addr); + memcpy(buffer + SPX_N, auth_path, SPX_N); } - auth_path += PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N; + auth_path += SPX_N; } /* The last iteration is exceptional; we do not copy an auth_path node. */ leaf_idx >>= 1; idx_offset >>= 1; - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_set_tree_height(addr, tree_height); - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_set_tree_index( - addr, leaf_idx + idx_offset); - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_thash_2( - root, buffer, pub_seed, addr, hash_state_seeded); + set_tree_height(addr, tree_height); + set_tree_index(addr, leaf_idx + idx_offset); + thash(root, buffer, 2, ctx, addr); } /** * For a given leaf index, computes the authentication path and the resulting * root node using Merkle's TreeHash algorithm. * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_ADDR_TYPE_FORSTREE). + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). * Applies the offset idx_offset to indices before building addresses, so that * it is possible to continue counting indices across trees. */ -static void PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_treehash( - unsigned char *root, unsigned char *auth_path, - unsigned char *stack, unsigned int *heights, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - +void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx * /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]) { + PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); + PQCLEAN_VLA(unsigned int, heights, tree_height + 1); unsigned int offset = 0; uint32_t idx; uint32_t tree_idx; for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { /* Add the next leaf node to the stack. */ - gen_leaf(stack + offset * PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N, - sk_seed, pub_seed, idx + idx_offset, tree_addr, - hash_state_seeded); + gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); offset++; heights[offset - 1] = 0; /* If this is a node we need for the auth path.. */ if ((leaf_idx ^ 0x1) == idx) { - memcpy(auth_path, stack + (offset - 1)*PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N, PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N); + memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); } /* While the top-most nodes are of equal height.. */ @@ -134,66 +127,22 @@ static void PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_treehash( tree_idx = (idx >> (heights[offset - 1] + 1)); /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_set_tree_height( - tree_addr, heights[offset - 1] + 1); - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_set_tree_index( - tree_addr, tree_idx + (idx_offset >> (heights[offset - 1] + 1))); + set_tree_height(tree_addr, heights[offset - 1] + 1); + set_tree_index(tree_addr, + tree_idx + (idx_offset >> (heights[offset - 1] + 1))); /* Hash the top-most nodes from the stack together. */ - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_thash_2( - stack + (offset - 2)*PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N, stack + (offset - 2)*PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N, - pub_seed, tree_addr, hash_state_seeded); + thash(stack + (offset - 2)*SPX_N, + stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); offset--; /* Note that the top-most node is now one layer higher. */ heights[offset - 1]++; /* If this is a node we need for the auth path.. */ if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_path + heights[offset - 1]*PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N, - stack + (offset - 1)*PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N, PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N); + memcpy(auth_path + heights[offset - 1]*SPX_N, + stack + (offset - 1)*SPX_N, SPX_N); } } } - memcpy(root, stack, PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N); -} - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_FORS_HEIGHT + 1)*PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N]; - unsigned int heights[PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_FORS_HEIGHT + 1]; - - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_FORS_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_TREE_HEIGHT + 1)*PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N]; - unsigned int heights[PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_TREE_HEIGHT + 1]; - - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_TREE_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); + memcpy(root, stack, SPX_N); } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/utils.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/utils.h index 9ea1872f20..64f5d5a53a 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/utils.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/utils.h @@ -1,64 +1,58 @@ -#ifndef PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_UTILS_H -#define PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_UTILS_H +#ifndef SPX_UTILS_H +#define SPX_UTILS_H -#include "hash_state.h" -#include "params.h" -#include #include +#include "compat.h" +#include "context.h" +#include "params.h" + + +/* To support MSVC use alloca() instead of VLAs. See #20. */ + + /** * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. */ -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in); +#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in); +#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) +void u32_to_bytes(unsigned char *out, uint32_t in); /** * Converts the inlen bytes in 'in' from big-endian byte order to an integer. */ -unsigned long long PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_bytes_to_ull( - const unsigned char *in, size_t inlen); +#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); /** * Computes a root node given a leaf and an auth path. * Expects address to be complete other than the tree_height and tree_index. */ -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); +#define compute_root SPX_NAMESPACE(compute_root) +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]); /** * For a given leaf index, computes the authentication path and the resulting * root node using Merkle's TreeHash algorithm. * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_ADDR_TYPE_FORSTREE). + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). * Applies the offset idx_offset to indices before building addresses, so that * it is possible to continue counting indices across trees. */ -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); +#define treehash SPX_NAMESPACE(treehash) +void treehash(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx *ctx /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]); -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/utilsx4.c b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/utilsx4.c index e05e35cbb8..1638677194 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/utilsx4.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/utilsx4.c @@ -1,98 +1,138 @@ +#include + +#include "utilsx4.h" + #include "address.h" #include "params.h" #include "thashx4.h" #include "utils.h" -#include "utilsx4.h" -#include - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. +/* + * Generate the entire Merkle tree, computing the authentication path for leaf_idx, + * and the resulting root node using Merkle's TreeHash algorithm. * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_ADDR_TYPE_FORSTREE). + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) + * + * This expects tree_addrx4 to be initialized to 4 parallel addr structures for + * the Merkle tree nodes + * * Applies the offset idx_offset to indices before building addresses, so that * it is possible to continue counting indices across trees. + * + * This works by using the standard Merkle tree building algorithm, except + * that each 'node' tracked is actually 4 consecutive nodes in the real tree. + * When we combine two logical nodes ABCD and WXYZ, we perform the H + * operation on adjacent real nodes, forming the parent logical node + * (AB)(CD)(WX)(YZ) + * + * When we get to the top two levels of the real tree (where there is only + * one logical node), we continue this operation two more times; the right + * most real node will by the actual root (and the other 3 nodes will be + * garbage). We follow the same thashx4 logic so that the 'extract + * authentication path components' part of the loop is still executed (and + * to simplify the code somewhat) + * + * This currently assumes tree_height >= 2; I suspect that doing an adjusting + * idx, addr_idx on the gen_leafx4 call if tree_height < 2 would fix it; since + * we don't actually use such short trees, I haven't bothered */ -#define treehashx4_variant(name, tree_height) \ - void PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_treehashx4_##name( \ - unsigned char *rootx4, unsigned char *auth_pathx4, const unsigned char *sk_seed, \ - const unsigned char *pub_seed, const uint32_t leaf_idx[4], uint32_t idx_offset[4], \ - void (*gen_leafx4)(unsigned char * /* leaf0 */, unsigned char * /* leaf1 */, \ - unsigned char * /* leaf2 */, unsigned char * /* leaf3 */, \ - const unsigned char * /* sk_seed */, \ - const unsigned char * /* pub_seed */, uint32_t /* addr_idx0 */, \ - uint32_t /* addr_idx1 */, uint32_t /* addr_idx2 */, \ - uint32_t /* addr_idx3 */, const uint32_t[8] /* tree_addr */, \ - const hash_state * /* state_seeded */), \ - uint32_t tree_addrx4[4 * 8], const hash_state *state_seeded) { \ - unsigned char stackx4[4 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N]; \ - unsigned int heights[(tree_height) + 1]; \ - unsigned int offset = 0; \ - uint32_t idx; \ - uint32_t tree_idx; \ - unsigned int j; \ - \ - for (idx = 0; idx < (uint32_t)(1 << (tree_height)); idx++) { \ - /* Add the next leaf node to the stack. */ \ - gen_leafx4(stackx4 + 0 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N + offset * PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N, \ - stackx4 + 1 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N + offset * PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N, \ - stackx4 + 2 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N + offset * PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N, \ - stackx4 + 3 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N + offset * PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N, sk_seed, \ - pub_seed, idx + idx_offset[0], idx + idx_offset[1], idx + idx_offset[2], \ - idx + idx_offset[3], tree_addrx4, state_seeded); \ - offset++; \ - heights[offset - 1] = 0; \ - \ - /* If this is a node we need for the auth path.. */ \ - for (j = 0; j < 4; j++) { \ - if ((leaf_idx[j] ^ 0x1) == idx) { \ - memcpy(auth_pathx4 + j * (tree_height)*PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N, \ - stackx4 + j * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N + (offset - 1) * PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N, \ - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N); \ - } \ - } \ - \ - /* While the top-most nodes are of equal height.. */ \ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { \ - /* Compute index of the new node, in the next layer. */ \ - tree_idx = (idx >> (heights[offset - 1] + 1)); \ - \ - /* Set the address of the node we're creating. */ \ - for (j = 0; j < 4; j++) { \ - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_set_tree_height(tree_addrx4 + j * 8, heights[offset - 1] + 1); \ - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_set_tree_index(tree_addrx4 + j * 8, \ - tree_idx + (idx_offset[j] >> (heights[offset - 1] + 1))); \ - } \ - /* Hash the top-most nodes from the stack together. */ \ - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_thashx4_2(stackx4 + 0 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N + (offset - 2) * PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N, \ - stackx4 + 1 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N + (offset - 2) * PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N, \ - stackx4 + 2 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N + (offset - 2) * PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N, \ - stackx4 + 3 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N + (offset - 2) * PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N, \ - stackx4 + 0 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N + (offset - 2) * PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N, \ - stackx4 + 1 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N + (offset - 2) * PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N, \ - stackx4 + 2 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N + (offset - 2) * PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N, \ - stackx4 + 3 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N + (offset - 2) * PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N, \ - pub_seed, tree_addrx4, state_seeded); \ - offset--; \ - /* Note that the top-most node is now one layer higher. */ \ - heights[offset - 1]++; \ - \ - /* If this is a node we need for the auth path.. */ \ - for (j = 0; j < 4; j++) { \ - if (((leaf_idx[j] >> heights[offset - 1]) ^ 0x1) == tree_idx) { \ - memcpy(auth_pathx4 + j * (tree_height)*PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N + \ - heights[offset - 1] * PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N, \ - stackx4 + j * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N + (offset - 1) * PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N, \ - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N); \ - } \ - } \ - } \ - } \ - \ - for (j = 0; j < 4; j++) { \ - memcpy(rootx4 + j * PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N, stackx4 + j * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N, PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N); \ - } \ - } +void treehashx4(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, + uint32_t tree_height, + void (*gen_leafx4)( + unsigned char * /* Where to write the leaves */, + const spx_ctx *, + uint32_t idx, void *info), + uint32_t tree_addrx4[4 * 8], + void *info) { + /* This is where we keep the intermediate nodes */ + PQCLEAN_VLA(unsigned char, stackx4, tree_height * 4 * SPX_N); + uint32_t left_adj = 0, prev_left_adj = 0; /* When we're doing the top 3 */ + /* levels, the left-most part of the tree isn't at the beginning */ + /* of current[]. These give the offset of the actual start */ + + uint32_t idx; + uint32_t max_idx = (1U << (tree_height - 2)) - 1; + for (idx = 0;; idx++) { + unsigned char current[4 * SPX_N]; /* Current logical node */ + gen_leafx4( current, ctx, 4 * idx + idx_offset, + info ); -treehashx4_variant(FORS_HEIGHT, PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_FORS_HEIGHT) + /* Now combine the freshly generated right node with previously */ + /* generated left ones */ + uint32_t internal_idx_offset = idx_offset; + uint32_t internal_idx = idx; + uint32_t internal_leaf = leaf_idx; + uint32_t h; /* The height we are in the Merkle tree */ + for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { + + /* Special processing if we're at the top of the tree */ + if (h >= tree_height - 2) { + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[3 * SPX_N], SPX_N ); + return; + } + /* The tree indexing logic is a bit off in this case */ + /* Adjust it so that the left-most node of the part of */ + /* the tree that we're processing has index 0 */ + prev_left_adj = left_adj; + left_adj = 4U - (1 << (tree_height - h - 1)); + } + + /* Check if we hit the top of the tree */ + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[3 * SPX_N], SPX_N ); + return; + } + + /* + * Check if one of the nodes we have is a part of the + * authentication path; if it is, write it out + */ + if ((((internal_idx << 2) ^ internal_leaf) & ~0x3U) == 0) { + memcpy( &auth_path[ h * SPX_N ], + ¤t[(((internal_leaf & 3) ^ 1) + prev_left_adj) * SPX_N], + SPX_N ); + } + + /* + * Check if we're at a left child; if so, stop going up the stack + * Exception: if we've reached the end of the tree, keep on going + * (so we combine the last 4 nodes into the one root node in two + * more iterations) + */ + if ((internal_idx & 1) == 0 && idx < max_idx) { + break; + } + + /* Ok, we're at a right node (or doing the top 3 levels) */ + /* Now combine the left and right logical nodes together */ + + /* Set the address of the node we're creating. */ + unsigned int j; + internal_idx_offset >>= 1; + for (j = 0; j < 4; j++) { + set_tree_height(tree_addrx4 + j * 8, h + 1); + set_tree_index(tree_addrx4 + j * 8, + (4 / 2) * (internal_idx & ~1U) + j - left_adj + internal_idx_offset ); + } + unsigned char *left = &stackx4[h * 4 * SPX_N]; + thashx4( ¤t[0 * SPX_N], + ¤t[1 * SPX_N], + ¤t[2 * SPX_N], + ¤t[3 * SPX_N], + &left [0 * SPX_N], + &left [2 * SPX_N], + ¤t[0 * SPX_N], + ¤t[2 * SPX_N], + 2, ctx, tree_addrx4); + } + + /* We've hit a left child; save the current for when we get the */ + /* corresponding right right */ + memcpy( &stackx4[h * 4 * SPX_N], current, 4 * SPX_N); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/utilsx4.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/utilsx4.h index aa00c98d6d..facb874b18 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/utilsx4.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/utilsx4.h @@ -1,38 +1,30 @@ -#ifndef PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_UTILSX4_H -#define PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_UTILSX4_H - -#include "hash_state.h" -#include "params.h" +#ifndef SPX_UTILSX4_H +#define SPX_UTILSX4_H #include +#include "context.h" +#include "params.h" + /** * For a given leaf index, computes the authentication path and the resulting * root node using Merkle's TreeHash algorithm. * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_ADDR_TYPE_FORSTREE). + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). * Applies the offset idx_offset to indices before building addresses, so that * it is possible to continue counting indices across trees. + * + * This implementation uses AVX to compute internal nodes 4 at a time (in + * parallel) */ -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_treehashx4_FORS_HEIGHT(unsigned char *rootx4, - unsigned char *auth_pathx4, - const unsigned char *sk_seed, - const unsigned char *pub_seed, - const uint32_t leaf_idx[4], - uint32_t idx_offset[4], - void (*gen_leafx4)(unsigned char * /* leaf0 */, - unsigned char * /* leaf1 */, - unsigned char * /* leaf2 */, - unsigned char * /* leaf3 */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx0 */, - uint32_t /* addr_idx1 */, - uint32_t /* addr_idx2 */, - uint32_t /* addr_idx3 */, - const uint32_t[8] /* tree_addr */, - const hash_state * /* state_seeded */), - uint32_t tree_addrx4[4 * 8], - const hash_state *state_seeded); +#define treehashx4 SPX_NAMESPACE(treehashx4) +void treehashx4(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leafx4)( + unsigned char * /* Where to write the leaves */, + const spx_ctx * /* ctx */, + uint32_t addr_idx, void *info), + uint32_t tree_addrx4[4 * 8], void *info); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/wots.c b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/wots.c index 239a8859a9..4d5041ce05 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/wots.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/wots.c @@ -1,106 +1,104 @@ #include #include +#include "wots.h" + #include "address.h" #include "hash.h" -#include "hash_state.h" #include "hashx4.h" #include "params.h" #include "thash.h" #include "thashx4.h" #include "utils.h" -#include "wots.h" +#include "utilsx4.h" +#include "wotsx4.h" // TODO clarify address expectations, and make them more uniform. // TODO i.e. do we expect types to be set already? // TODO and do we expect modifications or copies? /** - * Computes the starting value for a chain, i.e. the secret key. - * Expects the address to be complete up to the chain address. - */ -static void wots_gen_sk(unsigned char *sk, const unsigned char *sk_seed, - uint32_t wots_addr[8], const hash_state *state_seeded) { - /* Make sure that the hash address is actually zeroed. */ - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_set_hash_addr(wots_addr, 0); - - /* Generate sk element. */ - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_prf_addr(sk, sk_seed, wots_addr, state_seeded); -} - -/** - * 4-way parallel version of wots_gen_sk; expects 4x as much space in sk + * Computes up the chains */ -static void wots_gen_skx4(unsigned char *skx4, const unsigned char *sk_seed, - uint32_t wots_addrx4[4 * 8], const hash_state *state_seeded) { - unsigned int j; - - /* Make sure that the hash address is actually zeroed. */ +static void gen_chains( + unsigned char *out, + const unsigned char *in, + unsigned int start[SPX_WOTS_LEN], + const unsigned int steps[SPX_WOTS_LEN], + const spx_ctx *ctx, + uint32_t addr[8]) { + uint32_t i, j, k, idx, watching; + int done; + unsigned char empty[SPX_N]; + unsigned char *bufs[4]; + uint32_t addrs[8 * 4]; + + int l; + uint16_t counts[SPX_WOTS_W] = { 0 }; + uint16_t idxs[SPX_WOTS_LEN]; + uint16_t total, newTotal; + + /* set addrs = {addr, addr, addr, addr} */ for (j = 0; j < 4; j++) { - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_set_hash_addr(wots_addrx4 + j * 8, 0); + memcpy(addrs + j * 8, addr, sizeof(uint32_t) * 8); } - /* Generate sk element. */ - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_prf_addrx4(skx4 + 0 * PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N, - skx4 + 1 * PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N, - skx4 + 2 * PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N, - skx4 + 3 * PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N, - sk_seed, wots_addrx4, - state_seeded); -} - -/** - * Computes the chaining function. - * out and in have to be n-byte arrays. - * - * Interprets in as start-th value of the chain. - * addr has to contain the address of the chain. - */ -static void gen_chain(unsigned char *out, const unsigned char *in, - unsigned int start, unsigned int steps, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *state_seeded) { - uint32_t i; - /* Initialize out with the value at position 'start'. */ - memcpy(out, in, PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N); + memcpy(out, in, SPX_WOTS_LEN * SPX_N); - /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_WOTS_W; i++) { - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_set_hash_addr(addr, i); - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_thash_1(out, out, pub_seed, addr, state_seeded); + /* Sort the chains in reverse order by steps using counting sort. */ + for (i = 0; i < SPX_WOTS_LEN; i++) { + counts[steps[i]]++; + } + total = 0; + for (l = SPX_WOTS_W - 1; l >= 0; l--) { + newTotal = counts[l] + total; + counts[l] = total; + total = newTotal; + } + for (i = 0; i < SPX_WOTS_LEN; i++) { + idxs[counts[steps[i]]] = (uint16_t)i; + counts[steps[i]]++; } -} -/** - * 4-way parallel version of gen_chain; expects 4x as much space in out, and - * 4x as much space in inx4. Assumes start and step identical across chains. - */ -static void gen_chainx4(unsigned char *outx4, const unsigned char *inx4, - unsigned int start, unsigned int steps, - const unsigned char *pub_seed, uint32_t addrx4[4 * 8], - const hash_state *state_seeded) { - uint32_t i; - unsigned int j; + /* We got our work cut out for us: do it! */ + for (i = 0; i < SPX_WOTS_LEN; i += 4) { + for (j = 0; j < 4 && i + j < SPX_WOTS_LEN; j++) { + idx = idxs[i + j]; + set_chain_addr(addrs + j * 8, idx); + bufs[j] = out + SPX_N * idx; + } - /* Initialize outx4 with the value at position 'start'. */ - memcpy(outx4, inx4, 4 * PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N); + /* As the chains are sorted in reverse order, we know that the first + * chain is the longest and the last one is the shortest. We keep + * an eye on whether the last chain is done and then on the one before, + * et cetera. */ + watching = 3; + done = 0; + while (i + watching >= SPX_WOTS_LEN) { + bufs[watching] = &empty[0]; + watching--; + } - /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_WOTS_W; i++) { - for (j = 0; j < 4; j++) { - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_set_hash_addr(addrx4 + j * 8, i); + for (k = 0;; k++) { + while (k == steps[idxs[i + watching]]) { + bufs[watching] = &empty[0]; + if (watching == 0) { + done = 1; + break; + } + watching--; + } + if (done) { + break; + } + for (j = 0; j < watching + 1; j++) { + set_hash_addr(addrs + j * 8, k + start[idxs[i + j]]); + } + + thashx4(bufs[0], bufs[1], bufs[2], bufs[3], + bufs[0], bufs[1], bufs[2], bufs[3], 1, ctx, addrs); } - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_thashx4_1(outx4 + 0 * PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N, - outx4 + 1 * PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N, - outx4 + 2 * PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N, - outx4 + 3 * PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N, - outx4 + 0 * PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N, - outx4 + 1 * PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N, - outx4 + 2 * PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N, - outx4 + 3 * PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N, - pub_seed, addrx4, - state_seeded); } } @@ -109,7 +107,8 @@ static void gen_chainx4(unsigned char *outx4, const unsigned char *inx4, * Interprets an array of bytes as integers in base w. * This only works when log_w is a divisor of 8. */ -static void base_w(unsigned int *output, const int out_len, const unsigned char *input) { +static void base_w(unsigned int *output, const int out_len, + const unsigned char *input) { int in = 0; int out = 0; unsigned char total = 0; @@ -122,119 +121,149 @@ static void base_w(unsigned int *output, const int out_len, const unsigned char in++; bits += 8; } - bits -= PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_WOTS_LOGW; - output[out] = (unsigned int)(total >> bits) & (PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_WOTS_W - 1); + bits -= SPX_WOTS_LOGW; + output[out] = (total >> bits) & (SPX_WOTS_W - 1); out++; } } /* Computes the WOTS+ checksum over a message (in base_w). */ -static void wots_checksum(unsigned int *csum_base_w, const unsigned int *msg_base_w) { +static void wots_checksum(unsigned int *csum_base_w, + const unsigned int *msg_base_w) { unsigned int csum = 0; - unsigned char csum_bytes[(PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_WOTS_LEN2 * PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_WOTS_LOGW + 7) / 8]; + unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; unsigned int i; /* Compute checksum. */ - for (i = 0; i < PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_WOTS_LEN1; i++) { - csum += PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_WOTS_W - 1 - msg_base_w[i]; + for (i = 0; i < SPX_WOTS_LEN1; i++) { + csum += SPX_WOTS_W - 1 - msg_base_w[i]; } /* Convert checksum to base_w. */ /* Make sure expected empty zero bits are the least significant bits. */ - csum = csum << (8 - ((PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_WOTS_LEN2 * PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_WOTS_LOGW) % 8)); - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); - base_w(csum_base_w, PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_WOTS_LEN2, csum_bytes); + csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); + ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); + base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); } /* Takes a message and derives the matching chain lengths. */ -static void chain_lengths(unsigned int *lengths, const unsigned char *msg) { - base_w(lengths, PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_WOTS_LEN1, msg); - wots_checksum(lengths + PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_WOTS_LEN1, lengths); +void chain_lengths(unsigned int *lengths, const unsigned char *msg) { + base_w(lengths, SPX_WOTS_LEN1, msg); + wots_checksum(lengths + SPX_WOTS_LEN1, lengths); } /** - * WOTS key generation. Takes a 32 byte sk_seed, expands it to WOTS private key - * elements and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. * * Writes the computed public key to 'pk'. */ -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_wots_gen_pk(unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *state_seeded) { +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]) { + unsigned int steps[SPX_WOTS_LEN]; + unsigned int start[SPX_WOTS_LEN]; uint32_t i; - unsigned int j; - uint32_t addrx4[4 * 8]; - unsigned char pkbuf[4 * PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N]; + chain_lengths(start, msg); - for (j = 0; j < 4; j++) { - memcpy(addrx4 + j * 8, addr, sizeof(uint32_t) * 8); - } - - /* The last iteration typically does not have complete set of 4 chains, - but because we use pkbuf, this is not an issue -- we still do as many - in parallel as possible. */ - for (i = 0; i < ((PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_WOTS_LEN + 3) & ~0x3); i += 4) { - for (j = 0; j < 4; j++) { - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_set_chain_addr(addrx4 + j * 8, i + j); - } - wots_gen_skx4(pkbuf, sk_seed, addrx4, state_seeded); - gen_chainx4(pkbuf, pkbuf, 0, PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_WOTS_W - 1, pub_seed, addrx4, state_seeded); - for (j = 0; j < 4; j++) { - if (i + j < PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_WOTS_LEN) { - memcpy(pk + (i + j)*PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N, pkbuf + j * PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N, PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N); - } - } + for (i = 0; i < SPX_WOTS_LEN; i++) { + steps[i] = SPX_WOTS_W - 1 - start[i]; } - // Get rid of unused argument variable. - (void)state_seeded; + gen_chains(pk, sig, start, steps, ctx, addr); } -/** - * Takes a n-byte message and the 32-byte sk_see to compute a signature 'sig'. +/* + * This generates 4 sequential WOTS public keys + * It also generates the WOTS signature if leaf_info indicates + * that we're signing with one of these WOTS keys */ -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_wots_sign(unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); +void wots_gen_leafx4(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info) { + struct leaf_info_x4 *info = v_info; + uint32_t *leaf_addr = info->leaf_addr; + uint32_t *pk_addr = info->pk_addr; + unsigned int i, j, k; + unsigned char pk_buffer[ 4 * SPX_WOTS_BYTES ]; + unsigned wots_offset = SPX_WOTS_BYTES; + unsigned char *buffer; + uint32_t wots_k_mask; + unsigned wots_sign_index; + + if (((leaf_idx ^ info->wots_sign_leaf) & ~3U) == 0) { + /* We're traversing the leaf that's signing; generate the WOTS */ + /* signature */ + wots_k_mask = 0; + wots_sign_index = info->wots_sign_leaf & 3; /* Which of of the 4 */ + /* 4 slots do the signatures come from */ + } else { + /* Nope, we're just generating pk's; turn off the signature logic */ + wots_k_mask = (uint32_t)~0; + wots_sign_index = 0; + } - for (i = 0; i < PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_WOTS_LEN; i++) { - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_set_chain_addr(addr, i); - wots_gen_sk(sig + i * PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N, sk_seed, addr, state_seeded); - gen_chain(sig + i * PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N, sig + i * PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N, 0, lengths[i], pub_seed, addr, state_seeded); + for (j = 0; j < 4; j++) { + set_keypair_addr( leaf_addr + j * 8, leaf_idx + j ); + set_keypair_addr( pk_addr + j * 8, leaf_idx + j ); } - // avoid unused argument - (void)state_seeded; -} + for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { + uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k to */ + /* the step if we're generating a signature, ~0 if we're not */ -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_WOTS_LEN]; - uint32_t i; + /* Start with the secret seed */ + for (j = 0; j < 4; j++) { + set_chain_addr(leaf_addr + j * 8, i); + set_hash_addr(leaf_addr + j * 8, 0); + set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTSPRF); + } + prf_addrx4(buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + buffer + 2 * wots_offset, + buffer + 3 * wots_offset, + ctx, leaf_addr); - chain_lengths(lengths, msg); + for (j = 0; j < 4; j++) { + set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTS); + } + + /* Iterate down the WOTS chain */ + for (k = 0;; k++) { + /* Check if one of the values we have needs to be saved as a */ + /* part of the WOTS signature */ + if (k == wots_k) { + memcpy( info->wots_sig + i * SPX_N, + buffer + wots_sign_index * wots_offset, SPX_N ); + } - for (i = 0; i < PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_WOTS_LEN; i++) { - PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_set_chain_addr(addr, i); - gen_chain(pk + i * PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N, sig + i * PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_N, - lengths[i], PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_WOTS_W - 1 - lengths[i], pub_seed, addr, - state_seeded); + /* Check if we hit the top of the chain */ + if (k == SPX_WOTS_W - 1) { + break; + } + + /* Iterate one step on all 4 chains */ + for (j = 0; j < 4; j++) { + set_hash_addr(leaf_addr + j * 8, k); + } + thashx4(buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + buffer + 2 * wots_offset, + buffer + 3 * wots_offset, + buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + buffer + 2 * wots_offset, + buffer + 3 * wots_offset, 1, ctx, leaf_addr); + } } - // avoid unused argument - (void)state_seeded; + /* Do the final thash to generate the public keys */ + thashx4(dest + 0 * SPX_N, + dest + 1 * SPX_N, + dest + 2 * SPX_N, + dest + 3 * SPX_N, + pk_buffer + 0 * wots_offset, + pk_buffer + 1 * wots_offset, + pk_buffer + 2 * wots_offset, + pk_buffer + 3 * wots_offset, SPX_WOTS_LEN, ctx, pk_addr); } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/wots.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/wots.h index f035b0b364..4e7692eeef 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/wots.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/wots.h @@ -1,41 +1,25 @@ -#ifndef PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_WOTS_H -#define PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_WOTS_H +#ifndef SPX_WOTS_H +#define SPX_WOTS_H -#include "hash_state.h" -#include "params.h" #include -/** - * WOTS key generation. Takes a 32 byte seed for the private key, expands it to - * a full WOTS private key and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_wots_gen_pk( - unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -/** - * Takes a n-byte message and the 32-byte seed for the private key to compute a - * signature that is placed at 'sig'. - */ -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_wots_sign( - unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *hash_state_seeded); +#include "context.h" +#include "params.h" /** * Takes a WOTS signature and an n-byte message, computes a WOTS public key. * * Writes the computed public key to 'pk'. */ -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_wots_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); +#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]); + +/* + * Compute the chain lengths needed for a given message hash + */ +#define chain_lengths SPX_NAMESPACE(chain_lengths) +void chain_lengths(unsigned int *lengths, const unsigned char *msg); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/wotsx4.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/wotsx4.h new file mode 100644 index 0000000000..cd634f1743 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/wotsx4.h @@ -0,0 +1,41 @@ +#ifndef WOTSX4_H_ +#define WOTSX4_H_ + +#include + +#include "params.h" + +/* + * This is here to provide an interface to the internal wots_gen_leafx4 + * routine. While this routine is not referenced in the package outside of + * wots.c, it is called from the stand-alone benchmark code to characterize + * the performance + */ +struct leaf_info_x4 { + unsigned char *wots_sig; + uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ + uint32_t *wots_steps; + uint32_t leaf_addr[4 * 8]; + uint32_t pk_addr[4 * 8]; +}; + +/* Macro to set the leaf_info to something 'benign', that is, it would */ +/* run with the same time as it does during the real signing process */ +/* Used only by the benchmark code */ +#define INITIALIZE_LEAF_INFO_X4(info, addr, step_buffer) { \ + (info).wots_sig = 0; \ + (info).wots_sign_leaf = ~0; \ + (info).wots_steps = step_buffer; \ + int i; \ + for (i=0; i<4; i++) { \ + memcpy( &(info).leaf_addr[8*i], addr, 32 ); \ + memcpy( &(info).pk_addr[8*i], addr, 32 ); \ + } \ + } + +#define wots_gen_leafx4 SPX_NAMESPACE(wots_gen_leafx4) +void wots_gen_leafx4(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info); + +#endif /* WOTSX4_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/address.c b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/address.c index cacdfdcb93..d49d9f3b6b 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/address.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/address.c @@ -1,78 +1,95 @@ #include +#include #include "address.h" #include "params.h" #include "utils.h" -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]) { - int i; - - for (i = 0; i < 8; i++) { - PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_ull_to_bytes( - bytes + i * 4, 4, addr[i]); - } -} - -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_set_layer_addr( - uint32_t addr[8], uint32_t layer) { - addr[0] = layer; +/* + * Specify which level of Merkle tree (the "layer") we're working on + */ +void set_layer_addr(uint32_t addr[8], uint32_t layer) { + ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; } -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_set_tree_addr( - uint32_t addr[8], uint64_t tree) { - addr[1] = 0; - addr[2] = (uint32_t) (tree >> 32); - addr[3] = (uint32_t) tree; +/* + * Specify which Merkle tree within the level (the "tree address") we're working on + */ +void set_tree_addr(uint32_t addr[8], uint64_t tree) { + ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); } -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_set_type( - uint32_t addr[8], uint32_t type) { - addr[4] = type; +/* + * Specify the reason we'll use this address structure for, that is, what + * hash will we compute with it. This is used so that unrelated types of + * hashes don't accidentally get the same address structure. The type will be + * one of the SPX_ADDR_TYPE constants + */ +void set_type(uint32_t addr[8], uint32_t type) { + ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; } -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; +/* + * Copy the layer and tree fields of the address structure. This is used + * when we're doing multiple types of hashes within the same Merkle tree + */ +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); } /* These functions are used for OTS addresses. */ -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_set_keypair_addr( - uint32_t addr[8], uint32_t keypair) { - addr[5] = keypair; +/* + * Specify which Merkle leaf we're working on; that is, which OTS keypair + * we're talking about. + */ +void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { + /* We have > 256 OTS at the bottom of the Merkle tree; to specify */ + /* which one, we'd need to express it in two bytes */ + ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR2] = (unsigned char)(keypair >> 8); + ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; } -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; - out[5] = in[5]; +/* + * Copy the layer, tree and keypair fields of the address structure. This is + * used when we're doing multiple things within the same OTS keypair + */ +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); + ((unsigned char *)out)[SPX_OFFSET_KP_ADDR2] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR2]; + ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; } -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_set_chain_addr( - uint32_t addr[8], uint32_t chain) { - addr[6] = chain; +/* + * Specify which Merkle chain within the OTS we're working with + * (the chain address) + */ +void set_chain_addr(uint32_t addr[8], uint32_t chain) { + ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; } -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_set_hash_addr( - uint32_t addr[8], uint32_t hash) { - addr[7] = hash; +/* + * Specify where in the Merkle chain we are +* (the hash address) + */ +void set_hash_addr(uint32_t addr[8], uint32_t hash) { + ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; } /* These functions are used for all hash tree addresses (including FORS). */ -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_set_tree_height( - uint32_t addr[8], uint32_t tree_height) { - addr[6] = tree_height; +/* + * Specify the height of the node in the Merkle/FORS tree we are in + * (the tree height) + */ +void set_tree_height(uint32_t addr[8], uint32_t tree_height) { + ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; } -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_set_tree_index( - uint32_t addr[8], uint32_t tree_index) { - addr[7] = tree_index; +/* + * Specify the distance from the left edge of the node in the Merkle/FORS tree + * (the tree index) + */ +void set_tree_index(uint32_t addr[8], uint32_t tree_index) { + u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/address.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/address.h index ec19cb4d7b..24a84eb40c 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/address.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/address.h @@ -1,50 +1,52 @@ -#ifndef PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_ADDRESS_H -#define PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_ADDRESS_H +#ifndef SPX_ADDRESS_H +#define SPX_ADDRESS_H #include -#define PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_ADDR_TYPE_WOTS 0 -#define PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_ADDR_TYPE_WOTSPK 1 -#define PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_ADDR_TYPE_HASHTREE 2 -#define PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_ADDR_TYPE_FORSTREE 3 -#define PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_ADDR_TYPE_FORSPK 4 +#include "params.h" -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]); +/* The hash types that are passed to set_type */ +#define SPX_ADDR_TYPE_WOTS 0 +#define SPX_ADDR_TYPE_WOTSPK 1 +#define SPX_ADDR_TYPE_HASHTREE 2 +#define SPX_ADDR_TYPE_FORSTREE 3 +#define SPX_ADDR_TYPE_FORSPK 4 +#define SPX_ADDR_TYPE_WOTSPRF 5 +#define SPX_ADDR_TYPE_FORSPRF 6 -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_set_layer_addr( - uint32_t addr[8], uint32_t layer); +#define set_layer_addr SPX_NAMESPACE(set_layer_addr) +void set_layer_addr(uint32_t addr[8], uint32_t layer); -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_set_tree_addr( - uint32_t addr[8], uint64_t tree); +#define set_tree_addr SPX_NAMESPACE(set_tree_addr) +void set_tree_addr(uint32_t addr[8], uint64_t tree); -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_set_type( - uint32_t addr[8], uint32_t type); +#define set_type SPX_NAMESPACE(set_type) +void set_type(uint32_t addr[8], uint32_t type); /* Copies the layer and tree part of one address into the other */ -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]); +#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); /* These functions are used for WOTS and FORS addresses. */ -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_set_keypair_addr( - uint32_t addr[8], uint32_t keypair); +#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) +void set_keypair_addr(uint32_t addr[8], uint32_t keypair); -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_set_chain_addr( - uint32_t addr[8], uint32_t chain); +#define set_chain_addr SPX_NAMESPACE(set_chain_addr) +void set_chain_addr(uint32_t addr[8], uint32_t chain); -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_set_hash_addr( - uint32_t addr[8], uint32_t hash); +#define set_hash_addr SPX_NAMESPACE(set_hash_addr) +void set_hash_addr(uint32_t addr[8], uint32_t hash); -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]); +#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); /* These functions are used for all hash tree addresses (including FORS). */ -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_set_tree_height( - uint32_t addr[8], uint32_t tree_height); +#define set_tree_height SPX_NAMESPACE(set_tree_height) +void set_tree_height(uint32_t addr[8], uint32_t tree_height); -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_set_tree_index( - uint32_t addr[8], uint32_t tree_index); +#define set_tree_index SPX_NAMESPACE(set_tree_index) +void set_tree_index(uint32_t addr[8], uint32_t tree_index); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/api.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/api.h index a95a4f476c..ea16f2a221 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/api.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/api.h @@ -4,15 +4,13 @@ #include #include - - -#define PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_CRYPTO_ALGNAME "SPHINCS+" +#define PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_CRYPTO_ALGNAME "SPHINCS+-haraka-192s-simple" #define PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_CRYPTO_SECRETKEYBYTES 96 #define PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_CRYPTO_PUBLICKEYBYTES 48 -#define PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_CRYPTO_BYTES 16224 -#define PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_CRYPTO_SEEDBYTES 72 +#define PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_CRYPTO_BYTES 16224 +#define PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_CRYPTO_SEEDBYTES 72 /* * Returns the length of a secret key, in bytes @@ -39,43 +37,41 @@ size_t PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_crypto_sign_seedbytes(void); * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] * Format pk: [root || PUB_SEED] */ -int PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed); +int PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); /* * Generates a SPHINCS+ key pair. * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] * Format pk: [root || PUB_SEED] */ -int PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk); +int PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); /** * Returns an array containing a detached signature. */ -int PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk); +int PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); /** * Verifies a detached signature and message under a given public key. */ -int PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk); +int PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, + const uint8_t *pk); /** * Returns an array containing the signature followed by the message. */ -int PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk); +int PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); /** * Verifies a given signature-message pair under a given public key. */ -int PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk); - +int PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/context.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/context.h new file mode 100644 index 0000000000..600dfb73c7 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/context.h @@ -0,0 +1,24 @@ +#ifndef SPX_CONTEXT_H +#define SPX_CONTEXT_H + +#include +#include + +#include "params.h" + +typedef struct { + uint8_t pub_seed[SPX_N]; + uint8_t sk_seed[SPX_N]; + + + uint64_t tweaked512_rc64[10][8]; + uint32_t tweaked256_rc32[10][8]; +} spx_ctx; + +#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) +void initialize_hash_function(spx_ctx *ctx); + +#define free_hash_function SPX_NAMESPACE(free_hash_function) +void free_hash_function(spx_ctx *ctx); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/context_haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/context_haraka.c new file mode 100644 index 0000000000..f1cd7e3664 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/context_haraka.c @@ -0,0 +1,11 @@ +#include "context.h" +#include "haraka.h" + +void initialize_hash_function(spx_ctx *ctx) { + tweak_constants(ctx); +} + +// we don't support heap-based haraka right now +void free_hash_function(spx_ctx *ctx) { + (void)ctx; // suppress unused variable warnings +} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/fors.c b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/fors.c index e35d86e878..96ca72e986 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/fors.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/fors.c @@ -2,58 +2,58 @@ #include #include -#include "address.h" #include "fors.h" + +#include "address.h" #include "hash.h" -#include "hash_state.h" #include "thash.h" #include "utils.h" +#include "utilsx1.h" -static void fors_gen_sk(unsigned char *sk, const unsigned char *sk_seed, - uint32_t fors_leaf_addr[8], const hash_state *hash_state_seeded) { - PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_prf_addr( - sk, sk_seed, fors_leaf_addr, hash_state_seeded); +static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + prf_addr(sk, ctx, fors_leaf_addr); } static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, - const unsigned char *pub_seed, - uint32_t fors_leaf_addr[8], - const hash_state *hash_state_seeded) { - PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_thash_1( - leaf, sk, pub_seed, fors_leaf_addr, hash_state_seeded); + const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + thash(leaf, sk, 1, ctx, fors_leaf_addr); } -static void fors_gen_leaf(unsigned char *leaf, const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx, const uint32_t fors_tree_addr[8], - const hash_state *hash_state_seeded) { - uint32_t fors_leaf_addr[8] = {0}; - - /* Only copy the parts that must be kept in fors_leaf_addr. */ - PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_copy_keypair_addr( - fors_leaf_addr, fors_tree_addr); - PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_set_type( - fors_leaf_addr, PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_set_tree_index( - fors_leaf_addr, addr_idx); - - fors_gen_sk(leaf, sk_seed, fors_leaf_addr, hash_state_seeded); - fors_sk_to_leaf(leaf, leaf, pub_seed, fors_leaf_addr, hash_state_seeded); +struct fors_gen_leaf_info { + uint32_t leaf_addrx[8]; +}; + +static void fors_gen_leafx1(unsigned char *leaf, + const spx_ctx *ctx, + uint32_t addr_idx, void *info) { + struct fors_gen_leaf_info *fors_info = info; + uint32_t *fors_leaf_addr = fors_info->leaf_addrx; + + /* Only set the parts that the caller doesn't set */ + set_tree_index(fors_leaf_addr, addr_idx); + set_type(fors_leaf_addr, SPX_ADDR_TYPE_FORSPRF); + fors_gen_sk(leaf, ctx, fors_leaf_addr); + + set_type(fors_leaf_addr, SPX_ADDR_TYPE_FORSTREE); + fors_sk_to_leaf(leaf, leaf, + ctx, fors_leaf_addr); } /** - * Interprets m as PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_FORS_HEIGHT-bit unsigned integers. - * Assumes m contains at least PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_FORS_TREES bits. - * Assumes indices has space for PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_FORS_TREES integers. + * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + * Assumes indices has space for SPX_FORS_TREES integers. */ static void message_to_indices(uint32_t *indices, const unsigned char *m) { unsigned int i, j; unsigned int offset = 0; - for (i = 0; i < PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_FORS_TREES; i++) { + for (i = 0; i < SPX_FORS_TREES; i++) { indices[i] = 0; - for (j = 0; j < PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_FORS_HEIGHT; j++) { - indices[i] ^= (((uint32_t)m[offset >> 3] >> (offset & 0x7)) & 0x1) << j; + for (j = 0; j < SPX_FORS_HEIGHT; j++) { + indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); offset++; } } @@ -61,55 +61,51 @@ static void message_to_indices(uint32_t *indices, const unsigned char *m) { /** * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_FORS_TREES bits. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. */ -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_fors_sign( - unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *hash_state_seeded) { - uint32_t indices[PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_FORS_TREES]; - unsigned char roots[PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_FORS_TREES * PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_N]; +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; uint32_t fors_tree_addr[8] = {0}; + struct fors_gen_leaf_info fors_info = {0}; + uint32_t *fors_leaf_addr = fors_info.leaf_addrx; uint32_t fors_pk_addr[8] = {0}; uint32_t idx_offset; unsigned int i; - PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_copy_keypair_addr( - fors_tree_addr, fors_addr); - PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_copy_keypair_addr( - fors_pk_addr, fors_addr); + copy_keypair_addr(fors_tree_addr, fors_addr); + copy_keypair_addr(fors_leaf_addr, fors_addr); - PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_set_type( - fors_tree_addr, PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_set_type( - fors_pk_addr, PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_ADDR_TYPE_FORSPK); + copy_keypair_addr(fors_pk_addr, fors_addr); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); message_to_indices(indices, m); - for (i = 0; i < PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_FORS_TREES; i++) { - idx_offset = i * (1 << PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_FORS_HEIGHT); + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); - PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_set_tree_height( - fors_tree_addr, 0); - PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_set_tree_index( - fors_tree_addr, indices[i] + idx_offset); + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); /* Include the secret key part that produces the selected leaf node. */ - fors_gen_sk(sig, sk_seed, fors_tree_addr, hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_N; + fors_gen_sk(sig, ctx, fors_tree_addr); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + sig += SPX_N; /* Compute the authentication path for this leaf node. */ - PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_treehash_FORS_HEIGHT( - roots + i * PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_N, sig, sk_seed, pub_seed, - indices[i], idx_offset, fors_gen_leaf, fors_tree_addr, - hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_N * PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_FORS_HEIGHT; + treehashx1(roots + i * SPX_N, sig, ctx, + indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx1, + fors_tree_addr, &fors_info); + + sig += SPX_N * SPX_FORS_HEIGHT; } /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_thash_FORS_TREES( - pk, roots, pub_seed, fors_pk_addr, hash_state_seeded); + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); } /** @@ -117,45 +113,44 @@ void PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_fors_sign( * This can be used for verification by comparing to a known public key, or to * subsequently verify a signature on the derived public key. The latter is the * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_FORS_TREES bits. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. */ -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_fors_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, const uint32_t fors_addr[8], - const hash_state *hash_state_seeded) { - uint32_t indices[PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_FORS_TREES]; - unsigned char roots[PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_FORS_TREES * PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_N]; - unsigned char leaf[PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_N]; +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + unsigned char leaf[SPX_N]; uint32_t fors_tree_addr[8] = {0}; uint32_t fors_pk_addr[8] = {0}; uint32_t idx_offset; unsigned int i; - PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_copy_keypair_addr(fors_tree_addr, fors_addr); - PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_copy_keypair_addr(fors_pk_addr, fors_addr); + copy_keypair_addr(fors_tree_addr, fors_addr); + copy_keypair_addr(fors_pk_addr, fors_addr); - PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_set_type(fors_tree_addr, PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_set_type(fors_pk_addr, PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_ADDR_TYPE_FORSPK); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); message_to_indices(indices, m); - for (i = 0; i < PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_FORS_TREES; i++) { - idx_offset = i * (1 << PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_FORS_HEIGHT); + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); - PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_set_tree_height(fors_tree_addr, 0); - PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_set_tree_index(fors_tree_addr, indices[i] + idx_offset); + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); /* Derive the leaf from the included secret key part. */ - fors_sk_to_leaf(leaf, sig, pub_seed, fors_tree_addr, hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_N; + fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); + sig += SPX_N; /* Derive the corresponding root node of this tree. */ - PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_compute_root(roots + i * PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_N, leaf, indices[i], idx_offset, sig, - PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_FORS_HEIGHT, pub_seed, fors_tree_addr, hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_N * PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_FORS_HEIGHT; + compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, + sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); + sig += SPX_N * SPX_FORS_HEIGHT; } /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_thash_FORS_TREES(pk, roots, pub_seed, fors_pk_addr, hash_state_seeded); + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/fors.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/fors.h index 4c26c25f35..509140a178 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/fors.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/fors.h @@ -1,32 +1,32 @@ -#ifndef PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_FORS_H -#define PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_FORS_H +#ifndef SPX_FORS_H +#define SPX_FORS_H #include -#include "hash_state.h" +#include "context.h" #include "params.h" /** * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_FORS_TREES bits. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. */ -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_fors_sign( - unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *hash_state_seeded); +#define fors_sign SPX_NAMESPACE(fors_sign) +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); /** * Derives the FORS public key from a signature. * This can be used for verification by comparing to a known public key, or to * subsequently verify a signature on the derived public key. The latter is the * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_FORS_TREES bits. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. */ -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_fors_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, const uint32_t fors_addr[8], - const hash_state *hash_state_seeded); +#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/haraka.c index 232e1dc80d..a4944913b5 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/haraka.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/haraka.c @@ -6,12 +6,13 @@ * by Thomas Pornin */ -#include #include +#include #include #include #include "haraka.h" +#include "utils.h" #define HARAKAS_RATE 32 @@ -656,76 +657,62 @@ static void interleave_constant32(uint32_t *out, const unsigned char *in) { br_aes_ct_ortho(out); } -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_tweak_constants( - harakactx *state, - const unsigned char *pk_seed, const unsigned char *sk_seed, - unsigned long long seed_length) { +void tweak_constants(spx_ctx *ctx) { unsigned char buf[40 * 16]; int i; /* Use the standard constants to generate tweaked ones. */ - memcpy((uint8_t *)state->tweaked512_rc64, (uint8_t *)haraka512_rc64, 40 * 16); - - /* Constants for sk.seed */ - if (sk_seed != NULL) { - PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_haraka_S( - buf, 40 * 16, sk_seed, seed_length, state); - - /* Interleave constants */ - for (i = 0; i < 10; i++) { - interleave_constant32(state->tweaked256_rc32_sseed[i], buf + 32 * i); - } - } + memcpy((uint8_t *)ctx->tweaked512_rc64, (uint8_t *)haraka512_rc64, 40 * 16); /* Constants for pk.seed */ - PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_haraka_S( - buf, 40 * 16, pk_seed, seed_length, state); + haraka_S(buf, 40 * 16, ctx->pub_seed, SPX_N, ctx); for (i = 0; i < 10; i++) { - interleave_constant32(state->tweaked256_rc32[i], buf + 32 * i); - interleave_constant(state->tweaked512_rc64[i], buf + 64 * i); + interleave_constant32(ctx->tweaked256_rc32[i], buf + 32 * i); + interleave_constant(ctx->tweaked512_rc64[i], buf + 64 * i); } } -static void haraka_S_absorb(unsigned char *s, +static void haraka_S_absorb(unsigned char *s, unsigned int r, const unsigned char *m, unsigned long long mlen, - unsigned char p, const harakactx *state) { + unsigned char p, const spx_ctx *ctx) { unsigned long long i; - unsigned char t[HARAKAS_RATE]; + PQCLEAN_VLA(uint8_t, t, r); - while (mlen >= HARAKAS_RATE) { + while (mlen >= r) { /* XOR block to state */ - for (i = 0; i < HARAKAS_RATE; ++i) { + for (i = 0; i < r; ++i) { s[i] ^= m[i]; } - PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_haraka512_perm(s, s, state); - mlen -= HARAKAS_RATE; - m += HARAKAS_RATE; + haraka512_perm(s, s, ctx); + mlen -= r; + m += r; } - for (i = 0; i < HARAKAS_RATE; ++i) { + for (i = 0; i < r; ++i) { t[i] = 0; } for (i = 0; i < mlen; ++i) { t[i] = m[i]; } t[i] = p; - t[HARAKAS_RATE - 1] |= 128; - for (i = 0; i < HARAKAS_RATE; ++i) { + t[r - 1] |= 128; + for (i = 0; i < r; ++i) { s[i] ^= t[i]; } } static void haraka_S_squeezeblocks(unsigned char *h, unsigned long long nblocks, - unsigned char *s, const harakactx *state) { + unsigned char *s, unsigned int r, + const spx_ctx *ctx) { while (nblocks > 0) { - PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_haraka512_perm(s, s, state); + haraka512_perm(s, s, ctx); memcpy(h, s, HARAKAS_RATE); - h += HARAKAS_RATE; + h += r; nblocks--; } } -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_haraka_S_inc_init(uint8_t *s_inc) { +void haraka_S_inc_init(uint8_t *s_inc) { size_t i; for (i = 0; i < 64; i++) { @@ -734,7 +721,8 @@ void PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_haraka_S_inc_init(uint8_t *s_inc) { s_inc[64] = 0; } -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, const harakactx *state) { +void haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, + const spx_ctx *ctx) { size_t i; /* Recall that s_inc[64] is the non-absorbed bytes xored into the state */ @@ -745,19 +733,19 @@ void PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_haraka_S_inc_absorb(uint8_t *s_inc, c s_inc[s_inc[64] + i] ^= m[i]; } mlen -= (size_t)(HARAKAS_RATE - s_inc[64]); - m += HARAKAS_RATE - s_inc[64]; + m += HARAKAS_RATE - (uint8_t)s_inc[64]; s_inc[64] = 0; - PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_haraka512_perm(s_inc, s_inc, state); + haraka512_perm(s_inc, s_inc, ctx); } for (i = 0; i < mlen; i++) { s_inc[s_inc[64] + i] ^= m[i]; } - s_inc[64] = (uint8_t)(mlen + s_inc[64]); + s_inc[64] += (uint8_t)mlen; } -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_haraka_S_inc_finalize(uint8_t *s_inc) { +void haraka_S_inc_finalize(uint8_t *s_inc) { /* After haraka_S_inc_absorb, we are guaranteed that s_inc[64] < HARAKAS_RATE, so we can always use one more byte for p in the current state. */ s_inc[s_inc[64]] ^= 0x1F; @@ -765,22 +753,23 @@ void PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_haraka_S_inc_finalize(uint8_t *s_inc) s_inc[64] = 0; } -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, const harakactx *state) { - uint8_t i; +void haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, + const spx_ctx *ctx) { + size_t i; /* First consume any bytes we still have sitting around */ for (i = 0; i < outlen && i < s_inc[64]; i++) { /* There are s_inc[64] bytes left, so r - s_inc[64] is the first available byte. We consume from there, i.e., up to r. */ - out[i] = s_inc[(HARAKAS_RATE - s_inc[64] + i)]; + out[i] = (uint8_t)s_inc[(HARAKAS_RATE - s_inc[64] + i)]; } out += i; outlen -= i; - s_inc[64] = (uint8_t)(s_inc[64] - i); + s_inc[64] -= (uint8_t)i; /* Then squeeze the remaining necessary blocks */ while (outlen > 0) { - PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_haraka512_perm(s_inc, s_inc, state); + haraka512_perm(s_inc, s_inc, ctx); for (i = 0; i < outlen && i < HARAKAS_RATE; i++) { out[i] = s_inc[i]; @@ -791,7 +780,9 @@ void PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_haraka_S_inc_squeeze(uint8_t *out, si } } -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_haraka_S(unsigned char *out, unsigned long long outlen, const unsigned char *in, unsigned long long inlen, const harakactx *state) { +void haraka_S(unsigned char *out, unsigned long long outlen, + const unsigned char *in, unsigned long long inlen, + const spx_ctx *ctx) { unsigned long long i; unsigned char s[64]; unsigned char d[32]; @@ -799,20 +790,21 @@ void PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_haraka_S(unsigned char *out, unsigned for (i = 0; i < 64; i++) { s[i] = 0; } - haraka_S_absorb(s, in, inlen, 0x1F, state); + haraka_S_absorb(s, 32, in, inlen, 0x1F, ctx); - haraka_S_squeezeblocks(out, outlen / 32, s, state); + haraka_S_squeezeblocks(out, outlen / 32, s, 32, ctx); out += (outlen / 32) * 32; if (outlen % 32) { - haraka_S_squeezeblocks(d, 1, s, state); + haraka_S_squeezeblocks(d, 1, s, 32, ctx); for (i = 0; i < outlen % 32; i++) { out[i] = d[i]; } } } -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_haraka512_perm(unsigned char *out, const unsigned char *in, const harakactx *state) { +void haraka512_perm(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx) { uint32_t w[16]; uint64_t q[8], tmp_q; unsigned int i, j; @@ -829,7 +821,7 @@ void PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_haraka512_perm(unsigned char *out, co br_aes_ct64_bitslice_Sbox(q); shift_rows(q); mix_columns(q); - add_round_key(q, state->tweaked512_rc64[2 * i + j]); + add_round_key(q, ctx->tweaked512_rc64[2 * i + j]); } /* Mix states */ for (j = 0; j < 8; j++) { @@ -857,12 +849,12 @@ void PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_haraka512_perm(unsigned char *out, co br_range_enc32le(out, w, 16); } -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_haraka512(unsigned char *out, const unsigned char *in, const harakactx *state) { +void haraka512(unsigned char *out, const unsigned char *in, const spx_ctx *ctx) { int i; unsigned char buf[64]; - PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_haraka512_perm(buf, in, state); + haraka512_perm(buf, in, ctx); /* Feed-forward */ for (i = 0; i < 64; i++) { buf[i] = buf[i] ^ in[i]; @@ -876,50 +868,8 @@ void PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_haraka512(unsigned char *out, const u } -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_haraka256(unsigned char *out, const unsigned char *in, const harakactx *state) { - uint32_t q[8], tmp_q; - int i, j; - - for (i = 0; i < 4; i++) { - q[2 * i] = br_dec32le(in + 4 * i); - q[2 * i + 1] = br_dec32le(in + 4 * i + 16); - } - br_aes_ct_ortho(q); - - /* AES rounds */ - for (i = 0; i < 5; i++) { - for (j = 0; j < 2; j++) { - br_aes_ct_bitslice_Sbox(q); - shift_rows32(q); - mix_columns32(q); - add_round_key32(q, state->tweaked256_rc32[2 * i + j]); - } - - /* Mix states */ - for (j = 0; j < 8; j++) { - tmp_q = q[j]; - q[j] = (tmp_q & 0x81818181) | - (tmp_q & 0x02020202) << 1 | - (tmp_q & 0x04040404) << 2 | - (tmp_q & 0x08080808) << 3 | - (tmp_q & 0x10101010) >> 3 | - (tmp_q & 0x20202020) >> 2 | - (tmp_q & 0x40404040) >> 1; - } - } - - br_aes_ct_ortho(q); - for (i = 0; i < 4; i++) { - br_enc32le(out + 4 * i, q[2 * i]); - br_enc32le(out + 4 * i + 16, q[2 * i + 1]); - } - - for (i = 0; i < 32; i++) { - out[i] ^= in[i]; - } -} - -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_haraka256_sk(unsigned char *out, const unsigned char *in, const harakactx *state) { +void haraka256(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx) { uint32_t q[8], tmp_q; int i, j; @@ -935,7 +885,7 @@ void PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_haraka256_sk(unsigned char *out, cons br_aes_ct_bitslice_Sbox(q); shift_rows32(q); mix_columns32(q); - add_round_key32(q, state->tweaked256_rc32_sseed[2 * i + j]); + add_round_key32(q, ctx->tweaked256_rc32[2 * i + j]); } /* Mix states */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/haraka.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/haraka.h index 87f1b6ede4..737cb6065f 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/haraka.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/haraka.h @@ -1,40 +1,42 @@ -#ifndef PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_HARAKA_H -#define PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_HARAKA_H +#ifndef SPX_HARAKA_H +#define SPX_HARAKA_H -#include -#include - -typedef struct { - uint64_t tweaked512_rc64[10][8]; - uint32_t tweaked256_rc32[10][8]; - uint32_t tweaked256_rc32_sseed[10][8]; -} harakactx; +#include "context.h" +#include "params.h" /* Tweak constants with seed */ -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_tweak_constants( - harakactx *state, - const unsigned char *pk_seed, const unsigned char *sk_seed, - unsigned long long seed_length); +#define tweak_constants SPX_NAMESPACE(tweak_constants) +void tweak_constants(spx_ctx *ctx); /* Haraka Sponge */ -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_haraka_S_inc_init(uint8_t *s_inc); -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, const harakactx *state); -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_haraka_S_inc_finalize(uint8_t *s_inc); -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, const harakactx *state); -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_haraka_S( - unsigned char *out, unsigned long long outlen, - const unsigned char *in, unsigned long long inlen, const harakactx *state); +#define haraka_S_inc_init SPX_NAMESPACE(haraka_S_inc_init) +void haraka_S_inc_init(uint8_t *s_inc); +#define haraka_S_inc_absorb SPX_NAMESPACE(haraka_S_inc_absorb) +void haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, + const spx_ctx *ctx); +#define haraka_S_inc_finalize SPX_NAMESPACE(haraka_S_inc_finalize) +void haraka_S_inc_finalize(uint8_t *s_inc); +#define haraka_S_inc_squeeze SPX_NAMESPACE(haraka_S_inc_squeeze) +void haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, + const spx_ctx *ctx); +#define haraka_S SPX_NAMESPACE(haraka_S) +void haraka_S(unsigned char *out, unsigned long long outlen, + const unsigned char *in, unsigned long long inlen, + const spx_ctx *ctx); /* Applies the 512-bit Haraka permutation to in. */ -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_haraka512_perm(unsigned char *out, const unsigned char *in, const harakactx *state); +#define haraka512_perm SPX_NAMESPACE(haraka512_perm) +void haraka512_perm(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx); /* Implementation of Haraka-512 */ -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_haraka512(unsigned char *out, const unsigned char *in, const harakactx *state); +#define haraka512 SPX_NAMESPACE(haraka512) +void haraka512(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx); /* Implementation of Haraka-256 */ -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_haraka256(unsigned char *out, const unsigned char *in, const harakactx *state); - -/* Implementation of Haraka-256 using sk.seed constants */ -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_haraka256_sk(unsigned char *out, const unsigned char *in, const harakactx *state); +#define haraka256 SPX_NAMESPACE(haraka256) +void haraka256(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/haraka_offsets.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/haraka_offsets.h new file mode 100644 index 0000000000..7c062272a0 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/haraka_offsets.h @@ -0,0 +1,21 @@ +#ifndef HARAKA_OFFSETS_H_ +#define HARAKA_OFFSETS_H_ + +/* + * Offsets of various fields in the address structure when we use Haraka as + * the Sphincs+ hash function + */ + +#define SPX_OFFSET_LAYER 3 /* The byte used to specify the Merkle tree layer */ +#define SPX_OFFSET_TREE 8 /* The start of the 8 byte field used to specify the tree */ +#define SPX_OFFSET_TYPE 19 /* The byte used to specify the hash type (reason) */ +#define SPX_OFFSET_KP_ADDR2 22 /* The high byte used to specify the key pair (which one-time signature) */ +#define SPX_OFFSET_KP_ADDR1 23 /* The low byte used to specify the key pair */ +#define SPX_OFFSET_CHAIN_ADDR 27 /* The byte used to specify the chain address (which Winternitz chain) */ +#define SPX_OFFSET_HASH_ADDR 31 /* The byte used to specify the hash address (where in the Winternitz chain) */ +#define SPX_OFFSET_TREE_HGT 27 /* The byte used to specify the height of this node in the FORS or Merkle tree */ +#define SPX_OFFSET_TREE_INDEX 28 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ + +#define SPX_HARAKA 1 + +#endif /* HARAKA_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/hash.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/hash.h index 742306ad11..f7c87d4c3c 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/hash.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/hash.h @@ -1,31 +1,28 @@ -#ifndef PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_HASH_H -#define PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_HASH_H - -#include "hash_state.h" +#ifndef SPX_HASH_H +#define SPX_HASH_H #include #include -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_initialize_hash_function( - hash_state *hash_state_seeded, - const unsigned char *pub_seed, const unsigned char *sk_seed); +#include "context.h" +#include "params.h" + +#define prf_addr SPX_NAMESPACE(prf_addr) +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]); -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_destroy_hash_function(hash_state *hash_state_seeded); +#define gen_message_random SPX_NAMESPACE(gen_message_random) +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded); +#define hash_message SPX_NAMESPACE(hash_message) +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/hash_haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/hash_haraka.c index 3eae3f1074..750a67423b 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/hash_haraka.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/hash_haraka.c @@ -2,58 +2,44 @@ #include #include "address.h" -#include "haraka.h" -#include "hash.h" #include "params.h" #include "utils.h" -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_initialize_hash_function( - hash_state *hash_state_seeded, - const unsigned char *pub_seed, const unsigned char *sk_seed) { - PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_tweak_constants(hash_state_seeded, pub_seed, sk_seed, PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_N); -} - -/* The haraka implementation is stack based and won't be replaced in PQClean/OQS, - so we don't need to do anything */ -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_destroy_hash_function( - hash_state *hash_state_seeded) { // NOLINT(readability-non-const-parameter) - (void)hash_state_seeded; -} +#include "haraka.h" +#include "hash.h" /* - * Computes PRF(key, addr), given a secret key of PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_N bytes and an address + * Computes PRF(key, addr), given a secret key of SPX_N bytes and an address */ -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded) { - unsigned char buf[PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_ADDR_BYTES]; - /* Since PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_N may be smaller than 32, we need a temporary buffer. */ +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]) { + /* Since SPX_N may be smaller than 32, we need temporary buffers. */ unsigned char outbuf[32]; + unsigned char buf[64] = {0}; - (void)key; /* Suppress an 'unused parameter' warning. */ + memcpy(buf, addr, SPX_ADDR_BYTES); + memcpy(buf + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); - PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_addr_to_bytes(buf, addr); - PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_haraka256_sk(outbuf, buf, hash_state_seeded); - memcpy(out, outbuf, PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_N); + haraka512(outbuf, (const void *)buf, ctx); + memcpy(out, outbuf, SPX_N); } /** * Computes the message-dependent randomness R, using a secret seed and an * optional randomization value as well as the message. */ -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded) { +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { uint8_t s_inc[65]; - PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_haraka_S_inc_init(s_inc); - PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_haraka_S_inc_absorb(s_inc, sk_prf, PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_N, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_haraka_S_inc_absorb(s_inc, optrand, PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_N, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_haraka_S_inc_absorb(s_inc, m, mlen, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_haraka_S_inc_finalize(s_inc); - PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_haraka_S_inc_squeeze(R, PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_N, s_inc, hash_state_seeded); + haraka_S_inc_init(s_inc); + haraka_S_inc_absorb(s_inc, sk_prf, SPX_N, ctx); + haraka_S_inc_absorb(s_inc, optrand, SPX_N, ctx); + haraka_S_inc_absorb(s_inc, m, mlen, ctx); + haraka_S_inc_finalize(s_inc); + haraka_S_inc_squeeze(R, SPX_N, s_inc, ctx); } /** @@ -61,36 +47,35 @@ void PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_gen_message_random( * Outputs the message digest and the index of the leaf. The index is split in * the tree index and the leaf index, for convenient copying to an address. */ -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded) { -#define PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_TREE_BITS (PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_TREE_HEIGHT * (PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_D - 1)) -#define PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_TREE_BYTES ((PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_TREE_BITS + 7) / 8) -#define PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_LEAF_BITS PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_TREE_HEIGHT -#define PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_LEAF_BYTES ((PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_LEAF_BITS + 7) / 8) -#define PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_DGST_BYTES (PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_FORS_MSG_BYTES + PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_TREE_BYTES + PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_LEAF_BYTES) +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { +#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) +#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) +#define SPX_LEAF_BITS SPX_TREE_HEIGHT +#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) +#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) - unsigned char buf[PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_DGST_BYTES]; + unsigned char buf[SPX_DGST_BYTES]; unsigned char *bufp = buf; uint8_t s_inc[65]; - PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_haraka_S_inc_init(s_inc); - PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_haraka_S_inc_absorb(s_inc, R, PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_N, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_haraka_S_inc_absorb(s_inc, pk + PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_N, PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_N, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_haraka_S_inc_absorb(s_inc, m, mlen, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_haraka_S_inc_finalize(s_inc); - PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_haraka_S_inc_squeeze(buf, PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_DGST_BYTES, s_inc, hash_state_seeded); + haraka_S_inc_init(s_inc); + haraka_S_inc_absorb(s_inc, R, SPX_N, ctx); + haraka_S_inc_absorb(s_inc, pk + SPX_N, SPX_N, ctx); // Only absorb root part of pk + haraka_S_inc_absorb(s_inc, m, mlen, ctx); + haraka_S_inc_finalize(s_inc); + haraka_S_inc_squeeze(buf, SPX_DGST_BYTES, s_inc, ctx); + + memcpy(digest, bufp, SPX_FORS_MSG_BYTES); + bufp += SPX_FORS_MSG_BYTES; - memcpy(digest, bufp, PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_FORS_MSG_BYTES); - bufp += PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_FORS_MSG_BYTES; - *tree = PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_bytes_to_ull(bufp, PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_TREE_BYTES); - *tree &= (~(uint64_t)0) >> (64 - PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_TREE_BITS); - bufp += PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_TREE_BYTES; + *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); + *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); + bufp += SPX_TREE_BYTES; - *leaf_idx = (uint32_t)PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_bytes_to_ull( - bufp, PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_LEAF_BYTES); - *leaf_idx &= (~(uint32_t)0) >> (32 - PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_LEAF_BITS); + *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); + *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/hash_state.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/hash_state.h deleted file mode 100644 index 5adb1d9a22..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/hash_state.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef SPX_HASH_STATE_H -#define SPX_HASH_STATE_H - -/** - * Defines the type of the hash function state. - * - * Don't be fooled into thinking this instance of SPHINCS+ isn't stateless! - * - * From Section 7.2.2 from the SPHINCS+ round-2 specification: - * - * Each of the instances of the tweakable hash function take PK.seed as its - * first input, which is constant for a given key pair – and, thus, across - * a single signature. This leads to a lot of redundant computation. To remedy - * this, we pad PK.seed to the length of a full 64-byte SHA-256 input block. - * Because of the Merkle-DamgÃ¥rd construction that underlies SHA-256, this - * allows for reuse of the intermediate SHA-256 state after the initial call to - * the compression function which improves performance. - * - * We pass this hash state around in functions, because otherwise we need to - * have a global variable. - */ - -#include "haraka.h" -#define hash_state harakactx - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/merkle.c b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/merkle.c new file mode 100644 index 0000000000..0c1479fd93 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/merkle.c @@ -0,0 +1,59 @@ +#include +#include + +#include "address.h" +#include "merkle.h" +#include "params.h" +#include "utils.h" +#include "utilsx1.h" +#include "wots.h" +#include "wotsx1.h" + +/* + * This generates a Merkle signature (WOTS signature followed by the Merkle + * authentication path). This is in this file because most of the complexity + * is involved with the WOTS signature; the Merkle authentication path logic + * is mostly hidden in treehashx4 + */ +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf) { + unsigned char *auth_path = sig + SPX_WOTS_BYTES; + struct leaf_info_x1 info = { 0 }; + unsigned steps[ SPX_WOTS_LEN ]; + + info.wots_sig = sig; + chain_lengths(steps, root); + info.wots_steps = steps; + + set_type(&tree_addr[0], SPX_ADDR_TYPE_HASHTREE); + set_type(&info.pk_addr[0], SPX_ADDR_TYPE_WOTSPK); + copy_subtree_addr(&info.leaf_addr[0], wots_addr); + copy_subtree_addr(&info.pk_addr[0], wots_addr); + + info.wots_sign_leaf = idx_leaf; + + treehashx1(root, auth_path, ctx, + idx_leaf, 0, + SPX_TREE_HEIGHT, + wots_gen_leafx1, + tree_addr, &info); +} + +/* Compute root node of the top-most subtree. */ +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { + /* We do not need the auth path in key generation, but it simplifies the + code to have just one treehash routine that computes both root and path + in one function. */ + unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; + uint32_t top_tree_addr[8] = {0}; + uint32_t wots_addr[8] = {0}; + + set_layer_addr(top_tree_addr, SPX_D - 1); + set_layer_addr(wots_addr, SPX_D - 1); + + merkle_sign(auth_path, root, ctx, + wots_addr, top_tree_addr, + (uint32_t)~0 /* ~0 means "don't bother generating an auth path */ ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/merkle.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/merkle.h new file mode 100644 index 0000000000..769cf2e970 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/merkle.h @@ -0,0 +1,21 @@ +#ifndef MERKLE_H_ +#define MERKLE_H_ + +#include + +#include "context.h" +#include "params.h" + +/* Generate a Merkle signature (WOTS signature followed by the Merkle */ +/* authentication path) */ +#define merkle_sign SPX_NAMESPACE(merkle_sign) +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf); + +/* Compute the root node of the top-most subtree. */ +#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); + +#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/nistapi.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/nistapi.h new file mode 100644 index 0000000000..3cb71afad4 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/nistapi.h @@ -0,0 +1,87 @@ +#ifndef SPX_API_H +#define SPX_API_H + +#include +#include + +#include "params.h" + +#define CRYPTO_ALGNAME "SPHINCS+" + +#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES +#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES +#define CRYPTO_BYTES SPX_BYTES +#define CRYPTO_SEEDBYTES (3*SPX_N) + +/* + * Returns the length of a secret key, in bytes + */ +#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) +size_t crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) +size_t crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) +size_t crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) +size_t crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +#define crypto_sign SPX_NAMESPACE(crypto_sign) +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/params.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/params.h index 7601b7ba1c..c17b802b00 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/params.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/params.h @@ -1,53 +1,56 @@ -#ifndef PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_PARAMS_H -#define PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_PARAMS_H +#ifndef SPX_PARAMS_H +#define SPX_PARAMS_H + +#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_##s /* Hash output length in bytes. */ -#define PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_N 24 +#define SPX_N 24 /* Height of the hypertree. */ -#define PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_FULL_HEIGHT 63 +#define SPX_FULL_HEIGHT 63 /* Number of subtree layer. */ -#define PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_D 7 +#define SPX_D 7 /* FORS tree dimensions. */ -#define PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_FORS_HEIGHT 14 -#define PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_FORS_TREES 17 +#define SPX_FORS_HEIGHT 14 +#define SPX_FORS_TREES 17 /* Winternitz parameter, */ -#define PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_WOTS_W 16 +#define SPX_WOTS_W 16 /* The hash function is defined by linking a different hash.c file, as opposed to setting a #define constant. */ /* For clarity */ -#define PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_ADDR_BYTES 32 +#define SPX_ADDR_BYTES 32 /* WOTS parameters. */ -#define PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_WOTS_LOGW 4 +#define SPX_WOTS_LOGW 4 -#define PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_WOTS_LEN1 (8 * PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_N / PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_WOTS_LOGW) +#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) -/* PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#define PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_WOTS_LEN2 3 +/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ +#define SPX_WOTS_LEN2 3 -#define PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_WOTS_LEN (PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_WOTS_LEN1 + PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_WOTS_LEN2) -#define PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_WOTS_BYTES (PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_WOTS_LEN * PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_N) -#define PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_WOTS_PK_BYTES PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_WOTS_BYTES +#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) +#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) +#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES /* Subtree size. */ -#define PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_TREE_HEIGHT (PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_FULL_HEIGHT / PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_D) +#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) + +//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT +// #error SPX_D should always divide SPX_FULL_HEIGHT +//#endif /* FORS parameters. */ -#define PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_FORS_MSG_BYTES ((PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_FORS_TREES + 7) / 8) -#define PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_FORS_BYTES ((PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_FORS_HEIGHT + 1) * PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_FORS_TREES * PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_N) -#define PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_FORS_PK_BYTES PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_N +#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) +#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) +#define SPX_FORS_PK_BYTES SPX_N /* Resulting SPX sizes. */ -#define PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_BYTES (PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_N + PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_FORS_BYTES + PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_D * PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_WOTS_BYTES +\ - PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_FULL_HEIGHT * PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_N) -#define PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_PK_BYTES (2 * PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_N) -#define PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_SK_BYTES (2 * PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_N + PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_PK_BYTES) - -/* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ -#define PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_OPTRAND_BYTES 32 +#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ + SPX_FULL_HEIGHT * SPX_N) +#define SPX_PK_BYTES (2 * SPX_N) +#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) + +#include "haraka_offsets.h" #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/sign.c b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/sign.c index 3f06e1517b..9d0c7d1b22 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/sign.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/sign.c @@ -3,72 +3,43 @@ #include #include "address.h" -#include "api.h" +#include "context.h" #include "fors.h" #include "hash.h" -#include "hash_state.h" +#include "merkle.h" +#include "nistapi.h" #include "params.h" #include "randombytes.h" #include "thash.h" #include "utils.h" #include "wots.h" -/** - * Computes the leaf at a given address. First generates the WOTS key pair, - * then computes leaf by hashing horizontally. - */ -static void wots_gen_leaf(unsigned char *leaf, const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx, const uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - unsigned char pk[PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_WOTS_BYTES]; - uint32_t wots_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_set_type( - wots_addr, PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_set_type( - wots_pk_addr, PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_ADDR_TYPE_WOTSPK); - - PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_set_keypair_addr( - wots_addr, addr_idx); - PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_wots_gen_pk( - pk, sk_seed, pub_seed, wots_addr, hash_state_seeded); - - PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_copy_keypair_addr( - wots_pk_addr, wots_addr); - PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_thash_WOTS_LEN( - leaf, pk, pub_seed, wots_pk_addr, hash_state_seeded); -} - /* * Returns the length of a secret key, in bytes */ -size_t PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_crypto_sign_secretkeybytes(void) { - return PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_CRYPTO_SECRETKEYBYTES; +size_t crypto_sign_secretkeybytes(void) { + return CRYPTO_SECRETKEYBYTES; } /* * Returns the length of a public key, in bytes */ -size_t PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_crypto_sign_publickeybytes(void) { - return PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_CRYPTO_PUBLICKEYBYTES; +size_t crypto_sign_publickeybytes(void) { + return CRYPTO_PUBLICKEYBYTES; } /* * Returns the length of a signature, in bytes */ -size_t PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_crypto_sign_bytes(void) { - return PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_CRYPTO_BYTES; +size_t crypto_sign_bytes(void) { + return CRYPTO_BYTES; } /* * Returns the length of the seed required to generate a key pair, in bytes */ -size_t PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_crypto_sign_seedbytes(void) { - return PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_CRYPTO_SEEDBYTES; +size_t crypto_sign_seedbytes(void) { + return CRYPTO_SEEDBYTES; } /* @@ -76,37 +47,30 @@ size_t PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_crypto_sign_seedbytes(void) { * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] * Format pk: [PUB_SEED || root] */ -int PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed) { - /* We do not need the auth path in key generation, but it simplifies the - code to have just one treehash routine that computes both root and path - in one function. */ - unsigned char auth_path[PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_TREE_HEIGHT * PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_N]; - uint32_t top_tree_addr[8] = {0}; - hash_state hash_state_seeded; - - PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_set_layer_addr( - top_tree_addr, PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_D - 1); - PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_set_type( - top_tree_addr, PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_ADDR_TYPE_HASHTREE); +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed) { + spx_ctx ctx; /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ - memcpy(sk, seed, PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_CRYPTO_SEEDBYTES); + memcpy(sk, seed, CRYPTO_SEEDBYTES); - memcpy(pk, sk + 2 * PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_N, PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_N); + memcpy(pk, sk + 2 * SPX_N, SPX_N); + + memcpy(ctx.pub_seed, pk, SPX_N); + memcpy(ctx.sk_seed, sk, SPX_N); /* This hook allows the hash function instantiation to do whatever preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_initialize_hash_function(&hash_state_seeded, pk, sk); + initialize_hash_function(&ctx); /* Compute root node of the top-most subtree. */ - PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_treehash_TREE_HEIGHT( - sk + 3 * PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_N, auth_path, sk, sk + 2 * PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_N, 0, 0, - wots_gen_leaf, top_tree_addr, &hash_state_seeded); + merkle_gen_root(sk + 3 * SPX_N, &ctx); + + // cleanup + free_hash_function(&ctx); - memcpy(pk + PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_N, sk + 3 * PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_N, PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_N); + memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); - PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_destroy_hash_function(&hash_state_seeded); return 0; } @@ -115,12 +79,10 @@ int PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_crypto_sign_seed_keypair( * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] * Format pk: [PUB_SEED || root] */ -int PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk) { - unsigned char seed[PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_CRYPTO_SEEDBYTES]; - randombytes(seed, PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_CRYPTO_SEEDBYTES); - PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_crypto_sign_seed_keypair( - pk, sk, seed); +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { + uint8_t seed[CRYPTO_SEEDBYTES]; + randombytes(seed, CRYPTO_SEEDBYTES); + crypto_sign_seed_keypair(pk, sk, seed); return 0; } @@ -128,101 +90,83 @@ int PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_crypto_sign_keypair( /** * Returns an array containing a detached signature. */ -int PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - const unsigned char *sk_seed = sk; - const unsigned char *sk_prf = sk + PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_N; - const unsigned char *pk = sk + 2 * PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_N; - const unsigned char *pub_seed = pk; - - unsigned char optrand[PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_N]; - unsigned char mhash[PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_FORS_MSG_BYTES]; - unsigned char root[PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_N]; +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk) { + spx_ctx ctx; + + const uint8_t *sk_prf = sk + SPX_N; + const uint8_t *pk = sk + 2 * SPX_N; + + uint8_t optrand[SPX_N]; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t root[SPX_N]; uint32_t i; uint64_t tree; uint32_t idx_leaf; uint32_t wots_addr[8] = {0}; uint32_t tree_addr[8] = {0}; - hash_state hash_state_seeded; + memcpy(ctx.sk_seed, sk, SPX_N); + memcpy(ctx.pub_seed, pk, SPX_N); /* This hook allows the hash function instantiation to do whatever preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_initialize_hash_function( - &hash_state_seeded, - pub_seed, sk_seed); + initialize_hash_function(&ctx); - PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_set_type( - wots_addr, PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_set_type( - tree_addr, PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_ADDR_TYPE_HASHTREE); + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); /* Optionally, signing can be made non-deterministic using optrand. This can help counter side-channel attacks that would benefit from getting a large number of traces when the signer uses the same nodes. */ - randombytes(optrand, PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_N); + randombytes(optrand, SPX_N); /* Compute the digest randomization value. */ - PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_gen_message_random( - sig, sk_prf, optrand, m, mlen, &hash_state_seeded); + gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); /* Derive the message digest and leaf index from R, PK and M. */ - PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_N; + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; - PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); /* Sign the message hash using FORS. */ - PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_fors_sign( - sig, root, mhash, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_FORS_BYTES; - - for (i = 0; i < PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_D; i++) { - PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_set_tree_addr(tree_addr, tree); - - PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); - - /* Compute a WOTS signature. */ - PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_wots_sign( - sig, root, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_WOTS_BYTES; - - /* Compute the authentication path for the used WOTS leaf. */ - PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_treehash_TREE_HEIGHT( - root, sig, sk_seed, pub_seed, idx_leaf, 0, - wots_gen_leaf, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_TREE_HEIGHT * PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_N; + fors_sign(sig, root, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); + sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_TREE_HEIGHT; + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; } - *siglen = PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_BYTES; + free_hash_function(&ctx); + + *siglen = SPX_BYTES; - PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_destroy_hash_function(&hash_state_seeded); return 0; } /** * Verifies a detached signature and message under a given public key. */ -int PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk) { - const unsigned char *pub_seed = pk; - const unsigned char *pub_root = pk + PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_N; - unsigned char mhash[PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_FORS_MSG_BYTES]; - unsigned char wots_pk[PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_WOTS_BYTES]; - unsigned char root[PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_N]; - unsigned char leaf[PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_N]; +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk) { + spx_ctx ctx; + const uint8_t *pub_root = pk + SPX_N; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t wots_pk[SPX_WOTS_BYTES]; + uint8_t root[SPX_N]; + uint8_t leaf[SPX_N]; unsigned int i; uint64_t tree; uint32_t idx_leaf; @@ -230,78 +174,66 @@ int PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_crypto_sign_verify( uint32_t tree_addr[8] = {0}; uint32_t wots_pk_addr[8] = {0}; - hash_state hash_state_seeded; - - if (siglen != PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_BYTES) { + if (siglen != SPX_BYTES) { return -1; } + memcpy(ctx.pub_seed, pk, SPX_N); + /* This hook allows the hash function instantiation to do whatever preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_initialize_hash_function( - &hash_state_seeded, - pub_seed, NULL); + initialize_hash_function(&ctx); - PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_set_type( - wots_addr, PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_set_type( - tree_addr, PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_ADDR_TYPE_HASHTREE); - PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_set_type( - wots_pk_addr, PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_ADDR_TYPE_WOTSPK); + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); /* Derive the message digest and leaf index from R || PK || M. */ - /* The additional PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_N is a result of the hash domain separator. */ - PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_N; + /* The additional SPX_N is a result of the hash domain separator. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; /* Layer correctly defaults to 0, so no need to set_layer_addr */ - PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); - PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_fors_pk_from_sig( - root, sig, mhash, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_FORS_BYTES; + fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; /* For each subtree.. */ - for (i = 0; i < PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_D; i++) { - PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_set_tree_addr(tree_addr, tree); + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); - PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); - PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_copy_keypair_addr( - wots_pk_addr, wots_addr); + copy_keypair_addr(wots_pk_addr, wots_addr); /* The WOTS public key is only correct if the signature was correct. */ /* Initially, root is the FORS pk, but on subsequent iterations it is the root of the subtree below the currently processed subtree. */ - PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_wots_pk_from_sig( - wots_pk, sig, root, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_WOTS_BYTES; + wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); + sig += SPX_WOTS_BYTES; /* Compute the leaf node using the WOTS public key. */ - PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_thash_WOTS_LEN( - leaf, wots_pk, pub_seed, wots_pk_addr, &hash_state_seeded); + thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); /* Compute the root node of this subtree. */ - PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_compute_root( - root, leaf, idx_leaf, 0, sig, PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_TREE_HEIGHT, - pub_seed, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_TREE_HEIGHT * PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_N; + compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, + &ctx, tree_addr); + sig += SPX_TREE_HEIGHT * SPX_N; /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_TREE_HEIGHT; + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; } - PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_destroy_hash_function(&hash_state_seeded); + // cleanup + free_hash_function(&ctx); + /* Check if the root node equals the root node in the public key. */ - if (memcmp(root, pub_root, PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_N) != 0) { + if (memcmp(root, pub_root, SPX_N) != 0) { return -1; } @@ -312,15 +244,14 @@ int PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_crypto_sign_verify( /** * Returns an array containing the signature followed by the message. */ -int PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk) { size_t siglen; - PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_crypto_sign_signature( - sm, &siglen, m, mlen, sk); + crypto_sign_signature(sm, &siglen, m, mlen, sk); - memmove(sm + PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_BYTES, m, mlen); + memmove(sm + SPX_BYTES, m, mlen); *smlen = siglen + mlen; return 0; @@ -329,28 +260,27 @@ int PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_crypto_sign( /** * Verifies a given signature-message pair under a given public key. */ -int PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk) { +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk) { /* The API caller does not necessarily know what size a signature should be - but SPHINCS+ signatures are always exactly PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_BYTES. */ - if (smlen < PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_BYTES) { + but SPHINCS+ signatures are always exactly SPX_BYTES. */ + if (smlen < SPX_BYTES) { memset(m, 0, smlen); *mlen = 0; return -1; } - *mlen = smlen - PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_BYTES; + *mlen = smlen - SPX_BYTES; - if (PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_crypto_sign_verify( - sm, PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_BYTES, sm + PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_BYTES, *mlen, pk)) { + if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { memset(m, 0, smlen); *mlen = 0; return -1; } /* If verification was successful, move the message to the right place. */ - memmove(m, sm + PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_BYTES, *mlen); + memmove(m, sm + SPX_BYTES, *mlen); return 0; } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/thash.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/thash.h index 66efb5b5e9..8687ccfb4d 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/thash.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/thash.h @@ -1,28 +1,13 @@ -#ifndef PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_THASH_H -#define PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_THASH_H +#ifndef SPX_THASH_H +#define SPX_THASH_H -#include "hash_state.h" +#include "context.h" +#include "params.h" #include -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); +#define thash SPX_NAMESPACE(thash) +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/thash_haraka_simple.c b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/thash_haraka_simple.c index 69dbf5b768..207777bf8d 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/thash_haraka_simple.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/thash_haraka_simple.c @@ -4,80 +4,33 @@ #include "address.h" #include "params.h" #include "thash.h" +#include "utils.h" #include "haraka.h" /** - * Takes an array of inblocks concatenated arrays of PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_N bytes. + * Takes an array of inblocks concatenated arrays of SPX_N bytes. */ -static void PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_thash( - unsigned char *out, unsigned char *buf, - const unsigned char *in, unsigned int inblocks, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]) { + PQCLEAN_VLA(uint8_t, buf, SPX_ADDR_BYTES + inblocks * SPX_N); unsigned char outbuf[32]; unsigned char buf_tmp[64]; - (void)pub_seed; /* Suppress an 'unused parameter' warning. */ - if (inblocks == 1) { /* F function */ - /* Since PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_N may be smaller than 32, we need a temporary buffer. */ + /* Since SPX_N may be smaller than 32, we need a temporary buffer. */ memset(buf_tmp, 0, 64); - PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_addr_to_bytes(buf_tmp, addr); - memcpy(buf_tmp + PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_ADDR_BYTES, in, PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_N); + memcpy(buf_tmp, addr, 32); + memcpy(buf_tmp + SPX_ADDR_BYTES, in, SPX_N); - PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_haraka512(outbuf, buf_tmp, hash_state_seeded); - memcpy(out, outbuf, PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_N); + haraka512(outbuf, buf_tmp, ctx); + memcpy(out, outbuf, SPX_N); } else { /* All other tweakable hashes*/ - PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_addr_to_bytes(buf, addr); - memcpy(buf + PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_ADDR_BYTES, in, inblocks * PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_N); + memcpy(buf, addr, 32); + memcpy(buf + SPX_ADDR_BYTES, in, inblocks * SPX_N); - PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_haraka_S( - out, PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_N, buf, PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_N, hash_state_seeded); + haraka_S(out, SPX_N, buf, SPX_ADDR_BYTES + inblocks * SPX_N, ctx); } } - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_ADDR_BYTES + 1 * PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_N]; - PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_thash( - out, buf, in, 1, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_ADDR_BYTES + 2 * PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_N]; - PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_thash( - out, buf, in, 2, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_ADDR_BYTES + PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_WOTS_LEN * PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_N]; - PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_thash( - out, buf, in, PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_WOTS_LEN, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_ADDR_BYTES + PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_FORS_TREES * PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_N]; - PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_thash( - out, buf, in, PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_FORS_TREES, pub_seed, addr, hash_state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/utils.c b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/utils.c index 06badc487b..177b541fb9 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/utils.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/utils.c @@ -1,34 +1,41 @@ -#include #include +#include "utils.h" + #include "address.h" #include "hash.h" -#include "hash_state.h" #include "params.h" #include "thash.h" -#include "utils.h" /** * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. */ -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in) { +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in) { + int i; /* Iterate over out in decreasing order, for big-endianness. */ - for (size_t i = outlen; i > 0; i--) { - out[i - 1] = in & 0xff; + for (i = (signed int)outlen - 1; i >= 0; i--) { + out[i] = in & 0xff; in = in >> 8; } } +void u32_to_bytes(unsigned char *out, uint32_t in) { + out[0] = (unsigned char)(in >> 24); + out[1] = (unsigned char)(in >> 16); + out[2] = (unsigned char)(in >> 8); + out[3] = (unsigned char)in; +} + /** * Converts the inlen bytes in 'in' from big-endian byte order to an integer. */ -unsigned long long PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_bytes_to_ull( - const unsigned char *in, size_t inlen) { +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { unsigned long long retval = 0; + unsigned int i; - for (size_t i = 0; i < inlen; i++) { + for (i = 0; i < inlen; i++) { retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); } return retval; @@ -38,94 +45,80 @@ unsigned long long PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_bytes_to_ull( * Computes a root node given a leaf and an auth path. * Expects address to be complete other than the tree_height and tree_index. */ -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]) { uint32_t i; - unsigned char buffer[2 * PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_N]; + unsigned char buffer[2 * SPX_N]; /* If leaf_idx is odd (last bit = 1), current path element is a right child and auth_path has to go left. Otherwise it is the other way around. */ if (leaf_idx & 1) { - memcpy(buffer + PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_N, leaf, PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_N); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_N); + memcpy(buffer + SPX_N, leaf, SPX_N); + memcpy(buffer, auth_path, SPX_N); } else { - memcpy(buffer, leaf, PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_N); - memcpy(buffer + PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_N, auth_path, PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_N); + memcpy(buffer, leaf, SPX_N); + memcpy(buffer + SPX_N, auth_path, SPX_N); } - auth_path += PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_N; + auth_path += SPX_N; for (i = 0; i < tree_height - 1; i++) { leaf_idx >>= 1; idx_offset >>= 1; /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_set_tree_height(addr, i + 1); - PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_set_tree_index( - addr, leaf_idx + idx_offset); + set_tree_height(addr, i + 1); + set_tree_index(addr, leaf_idx + idx_offset); /* Pick the right or left neighbor, depending on parity of the node. */ if (leaf_idx & 1) { - PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_thash_2( - buffer + PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_N, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_N); + thash(buffer + SPX_N, buffer, 2, ctx, addr); + memcpy(buffer, auth_path, SPX_N); } else { - PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_thash_2( - buffer, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer + PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_N, auth_path, PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_N); + thash(buffer, buffer, 2, ctx, addr); + memcpy(buffer + SPX_N, auth_path, SPX_N); } - auth_path += PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_N; + auth_path += SPX_N; } /* The last iteration is exceptional; we do not copy an auth_path node. */ leaf_idx >>= 1; idx_offset >>= 1; - PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_set_tree_height(addr, tree_height); - PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_set_tree_index( - addr, leaf_idx + idx_offset); - PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_thash_2( - root, buffer, pub_seed, addr, hash_state_seeded); + set_tree_height(addr, tree_height); + set_tree_index(addr, leaf_idx + idx_offset); + thash(root, buffer, 2, ctx, addr); } /** * For a given leaf index, computes the authentication path and the resulting * root node using Merkle's TreeHash algorithm. * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_ADDR_TYPE_FORSTREE). + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). * Applies the offset idx_offset to indices before building addresses, so that * it is possible to continue counting indices across trees. */ -static void PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_treehash( - unsigned char *root, unsigned char *auth_path, - unsigned char *stack, unsigned int *heights, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - +void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx * /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]) { + PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); + PQCLEAN_VLA(unsigned int, heights, tree_height + 1); unsigned int offset = 0; uint32_t idx; uint32_t tree_idx; for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { /* Add the next leaf node to the stack. */ - gen_leaf(stack + offset * PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_N, - sk_seed, pub_seed, idx + idx_offset, tree_addr, - hash_state_seeded); + gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); offset++; heights[offset - 1] = 0; /* If this is a node we need for the auth path.. */ if ((leaf_idx ^ 0x1) == idx) { - memcpy(auth_path, stack + (offset - 1)*PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_N, PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_N); + memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); } /* While the top-most nodes are of equal height.. */ @@ -134,66 +127,22 @@ static void PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_treehash( tree_idx = (idx >> (heights[offset - 1] + 1)); /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_set_tree_height( - tree_addr, heights[offset - 1] + 1); - PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_set_tree_index( - tree_addr, tree_idx + (idx_offset >> (heights[offset - 1] + 1))); + set_tree_height(tree_addr, heights[offset - 1] + 1); + set_tree_index(tree_addr, + tree_idx + (idx_offset >> (heights[offset - 1] + 1))); /* Hash the top-most nodes from the stack together. */ - PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_thash_2( - stack + (offset - 2)*PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_N, stack + (offset - 2)*PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_N, - pub_seed, tree_addr, hash_state_seeded); + thash(stack + (offset - 2)*SPX_N, + stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); offset--; /* Note that the top-most node is now one layer higher. */ heights[offset - 1]++; /* If this is a node we need for the auth path.. */ if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_path + heights[offset - 1]*PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_N, - stack + (offset - 1)*PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_N, PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_N); + memcpy(auth_path + heights[offset - 1]*SPX_N, + stack + (offset - 1)*SPX_N, SPX_N); } } } - memcpy(root, stack, PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_N); -} - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_FORS_HEIGHT + 1)*PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_N]; - unsigned int heights[PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_FORS_HEIGHT + 1]; - - PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_FORS_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_TREE_HEIGHT + 1)*PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_N]; - unsigned int heights[PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_TREE_HEIGHT + 1]; - - PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_TREE_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); + memcpy(root, stack, SPX_N); } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/utils.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/utils.h index 08d1eff3ae..64f5d5a53a 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/utils.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/utils.h @@ -1,64 +1,58 @@ -#ifndef PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_UTILS_H -#define PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_UTILS_H +#ifndef SPX_UTILS_H +#define SPX_UTILS_H -#include "hash_state.h" -#include "params.h" -#include #include +#include "compat.h" +#include "context.h" +#include "params.h" + + +/* To support MSVC use alloca() instead of VLAs. See #20. */ + + /** * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. */ -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in); +#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in); +#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) +void u32_to_bytes(unsigned char *out, uint32_t in); /** * Converts the inlen bytes in 'in' from big-endian byte order to an integer. */ -unsigned long long PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_bytes_to_ull( - const unsigned char *in, size_t inlen); +#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); /** * Computes a root node given a leaf and an auth path. * Expects address to be complete other than the tree_height and tree_index. */ -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); +#define compute_root SPX_NAMESPACE(compute_root) +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]); /** * For a given leaf index, computes the authentication path and the resulting * root node using Merkle's TreeHash algorithm. * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_ADDR_TYPE_FORSTREE). + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). * Applies the offset idx_offset to indices before building addresses, so that * it is possible to continue counting indices across trees. */ -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); +#define treehash SPX_NAMESPACE(treehash) +void treehash(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx *ctx /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]); -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/utilsx1.c b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/utilsx1.c new file mode 100644 index 0000000000..fccb69b35d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/utilsx1.c @@ -0,0 +1,100 @@ +#include + +#include "utilsx1.h" + +#include "address.h" +#include "params.h" +#include "thash.h" +#include "utils.h" + +/* + * Generate the entire Merkle tree, computing the authentication path for + * leaf_idx, and the resulting root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) + * + * This expects tree_addr to be initialized to the addr structures for the + * Merkle tree nodes + * + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + * + * This works by using the standard Merkle tree building algorithm, + */ +void treehashx1(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, + uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* Where to write the leaves */, + const spx_ctx * /* ctx */, + uint32_t idx, void *info), + uint32_t tree_addr[8], + void *info) { + /* This is where we keep the intermediate nodes */ + PQCLEAN_VLA(uint8_t, stack, tree_height * SPX_N); + + uint32_t idx; + uint32_t max_idx = (uint32_t)((1 << tree_height) - 1); + for (idx = 0;; idx++) { + unsigned char current[2 * SPX_N]; /* Current logical node is at */ + /* index[SPX_N]. We do this to minimize the number of copies */ + /* needed during a thash */ + gen_leaf( ¤t[SPX_N], ctx, idx + idx_offset, + info ); + + /* Now combine the freshly generated right node with previously */ + /* generated left ones */ + uint32_t internal_idx_offset = idx_offset; + uint32_t internal_idx = idx; + uint32_t internal_leaf = leaf_idx; + uint32_t h; /* The height we are in the Merkle tree */ + for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { + + /* Check if we hit the top of the tree */ + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[SPX_N], SPX_N ); + return; + } + + /* + * Check if the node we have is a part of the + * authentication path; if it is, write it out + */ + if ((internal_idx ^ internal_leaf) == 0x01) { + memcpy( &auth_path[ h * SPX_N ], + ¤t[SPX_N], + SPX_N ); + } + + /* + * Check if we're at a left child; if so, stop going up the stack + * Exception: if we've reached the end of the tree, keep on going + * (so we combine the last 4 nodes into the one root node in two + * more iterations) + */ + if ((internal_idx & 1) == 0 && idx < max_idx) { + break; + } + + /* Ok, we're at a right node */ + /* Now combine the left and right logical nodes together */ + + /* Set the address of the node we're creating. */ + internal_idx_offset >>= 1; + set_tree_height(tree_addr, h + 1); + set_tree_index(tree_addr, internal_idx / 2 + internal_idx_offset ); + + unsigned char *left = &stack[h * SPX_N]; + memcpy( ¤t[0], left, SPX_N ); + thash( ¤t[1 * SPX_N], + ¤t[0 * SPX_N], + 2, ctx, tree_addr); + } + + /* We've hit a left child; save the current for when we get the */ + /* corresponding right right */ + memcpy( &stack[h * SPX_N], ¤t[SPX_N], SPX_N); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/utilsx1.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/utilsx1.h new file mode 100644 index 0000000000..e911d17d53 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/utilsx1.h @@ -0,0 +1,27 @@ +#ifndef SPX_UTILSX4_H +#define SPX_UTILSX4_H + +#include + +#include "context.h" +#include "params.h" + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +#define treehashx1 SPX_NAMESPACE(treehashx1) +void treehashx1(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* Where to write the leaf */, + const spx_ctx * /* ctx */, + uint32_t addr_idx, void *info), + uint32_t tree_addrx4[8], void *info); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/wots.c b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/wots.c index e28e546a88..249717aaa8 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/wots.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/wots.c @@ -1,32 +1,20 @@ #include #include +#include "wots.h" +#include "wotsx1.h" + #include "address.h" #include "hash.h" -#include "hash_state.h" #include "params.h" #include "thash.h" #include "utils.h" -#include "wots.h" +#include "utilsx1.h" // TODO clarify address expectations, and make them more uniform. // TODO i.e. do we expect types to be set already? // TODO and do we expect modifications or copies? -/** - * Computes the starting value for a chain, i.e. the secret key. - * Expects the address to be complete up to the chain address. - */ -static void wots_gen_sk(unsigned char *sk, const unsigned char *sk_seed, - uint32_t wots_addr[8], - const hash_state *hash_state_seeded) { - /* Make sure that the hash address is actually zeroed. */ - PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_set_hash_addr(wots_addr, 0); - - /* Generate sk element. */ - PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_prf_addr(sk, sk_seed, wots_addr, hash_state_seeded); -} - /** * Computes the chaining function. * out and in have to be n-byte arrays. @@ -36,18 +24,16 @@ static void wots_gen_sk(unsigned char *sk, const unsigned char *sk_seed, */ static void gen_chain(unsigned char *out, const unsigned char *in, unsigned int start, unsigned int steps, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { + const spx_ctx *ctx, uint32_t addr[8]) { uint32_t i; /* Initialize out with the value at position 'start'. */ - memcpy(out, in, PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_N); + memcpy(out, in, SPX_N); /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_WOTS_W; i++) { - PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_set_hash_addr(addr, i); - PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_thash_1( - out, out, pub_seed, addr, hash_state_seeded); + for (i = start; i < (start + steps) && i < SPX_WOTS_W; i++) { + set_hash_addr(addr, i); + thash(out, out, 1, ctx, addr); } } @@ -56,13 +42,13 @@ static void gen_chain(unsigned char *out, const unsigned char *in, * Interprets an array of bytes as integers in base w. * This only works when log_w is a divisor of 8. */ -static void base_w(unsigned int *output, const size_t out_len, +static void base_w(unsigned int *output, const int out_len, const unsigned char *input) { - size_t in = 0; - size_t out = 0; + int in = 0; + int out = 0; unsigned char total = 0; - unsigned int bits = 0; - size_t consumed; + int bits = 0; + int consumed; for (consumed = 0; consumed < out_len; consumed++) { if (bits == 0) { @@ -70,8 +56,8 @@ static void base_w(unsigned int *output, const size_t out_len, in++; bits += 8; } - bits -= PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_WOTS_LOGW; - output[out] = (unsigned int)((total >> bits) & (PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_WOTS_W - 1)); + bits -= SPX_WOTS_LOGW; + output[out] = (total >> bits) & (SPX_WOTS_W - 1); out++; } } @@ -80,67 +66,25 @@ static void base_w(unsigned int *output, const size_t out_len, static void wots_checksum(unsigned int *csum_base_w, const unsigned int *msg_base_w) { unsigned int csum = 0; - unsigned char csum_bytes[(PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_WOTS_LEN2 * PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_WOTS_LOGW + 7) / 8]; + unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; unsigned int i; /* Compute checksum. */ - for (i = 0; i < PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_WOTS_LEN1; i++) { - csum += PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_WOTS_W - 1 - msg_base_w[i]; + for (i = 0; i < SPX_WOTS_LEN1; i++) { + csum += SPX_WOTS_W - 1 - msg_base_w[i]; } /* Convert checksum to base_w. */ /* Make sure expected empty zero bits are the least significant bits. */ - csum = csum << (8 - ((PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_WOTS_LEN2 * PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_WOTS_LOGW) % 8)); - PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_ull_to_bytes( - csum_bytes, sizeof(csum_bytes), csum); - base_w(csum_base_w, PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_WOTS_LEN2, csum_bytes); + csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); + ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); + base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); } /* Takes a message and derives the matching chain lengths. */ -static void chain_lengths(unsigned int *lengths, const unsigned char *msg) { - base_w(lengths, PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_WOTS_LEN1, msg); - wots_checksum(lengths + PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_WOTS_LEN1, lengths); -} - -/** - * WOTS key generation. Takes a 32 byte sk_seed, expands it to WOTS private key - * elements and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_wots_gen_pk( - unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - uint32_t i; - - for (i = 0; i < PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_WOTS_LEN; i++) { - PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_set_chain_addr(addr, i); - wots_gen_sk(pk + i * PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_N, sk_seed, addr, hash_state_seeded); - gen_chain(pk + i * PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_N, pk + i * PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_N, - 0, PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_WOTS_W - 1, pub_seed, addr, hash_state_seeded); - } -} - -/** - * Takes a n-byte message and the 32-byte sk_see to compute a signature 'sig'. - */ -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_wots_sign( - unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *hash_state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_WOTS_LEN; i++) { - PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_set_chain_addr(addr, i); - wots_gen_sk(sig + i * PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_N, sk_seed, addr, hash_state_seeded); - gen_chain(sig + i * PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_N, sig + i * PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_N, 0, lengths[i], pub_seed, addr, hash_state_seeded); - } +void chain_lengths(unsigned int *lengths, const unsigned char *msg) { + base_w(lengths, SPX_WOTS_LEN1, msg); + wots_checksum(lengths + SPX_WOTS_LEN1, lengths); } /** @@ -148,20 +92,17 @@ void PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_wots_sign( * * Writes the computed public key to 'pk'. */ -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_wots_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_WOTS_LEN]; +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]) { + unsigned int lengths[SPX_WOTS_LEN]; uint32_t i; chain_lengths(lengths, msg); - for (i = 0; i < PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_WOTS_LEN; i++) { - PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_set_chain_addr(addr, i); - gen_chain(pk + i * PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_N, sig + i * PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_N, - lengths[i], PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_WOTS_W - 1 - lengths[i], pub_seed, addr, - hash_state_seeded); + for (i = 0; i < SPX_WOTS_LEN; i++) { + set_chain_addr(addr, i); + gen_chain(pk + i * SPX_N, sig + i * SPX_N, + lengths[i], SPX_WOTS_W - 1 - lengths[i], ctx, addr); } } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/wots.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/wots.h index 9050041bbb..4e7692eeef 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/wots.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/wots.h @@ -1,41 +1,25 @@ -#ifndef PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_WOTS_H -#define PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_WOTS_H +#ifndef SPX_WOTS_H +#define SPX_WOTS_H -#include "hash_state.h" -#include "params.h" #include -/** - * WOTS key generation. Takes a 32 byte seed for the private key, expands it to - * a full WOTS private key and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_wots_gen_pk( - unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -/** - * Takes a n-byte message and the 32-byte seed for the private key to compute a - * signature that is placed at 'sig'. - */ -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_wots_sign( - unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *hash_state_seeded); +#include "context.h" +#include "params.h" /** * Takes a WOTS signature and an n-byte message, computes a WOTS public key. * * Writes the computed public key to 'pk'. */ -void PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_wots_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); +#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]); + +/* + * Compute the chain lengths needed for a given message hash + */ +#define chain_lengths SPX_NAMESPACE(chain_lengths) +void chain_lengths(unsigned int *lengths, const unsigned char *msg); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/wotsx1.c b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/wotsx1.c new file mode 100644 index 0000000000..3adec78dfb --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/wotsx1.c @@ -0,0 +1,76 @@ +#include +#include + +#include "wots.h" +#include "wotsx1.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "thash.h" +#include "utils.h" + +/* + * This generates a WOTS public key + * It also generates the WOTS signature if leaf_info indicates + * that we're signing with this WOTS key + */ +void wots_gen_leafx1(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info) { + struct leaf_info_x1 *info = v_info; + uint32_t *leaf_addr = info->leaf_addr; + uint32_t *pk_addr = info->pk_addr; + unsigned int i, k; + unsigned char pk_buffer[ SPX_WOTS_BYTES ]; + unsigned char *buffer; + uint32_t wots_k_mask; + + if (leaf_idx == info->wots_sign_leaf) { + /* We're traversing the leaf that's signing; generate the WOTS */ + /* signature */ + wots_k_mask = 0; + } else { + /* Nope, we're just generating pk's; turn off the signature logic */ + wots_k_mask = (uint32_t)~0; + } + + set_keypair_addr( leaf_addr, leaf_idx ); + set_keypair_addr( pk_addr, leaf_idx ); + + for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { + uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k to */ + /* the step if we're generating a signature, ~0 if we're not */ + + /* Start with the secret seed */ + set_chain_addr(leaf_addr, i); + set_hash_addr(leaf_addr, 0); + set_type(leaf_addr, SPX_ADDR_TYPE_WOTSPRF); + + prf_addr(buffer, ctx, leaf_addr); + + set_type(leaf_addr, SPX_ADDR_TYPE_WOTS); + + /* Iterate down the WOTS chain */ + for (k = 0;; k++) { + /* Check if this is the value that needs to be saved as a */ + /* part of the WOTS signature */ + if (k == wots_k) { + memcpy( info->wots_sig + i * SPX_N, buffer, SPX_N ); + } + + /* Check if we hit the top of the chain */ + if (k == SPX_WOTS_W - 1) { + break; + } + + /* Iterate one step on the chain */ + set_hash_addr(leaf_addr, k); + + thash(buffer, buffer, 1, ctx, leaf_addr); + } + } + + /* Do the final thash to generate the public keys */ + thash(dest, pk_buffer, SPX_WOTS_LEN, ctx, pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/wotsx1.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/wotsx1.h new file mode 100644 index 0000000000..e617929f96 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/wotsx1.h @@ -0,0 +1,39 @@ +#ifndef WOTSX1_H_ +#define WOTSX1_H_ + +#include + +#include "context.h" +#include "params.h" + +/* + * This is here to provide an interface to the internal wots_gen_leafx1 + * routine. While this routine is not referenced in the package outside of + * wots.c, it is called from the stand-alone benchmark code to characterize + * the performance + */ +struct leaf_info_x1 { + unsigned char *wots_sig; + uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ + uint32_t *wots_steps; + uint32_t leaf_addr[8]; + uint32_t pk_addr[8]; +}; + +/* Macro to set the leaf_info to something 'benign', that is, it would */ +/* run with the same time as it does during the real signing process */ +/* Used only by the benchmark code */ +#define INITIALIZE_LEAF_INFO_X1(info, addr, step_buffer) { \ + (info).wots_sig = 0; \ + (info).wots_sign_leaf = ~0; \ + (info).wots_steps = step_buffer; \ + memcpy( &(info).leaf_addr[0], (addr), 32 ); \ + memcpy( &(info).pk_addr[0], (addr), 32 ); \ + } + +#define wots_gen_leafx1 SPX_NAMESPACE(wots_gen_leafx1) +void wots_gen_leafx1(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info); + +#endif /* WOTSX1_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/address.c b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/address.c index 7b5cf80a57..b956e9cb29 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/address.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/address.c @@ -1,78 +1,91 @@ #include +#include #include "address.h" #include "params.h" #include "utils.h" -void PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]) { - int i; - - for (i = 0; i < 8; i++) { - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_ull_to_bytes( - bytes + i * 4, 4, addr[i]); - } -} - -void PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_set_layer_addr( - uint32_t addr[8], uint32_t layer) { - addr[0] = layer; +/* + * Specify which level of Merkle tree (the "layer") we're working on + */ +void set_layer_addr(uint32_t addr[8], uint32_t layer) { + ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; } -void PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_set_tree_addr( - uint32_t addr[8], uint64_t tree) { - addr[1] = 0; - addr[2] = (uint32_t) (tree >> 32); - addr[3] = (uint32_t) tree; +/* + * Specify which Merkle tree within the level (the "tree address") we're working on + */ +void set_tree_addr(uint32_t addr[8], uint64_t tree) { + ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); } -void PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_set_type( - uint32_t addr[8], uint32_t type) { - addr[4] = type; +/* + * Specify the reason we'll use this address structure for, that is, what + * hash will we compute with it. This is used so that unrelated types of + * hashes don't accidentally get the same address structure. The type will be + * one of the SPX_ADDR_TYPE constants + */ +void set_type(uint32_t addr[8], uint32_t type) { + ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; } -void PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; +/* + * Copy the layer and tree fields of the address structure. This is used + * when we're doing multiple types of hashes within the same Merkle tree + */ +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); } /* These functions are used for OTS addresses. */ -void PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_set_keypair_addr( - uint32_t addr[8], uint32_t keypair) { - addr[5] = keypair; +/* + * Specify which Merkle leaf we're working on; that is, which OTS keypair + * we're talking about. + */ +void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { + ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; } -void PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; - out[5] = in[5]; +/* + * Copy the layer, tree and keypair fields of the address structure. This is + * used when we're doing multiple things within the same OTS keypair + */ +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); + ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; } -void PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_set_chain_addr( - uint32_t addr[8], uint32_t chain) { - addr[6] = chain; +/* + * Specify which Merkle chain within the OTS we're working with + * (the chain address) + */ +void set_chain_addr(uint32_t addr[8], uint32_t chain) { + ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; } -void PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_set_hash_addr( - uint32_t addr[8], uint32_t hash) { - addr[7] = hash; +/* + * Specify where in the Merkle chain we are +* (the hash address) + */ +void set_hash_addr(uint32_t addr[8], uint32_t hash) { + ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; } /* These functions are used for all hash tree addresses (including FORS). */ -void PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_set_tree_height( - uint32_t addr[8], uint32_t tree_height) { - addr[6] = tree_height; +/* + * Specify the height of the node in the Merkle/FORS tree we are in + * (the tree height) + */ +void set_tree_height(uint32_t addr[8], uint32_t tree_height) { + ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; } -void PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_set_tree_index( - uint32_t addr[8], uint32_t tree_index) { - addr[7] = tree_index; +/* + * Specify the distance from the left edge of the node in the Merkle/FORS tree + * (the tree index) + */ +void set_tree_index(uint32_t addr[8], uint32_t tree_index) { + u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/address.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/address.h index b40712ff7e..24a84eb40c 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/address.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/address.h @@ -1,50 +1,52 @@ -#ifndef PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_ADDRESS_H -#define PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_ADDRESS_H +#ifndef SPX_ADDRESS_H +#define SPX_ADDRESS_H #include -#define PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_ADDR_TYPE_WOTS 0 -#define PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_ADDR_TYPE_WOTSPK 1 -#define PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_ADDR_TYPE_HASHTREE 2 -#define PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_ADDR_TYPE_FORSTREE 3 -#define PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_ADDR_TYPE_FORSPK 4 +#include "params.h" -void PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]); +/* The hash types that are passed to set_type */ +#define SPX_ADDR_TYPE_WOTS 0 +#define SPX_ADDR_TYPE_WOTSPK 1 +#define SPX_ADDR_TYPE_HASHTREE 2 +#define SPX_ADDR_TYPE_FORSTREE 3 +#define SPX_ADDR_TYPE_FORSPK 4 +#define SPX_ADDR_TYPE_WOTSPRF 5 +#define SPX_ADDR_TYPE_FORSPRF 6 -void PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_set_layer_addr( - uint32_t addr[8], uint32_t layer); +#define set_layer_addr SPX_NAMESPACE(set_layer_addr) +void set_layer_addr(uint32_t addr[8], uint32_t layer); -void PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_set_tree_addr( - uint32_t addr[8], uint64_t tree); +#define set_tree_addr SPX_NAMESPACE(set_tree_addr) +void set_tree_addr(uint32_t addr[8], uint64_t tree); -void PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_set_type( - uint32_t addr[8], uint32_t type); +#define set_type SPX_NAMESPACE(set_type) +void set_type(uint32_t addr[8], uint32_t type); /* Copies the layer and tree part of one address into the other */ -void PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]); +#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); /* These functions are used for WOTS and FORS addresses. */ -void PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_set_keypair_addr( - uint32_t addr[8], uint32_t keypair); +#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) +void set_keypair_addr(uint32_t addr[8], uint32_t keypair); -void PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_set_chain_addr( - uint32_t addr[8], uint32_t chain); +#define set_chain_addr SPX_NAMESPACE(set_chain_addr) +void set_chain_addr(uint32_t addr[8], uint32_t chain); -void PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_set_hash_addr( - uint32_t addr[8], uint32_t hash); +#define set_hash_addr SPX_NAMESPACE(set_hash_addr) +void set_hash_addr(uint32_t addr[8], uint32_t hash); -void PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]); +#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); /* These functions are used for all hash tree addresses (including FORS). */ -void PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_set_tree_height( - uint32_t addr[8], uint32_t tree_height); +#define set_tree_height SPX_NAMESPACE(set_tree_height) +void set_tree_height(uint32_t addr[8], uint32_t tree_height); -void PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_set_tree_index( - uint32_t addr[8], uint32_t tree_index); +#define set_tree_index SPX_NAMESPACE(set_tree_index) +void set_tree_index(uint32_t addr[8], uint32_t tree_index); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/api.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/api.h index ad341ab6e7..01aa8ffd25 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/api.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/api.h @@ -4,15 +4,13 @@ #include #include - - -#define PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_CRYPTO_ALGNAME "SPHINCS+" +#define PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_CRYPTO_ALGNAME "SPHINCS+-haraka-256f-robust" #define PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_CRYPTO_SECRETKEYBYTES 128 #define PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_CRYPTO_PUBLICKEYBYTES 64 -#define PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_CRYPTO_BYTES 49856 -#define PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_CRYPTO_SEEDBYTES 96 +#define PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_CRYPTO_BYTES 49856 +#define PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_CRYPTO_SEEDBYTES 96 /* * Returns the length of a secret key, in bytes @@ -39,43 +37,41 @@ size_t PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_crypto_sign_seedbytes(void); * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] * Format pk: [root || PUB_SEED] */ -int PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed); +int PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); /* * Generates a SPHINCS+ key pair. * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] * Format pk: [root || PUB_SEED] */ -int PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk); +int PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); /** * Returns an array containing a detached signature. */ -int PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk); +int PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); /** * Verifies a detached signature and message under a given public key. */ -int PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk); +int PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, + const uint8_t *pk); /** * Returns an array containing the signature followed by the message. */ -int PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk); +int PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); /** * Verifies a given signature-message pair under a given public key. */ -int PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk); - +int PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/context.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/context.h new file mode 100644 index 0000000000..f03446b9cb --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/context.h @@ -0,0 +1,22 @@ +#ifndef SPX_CONTEXT_H +#define SPX_CONTEXT_H + +#include + +#include "immintrin.h" +#include "params.h" + +typedef struct { + uint8_t pub_seed[SPX_N]; + uint8_t sk_seed[SPX_N]; + + __m128i rc[40]; +} spx_ctx; + +#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) +void initialize_hash_function(spx_ctx *ctx); + +#define free_hash_function SPX_NAMESPACE(free_hash_function) +void free_hash_function(spx_ctx *ctx); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/context_haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/context_haraka.c new file mode 100644 index 0000000000..f1cd7e3664 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/context_haraka.c @@ -0,0 +1,11 @@ +#include "context.h" +#include "haraka.h" + +void initialize_hash_function(spx_ctx *ctx) { + tweak_constants(ctx); +} + +// we don't support heap-based haraka right now +void free_hash_function(spx_ctx *ctx) { + (void)ctx; // suppress unused variable warnings +} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/fors.c b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/fors.c index 68e83f323f..f1b0639cfc 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/fors.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/fors.c @@ -2,8 +2,9 @@ #include #include -#include "address.h" #include "fors.h" + +#include "address.h" #include "hash.h" #include "hashx4.h" #include "thash.h" @@ -11,19 +12,24 @@ #include "utils.h" #include "utilsx4.h" +static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + prf_addr(sk, ctx, fors_leaf_addr); +} + static void fors_gen_skx4(unsigned char *sk0, unsigned char *sk1, unsigned char *sk2, - unsigned char *sk3, const unsigned char *sk_seed, - uint32_t fors_leaf_addrx4[4 * 8], - const hash_state *state_seeded) { - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_prf_addrx4(sk0, sk1, sk2, sk3, sk_seed, fors_leaf_addrx4, state_seeded); + unsigned char *sk3, const spx_ctx *ctx, + uint32_t fors_leaf_addrx4[4 * 8]) { + prf_addrx4(sk0, sk1, sk2, sk3, + ctx, fors_leaf_addrx4); } static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, - const unsigned char *pub_seed, - uint32_t fors_leaf_addr[8], const hash_state *state_seeded) { - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_thash_1(leaf, sk, pub_seed, fors_leaf_addr, state_seeded); + const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + thash(leaf, sk, 1, ctx, fors_leaf_addr); } static void fors_sk_to_leafx4(unsigned char *leaf0, @@ -34,57 +40,64 @@ static void fors_sk_to_leafx4(unsigned char *leaf0, const unsigned char *sk1, const unsigned char *sk2, const unsigned char *sk3, - const unsigned char *pub_seed, - uint32_t fors_leaf_addrx4[4 * 8], - const hash_state *state_seeded) { - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_thashx4_1(leaf0, leaf1, leaf2, leaf3, - sk0, sk1, sk2, sk3, pub_seed, fors_leaf_addrx4, state_seeded); + const spx_ctx *ctx, + uint32_t fors_leaf_addrx4[4 * 8]) { + thashx4(leaf0, leaf1, leaf2, leaf3, + sk0, sk1, sk2, sk3, + 1, ctx, fors_leaf_addrx4); } -static void fors_gen_leafx4(unsigned char *leaf0, - unsigned char *leaf1, - unsigned char *leaf2, - unsigned char *leaf3, - const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx0, - uint32_t addr_idx1, - uint32_t addr_idx2, - uint32_t addr_idx3, - const uint32_t fors_tree_addr[8], - const hash_state *state_seeded) { - uint32_t fors_leaf_addrx4[4 * 8] = {0}; +struct fors_gen_leaf_info { + uint32_t leaf_addrx[4 * 8]; +}; + +static void fors_gen_leafx4(unsigned char *leaf, + const spx_ctx *ctx, + uint32_t addr_idx, void *info) { + struct fors_gen_leaf_info *fors_info = info; + uint32_t *fors_leaf_addrx4 = fors_info->leaf_addrx; unsigned int j; - /* Only copy the parts that must be kept in fors_leaf_addrx4. */ + /* Only set the parts that the caller doesn't set */ for (j = 0; j < 4; j++) { - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_copy_keypair_addr(fors_leaf_addrx4 + j * 8, fors_tree_addr); - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_set_type(fors_leaf_addrx4 + j * 8, PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_ADDR_TYPE_FORSTREE); + set_tree_index(fors_leaf_addrx4 + j * 8, addr_idx + j); + set_type(fors_leaf_addrx4 + j * 8, SPX_ADDR_TYPE_FORSPRF); } - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_set_tree_index(fors_leaf_addrx4 + 0 * 8, addr_idx0); - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_set_tree_index(fors_leaf_addrx4 + 1 * 8, addr_idx1); - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_set_tree_index(fors_leaf_addrx4 + 2 * 8, addr_idx2); - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_set_tree_index(fors_leaf_addrx4 + 3 * 8, addr_idx3); + fors_gen_skx4(leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + leaf + 2 * SPX_N, + leaf + 3 * SPX_N, + ctx, fors_leaf_addrx4); + + for (j = 0; j < 4; j++) { + set_type(fors_leaf_addrx4 + j * 8, SPX_ADDR_TYPE_FORSTREE); + } - fors_gen_skx4(leaf0, leaf1, leaf2, leaf3, sk_seed, fors_leaf_addrx4, state_seeded); - fors_sk_to_leafx4(leaf0, leaf1, leaf2, leaf3, - leaf0, leaf1, leaf2, leaf3, pub_seed, fors_leaf_addrx4, state_seeded); + fors_sk_to_leafx4(leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + leaf + 2 * SPX_N, + leaf + 3 * SPX_N, + leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + leaf + 2 * SPX_N, + leaf + 3 * SPX_N, + ctx, fors_leaf_addrx4); } /** - * Interprets m as PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_FORS_HEIGHT-bit unsigned integers. - * Assumes m contains at least PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_FORS_TREES bits. - * Assumes indices has space for PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_FORS_TREES integers. + * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + * Assumes indices has space for SPX_FORS_TREES integers. */ static void message_to_indices(uint32_t *indices, const unsigned char *m) { unsigned int i, j; unsigned int offset = 0; - for (i = 0; i < PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_FORS_TREES; i++) { + for (i = 0; i < SPX_FORS_TREES; i++) { indices[i] = 0; - for (j = 0; j < PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_FORS_HEIGHT; j++) { - indices[i] ^= (((uint32_t)m[offset >> 3] >> (offset & 0x7)) & 0x1) << j; + for (j = 0; j < SPX_FORS_HEIGHT; j++) { + indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); offset++; } } @@ -92,68 +105,53 @@ static void message_to_indices(uint32_t *indices, const unsigned char *m) { /** * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_FORS_TREES bits. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. */ -void PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *state_seeded) { - /* Round up to multiple of 4 to prevent out-of-bounds for x4 parallelism */ - uint32_t indices[(PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_FORS_TREES + 3) & ~3] = {0}; - unsigned char roots[((PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_FORS_TREES + 3) & ~3) * PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N]; - /* Sign to a buffer, since we may not have a nice multiple of 4 and would - otherwise overrun the signature. */ - unsigned char sigbufx4[4 * PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N * (1 + PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_FORS_HEIGHT)]; - uint32_t fors_tree_addrx4[4 * 8] = {0}; +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + uint32_t fors_tree_addr[4 * 8] = {0}; + struct fors_gen_leaf_info fors_info = {0}; + uint32_t *fors_leaf_addr = fors_info.leaf_addrx; uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset[4] = {0}; - unsigned int i, j; + uint32_t idx_offset; + unsigned int i; - for (j = 0; j < 4; j++) { - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_copy_keypair_addr(fors_tree_addrx4 + j * 8, fors_addr); - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_set_type(fors_tree_addrx4 + j * 8, PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_ADDR_TYPE_FORSTREE); + for (i = 0; i < 4; i++) { + copy_keypair_addr(fors_tree_addr + 8 * i, fors_addr); + set_type(fors_tree_addr + 8 * i, SPX_ADDR_TYPE_FORSTREE); + copy_keypair_addr(fors_leaf_addr + 8 * i, fors_addr); } - - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_copy_keypair_addr(fors_pk_addr, fors_addr); - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_set_type(fors_pk_addr, PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_ADDR_TYPE_FORSPK); + copy_keypair_addr(fors_pk_addr, fors_addr); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); message_to_indices(indices, m); - for (i = 0; i < ((PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_FORS_TREES + 3) & ~0x3); i += 4) { - for (j = 0; j < 4; j++) { - if (i + j < PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_FORS_TREES) { - idx_offset[j] = (i + j) * (1 << PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_FORS_HEIGHT); + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_set_tree_height(fors_tree_addrx4 + j * 8, 0); - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_set_tree_index(fors_tree_addrx4 + j * 8, - indices[i + j] + idx_offset[j]); - } - } + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); - /* Include the secret key part that produces the selected leaf nodes. */ - fors_gen_skx4(sigbufx4 + 0 * PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N, - sigbufx4 + 1 * PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N, - sigbufx4 + 2 * PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N, - sigbufx4 + 3 * PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N, - sk_seed, fors_tree_addrx4, state_seeded); - - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_treehashx4_FORS_HEIGHT(roots + i * PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N, sigbufx4 + 4 * PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N, sk_seed, pub_seed, - &indices[i], idx_offset, fors_gen_leafx4, fors_tree_addrx4, - state_seeded); - - for (j = 0; j < 4; j++) { - if (i + j < PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_FORS_TREES) { - memcpy(sig, sigbufx4 + j * PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N, PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N); - memcpy(sig + PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N, - sigbufx4 + 4 * PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N + j * PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N * PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_FORS_HEIGHT, - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N * PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_FORS_HEIGHT); - sig += PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N * (1 + PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_FORS_HEIGHT); - } - } + /* Include the secret key part that produces the selected leaf node. */ + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); + fors_gen_sk(sig, ctx, fors_tree_addr); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + sig += SPX_N; + + /* Compute the authentication path for this leaf node. */ + treehashx4(roots + i * SPX_N, sig, ctx, + indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx4, + fors_tree_addr, &fors_info); + + sig += SPX_N * SPX_FORS_HEIGHT; } /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_thash_FORS_TREES(pk, roots, pub_seed, fors_pk_addr, state_seeded); + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); } /** @@ -161,46 +159,44 @@ void PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_fors_sign(unsigned char *sig, unsigne * This can be used for verification by comparing to a known public key, or to * subsequently verify a signature on the derived public key. The latter is the * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_FORS_TREES bits. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. */ -void PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, - const uint32_t fors_addr[8], - const hash_state *state_seeded) { - uint32_t indices[PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_FORS_TREES]; - unsigned char roots[PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_FORS_TREES * PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N]; - unsigned char leaf[PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N]; +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + unsigned char leaf[SPX_N]; uint32_t fors_tree_addr[8] = {0}; uint32_t fors_pk_addr[8] = {0}; uint32_t idx_offset; unsigned int i; - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_copy_keypair_addr(fors_tree_addr, fors_addr); - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_copy_keypair_addr(fors_pk_addr, fors_addr); + copy_keypair_addr(fors_tree_addr, fors_addr); + copy_keypair_addr(fors_pk_addr, fors_addr); - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_set_type(fors_tree_addr, PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_set_type(fors_pk_addr, PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_ADDR_TYPE_FORSPK); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); message_to_indices(indices, m); - for (i = 0; i < PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_FORS_TREES; i++) { - idx_offset = i * (1 << PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_FORS_HEIGHT); + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_set_tree_height(fors_tree_addr, 0); - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_set_tree_index(fors_tree_addr, indices[i] + idx_offset); + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); /* Derive the leaf from the included secret key part. */ - fors_sk_to_leaf(leaf, sig, pub_seed, fors_tree_addr, state_seeded); - sig += PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N; + fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); + sig += SPX_N; /* Derive the corresponding root node of this tree. */ - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_compute_root(roots + i * PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N, leaf, indices[i], idx_offset, - sig, PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_FORS_HEIGHT, pub_seed, fors_tree_addr, - state_seeded); - sig += PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N * PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_FORS_HEIGHT; + compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, + sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); + sig += SPX_N * SPX_FORS_HEIGHT; } /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_thash_FORS_TREES(pk, roots, pub_seed, fors_pk_addr, state_seeded); + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/fors.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/fors.h index 197c1bde93..509140a178 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/fors.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/fors.h @@ -1,32 +1,32 @@ -#ifndef PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_FORS_H -#define PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_FORS_H +#ifndef SPX_FORS_H +#define SPX_FORS_H #include -#include "hash_state.h" +#include "context.h" #include "params.h" /** * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_FORS_TREES bits. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. */ -void PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_fors_sign( - unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *hash_state_seeded); +#define fors_sign SPX_NAMESPACE(fors_sign) +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); /** * Derives the FORS public key from a signature. * This can be used for verification by comparing to a known public key, or to * subsequently verify a signature on the derived public key. The latter is the * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_FORS_TREES bits. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. */ -void PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_fors_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, const uint32_t fors_addr[8], - const hash_state *hash_state_seeded); +#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/haraka.c index 52f0b191ae..b414b691d7 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/haraka.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/haraka.c @@ -8,10 +8,12 @@ Plain C implementation of the Haraka256 and Haraka512 permutations. #include #include "haraka.h" +#include "harakax4.h" +#include "utils.h" #define HARAKAS_RATE 32 -#define u64 uint64_t +#define u64 unsigned long #define u128 __m128i #define LOAD(src) _mm_loadu_si128((u128 *)(src)) @@ -20,7 +22,7 @@ Plain C implementation of the Haraka256 and Haraka512 permutations. #define XOR128(a, b) _mm_xor_si128(a, b) #define AES2(s0, s1, rci) \ - (s0) = _mm_aesenc_si128(s0, *(rci)); \ + s0 = _mm_aesenc_si128(s0, *(rci)); \ (s1) = _mm_aesenc_si128(s1, *((rci) + 1)); \ (s0) = _mm_aesenc_si128(s0, *((rci) + 2)); \ (s1) = _mm_aesenc_si128(s1, *((rci) + 3)); @@ -32,7 +34,7 @@ Plain C implementation of the Haraka256 and Haraka512 permutations. AES2((s3)[0], (s3)[1], rci); #define AES4(s0, s1, s2, s3, rci) \ - (s0) = _mm_aesenc_si128(s0, *(rci)); \ + s0 = _mm_aesenc_si128(s0, *(rci)); \ (s1) = _mm_aesenc_si128(s1, *((rci) + 1)); \ (s2) = _mm_aesenc_si128(s2, *((rci) + 2)); \ (s3) = _mm_aesenc_si128(s3, *((rci) + 3)); \ @@ -68,17 +70,17 @@ Plain C implementation of the Haraka256 and Haraka512 permutations. _mm_storeu_si128((u128 *)((out) + 16), \ _mm_castpd_si128(_mm_shuffle_pd(_mm_castsi128_pd(s2), _mm_castsi128_pd(s3), 0))); -static void load_haraka_constants(u128 rc[40]) { - rc[ 0] = _mm_set_epi32((int)0x0684704c, (int)0xe620c00a, (int)0xb2c5fef0, (int)0x75817b9d); - rc[ 1] = _mm_set_epi32((int)0x8b66b4e1, (int)0x88f3a06b, (int)0x640f6ba4, (int)0x2f08f717); - rc[ 2] = _mm_set_epi32((int)0x3402de2d, (int)0x53f28498, (int)0xcf029d60, (int)0x9f029114); - rc[ 3] = _mm_set_epi32((int)0x0ed6eae6, (int)0x2e7b4f08, (int)0xbbf3bcaf, (int)0xfd5b4f79); - rc[ 4] = _mm_set_epi32((int)0xcbcfb0cb, (int)0x4872448b, (int)0x79eecd1c, (int)0xbe397044); - rc[ 5] = _mm_set_epi32((int)0x7eeacdee, (int)0x6e9032b7, (int)0x8d5335ed, (int)0x2b8a057b); - rc[ 6] = _mm_set_epi32((int)0x67c28f43, (int)0x5e2e7cd0, (int)0xe2412761, (int)0xda4fef1b); - rc[ 7] = _mm_set_epi32((int)0x2924d9b0, (int)0xafcacc07, (int)0x675ffde2, (int)0x1fc70b3b); - rc[ 8] = _mm_set_epi32((int)0xab4d63f1, (int)0xe6867fe9, (int)0xecdb8fca, (int)0xb9d465ee); - rc[ 9] = _mm_set_epi32((int)0x1c30bf84, (int)0xd4b7cd64, (int)0x5b2a404f, (int)0xad037e33); +static void load_haraka_constants(u128 *rc) { + rc[0] = _mm_set_epi32((int)0x0684704c, (int)0xe620c00a, (int)0xb2c5fef0, (int)0x75817b9d); + rc[1] = _mm_set_epi32((int)0x8b66b4e1, (int)0x88f3a06b, (int)0x640f6ba4, (int)0x2f08f717); + rc[2] = _mm_set_epi32((int)0x3402de2d, (int)0x53f28498, (int)0xcf029d60, (int)0x9f029114); + rc[3] = _mm_set_epi32((int)0x0ed6eae6, (int)0x2e7b4f08, (int)0xbbf3bcaf, (int)0xfd5b4f79); + rc[4] = _mm_set_epi32((int)0xcbcfb0cb, (int)0x4872448b, (int)0x79eecd1c, (int)0xbe397044); + rc[5] = _mm_set_epi32((int)0x7eeacdee, (int)0x6e9032b7, (int)0x8d5335ed, (int)0x2b8a057b); + rc[6] = _mm_set_epi32((int)0x67c28f43, (int)0x5e2e7cd0, (int)0xe2412761, (int)0xda4fef1b); + rc[7] = _mm_set_epi32((int)0x2924d9b0, (int)0xafcacc07, (int)0x675ffde2, (int)0x1fc70b3b); + rc[8] = _mm_set_epi32((int)0xab4d63f1, (int)0xe6867fe9, (int)0xecdb8fca, (int)0xb9d465ee); + rc[9] = _mm_set_epi32((int)0x1c30bf84, (int)0xd4b7cd64, (int)0x5b2a404f, (int)0xad037e33); rc[10] = _mm_set_epi32((int)0xb2cc0bb9, (int)0x941723bf, (int)0x69028b2e, (int)0x8df69800); rc[11] = _mm_set_epi32((int)0xfa0478a6, (int)0xde6f5572, (int)0x4aaa9ec8, (int)0x5c9d2d8a); rc[12] = _mm_set_epi32((int)0xdfb49f2b, (int)0x6b772a12, (int)0x0efa4f2e, (int)0x29129fd4); @@ -111,77 +113,65 @@ static void load_haraka_constants(u128 rc[40]) { rc[39] = _mm_set_epi32((int)0x756acc03, (int)0x02288288, (int)0x4ad6bdfd, (int)0xe9c59da1); } -void PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_tweak_constants( - harakactx *state, - const unsigned char *pk_seed, const unsigned char *sk_seed, - unsigned long long seed_length) { +void tweak_constants(spx_ctx *ctx) { int i; unsigned char buf[40 * 16]; /* Use the standard constants to generate tweaked ones. */ - load_haraka_constants(state->rc); - - /* Constants for sk.seed */ - if (sk_seed != NULL) { - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_haraka_S(buf, 40 * 16, sk_seed, seed_length, state); - /* Tweak constants with the pub_seed */ - for (i = 0; i < 40; i++) { - state->rc_sseed[i] = LOAD(buf + i * 16); - } - } + load_haraka_constants(ctx->rc); /* Constants for pk.seed */ - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_haraka_S(buf, 40 * 16, pk_seed, seed_length, state); + haraka_S(buf, 40 * 16, ctx->pub_seed, SPX_N, ctx); /* Tweak constants with the pub_seed */ for (i = 0; i < 40; i++) { - state->rc[i] = LOAD(buf + i * 16); + ctx->rc[i] = LOAD(buf + i * 16); } } -static void haraka_S_absorb(unsigned char *s, +static void haraka_S_absorb(unsigned char *s, unsigned int r, const unsigned char *m, unsigned long long mlen, - unsigned char p, - const harakactx *state) { + unsigned char p, const spx_ctx *ctx) { unsigned long long i; - unsigned char t[HARAKAS_RATE]; + PQCLEAN_VLA(unsigned char, t, r); - while (mlen >= HARAKAS_RATE) { + while (mlen >= r) { // XOR block to state STORE(s, XOR128(LOAD(s), LOAD(m))); STORE(s + 16, XOR128(LOAD(s + 16), LOAD(m + 16))); - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_haraka512_perm(s, s, state); - mlen -= HARAKAS_RATE; - m += HARAKAS_RATE; + haraka512_perm(s, s, ctx); + mlen -= r; + m += r; } - for (i = 0; i < HARAKAS_RATE; ++i) { + for (i = 0; i < r; ++i) { t[i] = 0; } for (i = 0; i < mlen; ++i) { t[i] = m[i]; } t[i] = p; - t[HARAKAS_RATE - 1] |= 128; + t[r - 1] |= 128; STORE(s, XOR128(LOAD(s), LOAD(t))); STORE(s + 16, XOR128(LOAD(s + 16), LOAD(t + 16))); } static void haraka_S_absorb4x(unsigned char *s, + unsigned int r, const unsigned char *m0, const unsigned char *m1, const unsigned char *m2, const unsigned char *m3, unsigned long long int mlen, unsigned char p, - const harakactx *state) { + const spx_ctx *ctx) { unsigned long long i; - unsigned char t0[HARAKAS_RATE]; - unsigned char t1[HARAKAS_RATE]; - unsigned char t2[HARAKAS_RATE]; - unsigned char t3[HARAKAS_RATE]; + PQCLEAN_VLA(unsigned char, t0, r); + PQCLEAN_VLA(unsigned char, t1, r); + PQCLEAN_VLA(unsigned char, t2, r); + PQCLEAN_VLA(unsigned char, t3, r); - while (mlen >= HARAKAS_RATE) { + while (mlen >= r) { // XOR block to state STORE(s, XOR128(LOAD(s), LOAD(m0))); STORE(s + 16, XOR128(LOAD(s + 16), LOAD(m0 + 16))); @@ -192,15 +182,15 @@ static void haraka_S_absorb4x(unsigned char *s, STORE(s + 192, XOR128(LOAD(s + 192), LOAD(m3))); STORE(s + 208, XOR128(LOAD(s + 208), LOAD(m3 + 16))); - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_haraka512_perm_x4(s, s, state); - mlen -= HARAKAS_RATE; - m0 += HARAKAS_RATE; - m1 += HARAKAS_RATE; - m2 += HARAKAS_RATE; - m3 += HARAKAS_RATE; + haraka512_perm_x4(s, s, ctx); + mlen -= r; + m0 += r; + m1 += r; + m2 += r; + m3 += r; } - for (i = 0; i < HARAKAS_RATE; ++i) { + for (i = 0; i < r; ++i) { t0[i] = 0; t1[i] = 0; t2[i] = 0; @@ -218,10 +208,10 @@ static void haraka_S_absorb4x(unsigned char *s, t2[i] = p; t3[i] = p; - t0[HARAKAS_RATE - 1] |= 128; - t1[HARAKAS_RATE - 1] |= 128; - t2[HARAKAS_RATE - 1] |= 128; - t3[HARAKAS_RATE - 1] |= 128; + t0[r - 1] |= 128; + t1[r - 1] |= 128; + t2[r - 1] |= 128; + t3[r - 1] |= 128; STORE(s, XOR128(LOAD(s), LOAD(t0))); STORE(s + 16, XOR128(LOAD(s + 16), LOAD(t0 + 16))); @@ -234,9 +224,10 @@ static void haraka_S_absorb4x(unsigned char *s, } static void haraka_S_squeezeblocks(unsigned char *h, unsigned long long nblocks, - unsigned char *s, unsigned int r, const harakactx *state) { + unsigned char *s, unsigned int r, + const spx_ctx *ctx) { while (nblocks > 0) { - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_haraka512_perm(s, s, state); + haraka512_perm(s, s, ctx); STORE(h, LOAD(s)); STORE(h + 16, LOAD(s + 16)); h += r; @@ -251,9 +242,9 @@ static void haraka_S_squeezeblocks4x(unsigned char *h0, unsigned long long nblocks, unsigned char *s, unsigned int r, - const harakactx *state) { + const spx_ctx *ctx) { while (nblocks > 0) { - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_haraka512_perm_x4(s, s, state); + haraka512_perm_x4(s, s, ctx); STORE(h0, LOAD(s)); STORE(h0 + 16, LOAD(s + 16)); STORE(h1, LOAD(s + 64)); @@ -270,7 +261,7 @@ static void haraka_S_squeezeblocks4x(unsigned char *h0, } } -void PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_haraka_S_inc_init(uint8_t *s_inc) { +void haraka_S_inc_init(uint8_t *s_inc) { size_t i; for (i = 0; i < 64; i++) { @@ -279,7 +270,8 @@ void PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_haraka_S_inc_init(uint8_t *s_inc) { s_inc[64] = 0; } -void PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, const harakactx *state) { +void haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, + const spx_ctx *ctx) { size_t i; /* Recall that s_inc[64] is the non-absorbed bytes xored into the state */ @@ -293,16 +285,16 @@ void PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_haraka_S_inc_absorb(uint8_t *s_inc, c m += HARAKAS_RATE - s_inc[64]; s_inc[64] = 0; - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_haraka512_perm(s_inc, s_inc, state); + haraka512_perm(s_inc, s_inc, ctx); } for (i = 0; i < mlen; i++) { s_inc[s_inc[64] + i] ^= m[i]; } - s_inc[64] = (uint8_t)(s_inc[64] + mlen); + s_inc[64] += (uint8_t)mlen; } -void PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_haraka_S_inc_finalize(uint8_t *s_inc) { +void haraka_S_inc_finalize(uint8_t *s_inc) { /* After haraka_S_inc_absorb, we are guaranteed that s_inc[64] < HARAKAS_RATE, so we can always use one more byte for p in the current state. */ s_inc[s_inc[64]] ^= 0x1F; @@ -310,22 +302,23 @@ void PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_haraka_S_inc_finalize(uint8_t *s_inc) s_inc[64] = 0; } -void PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, const harakactx *state) { +void haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, + const spx_ctx *ctx) { size_t i; /* First consume any bytes we still have sitting around */ for (i = 0; i < outlen && i < s_inc[64]; i++) { /* There are s_inc[64] bytes left, so r - s_inc[64] is the first available byte. We consume from there, i.e., up to r. */ - out[i] = (uint8_t)s_inc[(HARAKAS_RATE - s_inc[64] + (uint8_t)i)]; + out[i] = (uint8_t)s_inc[(HARAKAS_RATE - s_inc[64] + i)]; } out += i; outlen -= i; - s_inc[64] = (uint8_t)(s_inc[64] - i); + s_inc[64] -= (uint8_t)i; /* Then squeeze the remaining necessary blocks */ while (outlen > 0) { - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_haraka512_perm(s_inc, s_inc, state); + haraka512_perm(s_inc, s_inc, ctx); for (i = 0; i < outlen && i < HARAKAS_RATE; i++) { out[i] = s_inc[i]; @@ -336,8 +329,9 @@ void PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_haraka_S_inc_squeeze(uint8_t *out, si } } -void PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_haraka_S(unsigned char *out, unsigned long long outlen, - const unsigned char *in, unsigned long long inlen, const harakactx *state) { +void haraka_S(unsigned char *out, unsigned long long outlen, + const unsigned char *in, unsigned long long inlen, + const spx_ctx *ctx) { unsigned long long i; unsigned char s[64]; unsigned char d[32]; @@ -345,30 +339,30 @@ void PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_haraka_S(unsigned char *out, unsigned for (i = 0; i < 64; i++) { s[i] = 0; } - haraka_S_absorb(s, in, inlen, 0x1F, state); + haraka_S_absorb(s, HARAKAS_RATE, in, inlen, 0x1F, ctx); - haraka_S_squeezeblocks(out, outlen / HARAKAS_RATE, s, HARAKAS_RATE, state); + haraka_S_squeezeblocks(out, outlen / HARAKAS_RATE, s, HARAKAS_RATE, ctx); out += (outlen / HARAKAS_RATE) * HARAKAS_RATE; if (outlen % HARAKAS_RATE) { - haraka_S_squeezeblocks(d, 1, s, HARAKAS_RATE, state); + haraka_S_squeezeblocks(d, 1, s, HARAKAS_RATE, ctx); for (i = 0; i < outlen % HARAKAS_RATE; i++) { out[i] = d[i]; } } } -void PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_haraka_Sx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned long long outlen, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - unsigned long long inlen, - const harakactx *state) { +void haraka_Sx4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned long long outlen, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + unsigned long long inlen, + const spx_ctx *ctx) { unsigned long long i; unsigned char s[64 * 4]; unsigned char d0[32]; @@ -379,16 +373,17 @@ void PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_haraka_Sx4(unsigned char *out0, for (i = 0; i < 64 * 4; i++) { s[i] = 0; } - haraka_S_absorb4x(s, in0, in1, in2, in3, inlen, 0x1F, state); + haraka_S_absorb4x(s, HARAKAS_RATE, in0, in1, in2, in3, inlen, 0x1F, ctx); - haraka_S_squeezeblocks4x(out0, out1, out2, out3, outlen / HARAKAS_RATE, s, HARAKAS_RATE, state); + haraka_S_squeezeblocks4x(out0, out1, out2, out3, outlen / HARAKAS_RATE, s, + HARAKAS_RATE, ctx); out0 += (outlen / HARAKAS_RATE) * HARAKAS_RATE; out1 += (outlen / HARAKAS_RATE) * HARAKAS_RATE; out2 += (outlen / HARAKAS_RATE) * HARAKAS_RATE; out3 += (outlen / HARAKAS_RATE) * HARAKAS_RATE; if (outlen % HARAKAS_RATE) { - haraka_S_squeezeblocks4x(d0, d1, d2, d3, 1, s, HARAKAS_RATE, state); + haraka_S_squeezeblocks4x(d0, d1, d2, d3, 1, s, HARAKAS_RATE, ctx); for (i = 0; i < outlen % HARAKAS_RATE; i++) { out0[i] = d0[i]; out1[i] = d1[i]; @@ -398,7 +393,8 @@ void PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_haraka_Sx4(unsigned char *out0, } } -void PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_haraka512_perm(unsigned char *out, const unsigned char *in, const harakactx *state) { +void haraka512_perm(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx) { u128 s[4], tmp; s[0] = LOAD(in); @@ -406,19 +402,19 @@ void PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_haraka512_perm(unsigned char *out, co s[2] = LOAD(in + 32); s[3] = LOAD(in + 48); - AES4(s[0], s[1], s[2], s[3], state->rc); + AES4(s[0], s[1], s[2], s[3], ctx->rc); MIX4(s[0], s[1], s[2], s[3]); - AES4(s[0], s[1], s[2], s[3], state->rc + 8); + AES4(s[0], s[1], s[2], s[3], ctx->rc + 8); MIX4(s[0], s[1], s[2], s[3]); - AES4(s[0], s[1], s[2], s[3], state->rc + 16); + AES4(s[0], s[1], s[2], s[3], ctx->rc + 16); MIX4(s[0], s[1], s[2], s[3]); - AES4(s[0], s[1], s[2], s[3], state->rc + 24); + AES4(s[0], s[1], s[2], s[3], ctx->rc + 24); MIX4(s[0], s[1], s[2], s[3]); - AES4(s[0], s[1], s[2], s[3], state->rc + 32); + AES4(s[0], s[1], s[2], s[3], ctx->rc + 32); MIX4(s[0], s[1], s[2], s[3]); STORE(out, s[0]); @@ -427,7 +423,8 @@ void PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_haraka512_perm(unsigned char *out, co STORE(out + 48, s[3]); } -void PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_haraka512_perm_x4(unsigned char *out, const unsigned char *in, const harakactx *state) { +void haraka512_perm_x4(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx) { u128 s[4][4], tmp; s[0][0] = LOAD(in); @@ -447,31 +444,31 @@ void PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_haraka512_perm_x4(unsigned char *out, s[3][2] = LOAD(in + 224); s[3][3] = LOAD(in + 240); - AES4_4x(s[0], s[1], s[2], s[3], state->rc); + AES4_4x(s[0], s[1], s[2], s[3], ctx->rc); MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - AES4_4x(s[0], s[1], s[2], s[3], state->rc + 8); + AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 8); MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - AES4_4x(s[0], s[1], s[2], s[3], state->rc + 16); + AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 16); MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - AES4_4x(s[0], s[1], s[2], s[3], state->rc + 24); + AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 24); MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - AES4_4x(s[0], s[1], s[2], s[3], state->rc + 32); + AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 32); MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); @@ -495,7 +492,8 @@ void PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_haraka512_perm_x4(unsigned char *out, STORE(out + 240, s[3][3]); } -void PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_haraka512(unsigned char *out, const unsigned char *in, const harakactx *state) { +void haraka512(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx) { u128 s[4], tmp; s[0] = LOAD(in); @@ -503,19 +501,19 @@ void PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_haraka512(unsigned char *out, const u s[2] = LOAD(in + 32); s[3] = LOAD(in + 48); - AES4(s[0], s[1], s[2], s[3], state->rc); + AES4(s[0], s[1], s[2], s[3], ctx->rc); MIX4(s[0], s[1], s[2], s[3]); - AES4(s[0], s[1], s[2], s[3], state->rc + 8); + AES4(s[0], s[1], s[2], s[3], ctx->rc + 8); MIX4(s[0], s[1], s[2], s[3]); - AES4(s[0], s[1], s[2], s[3], state->rc + 16); + AES4(s[0], s[1], s[2], s[3], ctx->rc + 16); MIX4(s[0], s[1], s[2], s[3]); - AES4(s[0], s[1], s[2], s[3], state->rc + 24); + AES4(s[0], s[1], s[2], s[3], ctx->rc + 24); MIX4(s[0], s[1], s[2], s[3]); - AES4(s[0], s[1], s[2], s[3], state->rc + 32); + AES4(s[0], s[1], s[2], s[3], ctx->rc + 32); MIX4(s[0], s[1], s[2], s[3]); s[0] = XOR128(s[0], LOAD(in)); @@ -527,7 +525,8 @@ void PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_haraka512(unsigned char *out, const u TRUNCSTORE(out, s[0], s[1], s[2], s[3]); } -void PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_haraka512x4(unsigned char *out, const unsigned char *in, const harakactx *state) { +void haraka512x4(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx) { u128 s[4][4], tmp; s[0][0] = LOAD(in); @@ -547,31 +546,31 @@ void PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_haraka512x4(unsigned char *out, const s[3][2] = LOAD(in + 224); s[3][3] = LOAD(in + 240); - AES4_4x(s[0], s[1], s[2], s[3], state->rc); + AES4_4x(s[0], s[1], s[2], s[3], ctx->rc); MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - AES4_4x(s[0], s[1], s[2], s[3], state->rc + 8); + AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 8); MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - AES4_4x(s[0], s[1], s[2], s[3], state->rc + 16); + AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 16); MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - AES4_4x(s[0], s[1], s[2], s[3], state->rc + 24); + AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 24); MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - AES4_4x(s[0], s[1], s[2], s[3], state->rc + 32); + AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 32); MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); @@ -600,25 +599,26 @@ void PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_haraka512x4(unsigned char *out, const TRUNCSTORE((out + 96), s[3][0], s[3][1], s[3][2], s[3][3]); } -void PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_haraka256(unsigned char *out, const unsigned char *in, const harakactx *state) { +void haraka256(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx) { u128 s[2], tmp; s[0] = LOAD(in); s[1] = LOAD(in + 16); - AES2(s[0], s[1], state->rc); + AES2(s[0], s[1], ctx->rc); MIX2(s[0], s[1]); - AES2(s[0], s[1], state->rc + 4); + AES2(s[0], s[1], ctx->rc + 4); MIX2(s[0], s[1]); - AES2(s[0], s[1], state->rc + 8); + AES2(s[0], s[1], ctx->rc + 8); MIX2(s[0], s[1]); - AES2(s[0], s[1], state->rc + 12); + AES2(s[0], s[1], ctx->rc + 12); MIX2(s[0], s[1]); - AES2(s[0], s[1], state->rc + 16); + AES2(s[0], s[1], ctx->rc + 16); MIX2(s[0], s[1]); s[0] = XOR128(s[0], LOAD(in)); @@ -628,7 +628,8 @@ void PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_haraka256(unsigned char *out, const u STORE(out + 16, s[1]); } -void PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_haraka256x4(unsigned char *out, const unsigned char *in, const harakactx *state) { +void haraka256x4(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx) { u128 s[4][2], tmp; s[0][0] = LOAD(in); @@ -641,7 +642,7 @@ void PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_haraka256x4(unsigned char *out, const s[3][1] = LOAD(in + 112); // Round 1 - AES2_4x(s[0], s[1], s[2], s[3], state->rc); + AES2_4x(s[0], s[1], s[2], s[3], ctx->rc); MIX2(s[0][0], s[0][1]); MIX2(s[1][0], s[1][1]); @@ -649,7 +650,7 @@ void PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_haraka256x4(unsigned char *out, const MIX2(s[3][0], s[3][1]); // Round 2 - AES2_4x(s[0], s[1], s[2], s[3], state->rc + 4); + AES2_4x(s[0], s[1], s[2], s[3], ctx->rc + 4); MIX2(s[0][0], s[0][1]); MIX2(s[1][0], s[1][1]); @@ -657,7 +658,7 @@ void PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_haraka256x4(unsigned char *out, const MIX2(s[3][0], s[3][1]); // Round 3 - AES2_4x(s[0], s[1], s[2], s[3], state->rc + 8); + AES2_4x(s[0], s[1], s[2], s[3], ctx->rc + 8); MIX2(s[0][0], s[0][1]); MIX2(s[1][0], s[1][1]); @@ -665,7 +666,7 @@ void PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_haraka256x4(unsigned char *out, const MIX2(s[3][0], s[3][1]); // Round 4 - AES2_4x(s[0], s[1], s[2], s[3], state->rc + 12); + AES2_4x(s[0], s[1], s[2], s[3], ctx->rc + 12); MIX2(s[0][0], s[0][1]); MIX2(s[1][0], s[1][1]); @@ -673,7 +674,7 @@ void PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_haraka256x4(unsigned char *out, const MIX2(s[3][0], s[3][1]); // Round 5 - AES2_4x(s[0], s[1], s[2], s[3], state->rc + 16); + AES2_4x(s[0], s[1], s[2], s[3], ctx->rc + 16); MIX2(s[0][0], s[0][1]); MIX2(s[1][0], s[1][1]); @@ -699,103 +700,3 @@ void PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_haraka256x4(unsigned char *out, const STORE(out + 96, s[3][0]); STORE(out + 112, s[3][1]); } - -void PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_haraka256_sk(unsigned char *out, const unsigned char *in, const harakactx *state) { - u128 s[2], tmp; - - s[0] = LOAD(in); - s[1] = LOAD(in + 16); - - AES2(s[0], s[1], state->rc_sseed); - MIX2(s[0], s[1]); - - AES2(s[0], s[1], state->rc_sseed + 4); - MIX2(s[0], s[1]); - - AES2(s[0], s[1], state->rc_sseed + 8); - MIX2(s[0], s[1]); - - AES2(s[0], s[1], state->rc_sseed + 12); - MIX2(s[0], s[1]); - - AES2(s[0], s[1], state->rc_sseed + 16); - MIX2(s[0], s[1]); - - s[0] = XOR128(s[0], LOAD(in)); - s[1] = XOR128(s[1], LOAD(in + 16)); - - STORE(out, s[0]); - STORE(out + 16, s[1]); -} - -void PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_haraka256_skx4(unsigned char *out, const unsigned char *in, const harakactx *state) { - u128 s[4][2], tmp; - - s[0][0] = LOAD(in); - s[0][1] = LOAD(in + 16); - s[1][0] = LOAD(in + 32); - s[1][1] = LOAD(in + 48); - s[2][0] = LOAD(in + 64); - s[2][1] = LOAD(in + 80); - s[3][0] = LOAD(in + 96); - s[3][1] = LOAD(in + 112); - - // Round 1 - AES2_4x(s[0], s[1], s[2], s[3], state->rc_sseed); - - MIX2(s[0][0], s[0][1]); - MIX2(s[1][0], s[1][1]); - MIX2(s[2][0], s[2][1]); - MIX2(s[3][0], s[3][1]); - - // Round 2 - AES2_4x(s[0], s[1], s[2], s[3], state->rc_sseed + 4); - - MIX2(s[0][0], s[0][1]); - MIX2(s[1][0], s[1][1]); - MIX2(s[2][0], s[2][1]); - MIX2(s[3][0], s[3][1]); - - // Round 3 - AES2_4x(s[0], s[1], s[2], s[3], state->rc_sseed + 8); - - MIX2(s[0][0], s[0][1]); - MIX2(s[1][0], s[1][1]); - MIX2(s[2][0], s[2][1]); - MIX2(s[3][0], s[3][1]); - - // Round 4 - AES2_4x(s[0], s[1], s[2], s[3], state->rc_sseed + 12); - - MIX2(s[0][0], s[0][1]); - MIX2(s[1][0], s[1][1]); - MIX2(s[2][0], s[2][1]); - MIX2(s[3][0], s[3][1]); - - // Round 5 - AES2_4x(s[0], s[1], s[2], s[3], state->rc_sseed + 16); - - MIX2(s[0][0], s[0][1]); - MIX2(s[1][0], s[1][1]); - MIX2(s[2][0], s[2][1]); - MIX2(s[3][0], s[3][1]); - - // Feed Forward - s[0][0] = XOR128(s[0][0], LOAD(in)); - s[0][1] = XOR128(s[0][1], LOAD(in + 16)); - s[1][0] = XOR128(s[1][0], LOAD(in + 32)); - s[1][1] = XOR128(s[1][1], LOAD(in + 48)); - s[2][0] = XOR128(s[2][0], LOAD(in + 64)); - s[2][1] = XOR128(s[2][1], LOAD(in + 80)); - s[3][0] = XOR128(s[3][0], LOAD(in + 96)); - s[3][1] = XOR128(s[3][1], LOAD(in + 112)); - - STORE(out, s[0][0]); - STORE(out + 16, s[0][1]); - STORE(out + 32, s[1][0]); - STORE(out + 48, s[1][1]); - STORE(out + 64, s[2][0]); - STORE(out + 80, s[2][1]); - STORE(out + 96, s[3][0]); - STORE(out + 112, s[3][1]); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/haraka.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/haraka.h index ed977f8d0e..737cb6065f 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/haraka.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/haraka.h @@ -1,57 +1,42 @@ -#ifndef PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_HARAKA_H -#define PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_HARAKA_H +#ifndef SPX_HARAKA_H +#define SPX_HARAKA_H -#include -#include -#include - -typedef struct { - __m128i rc[40]; - __m128i rc_sseed[40]; -} harakactx; +#include "context.h" +#include "params.h" /* Tweak constants with seed */ -void PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_tweak_constants( - harakactx *state, - const unsigned char *pk_seed, const unsigned char *sk_seed, - unsigned long long seed_length); +#define tweak_constants SPX_NAMESPACE(tweak_constants) +void tweak_constants(spx_ctx *ctx); /* Haraka Sponge */ -void PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_haraka_S_inc_init(uint8_t *s_inc); -void PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, const harakactx *state); -void PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_haraka_S_inc_finalize(uint8_t *s_inc); -void PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, const harakactx *state); -void PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_haraka_S( - unsigned char *out, unsigned long long outlen, - const unsigned char *in, unsigned long long inlen, const harakactx *state); -void PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_haraka_Sx4( - unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned long long outlen, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - unsigned long long inlen, - const harakactx *state); - +#define haraka_S_inc_init SPX_NAMESPACE(haraka_S_inc_init) +void haraka_S_inc_init(uint8_t *s_inc); +#define haraka_S_inc_absorb SPX_NAMESPACE(haraka_S_inc_absorb) +void haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, + const spx_ctx *ctx); +#define haraka_S_inc_finalize SPX_NAMESPACE(haraka_S_inc_finalize) +void haraka_S_inc_finalize(uint8_t *s_inc); +#define haraka_S_inc_squeeze SPX_NAMESPACE(haraka_S_inc_squeeze) +void haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, + const spx_ctx *ctx); +#define haraka_S SPX_NAMESPACE(haraka_S) +void haraka_S(unsigned char *out, unsigned long long outlen, + const unsigned char *in, unsigned long long inlen, + const spx_ctx *ctx); /* Applies the 512-bit Haraka permutation to in. */ -void PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_haraka512_perm(unsigned char *out, const unsigned char *in, const harakactx *state); -void PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_haraka512_perm_x4(unsigned char *out, const unsigned char *in, const harakactx *state); +#define haraka512_perm SPX_NAMESPACE(haraka512_perm) +void haraka512_perm(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx); /* Implementation of Haraka-512 */ -void PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_haraka512(unsigned char *out, const unsigned char *in, const harakactx *state); -void PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_haraka512x4(unsigned char *out, const unsigned char *in, const harakactx *state); +#define haraka512 SPX_NAMESPACE(haraka512) +void haraka512(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx); /* Implementation of Haraka-256 */ -void PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_haraka256(unsigned char *out, const unsigned char *in, const harakactx *state); -void PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_haraka256x4(unsigned char *out, const unsigned char *in, const harakactx *state); - -/* Implementation of Haraka-256 using sk.seed constants */ -void PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_haraka256_sk(unsigned char *out, const unsigned char *in, const harakactx *state); -void PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_haraka256_skx4(unsigned char *out, const unsigned char *in, const harakactx *state); +#define haraka256 SPX_NAMESPACE(haraka256) +void haraka256(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/haraka_offsets.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/haraka_offsets.h new file mode 100644 index 0000000000..7c062272a0 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/haraka_offsets.h @@ -0,0 +1,21 @@ +#ifndef HARAKA_OFFSETS_H_ +#define HARAKA_OFFSETS_H_ + +/* + * Offsets of various fields in the address structure when we use Haraka as + * the Sphincs+ hash function + */ + +#define SPX_OFFSET_LAYER 3 /* The byte used to specify the Merkle tree layer */ +#define SPX_OFFSET_TREE 8 /* The start of the 8 byte field used to specify the tree */ +#define SPX_OFFSET_TYPE 19 /* The byte used to specify the hash type (reason) */ +#define SPX_OFFSET_KP_ADDR2 22 /* The high byte used to specify the key pair (which one-time signature) */ +#define SPX_OFFSET_KP_ADDR1 23 /* The low byte used to specify the key pair */ +#define SPX_OFFSET_CHAIN_ADDR 27 /* The byte used to specify the chain address (which Winternitz chain) */ +#define SPX_OFFSET_HASH_ADDR 31 /* The byte used to specify the hash address (where in the Winternitz chain) */ +#define SPX_OFFSET_TREE_HGT 27 /* The byte used to specify the height of this node in the FORS or Merkle tree */ +#define SPX_OFFSET_TREE_INDEX 28 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ + +#define SPX_HARAKA 1 + +#endif /* HARAKA_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/harakax4.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/harakax4.h new file mode 100644 index 0000000000..eadc69aa48 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/harakax4.h @@ -0,0 +1,36 @@ +#ifndef SPX_HARAKAX4_H +#define SPX_HARAKAX4_H + +#include "context.h" +#include "params.h" + +/* Haraka Sponge */ +#define haraka_Sx4 SPX_NAMESPACE(haraka_Sx4) +void haraka_Sx4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned long long outlen, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + unsigned long long inlen, + const spx_ctx *ctx); + +/* Applies the 512-bit Haraka permutation x4 to in. */ +#define haraka512_perm_x4 SPX_NAMESPACE(haraka512_perm_x4) +void haraka512_perm_x4(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx); + +/* Implementation of Haraka-512 x4*/ +#define haraka512x4 SPX_NAMESPACE(haraka512x4) +void haraka512x4(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx); + +/* Implementation of Haraka-256 x4 */ +#define haraka256x4 SPX_NAMESPACE(haraka256x4) +void haraka256x4(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/hash.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/hash.h index 358ccf94cd..f7c87d4c3c 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/hash.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/hash.h @@ -1,31 +1,28 @@ -#ifndef PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_HASH_H -#define PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_HASH_H - -#include "hash_state.h" +#ifndef SPX_HASH_H +#define SPX_HASH_H #include #include -void PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_initialize_hash_function( - hash_state *hash_state_seeded, - const unsigned char *pub_seed, const unsigned char *sk_seed); +#include "context.h" +#include "params.h" + +#define prf_addr SPX_NAMESPACE(prf_addr) +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]); -void PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_destroy_hash_function(hash_state *hash_state_seeded); +#define gen_message_random SPX_NAMESPACE(gen_message_random) +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); -void PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded); +#define hash_message SPX_NAMESPACE(hash_message) +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); -void PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); -void PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/hash_haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/hash_haraka.c index 566210734d..750a67423b 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/hash_haraka.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/hash_haraka.c @@ -2,58 +2,44 @@ #include #include "address.h" -#include "haraka.h" -#include "hash.h" #include "params.h" #include "utils.h" -void PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_initialize_hash_function( - hash_state *hash_state_seeded, - const unsigned char *pub_seed, const unsigned char *sk_seed) { - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_tweak_constants(hash_state_seeded, pub_seed, sk_seed, PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N); -} - -/* The haraka implementation is stack based and won't be replaced in PQClean/OQS, - so we don't need to do anything */ -void PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_destroy_hash_function( - hash_state *hash_state_seeded) { // NOLINT(readability-non-const-parameter) - (void)hash_state_seeded; -} +#include "haraka.h" +#include "hash.h" /* - * Computes PRF(key, addr), given a secret key of PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N bytes and an address + * Computes PRF(key, addr), given a secret key of SPX_N bytes and an address */ -void PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded) { - unsigned char buf[PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_ADDR_BYTES]; - /* Since PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N may be smaller than 32, we need a temporary buffer. */ +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]) { + /* Since SPX_N may be smaller than 32, we need temporary buffers. */ unsigned char outbuf[32]; + unsigned char buf[64] = {0}; - (void)key; /* Suppress an 'unused parameter' warning. */ + memcpy(buf, addr, SPX_ADDR_BYTES); + memcpy(buf + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_addr_to_bytes(buf, addr); - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_haraka256_sk(outbuf, buf, hash_state_seeded); - memcpy(out, outbuf, PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N); + haraka512(outbuf, (const void *)buf, ctx); + memcpy(out, outbuf, SPX_N); } /** * Computes the message-dependent randomness R, using a secret seed and an * optional randomization value as well as the message. */ -void PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded) { +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { uint8_t s_inc[65]; - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_haraka_S_inc_init(s_inc); - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_haraka_S_inc_absorb(s_inc, sk_prf, PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_haraka_S_inc_absorb(s_inc, optrand, PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_haraka_S_inc_absorb(s_inc, m, mlen, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_haraka_S_inc_finalize(s_inc); - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_haraka_S_inc_squeeze(R, PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N, s_inc, hash_state_seeded); + haraka_S_inc_init(s_inc); + haraka_S_inc_absorb(s_inc, sk_prf, SPX_N, ctx); + haraka_S_inc_absorb(s_inc, optrand, SPX_N, ctx); + haraka_S_inc_absorb(s_inc, m, mlen, ctx); + haraka_S_inc_finalize(s_inc); + haraka_S_inc_squeeze(R, SPX_N, s_inc, ctx); } /** @@ -61,36 +47,35 @@ void PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_gen_message_random( * Outputs the message digest and the index of the leaf. The index is split in * the tree index and the leaf index, for convenient copying to an address. */ -void PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded) { -#define PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_TREE_BITS (PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_TREE_HEIGHT * (PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_D - 1)) -#define PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_TREE_BYTES ((PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_TREE_BITS + 7) / 8) -#define PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_LEAF_BITS PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_TREE_HEIGHT -#define PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_LEAF_BYTES ((PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_LEAF_BITS + 7) / 8) -#define PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_DGST_BYTES (PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_FORS_MSG_BYTES + PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_TREE_BYTES + PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_LEAF_BYTES) +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { +#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) +#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) +#define SPX_LEAF_BITS SPX_TREE_HEIGHT +#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) +#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) - unsigned char buf[PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_DGST_BYTES]; + unsigned char buf[SPX_DGST_BYTES]; unsigned char *bufp = buf; uint8_t s_inc[65]; - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_haraka_S_inc_init(s_inc); - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_haraka_S_inc_absorb(s_inc, R, PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_haraka_S_inc_absorb(s_inc, pk + PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N, PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_haraka_S_inc_absorb(s_inc, m, mlen, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_haraka_S_inc_finalize(s_inc); - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_haraka_S_inc_squeeze(buf, PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_DGST_BYTES, s_inc, hash_state_seeded); + haraka_S_inc_init(s_inc); + haraka_S_inc_absorb(s_inc, R, SPX_N, ctx); + haraka_S_inc_absorb(s_inc, pk + SPX_N, SPX_N, ctx); // Only absorb root part of pk + haraka_S_inc_absorb(s_inc, m, mlen, ctx); + haraka_S_inc_finalize(s_inc); + haraka_S_inc_squeeze(buf, SPX_DGST_BYTES, s_inc, ctx); + + memcpy(digest, bufp, SPX_FORS_MSG_BYTES); + bufp += SPX_FORS_MSG_BYTES; - memcpy(digest, bufp, PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_FORS_MSG_BYTES); - bufp += PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_FORS_MSG_BYTES; - *tree = PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_bytes_to_ull(bufp, PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_TREE_BYTES); - *tree &= (~(uint64_t)0) >> (64 - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_TREE_BITS); - bufp += PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_TREE_BYTES; + *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); + *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); + bufp += SPX_TREE_BYTES; - *leaf_idx = (uint32_t)PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_bytes_to_ull( - bufp, PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_LEAF_BYTES); - *leaf_idx &= (~(uint32_t)0) >> (32 - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_LEAF_BITS); + *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); + *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/hash_harakax4.c b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/hash_harakax4.c index 9fe614df0b..cfa5162d79 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/hash_harakax4.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/hash_harakax4.c @@ -2,36 +2,34 @@ #include #include "address.h" -#include "haraka.h" -#include "hash_state.h" +#include "harakax4.h" #include "hashx4.h" #include "params.h" /* * 4-way parallel version of prf_addr; takes 4x as much input and output */ -void PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_prf_addrx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const unsigned char *key, - const uint32_t addrx4[4 * 8], - const hash_state *state_seeded) { - unsigned char bufx4[4 * PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_ADDR_BYTES]; - /* Since PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N may be smaller than 32, we need a temporary buffer. */ +#define prf_addrx4 SPX_NAMESPACE(prf_addrx4) +void prf_addrx4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const spx_ctx *ctx, + const uint32_t addrx4[4 * 8]) { + unsigned char bufx4[4 * 64] = {0}; + /* Since SPX_N may be smaller than 32, we need temporary buffers. */ unsigned char outbuf[4 * 32]; unsigned int i; - (void)key; /* Suppress an 'unused parameter' warning. */ - for (i = 0; i < 4; i++) { - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_addr_to_bytes(bufx4 + i * PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_ADDR_BYTES, addrx4 + i * 8); + memcpy(bufx4 + i * 64, addrx4 + i * 8, SPX_ADDR_BYTES); + memcpy(bufx4 + i * 64 + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); } - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_haraka256_skx4(outbuf, bufx4, state_seeded); + haraka512x4(outbuf, bufx4, ctx); - memcpy(out0, outbuf, PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N); - memcpy(out1, outbuf + 32, PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N); - memcpy(out2, outbuf + 64, PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N); - memcpy(out3, outbuf + 96, PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N); + memcpy(out0, outbuf, SPX_N); + memcpy(out1, outbuf + 32, SPX_N); + memcpy(out2, outbuf + 64, SPX_N); + memcpy(out3, outbuf + 96, SPX_N); } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/hash_state.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/hash_state.h deleted file mode 100644 index cab028d090..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/hash_state.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_HASH_STATE_H -#define PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_HASH_STATE_H - -/** - * Defines the type of the hash function state. - * - * Don't be fooled into thinking this instance of SPHINCS+ isn't stateless! - * - * From Section 7.2.2 from the SPHINCS+ round-2 specification: - * - * Each of the instances of the tweakable hash function take PK.seed as its - * first input, which is constant for a given key pair – and, thus, across - * a single signature. This leads to a lot of redundant computation. To remedy - * this, we pad PK.seed to the length of a full 64-byte SHA-256 input block. - * Because of the Merkle-DamgÃ¥rd construction that underlies SHA-256, this - * allows for reuse of the intermediate SHA-256 state after the initial call to - * the compression function which improves performance. - * - * We pass this hash state around in functions, because otherwise we need to - * have a global variable. - */ - -#include "haraka.h" -#define hash_state harakactx - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/hashx4.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/hashx4.h index e453123a84..3751a0ebd0 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/hashx4.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/hashx4.h @@ -1,16 +1,17 @@ -#ifndef PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_HASHX4_H -#define PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_HASHX4_H +#ifndef SPX_HASHX4_H +#define SPX_HASHX4_H #include -#include "hash_state.h" +#include "context.h" +#include "params.h" -void PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_prf_addrx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const unsigned char *key, - const uint32_t addrx4[4 * 8], - const hash_state *state_seeded); +#define prf_addrx4 SPX_NAMESPACE(prf_addrx4) +void prf_addrx4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const spx_ctx *ctx, + const uint32_t addrx4[4 * 8]); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/merkle.c b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/merkle.c new file mode 100644 index 0000000000..f57811c1ac --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/merkle.c @@ -0,0 +1,64 @@ +#include +#include + +#include "merkle.h" + +#include "address.h" +#include "params.h" +#include "utils.h" +#include "utilsx4.h" +#include "wots.h" +#include "wotsx4.h" + +/* + * This generates a Merkle signature (WOTS signature followed by the Merkle + * authentication path). + */ +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf) { + unsigned char *auth_path = sig + SPX_WOTS_BYTES; + uint32_t tree_addrx4[4 * 8] = { 0 }; + int j; + struct leaf_info_x4 info = { 0 }; + unsigned steps[ SPX_WOTS_LEN ]; + + info.wots_sig = sig; + chain_lengths(steps, root); + info.wots_steps = steps; + + for (j = 0; j < 4; j++) { + set_type(&tree_addrx4[8 * j], SPX_ADDR_TYPE_HASHTREE); + set_type(&info.leaf_addr[8 * j], SPX_ADDR_TYPE_WOTS); + set_type(&info.pk_addr[8 * j], SPX_ADDR_TYPE_WOTSPK); + copy_subtree_addr(&tree_addrx4[8 * j], tree_addr); + copy_subtree_addr(&info.leaf_addr[8 * j], wots_addr); + copy_subtree_addr(&info.pk_addr[8 * j], wots_addr); + } + + info.wots_sign_leaf = idx_leaf; + + treehashx4(root, auth_path, ctx, + idx_leaf, 0, + SPX_TREE_HEIGHT, + wots_gen_leafx4, + tree_addrx4, &info); +} + +/* Compute root node of the top-most subtree. */ +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { + /* We do not need the auth path in key generation, but it simplifies the + code to have just one treehash routine that computes both root and path + in one function. */ + unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; + uint32_t top_tree_addr[8] = {0}; + uint32_t wots_addr[8] = {0}; + + set_layer_addr(top_tree_addr, SPX_D - 1); + set_layer_addr(wots_addr, SPX_D - 1); + + merkle_sign(auth_path, root, ctx, + wots_addr, top_tree_addr, + ~0U /* ~0 means "don't bother generating an auth path */ ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/merkle.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/merkle.h new file mode 100644 index 0000000000..769cf2e970 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/merkle.h @@ -0,0 +1,21 @@ +#ifndef MERKLE_H_ +#define MERKLE_H_ + +#include + +#include "context.h" +#include "params.h" + +/* Generate a Merkle signature (WOTS signature followed by the Merkle */ +/* authentication path) */ +#define merkle_sign SPX_NAMESPACE(merkle_sign) +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf); + +/* Compute the root node of the top-most subtree. */ +#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); + +#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/nistapi.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/nistapi.h new file mode 100644 index 0000000000..3cb71afad4 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/nistapi.h @@ -0,0 +1,87 @@ +#ifndef SPX_API_H +#define SPX_API_H + +#include +#include + +#include "params.h" + +#define CRYPTO_ALGNAME "SPHINCS+" + +#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES +#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES +#define CRYPTO_BYTES SPX_BYTES +#define CRYPTO_SEEDBYTES (3*SPX_N) + +/* + * Returns the length of a secret key, in bytes + */ +#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) +size_t crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) +size_t crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) +size_t crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) +size_t crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +#define crypto_sign SPX_NAMESPACE(crypto_sign) +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/params.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/params.h index f612864264..a4e20d99ac 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/params.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/params.h @@ -1,53 +1,56 @@ -#ifndef PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_PARAMS_H -#define PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_PARAMS_H +#ifndef SPX_PARAMS_H +#define SPX_PARAMS_H + +#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_##s /* Hash output length in bytes. */ -#define PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N 32 +#define SPX_N 32 /* Height of the hypertree. */ -#define PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_FULL_HEIGHT 68 +#define SPX_FULL_HEIGHT 68 /* Number of subtree layer. */ -#define PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_D 17 +#define SPX_D 17 /* FORS tree dimensions. */ -#define PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_FORS_HEIGHT 9 -#define PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_FORS_TREES 35 +#define SPX_FORS_HEIGHT 9 +#define SPX_FORS_TREES 35 /* Winternitz parameter, */ -#define PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_WOTS_W 16 +#define SPX_WOTS_W 16 /* The hash function is defined by linking a different hash.c file, as opposed to setting a #define constant. */ /* For clarity */ -#define PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_ADDR_BYTES 32 +#define SPX_ADDR_BYTES 32 /* WOTS parameters. */ -#define PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_WOTS_LOGW 4 +#define SPX_WOTS_LOGW 4 -#define PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_WOTS_LEN1 (8 * PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N / PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_WOTS_LOGW) +#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) -/* PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#define PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_WOTS_LEN2 3 +/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ +#define SPX_WOTS_LEN2 3 -#define PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_WOTS_LEN (PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_WOTS_LEN1 + PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_WOTS_LEN2) -#define PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_WOTS_BYTES (PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_WOTS_LEN * PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N) -#define PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_WOTS_PK_BYTES PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_WOTS_BYTES +#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) +#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) +#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES /* Subtree size. */ -#define PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_TREE_HEIGHT (PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_FULL_HEIGHT / PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_D) +#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) + +//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT +// #error SPX_D should always divide SPX_FULL_HEIGHT +//#endif /* FORS parameters. */ -#define PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_FORS_MSG_BYTES ((PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_FORS_TREES + 7) / 8) -#define PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_FORS_BYTES ((PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_FORS_HEIGHT + 1) * PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_FORS_TREES * PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N) -#define PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_FORS_PK_BYTES PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N +#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) +#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) +#define SPX_FORS_PK_BYTES SPX_N /* Resulting SPX sizes. */ -#define PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_BYTES (PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N + PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_FORS_BYTES + PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_D * PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_WOTS_BYTES +\ - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_FULL_HEIGHT * PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N) -#define PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_PK_BYTES (2 * PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N) -#define PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_SK_BYTES (2 * PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N + PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_PK_BYTES) - -/* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ -#define PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_OPTRAND_BYTES 32 +#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ + SPX_FULL_HEIGHT * SPX_N) +#define SPX_PK_BYTES (2 * SPX_N) +#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) + +#include "haraka_offsets.h" #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/sign.c b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/sign.c index 339f8b15cb..9d0c7d1b22 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/sign.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/sign.c @@ -1,76 +1,45 @@ -#include #include #include #include #include "address.h" -#include "api.h" +#include "context.h" #include "fors.h" #include "hash.h" -#include "hash_state.h" +#include "merkle.h" +#include "nistapi.h" #include "params.h" #include "randombytes.h" #include "thash.h" #include "utils.h" #include "wots.h" - -/** - * Computes the leaf at a given address. First generates the WOTS key pair, - * then computes leaf by hashing horizontally. - */ -static void wots_gen_leaf(unsigned char *leaf, const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx, const uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - unsigned char pk[PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_WOTS_BYTES]; - uint32_t wots_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_set_type( - wots_addr, PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_set_type( - wots_pk_addr, PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_ADDR_TYPE_WOTSPK); - - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_set_keypair_addr( - wots_addr, addr_idx); - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_wots_gen_pk( - pk, sk_seed, pub_seed, wots_addr, hash_state_seeded); - - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_copy_keypair_addr( - wots_pk_addr, wots_addr); - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_thash_WOTS_LEN( - leaf, pk, pub_seed, wots_pk_addr, hash_state_seeded); -} - /* * Returns the length of a secret key, in bytes */ -size_t PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_crypto_sign_secretkeybytes(void) { - return PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_CRYPTO_SECRETKEYBYTES; +size_t crypto_sign_secretkeybytes(void) { + return CRYPTO_SECRETKEYBYTES; } /* * Returns the length of a public key, in bytes */ -size_t PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_crypto_sign_publickeybytes(void) { - return PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_CRYPTO_PUBLICKEYBYTES; +size_t crypto_sign_publickeybytes(void) { + return CRYPTO_PUBLICKEYBYTES; } /* * Returns the length of a signature, in bytes */ -size_t PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_crypto_sign_bytes(void) { - return PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_CRYPTO_BYTES; +size_t crypto_sign_bytes(void) { + return CRYPTO_BYTES; } /* * Returns the length of the seed required to generate a key pair, in bytes */ -size_t PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_crypto_sign_seedbytes(void) { - return PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_CRYPTO_SEEDBYTES; +size_t crypto_sign_seedbytes(void) { + return CRYPTO_SEEDBYTES; } /* @@ -78,35 +47,29 @@ size_t PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_crypto_sign_seedbytes(void) { * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] * Format pk: [PUB_SEED || root] */ -int PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed) { - /* We do not need the auth path in key generation, but it simplifies the - code to have just one treehash routine that computes both root and path - in one function. */ - unsigned char auth_path[PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_TREE_HEIGHT * PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N]; - uint32_t top_tree_addr[8] = {0}; - hash_state hash_state_seeded; - - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_set_layer_addr( - top_tree_addr, PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_D - 1); - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_set_type( - top_tree_addr, PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_ADDR_TYPE_HASHTREE); +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed) { + spx_ctx ctx; /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ - memcpy(sk, seed, PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_CRYPTO_SEEDBYTES); + memcpy(sk, seed, CRYPTO_SEEDBYTES); + + memcpy(pk, sk + 2 * SPX_N, SPX_N); - memcpy(pk, sk + 2 * PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N, PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N); + memcpy(ctx.pub_seed, pk, SPX_N); + memcpy(ctx.sk_seed, sk, SPX_N); /* This hook allows the hash function instantiation to do whatever preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_initialize_hash_function(&hash_state_seeded, pk, sk); + initialize_hash_function(&ctx); /* Compute root node of the top-most subtree. */ - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_treehash_TREE_HEIGHT( - sk + 3 * PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N, auth_path, sk, sk + 2 * PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N, 0, 0, - wots_gen_leaf, top_tree_addr, &hash_state_seeded); + merkle_gen_root(sk + 3 * SPX_N, &ctx); - memcpy(pk + PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N, sk + 3 * PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N, PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N); + // cleanup + free_hash_function(&ctx); + + memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); return 0; } @@ -116,31 +79,10 @@ int PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_crypto_sign_seed_keypair( * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] * Format pk: [PUB_SEED || root] */ -int PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk) { - - // guarantee alignment of pk - union { - __m128 _x[PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_CRYPTO_PUBLICKEYBYTES / 16]; - uint8_t pk[PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_CRYPTO_PUBLICKEYBYTES]; - } aligned_pk; - - // guarantee alignment of sk - union { - __m128 _x[PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_CRYPTO_SECRETKEYBYTES / 16]; - uint8_t sk[PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_CRYPTO_SECRETKEYBYTES]; - } aligned_sk; - - union { - __m128 _x[PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_CRYPTO_SEEDBYTES / 16]; - uint8_t seed[PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_CRYPTO_SEEDBYTES]; - } aligned_seed; - randombytes(aligned_seed.seed, PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_CRYPTO_SEEDBYTES); - - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_crypto_sign_seed_keypair( - aligned_pk.pk, aligned_sk.sk, aligned_seed.seed); - memcpy(pk, aligned_pk.pk, PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_CRYPTO_PUBLICKEYBYTES); - memcpy(sk, aligned_sk.sk, PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_CRYPTO_SECRETKEYBYTES); +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { + uint8_t seed[CRYPTO_SEEDBYTES]; + randombytes(seed, CRYPTO_SEEDBYTES); + crypto_sign_seed_keypair(pk, sk, seed); return 0; } @@ -148,101 +90,68 @@ int PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_crypto_sign_keypair( /** * Returns an array containing a detached signature. */ -int PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - // guarantee alignment of sk - union { - __m128 *_x; - uint8_t sk[PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_CRYPTO_SECRETKEYBYTES]; - } aligned_sk; - memcpy(aligned_sk.sk, sk, PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_CRYPTO_SECRETKEYBYTES); - sk = aligned_sk.sk; - - // guarantee alignment of sig - union { - __m128 *_x; - uint8_t sig[PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_BYTES]; - } aligned_sig; - uint8_t *orig_sig = sig; - sig = (uint8_t *)aligned_sig.sig; - - const unsigned char *sk_seed = sk; - const unsigned char *sk_prf = sk + PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N; - const unsigned char *pk = sk + 2 * PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N; - const unsigned char *pub_seed = pk; - - unsigned char optrand[PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N]; - unsigned char mhash[PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_FORS_MSG_BYTES]; - unsigned char root[PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N]; +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk) { + spx_ctx ctx; + + const uint8_t *sk_prf = sk + SPX_N; + const uint8_t *pk = sk + 2 * SPX_N; + + uint8_t optrand[SPX_N]; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t root[SPX_N]; uint32_t i; uint64_t tree; uint32_t idx_leaf; uint32_t wots_addr[8] = {0}; uint32_t tree_addr[8] = {0}; - hash_state hash_state_seeded; + memcpy(ctx.sk_seed, sk, SPX_N); + memcpy(ctx.pub_seed, pk, SPX_N); /* This hook allows the hash function instantiation to do whatever preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_initialize_hash_function( - &hash_state_seeded, - pub_seed, sk_seed); + initialize_hash_function(&ctx); - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_set_type( - wots_addr, PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_set_type( - tree_addr, PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_ADDR_TYPE_HASHTREE); + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); /* Optionally, signing can be made non-deterministic using optrand. This can help counter side-channel attacks that would benefit from getting a large number of traces when the signer uses the same nodes. */ - randombytes(optrand, PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N); + randombytes(optrand, SPX_N); /* Compute the digest randomization value. */ - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_gen_message_random( - sig, sk_prf, optrand, m, mlen, &hash_state_seeded); + gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); /* Derive the message digest and leaf index from R, PK and M. */ - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N; + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_set_keypair_addr( - wots_addr, idx_leaf); + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); /* Sign the message hash using FORS. */ - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_fors_sign( - sig, root, mhash, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_FORS_BYTES; - - for (i = 0; i < PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_D; i++) { - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_set_tree_addr(tree_addr, tree); - - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_set_keypair_addr( - wots_addr, idx_leaf); - - /* Compute a WOTS signature. */ - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_wots_sign( - sig, root, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_WOTS_BYTES; - - /* Compute the authentication path for the used WOTS leaf. */ - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_treehash_TREE_HEIGHT( - root, sig, sk_seed, pub_seed, idx_leaf, 0, - wots_gen_leaf, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_TREE_HEIGHT * PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N; + fors_sign(sig, root, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); + sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_TREE_HEIGHT; + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; } - memcpy(orig_sig, aligned_sig.sig, PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_BYTES); - *siglen = PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_BYTES; + free_hash_function(&ctx); + + *siglen = SPX_BYTES; return 0; } @@ -250,23 +159,14 @@ int PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_crypto_sign_signature( /** * Verifies a detached signature and message under a given public key. */ -int PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk) { - // guarantee alignment of pk - union { - __m128 *_x; - uint8_t pk[PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_CRYPTO_PUBLICKEYBYTES]; - } aligned_pk; - memcpy(aligned_pk.pk, pk, PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_CRYPTO_PUBLICKEYBYTES); - pk = aligned_pk.pk; - - const unsigned char *pub_seed = pk; - const unsigned char *pub_root = pk + PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N; - unsigned char mhash[PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_FORS_MSG_BYTES]; - unsigned char wots_pk[PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_WOTS_BYTES]; - unsigned char root[PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N]; - unsigned char leaf[PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N]; +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk) { + spx_ctx ctx; + const uint8_t *pub_root = pk + SPX_N; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t wots_pk[SPX_WOTS_BYTES]; + uint8_t root[SPX_N]; + uint8_t leaf[SPX_N]; unsigned int i; uint64_t tree; uint32_t idx_leaf; @@ -274,77 +174,66 @@ int PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_crypto_sign_verify( uint32_t tree_addr[8] = {0}; uint32_t wots_pk_addr[8] = {0}; - hash_state hash_state_seeded; - - if (siglen != PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_BYTES) { + if (siglen != SPX_BYTES) { return -1; } + memcpy(ctx.pub_seed, pk, SPX_N); + /* This hook allows the hash function instantiation to do whatever preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_initialize_hash_function( - &hash_state_seeded, - pub_seed, NULL); + initialize_hash_function(&ctx); - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_set_type( - wots_addr, PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_set_type( - tree_addr, PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_ADDR_TYPE_HASHTREE); - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_set_type( - wots_pk_addr, PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_ADDR_TYPE_WOTSPK); + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); /* Derive the message digest and leaf index from R || PK || M. */ - /* The additional PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N is a result of the hash domain separator. */ - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N; + /* The additional SPX_N is a result of the hash domain separator. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; /* Layer correctly defaults to 0, so no need to set_layer_addr */ - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_set_keypair_addr( - wots_addr, idx_leaf); + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_fors_pk_from_sig( - root, sig, mhash, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_FORS_BYTES; + fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; /* For each subtree.. */ - for (i = 0; i < PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_D; i++) { - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_set_tree_addr(tree_addr, tree); + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_set_keypair_addr( - wots_addr, idx_leaf); + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_copy_keypair_addr( - wots_pk_addr, wots_addr); + copy_keypair_addr(wots_pk_addr, wots_addr); /* The WOTS public key is only correct if the signature was correct. */ /* Initially, root is the FORS pk, but on subsequent iterations it is the root of the subtree below the currently processed subtree. */ - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_wots_pk_from_sig( - wots_pk, sig, root, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_WOTS_BYTES; + wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); + sig += SPX_WOTS_BYTES; /* Compute the leaf node using the WOTS public key. */ - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_thash_WOTS_LEN( - leaf, wots_pk, pub_seed, wots_pk_addr, &hash_state_seeded); + thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); /* Compute the root node of this subtree. */ - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_compute_root( - root, leaf, idx_leaf, 0, sig, PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_TREE_HEIGHT, - pub_seed, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_TREE_HEIGHT * PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N; + compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, + &ctx, tree_addr); + sig += SPX_TREE_HEIGHT * SPX_N; /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_TREE_HEIGHT; + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; } + // cleanup + free_hash_function(&ctx); + /* Check if the root node equals the root node in the public key. */ - if (memcmp(root, pub_root, PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N) != 0) { + if (memcmp(root, pub_root, SPX_N) != 0) { return -1; } @@ -355,15 +244,14 @@ int PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_crypto_sign_verify( /** * Returns an array containing the signature followed by the message. */ -int PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk) { size_t siglen; - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_crypto_sign_signature( - sm, &siglen, m, mlen, sk); + crypto_sign_signature(sm, &siglen, m, mlen, sk); - memmove(sm + PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_BYTES, m, mlen); + memmove(sm + SPX_BYTES, m, mlen); *smlen = siglen + mlen; return 0; @@ -372,38 +260,27 @@ int PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_crypto_sign( /** * Verifies a given signature-message pair under a given public key. */ -int PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk) { - - // guarantee alignment of pk - union { - __m128 *_x; - uint8_t pk[PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_CRYPTO_PUBLICKEYBYTES]; - } aligned_pk; - memcpy(aligned_pk.pk, pk, PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_CRYPTO_PUBLICKEYBYTES); - pk = aligned_pk.pk; - - +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk) { /* The API caller does not necessarily know what size a signature should be - but SPHINCS+ signatures are always exactly PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_BYTES. */ - if (smlen < PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_BYTES) { + but SPHINCS+ signatures are always exactly SPX_BYTES. */ + if (smlen < SPX_BYTES) { memset(m, 0, smlen); *mlen = 0; return -1; } - *mlen = smlen - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_BYTES; + *mlen = smlen - SPX_BYTES; - if (PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_crypto_sign_verify( - sm, PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_BYTES, sm + PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_BYTES, *mlen, pk)) { + if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { memset(m, 0, smlen); *mlen = 0; return -1; } /* If verification was successful, move the message to the right place. */ - memmove(m, sm + PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_BYTES, *mlen); + memmove(m, sm + SPX_BYTES, *mlen); return 0; } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/thash.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/thash.h index 739d8da229..8687ccfb4d 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/thash.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/thash.h @@ -1,28 +1,13 @@ -#ifndef PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_THASH_H -#define PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_THASH_H +#ifndef SPX_THASH_H +#define SPX_THASH_H -#include "hash_state.h" +#include "context.h" +#include "params.h" #include -void PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); +#define thash SPX_NAMESPACE(thash) +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/thash_haraka_robust.c b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/thash_haraka_robust.c index 07bf0bf2ad..109502cbc2 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/thash_haraka_robust.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/thash_haraka_robust.c @@ -2,93 +2,44 @@ #include #include "address.h" -#include "hash_state.h" #include "params.h" #include "thash.h" +#include "utils.h" #include "haraka.h" /** - * Takes an array of inblocks concatenated arrays of PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N bytes. + * Takes an array of inblocks concatenated arrays of SPX_N bytes. */ -static void PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_thash( - unsigned char *out, unsigned char *buf, - const unsigned char *in, unsigned int inblocks, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char *bitmask = buf + PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_ADDR_BYTES; +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]) { + PQCLEAN_VLA(uint8_t, buf, SPX_ADDR_BYTES + inblocks * SPX_N); + PQCLEAN_VLA(uint8_t, bitmask, inblocks * SPX_N); unsigned char outbuf[32]; unsigned char buf_tmp[64]; unsigned int i; - (void)pub_seed; /* Suppress an 'unused parameter' warning. */ - if (inblocks == 1) { /* F function */ - /* Since PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N may be smaller than 32, we need a temporary buffer. */ + /* Since SPX_N may be smaller than 32, we need a temporary buffer. */ memset(buf_tmp, 0, 64); - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_addr_to_bytes(buf_tmp, addr); + memcpy(buf_tmp, addr, 32); - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_haraka256(outbuf, buf_tmp, hash_state_seeded); - for (i = 0; i < inblocks * PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N; i++) { - buf_tmp[PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_ADDR_BYTES + i] = in[i] ^ outbuf[i]; + haraka256(outbuf, buf_tmp, ctx); + for (i = 0; i < inblocks * SPX_N; i++) { + buf_tmp[SPX_ADDR_BYTES + i] = in[i] ^ outbuf[i]; } - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_haraka512(outbuf, buf_tmp, hash_state_seeded); - memcpy(out, outbuf, PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N); + haraka512(outbuf, buf_tmp, ctx); + memcpy(out, outbuf, SPX_N); } else { /* All other tweakable hashes*/ - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_addr_to_bytes(buf, addr); - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_haraka_S( - bitmask, inblocks * PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N, buf, PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_ADDR_BYTES, hash_state_seeded); + memcpy(buf, addr, 32); + haraka_S(bitmask, inblocks * SPX_N, buf, SPX_ADDR_BYTES, ctx); - for (i = 0; i < inblocks * PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N; i++) { - buf[PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_ADDR_BYTES + i] = in[i] ^ bitmask[i]; + for (i = 0; i < inblocks * SPX_N; i++) { + buf[SPX_ADDR_BYTES + i] = in[i] ^ bitmask[i]; } - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_haraka_S( - out, PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N, buf, PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N, hash_state_seeded); + haraka_S(out, SPX_N, buf, SPX_ADDR_BYTES + inblocks * SPX_N, ctx); } } - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_ADDR_BYTES + 1 * PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N]; - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_thash( - out, buf, in, 1, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_ADDR_BYTES + 2 * PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N]; - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_thash( - out, buf, in, 2, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_ADDR_BYTES + PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_WOTS_LEN * PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N]; - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_thash( - out, buf, in, PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_WOTS_LEN, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_ADDR_BYTES + PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_FORS_TREES * PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N]; - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_thash( - out, buf, in, PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_FORS_TREES, pub_seed, addr, hash_state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/thash_haraka_robustx4.c b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/thash_haraka_robustx4.c index fc3ee76758..100808a3a5 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/thash_haraka_robustx4.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/thash_haraka_robustx4.c @@ -2,91 +2,92 @@ #include #include "address.h" -#include "haraka.h" #include "params.h" #include "thashx4.h" +#include "harakax4.h" + +#include "utils.h" + /** * 4-way parallel version of thash; takes 4x as much input and output */ -#define thashx4_variant(name, inblocks) \ - void PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_thashx4_##name(unsigned char *out0, unsigned char *out1, unsigned char *out2, \ - unsigned char *out3, const unsigned char *in0, \ - const unsigned char *in1, const unsigned char *in2, \ - const unsigned char *in3, const unsigned char *pub_seed, \ - uint32_t addrx4[4 * 8], const harakactx *state) { \ - unsigned char buf0[PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_ADDR_BYTES + (inblocks)*PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N]; \ - unsigned char buf1[PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_ADDR_BYTES + (inblocks)*PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N]; \ - unsigned char buf2[PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_ADDR_BYTES + (inblocks)*PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N]; \ - unsigned char buf3[PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_ADDR_BYTES + (inblocks)*PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N]; \ - unsigned char bitmask0[(inblocks)*PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N]; \ - unsigned char bitmask1[(inblocks)*PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N]; \ - unsigned char bitmask2[(inblocks)*PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N]; \ - unsigned char bitmask3[(inblocks)*PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N]; \ - unsigned char outbuf[32 * 4]; \ - unsigned char buf_tmp[64 * 4]; \ - unsigned int i; \ - \ - (void)pub_seed; /* Suppress an 'unused parameter' warning. */ \ - \ - if ((inblocks) == 1) { \ - memset(buf_tmp, 0, 64 * 4); \ - \ - /* Generate masks first in buffer */ \ - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_addr_to_bytes(buf_tmp, addrx4 + 0 * 8); \ - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_addr_to_bytes(buf_tmp + 32, addrx4 + 1 * 8); \ - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_addr_to_bytes(buf_tmp + 64, addrx4 + 2 * 8); \ - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_addr_to_bytes(buf_tmp + 96, addrx4 + 3 * 8); \ - \ - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_haraka256x4(outbuf, buf_tmp, state); \ - \ - /* move addresses to make room for inputs; zero old values */ \ - memcpy(buf_tmp + 192, buf_tmp + 96, PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_ADDR_BYTES); \ - memcpy(buf_tmp + 128, buf_tmp + 64, PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_ADDR_BYTES); \ - memcpy(buf_tmp + 64, buf_tmp + 32, PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_ADDR_BYTES); \ - /* skip memcpy(buf_tmp, buf_tmp, PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_ADDR_BYTES); already in place */ \ - \ - /* skip memset(buf_tmp, 0, PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_ADDR_BYTES); remained untouched */ \ - memset(buf_tmp + 32, 0, PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_ADDR_BYTES); \ - /* skip memset(buf_tmp + 64, 0, PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_ADDR_BYTES); contains addr1 */ \ - memset(buf_tmp + 96, 0, PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_ADDR_BYTES); \ - \ - for (i = 0; i < PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N; i++) { \ - buf_tmp[PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_ADDR_BYTES + i] = in0[i] ^ outbuf[i]; \ - buf_tmp[PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_ADDR_BYTES + i + 64] = in1[i] ^ outbuf[i + 32]; \ - buf_tmp[PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_ADDR_BYTES + i + 128] = in2[i] ^ outbuf[i + 64]; \ - buf_tmp[PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_ADDR_BYTES + i + 192] = in3[i] ^ outbuf[i + 96]; \ - } \ - \ - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_haraka512x4(outbuf, buf_tmp, state); \ - \ - memcpy(out0, outbuf, PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N); \ - memcpy(out1, outbuf + 32, PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N); \ - memcpy(out2, outbuf + 64, PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N); \ - memcpy(out3, outbuf + 96, PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N); \ - } else { \ - /* All other tweakable hashes*/ \ - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_addr_to_bytes(buf0, addrx4 + 0 * 8); \ - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_addr_to_bytes(buf1, addrx4 + 1 * 8); \ - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_addr_to_bytes(buf2, addrx4 + 2 * 8); \ - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_addr_to_bytes(buf3, addrx4 + 3 * 8); \ - \ - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_haraka_Sx4(bitmask0, bitmask1, bitmask2, bitmask3, (inblocks)*PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N, buf0, buf1, \ - buf2, buf3, PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_ADDR_BYTES, state); \ - \ - for (i = 0; i < (inblocks)*PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N; i++) { \ - buf0[PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_ADDR_BYTES + i] = in0[i] ^ bitmask0[i]; \ - buf1[PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_ADDR_BYTES + i] = in1[i] ^ bitmask1[i]; \ - buf2[PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_ADDR_BYTES + i] = in2[i] ^ bitmask2[i]; \ - buf3[PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_ADDR_BYTES + i] = in3[i] ^ bitmask3[i]; \ - } \ - \ - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_haraka_Sx4(out0, out1, out2, out3, PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N, buf0, buf1, buf2, buf3, \ - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_ADDR_BYTES + (inblocks)*PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N, state); \ - } \ - } +#define thashx4 SPX_NAMESPACE(thashx4) +void thashx4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addrx4[4 * 8]) { + PQCLEAN_VLA(unsigned char, buf0, SPX_ADDR_BYTES + inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, buf1, SPX_ADDR_BYTES + inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, buf2, SPX_ADDR_BYTES + inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, buf3, SPX_ADDR_BYTES + inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, bitmask0, inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, bitmask1, inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, bitmask2, inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, bitmask3, inblocks * SPX_N); + unsigned char outbuf[32 * 4]; + unsigned char buf_tmp[64 * 4]; + unsigned int i; + + if (inblocks == 1) { + memset(buf_tmp, 0, 64 * 4); + + // Generate masks first in buffer + memcpy(buf_tmp, addrx4 + 0 * 8, 32); + memcpy(buf_tmp + 32, addrx4 + 1 * 8, 32); + memcpy(buf_tmp + 64, addrx4 + 2 * 8, 32); + memcpy(buf_tmp + 96, addrx4 + 3 * 8, 32); + + haraka256x4(outbuf, buf_tmp, ctx); + + /* move addresses to make room for inputs; zero old values */ + memcpy(buf_tmp + 192, buf_tmp + 96, SPX_ADDR_BYTES); + memcpy(buf_tmp + 128, buf_tmp + 64, SPX_ADDR_BYTES); + memcpy(buf_tmp + 64, buf_tmp + 32, SPX_ADDR_BYTES); + /* skip memcpy(buf_tmp, buf_tmp, SPX_ADDR_BYTES); already in place */ -thashx4_variant(1, 1) -thashx4_variant(2, 2) -thashx4_variant(WOTS_LEN, PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_WOTS_LEN) -thashx4_variant(FORS_TREES, PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_FORS_TREES) + /* skip memset(buf_tmp, 0, SPX_ADDR_BYTES); remained untouched */ + memset(buf_tmp + 32, 0, SPX_ADDR_BYTES); + /* skip memset(buf_tmp + 64, 0, SPX_ADDR_BYTES); contains addr1 */ + memset(buf_tmp + 96, 0, SPX_ADDR_BYTES); + + for (i = 0; i < SPX_N; i++) { + buf_tmp[SPX_ADDR_BYTES + i] = in0[i] ^ outbuf[i]; + buf_tmp[SPX_ADDR_BYTES + i + 64] = in1[i] ^ outbuf[i + 32]; + buf_tmp[SPX_ADDR_BYTES + i + 128] = in2[i] ^ outbuf[i + 64]; + buf_tmp[SPX_ADDR_BYTES + i + 192] = in3[i] ^ outbuf[i + 96]; + } + + haraka512x4(outbuf, buf_tmp, ctx); + + memcpy(out0, outbuf, SPX_N); + memcpy(out1, outbuf + 32, SPX_N); + memcpy(out2, outbuf + 64, SPX_N); + memcpy(out3, outbuf + 96, SPX_N); + } else { + /* All other tweakable hashes*/ + memcpy(buf0, addrx4 + 0 * 8, 32); + memcpy(buf1, addrx4 + 1 * 8, 32); + memcpy(buf2, addrx4 + 2 * 8, 32); + memcpy(buf3, addrx4 + 3 * 8, 32); + + haraka_Sx4(bitmask0, bitmask1, bitmask2, bitmask3, inblocks * SPX_N, + buf0, buf1, buf2, buf3, SPX_ADDR_BYTES, ctx); + + for (i = 0; i < inblocks * SPX_N; i++) { + buf0[SPX_ADDR_BYTES + i] = in0[i] ^ bitmask0[i]; + buf1[SPX_ADDR_BYTES + i] = in1[i] ^ bitmask1[i]; + buf2[SPX_ADDR_BYTES + i] = in2[i] ^ bitmask2[i]; + buf3[SPX_ADDR_BYTES + i] = in3[i] ^ bitmask3[i]; + } + + haraka_Sx4(out0, out1, out2, out3, SPX_N, + buf0, buf1, buf2, buf3, SPX_ADDR_BYTES + inblocks * SPX_N, + ctx); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/thashx4.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/thashx4.h index 8b0a0592eb..64798a3727 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/thashx4.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/thashx4.h @@ -1,25 +1,20 @@ -#ifndef PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_THASHX4_H -#define PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_THASHX4_H +#ifndef SPX_THASHX4_H +#define SPX_THASHX4_H #include -#include "hash_state.h" +#include "context.h" +#include "params.h" -#define thashx4_header(inblocks) \ - void PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_thashx4_##inblocks(unsigned char *out0, \ - unsigned char *out1, \ - unsigned char *out2, \ - unsigned char *out3, \ - const unsigned char *in0, \ - const unsigned char *in1, \ - const unsigned char *in2, \ - const unsigned char *in3, \ - const unsigned char *pub_seed, uint32_t addrx4[4*8], \ - const hash_state *state_seeded) - -thashx4_header(1); -thashx4_header(2); -thashx4_header(WOTS_LEN); -thashx4_header(FORS_TREES); +#define thashx4 SPX_NAMESPACE(thashx4) +void thashx4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addrx4[4 * 8]); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/utils.c b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/utils.c index eef5014fd1..177b541fb9 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/utils.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/utils.c @@ -1,34 +1,41 @@ -#include #include +#include "utils.h" + #include "address.h" #include "hash.h" -#include "hash_state.h" #include "params.h" #include "thash.h" -#include "utils.h" /** * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. */ -void PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in) { +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in) { + int i; /* Iterate over out in decreasing order, for big-endianness. */ - for (size_t i = outlen; i > 0; i--) { - out[i - 1] = in & 0xff; + for (i = (signed int)outlen - 1; i >= 0; i--) { + out[i] = in & 0xff; in = in >> 8; } } +void u32_to_bytes(unsigned char *out, uint32_t in) { + out[0] = (unsigned char)(in >> 24); + out[1] = (unsigned char)(in >> 16); + out[2] = (unsigned char)(in >> 8); + out[3] = (unsigned char)in; +} + /** * Converts the inlen bytes in 'in' from big-endian byte order to an integer. */ -unsigned long long PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_bytes_to_ull( - const unsigned char *in, size_t inlen) { +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { unsigned long long retval = 0; + unsigned int i; - for (size_t i = 0; i < inlen; i++) { + for (i = 0; i < inlen; i++) { retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); } return retval; @@ -38,94 +45,80 @@ unsigned long long PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_bytes_to_ull( * Computes a root node given a leaf and an auth path. * Expects address to be complete other than the tree_height and tree_index. */ -void PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]) { uint32_t i; - unsigned char buffer[2 * PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N]; + unsigned char buffer[2 * SPX_N]; /* If leaf_idx is odd (last bit = 1), current path element is a right child and auth_path has to go left. Otherwise it is the other way around. */ if (leaf_idx & 1) { - memcpy(buffer + PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N, leaf, PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N); + memcpy(buffer + SPX_N, leaf, SPX_N); + memcpy(buffer, auth_path, SPX_N); } else { - memcpy(buffer, leaf, PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N); - memcpy(buffer + PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N, auth_path, PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N); + memcpy(buffer, leaf, SPX_N); + memcpy(buffer + SPX_N, auth_path, SPX_N); } - auth_path += PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N; + auth_path += SPX_N; for (i = 0; i < tree_height - 1; i++) { leaf_idx >>= 1; idx_offset >>= 1; /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_set_tree_height(addr, i + 1); - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_set_tree_index( - addr, leaf_idx + idx_offset); + set_tree_height(addr, i + 1); + set_tree_index(addr, leaf_idx + idx_offset); /* Pick the right or left neighbor, depending on parity of the node. */ if (leaf_idx & 1) { - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_thash_2( - buffer + PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N); + thash(buffer + SPX_N, buffer, 2, ctx, addr); + memcpy(buffer, auth_path, SPX_N); } else { - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_thash_2( - buffer, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer + PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N, auth_path, PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N); + thash(buffer, buffer, 2, ctx, addr); + memcpy(buffer + SPX_N, auth_path, SPX_N); } - auth_path += PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N; + auth_path += SPX_N; } /* The last iteration is exceptional; we do not copy an auth_path node. */ leaf_idx >>= 1; idx_offset >>= 1; - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_set_tree_height(addr, tree_height); - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_set_tree_index( - addr, leaf_idx + idx_offset); - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_thash_2( - root, buffer, pub_seed, addr, hash_state_seeded); + set_tree_height(addr, tree_height); + set_tree_index(addr, leaf_idx + idx_offset); + thash(root, buffer, 2, ctx, addr); } /** * For a given leaf index, computes the authentication path and the resulting * root node using Merkle's TreeHash algorithm. * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_ADDR_TYPE_FORSTREE). + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). * Applies the offset idx_offset to indices before building addresses, so that * it is possible to continue counting indices across trees. */ -static void PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_treehash( - unsigned char *root, unsigned char *auth_path, - unsigned char *stack, unsigned int *heights, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - +void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx * /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]) { + PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); + PQCLEAN_VLA(unsigned int, heights, tree_height + 1); unsigned int offset = 0; uint32_t idx; uint32_t tree_idx; for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { /* Add the next leaf node to the stack. */ - gen_leaf(stack + offset * PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N, - sk_seed, pub_seed, idx + idx_offset, tree_addr, - hash_state_seeded); + gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); offset++; heights[offset - 1] = 0; /* If this is a node we need for the auth path.. */ if ((leaf_idx ^ 0x1) == idx) { - memcpy(auth_path, stack + (offset - 1)*PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N, PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N); + memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); } /* While the top-most nodes are of equal height.. */ @@ -134,66 +127,22 @@ static void PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_treehash( tree_idx = (idx >> (heights[offset - 1] + 1)); /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_set_tree_height( - tree_addr, heights[offset - 1] + 1); - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_set_tree_index( - tree_addr, tree_idx + (idx_offset >> (heights[offset - 1] + 1))); + set_tree_height(tree_addr, heights[offset - 1] + 1); + set_tree_index(tree_addr, + tree_idx + (idx_offset >> (heights[offset - 1] + 1))); /* Hash the top-most nodes from the stack together. */ - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_thash_2( - stack + (offset - 2)*PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N, stack + (offset - 2)*PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N, - pub_seed, tree_addr, hash_state_seeded); + thash(stack + (offset - 2)*SPX_N, + stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); offset--; /* Note that the top-most node is now one layer higher. */ heights[offset - 1]++; /* If this is a node we need for the auth path.. */ if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_path + heights[offset - 1]*PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N, - stack + (offset - 1)*PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N, PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N); + memcpy(auth_path + heights[offset - 1]*SPX_N, + stack + (offset - 1)*SPX_N, SPX_N); } } } - memcpy(root, stack, PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N); -} - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_FORS_HEIGHT + 1)*PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N]; - unsigned int heights[PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_FORS_HEIGHT + 1]; - - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_FORS_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_TREE_HEIGHT + 1)*PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N]; - unsigned int heights[PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_TREE_HEIGHT + 1]; - - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_TREE_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); + memcpy(root, stack, SPX_N); } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/utils.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/utils.h index c7bec52761..64f5d5a53a 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/utils.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/utils.h @@ -1,64 +1,58 @@ -#ifndef PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_UTILS_H -#define PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_UTILS_H +#ifndef SPX_UTILS_H +#define SPX_UTILS_H -#include "hash_state.h" -#include "params.h" -#include #include +#include "compat.h" +#include "context.h" +#include "params.h" + + +/* To support MSVC use alloca() instead of VLAs. See #20. */ + + /** * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. */ -void PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in); +#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in); +#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) +void u32_to_bytes(unsigned char *out, uint32_t in); /** * Converts the inlen bytes in 'in' from big-endian byte order to an integer. */ -unsigned long long PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_bytes_to_ull( - const unsigned char *in, size_t inlen); +#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); /** * Computes a root node given a leaf and an auth path. * Expects address to be complete other than the tree_height and tree_index. */ -void PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); +#define compute_root SPX_NAMESPACE(compute_root) +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]); /** * For a given leaf index, computes the authentication path and the resulting * root node using Merkle's TreeHash algorithm. * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_ADDR_TYPE_FORSTREE). + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). * Applies the offset idx_offset to indices before building addresses, so that * it is possible to continue counting indices across trees. */ -void PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); +#define treehash SPX_NAMESPACE(treehash) +void treehash(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx *ctx /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]); -void PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/utilsx4.c b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/utilsx4.c index 966a19cfad..1638677194 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/utilsx4.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/utilsx4.c @@ -1,98 +1,138 @@ +#include + +#include "utilsx4.h" + #include "address.h" #include "params.h" #include "thashx4.h" #include "utils.h" -#include "utilsx4.h" -#include - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. +/* + * Generate the entire Merkle tree, computing the authentication path for leaf_idx, + * and the resulting root node using Merkle's TreeHash algorithm. * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_ADDR_TYPE_FORSTREE). + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) + * + * This expects tree_addrx4 to be initialized to 4 parallel addr structures for + * the Merkle tree nodes + * * Applies the offset idx_offset to indices before building addresses, so that * it is possible to continue counting indices across trees. + * + * This works by using the standard Merkle tree building algorithm, except + * that each 'node' tracked is actually 4 consecutive nodes in the real tree. + * When we combine two logical nodes ABCD and WXYZ, we perform the H + * operation on adjacent real nodes, forming the parent logical node + * (AB)(CD)(WX)(YZ) + * + * When we get to the top two levels of the real tree (where there is only + * one logical node), we continue this operation two more times; the right + * most real node will by the actual root (and the other 3 nodes will be + * garbage). We follow the same thashx4 logic so that the 'extract + * authentication path components' part of the loop is still executed (and + * to simplify the code somewhat) + * + * This currently assumes tree_height >= 2; I suspect that doing an adjusting + * idx, addr_idx on the gen_leafx4 call if tree_height < 2 would fix it; since + * we don't actually use such short trees, I haven't bothered */ -#define treehashx4_variant(name, tree_height) \ - void PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_treehashx4_##name( \ - unsigned char *rootx4, unsigned char *auth_pathx4, const unsigned char *sk_seed, \ - const unsigned char *pub_seed, const uint32_t leaf_idx[4], uint32_t idx_offset[4], \ - void (*gen_leafx4)(unsigned char * /* leaf0 */, unsigned char * /* leaf1 */, \ - unsigned char * /* leaf2 */, unsigned char * /* leaf3 */, \ - const unsigned char * /* sk_seed */, \ - const unsigned char * /* pub_seed */, uint32_t /* addr_idx0 */, \ - uint32_t /* addr_idx1 */, uint32_t /* addr_idx2 */, \ - uint32_t /* addr_idx3 */, const uint32_t[8] /* tree_addr */, \ - const hash_state * /* state_seeded */), \ - uint32_t tree_addrx4[4 * 8], const hash_state *state_seeded) { \ - unsigned char stackx4[4 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N]; \ - unsigned int heights[(tree_height) + 1]; \ - unsigned int offset = 0; \ - uint32_t idx; \ - uint32_t tree_idx; \ - unsigned int j; \ - \ - for (idx = 0; idx < (uint32_t)(1 << (tree_height)); idx++) { \ - /* Add the next leaf node to the stack. */ \ - gen_leafx4(stackx4 + 0 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N + offset * PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N, \ - stackx4 + 1 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N + offset * PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N, \ - stackx4 + 2 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N + offset * PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N, \ - stackx4 + 3 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N + offset * PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N, sk_seed, \ - pub_seed, idx + idx_offset[0], idx + idx_offset[1], idx + idx_offset[2], \ - idx + idx_offset[3], tree_addrx4, state_seeded); \ - offset++; \ - heights[offset - 1] = 0; \ - \ - /* If this is a node we need for the auth path.. */ \ - for (j = 0; j < 4; j++) { \ - if ((leaf_idx[j] ^ 0x1) == idx) { \ - memcpy(auth_pathx4 + j * (tree_height)*PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N, \ - stackx4 + j * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N + (offset - 1) * PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N, \ - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N); \ - } \ - } \ - \ - /* While the top-most nodes are of equal height.. */ \ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { \ - /* Compute index of the new node, in the next layer. */ \ - tree_idx = (idx >> (heights[offset - 1] + 1)); \ - \ - /* Set the address of the node we're creating. */ \ - for (j = 0; j < 4; j++) { \ - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_set_tree_height(tree_addrx4 + j * 8, heights[offset - 1] + 1); \ - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_set_tree_index(tree_addrx4 + j * 8, \ - tree_idx + (idx_offset[j] >> (heights[offset - 1] + 1))); \ - } \ - /* Hash the top-most nodes from the stack together. */ \ - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_thashx4_2(stackx4 + 0 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N + (offset - 2) * PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N, \ - stackx4 + 1 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N + (offset - 2) * PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N, \ - stackx4 + 2 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N + (offset - 2) * PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N, \ - stackx4 + 3 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N + (offset - 2) * PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N, \ - stackx4 + 0 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N + (offset - 2) * PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N, \ - stackx4 + 1 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N + (offset - 2) * PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N, \ - stackx4 + 2 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N + (offset - 2) * PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N, \ - stackx4 + 3 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N + (offset - 2) * PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N, \ - pub_seed, tree_addrx4, state_seeded); \ - offset--; \ - /* Note that the top-most node is now one layer higher. */ \ - heights[offset - 1]++; \ - \ - /* If this is a node we need for the auth path.. */ \ - for (j = 0; j < 4; j++) { \ - if (((leaf_idx[j] >> heights[offset - 1]) ^ 0x1) == tree_idx) { \ - memcpy(auth_pathx4 + j * (tree_height)*PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N + \ - heights[offset - 1] * PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N, \ - stackx4 + j * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N + (offset - 1) * PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N, \ - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N); \ - } \ - } \ - } \ - } \ - \ - for (j = 0; j < 4; j++) { \ - memcpy(rootx4 + j * PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N, stackx4 + j * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N, PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N); \ - } \ - } +void treehashx4(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, + uint32_t tree_height, + void (*gen_leafx4)( + unsigned char * /* Where to write the leaves */, + const spx_ctx *, + uint32_t idx, void *info), + uint32_t tree_addrx4[4 * 8], + void *info) { + /* This is where we keep the intermediate nodes */ + PQCLEAN_VLA(unsigned char, stackx4, tree_height * 4 * SPX_N); + uint32_t left_adj = 0, prev_left_adj = 0; /* When we're doing the top 3 */ + /* levels, the left-most part of the tree isn't at the beginning */ + /* of current[]. These give the offset of the actual start */ + + uint32_t idx; + uint32_t max_idx = (1U << (tree_height - 2)) - 1; + for (idx = 0;; idx++) { + unsigned char current[4 * SPX_N]; /* Current logical node */ + gen_leafx4( current, ctx, 4 * idx + idx_offset, + info ); -treehashx4_variant(FORS_HEIGHT, PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_FORS_HEIGHT) + /* Now combine the freshly generated right node with previously */ + /* generated left ones */ + uint32_t internal_idx_offset = idx_offset; + uint32_t internal_idx = idx; + uint32_t internal_leaf = leaf_idx; + uint32_t h; /* The height we are in the Merkle tree */ + for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { + + /* Special processing if we're at the top of the tree */ + if (h >= tree_height - 2) { + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[3 * SPX_N], SPX_N ); + return; + } + /* The tree indexing logic is a bit off in this case */ + /* Adjust it so that the left-most node of the part of */ + /* the tree that we're processing has index 0 */ + prev_left_adj = left_adj; + left_adj = 4U - (1 << (tree_height - h - 1)); + } + + /* Check if we hit the top of the tree */ + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[3 * SPX_N], SPX_N ); + return; + } + + /* + * Check if one of the nodes we have is a part of the + * authentication path; if it is, write it out + */ + if ((((internal_idx << 2) ^ internal_leaf) & ~0x3U) == 0) { + memcpy( &auth_path[ h * SPX_N ], + ¤t[(((internal_leaf & 3) ^ 1) + prev_left_adj) * SPX_N], + SPX_N ); + } + + /* + * Check if we're at a left child; if so, stop going up the stack + * Exception: if we've reached the end of the tree, keep on going + * (so we combine the last 4 nodes into the one root node in two + * more iterations) + */ + if ((internal_idx & 1) == 0 && idx < max_idx) { + break; + } + + /* Ok, we're at a right node (or doing the top 3 levels) */ + /* Now combine the left and right logical nodes together */ + + /* Set the address of the node we're creating. */ + unsigned int j; + internal_idx_offset >>= 1; + for (j = 0; j < 4; j++) { + set_tree_height(tree_addrx4 + j * 8, h + 1); + set_tree_index(tree_addrx4 + j * 8, + (4 / 2) * (internal_idx & ~1U) + j - left_adj + internal_idx_offset ); + } + unsigned char *left = &stackx4[h * 4 * SPX_N]; + thashx4( ¤t[0 * SPX_N], + ¤t[1 * SPX_N], + ¤t[2 * SPX_N], + ¤t[3 * SPX_N], + &left [0 * SPX_N], + &left [2 * SPX_N], + ¤t[0 * SPX_N], + ¤t[2 * SPX_N], + 2, ctx, tree_addrx4); + } + + /* We've hit a left child; save the current for when we get the */ + /* corresponding right right */ + memcpy( &stackx4[h * 4 * SPX_N], current, 4 * SPX_N); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/utilsx4.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/utilsx4.h index fd8340d73a..facb874b18 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/utilsx4.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/utilsx4.h @@ -1,38 +1,30 @@ -#ifndef PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_UTILSX4_H -#define PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_UTILSX4_H - -#include "hash_state.h" -#include "params.h" +#ifndef SPX_UTILSX4_H +#define SPX_UTILSX4_H #include +#include "context.h" +#include "params.h" + /** * For a given leaf index, computes the authentication path and the resulting * root node using Merkle's TreeHash algorithm. * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_ADDR_TYPE_FORSTREE). + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). * Applies the offset idx_offset to indices before building addresses, so that * it is possible to continue counting indices across trees. + * + * This implementation uses AVX to compute internal nodes 4 at a time (in + * parallel) */ -void PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_treehashx4_FORS_HEIGHT(unsigned char *rootx4, - unsigned char *auth_pathx4, - const unsigned char *sk_seed, - const unsigned char *pub_seed, - const uint32_t leaf_idx[4], - uint32_t idx_offset[4], - void (*gen_leafx4)(unsigned char * /* leaf0 */, - unsigned char * /* leaf1 */, - unsigned char * /* leaf2 */, - unsigned char * /* leaf3 */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx0 */, - uint32_t /* addr_idx1 */, - uint32_t /* addr_idx2 */, - uint32_t /* addr_idx3 */, - const uint32_t[8] /* tree_addr */, - const hash_state * /* state_seeded */), - uint32_t tree_addrx4[4 * 8], - const hash_state *state_seeded); +#define treehashx4 SPX_NAMESPACE(treehashx4) +void treehashx4(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leafx4)( + unsigned char * /* Where to write the leaves */, + const spx_ctx * /* ctx */, + uint32_t addr_idx, void *info), + uint32_t tree_addrx4[4 * 8], void *info); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/wots.c b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/wots.c index 3573fe25df..4d5041ce05 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/wots.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/wots.c @@ -1,106 +1,104 @@ #include #include +#include "wots.h" + #include "address.h" #include "hash.h" -#include "hash_state.h" #include "hashx4.h" #include "params.h" #include "thash.h" #include "thashx4.h" #include "utils.h" -#include "wots.h" +#include "utilsx4.h" +#include "wotsx4.h" // TODO clarify address expectations, and make them more uniform. // TODO i.e. do we expect types to be set already? // TODO and do we expect modifications or copies? /** - * Computes the starting value for a chain, i.e. the secret key. - * Expects the address to be complete up to the chain address. - */ -static void wots_gen_sk(unsigned char *sk, const unsigned char *sk_seed, - uint32_t wots_addr[8], const hash_state *state_seeded) { - /* Make sure that the hash address is actually zeroed. */ - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_set_hash_addr(wots_addr, 0); - - /* Generate sk element. */ - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_prf_addr(sk, sk_seed, wots_addr, state_seeded); -} - -/** - * 4-way parallel version of wots_gen_sk; expects 4x as much space in sk + * Computes up the chains */ -static void wots_gen_skx4(unsigned char *skx4, const unsigned char *sk_seed, - uint32_t wots_addrx4[4 * 8], const hash_state *state_seeded) { - unsigned int j; - - /* Make sure that the hash address is actually zeroed. */ +static void gen_chains( + unsigned char *out, + const unsigned char *in, + unsigned int start[SPX_WOTS_LEN], + const unsigned int steps[SPX_WOTS_LEN], + const spx_ctx *ctx, + uint32_t addr[8]) { + uint32_t i, j, k, idx, watching; + int done; + unsigned char empty[SPX_N]; + unsigned char *bufs[4]; + uint32_t addrs[8 * 4]; + + int l; + uint16_t counts[SPX_WOTS_W] = { 0 }; + uint16_t idxs[SPX_WOTS_LEN]; + uint16_t total, newTotal; + + /* set addrs = {addr, addr, addr, addr} */ for (j = 0; j < 4; j++) { - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_set_hash_addr(wots_addrx4 + j * 8, 0); + memcpy(addrs + j * 8, addr, sizeof(uint32_t) * 8); } - /* Generate sk element. */ - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_prf_addrx4(skx4 + 0 * PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N, - skx4 + 1 * PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N, - skx4 + 2 * PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N, - skx4 + 3 * PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N, - sk_seed, wots_addrx4, - state_seeded); -} - -/** - * Computes the chaining function. - * out and in have to be n-byte arrays. - * - * Interprets in as start-th value of the chain. - * addr has to contain the address of the chain. - */ -static void gen_chain(unsigned char *out, const unsigned char *in, - unsigned int start, unsigned int steps, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *state_seeded) { - uint32_t i; - /* Initialize out with the value at position 'start'. */ - memcpy(out, in, PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N); + memcpy(out, in, SPX_WOTS_LEN * SPX_N); - /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_WOTS_W; i++) { - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_set_hash_addr(addr, i); - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_thash_1(out, out, pub_seed, addr, state_seeded); + /* Sort the chains in reverse order by steps using counting sort. */ + for (i = 0; i < SPX_WOTS_LEN; i++) { + counts[steps[i]]++; + } + total = 0; + for (l = SPX_WOTS_W - 1; l >= 0; l--) { + newTotal = counts[l] + total; + counts[l] = total; + total = newTotal; + } + for (i = 0; i < SPX_WOTS_LEN; i++) { + idxs[counts[steps[i]]] = (uint16_t)i; + counts[steps[i]]++; } -} -/** - * 4-way parallel version of gen_chain; expects 4x as much space in out, and - * 4x as much space in inx4. Assumes start and step identical across chains. - */ -static void gen_chainx4(unsigned char *outx4, const unsigned char *inx4, - unsigned int start, unsigned int steps, - const unsigned char *pub_seed, uint32_t addrx4[4 * 8], - const hash_state *state_seeded) { - uint32_t i; - unsigned int j; + /* We got our work cut out for us: do it! */ + for (i = 0; i < SPX_WOTS_LEN; i += 4) { + for (j = 0; j < 4 && i + j < SPX_WOTS_LEN; j++) { + idx = idxs[i + j]; + set_chain_addr(addrs + j * 8, idx); + bufs[j] = out + SPX_N * idx; + } - /* Initialize outx4 with the value at position 'start'. */ - memcpy(outx4, inx4, 4 * PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N); + /* As the chains are sorted in reverse order, we know that the first + * chain is the longest and the last one is the shortest. We keep + * an eye on whether the last chain is done and then on the one before, + * et cetera. */ + watching = 3; + done = 0; + while (i + watching >= SPX_WOTS_LEN) { + bufs[watching] = &empty[0]; + watching--; + } - /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_WOTS_W; i++) { - for (j = 0; j < 4; j++) { - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_set_hash_addr(addrx4 + j * 8, i); + for (k = 0;; k++) { + while (k == steps[idxs[i + watching]]) { + bufs[watching] = &empty[0]; + if (watching == 0) { + done = 1; + break; + } + watching--; + } + if (done) { + break; + } + for (j = 0; j < watching + 1; j++) { + set_hash_addr(addrs + j * 8, k + start[idxs[i + j]]); + } + + thashx4(bufs[0], bufs[1], bufs[2], bufs[3], + bufs[0], bufs[1], bufs[2], bufs[3], 1, ctx, addrs); } - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_thashx4_1(outx4 + 0 * PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N, - outx4 + 1 * PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N, - outx4 + 2 * PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N, - outx4 + 3 * PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N, - outx4 + 0 * PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N, - outx4 + 1 * PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N, - outx4 + 2 * PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N, - outx4 + 3 * PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N, - pub_seed, addrx4, - state_seeded); } } @@ -109,7 +107,8 @@ static void gen_chainx4(unsigned char *outx4, const unsigned char *inx4, * Interprets an array of bytes as integers in base w. * This only works when log_w is a divisor of 8. */ -static void base_w(unsigned int *output, const int out_len, const unsigned char *input) { +static void base_w(unsigned int *output, const int out_len, + const unsigned char *input) { int in = 0; int out = 0; unsigned char total = 0; @@ -122,119 +121,149 @@ static void base_w(unsigned int *output, const int out_len, const unsigned char in++; bits += 8; } - bits -= PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_WOTS_LOGW; - output[out] = (unsigned int)(total >> bits) & (PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_WOTS_W - 1); + bits -= SPX_WOTS_LOGW; + output[out] = (total >> bits) & (SPX_WOTS_W - 1); out++; } } /* Computes the WOTS+ checksum over a message (in base_w). */ -static void wots_checksum(unsigned int *csum_base_w, const unsigned int *msg_base_w) { +static void wots_checksum(unsigned int *csum_base_w, + const unsigned int *msg_base_w) { unsigned int csum = 0; - unsigned char csum_bytes[(PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_WOTS_LEN2 * PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_WOTS_LOGW + 7) / 8]; + unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; unsigned int i; /* Compute checksum. */ - for (i = 0; i < PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_WOTS_LEN1; i++) { - csum += PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_WOTS_W - 1 - msg_base_w[i]; + for (i = 0; i < SPX_WOTS_LEN1; i++) { + csum += SPX_WOTS_W - 1 - msg_base_w[i]; } /* Convert checksum to base_w. */ /* Make sure expected empty zero bits are the least significant bits. */ - csum = csum << (8 - ((PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_WOTS_LEN2 * PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_WOTS_LOGW) % 8)); - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); - base_w(csum_base_w, PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_WOTS_LEN2, csum_bytes); + csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); + ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); + base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); } /* Takes a message and derives the matching chain lengths. */ -static void chain_lengths(unsigned int *lengths, const unsigned char *msg) { - base_w(lengths, PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_WOTS_LEN1, msg); - wots_checksum(lengths + PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_WOTS_LEN1, lengths); +void chain_lengths(unsigned int *lengths, const unsigned char *msg) { + base_w(lengths, SPX_WOTS_LEN1, msg); + wots_checksum(lengths + SPX_WOTS_LEN1, lengths); } /** - * WOTS key generation. Takes a 32 byte sk_seed, expands it to WOTS private key - * elements and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. * * Writes the computed public key to 'pk'. */ -void PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_wots_gen_pk(unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *state_seeded) { +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]) { + unsigned int steps[SPX_WOTS_LEN]; + unsigned int start[SPX_WOTS_LEN]; uint32_t i; - unsigned int j; - uint32_t addrx4[4 * 8]; - unsigned char pkbuf[4 * PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N]; + chain_lengths(start, msg); - for (j = 0; j < 4; j++) { - memcpy(addrx4 + j * 8, addr, sizeof(uint32_t) * 8); - } - - /* The last iteration typically does not have complete set of 4 chains, - but because we use pkbuf, this is not an issue -- we still do as many - in parallel as possible. */ - for (i = 0; i < ((PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_WOTS_LEN + 3) & ~0x3); i += 4) { - for (j = 0; j < 4; j++) { - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_set_chain_addr(addrx4 + j * 8, i + j); - } - wots_gen_skx4(pkbuf, sk_seed, addrx4, state_seeded); - gen_chainx4(pkbuf, pkbuf, 0, PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_WOTS_W - 1, pub_seed, addrx4, state_seeded); - for (j = 0; j < 4; j++) { - if (i + j < PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_WOTS_LEN) { - memcpy(pk + (i + j)*PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N, pkbuf + j * PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N, PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N); - } - } + for (i = 0; i < SPX_WOTS_LEN; i++) { + steps[i] = SPX_WOTS_W - 1 - start[i]; } - // Get rid of unused argument variable. - (void)state_seeded; + gen_chains(pk, sig, start, steps, ctx, addr); } -/** - * Takes a n-byte message and the 32-byte sk_see to compute a signature 'sig'. +/* + * This generates 4 sequential WOTS public keys + * It also generates the WOTS signature if leaf_info indicates + * that we're signing with one of these WOTS keys */ -void PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_wots_sign(unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); +void wots_gen_leafx4(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info) { + struct leaf_info_x4 *info = v_info; + uint32_t *leaf_addr = info->leaf_addr; + uint32_t *pk_addr = info->pk_addr; + unsigned int i, j, k; + unsigned char pk_buffer[ 4 * SPX_WOTS_BYTES ]; + unsigned wots_offset = SPX_WOTS_BYTES; + unsigned char *buffer; + uint32_t wots_k_mask; + unsigned wots_sign_index; + + if (((leaf_idx ^ info->wots_sign_leaf) & ~3U) == 0) { + /* We're traversing the leaf that's signing; generate the WOTS */ + /* signature */ + wots_k_mask = 0; + wots_sign_index = info->wots_sign_leaf & 3; /* Which of of the 4 */ + /* 4 slots do the signatures come from */ + } else { + /* Nope, we're just generating pk's; turn off the signature logic */ + wots_k_mask = (uint32_t)~0; + wots_sign_index = 0; + } - for (i = 0; i < PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_WOTS_LEN; i++) { - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_set_chain_addr(addr, i); - wots_gen_sk(sig + i * PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N, sk_seed, addr, state_seeded); - gen_chain(sig + i * PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N, sig + i * PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N, 0, lengths[i], pub_seed, addr, state_seeded); + for (j = 0; j < 4; j++) { + set_keypair_addr( leaf_addr + j * 8, leaf_idx + j ); + set_keypair_addr( pk_addr + j * 8, leaf_idx + j ); } - // avoid unused argument - (void)state_seeded; -} + for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { + uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k to */ + /* the step if we're generating a signature, ~0 if we're not */ -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_WOTS_LEN]; - uint32_t i; + /* Start with the secret seed */ + for (j = 0; j < 4; j++) { + set_chain_addr(leaf_addr + j * 8, i); + set_hash_addr(leaf_addr + j * 8, 0); + set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTSPRF); + } + prf_addrx4(buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + buffer + 2 * wots_offset, + buffer + 3 * wots_offset, + ctx, leaf_addr); - chain_lengths(lengths, msg); + for (j = 0; j < 4; j++) { + set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTS); + } + + /* Iterate down the WOTS chain */ + for (k = 0;; k++) { + /* Check if one of the values we have needs to be saved as a */ + /* part of the WOTS signature */ + if (k == wots_k) { + memcpy( info->wots_sig + i * SPX_N, + buffer + wots_sign_index * wots_offset, SPX_N ); + } - for (i = 0; i < PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_WOTS_LEN; i++) { - PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_set_chain_addr(addr, i); - gen_chain(pk + i * PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N, sig + i * PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_N, - lengths[i], PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_WOTS_W - 1 - lengths[i], pub_seed, addr, - state_seeded); + /* Check if we hit the top of the chain */ + if (k == SPX_WOTS_W - 1) { + break; + } + + /* Iterate one step on all 4 chains */ + for (j = 0; j < 4; j++) { + set_hash_addr(leaf_addr + j * 8, k); + } + thashx4(buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + buffer + 2 * wots_offset, + buffer + 3 * wots_offset, + buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + buffer + 2 * wots_offset, + buffer + 3 * wots_offset, 1, ctx, leaf_addr); + } } - // avoid unused argument - (void)state_seeded; + /* Do the final thash to generate the public keys */ + thashx4(dest + 0 * SPX_N, + dest + 1 * SPX_N, + dest + 2 * SPX_N, + dest + 3 * SPX_N, + pk_buffer + 0 * wots_offset, + pk_buffer + 1 * wots_offset, + pk_buffer + 2 * wots_offset, + pk_buffer + 3 * wots_offset, SPX_WOTS_LEN, ctx, pk_addr); } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/wots.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/wots.h index d84a4725a7..4e7692eeef 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/wots.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/wots.h @@ -1,41 +1,25 @@ -#ifndef PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_WOTS_H -#define PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_WOTS_H +#ifndef SPX_WOTS_H +#define SPX_WOTS_H -#include "hash_state.h" -#include "params.h" #include -/** - * WOTS key generation. Takes a 32 byte seed for the private key, expands it to - * a full WOTS private key and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_wots_gen_pk( - unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -/** - * Takes a n-byte message and the 32-byte seed for the private key to compute a - * signature that is placed at 'sig'. - */ -void PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_wots_sign( - unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *hash_state_seeded); +#include "context.h" +#include "params.h" /** * Takes a WOTS signature and an n-byte message, computes a WOTS public key. * * Writes the computed public key to 'pk'. */ -void PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_wots_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); +#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]); + +/* + * Compute the chain lengths needed for a given message hash + */ +#define chain_lengths SPX_NAMESPACE(chain_lengths) +void chain_lengths(unsigned int *lengths, const unsigned char *msg); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/wotsx4.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/wotsx4.h new file mode 100644 index 0000000000..cd634f1743 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/wotsx4.h @@ -0,0 +1,41 @@ +#ifndef WOTSX4_H_ +#define WOTSX4_H_ + +#include + +#include "params.h" + +/* + * This is here to provide an interface to the internal wots_gen_leafx4 + * routine. While this routine is not referenced in the package outside of + * wots.c, it is called from the stand-alone benchmark code to characterize + * the performance + */ +struct leaf_info_x4 { + unsigned char *wots_sig; + uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ + uint32_t *wots_steps; + uint32_t leaf_addr[4 * 8]; + uint32_t pk_addr[4 * 8]; +}; + +/* Macro to set the leaf_info to something 'benign', that is, it would */ +/* run with the same time as it does during the real signing process */ +/* Used only by the benchmark code */ +#define INITIALIZE_LEAF_INFO_X4(info, addr, step_buffer) { \ + (info).wots_sig = 0; \ + (info).wots_sign_leaf = ~0; \ + (info).wots_steps = step_buffer; \ + int i; \ + for (i=0; i<4; i++) { \ + memcpy( &(info).leaf_addr[8*i], addr, 32 ); \ + memcpy( &(info).pk_addr[8*i], addr, 32 ); \ + } \ + } + +#define wots_gen_leafx4 SPX_NAMESPACE(wots_gen_leafx4) +void wots_gen_leafx4(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info); + +#endif /* WOTSX4_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/address.c b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/address.c index 11da5bb27b..b956e9cb29 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/address.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/address.c @@ -1,78 +1,91 @@ #include +#include #include "address.h" #include "params.h" #include "utils.h" -void PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]) { - int i; - - for (i = 0; i < 8; i++) { - PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_ull_to_bytes( - bytes + i * 4, 4, addr[i]); - } -} - -void PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_set_layer_addr( - uint32_t addr[8], uint32_t layer) { - addr[0] = layer; +/* + * Specify which level of Merkle tree (the "layer") we're working on + */ +void set_layer_addr(uint32_t addr[8], uint32_t layer) { + ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; } -void PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_set_tree_addr( - uint32_t addr[8], uint64_t tree) { - addr[1] = 0; - addr[2] = (uint32_t) (tree >> 32); - addr[3] = (uint32_t) tree; +/* + * Specify which Merkle tree within the level (the "tree address") we're working on + */ +void set_tree_addr(uint32_t addr[8], uint64_t tree) { + ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); } -void PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_set_type( - uint32_t addr[8], uint32_t type) { - addr[4] = type; +/* + * Specify the reason we'll use this address structure for, that is, what + * hash will we compute with it. This is used so that unrelated types of + * hashes don't accidentally get the same address structure. The type will be + * one of the SPX_ADDR_TYPE constants + */ +void set_type(uint32_t addr[8], uint32_t type) { + ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; } -void PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; +/* + * Copy the layer and tree fields of the address structure. This is used + * when we're doing multiple types of hashes within the same Merkle tree + */ +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); } /* These functions are used for OTS addresses. */ -void PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_set_keypair_addr( - uint32_t addr[8], uint32_t keypair) { - addr[5] = keypair; +/* + * Specify which Merkle leaf we're working on; that is, which OTS keypair + * we're talking about. + */ +void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { + ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; } -void PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; - out[5] = in[5]; +/* + * Copy the layer, tree and keypair fields of the address structure. This is + * used when we're doing multiple things within the same OTS keypair + */ +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); + ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; } -void PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_set_chain_addr( - uint32_t addr[8], uint32_t chain) { - addr[6] = chain; +/* + * Specify which Merkle chain within the OTS we're working with + * (the chain address) + */ +void set_chain_addr(uint32_t addr[8], uint32_t chain) { + ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; } -void PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_set_hash_addr( - uint32_t addr[8], uint32_t hash) { - addr[7] = hash; +/* + * Specify where in the Merkle chain we are +* (the hash address) + */ +void set_hash_addr(uint32_t addr[8], uint32_t hash) { + ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; } /* These functions are used for all hash tree addresses (including FORS). */ -void PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_set_tree_height( - uint32_t addr[8], uint32_t tree_height) { - addr[6] = tree_height; +/* + * Specify the height of the node in the Merkle/FORS tree we are in + * (the tree height) + */ +void set_tree_height(uint32_t addr[8], uint32_t tree_height) { + ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; } -void PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_set_tree_index( - uint32_t addr[8], uint32_t tree_index) { - addr[7] = tree_index; +/* + * Specify the distance from the left edge of the node in the Merkle/FORS tree + * (the tree index) + */ +void set_tree_index(uint32_t addr[8], uint32_t tree_index) { + u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/address.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/address.h index e1995b060a..24a84eb40c 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/address.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/address.h @@ -1,50 +1,52 @@ -#ifndef PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_ADDRESS_H -#define PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_ADDRESS_H +#ifndef SPX_ADDRESS_H +#define SPX_ADDRESS_H #include -#define PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_ADDR_TYPE_WOTS 0 -#define PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_ADDR_TYPE_WOTSPK 1 -#define PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_ADDR_TYPE_HASHTREE 2 -#define PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_ADDR_TYPE_FORSTREE 3 -#define PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_ADDR_TYPE_FORSPK 4 +#include "params.h" -void PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]); +/* The hash types that are passed to set_type */ +#define SPX_ADDR_TYPE_WOTS 0 +#define SPX_ADDR_TYPE_WOTSPK 1 +#define SPX_ADDR_TYPE_HASHTREE 2 +#define SPX_ADDR_TYPE_FORSTREE 3 +#define SPX_ADDR_TYPE_FORSPK 4 +#define SPX_ADDR_TYPE_WOTSPRF 5 +#define SPX_ADDR_TYPE_FORSPRF 6 -void PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_set_layer_addr( - uint32_t addr[8], uint32_t layer); +#define set_layer_addr SPX_NAMESPACE(set_layer_addr) +void set_layer_addr(uint32_t addr[8], uint32_t layer); -void PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_set_tree_addr( - uint32_t addr[8], uint64_t tree); +#define set_tree_addr SPX_NAMESPACE(set_tree_addr) +void set_tree_addr(uint32_t addr[8], uint64_t tree); -void PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_set_type( - uint32_t addr[8], uint32_t type); +#define set_type SPX_NAMESPACE(set_type) +void set_type(uint32_t addr[8], uint32_t type); /* Copies the layer and tree part of one address into the other */ -void PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]); +#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); /* These functions are used for WOTS and FORS addresses. */ -void PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_set_keypair_addr( - uint32_t addr[8], uint32_t keypair); +#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) +void set_keypair_addr(uint32_t addr[8], uint32_t keypair); -void PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_set_chain_addr( - uint32_t addr[8], uint32_t chain); +#define set_chain_addr SPX_NAMESPACE(set_chain_addr) +void set_chain_addr(uint32_t addr[8], uint32_t chain); -void PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_set_hash_addr( - uint32_t addr[8], uint32_t hash); +#define set_hash_addr SPX_NAMESPACE(set_hash_addr) +void set_hash_addr(uint32_t addr[8], uint32_t hash); -void PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]); +#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); /* These functions are used for all hash tree addresses (including FORS). */ -void PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_set_tree_height( - uint32_t addr[8], uint32_t tree_height); +#define set_tree_height SPX_NAMESPACE(set_tree_height) +void set_tree_height(uint32_t addr[8], uint32_t tree_height); -void PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_set_tree_index( - uint32_t addr[8], uint32_t tree_index); +#define set_tree_index SPX_NAMESPACE(set_tree_index) +void set_tree_index(uint32_t addr[8], uint32_t tree_index); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/api.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/api.h index dcdb8850a1..79754c0f43 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/api.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/api.h @@ -4,15 +4,13 @@ #include #include - - -#define PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_CRYPTO_ALGNAME "SPHINCS+" +#define PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_CRYPTO_ALGNAME "SPHINCS+-haraka-256f-robust" #define PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_CRYPTO_SECRETKEYBYTES 128 #define PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_CRYPTO_PUBLICKEYBYTES 64 -#define PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_CRYPTO_BYTES 49856 -#define PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_CRYPTO_SEEDBYTES 96 +#define PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_CRYPTO_BYTES 49856 +#define PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_CRYPTO_SEEDBYTES 96 /* * Returns the length of a secret key, in bytes @@ -39,43 +37,41 @@ size_t PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_crypto_sign_seedbytes(void); * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] * Format pk: [root || PUB_SEED] */ -int PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed); +int PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); /* * Generates a SPHINCS+ key pair. * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] * Format pk: [root || PUB_SEED] */ -int PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk); +int PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); /** * Returns an array containing a detached signature. */ -int PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk); +int PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); /** * Verifies a detached signature and message under a given public key. */ -int PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk); +int PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, + const uint8_t *pk); /** * Returns an array containing the signature followed by the message. */ -int PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk); +int PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); /** * Verifies a given signature-message pair under a given public key. */ -int PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk); - +int PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/context.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/context.h new file mode 100644 index 0000000000..600dfb73c7 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/context.h @@ -0,0 +1,24 @@ +#ifndef SPX_CONTEXT_H +#define SPX_CONTEXT_H + +#include +#include + +#include "params.h" + +typedef struct { + uint8_t pub_seed[SPX_N]; + uint8_t sk_seed[SPX_N]; + + + uint64_t tweaked512_rc64[10][8]; + uint32_t tweaked256_rc32[10][8]; +} spx_ctx; + +#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) +void initialize_hash_function(spx_ctx *ctx); + +#define free_hash_function SPX_NAMESPACE(free_hash_function) +void free_hash_function(spx_ctx *ctx); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/context_haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/context_haraka.c new file mode 100644 index 0000000000..f1cd7e3664 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/context_haraka.c @@ -0,0 +1,11 @@ +#include "context.h" +#include "haraka.h" + +void initialize_hash_function(spx_ctx *ctx) { + tweak_constants(ctx); +} + +// we don't support heap-based haraka right now +void free_hash_function(spx_ctx *ctx) { + (void)ctx; // suppress unused variable warnings +} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/fors.c b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/fors.c index 7db54ed86a..96ca72e986 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/fors.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/fors.c @@ -2,58 +2,58 @@ #include #include -#include "address.h" #include "fors.h" + +#include "address.h" #include "hash.h" -#include "hash_state.h" #include "thash.h" #include "utils.h" +#include "utilsx1.h" -static void fors_gen_sk(unsigned char *sk, const unsigned char *sk_seed, - uint32_t fors_leaf_addr[8], const hash_state *hash_state_seeded) { - PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_prf_addr( - sk, sk_seed, fors_leaf_addr, hash_state_seeded); +static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + prf_addr(sk, ctx, fors_leaf_addr); } static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, - const unsigned char *pub_seed, - uint32_t fors_leaf_addr[8], - const hash_state *hash_state_seeded) { - PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_thash_1( - leaf, sk, pub_seed, fors_leaf_addr, hash_state_seeded); + const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + thash(leaf, sk, 1, ctx, fors_leaf_addr); } -static void fors_gen_leaf(unsigned char *leaf, const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx, const uint32_t fors_tree_addr[8], - const hash_state *hash_state_seeded) { - uint32_t fors_leaf_addr[8] = {0}; - - /* Only copy the parts that must be kept in fors_leaf_addr. */ - PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_copy_keypair_addr( - fors_leaf_addr, fors_tree_addr); - PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_set_type( - fors_leaf_addr, PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_set_tree_index( - fors_leaf_addr, addr_idx); - - fors_gen_sk(leaf, sk_seed, fors_leaf_addr, hash_state_seeded); - fors_sk_to_leaf(leaf, leaf, pub_seed, fors_leaf_addr, hash_state_seeded); +struct fors_gen_leaf_info { + uint32_t leaf_addrx[8]; +}; + +static void fors_gen_leafx1(unsigned char *leaf, + const spx_ctx *ctx, + uint32_t addr_idx, void *info) { + struct fors_gen_leaf_info *fors_info = info; + uint32_t *fors_leaf_addr = fors_info->leaf_addrx; + + /* Only set the parts that the caller doesn't set */ + set_tree_index(fors_leaf_addr, addr_idx); + set_type(fors_leaf_addr, SPX_ADDR_TYPE_FORSPRF); + fors_gen_sk(leaf, ctx, fors_leaf_addr); + + set_type(fors_leaf_addr, SPX_ADDR_TYPE_FORSTREE); + fors_sk_to_leaf(leaf, leaf, + ctx, fors_leaf_addr); } /** - * Interprets m as PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_FORS_HEIGHT-bit unsigned integers. - * Assumes m contains at least PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_FORS_TREES bits. - * Assumes indices has space for PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_FORS_TREES integers. + * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + * Assumes indices has space for SPX_FORS_TREES integers. */ static void message_to_indices(uint32_t *indices, const unsigned char *m) { unsigned int i, j; unsigned int offset = 0; - for (i = 0; i < PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_FORS_TREES; i++) { + for (i = 0; i < SPX_FORS_TREES; i++) { indices[i] = 0; - for (j = 0; j < PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_FORS_HEIGHT; j++) { - indices[i] ^= (((uint32_t)m[offset >> 3] >> (offset & 0x7)) & 0x1) << j; + for (j = 0; j < SPX_FORS_HEIGHT; j++) { + indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); offset++; } } @@ -61,55 +61,51 @@ static void message_to_indices(uint32_t *indices, const unsigned char *m) { /** * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_FORS_TREES bits. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. */ -void PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_fors_sign( - unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *hash_state_seeded) { - uint32_t indices[PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_FORS_TREES]; - unsigned char roots[PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_FORS_TREES * PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_N]; +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; uint32_t fors_tree_addr[8] = {0}; + struct fors_gen_leaf_info fors_info = {0}; + uint32_t *fors_leaf_addr = fors_info.leaf_addrx; uint32_t fors_pk_addr[8] = {0}; uint32_t idx_offset; unsigned int i; - PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_copy_keypair_addr( - fors_tree_addr, fors_addr); - PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_copy_keypair_addr( - fors_pk_addr, fors_addr); + copy_keypair_addr(fors_tree_addr, fors_addr); + copy_keypair_addr(fors_leaf_addr, fors_addr); - PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_set_type( - fors_tree_addr, PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_set_type( - fors_pk_addr, PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_ADDR_TYPE_FORSPK); + copy_keypair_addr(fors_pk_addr, fors_addr); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); message_to_indices(indices, m); - for (i = 0; i < PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_FORS_TREES; i++) { - idx_offset = i * (1 << PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_FORS_HEIGHT); + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); - PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_set_tree_height( - fors_tree_addr, 0); - PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_set_tree_index( - fors_tree_addr, indices[i] + idx_offset); + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); /* Include the secret key part that produces the selected leaf node. */ - fors_gen_sk(sig, sk_seed, fors_tree_addr, hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_N; + fors_gen_sk(sig, ctx, fors_tree_addr); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + sig += SPX_N; /* Compute the authentication path for this leaf node. */ - PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_treehash_FORS_HEIGHT( - roots + i * PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_N, sig, sk_seed, pub_seed, - indices[i], idx_offset, fors_gen_leaf, fors_tree_addr, - hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_N * PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_FORS_HEIGHT; + treehashx1(roots + i * SPX_N, sig, ctx, + indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx1, + fors_tree_addr, &fors_info); + + sig += SPX_N * SPX_FORS_HEIGHT; } /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_thash_FORS_TREES( - pk, roots, pub_seed, fors_pk_addr, hash_state_seeded); + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); } /** @@ -117,45 +113,44 @@ void PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_fors_sign( * This can be used for verification by comparing to a known public key, or to * subsequently verify a signature on the derived public key. The latter is the * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_FORS_TREES bits. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. */ -void PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_fors_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, const uint32_t fors_addr[8], - const hash_state *hash_state_seeded) { - uint32_t indices[PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_FORS_TREES]; - unsigned char roots[PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_FORS_TREES * PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_N]; - unsigned char leaf[PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_N]; +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + unsigned char leaf[SPX_N]; uint32_t fors_tree_addr[8] = {0}; uint32_t fors_pk_addr[8] = {0}; uint32_t idx_offset; unsigned int i; - PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_copy_keypair_addr(fors_tree_addr, fors_addr); - PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_copy_keypair_addr(fors_pk_addr, fors_addr); + copy_keypair_addr(fors_tree_addr, fors_addr); + copy_keypair_addr(fors_pk_addr, fors_addr); - PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_set_type(fors_tree_addr, PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_set_type(fors_pk_addr, PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_ADDR_TYPE_FORSPK); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); message_to_indices(indices, m); - for (i = 0; i < PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_FORS_TREES; i++) { - idx_offset = i * (1 << PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_FORS_HEIGHT); + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); - PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_set_tree_height(fors_tree_addr, 0); - PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_set_tree_index(fors_tree_addr, indices[i] + idx_offset); + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); /* Derive the leaf from the included secret key part. */ - fors_sk_to_leaf(leaf, sig, pub_seed, fors_tree_addr, hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_N; + fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); + sig += SPX_N; /* Derive the corresponding root node of this tree. */ - PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_compute_root(roots + i * PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_N, leaf, indices[i], idx_offset, sig, - PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_FORS_HEIGHT, pub_seed, fors_tree_addr, hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_N * PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_FORS_HEIGHT; + compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, + sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); + sig += SPX_N * SPX_FORS_HEIGHT; } /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_thash_FORS_TREES(pk, roots, pub_seed, fors_pk_addr, hash_state_seeded); + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/fors.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/fors.h index 02a4e4dc94..509140a178 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/fors.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/fors.h @@ -1,32 +1,32 @@ -#ifndef PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_FORS_H -#define PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_FORS_H +#ifndef SPX_FORS_H +#define SPX_FORS_H #include -#include "hash_state.h" +#include "context.h" #include "params.h" /** * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_FORS_TREES bits. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. */ -void PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_fors_sign( - unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *hash_state_seeded); +#define fors_sign SPX_NAMESPACE(fors_sign) +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); /** * Derives the FORS public key from a signature. * This can be used for verification by comparing to a known public key, or to * subsequently verify a signature on the derived public key. The latter is the * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_FORS_TREES bits. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. */ -void PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_fors_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, const uint32_t fors_addr[8], - const hash_state *hash_state_seeded); +#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/haraka.c index c345e74390..a4944913b5 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/haraka.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/haraka.c @@ -6,12 +6,13 @@ * by Thomas Pornin */ -#include #include +#include #include #include #include "haraka.h" +#include "utils.h" #define HARAKAS_RATE 32 @@ -656,76 +657,62 @@ static void interleave_constant32(uint32_t *out, const unsigned char *in) { br_aes_ct_ortho(out); } -void PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_tweak_constants( - harakactx *state, - const unsigned char *pk_seed, const unsigned char *sk_seed, - unsigned long long seed_length) { +void tweak_constants(spx_ctx *ctx) { unsigned char buf[40 * 16]; int i; /* Use the standard constants to generate tweaked ones. */ - memcpy((uint8_t *)state->tweaked512_rc64, (uint8_t *)haraka512_rc64, 40 * 16); - - /* Constants for sk.seed */ - if (sk_seed != NULL) { - PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_haraka_S( - buf, 40 * 16, sk_seed, seed_length, state); - - /* Interleave constants */ - for (i = 0; i < 10; i++) { - interleave_constant32(state->tweaked256_rc32_sseed[i], buf + 32 * i); - } - } + memcpy((uint8_t *)ctx->tweaked512_rc64, (uint8_t *)haraka512_rc64, 40 * 16); /* Constants for pk.seed */ - PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_haraka_S( - buf, 40 * 16, pk_seed, seed_length, state); + haraka_S(buf, 40 * 16, ctx->pub_seed, SPX_N, ctx); for (i = 0; i < 10; i++) { - interleave_constant32(state->tweaked256_rc32[i], buf + 32 * i); - interleave_constant(state->tweaked512_rc64[i], buf + 64 * i); + interleave_constant32(ctx->tweaked256_rc32[i], buf + 32 * i); + interleave_constant(ctx->tweaked512_rc64[i], buf + 64 * i); } } -static void haraka_S_absorb(unsigned char *s, +static void haraka_S_absorb(unsigned char *s, unsigned int r, const unsigned char *m, unsigned long long mlen, - unsigned char p, const harakactx *state) { + unsigned char p, const spx_ctx *ctx) { unsigned long long i; - unsigned char t[HARAKAS_RATE]; + PQCLEAN_VLA(uint8_t, t, r); - while (mlen >= HARAKAS_RATE) { + while (mlen >= r) { /* XOR block to state */ - for (i = 0; i < HARAKAS_RATE; ++i) { + for (i = 0; i < r; ++i) { s[i] ^= m[i]; } - PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_haraka512_perm(s, s, state); - mlen -= HARAKAS_RATE; - m += HARAKAS_RATE; + haraka512_perm(s, s, ctx); + mlen -= r; + m += r; } - for (i = 0; i < HARAKAS_RATE; ++i) { + for (i = 0; i < r; ++i) { t[i] = 0; } for (i = 0; i < mlen; ++i) { t[i] = m[i]; } t[i] = p; - t[HARAKAS_RATE - 1] |= 128; - for (i = 0; i < HARAKAS_RATE; ++i) { + t[r - 1] |= 128; + for (i = 0; i < r; ++i) { s[i] ^= t[i]; } } static void haraka_S_squeezeblocks(unsigned char *h, unsigned long long nblocks, - unsigned char *s, const harakactx *state) { + unsigned char *s, unsigned int r, + const spx_ctx *ctx) { while (nblocks > 0) { - PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_haraka512_perm(s, s, state); + haraka512_perm(s, s, ctx); memcpy(h, s, HARAKAS_RATE); - h += HARAKAS_RATE; + h += r; nblocks--; } } -void PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_haraka_S_inc_init(uint8_t *s_inc) { +void haraka_S_inc_init(uint8_t *s_inc) { size_t i; for (i = 0; i < 64; i++) { @@ -734,7 +721,8 @@ void PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_haraka_S_inc_init(uint8_t *s_inc) { s_inc[64] = 0; } -void PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, const harakactx *state) { +void haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, + const spx_ctx *ctx) { size_t i; /* Recall that s_inc[64] is the non-absorbed bytes xored into the state */ @@ -745,19 +733,19 @@ void PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_haraka_S_inc_absorb(uint8_t *s_inc, c s_inc[s_inc[64] + i] ^= m[i]; } mlen -= (size_t)(HARAKAS_RATE - s_inc[64]); - m += HARAKAS_RATE - s_inc[64]; + m += HARAKAS_RATE - (uint8_t)s_inc[64]; s_inc[64] = 0; - PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_haraka512_perm(s_inc, s_inc, state); + haraka512_perm(s_inc, s_inc, ctx); } for (i = 0; i < mlen; i++) { s_inc[s_inc[64] + i] ^= m[i]; } - s_inc[64] = (uint8_t)(mlen + s_inc[64]); + s_inc[64] += (uint8_t)mlen; } -void PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_haraka_S_inc_finalize(uint8_t *s_inc) { +void haraka_S_inc_finalize(uint8_t *s_inc) { /* After haraka_S_inc_absorb, we are guaranteed that s_inc[64] < HARAKAS_RATE, so we can always use one more byte for p in the current state. */ s_inc[s_inc[64]] ^= 0x1F; @@ -765,22 +753,23 @@ void PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_haraka_S_inc_finalize(uint8_t *s_inc) s_inc[64] = 0; } -void PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, const harakactx *state) { - uint8_t i; +void haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, + const spx_ctx *ctx) { + size_t i; /* First consume any bytes we still have sitting around */ for (i = 0; i < outlen && i < s_inc[64]; i++) { /* There are s_inc[64] bytes left, so r - s_inc[64] is the first available byte. We consume from there, i.e., up to r. */ - out[i] = s_inc[(HARAKAS_RATE - s_inc[64] + i)]; + out[i] = (uint8_t)s_inc[(HARAKAS_RATE - s_inc[64] + i)]; } out += i; outlen -= i; - s_inc[64] = (uint8_t)(s_inc[64] - i); + s_inc[64] -= (uint8_t)i; /* Then squeeze the remaining necessary blocks */ while (outlen > 0) { - PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_haraka512_perm(s_inc, s_inc, state); + haraka512_perm(s_inc, s_inc, ctx); for (i = 0; i < outlen && i < HARAKAS_RATE; i++) { out[i] = s_inc[i]; @@ -791,7 +780,9 @@ void PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_haraka_S_inc_squeeze(uint8_t *out, si } } -void PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_haraka_S(unsigned char *out, unsigned long long outlen, const unsigned char *in, unsigned long long inlen, const harakactx *state) { +void haraka_S(unsigned char *out, unsigned long long outlen, + const unsigned char *in, unsigned long long inlen, + const spx_ctx *ctx) { unsigned long long i; unsigned char s[64]; unsigned char d[32]; @@ -799,20 +790,21 @@ void PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_haraka_S(unsigned char *out, unsigned for (i = 0; i < 64; i++) { s[i] = 0; } - haraka_S_absorb(s, in, inlen, 0x1F, state); + haraka_S_absorb(s, 32, in, inlen, 0x1F, ctx); - haraka_S_squeezeblocks(out, outlen / 32, s, state); + haraka_S_squeezeblocks(out, outlen / 32, s, 32, ctx); out += (outlen / 32) * 32; if (outlen % 32) { - haraka_S_squeezeblocks(d, 1, s, state); + haraka_S_squeezeblocks(d, 1, s, 32, ctx); for (i = 0; i < outlen % 32; i++) { out[i] = d[i]; } } } -void PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_haraka512_perm(unsigned char *out, const unsigned char *in, const harakactx *state) { +void haraka512_perm(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx) { uint32_t w[16]; uint64_t q[8], tmp_q; unsigned int i, j; @@ -829,7 +821,7 @@ void PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_haraka512_perm(unsigned char *out, co br_aes_ct64_bitslice_Sbox(q); shift_rows(q); mix_columns(q); - add_round_key(q, state->tweaked512_rc64[2 * i + j]); + add_round_key(q, ctx->tweaked512_rc64[2 * i + j]); } /* Mix states */ for (j = 0; j < 8; j++) { @@ -857,12 +849,12 @@ void PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_haraka512_perm(unsigned char *out, co br_range_enc32le(out, w, 16); } -void PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_haraka512(unsigned char *out, const unsigned char *in, const harakactx *state) { +void haraka512(unsigned char *out, const unsigned char *in, const spx_ctx *ctx) { int i; unsigned char buf[64]; - PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_haraka512_perm(buf, in, state); + haraka512_perm(buf, in, ctx); /* Feed-forward */ for (i = 0; i < 64; i++) { buf[i] = buf[i] ^ in[i]; @@ -876,50 +868,8 @@ void PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_haraka512(unsigned char *out, const u } -void PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_haraka256(unsigned char *out, const unsigned char *in, const harakactx *state) { - uint32_t q[8], tmp_q; - int i, j; - - for (i = 0; i < 4; i++) { - q[2 * i] = br_dec32le(in + 4 * i); - q[2 * i + 1] = br_dec32le(in + 4 * i + 16); - } - br_aes_ct_ortho(q); - - /* AES rounds */ - for (i = 0; i < 5; i++) { - for (j = 0; j < 2; j++) { - br_aes_ct_bitslice_Sbox(q); - shift_rows32(q); - mix_columns32(q); - add_round_key32(q, state->tweaked256_rc32[2 * i + j]); - } - - /* Mix states */ - for (j = 0; j < 8; j++) { - tmp_q = q[j]; - q[j] = (tmp_q & 0x81818181) | - (tmp_q & 0x02020202) << 1 | - (tmp_q & 0x04040404) << 2 | - (tmp_q & 0x08080808) << 3 | - (tmp_q & 0x10101010) >> 3 | - (tmp_q & 0x20202020) >> 2 | - (tmp_q & 0x40404040) >> 1; - } - } - - br_aes_ct_ortho(q); - for (i = 0; i < 4; i++) { - br_enc32le(out + 4 * i, q[2 * i]); - br_enc32le(out + 4 * i + 16, q[2 * i + 1]); - } - - for (i = 0; i < 32; i++) { - out[i] ^= in[i]; - } -} - -void PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_haraka256_sk(unsigned char *out, const unsigned char *in, const harakactx *state) { +void haraka256(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx) { uint32_t q[8], tmp_q; int i, j; @@ -935,7 +885,7 @@ void PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_haraka256_sk(unsigned char *out, cons br_aes_ct_bitslice_Sbox(q); shift_rows32(q); mix_columns32(q); - add_round_key32(q, state->tweaked256_rc32_sseed[2 * i + j]); + add_round_key32(q, ctx->tweaked256_rc32[2 * i + j]); } /* Mix states */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/haraka.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/haraka.h index c0e64fb788..737cb6065f 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/haraka.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/haraka.h @@ -1,40 +1,42 @@ -#ifndef PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_HARAKA_H -#define PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_HARAKA_H +#ifndef SPX_HARAKA_H +#define SPX_HARAKA_H -#include -#include - -typedef struct { - uint64_t tweaked512_rc64[10][8]; - uint32_t tweaked256_rc32[10][8]; - uint32_t tweaked256_rc32_sseed[10][8]; -} harakactx; +#include "context.h" +#include "params.h" /* Tweak constants with seed */ -void PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_tweak_constants( - harakactx *state, - const unsigned char *pk_seed, const unsigned char *sk_seed, - unsigned long long seed_length); +#define tweak_constants SPX_NAMESPACE(tweak_constants) +void tweak_constants(spx_ctx *ctx); /* Haraka Sponge */ -void PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_haraka_S_inc_init(uint8_t *s_inc); -void PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, const harakactx *state); -void PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_haraka_S_inc_finalize(uint8_t *s_inc); -void PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, const harakactx *state); -void PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_haraka_S( - unsigned char *out, unsigned long long outlen, - const unsigned char *in, unsigned long long inlen, const harakactx *state); +#define haraka_S_inc_init SPX_NAMESPACE(haraka_S_inc_init) +void haraka_S_inc_init(uint8_t *s_inc); +#define haraka_S_inc_absorb SPX_NAMESPACE(haraka_S_inc_absorb) +void haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, + const spx_ctx *ctx); +#define haraka_S_inc_finalize SPX_NAMESPACE(haraka_S_inc_finalize) +void haraka_S_inc_finalize(uint8_t *s_inc); +#define haraka_S_inc_squeeze SPX_NAMESPACE(haraka_S_inc_squeeze) +void haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, + const spx_ctx *ctx); +#define haraka_S SPX_NAMESPACE(haraka_S) +void haraka_S(unsigned char *out, unsigned long long outlen, + const unsigned char *in, unsigned long long inlen, + const spx_ctx *ctx); /* Applies the 512-bit Haraka permutation to in. */ -void PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_haraka512_perm(unsigned char *out, const unsigned char *in, const harakactx *state); +#define haraka512_perm SPX_NAMESPACE(haraka512_perm) +void haraka512_perm(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx); /* Implementation of Haraka-512 */ -void PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_haraka512(unsigned char *out, const unsigned char *in, const harakactx *state); +#define haraka512 SPX_NAMESPACE(haraka512) +void haraka512(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx); /* Implementation of Haraka-256 */ -void PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_haraka256(unsigned char *out, const unsigned char *in, const harakactx *state); - -/* Implementation of Haraka-256 using sk.seed constants */ -void PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_haraka256_sk(unsigned char *out, const unsigned char *in, const harakactx *state); +#define haraka256 SPX_NAMESPACE(haraka256) +void haraka256(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/haraka_offsets.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/haraka_offsets.h new file mode 100644 index 0000000000..7c062272a0 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/haraka_offsets.h @@ -0,0 +1,21 @@ +#ifndef HARAKA_OFFSETS_H_ +#define HARAKA_OFFSETS_H_ + +/* + * Offsets of various fields in the address structure when we use Haraka as + * the Sphincs+ hash function + */ + +#define SPX_OFFSET_LAYER 3 /* The byte used to specify the Merkle tree layer */ +#define SPX_OFFSET_TREE 8 /* The start of the 8 byte field used to specify the tree */ +#define SPX_OFFSET_TYPE 19 /* The byte used to specify the hash type (reason) */ +#define SPX_OFFSET_KP_ADDR2 22 /* The high byte used to specify the key pair (which one-time signature) */ +#define SPX_OFFSET_KP_ADDR1 23 /* The low byte used to specify the key pair */ +#define SPX_OFFSET_CHAIN_ADDR 27 /* The byte used to specify the chain address (which Winternitz chain) */ +#define SPX_OFFSET_HASH_ADDR 31 /* The byte used to specify the hash address (where in the Winternitz chain) */ +#define SPX_OFFSET_TREE_HGT 27 /* The byte used to specify the height of this node in the FORS or Merkle tree */ +#define SPX_OFFSET_TREE_INDEX 28 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ + +#define SPX_HARAKA 1 + +#endif /* HARAKA_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/hash.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/hash.h index 9cc5cad8ff..f7c87d4c3c 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/hash.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/hash.h @@ -1,31 +1,28 @@ -#ifndef PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_HASH_H -#define PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_HASH_H - -#include "hash_state.h" +#ifndef SPX_HASH_H +#define SPX_HASH_H #include #include -void PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_initialize_hash_function( - hash_state *hash_state_seeded, - const unsigned char *pub_seed, const unsigned char *sk_seed); +#include "context.h" +#include "params.h" + +#define prf_addr SPX_NAMESPACE(prf_addr) +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]); -void PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_destroy_hash_function(hash_state *hash_state_seeded); +#define gen_message_random SPX_NAMESPACE(gen_message_random) +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); -void PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded); +#define hash_message SPX_NAMESPACE(hash_message) +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); -void PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); -void PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/hash_haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/hash_haraka.c index 6033e20f11..750a67423b 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/hash_haraka.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/hash_haraka.c @@ -2,58 +2,44 @@ #include #include "address.h" -#include "haraka.h" -#include "hash.h" #include "params.h" #include "utils.h" -void PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_initialize_hash_function( - hash_state *hash_state_seeded, - const unsigned char *pub_seed, const unsigned char *sk_seed) { - PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_tweak_constants(hash_state_seeded, pub_seed, sk_seed, PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_N); -} - -/* The haraka implementation is stack based and won't be replaced in PQClean/OQS, - so we don't need to do anything */ -void PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_destroy_hash_function( - hash_state *hash_state_seeded) { // NOLINT(readability-non-const-parameter) - (void)hash_state_seeded; -} +#include "haraka.h" +#include "hash.h" /* - * Computes PRF(key, addr), given a secret key of PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_N bytes and an address + * Computes PRF(key, addr), given a secret key of SPX_N bytes and an address */ -void PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded) { - unsigned char buf[PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_ADDR_BYTES]; - /* Since PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_N may be smaller than 32, we need a temporary buffer. */ +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]) { + /* Since SPX_N may be smaller than 32, we need temporary buffers. */ unsigned char outbuf[32]; + unsigned char buf[64] = {0}; - (void)key; /* Suppress an 'unused parameter' warning. */ + memcpy(buf, addr, SPX_ADDR_BYTES); + memcpy(buf + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); - PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_addr_to_bytes(buf, addr); - PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_haraka256_sk(outbuf, buf, hash_state_seeded); - memcpy(out, outbuf, PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_N); + haraka512(outbuf, (const void *)buf, ctx); + memcpy(out, outbuf, SPX_N); } /** * Computes the message-dependent randomness R, using a secret seed and an * optional randomization value as well as the message. */ -void PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded) { +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { uint8_t s_inc[65]; - PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_haraka_S_inc_init(s_inc); - PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_haraka_S_inc_absorb(s_inc, sk_prf, PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_N, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_haraka_S_inc_absorb(s_inc, optrand, PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_N, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_haraka_S_inc_absorb(s_inc, m, mlen, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_haraka_S_inc_finalize(s_inc); - PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_haraka_S_inc_squeeze(R, PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_N, s_inc, hash_state_seeded); + haraka_S_inc_init(s_inc); + haraka_S_inc_absorb(s_inc, sk_prf, SPX_N, ctx); + haraka_S_inc_absorb(s_inc, optrand, SPX_N, ctx); + haraka_S_inc_absorb(s_inc, m, mlen, ctx); + haraka_S_inc_finalize(s_inc); + haraka_S_inc_squeeze(R, SPX_N, s_inc, ctx); } /** @@ -61,36 +47,35 @@ void PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_gen_message_random( * Outputs the message digest and the index of the leaf. The index is split in * the tree index and the leaf index, for convenient copying to an address. */ -void PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded) { -#define PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_TREE_BITS (PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_TREE_HEIGHT * (PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_D - 1)) -#define PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_TREE_BYTES ((PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_TREE_BITS + 7) / 8) -#define PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_LEAF_BITS PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_TREE_HEIGHT -#define PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_LEAF_BYTES ((PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_LEAF_BITS + 7) / 8) -#define PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_DGST_BYTES (PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_FORS_MSG_BYTES + PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_TREE_BYTES + PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_LEAF_BYTES) +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { +#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) +#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) +#define SPX_LEAF_BITS SPX_TREE_HEIGHT +#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) +#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) - unsigned char buf[PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_DGST_BYTES]; + unsigned char buf[SPX_DGST_BYTES]; unsigned char *bufp = buf; uint8_t s_inc[65]; - PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_haraka_S_inc_init(s_inc); - PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_haraka_S_inc_absorb(s_inc, R, PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_N, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_haraka_S_inc_absorb(s_inc, pk + PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_N, PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_N, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_haraka_S_inc_absorb(s_inc, m, mlen, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_haraka_S_inc_finalize(s_inc); - PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_haraka_S_inc_squeeze(buf, PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_DGST_BYTES, s_inc, hash_state_seeded); + haraka_S_inc_init(s_inc); + haraka_S_inc_absorb(s_inc, R, SPX_N, ctx); + haraka_S_inc_absorb(s_inc, pk + SPX_N, SPX_N, ctx); // Only absorb root part of pk + haraka_S_inc_absorb(s_inc, m, mlen, ctx); + haraka_S_inc_finalize(s_inc); + haraka_S_inc_squeeze(buf, SPX_DGST_BYTES, s_inc, ctx); + + memcpy(digest, bufp, SPX_FORS_MSG_BYTES); + bufp += SPX_FORS_MSG_BYTES; - memcpy(digest, bufp, PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_FORS_MSG_BYTES); - bufp += PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_FORS_MSG_BYTES; - *tree = PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_bytes_to_ull(bufp, PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_TREE_BYTES); - *tree &= (~(uint64_t)0) >> (64 - PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_TREE_BITS); - bufp += PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_TREE_BYTES; + *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); + *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); + bufp += SPX_TREE_BYTES; - *leaf_idx = (uint32_t)PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_bytes_to_ull( - bufp, PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_LEAF_BYTES); - *leaf_idx &= (~(uint32_t)0) >> (32 - PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_LEAF_BITS); + *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); + *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/hash_state.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/hash_state.h deleted file mode 100644 index 5adb1d9a22..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/hash_state.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef SPX_HASH_STATE_H -#define SPX_HASH_STATE_H - -/** - * Defines the type of the hash function state. - * - * Don't be fooled into thinking this instance of SPHINCS+ isn't stateless! - * - * From Section 7.2.2 from the SPHINCS+ round-2 specification: - * - * Each of the instances of the tweakable hash function take PK.seed as its - * first input, which is constant for a given key pair – and, thus, across - * a single signature. This leads to a lot of redundant computation. To remedy - * this, we pad PK.seed to the length of a full 64-byte SHA-256 input block. - * Because of the Merkle-DamgÃ¥rd construction that underlies SHA-256, this - * allows for reuse of the intermediate SHA-256 state after the initial call to - * the compression function which improves performance. - * - * We pass this hash state around in functions, because otherwise we need to - * have a global variable. - */ - -#include "haraka.h" -#define hash_state harakactx - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/merkle.c b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/merkle.c new file mode 100644 index 0000000000..0c1479fd93 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/merkle.c @@ -0,0 +1,59 @@ +#include +#include + +#include "address.h" +#include "merkle.h" +#include "params.h" +#include "utils.h" +#include "utilsx1.h" +#include "wots.h" +#include "wotsx1.h" + +/* + * This generates a Merkle signature (WOTS signature followed by the Merkle + * authentication path). This is in this file because most of the complexity + * is involved with the WOTS signature; the Merkle authentication path logic + * is mostly hidden in treehashx4 + */ +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf) { + unsigned char *auth_path = sig + SPX_WOTS_BYTES; + struct leaf_info_x1 info = { 0 }; + unsigned steps[ SPX_WOTS_LEN ]; + + info.wots_sig = sig; + chain_lengths(steps, root); + info.wots_steps = steps; + + set_type(&tree_addr[0], SPX_ADDR_TYPE_HASHTREE); + set_type(&info.pk_addr[0], SPX_ADDR_TYPE_WOTSPK); + copy_subtree_addr(&info.leaf_addr[0], wots_addr); + copy_subtree_addr(&info.pk_addr[0], wots_addr); + + info.wots_sign_leaf = idx_leaf; + + treehashx1(root, auth_path, ctx, + idx_leaf, 0, + SPX_TREE_HEIGHT, + wots_gen_leafx1, + tree_addr, &info); +} + +/* Compute root node of the top-most subtree. */ +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { + /* We do not need the auth path in key generation, but it simplifies the + code to have just one treehash routine that computes both root and path + in one function. */ + unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; + uint32_t top_tree_addr[8] = {0}; + uint32_t wots_addr[8] = {0}; + + set_layer_addr(top_tree_addr, SPX_D - 1); + set_layer_addr(wots_addr, SPX_D - 1); + + merkle_sign(auth_path, root, ctx, + wots_addr, top_tree_addr, + (uint32_t)~0 /* ~0 means "don't bother generating an auth path */ ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/merkle.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/merkle.h new file mode 100644 index 0000000000..769cf2e970 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/merkle.h @@ -0,0 +1,21 @@ +#ifndef MERKLE_H_ +#define MERKLE_H_ + +#include + +#include "context.h" +#include "params.h" + +/* Generate a Merkle signature (WOTS signature followed by the Merkle */ +/* authentication path) */ +#define merkle_sign SPX_NAMESPACE(merkle_sign) +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf); + +/* Compute the root node of the top-most subtree. */ +#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); + +#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/nistapi.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/nistapi.h new file mode 100644 index 0000000000..3cb71afad4 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/nistapi.h @@ -0,0 +1,87 @@ +#ifndef SPX_API_H +#define SPX_API_H + +#include +#include + +#include "params.h" + +#define CRYPTO_ALGNAME "SPHINCS+" + +#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES +#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES +#define CRYPTO_BYTES SPX_BYTES +#define CRYPTO_SEEDBYTES (3*SPX_N) + +/* + * Returns the length of a secret key, in bytes + */ +#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) +size_t crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) +size_t crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) +size_t crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) +size_t crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +#define crypto_sign SPX_NAMESPACE(crypto_sign) +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/params.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/params.h index 4d457ad843..41c7d2ff2b 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/params.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/params.h @@ -1,53 +1,56 @@ -#ifndef PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_PARAMS_H -#define PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_PARAMS_H +#ifndef SPX_PARAMS_H +#define SPX_PARAMS_H + +#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_##s /* Hash output length in bytes. */ -#define PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_N 32 +#define SPX_N 32 /* Height of the hypertree. */ -#define PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_FULL_HEIGHT 68 +#define SPX_FULL_HEIGHT 68 /* Number of subtree layer. */ -#define PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_D 17 +#define SPX_D 17 /* FORS tree dimensions. */ -#define PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_FORS_HEIGHT 9 -#define PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_FORS_TREES 35 +#define SPX_FORS_HEIGHT 9 +#define SPX_FORS_TREES 35 /* Winternitz parameter, */ -#define PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_WOTS_W 16 +#define SPX_WOTS_W 16 /* The hash function is defined by linking a different hash.c file, as opposed to setting a #define constant. */ /* For clarity */ -#define PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_ADDR_BYTES 32 +#define SPX_ADDR_BYTES 32 /* WOTS parameters. */ -#define PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_WOTS_LOGW 4 +#define SPX_WOTS_LOGW 4 -#define PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_WOTS_LEN1 (8 * PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_N / PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_WOTS_LOGW) +#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) -/* PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#define PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_WOTS_LEN2 3 +/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ +#define SPX_WOTS_LEN2 3 -#define PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_WOTS_LEN (PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_WOTS_LEN1 + PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_WOTS_LEN2) -#define PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_WOTS_BYTES (PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_WOTS_LEN * PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_N) -#define PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_WOTS_PK_BYTES PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_WOTS_BYTES +#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) +#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) +#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES /* Subtree size. */ -#define PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_TREE_HEIGHT (PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_FULL_HEIGHT / PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_D) +#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) + +//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT +// #error SPX_D should always divide SPX_FULL_HEIGHT +//#endif /* FORS parameters. */ -#define PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_FORS_MSG_BYTES ((PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_FORS_TREES + 7) / 8) -#define PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_FORS_BYTES ((PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_FORS_HEIGHT + 1) * PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_FORS_TREES * PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_N) -#define PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_FORS_PK_BYTES PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_N +#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) +#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) +#define SPX_FORS_PK_BYTES SPX_N /* Resulting SPX sizes. */ -#define PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_BYTES (PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_N + PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_FORS_BYTES + PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_D * PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_WOTS_BYTES +\ - PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_FULL_HEIGHT * PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_N) -#define PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_PK_BYTES (2 * PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_N) -#define PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_SK_BYTES (2 * PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_N + PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_PK_BYTES) - -/* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ -#define PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_OPTRAND_BYTES 32 +#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ + SPX_FULL_HEIGHT * SPX_N) +#define SPX_PK_BYTES (2 * SPX_N) +#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) + +#include "haraka_offsets.h" #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/sign.c b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/sign.c index cc7b1a664d..9d0c7d1b22 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/sign.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/sign.c @@ -3,72 +3,43 @@ #include #include "address.h" -#include "api.h" +#include "context.h" #include "fors.h" #include "hash.h" -#include "hash_state.h" +#include "merkle.h" +#include "nistapi.h" #include "params.h" #include "randombytes.h" #include "thash.h" #include "utils.h" #include "wots.h" -/** - * Computes the leaf at a given address. First generates the WOTS key pair, - * then computes leaf by hashing horizontally. - */ -static void wots_gen_leaf(unsigned char *leaf, const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx, const uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - unsigned char pk[PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_WOTS_BYTES]; - uint32_t wots_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_set_type( - wots_addr, PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_set_type( - wots_pk_addr, PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_ADDR_TYPE_WOTSPK); - - PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_set_keypair_addr( - wots_addr, addr_idx); - PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_wots_gen_pk( - pk, sk_seed, pub_seed, wots_addr, hash_state_seeded); - - PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_copy_keypair_addr( - wots_pk_addr, wots_addr); - PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_thash_WOTS_LEN( - leaf, pk, pub_seed, wots_pk_addr, hash_state_seeded); -} - /* * Returns the length of a secret key, in bytes */ -size_t PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_crypto_sign_secretkeybytes(void) { - return PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_CRYPTO_SECRETKEYBYTES; +size_t crypto_sign_secretkeybytes(void) { + return CRYPTO_SECRETKEYBYTES; } /* * Returns the length of a public key, in bytes */ -size_t PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_crypto_sign_publickeybytes(void) { - return PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_CRYPTO_PUBLICKEYBYTES; +size_t crypto_sign_publickeybytes(void) { + return CRYPTO_PUBLICKEYBYTES; } /* * Returns the length of a signature, in bytes */ -size_t PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_crypto_sign_bytes(void) { - return PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_CRYPTO_BYTES; +size_t crypto_sign_bytes(void) { + return CRYPTO_BYTES; } /* * Returns the length of the seed required to generate a key pair, in bytes */ -size_t PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_crypto_sign_seedbytes(void) { - return PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_CRYPTO_SEEDBYTES; +size_t crypto_sign_seedbytes(void) { + return CRYPTO_SEEDBYTES; } /* @@ -76,37 +47,30 @@ size_t PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_crypto_sign_seedbytes(void) { * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] * Format pk: [PUB_SEED || root] */ -int PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed) { - /* We do not need the auth path in key generation, but it simplifies the - code to have just one treehash routine that computes both root and path - in one function. */ - unsigned char auth_path[PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_TREE_HEIGHT * PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_N]; - uint32_t top_tree_addr[8] = {0}; - hash_state hash_state_seeded; - - PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_set_layer_addr( - top_tree_addr, PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_D - 1); - PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_set_type( - top_tree_addr, PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_ADDR_TYPE_HASHTREE); +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed) { + spx_ctx ctx; /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ - memcpy(sk, seed, PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_CRYPTO_SEEDBYTES); + memcpy(sk, seed, CRYPTO_SEEDBYTES); - memcpy(pk, sk + 2 * PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_N, PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_N); + memcpy(pk, sk + 2 * SPX_N, SPX_N); + + memcpy(ctx.pub_seed, pk, SPX_N); + memcpy(ctx.sk_seed, sk, SPX_N); /* This hook allows the hash function instantiation to do whatever preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_initialize_hash_function(&hash_state_seeded, pk, sk); + initialize_hash_function(&ctx); /* Compute root node of the top-most subtree. */ - PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_treehash_TREE_HEIGHT( - sk + 3 * PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_N, auth_path, sk, sk + 2 * PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_N, 0, 0, - wots_gen_leaf, top_tree_addr, &hash_state_seeded); + merkle_gen_root(sk + 3 * SPX_N, &ctx); + + // cleanup + free_hash_function(&ctx); - memcpy(pk + PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_N, sk + 3 * PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_N, PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_N); + memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); - PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_destroy_hash_function(&hash_state_seeded); return 0; } @@ -115,12 +79,10 @@ int PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_crypto_sign_seed_keypair( * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] * Format pk: [PUB_SEED || root] */ -int PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk) { - unsigned char seed[PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_CRYPTO_SEEDBYTES]; - randombytes(seed, PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_CRYPTO_SEEDBYTES); - PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_crypto_sign_seed_keypair( - pk, sk, seed); +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { + uint8_t seed[CRYPTO_SEEDBYTES]; + randombytes(seed, CRYPTO_SEEDBYTES); + crypto_sign_seed_keypair(pk, sk, seed); return 0; } @@ -128,101 +90,83 @@ int PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_crypto_sign_keypair( /** * Returns an array containing a detached signature. */ -int PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - const unsigned char *sk_seed = sk; - const unsigned char *sk_prf = sk + PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_N; - const unsigned char *pk = sk + 2 * PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_N; - const unsigned char *pub_seed = pk; - - unsigned char optrand[PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_N]; - unsigned char mhash[PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_FORS_MSG_BYTES]; - unsigned char root[PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_N]; +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk) { + spx_ctx ctx; + + const uint8_t *sk_prf = sk + SPX_N; + const uint8_t *pk = sk + 2 * SPX_N; + + uint8_t optrand[SPX_N]; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t root[SPX_N]; uint32_t i; uint64_t tree; uint32_t idx_leaf; uint32_t wots_addr[8] = {0}; uint32_t tree_addr[8] = {0}; - hash_state hash_state_seeded; + memcpy(ctx.sk_seed, sk, SPX_N); + memcpy(ctx.pub_seed, pk, SPX_N); /* This hook allows the hash function instantiation to do whatever preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_initialize_hash_function( - &hash_state_seeded, - pub_seed, sk_seed); + initialize_hash_function(&ctx); - PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_set_type( - wots_addr, PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_set_type( - tree_addr, PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_ADDR_TYPE_HASHTREE); + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); /* Optionally, signing can be made non-deterministic using optrand. This can help counter side-channel attacks that would benefit from getting a large number of traces when the signer uses the same nodes. */ - randombytes(optrand, PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_N); + randombytes(optrand, SPX_N); /* Compute the digest randomization value. */ - PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_gen_message_random( - sig, sk_prf, optrand, m, mlen, &hash_state_seeded); + gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); /* Derive the message digest and leaf index from R, PK and M. */ - PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_N; + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; - PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); /* Sign the message hash using FORS. */ - PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_fors_sign( - sig, root, mhash, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_FORS_BYTES; - - for (i = 0; i < PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_D; i++) { - PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_set_tree_addr(tree_addr, tree); - - PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); - - /* Compute a WOTS signature. */ - PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_wots_sign( - sig, root, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_WOTS_BYTES; - - /* Compute the authentication path for the used WOTS leaf. */ - PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_treehash_TREE_HEIGHT( - root, sig, sk_seed, pub_seed, idx_leaf, 0, - wots_gen_leaf, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_TREE_HEIGHT * PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_N; + fors_sign(sig, root, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); + sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_TREE_HEIGHT; + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; } - *siglen = PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_BYTES; + free_hash_function(&ctx); + + *siglen = SPX_BYTES; - PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_destroy_hash_function(&hash_state_seeded); return 0; } /** * Verifies a detached signature and message under a given public key. */ -int PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk) { - const unsigned char *pub_seed = pk; - const unsigned char *pub_root = pk + PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_N; - unsigned char mhash[PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_FORS_MSG_BYTES]; - unsigned char wots_pk[PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_WOTS_BYTES]; - unsigned char root[PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_N]; - unsigned char leaf[PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_N]; +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk) { + spx_ctx ctx; + const uint8_t *pub_root = pk + SPX_N; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t wots_pk[SPX_WOTS_BYTES]; + uint8_t root[SPX_N]; + uint8_t leaf[SPX_N]; unsigned int i; uint64_t tree; uint32_t idx_leaf; @@ -230,78 +174,66 @@ int PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_crypto_sign_verify( uint32_t tree_addr[8] = {0}; uint32_t wots_pk_addr[8] = {0}; - hash_state hash_state_seeded; - - if (siglen != PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_BYTES) { + if (siglen != SPX_BYTES) { return -1; } + memcpy(ctx.pub_seed, pk, SPX_N); + /* This hook allows the hash function instantiation to do whatever preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_initialize_hash_function( - &hash_state_seeded, - pub_seed, NULL); + initialize_hash_function(&ctx); - PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_set_type( - wots_addr, PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_set_type( - tree_addr, PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_ADDR_TYPE_HASHTREE); - PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_set_type( - wots_pk_addr, PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_ADDR_TYPE_WOTSPK); + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); /* Derive the message digest and leaf index from R || PK || M. */ - /* The additional PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_N is a result of the hash domain separator. */ - PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_N; + /* The additional SPX_N is a result of the hash domain separator. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; /* Layer correctly defaults to 0, so no need to set_layer_addr */ - PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); - PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_fors_pk_from_sig( - root, sig, mhash, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_FORS_BYTES; + fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; /* For each subtree.. */ - for (i = 0; i < PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_D; i++) { - PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_set_tree_addr(tree_addr, tree); + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); - PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); - PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_copy_keypair_addr( - wots_pk_addr, wots_addr); + copy_keypair_addr(wots_pk_addr, wots_addr); /* The WOTS public key is only correct if the signature was correct. */ /* Initially, root is the FORS pk, but on subsequent iterations it is the root of the subtree below the currently processed subtree. */ - PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_wots_pk_from_sig( - wots_pk, sig, root, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_WOTS_BYTES; + wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); + sig += SPX_WOTS_BYTES; /* Compute the leaf node using the WOTS public key. */ - PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_thash_WOTS_LEN( - leaf, wots_pk, pub_seed, wots_pk_addr, &hash_state_seeded); + thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); /* Compute the root node of this subtree. */ - PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_compute_root( - root, leaf, idx_leaf, 0, sig, PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_TREE_HEIGHT, - pub_seed, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_TREE_HEIGHT * PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_N; + compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, + &ctx, tree_addr); + sig += SPX_TREE_HEIGHT * SPX_N; /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_TREE_HEIGHT; + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; } - PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_destroy_hash_function(&hash_state_seeded); + // cleanup + free_hash_function(&ctx); + /* Check if the root node equals the root node in the public key. */ - if (memcmp(root, pub_root, PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_N) != 0) { + if (memcmp(root, pub_root, SPX_N) != 0) { return -1; } @@ -312,15 +244,14 @@ int PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_crypto_sign_verify( /** * Returns an array containing the signature followed by the message. */ -int PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk) { size_t siglen; - PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_crypto_sign_signature( - sm, &siglen, m, mlen, sk); + crypto_sign_signature(sm, &siglen, m, mlen, sk); - memmove(sm + PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_BYTES, m, mlen); + memmove(sm + SPX_BYTES, m, mlen); *smlen = siglen + mlen; return 0; @@ -329,28 +260,27 @@ int PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_crypto_sign( /** * Verifies a given signature-message pair under a given public key. */ -int PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk) { +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk) { /* The API caller does not necessarily know what size a signature should be - but SPHINCS+ signatures are always exactly PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_BYTES. */ - if (smlen < PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_BYTES) { + but SPHINCS+ signatures are always exactly SPX_BYTES. */ + if (smlen < SPX_BYTES) { memset(m, 0, smlen); *mlen = 0; return -1; } - *mlen = smlen - PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_BYTES; + *mlen = smlen - SPX_BYTES; - if (PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_crypto_sign_verify( - sm, PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_BYTES, sm + PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_BYTES, *mlen, pk)) { + if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { memset(m, 0, smlen); *mlen = 0; return -1; } /* If verification was successful, move the message to the right place. */ - memmove(m, sm + PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_BYTES, *mlen); + memmove(m, sm + SPX_BYTES, *mlen); return 0; } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/thash.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/thash.h index 451af2b953..8687ccfb4d 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/thash.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/thash.h @@ -1,28 +1,13 @@ -#ifndef PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_THASH_H -#define PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_THASH_H +#ifndef SPX_THASH_H +#define SPX_THASH_H -#include "hash_state.h" +#include "context.h" +#include "params.h" #include -void PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); +#define thash SPX_NAMESPACE(thash) +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/thash_haraka_robust.c b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/thash_haraka_robust.c index ed97ca4ee7..109502cbc2 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/thash_haraka_robust.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/thash_haraka_robust.c @@ -2,93 +2,44 @@ #include #include "address.h" -#include "hash_state.h" #include "params.h" #include "thash.h" +#include "utils.h" #include "haraka.h" /** - * Takes an array of inblocks concatenated arrays of PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_N bytes. + * Takes an array of inblocks concatenated arrays of SPX_N bytes. */ -static void PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_thash( - unsigned char *out, unsigned char *buf, - const unsigned char *in, unsigned int inblocks, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char *bitmask = buf + PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_ADDR_BYTES; +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]) { + PQCLEAN_VLA(uint8_t, buf, SPX_ADDR_BYTES + inblocks * SPX_N); + PQCLEAN_VLA(uint8_t, bitmask, inblocks * SPX_N); unsigned char outbuf[32]; unsigned char buf_tmp[64]; unsigned int i; - (void)pub_seed; /* Suppress an 'unused parameter' warning. */ - if (inblocks == 1) { /* F function */ - /* Since PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_N may be smaller than 32, we need a temporary buffer. */ + /* Since SPX_N may be smaller than 32, we need a temporary buffer. */ memset(buf_tmp, 0, 64); - PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_addr_to_bytes(buf_tmp, addr); + memcpy(buf_tmp, addr, 32); - PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_haraka256(outbuf, buf_tmp, hash_state_seeded); - for (i = 0; i < inblocks * PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_N; i++) { - buf_tmp[PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_ADDR_BYTES + i] = in[i] ^ outbuf[i]; + haraka256(outbuf, buf_tmp, ctx); + for (i = 0; i < inblocks * SPX_N; i++) { + buf_tmp[SPX_ADDR_BYTES + i] = in[i] ^ outbuf[i]; } - PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_haraka512(outbuf, buf_tmp, hash_state_seeded); - memcpy(out, outbuf, PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_N); + haraka512(outbuf, buf_tmp, ctx); + memcpy(out, outbuf, SPX_N); } else { /* All other tweakable hashes*/ - PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_addr_to_bytes(buf, addr); - PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_haraka_S( - bitmask, inblocks * PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_N, buf, PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_ADDR_BYTES, hash_state_seeded); + memcpy(buf, addr, 32); + haraka_S(bitmask, inblocks * SPX_N, buf, SPX_ADDR_BYTES, ctx); - for (i = 0; i < inblocks * PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_N; i++) { - buf[PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_ADDR_BYTES + i] = in[i] ^ bitmask[i]; + for (i = 0; i < inblocks * SPX_N; i++) { + buf[SPX_ADDR_BYTES + i] = in[i] ^ bitmask[i]; } - PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_haraka_S( - out, PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_N, buf, PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_N, hash_state_seeded); + haraka_S(out, SPX_N, buf, SPX_ADDR_BYTES + inblocks * SPX_N, ctx); } } - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_ADDR_BYTES + 1 * PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_N]; - PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_thash( - out, buf, in, 1, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_ADDR_BYTES + 2 * PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_N]; - PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_thash( - out, buf, in, 2, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_ADDR_BYTES + PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_WOTS_LEN * PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_N]; - PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_thash( - out, buf, in, PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_WOTS_LEN, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_ADDR_BYTES + PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_FORS_TREES * PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_N]; - PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_thash( - out, buf, in, PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_FORS_TREES, pub_seed, addr, hash_state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/utils.c b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/utils.c index c3b45d7f72..177b541fb9 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/utils.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/utils.c @@ -1,34 +1,41 @@ -#include #include +#include "utils.h" + #include "address.h" #include "hash.h" -#include "hash_state.h" #include "params.h" #include "thash.h" -#include "utils.h" /** * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. */ -void PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in) { +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in) { + int i; /* Iterate over out in decreasing order, for big-endianness. */ - for (size_t i = outlen; i > 0; i--) { - out[i - 1] = in & 0xff; + for (i = (signed int)outlen - 1; i >= 0; i--) { + out[i] = in & 0xff; in = in >> 8; } } +void u32_to_bytes(unsigned char *out, uint32_t in) { + out[0] = (unsigned char)(in >> 24); + out[1] = (unsigned char)(in >> 16); + out[2] = (unsigned char)(in >> 8); + out[3] = (unsigned char)in; +} + /** * Converts the inlen bytes in 'in' from big-endian byte order to an integer. */ -unsigned long long PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_bytes_to_ull( - const unsigned char *in, size_t inlen) { +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { unsigned long long retval = 0; + unsigned int i; - for (size_t i = 0; i < inlen; i++) { + for (i = 0; i < inlen; i++) { retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); } return retval; @@ -38,94 +45,80 @@ unsigned long long PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_bytes_to_ull( * Computes a root node given a leaf and an auth path. * Expects address to be complete other than the tree_height and tree_index. */ -void PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]) { uint32_t i; - unsigned char buffer[2 * PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_N]; + unsigned char buffer[2 * SPX_N]; /* If leaf_idx is odd (last bit = 1), current path element is a right child and auth_path has to go left. Otherwise it is the other way around. */ if (leaf_idx & 1) { - memcpy(buffer + PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_N, leaf, PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_N); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_N); + memcpy(buffer + SPX_N, leaf, SPX_N); + memcpy(buffer, auth_path, SPX_N); } else { - memcpy(buffer, leaf, PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_N); - memcpy(buffer + PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_N, auth_path, PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_N); + memcpy(buffer, leaf, SPX_N); + memcpy(buffer + SPX_N, auth_path, SPX_N); } - auth_path += PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_N; + auth_path += SPX_N; for (i = 0; i < tree_height - 1; i++) { leaf_idx >>= 1; idx_offset >>= 1; /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_set_tree_height(addr, i + 1); - PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_set_tree_index( - addr, leaf_idx + idx_offset); + set_tree_height(addr, i + 1); + set_tree_index(addr, leaf_idx + idx_offset); /* Pick the right or left neighbor, depending on parity of the node. */ if (leaf_idx & 1) { - PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_thash_2( - buffer + PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_N, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_N); + thash(buffer + SPX_N, buffer, 2, ctx, addr); + memcpy(buffer, auth_path, SPX_N); } else { - PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_thash_2( - buffer, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer + PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_N, auth_path, PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_N); + thash(buffer, buffer, 2, ctx, addr); + memcpy(buffer + SPX_N, auth_path, SPX_N); } - auth_path += PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_N; + auth_path += SPX_N; } /* The last iteration is exceptional; we do not copy an auth_path node. */ leaf_idx >>= 1; idx_offset >>= 1; - PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_set_tree_height(addr, tree_height); - PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_set_tree_index( - addr, leaf_idx + idx_offset); - PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_thash_2( - root, buffer, pub_seed, addr, hash_state_seeded); + set_tree_height(addr, tree_height); + set_tree_index(addr, leaf_idx + idx_offset); + thash(root, buffer, 2, ctx, addr); } /** * For a given leaf index, computes the authentication path and the resulting * root node using Merkle's TreeHash algorithm. * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_ADDR_TYPE_FORSTREE). + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). * Applies the offset idx_offset to indices before building addresses, so that * it is possible to continue counting indices across trees. */ -static void PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_treehash( - unsigned char *root, unsigned char *auth_path, - unsigned char *stack, unsigned int *heights, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - +void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx * /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]) { + PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); + PQCLEAN_VLA(unsigned int, heights, tree_height + 1); unsigned int offset = 0; uint32_t idx; uint32_t tree_idx; for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { /* Add the next leaf node to the stack. */ - gen_leaf(stack + offset * PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_N, - sk_seed, pub_seed, idx + idx_offset, tree_addr, - hash_state_seeded); + gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); offset++; heights[offset - 1] = 0; /* If this is a node we need for the auth path.. */ if ((leaf_idx ^ 0x1) == idx) { - memcpy(auth_path, stack + (offset - 1)*PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_N, PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_N); + memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); } /* While the top-most nodes are of equal height.. */ @@ -134,66 +127,22 @@ static void PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_treehash( tree_idx = (idx >> (heights[offset - 1] + 1)); /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_set_tree_height( - tree_addr, heights[offset - 1] + 1); - PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_set_tree_index( - tree_addr, tree_idx + (idx_offset >> (heights[offset - 1] + 1))); + set_tree_height(tree_addr, heights[offset - 1] + 1); + set_tree_index(tree_addr, + tree_idx + (idx_offset >> (heights[offset - 1] + 1))); /* Hash the top-most nodes from the stack together. */ - PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_thash_2( - stack + (offset - 2)*PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_N, stack + (offset - 2)*PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_N, - pub_seed, tree_addr, hash_state_seeded); + thash(stack + (offset - 2)*SPX_N, + stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); offset--; /* Note that the top-most node is now one layer higher. */ heights[offset - 1]++; /* If this is a node we need for the auth path.. */ if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_path + heights[offset - 1]*PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_N, - stack + (offset - 1)*PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_N, PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_N); + memcpy(auth_path + heights[offset - 1]*SPX_N, + stack + (offset - 1)*SPX_N, SPX_N); } } } - memcpy(root, stack, PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_N); -} - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_FORS_HEIGHT + 1)*PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_N]; - unsigned int heights[PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_FORS_HEIGHT + 1]; - - PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_FORS_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_TREE_HEIGHT + 1)*PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_N]; - unsigned int heights[PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_TREE_HEIGHT + 1]; - - PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_TREE_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); + memcpy(root, stack, SPX_N); } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/utils.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/utils.h index 072fd86b57..64f5d5a53a 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/utils.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/utils.h @@ -1,64 +1,58 @@ -#ifndef PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_UTILS_H -#define PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_UTILS_H +#ifndef SPX_UTILS_H +#define SPX_UTILS_H -#include "hash_state.h" -#include "params.h" -#include #include +#include "compat.h" +#include "context.h" +#include "params.h" + + +/* To support MSVC use alloca() instead of VLAs. See #20. */ + + /** * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. */ -void PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in); +#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in); +#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) +void u32_to_bytes(unsigned char *out, uint32_t in); /** * Converts the inlen bytes in 'in' from big-endian byte order to an integer. */ -unsigned long long PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_bytes_to_ull( - const unsigned char *in, size_t inlen); +#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); /** * Computes a root node given a leaf and an auth path. * Expects address to be complete other than the tree_height and tree_index. */ -void PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); +#define compute_root SPX_NAMESPACE(compute_root) +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]); /** * For a given leaf index, computes the authentication path and the resulting * root node using Merkle's TreeHash algorithm. * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_ADDR_TYPE_FORSTREE). + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). * Applies the offset idx_offset to indices before building addresses, so that * it is possible to continue counting indices across trees. */ -void PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); +#define treehash SPX_NAMESPACE(treehash) +void treehash(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx *ctx /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]); -void PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/utilsx1.c b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/utilsx1.c new file mode 100644 index 0000000000..fccb69b35d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/utilsx1.c @@ -0,0 +1,100 @@ +#include + +#include "utilsx1.h" + +#include "address.h" +#include "params.h" +#include "thash.h" +#include "utils.h" + +/* + * Generate the entire Merkle tree, computing the authentication path for + * leaf_idx, and the resulting root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) + * + * This expects tree_addr to be initialized to the addr structures for the + * Merkle tree nodes + * + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + * + * This works by using the standard Merkle tree building algorithm, + */ +void treehashx1(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, + uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* Where to write the leaves */, + const spx_ctx * /* ctx */, + uint32_t idx, void *info), + uint32_t tree_addr[8], + void *info) { + /* This is where we keep the intermediate nodes */ + PQCLEAN_VLA(uint8_t, stack, tree_height * SPX_N); + + uint32_t idx; + uint32_t max_idx = (uint32_t)((1 << tree_height) - 1); + for (idx = 0;; idx++) { + unsigned char current[2 * SPX_N]; /* Current logical node is at */ + /* index[SPX_N]. We do this to minimize the number of copies */ + /* needed during a thash */ + gen_leaf( ¤t[SPX_N], ctx, idx + idx_offset, + info ); + + /* Now combine the freshly generated right node with previously */ + /* generated left ones */ + uint32_t internal_idx_offset = idx_offset; + uint32_t internal_idx = idx; + uint32_t internal_leaf = leaf_idx; + uint32_t h; /* The height we are in the Merkle tree */ + for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { + + /* Check if we hit the top of the tree */ + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[SPX_N], SPX_N ); + return; + } + + /* + * Check if the node we have is a part of the + * authentication path; if it is, write it out + */ + if ((internal_idx ^ internal_leaf) == 0x01) { + memcpy( &auth_path[ h * SPX_N ], + ¤t[SPX_N], + SPX_N ); + } + + /* + * Check if we're at a left child; if so, stop going up the stack + * Exception: if we've reached the end of the tree, keep on going + * (so we combine the last 4 nodes into the one root node in two + * more iterations) + */ + if ((internal_idx & 1) == 0 && idx < max_idx) { + break; + } + + /* Ok, we're at a right node */ + /* Now combine the left and right logical nodes together */ + + /* Set the address of the node we're creating. */ + internal_idx_offset >>= 1; + set_tree_height(tree_addr, h + 1); + set_tree_index(tree_addr, internal_idx / 2 + internal_idx_offset ); + + unsigned char *left = &stack[h * SPX_N]; + memcpy( ¤t[0], left, SPX_N ); + thash( ¤t[1 * SPX_N], + ¤t[0 * SPX_N], + 2, ctx, tree_addr); + } + + /* We've hit a left child; save the current for when we get the */ + /* corresponding right right */ + memcpy( &stack[h * SPX_N], ¤t[SPX_N], SPX_N); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/utilsx1.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/utilsx1.h new file mode 100644 index 0000000000..e911d17d53 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/utilsx1.h @@ -0,0 +1,27 @@ +#ifndef SPX_UTILSX4_H +#define SPX_UTILSX4_H + +#include + +#include "context.h" +#include "params.h" + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +#define treehashx1 SPX_NAMESPACE(treehashx1) +void treehashx1(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* Where to write the leaf */, + const spx_ctx * /* ctx */, + uint32_t addr_idx, void *info), + uint32_t tree_addrx4[8], void *info); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/wots.c b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/wots.c index 83188d1fda..249717aaa8 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/wots.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/wots.c @@ -1,32 +1,20 @@ #include #include +#include "wots.h" +#include "wotsx1.h" + #include "address.h" #include "hash.h" -#include "hash_state.h" #include "params.h" #include "thash.h" #include "utils.h" -#include "wots.h" +#include "utilsx1.h" // TODO clarify address expectations, and make them more uniform. // TODO i.e. do we expect types to be set already? // TODO and do we expect modifications or copies? -/** - * Computes the starting value for a chain, i.e. the secret key. - * Expects the address to be complete up to the chain address. - */ -static void wots_gen_sk(unsigned char *sk, const unsigned char *sk_seed, - uint32_t wots_addr[8], - const hash_state *hash_state_seeded) { - /* Make sure that the hash address is actually zeroed. */ - PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_set_hash_addr(wots_addr, 0); - - /* Generate sk element. */ - PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_prf_addr(sk, sk_seed, wots_addr, hash_state_seeded); -} - /** * Computes the chaining function. * out and in have to be n-byte arrays. @@ -36,18 +24,16 @@ static void wots_gen_sk(unsigned char *sk, const unsigned char *sk_seed, */ static void gen_chain(unsigned char *out, const unsigned char *in, unsigned int start, unsigned int steps, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { + const spx_ctx *ctx, uint32_t addr[8]) { uint32_t i; /* Initialize out with the value at position 'start'. */ - memcpy(out, in, PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_N); + memcpy(out, in, SPX_N); /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_WOTS_W; i++) { - PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_set_hash_addr(addr, i); - PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_thash_1( - out, out, pub_seed, addr, hash_state_seeded); + for (i = start; i < (start + steps) && i < SPX_WOTS_W; i++) { + set_hash_addr(addr, i); + thash(out, out, 1, ctx, addr); } } @@ -56,13 +42,13 @@ static void gen_chain(unsigned char *out, const unsigned char *in, * Interprets an array of bytes as integers in base w. * This only works when log_w is a divisor of 8. */ -static void base_w(unsigned int *output, const size_t out_len, +static void base_w(unsigned int *output, const int out_len, const unsigned char *input) { - size_t in = 0; - size_t out = 0; + int in = 0; + int out = 0; unsigned char total = 0; - unsigned int bits = 0; - size_t consumed; + int bits = 0; + int consumed; for (consumed = 0; consumed < out_len; consumed++) { if (bits == 0) { @@ -70,8 +56,8 @@ static void base_w(unsigned int *output, const size_t out_len, in++; bits += 8; } - bits -= PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_WOTS_LOGW; - output[out] = (unsigned int)((total >> bits) & (PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_WOTS_W - 1)); + bits -= SPX_WOTS_LOGW; + output[out] = (total >> bits) & (SPX_WOTS_W - 1); out++; } } @@ -80,67 +66,25 @@ static void base_w(unsigned int *output, const size_t out_len, static void wots_checksum(unsigned int *csum_base_w, const unsigned int *msg_base_w) { unsigned int csum = 0; - unsigned char csum_bytes[(PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_WOTS_LEN2 * PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_WOTS_LOGW + 7) / 8]; + unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; unsigned int i; /* Compute checksum. */ - for (i = 0; i < PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_WOTS_LEN1; i++) { - csum += PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_WOTS_W - 1 - msg_base_w[i]; + for (i = 0; i < SPX_WOTS_LEN1; i++) { + csum += SPX_WOTS_W - 1 - msg_base_w[i]; } /* Convert checksum to base_w. */ /* Make sure expected empty zero bits are the least significant bits. */ - csum = csum << (8 - ((PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_WOTS_LEN2 * PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_WOTS_LOGW) % 8)); - PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_ull_to_bytes( - csum_bytes, sizeof(csum_bytes), csum); - base_w(csum_base_w, PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_WOTS_LEN2, csum_bytes); + csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); + ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); + base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); } /* Takes a message and derives the matching chain lengths. */ -static void chain_lengths(unsigned int *lengths, const unsigned char *msg) { - base_w(lengths, PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_WOTS_LEN1, msg); - wots_checksum(lengths + PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_WOTS_LEN1, lengths); -} - -/** - * WOTS key generation. Takes a 32 byte sk_seed, expands it to WOTS private key - * elements and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_wots_gen_pk( - unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - uint32_t i; - - for (i = 0; i < PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_WOTS_LEN; i++) { - PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_set_chain_addr(addr, i); - wots_gen_sk(pk + i * PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_N, sk_seed, addr, hash_state_seeded); - gen_chain(pk + i * PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_N, pk + i * PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_N, - 0, PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_WOTS_W - 1, pub_seed, addr, hash_state_seeded); - } -} - -/** - * Takes a n-byte message and the 32-byte sk_see to compute a signature 'sig'. - */ -void PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_wots_sign( - unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *hash_state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_WOTS_LEN; i++) { - PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_set_chain_addr(addr, i); - wots_gen_sk(sig + i * PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_N, sk_seed, addr, hash_state_seeded); - gen_chain(sig + i * PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_N, sig + i * PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_N, 0, lengths[i], pub_seed, addr, hash_state_seeded); - } +void chain_lengths(unsigned int *lengths, const unsigned char *msg) { + base_w(lengths, SPX_WOTS_LEN1, msg); + wots_checksum(lengths + SPX_WOTS_LEN1, lengths); } /** @@ -148,20 +92,17 @@ void PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_wots_sign( * * Writes the computed public key to 'pk'. */ -void PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_wots_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_WOTS_LEN]; +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]) { + unsigned int lengths[SPX_WOTS_LEN]; uint32_t i; chain_lengths(lengths, msg); - for (i = 0; i < PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_WOTS_LEN; i++) { - PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_set_chain_addr(addr, i); - gen_chain(pk + i * PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_N, sig + i * PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_N, - lengths[i], PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_WOTS_W - 1 - lengths[i], pub_seed, addr, - hash_state_seeded); + for (i = 0; i < SPX_WOTS_LEN; i++) { + set_chain_addr(addr, i); + gen_chain(pk + i * SPX_N, sig + i * SPX_N, + lengths[i], SPX_WOTS_W - 1 - lengths[i], ctx, addr); } } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/wots.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/wots.h index 483e1b38a6..4e7692eeef 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/wots.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/wots.h @@ -1,41 +1,25 @@ -#ifndef PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_WOTS_H -#define PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_WOTS_H +#ifndef SPX_WOTS_H +#define SPX_WOTS_H -#include "hash_state.h" -#include "params.h" #include -/** - * WOTS key generation. Takes a 32 byte seed for the private key, expands it to - * a full WOTS private key and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_wots_gen_pk( - unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -/** - * Takes a n-byte message and the 32-byte seed for the private key to compute a - * signature that is placed at 'sig'. - */ -void PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_wots_sign( - unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *hash_state_seeded); +#include "context.h" +#include "params.h" /** * Takes a WOTS signature and an n-byte message, computes a WOTS public key. * * Writes the computed public key to 'pk'. */ -void PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_wots_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); +#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]); + +/* + * Compute the chain lengths needed for a given message hash + */ +#define chain_lengths SPX_NAMESPACE(chain_lengths) +void chain_lengths(unsigned int *lengths, const unsigned char *msg); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/wotsx1.c b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/wotsx1.c new file mode 100644 index 0000000000..3adec78dfb --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/wotsx1.c @@ -0,0 +1,76 @@ +#include +#include + +#include "wots.h" +#include "wotsx1.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "thash.h" +#include "utils.h" + +/* + * This generates a WOTS public key + * It also generates the WOTS signature if leaf_info indicates + * that we're signing with this WOTS key + */ +void wots_gen_leafx1(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info) { + struct leaf_info_x1 *info = v_info; + uint32_t *leaf_addr = info->leaf_addr; + uint32_t *pk_addr = info->pk_addr; + unsigned int i, k; + unsigned char pk_buffer[ SPX_WOTS_BYTES ]; + unsigned char *buffer; + uint32_t wots_k_mask; + + if (leaf_idx == info->wots_sign_leaf) { + /* We're traversing the leaf that's signing; generate the WOTS */ + /* signature */ + wots_k_mask = 0; + } else { + /* Nope, we're just generating pk's; turn off the signature logic */ + wots_k_mask = (uint32_t)~0; + } + + set_keypair_addr( leaf_addr, leaf_idx ); + set_keypair_addr( pk_addr, leaf_idx ); + + for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { + uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k to */ + /* the step if we're generating a signature, ~0 if we're not */ + + /* Start with the secret seed */ + set_chain_addr(leaf_addr, i); + set_hash_addr(leaf_addr, 0); + set_type(leaf_addr, SPX_ADDR_TYPE_WOTSPRF); + + prf_addr(buffer, ctx, leaf_addr); + + set_type(leaf_addr, SPX_ADDR_TYPE_WOTS); + + /* Iterate down the WOTS chain */ + for (k = 0;; k++) { + /* Check if this is the value that needs to be saved as a */ + /* part of the WOTS signature */ + if (k == wots_k) { + memcpy( info->wots_sig + i * SPX_N, buffer, SPX_N ); + } + + /* Check if we hit the top of the chain */ + if (k == SPX_WOTS_W - 1) { + break; + } + + /* Iterate one step on the chain */ + set_hash_addr(leaf_addr, k); + + thash(buffer, buffer, 1, ctx, leaf_addr); + } + } + + /* Do the final thash to generate the public keys */ + thash(dest, pk_buffer, SPX_WOTS_LEN, ctx, pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/wotsx1.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/wotsx1.h new file mode 100644 index 0000000000..e617929f96 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/wotsx1.h @@ -0,0 +1,39 @@ +#ifndef WOTSX1_H_ +#define WOTSX1_H_ + +#include + +#include "context.h" +#include "params.h" + +/* + * This is here to provide an interface to the internal wots_gen_leafx1 + * routine. While this routine is not referenced in the package outside of + * wots.c, it is called from the stand-alone benchmark code to characterize + * the performance + */ +struct leaf_info_x1 { + unsigned char *wots_sig; + uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ + uint32_t *wots_steps; + uint32_t leaf_addr[8]; + uint32_t pk_addr[8]; +}; + +/* Macro to set the leaf_info to something 'benign', that is, it would */ +/* run with the same time as it does during the real signing process */ +/* Used only by the benchmark code */ +#define INITIALIZE_LEAF_INFO_X1(info, addr, step_buffer) { \ + (info).wots_sig = 0; \ + (info).wots_sign_leaf = ~0; \ + (info).wots_steps = step_buffer; \ + memcpy( &(info).leaf_addr[0], (addr), 32 ); \ + memcpy( &(info).pk_addr[0], (addr), 32 ); \ + } + +#define wots_gen_leafx1 SPX_NAMESPACE(wots_gen_leafx1) +void wots_gen_leafx1(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info); + +#endif /* WOTSX1_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/address.c b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/address.c index 9d4f81a822..b956e9cb29 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/address.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/address.c @@ -1,78 +1,91 @@ #include +#include #include "address.h" #include "params.h" #include "utils.h" -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]) { - int i; - - for (i = 0; i < 8; i++) { - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_ull_to_bytes( - bytes + i * 4, 4, addr[i]); - } -} - -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_set_layer_addr( - uint32_t addr[8], uint32_t layer) { - addr[0] = layer; +/* + * Specify which level of Merkle tree (the "layer") we're working on + */ +void set_layer_addr(uint32_t addr[8], uint32_t layer) { + ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; } -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_set_tree_addr( - uint32_t addr[8], uint64_t tree) { - addr[1] = 0; - addr[2] = (uint32_t) (tree >> 32); - addr[3] = (uint32_t) tree; +/* + * Specify which Merkle tree within the level (the "tree address") we're working on + */ +void set_tree_addr(uint32_t addr[8], uint64_t tree) { + ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); } -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_set_type( - uint32_t addr[8], uint32_t type) { - addr[4] = type; +/* + * Specify the reason we'll use this address structure for, that is, what + * hash will we compute with it. This is used so that unrelated types of + * hashes don't accidentally get the same address structure. The type will be + * one of the SPX_ADDR_TYPE constants + */ +void set_type(uint32_t addr[8], uint32_t type) { + ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; } -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; +/* + * Copy the layer and tree fields of the address structure. This is used + * when we're doing multiple types of hashes within the same Merkle tree + */ +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); } /* These functions are used for OTS addresses. */ -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_set_keypair_addr( - uint32_t addr[8], uint32_t keypair) { - addr[5] = keypair; +/* + * Specify which Merkle leaf we're working on; that is, which OTS keypair + * we're talking about. + */ +void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { + ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; } -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; - out[5] = in[5]; +/* + * Copy the layer, tree and keypair fields of the address structure. This is + * used when we're doing multiple things within the same OTS keypair + */ +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); + ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; } -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_set_chain_addr( - uint32_t addr[8], uint32_t chain) { - addr[6] = chain; +/* + * Specify which Merkle chain within the OTS we're working with + * (the chain address) + */ +void set_chain_addr(uint32_t addr[8], uint32_t chain) { + ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; } -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_set_hash_addr( - uint32_t addr[8], uint32_t hash) { - addr[7] = hash; +/* + * Specify where in the Merkle chain we are +* (the hash address) + */ +void set_hash_addr(uint32_t addr[8], uint32_t hash) { + ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; } /* These functions are used for all hash tree addresses (including FORS). */ -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_set_tree_height( - uint32_t addr[8], uint32_t tree_height) { - addr[6] = tree_height; +/* + * Specify the height of the node in the Merkle/FORS tree we are in + * (the tree height) + */ +void set_tree_height(uint32_t addr[8], uint32_t tree_height) { + ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; } -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_set_tree_index( - uint32_t addr[8], uint32_t tree_index) { - addr[7] = tree_index; +/* + * Specify the distance from the left edge of the node in the Merkle/FORS tree + * (the tree index) + */ +void set_tree_index(uint32_t addr[8], uint32_t tree_index) { + u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/address.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/address.h index cc7f456877..24a84eb40c 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/address.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/address.h @@ -1,50 +1,52 @@ -#ifndef PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_ADDRESS_H -#define PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_ADDRESS_H +#ifndef SPX_ADDRESS_H +#define SPX_ADDRESS_H #include -#define PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_ADDR_TYPE_WOTS 0 -#define PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_ADDR_TYPE_WOTSPK 1 -#define PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_ADDR_TYPE_HASHTREE 2 -#define PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_ADDR_TYPE_FORSTREE 3 -#define PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_ADDR_TYPE_FORSPK 4 +#include "params.h" -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]); +/* The hash types that are passed to set_type */ +#define SPX_ADDR_TYPE_WOTS 0 +#define SPX_ADDR_TYPE_WOTSPK 1 +#define SPX_ADDR_TYPE_HASHTREE 2 +#define SPX_ADDR_TYPE_FORSTREE 3 +#define SPX_ADDR_TYPE_FORSPK 4 +#define SPX_ADDR_TYPE_WOTSPRF 5 +#define SPX_ADDR_TYPE_FORSPRF 6 -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_set_layer_addr( - uint32_t addr[8], uint32_t layer); +#define set_layer_addr SPX_NAMESPACE(set_layer_addr) +void set_layer_addr(uint32_t addr[8], uint32_t layer); -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_set_tree_addr( - uint32_t addr[8], uint64_t tree); +#define set_tree_addr SPX_NAMESPACE(set_tree_addr) +void set_tree_addr(uint32_t addr[8], uint64_t tree); -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_set_type( - uint32_t addr[8], uint32_t type); +#define set_type SPX_NAMESPACE(set_type) +void set_type(uint32_t addr[8], uint32_t type); /* Copies the layer and tree part of one address into the other */ -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]); +#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); /* These functions are used for WOTS and FORS addresses. */ -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_set_keypair_addr( - uint32_t addr[8], uint32_t keypair); +#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) +void set_keypair_addr(uint32_t addr[8], uint32_t keypair); -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_set_chain_addr( - uint32_t addr[8], uint32_t chain); +#define set_chain_addr SPX_NAMESPACE(set_chain_addr) +void set_chain_addr(uint32_t addr[8], uint32_t chain); -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_set_hash_addr( - uint32_t addr[8], uint32_t hash); +#define set_hash_addr SPX_NAMESPACE(set_hash_addr) +void set_hash_addr(uint32_t addr[8], uint32_t hash); -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]); +#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); /* These functions are used for all hash tree addresses (including FORS). */ -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_set_tree_height( - uint32_t addr[8], uint32_t tree_height); +#define set_tree_height SPX_NAMESPACE(set_tree_height) +void set_tree_height(uint32_t addr[8], uint32_t tree_height); -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_set_tree_index( - uint32_t addr[8], uint32_t tree_index); +#define set_tree_index SPX_NAMESPACE(set_tree_index) +void set_tree_index(uint32_t addr[8], uint32_t tree_index); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/api.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/api.h index 7f3ef8c074..05d16a3ded 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/api.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/api.h @@ -4,15 +4,13 @@ #include #include - - -#define PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_CRYPTO_ALGNAME "SPHINCS+" +#define PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_CRYPTO_ALGNAME "SPHINCS+-haraka-256f-simple" #define PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_CRYPTO_SECRETKEYBYTES 128 #define PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_CRYPTO_PUBLICKEYBYTES 64 -#define PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_CRYPTO_BYTES 49856 -#define PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_CRYPTO_SEEDBYTES 96 +#define PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_CRYPTO_BYTES 49856 +#define PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_CRYPTO_SEEDBYTES 96 /* * Returns the length of a secret key, in bytes @@ -39,43 +37,41 @@ size_t PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_crypto_sign_seedbytes(void); * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] * Format pk: [root || PUB_SEED] */ -int PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed); +int PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); /* * Generates a SPHINCS+ key pair. * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] * Format pk: [root || PUB_SEED] */ -int PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk); +int PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); /** * Returns an array containing a detached signature. */ -int PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk); +int PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); /** * Verifies a detached signature and message under a given public key. */ -int PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk); +int PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, + const uint8_t *pk); /** * Returns an array containing the signature followed by the message. */ -int PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk); +int PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); /** * Verifies a given signature-message pair under a given public key. */ -int PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk); - +int PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/context.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/context.h new file mode 100644 index 0000000000..f03446b9cb --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/context.h @@ -0,0 +1,22 @@ +#ifndef SPX_CONTEXT_H +#define SPX_CONTEXT_H + +#include + +#include "immintrin.h" +#include "params.h" + +typedef struct { + uint8_t pub_seed[SPX_N]; + uint8_t sk_seed[SPX_N]; + + __m128i rc[40]; +} spx_ctx; + +#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) +void initialize_hash_function(spx_ctx *ctx); + +#define free_hash_function SPX_NAMESPACE(free_hash_function) +void free_hash_function(spx_ctx *ctx); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/context_haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/context_haraka.c new file mode 100644 index 0000000000..f1cd7e3664 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/context_haraka.c @@ -0,0 +1,11 @@ +#include "context.h" +#include "haraka.h" + +void initialize_hash_function(spx_ctx *ctx) { + tweak_constants(ctx); +} + +// we don't support heap-based haraka right now +void free_hash_function(spx_ctx *ctx) { + (void)ctx; // suppress unused variable warnings +} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/fors.c b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/fors.c index 52dbb8ed8c..f1b0639cfc 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/fors.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/fors.c @@ -2,8 +2,9 @@ #include #include -#include "address.h" #include "fors.h" + +#include "address.h" #include "hash.h" #include "hashx4.h" #include "thash.h" @@ -11,19 +12,24 @@ #include "utils.h" #include "utilsx4.h" +static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + prf_addr(sk, ctx, fors_leaf_addr); +} + static void fors_gen_skx4(unsigned char *sk0, unsigned char *sk1, unsigned char *sk2, - unsigned char *sk3, const unsigned char *sk_seed, - uint32_t fors_leaf_addrx4[4 * 8], - const hash_state *state_seeded) { - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_prf_addrx4(sk0, sk1, sk2, sk3, sk_seed, fors_leaf_addrx4, state_seeded); + unsigned char *sk3, const spx_ctx *ctx, + uint32_t fors_leaf_addrx4[4 * 8]) { + prf_addrx4(sk0, sk1, sk2, sk3, + ctx, fors_leaf_addrx4); } static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, - const unsigned char *pub_seed, - uint32_t fors_leaf_addr[8], const hash_state *state_seeded) { - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_thash_1(leaf, sk, pub_seed, fors_leaf_addr, state_seeded); + const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + thash(leaf, sk, 1, ctx, fors_leaf_addr); } static void fors_sk_to_leafx4(unsigned char *leaf0, @@ -34,57 +40,64 @@ static void fors_sk_to_leafx4(unsigned char *leaf0, const unsigned char *sk1, const unsigned char *sk2, const unsigned char *sk3, - const unsigned char *pub_seed, - uint32_t fors_leaf_addrx4[4 * 8], - const hash_state *state_seeded) { - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_thashx4_1(leaf0, leaf1, leaf2, leaf3, - sk0, sk1, sk2, sk3, pub_seed, fors_leaf_addrx4, state_seeded); + const spx_ctx *ctx, + uint32_t fors_leaf_addrx4[4 * 8]) { + thashx4(leaf0, leaf1, leaf2, leaf3, + sk0, sk1, sk2, sk3, + 1, ctx, fors_leaf_addrx4); } -static void fors_gen_leafx4(unsigned char *leaf0, - unsigned char *leaf1, - unsigned char *leaf2, - unsigned char *leaf3, - const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx0, - uint32_t addr_idx1, - uint32_t addr_idx2, - uint32_t addr_idx3, - const uint32_t fors_tree_addr[8], - const hash_state *state_seeded) { - uint32_t fors_leaf_addrx4[4 * 8] = {0}; +struct fors_gen_leaf_info { + uint32_t leaf_addrx[4 * 8]; +}; + +static void fors_gen_leafx4(unsigned char *leaf, + const spx_ctx *ctx, + uint32_t addr_idx, void *info) { + struct fors_gen_leaf_info *fors_info = info; + uint32_t *fors_leaf_addrx4 = fors_info->leaf_addrx; unsigned int j; - /* Only copy the parts that must be kept in fors_leaf_addrx4. */ + /* Only set the parts that the caller doesn't set */ for (j = 0; j < 4; j++) { - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_copy_keypair_addr(fors_leaf_addrx4 + j * 8, fors_tree_addr); - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_set_type(fors_leaf_addrx4 + j * 8, PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_ADDR_TYPE_FORSTREE); + set_tree_index(fors_leaf_addrx4 + j * 8, addr_idx + j); + set_type(fors_leaf_addrx4 + j * 8, SPX_ADDR_TYPE_FORSPRF); } - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_set_tree_index(fors_leaf_addrx4 + 0 * 8, addr_idx0); - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_set_tree_index(fors_leaf_addrx4 + 1 * 8, addr_idx1); - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_set_tree_index(fors_leaf_addrx4 + 2 * 8, addr_idx2); - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_set_tree_index(fors_leaf_addrx4 + 3 * 8, addr_idx3); + fors_gen_skx4(leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + leaf + 2 * SPX_N, + leaf + 3 * SPX_N, + ctx, fors_leaf_addrx4); + + for (j = 0; j < 4; j++) { + set_type(fors_leaf_addrx4 + j * 8, SPX_ADDR_TYPE_FORSTREE); + } - fors_gen_skx4(leaf0, leaf1, leaf2, leaf3, sk_seed, fors_leaf_addrx4, state_seeded); - fors_sk_to_leafx4(leaf0, leaf1, leaf2, leaf3, - leaf0, leaf1, leaf2, leaf3, pub_seed, fors_leaf_addrx4, state_seeded); + fors_sk_to_leafx4(leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + leaf + 2 * SPX_N, + leaf + 3 * SPX_N, + leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + leaf + 2 * SPX_N, + leaf + 3 * SPX_N, + ctx, fors_leaf_addrx4); } /** - * Interprets m as PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_FORS_HEIGHT-bit unsigned integers. - * Assumes m contains at least PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_FORS_TREES bits. - * Assumes indices has space for PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_FORS_TREES integers. + * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + * Assumes indices has space for SPX_FORS_TREES integers. */ static void message_to_indices(uint32_t *indices, const unsigned char *m) { unsigned int i, j; unsigned int offset = 0; - for (i = 0; i < PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_FORS_TREES; i++) { + for (i = 0; i < SPX_FORS_TREES; i++) { indices[i] = 0; - for (j = 0; j < PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_FORS_HEIGHT; j++) { - indices[i] ^= (((uint32_t)m[offset >> 3] >> (offset & 0x7)) & 0x1) << j; + for (j = 0; j < SPX_FORS_HEIGHT; j++) { + indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); offset++; } } @@ -92,68 +105,53 @@ static void message_to_indices(uint32_t *indices, const unsigned char *m) { /** * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_FORS_TREES bits. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. */ -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *state_seeded) { - /* Round up to multiple of 4 to prevent out-of-bounds for x4 parallelism */ - uint32_t indices[(PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_FORS_TREES + 3) & ~3] = {0}; - unsigned char roots[((PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_FORS_TREES + 3) & ~3) * PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N]; - /* Sign to a buffer, since we may not have a nice multiple of 4 and would - otherwise overrun the signature. */ - unsigned char sigbufx4[4 * PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N * (1 + PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_FORS_HEIGHT)]; - uint32_t fors_tree_addrx4[4 * 8] = {0}; +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + uint32_t fors_tree_addr[4 * 8] = {0}; + struct fors_gen_leaf_info fors_info = {0}; + uint32_t *fors_leaf_addr = fors_info.leaf_addrx; uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset[4] = {0}; - unsigned int i, j; + uint32_t idx_offset; + unsigned int i; - for (j = 0; j < 4; j++) { - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_copy_keypair_addr(fors_tree_addrx4 + j * 8, fors_addr); - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_set_type(fors_tree_addrx4 + j * 8, PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_ADDR_TYPE_FORSTREE); + for (i = 0; i < 4; i++) { + copy_keypair_addr(fors_tree_addr + 8 * i, fors_addr); + set_type(fors_tree_addr + 8 * i, SPX_ADDR_TYPE_FORSTREE); + copy_keypair_addr(fors_leaf_addr + 8 * i, fors_addr); } - - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_copy_keypair_addr(fors_pk_addr, fors_addr); - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_set_type(fors_pk_addr, PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_ADDR_TYPE_FORSPK); + copy_keypair_addr(fors_pk_addr, fors_addr); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); message_to_indices(indices, m); - for (i = 0; i < ((PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_FORS_TREES + 3) & ~0x3); i += 4) { - for (j = 0; j < 4; j++) { - if (i + j < PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_FORS_TREES) { - idx_offset[j] = (i + j) * (1 << PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_FORS_HEIGHT); + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_set_tree_height(fors_tree_addrx4 + j * 8, 0); - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_set_tree_index(fors_tree_addrx4 + j * 8, - indices[i + j] + idx_offset[j]); - } - } + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); - /* Include the secret key part that produces the selected leaf nodes. */ - fors_gen_skx4(sigbufx4 + 0 * PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N, - sigbufx4 + 1 * PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N, - sigbufx4 + 2 * PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N, - sigbufx4 + 3 * PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N, - sk_seed, fors_tree_addrx4, state_seeded); - - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_treehashx4_FORS_HEIGHT(roots + i * PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N, sigbufx4 + 4 * PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N, sk_seed, pub_seed, - &indices[i], idx_offset, fors_gen_leafx4, fors_tree_addrx4, - state_seeded); - - for (j = 0; j < 4; j++) { - if (i + j < PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_FORS_TREES) { - memcpy(sig, sigbufx4 + j * PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N, PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N); - memcpy(sig + PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N, - sigbufx4 + 4 * PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N + j * PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N * PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_FORS_HEIGHT, - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N * PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_FORS_HEIGHT); - sig += PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N * (1 + PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_FORS_HEIGHT); - } - } + /* Include the secret key part that produces the selected leaf node. */ + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); + fors_gen_sk(sig, ctx, fors_tree_addr); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + sig += SPX_N; + + /* Compute the authentication path for this leaf node. */ + treehashx4(roots + i * SPX_N, sig, ctx, + indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx4, + fors_tree_addr, &fors_info); + + sig += SPX_N * SPX_FORS_HEIGHT; } /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_thash_FORS_TREES(pk, roots, pub_seed, fors_pk_addr, state_seeded); + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); } /** @@ -161,46 +159,44 @@ void PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_fors_sign(unsigned char *sig, unsigne * This can be used for verification by comparing to a known public key, or to * subsequently verify a signature on the derived public key. The latter is the * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_FORS_TREES bits. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. */ -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, - const uint32_t fors_addr[8], - const hash_state *state_seeded) { - uint32_t indices[PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_FORS_TREES]; - unsigned char roots[PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_FORS_TREES * PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N]; - unsigned char leaf[PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N]; +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + unsigned char leaf[SPX_N]; uint32_t fors_tree_addr[8] = {0}; uint32_t fors_pk_addr[8] = {0}; uint32_t idx_offset; unsigned int i; - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_copy_keypair_addr(fors_tree_addr, fors_addr); - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_copy_keypair_addr(fors_pk_addr, fors_addr); + copy_keypair_addr(fors_tree_addr, fors_addr); + copy_keypair_addr(fors_pk_addr, fors_addr); - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_set_type(fors_tree_addr, PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_set_type(fors_pk_addr, PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_ADDR_TYPE_FORSPK); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); message_to_indices(indices, m); - for (i = 0; i < PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_FORS_TREES; i++) { - idx_offset = i * (1 << PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_FORS_HEIGHT); + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_set_tree_height(fors_tree_addr, 0); - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_set_tree_index(fors_tree_addr, indices[i] + idx_offset); + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); /* Derive the leaf from the included secret key part. */ - fors_sk_to_leaf(leaf, sig, pub_seed, fors_tree_addr, state_seeded); - sig += PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N; + fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); + sig += SPX_N; /* Derive the corresponding root node of this tree. */ - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_compute_root(roots + i * PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N, leaf, indices[i], idx_offset, - sig, PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_FORS_HEIGHT, pub_seed, fors_tree_addr, - state_seeded); - sig += PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N * PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_FORS_HEIGHT; + compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, + sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); + sig += SPX_N * SPX_FORS_HEIGHT; } /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_thash_FORS_TREES(pk, roots, pub_seed, fors_pk_addr, state_seeded); + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/fors.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/fors.h index ac30ea43f9..509140a178 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/fors.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/fors.h @@ -1,32 +1,32 @@ -#ifndef PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_FORS_H -#define PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_FORS_H +#ifndef SPX_FORS_H +#define SPX_FORS_H #include -#include "hash_state.h" +#include "context.h" #include "params.h" /** * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_FORS_TREES bits. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. */ -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_fors_sign( - unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *hash_state_seeded); +#define fors_sign SPX_NAMESPACE(fors_sign) +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); /** * Derives the FORS public key from a signature. * This can be used for verification by comparing to a known public key, or to * subsequently verify a signature on the derived public key. The latter is the * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_FORS_TREES bits. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. */ -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_fors_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, const uint32_t fors_addr[8], - const hash_state *hash_state_seeded); +#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/haraka.c index 46daeef867..b414b691d7 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/haraka.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/haraka.c @@ -8,10 +8,12 @@ Plain C implementation of the Haraka256 and Haraka512 permutations. #include #include "haraka.h" +#include "harakax4.h" +#include "utils.h" #define HARAKAS_RATE 32 -#define u64 uint64_t +#define u64 unsigned long #define u128 __m128i #define LOAD(src) _mm_loadu_si128((u128 *)(src)) @@ -20,7 +22,7 @@ Plain C implementation of the Haraka256 and Haraka512 permutations. #define XOR128(a, b) _mm_xor_si128(a, b) #define AES2(s0, s1, rci) \ - (s0) = _mm_aesenc_si128(s0, *(rci)); \ + s0 = _mm_aesenc_si128(s0, *(rci)); \ (s1) = _mm_aesenc_si128(s1, *((rci) + 1)); \ (s0) = _mm_aesenc_si128(s0, *((rci) + 2)); \ (s1) = _mm_aesenc_si128(s1, *((rci) + 3)); @@ -32,7 +34,7 @@ Plain C implementation of the Haraka256 and Haraka512 permutations. AES2((s3)[0], (s3)[1], rci); #define AES4(s0, s1, s2, s3, rci) \ - (s0) = _mm_aesenc_si128(s0, *(rci)); \ + s0 = _mm_aesenc_si128(s0, *(rci)); \ (s1) = _mm_aesenc_si128(s1, *((rci) + 1)); \ (s2) = _mm_aesenc_si128(s2, *((rci) + 2)); \ (s3) = _mm_aesenc_si128(s3, *((rci) + 3)); \ @@ -68,17 +70,17 @@ Plain C implementation of the Haraka256 and Haraka512 permutations. _mm_storeu_si128((u128 *)((out) + 16), \ _mm_castpd_si128(_mm_shuffle_pd(_mm_castsi128_pd(s2), _mm_castsi128_pd(s3), 0))); -static void load_haraka_constants(u128 rc[40]) { - rc[ 0] = _mm_set_epi32((int)0x0684704c, (int)0xe620c00a, (int)0xb2c5fef0, (int)0x75817b9d); - rc[ 1] = _mm_set_epi32((int)0x8b66b4e1, (int)0x88f3a06b, (int)0x640f6ba4, (int)0x2f08f717); - rc[ 2] = _mm_set_epi32((int)0x3402de2d, (int)0x53f28498, (int)0xcf029d60, (int)0x9f029114); - rc[ 3] = _mm_set_epi32((int)0x0ed6eae6, (int)0x2e7b4f08, (int)0xbbf3bcaf, (int)0xfd5b4f79); - rc[ 4] = _mm_set_epi32((int)0xcbcfb0cb, (int)0x4872448b, (int)0x79eecd1c, (int)0xbe397044); - rc[ 5] = _mm_set_epi32((int)0x7eeacdee, (int)0x6e9032b7, (int)0x8d5335ed, (int)0x2b8a057b); - rc[ 6] = _mm_set_epi32((int)0x67c28f43, (int)0x5e2e7cd0, (int)0xe2412761, (int)0xda4fef1b); - rc[ 7] = _mm_set_epi32((int)0x2924d9b0, (int)0xafcacc07, (int)0x675ffde2, (int)0x1fc70b3b); - rc[ 8] = _mm_set_epi32((int)0xab4d63f1, (int)0xe6867fe9, (int)0xecdb8fca, (int)0xb9d465ee); - rc[ 9] = _mm_set_epi32((int)0x1c30bf84, (int)0xd4b7cd64, (int)0x5b2a404f, (int)0xad037e33); +static void load_haraka_constants(u128 *rc) { + rc[0] = _mm_set_epi32((int)0x0684704c, (int)0xe620c00a, (int)0xb2c5fef0, (int)0x75817b9d); + rc[1] = _mm_set_epi32((int)0x8b66b4e1, (int)0x88f3a06b, (int)0x640f6ba4, (int)0x2f08f717); + rc[2] = _mm_set_epi32((int)0x3402de2d, (int)0x53f28498, (int)0xcf029d60, (int)0x9f029114); + rc[3] = _mm_set_epi32((int)0x0ed6eae6, (int)0x2e7b4f08, (int)0xbbf3bcaf, (int)0xfd5b4f79); + rc[4] = _mm_set_epi32((int)0xcbcfb0cb, (int)0x4872448b, (int)0x79eecd1c, (int)0xbe397044); + rc[5] = _mm_set_epi32((int)0x7eeacdee, (int)0x6e9032b7, (int)0x8d5335ed, (int)0x2b8a057b); + rc[6] = _mm_set_epi32((int)0x67c28f43, (int)0x5e2e7cd0, (int)0xe2412761, (int)0xda4fef1b); + rc[7] = _mm_set_epi32((int)0x2924d9b0, (int)0xafcacc07, (int)0x675ffde2, (int)0x1fc70b3b); + rc[8] = _mm_set_epi32((int)0xab4d63f1, (int)0xe6867fe9, (int)0xecdb8fca, (int)0xb9d465ee); + rc[9] = _mm_set_epi32((int)0x1c30bf84, (int)0xd4b7cd64, (int)0x5b2a404f, (int)0xad037e33); rc[10] = _mm_set_epi32((int)0xb2cc0bb9, (int)0x941723bf, (int)0x69028b2e, (int)0x8df69800); rc[11] = _mm_set_epi32((int)0xfa0478a6, (int)0xde6f5572, (int)0x4aaa9ec8, (int)0x5c9d2d8a); rc[12] = _mm_set_epi32((int)0xdfb49f2b, (int)0x6b772a12, (int)0x0efa4f2e, (int)0x29129fd4); @@ -111,77 +113,65 @@ static void load_haraka_constants(u128 rc[40]) { rc[39] = _mm_set_epi32((int)0x756acc03, (int)0x02288288, (int)0x4ad6bdfd, (int)0xe9c59da1); } -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_tweak_constants( - harakactx *state, - const unsigned char *pk_seed, const unsigned char *sk_seed, - unsigned long long seed_length) { +void tweak_constants(spx_ctx *ctx) { int i; unsigned char buf[40 * 16]; /* Use the standard constants to generate tweaked ones. */ - load_haraka_constants(state->rc); - - /* Constants for sk.seed */ - if (sk_seed != NULL) { - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_haraka_S(buf, 40 * 16, sk_seed, seed_length, state); - /* Tweak constants with the pub_seed */ - for (i = 0; i < 40; i++) { - state->rc_sseed[i] = LOAD(buf + i * 16); - } - } + load_haraka_constants(ctx->rc); /* Constants for pk.seed */ - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_haraka_S(buf, 40 * 16, pk_seed, seed_length, state); + haraka_S(buf, 40 * 16, ctx->pub_seed, SPX_N, ctx); /* Tweak constants with the pub_seed */ for (i = 0; i < 40; i++) { - state->rc[i] = LOAD(buf + i * 16); + ctx->rc[i] = LOAD(buf + i * 16); } } -static void haraka_S_absorb(unsigned char *s, +static void haraka_S_absorb(unsigned char *s, unsigned int r, const unsigned char *m, unsigned long long mlen, - unsigned char p, - const harakactx *state) { + unsigned char p, const spx_ctx *ctx) { unsigned long long i; - unsigned char t[HARAKAS_RATE]; + PQCLEAN_VLA(unsigned char, t, r); - while (mlen >= HARAKAS_RATE) { + while (mlen >= r) { // XOR block to state STORE(s, XOR128(LOAD(s), LOAD(m))); STORE(s + 16, XOR128(LOAD(s + 16), LOAD(m + 16))); - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_haraka512_perm(s, s, state); - mlen -= HARAKAS_RATE; - m += HARAKAS_RATE; + haraka512_perm(s, s, ctx); + mlen -= r; + m += r; } - for (i = 0; i < HARAKAS_RATE; ++i) { + for (i = 0; i < r; ++i) { t[i] = 0; } for (i = 0; i < mlen; ++i) { t[i] = m[i]; } t[i] = p; - t[HARAKAS_RATE - 1] |= 128; + t[r - 1] |= 128; STORE(s, XOR128(LOAD(s), LOAD(t))); STORE(s + 16, XOR128(LOAD(s + 16), LOAD(t + 16))); } static void haraka_S_absorb4x(unsigned char *s, + unsigned int r, const unsigned char *m0, const unsigned char *m1, const unsigned char *m2, const unsigned char *m3, unsigned long long int mlen, unsigned char p, - const harakactx *state) { + const spx_ctx *ctx) { unsigned long long i; - unsigned char t0[HARAKAS_RATE]; - unsigned char t1[HARAKAS_RATE]; - unsigned char t2[HARAKAS_RATE]; - unsigned char t3[HARAKAS_RATE]; + PQCLEAN_VLA(unsigned char, t0, r); + PQCLEAN_VLA(unsigned char, t1, r); + PQCLEAN_VLA(unsigned char, t2, r); + PQCLEAN_VLA(unsigned char, t3, r); - while (mlen >= HARAKAS_RATE) { + while (mlen >= r) { // XOR block to state STORE(s, XOR128(LOAD(s), LOAD(m0))); STORE(s + 16, XOR128(LOAD(s + 16), LOAD(m0 + 16))); @@ -192,15 +182,15 @@ static void haraka_S_absorb4x(unsigned char *s, STORE(s + 192, XOR128(LOAD(s + 192), LOAD(m3))); STORE(s + 208, XOR128(LOAD(s + 208), LOAD(m3 + 16))); - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_haraka512_perm_x4(s, s, state); - mlen -= HARAKAS_RATE; - m0 += HARAKAS_RATE; - m1 += HARAKAS_RATE; - m2 += HARAKAS_RATE; - m3 += HARAKAS_RATE; + haraka512_perm_x4(s, s, ctx); + mlen -= r; + m0 += r; + m1 += r; + m2 += r; + m3 += r; } - for (i = 0; i < HARAKAS_RATE; ++i) { + for (i = 0; i < r; ++i) { t0[i] = 0; t1[i] = 0; t2[i] = 0; @@ -218,10 +208,10 @@ static void haraka_S_absorb4x(unsigned char *s, t2[i] = p; t3[i] = p; - t0[HARAKAS_RATE - 1] |= 128; - t1[HARAKAS_RATE - 1] |= 128; - t2[HARAKAS_RATE - 1] |= 128; - t3[HARAKAS_RATE - 1] |= 128; + t0[r - 1] |= 128; + t1[r - 1] |= 128; + t2[r - 1] |= 128; + t3[r - 1] |= 128; STORE(s, XOR128(LOAD(s), LOAD(t0))); STORE(s + 16, XOR128(LOAD(s + 16), LOAD(t0 + 16))); @@ -234,9 +224,10 @@ static void haraka_S_absorb4x(unsigned char *s, } static void haraka_S_squeezeblocks(unsigned char *h, unsigned long long nblocks, - unsigned char *s, unsigned int r, const harakactx *state) { + unsigned char *s, unsigned int r, + const spx_ctx *ctx) { while (nblocks > 0) { - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_haraka512_perm(s, s, state); + haraka512_perm(s, s, ctx); STORE(h, LOAD(s)); STORE(h + 16, LOAD(s + 16)); h += r; @@ -251,9 +242,9 @@ static void haraka_S_squeezeblocks4x(unsigned char *h0, unsigned long long nblocks, unsigned char *s, unsigned int r, - const harakactx *state) { + const spx_ctx *ctx) { while (nblocks > 0) { - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_haraka512_perm_x4(s, s, state); + haraka512_perm_x4(s, s, ctx); STORE(h0, LOAD(s)); STORE(h0 + 16, LOAD(s + 16)); STORE(h1, LOAD(s + 64)); @@ -270,7 +261,7 @@ static void haraka_S_squeezeblocks4x(unsigned char *h0, } } -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_haraka_S_inc_init(uint8_t *s_inc) { +void haraka_S_inc_init(uint8_t *s_inc) { size_t i; for (i = 0; i < 64; i++) { @@ -279,7 +270,8 @@ void PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_haraka_S_inc_init(uint8_t *s_inc) { s_inc[64] = 0; } -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, const harakactx *state) { +void haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, + const spx_ctx *ctx) { size_t i; /* Recall that s_inc[64] is the non-absorbed bytes xored into the state */ @@ -293,16 +285,16 @@ void PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_haraka_S_inc_absorb(uint8_t *s_inc, c m += HARAKAS_RATE - s_inc[64]; s_inc[64] = 0; - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_haraka512_perm(s_inc, s_inc, state); + haraka512_perm(s_inc, s_inc, ctx); } for (i = 0; i < mlen; i++) { s_inc[s_inc[64] + i] ^= m[i]; } - s_inc[64] = (uint8_t)(s_inc[64] + mlen); + s_inc[64] += (uint8_t)mlen; } -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_haraka_S_inc_finalize(uint8_t *s_inc) { +void haraka_S_inc_finalize(uint8_t *s_inc) { /* After haraka_S_inc_absorb, we are guaranteed that s_inc[64] < HARAKAS_RATE, so we can always use one more byte for p in the current state. */ s_inc[s_inc[64]] ^= 0x1F; @@ -310,22 +302,23 @@ void PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_haraka_S_inc_finalize(uint8_t *s_inc) s_inc[64] = 0; } -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, const harakactx *state) { +void haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, + const spx_ctx *ctx) { size_t i; /* First consume any bytes we still have sitting around */ for (i = 0; i < outlen && i < s_inc[64]; i++) { /* There are s_inc[64] bytes left, so r - s_inc[64] is the first available byte. We consume from there, i.e., up to r. */ - out[i] = (uint8_t)s_inc[(HARAKAS_RATE - s_inc[64] + (uint8_t)i)]; + out[i] = (uint8_t)s_inc[(HARAKAS_RATE - s_inc[64] + i)]; } out += i; outlen -= i; - s_inc[64] = (uint8_t)(s_inc[64] - i); + s_inc[64] -= (uint8_t)i; /* Then squeeze the remaining necessary blocks */ while (outlen > 0) { - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_haraka512_perm(s_inc, s_inc, state); + haraka512_perm(s_inc, s_inc, ctx); for (i = 0; i < outlen && i < HARAKAS_RATE; i++) { out[i] = s_inc[i]; @@ -336,8 +329,9 @@ void PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_haraka_S_inc_squeeze(uint8_t *out, si } } -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_haraka_S(unsigned char *out, unsigned long long outlen, - const unsigned char *in, unsigned long long inlen, const harakactx *state) { +void haraka_S(unsigned char *out, unsigned long long outlen, + const unsigned char *in, unsigned long long inlen, + const spx_ctx *ctx) { unsigned long long i; unsigned char s[64]; unsigned char d[32]; @@ -345,30 +339,30 @@ void PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_haraka_S(unsigned char *out, unsigned for (i = 0; i < 64; i++) { s[i] = 0; } - haraka_S_absorb(s, in, inlen, 0x1F, state); + haraka_S_absorb(s, HARAKAS_RATE, in, inlen, 0x1F, ctx); - haraka_S_squeezeblocks(out, outlen / HARAKAS_RATE, s, HARAKAS_RATE, state); + haraka_S_squeezeblocks(out, outlen / HARAKAS_RATE, s, HARAKAS_RATE, ctx); out += (outlen / HARAKAS_RATE) * HARAKAS_RATE; if (outlen % HARAKAS_RATE) { - haraka_S_squeezeblocks(d, 1, s, HARAKAS_RATE, state); + haraka_S_squeezeblocks(d, 1, s, HARAKAS_RATE, ctx); for (i = 0; i < outlen % HARAKAS_RATE; i++) { out[i] = d[i]; } } } -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_haraka_Sx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned long long outlen, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - unsigned long long inlen, - const harakactx *state) { +void haraka_Sx4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned long long outlen, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + unsigned long long inlen, + const spx_ctx *ctx) { unsigned long long i; unsigned char s[64 * 4]; unsigned char d0[32]; @@ -379,16 +373,17 @@ void PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_haraka_Sx4(unsigned char *out0, for (i = 0; i < 64 * 4; i++) { s[i] = 0; } - haraka_S_absorb4x(s, in0, in1, in2, in3, inlen, 0x1F, state); + haraka_S_absorb4x(s, HARAKAS_RATE, in0, in1, in2, in3, inlen, 0x1F, ctx); - haraka_S_squeezeblocks4x(out0, out1, out2, out3, outlen / HARAKAS_RATE, s, HARAKAS_RATE, state); + haraka_S_squeezeblocks4x(out0, out1, out2, out3, outlen / HARAKAS_RATE, s, + HARAKAS_RATE, ctx); out0 += (outlen / HARAKAS_RATE) * HARAKAS_RATE; out1 += (outlen / HARAKAS_RATE) * HARAKAS_RATE; out2 += (outlen / HARAKAS_RATE) * HARAKAS_RATE; out3 += (outlen / HARAKAS_RATE) * HARAKAS_RATE; if (outlen % HARAKAS_RATE) { - haraka_S_squeezeblocks4x(d0, d1, d2, d3, 1, s, HARAKAS_RATE, state); + haraka_S_squeezeblocks4x(d0, d1, d2, d3, 1, s, HARAKAS_RATE, ctx); for (i = 0; i < outlen % HARAKAS_RATE; i++) { out0[i] = d0[i]; out1[i] = d1[i]; @@ -398,7 +393,8 @@ void PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_haraka_Sx4(unsigned char *out0, } } -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_haraka512_perm(unsigned char *out, const unsigned char *in, const harakactx *state) { +void haraka512_perm(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx) { u128 s[4], tmp; s[0] = LOAD(in); @@ -406,19 +402,19 @@ void PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_haraka512_perm(unsigned char *out, co s[2] = LOAD(in + 32); s[3] = LOAD(in + 48); - AES4(s[0], s[1], s[2], s[3], state->rc); + AES4(s[0], s[1], s[2], s[3], ctx->rc); MIX4(s[0], s[1], s[2], s[3]); - AES4(s[0], s[1], s[2], s[3], state->rc + 8); + AES4(s[0], s[1], s[2], s[3], ctx->rc + 8); MIX4(s[0], s[1], s[2], s[3]); - AES4(s[0], s[1], s[2], s[3], state->rc + 16); + AES4(s[0], s[1], s[2], s[3], ctx->rc + 16); MIX4(s[0], s[1], s[2], s[3]); - AES4(s[0], s[1], s[2], s[3], state->rc + 24); + AES4(s[0], s[1], s[2], s[3], ctx->rc + 24); MIX4(s[0], s[1], s[2], s[3]); - AES4(s[0], s[1], s[2], s[3], state->rc + 32); + AES4(s[0], s[1], s[2], s[3], ctx->rc + 32); MIX4(s[0], s[1], s[2], s[3]); STORE(out, s[0]); @@ -427,7 +423,8 @@ void PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_haraka512_perm(unsigned char *out, co STORE(out + 48, s[3]); } -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_haraka512_perm_x4(unsigned char *out, const unsigned char *in, const harakactx *state) { +void haraka512_perm_x4(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx) { u128 s[4][4], tmp; s[0][0] = LOAD(in); @@ -447,31 +444,31 @@ void PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_haraka512_perm_x4(unsigned char *out, s[3][2] = LOAD(in + 224); s[3][3] = LOAD(in + 240); - AES4_4x(s[0], s[1], s[2], s[3], state->rc); + AES4_4x(s[0], s[1], s[2], s[3], ctx->rc); MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - AES4_4x(s[0], s[1], s[2], s[3], state->rc + 8); + AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 8); MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - AES4_4x(s[0], s[1], s[2], s[3], state->rc + 16); + AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 16); MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - AES4_4x(s[0], s[1], s[2], s[3], state->rc + 24); + AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 24); MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - AES4_4x(s[0], s[1], s[2], s[3], state->rc + 32); + AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 32); MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); @@ -495,7 +492,8 @@ void PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_haraka512_perm_x4(unsigned char *out, STORE(out + 240, s[3][3]); } -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_haraka512(unsigned char *out, const unsigned char *in, const harakactx *state) { +void haraka512(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx) { u128 s[4], tmp; s[0] = LOAD(in); @@ -503,19 +501,19 @@ void PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_haraka512(unsigned char *out, const u s[2] = LOAD(in + 32); s[3] = LOAD(in + 48); - AES4(s[0], s[1], s[2], s[3], state->rc); + AES4(s[0], s[1], s[2], s[3], ctx->rc); MIX4(s[0], s[1], s[2], s[3]); - AES4(s[0], s[1], s[2], s[3], state->rc + 8); + AES4(s[0], s[1], s[2], s[3], ctx->rc + 8); MIX4(s[0], s[1], s[2], s[3]); - AES4(s[0], s[1], s[2], s[3], state->rc + 16); + AES4(s[0], s[1], s[2], s[3], ctx->rc + 16); MIX4(s[0], s[1], s[2], s[3]); - AES4(s[0], s[1], s[2], s[3], state->rc + 24); + AES4(s[0], s[1], s[2], s[3], ctx->rc + 24); MIX4(s[0], s[1], s[2], s[3]); - AES4(s[0], s[1], s[2], s[3], state->rc + 32); + AES4(s[0], s[1], s[2], s[3], ctx->rc + 32); MIX4(s[0], s[1], s[2], s[3]); s[0] = XOR128(s[0], LOAD(in)); @@ -527,7 +525,8 @@ void PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_haraka512(unsigned char *out, const u TRUNCSTORE(out, s[0], s[1], s[2], s[3]); } -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_haraka512x4(unsigned char *out, const unsigned char *in, const harakactx *state) { +void haraka512x4(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx) { u128 s[4][4], tmp; s[0][0] = LOAD(in); @@ -547,31 +546,31 @@ void PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_haraka512x4(unsigned char *out, const s[3][2] = LOAD(in + 224); s[3][3] = LOAD(in + 240); - AES4_4x(s[0], s[1], s[2], s[3], state->rc); + AES4_4x(s[0], s[1], s[2], s[3], ctx->rc); MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - AES4_4x(s[0], s[1], s[2], s[3], state->rc + 8); + AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 8); MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - AES4_4x(s[0], s[1], s[2], s[3], state->rc + 16); + AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 16); MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - AES4_4x(s[0], s[1], s[2], s[3], state->rc + 24); + AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 24); MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - AES4_4x(s[0], s[1], s[2], s[3], state->rc + 32); + AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 32); MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); @@ -600,25 +599,26 @@ void PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_haraka512x4(unsigned char *out, const TRUNCSTORE((out + 96), s[3][0], s[3][1], s[3][2], s[3][3]); } -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_haraka256(unsigned char *out, const unsigned char *in, const harakactx *state) { +void haraka256(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx) { u128 s[2], tmp; s[0] = LOAD(in); s[1] = LOAD(in + 16); - AES2(s[0], s[1], state->rc); + AES2(s[0], s[1], ctx->rc); MIX2(s[0], s[1]); - AES2(s[0], s[1], state->rc + 4); + AES2(s[0], s[1], ctx->rc + 4); MIX2(s[0], s[1]); - AES2(s[0], s[1], state->rc + 8); + AES2(s[0], s[1], ctx->rc + 8); MIX2(s[0], s[1]); - AES2(s[0], s[1], state->rc + 12); + AES2(s[0], s[1], ctx->rc + 12); MIX2(s[0], s[1]); - AES2(s[0], s[1], state->rc + 16); + AES2(s[0], s[1], ctx->rc + 16); MIX2(s[0], s[1]); s[0] = XOR128(s[0], LOAD(in)); @@ -628,7 +628,8 @@ void PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_haraka256(unsigned char *out, const u STORE(out + 16, s[1]); } -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_haraka256x4(unsigned char *out, const unsigned char *in, const harakactx *state) { +void haraka256x4(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx) { u128 s[4][2], tmp; s[0][0] = LOAD(in); @@ -641,7 +642,7 @@ void PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_haraka256x4(unsigned char *out, const s[3][1] = LOAD(in + 112); // Round 1 - AES2_4x(s[0], s[1], s[2], s[3], state->rc); + AES2_4x(s[0], s[1], s[2], s[3], ctx->rc); MIX2(s[0][0], s[0][1]); MIX2(s[1][0], s[1][1]); @@ -649,7 +650,7 @@ void PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_haraka256x4(unsigned char *out, const MIX2(s[3][0], s[3][1]); // Round 2 - AES2_4x(s[0], s[1], s[2], s[3], state->rc + 4); + AES2_4x(s[0], s[1], s[2], s[3], ctx->rc + 4); MIX2(s[0][0], s[0][1]); MIX2(s[1][0], s[1][1]); @@ -657,7 +658,7 @@ void PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_haraka256x4(unsigned char *out, const MIX2(s[3][0], s[3][1]); // Round 3 - AES2_4x(s[0], s[1], s[2], s[3], state->rc + 8); + AES2_4x(s[0], s[1], s[2], s[3], ctx->rc + 8); MIX2(s[0][0], s[0][1]); MIX2(s[1][0], s[1][1]); @@ -665,7 +666,7 @@ void PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_haraka256x4(unsigned char *out, const MIX2(s[3][0], s[3][1]); // Round 4 - AES2_4x(s[0], s[1], s[2], s[3], state->rc + 12); + AES2_4x(s[0], s[1], s[2], s[3], ctx->rc + 12); MIX2(s[0][0], s[0][1]); MIX2(s[1][0], s[1][1]); @@ -673,7 +674,7 @@ void PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_haraka256x4(unsigned char *out, const MIX2(s[3][0], s[3][1]); // Round 5 - AES2_4x(s[0], s[1], s[2], s[3], state->rc + 16); + AES2_4x(s[0], s[1], s[2], s[3], ctx->rc + 16); MIX2(s[0][0], s[0][1]); MIX2(s[1][0], s[1][1]); @@ -699,103 +700,3 @@ void PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_haraka256x4(unsigned char *out, const STORE(out + 96, s[3][0]); STORE(out + 112, s[3][1]); } - -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_haraka256_sk(unsigned char *out, const unsigned char *in, const harakactx *state) { - u128 s[2], tmp; - - s[0] = LOAD(in); - s[1] = LOAD(in + 16); - - AES2(s[0], s[1], state->rc_sseed); - MIX2(s[0], s[1]); - - AES2(s[0], s[1], state->rc_sseed + 4); - MIX2(s[0], s[1]); - - AES2(s[0], s[1], state->rc_sseed + 8); - MIX2(s[0], s[1]); - - AES2(s[0], s[1], state->rc_sseed + 12); - MIX2(s[0], s[1]); - - AES2(s[0], s[1], state->rc_sseed + 16); - MIX2(s[0], s[1]); - - s[0] = XOR128(s[0], LOAD(in)); - s[1] = XOR128(s[1], LOAD(in + 16)); - - STORE(out, s[0]); - STORE(out + 16, s[1]); -} - -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_haraka256_skx4(unsigned char *out, const unsigned char *in, const harakactx *state) { - u128 s[4][2], tmp; - - s[0][0] = LOAD(in); - s[0][1] = LOAD(in + 16); - s[1][0] = LOAD(in + 32); - s[1][1] = LOAD(in + 48); - s[2][0] = LOAD(in + 64); - s[2][1] = LOAD(in + 80); - s[3][0] = LOAD(in + 96); - s[3][1] = LOAD(in + 112); - - // Round 1 - AES2_4x(s[0], s[1], s[2], s[3], state->rc_sseed); - - MIX2(s[0][0], s[0][1]); - MIX2(s[1][0], s[1][1]); - MIX2(s[2][0], s[2][1]); - MIX2(s[3][0], s[3][1]); - - // Round 2 - AES2_4x(s[0], s[1], s[2], s[3], state->rc_sseed + 4); - - MIX2(s[0][0], s[0][1]); - MIX2(s[1][0], s[1][1]); - MIX2(s[2][0], s[2][1]); - MIX2(s[3][0], s[3][1]); - - // Round 3 - AES2_4x(s[0], s[1], s[2], s[3], state->rc_sseed + 8); - - MIX2(s[0][0], s[0][1]); - MIX2(s[1][0], s[1][1]); - MIX2(s[2][0], s[2][1]); - MIX2(s[3][0], s[3][1]); - - // Round 4 - AES2_4x(s[0], s[1], s[2], s[3], state->rc_sseed + 12); - - MIX2(s[0][0], s[0][1]); - MIX2(s[1][0], s[1][1]); - MIX2(s[2][0], s[2][1]); - MIX2(s[3][0], s[3][1]); - - // Round 5 - AES2_4x(s[0], s[1], s[2], s[3], state->rc_sseed + 16); - - MIX2(s[0][0], s[0][1]); - MIX2(s[1][0], s[1][1]); - MIX2(s[2][0], s[2][1]); - MIX2(s[3][0], s[3][1]); - - // Feed Forward - s[0][0] = XOR128(s[0][0], LOAD(in)); - s[0][1] = XOR128(s[0][1], LOAD(in + 16)); - s[1][0] = XOR128(s[1][0], LOAD(in + 32)); - s[1][1] = XOR128(s[1][1], LOAD(in + 48)); - s[2][0] = XOR128(s[2][0], LOAD(in + 64)); - s[2][1] = XOR128(s[2][1], LOAD(in + 80)); - s[3][0] = XOR128(s[3][0], LOAD(in + 96)); - s[3][1] = XOR128(s[3][1], LOAD(in + 112)); - - STORE(out, s[0][0]); - STORE(out + 16, s[0][1]); - STORE(out + 32, s[1][0]); - STORE(out + 48, s[1][1]); - STORE(out + 64, s[2][0]); - STORE(out + 80, s[2][1]); - STORE(out + 96, s[3][0]); - STORE(out + 112, s[3][1]); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/haraka.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/haraka.h index 147f179b25..737cb6065f 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/haraka.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/haraka.h @@ -1,57 +1,42 @@ -#ifndef PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_HARAKA_H -#define PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_HARAKA_H +#ifndef SPX_HARAKA_H +#define SPX_HARAKA_H -#include -#include -#include - -typedef struct { - __m128i rc[40]; - __m128i rc_sseed[40]; -} harakactx; +#include "context.h" +#include "params.h" /* Tweak constants with seed */ -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_tweak_constants( - harakactx *state, - const unsigned char *pk_seed, const unsigned char *sk_seed, - unsigned long long seed_length); +#define tweak_constants SPX_NAMESPACE(tweak_constants) +void tweak_constants(spx_ctx *ctx); /* Haraka Sponge */ -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_haraka_S_inc_init(uint8_t *s_inc); -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, const harakactx *state); -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_haraka_S_inc_finalize(uint8_t *s_inc); -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, const harakactx *state); -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_haraka_S( - unsigned char *out, unsigned long long outlen, - const unsigned char *in, unsigned long long inlen, const harakactx *state); -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_haraka_Sx4( - unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned long long outlen, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - unsigned long long inlen, - const harakactx *state); - +#define haraka_S_inc_init SPX_NAMESPACE(haraka_S_inc_init) +void haraka_S_inc_init(uint8_t *s_inc); +#define haraka_S_inc_absorb SPX_NAMESPACE(haraka_S_inc_absorb) +void haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, + const spx_ctx *ctx); +#define haraka_S_inc_finalize SPX_NAMESPACE(haraka_S_inc_finalize) +void haraka_S_inc_finalize(uint8_t *s_inc); +#define haraka_S_inc_squeeze SPX_NAMESPACE(haraka_S_inc_squeeze) +void haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, + const spx_ctx *ctx); +#define haraka_S SPX_NAMESPACE(haraka_S) +void haraka_S(unsigned char *out, unsigned long long outlen, + const unsigned char *in, unsigned long long inlen, + const spx_ctx *ctx); /* Applies the 512-bit Haraka permutation to in. */ -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_haraka512_perm(unsigned char *out, const unsigned char *in, const harakactx *state); -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_haraka512_perm_x4(unsigned char *out, const unsigned char *in, const harakactx *state); +#define haraka512_perm SPX_NAMESPACE(haraka512_perm) +void haraka512_perm(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx); /* Implementation of Haraka-512 */ -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_haraka512(unsigned char *out, const unsigned char *in, const harakactx *state); -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_haraka512x4(unsigned char *out, const unsigned char *in, const harakactx *state); +#define haraka512 SPX_NAMESPACE(haraka512) +void haraka512(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx); /* Implementation of Haraka-256 */ -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_haraka256(unsigned char *out, const unsigned char *in, const harakactx *state); -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_haraka256x4(unsigned char *out, const unsigned char *in, const harakactx *state); - -/* Implementation of Haraka-256 using sk.seed constants */ -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_haraka256_sk(unsigned char *out, const unsigned char *in, const harakactx *state); -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_haraka256_skx4(unsigned char *out, const unsigned char *in, const harakactx *state); +#define haraka256 SPX_NAMESPACE(haraka256) +void haraka256(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/haraka_offsets.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/haraka_offsets.h new file mode 100644 index 0000000000..7c062272a0 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/haraka_offsets.h @@ -0,0 +1,21 @@ +#ifndef HARAKA_OFFSETS_H_ +#define HARAKA_OFFSETS_H_ + +/* + * Offsets of various fields in the address structure when we use Haraka as + * the Sphincs+ hash function + */ + +#define SPX_OFFSET_LAYER 3 /* The byte used to specify the Merkle tree layer */ +#define SPX_OFFSET_TREE 8 /* The start of the 8 byte field used to specify the tree */ +#define SPX_OFFSET_TYPE 19 /* The byte used to specify the hash type (reason) */ +#define SPX_OFFSET_KP_ADDR2 22 /* The high byte used to specify the key pair (which one-time signature) */ +#define SPX_OFFSET_KP_ADDR1 23 /* The low byte used to specify the key pair */ +#define SPX_OFFSET_CHAIN_ADDR 27 /* The byte used to specify the chain address (which Winternitz chain) */ +#define SPX_OFFSET_HASH_ADDR 31 /* The byte used to specify the hash address (where in the Winternitz chain) */ +#define SPX_OFFSET_TREE_HGT 27 /* The byte used to specify the height of this node in the FORS or Merkle tree */ +#define SPX_OFFSET_TREE_INDEX 28 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ + +#define SPX_HARAKA 1 + +#endif /* HARAKA_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/harakax4.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/harakax4.h new file mode 100644 index 0000000000..eadc69aa48 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/harakax4.h @@ -0,0 +1,36 @@ +#ifndef SPX_HARAKAX4_H +#define SPX_HARAKAX4_H + +#include "context.h" +#include "params.h" + +/* Haraka Sponge */ +#define haraka_Sx4 SPX_NAMESPACE(haraka_Sx4) +void haraka_Sx4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned long long outlen, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + unsigned long long inlen, + const spx_ctx *ctx); + +/* Applies the 512-bit Haraka permutation x4 to in. */ +#define haraka512_perm_x4 SPX_NAMESPACE(haraka512_perm_x4) +void haraka512_perm_x4(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx); + +/* Implementation of Haraka-512 x4*/ +#define haraka512x4 SPX_NAMESPACE(haraka512x4) +void haraka512x4(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx); + +/* Implementation of Haraka-256 x4 */ +#define haraka256x4 SPX_NAMESPACE(haraka256x4) +void haraka256x4(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/hash.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/hash.h index 0baa004d69..f7c87d4c3c 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/hash.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/hash.h @@ -1,31 +1,28 @@ -#ifndef PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_HASH_H -#define PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_HASH_H - -#include "hash_state.h" +#ifndef SPX_HASH_H +#define SPX_HASH_H #include #include -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_initialize_hash_function( - hash_state *hash_state_seeded, - const unsigned char *pub_seed, const unsigned char *sk_seed); +#include "context.h" +#include "params.h" + +#define prf_addr SPX_NAMESPACE(prf_addr) +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]); -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_destroy_hash_function(hash_state *hash_state_seeded); +#define gen_message_random SPX_NAMESPACE(gen_message_random) +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded); +#define hash_message SPX_NAMESPACE(hash_message) +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/hash_haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/hash_haraka.c index 3a86f12be3..750a67423b 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/hash_haraka.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/hash_haraka.c @@ -2,58 +2,44 @@ #include #include "address.h" -#include "haraka.h" -#include "hash.h" #include "params.h" #include "utils.h" -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_initialize_hash_function( - hash_state *hash_state_seeded, - const unsigned char *pub_seed, const unsigned char *sk_seed) { - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_tweak_constants(hash_state_seeded, pub_seed, sk_seed, PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N); -} - -/* The haraka implementation is stack based and won't be replaced in PQClean/OQS, - so we don't need to do anything */ -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_destroy_hash_function( - hash_state *hash_state_seeded) { // NOLINT(readability-non-const-parameter) - (void)hash_state_seeded; -} +#include "haraka.h" +#include "hash.h" /* - * Computes PRF(key, addr), given a secret key of PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N bytes and an address + * Computes PRF(key, addr), given a secret key of SPX_N bytes and an address */ -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded) { - unsigned char buf[PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_ADDR_BYTES]; - /* Since PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N may be smaller than 32, we need a temporary buffer. */ +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]) { + /* Since SPX_N may be smaller than 32, we need temporary buffers. */ unsigned char outbuf[32]; + unsigned char buf[64] = {0}; - (void)key; /* Suppress an 'unused parameter' warning. */ + memcpy(buf, addr, SPX_ADDR_BYTES); + memcpy(buf + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_addr_to_bytes(buf, addr); - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_haraka256_sk(outbuf, buf, hash_state_seeded); - memcpy(out, outbuf, PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N); + haraka512(outbuf, (const void *)buf, ctx); + memcpy(out, outbuf, SPX_N); } /** * Computes the message-dependent randomness R, using a secret seed and an * optional randomization value as well as the message. */ -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded) { +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { uint8_t s_inc[65]; - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_haraka_S_inc_init(s_inc); - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_haraka_S_inc_absorb(s_inc, sk_prf, PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_haraka_S_inc_absorb(s_inc, optrand, PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_haraka_S_inc_absorb(s_inc, m, mlen, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_haraka_S_inc_finalize(s_inc); - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_haraka_S_inc_squeeze(R, PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N, s_inc, hash_state_seeded); + haraka_S_inc_init(s_inc); + haraka_S_inc_absorb(s_inc, sk_prf, SPX_N, ctx); + haraka_S_inc_absorb(s_inc, optrand, SPX_N, ctx); + haraka_S_inc_absorb(s_inc, m, mlen, ctx); + haraka_S_inc_finalize(s_inc); + haraka_S_inc_squeeze(R, SPX_N, s_inc, ctx); } /** @@ -61,36 +47,35 @@ void PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_gen_message_random( * Outputs the message digest and the index of the leaf. The index is split in * the tree index and the leaf index, for convenient copying to an address. */ -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded) { -#define PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_TREE_BITS (PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_TREE_HEIGHT * (PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_D - 1)) -#define PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_TREE_BYTES ((PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_TREE_BITS + 7) / 8) -#define PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_LEAF_BITS PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_TREE_HEIGHT -#define PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_LEAF_BYTES ((PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_LEAF_BITS + 7) / 8) -#define PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_DGST_BYTES (PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_FORS_MSG_BYTES + PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_TREE_BYTES + PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_LEAF_BYTES) +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { +#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) +#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) +#define SPX_LEAF_BITS SPX_TREE_HEIGHT +#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) +#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) - unsigned char buf[PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_DGST_BYTES]; + unsigned char buf[SPX_DGST_BYTES]; unsigned char *bufp = buf; uint8_t s_inc[65]; - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_haraka_S_inc_init(s_inc); - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_haraka_S_inc_absorb(s_inc, R, PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_haraka_S_inc_absorb(s_inc, pk + PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N, PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_haraka_S_inc_absorb(s_inc, m, mlen, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_haraka_S_inc_finalize(s_inc); - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_haraka_S_inc_squeeze(buf, PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_DGST_BYTES, s_inc, hash_state_seeded); + haraka_S_inc_init(s_inc); + haraka_S_inc_absorb(s_inc, R, SPX_N, ctx); + haraka_S_inc_absorb(s_inc, pk + SPX_N, SPX_N, ctx); // Only absorb root part of pk + haraka_S_inc_absorb(s_inc, m, mlen, ctx); + haraka_S_inc_finalize(s_inc); + haraka_S_inc_squeeze(buf, SPX_DGST_BYTES, s_inc, ctx); + + memcpy(digest, bufp, SPX_FORS_MSG_BYTES); + bufp += SPX_FORS_MSG_BYTES; - memcpy(digest, bufp, PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_FORS_MSG_BYTES); - bufp += PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_FORS_MSG_BYTES; - *tree = PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_bytes_to_ull(bufp, PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_TREE_BYTES); - *tree &= (~(uint64_t)0) >> (64 - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_TREE_BITS); - bufp += PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_TREE_BYTES; + *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); + *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); + bufp += SPX_TREE_BYTES; - *leaf_idx = (uint32_t)PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_bytes_to_ull( - bufp, PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_LEAF_BYTES); - *leaf_idx &= (~(uint32_t)0) >> (32 - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_LEAF_BITS); + *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); + *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/hash_harakax4.c b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/hash_harakax4.c index 2a938ad2da..cfa5162d79 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/hash_harakax4.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/hash_harakax4.c @@ -2,36 +2,34 @@ #include #include "address.h" -#include "haraka.h" -#include "hash_state.h" +#include "harakax4.h" #include "hashx4.h" #include "params.h" /* * 4-way parallel version of prf_addr; takes 4x as much input and output */ -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_prf_addrx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const unsigned char *key, - const uint32_t addrx4[4 * 8], - const hash_state *state_seeded) { - unsigned char bufx4[4 * PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_ADDR_BYTES]; - /* Since PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N may be smaller than 32, we need a temporary buffer. */ +#define prf_addrx4 SPX_NAMESPACE(prf_addrx4) +void prf_addrx4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const spx_ctx *ctx, + const uint32_t addrx4[4 * 8]) { + unsigned char bufx4[4 * 64] = {0}; + /* Since SPX_N may be smaller than 32, we need temporary buffers. */ unsigned char outbuf[4 * 32]; unsigned int i; - (void)key; /* Suppress an 'unused parameter' warning. */ - for (i = 0; i < 4; i++) { - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_addr_to_bytes(bufx4 + i * PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_ADDR_BYTES, addrx4 + i * 8); + memcpy(bufx4 + i * 64, addrx4 + i * 8, SPX_ADDR_BYTES); + memcpy(bufx4 + i * 64 + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); } - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_haraka256_skx4(outbuf, bufx4, state_seeded); + haraka512x4(outbuf, bufx4, ctx); - memcpy(out0, outbuf, PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N); - memcpy(out1, outbuf + 32, PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N); - memcpy(out2, outbuf + 64, PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N); - memcpy(out3, outbuf + 96, PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N); + memcpy(out0, outbuf, SPX_N); + memcpy(out1, outbuf + 32, SPX_N); + memcpy(out2, outbuf + 64, SPX_N); + memcpy(out3, outbuf + 96, SPX_N); } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/hash_state.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/hash_state.h deleted file mode 100644 index a61180ae5c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/hash_state.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_HASH_STATE_H -#define PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_HASH_STATE_H - -/** - * Defines the type of the hash function state. - * - * Don't be fooled into thinking this instance of SPHINCS+ isn't stateless! - * - * From Section 7.2.2 from the SPHINCS+ round-2 specification: - * - * Each of the instances of the tweakable hash function take PK.seed as its - * first input, which is constant for a given key pair – and, thus, across - * a single signature. This leads to a lot of redundant computation. To remedy - * this, we pad PK.seed to the length of a full 64-byte SHA-256 input block. - * Because of the Merkle-DamgÃ¥rd construction that underlies SHA-256, this - * allows for reuse of the intermediate SHA-256 state after the initial call to - * the compression function which improves performance. - * - * We pass this hash state around in functions, because otherwise we need to - * have a global variable. - */ - -#include "haraka.h" -#define hash_state harakactx - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/hashx4.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/hashx4.h index aaf73a5739..3751a0ebd0 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/hashx4.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/hashx4.h @@ -1,16 +1,17 @@ -#ifndef PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_HASHX4_H -#define PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_HASHX4_H +#ifndef SPX_HASHX4_H +#define SPX_HASHX4_H #include -#include "hash_state.h" +#include "context.h" +#include "params.h" -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_prf_addrx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const unsigned char *key, - const uint32_t addrx4[4 * 8], - const hash_state *state_seeded); +#define prf_addrx4 SPX_NAMESPACE(prf_addrx4) +void prf_addrx4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const spx_ctx *ctx, + const uint32_t addrx4[4 * 8]); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/merkle.c b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/merkle.c new file mode 100644 index 0000000000..f57811c1ac --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/merkle.c @@ -0,0 +1,64 @@ +#include +#include + +#include "merkle.h" + +#include "address.h" +#include "params.h" +#include "utils.h" +#include "utilsx4.h" +#include "wots.h" +#include "wotsx4.h" + +/* + * This generates a Merkle signature (WOTS signature followed by the Merkle + * authentication path). + */ +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf) { + unsigned char *auth_path = sig + SPX_WOTS_BYTES; + uint32_t tree_addrx4[4 * 8] = { 0 }; + int j; + struct leaf_info_x4 info = { 0 }; + unsigned steps[ SPX_WOTS_LEN ]; + + info.wots_sig = sig; + chain_lengths(steps, root); + info.wots_steps = steps; + + for (j = 0; j < 4; j++) { + set_type(&tree_addrx4[8 * j], SPX_ADDR_TYPE_HASHTREE); + set_type(&info.leaf_addr[8 * j], SPX_ADDR_TYPE_WOTS); + set_type(&info.pk_addr[8 * j], SPX_ADDR_TYPE_WOTSPK); + copy_subtree_addr(&tree_addrx4[8 * j], tree_addr); + copy_subtree_addr(&info.leaf_addr[8 * j], wots_addr); + copy_subtree_addr(&info.pk_addr[8 * j], wots_addr); + } + + info.wots_sign_leaf = idx_leaf; + + treehashx4(root, auth_path, ctx, + idx_leaf, 0, + SPX_TREE_HEIGHT, + wots_gen_leafx4, + tree_addrx4, &info); +} + +/* Compute root node of the top-most subtree. */ +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { + /* We do not need the auth path in key generation, but it simplifies the + code to have just one treehash routine that computes both root and path + in one function. */ + unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; + uint32_t top_tree_addr[8] = {0}; + uint32_t wots_addr[8] = {0}; + + set_layer_addr(top_tree_addr, SPX_D - 1); + set_layer_addr(wots_addr, SPX_D - 1); + + merkle_sign(auth_path, root, ctx, + wots_addr, top_tree_addr, + ~0U /* ~0 means "don't bother generating an auth path */ ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/merkle.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/merkle.h new file mode 100644 index 0000000000..769cf2e970 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/merkle.h @@ -0,0 +1,21 @@ +#ifndef MERKLE_H_ +#define MERKLE_H_ + +#include + +#include "context.h" +#include "params.h" + +/* Generate a Merkle signature (WOTS signature followed by the Merkle */ +/* authentication path) */ +#define merkle_sign SPX_NAMESPACE(merkle_sign) +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf); + +/* Compute the root node of the top-most subtree. */ +#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); + +#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/nistapi.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/nistapi.h new file mode 100644 index 0000000000..3cb71afad4 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/nistapi.h @@ -0,0 +1,87 @@ +#ifndef SPX_API_H +#define SPX_API_H + +#include +#include + +#include "params.h" + +#define CRYPTO_ALGNAME "SPHINCS+" + +#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES +#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES +#define CRYPTO_BYTES SPX_BYTES +#define CRYPTO_SEEDBYTES (3*SPX_N) + +/* + * Returns the length of a secret key, in bytes + */ +#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) +size_t crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) +size_t crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) +size_t crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) +size_t crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +#define crypto_sign SPX_NAMESPACE(crypto_sign) +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/params.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/params.h index c64f0330e0..21cd543162 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/params.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/params.h @@ -1,53 +1,56 @@ -#ifndef PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_PARAMS_H -#define PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_PARAMS_H +#ifndef SPX_PARAMS_H +#define SPX_PARAMS_H + +#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_##s /* Hash output length in bytes. */ -#define PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N 32 +#define SPX_N 32 /* Height of the hypertree. */ -#define PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_FULL_HEIGHT 68 +#define SPX_FULL_HEIGHT 68 /* Number of subtree layer. */ -#define PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_D 17 +#define SPX_D 17 /* FORS tree dimensions. */ -#define PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_FORS_HEIGHT 9 -#define PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_FORS_TREES 35 +#define SPX_FORS_HEIGHT 9 +#define SPX_FORS_TREES 35 /* Winternitz parameter, */ -#define PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_WOTS_W 16 +#define SPX_WOTS_W 16 /* The hash function is defined by linking a different hash.c file, as opposed to setting a #define constant. */ /* For clarity */ -#define PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_ADDR_BYTES 32 +#define SPX_ADDR_BYTES 32 /* WOTS parameters. */ -#define PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_WOTS_LOGW 4 +#define SPX_WOTS_LOGW 4 -#define PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_WOTS_LEN1 (8 * PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N / PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_WOTS_LOGW) +#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) -/* PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#define PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_WOTS_LEN2 3 +/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ +#define SPX_WOTS_LEN2 3 -#define PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_WOTS_LEN (PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_WOTS_LEN1 + PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_WOTS_LEN2) -#define PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_WOTS_BYTES (PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_WOTS_LEN * PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N) -#define PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_WOTS_PK_BYTES PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_WOTS_BYTES +#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) +#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) +#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES /* Subtree size. */ -#define PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_TREE_HEIGHT (PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_FULL_HEIGHT / PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_D) +#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) + +//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT +// #error SPX_D should always divide SPX_FULL_HEIGHT +//#endif /* FORS parameters. */ -#define PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_FORS_MSG_BYTES ((PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_FORS_TREES + 7) / 8) -#define PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_FORS_BYTES ((PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_FORS_HEIGHT + 1) * PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_FORS_TREES * PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N) -#define PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_FORS_PK_BYTES PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N +#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) +#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) +#define SPX_FORS_PK_BYTES SPX_N /* Resulting SPX sizes. */ -#define PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_BYTES (PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N + PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_FORS_BYTES + PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_D * PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_WOTS_BYTES +\ - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_FULL_HEIGHT * PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N) -#define PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_PK_BYTES (2 * PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N) -#define PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_SK_BYTES (2 * PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N + PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_PK_BYTES) - -/* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ -#define PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_OPTRAND_BYTES 32 +#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ + SPX_FULL_HEIGHT * SPX_N) +#define SPX_PK_BYTES (2 * SPX_N) +#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) + +#include "haraka_offsets.h" #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/sign.c b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/sign.c index 1f31a08b33..9d0c7d1b22 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/sign.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/sign.c @@ -1,76 +1,45 @@ -#include #include #include #include #include "address.h" -#include "api.h" +#include "context.h" #include "fors.h" #include "hash.h" -#include "hash_state.h" +#include "merkle.h" +#include "nistapi.h" #include "params.h" #include "randombytes.h" #include "thash.h" #include "utils.h" #include "wots.h" - -/** - * Computes the leaf at a given address. First generates the WOTS key pair, - * then computes leaf by hashing horizontally. - */ -static void wots_gen_leaf(unsigned char *leaf, const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx, const uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - unsigned char pk[PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_WOTS_BYTES]; - uint32_t wots_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_set_type( - wots_addr, PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_set_type( - wots_pk_addr, PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_ADDR_TYPE_WOTSPK); - - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_set_keypair_addr( - wots_addr, addr_idx); - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_wots_gen_pk( - pk, sk_seed, pub_seed, wots_addr, hash_state_seeded); - - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_copy_keypair_addr( - wots_pk_addr, wots_addr); - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_thash_WOTS_LEN( - leaf, pk, pub_seed, wots_pk_addr, hash_state_seeded); -} - /* * Returns the length of a secret key, in bytes */ -size_t PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_crypto_sign_secretkeybytes(void) { - return PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_CRYPTO_SECRETKEYBYTES; +size_t crypto_sign_secretkeybytes(void) { + return CRYPTO_SECRETKEYBYTES; } /* * Returns the length of a public key, in bytes */ -size_t PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_crypto_sign_publickeybytes(void) { - return PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_CRYPTO_PUBLICKEYBYTES; +size_t crypto_sign_publickeybytes(void) { + return CRYPTO_PUBLICKEYBYTES; } /* * Returns the length of a signature, in bytes */ -size_t PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_crypto_sign_bytes(void) { - return PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_CRYPTO_BYTES; +size_t crypto_sign_bytes(void) { + return CRYPTO_BYTES; } /* * Returns the length of the seed required to generate a key pair, in bytes */ -size_t PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_crypto_sign_seedbytes(void) { - return PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_CRYPTO_SEEDBYTES; +size_t crypto_sign_seedbytes(void) { + return CRYPTO_SEEDBYTES; } /* @@ -78,35 +47,29 @@ size_t PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_crypto_sign_seedbytes(void) { * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] * Format pk: [PUB_SEED || root] */ -int PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed) { - /* We do not need the auth path in key generation, but it simplifies the - code to have just one treehash routine that computes both root and path - in one function. */ - unsigned char auth_path[PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_TREE_HEIGHT * PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N]; - uint32_t top_tree_addr[8] = {0}; - hash_state hash_state_seeded; - - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_set_layer_addr( - top_tree_addr, PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_D - 1); - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_set_type( - top_tree_addr, PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_ADDR_TYPE_HASHTREE); +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed) { + spx_ctx ctx; /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ - memcpy(sk, seed, PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_CRYPTO_SEEDBYTES); + memcpy(sk, seed, CRYPTO_SEEDBYTES); + + memcpy(pk, sk + 2 * SPX_N, SPX_N); - memcpy(pk, sk + 2 * PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N, PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N); + memcpy(ctx.pub_seed, pk, SPX_N); + memcpy(ctx.sk_seed, sk, SPX_N); /* This hook allows the hash function instantiation to do whatever preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_initialize_hash_function(&hash_state_seeded, pk, sk); + initialize_hash_function(&ctx); /* Compute root node of the top-most subtree. */ - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_treehash_TREE_HEIGHT( - sk + 3 * PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N, auth_path, sk, sk + 2 * PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N, 0, 0, - wots_gen_leaf, top_tree_addr, &hash_state_seeded); + merkle_gen_root(sk + 3 * SPX_N, &ctx); - memcpy(pk + PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N, sk + 3 * PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N, PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N); + // cleanup + free_hash_function(&ctx); + + memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); return 0; } @@ -116,31 +79,10 @@ int PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_crypto_sign_seed_keypair( * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] * Format pk: [PUB_SEED || root] */ -int PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk) { - - // guarantee alignment of pk - union { - __m128 _x[PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_CRYPTO_PUBLICKEYBYTES / 16]; - uint8_t pk[PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_CRYPTO_PUBLICKEYBYTES]; - } aligned_pk; - - // guarantee alignment of sk - union { - __m128 _x[PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_CRYPTO_SECRETKEYBYTES / 16]; - uint8_t sk[PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_CRYPTO_SECRETKEYBYTES]; - } aligned_sk; - - union { - __m128 _x[PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_CRYPTO_SEEDBYTES / 16]; - uint8_t seed[PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_CRYPTO_SEEDBYTES]; - } aligned_seed; - randombytes(aligned_seed.seed, PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_CRYPTO_SEEDBYTES); - - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_crypto_sign_seed_keypair( - aligned_pk.pk, aligned_sk.sk, aligned_seed.seed); - memcpy(pk, aligned_pk.pk, PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_CRYPTO_PUBLICKEYBYTES); - memcpy(sk, aligned_sk.sk, PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_CRYPTO_SECRETKEYBYTES); +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { + uint8_t seed[CRYPTO_SEEDBYTES]; + randombytes(seed, CRYPTO_SEEDBYTES); + crypto_sign_seed_keypair(pk, sk, seed); return 0; } @@ -148,101 +90,68 @@ int PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_crypto_sign_keypair( /** * Returns an array containing a detached signature. */ -int PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - // guarantee alignment of sk - union { - __m128 *_x; - uint8_t sk[PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_CRYPTO_SECRETKEYBYTES]; - } aligned_sk; - memcpy(aligned_sk.sk, sk, PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_CRYPTO_SECRETKEYBYTES); - sk = aligned_sk.sk; - - // guarantee alignment of sig - union { - __m128 *_x; - uint8_t sig[PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_BYTES]; - } aligned_sig; - uint8_t *orig_sig = sig; - sig = (uint8_t *)aligned_sig.sig; - - const unsigned char *sk_seed = sk; - const unsigned char *sk_prf = sk + PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N; - const unsigned char *pk = sk + 2 * PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N; - const unsigned char *pub_seed = pk; - - unsigned char optrand[PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N]; - unsigned char mhash[PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_FORS_MSG_BYTES]; - unsigned char root[PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N]; +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk) { + spx_ctx ctx; + + const uint8_t *sk_prf = sk + SPX_N; + const uint8_t *pk = sk + 2 * SPX_N; + + uint8_t optrand[SPX_N]; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t root[SPX_N]; uint32_t i; uint64_t tree; uint32_t idx_leaf; uint32_t wots_addr[8] = {0}; uint32_t tree_addr[8] = {0}; - hash_state hash_state_seeded; + memcpy(ctx.sk_seed, sk, SPX_N); + memcpy(ctx.pub_seed, pk, SPX_N); /* This hook allows the hash function instantiation to do whatever preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_initialize_hash_function( - &hash_state_seeded, - pub_seed, sk_seed); + initialize_hash_function(&ctx); - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_set_type( - wots_addr, PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_set_type( - tree_addr, PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_ADDR_TYPE_HASHTREE); + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); /* Optionally, signing can be made non-deterministic using optrand. This can help counter side-channel attacks that would benefit from getting a large number of traces when the signer uses the same nodes. */ - randombytes(optrand, PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N); + randombytes(optrand, SPX_N); /* Compute the digest randomization value. */ - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_gen_message_random( - sig, sk_prf, optrand, m, mlen, &hash_state_seeded); + gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); /* Derive the message digest and leaf index from R, PK and M. */ - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N; + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_set_keypair_addr( - wots_addr, idx_leaf); + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); /* Sign the message hash using FORS. */ - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_fors_sign( - sig, root, mhash, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_FORS_BYTES; - - for (i = 0; i < PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_D; i++) { - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_set_tree_addr(tree_addr, tree); - - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_set_keypair_addr( - wots_addr, idx_leaf); - - /* Compute a WOTS signature. */ - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_wots_sign( - sig, root, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_WOTS_BYTES; - - /* Compute the authentication path for the used WOTS leaf. */ - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_treehash_TREE_HEIGHT( - root, sig, sk_seed, pub_seed, idx_leaf, 0, - wots_gen_leaf, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_TREE_HEIGHT * PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N; + fors_sign(sig, root, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); + sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_TREE_HEIGHT; + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; } - memcpy(orig_sig, aligned_sig.sig, PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_BYTES); - *siglen = PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_BYTES; + free_hash_function(&ctx); + + *siglen = SPX_BYTES; return 0; } @@ -250,23 +159,14 @@ int PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_crypto_sign_signature( /** * Verifies a detached signature and message under a given public key. */ -int PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk) { - // guarantee alignment of pk - union { - __m128 *_x; - uint8_t pk[PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_CRYPTO_PUBLICKEYBYTES]; - } aligned_pk; - memcpy(aligned_pk.pk, pk, PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_CRYPTO_PUBLICKEYBYTES); - pk = aligned_pk.pk; - - const unsigned char *pub_seed = pk; - const unsigned char *pub_root = pk + PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N; - unsigned char mhash[PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_FORS_MSG_BYTES]; - unsigned char wots_pk[PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_WOTS_BYTES]; - unsigned char root[PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N]; - unsigned char leaf[PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N]; +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk) { + spx_ctx ctx; + const uint8_t *pub_root = pk + SPX_N; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t wots_pk[SPX_WOTS_BYTES]; + uint8_t root[SPX_N]; + uint8_t leaf[SPX_N]; unsigned int i; uint64_t tree; uint32_t idx_leaf; @@ -274,77 +174,66 @@ int PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_crypto_sign_verify( uint32_t tree_addr[8] = {0}; uint32_t wots_pk_addr[8] = {0}; - hash_state hash_state_seeded; - - if (siglen != PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_BYTES) { + if (siglen != SPX_BYTES) { return -1; } + memcpy(ctx.pub_seed, pk, SPX_N); + /* This hook allows the hash function instantiation to do whatever preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_initialize_hash_function( - &hash_state_seeded, - pub_seed, NULL); + initialize_hash_function(&ctx); - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_set_type( - wots_addr, PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_set_type( - tree_addr, PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_ADDR_TYPE_HASHTREE); - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_set_type( - wots_pk_addr, PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_ADDR_TYPE_WOTSPK); + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); /* Derive the message digest and leaf index from R || PK || M. */ - /* The additional PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N is a result of the hash domain separator. */ - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N; + /* The additional SPX_N is a result of the hash domain separator. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; /* Layer correctly defaults to 0, so no need to set_layer_addr */ - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_set_keypair_addr( - wots_addr, idx_leaf); + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_fors_pk_from_sig( - root, sig, mhash, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_FORS_BYTES; + fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; /* For each subtree.. */ - for (i = 0; i < PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_D; i++) { - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_set_tree_addr(tree_addr, tree); + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_set_keypair_addr( - wots_addr, idx_leaf); + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_copy_keypair_addr( - wots_pk_addr, wots_addr); + copy_keypair_addr(wots_pk_addr, wots_addr); /* The WOTS public key is only correct if the signature was correct. */ /* Initially, root is the FORS pk, but on subsequent iterations it is the root of the subtree below the currently processed subtree. */ - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_wots_pk_from_sig( - wots_pk, sig, root, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_WOTS_BYTES; + wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); + sig += SPX_WOTS_BYTES; /* Compute the leaf node using the WOTS public key. */ - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_thash_WOTS_LEN( - leaf, wots_pk, pub_seed, wots_pk_addr, &hash_state_seeded); + thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); /* Compute the root node of this subtree. */ - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_compute_root( - root, leaf, idx_leaf, 0, sig, PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_TREE_HEIGHT, - pub_seed, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_TREE_HEIGHT * PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N; + compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, + &ctx, tree_addr); + sig += SPX_TREE_HEIGHT * SPX_N; /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_TREE_HEIGHT; + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; } + // cleanup + free_hash_function(&ctx); + /* Check if the root node equals the root node in the public key. */ - if (memcmp(root, pub_root, PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N) != 0) { + if (memcmp(root, pub_root, SPX_N) != 0) { return -1; } @@ -355,15 +244,14 @@ int PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_crypto_sign_verify( /** * Returns an array containing the signature followed by the message. */ -int PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk) { size_t siglen; - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_crypto_sign_signature( - sm, &siglen, m, mlen, sk); + crypto_sign_signature(sm, &siglen, m, mlen, sk); - memmove(sm + PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_BYTES, m, mlen); + memmove(sm + SPX_BYTES, m, mlen); *smlen = siglen + mlen; return 0; @@ -372,38 +260,27 @@ int PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_crypto_sign( /** * Verifies a given signature-message pair under a given public key. */ -int PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk) { - - // guarantee alignment of pk - union { - __m128 *_x; - uint8_t pk[PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_CRYPTO_PUBLICKEYBYTES]; - } aligned_pk; - memcpy(aligned_pk.pk, pk, PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_CRYPTO_PUBLICKEYBYTES); - pk = aligned_pk.pk; - - +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk) { /* The API caller does not necessarily know what size a signature should be - but SPHINCS+ signatures are always exactly PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_BYTES. */ - if (smlen < PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_BYTES) { + but SPHINCS+ signatures are always exactly SPX_BYTES. */ + if (smlen < SPX_BYTES) { memset(m, 0, smlen); *mlen = 0; return -1; } - *mlen = smlen - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_BYTES; + *mlen = smlen - SPX_BYTES; - if (PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_crypto_sign_verify( - sm, PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_BYTES, sm + PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_BYTES, *mlen, pk)) { + if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { memset(m, 0, smlen); *mlen = 0; return -1; } /* If verification was successful, move the message to the right place. */ - memmove(m, sm + PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_BYTES, *mlen); + memmove(m, sm + SPX_BYTES, *mlen); return 0; } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/thash.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/thash.h index b763d64cf1..8687ccfb4d 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/thash.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/thash.h @@ -1,28 +1,13 @@ -#ifndef PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_THASH_H -#define PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_THASH_H +#ifndef SPX_THASH_H +#define SPX_THASH_H -#include "hash_state.h" +#include "context.h" +#include "params.h" #include -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); +#define thash SPX_NAMESPACE(thash) +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/thash_haraka_simple.c b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/thash_haraka_simple.c index 4594b74f92..207777bf8d 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/thash_haraka_simple.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/thash_haraka_simple.c @@ -4,80 +4,33 @@ #include "address.h" #include "params.h" #include "thash.h" +#include "utils.h" #include "haraka.h" /** - * Takes an array of inblocks concatenated arrays of PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N bytes. + * Takes an array of inblocks concatenated arrays of SPX_N bytes. */ -static void PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_thash( - unsigned char *out, unsigned char *buf, - const unsigned char *in, unsigned int inblocks, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]) { + PQCLEAN_VLA(uint8_t, buf, SPX_ADDR_BYTES + inblocks * SPX_N); unsigned char outbuf[32]; unsigned char buf_tmp[64]; - (void)pub_seed; /* Suppress an 'unused parameter' warning. */ - if (inblocks == 1) { /* F function */ - /* Since PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N may be smaller than 32, we need a temporary buffer. */ + /* Since SPX_N may be smaller than 32, we need a temporary buffer. */ memset(buf_tmp, 0, 64); - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_addr_to_bytes(buf_tmp, addr); - memcpy(buf_tmp + PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_ADDR_BYTES, in, PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N); + memcpy(buf_tmp, addr, 32); + memcpy(buf_tmp + SPX_ADDR_BYTES, in, SPX_N); - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_haraka512(outbuf, buf_tmp, hash_state_seeded); - memcpy(out, outbuf, PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N); + haraka512(outbuf, buf_tmp, ctx); + memcpy(out, outbuf, SPX_N); } else { /* All other tweakable hashes*/ - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_addr_to_bytes(buf, addr); - memcpy(buf + PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_ADDR_BYTES, in, inblocks * PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N); + memcpy(buf, addr, 32); + memcpy(buf + SPX_ADDR_BYTES, in, inblocks * SPX_N); - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_haraka_S( - out, PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N, buf, PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N, hash_state_seeded); + haraka_S(out, SPX_N, buf, SPX_ADDR_BYTES + inblocks * SPX_N, ctx); } } - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_ADDR_BYTES + 1 * PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N]; - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_thash( - out, buf, in, 1, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_ADDR_BYTES + 2 * PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N]; - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_thash( - out, buf, in, 2, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_ADDR_BYTES + PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_WOTS_LEN * PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N]; - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_thash( - out, buf, in, PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_WOTS_LEN, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_ADDR_BYTES + PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_FORS_TREES * PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N]; - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_thash( - out, buf, in, PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_FORS_TREES, pub_seed, addr, hash_state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/thash_haraka_simplex4.c b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/thash_haraka_simplex4.c index a30d0e1c64..2ee763d7d9 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/thash_haraka_simplex4.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/thash_haraka_simplex4.c @@ -2,65 +2,66 @@ #include #include "address.h" -#include "haraka.h" #include "params.h" #include "thashx4.h" +#include "harakax4.h" + +#include "utils.h" + /** * 4-way parallel version of thash; takes 4x as much input and output */ -#define thashx4_variant(name, inblocks) \ - void PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_thashx4_##name(unsigned char *out0, unsigned char *out1, unsigned char *out2, \ - unsigned char *out3, const unsigned char *in0, \ - const unsigned char *in1, const unsigned char *in2, \ - const unsigned char *in3, const unsigned char *pub_seed, \ - uint32_t addrx4[4 * 8], const harakactx *state) { \ - unsigned char buf0[PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_ADDR_BYTES + (inblocks)*PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N]; \ - unsigned char buf1[PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_ADDR_BYTES + (inblocks)*PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N]; \ - unsigned char buf2[PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_ADDR_BYTES + (inblocks)*PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N]; \ - unsigned char buf3[PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_ADDR_BYTES + (inblocks)*PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N]; \ - unsigned char outbuf[32 * 4]; \ - unsigned char buf_tmp[64 * 4]; \ - \ - (void)pub_seed; /* Suppress an 'unused parameter' warning. */ \ - \ - if ((inblocks) == 1) { \ - memset(buf_tmp, 0, 64 * 4); \ - \ - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_addr_to_bytes(buf_tmp, addrx4 + 0 * 8); \ - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_addr_to_bytes(buf_tmp + 64, addrx4 + 1 * 8); \ - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_addr_to_bytes(buf_tmp + 128, addrx4 + 2 * 8); \ - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_addr_to_bytes(buf_tmp + 192, addrx4 + 3 * 8); \ - \ - memcpy(buf_tmp + PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_ADDR_BYTES, in0, PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N); \ - memcpy(buf_tmp + PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_ADDR_BYTES + 64, in1, PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N); \ - memcpy(buf_tmp + PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_ADDR_BYTES + 128, in2, PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N); \ - memcpy(buf_tmp + PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_ADDR_BYTES + 192, in3, PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N); \ - \ - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_haraka512x4(outbuf, buf_tmp, state); \ - \ - memcpy(out0, outbuf, PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N); \ - memcpy(out1, outbuf + 32, PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N); \ - memcpy(out2, outbuf + 64, PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N); \ - memcpy(out3, outbuf + 96, PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N); \ - } else { \ - /* All other tweakable hashes*/ \ - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_addr_to_bytes(buf0, addrx4 + 0 * 8); \ - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_addr_to_bytes(buf1, addrx4 + 1 * 8); \ - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_addr_to_bytes(buf2, addrx4 + 2 * 8); \ - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_addr_to_bytes(buf3, addrx4 + 3 * 8); \ - \ - memcpy(buf0 + PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_ADDR_BYTES, in0, (inblocks)*PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N); \ - memcpy(buf1 + PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_ADDR_BYTES, in1, (inblocks)*PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N); \ - memcpy(buf2 + PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_ADDR_BYTES, in2, (inblocks)*PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N); \ - memcpy(buf3 + PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_ADDR_BYTES, in3, (inblocks)*PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N); \ - \ - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_haraka_Sx4(out0, out1, out2, out3, PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N, buf0, buf1, buf2, buf3, \ - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_ADDR_BYTES + (inblocks)*PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N, state); \ - } \ - } +#define thashx4 SPX_NAMESPACE(thashx4) +void thashx4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addrx4[4 * 8]) { + PQCLEAN_VLA(unsigned char, buf0, SPX_ADDR_BYTES + inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, buf1, SPX_ADDR_BYTES + inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, buf2, SPX_ADDR_BYTES + inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, buf3, SPX_ADDR_BYTES + inblocks * SPX_N); + unsigned char outbuf[32 * 4]; + unsigned char buf_tmp[64 * 4]; + + if (inblocks == 1) { + memset(buf_tmp, 0, 64 * 4); + + memcpy(buf_tmp, addrx4 + 0 * 8, 32); + memcpy(buf_tmp + 64, addrx4 + 1 * 8, 32); + memcpy(buf_tmp + 128, addrx4 + 2 * 8, 32); + memcpy(buf_tmp + 192, addrx4 + 3 * 8, 32); -thashx4_variant(1, 1) -thashx4_variant(2, 2) -thashx4_variant(WOTS_LEN, PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_WOTS_LEN) -thashx4_variant(FORS_TREES, PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_FORS_TREES) + memcpy(buf_tmp + SPX_ADDR_BYTES, in0, SPX_N); + memcpy(buf_tmp + SPX_ADDR_BYTES + 64, in1, SPX_N); + memcpy(buf_tmp + SPX_ADDR_BYTES + 128, in2, SPX_N); + memcpy(buf_tmp + SPX_ADDR_BYTES + 192, in3, SPX_N); + + haraka512x4(outbuf, buf_tmp, ctx); + + memcpy(out0, outbuf, SPX_N); + memcpy(out1, outbuf + 32, SPX_N); + memcpy(out2, outbuf + 64, SPX_N); + memcpy(out3, outbuf + 96, SPX_N); + } else { + /* All other tweakable hashes*/ + memcpy(buf0, addrx4 + 0 * 8, 32); + memcpy(buf1, addrx4 + 1 * 8, 32); + memcpy(buf2, addrx4 + 2 * 8, 32); + memcpy(buf3, addrx4 + 3 * 8, 32); + + memcpy(buf0 + SPX_ADDR_BYTES, in0, inblocks * SPX_N); + memcpy(buf1 + SPX_ADDR_BYTES, in1, inblocks * SPX_N); + memcpy(buf2 + SPX_ADDR_BYTES, in2, inblocks * SPX_N); + memcpy(buf3 + SPX_ADDR_BYTES, in3, inblocks * SPX_N); + + haraka_Sx4(out0, out1, out2, out3, SPX_N, + buf0, buf1, buf2, buf3, SPX_ADDR_BYTES + inblocks * SPX_N, + ctx); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/thashx4.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/thashx4.h index 3059b65ce0..64798a3727 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/thashx4.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/thashx4.h @@ -1,25 +1,20 @@ -#ifndef PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_THASHX4_H -#define PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_THASHX4_H +#ifndef SPX_THASHX4_H +#define SPX_THASHX4_H #include -#include "hash_state.h" +#include "context.h" +#include "params.h" -#define thashx4_header(inblocks) \ - void PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_thashx4_##inblocks(unsigned char *out0, \ - unsigned char *out1, \ - unsigned char *out2, \ - unsigned char *out3, \ - const unsigned char *in0, \ - const unsigned char *in1, \ - const unsigned char *in2, \ - const unsigned char *in3, \ - const unsigned char *pub_seed, uint32_t addrx4[4*8], \ - const hash_state *state_seeded) - -thashx4_header(1); -thashx4_header(2); -thashx4_header(WOTS_LEN); -thashx4_header(FORS_TREES); +#define thashx4 SPX_NAMESPACE(thashx4) +void thashx4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addrx4[4 * 8]); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/utils.c b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/utils.c index 93aa184437..177b541fb9 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/utils.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/utils.c @@ -1,34 +1,41 @@ -#include #include +#include "utils.h" + #include "address.h" #include "hash.h" -#include "hash_state.h" #include "params.h" #include "thash.h" -#include "utils.h" /** * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. */ -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in) { +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in) { + int i; /* Iterate over out in decreasing order, for big-endianness. */ - for (size_t i = outlen; i > 0; i--) { - out[i - 1] = in & 0xff; + for (i = (signed int)outlen - 1; i >= 0; i--) { + out[i] = in & 0xff; in = in >> 8; } } +void u32_to_bytes(unsigned char *out, uint32_t in) { + out[0] = (unsigned char)(in >> 24); + out[1] = (unsigned char)(in >> 16); + out[2] = (unsigned char)(in >> 8); + out[3] = (unsigned char)in; +} + /** * Converts the inlen bytes in 'in' from big-endian byte order to an integer. */ -unsigned long long PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_bytes_to_ull( - const unsigned char *in, size_t inlen) { +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { unsigned long long retval = 0; + unsigned int i; - for (size_t i = 0; i < inlen; i++) { + for (i = 0; i < inlen; i++) { retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); } return retval; @@ -38,94 +45,80 @@ unsigned long long PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_bytes_to_ull( * Computes a root node given a leaf and an auth path. * Expects address to be complete other than the tree_height and tree_index. */ -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]) { uint32_t i; - unsigned char buffer[2 * PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N]; + unsigned char buffer[2 * SPX_N]; /* If leaf_idx is odd (last bit = 1), current path element is a right child and auth_path has to go left. Otherwise it is the other way around. */ if (leaf_idx & 1) { - memcpy(buffer + PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N, leaf, PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N); + memcpy(buffer + SPX_N, leaf, SPX_N); + memcpy(buffer, auth_path, SPX_N); } else { - memcpy(buffer, leaf, PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N); - memcpy(buffer + PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N, auth_path, PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N); + memcpy(buffer, leaf, SPX_N); + memcpy(buffer + SPX_N, auth_path, SPX_N); } - auth_path += PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N; + auth_path += SPX_N; for (i = 0; i < tree_height - 1; i++) { leaf_idx >>= 1; idx_offset >>= 1; /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_set_tree_height(addr, i + 1); - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_set_tree_index( - addr, leaf_idx + idx_offset); + set_tree_height(addr, i + 1); + set_tree_index(addr, leaf_idx + idx_offset); /* Pick the right or left neighbor, depending on parity of the node. */ if (leaf_idx & 1) { - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_thash_2( - buffer + PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N); + thash(buffer + SPX_N, buffer, 2, ctx, addr); + memcpy(buffer, auth_path, SPX_N); } else { - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_thash_2( - buffer, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer + PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N, auth_path, PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N); + thash(buffer, buffer, 2, ctx, addr); + memcpy(buffer + SPX_N, auth_path, SPX_N); } - auth_path += PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N; + auth_path += SPX_N; } /* The last iteration is exceptional; we do not copy an auth_path node. */ leaf_idx >>= 1; idx_offset >>= 1; - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_set_tree_height(addr, tree_height); - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_set_tree_index( - addr, leaf_idx + idx_offset); - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_thash_2( - root, buffer, pub_seed, addr, hash_state_seeded); + set_tree_height(addr, tree_height); + set_tree_index(addr, leaf_idx + idx_offset); + thash(root, buffer, 2, ctx, addr); } /** * For a given leaf index, computes the authentication path and the resulting * root node using Merkle's TreeHash algorithm. * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_ADDR_TYPE_FORSTREE). + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). * Applies the offset idx_offset to indices before building addresses, so that * it is possible to continue counting indices across trees. */ -static void PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_treehash( - unsigned char *root, unsigned char *auth_path, - unsigned char *stack, unsigned int *heights, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - +void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx * /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]) { + PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); + PQCLEAN_VLA(unsigned int, heights, tree_height + 1); unsigned int offset = 0; uint32_t idx; uint32_t tree_idx; for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { /* Add the next leaf node to the stack. */ - gen_leaf(stack + offset * PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N, - sk_seed, pub_seed, idx + idx_offset, tree_addr, - hash_state_seeded); + gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); offset++; heights[offset - 1] = 0; /* If this is a node we need for the auth path.. */ if ((leaf_idx ^ 0x1) == idx) { - memcpy(auth_path, stack + (offset - 1)*PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N, PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N); + memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); } /* While the top-most nodes are of equal height.. */ @@ -134,66 +127,22 @@ static void PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_treehash( tree_idx = (idx >> (heights[offset - 1] + 1)); /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_set_tree_height( - tree_addr, heights[offset - 1] + 1); - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_set_tree_index( - tree_addr, tree_idx + (idx_offset >> (heights[offset - 1] + 1))); + set_tree_height(tree_addr, heights[offset - 1] + 1); + set_tree_index(tree_addr, + tree_idx + (idx_offset >> (heights[offset - 1] + 1))); /* Hash the top-most nodes from the stack together. */ - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_thash_2( - stack + (offset - 2)*PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N, stack + (offset - 2)*PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N, - pub_seed, tree_addr, hash_state_seeded); + thash(stack + (offset - 2)*SPX_N, + stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); offset--; /* Note that the top-most node is now one layer higher. */ heights[offset - 1]++; /* If this is a node we need for the auth path.. */ if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_path + heights[offset - 1]*PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N, - stack + (offset - 1)*PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N, PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N); + memcpy(auth_path + heights[offset - 1]*SPX_N, + stack + (offset - 1)*SPX_N, SPX_N); } } } - memcpy(root, stack, PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N); -} - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_FORS_HEIGHT + 1)*PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N]; - unsigned int heights[PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_FORS_HEIGHT + 1]; - - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_FORS_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_TREE_HEIGHT + 1)*PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N]; - unsigned int heights[PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_TREE_HEIGHT + 1]; - - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_TREE_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); + memcpy(root, stack, SPX_N); } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/utils.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/utils.h index df3f21c6a7..64f5d5a53a 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/utils.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/utils.h @@ -1,64 +1,58 @@ -#ifndef PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_UTILS_H -#define PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_UTILS_H +#ifndef SPX_UTILS_H +#define SPX_UTILS_H -#include "hash_state.h" -#include "params.h" -#include #include +#include "compat.h" +#include "context.h" +#include "params.h" + + +/* To support MSVC use alloca() instead of VLAs. See #20. */ + + /** * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. */ -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in); +#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in); +#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) +void u32_to_bytes(unsigned char *out, uint32_t in); /** * Converts the inlen bytes in 'in' from big-endian byte order to an integer. */ -unsigned long long PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_bytes_to_ull( - const unsigned char *in, size_t inlen); +#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); /** * Computes a root node given a leaf and an auth path. * Expects address to be complete other than the tree_height and tree_index. */ -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); +#define compute_root SPX_NAMESPACE(compute_root) +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]); /** * For a given leaf index, computes the authentication path and the resulting * root node using Merkle's TreeHash algorithm. * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_ADDR_TYPE_FORSTREE). + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). * Applies the offset idx_offset to indices before building addresses, so that * it is possible to continue counting indices across trees. */ -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); +#define treehash SPX_NAMESPACE(treehash) +void treehash(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx *ctx /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]); -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/utilsx4.c b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/utilsx4.c index 9d3a35f5b0..1638677194 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/utilsx4.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/utilsx4.c @@ -1,98 +1,138 @@ +#include + +#include "utilsx4.h" + #include "address.h" #include "params.h" #include "thashx4.h" #include "utils.h" -#include "utilsx4.h" -#include - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. +/* + * Generate the entire Merkle tree, computing the authentication path for leaf_idx, + * and the resulting root node using Merkle's TreeHash algorithm. * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_ADDR_TYPE_FORSTREE). + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) + * + * This expects tree_addrx4 to be initialized to 4 parallel addr structures for + * the Merkle tree nodes + * * Applies the offset idx_offset to indices before building addresses, so that * it is possible to continue counting indices across trees. + * + * This works by using the standard Merkle tree building algorithm, except + * that each 'node' tracked is actually 4 consecutive nodes in the real tree. + * When we combine two logical nodes ABCD and WXYZ, we perform the H + * operation on adjacent real nodes, forming the parent logical node + * (AB)(CD)(WX)(YZ) + * + * When we get to the top two levels of the real tree (where there is only + * one logical node), we continue this operation two more times; the right + * most real node will by the actual root (and the other 3 nodes will be + * garbage). We follow the same thashx4 logic so that the 'extract + * authentication path components' part of the loop is still executed (and + * to simplify the code somewhat) + * + * This currently assumes tree_height >= 2; I suspect that doing an adjusting + * idx, addr_idx on the gen_leafx4 call if tree_height < 2 would fix it; since + * we don't actually use such short trees, I haven't bothered */ -#define treehashx4_variant(name, tree_height) \ - void PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_treehashx4_##name( \ - unsigned char *rootx4, unsigned char *auth_pathx4, const unsigned char *sk_seed, \ - const unsigned char *pub_seed, const uint32_t leaf_idx[4], uint32_t idx_offset[4], \ - void (*gen_leafx4)(unsigned char * /* leaf0 */, unsigned char * /* leaf1 */, \ - unsigned char * /* leaf2 */, unsigned char * /* leaf3 */, \ - const unsigned char * /* sk_seed */, \ - const unsigned char * /* pub_seed */, uint32_t /* addr_idx0 */, \ - uint32_t /* addr_idx1 */, uint32_t /* addr_idx2 */, \ - uint32_t /* addr_idx3 */, const uint32_t[8] /* tree_addr */, \ - const hash_state * /* state_seeded */), \ - uint32_t tree_addrx4[4 * 8], const hash_state *state_seeded) { \ - unsigned char stackx4[4 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N]; \ - unsigned int heights[(tree_height) + 1]; \ - unsigned int offset = 0; \ - uint32_t idx; \ - uint32_t tree_idx; \ - unsigned int j; \ - \ - for (idx = 0; idx < (uint32_t)(1 << (tree_height)); idx++) { \ - /* Add the next leaf node to the stack. */ \ - gen_leafx4(stackx4 + 0 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N + offset * PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N, \ - stackx4 + 1 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N + offset * PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N, \ - stackx4 + 2 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N + offset * PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N, \ - stackx4 + 3 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N + offset * PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N, sk_seed, \ - pub_seed, idx + idx_offset[0], idx + idx_offset[1], idx + idx_offset[2], \ - idx + idx_offset[3], tree_addrx4, state_seeded); \ - offset++; \ - heights[offset - 1] = 0; \ - \ - /* If this is a node we need for the auth path.. */ \ - for (j = 0; j < 4; j++) { \ - if ((leaf_idx[j] ^ 0x1) == idx) { \ - memcpy(auth_pathx4 + j * (tree_height)*PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N, \ - stackx4 + j * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N + (offset - 1) * PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N, \ - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N); \ - } \ - } \ - \ - /* While the top-most nodes are of equal height.. */ \ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { \ - /* Compute index of the new node, in the next layer. */ \ - tree_idx = (idx >> (heights[offset - 1] + 1)); \ - \ - /* Set the address of the node we're creating. */ \ - for (j = 0; j < 4; j++) { \ - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_set_tree_height(tree_addrx4 + j * 8, heights[offset - 1] + 1); \ - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_set_tree_index(tree_addrx4 + j * 8, \ - tree_idx + (idx_offset[j] >> (heights[offset - 1] + 1))); \ - } \ - /* Hash the top-most nodes from the stack together. */ \ - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_thashx4_2(stackx4 + 0 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N + (offset - 2) * PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N, \ - stackx4 + 1 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N + (offset - 2) * PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N, \ - stackx4 + 2 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N + (offset - 2) * PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N, \ - stackx4 + 3 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N + (offset - 2) * PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N, \ - stackx4 + 0 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N + (offset - 2) * PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N, \ - stackx4 + 1 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N + (offset - 2) * PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N, \ - stackx4 + 2 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N + (offset - 2) * PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N, \ - stackx4 + 3 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N + (offset - 2) * PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N, \ - pub_seed, tree_addrx4, state_seeded); \ - offset--; \ - /* Note that the top-most node is now one layer higher. */ \ - heights[offset - 1]++; \ - \ - /* If this is a node we need for the auth path.. */ \ - for (j = 0; j < 4; j++) { \ - if (((leaf_idx[j] >> heights[offset - 1]) ^ 0x1) == tree_idx) { \ - memcpy(auth_pathx4 + j * (tree_height)*PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N + \ - heights[offset - 1] * PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N, \ - stackx4 + j * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N + (offset - 1) * PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N, \ - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N); \ - } \ - } \ - } \ - } \ - \ - for (j = 0; j < 4; j++) { \ - memcpy(rootx4 + j * PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N, stackx4 + j * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N, PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N); \ - } \ - } +void treehashx4(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, + uint32_t tree_height, + void (*gen_leafx4)( + unsigned char * /* Where to write the leaves */, + const spx_ctx *, + uint32_t idx, void *info), + uint32_t tree_addrx4[4 * 8], + void *info) { + /* This is where we keep the intermediate nodes */ + PQCLEAN_VLA(unsigned char, stackx4, tree_height * 4 * SPX_N); + uint32_t left_adj = 0, prev_left_adj = 0; /* When we're doing the top 3 */ + /* levels, the left-most part of the tree isn't at the beginning */ + /* of current[]. These give the offset of the actual start */ + + uint32_t idx; + uint32_t max_idx = (1U << (tree_height - 2)) - 1; + for (idx = 0;; idx++) { + unsigned char current[4 * SPX_N]; /* Current logical node */ + gen_leafx4( current, ctx, 4 * idx + idx_offset, + info ); -treehashx4_variant(FORS_HEIGHT, PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_FORS_HEIGHT) + /* Now combine the freshly generated right node with previously */ + /* generated left ones */ + uint32_t internal_idx_offset = idx_offset; + uint32_t internal_idx = idx; + uint32_t internal_leaf = leaf_idx; + uint32_t h; /* The height we are in the Merkle tree */ + for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { + + /* Special processing if we're at the top of the tree */ + if (h >= tree_height - 2) { + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[3 * SPX_N], SPX_N ); + return; + } + /* The tree indexing logic is a bit off in this case */ + /* Adjust it so that the left-most node of the part of */ + /* the tree that we're processing has index 0 */ + prev_left_adj = left_adj; + left_adj = 4U - (1 << (tree_height - h - 1)); + } + + /* Check if we hit the top of the tree */ + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[3 * SPX_N], SPX_N ); + return; + } + + /* + * Check if one of the nodes we have is a part of the + * authentication path; if it is, write it out + */ + if ((((internal_idx << 2) ^ internal_leaf) & ~0x3U) == 0) { + memcpy( &auth_path[ h * SPX_N ], + ¤t[(((internal_leaf & 3) ^ 1) + prev_left_adj) * SPX_N], + SPX_N ); + } + + /* + * Check if we're at a left child; if so, stop going up the stack + * Exception: if we've reached the end of the tree, keep on going + * (so we combine the last 4 nodes into the one root node in two + * more iterations) + */ + if ((internal_idx & 1) == 0 && idx < max_idx) { + break; + } + + /* Ok, we're at a right node (or doing the top 3 levels) */ + /* Now combine the left and right logical nodes together */ + + /* Set the address of the node we're creating. */ + unsigned int j; + internal_idx_offset >>= 1; + for (j = 0; j < 4; j++) { + set_tree_height(tree_addrx4 + j * 8, h + 1); + set_tree_index(tree_addrx4 + j * 8, + (4 / 2) * (internal_idx & ~1U) + j - left_adj + internal_idx_offset ); + } + unsigned char *left = &stackx4[h * 4 * SPX_N]; + thashx4( ¤t[0 * SPX_N], + ¤t[1 * SPX_N], + ¤t[2 * SPX_N], + ¤t[3 * SPX_N], + &left [0 * SPX_N], + &left [2 * SPX_N], + ¤t[0 * SPX_N], + ¤t[2 * SPX_N], + 2, ctx, tree_addrx4); + } + + /* We've hit a left child; save the current for when we get the */ + /* corresponding right right */ + memcpy( &stackx4[h * 4 * SPX_N], current, 4 * SPX_N); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/utilsx4.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/utilsx4.h index 99623c2108..facb874b18 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/utilsx4.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/utilsx4.h @@ -1,38 +1,30 @@ -#ifndef PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_UTILSX4_H -#define PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_UTILSX4_H - -#include "hash_state.h" -#include "params.h" +#ifndef SPX_UTILSX4_H +#define SPX_UTILSX4_H #include +#include "context.h" +#include "params.h" + /** * For a given leaf index, computes the authentication path and the resulting * root node using Merkle's TreeHash algorithm. * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_ADDR_TYPE_FORSTREE). + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). * Applies the offset idx_offset to indices before building addresses, so that * it is possible to continue counting indices across trees. + * + * This implementation uses AVX to compute internal nodes 4 at a time (in + * parallel) */ -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_treehashx4_FORS_HEIGHT(unsigned char *rootx4, - unsigned char *auth_pathx4, - const unsigned char *sk_seed, - const unsigned char *pub_seed, - const uint32_t leaf_idx[4], - uint32_t idx_offset[4], - void (*gen_leafx4)(unsigned char * /* leaf0 */, - unsigned char * /* leaf1 */, - unsigned char * /* leaf2 */, - unsigned char * /* leaf3 */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx0 */, - uint32_t /* addr_idx1 */, - uint32_t /* addr_idx2 */, - uint32_t /* addr_idx3 */, - const uint32_t[8] /* tree_addr */, - const hash_state * /* state_seeded */), - uint32_t tree_addrx4[4 * 8], - const hash_state *state_seeded); +#define treehashx4 SPX_NAMESPACE(treehashx4) +void treehashx4(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leafx4)( + unsigned char * /* Where to write the leaves */, + const spx_ctx * /* ctx */, + uint32_t addr_idx, void *info), + uint32_t tree_addrx4[4 * 8], void *info); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/wots.c b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/wots.c index 1997f34497..4d5041ce05 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/wots.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/wots.c @@ -1,106 +1,104 @@ #include #include +#include "wots.h" + #include "address.h" #include "hash.h" -#include "hash_state.h" #include "hashx4.h" #include "params.h" #include "thash.h" #include "thashx4.h" #include "utils.h" -#include "wots.h" +#include "utilsx4.h" +#include "wotsx4.h" // TODO clarify address expectations, and make them more uniform. // TODO i.e. do we expect types to be set already? // TODO and do we expect modifications or copies? /** - * Computes the starting value for a chain, i.e. the secret key. - * Expects the address to be complete up to the chain address. - */ -static void wots_gen_sk(unsigned char *sk, const unsigned char *sk_seed, - uint32_t wots_addr[8], const hash_state *state_seeded) { - /* Make sure that the hash address is actually zeroed. */ - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_set_hash_addr(wots_addr, 0); - - /* Generate sk element. */ - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_prf_addr(sk, sk_seed, wots_addr, state_seeded); -} - -/** - * 4-way parallel version of wots_gen_sk; expects 4x as much space in sk + * Computes up the chains */ -static void wots_gen_skx4(unsigned char *skx4, const unsigned char *sk_seed, - uint32_t wots_addrx4[4 * 8], const hash_state *state_seeded) { - unsigned int j; - - /* Make sure that the hash address is actually zeroed. */ +static void gen_chains( + unsigned char *out, + const unsigned char *in, + unsigned int start[SPX_WOTS_LEN], + const unsigned int steps[SPX_WOTS_LEN], + const spx_ctx *ctx, + uint32_t addr[8]) { + uint32_t i, j, k, idx, watching; + int done; + unsigned char empty[SPX_N]; + unsigned char *bufs[4]; + uint32_t addrs[8 * 4]; + + int l; + uint16_t counts[SPX_WOTS_W] = { 0 }; + uint16_t idxs[SPX_WOTS_LEN]; + uint16_t total, newTotal; + + /* set addrs = {addr, addr, addr, addr} */ for (j = 0; j < 4; j++) { - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_set_hash_addr(wots_addrx4 + j * 8, 0); + memcpy(addrs + j * 8, addr, sizeof(uint32_t) * 8); } - /* Generate sk element. */ - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_prf_addrx4(skx4 + 0 * PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N, - skx4 + 1 * PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N, - skx4 + 2 * PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N, - skx4 + 3 * PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N, - sk_seed, wots_addrx4, - state_seeded); -} - -/** - * Computes the chaining function. - * out and in have to be n-byte arrays. - * - * Interprets in as start-th value of the chain. - * addr has to contain the address of the chain. - */ -static void gen_chain(unsigned char *out, const unsigned char *in, - unsigned int start, unsigned int steps, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *state_seeded) { - uint32_t i; - /* Initialize out with the value at position 'start'. */ - memcpy(out, in, PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N); + memcpy(out, in, SPX_WOTS_LEN * SPX_N); - /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_WOTS_W; i++) { - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_set_hash_addr(addr, i); - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_thash_1(out, out, pub_seed, addr, state_seeded); + /* Sort the chains in reverse order by steps using counting sort. */ + for (i = 0; i < SPX_WOTS_LEN; i++) { + counts[steps[i]]++; + } + total = 0; + for (l = SPX_WOTS_W - 1; l >= 0; l--) { + newTotal = counts[l] + total; + counts[l] = total; + total = newTotal; + } + for (i = 0; i < SPX_WOTS_LEN; i++) { + idxs[counts[steps[i]]] = (uint16_t)i; + counts[steps[i]]++; } -} -/** - * 4-way parallel version of gen_chain; expects 4x as much space in out, and - * 4x as much space in inx4. Assumes start and step identical across chains. - */ -static void gen_chainx4(unsigned char *outx4, const unsigned char *inx4, - unsigned int start, unsigned int steps, - const unsigned char *pub_seed, uint32_t addrx4[4 * 8], - const hash_state *state_seeded) { - uint32_t i; - unsigned int j; + /* We got our work cut out for us: do it! */ + for (i = 0; i < SPX_WOTS_LEN; i += 4) { + for (j = 0; j < 4 && i + j < SPX_WOTS_LEN; j++) { + idx = idxs[i + j]; + set_chain_addr(addrs + j * 8, idx); + bufs[j] = out + SPX_N * idx; + } - /* Initialize outx4 with the value at position 'start'. */ - memcpy(outx4, inx4, 4 * PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N); + /* As the chains are sorted in reverse order, we know that the first + * chain is the longest and the last one is the shortest. We keep + * an eye on whether the last chain is done and then on the one before, + * et cetera. */ + watching = 3; + done = 0; + while (i + watching >= SPX_WOTS_LEN) { + bufs[watching] = &empty[0]; + watching--; + } - /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_WOTS_W; i++) { - for (j = 0; j < 4; j++) { - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_set_hash_addr(addrx4 + j * 8, i); + for (k = 0;; k++) { + while (k == steps[idxs[i + watching]]) { + bufs[watching] = &empty[0]; + if (watching == 0) { + done = 1; + break; + } + watching--; + } + if (done) { + break; + } + for (j = 0; j < watching + 1; j++) { + set_hash_addr(addrs + j * 8, k + start[idxs[i + j]]); + } + + thashx4(bufs[0], bufs[1], bufs[2], bufs[3], + bufs[0], bufs[1], bufs[2], bufs[3], 1, ctx, addrs); } - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_thashx4_1(outx4 + 0 * PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N, - outx4 + 1 * PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N, - outx4 + 2 * PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N, - outx4 + 3 * PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N, - outx4 + 0 * PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N, - outx4 + 1 * PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N, - outx4 + 2 * PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N, - outx4 + 3 * PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N, - pub_seed, addrx4, - state_seeded); } } @@ -109,7 +107,8 @@ static void gen_chainx4(unsigned char *outx4, const unsigned char *inx4, * Interprets an array of bytes as integers in base w. * This only works when log_w is a divisor of 8. */ -static void base_w(unsigned int *output, const int out_len, const unsigned char *input) { +static void base_w(unsigned int *output, const int out_len, + const unsigned char *input) { int in = 0; int out = 0; unsigned char total = 0; @@ -122,119 +121,149 @@ static void base_w(unsigned int *output, const int out_len, const unsigned char in++; bits += 8; } - bits -= PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_WOTS_LOGW; - output[out] = (unsigned int)(total >> bits) & (PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_WOTS_W - 1); + bits -= SPX_WOTS_LOGW; + output[out] = (total >> bits) & (SPX_WOTS_W - 1); out++; } } /* Computes the WOTS+ checksum over a message (in base_w). */ -static void wots_checksum(unsigned int *csum_base_w, const unsigned int *msg_base_w) { +static void wots_checksum(unsigned int *csum_base_w, + const unsigned int *msg_base_w) { unsigned int csum = 0; - unsigned char csum_bytes[(PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_WOTS_LEN2 * PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_WOTS_LOGW + 7) / 8]; + unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; unsigned int i; /* Compute checksum. */ - for (i = 0; i < PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_WOTS_LEN1; i++) { - csum += PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_WOTS_W - 1 - msg_base_w[i]; + for (i = 0; i < SPX_WOTS_LEN1; i++) { + csum += SPX_WOTS_W - 1 - msg_base_w[i]; } /* Convert checksum to base_w. */ /* Make sure expected empty zero bits are the least significant bits. */ - csum = csum << (8 - ((PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_WOTS_LEN2 * PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_WOTS_LOGW) % 8)); - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); - base_w(csum_base_w, PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_WOTS_LEN2, csum_bytes); + csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); + ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); + base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); } /* Takes a message and derives the matching chain lengths. */ -static void chain_lengths(unsigned int *lengths, const unsigned char *msg) { - base_w(lengths, PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_WOTS_LEN1, msg); - wots_checksum(lengths + PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_WOTS_LEN1, lengths); +void chain_lengths(unsigned int *lengths, const unsigned char *msg) { + base_w(lengths, SPX_WOTS_LEN1, msg); + wots_checksum(lengths + SPX_WOTS_LEN1, lengths); } /** - * WOTS key generation. Takes a 32 byte sk_seed, expands it to WOTS private key - * elements and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. * * Writes the computed public key to 'pk'. */ -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_wots_gen_pk(unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *state_seeded) { +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]) { + unsigned int steps[SPX_WOTS_LEN]; + unsigned int start[SPX_WOTS_LEN]; uint32_t i; - unsigned int j; - uint32_t addrx4[4 * 8]; - unsigned char pkbuf[4 * PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N]; + chain_lengths(start, msg); - for (j = 0; j < 4; j++) { - memcpy(addrx4 + j * 8, addr, sizeof(uint32_t) * 8); - } - - /* The last iteration typically does not have complete set of 4 chains, - but because we use pkbuf, this is not an issue -- we still do as many - in parallel as possible. */ - for (i = 0; i < ((PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_WOTS_LEN + 3) & ~0x3); i += 4) { - for (j = 0; j < 4; j++) { - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_set_chain_addr(addrx4 + j * 8, i + j); - } - wots_gen_skx4(pkbuf, sk_seed, addrx4, state_seeded); - gen_chainx4(pkbuf, pkbuf, 0, PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_WOTS_W - 1, pub_seed, addrx4, state_seeded); - for (j = 0; j < 4; j++) { - if (i + j < PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_WOTS_LEN) { - memcpy(pk + (i + j)*PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N, pkbuf + j * PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N, PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N); - } - } + for (i = 0; i < SPX_WOTS_LEN; i++) { + steps[i] = SPX_WOTS_W - 1 - start[i]; } - // Get rid of unused argument variable. - (void)state_seeded; + gen_chains(pk, sig, start, steps, ctx, addr); } -/** - * Takes a n-byte message and the 32-byte sk_see to compute a signature 'sig'. +/* + * This generates 4 sequential WOTS public keys + * It also generates the WOTS signature if leaf_info indicates + * that we're signing with one of these WOTS keys */ -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_wots_sign(unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); +void wots_gen_leafx4(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info) { + struct leaf_info_x4 *info = v_info; + uint32_t *leaf_addr = info->leaf_addr; + uint32_t *pk_addr = info->pk_addr; + unsigned int i, j, k; + unsigned char pk_buffer[ 4 * SPX_WOTS_BYTES ]; + unsigned wots_offset = SPX_WOTS_BYTES; + unsigned char *buffer; + uint32_t wots_k_mask; + unsigned wots_sign_index; + + if (((leaf_idx ^ info->wots_sign_leaf) & ~3U) == 0) { + /* We're traversing the leaf that's signing; generate the WOTS */ + /* signature */ + wots_k_mask = 0; + wots_sign_index = info->wots_sign_leaf & 3; /* Which of of the 4 */ + /* 4 slots do the signatures come from */ + } else { + /* Nope, we're just generating pk's; turn off the signature logic */ + wots_k_mask = (uint32_t)~0; + wots_sign_index = 0; + } - for (i = 0; i < PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_WOTS_LEN; i++) { - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_set_chain_addr(addr, i); - wots_gen_sk(sig + i * PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N, sk_seed, addr, state_seeded); - gen_chain(sig + i * PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N, sig + i * PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N, 0, lengths[i], pub_seed, addr, state_seeded); + for (j = 0; j < 4; j++) { + set_keypair_addr( leaf_addr + j * 8, leaf_idx + j ); + set_keypair_addr( pk_addr + j * 8, leaf_idx + j ); } - // avoid unused argument - (void)state_seeded; -} + for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { + uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k to */ + /* the step if we're generating a signature, ~0 if we're not */ -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_WOTS_LEN]; - uint32_t i; + /* Start with the secret seed */ + for (j = 0; j < 4; j++) { + set_chain_addr(leaf_addr + j * 8, i); + set_hash_addr(leaf_addr + j * 8, 0); + set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTSPRF); + } + prf_addrx4(buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + buffer + 2 * wots_offset, + buffer + 3 * wots_offset, + ctx, leaf_addr); - chain_lengths(lengths, msg); + for (j = 0; j < 4; j++) { + set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTS); + } + + /* Iterate down the WOTS chain */ + for (k = 0;; k++) { + /* Check if one of the values we have needs to be saved as a */ + /* part of the WOTS signature */ + if (k == wots_k) { + memcpy( info->wots_sig + i * SPX_N, + buffer + wots_sign_index * wots_offset, SPX_N ); + } - for (i = 0; i < PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_WOTS_LEN; i++) { - PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_set_chain_addr(addr, i); - gen_chain(pk + i * PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N, sig + i * PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_N, - lengths[i], PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_WOTS_W - 1 - lengths[i], pub_seed, addr, - state_seeded); + /* Check if we hit the top of the chain */ + if (k == SPX_WOTS_W - 1) { + break; + } + + /* Iterate one step on all 4 chains */ + for (j = 0; j < 4; j++) { + set_hash_addr(leaf_addr + j * 8, k); + } + thashx4(buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + buffer + 2 * wots_offset, + buffer + 3 * wots_offset, + buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + buffer + 2 * wots_offset, + buffer + 3 * wots_offset, 1, ctx, leaf_addr); + } } - // avoid unused argument - (void)state_seeded; + /* Do the final thash to generate the public keys */ + thashx4(dest + 0 * SPX_N, + dest + 1 * SPX_N, + dest + 2 * SPX_N, + dest + 3 * SPX_N, + pk_buffer + 0 * wots_offset, + pk_buffer + 1 * wots_offset, + pk_buffer + 2 * wots_offset, + pk_buffer + 3 * wots_offset, SPX_WOTS_LEN, ctx, pk_addr); } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/wots.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/wots.h index cf3daa60b5..4e7692eeef 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/wots.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/wots.h @@ -1,41 +1,25 @@ -#ifndef PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_WOTS_H -#define PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_WOTS_H +#ifndef SPX_WOTS_H +#define SPX_WOTS_H -#include "hash_state.h" -#include "params.h" #include -/** - * WOTS key generation. Takes a 32 byte seed for the private key, expands it to - * a full WOTS private key and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_wots_gen_pk( - unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -/** - * Takes a n-byte message and the 32-byte seed for the private key to compute a - * signature that is placed at 'sig'. - */ -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_wots_sign( - unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *hash_state_seeded); +#include "context.h" +#include "params.h" /** * Takes a WOTS signature and an n-byte message, computes a WOTS public key. * * Writes the computed public key to 'pk'. */ -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_wots_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); +#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]); + +/* + * Compute the chain lengths needed for a given message hash + */ +#define chain_lengths SPX_NAMESPACE(chain_lengths) +void chain_lengths(unsigned int *lengths, const unsigned char *msg); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/wotsx4.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/wotsx4.h new file mode 100644 index 0000000000..cd634f1743 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/wotsx4.h @@ -0,0 +1,41 @@ +#ifndef WOTSX4_H_ +#define WOTSX4_H_ + +#include + +#include "params.h" + +/* + * This is here to provide an interface to the internal wots_gen_leafx4 + * routine. While this routine is not referenced in the package outside of + * wots.c, it is called from the stand-alone benchmark code to characterize + * the performance + */ +struct leaf_info_x4 { + unsigned char *wots_sig; + uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ + uint32_t *wots_steps; + uint32_t leaf_addr[4 * 8]; + uint32_t pk_addr[4 * 8]; +}; + +/* Macro to set the leaf_info to something 'benign', that is, it would */ +/* run with the same time as it does during the real signing process */ +/* Used only by the benchmark code */ +#define INITIALIZE_LEAF_INFO_X4(info, addr, step_buffer) { \ + (info).wots_sig = 0; \ + (info).wots_sign_leaf = ~0; \ + (info).wots_steps = step_buffer; \ + int i; \ + for (i=0; i<4; i++) { \ + memcpy( &(info).leaf_addr[8*i], addr, 32 ); \ + memcpy( &(info).pk_addr[8*i], addr, 32 ); \ + } \ + } + +#define wots_gen_leafx4 SPX_NAMESPACE(wots_gen_leafx4) +void wots_gen_leafx4(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info); + +#endif /* WOTSX4_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/address.c b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/address.c index 1ce4c0d97f..b956e9cb29 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/address.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/address.c @@ -1,78 +1,91 @@ #include +#include #include "address.h" #include "params.h" #include "utils.h" -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]) { - int i; - - for (i = 0; i < 8; i++) { - PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_ull_to_bytes( - bytes + i * 4, 4, addr[i]); - } -} - -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_set_layer_addr( - uint32_t addr[8], uint32_t layer) { - addr[0] = layer; +/* + * Specify which level of Merkle tree (the "layer") we're working on + */ +void set_layer_addr(uint32_t addr[8], uint32_t layer) { + ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; } -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_set_tree_addr( - uint32_t addr[8], uint64_t tree) { - addr[1] = 0; - addr[2] = (uint32_t) (tree >> 32); - addr[3] = (uint32_t) tree; +/* + * Specify which Merkle tree within the level (the "tree address") we're working on + */ +void set_tree_addr(uint32_t addr[8], uint64_t tree) { + ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); } -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_set_type( - uint32_t addr[8], uint32_t type) { - addr[4] = type; +/* + * Specify the reason we'll use this address structure for, that is, what + * hash will we compute with it. This is used so that unrelated types of + * hashes don't accidentally get the same address structure. The type will be + * one of the SPX_ADDR_TYPE constants + */ +void set_type(uint32_t addr[8], uint32_t type) { + ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; } -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; +/* + * Copy the layer and tree fields of the address structure. This is used + * when we're doing multiple types of hashes within the same Merkle tree + */ +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); } /* These functions are used for OTS addresses. */ -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_set_keypair_addr( - uint32_t addr[8], uint32_t keypair) { - addr[5] = keypair; +/* + * Specify which Merkle leaf we're working on; that is, which OTS keypair + * we're talking about. + */ +void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { + ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; } -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; - out[5] = in[5]; +/* + * Copy the layer, tree and keypair fields of the address structure. This is + * used when we're doing multiple things within the same OTS keypair + */ +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); + ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; } -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_set_chain_addr( - uint32_t addr[8], uint32_t chain) { - addr[6] = chain; +/* + * Specify which Merkle chain within the OTS we're working with + * (the chain address) + */ +void set_chain_addr(uint32_t addr[8], uint32_t chain) { + ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; } -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_set_hash_addr( - uint32_t addr[8], uint32_t hash) { - addr[7] = hash; +/* + * Specify where in the Merkle chain we are +* (the hash address) + */ +void set_hash_addr(uint32_t addr[8], uint32_t hash) { + ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; } /* These functions are used for all hash tree addresses (including FORS). */ -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_set_tree_height( - uint32_t addr[8], uint32_t tree_height) { - addr[6] = tree_height; +/* + * Specify the height of the node in the Merkle/FORS tree we are in + * (the tree height) + */ +void set_tree_height(uint32_t addr[8], uint32_t tree_height) { + ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; } -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_set_tree_index( - uint32_t addr[8], uint32_t tree_index) { - addr[7] = tree_index; +/* + * Specify the distance from the left edge of the node in the Merkle/FORS tree + * (the tree index) + */ +void set_tree_index(uint32_t addr[8], uint32_t tree_index) { + u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/address.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/address.h index 6e50c2dafc..24a84eb40c 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/address.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/address.h @@ -1,50 +1,52 @@ -#ifndef PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_ADDRESS_H -#define PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_ADDRESS_H +#ifndef SPX_ADDRESS_H +#define SPX_ADDRESS_H #include -#define PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_ADDR_TYPE_WOTS 0 -#define PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_ADDR_TYPE_WOTSPK 1 -#define PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_ADDR_TYPE_HASHTREE 2 -#define PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_ADDR_TYPE_FORSTREE 3 -#define PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_ADDR_TYPE_FORSPK 4 +#include "params.h" -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]); +/* The hash types that are passed to set_type */ +#define SPX_ADDR_TYPE_WOTS 0 +#define SPX_ADDR_TYPE_WOTSPK 1 +#define SPX_ADDR_TYPE_HASHTREE 2 +#define SPX_ADDR_TYPE_FORSTREE 3 +#define SPX_ADDR_TYPE_FORSPK 4 +#define SPX_ADDR_TYPE_WOTSPRF 5 +#define SPX_ADDR_TYPE_FORSPRF 6 -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_set_layer_addr( - uint32_t addr[8], uint32_t layer); +#define set_layer_addr SPX_NAMESPACE(set_layer_addr) +void set_layer_addr(uint32_t addr[8], uint32_t layer); -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_set_tree_addr( - uint32_t addr[8], uint64_t tree); +#define set_tree_addr SPX_NAMESPACE(set_tree_addr) +void set_tree_addr(uint32_t addr[8], uint64_t tree); -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_set_type( - uint32_t addr[8], uint32_t type); +#define set_type SPX_NAMESPACE(set_type) +void set_type(uint32_t addr[8], uint32_t type); /* Copies the layer and tree part of one address into the other */ -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]); +#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); /* These functions are used for WOTS and FORS addresses. */ -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_set_keypair_addr( - uint32_t addr[8], uint32_t keypair); +#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) +void set_keypair_addr(uint32_t addr[8], uint32_t keypair); -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_set_chain_addr( - uint32_t addr[8], uint32_t chain); +#define set_chain_addr SPX_NAMESPACE(set_chain_addr) +void set_chain_addr(uint32_t addr[8], uint32_t chain); -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_set_hash_addr( - uint32_t addr[8], uint32_t hash); +#define set_hash_addr SPX_NAMESPACE(set_hash_addr) +void set_hash_addr(uint32_t addr[8], uint32_t hash); -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]); +#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); /* These functions are used for all hash tree addresses (including FORS). */ -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_set_tree_height( - uint32_t addr[8], uint32_t tree_height); +#define set_tree_height SPX_NAMESPACE(set_tree_height) +void set_tree_height(uint32_t addr[8], uint32_t tree_height); -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_set_tree_index( - uint32_t addr[8], uint32_t tree_index); +#define set_tree_index SPX_NAMESPACE(set_tree_index) +void set_tree_index(uint32_t addr[8], uint32_t tree_index); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/api.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/api.h index 135cc297cb..ee94b774bf 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/api.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/api.h @@ -4,15 +4,13 @@ #include #include - - -#define PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_CRYPTO_ALGNAME "SPHINCS+" +#define PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_CRYPTO_ALGNAME "SPHINCS+-haraka-256f-simple" #define PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_CRYPTO_SECRETKEYBYTES 128 #define PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_CRYPTO_PUBLICKEYBYTES 64 -#define PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_CRYPTO_BYTES 49856 -#define PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_CRYPTO_SEEDBYTES 96 +#define PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_CRYPTO_BYTES 49856 +#define PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_CRYPTO_SEEDBYTES 96 /* * Returns the length of a secret key, in bytes @@ -39,43 +37,41 @@ size_t PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_crypto_sign_seedbytes(void); * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] * Format pk: [root || PUB_SEED] */ -int PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed); +int PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); /* * Generates a SPHINCS+ key pair. * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] * Format pk: [root || PUB_SEED] */ -int PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk); +int PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); /** * Returns an array containing a detached signature. */ -int PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk); +int PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); /** * Verifies a detached signature and message under a given public key. */ -int PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk); +int PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, + const uint8_t *pk); /** * Returns an array containing the signature followed by the message. */ -int PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk); +int PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); /** * Verifies a given signature-message pair under a given public key. */ -int PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk); - +int PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/context.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/context.h new file mode 100644 index 0000000000..600dfb73c7 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/context.h @@ -0,0 +1,24 @@ +#ifndef SPX_CONTEXT_H +#define SPX_CONTEXT_H + +#include +#include + +#include "params.h" + +typedef struct { + uint8_t pub_seed[SPX_N]; + uint8_t sk_seed[SPX_N]; + + + uint64_t tweaked512_rc64[10][8]; + uint32_t tweaked256_rc32[10][8]; +} spx_ctx; + +#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) +void initialize_hash_function(spx_ctx *ctx); + +#define free_hash_function SPX_NAMESPACE(free_hash_function) +void free_hash_function(spx_ctx *ctx); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/context_haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/context_haraka.c new file mode 100644 index 0000000000..f1cd7e3664 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/context_haraka.c @@ -0,0 +1,11 @@ +#include "context.h" +#include "haraka.h" + +void initialize_hash_function(spx_ctx *ctx) { + tweak_constants(ctx); +} + +// we don't support heap-based haraka right now +void free_hash_function(spx_ctx *ctx) { + (void)ctx; // suppress unused variable warnings +} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/fors.c b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/fors.c index ee2a1f7c12..96ca72e986 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/fors.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/fors.c @@ -2,58 +2,58 @@ #include #include -#include "address.h" #include "fors.h" + +#include "address.h" #include "hash.h" -#include "hash_state.h" #include "thash.h" #include "utils.h" +#include "utilsx1.h" -static void fors_gen_sk(unsigned char *sk, const unsigned char *sk_seed, - uint32_t fors_leaf_addr[8], const hash_state *hash_state_seeded) { - PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_prf_addr( - sk, sk_seed, fors_leaf_addr, hash_state_seeded); +static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + prf_addr(sk, ctx, fors_leaf_addr); } static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, - const unsigned char *pub_seed, - uint32_t fors_leaf_addr[8], - const hash_state *hash_state_seeded) { - PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_thash_1( - leaf, sk, pub_seed, fors_leaf_addr, hash_state_seeded); + const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + thash(leaf, sk, 1, ctx, fors_leaf_addr); } -static void fors_gen_leaf(unsigned char *leaf, const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx, const uint32_t fors_tree_addr[8], - const hash_state *hash_state_seeded) { - uint32_t fors_leaf_addr[8] = {0}; - - /* Only copy the parts that must be kept in fors_leaf_addr. */ - PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_copy_keypair_addr( - fors_leaf_addr, fors_tree_addr); - PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_set_type( - fors_leaf_addr, PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_set_tree_index( - fors_leaf_addr, addr_idx); - - fors_gen_sk(leaf, sk_seed, fors_leaf_addr, hash_state_seeded); - fors_sk_to_leaf(leaf, leaf, pub_seed, fors_leaf_addr, hash_state_seeded); +struct fors_gen_leaf_info { + uint32_t leaf_addrx[8]; +}; + +static void fors_gen_leafx1(unsigned char *leaf, + const spx_ctx *ctx, + uint32_t addr_idx, void *info) { + struct fors_gen_leaf_info *fors_info = info; + uint32_t *fors_leaf_addr = fors_info->leaf_addrx; + + /* Only set the parts that the caller doesn't set */ + set_tree_index(fors_leaf_addr, addr_idx); + set_type(fors_leaf_addr, SPX_ADDR_TYPE_FORSPRF); + fors_gen_sk(leaf, ctx, fors_leaf_addr); + + set_type(fors_leaf_addr, SPX_ADDR_TYPE_FORSTREE); + fors_sk_to_leaf(leaf, leaf, + ctx, fors_leaf_addr); } /** - * Interprets m as PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_FORS_HEIGHT-bit unsigned integers. - * Assumes m contains at least PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_FORS_TREES bits. - * Assumes indices has space for PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_FORS_TREES integers. + * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + * Assumes indices has space for SPX_FORS_TREES integers. */ static void message_to_indices(uint32_t *indices, const unsigned char *m) { unsigned int i, j; unsigned int offset = 0; - for (i = 0; i < PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_FORS_TREES; i++) { + for (i = 0; i < SPX_FORS_TREES; i++) { indices[i] = 0; - for (j = 0; j < PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_FORS_HEIGHT; j++) { - indices[i] ^= (((uint32_t)m[offset >> 3] >> (offset & 0x7)) & 0x1) << j; + for (j = 0; j < SPX_FORS_HEIGHT; j++) { + indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); offset++; } } @@ -61,55 +61,51 @@ static void message_to_indices(uint32_t *indices, const unsigned char *m) { /** * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_FORS_TREES bits. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. */ -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_fors_sign( - unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *hash_state_seeded) { - uint32_t indices[PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_FORS_TREES]; - unsigned char roots[PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_FORS_TREES * PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_N]; +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; uint32_t fors_tree_addr[8] = {0}; + struct fors_gen_leaf_info fors_info = {0}; + uint32_t *fors_leaf_addr = fors_info.leaf_addrx; uint32_t fors_pk_addr[8] = {0}; uint32_t idx_offset; unsigned int i; - PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_copy_keypair_addr( - fors_tree_addr, fors_addr); - PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_copy_keypair_addr( - fors_pk_addr, fors_addr); + copy_keypair_addr(fors_tree_addr, fors_addr); + copy_keypair_addr(fors_leaf_addr, fors_addr); - PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_set_type( - fors_tree_addr, PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_set_type( - fors_pk_addr, PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_ADDR_TYPE_FORSPK); + copy_keypair_addr(fors_pk_addr, fors_addr); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); message_to_indices(indices, m); - for (i = 0; i < PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_FORS_TREES; i++) { - idx_offset = i * (1 << PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_FORS_HEIGHT); + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); - PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_set_tree_height( - fors_tree_addr, 0); - PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_set_tree_index( - fors_tree_addr, indices[i] + idx_offset); + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); /* Include the secret key part that produces the selected leaf node. */ - fors_gen_sk(sig, sk_seed, fors_tree_addr, hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_N; + fors_gen_sk(sig, ctx, fors_tree_addr); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + sig += SPX_N; /* Compute the authentication path for this leaf node. */ - PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_treehash_FORS_HEIGHT( - roots + i * PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_N, sig, sk_seed, pub_seed, - indices[i], idx_offset, fors_gen_leaf, fors_tree_addr, - hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_N * PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_FORS_HEIGHT; + treehashx1(roots + i * SPX_N, sig, ctx, + indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx1, + fors_tree_addr, &fors_info); + + sig += SPX_N * SPX_FORS_HEIGHT; } /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_thash_FORS_TREES( - pk, roots, pub_seed, fors_pk_addr, hash_state_seeded); + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); } /** @@ -117,45 +113,44 @@ void PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_fors_sign( * This can be used for verification by comparing to a known public key, or to * subsequently verify a signature on the derived public key. The latter is the * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_FORS_TREES bits. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. */ -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_fors_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, const uint32_t fors_addr[8], - const hash_state *hash_state_seeded) { - uint32_t indices[PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_FORS_TREES]; - unsigned char roots[PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_FORS_TREES * PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_N]; - unsigned char leaf[PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_N]; +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + unsigned char leaf[SPX_N]; uint32_t fors_tree_addr[8] = {0}; uint32_t fors_pk_addr[8] = {0}; uint32_t idx_offset; unsigned int i; - PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_copy_keypair_addr(fors_tree_addr, fors_addr); - PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_copy_keypair_addr(fors_pk_addr, fors_addr); + copy_keypair_addr(fors_tree_addr, fors_addr); + copy_keypair_addr(fors_pk_addr, fors_addr); - PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_set_type(fors_tree_addr, PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_set_type(fors_pk_addr, PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_ADDR_TYPE_FORSPK); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); message_to_indices(indices, m); - for (i = 0; i < PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_FORS_TREES; i++) { - idx_offset = i * (1 << PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_FORS_HEIGHT); + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); - PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_set_tree_height(fors_tree_addr, 0); - PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_set_tree_index(fors_tree_addr, indices[i] + idx_offset); + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); /* Derive the leaf from the included secret key part. */ - fors_sk_to_leaf(leaf, sig, pub_seed, fors_tree_addr, hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_N; + fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); + sig += SPX_N; /* Derive the corresponding root node of this tree. */ - PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_compute_root(roots + i * PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_N, leaf, indices[i], idx_offset, sig, - PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_FORS_HEIGHT, pub_seed, fors_tree_addr, hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_N * PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_FORS_HEIGHT; + compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, + sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); + sig += SPX_N * SPX_FORS_HEIGHT; } /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_thash_FORS_TREES(pk, roots, pub_seed, fors_pk_addr, hash_state_seeded); + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/fors.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/fors.h index d51016ddb0..509140a178 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/fors.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/fors.h @@ -1,32 +1,32 @@ -#ifndef PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_FORS_H -#define PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_FORS_H +#ifndef SPX_FORS_H +#define SPX_FORS_H #include -#include "hash_state.h" +#include "context.h" #include "params.h" /** * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_FORS_TREES bits. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. */ -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_fors_sign( - unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *hash_state_seeded); +#define fors_sign SPX_NAMESPACE(fors_sign) +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); /** * Derives the FORS public key from a signature. * This can be used for verification by comparing to a known public key, or to * subsequently verify a signature on the derived public key. The latter is the * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_FORS_TREES bits. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. */ -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_fors_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, const uint32_t fors_addr[8], - const hash_state *hash_state_seeded); +#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/haraka.c index 4168c4c7f1..a4944913b5 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/haraka.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/haraka.c @@ -6,12 +6,13 @@ * by Thomas Pornin */ -#include #include +#include #include #include #include "haraka.h" +#include "utils.h" #define HARAKAS_RATE 32 @@ -656,76 +657,62 @@ static void interleave_constant32(uint32_t *out, const unsigned char *in) { br_aes_ct_ortho(out); } -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_tweak_constants( - harakactx *state, - const unsigned char *pk_seed, const unsigned char *sk_seed, - unsigned long long seed_length) { +void tweak_constants(spx_ctx *ctx) { unsigned char buf[40 * 16]; int i; /* Use the standard constants to generate tweaked ones. */ - memcpy((uint8_t *)state->tweaked512_rc64, (uint8_t *)haraka512_rc64, 40 * 16); - - /* Constants for sk.seed */ - if (sk_seed != NULL) { - PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_haraka_S( - buf, 40 * 16, sk_seed, seed_length, state); - - /* Interleave constants */ - for (i = 0; i < 10; i++) { - interleave_constant32(state->tweaked256_rc32_sseed[i], buf + 32 * i); - } - } + memcpy((uint8_t *)ctx->tweaked512_rc64, (uint8_t *)haraka512_rc64, 40 * 16); /* Constants for pk.seed */ - PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_haraka_S( - buf, 40 * 16, pk_seed, seed_length, state); + haraka_S(buf, 40 * 16, ctx->pub_seed, SPX_N, ctx); for (i = 0; i < 10; i++) { - interleave_constant32(state->tweaked256_rc32[i], buf + 32 * i); - interleave_constant(state->tweaked512_rc64[i], buf + 64 * i); + interleave_constant32(ctx->tweaked256_rc32[i], buf + 32 * i); + interleave_constant(ctx->tweaked512_rc64[i], buf + 64 * i); } } -static void haraka_S_absorb(unsigned char *s, +static void haraka_S_absorb(unsigned char *s, unsigned int r, const unsigned char *m, unsigned long long mlen, - unsigned char p, const harakactx *state) { + unsigned char p, const spx_ctx *ctx) { unsigned long long i; - unsigned char t[HARAKAS_RATE]; + PQCLEAN_VLA(uint8_t, t, r); - while (mlen >= HARAKAS_RATE) { + while (mlen >= r) { /* XOR block to state */ - for (i = 0; i < HARAKAS_RATE; ++i) { + for (i = 0; i < r; ++i) { s[i] ^= m[i]; } - PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_haraka512_perm(s, s, state); - mlen -= HARAKAS_RATE; - m += HARAKAS_RATE; + haraka512_perm(s, s, ctx); + mlen -= r; + m += r; } - for (i = 0; i < HARAKAS_RATE; ++i) { + for (i = 0; i < r; ++i) { t[i] = 0; } for (i = 0; i < mlen; ++i) { t[i] = m[i]; } t[i] = p; - t[HARAKAS_RATE - 1] |= 128; - for (i = 0; i < HARAKAS_RATE; ++i) { + t[r - 1] |= 128; + for (i = 0; i < r; ++i) { s[i] ^= t[i]; } } static void haraka_S_squeezeblocks(unsigned char *h, unsigned long long nblocks, - unsigned char *s, const harakactx *state) { + unsigned char *s, unsigned int r, + const spx_ctx *ctx) { while (nblocks > 0) { - PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_haraka512_perm(s, s, state); + haraka512_perm(s, s, ctx); memcpy(h, s, HARAKAS_RATE); - h += HARAKAS_RATE; + h += r; nblocks--; } } -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_haraka_S_inc_init(uint8_t *s_inc) { +void haraka_S_inc_init(uint8_t *s_inc) { size_t i; for (i = 0; i < 64; i++) { @@ -734,7 +721,8 @@ void PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_haraka_S_inc_init(uint8_t *s_inc) { s_inc[64] = 0; } -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, const harakactx *state) { +void haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, + const spx_ctx *ctx) { size_t i; /* Recall that s_inc[64] is the non-absorbed bytes xored into the state */ @@ -745,19 +733,19 @@ void PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_haraka_S_inc_absorb(uint8_t *s_inc, c s_inc[s_inc[64] + i] ^= m[i]; } mlen -= (size_t)(HARAKAS_RATE - s_inc[64]); - m += HARAKAS_RATE - s_inc[64]; + m += HARAKAS_RATE - (uint8_t)s_inc[64]; s_inc[64] = 0; - PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_haraka512_perm(s_inc, s_inc, state); + haraka512_perm(s_inc, s_inc, ctx); } for (i = 0; i < mlen; i++) { s_inc[s_inc[64] + i] ^= m[i]; } - s_inc[64] = (uint8_t)(mlen + s_inc[64]); + s_inc[64] += (uint8_t)mlen; } -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_haraka_S_inc_finalize(uint8_t *s_inc) { +void haraka_S_inc_finalize(uint8_t *s_inc) { /* After haraka_S_inc_absorb, we are guaranteed that s_inc[64] < HARAKAS_RATE, so we can always use one more byte for p in the current state. */ s_inc[s_inc[64]] ^= 0x1F; @@ -765,22 +753,23 @@ void PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_haraka_S_inc_finalize(uint8_t *s_inc) s_inc[64] = 0; } -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, const harakactx *state) { - uint8_t i; +void haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, + const spx_ctx *ctx) { + size_t i; /* First consume any bytes we still have sitting around */ for (i = 0; i < outlen && i < s_inc[64]; i++) { /* There are s_inc[64] bytes left, so r - s_inc[64] is the first available byte. We consume from there, i.e., up to r. */ - out[i] = s_inc[(HARAKAS_RATE - s_inc[64] + i)]; + out[i] = (uint8_t)s_inc[(HARAKAS_RATE - s_inc[64] + i)]; } out += i; outlen -= i; - s_inc[64] = (uint8_t)(s_inc[64] - i); + s_inc[64] -= (uint8_t)i; /* Then squeeze the remaining necessary blocks */ while (outlen > 0) { - PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_haraka512_perm(s_inc, s_inc, state); + haraka512_perm(s_inc, s_inc, ctx); for (i = 0; i < outlen && i < HARAKAS_RATE; i++) { out[i] = s_inc[i]; @@ -791,7 +780,9 @@ void PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_haraka_S_inc_squeeze(uint8_t *out, si } } -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_haraka_S(unsigned char *out, unsigned long long outlen, const unsigned char *in, unsigned long long inlen, const harakactx *state) { +void haraka_S(unsigned char *out, unsigned long long outlen, + const unsigned char *in, unsigned long long inlen, + const spx_ctx *ctx) { unsigned long long i; unsigned char s[64]; unsigned char d[32]; @@ -799,20 +790,21 @@ void PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_haraka_S(unsigned char *out, unsigned for (i = 0; i < 64; i++) { s[i] = 0; } - haraka_S_absorb(s, in, inlen, 0x1F, state); + haraka_S_absorb(s, 32, in, inlen, 0x1F, ctx); - haraka_S_squeezeblocks(out, outlen / 32, s, state); + haraka_S_squeezeblocks(out, outlen / 32, s, 32, ctx); out += (outlen / 32) * 32; if (outlen % 32) { - haraka_S_squeezeblocks(d, 1, s, state); + haraka_S_squeezeblocks(d, 1, s, 32, ctx); for (i = 0; i < outlen % 32; i++) { out[i] = d[i]; } } } -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_haraka512_perm(unsigned char *out, const unsigned char *in, const harakactx *state) { +void haraka512_perm(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx) { uint32_t w[16]; uint64_t q[8], tmp_q; unsigned int i, j; @@ -829,7 +821,7 @@ void PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_haraka512_perm(unsigned char *out, co br_aes_ct64_bitslice_Sbox(q); shift_rows(q); mix_columns(q); - add_round_key(q, state->tweaked512_rc64[2 * i + j]); + add_round_key(q, ctx->tweaked512_rc64[2 * i + j]); } /* Mix states */ for (j = 0; j < 8; j++) { @@ -857,12 +849,12 @@ void PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_haraka512_perm(unsigned char *out, co br_range_enc32le(out, w, 16); } -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_haraka512(unsigned char *out, const unsigned char *in, const harakactx *state) { +void haraka512(unsigned char *out, const unsigned char *in, const spx_ctx *ctx) { int i; unsigned char buf[64]; - PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_haraka512_perm(buf, in, state); + haraka512_perm(buf, in, ctx); /* Feed-forward */ for (i = 0; i < 64; i++) { buf[i] = buf[i] ^ in[i]; @@ -876,50 +868,8 @@ void PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_haraka512(unsigned char *out, const u } -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_haraka256(unsigned char *out, const unsigned char *in, const harakactx *state) { - uint32_t q[8], tmp_q; - int i, j; - - for (i = 0; i < 4; i++) { - q[2 * i] = br_dec32le(in + 4 * i); - q[2 * i + 1] = br_dec32le(in + 4 * i + 16); - } - br_aes_ct_ortho(q); - - /* AES rounds */ - for (i = 0; i < 5; i++) { - for (j = 0; j < 2; j++) { - br_aes_ct_bitslice_Sbox(q); - shift_rows32(q); - mix_columns32(q); - add_round_key32(q, state->tweaked256_rc32[2 * i + j]); - } - - /* Mix states */ - for (j = 0; j < 8; j++) { - tmp_q = q[j]; - q[j] = (tmp_q & 0x81818181) | - (tmp_q & 0x02020202) << 1 | - (tmp_q & 0x04040404) << 2 | - (tmp_q & 0x08080808) << 3 | - (tmp_q & 0x10101010) >> 3 | - (tmp_q & 0x20202020) >> 2 | - (tmp_q & 0x40404040) >> 1; - } - } - - br_aes_ct_ortho(q); - for (i = 0; i < 4; i++) { - br_enc32le(out + 4 * i, q[2 * i]); - br_enc32le(out + 4 * i + 16, q[2 * i + 1]); - } - - for (i = 0; i < 32; i++) { - out[i] ^= in[i]; - } -} - -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_haraka256_sk(unsigned char *out, const unsigned char *in, const harakactx *state) { +void haraka256(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx) { uint32_t q[8], tmp_q; int i, j; @@ -935,7 +885,7 @@ void PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_haraka256_sk(unsigned char *out, cons br_aes_ct_bitslice_Sbox(q); shift_rows32(q); mix_columns32(q); - add_round_key32(q, state->tweaked256_rc32_sseed[2 * i + j]); + add_round_key32(q, ctx->tweaked256_rc32[2 * i + j]); } /* Mix states */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/haraka.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/haraka.h index 5588763bc9..737cb6065f 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/haraka.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/haraka.h @@ -1,40 +1,42 @@ -#ifndef PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_HARAKA_H -#define PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_HARAKA_H +#ifndef SPX_HARAKA_H +#define SPX_HARAKA_H -#include -#include - -typedef struct { - uint64_t tweaked512_rc64[10][8]; - uint32_t tweaked256_rc32[10][8]; - uint32_t tweaked256_rc32_sseed[10][8]; -} harakactx; +#include "context.h" +#include "params.h" /* Tweak constants with seed */ -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_tweak_constants( - harakactx *state, - const unsigned char *pk_seed, const unsigned char *sk_seed, - unsigned long long seed_length); +#define tweak_constants SPX_NAMESPACE(tweak_constants) +void tweak_constants(spx_ctx *ctx); /* Haraka Sponge */ -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_haraka_S_inc_init(uint8_t *s_inc); -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, const harakactx *state); -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_haraka_S_inc_finalize(uint8_t *s_inc); -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, const harakactx *state); -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_haraka_S( - unsigned char *out, unsigned long long outlen, - const unsigned char *in, unsigned long long inlen, const harakactx *state); +#define haraka_S_inc_init SPX_NAMESPACE(haraka_S_inc_init) +void haraka_S_inc_init(uint8_t *s_inc); +#define haraka_S_inc_absorb SPX_NAMESPACE(haraka_S_inc_absorb) +void haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, + const spx_ctx *ctx); +#define haraka_S_inc_finalize SPX_NAMESPACE(haraka_S_inc_finalize) +void haraka_S_inc_finalize(uint8_t *s_inc); +#define haraka_S_inc_squeeze SPX_NAMESPACE(haraka_S_inc_squeeze) +void haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, + const spx_ctx *ctx); +#define haraka_S SPX_NAMESPACE(haraka_S) +void haraka_S(unsigned char *out, unsigned long long outlen, + const unsigned char *in, unsigned long long inlen, + const spx_ctx *ctx); /* Applies the 512-bit Haraka permutation to in. */ -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_haraka512_perm(unsigned char *out, const unsigned char *in, const harakactx *state); +#define haraka512_perm SPX_NAMESPACE(haraka512_perm) +void haraka512_perm(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx); /* Implementation of Haraka-512 */ -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_haraka512(unsigned char *out, const unsigned char *in, const harakactx *state); +#define haraka512 SPX_NAMESPACE(haraka512) +void haraka512(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx); /* Implementation of Haraka-256 */ -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_haraka256(unsigned char *out, const unsigned char *in, const harakactx *state); - -/* Implementation of Haraka-256 using sk.seed constants */ -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_haraka256_sk(unsigned char *out, const unsigned char *in, const harakactx *state); +#define haraka256 SPX_NAMESPACE(haraka256) +void haraka256(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/haraka_offsets.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/haraka_offsets.h new file mode 100644 index 0000000000..7c062272a0 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/haraka_offsets.h @@ -0,0 +1,21 @@ +#ifndef HARAKA_OFFSETS_H_ +#define HARAKA_OFFSETS_H_ + +/* + * Offsets of various fields in the address structure when we use Haraka as + * the Sphincs+ hash function + */ + +#define SPX_OFFSET_LAYER 3 /* The byte used to specify the Merkle tree layer */ +#define SPX_OFFSET_TREE 8 /* The start of the 8 byte field used to specify the tree */ +#define SPX_OFFSET_TYPE 19 /* The byte used to specify the hash type (reason) */ +#define SPX_OFFSET_KP_ADDR2 22 /* The high byte used to specify the key pair (which one-time signature) */ +#define SPX_OFFSET_KP_ADDR1 23 /* The low byte used to specify the key pair */ +#define SPX_OFFSET_CHAIN_ADDR 27 /* The byte used to specify the chain address (which Winternitz chain) */ +#define SPX_OFFSET_HASH_ADDR 31 /* The byte used to specify the hash address (where in the Winternitz chain) */ +#define SPX_OFFSET_TREE_HGT 27 /* The byte used to specify the height of this node in the FORS or Merkle tree */ +#define SPX_OFFSET_TREE_INDEX 28 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ + +#define SPX_HARAKA 1 + +#endif /* HARAKA_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/hash.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/hash.h index 15cd5a7ea0..f7c87d4c3c 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/hash.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/hash.h @@ -1,31 +1,28 @@ -#ifndef PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_HASH_H -#define PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_HASH_H - -#include "hash_state.h" +#ifndef SPX_HASH_H +#define SPX_HASH_H #include #include -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_initialize_hash_function( - hash_state *hash_state_seeded, - const unsigned char *pub_seed, const unsigned char *sk_seed); +#include "context.h" +#include "params.h" + +#define prf_addr SPX_NAMESPACE(prf_addr) +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]); -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_destroy_hash_function(hash_state *hash_state_seeded); +#define gen_message_random SPX_NAMESPACE(gen_message_random) +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded); +#define hash_message SPX_NAMESPACE(hash_message) +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/hash_haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/hash_haraka.c index da320bd2ee..750a67423b 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/hash_haraka.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/hash_haraka.c @@ -2,58 +2,44 @@ #include #include "address.h" -#include "haraka.h" -#include "hash.h" #include "params.h" #include "utils.h" -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_initialize_hash_function( - hash_state *hash_state_seeded, - const unsigned char *pub_seed, const unsigned char *sk_seed) { - PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_tweak_constants(hash_state_seeded, pub_seed, sk_seed, PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_N); -} - -/* The haraka implementation is stack based and won't be replaced in PQClean/OQS, - so we don't need to do anything */ -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_destroy_hash_function( - hash_state *hash_state_seeded) { // NOLINT(readability-non-const-parameter) - (void)hash_state_seeded; -} +#include "haraka.h" +#include "hash.h" /* - * Computes PRF(key, addr), given a secret key of PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_N bytes and an address + * Computes PRF(key, addr), given a secret key of SPX_N bytes and an address */ -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded) { - unsigned char buf[PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_ADDR_BYTES]; - /* Since PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_N may be smaller than 32, we need a temporary buffer. */ +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]) { + /* Since SPX_N may be smaller than 32, we need temporary buffers. */ unsigned char outbuf[32]; + unsigned char buf[64] = {0}; - (void)key; /* Suppress an 'unused parameter' warning. */ + memcpy(buf, addr, SPX_ADDR_BYTES); + memcpy(buf + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); - PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_addr_to_bytes(buf, addr); - PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_haraka256_sk(outbuf, buf, hash_state_seeded); - memcpy(out, outbuf, PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_N); + haraka512(outbuf, (const void *)buf, ctx); + memcpy(out, outbuf, SPX_N); } /** * Computes the message-dependent randomness R, using a secret seed and an * optional randomization value as well as the message. */ -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded) { +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { uint8_t s_inc[65]; - PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_haraka_S_inc_init(s_inc); - PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_haraka_S_inc_absorb(s_inc, sk_prf, PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_N, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_haraka_S_inc_absorb(s_inc, optrand, PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_N, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_haraka_S_inc_absorb(s_inc, m, mlen, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_haraka_S_inc_finalize(s_inc); - PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_haraka_S_inc_squeeze(R, PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_N, s_inc, hash_state_seeded); + haraka_S_inc_init(s_inc); + haraka_S_inc_absorb(s_inc, sk_prf, SPX_N, ctx); + haraka_S_inc_absorb(s_inc, optrand, SPX_N, ctx); + haraka_S_inc_absorb(s_inc, m, mlen, ctx); + haraka_S_inc_finalize(s_inc); + haraka_S_inc_squeeze(R, SPX_N, s_inc, ctx); } /** @@ -61,36 +47,35 @@ void PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_gen_message_random( * Outputs the message digest and the index of the leaf. The index is split in * the tree index and the leaf index, for convenient copying to an address. */ -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded) { -#define PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_TREE_BITS (PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_TREE_HEIGHT * (PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_D - 1)) -#define PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_TREE_BYTES ((PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_TREE_BITS + 7) / 8) -#define PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_LEAF_BITS PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_TREE_HEIGHT -#define PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_LEAF_BYTES ((PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_LEAF_BITS + 7) / 8) -#define PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_DGST_BYTES (PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_FORS_MSG_BYTES + PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_TREE_BYTES + PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_LEAF_BYTES) +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { +#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) +#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) +#define SPX_LEAF_BITS SPX_TREE_HEIGHT +#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) +#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) - unsigned char buf[PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_DGST_BYTES]; + unsigned char buf[SPX_DGST_BYTES]; unsigned char *bufp = buf; uint8_t s_inc[65]; - PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_haraka_S_inc_init(s_inc); - PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_haraka_S_inc_absorb(s_inc, R, PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_N, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_haraka_S_inc_absorb(s_inc, pk + PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_N, PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_N, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_haraka_S_inc_absorb(s_inc, m, mlen, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_haraka_S_inc_finalize(s_inc); - PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_haraka_S_inc_squeeze(buf, PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_DGST_BYTES, s_inc, hash_state_seeded); + haraka_S_inc_init(s_inc); + haraka_S_inc_absorb(s_inc, R, SPX_N, ctx); + haraka_S_inc_absorb(s_inc, pk + SPX_N, SPX_N, ctx); // Only absorb root part of pk + haraka_S_inc_absorb(s_inc, m, mlen, ctx); + haraka_S_inc_finalize(s_inc); + haraka_S_inc_squeeze(buf, SPX_DGST_BYTES, s_inc, ctx); + + memcpy(digest, bufp, SPX_FORS_MSG_BYTES); + bufp += SPX_FORS_MSG_BYTES; - memcpy(digest, bufp, PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_FORS_MSG_BYTES); - bufp += PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_FORS_MSG_BYTES; - *tree = PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_bytes_to_ull(bufp, PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_TREE_BYTES); - *tree &= (~(uint64_t)0) >> (64 - PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_TREE_BITS); - bufp += PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_TREE_BYTES; + *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); + *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); + bufp += SPX_TREE_BYTES; - *leaf_idx = (uint32_t)PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_bytes_to_ull( - bufp, PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_LEAF_BYTES); - *leaf_idx &= (~(uint32_t)0) >> (32 - PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_LEAF_BITS); + *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); + *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/hash_state.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/hash_state.h deleted file mode 100644 index 5adb1d9a22..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/hash_state.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef SPX_HASH_STATE_H -#define SPX_HASH_STATE_H - -/** - * Defines the type of the hash function state. - * - * Don't be fooled into thinking this instance of SPHINCS+ isn't stateless! - * - * From Section 7.2.2 from the SPHINCS+ round-2 specification: - * - * Each of the instances of the tweakable hash function take PK.seed as its - * first input, which is constant for a given key pair – and, thus, across - * a single signature. This leads to a lot of redundant computation. To remedy - * this, we pad PK.seed to the length of a full 64-byte SHA-256 input block. - * Because of the Merkle-DamgÃ¥rd construction that underlies SHA-256, this - * allows for reuse of the intermediate SHA-256 state after the initial call to - * the compression function which improves performance. - * - * We pass this hash state around in functions, because otherwise we need to - * have a global variable. - */ - -#include "haraka.h" -#define hash_state harakactx - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/merkle.c b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/merkle.c new file mode 100644 index 0000000000..0c1479fd93 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/merkle.c @@ -0,0 +1,59 @@ +#include +#include + +#include "address.h" +#include "merkle.h" +#include "params.h" +#include "utils.h" +#include "utilsx1.h" +#include "wots.h" +#include "wotsx1.h" + +/* + * This generates a Merkle signature (WOTS signature followed by the Merkle + * authentication path). This is in this file because most of the complexity + * is involved with the WOTS signature; the Merkle authentication path logic + * is mostly hidden in treehashx4 + */ +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf) { + unsigned char *auth_path = sig + SPX_WOTS_BYTES; + struct leaf_info_x1 info = { 0 }; + unsigned steps[ SPX_WOTS_LEN ]; + + info.wots_sig = sig; + chain_lengths(steps, root); + info.wots_steps = steps; + + set_type(&tree_addr[0], SPX_ADDR_TYPE_HASHTREE); + set_type(&info.pk_addr[0], SPX_ADDR_TYPE_WOTSPK); + copy_subtree_addr(&info.leaf_addr[0], wots_addr); + copy_subtree_addr(&info.pk_addr[0], wots_addr); + + info.wots_sign_leaf = idx_leaf; + + treehashx1(root, auth_path, ctx, + idx_leaf, 0, + SPX_TREE_HEIGHT, + wots_gen_leafx1, + tree_addr, &info); +} + +/* Compute root node of the top-most subtree. */ +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { + /* We do not need the auth path in key generation, but it simplifies the + code to have just one treehash routine that computes both root and path + in one function. */ + unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; + uint32_t top_tree_addr[8] = {0}; + uint32_t wots_addr[8] = {0}; + + set_layer_addr(top_tree_addr, SPX_D - 1); + set_layer_addr(wots_addr, SPX_D - 1); + + merkle_sign(auth_path, root, ctx, + wots_addr, top_tree_addr, + (uint32_t)~0 /* ~0 means "don't bother generating an auth path */ ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/merkle.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/merkle.h new file mode 100644 index 0000000000..769cf2e970 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/merkle.h @@ -0,0 +1,21 @@ +#ifndef MERKLE_H_ +#define MERKLE_H_ + +#include + +#include "context.h" +#include "params.h" + +/* Generate a Merkle signature (WOTS signature followed by the Merkle */ +/* authentication path) */ +#define merkle_sign SPX_NAMESPACE(merkle_sign) +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf); + +/* Compute the root node of the top-most subtree. */ +#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); + +#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/nistapi.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/nistapi.h new file mode 100644 index 0000000000..3cb71afad4 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/nistapi.h @@ -0,0 +1,87 @@ +#ifndef SPX_API_H +#define SPX_API_H + +#include +#include + +#include "params.h" + +#define CRYPTO_ALGNAME "SPHINCS+" + +#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES +#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES +#define CRYPTO_BYTES SPX_BYTES +#define CRYPTO_SEEDBYTES (3*SPX_N) + +/* + * Returns the length of a secret key, in bytes + */ +#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) +size_t crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) +size_t crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) +size_t crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) +size_t crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +#define crypto_sign SPX_NAMESPACE(crypto_sign) +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/params.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/params.h index ccd14efda3..ca96907eeb 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/params.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/params.h @@ -1,53 +1,56 @@ -#ifndef PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_PARAMS_H -#define PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_PARAMS_H +#ifndef SPX_PARAMS_H +#define SPX_PARAMS_H + +#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_##s /* Hash output length in bytes. */ -#define PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_N 32 +#define SPX_N 32 /* Height of the hypertree. */ -#define PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_FULL_HEIGHT 68 +#define SPX_FULL_HEIGHT 68 /* Number of subtree layer. */ -#define PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_D 17 +#define SPX_D 17 /* FORS tree dimensions. */ -#define PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_FORS_HEIGHT 9 -#define PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_FORS_TREES 35 +#define SPX_FORS_HEIGHT 9 +#define SPX_FORS_TREES 35 /* Winternitz parameter, */ -#define PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_WOTS_W 16 +#define SPX_WOTS_W 16 /* The hash function is defined by linking a different hash.c file, as opposed to setting a #define constant. */ /* For clarity */ -#define PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_ADDR_BYTES 32 +#define SPX_ADDR_BYTES 32 /* WOTS parameters. */ -#define PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_WOTS_LOGW 4 +#define SPX_WOTS_LOGW 4 -#define PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_WOTS_LEN1 (8 * PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_N / PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_WOTS_LOGW) +#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) -/* PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#define PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_WOTS_LEN2 3 +/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ +#define SPX_WOTS_LEN2 3 -#define PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_WOTS_LEN (PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_WOTS_LEN1 + PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_WOTS_LEN2) -#define PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_WOTS_BYTES (PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_WOTS_LEN * PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_N) -#define PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_WOTS_PK_BYTES PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_WOTS_BYTES +#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) +#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) +#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES /* Subtree size. */ -#define PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_TREE_HEIGHT (PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_FULL_HEIGHT / PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_D) +#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) + +//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT +// #error SPX_D should always divide SPX_FULL_HEIGHT +//#endif /* FORS parameters. */ -#define PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_FORS_MSG_BYTES ((PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_FORS_TREES + 7) / 8) -#define PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_FORS_BYTES ((PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_FORS_HEIGHT + 1) * PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_FORS_TREES * PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_N) -#define PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_FORS_PK_BYTES PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_N +#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) +#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) +#define SPX_FORS_PK_BYTES SPX_N /* Resulting SPX sizes. */ -#define PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_BYTES (PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_N + PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_FORS_BYTES + PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_D * PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_WOTS_BYTES +\ - PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_FULL_HEIGHT * PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_N) -#define PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_PK_BYTES (2 * PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_N) -#define PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_SK_BYTES (2 * PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_N + PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_PK_BYTES) - -/* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ -#define PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_OPTRAND_BYTES 32 +#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ + SPX_FULL_HEIGHT * SPX_N) +#define SPX_PK_BYTES (2 * SPX_N) +#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) + +#include "haraka_offsets.h" #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/sign.c b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/sign.c index 0c9a029fd5..9d0c7d1b22 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/sign.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/sign.c @@ -3,72 +3,43 @@ #include #include "address.h" -#include "api.h" +#include "context.h" #include "fors.h" #include "hash.h" -#include "hash_state.h" +#include "merkle.h" +#include "nistapi.h" #include "params.h" #include "randombytes.h" #include "thash.h" #include "utils.h" #include "wots.h" -/** - * Computes the leaf at a given address. First generates the WOTS key pair, - * then computes leaf by hashing horizontally. - */ -static void wots_gen_leaf(unsigned char *leaf, const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx, const uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - unsigned char pk[PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_WOTS_BYTES]; - uint32_t wots_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_set_type( - wots_addr, PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_set_type( - wots_pk_addr, PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_ADDR_TYPE_WOTSPK); - - PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_set_keypair_addr( - wots_addr, addr_idx); - PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_wots_gen_pk( - pk, sk_seed, pub_seed, wots_addr, hash_state_seeded); - - PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_copy_keypair_addr( - wots_pk_addr, wots_addr); - PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_thash_WOTS_LEN( - leaf, pk, pub_seed, wots_pk_addr, hash_state_seeded); -} - /* * Returns the length of a secret key, in bytes */ -size_t PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_crypto_sign_secretkeybytes(void) { - return PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_CRYPTO_SECRETKEYBYTES; +size_t crypto_sign_secretkeybytes(void) { + return CRYPTO_SECRETKEYBYTES; } /* * Returns the length of a public key, in bytes */ -size_t PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_crypto_sign_publickeybytes(void) { - return PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_CRYPTO_PUBLICKEYBYTES; +size_t crypto_sign_publickeybytes(void) { + return CRYPTO_PUBLICKEYBYTES; } /* * Returns the length of a signature, in bytes */ -size_t PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_crypto_sign_bytes(void) { - return PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_CRYPTO_BYTES; +size_t crypto_sign_bytes(void) { + return CRYPTO_BYTES; } /* * Returns the length of the seed required to generate a key pair, in bytes */ -size_t PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_crypto_sign_seedbytes(void) { - return PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_CRYPTO_SEEDBYTES; +size_t crypto_sign_seedbytes(void) { + return CRYPTO_SEEDBYTES; } /* @@ -76,37 +47,30 @@ size_t PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_crypto_sign_seedbytes(void) { * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] * Format pk: [PUB_SEED || root] */ -int PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed) { - /* We do not need the auth path in key generation, but it simplifies the - code to have just one treehash routine that computes both root and path - in one function. */ - unsigned char auth_path[PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_TREE_HEIGHT * PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_N]; - uint32_t top_tree_addr[8] = {0}; - hash_state hash_state_seeded; - - PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_set_layer_addr( - top_tree_addr, PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_D - 1); - PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_set_type( - top_tree_addr, PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_ADDR_TYPE_HASHTREE); +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed) { + spx_ctx ctx; /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ - memcpy(sk, seed, PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_CRYPTO_SEEDBYTES); + memcpy(sk, seed, CRYPTO_SEEDBYTES); - memcpy(pk, sk + 2 * PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_N, PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_N); + memcpy(pk, sk + 2 * SPX_N, SPX_N); + + memcpy(ctx.pub_seed, pk, SPX_N); + memcpy(ctx.sk_seed, sk, SPX_N); /* This hook allows the hash function instantiation to do whatever preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_initialize_hash_function(&hash_state_seeded, pk, sk); + initialize_hash_function(&ctx); /* Compute root node of the top-most subtree. */ - PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_treehash_TREE_HEIGHT( - sk + 3 * PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_N, auth_path, sk, sk + 2 * PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_N, 0, 0, - wots_gen_leaf, top_tree_addr, &hash_state_seeded); + merkle_gen_root(sk + 3 * SPX_N, &ctx); + + // cleanup + free_hash_function(&ctx); - memcpy(pk + PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_N, sk + 3 * PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_N, PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_N); + memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); - PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_destroy_hash_function(&hash_state_seeded); return 0; } @@ -115,12 +79,10 @@ int PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_crypto_sign_seed_keypair( * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] * Format pk: [PUB_SEED || root] */ -int PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk) { - unsigned char seed[PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_CRYPTO_SEEDBYTES]; - randombytes(seed, PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_CRYPTO_SEEDBYTES); - PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_crypto_sign_seed_keypair( - pk, sk, seed); +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { + uint8_t seed[CRYPTO_SEEDBYTES]; + randombytes(seed, CRYPTO_SEEDBYTES); + crypto_sign_seed_keypair(pk, sk, seed); return 0; } @@ -128,101 +90,83 @@ int PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_crypto_sign_keypair( /** * Returns an array containing a detached signature. */ -int PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - const unsigned char *sk_seed = sk; - const unsigned char *sk_prf = sk + PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_N; - const unsigned char *pk = sk + 2 * PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_N; - const unsigned char *pub_seed = pk; - - unsigned char optrand[PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_N]; - unsigned char mhash[PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_FORS_MSG_BYTES]; - unsigned char root[PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_N]; +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk) { + spx_ctx ctx; + + const uint8_t *sk_prf = sk + SPX_N; + const uint8_t *pk = sk + 2 * SPX_N; + + uint8_t optrand[SPX_N]; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t root[SPX_N]; uint32_t i; uint64_t tree; uint32_t idx_leaf; uint32_t wots_addr[8] = {0}; uint32_t tree_addr[8] = {0}; - hash_state hash_state_seeded; + memcpy(ctx.sk_seed, sk, SPX_N); + memcpy(ctx.pub_seed, pk, SPX_N); /* This hook allows the hash function instantiation to do whatever preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_initialize_hash_function( - &hash_state_seeded, - pub_seed, sk_seed); + initialize_hash_function(&ctx); - PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_set_type( - wots_addr, PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_set_type( - tree_addr, PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_ADDR_TYPE_HASHTREE); + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); /* Optionally, signing can be made non-deterministic using optrand. This can help counter side-channel attacks that would benefit from getting a large number of traces when the signer uses the same nodes. */ - randombytes(optrand, PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_N); + randombytes(optrand, SPX_N); /* Compute the digest randomization value. */ - PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_gen_message_random( - sig, sk_prf, optrand, m, mlen, &hash_state_seeded); + gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); /* Derive the message digest and leaf index from R, PK and M. */ - PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_N; + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; - PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); /* Sign the message hash using FORS. */ - PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_fors_sign( - sig, root, mhash, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_FORS_BYTES; - - for (i = 0; i < PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_D; i++) { - PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_set_tree_addr(tree_addr, tree); - - PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); - - /* Compute a WOTS signature. */ - PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_wots_sign( - sig, root, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_WOTS_BYTES; - - /* Compute the authentication path for the used WOTS leaf. */ - PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_treehash_TREE_HEIGHT( - root, sig, sk_seed, pub_seed, idx_leaf, 0, - wots_gen_leaf, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_TREE_HEIGHT * PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_N; + fors_sign(sig, root, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); + sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_TREE_HEIGHT; + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; } - *siglen = PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_BYTES; + free_hash_function(&ctx); + + *siglen = SPX_BYTES; - PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_destroy_hash_function(&hash_state_seeded); return 0; } /** * Verifies a detached signature and message under a given public key. */ -int PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk) { - const unsigned char *pub_seed = pk; - const unsigned char *pub_root = pk + PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_N; - unsigned char mhash[PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_FORS_MSG_BYTES]; - unsigned char wots_pk[PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_WOTS_BYTES]; - unsigned char root[PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_N]; - unsigned char leaf[PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_N]; +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk) { + spx_ctx ctx; + const uint8_t *pub_root = pk + SPX_N; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t wots_pk[SPX_WOTS_BYTES]; + uint8_t root[SPX_N]; + uint8_t leaf[SPX_N]; unsigned int i; uint64_t tree; uint32_t idx_leaf; @@ -230,78 +174,66 @@ int PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_crypto_sign_verify( uint32_t tree_addr[8] = {0}; uint32_t wots_pk_addr[8] = {0}; - hash_state hash_state_seeded; - - if (siglen != PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_BYTES) { + if (siglen != SPX_BYTES) { return -1; } + memcpy(ctx.pub_seed, pk, SPX_N); + /* This hook allows the hash function instantiation to do whatever preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_initialize_hash_function( - &hash_state_seeded, - pub_seed, NULL); + initialize_hash_function(&ctx); - PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_set_type( - wots_addr, PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_set_type( - tree_addr, PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_ADDR_TYPE_HASHTREE); - PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_set_type( - wots_pk_addr, PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_ADDR_TYPE_WOTSPK); + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); /* Derive the message digest and leaf index from R || PK || M. */ - /* The additional PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_N is a result of the hash domain separator. */ - PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_N; + /* The additional SPX_N is a result of the hash domain separator. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; /* Layer correctly defaults to 0, so no need to set_layer_addr */ - PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); - PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_fors_pk_from_sig( - root, sig, mhash, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_FORS_BYTES; + fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; /* For each subtree.. */ - for (i = 0; i < PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_D; i++) { - PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_set_tree_addr(tree_addr, tree); + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); - PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); - PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_copy_keypair_addr( - wots_pk_addr, wots_addr); + copy_keypair_addr(wots_pk_addr, wots_addr); /* The WOTS public key is only correct if the signature was correct. */ /* Initially, root is the FORS pk, but on subsequent iterations it is the root of the subtree below the currently processed subtree. */ - PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_wots_pk_from_sig( - wots_pk, sig, root, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_WOTS_BYTES; + wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); + sig += SPX_WOTS_BYTES; /* Compute the leaf node using the WOTS public key. */ - PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_thash_WOTS_LEN( - leaf, wots_pk, pub_seed, wots_pk_addr, &hash_state_seeded); + thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); /* Compute the root node of this subtree. */ - PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_compute_root( - root, leaf, idx_leaf, 0, sig, PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_TREE_HEIGHT, - pub_seed, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_TREE_HEIGHT * PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_N; + compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, + &ctx, tree_addr); + sig += SPX_TREE_HEIGHT * SPX_N; /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_TREE_HEIGHT; + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; } - PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_destroy_hash_function(&hash_state_seeded); + // cleanup + free_hash_function(&ctx); + /* Check if the root node equals the root node in the public key. */ - if (memcmp(root, pub_root, PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_N) != 0) { + if (memcmp(root, pub_root, SPX_N) != 0) { return -1; } @@ -312,15 +244,14 @@ int PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_crypto_sign_verify( /** * Returns an array containing the signature followed by the message. */ -int PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk) { size_t siglen; - PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_crypto_sign_signature( - sm, &siglen, m, mlen, sk); + crypto_sign_signature(sm, &siglen, m, mlen, sk); - memmove(sm + PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_BYTES, m, mlen); + memmove(sm + SPX_BYTES, m, mlen); *smlen = siglen + mlen; return 0; @@ -329,28 +260,27 @@ int PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_crypto_sign( /** * Verifies a given signature-message pair under a given public key. */ -int PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk) { +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk) { /* The API caller does not necessarily know what size a signature should be - but SPHINCS+ signatures are always exactly PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_BYTES. */ - if (smlen < PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_BYTES) { + but SPHINCS+ signatures are always exactly SPX_BYTES. */ + if (smlen < SPX_BYTES) { memset(m, 0, smlen); *mlen = 0; return -1; } - *mlen = smlen - PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_BYTES; + *mlen = smlen - SPX_BYTES; - if (PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_crypto_sign_verify( - sm, PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_BYTES, sm + PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_BYTES, *mlen, pk)) { + if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { memset(m, 0, smlen); *mlen = 0; return -1; } /* If verification was successful, move the message to the right place. */ - memmove(m, sm + PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_BYTES, *mlen); + memmove(m, sm + SPX_BYTES, *mlen); return 0; } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/thash.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/thash.h index 8bd21a97f4..8687ccfb4d 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/thash.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/thash.h @@ -1,28 +1,13 @@ -#ifndef PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_THASH_H -#define PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_THASH_H +#ifndef SPX_THASH_H +#define SPX_THASH_H -#include "hash_state.h" +#include "context.h" +#include "params.h" #include -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); +#define thash SPX_NAMESPACE(thash) +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/thash_haraka_simple.c b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/thash_haraka_simple.c index 2b74184075..207777bf8d 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/thash_haraka_simple.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/thash_haraka_simple.c @@ -4,80 +4,33 @@ #include "address.h" #include "params.h" #include "thash.h" +#include "utils.h" #include "haraka.h" /** - * Takes an array of inblocks concatenated arrays of PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_N bytes. + * Takes an array of inblocks concatenated arrays of SPX_N bytes. */ -static void PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_thash( - unsigned char *out, unsigned char *buf, - const unsigned char *in, unsigned int inblocks, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]) { + PQCLEAN_VLA(uint8_t, buf, SPX_ADDR_BYTES + inblocks * SPX_N); unsigned char outbuf[32]; unsigned char buf_tmp[64]; - (void)pub_seed; /* Suppress an 'unused parameter' warning. */ - if (inblocks == 1) { /* F function */ - /* Since PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_N may be smaller than 32, we need a temporary buffer. */ + /* Since SPX_N may be smaller than 32, we need a temporary buffer. */ memset(buf_tmp, 0, 64); - PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_addr_to_bytes(buf_tmp, addr); - memcpy(buf_tmp + PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_ADDR_BYTES, in, PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_N); + memcpy(buf_tmp, addr, 32); + memcpy(buf_tmp + SPX_ADDR_BYTES, in, SPX_N); - PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_haraka512(outbuf, buf_tmp, hash_state_seeded); - memcpy(out, outbuf, PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_N); + haraka512(outbuf, buf_tmp, ctx); + memcpy(out, outbuf, SPX_N); } else { /* All other tweakable hashes*/ - PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_addr_to_bytes(buf, addr); - memcpy(buf + PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_ADDR_BYTES, in, inblocks * PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_N); + memcpy(buf, addr, 32); + memcpy(buf + SPX_ADDR_BYTES, in, inblocks * SPX_N); - PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_haraka_S( - out, PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_N, buf, PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_N, hash_state_seeded); + haraka_S(out, SPX_N, buf, SPX_ADDR_BYTES + inblocks * SPX_N, ctx); } } - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_ADDR_BYTES + 1 * PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_N]; - PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_thash( - out, buf, in, 1, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_ADDR_BYTES + 2 * PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_N]; - PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_thash( - out, buf, in, 2, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_ADDR_BYTES + PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_WOTS_LEN * PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_N]; - PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_thash( - out, buf, in, PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_WOTS_LEN, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_ADDR_BYTES + PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_FORS_TREES * PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_N]; - PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_thash( - out, buf, in, PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_FORS_TREES, pub_seed, addr, hash_state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/utils.c b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/utils.c index 1051de96aa..177b541fb9 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/utils.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/utils.c @@ -1,34 +1,41 @@ -#include #include +#include "utils.h" + #include "address.h" #include "hash.h" -#include "hash_state.h" #include "params.h" #include "thash.h" -#include "utils.h" /** * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. */ -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in) { +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in) { + int i; /* Iterate over out in decreasing order, for big-endianness. */ - for (size_t i = outlen; i > 0; i--) { - out[i - 1] = in & 0xff; + for (i = (signed int)outlen - 1; i >= 0; i--) { + out[i] = in & 0xff; in = in >> 8; } } +void u32_to_bytes(unsigned char *out, uint32_t in) { + out[0] = (unsigned char)(in >> 24); + out[1] = (unsigned char)(in >> 16); + out[2] = (unsigned char)(in >> 8); + out[3] = (unsigned char)in; +} + /** * Converts the inlen bytes in 'in' from big-endian byte order to an integer. */ -unsigned long long PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_bytes_to_ull( - const unsigned char *in, size_t inlen) { +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { unsigned long long retval = 0; + unsigned int i; - for (size_t i = 0; i < inlen; i++) { + for (i = 0; i < inlen; i++) { retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); } return retval; @@ -38,94 +45,80 @@ unsigned long long PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_bytes_to_ull( * Computes a root node given a leaf and an auth path. * Expects address to be complete other than the tree_height and tree_index. */ -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]) { uint32_t i; - unsigned char buffer[2 * PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_N]; + unsigned char buffer[2 * SPX_N]; /* If leaf_idx is odd (last bit = 1), current path element is a right child and auth_path has to go left. Otherwise it is the other way around. */ if (leaf_idx & 1) { - memcpy(buffer + PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_N, leaf, PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_N); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_N); + memcpy(buffer + SPX_N, leaf, SPX_N); + memcpy(buffer, auth_path, SPX_N); } else { - memcpy(buffer, leaf, PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_N); - memcpy(buffer + PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_N, auth_path, PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_N); + memcpy(buffer, leaf, SPX_N); + memcpy(buffer + SPX_N, auth_path, SPX_N); } - auth_path += PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_N; + auth_path += SPX_N; for (i = 0; i < tree_height - 1; i++) { leaf_idx >>= 1; idx_offset >>= 1; /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_set_tree_height(addr, i + 1); - PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_set_tree_index( - addr, leaf_idx + idx_offset); + set_tree_height(addr, i + 1); + set_tree_index(addr, leaf_idx + idx_offset); /* Pick the right or left neighbor, depending on parity of the node. */ if (leaf_idx & 1) { - PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_thash_2( - buffer + PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_N, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_N); + thash(buffer + SPX_N, buffer, 2, ctx, addr); + memcpy(buffer, auth_path, SPX_N); } else { - PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_thash_2( - buffer, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer + PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_N, auth_path, PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_N); + thash(buffer, buffer, 2, ctx, addr); + memcpy(buffer + SPX_N, auth_path, SPX_N); } - auth_path += PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_N; + auth_path += SPX_N; } /* The last iteration is exceptional; we do not copy an auth_path node. */ leaf_idx >>= 1; idx_offset >>= 1; - PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_set_tree_height(addr, tree_height); - PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_set_tree_index( - addr, leaf_idx + idx_offset); - PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_thash_2( - root, buffer, pub_seed, addr, hash_state_seeded); + set_tree_height(addr, tree_height); + set_tree_index(addr, leaf_idx + idx_offset); + thash(root, buffer, 2, ctx, addr); } /** * For a given leaf index, computes the authentication path and the resulting * root node using Merkle's TreeHash algorithm. * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_ADDR_TYPE_FORSTREE). + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). * Applies the offset idx_offset to indices before building addresses, so that * it is possible to continue counting indices across trees. */ -static void PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_treehash( - unsigned char *root, unsigned char *auth_path, - unsigned char *stack, unsigned int *heights, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - +void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx * /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]) { + PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); + PQCLEAN_VLA(unsigned int, heights, tree_height + 1); unsigned int offset = 0; uint32_t idx; uint32_t tree_idx; for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { /* Add the next leaf node to the stack. */ - gen_leaf(stack + offset * PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_N, - sk_seed, pub_seed, idx + idx_offset, tree_addr, - hash_state_seeded); + gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); offset++; heights[offset - 1] = 0; /* If this is a node we need for the auth path.. */ if ((leaf_idx ^ 0x1) == idx) { - memcpy(auth_path, stack + (offset - 1)*PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_N, PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_N); + memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); } /* While the top-most nodes are of equal height.. */ @@ -134,66 +127,22 @@ static void PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_treehash( tree_idx = (idx >> (heights[offset - 1] + 1)); /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_set_tree_height( - tree_addr, heights[offset - 1] + 1); - PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_set_tree_index( - tree_addr, tree_idx + (idx_offset >> (heights[offset - 1] + 1))); + set_tree_height(tree_addr, heights[offset - 1] + 1); + set_tree_index(tree_addr, + tree_idx + (idx_offset >> (heights[offset - 1] + 1))); /* Hash the top-most nodes from the stack together. */ - PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_thash_2( - stack + (offset - 2)*PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_N, stack + (offset - 2)*PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_N, - pub_seed, tree_addr, hash_state_seeded); + thash(stack + (offset - 2)*SPX_N, + stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); offset--; /* Note that the top-most node is now one layer higher. */ heights[offset - 1]++; /* If this is a node we need for the auth path.. */ if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_path + heights[offset - 1]*PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_N, - stack + (offset - 1)*PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_N, PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_N); + memcpy(auth_path + heights[offset - 1]*SPX_N, + stack + (offset - 1)*SPX_N, SPX_N); } } } - memcpy(root, stack, PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_N); -} - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_FORS_HEIGHT + 1)*PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_N]; - unsigned int heights[PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_FORS_HEIGHT + 1]; - - PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_FORS_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_TREE_HEIGHT + 1)*PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_N]; - unsigned int heights[PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_TREE_HEIGHT + 1]; - - PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_TREE_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); + memcpy(root, stack, SPX_N); } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/utils.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/utils.h index 57fe2f4a90..64f5d5a53a 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/utils.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/utils.h @@ -1,64 +1,58 @@ -#ifndef PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_UTILS_H -#define PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_UTILS_H +#ifndef SPX_UTILS_H +#define SPX_UTILS_H -#include "hash_state.h" -#include "params.h" -#include #include +#include "compat.h" +#include "context.h" +#include "params.h" + + +/* To support MSVC use alloca() instead of VLAs. See #20. */ + + /** * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. */ -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in); +#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in); +#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) +void u32_to_bytes(unsigned char *out, uint32_t in); /** * Converts the inlen bytes in 'in' from big-endian byte order to an integer. */ -unsigned long long PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_bytes_to_ull( - const unsigned char *in, size_t inlen); +#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); /** * Computes a root node given a leaf and an auth path. * Expects address to be complete other than the tree_height and tree_index. */ -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); +#define compute_root SPX_NAMESPACE(compute_root) +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]); /** * For a given leaf index, computes the authentication path and the resulting * root node using Merkle's TreeHash algorithm. * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_ADDR_TYPE_FORSTREE). + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). * Applies the offset idx_offset to indices before building addresses, so that * it is possible to continue counting indices across trees. */ -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); +#define treehash SPX_NAMESPACE(treehash) +void treehash(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx *ctx /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]); -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/utilsx1.c b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/utilsx1.c new file mode 100644 index 0000000000..fccb69b35d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/utilsx1.c @@ -0,0 +1,100 @@ +#include + +#include "utilsx1.h" + +#include "address.h" +#include "params.h" +#include "thash.h" +#include "utils.h" + +/* + * Generate the entire Merkle tree, computing the authentication path for + * leaf_idx, and the resulting root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) + * + * This expects tree_addr to be initialized to the addr structures for the + * Merkle tree nodes + * + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + * + * This works by using the standard Merkle tree building algorithm, + */ +void treehashx1(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, + uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* Where to write the leaves */, + const spx_ctx * /* ctx */, + uint32_t idx, void *info), + uint32_t tree_addr[8], + void *info) { + /* This is where we keep the intermediate nodes */ + PQCLEAN_VLA(uint8_t, stack, tree_height * SPX_N); + + uint32_t idx; + uint32_t max_idx = (uint32_t)((1 << tree_height) - 1); + for (idx = 0;; idx++) { + unsigned char current[2 * SPX_N]; /* Current logical node is at */ + /* index[SPX_N]. We do this to minimize the number of copies */ + /* needed during a thash */ + gen_leaf( ¤t[SPX_N], ctx, idx + idx_offset, + info ); + + /* Now combine the freshly generated right node with previously */ + /* generated left ones */ + uint32_t internal_idx_offset = idx_offset; + uint32_t internal_idx = idx; + uint32_t internal_leaf = leaf_idx; + uint32_t h; /* The height we are in the Merkle tree */ + for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { + + /* Check if we hit the top of the tree */ + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[SPX_N], SPX_N ); + return; + } + + /* + * Check if the node we have is a part of the + * authentication path; if it is, write it out + */ + if ((internal_idx ^ internal_leaf) == 0x01) { + memcpy( &auth_path[ h * SPX_N ], + ¤t[SPX_N], + SPX_N ); + } + + /* + * Check if we're at a left child; if so, stop going up the stack + * Exception: if we've reached the end of the tree, keep on going + * (so we combine the last 4 nodes into the one root node in two + * more iterations) + */ + if ((internal_idx & 1) == 0 && idx < max_idx) { + break; + } + + /* Ok, we're at a right node */ + /* Now combine the left and right logical nodes together */ + + /* Set the address of the node we're creating. */ + internal_idx_offset >>= 1; + set_tree_height(tree_addr, h + 1); + set_tree_index(tree_addr, internal_idx / 2 + internal_idx_offset ); + + unsigned char *left = &stack[h * SPX_N]; + memcpy( ¤t[0], left, SPX_N ); + thash( ¤t[1 * SPX_N], + ¤t[0 * SPX_N], + 2, ctx, tree_addr); + } + + /* We've hit a left child; save the current for when we get the */ + /* corresponding right right */ + memcpy( &stack[h * SPX_N], ¤t[SPX_N], SPX_N); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/utilsx1.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/utilsx1.h new file mode 100644 index 0000000000..e911d17d53 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/utilsx1.h @@ -0,0 +1,27 @@ +#ifndef SPX_UTILSX4_H +#define SPX_UTILSX4_H + +#include + +#include "context.h" +#include "params.h" + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +#define treehashx1 SPX_NAMESPACE(treehashx1) +void treehashx1(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* Where to write the leaf */, + const spx_ctx * /* ctx */, + uint32_t addr_idx, void *info), + uint32_t tree_addrx4[8], void *info); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/wots.c b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/wots.c index 214f4826d7..249717aaa8 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/wots.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/wots.c @@ -1,32 +1,20 @@ #include #include +#include "wots.h" +#include "wotsx1.h" + #include "address.h" #include "hash.h" -#include "hash_state.h" #include "params.h" #include "thash.h" #include "utils.h" -#include "wots.h" +#include "utilsx1.h" // TODO clarify address expectations, and make them more uniform. // TODO i.e. do we expect types to be set already? // TODO and do we expect modifications or copies? -/** - * Computes the starting value for a chain, i.e. the secret key. - * Expects the address to be complete up to the chain address. - */ -static void wots_gen_sk(unsigned char *sk, const unsigned char *sk_seed, - uint32_t wots_addr[8], - const hash_state *hash_state_seeded) { - /* Make sure that the hash address is actually zeroed. */ - PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_set_hash_addr(wots_addr, 0); - - /* Generate sk element. */ - PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_prf_addr(sk, sk_seed, wots_addr, hash_state_seeded); -} - /** * Computes the chaining function. * out and in have to be n-byte arrays. @@ -36,18 +24,16 @@ static void wots_gen_sk(unsigned char *sk, const unsigned char *sk_seed, */ static void gen_chain(unsigned char *out, const unsigned char *in, unsigned int start, unsigned int steps, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { + const spx_ctx *ctx, uint32_t addr[8]) { uint32_t i; /* Initialize out with the value at position 'start'. */ - memcpy(out, in, PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_N); + memcpy(out, in, SPX_N); /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_WOTS_W; i++) { - PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_set_hash_addr(addr, i); - PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_thash_1( - out, out, pub_seed, addr, hash_state_seeded); + for (i = start; i < (start + steps) && i < SPX_WOTS_W; i++) { + set_hash_addr(addr, i); + thash(out, out, 1, ctx, addr); } } @@ -56,13 +42,13 @@ static void gen_chain(unsigned char *out, const unsigned char *in, * Interprets an array of bytes as integers in base w. * This only works when log_w is a divisor of 8. */ -static void base_w(unsigned int *output, const size_t out_len, +static void base_w(unsigned int *output, const int out_len, const unsigned char *input) { - size_t in = 0; - size_t out = 0; + int in = 0; + int out = 0; unsigned char total = 0; - unsigned int bits = 0; - size_t consumed; + int bits = 0; + int consumed; for (consumed = 0; consumed < out_len; consumed++) { if (bits == 0) { @@ -70,8 +56,8 @@ static void base_w(unsigned int *output, const size_t out_len, in++; bits += 8; } - bits -= PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_WOTS_LOGW; - output[out] = (unsigned int)((total >> bits) & (PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_WOTS_W - 1)); + bits -= SPX_WOTS_LOGW; + output[out] = (total >> bits) & (SPX_WOTS_W - 1); out++; } } @@ -80,67 +66,25 @@ static void base_w(unsigned int *output, const size_t out_len, static void wots_checksum(unsigned int *csum_base_w, const unsigned int *msg_base_w) { unsigned int csum = 0; - unsigned char csum_bytes[(PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_WOTS_LEN2 * PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_WOTS_LOGW + 7) / 8]; + unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; unsigned int i; /* Compute checksum. */ - for (i = 0; i < PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_WOTS_LEN1; i++) { - csum += PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_WOTS_W - 1 - msg_base_w[i]; + for (i = 0; i < SPX_WOTS_LEN1; i++) { + csum += SPX_WOTS_W - 1 - msg_base_w[i]; } /* Convert checksum to base_w. */ /* Make sure expected empty zero bits are the least significant bits. */ - csum = csum << (8 - ((PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_WOTS_LEN2 * PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_WOTS_LOGW) % 8)); - PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_ull_to_bytes( - csum_bytes, sizeof(csum_bytes), csum); - base_w(csum_base_w, PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_WOTS_LEN2, csum_bytes); + csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); + ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); + base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); } /* Takes a message and derives the matching chain lengths. */ -static void chain_lengths(unsigned int *lengths, const unsigned char *msg) { - base_w(lengths, PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_WOTS_LEN1, msg); - wots_checksum(lengths + PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_WOTS_LEN1, lengths); -} - -/** - * WOTS key generation. Takes a 32 byte sk_seed, expands it to WOTS private key - * elements and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_wots_gen_pk( - unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - uint32_t i; - - for (i = 0; i < PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_WOTS_LEN; i++) { - PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_set_chain_addr(addr, i); - wots_gen_sk(pk + i * PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_N, sk_seed, addr, hash_state_seeded); - gen_chain(pk + i * PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_N, pk + i * PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_N, - 0, PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_WOTS_W - 1, pub_seed, addr, hash_state_seeded); - } -} - -/** - * Takes a n-byte message and the 32-byte sk_see to compute a signature 'sig'. - */ -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_wots_sign( - unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *hash_state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_WOTS_LEN; i++) { - PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_set_chain_addr(addr, i); - wots_gen_sk(sig + i * PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_N, sk_seed, addr, hash_state_seeded); - gen_chain(sig + i * PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_N, sig + i * PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_N, 0, lengths[i], pub_seed, addr, hash_state_seeded); - } +void chain_lengths(unsigned int *lengths, const unsigned char *msg) { + base_w(lengths, SPX_WOTS_LEN1, msg); + wots_checksum(lengths + SPX_WOTS_LEN1, lengths); } /** @@ -148,20 +92,17 @@ void PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_wots_sign( * * Writes the computed public key to 'pk'. */ -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_wots_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_WOTS_LEN]; +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]) { + unsigned int lengths[SPX_WOTS_LEN]; uint32_t i; chain_lengths(lengths, msg); - for (i = 0; i < PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_WOTS_LEN; i++) { - PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_set_chain_addr(addr, i); - gen_chain(pk + i * PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_N, sig + i * PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_N, - lengths[i], PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_WOTS_W - 1 - lengths[i], pub_seed, addr, - hash_state_seeded); + for (i = 0; i < SPX_WOTS_LEN; i++) { + set_chain_addr(addr, i); + gen_chain(pk + i * SPX_N, sig + i * SPX_N, + lengths[i], SPX_WOTS_W - 1 - lengths[i], ctx, addr); } } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/wots.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/wots.h index 3c65111be5..4e7692eeef 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/wots.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/wots.h @@ -1,41 +1,25 @@ -#ifndef PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_WOTS_H -#define PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_WOTS_H +#ifndef SPX_WOTS_H +#define SPX_WOTS_H -#include "hash_state.h" -#include "params.h" #include -/** - * WOTS key generation. Takes a 32 byte seed for the private key, expands it to - * a full WOTS private key and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_wots_gen_pk( - unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -/** - * Takes a n-byte message and the 32-byte seed for the private key to compute a - * signature that is placed at 'sig'. - */ -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_wots_sign( - unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *hash_state_seeded); +#include "context.h" +#include "params.h" /** * Takes a WOTS signature and an n-byte message, computes a WOTS public key. * * Writes the computed public key to 'pk'. */ -void PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_wots_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); +#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]); + +/* + * Compute the chain lengths needed for a given message hash + */ +#define chain_lengths SPX_NAMESPACE(chain_lengths) +void chain_lengths(unsigned int *lengths, const unsigned char *msg); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/wotsx1.c b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/wotsx1.c new file mode 100644 index 0000000000..3adec78dfb --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/wotsx1.c @@ -0,0 +1,76 @@ +#include +#include + +#include "wots.h" +#include "wotsx1.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "thash.h" +#include "utils.h" + +/* + * This generates a WOTS public key + * It also generates the WOTS signature if leaf_info indicates + * that we're signing with this WOTS key + */ +void wots_gen_leafx1(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info) { + struct leaf_info_x1 *info = v_info; + uint32_t *leaf_addr = info->leaf_addr; + uint32_t *pk_addr = info->pk_addr; + unsigned int i, k; + unsigned char pk_buffer[ SPX_WOTS_BYTES ]; + unsigned char *buffer; + uint32_t wots_k_mask; + + if (leaf_idx == info->wots_sign_leaf) { + /* We're traversing the leaf that's signing; generate the WOTS */ + /* signature */ + wots_k_mask = 0; + } else { + /* Nope, we're just generating pk's; turn off the signature logic */ + wots_k_mask = (uint32_t)~0; + } + + set_keypair_addr( leaf_addr, leaf_idx ); + set_keypair_addr( pk_addr, leaf_idx ); + + for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { + uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k to */ + /* the step if we're generating a signature, ~0 if we're not */ + + /* Start with the secret seed */ + set_chain_addr(leaf_addr, i); + set_hash_addr(leaf_addr, 0); + set_type(leaf_addr, SPX_ADDR_TYPE_WOTSPRF); + + prf_addr(buffer, ctx, leaf_addr); + + set_type(leaf_addr, SPX_ADDR_TYPE_WOTS); + + /* Iterate down the WOTS chain */ + for (k = 0;; k++) { + /* Check if this is the value that needs to be saved as a */ + /* part of the WOTS signature */ + if (k == wots_k) { + memcpy( info->wots_sig + i * SPX_N, buffer, SPX_N ); + } + + /* Check if we hit the top of the chain */ + if (k == SPX_WOTS_W - 1) { + break; + } + + /* Iterate one step on the chain */ + set_hash_addr(leaf_addr, k); + + thash(buffer, buffer, 1, ctx, leaf_addr); + } + } + + /* Do the final thash to generate the public keys */ + thash(dest, pk_buffer, SPX_WOTS_LEN, ctx, pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/wotsx1.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/wotsx1.h new file mode 100644 index 0000000000..e617929f96 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/wotsx1.h @@ -0,0 +1,39 @@ +#ifndef WOTSX1_H_ +#define WOTSX1_H_ + +#include + +#include "context.h" +#include "params.h" + +/* + * This is here to provide an interface to the internal wots_gen_leafx1 + * routine. While this routine is not referenced in the package outside of + * wots.c, it is called from the stand-alone benchmark code to characterize + * the performance + */ +struct leaf_info_x1 { + unsigned char *wots_sig; + uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ + uint32_t *wots_steps; + uint32_t leaf_addr[8]; + uint32_t pk_addr[8]; +}; + +/* Macro to set the leaf_info to something 'benign', that is, it would */ +/* run with the same time as it does during the real signing process */ +/* Used only by the benchmark code */ +#define INITIALIZE_LEAF_INFO_X1(info, addr, step_buffer) { \ + (info).wots_sig = 0; \ + (info).wots_sign_leaf = ~0; \ + (info).wots_steps = step_buffer; \ + memcpy( &(info).leaf_addr[0], (addr), 32 ); \ + memcpy( &(info).pk_addr[0], (addr), 32 ); \ + } + +#define wots_gen_leafx1 SPX_NAMESPACE(wots_gen_leafx1) +void wots_gen_leafx1(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info); + +#endif /* WOTSX1_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/address.c b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/address.c index 3253b0b928..b956e9cb29 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/address.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/address.c @@ -1,78 +1,91 @@ #include +#include #include "address.h" #include "params.h" #include "utils.h" -void PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]) { - int i; - - for (i = 0; i < 8; i++) { - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_ull_to_bytes( - bytes + i * 4, 4, addr[i]); - } -} - -void PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_set_layer_addr( - uint32_t addr[8], uint32_t layer) { - addr[0] = layer; +/* + * Specify which level of Merkle tree (the "layer") we're working on + */ +void set_layer_addr(uint32_t addr[8], uint32_t layer) { + ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; } -void PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_set_tree_addr( - uint32_t addr[8], uint64_t tree) { - addr[1] = 0; - addr[2] = (uint32_t) (tree >> 32); - addr[3] = (uint32_t) tree; +/* + * Specify which Merkle tree within the level (the "tree address") we're working on + */ +void set_tree_addr(uint32_t addr[8], uint64_t tree) { + ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); } -void PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_set_type( - uint32_t addr[8], uint32_t type) { - addr[4] = type; +/* + * Specify the reason we'll use this address structure for, that is, what + * hash will we compute with it. This is used so that unrelated types of + * hashes don't accidentally get the same address structure. The type will be + * one of the SPX_ADDR_TYPE constants + */ +void set_type(uint32_t addr[8], uint32_t type) { + ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; } -void PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; +/* + * Copy the layer and tree fields of the address structure. This is used + * when we're doing multiple types of hashes within the same Merkle tree + */ +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); } /* These functions are used for OTS addresses. */ -void PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_set_keypair_addr( - uint32_t addr[8], uint32_t keypair) { - addr[5] = keypair; +/* + * Specify which Merkle leaf we're working on; that is, which OTS keypair + * we're talking about. + */ +void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { + ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; } -void PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; - out[5] = in[5]; +/* + * Copy the layer, tree and keypair fields of the address structure. This is + * used when we're doing multiple things within the same OTS keypair + */ +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); + ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; } -void PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_set_chain_addr( - uint32_t addr[8], uint32_t chain) { - addr[6] = chain; +/* + * Specify which Merkle chain within the OTS we're working with + * (the chain address) + */ +void set_chain_addr(uint32_t addr[8], uint32_t chain) { + ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; } -void PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_set_hash_addr( - uint32_t addr[8], uint32_t hash) { - addr[7] = hash; +/* + * Specify where in the Merkle chain we are +* (the hash address) + */ +void set_hash_addr(uint32_t addr[8], uint32_t hash) { + ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; } /* These functions are used for all hash tree addresses (including FORS). */ -void PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_set_tree_height( - uint32_t addr[8], uint32_t tree_height) { - addr[6] = tree_height; +/* + * Specify the height of the node in the Merkle/FORS tree we are in + * (the tree height) + */ +void set_tree_height(uint32_t addr[8], uint32_t tree_height) { + ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; } -void PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_set_tree_index( - uint32_t addr[8], uint32_t tree_index) { - addr[7] = tree_index; +/* + * Specify the distance from the left edge of the node in the Merkle/FORS tree + * (the tree index) + */ +void set_tree_index(uint32_t addr[8], uint32_t tree_index) { + u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/address.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/address.h index 1218edb9c2..24a84eb40c 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/address.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/address.h @@ -1,50 +1,52 @@ -#ifndef PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_ADDRESS_H -#define PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_ADDRESS_H +#ifndef SPX_ADDRESS_H +#define SPX_ADDRESS_H #include -#define PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_ADDR_TYPE_WOTS 0 -#define PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_ADDR_TYPE_WOTSPK 1 -#define PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_ADDR_TYPE_HASHTREE 2 -#define PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_ADDR_TYPE_FORSTREE 3 -#define PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_ADDR_TYPE_FORSPK 4 +#include "params.h" -void PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]); +/* The hash types that are passed to set_type */ +#define SPX_ADDR_TYPE_WOTS 0 +#define SPX_ADDR_TYPE_WOTSPK 1 +#define SPX_ADDR_TYPE_HASHTREE 2 +#define SPX_ADDR_TYPE_FORSTREE 3 +#define SPX_ADDR_TYPE_FORSPK 4 +#define SPX_ADDR_TYPE_WOTSPRF 5 +#define SPX_ADDR_TYPE_FORSPRF 6 -void PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_set_layer_addr( - uint32_t addr[8], uint32_t layer); +#define set_layer_addr SPX_NAMESPACE(set_layer_addr) +void set_layer_addr(uint32_t addr[8], uint32_t layer); -void PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_set_tree_addr( - uint32_t addr[8], uint64_t tree); +#define set_tree_addr SPX_NAMESPACE(set_tree_addr) +void set_tree_addr(uint32_t addr[8], uint64_t tree); -void PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_set_type( - uint32_t addr[8], uint32_t type); +#define set_type SPX_NAMESPACE(set_type) +void set_type(uint32_t addr[8], uint32_t type); /* Copies the layer and tree part of one address into the other */ -void PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]); +#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); /* These functions are used for WOTS and FORS addresses. */ -void PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_set_keypair_addr( - uint32_t addr[8], uint32_t keypair); +#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) +void set_keypair_addr(uint32_t addr[8], uint32_t keypair); -void PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_set_chain_addr( - uint32_t addr[8], uint32_t chain); +#define set_chain_addr SPX_NAMESPACE(set_chain_addr) +void set_chain_addr(uint32_t addr[8], uint32_t chain); -void PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_set_hash_addr( - uint32_t addr[8], uint32_t hash); +#define set_hash_addr SPX_NAMESPACE(set_hash_addr) +void set_hash_addr(uint32_t addr[8], uint32_t hash); -void PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]); +#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); /* These functions are used for all hash tree addresses (including FORS). */ -void PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_set_tree_height( - uint32_t addr[8], uint32_t tree_height); +#define set_tree_height SPX_NAMESPACE(set_tree_height) +void set_tree_height(uint32_t addr[8], uint32_t tree_height); -void PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_set_tree_index( - uint32_t addr[8], uint32_t tree_index); +#define set_tree_index SPX_NAMESPACE(set_tree_index) +void set_tree_index(uint32_t addr[8], uint32_t tree_index); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/api.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/api.h index bc26b0e1af..839bde0588 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/api.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/api.h @@ -4,15 +4,13 @@ #include #include - - -#define PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_CRYPTO_ALGNAME "SPHINCS+" +#define PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_CRYPTO_ALGNAME "SPHINCS+-haraka-256s-robust" #define PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_CRYPTO_SECRETKEYBYTES 128 #define PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_CRYPTO_PUBLICKEYBYTES 64 -#define PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_CRYPTO_BYTES 29792 -#define PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_CRYPTO_SEEDBYTES 96 +#define PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_CRYPTO_BYTES 29792 +#define PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_CRYPTO_SEEDBYTES 96 /* * Returns the length of a secret key, in bytes @@ -39,43 +37,41 @@ size_t PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_crypto_sign_seedbytes(void); * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] * Format pk: [root || PUB_SEED] */ -int PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed); +int PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); /* * Generates a SPHINCS+ key pair. * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] * Format pk: [root || PUB_SEED] */ -int PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk); +int PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); /** * Returns an array containing a detached signature. */ -int PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk); +int PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); /** * Verifies a detached signature and message under a given public key. */ -int PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk); +int PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, + const uint8_t *pk); /** * Returns an array containing the signature followed by the message. */ -int PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk); +int PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); /** * Verifies a given signature-message pair under a given public key. */ -int PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk); - +int PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/context.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/context.h new file mode 100644 index 0000000000..f03446b9cb --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/context.h @@ -0,0 +1,22 @@ +#ifndef SPX_CONTEXT_H +#define SPX_CONTEXT_H + +#include + +#include "immintrin.h" +#include "params.h" + +typedef struct { + uint8_t pub_seed[SPX_N]; + uint8_t sk_seed[SPX_N]; + + __m128i rc[40]; +} spx_ctx; + +#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) +void initialize_hash_function(spx_ctx *ctx); + +#define free_hash_function SPX_NAMESPACE(free_hash_function) +void free_hash_function(spx_ctx *ctx); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/context_haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/context_haraka.c new file mode 100644 index 0000000000..f1cd7e3664 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/context_haraka.c @@ -0,0 +1,11 @@ +#include "context.h" +#include "haraka.h" + +void initialize_hash_function(spx_ctx *ctx) { + tweak_constants(ctx); +} + +// we don't support heap-based haraka right now +void free_hash_function(spx_ctx *ctx) { + (void)ctx; // suppress unused variable warnings +} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/fors.c b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/fors.c index 2a36b63456..f1b0639cfc 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/fors.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/fors.c @@ -2,8 +2,9 @@ #include #include -#include "address.h" #include "fors.h" + +#include "address.h" #include "hash.h" #include "hashx4.h" #include "thash.h" @@ -11,19 +12,24 @@ #include "utils.h" #include "utilsx4.h" +static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + prf_addr(sk, ctx, fors_leaf_addr); +} + static void fors_gen_skx4(unsigned char *sk0, unsigned char *sk1, unsigned char *sk2, - unsigned char *sk3, const unsigned char *sk_seed, - uint32_t fors_leaf_addrx4[4 * 8], - const hash_state *state_seeded) { - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_prf_addrx4(sk0, sk1, sk2, sk3, sk_seed, fors_leaf_addrx4, state_seeded); + unsigned char *sk3, const spx_ctx *ctx, + uint32_t fors_leaf_addrx4[4 * 8]) { + prf_addrx4(sk0, sk1, sk2, sk3, + ctx, fors_leaf_addrx4); } static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, - const unsigned char *pub_seed, - uint32_t fors_leaf_addr[8], const hash_state *state_seeded) { - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_thash_1(leaf, sk, pub_seed, fors_leaf_addr, state_seeded); + const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + thash(leaf, sk, 1, ctx, fors_leaf_addr); } static void fors_sk_to_leafx4(unsigned char *leaf0, @@ -34,57 +40,64 @@ static void fors_sk_to_leafx4(unsigned char *leaf0, const unsigned char *sk1, const unsigned char *sk2, const unsigned char *sk3, - const unsigned char *pub_seed, - uint32_t fors_leaf_addrx4[4 * 8], - const hash_state *state_seeded) { - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_thashx4_1(leaf0, leaf1, leaf2, leaf3, - sk0, sk1, sk2, sk3, pub_seed, fors_leaf_addrx4, state_seeded); + const spx_ctx *ctx, + uint32_t fors_leaf_addrx4[4 * 8]) { + thashx4(leaf0, leaf1, leaf2, leaf3, + sk0, sk1, sk2, sk3, + 1, ctx, fors_leaf_addrx4); } -static void fors_gen_leafx4(unsigned char *leaf0, - unsigned char *leaf1, - unsigned char *leaf2, - unsigned char *leaf3, - const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx0, - uint32_t addr_idx1, - uint32_t addr_idx2, - uint32_t addr_idx3, - const uint32_t fors_tree_addr[8], - const hash_state *state_seeded) { - uint32_t fors_leaf_addrx4[4 * 8] = {0}; +struct fors_gen_leaf_info { + uint32_t leaf_addrx[4 * 8]; +}; + +static void fors_gen_leafx4(unsigned char *leaf, + const spx_ctx *ctx, + uint32_t addr_idx, void *info) { + struct fors_gen_leaf_info *fors_info = info; + uint32_t *fors_leaf_addrx4 = fors_info->leaf_addrx; unsigned int j; - /* Only copy the parts that must be kept in fors_leaf_addrx4. */ + /* Only set the parts that the caller doesn't set */ for (j = 0; j < 4; j++) { - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_copy_keypair_addr(fors_leaf_addrx4 + j * 8, fors_tree_addr); - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_set_type(fors_leaf_addrx4 + j * 8, PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_ADDR_TYPE_FORSTREE); + set_tree_index(fors_leaf_addrx4 + j * 8, addr_idx + j); + set_type(fors_leaf_addrx4 + j * 8, SPX_ADDR_TYPE_FORSPRF); } - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_set_tree_index(fors_leaf_addrx4 + 0 * 8, addr_idx0); - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_set_tree_index(fors_leaf_addrx4 + 1 * 8, addr_idx1); - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_set_tree_index(fors_leaf_addrx4 + 2 * 8, addr_idx2); - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_set_tree_index(fors_leaf_addrx4 + 3 * 8, addr_idx3); + fors_gen_skx4(leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + leaf + 2 * SPX_N, + leaf + 3 * SPX_N, + ctx, fors_leaf_addrx4); + + for (j = 0; j < 4; j++) { + set_type(fors_leaf_addrx4 + j * 8, SPX_ADDR_TYPE_FORSTREE); + } - fors_gen_skx4(leaf0, leaf1, leaf2, leaf3, sk_seed, fors_leaf_addrx4, state_seeded); - fors_sk_to_leafx4(leaf0, leaf1, leaf2, leaf3, - leaf0, leaf1, leaf2, leaf3, pub_seed, fors_leaf_addrx4, state_seeded); + fors_sk_to_leafx4(leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + leaf + 2 * SPX_N, + leaf + 3 * SPX_N, + leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + leaf + 2 * SPX_N, + leaf + 3 * SPX_N, + ctx, fors_leaf_addrx4); } /** - * Interprets m as PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_FORS_HEIGHT-bit unsigned integers. - * Assumes m contains at least PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_FORS_TREES bits. - * Assumes indices has space for PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_FORS_TREES integers. + * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + * Assumes indices has space for SPX_FORS_TREES integers. */ static void message_to_indices(uint32_t *indices, const unsigned char *m) { unsigned int i, j; unsigned int offset = 0; - for (i = 0; i < PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_FORS_TREES; i++) { + for (i = 0; i < SPX_FORS_TREES; i++) { indices[i] = 0; - for (j = 0; j < PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_FORS_HEIGHT; j++) { - indices[i] ^= (((uint32_t)m[offset >> 3] >> (offset & 0x7)) & 0x1) << j; + for (j = 0; j < SPX_FORS_HEIGHT; j++) { + indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); offset++; } } @@ -92,68 +105,53 @@ static void message_to_indices(uint32_t *indices, const unsigned char *m) { /** * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_FORS_TREES bits. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. */ -void PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *state_seeded) { - /* Round up to multiple of 4 to prevent out-of-bounds for x4 parallelism */ - uint32_t indices[(PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_FORS_TREES + 3) & ~3] = {0}; - unsigned char roots[((PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_FORS_TREES + 3) & ~3) * PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N]; - /* Sign to a buffer, since we may not have a nice multiple of 4 and would - otherwise overrun the signature. */ - unsigned char sigbufx4[4 * PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N * (1 + PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_FORS_HEIGHT)]; - uint32_t fors_tree_addrx4[4 * 8] = {0}; +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + uint32_t fors_tree_addr[4 * 8] = {0}; + struct fors_gen_leaf_info fors_info = {0}; + uint32_t *fors_leaf_addr = fors_info.leaf_addrx; uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset[4] = {0}; - unsigned int i, j; + uint32_t idx_offset; + unsigned int i; - for (j = 0; j < 4; j++) { - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_copy_keypair_addr(fors_tree_addrx4 + j * 8, fors_addr); - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_set_type(fors_tree_addrx4 + j * 8, PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_ADDR_TYPE_FORSTREE); + for (i = 0; i < 4; i++) { + copy_keypair_addr(fors_tree_addr + 8 * i, fors_addr); + set_type(fors_tree_addr + 8 * i, SPX_ADDR_TYPE_FORSTREE); + copy_keypair_addr(fors_leaf_addr + 8 * i, fors_addr); } - - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_copy_keypair_addr(fors_pk_addr, fors_addr); - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_set_type(fors_pk_addr, PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_ADDR_TYPE_FORSPK); + copy_keypair_addr(fors_pk_addr, fors_addr); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); message_to_indices(indices, m); - for (i = 0; i < ((PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_FORS_TREES + 3) & ~0x3); i += 4) { - for (j = 0; j < 4; j++) { - if (i + j < PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_FORS_TREES) { - idx_offset[j] = (i + j) * (1 << PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_FORS_HEIGHT); + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_set_tree_height(fors_tree_addrx4 + j * 8, 0); - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_set_tree_index(fors_tree_addrx4 + j * 8, - indices[i + j] + idx_offset[j]); - } - } + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); - /* Include the secret key part that produces the selected leaf nodes. */ - fors_gen_skx4(sigbufx4 + 0 * PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N, - sigbufx4 + 1 * PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N, - sigbufx4 + 2 * PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N, - sigbufx4 + 3 * PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N, - sk_seed, fors_tree_addrx4, state_seeded); - - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_treehashx4_FORS_HEIGHT(roots + i * PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N, sigbufx4 + 4 * PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N, sk_seed, pub_seed, - &indices[i], idx_offset, fors_gen_leafx4, fors_tree_addrx4, - state_seeded); - - for (j = 0; j < 4; j++) { - if (i + j < PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_FORS_TREES) { - memcpy(sig, sigbufx4 + j * PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N, PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N); - memcpy(sig + PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N, - sigbufx4 + 4 * PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N + j * PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N * PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_FORS_HEIGHT, - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N * PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_FORS_HEIGHT); - sig += PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N * (1 + PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_FORS_HEIGHT); - } - } + /* Include the secret key part that produces the selected leaf node. */ + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); + fors_gen_sk(sig, ctx, fors_tree_addr); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + sig += SPX_N; + + /* Compute the authentication path for this leaf node. */ + treehashx4(roots + i * SPX_N, sig, ctx, + indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx4, + fors_tree_addr, &fors_info); + + sig += SPX_N * SPX_FORS_HEIGHT; } /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_thash_FORS_TREES(pk, roots, pub_seed, fors_pk_addr, state_seeded); + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); } /** @@ -161,46 +159,44 @@ void PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_fors_sign(unsigned char *sig, unsigne * This can be used for verification by comparing to a known public key, or to * subsequently verify a signature on the derived public key. The latter is the * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_FORS_TREES bits. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. */ -void PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, - const uint32_t fors_addr[8], - const hash_state *state_seeded) { - uint32_t indices[PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_FORS_TREES]; - unsigned char roots[PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_FORS_TREES * PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N]; - unsigned char leaf[PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N]; +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + unsigned char leaf[SPX_N]; uint32_t fors_tree_addr[8] = {0}; uint32_t fors_pk_addr[8] = {0}; uint32_t idx_offset; unsigned int i; - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_copy_keypair_addr(fors_tree_addr, fors_addr); - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_copy_keypair_addr(fors_pk_addr, fors_addr); + copy_keypair_addr(fors_tree_addr, fors_addr); + copy_keypair_addr(fors_pk_addr, fors_addr); - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_set_type(fors_tree_addr, PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_set_type(fors_pk_addr, PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_ADDR_TYPE_FORSPK); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); message_to_indices(indices, m); - for (i = 0; i < PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_FORS_TREES; i++) { - idx_offset = i * (1 << PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_FORS_HEIGHT); + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_set_tree_height(fors_tree_addr, 0); - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_set_tree_index(fors_tree_addr, indices[i] + idx_offset); + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); /* Derive the leaf from the included secret key part. */ - fors_sk_to_leaf(leaf, sig, pub_seed, fors_tree_addr, state_seeded); - sig += PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N; + fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); + sig += SPX_N; /* Derive the corresponding root node of this tree. */ - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_compute_root(roots + i * PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N, leaf, indices[i], idx_offset, - sig, PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_FORS_HEIGHT, pub_seed, fors_tree_addr, - state_seeded); - sig += PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N * PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_FORS_HEIGHT; + compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, + sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); + sig += SPX_N * SPX_FORS_HEIGHT; } /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_thash_FORS_TREES(pk, roots, pub_seed, fors_pk_addr, state_seeded); + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/fors.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/fors.h index 3d8c9ba537..509140a178 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/fors.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/fors.h @@ -1,32 +1,32 @@ -#ifndef PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_FORS_H -#define PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_FORS_H +#ifndef SPX_FORS_H +#define SPX_FORS_H #include -#include "hash_state.h" +#include "context.h" #include "params.h" /** * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_FORS_TREES bits. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. */ -void PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_fors_sign( - unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *hash_state_seeded); +#define fors_sign SPX_NAMESPACE(fors_sign) +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); /** * Derives the FORS public key from a signature. * This can be used for verification by comparing to a known public key, or to * subsequently verify a signature on the derived public key. The latter is the * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_FORS_TREES bits. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. */ -void PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_fors_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, const uint32_t fors_addr[8], - const hash_state *hash_state_seeded); +#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/haraka.c index bd6cde2479..b414b691d7 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/haraka.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/haraka.c @@ -8,10 +8,12 @@ Plain C implementation of the Haraka256 and Haraka512 permutations. #include #include "haraka.h" +#include "harakax4.h" +#include "utils.h" #define HARAKAS_RATE 32 -#define u64 uint64_t +#define u64 unsigned long #define u128 __m128i #define LOAD(src) _mm_loadu_si128((u128 *)(src)) @@ -20,7 +22,7 @@ Plain C implementation of the Haraka256 and Haraka512 permutations. #define XOR128(a, b) _mm_xor_si128(a, b) #define AES2(s0, s1, rci) \ - (s0) = _mm_aesenc_si128(s0, *(rci)); \ + s0 = _mm_aesenc_si128(s0, *(rci)); \ (s1) = _mm_aesenc_si128(s1, *((rci) + 1)); \ (s0) = _mm_aesenc_si128(s0, *((rci) + 2)); \ (s1) = _mm_aesenc_si128(s1, *((rci) + 3)); @@ -32,7 +34,7 @@ Plain C implementation of the Haraka256 and Haraka512 permutations. AES2((s3)[0], (s3)[1], rci); #define AES4(s0, s1, s2, s3, rci) \ - (s0) = _mm_aesenc_si128(s0, *(rci)); \ + s0 = _mm_aesenc_si128(s0, *(rci)); \ (s1) = _mm_aesenc_si128(s1, *((rci) + 1)); \ (s2) = _mm_aesenc_si128(s2, *((rci) + 2)); \ (s3) = _mm_aesenc_si128(s3, *((rci) + 3)); \ @@ -68,17 +70,17 @@ Plain C implementation of the Haraka256 and Haraka512 permutations. _mm_storeu_si128((u128 *)((out) + 16), \ _mm_castpd_si128(_mm_shuffle_pd(_mm_castsi128_pd(s2), _mm_castsi128_pd(s3), 0))); -static void load_haraka_constants(u128 rc[40]) { - rc[ 0] = _mm_set_epi32((int)0x0684704c, (int)0xe620c00a, (int)0xb2c5fef0, (int)0x75817b9d); - rc[ 1] = _mm_set_epi32((int)0x8b66b4e1, (int)0x88f3a06b, (int)0x640f6ba4, (int)0x2f08f717); - rc[ 2] = _mm_set_epi32((int)0x3402de2d, (int)0x53f28498, (int)0xcf029d60, (int)0x9f029114); - rc[ 3] = _mm_set_epi32((int)0x0ed6eae6, (int)0x2e7b4f08, (int)0xbbf3bcaf, (int)0xfd5b4f79); - rc[ 4] = _mm_set_epi32((int)0xcbcfb0cb, (int)0x4872448b, (int)0x79eecd1c, (int)0xbe397044); - rc[ 5] = _mm_set_epi32((int)0x7eeacdee, (int)0x6e9032b7, (int)0x8d5335ed, (int)0x2b8a057b); - rc[ 6] = _mm_set_epi32((int)0x67c28f43, (int)0x5e2e7cd0, (int)0xe2412761, (int)0xda4fef1b); - rc[ 7] = _mm_set_epi32((int)0x2924d9b0, (int)0xafcacc07, (int)0x675ffde2, (int)0x1fc70b3b); - rc[ 8] = _mm_set_epi32((int)0xab4d63f1, (int)0xe6867fe9, (int)0xecdb8fca, (int)0xb9d465ee); - rc[ 9] = _mm_set_epi32((int)0x1c30bf84, (int)0xd4b7cd64, (int)0x5b2a404f, (int)0xad037e33); +static void load_haraka_constants(u128 *rc) { + rc[0] = _mm_set_epi32((int)0x0684704c, (int)0xe620c00a, (int)0xb2c5fef0, (int)0x75817b9d); + rc[1] = _mm_set_epi32((int)0x8b66b4e1, (int)0x88f3a06b, (int)0x640f6ba4, (int)0x2f08f717); + rc[2] = _mm_set_epi32((int)0x3402de2d, (int)0x53f28498, (int)0xcf029d60, (int)0x9f029114); + rc[3] = _mm_set_epi32((int)0x0ed6eae6, (int)0x2e7b4f08, (int)0xbbf3bcaf, (int)0xfd5b4f79); + rc[4] = _mm_set_epi32((int)0xcbcfb0cb, (int)0x4872448b, (int)0x79eecd1c, (int)0xbe397044); + rc[5] = _mm_set_epi32((int)0x7eeacdee, (int)0x6e9032b7, (int)0x8d5335ed, (int)0x2b8a057b); + rc[6] = _mm_set_epi32((int)0x67c28f43, (int)0x5e2e7cd0, (int)0xe2412761, (int)0xda4fef1b); + rc[7] = _mm_set_epi32((int)0x2924d9b0, (int)0xafcacc07, (int)0x675ffde2, (int)0x1fc70b3b); + rc[8] = _mm_set_epi32((int)0xab4d63f1, (int)0xe6867fe9, (int)0xecdb8fca, (int)0xb9d465ee); + rc[9] = _mm_set_epi32((int)0x1c30bf84, (int)0xd4b7cd64, (int)0x5b2a404f, (int)0xad037e33); rc[10] = _mm_set_epi32((int)0xb2cc0bb9, (int)0x941723bf, (int)0x69028b2e, (int)0x8df69800); rc[11] = _mm_set_epi32((int)0xfa0478a6, (int)0xde6f5572, (int)0x4aaa9ec8, (int)0x5c9d2d8a); rc[12] = _mm_set_epi32((int)0xdfb49f2b, (int)0x6b772a12, (int)0x0efa4f2e, (int)0x29129fd4); @@ -111,77 +113,65 @@ static void load_haraka_constants(u128 rc[40]) { rc[39] = _mm_set_epi32((int)0x756acc03, (int)0x02288288, (int)0x4ad6bdfd, (int)0xe9c59da1); } -void PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_tweak_constants( - harakactx *state, - const unsigned char *pk_seed, const unsigned char *sk_seed, - unsigned long long seed_length) { +void tweak_constants(spx_ctx *ctx) { int i; unsigned char buf[40 * 16]; /* Use the standard constants to generate tweaked ones. */ - load_haraka_constants(state->rc); - - /* Constants for sk.seed */ - if (sk_seed != NULL) { - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_haraka_S(buf, 40 * 16, sk_seed, seed_length, state); - /* Tweak constants with the pub_seed */ - for (i = 0; i < 40; i++) { - state->rc_sseed[i] = LOAD(buf + i * 16); - } - } + load_haraka_constants(ctx->rc); /* Constants for pk.seed */ - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_haraka_S(buf, 40 * 16, pk_seed, seed_length, state); + haraka_S(buf, 40 * 16, ctx->pub_seed, SPX_N, ctx); /* Tweak constants with the pub_seed */ for (i = 0; i < 40; i++) { - state->rc[i] = LOAD(buf + i * 16); + ctx->rc[i] = LOAD(buf + i * 16); } } -static void haraka_S_absorb(unsigned char *s, +static void haraka_S_absorb(unsigned char *s, unsigned int r, const unsigned char *m, unsigned long long mlen, - unsigned char p, - const harakactx *state) { + unsigned char p, const spx_ctx *ctx) { unsigned long long i; - unsigned char t[HARAKAS_RATE]; + PQCLEAN_VLA(unsigned char, t, r); - while (mlen >= HARAKAS_RATE) { + while (mlen >= r) { // XOR block to state STORE(s, XOR128(LOAD(s), LOAD(m))); STORE(s + 16, XOR128(LOAD(s + 16), LOAD(m + 16))); - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_haraka512_perm(s, s, state); - mlen -= HARAKAS_RATE; - m += HARAKAS_RATE; + haraka512_perm(s, s, ctx); + mlen -= r; + m += r; } - for (i = 0; i < HARAKAS_RATE; ++i) { + for (i = 0; i < r; ++i) { t[i] = 0; } for (i = 0; i < mlen; ++i) { t[i] = m[i]; } t[i] = p; - t[HARAKAS_RATE - 1] |= 128; + t[r - 1] |= 128; STORE(s, XOR128(LOAD(s), LOAD(t))); STORE(s + 16, XOR128(LOAD(s + 16), LOAD(t + 16))); } static void haraka_S_absorb4x(unsigned char *s, + unsigned int r, const unsigned char *m0, const unsigned char *m1, const unsigned char *m2, const unsigned char *m3, unsigned long long int mlen, unsigned char p, - const harakactx *state) { + const spx_ctx *ctx) { unsigned long long i; - unsigned char t0[HARAKAS_RATE]; - unsigned char t1[HARAKAS_RATE]; - unsigned char t2[HARAKAS_RATE]; - unsigned char t3[HARAKAS_RATE]; + PQCLEAN_VLA(unsigned char, t0, r); + PQCLEAN_VLA(unsigned char, t1, r); + PQCLEAN_VLA(unsigned char, t2, r); + PQCLEAN_VLA(unsigned char, t3, r); - while (mlen >= HARAKAS_RATE) { + while (mlen >= r) { // XOR block to state STORE(s, XOR128(LOAD(s), LOAD(m0))); STORE(s + 16, XOR128(LOAD(s + 16), LOAD(m0 + 16))); @@ -192,15 +182,15 @@ static void haraka_S_absorb4x(unsigned char *s, STORE(s + 192, XOR128(LOAD(s + 192), LOAD(m3))); STORE(s + 208, XOR128(LOAD(s + 208), LOAD(m3 + 16))); - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_haraka512_perm_x4(s, s, state); - mlen -= HARAKAS_RATE; - m0 += HARAKAS_RATE; - m1 += HARAKAS_RATE; - m2 += HARAKAS_RATE; - m3 += HARAKAS_RATE; + haraka512_perm_x4(s, s, ctx); + mlen -= r; + m0 += r; + m1 += r; + m2 += r; + m3 += r; } - for (i = 0; i < HARAKAS_RATE; ++i) { + for (i = 0; i < r; ++i) { t0[i] = 0; t1[i] = 0; t2[i] = 0; @@ -218,10 +208,10 @@ static void haraka_S_absorb4x(unsigned char *s, t2[i] = p; t3[i] = p; - t0[HARAKAS_RATE - 1] |= 128; - t1[HARAKAS_RATE - 1] |= 128; - t2[HARAKAS_RATE - 1] |= 128; - t3[HARAKAS_RATE - 1] |= 128; + t0[r - 1] |= 128; + t1[r - 1] |= 128; + t2[r - 1] |= 128; + t3[r - 1] |= 128; STORE(s, XOR128(LOAD(s), LOAD(t0))); STORE(s + 16, XOR128(LOAD(s + 16), LOAD(t0 + 16))); @@ -234,9 +224,10 @@ static void haraka_S_absorb4x(unsigned char *s, } static void haraka_S_squeezeblocks(unsigned char *h, unsigned long long nblocks, - unsigned char *s, unsigned int r, const harakactx *state) { + unsigned char *s, unsigned int r, + const spx_ctx *ctx) { while (nblocks > 0) { - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_haraka512_perm(s, s, state); + haraka512_perm(s, s, ctx); STORE(h, LOAD(s)); STORE(h + 16, LOAD(s + 16)); h += r; @@ -251,9 +242,9 @@ static void haraka_S_squeezeblocks4x(unsigned char *h0, unsigned long long nblocks, unsigned char *s, unsigned int r, - const harakactx *state) { + const spx_ctx *ctx) { while (nblocks > 0) { - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_haraka512_perm_x4(s, s, state); + haraka512_perm_x4(s, s, ctx); STORE(h0, LOAD(s)); STORE(h0 + 16, LOAD(s + 16)); STORE(h1, LOAD(s + 64)); @@ -270,7 +261,7 @@ static void haraka_S_squeezeblocks4x(unsigned char *h0, } } -void PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_haraka_S_inc_init(uint8_t *s_inc) { +void haraka_S_inc_init(uint8_t *s_inc) { size_t i; for (i = 0; i < 64; i++) { @@ -279,7 +270,8 @@ void PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_haraka_S_inc_init(uint8_t *s_inc) { s_inc[64] = 0; } -void PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, const harakactx *state) { +void haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, + const spx_ctx *ctx) { size_t i; /* Recall that s_inc[64] is the non-absorbed bytes xored into the state */ @@ -293,16 +285,16 @@ void PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_haraka_S_inc_absorb(uint8_t *s_inc, c m += HARAKAS_RATE - s_inc[64]; s_inc[64] = 0; - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_haraka512_perm(s_inc, s_inc, state); + haraka512_perm(s_inc, s_inc, ctx); } for (i = 0; i < mlen; i++) { s_inc[s_inc[64] + i] ^= m[i]; } - s_inc[64] = (uint8_t)(s_inc[64] + mlen); + s_inc[64] += (uint8_t)mlen; } -void PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_haraka_S_inc_finalize(uint8_t *s_inc) { +void haraka_S_inc_finalize(uint8_t *s_inc) { /* After haraka_S_inc_absorb, we are guaranteed that s_inc[64] < HARAKAS_RATE, so we can always use one more byte for p in the current state. */ s_inc[s_inc[64]] ^= 0x1F; @@ -310,22 +302,23 @@ void PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_haraka_S_inc_finalize(uint8_t *s_inc) s_inc[64] = 0; } -void PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, const harakactx *state) { +void haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, + const spx_ctx *ctx) { size_t i; /* First consume any bytes we still have sitting around */ for (i = 0; i < outlen && i < s_inc[64]; i++) { /* There are s_inc[64] bytes left, so r - s_inc[64] is the first available byte. We consume from there, i.e., up to r. */ - out[i] = (uint8_t)s_inc[(HARAKAS_RATE - s_inc[64] + (uint8_t)i)]; + out[i] = (uint8_t)s_inc[(HARAKAS_RATE - s_inc[64] + i)]; } out += i; outlen -= i; - s_inc[64] = (uint8_t)(s_inc[64] - i); + s_inc[64] -= (uint8_t)i; /* Then squeeze the remaining necessary blocks */ while (outlen > 0) { - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_haraka512_perm(s_inc, s_inc, state); + haraka512_perm(s_inc, s_inc, ctx); for (i = 0; i < outlen && i < HARAKAS_RATE; i++) { out[i] = s_inc[i]; @@ -336,8 +329,9 @@ void PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_haraka_S_inc_squeeze(uint8_t *out, si } } -void PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_haraka_S(unsigned char *out, unsigned long long outlen, - const unsigned char *in, unsigned long long inlen, const harakactx *state) { +void haraka_S(unsigned char *out, unsigned long long outlen, + const unsigned char *in, unsigned long long inlen, + const spx_ctx *ctx) { unsigned long long i; unsigned char s[64]; unsigned char d[32]; @@ -345,30 +339,30 @@ void PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_haraka_S(unsigned char *out, unsigned for (i = 0; i < 64; i++) { s[i] = 0; } - haraka_S_absorb(s, in, inlen, 0x1F, state); + haraka_S_absorb(s, HARAKAS_RATE, in, inlen, 0x1F, ctx); - haraka_S_squeezeblocks(out, outlen / HARAKAS_RATE, s, HARAKAS_RATE, state); + haraka_S_squeezeblocks(out, outlen / HARAKAS_RATE, s, HARAKAS_RATE, ctx); out += (outlen / HARAKAS_RATE) * HARAKAS_RATE; if (outlen % HARAKAS_RATE) { - haraka_S_squeezeblocks(d, 1, s, HARAKAS_RATE, state); + haraka_S_squeezeblocks(d, 1, s, HARAKAS_RATE, ctx); for (i = 0; i < outlen % HARAKAS_RATE; i++) { out[i] = d[i]; } } } -void PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_haraka_Sx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned long long outlen, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - unsigned long long inlen, - const harakactx *state) { +void haraka_Sx4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned long long outlen, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + unsigned long long inlen, + const spx_ctx *ctx) { unsigned long long i; unsigned char s[64 * 4]; unsigned char d0[32]; @@ -379,16 +373,17 @@ void PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_haraka_Sx4(unsigned char *out0, for (i = 0; i < 64 * 4; i++) { s[i] = 0; } - haraka_S_absorb4x(s, in0, in1, in2, in3, inlen, 0x1F, state); + haraka_S_absorb4x(s, HARAKAS_RATE, in0, in1, in2, in3, inlen, 0x1F, ctx); - haraka_S_squeezeblocks4x(out0, out1, out2, out3, outlen / HARAKAS_RATE, s, HARAKAS_RATE, state); + haraka_S_squeezeblocks4x(out0, out1, out2, out3, outlen / HARAKAS_RATE, s, + HARAKAS_RATE, ctx); out0 += (outlen / HARAKAS_RATE) * HARAKAS_RATE; out1 += (outlen / HARAKAS_RATE) * HARAKAS_RATE; out2 += (outlen / HARAKAS_RATE) * HARAKAS_RATE; out3 += (outlen / HARAKAS_RATE) * HARAKAS_RATE; if (outlen % HARAKAS_RATE) { - haraka_S_squeezeblocks4x(d0, d1, d2, d3, 1, s, HARAKAS_RATE, state); + haraka_S_squeezeblocks4x(d0, d1, d2, d3, 1, s, HARAKAS_RATE, ctx); for (i = 0; i < outlen % HARAKAS_RATE; i++) { out0[i] = d0[i]; out1[i] = d1[i]; @@ -398,7 +393,8 @@ void PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_haraka_Sx4(unsigned char *out0, } } -void PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_haraka512_perm(unsigned char *out, const unsigned char *in, const harakactx *state) { +void haraka512_perm(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx) { u128 s[4], tmp; s[0] = LOAD(in); @@ -406,19 +402,19 @@ void PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_haraka512_perm(unsigned char *out, co s[2] = LOAD(in + 32); s[3] = LOAD(in + 48); - AES4(s[0], s[1], s[2], s[3], state->rc); + AES4(s[0], s[1], s[2], s[3], ctx->rc); MIX4(s[0], s[1], s[2], s[3]); - AES4(s[0], s[1], s[2], s[3], state->rc + 8); + AES4(s[0], s[1], s[2], s[3], ctx->rc + 8); MIX4(s[0], s[1], s[2], s[3]); - AES4(s[0], s[1], s[2], s[3], state->rc + 16); + AES4(s[0], s[1], s[2], s[3], ctx->rc + 16); MIX4(s[0], s[1], s[2], s[3]); - AES4(s[0], s[1], s[2], s[3], state->rc + 24); + AES4(s[0], s[1], s[2], s[3], ctx->rc + 24); MIX4(s[0], s[1], s[2], s[3]); - AES4(s[0], s[1], s[2], s[3], state->rc + 32); + AES4(s[0], s[1], s[2], s[3], ctx->rc + 32); MIX4(s[0], s[1], s[2], s[3]); STORE(out, s[0]); @@ -427,7 +423,8 @@ void PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_haraka512_perm(unsigned char *out, co STORE(out + 48, s[3]); } -void PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_haraka512_perm_x4(unsigned char *out, const unsigned char *in, const harakactx *state) { +void haraka512_perm_x4(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx) { u128 s[4][4], tmp; s[0][0] = LOAD(in); @@ -447,31 +444,31 @@ void PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_haraka512_perm_x4(unsigned char *out, s[3][2] = LOAD(in + 224); s[3][3] = LOAD(in + 240); - AES4_4x(s[0], s[1], s[2], s[3], state->rc); + AES4_4x(s[0], s[1], s[2], s[3], ctx->rc); MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - AES4_4x(s[0], s[1], s[2], s[3], state->rc + 8); + AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 8); MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - AES4_4x(s[0], s[1], s[2], s[3], state->rc + 16); + AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 16); MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - AES4_4x(s[0], s[1], s[2], s[3], state->rc + 24); + AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 24); MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - AES4_4x(s[0], s[1], s[2], s[3], state->rc + 32); + AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 32); MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); @@ -495,7 +492,8 @@ void PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_haraka512_perm_x4(unsigned char *out, STORE(out + 240, s[3][3]); } -void PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_haraka512(unsigned char *out, const unsigned char *in, const harakactx *state) { +void haraka512(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx) { u128 s[4], tmp; s[0] = LOAD(in); @@ -503,19 +501,19 @@ void PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_haraka512(unsigned char *out, const u s[2] = LOAD(in + 32); s[3] = LOAD(in + 48); - AES4(s[0], s[1], s[2], s[3], state->rc); + AES4(s[0], s[1], s[2], s[3], ctx->rc); MIX4(s[0], s[1], s[2], s[3]); - AES4(s[0], s[1], s[2], s[3], state->rc + 8); + AES4(s[0], s[1], s[2], s[3], ctx->rc + 8); MIX4(s[0], s[1], s[2], s[3]); - AES4(s[0], s[1], s[2], s[3], state->rc + 16); + AES4(s[0], s[1], s[2], s[3], ctx->rc + 16); MIX4(s[0], s[1], s[2], s[3]); - AES4(s[0], s[1], s[2], s[3], state->rc + 24); + AES4(s[0], s[1], s[2], s[3], ctx->rc + 24); MIX4(s[0], s[1], s[2], s[3]); - AES4(s[0], s[1], s[2], s[3], state->rc + 32); + AES4(s[0], s[1], s[2], s[3], ctx->rc + 32); MIX4(s[0], s[1], s[2], s[3]); s[0] = XOR128(s[0], LOAD(in)); @@ -527,7 +525,8 @@ void PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_haraka512(unsigned char *out, const u TRUNCSTORE(out, s[0], s[1], s[2], s[3]); } -void PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_haraka512x4(unsigned char *out, const unsigned char *in, const harakactx *state) { +void haraka512x4(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx) { u128 s[4][4], tmp; s[0][0] = LOAD(in); @@ -547,31 +546,31 @@ void PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_haraka512x4(unsigned char *out, const s[3][2] = LOAD(in + 224); s[3][3] = LOAD(in + 240); - AES4_4x(s[0], s[1], s[2], s[3], state->rc); + AES4_4x(s[0], s[1], s[2], s[3], ctx->rc); MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - AES4_4x(s[0], s[1], s[2], s[3], state->rc + 8); + AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 8); MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - AES4_4x(s[0], s[1], s[2], s[3], state->rc + 16); + AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 16); MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - AES4_4x(s[0], s[1], s[2], s[3], state->rc + 24); + AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 24); MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - AES4_4x(s[0], s[1], s[2], s[3], state->rc + 32); + AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 32); MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); @@ -600,25 +599,26 @@ void PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_haraka512x4(unsigned char *out, const TRUNCSTORE((out + 96), s[3][0], s[3][1], s[3][2], s[3][3]); } -void PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_haraka256(unsigned char *out, const unsigned char *in, const harakactx *state) { +void haraka256(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx) { u128 s[2], tmp; s[0] = LOAD(in); s[1] = LOAD(in + 16); - AES2(s[0], s[1], state->rc); + AES2(s[0], s[1], ctx->rc); MIX2(s[0], s[1]); - AES2(s[0], s[1], state->rc + 4); + AES2(s[0], s[1], ctx->rc + 4); MIX2(s[0], s[1]); - AES2(s[0], s[1], state->rc + 8); + AES2(s[0], s[1], ctx->rc + 8); MIX2(s[0], s[1]); - AES2(s[0], s[1], state->rc + 12); + AES2(s[0], s[1], ctx->rc + 12); MIX2(s[0], s[1]); - AES2(s[0], s[1], state->rc + 16); + AES2(s[0], s[1], ctx->rc + 16); MIX2(s[0], s[1]); s[0] = XOR128(s[0], LOAD(in)); @@ -628,7 +628,8 @@ void PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_haraka256(unsigned char *out, const u STORE(out + 16, s[1]); } -void PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_haraka256x4(unsigned char *out, const unsigned char *in, const harakactx *state) { +void haraka256x4(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx) { u128 s[4][2], tmp; s[0][0] = LOAD(in); @@ -641,7 +642,7 @@ void PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_haraka256x4(unsigned char *out, const s[3][1] = LOAD(in + 112); // Round 1 - AES2_4x(s[0], s[1], s[2], s[3], state->rc); + AES2_4x(s[0], s[1], s[2], s[3], ctx->rc); MIX2(s[0][0], s[0][1]); MIX2(s[1][0], s[1][1]); @@ -649,7 +650,7 @@ void PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_haraka256x4(unsigned char *out, const MIX2(s[3][0], s[3][1]); // Round 2 - AES2_4x(s[0], s[1], s[2], s[3], state->rc + 4); + AES2_4x(s[0], s[1], s[2], s[3], ctx->rc + 4); MIX2(s[0][0], s[0][1]); MIX2(s[1][0], s[1][1]); @@ -657,7 +658,7 @@ void PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_haraka256x4(unsigned char *out, const MIX2(s[3][0], s[3][1]); // Round 3 - AES2_4x(s[0], s[1], s[2], s[3], state->rc + 8); + AES2_4x(s[0], s[1], s[2], s[3], ctx->rc + 8); MIX2(s[0][0], s[0][1]); MIX2(s[1][0], s[1][1]); @@ -665,7 +666,7 @@ void PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_haraka256x4(unsigned char *out, const MIX2(s[3][0], s[3][1]); // Round 4 - AES2_4x(s[0], s[1], s[2], s[3], state->rc + 12); + AES2_4x(s[0], s[1], s[2], s[3], ctx->rc + 12); MIX2(s[0][0], s[0][1]); MIX2(s[1][0], s[1][1]); @@ -673,7 +674,7 @@ void PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_haraka256x4(unsigned char *out, const MIX2(s[3][0], s[3][1]); // Round 5 - AES2_4x(s[0], s[1], s[2], s[3], state->rc + 16); + AES2_4x(s[0], s[1], s[2], s[3], ctx->rc + 16); MIX2(s[0][0], s[0][1]); MIX2(s[1][0], s[1][1]); @@ -699,103 +700,3 @@ void PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_haraka256x4(unsigned char *out, const STORE(out + 96, s[3][0]); STORE(out + 112, s[3][1]); } - -void PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_haraka256_sk(unsigned char *out, const unsigned char *in, const harakactx *state) { - u128 s[2], tmp; - - s[0] = LOAD(in); - s[1] = LOAD(in + 16); - - AES2(s[0], s[1], state->rc_sseed); - MIX2(s[0], s[1]); - - AES2(s[0], s[1], state->rc_sseed + 4); - MIX2(s[0], s[1]); - - AES2(s[0], s[1], state->rc_sseed + 8); - MIX2(s[0], s[1]); - - AES2(s[0], s[1], state->rc_sseed + 12); - MIX2(s[0], s[1]); - - AES2(s[0], s[1], state->rc_sseed + 16); - MIX2(s[0], s[1]); - - s[0] = XOR128(s[0], LOAD(in)); - s[1] = XOR128(s[1], LOAD(in + 16)); - - STORE(out, s[0]); - STORE(out + 16, s[1]); -} - -void PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_haraka256_skx4(unsigned char *out, const unsigned char *in, const harakactx *state) { - u128 s[4][2], tmp; - - s[0][0] = LOAD(in); - s[0][1] = LOAD(in + 16); - s[1][0] = LOAD(in + 32); - s[1][1] = LOAD(in + 48); - s[2][0] = LOAD(in + 64); - s[2][1] = LOAD(in + 80); - s[3][0] = LOAD(in + 96); - s[3][1] = LOAD(in + 112); - - // Round 1 - AES2_4x(s[0], s[1], s[2], s[3], state->rc_sseed); - - MIX2(s[0][0], s[0][1]); - MIX2(s[1][0], s[1][1]); - MIX2(s[2][0], s[2][1]); - MIX2(s[3][0], s[3][1]); - - // Round 2 - AES2_4x(s[0], s[1], s[2], s[3], state->rc_sseed + 4); - - MIX2(s[0][0], s[0][1]); - MIX2(s[1][0], s[1][1]); - MIX2(s[2][0], s[2][1]); - MIX2(s[3][0], s[3][1]); - - // Round 3 - AES2_4x(s[0], s[1], s[2], s[3], state->rc_sseed + 8); - - MIX2(s[0][0], s[0][1]); - MIX2(s[1][0], s[1][1]); - MIX2(s[2][0], s[2][1]); - MIX2(s[3][0], s[3][1]); - - // Round 4 - AES2_4x(s[0], s[1], s[2], s[3], state->rc_sseed + 12); - - MIX2(s[0][0], s[0][1]); - MIX2(s[1][0], s[1][1]); - MIX2(s[2][0], s[2][1]); - MIX2(s[3][0], s[3][1]); - - // Round 5 - AES2_4x(s[0], s[1], s[2], s[3], state->rc_sseed + 16); - - MIX2(s[0][0], s[0][1]); - MIX2(s[1][0], s[1][1]); - MIX2(s[2][0], s[2][1]); - MIX2(s[3][0], s[3][1]); - - // Feed Forward - s[0][0] = XOR128(s[0][0], LOAD(in)); - s[0][1] = XOR128(s[0][1], LOAD(in + 16)); - s[1][0] = XOR128(s[1][0], LOAD(in + 32)); - s[1][1] = XOR128(s[1][1], LOAD(in + 48)); - s[2][0] = XOR128(s[2][0], LOAD(in + 64)); - s[2][1] = XOR128(s[2][1], LOAD(in + 80)); - s[3][0] = XOR128(s[3][0], LOAD(in + 96)); - s[3][1] = XOR128(s[3][1], LOAD(in + 112)); - - STORE(out, s[0][0]); - STORE(out + 16, s[0][1]); - STORE(out + 32, s[1][0]); - STORE(out + 48, s[1][1]); - STORE(out + 64, s[2][0]); - STORE(out + 80, s[2][1]); - STORE(out + 96, s[3][0]); - STORE(out + 112, s[3][1]); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/haraka.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/haraka.h index 9805202b57..737cb6065f 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/haraka.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/haraka.h @@ -1,57 +1,42 @@ -#ifndef PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_HARAKA_H -#define PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_HARAKA_H +#ifndef SPX_HARAKA_H +#define SPX_HARAKA_H -#include -#include -#include - -typedef struct { - __m128i rc[40]; - __m128i rc_sseed[40]; -} harakactx; +#include "context.h" +#include "params.h" /* Tweak constants with seed */ -void PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_tweak_constants( - harakactx *state, - const unsigned char *pk_seed, const unsigned char *sk_seed, - unsigned long long seed_length); +#define tweak_constants SPX_NAMESPACE(tweak_constants) +void tweak_constants(spx_ctx *ctx); /* Haraka Sponge */ -void PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_haraka_S_inc_init(uint8_t *s_inc); -void PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, const harakactx *state); -void PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_haraka_S_inc_finalize(uint8_t *s_inc); -void PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, const harakactx *state); -void PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_haraka_S( - unsigned char *out, unsigned long long outlen, - const unsigned char *in, unsigned long long inlen, const harakactx *state); -void PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_haraka_Sx4( - unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned long long outlen, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - unsigned long long inlen, - const harakactx *state); - +#define haraka_S_inc_init SPX_NAMESPACE(haraka_S_inc_init) +void haraka_S_inc_init(uint8_t *s_inc); +#define haraka_S_inc_absorb SPX_NAMESPACE(haraka_S_inc_absorb) +void haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, + const spx_ctx *ctx); +#define haraka_S_inc_finalize SPX_NAMESPACE(haraka_S_inc_finalize) +void haraka_S_inc_finalize(uint8_t *s_inc); +#define haraka_S_inc_squeeze SPX_NAMESPACE(haraka_S_inc_squeeze) +void haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, + const spx_ctx *ctx); +#define haraka_S SPX_NAMESPACE(haraka_S) +void haraka_S(unsigned char *out, unsigned long long outlen, + const unsigned char *in, unsigned long long inlen, + const spx_ctx *ctx); /* Applies the 512-bit Haraka permutation to in. */ -void PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_haraka512_perm(unsigned char *out, const unsigned char *in, const harakactx *state); -void PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_haraka512_perm_x4(unsigned char *out, const unsigned char *in, const harakactx *state); +#define haraka512_perm SPX_NAMESPACE(haraka512_perm) +void haraka512_perm(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx); /* Implementation of Haraka-512 */ -void PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_haraka512(unsigned char *out, const unsigned char *in, const harakactx *state); -void PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_haraka512x4(unsigned char *out, const unsigned char *in, const harakactx *state); +#define haraka512 SPX_NAMESPACE(haraka512) +void haraka512(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx); /* Implementation of Haraka-256 */ -void PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_haraka256(unsigned char *out, const unsigned char *in, const harakactx *state); -void PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_haraka256x4(unsigned char *out, const unsigned char *in, const harakactx *state); - -/* Implementation of Haraka-256 using sk.seed constants */ -void PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_haraka256_sk(unsigned char *out, const unsigned char *in, const harakactx *state); -void PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_haraka256_skx4(unsigned char *out, const unsigned char *in, const harakactx *state); +#define haraka256 SPX_NAMESPACE(haraka256) +void haraka256(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/haraka_offsets.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/haraka_offsets.h new file mode 100644 index 0000000000..7c062272a0 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/haraka_offsets.h @@ -0,0 +1,21 @@ +#ifndef HARAKA_OFFSETS_H_ +#define HARAKA_OFFSETS_H_ + +/* + * Offsets of various fields in the address structure when we use Haraka as + * the Sphincs+ hash function + */ + +#define SPX_OFFSET_LAYER 3 /* The byte used to specify the Merkle tree layer */ +#define SPX_OFFSET_TREE 8 /* The start of the 8 byte field used to specify the tree */ +#define SPX_OFFSET_TYPE 19 /* The byte used to specify the hash type (reason) */ +#define SPX_OFFSET_KP_ADDR2 22 /* The high byte used to specify the key pair (which one-time signature) */ +#define SPX_OFFSET_KP_ADDR1 23 /* The low byte used to specify the key pair */ +#define SPX_OFFSET_CHAIN_ADDR 27 /* The byte used to specify the chain address (which Winternitz chain) */ +#define SPX_OFFSET_HASH_ADDR 31 /* The byte used to specify the hash address (where in the Winternitz chain) */ +#define SPX_OFFSET_TREE_HGT 27 /* The byte used to specify the height of this node in the FORS or Merkle tree */ +#define SPX_OFFSET_TREE_INDEX 28 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ + +#define SPX_HARAKA 1 + +#endif /* HARAKA_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/harakax4.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/harakax4.h new file mode 100644 index 0000000000..eadc69aa48 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/harakax4.h @@ -0,0 +1,36 @@ +#ifndef SPX_HARAKAX4_H +#define SPX_HARAKAX4_H + +#include "context.h" +#include "params.h" + +/* Haraka Sponge */ +#define haraka_Sx4 SPX_NAMESPACE(haraka_Sx4) +void haraka_Sx4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned long long outlen, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + unsigned long long inlen, + const spx_ctx *ctx); + +/* Applies the 512-bit Haraka permutation x4 to in. */ +#define haraka512_perm_x4 SPX_NAMESPACE(haraka512_perm_x4) +void haraka512_perm_x4(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx); + +/* Implementation of Haraka-512 x4*/ +#define haraka512x4 SPX_NAMESPACE(haraka512x4) +void haraka512x4(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx); + +/* Implementation of Haraka-256 x4 */ +#define haraka256x4 SPX_NAMESPACE(haraka256x4) +void haraka256x4(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/hash.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/hash.h index cbdc30d2a7..f7c87d4c3c 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/hash.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/hash.h @@ -1,31 +1,28 @@ -#ifndef PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_HASH_H -#define PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_HASH_H - -#include "hash_state.h" +#ifndef SPX_HASH_H +#define SPX_HASH_H #include #include -void PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_initialize_hash_function( - hash_state *hash_state_seeded, - const unsigned char *pub_seed, const unsigned char *sk_seed); +#include "context.h" +#include "params.h" + +#define prf_addr SPX_NAMESPACE(prf_addr) +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]); -void PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_destroy_hash_function(hash_state *hash_state_seeded); +#define gen_message_random SPX_NAMESPACE(gen_message_random) +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); -void PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded); +#define hash_message SPX_NAMESPACE(hash_message) +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); -void PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); -void PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/hash_haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/hash_haraka.c index 35c2f9673b..750a67423b 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/hash_haraka.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/hash_haraka.c @@ -2,58 +2,44 @@ #include #include "address.h" -#include "haraka.h" -#include "hash.h" #include "params.h" #include "utils.h" -void PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_initialize_hash_function( - hash_state *hash_state_seeded, - const unsigned char *pub_seed, const unsigned char *sk_seed) { - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_tweak_constants(hash_state_seeded, pub_seed, sk_seed, PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N); -} - -/* The haraka implementation is stack based and won't be replaced in PQClean/OQS, - so we don't need to do anything */ -void PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_destroy_hash_function( - hash_state *hash_state_seeded) { // NOLINT(readability-non-const-parameter) - (void)hash_state_seeded; -} +#include "haraka.h" +#include "hash.h" /* - * Computes PRF(key, addr), given a secret key of PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N bytes and an address + * Computes PRF(key, addr), given a secret key of SPX_N bytes and an address */ -void PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded) { - unsigned char buf[PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_ADDR_BYTES]; - /* Since PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N may be smaller than 32, we need a temporary buffer. */ +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]) { + /* Since SPX_N may be smaller than 32, we need temporary buffers. */ unsigned char outbuf[32]; + unsigned char buf[64] = {0}; - (void)key; /* Suppress an 'unused parameter' warning. */ + memcpy(buf, addr, SPX_ADDR_BYTES); + memcpy(buf + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_addr_to_bytes(buf, addr); - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_haraka256_sk(outbuf, buf, hash_state_seeded); - memcpy(out, outbuf, PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N); + haraka512(outbuf, (const void *)buf, ctx); + memcpy(out, outbuf, SPX_N); } /** * Computes the message-dependent randomness R, using a secret seed and an * optional randomization value as well as the message. */ -void PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded) { +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { uint8_t s_inc[65]; - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_haraka_S_inc_init(s_inc); - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_haraka_S_inc_absorb(s_inc, sk_prf, PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_haraka_S_inc_absorb(s_inc, optrand, PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_haraka_S_inc_absorb(s_inc, m, mlen, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_haraka_S_inc_finalize(s_inc); - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_haraka_S_inc_squeeze(R, PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N, s_inc, hash_state_seeded); + haraka_S_inc_init(s_inc); + haraka_S_inc_absorb(s_inc, sk_prf, SPX_N, ctx); + haraka_S_inc_absorb(s_inc, optrand, SPX_N, ctx); + haraka_S_inc_absorb(s_inc, m, mlen, ctx); + haraka_S_inc_finalize(s_inc); + haraka_S_inc_squeeze(R, SPX_N, s_inc, ctx); } /** @@ -61,36 +47,35 @@ void PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_gen_message_random( * Outputs the message digest and the index of the leaf. The index is split in * the tree index and the leaf index, for convenient copying to an address. */ -void PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded) { -#define PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_TREE_BITS (PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_TREE_HEIGHT * (PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_D - 1)) -#define PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_TREE_BYTES ((PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_TREE_BITS + 7) / 8) -#define PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_LEAF_BITS PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_TREE_HEIGHT -#define PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_LEAF_BYTES ((PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_LEAF_BITS + 7) / 8) -#define PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_DGST_BYTES (PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_FORS_MSG_BYTES + PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_TREE_BYTES + PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_LEAF_BYTES) +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { +#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) +#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) +#define SPX_LEAF_BITS SPX_TREE_HEIGHT +#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) +#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) - unsigned char buf[PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_DGST_BYTES]; + unsigned char buf[SPX_DGST_BYTES]; unsigned char *bufp = buf; uint8_t s_inc[65]; - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_haraka_S_inc_init(s_inc); - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_haraka_S_inc_absorb(s_inc, R, PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_haraka_S_inc_absorb(s_inc, pk + PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N, PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_haraka_S_inc_absorb(s_inc, m, mlen, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_haraka_S_inc_finalize(s_inc); - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_haraka_S_inc_squeeze(buf, PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_DGST_BYTES, s_inc, hash_state_seeded); + haraka_S_inc_init(s_inc); + haraka_S_inc_absorb(s_inc, R, SPX_N, ctx); + haraka_S_inc_absorb(s_inc, pk + SPX_N, SPX_N, ctx); // Only absorb root part of pk + haraka_S_inc_absorb(s_inc, m, mlen, ctx); + haraka_S_inc_finalize(s_inc); + haraka_S_inc_squeeze(buf, SPX_DGST_BYTES, s_inc, ctx); + + memcpy(digest, bufp, SPX_FORS_MSG_BYTES); + bufp += SPX_FORS_MSG_BYTES; - memcpy(digest, bufp, PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_FORS_MSG_BYTES); - bufp += PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_FORS_MSG_BYTES; - *tree = PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_bytes_to_ull(bufp, PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_TREE_BYTES); - *tree &= (~(uint64_t)0) >> (64 - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_TREE_BITS); - bufp += PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_TREE_BYTES; + *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); + *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); + bufp += SPX_TREE_BYTES; - *leaf_idx = (uint32_t)PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_bytes_to_ull( - bufp, PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_LEAF_BYTES); - *leaf_idx &= (~(uint32_t)0) >> (32 - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_LEAF_BITS); + *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); + *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/hash_harakax4.c b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/hash_harakax4.c index 862c760e45..cfa5162d79 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/hash_harakax4.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/hash_harakax4.c @@ -2,36 +2,34 @@ #include #include "address.h" -#include "haraka.h" -#include "hash_state.h" +#include "harakax4.h" #include "hashx4.h" #include "params.h" /* * 4-way parallel version of prf_addr; takes 4x as much input and output */ -void PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_prf_addrx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const unsigned char *key, - const uint32_t addrx4[4 * 8], - const hash_state *state_seeded) { - unsigned char bufx4[4 * PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_ADDR_BYTES]; - /* Since PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N may be smaller than 32, we need a temporary buffer. */ +#define prf_addrx4 SPX_NAMESPACE(prf_addrx4) +void prf_addrx4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const spx_ctx *ctx, + const uint32_t addrx4[4 * 8]) { + unsigned char bufx4[4 * 64] = {0}; + /* Since SPX_N may be smaller than 32, we need temporary buffers. */ unsigned char outbuf[4 * 32]; unsigned int i; - (void)key; /* Suppress an 'unused parameter' warning. */ - for (i = 0; i < 4; i++) { - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_addr_to_bytes(bufx4 + i * PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_ADDR_BYTES, addrx4 + i * 8); + memcpy(bufx4 + i * 64, addrx4 + i * 8, SPX_ADDR_BYTES); + memcpy(bufx4 + i * 64 + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); } - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_haraka256_skx4(outbuf, bufx4, state_seeded); + haraka512x4(outbuf, bufx4, ctx); - memcpy(out0, outbuf, PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N); - memcpy(out1, outbuf + 32, PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N); - memcpy(out2, outbuf + 64, PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N); - memcpy(out3, outbuf + 96, PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N); + memcpy(out0, outbuf, SPX_N); + memcpy(out1, outbuf + 32, SPX_N); + memcpy(out2, outbuf + 64, SPX_N); + memcpy(out3, outbuf + 96, SPX_N); } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/hash_state.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/hash_state.h deleted file mode 100644 index 11e3ad9356..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/hash_state.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_HASH_STATE_H -#define PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_HASH_STATE_H - -/** - * Defines the type of the hash function state. - * - * Don't be fooled into thinking this instance of SPHINCS+ isn't stateless! - * - * From Section 7.2.2 from the SPHINCS+ round-2 specification: - * - * Each of the instances of the tweakable hash function take PK.seed as its - * first input, which is constant for a given key pair – and, thus, across - * a single signature. This leads to a lot of redundant computation. To remedy - * this, we pad PK.seed to the length of a full 64-byte SHA-256 input block. - * Because of the Merkle-DamgÃ¥rd construction that underlies SHA-256, this - * allows for reuse of the intermediate SHA-256 state after the initial call to - * the compression function which improves performance. - * - * We pass this hash state around in functions, because otherwise we need to - * have a global variable. - */ - -#include "haraka.h" -#define hash_state harakactx - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/hashx4.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/hashx4.h index c754cbe6b9..3751a0ebd0 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/hashx4.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/hashx4.h @@ -1,16 +1,17 @@ -#ifndef PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_HASHX4_H -#define PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_HASHX4_H +#ifndef SPX_HASHX4_H +#define SPX_HASHX4_H #include -#include "hash_state.h" +#include "context.h" +#include "params.h" -void PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_prf_addrx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const unsigned char *key, - const uint32_t addrx4[4 * 8], - const hash_state *state_seeded); +#define prf_addrx4 SPX_NAMESPACE(prf_addrx4) +void prf_addrx4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const spx_ctx *ctx, + const uint32_t addrx4[4 * 8]); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/merkle.c b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/merkle.c new file mode 100644 index 0000000000..f57811c1ac --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/merkle.c @@ -0,0 +1,64 @@ +#include +#include + +#include "merkle.h" + +#include "address.h" +#include "params.h" +#include "utils.h" +#include "utilsx4.h" +#include "wots.h" +#include "wotsx4.h" + +/* + * This generates a Merkle signature (WOTS signature followed by the Merkle + * authentication path). + */ +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf) { + unsigned char *auth_path = sig + SPX_WOTS_BYTES; + uint32_t tree_addrx4[4 * 8] = { 0 }; + int j; + struct leaf_info_x4 info = { 0 }; + unsigned steps[ SPX_WOTS_LEN ]; + + info.wots_sig = sig; + chain_lengths(steps, root); + info.wots_steps = steps; + + for (j = 0; j < 4; j++) { + set_type(&tree_addrx4[8 * j], SPX_ADDR_TYPE_HASHTREE); + set_type(&info.leaf_addr[8 * j], SPX_ADDR_TYPE_WOTS); + set_type(&info.pk_addr[8 * j], SPX_ADDR_TYPE_WOTSPK); + copy_subtree_addr(&tree_addrx4[8 * j], tree_addr); + copy_subtree_addr(&info.leaf_addr[8 * j], wots_addr); + copy_subtree_addr(&info.pk_addr[8 * j], wots_addr); + } + + info.wots_sign_leaf = idx_leaf; + + treehashx4(root, auth_path, ctx, + idx_leaf, 0, + SPX_TREE_HEIGHT, + wots_gen_leafx4, + tree_addrx4, &info); +} + +/* Compute root node of the top-most subtree. */ +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { + /* We do not need the auth path in key generation, but it simplifies the + code to have just one treehash routine that computes both root and path + in one function. */ + unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; + uint32_t top_tree_addr[8] = {0}; + uint32_t wots_addr[8] = {0}; + + set_layer_addr(top_tree_addr, SPX_D - 1); + set_layer_addr(wots_addr, SPX_D - 1); + + merkle_sign(auth_path, root, ctx, + wots_addr, top_tree_addr, + ~0U /* ~0 means "don't bother generating an auth path */ ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/merkle.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/merkle.h new file mode 100644 index 0000000000..769cf2e970 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/merkle.h @@ -0,0 +1,21 @@ +#ifndef MERKLE_H_ +#define MERKLE_H_ + +#include + +#include "context.h" +#include "params.h" + +/* Generate a Merkle signature (WOTS signature followed by the Merkle */ +/* authentication path) */ +#define merkle_sign SPX_NAMESPACE(merkle_sign) +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf); + +/* Compute the root node of the top-most subtree. */ +#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); + +#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/nistapi.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/nistapi.h new file mode 100644 index 0000000000..3cb71afad4 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/nistapi.h @@ -0,0 +1,87 @@ +#ifndef SPX_API_H +#define SPX_API_H + +#include +#include + +#include "params.h" + +#define CRYPTO_ALGNAME "SPHINCS+" + +#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES +#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES +#define CRYPTO_BYTES SPX_BYTES +#define CRYPTO_SEEDBYTES (3*SPX_N) + +/* + * Returns the length of a secret key, in bytes + */ +#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) +size_t crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) +size_t crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) +size_t crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) +size_t crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +#define crypto_sign SPX_NAMESPACE(crypto_sign) +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/params.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/params.h index 30032b960a..e79b0d9fa5 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/params.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/params.h @@ -1,53 +1,56 @@ -#ifndef PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_PARAMS_H -#define PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_PARAMS_H +#ifndef SPX_PARAMS_H +#define SPX_PARAMS_H + +#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_##s /* Hash output length in bytes. */ -#define PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N 32 +#define SPX_N 32 /* Height of the hypertree. */ -#define PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_FULL_HEIGHT 64 +#define SPX_FULL_HEIGHT 64 /* Number of subtree layer. */ -#define PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_D 8 +#define SPX_D 8 /* FORS tree dimensions. */ -#define PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_FORS_HEIGHT 14 -#define PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_FORS_TREES 22 +#define SPX_FORS_HEIGHT 14 +#define SPX_FORS_TREES 22 /* Winternitz parameter, */ -#define PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_WOTS_W 16 +#define SPX_WOTS_W 16 /* The hash function is defined by linking a different hash.c file, as opposed to setting a #define constant. */ /* For clarity */ -#define PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_ADDR_BYTES 32 +#define SPX_ADDR_BYTES 32 /* WOTS parameters. */ -#define PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_WOTS_LOGW 4 +#define SPX_WOTS_LOGW 4 -#define PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_WOTS_LEN1 (8 * PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N / PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_WOTS_LOGW) +#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) -/* PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#define PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_WOTS_LEN2 3 +/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ +#define SPX_WOTS_LEN2 3 -#define PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_WOTS_LEN (PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_WOTS_LEN1 + PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_WOTS_LEN2) -#define PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_WOTS_BYTES (PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_WOTS_LEN * PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N) -#define PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_WOTS_PK_BYTES PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_WOTS_BYTES +#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) +#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) +#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES /* Subtree size. */ -#define PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_TREE_HEIGHT (PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_FULL_HEIGHT / PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_D) +#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) + +//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT +// #error SPX_D should always divide SPX_FULL_HEIGHT +//#endif /* FORS parameters. */ -#define PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_FORS_MSG_BYTES ((PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_FORS_TREES + 7) / 8) -#define PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_FORS_BYTES ((PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_FORS_HEIGHT + 1) * PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_FORS_TREES * PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N) -#define PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_FORS_PK_BYTES PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N +#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) +#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) +#define SPX_FORS_PK_BYTES SPX_N /* Resulting SPX sizes. */ -#define PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_BYTES (PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N + PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_FORS_BYTES + PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_D * PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_WOTS_BYTES +\ - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_FULL_HEIGHT * PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N) -#define PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_PK_BYTES (2 * PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N) -#define PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_SK_BYTES (2 * PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N + PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_PK_BYTES) - -/* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ -#define PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_OPTRAND_BYTES 32 +#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ + SPX_FULL_HEIGHT * SPX_N) +#define SPX_PK_BYTES (2 * SPX_N) +#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) + +#include "haraka_offsets.h" #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/sign.c b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/sign.c index 08e2a3232f..9d0c7d1b22 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/sign.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/sign.c @@ -1,76 +1,45 @@ -#include #include #include #include #include "address.h" -#include "api.h" +#include "context.h" #include "fors.h" #include "hash.h" -#include "hash_state.h" +#include "merkle.h" +#include "nistapi.h" #include "params.h" #include "randombytes.h" #include "thash.h" #include "utils.h" #include "wots.h" - -/** - * Computes the leaf at a given address. First generates the WOTS key pair, - * then computes leaf by hashing horizontally. - */ -static void wots_gen_leaf(unsigned char *leaf, const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx, const uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - unsigned char pk[PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_WOTS_BYTES]; - uint32_t wots_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_set_type( - wots_addr, PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_set_type( - wots_pk_addr, PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_ADDR_TYPE_WOTSPK); - - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_set_keypair_addr( - wots_addr, addr_idx); - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_wots_gen_pk( - pk, sk_seed, pub_seed, wots_addr, hash_state_seeded); - - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_copy_keypair_addr( - wots_pk_addr, wots_addr); - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_thash_WOTS_LEN( - leaf, pk, pub_seed, wots_pk_addr, hash_state_seeded); -} - /* * Returns the length of a secret key, in bytes */ -size_t PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_crypto_sign_secretkeybytes(void) { - return PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_CRYPTO_SECRETKEYBYTES; +size_t crypto_sign_secretkeybytes(void) { + return CRYPTO_SECRETKEYBYTES; } /* * Returns the length of a public key, in bytes */ -size_t PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_crypto_sign_publickeybytes(void) { - return PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_CRYPTO_PUBLICKEYBYTES; +size_t crypto_sign_publickeybytes(void) { + return CRYPTO_PUBLICKEYBYTES; } /* * Returns the length of a signature, in bytes */ -size_t PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_crypto_sign_bytes(void) { - return PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_CRYPTO_BYTES; +size_t crypto_sign_bytes(void) { + return CRYPTO_BYTES; } /* * Returns the length of the seed required to generate a key pair, in bytes */ -size_t PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_crypto_sign_seedbytes(void) { - return PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_CRYPTO_SEEDBYTES; +size_t crypto_sign_seedbytes(void) { + return CRYPTO_SEEDBYTES; } /* @@ -78,35 +47,29 @@ size_t PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_crypto_sign_seedbytes(void) { * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] * Format pk: [PUB_SEED || root] */ -int PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed) { - /* We do not need the auth path in key generation, but it simplifies the - code to have just one treehash routine that computes both root and path - in one function. */ - unsigned char auth_path[PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_TREE_HEIGHT * PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N]; - uint32_t top_tree_addr[8] = {0}; - hash_state hash_state_seeded; - - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_set_layer_addr( - top_tree_addr, PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_D - 1); - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_set_type( - top_tree_addr, PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_ADDR_TYPE_HASHTREE); +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed) { + spx_ctx ctx; /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ - memcpy(sk, seed, PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_CRYPTO_SEEDBYTES); + memcpy(sk, seed, CRYPTO_SEEDBYTES); + + memcpy(pk, sk + 2 * SPX_N, SPX_N); - memcpy(pk, sk + 2 * PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N, PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N); + memcpy(ctx.pub_seed, pk, SPX_N); + memcpy(ctx.sk_seed, sk, SPX_N); /* This hook allows the hash function instantiation to do whatever preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_initialize_hash_function(&hash_state_seeded, pk, sk); + initialize_hash_function(&ctx); /* Compute root node of the top-most subtree. */ - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_treehash_TREE_HEIGHT( - sk + 3 * PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N, auth_path, sk, sk + 2 * PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N, 0, 0, - wots_gen_leaf, top_tree_addr, &hash_state_seeded); + merkle_gen_root(sk + 3 * SPX_N, &ctx); - memcpy(pk + PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N, sk + 3 * PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N, PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N); + // cleanup + free_hash_function(&ctx); + + memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); return 0; } @@ -116,31 +79,10 @@ int PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_crypto_sign_seed_keypair( * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] * Format pk: [PUB_SEED || root] */ -int PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk) { - - // guarantee alignment of pk - union { - __m128 _x[PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_CRYPTO_PUBLICKEYBYTES / 16]; - uint8_t pk[PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_CRYPTO_PUBLICKEYBYTES]; - } aligned_pk; - - // guarantee alignment of sk - union { - __m128 _x[PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_CRYPTO_SECRETKEYBYTES / 16]; - uint8_t sk[PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_CRYPTO_SECRETKEYBYTES]; - } aligned_sk; - - union { - __m128 _x[PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_CRYPTO_SEEDBYTES / 16]; - uint8_t seed[PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_CRYPTO_SEEDBYTES]; - } aligned_seed; - randombytes(aligned_seed.seed, PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_CRYPTO_SEEDBYTES); - - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_crypto_sign_seed_keypair( - aligned_pk.pk, aligned_sk.sk, aligned_seed.seed); - memcpy(pk, aligned_pk.pk, PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_CRYPTO_PUBLICKEYBYTES); - memcpy(sk, aligned_sk.sk, PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_CRYPTO_SECRETKEYBYTES); +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { + uint8_t seed[CRYPTO_SEEDBYTES]; + randombytes(seed, CRYPTO_SEEDBYTES); + crypto_sign_seed_keypair(pk, sk, seed); return 0; } @@ -148,101 +90,68 @@ int PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_crypto_sign_keypair( /** * Returns an array containing a detached signature. */ -int PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - // guarantee alignment of sk - union { - __m128 *_x; - uint8_t sk[PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_CRYPTO_SECRETKEYBYTES]; - } aligned_sk; - memcpy(aligned_sk.sk, sk, PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_CRYPTO_SECRETKEYBYTES); - sk = aligned_sk.sk; - - // guarantee alignment of sig - union { - __m128 *_x; - uint8_t sig[PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_BYTES]; - } aligned_sig; - uint8_t *orig_sig = sig; - sig = (uint8_t *)aligned_sig.sig; - - const unsigned char *sk_seed = sk; - const unsigned char *sk_prf = sk + PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N; - const unsigned char *pk = sk + 2 * PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N; - const unsigned char *pub_seed = pk; - - unsigned char optrand[PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N]; - unsigned char mhash[PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_FORS_MSG_BYTES]; - unsigned char root[PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N]; +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk) { + spx_ctx ctx; + + const uint8_t *sk_prf = sk + SPX_N; + const uint8_t *pk = sk + 2 * SPX_N; + + uint8_t optrand[SPX_N]; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t root[SPX_N]; uint32_t i; uint64_t tree; uint32_t idx_leaf; uint32_t wots_addr[8] = {0}; uint32_t tree_addr[8] = {0}; - hash_state hash_state_seeded; + memcpy(ctx.sk_seed, sk, SPX_N); + memcpy(ctx.pub_seed, pk, SPX_N); /* This hook allows the hash function instantiation to do whatever preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_initialize_hash_function( - &hash_state_seeded, - pub_seed, sk_seed); + initialize_hash_function(&ctx); - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_set_type( - wots_addr, PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_set_type( - tree_addr, PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_ADDR_TYPE_HASHTREE); + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); /* Optionally, signing can be made non-deterministic using optrand. This can help counter side-channel attacks that would benefit from getting a large number of traces when the signer uses the same nodes. */ - randombytes(optrand, PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N); + randombytes(optrand, SPX_N); /* Compute the digest randomization value. */ - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_gen_message_random( - sig, sk_prf, optrand, m, mlen, &hash_state_seeded); + gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); /* Derive the message digest and leaf index from R, PK and M. */ - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N; + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_set_keypair_addr( - wots_addr, idx_leaf); + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); /* Sign the message hash using FORS. */ - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_fors_sign( - sig, root, mhash, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_FORS_BYTES; - - for (i = 0; i < PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_D; i++) { - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_set_tree_addr(tree_addr, tree); - - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_set_keypair_addr( - wots_addr, idx_leaf); - - /* Compute a WOTS signature. */ - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_wots_sign( - sig, root, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_WOTS_BYTES; - - /* Compute the authentication path for the used WOTS leaf. */ - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_treehash_TREE_HEIGHT( - root, sig, sk_seed, pub_seed, idx_leaf, 0, - wots_gen_leaf, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_TREE_HEIGHT * PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N; + fors_sign(sig, root, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); + sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_TREE_HEIGHT; + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; } - memcpy(orig_sig, aligned_sig.sig, PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_BYTES); - *siglen = PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_BYTES; + free_hash_function(&ctx); + + *siglen = SPX_BYTES; return 0; } @@ -250,23 +159,14 @@ int PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_crypto_sign_signature( /** * Verifies a detached signature and message under a given public key. */ -int PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk) { - // guarantee alignment of pk - union { - __m128 *_x; - uint8_t pk[PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_CRYPTO_PUBLICKEYBYTES]; - } aligned_pk; - memcpy(aligned_pk.pk, pk, PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_CRYPTO_PUBLICKEYBYTES); - pk = aligned_pk.pk; - - const unsigned char *pub_seed = pk; - const unsigned char *pub_root = pk + PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N; - unsigned char mhash[PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_FORS_MSG_BYTES]; - unsigned char wots_pk[PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_WOTS_BYTES]; - unsigned char root[PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N]; - unsigned char leaf[PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N]; +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk) { + spx_ctx ctx; + const uint8_t *pub_root = pk + SPX_N; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t wots_pk[SPX_WOTS_BYTES]; + uint8_t root[SPX_N]; + uint8_t leaf[SPX_N]; unsigned int i; uint64_t tree; uint32_t idx_leaf; @@ -274,77 +174,66 @@ int PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_crypto_sign_verify( uint32_t tree_addr[8] = {0}; uint32_t wots_pk_addr[8] = {0}; - hash_state hash_state_seeded; - - if (siglen != PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_BYTES) { + if (siglen != SPX_BYTES) { return -1; } + memcpy(ctx.pub_seed, pk, SPX_N); + /* This hook allows the hash function instantiation to do whatever preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_initialize_hash_function( - &hash_state_seeded, - pub_seed, NULL); + initialize_hash_function(&ctx); - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_set_type( - wots_addr, PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_set_type( - tree_addr, PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_ADDR_TYPE_HASHTREE); - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_set_type( - wots_pk_addr, PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_ADDR_TYPE_WOTSPK); + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); /* Derive the message digest and leaf index from R || PK || M. */ - /* The additional PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N is a result of the hash domain separator. */ - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N; + /* The additional SPX_N is a result of the hash domain separator. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; /* Layer correctly defaults to 0, so no need to set_layer_addr */ - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_set_keypair_addr( - wots_addr, idx_leaf); + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_fors_pk_from_sig( - root, sig, mhash, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_FORS_BYTES; + fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; /* For each subtree.. */ - for (i = 0; i < PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_D; i++) { - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_set_tree_addr(tree_addr, tree); + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_set_keypair_addr( - wots_addr, idx_leaf); + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_copy_keypair_addr( - wots_pk_addr, wots_addr); + copy_keypair_addr(wots_pk_addr, wots_addr); /* The WOTS public key is only correct if the signature was correct. */ /* Initially, root is the FORS pk, but on subsequent iterations it is the root of the subtree below the currently processed subtree. */ - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_wots_pk_from_sig( - wots_pk, sig, root, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_WOTS_BYTES; + wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); + sig += SPX_WOTS_BYTES; /* Compute the leaf node using the WOTS public key. */ - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_thash_WOTS_LEN( - leaf, wots_pk, pub_seed, wots_pk_addr, &hash_state_seeded); + thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); /* Compute the root node of this subtree. */ - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_compute_root( - root, leaf, idx_leaf, 0, sig, PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_TREE_HEIGHT, - pub_seed, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_TREE_HEIGHT * PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N; + compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, + &ctx, tree_addr); + sig += SPX_TREE_HEIGHT * SPX_N; /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_TREE_HEIGHT; + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; } + // cleanup + free_hash_function(&ctx); + /* Check if the root node equals the root node in the public key. */ - if (memcmp(root, pub_root, PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N) != 0) { + if (memcmp(root, pub_root, SPX_N) != 0) { return -1; } @@ -355,15 +244,14 @@ int PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_crypto_sign_verify( /** * Returns an array containing the signature followed by the message. */ -int PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk) { size_t siglen; - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_crypto_sign_signature( - sm, &siglen, m, mlen, sk); + crypto_sign_signature(sm, &siglen, m, mlen, sk); - memmove(sm + PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_BYTES, m, mlen); + memmove(sm + SPX_BYTES, m, mlen); *smlen = siglen + mlen; return 0; @@ -372,38 +260,27 @@ int PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_crypto_sign( /** * Verifies a given signature-message pair under a given public key. */ -int PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk) { - - // guarantee alignment of pk - union { - __m128 *_x; - uint8_t pk[PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_CRYPTO_PUBLICKEYBYTES]; - } aligned_pk; - memcpy(aligned_pk.pk, pk, PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_CRYPTO_PUBLICKEYBYTES); - pk = aligned_pk.pk; - - +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk) { /* The API caller does not necessarily know what size a signature should be - but SPHINCS+ signatures are always exactly PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_BYTES. */ - if (smlen < PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_BYTES) { + but SPHINCS+ signatures are always exactly SPX_BYTES. */ + if (smlen < SPX_BYTES) { memset(m, 0, smlen); *mlen = 0; return -1; } - *mlen = smlen - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_BYTES; + *mlen = smlen - SPX_BYTES; - if (PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_crypto_sign_verify( - sm, PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_BYTES, sm + PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_BYTES, *mlen, pk)) { + if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { memset(m, 0, smlen); *mlen = 0; return -1; } /* If verification was successful, move the message to the right place. */ - memmove(m, sm + PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_BYTES, *mlen); + memmove(m, sm + SPX_BYTES, *mlen); return 0; } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/thash.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/thash.h index e3d3a28f22..8687ccfb4d 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/thash.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/thash.h @@ -1,28 +1,13 @@ -#ifndef PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_THASH_H -#define PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_THASH_H +#ifndef SPX_THASH_H +#define SPX_THASH_H -#include "hash_state.h" +#include "context.h" +#include "params.h" #include -void PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); +#define thash SPX_NAMESPACE(thash) +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/thash_haraka_robust.c b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/thash_haraka_robust.c index 4c5034dcfc..109502cbc2 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/thash_haraka_robust.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/thash_haraka_robust.c @@ -2,93 +2,44 @@ #include #include "address.h" -#include "hash_state.h" #include "params.h" #include "thash.h" +#include "utils.h" #include "haraka.h" /** - * Takes an array of inblocks concatenated arrays of PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N bytes. + * Takes an array of inblocks concatenated arrays of SPX_N bytes. */ -static void PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_thash( - unsigned char *out, unsigned char *buf, - const unsigned char *in, unsigned int inblocks, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char *bitmask = buf + PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_ADDR_BYTES; +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]) { + PQCLEAN_VLA(uint8_t, buf, SPX_ADDR_BYTES + inblocks * SPX_N); + PQCLEAN_VLA(uint8_t, bitmask, inblocks * SPX_N); unsigned char outbuf[32]; unsigned char buf_tmp[64]; unsigned int i; - (void)pub_seed; /* Suppress an 'unused parameter' warning. */ - if (inblocks == 1) { /* F function */ - /* Since PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N may be smaller than 32, we need a temporary buffer. */ + /* Since SPX_N may be smaller than 32, we need a temporary buffer. */ memset(buf_tmp, 0, 64); - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_addr_to_bytes(buf_tmp, addr); + memcpy(buf_tmp, addr, 32); - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_haraka256(outbuf, buf_tmp, hash_state_seeded); - for (i = 0; i < inblocks * PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N; i++) { - buf_tmp[PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_ADDR_BYTES + i] = in[i] ^ outbuf[i]; + haraka256(outbuf, buf_tmp, ctx); + for (i = 0; i < inblocks * SPX_N; i++) { + buf_tmp[SPX_ADDR_BYTES + i] = in[i] ^ outbuf[i]; } - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_haraka512(outbuf, buf_tmp, hash_state_seeded); - memcpy(out, outbuf, PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N); + haraka512(outbuf, buf_tmp, ctx); + memcpy(out, outbuf, SPX_N); } else { /* All other tweakable hashes*/ - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_addr_to_bytes(buf, addr); - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_haraka_S( - bitmask, inblocks * PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N, buf, PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_ADDR_BYTES, hash_state_seeded); + memcpy(buf, addr, 32); + haraka_S(bitmask, inblocks * SPX_N, buf, SPX_ADDR_BYTES, ctx); - for (i = 0; i < inblocks * PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N; i++) { - buf[PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_ADDR_BYTES + i] = in[i] ^ bitmask[i]; + for (i = 0; i < inblocks * SPX_N; i++) { + buf[SPX_ADDR_BYTES + i] = in[i] ^ bitmask[i]; } - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_haraka_S( - out, PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N, buf, PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N, hash_state_seeded); + haraka_S(out, SPX_N, buf, SPX_ADDR_BYTES + inblocks * SPX_N, ctx); } } - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_ADDR_BYTES + 1 * PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N]; - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_thash( - out, buf, in, 1, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_ADDR_BYTES + 2 * PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N]; - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_thash( - out, buf, in, 2, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_ADDR_BYTES + PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_WOTS_LEN * PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N]; - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_thash( - out, buf, in, PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_WOTS_LEN, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_ADDR_BYTES + PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_FORS_TREES * PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N]; - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_thash( - out, buf, in, PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_FORS_TREES, pub_seed, addr, hash_state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/thash_haraka_robustx4.c b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/thash_haraka_robustx4.c index 6dc19df069..100808a3a5 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/thash_haraka_robustx4.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/thash_haraka_robustx4.c @@ -2,91 +2,92 @@ #include #include "address.h" -#include "haraka.h" #include "params.h" #include "thashx4.h" +#include "harakax4.h" + +#include "utils.h" + /** * 4-way parallel version of thash; takes 4x as much input and output */ -#define thashx4_variant(name, inblocks) \ - void PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_thashx4_##name(unsigned char *out0, unsigned char *out1, unsigned char *out2, \ - unsigned char *out3, const unsigned char *in0, \ - const unsigned char *in1, const unsigned char *in2, \ - const unsigned char *in3, const unsigned char *pub_seed, \ - uint32_t addrx4[4 * 8], const harakactx *state) { \ - unsigned char buf0[PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_ADDR_BYTES + (inblocks)*PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N]; \ - unsigned char buf1[PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_ADDR_BYTES + (inblocks)*PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N]; \ - unsigned char buf2[PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_ADDR_BYTES + (inblocks)*PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N]; \ - unsigned char buf3[PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_ADDR_BYTES + (inblocks)*PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N]; \ - unsigned char bitmask0[(inblocks)*PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N]; \ - unsigned char bitmask1[(inblocks)*PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N]; \ - unsigned char bitmask2[(inblocks)*PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N]; \ - unsigned char bitmask3[(inblocks)*PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N]; \ - unsigned char outbuf[32 * 4]; \ - unsigned char buf_tmp[64 * 4]; \ - unsigned int i; \ - \ - (void)pub_seed; /* Suppress an 'unused parameter' warning. */ \ - \ - if ((inblocks) == 1) { \ - memset(buf_tmp, 0, 64 * 4); \ - \ - /* Generate masks first in buffer */ \ - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_addr_to_bytes(buf_tmp, addrx4 + 0 * 8); \ - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_addr_to_bytes(buf_tmp + 32, addrx4 + 1 * 8); \ - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_addr_to_bytes(buf_tmp + 64, addrx4 + 2 * 8); \ - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_addr_to_bytes(buf_tmp + 96, addrx4 + 3 * 8); \ - \ - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_haraka256x4(outbuf, buf_tmp, state); \ - \ - /* move addresses to make room for inputs; zero old values */ \ - memcpy(buf_tmp + 192, buf_tmp + 96, PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_ADDR_BYTES); \ - memcpy(buf_tmp + 128, buf_tmp + 64, PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_ADDR_BYTES); \ - memcpy(buf_tmp + 64, buf_tmp + 32, PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_ADDR_BYTES); \ - /* skip memcpy(buf_tmp, buf_tmp, PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_ADDR_BYTES); already in place */ \ - \ - /* skip memset(buf_tmp, 0, PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_ADDR_BYTES); remained untouched */ \ - memset(buf_tmp + 32, 0, PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_ADDR_BYTES); \ - /* skip memset(buf_tmp + 64, 0, PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_ADDR_BYTES); contains addr1 */ \ - memset(buf_tmp + 96, 0, PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_ADDR_BYTES); \ - \ - for (i = 0; i < PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N; i++) { \ - buf_tmp[PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_ADDR_BYTES + i] = in0[i] ^ outbuf[i]; \ - buf_tmp[PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_ADDR_BYTES + i + 64] = in1[i] ^ outbuf[i + 32]; \ - buf_tmp[PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_ADDR_BYTES + i + 128] = in2[i] ^ outbuf[i + 64]; \ - buf_tmp[PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_ADDR_BYTES + i + 192] = in3[i] ^ outbuf[i + 96]; \ - } \ - \ - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_haraka512x4(outbuf, buf_tmp, state); \ - \ - memcpy(out0, outbuf, PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N); \ - memcpy(out1, outbuf + 32, PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N); \ - memcpy(out2, outbuf + 64, PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N); \ - memcpy(out3, outbuf + 96, PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N); \ - } else { \ - /* All other tweakable hashes*/ \ - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_addr_to_bytes(buf0, addrx4 + 0 * 8); \ - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_addr_to_bytes(buf1, addrx4 + 1 * 8); \ - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_addr_to_bytes(buf2, addrx4 + 2 * 8); \ - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_addr_to_bytes(buf3, addrx4 + 3 * 8); \ - \ - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_haraka_Sx4(bitmask0, bitmask1, bitmask2, bitmask3, (inblocks)*PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N, buf0, buf1, \ - buf2, buf3, PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_ADDR_BYTES, state); \ - \ - for (i = 0; i < (inblocks)*PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N; i++) { \ - buf0[PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_ADDR_BYTES + i] = in0[i] ^ bitmask0[i]; \ - buf1[PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_ADDR_BYTES + i] = in1[i] ^ bitmask1[i]; \ - buf2[PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_ADDR_BYTES + i] = in2[i] ^ bitmask2[i]; \ - buf3[PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_ADDR_BYTES + i] = in3[i] ^ bitmask3[i]; \ - } \ - \ - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_haraka_Sx4(out0, out1, out2, out3, PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N, buf0, buf1, buf2, buf3, \ - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_ADDR_BYTES + (inblocks)*PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N, state); \ - } \ - } +#define thashx4 SPX_NAMESPACE(thashx4) +void thashx4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addrx4[4 * 8]) { + PQCLEAN_VLA(unsigned char, buf0, SPX_ADDR_BYTES + inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, buf1, SPX_ADDR_BYTES + inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, buf2, SPX_ADDR_BYTES + inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, buf3, SPX_ADDR_BYTES + inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, bitmask0, inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, bitmask1, inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, bitmask2, inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, bitmask3, inblocks * SPX_N); + unsigned char outbuf[32 * 4]; + unsigned char buf_tmp[64 * 4]; + unsigned int i; + + if (inblocks == 1) { + memset(buf_tmp, 0, 64 * 4); + + // Generate masks first in buffer + memcpy(buf_tmp, addrx4 + 0 * 8, 32); + memcpy(buf_tmp + 32, addrx4 + 1 * 8, 32); + memcpy(buf_tmp + 64, addrx4 + 2 * 8, 32); + memcpy(buf_tmp + 96, addrx4 + 3 * 8, 32); + + haraka256x4(outbuf, buf_tmp, ctx); + + /* move addresses to make room for inputs; zero old values */ + memcpy(buf_tmp + 192, buf_tmp + 96, SPX_ADDR_BYTES); + memcpy(buf_tmp + 128, buf_tmp + 64, SPX_ADDR_BYTES); + memcpy(buf_tmp + 64, buf_tmp + 32, SPX_ADDR_BYTES); + /* skip memcpy(buf_tmp, buf_tmp, SPX_ADDR_BYTES); already in place */ -thashx4_variant(1, 1) -thashx4_variant(2, 2) -thashx4_variant(WOTS_LEN, PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_WOTS_LEN) -thashx4_variant(FORS_TREES, PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_FORS_TREES) + /* skip memset(buf_tmp, 0, SPX_ADDR_BYTES); remained untouched */ + memset(buf_tmp + 32, 0, SPX_ADDR_BYTES); + /* skip memset(buf_tmp + 64, 0, SPX_ADDR_BYTES); contains addr1 */ + memset(buf_tmp + 96, 0, SPX_ADDR_BYTES); + + for (i = 0; i < SPX_N; i++) { + buf_tmp[SPX_ADDR_BYTES + i] = in0[i] ^ outbuf[i]; + buf_tmp[SPX_ADDR_BYTES + i + 64] = in1[i] ^ outbuf[i + 32]; + buf_tmp[SPX_ADDR_BYTES + i + 128] = in2[i] ^ outbuf[i + 64]; + buf_tmp[SPX_ADDR_BYTES + i + 192] = in3[i] ^ outbuf[i + 96]; + } + + haraka512x4(outbuf, buf_tmp, ctx); + + memcpy(out0, outbuf, SPX_N); + memcpy(out1, outbuf + 32, SPX_N); + memcpy(out2, outbuf + 64, SPX_N); + memcpy(out3, outbuf + 96, SPX_N); + } else { + /* All other tweakable hashes*/ + memcpy(buf0, addrx4 + 0 * 8, 32); + memcpy(buf1, addrx4 + 1 * 8, 32); + memcpy(buf2, addrx4 + 2 * 8, 32); + memcpy(buf3, addrx4 + 3 * 8, 32); + + haraka_Sx4(bitmask0, bitmask1, bitmask2, bitmask3, inblocks * SPX_N, + buf0, buf1, buf2, buf3, SPX_ADDR_BYTES, ctx); + + for (i = 0; i < inblocks * SPX_N; i++) { + buf0[SPX_ADDR_BYTES + i] = in0[i] ^ bitmask0[i]; + buf1[SPX_ADDR_BYTES + i] = in1[i] ^ bitmask1[i]; + buf2[SPX_ADDR_BYTES + i] = in2[i] ^ bitmask2[i]; + buf3[SPX_ADDR_BYTES + i] = in3[i] ^ bitmask3[i]; + } + + haraka_Sx4(out0, out1, out2, out3, SPX_N, + buf0, buf1, buf2, buf3, SPX_ADDR_BYTES + inblocks * SPX_N, + ctx); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/thashx4.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/thashx4.h index 3d9c3465d1..64798a3727 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/thashx4.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/thashx4.h @@ -1,25 +1,20 @@ -#ifndef PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_THASHX4_H -#define PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_THASHX4_H +#ifndef SPX_THASHX4_H +#define SPX_THASHX4_H #include -#include "hash_state.h" +#include "context.h" +#include "params.h" -#define thashx4_header(inblocks) \ - void PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_thashx4_##inblocks(unsigned char *out0, \ - unsigned char *out1, \ - unsigned char *out2, \ - unsigned char *out3, \ - const unsigned char *in0, \ - const unsigned char *in1, \ - const unsigned char *in2, \ - const unsigned char *in3, \ - const unsigned char *pub_seed, uint32_t addrx4[4*8], \ - const hash_state *state_seeded) - -thashx4_header(1); -thashx4_header(2); -thashx4_header(WOTS_LEN); -thashx4_header(FORS_TREES); +#define thashx4 SPX_NAMESPACE(thashx4) +void thashx4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addrx4[4 * 8]); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/utils.c b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/utils.c index 3749635629..177b541fb9 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/utils.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/utils.c @@ -1,34 +1,41 @@ -#include #include +#include "utils.h" + #include "address.h" #include "hash.h" -#include "hash_state.h" #include "params.h" #include "thash.h" -#include "utils.h" /** * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. */ -void PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in) { +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in) { + int i; /* Iterate over out in decreasing order, for big-endianness. */ - for (size_t i = outlen; i > 0; i--) { - out[i - 1] = in & 0xff; + for (i = (signed int)outlen - 1; i >= 0; i--) { + out[i] = in & 0xff; in = in >> 8; } } +void u32_to_bytes(unsigned char *out, uint32_t in) { + out[0] = (unsigned char)(in >> 24); + out[1] = (unsigned char)(in >> 16); + out[2] = (unsigned char)(in >> 8); + out[3] = (unsigned char)in; +} + /** * Converts the inlen bytes in 'in' from big-endian byte order to an integer. */ -unsigned long long PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_bytes_to_ull( - const unsigned char *in, size_t inlen) { +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { unsigned long long retval = 0; + unsigned int i; - for (size_t i = 0; i < inlen; i++) { + for (i = 0; i < inlen; i++) { retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); } return retval; @@ -38,94 +45,80 @@ unsigned long long PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_bytes_to_ull( * Computes a root node given a leaf and an auth path. * Expects address to be complete other than the tree_height and tree_index. */ -void PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]) { uint32_t i; - unsigned char buffer[2 * PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N]; + unsigned char buffer[2 * SPX_N]; /* If leaf_idx is odd (last bit = 1), current path element is a right child and auth_path has to go left. Otherwise it is the other way around. */ if (leaf_idx & 1) { - memcpy(buffer + PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N, leaf, PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N); + memcpy(buffer + SPX_N, leaf, SPX_N); + memcpy(buffer, auth_path, SPX_N); } else { - memcpy(buffer, leaf, PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N); - memcpy(buffer + PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N, auth_path, PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N); + memcpy(buffer, leaf, SPX_N); + memcpy(buffer + SPX_N, auth_path, SPX_N); } - auth_path += PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N; + auth_path += SPX_N; for (i = 0; i < tree_height - 1; i++) { leaf_idx >>= 1; idx_offset >>= 1; /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_set_tree_height(addr, i + 1); - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_set_tree_index( - addr, leaf_idx + idx_offset); + set_tree_height(addr, i + 1); + set_tree_index(addr, leaf_idx + idx_offset); /* Pick the right or left neighbor, depending on parity of the node. */ if (leaf_idx & 1) { - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_thash_2( - buffer + PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N); + thash(buffer + SPX_N, buffer, 2, ctx, addr); + memcpy(buffer, auth_path, SPX_N); } else { - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_thash_2( - buffer, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer + PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N, auth_path, PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N); + thash(buffer, buffer, 2, ctx, addr); + memcpy(buffer + SPX_N, auth_path, SPX_N); } - auth_path += PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N; + auth_path += SPX_N; } /* The last iteration is exceptional; we do not copy an auth_path node. */ leaf_idx >>= 1; idx_offset >>= 1; - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_set_tree_height(addr, tree_height); - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_set_tree_index( - addr, leaf_idx + idx_offset); - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_thash_2( - root, buffer, pub_seed, addr, hash_state_seeded); + set_tree_height(addr, tree_height); + set_tree_index(addr, leaf_idx + idx_offset); + thash(root, buffer, 2, ctx, addr); } /** * For a given leaf index, computes the authentication path and the resulting * root node using Merkle's TreeHash algorithm. * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_ADDR_TYPE_FORSTREE). + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). * Applies the offset idx_offset to indices before building addresses, so that * it is possible to continue counting indices across trees. */ -static void PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_treehash( - unsigned char *root, unsigned char *auth_path, - unsigned char *stack, unsigned int *heights, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - +void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx * /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]) { + PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); + PQCLEAN_VLA(unsigned int, heights, tree_height + 1); unsigned int offset = 0; uint32_t idx; uint32_t tree_idx; for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { /* Add the next leaf node to the stack. */ - gen_leaf(stack + offset * PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N, - sk_seed, pub_seed, idx + idx_offset, tree_addr, - hash_state_seeded); + gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); offset++; heights[offset - 1] = 0; /* If this is a node we need for the auth path.. */ if ((leaf_idx ^ 0x1) == idx) { - memcpy(auth_path, stack + (offset - 1)*PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N, PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N); + memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); } /* While the top-most nodes are of equal height.. */ @@ -134,66 +127,22 @@ static void PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_treehash( tree_idx = (idx >> (heights[offset - 1] + 1)); /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_set_tree_height( - tree_addr, heights[offset - 1] + 1); - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_set_tree_index( - tree_addr, tree_idx + (idx_offset >> (heights[offset - 1] + 1))); + set_tree_height(tree_addr, heights[offset - 1] + 1); + set_tree_index(tree_addr, + tree_idx + (idx_offset >> (heights[offset - 1] + 1))); /* Hash the top-most nodes from the stack together. */ - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_thash_2( - stack + (offset - 2)*PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N, stack + (offset - 2)*PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N, - pub_seed, tree_addr, hash_state_seeded); + thash(stack + (offset - 2)*SPX_N, + stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); offset--; /* Note that the top-most node is now one layer higher. */ heights[offset - 1]++; /* If this is a node we need for the auth path.. */ if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_path + heights[offset - 1]*PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N, - stack + (offset - 1)*PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N, PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N); + memcpy(auth_path + heights[offset - 1]*SPX_N, + stack + (offset - 1)*SPX_N, SPX_N); } } } - memcpy(root, stack, PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N); -} - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_FORS_HEIGHT + 1)*PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N]; - unsigned int heights[PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_FORS_HEIGHT + 1]; - - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_FORS_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_TREE_HEIGHT + 1)*PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N]; - unsigned int heights[PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_TREE_HEIGHT + 1]; - - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_TREE_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); + memcpy(root, stack, SPX_N); } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/utils.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/utils.h index a3ecbf508e..64f5d5a53a 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/utils.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/utils.h @@ -1,64 +1,58 @@ -#ifndef PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_UTILS_H -#define PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_UTILS_H +#ifndef SPX_UTILS_H +#define SPX_UTILS_H -#include "hash_state.h" -#include "params.h" -#include #include +#include "compat.h" +#include "context.h" +#include "params.h" + + +/* To support MSVC use alloca() instead of VLAs. See #20. */ + + /** * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. */ -void PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in); +#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in); +#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) +void u32_to_bytes(unsigned char *out, uint32_t in); /** * Converts the inlen bytes in 'in' from big-endian byte order to an integer. */ -unsigned long long PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_bytes_to_ull( - const unsigned char *in, size_t inlen); +#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); /** * Computes a root node given a leaf and an auth path. * Expects address to be complete other than the tree_height and tree_index. */ -void PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); +#define compute_root SPX_NAMESPACE(compute_root) +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]); /** * For a given leaf index, computes the authentication path and the resulting * root node using Merkle's TreeHash algorithm. * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_ADDR_TYPE_FORSTREE). + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). * Applies the offset idx_offset to indices before building addresses, so that * it is possible to continue counting indices across trees. */ -void PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); +#define treehash SPX_NAMESPACE(treehash) +void treehash(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx *ctx /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]); -void PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/utilsx4.c b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/utilsx4.c index e79ed408b8..1638677194 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/utilsx4.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/utilsx4.c @@ -1,98 +1,138 @@ +#include + +#include "utilsx4.h" + #include "address.h" #include "params.h" #include "thashx4.h" #include "utils.h" -#include "utilsx4.h" -#include - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. +/* + * Generate the entire Merkle tree, computing the authentication path for leaf_idx, + * and the resulting root node using Merkle's TreeHash algorithm. * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_ADDR_TYPE_FORSTREE). + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) + * + * This expects tree_addrx4 to be initialized to 4 parallel addr structures for + * the Merkle tree nodes + * * Applies the offset idx_offset to indices before building addresses, so that * it is possible to continue counting indices across trees. + * + * This works by using the standard Merkle tree building algorithm, except + * that each 'node' tracked is actually 4 consecutive nodes in the real tree. + * When we combine two logical nodes ABCD and WXYZ, we perform the H + * operation on adjacent real nodes, forming the parent logical node + * (AB)(CD)(WX)(YZ) + * + * When we get to the top two levels of the real tree (where there is only + * one logical node), we continue this operation two more times; the right + * most real node will by the actual root (and the other 3 nodes will be + * garbage). We follow the same thashx4 logic so that the 'extract + * authentication path components' part of the loop is still executed (and + * to simplify the code somewhat) + * + * This currently assumes tree_height >= 2; I suspect that doing an adjusting + * idx, addr_idx on the gen_leafx4 call if tree_height < 2 would fix it; since + * we don't actually use such short trees, I haven't bothered */ -#define treehashx4_variant(name, tree_height) \ - void PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_treehashx4_##name( \ - unsigned char *rootx4, unsigned char *auth_pathx4, const unsigned char *sk_seed, \ - const unsigned char *pub_seed, const uint32_t leaf_idx[4], uint32_t idx_offset[4], \ - void (*gen_leafx4)(unsigned char * /* leaf0 */, unsigned char * /* leaf1 */, \ - unsigned char * /* leaf2 */, unsigned char * /* leaf3 */, \ - const unsigned char * /* sk_seed */, \ - const unsigned char * /* pub_seed */, uint32_t /* addr_idx0 */, \ - uint32_t /* addr_idx1 */, uint32_t /* addr_idx2 */, \ - uint32_t /* addr_idx3 */, const uint32_t[8] /* tree_addr */, \ - const hash_state * /* state_seeded */), \ - uint32_t tree_addrx4[4 * 8], const hash_state *state_seeded) { \ - unsigned char stackx4[4 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N]; \ - unsigned int heights[(tree_height) + 1]; \ - unsigned int offset = 0; \ - uint32_t idx; \ - uint32_t tree_idx; \ - unsigned int j; \ - \ - for (idx = 0; idx < (uint32_t)(1 << (tree_height)); idx++) { \ - /* Add the next leaf node to the stack. */ \ - gen_leafx4(stackx4 + 0 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N + offset * PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N, \ - stackx4 + 1 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N + offset * PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N, \ - stackx4 + 2 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N + offset * PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N, \ - stackx4 + 3 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N + offset * PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N, sk_seed, \ - pub_seed, idx + idx_offset[0], idx + idx_offset[1], idx + idx_offset[2], \ - idx + idx_offset[3], tree_addrx4, state_seeded); \ - offset++; \ - heights[offset - 1] = 0; \ - \ - /* If this is a node we need for the auth path.. */ \ - for (j = 0; j < 4; j++) { \ - if ((leaf_idx[j] ^ 0x1) == idx) { \ - memcpy(auth_pathx4 + j * (tree_height)*PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N, \ - stackx4 + j * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N + (offset - 1) * PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N, \ - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N); \ - } \ - } \ - \ - /* While the top-most nodes are of equal height.. */ \ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { \ - /* Compute index of the new node, in the next layer. */ \ - tree_idx = (idx >> (heights[offset - 1] + 1)); \ - \ - /* Set the address of the node we're creating. */ \ - for (j = 0; j < 4; j++) { \ - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_set_tree_height(tree_addrx4 + j * 8, heights[offset - 1] + 1); \ - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_set_tree_index(tree_addrx4 + j * 8, \ - tree_idx + (idx_offset[j] >> (heights[offset - 1] + 1))); \ - } \ - /* Hash the top-most nodes from the stack together. */ \ - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_thashx4_2(stackx4 + 0 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N + (offset - 2) * PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N, \ - stackx4 + 1 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N + (offset - 2) * PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N, \ - stackx4 + 2 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N + (offset - 2) * PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N, \ - stackx4 + 3 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N + (offset - 2) * PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N, \ - stackx4 + 0 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N + (offset - 2) * PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N, \ - stackx4 + 1 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N + (offset - 2) * PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N, \ - stackx4 + 2 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N + (offset - 2) * PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N, \ - stackx4 + 3 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N + (offset - 2) * PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N, \ - pub_seed, tree_addrx4, state_seeded); \ - offset--; \ - /* Note that the top-most node is now one layer higher. */ \ - heights[offset - 1]++; \ - \ - /* If this is a node we need for the auth path.. */ \ - for (j = 0; j < 4; j++) { \ - if (((leaf_idx[j] >> heights[offset - 1]) ^ 0x1) == tree_idx) { \ - memcpy(auth_pathx4 + j * (tree_height)*PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N + \ - heights[offset - 1] * PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N, \ - stackx4 + j * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N + (offset - 1) * PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N, \ - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N); \ - } \ - } \ - } \ - } \ - \ - for (j = 0; j < 4; j++) { \ - memcpy(rootx4 + j * PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N, stackx4 + j * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N, PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N); \ - } \ - } +void treehashx4(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, + uint32_t tree_height, + void (*gen_leafx4)( + unsigned char * /* Where to write the leaves */, + const spx_ctx *, + uint32_t idx, void *info), + uint32_t tree_addrx4[4 * 8], + void *info) { + /* This is where we keep the intermediate nodes */ + PQCLEAN_VLA(unsigned char, stackx4, tree_height * 4 * SPX_N); + uint32_t left_adj = 0, prev_left_adj = 0; /* When we're doing the top 3 */ + /* levels, the left-most part of the tree isn't at the beginning */ + /* of current[]. These give the offset of the actual start */ + + uint32_t idx; + uint32_t max_idx = (1U << (tree_height - 2)) - 1; + for (idx = 0;; idx++) { + unsigned char current[4 * SPX_N]; /* Current logical node */ + gen_leafx4( current, ctx, 4 * idx + idx_offset, + info ); -treehashx4_variant(FORS_HEIGHT, PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_FORS_HEIGHT) + /* Now combine the freshly generated right node with previously */ + /* generated left ones */ + uint32_t internal_idx_offset = idx_offset; + uint32_t internal_idx = idx; + uint32_t internal_leaf = leaf_idx; + uint32_t h; /* The height we are in the Merkle tree */ + for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { + + /* Special processing if we're at the top of the tree */ + if (h >= tree_height - 2) { + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[3 * SPX_N], SPX_N ); + return; + } + /* The tree indexing logic is a bit off in this case */ + /* Adjust it so that the left-most node of the part of */ + /* the tree that we're processing has index 0 */ + prev_left_adj = left_adj; + left_adj = 4U - (1 << (tree_height - h - 1)); + } + + /* Check if we hit the top of the tree */ + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[3 * SPX_N], SPX_N ); + return; + } + + /* + * Check if one of the nodes we have is a part of the + * authentication path; if it is, write it out + */ + if ((((internal_idx << 2) ^ internal_leaf) & ~0x3U) == 0) { + memcpy( &auth_path[ h * SPX_N ], + ¤t[(((internal_leaf & 3) ^ 1) + prev_left_adj) * SPX_N], + SPX_N ); + } + + /* + * Check if we're at a left child; if so, stop going up the stack + * Exception: if we've reached the end of the tree, keep on going + * (so we combine the last 4 nodes into the one root node in two + * more iterations) + */ + if ((internal_idx & 1) == 0 && idx < max_idx) { + break; + } + + /* Ok, we're at a right node (or doing the top 3 levels) */ + /* Now combine the left and right logical nodes together */ + + /* Set the address of the node we're creating. */ + unsigned int j; + internal_idx_offset >>= 1; + for (j = 0; j < 4; j++) { + set_tree_height(tree_addrx4 + j * 8, h + 1); + set_tree_index(tree_addrx4 + j * 8, + (4 / 2) * (internal_idx & ~1U) + j - left_adj + internal_idx_offset ); + } + unsigned char *left = &stackx4[h * 4 * SPX_N]; + thashx4( ¤t[0 * SPX_N], + ¤t[1 * SPX_N], + ¤t[2 * SPX_N], + ¤t[3 * SPX_N], + &left [0 * SPX_N], + &left [2 * SPX_N], + ¤t[0 * SPX_N], + ¤t[2 * SPX_N], + 2, ctx, tree_addrx4); + } + + /* We've hit a left child; save the current for when we get the */ + /* corresponding right right */ + memcpy( &stackx4[h * 4 * SPX_N], current, 4 * SPX_N); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/utilsx4.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/utilsx4.h index 1901dfe87f..facb874b18 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/utilsx4.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/utilsx4.h @@ -1,38 +1,30 @@ -#ifndef PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_UTILSX4_H -#define PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_UTILSX4_H - -#include "hash_state.h" -#include "params.h" +#ifndef SPX_UTILSX4_H +#define SPX_UTILSX4_H #include +#include "context.h" +#include "params.h" + /** * For a given leaf index, computes the authentication path and the resulting * root node using Merkle's TreeHash algorithm. * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_ADDR_TYPE_FORSTREE). + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). * Applies the offset idx_offset to indices before building addresses, so that * it is possible to continue counting indices across trees. + * + * This implementation uses AVX to compute internal nodes 4 at a time (in + * parallel) */ -void PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_treehashx4_FORS_HEIGHT(unsigned char *rootx4, - unsigned char *auth_pathx4, - const unsigned char *sk_seed, - const unsigned char *pub_seed, - const uint32_t leaf_idx[4], - uint32_t idx_offset[4], - void (*gen_leafx4)(unsigned char * /* leaf0 */, - unsigned char * /* leaf1 */, - unsigned char * /* leaf2 */, - unsigned char * /* leaf3 */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx0 */, - uint32_t /* addr_idx1 */, - uint32_t /* addr_idx2 */, - uint32_t /* addr_idx3 */, - const uint32_t[8] /* tree_addr */, - const hash_state * /* state_seeded */), - uint32_t tree_addrx4[4 * 8], - const hash_state *state_seeded); +#define treehashx4 SPX_NAMESPACE(treehashx4) +void treehashx4(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leafx4)( + unsigned char * /* Where to write the leaves */, + const spx_ctx * /* ctx */, + uint32_t addr_idx, void *info), + uint32_t tree_addrx4[4 * 8], void *info); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/wots.c b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/wots.c index 949585fbf3..4d5041ce05 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/wots.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/wots.c @@ -1,106 +1,104 @@ #include #include +#include "wots.h" + #include "address.h" #include "hash.h" -#include "hash_state.h" #include "hashx4.h" #include "params.h" #include "thash.h" #include "thashx4.h" #include "utils.h" -#include "wots.h" +#include "utilsx4.h" +#include "wotsx4.h" // TODO clarify address expectations, and make them more uniform. // TODO i.e. do we expect types to be set already? // TODO and do we expect modifications or copies? /** - * Computes the starting value for a chain, i.e. the secret key. - * Expects the address to be complete up to the chain address. - */ -static void wots_gen_sk(unsigned char *sk, const unsigned char *sk_seed, - uint32_t wots_addr[8], const hash_state *state_seeded) { - /* Make sure that the hash address is actually zeroed. */ - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_set_hash_addr(wots_addr, 0); - - /* Generate sk element. */ - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_prf_addr(sk, sk_seed, wots_addr, state_seeded); -} - -/** - * 4-way parallel version of wots_gen_sk; expects 4x as much space in sk + * Computes up the chains */ -static void wots_gen_skx4(unsigned char *skx4, const unsigned char *sk_seed, - uint32_t wots_addrx4[4 * 8], const hash_state *state_seeded) { - unsigned int j; - - /* Make sure that the hash address is actually zeroed. */ +static void gen_chains( + unsigned char *out, + const unsigned char *in, + unsigned int start[SPX_WOTS_LEN], + const unsigned int steps[SPX_WOTS_LEN], + const spx_ctx *ctx, + uint32_t addr[8]) { + uint32_t i, j, k, idx, watching; + int done; + unsigned char empty[SPX_N]; + unsigned char *bufs[4]; + uint32_t addrs[8 * 4]; + + int l; + uint16_t counts[SPX_WOTS_W] = { 0 }; + uint16_t idxs[SPX_WOTS_LEN]; + uint16_t total, newTotal; + + /* set addrs = {addr, addr, addr, addr} */ for (j = 0; j < 4; j++) { - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_set_hash_addr(wots_addrx4 + j * 8, 0); + memcpy(addrs + j * 8, addr, sizeof(uint32_t) * 8); } - /* Generate sk element. */ - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_prf_addrx4(skx4 + 0 * PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N, - skx4 + 1 * PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N, - skx4 + 2 * PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N, - skx4 + 3 * PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N, - sk_seed, wots_addrx4, - state_seeded); -} - -/** - * Computes the chaining function. - * out and in have to be n-byte arrays. - * - * Interprets in as start-th value of the chain. - * addr has to contain the address of the chain. - */ -static void gen_chain(unsigned char *out, const unsigned char *in, - unsigned int start, unsigned int steps, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *state_seeded) { - uint32_t i; - /* Initialize out with the value at position 'start'. */ - memcpy(out, in, PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N); + memcpy(out, in, SPX_WOTS_LEN * SPX_N); - /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_WOTS_W; i++) { - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_set_hash_addr(addr, i); - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_thash_1(out, out, pub_seed, addr, state_seeded); + /* Sort the chains in reverse order by steps using counting sort. */ + for (i = 0; i < SPX_WOTS_LEN; i++) { + counts[steps[i]]++; + } + total = 0; + for (l = SPX_WOTS_W - 1; l >= 0; l--) { + newTotal = counts[l] + total; + counts[l] = total; + total = newTotal; + } + for (i = 0; i < SPX_WOTS_LEN; i++) { + idxs[counts[steps[i]]] = (uint16_t)i; + counts[steps[i]]++; } -} -/** - * 4-way parallel version of gen_chain; expects 4x as much space in out, and - * 4x as much space in inx4. Assumes start and step identical across chains. - */ -static void gen_chainx4(unsigned char *outx4, const unsigned char *inx4, - unsigned int start, unsigned int steps, - const unsigned char *pub_seed, uint32_t addrx4[4 * 8], - const hash_state *state_seeded) { - uint32_t i; - unsigned int j; + /* We got our work cut out for us: do it! */ + for (i = 0; i < SPX_WOTS_LEN; i += 4) { + for (j = 0; j < 4 && i + j < SPX_WOTS_LEN; j++) { + idx = idxs[i + j]; + set_chain_addr(addrs + j * 8, idx); + bufs[j] = out + SPX_N * idx; + } - /* Initialize outx4 with the value at position 'start'. */ - memcpy(outx4, inx4, 4 * PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N); + /* As the chains are sorted in reverse order, we know that the first + * chain is the longest and the last one is the shortest. We keep + * an eye on whether the last chain is done and then on the one before, + * et cetera. */ + watching = 3; + done = 0; + while (i + watching >= SPX_WOTS_LEN) { + bufs[watching] = &empty[0]; + watching--; + } - /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_WOTS_W; i++) { - for (j = 0; j < 4; j++) { - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_set_hash_addr(addrx4 + j * 8, i); + for (k = 0;; k++) { + while (k == steps[idxs[i + watching]]) { + bufs[watching] = &empty[0]; + if (watching == 0) { + done = 1; + break; + } + watching--; + } + if (done) { + break; + } + for (j = 0; j < watching + 1; j++) { + set_hash_addr(addrs + j * 8, k + start[idxs[i + j]]); + } + + thashx4(bufs[0], bufs[1], bufs[2], bufs[3], + bufs[0], bufs[1], bufs[2], bufs[3], 1, ctx, addrs); } - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_thashx4_1(outx4 + 0 * PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N, - outx4 + 1 * PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N, - outx4 + 2 * PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N, - outx4 + 3 * PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N, - outx4 + 0 * PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N, - outx4 + 1 * PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N, - outx4 + 2 * PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N, - outx4 + 3 * PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N, - pub_seed, addrx4, - state_seeded); } } @@ -109,7 +107,8 @@ static void gen_chainx4(unsigned char *outx4, const unsigned char *inx4, * Interprets an array of bytes as integers in base w. * This only works when log_w is a divisor of 8. */ -static void base_w(unsigned int *output, const int out_len, const unsigned char *input) { +static void base_w(unsigned int *output, const int out_len, + const unsigned char *input) { int in = 0; int out = 0; unsigned char total = 0; @@ -122,119 +121,149 @@ static void base_w(unsigned int *output, const int out_len, const unsigned char in++; bits += 8; } - bits -= PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_WOTS_LOGW; - output[out] = (unsigned int)(total >> bits) & (PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_WOTS_W - 1); + bits -= SPX_WOTS_LOGW; + output[out] = (total >> bits) & (SPX_WOTS_W - 1); out++; } } /* Computes the WOTS+ checksum over a message (in base_w). */ -static void wots_checksum(unsigned int *csum_base_w, const unsigned int *msg_base_w) { +static void wots_checksum(unsigned int *csum_base_w, + const unsigned int *msg_base_w) { unsigned int csum = 0; - unsigned char csum_bytes[(PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_WOTS_LEN2 * PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_WOTS_LOGW + 7) / 8]; + unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; unsigned int i; /* Compute checksum. */ - for (i = 0; i < PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_WOTS_LEN1; i++) { - csum += PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_WOTS_W - 1 - msg_base_w[i]; + for (i = 0; i < SPX_WOTS_LEN1; i++) { + csum += SPX_WOTS_W - 1 - msg_base_w[i]; } /* Convert checksum to base_w. */ /* Make sure expected empty zero bits are the least significant bits. */ - csum = csum << (8 - ((PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_WOTS_LEN2 * PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_WOTS_LOGW) % 8)); - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); - base_w(csum_base_w, PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_WOTS_LEN2, csum_bytes); + csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); + ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); + base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); } /* Takes a message and derives the matching chain lengths. */ -static void chain_lengths(unsigned int *lengths, const unsigned char *msg) { - base_w(lengths, PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_WOTS_LEN1, msg); - wots_checksum(lengths + PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_WOTS_LEN1, lengths); +void chain_lengths(unsigned int *lengths, const unsigned char *msg) { + base_w(lengths, SPX_WOTS_LEN1, msg); + wots_checksum(lengths + SPX_WOTS_LEN1, lengths); } /** - * WOTS key generation. Takes a 32 byte sk_seed, expands it to WOTS private key - * elements and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. * * Writes the computed public key to 'pk'. */ -void PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_wots_gen_pk(unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *state_seeded) { +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]) { + unsigned int steps[SPX_WOTS_LEN]; + unsigned int start[SPX_WOTS_LEN]; uint32_t i; - unsigned int j; - uint32_t addrx4[4 * 8]; - unsigned char pkbuf[4 * PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N]; + chain_lengths(start, msg); - for (j = 0; j < 4; j++) { - memcpy(addrx4 + j * 8, addr, sizeof(uint32_t) * 8); - } - - /* The last iteration typically does not have complete set of 4 chains, - but because we use pkbuf, this is not an issue -- we still do as many - in parallel as possible. */ - for (i = 0; i < ((PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_WOTS_LEN + 3) & ~0x3); i += 4) { - for (j = 0; j < 4; j++) { - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_set_chain_addr(addrx4 + j * 8, i + j); - } - wots_gen_skx4(pkbuf, sk_seed, addrx4, state_seeded); - gen_chainx4(pkbuf, pkbuf, 0, PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_WOTS_W - 1, pub_seed, addrx4, state_seeded); - for (j = 0; j < 4; j++) { - if (i + j < PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_WOTS_LEN) { - memcpy(pk + (i + j)*PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N, pkbuf + j * PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N, PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N); - } - } + for (i = 0; i < SPX_WOTS_LEN; i++) { + steps[i] = SPX_WOTS_W - 1 - start[i]; } - // Get rid of unused argument variable. - (void)state_seeded; + gen_chains(pk, sig, start, steps, ctx, addr); } -/** - * Takes a n-byte message and the 32-byte sk_see to compute a signature 'sig'. +/* + * This generates 4 sequential WOTS public keys + * It also generates the WOTS signature if leaf_info indicates + * that we're signing with one of these WOTS keys */ -void PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_wots_sign(unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); +void wots_gen_leafx4(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info) { + struct leaf_info_x4 *info = v_info; + uint32_t *leaf_addr = info->leaf_addr; + uint32_t *pk_addr = info->pk_addr; + unsigned int i, j, k; + unsigned char pk_buffer[ 4 * SPX_WOTS_BYTES ]; + unsigned wots_offset = SPX_WOTS_BYTES; + unsigned char *buffer; + uint32_t wots_k_mask; + unsigned wots_sign_index; + + if (((leaf_idx ^ info->wots_sign_leaf) & ~3U) == 0) { + /* We're traversing the leaf that's signing; generate the WOTS */ + /* signature */ + wots_k_mask = 0; + wots_sign_index = info->wots_sign_leaf & 3; /* Which of of the 4 */ + /* 4 slots do the signatures come from */ + } else { + /* Nope, we're just generating pk's; turn off the signature logic */ + wots_k_mask = (uint32_t)~0; + wots_sign_index = 0; + } - for (i = 0; i < PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_WOTS_LEN; i++) { - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_set_chain_addr(addr, i); - wots_gen_sk(sig + i * PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N, sk_seed, addr, state_seeded); - gen_chain(sig + i * PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N, sig + i * PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N, 0, lengths[i], pub_seed, addr, state_seeded); + for (j = 0; j < 4; j++) { + set_keypair_addr( leaf_addr + j * 8, leaf_idx + j ); + set_keypair_addr( pk_addr + j * 8, leaf_idx + j ); } - // avoid unused argument - (void)state_seeded; -} + for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { + uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k to */ + /* the step if we're generating a signature, ~0 if we're not */ -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_WOTS_LEN]; - uint32_t i; + /* Start with the secret seed */ + for (j = 0; j < 4; j++) { + set_chain_addr(leaf_addr + j * 8, i); + set_hash_addr(leaf_addr + j * 8, 0); + set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTSPRF); + } + prf_addrx4(buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + buffer + 2 * wots_offset, + buffer + 3 * wots_offset, + ctx, leaf_addr); - chain_lengths(lengths, msg); + for (j = 0; j < 4; j++) { + set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTS); + } + + /* Iterate down the WOTS chain */ + for (k = 0;; k++) { + /* Check if one of the values we have needs to be saved as a */ + /* part of the WOTS signature */ + if (k == wots_k) { + memcpy( info->wots_sig + i * SPX_N, + buffer + wots_sign_index * wots_offset, SPX_N ); + } - for (i = 0; i < PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_WOTS_LEN; i++) { - PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_set_chain_addr(addr, i); - gen_chain(pk + i * PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N, sig + i * PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_N, - lengths[i], PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_WOTS_W - 1 - lengths[i], pub_seed, addr, - state_seeded); + /* Check if we hit the top of the chain */ + if (k == SPX_WOTS_W - 1) { + break; + } + + /* Iterate one step on all 4 chains */ + for (j = 0; j < 4; j++) { + set_hash_addr(leaf_addr + j * 8, k); + } + thashx4(buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + buffer + 2 * wots_offset, + buffer + 3 * wots_offset, + buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + buffer + 2 * wots_offset, + buffer + 3 * wots_offset, 1, ctx, leaf_addr); + } } - // avoid unused argument - (void)state_seeded; + /* Do the final thash to generate the public keys */ + thashx4(dest + 0 * SPX_N, + dest + 1 * SPX_N, + dest + 2 * SPX_N, + dest + 3 * SPX_N, + pk_buffer + 0 * wots_offset, + pk_buffer + 1 * wots_offset, + pk_buffer + 2 * wots_offset, + pk_buffer + 3 * wots_offset, SPX_WOTS_LEN, ctx, pk_addr); } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/wots.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/wots.h index e655453cf6..4e7692eeef 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/wots.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/wots.h @@ -1,41 +1,25 @@ -#ifndef PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_WOTS_H -#define PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_WOTS_H +#ifndef SPX_WOTS_H +#define SPX_WOTS_H -#include "hash_state.h" -#include "params.h" #include -/** - * WOTS key generation. Takes a 32 byte seed for the private key, expands it to - * a full WOTS private key and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_wots_gen_pk( - unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -/** - * Takes a n-byte message and the 32-byte seed for the private key to compute a - * signature that is placed at 'sig'. - */ -void PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_wots_sign( - unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *hash_state_seeded); +#include "context.h" +#include "params.h" /** * Takes a WOTS signature and an n-byte message, computes a WOTS public key. * * Writes the computed public key to 'pk'. */ -void PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_wots_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); +#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]); + +/* + * Compute the chain lengths needed for a given message hash + */ +#define chain_lengths SPX_NAMESPACE(chain_lengths) +void chain_lengths(unsigned int *lengths, const unsigned char *msg); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/wotsx4.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/wotsx4.h new file mode 100644 index 0000000000..cd634f1743 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/wotsx4.h @@ -0,0 +1,41 @@ +#ifndef WOTSX4_H_ +#define WOTSX4_H_ + +#include + +#include "params.h" + +/* + * This is here to provide an interface to the internal wots_gen_leafx4 + * routine. While this routine is not referenced in the package outside of + * wots.c, it is called from the stand-alone benchmark code to characterize + * the performance + */ +struct leaf_info_x4 { + unsigned char *wots_sig; + uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ + uint32_t *wots_steps; + uint32_t leaf_addr[4 * 8]; + uint32_t pk_addr[4 * 8]; +}; + +/* Macro to set the leaf_info to something 'benign', that is, it would */ +/* run with the same time as it does during the real signing process */ +/* Used only by the benchmark code */ +#define INITIALIZE_LEAF_INFO_X4(info, addr, step_buffer) { \ + (info).wots_sig = 0; \ + (info).wots_sign_leaf = ~0; \ + (info).wots_steps = step_buffer; \ + int i; \ + for (i=0; i<4; i++) { \ + memcpy( &(info).leaf_addr[8*i], addr, 32 ); \ + memcpy( &(info).pk_addr[8*i], addr, 32 ); \ + } \ + } + +#define wots_gen_leafx4 SPX_NAMESPACE(wots_gen_leafx4) +void wots_gen_leafx4(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info); + +#endif /* WOTSX4_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/address.c b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/address.c index fdb232ef1c..b956e9cb29 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/address.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/address.c @@ -1,78 +1,91 @@ #include +#include #include "address.h" #include "params.h" #include "utils.h" -void PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]) { - int i; - - for (i = 0; i < 8; i++) { - PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_ull_to_bytes( - bytes + i * 4, 4, addr[i]); - } -} - -void PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_set_layer_addr( - uint32_t addr[8], uint32_t layer) { - addr[0] = layer; +/* + * Specify which level of Merkle tree (the "layer") we're working on + */ +void set_layer_addr(uint32_t addr[8], uint32_t layer) { + ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; } -void PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_set_tree_addr( - uint32_t addr[8], uint64_t tree) { - addr[1] = 0; - addr[2] = (uint32_t) (tree >> 32); - addr[3] = (uint32_t) tree; +/* + * Specify which Merkle tree within the level (the "tree address") we're working on + */ +void set_tree_addr(uint32_t addr[8], uint64_t tree) { + ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); } -void PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_set_type( - uint32_t addr[8], uint32_t type) { - addr[4] = type; +/* + * Specify the reason we'll use this address structure for, that is, what + * hash will we compute with it. This is used so that unrelated types of + * hashes don't accidentally get the same address structure. The type will be + * one of the SPX_ADDR_TYPE constants + */ +void set_type(uint32_t addr[8], uint32_t type) { + ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; } -void PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; +/* + * Copy the layer and tree fields of the address structure. This is used + * when we're doing multiple types of hashes within the same Merkle tree + */ +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); } /* These functions are used for OTS addresses. */ -void PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_set_keypair_addr( - uint32_t addr[8], uint32_t keypair) { - addr[5] = keypair; +/* + * Specify which Merkle leaf we're working on; that is, which OTS keypair + * we're talking about. + */ +void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { + ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; } -void PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; - out[5] = in[5]; +/* + * Copy the layer, tree and keypair fields of the address structure. This is + * used when we're doing multiple things within the same OTS keypair + */ +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); + ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; } -void PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_set_chain_addr( - uint32_t addr[8], uint32_t chain) { - addr[6] = chain; +/* + * Specify which Merkle chain within the OTS we're working with + * (the chain address) + */ +void set_chain_addr(uint32_t addr[8], uint32_t chain) { + ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; } -void PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_set_hash_addr( - uint32_t addr[8], uint32_t hash) { - addr[7] = hash; +/* + * Specify where in the Merkle chain we are +* (the hash address) + */ +void set_hash_addr(uint32_t addr[8], uint32_t hash) { + ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; } /* These functions are used for all hash tree addresses (including FORS). */ -void PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_set_tree_height( - uint32_t addr[8], uint32_t tree_height) { - addr[6] = tree_height; +/* + * Specify the height of the node in the Merkle/FORS tree we are in + * (the tree height) + */ +void set_tree_height(uint32_t addr[8], uint32_t tree_height) { + ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; } -void PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_set_tree_index( - uint32_t addr[8], uint32_t tree_index) { - addr[7] = tree_index; +/* + * Specify the distance from the left edge of the node in the Merkle/FORS tree + * (the tree index) + */ +void set_tree_index(uint32_t addr[8], uint32_t tree_index) { + u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/address.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/address.h index 0d5ac60584..24a84eb40c 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/address.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/address.h @@ -1,50 +1,52 @@ -#ifndef PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_ADDRESS_H -#define PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_ADDRESS_H +#ifndef SPX_ADDRESS_H +#define SPX_ADDRESS_H #include -#define PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_ADDR_TYPE_WOTS 0 -#define PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_ADDR_TYPE_WOTSPK 1 -#define PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_ADDR_TYPE_HASHTREE 2 -#define PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_ADDR_TYPE_FORSTREE 3 -#define PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_ADDR_TYPE_FORSPK 4 +#include "params.h" -void PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]); +/* The hash types that are passed to set_type */ +#define SPX_ADDR_TYPE_WOTS 0 +#define SPX_ADDR_TYPE_WOTSPK 1 +#define SPX_ADDR_TYPE_HASHTREE 2 +#define SPX_ADDR_TYPE_FORSTREE 3 +#define SPX_ADDR_TYPE_FORSPK 4 +#define SPX_ADDR_TYPE_WOTSPRF 5 +#define SPX_ADDR_TYPE_FORSPRF 6 -void PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_set_layer_addr( - uint32_t addr[8], uint32_t layer); +#define set_layer_addr SPX_NAMESPACE(set_layer_addr) +void set_layer_addr(uint32_t addr[8], uint32_t layer); -void PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_set_tree_addr( - uint32_t addr[8], uint64_t tree); +#define set_tree_addr SPX_NAMESPACE(set_tree_addr) +void set_tree_addr(uint32_t addr[8], uint64_t tree); -void PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_set_type( - uint32_t addr[8], uint32_t type); +#define set_type SPX_NAMESPACE(set_type) +void set_type(uint32_t addr[8], uint32_t type); /* Copies the layer and tree part of one address into the other */ -void PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]); +#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); /* These functions are used for WOTS and FORS addresses. */ -void PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_set_keypair_addr( - uint32_t addr[8], uint32_t keypair); +#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) +void set_keypair_addr(uint32_t addr[8], uint32_t keypair); -void PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_set_chain_addr( - uint32_t addr[8], uint32_t chain); +#define set_chain_addr SPX_NAMESPACE(set_chain_addr) +void set_chain_addr(uint32_t addr[8], uint32_t chain); -void PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_set_hash_addr( - uint32_t addr[8], uint32_t hash); +#define set_hash_addr SPX_NAMESPACE(set_hash_addr) +void set_hash_addr(uint32_t addr[8], uint32_t hash); -void PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]); +#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); /* These functions are used for all hash tree addresses (including FORS). */ -void PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_set_tree_height( - uint32_t addr[8], uint32_t tree_height); +#define set_tree_height SPX_NAMESPACE(set_tree_height) +void set_tree_height(uint32_t addr[8], uint32_t tree_height); -void PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_set_tree_index( - uint32_t addr[8], uint32_t tree_index); +#define set_tree_index SPX_NAMESPACE(set_tree_index) +void set_tree_index(uint32_t addr[8], uint32_t tree_index); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/api.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/api.h index 783c93872d..b9d6d35c70 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/api.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/api.h @@ -4,15 +4,13 @@ #include #include - - -#define PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_CRYPTO_ALGNAME "SPHINCS+" +#define PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_CRYPTO_ALGNAME "SPHINCS+-haraka-256s-robust" #define PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_CRYPTO_SECRETKEYBYTES 128 #define PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_CRYPTO_PUBLICKEYBYTES 64 -#define PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_CRYPTO_BYTES 29792 -#define PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_CRYPTO_SEEDBYTES 96 +#define PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_CRYPTO_BYTES 29792 +#define PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_CRYPTO_SEEDBYTES 96 /* * Returns the length of a secret key, in bytes @@ -39,43 +37,41 @@ size_t PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_crypto_sign_seedbytes(void); * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] * Format pk: [root || PUB_SEED] */ -int PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed); +int PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); /* * Generates a SPHINCS+ key pair. * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] * Format pk: [root || PUB_SEED] */ -int PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk); +int PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); /** * Returns an array containing a detached signature. */ -int PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk); +int PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); /** * Verifies a detached signature and message under a given public key. */ -int PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk); +int PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, + const uint8_t *pk); /** * Returns an array containing the signature followed by the message. */ -int PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk); +int PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); /** * Verifies a given signature-message pair under a given public key. */ -int PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk); - +int PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/context.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/context.h new file mode 100644 index 0000000000..600dfb73c7 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/context.h @@ -0,0 +1,24 @@ +#ifndef SPX_CONTEXT_H +#define SPX_CONTEXT_H + +#include +#include + +#include "params.h" + +typedef struct { + uint8_t pub_seed[SPX_N]; + uint8_t sk_seed[SPX_N]; + + + uint64_t tweaked512_rc64[10][8]; + uint32_t tweaked256_rc32[10][8]; +} spx_ctx; + +#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) +void initialize_hash_function(spx_ctx *ctx); + +#define free_hash_function SPX_NAMESPACE(free_hash_function) +void free_hash_function(spx_ctx *ctx); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/context_haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/context_haraka.c new file mode 100644 index 0000000000..f1cd7e3664 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/context_haraka.c @@ -0,0 +1,11 @@ +#include "context.h" +#include "haraka.h" + +void initialize_hash_function(spx_ctx *ctx) { + tweak_constants(ctx); +} + +// we don't support heap-based haraka right now +void free_hash_function(spx_ctx *ctx) { + (void)ctx; // suppress unused variable warnings +} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/fors.c b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/fors.c index e09e117975..96ca72e986 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/fors.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/fors.c @@ -2,58 +2,58 @@ #include #include -#include "address.h" #include "fors.h" + +#include "address.h" #include "hash.h" -#include "hash_state.h" #include "thash.h" #include "utils.h" +#include "utilsx1.h" -static void fors_gen_sk(unsigned char *sk, const unsigned char *sk_seed, - uint32_t fors_leaf_addr[8], const hash_state *hash_state_seeded) { - PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_prf_addr( - sk, sk_seed, fors_leaf_addr, hash_state_seeded); +static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + prf_addr(sk, ctx, fors_leaf_addr); } static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, - const unsigned char *pub_seed, - uint32_t fors_leaf_addr[8], - const hash_state *hash_state_seeded) { - PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_thash_1( - leaf, sk, pub_seed, fors_leaf_addr, hash_state_seeded); + const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + thash(leaf, sk, 1, ctx, fors_leaf_addr); } -static void fors_gen_leaf(unsigned char *leaf, const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx, const uint32_t fors_tree_addr[8], - const hash_state *hash_state_seeded) { - uint32_t fors_leaf_addr[8] = {0}; - - /* Only copy the parts that must be kept in fors_leaf_addr. */ - PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_copy_keypair_addr( - fors_leaf_addr, fors_tree_addr); - PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_set_type( - fors_leaf_addr, PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_set_tree_index( - fors_leaf_addr, addr_idx); - - fors_gen_sk(leaf, sk_seed, fors_leaf_addr, hash_state_seeded); - fors_sk_to_leaf(leaf, leaf, pub_seed, fors_leaf_addr, hash_state_seeded); +struct fors_gen_leaf_info { + uint32_t leaf_addrx[8]; +}; + +static void fors_gen_leafx1(unsigned char *leaf, + const spx_ctx *ctx, + uint32_t addr_idx, void *info) { + struct fors_gen_leaf_info *fors_info = info; + uint32_t *fors_leaf_addr = fors_info->leaf_addrx; + + /* Only set the parts that the caller doesn't set */ + set_tree_index(fors_leaf_addr, addr_idx); + set_type(fors_leaf_addr, SPX_ADDR_TYPE_FORSPRF); + fors_gen_sk(leaf, ctx, fors_leaf_addr); + + set_type(fors_leaf_addr, SPX_ADDR_TYPE_FORSTREE); + fors_sk_to_leaf(leaf, leaf, + ctx, fors_leaf_addr); } /** - * Interprets m as PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_FORS_HEIGHT-bit unsigned integers. - * Assumes m contains at least PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_FORS_TREES bits. - * Assumes indices has space for PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_FORS_TREES integers. + * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + * Assumes indices has space for SPX_FORS_TREES integers. */ static void message_to_indices(uint32_t *indices, const unsigned char *m) { unsigned int i, j; unsigned int offset = 0; - for (i = 0; i < PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_FORS_TREES; i++) { + for (i = 0; i < SPX_FORS_TREES; i++) { indices[i] = 0; - for (j = 0; j < PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_FORS_HEIGHT; j++) { - indices[i] ^= (((uint32_t)m[offset >> 3] >> (offset & 0x7)) & 0x1) << j; + for (j = 0; j < SPX_FORS_HEIGHT; j++) { + indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); offset++; } } @@ -61,55 +61,51 @@ static void message_to_indices(uint32_t *indices, const unsigned char *m) { /** * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_FORS_TREES bits. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. */ -void PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_fors_sign( - unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *hash_state_seeded) { - uint32_t indices[PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_FORS_TREES]; - unsigned char roots[PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_FORS_TREES * PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_N]; +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; uint32_t fors_tree_addr[8] = {0}; + struct fors_gen_leaf_info fors_info = {0}; + uint32_t *fors_leaf_addr = fors_info.leaf_addrx; uint32_t fors_pk_addr[8] = {0}; uint32_t idx_offset; unsigned int i; - PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_copy_keypair_addr( - fors_tree_addr, fors_addr); - PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_copy_keypair_addr( - fors_pk_addr, fors_addr); + copy_keypair_addr(fors_tree_addr, fors_addr); + copy_keypair_addr(fors_leaf_addr, fors_addr); - PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_set_type( - fors_tree_addr, PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_set_type( - fors_pk_addr, PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_ADDR_TYPE_FORSPK); + copy_keypair_addr(fors_pk_addr, fors_addr); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); message_to_indices(indices, m); - for (i = 0; i < PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_FORS_TREES; i++) { - idx_offset = i * (1 << PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_FORS_HEIGHT); + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); - PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_set_tree_height( - fors_tree_addr, 0); - PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_set_tree_index( - fors_tree_addr, indices[i] + idx_offset); + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); /* Include the secret key part that produces the selected leaf node. */ - fors_gen_sk(sig, sk_seed, fors_tree_addr, hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_N; + fors_gen_sk(sig, ctx, fors_tree_addr); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + sig += SPX_N; /* Compute the authentication path for this leaf node. */ - PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_treehash_FORS_HEIGHT( - roots + i * PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_N, sig, sk_seed, pub_seed, - indices[i], idx_offset, fors_gen_leaf, fors_tree_addr, - hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_N * PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_FORS_HEIGHT; + treehashx1(roots + i * SPX_N, sig, ctx, + indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx1, + fors_tree_addr, &fors_info); + + sig += SPX_N * SPX_FORS_HEIGHT; } /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_thash_FORS_TREES( - pk, roots, pub_seed, fors_pk_addr, hash_state_seeded); + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); } /** @@ -117,45 +113,44 @@ void PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_fors_sign( * This can be used for verification by comparing to a known public key, or to * subsequently verify a signature on the derived public key. The latter is the * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_FORS_TREES bits. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. */ -void PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_fors_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, const uint32_t fors_addr[8], - const hash_state *hash_state_seeded) { - uint32_t indices[PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_FORS_TREES]; - unsigned char roots[PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_FORS_TREES * PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_N]; - unsigned char leaf[PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_N]; +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + unsigned char leaf[SPX_N]; uint32_t fors_tree_addr[8] = {0}; uint32_t fors_pk_addr[8] = {0}; uint32_t idx_offset; unsigned int i; - PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_copy_keypair_addr(fors_tree_addr, fors_addr); - PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_copy_keypair_addr(fors_pk_addr, fors_addr); + copy_keypair_addr(fors_tree_addr, fors_addr); + copy_keypair_addr(fors_pk_addr, fors_addr); - PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_set_type(fors_tree_addr, PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_set_type(fors_pk_addr, PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_ADDR_TYPE_FORSPK); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); message_to_indices(indices, m); - for (i = 0; i < PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_FORS_TREES; i++) { - idx_offset = i * (1 << PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_FORS_HEIGHT); + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); - PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_set_tree_height(fors_tree_addr, 0); - PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_set_tree_index(fors_tree_addr, indices[i] + idx_offset); + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); /* Derive the leaf from the included secret key part. */ - fors_sk_to_leaf(leaf, sig, pub_seed, fors_tree_addr, hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_N; + fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); + sig += SPX_N; /* Derive the corresponding root node of this tree. */ - PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_compute_root(roots + i * PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_N, leaf, indices[i], idx_offset, sig, - PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_FORS_HEIGHT, pub_seed, fors_tree_addr, hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_N * PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_FORS_HEIGHT; + compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, + sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); + sig += SPX_N * SPX_FORS_HEIGHT; } /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_thash_FORS_TREES(pk, roots, pub_seed, fors_pk_addr, hash_state_seeded); + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/fors.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/fors.h index 86b48f61d6..509140a178 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/fors.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/fors.h @@ -1,32 +1,32 @@ -#ifndef PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_FORS_H -#define PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_FORS_H +#ifndef SPX_FORS_H +#define SPX_FORS_H #include -#include "hash_state.h" +#include "context.h" #include "params.h" /** * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_FORS_TREES bits. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. */ -void PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_fors_sign( - unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *hash_state_seeded); +#define fors_sign SPX_NAMESPACE(fors_sign) +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); /** * Derives the FORS public key from a signature. * This can be used for verification by comparing to a known public key, or to * subsequently verify a signature on the derived public key. The latter is the * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_FORS_TREES bits. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. */ -void PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_fors_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, const uint32_t fors_addr[8], - const hash_state *hash_state_seeded); +#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/haraka.c index fb1bf5ef19..a4944913b5 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/haraka.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/haraka.c @@ -6,12 +6,13 @@ * by Thomas Pornin */ -#include #include +#include #include #include #include "haraka.h" +#include "utils.h" #define HARAKAS_RATE 32 @@ -656,76 +657,62 @@ static void interleave_constant32(uint32_t *out, const unsigned char *in) { br_aes_ct_ortho(out); } -void PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_tweak_constants( - harakactx *state, - const unsigned char *pk_seed, const unsigned char *sk_seed, - unsigned long long seed_length) { +void tweak_constants(spx_ctx *ctx) { unsigned char buf[40 * 16]; int i; /* Use the standard constants to generate tweaked ones. */ - memcpy((uint8_t *)state->tweaked512_rc64, (uint8_t *)haraka512_rc64, 40 * 16); - - /* Constants for sk.seed */ - if (sk_seed != NULL) { - PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_haraka_S( - buf, 40 * 16, sk_seed, seed_length, state); - - /* Interleave constants */ - for (i = 0; i < 10; i++) { - interleave_constant32(state->tweaked256_rc32_sseed[i], buf + 32 * i); - } - } + memcpy((uint8_t *)ctx->tweaked512_rc64, (uint8_t *)haraka512_rc64, 40 * 16); /* Constants for pk.seed */ - PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_haraka_S( - buf, 40 * 16, pk_seed, seed_length, state); + haraka_S(buf, 40 * 16, ctx->pub_seed, SPX_N, ctx); for (i = 0; i < 10; i++) { - interleave_constant32(state->tweaked256_rc32[i], buf + 32 * i); - interleave_constant(state->tweaked512_rc64[i], buf + 64 * i); + interleave_constant32(ctx->tweaked256_rc32[i], buf + 32 * i); + interleave_constant(ctx->tweaked512_rc64[i], buf + 64 * i); } } -static void haraka_S_absorb(unsigned char *s, +static void haraka_S_absorb(unsigned char *s, unsigned int r, const unsigned char *m, unsigned long long mlen, - unsigned char p, const harakactx *state) { + unsigned char p, const spx_ctx *ctx) { unsigned long long i; - unsigned char t[HARAKAS_RATE]; + PQCLEAN_VLA(uint8_t, t, r); - while (mlen >= HARAKAS_RATE) { + while (mlen >= r) { /* XOR block to state */ - for (i = 0; i < HARAKAS_RATE; ++i) { + for (i = 0; i < r; ++i) { s[i] ^= m[i]; } - PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_haraka512_perm(s, s, state); - mlen -= HARAKAS_RATE; - m += HARAKAS_RATE; + haraka512_perm(s, s, ctx); + mlen -= r; + m += r; } - for (i = 0; i < HARAKAS_RATE; ++i) { + for (i = 0; i < r; ++i) { t[i] = 0; } for (i = 0; i < mlen; ++i) { t[i] = m[i]; } t[i] = p; - t[HARAKAS_RATE - 1] |= 128; - for (i = 0; i < HARAKAS_RATE; ++i) { + t[r - 1] |= 128; + for (i = 0; i < r; ++i) { s[i] ^= t[i]; } } static void haraka_S_squeezeblocks(unsigned char *h, unsigned long long nblocks, - unsigned char *s, const harakactx *state) { + unsigned char *s, unsigned int r, + const spx_ctx *ctx) { while (nblocks > 0) { - PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_haraka512_perm(s, s, state); + haraka512_perm(s, s, ctx); memcpy(h, s, HARAKAS_RATE); - h += HARAKAS_RATE; + h += r; nblocks--; } } -void PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_haraka_S_inc_init(uint8_t *s_inc) { +void haraka_S_inc_init(uint8_t *s_inc) { size_t i; for (i = 0; i < 64; i++) { @@ -734,7 +721,8 @@ void PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_haraka_S_inc_init(uint8_t *s_inc) { s_inc[64] = 0; } -void PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, const harakactx *state) { +void haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, + const spx_ctx *ctx) { size_t i; /* Recall that s_inc[64] is the non-absorbed bytes xored into the state */ @@ -745,19 +733,19 @@ void PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_haraka_S_inc_absorb(uint8_t *s_inc, c s_inc[s_inc[64] + i] ^= m[i]; } mlen -= (size_t)(HARAKAS_RATE - s_inc[64]); - m += HARAKAS_RATE - s_inc[64]; + m += HARAKAS_RATE - (uint8_t)s_inc[64]; s_inc[64] = 0; - PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_haraka512_perm(s_inc, s_inc, state); + haraka512_perm(s_inc, s_inc, ctx); } for (i = 0; i < mlen; i++) { s_inc[s_inc[64] + i] ^= m[i]; } - s_inc[64] = (uint8_t)(mlen + s_inc[64]); + s_inc[64] += (uint8_t)mlen; } -void PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_haraka_S_inc_finalize(uint8_t *s_inc) { +void haraka_S_inc_finalize(uint8_t *s_inc) { /* After haraka_S_inc_absorb, we are guaranteed that s_inc[64] < HARAKAS_RATE, so we can always use one more byte for p in the current state. */ s_inc[s_inc[64]] ^= 0x1F; @@ -765,22 +753,23 @@ void PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_haraka_S_inc_finalize(uint8_t *s_inc) s_inc[64] = 0; } -void PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, const harakactx *state) { - uint8_t i; +void haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, + const spx_ctx *ctx) { + size_t i; /* First consume any bytes we still have sitting around */ for (i = 0; i < outlen && i < s_inc[64]; i++) { /* There are s_inc[64] bytes left, so r - s_inc[64] is the first available byte. We consume from there, i.e., up to r. */ - out[i] = s_inc[(HARAKAS_RATE - s_inc[64] + i)]; + out[i] = (uint8_t)s_inc[(HARAKAS_RATE - s_inc[64] + i)]; } out += i; outlen -= i; - s_inc[64] = (uint8_t)(s_inc[64] - i); + s_inc[64] -= (uint8_t)i; /* Then squeeze the remaining necessary blocks */ while (outlen > 0) { - PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_haraka512_perm(s_inc, s_inc, state); + haraka512_perm(s_inc, s_inc, ctx); for (i = 0; i < outlen && i < HARAKAS_RATE; i++) { out[i] = s_inc[i]; @@ -791,7 +780,9 @@ void PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_haraka_S_inc_squeeze(uint8_t *out, si } } -void PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_haraka_S(unsigned char *out, unsigned long long outlen, const unsigned char *in, unsigned long long inlen, const harakactx *state) { +void haraka_S(unsigned char *out, unsigned long long outlen, + const unsigned char *in, unsigned long long inlen, + const spx_ctx *ctx) { unsigned long long i; unsigned char s[64]; unsigned char d[32]; @@ -799,20 +790,21 @@ void PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_haraka_S(unsigned char *out, unsigned for (i = 0; i < 64; i++) { s[i] = 0; } - haraka_S_absorb(s, in, inlen, 0x1F, state); + haraka_S_absorb(s, 32, in, inlen, 0x1F, ctx); - haraka_S_squeezeblocks(out, outlen / 32, s, state); + haraka_S_squeezeblocks(out, outlen / 32, s, 32, ctx); out += (outlen / 32) * 32; if (outlen % 32) { - haraka_S_squeezeblocks(d, 1, s, state); + haraka_S_squeezeblocks(d, 1, s, 32, ctx); for (i = 0; i < outlen % 32; i++) { out[i] = d[i]; } } } -void PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_haraka512_perm(unsigned char *out, const unsigned char *in, const harakactx *state) { +void haraka512_perm(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx) { uint32_t w[16]; uint64_t q[8], tmp_q; unsigned int i, j; @@ -829,7 +821,7 @@ void PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_haraka512_perm(unsigned char *out, co br_aes_ct64_bitslice_Sbox(q); shift_rows(q); mix_columns(q); - add_round_key(q, state->tweaked512_rc64[2 * i + j]); + add_round_key(q, ctx->tweaked512_rc64[2 * i + j]); } /* Mix states */ for (j = 0; j < 8; j++) { @@ -857,12 +849,12 @@ void PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_haraka512_perm(unsigned char *out, co br_range_enc32le(out, w, 16); } -void PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_haraka512(unsigned char *out, const unsigned char *in, const harakactx *state) { +void haraka512(unsigned char *out, const unsigned char *in, const spx_ctx *ctx) { int i; unsigned char buf[64]; - PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_haraka512_perm(buf, in, state); + haraka512_perm(buf, in, ctx); /* Feed-forward */ for (i = 0; i < 64; i++) { buf[i] = buf[i] ^ in[i]; @@ -876,50 +868,8 @@ void PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_haraka512(unsigned char *out, const u } -void PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_haraka256(unsigned char *out, const unsigned char *in, const harakactx *state) { - uint32_t q[8], tmp_q; - int i, j; - - for (i = 0; i < 4; i++) { - q[2 * i] = br_dec32le(in + 4 * i); - q[2 * i + 1] = br_dec32le(in + 4 * i + 16); - } - br_aes_ct_ortho(q); - - /* AES rounds */ - for (i = 0; i < 5; i++) { - for (j = 0; j < 2; j++) { - br_aes_ct_bitslice_Sbox(q); - shift_rows32(q); - mix_columns32(q); - add_round_key32(q, state->tweaked256_rc32[2 * i + j]); - } - - /* Mix states */ - for (j = 0; j < 8; j++) { - tmp_q = q[j]; - q[j] = (tmp_q & 0x81818181) | - (tmp_q & 0x02020202) << 1 | - (tmp_q & 0x04040404) << 2 | - (tmp_q & 0x08080808) << 3 | - (tmp_q & 0x10101010) >> 3 | - (tmp_q & 0x20202020) >> 2 | - (tmp_q & 0x40404040) >> 1; - } - } - - br_aes_ct_ortho(q); - for (i = 0; i < 4; i++) { - br_enc32le(out + 4 * i, q[2 * i]); - br_enc32le(out + 4 * i + 16, q[2 * i + 1]); - } - - for (i = 0; i < 32; i++) { - out[i] ^= in[i]; - } -} - -void PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_haraka256_sk(unsigned char *out, const unsigned char *in, const harakactx *state) { +void haraka256(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx) { uint32_t q[8], tmp_q; int i, j; @@ -935,7 +885,7 @@ void PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_haraka256_sk(unsigned char *out, cons br_aes_ct_bitslice_Sbox(q); shift_rows32(q); mix_columns32(q); - add_round_key32(q, state->tweaked256_rc32_sseed[2 * i + j]); + add_round_key32(q, ctx->tweaked256_rc32[2 * i + j]); } /* Mix states */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/haraka.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/haraka.h index b5e035a641..737cb6065f 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/haraka.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/haraka.h @@ -1,40 +1,42 @@ -#ifndef PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_HARAKA_H -#define PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_HARAKA_H +#ifndef SPX_HARAKA_H +#define SPX_HARAKA_H -#include -#include - -typedef struct { - uint64_t tweaked512_rc64[10][8]; - uint32_t tweaked256_rc32[10][8]; - uint32_t tweaked256_rc32_sseed[10][8]; -} harakactx; +#include "context.h" +#include "params.h" /* Tweak constants with seed */ -void PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_tweak_constants( - harakactx *state, - const unsigned char *pk_seed, const unsigned char *sk_seed, - unsigned long long seed_length); +#define tweak_constants SPX_NAMESPACE(tweak_constants) +void tweak_constants(spx_ctx *ctx); /* Haraka Sponge */ -void PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_haraka_S_inc_init(uint8_t *s_inc); -void PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, const harakactx *state); -void PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_haraka_S_inc_finalize(uint8_t *s_inc); -void PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, const harakactx *state); -void PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_haraka_S( - unsigned char *out, unsigned long long outlen, - const unsigned char *in, unsigned long long inlen, const harakactx *state); +#define haraka_S_inc_init SPX_NAMESPACE(haraka_S_inc_init) +void haraka_S_inc_init(uint8_t *s_inc); +#define haraka_S_inc_absorb SPX_NAMESPACE(haraka_S_inc_absorb) +void haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, + const spx_ctx *ctx); +#define haraka_S_inc_finalize SPX_NAMESPACE(haraka_S_inc_finalize) +void haraka_S_inc_finalize(uint8_t *s_inc); +#define haraka_S_inc_squeeze SPX_NAMESPACE(haraka_S_inc_squeeze) +void haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, + const spx_ctx *ctx); +#define haraka_S SPX_NAMESPACE(haraka_S) +void haraka_S(unsigned char *out, unsigned long long outlen, + const unsigned char *in, unsigned long long inlen, + const spx_ctx *ctx); /* Applies the 512-bit Haraka permutation to in. */ -void PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_haraka512_perm(unsigned char *out, const unsigned char *in, const harakactx *state); +#define haraka512_perm SPX_NAMESPACE(haraka512_perm) +void haraka512_perm(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx); /* Implementation of Haraka-512 */ -void PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_haraka512(unsigned char *out, const unsigned char *in, const harakactx *state); +#define haraka512 SPX_NAMESPACE(haraka512) +void haraka512(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx); /* Implementation of Haraka-256 */ -void PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_haraka256(unsigned char *out, const unsigned char *in, const harakactx *state); - -/* Implementation of Haraka-256 using sk.seed constants */ -void PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_haraka256_sk(unsigned char *out, const unsigned char *in, const harakactx *state); +#define haraka256 SPX_NAMESPACE(haraka256) +void haraka256(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/haraka_offsets.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/haraka_offsets.h new file mode 100644 index 0000000000..7c062272a0 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/haraka_offsets.h @@ -0,0 +1,21 @@ +#ifndef HARAKA_OFFSETS_H_ +#define HARAKA_OFFSETS_H_ + +/* + * Offsets of various fields in the address structure when we use Haraka as + * the Sphincs+ hash function + */ + +#define SPX_OFFSET_LAYER 3 /* The byte used to specify the Merkle tree layer */ +#define SPX_OFFSET_TREE 8 /* The start of the 8 byte field used to specify the tree */ +#define SPX_OFFSET_TYPE 19 /* The byte used to specify the hash type (reason) */ +#define SPX_OFFSET_KP_ADDR2 22 /* The high byte used to specify the key pair (which one-time signature) */ +#define SPX_OFFSET_KP_ADDR1 23 /* The low byte used to specify the key pair */ +#define SPX_OFFSET_CHAIN_ADDR 27 /* The byte used to specify the chain address (which Winternitz chain) */ +#define SPX_OFFSET_HASH_ADDR 31 /* The byte used to specify the hash address (where in the Winternitz chain) */ +#define SPX_OFFSET_TREE_HGT 27 /* The byte used to specify the height of this node in the FORS or Merkle tree */ +#define SPX_OFFSET_TREE_INDEX 28 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ + +#define SPX_HARAKA 1 + +#endif /* HARAKA_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/hash.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/hash.h index e827cb18ac..f7c87d4c3c 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/hash.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/hash.h @@ -1,31 +1,28 @@ -#ifndef PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_HASH_H -#define PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_HASH_H - -#include "hash_state.h" +#ifndef SPX_HASH_H +#define SPX_HASH_H #include #include -void PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_initialize_hash_function( - hash_state *hash_state_seeded, - const unsigned char *pub_seed, const unsigned char *sk_seed); +#include "context.h" +#include "params.h" + +#define prf_addr SPX_NAMESPACE(prf_addr) +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]); -void PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_destroy_hash_function(hash_state *hash_state_seeded); +#define gen_message_random SPX_NAMESPACE(gen_message_random) +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); -void PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded); +#define hash_message SPX_NAMESPACE(hash_message) +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); -void PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); -void PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/hash_haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/hash_haraka.c index 13b0ca959d..750a67423b 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/hash_haraka.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/hash_haraka.c @@ -2,58 +2,44 @@ #include #include "address.h" -#include "haraka.h" -#include "hash.h" #include "params.h" #include "utils.h" -void PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_initialize_hash_function( - hash_state *hash_state_seeded, - const unsigned char *pub_seed, const unsigned char *sk_seed) { - PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_tweak_constants(hash_state_seeded, pub_seed, sk_seed, PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_N); -} - -/* The haraka implementation is stack based and won't be replaced in PQClean/OQS, - so we don't need to do anything */ -void PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_destroy_hash_function( - hash_state *hash_state_seeded) { // NOLINT(readability-non-const-parameter) - (void)hash_state_seeded; -} +#include "haraka.h" +#include "hash.h" /* - * Computes PRF(key, addr), given a secret key of PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_N bytes and an address + * Computes PRF(key, addr), given a secret key of SPX_N bytes and an address */ -void PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded) { - unsigned char buf[PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_ADDR_BYTES]; - /* Since PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_N may be smaller than 32, we need a temporary buffer. */ +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]) { + /* Since SPX_N may be smaller than 32, we need temporary buffers. */ unsigned char outbuf[32]; + unsigned char buf[64] = {0}; - (void)key; /* Suppress an 'unused parameter' warning. */ + memcpy(buf, addr, SPX_ADDR_BYTES); + memcpy(buf + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); - PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_addr_to_bytes(buf, addr); - PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_haraka256_sk(outbuf, buf, hash_state_seeded); - memcpy(out, outbuf, PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_N); + haraka512(outbuf, (const void *)buf, ctx); + memcpy(out, outbuf, SPX_N); } /** * Computes the message-dependent randomness R, using a secret seed and an * optional randomization value as well as the message. */ -void PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded) { +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { uint8_t s_inc[65]; - PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_haraka_S_inc_init(s_inc); - PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_haraka_S_inc_absorb(s_inc, sk_prf, PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_N, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_haraka_S_inc_absorb(s_inc, optrand, PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_N, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_haraka_S_inc_absorb(s_inc, m, mlen, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_haraka_S_inc_finalize(s_inc); - PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_haraka_S_inc_squeeze(R, PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_N, s_inc, hash_state_seeded); + haraka_S_inc_init(s_inc); + haraka_S_inc_absorb(s_inc, sk_prf, SPX_N, ctx); + haraka_S_inc_absorb(s_inc, optrand, SPX_N, ctx); + haraka_S_inc_absorb(s_inc, m, mlen, ctx); + haraka_S_inc_finalize(s_inc); + haraka_S_inc_squeeze(R, SPX_N, s_inc, ctx); } /** @@ -61,36 +47,35 @@ void PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_gen_message_random( * Outputs the message digest and the index of the leaf. The index is split in * the tree index and the leaf index, for convenient copying to an address. */ -void PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded) { -#define PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_TREE_BITS (PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_TREE_HEIGHT * (PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_D - 1)) -#define PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_TREE_BYTES ((PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_TREE_BITS + 7) / 8) -#define PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_LEAF_BITS PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_TREE_HEIGHT -#define PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_LEAF_BYTES ((PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_LEAF_BITS + 7) / 8) -#define PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_DGST_BYTES (PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_FORS_MSG_BYTES + PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_TREE_BYTES + PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_LEAF_BYTES) +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { +#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) +#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) +#define SPX_LEAF_BITS SPX_TREE_HEIGHT +#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) +#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) - unsigned char buf[PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_DGST_BYTES]; + unsigned char buf[SPX_DGST_BYTES]; unsigned char *bufp = buf; uint8_t s_inc[65]; - PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_haraka_S_inc_init(s_inc); - PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_haraka_S_inc_absorb(s_inc, R, PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_N, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_haraka_S_inc_absorb(s_inc, pk + PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_N, PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_N, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_haraka_S_inc_absorb(s_inc, m, mlen, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_haraka_S_inc_finalize(s_inc); - PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_haraka_S_inc_squeeze(buf, PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_DGST_BYTES, s_inc, hash_state_seeded); + haraka_S_inc_init(s_inc); + haraka_S_inc_absorb(s_inc, R, SPX_N, ctx); + haraka_S_inc_absorb(s_inc, pk + SPX_N, SPX_N, ctx); // Only absorb root part of pk + haraka_S_inc_absorb(s_inc, m, mlen, ctx); + haraka_S_inc_finalize(s_inc); + haraka_S_inc_squeeze(buf, SPX_DGST_BYTES, s_inc, ctx); + + memcpy(digest, bufp, SPX_FORS_MSG_BYTES); + bufp += SPX_FORS_MSG_BYTES; - memcpy(digest, bufp, PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_FORS_MSG_BYTES); - bufp += PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_FORS_MSG_BYTES; - *tree = PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_bytes_to_ull(bufp, PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_TREE_BYTES); - *tree &= (~(uint64_t)0) >> (64 - PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_TREE_BITS); - bufp += PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_TREE_BYTES; + *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); + *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); + bufp += SPX_TREE_BYTES; - *leaf_idx = (uint32_t)PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_bytes_to_ull( - bufp, PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_LEAF_BYTES); - *leaf_idx &= (~(uint32_t)0) >> (32 - PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_LEAF_BITS); + *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); + *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/hash_state.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/hash_state.h deleted file mode 100644 index 5adb1d9a22..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/hash_state.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef SPX_HASH_STATE_H -#define SPX_HASH_STATE_H - -/** - * Defines the type of the hash function state. - * - * Don't be fooled into thinking this instance of SPHINCS+ isn't stateless! - * - * From Section 7.2.2 from the SPHINCS+ round-2 specification: - * - * Each of the instances of the tweakable hash function take PK.seed as its - * first input, which is constant for a given key pair – and, thus, across - * a single signature. This leads to a lot of redundant computation. To remedy - * this, we pad PK.seed to the length of a full 64-byte SHA-256 input block. - * Because of the Merkle-DamgÃ¥rd construction that underlies SHA-256, this - * allows for reuse of the intermediate SHA-256 state after the initial call to - * the compression function which improves performance. - * - * We pass this hash state around in functions, because otherwise we need to - * have a global variable. - */ - -#include "haraka.h" -#define hash_state harakactx - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/merkle.c b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/merkle.c new file mode 100644 index 0000000000..0c1479fd93 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/merkle.c @@ -0,0 +1,59 @@ +#include +#include + +#include "address.h" +#include "merkle.h" +#include "params.h" +#include "utils.h" +#include "utilsx1.h" +#include "wots.h" +#include "wotsx1.h" + +/* + * This generates a Merkle signature (WOTS signature followed by the Merkle + * authentication path). This is in this file because most of the complexity + * is involved with the WOTS signature; the Merkle authentication path logic + * is mostly hidden in treehashx4 + */ +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf) { + unsigned char *auth_path = sig + SPX_WOTS_BYTES; + struct leaf_info_x1 info = { 0 }; + unsigned steps[ SPX_WOTS_LEN ]; + + info.wots_sig = sig; + chain_lengths(steps, root); + info.wots_steps = steps; + + set_type(&tree_addr[0], SPX_ADDR_TYPE_HASHTREE); + set_type(&info.pk_addr[0], SPX_ADDR_TYPE_WOTSPK); + copy_subtree_addr(&info.leaf_addr[0], wots_addr); + copy_subtree_addr(&info.pk_addr[0], wots_addr); + + info.wots_sign_leaf = idx_leaf; + + treehashx1(root, auth_path, ctx, + idx_leaf, 0, + SPX_TREE_HEIGHT, + wots_gen_leafx1, + tree_addr, &info); +} + +/* Compute root node of the top-most subtree. */ +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { + /* We do not need the auth path in key generation, but it simplifies the + code to have just one treehash routine that computes both root and path + in one function. */ + unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; + uint32_t top_tree_addr[8] = {0}; + uint32_t wots_addr[8] = {0}; + + set_layer_addr(top_tree_addr, SPX_D - 1); + set_layer_addr(wots_addr, SPX_D - 1); + + merkle_sign(auth_path, root, ctx, + wots_addr, top_tree_addr, + (uint32_t)~0 /* ~0 means "don't bother generating an auth path */ ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/merkle.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/merkle.h new file mode 100644 index 0000000000..769cf2e970 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/merkle.h @@ -0,0 +1,21 @@ +#ifndef MERKLE_H_ +#define MERKLE_H_ + +#include + +#include "context.h" +#include "params.h" + +/* Generate a Merkle signature (WOTS signature followed by the Merkle */ +/* authentication path) */ +#define merkle_sign SPX_NAMESPACE(merkle_sign) +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf); + +/* Compute the root node of the top-most subtree. */ +#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); + +#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/nistapi.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/nistapi.h new file mode 100644 index 0000000000..3cb71afad4 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/nistapi.h @@ -0,0 +1,87 @@ +#ifndef SPX_API_H +#define SPX_API_H + +#include +#include + +#include "params.h" + +#define CRYPTO_ALGNAME "SPHINCS+" + +#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES +#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES +#define CRYPTO_BYTES SPX_BYTES +#define CRYPTO_SEEDBYTES (3*SPX_N) + +/* + * Returns the length of a secret key, in bytes + */ +#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) +size_t crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) +size_t crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) +size_t crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) +size_t crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +#define crypto_sign SPX_NAMESPACE(crypto_sign) +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/params.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/params.h index f6f019f897..97a78a6066 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/params.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/params.h @@ -1,53 +1,56 @@ -#ifndef PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_PARAMS_H -#define PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_PARAMS_H +#ifndef SPX_PARAMS_H +#define SPX_PARAMS_H + +#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_##s /* Hash output length in bytes. */ -#define PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_N 32 +#define SPX_N 32 /* Height of the hypertree. */ -#define PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_FULL_HEIGHT 64 +#define SPX_FULL_HEIGHT 64 /* Number of subtree layer. */ -#define PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_D 8 +#define SPX_D 8 /* FORS tree dimensions. */ -#define PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_FORS_HEIGHT 14 -#define PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_FORS_TREES 22 +#define SPX_FORS_HEIGHT 14 +#define SPX_FORS_TREES 22 /* Winternitz parameter, */ -#define PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_WOTS_W 16 +#define SPX_WOTS_W 16 /* The hash function is defined by linking a different hash.c file, as opposed to setting a #define constant. */ /* For clarity */ -#define PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_ADDR_BYTES 32 +#define SPX_ADDR_BYTES 32 /* WOTS parameters. */ -#define PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_WOTS_LOGW 4 +#define SPX_WOTS_LOGW 4 -#define PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_WOTS_LEN1 (8 * PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_N / PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_WOTS_LOGW) +#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) -/* PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#define PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_WOTS_LEN2 3 +/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ +#define SPX_WOTS_LEN2 3 -#define PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_WOTS_LEN (PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_WOTS_LEN1 + PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_WOTS_LEN2) -#define PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_WOTS_BYTES (PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_WOTS_LEN * PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_N) -#define PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_WOTS_PK_BYTES PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_WOTS_BYTES +#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) +#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) +#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES /* Subtree size. */ -#define PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_TREE_HEIGHT (PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_FULL_HEIGHT / PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_D) +#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) + +//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT +// #error SPX_D should always divide SPX_FULL_HEIGHT +//#endif /* FORS parameters. */ -#define PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_FORS_MSG_BYTES ((PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_FORS_TREES + 7) / 8) -#define PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_FORS_BYTES ((PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_FORS_HEIGHT + 1) * PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_FORS_TREES * PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_N) -#define PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_FORS_PK_BYTES PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_N +#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) +#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) +#define SPX_FORS_PK_BYTES SPX_N /* Resulting SPX sizes. */ -#define PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_BYTES (PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_N + PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_FORS_BYTES + PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_D * PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_WOTS_BYTES +\ - PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_FULL_HEIGHT * PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_N) -#define PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_PK_BYTES (2 * PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_N) -#define PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_SK_BYTES (2 * PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_N + PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_PK_BYTES) - -/* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ -#define PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_OPTRAND_BYTES 32 +#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ + SPX_FULL_HEIGHT * SPX_N) +#define SPX_PK_BYTES (2 * SPX_N) +#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) + +#include "haraka_offsets.h" #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/sign.c b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/sign.c index 815a70e33b..9d0c7d1b22 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/sign.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/sign.c @@ -3,72 +3,43 @@ #include #include "address.h" -#include "api.h" +#include "context.h" #include "fors.h" #include "hash.h" -#include "hash_state.h" +#include "merkle.h" +#include "nistapi.h" #include "params.h" #include "randombytes.h" #include "thash.h" #include "utils.h" #include "wots.h" -/** - * Computes the leaf at a given address. First generates the WOTS key pair, - * then computes leaf by hashing horizontally. - */ -static void wots_gen_leaf(unsigned char *leaf, const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx, const uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - unsigned char pk[PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_WOTS_BYTES]; - uint32_t wots_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_set_type( - wots_addr, PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_set_type( - wots_pk_addr, PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_ADDR_TYPE_WOTSPK); - - PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_set_keypair_addr( - wots_addr, addr_idx); - PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_wots_gen_pk( - pk, sk_seed, pub_seed, wots_addr, hash_state_seeded); - - PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_copy_keypair_addr( - wots_pk_addr, wots_addr); - PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_thash_WOTS_LEN( - leaf, pk, pub_seed, wots_pk_addr, hash_state_seeded); -} - /* * Returns the length of a secret key, in bytes */ -size_t PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_crypto_sign_secretkeybytes(void) { - return PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_CRYPTO_SECRETKEYBYTES; +size_t crypto_sign_secretkeybytes(void) { + return CRYPTO_SECRETKEYBYTES; } /* * Returns the length of a public key, in bytes */ -size_t PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_crypto_sign_publickeybytes(void) { - return PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_CRYPTO_PUBLICKEYBYTES; +size_t crypto_sign_publickeybytes(void) { + return CRYPTO_PUBLICKEYBYTES; } /* * Returns the length of a signature, in bytes */ -size_t PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_crypto_sign_bytes(void) { - return PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_CRYPTO_BYTES; +size_t crypto_sign_bytes(void) { + return CRYPTO_BYTES; } /* * Returns the length of the seed required to generate a key pair, in bytes */ -size_t PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_crypto_sign_seedbytes(void) { - return PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_CRYPTO_SEEDBYTES; +size_t crypto_sign_seedbytes(void) { + return CRYPTO_SEEDBYTES; } /* @@ -76,37 +47,30 @@ size_t PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_crypto_sign_seedbytes(void) { * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] * Format pk: [PUB_SEED || root] */ -int PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed) { - /* We do not need the auth path in key generation, but it simplifies the - code to have just one treehash routine that computes both root and path - in one function. */ - unsigned char auth_path[PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_TREE_HEIGHT * PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_N]; - uint32_t top_tree_addr[8] = {0}; - hash_state hash_state_seeded; - - PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_set_layer_addr( - top_tree_addr, PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_D - 1); - PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_set_type( - top_tree_addr, PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_ADDR_TYPE_HASHTREE); +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed) { + spx_ctx ctx; /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ - memcpy(sk, seed, PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_CRYPTO_SEEDBYTES); + memcpy(sk, seed, CRYPTO_SEEDBYTES); - memcpy(pk, sk + 2 * PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_N, PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_N); + memcpy(pk, sk + 2 * SPX_N, SPX_N); + + memcpy(ctx.pub_seed, pk, SPX_N); + memcpy(ctx.sk_seed, sk, SPX_N); /* This hook allows the hash function instantiation to do whatever preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_initialize_hash_function(&hash_state_seeded, pk, sk); + initialize_hash_function(&ctx); /* Compute root node of the top-most subtree. */ - PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_treehash_TREE_HEIGHT( - sk + 3 * PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_N, auth_path, sk, sk + 2 * PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_N, 0, 0, - wots_gen_leaf, top_tree_addr, &hash_state_seeded); + merkle_gen_root(sk + 3 * SPX_N, &ctx); + + // cleanup + free_hash_function(&ctx); - memcpy(pk + PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_N, sk + 3 * PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_N, PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_N); + memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); - PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_destroy_hash_function(&hash_state_seeded); return 0; } @@ -115,12 +79,10 @@ int PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_crypto_sign_seed_keypair( * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] * Format pk: [PUB_SEED || root] */ -int PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk) { - unsigned char seed[PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_CRYPTO_SEEDBYTES]; - randombytes(seed, PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_CRYPTO_SEEDBYTES); - PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_crypto_sign_seed_keypair( - pk, sk, seed); +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { + uint8_t seed[CRYPTO_SEEDBYTES]; + randombytes(seed, CRYPTO_SEEDBYTES); + crypto_sign_seed_keypair(pk, sk, seed); return 0; } @@ -128,101 +90,83 @@ int PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_crypto_sign_keypair( /** * Returns an array containing a detached signature. */ -int PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - const unsigned char *sk_seed = sk; - const unsigned char *sk_prf = sk + PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_N; - const unsigned char *pk = sk + 2 * PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_N; - const unsigned char *pub_seed = pk; - - unsigned char optrand[PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_N]; - unsigned char mhash[PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_FORS_MSG_BYTES]; - unsigned char root[PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_N]; +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk) { + spx_ctx ctx; + + const uint8_t *sk_prf = sk + SPX_N; + const uint8_t *pk = sk + 2 * SPX_N; + + uint8_t optrand[SPX_N]; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t root[SPX_N]; uint32_t i; uint64_t tree; uint32_t idx_leaf; uint32_t wots_addr[8] = {0}; uint32_t tree_addr[8] = {0}; - hash_state hash_state_seeded; + memcpy(ctx.sk_seed, sk, SPX_N); + memcpy(ctx.pub_seed, pk, SPX_N); /* This hook allows the hash function instantiation to do whatever preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_initialize_hash_function( - &hash_state_seeded, - pub_seed, sk_seed); + initialize_hash_function(&ctx); - PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_set_type( - wots_addr, PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_set_type( - tree_addr, PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_ADDR_TYPE_HASHTREE); + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); /* Optionally, signing can be made non-deterministic using optrand. This can help counter side-channel attacks that would benefit from getting a large number of traces when the signer uses the same nodes. */ - randombytes(optrand, PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_N); + randombytes(optrand, SPX_N); /* Compute the digest randomization value. */ - PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_gen_message_random( - sig, sk_prf, optrand, m, mlen, &hash_state_seeded); + gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); /* Derive the message digest and leaf index from R, PK and M. */ - PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_N; + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; - PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); /* Sign the message hash using FORS. */ - PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_fors_sign( - sig, root, mhash, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_FORS_BYTES; - - for (i = 0; i < PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_D; i++) { - PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_set_tree_addr(tree_addr, tree); - - PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); - - /* Compute a WOTS signature. */ - PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_wots_sign( - sig, root, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_WOTS_BYTES; - - /* Compute the authentication path for the used WOTS leaf. */ - PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_treehash_TREE_HEIGHT( - root, sig, sk_seed, pub_seed, idx_leaf, 0, - wots_gen_leaf, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_TREE_HEIGHT * PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_N; + fors_sign(sig, root, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); + sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_TREE_HEIGHT; + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; } - *siglen = PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_BYTES; + free_hash_function(&ctx); + + *siglen = SPX_BYTES; - PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_destroy_hash_function(&hash_state_seeded); return 0; } /** * Verifies a detached signature and message under a given public key. */ -int PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk) { - const unsigned char *pub_seed = pk; - const unsigned char *pub_root = pk + PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_N; - unsigned char mhash[PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_FORS_MSG_BYTES]; - unsigned char wots_pk[PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_WOTS_BYTES]; - unsigned char root[PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_N]; - unsigned char leaf[PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_N]; +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk) { + spx_ctx ctx; + const uint8_t *pub_root = pk + SPX_N; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t wots_pk[SPX_WOTS_BYTES]; + uint8_t root[SPX_N]; + uint8_t leaf[SPX_N]; unsigned int i; uint64_t tree; uint32_t idx_leaf; @@ -230,78 +174,66 @@ int PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_crypto_sign_verify( uint32_t tree_addr[8] = {0}; uint32_t wots_pk_addr[8] = {0}; - hash_state hash_state_seeded; - - if (siglen != PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_BYTES) { + if (siglen != SPX_BYTES) { return -1; } + memcpy(ctx.pub_seed, pk, SPX_N); + /* This hook allows the hash function instantiation to do whatever preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_initialize_hash_function( - &hash_state_seeded, - pub_seed, NULL); + initialize_hash_function(&ctx); - PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_set_type( - wots_addr, PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_set_type( - tree_addr, PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_ADDR_TYPE_HASHTREE); - PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_set_type( - wots_pk_addr, PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_ADDR_TYPE_WOTSPK); + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); /* Derive the message digest and leaf index from R || PK || M. */ - /* The additional PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_N is a result of the hash domain separator. */ - PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_N; + /* The additional SPX_N is a result of the hash domain separator. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; /* Layer correctly defaults to 0, so no need to set_layer_addr */ - PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); - PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_fors_pk_from_sig( - root, sig, mhash, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_FORS_BYTES; + fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; /* For each subtree.. */ - for (i = 0; i < PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_D; i++) { - PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_set_tree_addr(tree_addr, tree); + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); - PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); - PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_copy_keypair_addr( - wots_pk_addr, wots_addr); + copy_keypair_addr(wots_pk_addr, wots_addr); /* The WOTS public key is only correct if the signature was correct. */ /* Initially, root is the FORS pk, but on subsequent iterations it is the root of the subtree below the currently processed subtree. */ - PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_wots_pk_from_sig( - wots_pk, sig, root, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_WOTS_BYTES; + wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); + sig += SPX_WOTS_BYTES; /* Compute the leaf node using the WOTS public key. */ - PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_thash_WOTS_LEN( - leaf, wots_pk, pub_seed, wots_pk_addr, &hash_state_seeded); + thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); /* Compute the root node of this subtree. */ - PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_compute_root( - root, leaf, idx_leaf, 0, sig, PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_TREE_HEIGHT, - pub_seed, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_TREE_HEIGHT * PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_N; + compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, + &ctx, tree_addr); + sig += SPX_TREE_HEIGHT * SPX_N; /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_TREE_HEIGHT; + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; } - PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_destroy_hash_function(&hash_state_seeded); + // cleanup + free_hash_function(&ctx); + /* Check if the root node equals the root node in the public key. */ - if (memcmp(root, pub_root, PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_N) != 0) { + if (memcmp(root, pub_root, SPX_N) != 0) { return -1; } @@ -312,15 +244,14 @@ int PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_crypto_sign_verify( /** * Returns an array containing the signature followed by the message. */ -int PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk) { size_t siglen; - PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_crypto_sign_signature( - sm, &siglen, m, mlen, sk); + crypto_sign_signature(sm, &siglen, m, mlen, sk); - memmove(sm + PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_BYTES, m, mlen); + memmove(sm + SPX_BYTES, m, mlen); *smlen = siglen + mlen; return 0; @@ -329,28 +260,27 @@ int PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_crypto_sign( /** * Verifies a given signature-message pair under a given public key. */ -int PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk) { +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk) { /* The API caller does not necessarily know what size a signature should be - but SPHINCS+ signatures are always exactly PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_BYTES. */ - if (smlen < PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_BYTES) { + but SPHINCS+ signatures are always exactly SPX_BYTES. */ + if (smlen < SPX_BYTES) { memset(m, 0, smlen); *mlen = 0; return -1; } - *mlen = smlen - PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_BYTES; + *mlen = smlen - SPX_BYTES; - if (PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_crypto_sign_verify( - sm, PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_BYTES, sm + PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_BYTES, *mlen, pk)) { + if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { memset(m, 0, smlen); *mlen = 0; return -1; } /* If verification was successful, move the message to the right place. */ - memmove(m, sm + PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_BYTES, *mlen); + memmove(m, sm + SPX_BYTES, *mlen); return 0; } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/thash.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/thash.h index d4f268e673..8687ccfb4d 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/thash.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/thash.h @@ -1,28 +1,13 @@ -#ifndef PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_THASH_H -#define PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_THASH_H +#ifndef SPX_THASH_H +#define SPX_THASH_H -#include "hash_state.h" +#include "context.h" +#include "params.h" #include -void PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); +#define thash SPX_NAMESPACE(thash) +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/thash_haraka_robust.c b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/thash_haraka_robust.c index a8b64059ca..109502cbc2 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/thash_haraka_robust.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/thash_haraka_robust.c @@ -2,93 +2,44 @@ #include #include "address.h" -#include "hash_state.h" #include "params.h" #include "thash.h" +#include "utils.h" #include "haraka.h" /** - * Takes an array of inblocks concatenated arrays of PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_N bytes. + * Takes an array of inblocks concatenated arrays of SPX_N bytes. */ -static void PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_thash( - unsigned char *out, unsigned char *buf, - const unsigned char *in, unsigned int inblocks, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char *bitmask = buf + PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_ADDR_BYTES; +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]) { + PQCLEAN_VLA(uint8_t, buf, SPX_ADDR_BYTES + inblocks * SPX_N); + PQCLEAN_VLA(uint8_t, bitmask, inblocks * SPX_N); unsigned char outbuf[32]; unsigned char buf_tmp[64]; unsigned int i; - (void)pub_seed; /* Suppress an 'unused parameter' warning. */ - if (inblocks == 1) { /* F function */ - /* Since PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_N may be smaller than 32, we need a temporary buffer. */ + /* Since SPX_N may be smaller than 32, we need a temporary buffer. */ memset(buf_tmp, 0, 64); - PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_addr_to_bytes(buf_tmp, addr); + memcpy(buf_tmp, addr, 32); - PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_haraka256(outbuf, buf_tmp, hash_state_seeded); - for (i = 0; i < inblocks * PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_N; i++) { - buf_tmp[PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_ADDR_BYTES + i] = in[i] ^ outbuf[i]; + haraka256(outbuf, buf_tmp, ctx); + for (i = 0; i < inblocks * SPX_N; i++) { + buf_tmp[SPX_ADDR_BYTES + i] = in[i] ^ outbuf[i]; } - PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_haraka512(outbuf, buf_tmp, hash_state_seeded); - memcpy(out, outbuf, PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_N); + haraka512(outbuf, buf_tmp, ctx); + memcpy(out, outbuf, SPX_N); } else { /* All other tweakable hashes*/ - PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_addr_to_bytes(buf, addr); - PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_haraka_S( - bitmask, inblocks * PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_N, buf, PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_ADDR_BYTES, hash_state_seeded); + memcpy(buf, addr, 32); + haraka_S(bitmask, inblocks * SPX_N, buf, SPX_ADDR_BYTES, ctx); - for (i = 0; i < inblocks * PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_N; i++) { - buf[PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_ADDR_BYTES + i] = in[i] ^ bitmask[i]; + for (i = 0; i < inblocks * SPX_N; i++) { + buf[SPX_ADDR_BYTES + i] = in[i] ^ bitmask[i]; } - PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_haraka_S( - out, PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_N, buf, PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_N, hash_state_seeded); + haraka_S(out, SPX_N, buf, SPX_ADDR_BYTES + inblocks * SPX_N, ctx); } } - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_ADDR_BYTES + 1 * PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_N]; - PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_thash( - out, buf, in, 1, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_ADDR_BYTES + 2 * PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_N]; - PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_thash( - out, buf, in, 2, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_ADDR_BYTES + PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_WOTS_LEN * PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_N]; - PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_thash( - out, buf, in, PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_WOTS_LEN, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_ADDR_BYTES + PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_FORS_TREES * PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_N]; - PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_thash( - out, buf, in, PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_FORS_TREES, pub_seed, addr, hash_state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/utils.c b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/utils.c index ab94abd51e..177b541fb9 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/utils.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/utils.c @@ -1,34 +1,41 @@ -#include #include +#include "utils.h" + #include "address.h" #include "hash.h" -#include "hash_state.h" #include "params.h" #include "thash.h" -#include "utils.h" /** * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. */ -void PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in) { +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in) { + int i; /* Iterate over out in decreasing order, for big-endianness. */ - for (size_t i = outlen; i > 0; i--) { - out[i - 1] = in & 0xff; + for (i = (signed int)outlen - 1; i >= 0; i--) { + out[i] = in & 0xff; in = in >> 8; } } +void u32_to_bytes(unsigned char *out, uint32_t in) { + out[0] = (unsigned char)(in >> 24); + out[1] = (unsigned char)(in >> 16); + out[2] = (unsigned char)(in >> 8); + out[3] = (unsigned char)in; +} + /** * Converts the inlen bytes in 'in' from big-endian byte order to an integer. */ -unsigned long long PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_bytes_to_ull( - const unsigned char *in, size_t inlen) { +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { unsigned long long retval = 0; + unsigned int i; - for (size_t i = 0; i < inlen; i++) { + for (i = 0; i < inlen; i++) { retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); } return retval; @@ -38,94 +45,80 @@ unsigned long long PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_bytes_to_ull( * Computes a root node given a leaf and an auth path. * Expects address to be complete other than the tree_height and tree_index. */ -void PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]) { uint32_t i; - unsigned char buffer[2 * PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_N]; + unsigned char buffer[2 * SPX_N]; /* If leaf_idx is odd (last bit = 1), current path element is a right child and auth_path has to go left. Otherwise it is the other way around. */ if (leaf_idx & 1) { - memcpy(buffer + PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_N, leaf, PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_N); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_N); + memcpy(buffer + SPX_N, leaf, SPX_N); + memcpy(buffer, auth_path, SPX_N); } else { - memcpy(buffer, leaf, PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_N); - memcpy(buffer + PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_N, auth_path, PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_N); + memcpy(buffer, leaf, SPX_N); + memcpy(buffer + SPX_N, auth_path, SPX_N); } - auth_path += PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_N; + auth_path += SPX_N; for (i = 0; i < tree_height - 1; i++) { leaf_idx >>= 1; idx_offset >>= 1; /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_set_tree_height(addr, i + 1); - PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_set_tree_index( - addr, leaf_idx + idx_offset); + set_tree_height(addr, i + 1); + set_tree_index(addr, leaf_idx + idx_offset); /* Pick the right or left neighbor, depending on parity of the node. */ if (leaf_idx & 1) { - PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_thash_2( - buffer + PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_N, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_N); + thash(buffer + SPX_N, buffer, 2, ctx, addr); + memcpy(buffer, auth_path, SPX_N); } else { - PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_thash_2( - buffer, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer + PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_N, auth_path, PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_N); + thash(buffer, buffer, 2, ctx, addr); + memcpy(buffer + SPX_N, auth_path, SPX_N); } - auth_path += PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_N; + auth_path += SPX_N; } /* The last iteration is exceptional; we do not copy an auth_path node. */ leaf_idx >>= 1; idx_offset >>= 1; - PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_set_tree_height(addr, tree_height); - PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_set_tree_index( - addr, leaf_idx + idx_offset); - PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_thash_2( - root, buffer, pub_seed, addr, hash_state_seeded); + set_tree_height(addr, tree_height); + set_tree_index(addr, leaf_idx + idx_offset); + thash(root, buffer, 2, ctx, addr); } /** * For a given leaf index, computes the authentication path and the resulting * root node using Merkle's TreeHash algorithm. * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_ADDR_TYPE_FORSTREE). + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). * Applies the offset idx_offset to indices before building addresses, so that * it is possible to continue counting indices across trees. */ -static void PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_treehash( - unsigned char *root, unsigned char *auth_path, - unsigned char *stack, unsigned int *heights, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - +void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx * /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]) { + PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); + PQCLEAN_VLA(unsigned int, heights, tree_height + 1); unsigned int offset = 0; uint32_t idx; uint32_t tree_idx; for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { /* Add the next leaf node to the stack. */ - gen_leaf(stack + offset * PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_N, - sk_seed, pub_seed, idx + idx_offset, tree_addr, - hash_state_seeded); + gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); offset++; heights[offset - 1] = 0; /* If this is a node we need for the auth path.. */ if ((leaf_idx ^ 0x1) == idx) { - memcpy(auth_path, stack + (offset - 1)*PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_N, PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_N); + memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); } /* While the top-most nodes are of equal height.. */ @@ -134,66 +127,22 @@ static void PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_treehash( tree_idx = (idx >> (heights[offset - 1] + 1)); /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_set_tree_height( - tree_addr, heights[offset - 1] + 1); - PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_set_tree_index( - tree_addr, tree_idx + (idx_offset >> (heights[offset - 1] + 1))); + set_tree_height(tree_addr, heights[offset - 1] + 1); + set_tree_index(tree_addr, + tree_idx + (idx_offset >> (heights[offset - 1] + 1))); /* Hash the top-most nodes from the stack together. */ - PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_thash_2( - stack + (offset - 2)*PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_N, stack + (offset - 2)*PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_N, - pub_seed, tree_addr, hash_state_seeded); + thash(stack + (offset - 2)*SPX_N, + stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); offset--; /* Note that the top-most node is now one layer higher. */ heights[offset - 1]++; /* If this is a node we need for the auth path.. */ if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_path + heights[offset - 1]*PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_N, - stack + (offset - 1)*PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_N, PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_N); + memcpy(auth_path + heights[offset - 1]*SPX_N, + stack + (offset - 1)*SPX_N, SPX_N); } } } - memcpy(root, stack, PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_N); -} - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_FORS_HEIGHT + 1)*PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_N]; - unsigned int heights[PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_FORS_HEIGHT + 1]; - - PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_FORS_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_TREE_HEIGHT + 1)*PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_N]; - unsigned int heights[PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_TREE_HEIGHT + 1]; - - PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_TREE_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); + memcpy(root, stack, SPX_N); } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/utils.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/utils.h index cd37ac8c2e..64f5d5a53a 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/utils.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/utils.h @@ -1,64 +1,58 @@ -#ifndef PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_UTILS_H -#define PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_UTILS_H +#ifndef SPX_UTILS_H +#define SPX_UTILS_H -#include "hash_state.h" -#include "params.h" -#include #include +#include "compat.h" +#include "context.h" +#include "params.h" + + +/* To support MSVC use alloca() instead of VLAs. See #20. */ + + /** * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. */ -void PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in); +#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in); +#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) +void u32_to_bytes(unsigned char *out, uint32_t in); /** * Converts the inlen bytes in 'in' from big-endian byte order to an integer. */ -unsigned long long PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_bytes_to_ull( - const unsigned char *in, size_t inlen); +#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); /** * Computes a root node given a leaf and an auth path. * Expects address to be complete other than the tree_height and tree_index. */ -void PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); +#define compute_root SPX_NAMESPACE(compute_root) +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]); /** * For a given leaf index, computes the authentication path and the resulting * root node using Merkle's TreeHash algorithm. * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_ADDR_TYPE_FORSTREE). + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). * Applies the offset idx_offset to indices before building addresses, so that * it is possible to continue counting indices across trees. */ -void PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); +#define treehash SPX_NAMESPACE(treehash) +void treehash(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx *ctx /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]); -void PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/utilsx1.c b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/utilsx1.c new file mode 100644 index 0000000000..fccb69b35d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/utilsx1.c @@ -0,0 +1,100 @@ +#include + +#include "utilsx1.h" + +#include "address.h" +#include "params.h" +#include "thash.h" +#include "utils.h" + +/* + * Generate the entire Merkle tree, computing the authentication path for + * leaf_idx, and the resulting root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) + * + * This expects tree_addr to be initialized to the addr structures for the + * Merkle tree nodes + * + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + * + * This works by using the standard Merkle tree building algorithm, + */ +void treehashx1(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, + uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* Where to write the leaves */, + const spx_ctx * /* ctx */, + uint32_t idx, void *info), + uint32_t tree_addr[8], + void *info) { + /* This is where we keep the intermediate nodes */ + PQCLEAN_VLA(uint8_t, stack, tree_height * SPX_N); + + uint32_t idx; + uint32_t max_idx = (uint32_t)((1 << tree_height) - 1); + for (idx = 0;; idx++) { + unsigned char current[2 * SPX_N]; /* Current logical node is at */ + /* index[SPX_N]. We do this to minimize the number of copies */ + /* needed during a thash */ + gen_leaf( ¤t[SPX_N], ctx, idx + idx_offset, + info ); + + /* Now combine the freshly generated right node with previously */ + /* generated left ones */ + uint32_t internal_idx_offset = idx_offset; + uint32_t internal_idx = idx; + uint32_t internal_leaf = leaf_idx; + uint32_t h; /* The height we are in the Merkle tree */ + for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { + + /* Check if we hit the top of the tree */ + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[SPX_N], SPX_N ); + return; + } + + /* + * Check if the node we have is a part of the + * authentication path; if it is, write it out + */ + if ((internal_idx ^ internal_leaf) == 0x01) { + memcpy( &auth_path[ h * SPX_N ], + ¤t[SPX_N], + SPX_N ); + } + + /* + * Check if we're at a left child; if so, stop going up the stack + * Exception: if we've reached the end of the tree, keep on going + * (so we combine the last 4 nodes into the one root node in two + * more iterations) + */ + if ((internal_idx & 1) == 0 && idx < max_idx) { + break; + } + + /* Ok, we're at a right node */ + /* Now combine the left and right logical nodes together */ + + /* Set the address of the node we're creating. */ + internal_idx_offset >>= 1; + set_tree_height(tree_addr, h + 1); + set_tree_index(tree_addr, internal_idx / 2 + internal_idx_offset ); + + unsigned char *left = &stack[h * SPX_N]; + memcpy( ¤t[0], left, SPX_N ); + thash( ¤t[1 * SPX_N], + ¤t[0 * SPX_N], + 2, ctx, tree_addr); + } + + /* We've hit a left child; save the current for when we get the */ + /* corresponding right right */ + memcpy( &stack[h * SPX_N], ¤t[SPX_N], SPX_N); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/utilsx1.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/utilsx1.h new file mode 100644 index 0000000000..e911d17d53 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/utilsx1.h @@ -0,0 +1,27 @@ +#ifndef SPX_UTILSX4_H +#define SPX_UTILSX4_H + +#include + +#include "context.h" +#include "params.h" + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +#define treehashx1 SPX_NAMESPACE(treehashx1) +void treehashx1(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* Where to write the leaf */, + const spx_ctx * /* ctx */, + uint32_t addr_idx, void *info), + uint32_t tree_addrx4[8], void *info); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/wots.c b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/wots.c index 52e861a490..249717aaa8 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/wots.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/wots.c @@ -1,32 +1,20 @@ #include #include +#include "wots.h" +#include "wotsx1.h" + #include "address.h" #include "hash.h" -#include "hash_state.h" #include "params.h" #include "thash.h" #include "utils.h" -#include "wots.h" +#include "utilsx1.h" // TODO clarify address expectations, and make them more uniform. // TODO i.e. do we expect types to be set already? // TODO and do we expect modifications or copies? -/** - * Computes the starting value for a chain, i.e. the secret key. - * Expects the address to be complete up to the chain address. - */ -static void wots_gen_sk(unsigned char *sk, const unsigned char *sk_seed, - uint32_t wots_addr[8], - const hash_state *hash_state_seeded) { - /* Make sure that the hash address is actually zeroed. */ - PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_set_hash_addr(wots_addr, 0); - - /* Generate sk element. */ - PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_prf_addr(sk, sk_seed, wots_addr, hash_state_seeded); -} - /** * Computes the chaining function. * out and in have to be n-byte arrays. @@ -36,18 +24,16 @@ static void wots_gen_sk(unsigned char *sk, const unsigned char *sk_seed, */ static void gen_chain(unsigned char *out, const unsigned char *in, unsigned int start, unsigned int steps, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { + const spx_ctx *ctx, uint32_t addr[8]) { uint32_t i; /* Initialize out with the value at position 'start'. */ - memcpy(out, in, PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_N); + memcpy(out, in, SPX_N); /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_WOTS_W; i++) { - PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_set_hash_addr(addr, i); - PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_thash_1( - out, out, pub_seed, addr, hash_state_seeded); + for (i = start; i < (start + steps) && i < SPX_WOTS_W; i++) { + set_hash_addr(addr, i); + thash(out, out, 1, ctx, addr); } } @@ -56,13 +42,13 @@ static void gen_chain(unsigned char *out, const unsigned char *in, * Interprets an array of bytes as integers in base w. * This only works when log_w is a divisor of 8. */ -static void base_w(unsigned int *output, const size_t out_len, +static void base_w(unsigned int *output, const int out_len, const unsigned char *input) { - size_t in = 0; - size_t out = 0; + int in = 0; + int out = 0; unsigned char total = 0; - unsigned int bits = 0; - size_t consumed; + int bits = 0; + int consumed; for (consumed = 0; consumed < out_len; consumed++) { if (bits == 0) { @@ -70,8 +56,8 @@ static void base_w(unsigned int *output, const size_t out_len, in++; bits += 8; } - bits -= PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_WOTS_LOGW; - output[out] = (unsigned int)((total >> bits) & (PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_WOTS_W - 1)); + bits -= SPX_WOTS_LOGW; + output[out] = (total >> bits) & (SPX_WOTS_W - 1); out++; } } @@ -80,67 +66,25 @@ static void base_w(unsigned int *output, const size_t out_len, static void wots_checksum(unsigned int *csum_base_w, const unsigned int *msg_base_w) { unsigned int csum = 0; - unsigned char csum_bytes[(PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_WOTS_LEN2 * PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_WOTS_LOGW + 7) / 8]; + unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; unsigned int i; /* Compute checksum. */ - for (i = 0; i < PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_WOTS_LEN1; i++) { - csum += PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_WOTS_W - 1 - msg_base_w[i]; + for (i = 0; i < SPX_WOTS_LEN1; i++) { + csum += SPX_WOTS_W - 1 - msg_base_w[i]; } /* Convert checksum to base_w. */ /* Make sure expected empty zero bits are the least significant bits. */ - csum = csum << (8 - ((PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_WOTS_LEN2 * PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_WOTS_LOGW) % 8)); - PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_ull_to_bytes( - csum_bytes, sizeof(csum_bytes), csum); - base_w(csum_base_w, PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_WOTS_LEN2, csum_bytes); + csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); + ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); + base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); } /* Takes a message and derives the matching chain lengths. */ -static void chain_lengths(unsigned int *lengths, const unsigned char *msg) { - base_w(lengths, PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_WOTS_LEN1, msg); - wots_checksum(lengths + PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_WOTS_LEN1, lengths); -} - -/** - * WOTS key generation. Takes a 32 byte sk_seed, expands it to WOTS private key - * elements and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_wots_gen_pk( - unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - uint32_t i; - - for (i = 0; i < PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_WOTS_LEN; i++) { - PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_set_chain_addr(addr, i); - wots_gen_sk(pk + i * PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_N, sk_seed, addr, hash_state_seeded); - gen_chain(pk + i * PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_N, pk + i * PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_N, - 0, PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_WOTS_W - 1, pub_seed, addr, hash_state_seeded); - } -} - -/** - * Takes a n-byte message and the 32-byte sk_see to compute a signature 'sig'. - */ -void PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_wots_sign( - unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *hash_state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_WOTS_LEN; i++) { - PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_set_chain_addr(addr, i); - wots_gen_sk(sig + i * PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_N, sk_seed, addr, hash_state_seeded); - gen_chain(sig + i * PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_N, sig + i * PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_N, 0, lengths[i], pub_seed, addr, hash_state_seeded); - } +void chain_lengths(unsigned int *lengths, const unsigned char *msg) { + base_w(lengths, SPX_WOTS_LEN1, msg); + wots_checksum(lengths + SPX_WOTS_LEN1, lengths); } /** @@ -148,20 +92,17 @@ void PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_wots_sign( * * Writes the computed public key to 'pk'. */ -void PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_wots_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_WOTS_LEN]; +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]) { + unsigned int lengths[SPX_WOTS_LEN]; uint32_t i; chain_lengths(lengths, msg); - for (i = 0; i < PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_WOTS_LEN; i++) { - PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_set_chain_addr(addr, i); - gen_chain(pk + i * PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_N, sig + i * PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_N, - lengths[i], PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_WOTS_W - 1 - lengths[i], pub_seed, addr, - hash_state_seeded); + for (i = 0; i < SPX_WOTS_LEN; i++) { + set_chain_addr(addr, i); + gen_chain(pk + i * SPX_N, sig + i * SPX_N, + lengths[i], SPX_WOTS_W - 1 - lengths[i], ctx, addr); } } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/wots.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/wots.h index d1c38c8fc6..4e7692eeef 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/wots.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/wots.h @@ -1,41 +1,25 @@ -#ifndef PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_WOTS_H -#define PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_WOTS_H +#ifndef SPX_WOTS_H +#define SPX_WOTS_H -#include "hash_state.h" -#include "params.h" #include -/** - * WOTS key generation. Takes a 32 byte seed for the private key, expands it to - * a full WOTS private key and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_wots_gen_pk( - unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -/** - * Takes a n-byte message and the 32-byte seed for the private key to compute a - * signature that is placed at 'sig'. - */ -void PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_wots_sign( - unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *hash_state_seeded); +#include "context.h" +#include "params.h" /** * Takes a WOTS signature and an n-byte message, computes a WOTS public key. * * Writes the computed public key to 'pk'. */ -void PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_wots_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); +#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]); + +/* + * Compute the chain lengths needed for a given message hash + */ +#define chain_lengths SPX_NAMESPACE(chain_lengths) +void chain_lengths(unsigned int *lengths, const unsigned char *msg); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/wotsx1.c b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/wotsx1.c new file mode 100644 index 0000000000..3adec78dfb --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/wotsx1.c @@ -0,0 +1,76 @@ +#include +#include + +#include "wots.h" +#include "wotsx1.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "thash.h" +#include "utils.h" + +/* + * This generates a WOTS public key + * It also generates the WOTS signature if leaf_info indicates + * that we're signing with this WOTS key + */ +void wots_gen_leafx1(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info) { + struct leaf_info_x1 *info = v_info; + uint32_t *leaf_addr = info->leaf_addr; + uint32_t *pk_addr = info->pk_addr; + unsigned int i, k; + unsigned char pk_buffer[ SPX_WOTS_BYTES ]; + unsigned char *buffer; + uint32_t wots_k_mask; + + if (leaf_idx == info->wots_sign_leaf) { + /* We're traversing the leaf that's signing; generate the WOTS */ + /* signature */ + wots_k_mask = 0; + } else { + /* Nope, we're just generating pk's; turn off the signature logic */ + wots_k_mask = (uint32_t)~0; + } + + set_keypair_addr( leaf_addr, leaf_idx ); + set_keypair_addr( pk_addr, leaf_idx ); + + for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { + uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k to */ + /* the step if we're generating a signature, ~0 if we're not */ + + /* Start with the secret seed */ + set_chain_addr(leaf_addr, i); + set_hash_addr(leaf_addr, 0); + set_type(leaf_addr, SPX_ADDR_TYPE_WOTSPRF); + + prf_addr(buffer, ctx, leaf_addr); + + set_type(leaf_addr, SPX_ADDR_TYPE_WOTS); + + /* Iterate down the WOTS chain */ + for (k = 0;; k++) { + /* Check if this is the value that needs to be saved as a */ + /* part of the WOTS signature */ + if (k == wots_k) { + memcpy( info->wots_sig + i * SPX_N, buffer, SPX_N ); + } + + /* Check if we hit the top of the chain */ + if (k == SPX_WOTS_W - 1) { + break; + } + + /* Iterate one step on the chain */ + set_hash_addr(leaf_addr, k); + + thash(buffer, buffer, 1, ctx, leaf_addr); + } + } + + /* Do the final thash to generate the public keys */ + thash(dest, pk_buffer, SPX_WOTS_LEN, ctx, pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/wotsx1.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/wotsx1.h new file mode 100644 index 0000000000..e617929f96 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/wotsx1.h @@ -0,0 +1,39 @@ +#ifndef WOTSX1_H_ +#define WOTSX1_H_ + +#include + +#include "context.h" +#include "params.h" + +/* + * This is here to provide an interface to the internal wots_gen_leafx1 + * routine. While this routine is not referenced in the package outside of + * wots.c, it is called from the stand-alone benchmark code to characterize + * the performance + */ +struct leaf_info_x1 { + unsigned char *wots_sig; + uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ + uint32_t *wots_steps; + uint32_t leaf_addr[8]; + uint32_t pk_addr[8]; +}; + +/* Macro to set the leaf_info to something 'benign', that is, it would */ +/* run with the same time as it does during the real signing process */ +/* Used only by the benchmark code */ +#define INITIALIZE_LEAF_INFO_X1(info, addr, step_buffer) { \ + (info).wots_sig = 0; \ + (info).wots_sign_leaf = ~0; \ + (info).wots_steps = step_buffer; \ + memcpy( &(info).leaf_addr[0], (addr), 32 ); \ + memcpy( &(info).pk_addr[0], (addr), 32 ); \ + } + +#define wots_gen_leafx1 SPX_NAMESPACE(wots_gen_leafx1) +void wots_gen_leafx1(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info); + +#endif /* WOTSX1_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/address.c b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/address.c index 74862370b6..b956e9cb29 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/address.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/address.c @@ -1,78 +1,91 @@ #include +#include #include "address.h" #include "params.h" #include "utils.h" -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]) { - int i; - - for (i = 0; i < 8; i++) { - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_ull_to_bytes( - bytes + i * 4, 4, addr[i]); - } -} - -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_set_layer_addr( - uint32_t addr[8], uint32_t layer) { - addr[0] = layer; +/* + * Specify which level of Merkle tree (the "layer") we're working on + */ +void set_layer_addr(uint32_t addr[8], uint32_t layer) { + ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; } -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_set_tree_addr( - uint32_t addr[8], uint64_t tree) { - addr[1] = 0; - addr[2] = (uint32_t) (tree >> 32); - addr[3] = (uint32_t) tree; +/* + * Specify which Merkle tree within the level (the "tree address") we're working on + */ +void set_tree_addr(uint32_t addr[8], uint64_t tree) { + ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); } -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_set_type( - uint32_t addr[8], uint32_t type) { - addr[4] = type; +/* + * Specify the reason we'll use this address structure for, that is, what + * hash will we compute with it. This is used so that unrelated types of + * hashes don't accidentally get the same address structure. The type will be + * one of the SPX_ADDR_TYPE constants + */ +void set_type(uint32_t addr[8], uint32_t type) { + ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; } -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; +/* + * Copy the layer and tree fields of the address structure. This is used + * when we're doing multiple types of hashes within the same Merkle tree + */ +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); } /* These functions are used for OTS addresses. */ -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_set_keypair_addr( - uint32_t addr[8], uint32_t keypair) { - addr[5] = keypair; +/* + * Specify which Merkle leaf we're working on; that is, which OTS keypair + * we're talking about. + */ +void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { + ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; } -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; - out[5] = in[5]; +/* + * Copy the layer, tree and keypair fields of the address structure. This is + * used when we're doing multiple things within the same OTS keypair + */ +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); + ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; } -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_set_chain_addr( - uint32_t addr[8], uint32_t chain) { - addr[6] = chain; +/* + * Specify which Merkle chain within the OTS we're working with + * (the chain address) + */ +void set_chain_addr(uint32_t addr[8], uint32_t chain) { + ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; } -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_set_hash_addr( - uint32_t addr[8], uint32_t hash) { - addr[7] = hash; +/* + * Specify where in the Merkle chain we are +* (the hash address) + */ +void set_hash_addr(uint32_t addr[8], uint32_t hash) { + ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; } /* These functions are used for all hash tree addresses (including FORS). */ -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_set_tree_height( - uint32_t addr[8], uint32_t tree_height) { - addr[6] = tree_height; +/* + * Specify the height of the node in the Merkle/FORS tree we are in + * (the tree height) + */ +void set_tree_height(uint32_t addr[8], uint32_t tree_height) { + ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; } -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_set_tree_index( - uint32_t addr[8], uint32_t tree_index) { - addr[7] = tree_index; +/* + * Specify the distance from the left edge of the node in the Merkle/FORS tree + * (the tree index) + */ +void set_tree_index(uint32_t addr[8], uint32_t tree_index) { + u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/address.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/address.h index 9df219cd6c..24a84eb40c 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/address.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/address.h @@ -1,50 +1,52 @@ -#ifndef PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_ADDRESS_H -#define PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_ADDRESS_H +#ifndef SPX_ADDRESS_H +#define SPX_ADDRESS_H #include -#define PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_ADDR_TYPE_WOTS 0 -#define PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_ADDR_TYPE_WOTSPK 1 -#define PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_ADDR_TYPE_HASHTREE 2 -#define PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_ADDR_TYPE_FORSTREE 3 -#define PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_ADDR_TYPE_FORSPK 4 +#include "params.h" -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]); +/* The hash types that are passed to set_type */ +#define SPX_ADDR_TYPE_WOTS 0 +#define SPX_ADDR_TYPE_WOTSPK 1 +#define SPX_ADDR_TYPE_HASHTREE 2 +#define SPX_ADDR_TYPE_FORSTREE 3 +#define SPX_ADDR_TYPE_FORSPK 4 +#define SPX_ADDR_TYPE_WOTSPRF 5 +#define SPX_ADDR_TYPE_FORSPRF 6 -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_set_layer_addr( - uint32_t addr[8], uint32_t layer); +#define set_layer_addr SPX_NAMESPACE(set_layer_addr) +void set_layer_addr(uint32_t addr[8], uint32_t layer); -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_set_tree_addr( - uint32_t addr[8], uint64_t tree); +#define set_tree_addr SPX_NAMESPACE(set_tree_addr) +void set_tree_addr(uint32_t addr[8], uint64_t tree); -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_set_type( - uint32_t addr[8], uint32_t type); +#define set_type SPX_NAMESPACE(set_type) +void set_type(uint32_t addr[8], uint32_t type); /* Copies the layer and tree part of one address into the other */ -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]); +#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); /* These functions are used for WOTS and FORS addresses. */ -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_set_keypair_addr( - uint32_t addr[8], uint32_t keypair); +#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) +void set_keypair_addr(uint32_t addr[8], uint32_t keypair); -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_set_chain_addr( - uint32_t addr[8], uint32_t chain); +#define set_chain_addr SPX_NAMESPACE(set_chain_addr) +void set_chain_addr(uint32_t addr[8], uint32_t chain); -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_set_hash_addr( - uint32_t addr[8], uint32_t hash); +#define set_hash_addr SPX_NAMESPACE(set_hash_addr) +void set_hash_addr(uint32_t addr[8], uint32_t hash); -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]); +#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); /* These functions are used for all hash tree addresses (including FORS). */ -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_set_tree_height( - uint32_t addr[8], uint32_t tree_height); +#define set_tree_height SPX_NAMESPACE(set_tree_height) +void set_tree_height(uint32_t addr[8], uint32_t tree_height); -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_set_tree_index( - uint32_t addr[8], uint32_t tree_index); +#define set_tree_index SPX_NAMESPACE(set_tree_index) +void set_tree_index(uint32_t addr[8], uint32_t tree_index); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/api.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/api.h index 4c8ef76543..099750a11c 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/api.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/api.h @@ -4,15 +4,13 @@ #include #include - - -#define PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_CRYPTO_ALGNAME "SPHINCS+" +#define PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_CRYPTO_ALGNAME "SPHINCS+-haraka-256s-simple" #define PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_CRYPTO_SECRETKEYBYTES 128 #define PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_CRYPTO_PUBLICKEYBYTES 64 -#define PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_CRYPTO_BYTES 29792 -#define PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_CRYPTO_SEEDBYTES 96 +#define PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_CRYPTO_BYTES 29792 +#define PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_CRYPTO_SEEDBYTES 96 /* * Returns the length of a secret key, in bytes @@ -39,43 +37,41 @@ size_t PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_crypto_sign_seedbytes(void); * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] * Format pk: [root || PUB_SEED] */ -int PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed); +int PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); /* * Generates a SPHINCS+ key pair. * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] * Format pk: [root || PUB_SEED] */ -int PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk); +int PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); /** * Returns an array containing a detached signature. */ -int PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk); +int PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); /** * Verifies a detached signature and message under a given public key. */ -int PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk); +int PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, + const uint8_t *pk); /** * Returns an array containing the signature followed by the message. */ -int PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk); +int PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); /** * Verifies a given signature-message pair under a given public key. */ -int PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk); - +int PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/context.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/context.h new file mode 100644 index 0000000000..f03446b9cb --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/context.h @@ -0,0 +1,22 @@ +#ifndef SPX_CONTEXT_H +#define SPX_CONTEXT_H + +#include + +#include "immintrin.h" +#include "params.h" + +typedef struct { + uint8_t pub_seed[SPX_N]; + uint8_t sk_seed[SPX_N]; + + __m128i rc[40]; +} spx_ctx; + +#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) +void initialize_hash_function(spx_ctx *ctx); + +#define free_hash_function SPX_NAMESPACE(free_hash_function) +void free_hash_function(spx_ctx *ctx); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/context_haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/context_haraka.c new file mode 100644 index 0000000000..f1cd7e3664 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/context_haraka.c @@ -0,0 +1,11 @@ +#include "context.h" +#include "haraka.h" + +void initialize_hash_function(spx_ctx *ctx) { + tweak_constants(ctx); +} + +// we don't support heap-based haraka right now +void free_hash_function(spx_ctx *ctx) { + (void)ctx; // suppress unused variable warnings +} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/fors.c b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/fors.c index 0793f16136..f1b0639cfc 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/fors.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/fors.c @@ -2,8 +2,9 @@ #include #include -#include "address.h" #include "fors.h" + +#include "address.h" #include "hash.h" #include "hashx4.h" #include "thash.h" @@ -11,19 +12,24 @@ #include "utils.h" #include "utilsx4.h" +static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + prf_addr(sk, ctx, fors_leaf_addr); +} + static void fors_gen_skx4(unsigned char *sk0, unsigned char *sk1, unsigned char *sk2, - unsigned char *sk3, const unsigned char *sk_seed, - uint32_t fors_leaf_addrx4[4 * 8], - const hash_state *state_seeded) { - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_prf_addrx4(sk0, sk1, sk2, sk3, sk_seed, fors_leaf_addrx4, state_seeded); + unsigned char *sk3, const spx_ctx *ctx, + uint32_t fors_leaf_addrx4[4 * 8]) { + prf_addrx4(sk0, sk1, sk2, sk3, + ctx, fors_leaf_addrx4); } static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, - const unsigned char *pub_seed, - uint32_t fors_leaf_addr[8], const hash_state *state_seeded) { - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_thash_1(leaf, sk, pub_seed, fors_leaf_addr, state_seeded); + const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + thash(leaf, sk, 1, ctx, fors_leaf_addr); } static void fors_sk_to_leafx4(unsigned char *leaf0, @@ -34,57 +40,64 @@ static void fors_sk_to_leafx4(unsigned char *leaf0, const unsigned char *sk1, const unsigned char *sk2, const unsigned char *sk3, - const unsigned char *pub_seed, - uint32_t fors_leaf_addrx4[4 * 8], - const hash_state *state_seeded) { - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_thashx4_1(leaf0, leaf1, leaf2, leaf3, - sk0, sk1, sk2, sk3, pub_seed, fors_leaf_addrx4, state_seeded); + const spx_ctx *ctx, + uint32_t fors_leaf_addrx4[4 * 8]) { + thashx4(leaf0, leaf1, leaf2, leaf3, + sk0, sk1, sk2, sk3, + 1, ctx, fors_leaf_addrx4); } -static void fors_gen_leafx4(unsigned char *leaf0, - unsigned char *leaf1, - unsigned char *leaf2, - unsigned char *leaf3, - const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx0, - uint32_t addr_idx1, - uint32_t addr_idx2, - uint32_t addr_idx3, - const uint32_t fors_tree_addr[8], - const hash_state *state_seeded) { - uint32_t fors_leaf_addrx4[4 * 8] = {0}; +struct fors_gen_leaf_info { + uint32_t leaf_addrx[4 * 8]; +}; + +static void fors_gen_leafx4(unsigned char *leaf, + const spx_ctx *ctx, + uint32_t addr_idx, void *info) { + struct fors_gen_leaf_info *fors_info = info; + uint32_t *fors_leaf_addrx4 = fors_info->leaf_addrx; unsigned int j; - /* Only copy the parts that must be kept in fors_leaf_addrx4. */ + /* Only set the parts that the caller doesn't set */ for (j = 0; j < 4; j++) { - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_copy_keypair_addr(fors_leaf_addrx4 + j * 8, fors_tree_addr); - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_set_type(fors_leaf_addrx4 + j * 8, PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_ADDR_TYPE_FORSTREE); + set_tree_index(fors_leaf_addrx4 + j * 8, addr_idx + j); + set_type(fors_leaf_addrx4 + j * 8, SPX_ADDR_TYPE_FORSPRF); } - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_set_tree_index(fors_leaf_addrx4 + 0 * 8, addr_idx0); - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_set_tree_index(fors_leaf_addrx4 + 1 * 8, addr_idx1); - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_set_tree_index(fors_leaf_addrx4 + 2 * 8, addr_idx2); - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_set_tree_index(fors_leaf_addrx4 + 3 * 8, addr_idx3); + fors_gen_skx4(leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + leaf + 2 * SPX_N, + leaf + 3 * SPX_N, + ctx, fors_leaf_addrx4); + + for (j = 0; j < 4; j++) { + set_type(fors_leaf_addrx4 + j * 8, SPX_ADDR_TYPE_FORSTREE); + } - fors_gen_skx4(leaf0, leaf1, leaf2, leaf3, sk_seed, fors_leaf_addrx4, state_seeded); - fors_sk_to_leafx4(leaf0, leaf1, leaf2, leaf3, - leaf0, leaf1, leaf2, leaf3, pub_seed, fors_leaf_addrx4, state_seeded); + fors_sk_to_leafx4(leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + leaf + 2 * SPX_N, + leaf + 3 * SPX_N, + leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + leaf + 2 * SPX_N, + leaf + 3 * SPX_N, + ctx, fors_leaf_addrx4); } /** - * Interprets m as PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_FORS_HEIGHT-bit unsigned integers. - * Assumes m contains at least PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_FORS_TREES bits. - * Assumes indices has space for PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_FORS_TREES integers. + * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + * Assumes indices has space for SPX_FORS_TREES integers. */ static void message_to_indices(uint32_t *indices, const unsigned char *m) { unsigned int i, j; unsigned int offset = 0; - for (i = 0; i < PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_FORS_TREES; i++) { + for (i = 0; i < SPX_FORS_TREES; i++) { indices[i] = 0; - for (j = 0; j < PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_FORS_HEIGHT; j++) { - indices[i] ^= (((uint32_t)m[offset >> 3] >> (offset & 0x7)) & 0x1) << j; + for (j = 0; j < SPX_FORS_HEIGHT; j++) { + indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); offset++; } } @@ -92,68 +105,53 @@ static void message_to_indices(uint32_t *indices, const unsigned char *m) { /** * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_FORS_TREES bits. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. */ -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *state_seeded) { - /* Round up to multiple of 4 to prevent out-of-bounds for x4 parallelism */ - uint32_t indices[(PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_FORS_TREES + 3) & ~3] = {0}; - unsigned char roots[((PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_FORS_TREES + 3) & ~3) * PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N]; - /* Sign to a buffer, since we may not have a nice multiple of 4 and would - otherwise overrun the signature. */ - unsigned char sigbufx4[4 * PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N * (1 + PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_FORS_HEIGHT)]; - uint32_t fors_tree_addrx4[4 * 8] = {0}; +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + uint32_t fors_tree_addr[4 * 8] = {0}; + struct fors_gen_leaf_info fors_info = {0}; + uint32_t *fors_leaf_addr = fors_info.leaf_addrx; uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset[4] = {0}; - unsigned int i, j; + uint32_t idx_offset; + unsigned int i; - for (j = 0; j < 4; j++) { - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_copy_keypair_addr(fors_tree_addrx4 + j * 8, fors_addr); - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_set_type(fors_tree_addrx4 + j * 8, PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_ADDR_TYPE_FORSTREE); + for (i = 0; i < 4; i++) { + copy_keypair_addr(fors_tree_addr + 8 * i, fors_addr); + set_type(fors_tree_addr + 8 * i, SPX_ADDR_TYPE_FORSTREE); + copy_keypair_addr(fors_leaf_addr + 8 * i, fors_addr); } - - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_copy_keypair_addr(fors_pk_addr, fors_addr); - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_set_type(fors_pk_addr, PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_ADDR_TYPE_FORSPK); + copy_keypair_addr(fors_pk_addr, fors_addr); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); message_to_indices(indices, m); - for (i = 0; i < ((PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_FORS_TREES + 3) & ~0x3); i += 4) { - for (j = 0; j < 4; j++) { - if (i + j < PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_FORS_TREES) { - idx_offset[j] = (i + j) * (1 << PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_FORS_HEIGHT); + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_set_tree_height(fors_tree_addrx4 + j * 8, 0); - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_set_tree_index(fors_tree_addrx4 + j * 8, - indices[i + j] + idx_offset[j]); - } - } + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); - /* Include the secret key part that produces the selected leaf nodes. */ - fors_gen_skx4(sigbufx4 + 0 * PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N, - sigbufx4 + 1 * PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N, - sigbufx4 + 2 * PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N, - sigbufx4 + 3 * PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N, - sk_seed, fors_tree_addrx4, state_seeded); - - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_treehashx4_FORS_HEIGHT(roots + i * PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N, sigbufx4 + 4 * PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N, sk_seed, pub_seed, - &indices[i], idx_offset, fors_gen_leafx4, fors_tree_addrx4, - state_seeded); - - for (j = 0; j < 4; j++) { - if (i + j < PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_FORS_TREES) { - memcpy(sig, sigbufx4 + j * PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N, PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N); - memcpy(sig + PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N, - sigbufx4 + 4 * PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N + j * PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N * PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_FORS_HEIGHT, - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N * PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_FORS_HEIGHT); - sig += PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N * (1 + PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_FORS_HEIGHT); - } - } + /* Include the secret key part that produces the selected leaf node. */ + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); + fors_gen_sk(sig, ctx, fors_tree_addr); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + sig += SPX_N; + + /* Compute the authentication path for this leaf node. */ + treehashx4(roots + i * SPX_N, sig, ctx, + indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx4, + fors_tree_addr, &fors_info); + + sig += SPX_N * SPX_FORS_HEIGHT; } /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_thash_FORS_TREES(pk, roots, pub_seed, fors_pk_addr, state_seeded); + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); } /** @@ -161,46 +159,44 @@ void PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_fors_sign(unsigned char *sig, unsigne * This can be used for verification by comparing to a known public key, or to * subsequently verify a signature on the derived public key. The latter is the * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_FORS_TREES bits. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. */ -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, - const uint32_t fors_addr[8], - const hash_state *state_seeded) { - uint32_t indices[PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_FORS_TREES]; - unsigned char roots[PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_FORS_TREES * PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N]; - unsigned char leaf[PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N]; +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + unsigned char leaf[SPX_N]; uint32_t fors_tree_addr[8] = {0}; uint32_t fors_pk_addr[8] = {0}; uint32_t idx_offset; unsigned int i; - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_copy_keypair_addr(fors_tree_addr, fors_addr); - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_copy_keypair_addr(fors_pk_addr, fors_addr); + copy_keypair_addr(fors_tree_addr, fors_addr); + copy_keypair_addr(fors_pk_addr, fors_addr); - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_set_type(fors_tree_addr, PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_set_type(fors_pk_addr, PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_ADDR_TYPE_FORSPK); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); message_to_indices(indices, m); - for (i = 0; i < PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_FORS_TREES; i++) { - idx_offset = i * (1 << PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_FORS_HEIGHT); + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_set_tree_height(fors_tree_addr, 0); - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_set_tree_index(fors_tree_addr, indices[i] + idx_offset); + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); /* Derive the leaf from the included secret key part. */ - fors_sk_to_leaf(leaf, sig, pub_seed, fors_tree_addr, state_seeded); - sig += PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N; + fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); + sig += SPX_N; /* Derive the corresponding root node of this tree. */ - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_compute_root(roots + i * PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N, leaf, indices[i], idx_offset, - sig, PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_FORS_HEIGHT, pub_seed, fors_tree_addr, - state_seeded); - sig += PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N * PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_FORS_HEIGHT; + compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, + sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); + sig += SPX_N * SPX_FORS_HEIGHT; } /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_thash_FORS_TREES(pk, roots, pub_seed, fors_pk_addr, state_seeded); + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/fors.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/fors.h index 7c58e29743..509140a178 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/fors.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/fors.h @@ -1,32 +1,32 @@ -#ifndef PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_FORS_H -#define PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_FORS_H +#ifndef SPX_FORS_H +#define SPX_FORS_H #include -#include "hash_state.h" +#include "context.h" #include "params.h" /** * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_FORS_TREES bits. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. */ -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_fors_sign( - unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *hash_state_seeded); +#define fors_sign SPX_NAMESPACE(fors_sign) +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); /** * Derives the FORS public key from a signature. * This can be used for verification by comparing to a known public key, or to * subsequently verify a signature on the derived public key. The latter is the * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_FORS_TREES bits. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. */ -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_fors_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, const uint32_t fors_addr[8], - const hash_state *hash_state_seeded); +#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/haraka.c index 403f074c48..b414b691d7 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/haraka.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/haraka.c @@ -8,10 +8,12 @@ Plain C implementation of the Haraka256 and Haraka512 permutations. #include #include "haraka.h" +#include "harakax4.h" +#include "utils.h" #define HARAKAS_RATE 32 -#define u64 uint64_t +#define u64 unsigned long #define u128 __m128i #define LOAD(src) _mm_loadu_si128((u128 *)(src)) @@ -20,7 +22,7 @@ Plain C implementation of the Haraka256 and Haraka512 permutations. #define XOR128(a, b) _mm_xor_si128(a, b) #define AES2(s0, s1, rci) \ - (s0) = _mm_aesenc_si128(s0, *(rci)); \ + s0 = _mm_aesenc_si128(s0, *(rci)); \ (s1) = _mm_aesenc_si128(s1, *((rci) + 1)); \ (s0) = _mm_aesenc_si128(s0, *((rci) + 2)); \ (s1) = _mm_aesenc_si128(s1, *((rci) + 3)); @@ -32,7 +34,7 @@ Plain C implementation of the Haraka256 and Haraka512 permutations. AES2((s3)[0], (s3)[1], rci); #define AES4(s0, s1, s2, s3, rci) \ - (s0) = _mm_aesenc_si128(s0, *(rci)); \ + s0 = _mm_aesenc_si128(s0, *(rci)); \ (s1) = _mm_aesenc_si128(s1, *((rci) + 1)); \ (s2) = _mm_aesenc_si128(s2, *((rci) + 2)); \ (s3) = _mm_aesenc_si128(s3, *((rci) + 3)); \ @@ -68,17 +70,17 @@ Plain C implementation of the Haraka256 and Haraka512 permutations. _mm_storeu_si128((u128 *)((out) + 16), \ _mm_castpd_si128(_mm_shuffle_pd(_mm_castsi128_pd(s2), _mm_castsi128_pd(s3), 0))); -static void load_haraka_constants(u128 rc[40]) { - rc[ 0] = _mm_set_epi32((int)0x0684704c, (int)0xe620c00a, (int)0xb2c5fef0, (int)0x75817b9d); - rc[ 1] = _mm_set_epi32((int)0x8b66b4e1, (int)0x88f3a06b, (int)0x640f6ba4, (int)0x2f08f717); - rc[ 2] = _mm_set_epi32((int)0x3402de2d, (int)0x53f28498, (int)0xcf029d60, (int)0x9f029114); - rc[ 3] = _mm_set_epi32((int)0x0ed6eae6, (int)0x2e7b4f08, (int)0xbbf3bcaf, (int)0xfd5b4f79); - rc[ 4] = _mm_set_epi32((int)0xcbcfb0cb, (int)0x4872448b, (int)0x79eecd1c, (int)0xbe397044); - rc[ 5] = _mm_set_epi32((int)0x7eeacdee, (int)0x6e9032b7, (int)0x8d5335ed, (int)0x2b8a057b); - rc[ 6] = _mm_set_epi32((int)0x67c28f43, (int)0x5e2e7cd0, (int)0xe2412761, (int)0xda4fef1b); - rc[ 7] = _mm_set_epi32((int)0x2924d9b0, (int)0xafcacc07, (int)0x675ffde2, (int)0x1fc70b3b); - rc[ 8] = _mm_set_epi32((int)0xab4d63f1, (int)0xe6867fe9, (int)0xecdb8fca, (int)0xb9d465ee); - rc[ 9] = _mm_set_epi32((int)0x1c30bf84, (int)0xd4b7cd64, (int)0x5b2a404f, (int)0xad037e33); +static void load_haraka_constants(u128 *rc) { + rc[0] = _mm_set_epi32((int)0x0684704c, (int)0xe620c00a, (int)0xb2c5fef0, (int)0x75817b9d); + rc[1] = _mm_set_epi32((int)0x8b66b4e1, (int)0x88f3a06b, (int)0x640f6ba4, (int)0x2f08f717); + rc[2] = _mm_set_epi32((int)0x3402de2d, (int)0x53f28498, (int)0xcf029d60, (int)0x9f029114); + rc[3] = _mm_set_epi32((int)0x0ed6eae6, (int)0x2e7b4f08, (int)0xbbf3bcaf, (int)0xfd5b4f79); + rc[4] = _mm_set_epi32((int)0xcbcfb0cb, (int)0x4872448b, (int)0x79eecd1c, (int)0xbe397044); + rc[5] = _mm_set_epi32((int)0x7eeacdee, (int)0x6e9032b7, (int)0x8d5335ed, (int)0x2b8a057b); + rc[6] = _mm_set_epi32((int)0x67c28f43, (int)0x5e2e7cd0, (int)0xe2412761, (int)0xda4fef1b); + rc[7] = _mm_set_epi32((int)0x2924d9b0, (int)0xafcacc07, (int)0x675ffde2, (int)0x1fc70b3b); + rc[8] = _mm_set_epi32((int)0xab4d63f1, (int)0xe6867fe9, (int)0xecdb8fca, (int)0xb9d465ee); + rc[9] = _mm_set_epi32((int)0x1c30bf84, (int)0xd4b7cd64, (int)0x5b2a404f, (int)0xad037e33); rc[10] = _mm_set_epi32((int)0xb2cc0bb9, (int)0x941723bf, (int)0x69028b2e, (int)0x8df69800); rc[11] = _mm_set_epi32((int)0xfa0478a6, (int)0xde6f5572, (int)0x4aaa9ec8, (int)0x5c9d2d8a); rc[12] = _mm_set_epi32((int)0xdfb49f2b, (int)0x6b772a12, (int)0x0efa4f2e, (int)0x29129fd4); @@ -111,77 +113,65 @@ static void load_haraka_constants(u128 rc[40]) { rc[39] = _mm_set_epi32((int)0x756acc03, (int)0x02288288, (int)0x4ad6bdfd, (int)0xe9c59da1); } -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_tweak_constants( - harakactx *state, - const unsigned char *pk_seed, const unsigned char *sk_seed, - unsigned long long seed_length) { +void tweak_constants(spx_ctx *ctx) { int i; unsigned char buf[40 * 16]; /* Use the standard constants to generate tweaked ones. */ - load_haraka_constants(state->rc); - - /* Constants for sk.seed */ - if (sk_seed != NULL) { - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_haraka_S(buf, 40 * 16, sk_seed, seed_length, state); - /* Tweak constants with the pub_seed */ - for (i = 0; i < 40; i++) { - state->rc_sseed[i] = LOAD(buf + i * 16); - } - } + load_haraka_constants(ctx->rc); /* Constants for pk.seed */ - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_haraka_S(buf, 40 * 16, pk_seed, seed_length, state); + haraka_S(buf, 40 * 16, ctx->pub_seed, SPX_N, ctx); /* Tweak constants with the pub_seed */ for (i = 0; i < 40; i++) { - state->rc[i] = LOAD(buf + i * 16); + ctx->rc[i] = LOAD(buf + i * 16); } } -static void haraka_S_absorb(unsigned char *s, +static void haraka_S_absorb(unsigned char *s, unsigned int r, const unsigned char *m, unsigned long long mlen, - unsigned char p, - const harakactx *state) { + unsigned char p, const spx_ctx *ctx) { unsigned long long i; - unsigned char t[HARAKAS_RATE]; + PQCLEAN_VLA(unsigned char, t, r); - while (mlen >= HARAKAS_RATE) { + while (mlen >= r) { // XOR block to state STORE(s, XOR128(LOAD(s), LOAD(m))); STORE(s + 16, XOR128(LOAD(s + 16), LOAD(m + 16))); - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_haraka512_perm(s, s, state); - mlen -= HARAKAS_RATE; - m += HARAKAS_RATE; + haraka512_perm(s, s, ctx); + mlen -= r; + m += r; } - for (i = 0; i < HARAKAS_RATE; ++i) { + for (i = 0; i < r; ++i) { t[i] = 0; } for (i = 0; i < mlen; ++i) { t[i] = m[i]; } t[i] = p; - t[HARAKAS_RATE - 1] |= 128; + t[r - 1] |= 128; STORE(s, XOR128(LOAD(s), LOAD(t))); STORE(s + 16, XOR128(LOAD(s + 16), LOAD(t + 16))); } static void haraka_S_absorb4x(unsigned char *s, + unsigned int r, const unsigned char *m0, const unsigned char *m1, const unsigned char *m2, const unsigned char *m3, unsigned long long int mlen, unsigned char p, - const harakactx *state) { + const spx_ctx *ctx) { unsigned long long i; - unsigned char t0[HARAKAS_RATE]; - unsigned char t1[HARAKAS_RATE]; - unsigned char t2[HARAKAS_RATE]; - unsigned char t3[HARAKAS_RATE]; + PQCLEAN_VLA(unsigned char, t0, r); + PQCLEAN_VLA(unsigned char, t1, r); + PQCLEAN_VLA(unsigned char, t2, r); + PQCLEAN_VLA(unsigned char, t3, r); - while (mlen >= HARAKAS_RATE) { + while (mlen >= r) { // XOR block to state STORE(s, XOR128(LOAD(s), LOAD(m0))); STORE(s + 16, XOR128(LOAD(s + 16), LOAD(m0 + 16))); @@ -192,15 +182,15 @@ static void haraka_S_absorb4x(unsigned char *s, STORE(s + 192, XOR128(LOAD(s + 192), LOAD(m3))); STORE(s + 208, XOR128(LOAD(s + 208), LOAD(m3 + 16))); - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_haraka512_perm_x4(s, s, state); - mlen -= HARAKAS_RATE; - m0 += HARAKAS_RATE; - m1 += HARAKAS_RATE; - m2 += HARAKAS_RATE; - m3 += HARAKAS_RATE; + haraka512_perm_x4(s, s, ctx); + mlen -= r; + m0 += r; + m1 += r; + m2 += r; + m3 += r; } - for (i = 0; i < HARAKAS_RATE; ++i) { + for (i = 0; i < r; ++i) { t0[i] = 0; t1[i] = 0; t2[i] = 0; @@ -218,10 +208,10 @@ static void haraka_S_absorb4x(unsigned char *s, t2[i] = p; t3[i] = p; - t0[HARAKAS_RATE - 1] |= 128; - t1[HARAKAS_RATE - 1] |= 128; - t2[HARAKAS_RATE - 1] |= 128; - t3[HARAKAS_RATE - 1] |= 128; + t0[r - 1] |= 128; + t1[r - 1] |= 128; + t2[r - 1] |= 128; + t3[r - 1] |= 128; STORE(s, XOR128(LOAD(s), LOAD(t0))); STORE(s + 16, XOR128(LOAD(s + 16), LOAD(t0 + 16))); @@ -234,9 +224,10 @@ static void haraka_S_absorb4x(unsigned char *s, } static void haraka_S_squeezeblocks(unsigned char *h, unsigned long long nblocks, - unsigned char *s, unsigned int r, const harakactx *state) { + unsigned char *s, unsigned int r, + const spx_ctx *ctx) { while (nblocks > 0) { - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_haraka512_perm(s, s, state); + haraka512_perm(s, s, ctx); STORE(h, LOAD(s)); STORE(h + 16, LOAD(s + 16)); h += r; @@ -251,9 +242,9 @@ static void haraka_S_squeezeblocks4x(unsigned char *h0, unsigned long long nblocks, unsigned char *s, unsigned int r, - const harakactx *state) { + const spx_ctx *ctx) { while (nblocks > 0) { - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_haraka512_perm_x4(s, s, state); + haraka512_perm_x4(s, s, ctx); STORE(h0, LOAD(s)); STORE(h0 + 16, LOAD(s + 16)); STORE(h1, LOAD(s + 64)); @@ -270,7 +261,7 @@ static void haraka_S_squeezeblocks4x(unsigned char *h0, } } -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_haraka_S_inc_init(uint8_t *s_inc) { +void haraka_S_inc_init(uint8_t *s_inc) { size_t i; for (i = 0; i < 64; i++) { @@ -279,7 +270,8 @@ void PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_haraka_S_inc_init(uint8_t *s_inc) { s_inc[64] = 0; } -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, const harakactx *state) { +void haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, + const spx_ctx *ctx) { size_t i; /* Recall that s_inc[64] is the non-absorbed bytes xored into the state */ @@ -293,16 +285,16 @@ void PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_haraka_S_inc_absorb(uint8_t *s_inc, c m += HARAKAS_RATE - s_inc[64]; s_inc[64] = 0; - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_haraka512_perm(s_inc, s_inc, state); + haraka512_perm(s_inc, s_inc, ctx); } for (i = 0; i < mlen; i++) { s_inc[s_inc[64] + i] ^= m[i]; } - s_inc[64] = (uint8_t)(s_inc[64] + mlen); + s_inc[64] += (uint8_t)mlen; } -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_haraka_S_inc_finalize(uint8_t *s_inc) { +void haraka_S_inc_finalize(uint8_t *s_inc) { /* After haraka_S_inc_absorb, we are guaranteed that s_inc[64] < HARAKAS_RATE, so we can always use one more byte for p in the current state. */ s_inc[s_inc[64]] ^= 0x1F; @@ -310,22 +302,23 @@ void PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_haraka_S_inc_finalize(uint8_t *s_inc) s_inc[64] = 0; } -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, const harakactx *state) { +void haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, + const spx_ctx *ctx) { size_t i; /* First consume any bytes we still have sitting around */ for (i = 0; i < outlen && i < s_inc[64]; i++) { /* There are s_inc[64] bytes left, so r - s_inc[64] is the first available byte. We consume from there, i.e., up to r. */ - out[i] = (uint8_t)s_inc[(HARAKAS_RATE - s_inc[64] + (uint8_t)i)]; + out[i] = (uint8_t)s_inc[(HARAKAS_RATE - s_inc[64] + i)]; } out += i; outlen -= i; - s_inc[64] = (uint8_t)(s_inc[64] - i); + s_inc[64] -= (uint8_t)i; /* Then squeeze the remaining necessary blocks */ while (outlen > 0) { - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_haraka512_perm(s_inc, s_inc, state); + haraka512_perm(s_inc, s_inc, ctx); for (i = 0; i < outlen && i < HARAKAS_RATE; i++) { out[i] = s_inc[i]; @@ -336,8 +329,9 @@ void PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_haraka_S_inc_squeeze(uint8_t *out, si } } -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_haraka_S(unsigned char *out, unsigned long long outlen, - const unsigned char *in, unsigned long long inlen, const harakactx *state) { +void haraka_S(unsigned char *out, unsigned long long outlen, + const unsigned char *in, unsigned long long inlen, + const spx_ctx *ctx) { unsigned long long i; unsigned char s[64]; unsigned char d[32]; @@ -345,30 +339,30 @@ void PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_haraka_S(unsigned char *out, unsigned for (i = 0; i < 64; i++) { s[i] = 0; } - haraka_S_absorb(s, in, inlen, 0x1F, state); + haraka_S_absorb(s, HARAKAS_RATE, in, inlen, 0x1F, ctx); - haraka_S_squeezeblocks(out, outlen / HARAKAS_RATE, s, HARAKAS_RATE, state); + haraka_S_squeezeblocks(out, outlen / HARAKAS_RATE, s, HARAKAS_RATE, ctx); out += (outlen / HARAKAS_RATE) * HARAKAS_RATE; if (outlen % HARAKAS_RATE) { - haraka_S_squeezeblocks(d, 1, s, HARAKAS_RATE, state); + haraka_S_squeezeblocks(d, 1, s, HARAKAS_RATE, ctx); for (i = 0; i < outlen % HARAKAS_RATE; i++) { out[i] = d[i]; } } } -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_haraka_Sx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned long long outlen, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - unsigned long long inlen, - const harakactx *state) { +void haraka_Sx4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned long long outlen, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + unsigned long long inlen, + const spx_ctx *ctx) { unsigned long long i; unsigned char s[64 * 4]; unsigned char d0[32]; @@ -379,16 +373,17 @@ void PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_haraka_Sx4(unsigned char *out0, for (i = 0; i < 64 * 4; i++) { s[i] = 0; } - haraka_S_absorb4x(s, in0, in1, in2, in3, inlen, 0x1F, state); + haraka_S_absorb4x(s, HARAKAS_RATE, in0, in1, in2, in3, inlen, 0x1F, ctx); - haraka_S_squeezeblocks4x(out0, out1, out2, out3, outlen / HARAKAS_RATE, s, HARAKAS_RATE, state); + haraka_S_squeezeblocks4x(out0, out1, out2, out3, outlen / HARAKAS_RATE, s, + HARAKAS_RATE, ctx); out0 += (outlen / HARAKAS_RATE) * HARAKAS_RATE; out1 += (outlen / HARAKAS_RATE) * HARAKAS_RATE; out2 += (outlen / HARAKAS_RATE) * HARAKAS_RATE; out3 += (outlen / HARAKAS_RATE) * HARAKAS_RATE; if (outlen % HARAKAS_RATE) { - haraka_S_squeezeblocks4x(d0, d1, d2, d3, 1, s, HARAKAS_RATE, state); + haraka_S_squeezeblocks4x(d0, d1, d2, d3, 1, s, HARAKAS_RATE, ctx); for (i = 0; i < outlen % HARAKAS_RATE; i++) { out0[i] = d0[i]; out1[i] = d1[i]; @@ -398,7 +393,8 @@ void PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_haraka_Sx4(unsigned char *out0, } } -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_haraka512_perm(unsigned char *out, const unsigned char *in, const harakactx *state) { +void haraka512_perm(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx) { u128 s[4], tmp; s[0] = LOAD(in); @@ -406,19 +402,19 @@ void PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_haraka512_perm(unsigned char *out, co s[2] = LOAD(in + 32); s[3] = LOAD(in + 48); - AES4(s[0], s[1], s[2], s[3], state->rc); + AES4(s[0], s[1], s[2], s[3], ctx->rc); MIX4(s[0], s[1], s[2], s[3]); - AES4(s[0], s[1], s[2], s[3], state->rc + 8); + AES4(s[0], s[1], s[2], s[3], ctx->rc + 8); MIX4(s[0], s[1], s[2], s[3]); - AES4(s[0], s[1], s[2], s[3], state->rc + 16); + AES4(s[0], s[1], s[2], s[3], ctx->rc + 16); MIX4(s[0], s[1], s[2], s[3]); - AES4(s[0], s[1], s[2], s[3], state->rc + 24); + AES4(s[0], s[1], s[2], s[3], ctx->rc + 24); MIX4(s[0], s[1], s[2], s[3]); - AES4(s[0], s[1], s[2], s[3], state->rc + 32); + AES4(s[0], s[1], s[2], s[3], ctx->rc + 32); MIX4(s[0], s[1], s[2], s[3]); STORE(out, s[0]); @@ -427,7 +423,8 @@ void PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_haraka512_perm(unsigned char *out, co STORE(out + 48, s[3]); } -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_haraka512_perm_x4(unsigned char *out, const unsigned char *in, const harakactx *state) { +void haraka512_perm_x4(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx) { u128 s[4][4], tmp; s[0][0] = LOAD(in); @@ -447,31 +444,31 @@ void PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_haraka512_perm_x4(unsigned char *out, s[3][2] = LOAD(in + 224); s[3][3] = LOAD(in + 240); - AES4_4x(s[0], s[1], s[2], s[3], state->rc); + AES4_4x(s[0], s[1], s[2], s[3], ctx->rc); MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - AES4_4x(s[0], s[1], s[2], s[3], state->rc + 8); + AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 8); MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - AES4_4x(s[0], s[1], s[2], s[3], state->rc + 16); + AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 16); MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - AES4_4x(s[0], s[1], s[2], s[3], state->rc + 24); + AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 24); MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - AES4_4x(s[0], s[1], s[2], s[3], state->rc + 32); + AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 32); MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); @@ -495,7 +492,8 @@ void PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_haraka512_perm_x4(unsigned char *out, STORE(out + 240, s[3][3]); } -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_haraka512(unsigned char *out, const unsigned char *in, const harakactx *state) { +void haraka512(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx) { u128 s[4], tmp; s[0] = LOAD(in); @@ -503,19 +501,19 @@ void PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_haraka512(unsigned char *out, const u s[2] = LOAD(in + 32); s[3] = LOAD(in + 48); - AES4(s[0], s[1], s[2], s[3], state->rc); + AES4(s[0], s[1], s[2], s[3], ctx->rc); MIX4(s[0], s[1], s[2], s[3]); - AES4(s[0], s[1], s[2], s[3], state->rc + 8); + AES4(s[0], s[1], s[2], s[3], ctx->rc + 8); MIX4(s[0], s[1], s[2], s[3]); - AES4(s[0], s[1], s[2], s[3], state->rc + 16); + AES4(s[0], s[1], s[2], s[3], ctx->rc + 16); MIX4(s[0], s[1], s[2], s[3]); - AES4(s[0], s[1], s[2], s[3], state->rc + 24); + AES4(s[0], s[1], s[2], s[3], ctx->rc + 24); MIX4(s[0], s[1], s[2], s[3]); - AES4(s[0], s[1], s[2], s[3], state->rc + 32); + AES4(s[0], s[1], s[2], s[3], ctx->rc + 32); MIX4(s[0], s[1], s[2], s[3]); s[0] = XOR128(s[0], LOAD(in)); @@ -527,7 +525,8 @@ void PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_haraka512(unsigned char *out, const u TRUNCSTORE(out, s[0], s[1], s[2], s[3]); } -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_haraka512x4(unsigned char *out, const unsigned char *in, const harakactx *state) { +void haraka512x4(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx) { u128 s[4][4], tmp; s[0][0] = LOAD(in); @@ -547,31 +546,31 @@ void PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_haraka512x4(unsigned char *out, const s[3][2] = LOAD(in + 224); s[3][3] = LOAD(in + 240); - AES4_4x(s[0], s[1], s[2], s[3], state->rc); + AES4_4x(s[0], s[1], s[2], s[3], ctx->rc); MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - AES4_4x(s[0], s[1], s[2], s[3], state->rc + 8); + AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 8); MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - AES4_4x(s[0], s[1], s[2], s[3], state->rc + 16); + AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 16); MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - AES4_4x(s[0], s[1], s[2], s[3], state->rc + 24); + AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 24); MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - AES4_4x(s[0], s[1], s[2], s[3], state->rc + 32); + AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 32); MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); @@ -600,25 +599,26 @@ void PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_haraka512x4(unsigned char *out, const TRUNCSTORE((out + 96), s[3][0], s[3][1], s[3][2], s[3][3]); } -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_haraka256(unsigned char *out, const unsigned char *in, const harakactx *state) { +void haraka256(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx) { u128 s[2], tmp; s[0] = LOAD(in); s[1] = LOAD(in + 16); - AES2(s[0], s[1], state->rc); + AES2(s[0], s[1], ctx->rc); MIX2(s[0], s[1]); - AES2(s[0], s[1], state->rc + 4); + AES2(s[0], s[1], ctx->rc + 4); MIX2(s[0], s[1]); - AES2(s[0], s[1], state->rc + 8); + AES2(s[0], s[1], ctx->rc + 8); MIX2(s[0], s[1]); - AES2(s[0], s[1], state->rc + 12); + AES2(s[0], s[1], ctx->rc + 12); MIX2(s[0], s[1]); - AES2(s[0], s[1], state->rc + 16); + AES2(s[0], s[1], ctx->rc + 16); MIX2(s[0], s[1]); s[0] = XOR128(s[0], LOAD(in)); @@ -628,7 +628,8 @@ void PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_haraka256(unsigned char *out, const u STORE(out + 16, s[1]); } -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_haraka256x4(unsigned char *out, const unsigned char *in, const harakactx *state) { +void haraka256x4(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx) { u128 s[4][2], tmp; s[0][0] = LOAD(in); @@ -641,7 +642,7 @@ void PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_haraka256x4(unsigned char *out, const s[3][1] = LOAD(in + 112); // Round 1 - AES2_4x(s[0], s[1], s[2], s[3], state->rc); + AES2_4x(s[0], s[1], s[2], s[3], ctx->rc); MIX2(s[0][0], s[0][1]); MIX2(s[1][0], s[1][1]); @@ -649,7 +650,7 @@ void PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_haraka256x4(unsigned char *out, const MIX2(s[3][0], s[3][1]); // Round 2 - AES2_4x(s[0], s[1], s[2], s[3], state->rc + 4); + AES2_4x(s[0], s[1], s[2], s[3], ctx->rc + 4); MIX2(s[0][0], s[0][1]); MIX2(s[1][0], s[1][1]); @@ -657,7 +658,7 @@ void PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_haraka256x4(unsigned char *out, const MIX2(s[3][0], s[3][1]); // Round 3 - AES2_4x(s[0], s[1], s[2], s[3], state->rc + 8); + AES2_4x(s[0], s[1], s[2], s[3], ctx->rc + 8); MIX2(s[0][0], s[0][1]); MIX2(s[1][0], s[1][1]); @@ -665,7 +666,7 @@ void PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_haraka256x4(unsigned char *out, const MIX2(s[3][0], s[3][1]); // Round 4 - AES2_4x(s[0], s[1], s[2], s[3], state->rc + 12); + AES2_4x(s[0], s[1], s[2], s[3], ctx->rc + 12); MIX2(s[0][0], s[0][1]); MIX2(s[1][0], s[1][1]); @@ -673,7 +674,7 @@ void PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_haraka256x4(unsigned char *out, const MIX2(s[3][0], s[3][1]); // Round 5 - AES2_4x(s[0], s[1], s[2], s[3], state->rc + 16); + AES2_4x(s[0], s[1], s[2], s[3], ctx->rc + 16); MIX2(s[0][0], s[0][1]); MIX2(s[1][0], s[1][1]); @@ -699,103 +700,3 @@ void PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_haraka256x4(unsigned char *out, const STORE(out + 96, s[3][0]); STORE(out + 112, s[3][1]); } - -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_haraka256_sk(unsigned char *out, const unsigned char *in, const harakactx *state) { - u128 s[2], tmp; - - s[0] = LOAD(in); - s[1] = LOAD(in + 16); - - AES2(s[0], s[1], state->rc_sseed); - MIX2(s[0], s[1]); - - AES2(s[0], s[1], state->rc_sseed + 4); - MIX2(s[0], s[1]); - - AES2(s[0], s[1], state->rc_sseed + 8); - MIX2(s[0], s[1]); - - AES2(s[0], s[1], state->rc_sseed + 12); - MIX2(s[0], s[1]); - - AES2(s[0], s[1], state->rc_sseed + 16); - MIX2(s[0], s[1]); - - s[0] = XOR128(s[0], LOAD(in)); - s[1] = XOR128(s[1], LOAD(in + 16)); - - STORE(out, s[0]); - STORE(out + 16, s[1]); -} - -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_haraka256_skx4(unsigned char *out, const unsigned char *in, const harakactx *state) { - u128 s[4][2], tmp; - - s[0][0] = LOAD(in); - s[0][1] = LOAD(in + 16); - s[1][0] = LOAD(in + 32); - s[1][1] = LOAD(in + 48); - s[2][0] = LOAD(in + 64); - s[2][1] = LOAD(in + 80); - s[3][0] = LOAD(in + 96); - s[3][1] = LOAD(in + 112); - - // Round 1 - AES2_4x(s[0], s[1], s[2], s[3], state->rc_sseed); - - MIX2(s[0][0], s[0][1]); - MIX2(s[1][0], s[1][1]); - MIX2(s[2][0], s[2][1]); - MIX2(s[3][0], s[3][1]); - - // Round 2 - AES2_4x(s[0], s[1], s[2], s[3], state->rc_sseed + 4); - - MIX2(s[0][0], s[0][1]); - MIX2(s[1][0], s[1][1]); - MIX2(s[2][0], s[2][1]); - MIX2(s[3][0], s[3][1]); - - // Round 3 - AES2_4x(s[0], s[1], s[2], s[3], state->rc_sseed + 8); - - MIX2(s[0][0], s[0][1]); - MIX2(s[1][0], s[1][1]); - MIX2(s[2][0], s[2][1]); - MIX2(s[3][0], s[3][1]); - - // Round 4 - AES2_4x(s[0], s[1], s[2], s[3], state->rc_sseed + 12); - - MIX2(s[0][0], s[0][1]); - MIX2(s[1][0], s[1][1]); - MIX2(s[2][0], s[2][1]); - MIX2(s[3][0], s[3][1]); - - // Round 5 - AES2_4x(s[0], s[1], s[2], s[3], state->rc_sseed + 16); - - MIX2(s[0][0], s[0][1]); - MIX2(s[1][0], s[1][1]); - MIX2(s[2][0], s[2][1]); - MIX2(s[3][0], s[3][1]); - - // Feed Forward - s[0][0] = XOR128(s[0][0], LOAD(in)); - s[0][1] = XOR128(s[0][1], LOAD(in + 16)); - s[1][0] = XOR128(s[1][0], LOAD(in + 32)); - s[1][1] = XOR128(s[1][1], LOAD(in + 48)); - s[2][0] = XOR128(s[2][0], LOAD(in + 64)); - s[2][1] = XOR128(s[2][1], LOAD(in + 80)); - s[3][0] = XOR128(s[3][0], LOAD(in + 96)); - s[3][1] = XOR128(s[3][1], LOAD(in + 112)); - - STORE(out, s[0][0]); - STORE(out + 16, s[0][1]); - STORE(out + 32, s[1][0]); - STORE(out + 48, s[1][1]); - STORE(out + 64, s[2][0]); - STORE(out + 80, s[2][1]); - STORE(out + 96, s[3][0]); - STORE(out + 112, s[3][1]); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/haraka.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/haraka.h index 1104295153..737cb6065f 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/haraka.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/haraka.h @@ -1,57 +1,42 @@ -#ifndef PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_HARAKA_H -#define PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_HARAKA_H +#ifndef SPX_HARAKA_H +#define SPX_HARAKA_H -#include -#include -#include - -typedef struct { - __m128i rc[40]; - __m128i rc_sseed[40]; -} harakactx; +#include "context.h" +#include "params.h" /* Tweak constants with seed */ -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_tweak_constants( - harakactx *state, - const unsigned char *pk_seed, const unsigned char *sk_seed, - unsigned long long seed_length); +#define tweak_constants SPX_NAMESPACE(tweak_constants) +void tweak_constants(spx_ctx *ctx); /* Haraka Sponge */ -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_haraka_S_inc_init(uint8_t *s_inc); -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, const harakactx *state); -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_haraka_S_inc_finalize(uint8_t *s_inc); -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, const harakactx *state); -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_haraka_S( - unsigned char *out, unsigned long long outlen, - const unsigned char *in, unsigned long long inlen, const harakactx *state); -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_haraka_Sx4( - unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned long long outlen, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - unsigned long long inlen, - const harakactx *state); - +#define haraka_S_inc_init SPX_NAMESPACE(haraka_S_inc_init) +void haraka_S_inc_init(uint8_t *s_inc); +#define haraka_S_inc_absorb SPX_NAMESPACE(haraka_S_inc_absorb) +void haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, + const spx_ctx *ctx); +#define haraka_S_inc_finalize SPX_NAMESPACE(haraka_S_inc_finalize) +void haraka_S_inc_finalize(uint8_t *s_inc); +#define haraka_S_inc_squeeze SPX_NAMESPACE(haraka_S_inc_squeeze) +void haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, + const spx_ctx *ctx); +#define haraka_S SPX_NAMESPACE(haraka_S) +void haraka_S(unsigned char *out, unsigned long long outlen, + const unsigned char *in, unsigned long long inlen, + const spx_ctx *ctx); /* Applies the 512-bit Haraka permutation to in. */ -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_haraka512_perm(unsigned char *out, const unsigned char *in, const harakactx *state); -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_haraka512_perm_x4(unsigned char *out, const unsigned char *in, const harakactx *state); +#define haraka512_perm SPX_NAMESPACE(haraka512_perm) +void haraka512_perm(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx); /* Implementation of Haraka-512 */ -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_haraka512(unsigned char *out, const unsigned char *in, const harakactx *state); -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_haraka512x4(unsigned char *out, const unsigned char *in, const harakactx *state); +#define haraka512 SPX_NAMESPACE(haraka512) +void haraka512(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx); /* Implementation of Haraka-256 */ -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_haraka256(unsigned char *out, const unsigned char *in, const harakactx *state); -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_haraka256x4(unsigned char *out, const unsigned char *in, const harakactx *state); - -/* Implementation of Haraka-256 using sk.seed constants */ -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_haraka256_sk(unsigned char *out, const unsigned char *in, const harakactx *state); -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_haraka256_skx4(unsigned char *out, const unsigned char *in, const harakactx *state); +#define haraka256 SPX_NAMESPACE(haraka256) +void haraka256(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/haraka_offsets.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/haraka_offsets.h new file mode 100644 index 0000000000..7c062272a0 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/haraka_offsets.h @@ -0,0 +1,21 @@ +#ifndef HARAKA_OFFSETS_H_ +#define HARAKA_OFFSETS_H_ + +/* + * Offsets of various fields in the address structure when we use Haraka as + * the Sphincs+ hash function + */ + +#define SPX_OFFSET_LAYER 3 /* The byte used to specify the Merkle tree layer */ +#define SPX_OFFSET_TREE 8 /* The start of the 8 byte field used to specify the tree */ +#define SPX_OFFSET_TYPE 19 /* The byte used to specify the hash type (reason) */ +#define SPX_OFFSET_KP_ADDR2 22 /* The high byte used to specify the key pair (which one-time signature) */ +#define SPX_OFFSET_KP_ADDR1 23 /* The low byte used to specify the key pair */ +#define SPX_OFFSET_CHAIN_ADDR 27 /* The byte used to specify the chain address (which Winternitz chain) */ +#define SPX_OFFSET_HASH_ADDR 31 /* The byte used to specify the hash address (where in the Winternitz chain) */ +#define SPX_OFFSET_TREE_HGT 27 /* The byte used to specify the height of this node in the FORS or Merkle tree */ +#define SPX_OFFSET_TREE_INDEX 28 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ + +#define SPX_HARAKA 1 + +#endif /* HARAKA_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/harakax4.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/harakax4.h new file mode 100644 index 0000000000..eadc69aa48 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/harakax4.h @@ -0,0 +1,36 @@ +#ifndef SPX_HARAKAX4_H +#define SPX_HARAKAX4_H + +#include "context.h" +#include "params.h" + +/* Haraka Sponge */ +#define haraka_Sx4 SPX_NAMESPACE(haraka_Sx4) +void haraka_Sx4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned long long outlen, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + unsigned long long inlen, + const spx_ctx *ctx); + +/* Applies the 512-bit Haraka permutation x4 to in. */ +#define haraka512_perm_x4 SPX_NAMESPACE(haraka512_perm_x4) +void haraka512_perm_x4(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx); + +/* Implementation of Haraka-512 x4*/ +#define haraka512x4 SPX_NAMESPACE(haraka512x4) +void haraka512x4(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx); + +/* Implementation of Haraka-256 x4 */ +#define haraka256x4 SPX_NAMESPACE(haraka256x4) +void haraka256x4(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/hash.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/hash.h index 6d302e86fe..f7c87d4c3c 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/hash.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/hash.h @@ -1,31 +1,28 @@ -#ifndef PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_HASH_H -#define PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_HASH_H - -#include "hash_state.h" +#ifndef SPX_HASH_H +#define SPX_HASH_H #include #include -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_initialize_hash_function( - hash_state *hash_state_seeded, - const unsigned char *pub_seed, const unsigned char *sk_seed); +#include "context.h" +#include "params.h" + +#define prf_addr SPX_NAMESPACE(prf_addr) +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]); -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_destroy_hash_function(hash_state *hash_state_seeded); +#define gen_message_random SPX_NAMESPACE(gen_message_random) +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded); +#define hash_message SPX_NAMESPACE(hash_message) +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/hash_haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/hash_haraka.c index 54f3bc1ac8..750a67423b 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/hash_haraka.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/hash_haraka.c @@ -2,58 +2,44 @@ #include #include "address.h" -#include "haraka.h" -#include "hash.h" #include "params.h" #include "utils.h" -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_initialize_hash_function( - hash_state *hash_state_seeded, - const unsigned char *pub_seed, const unsigned char *sk_seed) { - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_tweak_constants(hash_state_seeded, pub_seed, sk_seed, PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N); -} - -/* The haraka implementation is stack based and won't be replaced in PQClean/OQS, - so we don't need to do anything */ -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_destroy_hash_function( - hash_state *hash_state_seeded) { // NOLINT(readability-non-const-parameter) - (void)hash_state_seeded; -} +#include "haraka.h" +#include "hash.h" /* - * Computes PRF(key, addr), given a secret key of PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N bytes and an address + * Computes PRF(key, addr), given a secret key of SPX_N bytes and an address */ -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded) { - unsigned char buf[PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_ADDR_BYTES]; - /* Since PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N may be smaller than 32, we need a temporary buffer. */ +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]) { + /* Since SPX_N may be smaller than 32, we need temporary buffers. */ unsigned char outbuf[32]; + unsigned char buf[64] = {0}; - (void)key; /* Suppress an 'unused parameter' warning. */ + memcpy(buf, addr, SPX_ADDR_BYTES); + memcpy(buf + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_addr_to_bytes(buf, addr); - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_haraka256_sk(outbuf, buf, hash_state_seeded); - memcpy(out, outbuf, PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N); + haraka512(outbuf, (const void *)buf, ctx); + memcpy(out, outbuf, SPX_N); } /** * Computes the message-dependent randomness R, using a secret seed and an * optional randomization value as well as the message. */ -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded) { +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { uint8_t s_inc[65]; - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_haraka_S_inc_init(s_inc); - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_haraka_S_inc_absorb(s_inc, sk_prf, PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_haraka_S_inc_absorb(s_inc, optrand, PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_haraka_S_inc_absorb(s_inc, m, mlen, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_haraka_S_inc_finalize(s_inc); - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_haraka_S_inc_squeeze(R, PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N, s_inc, hash_state_seeded); + haraka_S_inc_init(s_inc); + haraka_S_inc_absorb(s_inc, sk_prf, SPX_N, ctx); + haraka_S_inc_absorb(s_inc, optrand, SPX_N, ctx); + haraka_S_inc_absorb(s_inc, m, mlen, ctx); + haraka_S_inc_finalize(s_inc); + haraka_S_inc_squeeze(R, SPX_N, s_inc, ctx); } /** @@ -61,36 +47,35 @@ void PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_gen_message_random( * Outputs the message digest and the index of the leaf. The index is split in * the tree index and the leaf index, for convenient copying to an address. */ -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded) { -#define PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_TREE_BITS (PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_TREE_HEIGHT * (PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_D - 1)) -#define PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_TREE_BYTES ((PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_TREE_BITS + 7) / 8) -#define PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_LEAF_BITS PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_TREE_HEIGHT -#define PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_LEAF_BYTES ((PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_LEAF_BITS + 7) / 8) -#define PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_DGST_BYTES (PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_FORS_MSG_BYTES + PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_TREE_BYTES + PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_LEAF_BYTES) +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { +#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) +#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) +#define SPX_LEAF_BITS SPX_TREE_HEIGHT +#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) +#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) - unsigned char buf[PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_DGST_BYTES]; + unsigned char buf[SPX_DGST_BYTES]; unsigned char *bufp = buf; uint8_t s_inc[65]; - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_haraka_S_inc_init(s_inc); - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_haraka_S_inc_absorb(s_inc, R, PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_haraka_S_inc_absorb(s_inc, pk + PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N, PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_haraka_S_inc_absorb(s_inc, m, mlen, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_haraka_S_inc_finalize(s_inc); - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_haraka_S_inc_squeeze(buf, PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_DGST_BYTES, s_inc, hash_state_seeded); + haraka_S_inc_init(s_inc); + haraka_S_inc_absorb(s_inc, R, SPX_N, ctx); + haraka_S_inc_absorb(s_inc, pk + SPX_N, SPX_N, ctx); // Only absorb root part of pk + haraka_S_inc_absorb(s_inc, m, mlen, ctx); + haraka_S_inc_finalize(s_inc); + haraka_S_inc_squeeze(buf, SPX_DGST_BYTES, s_inc, ctx); + + memcpy(digest, bufp, SPX_FORS_MSG_BYTES); + bufp += SPX_FORS_MSG_BYTES; - memcpy(digest, bufp, PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_FORS_MSG_BYTES); - bufp += PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_FORS_MSG_BYTES; - *tree = PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_bytes_to_ull(bufp, PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_TREE_BYTES); - *tree &= (~(uint64_t)0) >> (64 - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_TREE_BITS); - bufp += PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_TREE_BYTES; + *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); + *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); + bufp += SPX_TREE_BYTES; - *leaf_idx = (uint32_t)PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_bytes_to_ull( - bufp, PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_LEAF_BYTES); - *leaf_idx &= (~(uint32_t)0) >> (32 - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_LEAF_BITS); + *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); + *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/hash_harakax4.c b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/hash_harakax4.c index 34b5042919..cfa5162d79 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/hash_harakax4.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/hash_harakax4.c @@ -2,36 +2,34 @@ #include #include "address.h" -#include "haraka.h" -#include "hash_state.h" +#include "harakax4.h" #include "hashx4.h" #include "params.h" /* * 4-way parallel version of prf_addr; takes 4x as much input and output */ -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_prf_addrx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const unsigned char *key, - const uint32_t addrx4[4 * 8], - const hash_state *state_seeded) { - unsigned char bufx4[4 * PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_ADDR_BYTES]; - /* Since PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N may be smaller than 32, we need a temporary buffer. */ +#define prf_addrx4 SPX_NAMESPACE(prf_addrx4) +void prf_addrx4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const spx_ctx *ctx, + const uint32_t addrx4[4 * 8]) { + unsigned char bufx4[4 * 64] = {0}; + /* Since SPX_N may be smaller than 32, we need temporary buffers. */ unsigned char outbuf[4 * 32]; unsigned int i; - (void)key; /* Suppress an 'unused parameter' warning. */ - for (i = 0; i < 4; i++) { - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_addr_to_bytes(bufx4 + i * PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_ADDR_BYTES, addrx4 + i * 8); + memcpy(bufx4 + i * 64, addrx4 + i * 8, SPX_ADDR_BYTES); + memcpy(bufx4 + i * 64 + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); } - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_haraka256_skx4(outbuf, bufx4, state_seeded); + haraka512x4(outbuf, bufx4, ctx); - memcpy(out0, outbuf, PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N); - memcpy(out1, outbuf + 32, PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N); - memcpy(out2, outbuf + 64, PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N); - memcpy(out3, outbuf + 96, PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N); + memcpy(out0, outbuf, SPX_N); + memcpy(out1, outbuf + 32, SPX_N); + memcpy(out2, outbuf + 64, SPX_N); + memcpy(out3, outbuf + 96, SPX_N); } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/hash_state.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/hash_state.h deleted file mode 100644 index 2d366c0e47..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/hash_state.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_HASH_STATE_H -#define PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_HASH_STATE_H - -/** - * Defines the type of the hash function state. - * - * Don't be fooled into thinking this instance of SPHINCS+ isn't stateless! - * - * From Section 7.2.2 from the SPHINCS+ round-2 specification: - * - * Each of the instances of the tweakable hash function take PK.seed as its - * first input, which is constant for a given key pair – and, thus, across - * a single signature. This leads to a lot of redundant computation. To remedy - * this, we pad PK.seed to the length of a full 64-byte SHA-256 input block. - * Because of the Merkle-DamgÃ¥rd construction that underlies SHA-256, this - * allows for reuse of the intermediate SHA-256 state after the initial call to - * the compression function which improves performance. - * - * We pass this hash state around in functions, because otherwise we need to - * have a global variable. - */ - -#include "haraka.h" -#define hash_state harakactx - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/hashx4.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/hashx4.h index 75b7c304ba..3751a0ebd0 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/hashx4.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/hashx4.h @@ -1,16 +1,17 @@ -#ifndef PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_HASHX4_H -#define PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_HASHX4_H +#ifndef SPX_HASHX4_H +#define SPX_HASHX4_H #include -#include "hash_state.h" +#include "context.h" +#include "params.h" -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_prf_addrx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const unsigned char *key, - const uint32_t addrx4[4 * 8], - const hash_state *state_seeded); +#define prf_addrx4 SPX_NAMESPACE(prf_addrx4) +void prf_addrx4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const spx_ctx *ctx, + const uint32_t addrx4[4 * 8]); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/merkle.c b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/merkle.c new file mode 100644 index 0000000000..f57811c1ac --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/merkle.c @@ -0,0 +1,64 @@ +#include +#include + +#include "merkle.h" + +#include "address.h" +#include "params.h" +#include "utils.h" +#include "utilsx4.h" +#include "wots.h" +#include "wotsx4.h" + +/* + * This generates a Merkle signature (WOTS signature followed by the Merkle + * authentication path). + */ +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf) { + unsigned char *auth_path = sig + SPX_WOTS_BYTES; + uint32_t tree_addrx4[4 * 8] = { 0 }; + int j; + struct leaf_info_x4 info = { 0 }; + unsigned steps[ SPX_WOTS_LEN ]; + + info.wots_sig = sig; + chain_lengths(steps, root); + info.wots_steps = steps; + + for (j = 0; j < 4; j++) { + set_type(&tree_addrx4[8 * j], SPX_ADDR_TYPE_HASHTREE); + set_type(&info.leaf_addr[8 * j], SPX_ADDR_TYPE_WOTS); + set_type(&info.pk_addr[8 * j], SPX_ADDR_TYPE_WOTSPK); + copy_subtree_addr(&tree_addrx4[8 * j], tree_addr); + copy_subtree_addr(&info.leaf_addr[8 * j], wots_addr); + copy_subtree_addr(&info.pk_addr[8 * j], wots_addr); + } + + info.wots_sign_leaf = idx_leaf; + + treehashx4(root, auth_path, ctx, + idx_leaf, 0, + SPX_TREE_HEIGHT, + wots_gen_leafx4, + tree_addrx4, &info); +} + +/* Compute root node of the top-most subtree. */ +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { + /* We do not need the auth path in key generation, but it simplifies the + code to have just one treehash routine that computes both root and path + in one function. */ + unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; + uint32_t top_tree_addr[8] = {0}; + uint32_t wots_addr[8] = {0}; + + set_layer_addr(top_tree_addr, SPX_D - 1); + set_layer_addr(wots_addr, SPX_D - 1); + + merkle_sign(auth_path, root, ctx, + wots_addr, top_tree_addr, + ~0U /* ~0 means "don't bother generating an auth path */ ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/merkle.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/merkle.h new file mode 100644 index 0000000000..769cf2e970 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/merkle.h @@ -0,0 +1,21 @@ +#ifndef MERKLE_H_ +#define MERKLE_H_ + +#include + +#include "context.h" +#include "params.h" + +/* Generate a Merkle signature (WOTS signature followed by the Merkle */ +/* authentication path) */ +#define merkle_sign SPX_NAMESPACE(merkle_sign) +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf); + +/* Compute the root node of the top-most subtree. */ +#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); + +#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/nistapi.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/nistapi.h new file mode 100644 index 0000000000..3cb71afad4 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/nistapi.h @@ -0,0 +1,87 @@ +#ifndef SPX_API_H +#define SPX_API_H + +#include +#include + +#include "params.h" + +#define CRYPTO_ALGNAME "SPHINCS+" + +#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES +#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES +#define CRYPTO_BYTES SPX_BYTES +#define CRYPTO_SEEDBYTES (3*SPX_N) + +/* + * Returns the length of a secret key, in bytes + */ +#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) +size_t crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) +size_t crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) +size_t crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) +size_t crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +#define crypto_sign SPX_NAMESPACE(crypto_sign) +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/params.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/params.h index 5e206f878f..4390aba58b 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/params.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/params.h @@ -1,53 +1,56 @@ -#ifndef PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_PARAMS_H -#define PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_PARAMS_H +#ifndef SPX_PARAMS_H +#define SPX_PARAMS_H + +#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_##s /* Hash output length in bytes. */ -#define PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N 32 +#define SPX_N 32 /* Height of the hypertree. */ -#define PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_FULL_HEIGHT 64 +#define SPX_FULL_HEIGHT 64 /* Number of subtree layer. */ -#define PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_D 8 +#define SPX_D 8 /* FORS tree dimensions. */ -#define PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_FORS_HEIGHT 14 -#define PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_FORS_TREES 22 +#define SPX_FORS_HEIGHT 14 +#define SPX_FORS_TREES 22 /* Winternitz parameter, */ -#define PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_WOTS_W 16 +#define SPX_WOTS_W 16 /* The hash function is defined by linking a different hash.c file, as opposed to setting a #define constant. */ /* For clarity */ -#define PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_ADDR_BYTES 32 +#define SPX_ADDR_BYTES 32 /* WOTS parameters. */ -#define PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_WOTS_LOGW 4 +#define SPX_WOTS_LOGW 4 -#define PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_WOTS_LEN1 (8 * PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N / PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_WOTS_LOGW) +#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) -/* PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#define PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_WOTS_LEN2 3 +/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ +#define SPX_WOTS_LEN2 3 -#define PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_WOTS_LEN (PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_WOTS_LEN1 + PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_WOTS_LEN2) -#define PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_WOTS_BYTES (PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_WOTS_LEN * PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N) -#define PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_WOTS_PK_BYTES PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_WOTS_BYTES +#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) +#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) +#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES /* Subtree size. */ -#define PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_TREE_HEIGHT (PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_FULL_HEIGHT / PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_D) +#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) + +//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT +// #error SPX_D should always divide SPX_FULL_HEIGHT +//#endif /* FORS parameters. */ -#define PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_FORS_MSG_BYTES ((PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_FORS_TREES + 7) / 8) -#define PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_FORS_BYTES ((PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_FORS_HEIGHT + 1) * PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_FORS_TREES * PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N) -#define PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_FORS_PK_BYTES PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N +#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) +#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) +#define SPX_FORS_PK_BYTES SPX_N /* Resulting SPX sizes. */ -#define PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_BYTES (PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N + PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_FORS_BYTES + PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_D * PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_WOTS_BYTES +\ - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_FULL_HEIGHT * PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N) -#define PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_PK_BYTES (2 * PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N) -#define PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_SK_BYTES (2 * PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N + PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_PK_BYTES) - -/* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ -#define PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_OPTRAND_BYTES 32 +#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ + SPX_FULL_HEIGHT * SPX_N) +#define SPX_PK_BYTES (2 * SPX_N) +#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) + +#include "haraka_offsets.h" #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/sign.c b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/sign.c index 158d60c19a..9d0c7d1b22 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/sign.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/sign.c @@ -1,76 +1,45 @@ -#include #include #include #include #include "address.h" -#include "api.h" +#include "context.h" #include "fors.h" #include "hash.h" -#include "hash_state.h" +#include "merkle.h" +#include "nistapi.h" #include "params.h" #include "randombytes.h" #include "thash.h" #include "utils.h" #include "wots.h" - -/** - * Computes the leaf at a given address. First generates the WOTS key pair, - * then computes leaf by hashing horizontally. - */ -static void wots_gen_leaf(unsigned char *leaf, const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx, const uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - unsigned char pk[PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_WOTS_BYTES]; - uint32_t wots_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_set_type( - wots_addr, PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_set_type( - wots_pk_addr, PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_ADDR_TYPE_WOTSPK); - - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_set_keypair_addr( - wots_addr, addr_idx); - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_wots_gen_pk( - pk, sk_seed, pub_seed, wots_addr, hash_state_seeded); - - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_copy_keypair_addr( - wots_pk_addr, wots_addr); - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_thash_WOTS_LEN( - leaf, pk, pub_seed, wots_pk_addr, hash_state_seeded); -} - /* * Returns the length of a secret key, in bytes */ -size_t PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_crypto_sign_secretkeybytes(void) { - return PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_CRYPTO_SECRETKEYBYTES; +size_t crypto_sign_secretkeybytes(void) { + return CRYPTO_SECRETKEYBYTES; } /* * Returns the length of a public key, in bytes */ -size_t PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_crypto_sign_publickeybytes(void) { - return PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_CRYPTO_PUBLICKEYBYTES; +size_t crypto_sign_publickeybytes(void) { + return CRYPTO_PUBLICKEYBYTES; } /* * Returns the length of a signature, in bytes */ -size_t PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_crypto_sign_bytes(void) { - return PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_CRYPTO_BYTES; +size_t crypto_sign_bytes(void) { + return CRYPTO_BYTES; } /* * Returns the length of the seed required to generate a key pair, in bytes */ -size_t PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_crypto_sign_seedbytes(void) { - return PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_CRYPTO_SEEDBYTES; +size_t crypto_sign_seedbytes(void) { + return CRYPTO_SEEDBYTES; } /* @@ -78,35 +47,29 @@ size_t PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_crypto_sign_seedbytes(void) { * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] * Format pk: [PUB_SEED || root] */ -int PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed) { - /* We do not need the auth path in key generation, but it simplifies the - code to have just one treehash routine that computes both root and path - in one function. */ - unsigned char auth_path[PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_TREE_HEIGHT * PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N]; - uint32_t top_tree_addr[8] = {0}; - hash_state hash_state_seeded; - - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_set_layer_addr( - top_tree_addr, PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_D - 1); - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_set_type( - top_tree_addr, PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_ADDR_TYPE_HASHTREE); +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed) { + spx_ctx ctx; /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ - memcpy(sk, seed, PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_CRYPTO_SEEDBYTES); + memcpy(sk, seed, CRYPTO_SEEDBYTES); + + memcpy(pk, sk + 2 * SPX_N, SPX_N); - memcpy(pk, sk + 2 * PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N, PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N); + memcpy(ctx.pub_seed, pk, SPX_N); + memcpy(ctx.sk_seed, sk, SPX_N); /* This hook allows the hash function instantiation to do whatever preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_initialize_hash_function(&hash_state_seeded, pk, sk); + initialize_hash_function(&ctx); /* Compute root node of the top-most subtree. */ - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_treehash_TREE_HEIGHT( - sk + 3 * PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N, auth_path, sk, sk + 2 * PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N, 0, 0, - wots_gen_leaf, top_tree_addr, &hash_state_seeded); + merkle_gen_root(sk + 3 * SPX_N, &ctx); - memcpy(pk + PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N, sk + 3 * PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N, PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N); + // cleanup + free_hash_function(&ctx); + + memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); return 0; } @@ -116,31 +79,10 @@ int PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_crypto_sign_seed_keypair( * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] * Format pk: [PUB_SEED || root] */ -int PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk) { - - // guarantee alignment of pk - union { - __m128 _x[PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_CRYPTO_PUBLICKEYBYTES / 16]; - uint8_t pk[PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_CRYPTO_PUBLICKEYBYTES]; - } aligned_pk; - - // guarantee alignment of sk - union { - __m128 _x[PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_CRYPTO_SECRETKEYBYTES / 16]; - uint8_t sk[PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_CRYPTO_SECRETKEYBYTES]; - } aligned_sk; - - union { - __m128 _x[PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_CRYPTO_SEEDBYTES / 16]; - uint8_t seed[PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_CRYPTO_SEEDBYTES]; - } aligned_seed; - randombytes(aligned_seed.seed, PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_CRYPTO_SEEDBYTES); - - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_crypto_sign_seed_keypair( - aligned_pk.pk, aligned_sk.sk, aligned_seed.seed); - memcpy(pk, aligned_pk.pk, PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_CRYPTO_PUBLICKEYBYTES); - memcpy(sk, aligned_sk.sk, PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_CRYPTO_SECRETKEYBYTES); +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { + uint8_t seed[CRYPTO_SEEDBYTES]; + randombytes(seed, CRYPTO_SEEDBYTES); + crypto_sign_seed_keypair(pk, sk, seed); return 0; } @@ -148,101 +90,68 @@ int PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_crypto_sign_keypair( /** * Returns an array containing a detached signature. */ -int PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - // guarantee alignment of sk - union { - __m128 *_x; - uint8_t sk[PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_CRYPTO_SECRETKEYBYTES]; - } aligned_sk; - memcpy(aligned_sk.sk, sk, PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_CRYPTO_SECRETKEYBYTES); - sk = aligned_sk.sk; - - // guarantee alignment of sig - union { - __m128 *_x; - uint8_t sig[PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_BYTES]; - } aligned_sig; - uint8_t *orig_sig = sig; - sig = (uint8_t *)aligned_sig.sig; - - const unsigned char *sk_seed = sk; - const unsigned char *sk_prf = sk + PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N; - const unsigned char *pk = sk + 2 * PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N; - const unsigned char *pub_seed = pk; - - unsigned char optrand[PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N]; - unsigned char mhash[PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_FORS_MSG_BYTES]; - unsigned char root[PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N]; +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk) { + spx_ctx ctx; + + const uint8_t *sk_prf = sk + SPX_N; + const uint8_t *pk = sk + 2 * SPX_N; + + uint8_t optrand[SPX_N]; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t root[SPX_N]; uint32_t i; uint64_t tree; uint32_t idx_leaf; uint32_t wots_addr[8] = {0}; uint32_t tree_addr[8] = {0}; - hash_state hash_state_seeded; + memcpy(ctx.sk_seed, sk, SPX_N); + memcpy(ctx.pub_seed, pk, SPX_N); /* This hook allows the hash function instantiation to do whatever preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_initialize_hash_function( - &hash_state_seeded, - pub_seed, sk_seed); + initialize_hash_function(&ctx); - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_set_type( - wots_addr, PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_set_type( - tree_addr, PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_ADDR_TYPE_HASHTREE); + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); /* Optionally, signing can be made non-deterministic using optrand. This can help counter side-channel attacks that would benefit from getting a large number of traces when the signer uses the same nodes. */ - randombytes(optrand, PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N); + randombytes(optrand, SPX_N); /* Compute the digest randomization value. */ - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_gen_message_random( - sig, sk_prf, optrand, m, mlen, &hash_state_seeded); + gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); /* Derive the message digest and leaf index from R, PK and M. */ - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N; + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_set_keypair_addr( - wots_addr, idx_leaf); + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); /* Sign the message hash using FORS. */ - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_fors_sign( - sig, root, mhash, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_FORS_BYTES; - - for (i = 0; i < PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_D; i++) { - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_set_tree_addr(tree_addr, tree); - - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_set_keypair_addr( - wots_addr, idx_leaf); - - /* Compute a WOTS signature. */ - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_wots_sign( - sig, root, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_WOTS_BYTES; - - /* Compute the authentication path for the used WOTS leaf. */ - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_treehash_TREE_HEIGHT( - root, sig, sk_seed, pub_seed, idx_leaf, 0, - wots_gen_leaf, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_TREE_HEIGHT * PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N; + fors_sign(sig, root, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); + sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_TREE_HEIGHT; + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; } - memcpy(orig_sig, aligned_sig.sig, PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_BYTES); - *siglen = PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_BYTES; + free_hash_function(&ctx); + + *siglen = SPX_BYTES; return 0; } @@ -250,23 +159,14 @@ int PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_crypto_sign_signature( /** * Verifies a detached signature and message under a given public key. */ -int PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk) { - // guarantee alignment of pk - union { - __m128 *_x; - uint8_t pk[PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_CRYPTO_PUBLICKEYBYTES]; - } aligned_pk; - memcpy(aligned_pk.pk, pk, PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_CRYPTO_PUBLICKEYBYTES); - pk = aligned_pk.pk; - - const unsigned char *pub_seed = pk; - const unsigned char *pub_root = pk + PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N; - unsigned char mhash[PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_FORS_MSG_BYTES]; - unsigned char wots_pk[PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_WOTS_BYTES]; - unsigned char root[PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N]; - unsigned char leaf[PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N]; +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk) { + spx_ctx ctx; + const uint8_t *pub_root = pk + SPX_N; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t wots_pk[SPX_WOTS_BYTES]; + uint8_t root[SPX_N]; + uint8_t leaf[SPX_N]; unsigned int i; uint64_t tree; uint32_t idx_leaf; @@ -274,77 +174,66 @@ int PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_crypto_sign_verify( uint32_t tree_addr[8] = {0}; uint32_t wots_pk_addr[8] = {0}; - hash_state hash_state_seeded; - - if (siglen != PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_BYTES) { + if (siglen != SPX_BYTES) { return -1; } + memcpy(ctx.pub_seed, pk, SPX_N); + /* This hook allows the hash function instantiation to do whatever preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_initialize_hash_function( - &hash_state_seeded, - pub_seed, NULL); + initialize_hash_function(&ctx); - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_set_type( - wots_addr, PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_set_type( - tree_addr, PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_ADDR_TYPE_HASHTREE); - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_set_type( - wots_pk_addr, PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_ADDR_TYPE_WOTSPK); + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); /* Derive the message digest and leaf index from R || PK || M. */ - /* The additional PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N is a result of the hash domain separator. */ - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N; + /* The additional SPX_N is a result of the hash domain separator. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; /* Layer correctly defaults to 0, so no need to set_layer_addr */ - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_set_keypair_addr( - wots_addr, idx_leaf); + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_fors_pk_from_sig( - root, sig, mhash, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_FORS_BYTES; + fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; /* For each subtree.. */ - for (i = 0; i < PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_D; i++) { - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_set_tree_addr(tree_addr, tree); + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_set_keypair_addr( - wots_addr, idx_leaf); + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_copy_keypair_addr( - wots_pk_addr, wots_addr); + copy_keypair_addr(wots_pk_addr, wots_addr); /* The WOTS public key is only correct if the signature was correct. */ /* Initially, root is the FORS pk, but on subsequent iterations it is the root of the subtree below the currently processed subtree. */ - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_wots_pk_from_sig( - wots_pk, sig, root, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_WOTS_BYTES; + wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); + sig += SPX_WOTS_BYTES; /* Compute the leaf node using the WOTS public key. */ - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_thash_WOTS_LEN( - leaf, wots_pk, pub_seed, wots_pk_addr, &hash_state_seeded); + thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); /* Compute the root node of this subtree. */ - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_compute_root( - root, leaf, idx_leaf, 0, sig, PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_TREE_HEIGHT, - pub_seed, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_TREE_HEIGHT * PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N; + compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, + &ctx, tree_addr); + sig += SPX_TREE_HEIGHT * SPX_N; /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_TREE_HEIGHT; + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; } + // cleanup + free_hash_function(&ctx); + /* Check if the root node equals the root node in the public key. */ - if (memcmp(root, pub_root, PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N) != 0) { + if (memcmp(root, pub_root, SPX_N) != 0) { return -1; } @@ -355,15 +244,14 @@ int PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_crypto_sign_verify( /** * Returns an array containing the signature followed by the message. */ -int PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk) { size_t siglen; - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_crypto_sign_signature( - sm, &siglen, m, mlen, sk); + crypto_sign_signature(sm, &siglen, m, mlen, sk); - memmove(sm + PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_BYTES, m, mlen); + memmove(sm + SPX_BYTES, m, mlen); *smlen = siglen + mlen; return 0; @@ -372,38 +260,27 @@ int PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_crypto_sign( /** * Verifies a given signature-message pair under a given public key. */ -int PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk) { - - // guarantee alignment of pk - union { - __m128 *_x; - uint8_t pk[PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_CRYPTO_PUBLICKEYBYTES]; - } aligned_pk; - memcpy(aligned_pk.pk, pk, PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_CRYPTO_PUBLICKEYBYTES); - pk = aligned_pk.pk; - - +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk) { /* The API caller does not necessarily know what size a signature should be - but SPHINCS+ signatures are always exactly PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_BYTES. */ - if (smlen < PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_BYTES) { + but SPHINCS+ signatures are always exactly SPX_BYTES. */ + if (smlen < SPX_BYTES) { memset(m, 0, smlen); *mlen = 0; return -1; } - *mlen = smlen - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_BYTES; + *mlen = smlen - SPX_BYTES; - if (PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_crypto_sign_verify( - sm, PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_BYTES, sm + PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_BYTES, *mlen, pk)) { + if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { memset(m, 0, smlen); *mlen = 0; return -1; } /* If verification was successful, move the message to the right place. */ - memmove(m, sm + PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_BYTES, *mlen); + memmove(m, sm + SPX_BYTES, *mlen); return 0; } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/thash.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/thash.h index b5faf26575..8687ccfb4d 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/thash.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/thash.h @@ -1,28 +1,13 @@ -#ifndef PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_THASH_H -#define PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_THASH_H +#ifndef SPX_THASH_H +#define SPX_THASH_H -#include "hash_state.h" +#include "context.h" +#include "params.h" #include -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); +#define thash SPX_NAMESPACE(thash) +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/thash_haraka_simple.c b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/thash_haraka_simple.c index 4bfe5daa16..207777bf8d 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/thash_haraka_simple.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/thash_haraka_simple.c @@ -4,80 +4,33 @@ #include "address.h" #include "params.h" #include "thash.h" +#include "utils.h" #include "haraka.h" /** - * Takes an array of inblocks concatenated arrays of PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N bytes. + * Takes an array of inblocks concatenated arrays of SPX_N bytes. */ -static void PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_thash( - unsigned char *out, unsigned char *buf, - const unsigned char *in, unsigned int inblocks, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]) { + PQCLEAN_VLA(uint8_t, buf, SPX_ADDR_BYTES + inblocks * SPX_N); unsigned char outbuf[32]; unsigned char buf_tmp[64]; - (void)pub_seed; /* Suppress an 'unused parameter' warning. */ - if (inblocks == 1) { /* F function */ - /* Since PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N may be smaller than 32, we need a temporary buffer. */ + /* Since SPX_N may be smaller than 32, we need a temporary buffer. */ memset(buf_tmp, 0, 64); - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_addr_to_bytes(buf_tmp, addr); - memcpy(buf_tmp + PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_ADDR_BYTES, in, PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N); + memcpy(buf_tmp, addr, 32); + memcpy(buf_tmp + SPX_ADDR_BYTES, in, SPX_N); - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_haraka512(outbuf, buf_tmp, hash_state_seeded); - memcpy(out, outbuf, PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N); + haraka512(outbuf, buf_tmp, ctx); + memcpy(out, outbuf, SPX_N); } else { /* All other tweakable hashes*/ - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_addr_to_bytes(buf, addr); - memcpy(buf + PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_ADDR_BYTES, in, inblocks * PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N); + memcpy(buf, addr, 32); + memcpy(buf + SPX_ADDR_BYTES, in, inblocks * SPX_N); - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_haraka_S( - out, PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N, buf, PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N, hash_state_seeded); + haraka_S(out, SPX_N, buf, SPX_ADDR_BYTES + inblocks * SPX_N, ctx); } } - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_ADDR_BYTES + 1 * PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N]; - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_thash( - out, buf, in, 1, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_ADDR_BYTES + 2 * PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N]; - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_thash( - out, buf, in, 2, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_ADDR_BYTES + PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_WOTS_LEN * PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N]; - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_thash( - out, buf, in, PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_WOTS_LEN, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_ADDR_BYTES + PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_FORS_TREES * PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N]; - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_thash( - out, buf, in, PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_FORS_TREES, pub_seed, addr, hash_state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/thash_haraka_simplex4.c b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/thash_haraka_simplex4.c index 98279e479b..2ee763d7d9 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/thash_haraka_simplex4.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/thash_haraka_simplex4.c @@ -2,65 +2,66 @@ #include #include "address.h" -#include "haraka.h" #include "params.h" #include "thashx4.h" +#include "harakax4.h" + +#include "utils.h" + /** * 4-way parallel version of thash; takes 4x as much input and output */ -#define thashx4_variant(name, inblocks) \ - void PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_thashx4_##name(unsigned char *out0, unsigned char *out1, unsigned char *out2, \ - unsigned char *out3, const unsigned char *in0, \ - const unsigned char *in1, const unsigned char *in2, \ - const unsigned char *in3, const unsigned char *pub_seed, \ - uint32_t addrx4[4 * 8], const harakactx *state) { \ - unsigned char buf0[PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_ADDR_BYTES + (inblocks)*PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N]; \ - unsigned char buf1[PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_ADDR_BYTES + (inblocks)*PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N]; \ - unsigned char buf2[PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_ADDR_BYTES + (inblocks)*PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N]; \ - unsigned char buf3[PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_ADDR_BYTES + (inblocks)*PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N]; \ - unsigned char outbuf[32 * 4]; \ - unsigned char buf_tmp[64 * 4]; \ - \ - (void)pub_seed; /* Suppress an 'unused parameter' warning. */ \ - \ - if ((inblocks) == 1) { \ - memset(buf_tmp, 0, 64 * 4); \ - \ - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_addr_to_bytes(buf_tmp, addrx4 + 0 * 8); \ - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_addr_to_bytes(buf_tmp + 64, addrx4 + 1 * 8); \ - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_addr_to_bytes(buf_tmp + 128, addrx4 + 2 * 8); \ - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_addr_to_bytes(buf_tmp + 192, addrx4 + 3 * 8); \ - \ - memcpy(buf_tmp + PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_ADDR_BYTES, in0, PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N); \ - memcpy(buf_tmp + PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_ADDR_BYTES + 64, in1, PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N); \ - memcpy(buf_tmp + PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_ADDR_BYTES + 128, in2, PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N); \ - memcpy(buf_tmp + PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_ADDR_BYTES + 192, in3, PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N); \ - \ - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_haraka512x4(outbuf, buf_tmp, state); \ - \ - memcpy(out0, outbuf, PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N); \ - memcpy(out1, outbuf + 32, PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N); \ - memcpy(out2, outbuf + 64, PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N); \ - memcpy(out3, outbuf + 96, PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N); \ - } else { \ - /* All other tweakable hashes*/ \ - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_addr_to_bytes(buf0, addrx4 + 0 * 8); \ - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_addr_to_bytes(buf1, addrx4 + 1 * 8); \ - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_addr_to_bytes(buf2, addrx4 + 2 * 8); \ - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_addr_to_bytes(buf3, addrx4 + 3 * 8); \ - \ - memcpy(buf0 + PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_ADDR_BYTES, in0, (inblocks)*PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N); \ - memcpy(buf1 + PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_ADDR_BYTES, in1, (inblocks)*PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N); \ - memcpy(buf2 + PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_ADDR_BYTES, in2, (inblocks)*PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N); \ - memcpy(buf3 + PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_ADDR_BYTES, in3, (inblocks)*PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N); \ - \ - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_haraka_Sx4(out0, out1, out2, out3, PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N, buf0, buf1, buf2, buf3, \ - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_ADDR_BYTES + (inblocks)*PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N, state); \ - } \ - } +#define thashx4 SPX_NAMESPACE(thashx4) +void thashx4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addrx4[4 * 8]) { + PQCLEAN_VLA(unsigned char, buf0, SPX_ADDR_BYTES + inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, buf1, SPX_ADDR_BYTES + inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, buf2, SPX_ADDR_BYTES + inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, buf3, SPX_ADDR_BYTES + inblocks * SPX_N); + unsigned char outbuf[32 * 4]; + unsigned char buf_tmp[64 * 4]; + + if (inblocks == 1) { + memset(buf_tmp, 0, 64 * 4); + + memcpy(buf_tmp, addrx4 + 0 * 8, 32); + memcpy(buf_tmp + 64, addrx4 + 1 * 8, 32); + memcpy(buf_tmp + 128, addrx4 + 2 * 8, 32); + memcpy(buf_tmp + 192, addrx4 + 3 * 8, 32); -thashx4_variant(1, 1) -thashx4_variant(2, 2) -thashx4_variant(WOTS_LEN, PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_WOTS_LEN) -thashx4_variant(FORS_TREES, PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_FORS_TREES) + memcpy(buf_tmp + SPX_ADDR_BYTES, in0, SPX_N); + memcpy(buf_tmp + SPX_ADDR_BYTES + 64, in1, SPX_N); + memcpy(buf_tmp + SPX_ADDR_BYTES + 128, in2, SPX_N); + memcpy(buf_tmp + SPX_ADDR_BYTES + 192, in3, SPX_N); + + haraka512x4(outbuf, buf_tmp, ctx); + + memcpy(out0, outbuf, SPX_N); + memcpy(out1, outbuf + 32, SPX_N); + memcpy(out2, outbuf + 64, SPX_N); + memcpy(out3, outbuf + 96, SPX_N); + } else { + /* All other tweakable hashes*/ + memcpy(buf0, addrx4 + 0 * 8, 32); + memcpy(buf1, addrx4 + 1 * 8, 32); + memcpy(buf2, addrx4 + 2 * 8, 32); + memcpy(buf3, addrx4 + 3 * 8, 32); + + memcpy(buf0 + SPX_ADDR_BYTES, in0, inblocks * SPX_N); + memcpy(buf1 + SPX_ADDR_BYTES, in1, inblocks * SPX_N); + memcpy(buf2 + SPX_ADDR_BYTES, in2, inblocks * SPX_N); + memcpy(buf3 + SPX_ADDR_BYTES, in3, inblocks * SPX_N); + + haraka_Sx4(out0, out1, out2, out3, SPX_N, + buf0, buf1, buf2, buf3, SPX_ADDR_BYTES + inblocks * SPX_N, + ctx); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/thashx4.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/thashx4.h index 407da7d5c7..64798a3727 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/thashx4.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/thashx4.h @@ -1,25 +1,20 @@ -#ifndef PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_THASHX4_H -#define PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_THASHX4_H +#ifndef SPX_THASHX4_H +#define SPX_THASHX4_H #include -#include "hash_state.h" +#include "context.h" +#include "params.h" -#define thashx4_header(inblocks) \ - void PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_thashx4_##inblocks(unsigned char *out0, \ - unsigned char *out1, \ - unsigned char *out2, \ - unsigned char *out3, \ - const unsigned char *in0, \ - const unsigned char *in1, \ - const unsigned char *in2, \ - const unsigned char *in3, \ - const unsigned char *pub_seed, uint32_t addrx4[4*8], \ - const hash_state *state_seeded) - -thashx4_header(1); -thashx4_header(2); -thashx4_header(WOTS_LEN); -thashx4_header(FORS_TREES); +#define thashx4 SPX_NAMESPACE(thashx4) +void thashx4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addrx4[4 * 8]); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/utils.c b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/utils.c index 75fe4b6a21..177b541fb9 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/utils.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/utils.c @@ -1,34 +1,41 @@ -#include #include +#include "utils.h" + #include "address.h" #include "hash.h" -#include "hash_state.h" #include "params.h" #include "thash.h" -#include "utils.h" /** * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. */ -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in) { +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in) { + int i; /* Iterate over out in decreasing order, for big-endianness. */ - for (size_t i = outlen; i > 0; i--) { - out[i - 1] = in & 0xff; + for (i = (signed int)outlen - 1; i >= 0; i--) { + out[i] = in & 0xff; in = in >> 8; } } +void u32_to_bytes(unsigned char *out, uint32_t in) { + out[0] = (unsigned char)(in >> 24); + out[1] = (unsigned char)(in >> 16); + out[2] = (unsigned char)(in >> 8); + out[3] = (unsigned char)in; +} + /** * Converts the inlen bytes in 'in' from big-endian byte order to an integer. */ -unsigned long long PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_bytes_to_ull( - const unsigned char *in, size_t inlen) { +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { unsigned long long retval = 0; + unsigned int i; - for (size_t i = 0; i < inlen; i++) { + for (i = 0; i < inlen; i++) { retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); } return retval; @@ -38,94 +45,80 @@ unsigned long long PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_bytes_to_ull( * Computes a root node given a leaf and an auth path. * Expects address to be complete other than the tree_height and tree_index. */ -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]) { uint32_t i; - unsigned char buffer[2 * PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N]; + unsigned char buffer[2 * SPX_N]; /* If leaf_idx is odd (last bit = 1), current path element is a right child and auth_path has to go left. Otherwise it is the other way around. */ if (leaf_idx & 1) { - memcpy(buffer + PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N, leaf, PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N); + memcpy(buffer + SPX_N, leaf, SPX_N); + memcpy(buffer, auth_path, SPX_N); } else { - memcpy(buffer, leaf, PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N); - memcpy(buffer + PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N, auth_path, PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N); + memcpy(buffer, leaf, SPX_N); + memcpy(buffer + SPX_N, auth_path, SPX_N); } - auth_path += PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N; + auth_path += SPX_N; for (i = 0; i < tree_height - 1; i++) { leaf_idx >>= 1; idx_offset >>= 1; /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_set_tree_height(addr, i + 1); - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_set_tree_index( - addr, leaf_idx + idx_offset); + set_tree_height(addr, i + 1); + set_tree_index(addr, leaf_idx + idx_offset); /* Pick the right or left neighbor, depending on parity of the node. */ if (leaf_idx & 1) { - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_thash_2( - buffer + PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N); + thash(buffer + SPX_N, buffer, 2, ctx, addr); + memcpy(buffer, auth_path, SPX_N); } else { - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_thash_2( - buffer, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer + PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N, auth_path, PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N); + thash(buffer, buffer, 2, ctx, addr); + memcpy(buffer + SPX_N, auth_path, SPX_N); } - auth_path += PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N; + auth_path += SPX_N; } /* The last iteration is exceptional; we do not copy an auth_path node. */ leaf_idx >>= 1; idx_offset >>= 1; - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_set_tree_height(addr, tree_height); - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_set_tree_index( - addr, leaf_idx + idx_offset); - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_thash_2( - root, buffer, pub_seed, addr, hash_state_seeded); + set_tree_height(addr, tree_height); + set_tree_index(addr, leaf_idx + idx_offset); + thash(root, buffer, 2, ctx, addr); } /** * For a given leaf index, computes the authentication path and the resulting * root node using Merkle's TreeHash algorithm. * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_ADDR_TYPE_FORSTREE). + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). * Applies the offset idx_offset to indices before building addresses, so that * it is possible to continue counting indices across trees. */ -static void PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_treehash( - unsigned char *root, unsigned char *auth_path, - unsigned char *stack, unsigned int *heights, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - +void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx * /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]) { + PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); + PQCLEAN_VLA(unsigned int, heights, tree_height + 1); unsigned int offset = 0; uint32_t idx; uint32_t tree_idx; for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { /* Add the next leaf node to the stack. */ - gen_leaf(stack + offset * PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N, - sk_seed, pub_seed, idx + idx_offset, tree_addr, - hash_state_seeded); + gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); offset++; heights[offset - 1] = 0; /* If this is a node we need for the auth path.. */ if ((leaf_idx ^ 0x1) == idx) { - memcpy(auth_path, stack + (offset - 1)*PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N, PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N); + memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); } /* While the top-most nodes are of equal height.. */ @@ -134,66 +127,22 @@ static void PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_treehash( tree_idx = (idx >> (heights[offset - 1] + 1)); /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_set_tree_height( - tree_addr, heights[offset - 1] + 1); - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_set_tree_index( - tree_addr, tree_idx + (idx_offset >> (heights[offset - 1] + 1))); + set_tree_height(tree_addr, heights[offset - 1] + 1); + set_tree_index(tree_addr, + tree_idx + (idx_offset >> (heights[offset - 1] + 1))); /* Hash the top-most nodes from the stack together. */ - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_thash_2( - stack + (offset - 2)*PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N, stack + (offset - 2)*PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N, - pub_seed, tree_addr, hash_state_seeded); + thash(stack + (offset - 2)*SPX_N, + stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); offset--; /* Note that the top-most node is now one layer higher. */ heights[offset - 1]++; /* If this is a node we need for the auth path.. */ if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_path + heights[offset - 1]*PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N, - stack + (offset - 1)*PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N, PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N); + memcpy(auth_path + heights[offset - 1]*SPX_N, + stack + (offset - 1)*SPX_N, SPX_N); } } } - memcpy(root, stack, PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N); -} - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_FORS_HEIGHT + 1)*PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N]; - unsigned int heights[PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_FORS_HEIGHT + 1]; - - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_FORS_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_TREE_HEIGHT + 1)*PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N]; - unsigned int heights[PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_TREE_HEIGHT + 1]; - - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_TREE_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); + memcpy(root, stack, SPX_N); } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/utils.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/utils.h index 85e1c43cbf..64f5d5a53a 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/utils.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/utils.h @@ -1,64 +1,58 @@ -#ifndef PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_UTILS_H -#define PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_UTILS_H +#ifndef SPX_UTILS_H +#define SPX_UTILS_H -#include "hash_state.h" -#include "params.h" -#include #include +#include "compat.h" +#include "context.h" +#include "params.h" + + +/* To support MSVC use alloca() instead of VLAs. See #20. */ + + /** * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. */ -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in); +#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in); +#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) +void u32_to_bytes(unsigned char *out, uint32_t in); /** * Converts the inlen bytes in 'in' from big-endian byte order to an integer. */ -unsigned long long PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_bytes_to_ull( - const unsigned char *in, size_t inlen); +#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); /** * Computes a root node given a leaf and an auth path. * Expects address to be complete other than the tree_height and tree_index. */ -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); +#define compute_root SPX_NAMESPACE(compute_root) +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]); /** * For a given leaf index, computes the authentication path and the resulting * root node using Merkle's TreeHash algorithm. * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_ADDR_TYPE_FORSTREE). + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). * Applies the offset idx_offset to indices before building addresses, so that * it is possible to continue counting indices across trees. */ -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); +#define treehash SPX_NAMESPACE(treehash) +void treehash(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx *ctx /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]); -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/utilsx4.c b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/utilsx4.c index 36d910902e..1638677194 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/utilsx4.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/utilsx4.c @@ -1,98 +1,138 @@ +#include + +#include "utilsx4.h" + #include "address.h" #include "params.h" #include "thashx4.h" #include "utils.h" -#include "utilsx4.h" -#include - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. +/* + * Generate the entire Merkle tree, computing the authentication path for leaf_idx, + * and the resulting root node using Merkle's TreeHash algorithm. * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_ADDR_TYPE_FORSTREE). + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) + * + * This expects tree_addrx4 to be initialized to 4 parallel addr structures for + * the Merkle tree nodes + * * Applies the offset idx_offset to indices before building addresses, so that * it is possible to continue counting indices across trees. + * + * This works by using the standard Merkle tree building algorithm, except + * that each 'node' tracked is actually 4 consecutive nodes in the real tree. + * When we combine two logical nodes ABCD and WXYZ, we perform the H + * operation on adjacent real nodes, forming the parent logical node + * (AB)(CD)(WX)(YZ) + * + * When we get to the top two levels of the real tree (where there is only + * one logical node), we continue this operation two more times; the right + * most real node will by the actual root (and the other 3 nodes will be + * garbage). We follow the same thashx4 logic so that the 'extract + * authentication path components' part of the loop is still executed (and + * to simplify the code somewhat) + * + * This currently assumes tree_height >= 2; I suspect that doing an adjusting + * idx, addr_idx on the gen_leafx4 call if tree_height < 2 would fix it; since + * we don't actually use such short trees, I haven't bothered */ -#define treehashx4_variant(name, tree_height) \ - void PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_treehashx4_##name( \ - unsigned char *rootx4, unsigned char *auth_pathx4, const unsigned char *sk_seed, \ - const unsigned char *pub_seed, const uint32_t leaf_idx[4], uint32_t idx_offset[4], \ - void (*gen_leafx4)(unsigned char * /* leaf0 */, unsigned char * /* leaf1 */, \ - unsigned char * /* leaf2 */, unsigned char * /* leaf3 */, \ - const unsigned char * /* sk_seed */, \ - const unsigned char * /* pub_seed */, uint32_t /* addr_idx0 */, \ - uint32_t /* addr_idx1 */, uint32_t /* addr_idx2 */, \ - uint32_t /* addr_idx3 */, const uint32_t[8] /* tree_addr */, \ - const hash_state * /* state_seeded */), \ - uint32_t tree_addrx4[4 * 8], const hash_state *state_seeded) { \ - unsigned char stackx4[4 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N]; \ - unsigned int heights[(tree_height) + 1]; \ - unsigned int offset = 0; \ - uint32_t idx; \ - uint32_t tree_idx; \ - unsigned int j; \ - \ - for (idx = 0; idx < (uint32_t)(1 << (tree_height)); idx++) { \ - /* Add the next leaf node to the stack. */ \ - gen_leafx4(stackx4 + 0 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N + offset * PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N, \ - stackx4 + 1 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N + offset * PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N, \ - stackx4 + 2 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N + offset * PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N, \ - stackx4 + 3 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N + offset * PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N, sk_seed, \ - pub_seed, idx + idx_offset[0], idx + idx_offset[1], idx + idx_offset[2], \ - idx + idx_offset[3], tree_addrx4, state_seeded); \ - offset++; \ - heights[offset - 1] = 0; \ - \ - /* If this is a node we need for the auth path.. */ \ - for (j = 0; j < 4; j++) { \ - if ((leaf_idx[j] ^ 0x1) == idx) { \ - memcpy(auth_pathx4 + j * (tree_height)*PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N, \ - stackx4 + j * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N + (offset - 1) * PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N, \ - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N); \ - } \ - } \ - \ - /* While the top-most nodes are of equal height.. */ \ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { \ - /* Compute index of the new node, in the next layer. */ \ - tree_idx = (idx >> (heights[offset - 1] + 1)); \ - \ - /* Set the address of the node we're creating. */ \ - for (j = 0; j < 4; j++) { \ - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_set_tree_height(tree_addrx4 + j * 8, heights[offset - 1] + 1); \ - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_set_tree_index(tree_addrx4 + j * 8, \ - tree_idx + (idx_offset[j] >> (heights[offset - 1] + 1))); \ - } \ - /* Hash the top-most nodes from the stack together. */ \ - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_thashx4_2(stackx4 + 0 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N + (offset - 2) * PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N, \ - stackx4 + 1 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N + (offset - 2) * PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N, \ - stackx4 + 2 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N + (offset - 2) * PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N, \ - stackx4 + 3 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N + (offset - 2) * PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N, \ - stackx4 + 0 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N + (offset - 2) * PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N, \ - stackx4 + 1 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N + (offset - 2) * PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N, \ - stackx4 + 2 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N + (offset - 2) * PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N, \ - stackx4 + 3 * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N + (offset - 2) * PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N, \ - pub_seed, tree_addrx4, state_seeded); \ - offset--; \ - /* Note that the top-most node is now one layer higher. */ \ - heights[offset - 1]++; \ - \ - /* If this is a node we need for the auth path.. */ \ - for (j = 0; j < 4; j++) { \ - if (((leaf_idx[j] >> heights[offset - 1]) ^ 0x1) == tree_idx) { \ - memcpy(auth_pathx4 + j * (tree_height)*PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N + \ - heights[offset - 1] * PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N, \ - stackx4 + j * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N + (offset - 1) * PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N, \ - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N); \ - } \ - } \ - } \ - } \ - \ - for (j = 0; j < 4; j++) { \ - memcpy(rootx4 + j * PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N, stackx4 + j * ((tree_height) + 1) * PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N, PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N); \ - } \ - } +void treehashx4(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, + uint32_t tree_height, + void (*gen_leafx4)( + unsigned char * /* Where to write the leaves */, + const spx_ctx *, + uint32_t idx, void *info), + uint32_t tree_addrx4[4 * 8], + void *info) { + /* This is where we keep the intermediate nodes */ + PQCLEAN_VLA(unsigned char, stackx4, tree_height * 4 * SPX_N); + uint32_t left_adj = 0, prev_left_adj = 0; /* When we're doing the top 3 */ + /* levels, the left-most part of the tree isn't at the beginning */ + /* of current[]. These give the offset of the actual start */ + + uint32_t idx; + uint32_t max_idx = (1U << (tree_height - 2)) - 1; + for (idx = 0;; idx++) { + unsigned char current[4 * SPX_N]; /* Current logical node */ + gen_leafx4( current, ctx, 4 * idx + idx_offset, + info ); -treehashx4_variant(FORS_HEIGHT, PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_FORS_HEIGHT) + /* Now combine the freshly generated right node with previously */ + /* generated left ones */ + uint32_t internal_idx_offset = idx_offset; + uint32_t internal_idx = idx; + uint32_t internal_leaf = leaf_idx; + uint32_t h; /* The height we are in the Merkle tree */ + for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { + + /* Special processing if we're at the top of the tree */ + if (h >= tree_height - 2) { + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[3 * SPX_N], SPX_N ); + return; + } + /* The tree indexing logic is a bit off in this case */ + /* Adjust it so that the left-most node of the part of */ + /* the tree that we're processing has index 0 */ + prev_left_adj = left_adj; + left_adj = 4U - (1 << (tree_height - h - 1)); + } + + /* Check if we hit the top of the tree */ + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[3 * SPX_N], SPX_N ); + return; + } + + /* + * Check if one of the nodes we have is a part of the + * authentication path; if it is, write it out + */ + if ((((internal_idx << 2) ^ internal_leaf) & ~0x3U) == 0) { + memcpy( &auth_path[ h * SPX_N ], + ¤t[(((internal_leaf & 3) ^ 1) + prev_left_adj) * SPX_N], + SPX_N ); + } + + /* + * Check if we're at a left child; if so, stop going up the stack + * Exception: if we've reached the end of the tree, keep on going + * (so we combine the last 4 nodes into the one root node in two + * more iterations) + */ + if ((internal_idx & 1) == 0 && idx < max_idx) { + break; + } + + /* Ok, we're at a right node (or doing the top 3 levels) */ + /* Now combine the left and right logical nodes together */ + + /* Set the address of the node we're creating. */ + unsigned int j; + internal_idx_offset >>= 1; + for (j = 0; j < 4; j++) { + set_tree_height(tree_addrx4 + j * 8, h + 1); + set_tree_index(tree_addrx4 + j * 8, + (4 / 2) * (internal_idx & ~1U) + j - left_adj + internal_idx_offset ); + } + unsigned char *left = &stackx4[h * 4 * SPX_N]; + thashx4( ¤t[0 * SPX_N], + ¤t[1 * SPX_N], + ¤t[2 * SPX_N], + ¤t[3 * SPX_N], + &left [0 * SPX_N], + &left [2 * SPX_N], + ¤t[0 * SPX_N], + ¤t[2 * SPX_N], + 2, ctx, tree_addrx4); + } + + /* We've hit a left child; save the current for when we get the */ + /* corresponding right right */ + memcpy( &stackx4[h * 4 * SPX_N], current, 4 * SPX_N); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/utilsx4.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/utilsx4.h index d9c5ba19b9..facb874b18 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/utilsx4.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/utilsx4.h @@ -1,38 +1,30 @@ -#ifndef PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_UTILSX4_H -#define PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_UTILSX4_H - -#include "hash_state.h" -#include "params.h" +#ifndef SPX_UTILSX4_H +#define SPX_UTILSX4_H #include +#include "context.h" +#include "params.h" + /** * For a given leaf index, computes the authentication path and the resulting * root node using Merkle's TreeHash algorithm. * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_ADDR_TYPE_FORSTREE). + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). * Applies the offset idx_offset to indices before building addresses, so that * it is possible to continue counting indices across trees. + * + * This implementation uses AVX to compute internal nodes 4 at a time (in + * parallel) */ -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_treehashx4_FORS_HEIGHT(unsigned char *rootx4, - unsigned char *auth_pathx4, - const unsigned char *sk_seed, - const unsigned char *pub_seed, - const uint32_t leaf_idx[4], - uint32_t idx_offset[4], - void (*gen_leafx4)(unsigned char * /* leaf0 */, - unsigned char * /* leaf1 */, - unsigned char * /* leaf2 */, - unsigned char * /* leaf3 */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx0 */, - uint32_t /* addr_idx1 */, - uint32_t /* addr_idx2 */, - uint32_t /* addr_idx3 */, - const uint32_t[8] /* tree_addr */, - const hash_state * /* state_seeded */), - uint32_t tree_addrx4[4 * 8], - const hash_state *state_seeded); +#define treehashx4 SPX_NAMESPACE(treehashx4) +void treehashx4(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leafx4)( + unsigned char * /* Where to write the leaves */, + const spx_ctx * /* ctx */, + uint32_t addr_idx, void *info), + uint32_t tree_addrx4[4 * 8], void *info); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/wots.c b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/wots.c index 1f72634b4c..4d5041ce05 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/wots.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/wots.c @@ -1,106 +1,104 @@ #include #include +#include "wots.h" + #include "address.h" #include "hash.h" -#include "hash_state.h" #include "hashx4.h" #include "params.h" #include "thash.h" #include "thashx4.h" #include "utils.h" -#include "wots.h" +#include "utilsx4.h" +#include "wotsx4.h" // TODO clarify address expectations, and make them more uniform. // TODO i.e. do we expect types to be set already? // TODO and do we expect modifications or copies? /** - * Computes the starting value for a chain, i.e. the secret key. - * Expects the address to be complete up to the chain address. - */ -static void wots_gen_sk(unsigned char *sk, const unsigned char *sk_seed, - uint32_t wots_addr[8], const hash_state *state_seeded) { - /* Make sure that the hash address is actually zeroed. */ - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_set_hash_addr(wots_addr, 0); - - /* Generate sk element. */ - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_prf_addr(sk, sk_seed, wots_addr, state_seeded); -} - -/** - * 4-way parallel version of wots_gen_sk; expects 4x as much space in sk + * Computes up the chains */ -static void wots_gen_skx4(unsigned char *skx4, const unsigned char *sk_seed, - uint32_t wots_addrx4[4 * 8], const hash_state *state_seeded) { - unsigned int j; - - /* Make sure that the hash address is actually zeroed. */ +static void gen_chains( + unsigned char *out, + const unsigned char *in, + unsigned int start[SPX_WOTS_LEN], + const unsigned int steps[SPX_WOTS_LEN], + const spx_ctx *ctx, + uint32_t addr[8]) { + uint32_t i, j, k, idx, watching; + int done; + unsigned char empty[SPX_N]; + unsigned char *bufs[4]; + uint32_t addrs[8 * 4]; + + int l; + uint16_t counts[SPX_WOTS_W] = { 0 }; + uint16_t idxs[SPX_WOTS_LEN]; + uint16_t total, newTotal; + + /* set addrs = {addr, addr, addr, addr} */ for (j = 0; j < 4; j++) { - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_set_hash_addr(wots_addrx4 + j * 8, 0); + memcpy(addrs + j * 8, addr, sizeof(uint32_t) * 8); } - /* Generate sk element. */ - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_prf_addrx4(skx4 + 0 * PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N, - skx4 + 1 * PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N, - skx4 + 2 * PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N, - skx4 + 3 * PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N, - sk_seed, wots_addrx4, - state_seeded); -} - -/** - * Computes the chaining function. - * out and in have to be n-byte arrays. - * - * Interprets in as start-th value of the chain. - * addr has to contain the address of the chain. - */ -static void gen_chain(unsigned char *out, const unsigned char *in, - unsigned int start, unsigned int steps, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *state_seeded) { - uint32_t i; - /* Initialize out with the value at position 'start'. */ - memcpy(out, in, PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N); + memcpy(out, in, SPX_WOTS_LEN * SPX_N); - /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_WOTS_W; i++) { - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_set_hash_addr(addr, i); - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_thash_1(out, out, pub_seed, addr, state_seeded); + /* Sort the chains in reverse order by steps using counting sort. */ + for (i = 0; i < SPX_WOTS_LEN; i++) { + counts[steps[i]]++; + } + total = 0; + for (l = SPX_WOTS_W - 1; l >= 0; l--) { + newTotal = counts[l] + total; + counts[l] = total; + total = newTotal; + } + for (i = 0; i < SPX_WOTS_LEN; i++) { + idxs[counts[steps[i]]] = (uint16_t)i; + counts[steps[i]]++; } -} -/** - * 4-way parallel version of gen_chain; expects 4x as much space in out, and - * 4x as much space in inx4. Assumes start and step identical across chains. - */ -static void gen_chainx4(unsigned char *outx4, const unsigned char *inx4, - unsigned int start, unsigned int steps, - const unsigned char *pub_seed, uint32_t addrx4[4 * 8], - const hash_state *state_seeded) { - uint32_t i; - unsigned int j; + /* We got our work cut out for us: do it! */ + for (i = 0; i < SPX_WOTS_LEN; i += 4) { + for (j = 0; j < 4 && i + j < SPX_WOTS_LEN; j++) { + idx = idxs[i + j]; + set_chain_addr(addrs + j * 8, idx); + bufs[j] = out + SPX_N * idx; + } - /* Initialize outx4 with the value at position 'start'. */ - memcpy(outx4, inx4, 4 * PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N); + /* As the chains are sorted in reverse order, we know that the first + * chain is the longest and the last one is the shortest. We keep + * an eye on whether the last chain is done and then on the one before, + * et cetera. */ + watching = 3; + done = 0; + while (i + watching >= SPX_WOTS_LEN) { + bufs[watching] = &empty[0]; + watching--; + } - /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_WOTS_W; i++) { - for (j = 0; j < 4; j++) { - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_set_hash_addr(addrx4 + j * 8, i); + for (k = 0;; k++) { + while (k == steps[idxs[i + watching]]) { + bufs[watching] = &empty[0]; + if (watching == 0) { + done = 1; + break; + } + watching--; + } + if (done) { + break; + } + for (j = 0; j < watching + 1; j++) { + set_hash_addr(addrs + j * 8, k + start[idxs[i + j]]); + } + + thashx4(bufs[0], bufs[1], bufs[2], bufs[3], + bufs[0], bufs[1], bufs[2], bufs[3], 1, ctx, addrs); } - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_thashx4_1(outx4 + 0 * PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N, - outx4 + 1 * PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N, - outx4 + 2 * PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N, - outx4 + 3 * PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N, - outx4 + 0 * PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N, - outx4 + 1 * PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N, - outx4 + 2 * PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N, - outx4 + 3 * PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N, - pub_seed, addrx4, - state_seeded); } } @@ -109,7 +107,8 @@ static void gen_chainx4(unsigned char *outx4, const unsigned char *inx4, * Interprets an array of bytes as integers in base w. * This only works when log_w is a divisor of 8. */ -static void base_w(unsigned int *output, const int out_len, const unsigned char *input) { +static void base_w(unsigned int *output, const int out_len, + const unsigned char *input) { int in = 0; int out = 0; unsigned char total = 0; @@ -122,119 +121,149 @@ static void base_w(unsigned int *output, const int out_len, const unsigned char in++; bits += 8; } - bits -= PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_WOTS_LOGW; - output[out] = (unsigned int)(total >> bits) & (PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_WOTS_W - 1); + bits -= SPX_WOTS_LOGW; + output[out] = (total >> bits) & (SPX_WOTS_W - 1); out++; } } /* Computes the WOTS+ checksum over a message (in base_w). */ -static void wots_checksum(unsigned int *csum_base_w, const unsigned int *msg_base_w) { +static void wots_checksum(unsigned int *csum_base_w, + const unsigned int *msg_base_w) { unsigned int csum = 0; - unsigned char csum_bytes[(PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_WOTS_LEN2 * PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_WOTS_LOGW + 7) / 8]; + unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; unsigned int i; /* Compute checksum. */ - for (i = 0; i < PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_WOTS_LEN1; i++) { - csum += PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_WOTS_W - 1 - msg_base_w[i]; + for (i = 0; i < SPX_WOTS_LEN1; i++) { + csum += SPX_WOTS_W - 1 - msg_base_w[i]; } /* Convert checksum to base_w. */ /* Make sure expected empty zero bits are the least significant bits. */ - csum = csum << (8 - ((PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_WOTS_LEN2 * PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_WOTS_LOGW) % 8)); - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); - base_w(csum_base_w, PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_WOTS_LEN2, csum_bytes); + csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); + ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); + base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); } /* Takes a message and derives the matching chain lengths. */ -static void chain_lengths(unsigned int *lengths, const unsigned char *msg) { - base_w(lengths, PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_WOTS_LEN1, msg); - wots_checksum(lengths + PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_WOTS_LEN1, lengths); +void chain_lengths(unsigned int *lengths, const unsigned char *msg) { + base_w(lengths, SPX_WOTS_LEN1, msg); + wots_checksum(lengths + SPX_WOTS_LEN1, lengths); } /** - * WOTS key generation. Takes a 32 byte sk_seed, expands it to WOTS private key - * elements and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. * * Writes the computed public key to 'pk'. */ -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_wots_gen_pk(unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *state_seeded) { +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]) { + unsigned int steps[SPX_WOTS_LEN]; + unsigned int start[SPX_WOTS_LEN]; uint32_t i; - unsigned int j; - uint32_t addrx4[4 * 8]; - unsigned char pkbuf[4 * PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N]; + chain_lengths(start, msg); - for (j = 0; j < 4; j++) { - memcpy(addrx4 + j * 8, addr, sizeof(uint32_t) * 8); - } - - /* The last iteration typically does not have complete set of 4 chains, - but because we use pkbuf, this is not an issue -- we still do as many - in parallel as possible. */ - for (i = 0; i < ((PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_WOTS_LEN + 3) & ~0x3); i += 4) { - for (j = 0; j < 4; j++) { - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_set_chain_addr(addrx4 + j * 8, i + j); - } - wots_gen_skx4(pkbuf, sk_seed, addrx4, state_seeded); - gen_chainx4(pkbuf, pkbuf, 0, PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_WOTS_W - 1, pub_seed, addrx4, state_seeded); - for (j = 0; j < 4; j++) { - if (i + j < PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_WOTS_LEN) { - memcpy(pk + (i + j)*PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N, pkbuf + j * PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N, PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N); - } - } + for (i = 0; i < SPX_WOTS_LEN; i++) { + steps[i] = SPX_WOTS_W - 1 - start[i]; } - // Get rid of unused argument variable. - (void)state_seeded; + gen_chains(pk, sig, start, steps, ctx, addr); } -/** - * Takes a n-byte message and the 32-byte sk_see to compute a signature 'sig'. +/* + * This generates 4 sequential WOTS public keys + * It also generates the WOTS signature if leaf_info indicates + * that we're signing with one of these WOTS keys */ -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_wots_sign(unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); +void wots_gen_leafx4(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info) { + struct leaf_info_x4 *info = v_info; + uint32_t *leaf_addr = info->leaf_addr; + uint32_t *pk_addr = info->pk_addr; + unsigned int i, j, k; + unsigned char pk_buffer[ 4 * SPX_WOTS_BYTES ]; + unsigned wots_offset = SPX_WOTS_BYTES; + unsigned char *buffer; + uint32_t wots_k_mask; + unsigned wots_sign_index; + + if (((leaf_idx ^ info->wots_sign_leaf) & ~3U) == 0) { + /* We're traversing the leaf that's signing; generate the WOTS */ + /* signature */ + wots_k_mask = 0; + wots_sign_index = info->wots_sign_leaf & 3; /* Which of of the 4 */ + /* 4 slots do the signatures come from */ + } else { + /* Nope, we're just generating pk's; turn off the signature logic */ + wots_k_mask = (uint32_t)~0; + wots_sign_index = 0; + } - for (i = 0; i < PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_WOTS_LEN; i++) { - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_set_chain_addr(addr, i); - wots_gen_sk(sig + i * PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N, sk_seed, addr, state_seeded); - gen_chain(sig + i * PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N, sig + i * PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N, 0, lengths[i], pub_seed, addr, state_seeded); + for (j = 0; j < 4; j++) { + set_keypair_addr( leaf_addr + j * 8, leaf_idx + j ); + set_keypair_addr( pk_addr + j * 8, leaf_idx + j ); } - // avoid unused argument - (void)state_seeded; -} + for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { + uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k to */ + /* the step if we're generating a signature, ~0 if we're not */ -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_WOTS_LEN]; - uint32_t i; + /* Start with the secret seed */ + for (j = 0; j < 4; j++) { + set_chain_addr(leaf_addr + j * 8, i); + set_hash_addr(leaf_addr + j * 8, 0); + set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTSPRF); + } + prf_addrx4(buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + buffer + 2 * wots_offset, + buffer + 3 * wots_offset, + ctx, leaf_addr); - chain_lengths(lengths, msg); + for (j = 0; j < 4; j++) { + set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTS); + } + + /* Iterate down the WOTS chain */ + for (k = 0;; k++) { + /* Check if one of the values we have needs to be saved as a */ + /* part of the WOTS signature */ + if (k == wots_k) { + memcpy( info->wots_sig + i * SPX_N, + buffer + wots_sign_index * wots_offset, SPX_N ); + } - for (i = 0; i < PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_WOTS_LEN; i++) { - PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_set_chain_addr(addr, i); - gen_chain(pk + i * PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N, sig + i * PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_N, - lengths[i], PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_WOTS_W - 1 - lengths[i], pub_seed, addr, - state_seeded); + /* Check if we hit the top of the chain */ + if (k == SPX_WOTS_W - 1) { + break; + } + + /* Iterate one step on all 4 chains */ + for (j = 0; j < 4; j++) { + set_hash_addr(leaf_addr + j * 8, k); + } + thashx4(buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + buffer + 2 * wots_offset, + buffer + 3 * wots_offset, + buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + buffer + 2 * wots_offset, + buffer + 3 * wots_offset, 1, ctx, leaf_addr); + } } - // avoid unused argument - (void)state_seeded; + /* Do the final thash to generate the public keys */ + thashx4(dest + 0 * SPX_N, + dest + 1 * SPX_N, + dest + 2 * SPX_N, + dest + 3 * SPX_N, + pk_buffer + 0 * wots_offset, + pk_buffer + 1 * wots_offset, + pk_buffer + 2 * wots_offset, + pk_buffer + 3 * wots_offset, SPX_WOTS_LEN, ctx, pk_addr); } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/wots.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/wots.h index 7bf3f4d1ed..4e7692eeef 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/wots.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/wots.h @@ -1,41 +1,25 @@ -#ifndef PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_WOTS_H -#define PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_WOTS_H +#ifndef SPX_WOTS_H +#define SPX_WOTS_H -#include "hash_state.h" -#include "params.h" #include -/** - * WOTS key generation. Takes a 32 byte seed for the private key, expands it to - * a full WOTS private key and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_wots_gen_pk( - unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -/** - * Takes a n-byte message and the 32-byte seed for the private key to compute a - * signature that is placed at 'sig'. - */ -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_wots_sign( - unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *hash_state_seeded); +#include "context.h" +#include "params.h" /** * Takes a WOTS signature and an n-byte message, computes a WOTS public key. * * Writes the computed public key to 'pk'. */ -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_wots_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); +#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]); + +/* + * Compute the chain lengths needed for a given message hash + */ +#define chain_lengths SPX_NAMESPACE(chain_lengths) +void chain_lengths(unsigned int *lengths, const unsigned char *msg); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/wotsx4.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/wotsx4.h new file mode 100644 index 0000000000..cd634f1743 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/wotsx4.h @@ -0,0 +1,41 @@ +#ifndef WOTSX4_H_ +#define WOTSX4_H_ + +#include + +#include "params.h" + +/* + * This is here to provide an interface to the internal wots_gen_leafx4 + * routine. While this routine is not referenced in the package outside of + * wots.c, it is called from the stand-alone benchmark code to characterize + * the performance + */ +struct leaf_info_x4 { + unsigned char *wots_sig; + uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ + uint32_t *wots_steps; + uint32_t leaf_addr[4 * 8]; + uint32_t pk_addr[4 * 8]; +}; + +/* Macro to set the leaf_info to something 'benign', that is, it would */ +/* run with the same time as it does during the real signing process */ +/* Used only by the benchmark code */ +#define INITIALIZE_LEAF_INFO_X4(info, addr, step_buffer) { \ + (info).wots_sig = 0; \ + (info).wots_sign_leaf = ~0; \ + (info).wots_steps = step_buffer; \ + int i; \ + for (i=0; i<4; i++) { \ + memcpy( &(info).leaf_addr[8*i], addr, 32 ); \ + memcpy( &(info).pk_addr[8*i], addr, 32 ); \ + } \ + } + +#define wots_gen_leafx4 SPX_NAMESPACE(wots_gen_leafx4) +void wots_gen_leafx4(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info); + +#endif /* WOTSX4_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/address.c b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/address.c index 89206539b0..b956e9cb29 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/address.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/address.c @@ -1,78 +1,91 @@ #include +#include #include "address.h" #include "params.h" #include "utils.h" -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]) { - int i; - - for (i = 0; i < 8; i++) { - PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_ull_to_bytes( - bytes + i * 4, 4, addr[i]); - } -} - -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_set_layer_addr( - uint32_t addr[8], uint32_t layer) { - addr[0] = layer; +/* + * Specify which level of Merkle tree (the "layer") we're working on + */ +void set_layer_addr(uint32_t addr[8], uint32_t layer) { + ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; } -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_set_tree_addr( - uint32_t addr[8], uint64_t tree) { - addr[1] = 0; - addr[2] = (uint32_t) (tree >> 32); - addr[3] = (uint32_t) tree; +/* + * Specify which Merkle tree within the level (the "tree address") we're working on + */ +void set_tree_addr(uint32_t addr[8], uint64_t tree) { + ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); } -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_set_type( - uint32_t addr[8], uint32_t type) { - addr[4] = type; +/* + * Specify the reason we'll use this address structure for, that is, what + * hash will we compute with it. This is used so that unrelated types of + * hashes don't accidentally get the same address structure. The type will be + * one of the SPX_ADDR_TYPE constants + */ +void set_type(uint32_t addr[8], uint32_t type) { + ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; } -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; +/* + * Copy the layer and tree fields of the address structure. This is used + * when we're doing multiple types of hashes within the same Merkle tree + */ +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); } /* These functions are used for OTS addresses. */ -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_set_keypair_addr( - uint32_t addr[8], uint32_t keypair) { - addr[5] = keypair; +/* + * Specify which Merkle leaf we're working on; that is, which OTS keypair + * we're talking about. + */ +void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { + ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; } -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; - out[5] = in[5]; +/* + * Copy the layer, tree and keypair fields of the address structure. This is + * used when we're doing multiple things within the same OTS keypair + */ +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); + ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; } -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_set_chain_addr( - uint32_t addr[8], uint32_t chain) { - addr[6] = chain; +/* + * Specify which Merkle chain within the OTS we're working with + * (the chain address) + */ +void set_chain_addr(uint32_t addr[8], uint32_t chain) { + ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; } -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_set_hash_addr( - uint32_t addr[8], uint32_t hash) { - addr[7] = hash; +/* + * Specify where in the Merkle chain we are +* (the hash address) + */ +void set_hash_addr(uint32_t addr[8], uint32_t hash) { + ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; } /* These functions are used for all hash tree addresses (including FORS). */ -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_set_tree_height( - uint32_t addr[8], uint32_t tree_height) { - addr[6] = tree_height; +/* + * Specify the height of the node in the Merkle/FORS tree we are in + * (the tree height) + */ +void set_tree_height(uint32_t addr[8], uint32_t tree_height) { + ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; } -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_set_tree_index( - uint32_t addr[8], uint32_t tree_index) { - addr[7] = tree_index; +/* + * Specify the distance from the left edge of the node in the Merkle/FORS tree + * (the tree index) + */ +void set_tree_index(uint32_t addr[8], uint32_t tree_index) { + u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/address.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/address.h index 23870ee71e..24a84eb40c 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/address.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/address.h @@ -1,50 +1,52 @@ -#ifndef PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_ADDRESS_H -#define PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_ADDRESS_H +#ifndef SPX_ADDRESS_H +#define SPX_ADDRESS_H #include -#define PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_ADDR_TYPE_WOTS 0 -#define PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_ADDR_TYPE_WOTSPK 1 -#define PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_ADDR_TYPE_HASHTREE 2 -#define PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_ADDR_TYPE_FORSTREE 3 -#define PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_ADDR_TYPE_FORSPK 4 +#include "params.h" -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]); +/* The hash types that are passed to set_type */ +#define SPX_ADDR_TYPE_WOTS 0 +#define SPX_ADDR_TYPE_WOTSPK 1 +#define SPX_ADDR_TYPE_HASHTREE 2 +#define SPX_ADDR_TYPE_FORSTREE 3 +#define SPX_ADDR_TYPE_FORSPK 4 +#define SPX_ADDR_TYPE_WOTSPRF 5 +#define SPX_ADDR_TYPE_FORSPRF 6 -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_set_layer_addr( - uint32_t addr[8], uint32_t layer); +#define set_layer_addr SPX_NAMESPACE(set_layer_addr) +void set_layer_addr(uint32_t addr[8], uint32_t layer); -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_set_tree_addr( - uint32_t addr[8], uint64_t tree); +#define set_tree_addr SPX_NAMESPACE(set_tree_addr) +void set_tree_addr(uint32_t addr[8], uint64_t tree); -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_set_type( - uint32_t addr[8], uint32_t type); +#define set_type SPX_NAMESPACE(set_type) +void set_type(uint32_t addr[8], uint32_t type); /* Copies the layer and tree part of one address into the other */ -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]); +#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); /* These functions are used for WOTS and FORS addresses. */ -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_set_keypair_addr( - uint32_t addr[8], uint32_t keypair); +#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) +void set_keypair_addr(uint32_t addr[8], uint32_t keypair); -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_set_chain_addr( - uint32_t addr[8], uint32_t chain); +#define set_chain_addr SPX_NAMESPACE(set_chain_addr) +void set_chain_addr(uint32_t addr[8], uint32_t chain); -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_set_hash_addr( - uint32_t addr[8], uint32_t hash); +#define set_hash_addr SPX_NAMESPACE(set_hash_addr) +void set_hash_addr(uint32_t addr[8], uint32_t hash); -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]); +#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); /* These functions are used for all hash tree addresses (including FORS). */ -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_set_tree_height( - uint32_t addr[8], uint32_t tree_height); +#define set_tree_height SPX_NAMESPACE(set_tree_height) +void set_tree_height(uint32_t addr[8], uint32_t tree_height); -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_set_tree_index( - uint32_t addr[8], uint32_t tree_index); +#define set_tree_index SPX_NAMESPACE(set_tree_index) +void set_tree_index(uint32_t addr[8], uint32_t tree_index); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/api.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/api.h index 99ef1ee67c..50690ddb7c 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/api.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/api.h @@ -4,15 +4,13 @@ #include #include - - -#define PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_CRYPTO_ALGNAME "SPHINCS+" +#define PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_CRYPTO_ALGNAME "SPHINCS+-haraka-256s-simple" #define PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_CRYPTO_SECRETKEYBYTES 128 #define PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_CRYPTO_PUBLICKEYBYTES 64 -#define PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_CRYPTO_BYTES 29792 -#define PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_CRYPTO_SEEDBYTES 96 +#define PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_CRYPTO_BYTES 29792 +#define PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_CRYPTO_SEEDBYTES 96 /* * Returns the length of a secret key, in bytes @@ -39,43 +37,41 @@ size_t PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_crypto_sign_seedbytes(void); * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] * Format pk: [root || PUB_SEED] */ -int PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed); +int PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); /* * Generates a SPHINCS+ key pair. * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] * Format pk: [root || PUB_SEED] */ -int PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk); +int PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); /** * Returns an array containing a detached signature. */ -int PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk); +int PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); /** * Verifies a detached signature and message under a given public key. */ -int PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk); +int PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, + const uint8_t *pk); /** * Returns an array containing the signature followed by the message. */ -int PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk); +int PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); /** * Verifies a given signature-message pair under a given public key. */ -int PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk); - +int PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/context.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/context.h new file mode 100644 index 0000000000..600dfb73c7 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/context.h @@ -0,0 +1,24 @@ +#ifndef SPX_CONTEXT_H +#define SPX_CONTEXT_H + +#include +#include + +#include "params.h" + +typedef struct { + uint8_t pub_seed[SPX_N]; + uint8_t sk_seed[SPX_N]; + + + uint64_t tweaked512_rc64[10][8]; + uint32_t tweaked256_rc32[10][8]; +} spx_ctx; + +#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) +void initialize_hash_function(spx_ctx *ctx); + +#define free_hash_function SPX_NAMESPACE(free_hash_function) +void free_hash_function(spx_ctx *ctx); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/context_haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/context_haraka.c new file mode 100644 index 0000000000..f1cd7e3664 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/context_haraka.c @@ -0,0 +1,11 @@ +#include "context.h" +#include "haraka.h" + +void initialize_hash_function(spx_ctx *ctx) { + tweak_constants(ctx); +} + +// we don't support heap-based haraka right now +void free_hash_function(spx_ctx *ctx) { + (void)ctx; // suppress unused variable warnings +} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/fors.c b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/fors.c index 41db5d2f80..96ca72e986 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/fors.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/fors.c @@ -2,58 +2,58 @@ #include #include -#include "address.h" #include "fors.h" + +#include "address.h" #include "hash.h" -#include "hash_state.h" #include "thash.h" #include "utils.h" +#include "utilsx1.h" -static void fors_gen_sk(unsigned char *sk, const unsigned char *sk_seed, - uint32_t fors_leaf_addr[8], const hash_state *hash_state_seeded) { - PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_prf_addr( - sk, sk_seed, fors_leaf_addr, hash_state_seeded); +static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + prf_addr(sk, ctx, fors_leaf_addr); } static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, - const unsigned char *pub_seed, - uint32_t fors_leaf_addr[8], - const hash_state *hash_state_seeded) { - PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_thash_1( - leaf, sk, pub_seed, fors_leaf_addr, hash_state_seeded); + const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + thash(leaf, sk, 1, ctx, fors_leaf_addr); } -static void fors_gen_leaf(unsigned char *leaf, const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx, const uint32_t fors_tree_addr[8], - const hash_state *hash_state_seeded) { - uint32_t fors_leaf_addr[8] = {0}; - - /* Only copy the parts that must be kept in fors_leaf_addr. */ - PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_copy_keypair_addr( - fors_leaf_addr, fors_tree_addr); - PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_set_type( - fors_leaf_addr, PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_set_tree_index( - fors_leaf_addr, addr_idx); - - fors_gen_sk(leaf, sk_seed, fors_leaf_addr, hash_state_seeded); - fors_sk_to_leaf(leaf, leaf, pub_seed, fors_leaf_addr, hash_state_seeded); +struct fors_gen_leaf_info { + uint32_t leaf_addrx[8]; +}; + +static void fors_gen_leafx1(unsigned char *leaf, + const spx_ctx *ctx, + uint32_t addr_idx, void *info) { + struct fors_gen_leaf_info *fors_info = info; + uint32_t *fors_leaf_addr = fors_info->leaf_addrx; + + /* Only set the parts that the caller doesn't set */ + set_tree_index(fors_leaf_addr, addr_idx); + set_type(fors_leaf_addr, SPX_ADDR_TYPE_FORSPRF); + fors_gen_sk(leaf, ctx, fors_leaf_addr); + + set_type(fors_leaf_addr, SPX_ADDR_TYPE_FORSTREE); + fors_sk_to_leaf(leaf, leaf, + ctx, fors_leaf_addr); } /** - * Interprets m as PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_FORS_HEIGHT-bit unsigned integers. - * Assumes m contains at least PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_FORS_TREES bits. - * Assumes indices has space for PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_FORS_TREES integers. + * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + * Assumes indices has space for SPX_FORS_TREES integers. */ static void message_to_indices(uint32_t *indices, const unsigned char *m) { unsigned int i, j; unsigned int offset = 0; - for (i = 0; i < PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_FORS_TREES; i++) { + for (i = 0; i < SPX_FORS_TREES; i++) { indices[i] = 0; - for (j = 0; j < PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_FORS_HEIGHT; j++) { - indices[i] ^= (((uint32_t)m[offset >> 3] >> (offset & 0x7)) & 0x1) << j; + for (j = 0; j < SPX_FORS_HEIGHT; j++) { + indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); offset++; } } @@ -61,55 +61,51 @@ static void message_to_indices(uint32_t *indices, const unsigned char *m) { /** * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_FORS_TREES bits. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. */ -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_fors_sign( - unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *hash_state_seeded) { - uint32_t indices[PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_FORS_TREES]; - unsigned char roots[PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_FORS_TREES * PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_N]; +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; uint32_t fors_tree_addr[8] = {0}; + struct fors_gen_leaf_info fors_info = {0}; + uint32_t *fors_leaf_addr = fors_info.leaf_addrx; uint32_t fors_pk_addr[8] = {0}; uint32_t idx_offset; unsigned int i; - PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_copy_keypair_addr( - fors_tree_addr, fors_addr); - PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_copy_keypair_addr( - fors_pk_addr, fors_addr); + copy_keypair_addr(fors_tree_addr, fors_addr); + copy_keypair_addr(fors_leaf_addr, fors_addr); - PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_set_type( - fors_tree_addr, PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_set_type( - fors_pk_addr, PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_ADDR_TYPE_FORSPK); + copy_keypair_addr(fors_pk_addr, fors_addr); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); message_to_indices(indices, m); - for (i = 0; i < PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_FORS_TREES; i++) { - idx_offset = i * (1 << PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_FORS_HEIGHT); + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); - PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_set_tree_height( - fors_tree_addr, 0); - PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_set_tree_index( - fors_tree_addr, indices[i] + idx_offset); + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); /* Include the secret key part that produces the selected leaf node. */ - fors_gen_sk(sig, sk_seed, fors_tree_addr, hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_N; + fors_gen_sk(sig, ctx, fors_tree_addr); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + sig += SPX_N; /* Compute the authentication path for this leaf node. */ - PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_treehash_FORS_HEIGHT( - roots + i * PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_N, sig, sk_seed, pub_seed, - indices[i], idx_offset, fors_gen_leaf, fors_tree_addr, - hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_N * PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_FORS_HEIGHT; + treehashx1(roots + i * SPX_N, sig, ctx, + indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx1, + fors_tree_addr, &fors_info); + + sig += SPX_N * SPX_FORS_HEIGHT; } /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_thash_FORS_TREES( - pk, roots, pub_seed, fors_pk_addr, hash_state_seeded); + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); } /** @@ -117,45 +113,44 @@ void PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_fors_sign( * This can be used for verification by comparing to a known public key, or to * subsequently verify a signature on the derived public key. The latter is the * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_FORS_TREES bits. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. */ -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_fors_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, const uint32_t fors_addr[8], - const hash_state *hash_state_seeded) { - uint32_t indices[PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_FORS_TREES]; - unsigned char roots[PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_FORS_TREES * PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_N]; - unsigned char leaf[PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_N]; +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + unsigned char leaf[SPX_N]; uint32_t fors_tree_addr[8] = {0}; uint32_t fors_pk_addr[8] = {0}; uint32_t idx_offset; unsigned int i; - PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_copy_keypair_addr(fors_tree_addr, fors_addr); - PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_copy_keypair_addr(fors_pk_addr, fors_addr); + copy_keypair_addr(fors_tree_addr, fors_addr); + copy_keypair_addr(fors_pk_addr, fors_addr); - PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_set_type(fors_tree_addr, PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_set_type(fors_pk_addr, PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_ADDR_TYPE_FORSPK); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); message_to_indices(indices, m); - for (i = 0; i < PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_FORS_TREES; i++) { - idx_offset = i * (1 << PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_FORS_HEIGHT); + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); - PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_set_tree_height(fors_tree_addr, 0); - PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_set_tree_index(fors_tree_addr, indices[i] + idx_offset); + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); /* Derive the leaf from the included secret key part. */ - fors_sk_to_leaf(leaf, sig, pub_seed, fors_tree_addr, hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_N; + fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); + sig += SPX_N; /* Derive the corresponding root node of this tree. */ - PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_compute_root(roots + i * PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_N, leaf, indices[i], idx_offset, sig, - PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_FORS_HEIGHT, pub_seed, fors_tree_addr, hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_N * PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_FORS_HEIGHT; + compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, + sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); + sig += SPX_N * SPX_FORS_HEIGHT; } /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_thash_FORS_TREES(pk, roots, pub_seed, fors_pk_addr, hash_state_seeded); + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/fors.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/fors.h index 6417d555a2..509140a178 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/fors.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/fors.h @@ -1,32 +1,32 @@ -#ifndef PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_FORS_H -#define PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_FORS_H +#ifndef SPX_FORS_H +#define SPX_FORS_H #include -#include "hash_state.h" +#include "context.h" #include "params.h" /** * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_FORS_TREES bits. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. */ -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_fors_sign( - unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *hash_state_seeded); +#define fors_sign SPX_NAMESPACE(fors_sign) +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); /** * Derives the FORS public key from a signature. * This can be used for verification by comparing to a known public key, or to * subsequently verify a signature on the derived public key. The latter is the * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_FORS_TREES bits. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. */ -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_fors_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, const uint32_t fors_addr[8], - const hash_state *hash_state_seeded); +#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/haraka.c index b8b9c44991..a4944913b5 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/haraka.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/haraka.c @@ -6,12 +6,13 @@ * by Thomas Pornin */ -#include #include +#include #include #include #include "haraka.h" +#include "utils.h" #define HARAKAS_RATE 32 @@ -656,76 +657,62 @@ static void interleave_constant32(uint32_t *out, const unsigned char *in) { br_aes_ct_ortho(out); } -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_tweak_constants( - harakactx *state, - const unsigned char *pk_seed, const unsigned char *sk_seed, - unsigned long long seed_length) { +void tweak_constants(spx_ctx *ctx) { unsigned char buf[40 * 16]; int i; /* Use the standard constants to generate tweaked ones. */ - memcpy((uint8_t *)state->tweaked512_rc64, (uint8_t *)haraka512_rc64, 40 * 16); - - /* Constants for sk.seed */ - if (sk_seed != NULL) { - PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_haraka_S( - buf, 40 * 16, sk_seed, seed_length, state); - - /* Interleave constants */ - for (i = 0; i < 10; i++) { - interleave_constant32(state->tweaked256_rc32_sseed[i], buf + 32 * i); - } - } + memcpy((uint8_t *)ctx->tweaked512_rc64, (uint8_t *)haraka512_rc64, 40 * 16); /* Constants for pk.seed */ - PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_haraka_S( - buf, 40 * 16, pk_seed, seed_length, state); + haraka_S(buf, 40 * 16, ctx->pub_seed, SPX_N, ctx); for (i = 0; i < 10; i++) { - interleave_constant32(state->tweaked256_rc32[i], buf + 32 * i); - interleave_constant(state->tweaked512_rc64[i], buf + 64 * i); + interleave_constant32(ctx->tweaked256_rc32[i], buf + 32 * i); + interleave_constant(ctx->tweaked512_rc64[i], buf + 64 * i); } } -static void haraka_S_absorb(unsigned char *s, +static void haraka_S_absorb(unsigned char *s, unsigned int r, const unsigned char *m, unsigned long long mlen, - unsigned char p, const harakactx *state) { + unsigned char p, const spx_ctx *ctx) { unsigned long long i; - unsigned char t[HARAKAS_RATE]; + PQCLEAN_VLA(uint8_t, t, r); - while (mlen >= HARAKAS_RATE) { + while (mlen >= r) { /* XOR block to state */ - for (i = 0; i < HARAKAS_RATE; ++i) { + for (i = 0; i < r; ++i) { s[i] ^= m[i]; } - PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_haraka512_perm(s, s, state); - mlen -= HARAKAS_RATE; - m += HARAKAS_RATE; + haraka512_perm(s, s, ctx); + mlen -= r; + m += r; } - for (i = 0; i < HARAKAS_RATE; ++i) { + for (i = 0; i < r; ++i) { t[i] = 0; } for (i = 0; i < mlen; ++i) { t[i] = m[i]; } t[i] = p; - t[HARAKAS_RATE - 1] |= 128; - for (i = 0; i < HARAKAS_RATE; ++i) { + t[r - 1] |= 128; + for (i = 0; i < r; ++i) { s[i] ^= t[i]; } } static void haraka_S_squeezeblocks(unsigned char *h, unsigned long long nblocks, - unsigned char *s, const harakactx *state) { + unsigned char *s, unsigned int r, + const spx_ctx *ctx) { while (nblocks > 0) { - PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_haraka512_perm(s, s, state); + haraka512_perm(s, s, ctx); memcpy(h, s, HARAKAS_RATE); - h += HARAKAS_RATE; + h += r; nblocks--; } } -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_haraka_S_inc_init(uint8_t *s_inc) { +void haraka_S_inc_init(uint8_t *s_inc) { size_t i; for (i = 0; i < 64; i++) { @@ -734,7 +721,8 @@ void PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_haraka_S_inc_init(uint8_t *s_inc) { s_inc[64] = 0; } -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, const harakactx *state) { +void haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, + const spx_ctx *ctx) { size_t i; /* Recall that s_inc[64] is the non-absorbed bytes xored into the state */ @@ -745,19 +733,19 @@ void PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_haraka_S_inc_absorb(uint8_t *s_inc, c s_inc[s_inc[64] + i] ^= m[i]; } mlen -= (size_t)(HARAKAS_RATE - s_inc[64]); - m += HARAKAS_RATE - s_inc[64]; + m += HARAKAS_RATE - (uint8_t)s_inc[64]; s_inc[64] = 0; - PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_haraka512_perm(s_inc, s_inc, state); + haraka512_perm(s_inc, s_inc, ctx); } for (i = 0; i < mlen; i++) { s_inc[s_inc[64] + i] ^= m[i]; } - s_inc[64] = (uint8_t)(mlen + s_inc[64]); + s_inc[64] += (uint8_t)mlen; } -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_haraka_S_inc_finalize(uint8_t *s_inc) { +void haraka_S_inc_finalize(uint8_t *s_inc) { /* After haraka_S_inc_absorb, we are guaranteed that s_inc[64] < HARAKAS_RATE, so we can always use one more byte for p in the current state. */ s_inc[s_inc[64]] ^= 0x1F; @@ -765,22 +753,23 @@ void PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_haraka_S_inc_finalize(uint8_t *s_inc) s_inc[64] = 0; } -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, const harakactx *state) { - uint8_t i; +void haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, + const spx_ctx *ctx) { + size_t i; /* First consume any bytes we still have sitting around */ for (i = 0; i < outlen && i < s_inc[64]; i++) { /* There are s_inc[64] bytes left, so r - s_inc[64] is the first available byte. We consume from there, i.e., up to r. */ - out[i] = s_inc[(HARAKAS_RATE - s_inc[64] + i)]; + out[i] = (uint8_t)s_inc[(HARAKAS_RATE - s_inc[64] + i)]; } out += i; outlen -= i; - s_inc[64] = (uint8_t)(s_inc[64] - i); + s_inc[64] -= (uint8_t)i; /* Then squeeze the remaining necessary blocks */ while (outlen > 0) { - PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_haraka512_perm(s_inc, s_inc, state); + haraka512_perm(s_inc, s_inc, ctx); for (i = 0; i < outlen && i < HARAKAS_RATE; i++) { out[i] = s_inc[i]; @@ -791,7 +780,9 @@ void PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_haraka_S_inc_squeeze(uint8_t *out, si } } -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_haraka_S(unsigned char *out, unsigned long long outlen, const unsigned char *in, unsigned long long inlen, const harakactx *state) { +void haraka_S(unsigned char *out, unsigned long long outlen, + const unsigned char *in, unsigned long long inlen, + const spx_ctx *ctx) { unsigned long long i; unsigned char s[64]; unsigned char d[32]; @@ -799,20 +790,21 @@ void PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_haraka_S(unsigned char *out, unsigned for (i = 0; i < 64; i++) { s[i] = 0; } - haraka_S_absorb(s, in, inlen, 0x1F, state); + haraka_S_absorb(s, 32, in, inlen, 0x1F, ctx); - haraka_S_squeezeblocks(out, outlen / 32, s, state); + haraka_S_squeezeblocks(out, outlen / 32, s, 32, ctx); out += (outlen / 32) * 32; if (outlen % 32) { - haraka_S_squeezeblocks(d, 1, s, state); + haraka_S_squeezeblocks(d, 1, s, 32, ctx); for (i = 0; i < outlen % 32; i++) { out[i] = d[i]; } } } -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_haraka512_perm(unsigned char *out, const unsigned char *in, const harakactx *state) { +void haraka512_perm(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx) { uint32_t w[16]; uint64_t q[8], tmp_q; unsigned int i, j; @@ -829,7 +821,7 @@ void PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_haraka512_perm(unsigned char *out, co br_aes_ct64_bitslice_Sbox(q); shift_rows(q); mix_columns(q); - add_round_key(q, state->tweaked512_rc64[2 * i + j]); + add_round_key(q, ctx->tweaked512_rc64[2 * i + j]); } /* Mix states */ for (j = 0; j < 8; j++) { @@ -857,12 +849,12 @@ void PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_haraka512_perm(unsigned char *out, co br_range_enc32le(out, w, 16); } -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_haraka512(unsigned char *out, const unsigned char *in, const harakactx *state) { +void haraka512(unsigned char *out, const unsigned char *in, const spx_ctx *ctx) { int i; unsigned char buf[64]; - PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_haraka512_perm(buf, in, state); + haraka512_perm(buf, in, ctx); /* Feed-forward */ for (i = 0; i < 64; i++) { buf[i] = buf[i] ^ in[i]; @@ -876,50 +868,8 @@ void PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_haraka512(unsigned char *out, const u } -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_haraka256(unsigned char *out, const unsigned char *in, const harakactx *state) { - uint32_t q[8], tmp_q; - int i, j; - - for (i = 0; i < 4; i++) { - q[2 * i] = br_dec32le(in + 4 * i); - q[2 * i + 1] = br_dec32le(in + 4 * i + 16); - } - br_aes_ct_ortho(q); - - /* AES rounds */ - for (i = 0; i < 5; i++) { - for (j = 0; j < 2; j++) { - br_aes_ct_bitslice_Sbox(q); - shift_rows32(q); - mix_columns32(q); - add_round_key32(q, state->tweaked256_rc32[2 * i + j]); - } - - /* Mix states */ - for (j = 0; j < 8; j++) { - tmp_q = q[j]; - q[j] = (tmp_q & 0x81818181) | - (tmp_q & 0x02020202) << 1 | - (tmp_q & 0x04040404) << 2 | - (tmp_q & 0x08080808) << 3 | - (tmp_q & 0x10101010) >> 3 | - (tmp_q & 0x20202020) >> 2 | - (tmp_q & 0x40404040) >> 1; - } - } - - br_aes_ct_ortho(q); - for (i = 0; i < 4; i++) { - br_enc32le(out + 4 * i, q[2 * i]); - br_enc32le(out + 4 * i + 16, q[2 * i + 1]); - } - - for (i = 0; i < 32; i++) { - out[i] ^= in[i]; - } -} - -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_haraka256_sk(unsigned char *out, const unsigned char *in, const harakactx *state) { +void haraka256(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx) { uint32_t q[8], tmp_q; int i, j; @@ -935,7 +885,7 @@ void PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_haraka256_sk(unsigned char *out, cons br_aes_ct_bitslice_Sbox(q); shift_rows32(q); mix_columns32(q); - add_round_key32(q, state->tweaked256_rc32_sseed[2 * i + j]); + add_round_key32(q, ctx->tweaked256_rc32[2 * i + j]); } /* Mix states */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/haraka.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/haraka.h index 4c60a28999..737cb6065f 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/haraka.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/haraka.h @@ -1,40 +1,42 @@ -#ifndef PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_HARAKA_H -#define PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_HARAKA_H +#ifndef SPX_HARAKA_H +#define SPX_HARAKA_H -#include -#include - -typedef struct { - uint64_t tweaked512_rc64[10][8]; - uint32_t tweaked256_rc32[10][8]; - uint32_t tweaked256_rc32_sseed[10][8]; -} harakactx; +#include "context.h" +#include "params.h" /* Tweak constants with seed */ -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_tweak_constants( - harakactx *state, - const unsigned char *pk_seed, const unsigned char *sk_seed, - unsigned long long seed_length); +#define tweak_constants SPX_NAMESPACE(tweak_constants) +void tweak_constants(spx_ctx *ctx); /* Haraka Sponge */ -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_haraka_S_inc_init(uint8_t *s_inc); -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, const harakactx *state); -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_haraka_S_inc_finalize(uint8_t *s_inc); -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, const harakactx *state); -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_haraka_S( - unsigned char *out, unsigned long long outlen, - const unsigned char *in, unsigned long long inlen, const harakactx *state); +#define haraka_S_inc_init SPX_NAMESPACE(haraka_S_inc_init) +void haraka_S_inc_init(uint8_t *s_inc); +#define haraka_S_inc_absorb SPX_NAMESPACE(haraka_S_inc_absorb) +void haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, + const spx_ctx *ctx); +#define haraka_S_inc_finalize SPX_NAMESPACE(haraka_S_inc_finalize) +void haraka_S_inc_finalize(uint8_t *s_inc); +#define haraka_S_inc_squeeze SPX_NAMESPACE(haraka_S_inc_squeeze) +void haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, + const spx_ctx *ctx); +#define haraka_S SPX_NAMESPACE(haraka_S) +void haraka_S(unsigned char *out, unsigned long long outlen, + const unsigned char *in, unsigned long long inlen, + const spx_ctx *ctx); /* Applies the 512-bit Haraka permutation to in. */ -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_haraka512_perm(unsigned char *out, const unsigned char *in, const harakactx *state); +#define haraka512_perm SPX_NAMESPACE(haraka512_perm) +void haraka512_perm(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx); /* Implementation of Haraka-512 */ -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_haraka512(unsigned char *out, const unsigned char *in, const harakactx *state); +#define haraka512 SPX_NAMESPACE(haraka512) +void haraka512(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx); /* Implementation of Haraka-256 */ -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_haraka256(unsigned char *out, const unsigned char *in, const harakactx *state); - -/* Implementation of Haraka-256 using sk.seed constants */ -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_haraka256_sk(unsigned char *out, const unsigned char *in, const harakactx *state); +#define haraka256 SPX_NAMESPACE(haraka256) +void haraka256(unsigned char *out, const unsigned char *in, + const spx_ctx *ctx); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/haraka_offsets.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/haraka_offsets.h new file mode 100644 index 0000000000..7c062272a0 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/haraka_offsets.h @@ -0,0 +1,21 @@ +#ifndef HARAKA_OFFSETS_H_ +#define HARAKA_OFFSETS_H_ + +/* + * Offsets of various fields in the address structure when we use Haraka as + * the Sphincs+ hash function + */ + +#define SPX_OFFSET_LAYER 3 /* The byte used to specify the Merkle tree layer */ +#define SPX_OFFSET_TREE 8 /* The start of the 8 byte field used to specify the tree */ +#define SPX_OFFSET_TYPE 19 /* The byte used to specify the hash type (reason) */ +#define SPX_OFFSET_KP_ADDR2 22 /* The high byte used to specify the key pair (which one-time signature) */ +#define SPX_OFFSET_KP_ADDR1 23 /* The low byte used to specify the key pair */ +#define SPX_OFFSET_CHAIN_ADDR 27 /* The byte used to specify the chain address (which Winternitz chain) */ +#define SPX_OFFSET_HASH_ADDR 31 /* The byte used to specify the hash address (where in the Winternitz chain) */ +#define SPX_OFFSET_TREE_HGT 27 /* The byte used to specify the height of this node in the FORS or Merkle tree */ +#define SPX_OFFSET_TREE_INDEX 28 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ + +#define SPX_HARAKA 1 + +#endif /* HARAKA_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/hash.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/hash.h index 71d573714e..f7c87d4c3c 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/hash.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/hash.h @@ -1,31 +1,28 @@ -#ifndef PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_HASH_H -#define PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_HASH_H - -#include "hash_state.h" +#ifndef SPX_HASH_H +#define SPX_HASH_H #include #include -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_initialize_hash_function( - hash_state *hash_state_seeded, - const unsigned char *pub_seed, const unsigned char *sk_seed); +#include "context.h" +#include "params.h" + +#define prf_addr SPX_NAMESPACE(prf_addr) +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]); -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_destroy_hash_function(hash_state *hash_state_seeded); +#define gen_message_random SPX_NAMESPACE(gen_message_random) +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded); +#define hash_message SPX_NAMESPACE(hash_message) +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/hash_haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/hash_haraka.c index 63b4e1096b..750a67423b 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/hash_haraka.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/hash_haraka.c @@ -2,58 +2,44 @@ #include #include "address.h" -#include "haraka.h" -#include "hash.h" #include "params.h" #include "utils.h" -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_initialize_hash_function( - hash_state *hash_state_seeded, - const unsigned char *pub_seed, const unsigned char *sk_seed) { - PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_tweak_constants(hash_state_seeded, pub_seed, sk_seed, PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_N); -} - -/* The haraka implementation is stack based and won't be replaced in PQClean/OQS, - so we don't need to do anything */ -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_destroy_hash_function( - hash_state *hash_state_seeded) { // NOLINT(readability-non-const-parameter) - (void)hash_state_seeded; -} +#include "haraka.h" +#include "hash.h" /* - * Computes PRF(key, addr), given a secret key of PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_N bytes and an address + * Computes PRF(key, addr), given a secret key of SPX_N bytes and an address */ -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded) { - unsigned char buf[PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_ADDR_BYTES]; - /* Since PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_N may be smaller than 32, we need a temporary buffer. */ +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]) { + /* Since SPX_N may be smaller than 32, we need temporary buffers. */ unsigned char outbuf[32]; + unsigned char buf[64] = {0}; - (void)key; /* Suppress an 'unused parameter' warning. */ + memcpy(buf, addr, SPX_ADDR_BYTES); + memcpy(buf + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); - PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_addr_to_bytes(buf, addr); - PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_haraka256_sk(outbuf, buf, hash_state_seeded); - memcpy(out, outbuf, PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_N); + haraka512(outbuf, (const void *)buf, ctx); + memcpy(out, outbuf, SPX_N); } /** * Computes the message-dependent randomness R, using a secret seed and an * optional randomization value as well as the message. */ -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded) { +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { uint8_t s_inc[65]; - PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_haraka_S_inc_init(s_inc); - PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_haraka_S_inc_absorb(s_inc, sk_prf, PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_N, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_haraka_S_inc_absorb(s_inc, optrand, PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_N, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_haraka_S_inc_absorb(s_inc, m, mlen, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_haraka_S_inc_finalize(s_inc); - PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_haraka_S_inc_squeeze(R, PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_N, s_inc, hash_state_seeded); + haraka_S_inc_init(s_inc); + haraka_S_inc_absorb(s_inc, sk_prf, SPX_N, ctx); + haraka_S_inc_absorb(s_inc, optrand, SPX_N, ctx); + haraka_S_inc_absorb(s_inc, m, mlen, ctx); + haraka_S_inc_finalize(s_inc); + haraka_S_inc_squeeze(R, SPX_N, s_inc, ctx); } /** @@ -61,36 +47,35 @@ void PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_gen_message_random( * Outputs the message digest and the index of the leaf. The index is split in * the tree index and the leaf index, for convenient copying to an address. */ -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded) { -#define PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_TREE_BITS (PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_TREE_HEIGHT * (PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_D - 1)) -#define PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_TREE_BYTES ((PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_TREE_BITS + 7) / 8) -#define PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_LEAF_BITS PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_TREE_HEIGHT -#define PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_LEAF_BYTES ((PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_LEAF_BITS + 7) / 8) -#define PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_DGST_BYTES (PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_FORS_MSG_BYTES + PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_TREE_BYTES + PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_LEAF_BYTES) +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { +#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) +#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) +#define SPX_LEAF_BITS SPX_TREE_HEIGHT +#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) +#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) - unsigned char buf[PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_DGST_BYTES]; + unsigned char buf[SPX_DGST_BYTES]; unsigned char *bufp = buf; uint8_t s_inc[65]; - PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_haraka_S_inc_init(s_inc); - PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_haraka_S_inc_absorb(s_inc, R, PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_N, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_haraka_S_inc_absorb(s_inc, pk + PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_N, PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_N, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_haraka_S_inc_absorb(s_inc, m, mlen, hash_state_seeded); - PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_haraka_S_inc_finalize(s_inc); - PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_haraka_S_inc_squeeze(buf, PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_DGST_BYTES, s_inc, hash_state_seeded); + haraka_S_inc_init(s_inc); + haraka_S_inc_absorb(s_inc, R, SPX_N, ctx); + haraka_S_inc_absorb(s_inc, pk + SPX_N, SPX_N, ctx); // Only absorb root part of pk + haraka_S_inc_absorb(s_inc, m, mlen, ctx); + haraka_S_inc_finalize(s_inc); + haraka_S_inc_squeeze(buf, SPX_DGST_BYTES, s_inc, ctx); + + memcpy(digest, bufp, SPX_FORS_MSG_BYTES); + bufp += SPX_FORS_MSG_BYTES; - memcpy(digest, bufp, PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_FORS_MSG_BYTES); - bufp += PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_FORS_MSG_BYTES; - *tree = PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_bytes_to_ull(bufp, PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_TREE_BYTES); - *tree &= (~(uint64_t)0) >> (64 - PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_TREE_BITS); - bufp += PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_TREE_BYTES; + *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); + *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); + bufp += SPX_TREE_BYTES; - *leaf_idx = (uint32_t)PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_bytes_to_ull( - bufp, PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_LEAF_BYTES); - *leaf_idx &= (~(uint32_t)0) >> (32 - PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_LEAF_BITS); + *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); + *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/hash_state.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/hash_state.h deleted file mode 100644 index 5adb1d9a22..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/hash_state.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef SPX_HASH_STATE_H -#define SPX_HASH_STATE_H - -/** - * Defines the type of the hash function state. - * - * Don't be fooled into thinking this instance of SPHINCS+ isn't stateless! - * - * From Section 7.2.2 from the SPHINCS+ round-2 specification: - * - * Each of the instances of the tweakable hash function take PK.seed as its - * first input, which is constant for a given key pair – and, thus, across - * a single signature. This leads to a lot of redundant computation. To remedy - * this, we pad PK.seed to the length of a full 64-byte SHA-256 input block. - * Because of the Merkle-DamgÃ¥rd construction that underlies SHA-256, this - * allows for reuse of the intermediate SHA-256 state after the initial call to - * the compression function which improves performance. - * - * We pass this hash state around in functions, because otherwise we need to - * have a global variable. - */ - -#include "haraka.h" -#define hash_state harakactx - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/merkle.c b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/merkle.c new file mode 100644 index 0000000000..0c1479fd93 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/merkle.c @@ -0,0 +1,59 @@ +#include +#include + +#include "address.h" +#include "merkle.h" +#include "params.h" +#include "utils.h" +#include "utilsx1.h" +#include "wots.h" +#include "wotsx1.h" + +/* + * This generates a Merkle signature (WOTS signature followed by the Merkle + * authentication path). This is in this file because most of the complexity + * is involved with the WOTS signature; the Merkle authentication path logic + * is mostly hidden in treehashx4 + */ +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf) { + unsigned char *auth_path = sig + SPX_WOTS_BYTES; + struct leaf_info_x1 info = { 0 }; + unsigned steps[ SPX_WOTS_LEN ]; + + info.wots_sig = sig; + chain_lengths(steps, root); + info.wots_steps = steps; + + set_type(&tree_addr[0], SPX_ADDR_TYPE_HASHTREE); + set_type(&info.pk_addr[0], SPX_ADDR_TYPE_WOTSPK); + copy_subtree_addr(&info.leaf_addr[0], wots_addr); + copy_subtree_addr(&info.pk_addr[0], wots_addr); + + info.wots_sign_leaf = idx_leaf; + + treehashx1(root, auth_path, ctx, + idx_leaf, 0, + SPX_TREE_HEIGHT, + wots_gen_leafx1, + tree_addr, &info); +} + +/* Compute root node of the top-most subtree. */ +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { + /* We do not need the auth path in key generation, but it simplifies the + code to have just one treehash routine that computes both root and path + in one function. */ + unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; + uint32_t top_tree_addr[8] = {0}; + uint32_t wots_addr[8] = {0}; + + set_layer_addr(top_tree_addr, SPX_D - 1); + set_layer_addr(wots_addr, SPX_D - 1); + + merkle_sign(auth_path, root, ctx, + wots_addr, top_tree_addr, + (uint32_t)~0 /* ~0 means "don't bother generating an auth path */ ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/merkle.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/merkle.h new file mode 100644 index 0000000000..769cf2e970 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/merkle.h @@ -0,0 +1,21 @@ +#ifndef MERKLE_H_ +#define MERKLE_H_ + +#include + +#include "context.h" +#include "params.h" + +/* Generate a Merkle signature (WOTS signature followed by the Merkle */ +/* authentication path) */ +#define merkle_sign SPX_NAMESPACE(merkle_sign) +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf); + +/* Compute the root node of the top-most subtree. */ +#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); + +#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/nistapi.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/nistapi.h new file mode 100644 index 0000000000..3cb71afad4 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/nistapi.h @@ -0,0 +1,87 @@ +#ifndef SPX_API_H +#define SPX_API_H + +#include +#include + +#include "params.h" + +#define CRYPTO_ALGNAME "SPHINCS+" + +#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES +#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES +#define CRYPTO_BYTES SPX_BYTES +#define CRYPTO_SEEDBYTES (3*SPX_N) + +/* + * Returns the length of a secret key, in bytes + */ +#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) +size_t crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) +size_t crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) +size_t crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) +size_t crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +#define crypto_sign SPX_NAMESPACE(crypto_sign) +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/params.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/params.h index 344a7ecc24..89e496c816 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/params.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/params.h @@ -1,53 +1,56 @@ -#ifndef PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_PARAMS_H -#define PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_PARAMS_H +#ifndef SPX_PARAMS_H +#define SPX_PARAMS_H + +#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_##s /* Hash output length in bytes. */ -#define PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_N 32 +#define SPX_N 32 /* Height of the hypertree. */ -#define PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_FULL_HEIGHT 64 +#define SPX_FULL_HEIGHT 64 /* Number of subtree layer. */ -#define PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_D 8 +#define SPX_D 8 /* FORS tree dimensions. */ -#define PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_FORS_HEIGHT 14 -#define PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_FORS_TREES 22 +#define SPX_FORS_HEIGHT 14 +#define SPX_FORS_TREES 22 /* Winternitz parameter, */ -#define PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_WOTS_W 16 +#define SPX_WOTS_W 16 /* The hash function is defined by linking a different hash.c file, as opposed to setting a #define constant. */ /* For clarity */ -#define PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_ADDR_BYTES 32 +#define SPX_ADDR_BYTES 32 /* WOTS parameters. */ -#define PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_WOTS_LOGW 4 +#define SPX_WOTS_LOGW 4 -#define PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_WOTS_LEN1 (8 * PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_N / PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_WOTS_LOGW) +#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) -/* PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#define PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_WOTS_LEN2 3 +/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ +#define SPX_WOTS_LEN2 3 -#define PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_WOTS_LEN (PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_WOTS_LEN1 + PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_WOTS_LEN2) -#define PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_WOTS_BYTES (PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_WOTS_LEN * PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_N) -#define PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_WOTS_PK_BYTES PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_WOTS_BYTES +#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) +#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) +#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES /* Subtree size. */ -#define PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_TREE_HEIGHT (PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_FULL_HEIGHT / PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_D) +#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) + +//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT +// #error SPX_D should always divide SPX_FULL_HEIGHT +//#endif /* FORS parameters. */ -#define PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_FORS_MSG_BYTES ((PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_FORS_TREES + 7) / 8) -#define PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_FORS_BYTES ((PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_FORS_HEIGHT + 1) * PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_FORS_TREES * PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_N) -#define PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_FORS_PK_BYTES PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_N +#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) +#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) +#define SPX_FORS_PK_BYTES SPX_N /* Resulting SPX sizes. */ -#define PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_BYTES (PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_N + PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_FORS_BYTES + PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_D * PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_WOTS_BYTES +\ - PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_FULL_HEIGHT * PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_N) -#define PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_PK_BYTES (2 * PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_N) -#define PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_SK_BYTES (2 * PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_N + PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_PK_BYTES) - -/* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ -#define PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_OPTRAND_BYTES 32 +#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ + SPX_FULL_HEIGHT * SPX_N) +#define SPX_PK_BYTES (2 * SPX_N) +#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) + +#include "haraka_offsets.h" #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/sign.c b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/sign.c index fd4447153b..9d0c7d1b22 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/sign.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/sign.c @@ -3,72 +3,43 @@ #include #include "address.h" -#include "api.h" +#include "context.h" #include "fors.h" #include "hash.h" -#include "hash_state.h" +#include "merkle.h" +#include "nistapi.h" #include "params.h" #include "randombytes.h" #include "thash.h" #include "utils.h" #include "wots.h" -/** - * Computes the leaf at a given address. First generates the WOTS key pair, - * then computes leaf by hashing horizontally. - */ -static void wots_gen_leaf(unsigned char *leaf, const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx, const uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - unsigned char pk[PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_WOTS_BYTES]; - uint32_t wots_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_set_type( - wots_addr, PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_set_type( - wots_pk_addr, PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_ADDR_TYPE_WOTSPK); - - PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_set_keypair_addr( - wots_addr, addr_idx); - PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_wots_gen_pk( - pk, sk_seed, pub_seed, wots_addr, hash_state_seeded); - - PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_copy_keypair_addr( - wots_pk_addr, wots_addr); - PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_thash_WOTS_LEN( - leaf, pk, pub_seed, wots_pk_addr, hash_state_seeded); -} - /* * Returns the length of a secret key, in bytes */ -size_t PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_crypto_sign_secretkeybytes(void) { - return PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_CRYPTO_SECRETKEYBYTES; +size_t crypto_sign_secretkeybytes(void) { + return CRYPTO_SECRETKEYBYTES; } /* * Returns the length of a public key, in bytes */ -size_t PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_crypto_sign_publickeybytes(void) { - return PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_CRYPTO_PUBLICKEYBYTES; +size_t crypto_sign_publickeybytes(void) { + return CRYPTO_PUBLICKEYBYTES; } /* * Returns the length of a signature, in bytes */ -size_t PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_crypto_sign_bytes(void) { - return PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_CRYPTO_BYTES; +size_t crypto_sign_bytes(void) { + return CRYPTO_BYTES; } /* * Returns the length of the seed required to generate a key pair, in bytes */ -size_t PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_crypto_sign_seedbytes(void) { - return PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_CRYPTO_SEEDBYTES; +size_t crypto_sign_seedbytes(void) { + return CRYPTO_SEEDBYTES; } /* @@ -76,37 +47,30 @@ size_t PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_crypto_sign_seedbytes(void) { * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] * Format pk: [PUB_SEED || root] */ -int PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed) { - /* We do not need the auth path in key generation, but it simplifies the - code to have just one treehash routine that computes both root and path - in one function. */ - unsigned char auth_path[PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_TREE_HEIGHT * PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_N]; - uint32_t top_tree_addr[8] = {0}; - hash_state hash_state_seeded; - - PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_set_layer_addr( - top_tree_addr, PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_D - 1); - PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_set_type( - top_tree_addr, PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_ADDR_TYPE_HASHTREE); +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed) { + spx_ctx ctx; /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ - memcpy(sk, seed, PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_CRYPTO_SEEDBYTES); + memcpy(sk, seed, CRYPTO_SEEDBYTES); - memcpy(pk, sk + 2 * PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_N, PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_N); + memcpy(pk, sk + 2 * SPX_N, SPX_N); + + memcpy(ctx.pub_seed, pk, SPX_N); + memcpy(ctx.sk_seed, sk, SPX_N); /* This hook allows the hash function instantiation to do whatever preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_initialize_hash_function(&hash_state_seeded, pk, sk); + initialize_hash_function(&ctx); /* Compute root node of the top-most subtree. */ - PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_treehash_TREE_HEIGHT( - sk + 3 * PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_N, auth_path, sk, sk + 2 * PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_N, 0, 0, - wots_gen_leaf, top_tree_addr, &hash_state_seeded); + merkle_gen_root(sk + 3 * SPX_N, &ctx); + + // cleanup + free_hash_function(&ctx); - memcpy(pk + PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_N, sk + 3 * PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_N, PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_N); + memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); - PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_destroy_hash_function(&hash_state_seeded); return 0; } @@ -115,12 +79,10 @@ int PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_crypto_sign_seed_keypair( * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] * Format pk: [PUB_SEED || root] */ -int PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk) { - unsigned char seed[PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_CRYPTO_SEEDBYTES]; - randombytes(seed, PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_CRYPTO_SEEDBYTES); - PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_crypto_sign_seed_keypair( - pk, sk, seed); +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { + uint8_t seed[CRYPTO_SEEDBYTES]; + randombytes(seed, CRYPTO_SEEDBYTES); + crypto_sign_seed_keypair(pk, sk, seed); return 0; } @@ -128,101 +90,83 @@ int PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_crypto_sign_keypair( /** * Returns an array containing a detached signature. */ -int PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - const unsigned char *sk_seed = sk; - const unsigned char *sk_prf = sk + PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_N; - const unsigned char *pk = sk + 2 * PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_N; - const unsigned char *pub_seed = pk; - - unsigned char optrand[PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_N]; - unsigned char mhash[PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_FORS_MSG_BYTES]; - unsigned char root[PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_N]; +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk) { + spx_ctx ctx; + + const uint8_t *sk_prf = sk + SPX_N; + const uint8_t *pk = sk + 2 * SPX_N; + + uint8_t optrand[SPX_N]; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t root[SPX_N]; uint32_t i; uint64_t tree; uint32_t idx_leaf; uint32_t wots_addr[8] = {0}; uint32_t tree_addr[8] = {0}; - hash_state hash_state_seeded; + memcpy(ctx.sk_seed, sk, SPX_N); + memcpy(ctx.pub_seed, pk, SPX_N); /* This hook allows the hash function instantiation to do whatever preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_initialize_hash_function( - &hash_state_seeded, - pub_seed, sk_seed); + initialize_hash_function(&ctx); - PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_set_type( - wots_addr, PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_set_type( - tree_addr, PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_ADDR_TYPE_HASHTREE); + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); /* Optionally, signing can be made non-deterministic using optrand. This can help counter side-channel attacks that would benefit from getting a large number of traces when the signer uses the same nodes. */ - randombytes(optrand, PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_N); + randombytes(optrand, SPX_N); /* Compute the digest randomization value. */ - PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_gen_message_random( - sig, sk_prf, optrand, m, mlen, &hash_state_seeded); + gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); /* Derive the message digest and leaf index from R, PK and M. */ - PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_N; + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; - PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); /* Sign the message hash using FORS. */ - PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_fors_sign( - sig, root, mhash, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_FORS_BYTES; - - for (i = 0; i < PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_D; i++) { - PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_set_tree_addr(tree_addr, tree); - - PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); - - /* Compute a WOTS signature. */ - PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_wots_sign( - sig, root, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_WOTS_BYTES; - - /* Compute the authentication path for the used WOTS leaf. */ - PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_treehash_TREE_HEIGHT( - root, sig, sk_seed, pub_seed, idx_leaf, 0, - wots_gen_leaf, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_TREE_HEIGHT * PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_N; + fors_sign(sig, root, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); + sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_TREE_HEIGHT; + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; } - *siglen = PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_BYTES; + free_hash_function(&ctx); + + *siglen = SPX_BYTES; - PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_destroy_hash_function(&hash_state_seeded); return 0; } /** * Verifies a detached signature and message under a given public key. */ -int PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk) { - const unsigned char *pub_seed = pk; - const unsigned char *pub_root = pk + PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_N; - unsigned char mhash[PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_FORS_MSG_BYTES]; - unsigned char wots_pk[PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_WOTS_BYTES]; - unsigned char root[PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_N]; - unsigned char leaf[PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_N]; +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk) { + spx_ctx ctx; + const uint8_t *pub_root = pk + SPX_N; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t wots_pk[SPX_WOTS_BYTES]; + uint8_t root[SPX_N]; + uint8_t leaf[SPX_N]; unsigned int i; uint64_t tree; uint32_t idx_leaf; @@ -230,78 +174,66 @@ int PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_crypto_sign_verify( uint32_t tree_addr[8] = {0}; uint32_t wots_pk_addr[8] = {0}; - hash_state hash_state_seeded; - - if (siglen != PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_BYTES) { + if (siglen != SPX_BYTES) { return -1; } + memcpy(ctx.pub_seed, pk, SPX_N); + /* This hook allows the hash function instantiation to do whatever preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_initialize_hash_function( - &hash_state_seeded, - pub_seed, NULL); + initialize_hash_function(&ctx); - PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_set_type( - wots_addr, PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_set_type( - tree_addr, PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_ADDR_TYPE_HASHTREE); - PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_set_type( - wots_pk_addr, PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_ADDR_TYPE_WOTSPK); + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); /* Derive the message digest and leaf index from R || PK || M. */ - /* The additional PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_N is a result of the hash domain separator. */ - PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_N; + /* The additional SPX_N is a result of the hash domain separator. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; /* Layer correctly defaults to 0, so no need to set_layer_addr */ - PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); - PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_fors_pk_from_sig( - root, sig, mhash, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_FORS_BYTES; + fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; /* For each subtree.. */ - for (i = 0; i < PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_D; i++) { - PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_set_tree_addr(tree_addr, tree); + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); - PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); - PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_copy_keypair_addr( - wots_pk_addr, wots_addr); + copy_keypair_addr(wots_pk_addr, wots_addr); /* The WOTS public key is only correct if the signature was correct. */ /* Initially, root is the FORS pk, but on subsequent iterations it is the root of the subtree below the currently processed subtree. */ - PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_wots_pk_from_sig( - wots_pk, sig, root, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_WOTS_BYTES; + wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); + sig += SPX_WOTS_BYTES; /* Compute the leaf node using the WOTS public key. */ - PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_thash_WOTS_LEN( - leaf, wots_pk, pub_seed, wots_pk_addr, &hash_state_seeded); + thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); /* Compute the root node of this subtree. */ - PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_compute_root( - root, leaf, idx_leaf, 0, sig, PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_TREE_HEIGHT, - pub_seed, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_TREE_HEIGHT * PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_N; + compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, + &ctx, tree_addr); + sig += SPX_TREE_HEIGHT * SPX_N; /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_TREE_HEIGHT; + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; } - PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_destroy_hash_function(&hash_state_seeded); + // cleanup + free_hash_function(&ctx); + /* Check if the root node equals the root node in the public key. */ - if (memcmp(root, pub_root, PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_N) != 0) { + if (memcmp(root, pub_root, SPX_N) != 0) { return -1; } @@ -312,15 +244,14 @@ int PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_crypto_sign_verify( /** * Returns an array containing the signature followed by the message. */ -int PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk) { size_t siglen; - PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_crypto_sign_signature( - sm, &siglen, m, mlen, sk); + crypto_sign_signature(sm, &siglen, m, mlen, sk); - memmove(sm + PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_BYTES, m, mlen); + memmove(sm + SPX_BYTES, m, mlen); *smlen = siglen + mlen; return 0; @@ -329,28 +260,27 @@ int PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_crypto_sign( /** * Verifies a given signature-message pair under a given public key. */ -int PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk) { +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk) { /* The API caller does not necessarily know what size a signature should be - but SPHINCS+ signatures are always exactly PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_BYTES. */ - if (smlen < PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_BYTES) { + but SPHINCS+ signatures are always exactly SPX_BYTES. */ + if (smlen < SPX_BYTES) { memset(m, 0, smlen); *mlen = 0; return -1; } - *mlen = smlen - PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_BYTES; + *mlen = smlen - SPX_BYTES; - if (PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_crypto_sign_verify( - sm, PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_BYTES, sm + PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_BYTES, *mlen, pk)) { + if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { memset(m, 0, smlen); *mlen = 0; return -1; } /* If verification was successful, move the message to the right place. */ - memmove(m, sm + PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_BYTES, *mlen); + memmove(m, sm + SPX_BYTES, *mlen); return 0; } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/thash.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/thash.h index fec5e8b08a..8687ccfb4d 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/thash.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/thash.h @@ -1,28 +1,13 @@ -#ifndef PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_THASH_H -#define PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_THASH_H +#ifndef SPX_THASH_H +#define SPX_THASH_H -#include "hash_state.h" +#include "context.h" +#include "params.h" #include -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); +#define thash SPX_NAMESPACE(thash) +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/thash_haraka_simple.c b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/thash_haraka_simple.c index 462c91426f..207777bf8d 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/thash_haraka_simple.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/thash_haraka_simple.c @@ -4,80 +4,33 @@ #include "address.h" #include "params.h" #include "thash.h" +#include "utils.h" #include "haraka.h" /** - * Takes an array of inblocks concatenated arrays of PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_N bytes. + * Takes an array of inblocks concatenated arrays of SPX_N bytes. */ -static void PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_thash( - unsigned char *out, unsigned char *buf, - const unsigned char *in, unsigned int inblocks, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]) { + PQCLEAN_VLA(uint8_t, buf, SPX_ADDR_BYTES + inblocks * SPX_N); unsigned char outbuf[32]; unsigned char buf_tmp[64]; - (void)pub_seed; /* Suppress an 'unused parameter' warning. */ - if (inblocks == 1) { /* F function */ - /* Since PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_N may be smaller than 32, we need a temporary buffer. */ + /* Since SPX_N may be smaller than 32, we need a temporary buffer. */ memset(buf_tmp, 0, 64); - PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_addr_to_bytes(buf_tmp, addr); - memcpy(buf_tmp + PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_ADDR_BYTES, in, PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_N); + memcpy(buf_tmp, addr, 32); + memcpy(buf_tmp + SPX_ADDR_BYTES, in, SPX_N); - PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_haraka512(outbuf, buf_tmp, hash_state_seeded); - memcpy(out, outbuf, PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_N); + haraka512(outbuf, buf_tmp, ctx); + memcpy(out, outbuf, SPX_N); } else { /* All other tweakable hashes*/ - PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_addr_to_bytes(buf, addr); - memcpy(buf + PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_ADDR_BYTES, in, inblocks * PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_N); + memcpy(buf, addr, 32); + memcpy(buf + SPX_ADDR_BYTES, in, inblocks * SPX_N); - PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_haraka_S( - out, PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_N, buf, PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_N, hash_state_seeded); + haraka_S(out, SPX_N, buf, SPX_ADDR_BYTES + inblocks * SPX_N, ctx); } } - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_ADDR_BYTES + 1 * PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_N]; - PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_thash( - out, buf, in, 1, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_ADDR_BYTES + 2 * PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_N]; - PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_thash( - out, buf, in, 2, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_ADDR_BYTES + PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_WOTS_LEN * PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_N]; - PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_thash( - out, buf, in, PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_WOTS_LEN, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_ADDR_BYTES + PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_FORS_TREES * PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_N]; - PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_thash( - out, buf, in, PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_FORS_TREES, pub_seed, addr, hash_state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/utils.c b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/utils.c index 8db8be5626..177b541fb9 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/utils.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/utils.c @@ -1,34 +1,41 @@ -#include #include +#include "utils.h" + #include "address.h" #include "hash.h" -#include "hash_state.h" #include "params.h" #include "thash.h" -#include "utils.h" /** * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. */ -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in) { +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in) { + int i; /* Iterate over out in decreasing order, for big-endianness. */ - for (size_t i = outlen; i > 0; i--) { - out[i - 1] = in & 0xff; + for (i = (signed int)outlen - 1; i >= 0; i--) { + out[i] = in & 0xff; in = in >> 8; } } +void u32_to_bytes(unsigned char *out, uint32_t in) { + out[0] = (unsigned char)(in >> 24); + out[1] = (unsigned char)(in >> 16); + out[2] = (unsigned char)(in >> 8); + out[3] = (unsigned char)in; +} + /** * Converts the inlen bytes in 'in' from big-endian byte order to an integer. */ -unsigned long long PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_bytes_to_ull( - const unsigned char *in, size_t inlen) { +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { unsigned long long retval = 0; + unsigned int i; - for (size_t i = 0; i < inlen; i++) { + for (i = 0; i < inlen; i++) { retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); } return retval; @@ -38,94 +45,80 @@ unsigned long long PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_bytes_to_ull( * Computes a root node given a leaf and an auth path. * Expects address to be complete other than the tree_height and tree_index. */ -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]) { uint32_t i; - unsigned char buffer[2 * PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_N]; + unsigned char buffer[2 * SPX_N]; /* If leaf_idx is odd (last bit = 1), current path element is a right child and auth_path has to go left. Otherwise it is the other way around. */ if (leaf_idx & 1) { - memcpy(buffer + PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_N, leaf, PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_N); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_N); + memcpy(buffer + SPX_N, leaf, SPX_N); + memcpy(buffer, auth_path, SPX_N); } else { - memcpy(buffer, leaf, PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_N); - memcpy(buffer + PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_N, auth_path, PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_N); + memcpy(buffer, leaf, SPX_N); + memcpy(buffer + SPX_N, auth_path, SPX_N); } - auth_path += PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_N; + auth_path += SPX_N; for (i = 0; i < tree_height - 1; i++) { leaf_idx >>= 1; idx_offset >>= 1; /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_set_tree_height(addr, i + 1); - PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_set_tree_index( - addr, leaf_idx + idx_offset); + set_tree_height(addr, i + 1); + set_tree_index(addr, leaf_idx + idx_offset); /* Pick the right or left neighbor, depending on parity of the node. */ if (leaf_idx & 1) { - PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_thash_2( - buffer + PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_N, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_N); + thash(buffer + SPX_N, buffer, 2, ctx, addr); + memcpy(buffer, auth_path, SPX_N); } else { - PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_thash_2( - buffer, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer + PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_N, auth_path, PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_N); + thash(buffer, buffer, 2, ctx, addr); + memcpy(buffer + SPX_N, auth_path, SPX_N); } - auth_path += PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_N; + auth_path += SPX_N; } /* The last iteration is exceptional; we do not copy an auth_path node. */ leaf_idx >>= 1; idx_offset >>= 1; - PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_set_tree_height(addr, tree_height); - PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_set_tree_index( - addr, leaf_idx + idx_offset); - PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_thash_2( - root, buffer, pub_seed, addr, hash_state_seeded); + set_tree_height(addr, tree_height); + set_tree_index(addr, leaf_idx + idx_offset); + thash(root, buffer, 2, ctx, addr); } /** * For a given leaf index, computes the authentication path and the resulting * root node using Merkle's TreeHash algorithm. * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_ADDR_TYPE_FORSTREE). + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). * Applies the offset idx_offset to indices before building addresses, so that * it is possible to continue counting indices across trees. */ -static void PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_treehash( - unsigned char *root, unsigned char *auth_path, - unsigned char *stack, unsigned int *heights, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - +void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx * /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]) { + PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); + PQCLEAN_VLA(unsigned int, heights, tree_height + 1); unsigned int offset = 0; uint32_t idx; uint32_t tree_idx; for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { /* Add the next leaf node to the stack. */ - gen_leaf(stack + offset * PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_N, - sk_seed, pub_seed, idx + idx_offset, tree_addr, - hash_state_seeded); + gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); offset++; heights[offset - 1] = 0; /* If this is a node we need for the auth path.. */ if ((leaf_idx ^ 0x1) == idx) { - memcpy(auth_path, stack + (offset - 1)*PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_N, PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_N); + memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); } /* While the top-most nodes are of equal height.. */ @@ -134,66 +127,22 @@ static void PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_treehash( tree_idx = (idx >> (heights[offset - 1] + 1)); /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_set_tree_height( - tree_addr, heights[offset - 1] + 1); - PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_set_tree_index( - tree_addr, tree_idx + (idx_offset >> (heights[offset - 1] + 1))); + set_tree_height(tree_addr, heights[offset - 1] + 1); + set_tree_index(tree_addr, + tree_idx + (idx_offset >> (heights[offset - 1] + 1))); /* Hash the top-most nodes from the stack together. */ - PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_thash_2( - stack + (offset - 2)*PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_N, stack + (offset - 2)*PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_N, - pub_seed, tree_addr, hash_state_seeded); + thash(stack + (offset - 2)*SPX_N, + stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); offset--; /* Note that the top-most node is now one layer higher. */ heights[offset - 1]++; /* If this is a node we need for the auth path.. */ if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_path + heights[offset - 1]*PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_N, - stack + (offset - 1)*PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_N, PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_N); + memcpy(auth_path + heights[offset - 1]*SPX_N, + stack + (offset - 1)*SPX_N, SPX_N); } } } - memcpy(root, stack, PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_N); -} - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_FORS_HEIGHT + 1)*PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_N]; - unsigned int heights[PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_FORS_HEIGHT + 1]; - - PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_FORS_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_TREE_HEIGHT + 1)*PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_N]; - unsigned int heights[PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_TREE_HEIGHT + 1]; - - PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_TREE_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); + memcpy(root, stack, SPX_N); } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/utils.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/utils.h index c3e119ff4c..64f5d5a53a 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/utils.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/utils.h @@ -1,64 +1,58 @@ -#ifndef PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_UTILS_H -#define PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_UTILS_H +#ifndef SPX_UTILS_H +#define SPX_UTILS_H -#include "hash_state.h" -#include "params.h" -#include #include +#include "compat.h" +#include "context.h" +#include "params.h" + + +/* To support MSVC use alloca() instead of VLAs. See #20. */ + + /** * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. */ -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in); +#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in); +#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) +void u32_to_bytes(unsigned char *out, uint32_t in); /** * Converts the inlen bytes in 'in' from big-endian byte order to an integer. */ -unsigned long long PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_bytes_to_ull( - const unsigned char *in, size_t inlen); +#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); /** * Computes a root node given a leaf and an auth path. * Expects address to be complete other than the tree_height and tree_index. */ -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); +#define compute_root SPX_NAMESPACE(compute_root) +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]); /** * For a given leaf index, computes the authentication path and the resulting * root node using Merkle's TreeHash algorithm. * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_ADDR_TYPE_FORSTREE). + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). * Applies the offset idx_offset to indices before building addresses, so that * it is possible to continue counting indices across trees. */ -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); +#define treehash SPX_NAMESPACE(treehash) +void treehash(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx *ctx /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]); -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/utilsx1.c b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/utilsx1.c new file mode 100644 index 0000000000..fccb69b35d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/utilsx1.c @@ -0,0 +1,100 @@ +#include + +#include "utilsx1.h" + +#include "address.h" +#include "params.h" +#include "thash.h" +#include "utils.h" + +/* + * Generate the entire Merkle tree, computing the authentication path for + * leaf_idx, and the resulting root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) + * + * This expects tree_addr to be initialized to the addr structures for the + * Merkle tree nodes + * + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + * + * This works by using the standard Merkle tree building algorithm, + */ +void treehashx1(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, + uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* Where to write the leaves */, + const spx_ctx * /* ctx */, + uint32_t idx, void *info), + uint32_t tree_addr[8], + void *info) { + /* This is where we keep the intermediate nodes */ + PQCLEAN_VLA(uint8_t, stack, tree_height * SPX_N); + + uint32_t idx; + uint32_t max_idx = (uint32_t)((1 << tree_height) - 1); + for (idx = 0;; idx++) { + unsigned char current[2 * SPX_N]; /* Current logical node is at */ + /* index[SPX_N]. We do this to minimize the number of copies */ + /* needed during a thash */ + gen_leaf( ¤t[SPX_N], ctx, idx + idx_offset, + info ); + + /* Now combine the freshly generated right node with previously */ + /* generated left ones */ + uint32_t internal_idx_offset = idx_offset; + uint32_t internal_idx = idx; + uint32_t internal_leaf = leaf_idx; + uint32_t h; /* The height we are in the Merkle tree */ + for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { + + /* Check if we hit the top of the tree */ + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[SPX_N], SPX_N ); + return; + } + + /* + * Check if the node we have is a part of the + * authentication path; if it is, write it out + */ + if ((internal_idx ^ internal_leaf) == 0x01) { + memcpy( &auth_path[ h * SPX_N ], + ¤t[SPX_N], + SPX_N ); + } + + /* + * Check if we're at a left child; if so, stop going up the stack + * Exception: if we've reached the end of the tree, keep on going + * (so we combine the last 4 nodes into the one root node in two + * more iterations) + */ + if ((internal_idx & 1) == 0 && idx < max_idx) { + break; + } + + /* Ok, we're at a right node */ + /* Now combine the left and right logical nodes together */ + + /* Set the address of the node we're creating. */ + internal_idx_offset >>= 1; + set_tree_height(tree_addr, h + 1); + set_tree_index(tree_addr, internal_idx / 2 + internal_idx_offset ); + + unsigned char *left = &stack[h * SPX_N]; + memcpy( ¤t[0], left, SPX_N ); + thash( ¤t[1 * SPX_N], + ¤t[0 * SPX_N], + 2, ctx, tree_addr); + } + + /* We've hit a left child; save the current for when we get the */ + /* corresponding right right */ + memcpy( &stack[h * SPX_N], ¤t[SPX_N], SPX_N); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/utilsx1.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/utilsx1.h new file mode 100644 index 0000000000..e911d17d53 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/utilsx1.h @@ -0,0 +1,27 @@ +#ifndef SPX_UTILSX4_H +#define SPX_UTILSX4_H + +#include + +#include "context.h" +#include "params.h" + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +#define treehashx1 SPX_NAMESPACE(treehashx1) +void treehashx1(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* Where to write the leaf */, + const spx_ctx * /* ctx */, + uint32_t addr_idx, void *info), + uint32_t tree_addrx4[8], void *info); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/wots.c b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/wots.c index 912161dbee..249717aaa8 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/wots.c +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/wots.c @@ -1,32 +1,20 @@ #include #include +#include "wots.h" +#include "wotsx1.h" + #include "address.h" #include "hash.h" -#include "hash_state.h" #include "params.h" #include "thash.h" #include "utils.h" -#include "wots.h" +#include "utilsx1.h" // TODO clarify address expectations, and make them more uniform. // TODO i.e. do we expect types to be set already? // TODO and do we expect modifications or copies? -/** - * Computes the starting value for a chain, i.e. the secret key. - * Expects the address to be complete up to the chain address. - */ -static void wots_gen_sk(unsigned char *sk, const unsigned char *sk_seed, - uint32_t wots_addr[8], - const hash_state *hash_state_seeded) { - /* Make sure that the hash address is actually zeroed. */ - PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_set_hash_addr(wots_addr, 0); - - /* Generate sk element. */ - PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_prf_addr(sk, sk_seed, wots_addr, hash_state_seeded); -} - /** * Computes the chaining function. * out and in have to be n-byte arrays. @@ -36,18 +24,16 @@ static void wots_gen_sk(unsigned char *sk, const unsigned char *sk_seed, */ static void gen_chain(unsigned char *out, const unsigned char *in, unsigned int start, unsigned int steps, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { + const spx_ctx *ctx, uint32_t addr[8]) { uint32_t i; /* Initialize out with the value at position 'start'. */ - memcpy(out, in, PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_N); + memcpy(out, in, SPX_N); /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_WOTS_W; i++) { - PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_set_hash_addr(addr, i); - PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_thash_1( - out, out, pub_seed, addr, hash_state_seeded); + for (i = start; i < (start + steps) && i < SPX_WOTS_W; i++) { + set_hash_addr(addr, i); + thash(out, out, 1, ctx, addr); } } @@ -56,13 +42,13 @@ static void gen_chain(unsigned char *out, const unsigned char *in, * Interprets an array of bytes as integers in base w. * This only works when log_w is a divisor of 8. */ -static void base_w(unsigned int *output, const size_t out_len, +static void base_w(unsigned int *output, const int out_len, const unsigned char *input) { - size_t in = 0; - size_t out = 0; + int in = 0; + int out = 0; unsigned char total = 0; - unsigned int bits = 0; - size_t consumed; + int bits = 0; + int consumed; for (consumed = 0; consumed < out_len; consumed++) { if (bits == 0) { @@ -70,8 +56,8 @@ static void base_w(unsigned int *output, const size_t out_len, in++; bits += 8; } - bits -= PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_WOTS_LOGW; - output[out] = (unsigned int)((total >> bits) & (PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_WOTS_W - 1)); + bits -= SPX_WOTS_LOGW; + output[out] = (total >> bits) & (SPX_WOTS_W - 1); out++; } } @@ -80,67 +66,25 @@ static void base_w(unsigned int *output, const size_t out_len, static void wots_checksum(unsigned int *csum_base_w, const unsigned int *msg_base_w) { unsigned int csum = 0; - unsigned char csum_bytes[(PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_WOTS_LEN2 * PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_WOTS_LOGW + 7) / 8]; + unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; unsigned int i; /* Compute checksum. */ - for (i = 0; i < PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_WOTS_LEN1; i++) { - csum += PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_WOTS_W - 1 - msg_base_w[i]; + for (i = 0; i < SPX_WOTS_LEN1; i++) { + csum += SPX_WOTS_W - 1 - msg_base_w[i]; } /* Convert checksum to base_w. */ /* Make sure expected empty zero bits are the least significant bits. */ - csum = csum << (8 - ((PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_WOTS_LEN2 * PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_WOTS_LOGW) % 8)); - PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_ull_to_bytes( - csum_bytes, sizeof(csum_bytes), csum); - base_w(csum_base_w, PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_WOTS_LEN2, csum_bytes); + csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); + ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); + base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); } /* Takes a message and derives the matching chain lengths. */ -static void chain_lengths(unsigned int *lengths, const unsigned char *msg) { - base_w(lengths, PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_WOTS_LEN1, msg); - wots_checksum(lengths + PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_WOTS_LEN1, lengths); -} - -/** - * WOTS key generation. Takes a 32 byte sk_seed, expands it to WOTS private key - * elements and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_wots_gen_pk( - unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - uint32_t i; - - for (i = 0; i < PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_WOTS_LEN; i++) { - PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_set_chain_addr(addr, i); - wots_gen_sk(pk + i * PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_N, sk_seed, addr, hash_state_seeded); - gen_chain(pk + i * PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_N, pk + i * PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_N, - 0, PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_WOTS_W - 1, pub_seed, addr, hash_state_seeded); - } -} - -/** - * Takes a n-byte message and the 32-byte sk_see to compute a signature 'sig'. - */ -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_wots_sign( - unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *hash_state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_WOTS_LEN; i++) { - PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_set_chain_addr(addr, i); - wots_gen_sk(sig + i * PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_N, sk_seed, addr, hash_state_seeded); - gen_chain(sig + i * PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_N, sig + i * PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_N, 0, lengths[i], pub_seed, addr, hash_state_seeded); - } +void chain_lengths(unsigned int *lengths, const unsigned char *msg) { + base_w(lengths, SPX_WOTS_LEN1, msg); + wots_checksum(lengths + SPX_WOTS_LEN1, lengths); } /** @@ -148,20 +92,17 @@ void PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_wots_sign( * * Writes the computed public key to 'pk'. */ -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_wots_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_WOTS_LEN]; +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]) { + unsigned int lengths[SPX_WOTS_LEN]; uint32_t i; chain_lengths(lengths, msg); - for (i = 0; i < PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_WOTS_LEN; i++) { - PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_set_chain_addr(addr, i); - gen_chain(pk + i * PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_N, sig + i * PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_N, - lengths[i], PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_WOTS_W - 1 - lengths[i], pub_seed, addr, - hash_state_seeded); + for (i = 0; i < SPX_WOTS_LEN; i++) { + set_chain_addr(addr, i); + gen_chain(pk + i * SPX_N, sig + i * SPX_N, + lengths[i], SPX_WOTS_W - 1 - lengths[i], ctx, addr); } } diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/wots.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/wots.h index acbb4b2993..4e7692eeef 100644 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/wots.h +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/wots.h @@ -1,41 +1,25 @@ -#ifndef PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_WOTS_H -#define PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_WOTS_H +#ifndef SPX_WOTS_H +#define SPX_WOTS_H -#include "hash_state.h" -#include "params.h" #include -/** - * WOTS key generation. Takes a 32 byte seed for the private key, expands it to - * a full WOTS private key and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_wots_gen_pk( - unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -/** - * Takes a n-byte message and the 32-byte seed for the private key to compute a - * signature that is placed at 'sig'. - */ -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_wots_sign( - unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *hash_state_seeded); +#include "context.h" +#include "params.h" /** * Takes a WOTS signature and an n-byte message, computes a WOTS public key. * * Writes the computed public key to 'pk'. */ -void PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_wots_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); +#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]); + +/* + * Compute the chain lengths needed for a given message hash + */ +#define chain_lengths SPX_NAMESPACE(chain_lengths) +void chain_lengths(unsigned int *lengths, const unsigned char *msg); #endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/wotsx1.c b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/wotsx1.c new file mode 100644 index 0000000000..3adec78dfb --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/wotsx1.c @@ -0,0 +1,76 @@ +#include +#include + +#include "wots.h" +#include "wotsx1.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "thash.h" +#include "utils.h" + +/* + * This generates a WOTS public key + * It also generates the WOTS signature if leaf_info indicates + * that we're signing with this WOTS key + */ +void wots_gen_leafx1(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info) { + struct leaf_info_x1 *info = v_info; + uint32_t *leaf_addr = info->leaf_addr; + uint32_t *pk_addr = info->pk_addr; + unsigned int i, k; + unsigned char pk_buffer[ SPX_WOTS_BYTES ]; + unsigned char *buffer; + uint32_t wots_k_mask; + + if (leaf_idx == info->wots_sign_leaf) { + /* We're traversing the leaf that's signing; generate the WOTS */ + /* signature */ + wots_k_mask = 0; + } else { + /* Nope, we're just generating pk's; turn off the signature logic */ + wots_k_mask = (uint32_t)~0; + } + + set_keypair_addr( leaf_addr, leaf_idx ); + set_keypair_addr( pk_addr, leaf_idx ); + + for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { + uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k to */ + /* the step if we're generating a signature, ~0 if we're not */ + + /* Start with the secret seed */ + set_chain_addr(leaf_addr, i); + set_hash_addr(leaf_addr, 0); + set_type(leaf_addr, SPX_ADDR_TYPE_WOTSPRF); + + prf_addr(buffer, ctx, leaf_addr); + + set_type(leaf_addr, SPX_ADDR_TYPE_WOTS); + + /* Iterate down the WOTS chain */ + for (k = 0;; k++) { + /* Check if this is the value that needs to be saved as a */ + /* part of the WOTS signature */ + if (k == wots_k) { + memcpy( info->wots_sig + i * SPX_N, buffer, SPX_N ); + } + + /* Check if we hit the top of the chain */ + if (k == SPX_WOTS_W - 1) { + break; + } + + /* Iterate one step on the chain */ + set_hash_addr(leaf_addr, k); + + thash(buffer, buffer, 1, ctx, leaf_addr); + } + } + + /* Do the final thash to generate the public keys */ + thash(dest, pk_buffer, SPX_WOTS_LEN, ctx, pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/wotsx1.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/wotsx1.h new file mode 100644 index 0000000000..e617929f96 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/wotsx1.h @@ -0,0 +1,39 @@ +#ifndef WOTSX1_H_ +#define WOTSX1_H_ + +#include + +#include "context.h" +#include "params.h" + +/* + * This is here to provide an interface to the internal wots_gen_leafx1 + * routine. While this routine is not referenced in the package outside of + * wots.c, it is called from the stand-alone benchmark code to characterize + * the performance + */ +struct leaf_info_x1 { + unsigned char *wots_sig; + uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ + uint32_t *wots_steps; + uint32_t leaf_addr[8]; + uint32_t pk_addr[8]; +}; + +/* Macro to set the leaf_info to something 'benign', that is, it would */ +/* run with the same time as it does during the real signing process */ +/* Used only by the benchmark code */ +#define INITIALIZE_LEAF_INFO_X1(info, addr, step_buffer) { \ + (info).wots_sig = 0; \ + (info).wots_sign_leaf = ~0; \ + (info).wots_steps = step_buffer; \ + memcpy( &(info).leaf_addr[0], (addr), 32 ); \ + memcpy( &(info).pk_addr[0], (addr), 32 ); \ + } + +#define wots_gen_leafx1 SPX_NAMESPACE(wots_gen_leafx1) +void wots_gen_leafx1(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info); + +#endif /* WOTSX1_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/LICENSE b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/LICENSE new file mode 100644 index 0000000000..670154e353 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/LICENSE @@ -0,0 +1,116 @@ +CC0 1.0 Universal + +Statement of Purpose + +The laws of most jurisdictions throughout the world automatically confer +exclusive Copyright and Related Rights (defined below) upon the creator and +subsequent owner(s) (each and all, an "owner") of an original work of +authorship and/or a database (each, a "Work"). + +Certain owners wish to permanently relinquish those rights to a Work for the +purpose of contributing to a commons of creative, cultural and scientific +works ("Commons") that the public can reliably and without fear of later +claims of infringement build upon, modify, incorporate in other works, reuse +and redistribute as freely as possible in any form whatsoever and for any +purposes, including without limitation commercial purposes. These owners may +contribute to the Commons to promote the ideal of a free culture and the +further production of creative, cultural and scientific works, or to gain +reputation or greater distribution for their Work in part through the use and +efforts of others. + +For these and/or other purposes and motivations, and without any expectation +of additional consideration or compensation, the person associating CC0 with a +Work (the "Affirmer"), to the extent that he or she is an owner of Copyright +and Related Rights in the Work, voluntarily elects to apply CC0 to the Work +and publicly distribute the Work under its terms, with knowledge of his or her +Copyright and Related Rights in the Work and the meaning and intended legal +effect of CC0 on those rights. + +1. Copyright and Related Rights. A Work made available under CC0 may be +protected by copyright and related or neighboring rights ("Copyright and +Related Rights"). Copyright and Related Rights include, but are not limited +to, the following: + + i. the right to reproduce, adapt, distribute, perform, display, communicate, + and translate a Work; + + ii. moral rights retained by the original author(s) and/or performer(s); + + iii. publicity and privacy rights pertaining to a person's image or likeness + depicted in a Work; + + iv. rights protecting against unfair competition in regards to a Work, + subject to the limitations in paragraph 4(a), below; + + v. rights protecting the extraction, dissemination, use and reuse of data in + a Work; + + vi. database rights (such as those arising under Directive 96/9/EC of the + European Parliament and of the Council of 11 March 1996 on the legal + protection of databases, and under any national implementation thereof, + including any amended or successor version of such directive); and + + vii. other similar, equivalent or corresponding rights throughout the world + based on applicable law or treaty, and any national implementations thereof. + +2. Waiver. To the greatest extent permitted by, but not in contravention of, +applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and +unconditionally waives, abandons, and surrenders all of Affirmer's Copyright +and Related Rights and associated claims and causes of action, whether now +known or unknown (including existing as well as future claims and causes of +action), in the Work (i) in all territories worldwide, (ii) for the maximum +duration provided by applicable law or treaty (including future time +extensions), (iii) in any current or future medium and for any number of +copies, and (iv) for any purpose whatsoever, including without limitation +commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes +the Waiver for the benefit of each member of the public at large and to the +detriment of Affirmer's heirs and successors, fully intending that such Waiver +shall not be subject to revocation, rescission, cancellation, termination, or +any other legal or equitable action to disrupt the quiet enjoyment of the Work +by the public as contemplated by Affirmer's express Statement of Purpose. + +3. Public License Fallback. Should any part of the Waiver for any reason be +judged legally invalid or ineffective under applicable law, then the Waiver +shall be preserved to the maximum extent permitted taking into account +Affirmer's express Statement of Purpose. In addition, to the extent the Waiver +is so judged Affirmer hereby grants to each affected person a royalty-free, +non transferable, non sublicensable, non exclusive, irrevocable and +unconditional license to exercise Affirmer's Copyright and Related Rights in +the Work (i) in all territories worldwide, (ii) for the maximum duration +provided by applicable law or treaty (including future time extensions), (iii) +in any current or future medium and for any number of copies, and (iv) for any +purpose whatsoever, including without limitation commercial, advertising or +promotional purposes (the "License"). The License shall be deemed effective as +of the date CC0 was applied by Affirmer to the Work. Should any part of the +License for any reason be judged legally invalid or ineffective under +applicable law, such partial invalidity or ineffectiveness shall not +invalidate the remainder of the License, and in such case Affirmer hereby +affirms that he or she will not (i) exercise any of his or her remaining +Copyright and Related Rights in the Work or (ii) assert any associated claims +and causes of action with respect to the Work, in either case contrary to +Affirmer's express Statement of Purpose. + +4. Limitations and Disclaimers. + + a. No trademark or patent rights held by Affirmer are waived, abandoned, + surrendered, licensed or otherwise affected by this document. + + b. Affirmer offers the Work as-is and makes no representations or warranties + of any kind concerning the Work, express, implied, statutory or otherwise, + including without limitation warranties of title, merchantability, fitness + for a particular purpose, non infringement, or the absence of latent or + other defects, accuracy, or the present or absence of errors, whether or not + discoverable, all to the greatest extent permissible under applicable law. + + c. Affirmer disclaims responsibility for clearing rights of other persons + that may apply to the Work or any use thereof, including without limitation + any person's Copyright and Related Rights in the Work. Further, Affirmer + disclaims responsibility for obtaining any necessary consents, permissions + or other rights required for any use of the Work. + + d. Affirmer understands and acknowledges that Creative Commons is not a + party to this document and has no duty or obligation with respect to this + CC0 or use of the Work. + +For more information, please see + diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/address.c b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/address.c new file mode 100644 index 0000000000..b956e9cb29 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/address.c @@ -0,0 +1,91 @@ +#include +#include + +#include "address.h" +#include "params.h" +#include "utils.h" + +/* + * Specify which level of Merkle tree (the "layer") we're working on + */ +void set_layer_addr(uint32_t addr[8], uint32_t layer) { + ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; +} + +/* + * Specify which Merkle tree within the level (the "tree address") we're working on + */ +void set_tree_addr(uint32_t addr[8], uint64_t tree) { + ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); +} + +/* + * Specify the reason we'll use this address structure for, that is, what + * hash will we compute with it. This is used so that unrelated types of + * hashes don't accidentally get the same address structure. The type will be + * one of the SPX_ADDR_TYPE constants + */ +void set_type(uint32_t addr[8], uint32_t type) { + ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; +} + +/* + * Copy the layer and tree fields of the address structure. This is used + * when we're doing multiple types of hashes within the same Merkle tree + */ +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); +} + +/* These functions are used for OTS addresses. */ + +/* + * Specify which Merkle leaf we're working on; that is, which OTS keypair + * we're talking about. + */ +void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { + ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; +} + +/* + * Copy the layer, tree and keypair fields of the address structure. This is + * used when we're doing multiple things within the same OTS keypair + */ +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); + ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; +} + +/* + * Specify which Merkle chain within the OTS we're working with + * (the chain address) + */ +void set_chain_addr(uint32_t addr[8], uint32_t chain) { + ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; +} + +/* + * Specify where in the Merkle chain we are +* (the hash address) + */ +void set_hash_addr(uint32_t addr[8], uint32_t hash) { + ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; +} + +/* These functions are used for all hash tree addresses (including FORS). */ + +/* + * Specify the height of the node in the Merkle/FORS tree we are in + * (the tree height) + */ +void set_tree_height(uint32_t addr[8], uint32_t tree_height) { + ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; +} + +/* + * Specify the distance from the left edge of the node in the Merkle/FORS tree + * (the tree index) + */ +void set_tree_index(uint32_t addr[8], uint32_t tree_index) { + u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/address.h b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/address.h new file mode 100644 index 0000000000..24a84eb40c --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/address.h @@ -0,0 +1,52 @@ +#ifndef SPX_ADDRESS_H +#define SPX_ADDRESS_H + +#include + +#include "params.h" + +/* The hash types that are passed to set_type */ +#define SPX_ADDR_TYPE_WOTS 0 +#define SPX_ADDR_TYPE_WOTSPK 1 +#define SPX_ADDR_TYPE_HASHTREE 2 +#define SPX_ADDR_TYPE_FORSTREE 3 +#define SPX_ADDR_TYPE_FORSPK 4 +#define SPX_ADDR_TYPE_WOTSPRF 5 +#define SPX_ADDR_TYPE_FORSPRF 6 + +#define set_layer_addr SPX_NAMESPACE(set_layer_addr) +void set_layer_addr(uint32_t addr[8], uint32_t layer); + +#define set_tree_addr SPX_NAMESPACE(set_tree_addr) +void set_tree_addr(uint32_t addr[8], uint64_t tree); + +#define set_type SPX_NAMESPACE(set_type) +void set_type(uint32_t addr[8], uint32_t type); + +/* Copies the layer and tree part of one address into the other */ +#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); + +/* These functions are used for WOTS and FORS addresses. */ + +#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) +void set_keypair_addr(uint32_t addr[8], uint32_t keypair); + +#define set_chain_addr SPX_NAMESPACE(set_chain_addr) +void set_chain_addr(uint32_t addr[8], uint32_t chain); + +#define set_hash_addr SPX_NAMESPACE(set_hash_addr) +void set_hash_addr(uint32_t addr[8], uint32_t hash); + +#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); + +/* These functions are used for all hash tree addresses (including FORS). */ + +#define set_tree_height SPX_NAMESPACE(set_tree_height) +void set_tree_height(uint32_t addr[8], uint32_t tree_height); + +#define set_tree_index SPX_NAMESPACE(set_tree_index) +void set_tree_index(uint32_t addr[8], uint32_t tree_index); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/api.h b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/api.h new file mode 100644 index 0000000000..2748190643 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/api.h @@ -0,0 +1,77 @@ +#ifndef PQCLEAN_SPHINCSSHA2128FROBUST_AVX2_API_H +#define PQCLEAN_SPHINCSSHA2128FROBUST_AVX2_API_H + +#include +#include + +#define PQCLEAN_SPHINCSSHA2128FROBUST_AVX2_CRYPTO_ALGNAME "SPHINCS+-sha2-128f-robust" + +#define PQCLEAN_SPHINCSSHA2128FROBUST_AVX2_CRYPTO_SECRETKEYBYTES 64 +#define PQCLEAN_SPHINCSSHA2128FROBUST_AVX2_CRYPTO_PUBLICKEYBYTES 32 +#define PQCLEAN_SPHINCSSHA2128FROBUST_AVX2_CRYPTO_BYTES 17088 + +#define PQCLEAN_SPHINCSSHA2128FROBUST_AVX2_CRYPTO_SEEDBYTES 48 + +/* + * Returns the length of a secret key, in bytes + */ +size_t PQCLEAN_SPHINCSSHA2128FROBUST_AVX2_crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +size_t PQCLEAN_SPHINCSSHA2128FROBUST_AVX2_crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +size_t PQCLEAN_SPHINCSSHA2128FROBUST_AVX2_crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +size_t PQCLEAN_SPHINCSSHA2128FROBUST_AVX2_crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +int PQCLEAN_SPHINCSSHA2128FROBUST_AVX2_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +int PQCLEAN_SPHINCSSHA2128FROBUST_AVX2_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +int PQCLEAN_SPHINCSSHA2128FROBUST_AVX2_crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +int PQCLEAN_SPHINCSSHA2128FROBUST_AVX2_crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, + const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +int PQCLEAN_SPHINCSSHA2128FROBUST_AVX2_crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +int PQCLEAN_SPHINCSSHA2128FROBUST_AVX2_crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/context.h b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/context.h new file mode 100644 index 0000000000..200d3c0fb1 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/context.h @@ -0,0 +1,26 @@ +#ifndef SPX_CONTEXT_H +#define SPX_CONTEXT_H + +#include + +#include "params.h" +#include "sha2.h" +#include "sha256avx.h" + +// funky ordering due to optimal padding +typedef struct { + sha256x8ctx statex8_seeded; + sha256ctx state_seeded; + + uint8_t pub_seed[SPX_N]; + uint8_t sk_seed[SPX_N]; +} spx_ctx; + + +#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) +void initialize_hash_function(spx_ctx *ctx); + +#define free_hash_function SPX_NAMESPACE(free_hash_function) +void free_hash_function(spx_ctx *ctx); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/context_sha2.c b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/context_sha2.c new file mode 100644 index 0000000000..073af8dd15 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/context_sha2.c @@ -0,0 +1,44 @@ +#include + +#include "context.h" + +/** + * Absorb the constant pub_seed using one round of the compression function + * This initializes state_seeded and state_seeded_512, which can then be + * reused in thash + **/ +static void seed_state(spx_ctx *ctx) { + uint8_t block[SPX_SHA512_BLOCK_BYTES]; + size_t i; + + for (i = 0; i < SPX_N; ++i) { + block[i] = ctx->pub_seed[i]; + } + for (i = SPX_N; i < SPX_SHA512_BLOCK_BYTES; ++i) { + block[i] = 0; + } + /* block has been properly initialized for both SHA-256 and SHA-512 */ + + sha256_inc_init(&ctx->state_seeded); + sha256_inc_blocks(&ctx->state_seeded, block, 1); + + // initialize x8 + sha256_init8x(&ctx->statex8_seeded); + sha256_transform8x(&ctx->statex8_seeded, + block, block, block, block, block, block, block, block); + + ctx->statex8_seeded.datalen = 0; + ctx->statex8_seeded.msglen = 512; + +} + + +/* For SHA, we initialize the hash function at the start */ +void initialize_hash_function(spx_ctx *ctx) { + seed_state(ctx); +} + +/* Free the incremental hashing context for heap-based SHA2 APIs */ +void free_hash_function(spx_ctx *ctx) { + sha256_inc_ctx_release(&ctx->state_seeded); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/fors.c b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/fors.c new file mode 100644 index 0000000000..4cab8e7415 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/fors.c @@ -0,0 +1,226 @@ +#include +#include +#include + +#include "fors.h" + + +#include "address.h" +#include "hash.h" +#include "hashx8.h" +#include "thash.h" +#include "thashx8.h" +#include "utils.h" +#include "utilsx8.h" +static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + prf_addr(sk, ctx, fors_leaf_addr); +} + +static void fors_gen_skx8(unsigned char *sk0, + unsigned char *sk1, + unsigned char *sk2, + unsigned char *sk3, + unsigned char *sk4, + unsigned char *sk5, + unsigned char *sk6, + unsigned char *sk7, const spx_ctx *ctx, + uint32_t fors_leaf_addrx8[8 * 8]) { + prf_addrx8(sk0, sk1, sk2, sk3, sk4, sk5, sk6, sk7, + ctx, fors_leaf_addrx8); +} + +static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, + const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + thash(leaf, sk, 1, ctx, fors_leaf_addr); +} + +static void fors_sk_to_leafx8(unsigned char *leaf0, + unsigned char *leaf1, + unsigned char *leaf2, + unsigned char *leaf3, + unsigned char *leaf4, + unsigned char *leaf5, + unsigned char *leaf6, + unsigned char *leaf7, + const unsigned char *sk0, + const unsigned char *sk1, + const unsigned char *sk2, + const unsigned char *sk3, + const unsigned char *sk4, + const unsigned char *sk5, + const unsigned char *sk6, + const unsigned char *sk7, + const spx_ctx *ctx, + uint32_t fors_leaf_addrx8[8 * 8]) { + thashx8(leaf0, leaf1, leaf2, leaf3, leaf4, leaf5, leaf6, leaf7, + sk0, sk1, sk2, sk3, sk4, sk5, sk6, sk7, + 1, ctx, fors_leaf_addrx8); +} + +struct fors_gen_leaf_info { + uint32_t leaf_addrx[8 * 8]; +}; + +static void fors_gen_leafx8(unsigned char *leaf, + const spx_ctx *ctx, + uint32_t addr_idx, void *info) { + struct fors_gen_leaf_info *fors_info = info; + uint32_t *fors_leaf_addrx8 = fors_info->leaf_addrx; + unsigned int j; + + /* Only set the parts that the caller doesn't set */ + for (j = 0; j < 8; j++) { + set_tree_index(fors_leaf_addrx8 + j * 8, addr_idx + j); + set_type(fors_leaf_addrx8 + j * 8, SPX_ADDR_TYPE_FORSPRF); + } + + fors_gen_skx8(leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + leaf + 2 * SPX_N, + leaf + 3 * SPX_N, + leaf + 4 * SPX_N, + leaf + 5 * SPX_N, + leaf + 6 * SPX_N, + leaf + 7 * SPX_N, + ctx, fors_leaf_addrx8); + + for (j = 0; j < 8; j++) { + set_type(fors_leaf_addrx8 + j * 8, SPX_ADDR_TYPE_FORSTREE); + } + + fors_sk_to_leafx8(leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + leaf + 2 * SPX_N, + leaf + 3 * SPX_N, + leaf + 4 * SPX_N, + leaf + 5 * SPX_N, + leaf + 6 * SPX_N, + leaf + 7 * SPX_N, + leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + leaf + 2 * SPX_N, + leaf + 3 * SPX_N, + leaf + 4 * SPX_N, + leaf + 5 * SPX_N, + leaf + 6 * SPX_N, + leaf + 7 * SPX_N, + ctx, fors_leaf_addrx8); +} + +/** + * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + * Assumes indices has space for SPX_FORS_TREES integers. + */ +static void message_to_indices(uint32_t *indices, const unsigned char *m) { + unsigned int i, j; + unsigned int offset = 0; + + for (i = 0; i < SPX_FORS_TREES; i++) { + indices[i] = 0; + for (j = 0; j < SPX_FORS_HEIGHT; j++) { + indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); + offset++; + } + } +} + +/** + * Signs a message m, deriving the secret key from sk_seed and the FTS address. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + uint32_t fors_tree_addr[8 * 8] = {0}; + struct fors_gen_leaf_info fors_info = {0}; + uint32_t *fors_leaf_addr = fors_info.leaf_addrx; + uint32_t fors_pk_addr[8] = {0}; + uint32_t idx_offset; + unsigned int i; + + for (i = 0; i < 8; i++) { + copy_keypair_addr(fors_tree_addr + 8 * i, fors_addr); + set_type(fors_tree_addr + 8 * i, SPX_ADDR_TYPE_FORSTREE); + copy_keypair_addr(fors_leaf_addr + 8 * i, fors_addr); + } + copy_keypair_addr(fors_pk_addr, fors_addr); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); + + message_to_indices(indices, m); + + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); + + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + + /* Include the secret key part that produces the selected leaf node. */ + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); + fors_gen_sk(sig, ctx, fors_tree_addr); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + sig += SPX_N; + + /* Compute the authentication path for this leaf node. */ + treehashx8(roots + i * SPX_N, sig, ctx, + indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx8, + fors_tree_addr, &fors_info); + + sig += SPX_N * SPX_FORS_HEIGHT; + } + + /* Hash horizontally across all tree roots to derive the public key. */ + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); +} + +/** + * Derives the FORS public key from a signature. + * This can be used for verification by comparing to a known public key, or to + * subsequently verify a signature on the derived public key. The latter is the + * typical use-case when used as an FTS below an OTS in a hypertree. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + unsigned char leaf[SPX_N]; + uint32_t fors_tree_addr[8] = {0}; + uint32_t fors_pk_addr[8] = {0}; + uint32_t idx_offset; + unsigned int i; + + copy_keypair_addr(fors_tree_addr, fors_addr); + copy_keypair_addr(fors_pk_addr, fors_addr); + + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); + + message_to_indices(indices, m); + + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); + + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + + /* Derive the leaf from the included secret key part. */ + fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); + sig += SPX_N; + + /* Derive the corresponding root node of this tree. */ + compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, + sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); + sig += SPX_N * SPX_FORS_HEIGHT; + } + + /* Hash horizontally across all tree roots to derive the public key. */ + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/fors.h b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/fors.h new file mode 100644 index 0000000000..509140a178 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/fors.h @@ -0,0 +1,32 @@ +#ifndef SPX_FORS_H +#define SPX_FORS_H + +#include + +#include "context.h" +#include "params.h" + +/** + * Signs a message m, deriving the secret key from sk_seed and the FTS address. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +#define fors_sign SPX_NAMESPACE(fors_sign) +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); + +/** + * Derives the FORS public key from a signature. + * This can be used for verification by comparing to a known public key, or to + * subsequently verify a signature on the derived public key. The latter is the + * typical use-case when used as an FTS below an OTS in a hypertree. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/hash.h b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/hash.h new file mode 100644 index 0000000000..ffe815f45d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/hash.h @@ -0,0 +1,37 @@ +#ifndef SPX_HASH_H +#define SPX_HASH_H + +#include +#include + +#include "context.h" +#include "params.h" + +#define prf_addr SPX_NAMESPACE(prf_addr) +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]); + +#define gen_message_random SPX_NAMESPACE(gen_message_random) +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); + +#define hash_message SPX_NAMESPACE(hash_message) +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); + + +# define SPX_SHA256_ADDR_BYTES 22 + +# define mgf1_256 SPX_NAMESPACE(mgf1_256) +void mgf1_256(unsigned char *out, unsigned long outlen, + const unsigned char *in, unsigned long inlen); + +# define mgf1_512 SPX_NAMESPACE(mgf1_512) +void mgf1_512(unsigned char *out, unsigned long outlen, + const unsigned char *in, unsigned long inlen); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/hash_sha2.c b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/hash_sha2.c new file mode 100644 index 0000000000..69f0dc0013 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/hash_sha2.c @@ -0,0 +1,219 @@ +#include +#include + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "sha2.h" +#include "utils.h" + + + +#define SPX_SHAX_OUTPUT_BYTES SPX_SHA256_OUTPUT_BYTES +#define SPX_SHAX_BLOCK_BYTES SPX_SHA256_BLOCK_BYTES +#define shaX_inc_init sha256_inc_init +#define shaX_inc_blocks sha256_inc_blocks +#define shaX_inc_finalize sha256_inc_finalize +#define shaX sha256 +#define mgf1_X mgf1_256 +#define shaXstate sha256ctx + +/** + * mgf1 function based on the SHA-256 hash function + * Note that inlen should be sufficiently small that it still allows for + * an array to be allocated on the stack. Typically 'in' is merely a seed. + * Outputs outlen number of bytes + */ +void mgf1_256(unsigned char *out, unsigned long outlen, + const unsigned char *in, unsigned long inlen) { + PQCLEAN_VLA(uint8_t, inbuf, inlen + 4); + unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES]; + uint32_t i; + + memcpy(inbuf, in, inlen); + + /* While we can fit in at least another full block of SHA256 output.. */ + for (i = 0; (i + 1)*SPX_SHA256_OUTPUT_BYTES <= outlen; i++) { + u32_to_bytes(inbuf + inlen, i); + sha256(out, inbuf, inlen + 4); + out += SPX_SHA256_OUTPUT_BYTES; + } + /* Until we cannot anymore, and we fill the remainder. */ + if (outlen > i * SPX_SHA256_OUTPUT_BYTES) { + u32_to_bytes(inbuf + inlen, i); + sha256(outbuf, inbuf, inlen + 4); + memcpy(out, outbuf, outlen - i * SPX_SHA256_OUTPUT_BYTES); + } +} + +/* + * mgf1 function based on the SHA-512 hash function + */ +void mgf1_512(unsigned char *out, unsigned long outlen, + const unsigned char *in, unsigned long inlen) { + PQCLEAN_VLA(uint8_t, inbuf, inlen + 4); + unsigned char outbuf[SPX_SHA512_OUTPUT_BYTES]; + uint32_t i; + + memcpy(inbuf, in, inlen); + + /* While we can fit in at least another full block of SHA512 output.. */ + for (i = 0; (i + 1)*SPX_SHA512_OUTPUT_BYTES <= outlen; i++) { + u32_to_bytes(inbuf + inlen, i); + sha512(out, inbuf, inlen + 4); + out += SPX_SHA512_OUTPUT_BYTES; + } + /* Until we cannot anymore, and we fill the remainder. */ + if (outlen > i * SPX_SHA512_OUTPUT_BYTES) { + u32_to_bytes(inbuf + inlen, i); + sha512(outbuf, inbuf, inlen + 4); + memcpy(out, outbuf, outlen - i * SPX_SHA512_OUTPUT_BYTES); + } +} + +/* + * Computes PRF(pk_seed, sk_seed, addr). + */ +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]) { + sha256ctx sha2_state; + unsigned char buf[SPX_SHA256_ADDR_BYTES + SPX_N]; + unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES]; + + /* Retrieve precomputed state containing pub_seed */ + sha256_inc_ctx_clone(&sha2_state, &ctx->state_seeded); + + /* Remainder: ADDR^c ‖ SK.seed */ + memcpy(buf, addr, SPX_SHA256_ADDR_BYTES); + memcpy(buf + SPX_SHA256_ADDR_BYTES, ctx->sk_seed, SPX_N); + + sha256_inc_finalize(outbuf, &sha2_state, buf, SPX_SHA256_ADDR_BYTES + SPX_N); + + memcpy(out, outbuf, SPX_N); +} + +/** + * Computes the message-dependent randomness R, using a secret seed as a key + * for HMAC, and an optional randomization value prefixed to the message. + * This requires m to have at least SPX_SHAX_BLOCK_BYTES + SPX_N space + * available in front of the pointer, i.e. before the message to use for the + * prefix. This is necessary to prevent having to move the message around (and + * allocate memory for it). + */ +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { + (void)ctx; + + unsigned char buf[SPX_SHAX_BLOCK_BYTES + SPX_SHAX_OUTPUT_BYTES]; + shaXstate state; + int i; + + + /* This implements HMAC-SHA */ + for (i = 0; i < SPX_N; i++) { + buf[i] = 0x36 ^ sk_prf[i]; + } + memset(buf + SPX_N, 0x36, SPX_SHAX_BLOCK_BYTES - SPX_N); + + shaX_inc_init(&state); + shaX_inc_blocks(&state, buf, 1); + + memcpy(buf, optrand, SPX_N); + + /* If optrand + message cannot fill up an entire block */ + if (SPX_N + mlen < SPX_SHAX_BLOCK_BYTES) { + memcpy(buf + SPX_N, m, mlen); + shaX_inc_finalize(buf + SPX_SHAX_BLOCK_BYTES, &state, + buf, mlen + SPX_N); + } + /* Otherwise first fill a block, so that finalize only uses the message */ + else { + memcpy(buf + SPX_N, m, SPX_SHAX_BLOCK_BYTES - SPX_N); + shaX_inc_blocks(&state, buf, 1); + + m += SPX_SHAX_BLOCK_BYTES - SPX_N; + mlen -= SPX_SHAX_BLOCK_BYTES - SPX_N; + shaX_inc_finalize(buf + SPX_SHAX_BLOCK_BYTES, &state, m, mlen); + } + + for (i = 0; i < SPX_N; i++) { + buf[i] = 0x5c ^ sk_prf[i]; + } + memset(buf + SPX_N, 0x5c, SPX_SHAX_BLOCK_BYTES - SPX_N); + + shaX(buf, buf, SPX_SHAX_BLOCK_BYTES + SPX_SHAX_OUTPUT_BYTES); + memcpy(R, buf, SPX_N); +} + +/** + * Computes the message hash using R, the public key, and the message. + * Outputs the message digest and the index of the leaf. The index is split in + * the tree index and the leaf index, for convenient copying to an address. + */ +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { + (void)ctx; +#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) +#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) +#define SPX_LEAF_BITS SPX_TREE_HEIGHT +#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) +#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) + + unsigned char seed[2 * SPX_N + SPX_SHAX_OUTPUT_BYTES]; + + /* Round to nearest multiple of SPX_SHAX_BLOCK_BYTES */ +#define SPX_INBLOCKS (((SPX_N + SPX_PK_BYTES + SPX_SHAX_BLOCK_BYTES - 1) & \ + -SPX_SHAX_BLOCK_BYTES) / SPX_SHAX_BLOCK_BYTES) + unsigned char inbuf[SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES]; + + unsigned char buf[SPX_DGST_BYTES]; + unsigned char *bufp = buf; + shaXstate state; + + shaX_inc_init(&state); + + // seed: SHA-X(R ‖ PK.seed ‖ PK.root ‖ M) + memcpy(inbuf, R, SPX_N); + memcpy(inbuf + SPX_N, pk, SPX_PK_BYTES); + + /* If R + pk + message cannot fill up an entire block */ + if (SPX_N + SPX_PK_BYTES + mlen < SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES) { + memcpy(inbuf + SPX_N + SPX_PK_BYTES, m, mlen); + shaX_inc_finalize(seed + 2 * SPX_N, &state, inbuf, SPX_N + SPX_PK_BYTES + mlen); + } + /* Otherwise first fill a block, so that finalize only uses the message */ + else { + memcpy(inbuf + SPX_N + SPX_PK_BYTES, m, + SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES - SPX_N - SPX_PK_BYTES); + shaX_inc_blocks(&state, inbuf, SPX_INBLOCKS); + + m += SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES - SPX_N - SPX_PK_BYTES; + mlen -= SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES - SPX_N - SPX_PK_BYTES; + shaX_inc_finalize(seed + 2 * SPX_N, &state, m, (size_t)mlen); + } + + // H_msg: MGF1-SHA-X(R ‖ PK.seed ‖ seed) + memcpy(seed, R, SPX_N); + memcpy(seed + SPX_N, pk, SPX_N); + + /* By doing this in two steps, we prevent hashing the message twice; + otherwise each iteration in MGF1 would hash the message again. */ + mgf1_X(bufp, SPX_DGST_BYTES, seed, 2 * SPX_N + SPX_SHAX_OUTPUT_BYTES); + + memcpy(digest, bufp, SPX_FORS_MSG_BYTES); + bufp += SPX_FORS_MSG_BYTES; + + + *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); + *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); + bufp += SPX_TREE_BYTES; + + *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); + *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); +} + + diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/hash_sha2x8.c b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/hash_sha2x8.c new file mode 100644 index 0000000000..e04af7a069 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/hash_sha2x8.c @@ -0,0 +1,75 @@ +#include +#include + +#include "hash.h" +#include "hashx8.h" + +#include "address.h" +#include "params.h" +#include "sha2.h" +#include "sha256avx.h" +#include "sha256x8.h" +#include "utils.h" + +/* + * 8-way parallel version of prf_addr; takes 8x as much input and output + */ +void prf_addrx8(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const spx_ctx *ctx, + const uint32_t addrx8[8 * 8]) { + unsigned char bufx8[8 * (SPX_N + SPX_SHA256_ADDR_BYTES)]; + unsigned char outbufx8[8 * SPX_SHA256_OUTPUT_BYTES]; + unsigned int j; + + for (j = 0; j < 8; j++) { + memcpy(bufx8 + j * (SPX_N + SPX_SHA256_ADDR_BYTES), + addrx8 + j * 8, SPX_SHA256_ADDR_BYTES); + memcpy( + bufx8 + j * (SPX_N + SPX_SHA256_ADDR_BYTES) + SPX_SHA256_ADDR_BYTES, + ctx->sk_seed, + SPX_N + ); + } + + sha256x8_seeded( + /* out */ + outbufx8 + 0 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 1 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 2 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 3 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 4 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 5 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 6 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 7 * SPX_SHA256_OUTPUT_BYTES, + + /* seed */ + &ctx->statex8_seeded, + + /* in */ + bufx8 + 0 * (SPX_SHA256_ADDR_BYTES + SPX_N), + bufx8 + 1 * (SPX_SHA256_ADDR_BYTES + SPX_N), + bufx8 + 2 * (SPX_SHA256_ADDR_BYTES + SPX_N), + bufx8 + 3 * (SPX_SHA256_ADDR_BYTES + SPX_N), + bufx8 + 4 * (SPX_SHA256_ADDR_BYTES + SPX_N), + bufx8 + 5 * (SPX_SHA256_ADDR_BYTES + SPX_N), + bufx8 + 6 * (SPX_SHA256_ADDR_BYTES + SPX_N), + bufx8 + 7 * (SPX_SHA256_ADDR_BYTES + SPX_N), + SPX_SHA256_ADDR_BYTES + SPX_N /* len */ + ); + + memcpy(out0, outbufx8 + 0 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out1, outbufx8 + 1 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out2, outbufx8 + 2 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out3, outbufx8 + 3 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out4, outbufx8 + 4 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out5, outbufx8 + 5 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out6, outbufx8 + 6 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out7, outbufx8 + 7 * SPX_SHA256_OUTPUT_BYTES, SPX_N); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/hashx8.h b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/hashx8.h new file mode 100644 index 0000000000..46503f0a10 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/hashx8.h @@ -0,0 +1,20 @@ +#ifndef SPX_HASHX8_H +#define SPX_HASHX8_H + +#include + +#include "params.h" + +#define prf_addrx8 SPX_NAMESPACE(prf_addrx8) +void prf_addrx8(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const spx_ctx *ctx, + const uint32_t addrx8[8 * 8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/merkle.c b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/merkle.c new file mode 100644 index 0000000000..1f353c8dd8 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/merkle.c @@ -0,0 +1,65 @@ +#include +#include + +#include "merkle.h" + +#include "address.h" +#include "params.h" +#include "utils.h" +#include "utilsx8.h" +#include "wots.h" +#include "wotsx8.h" + +/* + * This generates a Merkle signature (WOTS signature followed by the Merkle + * authentication path). + */ +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf) { + unsigned char *auth_path = sig + SPX_WOTS_BYTES; + uint32_t tree_addrx8[8 * 8] = { 0 }; + int j; + struct leaf_info_x8 info = { 0 }; + unsigned steps[ SPX_WOTS_LEN ]; + + info.wots_sig = sig; + chain_lengths(steps, root); + info.wots_steps = steps; + + for (j = 0; j < 8; j++) { + set_type(&tree_addrx8[8 * j], SPX_ADDR_TYPE_HASHTREE); + set_type(&info.leaf_addr[8 * j], SPX_ADDR_TYPE_WOTS); + set_type(&info.pk_addr[8 * j], SPX_ADDR_TYPE_WOTSPK); + copy_subtree_addr(&tree_addrx8[8 * j], tree_addr); + copy_subtree_addr(&info.leaf_addr[8 * j], wots_addr); + copy_subtree_addr(&info.pk_addr[8 * j], wots_addr); + } + + info.wots_sign_leaf = idx_leaf; + + treehashx8(root, auth_path, ctx, + idx_leaf, 0, + SPX_TREE_HEIGHT, + wots_gen_leafx8, + tree_addrx8, &info); +} + +/* Compute root node of the top-most subtree. */ +/* Again, in this file because wots_gen_leaf is most of the work */ +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { + /* We do not need the auth path in key generation, but it simplifies the + code to have just one treehash routine that computes both root and path + in one function. */ + unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; + uint32_t top_tree_addr[8] = {0}; + uint32_t wots_addr[8] = {0}; + + set_layer_addr(top_tree_addr, SPX_D - 1); + set_layer_addr(wots_addr, SPX_D - 1); + + merkle_sign(auth_path, root, ctx, + wots_addr, top_tree_addr, + ~0U /* ~0 means "don't bother generating an auth path */ ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/merkle.h b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/merkle.h new file mode 100644 index 0000000000..769cf2e970 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/merkle.h @@ -0,0 +1,21 @@ +#ifndef MERKLE_H_ +#define MERKLE_H_ + +#include + +#include "context.h" +#include "params.h" + +/* Generate a Merkle signature (WOTS signature followed by the Merkle */ +/* authentication path) */ +#define merkle_sign SPX_NAMESPACE(merkle_sign) +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf); + +/* Compute the root node of the top-most subtree. */ +#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); + +#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/nistapi.h b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/nistapi.h new file mode 100644 index 0000000000..3cb71afad4 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/nistapi.h @@ -0,0 +1,87 @@ +#ifndef SPX_API_H +#define SPX_API_H + +#include +#include + +#include "params.h" + +#define CRYPTO_ALGNAME "SPHINCS+" + +#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES +#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES +#define CRYPTO_BYTES SPX_BYTES +#define CRYPTO_SEEDBYTES (3*SPX_N) + +/* + * Returns the length of a secret key, in bytes + */ +#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) +size_t crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) +size_t crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) +size_t crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) +size_t crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +#define crypto_sign SPX_NAMESPACE(crypto_sign) +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/params.h b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/params.h new file mode 100644 index 0000000000..73e2f8c913 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/params.h @@ -0,0 +1,61 @@ +#ifndef SPX_PARAMS_H +#define SPX_PARAMS_H + +#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSSHA2128FROBUST_AVX2_##s + +/* Hash output length in bytes. */ +#define SPX_N 16 +/* Height of the hypertree. */ +#define SPX_FULL_HEIGHT 66 +/* Number of subtree layer. */ +#define SPX_D 22 +/* FORS tree dimensions. */ +#define SPX_FORS_HEIGHT 6 +#define SPX_FORS_TREES 33 +/* Winternitz parameter, */ +#define SPX_WOTS_W 16 + +/* The hash function is defined by linking a different hash.c file, as opposed + to setting a #define constant. */ + +/* This is a SHA2-based parameter set, hence whether we use SHA-256 + * exclusively or we use both SHA-256 and SHA-512 is controlled by + * the following #define */ +#define SPX_SHA512 0 /* Use SHA-256 for all hashes */ + +/* For clarity */ +#define SPX_ADDR_BYTES 32 + +/* WOTS parameters. */ +#define SPX_WOTS_LOGW 4 + +#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) + +/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ +#define SPX_WOTS_LEN2 3 + +#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) +#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) +#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES + +/* Subtree size. */ +#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) + +//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT +// #error SPX_D should always divide SPX_FULL_HEIGHT +//#endif + +/* FORS parameters. */ +#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) +#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) +#define SPX_FORS_PK_BYTES SPX_N + +/* Resulting SPX sizes. */ +#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ + SPX_FULL_HEIGHT * SPX_N) +#define SPX_PK_BYTES (2 * SPX_N) +#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) + +#include "sha2_offsets.h" + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/sha256avx.c b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/sha256avx.c new file mode 100644 index 0000000000..6bbe6ecc24 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/sha256avx.c @@ -0,0 +1,357 @@ +#include +#include +#include + +#include "sha256avx.h" + +static const unsigned int RC[] = { + 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, + 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, + 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, + 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, + 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, + 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, + 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, + 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, + 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, + 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, + 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, + 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, + 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, + 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, + 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, + 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 +}; + +#define u32 uint32_t +#define u256 __m256i + +#define XOR _mm256_xor_si256 +#define OR _mm256_or_si256 +#define AND _mm256_and_si256 +#define ADD32 _mm256_add_epi32 +#define NOT(x) _mm256_xor_si256(x, _mm256_set_epi32(-1, -1, -1, -1, -1, -1, -1, -1)) + +#define LOAD(src) _mm256_loadu_si256((__m256i *)(src)) +#define STORE(dest,src) _mm256_storeu_si256((__m256i *)(dest),src) + +#define BYTESWAP(x) _mm256_shuffle_epi8(x, _mm256_set_epi8(0xc,0xd,0xe,0xf,0x8,0x9,0xa,0xb,0x4,0x5,0x6,0x7,0x0,0x1,0x2,0x3,0xc,0xd,0xe,0xf,0x8,0x9,0xa,0xb,0x4,0x5,0x6,0x7,0x0,0x1,0x2,0x3)) + +#define SHIFTR32(x, y) _mm256_srli_epi32(x, y) +#define SHIFTL32(x, y) _mm256_slli_epi32(x, y) + +#define ROTR32(x, y) OR(SHIFTR32(x, y), SHIFTL32(x, 32 - (y))) +#define ROTL32(x, y) OR(SHIFTL32(x, y), SHIFTR32(x, 32 - (y))) + +#define XOR3(a, b, c) XOR(XOR(a, b), c) + +#define ADD3_32(a, b, c) ADD32(ADD32(a, b), c) +#define ADD4_32(a, b, c, d) ADD32(ADD32(ADD32(a, b), c), d) +#define ADD5_32(a, b, c, d, e) ADD32(ADD32(ADD32(ADD32(a, b), c), d), e) + +#define MAJ_AVX(a, b, c) XOR3(AND(a, b), AND(a, c), AND(b, c)) +#define CH_AVX(a, b, c) XOR(AND(a, b), AND(NOT(a), c)) + +#define SIGMA1_AVX(x) XOR3(ROTR32(x, 6), ROTR32(x, 11), ROTR32(x, 25)) +#define SIGMA0_AVX(x) XOR3(ROTR32(x, 2), ROTR32(x, 13), ROTR32(x, 22)) + +#define WSIGMA1_AVX(x) XOR3(ROTR32(x, 17), ROTR32(x, 19), SHIFTR32(x, 10)) +#define WSIGMA0_AVX(x) XOR3(ROTR32(x, 7), ROTR32(x, 18), SHIFTR32(x, 3)) + +#define SHA256ROUND_AVX(a, b, c, d, e, f, g, h, rc, w) \ + T0 = ADD5_32(h, SIGMA1_AVX(e), CH_AVX(e, f, g), _mm256_set1_epi32((int)RC[rc]), w); \ + (d) = ADD32(d, T0); \ + T1 = ADD32(SIGMA0_AVX(a), MAJ_AVX(a, b, c)); \ + (h) = ADD32(T0, T1); + +// Transpose 8 vectors containing 32-bit values +static void transpose(u256 s[8]) { + u256 tmp0[8]; + u256 tmp1[8]; + tmp0[0] = _mm256_unpacklo_epi32(s[0], s[1]); + tmp0[1] = _mm256_unpackhi_epi32(s[0], s[1]); + tmp0[2] = _mm256_unpacklo_epi32(s[2], s[3]); + tmp0[3] = _mm256_unpackhi_epi32(s[2], s[3]); + tmp0[4] = _mm256_unpacklo_epi32(s[4], s[5]); + tmp0[5] = _mm256_unpackhi_epi32(s[4], s[5]); + tmp0[6] = _mm256_unpacklo_epi32(s[6], s[7]); + tmp0[7] = _mm256_unpackhi_epi32(s[6], s[7]); + tmp1[0] = _mm256_unpacklo_epi64(tmp0[0], tmp0[2]); + tmp1[1] = _mm256_unpackhi_epi64(tmp0[0], tmp0[2]); + tmp1[2] = _mm256_unpacklo_epi64(tmp0[1], tmp0[3]); + tmp1[3] = _mm256_unpackhi_epi64(tmp0[1], tmp0[3]); + tmp1[4] = _mm256_unpacklo_epi64(tmp0[4], tmp0[6]); + tmp1[5] = _mm256_unpackhi_epi64(tmp0[4], tmp0[6]); + tmp1[6] = _mm256_unpacklo_epi64(tmp0[5], tmp0[7]); + tmp1[7] = _mm256_unpackhi_epi64(tmp0[5], tmp0[7]); + s[0] = _mm256_permute2x128_si256(tmp1[0], tmp1[4], 0x20); + s[1] = _mm256_permute2x128_si256(tmp1[1], tmp1[5], 0x20); + s[2] = _mm256_permute2x128_si256(tmp1[2], tmp1[6], 0x20); + s[3] = _mm256_permute2x128_si256(tmp1[3], tmp1[7], 0x20); + s[4] = _mm256_permute2x128_si256(tmp1[0], tmp1[4], 0x31); + s[5] = _mm256_permute2x128_si256(tmp1[1], tmp1[5], 0x31); + s[6] = _mm256_permute2x128_si256(tmp1[2], tmp1[6], 0x31); + s[7] = _mm256_permute2x128_si256(tmp1[3], tmp1[7], 0x31); +} + +void sha256_ctx_clone8x(sha256x8ctx *out, const sha256x8ctx *in) { + memcpy(out, in, sizeof(sha256x8ctx)); +} + +void sha256_init8x(sha256x8ctx *ctx) { + ctx->s[0] = _mm256_set_epi32((int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667); + ctx->s[1] = _mm256_set_epi32((int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85); + ctx->s[2] = _mm256_set_epi32((int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372); + ctx->s[3] = _mm256_set_epi32((int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a); + ctx->s[4] = _mm256_set_epi32((int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f); + ctx->s[5] = _mm256_set_epi32((int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c); + ctx->s[6] = _mm256_set_epi32((int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab); + ctx->s[7] = _mm256_set_epi32((int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19); + + ctx->datalen = 0; + ctx->msglen = 0; +} + +void sha256_final8x(sha256x8ctx *ctx, + unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7) { + unsigned int i, curlen; + + // Padding + if (ctx->datalen < 56) { + for (i = 0; i < 8; ++i) { + curlen = ctx->datalen; + ctx->msgblocks[64 * i + curlen++] = 0x80; + while (curlen < 64) { + ctx->msgblocks[64 * i + curlen++] = 0x00; + } + } + } else { + for (i = 0; i < 8; ++i) { + curlen = ctx->datalen; + ctx->msgblocks[64 * i + curlen++] = 0x80; + while (curlen < 64) { + ctx->msgblocks[64 * i + curlen++] = 0x00; + } + } + sha256_transform8x(ctx, + &ctx->msgblocks[64 * 0], + &ctx->msgblocks[64 * 1], + &ctx->msgblocks[64 * 2], + &ctx->msgblocks[64 * 3], + &ctx->msgblocks[64 * 4], + &ctx->msgblocks[64 * 5], + &ctx->msgblocks[64 * 6], + &ctx->msgblocks[64 * 7] + ); + memset(ctx->msgblocks, 0, 8 * 64); + } + + // Add length of the message to each block + ctx->msglen += ctx->datalen * 8; + for (i = 0; i < 8; i++) { + ctx->msgblocks[64 * i + 63] = (unsigned char)(ctx->msglen); + ctx->msgblocks[64 * i + 62] = (unsigned char)(ctx->msglen >> 8); + ctx->msgblocks[64 * i + 61] = (unsigned char)(ctx->msglen >> 16); + ctx->msgblocks[64 * i + 60] = (unsigned char)(ctx->msglen >> 24); + ctx->msgblocks[64 * i + 59] = (unsigned char)(ctx->msglen >> 32); + ctx->msgblocks[64 * i + 58] = (unsigned char)(ctx->msglen >> 40); + ctx->msgblocks[64 * i + 57] = (unsigned char)(ctx->msglen >> 48); + ctx->msgblocks[64 * i + 56] = (unsigned char)(ctx->msglen >> 56); + } + sha256_transform8x(ctx, + &ctx->msgblocks[64 * 0], + &ctx->msgblocks[64 * 1], + &ctx->msgblocks[64 * 2], + &ctx->msgblocks[64 * 3], + &ctx->msgblocks[64 * 4], + &ctx->msgblocks[64 * 5], + &ctx->msgblocks[64 * 6], + &ctx->msgblocks[64 * 7] + ); + + // Compute final hash output + transpose(ctx->s); + + // Store Hash value + STORE(out0, BYTESWAP(ctx->s[0])); + STORE(out1, BYTESWAP(ctx->s[1])); + STORE(out2, BYTESWAP(ctx->s[2])); + STORE(out3, BYTESWAP(ctx->s[3])); + STORE(out4, BYTESWAP(ctx->s[4])); + STORE(out5, BYTESWAP(ctx->s[5])); + STORE(out6, BYTESWAP(ctx->s[6])); + STORE(out7, BYTESWAP(ctx->s[7])); +} + +void sha256_transform8x(sha256x8ctx *ctx, + const unsigned char *data0, + const unsigned char *data1, + const unsigned char *data2, + const unsigned char *data3, + const unsigned char *data4, + const unsigned char *data5, + const unsigned char *data6, + const unsigned char *data7) { + u256 s[8], w[64], T0, T1; + + // Load words and transform data correctly + w[0] = BYTESWAP(LOAD(data0)); + w[0 + 8] = BYTESWAP(LOAD(data0 + 32)); + w[1] = BYTESWAP(LOAD(data1)); + w[1 + 8] = BYTESWAP(LOAD(data1 + 32)); + w[2] = BYTESWAP(LOAD(data2)); + w[2 + 8] = BYTESWAP(LOAD(data2 + 32)); + w[3] = BYTESWAP(LOAD(data3)); + w[3 + 8] = BYTESWAP(LOAD(data3 + 32)); + w[4] = BYTESWAP(LOAD(data4)); + w[4 + 8] = BYTESWAP(LOAD(data4 + 32)); + w[5] = BYTESWAP(LOAD(data5)); + w[5 + 8] = BYTESWAP(LOAD(data5 + 32)); + w[6] = BYTESWAP(LOAD(data6)); + w[6 + 8] = BYTESWAP(LOAD(data6 + 32)); + w[7] = BYTESWAP(LOAD(data7)); + w[7 + 8] = BYTESWAP(LOAD(data7 + 32)); + + transpose(w); + transpose(w + 8); + + // Initial State + s[0] = ctx->s[0]; + s[1] = ctx->s[1]; + s[2] = ctx->s[2]; + s[3] = ctx->s[3]; + s[4] = ctx->s[4]; + s[5] = ctx->s[5]; + s[6] = ctx->s[6]; + s[7] = ctx->s[7]; + + SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 0, w[0]); + SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 1, w[1]); + SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 2, w[2]); + SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 3, w[3]); + SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 4, w[4]); + SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 5, w[5]); + SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 6, w[6]); + SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 7, w[7]); + SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 8, w[8]); + SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 9, w[9]); + SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 10, w[10]); + SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 11, w[11]); + SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 12, w[12]); + SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 13, w[13]); + SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 14, w[14]); + SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 15, w[15]); + w[16] = ADD4_32(WSIGMA1_AVX(w[14]), w[0], w[9], WSIGMA0_AVX(w[1])); + SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 16, w[16]); + w[17] = ADD4_32(WSIGMA1_AVX(w[15]), w[1], w[10], WSIGMA0_AVX(w[2])); + SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 17, w[17]); + w[18] = ADD4_32(WSIGMA1_AVX(w[16]), w[2], w[11], WSIGMA0_AVX(w[3])); + SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 18, w[18]); + w[19] = ADD4_32(WSIGMA1_AVX(w[17]), w[3], w[12], WSIGMA0_AVX(w[4])); + SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 19, w[19]); + w[20] = ADD4_32(WSIGMA1_AVX(w[18]), w[4], w[13], WSIGMA0_AVX(w[5])); + SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 20, w[20]); + w[21] = ADD4_32(WSIGMA1_AVX(w[19]), w[5], w[14], WSIGMA0_AVX(w[6])); + SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 21, w[21]); + w[22] = ADD4_32(WSIGMA1_AVX(w[20]), w[6], w[15], WSIGMA0_AVX(w[7])); + SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 22, w[22]); + w[23] = ADD4_32(WSIGMA1_AVX(w[21]), w[7], w[16], WSIGMA0_AVX(w[8])); + SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 23, w[23]); + w[24] = ADD4_32(WSIGMA1_AVX(w[22]), w[8], w[17], WSIGMA0_AVX(w[9])); + SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 24, w[24]); + w[25] = ADD4_32(WSIGMA1_AVX(w[23]), w[9], w[18], WSIGMA0_AVX(w[10])); + SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 25, w[25]); + w[26] = ADD4_32(WSIGMA1_AVX(w[24]), w[10], w[19], WSIGMA0_AVX(w[11])); + SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 26, w[26]); + w[27] = ADD4_32(WSIGMA1_AVX(w[25]), w[11], w[20], WSIGMA0_AVX(w[12])); + SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 27, w[27]); + w[28] = ADD4_32(WSIGMA1_AVX(w[26]), w[12], w[21], WSIGMA0_AVX(w[13])); + SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 28, w[28]); + w[29] = ADD4_32(WSIGMA1_AVX(w[27]), w[13], w[22], WSIGMA0_AVX(w[14])); + SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 29, w[29]); + w[30] = ADD4_32(WSIGMA1_AVX(w[28]), w[14], w[23], WSIGMA0_AVX(w[15])); + SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 30, w[30]); + w[31] = ADD4_32(WSIGMA1_AVX(w[29]), w[15], w[24], WSIGMA0_AVX(w[16])); + SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 31, w[31]); + w[32] = ADD4_32(WSIGMA1_AVX(w[30]), w[16], w[25], WSIGMA0_AVX(w[17])); + SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 32, w[32]); + w[33] = ADD4_32(WSIGMA1_AVX(w[31]), w[17], w[26], WSIGMA0_AVX(w[18])); + SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 33, w[33]); + w[34] = ADD4_32(WSIGMA1_AVX(w[32]), w[18], w[27], WSIGMA0_AVX(w[19])); + SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 34, w[34]); + w[35] = ADD4_32(WSIGMA1_AVX(w[33]), w[19], w[28], WSIGMA0_AVX(w[20])); + SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 35, w[35]); + w[36] = ADD4_32(WSIGMA1_AVX(w[34]), w[20], w[29], WSIGMA0_AVX(w[21])); + SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 36, w[36]); + w[37] = ADD4_32(WSIGMA1_AVX(w[35]), w[21], w[30], WSIGMA0_AVX(w[22])); + SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 37, w[37]); + w[38] = ADD4_32(WSIGMA1_AVX(w[36]), w[22], w[31], WSIGMA0_AVX(w[23])); + SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 38, w[38]); + w[39] = ADD4_32(WSIGMA1_AVX(w[37]), w[23], w[32], WSIGMA0_AVX(w[24])); + SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 39, w[39]); + w[40] = ADD4_32(WSIGMA1_AVX(w[38]), w[24], w[33], WSIGMA0_AVX(w[25])); + SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 40, w[40]); + w[41] = ADD4_32(WSIGMA1_AVX(w[39]), w[25], w[34], WSIGMA0_AVX(w[26])); + SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 41, w[41]); + w[42] = ADD4_32(WSIGMA1_AVX(w[40]), w[26], w[35], WSIGMA0_AVX(w[27])); + SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 42, w[42]); + w[43] = ADD4_32(WSIGMA1_AVX(w[41]), w[27], w[36], WSIGMA0_AVX(w[28])); + SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 43, w[43]); + w[44] = ADD4_32(WSIGMA1_AVX(w[42]), w[28], w[37], WSIGMA0_AVX(w[29])); + SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 44, w[44]); + w[45] = ADD4_32(WSIGMA1_AVX(w[43]), w[29], w[38], WSIGMA0_AVX(w[30])); + SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 45, w[45]); + w[46] = ADD4_32(WSIGMA1_AVX(w[44]), w[30], w[39], WSIGMA0_AVX(w[31])); + SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 46, w[46]); + w[47] = ADD4_32(WSIGMA1_AVX(w[45]), w[31], w[40], WSIGMA0_AVX(w[32])); + SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 47, w[47]); + w[48] = ADD4_32(WSIGMA1_AVX(w[46]), w[32], w[41], WSIGMA0_AVX(w[33])); + SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 48, w[48]); + w[49] = ADD4_32(WSIGMA1_AVX(w[47]), w[33], w[42], WSIGMA0_AVX(w[34])); + SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 49, w[49]); + w[50] = ADD4_32(WSIGMA1_AVX(w[48]), w[34], w[43], WSIGMA0_AVX(w[35])); + SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 50, w[50]); + w[51] = ADD4_32(WSIGMA1_AVX(w[49]), w[35], w[44], WSIGMA0_AVX(w[36])); + SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 51, w[51]); + w[52] = ADD4_32(WSIGMA1_AVX(w[50]), w[36], w[45], WSIGMA0_AVX(w[37])); + SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 52, w[52]); + w[53] = ADD4_32(WSIGMA1_AVX(w[51]), w[37], w[46], WSIGMA0_AVX(w[38])); + SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 53, w[53]); + w[54] = ADD4_32(WSIGMA1_AVX(w[52]), w[38], w[47], WSIGMA0_AVX(w[39])); + SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 54, w[54]); + w[55] = ADD4_32(WSIGMA1_AVX(w[53]), w[39], w[48], WSIGMA0_AVX(w[40])); + SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 55, w[55]); + w[56] = ADD4_32(WSIGMA1_AVX(w[54]), w[40], w[49], WSIGMA0_AVX(w[41])); + SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 56, w[56]); + w[57] = ADD4_32(WSIGMA1_AVX(w[55]), w[41], w[50], WSIGMA0_AVX(w[42])); + SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 57, w[57]); + w[58] = ADD4_32(WSIGMA1_AVX(w[56]), w[42], w[51], WSIGMA0_AVX(w[43])); + SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 58, w[58]); + w[59] = ADD4_32(WSIGMA1_AVX(w[57]), w[43], w[52], WSIGMA0_AVX(w[44])); + SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 59, w[59]); + w[60] = ADD4_32(WSIGMA1_AVX(w[58]), w[44], w[53], WSIGMA0_AVX(w[45])); + SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 60, w[60]); + w[61] = ADD4_32(WSIGMA1_AVX(w[59]), w[45], w[54], WSIGMA0_AVX(w[46])); + SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 61, w[61]); + w[62] = ADD4_32(WSIGMA1_AVX(w[60]), w[46], w[55], WSIGMA0_AVX(w[47])); + SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 62, w[62]); + w[63] = ADD4_32(WSIGMA1_AVX(w[61]), w[47], w[56], WSIGMA0_AVX(w[48])); + SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 63, w[63]); + + // Feed Forward + ctx->s[0] = ADD32(s[0], ctx->s[0]); + ctx->s[1] = ADD32(s[1], ctx->s[1]); + ctx->s[2] = ADD32(s[2], ctx->s[2]); + ctx->s[3] = ADD32(s[3], ctx->s[3]); + ctx->s[4] = ADD32(s[4], ctx->s[4]); + ctx->s[5] = ADD32(s[5], ctx->s[5]); + ctx->s[6] = ADD32(s[6], ctx->s[6]); + ctx->s[7] = ADD32(s[7], ctx->s[7]); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/sha256avx.h b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/sha256avx.h new file mode 100644 index 0000000000..1e3bcf889b --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/sha256avx.h @@ -0,0 +1,44 @@ +#ifndef SHA256AVX_H +#define SHA256AVX_H + +#include +#include + +#include "params.h" + +typedef struct SHA256state { + __m256i s[8]; + unsigned char msgblocks[8 * 64]; + unsigned int datalen; + unsigned long long msglen; +} sha256x8ctx; + +#define sha256_ctx_clone8x SPX_NAMESPACE(sha256_ctx_clone8x) +void sha256_ctx_clone8x(sha256x8ctx *out, const sha256x8ctx *in); + +#define sha256_init8x SPX_NAMESPACE(sha256_init8x) +void sha256_init8x(sha256x8ctx *ctx); + +#define sha256_final8x SPX_NAMESPACE(sha256_final8x) +void sha256_final8x(sha256x8ctx *ctx, + unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7); + +#define sha256_transform8x SPX_NAMESPACE(sha256_transform8x) +void sha256_transform8x(sha256x8ctx *ctx, + const unsigned char *data0, + const unsigned char *data1, + const unsigned char *data2, + const unsigned char *data3, + const unsigned char *data4, + const unsigned char *data5, + const unsigned char *data6, + const unsigned char *data7); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/sha256x8.c b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/sha256x8.c new file mode 100644 index 0000000000..d97750c09b --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/sha256x8.c @@ -0,0 +1,185 @@ +#include + +#include "sha256avx.h" +#include "sha256x8.h" +#include "utils.h" + +// Performs sha256x8 on an initialized (and perhaps seeded) state. +static void _sha256x8( + sha256x8ctx *ctx, + unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, unsigned long long inlen) { + unsigned long long i = 0; + while (inlen - i >= 64) { + sha256_transform8x(ctx, + in0 + i, + in1 + i, + in2 + i, + in3 + i, + in4 + i, + in5 + i, + in6 + i, + in7 + i + ); + i += 64; + ctx->msglen += 512; + } + + size_t bytes_to_copy = (size_t)(inlen - i); + memcpy(&ctx->msgblocks[64 * 0], in0 + i, bytes_to_copy); + memcpy(&ctx->msgblocks[64 * 1], in1 + i, bytes_to_copy); + memcpy(&ctx->msgblocks[64 * 2], in2 + i, bytes_to_copy); + memcpy(&ctx->msgblocks[64 * 3], in3 + i, bytes_to_copy); + memcpy(&ctx->msgblocks[64 * 4], in4 + i, bytes_to_copy); + memcpy(&ctx->msgblocks[64 * 5], in5 + i, bytes_to_copy); + memcpy(&ctx->msgblocks[64 * 6], in6 + i, bytes_to_copy); + memcpy(&ctx->msgblocks[64 * 7], in7 + i, bytes_to_copy); + ctx->datalen = (unsigned int)bytes_to_copy; + + sha256_final8x(ctx, out0, out1, out2, out3, out4, out5, out6, out7); +} + +void sha256x8_seeded( + unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const sha256x8ctx *seed, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, unsigned long long inlen) { + + sha256x8ctx ctx; + sha256_ctx_clone8x(&ctx, seed); + + _sha256x8(&ctx, out0, out1, out2, out3, out4, out5, out6, out7, + in0, in1, in2, in3, in4, in5, in6, in7, inlen); +} + +/* This provides a wrapper around the internals of 8x parallel SHA256 */ +void sha256x8(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, unsigned long long inlen) { + sha256x8ctx ctx; + sha256_init8x(&ctx); + + _sha256x8(&ctx, out0, out1, out2, out3, out4, out5, out6, out7, + in0, in1, in2, in3, in4, in5, in6, in7, inlen); +} + +/** + * Note that inlen should be sufficiently small that it still allows for + * an array to be allocated on the stack. Typically 'in' is merely a seed. + * Outputs outlen number of bytes + */ +void mgf1x8(unsigned char *outx8, unsigned long outlen, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, + unsigned long inlen) { + PQCLEAN_VLA(unsigned char, inbufx8, 8 * (inlen + 4)); + unsigned char outbufx8[8 * SPX_SHA256_OUTPUT_BYTES]; + uint32_t i; + unsigned int j; + + memcpy(inbufx8 + 0 * (inlen + 4), in0, inlen); + memcpy(inbufx8 + 1 * (inlen + 4), in1, inlen); + memcpy(inbufx8 + 2 * (inlen + 4), in2, inlen); + memcpy(inbufx8 + 3 * (inlen + 4), in3, inlen); + memcpy(inbufx8 + 4 * (inlen + 4), in4, inlen); + memcpy(inbufx8 + 5 * (inlen + 4), in5, inlen); + memcpy(inbufx8 + 6 * (inlen + 4), in6, inlen); + memcpy(inbufx8 + 7 * (inlen + 4), in7, inlen); + + /* While we can fit in at least another full block of SHA256 output.. */ + for (i = 0; (i + 1)*SPX_SHA256_OUTPUT_BYTES <= outlen; i++) { + for (j = 0; j < 8; j++) { + u32_to_bytes(inbufx8 + inlen + j * (inlen + 4), i); + } + + sha256x8(outx8 + 0 * outlen, + outx8 + 1 * outlen, + outx8 + 2 * outlen, + outx8 + 3 * outlen, + outx8 + 4 * outlen, + outx8 + 5 * outlen, + outx8 + 6 * outlen, + outx8 + 7 * outlen, + inbufx8 + 0 * (inlen + 4), + inbufx8 + 1 * (inlen + 4), + inbufx8 + 2 * (inlen + 4), + inbufx8 + 3 * (inlen + 4), + inbufx8 + 4 * (inlen + 4), + inbufx8 + 5 * (inlen + 4), + inbufx8 + 6 * (inlen + 4), + inbufx8 + 7 * (inlen + 4), inlen + 4); + outx8 += SPX_SHA256_OUTPUT_BYTES; + } + /* Until we cannot anymore, and we fill the remainder. */ + for (j = 0; j < 8; j++) { + u32_to_bytes(inbufx8 + inlen + j * (inlen + 4), i); + } + sha256x8(outbufx8 + 0 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 1 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 2 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 3 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 4 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 5 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 6 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 7 * SPX_SHA256_OUTPUT_BYTES, + inbufx8 + 0 * (inlen + 4), + inbufx8 + 1 * (inlen + 4), + inbufx8 + 2 * (inlen + 4), + inbufx8 + 3 * (inlen + 4), + inbufx8 + 4 * (inlen + 4), + inbufx8 + 5 * (inlen + 4), + inbufx8 + 6 * (inlen + 4), + inbufx8 + 7 * (inlen + 4), inlen + 4); + + for (j = 0; j < 8; j++) { + memcpy(outx8 + j * outlen, + outbufx8 + j * SPX_SHA256_OUTPUT_BYTES, + outlen - i * SPX_SHA256_OUTPUT_BYTES); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/sha256x8.h b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/sha256x8.h new file mode 100644 index 0000000000..4f7330a6c1 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/sha256x8.h @@ -0,0 +1,64 @@ +#ifndef SPX_SHA256X8_H +#define SPX_SHA256X8_H + +#include "params.h" +#include "sha256avx.h" + + + +#define sha256x8_seeded SPX_NAMESPACE(sha256x8_seeded) +void sha256x8_seeded( + unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const sha256x8ctx *seed, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, unsigned long long inlen); + +/* This provides a wrapper around the internals of 8x parallel SHA256 */ +#define sha256x8 SPX_NAMESPACE(sha256x8) +void sha256x8(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, unsigned long long inlen); + +/** + * Note that inlen should be sufficiently small that it still allows for + * an array to be allocated on the stack. Typically 'in' is merely a seed. + * Outputs outlen number of bytes + */ +#define mgf1x8 SPX_NAMESPACE(mgf1x8) +void mgf1x8(unsigned char *outx8, unsigned long outlen, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, + unsigned long inlen); +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/sha2_offsets.h b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/sha2_offsets.h new file mode 100644 index 0000000000..6e3584f7a4 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/sha2_offsets.h @@ -0,0 +1,27 @@ +#ifndef SHA2_OFFSETS_H_ +#define SHA2_OFFSETS_H_ + +#define SPX_SHA256_BLOCK_BYTES 64 +#define SPX_SHA256_OUTPUT_BYTES 32 + +#define SPX_SHA512_BLOCK_BYTES 128 +#define SPX_SHA512_OUTPUT_BYTES 64 + +/* + * Offsets of various fields in the address structure when we use SHA2 as + * the Sphincs+ hash function + */ + +#define SPX_OFFSET_LAYER 0 /* The byte used to specify the Merkle tree layer */ +#define SPX_OFFSET_TREE 1 /* The start of the 8 byte field used to specify the tree */ +#define SPX_OFFSET_TYPE 9 /* The byte used to specify the hash type (reason) */ +#define SPX_OFFSET_KP_ADDR2 12 /* The high byte used to specify the key pair (which one-time signature) */ +#define SPX_OFFSET_KP_ADDR1 13 /* The low byte used to specify the key pair */ +#define SPX_OFFSET_CHAIN_ADDR 17 /* The byte used to specify the chain address (which Winternitz chain) */ +#define SPX_OFFSET_HASH_ADDR 21 /* The byte used to specify the hash address (where in the Winternitz chain) */ +#define SPX_OFFSET_TREE_HGT 17 /* The byte used to specify the height of this node in the FORS or Merkle tree */ +#define SPX_OFFSET_TREE_INDEX 18 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ + +#define SPX_SHA2 1 + +#endif /* SHA2_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/sign.c b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/sign.c new file mode 100644 index 0000000000..9d0c7d1b22 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/sign.c @@ -0,0 +1,286 @@ +#include +#include +#include + +#include "address.h" +#include "context.h" +#include "fors.h" +#include "hash.h" +#include "merkle.h" +#include "nistapi.h" +#include "params.h" +#include "randombytes.h" +#include "thash.h" +#include "utils.h" +#include "wots.h" + +/* + * Returns the length of a secret key, in bytes + */ +size_t crypto_sign_secretkeybytes(void) { + return CRYPTO_SECRETKEYBYTES; +} + +/* + * Returns the length of a public key, in bytes + */ +size_t crypto_sign_publickeybytes(void) { + return CRYPTO_PUBLICKEYBYTES; +} + +/* + * Returns the length of a signature, in bytes + */ +size_t crypto_sign_bytes(void) { + return CRYPTO_BYTES; +} + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +size_t crypto_sign_seedbytes(void) { + return CRYPTO_SEEDBYTES; +} + +/* + * Generates an SPX key pair given a seed of length + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [PUB_SEED || root] + */ +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed) { + spx_ctx ctx; + + /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ + memcpy(sk, seed, CRYPTO_SEEDBYTES); + + memcpy(pk, sk + 2 * SPX_N, SPX_N); + + memcpy(ctx.pub_seed, pk, SPX_N); + memcpy(ctx.sk_seed, sk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + /* Compute root node of the top-most subtree. */ + merkle_gen_root(sk + 3 * SPX_N, &ctx); + + // cleanup + free_hash_function(&ctx); + + memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); + + return 0; +} + +/* + * Generates an SPX key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [PUB_SEED || root] + */ +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { + uint8_t seed[CRYPTO_SEEDBYTES]; + randombytes(seed, CRYPTO_SEEDBYTES); + crypto_sign_seed_keypair(pk, sk, seed); + + return 0; +} + +/** + * Returns an array containing a detached signature. + */ +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk) { + spx_ctx ctx; + + const uint8_t *sk_prf = sk + SPX_N; + const uint8_t *pk = sk + 2 * SPX_N; + + uint8_t optrand[SPX_N]; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t root[SPX_N]; + uint32_t i; + uint64_t tree; + uint32_t idx_leaf; + uint32_t wots_addr[8] = {0}; + uint32_t tree_addr[8] = {0}; + + memcpy(ctx.sk_seed, sk, SPX_N); + memcpy(ctx.pub_seed, pk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + + /* Optionally, signing can be made non-deterministic using optrand. + This can help counter side-channel attacks that would benefit from + getting a large number of traces when the signer uses the same nodes. */ + randombytes(optrand, SPX_N); + /* Compute the digest randomization value. */ + gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); + + /* Derive the message digest and leaf index from R, PK and M. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; + + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); + + /* Sign the message hash using FORS. */ + fors_sign(sig, root, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); + sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; + + /* Update the indices for the next layer. */ + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; + } + + free_hash_function(&ctx); + + *siglen = SPX_BYTES; + + return 0; +} + +/** + * Verifies a detached signature and message under a given public key. + */ +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk) { + spx_ctx ctx; + const uint8_t *pub_root = pk + SPX_N; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t wots_pk[SPX_WOTS_BYTES]; + uint8_t root[SPX_N]; + uint8_t leaf[SPX_N]; + unsigned int i; + uint64_t tree; + uint32_t idx_leaf; + uint32_t wots_addr[8] = {0}; + uint32_t tree_addr[8] = {0}; + uint32_t wots_pk_addr[8] = {0}; + + if (siglen != SPX_BYTES) { + return -1; + } + + memcpy(ctx.pub_seed, pk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); + + /* Derive the message digest and leaf index from R || PK || M. */ + /* The additional SPX_N is a result of the hash domain separator. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; + + /* Layer correctly defaults to 0, so no need to set_layer_addr */ + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); + + fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + /* For each subtree.. */ + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + copy_keypair_addr(wots_pk_addr, wots_addr); + + /* The WOTS public key is only correct if the signature was correct. */ + /* Initially, root is the FORS pk, but on subsequent iterations it is + the root of the subtree below the currently processed subtree. */ + wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); + sig += SPX_WOTS_BYTES; + + /* Compute the leaf node using the WOTS public key. */ + thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); + + /* Compute the root node of this subtree. */ + compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, + &ctx, tree_addr); + sig += SPX_TREE_HEIGHT * SPX_N; + + /* Update the indices for the next layer. */ + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; + } + + // cleanup + free_hash_function(&ctx); + + /* Check if the root node equals the root node in the public key. */ + if (memcmp(root, pub_root, SPX_N) != 0) { + return -1; + } + + return 0; +} + + +/** + * Returns an array containing the signature followed by the message. + */ +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk) { + size_t siglen; + + crypto_sign_signature(sm, &siglen, m, mlen, sk); + + memmove(sm + SPX_BYTES, m, mlen); + *smlen = siglen + mlen; + + return 0; +} + +/** + * Verifies a given signature-message pair under a given public key. + */ +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk) { + /* The API caller does not necessarily know what size a signature should be + but SPHINCS+ signatures are always exactly SPX_BYTES. */ + if (smlen < SPX_BYTES) { + memset(m, 0, smlen); + *mlen = 0; + return -1; + } + + *mlen = smlen - SPX_BYTES; + + if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { + memset(m, 0, smlen); + *mlen = 0; + return -1; + } + + /* If verification was successful, move the message to the right place. */ + memmove(m, sm + SPX_BYTES, *mlen); + + return 0; +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/thash.h b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/thash.h new file mode 100644 index 0000000000..8687ccfb4d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/thash.h @@ -0,0 +1,13 @@ +#ifndef SPX_THASH_H +#define SPX_THASH_H + +#include "context.h" +#include "params.h" + +#include + +#define thash SPX_NAMESPACE(thash) +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/thash_sha2_robust.c b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/thash_sha2_robust.c new file mode 100644 index 0000000000..18f65c2e42 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/thash_sha2_robust.c @@ -0,0 +1,39 @@ +#include +#include + +#include "address.h" +#include "context.h" +#include "hash.h" +#include "params.h" +#include "sha2.h" +#include "thash.h" +#include "utils.h" + + +/** + * Takes an array of inblocks concatenated arrays of SPX_N bytes. + */ +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]) { + unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES]; + PQCLEAN_VLA(uint8_t, bitmask, inblocks * SPX_N); + PQCLEAN_VLA(uint8_t, buf, SPX_N + SPX_SHA256_OUTPUT_BYTES + inblocks * SPX_N); + sha256ctx sha2_state; + unsigned int i; + + memcpy(buf, ctx->pub_seed, SPX_N); + memcpy(buf + SPX_N, addr, SPX_SHA256_ADDR_BYTES); + mgf1_256(bitmask, inblocks * SPX_N, buf, SPX_N + SPX_SHA256_ADDR_BYTES); + + /* Retrieve precomputed state containing pub_seed */ + sha256_inc_ctx_clone(&sha2_state, &ctx->state_seeded); + + for (i = 0; i < inblocks * SPX_N; i++) { + buf[SPX_N + SPX_SHA256_ADDR_BYTES + i] = in[i] ^ bitmask[i]; + } + + sha256_inc_finalize(outbuf, &sha2_state, buf + SPX_N, + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N); + memcpy(out, outbuf, SPX_N); +} + diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/thash_sha2_robustx8.c b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/thash_sha2_robustx8.c new file mode 100644 index 0000000000..09ae4e1265 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/thash_sha2_robustx8.c @@ -0,0 +1,121 @@ +#include +#include + +#include "thashx8.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "sha2.h" +#include "sha256avx.h" +#include "sha256x8.h" +#include "utils.h" + + +/** + * 8-way parallel version of thash; takes 8x as much input and output + */ +void thashx8(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addrx8[8 * 8]) { + PQCLEAN_VLA(unsigned char, bufx8, 8 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)); + unsigned char outbufx8[8 * SPX_SHA256_OUTPUT_BYTES]; + PQCLEAN_VLA(unsigned char, bitmaskx8, 8 * (inblocks * SPX_N)); + unsigned int i; + + for (i = 0; i < 8; i++) { + memcpy(bufx8 + i * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + ctx->pub_seed, SPX_N); + memcpy(bufx8 + SPX_N + + i * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + addrx8 + i * 8, SPX_SHA256_ADDR_BYTES); + } + + mgf1x8(bitmaskx8, inblocks * SPX_N, + bufx8 + 0 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + 1 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + 2 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + 3 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + 4 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + 5 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + 6 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + 7 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + SPX_N + SPX_SHA256_ADDR_BYTES); + + for (i = 0; i < inblocks * SPX_N; i++) { + bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + + 0 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = + in0[i] ^ bitmaskx8[i + 0 * (inblocks * SPX_N)]; + bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + + 1 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = + in1[i] ^ bitmaskx8[i + 1 * (inblocks * SPX_N)]; + bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + + 2 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = + in2[i] ^ bitmaskx8[i + 2 * (inblocks * SPX_N)]; + bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + + 3 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = + in3[i] ^ bitmaskx8[i + 3 * (inblocks * SPX_N)]; + bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + + 4 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = + in4[i] ^ bitmaskx8[i + 4 * (inblocks * SPX_N)]; + bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + + 5 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = + in5[i] ^ bitmaskx8[i + 5 * (inblocks * SPX_N)]; + bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + + 6 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = + in6[i] ^ bitmaskx8[i + 6 * (inblocks * SPX_N)]; + bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + + 7 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = + in7[i] ^ bitmaskx8[i + 7 * (inblocks * SPX_N)]; + } + + sha256x8_seeded( + /* out */ + outbufx8 + 0 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 1 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 2 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 3 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 4 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 5 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 6 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 7 * SPX_SHA256_OUTPUT_BYTES, + + /* seed */ + &ctx->statex8_seeded, + + /* in */ + bufx8 + SPX_N + 0 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + SPX_N + 1 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + SPX_N + 2 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + SPX_N + 3 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + SPX_N + 4 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + SPX_N + 5 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + SPX_N + 6 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + SPX_N + 7 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N /* len */ + ); + + memcpy(out0, outbufx8 + 0 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out1, outbufx8 + 1 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out2, outbufx8 + 2 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out3, outbufx8 + 3 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out4, outbufx8 + 4 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out5, outbufx8 + 5 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out6, outbufx8 + 6 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out7, outbufx8 + 7 * SPX_SHA256_OUTPUT_BYTES, SPX_N); +} + diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/thashx8.h b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/thashx8.h new file mode 100644 index 0000000000..c02fe9cf3e --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/thashx8.h @@ -0,0 +1,28 @@ +#ifndef SPX_THASHX8_H +#define SPX_THASHX8_H + +#include + +#include "context.h" +#include "params.h" + +#define thashx8 SPX_NAMESPACE(thashx8) +void thashx8(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addrx8[8 * 8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/utils.c b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/utils.c new file mode 100644 index 0000000000..177b541fb9 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/utils.c @@ -0,0 +1,148 @@ +#include + +#include "utils.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "thash.h" + +/** + * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. + */ +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in) { + int i; + + /* Iterate over out in decreasing order, for big-endianness. */ + for (i = (signed int)outlen - 1; i >= 0; i--) { + out[i] = in & 0xff; + in = in >> 8; + } +} + +void u32_to_bytes(unsigned char *out, uint32_t in) { + out[0] = (unsigned char)(in >> 24); + out[1] = (unsigned char)(in >> 16); + out[2] = (unsigned char)(in >> 8); + out[3] = (unsigned char)in; +} + +/** + * Converts the inlen bytes in 'in' from big-endian byte order to an integer. + */ +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { + unsigned long long retval = 0; + unsigned int i; + + for (i = 0; i < inlen; i++) { + retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); + } + return retval; +} + +/** + * Computes a root node given a leaf and an auth path. + * Expects address to be complete other than the tree_height and tree_index. + */ +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]) { + uint32_t i; + unsigned char buffer[2 * SPX_N]; + + /* If leaf_idx is odd (last bit = 1), current path element is a right child + and auth_path has to go left. Otherwise it is the other way around. */ + if (leaf_idx & 1) { + memcpy(buffer + SPX_N, leaf, SPX_N); + memcpy(buffer, auth_path, SPX_N); + } else { + memcpy(buffer, leaf, SPX_N); + memcpy(buffer + SPX_N, auth_path, SPX_N); + } + auth_path += SPX_N; + + for (i = 0; i < tree_height - 1; i++) { + leaf_idx >>= 1; + idx_offset >>= 1; + /* Set the address of the node we're creating. */ + set_tree_height(addr, i + 1); + set_tree_index(addr, leaf_idx + idx_offset); + + /* Pick the right or left neighbor, depending on parity of the node. */ + if (leaf_idx & 1) { + thash(buffer + SPX_N, buffer, 2, ctx, addr); + memcpy(buffer, auth_path, SPX_N); + } else { + thash(buffer, buffer, 2, ctx, addr); + memcpy(buffer + SPX_N, auth_path, SPX_N); + } + auth_path += SPX_N; + } + + /* The last iteration is exceptional; we do not copy an auth_path node. */ + leaf_idx >>= 1; + idx_offset >>= 1; + set_tree_height(addr, tree_height); + set_tree_index(addr, leaf_idx + idx_offset); + thash(root, buffer, 2, ctx, addr); +} + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx * /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]) { + PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); + PQCLEAN_VLA(unsigned int, heights, tree_height + 1); + unsigned int offset = 0; + uint32_t idx; + uint32_t tree_idx; + + for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { + /* Add the next leaf node to the stack. */ + gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); + offset++; + heights[offset - 1] = 0; + + /* If this is a node we need for the auth path.. */ + if ((leaf_idx ^ 0x1) == idx) { + memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); + } + + /* While the top-most nodes are of equal height.. */ + while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { + /* Compute index of the new node, in the next layer. */ + tree_idx = (idx >> (heights[offset - 1] + 1)); + + /* Set the address of the node we're creating. */ + set_tree_height(tree_addr, heights[offset - 1] + 1); + set_tree_index(tree_addr, + tree_idx + (idx_offset >> (heights[offset - 1] + 1))); + /* Hash the top-most nodes from the stack together. */ + thash(stack + (offset - 2)*SPX_N, + stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); + offset--; + /* Note that the top-most node is now one layer higher. */ + heights[offset - 1]++; + + /* If this is a node we need for the auth path.. */ + if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { + memcpy(auth_path + heights[offset - 1]*SPX_N, + stack + (offset - 1)*SPX_N, SPX_N); + } + } + } + memcpy(root, stack, SPX_N); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/utils.h b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/utils.h new file mode 100644 index 0000000000..64f5d5a53a --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/utils.h @@ -0,0 +1,58 @@ +#ifndef SPX_UTILS_H +#define SPX_UTILS_H + +#include + +#include "compat.h" +#include "context.h" +#include "params.h" + + +/* To support MSVC use alloca() instead of VLAs. See #20. */ + + +/** + * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. + */ +#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in); +#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) +void u32_to_bytes(unsigned char *out, uint32_t in); + +/** + * Converts the inlen bytes in 'in' from big-endian byte order to an integer. + */ +#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); + +/** + * Computes a root node given a leaf and an auth path. + * Expects address to be complete other than the tree_height and tree_index. + */ +#define compute_root SPX_NAMESPACE(compute_root) +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]); + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +#define treehash SPX_NAMESPACE(treehash) +void treehash(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx *ctx /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]); + + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/utilsx8.c b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/utilsx8.c new file mode 100644 index 0000000000..f044b9595d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/utilsx8.c @@ -0,0 +1,146 @@ +#include + +#include "utils.h" +#include "utilsx8.h" + +#include "address.h" +#include "params.h" +#include "thashx8.h" + +/* + * Generate the entire Merkle tree, computing the authentication path for leaf_idx, + * and the resulting root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) + * + * This expects tree_addrx8 to be initialized to 8 parallel addr structures for + * the Merkle tree nodes + * + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + * + * This works by using the standard Merkle tree building algorithm, except + * that each 'node' tracked is actually 8 consecutive nodes in the real tree. + * When we combine two logical nodes ABCDEFGH and STUVWXYZ, we perform the H + * operation on adjacent real nodes, forming the parent logical node + * (AB)(CD)(EF)(GH)(ST)(UV)(WX)(YZ) + * + * When we get to the top three levels of the real tree (where there is only + * one logical node), we continue this operation three more times; the right + * most real node will by the actual root (and the other 7 nodes will be + * garbage). We follow the same thashx8 logic so that the 'extract + * authentication path components' part of the loop is still executed (and + * to simplify the code somewhat) + * + * This currently assumes tree_height >= 3; I suspect that doing an adjusting + * idx, addr_idx on the gen_leafx8 call if tree_height < 3 would fix it; since + * we don't actually use such short trees, I haven't bothered + */ +void treehashx8(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, + uint32_t tree_height, + void (*gen_leafx8)( + unsigned char * /* Where to write the leaves */, + const spx_ctx *, + uint32_t idx, void *info), + uint32_t tree_addrx8[8 * 8], + void *info) { + /* This is where we keep the intermediate nodes */ + PQCLEAN_VLA(unsigned char, stackx8, tree_height * 8 * SPX_N); + uint32_t left_adj = 0, prev_left_adj = 0; /* When we're doing the top 3 */ + /* levels, the left-most part of the tree isn't at the beginning */ + /* of current[]. These give the offset of the actual start */ + + uint32_t idx; + uint32_t max_idx = ((uint32_t)1 << (tree_height - 3)) - 1; + for (idx = 0;; idx++) { + unsigned char current[8 * SPX_N]; /* Current logical node */ + gen_leafx8( current, ctx, 8 * idx + idx_offset, + info ); + + /* Now combine the freshly generated right node with previously */ + /* generated left ones */ + uint32_t internal_idx_offset = idx_offset; + uint32_t internal_idx = idx; + uint32_t internal_leaf = leaf_idx; + uint32_t h; /* The height we are in the Merkle tree */ + for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { + + /* Special processing if we're at the top of the tree */ + if (h >= tree_height - 3) { + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[7 * SPX_N], SPX_N ); + return; + } + /* The tree indexing logic is a bit off in this case */ + /* Adjust it so that the left-most node of the part of */ + /* the tree that we're processing has index 0 */ + prev_left_adj = left_adj; + left_adj = (uint32_t)(8 - (1 << (tree_height - h - 1))); + } + + /* Check if we hit the top of the tree */ + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[7 * SPX_N], SPX_N ); + return; + } + + /* + * Check if one of the nodes we have is a part of the + * authentication path; if it is, write it out + */ + if ((((internal_idx << 3) ^ internal_leaf) & ~0x7U) == 0) { + memcpy( &auth_path[ h * SPX_N ], + ¤t[(((internal_leaf & 7) ^ 1) + prev_left_adj) * SPX_N], + SPX_N ); + } + + /* + * Check if we're at a left child; if so, stop going up the stack + * Exception: if we've reached the end of the tree, keep on going + * (so we combine the last 8 nodes into the one root node in three + * more iterations) + */ + if ((internal_idx & 1) == 0 && idx < max_idx) { + break; + } + + /* Ok, we're at a right node (or doing the top 3 levels) */ + /* Now combine the left and right logical nodes together */ + + /* Set the address of the node we're creating. */ + uint32_t j; + internal_idx_offset >>= 1; + for (j = 0; j < 8; j++) { + set_tree_height(tree_addrx8 + j * 8, h + 1); + set_tree_index(tree_addrx8 + j * 8, + (8 / 2) * (internal_idx & ~1U) + j - left_adj + internal_idx_offset ); + } + unsigned char *left = &stackx8[h * 8 * SPX_N]; + thashx8( ¤t[0 * SPX_N], + ¤t[1 * SPX_N], + ¤t[2 * SPX_N], + ¤t[3 * SPX_N], + ¤t[4 * SPX_N], + ¤t[5 * SPX_N], + ¤t[6 * SPX_N], + ¤t[7 * SPX_N], + &left [0 * SPX_N], + &left [2 * SPX_N], + &left [4 * SPX_N], + &left [6 * SPX_N], + ¤t[0 * SPX_N], + ¤t[2 * SPX_N], + ¤t[4 * SPX_N], + ¤t[6 * SPX_N], + 2, ctx, tree_addrx8); + } + + /* We've hit a left child; save the current for when we get the */ + /* corresponding right right */ + memcpy( &stackx8[h * 8 * SPX_N], current, 8 * SPX_N); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/utilsx8.h b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/utilsx8.h new file mode 100644 index 0000000000..806d1e85be --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/utilsx8.h @@ -0,0 +1,29 @@ +#ifndef SPX_UTILSX8_H +#define SPX_UTILSX8_H + +#include + +#include "params.h" + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + * + * This implementation uses AVX to compute internal nodes 8 at a time (in + * parallel) + */ +#define treehashx8 SPX_NAMESPACE(treehashx8) +void treehashx8(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leafx8)( + unsigned char * /* Where to write the leaves */, + const spx_ctx * /* ctx */, + uint32_t addr_idx, void *info), + uint32_t tree_addrx8[8 * 8], void *info); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/wots.c b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/wots.c new file mode 100644 index 0000000000..689baf4db9 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/wots.c @@ -0,0 +1,291 @@ +#include +#include + +#include "wots.h" + +#include "address.h" +#include "hash.h" +#include "hashx8.h" +#include "params.h" +#include "thash.h" +#include "thashx8.h" +#include "utils.h" +#include "utilsx8.h" +#include "wotsx8.h" + +// TODO clarify address expectations, and make them more uniform. +// TODO i.e. do we expect types to be set already? +// TODO and do we expect modifications or copies? + +/** + * Computes up the chains + */ +static void gen_chains( + unsigned char *out, + const unsigned char *in, + unsigned int start[SPX_WOTS_LEN], + const unsigned int steps[SPX_WOTS_LEN], + const spx_ctx *ctx, + uint32_t addr[8]) { + uint32_t i, j, k, idx, watching; + int done; + unsigned char empty[SPX_N]; + unsigned char *bufs[8]; + uint32_t addrs[8 * 8]; + + int l; + uint16_t counts[SPX_WOTS_W] = { 0 }; + uint16_t idxs[SPX_WOTS_LEN]; + uint16_t total, newTotal; + + /* set addrs = {addr, addr, ..., addr} */ + for (j = 0; j < 8; j++) { + memcpy(addrs + j * 8, addr, sizeof(uint32_t) * 8); + } + + /* Initialize out with the value at position 'start'. */ + memcpy(out, in, SPX_WOTS_LEN * SPX_N); + + /* Sort the chains in reverse order by steps using counting sort. */ + for (i = 0; i < SPX_WOTS_LEN; i++) { + counts[steps[i]]++; + } + total = 0; + for (l = SPX_WOTS_W - 1; l >= 0; l--) { + newTotal = counts[l] + total; + counts[l] = total; + total = newTotal; + } + for (i = 0; i < SPX_WOTS_LEN; i++) { + idxs[counts[steps[i]]] = (uint16_t)i; + counts[steps[i]]++; + } + + /* We got our work cut out for us: do it! */ + for (i = 0; i < SPX_WOTS_LEN; i += 8) { + for (j = 0; j < 8 && i + j < SPX_WOTS_LEN; j++) { + idx = idxs[i + j]; + set_chain_addr(addrs + j * 8, idx); + bufs[j] = out + SPX_N * idx; + } + + /* As the chains are sorted in reverse order, we know that the first + * chain is the longest and the last one is the shortest. We keep + * an eye on whether the last chain is done and then on the one before, + * et cetera. */ + watching = 7; + done = 0; + while (i + watching >= SPX_WOTS_LEN) { + bufs[watching] = &empty[0]; + watching--; + } + + for (k = 0;; k++) { + while (k == steps[idxs[i + watching]]) { + bufs[watching] = &empty[0]; + if (watching == 0) { + done = 1; + break; + } + watching--; + } + if (done) { + break; + } + for (j = 0; j < watching + 1; j++) { + set_hash_addr(addrs + j * 8, k + start[idxs[i + j]]); + } + + thashx8(bufs[0], bufs[1], bufs[2], bufs[3], + bufs[4], bufs[5], bufs[6], bufs[7], + bufs[0], bufs[1], bufs[2], bufs[3], + bufs[4], bufs[5], bufs[6], bufs[7], 1, ctx, addrs); + } + } +} + +/** + * base_w algorithm as described in draft. + * Interprets an array of bytes as integers in base w. + * This only works when log_w is a divisor of 8. + */ +static void base_w(unsigned int *output, const int out_len, + const unsigned char *input) { + int in = 0; + int out = 0; + unsigned char total = 0; + int bits = 0; + int consumed; + + for (consumed = 0; consumed < out_len; consumed++) { + if (bits == 0) { + total = input[in]; + in++; + bits += 8; + } + bits -= SPX_WOTS_LOGW; + output[out] = (total >> bits) & (SPX_WOTS_W - 1); + out++; + } +} + +/* Computes the WOTS+ checksum over a message (in base_w). */ +static void wots_checksum(unsigned int *csum_base_w, + const unsigned int *msg_base_w) { + unsigned int csum = 0; + unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; + unsigned int i; + + /* Compute checksum. */ + for (i = 0; i < SPX_WOTS_LEN1; i++) { + csum += SPX_WOTS_W - 1 - msg_base_w[i]; + } + + /* Convert checksum to base_w. */ + /* Make sure expected empty zero bits are the least significant bits. */ + csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); + ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); + base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); +} + +/* Takes a message and derives the matching chain lengths. */ +void chain_lengths(unsigned int *lengths, const unsigned char *msg) { + base_w(lengths, SPX_WOTS_LEN1, msg); + wots_checksum(lengths + SPX_WOTS_LEN1, lengths); +} + +/** + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. + * + * Writes the computed public key to 'pk'. + */ +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]) { + unsigned int steps[SPX_WOTS_LEN]; + unsigned int start[SPX_WOTS_LEN]; + uint32_t i; + + chain_lengths(start, msg); + + for (i = 0; i < SPX_WOTS_LEN; i++) { + steps[i] = SPX_WOTS_W - 1 - start[i]; + } + + gen_chains(pk, sig, start, steps, ctx, addr); +} + +/* + * This generates 8 sequential WOTS public keys + * It also generates the WOTS signature if leaf_info indicates + * that we're signing with one of these WOTS keys + */ +void wots_gen_leafx8(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info) { + struct leaf_info_x8 *info = v_info; + uint32_t *leaf_addr = info->leaf_addr; + uint32_t *pk_addr = info->pk_addr; + unsigned int i, j, k; + unsigned char pk_buffer[ 8 * SPX_WOTS_BYTES ]; + unsigned wots_offset = SPX_WOTS_BYTES; + unsigned char *buffer; + uint32_t wots_k_mask; + unsigned wots_sign_index; + + if (((leaf_idx ^ info->wots_sign_leaf) & ~7U) == 0) { + /* We're traversing the leaf that's signing; generate the WOTS */ + /* signature */ + wots_k_mask = 0; + wots_sign_index = info->wots_sign_leaf & 7; /* Which of of the 8 */ + /* slots do the signatures come from */ + } else { + /* Nope, we're just generating pk's; turn off the signature logic */ + wots_k_mask = ~0U; + wots_sign_index = 0; + } + + for (j = 0; j < 8; j++) { + set_keypair_addr( leaf_addr + j * 8, leaf_idx + j ); + set_keypair_addr( pk_addr + j * 8, leaf_idx + j ); + } + + for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { + uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k */ + /* to the step if we're generating a signature, ~0 if we're not */ + + /* Start with the secret seed */ + for (j = 0; j < 8; j++) { + set_chain_addr(leaf_addr + j * 8, i); + set_hash_addr(leaf_addr + j * 8, 0); + set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTSPRF); + } + prf_addrx8(buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + buffer + 2 * wots_offset, + buffer + 3 * wots_offset, + buffer + 4 * wots_offset, + buffer + 5 * wots_offset, + buffer + 6 * wots_offset, + buffer + 7 * wots_offset, + ctx, leaf_addr); + + for (j = 0; j < 8; j++) { + set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTS); + } + + /* Iterate down the WOTS chain */ + for (k = 0;; k++) { + /* Check if one of the values we have needs to be saved as a */ + /* part of the WOTS signature */ + if (k == wots_k) { + memcpy( info->wots_sig + i * SPX_N, + buffer + wots_sign_index * wots_offset, SPX_N ); + } + + /* Check if we hit the top of the chain */ + if (k == SPX_WOTS_W - 1) { + break; + } + + /* Iterate one step on all 8 chains */ + for (j = 0; j < 8; j++) { + set_hash_addr(leaf_addr + j * 8, k); + } + thashx8(buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + buffer + 2 * wots_offset, + buffer + 3 * wots_offset, + buffer + 4 * wots_offset, + buffer + 5 * wots_offset, + buffer + 6 * wots_offset, + buffer + 7 * wots_offset, + buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + buffer + 2 * wots_offset, + buffer + 3 * wots_offset, + buffer + 4 * wots_offset, + buffer + 5 * wots_offset, + buffer + 6 * wots_offset, + buffer + 7 * wots_offset, 1, ctx, leaf_addr); + } + } + + /* Do the final thash to generate the public keys */ + thashx8(dest + 0 * SPX_N, + dest + 1 * SPX_N, + dest + 2 * SPX_N, + dest + 3 * SPX_N, + dest + 4 * SPX_N, + dest + 5 * SPX_N, + dest + 6 * SPX_N, + dest + 7 * SPX_N, + pk_buffer + 0 * wots_offset, + pk_buffer + 1 * wots_offset, + pk_buffer + 2 * wots_offset, + pk_buffer + 3 * wots_offset, + pk_buffer + 4 * wots_offset, + pk_buffer + 5 * wots_offset, + pk_buffer + 6 * wots_offset, + pk_buffer + 7 * wots_offset, SPX_WOTS_LEN, ctx, pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/wots.h b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/wots.h new file mode 100644 index 0000000000..4e7692eeef --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/wots.h @@ -0,0 +1,25 @@ +#ifndef SPX_WOTS_H +#define SPX_WOTS_H + +#include + +#include "context.h" +#include "params.h" + +/** + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. + * + * Writes the computed public key to 'pk'. + */ +#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]); + +/* + * Compute the chain lengths needed for a given message hash + */ +#define chain_lengths SPX_NAMESPACE(chain_lengths) +void chain_lengths(unsigned int *lengths, const unsigned char *msg); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/wotsx8.h b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/wotsx8.h new file mode 100644 index 0000000000..10866efb35 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/wotsx8.h @@ -0,0 +1,42 @@ +#ifndef WOTSX8_H_ +#define WOTSX8_H_ + +#include + +#include "context.h" +#include "params.h" + +/* + * This is here to provide an interface to the internal wots_gen_leafx8 + * routine. While this routine is not referenced in the package outside of + * wots.c, it is called from the stand-alone benchmark code to characterize + * the performance + */ +struct leaf_info_x8 { + unsigned char *wots_sig; + uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ + uint32_t *wots_steps; + uint32_t leaf_addr[8 * 8]; + uint32_t pk_addr[8 * 8]; +}; + +/* Macro to set the leaf_info to something 'benign', that is, it would */ +/* run with the same time as it does during the real signing process */ +/* Used only by the benchmark code */ +#define INITIALIZE_LEAF_INFO_X8(info, addr, step_buffer) { \ + (info).wots_sig = 0; \ + (info).wots_sign_leaf = ~0; \ + (info).wots_steps = step_buffer; \ + int i; \ + for (i=0; i<8; i++) { \ + memcpy( &(info).leaf_addr[8*i], addr, 32 ); \ + memcpy( &(info).pk_addr[8*i], addr, 32 ); \ + } \ + } + +#define wots_gen_leafx8 SPX_NAMESPACE(wots_gen_leafx8) +void wots_gen_leafx8(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info); + +#endif /* WOTSX8_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/LICENSE b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/LICENSE new file mode 100644 index 0000000000..670154e353 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/LICENSE @@ -0,0 +1,116 @@ +CC0 1.0 Universal + +Statement of Purpose + +The laws of most jurisdictions throughout the world automatically confer +exclusive Copyright and Related Rights (defined below) upon the creator and +subsequent owner(s) (each and all, an "owner") of an original work of +authorship and/or a database (each, a "Work"). + +Certain owners wish to permanently relinquish those rights to a Work for the +purpose of contributing to a commons of creative, cultural and scientific +works ("Commons") that the public can reliably and without fear of later +claims of infringement build upon, modify, incorporate in other works, reuse +and redistribute as freely as possible in any form whatsoever and for any +purposes, including without limitation commercial purposes. These owners may +contribute to the Commons to promote the ideal of a free culture and the +further production of creative, cultural and scientific works, or to gain +reputation or greater distribution for their Work in part through the use and +efforts of others. + +For these and/or other purposes and motivations, and without any expectation +of additional consideration or compensation, the person associating CC0 with a +Work (the "Affirmer"), to the extent that he or she is an owner of Copyright +and Related Rights in the Work, voluntarily elects to apply CC0 to the Work +and publicly distribute the Work under its terms, with knowledge of his or her +Copyright and Related Rights in the Work and the meaning and intended legal +effect of CC0 on those rights. + +1. Copyright and Related Rights. A Work made available under CC0 may be +protected by copyright and related or neighboring rights ("Copyright and +Related Rights"). Copyright and Related Rights include, but are not limited +to, the following: + + i. the right to reproduce, adapt, distribute, perform, display, communicate, + and translate a Work; + + ii. moral rights retained by the original author(s) and/or performer(s); + + iii. publicity and privacy rights pertaining to a person's image or likeness + depicted in a Work; + + iv. rights protecting against unfair competition in regards to a Work, + subject to the limitations in paragraph 4(a), below; + + v. rights protecting the extraction, dissemination, use and reuse of data in + a Work; + + vi. database rights (such as those arising under Directive 96/9/EC of the + European Parliament and of the Council of 11 March 1996 on the legal + protection of databases, and under any national implementation thereof, + including any amended or successor version of such directive); and + + vii. other similar, equivalent or corresponding rights throughout the world + based on applicable law or treaty, and any national implementations thereof. + +2. Waiver. To the greatest extent permitted by, but not in contravention of, +applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and +unconditionally waives, abandons, and surrenders all of Affirmer's Copyright +and Related Rights and associated claims and causes of action, whether now +known or unknown (including existing as well as future claims and causes of +action), in the Work (i) in all territories worldwide, (ii) for the maximum +duration provided by applicable law or treaty (including future time +extensions), (iii) in any current or future medium and for any number of +copies, and (iv) for any purpose whatsoever, including without limitation +commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes +the Waiver for the benefit of each member of the public at large and to the +detriment of Affirmer's heirs and successors, fully intending that such Waiver +shall not be subject to revocation, rescission, cancellation, termination, or +any other legal or equitable action to disrupt the quiet enjoyment of the Work +by the public as contemplated by Affirmer's express Statement of Purpose. + +3. Public License Fallback. Should any part of the Waiver for any reason be +judged legally invalid or ineffective under applicable law, then the Waiver +shall be preserved to the maximum extent permitted taking into account +Affirmer's express Statement of Purpose. In addition, to the extent the Waiver +is so judged Affirmer hereby grants to each affected person a royalty-free, +non transferable, non sublicensable, non exclusive, irrevocable and +unconditional license to exercise Affirmer's Copyright and Related Rights in +the Work (i) in all territories worldwide, (ii) for the maximum duration +provided by applicable law or treaty (including future time extensions), (iii) +in any current or future medium and for any number of copies, and (iv) for any +purpose whatsoever, including without limitation commercial, advertising or +promotional purposes (the "License"). The License shall be deemed effective as +of the date CC0 was applied by Affirmer to the Work. Should any part of the +License for any reason be judged legally invalid or ineffective under +applicable law, such partial invalidity or ineffectiveness shall not +invalidate the remainder of the License, and in such case Affirmer hereby +affirms that he or she will not (i) exercise any of his or her remaining +Copyright and Related Rights in the Work or (ii) assert any associated claims +and causes of action with respect to the Work, in either case contrary to +Affirmer's express Statement of Purpose. + +4. Limitations and Disclaimers. + + a. No trademark or patent rights held by Affirmer are waived, abandoned, + surrendered, licensed or otherwise affected by this document. + + b. Affirmer offers the Work as-is and makes no representations or warranties + of any kind concerning the Work, express, implied, statutory or otherwise, + including without limitation warranties of title, merchantability, fitness + for a particular purpose, non infringement, or the absence of latent or + other defects, accuracy, or the present or absence of errors, whether or not + discoverable, all to the greatest extent permissible under applicable law. + + c. Affirmer disclaims responsibility for clearing rights of other persons + that may apply to the Work or any use thereof, including without limitation + any person's Copyright and Related Rights in the Work. Further, Affirmer + disclaims responsibility for obtaining any necessary consents, permissions + or other rights required for any use of the Work. + + d. Affirmer understands and acknowledges that Creative Commons is not a + party to this document and has no duty or obligation with respect to this + CC0 or use of the Work. + +For more information, please see + diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/address.c b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/address.c new file mode 100644 index 0000000000..b956e9cb29 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/address.c @@ -0,0 +1,91 @@ +#include +#include + +#include "address.h" +#include "params.h" +#include "utils.h" + +/* + * Specify which level of Merkle tree (the "layer") we're working on + */ +void set_layer_addr(uint32_t addr[8], uint32_t layer) { + ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; +} + +/* + * Specify which Merkle tree within the level (the "tree address") we're working on + */ +void set_tree_addr(uint32_t addr[8], uint64_t tree) { + ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); +} + +/* + * Specify the reason we'll use this address structure for, that is, what + * hash will we compute with it. This is used so that unrelated types of + * hashes don't accidentally get the same address structure. The type will be + * one of the SPX_ADDR_TYPE constants + */ +void set_type(uint32_t addr[8], uint32_t type) { + ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; +} + +/* + * Copy the layer and tree fields of the address structure. This is used + * when we're doing multiple types of hashes within the same Merkle tree + */ +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); +} + +/* These functions are used for OTS addresses. */ + +/* + * Specify which Merkle leaf we're working on; that is, which OTS keypair + * we're talking about. + */ +void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { + ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; +} + +/* + * Copy the layer, tree and keypair fields of the address structure. This is + * used when we're doing multiple things within the same OTS keypair + */ +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); + ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; +} + +/* + * Specify which Merkle chain within the OTS we're working with + * (the chain address) + */ +void set_chain_addr(uint32_t addr[8], uint32_t chain) { + ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; +} + +/* + * Specify where in the Merkle chain we are +* (the hash address) + */ +void set_hash_addr(uint32_t addr[8], uint32_t hash) { + ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; +} + +/* These functions are used for all hash tree addresses (including FORS). */ + +/* + * Specify the height of the node in the Merkle/FORS tree we are in + * (the tree height) + */ +void set_tree_height(uint32_t addr[8], uint32_t tree_height) { + ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; +} + +/* + * Specify the distance from the left edge of the node in the Merkle/FORS tree + * (the tree index) + */ +void set_tree_index(uint32_t addr[8], uint32_t tree_index) { + u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/address.h b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/address.h new file mode 100644 index 0000000000..24a84eb40c --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/address.h @@ -0,0 +1,52 @@ +#ifndef SPX_ADDRESS_H +#define SPX_ADDRESS_H + +#include + +#include "params.h" + +/* The hash types that are passed to set_type */ +#define SPX_ADDR_TYPE_WOTS 0 +#define SPX_ADDR_TYPE_WOTSPK 1 +#define SPX_ADDR_TYPE_HASHTREE 2 +#define SPX_ADDR_TYPE_FORSTREE 3 +#define SPX_ADDR_TYPE_FORSPK 4 +#define SPX_ADDR_TYPE_WOTSPRF 5 +#define SPX_ADDR_TYPE_FORSPRF 6 + +#define set_layer_addr SPX_NAMESPACE(set_layer_addr) +void set_layer_addr(uint32_t addr[8], uint32_t layer); + +#define set_tree_addr SPX_NAMESPACE(set_tree_addr) +void set_tree_addr(uint32_t addr[8], uint64_t tree); + +#define set_type SPX_NAMESPACE(set_type) +void set_type(uint32_t addr[8], uint32_t type); + +/* Copies the layer and tree part of one address into the other */ +#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); + +/* These functions are used for WOTS and FORS addresses. */ + +#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) +void set_keypair_addr(uint32_t addr[8], uint32_t keypair); + +#define set_chain_addr SPX_NAMESPACE(set_chain_addr) +void set_chain_addr(uint32_t addr[8], uint32_t chain); + +#define set_hash_addr SPX_NAMESPACE(set_hash_addr) +void set_hash_addr(uint32_t addr[8], uint32_t hash); + +#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); + +/* These functions are used for all hash tree addresses (including FORS). */ + +#define set_tree_height SPX_NAMESPACE(set_tree_height) +void set_tree_height(uint32_t addr[8], uint32_t tree_height); + +#define set_tree_index SPX_NAMESPACE(set_tree_index) +void set_tree_index(uint32_t addr[8], uint32_t tree_index); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/api.h b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/api.h new file mode 100644 index 0000000000..6b4acf9b80 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/api.h @@ -0,0 +1,77 @@ +#ifndef PQCLEAN_SPHINCSSHA2128FROBUST_CLEAN_API_H +#define PQCLEAN_SPHINCSSHA2128FROBUST_CLEAN_API_H + +#include +#include + +#define PQCLEAN_SPHINCSSHA2128FROBUST_CLEAN_CRYPTO_ALGNAME "SPHINCS+-sha2-128f-robust" + +#define PQCLEAN_SPHINCSSHA2128FROBUST_CLEAN_CRYPTO_SECRETKEYBYTES 64 +#define PQCLEAN_SPHINCSSHA2128FROBUST_CLEAN_CRYPTO_PUBLICKEYBYTES 32 +#define PQCLEAN_SPHINCSSHA2128FROBUST_CLEAN_CRYPTO_BYTES 17088 + +#define PQCLEAN_SPHINCSSHA2128FROBUST_CLEAN_CRYPTO_SEEDBYTES 48 + +/* + * Returns the length of a secret key, in bytes + */ +size_t PQCLEAN_SPHINCSSHA2128FROBUST_CLEAN_crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +size_t PQCLEAN_SPHINCSSHA2128FROBUST_CLEAN_crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +size_t PQCLEAN_SPHINCSSHA2128FROBUST_CLEAN_crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +size_t PQCLEAN_SPHINCSSHA2128FROBUST_CLEAN_crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +int PQCLEAN_SPHINCSSHA2128FROBUST_CLEAN_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +int PQCLEAN_SPHINCSSHA2128FROBUST_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +int PQCLEAN_SPHINCSSHA2128FROBUST_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +int PQCLEAN_SPHINCSSHA2128FROBUST_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, + const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +int PQCLEAN_SPHINCSSHA2128FROBUST_CLEAN_crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +int PQCLEAN_SPHINCSSHA2128FROBUST_CLEAN_crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/context.h b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/context.h new file mode 100644 index 0000000000..27effb3e10 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/context.h @@ -0,0 +1,26 @@ +#ifndef SPX_CONTEXT_H +#define SPX_CONTEXT_H + +#include +#include + +#include "params.h" +#include "sha2.h" + +typedef struct { + uint8_t pub_seed[SPX_N]; + uint8_t sk_seed[SPX_N]; + + // sha256 state that absorbed pub_seed + sha256ctx state_seeded; + + +} spx_ctx; + +#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) +void initialize_hash_function(spx_ctx *ctx); + +#define free_hash_function SPX_NAMESPACE(free_hash_function) +void free_hash_function(spx_ctx *ctx); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/context_sha2.c b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/context_sha2.c new file mode 100644 index 0000000000..64f7e65465 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/context_sha2.c @@ -0,0 +1,33 @@ +#include "context.h" + +/** + * Absorb the constant pub_seed using one round of the compression function + * This initializes state_seeded and state_seeded_512, which can then be + * reused in thash + **/ +static void seed_state(spx_ctx *ctx) { + uint8_t block[SPX_SHA512_BLOCK_BYTES]; + size_t i; + + for (i = 0; i < SPX_N; ++i) { + block[i] = ctx->pub_seed[i]; + } + for (i = SPX_N; i < SPX_SHA512_BLOCK_BYTES; ++i) { + block[i] = 0; + } + /* block has been properly initialized for both SHA-256 and SHA-512 */ + + sha256_inc_init(&ctx->state_seeded); + sha256_inc_blocks(&ctx->state_seeded, block, 1); +} + + +/* We initialize the state for the hash functions */ +void initialize_hash_function(spx_ctx *ctx) { + seed_state(ctx); +} + +/* Free the incremental hashing context for heap-based SHA2 APIs */ +void free_hash_function(spx_ctx *ctx) { + sha256_inc_ctx_release(&ctx->state_seeded); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/fors.c b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/fors.c new file mode 100644 index 0000000000..96ca72e986 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/fors.c @@ -0,0 +1,156 @@ +#include +#include +#include + +#include "fors.h" + +#include "address.h" +#include "hash.h" +#include "thash.h" +#include "utils.h" +#include "utilsx1.h" + +static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + prf_addr(sk, ctx, fors_leaf_addr); +} + +static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, + const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + thash(leaf, sk, 1, ctx, fors_leaf_addr); +} + +struct fors_gen_leaf_info { + uint32_t leaf_addrx[8]; +}; + +static void fors_gen_leafx1(unsigned char *leaf, + const spx_ctx *ctx, + uint32_t addr_idx, void *info) { + struct fors_gen_leaf_info *fors_info = info; + uint32_t *fors_leaf_addr = fors_info->leaf_addrx; + + /* Only set the parts that the caller doesn't set */ + set_tree_index(fors_leaf_addr, addr_idx); + set_type(fors_leaf_addr, SPX_ADDR_TYPE_FORSPRF); + fors_gen_sk(leaf, ctx, fors_leaf_addr); + + set_type(fors_leaf_addr, SPX_ADDR_TYPE_FORSTREE); + fors_sk_to_leaf(leaf, leaf, + ctx, fors_leaf_addr); +} + +/** + * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + * Assumes indices has space for SPX_FORS_TREES integers. + */ +static void message_to_indices(uint32_t *indices, const unsigned char *m) { + unsigned int i, j; + unsigned int offset = 0; + + for (i = 0; i < SPX_FORS_TREES; i++) { + indices[i] = 0; + for (j = 0; j < SPX_FORS_HEIGHT; j++) { + indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); + offset++; + } + } +} + +/** + * Signs a message m, deriving the secret key from sk_seed and the FTS address. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + uint32_t fors_tree_addr[8] = {0}; + struct fors_gen_leaf_info fors_info = {0}; + uint32_t *fors_leaf_addr = fors_info.leaf_addrx; + uint32_t fors_pk_addr[8] = {0}; + uint32_t idx_offset; + unsigned int i; + + copy_keypair_addr(fors_tree_addr, fors_addr); + copy_keypair_addr(fors_leaf_addr, fors_addr); + + copy_keypair_addr(fors_pk_addr, fors_addr); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); + + message_to_indices(indices, m); + + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); + + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); + + /* Include the secret key part that produces the selected leaf node. */ + fors_gen_sk(sig, ctx, fors_tree_addr); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + sig += SPX_N; + + /* Compute the authentication path for this leaf node. */ + treehashx1(roots + i * SPX_N, sig, ctx, + indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx1, + fors_tree_addr, &fors_info); + + sig += SPX_N * SPX_FORS_HEIGHT; + } + + /* Hash horizontally across all tree roots to derive the public key. */ + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); +} + +/** + * Derives the FORS public key from a signature. + * This can be used for verification by comparing to a known public key, or to + * subsequently verify a signature on the derived public key. The latter is the + * typical use-case when used as an FTS below an OTS in a hypertree. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + unsigned char leaf[SPX_N]; + uint32_t fors_tree_addr[8] = {0}; + uint32_t fors_pk_addr[8] = {0}; + uint32_t idx_offset; + unsigned int i; + + copy_keypair_addr(fors_tree_addr, fors_addr); + copy_keypair_addr(fors_pk_addr, fors_addr); + + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); + + message_to_indices(indices, m); + + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); + + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + + /* Derive the leaf from the included secret key part. */ + fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); + sig += SPX_N; + + /* Derive the corresponding root node of this tree. */ + compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, + sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); + sig += SPX_N * SPX_FORS_HEIGHT; + } + + /* Hash horizontally across all tree roots to derive the public key. */ + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/fors.h b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/fors.h new file mode 100644 index 0000000000..509140a178 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/fors.h @@ -0,0 +1,32 @@ +#ifndef SPX_FORS_H +#define SPX_FORS_H + +#include + +#include "context.h" +#include "params.h" + +/** + * Signs a message m, deriving the secret key from sk_seed and the FTS address. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +#define fors_sign SPX_NAMESPACE(fors_sign) +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); + +/** + * Derives the FORS public key from a signature. + * This can be used for verification by comparing to a known public key, or to + * subsequently verify a signature on the derived public key. The latter is the + * typical use-case when used as an FTS below an OTS in a hypertree. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/hash.h b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/hash.h new file mode 100644 index 0000000000..ffe815f45d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/hash.h @@ -0,0 +1,37 @@ +#ifndef SPX_HASH_H +#define SPX_HASH_H + +#include +#include + +#include "context.h" +#include "params.h" + +#define prf_addr SPX_NAMESPACE(prf_addr) +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]); + +#define gen_message_random SPX_NAMESPACE(gen_message_random) +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); + +#define hash_message SPX_NAMESPACE(hash_message) +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); + + +# define SPX_SHA256_ADDR_BYTES 22 + +# define mgf1_256 SPX_NAMESPACE(mgf1_256) +void mgf1_256(unsigned char *out, unsigned long outlen, + const unsigned char *in, unsigned long inlen); + +# define mgf1_512 SPX_NAMESPACE(mgf1_512) +void mgf1_512(unsigned char *out, unsigned long outlen, + const unsigned char *in, unsigned long inlen); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/hash_sha2.c b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/hash_sha2.c new file mode 100644 index 0000000000..69f0dc0013 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/hash_sha2.c @@ -0,0 +1,219 @@ +#include +#include + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "sha2.h" +#include "utils.h" + + + +#define SPX_SHAX_OUTPUT_BYTES SPX_SHA256_OUTPUT_BYTES +#define SPX_SHAX_BLOCK_BYTES SPX_SHA256_BLOCK_BYTES +#define shaX_inc_init sha256_inc_init +#define shaX_inc_blocks sha256_inc_blocks +#define shaX_inc_finalize sha256_inc_finalize +#define shaX sha256 +#define mgf1_X mgf1_256 +#define shaXstate sha256ctx + +/** + * mgf1 function based on the SHA-256 hash function + * Note that inlen should be sufficiently small that it still allows for + * an array to be allocated on the stack. Typically 'in' is merely a seed. + * Outputs outlen number of bytes + */ +void mgf1_256(unsigned char *out, unsigned long outlen, + const unsigned char *in, unsigned long inlen) { + PQCLEAN_VLA(uint8_t, inbuf, inlen + 4); + unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES]; + uint32_t i; + + memcpy(inbuf, in, inlen); + + /* While we can fit in at least another full block of SHA256 output.. */ + for (i = 0; (i + 1)*SPX_SHA256_OUTPUT_BYTES <= outlen; i++) { + u32_to_bytes(inbuf + inlen, i); + sha256(out, inbuf, inlen + 4); + out += SPX_SHA256_OUTPUT_BYTES; + } + /* Until we cannot anymore, and we fill the remainder. */ + if (outlen > i * SPX_SHA256_OUTPUT_BYTES) { + u32_to_bytes(inbuf + inlen, i); + sha256(outbuf, inbuf, inlen + 4); + memcpy(out, outbuf, outlen - i * SPX_SHA256_OUTPUT_BYTES); + } +} + +/* + * mgf1 function based on the SHA-512 hash function + */ +void mgf1_512(unsigned char *out, unsigned long outlen, + const unsigned char *in, unsigned long inlen) { + PQCLEAN_VLA(uint8_t, inbuf, inlen + 4); + unsigned char outbuf[SPX_SHA512_OUTPUT_BYTES]; + uint32_t i; + + memcpy(inbuf, in, inlen); + + /* While we can fit in at least another full block of SHA512 output.. */ + for (i = 0; (i + 1)*SPX_SHA512_OUTPUT_BYTES <= outlen; i++) { + u32_to_bytes(inbuf + inlen, i); + sha512(out, inbuf, inlen + 4); + out += SPX_SHA512_OUTPUT_BYTES; + } + /* Until we cannot anymore, and we fill the remainder. */ + if (outlen > i * SPX_SHA512_OUTPUT_BYTES) { + u32_to_bytes(inbuf + inlen, i); + sha512(outbuf, inbuf, inlen + 4); + memcpy(out, outbuf, outlen - i * SPX_SHA512_OUTPUT_BYTES); + } +} + +/* + * Computes PRF(pk_seed, sk_seed, addr). + */ +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]) { + sha256ctx sha2_state; + unsigned char buf[SPX_SHA256_ADDR_BYTES + SPX_N]; + unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES]; + + /* Retrieve precomputed state containing pub_seed */ + sha256_inc_ctx_clone(&sha2_state, &ctx->state_seeded); + + /* Remainder: ADDR^c ‖ SK.seed */ + memcpy(buf, addr, SPX_SHA256_ADDR_BYTES); + memcpy(buf + SPX_SHA256_ADDR_BYTES, ctx->sk_seed, SPX_N); + + sha256_inc_finalize(outbuf, &sha2_state, buf, SPX_SHA256_ADDR_BYTES + SPX_N); + + memcpy(out, outbuf, SPX_N); +} + +/** + * Computes the message-dependent randomness R, using a secret seed as a key + * for HMAC, and an optional randomization value prefixed to the message. + * This requires m to have at least SPX_SHAX_BLOCK_BYTES + SPX_N space + * available in front of the pointer, i.e. before the message to use for the + * prefix. This is necessary to prevent having to move the message around (and + * allocate memory for it). + */ +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { + (void)ctx; + + unsigned char buf[SPX_SHAX_BLOCK_BYTES + SPX_SHAX_OUTPUT_BYTES]; + shaXstate state; + int i; + + + /* This implements HMAC-SHA */ + for (i = 0; i < SPX_N; i++) { + buf[i] = 0x36 ^ sk_prf[i]; + } + memset(buf + SPX_N, 0x36, SPX_SHAX_BLOCK_BYTES - SPX_N); + + shaX_inc_init(&state); + shaX_inc_blocks(&state, buf, 1); + + memcpy(buf, optrand, SPX_N); + + /* If optrand + message cannot fill up an entire block */ + if (SPX_N + mlen < SPX_SHAX_BLOCK_BYTES) { + memcpy(buf + SPX_N, m, mlen); + shaX_inc_finalize(buf + SPX_SHAX_BLOCK_BYTES, &state, + buf, mlen + SPX_N); + } + /* Otherwise first fill a block, so that finalize only uses the message */ + else { + memcpy(buf + SPX_N, m, SPX_SHAX_BLOCK_BYTES - SPX_N); + shaX_inc_blocks(&state, buf, 1); + + m += SPX_SHAX_BLOCK_BYTES - SPX_N; + mlen -= SPX_SHAX_BLOCK_BYTES - SPX_N; + shaX_inc_finalize(buf + SPX_SHAX_BLOCK_BYTES, &state, m, mlen); + } + + for (i = 0; i < SPX_N; i++) { + buf[i] = 0x5c ^ sk_prf[i]; + } + memset(buf + SPX_N, 0x5c, SPX_SHAX_BLOCK_BYTES - SPX_N); + + shaX(buf, buf, SPX_SHAX_BLOCK_BYTES + SPX_SHAX_OUTPUT_BYTES); + memcpy(R, buf, SPX_N); +} + +/** + * Computes the message hash using R, the public key, and the message. + * Outputs the message digest and the index of the leaf. The index is split in + * the tree index and the leaf index, for convenient copying to an address. + */ +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { + (void)ctx; +#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) +#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) +#define SPX_LEAF_BITS SPX_TREE_HEIGHT +#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) +#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) + + unsigned char seed[2 * SPX_N + SPX_SHAX_OUTPUT_BYTES]; + + /* Round to nearest multiple of SPX_SHAX_BLOCK_BYTES */ +#define SPX_INBLOCKS (((SPX_N + SPX_PK_BYTES + SPX_SHAX_BLOCK_BYTES - 1) & \ + -SPX_SHAX_BLOCK_BYTES) / SPX_SHAX_BLOCK_BYTES) + unsigned char inbuf[SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES]; + + unsigned char buf[SPX_DGST_BYTES]; + unsigned char *bufp = buf; + shaXstate state; + + shaX_inc_init(&state); + + // seed: SHA-X(R ‖ PK.seed ‖ PK.root ‖ M) + memcpy(inbuf, R, SPX_N); + memcpy(inbuf + SPX_N, pk, SPX_PK_BYTES); + + /* If R + pk + message cannot fill up an entire block */ + if (SPX_N + SPX_PK_BYTES + mlen < SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES) { + memcpy(inbuf + SPX_N + SPX_PK_BYTES, m, mlen); + shaX_inc_finalize(seed + 2 * SPX_N, &state, inbuf, SPX_N + SPX_PK_BYTES + mlen); + } + /* Otherwise first fill a block, so that finalize only uses the message */ + else { + memcpy(inbuf + SPX_N + SPX_PK_BYTES, m, + SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES - SPX_N - SPX_PK_BYTES); + shaX_inc_blocks(&state, inbuf, SPX_INBLOCKS); + + m += SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES - SPX_N - SPX_PK_BYTES; + mlen -= SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES - SPX_N - SPX_PK_BYTES; + shaX_inc_finalize(seed + 2 * SPX_N, &state, m, (size_t)mlen); + } + + // H_msg: MGF1-SHA-X(R ‖ PK.seed ‖ seed) + memcpy(seed, R, SPX_N); + memcpy(seed + SPX_N, pk, SPX_N); + + /* By doing this in two steps, we prevent hashing the message twice; + otherwise each iteration in MGF1 would hash the message again. */ + mgf1_X(bufp, SPX_DGST_BYTES, seed, 2 * SPX_N + SPX_SHAX_OUTPUT_BYTES); + + memcpy(digest, bufp, SPX_FORS_MSG_BYTES); + bufp += SPX_FORS_MSG_BYTES; + + + *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); + *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); + bufp += SPX_TREE_BYTES; + + *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); + *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); +} + + diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/merkle.c b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/merkle.c new file mode 100644 index 0000000000..0c1479fd93 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/merkle.c @@ -0,0 +1,59 @@ +#include +#include + +#include "address.h" +#include "merkle.h" +#include "params.h" +#include "utils.h" +#include "utilsx1.h" +#include "wots.h" +#include "wotsx1.h" + +/* + * This generates a Merkle signature (WOTS signature followed by the Merkle + * authentication path). This is in this file because most of the complexity + * is involved with the WOTS signature; the Merkle authentication path logic + * is mostly hidden in treehashx4 + */ +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf) { + unsigned char *auth_path = sig + SPX_WOTS_BYTES; + struct leaf_info_x1 info = { 0 }; + unsigned steps[ SPX_WOTS_LEN ]; + + info.wots_sig = sig; + chain_lengths(steps, root); + info.wots_steps = steps; + + set_type(&tree_addr[0], SPX_ADDR_TYPE_HASHTREE); + set_type(&info.pk_addr[0], SPX_ADDR_TYPE_WOTSPK); + copy_subtree_addr(&info.leaf_addr[0], wots_addr); + copy_subtree_addr(&info.pk_addr[0], wots_addr); + + info.wots_sign_leaf = idx_leaf; + + treehashx1(root, auth_path, ctx, + idx_leaf, 0, + SPX_TREE_HEIGHT, + wots_gen_leafx1, + tree_addr, &info); +} + +/* Compute root node of the top-most subtree. */ +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { + /* We do not need the auth path in key generation, but it simplifies the + code to have just one treehash routine that computes both root and path + in one function. */ + unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; + uint32_t top_tree_addr[8] = {0}; + uint32_t wots_addr[8] = {0}; + + set_layer_addr(top_tree_addr, SPX_D - 1); + set_layer_addr(wots_addr, SPX_D - 1); + + merkle_sign(auth_path, root, ctx, + wots_addr, top_tree_addr, + (uint32_t)~0 /* ~0 means "don't bother generating an auth path */ ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/merkle.h b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/merkle.h new file mode 100644 index 0000000000..769cf2e970 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/merkle.h @@ -0,0 +1,21 @@ +#ifndef MERKLE_H_ +#define MERKLE_H_ + +#include + +#include "context.h" +#include "params.h" + +/* Generate a Merkle signature (WOTS signature followed by the Merkle */ +/* authentication path) */ +#define merkle_sign SPX_NAMESPACE(merkle_sign) +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf); + +/* Compute the root node of the top-most subtree. */ +#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); + +#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/nistapi.h b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/nistapi.h new file mode 100644 index 0000000000..3cb71afad4 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/nistapi.h @@ -0,0 +1,87 @@ +#ifndef SPX_API_H +#define SPX_API_H + +#include +#include + +#include "params.h" + +#define CRYPTO_ALGNAME "SPHINCS+" + +#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES +#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES +#define CRYPTO_BYTES SPX_BYTES +#define CRYPTO_SEEDBYTES (3*SPX_N) + +/* + * Returns the length of a secret key, in bytes + */ +#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) +size_t crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) +size_t crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) +size_t crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) +size_t crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +#define crypto_sign SPX_NAMESPACE(crypto_sign) +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/params.h b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/params.h new file mode 100644 index 0000000000..9b78d4d3bf --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/params.h @@ -0,0 +1,61 @@ +#ifndef SPX_PARAMS_H +#define SPX_PARAMS_H + +#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSSHA2128FROBUST_CLEAN_##s + +/* Hash output length in bytes. */ +#define SPX_N 16 +/* Height of the hypertree. */ +#define SPX_FULL_HEIGHT 66 +/* Number of subtree layer. */ +#define SPX_D 22 +/* FORS tree dimensions. */ +#define SPX_FORS_HEIGHT 6 +#define SPX_FORS_TREES 33 +/* Winternitz parameter, */ +#define SPX_WOTS_W 16 + +/* The hash function is defined by linking a different hash.c file, as opposed + to setting a #define constant. */ + +/* This is a SHA2-based parameter set, hence whether we use SHA-256 + * exclusively or we use both SHA-256 and SHA-512 is controlled by + * the following #define */ +#define SPX_SHA512 0 /* Use SHA-256 for all hashes */ + +/* For clarity */ +#define SPX_ADDR_BYTES 32 + +/* WOTS parameters. */ +#define SPX_WOTS_LOGW 4 + +#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) + +/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ +#define SPX_WOTS_LEN2 3 + +#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) +#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) +#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES + +/* Subtree size. */ +#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) + +//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT +// #error SPX_D should always divide SPX_FULL_HEIGHT +//#endif + +/* FORS parameters. */ +#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) +#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) +#define SPX_FORS_PK_BYTES SPX_N + +/* Resulting SPX sizes. */ +#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ + SPX_FULL_HEIGHT * SPX_N) +#define SPX_PK_BYTES (2 * SPX_N) +#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) + +#include "sha2_offsets.h" + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/sha2_offsets.h b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/sha2_offsets.h new file mode 100644 index 0000000000..6e3584f7a4 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/sha2_offsets.h @@ -0,0 +1,27 @@ +#ifndef SHA2_OFFSETS_H_ +#define SHA2_OFFSETS_H_ + +#define SPX_SHA256_BLOCK_BYTES 64 +#define SPX_SHA256_OUTPUT_BYTES 32 + +#define SPX_SHA512_BLOCK_BYTES 128 +#define SPX_SHA512_OUTPUT_BYTES 64 + +/* + * Offsets of various fields in the address structure when we use SHA2 as + * the Sphincs+ hash function + */ + +#define SPX_OFFSET_LAYER 0 /* The byte used to specify the Merkle tree layer */ +#define SPX_OFFSET_TREE 1 /* The start of the 8 byte field used to specify the tree */ +#define SPX_OFFSET_TYPE 9 /* The byte used to specify the hash type (reason) */ +#define SPX_OFFSET_KP_ADDR2 12 /* The high byte used to specify the key pair (which one-time signature) */ +#define SPX_OFFSET_KP_ADDR1 13 /* The low byte used to specify the key pair */ +#define SPX_OFFSET_CHAIN_ADDR 17 /* The byte used to specify the chain address (which Winternitz chain) */ +#define SPX_OFFSET_HASH_ADDR 21 /* The byte used to specify the hash address (where in the Winternitz chain) */ +#define SPX_OFFSET_TREE_HGT 17 /* The byte used to specify the height of this node in the FORS or Merkle tree */ +#define SPX_OFFSET_TREE_INDEX 18 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ + +#define SPX_SHA2 1 + +#endif /* SHA2_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/sign.c b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/sign.c new file mode 100644 index 0000000000..9d0c7d1b22 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/sign.c @@ -0,0 +1,286 @@ +#include +#include +#include + +#include "address.h" +#include "context.h" +#include "fors.h" +#include "hash.h" +#include "merkle.h" +#include "nistapi.h" +#include "params.h" +#include "randombytes.h" +#include "thash.h" +#include "utils.h" +#include "wots.h" + +/* + * Returns the length of a secret key, in bytes + */ +size_t crypto_sign_secretkeybytes(void) { + return CRYPTO_SECRETKEYBYTES; +} + +/* + * Returns the length of a public key, in bytes + */ +size_t crypto_sign_publickeybytes(void) { + return CRYPTO_PUBLICKEYBYTES; +} + +/* + * Returns the length of a signature, in bytes + */ +size_t crypto_sign_bytes(void) { + return CRYPTO_BYTES; +} + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +size_t crypto_sign_seedbytes(void) { + return CRYPTO_SEEDBYTES; +} + +/* + * Generates an SPX key pair given a seed of length + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [PUB_SEED || root] + */ +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed) { + spx_ctx ctx; + + /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ + memcpy(sk, seed, CRYPTO_SEEDBYTES); + + memcpy(pk, sk + 2 * SPX_N, SPX_N); + + memcpy(ctx.pub_seed, pk, SPX_N); + memcpy(ctx.sk_seed, sk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + /* Compute root node of the top-most subtree. */ + merkle_gen_root(sk + 3 * SPX_N, &ctx); + + // cleanup + free_hash_function(&ctx); + + memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); + + return 0; +} + +/* + * Generates an SPX key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [PUB_SEED || root] + */ +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { + uint8_t seed[CRYPTO_SEEDBYTES]; + randombytes(seed, CRYPTO_SEEDBYTES); + crypto_sign_seed_keypair(pk, sk, seed); + + return 0; +} + +/** + * Returns an array containing a detached signature. + */ +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk) { + spx_ctx ctx; + + const uint8_t *sk_prf = sk + SPX_N; + const uint8_t *pk = sk + 2 * SPX_N; + + uint8_t optrand[SPX_N]; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t root[SPX_N]; + uint32_t i; + uint64_t tree; + uint32_t idx_leaf; + uint32_t wots_addr[8] = {0}; + uint32_t tree_addr[8] = {0}; + + memcpy(ctx.sk_seed, sk, SPX_N); + memcpy(ctx.pub_seed, pk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + + /* Optionally, signing can be made non-deterministic using optrand. + This can help counter side-channel attacks that would benefit from + getting a large number of traces when the signer uses the same nodes. */ + randombytes(optrand, SPX_N); + /* Compute the digest randomization value. */ + gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); + + /* Derive the message digest and leaf index from R, PK and M. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; + + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); + + /* Sign the message hash using FORS. */ + fors_sign(sig, root, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); + sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; + + /* Update the indices for the next layer. */ + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; + } + + free_hash_function(&ctx); + + *siglen = SPX_BYTES; + + return 0; +} + +/** + * Verifies a detached signature and message under a given public key. + */ +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk) { + spx_ctx ctx; + const uint8_t *pub_root = pk + SPX_N; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t wots_pk[SPX_WOTS_BYTES]; + uint8_t root[SPX_N]; + uint8_t leaf[SPX_N]; + unsigned int i; + uint64_t tree; + uint32_t idx_leaf; + uint32_t wots_addr[8] = {0}; + uint32_t tree_addr[8] = {0}; + uint32_t wots_pk_addr[8] = {0}; + + if (siglen != SPX_BYTES) { + return -1; + } + + memcpy(ctx.pub_seed, pk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); + + /* Derive the message digest and leaf index from R || PK || M. */ + /* The additional SPX_N is a result of the hash domain separator. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; + + /* Layer correctly defaults to 0, so no need to set_layer_addr */ + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); + + fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + /* For each subtree.. */ + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + copy_keypair_addr(wots_pk_addr, wots_addr); + + /* The WOTS public key is only correct if the signature was correct. */ + /* Initially, root is the FORS pk, but on subsequent iterations it is + the root of the subtree below the currently processed subtree. */ + wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); + sig += SPX_WOTS_BYTES; + + /* Compute the leaf node using the WOTS public key. */ + thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); + + /* Compute the root node of this subtree. */ + compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, + &ctx, tree_addr); + sig += SPX_TREE_HEIGHT * SPX_N; + + /* Update the indices for the next layer. */ + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; + } + + // cleanup + free_hash_function(&ctx); + + /* Check if the root node equals the root node in the public key. */ + if (memcmp(root, pub_root, SPX_N) != 0) { + return -1; + } + + return 0; +} + + +/** + * Returns an array containing the signature followed by the message. + */ +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk) { + size_t siglen; + + crypto_sign_signature(sm, &siglen, m, mlen, sk); + + memmove(sm + SPX_BYTES, m, mlen); + *smlen = siglen + mlen; + + return 0; +} + +/** + * Verifies a given signature-message pair under a given public key. + */ +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk) { + /* The API caller does not necessarily know what size a signature should be + but SPHINCS+ signatures are always exactly SPX_BYTES. */ + if (smlen < SPX_BYTES) { + memset(m, 0, smlen); + *mlen = 0; + return -1; + } + + *mlen = smlen - SPX_BYTES; + + if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { + memset(m, 0, smlen); + *mlen = 0; + return -1; + } + + /* If verification was successful, move the message to the right place. */ + memmove(m, sm + SPX_BYTES, *mlen); + + return 0; +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/thash.h b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/thash.h new file mode 100644 index 0000000000..8687ccfb4d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/thash.h @@ -0,0 +1,13 @@ +#ifndef SPX_THASH_H +#define SPX_THASH_H + +#include "context.h" +#include "params.h" + +#include + +#define thash SPX_NAMESPACE(thash) +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/thash_sha2_robust.c b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/thash_sha2_robust.c new file mode 100644 index 0000000000..18f65c2e42 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/thash_sha2_robust.c @@ -0,0 +1,39 @@ +#include +#include + +#include "address.h" +#include "context.h" +#include "hash.h" +#include "params.h" +#include "sha2.h" +#include "thash.h" +#include "utils.h" + + +/** + * Takes an array of inblocks concatenated arrays of SPX_N bytes. + */ +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]) { + unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES]; + PQCLEAN_VLA(uint8_t, bitmask, inblocks * SPX_N); + PQCLEAN_VLA(uint8_t, buf, SPX_N + SPX_SHA256_OUTPUT_BYTES + inblocks * SPX_N); + sha256ctx sha2_state; + unsigned int i; + + memcpy(buf, ctx->pub_seed, SPX_N); + memcpy(buf + SPX_N, addr, SPX_SHA256_ADDR_BYTES); + mgf1_256(bitmask, inblocks * SPX_N, buf, SPX_N + SPX_SHA256_ADDR_BYTES); + + /* Retrieve precomputed state containing pub_seed */ + sha256_inc_ctx_clone(&sha2_state, &ctx->state_seeded); + + for (i = 0; i < inblocks * SPX_N; i++) { + buf[SPX_N + SPX_SHA256_ADDR_BYTES + i] = in[i] ^ bitmask[i]; + } + + sha256_inc_finalize(outbuf, &sha2_state, buf + SPX_N, + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N); + memcpy(out, outbuf, SPX_N); +} + diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/utils.c b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/utils.c new file mode 100644 index 0000000000..177b541fb9 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/utils.c @@ -0,0 +1,148 @@ +#include + +#include "utils.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "thash.h" + +/** + * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. + */ +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in) { + int i; + + /* Iterate over out in decreasing order, for big-endianness. */ + for (i = (signed int)outlen - 1; i >= 0; i--) { + out[i] = in & 0xff; + in = in >> 8; + } +} + +void u32_to_bytes(unsigned char *out, uint32_t in) { + out[0] = (unsigned char)(in >> 24); + out[1] = (unsigned char)(in >> 16); + out[2] = (unsigned char)(in >> 8); + out[3] = (unsigned char)in; +} + +/** + * Converts the inlen bytes in 'in' from big-endian byte order to an integer. + */ +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { + unsigned long long retval = 0; + unsigned int i; + + for (i = 0; i < inlen; i++) { + retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); + } + return retval; +} + +/** + * Computes a root node given a leaf and an auth path. + * Expects address to be complete other than the tree_height and tree_index. + */ +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]) { + uint32_t i; + unsigned char buffer[2 * SPX_N]; + + /* If leaf_idx is odd (last bit = 1), current path element is a right child + and auth_path has to go left. Otherwise it is the other way around. */ + if (leaf_idx & 1) { + memcpy(buffer + SPX_N, leaf, SPX_N); + memcpy(buffer, auth_path, SPX_N); + } else { + memcpy(buffer, leaf, SPX_N); + memcpy(buffer + SPX_N, auth_path, SPX_N); + } + auth_path += SPX_N; + + for (i = 0; i < tree_height - 1; i++) { + leaf_idx >>= 1; + idx_offset >>= 1; + /* Set the address of the node we're creating. */ + set_tree_height(addr, i + 1); + set_tree_index(addr, leaf_idx + idx_offset); + + /* Pick the right or left neighbor, depending on parity of the node. */ + if (leaf_idx & 1) { + thash(buffer + SPX_N, buffer, 2, ctx, addr); + memcpy(buffer, auth_path, SPX_N); + } else { + thash(buffer, buffer, 2, ctx, addr); + memcpy(buffer + SPX_N, auth_path, SPX_N); + } + auth_path += SPX_N; + } + + /* The last iteration is exceptional; we do not copy an auth_path node. */ + leaf_idx >>= 1; + idx_offset >>= 1; + set_tree_height(addr, tree_height); + set_tree_index(addr, leaf_idx + idx_offset); + thash(root, buffer, 2, ctx, addr); +} + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx * /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]) { + PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); + PQCLEAN_VLA(unsigned int, heights, tree_height + 1); + unsigned int offset = 0; + uint32_t idx; + uint32_t tree_idx; + + for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { + /* Add the next leaf node to the stack. */ + gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); + offset++; + heights[offset - 1] = 0; + + /* If this is a node we need for the auth path.. */ + if ((leaf_idx ^ 0x1) == idx) { + memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); + } + + /* While the top-most nodes are of equal height.. */ + while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { + /* Compute index of the new node, in the next layer. */ + tree_idx = (idx >> (heights[offset - 1] + 1)); + + /* Set the address of the node we're creating. */ + set_tree_height(tree_addr, heights[offset - 1] + 1); + set_tree_index(tree_addr, + tree_idx + (idx_offset >> (heights[offset - 1] + 1))); + /* Hash the top-most nodes from the stack together. */ + thash(stack + (offset - 2)*SPX_N, + stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); + offset--; + /* Note that the top-most node is now one layer higher. */ + heights[offset - 1]++; + + /* If this is a node we need for the auth path.. */ + if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { + memcpy(auth_path + heights[offset - 1]*SPX_N, + stack + (offset - 1)*SPX_N, SPX_N); + } + } + } + memcpy(root, stack, SPX_N); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/utils.h b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/utils.h new file mode 100644 index 0000000000..64f5d5a53a --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/utils.h @@ -0,0 +1,58 @@ +#ifndef SPX_UTILS_H +#define SPX_UTILS_H + +#include + +#include "compat.h" +#include "context.h" +#include "params.h" + + +/* To support MSVC use alloca() instead of VLAs. See #20. */ + + +/** + * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. + */ +#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in); +#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) +void u32_to_bytes(unsigned char *out, uint32_t in); + +/** + * Converts the inlen bytes in 'in' from big-endian byte order to an integer. + */ +#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); + +/** + * Computes a root node given a leaf and an auth path. + * Expects address to be complete other than the tree_height and tree_index. + */ +#define compute_root SPX_NAMESPACE(compute_root) +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]); + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +#define treehash SPX_NAMESPACE(treehash) +void treehash(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx *ctx /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]); + + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/utilsx1.c b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/utilsx1.c new file mode 100644 index 0000000000..fccb69b35d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/utilsx1.c @@ -0,0 +1,100 @@ +#include + +#include "utilsx1.h" + +#include "address.h" +#include "params.h" +#include "thash.h" +#include "utils.h" + +/* + * Generate the entire Merkle tree, computing the authentication path for + * leaf_idx, and the resulting root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) + * + * This expects tree_addr to be initialized to the addr structures for the + * Merkle tree nodes + * + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + * + * This works by using the standard Merkle tree building algorithm, + */ +void treehashx1(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, + uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* Where to write the leaves */, + const spx_ctx * /* ctx */, + uint32_t idx, void *info), + uint32_t tree_addr[8], + void *info) { + /* This is where we keep the intermediate nodes */ + PQCLEAN_VLA(uint8_t, stack, tree_height * SPX_N); + + uint32_t idx; + uint32_t max_idx = (uint32_t)((1 << tree_height) - 1); + for (idx = 0;; idx++) { + unsigned char current[2 * SPX_N]; /* Current logical node is at */ + /* index[SPX_N]. We do this to minimize the number of copies */ + /* needed during a thash */ + gen_leaf( ¤t[SPX_N], ctx, idx + idx_offset, + info ); + + /* Now combine the freshly generated right node with previously */ + /* generated left ones */ + uint32_t internal_idx_offset = idx_offset; + uint32_t internal_idx = idx; + uint32_t internal_leaf = leaf_idx; + uint32_t h; /* The height we are in the Merkle tree */ + for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { + + /* Check if we hit the top of the tree */ + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[SPX_N], SPX_N ); + return; + } + + /* + * Check if the node we have is a part of the + * authentication path; if it is, write it out + */ + if ((internal_idx ^ internal_leaf) == 0x01) { + memcpy( &auth_path[ h * SPX_N ], + ¤t[SPX_N], + SPX_N ); + } + + /* + * Check if we're at a left child; if so, stop going up the stack + * Exception: if we've reached the end of the tree, keep on going + * (so we combine the last 4 nodes into the one root node in two + * more iterations) + */ + if ((internal_idx & 1) == 0 && idx < max_idx) { + break; + } + + /* Ok, we're at a right node */ + /* Now combine the left and right logical nodes together */ + + /* Set the address of the node we're creating. */ + internal_idx_offset >>= 1; + set_tree_height(tree_addr, h + 1); + set_tree_index(tree_addr, internal_idx / 2 + internal_idx_offset ); + + unsigned char *left = &stack[h * SPX_N]; + memcpy( ¤t[0], left, SPX_N ); + thash( ¤t[1 * SPX_N], + ¤t[0 * SPX_N], + 2, ctx, tree_addr); + } + + /* We've hit a left child; save the current for when we get the */ + /* corresponding right right */ + memcpy( &stack[h * SPX_N], ¤t[SPX_N], SPX_N); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/utilsx1.h b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/utilsx1.h new file mode 100644 index 0000000000..e911d17d53 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/utilsx1.h @@ -0,0 +1,27 @@ +#ifndef SPX_UTILSX4_H +#define SPX_UTILSX4_H + +#include + +#include "context.h" +#include "params.h" + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +#define treehashx1 SPX_NAMESPACE(treehashx1) +void treehashx1(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* Where to write the leaf */, + const spx_ctx * /* ctx */, + uint32_t addr_idx, void *info), + uint32_t tree_addrx4[8], void *info); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/wots.c b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/wots.c new file mode 100644 index 0000000000..249717aaa8 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/wots.c @@ -0,0 +1,108 @@ +#include +#include + +#include "wots.h" +#include "wotsx1.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "thash.h" +#include "utils.h" +#include "utilsx1.h" + +// TODO clarify address expectations, and make them more uniform. +// TODO i.e. do we expect types to be set already? +// TODO and do we expect modifications or copies? + +/** + * Computes the chaining function. + * out and in have to be n-byte arrays. + * + * Interprets in as start-th value of the chain. + * addr has to contain the address of the chain. + */ +static void gen_chain(unsigned char *out, const unsigned char *in, + unsigned int start, unsigned int steps, + const spx_ctx *ctx, uint32_t addr[8]) { + uint32_t i; + + /* Initialize out with the value at position 'start'. */ + memcpy(out, in, SPX_N); + + /* Iterate 'steps' calls to the hash function. */ + for (i = start; i < (start + steps) && i < SPX_WOTS_W; i++) { + set_hash_addr(addr, i); + thash(out, out, 1, ctx, addr); + } +} + +/** + * base_w algorithm as described in draft. + * Interprets an array of bytes as integers in base w. + * This only works when log_w is a divisor of 8. + */ +static void base_w(unsigned int *output, const int out_len, + const unsigned char *input) { + int in = 0; + int out = 0; + unsigned char total = 0; + int bits = 0; + int consumed; + + for (consumed = 0; consumed < out_len; consumed++) { + if (bits == 0) { + total = input[in]; + in++; + bits += 8; + } + bits -= SPX_WOTS_LOGW; + output[out] = (total >> bits) & (SPX_WOTS_W - 1); + out++; + } +} + +/* Computes the WOTS+ checksum over a message (in base_w). */ +static void wots_checksum(unsigned int *csum_base_w, + const unsigned int *msg_base_w) { + unsigned int csum = 0; + unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; + unsigned int i; + + /* Compute checksum. */ + for (i = 0; i < SPX_WOTS_LEN1; i++) { + csum += SPX_WOTS_W - 1 - msg_base_w[i]; + } + + /* Convert checksum to base_w. */ + /* Make sure expected empty zero bits are the least significant bits. */ + csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); + ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); + base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); +} + +/* Takes a message and derives the matching chain lengths. */ +void chain_lengths(unsigned int *lengths, const unsigned char *msg) { + base_w(lengths, SPX_WOTS_LEN1, msg); + wots_checksum(lengths + SPX_WOTS_LEN1, lengths); +} + +/** + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. + * + * Writes the computed public key to 'pk'. + */ +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]) { + unsigned int lengths[SPX_WOTS_LEN]; + uint32_t i; + + chain_lengths(lengths, msg); + + for (i = 0; i < SPX_WOTS_LEN; i++) { + set_chain_addr(addr, i); + gen_chain(pk + i * SPX_N, sig + i * SPX_N, + lengths[i], SPX_WOTS_W - 1 - lengths[i], ctx, addr); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/wots.h b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/wots.h new file mode 100644 index 0000000000..4e7692eeef --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/wots.h @@ -0,0 +1,25 @@ +#ifndef SPX_WOTS_H +#define SPX_WOTS_H + +#include + +#include "context.h" +#include "params.h" + +/** + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. + * + * Writes the computed public key to 'pk'. + */ +#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]); + +/* + * Compute the chain lengths needed for a given message hash + */ +#define chain_lengths SPX_NAMESPACE(chain_lengths) +void chain_lengths(unsigned int *lengths, const unsigned char *msg); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/wotsx1.c b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/wotsx1.c new file mode 100644 index 0000000000..3adec78dfb --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/wotsx1.c @@ -0,0 +1,76 @@ +#include +#include + +#include "wots.h" +#include "wotsx1.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "thash.h" +#include "utils.h" + +/* + * This generates a WOTS public key + * It also generates the WOTS signature if leaf_info indicates + * that we're signing with this WOTS key + */ +void wots_gen_leafx1(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info) { + struct leaf_info_x1 *info = v_info; + uint32_t *leaf_addr = info->leaf_addr; + uint32_t *pk_addr = info->pk_addr; + unsigned int i, k; + unsigned char pk_buffer[ SPX_WOTS_BYTES ]; + unsigned char *buffer; + uint32_t wots_k_mask; + + if (leaf_idx == info->wots_sign_leaf) { + /* We're traversing the leaf that's signing; generate the WOTS */ + /* signature */ + wots_k_mask = 0; + } else { + /* Nope, we're just generating pk's; turn off the signature logic */ + wots_k_mask = (uint32_t)~0; + } + + set_keypair_addr( leaf_addr, leaf_idx ); + set_keypair_addr( pk_addr, leaf_idx ); + + for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { + uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k to */ + /* the step if we're generating a signature, ~0 if we're not */ + + /* Start with the secret seed */ + set_chain_addr(leaf_addr, i); + set_hash_addr(leaf_addr, 0); + set_type(leaf_addr, SPX_ADDR_TYPE_WOTSPRF); + + prf_addr(buffer, ctx, leaf_addr); + + set_type(leaf_addr, SPX_ADDR_TYPE_WOTS); + + /* Iterate down the WOTS chain */ + for (k = 0;; k++) { + /* Check if this is the value that needs to be saved as a */ + /* part of the WOTS signature */ + if (k == wots_k) { + memcpy( info->wots_sig + i * SPX_N, buffer, SPX_N ); + } + + /* Check if we hit the top of the chain */ + if (k == SPX_WOTS_W - 1) { + break; + } + + /* Iterate one step on the chain */ + set_hash_addr(leaf_addr, k); + + thash(buffer, buffer, 1, ctx, leaf_addr); + } + } + + /* Do the final thash to generate the public keys */ + thash(dest, pk_buffer, SPX_WOTS_LEN, ctx, pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/wotsx1.h b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/wotsx1.h new file mode 100644 index 0000000000..e617929f96 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/wotsx1.h @@ -0,0 +1,39 @@ +#ifndef WOTSX1_H_ +#define WOTSX1_H_ + +#include + +#include "context.h" +#include "params.h" + +/* + * This is here to provide an interface to the internal wots_gen_leafx1 + * routine. While this routine is not referenced in the package outside of + * wots.c, it is called from the stand-alone benchmark code to characterize + * the performance + */ +struct leaf_info_x1 { + unsigned char *wots_sig; + uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ + uint32_t *wots_steps; + uint32_t leaf_addr[8]; + uint32_t pk_addr[8]; +}; + +/* Macro to set the leaf_info to something 'benign', that is, it would */ +/* run with the same time as it does during the real signing process */ +/* Used only by the benchmark code */ +#define INITIALIZE_LEAF_INFO_X1(info, addr, step_buffer) { \ + (info).wots_sig = 0; \ + (info).wots_sign_leaf = ~0; \ + (info).wots_steps = step_buffer; \ + memcpy( &(info).leaf_addr[0], (addr), 32 ); \ + memcpy( &(info).pk_addr[0], (addr), 32 ); \ + } + +#define wots_gen_leafx1 SPX_NAMESPACE(wots_gen_leafx1) +void wots_gen_leafx1(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info); + +#endif /* WOTSX1_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/LICENSE b/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/LICENSE new file mode 100644 index 0000000000..670154e353 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/LICENSE @@ -0,0 +1,116 @@ +CC0 1.0 Universal + +Statement of Purpose + +The laws of most jurisdictions throughout the world automatically confer +exclusive Copyright and Related Rights (defined below) upon the creator and +subsequent owner(s) (each and all, an "owner") of an original work of +authorship and/or a database (each, a "Work"). + +Certain owners wish to permanently relinquish those rights to a Work for the +purpose of contributing to a commons of creative, cultural and scientific +works ("Commons") that the public can reliably and without fear of later +claims of infringement build upon, modify, incorporate in other works, reuse +and redistribute as freely as possible in any form whatsoever and for any +purposes, including without limitation commercial purposes. These owners may +contribute to the Commons to promote the ideal of a free culture and the +further production of creative, cultural and scientific works, or to gain +reputation or greater distribution for their Work in part through the use and +efforts of others. + +For these and/or other purposes and motivations, and without any expectation +of additional consideration or compensation, the person associating CC0 with a +Work (the "Affirmer"), to the extent that he or she is an owner of Copyright +and Related Rights in the Work, voluntarily elects to apply CC0 to the Work +and publicly distribute the Work under its terms, with knowledge of his or her +Copyright and Related Rights in the Work and the meaning and intended legal +effect of CC0 on those rights. + +1. Copyright and Related Rights. A Work made available under CC0 may be +protected by copyright and related or neighboring rights ("Copyright and +Related Rights"). Copyright and Related Rights include, but are not limited +to, the following: + + i. the right to reproduce, adapt, distribute, perform, display, communicate, + and translate a Work; + + ii. moral rights retained by the original author(s) and/or performer(s); + + iii. publicity and privacy rights pertaining to a person's image or likeness + depicted in a Work; + + iv. rights protecting against unfair competition in regards to a Work, + subject to the limitations in paragraph 4(a), below; + + v. rights protecting the extraction, dissemination, use and reuse of data in + a Work; + + vi. database rights (such as those arising under Directive 96/9/EC of the + European Parliament and of the Council of 11 March 1996 on the legal + protection of databases, and under any national implementation thereof, + including any amended or successor version of such directive); and + + vii. other similar, equivalent or corresponding rights throughout the world + based on applicable law or treaty, and any national implementations thereof. + +2. Waiver. To the greatest extent permitted by, but not in contravention of, +applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and +unconditionally waives, abandons, and surrenders all of Affirmer's Copyright +and Related Rights and associated claims and causes of action, whether now +known or unknown (including existing as well as future claims and causes of +action), in the Work (i) in all territories worldwide, (ii) for the maximum +duration provided by applicable law or treaty (including future time +extensions), (iii) in any current or future medium and for any number of +copies, and (iv) for any purpose whatsoever, including without limitation +commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes +the Waiver for the benefit of each member of the public at large and to the +detriment of Affirmer's heirs and successors, fully intending that such Waiver +shall not be subject to revocation, rescission, cancellation, termination, or +any other legal or equitable action to disrupt the quiet enjoyment of the Work +by the public as contemplated by Affirmer's express Statement of Purpose. + +3. Public License Fallback. Should any part of the Waiver for any reason be +judged legally invalid or ineffective under applicable law, then the Waiver +shall be preserved to the maximum extent permitted taking into account +Affirmer's express Statement of Purpose. In addition, to the extent the Waiver +is so judged Affirmer hereby grants to each affected person a royalty-free, +non transferable, non sublicensable, non exclusive, irrevocable and +unconditional license to exercise Affirmer's Copyright and Related Rights in +the Work (i) in all territories worldwide, (ii) for the maximum duration +provided by applicable law or treaty (including future time extensions), (iii) +in any current or future medium and for any number of copies, and (iv) for any +purpose whatsoever, including without limitation commercial, advertising or +promotional purposes (the "License"). The License shall be deemed effective as +of the date CC0 was applied by Affirmer to the Work. Should any part of the +License for any reason be judged legally invalid or ineffective under +applicable law, such partial invalidity or ineffectiveness shall not +invalidate the remainder of the License, and in such case Affirmer hereby +affirms that he or she will not (i) exercise any of his or her remaining +Copyright and Related Rights in the Work or (ii) assert any associated claims +and causes of action with respect to the Work, in either case contrary to +Affirmer's express Statement of Purpose. + +4. Limitations and Disclaimers. + + a. No trademark or patent rights held by Affirmer are waived, abandoned, + surrendered, licensed or otherwise affected by this document. + + b. Affirmer offers the Work as-is and makes no representations or warranties + of any kind concerning the Work, express, implied, statutory or otherwise, + including without limitation warranties of title, merchantability, fitness + for a particular purpose, non infringement, or the absence of latent or + other defects, accuracy, or the present or absence of errors, whether or not + discoverable, all to the greatest extent permissible under applicable law. + + c. Affirmer disclaims responsibility for clearing rights of other persons + that may apply to the Work or any use thereof, including without limitation + any person's Copyright and Related Rights in the Work. Further, Affirmer + disclaims responsibility for obtaining any necessary consents, permissions + or other rights required for any use of the Work. + + d. Affirmer understands and acknowledges that Creative Commons is not a + party to this document and has no duty or obligation with respect to this + CC0 or use of the Work. + +For more information, please see + diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/address.c b/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/address.c new file mode 100644 index 0000000000..b956e9cb29 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/address.c @@ -0,0 +1,91 @@ +#include +#include + +#include "address.h" +#include "params.h" +#include "utils.h" + +/* + * Specify which level of Merkle tree (the "layer") we're working on + */ +void set_layer_addr(uint32_t addr[8], uint32_t layer) { + ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; +} + +/* + * Specify which Merkle tree within the level (the "tree address") we're working on + */ +void set_tree_addr(uint32_t addr[8], uint64_t tree) { + ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); +} + +/* + * Specify the reason we'll use this address structure for, that is, what + * hash will we compute with it. This is used so that unrelated types of + * hashes don't accidentally get the same address structure. The type will be + * one of the SPX_ADDR_TYPE constants + */ +void set_type(uint32_t addr[8], uint32_t type) { + ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; +} + +/* + * Copy the layer and tree fields of the address structure. This is used + * when we're doing multiple types of hashes within the same Merkle tree + */ +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); +} + +/* These functions are used for OTS addresses. */ + +/* + * Specify which Merkle leaf we're working on; that is, which OTS keypair + * we're talking about. + */ +void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { + ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; +} + +/* + * Copy the layer, tree and keypair fields of the address structure. This is + * used when we're doing multiple things within the same OTS keypair + */ +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); + ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; +} + +/* + * Specify which Merkle chain within the OTS we're working with + * (the chain address) + */ +void set_chain_addr(uint32_t addr[8], uint32_t chain) { + ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; +} + +/* + * Specify where in the Merkle chain we are +* (the hash address) + */ +void set_hash_addr(uint32_t addr[8], uint32_t hash) { + ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; +} + +/* These functions are used for all hash tree addresses (including FORS). */ + +/* + * Specify the height of the node in the Merkle/FORS tree we are in + * (the tree height) + */ +void set_tree_height(uint32_t addr[8], uint32_t tree_height) { + ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; +} + +/* + * Specify the distance from the left edge of the node in the Merkle/FORS tree + * (the tree index) + */ +void set_tree_index(uint32_t addr[8], uint32_t tree_index) { + u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/address.h b/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/address.h new file mode 100644 index 0000000000..24a84eb40c --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/address.h @@ -0,0 +1,52 @@ +#ifndef SPX_ADDRESS_H +#define SPX_ADDRESS_H + +#include + +#include "params.h" + +/* The hash types that are passed to set_type */ +#define SPX_ADDR_TYPE_WOTS 0 +#define SPX_ADDR_TYPE_WOTSPK 1 +#define SPX_ADDR_TYPE_HASHTREE 2 +#define SPX_ADDR_TYPE_FORSTREE 3 +#define SPX_ADDR_TYPE_FORSPK 4 +#define SPX_ADDR_TYPE_WOTSPRF 5 +#define SPX_ADDR_TYPE_FORSPRF 6 + +#define set_layer_addr SPX_NAMESPACE(set_layer_addr) +void set_layer_addr(uint32_t addr[8], uint32_t layer); + +#define set_tree_addr SPX_NAMESPACE(set_tree_addr) +void set_tree_addr(uint32_t addr[8], uint64_t tree); + +#define set_type SPX_NAMESPACE(set_type) +void set_type(uint32_t addr[8], uint32_t type); + +/* Copies the layer and tree part of one address into the other */ +#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); + +/* These functions are used for WOTS and FORS addresses. */ + +#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) +void set_keypair_addr(uint32_t addr[8], uint32_t keypair); + +#define set_chain_addr SPX_NAMESPACE(set_chain_addr) +void set_chain_addr(uint32_t addr[8], uint32_t chain); + +#define set_hash_addr SPX_NAMESPACE(set_hash_addr) +void set_hash_addr(uint32_t addr[8], uint32_t hash); + +#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); + +/* These functions are used for all hash tree addresses (including FORS). */ + +#define set_tree_height SPX_NAMESPACE(set_tree_height) +void set_tree_height(uint32_t addr[8], uint32_t tree_height); + +#define set_tree_index SPX_NAMESPACE(set_tree_index) +void set_tree_index(uint32_t addr[8], uint32_t tree_index); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/api.h b/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/api.h new file mode 100644 index 0000000000..91468945ab --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/api.h @@ -0,0 +1,77 @@ +#ifndef PQCLEAN_SPHINCSSHA2128FSIMPLE_AVX2_API_H +#define PQCLEAN_SPHINCSSHA2128FSIMPLE_AVX2_API_H + +#include +#include + +#define PQCLEAN_SPHINCSSHA2128FSIMPLE_AVX2_CRYPTO_ALGNAME "SPHINCS+-sha2-128f-simple" + +#define PQCLEAN_SPHINCSSHA2128FSIMPLE_AVX2_CRYPTO_SECRETKEYBYTES 64 +#define PQCLEAN_SPHINCSSHA2128FSIMPLE_AVX2_CRYPTO_PUBLICKEYBYTES 32 +#define PQCLEAN_SPHINCSSHA2128FSIMPLE_AVX2_CRYPTO_BYTES 17088 + +#define PQCLEAN_SPHINCSSHA2128FSIMPLE_AVX2_CRYPTO_SEEDBYTES 48 + +/* + * Returns the length of a secret key, in bytes + */ +size_t PQCLEAN_SPHINCSSHA2128FSIMPLE_AVX2_crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +size_t PQCLEAN_SPHINCSSHA2128FSIMPLE_AVX2_crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +size_t PQCLEAN_SPHINCSSHA2128FSIMPLE_AVX2_crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +size_t PQCLEAN_SPHINCSSHA2128FSIMPLE_AVX2_crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +int PQCLEAN_SPHINCSSHA2128FSIMPLE_AVX2_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +int PQCLEAN_SPHINCSSHA2128FSIMPLE_AVX2_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +int PQCLEAN_SPHINCSSHA2128FSIMPLE_AVX2_crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +int PQCLEAN_SPHINCSSHA2128FSIMPLE_AVX2_crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, + const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +int PQCLEAN_SPHINCSSHA2128FSIMPLE_AVX2_crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +int PQCLEAN_SPHINCSSHA2128FSIMPLE_AVX2_crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/context.h b/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/context.h new file mode 100644 index 0000000000..200d3c0fb1 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/context.h @@ -0,0 +1,26 @@ +#ifndef SPX_CONTEXT_H +#define SPX_CONTEXT_H + +#include + +#include "params.h" +#include "sha2.h" +#include "sha256avx.h" + +// funky ordering due to optimal padding +typedef struct { + sha256x8ctx statex8_seeded; + sha256ctx state_seeded; + + uint8_t pub_seed[SPX_N]; + uint8_t sk_seed[SPX_N]; +} spx_ctx; + + +#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) +void initialize_hash_function(spx_ctx *ctx); + +#define free_hash_function SPX_NAMESPACE(free_hash_function) +void free_hash_function(spx_ctx *ctx); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/context_sha2.c b/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/context_sha2.c new file mode 100644 index 0000000000..073af8dd15 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/context_sha2.c @@ -0,0 +1,44 @@ +#include + +#include "context.h" + +/** + * Absorb the constant pub_seed using one round of the compression function + * This initializes state_seeded and state_seeded_512, which can then be + * reused in thash + **/ +static void seed_state(spx_ctx *ctx) { + uint8_t block[SPX_SHA512_BLOCK_BYTES]; + size_t i; + + for (i = 0; i < SPX_N; ++i) { + block[i] = ctx->pub_seed[i]; + } + for (i = SPX_N; i < SPX_SHA512_BLOCK_BYTES; ++i) { + block[i] = 0; + } + /* block has been properly initialized for both SHA-256 and SHA-512 */ + + sha256_inc_init(&ctx->state_seeded); + sha256_inc_blocks(&ctx->state_seeded, block, 1); + + // initialize x8 + sha256_init8x(&ctx->statex8_seeded); + sha256_transform8x(&ctx->statex8_seeded, + block, block, block, block, block, block, block, block); + + ctx->statex8_seeded.datalen = 0; + ctx->statex8_seeded.msglen = 512; + +} + + +/* For SHA, we initialize the hash function at the start */ +void initialize_hash_function(spx_ctx *ctx) { + seed_state(ctx); +} + +/* Free the incremental hashing context for heap-based SHA2 APIs */ +void free_hash_function(spx_ctx *ctx) { + sha256_inc_ctx_release(&ctx->state_seeded); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/fors.c b/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/fors.c new file mode 100644 index 0000000000..4cab8e7415 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/fors.c @@ -0,0 +1,226 @@ +#include +#include +#include + +#include "fors.h" + + +#include "address.h" +#include "hash.h" +#include "hashx8.h" +#include "thash.h" +#include "thashx8.h" +#include "utils.h" +#include "utilsx8.h" +static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + prf_addr(sk, ctx, fors_leaf_addr); +} + +static void fors_gen_skx8(unsigned char *sk0, + unsigned char *sk1, + unsigned char *sk2, + unsigned char *sk3, + unsigned char *sk4, + unsigned char *sk5, + unsigned char *sk6, + unsigned char *sk7, const spx_ctx *ctx, + uint32_t fors_leaf_addrx8[8 * 8]) { + prf_addrx8(sk0, sk1, sk2, sk3, sk4, sk5, sk6, sk7, + ctx, fors_leaf_addrx8); +} + +static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, + const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + thash(leaf, sk, 1, ctx, fors_leaf_addr); +} + +static void fors_sk_to_leafx8(unsigned char *leaf0, + unsigned char *leaf1, + unsigned char *leaf2, + unsigned char *leaf3, + unsigned char *leaf4, + unsigned char *leaf5, + unsigned char *leaf6, + unsigned char *leaf7, + const unsigned char *sk0, + const unsigned char *sk1, + const unsigned char *sk2, + const unsigned char *sk3, + const unsigned char *sk4, + const unsigned char *sk5, + const unsigned char *sk6, + const unsigned char *sk7, + const spx_ctx *ctx, + uint32_t fors_leaf_addrx8[8 * 8]) { + thashx8(leaf0, leaf1, leaf2, leaf3, leaf4, leaf5, leaf6, leaf7, + sk0, sk1, sk2, sk3, sk4, sk5, sk6, sk7, + 1, ctx, fors_leaf_addrx8); +} + +struct fors_gen_leaf_info { + uint32_t leaf_addrx[8 * 8]; +}; + +static void fors_gen_leafx8(unsigned char *leaf, + const spx_ctx *ctx, + uint32_t addr_idx, void *info) { + struct fors_gen_leaf_info *fors_info = info; + uint32_t *fors_leaf_addrx8 = fors_info->leaf_addrx; + unsigned int j; + + /* Only set the parts that the caller doesn't set */ + for (j = 0; j < 8; j++) { + set_tree_index(fors_leaf_addrx8 + j * 8, addr_idx + j); + set_type(fors_leaf_addrx8 + j * 8, SPX_ADDR_TYPE_FORSPRF); + } + + fors_gen_skx8(leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + leaf + 2 * SPX_N, + leaf + 3 * SPX_N, + leaf + 4 * SPX_N, + leaf + 5 * SPX_N, + leaf + 6 * SPX_N, + leaf + 7 * SPX_N, + ctx, fors_leaf_addrx8); + + for (j = 0; j < 8; j++) { + set_type(fors_leaf_addrx8 + j * 8, SPX_ADDR_TYPE_FORSTREE); + } + + fors_sk_to_leafx8(leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + leaf + 2 * SPX_N, + leaf + 3 * SPX_N, + leaf + 4 * SPX_N, + leaf + 5 * SPX_N, + leaf + 6 * SPX_N, + leaf + 7 * SPX_N, + leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + leaf + 2 * SPX_N, + leaf + 3 * SPX_N, + leaf + 4 * SPX_N, + leaf + 5 * SPX_N, + leaf + 6 * SPX_N, + leaf + 7 * SPX_N, + ctx, fors_leaf_addrx8); +} + +/** + * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + * Assumes indices has space for SPX_FORS_TREES integers. + */ +static void message_to_indices(uint32_t *indices, const unsigned char *m) { + unsigned int i, j; + unsigned int offset = 0; + + for (i = 0; i < SPX_FORS_TREES; i++) { + indices[i] = 0; + for (j = 0; j < SPX_FORS_HEIGHT; j++) { + indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); + offset++; + } + } +} + +/** + * Signs a message m, deriving the secret key from sk_seed and the FTS address. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + uint32_t fors_tree_addr[8 * 8] = {0}; + struct fors_gen_leaf_info fors_info = {0}; + uint32_t *fors_leaf_addr = fors_info.leaf_addrx; + uint32_t fors_pk_addr[8] = {0}; + uint32_t idx_offset; + unsigned int i; + + for (i = 0; i < 8; i++) { + copy_keypair_addr(fors_tree_addr + 8 * i, fors_addr); + set_type(fors_tree_addr + 8 * i, SPX_ADDR_TYPE_FORSTREE); + copy_keypair_addr(fors_leaf_addr + 8 * i, fors_addr); + } + copy_keypair_addr(fors_pk_addr, fors_addr); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); + + message_to_indices(indices, m); + + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); + + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + + /* Include the secret key part that produces the selected leaf node. */ + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); + fors_gen_sk(sig, ctx, fors_tree_addr); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + sig += SPX_N; + + /* Compute the authentication path for this leaf node. */ + treehashx8(roots + i * SPX_N, sig, ctx, + indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx8, + fors_tree_addr, &fors_info); + + sig += SPX_N * SPX_FORS_HEIGHT; + } + + /* Hash horizontally across all tree roots to derive the public key. */ + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); +} + +/** + * Derives the FORS public key from a signature. + * This can be used for verification by comparing to a known public key, or to + * subsequently verify a signature on the derived public key. The latter is the + * typical use-case when used as an FTS below an OTS in a hypertree. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + unsigned char leaf[SPX_N]; + uint32_t fors_tree_addr[8] = {0}; + uint32_t fors_pk_addr[8] = {0}; + uint32_t idx_offset; + unsigned int i; + + copy_keypair_addr(fors_tree_addr, fors_addr); + copy_keypair_addr(fors_pk_addr, fors_addr); + + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); + + message_to_indices(indices, m); + + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); + + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + + /* Derive the leaf from the included secret key part. */ + fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); + sig += SPX_N; + + /* Derive the corresponding root node of this tree. */ + compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, + sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); + sig += SPX_N * SPX_FORS_HEIGHT; + } + + /* Hash horizontally across all tree roots to derive the public key. */ + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/fors.h b/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/fors.h new file mode 100644 index 0000000000..509140a178 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/fors.h @@ -0,0 +1,32 @@ +#ifndef SPX_FORS_H +#define SPX_FORS_H + +#include + +#include "context.h" +#include "params.h" + +/** + * Signs a message m, deriving the secret key from sk_seed and the FTS address. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +#define fors_sign SPX_NAMESPACE(fors_sign) +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); + +/** + * Derives the FORS public key from a signature. + * This can be used for verification by comparing to a known public key, or to + * subsequently verify a signature on the derived public key. The latter is the + * typical use-case when used as an FTS below an OTS in a hypertree. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/hash.h b/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/hash.h new file mode 100644 index 0000000000..ffe815f45d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/hash.h @@ -0,0 +1,37 @@ +#ifndef SPX_HASH_H +#define SPX_HASH_H + +#include +#include + +#include "context.h" +#include "params.h" + +#define prf_addr SPX_NAMESPACE(prf_addr) +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]); + +#define gen_message_random SPX_NAMESPACE(gen_message_random) +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); + +#define hash_message SPX_NAMESPACE(hash_message) +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); + + +# define SPX_SHA256_ADDR_BYTES 22 + +# define mgf1_256 SPX_NAMESPACE(mgf1_256) +void mgf1_256(unsigned char *out, unsigned long outlen, + const unsigned char *in, unsigned long inlen); + +# define mgf1_512 SPX_NAMESPACE(mgf1_512) +void mgf1_512(unsigned char *out, unsigned long outlen, + const unsigned char *in, unsigned long inlen); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/hash_sha2.c b/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/hash_sha2.c new file mode 100644 index 0000000000..69f0dc0013 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/hash_sha2.c @@ -0,0 +1,219 @@ +#include +#include + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "sha2.h" +#include "utils.h" + + + +#define SPX_SHAX_OUTPUT_BYTES SPX_SHA256_OUTPUT_BYTES +#define SPX_SHAX_BLOCK_BYTES SPX_SHA256_BLOCK_BYTES +#define shaX_inc_init sha256_inc_init +#define shaX_inc_blocks sha256_inc_blocks +#define shaX_inc_finalize sha256_inc_finalize +#define shaX sha256 +#define mgf1_X mgf1_256 +#define shaXstate sha256ctx + +/** + * mgf1 function based on the SHA-256 hash function + * Note that inlen should be sufficiently small that it still allows for + * an array to be allocated on the stack. Typically 'in' is merely a seed. + * Outputs outlen number of bytes + */ +void mgf1_256(unsigned char *out, unsigned long outlen, + const unsigned char *in, unsigned long inlen) { + PQCLEAN_VLA(uint8_t, inbuf, inlen + 4); + unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES]; + uint32_t i; + + memcpy(inbuf, in, inlen); + + /* While we can fit in at least another full block of SHA256 output.. */ + for (i = 0; (i + 1)*SPX_SHA256_OUTPUT_BYTES <= outlen; i++) { + u32_to_bytes(inbuf + inlen, i); + sha256(out, inbuf, inlen + 4); + out += SPX_SHA256_OUTPUT_BYTES; + } + /* Until we cannot anymore, and we fill the remainder. */ + if (outlen > i * SPX_SHA256_OUTPUT_BYTES) { + u32_to_bytes(inbuf + inlen, i); + sha256(outbuf, inbuf, inlen + 4); + memcpy(out, outbuf, outlen - i * SPX_SHA256_OUTPUT_BYTES); + } +} + +/* + * mgf1 function based on the SHA-512 hash function + */ +void mgf1_512(unsigned char *out, unsigned long outlen, + const unsigned char *in, unsigned long inlen) { + PQCLEAN_VLA(uint8_t, inbuf, inlen + 4); + unsigned char outbuf[SPX_SHA512_OUTPUT_BYTES]; + uint32_t i; + + memcpy(inbuf, in, inlen); + + /* While we can fit in at least another full block of SHA512 output.. */ + for (i = 0; (i + 1)*SPX_SHA512_OUTPUT_BYTES <= outlen; i++) { + u32_to_bytes(inbuf + inlen, i); + sha512(out, inbuf, inlen + 4); + out += SPX_SHA512_OUTPUT_BYTES; + } + /* Until we cannot anymore, and we fill the remainder. */ + if (outlen > i * SPX_SHA512_OUTPUT_BYTES) { + u32_to_bytes(inbuf + inlen, i); + sha512(outbuf, inbuf, inlen + 4); + memcpy(out, outbuf, outlen - i * SPX_SHA512_OUTPUT_BYTES); + } +} + +/* + * Computes PRF(pk_seed, sk_seed, addr). + */ +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]) { + sha256ctx sha2_state; + unsigned char buf[SPX_SHA256_ADDR_BYTES + SPX_N]; + unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES]; + + /* Retrieve precomputed state containing pub_seed */ + sha256_inc_ctx_clone(&sha2_state, &ctx->state_seeded); + + /* Remainder: ADDR^c ‖ SK.seed */ + memcpy(buf, addr, SPX_SHA256_ADDR_BYTES); + memcpy(buf + SPX_SHA256_ADDR_BYTES, ctx->sk_seed, SPX_N); + + sha256_inc_finalize(outbuf, &sha2_state, buf, SPX_SHA256_ADDR_BYTES + SPX_N); + + memcpy(out, outbuf, SPX_N); +} + +/** + * Computes the message-dependent randomness R, using a secret seed as a key + * for HMAC, and an optional randomization value prefixed to the message. + * This requires m to have at least SPX_SHAX_BLOCK_BYTES + SPX_N space + * available in front of the pointer, i.e. before the message to use for the + * prefix. This is necessary to prevent having to move the message around (and + * allocate memory for it). + */ +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { + (void)ctx; + + unsigned char buf[SPX_SHAX_BLOCK_BYTES + SPX_SHAX_OUTPUT_BYTES]; + shaXstate state; + int i; + + + /* This implements HMAC-SHA */ + for (i = 0; i < SPX_N; i++) { + buf[i] = 0x36 ^ sk_prf[i]; + } + memset(buf + SPX_N, 0x36, SPX_SHAX_BLOCK_BYTES - SPX_N); + + shaX_inc_init(&state); + shaX_inc_blocks(&state, buf, 1); + + memcpy(buf, optrand, SPX_N); + + /* If optrand + message cannot fill up an entire block */ + if (SPX_N + mlen < SPX_SHAX_BLOCK_BYTES) { + memcpy(buf + SPX_N, m, mlen); + shaX_inc_finalize(buf + SPX_SHAX_BLOCK_BYTES, &state, + buf, mlen + SPX_N); + } + /* Otherwise first fill a block, so that finalize only uses the message */ + else { + memcpy(buf + SPX_N, m, SPX_SHAX_BLOCK_BYTES - SPX_N); + shaX_inc_blocks(&state, buf, 1); + + m += SPX_SHAX_BLOCK_BYTES - SPX_N; + mlen -= SPX_SHAX_BLOCK_BYTES - SPX_N; + shaX_inc_finalize(buf + SPX_SHAX_BLOCK_BYTES, &state, m, mlen); + } + + for (i = 0; i < SPX_N; i++) { + buf[i] = 0x5c ^ sk_prf[i]; + } + memset(buf + SPX_N, 0x5c, SPX_SHAX_BLOCK_BYTES - SPX_N); + + shaX(buf, buf, SPX_SHAX_BLOCK_BYTES + SPX_SHAX_OUTPUT_BYTES); + memcpy(R, buf, SPX_N); +} + +/** + * Computes the message hash using R, the public key, and the message. + * Outputs the message digest and the index of the leaf. The index is split in + * the tree index and the leaf index, for convenient copying to an address. + */ +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { + (void)ctx; +#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) +#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) +#define SPX_LEAF_BITS SPX_TREE_HEIGHT +#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) +#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) + + unsigned char seed[2 * SPX_N + SPX_SHAX_OUTPUT_BYTES]; + + /* Round to nearest multiple of SPX_SHAX_BLOCK_BYTES */ +#define SPX_INBLOCKS (((SPX_N + SPX_PK_BYTES + SPX_SHAX_BLOCK_BYTES - 1) & \ + -SPX_SHAX_BLOCK_BYTES) / SPX_SHAX_BLOCK_BYTES) + unsigned char inbuf[SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES]; + + unsigned char buf[SPX_DGST_BYTES]; + unsigned char *bufp = buf; + shaXstate state; + + shaX_inc_init(&state); + + // seed: SHA-X(R ‖ PK.seed ‖ PK.root ‖ M) + memcpy(inbuf, R, SPX_N); + memcpy(inbuf + SPX_N, pk, SPX_PK_BYTES); + + /* If R + pk + message cannot fill up an entire block */ + if (SPX_N + SPX_PK_BYTES + mlen < SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES) { + memcpy(inbuf + SPX_N + SPX_PK_BYTES, m, mlen); + shaX_inc_finalize(seed + 2 * SPX_N, &state, inbuf, SPX_N + SPX_PK_BYTES + mlen); + } + /* Otherwise first fill a block, so that finalize only uses the message */ + else { + memcpy(inbuf + SPX_N + SPX_PK_BYTES, m, + SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES - SPX_N - SPX_PK_BYTES); + shaX_inc_blocks(&state, inbuf, SPX_INBLOCKS); + + m += SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES - SPX_N - SPX_PK_BYTES; + mlen -= SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES - SPX_N - SPX_PK_BYTES; + shaX_inc_finalize(seed + 2 * SPX_N, &state, m, (size_t)mlen); + } + + // H_msg: MGF1-SHA-X(R ‖ PK.seed ‖ seed) + memcpy(seed, R, SPX_N); + memcpy(seed + SPX_N, pk, SPX_N); + + /* By doing this in two steps, we prevent hashing the message twice; + otherwise each iteration in MGF1 would hash the message again. */ + mgf1_X(bufp, SPX_DGST_BYTES, seed, 2 * SPX_N + SPX_SHAX_OUTPUT_BYTES); + + memcpy(digest, bufp, SPX_FORS_MSG_BYTES); + bufp += SPX_FORS_MSG_BYTES; + + + *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); + *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); + bufp += SPX_TREE_BYTES; + + *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); + *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); +} + + diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/hash_sha2x8.c b/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/hash_sha2x8.c new file mode 100644 index 0000000000..e04af7a069 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/hash_sha2x8.c @@ -0,0 +1,75 @@ +#include +#include + +#include "hash.h" +#include "hashx8.h" + +#include "address.h" +#include "params.h" +#include "sha2.h" +#include "sha256avx.h" +#include "sha256x8.h" +#include "utils.h" + +/* + * 8-way parallel version of prf_addr; takes 8x as much input and output + */ +void prf_addrx8(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const spx_ctx *ctx, + const uint32_t addrx8[8 * 8]) { + unsigned char bufx8[8 * (SPX_N + SPX_SHA256_ADDR_BYTES)]; + unsigned char outbufx8[8 * SPX_SHA256_OUTPUT_BYTES]; + unsigned int j; + + for (j = 0; j < 8; j++) { + memcpy(bufx8 + j * (SPX_N + SPX_SHA256_ADDR_BYTES), + addrx8 + j * 8, SPX_SHA256_ADDR_BYTES); + memcpy( + bufx8 + j * (SPX_N + SPX_SHA256_ADDR_BYTES) + SPX_SHA256_ADDR_BYTES, + ctx->sk_seed, + SPX_N + ); + } + + sha256x8_seeded( + /* out */ + outbufx8 + 0 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 1 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 2 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 3 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 4 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 5 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 6 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 7 * SPX_SHA256_OUTPUT_BYTES, + + /* seed */ + &ctx->statex8_seeded, + + /* in */ + bufx8 + 0 * (SPX_SHA256_ADDR_BYTES + SPX_N), + bufx8 + 1 * (SPX_SHA256_ADDR_BYTES + SPX_N), + bufx8 + 2 * (SPX_SHA256_ADDR_BYTES + SPX_N), + bufx8 + 3 * (SPX_SHA256_ADDR_BYTES + SPX_N), + bufx8 + 4 * (SPX_SHA256_ADDR_BYTES + SPX_N), + bufx8 + 5 * (SPX_SHA256_ADDR_BYTES + SPX_N), + bufx8 + 6 * (SPX_SHA256_ADDR_BYTES + SPX_N), + bufx8 + 7 * (SPX_SHA256_ADDR_BYTES + SPX_N), + SPX_SHA256_ADDR_BYTES + SPX_N /* len */ + ); + + memcpy(out0, outbufx8 + 0 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out1, outbufx8 + 1 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out2, outbufx8 + 2 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out3, outbufx8 + 3 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out4, outbufx8 + 4 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out5, outbufx8 + 5 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out6, outbufx8 + 6 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out7, outbufx8 + 7 * SPX_SHA256_OUTPUT_BYTES, SPX_N); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/hashx8.h b/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/hashx8.h new file mode 100644 index 0000000000..46503f0a10 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/hashx8.h @@ -0,0 +1,20 @@ +#ifndef SPX_HASHX8_H +#define SPX_HASHX8_H + +#include + +#include "params.h" + +#define prf_addrx8 SPX_NAMESPACE(prf_addrx8) +void prf_addrx8(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const spx_ctx *ctx, + const uint32_t addrx8[8 * 8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/merkle.c b/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/merkle.c new file mode 100644 index 0000000000..1f353c8dd8 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/merkle.c @@ -0,0 +1,65 @@ +#include +#include + +#include "merkle.h" + +#include "address.h" +#include "params.h" +#include "utils.h" +#include "utilsx8.h" +#include "wots.h" +#include "wotsx8.h" + +/* + * This generates a Merkle signature (WOTS signature followed by the Merkle + * authentication path). + */ +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf) { + unsigned char *auth_path = sig + SPX_WOTS_BYTES; + uint32_t tree_addrx8[8 * 8] = { 0 }; + int j; + struct leaf_info_x8 info = { 0 }; + unsigned steps[ SPX_WOTS_LEN ]; + + info.wots_sig = sig; + chain_lengths(steps, root); + info.wots_steps = steps; + + for (j = 0; j < 8; j++) { + set_type(&tree_addrx8[8 * j], SPX_ADDR_TYPE_HASHTREE); + set_type(&info.leaf_addr[8 * j], SPX_ADDR_TYPE_WOTS); + set_type(&info.pk_addr[8 * j], SPX_ADDR_TYPE_WOTSPK); + copy_subtree_addr(&tree_addrx8[8 * j], tree_addr); + copy_subtree_addr(&info.leaf_addr[8 * j], wots_addr); + copy_subtree_addr(&info.pk_addr[8 * j], wots_addr); + } + + info.wots_sign_leaf = idx_leaf; + + treehashx8(root, auth_path, ctx, + idx_leaf, 0, + SPX_TREE_HEIGHT, + wots_gen_leafx8, + tree_addrx8, &info); +} + +/* Compute root node of the top-most subtree. */ +/* Again, in this file because wots_gen_leaf is most of the work */ +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { + /* We do not need the auth path in key generation, but it simplifies the + code to have just one treehash routine that computes both root and path + in one function. */ + unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; + uint32_t top_tree_addr[8] = {0}; + uint32_t wots_addr[8] = {0}; + + set_layer_addr(top_tree_addr, SPX_D - 1); + set_layer_addr(wots_addr, SPX_D - 1); + + merkle_sign(auth_path, root, ctx, + wots_addr, top_tree_addr, + ~0U /* ~0 means "don't bother generating an auth path */ ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/merkle.h b/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/merkle.h new file mode 100644 index 0000000000..769cf2e970 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/merkle.h @@ -0,0 +1,21 @@ +#ifndef MERKLE_H_ +#define MERKLE_H_ + +#include + +#include "context.h" +#include "params.h" + +/* Generate a Merkle signature (WOTS signature followed by the Merkle */ +/* authentication path) */ +#define merkle_sign SPX_NAMESPACE(merkle_sign) +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf); + +/* Compute the root node of the top-most subtree. */ +#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); + +#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/nistapi.h b/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/nistapi.h new file mode 100644 index 0000000000..3cb71afad4 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/nistapi.h @@ -0,0 +1,87 @@ +#ifndef SPX_API_H +#define SPX_API_H + +#include +#include + +#include "params.h" + +#define CRYPTO_ALGNAME "SPHINCS+" + +#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES +#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES +#define CRYPTO_BYTES SPX_BYTES +#define CRYPTO_SEEDBYTES (3*SPX_N) + +/* + * Returns the length of a secret key, in bytes + */ +#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) +size_t crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) +size_t crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) +size_t crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) +size_t crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +#define crypto_sign SPX_NAMESPACE(crypto_sign) +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/params.h b/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/params.h new file mode 100644 index 0000000000..79312d0d84 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/params.h @@ -0,0 +1,61 @@ +#ifndef SPX_PARAMS_H +#define SPX_PARAMS_H + +#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSSHA2128FSIMPLE_AVX2_##s + +/* Hash output length in bytes. */ +#define SPX_N 16 +/* Height of the hypertree. */ +#define SPX_FULL_HEIGHT 66 +/* Number of subtree layer. */ +#define SPX_D 22 +/* FORS tree dimensions. */ +#define SPX_FORS_HEIGHT 6 +#define SPX_FORS_TREES 33 +/* Winternitz parameter, */ +#define SPX_WOTS_W 16 + +/* The hash function is defined by linking a different hash.c file, as opposed + to setting a #define constant. */ + +/* This is a SHA2-based parameter set, hence whether we use SHA-256 + * exclusively or we use both SHA-256 and SHA-512 is controlled by + * the following #define */ +#define SPX_SHA512 0 /* Use SHA-256 for all hashes */ + +/* For clarity */ +#define SPX_ADDR_BYTES 32 + +/* WOTS parameters. */ +#define SPX_WOTS_LOGW 4 + +#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) + +/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ +#define SPX_WOTS_LEN2 3 + +#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) +#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) +#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES + +/* Subtree size. */ +#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) + +//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT +// #error SPX_D should always divide SPX_FULL_HEIGHT +//#endif + +/* FORS parameters. */ +#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) +#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) +#define SPX_FORS_PK_BYTES SPX_N + +/* Resulting SPX sizes. */ +#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ + SPX_FULL_HEIGHT * SPX_N) +#define SPX_PK_BYTES (2 * SPX_N) +#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) + +#include "sha2_offsets.h" + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/sha256avx.c b/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/sha256avx.c new file mode 100644 index 0000000000..6bbe6ecc24 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/sha256avx.c @@ -0,0 +1,357 @@ +#include +#include +#include + +#include "sha256avx.h" + +static const unsigned int RC[] = { + 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, + 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, + 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, + 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, + 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, + 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, + 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, + 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, + 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, + 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, + 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, + 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, + 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, + 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, + 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, + 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 +}; + +#define u32 uint32_t +#define u256 __m256i + +#define XOR _mm256_xor_si256 +#define OR _mm256_or_si256 +#define AND _mm256_and_si256 +#define ADD32 _mm256_add_epi32 +#define NOT(x) _mm256_xor_si256(x, _mm256_set_epi32(-1, -1, -1, -1, -1, -1, -1, -1)) + +#define LOAD(src) _mm256_loadu_si256((__m256i *)(src)) +#define STORE(dest,src) _mm256_storeu_si256((__m256i *)(dest),src) + +#define BYTESWAP(x) _mm256_shuffle_epi8(x, _mm256_set_epi8(0xc,0xd,0xe,0xf,0x8,0x9,0xa,0xb,0x4,0x5,0x6,0x7,0x0,0x1,0x2,0x3,0xc,0xd,0xe,0xf,0x8,0x9,0xa,0xb,0x4,0x5,0x6,0x7,0x0,0x1,0x2,0x3)) + +#define SHIFTR32(x, y) _mm256_srli_epi32(x, y) +#define SHIFTL32(x, y) _mm256_slli_epi32(x, y) + +#define ROTR32(x, y) OR(SHIFTR32(x, y), SHIFTL32(x, 32 - (y))) +#define ROTL32(x, y) OR(SHIFTL32(x, y), SHIFTR32(x, 32 - (y))) + +#define XOR3(a, b, c) XOR(XOR(a, b), c) + +#define ADD3_32(a, b, c) ADD32(ADD32(a, b), c) +#define ADD4_32(a, b, c, d) ADD32(ADD32(ADD32(a, b), c), d) +#define ADD5_32(a, b, c, d, e) ADD32(ADD32(ADD32(ADD32(a, b), c), d), e) + +#define MAJ_AVX(a, b, c) XOR3(AND(a, b), AND(a, c), AND(b, c)) +#define CH_AVX(a, b, c) XOR(AND(a, b), AND(NOT(a), c)) + +#define SIGMA1_AVX(x) XOR3(ROTR32(x, 6), ROTR32(x, 11), ROTR32(x, 25)) +#define SIGMA0_AVX(x) XOR3(ROTR32(x, 2), ROTR32(x, 13), ROTR32(x, 22)) + +#define WSIGMA1_AVX(x) XOR3(ROTR32(x, 17), ROTR32(x, 19), SHIFTR32(x, 10)) +#define WSIGMA0_AVX(x) XOR3(ROTR32(x, 7), ROTR32(x, 18), SHIFTR32(x, 3)) + +#define SHA256ROUND_AVX(a, b, c, d, e, f, g, h, rc, w) \ + T0 = ADD5_32(h, SIGMA1_AVX(e), CH_AVX(e, f, g), _mm256_set1_epi32((int)RC[rc]), w); \ + (d) = ADD32(d, T0); \ + T1 = ADD32(SIGMA0_AVX(a), MAJ_AVX(a, b, c)); \ + (h) = ADD32(T0, T1); + +// Transpose 8 vectors containing 32-bit values +static void transpose(u256 s[8]) { + u256 tmp0[8]; + u256 tmp1[8]; + tmp0[0] = _mm256_unpacklo_epi32(s[0], s[1]); + tmp0[1] = _mm256_unpackhi_epi32(s[0], s[1]); + tmp0[2] = _mm256_unpacklo_epi32(s[2], s[3]); + tmp0[3] = _mm256_unpackhi_epi32(s[2], s[3]); + tmp0[4] = _mm256_unpacklo_epi32(s[4], s[5]); + tmp0[5] = _mm256_unpackhi_epi32(s[4], s[5]); + tmp0[6] = _mm256_unpacklo_epi32(s[6], s[7]); + tmp0[7] = _mm256_unpackhi_epi32(s[6], s[7]); + tmp1[0] = _mm256_unpacklo_epi64(tmp0[0], tmp0[2]); + tmp1[1] = _mm256_unpackhi_epi64(tmp0[0], tmp0[2]); + tmp1[2] = _mm256_unpacklo_epi64(tmp0[1], tmp0[3]); + tmp1[3] = _mm256_unpackhi_epi64(tmp0[1], tmp0[3]); + tmp1[4] = _mm256_unpacklo_epi64(tmp0[4], tmp0[6]); + tmp1[5] = _mm256_unpackhi_epi64(tmp0[4], tmp0[6]); + tmp1[6] = _mm256_unpacklo_epi64(tmp0[5], tmp0[7]); + tmp1[7] = _mm256_unpackhi_epi64(tmp0[5], tmp0[7]); + s[0] = _mm256_permute2x128_si256(tmp1[0], tmp1[4], 0x20); + s[1] = _mm256_permute2x128_si256(tmp1[1], tmp1[5], 0x20); + s[2] = _mm256_permute2x128_si256(tmp1[2], tmp1[6], 0x20); + s[3] = _mm256_permute2x128_si256(tmp1[3], tmp1[7], 0x20); + s[4] = _mm256_permute2x128_si256(tmp1[0], tmp1[4], 0x31); + s[5] = _mm256_permute2x128_si256(tmp1[1], tmp1[5], 0x31); + s[6] = _mm256_permute2x128_si256(tmp1[2], tmp1[6], 0x31); + s[7] = _mm256_permute2x128_si256(tmp1[3], tmp1[7], 0x31); +} + +void sha256_ctx_clone8x(sha256x8ctx *out, const sha256x8ctx *in) { + memcpy(out, in, sizeof(sha256x8ctx)); +} + +void sha256_init8x(sha256x8ctx *ctx) { + ctx->s[0] = _mm256_set_epi32((int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667); + ctx->s[1] = _mm256_set_epi32((int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85); + ctx->s[2] = _mm256_set_epi32((int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372); + ctx->s[3] = _mm256_set_epi32((int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a); + ctx->s[4] = _mm256_set_epi32((int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f); + ctx->s[5] = _mm256_set_epi32((int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c); + ctx->s[6] = _mm256_set_epi32((int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab); + ctx->s[7] = _mm256_set_epi32((int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19); + + ctx->datalen = 0; + ctx->msglen = 0; +} + +void sha256_final8x(sha256x8ctx *ctx, + unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7) { + unsigned int i, curlen; + + // Padding + if (ctx->datalen < 56) { + for (i = 0; i < 8; ++i) { + curlen = ctx->datalen; + ctx->msgblocks[64 * i + curlen++] = 0x80; + while (curlen < 64) { + ctx->msgblocks[64 * i + curlen++] = 0x00; + } + } + } else { + for (i = 0; i < 8; ++i) { + curlen = ctx->datalen; + ctx->msgblocks[64 * i + curlen++] = 0x80; + while (curlen < 64) { + ctx->msgblocks[64 * i + curlen++] = 0x00; + } + } + sha256_transform8x(ctx, + &ctx->msgblocks[64 * 0], + &ctx->msgblocks[64 * 1], + &ctx->msgblocks[64 * 2], + &ctx->msgblocks[64 * 3], + &ctx->msgblocks[64 * 4], + &ctx->msgblocks[64 * 5], + &ctx->msgblocks[64 * 6], + &ctx->msgblocks[64 * 7] + ); + memset(ctx->msgblocks, 0, 8 * 64); + } + + // Add length of the message to each block + ctx->msglen += ctx->datalen * 8; + for (i = 0; i < 8; i++) { + ctx->msgblocks[64 * i + 63] = (unsigned char)(ctx->msglen); + ctx->msgblocks[64 * i + 62] = (unsigned char)(ctx->msglen >> 8); + ctx->msgblocks[64 * i + 61] = (unsigned char)(ctx->msglen >> 16); + ctx->msgblocks[64 * i + 60] = (unsigned char)(ctx->msglen >> 24); + ctx->msgblocks[64 * i + 59] = (unsigned char)(ctx->msglen >> 32); + ctx->msgblocks[64 * i + 58] = (unsigned char)(ctx->msglen >> 40); + ctx->msgblocks[64 * i + 57] = (unsigned char)(ctx->msglen >> 48); + ctx->msgblocks[64 * i + 56] = (unsigned char)(ctx->msglen >> 56); + } + sha256_transform8x(ctx, + &ctx->msgblocks[64 * 0], + &ctx->msgblocks[64 * 1], + &ctx->msgblocks[64 * 2], + &ctx->msgblocks[64 * 3], + &ctx->msgblocks[64 * 4], + &ctx->msgblocks[64 * 5], + &ctx->msgblocks[64 * 6], + &ctx->msgblocks[64 * 7] + ); + + // Compute final hash output + transpose(ctx->s); + + // Store Hash value + STORE(out0, BYTESWAP(ctx->s[0])); + STORE(out1, BYTESWAP(ctx->s[1])); + STORE(out2, BYTESWAP(ctx->s[2])); + STORE(out3, BYTESWAP(ctx->s[3])); + STORE(out4, BYTESWAP(ctx->s[4])); + STORE(out5, BYTESWAP(ctx->s[5])); + STORE(out6, BYTESWAP(ctx->s[6])); + STORE(out7, BYTESWAP(ctx->s[7])); +} + +void sha256_transform8x(sha256x8ctx *ctx, + const unsigned char *data0, + const unsigned char *data1, + const unsigned char *data2, + const unsigned char *data3, + const unsigned char *data4, + const unsigned char *data5, + const unsigned char *data6, + const unsigned char *data7) { + u256 s[8], w[64], T0, T1; + + // Load words and transform data correctly + w[0] = BYTESWAP(LOAD(data0)); + w[0 + 8] = BYTESWAP(LOAD(data0 + 32)); + w[1] = BYTESWAP(LOAD(data1)); + w[1 + 8] = BYTESWAP(LOAD(data1 + 32)); + w[2] = BYTESWAP(LOAD(data2)); + w[2 + 8] = BYTESWAP(LOAD(data2 + 32)); + w[3] = BYTESWAP(LOAD(data3)); + w[3 + 8] = BYTESWAP(LOAD(data3 + 32)); + w[4] = BYTESWAP(LOAD(data4)); + w[4 + 8] = BYTESWAP(LOAD(data4 + 32)); + w[5] = BYTESWAP(LOAD(data5)); + w[5 + 8] = BYTESWAP(LOAD(data5 + 32)); + w[6] = BYTESWAP(LOAD(data6)); + w[6 + 8] = BYTESWAP(LOAD(data6 + 32)); + w[7] = BYTESWAP(LOAD(data7)); + w[7 + 8] = BYTESWAP(LOAD(data7 + 32)); + + transpose(w); + transpose(w + 8); + + // Initial State + s[0] = ctx->s[0]; + s[1] = ctx->s[1]; + s[2] = ctx->s[2]; + s[3] = ctx->s[3]; + s[4] = ctx->s[4]; + s[5] = ctx->s[5]; + s[6] = ctx->s[6]; + s[7] = ctx->s[7]; + + SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 0, w[0]); + SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 1, w[1]); + SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 2, w[2]); + SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 3, w[3]); + SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 4, w[4]); + SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 5, w[5]); + SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 6, w[6]); + SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 7, w[7]); + SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 8, w[8]); + SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 9, w[9]); + SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 10, w[10]); + SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 11, w[11]); + SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 12, w[12]); + SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 13, w[13]); + SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 14, w[14]); + SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 15, w[15]); + w[16] = ADD4_32(WSIGMA1_AVX(w[14]), w[0], w[9], WSIGMA0_AVX(w[1])); + SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 16, w[16]); + w[17] = ADD4_32(WSIGMA1_AVX(w[15]), w[1], w[10], WSIGMA0_AVX(w[2])); + SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 17, w[17]); + w[18] = ADD4_32(WSIGMA1_AVX(w[16]), w[2], w[11], WSIGMA0_AVX(w[3])); + SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 18, w[18]); + w[19] = ADD4_32(WSIGMA1_AVX(w[17]), w[3], w[12], WSIGMA0_AVX(w[4])); + SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 19, w[19]); + w[20] = ADD4_32(WSIGMA1_AVX(w[18]), w[4], w[13], WSIGMA0_AVX(w[5])); + SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 20, w[20]); + w[21] = ADD4_32(WSIGMA1_AVX(w[19]), w[5], w[14], WSIGMA0_AVX(w[6])); + SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 21, w[21]); + w[22] = ADD4_32(WSIGMA1_AVX(w[20]), w[6], w[15], WSIGMA0_AVX(w[7])); + SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 22, w[22]); + w[23] = ADD4_32(WSIGMA1_AVX(w[21]), w[7], w[16], WSIGMA0_AVX(w[8])); + SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 23, w[23]); + w[24] = ADD4_32(WSIGMA1_AVX(w[22]), w[8], w[17], WSIGMA0_AVX(w[9])); + SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 24, w[24]); + w[25] = ADD4_32(WSIGMA1_AVX(w[23]), w[9], w[18], WSIGMA0_AVX(w[10])); + SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 25, w[25]); + w[26] = ADD4_32(WSIGMA1_AVX(w[24]), w[10], w[19], WSIGMA0_AVX(w[11])); + SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 26, w[26]); + w[27] = ADD4_32(WSIGMA1_AVX(w[25]), w[11], w[20], WSIGMA0_AVX(w[12])); + SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 27, w[27]); + w[28] = ADD4_32(WSIGMA1_AVX(w[26]), w[12], w[21], WSIGMA0_AVX(w[13])); + SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 28, w[28]); + w[29] = ADD4_32(WSIGMA1_AVX(w[27]), w[13], w[22], WSIGMA0_AVX(w[14])); + SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 29, w[29]); + w[30] = ADD4_32(WSIGMA1_AVX(w[28]), w[14], w[23], WSIGMA0_AVX(w[15])); + SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 30, w[30]); + w[31] = ADD4_32(WSIGMA1_AVX(w[29]), w[15], w[24], WSIGMA0_AVX(w[16])); + SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 31, w[31]); + w[32] = ADD4_32(WSIGMA1_AVX(w[30]), w[16], w[25], WSIGMA0_AVX(w[17])); + SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 32, w[32]); + w[33] = ADD4_32(WSIGMA1_AVX(w[31]), w[17], w[26], WSIGMA0_AVX(w[18])); + SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 33, w[33]); + w[34] = ADD4_32(WSIGMA1_AVX(w[32]), w[18], w[27], WSIGMA0_AVX(w[19])); + SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 34, w[34]); + w[35] = ADD4_32(WSIGMA1_AVX(w[33]), w[19], w[28], WSIGMA0_AVX(w[20])); + SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 35, w[35]); + w[36] = ADD4_32(WSIGMA1_AVX(w[34]), w[20], w[29], WSIGMA0_AVX(w[21])); + SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 36, w[36]); + w[37] = ADD4_32(WSIGMA1_AVX(w[35]), w[21], w[30], WSIGMA0_AVX(w[22])); + SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 37, w[37]); + w[38] = ADD4_32(WSIGMA1_AVX(w[36]), w[22], w[31], WSIGMA0_AVX(w[23])); + SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 38, w[38]); + w[39] = ADD4_32(WSIGMA1_AVX(w[37]), w[23], w[32], WSIGMA0_AVX(w[24])); + SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 39, w[39]); + w[40] = ADD4_32(WSIGMA1_AVX(w[38]), w[24], w[33], WSIGMA0_AVX(w[25])); + SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 40, w[40]); + w[41] = ADD4_32(WSIGMA1_AVX(w[39]), w[25], w[34], WSIGMA0_AVX(w[26])); + SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 41, w[41]); + w[42] = ADD4_32(WSIGMA1_AVX(w[40]), w[26], w[35], WSIGMA0_AVX(w[27])); + SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 42, w[42]); + w[43] = ADD4_32(WSIGMA1_AVX(w[41]), w[27], w[36], WSIGMA0_AVX(w[28])); + SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 43, w[43]); + w[44] = ADD4_32(WSIGMA1_AVX(w[42]), w[28], w[37], WSIGMA0_AVX(w[29])); + SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 44, w[44]); + w[45] = ADD4_32(WSIGMA1_AVX(w[43]), w[29], w[38], WSIGMA0_AVX(w[30])); + SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 45, w[45]); + w[46] = ADD4_32(WSIGMA1_AVX(w[44]), w[30], w[39], WSIGMA0_AVX(w[31])); + SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 46, w[46]); + w[47] = ADD4_32(WSIGMA1_AVX(w[45]), w[31], w[40], WSIGMA0_AVX(w[32])); + SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 47, w[47]); + w[48] = ADD4_32(WSIGMA1_AVX(w[46]), w[32], w[41], WSIGMA0_AVX(w[33])); + SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 48, w[48]); + w[49] = ADD4_32(WSIGMA1_AVX(w[47]), w[33], w[42], WSIGMA0_AVX(w[34])); + SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 49, w[49]); + w[50] = ADD4_32(WSIGMA1_AVX(w[48]), w[34], w[43], WSIGMA0_AVX(w[35])); + SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 50, w[50]); + w[51] = ADD4_32(WSIGMA1_AVX(w[49]), w[35], w[44], WSIGMA0_AVX(w[36])); + SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 51, w[51]); + w[52] = ADD4_32(WSIGMA1_AVX(w[50]), w[36], w[45], WSIGMA0_AVX(w[37])); + SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 52, w[52]); + w[53] = ADD4_32(WSIGMA1_AVX(w[51]), w[37], w[46], WSIGMA0_AVX(w[38])); + SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 53, w[53]); + w[54] = ADD4_32(WSIGMA1_AVX(w[52]), w[38], w[47], WSIGMA0_AVX(w[39])); + SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 54, w[54]); + w[55] = ADD4_32(WSIGMA1_AVX(w[53]), w[39], w[48], WSIGMA0_AVX(w[40])); + SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 55, w[55]); + w[56] = ADD4_32(WSIGMA1_AVX(w[54]), w[40], w[49], WSIGMA0_AVX(w[41])); + SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 56, w[56]); + w[57] = ADD4_32(WSIGMA1_AVX(w[55]), w[41], w[50], WSIGMA0_AVX(w[42])); + SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 57, w[57]); + w[58] = ADD4_32(WSIGMA1_AVX(w[56]), w[42], w[51], WSIGMA0_AVX(w[43])); + SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 58, w[58]); + w[59] = ADD4_32(WSIGMA1_AVX(w[57]), w[43], w[52], WSIGMA0_AVX(w[44])); + SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 59, w[59]); + w[60] = ADD4_32(WSIGMA1_AVX(w[58]), w[44], w[53], WSIGMA0_AVX(w[45])); + SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 60, w[60]); + w[61] = ADD4_32(WSIGMA1_AVX(w[59]), w[45], w[54], WSIGMA0_AVX(w[46])); + SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 61, w[61]); + w[62] = ADD4_32(WSIGMA1_AVX(w[60]), w[46], w[55], WSIGMA0_AVX(w[47])); + SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 62, w[62]); + w[63] = ADD4_32(WSIGMA1_AVX(w[61]), w[47], w[56], WSIGMA0_AVX(w[48])); + SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 63, w[63]); + + // Feed Forward + ctx->s[0] = ADD32(s[0], ctx->s[0]); + ctx->s[1] = ADD32(s[1], ctx->s[1]); + ctx->s[2] = ADD32(s[2], ctx->s[2]); + ctx->s[3] = ADD32(s[3], ctx->s[3]); + ctx->s[4] = ADD32(s[4], ctx->s[4]); + ctx->s[5] = ADD32(s[5], ctx->s[5]); + ctx->s[6] = ADD32(s[6], ctx->s[6]); + ctx->s[7] = ADD32(s[7], ctx->s[7]); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/sha256avx.h b/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/sha256avx.h new file mode 100644 index 0000000000..1e3bcf889b --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/sha256avx.h @@ -0,0 +1,44 @@ +#ifndef SHA256AVX_H +#define SHA256AVX_H + +#include +#include + +#include "params.h" + +typedef struct SHA256state { + __m256i s[8]; + unsigned char msgblocks[8 * 64]; + unsigned int datalen; + unsigned long long msglen; +} sha256x8ctx; + +#define sha256_ctx_clone8x SPX_NAMESPACE(sha256_ctx_clone8x) +void sha256_ctx_clone8x(sha256x8ctx *out, const sha256x8ctx *in); + +#define sha256_init8x SPX_NAMESPACE(sha256_init8x) +void sha256_init8x(sha256x8ctx *ctx); + +#define sha256_final8x SPX_NAMESPACE(sha256_final8x) +void sha256_final8x(sha256x8ctx *ctx, + unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7); + +#define sha256_transform8x SPX_NAMESPACE(sha256_transform8x) +void sha256_transform8x(sha256x8ctx *ctx, + const unsigned char *data0, + const unsigned char *data1, + const unsigned char *data2, + const unsigned char *data3, + const unsigned char *data4, + const unsigned char *data5, + const unsigned char *data6, + const unsigned char *data7); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/sha256x8.c b/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/sha256x8.c new file mode 100644 index 0000000000..d97750c09b --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/sha256x8.c @@ -0,0 +1,185 @@ +#include + +#include "sha256avx.h" +#include "sha256x8.h" +#include "utils.h" + +// Performs sha256x8 on an initialized (and perhaps seeded) state. +static void _sha256x8( + sha256x8ctx *ctx, + unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, unsigned long long inlen) { + unsigned long long i = 0; + while (inlen - i >= 64) { + sha256_transform8x(ctx, + in0 + i, + in1 + i, + in2 + i, + in3 + i, + in4 + i, + in5 + i, + in6 + i, + in7 + i + ); + i += 64; + ctx->msglen += 512; + } + + size_t bytes_to_copy = (size_t)(inlen - i); + memcpy(&ctx->msgblocks[64 * 0], in0 + i, bytes_to_copy); + memcpy(&ctx->msgblocks[64 * 1], in1 + i, bytes_to_copy); + memcpy(&ctx->msgblocks[64 * 2], in2 + i, bytes_to_copy); + memcpy(&ctx->msgblocks[64 * 3], in3 + i, bytes_to_copy); + memcpy(&ctx->msgblocks[64 * 4], in4 + i, bytes_to_copy); + memcpy(&ctx->msgblocks[64 * 5], in5 + i, bytes_to_copy); + memcpy(&ctx->msgblocks[64 * 6], in6 + i, bytes_to_copy); + memcpy(&ctx->msgblocks[64 * 7], in7 + i, bytes_to_copy); + ctx->datalen = (unsigned int)bytes_to_copy; + + sha256_final8x(ctx, out0, out1, out2, out3, out4, out5, out6, out7); +} + +void sha256x8_seeded( + unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const sha256x8ctx *seed, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, unsigned long long inlen) { + + sha256x8ctx ctx; + sha256_ctx_clone8x(&ctx, seed); + + _sha256x8(&ctx, out0, out1, out2, out3, out4, out5, out6, out7, + in0, in1, in2, in3, in4, in5, in6, in7, inlen); +} + +/* This provides a wrapper around the internals of 8x parallel SHA256 */ +void sha256x8(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, unsigned long long inlen) { + sha256x8ctx ctx; + sha256_init8x(&ctx); + + _sha256x8(&ctx, out0, out1, out2, out3, out4, out5, out6, out7, + in0, in1, in2, in3, in4, in5, in6, in7, inlen); +} + +/** + * Note that inlen should be sufficiently small that it still allows for + * an array to be allocated on the stack. Typically 'in' is merely a seed. + * Outputs outlen number of bytes + */ +void mgf1x8(unsigned char *outx8, unsigned long outlen, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, + unsigned long inlen) { + PQCLEAN_VLA(unsigned char, inbufx8, 8 * (inlen + 4)); + unsigned char outbufx8[8 * SPX_SHA256_OUTPUT_BYTES]; + uint32_t i; + unsigned int j; + + memcpy(inbufx8 + 0 * (inlen + 4), in0, inlen); + memcpy(inbufx8 + 1 * (inlen + 4), in1, inlen); + memcpy(inbufx8 + 2 * (inlen + 4), in2, inlen); + memcpy(inbufx8 + 3 * (inlen + 4), in3, inlen); + memcpy(inbufx8 + 4 * (inlen + 4), in4, inlen); + memcpy(inbufx8 + 5 * (inlen + 4), in5, inlen); + memcpy(inbufx8 + 6 * (inlen + 4), in6, inlen); + memcpy(inbufx8 + 7 * (inlen + 4), in7, inlen); + + /* While we can fit in at least another full block of SHA256 output.. */ + for (i = 0; (i + 1)*SPX_SHA256_OUTPUT_BYTES <= outlen; i++) { + for (j = 0; j < 8; j++) { + u32_to_bytes(inbufx8 + inlen + j * (inlen + 4), i); + } + + sha256x8(outx8 + 0 * outlen, + outx8 + 1 * outlen, + outx8 + 2 * outlen, + outx8 + 3 * outlen, + outx8 + 4 * outlen, + outx8 + 5 * outlen, + outx8 + 6 * outlen, + outx8 + 7 * outlen, + inbufx8 + 0 * (inlen + 4), + inbufx8 + 1 * (inlen + 4), + inbufx8 + 2 * (inlen + 4), + inbufx8 + 3 * (inlen + 4), + inbufx8 + 4 * (inlen + 4), + inbufx8 + 5 * (inlen + 4), + inbufx8 + 6 * (inlen + 4), + inbufx8 + 7 * (inlen + 4), inlen + 4); + outx8 += SPX_SHA256_OUTPUT_BYTES; + } + /* Until we cannot anymore, and we fill the remainder. */ + for (j = 0; j < 8; j++) { + u32_to_bytes(inbufx8 + inlen + j * (inlen + 4), i); + } + sha256x8(outbufx8 + 0 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 1 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 2 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 3 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 4 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 5 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 6 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 7 * SPX_SHA256_OUTPUT_BYTES, + inbufx8 + 0 * (inlen + 4), + inbufx8 + 1 * (inlen + 4), + inbufx8 + 2 * (inlen + 4), + inbufx8 + 3 * (inlen + 4), + inbufx8 + 4 * (inlen + 4), + inbufx8 + 5 * (inlen + 4), + inbufx8 + 6 * (inlen + 4), + inbufx8 + 7 * (inlen + 4), inlen + 4); + + for (j = 0; j < 8; j++) { + memcpy(outx8 + j * outlen, + outbufx8 + j * SPX_SHA256_OUTPUT_BYTES, + outlen - i * SPX_SHA256_OUTPUT_BYTES); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/sha256x8.h b/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/sha256x8.h new file mode 100644 index 0000000000..4f7330a6c1 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/sha256x8.h @@ -0,0 +1,64 @@ +#ifndef SPX_SHA256X8_H +#define SPX_SHA256X8_H + +#include "params.h" +#include "sha256avx.h" + + + +#define sha256x8_seeded SPX_NAMESPACE(sha256x8_seeded) +void sha256x8_seeded( + unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const sha256x8ctx *seed, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, unsigned long long inlen); + +/* This provides a wrapper around the internals of 8x parallel SHA256 */ +#define sha256x8 SPX_NAMESPACE(sha256x8) +void sha256x8(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, unsigned long long inlen); + +/** + * Note that inlen should be sufficiently small that it still allows for + * an array to be allocated on the stack. Typically 'in' is merely a seed. + * Outputs outlen number of bytes + */ +#define mgf1x8 SPX_NAMESPACE(mgf1x8) +void mgf1x8(unsigned char *outx8, unsigned long outlen, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, + unsigned long inlen); +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/sha2_offsets.h b/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/sha2_offsets.h new file mode 100644 index 0000000000..6e3584f7a4 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/sha2_offsets.h @@ -0,0 +1,27 @@ +#ifndef SHA2_OFFSETS_H_ +#define SHA2_OFFSETS_H_ + +#define SPX_SHA256_BLOCK_BYTES 64 +#define SPX_SHA256_OUTPUT_BYTES 32 + +#define SPX_SHA512_BLOCK_BYTES 128 +#define SPX_SHA512_OUTPUT_BYTES 64 + +/* + * Offsets of various fields in the address structure when we use SHA2 as + * the Sphincs+ hash function + */ + +#define SPX_OFFSET_LAYER 0 /* The byte used to specify the Merkle tree layer */ +#define SPX_OFFSET_TREE 1 /* The start of the 8 byte field used to specify the tree */ +#define SPX_OFFSET_TYPE 9 /* The byte used to specify the hash type (reason) */ +#define SPX_OFFSET_KP_ADDR2 12 /* The high byte used to specify the key pair (which one-time signature) */ +#define SPX_OFFSET_KP_ADDR1 13 /* The low byte used to specify the key pair */ +#define SPX_OFFSET_CHAIN_ADDR 17 /* The byte used to specify the chain address (which Winternitz chain) */ +#define SPX_OFFSET_HASH_ADDR 21 /* The byte used to specify the hash address (where in the Winternitz chain) */ +#define SPX_OFFSET_TREE_HGT 17 /* The byte used to specify the height of this node in the FORS or Merkle tree */ +#define SPX_OFFSET_TREE_INDEX 18 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ + +#define SPX_SHA2 1 + +#endif /* SHA2_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/sign.c b/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/sign.c new file mode 100644 index 0000000000..9d0c7d1b22 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/sign.c @@ -0,0 +1,286 @@ +#include +#include +#include + +#include "address.h" +#include "context.h" +#include "fors.h" +#include "hash.h" +#include "merkle.h" +#include "nistapi.h" +#include "params.h" +#include "randombytes.h" +#include "thash.h" +#include "utils.h" +#include "wots.h" + +/* + * Returns the length of a secret key, in bytes + */ +size_t crypto_sign_secretkeybytes(void) { + return CRYPTO_SECRETKEYBYTES; +} + +/* + * Returns the length of a public key, in bytes + */ +size_t crypto_sign_publickeybytes(void) { + return CRYPTO_PUBLICKEYBYTES; +} + +/* + * Returns the length of a signature, in bytes + */ +size_t crypto_sign_bytes(void) { + return CRYPTO_BYTES; +} + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +size_t crypto_sign_seedbytes(void) { + return CRYPTO_SEEDBYTES; +} + +/* + * Generates an SPX key pair given a seed of length + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [PUB_SEED || root] + */ +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed) { + spx_ctx ctx; + + /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ + memcpy(sk, seed, CRYPTO_SEEDBYTES); + + memcpy(pk, sk + 2 * SPX_N, SPX_N); + + memcpy(ctx.pub_seed, pk, SPX_N); + memcpy(ctx.sk_seed, sk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + /* Compute root node of the top-most subtree. */ + merkle_gen_root(sk + 3 * SPX_N, &ctx); + + // cleanup + free_hash_function(&ctx); + + memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); + + return 0; +} + +/* + * Generates an SPX key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [PUB_SEED || root] + */ +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { + uint8_t seed[CRYPTO_SEEDBYTES]; + randombytes(seed, CRYPTO_SEEDBYTES); + crypto_sign_seed_keypair(pk, sk, seed); + + return 0; +} + +/** + * Returns an array containing a detached signature. + */ +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk) { + spx_ctx ctx; + + const uint8_t *sk_prf = sk + SPX_N; + const uint8_t *pk = sk + 2 * SPX_N; + + uint8_t optrand[SPX_N]; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t root[SPX_N]; + uint32_t i; + uint64_t tree; + uint32_t idx_leaf; + uint32_t wots_addr[8] = {0}; + uint32_t tree_addr[8] = {0}; + + memcpy(ctx.sk_seed, sk, SPX_N); + memcpy(ctx.pub_seed, pk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + + /* Optionally, signing can be made non-deterministic using optrand. + This can help counter side-channel attacks that would benefit from + getting a large number of traces when the signer uses the same nodes. */ + randombytes(optrand, SPX_N); + /* Compute the digest randomization value. */ + gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); + + /* Derive the message digest and leaf index from R, PK and M. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; + + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); + + /* Sign the message hash using FORS. */ + fors_sign(sig, root, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); + sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; + + /* Update the indices for the next layer. */ + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; + } + + free_hash_function(&ctx); + + *siglen = SPX_BYTES; + + return 0; +} + +/** + * Verifies a detached signature and message under a given public key. + */ +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk) { + spx_ctx ctx; + const uint8_t *pub_root = pk + SPX_N; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t wots_pk[SPX_WOTS_BYTES]; + uint8_t root[SPX_N]; + uint8_t leaf[SPX_N]; + unsigned int i; + uint64_t tree; + uint32_t idx_leaf; + uint32_t wots_addr[8] = {0}; + uint32_t tree_addr[8] = {0}; + uint32_t wots_pk_addr[8] = {0}; + + if (siglen != SPX_BYTES) { + return -1; + } + + memcpy(ctx.pub_seed, pk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); + + /* Derive the message digest and leaf index from R || PK || M. */ + /* The additional SPX_N is a result of the hash domain separator. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; + + /* Layer correctly defaults to 0, so no need to set_layer_addr */ + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); + + fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + /* For each subtree.. */ + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + copy_keypair_addr(wots_pk_addr, wots_addr); + + /* The WOTS public key is only correct if the signature was correct. */ + /* Initially, root is the FORS pk, but on subsequent iterations it is + the root of the subtree below the currently processed subtree. */ + wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); + sig += SPX_WOTS_BYTES; + + /* Compute the leaf node using the WOTS public key. */ + thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); + + /* Compute the root node of this subtree. */ + compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, + &ctx, tree_addr); + sig += SPX_TREE_HEIGHT * SPX_N; + + /* Update the indices for the next layer. */ + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; + } + + // cleanup + free_hash_function(&ctx); + + /* Check if the root node equals the root node in the public key. */ + if (memcmp(root, pub_root, SPX_N) != 0) { + return -1; + } + + return 0; +} + + +/** + * Returns an array containing the signature followed by the message. + */ +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk) { + size_t siglen; + + crypto_sign_signature(sm, &siglen, m, mlen, sk); + + memmove(sm + SPX_BYTES, m, mlen); + *smlen = siglen + mlen; + + return 0; +} + +/** + * Verifies a given signature-message pair under a given public key. + */ +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk) { + /* The API caller does not necessarily know what size a signature should be + but SPHINCS+ signatures are always exactly SPX_BYTES. */ + if (smlen < SPX_BYTES) { + memset(m, 0, smlen); + *mlen = 0; + return -1; + } + + *mlen = smlen - SPX_BYTES; + + if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { + memset(m, 0, smlen); + *mlen = 0; + return -1; + } + + /* If verification was successful, move the message to the right place. */ + memmove(m, sm + SPX_BYTES, *mlen); + + return 0; +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/thash.h b/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/thash.h new file mode 100644 index 0000000000..8687ccfb4d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/thash.h @@ -0,0 +1,13 @@ +#ifndef SPX_THASH_H +#define SPX_THASH_H + +#include "context.h" +#include "params.h" + +#include + +#define thash SPX_NAMESPACE(thash) +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/thash_sha2_simple.c b/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/thash_sha2_simple.c new file mode 100644 index 0000000000..197b4e7a0a --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/thash_sha2_simple.c @@ -0,0 +1,32 @@ +#include +#include + +#include "thash.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "sha2.h" +#include "utils.h" + + +/** + * Takes an array of inblocks concatenated arrays of SPX_N bytes. + */ +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]) { + + unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES]; + sha256ctx sha2_state; + PQCLEAN_VLA(uint8_t, buf, SPX_SHA256_ADDR_BYTES + inblocks * SPX_N); + + /* Retrieve precomputed state containing pub_seed */ + sha256_inc_ctx_clone(&sha2_state, &ctx->state_seeded); + + memcpy(buf, addr, SPX_SHA256_ADDR_BYTES); + memcpy(buf + SPX_SHA256_ADDR_BYTES, in, inblocks * SPX_N); + + sha256_inc_finalize(outbuf, &sha2_state, buf, SPX_SHA256_ADDR_BYTES + inblocks * SPX_N); + memcpy(out, outbuf, SPX_N); +} + diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/thash_sha2_simplex8.c b/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/thash_sha2_simplex8.c new file mode 100644 index 0000000000..eb491a0a43 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/thash_sha2_simplex8.c @@ -0,0 +1,96 @@ +#include +#include + +#include "thashx8.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "sha2.h" +#include "sha256avx.h" +#include "sha256x8.h" +#include "utils.h" + + +/** + * 8-way parallel version of thash; takes 8x as much input and output + */ +void thashx8(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addrx8[8 * 8]) { + PQCLEAN_VLA(unsigned char, bufx8, 8 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)); + unsigned char outbufx8[8 * SPX_SHA256_OUTPUT_BYTES]; + unsigned int i; + + for (i = 0; i < 8; i++) { + memcpy(bufx8 + i * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + addrx8 + i * 8, SPX_SHA256_ADDR_BYTES); + } + + memcpy(bufx8 + SPX_SHA256_ADDR_BYTES + + 0 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), in0, inblocks * SPX_N); + memcpy(bufx8 + SPX_SHA256_ADDR_BYTES + + 1 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), in1, inblocks * SPX_N); + memcpy(bufx8 + SPX_SHA256_ADDR_BYTES + + 2 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), in2, inblocks * SPX_N); + memcpy(bufx8 + SPX_SHA256_ADDR_BYTES + + 3 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), in3, inblocks * SPX_N); + memcpy(bufx8 + SPX_SHA256_ADDR_BYTES + + 4 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), in4, inblocks * SPX_N); + memcpy(bufx8 + SPX_SHA256_ADDR_BYTES + + 5 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), in5, inblocks * SPX_N); + memcpy(bufx8 + SPX_SHA256_ADDR_BYTES + + 6 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), in6, inblocks * SPX_N); + memcpy(bufx8 + SPX_SHA256_ADDR_BYTES + + 7 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), in7, inblocks * SPX_N); + + sha256x8_seeded( + /* out */ + outbufx8 + 0 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 1 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 2 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 3 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 4 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 5 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 6 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 7 * SPX_SHA256_OUTPUT_BYTES, + + /* seed */ + &ctx->statex8_seeded, + + /* in */ + bufx8 + 0 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + 1 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + 2 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + 3 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + 4 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + 5 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + 6 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + 7 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N /* len */ + ); + + memcpy(out0, outbufx8 + 0 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out1, outbufx8 + 1 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out2, outbufx8 + 2 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out3, outbufx8 + 3 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out4, outbufx8 + 4 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out5, outbufx8 + 5 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out6, outbufx8 + 6 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out7, outbufx8 + 7 * SPX_SHA256_OUTPUT_BYTES, SPX_N); +} + diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/thashx8.h b/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/thashx8.h new file mode 100644 index 0000000000..c02fe9cf3e --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/thashx8.h @@ -0,0 +1,28 @@ +#ifndef SPX_THASHX8_H +#define SPX_THASHX8_H + +#include + +#include "context.h" +#include "params.h" + +#define thashx8 SPX_NAMESPACE(thashx8) +void thashx8(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addrx8[8 * 8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/utils.c b/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/utils.c new file mode 100644 index 0000000000..177b541fb9 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/utils.c @@ -0,0 +1,148 @@ +#include + +#include "utils.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "thash.h" + +/** + * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. + */ +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in) { + int i; + + /* Iterate over out in decreasing order, for big-endianness. */ + for (i = (signed int)outlen - 1; i >= 0; i--) { + out[i] = in & 0xff; + in = in >> 8; + } +} + +void u32_to_bytes(unsigned char *out, uint32_t in) { + out[0] = (unsigned char)(in >> 24); + out[1] = (unsigned char)(in >> 16); + out[2] = (unsigned char)(in >> 8); + out[3] = (unsigned char)in; +} + +/** + * Converts the inlen bytes in 'in' from big-endian byte order to an integer. + */ +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { + unsigned long long retval = 0; + unsigned int i; + + for (i = 0; i < inlen; i++) { + retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); + } + return retval; +} + +/** + * Computes a root node given a leaf and an auth path. + * Expects address to be complete other than the tree_height and tree_index. + */ +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]) { + uint32_t i; + unsigned char buffer[2 * SPX_N]; + + /* If leaf_idx is odd (last bit = 1), current path element is a right child + and auth_path has to go left. Otherwise it is the other way around. */ + if (leaf_idx & 1) { + memcpy(buffer + SPX_N, leaf, SPX_N); + memcpy(buffer, auth_path, SPX_N); + } else { + memcpy(buffer, leaf, SPX_N); + memcpy(buffer + SPX_N, auth_path, SPX_N); + } + auth_path += SPX_N; + + for (i = 0; i < tree_height - 1; i++) { + leaf_idx >>= 1; + idx_offset >>= 1; + /* Set the address of the node we're creating. */ + set_tree_height(addr, i + 1); + set_tree_index(addr, leaf_idx + idx_offset); + + /* Pick the right or left neighbor, depending on parity of the node. */ + if (leaf_idx & 1) { + thash(buffer + SPX_N, buffer, 2, ctx, addr); + memcpy(buffer, auth_path, SPX_N); + } else { + thash(buffer, buffer, 2, ctx, addr); + memcpy(buffer + SPX_N, auth_path, SPX_N); + } + auth_path += SPX_N; + } + + /* The last iteration is exceptional; we do not copy an auth_path node. */ + leaf_idx >>= 1; + idx_offset >>= 1; + set_tree_height(addr, tree_height); + set_tree_index(addr, leaf_idx + idx_offset); + thash(root, buffer, 2, ctx, addr); +} + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx * /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]) { + PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); + PQCLEAN_VLA(unsigned int, heights, tree_height + 1); + unsigned int offset = 0; + uint32_t idx; + uint32_t tree_idx; + + for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { + /* Add the next leaf node to the stack. */ + gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); + offset++; + heights[offset - 1] = 0; + + /* If this is a node we need for the auth path.. */ + if ((leaf_idx ^ 0x1) == idx) { + memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); + } + + /* While the top-most nodes are of equal height.. */ + while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { + /* Compute index of the new node, in the next layer. */ + tree_idx = (idx >> (heights[offset - 1] + 1)); + + /* Set the address of the node we're creating. */ + set_tree_height(tree_addr, heights[offset - 1] + 1); + set_tree_index(tree_addr, + tree_idx + (idx_offset >> (heights[offset - 1] + 1))); + /* Hash the top-most nodes from the stack together. */ + thash(stack + (offset - 2)*SPX_N, + stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); + offset--; + /* Note that the top-most node is now one layer higher. */ + heights[offset - 1]++; + + /* If this is a node we need for the auth path.. */ + if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { + memcpy(auth_path + heights[offset - 1]*SPX_N, + stack + (offset - 1)*SPX_N, SPX_N); + } + } + } + memcpy(root, stack, SPX_N); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/utils.h b/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/utils.h new file mode 100644 index 0000000000..64f5d5a53a --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/utils.h @@ -0,0 +1,58 @@ +#ifndef SPX_UTILS_H +#define SPX_UTILS_H + +#include + +#include "compat.h" +#include "context.h" +#include "params.h" + + +/* To support MSVC use alloca() instead of VLAs. See #20. */ + + +/** + * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. + */ +#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in); +#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) +void u32_to_bytes(unsigned char *out, uint32_t in); + +/** + * Converts the inlen bytes in 'in' from big-endian byte order to an integer. + */ +#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); + +/** + * Computes a root node given a leaf and an auth path. + * Expects address to be complete other than the tree_height and tree_index. + */ +#define compute_root SPX_NAMESPACE(compute_root) +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]); + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +#define treehash SPX_NAMESPACE(treehash) +void treehash(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx *ctx /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]); + + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/utilsx8.c b/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/utilsx8.c new file mode 100644 index 0000000000..f044b9595d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/utilsx8.c @@ -0,0 +1,146 @@ +#include + +#include "utils.h" +#include "utilsx8.h" + +#include "address.h" +#include "params.h" +#include "thashx8.h" + +/* + * Generate the entire Merkle tree, computing the authentication path for leaf_idx, + * and the resulting root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) + * + * This expects tree_addrx8 to be initialized to 8 parallel addr structures for + * the Merkle tree nodes + * + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + * + * This works by using the standard Merkle tree building algorithm, except + * that each 'node' tracked is actually 8 consecutive nodes in the real tree. + * When we combine two logical nodes ABCDEFGH and STUVWXYZ, we perform the H + * operation on adjacent real nodes, forming the parent logical node + * (AB)(CD)(EF)(GH)(ST)(UV)(WX)(YZ) + * + * When we get to the top three levels of the real tree (where there is only + * one logical node), we continue this operation three more times; the right + * most real node will by the actual root (and the other 7 nodes will be + * garbage). We follow the same thashx8 logic so that the 'extract + * authentication path components' part of the loop is still executed (and + * to simplify the code somewhat) + * + * This currently assumes tree_height >= 3; I suspect that doing an adjusting + * idx, addr_idx on the gen_leafx8 call if tree_height < 3 would fix it; since + * we don't actually use such short trees, I haven't bothered + */ +void treehashx8(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, + uint32_t tree_height, + void (*gen_leafx8)( + unsigned char * /* Where to write the leaves */, + const spx_ctx *, + uint32_t idx, void *info), + uint32_t tree_addrx8[8 * 8], + void *info) { + /* This is where we keep the intermediate nodes */ + PQCLEAN_VLA(unsigned char, stackx8, tree_height * 8 * SPX_N); + uint32_t left_adj = 0, prev_left_adj = 0; /* When we're doing the top 3 */ + /* levels, the left-most part of the tree isn't at the beginning */ + /* of current[]. These give the offset of the actual start */ + + uint32_t idx; + uint32_t max_idx = ((uint32_t)1 << (tree_height - 3)) - 1; + for (idx = 0;; idx++) { + unsigned char current[8 * SPX_N]; /* Current logical node */ + gen_leafx8( current, ctx, 8 * idx + idx_offset, + info ); + + /* Now combine the freshly generated right node with previously */ + /* generated left ones */ + uint32_t internal_idx_offset = idx_offset; + uint32_t internal_idx = idx; + uint32_t internal_leaf = leaf_idx; + uint32_t h; /* The height we are in the Merkle tree */ + for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { + + /* Special processing if we're at the top of the tree */ + if (h >= tree_height - 3) { + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[7 * SPX_N], SPX_N ); + return; + } + /* The tree indexing logic is a bit off in this case */ + /* Adjust it so that the left-most node of the part of */ + /* the tree that we're processing has index 0 */ + prev_left_adj = left_adj; + left_adj = (uint32_t)(8 - (1 << (tree_height - h - 1))); + } + + /* Check if we hit the top of the tree */ + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[7 * SPX_N], SPX_N ); + return; + } + + /* + * Check if one of the nodes we have is a part of the + * authentication path; if it is, write it out + */ + if ((((internal_idx << 3) ^ internal_leaf) & ~0x7U) == 0) { + memcpy( &auth_path[ h * SPX_N ], + ¤t[(((internal_leaf & 7) ^ 1) + prev_left_adj) * SPX_N], + SPX_N ); + } + + /* + * Check if we're at a left child; if so, stop going up the stack + * Exception: if we've reached the end of the tree, keep on going + * (so we combine the last 8 nodes into the one root node in three + * more iterations) + */ + if ((internal_idx & 1) == 0 && idx < max_idx) { + break; + } + + /* Ok, we're at a right node (or doing the top 3 levels) */ + /* Now combine the left and right logical nodes together */ + + /* Set the address of the node we're creating. */ + uint32_t j; + internal_idx_offset >>= 1; + for (j = 0; j < 8; j++) { + set_tree_height(tree_addrx8 + j * 8, h + 1); + set_tree_index(tree_addrx8 + j * 8, + (8 / 2) * (internal_idx & ~1U) + j - left_adj + internal_idx_offset ); + } + unsigned char *left = &stackx8[h * 8 * SPX_N]; + thashx8( ¤t[0 * SPX_N], + ¤t[1 * SPX_N], + ¤t[2 * SPX_N], + ¤t[3 * SPX_N], + ¤t[4 * SPX_N], + ¤t[5 * SPX_N], + ¤t[6 * SPX_N], + ¤t[7 * SPX_N], + &left [0 * SPX_N], + &left [2 * SPX_N], + &left [4 * SPX_N], + &left [6 * SPX_N], + ¤t[0 * SPX_N], + ¤t[2 * SPX_N], + ¤t[4 * SPX_N], + ¤t[6 * SPX_N], + 2, ctx, tree_addrx8); + } + + /* We've hit a left child; save the current for when we get the */ + /* corresponding right right */ + memcpy( &stackx8[h * 8 * SPX_N], current, 8 * SPX_N); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/utilsx8.h b/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/utilsx8.h new file mode 100644 index 0000000000..806d1e85be --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/utilsx8.h @@ -0,0 +1,29 @@ +#ifndef SPX_UTILSX8_H +#define SPX_UTILSX8_H + +#include + +#include "params.h" + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + * + * This implementation uses AVX to compute internal nodes 8 at a time (in + * parallel) + */ +#define treehashx8 SPX_NAMESPACE(treehashx8) +void treehashx8(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leafx8)( + unsigned char * /* Where to write the leaves */, + const spx_ctx * /* ctx */, + uint32_t addr_idx, void *info), + uint32_t tree_addrx8[8 * 8], void *info); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/wots.c b/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/wots.c new file mode 100644 index 0000000000..689baf4db9 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/wots.c @@ -0,0 +1,291 @@ +#include +#include + +#include "wots.h" + +#include "address.h" +#include "hash.h" +#include "hashx8.h" +#include "params.h" +#include "thash.h" +#include "thashx8.h" +#include "utils.h" +#include "utilsx8.h" +#include "wotsx8.h" + +// TODO clarify address expectations, and make them more uniform. +// TODO i.e. do we expect types to be set already? +// TODO and do we expect modifications or copies? + +/** + * Computes up the chains + */ +static void gen_chains( + unsigned char *out, + const unsigned char *in, + unsigned int start[SPX_WOTS_LEN], + const unsigned int steps[SPX_WOTS_LEN], + const spx_ctx *ctx, + uint32_t addr[8]) { + uint32_t i, j, k, idx, watching; + int done; + unsigned char empty[SPX_N]; + unsigned char *bufs[8]; + uint32_t addrs[8 * 8]; + + int l; + uint16_t counts[SPX_WOTS_W] = { 0 }; + uint16_t idxs[SPX_WOTS_LEN]; + uint16_t total, newTotal; + + /* set addrs = {addr, addr, ..., addr} */ + for (j = 0; j < 8; j++) { + memcpy(addrs + j * 8, addr, sizeof(uint32_t) * 8); + } + + /* Initialize out with the value at position 'start'. */ + memcpy(out, in, SPX_WOTS_LEN * SPX_N); + + /* Sort the chains in reverse order by steps using counting sort. */ + for (i = 0; i < SPX_WOTS_LEN; i++) { + counts[steps[i]]++; + } + total = 0; + for (l = SPX_WOTS_W - 1; l >= 0; l--) { + newTotal = counts[l] + total; + counts[l] = total; + total = newTotal; + } + for (i = 0; i < SPX_WOTS_LEN; i++) { + idxs[counts[steps[i]]] = (uint16_t)i; + counts[steps[i]]++; + } + + /* We got our work cut out for us: do it! */ + for (i = 0; i < SPX_WOTS_LEN; i += 8) { + for (j = 0; j < 8 && i + j < SPX_WOTS_LEN; j++) { + idx = idxs[i + j]; + set_chain_addr(addrs + j * 8, idx); + bufs[j] = out + SPX_N * idx; + } + + /* As the chains are sorted in reverse order, we know that the first + * chain is the longest and the last one is the shortest. We keep + * an eye on whether the last chain is done and then on the one before, + * et cetera. */ + watching = 7; + done = 0; + while (i + watching >= SPX_WOTS_LEN) { + bufs[watching] = &empty[0]; + watching--; + } + + for (k = 0;; k++) { + while (k == steps[idxs[i + watching]]) { + bufs[watching] = &empty[0]; + if (watching == 0) { + done = 1; + break; + } + watching--; + } + if (done) { + break; + } + for (j = 0; j < watching + 1; j++) { + set_hash_addr(addrs + j * 8, k + start[idxs[i + j]]); + } + + thashx8(bufs[0], bufs[1], bufs[2], bufs[3], + bufs[4], bufs[5], bufs[6], bufs[7], + bufs[0], bufs[1], bufs[2], bufs[3], + bufs[4], bufs[5], bufs[6], bufs[7], 1, ctx, addrs); + } + } +} + +/** + * base_w algorithm as described in draft. + * Interprets an array of bytes as integers in base w. + * This only works when log_w is a divisor of 8. + */ +static void base_w(unsigned int *output, const int out_len, + const unsigned char *input) { + int in = 0; + int out = 0; + unsigned char total = 0; + int bits = 0; + int consumed; + + for (consumed = 0; consumed < out_len; consumed++) { + if (bits == 0) { + total = input[in]; + in++; + bits += 8; + } + bits -= SPX_WOTS_LOGW; + output[out] = (total >> bits) & (SPX_WOTS_W - 1); + out++; + } +} + +/* Computes the WOTS+ checksum over a message (in base_w). */ +static void wots_checksum(unsigned int *csum_base_w, + const unsigned int *msg_base_w) { + unsigned int csum = 0; + unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; + unsigned int i; + + /* Compute checksum. */ + for (i = 0; i < SPX_WOTS_LEN1; i++) { + csum += SPX_WOTS_W - 1 - msg_base_w[i]; + } + + /* Convert checksum to base_w. */ + /* Make sure expected empty zero bits are the least significant bits. */ + csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); + ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); + base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); +} + +/* Takes a message and derives the matching chain lengths. */ +void chain_lengths(unsigned int *lengths, const unsigned char *msg) { + base_w(lengths, SPX_WOTS_LEN1, msg); + wots_checksum(lengths + SPX_WOTS_LEN1, lengths); +} + +/** + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. + * + * Writes the computed public key to 'pk'. + */ +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]) { + unsigned int steps[SPX_WOTS_LEN]; + unsigned int start[SPX_WOTS_LEN]; + uint32_t i; + + chain_lengths(start, msg); + + for (i = 0; i < SPX_WOTS_LEN; i++) { + steps[i] = SPX_WOTS_W - 1 - start[i]; + } + + gen_chains(pk, sig, start, steps, ctx, addr); +} + +/* + * This generates 8 sequential WOTS public keys + * It also generates the WOTS signature if leaf_info indicates + * that we're signing with one of these WOTS keys + */ +void wots_gen_leafx8(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info) { + struct leaf_info_x8 *info = v_info; + uint32_t *leaf_addr = info->leaf_addr; + uint32_t *pk_addr = info->pk_addr; + unsigned int i, j, k; + unsigned char pk_buffer[ 8 * SPX_WOTS_BYTES ]; + unsigned wots_offset = SPX_WOTS_BYTES; + unsigned char *buffer; + uint32_t wots_k_mask; + unsigned wots_sign_index; + + if (((leaf_idx ^ info->wots_sign_leaf) & ~7U) == 0) { + /* We're traversing the leaf that's signing; generate the WOTS */ + /* signature */ + wots_k_mask = 0; + wots_sign_index = info->wots_sign_leaf & 7; /* Which of of the 8 */ + /* slots do the signatures come from */ + } else { + /* Nope, we're just generating pk's; turn off the signature logic */ + wots_k_mask = ~0U; + wots_sign_index = 0; + } + + for (j = 0; j < 8; j++) { + set_keypair_addr( leaf_addr + j * 8, leaf_idx + j ); + set_keypair_addr( pk_addr + j * 8, leaf_idx + j ); + } + + for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { + uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k */ + /* to the step if we're generating a signature, ~0 if we're not */ + + /* Start with the secret seed */ + for (j = 0; j < 8; j++) { + set_chain_addr(leaf_addr + j * 8, i); + set_hash_addr(leaf_addr + j * 8, 0); + set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTSPRF); + } + prf_addrx8(buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + buffer + 2 * wots_offset, + buffer + 3 * wots_offset, + buffer + 4 * wots_offset, + buffer + 5 * wots_offset, + buffer + 6 * wots_offset, + buffer + 7 * wots_offset, + ctx, leaf_addr); + + for (j = 0; j < 8; j++) { + set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTS); + } + + /* Iterate down the WOTS chain */ + for (k = 0;; k++) { + /* Check if one of the values we have needs to be saved as a */ + /* part of the WOTS signature */ + if (k == wots_k) { + memcpy( info->wots_sig + i * SPX_N, + buffer + wots_sign_index * wots_offset, SPX_N ); + } + + /* Check if we hit the top of the chain */ + if (k == SPX_WOTS_W - 1) { + break; + } + + /* Iterate one step on all 8 chains */ + for (j = 0; j < 8; j++) { + set_hash_addr(leaf_addr + j * 8, k); + } + thashx8(buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + buffer + 2 * wots_offset, + buffer + 3 * wots_offset, + buffer + 4 * wots_offset, + buffer + 5 * wots_offset, + buffer + 6 * wots_offset, + buffer + 7 * wots_offset, + buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + buffer + 2 * wots_offset, + buffer + 3 * wots_offset, + buffer + 4 * wots_offset, + buffer + 5 * wots_offset, + buffer + 6 * wots_offset, + buffer + 7 * wots_offset, 1, ctx, leaf_addr); + } + } + + /* Do the final thash to generate the public keys */ + thashx8(dest + 0 * SPX_N, + dest + 1 * SPX_N, + dest + 2 * SPX_N, + dest + 3 * SPX_N, + dest + 4 * SPX_N, + dest + 5 * SPX_N, + dest + 6 * SPX_N, + dest + 7 * SPX_N, + pk_buffer + 0 * wots_offset, + pk_buffer + 1 * wots_offset, + pk_buffer + 2 * wots_offset, + pk_buffer + 3 * wots_offset, + pk_buffer + 4 * wots_offset, + pk_buffer + 5 * wots_offset, + pk_buffer + 6 * wots_offset, + pk_buffer + 7 * wots_offset, SPX_WOTS_LEN, ctx, pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/wots.h b/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/wots.h new file mode 100644 index 0000000000..4e7692eeef --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/wots.h @@ -0,0 +1,25 @@ +#ifndef SPX_WOTS_H +#define SPX_WOTS_H + +#include + +#include "context.h" +#include "params.h" + +/** + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. + * + * Writes the computed public key to 'pk'. + */ +#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]); + +/* + * Compute the chain lengths needed for a given message hash + */ +#define chain_lengths SPX_NAMESPACE(chain_lengths) +void chain_lengths(unsigned int *lengths, const unsigned char *msg); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/wotsx8.h b/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/wotsx8.h new file mode 100644 index 0000000000..10866efb35 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_avx2/wotsx8.h @@ -0,0 +1,42 @@ +#ifndef WOTSX8_H_ +#define WOTSX8_H_ + +#include + +#include "context.h" +#include "params.h" + +/* + * This is here to provide an interface to the internal wots_gen_leafx8 + * routine. While this routine is not referenced in the package outside of + * wots.c, it is called from the stand-alone benchmark code to characterize + * the performance + */ +struct leaf_info_x8 { + unsigned char *wots_sig; + uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ + uint32_t *wots_steps; + uint32_t leaf_addr[8 * 8]; + uint32_t pk_addr[8 * 8]; +}; + +/* Macro to set the leaf_info to something 'benign', that is, it would */ +/* run with the same time as it does during the real signing process */ +/* Used only by the benchmark code */ +#define INITIALIZE_LEAF_INFO_X8(info, addr, step_buffer) { \ + (info).wots_sig = 0; \ + (info).wots_sign_leaf = ~0; \ + (info).wots_steps = step_buffer; \ + int i; \ + for (i=0; i<8; i++) { \ + memcpy( &(info).leaf_addr[8*i], addr, 32 ); \ + memcpy( &(info).pk_addr[8*i], addr, 32 ); \ + } \ + } + +#define wots_gen_leafx8 SPX_NAMESPACE(wots_gen_leafx8) +void wots_gen_leafx8(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info); + +#endif /* WOTSX8_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_clean/LICENSE b/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_clean/LICENSE new file mode 100644 index 0000000000..670154e353 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_clean/LICENSE @@ -0,0 +1,116 @@ +CC0 1.0 Universal + +Statement of Purpose + +The laws of most jurisdictions throughout the world automatically confer +exclusive Copyright and Related Rights (defined below) upon the creator and +subsequent owner(s) (each and all, an "owner") of an original work of +authorship and/or a database (each, a "Work"). + +Certain owners wish to permanently relinquish those rights to a Work for the +purpose of contributing to a commons of creative, cultural and scientific +works ("Commons") that the public can reliably and without fear of later +claims of infringement build upon, modify, incorporate in other works, reuse +and redistribute as freely as possible in any form whatsoever and for any +purposes, including without limitation commercial purposes. These owners may +contribute to the Commons to promote the ideal of a free culture and the +further production of creative, cultural and scientific works, or to gain +reputation or greater distribution for their Work in part through the use and +efforts of others. + +For these and/or other purposes and motivations, and without any expectation +of additional consideration or compensation, the person associating CC0 with a +Work (the "Affirmer"), to the extent that he or she is an owner of Copyright +and Related Rights in the Work, voluntarily elects to apply CC0 to the Work +and publicly distribute the Work under its terms, with knowledge of his or her +Copyright and Related Rights in the Work and the meaning and intended legal +effect of CC0 on those rights. + +1. Copyright and Related Rights. A Work made available under CC0 may be +protected by copyright and related or neighboring rights ("Copyright and +Related Rights"). Copyright and Related Rights include, but are not limited +to, the following: + + i. the right to reproduce, adapt, distribute, perform, display, communicate, + and translate a Work; + + ii. moral rights retained by the original author(s) and/or performer(s); + + iii. publicity and privacy rights pertaining to a person's image or likeness + depicted in a Work; + + iv. rights protecting against unfair competition in regards to a Work, + subject to the limitations in paragraph 4(a), below; + + v. rights protecting the extraction, dissemination, use and reuse of data in + a Work; + + vi. database rights (such as those arising under Directive 96/9/EC of the + European Parliament and of the Council of 11 March 1996 on the legal + protection of databases, and under any national implementation thereof, + including any amended or successor version of such directive); and + + vii. other similar, equivalent or corresponding rights throughout the world + based on applicable law or treaty, and any national implementations thereof. + +2. Waiver. To the greatest extent permitted by, but not in contravention of, +applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and +unconditionally waives, abandons, and surrenders all of Affirmer's Copyright +and Related Rights and associated claims and causes of action, whether now +known or unknown (including existing as well as future claims and causes of +action), in the Work (i) in all territories worldwide, (ii) for the maximum +duration provided by applicable law or treaty (including future time +extensions), (iii) in any current or future medium and for any number of +copies, and (iv) for any purpose whatsoever, including without limitation +commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes +the Waiver for the benefit of each member of the public at large and to the +detriment of Affirmer's heirs and successors, fully intending that such Waiver +shall not be subject to revocation, rescission, cancellation, termination, or +any other legal or equitable action to disrupt the quiet enjoyment of the Work +by the public as contemplated by Affirmer's express Statement of Purpose. + +3. Public License Fallback. Should any part of the Waiver for any reason be +judged legally invalid or ineffective under applicable law, then the Waiver +shall be preserved to the maximum extent permitted taking into account +Affirmer's express Statement of Purpose. In addition, to the extent the Waiver +is so judged Affirmer hereby grants to each affected person a royalty-free, +non transferable, non sublicensable, non exclusive, irrevocable and +unconditional license to exercise Affirmer's Copyright and Related Rights in +the Work (i) in all territories worldwide, (ii) for the maximum duration +provided by applicable law or treaty (including future time extensions), (iii) +in any current or future medium and for any number of copies, and (iv) for any +purpose whatsoever, including without limitation commercial, advertising or +promotional purposes (the "License"). The License shall be deemed effective as +of the date CC0 was applied by Affirmer to the Work. Should any part of the +License for any reason be judged legally invalid or ineffective under +applicable law, such partial invalidity or ineffectiveness shall not +invalidate the remainder of the License, and in such case Affirmer hereby +affirms that he or she will not (i) exercise any of his or her remaining +Copyright and Related Rights in the Work or (ii) assert any associated claims +and causes of action with respect to the Work, in either case contrary to +Affirmer's express Statement of Purpose. + +4. Limitations and Disclaimers. + + a. No trademark or patent rights held by Affirmer are waived, abandoned, + surrendered, licensed or otherwise affected by this document. + + b. Affirmer offers the Work as-is and makes no representations or warranties + of any kind concerning the Work, express, implied, statutory or otherwise, + including without limitation warranties of title, merchantability, fitness + for a particular purpose, non infringement, or the absence of latent or + other defects, accuracy, or the present or absence of errors, whether or not + discoverable, all to the greatest extent permissible under applicable law. + + c. Affirmer disclaims responsibility for clearing rights of other persons + that may apply to the Work or any use thereof, including without limitation + any person's Copyright and Related Rights in the Work. Further, Affirmer + disclaims responsibility for obtaining any necessary consents, permissions + or other rights required for any use of the Work. + + d. Affirmer understands and acknowledges that Creative Commons is not a + party to this document and has no duty or obligation with respect to this + CC0 or use of the Work. + +For more information, please see + diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_clean/address.c b/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_clean/address.c new file mode 100644 index 0000000000..b956e9cb29 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_clean/address.c @@ -0,0 +1,91 @@ +#include +#include + +#include "address.h" +#include "params.h" +#include "utils.h" + +/* + * Specify which level of Merkle tree (the "layer") we're working on + */ +void set_layer_addr(uint32_t addr[8], uint32_t layer) { + ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; +} + +/* + * Specify which Merkle tree within the level (the "tree address") we're working on + */ +void set_tree_addr(uint32_t addr[8], uint64_t tree) { + ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); +} + +/* + * Specify the reason we'll use this address structure for, that is, what + * hash will we compute with it. This is used so that unrelated types of + * hashes don't accidentally get the same address structure. The type will be + * one of the SPX_ADDR_TYPE constants + */ +void set_type(uint32_t addr[8], uint32_t type) { + ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; +} + +/* + * Copy the layer and tree fields of the address structure. This is used + * when we're doing multiple types of hashes within the same Merkle tree + */ +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); +} + +/* These functions are used for OTS addresses. */ + +/* + * Specify which Merkle leaf we're working on; that is, which OTS keypair + * we're talking about. + */ +void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { + ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; +} + +/* + * Copy the layer, tree and keypair fields of the address structure. This is + * used when we're doing multiple things within the same OTS keypair + */ +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); + ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; +} + +/* + * Specify which Merkle chain within the OTS we're working with + * (the chain address) + */ +void set_chain_addr(uint32_t addr[8], uint32_t chain) { + ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; +} + +/* + * Specify where in the Merkle chain we are +* (the hash address) + */ +void set_hash_addr(uint32_t addr[8], uint32_t hash) { + ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; +} + +/* These functions are used for all hash tree addresses (including FORS). */ + +/* + * Specify the height of the node in the Merkle/FORS tree we are in + * (the tree height) + */ +void set_tree_height(uint32_t addr[8], uint32_t tree_height) { + ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; +} + +/* + * Specify the distance from the left edge of the node in the Merkle/FORS tree + * (the tree index) + */ +void set_tree_index(uint32_t addr[8], uint32_t tree_index) { + u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_clean/address.h b/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_clean/address.h new file mode 100644 index 0000000000..24a84eb40c --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_clean/address.h @@ -0,0 +1,52 @@ +#ifndef SPX_ADDRESS_H +#define SPX_ADDRESS_H + +#include + +#include "params.h" + +/* The hash types that are passed to set_type */ +#define SPX_ADDR_TYPE_WOTS 0 +#define SPX_ADDR_TYPE_WOTSPK 1 +#define SPX_ADDR_TYPE_HASHTREE 2 +#define SPX_ADDR_TYPE_FORSTREE 3 +#define SPX_ADDR_TYPE_FORSPK 4 +#define SPX_ADDR_TYPE_WOTSPRF 5 +#define SPX_ADDR_TYPE_FORSPRF 6 + +#define set_layer_addr SPX_NAMESPACE(set_layer_addr) +void set_layer_addr(uint32_t addr[8], uint32_t layer); + +#define set_tree_addr SPX_NAMESPACE(set_tree_addr) +void set_tree_addr(uint32_t addr[8], uint64_t tree); + +#define set_type SPX_NAMESPACE(set_type) +void set_type(uint32_t addr[8], uint32_t type); + +/* Copies the layer and tree part of one address into the other */ +#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); + +/* These functions are used for WOTS and FORS addresses. */ + +#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) +void set_keypair_addr(uint32_t addr[8], uint32_t keypair); + +#define set_chain_addr SPX_NAMESPACE(set_chain_addr) +void set_chain_addr(uint32_t addr[8], uint32_t chain); + +#define set_hash_addr SPX_NAMESPACE(set_hash_addr) +void set_hash_addr(uint32_t addr[8], uint32_t hash); + +#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); + +/* These functions are used for all hash tree addresses (including FORS). */ + +#define set_tree_height SPX_NAMESPACE(set_tree_height) +void set_tree_height(uint32_t addr[8], uint32_t tree_height); + +#define set_tree_index SPX_NAMESPACE(set_tree_index) +void set_tree_index(uint32_t addr[8], uint32_t tree_index); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_clean/api.h b/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_clean/api.h new file mode 100644 index 0000000000..33b3f66e7b --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_clean/api.h @@ -0,0 +1,77 @@ +#ifndef PQCLEAN_SPHINCSSHA2128FSIMPLE_CLEAN_API_H +#define PQCLEAN_SPHINCSSHA2128FSIMPLE_CLEAN_API_H + +#include +#include + +#define PQCLEAN_SPHINCSSHA2128FSIMPLE_CLEAN_CRYPTO_ALGNAME "SPHINCS+-sha2-128f-simple" + +#define PQCLEAN_SPHINCSSHA2128FSIMPLE_CLEAN_CRYPTO_SECRETKEYBYTES 64 +#define PQCLEAN_SPHINCSSHA2128FSIMPLE_CLEAN_CRYPTO_PUBLICKEYBYTES 32 +#define PQCLEAN_SPHINCSSHA2128FSIMPLE_CLEAN_CRYPTO_BYTES 17088 + +#define PQCLEAN_SPHINCSSHA2128FSIMPLE_CLEAN_CRYPTO_SEEDBYTES 48 + +/* + * Returns the length of a secret key, in bytes + */ +size_t PQCLEAN_SPHINCSSHA2128FSIMPLE_CLEAN_crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +size_t PQCLEAN_SPHINCSSHA2128FSIMPLE_CLEAN_crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +size_t PQCLEAN_SPHINCSSHA2128FSIMPLE_CLEAN_crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +size_t PQCLEAN_SPHINCSSHA2128FSIMPLE_CLEAN_crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +int PQCLEAN_SPHINCSSHA2128FSIMPLE_CLEAN_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +int PQCLEAN_SPHINCSSHA2128FSIMPLE_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +int PQCLEAN_SPHINCSSHA2128FSIMPLE_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +int PQCLEAN_SPHINCSSHA2128FSIMPLE_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, + const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +int PQCLEAN_SPHINCSSHA2128FSIMPLE_CLEAN_crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +int PQCLEAN_SPHINCSSHA2128FSIMPLE_CLEAN_crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_clean/context.h b/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_clean/context.h new file mode 100644 index 0000000000..27effb3e10 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_clean/context.h @@ -0,0 +1,26 @@ +#ifndef SPX_CONTEXT_H +#define SPX_CONTEXT_H + +#include +#include + +#include "params.h" +#include "sha2.h" + +typedef struct { + uint8_t pub_seed[SPX_N]; + uint8_t sk_seed[SPX_N]; + + // sha256 state that absorbed pub_seed + sha256ctx state_seeded; + + +} spx_ctx; + +#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) +void initialize_hash_function(spx_ctx *ctx); + +#define free_hash_function SPX_NAMESPACE(free_hash_function) +void free_hash_function(spx_ctx *ctx); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_clean/context_sha2.c b/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_clean/context_sha2.c new file mode 100644 index 0000000000..64f7e65465 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_clean/context_sha2.c @@ -0,0 +1,33 @@ +#include "context.h" + +/** + * Absorb the constant pub_seed using one round of the compression function + * This initializes state_seeded and state_seeded_512, which can then be + * reused in thash + **/ +static void seed_state(spx_ctx *ctx) { + uint8_t block[SPX_SHA512_BLOCK_BYTES]; + size_t i; + + for (i = 0; i < SPX_N; ++i) { + block[i] = ctx->pub_seed[i]; + } + for (i = SPX_N; i < SPX_SHA512_BLOCK_BYTES; ++i) { + block[i] = 0; + } + /* block has been properly initialized for both SHA-256 and SHA-512 */ + + sha256_inc_init(&ctx->state_seeded); + sha256_inc_blocks(&ctx->state_seeded, block, 1); +} + + +/* We initialize the state for the hash functions */ +void initialize_hash_function(spx_ctx *ctx) { + seed_state(ctx); +} + +/* Free the incremental hashing context for heap-based SHA2 APIs */ +void free_hash_function(spx_ctx *ctx) { + sha256_inc_ctx_release(&ctx->state_seeded); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_clean/fors.c b/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_clean/fors.c new file mode 100644 index 0000000000..96ca72e986 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_clean/fors.c @@ -0,0 +1,156 @@ +#include +#include +#include + +#include "fors.h" + +#include "address.h" +#include "hash.h" +#include "thash.h" +#include "utils.h" +#include "utilsx1.h" + +static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + prf_addr(sk, ctx, fors_leaf_addr); +} + +static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, + const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + thash(leaf, sk, 1, ctx, fors_leaf_addr); +} + +struct fors_gen_leaf_info { + uint32_t leaf_addrx[8]; +}; + +static void fors_gen_leafx1(unsigned char *leaf, + const spx_ctx *ctx, + uint32_t addr_idx, void *info) { + struct fors_gen_leaf_info *fors_info = info; + uint32_t *fors_leaf_addr = fors_info->leaf_addrx; + + /* Only set the parts that the caller doesn't set */ + set_tree_index(fors_leaf_addr, addr_idx); + set_type(fors_leaf_addr, SPX_ADDR_TYPE_FORSPRF); + fors_gen_sk(leaf, ctx, fors_leaf_addr); + + set_type(fors_leaf_addr, SPX_ADDR_TYPE_FORSTREE); + fors_sk_to_leaf(leaf, leaf, + ctx, fors_leaf_addr); +} + +/** + * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + * Assumes indices has space for SPX_FORS_TREES integers. + */ +static void message_to_indices(uint32_t *indices, const unsigned char *m) { + unsigned int i, j; + unsigned int offset = 0; + + for (i = 0; i < SPX_FORS_TREES; i++) { + indices[i] = 0; + for (j = 0; j < SPX_FORS_HEIGHT; j++) { + indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); + offset++; + } + } +} + +/** + * Signs a message m, deriving the secret key from sk_seed and the FTS address. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + uint32_t fors_tree_addr[8] = {0}; + struct fors_gen_leaf_info fors_info = {0}; + uint32_t *fors_leaf_addr = fors_info.leaf_addrx; + uint32_t fors_pk_addr[8] = {0}; + uint32_t idx_offset; + unsigned int i; + + copy_keypair_addr(fors_tree_addr, fors_addr); + copy_keypair_addr(fors_leaf_addr, fors_addr); + + copy_keypair_addr(fors_pk_addr, fors_addr); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); + + message_to_indices(indices, m); + + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); + + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); + + /* Include the secret key part that produces the selected leaf node. */ + fors_gen_sk(sig, ctx, fors_tree_addr); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + sig += SPX_N; + + /* Compute the authentication path for this leaf node. */ + treehashx1(roots + i * SPX_N, sig, ctx, + indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx1, + fors_tree_addr, &fors_info); + + sig += SPX_N * SPX_FORS_HEIGHT; + } + + /* Hash horizontally across all tree roots to derive the public key. */ + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); +} + +/** + * Derives the FORS public key from a signature. + * This can be used for verification by comparing to a known public key, or to + * subsequently verify a signature on the derived public key. The latter is the + * typical use-case when used as an FTS below an OTS in a hypertree. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + unsigned char leaf[SPX_N]; + uint32_t fors_tree_addr[8] = {0}; + uint32_t fors_pk_addr[8] = {0}; + uint32_t idx_offset; + unsigned int i; + + copy_keypair_addr(fors_tree_addr, fors_addr); + copy_keypair_addr(fors_pk_addr, fors_addr); + + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); + + message_to_indices(indices, m); + + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); + + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + + /* Derive the leaf from the included secret key part. */ + fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); + sig += SPX_N; + + /* Derive the corresponding root node of this tree. */ + compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, + sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); + sig += SPX_N * SPX_FORS_HEIGHT; + } + + /* Hash horizontally across all tree roots to derive the public key. */ + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_clean/fors.h b/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_clean/fors.h new file mode 100644 index 0000000000..509140a178 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_clean/fors.h @@ -0,0 +1,32 @@ +#ifndef SPX_FORS_H +#define SPX_FORS_H + +#include + +#include "context.h" +#include "params.h" + +/** + * Signs a message m, deriving the secret key from sk_seed and the FTS address. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +#define fors_sign SPX_NAMESPACE(fors_sign) +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); + +/** + * Derives the FORS public key from a signature. + * This can be used for verification by comparing to a known public key, or to + * subsequently verify a signature on the derived public key. The latter is the + * typical use-case when used as an FTS below an OTS in a hypertree. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_clean/hash.h b/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_clean/hash.h new file mode 100644 index 0000000000..ffe815f45d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_clean/hash.h @@ -0,0 +1,37 @@ +#ifndef SPX_HASH_H +#define SPX_HASH_H + +#include +#include + +#include "context.h" +#include "params.h" + +#define prf_addr SPX_NAMESPACE(prf_addr) +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]); + +#define gen_message_random SPX_NAMESPACE(gen_message_random) +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); + +#define hash_message SPX_NAMESPACE(hash_message) +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); + + +# define SPX_SHA256_ADDR_BYTES 22 + +# define mgf1_256 SPX_NAMESPACE(mgf1_256) +void mgf1_256(unsigned char *out, unsigned long outlen, + const unsigned char *in, unsigned long inlen); + +# define mgf1_512 SPX_NAMESPACE(mgf1_512) +void mgf1_512(unsigned char *out, unsigned long outlen, + const unsigned char *in, unsigned long inlen); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_clean/hash_sha2.c b/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_clean/hash_sha2.c new file mode 100644 index 0000000000..69f0dc0013 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_clean/hash_sha2.c @@ -0,0 +1,219 @@ +#include +#include + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "sha2.h" +#include "utils.h" + + + +#define SPX_SHAX_OUTPUT_BYTES SPX_SHA256_OUTPUT_BYTES +#define SPX_SHAX_BLOCK_BYTES SPX_SHA256_BLOCK_BYTES +#define shaX_inc_init sha256_inc_init +#define shaX_inc_blocks sha256_inc_blocks +#define shaX_inc_finalize sha256_inc_finalize +#define shaX sha256 +#define mgf1_X mgf1_256 +#define shaXstate sha256ctx + +/** + * mgf1 function based on the SHA-256 hash function + * Note that inlen should be sufficiently small that it still allows for + * an array to be allocated on the stack. Typically 'in' is merely a seed. + * Outputs outlen number of bytes + */ +void mgf1_256(unsigned char *out, unsigned long outlen, + const unsigned char *in, unsigned long inlen) { + PQCLEAN_VLA(uint8_t, inbuf, inlen + 4); + unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES]; + uint32_t i; + + memcpy(inbuf, in, inlen); + + /* While we can fit in at least another full block of SHA256 output.. */ + for (i = 0; (i + 1)*SPX_SHA256_OUTPUT_BYTES <= outlen; i++) { + u32_to_bytes(inbuf + inlen, i); + sha256(out, inbuf, inlen + 4); + out += SPX_SHA256_OUTPUT_BYTES; + } + /* Until we cannot anymore, and we fill the remainder. */ + if (outlen > i * SPX_SHA256_OUTPUT_BYTES) { + u32_to_bytes(inbuf + inlen, i); + sha256(outbuf, inbuf, inlen + 4); + memcpy(out, outbuf, outlen - i * SPX_SHA256_OUTPUT_BYTES); + } +} + +/* + * mgf1 function based on the SHA-512 hash function + */ +void mgf1_512(unsigned char *out, unsigned long outlen, + const unsigned char *in, unsigned long inlen) { + PQCLEAN_VLA(uint8_t, inbuf, inlen + 4); + unsigned char outbuf[SPX_SHA512_OUTPUT_BYTES]; + uint32_t i; + + memcpy(inbuf, in, inlen); + + /* While we can fit in at least another full block of SHA512 output.. */ + for (i = 0; (i + 1)*SPX_SHA512_OUTPUT_BYTES <= outlen; i++) { + u32_to_bytes(inbuf + inlen, i); + sha512(out, inbuf, inlen + 4); + out += SPX_SHA512_OUTPUT_BYTES; + } + /* Until we cannot anymore, and we fill the remainder. */ + if (outlen > i * SPX_SHA512_OUTPUT_BYTES) { + u32_to_bytes(inbuf + inlen, i); + sha512(outbuf, inbuf, inlen + 4); + memcpy(out, outbuf, outlen - i * SPX_SHA512_OUTPUT_BYTES); + } +} + +/* + * Computes PRF(pk_seed, sk_seed, addr). + */ +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]) { + sha256ctx sha2_state; + unsigned char buf[SPX_SHA256_ADDR_BYTES + SPX_N]; + unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES]; + + /* Retrieve precomputed state containing pub_seed */ + sha256_inc_ctx_clone(&sha2_state, &ctx->state_seeded); + + /* Remainder: ADDR^c ‖ SK.seed */ + memcpy(buf, addr, SPX_SHA256_ADDR_BYTES); + memcpy(buf + SPX_SHA256_ADDR_BYTES, ctx->sk_seed, SPX_N); + + sha256_inc_finalize(outbuf, &sha2_state, buf, SPX_SHA256_ADDR_BYTES + SPX_N); + + memcpy(out, outbuf, SPX_N); +} + +/** + * Computes the message-dependent randomness R, using a secret seed as a key + * for HMAC, and an optional randomization value prefixed to the message. + * This requires m to have at least SPX_SHAX_BLOCK_BYTES + SPX_N space + * available in front of the pointer, i.e. before the message to use for the + * prefix. This is necessary to prevent having to move the message around (and + * allocate memory for it). + */ +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { + (void)ctx; + + unsigned char buf[SPX_SHAX_BLOCK_BYTES + SPX_SHAX_OUTPUT_BYTES]; + shaXstate state; + int i; + + + /* This implements HMAC-SHA */ + for (i = 0; i < SPX_N; i++) { + buf[i] = 0x36 ^ sk_prf[i]; + } + memset(buf + SPX_N, 0x36, SPX_SHAX_BLOCK_BYTES - SPX_N); + + shaX_inc_init(&state); + shaX_inc_blocks(&state, buf, 1); + + memcpy(buf, optrand, SPX_N); + + /* If optrand + message cannot fill up an entire block */ + if (SPX_N + mlen < SPX_SHAX_BLOCK_BYTES) { + memcpy(buf + SPX_N, m, mlen); + shaX_inc_finalize(buf + SPX_SHAX_BLOCK_BYTES, &state, + buf, mlen + SPX_N); + } + /* Otherwise first fill a block, so that finalize only uses the message */ + else { + memcpy(buf + SPX_N, m, SPX_SHAX_BLOCK_BYTES - SPX_N); + shaX_inc_blocks(&state, buf, 1); + + m += SPX_SHAX_BLOCK_BYTES - SPX_N; + mlen -= SPX_SHAX_BLOCK_BYTES - SPX_N; + shaX_inc_finalize(buf + SPX_SHAX_BLOCK_BYTES, &state, m, mlen); + } + + for (i = 0; i < SPX_N; i++) { + buf[i] = 0x5c ^ sk_prf[i]; + } + memset(buf + SPX_N, 0x5c, SPX_SHAX_BLOCK_BYTES - SPX_N); + + shaX(buf, buf, SPX_SHAX_BLOCK_BYTES + SPX_SHAX_OUTPUT_BYTES); + memcpy(R, buf, SPX_N); +} + +/** + * Computes the message hash using R, the public key, and the message. + * Outputs the message digest and the index of the leaf. The index is split in + * the tree index and the leaf index, for convenient copying to an address. + */ +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { + (void)ctx; +#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) +#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) +#define SPX_LEAF_BITS SPX_TREE_HEIGHT +#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) +#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) + + unsigned char seed[2 * SPX_N + SPX_SHAX_OUTPUT_BYTES]; + + /* Round to nearest multiple of SPX_SHAX_BLOCK_BYTES */ +#define SPX_INBLOCKS (((SPX_N + SPX_PK_BYTES + SPX_SHAX_BLOCK_BYTES - 1) & \ + -SPX_SHAX_BLOCK_BYTES) / SPX_SHAX_BLOCK_BYTES) + unsigned char inbuf[SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES]; + + unsigned char buf[SPX_DGST_BYTES]; + unsigned char *bufp = buf; + shaXstate state; + + shaX_inc_init(&state); + + // seed: SHA-X(R ‖ PK.seed ‖ PK.root ‖ M) + memcpy(inbuf, R, SPX_N); + memcpy(inbuf + SPX_N, pk, SPX_PK_BYTES); + + /* If R + pk + message cannot fill up an entire block */ + if (SPX_N + SPX_PK_BYTES + mlen < SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES) { + memcpy(inbuf + SPX_N + SPX_PK_BYTES, m, mlen); + shaX_inc_finalize(seed + 2 * SPX_N, &state, inbuf, SPX_N + SPX_PK_BYTES + mlen); + } + /* Otherwise first fill a block, so that finalize only uses the message */ + else { + memcpy(inbuf + SPX_N + SPX_PK_BYTES, m, + SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES - SPX_N - SPX_PK_BYTES); + shaX_inc_blocks(&state, inbuf, SPX_INBLOCKS); + + m += SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES - SPX_N - SPX_PK_BYTES; + mlen -= SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES - SPX_N - SPX_PK_BYTES; + shaX_inc_finalize(seed + 2 * SPX_N, &state, m, (size_t)mlen); + } + + // H_msg: MGF1-SHA-X(R ‖ PK.seed ‖ seed) + memcpy(seed, R, SPX_N); + memcpy(seed + SPX_N, pk, SPX_N); + + /* By doing this in two steps, we prevent hashing the message twice; + otherwise each iteration in MGF1 would hash the message again. */ + mgf1_X(bufp, SPX_DGST_BYTES, seed, 2 * SPX_N + SPX_SHAX_OUTPUT_BYTES); + + memcpy(digest, bufp, SPX_FORS_MSG_BYTES); + bufp += SPX_FORS_MSG_BYTES; + + + *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); + *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); + bufp += SPX_TREE_BYTES; + + *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); + *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); +} + + diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_clean/merkle.c b/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_clean/merkle.c new file mode 100644 index 0000000000..0c1479fd93 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_clean/merkle.c @@ -0,0 +1,59 @@ +#include +#include + +#include "address.h" +#include "merkle.h" +#include "params.h" +#include "utils.h" +#include "utilsx1.h" +#include "wots.h" +#include "wotsx1.h" + +/* + * This generates a Merkle signature (WOTS signature followed by the Merkle + * authentication path). This is in this file because most of the complexity + * is involved with the WOTS signature; the Merkle authentication path logic + * is mostly hidden in treehashx4 + */ +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf) { + unsigned char *auth_path = sig + SPX_WOTS_BYTES; + struct leaf_info_x1 info = { 0 }; + unsigned steps[ SPX_WOTS_LEN ]; + + info.wots_sig = sig; + chain_lengths(steps, root); + info.wots_steps = steps; + + set_type(&tree_addr[0], SPX_ADDR_TYPE_HASHTREE); + set_type(&info.pk_addr[0], SPX_ADDR_TYPE_WOTSPK); + copy_subtree_addr(&info.leaf_addr[0], wots_addr); + copy_subtree_addr(&info.pk_addr[0], wots_addr); + + info.wots_sign_leaf = idx_leaf; + + treehashx1(root, auth_path, ctx, + idx_leaf, 0, + SPX_TREE_HEIGHT, + wots_gen_leafx1, + tree_addr, &info); +} + +/* Compute root node of the top-most subtree. */ +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { + /* We do not need the auth path in key generation, but it simplifies the + code to have just one treehash routine that computes both root and path + in one function. */ + unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; + uint32_t top_tree_addr[8] = {0}; + uint32_t wots_addr[8] = {0}; + + set_layer_addr(top_tree_addr, SPX_D - 1); + set_layer_addr(wots_addr, SPX_D - 1); + + merkle_sign(auth_path, root, ctx, + wots_addr, top_tree_addr, + (uint32_t)~0 /* ~0 means "don't bother generating an auth path */ ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_clean/merkle.h b/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_clean/merkle.h new file mode 100644 index 0000000000..769cf2e970 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_clean/merkle.h @@ -0,0 +1,21 @@ +#ifndef MERKLE_H_ +#define MERKLE_H_ + +#include + +#include "context.h" +#include "params.h" + +/* Generate a Merkle signature (WOTS signature followed by the Merkle */ +/* authentication path) */ +#define merkle_sign SPX_NAMESPACE(merkle_sign) +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf); + +/* Compute the root node of the top-most subtree. */ +#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); + +#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_clean/nistapi.h b/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_clean/nistapi.h new file mode 100644 index 0000000000..3cb71afad4 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_clean/nistapi.h @@ -0,0 +1,87 @@ +#ifndef SPX_API_H +#define SPX_API_H + +#include +#include + +#include "params.h" + +#define CRYPTO_ALGNAME "SPHINCS+" + +#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES +#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES +#define CRYPTO_BYTES SPX_BYTES +#define CRYPTO_SEEDBYTES (3*SPX_N) + +/* + * Returns the length of a secret key, in bytes + */ +#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) +size_t crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) +size_t crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) +size_t crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) +size_t crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +#define crypto_sign SPX_NAMESPACE(crypto_sign) +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_clean/params.h b/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_clean/params.h new file mode 100644 index 0000000000..250162de05 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_clean/params.h @@ -0,0 +1,61 @@ +#ifndef SPX_PARAMS_H +#define SPX_PARAMS_H + +#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSSHA2128FSIMPLE_CLEAN_##s + +/* Hash output length in bytes. */ +#define SPX_N 16 +/* Height of the hypertree. */ +#define SPX_FULL_HEIGHT 66 +/* Number of subtree layer. */ +#define SPX_D 22 +/* FORS tree dimensions. */ +#define SPX_FORS_HEIGHT 6 +#define SPX_FORS_TREES 33 +/* Winternitz parameter, */ +#define SPX_WOTS_W 16 + +/* The hash function is defined by linking a different hash.c file, as opposed + to setting a #define constant. */ + +/* This is a SHA2-based parameter set, hence whether we use SHA-256 + * exclusively or we use both SHA-256 and SHA-512 is controlled by + * the following #define */ +#define SPX_SHA512 0 /* Use SHA-256 for all hashes */ + +/* For clarity */ +#define SPX_ADDR_BYTES 32 + +/* WOTS parameters. */ +#define SPX_WOTS_LOGW 4 + +#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) + +/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ +#define SPX_WOTS_LEN2 3 + +#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) +#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) +#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES + +/* Subtree size. */ +#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) + +//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT +// #error SPX_D should always divide SPX_FULL_HEIGHT +//#endif + +/* FORS parameters. */ +#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) +#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) +#define SPX_FORS_PK_BYTES SPX_N + +/* Resulting SPX sizes. */ +#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ + SPX_FULL_HEIGHT * SPX_N) +#define SPX_PK_BYTES (2 * SPX_N) +#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) + +#include "sha2_offsets.h" + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_clean/sha2_offsets.h b/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_clean/sha2_offsets.h new file mode 100644 index 0000000000..6e3584f7a4 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_clean/sha2_offsets.h @@ -0,0 +1,27 @@ +#ifndef SHA2_OFFSETS_H_ +#define SHA2_OFFSETS_H_ + +#define SPX_SHA256_BLOCK_BYTES 64 +#define SPX_SHA256_OUTPUT_BYTES 32 + +#define SPX_SHA512_BLOCK_BYTES 128 +#define SPX_SHA512_OUTPUT_BYTES 64 + +/* + * Offsets of various fields in the address structure when we use SHA2 as + * the Sphincs+ hash function + */ + +#define SPX_OFFSET_LAYER 0 /* The byte used to specify the Merkle tree layer */ +#define SPX_OFFSET_TREE 1 /* The start of the 8 byte field used to specify the tree */ +#define SPX_OFFSET_TYPE 9 /* The byte used to specify the hash type (reason) */ +#define SPX_OFFSET_KP_ADDR2 12 /* The high byte used to specify the key pair (which one-time signature) */ +#define SPX_OFFSET_KP_ADDR1 13 /* The low byte used to specify the key pair */ +#define SPX_OFFSET_CHAIN_ADDR 17 /* The byte used to specify the chain address (which Winternitz chain) */ +#define SPX_OFFSET_HASH_ADDR 21 /* The byte used to specify the hash address (where in the Winternitz chain) */ +#define SPX_OFFSET_TREE_HGT 17 /* The byte used to specify the height of this node in the FORS or Merkle tree */ +#define SPX_OFFSET_TREE_INDEX 18 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ + +#define SPX_SHA2 1 + +#endif /* SHA2_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_clean/sign.c b/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_clean/sign.c new file mode 100644 index 0000000000..9d0c7d1b22 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_clean/sign.c @@ -0,0 +1,286 @@ +#include +#include +#include + +#include "address.h" +#include "context.h" +#include "fors.h" +#include "hash.h" +#include "merkle.h" +#include "nistapi.h" +#include "params.h" +#include "randombytes.h" +#include "thash.h" +#include "utils.h" +#include "wots.h" + +/* + * Returns the length of a secret key, in bytes + */ +size_t crypto_sign_secretkeybytes(void) { + return CRYPTO_SECRETKEYBYTES; +} + +/* + * Returns the length of a public key, in bytes + */ +size_t crypto_sign_publickeybytes(void) { + return CRYPTO_PUBLICKEYBYTES; +} + +/* + * Returns the length of a signature, in bytes + */ +size_t crypto_sign_bytes(void) { + return CRYPTO_BYTES; +} + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +size_t crypto_sign_seedbytes(void) { + return CRYPTO_SEEDBYTES; +} + +/* + * Generates an SPX key pair given a seed of length + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [PUB_SEED || root] + */ +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed) { + spx_ctx ctx; + + /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ + memcpy(sk, seed, CRYPTO_SEEDBYTES); + + memcpy(pk, sk + 2 * SPX_N, SPX_N); + + memcpy(ctx.pub_seed, pk, SPX_N); + memcpy(ctx.sk_seed, sk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + /* Compute root node of the top-most subtree. */ + merkle_gen_root(sk + 3 * SPX_N, &ctx); + + // cleanup + free_hash_function(&ctx); + + memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); + + return 0; +} + +/* + * Generates an SPX key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [PUB_SEED || root] + */ +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { + uint8_t seed[CRYPTO_SEEDBYTES]; + randombytes(seed, CRYPTO_SEEDBYTES); + crypto_sign_seed_keypair(pk, sk, seed); + + return 0; +} + +/** + * Returns an array containing a detached signature. + */ +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk) { + spx_ctx ctx; + + const uint8_t *sk_prf = sk + SPX_N; + const uint8_t *pk = sk + 2 * SPX_N; + + uint8_t optrand[SPX_N]; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t root[SPX_N]; + uint32_t i; + uint64_t tree; + uint32_t idx_leaf; + uint32_t wots_addr[8] = {0}; + uint32_t tree_addr[8] = {0}; + + memcpy(ctx.sk_seed, sk, SPX_N); + memcpy(ctx.pub_seed, pk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + + /* Optionally, signing can be made non-deterministic using optrand. + This can help counter side-channel attacks that would benefit from + getting a large number of traces when the signer uses the same nodes. */ + randombytes(optrand, SPX_N); + /* Compute the digest randomization value. */ + gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); + + /* Derive the message digest and leaf index from R, PK and M. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; + + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); + + /* Sign the message hash using FORS. */ + fors_sign(sig, root, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); + sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; + + /* Update the indices for the next layer. */ + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; + } + + free_hash_function(&ctx); + + *siglen = SPX_BYTES; + + return 0; +} + +/** + * Verifies a detached signature and message under a given public key. + */ +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk) { + spx_ctx ctx; + const uint8_t *pub_root = pk + SPX_N; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t wots_pk[SPX_WOTS_BYTES]; + uint8_t root[SPX_N]; + uint8_t leaf[SPX_N]; + unsigned int i; + uint64_t tree; + uint32_t idx_leaf; + uint32_t wots_addr[8] = {0}; + uint32_t tree_addr[8] = {0}; + uint32_t wots_pk_addr[8] = {0}; + + if (siglen != SPX_BYTES) { + return -1; + } + + memcpy(ctx.pub_seed, pk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); + + /* Derive the message digest and leaf index from R || PK || M. */ + /* The additional SPX_N is a result of the hash domain separator. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; + + /* Layer correctly defaults to 0, so no need to set_layer_addr */ + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); + + fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + /* For each subtree.. */ + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + copy_keypair_addr(wots_pk_addr, wots_addr); + + /* The WOTS public key is only correct if the signature was correct. */ + /* Initially, root is the FORS pk, but on subsequent iterations it is + the root of the subtree below the currently processed subtree. */ + wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); + sig += SPX_WOTS_BYTES; + + /* Compute the leaf node using the WOTS public key. */ + thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); + + /* Compute the root node of this subtree. */ + compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, + &ctx, tree_addr); + sig += SPX_TREE_HEIGHT * SPX_N; + + /* Update the indices for the next layer. */ + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; + } + + // cleanup + free_hash_function(&ctx); + + /* Check if the root node equals the root node in the public key. */ + if (memcmp(root, pub_root, SPX_N) != 0) { + return -1; + } + + return 0; +} + + +/** + * Returns an array containing the signature followed by the message. + */ +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk) { + size_t siglen; + + crypto_sign_signature(sm, &siglen, m, mlen, sk); + + memmove(sm + SPX_BYTES, m, mlen); + *smlen = siglen + mlen; + + return 0; +} + +/** + * Verifies a given signature-message pair under a given public key. + */ +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk) { + /* The API caller does not necessarily know what size a signature should be + but SPHINCS+ signatures are always exactly SPX_BYTES. */ + if (smlen < SPX_BYTES) { + memset(m, 0, smlen); + *mlen = 0; + return -1; + } + + *mlen = smlen - SPX_BYTES; + + if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { + memset(m, 0, smlen); + *mlen = 0; + return -1; + } + + /* If verification was successful, move the message to the right place. */ + memmove(m, sm + SPX_BYTES, *mlen); + + return 0; +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_clean/thash.h b/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_clean/thash.h new file mode 100644 index 0000000000..8687ccfb4d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_clean/thash.h @@ -0,0 +1,13 @@ +#ifndef SPX_THASH_H +#define SPX_THASH_H + +#include "context.h" +#include "params.h" + +#include + +#define thash SPX_NAMESPACE(thash) +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_clean/thash_sha2_simple.c b/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_clean/thash_sha2_simple.c new file mode 100644 index 0000000000..197b4e7a0a --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_clean/thash_sha2_simple.c @@ -0,0 +1,32 @@ +#include +#include + +#include "thash.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "sha2.h" +#include "utils.h" + + +/** + * Takes an array of inblocks concatenated arrays of SPX_N bytes. + */ +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]) { + + unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES]; + sha256ctx sha2_state; + PQCLEAN_VLA(uint8_t, buf, SPX_SHA256_ADDR_BYTES + inblocks * SPX_N); + + /* Retrieve precomputed state containing pub_seed */ + sha256_inc_ctx_clone(&sha2_state, &ctx->state_seeded); + + memcpy(buf, addr, SPX_SHA256_ADDR_BYTES); + memcpy(buf + SPX_SHA256_ADDR_BYTES, in, inblocks * SPX_N); + + sha256_inc_finalize(outbuf, &sha2_state, buf, SPX_SHA256_ADDR_BYTES + inblocks * SPX_N); + memcpy(out, outbuf, SPX_N); +} + diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_clean/utils.c b/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_clean/utils.c new file mode 100644 index 0000000000..177b541fb9 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_clean/utils.c @@ -0,0 +1,148 @@ +#include + +#include "utils.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "thash.h" + +/** + * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. + */ +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in) { + int i; + + /* Iterate over out in decreasing order, for big-endianness. */ + for (i = (signed int)outlen - 1; i >= 0; i--) { + out[i] = in & 0xff; + in = in >> 8; + } +} + +void u32_to_bytes(unsigned char *out, uint32_t in) { + out[0] = (unsigned char)(in >> 24); + out[1] = (unsigned char)(in >> 16); + out[2] = (unsigned char)(in >> 8); + out[3] = (unsigned char)in; +} + +/** + * Converts the inlen bytes in 'in' from big-endian byte order to an integer. + */ +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { + unsigned long long retval = 0; + unsigned int i; + + for (i = 0; i < inlen; i++) { + retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); + } + return retval; +} + +/** + * Computes a root node given a leaf and an auth path. + * Expects address to be complete other than the tree_height and tree_index. + */ +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]) { + uint32_t i; + unsigned char buffer[2 * SPX_N]; + + /* If leaf_idx is odd (last bit = 1), current path element is a right child + and auth_path has to go left. Otherwise it is the other way around. */ + if (leaf_idx & 1) { + memcpy(buffer + SPX_N, leaf, SPX_N); + memcpy(buffer, auth_path, SPX_N); + } else { + memcpy(buffer, leaf, SPX_N); + memcpy(buffer + SPX_N, auth_path, SPX_N); + } + auth_path += SPX_N; + + for (i = 0; i < tree_height - 1; i++) { + leaf_idx >>= 1; + idx_offset >>= 1; + /* Set the address of the node we're creating. */ + set_tree_height(addr, i + 1); + set_tree_index(addr, leaf_idx + idx_offset); + + /* Pick the right or left neighbor, depending on parity of the node. */ + if (leaf_idx & 1) { + thash(buffer + SPX_N, buffer, 2, ctx, addr); + memcpy(buffer, auth_path, SPX_N); + } else { + thash(buffer, buffer, 2, ctx, addr); + memcpy(buffer + SPX_N, auth_path, SPX_N); + } + auth_path += SPX_N; + } + + /* The last iteration is exceptional; we do not copy an auth_path node. */ + leaf_idx >>= 1; + idx_offset >>= 1; + set_tree_height(addr, tree_height); + set_tree_index(addr, leaf_idx + idx_offset); + thash(root, buffer, 2, ctx, addr); +} + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx * /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]) { + PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); + PQCLEAN_VLA(unsigned int, heights, tree_height + 1); + unsigned int offset = 0; + uint32_t idx; + uint32_t tree_idx; + + for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { + /* Add the next leaf node to the stack. */ + gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); + offset++; + heights[offset - 1] = 0; + + /* If this is a node we need for the auth path.. */ + if ((leaf_idx ^ 0x1) == idx) { + memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); + } + + /* While the top-most nodes are of equal height.. */ + while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { + /* Compute index of the new node, in the next layer. */ + tree_idx = (idx >> (heights[offset - 1] + 1)); + + /* Set the address of the node we're creating. */ + set_tree_height(tree_addr, heights[offset - 1] + 1); + set_tree_index(tree_addr, + tree_idx + (idx_offset >> (heights[offset - 1] + 1))); + /* Hash the top-most nodes from the stack together. */ + thash(stack + (offset - 2)*SPX_N, + stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); + offset--; + /* Note that the top-most node is now one layer higher. */ + heights[offset - 1]++; + + /* If this is a node we need for the auth path.. */ + if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { + memcpy(auth_path + heights[offset - 1]*SPX_N, + stack + (offset - 1)*SPX_N, SPX_N); + } + } + } + memcpy(root, stack, SPX_N); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_clean/utils.h b/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_clean/utils.h new file mode 100644 index 0000000000..64f5d5a53a --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_clean/utils.h @@ -0,0 +1,58 @@ +#ifndef SPX_UTILS_H +#define SPX_UTILS_H + +#include + +#include "compat.h" +#include "context.h" +#include "params.h" + + +/* To support MSVC use alloca() instead of VLAs. See #20. */ + + +/** + * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. + */ +#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in); +#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) +void u32_to_bytes(unsigned char *out, uint32_t in); + +/** + * Converts the inlen bytes in 'in' from big-endian byte order to an integer. + */ +#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); + +/** + * Computes a root node given a leaf and an auth path. + * Expects address to be complete other than the tree_height and tree_index. + */ +#define compute_root SPX_NAMESPACE(compute_root) +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]); + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +#define treehash SPX_NAMESPACE(treehash) +void treehash(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx *ctx /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]); + + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_clean/utilsx1.c b/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_clean/utilsx1.c new file mode 100644 index 0000000000..fccb69b35d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_clean/utilsx1.c @@ -0,0 +1,100 @@ +#include + +#include "utilsx1.h" + +#include "address.h" +#include "params.h" +#include "thash.h" +#include "utils.h" + +/* + * Generate the entire Merkle tree, computing the authentication path for + * leaf_idx, and the resulting root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) + * + * This expects tree_addr to be initialized to the addr structures for the + * Merkle tree nodes + * + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + * + * This works by using the standard Merkle tree building algorithm, + */ +void treehashx1(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, + uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* Where to write the leaves */, + const spx_ctx * /* ctx */, + uint32_t idx, void *info), + uint32_t tree_addr[8], + void *info) { + /* This is where we keep the intermediate nodes */ + PQCLEAN_VLA(uint8_t, stack, tree_height * SPX_N); + + uint32_t idx; + uint32_t max_idx = (uint32_t)((1 << tree_height) - 1); + for (idx = 0;; idx++) { + unsigned char current[2 * SPX_N]; /* Current logical node is at */ + /* index[SPX_N]. We do this to minimize the number of copies */ + /* needed during a thash */ + gen_leaf( ¤t[SPX_N], ctx, idx + idx_offset, + info ); + + /* Now combine the freshly generated right node with previously */ + /* generated left ones */ + uint32_t internal_idx_offset = idx_offset; + uint32_t internal_idx = idx; + uint32_t internal_leaf = leaf_idx; + uint32_t h; /* The height we are in the Merkle tree */ + for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { + + /* Check if we hit the top of the tree */ + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[SPX_N], SPX_N ); + return; + } + + /* + * Check if the node we have is a part of the + * authentication path; if it is, write it out + */ + if ((internal_idx ^ internal_leaf) == 0x01) { + memcpy( &auth_path[ h * SPX_N ], + ¤t[SPX_N], + SPX_N ); + } + + /* + * Check if we're at a left child; if so, stop going up the stack + * Exception: if we've reached the end of the tree, keep on going + * (so we combine the last 4 nodes into the one root node in two + * more iterations) + */ + if ((internal_idx & 1) == 0 && idx < max_idx) { + break; + } + + /* Ok, we're at a right node */ + /* Now combine the left and right logical nodes together */ + + /* Set the address of the node we're creating. */ + internal_idx_offset >>= 1; + set_tree_height(tree_addr, h + 1); + set_tree_index(tree_addr, internal_idx / 2 + internal_idx_offset ); + + unsigned char *left = &stack[h * SPX_N]; + memcpy( ¤t[0], left, SPX_N ); + thash( ¤t[1 * SPX_N], + ¤t[0 * SPX_N], + 2, ctx, tree_addr); + } + + /* We've hit a left child; save the current for when we get the */ + /* corresponding right right */ + memcpy( &stack[h * SPX_N], ¤t[SPX_N], SPX_N); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_clean/utilsx1.h b/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_clean/utilsx1.h new file mode 100644 index 0000000000..e911d17d53 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_clean/utilsx1.h @@ -0,0 +1,27 @@ +#ifndef SPX_UTILSX4_H +#define SPX_UTILSX4_H + +#include + +#include "context.h" +#include "params.h" + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +#define treehashx1 SPX_NAMESPACE(treehashx1) +void treehashx1(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* Where to write the leaf */, + const spx_ctx * /* ctx */, + uint32_t addr_idx, void *info), + uint32_t tree_addrx4[8], void *info); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_clean/wots.c b/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_clean/wots.c new file mode 100644 index 0000000000..249717aaa8 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_clean/wots.c @@ -0,0 +1,108 @@ +#include +#include + +#include "wots.h" +#include "wotsx1.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "thash.h" +#include "utils.h" +#include "utilsx1.h" + +// TODO clarify address expectations, and make them more uniform. +// TODO i.e. do we expect types to be set already? +// TODO and do we expect modifications or copies? + +/** + * Computes the chaining function. + * out and in have to be n-byte arrays. + * + * Interprets in as start-th value of the chain. + * addr has to contain the address of the chain. + */ +static void gen_chain(unsigned char *out, const unsigned char *in, + unsigned int start, unsigned int steps, + const spx_ctx *ctx, uint32_t addr[8]) { + uint32_t i; + + /* Initialize out with the value at position 'start'. */ + memcpy(out, in, SPX_N); + + /* Iterate 'steps' calls to the hash function. */ + for (i = start; i < (start + steps) && i < SPX_WOTS_W; i++) { + set_hash_addr(addr, i); + thash(out, out, 1, ctx, addr); + } +} + +/** + * base_w algorithm as described in draft. + * Interprets an array of bytes as integers in base w. + * This only works when log_w is a divisor of 8. + */ +static void base_w(unsigned int *output, const int out_len, + const unsigned char *input) { + int in = 0; + int out = 0; + unsigned char total = 0; + int bits = 0; + int consumed; + + for (consumed = 0; consumed < out_len; consumed++) { + if (bits == 0) { + total = input[in]; + in++; + bits += 8; + } + bits -= SPX_WOTS_LOGW; + output[out] = (total >> bits) & (SPX_WOTS_W - 1); + out++; + } +} + +/* Computes the WOTS+ checksum over a message (in base_w). */ +static void wots_checksum(unsigned int *csum_base_w, + const unsigned int *msg_base_w) { + unsigned int csum = 0; + unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; + unsigned int i; + + /* Compute checksum. */ + for (i = 0; i < SPX_WOTS_LEN1; i++) { + csum += SPX_WOTS_W - 1 - msg_base_w[i]; + } + + /* Convert checksum to base_w. */ + /* Make sure expected empty zero bits are the least significant bits. */ + csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); + ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); + base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); +} + +/* Takes a message and derives the matching chain lengths. */ +void chain_lengths(unsigned int *lengths, const unsigned char *msg) { + base_w(lengths, SPX_WOTS_LEN1, msg); + wots_checksum(lengths + SPX_WOTS_LEN1, lengths); +} + +/** + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. + * + * Writes the computed public key to 'pk'. + */ +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]) { + unsigned int lengths[SPX_WOTS_LEN]; + uint32_t i; + + chain_lengths(lengths, msg); + + for (i = 0; i < SPX_WOTS_LEN; i++) { + set_chain_addr(addr, i); + gen_chain(pk + i * SPX_N, sig + i * SPX_N, + lengths[i], SPX_WOTS_W - 1 - lengths[i], ctx, addr); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_clean/wots.h b/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_clean/wots.h new file mode 100644 index 0000000000..4e7692eeef --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_clean/wots.h @@ -0,0 +1,25 @@ +#ifndef SPX_WOTS_H +#define SPX_WOTS_H + +#include + +#include "context.h" +#include "params.h" + +/** + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. + * + * Writes the computed public key to 'pk'. + */ +#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]); + +/* + * Compute the chain lengths needed for a given message hash + */ +#define chain_lengths SPX_NAMESPACE(chain_lengths) +void chain_lengths(unsigned int *lengths, const unsigned char *msg); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_clean/wotsx1.c b/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_clean/wotsx1.c new file mode 100644 index 0000000000..3adec78dfb --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_clean/wotsx1.c @@ -0,0 +1,76 @@ +#include +#include + +#include "wots.h" +#include "wotsx1.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "thash.h" +#include "utils.h" + +/* + * This generates a WOTS public key + * It also generates the WOTS signature if leaf_info indicates + * that we're signing with this WOTS key + */ +void wots_gen_leafx1(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info) { + struct leaf_info_x1 *info = v_info; + uint32_t *leaf_addr = info->leaf_addr; + uint32_t *pk_addr = info->pk_addr; + unsigned int i, k; + unsigned char pk_buffer[ SPX_WOTS_BYTES ]; + unsigned char *buffer; + uint32_t wots_k_mask; + + if (leaf_idx == info->wots_sign_leaf) { + /* We're traversing the leaf that's signing; generate the WOTS */ + /* signature */ + wots_k_mask = 0; + } else { + /* Nope, we're just generating pk's; turn off the signature logic */ + wots_k_mask = (uint32_t)~0; + } + + set_keypair_addr( leaf_addr, leaf_idx ); + set_keypair_addr( pk_addr, leaf_idx ); + + for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { + uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k to */ + /* the step if we're generating a signature, ~0 if we're not */ + + /* Start with the secret seed */ + set_chain_addr(leaf_addr, i); + set_hash_addr(leaf_addr, 0); + set_type(leaf_addr, SPX_ADDR_TYPE_WOTSPRF); + + prf_addr(buffer, ctx, leaf_addr); + + set_type(leaf_addr, SPX_ADDR_TYPE_WOTS); + + /* Iterate down the WOTS chain */ + for (k = 0;; k++) { + /* Check if this is the value that needs to be saved as a */ + /* part of the WOTS signature */ + if (k == wots_k) { + memcpy( info->wots_sig + i * SPX_N, buffer, SPX_N ); + } + + /* Check if we hit the top of the chain */ + if (k == SPX_WOTS_W - 1) { + break; + } + + /* Iterate one step on the chain */ + set_hash_addr(leaf_addr, k); + + thash(buffer, buffer, 1, ctx, leaf_addr); + } + } + + /* Do the final thash to generate the public keys */ + thash(dest, pk_buffer, SPX_WOTS_LEN, ctx, pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_clean/wotsx1.h b/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_clean/wotsx1.h new file mode 100644 index 0000000000..e617929f96 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128f-simple_clean/wotsx1.h @@ -0,0 +1,39 @@ +#ifndef WOTSX1_H_ +#define WOTSX1_H_ + +#include + +#include "context.h" +#include "params.h" + +/* + * This is here to provide an interface to the internal wots_gen_leafx1 + * routine. While this routine is not referenced in the package outside of + * wots.c, it is called from the stand-alone benchmark code to characterize + * the performance + */ +struct leaf_info_x1 { + unsigned char *wots_sig; + uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ + uint32_t *wots_steps; + uint32_t leaf_addr[8]; + uint32_t pk_addr[8]; +}; + +/* Macro to set the leaf_info to something 'benign', that is, it would */ +/* run with the same time as it does during the real signing process */ +/* Used only by the benchmark code */ +#define INITIALIZE_LEAF_INFO_X1(info, addr, step_buffer) { \ + (info).wots_sig = 0; \ + (info).wots_sign_leaf = ~0; \ + (info).wots_steps = step_buffer; \ + memcpy( &(info).leaf_addr[0], (addr), 32 ); \ + memcpy( &(info).pk_addr[0], (addr), 32 ); \ + } + +#define wots_gen_leafx1 SPX_NAMESPACE(wots_gen_leafx1) +void wots_gen_leafx1(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info); + +#endif /* WOTSX1_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/LICENSE b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/LICENSE new file mode 100644 index 0000000000..670154e353 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/LICENSE @@ -0,0 +1,116 @@ +CC0 1.0 Universal + +Statement of Purpose + +The laws of most jurisdictions throughout the world automatically confer +exclusive Copyright and Related Rights (defined below) upon the creator and +subsequent owner(s) (each and all, an "owner") of an original work of +authorship and/or a database (each, a "Work"). + +Certain owners wish to permanently relinquish those rights to a Work for the +purpose of contributing to a commons of creative, cultural and scientific +works ("Commons") that the public can reliably and without fear of later +claims of infringement build upon, modify, incorporate in other works, reuse +and redistribute as freely as possible in any form whatsoever and for any +purposes, including without limitation commercial purposes. These owners may +contribute to the Commons to promote the ideal of a free culture and the +further production of creative, cultural and scientific works, or to gain +reputation or greater distribution for their Work in part through the use and +efforts of others. + +For these and/or other purposes and motivations, and without any expectation +of additional consideration or compensation, the person associating CC0 with a +Work (the "Affirmer"), to the extent that he or she is an owner of Copyright +and Related Rights in the Work, voluntarily elects to apply CC0 to the Work +and publicly distribute the Work under its terms, with knowledge of his or her +Copyright and Related Rights in the Work and the meaning and intended legal +effect of CC0 on those rights. + +1. Copyright and Related Rights. A Work made available under CC0 may be +protected by copyright and related or neighboring rights ("Copyright and +Related Rights"). Copyright and Related Rights include, but are not limited +to, the following: + + i. the right to reproduce, adapt, distribute, perform, display, communicate, + and translate a Work; + + ii. moral rights retained by the original author(s) and/or performer(s); + + iii. publicity and privacy rights pertaining to a person's image or likeness + depicted in a Work; + + iv. rights protecting against unfair competition in regards to a Work, + subject to the limitations in paragraph 4(a), below; + + v. rights protecting the extraction, dissemination, use and reuse of data in + a Work; + + vi. database rights (such as those arising under Directive 96/9/EC of the + European Parliament and of the Council of 11 March 1996 on the legal + protection of databases, and under any national implementation thereof, + including any amended or successor version of such directive); and + + vii. other similar, equivalent or corresponding rights throughout the world + based on applicable law or treaty, and any national implementations thereof. + +2. Waiver. To the greatest extent permitted by, but not in contravention of, +applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and +unconditionally waives, abandons, and surrenders all of Affirmer's Copyright +and Related Rights and associated claims and causes of action, whether now +known or unknown (including existing as well as future claims and causes of +action), in the Work (i) in all territories worldwide, (ii) for the maximum +duration provided by applicable law or treaty (including future time +extensions), (iii) in any current or future medium and for any number of +copies, and (iv) for any purpose whatsoever, including without limitation +commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes +the Waiver for the benefit of each member of the public at large and to the +detriment of Affirmer's heirs and successors, fully intending that such Waiver +shall not be subject to revocation, rescission, cancellation, termination, or +any other legal or equitable action to disrupt the quiet enjoyment of the Work +by the public as contemplated by Affirmer's express Statement of Purpose. + +3. Public License Fallback. Should any part of the Waiver for any reason be +judged legally invalid or ineffective under applicable law, then the Waiver +shall be preserved to the maximum extent permitted taking into account +Affirmer's express Statement of Purpose. In addition, to the extent the Waiver +is so judged Affirmer hereby grants to each affected person a royalty-free, +non transferable, non sublicensable, non exclusive, irrevocable and +unconditional license to exercise Affirmer's Copyright and Related Rights in +the Work (i) in all territories worldwide, (ii) for the maximum duration +provided by applicable law or treaty (including future time extensions), (iii) +in any current or future medium and for any number of copies, and (iv) for any +purpose whatsoever, including without limitation commercial, advertising or +promotional purposes (the "License"). The License shall be deemed effective as +of the date CC0 was applied by Affirmer to the Work. Should any part of the +License for any reason be judged legally invalid or ineffective under +applicable law, such partial invalidity or ineffectiveness shall not +invalidate the remainder of the License, and in such case Affirmer hereby +affirms that he or she will not (i) exercise any of his or her remaining +Copyright and Related Rights in the Work or (ii) assert any associated claims +and causes of action with respect to the Work, in either case contrary to +Affirmer's express Statement of Purpose. + +4. Limitations and Disclaimers. + + a. No trademark or patent rights held by Affirmer are waived, abandoned, + surrendered, licensed or otherwise affected by this document. + + b. Affirmer offers the Work as-is and makes no representations or warranties + of any kind concerning the Work, express, implied, statutory or otherwise, + including without limitation warranties of title, merchantability, fitness + for a particular purpose, non infringement, or the absence of latent or + other defects, accuracy, or the present or absence of errors, whether or not + discoverable, all to the greatest extent permissible under applicable law. + + c. Affirmer disclaims responsibility for clearing rights of other persons + that may apply to the Work or any use thereof, including without limitation + any person's Copyright and Related Rights in the Work. Further, Affirmer + disclaims responsibility for obtaining any necessary consents, permissions + or other rights required for any use of the Work. + + d. Affirmer understands and acknowledges that Creative Commons is not a + party to this document and has no duty or obligation with respect to this + CC0 or use of the Work. + +For more information, please see + diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/address.c b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/address.c new file mode 100644 index 0000000000..d49d9f3b6b --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/address.c @@ -0,0 +1,95 @@ +#include +#include + +#include "address.h" +#include "params.h" +#include "utils.h" + +/* + * Specify which level of Merkle tree (the "layer") we're working on + */ +void set_layer_addr(uint32_t addr[8], uint32_t layer) { + ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; +} + +/* + * Specify which Merkle tree within the level (the "tree address") we're working on + */ +void set_tree_addr(uint32_t addr[8], uint64_t tree) { + ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); +} + +/* + * Specify the reason we'll use this address structure for, that is, what + * hash will we compute with it. This is used so that unrelated types of + * hashes don't accidentally get the same address structure. The type will be + * one of the SPX_ADDR_TYPE constants + */ +void set_type(uint32_t addr[8], uint32_t type) { + ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; +} + +/* + * Copy the layer and tree fields of the address structure. This is used + * when we're doing multiple types of hashes within the same Merkle tree + */ +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); +} + +/* These functions are used for OTS addresses. */ + +/* + * Specify which Merkle leaf we're working on; that is, which OTS keypair + * we're talking about. + */ +void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { + /* We have > 256 OTS at the bottom of the Merkle tree; to specify */ + /* which one, we'd need to express it in two bytes */ + ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR2] = (unsigned char)(keypair >> 8); + ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; +} + +/* + * Copy the layer, tree and keypair fields of the address structure. This is + * used when we're doing multiple things within the same OTS keypair + */ +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); + ((unsigned char *)out)[SPX_OFFSET_KP_ADDR2] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR2]; + ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; +} + +/* + * Specify which Merkle chain within the OTS we're working with + * (the chain address) + */ +void set_chain_addr(uint32_t addr[8], uint32_t chain) { + ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; +} + +/* + * Specify where in the Merkle chain we are +* (the hash address) + */ +void set_hash_addr(uint32_t addr[8], uint32_t hash) { + ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; +} + +/* These functions are used for all hash tree addresses (including FORS). */ + +/* + * Specify the height of the node in the Merkle/FORS tree we are in + * (the tree height) + */ +void set_tree_height(uint32_t addr[8], uint32_t tree_height) { + ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; +} + +/* + * Specify the distance from the left edge of the node in the Merkle/FORS tree + * (the tree index) + */ +void set_tree_index(uint32_t addr[8], uint32_t tree_index) { + u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/address.h b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/address.h new file mode 100644 index 0000000000..24a84eb40c --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/address.h @@ -0,0 +1,52 @@ +#ifndef SPX_ADDRESS_H +#define SPX_ADDRESS_H + +#include + +#include "params.h" + +/* The hash types that are passed to set_type */ +#define SPX_ADDR_TYPE_WOTS 0 +#define SPX_ADDR_TYPE_WOTSPK 1 +#define SPX_ADDR_TYPE_HASHTREE 2 +#define SPX_ADDR_TYPE_FORSTREE 3 +#define SPX_ADDR_TYPE_FORSPK 4 +#define SPX_ADDR_TYPE_WOTSPRF 5 +#define SPX_ADDR_TYPE_FORSPRF 6 + +#define set_layer_addr SPX_NAMESPACE(set_layer_addr) +void set_layer_addr(uint32_t addr[8], uint32_t layer); + +#define set_tree_addr SPX_NAMESPACE(set_tree_addr) +void set_tree_addr(uint32_t addr[8], uint64_t tree); + +#define set_type SPX_NAMESPACE(set_type) +void set_type(uint32_t addr[8], uint32_t type); + +/* Copies the layer and tree part of one address into the other */ +#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); + +/* These functions are used for WOTS and FORS addresses. */ + +#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) +void set_keypair_addr(uint32_t addr[8], uint32_t keypair); + +#define set_chain_addr SPX_NAMESPACE(set_chain_addr) +void set_chain_addr(uint32_t addr[8], uint32_t chain); + +#define set_hash_addr SPX_NAMESPACE(set_hash_addr) +void set_hash_addr(uint32_t addr[8], uint32_t hash); + +#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); + +/* These functions are used for all hash tree addresses (including FORS). */ + +#define set_tree_height SPX_NAMESPACE(set_tree_height) +void set_tree_height(uint32_t addr[8], uint32_t tree_height); + +#define set_tree_index SPX_NAMESPACE(set_tree_index) +void set_tree_index(uint32_t addr[8], uint32_t tree_index); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/api.h b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/api.h new file mode 100644 index 0000000000..a65994d064 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/api.h @@ -0,0 +1,77 @@ +#ifndef PQCLEAN_SPHINCSSHA2128SROBUST_AVX2_API_H +#define PQCLEAN_SPHINCSSHA2128SROBUST_AVX2_API_H + +#include +#include + +#define PQCLEAN_SPHINCSSHA2128SROBUST_AVX2_CRYPTO_ALGNAME "SPHINCS+-sha2-128s-robust" + +#define PQCLEAN_SPHINCSSHA2128SROBUST_AVX2_CRYPTO_SECRETKEYBYTES 64 +#define PQCLEAN_SPHINCSSHA2128SROBUST_AVX2_CRYPTO_PUBLICKEYBYTES 32 +#define PQCLEAN_SPHINCSSHA2128SROBUST_AVX2_CRYPTO_BYTES 7856 + +#define PQCLEAN_SPHINCSSHA2128SROBUST_AVX2_CRYPTO_SEEDBYTES 48 + +/* + * Returns the length of a secret key, in bytes + */ +size_t PQCLEAN_SPHINCSSHA2128SROBUST_AVX2_crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +size_t PQCLEAN_SPHINCSSHA2128SROBUST_AVX2_crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +size_t PQCLEAN_SPHINCSSHA2128SROBUST_AVX2_crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +size_t PQCLEAN_SPHINCSSHA2128SROBUST_AVX2_crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +int PQCLEAN_SPHINCSSHA2128SROBUST_AVX2_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +int PQCLEAN_SPHINCSSHA2128SROBUST_AVX2_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +int PQCLEAN_SPHINCSSHA2128SROBUST_AVX2_crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +int PQCLEAN_SPHINCSSHA2128SROBUST_AVX2_crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, + const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +int PQCLEAN_SPHINCSSHA2128SROBUST_AVX2_crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +int PQCLEAN_SPHINCSSHA2128SROBUST_AVX2_crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/context.h b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/context.h new file mode 100644 index 0000000000..200d3c0fb1 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/context.h @@ -0,0 +1,26 @@ +#ifndef SPX_CONTEXT_H +#define SPX_CONTEXT_H + +#include + +#include "params.h" +#include "sha2.h" +#include "sha256avx.h" + +// funky ordering due to optimal padding +typedef struct { + sha256x8ctx statex8_seeded; + sha256ctx state_seeded; + + uint8_t pub_seed[SPX_N]; + uint8_t sk_seed[SPX_N]; +} spx_ctx; + + +#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) +void initialize_hash_function(spx_ctx *ctx); + +#define free_hash_function SPX_NAMESPACE(free_hash_function) +void free_hash_function(spx_ctx *ctx); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/context_sha2.c b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/context_sha2.c new file mode 100644 index 0000000000..073af8dd15 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/context_sha2.c @@ -0,0 +1,44 @@ +#include + +#include "context.h" + +/** + * Absorb the constant pub_seed using one round of the compression function + * This initializes state_seeded and state_seeded_512, which can then be + * reused in thash + **/ +static void seed_state(spx_ctx *ctx) { + uint8_t block[SPX_SHA512_BLOCK_BYTES]; + size_t i; + + for (i = 0; i < SPX_N; ++i) { + block[i] = ctx->pub_seed[i]; + } + for (i = SPX_N; i < SPX_SHA512_BLOCK_BYTES; ++i) { + block[i] = 0; + } + /* block has been properly initialized for both SHA-256 and SHA-512 */ + + sha256_inc_init(&ctx->state_seeded); + sha256_inc_blocks(&ctx->state_seeded, block, 1); + + // initialize x8 + sha256_init8x(&ctx->statex8_seeded); + sha256_transform8x(&ctx->statex8_seeded, + block, block, block, block, block, block, block, block); + + ctx->statex8_seeded.datalen = 0; + ctx->statex8_seeded.msglen = 512; + +} + + +/* For SHA, we initialize the hash function at the start */ +void initialize_hash_function(spx_ctx *ctx) { + seed_state(ctx); +} + +/* Free the incremental hashing context for heap-based SHA2 APIs */ +void free_hash_function(spx_ctx *ctx) { + sha256_inc_ctx_release(&ctx->state_seeded); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/fors.c b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/fors.c new file mode 100644 index 0000000000..4cab8e7415 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/fors.c @@ -0,0 +1,226 @@ +#include +#include +#include + +#include "fors.h" + + +#include "address.h" +#include "hash.h" +#include "hashx8.h" +#include "thash.h" +#include "thashx8.h" +#include "utils.h" +#include "utilsx8.h" +static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + prf_addr(sk, ctx, fors_leaf_addr); +} + +static void fors_gen_skx8(unsigned char *sk0, + unsigned char *sk1, + unsigned char *sk2, + unsigned char *sk3, + unsigned char *sk4, + unsigned char *sk5, + unsigned char *sk6, + unsigned char *sk7, const spx_ctx *ctx, + uint32_t fors_leaf_addrx8[8 * 8]) { + prf_addrx8(sk0, sk1, sk2, sk3, sk4, sk5, sk6, sk7, + ctx, fors_leaf_addrx8); +} + +static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, + const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + thash(leaf, sk, 1, ctx, fors_leaf_addr); +} + +static void fors_sk_to_leafx8(unsigned char *leaf0, + unsigned char *leaf1, + unsigned char *leaf2, + unsigned char *leaf3, + unsigned char *leaf4, + unsigned char *leaf5, + unsigned char *leaf6, + unsigned char *leaf7, + const unsigned char *sk0, + const unsigned char *sk1, + const unsigned char *sk2, + const unsigned char *sk3, + const unsigned char *sk4, + const unsigned char *sk5, + const unsigned char *sk6, + const unsigned char *sk7, + const spx_ctx *ctx, + uint32_t fors_leaf_addrx8[8 * 8]) { + thashx8(leaf0, leaf1, leaf2, leaf3, leaf4, leaf5, leaf6, leaf7, + sk0, sk1, sk2, sk3, sk4, sk5, sk6, sk7, + 1, ctx, fors_leaf_addrx8); +} + +struct fors_gen_leaf_info { + uint32_t leaf_addrx[8 * 8]; +}; + +static void fors_gen_leafx8(unsigned char *leaf, + const spx_ctx *ctx, + uint32_t addr_idx, void *info) { + struct fors_gen_leaf_info *fors_info = info; + uint32_t *fors_leaf_addrx8 = fors_info->leaf_addrx; + unsigned int j; + + /* Only set the parts that the caller doesn't set */ + for (j = 0; j < 8; j++) { + set_tree_index(fors_leaf_addrx8 + j * 8, addr_idx + j); + set_type(fors_leaf_addrx8 + j * 8, SPX_ADDR_TYPE_FORSPRF); + } + + fors_gen_skx8(leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + leaf + 2 * SPX_N, + leaf + 3 * SPX_N, + leaf + 4 * SPX_N, + leaf + 5 * SPX_N, + leaf + 6 * SPX_N, + leaf + 7 * SPX_N, + ctx, fors_leaf_addrx8); + + for (j = 0; j < 8; j++) { + set_type(fors_leaf_addrx8 + j * 8, SPX_ADDR_TYPE_FORSTREE); + } + + fors_sk_to_leafx8(leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + leaf + 2 * SPX_N, + leaf + 3 * SPX_N, + leaf + 4 * SPX_N, + leaf + 5 * SPX_N, + leaf + 6 * SPX_N, + leaf + 7 * SPX_N, + leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + leaf + 2 * SPX_N, + leaf + 3 * SPX_N, + leaf + 4 * SPX_N, + leaf + 5 * SPX_N, + leaf + 6 * SPX_N, + leaf + 7 * SPX_N, + ctx, fors_leaf_addrx8); +} + +/** + * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + * Assumes indices has space for SPX_FORS_TREES integers. + */ +static void message_to_indices(uint32_t *indices, const unsigned char *m) { + unsigned int i, j; + unsigned int offset = 0; + + for (i = 0; i < SPX_FORS_TREES; i++) { + indices[i] = 0; + for (j = 0; j < SPX_FORS_HEIGHT; j++) { + indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); + offset++; + } + } +} + +/** + * Signs a message m, deriving the secret key from sk_seed and the FTS address. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + uint32_t fors_tree_addr[8 * 8] = {0}; + struct fors_gen_leaf_info fors_info = {0}; + uint32_t *fors_leaf_addr = fors_info.leaf_addrx; + uint32_t fors_pk_addr[8] = {0}; + uint32_t idx_offset; + unsigned int i; + + for (i = 0; i < 8; i++) { + copy_keypair_addr(fors_tree_addr + 8 * i, fors_addr); + set_type(fors_tree_addr + 8 * i, SPX_ADDR_TYPE_FORSTREE); + copy_keypair_addr(fors_leaf_addr + 8 * i, fors_addr); + } + copy_keypair_addr(fors_pk_addr, fors_addr); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); + + message_to_indices(indices, m); + + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); + + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + + /* Include the secret key part that produces the selected leaf node. */ + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); + fors_gen_sk(sig, ctx, fors_tree_addr); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + sig += SPX_N; + + /* Compute the authentication path for this leaf node. */ + treehashx8(roots + i * SPX_N, sig, ctx, + indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx8, + fors_tree_addr, &fors_info); + + sig += SPX_N * SPX_FORS_HEIGHT; + } + + /* Hash horizontally across all tree roots to derive the public key. */ + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); +} + +/** + * Derives the FORS public key from a signature. + * This can be used for verification by comparing to a known public key, or to + * subsequently verify a signature on the derived public key. The latter is the + * typical use-case when used as an FTS below an OTS in a hypertree. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + unsigned char leaf[SPX_N]; + uint32_t fors_tree_addr[8] = {0}; + uint32_t fors_pk_addr[8] = {0}; + uint32_t idx_offset; + unsigned int i; + + copy_keypair_addr(fors_tree_addr, fors_addr); + copy_keypair_addr(fors_pk_addr, fors_addr); + + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); + + message_to_indices(indices, m); + + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); + + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + + /* Derive the leaf from the included secret key part. */ + fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); + sig += SPX_N; + + /* Derive the corresponding root node of this tree. */ + compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, + sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); + sig += SPX_N * SPX_FORS_HEIGHT; + } + + /* Hash horizontally across all tree roots to derive the public key. */ + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/fors.h b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/fors.h new file mode 100644 index 0000000000..509140a178 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/fors.h @@ -0,0 +1,32 @@ +#ifndef SPX_FORS_H +#define SPX_FORS_H + +#include + +#include "context.h" +#include "params.h" + +/** + * Signs a message m, deriving the secret key from sk_seed and the FTS address. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +#define fors_sign SPX_NAMESPACE(fors_sign) +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); + +/** + * Derives the FORS public key from a signature. + * This can be used for verification by comparing to a known public key, or to + * subsequently verify a signature on the derived public key. The latter is the + * typical use-case when used as an FTS below an OTS in a hypertree. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/hash.h b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/hash.h new file mode 100644 index 0000000000..ffe815f45d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/hash.h @@ -0,0 +1,37 @@ +#ifndef SPX_HASH_H +#define SPX_HASH_H + +#include +#include + +#include "context.h" +#include "params.h" + +#define prf_addr SPX_NAMESPACE(prf_addr) +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]); + +#define gen_message_random SPX_NAMESPACE(gen_message_random) +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); + +#define hash_message SPX_NAMESPACE(hash_message) +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); + + +# define SPX_SHA256_ADDR_BYTES 22 + +# define mgf1_256 SPX_NAMESPACE(mgf1_256) +void mgf1_256(unsigned char *out, unsigned long outlen, + const unsigned char *in, unsigned long inlen); + +# define mgf1_512 SPX_NAMESPACE(mgf1_512) +void mgf1_512(unsigned char *out, unsigned long outlen, + const unsigned char *in, unsigned long inlen); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/hash_sha2.c b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/hash_sha2.c new file mode 100644 index 0000000000..69f0dc0013 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/hash_sha2.c @@ -0,0 +1,219 @@ +#include +#include + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "sha2.h" +#include "utils.h" + + + +#define SPX_SHAX_OUTPUT_BYTES SPX_SHA256_OUTPUT_BYTES +#define SPX_SHAX_BLOCK_BYTES SPX_SHA256_BLOCK_BYTES +#define shaX_inc_init sha256_inc_init +#define shaX_inc_blocks sha256_inc_blocks +#define shaX_inc_finalize sha256_inc_finalize +#define shaX sha256 +#define mgf1_X mgf1_256 +#define shaXstate sha256ctx + +/** + * mgf1 function based on the SHA-256 hash function + * Note that inlen should be sufficiently small that it still allows for + * an array to be allocated on the stack. Typically 'in' is merely a seed. + * Outputs outlen number of bytes + */ +void mgf1_256(unsigned char *out, unsigned long outlen, + const unsigned char *in, unsigned long inlen) { + PQCLEAN_VLA(uint8_t, inbuf, inlen + 4); + unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES]; + uint32_t i; + + memcpy(inbuf, in, inlen); + + /* While we can fit in at least another full block of SHA256 output.. */ + for (i = 0; (i + 1)*SPX_SHA256_OUTPUT_BYTES <= outlen; i++) { + u32_to_bytes(inbuf + inlen, i); + sha256(out, inbuf, inlen + 4); + out += SPX_SHA256_OUTPUT_BYTES; + } + /* Until we cannot anymore, and we fill the remainder. */ + if (outlen > i * SPX_SHA256_OUTPUT_BYTES) { + u32_to_bytes(inbuf + inlen, i); + sha256(outbuf, inbuf, inlen + 4); + memcpy(out, outbuf, outlen - i * SPX_SHA256_OUTPUT_BYTES); + } +} + +/* + * mgf1 function based on the SHA-512 hash function + */ +void mgf1_512(unsigned char *out, unsigned long outlen, + const unsigned char *in, unsigned long inlen) { + PQCLEAN_VLA(uint8_t, inbuf, inlen + 4); + unsigned char outbuf[SPX_SHA512_OUTPUT_BYTES]; + uint32_t i; + + memcpy(inbuf, in, inlen); + + /* While we can fit in at least another full block of SHA512 output.. */ + for (i = 0; (i + 1)*SPX_SHA512_OUTPUT_BYTES <= outlen; i++) { + u32_to_bytes(inbuf + inlen, i); + sha512(out, inbuf, inlen + 4); + out += SPX_SHA512_OUTPUT_BYTES; + } + /* Until we cannot anymore, and we fill the remainder. */ + if (outlen > i * SPX_SHA512_OUTPUT_BYTES) { + u32_to_bytes(inbuf + inlen, i); + sha512(outbuf, inbuf, inlen + 4); + memcpy(out, outbuf, outlen - i * SPX_SHA512_OUTPUT_BYTES); + } +} + +/* + * Computes PRF(pk_seed, sk_seed, addr). + */ +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]) { + sha256ctx sha2_state; + unsigned char buf[SPX_SHA256_ADDR_BYTES + SPX_N]; + unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES]; + + /* Retrieve precomputed state containing pub_seed */ + sha256_inc_ctx_clone(&sha2_state, &ctx->state_seeded); + + /* Remainder: ADDR^c ‖ SK.seed */ + memcpy(buf, addr, SPX_SHA256_ADDR_BYTES); + memcpy(buf + SPX_SHA256_ADDR_BYTES, ctx->sk_seed, SPX_N); + + sha256_inc_finalize(outbuf, &sha2_state, buf, SPX_SHA256_ADDR_BYTES + SPX_N); + + memcpy(out, outbuf, SPX_N); +} + +/** + * Computes the message-dependent randomness R, using a secret seed as a key + * for HMAC, and an optional randomization value prefixed to the message. + * This requires m to have at least SPX_SHAX_BLOCK_BYTES + SPX_N space + * available in front of the pointer, i.e. before the message to use for the + * prefix. This is necessary to prevent having to move the message around (and + * allocate memory for it). + */ +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { + (void)ctx; + + unsigned char buf[SPX_SHAX_BLOCK_BYTES + SPX_SHAX_OUTPUT_BYTES]; + shaXstate state; + int i; + + + /* This implements HMAC-SHA */ + for (i = 0; i < SPX_N; i++) { + buf[i] = 0x36 ^ sk_prf[i]; + } + memset(buf + SPX_N, 0x36, SPX_SHAX_BLOCK_BYTES - SPX_N); + + shaX_inc_init(&state); + shaX_inc_blocks(&state, buf, 1); + + memcpy(buf, optrand, SPX_N); + + /* If optrand + message cannot fill up an entire block */ + if (SPX_N + mlen < SPX_SHAX_BLOCK_BYTES) { + memcpy(buf + SPX_N, m, mlen); + shaX_inc_finalize(buf + SPX_SHAX_BLOCK_BYTES, &state, + buf, mlen + SPX_N); + } + /* Otherwise first fill a block, so that finalize only uses the message */ + else { + memcpy(buf + SPX_N, m, SPX_SHAX_BLOCK_BYTES - SPX_N); + shaX_inc_blocks(&state, buf, 1); + + m += SPX_SHAX_BLOCK_BYTES - SPX_N; + mlen -= SPX_SHAX_BLOCK_BYTES - SPX_N; + shaX_inc_finalize(buf + SPX_SHAX_BLOCK_BYTES, &state, m, mlen); + } + + for (i = 0; i < SPX_N; i++) { + buf[i] = 0x5c ^ sk_prf[i]; + } + memset(buf + SPX_N, 0x5c, SPX_SHAX_BLOCK_BYTES - SPX_N); + + shaX(buf, buf, SPX_SHAX_BLOCK_BYTES + SPX_SHAX_OUTPUT_BYTES); + memcpy(R, buf, SPX_N); +} + +/** + * Computes the message hash using R, the public key, and the message. + * Outputs the message digest and the index of the leaf. The index is split in + * the tree index and the leaf index, for convenient copying to an address. + */ +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { + (void)ctx; +#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) +#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) +#define SPX_LEAF_BITS SPX_TREE_HEIGHT +#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) +#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) + + unsigned char seed[2 * SPX_N + SPX_SHAX_OUTPUT_BYTES]; + + /* Round to nearest multiple of SPX_SHAX_BLOCK_BYTES */ +#define SPX_INBLOCKS (((SPX_N + SPX_PK_BYTES + SPX_SHAX_BLOCK_BYTES - 1) & \ + -SPX_SHAX_BLOCK_BYTES) / SPX_SHAX_BLOCK_BYTES) + unsigned char inbuf[SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES]; + + unsigned char buf[SPX_DGST_BYTES]; + unsigned char *bufp = buf; + shaXstate state; + + shaX_inc_init(&state); + + // seed: SHA-X(R ‖ PK.seed ‖ PK.root ‖ M) + memcpy(inbuf, R, SPX_N); + memcpy(inbuf + SPX_N, pk, SPX_PK_BYTES); + + /* If R + pk + message cannot fill up an entire block */ + if (SPX_N + SPX_PK_BYTES + mlen < SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES) { + memcpy(inbuf + SPX_N + SPX_PK_BYTES, m, mlen); + shaX_inc_finalize(seed + 2 * SPX_N, &state, inbuf, SPX_N + SPX_PK_BYTES + mlen); + } + /* Otherwise first fill a block, so that finalize only uses the message */ + else { + memcpy(inbuf + SPX_N + SPX_PK_BYTES, m, + SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES - SPX_N - SPX_PK_BYTES); + shaX_inc_blocks(&state, inbuf, SPX_INBLOCKS); + + m += SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES - SPX_N - SPX_PK_BYTES; + mlen -= SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES - SPX_N - SPX_PK_BYTES; + shaX_inc_finalize(seed + 2 * SPX_N, &state, m, (size_t)mlen); + } + + // H_msg: MGF1-SHA-X(R ‖ PK.seed ‖ seed) + memcpy(seed, R, SPX_N); + memcpy(seed + SPX_N, pk, SPX_N); + + /* By doing this in two steps, we prevent hashing the message twice; + otherwise each iteration in MGF1 would hash the message again. */ + mgf1_X(bufp, SPX_DGST_BYTES, seed, 2 * SPX_N + SPX_SHAX_OUTPUT_BYTES); + + memcpy(digest, bufp, SPX_FORS_MSG_BYTES); + bufp += SPX_FORS_MSG_BYTES; + + + *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); + *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); + bufp += SPX_TREE_BYTES; + + *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); + *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); +} + + diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/hash_sha2x8.c b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/hash_sha2x8.c new file mode 100644 index 0000000000..e04af7a069 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/hash_sha2x8.c @@ -0,0 +1,75 @@ +#include +#include + +#include "hash.h" +#include "hashx8.h" + +#include "address.h" +#include "params.h" +#include "sha2.h" +#include "sha256avx.h" +#include "sha256x8.h" +#include "utils.h" + +/* + * 8-way parallel version of prf_addr; takes 8x as much input and output + */ +void prf_addrx8(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const spx_ctx *ctx, + const uint32_t addrx8[8 * 8]) { + unsigned char bufx8[8 * (SPX_N + SPX_SHA256_ADDR_BYTES)]; + unsigned char outbufx8[8 * SPX_SHA256_OUTPUT_BYTES]; + unsigned int j; + + for (j = 0; j < 8; j++) { + memcpy(bufx8 + j * (SPX_N + SPX_SHA256_ADDR_BYTES), + addrx8 + j * 8, SPX_SHA256_ADDR_BYTES); + memcpy( + bufx8 + j * (SPX_N + SPX_SHA256_ADDR_BYTES) + SPX_SHA256_ADDR_BYTES, + ctx->sk_seed, + SPX_N + ); + } + + sha256x8_seeded( + /* out */ + outbufx8 + 0 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 1 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 2 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 3 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 4 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 5 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 6 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 7 * SPX_SHA256_OUTPUT_BYTES, + + /* seed */ + &ctx->statex8_seeded, + + /* in */ + bufx8 + 0 * (SPX_SHA256_ADDR_BYTES + SPX_N), + bufx8 + 1 * (SPX_SHA256_ADDR_BYTES + SPX_N), + bufx8 + 2 * (SPX_SHA256_ADDR_BYTES + SPX_N), + bufx8 + 3 * (SPX_SHA256_ADDR_BYTES + SPX_N), + bufx8 + 4 * (SPX_SHA256_ADDR_BYTES + SPX_N), + bufx8 + 5 * (SPX_SHA256_ADDR_BYTES + SPX_N), + bufx8 + 6 * (SPX_SHA256_ADDR_BYTES + SPX_N), + bufx8 + 7 * (SPX_SHA256_ADDR_BYTES + SPX_N), + SPX_SHA256_ADDR_BYTES + SPX_N /* len */ + ); + + memcpy(out0, outbufx8 + 0 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out1, outbufx8 + 1 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out2, outbufx8 + 2 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out3, outbufx8 + 3 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out4, outbufx8 + 4 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out5, outbufx8 + 5 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out6, outbufx8 + 6 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out7, outbufx8 + 7 * SPX_SHA256_OUTPUT_BYTES, SPX_N); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/hashx8.h b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/hashx8.h new file mode 100644 index 0000000000..46503f0a10 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/hashx8.h @@ -0,0 +1,20 @@ +#ifndef SPX_HASHX8_H +#define SPX_HASHX8_H + +#include + +#include "params.h" + +#define prf_addrx8 SPX_NAMESPACE(prf_addrx8) +void prf_addrx8(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const spx_ctx *ctx, + const uint32_t addrx8[8 * 8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/merkle.c b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/merkle.c new file mode 100644 index 0000000000..1f353c8dd8 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/merkle.c @@ -0,0 +1,65 @@ +#include +#include + +#include "merkle.h" + +#include "address.h" +#include "params.h" +#include "utils.h" +#include "utilsx8.h" +#include "wots.h" +#include "wotsx8.h" + +/* + * This generates a Merkle signature (WOTS signature followed by the Merkle + * authentication path). + */ +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf) { + unsigned char *auth_path = sig + SPX_WOTS_BYTES; + uint32_t tree_addrx8[8 * 8] = { 0 }; + int j; + struct leaf_info_x8 info = { 0 }; + unsigned steps[ SPX_WOTS_LEN ]; + + info.wots_sig = sig; + chain_lengths(steps, root); + info.wots_steps = steps; + + for (j = 0; j < 8; j++) { + set_type(&tree_addrx8[8 * j], SPX_ADDR_TYPE_HASHTREE); + set_type(&info.leaf_addr[8 * j], SPX_ADDR_TYPE_WOTS); + set_type(&info.pk_addr[8 * j], SPX_ADDR_TYPE_WOTSPK); + copy_subtree_addr(&tree_addrx8[8 * j], tree_addr); + copy_subtree_addr(&info.leaf_addr[8 * j], wots_addr); + copy_subtree_addr(&info.pk_addr[8 * j], wots_addr); + } + + info.wots_sign_leaf = idx_leaf; + + treehashx8(root, auth_path, ctx, + idx_leaf, 0, + SPX_TREE_HEIGHT, + wots_gen_leafx8, + tree_addrx8, &info); +} + +/* Compute root node of the top-most subtree. */ +/* Again, in this file because wots_gen_leaf is most of the work */ +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { + /* We do not need the auth path in key generation, but it simplifies the + code to have just one treehash routine that computes both root and path + in one function. */ + unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; + uint32_t top_tree_addr[8] = {0}; + uint32_t wots_addr[8] = {0}; + + set_layer_addr(top_tree_addr, SPX_D - 1); + set_layer_addr(wots_addr, SPX_D - 1); + + merkle_sign(auth_path, root, ctx, + wots_addr, top_tree_addr, + ~0U /* ~0 means "don't bother generating an auth path */ ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/merkle.h b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/merkle.h new file mode 100644 index 0000000000..769cf2e970 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/merkle.h @@ -0,0 +1,21 @@ +#ifndef MERKLE_H_ +#define MERKLE_H_ + +#include + +#include "context.h" +#include "params.h" + +/* Generate a Merkle signature (WOTS signature followed by the Merkle */ +/* authentication path) */ +#define merkle_sign SPX_NAMESPACE(merkle_sign) +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf); + +/* Compute the root node of the top-most subtree. */ +#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); + +#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/nistapi.h b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/nistapi.h new file mode 100644 index 0000000000..3cb71afad4 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/nistapi.h @@ -0,0 +1,87 @@ +#ifndef SPX_API_H +#define SPX_API_H + +#include +#include + +#include "params.h" + +#define CRYPTO_ALGNAME "SPHINCS+" + +#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES +#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES +#define CRYPTO_BYTES SPX_BYTES +#define CRYPTO_SEEDBYTES (3*SPX_N) + +/* + * Returns the length of a secret key, in bytes + */ +#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) +size_t crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) +size_t crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) +size_t crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) +size_t crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +#define crypto_sign SPX_NAMESPACE(crypto_sign) +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/params.h b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/params.h new file mode 100644 index 0000000000..ea5b76871e --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/params.h @@ -0,0 +1,61 @@ +#ifndef SPX_PARAMS_H +#define SPX_PARAMS_H + +#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSSHA2128SROBUST_AVX2_##s + +/* Hash output length in bytes. */ +#define SPX_N 16 +/* Height of the hypertree. */ +#define SPX_FULL_HEIGHT 63 +/* Number of subtree layer. */ +#define SPX_D 7 +/* FORS tree dimensions. */ +#define SPX_FORS_HEIGHT 12 +#define SPX_FORS_TREES 14 +/* Winternitz parameter, */ +#define SPX_WOTS_W 16 + +/* The hash function is defined by linking a different hash.c file, as opposed + to setting a #define constant. */ + +/* This is a SHA2-based parameter set, hence whether we use SHA-256 + * exclusively or we use both SHA-256 and SHA-512 is controlled by + * the following #define */ +#define SPX_SHA512 0 /* Use SHA-256 for all hashes */ + +/* For clarity */ +#define SPX_ADDR_BYTES 32 + +/* WOTS parameters. */ +#define SPX_WOTS_LOGW 4 + +#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) + +/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ +#define SPX_WOTS_LEN2 3 + +#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) +#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) +#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES + +/* Subtree size. */ +#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) + +//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT +// #error SPX_D should always divide SPX_FULL_HEIGHT +//#endif + +/* FORS parameters. */ +#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) +#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) +#define SPX_FORS_PK_BYTES SPX_N + +/* Resulting SPX sizes. */ +#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ + SPX_FULL_HEIGHT * SPX_N) +#define SPX_PK_BYTES (2 * SPX_N) +#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) + +#include "sha2_offsets.h" + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/sha256avx.c b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/sha256avx.c new file mode 100644 index 0000000000..6bbe6ecc24 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/sha256avx.c @@ -0,0 +1,357 @@ +#include +#include +#include + +#include "sha256avx.h" + +static const unsigned int RC[] = { + 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, + 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, + 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, + 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, + 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, + 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, + 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, + 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, + 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, + 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, + 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, + 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, + 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, + 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, + 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, + 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 +}; + +#define u32 uint32_t +#define u256 __m256i + +#define XOR _mm256_xor_si256 +#define OR _mm256_or_si256 +#define AND _mm256_and_si256 +#define ADD32 _mm256_add_epi32 +#define NOT(x) _mm256_xor_si256(x, _mm256_set_epi32(-1, -1, -1, -1, -1, -1, -1, -1)) + +#define LOAD(src) _mm256_loadu_si256((__m256i *)(src)) +#define STORE(dest,src) _mm256_storeu_si256((__m256i *)(dest),src) + +#define BYTESWAP(x) _mm256_shuffle_epi8(x, _mm256_set_epi8(0xc,0xd,0xe,0xf,0x8,0x9,0xa,0xb,0x4,0x5,0x6,0x7,0x0,0x1,0x2,0x3,0xc,0xd,0xe,0xf,0x8,0x9,0xa,0xb,0x4,0x5,0x6,0x7,0x0,0x1,0x2,0x3)) + +#define SHIFTR32(x, y) _mm256_srli_epi32(x, y) +#define SHIFTL32(x, y) _mm256_slli_epi32(x, y) + +#define ROTR32(x, y) OR(SHIFTR32(x, y), SHIFTL32(x, 32 - (y))) +#define ROTL32(x, y) OR(SHIFTL32(x, y), SHIFTR32(x, 32 - (y))) + +#define XOR3(a, b, c) XOR(XOR(a, b), c) + +#define ADD3_32(a, b, c) ADD32(ADD32(a, b), c) +#define ADD4_32(a, b, c, d) ADD32(ADD32(ADD32(a, b), c), d) +#define ADD5_32(a, b, c, d, e) ADD32(ADD32(ADD32(ADD32(a, b), c), d), e) + +#define MAJ_AVX(a, b, c) XOR3(AND(a, b), AND(a, c), AND(b, c)) +#define CH_AVX(a, b, c) XOR(AND(a, b), AND(NOT(a), c)) + +#define SIGMA1_AVX(x) XOR3(ROTR32(x, 6), ROTR32(x, 11), ROTR32(x, 25)) +#define SIGMA0_AVX(x) XOR3(ROTR32(x, 2), ROTR32(x, 13), ROTR32(x, 22)) + +#define WSIGMA1_AVX(x) XOR3(ROTR32(x, 17), ROTR32(x, 19), SHIFTR32(x, 10)) +#define WSIGMA0_AVX(x) XOR3(ROTR32(x, 7), ROTR32(x, 18), SHIFTR32(x, 3)) + +#define SHA256ROUND_AVX(a, b, c, d, e, f, g, h, rc, w) \ + T0 = ADD5_32(h, SIGMA1_AVX(e), CH_AVX(e, f, g), _mm256_set1_epi32((int)RC[rc]), w); \ + (d) = ADD32(d, T0); \ + T1 = ADD32(SIGMA0_AVX(a), MAJ_AVX(a, b, c)); \ + (h) = ADD32(T0, T1); + +// Transpose 8 vectors containing 32-bit values +static void transpose(u256 s[8]) { + u256 tmp0[8]; + u256 tmp1[8]; + tmp0[0] = _mm256_unpacklo_epi32(s[0], s[1]); + tmp0[1] = _mm256_unpackhi_epi32(s[0], s[1]); + tmp0[2] = _mm256_unpacklo_epi32(s[2], s[3]); + tmp0[3] = _mm256_unpackhi_epi32(s[2], s[3]); + tmp0[4] = _mm256_unpacklo_epi32(s[4], s[5]); + tmp0[5] = _mm256_unpackhi_epi32(s[4], s[5]); + tmp0[6] = _mm256_unpacklo_epi32(s[6], s[7]); + tmp0[7] = _mm256_unpackhi_epi32(s[6], s[7]); + tmp1[0] = _mm256_unpacklo_epi64(tmp0[0], tmp0[2]); + tmp1[1] = _mm256_unpackhi_epi64(tmp0[0], tmp0[2]); + tmp1[2] = _mm256_unpacklo_epi64(tmp0[1], tmp0[3]); + tmp1[3] = _mm256_unpackhi_epi64(tmp0[1], tmp0[3]); + tmp1[4] = _mm256_unpacklo_epi64(tmp0[4], tmp0[6]); + tmp1[5] = _mm256_unpackhi_epi64(tmp0[4], tmp0[6]); + tmp1[6] = _mm256_unpacklo_epi64(tmp0[5], tmp0[7]); + tmp1[7] = _mm256_unpackhi_epi64(tmp0[5], tmp0[7]); + s[0] = _mm256_permute2x128_si256(tmp1[0], tmp1[4], 0x20); + s[1] = _mm256_permute2x128_si256(tmp1[1], tmp1[5], 0x20); + s[2] = _mm256_permute2x128_si256(tmp1[2], tmp1[6], 0x20); + s[3] = _mm256_permute2x128_si256(tmp1[3], tmp1[7], 0x20); + s[4] = _mm256_permute2x128_si256(tmp1[0], tmp1[4], 0x31); + s[5] = _mm256_permute2x128_si256(tmp1[1], tmp1[5], 0x31); + s[6] = _mm256_permute2x128_si256(tmp1[2], tmp1[6], 0x31); + s[7] = _mm256_permute2x128_si256(tmp1[3], tmp1[7], 0x31); +} + +void sha256_ctx_clone8x(sha256x8ctx *out, const sha256x8ctx *in) { + memcpy(out, in, sizeof(sha256x8ctx)); +} + +void sha256_init8x(sha256x8ctx *ctx) { + ctx->s[0] = _mm256_set_epi32((int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667); + ctx->s[1] = _mm256_set_epi32((int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85); + ctx->s[2] = _mm256_set_epi32((int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372); + ctx->s[3] = _mm256_set_epi32((int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a); + ctx->s[4] = _mm256_set_epi32((int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f); + ctx->s[5] = _mm256_set_epi32((int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c); + ctx->s[6] = _mm256_set_epi32((int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab); + ctx->s[7] = _mm256_set_epi32((int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19); + + ctx->datalen = 0; + ctx->msglen = 0; +} + +void sha256_final8x(sha256x8ctx *ctx, + unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7) { + unsigned int i, curlen; + + // Padding + if (ctx->datalen < 56) { + for (i = 0; i < 8; ++i) { + curlen = ctx->datalen; + ctx->msgblocks[64 * i + curlen++] = 0x80; + while (curlen < 64) { + ctx->msgblocks[64 * i + curlen++] = 0x00; + } + } + } else { + for (i = 0; i < 8; ++i) { + curlen = ctx->datalen; + ctx->msgblocks[64 * i + curlen++] = 0x80; + while (curlen < 64) { + ctx->msgblocks[64 * i + curlen++] = 0x00; + } + } + sha256_transform8x(ctx, + &ctx->msgblocks[64 * 0], + &ctx->msgblocks[64 * 1], + &ctx->msgblocks[64 * 2], + &ctx->msgblocks[64 * 3], + &ctx->msgblocks[64 * 4], + &ctx->msgblocks[64 * 5], + &ctx->msgblocks[64 * 6], + &ctx->msgblocks[64 * 7] + ); + memset(ctx->msgblocks, 0, 8 * 64); + } + + // Add length of the message to each block + ctx->msglen += ctx->datalen * 8; + for (i = 0; i < 8; i++) { + ctx->msgblocks[64 * i + 63] = (unsigned char)(ctx->msglen); + ctx->msgblocks[64 * i + 62] = (unsigned char)(ctx->msglen >> 8); + ctx->msgblocks[64 * i + 61] = (unsigned char)(ctx->msglen >> 16); + ctx->msgblocks[64 * i + 60] = (unsigned char)(ctx->msglen >> 24); + ctx->msgblocks[64 * i + 59] = (unsigned char)(ctx->msglen >> 32); + ctx->msgblocks[64 * i + 58] = (unsigned char)(ctx->msglen >> 40); + ctx->msgblocks[64 * i + 57] = (unsigned char)(ctx->msglen >> 48); + ctx->msgblocks[64 * i + 56] = (unsigned char)(ctx->msglen >> 56); + } + sha256_transform8x(ctx, + &ctx->msgblocks[64 * 0], + &ctx->msgblocks[64 * 1], + &ctx->msgblocks[64 * 2], + &ctx->msgblocks[64 * 3], + &ctx->msgblocks[64 * 4], + &ctx->msgblocks[64 * 5], + &ctx->msgblocks[64 * 6], + &ctx->msgblocks[64 * 7] + ); + + // Compute final hash output + transpose(ctx->s); + + // Store Hash value + STORE(out0, BYTESWAP(ctx->s[0])); + STORE(out1, BYTESWAP(ctx->s[1])); + STORE(out2, BYTESWAP(ctx->s[2])); + STORE(out3, BYTESWAP(ctx->s[3])); + STORE(out4, BYTESWAP(ctx->s[4])); + STORE(out5, BYTESWAP(ctx->s[5])); + STORE(out6, BYTESWAP(ctx->s[6])); + STORE(out7, BYTESWAP(ctx->s[7])); +} + +void sha256_transform8x(sha256x8ctx *ctx, + const unsigned char *data0, + const unsigned char *data1, + const unsigned char *data2, + const unsigned char *data3, + const unsigned char *data4, + const unsigned char *data5, + const unsigned char *data6, + const unsigned char *data7) { + u256 s[8], w[64], T0, T1; + + // Load words and transform data correctly + w[0] = BYTESWAP(LOAD(data0)); + w[0 + 8] = BYTESWAP(LOAD(data0 + 32)); + w[1] = BYTESWAP(LOAD(data1)); + w[1 + 8] = BYTESWAP(LOAD(data1 + 32)); + w[2] = BYTESWAP(LOAD(data2)); + w[2 + 8] = BYTESWAP(LOAD(data2 + 32)); + w[3] = BYTESWAP(LOAD(data3)); + w[3 + 8] = BYTESWAP(LOAD(data3 + 32)); + w[4] = BYTESWAP(LOAD(data4)); + w[4 + 8] = BYTESWAP(LOAD(data4 + 32)); + w[5] = BYTESWAP(LOAD(data5)); + w[5 + 8] = BYTESWAP(LOAD(data5 + 32)); + w[6] = BYTESWAP(LOAD(data6)); + w[6 + 8] = BYTESWAP(LOAD(data6 + 32)); + w[7] = BYTESWAP(LOAD(data7)); + w[7 + 8] = BYTESWAP(LOAD(data7 + 32)); + + transpose(w); + transpose(w + 8); + + // Initial State + s[0] = ctx->s[0]; + s[1] = ctx->s[1]; + s[2] = ctx->s[2]; + s[3] = ctx->s[3]; + s[4] = ctx->s[4]; + s[5] = ctx->s[5]; + s[6] = ctx->s[6]; + s[7] = ctx->s[7]; + + SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 0, w[0]); + SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 1, w[1]); + SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 2, w[2]); + SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 3, w[3]); + SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 4, w[4]); + SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 5, w[5]); + SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 6, w[6]); + SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 7, w[7]); + SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 8, w[8]); + SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 9, w[9]); + SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 10, w[10]); + SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 11, w[11]); + SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 12, w[12]); + SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 13, w[13]); + SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 14, w[14]); + SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 15, w[15]); + w[16] = ADD4_32(WSIGMA1_AVX(w[14]), w[0], w[9], WSIGMA0_AVX(w[1])); + SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 16, w[16]); + w[17] = ADD4_32(WSIGMA1_AVX(w[15]), w[1], w[10], WSIGMA0_AVX(w[2])); + SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 17, w[17]); + w[18] = ADD4_32(WSIGMA1_AVX(w[16]), w[2], w[11], WSIGMA0_AVX(w[3])); + SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 18, w[18]); + w[19] = ADD4_32(WSIGMA1_AVX(w[17]), w[3], w[12], WSIGMA0_AVX(w[4])); + SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 19, w[19]); + w[20] = ADD4_32(WSIGMA1_AVX(w[18]), w[4], w[13], WSIGMA0_AVX(w[5])); + SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 20, w[20]); + w[21] = ADD4_32(WSIGMA1_AVX(w[19]), w[5], w[14], WSIGMA0_AVX(w[6])); + SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 21, w[21]); + w[22] = ADD4_32(WSIGMA1_AVX(w[20]), w[6], w[15], WSIGMA0_AVX(w[7])); + SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 22, w[22]); + w[23] = ADD4_32(WSIGMA1_AVX(w[21]), w[7], w[16], WSIGMA0_AVX(w[8])); + SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 23, w[23]); + w[24] = ADD4_32(WSIGMA1_AVX(w[22]), w[8], w[17], WSIGMA0_AVX(w[9])); + SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 24, w[24]); + w[25] = ADD4_32(WSIGMA1_AVX(w[23]), w[9], w[18], WSIGMA0_AVX(w[10])); + SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 25, w[25]); + w[26] = ADD4_32(WSIGMA1_AVX(w[24]), w[10], w[19], WSIGMA0_AVX(w[11])); + SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 26, w[26]); + w[27] = ADD4_32(WSIGMA1_AVX(w[25]), w[11], w[20], WSIGMA0_AVX(w[12])); + SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 27, w[27]); + w[28] = ADD4_32(WSIGMA1_AVX(w[26]), w[12], w[21], WSIGMA0_AVX(w[13])); + SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 28, w[28]); + w[29] = ADD4_32(WSIGMA1_AVX(w[27]), w[13], w[22], WSIGMA0_AVX(w[14])); + SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 29, w[29]); + w[30] = ADD4_32(WSIGMA1_AVX(w[28]), w[14], w[23], WSIGMA0_AVX(w[15])); + SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 30, w[30]); + w[31] = ADD4_32(WSIGMA1_AVX(w[29]), w[15], w[24], WSIGMA0_AVX(w[16])); + SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 31, w[31]); + w[32] = ADD4_32(WSIGMA1_AVX(w[30]), w[16], w[25], WSIGMA0_AVX(w[17])); + SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 32, w[32]); + w[33] = ADD4_32(WSIGMA1_AVX(w[31]), w[17], w[26], WSIGMA0_AVX(w[18])); + SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 33, w[33]); + w[34] = ADD4_32(WSIGMA1_AVX(w[32]), w[18], w[27], WSIGMA0_AVX(w[19])); + SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 34, w[34]); + w[35] = ADD4_32(WSIGMA1_AVX(w[33]), w[19], w[28], WSIGMA0_AVX(w[20])); + SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 35, w[35]); + w[36] = ADD4_32(WSIGMA1_AVX(w[34]), w[20], w[29], WSIGMA0_AVX(w[21])); + SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 36, w[36]); + w[37] = ADD4_32(WSIGMA1_AVX(w[35]), w[21], w[30], WSIGMA0_AVX(w[22])); + SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 37, w[37]); + w[38] = ADD4_32(WSIGMA1_AVX(w[36]), w[22], w[31], WSIGMA0_AVX(w[23])); + SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 38, w[38]); + w[39] = ADD4_32(WSIGMA1_AVX(w[37]), w[23], w[32], WSIGMA0_AVX(w[24])); + SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 39, w[39]); + w[40] = ADD4_32(WSIGMA1_AVX(w[38]), w[24], w[33], WSIGMA0_AVX(w[25])); + SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 40, w[40]); + w[41] = ADD4_32(WSIGMA1_AVX(w[39]), w[25], w[34], WSIGMA0_AVX(w[26])); + SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 41, w[41]); + w[42] = ADD4_32(WSIGMA1_AVX(w[40]), w[26], w[35], WSIGMA0_AVX(w[27])); + SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 42, w[42]); + w[43] = ADD4_32(WSIGMA1_AVX(w[41]), w[27], w[36], WSIGMA0_AVX(w[28])); + SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 43, w[43]); + w[44] = ADD4_32(WSIGMA1_AVX(w[42]), w[28], w[37], WSIGMA0_AVX(w[29])); + SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 44, w[44]); + w[45] = ADD4_32(WSIGMA1_AVX(w[43]), w[29], w[38], WSIGMA0_AVX(w[30])); + SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 45, w[45]); + w[46] = ADD4_32(WSIGMA1_AVX(w[44]), w[30], w[39], WSIGMA0_AVX(w[31])); + SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 46, w[46]); + w[47] = ADD4_32(WSIGMA1_AVX(w[45]), w[31], w[40], WSIGMA0_AVX(w[32])); + SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 47, w[47]); + w[48] = ADD4_32(WSIGMA1_AVX(w[46]), w[32], w[41], WSIGMA0_AVX(w[33])); + SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 48, w[48]); + w[49] = ADD4_32(WSIGMA1_AVX(w[47]), w[33], w[42], WSIGMA0_AVX(w[34])); + SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 49, w[49]); + w[50] = ADD4_32(WSIGMA1_AVX(w[48]), w[34], w[43], WSIGMA0_AVX(w[35])); + SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 50, w[50]); + w[51] = ADD4_32(WSIGMA1_AVX(w[49]), w[35], w[44], WSIGMA0_AVX(w[36])); + SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 51, w[51]); + w[52] = ADD4_32(WSIGMA1_AVX(w[50]), w[36], w[45], WSIGMA0_AVX(w[37])); + SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 52, w[52]); + w[53] = ADD4_32(WSIGMA1_AVX(w[51]), w[37], w[46], WSIGMA0_AVX(w[38])); + SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 53, w[53]); + w[54] = ADD4_32(WSIGMA1_AVX(w[52]), w[38], w[47], WSIGMA0_AVX(w[39])); + SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 54, w[54]); + w[55] = ADD4_32(WSIGMA1_AVX(w[53]), w[39], w[48], WSIGMA0_AVX(w[40])); + SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 55, w[55]); + w[56] = ADD4_32(WSIGMA1_AVX(w[54]), w[40], w[49], WSIGMA0_AVX(w[41])); + SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 56, w[56]); + w[57] = ADD4_32(WSIGMA1_AVX(w[55]), w[41], w[50], WSIGMA0_AVX(w[42])); + SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 57, w[57]); + w[58] = ADD4_32(WSIGMA1_AVX(w[56]), w[42], w[51], WSIGMA0_AVX(w[43])); + SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 58, w[58]); + w[59] = ADD4_32(WSIGMA1_AVX(w[57]), w[43], w[52], WSIGMA0_AVX(w[44])); + SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 59, w[59]); + w[60] = ADD4_32(WSIGMA1_AVX(w[58]), w[44], w[53], WSIGMA0_AVX(w[45])); + SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 60, w[60]); + w[61] = ADD4_32(WSIGMA1_AVX(w[59]), w[45], w[54], WSIGMA0_AVX(w[46])); + SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 61, w[61]); + w[62] = ADD4_32(WSIGMA1_AVX(w[60]), w[46], w[55], WSIGMA0_AVX(w[47])); + SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 62, w[62]); + w[63] = ADD4_32(WSIGMA1_AVX(w[61]), w[47], w[56], WSIGMA0_AVX(w[48])); + SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 63, w[63]); + + // Feed Forward + ctx->s[0] = ADD32(s[0], ctx->s[0]); + ctx->s[1] = ADD32(s[1], ctx->s[1]); + ctx->s[2] = ADD32(s[2], ctx->s[2]); + ctx->s[3] = ADD32(s[3], ctx->s[3]); + ctx->s[4] = ADD32(s[4], ctx->s[4]); + ctx->s[5] = ADD32(s[5], ctx->s[5]); + ctx->s[6] = ADD32(s[6], ctx->s[6]); + ctx->s[7] = ADD32(s[7], ctx->s[7]); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/sha256avx.h b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/sha256avx.h new file mode 100644 index 0000000000..1e3bcf889b --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/sha256avx.h @@ -0,0 +1,44 @@ +#ifndef SHA256AVX_H +#define SHA256AVX_H + +#include +#include + +#include "params.h" + +typedef struct SHA256state { + __m256i s[8]; + unsigned char msgblocks[8 * 64]; + unsigned int datalen; + unsigned long long msglen; +} sha256x8ctx; + +#define sha256_ctx_clone8x SPX_NAMESPACE(sha256_ctx_clone8x) +void sha256_ctx_clone8x(sha256x8ctx *out, const sha256x8ctx *in); + +#define sha256_init8x SPX_NAMESPACE(sha256_init8x) +void sha256_init8x(sha256x8ctx *ctx); + +#define sha256_final8x SPX_NAMESPACE(sha256_final8x) +void sha256_final8x(sha256x8ctx *ctx, + unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7); + +#define sha256_transform8x SPX_NAMESPACE(sha256_transform8x) +void sha256_transform8x(sha256x8ctx *ctx, + const unsigned char *data0, + const unsigned char *data1, + const unsigned char *data2, + const unsigned char *data3, + const unsigned char *data4, + const unsigned char *data5, + const unsigned char *data6, + const unsigned char *data7); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/sha256x8.c b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/sha256x8.c new file mode 100644 index 0000000000..d97750c09b --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/sha256x8.c @@ -0,0 +1,185 @@ +#include + +#include "sha256avx.h" +#include "sha256x8.h" +#include "utils.h" + +// Performs sha256x8 on an initialized (and perhaps seeded) state. +static void _sha256x8( + sha256x8ctx *ctx, + unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, unsigned long long inlen) { + unsigned long long i = 0; + while (inlen - i >= 64) { + sha256_transform8x(ctx, + in0 + i, + in1 + i, + in2 + i, + in3 + i, + in4 + i, + in5 + i, + in6 + i, + in7 + i + ); + i += 64; + ctx->msglen += 512; + } + + size_t bytes_to_copy = (size_t)(inlen - i); + memcpy(&ctx->msgblocks[64 * 0], in0 + i, bytes_to_copy); + memcpy(&ctx->msgblocks[64 * 1], in1 + i, bytes_to_copy); + memcpy(&ctx->msgblocks[64 * 2], in2 + i, bytes_to_copy); + memcpy(&ctx->msgblocks[64 * 3], in3 + i, bytes_to_copy); + memcpy(&ctx->msgblocks[64 * 4], in4 + i, bytes_to_copy); + memcpy(&ctx->msgblocks[64 * 5], in5 + i, bytes_to_copy); + memcpy(&ctx->msgblocks[64 * 6], in6 + i, bytes_to_copy); + memcpy(&ctx->msgblocks[64 * 7], in7 + i, bytes_to_copy); + ctx->datalen = (unsigned int)bytes_to_copy; + + sha256_final8x(ctx, out0, out1, out2, out3, out4, out5, out6, out7); +} + +void sha256x8_seeded( + unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const sha256x8ctx *seed, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, unsigned long long inlen) { + + sha256x8ctx ctx; + sha256_ctx_clone8x(&ctx, seed); + + _sha256x8(&ctx, out0, out1, out2, out3, out4, out5, out6, out7, + in0, in1, in2, in3, in4, in5, in6, in7, inlen); +} + +/* This provides a wrapper around the internals of 8x parallel SHA256 */ +void sha256x8(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, unsigned long long inlen) { + sha256x8ctx ctx; + sha256_init8x(&ctx); + + _sha256x8(&ctx, out0, out1, out2, out3, out4, out5, out6, out7, + in0, in1, in2, in3, in4, in5, in6, in7, inlen); +} + +/** + * Note that inlen should be sufficiently small that it still allows for + * an array to be allocated on the stack. Typically 'in' is merely a seed. + * Outputs outlen number of bytes + */ +void mgf1x8(unsigned char *outx8, unsigned long outlen, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, + unsigned long inlen) { + PQCLEAN_VLA(unsigned char, inbufx8, 8 * (inlen + 4)); + unsigned char outbufx8[8 * SPX_SHA256_OUTPUT_BYTES]; + uint32_t i; + unsigned int j; + + memcpy(inbufx8 + 0 * (inlen + 4), in0, inlen); + memcpy(inbufx8 + 1 * (inlen + 4), in1, inlen); + memcpy(inbufx8 + 2 * (inlen + 4), in2, inlen); + memcpy(inbufx8 + 3 * (inlen + 4), in3, inlen); + memcpy(inbufx8 + 4 * (inlen + 4), in4, inlen); + memcpy(inbufx8 + 5 * (inlen + 4), in5, inlen); + memcpy(inbufx8 + 6 * (inlen + 4), in6, inlen); + memcpy(inbufx8 + 7 * (inlen + 4), in7, inlen); + + /* While we can fit in at least another full block of SHA256 output.. */ + for (i = 0; (i + 1)*SPX_SHA256_OUTPUT_BYTES <= outlen; i++) { + for (j = 0; j < 8; j++) { + u32_to_bytes(inbufx8 + inlen + j * (inlen + 4), i); + } + + sha256x8(outx8 + 0 * outlen, + outx8 + 1 * outlen, + outx8 + 2 * outlen, + outx8 + 3 * outlen, + outx8 + 4 * outlen, + outx8 + 5 * outlen, + outx8 + 6 * outlen, + outx8 + 7 * outlen, + inbufx8 + 0 * (inlen + 4), + inbufx8 + 1 * (inlen + 4), + inbufx8 + 2 * (inlen + 4), + inbufx8 + 3 * (inlen + 4), + inbufx8 + 4 * (inlen + 4), + inbufx8 + 5 * (inlen + 4), + inbufx8 + 6 * (inlen + 4), + inbufx8 + 7 * (inlen + 4), inlen + 4); + outx8 += SPX_SHA256_OUTPUT_BYTES; + } + /* Until we cannot anymore, and we fill the remainder. */ + for (j = 0; j < 8; j++) { + u32_to_bytes(inbufx8 + inlen + j * (inlen + 4), i); + } + sha256x8(outbufx8 + 0 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 1 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 2 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 3 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 4 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 5 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 6 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 7 * SPX_SHA256_OUTPUT_BYTES, + inbufx8 + 0 * (inlen + 4), + inbufx8 + 1 * (inlen + 4), + inbufx8 + 2 * (inlen + 4), + inbufx8 + 3 * (inlen + 4), + inbufx8 + 4 * (inlen + 4), + inbufx8 + 5 * (inlen + 4), + inbufx8 + 6 * (inlen + 4), + inbufx8 + 7 * (inlen + 4), inlen + 4); + + for (j = 0; j < 8; j++) { + memcpy(outx8 + j * outlen, + outbufx8 + j * SPX_SHA256_OUTPUT_BYTES, + outlen - i * SPX_SHA256_OUTPUT_BYTES); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/sha256x8.h b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/sha256x8.h new file mode 100644 index 0000000000..4f7330a6c1 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/sha256x8.h @@ -0,0 +1,64 @@ +#ifndef SPX_SHA256X8_H +#define SPX_SHA256X8_H + +#include "params.h" +#include "sha256avx.h" + + + +#define sha256x8_seeded SPX_NAMESPACE(sha256x8_seeded) +void sha256x8_seeded( + unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const sha256x8ctx *seed, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, unsigned long long inlen); + +/* This provides a wrapper around the internals of 8x parallel SHA256 */ +#define sha256x8 SPX_NAMESPACE(sha256x8) +void sha256x8(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, unsigned long long inlen); + +/** + * Note that inlen should be sufficiently small that it still allows for + * an array to be allocated on the stack. Typically 'in' is merely a seed. + * Outputs outlen number of bytes + */ +#define mgf1x8 SPX_NAMESPACE(mgf1x8) +void mgf1x8(unsigned char *outx8, unsigned long outlen, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, + unsigned long inlen); +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/sha2_offsets.h b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/sha2_offsets.h new file mode 100644 index 0000000000..6e3584f7a4 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/sha2_offsets.h @@ -0,0 +1,27 @@ +#ifndef SHA2_OFFSETS_H_ +#define SHA2_OFFSETS_H_ + +#define SPX_SHA256_BLOCK_BYTES 64 +#define SPX_SHA256_OUTPUT_BYTES 32 + +#define SPX_SHA512_BLOCK_BYTES 128 +#define SPX_SHA512_OUTPUT_BYTES 64 + +/* + * Offsets of various fields in the address structure when we use SHA2 as + * the Sphincs+ hash function + */ + +#define SPX_OFFSET_LAYER 0 /* The byte used to specify the Merkle tree layer */ +#define SPX_OFFSET_TREE 1 /* The start of the 8 byte field used to specify the tree */ +#define SPX_OFFSET_TYPE 9 /* The byte used to specify the hash type (reason) */ +#define SPX_OFFSET_KP_ADDR2 12 /* The high byte used to specify the key pair (which one-time signature) */ +#define SPX_OFFSET_KP_ADDR1 13 /* The low byte used to specify the key pair */ +#define SPX_OFFSET_CHAIN_ADDR 17 /* The byte used to specify the chain address (which Winternitz chain) */ +#define SPX_OFFSET_HASH_ADDR 21 /* The byte used to specify the hash address (where in the Winternitz chain) */ +#define SPX_OFFSET_TREE_HGT 17 /* The byte used to specify the height of this node in the FORS or Merkle tree */ +#define SPX_OFFSET_TREE_INDEX 18 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ + +#define SPX_SHA2 1 + +#endif /* SHA2_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/sign.c b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/sign.c new file mode 100644 index 0000000000..9d0c7d1b22 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/sign.c @@ -0,0 +1,286 @@ +#include +#include +#include + +#include "address.h" +#include "context.h" +#include "fors.h" +#include "hash.h" +#include "merkle.h" +#include "nistapi.h" +#include "params.h" +#include "randombytes.h" +#include "thash.h" +#include "utils.h" +#include "wots.h" + +/* + * Returns the length of a secret key, in bytes + */ +size_t crypto_sign_secretkeybytes(void) { + return CRYPTO_SECRETKEYBYTES; +} + +/* + * Returns the length of a public key, in bytes + */ +size_t crypto_sign_publickeybytes(void) { + return CRYPTO_PUBLICKEYBYTES; +} + +/* + * Returns the length of a signature, in bytes + */ +size_t crypto_sign_bytes(void) { + return CRYPTO_BYTES; +} + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +size_t crypto_sign_seedbytes(void) { + return CRYPTO_SEEDBYTES; +} + +/* + * Generates an SPX key pair given a seed of length + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [PUB_SEED || root] + */ +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed) { + spx_ctx ctx; + + /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ + memcpy(sk, seed, CRYPTO_SEEDBYTES); + + memcpy(pk, sk + 2 * SPX_N, SPX_N); + + memcpy(ctx.pub_seed, pk, SPX_N); + memcpy(ctx.sk_seed, sk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + /* Compute root node of the top-most subtree. */ + merkle_gen_root(sk + 3 * SPX_N, &ctx); + + // cleanup + free_hash_function(&ctx); + + memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); + + return 0; +} + +/* + * Generates an SPX key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [PUB_SEED || root] + */ +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { + uint8_t seed[CRYPTO_SEEDBYTES]; + randombytes(seed, CRYPTO_SEEDBYTES); + crypto_sign_seed_keypair(pk, sk, seed); + + return 0; +} + +/** + * Returns an array containing a detached signature. + */ +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk) { + spx_ctx ctx; + + const uint8_t *sk_prf = sk + SPX_N; + const uint8_t *pk = sk + 2 * SPX_N; + + uint8_t optrand[SPX_N]; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t root[SPX_N]; + uint32_t i; + uint64_t tree; + uint32_t idx_leaf; + uint32_t wots_addr[8] = {0}; + uint32_t tree_addr[8] = {0}; + + memcpy(ctx.sk_seed, sk, SPX_N); + memcpy(ctx.pub_seed, pk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + + /* Optionally, signing can be made non-deterministic using optrand. + This can help counter side-channel attacks that would benefit from + getting a large number of traces when the signer uses the same nodes. */ + randombytes(optrand, SPX_N); + /* Compute the digest randomization value. */ + gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); + + /* Derive the message digest and leaf index from R, PK and M. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; + + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); + + /* Sign the message hash using FORS. */ + fors_sign(sig, root, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); + sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; + + /* Update the indices for the next layer. */ + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; + } + + free_hash_function(&ctx); + + *siglen = SPX_BYTES; + + return 0; +} + +/** + * Verifies a detached signature and message under a given public key. + */ +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk) { + spx_ctx ctx; + const uint8_t *pub_root = pk + SPX_N; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t wots_pk[SPX_WOTS_BYTES]; + uint8_t root[SPX_N]; + uint8_t leaf[SPX_N]; + unsigned int i; + uint64_t tree; + uint32_t idx_leaf; + uint32_t wots_addr[8] = {0}; + uint32_t tree_addr[8] = {0}; + uint32_t wots_pk_addr[8] = {0}; + + if (siglen != SPX_BYTES) { + return -1; + } + + memcpy(ctx.pub_seed, pk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); + + /* Derive the message digest and leaf index from R || PK || M. */ + /* The additional SPX_N is a result of the hash domain separator. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; + + /* Layer correctly defaults to 0, so no need to set_layer_addr */ + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); + + fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + /* For each subtree.. */ + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + copy_keypair_addr(wots_pk_addr, wots_addr); + + /* The WOTS public key is only correct if the signature was correct. */ + /* Initially, root is the FORS pk, but on subsequent iterations it is + the root of the subtree below the currently processed subtree. */ + wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); + sig += SPX_WOTS_BYTES; + + /* Compute the leaf node using the WOTS public key. */ + thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); + + /* Compute the root node of this subtree. */ + compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, + &ctx, tree_addr); + sig += SPX_TREE_HEIGHT * SPX_N; + + /* Update the indices for the next layer. */ + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; + } + + // cleanup + free_hash_function(&ctx); + + /* Check if the root node equals the root node in the public key. */ + if (memcmp(root, pub_root, SPX_N) != 0) { + return -1; + } + + return 0; +} + + +/** + * Returns an array containing the signature followed by the message. + */ +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk) { + size_t siglen; + + crypto_sign_signature(sm, &siglen, m, mlen, sk); + + memmove(sm + SPX_BYTES, m, mlen); + *smlen = siglen + mlen; + + return 0; +} + +/** + * Verifies a given signature-message pair under a given public key. + */ +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk) { + /* The API caller does not necessarily know what size a signature should be + but SPHINCS+ signatures are always exactly SPX_BYTES. */ + if (smlen < SPX_BYTES) { + memset(m, 0, smlen); + *mlen = 0; + return -1; + } + + *mlen = smlen - SPX_BYTES; + + if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { + memset(m, 0, smlen); + *mlen = 0; + return -1; + } + + /* If verification was successful, move the message to the right place. */ + memmove(m, sm + SPX_BYTES, *mlen); + + return 0; +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/thash.h b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/thash.h new file mode 100644 index 0000000000..8687ccfb4d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/thash.h @@ -0,0 +1,13 @@ +#ifndef SPX_THASH_H +#define SPX_THASH_H + +#include "context.h" +#include "params.h" + +#include + +#define thash SPX_NAMESPACE(thash) +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/thash_sha2_robust.c b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/thash_sha2_robust.c new file mode 100644 index 0000000000..18f65c2e42 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/thash_sha2_robust.c @@ -0,0 +1,39 @@ +#include +#include + +#include "address.h" +#include "context.h" +#include "hash.h" +#include "params.h" +#include "sha2.h" +#include "thash.h" +#include "utils.h" + + +/** + * Takes an array of inblocks concatenated arrays of SPX_N bytes. + */ +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]) { + unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES]; + PQCLEAN_VLA(uint8_t, bitmask, inblocks * SPX_N); + PQCLEAN_VLA(uint8_t, buf, SPX_N + SPX_SHA256_OUTPUT_BYTES + inblocks * SPX_N); + sha256ctx sha2_state; + unsigned int i; + + memcpy(buf, ctx->pub_seed, SPX_N); + memcpy(buf + SPX_N, addr, SPX_SHA256_ADDR_BYTES); + mgf1_256(bitmask, inblocks * SPX_N, buf, SPX_N + SPX_SHA256_ADDR_BYTES); + + /* Retrieve precomputed state containing pub_seed */ + sha256_inc_ctx_clone(&sha2_state, &ctx->state_seeded); + + for (i = 0; i < inblocks * SPX_N; i++) { + buf[SPX_N + SPX_SHA256_ADDR_BYTES + i] = in[i] ^ bitmask[i]; + } + + sha256_inc_finalize(outbuf, &sha2_state, buf + SPX_N, + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N); + memcpy(out, outbuf, SPX_N); +} + diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/thash_sha2_robustx8.c b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/thash_sha2_robustx8.c new file mode 100644 index 0000000000..09ae4e1265 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/thash_sha2_robustx8.c @@ -0,0 +1,121 @@ +#include +#include + +#include "thashx8.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "sha2.h" +#include "sha256avx.h" +#include "sha256x8.h" +#include "utils.h" + + +/** + * 8-way parallel version of thash; takes 8x as much input and output + */ +void thashx8(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addrx8[8 * 8]) { + PQCLEAN_VLA(unsigned char, bufx8, 8 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)); + unsigned char outbufx8[8 * SPX_SHA256_OUTPUT_BYTES]; + PQCLEAN_VLA(unsigned char, bitmaskx8, 8 * (inblocks * SPX_N)); + unsigned int i; + + for (i = 0; i < 8; i++) { + memcpy(bufx8 + i * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + ctx->pub_seed, SPX_N); + memcpy(bufx8 + SPX_N + + i * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + addrx8 + i * 8, SPX_SHA256_ADDR_BYTES); + } + + mgf1x8(bitmaskx8, inblocks * SPX_N, + bufx8 + 0 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + 1 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + 2 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + 3 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + 4 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + 5 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + 6 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + 7 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + SPX_N + SPX_SHA256_ADDR_BYTES); + + for (i = 0; i < inblocks * SPX_N; i++) { + bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + + 0 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = + in0[i] ^ bitmaskx8[i + 0 * (inblocks * SPX_N)]; + bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + + 1 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = + in1[i] ^ bitmaskx8[i + 1 * (inblocks * SPX_N)]; + bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + + 2 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = + in2[i] ^ bitmaskx8[i + 2 * (inblocks * SPX_N)]; + bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + + 3 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = + in3[i] ^ bitmaskx8[i + 3 * (inblocks * SPX_N)]; + bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + + 4 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = + in4[i] ^ bitmaskx8[i + 4 * (inblocks * SPX_N)]; + bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + + 5 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = + in5[i] ^ bitmaskx8[i + 5 * (inblocks * SPX_N)]; + bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + + 6 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = + in6[i] ^ bitmaskx8[i + 6 * (inblocks * SPX_N)]; + bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + + 7 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = + in7[i] ^ bitmaskx8[i + 7 * (inblocks * SPX_N)]; + } + + sha256x8_seeded( + /* out */ + outbufx8 + 0 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 1 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 2 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 3 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 4 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 5 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 6 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 7 * SPX_SHA256_OUTPUT_BYTES, + + /* seed */ + &ctx->statex8_seeded, + + /* in */ + bufx8 + SPX_N + 0 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + SPX_N + 1 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + SPX_N + 2 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + SPX_N + 3 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + SPX_N + 4 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + SPX_N + 5 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + SPX_N + 6 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + SPX_N + 7 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N /* len */ + ); + + memcpy(out0, outbufx8 + 0 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out1, outbufx8 + 1 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out2, outbufx8 + 2 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out3, outbufx8 + 3 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out4, outbufx8 + 4 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out5, outbufx8 + 5 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out6, outbufx8 + 6 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out7, outbufx8 + 7 * SPX_SHA256_OUTPUT_BYTES, SPX_N); +} + diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/thashx8.h b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/thashx8.h new file mode 100644 index 0000000000..c02fe9cf3e --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/thashx8.h @@ -0,0 +1,28 @@ +#ifndef SPX_THASHX8_H +#define SPX_THASHX8_H + +#include + +#include "context.h" +#include "params.h" + +#define thashx8 SPX_NAMESPACE(thashx8) +void thashx8(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addrx8[8 * 8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/utils.c b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/utils.c new file mode 100644 index 0000000000..177b541fb9 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/utils.c @@ -0,0 +1,148 @@ +#include + +#include "utils.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "thash.h" + +/** + * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. + */ +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in) { + int i; + + /* Iterate over out in decreasing order, for big-endianness. */ + for (i = (signed int)outlen - 1; i >= 0; i--) { + out[i] = in & 0xff; + in = in >> 8; + } +} + +void u32_to_bytes(unsigned char *out, uint32_t in) { + out[0] = (unsigned char)(in >> 24); + out[1] = (unsigned char)(in >> 16); + out[2] = (unsigned char)(in >> 8); + out[3] = (unsigned char)in; +} + +/** + * Converts the inlen bytes in 'in' from big-endian byte order to an integer. + */ +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { + unsigned long long retval = 0; + unsigned int i; + + for (i = 0; i < inlen; i++) { + retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); + } + return retval; +} + +/** + * Computes a root node given a leaf and an auth path. + * Expects address to be complete other than the tree_height and tree_index. + */ +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]) { + uint32_t i; + unsigned char buffer[2 * SPX_N]; + + /* If leaf_idx is odd (last bit = 1), current path element is a right child + and auth_path has to go left. Otherwise it is the other way around. */ + if (leaf_idx & 1) { + memcpy(buffer + SPX_N, leaf, SPX_N); + memcpy(buffer, auth_path, SPX_N); + } else { + memcpy(buffer, leaf, SPX_N); + memcpy(buffer + SPX_N, auth_path, SPX_N); + } + auth_path += SPX_N; + + for (i = 0; i < tree_height - 1; i++) { + leaf_idx >>= 1; + idx_offset >>= 1; + /* Set the address of the node we're creating. */ + set_tree_height(addr, i + 1); + set_tree_index(addr, leaf_idx + idx_offset); + + /* Pick the right or left neighbor, depending on parity of the node. */ + if (leaf_idx & 1) { + thash(buffer + SPX_N, buffer, 2, ctx, addr); + memcpy(buffer, auth_path, SPX_N); + } else { + thash(buffer, buffer, 2, ctx, addr); + memcpy(buffer + SPX_N, auth_path, SPX_N); + } + auth_path += SPX_N; + } + + /* The last iteration is exceptional; we do not copy an auth_path node. */ + leaf_idx >>= 1; + idx_offset >>= 1; + set_tree_height(addr, tree_height); + set_tree_index(addr, leaf_idx + idx_offset); + thash(root, buffer, 2, ctx, addr); +} + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx * /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]) { + PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); + PQCLEAN_VLA(unsigned int, heights, tree_height + 1); + unsigned int offset = 0; + uint32_t idx; + uint32_t tree_idx; + + for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { + /* Add the next leaf node to the stack. */ + gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); + offset++; + heights[offset - 1] = 0; + + /* If this is a node we need for the auth path.. */ + if ((leaf_idx ^ 0x1) == idx) { + memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); + } + + /* While the top-most nodes are of equal height.. */ + while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { + /* Compute index of the new node, in the next layer. */ + tree_idx = (idx >> (heights[offset - 1] + 1)); + + /* Set the address of the node we're creating. */ + set_tree_height(tree_addr, heights[offset - 1] + 1); + set_tree_index(tree_addr, + tree_idx + (idx_offset >> (heights[offset - 1] + 1))); + /* Hash the top-most nodes from the stack together. */ + thash(stack + (offset - 2)*SPX_N, + stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); + offset--; + /* Note that the top-most node is now one layer higher. */ + heights[offset - 1]++; + + /* If this is a node we need for the auth path.. */ + if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { + memcpy(auth_path + heights[offset - 1]*SPX_N, + stack + (offset - 1)*SPX_N, SPX_N); + } + } + } + memcpy(root, stack, SPX_N); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/utils.h b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/utils.h new file mode 100644 index 0000000000..64f5d5a53a --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/utils.h @@ -0,0 +1,58 @@ +#ifndef SPX_UTILS_H +#define SPX_UTILS_H + +#include + +#include "compat.h" +#include "context.h" +#include "params.h" + + +/* To support MSVC use alloca() instead of VLAs. See #20. */ + + +/** + * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. + */ +#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in); +#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) +void u32_to_bytes(unsigned char *out, uint32_t in); + +/** + * Converts the inlen bytes in 'in' from big-endian byte order to an integer. + */ +#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); + +/** + * Computes a root node given a leaf and an auth path. + * Expects address to be complete other than the tree_height and tree_index. + */ +#define compute_root SPX_NAMESPACE(compute_root) +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]); + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +#define treehash SPX_NAMESPACE(treehash) +void treehash(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx *ctx /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]); + + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/utilsx8.c b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/utilsx8.c new file mode 100644 index 0000000000..f044b9595d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/utilsx8.c @@ -0,0 +1,146 @@ +#include + +#include "utils.h" +#include "utilsx8.h" + +#include "address.h" +#include "params.h" +#include "thashx8.h" + +/* + * Generate the entire Merkle tree, computing the authentication path for leaf_idx, + * and the resulting root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) + * + * This expects tree_addrx8 to be initialized to 8 parallel addr structures for + * the Merkle tree nodes + * + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + * + * This works by using the standard Merkle tree building algorithm, except + * that each 'node' tracked is actually 8 consecutive nodes in the real tree. + * When we combine two logical nodes ABCDEFGH and STUVWXYZ, we perform the H + * operation on adjacent real nodes, forming the parent logical node + * (AB)(CD)(EF)(GH)(ST)(UV)(WX)(YZ) + * + * When we get to the top three levels of the real tree (where there is only + * one logical node), we continue this operation three more times; the right + * most real node will by the actual root (and the other 7 nodes will be + * garbage). We follow the same thashx8 logic so that the 'extract + * authentication path components' part of the loop is still executed (and + * to simplify the code somewhat) + * + * This currently assumes tree_height >= 3; I suspect that doing an adjusting + * idx, addr_idx on the gen_leafx8 call if tree_height < 3 would fix it; since + * we don't actually use such short trees, I haven't bothered + */ +void treehashx8(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, + uint32_t tree_height, + void (*gen_leafx8)( + unsigned char * /* Where to write the leaves */, + const spx_ctx *, + uint32_t idx, void *info), + uint32_t tree_addrx8[8 * 8], + void *info) { + /* This is where we keep the intermediate nodes */ + PQCLEAN_VLA(unsigned char, stackx8, tree_height * 8 * SPX_N); + uint32_t left_adj = 0, prev_left_adj = 0; /* When we're doing the top 3 */ + /* levels, the left-most part of the tree isn't at the beginning */ + /* of current[]. These give the offset of the actual start */ + + uint32_t idx; + uint32_t max_idx = ((uint32_t)1 << (tree_height - 3)) - 1; + for (idx = 0;; idx++) { + unsigned char current[8 * SPX_N]; /* Current logical node */ + gen_leafx8( current, ctx, 8 * idx + idx_offset, + info ); + + /* Now combine the freshly generated right node with previously */ + /* generated left ones */ + uint32_t internal_idx_offset = idx_offset; + uint32_t internal_idx = idx; + uint32_t internal_leaf = leaf_idx; + uint32_t h; /* The height we are in the Merkle tree */ + for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { + + /* Special processing if we're at the top of the tree */ + if (h >= tree_height - 3) { + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[7 * SPX_N], SPX_N ); + return; + } + /* The tree indexing logic is a bit off in this case */ + /* Adjust it so that the left-most node of the part of */ + /* the tree that we're processing has index 0 */ + prev_left_adj = left_adj; + left_adj = (uint32_t)(8 - (1 << (tree_height - h - 1))); + } + + /* Check if we hit the top of the tree */ + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[7 * SPX_N], SPX_N ); + return; + } + + /* + * Check if one of the nodes we have is a part of the + * authentication path; if it is, write it out + */ + if ((((internal_idx << 3) ^ internal_leaf) & ~0x7U) == 0) { + memcpy( &auth_path[ h * SPX_N ], + ¤t[(((internal_leaf & 7) ^ 1) + prev_left_adj) * SPX_N], + SPX_N ); + } + + /* + * Check if we're at a left child; if so, stop going up the stack + * Exception: if we've reached the end of the tree, keep on going + * (so we combine the last 8 nodes into the one root node in three + * more iterations) + */ + if ((internal_idx & 1) == 0 && idx < max_idx) { + break; + } + + /* Ok, we're at a right node (or doing the top 3 levels) */ + /* Now combine the left and right logical nodes together */ + + /* Set the address of the node we're creating. */ + uint32_t j; + internal_idx_offset >>= 1; + for (j = 0; j < 8; j++) { + set_tree_height(tree_addrx8 + j * 8, h + 1); + set_tree_index(tree_addrx8 + j * 8, + (8 / 2) * (internal_idx & ~1U) + j - left_adj + internal_idx_offset ); + } + unsigned char *left = &stackx8[h * 8 * SPX_N]; + thashx8( ¤t[0 * SPX_N], + ¤t[1 * SPX_N], + ¤t[2 * SPX_N], + ¤t[3 * SPX_N], + ¤t[4 * SPX_N], + ¤t[5 * SPX_N], + ¤t[6 * SPX_N], + ¤t[7 * SPX_N], + &left [0 * SPX_N], + &left [2 * SPX_N], + &left [4 * SPX_N], + &left [6 * SPX_N], + ¤t[0 * SPX_N], + ¤t[2 * SPX_N], + ¤t[4 * SPX_N], + ¤t[6 * SPX_N], + 2, ctx, tree_addrx8); + } + + /* We've hit a left child; save the current for when we get the */ + /* corresponding right right */ + memcpy( &stackx8[h * 8 * SPX_N], current, 8 * SPX_N); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/utilsx8.h b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/utilsx8.h new file mode 100644 index 0000000000..806d1e85be --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/utilsx8.h @@ -0,0 +1,29 @@ +#ifndef SPX_UTILSX8_H +#define SPX_UTILSX8_H + +#include + +#include "params.h" + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + * + * This implementation uses AVX to compute internal nodes 8 at a time (in + * parallel) + */ +#define treehashx8 SPX_NAMESPACE(treehashx8) +void treehashx8(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leafx8)( + unsigned char * /* Where to write the leaves */, + const spx_ctx * /* ctx */, + uint32_t addr_idx, void *info), + uint32_t tree_addrx8[8 * 8], void *info); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/wots.c b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/wots.c new file mode 100644 index 0000000000..689baf4db9 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/wots.c @@ -0,0 +1,291 @@ +#include +#include + +#include "wots.h" + +#include "address.h" +#include "hash.h" +#include "hashx8.h" +#include "params.h" +#include "thash.h" +#include "thashx8.h" +#include "utils.h" +#include "utilsx8.h" +#include "wotsx8.h" + +// TODO clarify address expectations, and make them more uniform. +// TODO i.e. do we expect types to be set already? +// TODO and do we expect modifications or copies? + +/** + * Computes up the chains + */ +static void gen_chains( + unsigned char *out, + const unsigned char *in, + unsigned int start[SPX_WOTS_LEN], + const unsigned int steps[SPX_WOTS_LEN], + const spx_ctx *ctx, + uint32_t addr[8]) { + uint32_t i, j, k, idx, watching; + int done; + unsigned char empty[SPX_N]; + unsigned char *bufs[8]; + uint32_t addrs[8 * 8]; + + int l; + uint16_t counts[SPX_WOTS_W] = { 0 }; + uint16_t idxs[SPX_WOTS_LEN]; + uint16_t total, newTotal; + + /* set addrs = {addr, addr, ..., addr} */ + for (j = 0; j < 8; j++) { + memcpy(addrs + j * 8, addr, sizeof(uint32_t) * 8); + } + + /* Initialize out with the value at position 'start'. */ + memcpy(out, in, SPX_WOTS_LEN * SPX_N); + + /* Sort the chains in reverse order by steps using counting sort. */ + for (i = 0; i < SPX_WOTS_LEN; i++) { + counts[steps[i]]++; + } + total = 0; + for (l = SPX_WOTS_W - 1; l >= 0; l--) { + newTotal = counts[l] + total; + counts[l] = total; + total = newTotal; + } + for (i = 0; i < SPX_WOTS_LEN; i++) { + idxs[counts[steps[i]]] = (uint16_t)i; + counts[steps[i]]++; + } + + /* We got our work cut out for us: do it! */ + for (i = 0; i < SPX_WOTS_LEN; i += 8) { + for (j = 0; j < 8 && i + j < SPX_WOTS_LEN; j++) { + idx = idxs[i + j]; + set_chain_addr(addrs + j * 8, idx); + bufs[j] = out + SPX_N * idx; + } + + /* As the chains are sorted in reverse order, we know that the first + * chain is the longest and the last one is the shortest. We keep + * an eye on whether the last chain is done and then on the one before, + * et cetera. */ + watching = 7; + done = 0; + while (i + watching >= SPX_WOTS_LEN) { + bufs[watching] = &empty[0]; + watching--; + } + + for (k = 0;; k++) { + while (k == steps[idxs[i + watching]]) { + bufs[watching] = &empty[0]; + if (watching == 0) { + done = 1; + break; + } + watching--; + } + if (done) { + break; + } + for (j = 0; j < watching + 1; j++) { + set_hash_addr(addrs + j * 8, k + start[idxs[i + j]]); + } + + thashx8(bufs[0], bufs[1], bufs[2], bufs[3], + bufs[4], bufs[5], bufs[6], bufs[7], + bufs[0], bufs[1], bufs[2], bufs[3], + bufs[4], bufs[5], bufs[6], bufs[7], 1, ctx, addrs); + } + } +} + +/** + * base_w algorithm as described in draft. + * Interprets an array of bytes as integers in base w. + * This only works when log_w is a divisor of 8. + */ +static void base_w(unsigned int *output, const int out_len, + const unsigned char *input) { + int in = 0; + int out = 0; + unsigned char total = 0; + int bits = 0; + int consumed; + + for (consumed = 0; consumed < out_len; consumed++) { + if (bits == 0) { + total = input[in]; + in++; + bits += 8; + } + bits -= SPX_WOTS_LOGW; + output[out] = (total >> bits) & (SPX_WOTS_W - 1); + out++; + } +} + +/* Computes the WOTS+ checksum over a message (in base_w). */ +static void wots_checksum(unsigned int *csum_base_w, + const unsigned int *msg_base_w) { + unsigned int csum = 0; + unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; + unsigned int i; + + /* Compute checksum. */ + for (i = 0; i < SPX_WOTS_LEN1; i++) { + csum += SPX_WOTS_W - 1 - msg_base_w[i]; + } + + /* Convert checksum to base_w. */ + /* Make sure expected empty zero bits are the least significant bits. */ + csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); + ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); + base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); +} + +/* Takes a message and derives the matching chain lengths. */ +void chain_lengths(unsigned int *lengths, const unsigned char *msg) { + base_w(lengths, SPX_WOTS_LEN1, msg); + wots_checksum(lengths + SPX_WOTS_LEN1, lengths); +} + +/** + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. + * + * Writes the computed public key to 'pk'. + */ +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]) { + unsigned int steps[SPX_WOTS_LEN]; + unsigned int start[SPX_WOTS_LEN]; + uint32_t i; + + chain_lengths(start, msg); + + for (i = 0; i < SPX_WOTS_LEN; i++) { + steps[i] = SPX_WOTS_W - 1 - start[i]; + } + + gen_chains(pk, sig, start, steps, ctx, addr); +} + +/* + * This generates 8 sequential WOTS public keys + * It also generates the WOTS signature if leaf_info indicates + * that we're signing with one of these WOTS keys + */ +void wots_gen_leafx8(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info) { + struct leaf_info_x8 *info = v_info; + uint32_t *leaf_addr = info->leaf_addr; + uint32_t *pk_addr = info->pk_addr; + unsigned int i, j, k; + unsigned char pk_buffer[ 8 * SPX_WOTS_BYTES ]; + unsigned wots_offset = SPX_WOTS_BYTES; + unsigned char *buffer; + uint32_t wots_k_mask; + unsigned wots_sign_index; + + if (((leaf_idx ^ info->wots_sign_leaf) & ~7U) == 0) { + /* We're traversing the leaf that's signing; generate the WOTS */ + /* signature */ + wots_k_mask = 0; + wots_sign_index = info->wots_sign_leaf & 7; /* Which of of the 8 */ + /* slots do the signatures come from */ + } else { + /* Nope, we're just generating pk's; turn off the signature logic */ + wots_k_mask = ~0U; + wots_sign_index = 0; + } + + for (j = 0; j < 8; j++) { + set_keypair_addr( leaf_addr + j * 8, leaf_idx + j ); + set_keypair_addr( pk_addr + j * 8, leaf_idx + j ); + } + + for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { + uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k */ + /* to the step if we're generating a signature, ~0 if we're not */ + + /* Start with the secret seed */ + for (j = 0; j < 8; j++) { + set_chain_addr(leaf_addr + j * 8, i); + set_hash_addr(leaf_addr + j * 8, 0); + set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTSPRF); + } + prf_addrx8(buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + buffer + 2 * wots_offset, + buffer + 3 * wots_offset, + buffer + 4 * wots_offset, + buffer + 5 * wots_offset, + buffer + 6 * wots_offset, + buffer + 7 * wots_offset, + ctx, leaf_addr); + + for (j = 0; j < 8; j++) { + set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTS); + } + + /* Iterate down the WOTS chain */ + for (k = 0;; k++) { + /* Check if one of the values we have needs to be saved as a */ + /* part of the WOTS signature */ + if (k == wots_k) { + memcpy( info->wots_sig + i * SPX_N, + buffer + wots_sign_index * wots_offset, SPX_N ); + } + + /* Check if we hit the top of the chain */ + if (k == SPX_WOTS_W - 1) { + break; + } + + /* Iterate one step on all 8 chains */ + for (j = 0; j < 8; j++) { + set_hash_addr(leaf_addr + j * 8, k); + } + thashx8(buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + buffer + 2 * wots_offset, + buffer + 3 * wots_offset, + buffer + 4 * wots_offset, + buffer + 5 * wots_offset, + buffer + 6 * wots_offset, + buffer + 7 * wots_offset, + buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + buffer + 2 * wots_offset, + buffer + 3 * wots_offset, + buffer + 4 * wots_offset, + buffer + 5 * wots_offset, + buffer + 6 * wots_offset, + buffer + 7 * wots_offset, 1, ctx, leaf_addr); + } + } + + /* Do the final thash to generate the public keys */ + thashx8(dest + 0 * SPX_N, + dest + 1 * SPX_N, + dest + 2 * SPX_N, + dest + 3 * SPX_N, + dest + 4 * SPX_N, + dest + 5 * SPX_N, + dest + 6 * SPX_N, + dest + 7 * SPX_N, + pk_buffer + 0 * wots_offset, + pk_buffer + 1 * wots_offset, + pk_buffer + 2 * wots_offset, + pk_buffer + 3 * wots_offset, + pk_buffer + 4 * wots_offset, + pk_buffer + 5 * wots_offset, + pk_buffer + 6 * wots_offset, + pk_buffer + 7 * wots_offset, SPX_WOTS_LEN, ctx, pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/wots.h b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/wots.h new file mode 100644 index 0000000000..4e7692eeef --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/wots.h @@ -0,0 +1,25 @@ +#ifndef SPX_WOTS_H +#define SPX_WOTS_H + +#include + +#include "context.h" +#include "params.h" + +/** + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. + * + * Writes the computed public key to 'pk'. + */ +#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]); + +/* + * Compute the chain lengths needed for a given message hash + */ +#define chain_lengths SPX_NAMESPACE(chain_lengths) +void chain_lengths(unsigned int *lengths, const unsigned char *msg); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/wotsx8.h b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/wotsx8.h new file mode 100644 index 0000000000..10866efb35 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/wotsx8.h @@ -0,0 +1,42 @@ +#ifndef WOTSX8_H_ +#define WOTSX8_H_ + +#include + +#include "context.h" +#include "params.h" + +/* + * This is here to provide an interface to the internal wots_gen_leafx8 + * routine. While this routine is not referenced in the package outside of + * wots.c, it is called from the stand-alone benchmark code to characterize + * the performance + */ +struct leaf_info_x8 { + unsigned char *wots_sig; + uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ + uint32_t *wots_steps; + uint32_t leaf_addr[8 * 8]; + uint32_t pk_addr[8 * 8]; +}; + +/* Macro to set the leaf_info to something 'benign', that is, it would */ +/* run with the same time as it does during the real signing process */ +/* Used only by the benchmark code */ +#define INITIALIZE_LEAF_INFO_X8(info, addr, step_buffer) { \ + (info).wots_sig = 0; \ + (info).wots_sign_leaf = ~0; \ + (info).wots_steps = step_buffer; \ + int i; \ + for (i=0; i<8; i++) { \ + memcpy( &(info).leaf_addr[8*i], addr, 32 ); \ + memcpy( &(info).pk_addr[8*i], addr, 32 ); \ + } \ + } + +#define wots_gen_leafx8 SPX_NAMESPACE(wots_gen_leafx8) +void wots_gen_leafx8(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info); + +#endif /* WOTSX8_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/LICENSE b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/LICENSE new file mode 100644 index 0000000000..670154e353 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/LICENSE @@ -0,0 +1,116 @@ +CC0 1.0 Universal + +Statement of Purpose + +The laws of most jurisdictions throughout the world automatically confer +exclusive Copyright and Related Rights (defined below) upon the creator and +subsequent owner(s) (each and all, an "owner") of an original work of +authorship and/or a database (each, a "Work"). + +Certain owners wish to permanently relinquish those rights to a Work for the +purpose of contributing to a commons of creative, cultural and scientific +works ("Commons") that the public can reliably and without fear of later +claims of infringement build upon, modify, incorporate in other works, reuse +and redistribute as freely as possible in any form whatsoever and for any +purposes, including without limitation commercial purposes. These owners may +contribute to the Commons to promote the ideal of a free culture and the +further production of creative, cultural and scientific works, or to gain +reputation or greater distribution for their Work in part through the use and +efforts of others. + +For these and/or other purposes and motivations, and without any expectation +of additional consideration or compensation, the person associating CC0 with a +Work (the "Affirmer"), to the extent that he or she is an owner of Copyright +and Related Rights in the Work, voluntarily elects to apply CC0 to the Work +and publicly distribute the Work under its terms, with knowledge of his or her +Copyright and Related Rights in the Work and the meaning and intended legal +effect of CC0 on those rights. + +1. Copyright and Related Rights. A Work made available under CC0 may be +protected by copyright and related or neighboring rights ("Copyright and +Related Rights"). Copyright and Related Rights include, but are not limited +to, the following: + + i. the right to reproduce, adapt, distribute, perform, display, communicate, + and translate a Work; + + ii. moral rights retained by the original author(s) and/or performer(s); + + iii. publicity and privacy rights pertaining to a person's image or likeness + depicted in a Work; + + iv. rights protecting against unfair competition in regards to a Work, + subject to the limitations in paragraph 4(a), below; + + v. rights protecting the extraction, dissemination, use and reuse of data in + a Work; + + vi. database rights (such as those arising under Directive 96/9/EC of the + European Parliament and of the Council of 11 March 1996 on the legal + protection of databases, and under any national implementation thereof, + including any amended or successor version of such directive); and + + vii. other similar, equivalent or corresponding rights throughout the world + based on applicable law or treaty, and any national implementations thereof. + +2. Waiver. To the greatest extent permitted by, but not in contravention of, +applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and +unconditionally waives, abandons, and surrenders all of Affirmer's Copyright +and Related Rights and associated claims and causes of action, whether now +known or unknown (including existing as well as future claims and causes of +action), in the Work (i) in all territories worldwide, (ii) for the maximum +duration provided by applicable law or treaty (including future time +extensions), (iii) in any current or future medium and for any number of +copies, and (iv) for any purpose whatsoever, including without limitation +commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes +the Waiver for the benefit of each member of the public at large and to the +detriment of Affirmer's heirs and successors, fully intending that such Waiver +shall not be subject to revocation, rescission, cancellation, termination, or +any other legal or equitable action to disrupt the quiet enjoyment of the Work +by the public as contemplated by Affirmer's express Statement of Purpose. + +3. Public License Fallback. Should any part of the Waiver for any reason be +judged legally invalid or ineffective under applicable law, then the Waiver +shall be preserved to the maximum extent permitted taking into account +Affirmer's express Statement of Purpose. In addition, to the extent the Waiver +is so judged Affirmer hereby grants to each affected person a royalty-free, +non transferable, non sublicensable, non exclusive, irrevocable and +unconditional license to exercise Affirmer's Copyright and Related Rights in +the Work (i) in all territories worldwide, (ii) for the maximum duration +provided by applicable law or treaty (including future time extensions), (iii) +in any current or future medium and for any number of copies, and (iv) for any +purpose whatsoever, including without limitation commercial, advertising or +promotional purposes (the "License"). The License shall be deemed effective as +of the date CC0 was applied by Affirmer to the Work. Should any part of the +License for any reason be judged legally invalid or ineffective under +applicable law, such partial invalidity or ineffectiveness shall not +invalidate the remainder of the License, and in such case Affirmer hereby +affirms that he or she will not (i) exercise any of his or her remaining +Copyright and Related Rights in the Work or (ii) assert any associated claims +and causes of action with respect to the Work, in either case contrary to +Affirmer's express Statement of Purpose. + +4. Limitations and Disclaimers. + + a. No trademark or patent rights held by Affirmer are waived, abandoned, + surrendered, licensed or otherwise affected by this document. + + b. Affirmer offers the Work as-is and makes no representations or warranties + of any kind concerning the Work, express, implied, statutory or otherwise, + including without limitation warranties of title, merchantability, fitness + for a particular purpose, non infringement, or the absence of latent or + other defects, accuracy, or the present or absence of errors, whether or not + discoverable, all to the greatest extent permissible under applicable law. + + c. Affirmer disclaims responsibility for clearing rights of other persons + that may apply to the Work or any use thereof, including without limitation + any person's Copyright and Related Rights in the Work. Further, Affirmer + disclaims responsibility for obtaining any necessary consents, permissions + or other rights required for any use of the Work. + + d. Affirmer understands and acknowledges that Creative Commons is not a + party to this document and has no duty or obligation with respect to this + CC0 or use of the Work. + +For more information, please see + diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/address.c b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/address.c new file mode 100644 index 0000000000..d49d9f3b6b --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/address.c @@ -0,0 +1,95 @@ +#include +#include + +#include "address.h" +#include "params.h" +#include "utils.h" + +/* + * Specify which level of Merkle tree (the "layer") we're working on + */ +void set_layer_addr(uint32_t addr[8], uint32_t layer) { + ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; +} + +/* + * Specify which Merkle tree within the level (the "tree address") we're working on + */ +void set_tree_addr(uint32_t addr[8], uint64_t tree) { + ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); +} + +/* + * Specify the reason we'll use this address structure for, that is, what + * hash will we compute with it. This is used so that unrelated types of + * hashes don't accidentally get the same address structure. The type will be + * one of the SPX_ADDR_TYPE constants + */ +void set_type(uint32_t addr[8], uint32_t type) { + ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; +} + +/* + * Copy the layer and tree fields of the address structure. This is used + * when we're doing multiple types of hashes within the same Merkle tree + */ +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); +} + +/* These functions are used for OTS addresses. */ + +/* + * Specify which Merkle leaf we're working on; that is, which OTS keypair + * we're talking about. + */ +void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { + /* We have > 256 OTS at the bottom of the Merkle tree; to specify */ + /* which one, we'd need to express it in two bytes */ + ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR2] = (unsigned char)(keypair >> 8); + ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; +} + +/* + * Copy the layer, tree and keypair fields of the address structure. This is + * used when we're doing multiple things within the same OTS keypair + */ +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); + ((unsigned char *)out)[SPX_OFFSET_KP_ADDR2] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR2]; + ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; +} + +/* + * Specify which Merkle chain within the OTS we're working with + * (the chain address) + */ +void set_chain_addr(uint32_t addr[8], uint32_t chain) { + ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; +} + +/* + * Specify where in the Merkle chain we are +* (the hash address) + */ +void set_hash_addr(uint32_t addr[8], uint32_t hash) { + ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; +} + +/* These functions are used for all hash tree addresses (including FORS). */ + +/* + * Specify the height of the node in the Merkle/FORS tree we are in + * (the tree height) + */ +void set_tree_height(uint32_t addr[8], uint32_t tree_height) { + ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; +} + +/* + * Specify the distance from the left edge of the node in the Merkle/FORS tree + * (the tree index) + */ +void set_tree_index(uint32_t addr[8], uint32_t tree_index) { + u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/address.h b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/address.h new file mode 100644 index 0000000000..24a84eb40c --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/address.h @@ -0,0 +1,52 @@ +#ifndef SPX_ADDRESS_H +#define SPX_ADDRESS_H + +#include + +#include "params.h" + +/* The hash types that are passed to set_type */ +#define SPX_ADDR_TYPE_WOTS 0 +#define SPX_ADDR_TYPE_WOTSPK 1 +#define SPX_ADDR_TYPE_HASHTREE 2 +#define SPX_ADDR_TYPE_FORSTREE 3 +#define SPX_ADDR_TYPE_FORSPK 4 +#define SPX_ADDR_TYPE_WOTSPRF 5 +#define SPX_ADDR_TYPE_FORSPRF 6 + +#define set_layer_addr SPX_NAMESPACE(set_layer_addr) +void set_layer_addr(uint32_t addr[8], uint32_t layer); + +#define set_tree_addr SPX_NAMESPACE(set_tree_addr) +void set_tree_addr(uint32_t addr[8], uint64_t tree); + +#define set_type SPX_NAMESPACE(set_type) +void set_type(uint32_t addr[8], uint32_t type); + +/* Copies the layer and tree part of one address into the other */ +#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); + +/* These functions are used for WOTS and FORS addresses. */ + +#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) +void set_keypair_addr(uint32_t addr[8], uint32_t keypair); + +#define set_chain_addr SPX_NAMESPACE(set_chain_addr) +void set_chain_addr(uint32_t addr[8], uint32_t chain); + +#define set_hash_addr SPX_NAMESPACE(set_hash_addr) +void set_hash_addr(uint32_t addr[8], uint32_t hash); + +#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); + +/* These functions are used for all hash tree addresses (including FORS). */ + +#define set_tree_height SPX_NAMESPACE(set_tree_height) +void set_tree_height(uint32_t addr[8], uint32_t tree_height); + +#define set_tree_index SPX_NAMESPACE(set_tree_index) +void set_tree_index(uint32_t addr[8], uint32_t tree_index); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/api.h b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/api.h new file mode 100644 index 0000000000..1c0a4f8659 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/api.h @@ -0,0 +1,77 @@ +#ifndef PQCLEAN_SPHINCSSHA2128SROBUST_CLEAN_API_H +#define PQCLEAN_SPHINCSSHA2128SROBUST_CLEAN_API_H + +#include +#include + +#define PQCLEAN_SPHINCSSHA2128SROBUST_CLEAN_CRYPTO_ALGNAME "SPHINCS+-sha2-128s-robust" + +#define PQCLEAN_SPHINCSSHA2128SROBUST_CLEAN_CRYPTO_SECRETKEYBYTES 64 +#define PQCLEAN_SPHINCSSHA2128SROBUST_CLEAN_CRYPTO_PUBLICKEYBYTES 32 +#define PQCLEAN_SPHINCSSHA2128SROBUST_CLEAN_CRYPTO_BYTES 7856 + +#define PQCLEAN_SPHINCSSHA2128SROBUST_CLEAN_CRYPTO_SEEDBYTES 48 + +/* + * Returns the length of a secret key, in bytes + */ +size_t PQCLEAN_SPHINCSSHA2128SROBUST_CLEAN_crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +size_t PQCLEAN_SPHINCSSHA2128SROBUST_CLEAN_crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +size_t PQCLEAN_SPHINCSSHA2128SROBUST_CLEAN_crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +size_t PQCLEAN_SPHINCSSHA2128SROBUST_CLEAN_crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +int PQCLEAN_SPHINCSSHA2128SROBUST_CLEAN_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +int PQCLEAN_SPHINCSSHA2128SROBUST_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +int PQCLEAN_SPHINCSSHA2128SROBUST_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +int PQCLEAN_SPHINCSSHA2128SROBUST_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, + const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +int PQCLEAN_SPHINCSSHA2128SROBUST_CLEAN_crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +int PQCLEAN_SPHINCSSHA2128SROBUST_CLEAN_crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/context.h b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/context.h new file mode 100644 index 0000000000..27effb3e10 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/context.h @@ -0,0 +1,26 @@ +#ifndef SPX_CONTEXT_H +#define SPX_CONTEXT_H + +#include +#include + +#include "params.h" +#include "sha2.h" + +typedef struct { + uint8_t pub_seed[SPX_N]; + uint8_t sk_seed[SPX_N]; + + // sha256 state that absorbed pub_seed + sha256ctx state_seeded; + + +} spx_ctx; + +#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) +void initialize_hash_function(spx_ctx *ctx); + +#define free_hash_function SPX_NAMESPACE(free_hash_function) +void free_hash_function(spx_ctx *ctx); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/context_sha2.c b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/context_sha2.c new file mode 100644 index 0000000000..64f7e65465 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/context_sha2.c @@ -0,0 +1,33 @@ +#include "context.h" + +/** + * Absorb the constant pub_seed using one round of the compression function + * This initializes state_seeded and state_seeded_512, which can then be + * reused in thash + **/ +static void seed_state(spx_ctx *ctx) { + uint8_t block[SPX_SHA512_BLOCK_BYTES]; + size_t i; + + for (i = 0; i < SPX_N; ++i) { + block[i] = ctx->pub_seed[i]; + } + for (i = SPX_N; i < SPX_SHA512_BLOCK_BYTES; ++i) { + block[i] = 0; + } + /* block has been properly initialized for both SHA-256 and SHA-512 */ + + sha256_inc_init(&ctx->state_seeded); + sha256_inc_blocks(&ctx->state_seeded, block, 1); +} + + +/* We initialize the state for the hash functions */ +void initialize_hash_function(spx_ctx *ctx) { + seed_state(ctx); +} + +/* Free the incremental hashing context for heap-based SHA2 APIs */ +void free_hash_function(spx_ctx *ctx) { + sha256_inc_ctx_release(&ctx->state_seeded); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/fors.c b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/fors.c new file mode 100644 index 0000000000..96ca72e986 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/fors.c @@ -0,0 +1,156 @@ +#include +#include +#include + +#include "fors.h" + +#include "address.h" +#include "hash.h" +#include "thash.h" +#include "utils.h" +#include "utilsx1.h" + +static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + prf_addr(sk, ctx, fors_leaf_addr); +} + +static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, + const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + thash(leaf, sk, 1, ctx, fors_leaf_addr); +} + +struct fors_gen_leaf_info { + uint32_t leaf_addrx[8]; +}; + +static void fors_gen_leafx1(unsigned char *leaf, + const spx_ctx *ctx, + uint32_t addr_idx, void *info) { + struct fors_gen_leaf_info *fors_info = info; + uint32_t *fors_leaf_addr = fors_info->leaf_addrx; + + /* Only set the parts that the caller doesn't set */ + set_tree_index(fors_leaf_addr, addr_idx); + set_type(fors_leaf_addr, SPX_ADDR_TYPE_FORSPRF); + fors_gen_sk(leaf, ctx, fors_leaf_addr); + + set_type(fors_leaf_addr, SPX_ADDR_TYPE_FORSTREE); + fors_sk_to_leaf(leaf, leaf, + ctx, fors_leaf_addr); +} + +/** + * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + * Assumes indices has space for SPX_FORS_TREES integers. + */ +static void message_to_indices(uint32_t *indices, const unsigned char *m) { + unsigned int i, j; + unsigned int offset = 0; + + for (i = 0; i < SPX_FORS_TREES; i++) { + indices[i] = 0; + for (j = 0; j < SPX_FORS_HEIGHT; j++) { + indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); + offset++; + } + } +} + +/** + * Signs a message m, deriving the secret key from sk_seed and the FTS address. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + uint32_t fors_tree_addr[8] = {0}; + struct fors_gen_leaf_info fors_info = {0}; + uint32_t *fors_leaf_addr = fors_info.leaf_addrx; + uint32_t fors_pk_addr[8] = {0}; + uint32_t idx_offset; + unsigned int i; + + copy_keypair_addr(fors_tree_addr, fors_addr); + copy_keypair_addr(fors_leaf_addr, fors_addr); + + copy_keypair_addr(fors_pk_addr, fors_addr); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); + + message_to_indices(indices, m); + + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); + + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); + + /* Include the secret key part that produces the selected leaf node. */ + fors_gen_sk(sig, ctx, fors_tree_addr); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + sig += SPX_N; + + /* Compute the authentication path for this leaf node. */ + treehashx1(roots + i * SPX_N, sig, ctx, + indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx1, + fors_tree_addr, &fors_info); + + sig += SPX_N * SPX_FORS_HEIGHT; + } + + /* Hash horizontally across all tree roots to derive the public key. */ + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); +} + +/** + * Derives the FORS public key from a signature. + * This can be used for verification by comparing to a known public key, or to + * subsequently verify a signature on the derived public key. The latter is the + * typical use-case when used as an FTS below an OTS in a hypertree. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + unsigned char leaf[SPX_N]; + uint32_t fors_tree_addr[8] = {0}; + uint32_t fors_pk_addr[8] = {0}; + uint32_t idx_offset; + unsigned int i; + + copy_keypair_addr(fors_tree_addr, fors_addr); + copy_keypair_addr(fors_pk_addr, fors_addr); + + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); + + message_to_indices(indices, m); + + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); + + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + + /* Derive the leaf from the included secret key part. */ + fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); + sig += SPX_N; + + /* Derive the corresponding root node of this tree. */ + compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, + sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); + sig += SPX_N * SPX_FORS_HEIGHT; + } + + /* Hash horizontally across all tree roots to derive the public key. */ + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/fors.h b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/fors.h new file mode 100644 index 0000000000..509140a178 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/fors.h @@ -0,0 +1,32 @@ +#ifndef SPX_FORS_H +#define SPX_FORS_H + +#include + +#include "context.h" +#include "params.h" + +/** + * Signs a message m, deriving the secret key from sk_seed and the FTS address. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +#define fors_sign SPX_NAMESPACE(fors_sign) +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); + +/** + * Derives the FORS public key from a signature. + * This can be used for verification by comparing to a known public key, or to + * subsequently verify a signature on the derived public key. The latter is the + * typical use-case when used as an FTS below an OTS in a hypertree. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/hash.h b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/hash.h new file mode 100644 index 0000000000..ffe815f45d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/hash.h @@ -0,0 +1,37 @@ +#ifndef SPX_HASH_H +#define SPX_HASH_H + +#include +#include + +#include "context.h" +#include "params.h" + +#define prf_addr SPX_NAMESPACE(prf_addr) +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]); + +#define gen_message_random SPX_NAMESPACE(gen_message_random) +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); + +#define hash_message SPX_NAMESPACE(hash_message) +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); + + +# define SPX_SHA256_ADDR_BYTES 22 + +# define mgf1_256 SPX_NAMESPACE(mgf1_256) +void mgf1_256(unsigned char *out, unsigned long outlen, + const unsigned char *in, unsigned long inlen); + +# define mgf1_512 SPX_NAMESPACE(mgf1_512) +void mgf1_512(unsigned char *out, unsigned long outlen, + const unsigned char *in, unsigned long inlen); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/hash_sha2.c b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/hash_sha2.c new file mode 100644 index 0000000000..69f0dc0013 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/hash_sha2.c @@ -0,0 +1,219 @@ +#include +#include + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "sha2.h" +#include "utils.h" + + + +#define SPX_SHAX_OUTPUT_BYTES SPX_SHA256_OUTPUT_BYTES +#define SPX_SHAX_BLOCK_BYTES SPX_SHA256_BLOCK_BYTES +#define shaX_inc_init sha256_inc_init +#define shaX_inc_blocks sha256_inc_blocks +#define shaX_inc_finalize sha256_inc_finalize +#define shaX sha256 +#define mgf1_X mgf1_256 +#define shaXstate sha256ctx + +/** + * mgf1 function based on the SHA-256 hash function + * Note that inlen should be sufficiently small that it still allows for + * an array to be allocated on the stack. Typically 'in' is merely a seed. + * Outputs outlen number of bytes + */ +void mgf1_256(unsigned char *out, unsigned long outlen, + const unsigned char *in, unsigned long inlen) { + PQCLEAN_VLA(uint8_t, inbuf, inlen + 4); + unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES]; + uint32_t i; + + memcpy(inbuf, in, inlen); + + /* While we can fit in at least another full block of SHA256 output.. */ + for (i = 0; (i + 1)*SPX_SHA256_OUTPUT_BYTES <= outlen; i++) { + u32_to_bytes(inbuf + inlen, i); + sha256(out, inbuf, inlen + 4); + out += SPX_SHA256_OUTPUT_BYTES; + } + /* Until we cannot anymore, and we fill the remainder. */ + if (outlen > i * SPX_SHA256_OUTPUT_BYTES) { + u32_to_bytes(inbuf + inlen, i); + sha256(outbuf, inbuf, inlen + 4); + memcpy(out, outbuf, outlen - i * SPX_SHA256_OUTPUT_BYTES); + } +} + +/* + * mgf1 function based on the SHA-512 hash function + */ +void mgf1_512(unsigned char *out, unsigned long outlen, + const unsigned char *in, unsigned long inlen) { + PQCLEAN_VLA(uint8_t, inbuf, inlen + 4); + unsigned char outbuf[SPX_SHA512_OUTPUT_BYTES]; + uint32_t i; + + memcpy(inbuf, in, inlen); + + /* While we can fit in at least another full block of SHA512 output.. */ + for (i = 0; (i + 1)*SPX_SHA512_OUTPUT_BYTES <= outlen; i++) { + u32_to_bytes(inbuf + inlen, i); + sha512(out, inbuf, inlen + 4); + out += SPX_SHA512_OUTPUT_BYTES; + } + /* Until we cannot anymore, and we fill the remainder. */ + if (outlen > i * SPX_SHA512_OUTPUT_BYTES) { + u32_to_bytes(inbuf + inlen, i); + sha512(outbuf, inbuf, inlen + 4); + memcpy(out, outbuf, outlen - i * SPX_SHA512_OUTPUT_BYTES); + } +} + +/* + * Computes PRF(pk_seed, sk_seed, addr). + */ +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]) { + sha256ctx sha2_state; + unsigned char buf[SPX_SHA256_ADDR_BYTES + SPX_N]; + unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES]; + + /* Retrieve precomputed state containing pub_seed */ + sha256_inc_ctx_clone(&sha2_state, &ctx->state_seeded); + + /* Remainder: ADDR^c ‖ SK.seed */ + memcpy(buf, addr, SPX_SHA256_ADDR_BYTES); + memcpy(buf + SPX_SHA256_ADDR_BYTES, ctx->sk_seed, SPX_N); + + sha256_inc_finalize(outbuf, &sha2_state, buf, SPX_SHA256_ADDR_BYTES + SPX_N); + + memcpy(out, outbuf, SPX_N); +} + +/** + * Computes the message-dependent randomness R, using a secret seed as a key + * for HMAC, and an optional randomization value prefixed to the message. + * This requires m to have at least SPX_SHAX_BLOCK_BYTES + SPX_N space + * available in front of the pointer, i.e. before the message to use for the + * prefix. This is necessary to prevent having to move the message around (and + * allocate memory for it). + */ +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { + (void)ctx; + + unsigned char buf[SPX_SHAX_BLOCK_BYTES + SPX_SHAX_OUTPUT_BYTES]; + shaXstate state; + int i; + + + /* This implements HMAC-SHA */ + for (i = 0; i < SPX_N; i++) { + buf[i] = 0x36 ^ sk_prf[i]; + } + memset(buf + SPX_N, 0x36, SPX_SHAX_BLOCK_BYTES - SPX_N); + + shaX_inc_init(&state); + shaX_inc_blocks(&state, buf, 1); + + memcpy(buf, optrand, SPX_N); + + /* If optrand + message cannot fill up an entire block */ + if (SPX_N + mlen < SPX_SHAX_BLOCK_BYTES) { + memcpy(buf + SPX_N, m, mlen); + shaX_inc_finalize(buf + SPX_SHAX_BLOCK_BYTES, &state, + buf, mlen + SPX_N); + } + /* Otherwise first fill a block, so that finalize only uses the message */ + else { + memcpy(buf + SPX_N, m, SPX_SHAX_BLOCK_BYTES - SPX_N); + shaX_inc_blocks(&state, buf, 1); + + m += SPX_SHAX_BLOCK_BYTES - SPX_N; + mlen -= SPX_SHAX_BLOCK_BYTES - SPX_N; + shaX_inc_finalize(buf + SPX_SHAX_BLOCK_BYTES, &state, m, mlen); + } + + for (i = 0; i < SPX_N; i++) { + buf[i] = 0x5c ^ sk_prf[i]; + } + memset(buf + SPX_N, 0x5c, SPX_SHAX_BLOCK_BYTES - SPX_N); + + shaX(buf, buf, SPX_SHAX_BLOCK_BYTES + SPX_SHAX_OUTPUT_BYTES); + memcpy(R, buf, SPX_N); +} + +/** + * Computes the message hash using R, the public key, and the message. + * Outputs the message digest and the index of the leaf. The index is split in + * the tree index and the leaf index, for convenient copying to an address. + */ +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { + (void)ctx; +#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) +#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) +#define SPX_LEAF_BITS SPX_TREE_HEIGHT +#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) +#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) + + unsigned char seed[2 * SPX_N + SPX_SHAX_OUTPUT_BYTES]; + + /* Round to nearest multiple of SPX_SHAX_BLOCK_BYTES */ +#define SPX_INBLOCKS (((SPX_N + SPX_PK_BYTES + SPX_SHAX_BLOCK_BYTES - 1) & \ + -SPX_SHAX_BLOCK_BYTES) / SPX_SHAX_BLOCK_BYTES) + unsigned char inbuf[SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES]; + + unsigned char buf[SPX_DGST_BYTES]; + unsigned char *bufp = buf; + shaXstate state; + + shaX_inc_init(&state); + + // seed: SHA-X(R ‖ PK.seed ‖ PK.root ‖ M) + memcpy(inbuf, R, SPX_N); + memcpy(inbuf + SPX_N, pk, SPX_PK_BYTES); + + /* If R + pk + message cannot fill up an entire block */ + if (SPX_N + SPX_PK_BYTES + mlen < SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES) { + memcpy(inbuf + SPX_N + SPX_PK_BYTES, m, mlen); + shaX_inc_finalize(seed + 2 * SPX_N, &state, inbuf, SPX_N + SPX_PK_BYTES + mlen); + } + /* Otherwise first fill a block, so that finalize only uses the message */ + else { + memcpy(inbuf + SPX_N + SPX_PK_BYTES, m, + SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES - SPX_N - SPX_PK_BYTES); + shaX_inc_blocks(&state, inbuf, SPX_INBLOCKS); + + m += SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES - SPX_N - SPX_PK_BYTES; + mlen -= SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES - SPX_N - SPX_PK_BYTES; + shaX_inc_finalize(seed + 2 * SPX_N, &state, m, (size_t)mlen); + } + + // H_msg: MGF1-SHA-X(R ‖ PK.seed ‖ seed) + memcpy(seed, R, SPX_N); + memcpy(seed + SPX_N, pk, SPX_N); + + /* By doing this in two steps, we prevent hashing the message twice; + otherwise each iteration in MGF1 would hash the message again. */ + mgf1_X(bufp, SPX_DGST_BYTES, seed, 2 * SPX_N + SPX_SHAX_OUTPUT_BYTES); + + memcpy(digest, bufp, SPX_FORS_MSG_BYTES); + bufp += SPX_FORS_MSG_BYTES; + + + *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); + *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); + bufp += SPX_TREE_BYTES; + + *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); + *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); +} + + diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/merkle.c b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/merkle.c new file mode 100644 index 0000000000..0c1479fd93 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/merkle.c @@ -0,0 +1,59 @@ +#include +#include + +#include "address.h" +#include "merkle.h" +#include "params.h" +#include "utils.h" +#include "utilsx1.h" +#include "wots.h" +#include "wotsx1.h" + +/* + * This generates a Merkle signature (WOTS signature followed by the Merkle + * authentication path). This is in this file because most of the complexity + * is involved with the WOTS signature; the Merkle authentication path logic + * is mostly hidden in treehashx4 + */ +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf) { + unsigned char *auth_path = sig + SPX_WOTS_BYTES; + struct leaf_info_x1 info = { 0 }; + unsigned steps[ SPX_WOTS_LEN ]; + + info.wots_sig = sig; + chain_lengths(steps, root); + info.wots_steps = steps; + + set_type(&tree_addr[0], SPX_ADDR_TYPE_HASHTREE); + set_type(&info.pk_addr[0], SPX_ADDR_TYPE_WOTSPK); + copy_subtree_addr(&info.leaf_addr[0], wots_addr); + copy_subtree_addr(&info.pk_addr[0], wots_addr); + + info.wots_sign_leaf = idx_leaf; + + treehashx1(root, auth_path, ctx, + idx_leaf, 0, + SPX_TREE_HEIGHT, + wots_gen_leafx1, + tree_addr, &info); +} + +/* Compute root node of the top-most subtree. */ +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { + /* We do not need the auth path in key generation, but it simplifies the + code to have just one treehash routine that computes both root and path + in one function. */ + unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; + uint32_t top_tree_addr[8] = {0}; + uint32_t wots_addr[8] = {0}; + + set_layer_addr(top_tree_addr, SPX_D - 1); + set_layer_addr(wots_addr, SPX_D - 1); + + merkle_sign(auth_path, root, ctx, + wots_addr, top_tree_addr, + (uint32_t)~0 /* ~0 means "don't bother generating an auth path */ ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/merkle.h b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/merkle.h new file mode 100644 index 0000000000..769cf2e970 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/merkle.h @@ -0,0 +1,21 @@ +#ifndef MERKLE_H_ +#define MERKLE_H_ + +#include + +#include "context.h" +#include "params.h" + +/* Generate a Merkle signature (WOTS signature followed by the Merkle */ +/* authentication path) */ +#define merkle_sign SPX_NAMESPACE(merkle_sign) +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf); + +/* Compute the root node of the top-most subtree. */ +#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); + +#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/nistapi.h b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/nistapi.h new file mode 100644 index 0000000000..3cb71afad4 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/nistapi.h @@ -0,0 +1,87 @@ +#ifndef SPX_API_H +#define SPX_API_H + +#include +#include + +#include "params.h" + +#define CRYPTO_ALGNAME "SPHINCS+" + +#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES +#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES +#define CRYPTO_BYTES SPX_BYTES +#define CRYPTO_SEEDBYTES (3*SPX_N) + +/* + * Returns the length of a secret key, in bytes + */ +#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) +size_t crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) +size_t crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) +size_t crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) +size_t crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +#define crypto_sign SPX_NAMESPACE(crypto_sign) +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/params.h b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/params.h new file mode 100644 index 0000000000..14eb890bfb --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/params.h @@ -0,0 +1,61 @@ +#ifndef SPX_PARAMS_H +#define SPX_PARAMS_H + +#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSSHA2128SROBUST_CLEAN_##s + +/* Hash output length in bytes. */ +#define SPX_N 16 +/* Height of the hypertree. */ +#define SPX_FULL_HEIGHT 63 +/* Number of subtree layer. */ +#define SPX_D 7 +/* FORS tree dimensions. */ +#define SPX_FORS_HEIGHT 12 +#define SPX_FORS_TREES 14 +/* Winternitz parameter, */ +#define SPX_WOTS_W 16 + +/* The hash function is defined by linking a different hash.c file, as opposed + to setting a #define constant. */ + +/* This is a SHA2-based parameter set, hence whether we use SHA-256 + * exclusively or we use both SHA-256 and SHA-512 is controlled by + * the following #define */ +#define SPX_SHA512 0 /* Use SHA-256 for all hashes */ + +/* For clarity */ +#define SPX_ADDR_BYTES 32 + +/* WOTS parameters. */ +#define SPX_WOTS_LOGW 4 + +#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) + +/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ +#define SPX_WOTS_LEN2 3 + +#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) +#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) +#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES + +/* Subtree size. */ +#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) + +//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT +// #error SPX_D should always divide SPX_FULL_HEIGHT +//#endif + +/* FORS parameters. */ +#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) +#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) +#define SPX_FORS_PK_BYTES SPX_N + +/* Resulting SPX sizes. */ +#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ + SPX_FULL_HEIGHT * SPX_N) +#define SPX_PK_BYTES (2 * SPX_N) +#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) + +#include "sha2_offsets.h" + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/sha2_offsets.h b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/sha2_offsets.h new file mode 100644 index 0000000000..6e3584f7a4 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/sha2_offsets.h @@ -0,0 +1,27 @@ +#ifndef SHA2_OFFSETS_H_ +#define SHA2_OFFSETS_H_ + +#define SPX_SHA256_BLOCK_BYTES 64 +#define SPX_SHA256_OUTPUT_BYTES 32 + +#define SPX_SHA512_BLOCK_BYTES 128 +#define SPX_SHA512_OUTPUT_BYTES 64 + +/* + * Offsets of various fields in the address structure when we use SHA2 as + * the Sphincs+ hash function + */ + +#define SPX_OFFSET_LAYER 0 /* The byte used to specify the Merkle tree layer */ +#define SPX_OFFSET_TREE 1 /* The start of the 8 byte field used to specify the tree */ +#define SPX_OFFSET_TYPE 9 /* The byte used to specify the hash type (reason) */ +#define SPX_OFFSET_KP_ADDR2 12 /* The high byte used to specify the key pair (which one-time signature) */ +#define SPX_OFFSET_KP_ADDR1 13 /* The low byte used to specify the key pair */ +#define SPX_OFFSET_CHAIN_ADDR 17 /* The byte used to specify the chain address (which Winternitz chain) */ +#define SPX_OFFSET_HASH_ADDR 21 /* The byte used to specify the hash address (where in the Winternitz chain) */ +#define SPX_OFFSET_TREE_HGT 17 /* The byte used to specify the height of this node in the FORS or Merkle tree */ +#define SPX_OFFSET_TREE_INDEX 18 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ + +#define SPX_SHA2 1 + +#endif /* SHA2_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/sign.c b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/sign.c new file mode 100644 index 0000000000..9d0c7d1b22 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/sign.c @@ -0,0 +1,286 @@ +#include +#include +#include + +#include "address.h" +#include "context.h" +#include "fors.h" +#include "hash.h" +#include "merkle.h" +#include "nistapi.h" +#include "params.h" +#include "randombytes.h" +#include "thash.h" +#include "utils.h" +#include "wots.h" + +/* + * Returns the length of a secret key, in bytes + */ +size_t crypto_sign_secretkeybytes(void) { + return CRYPTO_SECRETKEYBYTES; +} + +/* + * Returns the length of a public key, in bytes + */ +size_t crypto_sign_publickeybytes(void) { + return CRYPTO_PUBLICKEYBYTES; +} + +/* + * Returns the length of a signature, in bytes + */ +size_t crypto_sign_bytes(void) { + return CRYPTO_BYTES; +} + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +size_t crypto_sign_seedbytes(void) { + return CRYPTO_SEEDBYTES; +} + +/* + * Generates an SPX key pair given a seed of length + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [PUB_SEED || root] + */ +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed) { + spx_ctx ctx; + + /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ + memcpy(sk, seed, CRYPTO_SEEDBYTES); + + memcpy(pk, sk + 2 * SPX_N, SPX_N); + + memcpy(ctx.pub_seed, pk, SPX_N); + memcpy(ctx.sk_seed, sk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + /* Compute root node of the top-most subtree. */ + merkle_gen_root(sk + 3 * SPX_N, &ctx); + + // cleanup + free_hash_function(&ctx); + + memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); + + return 0; +} + +/* + * Generates an SPX key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [PUB_SEED || root] + */ +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { + uint8_t seed[CRYPTO_SEEDBYTES]; + randombytes(seed, CRYPTO_SEEDBYTES); + crypto_sign_seed_keypair(pk, sk, seed); + + return 0; +} + +/** + * Returns an array containing a detached signature. + */ +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk) { + spx_ctx ctx; + + const uint8_t *sk_prf = sk + SPX_N; + const uint8_t *pk = sk + 2 * SPX_N; + + uint8_t optrand[SPX_N]; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t root[SPX_N]; + uint32_t i; + uint64_t tree; + uint32_t idx_leaf; + uint32_t wots_addr[8] = {0}; + uint32_t tree_addr[8] = {0}; + + memcpy(ctx.sk_seed, sk, SPX_N); + memcpy(ctx.pub_seed, pk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + + /* Optionally, signing can be made non-deterministic using optrand. + This can help counter side-channel attacks that would benefit from + getting a large number of traces when the signer uses the same nodes. */ + randombytes(optrand, SPX_N); + /* Compute the digest randomization value. */ + gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); + + /* Derive the message digest and leaf index from R, PK and M. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; + + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); + + /* Sign the message hash using FORS. */ + fors_sign(sig, root, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); + sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; + + /* Update the indices for the next layer. */ + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; + } + + free_hash_function(&ctx); + + *siglen = SPX_BYTES; + + return 0; +} + +/** + * Verifies a detached signature and message under a given public key. + */ +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk) { + spx_ctx ctx; + const uint8_t *pub_root = pk + SPX_N; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t wots_pk[SPX_WOTS_BYTES]; + uint8_t root[SPX_N]; + uint8_t leaf[SPX_N]; + unsigned int i; + uint64_t tree; + uint32_t idx_leaf; + uint32_t wots_addr[8] = {0}; + uint32_t tree_addr[8] = {0}; + uint32_t wots_pk_addr[8] = {0}; + + if (siglen != SPX_BYTES) { + return -1; + } + + memcpy(ctx.pub_seed, pk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); + + /* Derive the message digest and leaf index from R || PK || M. */ + /* The additional SPX_N is a result of the hash domain separator. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; + + /* Layer correctly defaults to 0, so no need to set_layer_addr */ + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); + + fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + /* For each subtree.. */ + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + copy_keypair_addr(wots_pk_addr, wots_addr); + + /* The WOTS public key is only correct if the signature was correct. */ + /* Initially, root is the FORS pk, but on subsequent iterations it is + the root of the subtree below the currently processed subtree. */ + wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); + sig += SPX_WOTS_BYTES; + + /* Compute the leaf node using the WOTS public key. */ + thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); + + /* Compute the root node of this subtree. */ + compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, + &ctx, tree_addr); + sig += SPX_TREE_HEIGHT * SPX_N; + + /* Update the indices for the next layer. */ + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; + } + + // cleanup + free_hash_function(&ctx); + + /* Check if the root node equals the root node in the public key. */ + if (memcmp(root, pub_root, SPX_N) != 0) { + return -1; + } + + return 0; +} + + +/** + * Returns an array containing the signature followed by the message. + */ +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk) { + size_t siglen; + + crypto_sign_signature(sm, &siglen, m, mlen, sk); + + memmove(sm + SPX_BYTES, m, mlen); + *smlen = siglen + mlen; + + return 0; +} + +/** + * Verifies a given signature-message pair under a given public key. + */ +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk) { + /* The API caller does not necessarily know what size a signature should be + but SPHINCS+ signatures are always exactly SPX_BYTES. */ + if (smlen < SPX_BYTES) { + memset(m, 0, smlen); + *mlen = 0; + return -1; + } + + *mlen = smlen - SPX_BYTES; + + if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { + memset(m, 0, smlen); + *mlen = 0; + return -1; + } + + /* If verification was successful, move the message to the right place. */ + memmove(m, sm + SPX_BYTES, *mlen); + + return 0; +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/thash.h b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/thash.h new file mode 100644 index 0000000000..8687ccfb4d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/thash.h @@ -0,0 +1,13 @@ +#ifndef SPX_THASH_H +#define SPX_THASH_H + +#include "context.h" +#include "params.h" + +#include + +#define thash SPX_NAMESPACE(thash) +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/thash_sha2_robust.c b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/thash_sha2_robust.c new file mode 100644 index 0000000000..18f65c2e42 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/thash_sha2_robust.c @@ -0,0 +1,39 @@ +#include +#include + +#include "address.h" +#include "context.h" +#include "hash.h" +#include "params.h" +#include "sha2.h" +#include "thash.h" +#include "utils.h" + + +/** + * Takes an array of inblocks concatenated arrays of SPX_N bytes. + */ +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]) { + unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES]; + PQCLEAN_VLA(uint8_t, bitmask, inblocks * SPX_N); + PQCLEAN_VLA(uint8_t, buf, SPX_N + SPX_SHA256_OUTPUT_BYTES + inblocks * SPX_N); + sha256ctx sha2_state; + unsigned int i; + + memcpy(buf, ctx->pub_seed, SPX_N); + memcpy(buf + SPX_N, addr, SPX_SHA256_ADDR_BYTES); + mgf1_256(bitmask, inblocks * SPX_N, buf, SPX_N + SPX_SHA256_ADDR_BYTES); + + /* Retrieve precomputed state containing pub_seed */ + sha256_inc_ctx_clone(&sha2_state, &ctx->state_seeded); + + for (i = 0; i < inblocks * SPX_N; i++) { + buf[SPX_N + SPX_SHA256_ADDR_BYTES + i] = in[i] ^ bitmask[i]; + } + + sha256_inc_finalize(outbuf, &sha2_state, buf + SPX_N, + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N); + memcpy(out, outbuf, SPX_N); +} + diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/utils.c b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/utils.c new file mode 100644 index 0000000000..177b541fb9 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/utils.c @@ -0,0 +1,148 @@ +#include + +#include "utils.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "thash.h" + +/** + * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. + */ +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in) { + int i; + + /* Iterate over out in decreasing order, for big-endianness. */ + for (i = (signed int)outlen - 1; i >= 0; i--) { + out[i] = in & 0xff; + in = in >> 8; + } +} + +void u32_to_bytes(unsigned char *out, uint32_t in) { + out[0] = (unsigned char)(in >> 24); + out[1] = (unsigned char)(in >> 16); + out[2] = (unsigned char)(in >> 8); + out[3] = (unsigned char)in; +} + +/** + * Converts the inlen bytes in 'in' from big-endian byte order to an integer. + */ +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { + unsigned long long retval = 0; + unsigned int i; + + for (i = 0; i < inlen; i++) { + retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); + } + return retval; +} + +/** + * Computes a root node given a leaf and an auth path. + * Expects address to be complete other than the tree_height and tree_index. + */ +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]) { + uint32_t i; + unsigned char buffer[2 * SPX_N]; + + /* If leaf_idx is odd (last bit = 1), current path element is a right child + and auth_path has to go left. Otherwise it is the other way around. */ + if (leaf_idx & 1) { + memcpy(buffer + SPX_N, leaf, SPX_N); + memcpy(buffer, auth_path, SPX_N); + } else { + memcpy(buffer, leaf, SPX_N); + memcpy(buffer + SPX_N, auth_path, SPX_N); + } + auth_path += SPX_N; + + for (i = 0; i < tree_height - 1; i++) { + leaf_idx >>= 1; + idx_offset >>= 1; + /* Set the address of the node we're creating. */ + set_tree_height(addr, i + 1); + set_tree_index(addr, leaf_idx + idx_offset); + + /* Pick the right or left neighbor, depending on parity of the node. */ + if (leaf_idx & 1) { + thash(buffer + SPX_N, buffer, 2, ctx, addr); + memcpy(buffer, auth_path, SPX_N); + } else { + thash(buffer, buffer, 2, ctx, addr); + memcpy(buffer + SPX_N, auth_path, SPX_N); + } + auth_path += SPX_N; + } + + /* The last iteration is exceptional; we do not copy an auth_path node. */ + leaf_idx >>= 1; + idx_offset >>= 1; + set_tree_height(addr, tree_height); + set_tree_index(addr, leaf_idx + idx_offset); + thash(root, buffer, 2, ctx, addr); +} + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx * /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]) { + PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); + PQCLEAN_VLA(unsigned int, heights, tree_height + 1); + unsigned int offset = 0; + uint32_t idx; + uint32_t tree_idx; + + for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { + /* Add the next leaf node to the stack. */ + gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); + offset++; + heights[offset - 1] = 0; + + /* If this is a node we need for the auth path.. */ + if ((leaf_idx ^ 0x1) == idx) { + memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); + } + + /* While the top-most nodes are of equal height.. */ + while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { + /* Compute index of the new node, in the next layer. */ + tree_idx = (idx >> (heights[offset - 1] + 1)); + + /* Set the address of the node we're creating. */ + set_tree_height(tree_addr, heights[offset - 1] + 1); + set_tree_index(tree_addr, + tree_idx + (idx_offset >> (heights[offset - 1] + 1))); + /* Hash the top-most nodes from the stack together. */ + thash(stack + (offset - 2)*SPX_N, + stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); + offset--; + /* Note that the top-most node is now one layer higher. */ + heights[offset - 1]++; + + /* If this is a node we need for the auth path.. */ + if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { + memcpy(auth_path + heights[offset - 1]*SPX_N, + stack + (offset - 1)*SPX_N, SPX_N); + } + } + } + memcpy(root, stack, SPX_N); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/utils.h b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/utils.h new file mode 100644 index 0000000000..64f5d5a53a --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/utils.h @@ -0,0 +1,58 @@ +#ifndef SPX_UTILS_H +#define SPX_UTILS_H + +#include + +#include "compat.h" +#include "context.h" +#include "params.h" + + +/* To support MSVC use alloca() instead of VLAs. See #20. */ + + +/** + * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. + */ +#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in); +#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) +void u32_to_bytes(unsigned char *out, uint32_t in); + +/** + * Converts the inlen bytes in 'in' from big-endian byte order to an integer. + */ +#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); + +/** + * Computes a root node given a leaf and an auth path. + * Expects address to be complete other than the tree_height and tree_index. + */ +#define compute_root SPX_NAMESPACE(compute_root) +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]); + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +#define treehash SPX_NAMESPACE(treehash) +void treehash(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx *ctx /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]); + + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/utilsx1.c b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/utilsx1.c new file mode 100644 index 0000000000..fccb69b35d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/utilsx1.c @@ -0,0 +1,100 @@ +#include + +#include "utilsx1.h" + +#include "address.h" +#include "params.h" +#include "thash.h" +#include "utils.h" + +/* + * Generate the entire Merkle tree, computing the authentication path for + * leaf_idx, and the resulting root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) + * + * This expects tree_addr to be initialized to the addr structures for the + * Merkle tree nodes + * + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + * + * This works by using the standard Merkle tree building algorithm, + */ +void treehashx1(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, + uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* Where to write the leaves */, + const spx_ctx * /* ctx */, + uint32_t idx, void *info), + uint32_t tree_addr[8], + void *info) { + /* This is where we keep the intermediate nodes */ + PQCLEAN_VLA(uint8_t, stack, tree_height * SPX_N); + + uint32_t idx; + uint32_t max_idx = (uint32_t)((1 << tree_height) - 1); + for (idx = 0;; idx++) { + unsigned char current[2 * SPX_N]; /* Current logical node is at */ + /* index[SPX_N]. We do this to minimize the number of copies */ + /* needed during a thash */ + gen_leaf( ¤t[SPX_N], ctx, idx + idx_offset, + info ); + + /* Now combine the freshly generated right node with previously */ + /* generated left ones */ + uint32_t internal_idx_offset = idx_offset; + uint32_t internal_idx = idx; + uint32_t internal_leaf = leaf_idx; + uint32_t h; /* The height we are in the Merkle tree */ + for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { + + /* Check if we hit the top of the tree */ + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[SPX_N], SPX_N ); + return; + } + + /* + * Check if the node we have is a part of the + * authentication path; if it is, write it out + */ + if ((internal_idx ^ internal_leaf) == 0x01) { + memcpy( &auth_path[ h * SPX_N ], + ¤t[SPX_N], + SPX_N ); + } + + /* + * Check if we're at a left child; if so, stop going up the stack + * Exception: if we've reached the end of the tree, keep on going + * (so we combine the last 4 nodes into the one root node in two + * more iterations) + */ + if ((internal_idx & 1) == 0 && idx < max_idx) { + break; + } + + /* Ok, we're at a right node */ + /* Now combine the left and right logical nodes together */ + + /* Set the address of the node we're creating. */ + internal_idx_offset >>= 1; + set_tree_height(tree_addr, h + 1); + set_tree_index(tree_addr, internal_idx / 2 + internal_idx_offset ); + + unsigned char *left = &stack[h * SPX_N]; + memcpy( ¤t[0], left, SPX_N ); + thash( ¤t[1 * SPX_N], + ¤t[0 * SPX_N], + 2, ctx, tree_addr); + } + + /* We've hit a left child; save the current for when we get the */ + /* corresponding right right */ + memcpy( &stack[h * SPX_N], ¤t[SPX_N], SPX_N); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/utilsx1.h b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/utilsx1.h new file mode 100644 index 0000000000..e911d17d53 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/utilsx1.h @@ -0,0 +1,27 @@ +#ifndef SPX_UTILSX4_H +#define SPX_UTILSX4_H + +#include + +#include "context.h" +#include "params.h" + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +#define treehashx1 SPX_NAMESPACE(treehashx1) +void treehashx1(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* Where to write the leaf */, + const spx_ctx * /* ctx */, + uint32_t addr_idx, void *info), + uint32_t tree_addrx4[8], void *info); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/wots.c b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/wots.c new file mode 100644 index 0000000000..249717aaa8 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/wots.c @@ -0,0 +1,108 @@ +#include +#include + +#include "wots.h" +#include "wotsx1.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "thash.h" +#include "utils.h" +#include "utilsx1.h" + +// TODO clarify address expectations, and make them more uniform. +// TODO i.e. do we expect types to be set already? +// TODO and do we expect modifications or copies? + +/** + * Computes the chaining function. + * out and in have to be n-byte arrays. + * + * Interprets in as start-th value of the chain. + * addr has to contain the address of the chain. + */ +static void gen_chain(unsigned char *out, const unsigned char *in, + unsigned int start, unsigned int steps, + const spx_ctx *ctx, uint32_t addr[8]) { + uint32_t i; + + /* Initialize out with the value at position 'start'. */ + memcpy(out, in, SPX_N); + + /* Iterate 'steps' calls to the hash function. */ + for (i = start; i < (start + steps) && i < SPX_WOTS_W; i++) { + set_hash_addr(addr, i); + thash(out, out, 1, ctx, addr); + } +} + +/** + * base_w algorithm as described in draft. + * Interprets an array of bytes as integers in base w. + * This only works when log_w is a divisor of 8. + */ +static void base_w(unsigned int *output, const int out_len, + const unsigned char *input) { + int in = 0; + int out = 0; + unsigned char total = 0; + int bits = 0; + int consumed; + + for (consumed = 0; consumed < out_len; consumed++) { + if (bits == 0) { + total = input[in]; + in++; + bits += 8; + } + bits -= SPX_WOTS_LOGW; + output[out] = (total >> bits) & (SPX_WOTS_W - 1); + out++; + } +} + +/* Computes the WOTS+ checksum over a message (in base_w). */ +static void wots_checksum(unsigned int *csum_base_w, + const unsigned int *msg_base_w) { + unsigned int csum = 0; + unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; + unsigned int i; + + /* Compute checksum. */ + for (i = 0; i < SPX_WOTS_LEN1; i++) { + csum += SPX_WOTS_W - 1 - msg_base_w[i]; + } + + /* Convert checksum to base_w. */ + /* Make sure expected empty zero bits are the least significant bits. */ + csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); + ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); + base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); +} + +/* Takes a message and derives the matching chain lengths. */ +void chain_lengths(unsigned int *lengths, const unsigned char *msg) { + base_w(lengths, SPX_WOTS_LEN1, msg); + wots_checksum(lengths + SPX_WOTS_LEN1, lengths); +} + +/** + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. + * + * Writes the computed public key to 'pk'. + */ +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]) { + unsigned int lengths[SPX_WOTS_LEN]; + uint32_t i; + + chain_lengths(lengths, msg); + + for (i = 0; i < SPX_WOTS_LEN; i++) { + set_chain_addr(addr, i); + gen_chain(pk + i * SPX_N, sig + i * SPX_N, + lengths[i], SPX_WOTS_W - 1 - lengths[i], ctx, addr); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/wots.h b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/wots.h new file mode 100644 index 0000000000..4e7692eeef --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/wots.h @@ -0,0 +1,25 @@ +#ifndef SPX_WOTS_H +#define SPX_WOTS_H + +#include + +#include "context.h" +#include "params.h" + +/** + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. + * + * Writes the computed public key to 'pk'. + */ +#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]); + +/* + * Compute the chain lengths needed for a given message hash + */ +#define chain_lengths SPX_NAMESPACE(chain_lengths) +void chain_lengths(unsigned int *lengths, const unsigned char *msg); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/wotsx1.c b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/wotsx1.c new file mode 100644 index 0000000000..3adec78dfb --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/wotsx1.c @@ -0,0 +1,76 @@ +#include +#include + +#include "wots.h" +#include "wotsx1.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "thash.h" +#include "utils.h" + +/* + * This generates a WOTS public key + * It also generates the WOTS signature if leaf_info indicates + * that we're signing with this WOTS key + */ +void wots_gen_leafx1(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info) { + struct leaf_info_x1 *info = v_info; + uint32_t *leaf_addr = info->leaf_addr; + uint32_t *pk_addr = info->pk_addr; + unsigned int i, k; + unsigned char pk_buffer[ SPX_WOTS_BYTES ]; + unsigned char *buffer; + uint32_t wots_k_mask; + + if (leaf_idx == info->wots_sign_leaf) { + /* We're traversing the leaf that's signing; generate the WOTS */ + /* signature */ + wots_k_mask = 0; + } else { + /* Nope, we're just generating pk's; turn off the signature logic */ + wots_k_mask = (uint32_t)~0; + } + + set_keypair_addr( leaf_addr, leaf_idx ); + set_keypair_addr( pk_addr, leaf_idx ); + + for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { + uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k to */ + /* the step if we're generating a signature, ~0 if we're not */ + + /* Start with the secret seed */ + set_chain_addr(leaf_addr, i); + set_hash_addr(leaf_addr, 0); + set_type(leaf_addr, SPX_ADDR_TYPE_WOTSPRF); + + prf_addr(buffer, ctx, leaf_addr); + + set_type(leaf_addr, SPX_ADDR_TYPE_WOTS); + + /* Iterate down the WOTS chain */ + for (k = 0;; k++) { + /* Check if this is the value that needs to be saved as a */ + /* part of the WOTS signature */ + if (k == wots_k) { + memcpy( info->wots_sig + i * SPX_N, buffer, SPX_N ); + } + + /* Check if we hit the top of the chain */ + if (k == SPX_WOTS_W - 1) { + break; + } + + /* Iterate one step on the chain */ + set_hash_addr(leaf_addr, k); + + thash(buffer, buffer, 1, ctx, leaf_addr); + } + } + + /* Do the final thash to generate the public keys */ + thash(dest, pk_buffer, SPX_WOTS_LEN, ctx, pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/wotsx1.h b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/wotsx1.h new file mode 100644 index 0000000000..e617929f96 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/wotsx1.h @@ -0,0 +1,39 @@ +#ifndef WOTSX1_H_ +#define WOTSX1_H_ + +#include + +#include "context.h" +#include "params.h" + +/* + * This is here to provide an interface to the internal wots_gen_leafx1 + * routine. While this routine is not referenced in the package outside of + * wots.c, it is called from the stand-alone benchmark code to characterize + * the performance + */ +struct leaf_info_x1 { + unsigned char *wots_sig; + uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ + uint32_t *wots_steps; + uint32_t leaf_addr[8]; + uint32_t pk_addr[8]; +}; + +/* Macro to set the leaf_info to something 'benign', that is, it would */ +/* run with the same time as it does during the real signing process */ +/* Used only by the benchmark code */ +#define INITIALIZE_LEAF_INFO_X1(info, addr, step_buffer) { \ + (info).wots_sig = 0; \ + (info).wots_sign_leaf = ~0; \ + (info).wots_steps = step_buffer; \ + memcpy( &(info).leaf_addr[0], (addr), 32 ); \ + memcpy( &(info).pk_addr[0], (addr), 32 ); \ + } + +#define wots_gen_leafx1 SPX_NAMESPACE(wots_gen_leafx1) +void wots_gen_leafx1(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info); + +#endif /* WOTSX1_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/LICENSE b/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/LICENSE new file mode 100644 index 0000000000..670154e353 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/LICENSE @@ -0,0 +1,116 @@ +CC0 1.0 Universal + +Statement of Purpose + +The laws of most jurisdictions throughout the world automatically confer +exclusive Copyright and Related Rights (defined below) upon the creator and +subsequent owner(s) (each and all, an "owner") of an original work of +authorship and/or a database (each, a "Work"). + +Certain owners wish to permanently relinquish those rights to a Work for the +purpose of contributing to a commons of creative, cultural and scientific +works ("Commons") that the public can reliably and without fear of later +claims of infringement build upon, modify, incorporate in other works, reuse +and redistribute as freely as possible in any form whatsoever and for any +purposes, including without limitation commercial purposes. These owners may +contribute to the Commons to promote the ideal of a free culture and the +further production of creative, cultural and scientific works, or to gain +reputation or greater distribution for their Work in part through the use and +efforts of others. + +For these and/or other purposes and motivations, and without any expectation +of additional consideration or compensation, the person associating CC0 with a +Work (the "Affirmer"), to the extent that he or she is an owner of Copyright +and Related Rights in the Work, voluntarily elects to apply CC0 to the Work +and publicly distribute the Work under its terms, with knowledge of his or her +Copyright and Related Rights in the Work and the meaning and intended legal +effect of CC0 on those rights. + +1. Copyright and Related Rights. A Work made available under CC0 may be +protected by copyright and related or neighboring rights ("Copyright and +Related Rights"). Copyright and Related Rights include, but are not limited +to, the following: + + i. the right to reproduce, adapt, distribute, perform, display, communicate, + and translate a Work; + + ii. moral rights retained by the original author(s) and/or performer(s); + + iii. publicity and privacy rights pertaining to a person's image or likeness + depicted in a Work; + + iv. rights protecting against unfair competition in regards to a Work, + subject to the limitations in paragraph 4(a), below; + + v. rights protecting the extraction, dissemination, use and reuse of data in + a Work; + + vi. database rights (such as those arising under Directive 96/9/EC of the + European Parliament and of the Council of 11 March 1996 on the legal + protection of databases, and under any national implementation thereof, + including any amended or successor version of such directive); and + + vii. other similar, equivalent or corresponding rights throughout the world + based on applicable law or treaty, and any national implementations thereof. + +2. Waiver. To the greatest extent permitted by, but not in contravention of, +applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and +unconditionally waives, abandons, and surrenders all of Affirmer's Copyright +and Related Rights and associated claims and causes of action, whether now +known or unknown (including existing as well as future claims and causes of +action), in the Work (i) in all territories worldwide, (ii) for the maximum +duration provided by applicable law or treaty (including future time +extensions), (iii) in any current or future medium and for any number of +copies, and (iv) for any purpose whatsoever, including without limitation +commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes +the Waiver for the benefit of each member of the public at large and to the +detriment of Affirmer's heirs and successors, fully intending that such Waiver +shall not be subject to revocation, rescission, cancellation, termination, or +any other legal or equitable action to disrupt the quiet enjoyment of the Work +by the public as contemplated by Affirmer's express Statement of Purpose. + +3. Public License Fallback. Should any part of the Waiver for any reason be +judged legally invalid or ineffective under applicable law, then the Waiver +shall be preserved to the maximum extent permitted taking into account +Affirmer's express Statement of Purpose. In addition, to the extent the Waiver +is so judged Affirmer hereby grants to each affected person a royalty-free, +non transferable, non sublicensable, non exclusive, irrevocable and +unconditional license to exercise Affirmer's Copyright and Related Rights in +the Work (i) in all territories worldwide, (ii) for the maximum duration +provided by applicable law or treaty (including future time extensions), (iii) +in any current or future medium and for any number of copies, and (iv) for any +purpose whatsoever, including without limitation commercial, advertising or +promotional purposes (the "License"). The License shall be deemed effective as +of the date CC0 was applied by Affirmer to the Work. Should any part of the +License for any reason be judged legally invalid or ineffective under +applicable law, such partial invalidity or ineffectiveness shall not +invalidate the remainder of the License, and in such case Affirmer hereby +affirms that he or she will not (i) exercise any of his or her remaining +Copyright and Related Rights in the Work or (ii) assert any associated claims +and causes of action with respect to the Work, in either case contrary to +Affirmer's express Statement of Purpose. + +4. Limitations and Disclaimers. + + a. No trademark or patent rights held by Affirmer are waived, abandoned, + surrendered, licensed or otherwise affected by this document. + + b. Affirmer offers the Work as-is and makes no representations or warranties + of any kind concerning the Work, express, implied, statutory or otherwise, + including without limitation warranties of title, merchantability, fitness + for a particular purpose, non infringement, or the absence of latent or + other defects, accuracy, or the present or absence of errors, whether or not + discoverable, all to the greatest extent permissible under applicable law. + + c. Affirmer disclaims responsibility for clearing rights of other persons + that may apply to the Work or any use thereof, including without limitation + any person's Copyright and Related Rights in the Work. Further, Affirmer + disclaims responsibility for obtaining any necessary consents, permissions + or other rights required for any use of the Work. + + d. Affirmer understands and acknowledges that Creative Commons is not a + party to this document and has no duty or obligation with respect to this + CC0 or use of the Work. + +For more information, please see + diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/address.c b/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/address.c new file mode 100644 index 0000000000..d49d9f3b6b --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/address.c @@ -0,0 +1,95 @@ +#include +#include + +#include "address.h" +#include "params.h" +#include "utils.h" + +/* + * Specify which level of Merkle tree (the "layer") we're working on + */ +void set_layer_addr(uint32_t addr[8], uint32_t layer) { + ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; +} + +/* + * Specify which Merkle tree within the level (the "tree address") we're working on + */ +void set_tree_addr(uint32_t addr[8], uint64_t tree) { + ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); +} + +/* + * Specify the reason we'll use this address structure for, that is, what + * hash will we compute with it. This is used so that unrelated types of + * hashes don't accidentally get the same address structure. The type will be + * one of the SPX_ADDR_TYPE constants + */ +void set_type(uint32_t addr[8], uint32_t type) { + ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; +} + +/* + * Copy the layer and tree fields of the address structure. This is used + * when we're doing multiple types of hashes within the same Merkle tree + */ +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); +} + +/* These functions are used for OTS addresses. */ + +/* + * Specify which Merkle leaf we're working on; that is, which OTS keypair + * we're talking about. + */ +void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { + /* We have > 256 OTS at the bottom of the Merkle tree; to specify */ + /* which one, we'd need to express it in two bytes */ + ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR2] = (unsigned char)(keypair >> 8); + ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; +} + +/* + * Copy the layer, tree and keypair fields of the address structure. This is + * used when we're doing multiple things within the same OTS keypair + */ +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); + ((unsigned char *)out)[SPX_OFFSET_KP_ADDR2] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR2]; + ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; +} + +/* + * Specify which Merkle chain within the OTS we're working with + * (the chain address) + */ +void set_chain_addr(uint32_t addr[8], uint32_t chain) { + ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; +} + +/* + * Specify where in the Merkle chain we are +* (the hash address) + */ +void set_hash_addr(uint32_t addr[8], uint32_t hash) { + ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; +} + +/* These functions are used for all hash tree addresses (including FORS). */ + +/* + * Specify the height of the node in the Merkle/FORS tree we are in + * (the tree height) + */ +void set_tree_height(uint32_t addr[8], uint32_t tree_height) { + ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; +} + +/* + * Specify the distance from the left edge of the node in the Merkle/FORS tree + * (the tree index) + */ +void set_tree_index(uint32_t addr[8], uint32_t tree_index) { + u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/address.h b/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/address.h new file mode 100644 index 0000000000..24a84eb40c --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/address.h @@ -0,0 +1,52 @@ +#ifndef SPX_ADDRESS_H +#define SPX_ADDRESS_H + +#include + +#include "params.h" + +/* The hash types that are passed to set_type */ +#define SPX_ADDR_TYPE_WOTS 0 +#define SPX_ADDR_TYPE_WOTSPK 1 +#define SPX_ADDR_TYPE_HASHTREE 2 +#define SPX_ADDR_TYPE_FORSTREE 3 +#define SPX_ADDR_TYPE_FORSPK 4 +#define SPX_ADDR_TYPE_WOTSPRF 5 +#define SPX_ADDR_TYPE_FORSPRF 6 + +#define set_layer_addr SPX_NAMESPACE(set_layer_addr) +void set_layer_addr(uint32_t addr[8], uint32_t layer); + +#define set_tree_addr SPX_NAMESPACE(set_tree_addr) +void set_tree_addr(uint32_t addr[8], uint64_t tree); + +#define set_type SPX_NAMESPACE(set_type) +void set_type(uint32_t addr[8], uint32_t type); + +/* Copies the layer and tree part of one address into the other */ +#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); + +/* These functions are used for WOTS and FORS addresses. */ + +#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) +void set_keypair_addr(uint32_t addr[8], uint32_t keypair); + +#define set_chain_addr SPX_NAMESPACE(set_chain_addr) +void set_chain_addr(uint32_t addr[8], uint32_t chain); + +#define set_hash_addr SPX_NAMESPACE(set_hash_addr) +void set_hash_addr(uint32_t addr[8], uint32_t hash); + +#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); + +/* These functions are used for all hash tree addresses (including FORS). */ + +#define set_tree_height SPX_NAMESPACE(set_tree_height) +void set_tree_height(uint32_t addr[8], uint32_t tree_height); + +#define set_tree_index SPX_NAMESPACE(set_tree_index) +void set_tree_index(uint32_t addr[8], uint32_t tree_index); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/api.h b/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/api.h new file mode 100644 index 0000000000..87c33738e7 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/api.h @@ -0,0 +1,77 @@ +#ifndef PQCLEAN_SPHINCSSHA2128SSIMPLE_AVX2_API_H +#define PQCLEAN_SPHINCSSHA2128SSIMPLE_AVX2_API_H + +#include +#include + +#define PQCLEAN_SPHINCSSHA2128SSIMPLE_AVX2_CRYPTO_ALGNAME "SPHINCS+-sha2-128s-simple" + +#define PQCLEAN_SPHINCSSHA2128SSIMPLE_AVX2_CRYPTO_SECRETKEYBYTES 64 +#define PQCLEAN_SPHINCSSHA2128SSIMPLE_AVX2_CRYPTO_PUBLICKEYBYTES 32 +#define PQCLEAN_SPHINCSSHA2128SSIMPLE_AVX2_CRYPTO_BYTES 7856 + +#define PQCLEAN_SPHINCSSHA2128SSIMPLE_AVX2_CRYPTO_SEEDBYTES 48 + +/* + * Returns the length of a secret key, in bytes + */ +size_t PQCLEAN_SPHINCSSHA2128SSIMPLE_AVX2_crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +size_t PQCLEAN_SPHINCSSHA2128SSIMPLE_AVX2_crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +size_t PQCLEAN_SPHINCSSHA2128SSIMPLE_AVX2_crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +size_t PQCLEAN_SPHINCSSHA2128SSIMPLE_AVX2_crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +int PQCLEAN_SPHINCSSHA2128SSIMPLE_AVX2_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +int PQCLEAN_SPHINCSSHA2128SSIMPLE_AVX2_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +int PQCLEAN_SPHINCSSHA2128SSIMPLE_AVX2_crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +int PQCLEAN_SPHINCSSHA2128SSIMPLE_AVX2_crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, + const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +int PQCLEAN_SPHINCSSHA2128SSIMPLE_AVX2_crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +int PQCLEAN_SPHINCSSHA2128SSIMPLE_AVX2_crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/context.h b/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/context.h new file mode 100644 index 0000000000..200d3c0fb1 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/context.h @@ -0,0 +1,26 @@ +#ifndef SPX_CONTEXT_H +#define SPX_CONTEXT_H + +#include + +#include "params.h" +#include "sha2.h" +#include "sha256avx.h" + +// funky ordering due to optimal padding +typedef struct { + sha256x8ctx statex8_seeded; + sha256ctx state_seeded; + + uint8_t pub_seed[SPX_N]; + uint8_t sk_seed[SPX_N]; +} spx_ctx; + + +#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) +void initialize_hash_function(spx_ctx *ctx); + +#define free_hash_function SPX_NAMESPACE(free_hash_function) +void free_hash_function(spx_ctx *ctx); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/context_sha2.c b/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/context_sha2.c new file mode 100644 index 0000000000..073af8dd15 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/context_sha2.c @@ -0,0 +1,44 @@ +#include + +#include "context.h" + +/** + * Absorb the constant pub_seed using one round of the compression function + * This initializes state_seeded and state_seeded_512, which can then be + * reused in thash + **/ +static void seed_state(spx_ctx *ctx) { + uint8_t block[SPX_SHA512_BLOCK_BYTES]; + size_t i; + + for (i = 0; i < SPX_N; ++i) { + block[i] = ctx->pub_seed[i]; + } + for (i = SPX_N; i < SPX_SHA512_BLOCK_BYTES; ++i) { + block[i] = 0; + } + /* block has been properly initialized for both SHA-256 and SHA-512 */ + + sha256_inc_init(&ctx->state_seeded); + sha256_inc_blocks(&ctx->state_seeded, block, 1); + + // initialize x8 + sha256_init8x(&ctx->statex8_seeded); + sha256_transform8x(&ctx->statex8_seeded, + block, block, block, block, block, block, block, block); + + ctx->statex8_seeded.datalen = 0; + ctx->statex8_seeded.msglen = 512; + +} + + +/* For SHA, we initialize the hash function at the start */ +void initialize_hash_function(spx_ctx *ctx) { + seed_state(ctx); +} + +/* Free the incremental hashing context for heap-based SHA2 APIs */ +void free_hash_function(spx_ctx *ctx) { + sha256_inc_ctx_release(&ctx->state_seeded); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/fors.c b/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/fors.c new file mode 100644 index 0000000000..4cab8e7415 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/fors.c @@ -0,0 +1,226 @@ +#include +#include +#include + +#include "fors.h" + + +#include "address.h" +#include "hash.h" +#include "hashx8.h" +#include "thash.h" +#include "thashx8.h" +#include "utils.h" +#include "utilsx8.h" +static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + prf_addr(sk, ctx, fors_leaf_addr); +} + +static void fors_gen_skx8(unsigned char *sk0, + unsigned char *sk1, + unsigned char *sk2, + unsigned char *sk3, + unsigned char *sk4, + unsigned char *sk5, + unsigned char *sk6, + unsigned char *sk7, const spx_ctx *ctx, + uint32_t fors_leaf_addrx8[8 * 8]) { + prf_addrx8(sk0, sk1, sk2, sk3, sk4, sk5, sk6, sk7, + ctx, fors_leaf_addrx8); +} + +static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, + const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + thash(leaf, sk, 1, ctx, fors_leaf_addr); +} + +static void fors_sk_to_leafx8(unsigned char *leaf0, + unsigned char *leaf1, + unsigned char *leaf2, + unsigned char *leaf3, + unsigned char *leaf4, + unsigned char *leaf5, + unsigned char *leaf6, + unsigned char *leaf7, + const unsigned char *sk0, + const unsigned char *sk1, + const unsigned char *sk2, + const unsigned char *sk3, + const unsigned char *sk4, + const unsigned char *sk5, + const unsigned char *sk6, + const unsigned char *sk7, + const spx_ctx *ctx, + uint32_t fors_leaf_addrx8[8 * 8]) { + thashx8(leaf0, leaf1, leaf2, leaf3, leaf4, leaf5, leaf6, leaf7, + sk0, sk1, sk2, sk3, sk4, sk5, sk6, sk7, + 1, ctx, fors_leaf_addrx8); +} + +struct fors_gen_leaf_info { + uint32_t leaf_addrx[8 * 8]; +}; + +static void fors_gen_leafx8(unsigned char *leaf, + const spx_ctx *ctx, + uint32_t addr_idx, void *info) { + struct fors_gen_leaf_info *fors_info = info; + uint32_t *fors_leaf_addrx8 = fors_info->leaf_addrx; + unsigned int j; + + /* Only set the parts that the caller doesn't set */ + for (j = 0; j < 8; j++) { + set_tree_index(fors_leaf_addrx8 + j * 8, addr_idx + j); + set_type(fors_leaf_addrx8 + j * 8, SPX_ADDR_TYPE_FORSPRF); + } + + fors_gen_skx8(leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + leaf + 2 * SPX_N, + leaf + 3 * SPX_N, + leaf + 4 * SPX_N, + leaf + 5 * SPX_N, + leaf + 6 * SPX_N, + leaf + 7 * SPX_N, + ctx, fors_leaf_addrx8); + + for (j = 0; j < 8; j++) { + set_type(fors_leaf_addrx8 + j * 8, SPX_ADDR_TYPE_FORSTREE); + } + + fors_sk_to_leafx8(leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + leaf + 2 * SPX_N, + leaf + 3 * SPX_N, + leaf + 4 * SPX_N, + leaf + 5 * SPX_N, + leaf + 6 * SPX_N, + leaf + 7 * SPX_N, + leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + leaf + 2 * SPX_N, + leaf + 3 * SPX_N, + leaf + 4 * SPX_N, + leaf + 5 * SPX_N, + leaf + 6 * SPX_N, + leaf + 7 * SPX_N, + ctx, fors_leaf_addrx8); +} + +/** + * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + * Assumes indices has space for SPX_FORS_TREES integers. + */ +static void message_to_indices(uint32_t *indices, const unsigned char *m) { + unsigned int i, j; + unsigned int offset = 0; + + for (i = 0; i < SPX_FORS_TREES; i++) { + indices[i] = 0; + for (j = 0; j < SPX_FORS_HEIGHT; j++) { + indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); + offset++; + } + } +} + +/** + * Signs a message m, deriving the secret key from sk_seed and the FTS address. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + uint32_t fors_tree_addr[8 * 8] = {0}; + struct fors_gen_leaf_info fors_info = {0}; + uint32_t *fors_leaf_addr = fors_info.leaf_addrx; + uint32_t fors_pk_addr[8] = {0}; + uint32_t idx_offset; + unsigned int i; + + for (i = 0; i < 8; i++) { + copy_keypair_addr(fors_tree_addr + 8 * i, fors_addr); + set_type(fors_tree_addr + 8 * i, SPX_ADDR_TYPE_FORSTREE); + copy_keypair_addr(fors_leaf_addr + 8 * i, fors_addr); + } + copy_keypair_addr(fors_pk_addr, fors_addr); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); + + message_to_indices(indices, m); + + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); + + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + + /* Include the secret key part that produces the selected leaf node. */ + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); + fors_gen_sk(sig, ctx, fors_tree_addr); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + sig += SPX_N; + + /* Compute the authentication path for this leaf node. */ + treehashx8(roots + i * SPX_N, sig, ctx, + indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx8, + fors_tree_addr, &fors_info); + + sig += SPX_N * SPX_FORS_HEIGHT; + } + + /* Hash horizontally across all tree roots to derive the public key. */ + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); +} + +/** + * Derives the FORS public key from a signature. + * This can be used for verification by comparing to a known public key, or to + * subsequently verify a signature on the derived public key. The latter is the + * typical use-case when used as an FTS below an OTS in a hypertree. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + unsigned char leaf[SPX_N]; + uint32_t fors_tree_addr[8] = {0}; + uint32_t fors_pk_addr[8] = {0}; + uint32_t idx_offset; + unsigned int i; + + copy_keypair_addr(fors_tree_addr, fors_addr); + copy_keypair_addr(fors_pk_addr, fors_addr); + + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); + + message_to_indices(indices, m); + + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); + + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + + /* Derive the leaf from the included secret key part. */ + fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); + sig += SPX_N; + + /* Derive the corresponding root node of this tree. */ + compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, + sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); + sig += SPX_N * SPX_FORS_HEIGHT; + } + + /* Hash horizontally across all tree roots to derive the public key. */ + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/fors.h b/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/fors.h new file mode 100644 index 0000000000..509140a178 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/fors.h @@ -0,0 +1,32 @@ +#ifndef SPX_FORS_H +#define SPX_FORS_H + +#include + +#include "context.h" +#include "params.h" + +/** + * Signs a message m, deriving the secret key from sk_seed and the FTS address. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +#define fors_sign SPX_NAMESPACE(fors_sign) +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); + +/** + * Derives the FORS public key from a signature. + * This can be used for verification by comparing to a known public key, or to + * subsequently verify a signature on the derived public key. The latter is the + * typical use-case when used as an FTS below an OTS in a hypertree. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/hash.h b/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/hash.h new file mode 100644 index 0000000000..ffe815f45d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/hash.h @@ -0,0 +1,37 @@ +#ifndef SPX_HASH_H +#define SPX_HASH_H + +#include +#include + +#include "context.h" +#include "params.h" + +#define prf_addr SPX_NAMESPACE(prf_addr) +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]); + +#define gen_message_random SPX_NAMESPACE(gen_message_random) +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); + +#define hash_message SPX_NAMESPACE(hash_message) +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); + + +# define SPX_SHA256_ADDR_BYTES 22 + +# define mgf1_256 SPX_NAMESPACE(mgf1_256) +void mgf1_256(unsigned char *out, unsigned long outlen, + const unsigned char *in, unsigned long inlen); + +# define mgf1_512 SPX_NAMESPACE(mgf1_512) +void mgf1_512(unsigned char *out, unsigned long outlen, + const unsigned char *in, unsigned long inlen); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/hash_sha2.c b/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/hash_sha2.c new file mode 100644 index 0000000000..69f0dc0013 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/hash_sha2.c @@ -0,0 +1,219 @@ +#include +#include + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "sha2.h" +#include "utils.h" + + + +#define SPX_SHAX_OUTPUT_BYTES SPX_SHA256_OUTPUT_BYTES +#define SPX_SHAX_BLOCK_BYTES SPX_SHA256_BLOCK_BYTES +#define shaX_inc_init sha256_inc_init +#define shaX_inc_blocks sha256_inc_blocks +#define shaX_inc_finalize sha256_inc_finalize +#define shaX sha256 +#define mgf1_X mgf1_256 +#define shaXstate sha256ctx + +/** + * mgf1 function based on the SHA-256 hash function + * Note that inlen should be sufficiently small that it still allows for + * an array to be allocated on the stack. Typically 'in' is merely a seed. + * Outputs outlen number of bytes + */ +void mgf1_256(unsigned char *out, unsigned long outlen, + const unsigned char *in, unsigned long inlen) { + PQCLEAN_VLA(uint8_t, inbuf, inlen + 4); + unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES]; + uint32_t i; + + memcpy(inbuf, in, inlen); + + /* While we can fit in at least another full block of SHA256 output.. */ + for (i = 0; (i + 1)*SPX_SHA256_OUTPUT_BYTES <= outlen; i++) { + u32_to_bytes(inbuf + inlen, i); + sha256(out, inbuf, inlen + 4); + out += SPX_SHA256_OUTPUT_BYTES; + } + /* Until we cannot anymore, and we fill the remainder. */ + if (outlen > i * SPX_SHA256_OUTPUT_BYTES) { + u32_to_bytes(inbuf + inlen, i); + sha256(outbuf, inbuf, inlen + 4); + memcpy(out, outbuf, outlen - i * SPX_SHA256_OUTPUT_BYTES); + } +} + +/* + * mgf1 function based on the SHA-512 hash function + */ +void mgf1_512(unsigned char *out, unsigned long outlen, + const unsigned char *in, unsigned long inlen) { + PQCLEAN_VLA(uint8_t, inbuf, inlen + 4); + unsigned char outbuf[SPX_SHA512_OUTPUT_BYTES]; + uint32_t i; + + memcpy(inbuf, in, inlen); + + /* While we can fit in at least another full block of SHA512 output.. */ + for (i = 0; (i + 1)*SPX_SHA512_OUTPUT_BYTES <= outlen; i++) { + u32_to_bytes(inbuf + inlen, i); + sha512(out, inbuf, inlen + 4); + out += SPX_SHA512_OUTPUT_BYTES; + } + /* Until we cannot anymore, and we fill the remainder. */ + if (outlen > i * SPX_SHA512_OUTPUT_BYTES) { + u32_to_bytes(inbuf + inlen, i); + sha512(outbuf, inbuf, inlen + 4); + memcpy(out, outbuf, outlen - i * SPX_SHA512_OUTPUT_BYTES); + } +} + +/* + * Computes PRF(pk_seed, sk_seed, addr). + */ +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]) { + sha256ctx sha2_state; + unsigned char buf[SPX_SHA256_ADDR_BYTES + SPX_N]; + unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES]; + + /* Retrieve precomputed state containing pub_seed */ + sha256_inc_ctx_clone(&sha2_state, &ctx->state_seeded); + + /* Remainder: ADDR^c ‖ SK.seed */ + memcpy(buf, addr, SPX_SHA256_ADDR_BYTES); + memcpy(buf + SPX_SHA256_ADDR_BYTES, ctx->sk_seed, SPX_N); + + sha256_inc_finalize(outbuf, &sha2_state, buf, SPX_SHA256_ADDR_BYTES + SPX_N); + + memcpy(out, outbuf, SPX_N); +} + +/** + * Computes the message-dependent randomness R, using a secret seed as a key + * for HMAC, and an optional randomization value prefixed to the message. + * This requires m to have at least SPX_SHAX_BLOCK_BYTES + SPX_N space + * available in front of the pointer, i.e. before the message to use for the + * prefix. This is necessary to prevent having to move the message around (and + * allocate memory for it). + */ +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { + (void)ctx; + + unsigned char buf[SPX_SHAX_BLOCK_BYTES + SPX_SHAX_OUTPUT_BYTES]; + shaXstate state; + int i; + + + /* This implements HMAC-SHA */ + for (i = 0; i < SPX_N; i++) { + buf[i] = 0x36 ^ sk_prf[i]; + } + memset(buf + SPX_N, 0x36, SPX_SHAX_BLOCK_BYTES - SPX_N); + + shaX_inc_init(&state); + shaX_inc_blocks(&state, buf, 1); + + memcpy(buf, optrand, SPX_N); + + /* If optrand + message cannot fill up an entire block */ + if (SPX_N + mlen < SPX_SHAX_BLOCK_BYTES) { + memcpy(buf + SPX_N, m, mlen); + shaX_inc_finalize(buf + SPX_SHAX_BLOCK_BYTES, &state, + buf, mlen + SPX_N); + } + /* Otherwise first fill a block, so that finalize only uses the message */ + else { + memcpy(buf + SPX_N, m, SPX_SHAX_BLOCK_BYTES - SPX_N); + shaX_inc_blocks(&state, buf, 1); + + m += SPX_SHAX_BLOCK_BYTES - SPX_N; + mlen -= SPX_SHAX_BLOCK_BYTES - SPX_N; + shaX_inc_finalize(buf + SPX_SHAX_BLOCK_BYTES, &state, m, mlen); + } + + for (i = 0; i < SPX_N; i++) { + buf[i] = 0x5c ^ sk_prf[i]; + } + memset(buf + SPX_N, 0x5c, SPX_SHAX_BLOCK_BYTES - SPX_N); + + shaX(buf, buf, SPX_SHAX_BLOCK_BYTES + SPX_SHAX_OUTPUT_BYTES); + memcpy(R, buf, SPX_N); +} + +/** + * Computes the message hash using R, the public key, and the message. + * Outputs the message digest and the index of the leaf. The index is split in + * the tree index and the leaf index, for convenient copying to an address. + */ +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { + (void)ctx; +#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) +#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) +#define SPX_LEAF_BITS SPX_TREE_HEIGHT +#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) +#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) + + unsigned char seed[2 * SPX_N + SPX_SHAX_OUTPUT_BYTES]; + + /* Round to nearest multiple of SPX_SHAX_BLOCK_BYTES */ +#define SPX_INBLOCKS (((SPX_N + SPX_PK_BYTES + SPX_SHAX_BLOCK_BYTES - 1) & \ + -SPX_SHAX_BLOCK_BYTES) / SPX_SHAX_BLOCK_BYTES) + unsigned char inbuf[SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES]; + + unsigned char buf[SPX_DGST_BYTES]; + unsigned char *bufp = buf; + shaXstate state; + + shaX_inc_init(&state); + + // seed: SHA-X(R ‖ PK.seed ‖ PK.root ‖ M) + memcpy(inbuf, R, SPX_N); + memcpy(inbuf + SPX_N, pk, SPX_PK_BYTES); + + /* If R + pk + message cannot fill up an entire block */ + if (SPX_N + SPX_PK_BYTES + mlen < SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES) { + memcpy(inbuf + SPX_N + SPX_PK_BYTES, m, mlen); + shaX_inc_finalize(seed + 2 * SPX_N, &state, inbuf, SPX_N + SPX_PK_BYTES + mlen); + } + /* Otherwise first fill a block, so that finalize only uses the message */ + else { + memcpy(inbuf + SPX_N + SPX_PK_BYTES, m, + SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES - SPX_N - SPX_PK_BYTES); + shaX_inc_blocks(&state, inbuf, SPX_INBLOCKS); + + m += SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES - SPX_N - SPX_PK_BYTES; + mlen -= SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES - SPX_N - SPX_PK_BYTES; + shaX_inc_finalize(seed + 2 * SPX_N, &state, m, (size_t)mlen); + } + + // H_msg: MGF1-SHA-X(R ‖ PK.seed ‖ seed) + memcpy(seed, R, SPX_N); + memcpy(seed + SPX_N, pk, SPX_N); + + /* By doing this in two steps, we prevent hashing the message twice; + otherwise each iteration in MGF1 would hash the message again. */ + mgf1_X(bufp, SPX_DGST_BYTES, seed, 2 * SPX_N + SPX_SHAX_OUTPUT_BYTES); + + memcpy(digest, bufp, SPX_FORS_MSG_BYTES); + bufp += SPX_FORS_MSG_BYTES; + + + *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); + *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); + bufp += SPX_TREE_BYTES; + + *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); + *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); +} + + diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/hash_sha2x8.c b/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/hash_sha2x8.c new file mode 100644 index 0000000000..e04af7a069 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/hash_sha2x8.c @@ -0,0 +1,75 @@ +#include +#include + +#include "hash.h" +#include "hashx8.h" + +#include "address.h" +#include "params.h" +#include "sha2.h" +#include "sha256avx.h" +#include "sha256x8.h" +#include "utils.h" + +/* + * 8-way parallel version of prf_addr; takes 8x as much input and output + */ +void prf_addrx8(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const spx_ctx *ctx, + const uint32_t addrx8[8 * 8]) { + unsigned char bufx8[8 * (SPX_N + SPX_SHA256_ADDR_BYTES)]; + unsigned char outbufx8[8 * SPX_SHA256_OUTPUT_BYTES]; + unsigned int j; + + for (j = 0; j < 8; j++) { + memcpy(bufx8 + j * (SPX_N + SPX_SHA256_ADDR_BYTES), + addrx8 + j * 8, SPX_SHA256_ADDR_BYTES); + memcpy( + bufx8 + j * (SPX_N + SPX_SHA256_ADDR_BYTES) + SPX_SHA256_ADDR_BYTES, + ctx->sk_seed, + SPX_N + ); + } + + sha256x8_seeded( + /* out */ + outbufx8 + 0 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 1 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 2 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 3 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 4 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 5 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 6 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 7 * SPX_SHA256_OUTPUT_BYTES, + + /* seed */ + &ctx->statex8_seeded, + + /* in */ + bufx8 + 0 * (SPX_SHA256_ADDR_BYTES + SPX_N), + bufx8 + 1 * (SPX_SHA256_ADDR_BYTES + SPX_N), + bufx8 + 2 * (SPX_SHA256_ADDR_BYTES + SPX_N), + bufx8 + 3 * (SPX_SHA256_ADDR_BYTES + SPX_N), + bufx8 + 4 * (SPX_SHA256_ADDR_BYTES + SPX_N), + bufx8 + 5 * (SPX_SHA256_ADDR_BYTES + SPX_N), + bufx8 + 6 * (SPX_SHA256_ADDR_BYTES + SPX_N), + bufx8 + 7 * (SPX_SHA256_ADDR_BYTES + SPX_N), + SPX_SHA256_ADDR_BYTES + SPX_N /* len */ + ); + + memcpy(out0, outbufx8 + 0 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out1, outbufx8 + 1 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out2, outbufx8 + 2 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out3, outbufx8 + 3 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out4, outbufx8 + 4 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out5, outbufx8 + 5 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out6, outbufx8 + 6 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out7, outbufx8 + 7 * SPX_SHA256_OUTPUT_BYTES, SPX_N); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/hashx8.h b/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/hashx8.h new file mode 100644 index 0000000000..46503f0a10 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/hashx8.h @@ -0,0 +1,20 @@ +#ifndef SPX_HASHX8_H +#define SPX_HASHX8_H + +#include + +#include "params.h" + +#define prf_addrx8 SPX_NAMESPACE(prf_addrx8) +void prf_addrx8(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const spx_ctx *ctx, + const uint32_t addrx8[8 * 8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/merkle.c b/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/merkle.c new file mode 100644 index 0000000000..1f353c8dd8 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/merkle.c @@ -0,0 +1,65 @@ +#include +#include + +#include "merkle.h" + +#include "address.h" +#include "params.h" +#include "utils.h" +#include "utilsx8.h" +#include "wots.h" +#include "wotsx8.h" + +/* + * This generates a Merkle signature (WOTS signature followed by the Merkle + * authentication path). + */ +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf) { + unsigned char *auth_path = sig + SPX_WOTS_BYTES; + uint32_t tree_addrx8[8 * 8] = { 0 }; + int j; + struct leaf_info_x8 info = { 0 }; + unsigned steps[ SPX_WOTS_LEN ]; + + info.wots_sig = sig; + chain_lengths(steps, root); + info.wots_steps = steps; + + for (j = 0; j < 8; j++) { + set_type(&tree_addrx8[8 * j], SPX_ADDR_TYPE_HASHTREE); + set_type(&info.leaf_addr[8 * j], SPX_ADDR_TYPE_WOTS); + set_type(&info.pk_addr[8 * j], SPX_ADDR_TYPE_WOTSPK); + copy_subtree_addr(&tree_addrx8[8 * j], tree_addr); + copy_subtree_addr(&info.leaf_addr[8 * j], wots_addr); + copy_subtree_addr(&info.pk_addr[8 * j], wots_addr); + } + + info.wots_sign_leaf = idx_leaf; + + treehashx8(root, auth_path, ctx, + idx_leaf, 0, + SPX_TREE_HEIGHT, + wots_gen_leafx8, + tree_addrx8, &info); +} + +/* Compute root node of the top-most subtree. */ +/* Again, in this file because wots_gen_leaf is most of the work */ +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { + /* We do not need the auth path in key generation, but it simplifies the + code to have just one treehash routine that computes both root and path + in one function. */ + unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; + uint32_t top_tree_addr[8] = {0}; + uint32_t wots_addr[8] = {0}; + + set_layer_addr(top_tree_addr, SPX_D - 1); + set_layer_addr(wots_addr, SPX_D - 1); + + merkle_sign(auth_path, root, ctx, + wots_addr, top_tree_addr, + ~0U /* ~0 means "don't bother generating an auth path */ ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/merkle.h b/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/merkle.h new file mode 100644 index 0000000000..769cf2e970 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/merkle.h @@ -0,0 +1,21 @@ +#ifndef MERKLE_H_ +#define MERKLE_H_ + +#include + +#include "context.h" +#include "params.h" + +/* Generate a Merkle signature (WOTS signature followed by the Merkle */ +/* authentication path) */ +#define merkle_sign SPX_NAMESPACE(merkle_sign) +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf); + +/* Compute the root node of the top-most subtree. */ +#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); + +#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/nistapi.h b/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/nistapi.h new file mode 100644 index 0000000000..3cb71afad4 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/nistapi.h @@ -0,0 +1,87 @@ +#ifndef SPX_API_H +#define SPX_API_H + +#include +#include + +#include "params.h" + +#define CRYPTO_ALGNAME "SPHINCS+" + +#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES +#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES +#define CRYPTO_BYTES SPX_BYTES +#define CRYPTO_SEEDBYTES (3*SPX_N) + +/* + * Returns the length of a secret key, in bytes + */ +#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) +size_t crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) +size_t crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) +size_t crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) +size_t crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +#define crypto_sign SPX_NAMESPACE(crypto_sign) +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/params.h b/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/params.h new file mode 100644 index 0000000000..22506474fb --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/params.h @@ -0,0 +1,61 @@ +#ifndef SPX_PARAMS_H +#define SPX_PARAMS_H + +#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSSHA2128SSIMPLE_AVX2_##s + +/* Hash output length in bytes. */ +#define SPX_N 16 +/* Height of the hypertree. */ +#define SPX_FULL_HEIGHT 63 +/* Number of subtree layer. */ +#define SPX_D 7 +/* FORS tree dimensions. */ +#define SPX_FORS_HEIGHT 12 +#define SPX_FORS_TREES 14 +/* Winternitz parameter, */ +#define SPX_WOTS_W 16 + +/* The hash function is defined by linking a different hash.c file, as opposed + to setting a #define constant. */ + +/* This is a SHA2-based parameter set, hence whether we use SHA-256 + * exclusively or we use both SHA-256 and SHA-512 is controlled by + * the following #define */ +#define SPX_SHA512 0 /* Use SHA-256 for all hashes */ + +/* For clarity */ +#define SPX_ADDR_BYTES 32 + +/* WOTS parameters. */ +#define SPX_WOTS_LOGW 4 + +#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) + +/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ +#define SPX_WOTS_LEN2 3 + +#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) +#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) +#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES + +/* Subtree size. */ +#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) + +//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT +// #error SPX_D should always divide SPX_FULL_HEIGHT +//#endif + +/* FORS parameters. */ +#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) +#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) +#define SPX_FORS_PK_BYTES SPX_N + +/* Resulting SPX sizes. */ +#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ + SPX_FULL_HEIGHT * SPX_N) +#define SPX_PK_BYTES (2 * SPX_N) +#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) + +#include "sha2_offsets.h" + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/sha256avx.c b/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/sha256avx.c new file mode 100644 index 0000000000..6bbe6ecc24 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/sha256avx.c @@ -0,0 +1,357 @@ +#include +#include +#include + +#include "sha256avx.h" + +static const unsigned int RC[] = { + 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, + 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, + 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, + 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, + 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, + 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, + 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, + 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, + 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, + 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, + 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, + 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, + 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, + 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, + 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, + 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 +}; + +#define u32 uint32_t +#define u256 __m256i + +#define XOR _mm256_xor_si256 +#define OR _mm256_or_si256 +#define AND _mm256_and_si256 +#define ADD32 _mm256_add_epi32 +#define NOT(x) _mm256_xor_si256(x, _mm256_set_epi32(-1, -1, -1, -1, -1, -1, -1, -1)) + +#define LOAD(src) _mm256_loadu_si256((__m256i *)(src)) +#define STORE(dest,src) _mm256_storeu_si256((__m256i *)(dest),src) + +#define BYTESWAP(x) _mm256_shuffle_epi8(x, _mm256_set_epi8(0xc,0xd,0xe,0xf,0x8,0x9,0xa,0xb,0x4,0x5,0x6,0x7,0x0,0x1,0x2,0x3,0xc,0xd,0xe,0xf,0x8,0x9,0xa,0xb,0x4,0x5,0x6,0x7,0x0,0x1,0x2,0x3)) + +#define SHIFTR32(x, y) _mm256_srli_epi32(x, y) +#define SHIFTL32(x, y) _mm256_slli_epi32(x, y) + +#define ROTR32(x, y) OR(SHIFTR32(x, y), SHIFTL32(x, 32 - (y))) +#define ROTL32(x, y) OR(SHIFTL32(x, y), SHIFTR32(x, 32 - (y))) + +#define XOR3(a, b, c) XOR(XOR(a, b), c) + +#define ADD3_32(a, b, c) ADD32(ADD32(a, b), c) +#define ADD4_32(a, b, c, d) ADD32(ADD32(ADD32(a, b), c), d) +#define ADD5_32(a, b, c, d, e) ADD32(ADD32(ADD32(ADD32(a, b), c), d), e) + +#define MAJ_AVX(a, b, c) XOR3(AND(a, b), AND(a, c), AND(b, c)) +#define CH_AVX(a, b, c) XOR(AND(a, b), AND(NOT(a), c)) + +#define SIGMA1_AVX(x) XOR3(ROTR32(x, 6), ROTR32(x, 11), ROTR32(x, 25)) +#define SIGMA0_AVX(x) XOR3(ROTR32(x, 2), ROTR32(x, 13), ROTR32(x, 22)) + +#define WSIGMA1_AVX(x) XOR3(ROTR32(x, 17), ROTR32(x, 19), SHIFTR32(x, 10)) +#define WSIGMA0_AVX(x) XOR3(ROTR32(x, 7), ROTR32(x, 18), SHIFTR32(x, 3)) + +#define SHA256ROUND_AVX(a, b, c, d, e, f, g, h, rc, w) \ + T0 = ADD5_32(h, SIGMA1_AVX(e), CH_AVX(e, f, g), _mm256_set1_epi32((int)RC[rc]), w); \ + (d) = ADD32(d, T0); \ + T1 = ADD32(SIGMA0_AVX(a), MAJ_AVX(a, b, c)); \ + (h) = ADD32(T0, T1); + +// Transpose 8 vectors containing 32-bit values +static void transpose(u256 s[8]) { + u256 tmp0[8]; + u256 tmp1[8]; + tmp0[0] = _mm256_unpacklo_epi32(s[0], s[1]); + tmp0[1] = _mm256_unpackhi_epi32(s[0], s[1]); + tmp0[2] = _mm256_unpacklo_epi32(s[2], s[3]); + tmp0[3] = _mm256_unpackhi_epi32(s[2], s[3]); + tmp0[4] = _mm256_unpacklo_epi32(s[4], s[5]); + tmp0[5] = _mm256_unpackhi_epi32(s[4], s[5]); + tmp0[6] = _mm256_unpacklo_epi32(s[6], s[7]); + tmp0[7] = _mm256_unpackhi_epi32(s[6], s[7]); + tmp1[0] = _mm256_unpacklo_epi64(tmp0[0], tmp0[2]); + tmp1[1] = _mm256_unpackhi_epi64(tmp0[0], tmp0[2]); + tmp1[2] = _mm256_unpacklo_epi64(tmp0[1], tmp0[3]); + tmp1[3] = _mm256_unpackhi_epi64(tmp0[1], tmp0[3]); + tmp1[4] = _mm256_unpacklo_epi64(tmp0[4], tmp0[6]); + tmp1[5] = _mm256_unpackhi_epi64(tmp0[4], tmp0[6]); + tmp1[6] = _mm256_unpacklo_epi64(tmp0[5], tmp0[7]); + tmp1[7] = _mm256_unpackhi_epi64(tmp0[5], tmp0[7]); + s[0] = _mm256_permute2x128_si256(tmp1[0], tmp1[4], 0x20); + s[1] = _mm256_permute2x128_si256(tmp1[1], tmp1[5], 0x20); + s[2] = _mm256_permute2x128_si256(tmp1[2], tmp1[6], 0x20); + s[3] = _mm256_permute2x128_si256(tmp1[3], tmp1[7], 0x20); + s[4] = _mm256_permute2x128_si256(tmp1[0], tmp1[4], 0x31); + s[5] = _mm256_permute2x128_si256(tmp1[1], tmp1[5], 0x31); + s[6] = _mm256_permute2x128_si256(tmp1[2], tmp1[6], 0x31); + s[7] = _mm256_permute2x128_si256(tmp1[3], tmp1[7], 0x31); +} + +void sha256_ctx_clone8x(sha256x8ctx *out, const sha256x8ctx *in) { + memcpy(out, in, sizeof(sha256x8ctx)); +} + +void sha256_init8x(sha256x8ctx *ctx) { + ctx->s[0] = _mm256_set_epi32((int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667); + ctx->s[1] = _mm256_set_epi32((int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85); + ctx->s[2] = _mm256_set_epi32((int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372); + ctx->s[3] = _mm256_set_epi32((int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a); + ctx->s[4] = _mm256_set_epi32((int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f); + ctx->s[5] = _mm256_set_epi32((int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c); + ctx->s[6] = _mm256_set_epi32((int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab); + ctx->s[7] = _mm256_set_epi32((int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19); + + ctx->datalen = 0; + ctx->msglen = 0; +} + +void sha256_final8x(sha256x8ctx *ctx, + unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7) { + unsigned int i, curlen; + + // Padding + if (ctx->datalen < 56) { + for (i = 0; i < 8; ++i) { + curlen = ctx->datalen; + ctx->msgblocks[64 * i + curlen++] = 0x80; + while (curlen < 64) { + ctx->msgblocks[64 * i + curlen++] = 0x00; + } + } + } else { + for (i = 0; i < 8; ++i) { + curlen = ctx->datalen; + ctx->msgblocks[64 * i + curlen++] = 0x80; + while (curlen < 64) { + ctx->msgblocks[64 * i + curlen++] = 0x00; + } + } + sha256_transform8x(ctx, + &ctx->msgblocks[64 * 0], + &ctx->msgblocks[64 * 1], + &ctx->msgblocks[64 * 2], + &ctx->msgblocks[64 * 3], + &ctx->msgblocks[64 * 4], + &ctx->msgblocks[64 * 5], + &ctx->msgblocks[64 * 6], + &ctx->msgblocks[64 * 7] + ); + memset(ctx->msgblocks, 0, 8 * 64); + } + + // Add length of the message to each block + ctx->msglen += ctx->datalen * 8; + for (i = 0; i < 8; i++) { + ctx->msgblocks[64 * i + 63] = (unsigned char)(ctx->msglen); + ctx->msgblocks[64 * i + 62] = (unsigned char)(ctx->msglen >> 8); + ctx->msgblocks[64 * i + 61] = (unsigned char)(ctx->msglen >> 16); + ctx->msgblocks[64 * i + 60] = (unsigned char)(ctx->msglen >> 24); + ctx->msgblocks[64 * i + 59] = (unsigned char)(ctx->msglen >> 32); + ctx->msgblocks[64 * i + 58] = (unsigned char)(ctx->msglen >> 40); + ctx->msgblocks[64 * i + 57] = (unsigned char)(ctx->msglen >> 48); + ctx->msgblocks[64 * i + 56] = (unsigned char)(ctx->msglen >> 56); + } + sha256_transform8x(ctx, + &ctx->msgblocks[64 * 0], + &ctx->msgblocks[64 * 1], + &ctx->msgblocks[64 * 2], + &ctx->msgblocks[64 * 3], + &ctx->msgblocks[64 * 4], + &ctx->msgblocks[64 * 5], + &ctx->msgblocks[64 * 6], + &ctx->msgblocks[64 * 7] + ); + + // Compute final hash output + transpose(ctx->s); + + // Store Hash value + STORE(out0, BYTESWAP(ctx->s[0])); + STORE(out1, BYTESWAP(ctx->s[1])); + STORE(out2, BYTESWAP(ctx->s[2])); + STORE(out3, BYTESWAP(ctx->s[3])); + STORE(out4, BYTESWAP(ctx->s[4])); + STORE(out5, BYTESWAP(ctx->s[5])); + STORE(out6, BYTESWAP(ctx->s[6])); + STORE(out7, BYTESWAP(ctx->s[7])); +} + +void sha256_transform8x(sha256x8ctx *ctx, + const unsigned char *data0, + const unsigned char *data1, + const unsigned char *data2, + const unsigned char *data3, + const unsigned char *data4, + const unsigned char *data5, + const unsigned char *data6, + const unsigned char *data7) { + u256 s[8], w[64], T0, T1; + + // Load words and transform data correctly + w[0] = BYTESWAP(LOAD(data0)); + w[0 + 8] = BYTESWAP(LOAD(data0 + 32)); + w[1] = BYTESWAP(LOAD(data1)); + w[1 + 8] = BYTESWAP(LOAD(data1 + 32)); + w[2] = BYTESWAP(LOAD(data2)); + w[2 + 8] = BYTESWAP(LOAD(data2 + 32)); + w[3] = BYTESWAP(LOAD(data3)); + w[3 + 8] = BYTESWAP(LOAD(data3 + 32)); + w[4] = BYTESWAP(LOAD(data4)); + w[4 + 8] = BYTESWAP(LOAD(data4 + 32)); + w[5] = BYTESWAP(LOAD(data5)); + w[5 + 8] = BYTESWAP(LOAD(data5 + 32)); + w[6] = BYTESWAP(LOAD(data6)); + w[6 + 8] = BYTESWAP(LOAD(data6 + 32)); + w[7] = BYTESWAP(LOAD(data7)); + w[7 + 8] = BYTESWAP(LOAD(data7 + 32)); + + transpose(w); + transpose(w + 8); + + // Initial State + s[0] = ctx->s[0]; + s[1] = ctx->s[1]; + s[2] = ctx->s[2]; + s[3] = ctx->s[3]; + s[4] = ctx->s[4]; + s[5] = ctx->s[5]; + s[6] = ctx->s[6]; + s[7] = ctx->s[7]; + + SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 0, w[0]); + SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 1, w[1]); + SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 2, w[2]); + SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 3, w[3]); + SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 4, w[4]); + SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 5, w[5]); + SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 6, w[6]); + SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 7, w[7]); + SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 8, w[8]); + SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 9, w[9]); + SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 10, w[10]); + SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 11, w[11]); + SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 12, w[12]); + SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 13, w[13]); + SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 14, w[14]); + SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 15, w[15]); + w[16] = ADD4_32(WSIGMA1_AVX(w[14]), w[0], w[9], WSIGMA0_AVX(w[1])); + SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 16, w[16]); + w[17] = ADD4_32(WSIGMA1_AVX(w[15]), w[1], w[10], WSIGMA0_AVX(w[2])); + SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 17, w[17]); + w[18] = ADD4_32(WSIGMA1_AVX(w[16]), w[2], w[11], WSIGMA0_AVX(w[3])); + SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 18, w[18]); + w[19] = ADD4_32(WSIGMA1_AVX(w[17]), w[3], w[12], WSIGMA0_AVX(w[4])); + SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 19, w[19]); + w[20] = ADD4_32(WSIGMA1_AVX(w[18]), w[4], w[13], WSIGMA0_AVX(w[5])); + SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 20, w[20]); + w[21] = ADD4_32(WSIGMA1_AVX(w[19]), w[5], w[14], WSIGMA0_AVX(w[6])); + SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 21, w[21]); + w[22] = ADD4_32(WSIGMA1_AVX(w[20]), w[6], w[15], WSIGMA0_AVX(w[7])); + SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 22, w[22]); + w[23] = ADD4_32(WSIGMA1_AVX(w[21]), w[7], w[16], WSIGMA0_AVX(w[8])); + SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 23, w[23]); + w[24] = ADD4_32(WSIGMA1_AVX(w[22]), w[8], w[17], WSIGMA0_AVX(w[9])); + SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 24, w[24]); + w[25] = ADD4_32(WSIGMA1_AVX(w[23]), w[9], w[18], WSIGMA0_AVX(w[10])); + SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 25, w[25]); + w[26] = ADD4_32(WSIGMA1_AVX(w[24]), w[10], w[19], WSIGMA0_AVX(w[11])); + SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 26, w[26]); + w[27] = ADD4_32(WSIGMA1_AVX(w[25]), w[11], w[20], WSIGMA0_AVX(w[12])); + SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 27, w[27]); + w[28] = ADD4_32(WSIGMA1_AVX(w[26]), w[12], w[21], WSIGMA0_AVX(w[13])); + SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 28, w[28]); + w[29] = ADD4_32(WSIGMA1_AVX(w[27]), w[13], w[22], WSIGMA0_AVX(w[14])); + SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 29, w[29]); + w[30] = ADD4_32(WSIGMA1_AVX(w[28]), w[14], w[23], WSIGMA0_AVX(w[15])); + SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 30, w[30]); + w[31] = ADD4_32(WSIGMA1_AVX(w[29]), w[15], w[24], WSIGMA0_AVX(w[16])); + SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 31, w[31]); + w[32] = ADD4_32(WSIGMA1_AVX(w[30]), w[16], w[25], WSIGMA0_AVX(w[17])); + SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 32, w[32]); + w[33] = ADD4_32(WSIGMA1_AVX(w[31]), w[17], w[26], WSIGMA0_AVX(w[18])); + SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 33, w[33]); + w[34] = ADD4_32(WSIGMA1_AVX(w[32]), w[18], w[27], WSIGMA0_AVX(w[19])); + SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 34, w[34]); + w[35] = ADD4_32(WSIGMA1_AVX(w[33]), w[19], w[28], WSIGMA0_AVX(w[20])); + SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 35, w[35]); + w[36] = ADD4_32(WSIGMA1_AVX(w[34]), w[20], w[29], WSIGMA0_AVX(w[21])); + SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 36, w[36]); + w[37] = ADD4_32(WSIGMA1_AVX(w[35]), w[21], w[30], WSIGMA0_AVX(w[22])); + SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 37, w[37]); + w[38] = ADD4_32(WSIGMA1_AVX(w[36]), w[22], w[31], WSIGMA0_AVX(w[23])); + SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 38, w[38]); + w[39] = ADD4_32(WSIGMA1_AVX(w[37]), w[23], w[32], WSIGMA0_AVX(w[24])); + SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 39, w[39]); + w[40] = ADD4_32(WSIGMA1_AVX(w[38]), w[24], w[33], WSIGMA0_AVX(w[25])); + SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 40, w[40]); + w[41] = ADD4_32(WSIGMA1_AVX(w[39]), w[25], w[34], WSIGMA0_AVX(w[26])); + SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 41, w[41]); + w[42] = ADD4_32(WSIGMA1_AVX(w[40]), w[26], w[35], WSIGMA0_AVX(w[27])); + SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 42, w[42]); + w[43] = ADD4_32(WSIGMA1_AVX(w[41]), w[27], w[36], WSIGMA0_AVX(w[28])); + SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 43, w[43]); + w[44] = ADD4_32(WSIGMA1_AVX(w[42]), w[28], w[37], WSIGMA0_AVX(w[29])); + SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 44, w[44]); + w[45] = ADD4_32(WSIGMA1_AVX(w[43]), w[29], w[38], WSIGMA0_AVX(w[30])); + SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 45, w[45]); + w[46] = ADD4_32(WSIGMA1_AVX(w[44]), w[30], w[39], WSIGMA0_AVX(w[31])); + SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 46, w[46]); + w[47] = ADD4_32(WSIGMA1_AVX(w[45]), w[31], w[40], WSIGMA0_AVX(w[32])); + SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 47, w[47]); + w[48] = ADD4_32(WSIGMA1_AVX(w[46]), w[32], w[41], WSIGMA0_AVX(w[33])); + SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 48, w[48]); + w[49] = ADD4_32(WSIGMA1_AVX(w[47]), w[33], w[42], WSIGMA0_AVX(w[34])); + SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 49, w[49]); + w[50] = ADD4_32(WSIGMA1_AVX(w[48]), w[34], w[43], WSIGMA0_AVX(w[35])); + SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 50, w[50]); + w[51] = ADD4_32(WSIGMA1_AVX(w[49]), w[35], w[44], WSIGMA0_AVX(w[36])); + SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 51, w[51]); + w[52] = ADD4_32(WSIGMA1_AVX(w[50]), w[36], w[45], WSIGMA0_AVX(w[37])); + SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 52, w[52]); + w[53] = ADD4_32(WSIGMA1_AVX(w[51]), w[37], w[46], WSIGMA0_AVX(w[38])); + SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 53, w[53]); + w[54] = ADD4_32(WSIGMA1_AVX(w[52]), w[38], w[47], WSIGMA0_AVX(w[39])); + SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 54, w[54]); + w[55] = ADD4_32(WSIGMA1_AVX(w[53]), w[39], w[48], WSIGMA0_AVX(w[40])); + SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 55, w[55]); + w[56] = ADD4_32(WSIGMA1_AVX(w[54]), w[40], w[49], WSIGMA0_AVX(w[41])); + SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 56, w[56]); + w[57] = ADD4_32(WSIGMA1_AVX(w[55]), w[41], w[50], WSIGMA0_AVX(w[42])); + SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 57, w[57]); + w[58] = ADD4_32(WSIGMA1_AVX(w[56]), w[42], w[51], WSIGMA0_AVX(w[43])); + SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 58, w[58]); + w[59] = ADD4_32(WSIGMA1_AVX(w[57]), w[43], w[52], WSIGMA0_AVX(w[44])); + SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 59, w[59]); + w[60] = ADD4_32(WSIGMA1_AVX(w[58]), w[44], w[53], WSIGMA0_AVX(w[45])); + SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 60, w[60]); + w[61] = ADD4_32(WSIGMA1_AVX(w[59]), w[45], w[54], WSIGMA0_AVX(w[46])); + SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 61, w[61]); + w[62] = ADD4_32(WSIGMA1_AVX(w[60]), w[46], w[55], WSIGMA0_AVX(w[47])); + SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 62, w[62]); + w[63] = ADD4_32(WSIGMA1_AVX(w[61]), w[47], w[56], WSIGMA0_AVX(w[48])); + SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 63, w[63]); + + // Feed Forward + ctx->s[0] = ADD32(s[0], ctx->s[0]); + ctx->s[1] = ADD32(s[1], ctx->s[1]); + ctx->s[2] = ADD32(s[2], ctx->s[2]); + ctx->s[3] = ADD32(s[3], ctx->s[3]); + ctx->s[4] = ADD32(s[4], ctx->s[4]); + ctx->s[5] = ADD32(s[5], ctx->s[5]); + ctx->s[6] = ADD32(s[6], ctx->s[6]); + ctx->s[7] = ADD32(s[7], ctx->s[7]); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/sha256avx.h b/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/sha256avx.h new file mode 100644 index 0000000000..1e3bcf889b --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/sha256avx.h @@ -0,0 +1,44 @@ +#ifndef SHA256AVX_H +#define SHA256AVX_H + +#include +#include + +#include "params.h" + +typedef struct SHA256state { + __m256i s[8]; + unsigned char msgblocks[8 * 64]; + unsigned int datalen; + unsigned long long msglen; +} sha256x8ctx; + +#define sha256_ctx_clone8x SPX_NAMESPACE(sha256_ctx_clone8x) +void sha256_ctx_clone8x(sha256x8ctx *out, const sha256x8ctx *in); + +#define sha256_init8x SPX_NAMESPACE(sha256_init8x) +void sha256_init8x(sha256x8ctx *ctx); + +#define sha256_final8x SPX_NAMESPACE(sha256_final8x) +void sha256_final8x(sha256x8ctx *ctx, + unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7); + +#define sha256_transform8x SPX_NAMESPACE(sha256_transform8x) +void sha256_transform8x(sha256x8ctx *ctx, + const unsigned char *data0, + const unsigned char *data1, + const unsigned char *data2, + const unsigned char *data3, + const unsigned char *data4, + const unsigned char *data5, + const unsigned char *data6, + const unsigned char *data7); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/sha256x8.c b/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/sha256x8.c new file mode 100644 index 0000000000..d97750c09b --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/sha256x8.c @@ -0,0 +1,185 @@ +#include + +#include "sha256avx.h" +#include "sha256x8.h" +#include "utils.h" + +// Performs sha256x8 on an initialized (and perhaps seeded) state. +static void _sha256x8( + sha256x8ctx *ctx, + unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, unsigned long long inlen) { + unsigned long long i = 0; + while (inlen - i >= 64) { + sha256_transform8x(ctx, + in0 + i, + in1 + i, + in2 + i, + in3 + i, + in4 + i, + in5 + i, + in6 + i, + in7 + i + ); + i += 64; + ctx->msglen += 512; + } + + size_t bytes_to_copy = (size_t)(inlen - i); + memcpy(&ctx->msgblocks[64 * 0], in0 + i, bytes_to_copy); + memcpy(&ctx->msgblocks[64 * 1], in1 + i, bytes_to_copy); + memcpy(&ctx->msgblocks[64 * 2], in2 + i, bytes_to_copy); + memcpy(&ctx->msgblocks[64 * 3], in3 + i, bytes_to_copy); + memcpy(&ctx->msgblocks[64 * 4], in4 + i, bytes_to_copy); + memcpy(&ctx->msgblocks[64 * 5], in5 + i, bytes_to_copy); + memcpy(&ctx->msgblocks[64 * 6], in6 + i, bytes_to_copy); + memcpy(&ctx->msgblocks[64 * 7], in7 + i, bytes_to_copy); + ctx->datalen = (unsigned int)bytes_to_copy; + + sha256_final8x(ctx, out0, out1, out2, out3, out4, out5, out6, out7); +} + +void sha256x8_seeded( + unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const sha256x8ctx *seed, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, unsigned long long inlen) { + + sha256x8ctx ctx; + sha256_ctx_clone8x(&ctx, seed); + + _sha256x8(&ctx, out0, out1, out2, out3, out4, out5, out6, out7, + in0, in1, in2, in3, in4, in5, in6, in7, inlen); +} + +/* This provides a wrapper around the internals of 8x parallel SHA256 */ +void sha256x8(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, unsigned long long inlen) { + sha256x8ctx ctx; + sha256_init8x(&ctx); + + _sha256x8(&ctx, out0, out1, out2, out3, out4, out5, out6, out7, + in0, in1, in2, in3, in4, in5, in6, in7, inlen); +} + +/** + * Note that inlen should be sufficiently small that it still allows for + * an array to be allocated on the stack. Typically 'in' is merely a seed. + * Outputs outlen number of bytes + */ +void mgf1x8(unsigned char *outx8, unsigned long outlen, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, + unsigned long inlen) { + PQCLEAN_VLA(unsigned char, inbufx8, 8 * (inlen + 4)); + unsigned char outbufx8[8 * SPX_SHA256_OUTPUT_BYTES]; + uint32_t i; + unsigned int j; + + memcpy(inbufx8 + 0 * (inlen + 4), in0, inlen); + memcpy(inbufx8 + 1 * (inlen + 4), in1, inlen); + memcpy(inbufx8 + 2 * (inlen + 4), in2, inlen); + memcpy(inbufx8 + 3 * (inlen + 4), in3, inlen); + memcpy(inbufx8 + 4 * (inlen + 4), in4, inlen); + memcpy(inbufx8 + 5 * (inlen + 4), in5, inlen); + memcpy(inbufx8 + 6 * (inlen + 4), in6, inlen); + memcpy(inbufx8 + 7 * (inlen + 4), in7, inlen); + + /* While we can fit in at least another full block of SHA256 output.. */ + for (i = 0; (i + 1)*SPX_SHA256_OUTPUT_BYTES <= outlen; i++) { + for (j = 0; j < 8; j++) { + u32_to_bytes(inbufx8 + inlen + j * (inlen + 4), i); + } + + sha256x8(outx8 + 0 * outlen, + outx8 + 1 * outlen, + outx8 + 2 * outlen, + outx8 + 3 * outlen, + outx8 + 4 * outlen, + outx8 + 5 * outlen, + outx8 + 6 * outlen, + outx8 + 7 * outlen, + inbufx8 + 0 * (inlen + 4), + inbufx8 + 1 * (inlen + 4), + inbufx8 + 2 * (inlen + 4), + inbufx8 + 3 * (inlen + 4), + inbufx8 + 4 * (inlen + 4), + inbufx8 + 5 * (inlen + 4), + inbufx8 + 6 * (inlen + 4), + inbufx8 + 7 * (inlen + 4), inlen + 4); + outx8 += SPX_SHA256_OUTPUT_BYTES; + } + /* Until we cannot anymore, and we fill the remainder. */ + for (j = 0; j < 8; j++) { + u32_to_bytes(inbufx8 + inlen + j * (inlen + 4), i); + } + sha256x8(outbufx8 + 0 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 1 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 2 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 3 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 4 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 5 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 6 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 7 * SPX_SHA256_OUTPUT_BYTES, + inbufx8 + 0 * (inlen + 4), + inbufx8 + 1 * (inlen + 4), + inbufx8 + 2 * (inlen + 4), + inbufx8 + 3 * (inlen + 4), + inbufx8 + 4 * (inlen + 4), + inbufx8 + 5 * (inlen + 4), + inbufx8 + 6 * (inlen + 4), + inbufx8 + 7 * (inlen + 4), inlen + 4); + + for (j = 0; j < 8; j++) { + memcpy(outx8 + j * outlen, + outbufx8 + j * SPX_SHA256_OUTPUT_BYTES, + outlen - i * SPX_SHA256_OUTPUT_BYTES); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/sha256x8.h b/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/sha256x8.h new file mode 100644 index 0000000000..4f7330a6c1 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/sha256x8.h @@ -0,0 +1,64 @@ +#ifndef SPX_SHA256X8_H +#define SPX_SHA256X8_H + +#include "params.h" +#include "sha256avx.h" + + + +#define sha256x8_seeded SPX_NAMESPACE(sha256x8_seeded) +void sha256x8_seeded( + unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const sha256x8ctx *seed, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, unsigned long long inlen); + +/* This provides a wrapper around the internals of 8x parallel SHA256 */ +#define sha256x8 SPX_NAMESPACE(sha256x8) +void sha256x8(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, unsigned long long inlen); + +/** + * Note that inlen should be sufficiently small that it still allows for + * an array to be allocated on the stack. Typically 'in' is merely a seed. + * Outputs outlen number of bytes + */ +#define mgf1x8 SPX_NAMESPACE(mgf1x8) +void mgf1x8(unsigned char *outx8, unsigned long outlen, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, + unsigned long inlen); +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/sha2_offsets.h b/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/sha2_offsets.h new file mode 100644 index 0000000000..6e3584f7a4 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/sha2_offsets.h @@ -0,0 +1,27 @@ +#ifndef SHA2_OFFSETS_H_ +#define SHA2_OFFSETS_H_ + +#define SPX_SHA256_BLOCK_BYTES 64 +#define SPX_SHA256_OUTPUT_BYTES 32 + +#define SPX_SHA512_BLOCK_BYTES 128 +#define SPX_SHA512_OUTPUT_BYTES 64 + +/* + * Offsets of various fields in the address structure when we use SHA2 as + * the Sphincs+ hash function + */ + +#define SPX_OFFSET_LAYER 0 /* The byte used to specify the Merkle tree layer */ +#define SPX_OFFSET_TREE 1 /* The start of the 8 byte field used to specify the tree */ +#define SPX_OFFSET_TYPE 9 /* The byte used to specify the hash type (reason) */ +#define SPX_OFFSET_KP_ADDR2 12 /* The high byte used to specify the key pair (which one-time signature) */ +#define SPX_OFFSET_KP_ADDR1 13 /* The low byte used to specify the key pair */ +#define SPX_OFFSET_CHAIN_ADDR 17 /* The byte used to specify the chain address (which Winternitz chain) */ +#define SPX_OFFSET_HASH_ADDR 21 /* The byte used to specify the hash address (where in the Winternitz chain) */ +#define SPX_OFFSET_TREE_HGT 17 /* The byte used to specify the height of this node in the FORS or Merkle tree */ +#define SPX_OFFSET_TREE_INDEX 18 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ + +#define SPX_SHA2 1 + +#endif /* SHA2_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/sign.c b/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/sign.c new file mode 100644 index 0000000000..9d0c7d1b22 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/sign.c @@ -0,0 +1,286 @@ +#include +#include +#include + +#include "address.h" +#include "context.h" +#include "fors.h" +#include "hash.h" +#include "merkle.h" +#include "nistapi.h" +#include "params.h" +#include "randombytes.h" +#include "thash.h" +#include "utils.h" +#include "wots.h" + +/* + * Returns the length of a secret key, in bytes + */ +size_t crypto_sign_secretkeybytes(void) { + return CRYPTO_SECRETKEYBYTES; +} + +/* + * Returns the length of a public key, in bytes + */ +size_t crypto_sign_publickeybytes(void) { + return CRYPTO_PUBLICKEYBYTES; +} + +/* + * Returns the length of a signature, in bytes + */ +size_t crypto_sign_bytes(void) { + return CRYPTO_BYTES; +} + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +size_t crypto_sign_seedbytes(void) { + return CRYPTO_SEEDBYTES; +} + +/* + * Generates an SPX key pair given a seed of length + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [PUB_SEED || root] + */ +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed) { + spx_ctx ctx; + + /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ + memcpy(sk, seed, CRYPTO_SEEDBYTES); + + memcpy(pk, sk + 2 * SPX_N, SPX_N); + + memcpy(ctx.pub_seed, pk, SPX_N); + memcpy(ctx.sk_seed, sk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + /* Compute root node of the top-most subtree. */ + merkle_gen_root(sk + 3 * SPX_N, &ctx); + + // cleanup + free_hash_function(&ctx); + + memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); + + return 0; +} + +/* + * Generates an SPX key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [PUB_SEED || root] + */ +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { + uint8_t seed[CRYPTO_SEEDBYTES]; + randombytes(seed, CRYPTO_SEEDBYTES); + crypto_sign_seed_keypair(pk, sk, seed); + + return 0; +} + +/** + * Returns an array containing a detached signature. + */ +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk) { + spx_ctx ctx; + + const uint8_t *sk_prf = sk + SPX_N; + const uint8_t *pk = sk + 2 * SPX_N; + + uint8_t optrand[SPX_N]; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t root[SPX_N]; + uint32_t i; + uint64_t tree; + uint32_t idx_leaf; + uint32_t wots_addr[8] = {0}; + uint32_t tree_addr[8] = {0}; + + memcpy(ctx.sk_seed, sk, SPX_N); + memcpy(ctx.pub_seed, pk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + + /* Optionally, signing can be made non-deterministic using optrand. + This can help counter side-channel attacks that would benefit from + getting a large number of traces when the signer uses the same nodes. */ + randombytes(optrand, SPX_N); + /* Compute the digest randomization value. */ + gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); + + /* Derive the message digest and leaf index from R, PK and M. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; + + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); + + /* Sign the message hash using FORS. */ + fors_sign(sig, root, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); + sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; + + /* Update the indices for the next layer. */ + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; + } + + free_hash_function(&ctx); + + *siglen = SPX_BYTES; + + return 0; +} + +/** + * Verifies a detached signature and message under a given public key. + */ +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk) { + spx_ctx ctx; + const uint8_t *pub_root = pk + SPX_N; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t wots_pk[SPX_WOTS_BYTES]; + uint8_t root[SPX_N]; + uint8_t leaf[SPX_N]; + unsigned int i; + uint64_t tree; + uint32_t idx_leaf; + uint32_t wots_addr[8] = {0}; + uint32_t tree_addr[8] = {0}; + uint32_t wots_pk_addr[8] = {0}; + + if (siglen != SPX_BYTES) { + return -1; + } + + memcpy(ctx.pub_seed, pk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); + + /* Derive the message digest and leaf index from R || PK || M. */ + /* The additional SPX_N is a result of the hash domain separator. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; + + /* Layer correctly defaults to 0, so no need to set_layer_addr */ + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); + + fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + /* For each subtree.. */ + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + copy_keypair_addr(wots_pk_addr, wots_addr); + + /* The WOTS public key is only correct if the signature was correct. */ + /* Initially, root is the FORS pk, but on subsequent iterations it is + the root of the subtree below the currently processed subtree. */ + wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); + sig += SPX_WOTS_BYTES; + + /* Compute the leaf node using the WOTS public key. */ + thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); + + /* Compute the root node of this subtree. */ + compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, + &ctx, tree_addr); + sig += SPX_TREE_HEIGHT * SPX_N; + + /* Update the indices for the next layer. */ + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; + } + + // cleanup + free_hash_function(&ctx); + + /* Check if the root node equals the root node in the public key. */ + if (memcmp(root, pub_root, SPX_N) != 0) { + return -1; + } + + return 0; +} + + +/** + * Returns an array containing the signature followed by the message. + */ +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk) { + size_t siglen; + + crypto_sign_signature(sm, &siglen, m, mlen, sk); + + memmove(sm + SPX_BYTES, m, mlen); + *smlen = siglen + mlen; + + return 0; +} + +/** + * Verifies a given signature-message pair under a given public key. + */ +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk) { + /* The API caller does not necessarily know what size a signature should be + but SPHINCS+ signatures are always exactly SPX_BYTES. */ + if (smlen < SPX_BYTES) { + memset(m, 0, smlen); + *mlen = 0; + return -1; + } + + *mlen = smlen - SPX_BYTES; + + if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { + memset(m, 0, smlen); + *mlen = 0; + return -1; + } + + /* If verification was successful, move the message to the right place. */ + memmove(m, sm + SPX_BYTES, *mlen); + + return 0; +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/thash.h b/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/thash.h new file mode 100644 index 0000000000..8687ccfb4d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/thash.h @@ -0,0 +1,13 @@ +#ifndef SPX_THASH_H +#define SPX_THASH_H + +#include "context.h" +#include "params.h" + +#include + +#define thash SPX_NAMESPACE(thash) +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/thash_sha2_simple.c b/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/thash_sha2_simple.c new file mode 100644 index 0000000000..197b4e7a0a --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/thash_sha2_simple.c @@ -0,0 +1,32 @@ +#include +#include + +#include "thash.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "sha2.h" +#include "utils.h" + + +/** + * Takes an array of inblocks concatenated arrays of SPX_N bytes. + */ +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]) { + + unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES]; + sha256ctx sha2_state; + PQCLEAN_VLA(uint8_t, buf, SPX_SHA256_ADDR_BYTES + inblocks * SPX_N); + + /* Retrieve precomputed state containing pub_seed */ + sha256_inc_ctx_clone(&sha2_state, &ctx->state_seeded); + + memcpy(buf, addr, SPX_SHA256_ADDR_BYTES); + memcpy(buf + SPX_SHA256_ADDR_BYTES, in, inblocks * SPX_N); + + sha256_inc_finalize(outbuf, &sha2_state, buf, SPX_SHA256_ADDR_BYTES + inblocks * SPX_N); + memcpy(out, outbuf, SPX_N); +} + diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/thash_sha2_simplex8.c b/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/thash_sha2_simplex8.c new file mode 100644 index 0000000000..eb491a0a43 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/thash_sha2_simplex8.c @@ -0,0 +1,96 @@ +#include +#include + +#include "thashx8.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "sha2.h" +#include "sha256avx.h" +#include "sha256x8.h" +#include "utils.h" + + +/** + * 8-way parallel version of thash; takes 8x as much input and output + */ +void thashx8(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addrx8[8 * 8]) { + PQCLEAN_VLA(unsigned char, bufx8, 8 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)); + unsigned char outbufx8[8 * SPX_SHA256_OUTPUT_BYTES]; + unsigned int i; + + for (i = 0; i < 8; i++) { + memcpy(bufx8 + i * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + addrx8 + i * 8, SPX_SHA256_ADDR_BYTES); + } + + memcpy(bufx8 + SPX_SHA256_ADDR_BYTES + + 0 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), in0, inblocks * SPX_N); + memcpy(bufx8 + SPX_SHA256_ADDR_BYTES + + 1 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), in1, inblocks * SPX_N); + memcpy(bufx8 + SPX_SHA256_ADDR_BYTES + + 2 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), in2, inblocks * SPX_N); + memcpy(bufx8 + SPX_SHA256_ADDR_BYTES + + 3 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), in3, inblocks * SPX_N); + memcpy(bufx8 + SPX_SHA256_ADDR_BYTES + + 4 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), in4, inblocks * SPX_N); + memcpy(bufx8 + SPX_SHA256_ADDR_BYTES + + 5 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), in5, inblocks * SPX_N); + memcpy(bufx8 + SPX_SHA256_ADDR_BYTES + + 6 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), in6, inblocks * SPX_N); + memcpy(bufx8 + SPX_SHA256_ADDR_BYTES + + 7 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), in7, inblocks * SPX_N); + + sha256x8_seeded( + /* out */ + outbufx8 + 0 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 1 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 2 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 3 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 4 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 5 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 6 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 7 * SPX_SHA256_OUTPUT_BYTES, + + /* seed */ + &ctx->statex8_seeded, + + /* in */ + bufx8 + 0 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + 1 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + 2 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + 3 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + 4 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + 5 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + 6 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + 7 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N /* len */ + ); + + memcpy(out0, outbufx8 + 0 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out1, outbufx8 + 1 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out2, outbufx8 + 2 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out3, outbufx8 + 3 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out4, outbufx8 + 4 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out5, outbufx8 + 5 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out6, outbufx8 + 6 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out7, outbufx8 + 7 * SPX_SHA256_OUTPUT_BYTES, SPX_N); +} + diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/thashx8.h b/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/thashx8.h new file mode 100644 index 0000000000..c02fe9cf3e --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/thashx8.h @@ -0,0 +1,28 @@ +#ifndef SPX_THASHX8_H +#define SPX_THASHX8_H + +#include + +#include "context.h" +#include "params.h" + +#define thashx8 SPX_NAMESPACE(thashx8) +void thashx8(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addrx8[8 * 8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/utils.c b/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/utils.c new file mode 100644 index 0000000000..177b541fb9 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/utils.c @@ -0,0 +1,148 @@ +#include + +#include "utils.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "thash.h" + +/** + * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. + */ +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in) { + int i; + + /* Iterate over out in decreasing order, for big-endianness. */ + for (i = (signed int)outlen - 1; i >= 0; i--) { + out[i] = in & 0xff; + in = in >> 8; + } +} + +void u32_to_bytes(unsigned char *out, uint32_t in) { + out[0] = (unsigned char)(in >> 24); + out[1] = (unsigned char)(in >> 16); + out[2] = (unsigned char)(in >> 8); + out[3] = (unsigned char)in; +} + +/** + * Converts the inlen bytes in 'in' from big-endian byte order to an integer. + */ +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { + unsigned long long retval = 0; + unsigned int i; + + for (i = 0; i < inlen; i++) { + retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); + } + return retval; +} + +/** + * Computes a root node given a leaf and an auth path. + * Expects address to be complete other than the tree_height and tree_index. + */ +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]) { + uint32_t i; + unsigned char buffer[2 * SPX_N]; + + /* If leaf_idx is odd (last bit = 1), current path element is a right child + and auth_path has to go left. Otherwise it is the other way around. */ + if (leaf_idx & 1) { + memcpy(buffer + SPX_N, leaf, SPX_N); + memcpy(buffer, auth_path, SPX_N); + } else { + memcpy(buffer, leaf, SPX_N); + memcpy(buffer + SPX_N, auth_path, SPX_N); + } + auth_path += SPX_N; + + for (i = 0; i < tree_height - 1; i++) { + leaf_idx >>= 1; + idx_offset >>= 1; + /* Set the address of the node we're creating. */ + set_tree_height(addr, i + 1); + set_tree_index(addr, leaf_idx + idx_offset); + + /* Pick the right or left neighbor, depending on parity of the node. */ + if (leaf_idx & 1) { + thash(buffer + SPX_N, buffer, 2, ctx, addr); + memcpy(buffer, auth_path, SPX_N); + } else { + thash(buffer, buffer, 2, ctx, addr); + memcpy(buffer + SPX_N, auth_path, SPX_N); + } + auth_path += SPX_N; + } + + /* The last iteration is exceptional; we do not copy an auth_path node. */ + leaf_idx >>= 1; + idx_offset >>= 1; + set_tree_height(addr, tree_height); + set_tree_index(addr, leaf_idx + idx_offset); + thash(root, buffer, 2, ctx, addr); +} + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx * /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]) { + PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); + PQCLEAN_VLA(unsigned int, heights, tree_height + 1); + unsigned int offset = 0; + uint32_t idx; + uint32_t tree_idx; + + for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { + /* Add the next leaf node to the stack. */ + gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); + offset++; + heights[offset - 1] = 0; + + /* If this is a node we need for the auth path.. */ + if ((leaf_idx ^ 0x1) == idx) { + memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); + } + + /* While the top-most nodes are of equal height.. */ + while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { + /* Compute index of the new node, in the next layer. */ + tree_idx = (idx >> (heights[offset - 1] + 1)); + + /* Set the address of the node we're creating. */ + set_tree_height(tree_addr, heights[offset - 1] + 1); + set_tree_index(tree_addr, + tree_idx + (idx_offset >> (heights[offset - 1] + 1))); + /* Hash the top-most nodes from the stack together. */ + thash(stack + (offset - 2)*SPX_N, + stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); + offset--; + /* Note that the top-most node is now one layer higher. */ + heights[offset - 1]++; + + /* If this is a node we need for the auth path.. */ + if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { + memcpy(auth_path + heights[offset - 1]*SPX_N, + stack + (offset - 1)*SPX_N, SPX_N); + } + } + } + memcpy(root, stack, SPX_N); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/utils.h b/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/utils.h new file mode 100644 index 0000000000..64f5d5a53a --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/utils.h @@ -0,0 +1,58 @@ +#ifndef SPX_UTILS_H +#define SPX_UTILS_H + +#include + +#include "compat.h" +#include "context.h" +#include "params.h" + + +/* To support MSVC use alloca() instead of VLAs. See #20. */ + + +/** + * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. + */ +#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in); +#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) +void u32_to_bytes(unsigned char *out, uint32_t in); + +/** + * Converts the inlen bytes in 'in' from big-endian byte order to an integer. + */ +#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); + +/** + * Computes a root node given a leaf and an auth path. + * Expects address to be complete other than the tree_height and tree_index. + */ +#define compute_root SPX_NAMESPACE(compute_root) +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]); + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +#define treehash SPX_NAMESPACE(treehash) +void treehash(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx *ctx /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]); + + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/utilsx8.c b/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/utilsx8.c new file mode 100644 index 0000000000..f044b9595d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/utilsx8.c @@ -0,0 +1,146 @@ +#include + +#include "utils.h" +#include "utilsx8.h" + +#include "address.h" +#include "params.h" +#include "thashx8.h" + +/* + * Generate the entire Merkle tree, computing the authentication path for leaf_idx, + * and the resulting root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) + * + * This expects tree_addrx8 to be initialized to 8 parallel addr structures for + * the Merkle tree nodes + * + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + * + * This works by using the standard Merkle tree building algorithm, except + * that each 'node' tracked is actually 8 consecutive nodes in the real tree. + * When we combine two logical nodes ABCDEFGH and STUVWXYZ, we perform the H + * operation on adjacent real nodes, forming the parent logical node + * (AB)(CD)(EF)(GH)(ST)(UV)(WX)(YZ) + * + * When we get to the top three levels of the real tree (where there is only + * one logical node), we continue this operation three more times; the right + * most real node will by the actual root (and the other 7 nodes will be + * garbage). We follow the same thashx8 logic so that the 'extract + * authentication path components' part of the loop is still executed (and + * to simplify the code somewhat) + * + * This currently assumes tree_height >= 3; I suspect that doing an adjusting + * idx, addr_idx on the gen_leafx8 call if tree_height < 3 would fix it; since + * we don't actually use such short trees, I haven't bothered + */ +void treehashx8(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, + uint32_t tree_height, + void (*gen_leafx8)( + unsigned char * /* Where to write the leaves */, + const spx_ctx *, + uint32_t idx, void *info), + uint32_t tree_addrx8[8 * 8], + void *info) { + /* This is where we keep the intermediate nodes */ + PQCLEAN_VLA(unsigned char, stackx8, tree_height * 8 * SPX_N); + uint32_t left_adj = 0, prev_left_adj = 0; /* When we're doing the top 3 */ + /* levels, the left-most part of the tree isn't at the beginning */ + /* of current[]. These give the offset of the actual start */ + + uint32_t idx; + uint32_t max_idx = ((uint32_t)1 << (tree_height - 3)) - 1; + for (idx = 0;; idx++) { + unsigned char current[8 * SPX_N]; /* Current logical node */ + gen_leafx8( current, ctx, 8 * idx + idx_offset, + info ); + + /* Now combine the freshly generated right node with previously */ + /* generated left ones */ + uint32_t internal_idx_offset = idx_offset; + uint32_t internal_idx = idx; + uint32_t internal_leaf = leaf_idx; + uint32_t h; /* The height we are in the Merkle tree */ + for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { + + /* Special processing if we're at the top of the tree */ + if (h >= tree_height - 3) { + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[7 * SPX_N], SPX_N ); + return; + } + /* The tree indexing logic is a bit off in this case */ + /* Adjust it so that the left-most node of the part of */ + /* the tree that we're processing has index 0 */ + prev_left_adj = left_adj; + left_adj = (uint32_t)(8 - (1 << (tree_height - h - 1))); + } + + /* Check if we hit the top of the tree */ + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[7 * SPX_N], SPX_N ); + return; + } + + /* + * Check if one of the nodes we have is a part of the + * authentication path; if it is, write it out + */ + if ((((internal_idx << 3) ^ internal_leaf) & ~0x7U) == 0) { + memcpy( &auth_path[ h * SPX_N ], + ¤t[(((internal_leaf & 7) ^ 1) + prev_left_adj) * SPX_N], + SPX_N ); + } + + /* + * Check if we're at a left child; if so, stop going up the stack + * Exception: if we've reached the end of the tree, keep on going + * (so we combine the last 8 nodes into the one root node in three + * more iterations) + */ + if ((internal_idx & 1) == 0 && idx < max_idx) { + break; + } + + /* Ok, we're at a right node (or doing the top 3 levels) */ + /* Now combine the left and right logical nodes together */ + + /* Set the address of the node we're creating. */ + uint32_t j; + internal_idx_offset >>= 1; + for (j = 0; j < 8; j++) { + set_tree_height(tree_addrx8 + j * 8, h + 1); + set_tree_index(tree_addrx8 + j * 8, + (8 / 2) * (internal_idx & ~1U) + j - left_adj + internal_idx_offset ); + } + unsigned char *left = &stackx8[h * 8 * SPX_N]; + thashx8( ¤t[0 * SPX_N], + ¤t[1 * SPX_N], + ¤t[2 * SPX_N], + ¤t[3 * SPX_N], + ¤t[4 * SPX_N], + ¤t[5 * SPX_N], + ¤t[6 * SPX_N], + ¤t[7 * SPX_N], + &left [0 * SPX_N], + &left [2 * SPX_N], + &left [4 * SPX_N], + &left [6 * SPX_N], + ¤t[0 * SPX_N], + ¤t[2 * SPX_N], + ¤t[4 * SPX_N], + ¤t[6 * SPX_N], + 2, ctx, tree_addrx8); + } + + /* We've hit a left child; save the current for when we get the */ + /* corresponding right right */ + memcpy( &stackx8[h * 8 * SPX_N], current, 8 * SPX_N); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/utilsx8.h b/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/utilsx8.h new file mode 100644 index 0000000000..806d1e85be --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/utilsx8.h @@ -0,0 +1,29 @@ +#ifndef SPX_UTILSX8_H +#define SPX_UTILSX8_H + +#include + +#include "params.h" + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + * + * This implementation uses AVX to compute internal nodes 8 at a time (in + * parallel) + */ +#define treehashx8 SPX_NAMESPACE(treehashx8) +void treehashx8(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leafx8)( + unsigned char * /* Where to write the leaves */, + const spx_ctx * /* ctx */, + uint32_t addr_idx, void *info), + uint32_t tree_addrx8[8 * 8], void *info); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/wots.c b/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/wots.c new file mode 100644 index 0000000000..689baf4db9 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/wots.c @@ -0,0 +1,291 @@ +#include +#include + +#include "wots.h" + +#include "address.h" +#include "hash.h" +#include "hashx8.h" +#include "params.h" +#include "thash.h" +#include "thashx8.h" +#include "utils.h" +#include "utilsx8.h" +#include "wotsx8.h" + +// TODO clarify address expectations, and make them more uniform. +// TODO i.e. do we expect types to be set already? +// TODO and do we expect modifications or copies? + +/** + * Computes up the chains + */ +static void gen_chains( + unsigned char *out, + const unsigned char *in, + unsigned int start[SPX_WOTS_LEN], + const unsigned int steps[SPX_WOTS_LEN], + const spx_ctx *ctx, + uint32_t addr[8]) { + uint32_t i, j, k, idx, watching; + int done; + unsigned char empty[SPX_N]; + unsigned char *bufs[8]; + uint32_t addrs[8 * 8]; + + int l; + uint16_t counts[SPX_WOTS_W] = { 0 }; + uint16_t idxs[SPX_WOTS_LEN]; + uint16_t total, newTotal; + + /* set addrs = {addr, addr, ..., addr} */ + for (j = 0; j < 8; j++) { + memcpy(addrs + j * 8, addr, sizeof(uint32_t) * 8); + } + + /* Initialize out with the value at position 'start'. */ + memcpy(out, in, SPX_WOTS_LEN * SPX_N); + + /* Sort the chains in reverse order by steps using counting sort. */ + for (i = 0; i < SPX_WOTS_LEN; i++) { + counts[steps[i]]++; + } + total = 0; + for (l = SPX_WOTS_W - 1; l >= 0; l--) { + newTotal = counts[l] + total; + counts[l] = total; + total = newTotal; + } + for (i = 0; i < SPX_WOTS_LEN; i++) { + idxs[counts[steps[i]]] = (uint16_t)i; + counts[steps[i]]++; + } + + /* We got our work cut out for us: do it! */ + for (i = 0; i < SPX_WOTS_LEN; i += 8) { + for (j = 0; j < 8 && i + j < SPX_WOTS_LEN; j++) { + idx = idxs[i + j]; + set_chain_addr(addrs + j * 8, idx); + bufs[j] = out + SPX_N * idx; + } + + /* As the chains are sorted in reverse order, we know that the first + * chain is the longest and the last one is the shortest. We keep + * an eye on whether the last chain is done and then on the one before, + * et cetera. */ + watching = 7; + done = 0; + while (i + watching >= SPX_WOTS_LEN) { + bufs[watching] = &empty[0]; + watching--; + } + + for (k = 0;; k++) { + while (k == steps[idxs[i + watching]]) { + bufs[watching] = &empty[0]; + if (watching == 0) { + done = 1; + break; + } + watching--; + } + if (done) { + break; + } + for (j = 0; j < watching + 1; j++) { + set_hash_addr(addrs + j * 8, k + start[idxs[i + j]]); + } + + thashx8(bufs[0], bufs[1], bufs[2], bufs[3], + bufs[4], bufs[5], bufs[6], bufs[7], + bufs[0], bufs[1], bufs[2], bufs[3], + bufs[4], bufs[5], bufs[6], bufs[7], 1, ctx, addrs); + } + } +} + +/** + * base_w algorithm as described in draft. + * Interprets an array of bytes as integers in base w. + * This only works when log_w is a divisor of 8. + */ +static void base_w(unsigned int *output, const int out_len, + const unsigned char *input) { + int in = 0; + int out = 0; + unsigned char total = 0; + int bits = 0; + int consumed; + + for (consumed = 0; consumed < out_len; consumed++) { + if (bits == 0) { + total = input[in]; + in++; + bits += 8; + } + bits -= SPX_WOTS_LOGW; + output[out] = (total >> bits) & (SPX_WOTS_W - 1); + out++; + } +} + +/* Computes the WOTS+ checksum over a message (in base_w). */ +static void wots_checksum(unsigned int *csum_base_w, + const unsigned int *msg_base_w) { + unsigned int csum = 0; + unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; + unsigned int i; + + /* Compute checksum. */ + for (i = 0; i < SPX_WOTS_LEN1; i++) { + csum += SPX_WOTS_W - 1 - msg_base_w[i]; + } + + /* Convert checksum to base_w. */ + /* Make sure expected empty zero bits are the least significant bits. */ + csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); + ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); + base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); +} + +/* Takes a message and derives the matching chain lengths. */ +void chain_lengths(unsigned int *lengths, const unsigned char *msg) { + base_w(lengths, SPX_WOTS_LEN1, msg); + wots_checksum(lengths + SPX_WOTS_LEN1, lengths); +} + +/** + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. + * + * Writes the computed public key to 'pk'. + */ +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]) { + unsigned int steps[SPX_WOTS_LEN]; + unsigned int start[SPX_WOTS_LEN]; + uint32_t i; + + chain_lengths(start, msg); + + for (i = 0; i < SPX_WOTS_LEN; i++) { + steps[i] = SPX_WOTS_W - 1 - start[i]; + } + + gen_chains(pk, sig, start, steps, ctx, addr); +} + +/* + * This generates 8 sequential WOTS public keys + * It also generates the WOTS signature if leaf_info indicates + * that we're signing with one of these WOTS keys + */ +void wots_gen_leafx8(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info) { + struct leaf_info_x8 *info = v_info; + uint32_t *leaf_addr = info->leaf_addr; + uint32_t *pk_addr = info->pk_addr; + unsigned int i, j, k; + unsigned char pk_buffer[ 8 * SPX_WOTS_BYTES ]; + unsigned wots_offset = SPX_WOTS_BYTES; + unsigned char *buffer; + uint32_t wots_k_mask; + unsigned wots_sign_index; + + if (((leaf_idx ^ info->wots_sign_leaf) & ~7U) == 0) { + /* We're traversing the leaf that's signing; generate the WOTS */ + /* signature */ + wots_k_mask = 0; + wots_sign_index = info->wots_sign_leaf & 7; /* Which of of the 8 */ + /* slots do the signatures come from */ + } else { + /* Nope, we're just generating pk's; turn off the signature logic */ + wots_k_mask = ~0U; + wots_sign_index = 0; + } + + for (j = 0; j < 8; j++) { + set_keypair_addr( leaf_addr + j * 8, leaf_idx + j ); + set_keypair_addr( pk_addr + j * 8, leaf_idx + j ); + } + + for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { + uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k */ + /* to the step if we're generating a signature, ~0 if we're not */ + + /* Start with the secret seed */ + for (j = 0; j < 8; j++) { + set_chain_addr(leaf_addr + j * 8, i); + set_hash_addr(leaf_addr + j * 8, 0); + set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTSPRF); + } + prf_addrx8(buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + buffer + 2 * wots_offset, + buffer + 3 * wots_offset, + buffer + 4 * wots_offset, + buffer + 5 * wots_offset, + buffer + 6 * wots_offset, + buffer + 7 * wots_offset, + ctx, leaf_addr); + + for (j = 0; j < 8; j++) { + set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTS); + } + + /* Iterate down the WOTS chain */ + for (k = 0;; k++) { + /* Check if one of the values we have needs to be saved as a */ + /* part of the WOTS signature */ + if (k == wots_k) { + memcpy( info->wots_sig + i * SPX_N, + buffer + wots_sign_index * wots_offset, SPX_N ); + } + + /* Check if we hit the top of the chain */ + if (k == SPX_WOTS_W - 1) { + break; + } + + /* Iterate one step on all 8 chains */ + for (j = 0; j < 8; j++) { + set_hash_addr(leaf_addr + j * 8, k); + } + thashx8(buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + buffer + 2 * wots_offset, + buffer + 3 * wots_offset, + buffer + 4 * wots_offset, + buffer + 5 * wots_offset, + buffer + 6 * wots_offset, + buffer + 7 * wots_offset, + buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + buffer + 2 * wots_offset, + buffer + 3 * wots_offset, + buffer + 4 * wots_offset, + buffer + 5 * wots_offset, + buffer + 6 * wots_offset, + buffer + 7 * wots_offset, 1, ctx, leaf_addr); + } + } + + /* Do the final thash to generate the public keys */ + thashx8(dest + 0 * SPX_N, + dest + 1 * SPX_N, + dest + 2 * SPX_N, + dest + 3 * SPX_N, + dest + 4 * SPX_N, + dest + 5 * SPX_N, + dest + 6 * SPX_N, + dest + 7 * SPX_N, + pk_buffer + 0 * wots_offset, + pk_buffer + 1 * wots_offset, + pk_buffer + 2 * wots_offset, + pk_buffer + 3 * wots_offset, + pk_buffer + 4 * wots_offset, + pk_buffer + 5 * wots_offset, + pk_buffer + 6 * wots_offset, + pk_buffer + 7 * wots_offset, SPX_WOTS_LEN, ctx, pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/wots.h b/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/wots.h new file mode 100644 index 0000000000..4e7692eeef --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/wots.h @@ -0,0 +1,25 @@ +#ifndef SPX_WOTS_H +#define SPX_WOTS_H + +#include + +#include "context.h" +#include "params.h" + +/** + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. + * + * Writes the computed public key to 'pk'. + */ +#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]); + +/* + * Compute the chain lengths needed for a given message hash + */ +#define chain_lengths SPX_NAMESPACE(chain_lengths) +void chain_lengths(unsigned int *lengths, const unsigned char *msg); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/wotsx8.h b/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/wotsx8.h new file mode 100644 index 0000000000..10866efb35 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_avx2/wotsx8.h @@ -0,0 +1,42 @@ +#ifndef WOTSX8_H_ +#define WOTSX8_H_ + +#include + +#include "context.h" +#include "params.h" + +/* + * This is here to provide an interface to the internal wots_gen_leafx8 + * routine. While this routine is not referenced in the package outside of + * wots.c, it is called from the stand-alone benchmark code to characterize + * the performance + */ +struct leaf_info_x8 { + unsigned char *wots_sig; + uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ + uint32_t *wots_steps; + uint32_t leaf_addr[8 * 8]; + uint32_t pk_addr[8 * 8]; +}; + +/* Macro to set the leaf_info to something 'benign', that is, it would */ +/* run with the same time as it does during the real signing process */ +/* Used only by the benchmark code */ +#define INITIALIZE_LEAF_INFO_X8(info, addr, step_buffer) { \ + (info).wots_sig = 0; \ + (info).wots_sign_leaf = ~0; \ + (info).wots_steps = step_buffer; \ + int i; \ + for (i=0; i<8; i++) { \ + memcpy( &(info).leaf_addr[8*i], addr, 32 ); \ + memcpy( &(info).pk_addr[8*i], addr, 32 ); \ + } \ + } + +#define wots_gen_leafx8 SPX_NAMESPACE(wots_gen_leafx8) +void wots_gen_leafx8(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info); + +#endif /* WOTSX8_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_clean/LICENSE b/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_clean/LICENSE new file mode 100644 index 0000000000..670154e353 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_clean/LICENSE @@ -0,0 +1,116 @@ +CC0 1.0 Universal + +Statement of Purpose + +The laws of most jurisdictions throughout the world automatically confer +exclusive Copyright and Related Rights (defined below) upon the creator and +subsequent owner(s) (each and all, an "owner") of an original work of +authorship and/or a database (each, a "Work"). + +Certain owners wish to permanently relinquish those rights to a Work for the +purpose of contributing to a commons of creative, cultural and scientific +works ("Commons") that the public can reliably and without fear of later +claims of infringement build upon, modify, incorporate in other works, reuse +and redistribute as freely as possible in any form whatsoever and for any +purposes, including without limitation commercial purposes. These owners may +contribute to the Commons to promote the ideal of a free culture and the +further production of creative, cultural and scientific works, or to gain +reputation or greater distribution for their Work in part through the use and +efforts of others. + +For these and/or other purposes and motivations, and without any expectation +of additional consideration or compensation, the person associating CC0 with a +Work (the "Affirmer"), to the extent that he or she is an owner of Copyright +and Related Rights in the Work, voluntarily elects to apply CC0 to the Work +and publicly distribute the Work under its terms, with knowledge of his or her +Copyright and Related Rights in the Work and the meaning and intended legal +effect of CC0 on those rights. + +1. Copyright and Related Rights. A Work made available under CC0 may be +protected by copyright and related or neighboring rights ("Copyright and +Related Rights"). Copyright and Related Rights include, but are not limited +to, the following: + + i. the right to reproduce, adapt, distribute, perform, display, communicate, + and translate a Work; + + ii. moral rights retained by the original author(s) and/or performer(s); + + iii. publicity and privacy rights pertaining to a person's image or likeness + depicted in a Work; + + iv. rights protecting against unfair competition in regards to a Work, + subject to the limitations in paragraph 4(a), below; + + v. rights protecting the extraction, dissemination, use and reuse of data in + a Work; + + vi. database rights (such as those arising under Directive 96/9/EC of the + European Parliament and of the Council of 11 March 1996 on the legal + protection of databases, and under any national implementation thereof, + including any amended or successor version of such directive); and + + vii. other similar, equivalent or corresponding rights throughout the world + based on applicable law or treaty, and any national implementations thereof. + +2. Waiver. To the greatest extent permitted by, but not in contravention of, +applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and +unconditionally waives, abandons, and surrenders all of Affirmer's Copyright +and Related Rights and associated claims and causes of action, whether now +known or unknown (including existing as well as future claims and causes of +action), in the Work (i) in all territories worldwide, (ii) for the maximum +duration provided by applicable law or treaty (including future time +extensions), (iii) in any current or future medium and for any number of +copies, and (iv) for any purpose whatsoever, including without limitation +commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes +the Waiver for the benefit of each member of the public at large and to the +detriment of Affirmer's heirs and successors, fully intending that such Waiver +shall not be subject to revocation, rescission, cancellation, termination, or +any other legal or equitable action to disrupt the quiet enjoyment of the Work +by the public as contemplated by Affirmer's express Statement of Purpose. + +3. Public License Fallback. Should any part of the Waiver for any reason be +judged legally invalid or ineffective under applicable law, then the Waiver +shall be preserved to the maximum extent permitted taking into account +Affirmer's express Statement of Purpose. In addition, to the extent the Waiver +is so judged Affirmer hereby grants to each affected person a royalty-free, +non transferable, non sublicensable, non exclusive, irrevocable and +unconditional license to exercise Affirmer's Copyright and Related Rights in +the Work (i) in all territories worldwide, (ii) for the maximum duration +provided by applicable law or treaty (including future time extensions), (iii) +in any current or future medium and for any number of copies, and (iv) for any +purpose whatsoever, including without limitation commercial, advertising or +promotional purposes (the "License"). The License shall be deemed effective as +of the date CC0 was applied by Affirmer to the Work. Should any part of the +License for any reason be judged legally invalid or ineffective under +applicable law, such partial invalidity or ineffectiveness shall not +invalidate the remainder of the License, and in such case Affirmer hereby +affirms that he or she will not (i) exercise any of his or her remaining +Copyright and Related Rights in the Work or (ii) assert any associated claims +and causes of action with respect to the Work, in either case contrary to +Affirmer's express Statement of Purpose. + +4. Limitations and Disclaimers. + + a. No trademark or patent rights held by Affirmer are waived, abandoned, + surrendered, licensed or otherwise affected by this document. + + b. Affirmer offers the Work as-is and makes no representations or warranties + of any kind concerning the Work, express, implied, statutory or otherwise, + including without limitation warranties of title, merchantability, fitness + for a particular purpose, non infringement, or the absence of latent or + other defects, accuracy, or the present or absence of errors, whether or not + discoverable, all to the greatest extent permissible under applicable law. + + c. Affirmer disclaims responsibility for clearing rights of other persons + that may apply to the Work or any use thereof, including without limitation + any person's Copyright and Related Rights in the Work. Further, Affirmer + disclaims responsibility for obtaining any necessary consents, permissions + or other rights required for any use of the Work. + + d. Affirmer understands and acknowledges that Creative Commons is not a + party to this document and has no duty or obligation with respect to this + CC0 or use of the Work. + +For more information, please see + diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_clean/address.c b/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_clean/address.c new file mode 100644 index 0000000000..d49d9f3b6b --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_clean/address.c @@ -0,0 +1,95 @@ +#include +#include + +#include "address.h" +#include "params.h" +#include "utils.h" + +/* + * Specify which level of Merkle tree (the "layer") we're working on + */ +void set_layer_addr(uint32_t addr[8], uint32_t layer) { + ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; +} + +/* + * Specify which Merkle tree within the level (the "tree address") we're working on + */ +void set_tree_addr(uint32_t addr[8], uint64_t tree) { + ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); +} + +/* + * Specify the reason we'll use this address structure for, that is, what + * hash will we compute with it. This is used so that unrelated types of + * hashes don't accidentally get the same address structure. The type will be + * one of the SPX_ADDR_TYPE constants + */ +void set_type(uint32_t addr[8], uint32_t type) { + ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; +} + +/* + * Copy the layer and tree fields of the address structure. This is used + * when we're doing multiple types of hashes within the same Merkle tree + */ +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); +} + +/* These functions are used for OTS addresses. */ + +/* + * Specify which Merkle leaf we're working on; that is, which OTS keypair + * we're talking about. + */ +void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { + /* We have > 256 OTS at the bottom of the Merkle tree; to specify */ + /* which one, we'd need to express it in two bytes */ + ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR2] = (unsigned char)(keypair >> 8); + ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; +} + +/* + * Copy the layer, tree and keypair fields of the address structure. This is + * used when we're doing multiple things within the same OTS keypair + */ +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); + ((unsigned char *)out)[SPX_OFFSET_KP_ADDR2] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR2]; + ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; +} + +/* + * Specify which Merkle chain within the OTS we're working with + * (the chain address) + */ +void set_chain_addr(uint32_t addr[8], uint32_t chain) { + ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; +} + +/* + * Specify where in the Merkle chain we are +* (the hash address) + */ +void set_hash_addr(uint32_t addr[8], uint32_t hash) { + ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; +} + +/* These functions are used for all hash tree addresses (including FORS). */ + +/* + * Specify the height of the node in the Merkle/FORS tree we are in + * (the tree height) + */ +void set_tree_height(uint32_t addr[8], uint32_t tree_height) { + ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; +} + +/* + * Specify the distance from the left edge of the node in the Merkle/FORS tree + * (the tree index) + */ +void set_tree_index(uint32_t addr[8], uint32_t tree_index) { + u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_clean/address.h b/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_clean/address.h new file mode 100644 index 0000000000..24a84eb40c --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_clean/address.h @@ -0,0 +1,52 @@ +#ifndef SPX_ADDRESS_H +#define SPX_ADDRESS_H + +#include + +#include "params.h" + +/* The hash types that are passed to set_type */ +#define SPX_ADDR_TYPE_WOTS 0 +#define SPX_ADDR_TYPE_WOTSPK 1 +#define SPX_ADDR_TYPE_HASHTREE 2 +#define SPX_ADDR_TYPE_FORSTREE 3 +#define SPX_ADDR_TYPE_FORSPK 4 +#define SPX_ADDR_TYPE_WOTSPRF 5 +#define SPX_ADDR_TYPE_FORSPRF 6 + +#define set_layer_addr SPX_NAMESPACE(set_layer_addr) +void set_layer_addr(uint32_t addr[8], uint32_t layer); + +#define set_tree_addr SPX_NAMESPACE(set_tree_addr) +void set_tree_addr(uint32_t addr[8], uint64_t tree); + +#define set_type SPX_NAMESPACE(set_type) +void set_type(uint32_t addr[8], uint32_t type); + +/* Copies the layer and tree part of one address into the other */ +#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); + +/* These functions are used for WOTS and FORS addresses. */ + +#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) +void set_keypair_addr(uint32_t addr[8], uint32_t keypair); + +#define set_chain_addr SPX_NAMESPACE(set_chain_addr) +void set_chain_addr(uint32_t addr[8], uint32_t chain); + +#define set_hash_addr SPX_NAMESPACE(set_hash_addr) +void set_hash_addr(uint32_t addr[8], uint32_t hash); + +#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); + +/* These functions are used for all hash tree addresses (including FORS). */ + +#define set_tree_height SPX_NAMESPACE(set_tree_height) +void set_tree_height(uint32_t addr[8], uint32_t tree_height); + +#define set_tree_index SPX_NAMESPACE(set_tree_index) +void set_tree_index(uint32_t addr[8], uint32_t tree_index); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_clean/api.h b/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_clean/api.h new file mode 100644 index 0000000000..354080cd13 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_clean/api.h @@ -0,0 +1,77 @@ +#ifndef PQCLEAN_SPHINCSSHA2128SSIMPLE_CLEAN_API_H +#define PQCLEAN_SPHINCSSHA2128SSIMPLE_CLEAN_API_H + +#include +#include + +#define PQCLEAN_SPHINCSSHA2128SSIMPLE_CLEAN_CRYPTO_ALGNAME "SPHINCS+-sha2-128s-simple" + +#define PQCLEAN_SPHINCSSHA2128SSIMPLE_CLEAN_CRYPTO_SECRETKEYBYTES 64 +#define PQCLEAN_SPHINCSSHA2128SSIMPLE_CLEAN_CRYPTO_PUBLICKEYBYTES 32 +#define PQCLEAN_SPHINCSSHA2128SSIMPLE_CLEAN_CRYPTO_BYTES 7856 + +#define PQCLEAN_SPHINCSSHA2128SSIMPLE_CLEAN_CRYPTO_SEEDBYTES 48 + +/* + * Returns the length of a secret key, in bytes + */ +size_t PQCLEAN_SPHINCSSHA2128SSIMPLE_CLEAN_crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +size_t PQCLEAN_SPHINCSSHA2128SSIMPLE_CLEAN_crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +size_t PQCLEAN_SPHINCSSHA2128SSIMPLE_CLEAN_crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +size_t PQCLEAN_SPHINCSSHA2128SSIMPLE_CLEAN_crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +int PQCLEAN_SPHINCSSHA2128SSIMPLE_CLEAN_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +int PQCLEAN_SPHINCSSHA2128SSIMPLE_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +int PQCLEAN_SPHINCSSHA2128SSIMPLE_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +int PQCLEAN_SPHINCSSHA2128SSIMPLE_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, + const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +int PQCLEAN_SPHINCSSHA2128SSIMPLE_CLEAN_crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +int PQCLEAN_SPHINCSSHA2128SSIMPLE_CLEAN_crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_clean/context.h b/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_clean/context.h new file mode 100644 index 0000000000..27effb3e10 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_clean/context.h @@ -0,0 +1,26 @@ +#ifndef SPX_CONTEXT_H +#define SPX_CONTEXT_H + +#include +#include + +#include "params.h" +#include "sha2.h" + +typedef struct { + uint8_t pub_seed[SPX_N]; + uint8_t sk_seed[SPX_N]; + + // sha256 state that absorbed pub_seed + sha256ctx state_seeded; + + +} spx_ctx; + +#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) +void initialize_hash_function(spx_ctx *ctx); + +#define free_hash_function SPX_NAMESPACE(free_hash_function) +void free_hash_function(spx_ctx *ctx); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_clean/context_sha2.c b/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_clean/context_sha2.c new file mode 100644 index 0000000000..64f7e65465 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_clean/context_sha2.c @@ -0,0 +1,33 @@ +#include "context.h" + +/** + * Absorb the constant pub_seed using one round of the compression function + * This initializes state_seeded and state_seeded_512, which can then be + * reused in thash + **/ +static void seed_state(spx_ctx *ctx) { + uint8_t block[SPX_SHA512_BLOCK_BYTES]; + size_t i; + + for (i = 0; i < SPX_N; ++i) { + block[i] = ctx->pub_seed[i]; + } + for (i = SPX_N; i < SPX_SHA512_BLOCK_BYTES; ++i) { + block[i] = 0; + } + /* block has been properly initialized for both SHA-256 and SHA-512 */ + + sha256_inc_init(&ctx->state_seeded); + sha256_inc_blocks(&ctx->state_seeded, block, 1); +} + + +/* We initialize the state for the hash functions */ +void initialize_hash_function(spx_ctx *ctx) { + seed_state(ctx); +} + +/* Free the incremental hashing context for heap-based SHA2 APIs */ +void free_hash_function(spx_ctx *ctx) { + sha256_inc_ctx_release(&ctx->state_seeded); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_clean/fors.c b/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_clean/fors.c new file mode 100644 index 0000000000..96ca72e986 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_clean/fors.c @@ -0,0 +1,156 @@ +#include +#include +#include + +#include "fors.h" + +#include "address.h" +#include "hash.h" +#include "thash.h" +#include "utils.h" +#include "utilsx1.h" + +static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + prf_addr(sk, ctx, fors_leaf_addr); +} + +static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, + const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + thash(leaf, sk, 1, ctx, fors_leaf_addr); +} + +struct fors_gen_leaf_info { + uint32_t leaf_addrx[8]; +}; + +static void fors_gen_leafx1(unsigned char *leaf, + const spx_ctx *ctx, + uint32_t addr_idx, void *info) { + struct fors_gen_leaf_info *fors_info = info; + uint32_t *fors_leaf_addr = fors_info->leaf_addrx; + + /* Only set the parts that the caller doesn't set */ + set_tree_index(fors_leaf_addr, addr_idx); + set_type(fors_leaf_addr, SPX_ADDR_TYPE_FORSPRF); + fors_gen_sk(leaf, ctx, fors_leaf_addr); + + set_type(fors_leaf_addr, SPX_ADDR_TYPE_FORSTREE); + fors_sk_to_leaf(leaf, leaf, + ctx, fors_leaf_addr); +} + +/** + * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + * Assumes indices has space for SPX_FORS_TREES integers. + */ +static void message_to_indices(uint32_t *indices, const unsigned char *m) { + unsigned int i, j; + unsigned int offset = 0; + + for (i = 0; i < SPX_FORS_TREES; i++) { + indices[i] = 0; + for (j = 0; j < SPX_FORS_HEIGHT; j++) { + indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); + offset++; + } + } +} + +/** + * Signs a message m, deriving the secret key from sk_seed and the FTS address. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + uint32_t fors_tree_addr[8] = {0}; + struct fors_gen_leaf_info fors_info = {0}; + uint32_t *fors_leaf_addr = fors_info.leaf_addrx; + uint32_t fors_pk_addr[8] = {0}; + uint32_t idx_offset; + unsigned int i; + + copy_keypair_addr(fors_tree_addr, fors_addr); + copy_keypair_addr(fors_leaf_addr, fors_addr); + + copy_keypair_addr(fors_pk_addr, fors_addr); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); + + message_to_indices(indices, m); + + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); + + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); + + /* Include the secret key part that produces the selected leaf node. */ + fors_gen_sk(sig, ctx, fors_tree_addr); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + sig += SPX_N; + + /* Compute the authentication path for this leaf node. */ + treehashx1(roots + i * SPX_N, sig, ctx, + indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx1, + fors_tree_addr, &fors_info); + + sig += SPX_N * SPX_FORS_HEIGHT; + } + + /* Hash horizontally across all tree roots to derive the public key. */ + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); +} + +/** + * Derives the FORS public key from a signature. + * This can be used for verification by comparing to a known public key, or to + * subsequently verify a signature on the derived public key. The latter is the + * typical use-case when used as an FTS below an OTS in a hypertree. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + unsigned char leaf[SPX_N]; + uint32_t fors_tree_addr[8] = {0}; + uint32_t fors_pk_addr[8] = {0}; + uint32_t idx_offset; + unsigned int i; + + copy_keypair_addr(fors_tree_addr, fors_addr); + copy_keypair_addr(fors_pk_addr, fors_addr); + + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); + + message_to_indices(indices, m); + + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); + + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + + /* Derive the leaf from the included secret key part. */ + fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); + sig += SPX_N; + + /* Derive the corresponding root node of this tree. */ + compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, + sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); + sig += SPX_N * SPX_FORS_HEIGHT; + } + + /* Hash horizontally across all tree roots to derive the public key. */ + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_clean/fors.h b/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_clean/fors.h new file mode 100644 index 0000000000..509140a178 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_clean/fors.h @@ -0,0 +1,32 @@ +#ifndef SPX_FORS_H +#define SPX_FORS_H + +#include + +#include "context.h" +#include "params.h" + +/** + * Signs a message m, deriving the secret key from sk_seed and the FTS address. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +#define fors_sign SPX_NAMESPACE(fors_sign) +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); + +/** + * Derives the FORS public key from a signature. + * This can be used for verification by comparing to a known public key, or to + * subsequently verify a signature on the derived public key. The latter is the + * typical use-case when used as an FTS below an OTS in a hypertree. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_clean/hash.h b/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_clean/hash.h new file mode 100644 index 0000000000..ffe815f45d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_clean/hash.h @@ -0,0 +1,37 @@ +#ifndef SPX_HASH_H +#define SPX_HASH_H + +#include +#include + +#include "context.h" +#include "params.h" + +#define prf_addr SPX_NAMESPACE(prf_addr) +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]); + +#define gen_message_random SPX_NAMESPACE(gen_message_random) +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); + +#define hash_message SPX_NAMESPACE(hash_message) +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); + + +# define SPX_SHA256_ADDR_BYTES 22 + +# define mgf1_256 SPX_NAMESPACE(mgf1_256) +void mgf1_256(unsigned char *out, unsigned long outlen, + const unsigned char *in, unsigned long inlen); + +# define mgf1_512 SPX_NAMESPACE(mgf1_512) +void mgf1_512(unsigned char *out, unsigned long outlen, + const unsigned char *in, unsigned long inlen); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_clean/hash_sha2.c b/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_clean/hash_sha2.c new file mode 100644 index 0000000000..69f0dc0013 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_clean/hash_sha2.c @@ -0,0 +1,219 @@ +#include +#include + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "sha2.h" +#include "utils.h" + + + +#define SPX_SHAX_OUTPUT_BYTES SPX_SHA256_OUTPUT_BYTES +#define SPX_SHAX_BLOCK_BYTES SPX_SHA256_BLOCK_BYTES +#define shaX_inc_init sha256_inc_init +#define shaX_inc_blocks sha256_inc_blocks +#define shaX_inc_finalize sha256_inc_finalize +#define shaX sha256 +#define mgf1_X mgf1_256 +#define shaXstate sha256ctx + +/** + * mgf1 function based on the SHA-256 hash function + * Note that inlen should be sufficiently small that it still allows for + * an array to be allocated on the stack. Typically 'in' is merely a seed. + * Outputs outlen number of bytes + */ +void mgf1_256(unsigned char *out, unsigned long outlen, + const unsigned char *in, unsigned long inlen) { + PQCLEAN_VLA(uint8_t, inbuf, inlen + 4); + unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES]; + uint32_t i; + + memcpy(inbuf, in, inlen); + + /* While we can fit in at least another full block of SHA256 output.. */ + for (i = 0; (i + 1)*SPX_SHA256_OUTPUT_BYTES <= outlen; i++) { + u32_to_bytes(inbuf + inlen, i); + sha256(out, inbuf, inlen + 4); + out += SPX_SHA256_OUTPUT_BYTES; + } + /* Until we cannot anymore, and we fill the remainder. */ + if (outlen > i * SPX_SHA256_OUTPUT_BYTES) { + u32_to_bytes(inbuf + inlen, i); + sha256(outbuf, inbuf, inlen + 4); + memcpy(out, outbuf, outlen - i * SPX_SHA256_OUTPUT_BYTES); + } +} + +/* + * mgf1 function based on the SHA-512 hash function + */ +void mgf1_512(unsigned char *out, unsigned long outlen, + const unsigned char *in, unsigned long inlen) { + PQCLEAN_VLA(uint8_t, inbuf, inlen + 4); + unsigned char outbuf[SPX_SHA512_OUTPUT_BYTES]; + uint32_t i; + + memcpy(inbuf, in, inlen); + + /* While we can fit in at least another full block of SHA512 output.. */ + for (i = 0; (i + 1)*SPX_SHA512_OUTPUT_BYTES <= outlen; i++) { + u32_to_bytes(inbuf + inlen, i); + sha512(out, inbuf, inlen + 4); + out += SPX_SHA512_OUTPUT_BYTES; + } + /* Until we cannot anymore, and we fill the remainder. */ + if (outlen > i * SPX_SHA512_OUTPUT_BYTES) { + u32_to_bytes(inbuf + inlen, i); + sha512(outbuf, inbuf, inlen + 4); + memcpy(out, outbuf, outlen - i * SPX_SHA512_OUTPUT_BYTES); + } +} + +/* + * Computes PRF(pk_seed, sk_seed, addr). + */ +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]) { + sha256ctx sha2_state; + unsigned char buf[SPX_SHA256_ADDR_BYTES + SPX_N]; + unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES]; + + /* Retrieve precomputed state containing pub_seed */ + sha256_inc_ctx_clone(&sha2_state, &ctx->state_seeded); + + /* Remainder: ADDR^c ‖ SK.seed */ + memcpy(buf, addr, SPX_SHA256_ADDR_BYTES); + memcpy(buf + SPX_SHA256_ADDR_BYTES, ctx->sk_seed, SPX_N); + + sha256_inc_finalize(outbuf, &sha2_state, buf, SPX_SHA256_ADDR_BYTES + SPX_N); + + memcpy(out, outbuf, SPX_N); +} + +/** + * Computes the message-dependent randomness R, using a secret seed as a key + * for HMAC, and an optional randomization value prefixed to the message. + * This requires m to have at least SPX_SHAX_BLOCK_BYTES + SPX_N space + * available in front of the pointer, i.e. before the message to use for the + * prefix. This is necessary to prevent having to move the message around (and + * allocate memory for it). + */ +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { + (void)ctx; + + unsigned char buf[SPX_SHAX_BLOCK_BYTES + SPX_SHAX_OUTPUT_BYTES]; + shaXstate state; + int i; + + + /* This implements HMAC-SHA */ + for (i = 0; i < SPX_N; i++) { + buf[i] = 0x36 ^ sk_prf[i]; + } + memset(buf + SPX_N, 0x36, SPX_SHAX_BLOCK_BYTES - SPX_N); + + shaX_inc_init(&state); + shaX_inc_blocks(&state, buf, 1); + + memcpy(buf, optrand, SPX_N); + + /* If optrand + message cannot fill up an entire block */ + if (SPX_N + mlen < SPX_SHAX_BLOCK_BYTES) { + memcpy(buf + SPX_N, m, mlen); + shaX_inc_finalize(buf + SPX_SHAX_BLOCK_BYTES, &state, + buf, mlen + SPX_N); + } + /* Otherwise first fill a block, so that finalize only uses the message */ + else { + memcpy(buf + SPX_N, m, SPX_SHAX_BLOCK_BYTES - SPX_N); + shaX_inc_blocks(&state, buf, 1); + + m += SPX_SHAX_BLOCK_BYTES - SPX_N; + mlen -= SPX_SHAX_BLOCK_BYTES - SPX_N; + shaX_inc_finalize(buf + SPX_SHAX_BLOCK_BYTES, &state, m, mlen); + } + + for (i = 0; i < SPX_N; i++) { + buf[i] = 0x5c ^ sk_prf[i]; + } + memset(buf + SPX_N, 0x5c, SPX_SHAX_BLOCK_BYTES - SPX_N); + + shaX(buf, buf, SPX_SHAX_BLOCK_BYTES + SPX_SHAX_OUTPUT_BYTES); + memcpy(R, buf, SPX_N); +} + +/** + * Computes the message hash using R, the public key, and the message. + * Outputs the message digest and the index of the leaf. The index is split in + * the tree index and the leaf index, for convenient copying to an address. + */ +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { + (void)ctx; +#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) +#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) +#define SPX_LEAF_BITS SPX_TREE_HEIGHT +#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) +#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) + + unsigned char seed[2 * SPX_N + SPX_SHAX_OUTPUT_BYTES]; + + /* Round to nearest multiple of SPX_SHAX_BLOCK_BYTES */ +#define SPX_INBLOCKS (((SPX_N + SPX_PK_BYTES + SPX_SHAX_BLOCK_BYTES - 1) & \ + -SPX_SHAX_BLOCK_BYTES) / SPX_SHAX_BLOCK_BYTES) + unsigned char inbuf[SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES]; + + unsigned char buf[SPX_DGST_BYTES]; + unsigned char *bufp = buf; + shaXstate state; + + shaX_inc_init(&state); + + // seed: SHA-X(R ‖ PK.seed ‖ PK.root ‖ M) + memcpy(inbuf, R, SPX_N); + memcpy(inbuf + SPX_N, pk, SPX_PK_BYTES); + + /* If R + pk + message cannot fill up an entire block */ + if (SPX_N + SPX_PK_BYTES + mlen < SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES) { + memcpy(inbuf + SPX_N + SPX_PK_BYTES, m, mlen); + shaX_inc_finalize(seed + 2 * SPX_N, &state, inbuf, SPX_N + SPX_PK_BYTES + mlen); + } + /* Otherwise first fill a block, so that finalize only uses the message */ + else { + memcpy(inbuf + SPX_N + SPX_PK_BYTES, m, + SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES - SPX_N - SPX_PK_BYTES); + shaX_inc_blocks(&state, inbuf, SPX_INBLOCKS); + + m += SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES - SPX_N - SPX_PK_BYTES; + mlen -= SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES - SPX_N - SPX_PK_BYTES; + shaX_inc_finalize(seed + 2 * SPX_N, &state, m, (size_t)mlen); + } + + // H_msg: MGF1-SHA-X(R ‖ PK.seed ‖ seed) + memcpy(seed, R, SPX_N); + memcpy(seed + SPX_N, pk, SPX_N); + + /* By doing this in two steps, we prevent hashing the message twice; + otherwise each iteration in MGF1 would hash the message again. */ + mgf1_X(bufp, SPX_DGST_BYTES, seed, 2 * SPX_N + SPX_SHAX_OUTPUT_BYTES); + + memcpy(digest, bufp, SPX_FORS_MSG_BYTES); + bufp += SPX_FORS_MSG_BYTES; + + + *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); + *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); + bufp += SPX_TREE_BYTES; + + *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); + *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); +} + + diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_clean/merkle.c b/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_clean/merkle.c new file mode 100644 index 0000000000..0c1479fd93 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_clean/merkle.c @@ -0,0 +1,59 @@ +#include +#include + +#include "address.h" +#include "merkle.h" +#include "params.h" +#include "utils.h" +#include "utilsx1.h" +#include "wots.h" +#include "wotsx1.h" + +/* + * This generates a Merkle signature (WOTS signature followed by the Merkle + * authentication path). This is in this file because most of the complexity + * is involved with the WOTS signature; the Merkle authentication path logic + * is mostly hidden in treehashx4 + */ +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf) { + unsigned char *auth_path = sig + SPX_WOTS_BYTES; + struct leaf_info_x1 info = { 0 }; + unsigned steps[ SPX_WOTS_LEN ]; + + info.wots_sig = sig; + chain_lengths(steps, root); + info.wots_steps = steps; + + set_type(&tree_addr[0], SPX_ADDR_TYPE_HASHTREE); + set_type(&info.pk_addr[0], SPX_ADDR_TYPE_WOTSPK); + copy_subtree_addr(&info.leaf_addr[0], wots_addr); + copy_subtree_addr(&info.pk_addr[0], wots_addr); + + info.wots_sign_leaf = idx_leaf; + + treehashx1(root, auth_path, ctx, + idx_leaf, 0, + SPX_TREE_HEIGHT, + wots_gen_leafx1, + tree_addr, &info); +} + +/* Compute root node of the top-most subtree. */ +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { + /* We do not need the auth path in key generation, but it simplifies the + code to have just one treehash routine that computes both root and path + in one function. */ + unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; + uint32_t top_tree_addr[8] = {0}; + uint32_t wots_addr[8] = {0}; + + set_layer_addr(top_tree_addr, SPX_D - 1); + set_layer_addr(wots_addr, SPX_D - 1); + + merkle_sign(auth_path, root, ctx, + wots_addr, top_tree_addr, + (uint32_t)~0 /* ~0 means "don't bother generating an auth path */ ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_clean/merkle.h b/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_clean/merkle.h new file mode 100644 index 0000000000..769cf2e970 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_clean/merkle.h @@ -0,0 +1,21 @@ +#ifndef MERKLE_H_ +#define MERKLE_H_ + +#include + +#include "context.h" +#include "params.h" + +/* Generate a Merkle signature (WOTS signature followed by the Merkle */ +/* authentication path) */ +#define merkle_sign SPX_NAMESPACE(merkle_sign) +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf); + +/* Compute the root node of the top-most subtree. */ +#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); + +#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_clean/nistapi.h b/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_clean/nistapi.h new file mode 100644 index 0000000000..3cb71afad4 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_clean/nistapi.h @@ -0,0 +1,87 @@ +#ifndef SPX_API_H +#define SPX_API_H + +#include +#include + +#include "params.h" + +#define CRYPTO_ALGNAME "SPHINCS+" + +#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES +#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES +#define CRYPTO_BYTES SPX_BYTES +#define CRYPTO_SEEDBYTES (3*SPX_N) + +/* + * Returns the length of a secret key, in bytes + */ +#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) +size_t crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) +size_t crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) +size_t crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) +size_t crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +#define crypto_sign SPX_NAMESPACE(crypto_sign) +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_clean/params.h b/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_clean/params.h new file mode 100644 index 0000000000..10da2cb0f1 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_clean/params.h @@ -0,0 +1,61 @@ +#ifndef SPX_PARAMS_H +#define SPX_PARAMS_H + +#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSSHA2128SSIMPLE_CLEAN_##s + +/* Hash output length in bytes. */ +#define SPX_N 16 +/* Height of the hypertree. */ +#define SPX_FULL_HEIGHT 63 +/* Number of subtree layer. */ +#define SPX_D 7 +/* FORS tree dimensions. */ +#define SPX_FORS_HEIGHT 12 +#define SPX_FORS_TREES 14 +/* Winternitz parameter, */ +#define SPX_WOTS_W 16 + +/* The hash function is defined by linking a different hash.c file, as opposed + to setting a #define constant. */ + +/* This is a SHA2-based parameter set, hence whether we use SHA-256 + * exclusively or we use both SHA-256 and SHA-512 is controlled by + * the following #define */ +#define SPX_SHA512 0 /* Use SHA-256 for all hashes */ + +/* For clarity */ +#define SPX_ADDR_BYTES 32 + +/* WOTS parameters. */ +#define SPX_WOTS_LOGW 4 + +#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) + +/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ +#define SPX_WOTS_LEN2 3 + +#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) +#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) +#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES + +/* Subtree size. */ +#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) + +//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT +// #error SPX_D should always divide SPX_FULL_HEIGHT +//#endif + +/* FORS parameters. */ +#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) +#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) +#define SPX_FORS_PK_BYTES SPX_N + +/* Resulting SPX sizes. */ +#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ + SPX_FULL_HEIGHT * SPX_N) +#define SPX_PK_BYTES (2 * SPX_N) +#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) + +#include "sha2_offsets.h" + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_clean/sha2_offsets.h b/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_clean/sha2_offsets.h new file mode 100644 index 0000000000..6e3584f7a4 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_clean/sha2_offsets.h @@ -0,0 +1,27 @@ +#ifndef SHA2_OFFSETS_H_ +#define SHA2_OFFSETS_H_ + +#define SPX_SHA256_BLOCK_BYTES 64 +#define SPX_SHA256_OUTPUT_BYTES 32 + +#define SPX_SHA512_BLOCK_BYTES 128 +#define SPX_SHA512_OUTPUT_BYTES 64 + +/* + * Offsets of various fields in the address structure when we use SHA2 as + * the Sphincs+ hash function + */ + +#define SPX_OFFSET_LAYER 0 /* The byte used to specify the Merkle tree layer */ +#define SPX_OFFSET_TREE 1 /* The start of the 8 byte field used to specify the tree */ +#define SPX_OFFSET_TYPE 9 /* The byte used to specify the hash type (reason) */ +#define SPX_OFFSET_KP_ADDR2 12 /* The high byte used to specify the key pair (which one-time signature) */ +#define SPX_OFFSET_KP_ADDR1 13 /* The low byte used to specify the key pair */ +#define SPX_OFFSET_CHAIN_ADDR 17 /* The byte used to specify the chain address (which Winternitz chain) */ +#define SPX_OFFSET_HASH_ADDR 21 /* The byte used to specify the hash address (where in the Winternitz chain) */ +#define SPX_OFFSET_TREE_HGT 17 /* The byte used to specify the height of this node in the FORS or Merkle tree */ +#define SPX_OFFSET_TREE_INDEX 18 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ + +#define SPX_SHA2 1 + +#endif /* SHA2_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_clean/sign.c b/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_clean/sign.c new file mode 100644 index 0000000000..9d0c7d1b22 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_clean/sign.c @@ -0,0 +1,286 @@ +#include +#include +#include + +#include "address.h" +#include "context.h" +#include "fors.h" +#include "hash.h" +#include "merkle.h" +#include "nistapi.h" +#include "params.h" +#include "randombytes.h" +#include "thash.h" +#include "utils.h" +#include "wots.h" + +/* + * Returns the length of a secret key, in bytes + */ +size_t crypto_sign_secretkeybytes(void) { + return CRYPTO_SECRETKEYBYTES; +} + +/* + * Returns the length of a public key, in bytes + */ +size_t crypto_sign_publickeybytes(void) { + return CRYPTO_PUBLICKEYBYTES; +} + +/* + * Returns the length of a signature, in bytes + */ +size_t crypto_sign_bytes(void) { + return CRYPTO_BYTES; +} + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +size_t crypto_sign_seedbytes(void) { + return CRYPTO_SEEDBYTES; +} + +/* + * Generates an SPX key pair given a seed of length + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [PUB_SEED || root] + */ +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed) { + spx_ctx ctx; + + /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ + memcpy(sk, seed, CRYPTO_SEEDBYTES); + + memcpy(pk, sk + 2 * SPX_N, SPX_N); + + memcpy(ctx.pub_seed, pk, SPX_N); + memcpy(ctx.sk_seed, sk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + /* Compute root node of the top-most subtree. */ + merkle_gen_root(sk + 3 * SPX_N, &ctx); + + // cleanup + free_hash_function(&ctx); + + memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); + + return 0; +} + +/* + * Generates an SPX key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [PUB_SEED || root] + */ +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { + uint8_t seed[CRYPTO_SEEDBYTES]; + randombytes(seed, CRYPTO_SEEDBYTES); + crypto_sign_seed_keypair(pk, sk, seed); + + return 0; +} + +/** + * Returns an array containing a detached signature. + */ +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk) { + spx_ctx ctx; + + const uint8_t *sk_prf = sk + SPX_N; + const uint8_t *pk = sk + 2 * SPX_N; + + uint8_t optrand[SPX_N]; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t root[SPX_N]; + uint32_t i; + uint64_t tree; + uint32_t idx_leaf; + uint32_t wots_addr[8] = {0}; + uint32_t tree_addr[8] = {0}; + + memcpy(ctx.sk_seed, sk, SPX_N); + memcpy(ctx.pub_seed, pk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + + /* Optionally, signing can be made non-deterministic using optrand. + This can help counter side-channel attacks that would benefit from + getting a large number of traces when the signer uses the same nodes. */ + randombytes(optrand, SPX_N); + /* Compute the digest randomization value. */ + gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); + + /* Derive the message digest and leaf index from R, PK and M. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; + + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); + + /* Sign the message hash using FORS. */ + fors_sign(sig, root, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); + sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; + + /* Update the indices for the next layer. */ + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; + } + + free_hash_function(&ctx); + + *siglen = SPX_BYTES; + + return 0; +} + +/** + * Verifies a detached signature and message under a given public key. + */ +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk) { + spx_ctx ctx; + const uint8_t *pub_root = pk + SPX_N; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t wots_pk[SPX_WOTS_BYTES]; + uint8_t root[SPX_N]; + uint8_t leaf[SPX_N]; + unsigned int i; + uint64_t tree; + uint32_t idx_leaf; + uint32_t wots_addr[8] = {0}; + uint32_t tree_addr[8] = {0}; + uint32_t wots_pk_addr[8] = {0}; + + if (siglen != SPX_BYTES) { + return -1; + } + + memcpy(ctx.pub_seed, pk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); + + /* Derive the message digest and leaf index from R || PK || M. */ + /* The additional SPX_N is a result of the hash domain separator. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; + + /* Layer correctly defaults to 0, so no need to set_layer_addr */ + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); + + fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + /* For each subtree.. */ + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + copy_keypair_addr(wots_pk_addr, wots_addr); + + /* The WOTS public key is only correct if the signature was correct. */ + /* Initially, root is the FORS pk, but on subsequent iterations it is + the root of the subtree below the currently processed subtree. */ + wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); + sig += SPX_WOTS_BYTES; + + /* Compute the leaf node using the WOTS public key. */ + thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); + + /* Compute the root node of this subtree. */ + compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, + &ctx, tree_addr); + sig += SPX_TREE_HEIGHT * SPX_N; + + /* Update the indices for the next layer. */ + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; + } + + // cleanup + free_hash_function(&ctx); + + /* Check if the root node equals the root node in the public key. */ + if (memcmp(root, pub_root, SPX_N) != 0) { + return -1; + } + + return 0; +} + + +/** + * Returns an array containing the signature followed by the message. + */ +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk) { + size_t siglen; + + crypto_sign_signature(sm, &siglen, m, mlen, sk); + + memmove(sm + SPX_BYTES, m, mlen); + *smlen = siglen + mlen; + + return 0; +} + +/** + * Verifies a given signature-message pair under a given public key. + */ +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk) { + /* The API caller does not necessarily know what size a signature should be + but SPHINCS+ signatures are always exactly SPX_BYTES. */ + if (smlen < SPX_BYTES) { + memset(m, 0, smlen); + *mlen = 0; + return -1; + } + + *mlen = smlen - SPX_BYTES; + + if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { + memset(m, 0, smlen); + *mlen = 0; + return -1; + } + + /* If verification was successful, move the message to the right place. */ + memmove(m, sm + SPX_BYTES, *mlen); + + return 0; +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_clean/thash.h b/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_clean/thash.h new file mode 100644 index 0000000000..8687ccfb4d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_clean/thash.h @@ -0,0 +1,13 @@ +#ifndef SPX_THASH_H +#define SPX_THASH_H + +#include "context.h" +#include "params.h" + +#include + +#define thash SPX_NAMESPACE(thash) +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_clean/thash_sha2_simple.c b/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_clean/thash_sha2_simple.c new file mode 100644 index 0000000000..197b4e7a0a --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_clean/thash_sha2_simple.c @@ -0,0 +1,32 @@ +#include +#include + +#include "thash.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "sha2.h" +#include "utils.h" + + +/** + * Takes an array of inblocks concatenated arrays of SPX_N bytes. + */ +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]) { + + unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES]; + sha256ctx sha2_state; + PQCLEAN_VLA(uint8_t, buf, SPX_SHA256_ADDR_BYTES + inblocks * SPX_N); + + /* Retrieve precomputed state containing pub_seed */ + sha256_inc_ctx_clone(&sha2_state, &ctx->state_seeded); + + memcpy(buf, addr, SPX_SHA256_ADDR_BYTES); + memcpy(buf + SPX_SHA256_ADDR_BYTES, in, inblocks * SPX_N); + + sha256_inc_finalize(outbuf, &sha2_state, buf, SPX_SHA256_ADDR_BYTES + inblocks * SPX_N); + memcpy(out, outbuf, SPX_N); +} + diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_clean/utils.c b/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_clean/utils.c new file mode 100644 index 0000000000..177b541fb9 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_clean/utils.c @@ -0,0 +1,148 @@ +#include + +#include "utils.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "thash.h" + +/** + * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. + */ +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in) { + int i; + + /* Iterate over out in decreasing order, for big-endianness. */ + for (i = (signed int)outlen - 1; i >= 0; i--) { + out[i] = in & 0xff; + in = in >> 8; + } +} + +void u32_to_bytes(unsigned char *out, uint32_t in) { + out[0] = (unsigned char)(in >> 24); + out[1] = (unsigned char)(in >> 16); + out[2] = (unsigned char)(in >> 8); + out[3] = (unsigned char)in; +} + +/** + * Converts the inlen bytes in 'in' from big-endian byte order to an integer. + */ +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { + unsigned long long retval = 0; + unsigned int i; + + for (i = 0; i < inlen; i++) { + retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); + } + return retval; +} + +/** + * Computes a root node given a leaf and an auth path. + * Expects address to be complete other than the tree_height and tree_index. + */ +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]) { + uint32_t i; + unsigned char buffer[2 * SPX_N]; + + /* If leaf_idx is odd (last bit = 1), current path element is a right child + and auth_path has to go left. Otherwise it is the other way around. */ + if (leaf_idx & 1) { + memcpy(buffer + SPX_N, leaf, SPX_N); + memcpy(buffer, auth_path, SPX_N); + } else { + memcpy(buffer, leaf, SPX_N); + memcpy(buffer + SPX_N, auth_path, SPX_N); + } + auth_path += SPX_N; + + for (i = 0; i < tree_height - 1; i++) { + leaf_idx >>= 1; + idx_offset >>= 1; + /* Set the address of the node we're creating. */ + set_tree_height(addr, i + 1); + set_tree_index(addr, leaf_idx + idx_offset); + + /* Pick the right or left neighbor, depending on parity of the node. */ + if (leaf_idx & 1) { + thash(buffer + SPX_N, buffer, 2, ctx, addr); + memcpy(buffer, auth_path, SPX_N); + } else { + thash(buffer, buffer, 2, ctx, addr); + memcpy(buffer + SPX_N, auth_path, SPX_N); + } + auth_path += SPX_N; + } + + /* The last iteration is exceptional; we do not copy an auth_path node. */ + leaf_idx >>= 1; + idx_offset >>= 1; + set_tree_height(addr, tree_height); + set_tree_index(addr, leaf_idx + idx_offset); + thash(root, buffer, 2, ctx, addr); +} + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx * /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]) { + PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); + PQCLEAN_VLA(unsigned int, heights, tree_height + 1); + unsigned int offset = 0; + uint32_t idx; + uint32_t tree_idx; + + for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { + /* Add the next leaf node to the stack. */ + gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); + offset++; + heights[offset - 1] = 0; + + /* If this is a node we need for the auth path.. */ + if ((leaf_idx ^ 0x1) == idx) { + memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); + } + + /* While the top-most nodes are of equal height.. */ + while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { + /* Compute index of the new node, in the next layer. */ + tree_idx = (idx >> (heights[offset - 1] + 1)); + + /* Set the address of the node we're creating. */ + set_tree_height(tree_addr, heights[offset - 1] + 1); + set_tree_index(tree_addr, + tree_idx + (idx_offset >> (heights[offset - 1] + 1))); + /* Hash the top-most nodes from the stack together. */ + thash(stack + (offset - 2)*SPX_N, + stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); + offset--; + /* Note that the top-most node is now one layer higher. */ + heights[offset - 1]++; + + /* If this is a node we need for the auth path.. */ + if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { + memcpy(auth_path + heights[offset - 1]*SPX_N, + stack + (offset - 1)*SPX_N, SPX_N); + } + } + } + memcpy(root, stack, SPX_N); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_clean/utils.h b/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_clean/utils.h new file mode 100644 index 0000000000..64f5d5a53a --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_clean/utils.h @@ -0,0 +1,58 @@ +#ifndef SPX_UTILS_H +#define SPX_UTILS_H + +#include + +#include "compat.h" +#include "context.h" +#include "params.h" + + +/* To support MSVC use alloca() instead of VLAs. See #20. */ + + +/** + * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. + */ +#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in); +#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) +void u32_to_bytes(unsigned char *out, uint32_t in); + +/** + * Converts the inlen bytes in 'in' from big-endian byte order to an integer. + */ +#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); + +/** + * Computes a root node given a leaf and an auth path. + * Expects address to be complete other than the tree_height and tree_index. + */ +#define compute_root SPX_NAMESPACE(compute_root) +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]); + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +#define treehash SPX_NAMESPACE(treehash) +void treehash(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx *ctx /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]); + + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_clean/utilsx1.c b/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_clean/utilsx1.c new file mode 100644 index 0000000000..fccb69b35d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_clean/utilsx1.c @@ -0,0 +1,100 @@ +#include + +#include "utilsx1.h" + +#include "address.h" +#include "params.h" +#include "thash.h" +#include "utils.h" + +/* + * Generate the entire Merkle tree, computing the authentication path for + * leaf_idx, and the resulting root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) + * + * This expects tree_addr to be initialized to the addr structures for the + * Merkle tree nodes + * + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + * + * This works by using the standard Merkle tree building algorithm, + */ +void treehashx1(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, + uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* Where to write the leaves */, + const spx_ctx * /* ctx */, + uint32_t idx, void *info), + uint32_t tree_addr[8], + void *info) { + /* This is where we keep the intermediate nodes */ + PQCLEAN_VLA(uint8_t, stack, tree_height * SPX_N); + + uint32_t idx; + uint32_t max_idx = (uint32_t)((1 << tree_height) - 1); + for (idx = 0;; idx++) { + unsigned char current[2 * SPX_N]; /* Current logical node is at */ + /* index[SPX_N]. We do this to minimize the number of copies */ + /* needed during a thash */ + gen_leaf( ¤t[SPX_N], ctx, idx + idx_offset, + info ); + + /* Now combine the freshly generated right node with previously */ + /* generated left ones */ + uint32_t internal_idx_offset = idx_offset; + uint32_t internal_idx = idx; + uint32_t internal_leaf = leaf_idx; + uint32_t h; /* The height we are in the Merkle tree */ + for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { + + /* Check if we hit the top of the tree */ + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[SPX_N], SPX_N ); + return; + } + + /* + * Check if the node we have is a part of the + * authentication path; if it is, write it out + */ + if ((internal_idx ^ internal_leaf) == 0x01) { + memcpy( &auth_path[ h * SPX_N ], + ¤t[SPX_N], + SPX_N ); + } + + /* + * Check if we're at a left child; if so, stop going up the stack + * Exception: if we've reached the end of the tree, keep on going + * (so we combine the last 4 nodes into the one root node in two + * more iterations) + */ + if ((internal_idx & 1) == 0 && idx < max_idx) { + break; + } + + /* Ok, we're at a right node */ + /* Now combine the left and right logical nodes together */ + + /* Set the address of the node we're creating. */ + internal_idx_offset >>= 1; + set_tree_height(tree_addr, h + 1); + set_tree_index(tree_addr, internal_idx / 2 + internal_idx_offset ); + + unsigned char *left = &stack[h * SPX_N]; + memcpy( ¤t[0], left, SPX_N ); + thash( ¤t[1 * SPX_N], + ¤t[0 * SPX_N], + 2, ctx, tree_addr); + } + + /* We've hit a left child; save the current for when we get the */ + /* corresponding right right */ + memcpy( &stack[h * SPX_N], ¤t[SPX_N], SPX_N); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_clean/utilsx1.h b/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_clean/utilsx1.h new file mode 100644 index 0000000000..e911d17d53 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_clean/utilsx1.h @@ -0,0 +1,27 @@ +#ifndef SPX_UTILSX4_H +#define SPX_UTILSX4_H + +#include + +#include "context.h" +#include "params.h" + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +#define treehashx1 SPX_NAMESPACE(treehashx1) +void treehashx1(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* Where to write the leaf */, + const spx_ctx * /* ctx */, + uint32_t addr_idx, void *info), + uint32_t tree_addrx4[8], void *info); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_clean/wots.c b/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_clean/wots.c new file mode 100644 index 0000000000..249717aaa8 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_clean/wots.c @@ -0,0 +1,108 @@ +#include +#include + +#include "wots.h" +#include "wotsx1.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "thash.h" +#include "utils.h" +#include "utilsx1.h" + +// TODO clarify address expectations, and make them more uniform. +// TODO i.e. do we expect types to be set already? +// TODO and do we expect modifications or copies? + +/** + * Computes the chaining function. + * out and in have to be n-byte arrays. + * + * Interprets in as start-th value of the chain. + * addr has to contain the address of the chain. + */ +static void gen_chain(unsigned char *out, const unsigned char *in, + unsigned int start, unsigned int steps, + const spx_ctx *ctx, uint32_t addr[8]) { + uint32_t i; + + /* Initialize out with the value at position 'start'. */ + memcpy(out, in, SPX_N); + + /* Iterate 'steps' calls to the hash function. */ + for (i = start; i < (start + steps) && i < SPX_WOTS_W; i++) { + set_hash_addr(addr, i); + thash(out, out, 1, ctx, addr); + } +} + +/** + * base_w algorithm as described in draft. + * Interprets an array of bytes as integers in base w. + * This only works when log_w is a divisor of 8. + */ +static void base_w(unsigned int *output, const int out_len, + const unsigned char *input) { + int in = 0; + int out = 0; + unsigned char total = 0; + int bits = 0; + int consumed; + + for (consumed = 0; consumed < out_len; consumed++) { + if (bits == 0) { + total = input[in]; + in++; + bits += 8; + } + bits -= SPX_WOTS_LOGW; + output[out] = (total >> bits) & (SPX_WOTS_W - 1); + out++; + } +} + +/* Computes the WOTS+ checksum over a message (in base_w). */ +static void wots_checksum(unsigned int *csum_base_w, + const unsigned int *msg_base_w) { + unsigned int csum = 0; + unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; + unsigned int i; + + /* Compute checksum. */ + for (i = 0; i < SPX_WOTS_LEN1; i++) { + csum += SPX_WOTS_W - 1 - msg_base_w[i]; + } + + /* Convert checksum to base_w. */ + /* Make sure expected empty zero bits are the least significant bits. */ + csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); + ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); + base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); +} + +/* Takes a message and derives the matching chain lengths. */ +void chain_lengths(unsigned int *lengths, const unsigned char *msg) { + base_w(lengths, SPX_WOTS_LEN1, msg); + wots_checksum(lengths + SPX_WOTS_LEN1, lengths); +} + +/** + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. + * + * Writes the computed public key to 'pk'. + */ +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]) { + unsigned int lengths[SPX_WOTS_LEN]; + uint32_t i; + + chain_lengths(lengths, msg); + + for (i = 0; i < SPX_WOTS_LEN; i++) { + set_chain_addr(addr, i); + gen_chain(pk + i * SPX_N, sig + i * SPX_N, + lengths[i], SPX_WOTS_W - 1 - lengths[i], ctx, addr); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_clean/wots.h b/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_clean/wots.h new file mode 100644 index 0000000000..4e7692eeef --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_clean/wots.h @@ -0,0 +1,25 @@ +#ifndef SPX_WOTS_H +#define SPX_WOTS_H + +#include + +#include "context.h" +#include "params.h" + +/** + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. + * + * Writes the computed public key to 'pk'. + */ +#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]); + +/* + * Compute the chain lengths needed for a given message hash + */ +#define chain_lengths SPX_NAMESPACE(chain_lengths) +void chain_lengths(unsigned int *lengths, const unsigned char *msg); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_clean/wotsx1.c b/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_clean/wotsx1.c new file mode 100644 index 0000000000..3adec78dfb --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_clean/wotsx1.c @@ -0,0 +1,76 @@ +#include +#include + +#include "wots.h" +#include "wotsx1.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "thash.h" +#include "utils.h" + +/* + * This generates a WOTS public key + * It also generates the WOTS signature if leaf_info indicates + * that we're signing with this WOTS key + */ +void wots_gen_leafx1(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info) { + struct leaf_info_x1 *info = v_info; + uint32_t *leaf_addr = info->leaf_addr; + uint32_t *pk_addr = info->pk_addr; + unsigned int i, k; + unsigned char pk_buffer[ SPX_WOTS_BYTES ]; + unsigned char *buffer; + uint32_t wots_k_mask; + + if (leaf_idx == info->wots_sign_leaf) { + /* We're traversing the leaf that's signing; generate the WOTS */ + /* signature */ + wots_k_mask = 0; + } else { + /* Nope, we're just generating pk's; turn off the signature logic */ + wots_k_mask = (uint32_t)~0; + } + + set_keypair_addr( leaf_addr, leaf_idx ); + set_keypair_addr( pk_addr, leaf_idx ); + + for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { + uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k to */ + /* the step if we're generating a signature, ~0 if we're not */ + + /* Start with the secret seed */ + set_chain_addr(leaf_addr, i); + set_hash_addr(leaf_addr, 0); + set_type(leaf_addr, SPX_ADDR_TYPE_WOTSPRF); + + prf_addr(buffer, ctx, leaf_addr); + + set_type(leaf_addr, SPX_ADDR_TYPE_WOTS); + + /* Iterate down the WOTS chain */ + for (k = 0;; k++) { + /* Check if this is the value that needs to be saved as a */ + /* part of the WOTS signature */ + if (k == wots_k) { + memcpy( info->wots_sig + i * SPX_N, buffer, SPX_N ); + } + + /* Check if we hit the top of the chain */ + if (k == SPX_WOTS_W - 1) { + break; + } + + /* Iterate one step on the chain */ + set_hash_addr(leaf_addr, k); + + thash(buffer, buffer, 1, ctx, leaf_addr); + } + } + + /* Do the final thash to generate the public keys */ + thash(dest, pk_buffer, SPX_WOTS_LEN, ctx, pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_clean/wotsx1.h b/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_clean/wotsx1.h new file mode 100644 index 0000000000..e617929f96 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-128s-simple_clean/wotsx1.h @@ -0,0 +1,39 @@ +#ifndef WOTSX1_H_ +#define WOTSX1_H_ + +#include + +#include "context.h" +#include "params.h" + +/* + * This is here to provide an interface to the internal wots_gen_leafx1 + * routine. While this routine is not referenced in the package outside of + * wots.c, it is called from the stand-alone benchmark code to characterize + * the performance + */ +struct leaf_info_x1 { + unsigned char *wots_sig; + uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ + uint32_t *wots_steps; + uint32_t leaf_addr[8]; + uint32_t pk_addr[8]; +}; + +/* Macro to set the leaf_info to something 'benign', that is, it would */ +/* run with the same time as it does during the real signing process */ +/* Used only by the benchmark code */ +#define INITIALIZE_LEAF_INFO_X1(info, addr, step_buffer) { \ + (info).wots_sig = 0; \ + (info).wots_sign_leaf = ~0; \ + (info).wots_steps = step_buffer; \ + memcpy( &(info).leaf_addr[0], (addr), 32 ); \ + memcpy( &(info).pk_addr[0], (addr), 32 ); \ + } + +#define wots_gen_leafx1 SPX_NAMESPACE(wots_gen_leafx1) +void wots_gen_leafx1(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info); + +#endif /* WOTSX1_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/LICENSE b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/LICENSE new file mode 100644 index 0000000000..670154e353 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/LICENSE @@ -0,0 +1,116 @@ +CC0 1.0 Universal + +Statement of Purpose + +The laws of most jurisdictions throughout the world automatically confer +exclusive Copyright and Related Rights (defined below) upon the creator and +subsequent owner(s) (each and all, an "owner") of an original work of +authorship and/or a database (each, a "Work"). + +Certain owners wish to permanently relinquish those rights to a Work for the +purpose of contributing to a commons of creative, cultural and scientific +works ("Commons") that the public can reliably and without fear of later +claims of infringement build upon, modify, incorporate in other works, reuse +and redistribute as freely as possible in any form whatsoever and for any +purposes, including without limitation commercial purposes. These owners may +contribute to the Commons to promote the ideal of a free culture and the +further production of creative, cultural and scientific works, or to gain +reputation or greater distribution for their Work in part through the use and +efforts of others. + +For these and/or other purposes and motivations, and without any expectation +of additional consideration or compensation, the person associating CC0 with a +Work (the "Affirmer"), to the extent that he or she is an owner of Copyright +and Related Rights in the Work, voluntarily elects to apply CC0 to the Work +and publicly distribute the Work under its terms, with knowledge of his or her +Copyright and Related Rights in the Work and the meaning and intended legal +effect of CC0 on those rights. + +1. Copyright and Related Rights. A Work made available under CC0 may be +protected by copyright and related or neighboring rights ("Copyright and +Related Rights"). Copyright and Related Rights include, but are not limited +to, the following: + + i. the right to reproduce, adapt, distribute, perform, display, communicate, + and translate a Work; + + ii. moral rights retained by the original author(s) and/or performer(s); + + iii. publicity and privacy rights pertaining to a person's image or likeness + depicted in a Work; + + iv. rights protecting against unfair competition in regards to a Work, + subject to the limitations in paragraph 4(a), below; + + v. rights protecting the extraction, dissemination, use and reuse of data in + a Work; + + vi. database rights (such as those arising under Directive 96/9/EC of the + European Parliament and of the Council of 11 March 1996 on the legal + protection of databases, and under any national implementation thereof, + including any amended or successor version of such directive); and + + vii. other similar, equivalent or corresponding rights throughout the world + based on applicable law or treaty, and any national implementations thereof. + +2. Waiver. To the greatest extent permitted by, but not in contravention of, +applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and +unconditionally waives, abandons, and surrenders all of Affirmer's Copyright +and Related Rights and associated claims and causes of action, whether now +known or unknown (including existing as well as future claims and causes of +action), in the Work (i) in all territories worldwide, (ii) for the maximum +duration provided by applicable law or treaty (including future time +extensions), (iii) in any current or future medium and for any number of +copies, and (iv) for any purpose whatsoever, including without limitation +commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes +the Waiver for the benefit of each member of the public at large and to the +detriment of Affirmer's heirs and successors, fully intending that such Waiver +shall not be subject to revocation, rescission, cancellation, termination, or +any other legal or equitable action to disrupt the quiet enjoyment of the Work +by the public as contemplated by Affirmer's express Statement of Purpose. + +3. Public License Fallback. Should any part of the Waiver for any reason be +judged legally invalid or ineffective under applicable law, then the Waiver +shall be preserved to the maximum extent permitted taking into account +Affirmer's express Statement of Purpose. In addition, to the extent the Waiver +is so judged Affirmer hereby grants to each affected person a royalty-free, +non transferable, non sublicensable, non exclusive, irrevocable and +unconditional license to exercise Affirmer's Copyright and Related Rights in +the Work (i) in all territories worldwide, (ii) for the maximum duration +provided by applicable law or treaty (including future time extensions), (iii) +in any current or future medium and for any number of copies, and (iv) for any +purpose whatsoever, including without limitation commercial, advertising or +promotional purposes (the "License"). The License shall be deemed effective as +of the date CC0 was applied by Affirmer to the Work. Should any part of the +License for any reason be judged legally invalid or ineffective under +applicable law, such partial invalidity or ineffectiveness shall not +invalidate the remainder of the License, and in such case Affirmer hereby +affirms that he or she will not (i) exercise any of his or her remaining +Copyright and Related Rights in the Work or (ii) assert any associated claims +and causes of action with respect to the Work, in either case contrary to +Affirmer's express Statement of Purpose. + +4. Limitations and Disclaimers. + + a. No trademark or patent rights held by Affirmer are waived, abandoned, + surrendered, licensed or otherwise affected by this document. + + b. Affirmer offers the Work as-is and makes no representations or warranties + of any kind concerning the Work, express, implied, statutory or otherwise, + including without limitation warranties of title, merchantability, fitness + for a particular purpose, non infringement, or the absence of latent or + other defects, accuracy, or the present or absence of errors, whether or not + discoverable, all to the greatest extent permissible under applicable law. + + c. Affirmer disclaims responsibility for clearing rights of other persons + that may apply to the Work or any use thereof, including without limitation + any person's Copyright and Related Rights in the Work. Further, Affirmer + disclaims responsibility for obtaining any necessary consents, permissions + or other rights required for any use of the Work. + + d. Affirmer understands and acknowledges that Creative Commons is not a + party to this document and has no duty or obligation with respect to this + CC0 or use of the Work. + +For more information, please see + diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/address.c b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/address.c new file mode 100644 index 0000000000..b956e9cb29 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/address.c @@ -0,0 +1,91 @@ +#include +#include + +#include "address.h" +#include "params.h" +#include "utils.h" + +/* + * Specify which level of Merkle tree (the "layer") we're working on + */ +void set_layer_addr(uint32_t addr[8], uint32_t layer) { + ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; +} + +/* + * Specify which Merkle tree within the level (the "tree address") we're working on + */ +void set_tree_addr(uint32_t addr[8], uint64_t tree) { + ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); +} + +/* + * Specify the reason we'll use this address structure for, that is, what + * hash will we compute with it. This is used so that unrelated types of + * hashes don't accidentally get the same address structure. The type will be + * one of the SPX_ADDR_TYPE constants + */ +void set_type(uint32_t addr[8], uint32_t type) { + ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; +} + +/* + * Copy the layer and tree fields of the address structure. This is used + * when we're doing multiple types of hashes within the same Merkle tree + */ +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); +} + +/* These functions are used for OTS addresses. */ + +/* + * Specify which Merkle leaf we're working on; that is, which OTS keypair + * we're talking about. + */ +void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { + ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; +} + +/* + * Copy the layer, tree and keypair fields of the address structure. This is + * used when we're doing multiple things within the same OTS keypair + */ +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); + ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; +} + +/* + * Specify which Merkle chain within the OTS we're working with + * (the chain address) + */ +void set_chain_addr(uint32_t addr[8], uint32_t chain) { + ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; +} + +/* + * Specify where in the Merkle chain we are +* (the hash address) + */ +void set_hash_addr(uint32_t addr[8], uint32_t hash) { + ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; +} + +/* These functions are used for all hash tree addresses (including FORS). */ + +/* + * Specify the height of the node in the Merkle/FORS tree we are in + * (the tree height) + */ +void set_tree_height(uint32_t addr[8], uint32_t tree_height) { + ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; +} + +/* + * Specify the distance from the left edge of the node in the Merkle/FORS tree + * (the tree index) + */ +void set_tree_index(uint32_t addr[8], uint32_t tree_index) { + u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/address.h b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/address.h new file mode 100644 index 0000000000..24a84eb40c --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/address.h @@ -0,0 +1,52 @@ +#ifndef SPX_ADDRESS_H +#define SPX_ADDRESS_H + +#include + +#include "params.h" + +/* The hash types that are passed to set_type */ +#define SPX_ADDR_TYPE_WOTS 0 +#define SPX_ADDR_TYPE_WOTSPK 1 +#define SPX_ADDR_TYPE_HASHTREE 2 +#define SPX_ADDR_TYPE_FORSTREE 3 +#define SPX_ADDR_TYPE_FORSPK 4 +#define SPX_ADDR_TYPE_WOTSPRF 5 +#define SPX_ADDR_TYPE_FORSPRF 6 + +#define set_layer_addr SPX_NAMESPACE(set_layer_addr) +void set_layer_addr(uint32_t addr[8], uint32_t layer); + +#define set_tree_addr SPX_NAMESPACE(set_tree_addr) +void set_tree_addr(uint32_t addr[8], uint64_t tree); + +#define set_type SPX_NAMESPACE(set_type) +void set_type(uint32_t addr[8], uint32_t type); + +/* Copies the layer and tree part of one address into the other */ +#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); + +/* These functions are used for WOTS and FORS addresses. */ + +#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) +void set_keypair_addr(uint32_t addr[8], uint32_t keypair); + +#define set_chain_addr SPX_NAMESPACE(set_chain_addr) +void set_chain_addr(uint32_t addr[8], uint32_t chain); + +#define set_hash_addr SPX_NAMESPACE(set_hash_addr) +void set_hash_addr(uint32_t addr[8], uint32_t hash); + +#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); + +/* These functions are used for all hash tree addresses (including FORS). */ + +#define set_tree_height SPX_NAMESPACE(set_tree_height) +void set_tree_height(uint32_t addr[8], uint32_t tree_height); + +#define set_tree_index SPX_NAMESPACE(set_tree_index) +void set_tree_index(uint32_t addr[8], uint32_t tree_index); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/api.h b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/api.h new file mode 100644 index 0000000000..546545b0c1 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/api.h @@ -0,0 +1,77 @@ +#ifndef PQCLEAN_SPHINCSSHA2192FROBUST_AVX2_API_H +#define PQCLEAN_SPHINCSSHA2192FROBUST_AVX2_API_H + +#include +#include + +#define PQCLEAN_SPHINCSSHA2192FROBUST_AVX2_CRYPTO_ALGNAME "SPHINCS+-sha2-192f-robust" + +#define PQCLEAN_SPHINCSSHA2192FROBUST_AVX2_CRYPTO_SECRETKEYBYTES 96 +#define PQCLEAN_SPHINCSSHA2192FROBUST_AVX2_CRYPTO_PUBLICKEYBYTES 48 +#define PQCLEAN_SPHINCSSHA2192FROBUST_AVX2_CRYPTO_BYTES 35664 + +#define PQCLEAN_SPHINCSSHA2192FROBUST_AVX2_CRYPTO_SEEDBYTES 72 + +/* + * Returns the length of a secret key, in bytes + */ +size_t PQCLEAN_SPHINCSSHA2192FROBUST_AVX2_crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +size_t PQCLEAN_SPHINCSSHA2192FROBUST_AVX2_crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +size_t PQCLEAN_SPHINCSSHA2192FROBUST_AVX2_crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +size_t PQCLEAN_SPHINCSSHA2192FROBUST_AVX2_crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +int PQCLEAN_SPHINCSSHA2192FROBUST_AVX2_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +int PQCLEAN_SPHINCSSHA2192FROBUST_AVX2_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +int PQCLEAN_SPHINCSSHA2192FROBUST_AVX2_crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +int PQCLEAN_SPHINCSSHA2192FROBUST_AVX2_crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, + const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +int PQCLEAN_SPHINCSSHA2192FROBUST_AVX2_crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +int PQCLEAN_SPHINCSSHA2192FROBUST_AVX2_crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/context.h b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/context.h new file mode 100644 index 0000000000..d3bf1c3aac --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/context.h @@ -0,0 +1,29 @@ +#ifndef SPX_CONTEXT_H +#define SPX_CONTEXT_H + +#include + +#include "params.h" +#include "sha2.h" +#include "sha256avx.h" +#include "sha512x4.h" + +// funky ordering due to optimal padding +typedef struct { + sha256x8ctx statex8_seeded; + sha512x4ctx statex4_seeded_512; + sha256ctx state_seeded; + sha512ctx state_seeded_512; + + uint8_t pub_seed[SPX_N]; + uint8_t sk_seed[SPX_N]; +} spx_ctx; + + +#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) +void initialize_hash_function(spx_ctx *ctx); + +#define free_hash_function SPX_NAMESPACE(free_hash_function) +void free_hash_function(spx_ctx *ctx); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/context_sha2.c b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/context_sha2.c new file mode 100644 index 0000000000..83c1b6585d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/context_sha2.c @@ -0,0 +1,56 @@ +#include + +#include "context.h" + +/** + * Absorb the constant pub_seed using one round of the compression function + * This initializes state_seeded and state_seeded_512, which can then be + * reused in thash + **/ +static void seed_state(spx_ctx *ctx) { + uint8_t block[SPX_SHA512_BLOCK_BYTES]; + size_t i; + + for (i = 0; i < SPX_N; ++i) { + block[i] = ctx->pub_seed[i]; + } + for (i = SPX_N; i < SPX_SHA512_BLOCK_BYTES; ++i) { + block[i] = 0; + } + /* block has been properly initialized for both SHA-256 and SHA-512 */ + + sha256_inc_init(&ctx->state_seeded); + sha256_inc_blocks(&ctx->state_seeded, block, 1); + + // initialize x8 + sha256_init8x(&ctx->statex8_seeded); + sha256_transform8x(&ctx->statex8_seeded, + block, block, block, block, block, block, block, block); + + ctx->statex8_seeded.datalen = 0; + ctx->statex8_seeded.msglen = 512; + + sha512_inc_init(&ctx->state_seeded_512); + sha512_inc_blocks(&ctx->state_seeded_512, block, 1); + + // initialize x4 + sha512_init4x(&ctx->statex4_seeded_512); + sha512_transform4x(&ctx->statex4_seeded_512, block, block, block, block); + + ctx->statex4_seeded_512.datalen = 0; + ctx->statex4_seeded_512.msglen = 1024; + + +} + + +/* For SHA, we initialize the hash function at the start */ +void initialize_hash_function(spx_ctx *ctx) { + seed_state(ctx); +} + +/* Free the incremental hashing context for heap-based SHA2 APIs */ +void free_hash_function(spx_ctx *ctx) { + sha256_inc_ctx_release(&ctx->state_seeded); + sha512_inc_ctx_release(&ctx->state_seeded_512); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/fors.c b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/fors.c new file mode 100644 index 0000000000..4cab8e7415 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/fors.c @@ -0,0 +1,226 @@ +#include +#include +#include + +#include "fors.h" + + +#include "address.h" +#include "hash.h" +#include "hashx8.h" +#include "thash.h" +#include "thashx8.h" +#include "utils.h" +#include "utilsx8.h" +static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + prf_addr(sk, ctx, fors_leaf_addr); +} + +static void fors_gen_skx8(unsigned char *sk0, + unsigned char *sk1, + unsigned char *sk2, + unsigned char *sk3, + unsigned char *sk4, + unsigned char *sk5, + unsigned char *sk6, + unsigned char *sk7, const spx_ctx *ctx, + uint32_t fors_leaf_addrx8[8 * 8]) { + prf_addrx8(sk0, sk1, sk2, sk3, sk4, sk5, sk6, sk7, + ctx, fors_leaf_addrx8); +} + +static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, + const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + thash(leaf, sk, 1, ctx, fors_leaf_addr); +} + +static void fors_sk_to_leafx8(unsigned char *leaf0, + unsigned char *leaf1, + unsigned char *leaf2, + unsigned char *leaf3, + unsigned char *leaf4, + unsigned char *leaf5, + unsigned char *leaf6, + unsigned char *leaf7, + const unsigned char *sk0, + const unsigned char *sk1, + const unsigned char *sk2, + const unsigned char *sk3, + const unsigned char *sk4, + const unsigned char *sk5, + const unsigned char *sk6, + const unsigned char *sk7, + const spx_ctx *ctx, + uint32_t fors_leaf_addrx8[8 * 8]) { + thashx8(leaf0, leaf1, leaf2, leaf3, leaf4, leaf5, leaf6, leaf7, + sk0, sk1, sk2, sk3, sk4, sk5, sk6, sk7, + 1, ctx, fors_leaf_addrx8); +} + +struct fors_gen_leaf_info { + uint32_t leaf_addrx[8 * 8]; +}; + +static void fors_gen_leafx8(unsigned char *leaf, + const spx_ctx *ctx, + uint32_t addr_idx, void *info) { + struct fors_gen_leaf_info *fors_info = info; + uint32_t *fors_leaf_addrx8 = fors_info->leaf_addrx; + unsigned int j; + + /* Only set the parts that the caller doesn't set */ + for (j = 0; j < 8; j++) { + set_tree_index(fors_leaf_addrx8 + j * 8, addr_idx + j); + set_type(fors_leaf_addrx8 + j * 8, SPX_ADDR_TYPE_FORSPRF); + } + + fors_gen_skx8(leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + leaf + 2 * SPX_N, + leaf + 3 * SPX_N, + leaf + 4 * SPX_N, + leaf + 5 * SPX_N, + leaf + 6 * SPX_N, + leaf + 7 * SPX_N, + ctx, fors_leaf_addrx8); + + for (j = 0; j < 8; j++) { + set_type(fors_leaf_addrx8 + j * 8, SPX_ADDR_TYPE_FORSTREE); + } + + fors_sk_to_leafx8(leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + leaf + 2 * SPX_N, + leaf + 3 * SPX_N, + leaf + 4 * SPX_N, + leaf + 5 * SPX_N, + leaf + 6 * SPX_N, + leaf + 7 * SPX_N, + leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + leaf + 2 * SPX_N, + leaf + 3 * SPX_N, + leaf + 4 * SPX_N, + leaf + 5 * SPX_N, + leaf + 6 * SPX_N, + leaf + 7 * SPX_N, + ctx, fors_leaf_addrx8); +} + +/** + * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + * Assumes indices has space for SPX_FORS_TREES integers. + */ +static void message_to_indices(uint32_t *indices, const unsigned char *m) { + unsigned int i, j; + unsigned int offset = 0; + + for (i = 0; i < SPX_FORS_TREES; i++) { + indices[i] = 0; + for (j = 0; j < SPX_FORS_HEIGHT; j++) { + indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); + offset++; + } + } +} + +/** + * Signs a message m, deriving the secret key from sk_seed and the FTS address. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + uint32_t fors_tree_addr[8 * 8] = {0}; + struct fors_gen_leaf_info fors_info = {0}; + uint32_t *fors_leaf_addr = fors_info.leaf_addrx; + uint32_t fors_pk_addr[8] = {0}; + uint32_t idx_offset; + unsigned int i; + + for (i = 0; i < 8; i++) { + copy_keypair_addr(fors_tree_addr + 8 * i, fors_addr); + set_type(fors_tree_addr + 8 * i, SPX_ADDR_TYPE_FORSTREE); + copy_keypair_addr(fors_leaf_addr + 8 * i, fors_addr); + } + copy_keypair_addr(fors_pk_addr, fors_addr); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); + + message_to_indices(indices, m); + + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); + + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + + /* Include the secret key part that produces the selected leaf node. */ + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); + fors_gen_sk(sig, ctx, fors_tree_addr); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + sig += SPX_N; + + /* Compute the authentication path for this leaf node. */ + treehashx8(roots + i * SPX_N, sig, ctx, + indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx8, + fors_tree_addr, &fors_info); + + sig += SPX_N * SPX_FORS_HEIGHT; + } + + /* Hash horizontally across all tree roots to derive the public key. */ + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); +} + +/** + * Derives the FORS public key from a signature. + * This can be used for verification by comparing to a known public key, or to + * subsequently verify a signature on the derived public key. The latter is the + * typical use-case when used as an FTS below an OTS in a hypertree. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + unsigned char leaf[SPX_N]; + uint32_t fors_tree_addr[8] = {0}; + uint32_t fors_pk_addr[8] = {0}; + uint32_t idx_offset; + unsigned int i; + + copy_keypair_addr(fors_tree_addr, fors_addr); + copy_keypair_addr(fors_pk_addr, fors_addr); + + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); + + message_to_indices(indices, m); + + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); + + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + + /* Derive the leaf from the included secret key part. */ + fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); + sig += SPX_N; + + /* Derive the corresponding root node of this tree. */ + compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, + sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); + sig += SPX_N * SPX_FORS_HEIGHT; + } + + /* Hash horizontally across all tree roots to derive the public key. */ + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/fors.h b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/fors.h new file mode 100644 index 0000000000..509140a178 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/fors.h @@ -0,0 +1,32 @@ +#ifndef SPX_FORS_H +#define SPX_FORS_H + +#include + +#include "context.h" +#include "params.h" + +/** + * Signs a message m, deriving the secret key from sk_seed and the FTS address. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +#define fors_sign SPX_NAMESPACE(fors_sign) +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); + +/** + * Derives the FORS public key from a signature. + * This can be used for verification by comparing to a known public key, or to + * subsequently verify a signature on the derived public key. The latter is the + * typical use-case when used as an FTS below an OTS in a hypertree. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/hash.h b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/hash.h new file mode 100644 index 0000000000..ffe815f45d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/hash.h @@ -0,0 +1,37 @@ +#ifndef SPX_HASH_H +#define SPX_HASH_H + +#include +#include + +#include "context.h" +#include "params.h" + +#define prf_addr SPX_NAMESPACE(prf_addr) +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]); + +#define gen_message_random SPX_NAMESPACE(gen_message_random) +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); + +#define hash_message SPX_NAMESPACE(hash_message) +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); + + +# define SPX_SHA256_ADDR_BYTES 22 + +# define mgf1_256 SPX_NAMESPACE(mgf1_256) +void mgf1_256(unsigned char *out, unsigned long outlen, + const unsigned char *in, unsigned long inlen); + +# define mgf1_512 SPX_NAMESPACE(mgf1_512) +void mgf1_512(unsigned char *out, unsigned long outlen, + const unsigned char *in, unsigned long inlen); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/hash_sha2.c b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/hash_sha2.c new file mode 100644 index 0000000000..3d0085c8c1 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/hash_sha2.c @@ -0,0 +1,219 @@ +#include +#include + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "sha2.h" +#include "utils.h" + + + +#define SPX_SHAX_OUTPUT_BYTES SPX_SHA512_OUTPUT_BYTES +#define SPX_SHAX_BLOCK_BYTES SPX_SHA512_BLOCK_BYTES +#define shaX_inc_init sha512_inc_init +#define shaX_inc_blocks sha512_inc_blocks +#define shaX_inc_finalize sha512_inc_finalize +#define shaX sha512 +#define mgf1_X mgf1_512 +#define shaXstate sha512ctx + +/** + * mgf1 function based on the SHA-256 hash function + * Note that inlen should be sufficiently small that it still allows for + * an array to be allocated on the stack. Typically 'in' is merely a seed. + * Outputs outlen number of bytes + */ +void mgf1_256(unsigned char *out, unsigned long outlen, + const unsigned char *in, unsigned long inlen) { + PQCLEAN_VLA(uint8_t, inbuf, inlen + 4); + unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES]; + uint32_t i; + + memcpy(inbuf, in, inlen); + + /* While we can fit in at least another full block of SHA256 output.. */ + for (i = 0; (i + 1)*SPX_SHA256_OUTPUT_BYTES <= outlen; i++) { + u32_to_bytes(inbuf + inlen, i); + sha256(out, inbuf, inlen + 4); + out += SPX_SHA256_OUTPUT_BYTES; + } + /* Until we cannot anymore, and we fill the remainder. */ + if (outlen > i * SPX_SHA256_OUTPUT_BYTES) { + u32_to_bytes(inbuf + inlen, i); + sha256(outbuf, inbuf, inlen + 4); + memcpy(out, outbuf, outlen - i * SPX_SHA256_OUTPUT_BYTES); + } +} + +/* + * mgf1 function based on the SHA-512 hash function + */ +void mgf1_512(unsigned char *out, unsigned long outlen, + const unsigned char *in, unsigned long inlen) { + PQCLEAN_VLA(uint8_t, inbuf, inlen + 4); + unsigned char outbuf[SPX_SHA512_OUTPUT_BYTES]; + uint32_t i; + + memcpy(inbuf, in, inlen); + + /* While we can fit in at least another full block of SHA512 output.. */ + for (i = 0; (i + 1)*SPX_SHA512_OUTPUT_BYTES <= outlen; i++) { + u32_to_bytes(inbuf + inlen, i); + sha512(out, inbuf, inlen + 4); + out += SPX_SHA512_OUTPUT_BYTES; + } + /* Until we cannot anymore, and we fill the remainder. */ + if (outlen > i * SPX_SHA512_OUTPUT_BYTES) { + u32_to_bytes(inbuf + inlen, i); + sha512(outbuf, inbuf, inlen + 4); + memcpy(out, outbuf, outlen - i * SPX_SHA512_OUTPUT_BYTES); + } +} + +/* + * Computes PRF(pk_seed, sk_seed, addr). + */ +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]) { + sha256ctx sha2_state; + unsigned char buf[SPX_SHA256_ADDR_BYTES + SPX_N]; + unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES]; + + /* Retrieve precomputed state containing pub_seed */ + sha256_inc_ctx_clone(&sha2_state, &ctx->state_seeded); + + /* Remainder: ADDR^c ‖ SK.seed */ + memcpy(buf, addr, SPX_SHA256_ADDR_BYTES); + memcpy(buf + SPX_SHA256_ADDR_BYTES, ctx->sk_seed, SPX_N); + + sha256_inc_finalize(outbuf, &sha2_state, buf, SPX_SHA256_ADDR_BYTES + SPX_N); + + memcpy(out, outbuf, SPX_N); +} + +/** + * Computes the message-dependent randomness R, using a secret seed as a key + * for HMAC, and an optional randomization value prefixed to the message. + * This requires m to have at least SPX_SHAX_BLOCK_BYTES + SPX_N space + * available in front of the pointer, i.e. before the message to use for the + * prefix. This is necessary to prevent having to move the message around (and + * allocate memory for it). + */ +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { + (void)ctx; + + unsigned char buf[SPX_SHAX_BLOCK_BYTES + SPX_SHAX_OUTPUT_BYTES]; + shaXstate state; + int i; + + + /* This implements HMAC-SHA */ + for (i = 0; i < SPX_N; i++) { + buf[i] = 0x36 ^ sk_prf[i]; + } + memset(buf + SPX_N, 0x36, SPX_SHAX_BLOCK_BYTES - SPX_N); + + shaX_inc_init(&state); + shaX_inc_blocks(&state, buf, 1); + + memcpy(buf, optrand, SPX_N); + + /* If optrand + message cannot fill up an entire block */ + if (SPX_N + mlen < SPX_SHAX_BLOCK_BYTES) { + memcpy(buf + SPX_N, m, mlen); + shaX_inc_finalize(buf + SPX_SHAX_BLOCK_BYTES, &state, + buf, mlen + SPX_N); + } + /* Otherwise first fill a block, so that finalize only uses the message */ + else { + memcpy(buf + SPX_N, m, SPX_SHAX_BLOCK_BYTES - SPX_N); + shaX_inc_blocks(&state, buf, 1); + + m += SPX_SHAX_BLOCK_BYTES - SPX_N; + mlen -= SPX_SHAX_BLOCK_BYTES - SPX_N; + shaX_inc_finalize(buf + SPX_SHAX_BLOCK_BYTES, &state, m, mlen); + } + + for (i = 0; i < SPX_N; i++) { + buf[i] = 0x5c ^ sk_prf[i]; + } + memset(buf + SPX_N, 0x5c, SPX_SHAX_BLOCK_BYTES - SPX_N); + + shaX(buf, buf, SPX_SHAX_BLOCK_BYTES + SPX_SHAX_OUTPUT_BYTES); + memcpy(R, buf, SPX_N); +} + +/** + * Computes the message hash using R, the public key, and the message. + * Outputs the message digest and the index of the leaf. The index is split in + * the tree index and the leaf index, for convenient copying to an address. + */ +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { + (void)ctx; +#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) +#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) +#define SPX_LEAF_BITS SPX_TREE_HEIGHT +#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) +#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) + + unsigned char seed[2 * SPX_N + SPX_SHAX_OUTPUT_BYTES]; + + /* Round to nearest multiple of SPX_SHAX_BLOCK_BYTES */ +#define SPX_INBLOCKS (((SPX_N + SPX_PK_BYTES + SPX_SHAX_BLOCK_BYTES - 1) & \ + -SPX_SHAX_BLOCK_BYTES) / SPX_SHAX_BLOCK_BYTES) + unsigned char inbuf[SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES]; + + unsigned char buf[SPX_DGST_BYTES]; + unsigned char *bufp = buf; + shaXstate state; + + shaX_inc_init(&state); + + // seed: SHA-X(R ‖ PK.seed ‖ PK.root ‖ M) + memcpy(inbuf, R, SPX_N); + memcpy(inbuf + SPX_N, pk, SPX_PK_BYTES); + + /* If R + pk + message cannot fill up an entire block */ + if (SPX_N + SPX_PK_BYTES + mlen < SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES) { + memcpy(inbuf + SPX_N + SPX_PK_BYTES, m, mlen); + shaX_inc_finalize(seed + 2 * SPX_N, &state, inbuf, SPX_N + SPX_PK_BYTES + mlen); + } + /* Otherwise first fill a block, so that finalize only uses the message */ + else { + memcpy(inbuf + SPX_N + SPX_PK_BYTES, m, + SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES - SPX_N - SPX_PK_BYTES); + shaX_inc_blocks(&state, inbuf, SPX_INBLOCKS); + + m += SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES - SPX_N - SPX_PK_BYTES; + mlen -= SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES - SPX_N - SPX_PK_BYTES; + shaX_inc_finalize(seed + 2 * SPX_N, &state, m, (size_t)mlen); + } + + // H_msg: MGF1-SHA-X(R ‖ PK.seed ‖ seed) + memcpy(seed, R, SPX_N); + memcpy(seed + SPX_N, pk, SPX_N); + + /* By doing this in two steps, we prevent hashing the message twice; + otherwise each iteration in MGF1 would hash the message again. */ + mgf1_X(bufp, SPX_DGST_BYTES, seed, 2 * SPX_N + SPX_SHAX_OUTPUT_BYTES); + + memcpy(digest, bufp, SPX_FORS_MSG_BYTES); + bufp += SPX_FORS_MSG_BYTES; + + + *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); + *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); + bufp += SPX_TREE_BYTES; + + *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); + *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); +} + + diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/hash_sha2x8.c b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/hash_sha2x8.c new file mode 100644 index 0000000000..e04af7a069 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/hash_sha2x8.c @@ -0,0 +1,75 @@ +#include +#include + +#include "hash.h" +#include "hashx8.h" + +#include "address.h" +#include "params.h" +#include "sha2.h" +#include "sha256avx.h" +#include "sha256x8.h" +#include "utils.h" + +/* + * 8-way parallel version of prf_addr; takes 8x as much input and output + */ +void prf_addrx8(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const spx_ctx *ctx, + const uint32_t addrx8[8 * 8]) { + unsigned char bufx8[8 * (SPX_N + SPX_SHA256_ADDR_BYTES)]; + unsigned char outbufx8[8 * SPX_SHA256_OUTPUT_BYTES]; + unsigned int j; + + for (j = 0; j < 8; j++) { + memcpy(bufx8 + j * (SPX_N + SPX_SHA256_ADDR_BYTES), + addrx8 + j * 8, SPX_SHA256_ADDR_BYTES); + memcpy( + bufx8 + j * (SPX_N + SPX_SHA256_ADDR_BYTES) + SPX_SHA256_ADDR_BYTES, + ctx->sk_seed, + SPX_N + ); + } + + sha256x8_seeded( + /* out */ + outbufx8 + 0 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 1 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 2 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 3 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 4 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 5 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 6 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 7 * SPX_SHA256_OUTPUT_BYTES, + + /* seed */ + &ctx->statex8_seeded, + + /* in */ + bufx8 + 0 * (SPX_SHA256_ADDR_BYTES + SPX_N), + bufx8 + 1 * (SPX_SHA256_ADDR_BYTES + SPX_N), + bufx8 + 2 * (SPX_SHA256_ADDR_BYTES + SPX_N), + bufx8 + 3 * (SPX_SHA256_ADDR_BYTES + SPX_N), + bufx8 + 4 * (SPX_SHA256_ADDR_BYTES + SPX_N), + bufx8 + 5 * (SPX_SHA256_ADDR_BYTES + SPX_N), + bufx8 + 6 * (SPX_SHA256_ADDR_BYTES + SPX_N), + bufx8 + 7 * (SPX_SHA256_ADDR_BYTES + SPX_N), + SPX_SHA256_ADDR_BYTES + SPX_N /* len */ + ); + + memcpy(out0, outbufx8 + 0 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out1, outbufx8 + 1 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out2, outbufx8 + 2 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out3, outbufx8 + 3 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out4, outbufx8 + 4 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out5, outbufx8 + 5 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out6, outbufx8 + 6 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out7, outbufx8 + 7 * SPX_SHA256_OUTPUT_BYTES, SPX_N); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/hashx8.h b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/hashx8.h new file mode 100644 index 0000000000..46503f0a10 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/hashx8.h @@ -0,0 +1,20 @@ +#ifndef SPX_HASHX8_H +#define SPX_HASHX8_H + +#include + +#include "params.h" + +#define prf_addrx8 SPX_NAMESPACE(prf_addrx8) +void prf_addrx8(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const spx_ctx *ctx, + const uint32_t addrx8[8 * 8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/merkle.c b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/merkle.c new file mode 100644 index 0000000000..1f353c8dd8 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/merkle.c @@ -0,0 +1,65 @@ +#include +#include + +#include "merkle.h" + +#include "address.h" +#include "params.h" +#include "utils.h" +#include "utilsx8.h" +#include "wots.h" +#include "wotsx8.h" + +/* + * This generates a Merkle signature (WOTS signature followed by the Merkle + * authentication path). + */ +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf) { + unsigned char *auth_path = sig + SPX_WOTS_BYTES; + uint32_t tree_addrx8[8 * 8] = { 0 }; + int j; + struct leaf_info_x8 info = { 0 }; + unsigned steps[ SPX_WOTS_LEN ]; + + info.wots_sig = sig; + chain_lengths(steps, root); + info.wots_steps = steps; + + for (j = 0; j < 8; j++) { + set_type(&tree_addrx8[8 * j], SPX_ADDR_TYPE_HASHTREE); + set_type(&info.leaf_addr[8 * j], SPX_ADDR_TYPE_WOTS); + set_type(&info.pk_addr[8 * j], SPX_ADDR_TYPE_WOTSPK); + copy_subtree_addr(&tree_addrx8[8 * j], tree_addr); + copy_subtree_addr(&info.leaf_addr[8 * j], wots_addr); + copy_subtree_addr(&info.pk_addr[8 * j], wots_addr); + } + + info.wots_sign_leaf = idx_leaf; + + treehashx8(root, auth_path, ctx, + idx_leaf, 0, + SPX_TREE_HEIGHT, + wots_gen_leafx8, + tree_addrx8, &info); +} + +/* Compute root node of the top-most subtree. */ +/* Again, in this file because wots_gen_leaf is most of the work */ +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { + /* We do not need the auth path in key generation, but it simplifies the + code to have just one treehash routine that computes both root and path + in one function. */ + unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; + uint32_t top_tree_addr[8] = {0}; + uint32_t wots_addr[8] = {0}; + + set_layer_addr(top_tree_addr, SPX_D - 1); + set_layer_addr(wots_addr, SPX_D - 1); + + merkle_sign(auth_path, root, ctx, + wots_addr, top_tree_addr, + ~0U /* ~0 means "don't bother generating an auth path */ ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/merkle.h b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/merkle.h new file mode 100644 index 0000000000..769cf2e970 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/merkle.h @@ -0,0 +1,21 @@ +#ifndef MERKLE_H_ +#define MERKLE_H_ + +#include + +#include "context.h" +#include "params.h" + +/* Generate a Merkle signature (WOTS signature followed by the Merkle */ +/* authentication path) */ +#define merkle_sign SPX_NAMESPACE(merkle_sign) +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf); + +/* Compute the root node of the top-most subtree. */ +#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); + +#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/nistapi.h b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/nistapi.h new file mode 100644 index 0000000000..3cb71afad4 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/nistapi.h @@ -0,0 +1,87 @@ +#ifndef SPX_API_H +#define SPX_API_H + +#include +#include + +#include "params.h" + +#define CRYPTO_ALGNAME "SPHINCS+" + +#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES +#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES +#define CRYPTO_BYTES SPX_BYTES +#define CRYPTO_SEEDBYTES (3*SPX_N) + +/* + * Returns the length of a secret key, in bytes + */ +#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) +size_t crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) +size_t crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) +size_t crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) +size_t crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +#define crypto_sign SPX_NAMESPACE(crypto_sign) +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/params.h b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/params.h new file mode 100644 index 0000000000..c13415ac1c --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/params.h @@ -0,0 +1,61 @@ +#ifndef SPX_PARAMS_H +#define SPX_PARAMS_H + +#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSSHA2192FROBUST_AVX2_##s + +/* Hash output length in bytes. */ +#define SPX_N 24 +/* Height of the hypertree. */ +#define SPX_FULL_HEIGHT 66 +/* Number of subtree layer. */ +#define SPX_D 22 +/* FORS tree dimensions. */ +#define SPX_FORS_HEIGHT 8 +#define SPX_FORS_TREES 33 +/* Winternitz parameter, */ +#define SPX_WOTS_W 16 + +/* The hash function is defined by linking a different hash.c file, as opposed + to setting a #define constant. */ + +/* This is a SHA2-based parameter set, hence whether we use SHA-256 + * exclusively or we use both SHA-256 and SHA-512 is controlled by + * the following #define */ +#define SPX_SHA512 1 /* Use SHA-512 for H and T_l, l >= 2 */ + +/* For clarity */ +#define SPX_ADDR_BYTES 32 + +/* WOTS parameters. */ +#define SPX_WOTS_LOGW 4 + +#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) + +/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ +#define SPX_WOTS_LEN2 3 + +#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) +#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) +#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES + +/* Subtree size. */ +#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) + +//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT +// #error SPX_D should always divide SPX_FULL_HEIGHT +//#endif + +/* FORS parameters. */ +#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) +#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) +#define SPX_FORS_PK_BYTES SPX_N + +/* Resulting SPX sizes. */ +#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ + SPX_FULL_HEIGHT * SPX_N) +#define SPX_PK_BYTES (2 * SPX_N) +#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) + +#include "sha2_offsets.h" + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/sha256avx.c b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/sha256avx.c new file mode 100644 index 0000000000..6bbe6ecc24 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/sha256avx.c @@ -0,0 +1,357 @@ +#include +#include +#include + +#include "sha256avx.h" + +static const unsigned int RC[] = { + 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, + 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, + 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, + 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, + 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, + 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, + 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, + 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, + 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, + 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, + 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, + 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, + 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, + 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, + 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, + 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 +}; + +#define u32 uint32_t +#define u256 __m256i + +#define XOR _mm256_xor_si256 +#define OR _mm256_or_si256 +#define AND _mm256_and_si256 +#define ADD32 _mm256_add_epi32 +#define NOT(x) _mm256_xor_si256(x, _mm256_set_epi32(-1, -1, -1, -1, -1, -1, -1, -1)) + +#define LOAD(src) _mm256_loadu_si256((__m256i *)(src)) +#define STORE(dest,src) _mm256_storeu_si256((__m256i *)(dest),src) + +#define BYTESWAP(x) _mm256_shuffle_epi8(x, _mm256_set_epi8(0xc,0xd,0xe,0xf,0x8,0x9,0xa,0xb,0x4,0x5,0x6,0x7,0x0,0x1,0x2,0x3,0xc,0xd,0xe,0xf,0x8,0x9,0xa,0xb,0x4,0x5,0x6,0x7,0x0,0x1,0x2,0x3)) + +#define SHIFTR32(x, y) _mm256_srli_epi32(x, y) +#define SHIFTL32(x, y) _mm256_slli_epi32(x, y) + +#define ROTR32(x, y) OR(SHIFTR32(x, y), SHIFTL32(x, 32 - (y))) +#define ROTL32(x, y) OR(SHIFTL32(x, y), SHIFTR32(x, 32 - (y))) + +#define XOR3(a, b, c) XOR(XOR(a, b), c) + +#define ADD3_32(a, b, c) ADD32(ADD32(a, b), c) +#define ADD4_32(a, b, c, d) ADD32(ADD32(ADD32(a, b), c), d) +#define ADD5_32(a, b, c, d, e) ADD32(ADD32(ADD32(ADD32(a, b), c), d), e) + +#define MAJ_AVX(a, b, c) XOR3(AND(a, b), AND(a, c), AND(b, c)) +#define CH_AVX(a, b, c) XOR(AND(a, b), AND(NOT(a), c)) + +#define SIGMA1_AVX(x) XOR3(ROTR32(x, 6), ROTR32(x, 11), ROTR32(x, 25)) +#define SIGMA0_AVX(x) XOR3(ROTR32(x, 2), ROTR32(x, 13), ROTR32(x, 22)) + +#define WSIGMA1_AVX(x) XOR3(ROTR32(x, 17), ROTR32(x, 19), SHIFTR32(x, 10)) +#define WSIGMA0_AVX(x) XOR3(ROTR32(x, 7), ROTR32(x, 18), SHIFTR32(x, 3)) + +#define SHA256ROUND_AVX(a, b, c, d, e, f, g, h, rc, w) \ + T0 = ADD5_32(h, SIGMA1_AVX(e), CH_AVX(e, f, g), _mm256_set1_epi32((int)RC[rc]), w); \ + (d) = ADD32(d, T0); \ + T1 = ADD32(SIGMA0_AVX(a), MAJ_AVX(a, b, c)); \ + (h) = ADD32(T0, T1); + +// Transpose 8 vectors containing 32-bit values +static void transpose(u256 s[8]) { + u256 tmp0[8]; + u256 tmp1[8]; + tmp0[0] = _mm256_unpacklo_epi32(s[0], s[1]); + tmp0[1] = _mm256_unpackhi_epi32(s[0], s[1]); + tmp0[2] = _mm256_unpacklo_epi32(s[2], s[3]); + tmp0[3] = _mm256_unpackhi_epi32(s[2], s[3]); + tmp0[4] = _mm256_unpacklo_epi32(s[4], s[5]); + tmp0[5] = _mm256_unpackhi_epi32(s[4], s[5]); + tmp0[6] = _mm256_unpacklo_epi32(s[6], s[7]); + tmp0[7] = _mm256_unpackhi_epi32(s[6], s[7]); + tmp1[0] = _mm256_unpacklo_epi64(tmp0[0], tmp0[2]); + tmp1[1] = _mm256_unpackhi_epi64(tmp0[0], tmp0[2]); + tmp1[2] = _mm256_unpacklo_epi64(tmp0[1], tmp0[3]); + tmp1[3] = _mm256_unpackhi_epi64(tmp0[1], tmp0[3]); + tmp1[4] = _mm256_unpacklo_epi64(tmp0[4], tmp0[6]); + tmp1[5] = _mm256_unpackhi_epi64(tmp0[4], tmp0[6]); + tmp1[6] = _mm256_unpacklo_epi64(tmp0[5], tmp0[7]); + tmp1[7] = _mm256_unpackhi_epi64(tmp0[5], tmp0[7]); + s[0] = _mm256_permute2x128_si256(tmp1[0], tmp1[4], 0x20); + s[1] = _mm256_permute2x128_si256(tmp1[1], tmp1[5], 0x20); + s[2] = _mm256_permute2x128_si256(tmp1[2], tmp1[6], 0x20); + s[3] = _mm256_permute2x128_si256(tmp1[3], tmp1[7], 0x20); + s[4] = _mm256_permute2x128_si256(tmp1[0], tmp1[4], 0x31); + s[5] = _mm256_permute2x128_si256(tmp1[1], tmp1[5], 0x31); + s[6] = _mm256_permute2x128_si256(tmp1[2], tmp1[6], 0x31); + s[7] = _mm256_permute2x128_si256(tmp1[3], tmp1[7], 0x31); +} + +void sha256_ctx_clone8x(sha256x8ctx *out, const sha256x8ctx *in) { + memcpy(out, in, sizeof(sha256x8ctx)); +} + +void sha256_init8x(sha256x8ctx *ctx) { + ctx->s[0] = _mm256_set_epi32((int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667); + ctx->s[1] = _mm256_set_epi32((int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85); + ctx->s[2] = _mm256_set_epi32((int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372); + ctx->s[3] = _mm256_set_epi32((int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a); + ctx->s[4] = _mm256_set_epi32((int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f); + ctx->s[5] = _mm256_set_epi32((int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c); + ctx->s[6] = _mm256_set_epi32((int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab); + ctx->s[7] = _mm256_set_epi32((int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19); + + ctx->datalen = 0; + ctx->msglen = 0; +} + +void sha256_final8x(sha256x8ctx *ctx, + unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7) { + unsigned int i, curlen; + + // Padding + if (ctx->datalen < 56) { + for (i = 0; i < 8; ++i) { + curlen = ctx->datalen; + ctx->msgblocks[64 * i + curlen++] = 0x80; + while (curlen < 64) { + ctx->msgblocks[64 * i + curlen++] = 0x00; + } + } + } else { + for (i = 0; i < 8; ++i) { + curlen = ctx->datalen; + ctx->msgblocks[64 * i + curlen++] = 0x80; + while (curlen < 64) { + ctx->msgblocks[64 * i + curlen++] = 0x00; + } + } + sha256_transform8x(ctx, + &ctx->msgblocks[64 * 0], + &ctx->msgblocks[64 * 1], + &ctx->msgblocks[64 * 2], + &ctx->msgblocks[64 * 3], + &ctx->msgblocks[64 * 4], + &ctx->msgblocks[64 * 5], + &ctx->msgblocks[64 * 6], + &ctx->msgblocks[64 * 7] + ); + memset(ctx->msgblocks, 0, 8 * 64); + } + + // Add length of the message to each block + ctx->msglen += ctx->datalen * 8; + for (i = 0; i < 8; i++) { + ctx->msgblocks[64 * i + 63] = (unsigned char)(ctx->msglen); + ctx->msgblocks[64 * i + 62] = (unsigned char)(ctx->msglen >> 8); + ctx->msgblocks[64 * i + 61] = (unsigned char)(ctx->msglen >> 16); + ctx->msgblocks[64 * i + 60] = (unsigned char)(ctx->msglen >> 24); + ctx->msgblocks[64 * i + 59] = (unsigned char)(ctx->msglen >> 32); + ctx->msgblocks[64 * i + 58] = (unsigned char)(ctx->msglen >> 40); + ctx->msgblocks[64 * i + 57] = (unsigned char)(ctx->msglen >> 48); + ctx->msgblocks[64 * i + 56] = (unsigned char)(ctx->msglen >> 56); + } + sha256_transform8x(ctx, + &ctx->msgblocks[64 * 0], + &ctx->msgblocks[64 * 1], + &ctx->msgblocks[64 * 2], + &ctx->msgblocks[64 * 3], + &ctx->msgblocks[64 * 4], + &ctx->msgblocks[64 * 5], + &ctx->msgblocks[64 * 6], + &ctx->msgblocks[64 * 7] + ); + + // Compute final hash output + transpose(ctx->s); + + // Store Hash value + STORE(out0, BYTESWAP(ctx->s[0])); + STORE(out1, BYTESWAP(ctx->s[1])); + STORE(out2, BYTESWAP(ctx->s[2])); + STORE(out3, BYTESWAP(ctx->s[3])); + STORE(out4, BYTESWAP(ctx->s[4])); + STORE(out5, BYTESWAP(ctx->s[5])); + STORE(out6, BYTESWAP(ctx->s[6])); + STORE(out7, BYTESWAP(ctx->s[7])); +} + +void sha256_transform8x(sha256x8ctx *ctx, + const unsigned char *data0, + const unsigned char *data1, + const unsigned char *data2, + const unsigned char *data3, + const unsigned char *data4, + const unsigned char *data5, + const unsigned char *data6, + const unsigned char *data7) { + u256 s[8], w[64], T0, T1; + + // Load words and transform data correctly + w[0] = BYTESWAP(LOAD(data0)); + w[0 + 8] = BYTESWAP(LOAD(data0 + 32)); + w[1] = BYTESWAP(LOAD(data1)); + w[1 + 8] = BYTESWAP(LOAD(data1 + 32)); + w[2] = BYTESWAP(LOAD(data2)); + w[2 + 8] = BYTESWAP(LOAD(data2 + 32)); + w[3] = BYTESWAP(LOAD(data3)); + w[3 + 8] = BYTESWAP(LOAD(data3 + 32)); + w[4] = BYTESWAP(LOAD(data4)); + w[4 + 8] = BYTESWAP(LOAD(data4 + 32)); + w[5] = BYTESWAP(LOAD(data5)); + w[5 + 8] = BYTESWAP(LOAD(data5 + 32)); + w[6] = BYTESWAP(LOAD(data6)); + w[6 + 8] = BYTESWAP(LOAD(data6 + 32)); + w[7] = BYTESWAP(LOAD(data7)); + w[7 + 8] = BYTESWAP(LOAD(data7 + 32)); + + transpose(w); + transpose(w + 8); + + // Initial State + s[0] = ctx->s[0]; + s[1] = ctx->s[1]; + s[2] = ctx->s[2]; + s[3] = ctx->s[3]; + s[4] = ctx->s[4]; + s[5] = ctx->s[5]; + s[6] = ctx->s[6]; + s[7] = ctx->s[7]; + + SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 0, w[0]); + SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 1, w[1]); + SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 2, w[2]); + SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 3, w[3]); + SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 4, w[4]); + SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 5, w[5]); + SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 6, w[6]); + SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 7, w[7]); + SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 8, w[8]); + SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 9, w[9]); + SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 10, w[10]); + SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 11, w[11]); + SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 12, w[12]); + SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 13, w[13]); + SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 14, w[14]); + SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 15, w[15]); + w[16] = ADD4_32(WSIGMA1_AVX(w[14]), w[0], w[9], WSIGMA0_AVX(w[1])); + SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 16, w[16]); + w[17] = ADD4_32(WSIGMA1_AVX(w[15]), w[1], w[10], WSIGMA0_AVX(w[2])); + SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 17, w[17]); + w[18] = ADD4_32(WSIGMA1_AVX(w[16]), w[2], w[11], WSIGMA0_AVX(w[3])); + SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 18, w[18]); + w[19] = ADD4_32(WSIGMA1_AVX(w[17]), w[3], w[12], WSIGMA0_AVX(w[4])); + SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 19, w[19]); + w[20] = ADD4_32(WSIGMA1_AVX(w[18]), w[4], w[13], WSIGMA0_AVX(w[5])); + SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 20, w[20]); + w[21] = ADD4_32(WSIGMA1_AVX(w[19]), w[5], w[14], WSIGMA0_AVX(w[6])); + SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 21, w[21]); + w[22] = ADD4_32(WSIGMA1_AVX(w[20]), w[6], w[15], WSIGMA0_AVX(w[7])); + SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 22, w[22]); + w[23] = ADD4_32(WSIGMA1_AVX(w[21]), w[7], w[16], WSIGMA0_AVX(w[8])); + SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 23, w[23]); + w[24] = ADD4_32(WSIGMA1_AVX(w[22]), w[8], w[17], WSIGMA0_AVX(w[9])); + SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 24, w[24]); + w[25] = ADD4_32(WSIGMA1_AVX(w[23]), w[9], w[18], WSIGMA0_AVX(w[10])); + SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 25, w[25]); + w[26] = ADD4_32(WSIGMA1_AVX(w[24]), w[10], w[19], WSIGMA0_AVX(w[11])); + SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 26, w[26]); + w[27] = ADD4_32(WSIGMA1_AVX(w[25]), w[11], w[20], WSIGMA0_AVX(w[12])); + SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 27, w[27]); + w[28] = ADD4_32(WSIGMA1_AVX(w[26]), w[12], w[21], WSIGMA0_AVX(w[13])); + SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 28, w[28]); + w[29] = ADD4_32(WSIGMA1_AVX(w[27]), w[13], w[22], WSIGMA0_AVX(w[14])); + SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 29, w[29]); + w[30] = ADD4_32(WSIGMA1_AVX(w[28]), w[14], w[23], WSIGMA0_AVX(w[15])); + SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 30, w[30]); + w[31] = ADD4_32(WSIGMA1_AVX(w[29]), w[15], w[24], WSIGMA0_AVX(w[16])); + SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 31, w[31]); + w[32] = ADD4_32(WSIGMA1_AVX(w[30]), w[16], w[25], WSIGMA0_AVX(w[17])); + SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 32, w[32]); + w[33] = ADD4_32(WSIGMA1_AVX(w[31]), w[17], w[26], WSIGMA0_AVX(w[18])); + SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 33, w[33]); + w[34] = ADD4_32(WSIGMA1_AVX(w[32]), w[18], w[27], WSIGMA0_AVX(w[19])); + SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 34, w[34]); + w[35] = ADD4_32(WSIGMA1_AVX(w[33]), w[19], w[28], WSIGMA0_AVX(w[20])); + SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 35, w[35]); + w[36] = ADD4_32(WSIGMA1_AVX(w[34]), w[20], w[29], WSIGMA0_AVX(w[21])); + SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 36, w[36]); + w[37] = ADD4_32(WSIGMA1_AVX(w[35]), w[21], w[30], WSIGMA0_AVX(w[22])); + SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 37, w[37]); + w[38] = ADD4_32(WSIGMA1_AVX(w[36]), w[22], w[31], WSIGMA0_AVX(w[23])); + SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 38, w[38]); + w[39] = ADD4_32(WSIGMA1_AVX(w[37]), w[23], w[32], WSIGMA0_AVX(w[24])); + SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 39, w[39]); + w[40] = ADD4_32(WSIGMA1_AVX(w[38]), w[24], w[33], WSIGMA0_AVX(w[25])); + SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 40, w[40]); + w[41] = ADD4_32(WSIGMA1_AVX(w[39]), w[25], w[34], WSIGMA0_AVX(w[26])); + SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 41, w[41]); + w[42] = ADD4_32(WSIGMA1_AVX(w[40]), w[26], w[35], WSIGMA0_AVX(w[27])); + SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 42, w[42]); + w[43] = ADD4_32(WSIGMA1_AVX(w[41]), w[27], w[36], WSIGMA0_AVX(w[28])); + SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 43, w[43]); + w[44] = ADD4_32(WSIGMA1_AVX(w[42]), w[28], w[37], WSIGMA0_AVX(w[29])); + SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 44, w[44]); + w[45] = ADD4_32(WSIGMA1_AVX(w[43]), w[29], w[38], WSIGMA0_AVX(w[30])); + SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 45, w[45]); + w[46] = ADD4_32(WSIGMA1_AVX(w[44]), w[30], w[39], WSIGMA0_AVX(w[31])); + SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 46, w[46]); + w[47] = ADD4_32(WSIGMA1_AVX(w[45]), w[31], w[40], WSIGMA0_AVX(w[32])); + SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 47, w[47]); + w[48] = ADD4_32(WSIGMA1_AVX(w[46]), w[32], w[41], WSIGMA0_AVX(w[33])); + SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 48, w[48]); + w[49] = ADD4_32(WSIGMA1_AVX(w[47]), w[33], w[42], WSIGMA0_AVX(w[34])); + SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 49, w[49]); + w[50] = ADD4_32(WSIGMA1_AVX(w[48]), w[34], w[43], WSIGMA0_AVX(w[35])); + SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 50, w[50]); + w[51] = ADD4_32(WSIGMA1_AVX(w[49]), w[35], w[44], WSIGMA0_AVX(w[36])); + SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 51, w[51]); + w[52] = ADD4_32(WSIGMA1_AVX(w[50]), w[36], w[45], WSIGMA0_AVX(w[37])); + SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 52, w[52]); + w[53] = ADD4_32(WSIGMA1_AVX(w[51]), w[37], w[46], WSIGMA0_AVX(w[38])); + SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 53, w[53]); + w[54] = ADD4_32(WSIGMA1_AVX(w[52]), w[38], w[47], WSIGMA0_AVX(w[39])); + SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 54, w[54]); + w[55] = ADD4_32(WSIGMA1_AVX(w[53]), w[39], w[48], WSIGMA0_AVX(w[40])); + SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 55, w[55]); + w[56] = ADD4_32(WSIGMA1_AVX(w[54]), w[40], w[49], WSIGMA0_AVX(w[41])); + SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 56, w[56]); + w[57] = ADD4_32(WSIGMA1_AVX(w[55]), w[41], w[50], WSIGMA0_AVX(w[42])); + SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 57, w[57]); + w[58] = ADD4_32(WSIGMA1_AVX(w[56]), w[42], w[51], WSIGMA0_AVX(w[43])); + SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 58, w[58]); + w[59] = ADD4_32(WSIGMA1_AVX(w[57]), w[43], w[52], WSIGMA0_AVX(w[44])); + SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 59, w[59]); + w[60] = ADD4_32(WSIGMA1_AVX(w[58]), w[44], w[53], WSIGMA0_AVX(w[45])); + SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 60, w[60]); + w[61] = ADD4_32(WSIGMA1_AVX(w[59]), w[45], w[54], WSIGMA0_AVX(w[46])); + SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 61, w[61]); + w[62] = ADD4_32(WSIGMA1_AVX(w[60]), w[46], w[55], WSIGMA0_AVX(w[47])); + SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 62, w[62]); + w[63] = ADD4_32(WSIGMA1_AVX(w[61]), w[47], w[56], WSIGMA0_AVX(w[48])); + SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 63, w[63]); + + // Feed Forward + ctx->s[0] = ADD32(s[0], ctx->s[0]); + ctx->s[1] = ADD32(s[1], ctx->s[1]); + ctx->s[2] = ADD32(s[2], ctx->s[2]); + ctx->s[3] = ADD32(s[3], ctx->s[3]); + ctx->s[4] = ADD32(s[4], ctx->s[4]); + ctx->s[5] = ADD32(s[5], ctx->s[5]); + ctx->s[6] = ADD32(s[6], ctx->s[6]); + ctx->s[7] = ADD32(s[7], ctx->s[7]); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/sha256avx.h b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/sha256avx.h new file mode 100644 index 0000000000..1e3bcf889b --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/sha256avx.h @@ -0,0 +1,44 @@ +#ifndef SHA256AVX_H +#define SHA256AVX_H + +#include +#include + +#include "params.h" + +typedef struct SHA256state { + __m256i s[8]; + unsigned char msgblocks[8 * 64]; + unsigned int datalen; + unsigned long long msglen; +} sha256x8ctx; + +#define sha256_ctx_clone8x SPX_NAMESPACE(sha256_ctx_clone8x) +void sha256_ctx_clone8x(sha256x8ctx *out, const sha256x8ctx *in); + +#define sha256_init8x SPX_NAMESPACE(sha256_init8x) +void sha256_init8x(sha256x8ctx *ctx); + +#define sha256_final8x SPX_NAMESPACE(sha256_final8x) +void sha256_final8x(sha256x8ctx *ctx, + unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7); + +#define sha256_transform8x SPX_NAMESPACE(sha256_transform8x) +void sha256_transform8x(sha256x8ctx *ctx, + const unsigned char *data0, + const unsigned char *data1, + const unsigned char *data2, + const unsigned char *data3, + const unsigned char *data4, + const unsigned char *data5, + const unsigned char *data6, + const unsigned char *data7); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/sha256x8.c b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/sha256x8.c new file mode 100644 index 0000000000..d97750c09b --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/sha256x8.c @@ -0,0 +1,185 @@ +#include + +#include "sha256avx.h" +#include "sha256x8.h" +#include "utils.h" + +// Performs sha256x8 on an initialized (and perhaps seeded) state. +static void _sha256x8( + sha256x8ctx *ctx, + unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, unsigned long long inlen) { + unsigned long long i = 0; + while (inlen - i >= 64) { + sha256_transform8x(ctx, + in0 + i, + in1 + i, + in2 + i, + in3 + i, + in4 + i, + in5 + i, + in6 + i, + in7 + i + ); + i += 64; + ctx->msglen += 512; + } + + size_t bytes_to_copy = (size_t)(inlen - i); + memcpy(&ctx->msgblocks[64 * 0], in0 + i, bytes_to_copy); + memcpy(&ctx->msgblocks[64 * 1], in1 + i, bytes_to_copy); + memcpy(&ctx->msgblocks[64 * 2], in2 + i, bytes_to_copy); + memcpy(&ctx->msgblocks[64 * 3], in3 + i, bytes_to_copy); + memcpy(&ctx->msgblocks[64 * 4], in4 + i, bytes_to_copy); + memcpy(&ctx->msgblocks[64 * 5], in5 + i, bytes_to_copy); + memcpy(&ctx->msgblocks[64 * 6], in6 + i, bytes_to_copy); + memcpy(&ctx->msgblocks[64 * 7], in7 + i, bytes_to_copy); + ctx->datalen = (unsigned int)bytes_to_copy; + + sha256_final8x(ctx, out0, out1, out2, out3, out4, out5, out6, out7); +} + +void sha256x8_seeded( + unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const sha256x8ctx *seed, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, unsigned long long inlen) { + + sha256x8ctx ctx; + sha256_ctx_clone8x(&ctx, seed); + + _sha256x8(&ctx, out0, out1, out2, out3, out4, out5, out6, out7, + in0, in1, in2, in3, in4, in5, in6, in7, inlen); +} + +/* This provides a wrapper around the internals of 8x parallel SHA256 */ +void sha256x8(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, unsigned long long inlen) { + sha256x8ctx ctx; + sha256_init8x(&ctx); + + _sha256x8(&ctx, out0, out1, out2, out3, out4, out5, out6, out7, + in0, in1, in2, in3, in4, in5, in6, in7, inlen); +} + +/** + * Note that inlen should be sufficiently small that it still allows for + * an array to be allocated on the stack. Typically 'in' is merely a seed. + * Outputs outlen number of bytes + */ +void mgf1x8(unsigned char *outx8, unsigned long outlen, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, + unsigned long inlen) { + PQCLEAN_VLA(unsigned char, inbufx8, 8 * (inlen + 4)); + unsigned char outbufx8[8 * SPX_SHA256_OUTPUT_BYTES]; + uint32_t i; + unsigned int j; + + memcpy(inbufx8 + 0 * (inlen + 4), in0, inlen); + memcpy(inbufx8 + 1 * (inlen + 4), in1, inlen); + memcpy(inbufx8 + 2 * (inlen + 4), in2, inlen); + memcpy(inbufx8 + 3 * (inlen + 4), in3, inlen); + memcpy(inbufx8 + 4 * (inlen + 4), in4, inlen); + memcpy(inbufx8 + 5 * (inlen + 4), in5, inlen); + memcpy(inbufx8 + 6 * (inlen + 4), in6, inlen); + memcpy(inbufx8 + 7 * (inlen + 4), in7, inlen); + + /* While we can fit in at least another full block of SHA256 output.. */ + for (i = 0; (i + 1)*SPX_SHA256_OUTPUT_BYTES <= outlen; i++) { + for (j = 0; j < 8; j++) { + u32_to_bytes(inbufx8 + inlen + j * (inlen + 4), i); + } + + sha256x8(outx8 + 0 * outlen, + outx8 + 1 * outlen, + outx8 + 2 * outlen, + outx8 + 3 * outlen, + outx8 + 4 * outlen, + outx8 + 5 * outlen, + outx8 + 6 * outlen, + outx8 + 7 * outlen, + inbufx8 + 0 * (inlen + 4), + inbufx8 + 1 * (inlen + 4), + inbufx8 + 2 * (inlen + 4), + inbufx8 + 3 * (inlen + 4), + inbufx8 + 4 * (inlen + 4), + inbufx8 + 5 * (inlen + 4), + inbufx8 + 6 * (inlen + 4), + inbufx8 + 7 * (inlen + 4), inlen + 4); + outx8 += SPX_SHA256_OUTPUT_BYTES; + } + /* Until we cannot anymore, and we fill the remainder. */ + for (j = 0; j < 8; j++) { + u32_to_bytes(inbufx8 + inlen + j * (inlen + 4), i); + } + sha256x8(outbufx8 + 0 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 1 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 2 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 3 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 4 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 5 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 6 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 7 * SPX_SHA256_OUTPUT_BYTES, + inbufx8 + 0 * (inlen + 4), + inbufx8 + 1 * (inlen + 4), + inbufx8 + 2 * (inlen + 4), + inbufx8 + 3 * (inlen + 4), + inbufx8 + 4 * (inlen + 4), + inbufx8 + 5 * (inlen + 4), + inbufx8 + 6 * (inlen + 4), + inbufx8 + 7 * (inlen + 4), inlen + 4); + + for (j = 0; j < 8; j++) { + memcpy(outx8 + j * outlen, + outbufx8 + j * SPX_SHA256_OUTPUT_BYTES, + outlen - i * SPX_SHA256_OUTPUT_BYTES); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/sha256x8.h b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/sha256x8.h new file mode 100644 index 0000000000..4f7330a6c1 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/sha256x8.h @@ -0,0 +1,64 @@ +#ifndef SPX_SHA256X8_H +#define SPX_SHA256X8_H + +#include "params.h" +#include "sha256avx.h" + + + +#define sha256x8_seeded SPX_NAMESPACE(sha256x8_seeded) +void sha256x8_seeded( + unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const sha256x8ctx *seed, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, unsigned long long inlen); + +/* This provides a wrapper around the internals of 8x parallel SHA256 */ +#define sha256x8 SPX_NAMESPACE(sha256x8) +void sha256x8(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, unsigned long long inlen); + +/** + * Note that inlen should be sufficiently small that it still allows for + * an array to be allocated on the stack. Typically 'in' is merely a seed. + * Outputs outlen number of bytes + */ +#define mgf1x8 SPX_NAMESPACE(mgf1x8) +void mgf1x8(unsigned char *outx8, unsigned long outlen, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, + unsigned long inlen); +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/sha2_offsets.h b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/sha2_offsets.h new file mode 100644 index 0000000000..6e3584f7a4 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/sha2_offsets.h @@ -0,0 +1,27 @@ +#ifndef SHA2_OFFSETS_H_ +#define SHA2_OFFSETS_H_ + +#define SPX_SHA256_BLOCK_BYTES 64 +#define SPX_SHA256_OUTPUT_BYTES 32 + +#define SPX_SHA512_BLOCK_BYTES 128 +#define SPX_SHA512_OUTPUT_BYTES 64 + +/* + * Offsets of various fields in the address structure when we use SHA2 as + * the Sphincs+ hash function + */ + +#define SPX_OFFSET_LAYER 0 /* The byte used to specify the Merkle tree layer */ +#define SPX_OFFSET_TREE 1 /* The start of the 8 byte field used to specify the tree */ +#define SPX_OFFSET_TYPE 9 /* The byte used to specify the hash type (reason) */ +#define SPX_OFFSET_KP_ADDR2 12 /* The high byte used to specify the key pair (which one-time signature) */ +#define SPX_OFFSET_KP_ADDR1 13 /* The low byte used to specify the key pair */ +#define SPX_OFFSET_CHAIN_ADDR 17 /* The byte used to specify the chain address (which Winternitz chain) */ +#define SPX_OFFSET_HASH_ADDR 21 /* The byte used to specify the hash address (where in the Winternitz chain) */ +#define SPX_OFFSET_TREE_HGT 17 /* The byte used to specify the height of this node in the FORS or Merkle tree */ +#define SPX_OFFSET_TREE_INDEX 18 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ + +#define SPX_SHA2 1 + +#endif /* SHA2_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/sha512x4.c b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/sha512x4.c new file mode 100644 index 0000000000..8d33deffdd --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/sha512x4.c @@ -0,0 +1,446 @@ +#include +#include +#include + +/* pull in the entire thing */ +#include "sha512x4.h" +#include "utils.h" + +typedef uint64_t u64; +typedef __m256i u256; + +#define BYTESWAP(x) _mm256_shuffle_epi8(x, _mm256_set_epi8(0x8,0x9,0xa,0xb,0xc,0xd,0xe,0xf,0x0,0x1,0x2,0x3,0x4,0x5,0x6,0x7,0x8,0x9,0xa,0xb,0xc,0xd,0xe,0xf,0x0,0x1,0x2,0x3,0x4,0x5,0x6,0x7)) +#define STORE(dest,src) _mm256_storeu_si256((__m256i *)(dest),src) + +// Transpose 4 vectors containing 64-bit values +// That is, it rearranges the array: +// A B C D +// E F G H +// I J K L +// M N O P +// into +// A E I M +// B F J N +// C G K O +// D H L P +// where each letter stands for 64 bits (and lsbits on the left) +static void transpose(u256 s[4]) { + u256 tmp[4]; + tmp[0] = _mm256_unpacklo_epi64(s[0], s[1]); + tmp[1] = _mm256_unpackhi_epi64(s[0], s[1]); + tmp[2] = _mm256_unpacklo_epi64(s[2], s[3]); + tmp[3] = _mm256_unpackhi_epi64(s[2], s[3]); + // tmp is in the order of + // A E C G + // B F D H + // I M K O + // J N L P + s[0] = _mm256_permute2x128_si256(tmp[0], tmp[2], 0x20); + s[1] = _mm256_permute2x128_si256(tmp[1], tmp[3], 0x20); + s[2] = _mm256_permute2x128_si256(tmp[0], tmp[2], 0x31); + s[3] = _mm256_permute2x128_si256(tmp[1], tmp[3], 0x31); +} + + +void sha512_init4x(sha512x4ctx *ctx) { +#define SET4(x) _mm256_set_epi64x((long long)(x), (long long)(x), (long long)(x), (long long)(x)) + ctx->s[0] = SET4(0x6a09e667f3bcc908ULL); + ctx->s[1] = SET4(0xbb67ae8584caa73bULL); + ctx->s[2] = SET4(0x3c6ef372fe94f82bULL); + ctx->s[3] = SET4(0xa54ff53a5f1d36f1ULL); + ctx->s[4] = SET4(0x510e527fade682d1ULL); + ctx->s[5] = SET4(0x9b05688c2b3e6c1fULL); + ctx->s[6] = SET4(0x1f83d9abfb41bd6bULL); + ctx->s[7] = SET4(0x5be0cd19137e2179ULL); +#undef SET4 + + ctx->datalen = 0; + ctx->msglen = 0; +} + +#define XOR _mm256_xor_si256 +#define OR _mm256_or_si256 +#define AND _mm256_and_si256 +#define ADD64 _mm256_add_epi64 + +#define LOAD(src) _mm256_loadu_si256((__m256i *)(src)) + +#define SHIFTR64(x, y) _mm256_srli_epi64(x, y) +#define SHIFTL64(x, y) _mm256_slli_epi64(x, y) + +#define ROTR64(x, y) OR(SHIFTR64(x, y), SHIFTL64(x, 64 - (y))) + +static u256 XOR3(u256 a, u256 b, u256 c) { + return XOR(XOR(a, b), c); +} + +#define ADD3_64(a, b, c) ADD64(ADD64(a, b), c) +#define ADD4_64(a, b, c, d) ADD64(ADD64(ADD64(a, b), c), d) +#define ADD5_64(a, b, c, d, e) ADD64(ADD64(ADD64(ADD64(a, b), c), d), e) + +static u256 MAJ_AVX(u256 a, u256 b, u256 c) { + return XOR(c, AND(XOR(a, c), XOR(b, c))); +} +static u256 CH_AVX(u256 a, u256 b, u256 c) { + return XOR(c, AND(a, XOR(b, c))); +} +static u256 SIGMA0_AVX(u256 x) { + return XOR3(ROTR64(x, 28), ROTR64(x, 34), ROTR64(x, 39)); +} +static u256 SIGMA1_AVX(u256 x) { + return XOR3(ROTR64(x, 14), ROTR64(x, 18), ROTR64(x, 41)); +} +static u256 GAMMA0_AVX(u256 x) { + return XOR3(ROTR64(x, 1), ROTR64(x, 8), SHIFTR64(x, 7)); +} +static u256 GAMMA1_AVX(u256 x) { + return XOR3(ROTR64(x, 19), ROTR64(x, 61), SHIFTR64(x, 6)); +} + +#define SHA512ROUND_AVX(a, b, c, d, e, f, g, h, rc, w) \ + T0 = ADD5_64(h, w, SIGMA1_AVX(e), CH_AVX(e, f, g), _mm256_set1_epi64x((long long)RC[rc])); \ + T1 = ADD64(SIGMA0_AVX(a), MAJ_AVX(a, b, c)); \ + (d) = ADD64(d, T0); \ + (h) = ADD64(T0, T1); + +static const unsigned long long RC[80] = { + 0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL, + 0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL, + 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL, + 0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL, + 0xd807aa98a3030242ULL, 0x12835b0145706fbeULL, + 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL, + 0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL, + 0x9bdc06a725c71235ULL, 0xc19bf174cf692694ULL, + 0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL, + 0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL, + 0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL, + 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL, + 0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL, + 0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL, + 0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL, + 0x06ca6351e003826fULL, 0x142929670a0e6e70ULL, + 0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL, + 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL, + 0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL, + 0x81c2c92e47edaee6ULL, 0x92722c851482353bULL, + 0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL, + 0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL, + 0xd192e819d6ef5218ULL, 0xd69906245565a910ULL, + 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL, + 0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL, + 0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL, + 0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL, + 0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL, + 0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL, + 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL, + 0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL, + 0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL, + 0xca273eceea26619cULL, 0xd186b8c721c0c207ULL, + 0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL, + 0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL, + 0x113f9804bef90daeULL, 0x1b710b35131c471bULL, + 0x28db77f523047d84ULL, 0x32caab7b40c72493ULL, + 0x3c9ebe0a15c9bebcULL, 0x431d67c49c100d4cULL, + 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL, + 0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL, +}; + +void sha512_transform4x( + sha512x4ctx *ctx, + const unsigned char *d0, + const unsigned char *d1, + const unsigned char *d2, + const unsigned char *d3) { + u256 s0, s1, s2, s3, s4, s5, s6, s7, w[16], T0, T1, nw; + + // Load words and transform data correctly + w[0 ] = BYTESWAP(LOAD(d0 )); + w[0 + 4] = BYTESWAP(LOAD(d0 + 32)); + w[0 + 8] = BYTESWAP(LOAD(d0 + 64)); + w[0 + 12] = BYTESWAP(LOAD(d0 + 96)); + + w[1 ] = BYTESWAP(LOAD(d1 )); + w[1 + 4] = BYTESWAP(LOAD(d1 + 32)); + w[1 + 8] = BYTESWAP(LOAD(d1 + 64)); + w[1 + 12] = BYTESWAP(LOAD(d1 + 96)); + + w[2 ] = BYTESWAP(LOAD(d2 )); + w[2 + 4] = BYTESWAP(LOAD(d2 + 32)); + w[2 + 8] = BYTESWAP(LOAD(d2 + 64)); + w[2 + 12] = BYTESWAP(LOAD(d2 + 96)); + + w[3 ] = BYTESWAP(LOAD(d3 )); + w[3 + 4] = BYTESWAP(LOAD(d3 + 32)); + w[3 + 8] = BYTESWAP(LOAD(d3 + 64)); + w[3 + 12] = BYTESWAP(LOAD(d3 + 96)); + + transpose(w); + transpose(w + 4); + transpose(w + 8); + transpose(w + 12); + + // Initial State + s0 = ctx->s[0]; + s1 = ctx->s[1]; + s2 = ctx->s[2]; + s3 = ctx->s[3]; + s4 = ctx->s[4]; + s5 = ctx->s[5]; + s6 = ctx->s[6]; + s7 = ctx->s[7]; + + // The first 16 rounds (where the w inputs are directly from the data) + SHA512ROUND_AVX(s0, s1, s2, s3, s4, s5, s6, s7, 0, w[0]); + SHA512ROUND_AVX(s7, s0, s1, s2, s3, s4, s5, s6, 1, w[1]); + SHA512ROUND_AVX(s6, s7, s0, s1, s2, s3, s4, s5, 2, w[2]); + SHA512ROUND_AVX(s5, s6, s7, s0, s1, s2, s3, s4, 3, w[3]); + SHA512ROUND_AVX(s4, s5, s6, s7, s0, s1, s2, s3, 4, w[4]); + SHA512ROUND_AVX(s3, s4, s5, s6, s7, s0, s1, s2, 5, w[5]); + SHA512ROUND_AVX(s2, s3, s4, s5, s6, s7, s0, s1, 6, w[6]); + SHA512ROUND_AVX(s1, s2, s3, s4, s5, s6, s7, s0, 7, w[7]); + SHA512ROUND_AVX(s0, s1, s2, s3, s4, s5, s6, s7, 8, w[8]); + SHA512ROUND_AVX(s7, s0, s1, s2, s3, s4, s5, s6, 9, w[9]); + SHA512ROUND_AVX(s6, s7, s0, s1, s2, s3, s4, s5, 10, w[10]); + SHA512ROUND_AVX(s5, s6, s7, s0, s1, s2, s3, s4, 11, w[11]); + SHA512ROUND_AVX(s4, s5, s6, s7, s0, s1, s2, s3, 12, w[12]); + SHA512ROUND_AVX(s3, s4, s5, s6, s7, s0, s1, s2, 13, w[13]); + SHA512ROUND_AVX(s2, s3, s4, s5, s6, s7, s0, s1, 14, w[14]); + SHA512ROUND_AVX(s1, s2, s3, s4, s5, s6, s7, s0, 15, w[15]); + +#define M(i) (((i)+16) & 0xf) +#define NextW(i) \ + w[M(i)] = ADD4_64(GAMMA1_AVX(w[M((i)-2)]), w[M((i)-7)], GAMMA0_AVX(w[M((i)-15)]), w[M((i)-16)]); + + // The remaining 64 rounds (where the w inputs are a linear fix of the data) + for (unsigned i = 16; i < 80; i += 16) { + nw = NextW(0); + SHA512ROUND_AVX(s0, s1, s2, s3, s4, s5, s6, s7, i + 0, nw); + nw = NextW(1); + SHA512ROUND_AVX(s7, s0, s1, s2, s3, s4, s5, s6, i + 1, nw); + nw = NextW(2); + SHA512ROUND_AVX(s6, s7, s0, s1, s2, s3, s4, s5, i + 2, nw); + nw = NextW(3); + SHA512ROUND_AVX(s5, s6, s7, s0, s1, s2, s3, s4, i + 3, nw); + nw = NextW(4); + SHA512ROUND_AVX(s4, s5, s6, s7, s0, s1, s2, s3, i + 4, nw); + nw = NextW(5); + SHA512ROUND_AVX(s3, s4, s5, s6, s7, s0, s1, s2, i + 5, nw); + nw = NextW(6); + SHA512ROUND_AVX(s2, s3, s4, s5, s6, s7, s0, s1, i + 6, nw); + nw = NextW(7); + SHA512ROUND_AVX(s1, s2, s3, s4, s5, s6, s7, s0, i + 7, nw); + nw = NextW(8); + SHA512ROUND_AVX(s0, s1, s2, s3, s4, s5, s6, s7, i + 8, nw); + nw = NextW(9); + SHA512ROUND_AVX(s7, s0, s1, s2, s3, s4, s5, s6, i + 9, nw); + nw = NextW(10); + SHA512ROUND_AVX(s6, s7, s0, s1, s2, s3, s4, s5, i + 10, nw); + nw = NextW(11); + SHA512ROUND_AVX(s5, s6, s7, s0, s1, s2, s3, s4, i + 11, nw); + nw = NextW(12); + SHA512ROUND_AVX(s4, s5, s6, s7, s0, s1, s2, s3, i + 12, nw); + nw = NextW(13); + SHA512ROUND_AVX(s3, s4, s5, s6, s7, s0, s1, s2, i + 13, nw); + nw = NextW(14); + SHA512ROUND_AVX(s2, s3, s4, s5, s6, s7, s0, s1, i + 14, nw); + nw = NextW(15); + SHA512ROUND_AVX(s1, s2, s3, s4, s5, s6, s7, s0, i + 15, nw); + } + + // Feed Forward + ctx->s[0] = ADD64(s0, ctx->s[0]); + ctx->s[1] = ADD64(s1, ctx->s[1]); + ctx->s[2] = ADD64(s2, ctx->s[2]); + ctx->s[3] = ADD64(s3, ctx->s[3]); + ctx->s[4] = ADD64(s4, ctx->s[4]); + ctx->s[5] = ADD64(s5, ctx->s[5]); + ctx->s[6] = ADD64(s6, ctx->s[6]); + ctx->s[7] = ADD64(s7, ctx->s[7]); +} + +static void _sha512x4( + sha512x4ctx *ctx, + unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + unsigned long long inlen) { + unsigned int i = 0; + + while (inlen - i >= 128) { + sha512_transform4x( + ctx, + in0 + i, + in1 + i, + in2 + i, + in3 + i + ); + ctx->msglen += 1024; + i += 128; + } + + ctx->datalen = (unsigned int)(inlen - i); + memcpy(&ctx->msgblocks[128 * 0], in0 + i, ctx->datalen); + memcpy(&ctx->msgblocks[128 * 1], in1 + i, ctx->datalen); + memcpy(&ctx->msgblocks[128 * 2], in2 + i, ctx->datalen); + memcpy(&ctx->msgblocks[128 * 3], in3 + i, ctx->datalen); + + // Padding + unsigned long curlen; + if (ctx->datalen < 112) { + for (i = 0; i < 4; ++i) { + curlen = ctx->datalen; + ctx->msgblocks[128 * i + curlen++] = 0x80; + while (curlen < 128) { + ctx->msgblocks[128 * i + curlen++] = 0x00; + } + } + } else { + for (i = 0; i < 4; ++i) { + curlen = ctx->datalen; + ctx->msgblocks[128 * i + curlen++] = 0x80; + while (curlen < 128) { + ctx->msgblocks[128 * i + curlen++] = 0x00; + } + } + sha512_transform4x( + ctx, + ctx->msgblocks, + ctx->msgblocks + 128, + ctx->msgblocks + 256, + ctx->msgblocks + 384 + ); + memset(ctx->msgblocks, 0, 4 * 128); + } + + // Add length of the message to each block + ctx->msglen += (unsigned long long)(ctx->datalen) * 8; + for (i = 0; i < 4; i++) { + ctx->msgblocks[128 * i + 127] = (unsigned char)(ctx->msglen); + ctx->msgblocks[128 * i + 126] = (unsigned char)(ctx->msglen >> 8); + ctx->msgblocks[128 * i + 125] = (unsigned char)(ctx->msglen >> 16); + ctx->msgblocks[128 * i + 124] = (unsigned char)(ctx->msglen >> 24); + ctx->msgblocks[128 * i + 123] = (unsigned char)(ctx->msglen >> 32); + ctx->msgblocks[128 * i + 122] = (unsigned char)(ctx->msglen >> 40); + ctx->msgblocks[128 * i + 121] = (unsigned char)(ctx->msglen >> 48); + ctx->msgblocks[128 * i + 120] = (unsigned char)(ctx->msglen >> 56); + memset( &ctx->msgblocks[128 * i + 112], 0, 8 ); + } + sha512_transform4x( + ctx, + ctx->msgblocks, + ctx->msgblocks + 128, + ctx->msgblocks + 256, + ctx->msgblocks + 384 + ); + + // Compute final hash output + transpose(ctx->s); + transpose(ctx->s + 4); + + // Store Hash value + __m256i out[2]; + STORE(out, BYTESWAP(ctx->s[0])); + STORE(out + 1, BYTESWAP(ctx->s[4])); + memcpy(out0, out, 64); + + STORE(out, BYTESWAP(ctx->s[1])); + STORE(out + 1, BYTESWAP(ctx->s[5])); + memcpy(out1, out, 64); + + STORE(out, BYTESWAP(ctx->s[2])); + STORE(out + 1, BYTESWAP(ctx->s[6])); + memcpy(out2, out, 64); + + STORE(out, BYTESWAP(ctx->s[3])); + STORE(out + 1, BYTESWAP(ctx->s[7])); + memcpy(out3, out, 64); +} + + +/** + * Note that inlen should be sufficiently small that it still allows for + * an array to be allocated on the stack. Typically 'in' is merely a seed. + * Outputs outlen number of bytes + */ +void mgf1x4_512(unsigned char *outx4, unsigned long outlen, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + unsigned long inlen) { + PQCLEAN_VLA(unsigned char, inbufx4, 4 * (inlen + 4)); + unsigned char outbuf[4 * 64]; + uint32_t i; + unsigned int j; + + memcpy(inbufx4 + 0 * (inlen + 4), in0, inlen); + memcpy(inbufx4 + 1 * (inlen + 4), in1, inlen); + memcpy(inbufx4 + 2 * (inlen + 4), in2, inlen); + memcpy(inbufx4 + 3 * (inlen + 4), in3, inlen); + + /* While we can fit in at least another full block of SHA512 output.. */ + unsigned long remaining = outlen; + for (i = 0; remaining > 0; i++) { + unsigned long this_step = SPX_SHA512_OUTPUT_BYTES; + if (this_step > remaining) { + this_step = remaining; + } + remaining -= this_step; + for (j = 0; j < 4; j++) { + u32_to_bytes(inbufx4 + inlen + j * (inlen + 4), i); + } + + sha512x4ctx ctx; + sha512_init4x(&ctx); + + _sha512x4( + &ctx, + outbuf + 0 * 64, + outbuf + 1 * 64, + outbuf + 2 * 64, + outbuf + 3 * 64, + inbufx4 + 0 * (inlen + 4), + inbufx4 + 1 * (inlen + 4), + inbufx4 + 2 * (inlen + 4), + inbufx4 + 3 * (inlen + 4), + inlen + 4 + ); + + memcpy(outx4 + 0 * outlen, outbuf + 0 * 64, this_step); + memcpy(outx4 + 1 * outlen, outbuf + 1 * 64, this_step); + memcpy(outx4 + 2 * outlen, outbuf + 2 * 64, this_step); + memcpy(outx4 + 3 * outlen, outbuf + 3 * 64, this_step); + outx4 += this_step; + } +} + +void sha512x4_seeded( + unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const sha512x4ctx *seed, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + unsigned long long inlen) { + sha512x4ctx ctx; + sha512_ctx_clone4x(&ctx, seed); + _sha512x4( + &ctx, + out0, out1, out2, out3, + in0, in1, in2, in3, + inlen + ); +} + +void sha512_ctx_clone4x(sha512x4ctx *out, const sha512x4ctx *in) { + memcpy(out, in, sizeof(sha512x4ctx)); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/sha512x4.h b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/sha512x4.h new file mode 100644 index 0000000000..9bbe736514 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/sha512x4.h @@ -0,0 +1,58 @@ +#ifndef SHA512AVX_H +#define SHA512AVX_H + +#include +#include + + +#include "params.h" + +typedef struct SHA512state4x { + __m256i s[8]; + unsigned char msgblocks[4 * 128]; + unsigned int datalen; + unsigned long long msglen; +} sha512x4ctx; + +#define sha512_init4x SPX_NAMESPACE(sha512_init4x) +void sha512_init4x(sha512x4ctx *ctx); + +#define sha512_transform4x SPX_NAMESPACE(sha512_transform4x) +void sha512_transform4x( + sha512x4ctx *ctx, + const unsigned char *d0, + const unsigned char *d1, + const unsigned char *d2, + const unsigned char *d3); + + +#define sha512x4_seeded SPX_NAMESPACE(sha512x4_seeded) +void sha512x4_seeded( + unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const sha512x4ctx *seed, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + unsigned long long inlen); + +#define sha512_ctx_clone4x SPX_NAMESPACE(sha512_ctx_clone4x) +void sha512_ctx_clone4x(sha512x4ctx *out, const sha512x4ctx *in); + +/** + * Note that inlen should be sufficiently small that it still allows for + * an array to be allocated on the stack. Typically 'in' is merely a seed. + * Outputs outlen number of bytes + */ +#define mgf1x4_512 SPX_NAMESPACE(mgf1x4_512) +void mgf1x4_512(unsigned char *outx4, unsigned long outlen, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + unsigned long inlen); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/sign.c b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/sign.c new file mode 100644 index 0000000000..9d0c7d1b22 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/sign.c @@ -0,0 +1,286 @@ +#include +#include +#include + +#include "address.h" +#include "context.h" +#include "fors.h" +#include "hash.h" +#include "merkle.h" +#include "nistapi.h" +#include "params.h" +#include "randombytes.h" +#include "thash.h" +#include "utils.h" +#include "wots.h" + +/* + * Returns the length of a secret key, in bytes + */ +size_t crypto_sign_secretkeybytes(void) { + return CRYPTO_SECRETKEYBYTES; +} + +/* + * Returns the length of a public key, in bytes + */ +size_t crypto_sign_publickeybytes(void) { + return CRYPTO_PUBLICKEYBYTES; +} + +/* + * Returns the length of a signature, in bytes + */ +size_t crypto_sign_bytes(void) { + return CRYPTO_BYTES; +} + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +size_t crypto_sign_seedbytes(void) { + return CRYPTO_SEEDBYTES; +} + +/* + * Generates an SPX key pair given a seed of length + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [PUB_SEED || root] + */ +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed) { + spx_ctx ctx; + + /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ + memcpy(sk, seed, CRYPTO_SEEDBYTES); + + memcpy(pk, sk + 2 * SPX_N, SPX_N); + + memcpy(ctx.pub_seed, pk, SPX_N); + memcpy(ctx.sk_seed, sk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + /* Compute root node of the top-most subtree. */ + merkle_gen_root(sk + 3 * SPX_N, &ctx); + + // cleanup + free_hash_function(&ctx); + + memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); + + return 0; +} + +/* + * Generates an SPX key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [PUB_SEED || root] + */ +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { + uint8_t seed[CRYPTO_SEEDBYTES]; + randombytes(seed, CRYPTO_SEEDBYTES); + crypto_sign_seed_keypair(pk, sk, seed); + + return 0; +} + +/** + * Returns an array containing a detached signature. + */ +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk) { + spx_ctx ctx; + + const uint8_t *sk_prf = sk + SPX_N; + const uint8_t *pk = sk + 2 * SPX_N; + + uint8_t optrand[SPX_N]; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t root[SPX_N]; + uint32_t i; + uint64_t tree; + uint32_t idx_leaf; + uint32_t wots_addr[8] = {0}; + uint32_t tree_addr[8] = {0}; + + memcpy(ctx.sk_seed, sk, SPX_N); + memcpy(ctx.pub_seed, pk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + + /* Optionally, signing can be made non-deterministic using optrand. + This can help counter side-channel attacks that would benefit from + getting a large number of traces when the signer uses the same nodes. */ + randombytes(optrand, SPX_N); + /* Compute the digest randomization value. */ + gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); + + /* Derive the message digest and leaf index from R, PK and M. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; + + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); + + /* Sign the message hash using FORS. */ + fors_sign(sig, root, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); + sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; + + /* Update the indices for the next layer. */ + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; + } + + free_hash_function(&ctx); + + *siglen = SPX_BYTES; + + return 0; +} + +/** + * Verifies a detached signature and message under a given public key. + */ +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk) { + spx_ctx ctx; + const uint8_t *pub_root = pk + SPX_N; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t wots_pk[SPX_WOTS_BYTES]; + uint8_t root[SPX_N]; + uint8_t leaf[SPX_N]; + unsigned int i; + uint64_t tree; + uint32_t idx_leaf; + uint32_t wots_addr[8] = {0}; + uint32_t tree_addr[8] = {0}; + uint32_t wots_pk_addr[8] = {0}; + + if (siglen != SPX_BYTES) { + return -1; + } + + memcpy(ctx.pub_seed, pk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); + + /* Derive the message digest and leaf index from R || PK || M. */ + /* The additional SPX_N is a result of the hash domain separator. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; + + /* Layer correctly defaults to 0, so no need to set_layer_addr */ + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); + + fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + /* For each subtree.. */ + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + copy_keypair_addr(wots_pk_addr, wots_addr); + + /* The WOTS public key is only correct if the signature was correct. */ + /* Initially, root is the FORS pk, but on subsequent iterations it is + the root of the subtree below the currently processed subtree. */ + wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); + sig += SPX_WOTS_BYTES; + + /* Compute the leaf node using the WOTS public key. */ + thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); + + /* Compute the root node of this subtree. */ + compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, + &ctx, tree_addr); + sig += SPX_TREE_HEIGHT * SPX_N; + + /* Update the indices for the next layer. */ + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; + } + + // cleanup + free_hash_function(&ctx); + + /* Check if the root node equals the root node in the public key. */ + if (memcmp(root, pub_root, SPX_N) != 0) { + return -1; + } + + return 0; +} + + +/** + * Returns an array containing the signature followed by the message. + */ +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk) { + size_t siglen; + + crypto_sign_signature(sm, &siglen, m, mlen, sk); + + memmove(sm + SPX_BYTES, m, mlen); + *smlen = siglen + mlen; + + return 0; +} + +/** + * Verifies a given signature-message pair under a given public key. + */ +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk) { + /* The API caller does not necessarily know what size a signature should be + but SPHINCS+ signatures are always exactly SPX_BYTES. */ + if (smlen < SPX_BYTES) { + memset(m, 0, smlen); + *mlen = 0; + return -1; + } + + *mlen = smlen - SPX_BYTES; + + if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { + memset(m, 0, smlen); + *mlen = 0; + return -1; + } + + /* If verification was successful, move the message to the right place. */ + memmove(m, sm + SPX_BYTES, *mlen); + + return 0; +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/thash.h b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/thash.h new file mode 100644 index 0000000000..8687ccfb4d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/thash.h @@ -0,0 +1,13 @@ +#ifndef SPX_THASH_H +#define SPX_THASH_H + +#include "context.h" +#include "params.h" + +#include + +#define thash SPX_NAMESPACE(thash) +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/thash_sha2_robust.c b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/thash_sha2_robust.c new file mode 100644 index 0000000000..3ab891175f --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/thash_sha2_robust.c @@ -0,0 +1,68 @@ +#include +#include + +#include "address.h" +#include "context.h" +#include "hash.h" +#include "params.h" +#include "sha2.h" +#include "thash.h" +#include "utils.h" + +static void thash_512(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]); + +/** + * Takes an array of inblocks concatenated arrays of SPX_N bytes. + */ +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]) { + if (inblocks > 1) { + thash_512(out, in, inblocks, ctx, addr); + return; + } + unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES]; + PQCLEAN_VLA(uint8_t, bitmask, inblocks * SPX_N); + PQCLEAN_VLA(uint8_t, buf, SPX_N + SPX_SHA256_OUTPUT_BYTES + inblocks * SPX_N); + sha256ctx sha2_state; + unsigned int i; + + memcpy(buf, ctx->pub_seed, SPX_N); + memcpy(buf + SPX_N, addr, SPX_SHA256_ADDR_BYTES); + mgf1_256(bitmask, inblocks * SPX_N, buf, SPX_N + SPX_SHA256_ADDR_BYTES); + + /* Retrieve precomputed state containing pub_seed */ + sha256_inc_ctx_clone(&sha2_state, &ctx->state_seeded); + + for (i = 0; i < inblocks * SPX_N; i++) { + buf[SPX_N + SPX_SHA256_ADDR_BYTES + i] = in[i] ^ bitmask[i]; + } + + sha256_inc_finalize(outbuf, &sha2_state, buf + SPX_N, + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N); + memcpy(out, outbuf, SPX_N); +} + +static void thash_512(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]) { + unsigned char outbuf[SPX_SHA512_OUTPUT_BYTES]; + PQCLEAN_VLA(uint8_t, bitmask, inblocks * SPX_N); + PQCLEAN_VLA(uint8_t, buf, SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N); + sha512ctx sha2_state; + unsigned int i; + + memcpy(buf, ctx->pub_seed, SPX_N); + memcpy(buf + SPX_N, addr, SPX_SHA256_ADDR_BYTES); + mgf1_512(bitmask, inblocks * SPX_N, buf, SPX_N + SPX_SHA256_ADDR_BYTES); + + /* Retrieve precomputed state containing pub_seed */ + sha512_inc_ctx_clone(&sha2_state, &ctx->state_seeded_512); + + for (i = 0; i < inblocks * SPX_N; i++) { + buf[SPX_N + SPX_SHA256_ADDR_BYTES + i] = in[i] ^ bitmask[i]; + } + + sha512_inc_finalize(outbuf, &sha2_state, buf + SPX_N, + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N); + memcpy(out, outbuf, SPX_N); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/thash_sha2_robustx8.c b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/thash_sha2_robustx8.c new file mode 100644 index 0000000000..991faa7eeb --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/thash_sha2_robustx8.c @@ -0,0 +1,268 @@ +#include +#include + +#include "thashx8.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "sha2.h" +#include "sha256avx.h" +#include "sha256x8.h" +#include "utils.h" + +#include "sha512x4.h" + +static void thashx8_512( + unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, + unsigned int inblocks, + const spx_ctx *ctx, + uint32_t addrx8[8 * 8] +); + +/** + * 8-way parallel version of thash; takes 8x as much input and output + */ +void thashx8(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addrx8[8 * 8]) { + if (inblocks > 1) { + thashx8_512( + out0, out1, out2, out3, out4, out5, out6, out7, + in0, in1, in2, in3, in4, in5, in6, in7, + inblocks, ctx, addrx8); + return; + } + PQCLEAN_VLA(unsigned char, bufx8, 8 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)); + unsigned char outbufx8[8 * SPX_SHA256_OUTPUT_BYTES]; + PQCLEAN_VLA(unsigned char, bitmaskx8, 8 * (inblocks * SPX_N)); + unsigned int i; + + for (i = 0; i < 8; i++) { + memcpy(bufx8 + i * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + ctx->pub_seed, SPX_N); + memcpy(bufx8 + SPX_N + + i * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + addrx8 + i * 8, SPX_SHA256_ADDR_BYTES); + } + + mgf1x8(bitmaskx8, inblocks * SPX_N, + bufx8 + 0 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + 1 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + 2 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + 3 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + 4 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + 5 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + 6 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + 7 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + SPX_N + SPX_SHA256_ADDR_BYTES); + + for (i = 0; i < inblocks * SPX_N; i++) { + bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + + 0 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = + in0[i] ^ bitmaskx8[i + 0 * (inblocks * SPX_N)]; + bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + + 1 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = + in1[i] ^ bitmaskx8[i + 1 * (inblocks * SPX_N)]; + bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + + 2 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = + in2[i] ^ bitmaskx8[i + 2 * (inblocks * SPX_N)]; + bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + + 3 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = + in3[i] ^ bitmaskx8[i + 3 * (inblocks * SPX_N)]; + bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + + 4 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = + in4[i] ^ bitmaskx8[i + 4 * (inblocks * SPX_N)]; + bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + + 5 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = + in5[i] ^ bitmaskx8[i + 5 * (inblocks * SPX_N)]; + bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + + 6 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = + in6[i] ^ bitmaskx8[i + 6 * (inblocks * SPX_N)]; + bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + + 7 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = + in7[i] ^ bitmaskx8[i + 7 * (inblocks * SPX_N)]; + } + + sha256x8_seeded( + /* out */ + outbufx8 + 0 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 1 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 2 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 3 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 4 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 5 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 6 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 7 * SPX_SHA256_OUTPUT_BYTES, + + /* seed */ + &ctx->statex8_seeded, + + /* in */ + bufx8 + SPX_N + 0 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + SPX_N + 1 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + SPX_N + 2 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + SPX_N + 3 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + SPX_N + 4 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + SPX_N + 5 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + SPX_N + 6 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + SPX_N + 7 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N /* len */ + ); + + memcpy(out0, outbufx8 + 0 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out1, outbufx8 + 1 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out2, outbufx8 + 2 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out3, outbufx8 + 3 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out4, outbufx8 + 4 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out5, outbufx8 + 5 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out6, outbufx8 + 6 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out7, outbufx8 + 7 * SPX_SHA256_OUTPUT_BYTES, SPX_N); +} + +/** + * 2x4-way parallel version of thash; this is for the uses of thash that are + * based on SHA-512 + */ +static void thashx8_512( + unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, + unsigned int inblocks, + const spx_ctx *ctx, + uint32_t addrx8[8 * 8]) { + PQCLEAN_VLA(unsigned char, bufx8, 8 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)); + unsigned char outbuf[4 * SPX_SHA512_OUTPUT_BYTES]; + PQCLEAN_VLA(unsigned char, bitmaskx4, 4 * (inblocks * SPX_N)); + unsigned int i; + + for (i = 0; i < 8; i++) { + memcpy(bufx8 + i * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + ctx->pub_seed, SPX_N); + memcpy(bufx8 + SPX_N + + i * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + addrx8 + i * 8, SPX_SHA256_ADDR_BYTES); + } + + mgf1x4_512(bitmaskx4, inblocks * SPX_N, + bufx8 + 0 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + 1 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + 2 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + 3 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + SPX_N + SPX_SHA256_ADDR_BYTES); + + for (i = 0; i < inblocks * SPX_N; i++) { + bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + + 0 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = + in0[i] ^ bitmaskx4[i + 0 * (inblocks * SPX_N)]; + bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + + 1 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = + in1[i] ^ bitmaskx4[i + 1 * (inblocks * SPX_N)]; + bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + + 2 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = + in2[i] ^ bitmaskx4[i + 2 * (inblocks * SPX_N)]; + bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + + 3 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = + in3[i] ^ bitmaskx4[i + 3 * (inblocks * SPX_N)]; + } + + mgf1x4_512(bitmaskx4, inblocks * SPX_N, + bufx8 + 4 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + 5 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + 6 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + 7 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + SPX_N + SPX_SHA256_ADDR_BYTES); + + for (i = 0; i < inblocks * SPX_N; i++) { + bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + + 4 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = + in4[i] ^ bitmaskx4[i + 0 * (inblocks * SPX_N)]; + bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + + 5 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = + in5[i] ^ bitmaskx4[i + 1 * (inblocks * SPX_N)]; + bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + + 6 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = + in6[i] ^ bitmaskx4[i + 2 * (inblocks * SPX_N)]; + bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + + 7 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = + in7[i] ^ bitmaskx4[i + 3 * (inblocks * SPX_N)]; + } + + sha512x4_seeded( + outbuf + 0 * SPX_SHA512_OUTPUT_BYTES, + outbuf + 1 * SPX_SHA512_OUTPUT_BYTES, + outbuf + 2 * SPX_SHA512_OUTPUT_BYTES, + outbuf + 3 * SPX_SHA512_OUTPUT_BYTES, + &ctx->statex4_seeded_512, /* seed */ + bufx8 + SPX_N + 0 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + SPX_N + 1 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + SPX_N + 2 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + SPX_N + 3 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N /* len */ + ); + + memcpy(out0, outbuf + 0 * SPX_SHA512_OUTPUT_BYTES, SPX_N); + memcpy(out1, outbuf + 1 * SPX_SHA512_OUTPUT_BYTES, SPX_N); + memcpy(out2, outbuf + 2 * SPX_SHA512_OUTPUT_BYTES, SPX_N); + memcpy(out3, outbuf + 3 * SPX_SHA512_OUTPUT_BYTES, SPX_N); + + sha512x4_seeded( + outbuf + 0 * SPX_SHA512_OUTPUT_BYTES, + outbuf + 1 * SPX_SHA512_OUTPUT_BYTES, + outbuf + 2 * SPX_SHA512_OUTPUT_BYTES, + outbuf + 3 * SPX_SHA512_OUTPUT_BYTES, + &ctx->statex4_seeded_512, /* seed */ + bufx8 + SPX_N + 4 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + SPX_N + 5 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + SPX_N + 6 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + SPX_N + 7 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N /* len */ + ); + + memcpy(out4, outbuf + 0 * SPX_SHA512_OUTPUT_BYTES, SPX_N); + memcpy(out5, outbuf + 1 * SPX_SHA512_OUTPUT_BYTES, SPX_N); + memcpy(out6, outbuf + 2 * SPX_SHA512_OUTPUT_BYTES, SPX_N); + memcpy(out7, outbuf + 3 * SPX_SHA512_OUTPUT_BYTES, SPX_N); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/thashx8.h b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/thashx8.h new file mode 100644 index 0000000000..c02fe9cf3e --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/thashx8.h @@ -0,0 +1,28 @@ +#ifndef SPX_THASHX8_H +#define SPX_THASHX8_H + +#include + +#include "context.h" +#include "params.h" + +#define thashx8 SPX_NAMESPACE(thashx8) +void thashx8(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addrx8[8 * 8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/utils.c b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/utils.c new file mode 100644 index 0000000000..177b541fb9 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/utils.c @@ -0,0 +1,148 @@ +#include + +#include "utils.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "thash.h" + +/** + * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. + */ +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in) { + int i; + + /* Iterate over out in decreasing order, for big-endianness. */ + for (i = (signed int)outlen - 1; i >= 0; i--) { + out[i] = in & 0xff; + in = in >> 8; + } +} + +void u32_to_bytes(unsigned char *out, uint32_t in) { + out[0] = (unsigned char)(in >> 24); + out[1] = (unsigned char)(in >> 16); + out[2] = (unsigned char)(in >> 8); + out[3] = (unsigned char)in; +} + +/** + * Converts the inlen bytes in 'in' from big-endian byte order to an integer. + */ +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { + unsigned long long retval = 0; + unsigned int i; + + for (i = 0; i < inlen; i++) { + retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); + } + return retval; +} + +/** + * Computes a root node given a leaf and an auth path. + * Expects address to be complete other than the tree_height and tree_index. + */ +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]) { + uint32_t i; + unsigned char buffer[2 * SPX_N]; + + /* If leaf_idx is odd (last bit = 1), current path element is a right child + and auth_path has to go left. Otherwise it is the other way around. */ + if (leaf_idx & 1) { + memcpy(buffer + SPX_N, leaf, SPX_N); + memcpy(buffer, auth_path, SPX_N); + } else { + memcpy(buffer, leaf, SPX_N); + memcpy(buffer + SPX_N, auth_path, SPX_N); + } + auth_path += SPX_N; + + for (i = 0; i < tree_height - 1; i++) { + leaf_idx >>= 1; + idx_offset >>= 1; + /* Set the address of the node we're creating. */ + set_tree_height(addr, i + 1); + set_tree_index(addr, leaf_idx + idx_offset); + + /* Pick the right or left neighbor, depending on parity of the node. */ + if (leaf_idx & 1) { + thash(buffer + SPX_N, buffer, 2, ctx, addr); + memcpy(buffer, auth_path, SPX_N); + } else { + thash(buffer, buffer, 2, ctx, addr); + memcpy(buffer + SPX_N, auth_path, SPX_N); + } + auth_path += SPX_N; + } + + /* The last iteration is exceptional; we do not copy an auth_path node. */ + leaf_idx >>= 1; + idx_offset >>= 1; + set_tree_height(addr, tree_height); + set_tree_index(addr, leaf_idx + idx_offset); + thash(root, buffer, 2, ctx, addr); +} + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx * /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]) { + PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); + PQCLEAN_VLA(unsigned int, heights, tree_height + 1); + unsigned int offset = 0; + uint32_t idx; + uint32_t tree_idx; + + for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { + /* Add the next leaf node to the stack. */ + gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); + offset++; + heights[offset - 1] = 0; + + /* If this is a node we need for the auth path.. */ + if ((leaf_idx ^ 0x1) == idx) { + memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); + } + + /* While the top-most nodes are of equal height.. */ + while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { + /* Compute index of the new node, in the next layer. */ + tree_idx = (idx >> (heights[offset - 1] + 1)); + + /* Set the address of the node we're creating. */ + set_tree_height(tree_addr, heights[offset - 1] + 1); + set_tree_index(tree_addr, + tree_idx + (idx_offset >> (heights[offset - 1] + 1))); + /* Hash the top-most nodes from the stack together. */ + thash(stack + (offset - 2)*SPX_N, + stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); + offset--; + /* Note that the top-most node is now one layer higher. */ + heights[offset - 1]++; + + /* If this is a node we need for the auth path.. */ + if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { + memcpy(auth_path + heights[offset - 1]*SPX_N, + stack + (offset - 1)*SPX_N, SPX_N); + } + } + } + memcpy(root, stack, SPX_N); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/utils.h b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/utils.h new file mode 100644 index 0000000000..64f5d5a53a --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/utils.h @@ -0,0 +1,58 @@ +#ifndef SPX_UTILS_H +#define SPX_UTILS_H + +#include + +#include "compat.h" +#include "context.h" +#include "params.h" + + +/* To support MSVC use alloca() instead of VLAs. See #20. */ + + +/** + * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. + */ +#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in); +#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) +void u32_to_bytes(unsigned char *out, uint32_t in); + +/** + * Converts the inlen bytes in 'in' from big-endian byte order to an integer. + */ +#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); + +/** + * Computes a root node given a leaf and an auth path. + * Expects address to be complete other than the tree_height and tree_index. + */ +#define compute_root SPX_NAMESPACE(compute_root) +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]); + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +#define treehash SPX_NAMESPACE(treehash) +void treehash(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx *ctx /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]); + + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/utilsx8.c b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/utilsx8.c new file mode 100644 index 0000000000..f044b9595d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/utilsx8.c @@ -0,0 +1,146 @@ +#include + +#include "utils.h" +#include "utilsx8.h" + +#include "address.h" +#include "params.h" +#include "thashx8.h" + +/* + * Generate the entire Merkle tree, computing the authentication path for leaf_idx, + * and the resulting root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) + * + * This expects tree_addrx8 to be initialized to 8 parallel addr structures for + * the Merkle tree nodes + * + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + * + * This works by using the standard Merkle tree building algorithm, except + * that each 'node' tracked is actually 8 consecutive nodes in the real tree. + * When we combine two logical nodes ABCDEFGH and STUVWXYZ, we perform the H + * operation on adjacent real nodes, forming the parent logical node + * (AB)(CD)(EF)(GH)(ST)(UV)(WX)(YZ) + * + * When we get to the top three levels of the real tree (where there is only + * one logical node), we continue this operation three more times; the right + * most real node will by the actual root (and the other 7 nodes will be + * garbage). We follow the same thashx8 logic so that the 'extract + * authentication path components' part of the loop is still executed (and + * to simplify the code somewhat) + * + * This currently assumes tree_height >= 3; I suspect that doing an adjusting + * idx, addr_idx on the gen_leafx8 call if tree_height < 3 would fix it; since + * we don't actually use such short trees, I haven't bothered + */ +void treehashx8(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, + uint32_t tree_height, + void (*gen_leafx8)( + unsigned char * /* Where to write the leaves */, + const spx_ctx *, + uint32_t idx, void *info), + uint32_t tree_addrx8[8 * 8], + void *info) { + /* This is where we keep the intermediate nodes */ + PQCLEAN_VLA(unsigned char, stackx8, tree_height * 8 * SPX_N); + uint32_t left_adj = 0, prev_left_adj = 0; /* When we're doing the top 3 */ + /* levels, the left-most part of the tree isn't at the beginning */ + /* of current[]. These give the offset of the actual start */ + + uint32_t idx; + uint32_t max_idx = ((uint32_t)1 << (tree_height - 3)) - 1; + for (idx = 0;; idx++) { + unsigned char current[8 * SPX_N]; /* Current logical node */ + gen_leafx8( current, ctx, 8 * idx + idx_offset, + info ); + + /* Now combine the freshly generated right node with previously */ + /* generated left ones */ + uint32_t internal_idx_offset = idx_offset; + uint32_t internal_idx = idx; + uint32_t internal_leaf = leaf_idx; + uint32_t h; /* The height we are in the Merkle tree */ + for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { + + /* Special processing if we're at the top of the tree */ + if (h >= tree_height - 3) { + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[7 * SPX_N], SPX_N ); + return; + } + /* The tree indexing logic is a bit off in this case */ + /* Adjust it so that the left-most node of the part of */ + /* the tree that we're processing has index 0 */ + prev_left_adj = left_adj; + left_adj = (uint32_t)(8 - (1 << (tree_height - h - 1))); + } + + /* Check if we hit the top of the tree */ + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[7 * SPX_N], SPX_N ); + return; + } + + /* + * Check if one of the nodes we have is a part of the + * authentication path; if it is, write it out + */ + if ((((internal_idx << 3) ^ internal_leaf) & ~0x7U) == 0) { + memcpy( &auth_path[ h * SPX_N ], + ¤t[(((internal_leaf & 7) ^ 1) + prev_left_adj) * SPX_N], + SPX_N ); + } + + /* + * Check if we're at a left child; if so, stop going up the stack + * Exception: if we've reached the end of the tree, keep on going + * (so we combine the last 8 nodes into the one root node in three + * more iterations) + */ + if ((internal_idx & 1) == 0 && idx < max_idx) { + break; + } + + /* Ok, we're at a right node (or doing the top 3 levels) */ + /* Now combine the left and right logical nodes together */ + + /* Set the address of the node we're creating. */ + uint32_t j; + internal_idx_offset >>= 1; + for (j = 0; j < 8; j++) { + set_tree_height(tree_addrx8 + j * 8, h + 1); + set_tree_index(tree_addrx8 + j * 8, + (8 / 2) * (internal_idx & ~1U) + j - left_adj + internal_idx_offset ); + } + unsigned char *left = &stackx8[h * 8 * SPX_N]; + thashx8( ¤t[0 * SPX_N], + ¤t[1 * SPX_N], + ¤t[2 * SPX_N], + ¤t[3 * SPX_N], + ¤t[4 * SPX_N], + ¤t[5 * SPX_N], + ¤t[6 * SPX_N], + ¤t[7 * SPX_N], + &left [0 * SPX_N], + &left [2 * SPX_N], + &left [4 * SPX_N], + &left [6 * SPX_N], + ¤t[0 * SPX_N], + ¤t[2 * SPX_N], + ¤t[4 * SPX_N], + ¤t[6 * SPX_N], + 2, ctx, tree_addrx8); + } + + /* We've hit a left child; save the current for when we get the */ + /* corresponding right right */ + memcpy( &stackx8[h * 8 * SPX_N], current, 8 * SPX_N); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/utilsx8.h b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/utilsx8.h new file mode 100644 index 0000000000..806d1e85be --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/utilsx8.h @@ -0,0 +1,29 @@ +#ifndef SPX_UTILSX8_H +#define SPX_UTILSX8_H + +#include + +#include "params.h" + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + * + * This implementation uses AVX to compute internal nodes 8 at a time (in + * parallel) + */ +#define treehashx8 SPX_NAMESPACE(treehashx8) +void treehashx8(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leafx8)( + unsigned char * /* Where to write the leaves */, + const spx_ctx * /* ctx */, + uint32_t addr_idx, void *info), + uint32_t tree_addrx8[8 * 8], void *info); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/wots.c b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/wots.c new file mode 100644 index 0000000000..689baf4db9 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/wots.c @@ -0,0 +1,291 @@ +#include +#include + +#include "wots.h" + +#include "address.h" +#include "hash.h" +#include "hashx8.h" +#include "params.h" +#include "thash.h" +#include "thashx8.h" +#include "utils.h" +#include "utilsx8.h" +#include "wotsx8.h" + +// TODO clarify address expectations, and make them more uniform. +// TODO i.e. do we expect types to be set already? +// TODO and do we expect modifications or copies? + +/** + * Computes up the chains + */ +static void gen_chains( + unsigned char *out, + const unsigned char *in, + unsigned int start[SPX_WOTS_LEN], + const unsigned int steps[SPX_WOTS_LEN], + const spx_ctx *ctx, + uint32_t addr[8]) { + uint32_t i, j, k, idx, watching; + int done; + unsigned char empty[SPX_N]; + unsigned char *bufs[8]; + uint32_t addrs[8 * 8]; + + int l; + uint16_t counts[SPX_WOTS_W] = { 0 }; + uint16_t idxs[SPX_WOTS_LEN]; + uint16_t total, newTotal; + + /* set addrs = {addr, addr, ..., addr} */ + for (j = 0; j < 8; j++) { + memcpy(addrs + j * 8, addr, sizeof(uint32_t) * 8); + } + + /* Initialize out with the value at position 'start'. */ + memcpy(out, in, SPX_WOTS_LEN * SPX_N); + + /* Sort the chains in reverse order by steps using counting sort. */ + for (i = 0; i < SPX_WOTS_LEN; i++) { + counts[steps[i]]++; + } + total = 0; + for (l = SPX_WOTS_W - 1; l >= 0; l--) { + newTotal = counts[l] + total; + counts[l] = total; + total = newTotal; + } + for (i = 0; i < SPX_WOTS_LEN; i++) { + idxs[counts[steps[i]]] = (uint16_t)i; + counts[steps[i]]++; + } + + /* We got our work cut out for us: do it! */ + for (i = 0; i < SPX_WOTS_LEN; i += 8) { + for (j = 0; j < 8 && i + j < SPX_WOTS_LEN; j++) { + idx = idxs[i + j]; + set_chain_addr(addrs + j * 8, idx); + bufs[j] = out + SPX_N * idx; + } + + /* As the chains are sorted in reverse order, we know that the first + * chain is the longest and the last one is the shortest. We keep + * an eye on whether the last chain is done and then on the one before, + * et cetera. */ + watching = 7; + done = 0; + while (i + watching >= SPX_WOTS_LEN) { + bufs[watching] = &empty[0]; + watching--; + } + + for (k = 0;; k++) { + while (k == steps[idxs[i + watching]]) { + bufs[watching] = &empty[0]; + if (watching == 0) { + done = 1; + break; + } + watching--; + } + if (done) { + break; + } + for (j = 0; j < watching + 1; j++) { + set_hash_addr(addrs + j * 8, k + start[idxs[i + j]]); + } + + thashx8(bufs[0], bufs[1], bufs[2], bufs[3], + bufs[4], bufs[5], bufs[6], bufs[7], + bufs[0], bufs[1], bufs[2], bufs[3], + bufs[4], bufs[5], bufs[6], bufs[7], 1, ctx, addrs); + } + } +} + +/** + * base_w algorithm as described in draft. + * Interprets an array of bytes as integers in base w. + * This only works when log_w is a divisor of 8. + */ +static void base_w(unsigned int *output, const int out_len, + const unsigned char *input) { + int in = 0; + int out = 0; + unsigned char total = 0; + int bits = 0; + int consumed; + + for (consumed = 0; consumed < out_len; consumed++) { + if (bits == 0) { + total = input[in]; + in++; + bits += 8; + } + bits -= SPX_WOTS_LOGW; + output[out] = (total >> bits) & (SPX_WOTS_W - 1); + out++; + } +} + +/* Computes the WOTS+ checksum over a message (in base_w). */ +static void wots_checksum(unsigned int *csum_base_w, + const unsigned int *msg_base_w) { + unsigned int csum = 0; + unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; + unsigned int i; + + /* Compute checksum. */ + for (i = 0; i < SPX_WOTS_LEN1; i++) { + csum += SPX_WOTS_W - 1 - msg_base_w[i]; + } + + /* Convert checksum to base_w. */ + /* Make sure expected empty zero bits are the least significant bits. */ + csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); + ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); + base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); +} + +/* Takes a message and derives the matching chain lengths. */ +void chain_lengths(unsigned int *lengths, const unsigned char *msg) { + base_w(lengths, SPX_WOTS_LEN1, msg); + wots_checksum(lengths + SPX_WOTS_LEN1, lengths); +} + +/** + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. + * + * Writes the computed public key to 'pk'. + */ +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]) { + unsigned int steps[SPX_WOTS_LEN]; + unsigned int start[SPX_WOTS_LEN]; + uint32_t i; + + chain_lengths(start, msg); + + for (i = 0; i < SPX_WOTS_LEN; i++) { + steps[i] = SPX_WOTS_W - 1 - start[i]; + } + + gen_chains(pk, sig, start, steps, ctx, addr); +} + +/* + * This generates 8 sequential WOTS public keys + * It also generates the WOTS signature if leaf_info indicates + * that we're signing with one of these WOTS keys + */ +void wots_gen_leafx8(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info) { + struct leaf_info_x8 *info = v_info; + uint32_t *leaf_addr = info->leaf_addr; + uint32_t *pk_addr = info->pk_addr; + unsigned int i, j, k; + unsigned char pk_buffer[ 8 * SPX_WOTS_BYTES ]; + unsigned wots_offset = SPX_WOTS_BYTES; + unsigned char *buffer; + uint32_t wots_k_mask; + unsigned wots_sign_index; + + if (((leaf_idx ^ info->wots_sign_leaf) & ~7U) == 0) { + /* We're traversing the leaf that's signing; generate the WOTS */ + /* signature */ + wots_k_mask = 0; + wots_sign_index = info->wots_sign_leaf & 7; /* Which of of the 8 */ + /* slots do the signatures come from */ + } else { + /* Nope, we're just generating pk's; turn off the signature logic */ + wots_k_mask = ~0U; + wots_sign_index = 0; + } + + for (j = 0; j < 8; j++) { + set_keypair_addr( leaf_addr + j * 8, leaf_idx + j ); + set_keypair_addr( pk_addr + j * 8, leaf_idx + j ); + } + + for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { + uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k */ + /* to the step if we're generating a signature, ~0 if we're not */ + + /* Start with the secret seed */ + for (j = 0; j < 8; j++) { + set_chain_addr(leaf_addr + j * 8, i); + set_hash_addr(leaf_addr + j * 8, 0); + set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTSPRF); + } + prf_addrx8(buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + buffer + 2 * wots_offset, + buffer + 3 * wots_offset, + buffer + 4 * wots_offset, + buffer + 5 * wots_offset, + buffer + 6 * wots_offset, + buffer + 7 * wots_offset, + ctx, leaf_addr); + + for (j = 0; j < 8; j++) { + set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTS); + } + + /* Iterate down the WOTS chain */ + for (k = 0;; k++) { + /* Check if one of the values we have needs to be saved as a */ + /* part of the WOTS signature */ + if (k == wots_k) { + memcpy( info->wots_sig + i * SPX_N, + buffer + wots_sign_index * wots_offset, SPX_N ); + } + + /* Check if we hit the top of the chain */ + if (k == SPX_WOTS_W - 1) { + break; + } + + /* Iterate one step on all 8 chains */ + for (j = 0; j < 8; j++) { + set_hash_addr(leaf_addr + j * 8, k); + } + thashx8(buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + buffer + 2 * wots_offset, + buffer + 3 * wots_offset, + buffer + 4 * wots_offset, + buffer + 5 * wots_offset, + buffer + 6 * wots_offset, + buffer + 7 * wots_offset, + buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + buffer + 2 * wots_offset, + buffer + 3 * wots_offset, + buffer + 4 * wots_offset, + buffer + 5 * wots_offset, + buffer + 6 * wots_offset, + buffer + 7 * wots_offset, 1, ctx, leaf_addr); + } + } + + /* Do the final thash to generate the public keys */ + thashx8(dest + 0 * SPX_N, + dest + 1 * SPX_N, + dest + 2 * SPX_N, + dest + 3 * SPX_N, + dest + 4 * SPX_N, + dest + 5 * SPX_N, + dest + 6 * SPX_N, + dest + 7 * SPX_N, + pk_buffer + 0 * wots_offset, + pk_buffer + 1 * wots_offset, + pk_buffer + 2 * wots_offset, + pk_buffer + 3 * wots_offset, + pk_buffer + 4 * wots_offset, + pk_buffer + 5 * wots_offset, + pk_buffer + 6 * wots_offset, + pk_buffer + 7 * wots_offset, SPX_WOTS_LEN, ctx, pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/wots.h b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/wots.h new file mode 100644 index 0000000000..4e7692eeef --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/wots.h @@ -0,0 +1,25 @@ +#ifndef SPX_WOTS_H +#define SPX_WOTS_H + +#include + +#include "context.h" +#include "params.h" + +/** + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. + * + * Writes the computed public key to 'pk'. + */ +#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]); + +/* + * Compute the chain lengths needed for a given message hash + */ +#define chain_lengths SPX_NAMESPACE(chain_lengths) +void chain_lengths(unsigned int *lengths, const unsigned char *msg); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/wotsx8.h b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/wotsx8.h new file mode 100644 index 0000000000..10866efb35 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/wotsx8.h @@ -0,0 +1,42 @@ +#ifndef WOTSX8_H_ +#define WOTSX8_H_ + +#include + +#include "context.h" +#include "params.h" + +/* + * This is here to provide an interface to the internal wots_gen_leafx8 + * routine. While this routine is not referenced in the package outside of + * wots.c, it is called from the stand-alone benchmark code to characterize + * the performance + */ +struct leaf_info_x8 { + unsigned char *wots_sig; + uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ + uint32_t *wots_steps; + uint32_t leaf_addr[8 * 8]; + uint32_t pk_addr[8 * 8]; +}; + +/* Macro to set the leaf_info to something 'benign', that is, it would */ +/* run with the same time as it does during the real signing process */ +/* Used only by the benchmark code */ +#define INITIALIZE_LEAF_INFO_X8(info, addr, step_buffer) { \ + (info).wots_sig = 0; \ + (info).wots_sign_leaf = ~0; \ + (info).wots_steps = step_buffer; \ + int i; \ + for (i=0; i<8; i++) { \ + memcpy( &(info).leaf_addr[8*i], addr, 32 ); \ + memcpy( &(info).pk_addr[8*i], addr, 32 ); \ + } \ + } + +#define wots_gen_leafx8 SPX_NAMESPACE(wots_gen_leafx8) +void wots_gen_leafx8(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info); + +#endif /* WOTSX8_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/LICENSE b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/LICENSE new file mode 100644 index 0000000000..670154e353 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/LICENSE @@ -0,0 +1,116 @@ +CC0 1.0 Universal + +Statement of Purpose + +The laws of most jurisdictions throughout the world automatically confer +exclusive Copyright and Related Rights (defined below) upon the creator and +subsequent owner(s) (each and all, an "owner") of an original work of +authorship and/or a database (each, a "Work"). + +Certain owners wish to permanently relinquish those rights to a Work for the +purpose of contributing to a commons of creative, cultural and scientific +works ("Commons") that the public can reliably and without fear of later +claims of infringement build upon, modify, incorporate in other works, reuse +and redistribute as freely as possible in any form whatsoever and for any +purposes, including without limitation commercial purposes. These owners may +contribute to the Commons to promote the ideal of a free culture and the +further production of creative, cultural and scientific works, or to gain +reputation or greater distribution for their Work in part through the use and +efforts of others. + +For these and/or other purposes and motivations, and without any expectation +of additional consideration or compensation, the person associating CC0 with a +Work (the "Affirmer"), to the extent that he or she is an owner of Copyright +and Related Rights in the Work, voluntarily elects to apply CC0 to the Work +and publicly distribute the Work under its terms, with knowledge of his or her +Copyright and Related Rights in the Work and the meaning and intended legal +effect of CC0 on those rights. + +1. Copyright and Related Rights. A Work made available under CC0 may be +protected by copyright and related or neighboring rights ("Copyright and +Related Rights"). Copyright and Related Rights include, but are not limited +to, the following: + + i. the right to reproduce, adapt, distribute, perform, display, communicate, + and translate a Work; + + ii. moral rights retained by the original author(s) and/or performer(s); + + iii. publicity and privacy rights pertaining to a person's image or likeness + depicted in a Work; + + iv. rights protecting against unfair competition in regards to a Work, + subject to the limitations in paragraph 4(a), below; + + v. rights protecting the extraction, dissemination, use and reuse of data in + a Work; + + vi. database rights (such as those arising under Directive 96/9/EC of the + European Parliament and of the Council of 11 March 1996 on the legal + protection of databases, and under any national implementation thereof, + including any amended or successor version of such directive); and + + vii. other similar, equivalent or corresponding rights throughout the world + based on applicable law or treaty, and any national implementations thereof. + +2. Waiver. To the greatest extent permitted by, but not in contravention of, +applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and +unconditionally waives, abandons, and surrenders all of Affirmer's Copyright +and Related Rights and associated claims and causes of action, whether now +known or unknown (including existing as well as future claims and causes of +action), in the Work (i) in all territories worldwide, (ii) for the maximum +duration provided by applicable law or treaty (including future time +extensions), (iii) in any current or future medium and for any number of +copies, and (iv) for any purpose whatsoever, including without limitation +commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes +the Waiver for the benefit of each member of the public at large and to the +detriment of Affirmer's heirs and successors, fully intending that such Waiver +shall not be subject to revocation, rescission, cancellation, termination, or +any other legal or equitable action to disrupt the quiet enjoyment of the Work +by the public as contemplated by Affirmer's express Statement of Purpose. + +3. Public License Fallback. Should any part of the Waiver for any reason be +judged legally invalid or ineffective under applicable law, then the Waiver +shall be preserved to the maximum extent permitted taking into account +Affirmer's express Statement of Purpose. In addition, to the extent the Waiver +is so judged Affirmer hereby grants to each affected person a royalty-free, +non transferable, non sublicensable, non exclusive, irrevocable and +unconditional license to exercise Affirmer's Copyright and Related Rights in +the Work (i) in all territories worldwide, (ii) for the maximum duration +provided by applicable law or treaty (including future time extensions), (iii) +in any current or future medium and for any number of copies, and (iv) for any +purpose whatsoever, including without limitation commercial, advertising or +promotional purposes (the "License"). The License shall be deemed effective as +of the date CC0 was applied by Affirmer to the Work. Should any part of the +License for any reason be judged legally invalid or ineffective under +applicable law, such partial invalidity or ineffectiveness shall not +invalidate the remainder of the License, and in such case Affirmer hereby +affirms that he or she will not (i) exercise any of his or her remaining +Copyright and Related Rights in the Work or (ii) assert any associated claims +and causes of action with respect to the Work, in either case contrary to +Affirmer's express Statement of Purpose. + +4. Limitations and Disclaimers. + + a. No trademark or patent rights held by Affirmer are waived, abandoned, + surrendered, licensed or otherwise affected by this document. + + b. Affirmer offers the Work as-is and makes no representations or warranties + of any kind concerning the Work, express, implied, statutory or otherwise, + including without limitation warranties of title, merchantability, fitness + for a particular purpose, non infringement, or the absence of latent or + other defects, accuracy, or the present or absence of errors, whether or not + discoverable, all to the greatest extent permissible under applicable law. + + c. Affirmer disclaims responsibility for clearing rights of other persons + that may apply to the Work or any use thereof, including without limitation + any person's Copyright and Related Rights in the Work. Further, Affirmer + disclaims responsibility for obtaining any necessary consents, permissions + or other rights required for any use of the Work. + + d. Affirmer understands and acknowledges that Creative Commons is not a + party to this document and has no duty or obligation with respect to this + CC0 or use of the Work. + +For more information, please see + diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/address.c b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/address.c new file mode 100644 index 0000000000..b956e9cb29 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/address.c @@ -0,0 +1,91 @@ +#include +#include + +#include "address.h" +#include "params.h" +#include "utils.h" + +/* + * Specify which level of Merkle tree (the "layer") we're working on + */ +void set_layer_addr(uint32_t addr[8], uint32_t layer) { + ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; +} + +/* + * Specify which Merkle tree within the level (the "tree address") we're working on + */ +void set_tree_addr(uint32_t addr[8], uint64_t tree) { + ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); +} + +/* + * Specify the reason we'll use this address structure for, that is, what + * hash will we compute with it. This is used so that unrelated types of + * hashes don't accidentally get the same address structure. The type will be + * one of the SPX_ADDR_TYPE constants + */ +void set_type(uint32_t addr[8], uint32_t type) { + ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; +} + +/* + * Copy the layer and tree fields of the address structure. This is used + * when we're doing multiple types of hashes within the same Merkle tree + */ +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); +} + +/* These functions are used for OTS addresses. */ + +/* + * Specify which Merkle leaf we're working on; that is, which OTS keypair + * we're talking about. + */ +void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { + ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; +} + +/* + * Copy the layer, tree and keypair fields of the address structure. This is + * used when we're doing multiple things within the same OTS keypair + */ +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); + ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; +} + +/* + * Specify which Merkle chain within the OTS we're working with + * (the chain address) + */ +void set_chain_addr(uint32_t addr[8], uint32_t chain) { + ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; +} + +/* + * Specify where in the Merkle chain we are +* (the hash address) + */ +void set_hash_addr(uint32_t addr[8], uint32_t hash) { + ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; +} + +/* These functions are used for all hash tree addresses (including FORS). */ + +/* + * Specify the height of the node in the Merkle/FORS tree we are in + * (the tree height) + */ +void set_tree_height(uint32_t addr[8], uint32_t tree_height) { + ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; +} + +/* + * Specify the distance from the left edge of the node in the Merkle/FORS tree + * (the tree index) + */ +void set_tree_index(uint32_t addr[8], uint32_t tree_index) { + u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/address.h b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/address.h new file mode 100644 index 0000000000..24a84eb40c --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/address.h @@ -0,0 +1,52 @@ +#ifndef SPX_ADDRESS_H +#define SPX_ADDRESS_H + +#include + +#include "params.h" + +/* The hash types that are passed to set_type */ +#define SPX_ADDR_TYPE_WOTS 0 +#define SPX_ADDR_TYPE_WOTSPK 1 +#define SPX_ADDR_TYPE_HASHTREE 2 +#define SPX_ADDR_TYPE_FORSTREE 3 +#define SPX_ADDR_TYPE_FORSPK 4 +#define SPX_ADDR_TYPE_WOTSPRF 5 +#define SPX_ADDR_TYPE_FORSPRF 6 + +#define set_layer_addr SPX_NAMESPACE(set_layer_addr) +void set_layer_addr(uint32_t addr[8], uint32_t layer); + +#define set_tree_addr SPX_NAMESPACE(set_tree_addr) +void set_tree_addr(uint32_t addr[8], uint64_t tree); + +#define set_type SPX_NAMESPACE(set_type) +void set_type(uint32_t addr[8], uint32_t type); + +/* Copies the layer and tree part of one address into the other */ +#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); + +/* These functions are used for WOTS and FORS addresses. */ + +#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) +void set_keypair_addr(uint32_t addr[8], uint32_t keypair); + +#define set_chain_addr SPX_NAMESPACE(set_chain_addr) +void set_chain_addr(uint32_t addr[8], uint32_t chain); + +#define set_hash_addr SPX_NAMESPACE(set_hash_addr) +void set_hash_addr(uint32_t addr[8], uint32_t hash); + +#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); + +/* These functions are used for all hash tree addresses (including FORS). */ + +#define set_tree_height SPX_NAMESPACE(set_tree_height) +void set_tree_height(uint32_t addr[8], uint32_t tree_height); + +#define set_tree_index SPX_NAMESPACE(set_tree_index) +void set_tree_index(uint32_t addr[8], uint32_t tree_index); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/api.h b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/api.h new file mode 100644 index 0000000000..24875d652c --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/api.h @@ -0,0 +1,77 @@ +#ifndef PQCLEAN_SPHINCSSHA2192FROBUST_CLEAN_API_H +#define PQCLEAN_SPHINCSSHA2192FROBUST_CLEAN_API_H + +#include +#include + +#define PQCLEAN_SPHINCSSHA2192FROBUST_CLEAN_CRYPTO_ALGNAME "SPHINCS+-sha2-192f-robust" + +#define PQCLEAN_SPHINCSSHA2192FROBUST_CLEAN_CRYPTO_SECRETKEYBYTES 96 +#define PQCLEAN_SPHINCSSHA2192FROBUST_CLEAN_CRYPTO_PUBLICKEYBYTES 48 +#define PQCLEAN_SPHINCSSHA2192FROBUST_CLEAN_CRYPTO_BYTES 35664 + +#define PQCLEAN_SPHINCSSHA2192FROBUST_CLEAN_CRYPTO_SEEDBYTES 72 + +/* + * Returns the length of a secret key, in bytes + */ +size_t PQCLEAN_SPHINCSSHA2192FROBUST_CLEAN_crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +size_t PQCLEAN_SPHINCSSHA2192FROBUST_CLEAN_crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +size_t PQCLEAN_SPHINCSSHA2192FROBUST_CLEAN_crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +size_t PQCLEAN_SPHINCSSHA2192FROBUST_CLEAN_crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +int PQCLEAN_SPHINCSSHA2192FROBUST_CLEAN_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +int PQCLEAN_SPHINCSSHA2192FROBUST_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +int PQCLEAN_SPHINCSSHA2192FROBUST_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +int PQCLEAN_SPHINCSSHA2192FROBUST_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, + const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +int PQCLEAN_SPHINCSSHA2192FROBUST_CLEAN_crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +int PQCLEAN_SPHINCSSHA2192FROBUST_CLEAN_crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/context.h b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/context.h new file mode 100644 index 0000000000..97e2e2469e --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/context.h @@ -0,0 +1,28 @@ +#ifndef SPX_CONTEXT_H +#define SPX_CONTEXT_H + +#include +#include + +#include "params.h" +#include "sha2.h" + +typedef struct { + uint8_t pub_seed[SPX_N]; + uint8_t sk_seed[SPX_N]; + + // sha256 state that absorbed pub_seed + sha256ctx state_seeded; + + // sha512 state that absorbed pub_seed + sha512ctx state_seeded_512; + +} spx_ctx; + +#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) +void initialize_hash_function(spx_ctx *ctx); + +#define free_hash_function SPX_NAMESPACE(free_hash_function) +void free_hash_function(spx_ctx *ctx); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/context_sha2.c b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/context_sha2.c new file mode 100644 index 0000000000..9ca9f4e7ac --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/context_sha2.c @@ -0,0 +1,36 @@ +#include "context.h" + +/** + * Absorb the constant pub_seed using one round of the compression function + * This initializes state_seeded and state_seeded_512, which can then be + * reused in thash + **/ +static void seed_state(spx_ctx *ctx) { + uint8_t block[SPX_SHA512_BLOCK_BYTES]; + size_t i; + + for (i = 0; i < SPX_N; ++i) { + block[i] = ctx->pub_seed[i]; + } + for (i = SPX_N; i < SPX_SHA512_BLOCK_BYTES; ++i) { + block[i] = 0; + } + /* block has been properly initialized for both SHA-256 and SHA-512 */ + + sha256_inc_init(&ctx->state_seeded); + sha256_inc_blocks(&ctx->state_seeded, block, 1); + sha512_inc_init(&ctx->state_seeded_512); + sha512_inc_blocks(&ctx->state_seeded_512, block, 1); +} + + +/* We initialize the state for the hash functions */ +void initialize_hash_function(spx_ctx *ctx) { + seed_state(ctx); +} + +/* Free the incremental hashing context for heap-based SHA2 APIs */ +void free_hash_function(spx_ctx *ctx) { + sha256_inc_ctx_release(&ctx->state_seeded); + sha512_inc_ctx_release(&ctx->state_seeded_512); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/fors.c b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/fors.c new file mode 100644 index 0000000000..96ca72e986 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/fors.c @@ -0,0 +1,156 @@ +#include +#include +#include + +#include "fors.h" + +#include "address.h" +#include "hash.h" +#include "thash.h" +#include "utils.h" +#include "utilsx1.h" + +static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + prf_addr(sk, ctx, fors_leaf_addr); +} + +static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, + const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + thash(leaf, sk, 1, ctx, fors_leaf_addr); +} + +struct fors_gen_leaf_info { + uint32_t leaf_addrx[8]; +}; + +static void fors_gen_leafx1(unsigned char *leaf, + const spx_ctx *ctx, + uint32_t addr_idx, void *info) { + struct fors_gen_leaf_info *fors_info = info; + uint32_t *fors_leaf_addr = fors_info->leaf_addrx; + + /* Only set the parts that the caller doesn't set */ + set_tree_index(fors_leaf_addr, addr_idx); + set_type(fors_leaf_addr, SPX_ADDR_TYPE_FORSPRF); + fors_gen_sk(leaf, ctx, fors_leaf_addr); + + set_type(fors_leaf_addr, SPX_ADDR_TYPE_FORSTREE); + fors_sk_to_leaf(leaf, leaf, + ctx, fors_leaf_addr); +} + +/** + * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + * Assumes indices has space for SPX_FORS_TREES integers. + */ +static void message_to_indices(uint32_t *indices, const unsigned char *m) { + unsigned int i, j; + unsigned int offset = 0; + + for (i = 0; i < SPX_FORS_TREES; i++) { + indices[i] = 0; + for (j = 0; j < SPX_FORS_HEIGHT; j++) { + indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); + offset++; + } + } +} + +/** + * Signs a message m, deriving the secret key from sk_seed and the FTS address. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + uint32_t fors_tree_addr[8] = {0}; + struct fors_gen_leaf_info fors_info = {0}; + uint32_t *fors_leaf_addr = fors_info.leaf_addrx; + uint32_t fors_pk_addr[8] = {0}; + uint32_t idx_offset; + unsigned int i; + + copy_keypair_addr(fors_tree_addr, fors_addr); + copy_keypair_addr(fors_leaf_addr, fors_addr); + + copy_keypair_addr(fors_pk_addr, fors_addr); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); + + message_to_indices(indices, m); + + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); + + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); + + /* Include the secret key part that produces the selected leaf node. */ + fors_gen_sk(sig, ctx, fors_tree_addr); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + sig += SPX_N; + + /* Compute the authentication path for this leaf node. */ + treehashx1(roots + i * SPX_N, sig, ctx, + indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx1, + fors_tree_addr, &fors_info); + + sig += SPX_N * SPX_FORS_HEIGHT; + } + + /* Hash horizontally across all tree roots to derive the public key. */ + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); +} + +/** + * Derives the FORS public key from a signature. + * This can be used for verification by comparing to a known public key, or to + * subsequently verify a signature on the derived public key. The latter is the + * typical use-case when used as an FTS below an OTS in a hypertree. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + unsigned char leaf[SPX_N]; + uint32_t fors_tree_addr[8] = {0}; + uint32_t fors_pk_addr[8] = {0}; + uint32_t idx_offset; + unsigned int i; + + copy_keypair_addr(fors_tree_addr, fors_addr); + copy_keypair_addr(fors_pk_addr, fors_addr); + + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); + + message_to_indices(indices, m); + + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); + + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + + /* Derive the leaf from the included secret key part. */ + fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); + sig += SPX_N; + + /* Derive the corresponding root node of this tree. */ + compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, + sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); + sig += SPX_N * SPX_FORS_HEIGHT; + } + + /* Hash horizontally across all tree roots to derive the public key. */ + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/fors.h b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/fors.h new file mode 100644 index 0000000000..509140a178 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/fors.h @@ -0,0 +1,32 @@ +#ifndef SPX_FORS_H +#define SPX_FORS_H + +#include + +#include "context.h" +#include "params.h" + +/** + * Signs a message m, deriving the secret key from sk_seed and the FTS address. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +#define fors_sign SPX_NAMESPACE(fors_sign) +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); + +/** + * Derives the FORS public key from a signature. + * This can be used for verification by comparing to a known public key, or to + * subsequently verify a signature on the derived public key. The latter is the + * typical use-case when used as an FTS below an OTS in a hypertree. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/hash.h b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/hash.h new file mode 100644 index 0000000000..ffe815f45d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/hash.h @@ -0,0 +1,37 @@ +#ifndef SPX_HASH_H +#define SPX_HASH_H + +#include +#include + +#include "context.h" +#include "params.h" + +#define prf_addr SPX_NAMESPACE(prf_addr) +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]); + +#define gen_message_random SPX_NAMESPACE(gen_message_random) +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); + +#define hash_message SPX_NAMESPACE(hash_message) +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); + + +# define SPX_SHA256_ADDR_BYTES 22 + +# define mgf1_256 SPX_NAMESPACE(mgf1_256) +void mgf1_256(unsigned char *out, unsigned long outlen, + const unsigned char *in, unsigned long inlen); + +# define mgf1_512 SPX_NAMESPACE(mgf1_512) +void mgf1_512(unsigned char *out, unsigned long outlen, + const unsigned char *in, unsigned long inlen); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/hash_sha2.c b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/hash_sha2.c new file mode 100644 index 0000000000..3d0085c8c1 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/hash_sha2.c @@ -0,0 +1,219 @@ +#include +#include + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "sha2.h" +#include "utils.h" + + + +#define SPX_SHAX_OUTPUT_BYTES SPX_SHA512_OUTPUT_BYTES +#define SPX_SHAX_BLOCK_BYTES SPX_SHA512_BLOCK_BYTES +#define shaX_inc_init sha512_inc_init +#define shaX_inc_blocks sha512_inc_blocks +#define shaX_inc_finalize sha512_inc_finalize +#define shaX sha512 +#define mgf1_X mgf1_512 +#define shaXstate sha512ctx + +/** + * mgf1 function based on the SHA-256 hash function + * Note that inlen should be sufficiently small that it still allows for + * an array to be allocated on the stack. Typically 'in' is merely a seed. + * Outputs outlen number of bytes + */ +void mgf1_256(unsigned char *out, unsigned long outlen, + const unsigned char *in, unsigned long inlen) { + PQCLEAN_VLA(uint8_t, inbuf, inlen + 4); + unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES]; + uint32_t i; + + memcpy(inbuf, in, inlen); + + /* While we can fit in at least another full block of SHA256 output.. */ + for (i = 0; (i + 1)*SPX_SHA256_OUTPUT_BYTES <= outlen; i++) { + u32_to_bytes(inbuf + inlen, i); + sha256(out, inbuf, inlen + 4); + out += SPX_SHA256_OUTPUT_BYTES; + } + /* Until we cannot anymore, and we fill the remainder. */ + if (outlen > i * SPX_SHA256_OUTPUT_BYTES) { + u32_to_bytes(inbuf + inlen, i); + sha256(outbuf, inbuf, inlen + 4); + memcpy(out, outbuf, outlen - i * SPX_SHA256_OUTPUT_BYTES); + } +} + +/* + * mgf1 function based on the SHA-512 hash function + */ +void mgf1_512(unsigned char *out, unsigned long outlen, + const unsigned char *in, unsigned long inlen) { + PQCLEAN_VLA(uint8_t, inbuf, inlen + 4); + unsigned char outbuf[SPX_SHA512_OUTPUT_BYTES]; + uint32_t i; + + memcpy(inbuf, in, inlen); + + /* While we can fit in at least another full block of SHA512 output.. */ + for (i = 0; (i + 1)*SPX_SHA512_OUTPUT_BYTES <= outlen; i++) { + u32_to_bytes(inbuf + inlen, i); + sha512(out, inbuf, inlen + 4); + out += SPX_SHA512_OUTPUT_BYTES; + } + /* Until we cannot anymore, and we fill the remainder. */ + if (outlen > i * SPX_SHA512_OUTPUT_BYTES) { + u32_to_bytes(inbuf + inlen, i); + sha512(outbuf, inbuf, inlen + 4); + memcpy(out, outbuf, outlen - i * SPX_SHA512_OUTPUT_BYTES); + } +} + +/* + * Computes PRF(pk_seed, sk_seed, addr). + */ +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]) { + sha256ctx sha2_state; + unsigned char buf[SPX_SHA256_ADDR_BYTES + SPX_N]; + unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES]; + + /* Retrieve precomputed state containing pub_seed */ + sha256_inc_ctx_clone(&sha2_state, &ctx->state_seeded); + + /* Remainder: ADDR^c ‖ SK.seed */ + memcpy(buf, addr, SPX_SHA256_ADDR_BYTES); + memcpy(buf + SPX_SHA256_ADDR_BYTES, ctx->sk_seed, SPX_N); + + sha256_inc_finalize(outbuf, &sha2_state, buf, SPX_SHA256_ADDR_BYTES + SPX_N); + + memcpy(out, outbuf, SPX_N); +} + +/** + * Computes the message-dependent randomness R, using a secret seed as a key + * for HMAC, and an optional randomization value prefixed to the message. + * This requires m to have at least SPX_SHAX_BLOCK_BYTES + SPX_N space + * available in front of the pointer, i.e. before the message to use for the + * prefix. This is necessary to prevent having to move the message around (and + * allocate memory for it). + */ +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { + (void)ctx; + + unsigned char buf[SPX_SHAX_BLOCK_BYTES + SPX_SHAX_OUTPUT_BYTES]; + shaXstate state; + int i; + + + /* This implements HMAC-SHA */ + for (i = 0; i < SPX_N; i++) { + buf[i] = 0x36 ^ sk_prf[i]; + } + memset(buf + SPX_N, 0x36, SPX_SHAX_BLOCK_BYTES - SPX_N); + + shaX_inc_init(&state); + shaX_inc_blocks(&state, buf, 1); + + memcpy(buf, optrand, SPX_N); + + /* If optrand + message cannot fill up an entire block */ + if (SPX_N + mlen < SPX_SHAX_BLOCK_BYTES) { + memcpy(buf + SPX_N, m, mlen); + shaX_inc_finalize(buf + SPX_SHAX_BLOCK_BYTES, &state, + buf, mlen + SPX_N); + } + /* Otherwise first fill a block, so that finalize only uses the message */ + else { + memcpy(buf + SPX_N, m, SPX_SHAX_BLOCK_BYTES - SPX_N); + shaX_inc_blocks(&state, buf, 1); + + m += SPX_SHAX_BLOCK_BYTES - SPX_N; + mlen -= SPX_SHAX_BLOCK_BYTES - SPX_N; + shaX_inc_finalize(buf + SPX_SHAX_BLOCK_BYTES, &state, m, mlen); + } + + for (i = 0; i < SPX_N; i++) { + buf[i] = 0x5c ^ sk_prf[i]; + } + memset(buf + SPX_N, 0x5c, SPX_SHAX_BLOCK_BYTES - SPX_N); + + shaX(buf, buf, SPX_SHAX_BLOCK_BYTES + SPX_SHAX_OUTPUT_BYTES); + memcpy(R, buf, SPX_N); +} + +/** + * Computes the message hash using R, the public key, and the message. + * Outputs the message digest and the index of the leaf. The index is split in + * the tree index and the leaf index, for convenient copying to an address. + */ +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { + (void)ctx; +#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) +#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) +#define SPX_LEAF_BITS SPX_TREE_HEIGHT +#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) +#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) + + unsigned char seed[2 * SPX_N + SPX_SHAX_OUTPUT_BYTES]; + + /* Round to nearest multiple of SPX_SHAX_BLOCK_BYTES */ +#define SPX_INBLOCKS (((SPX_N + SPX_PK_BYTES + SPX_SHAX_BLOCK_BYTES - 1) & \ + -SPX_SHAX_BLOCK_BYTES) / SPX_SHAX_BLOCK_BYTES) + unsigned char inbuf[SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES]; + + unsigned char buf[SPX_DGST_BYTES]; + unsigned char *bufp = buf; + shaXstate state; + + shaX_inc_init(&state); + + // seed: SHA-X(R ‖ PK.seed ‖ PK.root ‖ M) + memcpy(inbuf, R, SPX_N); + memcpy(inbuf + SPX_N, pk, SPX_PK_BYTES); + + /* If R + pk + message cannot fill up an entire block */ + if (SPX_N + SPX_PK_BYTES + mlen < SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES) { + memcpy(inbuf + SPX_N + SPX_PK_BYTES, m, mlen); + shaX_inc_finalize(seed + 2 * SPX_N, &state, inbuf, SPX_N + SPX_PK_BYTES + mlen); + } + /* Otherwise first fill a block, so that finalize only uses the message */ + else { + memcpy(inbuf + SPX_N + SPX_PK_BYTES, m, + SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES - SPX_N - SPX_PK_BYTES); + shaX_inc_blocks(&state, inbuf, SPX_INBLOCKS); + + m += SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES - SPX_N - SPX_PK_BYTES; + mlen -= SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES - SPX_N - SPX_PK_BYTES; + shaX_inc_finalize(seed + 2 * SPX_N, &state, m, (size_t)mlen); + } + + // H_msg: MGF1-SHA-X(R ‖ PK.seed ‖ seed) + memcpy(seed, R, SPX_N); + memcpy(seed + SPX_N, pk, SPX_N); + + /* By doing this in two steps, we prevent hashing the message twice; + otherwise each iteration in MGF1 would hash the message again. */ + mgf1_X(bufp, SPX_DGST_BYTES, seed, 2 * SPX_N + SPX_SHAX_OUTPUT_BYTES); + + memcpy(digest, bufp, SPX_FORS_MSG_BYTES); + bufp += SPX_FORS_MSG_BYTES; + + + *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); + *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); + bufp += SPX_TREE_BYTES; + + *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); + *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); +} + + diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/merkle.c b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/merkle.c new file mode 100644 index 0000000000..0c1479fd93 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/merkle.c @@ -0,0 +1,59 @@ +#include +#include + +#include "address.h" +#include "merkle.h" +#include "params.h" +#include "utils.h" +#include "utilsx1.h" +#include "wots.h" +#include "wotsx1.h" + +/* + * This generates a Merkle signature (WOTS signature followed by the Merkle + * authentication path). This is in this file because most of the complexity + * is involved with the WOTS signature; the Merkle authentication path logic + * is mostly hidden in treehashx4 + */ +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf) { + unsigned char *auth_path = sig + SPX_WOTS_BYTES; + struct leaf_info_x1 info = { 0 }; + unsigned steps[ SPX_WOTS_LEN ]; + + info.wots_sig = sig; + chain_lengths(steps, root); + info.wots_steps = steps; + + set_type(&tree_addr[0], SPX_ADDR_TYPE_HASHTREE); + set_type(&info.pk_addr[0], SPX_ADDR_TYPE_WOTSPK); + copy_subtree_addr(&info.leaf_addr[0], wots_addr); + copy_subtree_addr(&info.pk_addr[0], wots_addr); + + info.wots_sign_leaf = idx_leaf; + + treehashx1(root, auth_path, ctx, + idx_leaf, 0, + SPX_TREE_HEIGHT, + wots_gen_leafx1, + tree_addr, &info); +} + +/* Compute root node of the top-most subtree. */ +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { + /* We do not need the auth path in key generation, but it simplifies the + code to have just one treehash routine that computes both root and path + in one function. */ + unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; + uint32_t top_tree_addr[8] = {0}; + uint32_t wots_addr[8] = {0}; + + set_layer_addr(top_tree_addr, SPX_D - 1); + set_layer_addr(wots_addr, SPX_D - 1); + + merkle_sign(auth_path, root, ctx, + wots_addr, top_tree_addr, + (uint32_t)~0 /* ~0 means "don't bother generating an auth path */ ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/merkle.h b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/merkle.h new file mode 100644 index 0000000000..769cf2e970 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/merkle.h @@ -0,0 +1,21 @@ +#ifndef MERKLE_H_ +#define MERKLE_H_ + +#include + +#include "context.h" +#include "params.h" + +/* Generate a Merkle signature (WOTS signature followed by the Merkle */ +/* authentication path) */ +#define merkle_sign SPX_NAMESPACE(merkle_sign) +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf); + +/* Compute the root node of the top-most subtree. */ +#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); + +#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/nistapi.h b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/nistapi.h new file mode 100644 index 0000000000..3cb71afad4 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/nistapi.h @@ -0,0 +1,87 @@ +#ifndef SPX_API_H +#define SPX_API_H + +#include +#include + +#include "params.h" + +#define CRYPTO_ALGNAME "SPHINCS+" + +#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES +#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES +#define CRYPTO_BYTES SPX_BYTES +#define CRYPTO_SEEDBYTES (3*SPX_N) + +/* + * Returns the length of a secret key, in bytes + */ +#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) +size_t crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) +size_t crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) +size_t crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) +size_t crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +#define crypto_sign SPX_NAMESPACE(crypto_sign) +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/params.h b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/params.h new file mode 100644 index 0000000000..23704bcd52 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/params.h @@ -0,0 +1,61 @@ +#ifndef SPX_PARAMS_H +#define SPX_PARAMS_H + +#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSSHA2192FROBUST_CLEAN_##s + +/* Hash output length in bytes. */ +#define SPX_N 24 +/* Height of the hypertree. */ +#define SPX_FULL_HEIGHT 66 +/* Number of subtree layer. */ +#define SPX_D 22 +/* FORS tree dimensions. */ +#define SPX_FORS_HEIGHT 8 +#define SPX_FORS_TREES 33 +/* Winternitz parameter, */ +#define SPX_WOTS_W 16 + +/* The hash function is defined by linking a different hash.c file, as opposed + to setting a #define constant. */ + +/* This is a SHA2-based parameter set, hence whether we use SHA-256 + * exclusively or we use both SHA-256 and SHA-512 is controlled by + * the following #define */ +#define SPX_SHA512 1 /* Use SHA-512 for H and T_l, l >= 2 */ + +/* For clarity */ +#define SPX_ADDR_BYTES 32 + +/* WOTS parameters. */ +#define SPX_WOTS_LOGW 4 + +#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) + +/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ +#define SPX_WOTS_LEN2 3 + +#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) +#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) +#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES + +/* Subtree size. */ +#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) + +//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT +// #error SPX_D should always divide SPX_FULL_HEIGHT +//#endif + +/* FORS parameters. */ +#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) +#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) +#define SPX_FORS_PK_BYTES SPX_N + +/* Resulting SPX sizes. */ +#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ + SPX_FULL_HEIGHT * SPX_N) +#define SPX_PK_BYTES (2 * SPX_N) +#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) + +#include "sha2_offsets.h" + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/sha2_offsets.h b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/sha2_offsets.h new file mode 100644 index 0000000000..6e3584f7a4 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/sha2_offsets.h @@ -0,0 +1,27 @@ +#ifndef SHA2_OFFSETS_H_ +#define SHA2_OFFSETS_H_ + +#define SPX_SHA256_BLOCK_BYTES 64 +#define SPX_SHA256_OUTPUT_BYTES 32 + +#define SPX_SHA512_BLOCK_BYTES 128 +#define SPX_SHA512_OUTPUT_BYTES 64 + +/* + * Offsets of various fields in the address structure when we use SHA2 as + * the Sphincs+ hash function + */ + +#define SPX_OFFSET_LAYER 0 /* The byte used to specify the Merkle tree layer */ +#define SPX_OFFSET_TREE 1 /* The start of the 8 byte field used to specify the tree */ +#define SPX_OFFSET_TYPE 9 /* The byte used to specify the hash type (reason) */ +#define SPX_OFFSET_KP_ADDR2 12 /* The high byte used to specify the key pair (which one-time signature) */ +#define SPX_OFFSET_KP_ADDR1 13 /* The low byte used to specify the key pair */ +#define SPX_OFFSET_CHAIN_ADDR 17 /* The byte used to specify the chain address (which Winternitz chain) */ +#define SPX_OFFSET_HASH_ADDR 21 /* The byte used to specify the hash address (where in the Winternitz chain) */ +#define SPX_OFFSET_TREE_HGT 17 /* The byte used to specify the height of this node in the FORS or Merkle tree */ +#define SPX_OFFSET_TREE_INDEX 18 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ + +#define SPX_SHA2 1 + +#endif /* SHA2_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/sign.c b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/sign.c new file mode 100644 index 0000000000..9d0c7d1b22 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/sign.c @@ -0,0 +1,286 @@ +#include +#include +#include + +#include "address.h" +#include "context.h" +#include "fors.h" +#include "hash.h" +#include "merkle.h" +#include "nistapi.h" +#include "params.h" +#include "randombytes.h" +#include "thash.h" +#include "utils.h" +#include "wots.h" + +/* + * Returns the length of a secret key, in bytes + */ +size_t crypto_sign_secretkeybytes(void) { + return CRYPTO_SECRETKEYBYTES; +} + +/* + * Returns the length of a public key, in bytes + */ +size_t crypto_sign_publickeybytes(void) { + return CRYPTO_PUBLICKEYBYTES; +} + +/* + * Returns the length of a signature, in bytes + */ +size_t crypto_sign_bytes(void) { + return CRYPTO_BYTES; +} + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +size_t crypto_sign_seedbytes(void) { + return CRYPTO_SEEDBYTES; +} + +/* + * Generates an SPX key pair given a seed of length + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [PUB_SEED || root] + */ +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed) { + spx_ctx ctx; + + /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ + memcpy(sk, seed, CRYPTO_SEEDBYTES); + + memcpy(pk, sk + 2 * SPX_N, SPX_N); + + memcpy(ctx.pub_seed, pk, SPX_N); + memcpy(ctx.sk_seed, sk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + /* Compute root node of the top-most subtree. */ + merkle_gen_root(sk + 3 * SPX_N, &ctx); + + // cleanup + free_hash_function(&ctx); + + memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); + + return 0; +} + +/* + * Generates an SPX key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [PUB_SEED || root] + */ +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { + uint8_t seed[CRYPTO_SEEDBYTES]; + randombytes(seed, CRYPTO_SEEDBYTES); + crypto_sign_seed_keypair(pk, sk, seed); + + return 0; +} + +/** + * Returns an array containing a detached signature. + */ +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk) { + spx_ctx ctx; + + const uint8_t *sk_prf = sk + SPX_N; + const uint8_t *pk = sk + 2 * SPX_N; + + uint8_t optrand[SPX_N]; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t root[SPX_N]; + uint32_t i; + uint64_t tree; + uint32_t idx_leaf; + uint32_t wots_addr[8] = {0}; + uint32_t tree_addr[8] = {0}; + + memcpy(ctx.sk_seed, sk, SPX_N); + memcpy(ctx.pub_seed, pk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + + /* Optionally, signing can be made non-deterministic using optrand. + This can help counter side-channel attacks that would benefit from + getting a large number of traces when the signer uses the same nodes. */ + randombytes(optrand, SPX_N); + /* Compute the digest randomization value. */ + gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); + + /* Derive the message digest and leaf index from R, PK and M. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; + + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); + + /* Sign the message hash using FORS. */ + fors_sign(sig, root, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); + sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; + + /* Update the indices for the next layer. */ + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; + } + + free_hash_function(&ctx); + + *siglen = SPX_BYTES; + + return 0; +} + +/** + * Verifies a detached signature and message under a given public key. + */ +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk) { + spx_ctx ctx; + const uint8_t *pub_root = pk + SPX_N; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t wots_pk[SPX_WOTS_BYTES]; + uint8_t root[SPX_N]; + uint8_t leaf[SPX_N]; + unsigned int i; + uint64_t tree; + uint32_t idx_leaf; + uint32_t wots_addr[8] = {0}; + uint32_t tree_addr[8] = {0}; + uint32_t wots_pk_addr[8] = {0}; + + if (siglen != SPX_BYTES) { + return -1; + } + + memcpy(ctx.pub_seed, pk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); + + /* Derive the message digest and leaf index from R || PK || M. */ + /* The additional SPX_N is a result of the hash domain separator. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; + + /* Layer correctly defaults to 0, so no need to set_layer_addr */ + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); + + fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + /* For each subtree.. */ + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + copy_keypair_addr(wots_pk_addr, wots_addr); + + /* The WOTS public key is only correct if the signature was correct. */ + /* Initially, root is the FORS pk, but on subsequent iterations it is + the root of the subtree below the currently processed subtree. */ + wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); + sig += SPX_WOTS_BYTES; + + /* Compute the leaf node using the WOTS public key. */ + thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); + + /* Compute the root node of this subtree. */ + compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, + &ctx, tree_addr); + sig += SPX_TREE_HEIGHT * SPX_N; + + /* Update the indices for the next layer. */ + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; + } + + // cleanup + free_hash_function(&ctx); + + /* Check if the root node equals the root node in the public key. */ + if (memcmp(root, pub_root, SPX_N) != 0) { + return -1; + } + + return 0; +} + + +/** + * Returns an array containing the signature followed by the message. + */ +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk) { + size_t siglen; + + crypto_sign_signature(sm, &siglen, m, mlen, sk); + + memmove(sm + SPX_BYTES, m, mlen); + *smlen = siglen + mlen; + + return 0; +} + +/** + * Verifies a given signature-message pair under a given public key. + */ +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk) { + /* The API caller does not necessarily know what size a signature should be + but SPHINCS+ signatures are always exactly SPX_BYTES. */ + if (smlen < SPX_BYTES) { + memset(m, 0, smlen); + *mlen = 0; + return -1; + } + + *mlen = smlen - SPX_BYTES; + + if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { + memset(m, 0, smlen); + *mlen = 0; + return -1; + } + + /* If verification was successful, move the message to the right place. */ + memmove(m, sm + SPX_BYTES, *mlen); + + return 0; +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/thash.h b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/thash.h new file mode 100644 index 0000000000..8687ccfb4d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/thash.h @@ -0,0 +1,13 @@ +#ifndef SPX_THASH_H +#define SPX_THASH_H + +#include "context.h" +#include "params.h" + +#include + +#define thash SPX_NAMESPACE(thash) +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/thash_sha2_robust.c b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/thash_sha2_robust.c new file mode 100644 index 0000000000..3ab891175f --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/thash_sha2_robust.c @@ -0,0 +1,68 @@ +#include +#include + +#include "address.h" +#include "context.h" +#include "hash.h" +#include "params.h" +#include "sha2.h" +#include "thash.h" +#include "utils.h" + +static void thash_512(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]); + +/** + * Takes an array of inblocks concatenated arrays of SPX_N bytes. + */ +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]) { + if (inblocks > 1) { + thash_512(out, in, inblocks, ctx, addr); + return; + } + unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES]; + PQCLEAN_VLA(uint8_t, bitmask, inblocks * SPX_N); + PQCLEAN_VLA(uint8_t, buf, SPX_N + SPX_SHA256_OUTPUT_BYTES + inblocks * SPX_N); + sha256ctx sha2_state; + unsigned int i; + + memcpy(buf, ctx->pub_seed, SPX_N); + memcpy(buf + SPX_N, addr, SPX_SHA256_ADDR_BYTES); + mgf1_256(bitmask, inblocks * SPX_N, buf, SPX_N + SPX_SHA256_ADDR_BYTES); + + /* Retrieve precomputed state containing pub_seed */ + sha256_inc_ctx_clone(&sha2_state, &ctx->state_seeded); + + for (i = 0; i < inblocks * SPX_N; i++) { + buf[SPX_N + SPX_SHA256_ADDR_BYTES + i] = in[i] ^ bitmask[i]; + } + + sha256_inc_finalize(outbuf, &sha2_state, buf + SPX_N, + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N); + memcpy(out, outbuf, SPX_N); +} + +static void thash_512(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]) { + unsigned char outbuf[SPX_SHA512_OUTPUT_BYTES]; + PQCLEAN_VLA(uint8_t, bitmask, inblocks * SPX_N); + PQCLEAN_VLA(uint8_t, buf, SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N); + sha512ctx sha2_state; + unsigned int i; + + memcpy(buf, ctx->pub_seed, SPX_N); + memcpy(buf + SPX_N, addr, SPX_SHA256_ADDR_BYTES); + mgf1_512(bitmask, inblocks * SPX_N, buf, SPX_N + SPX_SHA256_ADDR_BYTES); + + /* Retrieve precomputed state containing pub_seed */ + sha512_inc_ctx_clone(&sha2_state, &ctx->state_seeded_512); + + for (i = 0; i < inblocks * SPX_N; i++) { + buf[SPX_N + SPX_SHA256_ADDR_BYTES + i] = in[i] ^ bitmask[i]; + } + + sha512_inc_finalize(outbuf, &sha2_state, buf + SPX_N, + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N); + memcpy(out, outbuf, SPX_N); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/utils.c b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/utils.c new file mode 100644 index 0000000000..177b541fb9 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/utils.c @@ -0,0 +1,148 @@ +#include + +#include "utils.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "thash.h" + +/** + * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. + */ +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in) { + int i; + + /* Iterate over out in decreasing order, for big-endianness. */ + for (i = (signed int)outlen - 1; i >= 0; i--) { + out[i] = in & 0xff; + in = in >> 8; + } +} + +void u32_to_bytes(unsigned char *out, uint32_t in) { + out[0] = (unsigned char)(in >> 24); + out[1] = (unsigned char)(in >> 16); + out[2] = (unsigned char)(in >> 8); + out[3] = (unsigned char)in; +} + +/** + * Converts the inlen bytes in 'in' from big-endian byte order to an integer. + */ +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { + unsigned long long retval = 0; + unsigned int i; + + for (i = 0; i < inlen; i++) { + retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); + } + return retval; +} + +/** + * Computes a root node given a leaf and an auth path. + * Expects address to be complete other than the tree_height and tree_index. + */ +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]) { + uint32_t i; + unsigned char buffer[2 * SPX_N]; + + /* If leaf_idx is odd (last bit = 1), current path element is a right child + and auth_path has to go left. Otherwise it is the other way around. */ + if (leaf_idx & 1) { + memcpy(buffer + SPX_N, leaf, SPX_N); + memcpy(buffer, auth_path, SPX_N); + } else { + memcpy(buffer, leaf, SPX_N); + memcpy(buffer + SPX_N, auth_path, SPX_N); + } + auth_path += SPX_N; + + for (i = 0; i < tree_height - 1; i++) { + leaf_idx >>= 1; + idx_offset >>= 1; + /* Set the address of the node we're creating. */ + set_tree_height(addr, i + 1); + set_tree_index(addr, leaf_idx + idx_offset); + + /* Pick the right or left neighbor, depending on parity of the node. */ + if (leaf_idx & 1) { + thash(buffer + SPX_N, buffer, 2, ctx, addr); + memcpy(buffer, auth_path, SPX_N); + } else { + thash(buffer, buffer, 2, ctx, addr); + memcpy(buffer + SPX_N, auth_path, SPX_N); + } + auth_path += SPX_N; + } + + /* The last iteration is exceptional; we do not copy an auth_path node. */ + leaf_idx >>= 1; + idx_offset >>= 1; + set_tree_height(addr, tree_height); + set_tree_index(addr, leaf_idx + idx_offset); + thash(root, buffer, 2, ctx, addr); +} + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx * /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]) { + PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); + PQCLEAN_VLA(unsigned int, heights, tree_height + 1); + unsigned int offset = 0; + uint32_t idx; + uint32_t tree_idx; + + for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { + /* Add the next leaf node to the stack. */ + gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); + offset++; + heights[offset - 1] = 0; + + /* If this is a node we need for the auth path.. */ + if ((leaf_idx ^ 0x1) == idx) { + memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); + } + + /* While the top-most nodes are of equal height.. */ + while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { + /* Compute index of the new node, in the next layer. */ + tree_idx = (idx >> (heights[offset - 1] + 1)); + + /* Set the address of the node we're creating. */ + set_tree_height(tree_addr, heights[offset - 1] + 1); + set_tree_index(tree_addr, + tree_idx + (idx_offset >> (heights[offset - 1] + 1))); + /* Hash the top-most nodes from the stack together. */ + thash(stack + (offset - 2)*SPX_N, + stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); + offset--; + /* Note that the top-most node is now one layer higher. */ + heights[offset - 1]++; + + /* If this is a node we need for the auth path.. */ + if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { + memcpy(auth_path + heights[offset - 1]*SPX_N, + stack + (offset - 1)*SPX_N, SPX_N); + } + } + } + memcpy(root, stack, SPX_N); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/utils.h b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/utils.h new file mode 100644 index 0000000000..64f5d5a53a --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/utils.h @@ -0,0 +1,58 @@ +#ifndef SPX_UTILS_H +#define SPX_UTILS_H + +#include + +#include "compat.h" +#include "context.h" +#include "params.h" + + +/* To support MSVC use alloca() instead of VLAs. See #20. */ + + +/** + * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. + */ +#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in); +#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) +void u32_to_bytes(unsigned char *out, uint32_t in); + +/** + * Converts the inlen bytes in 'in' from big-endian byte order to an integer. + */ +#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); + +/** + * Computes a root node given a leaf and an auth path. + * Expects address to be complete other than the tree_height and tree_index. + */ +#define compute_root SPX_NAMESPACE(compute_root) +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]); + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +#define treehash SPX_NAMESPACE(treehash) +void treehash(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx *ctx /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]); + + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/utilsx1.c b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/utilsx1.c new file mode 100644 index 0000000000..fccb69b35d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/utilsx1.c @@ -0,0 +1,100 @@ +#include + +#include "utilsx1.h" + +#include "address.h" +#include "params.h" +#include "thash.h" +#include "utils.h" + +/* + * Generate the entire Merkle tree, computing the authentication path for + * leaf_idx, and the resulting root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) + * + * This expects tree_addr to be initialized to the addr structures for the + * Merkle tree nodes + * + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + * + * This works by using the standard Merkle tree building algorithm, + */ +void treehashx1(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, + uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* Where to write the leaves */, + const spx_ctx * /* ctx */, + uint32_t idx, void *info), + uint32_t tree_addr[8], + void *info) { + /* This is where we keep the intermediate nodes */ + PQCLEAN_VLA(uint8_t, stack, tree_height * SPX_N); + + uint32_t idx; + uint32_t max_idx = (uint32_t)((1 << tree_height) - 1); + for (idx = 0;; idx++) { + unsigned char current[2 * SPX_N]; /* Current logical node is at */ + /* index[SPX_N]. We do this to minimize the number of copies */ + /* needed during a thash */ + gen_leaf( ¤t[SPX_N], ctx, idx + idx_offset, + info ); + + /* Now combine the freshly generated right node with previously */ + /* generated left ones */ + uint32_t internal_idx_offset = idx_offset; + uint32_t internal_idx = idx; + uint32_t internal_leaf = leaf_idx; + uint32_t h; /* The height we are in the Merkle tree */ + for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { + + /* Check if we hit the top of the tree */ + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[SPX_N], SPX_N ); + return; + } + + /* + * Check if the node we have is a part of the + * authentication path; if it is, write it out + */ + if ((internal_idx ^ internal_leaf) == 0x01) { + memcpy( &auth_path[ h * SPX_N ], + ¤t[SPX_N], + SPX_N ); + } + + /* + * Check if we're at a left child; if so, stop going up the stack + * Exception: if we've reached the end of the tree, keep on going + * (so we combine the last 4 nodes into the one root node in two + * more iterations) + */ + if ((internal_idx & 1) == 0 && idx < max_idx) { + break; + } + + /* Ok, we're at a right node */ + /* Now combine the left and right logical nodes together */ + + /* Set the address of the node we're creating. */ + internal_idx_offset >>= 1; + set_tree_height(tree_addr, h + 1); + set_tree_index(tree_addr, internal_idx / 2 + internal_idx_offset ); + + unsigned char *left = &stack[h * SPX_N]; + memcpy( ¤t[0], left, SPX_N ); + thash( ¤t[1 * SPX_N], + ¤t[0 * SPX_N], + 2, ctx, tree_addr); + } + + /* We've hit a left child; save the current for when we get the */ + /* corresponding right right */ + memcpy( &stack[h * SPX_N], ¤t[SPX_N], SPX_N); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/utilsx1.h b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/utilsx1.h new file mode 100644 index 0000000000..e911d17d53 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/utilsx1.h @@ -0,0 +1,27 @@ +#ifndef SPX_UTILSX4_H +#define SPX_UTILSX4_H + +#include + +#include "context.h" +#include "params.h" + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +#define treehashx1 SPX_NAMESPACE(treehashx1) +void treehashx1(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* Where to write the leaf */, + const spx_ctx * /* ctx */, + uint32_t addr_idx, void *info), + uint32_t tree_addrx4[8], void *info); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/wots.c b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/wots.c new file mode 100644 index 0000000000..249717aaa8 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/wots.c @@ -0,0 +1,108 @@ +#include +#include + +#include "wots.h" +#include "wotsx1.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "thash.h" +#include "utils.h" +#include "utilsx1.h" + +// TODO clarify address expectations, and make them more uniform. +// TODO i.e. do we expect types to be set already? +// TODO and do we expect modifications or copies? + +/** + * Computes the chaining function. + * out and in have to be n-byte arrays. + * + * Interprets in as start-th value of the chain. + * addr has to contain the address of the chain. + */ +static void gen_chain(unsigned char *out, const unsigned char *in, + unsigned int start, unsigned int steps, + const spx_ctx *ctx, uint32_t addr[8]) { + uint32_t i; + + /* Initialize out with the value at position 'start'. */ + memcpy(out, in, SPX_N); + + /* Iterate 'steps' calls to the hash function. */ + for (i = start; i < (start + steps) && i < SPX_WOTS_W; i++) { + set_hash_addr(addr, i); + thash(out, out, 1, ctx, addr); + } +} + +/** + * base_w algorithm as described in draft. + * Interprets an array of bytes as integers in base w. + * This only works when log_w is a divisor of 8. + */ +static void base_w(unsigned int *output, const int out_len, + const unsigned char *input) { + int in = 0; + int out = 0; + unsigned char total = 0; + int bits = 0; + int consumed; + + for (consumed = 0; consumed < out_len; consumed++) { + if (bits == 0) { + total = input[in]; + in++; + bits += 8; + } + bits -= SPX_WOTS_LOGW; + output[out] = (total >> bits) & (SPX_WOTS_W - 1); + out++; + } +} + +/* Computes the WOTS+ checksum over a message (in base_w). */ +static void wots_checksum(unsigned int *csum_base_w, + const unsigned int *msg_base_w) { + unsigned int csum = 0; + unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; + unsigned int i; + + /* Compute checksum. */ + for (i = 0; i < SPX_WOTS_LEN1; i++) { + csum += SPX_WOTS_W - 1 - msg_base_w[i]; + } + + /* Convert checksum to base_w. */ + /* Make sure expected empty zero bits are the least significant bits. */ + csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); + ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); + base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); +} + +/* Takes a message and derives the matching chain lengths. */ +void chain_lengths(unsigned int *lengths, const unsigned char *msg) { + base_w(lengths, SPX_WOTS_LEN1, msg); + wots_checksum(lengths + SPX_WOTS_LEN1, lengths); +} + +/** + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. + * + * Writes the computed public key to 'pk'. + */ +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]) { + unsigned int lengths[SPX_WOTS_LEN]; + uint32_t i; + + chain_lengths(lengths, msg); + + for (i = 0; i < SPX_WOTS_LEN; i++) { + set_chain_addr(addr, i); + gen_chain(pk + i * SPX_N, sig + i * SPX_N, + lengths[i], SPX_WOTS_W - 1 - lengths[i], ctx, addr); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/wots.h b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/wots.h new file mode 100644 index 0000000000..4e7692eeef --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/wots.h @@ -0,0 +1,25 @@ +#ifndef SPX_WOTS_H +#define SPX_WOTS_H + +#include + +#include "context.h" +#include "params.h" + +/** + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. + * + * Writes the computed public key to 'pk'. + */ +#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]); + +/* + * Compute the chain lengths needed for a given message hash + */ +#define chain_lengths SPX_NAMESPACE(chain_lengths) +void chain_lengths(unsigned int *lengths, const unsigned char *msg); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/wotsx1.c b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/wotsx1.c new file mode 100644 index 0000000000..3adec78dfb --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/wotsx1.c @@ -0,0 +1,76 @@ +#include +#include + +#include "wots.h" +#include "wotsx1.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "thash.h" +#include "utils.h" + +/* + * This generates a WOTS public key + * It also generates the WOTS signature if leaf_info indicates + * that we're signing with this WOTS key + */ +void wots_gen_leafx1(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info) { + struct leaf_info_x1 *info = v_info; + uint32_t *leaf_addr = info->leaf_addr; + uint32_t *pk_addr = info->pk_addr; + unsigned int i, k; + unsigned char pk_buffer[ SPX_WOTS_BYTES ]; + unsigned char *buffer; + uint32_t wots_k_mask; + + if (leaf_idx == info->wots_sign_leaf) { + /* We're traversing the leaf that's signing; generate the WOTS */ + /* signature */ + wots_k_mask = 0; + } else { + /* Nope, we're just generating pk's; turn off the signature logic */ + wots_k_mask = (uint32_t)~0; + } + + set_keypair_addr( leaf_addr, leaf_idx ); + set_keypair_addr( pk_addr, leaf_idx ); + + for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { + uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k to */ + /* the step if we're generating a signature, ~0 if we're not */ + + /* Start with the secret seed */ + set_chain_addr(leaf_addr, i); + set_hash_addr(leaf_addr, 0); + set_type(leaf_addr, SPX_ADDR_TYPE_WOTSPRF); + + prf_addr(buffer, ctx, leaf_addr); + + set_type(leaf_addr, SPX_ADDR_TYPE_WOTS); + + /* Iterate down the WOTS chain */ + for (k = 0;; k++) { + /* Check if this is the value that needs to be saved as a */ + /* part of the WOTS signature */ + if (k == wots_k) { + memcpy( info->wots_sig + i * SPX_N, buffer, SPX_N ); + } + + /* Check if we hit the top of the chain */ + if (k == SPX_WOTS_W - 1) { + break; + } + + /* Iterate one step on the chain */ + set_hash_addr(leaf_addr, k); + + thash(buffer, buffer, 1, ctx, leaf_addr); + } + } + + /* Do the final thash to generate the public keys */ + thash(dest, pk_buffer, SPX_WOTS_LEN, ctx, pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/wotsx1.h b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/wotsx1.h new file mode 100644 index 0000000000..e617929f96 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/wotsx1.h @@ -0,0 +1,39 @@ +#ifndef WOTSX1_H_ +#define WOTSX1_H_ + +#include + +#include "context.h" +#include "params.h" + +/* + * This is here to provide an interface to the internal wots_gen_leafx1 + * routine. While this routine is not referenced in the package outside of + * wots.c, it is called from the stand-alone benchmark code to characterize + * the performance + */ +struct leaf_info_x1 { + unsigned char *wots_sig; + uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ + uint32_t *wots_steps; + uint32_t leaf_addr[8]; + uint32_t pk_addr[8]; +}; + +/* Macro to set the leaf_info to something 'benign', that is, it would */ +/* run with the same time as it does during the real signing process */ +/* Used only by the benchmark code */ +#define INITIALIZE_LEAF_INFO_X1(info, addr, step_buffer) { \ + (info).wots_sig = 0; \ + (info).wots_sign_leaf = ~0; \ + (info).wots_steps = step_buffer; \ + memcpy( &(info).leaf_addr[0], (addr), 32 ); \ + memcpy( &(info).pk_addr[0], (addr), 32 ); \ + } + +#define wots_gen_leafx1 SPX_NAMESPACE(wots_gen_leafx1) +void wots_gen_leafx1(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info); + +#endif /* WOTSX1_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/LICENSE b/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/LICENSE new file mode 100644 index 0000000000..670154e353 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/LICENSE @@ -0,0 +1,116 @@ +CC0 1.0 Universal + +Statement of Purpose + +The laws of most jurisdictions throughout the world automatically confer +exclusive Copyright and Related Rights (defined below) upon the creator and +subsequent owner(s) (each and all, an "owner") of an original work of +authorship and/or a database (each, a "Work"). + +Certain owners wish to permanently relinquish those rights to a Work for the +purpose of contributing to a commons of creative, cultural and scientific +works ("Commons") that the public can reliably and without fear of later +claims of infringement build upon, modify, incorporate in other works, reuse +and redistribute as freely as possible in any form whatsoever and for any +purposes, including without limitation commercial purposes. These owners may +contribute to the Commons to promote the ideal of a free culture and the +further production of creative, cultural and scientific works, or to gain +reputation or greater distribution for their Work in part through the use and +efforts of others. + +For these and/or other purposes and motivations, and without any expectation +of additional consideration or compensation, the person associating CC0 with a +Work (the "Affirmer"), to the extent that he or she is an owner of Copyright +and Related Rights in the Work, voluntarily elects to apply CC0 to the Work +and publicly distribute the Work under its terms, with knowledge of his or her +Copyright and Related Rights in the Work and the meaning and intended legal +effect of CC0 on those rights. + +1. Copyright and Related Rights. A Work made available under CC0 may be +protected by copyright and related or neighboring rights ("Copyright and +Related Rights"). Copyright and Related Rights include, but are not limited +to, the following: + + i. the right to reproduce, adapt, distribute, perform, display, communicate, + and translate a Work; + + ii. moral rights retained by the original author(s) and/or performer(s); + + iii. publicity and privacy rights pertaining to a person's image or likeness + depicted in a Work; + + iv. rights protecting against unfair competition in regards to a Work, + subject to the limitations in paragraph 4(a), below; + + v. rights protecting the extraction, dissemination, use and reuse of data in + a Work; + + vi. database rights (such as those arising under Directive 96/9/EC of the + European Parliament and of the Council of 11 March 1996 on the legal + protection of databases, and under any national implementation thereof, + including any amended or successor version of such directive); and + + vii. other similar, equivalent or corresponding rights throughout the world + based on applicable law or treaty, and any national implementations thereof. + +2. Waiver. To the greatest extent permitted by, but not in contravention of, +applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and +unconditionally waives, abandons, and surrenders all of Affirmer's Copyright +and Related Rights and associated claims and causes of action, whether now +known or unknown (including existing as well as future claims and causes of +action), in the Work (i) in all territories worldwide, (ii) for the maximum +duration provided by applicable law or treaty (including future time +extensions), (iii) in any current or future medium and for any number of +copies, and (iv) for any purpose whatsoever, including without limitation +commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes +the Waiver for the benefit of each member of the public at large and to the +detriment of Affirmer's heirs and successors, fully intending that such Waiver +shall not be subject to revocation, rescission, cancellation, termination, or +any other legal or equitable action to disrupt the quiet enjoyment of the Work +by the public as contemplated by Affirmer's express Statement of Purpose. + +3. Public License Fallback. Should any part of the Waiver for any reason be +judged legally invalid or ineffective under applicable law, then the Waiver +shall be preserved to the maximum extent permitted taking into account +Affirmer's express Statement of Purpose. In addition, to the extent the Waiver +is so judged Affirmer hereby grants to each affected person a royalty-free, +non transferable, non sublicensable, non exclusive, irrevocable and +unconditional license to exercise Affirmer's Copyright and Related Rights in +the Work (i) in all territories worldwide, (ii) for the maximum duration +provided by applicable law or treaty (including future time extensions), (iii) +in any current or future medium and for any number of copies, and (iv) for any +purpose whatsoever, including without limitation commercial, advertising or +promotional purposes (the "License"). The License shall be deemed effective as +of the date CC0 was applied by Affirmer to the Work. Should any part of the +License for any reason be judged legally invalid or ineffective under +applicable law, such partial invalidity or ineffectiveness shall not +invalidate the remainder of the License, and in such case Affirmer hereby +affirms that he or she will not (i) exercise any of his or her remaining +Copyright and Related Rights in the Work or (ii) assert any associated claims +and causes of action with respect to the Work, in either case contrary to +Affirmer's express Statement of Purpose. + +4. Limitations and Disclaimers. + + a. No trademark or patent rights held by Affirmer are waived, abandoned, + surrendered, licensed or otherwise affected by this document. + + b. Affirmer offers the Work as-is and makes no representations or warranties + of any kind concerning the Work, express, implied, statutory or otherwise, + including without limitation warranties of title, merchantability, fitness + for a particular purpose, non infringement, or the absence of latent or + other defects, accuracy, or the present or absence of errors, whether or not + discoverable, all to the greatest extent permissible under applicable law. + + c. Affirmer disclaims responsibility for clearing rights of other persons + that may apply to the Work or any use thereof, including without limitation + any person's Copyright and Related Rights in the Work. Further, Affirmer + disclaims responsibility for obtaining any necessary consents, permissions + or other rights required for any use of the Work. + + d. Affirmer understands and acknowledges that Creative Commons is not a + party to this document and has no duty or obligation with respect to this + CC0 or use of the Work. + +For more information, please see + diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/address.c b/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/address.c new file mode 100644 index 0000000000..b956e9cb29 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/address.c @@ -0,0 +1,91 @@ +#include +#include + +#include "address.h" +#include "params.h" +#include "utils.h" + +/* + * Specify which level of Merkle tree (the "layer") we're working on + */ +void set_layer_addr(uint32_t addr[8], uint32_t layer) { + ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; +} + +/* + * Specify which Merkle tree within the level (the "tree address") we're working on + */ +void set_tree_addr(uint32_t addr[8], uint64_t tree) { + ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); +} + +/* + * Specify the reason we'll use this address structure for, that is, what + * hash will we compute with it. This is used so that unrelated types of + * hashes don't accidentally get the same address structure. The type will be + * one of the SPX_ADDR_TYPE constants + */ +void set_type(uint32_t addr[8], uint32_t type) { + ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; +} + +/* + * Copy the layer and tree fields of the address structure. This is used + * when we're doing multiple types of hashes within the same Merkle tree + */ +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); +} + +/* These functions are used for OTS addresses. */ + +/* + * Specify which Merkle leaf we're working on; that is, which OTS keypair + * we're talking about. + */ +void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { + ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; +} + +/* + * Copy the layer, tree and keypair fields of the address structure. This is + * used when we're doing multiple things within the same OTS keypair + */ +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); + ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; +} + +/* + * Specify which Merkle chain within the OTS we're working with + * (the chain address) + */ +void set_chain_addr(uint32_t addr[8], uint32_t chain) { + ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; +} + +/* + * Specify where in the Merkle chain we are +* (the hash address) + */ +void set_hash_addr(uint32_t addr[8], uint32_t hash) { + ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; +} + +/* These functions are used for all hash tree addresses (including FORS). */ + +/* + * Specify the height of the node in the Merkle/FORS tree we are in + * (the tree height) + */ +void set_tree_height(uint32_t addr[8], uint32_t tree_height) { + ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; +} + +/* + * Specify the distance from the left edge of the node in the Merkle/FORS tree + * (the tree index) + */ +void set_tree_index(uint32_t addr[8], uint32_t tree_index) { + u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/address.h b/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/address.h new file mode 100644 index 0000000000..24a84eb40c --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/address.h @@ -0,0 +1,52 @@ +#ifndef SPX_ADDRESS_H +#define SPX_ADDRESS_H + +#include + +#include "params.h" + +/* The hash types that are passed to set_type */ +#define SPX_ADDR_TYPE_WOTS 0 +#define SPX_ADDR_TYPE_WOTSPK 1 +#define SPX_ADDR_TYPE_HASHTREE 2 +#define SPX_ADDR_TYPE_FORSTREE 3 +#define SPX_ADDR_TYPE_FORSPK 4 +#define SPX_ADDR_TYPE_WOTSPRF 5 +#define SPX_ADDR_TYPE_FORSPRF 6 + +#define set_layer_addr SPX_NAMESPACE(set_layer_addr) +void set_layer_addr(uint32_t addr[8], uint32_t layer); + +#define set_tree_addr SPX_NAMESPACE(set_tree_addr) +void set_tree_addr(uint32_t addr[8], uint64_t tree); + +#define set_type SPX_NAMESPACE(set_type) +void set_type(uint32_t addr[8], uint32_t type); + +/* Copies the layer and tree part of one address into the other */ +#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); + +/* These functions are used for WOTS and FORS addresses. */ + +#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) +void set_keypair_addr(uint32_t addr[8], uint32_t keypair); + +#define set_chain_addr SPX_NAMESPACE(set_chain_addr) +void set_chain_addr(uint32_t addr[8], uint32_t chain); + +#define set_hash_addr SPX_NAMESPACE(set_hash_addr) +void set_hash_addr(uint32_t addr[8], uint32_t hash); + +#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); + +/* These functions are used for all hash tree addresses (including FORS). */ + +#define set_tree_height SPX_NAMESPACE(set_tree_height) +void set_tree_height(uint32_t addr[8], uint32_t tree_height); + +#define set_tree_index SPX_NAMESPACE(set_tree_index) +void set_tree_index(uint32_t addr[8], uint32_t tree_index); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/api.h b/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/api.h new file mode 100644 index 0000000000..32ce308794 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/api.h @@ -0,0 +1,77 @@ +#ifndef PQCLEAN_SPHINCSSHA2192FSIMPLE_AVX2_API_H +#define PQCLEAN_SPHINCSSHA2192FSIMPLE_AVX2_API_H + +#include +#include + +#define PQCLEAN_SPHINCSSHA2192FSIMPLE_AVX2_CRYPTO_ALGNAME "SPHINCS+-sha2-192f-simple" + +#define PQCLEAN_SPHINCSSHA2192FSIMPLE_AVX2_CRYPTO_SECRETKEYBYTES 96 +#define PQCLEAN_SPHINCSSHA2192FSIMPLE_AVX2_CRYPTO_PUBLICKEYBYTES 48 +#define PQCLEAN_SPHINCSSHA2192FSIMPLE_AVX2_CRYPTO_BYTES 35664 + +#define PQCLEAN_SPHINCSSHA2192FSIMPLE_AVX2_CRYPTO_SEEDBYTES 72 + +/* + * Returns the length of a secret key, in bytes + */ +size_t PQCLEAN_SPHINCSSHA2192FSIMPLE_AVX2_crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +size_t PQCLEAN_SPHINCSSHA2192FSIMPLE_AVX2_crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +size_t PQCLEAN_SPHINCSSHA2192FSIMPLE_AVX2_crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +size_t PQCLEAN_SPHINCSSHA2192FSIMPLE_AVX2_crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +int PQCLEAN_SPHINCSSHA2192FSIMPLE_AVX2_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +int PQCLEAN_SPHINCSSHA2192FSIMPLE_AVX2_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +int PQCLEAN_SPHINCSSHA2192FSIMPLE_AVX2_crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +int PQCLEAN_SPHINCSSHA2192FSIMPLE_AVX2_crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, + const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +int PQCLEAN_SPHINCSSHA2192FSIMPLE_AVX2_crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +int PQCLEAN_SPHINCSSHA2192FSIMPLE_AVX2_crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/context.h b/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/context.h new file mode 100644 index 0000000000..d3bf1c3aac --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/context.h @@ -0,0 +1,29 @@ +#ifndef SPX_CONTEXT_H +#define SPX_CONTEXT_H + +#include + +#include "params.h" +#include "sha2.h" +#include "sha256avx.h" +#include "sha512x4.h" + +// funky ordering due to optimal padding +typedef struct { + sha256x8ctx statex8_seeded; + sha512x4ctx statex4_seeded_512; + sha256ctx state_seeded; + sha512ctx state_seeded_512; + + uint8_t pub_seed[SPX_N]; + uint8_t sk_seed[SPX_N]; +} spx_ctx; + + +#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) +void initialize_hash_function(spx_ctx *ctx); + +#define free_hash_function SPX_NAMESPACE(free_hash_function) +void free_hash_function(spx_ctx *ctx); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/context_sha2.c b/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/context_sha2.c new file mode 100644 index 0000000000..83c1b6585d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/context_sha2.c @@ -0,0 +1,56 @@ +#include + +#include "context.h" + +/** + * Absorb the constant pub_seed using one round of the compression function + * This initializes state_seeded and state_seeded_512, which can then be + * reused in thash + **/ +static void seed_state(spx_ctx *ctx) { + uint8_t block[SPX_SHA512_BLOCK_BYTES]; + size_t i; + + for (i = 0; i < SPX_N; ++i) { + block[i] = ctx->pub_seed[i]; + } + for (i = SPX_N; i < SPX_SHA512_BLOCK_BYTES; ++i) { + block[i] = 0; + } + /* block has been properly initialized for both SHA-256 and SHA-512 */ + + sha256_inc_init(&ctx->state_seeded); + sha256_inc_blocks(&ctx->state_seeded, block, 1); + + // initialize x8 + sha256_init8x(&ctx->statex8_seeded); + sha256_transform8x(&ctx->statex8_seeded, + block, block, block, block, block, block, block, block); + + ctx->statex8_seeded.datalen = 0; + ctx->statex8_seeded.msglen = 512; + + sha512_inc_init(&ctx->state_seeded_512); + sha512_inc_blocks(&ctx->state_seeded_512, block, 1); + + // initialize x4 + sha512_init4x(&ctx->statex4_seeded_512); + sha512_transform4x(&ctx->statex4_seeded_512, block, block, block, block); + + ctx->statex4_seeded_512.datalen = 0; + ctx->statex4_seeded_512.msglen = 1024; + + +} + + +/* For SHA, we initialize the hash function at the start */ +void initialize_hash_function(spx_ctx *ctx) { + seed_state(ctx); +} + +/* Free the incremental hashing context for heap-based SHA2 APIs */ +void free_hash_function(spx_ctx *ctx) { + sha256_inc_ctx_release(&ctx->state_seeded); + sha512_inc_ctx_release(&ctx->state_seeded_512); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/fors.c b/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/fors.c new file mode 100644 index 0000000000..4cab8e7415 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/fors.c @@ -0,0 +1,226 @@ +#include +#include +#include + +#include "fors.h" + + +#include "address.h" +#include "hash.h" +#include "hashx8.h" +#include "thash.h" +#include "thashx8.h" +#include "utils.h" +#include "utilsx8.h" +static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + prf_addr(sk, ctx, fors_leaf_addr); +} + +static void fors_gen_skx8(unsigned char *sk0, + unsigned char *sk1, + unsigned char *sk2, + unsigned char *sk3, + unsigned char *sk4, + unsigned char *sk5, + unsigned char *sk6, + unsigned char *sk7, const spx_ctx *ctx, + uint32_t fors_leaf_addrx8[8 * 8]) { + prf_addrx8(sk0, sk1, sk2, sk3, sk4, sk5, sk6, sk7, + ctx, fors_leaf_addrx8); +} + +static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, + const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + thash(leaf, sk, 1, ctx, fors_leaf_addr); +} + +static void fors_sk_to_leafx8(unsigned char *leaf0, + unsigned char *leaf1, + unsigned char *leaf2, + unsigned char *leaf3, + unsigned char *leaf4, + unsigned char *leaf5, + unsigned char *leaf6, + unsigned char *leaf7, + const unsigned char *sk0, + const unsigned char *sk1, + const unsigned char *sk2, + const unsigned char *sk3, + const unsigned char *sk4, + const unsigned char *sk5, + const unsigned char *sk6, + const unsigned char *sk7, + const spx_ctx *ctx, + uint32_t fors_leaf_addrx8[8 * 8]) { + thashx8(leaf0, leaf1, leaf2, leaf3, leaf4, leaf5, leaf6, leaf7, + sk0, sk1, sk2, sk3, sk4, sk5, sk6, sk7, + 1, ctx, fors_leaf_addrx8); +} + +struct fors_gen_leaf_info { + uint32_t leaf_addrx[8 * 8]; +}; + +static void fors_gen_leafx8(unsigned char *leaf, + const spx_ctx *ctx, + uint32_t addr_idx, void *info) { + struct fors_gen_leaf_info *fors_info = info; + uint32_t *fors_leaf_addrx8 = fors_info->leaf_addrx; + unsigned int j; + + /* Only set the parts that the caller doesn't set */ + for (j = 0; j < 8; j++) { + set_tree_index(fors_leaf_addrx8 + j * 8, addr_idx + j); + set_type(fors_leaf_addrx8 + j * 8, SPX_ADDR_TYPE_FORSPRF); + } + + fors_gen_skx8(leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + leaf + 2 * SPX_N, + leaf + 3 * SPX_N, + leaf + 4 * SPX_N, + leaf + 5 * SPX_N, + leaf + 6 * SPX_N, + leaf + 7 * SPX_N, + ctx, fors_leaf_addrx8); + + for (j = 0; j < 8; j++) { + set_type(fors_leaf_addrx8 + j * 8, SPX_ADDR_TYPE_FORSTREE); + } + + fors_sk_to_leafx8(leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + leaf + 2 * SPX_N, + leaf + 3 * SPX_N, + leaf + 4 * SPX_N, + leaf + 5 * SPX_N, + leaf + 6 * SPX_N, + leaf + 7 * SPX_N, + leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + leaf + 2 * SPX_N, + leaf + 3 * SPX_N, + leaf + 4 * SPX_N, + leaf + 5 * SPX_N, + leaf + 6 * SPX_N, + leaf + 7 * SPX_N, + ctx, fors_leaf_addrx8); +} + +/** + * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + * Assumes indices has space for SPX_FORS_TREES integers. + */ +static void message_to_indices(uint32_t *indices, const unsigned char *m) { + unsigned int i, j; + unsigned int offset = 0; + + for (i = 0; i < SPX_FORS_TREES; i++) { + indices[i] = 0; + for (j = 0; j < SPX_FORS_HEIGHT; j++) { + indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); + offset++; + } + } +} + +/** + * Signs a message m, deriving the secret key from sk_seed and the FTS address. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + uint32_t fors_tree_addr[8 * 8] = {0}; + struct fors_gen_leaf_info fors_info = {0}; + uint32_t *fors_leaf_addr = fors_info.leaf_addrx; + uint32_t fors_pk_addr[8] = {0}; + uint32_t idx_offset; + unsigned int i; + + for (i = 0; i < 8; i++) { + copy_keypair_addr(fors_tree_addr + 8 * i, fors_addr); + set_type(fors_tree_addr + 8 * i, SPX_ADDR_TYPE_FORSTREE); + copy_keypair_addr(fors_leaf_addr + 8 * i, fors_addr); + } + copy_keypair_addr(fors_pk_addr, fors_addr); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); + + message_to_indices(indices, m); + + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); + + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + + /* Include the secret key part that produces the selected leaf node. */ + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); + fors_gen_sk(sig, ctx, fors_tree_addr); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + sig += SPX_N; + + /* Compute the authentication path for this leaf node. */ + treehashx8(roots + i * SPX_N, sig, ctx, + indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx8, + fors_tree_addr, &fors_info); + + sig += SPX_N * SPX_FORS_HEIGHT; + } + + /* Hash horizontally across all tree roots to derive the public key. */ + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); +} + +/** + * Derives the FORS public key from a signature. + * This can be used for verification by comparing to a known public key, or to + * subsequently verify a signature on the derived public key. The latter is the + * typical use-case when used as an FTS below an OTS in a hypertree. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + unsigned char leaf[SPX_N]; + uint32_t fors_tree_addr[8] = {0}; + uint32_t fors_pk_addr[8] = {0}; + uint32_t idx_offset; + unsigned int i; + + copy_keypair_addr(fors_tree_addr, fors_addr); + copy_keypair_addr(fors_pk_addr, fors_addr); + + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); + + message_to_indices(indices, m); + + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); + + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + + /* Derive the leaf from the included secret key part. */ + fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); + sig += SPX_N; + + /* Derive the corresponding root node of this tree. */ + compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, + sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); + sig += SPX_N * SPX_FORS_HEIGHT; + } + + /* Hash horizontally across all tree roots to derive the public key. */ + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/fors.h b/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/fors.h new file mode 100644 index 0000000000..509140a178 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/fors.h @@ -0,0 +1,32 @@ +#ifndef SPX_FORS_H +#define SPX_FORS_H + +#include + +#include "context.h" +#include "params.h" + +/** + * Signs a message m, deriving the secret key from sk_seed and the FTS address. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +#define fors_sign SPX_NAMESPACE(fors_sign) +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); + +/** + * Derives the FORS public key from a signature. + * This can be used for verification by comparing to a known public key, or to + * subsequently verify a signature on the derived public key. The latter is the + * typical use-case when used as an FTS below an OTS in a hypertree. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/hash.h b/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/hash.h new file mode 100644 index 0000000000..ffe815f45d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/hash.h @@ -0,0 +1,37 @@ +#ifndef SPX_HASH_H +#define SPX_HASH_H + +#include +#include + +#include "context.h" +#include "params.h" + +#define prf_addr SPX_NAMESPACE(prf_addr) +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]); + +#define gen_message_random SPX_NAMESPACE(gen_message_random) +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); + +#define hash_message SPX_NAMESPACE(hash_message) +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); + + +# define SPX_SHA256_ADDR_BYTES 22 + +# define mgf1_256 SPX_NAMESPACE(mgf1_256) +void mgf1_256(unsigned char *out, unsigned long outlen, + const unsigned char *in, unsigned long inlen); + +# define mgf1_512 SPX_NAMESPACE(mgf1_512) +void mgf1_512(unsigned char *out, unsigned long outlen, + const unsigned char *in, unsigned long inlen); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/hash_sha2.c b/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/hash_sha2.c new file mode 100644 index 0000000000..3d0085c8c1 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/hash_sha2.c @@ -0,0 +1,219 @@ +#include +#include + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "sha2.h" +#include "utils.h" + + + +#define SPX_SHAX_OUTPUT_BYTES SPX_SHA512_OUTPUT_BYTES +#define SPX_SHAX_BLOCK_BYTES SPX_SHA512_BLOCK_BYTES +#define shaX_inc_init sha512_inc_init +#define shaX_inc_blocks sha512_inc_blocks +#define shaX_inc_finalize sha512_inc_finalize +#define shaX sha512 +#define mgf1_X mgf1_512 +#define shaXstate sha512ctx + +/** + * mgf1 function based on the SHA-256 hash function + * Note that inlen should be sufficiently small that it still allows for + * an array to be allocated on the stack. Typically 'in' is merely a seed. + * Outputs outlen number of bytes + */ +void mgf1_256(unsigned char *out, unsigned long outlen, + const unsigned char *in, unsigned long inlen) { + PQCLEAN_VLA(uint8_t, inbuf, inlen + 4); + unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES]; + uint32_t i; + + memcpy(inbuf, in, inlen); + + /* While we can fit in at least another full block of SHA256 output.. */ + for (i = 0; (i + 1)*SPX_SHA256_OUTPUT_BYTES <= outlen; i++) { + u32_to_bytes(inbuf + inlen, i); + sha256(out, inbuf, inlen + 4); + out += SPX_SHA256_OUTPUT_BYTES; + } + /* Until we cannot anymore, and we fill the remainder. */ + if (outlen > i * SPX_SHA256_OUTPUT_BYTES) { + u32_to_bytes(inbuf + inlen, i); + sha256(outbuf, inbuf, inlen + 4); + memcpy(out, outbuf, outlen - i * SPX_SHA256_OUTPUT_BYTES); + } +} + +/* + * mgf1 function based on the SHA-512 hash function + */ +void mgf1_512(unsigned char *out, unsigned long outlen, + const unsigned char *in, unsigned long inlen) { + PQCLEAN_VLA(uint8_t, inbuf, inlen + 4); + unsigned char outbuf[SPX_SHA512_OUTPUT_BYTES]; + uint32_t i; + + memcpy(inbuf, in, inlen); + + /* While we can fit in at least another full block of SHA512 output.. */ + for (i = 0; (i + 1)*SPX_SHA512_OUTPUT_BYTES <= outlen; i++) { + u32_to_bytes(inbuf + inlen, i); + sha512(out, inbuf, inlen + 4); + out += SPX_SHA512_OUTPUT_BYTES; + } + /* Until we cannot anymore, and we fill the remainder. */ + if (outlen > i * SPX_SHA512_OUTPUT_BYTES) { + u32_to_bytes(inbuf + inlen, i); + sha512(outbuf, inbuf, inlen + 4); + memcpy(out, outbuf, outlen - i * SPX_SHA512_OUTPUT_BYTES); + } +} + +/* + * Computes PRF(pk_seed, sk_seed, addr). + */ +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]) { + sha256ctx sha2_state; + unsigned char buf[SPX_SHA256_ADDR_BYTES + SPX_N]; + unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES]; + + /* Retrieve precomputed state containing pub_seed */ + sha256_inc_ctx_clone(&sha2_state, &ctx->state_seeded); + + /* Remainder: ADDR^c ‖ SK.seed */ + memcpy(buf, addr, SPX_SHA256_ADDR_BYTES); + memcpy(buf + SPX_SHA256_ADDR_BYTES, ctx->sk_seed, SPX_N); + + sha256_inc_finalize(outbuf, &sha2_state, buf, SPX_SHA256_ADDR_BYTES + SPX_N); + + memcpy(out, outbuf, SPX_N); +} + +/** + * Computes the message-dependent randomness R, using a secret seed as a key + * for HMAC, and an optional randomization value prefixed to the message. + * This requires m to have at least SPX_SHAX_BLOCK_BYTES + SPX_N space + * available in front of the pointer, i.e. before the message to use for the + * prefix. This is necessary to prevent having to move the message around (and + * allocate memory for it). + */ +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { + (void)ctx; + + unsigned char buf[SPX_SHAX_BLOCK_BYTES + SPX_SHAX_OUTPUT_BYTES]; + shaXstate state; + int i; + + + /* This implements HMAC-SHA */ + for (i = 0; i < SPX_N; i++) { + buf[i] = 0x36 ^ sk_prf[i]; + } + memset(buf + SPX_N, 0x36, SPX_SHAX_BLOCK_BYTES - SPX_N); + + shaX_inc_init(&state); + shaX_inc_blocks(&state, buf, 1); + + memcpy(buf, optrand, SPX_N); + + /* If optrand + message cannot fill up an entire block */ + if (SPX_N + mlen < SPX_SHAX_BLOCK_BYTES) { + memcpy(buf + SPX_N, m, mlen); + shaX_inc_finalize(buf + SPX_SHAX_BLOCK_BYTES, &state, + buf, mlen + SPX_N); + } + /* Otherwise first fill a block, so that finalize only uses the message */ + else { + memcpy(buf + SPX_N, m, SPX_SHAX_BLOCK_BYTES - SPX_N); + shaX_inc_blocks(&state, buf, 1); + + m += SPX_SHAX_BLOCK_BYTES - SPX_N; + mlen -= SPX_SHAX_BLOCK_BYTES - SPX_N; + shaX_inc_finalize(buf + SPX_SHAX_BLOCK_BYTES, &state, m, mlen); + } + + for (i = 0; i < SPX_N; i++) { + buf[i] = 0x5c ^ sk_prf[i]; + } + memset(buf + SPX_N, 0x5c, SPX_SHAX_BLOCK_BYTES - SPX_N); + + shaX(buf, buf, SPX_SHAX_BLOCK_BYTES + SPX_SHAX_OUTPUT_BYTES); + memcpy(R, buf, SPX_N); +} + +/** + * Computes the message hash using R, the public key, and the message. + * Outputs the message digest and the index of the leaf. The index is split in + * the tree index and the leaf index, for convenient copying to an address. + */ +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { + (void)ctx; +#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) +#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) +#define SPX_LEAF_BITS SPX_TREE_HEIGHT +#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) +#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) + + unsigned char seed[2 * SPX_N + SPX_SHAX_OUTPUT_BYTES]; + + /* Round to nearest multiple of SPX_SHAX_BLOCK_BYTES */ +#define SPX_INBLOCKS (((SPX_N + SPX_PK_BYTES + SPX_SHAX_BLOCK_BYTES - 1) & \ + -SPX_SHAX_BLOCK_BYTES) / SPX_SHAX_BLOCK_BYTES) + unsigned char inbuf[SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES]; + + unsigned char buf[SPX_DGST_BYTES]; + unsigned char *bufp = buf; + shaXstate state; + + shaX_inc_init(&state); + + // seed: SHA-X(R ‖ PK.seed ‖ PK.root ‖ M) + memcpy(inbuf, R, SPX_N); + memcpy(inbuf + SPX_N, pk, SPX_PK_BYTES); + + /* If R + pk + message cannot fill up an entire block */ + if (SPX_N + SPX_PK_BYTES + mlen < SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES) { + memcpy(inbuf + SPX_N + SPX_PK_BYTES, m, mlen); + shaX_inc_finalize(seed + 2 * SPX_N, &state, inbuf, SPX_N + SPX_PK_BYTES + mlen); + } + /* Otherwise first fill a block, so that finalize only uses the message */ + else { + memcpy(inbuf + SPX_N + SPX_PK_BYTES, m, + SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES - SPX_N - SPX_PK_BYTES); + shaX_inc_blocks(&state, inbuf, SPX_INBLOCKS); + + m += SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES - SPX_N - SPX_PK_BYTES; + mlen -= SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES - SPX_N - SPX_PK_BYTES; + shaX_inc_finalize(seed + 2 * SPX_N, &state, m, (size_t)mlen); + } + + // H_msg: MGF1-SHA-X(R ‖ PK.seed ‖ seed) + memcpy(seed, R, SPX_N); + memcpy(seed + SPX_N, pk, SPX_N); + + /* By doing this in two steps, we prevent hashing the message twice; + otherwise each iteration in MGF1 would hash the message again. */ + mgf1_X(bufp, SPX_DGST_BYTES, seed, 2 * SPX_N + SPX_SHAX_OUTPUT_BYTES); + + memcpy(digest, bufp, SPX_FORS_MSG_BYTES); + bufp += SPX_FORS_MSG_BYTES; + + + *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); + *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); + bufp += SPX_TREE_BYTES; + + *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); + *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); +} + + diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/hash_sha2x8.c b/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/hash_sha2x8.c new file mode 100644 index 0000000000..e04af7a069 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/hash_sha2x8.c @@ -0,0 +1,75 @@ +#include +#include + +#include "hash.h" +#include "hashx8.h" + +#include "address.h" +#include "params.h" +#include "sha2.h" +#include "sha256avx.h" +#include "sha256x8.h" +#include "utils.h" + +/* + * 8-way parallel version of prf_addr; takes 8x as much input and output + */ +void prf_addrx8(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const spx_ctx *ctx, + const uint32_t addrx8[8 * 8]) { + unsigned char bufx8[8 * (SPX_N + SPX_SHA256_ADDR_BYTES)]; + unsigned char outbufx8[8 * SPX_SHA256_OUTPUT_BYTES]; + unsigned int j; + + for (j = 0; j < 8; j++) { + memcpy(bufx8 + j * (SPX_N + SPX_SHA256_ADDR_BYTES), + addrx8 + j * 8, SPX_SHA256_ADDR_BYTES); + memcpy( + bufx8 + j * (SPX_N + SPX_SHA256_ADDR_BYTES) + SPX_SHA256_ADDR_BYTES, + ctx->sk_seed, + SPX_N + ); + } + + sha256x8_seeded( + /* out */ + outbufx8 + 0 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 1 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 2 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 3 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 4 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 5 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 6 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 7 * SPX_SHA256_OUTPUT_BYTES, + + /* seed */ + &ctx->statex8_seeded, + + /* in */ + bufx8 + 0 * (SPX_SHA256_ADDR_BYTES + SPX_N), + bufx8 + 1 * (SPX_SHA256_ADDR_BYTES + SPX_N), + bufx8 + 2 * (SPX_SHA256_ADDR_BYTES + SPX_N), + bufx8 + 3 * (SPX_SHA256_ADDR_BYTES + SPX_N), + bufx8 + 4 * (SPX_SHA256_ADDR_BYTES + SPX_N), + bufx8 + 5 * (SPX_SHA256_ADDR_BYTES + SPX_N), + bufx8 + 6 * (SPX_SHA256_ADDR_BYTES + SPX_N), + bufx8 + 7 * (SPX_SHA256_ADDR_BYTES + SPX_N), + SPX_SHA256_ADDR_BYTES + SPX_N /* len */ + ); + + memcpy(out0, outbufx8 + 0 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out1, outbufx8 + 1 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out2, outbufx8 + 2 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out3, outbufx8 + 3 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out4, outbufx8 + 4 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out5, outbufx8 + 5 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out6, outbufx8 + 6 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out7, outbufx8 + 7 * SPX_SHA256_OUTPUT_BYTES, SPX_N); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/hashx8.h b/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/hashx8.h new file mode 100644 index 0000000000..46503f0a10 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/hashx8.h @@ -0,0 +1,20 @@ +#ifndef SPX_HASHX8_H +#define SPX_HASHX8_H + +#include + +#include "params.h" + +#define prf_addrx8 SPX_NAMESPACE(prf_addrx8) +void prf_addrx8(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const spx_ctx *ctx, + const uint32_t addrx8[8 * 8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/merkle.c b/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/merkle.c new file mode 100644 index 0000000000..1f353c8dd8 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/merkle.c @@ -0,0 +1,65 @@ +#include +#include + +#include "merkle.h" + +#include "address.h" +#include "params.h" +#include "utils.h" +#include "utilsx8.h" +#include "wots.h" +#include "wotsx8.h" + +/* + * This generates a Merkle signature (WOTS signature followed by the Merkle + * authentication path). + */ +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf) { + unsigned char *auth_path = sig + SPX_WOTS_BYTES; + uint32_t tree_addrx8[8 * 8] = { 0 }; + int j; + struct leaf_info_x8 info = { 0 }; + unsigned steps[ SPX_WOTS_LEN ]; + + info.wots_sig = sig; + chain_lengths(steps, root); + info.wots_steps = steps; + + for (j = 0; j < 8; j++) { + set_type(&tree_addrx8[8 * j], SPX_ADDR_TYPE_HASHTREE); + set_type(&info.leaf_addr[8 * j], SPX_ADDR_TYPE_WOTS); + set_type(&info.pk_addr[8 * j], SPX_ADDR_TYPE_WOTSPK); + copy_subtree_addr(&tree_addrx8[8 * j], tree_addr); + copy_subtree_addr(&info.leaf_addr[8 * j], wots_addr); + copy_subtree_addr(&info.pk_addr[8 * j], wots_addr); + } + + info.wots_sign_leaf = idx_leaf; + + treehashx8(root, auth_path, ctx, + idx_leaf, 0, + SPX_TREE_HEIGHT, + wots_gen_leafx8, + tree_addrx8, &info); +} + +/* Compute root node of the top-most subtree. */ +/* Again, in this file because wots_gen_leaf is most of the work */ +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { + /* We do not need the auth path in key generation, but it simplifies the + code to have just one treehash routine that computes both root and path + in one function. */ + unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; + uint32_t top_tree_addr[8] = {0}; + uint32_t wots_addr[8] = {0}; + + set_layer_addr(top_tree_addr, SPX_D - 1); + set_layer_addr(wots_addr, SPX_D - 1); + + merkle_sign(auth_path, root, ctx, + wots_addr, top_tree_addr, + ~0U /* ~0 means "don't bother generating an auth path */ ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/merkle.h b/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/merkle.h new file mode 100644 index 0000000000..769cf2e970 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/merkle.h @@ -0,0 +1,21 @@ +#ifndef MERKLE_H_ +#define MERKLE_H_ + +#include + +#include "context.h" +#include "params.h" + +/* Generate a Merkle signature (WOTS signature followed by the Merkle */ +/* authentication path) */ +#define merkle_sign SPX_NAMESPACE(merkle_sign) +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf); + +/* Compute the root node of the top-most subtree. */ +#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); + +#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/nistapi.h b/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/nistapi.h new file mode 100644 index 0000000000..3cb71afad4 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/nistapi.h @@ -0,0 +1,87 @@ +#ifndef SPX_API_H +#define SPX_API_H + +#include +#include + +#include "params.h" + +#define CRYPTO_ALGNAME "SPHINCS+" + +#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES +#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES +#define CRYPTO_BYTES SPX_BYTES +#define CRYPTO_SEEDBYTES (3*SPX_N) + +/* + * Returns the length of a secret key, in bytes + */ +#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) +size_t crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) +size_t crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) +size_t crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) +size_t crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +#define crypto_sign SPX_NAMESPACE(crypto_sign) +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/params.h b/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/params.h new file mode 100644 index 0000000000..c9a25c3819 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/params.h @@ -0,0 +1,61 @@ +#ifndef SPX_PARAMS_H +#define SPX_PARAMS_H + +#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSSHA2192FSIMPLE_AVX2_##s + +/* Hash output length in bytes. */ +#define SPX_N 24 +/* Height of the hypertree. */ +#define SPX_FULL_HEIGHT 66 +/* Number of subtree layer. */ +#define SPX_D 22 +/* FORS tree dimensions. */ +#define SPX_FORS_HEIGHT 8 +#define SPX_FORS_TREES 33 +/* Winternitz parameter, */ +#define SPX_WOTS_W 16 + +/* The hash function is defined by linking a different hash.c file, as opposed + to setting a #define constant. */ + +/* This is a SHA2-based parameter set, hence whether we use SHA-256 + * exclusively or we use both SHA-256 and SHA-512 is controlled by + * the following #define */ +#define SPX_SHA512 1 /* Use SHA-512 for H and T_l, l >= 2 */ + +/* For clarity */ +#define SPX_ADDR_BYTES 32 + +/* WOTS parameters. */ +#define SPX_WOTS_LOGW 4 + +#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) + +/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ +#define SPX_WOTS_LEN2 3 + +#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) +#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) +#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES + +/* Subtree size. */ +#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) + +//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT +// #error SPX_D should always divide SPX_FULL_HEIGHT +//#endif + +/* FORS parameters. */ +#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) +#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) +#define SPX_FORS_PK_BYTES SPX_N + +/* Resulting SPX sizes. */ +#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ + SPX_FULL_HEIGHT * SPX_N) +#define SPX_PK_BYTES (2 * SPX_N) +#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) + +#include "sha2_offsets.h" + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/sha256avx.c b/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/sha256avx.c new file mode 100644 index 0000000000..6bbe6ecc24 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/sha256avx.c @@ -0,0 +1,357 @@ +#include +#include +#include + +#include "sha256avx.h" + +static const unsigned int RC[] = { + 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, + 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, + 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, + 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, + 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, + 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, + 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, + 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, + 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, + 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, + 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, + 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, + 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, + 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, + 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, + 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 +}; + +#define u32 uint32_t +#define u256 __m256i + +#define XOR _mm256_xor_si256 +#define OR _mm256_or_si256 +#define AND _mm256_and_si256 +#define ADD32 _mm256_add_epi32 +#define NOT(x) _mm256_xor_si256(x, _mm256_set_epi32(-1, -1, -1, -1, -1, -1, -1, -1)) + +#define LOAD(src) _mm256_loadu_si256((__m256i *)(src)) +#define STORE(dest,src) _mm256_storeu_si256((__m256i *)(dest),src) + +#define BYTESWAP(x) _mm256_shuffle_epi8(x, _mm256_set_epi8(0xc,0xd,0xe,0xf,0x8,0x9,0xa,0xb,0x4,0x5,0x6,0x7,0x0,0x1,0x2,0x3,0xc,0xd,0xe,0xf,0x8,0x9,0xa,0xb,0x4,0x5,0x6,0x7,0x0,0x1,0x2,0x3)) + +#define SHIFTR32(x, y) _mm256_srli_epi32(x, y) +#define SHIFTL32(x, y) _mm256_slli_epi32(x, y) + +#define ROTR32(x, y) OR(SHIFTR32(x, y), SHIFTL32(x, 32 - (y))) +#define ROTL32(x, y) OR(SHIFTL32(x, y), SHIFTR32(x, 32 - (y))) + +#define XOR3(a, b, c) XOR(XOR(a, b), c) + +#define ADD3_32(a, b, c) ADD32(ADD32(a, b), c) +#define ADD4_32(a, b, c, d) ADD32(ADD32(ADD32(a, b), c), d) +#define ADD5_32(a, b, c, d, e) ADD32(ADD32(ADD32(ADD32(a, b), c), d), e) + +#define MAJ_AVX(a, b, c) XOR3(AND(a, b), AND(a, c), AND(b, c)) +#define CH_AVX(a, b, c) XOR(AND(a, b), AND(NOT(a), c)) + +#define SIGMA1_AVX(x) XOR3(ROTR32(x, 6), ROTR32(x, 11), ROTR32(x, 25)) +#define SIGMA0_AVX(x) XOR3(ROTR32(x, 2), ROTR32(x, 13), ROTR32(x, 22)) + +#define WSIGMA1_AVX(x) XOR3(ROTR32(x, 17), ROTR32(x, 19), SHIFTR32(x, 10)) +#define WSIGMA0_AVX(x) XOR3(ROTR32(x, 7), ROTR32(x, 18), SHIFTR32(x, 3)) + +#define SHA256ROUND_AVX(a, b, c, d, e, f, g, h, rc, w) \ + T0 = ADD5_32(h, SIGMA1_AVX(e), CH_AVX(e, f, g), _mm256_set1_epi32((int)RC[rc]), w); \ + (d) = ADD32(d, T0); \ + T1 = ADD32(SIGMA0_AVX(a), MAJ_AVX(a, b, c)); \ + (h) = ADD32(T0, T1); + +// Transpose 8 vectors containing 32-bit values +static void transpose(u256 s[8]) { + u256 tmp0[8]; + u256 tmp1[8]; + tmp0[0] = _mm256_unpacklo_epi32(s[0], s[1]); + tmp0[1] = _mm256_unpackhi_epi32(s[0], s[1]); + tmp0[2] = _mm256_unpacklo_epi32(s[2], s[3]); + tmp0[3] = _mm256_unpackhi_epi32(s[2], s[3]); + tmp0[4] = _mm256_unpacklo_epi32(s[4], s[5]); + tmp0[5] = _mm256_unpackhi_epi32(s[4], s[5]); + tmp0[6] = _mm256_unpacklo_epi32(s[6], s[7]); + tmp0[7] = _mm256_unpackhi_epi32(s[6], s[7]); + tmp1[0] = _mm256_unpacklo_epi64(tmp0[0], tmp0[2]); + tmp1[1] = _mm256_unpackhi_epi64(tmp0[0], tmp0[2]); + tmp1[2] = _mm256_unpacklo_epi64(tmp0[1], tmp0[3]); + tmp1[3] = _mm256_unpackhi_epi64(tmp0[1], tmp0[3]); + tmp1[4] = _mm256_unpacklo_epi64(tmp0[4], tmp0[6]); + tmp1[5] = _mm256_unpackhi_epi64(tmp0[4], tmp0[6]); + tmp1[6] = _mm256_unpacklo_epi64(tmp0[5], tmp0[7]); + tmp1[7] = _mm256_unpackhi_epi64(tmp0[5], tmp0[7]); + s[0] = _mm256_permute2x128_si256(tmp1[0], tmp1[4], 0x20); + s[1] = _mm256_permute2x128_si256(tmp1[1], tmp1[5], 0x20); + s[2] = _mm256_permute2x128_si256(tmp1[2], tmp1[6], 0x20); + s[3] = _mm256_permute2x128_si256(tmp1[3], tmp1[7], 0x20); + s[4] = _mm256_permute2x128_si256(tmp1[0], tmp1[4], 0x31); + s[5] = _mm256_permute2x128_si256(tmp1[1], tmp1[5], 0x31); + s[6] = _mm256_permute2x128_si256(tmp1[2], tmp1[6], 0x31); + s[7] = _mm256_permute2x128_si256(tmp1[3], tmp1[7], 0x31); +} + +void sha256_ctx_clone8x(sha256x8ctx *out, const sha256x8ctx *in) { + memcpy(out, in, sizeof(sha256x8ctx)); +} + +void sha256_init8x(sha256x8ctx *ctx) { + ctx->s[0] = _mm256_set_epi32((int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667); + ctx->s[1] = _mm256_set_epi32((int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85); + ctx->s[2] = _mm256_set_epi32((int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372); + ctx->s[3] = _mm256_set_epi32((int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a); + ctx->s[4] = _mm256_set_epi32((int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f); + ctx->s[5] = _mm256_set_epi32((int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c); + ctx->s[6] = _mm256_set_epi32((int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab); + ctx->s[7] = _mm256_set_epi32((int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19); + + ctx->datalen = 0; + ctx->msglen = 0; +} + +void sha256_final8x(sha256x8ctx *ctx, + unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7) { + unsigned int i, curlen; + + // Padding + if (ctx->datalen < 56) { + for (i = 0; i < 8; ++i) { + curlen = ctx->datalen; + ctx->msgblocks[64 * i + curlen++] = 0x80; + while (curlen < 64) { + ctx->msgblocks[64 * i + curlen++] = 0x00; + } + } + } else { + for (i = 0; i < 8; ++i) { + curlen = ctx->datalen; + ctx->msgblocks[64 * i + curlen++] = 0x80; + while (curlen < 64) { + ctx->msgblocks[64 * i + curlen++] = 0x00; + } + } + sha256_transform8x(ctx, + &ctx->msgblocks[64 * 0], + &ctx->msgblocks[64 * 1], + &ctx->msgblocks[64 * 2], + &ctx->msgblocks[64 * 3], + &ctx->msgblocks[64 * 4], + &ctx->msgblocks[64 * 5], + &ctx->msgblocks[64 * 6], + &ctx->msgblocks[64 * 7] + ); + memset(ctx->msgblocks, 0, 8 * 64); + } + + // Add length of the message to each block + ctx->msglen += ctx->datalen * 8; + for (i = 0; i < 8; i++) { + ctx->msgblocks[64 * i + 63] = (unsigned char)(ctx->msglen); + ctx->msgblocks[64 * i + 62] = (unsigned char)(ctx->msglen >> 8); + ctx->msgblocks[64 * i + 61] = (unsigned char)(ctx->msglen >> 16); + ctx->msgblocks[64 * i + 60] = (unsigned char)(ctx->msglen >> 24); + ctx->msgblocks[64 * i + 59] = (unsigned char)(ctx->msglen >> 32); + ctx->msgblocks[64 * i + 58] = (unsigned char)(ctx->msglen >> 40); + ctx->msgblocks[64 * i + 57] = (unsigned char)(ctx->msglen >> 48); + ctx->msgblocks[64 * i + 56] = (unsigned char)(ctx->msglen >> 56); + } + sha256_transform8x(ctx, + &ctx->msgblocks[64 * 0], + &ctx->msgblocks[64 * 1], + &ctx->msgblocks[64 * 2], + &ctx->msgblocks[64 * 3], + &ctx->msgblocks[64 * 4], + &ctx->msgblocks[64 * 5], + &ctx->msgblocks[64 * 6], + &ctx->msgblocks[64 * 7] + ); + + // Compute final hash output + transpose(ctx->s); + + // Store Hash value + STORE(out0, BYTESWAP(ctx->s[0])); + STORE(out1, BYTESWAP(ctx->s[1])); + STORE(out2, BYTESWAP(ctx->s[2])); + STORE(out3, BYTESWAP(ctx->s[3])); + STORE(out4, BYTESWAP(ctx->s[4])); + STORE(out5, BYTESWAP(ctx->s[5])); + STORE(out6, BYTESWAP(ctx->s[6])); + STORE(out7, BYTESWAP(ctx->s[7])); +} + +void sha256_transform8x(sha256x8ctx *ctx, + const unsigned char *data0, + const unsigned char *data1, + const unsigned char *data2, + const unsigned char *data3, + const unsigned char *data4, + const unsigned char *data5, + const unsigned char *data6, + const unsigned char *data7) { + u256 s[8], w[64], T0, T1; + + // Load words and transform data correctly + w[0] = BYTESWAP(LOAD(data0)); + w[0 + 8] = BYTESWAP(LOAD(data0 + 32)); + w[1] = BYTESWAP(LOAD(data1)); + w[1 + 8] = BYTESWAP(LOAD(data1 + 32)); + w[2] = BYTESWAP(LOAD(data2)); + w[2 + 8] = BYTESWAP(LOAD(data2 + 32)); + w[3] = BYTESWAP(LOAD(data3)); + w[3 + 8] = BYTESWAP(LOAD(data3 + 32)); + w[4] = BYTESWAP(LOAD(data4)); + w[4 + 8] = BYTESWAP(LOAD(data4 + 32)); + w[5] = BYTESWAP(LOAD(data5)); + w[5 + 8] = BYTESWAP(LOAD(data5 + 32)); + w[6] = BYTESWAP(LOAD(data6)); + w[6 + 8] = BYTESWAP(LOAD(data6 + 32)); + w[7] = BYTESWAP(LOAD(data7)); + w[7 + 8] = BYTESWAP(LOAD(data7 + 32)); + + transpose(w); + transpose(w + 8); + + // Initial State + s[0] = ctx->s[0]; + s[1] = ctx->s[1]; + s[2] = ctx->s[2]; + s[3] = ctx->s[3]; + s[4] = ctx->s[4]; + s[5] = ctx->s[5]; + s[6] = ctx->s[6]; + s[7] = ctx->s[7]; + + SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 0, w[0]); + SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 1, w[1]); + SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 2, w[2]); + SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 3, w[3]); + SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 4, w[4]); + SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 5, w[5]); + SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 6, w[6]); + SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 7, w[7]); + SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 8, w[8]); + SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 9, w[9]); + SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 10, w[10]); + SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 11, w[11]); + SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 12, w[12]); + SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 13, w[13]); + SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 14, w[14]); + SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 15, w[15]); + w[16] = ADD4_32(WSIGMA1_AVX(w[14]), w[0], w[9], WSIGMA0_AVX(w[1])); + SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 16, w[16]); + w[17] = ADD4_32(WSIGMA1_AVX(w[15]), w[1], w[10], WSIGMA0_AVX(w[2])); + SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 17, w[17]); + w[18] = ADD4_32(WSIGMA1_AVX(w[16]), w[2], w[11], WSIGMA0_AVX(w[3])); + SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 18, w[18]); + w[19] = ADD4_32(WSIGMA1_AVX(w[17]), w[3], w[12], WSIGMA0_AVX(w[4])); + SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 19, w[19]); + w[20] = ADD4_32(WSIGMA1_AVX(w[18]), w[4], w[13], WSIGMA0_AVX(w[5])); + SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 20, w[20]); + w[21] = ADD4_32(WSIGMA1_AVX(w[19]), w[5], w[14], WSIGMA0_AVX(w[6])); + SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 21, w[21]); + w[22] = ADD4_32(WSIGMA1_AVX(w[20]), w[6], w[15], WSIGMA0_AVX(w[7])); + SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 22, w[22]); + w[23] = ADD4_32(WSIGMA1_AVX(w[21]), w[7], w[16], WSIGMA0_AVX(w[8])); + SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 23, w[23]); + w[24] = ADD4_32(WSIGMA1_AVX(w[22]), w[8], w[17], WSIGMA0_AVX(w[9])); + SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 24, w[24]); + w[25] = ADD4_32(WSIGMA1_AVX(w[23]), w[9], w[18], WSIGMA0_AVX(w[10])); + SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 25, w[25]); + w[26] = ADD4_32(WSIGMA1_AVX(w[24]), w[10], w[19], WSIGMA0_AVX(w[11])); + SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 26, w[26]); + w[27] = ADD4_32(WSIGMA1_AVX(w[25]), w[11], w[20], WSIGMA0_AVX(w[12])); + SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 27, w[27]); + w[28] = ADD4_32(WSIGMA1_AVX(w[26]), w[12], w[21], WSIGMA0_AVX(w[13])); + SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 28, w[28]); + w[29] = ADD4_32(WSIGMA1_AVX(w[27]), w[13], w[22], WSIGMA0_AVX(w[14])); + SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 29, w[29]); + w[30] = ADD4_32(WSIGMA1_AVX(w[28]), w[14], w[23], WSIGMA0_AVX(w[15])); + SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 30, w[30]); + w[31] = ADD4_32(WSIGMA1_AVX(w[29]), w[15], w[24], WSIGMA0_AVX(w[16])); + SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 31, w[31]); + w[32] = ADD4_32(WSIGMA1_AVX(w[30]), w[16], w[25], WSIGMA0_AVX(w[17])); + SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 32, w[32]); + w[33] = ADD4_32(WSIGMA1_AVX(w[31]), w[17], w[26], WSIGMA0_AVX(w[18])); + SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 33, w[33]); + w[34] = ADD4_32(WSIGMA1_AVX(w[32]), w[18], w[27], WSIGMA0_AVX(w[19])); + SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 34, w[34]); + w[35] = ADD4_32(WSIGMA1_AVX(w[33]), w[19], w[28], WSIGMA0_AVX(w[20])); + SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 35, w[35]); + w[36] = ADD4_32(WSIGMA1_AVX(w[34]), w[20], w[29], WSIGMA0_AVX(w[21])); + SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 36, w[36]); + w[37] = ADD4_32(WSIGMA1_AVX(w[35]), w[21], w[30], WSIGMA0_AVX(w[22])); + SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 37, w[37]); + w[38] = ADD4_32(WSIGMA1_AVX(w[36]), w[22], w[31], WSIGMA0_AVX(w[23])); + SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 38, w[38]); + w[39] = ADD4_32(WSIGMA1_AVX(w[37]), w[23], w[32], WSIGMA0_AVX(w[24])); + SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 39, w[39]); + w[40] = ADD4_32(WSIGMA1_AVX(w[38]), w[24], w[33], WSIGMA0_AVX(w[25])); + SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 40, w[40]); + w[41] = ADD4_32(WSIGMA1_AVX(w[39]), w[25], w[34], WSIGMA0_AVX(w[26])); + SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 41, w[41]); + w[42] = ADD4_32(WSIGMA1_AVX(w[40]), w[26], w[35], WSIGMA0_AVX(w[27])); + SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 42, w[42]); + w[43] = ADD4_32(WSIGMA1_AVX(w[41]), w[27], w[36], WSIGMA0_AVX(w[28])); + SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 43, w[43]); + w[44] = ADD4_32(WSIGMA1_AVX(w[42]), w[28], w[37], WSIGMA0_AVX(w[29])); + SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 44, w[44]); + w[45] = ADD4_32(WSIGMA1_AVX(w[43]), w[29], w[38], WSIGMA0_AVX(w[30])); + SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 45, w[45]); + w[46] = ADD4_32(WSIGMA1_AVX(w[44]), w[30], w[39], WSIGMA0_AVX(w[31])); + SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 46, w[46]); + w[47] = ADD4_32(WSIGMA1_AVX(w[45]), w[31], w[40], WSIGMA0_AVX(w[32])); + SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 47, w[47]); + w[48] = ADD4_32(WSIGMA1_AVX(w[46]), w[32], w[41], WSIGMA0_AVX(w[33])); + SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 48, w[48]); + w[49] = ADD4_32(WSIGMA1_AVX(w[47]), w[33], w[42], WSIGMA0_AVX(w[34])); + SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 49, w[49]); + w[50] = ADD4_32(WSIGMA1_AVX(w[48]), w[34], w[43], WSIGMA0_AVX(w[35])); + SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 50, w[50]); + w[51] = ADD4_32(WSIGMA1_AVX(w[49]), w[35], w[44], WSIGMA0_AVX(w[36])); + SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 51, w[51]); + w[52] = ADD4_32(WSIGMA1_AVX(w[50]), w[36], w[45], WSIGMA0_AVX(w[37])); + SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 52, w[52]); + w[53] = ADD4_32(WSIGMA1_AVX(w[51]), w[37], w[46], WSIGMA0_AVX(w[38])); + SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 53, w[53]); + w[54] = ADD4_32(WSIGMA1_AVX(w[52]), w[38], w[47], WSIGMA0_AVX(w[39])); + SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 54, w[54]); + w[55] = ADD4_32(WSIGMA1_AVX(w[53]), w[39], w[48], WSIGMA0_AVX(w[40])); + SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 55, w[55]); + w[56] = ADD4_32(WSIGMA1_AVX(w[54]), w[40], w[49], WSIGMA0_AVX(w[41])); + SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 56, w[56]); + w[57] = ADD4_32(WSIGMA1_AVX(w[55]), w[41], w[50], WSIGMA0_AVX(w[42])); + SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 57, w[57]); + w[58] = ADD4_32(WSIGMA1_AVX(w[56]), w[42], w[51], WSIGMA0_AVX(w[43])); + SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 58, w[58]); + w[59] = ADD4_32(WSIGMA1_AVX(w[57]), w[43], w[52], WSIGMA0_AVX(w[44])); + SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 59, w[59]); + w[60] = ADD4_32(WSIGMA1_AVX(w[58]), w[44], w[53], WSIGMA0_AVX(w[45])); + SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 60, w[60]); + w[61] = ADD4_32(WSIGMA1_AVX(w[59]), w[45], w[54], WSIGMA0_AVX(w[46])); + SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 61, w[61]); + w[62] = ADD4_32(WSIGMA1_AVX(w[60]), w[46], w[55], WSIGMA0_AVX(w[47])); + SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 62, w[62]); + w[63] = ADD4_32(WSIGMA1_AVX(w[61]), w[47], w[56], WSIGMA0_AVX(w[48])); + SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 63, w[63]); + + // Feed Forward + ctx->s[0] = ADD32(s[0], ctx->s[0]); + ctx->s[1] = ADD32(s[1], ctx->s[1]); + ctx->s[2] = ADD32(s[2], ctx->s[2]); + ctx->s[3] = ADD32(s[3], ctx->s[3]); + ctx->s[4] = ADD32(s[4], ctx->s[4]); + ctx->s[5] = ADD32(s[5], ctx->s[5]); + ctx->s[6] = ADD32(s[6], ctx->s[6]); + ctx->s[7] = ADD32(s[7], ctx->s[7]); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/sha256avx.h b/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/sha256avx.h new file mode 100644 index 0000000000..1e3bcf889b --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/sha256avx.h @@ -0,0 +1,44 @@ +#ifndef SHA256AVX_H +#define SHA256AVX_H + +#include +#include + +#include "params.h" + +typedef struct SHA256state { + __m256i s[8]; + unsigned char msgblocks[8 * 64]; + unsigned int datalen; + unsigned long long msglen; +} sha256x8ctx; + +#define sha256_ctx_clone8x SPX_NAMESPACE(sha256_ctx_clone8x) +void sha256_ctx_clone8x(sha256x8ctx *out, const sha256x8ctx *in); + +#define sha256_init8x SPX_NAMESPACE(sha256_init8x) +void sha256_init8x(sha256x8ctx *ctx); + +#define sha256_final8x SPX_NAMESPACE(sha256_final8x) +void sha256_final8x(sha256x8ctx *ctx, + unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7); + +#define sha256_transform8x SPX_NAMESPACE(sha256_transform8x) +void sha256_transform8x(sha256x8ctx *ctx, + const unsigned char *data0, + const unsigned char *data1, + const unsigned char *data2, + const unsigned char *data3, + const unsigned char *data4, + const unsigned char *data5, + const unsigned char *data6, + const unsigned char *data7); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/sha256x8.c b/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/sha256x8.c new file mode 100644 index 0000000000..d97750c09b --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/sha256x8.c @@ -0,0 +1,185 @@ +#include + +#include "sha256avx.h" +#include "sha256x8.h" +#include "utils.h" + +// Performs sha256x8 on an initialized (and perhaps seeded) state. +static void _sha256x8( + sha256x8ctx *ctx, + unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, unsigned long long inlen) { + unsigned long long i = 0; + while (inlen - i >= 64) { + sha256_transform8x(ctx, + in0 + i, + in1 + i, + in2 + i, + in3 + i, + in4 + i, + in5 + i, + in6 + i, + in7 + i + ); + i += 64; + ctx->msglen += 512; + } + + size_t bytes_to_copy = (size_t)(inlen - i); + memcpy(&ctx->msgblocks[64 * 0], in0 + i, bytes_to_copy); + memcpy(&ctx->msgblocks[64 * 1], in1 + i, bytes_to_copy); + memcpy(&ctx->msgblocks[64 * 2], in2 + i, bytes_to_copy); + memcpy(&ctx->msgblocks[64 * 3], in3 + i, bytes_to_copy); + memcpy(&ctx->msgblocks[64 * 4], in4 + i, bytes_to_copy); + memcpy(&ctx->msgblocks[64 * 5], in5 + i, bytes_to_copy); + memcpy(&ctx->msgblocks[64 * 6], in6 + i, bytes_to_copy); + memcpy(&ctx->msgblocks[64 * 7], in7 + i, bytes_to_copy); + ctx->datalen = (unsigned int)bytes_to_copy; + + sha256_final8x(ctx, out0, out1, out2, out3, out4, out5, out6, out7); +} + +void sha256x8_seeded( + unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const sha256x8ctx *seed, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, unsigned long long inlen) { + + sha256x8ctx ctx; + sha256_ctx_clone8x(&ctx, seed); + + _sha256x8(&ctx, out0, out1, out2, out3, out4, out5, out6, out7, + in0, in1, in2, in3, in4, in5, in6, in7, inlen); +} + +/* This provides a wrapper around the internals of 8x parallel SHA256 */ +void sha256x8(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, unsigned long long inlen) { + sha256x8ctx ctx; + sha256_init8x(&ctx); + + _sha256x8(&ctx, out0, out1, out2, out3, out4, out5, out6, out7, + in0, in1, in2, in3, in4, in5, in6, in7, inlen); +} + +/** + * Note that inlen should be sufficiently small that it still allows for + * an array to be allocated on the stack. Typically 'in' is merely a seed. + * Outputs outlen number of bytes + */ +void mgf1x8(unsigned char *outx8, unsigned long outlen, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, + unsigned long inlen) { + PQCLEAN_VLA(unsigned char, inbufx8, 8 * (inlen + 4)); + unsigned char outbufx8[8 * SPX_SHA256_OUTPUT_BYTES]; + uint32_t i; + unsigned int j; + + memcpy(inbufx8 + 0 * (inlen + 4), in0, inlen); + memcpy(inbufx8 + 1 * (inlen + 4), in1, inlen); + memcpy(inbufx8 + 2 * (inlen + 4), in2, inlen); + memcpy(inbufx8 + 3 * (inlen + 4), in3, inlen); + memcpy(inbufx8 + 4 * (inlen + 4), in4, inlen); + memcpy(inbufx8 + 5 * (inlen + 4), in5, inlen); + memcpy(inbufx8 + 6 * (inlen + 4), in6, inlen); + memcpy(inbufx8 + 7 * (inlen + 4), in7, inlen); + + /* While we can fit in at least another full block of SHA256 output.. */ + for (i = 0; (i + 1)*SPX_SHA256_OUTPUT_BYTES <= outlen; i++) { + for (j = 0; j < 8; j++) { + u32_to_bytes(inbufx8 + inlen + j * (inlen + 4), i); + } + + sha256x8(outx8 + 0 * outlen, + outx8 + 1 * outlen, + outx8 + 2 * outlen, + outx8 + 3 * outlen, + outx8 + 4 * outlen, + outx8 + 5 * outlen, + outx8 + 6 * outlen, + outx8 + 7 * outlen, + inbufx8 + 0 * (inlen + 4), + inbufx8 + 1 * (inlen + 4), + inbufx8 + 2 * (inlen + 4), + inbufx8 + 3 * (inlen + 4), + inbufx8 + 4 * (inlen + 4), + inbufx8 + 5 * (inlen + 4), + inbufx8 + 6 * (inlen + 4), + inbufx8 + 7 * (inlen + 4), inlen + 4); + outx8 += SPX_SHA256_OUTPUT_BYTES; + } + /* Until we cannot anymore, and we fill the remainder. */ + for (j = 0; j < 8; j++) { + u32_to_bytes(inbufx8 + inlen + j * (inlen + 4), i); + } + sha256x8(outbufx8 + 0 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 1 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 2 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 3 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 4 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 5 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 6 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 7 * SPX_SHA256_OUTPUT_BYTES, + inbufx8 + 0 * (inlen + 4), + inbufx8 + 1 * (inlen + 4), + inbufx8 + 2 * (inlen + 4), + inbufx8 + 3 * (inlen + 4), + inbufx8 + 4 * (inlen + 4), + inbufx8 + 5 * (inlen + 4), + inbufx8 + 6 * (inlen + 4), + inbufx8 + 7 * (inlen + 4), inlen + 4); + + for (j = 0; j < 8; j++) { + memcpy(outx8 + j * outlen, + outbufx8 + j * SPX_SHA256_OUTPUT_BYTES, + outlen - i * SPX_SHA256_OUTPUT_BYTES); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/sha256x8.h b/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/sha256x8.h new file mode 100644 index 0000000000..4f7330a6c1 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/sha256x8.h @@ -0,0 +1,64 @@ +#ifndef SPX_SHA256X8_H +#define SPX_SHA256X8_H + +#include "params.h" +#include "sha256avx.h" + + + +#define sha256x8_seeded SPX_NAMESPACE(sha256x8_seeded) +void sha256x8_seeded( + unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const sha256x8ctx *seed, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, unsigned long long inlen); + +/* This provides a wrapper around the internals of 8x parallel SHA256 */ +#define sha256x8 SPX_NAMESPACE(sha256x8) +void sha256x8(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, unsigned long long inlen); + +/** + * Note that inlen should be sufficiently small that it still allows for + * an array to be allocated on the stack. Typically 'in' is merely a seed. + * Outputs outlen number of bytes + */ +#define mgf1x8 SPX_NAMESPACE(mgf1x8) +void mgf1x8(unsigned char *outx8, unsigned long outlen, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, + unsigned long inlen); +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/sha2_offsets.h b/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/sha2_offsets.h new file mode 100644 index 0000000000..6e3584f7a4 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/sha2_offsets.h @@ -0,0 +1,27 @@ +#ifndef SHA2_OFFSETS_H_ +#define SHA2_OFFSETS_H_ + +#define SPX_SHA256_BLOCK_BYTES 64 +#define SPX_SHA256_OUTPUT_BYTES 32 + +#define SPX_SHA512_BLOCK_BYTES 128 +#define SPX_SHA512_OUTPUT_BYTES 64 + +/* + * Offsets of various fields in the address structure when we use SHA2 as + * the Sphincs+ hash function + */ + +#define SPX_OFFSET_LAYER 0 /* The byte used to specify the Merkle tree layer */ +#define SPX_OFFSET_TREE 1 /* The start of the 8 byte field used to specify the tree */ +#define SPX_OFFSET_TYPE 9 /* The byte used to specify the hash type (reason) */ +#define SPX_OFFSET_KP_ADDR2 12 /* The high byte used to specify the key pair (which one-time signature) */ +#define SPX_OFFSET_KP_ADDR1 13 /* The low byte used to specify the key pair */ +#define SPX_OFFSET_CHAIN_ADDR 17 /* The byte used to specify the chain address (which Winternitz chain) */ +#define SPX_OFFSET_HASH_ADDR 21 /* The byte used to specify the hash address (where in the Winternitz chain) */ +#define SPX_OFFSET_TREE_HGT 17 /* The byte used to specify the height of this node in the FORS or Merkle tree */ +#define SPX_OFFSET_TREE_INDEX 18 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ + +#define SPX_SHA2 1 + +#endif /* SHA2_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/sha512x4.c b/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/sha512x4.c new file mode 100644 index 0000000000..8d33deffdd --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/sha512x4.c @@ -0,0 +1,446 @@ +#include +#include +#include + +/* pull in the entire thing */ +#include "sha512x4.h" +#include "utils.h" + +typedef uint64_t u64; +typedef __m256i u256; + +#define BYTESWAP(x) _mm256_shuffle_epi8(x, _mm256_set_epi8(0x8,0x9,0xa,0xb,0xc,0xd,0xe,0xf,0x0,0x1,0x2,0x3,0x4,0x5,0x6,0x7,0x8,0x9,0xa,0xb,0xc,0xd,0xe,0xf,0x0,0x1,0x2,0x3,0x4,0x5,0x6,0x7)) +#define STORE(dest,src) _mm256_storeu_si256((__m256i *)(dest),src) + +// Transpose 4 vectors containing 64-bit values +// That is, it rearranges the array: +// A B C D +// E F G H +// I J K L +// M N O P +// into +// A E I M +// B F J N +// C G K O +// D H L P +// where each letter stands for 64 bits (and lsbits on the left) +static void transpose(u256 s[4]) { + u256 tmp[4]; + tmp[0] = _mm256_unpacklo_epi64(s[0], s[1]); + tmp[1] = _mm256_unpackhi_epi64(s[0], s[1]); + tmp[2] = _mm256_unpacklo_epi64(s[2], s[3]); + tmp[3] = _mm256_unpackhi_epi64(s[2], s[3]); + // tmp is in the order of + // A E C G + // B F D H + // I M K O + // J N L P + s[0] = _mm256_permute2x128_si256(tmp[0], tmp[2], 0x20); + s[1] = _mm256_permute2x128_si256(tmp[1], tmp[3], 0x20); + s[2] = _mm256_permute2x128_si256(tmp[0], tmp[2], 0x31); + s[3] = _mm256_permute2x128_si256(tmp[1], tmp[3], 0x31); +} + + +void sha512_init4x(sha512x4ctx *ctx) { +#define SET4(x) _mm256_set_epi64x((long long)(x), (long long)(x), (long long)(x), (long long)(x)) + ctx->s[0] = SET4(0x6a09e667f3bcc908ULL); + ctx->s[1] = SET4(0xbb67ae8584caa73bULL); + ctx->s[2] = SET4(0x3c6ef372fe94f82bULL); + ctx->s[3] = SET4(0xa54ff53a5f1d36f1ULL); + ctx->s[4] = SET4(0x510e527fade682d1ULL); + ctx->s[5] = SET4(0x9b05688c2b3e6c1fULL); + ctx->s[6] = SET4(0x1f83d9abfb41bd6bULL); + ctx->s[7] = SET4(0x5be0cd19137e2179ULL); +#undef SET4 + + ctx->datalen = 0; + ctx->msglen = 0; +} + +#define XOR _mm256_xor_si256 +#define OR _mm256_or_si256 +#define AND _mm256_and_si256 +#define ADD64 _mm256_add_epi64 + +#define LOAD(src) _mm256_loadu_si256((__m256i *)(src)) + +#define SHIFTR64(x, y) _mm256_srli_epi64(x, y) +#define SHIFTL64(x, y) _mm256_slli_epi64(x, y) + +#define ROTR64(x, y) OR(SHIFTR64(x, y), SHIFTL64(x, 64 - (y))) + +static u256 XOR3(u256 a, u256 b, u256 c) { + return XOR(XOR(a, b), c); +} + +#define ADD3_64(a, b, c) ADD64(ADD64(a, b), c) +#define ADD4_64(a, b, c, d) ADD64(ADD64(ADD64(a, b), c), d) +#define ADD5_64(a, b, c, d, e) ADD64(ADD64(ADD64(ADD64(a, b), c), d), e) + +static u256 MAJ_AVX(u256 a, u256 b, u256 c) { + return XOR(c, AND(XOR(a, c), XOR(b, c))); +} +static u256 CH_AVX(u256 a, u256 b, u256 c) { + return XOR(c, AND(a, XOR(b, c))); +} +static u256 SIGMA0_AVX(u256 x) { + return XOR3(ROTR64(x, 28), ROTR64(x, 34), ROTR64(x, 39)); +} +static u256 SIGMA1_AVX(u256 x) { + return XOR3(ROTR64(x, 14), ROTR64(x, 18), ROTR64(x, 41)); +} +static u256 GAMMA0_AVX(u256 x) { + return XOR3(ROTR64(x, 1), ROTR64(x, 8), SHIFTR64(x, 7)); +} +static u256 GAMMA1_AVX(u256 x) { + return XOR3(ROTR64(x, 19), ROTR64(x, 61), SHIFTR64(x, 6)); +} + +#define SHA512ROUND_AVX(a, b, c, d, e, f, g, h, rc, w) \ + T0 = ADD5_64(h, w, SIGMA1_AVX(e), CH_AVX(e, f, g), _mm256_set1_epi64x((long long)RC[rc])); \ + T1 = ADD64(SIGMA0_AVX(a), MAJ_AVX(a, b, c)); \ + (d) = ADD64(d, T0); \ + (h) = ADD64(T0, T1); + +static const unsigned long long RC[80] = { + 0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL, + 0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL, + 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL, + 0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL, + 0xd807aa98a3030242ULL, 0x12835b0145706fbeULL, + 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL, + 0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL, + 0x9bdc06a725c71235ULL, 0xc19bf174cf692694ULL, + 0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL, + 0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL, + 0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL, + 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL, + 0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL, + 0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL, + 0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL, + 0x06ca6351e003826fULL, 0x142929670a0e6e70ULL, + 0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL, + 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL, + 0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL, + 0x81c2c92e47edaee6ULL, 0x92722c851482353bULL, + 0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL, + 0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL, + 0xd192e819d6ef5218ULL, 0xd69906245565a910ULL, + 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL, + 0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL, + 0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL, + 0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL, + 0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL, + 0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL, + 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL, + 0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL, + 0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL, + 0xca273eceea26619cULL, 0xd186b8c721c0c207ULL, + 0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL, + 0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL, + 0x113f9804bef90daeULL, 0x1b710b35131c471bULL, + 0x28db77f523047d84ULL, 0x32caab7b40c72493ULL, + 0x3c9ebe0a15c9bebcULL, 0x431d67c49c100d4cULL, + 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL, + 0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL, +}; + +void sha512_transform4x( + sha512x4ctx *ctx, + const unsigned char *d0, + const unsigned char *d1, + const unsigned char *d2, + const unsigned char *d3) { + u256 s0, s1, s2, s3, s4, s5, s6, s7, w[16], T0, T1, nw; + + // Load words and transform data correctly + w[0 ] = BYTESWAP(LOAD(d0 )); + w[0 + 4] = BYTESWAP(LOAD(d0 + 32)); + w[0 + 8] = BYTESWAP(LOAD(d0 + 64)); + w[0 + 12] = BYTESWAP(LOAD(d0 + 96)); + + w[1 ] = BYTESWAP(LOAD(d1 )); + w[1 + 4] = BYTESWAP(LOAD(d1 + 32)); + w[1 + 8] = BYTESWAP(LOAD(d1 + 64)); + w[1 + 12] = BYTESWAP(LOAD(d1 + 96)); + + w[2 ] = BYTESWAP(LOAD(d2 )); + w[2 + 4] = BYTESWAP(LOAD(d2 + 32)); + w[2 + 8] = BYTESWAP(LOAD(d2 + 64)); + w[2 + 12] = BYTESWAP(LOAD(d2 + 96)); + + w[3 ] = BYTESWAP(LOAD(d3 )); + w[3 + 4] = BYTESWAP(LOAD(d3 + 32)); + w[3 + 8] = BYTESWAP(LOAD(d3 + 64)); + w[3 + 12] = BYTESWAP(LOAD(d3 + 96)); + + transpose(w); + transpose(w + 4); + transpose(w + 8); + transpose(w + 12); + + // Initial State + s0 = ctx->s[0]; + s1 = ctx->s[1]; + s2 = ctx->s[2]; + s3 = ctx->s[3]; + s4 = ctx->s[4]; + s5 = ctx->s[5]; + s6 = ctx->s[6]; + s7 = ctx->s[7]; + + // The first 16 rounds (where the w inputs are directly from the data) + SHA512ROUND_AVX(s0, s1, s2, s3, s4, s5, s6, s7, 0, w[0]); + SHA512ROUND_AVX(s7, s0, s1, s2, s3, s4, s5, s6, 1, w[1]); + SHA512ROUND_AVX(s6, s7, s0, s1, s2, s3, s4, s5, 2, w[2]); + SHA512ROUND_AVX(s5, s6, s7, s0, s1, s2, s3, s4, 3, w[3]); + SHA512ROUND_AVX(s4, s5, s6, s7, s0, s1, s2, s3, 4, w[4]); + SHA512ROUND_AVX(s3, s4, s5, s6, s7, s0, s1, s2, 5, w[5]); + SHA512ROUND_AVX(s2, s3, s4, s5, s6, s7, s0, s1, 6, w[6]); + SHA512ROUND_AVX(s1, s2, s3, s4, s5, s6, s7, s0, 7, w[7]); + SHA512ROUND_AVX(s0, s1, s2, s3, s4, s5, s6, s7, 8, w[8]); + SHA512ROUND_AVX(s7, s0, s1, s2, s3, s4, s5, s6, 9, w[9]); + SHA512ROUND_AVX(s6, s7, s0, s1, s2, s3, s4, s5, 10, w[10]); + SHA512ROUND_AVX(s5, s6, s7, s0, s1, s2, s3, s4, 11, w[11]); + SHA512ROUND_AVX(s4, s5, s6, s7, s0, s1, s2, s3, 12, w[12]); + SHA512ROUND_AVX(s3, s4, s5, s6, s7, s0, s1, s2, 13, w[13]); + SHA512ROUND_AVX(s2, s3, s4, s5, s6, s7, s0, s1, 14, w[14]); + SHA512ROUND_AVX(s1, s2, s3, s4, s5, s6, s7, s0, 15, w[15]); + +#define M(i) (((i)+16) & 0xf) +#define NextW(i) \ + w[M(i)] = ADD4_64(GAMMA1_AVX(w[M((i)-2)]), w[M((i)-7)], GAMMA0_AVX(w[M((i)-15)]), w[M((i)-16)]); + + // The remaining 64 rounds (where the w inputs are a linear fix of the data) + for (unsigned i = 16; i < 80; i += 16) { + nw = NextW(0); + SHA512ROUND_AVX(s0, s1, s2, s3, s4, s5, s6, s7, i + 0, nw); + nw = NextW(1); + SHA512ROUND_AVX(s7, s0, s1, s2, s3, s4, s5, s6, i + 1, nw); + nw = NextW(2); + SHA512ROUND_AVX(s6, s7, s0, s1, s2, s3, s4, s5, i + 2, nw); + nw = NextW(3); + SHA512ROUND_AVX(s5, s6, s7, s0, s1, s2, s3, s4, i + 3, nw); + nw = NextW(4); + SHA512ROUND_AVX(s4, s5, s6, s7, s0, s1, s2, s3, i + 4, nw); + nw = NextW(5); + SHA512ROUND_AVX(s3, s4, s5, s6, s7, s0, s1, s2, i + 5, nw); + nw = NextW(6); + SHA512ROUND_AVX(s2, s3, s4, s5, s6, s7, s0, s1, i + 6, nw); + nw = NextW(7); + SHA512ROUND_AVX(s1, s2, s3, s4, s5, s6, s7, s0, i + 7, nw); + nw = NextW(8); + SHA512ROUND_AVX(s0, s1, s2, s3, s4, s5, s6, s7, i + 8, nw); + nw = NextW(9); + SHA512ROUND_AVX(s7, s0, s1, s2, s3, s4, s5, s6, i + 9, nw); + nw = NextW(10); + SHA512ROUND_AVX(s6, s7, s0, s1, s2, s3, s4, s5, i + 10, nw); + nw = NextW(11); + SHA512ROUND_AVX(s5, s6, s7, s0, s1, s2, s3, s4, i + 11, nw); + nw = NextW(12); + SHA512ROUND_AVX(s4, s5, s6, s7, s0, s1, s2, s3, i + 12, nw); + nw = NextW(13); + SHA512ROUND_AVX(s3, s4, s5, s6, s7, s0, s1, s2, i + 13, nw); + nw = NextW(14); + SHA512ROUND_AVX(s2, s3, s4, s5, s6, s7, s0, s1, i + 14, nw); + nw = NextW(15); + SHA512ROUND_AVX(s1, s2, s3, s4, s5, s6, s7, s0, i + 15, nw); + } + + // Feed Forward + ctx->s[0] = ADD64(s0, ctx->s[0]); + ctx->s[1] = ADD64(s1, ctx->s[1]); + ctx->s[2] = ADD64(s2, ctx->s[2]); + ctx->s[3] = ADD64(s3, ctx->s[3]); + ctx->s[4] = ADD64(s4, ctx->s[4]); + ctx->s[5] = ADD64(s5, ctx->s[5]); + ctx->s[6] = ADD64(s6, ctx->s[6]); + ctx->s[7] = ADD64(s7, ctx->s[7]); +} + +static void _sha512x4( + sha512x4ctx *ctx, + unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + unsigned long long inlen) { + unsigned int i = 0; + + while (inlen - i >= 128) { + sha512_transform4x( + ctx, + in0 + i, + in1 + i, + in2 + i, + in3 + i + ); + ctx->msglen += 1024; + i += 128; + } + + ctx->datalen = (unsigned int)(inlen - i); + memcpy(&ctx->msgblocks[128 * 0], in0 + i, ctx->datalen); + memcpy(&ctx->msgblocks[128 * 1], in1 + i, ctx->datalen); + memcpy(&ctx->msgblocks[128 * 2], in2 + i, ctx->datalen); + memcpy(&ctx->msgblocks[128 * 3], in3 + i, ctx->datalen); + + // Padding + unsigned long curlen; + if (ctx->datalen < 112) { + for (i = 0; i < 4; ++i) { + curlen = ctx->datalen; + ctx->msgblocks[128 * i + curlen++] = 0x80; + while (curlen < 128) { + ctx->msgblocks[128 * i + curlen++] = 0x00; + } + } + } else { + for (i = 0; i < 4; ++i) { + curlen = ctx->datalen; + ctx->msgblocks[128 * i + curlen++] = 0x80; + while (curlen < 128) { + ctx->msgblocks[128 * i + curlen++] = 0x00; + } + } + sha512_transform4x( + ctx, + ctx->msgblocks, + ctx->msgblocks + 128, + ctx->msgblocks + 256, + ctx->msgblocks + 384 + ); + memset(ctx->msgblocks, 0, 4 * 128); + } + + // Add length of the message to each block + ctx->msglen += (unsigned long long)(ctx->datalen) * 8; + for (i = 0; i < 4; i++) { + ctx->msgblocks[128 * i + 127] = (unsigned char)(ctx->msglen); + ctx->msgblocks[128 * i + 126] = (unsigned char)(ctx->msglen >> 8); + ctx->msgblocks[128 * i + 125] = (unsigned char)(ctx->msglen >> 16); + ctx->msgblocks[128 * i + 124] = (unsigned char)(ctx->msglen >> 24); + ctx->msgblocks[128 * i + 123] = (unsigned char)(ctx->msglen >> 32); + ctx->msgblocks[128 * i + 122] = (unsigned char)(ctx->msglen >> 40); + ctx->msgblocks[128 * i + 121] = (unsigned char)(ctx->msglen >> 48); + ctx->msgblocks[128 * i + 120] = (unsigned char)(ctx->msglen >> 56); + memset( &ctx->msgblocks[128 * i + 112], 0, 8 ); + } + sha512_transform4x( + ctx, + ctx->msgblocks, + ctx->msgblocks + 128, + ctx->msgblocks + 256, + ctx->msgblocks + 384 + ); + + // Compute final hash output + transpose(ctx->s); + transpose(ctx->s + 4); + + // Store Hash value + __m256i out[2]; + STORE(out, BYTESWAP(ctx->s[0])); + STORE(out + 1, BYTESWAP(ctx->s[4])); + memcpy(out0, out, 64); + + STORE(out, BYTESWAP(ctx->s[1])); + STORE(out + 1, BYTESWAP(ctx->s[5])); + memcpy(out1, out, 64); + + STORE(out, BYTESWAP(ctx->s[2])); + STORE(out + 1, BYTESWAP(ctx->s[6])); + memcpy(out2, out, 64); + + STORE(out, BYTESWAP(ctx->s[3])); + STORE(out + 1, BYTESWAP(ctx->s[7])); + memcpy(out3, out, 64); +} + + +/** + * Note that inlen should be sufficiently small that it still allows for + * an array to be allocated on the stack. Typically 'in' is merely a seed. + * Outputs outlen number of bytes + */ +void mgf1x4_512(unsigned char *outx4, unsigned long outlen, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + unsigned long inlen) { + PQCLEAN_VLA(unsigned char, inbufx4, 4 * (inlen + 4)); + unsigned char outbuf[4 * 64]; + uint32_t i; + unsigned int j; + + memcpy(inbufx4 + 0 * (inlen + 4), in0, inlen); + memcpy(inbufx4 + 1 * (inlen + 4), in1, inlen); + memcpy(inbufx4 + 2 * (inlen + 4), in2, inlen); + memcpy(inbufx4 + 3 * (inlen + 4), in3, inlen); + + /* While we can fit in at least another full block of SHA512 output.. */ + unsigned long remaining = outlen; + for (i = 0; remaining > 0; i++) { + unsigned long this_step = SPX_SHA512_OUTPUT_BYTES; + if (this_step > remaining) { + this_step = remaining; + } + remaining -= this_step; + for (j = 0; j < 4; j++) { + u32_to_bytes(inbufx4 + inlen + j * (inlen + 4), i); + } + + sha512x4ctx ctx; + sha512_init4x(&ctx); + + _sha512x4( + &ctx, + outbuf + 0 * 64, + outbuf + 1 * 64, + outbuf + 2 * 64, + outbuf + 3 * 64, + inbufx4 + 0 * (inlen + 4), + inbufx4 + 1 * (inlen + 4), + inbufx4 + 2 * (inlen + 4), + inbufx4 + 3 * (inlen + 4), + inlen + 4 + ); + + memcpy(outx4 + 0 * outlen, outbuf + 0 * 64, this_step); + memcpy(outx4 + 1 * outlen, outbuf + 1 * 64, this_step); + memcpy(outx4 + 2 * outlen, outbuf + 2 * 64, this_step); + memcpy(outx4 + 3 * outlen, outbuf + 3 * 64, this_step); + outx4 += this_step; + } +} + +void sha512x4_seeded( + unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const sha512x4ctx *seed, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + unsigned long long inlen) { + sha512x4ctx ctx; + sha512_ctx_clone4x(&ctx, seed); + _sha512x4( + &ctx, + out0, out1, out2, out3, + in0, in1, in2, in3, + inlen + ); +} + +void sha512_ctx_clone4x(sha512x4ctx *out, const sha512x4ctx *in) { + memcpy(out, in, sizeof(sha512x4ctx)); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/sha512x4.h b/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/sha512x4.h new file mode 100644 index 0000000000..9bbe736514 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/sha512x4.h @@ -0,0 +1,58 @@ +#ifndef SHA512AVX_H +#define SHA512AVX_H + +#include +#include + + +#include "params.h" + +typedef struct SHA512state4x { + __m256i s[8]; + unsigned char msgblocks[4 * 128]; + unsigned int datalen; + unsigned long long msglen; +} sha512x4ctx; + +#define sha512_init4x SPX_NAMESPACE(sha512_init4x) +void sha512_init4x(sha512x4ctx *ctx); + +#define sha512_transform4x SPX_NAMESPACE(sha512_transform4x) +void sha512_transform4x( + sha512x4ctx *ctx, + const unsigned char *d0, + const unsigned char *d1, + const unsigned char *d2, + const unsigned char *d3); + + +#define sha512x4_seeded SPX_NAMESPACE(sha512x4_seeded) +void sha512x4_seeded( + unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const sha512x4ctx *seed, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + unsigned long long inlen); + +#define sha512_ctx_clone4x SPX_NAMESPACE(sha512_ctx_clone4x) +void sha512_ctx_clone4x(sha512x4ctx *out, const sha512x4ctx *in); + +/** + * Note that inlen should be sufficiently small that it still allows for + * an array to be allocated on the stack. Typically 'in' is merely a seed. + * Outputs outlen number of bytes + */ +#define mgf1x4_512 SPX_NAMESPACE(mgf1x4_512) +void mgf1x4_512(unsigned char *outx4, unsigned long outlen, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + unsigned long inlen); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/sign.c b/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/sign.c new file mode 100644 index 0000000000..9d0c7d1b22 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/sign.c @@ -0,0 +1,286 @@ +#include +#include +#include + +#include "address.h" +#include "context.h" +#include "fors.h" +#include "hash.h" +#include "merkle.h" +#include "nistapi.h" +#include "params.h" +#include "randombytes.h" +#include "thash.h" +#include "utils.h" +#include "wots.h" + +/* + * Returns the length of a secret key, in bytes + */ +size_t crypto_sign_secretkeybytes(void) { + return CRYPTO_SECRETKEYBYTES; +} + +/* + * Returns the length of a public key, in bytes + */ +size_t crypto_sign_publickeybytes(void) { + return CRYPTO_PUBLICKEYBYTES; +} + +/* + * Returns the length of a signature, in bytes + */ +size_t crypto_sign_bytes(void) { + return CRYPTO_BYTES; +} + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +size_t crypto_sign_seedbytes(void) { + return CRYPTO_SEEDBYTES; +} + +/* + * Generates an SPX key pair given a seed of length + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [PUB_SEED || root] + */ +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed) { + spx_ctx ctx; + + /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ + memcpy(sk, seed, CRYPTO_SEEDBYTES); + + memcpy(pk, sk + 2 * SPX_N, SPX_N); + + memcpy(ctx.pub_seed, pk, SPX_N); + memcpy(ctx.sk_seed, sk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + /* Compute root node of the top-most subtree. */ + merkle_gen_root(sk + 3 * SPX_N, &ctx); + + // cleanup + free_hash_function(&ctx); + + memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); + + return 0; +} + +/* + * Generates an SPX key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [PUB_SEED || root] + */ +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { + uint8_t seed[CRYPTO_SEEDBYTES]; + randombytes(seed, CRYPTO_SEEDBYTES); + crypto_sign_seed_keypair(pk, sk, seed); + + return 0; +} + +/** + * Returns an array containing a detached signature. + */ +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk) { + spx_ctx ctx; + + const uint8_t *sk_prf = sk + SPX_N; + const uint8_t *pk = sk + 2 * SPX_N; + + uint8_t optrand[SPX_N]; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t root[SPX_N]; + uint32_t i; + uint64_t tree; + uint32_t idx_leaf; + uint32_t wots_addr[8] = {0}; + uint32_t tree_addr[8] = {0}; + + memcpy(ctx.sk_seed, sk, SPX_N); + memcpy(ctx.pub_seed, pk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + + /* Optionally, signing can be made non-deterministic using optrand. + This can help counter side-channel attacks that would benefit from + getting a large number of traces when the signer uses the same nodes. */ + randombytes(optrand, SPX_N); + /* Compute the digest randomization value. */ + gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); + + /* Derive the message digest and leaf index from R, PK and M. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; + + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); + + /* Sign the message hash using FORS. */ + fors_sign(sig, root, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); + sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; + + /* Update the indices for the next layer. */ + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; + } + + free_hash_function(&ctx); + + *siglen = SPX_BYTES; + + return 0; +} + +/** + * Verifies a detached signature and message under a given public key. + */ +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk) { + spx_ctx ctx; + const uint8_t *pub_root = pk + SPX_N; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t wots_pk[SPX_WOTS_BYTES]; + uint8_t root[SPX_N]; + uint8_t leaf[SPX_N]; + unsigned int i; + uint64_t tree; + uint32_t idx_leaf; + uint32_t wots_addr[8] = {0}; + uint32_t tree_addr[8] = {0}; + uint32_t wots_pk_addr[8] = {0}; + + if (siglen != SPX_BYTES) { + return -1; + } + + memcpy(ctx.pub_seed, pk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); + + /* Derive the message digest and leaf index from R || PK || M. */ + /* The additional SPX_N is a result of the hash domain separator. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; + + /* Layer correctly defaults to 0, so no need to set_layer_addr */ + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); + + fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + /* For each subtree.. */ + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + copy_keypair_addr(wots_pk_addr, wots_addr); + + /* The WOTS public key is only correct if the signature was correct. */ + /* Initially, root is the FORS pk, but on subsequent iterations it is + the root of the subtree below the currently processed subtree. */ + wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); + sig += SPX_WOTS_BYTES; + + /* Compute the leaf node using the WOTS public key. */ + thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); + + /* Compute the root node of this subtree. */ + compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, + &ctx, tree_addr); + sig += SPX_TREE_HEIGHT * SPX_N; + + /* Update the indices for the next layer. */ + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; + } + + // cleanup + free_hash_function(&ctx); + + /* Check if the root node equals the root node in the public key. */ + if (memcmp(root, pub_root, SPX_N) != 0) { + return -1; + } + + return 0; +} + + +/** + * Returns an array containing the signature followed by the message. + */ +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk) { + size_t siglen; + + crypto_sign_signature(sm, &siglen, m, mlen, sk); + + memmove(sm + SPX_BYTES, m, mlen); + *smlen = siglen + mlen; + + return 0; +} + +/** + * Verifies a given signature-message pair under a given public key. + */ +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk) { + /* The API caller does not necessarily know what size a signature should be + but SPHINCS+ signatures are always exactly SPX_BYTES. */ + if (smlen < SPX_BYTES) { + memset(m, 0, smlen); + *mlen = 0; + return -1; + } + + *mlen = smlen - SPX_BYTES; + + if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { + memset(m, 0, smlen); + *mlen = 0; + return -1; + } + + /* If verification was successful, move the message to the right place. */ + memmove(m, sm + SPX_BYTES, *mlen); + + return 0; +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/thash.h b/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/thash.h new file mode 100644 index 0000000000..8687ccfb4d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/thash.h @@ -0,0 +1,13 @@ +#ifndef SPX_THASH_H +#define SPX_THASH_H + +#include "context.h" +#include "params.h" + +#include + +#define thash SPX_NAMESPACE(thash) +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/thash_sha2_simple.c b/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/thash_sha2_simple.c new file mode 100644 index 0000000000..87badc4d53 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/thash_sha2_simple.c @@ -0,0 +1,53 @@ +#include +#include + +#include "thash.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "sha2.h" +#include "utils.h" + +static void thash_512(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]); + +/** + * Takes an array of inblocks concatenated arrays of SPX_N bytes. + */ +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]) { + if (inblocks > 1) { + thash_512(out, in, inblocks, ctx, addr); + return; + } + + unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES]; + sha256ctx sha2_state; + PQCLEAN_VLA(uint8_t, buf, SPX_SHA256_ADDR_BYTES + inblocks * SPX_N); + + /* Retrieve precomputed state containing pub_seed */ + sha256_inc_ctx_clone(&sha2_state, &ctx->state_seeded); + + memcpy(buf, addr, SPX_SHA256_ADDR_BYTES); + memcpy(buf + SPX_SHA256_ADDR_BYTES, in, inblocks * SPX_N); + + sha256_inc_finalize(outbuf, &sha2_state, buf, SPX_SHA256_ADDR_BYTES + inblocks * SPX_N); + memcpy(out, outbuf, SPX_N); +} + +static void thash_512(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]) { + unsigned char outbuf[SPX_SHA512_OUTPUT_BYTES]; + sha512ctx sha2_state; + PQCLEAN_VLA(uint8_t, buf, SPX_SHA256_ADDR_BYTES + inblocks * SPX_N); + + /* Retrieve precomputed state containing pub_seed */ + sha512_inc_ctx_clone(&sha2_state, &ctx->state_seeded_512); + + memcpy(buf, addr, SPX_SHA256_ADDR_BYTES); + memcpy(buf + SPX_SHA256_ADDR_BYTES, in, inblocks * SPX_N); + + sha512_inc_finalize(outbuf, &sha2_state, buf, SPX_SHA256_ADDR_BYTES + inblocks * SPX_N); + memcpy(out, outbuf, SPX_N); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/thash_sha2_simplex8.c b/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/thash_sha2_simplex8.c new file mode 100644 index 0000000000..9b946f4e4a --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/thash_sha2_simplex8.c @@ -0,0 +1,212 @@ +#include +#include + +#include "thashx8.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "sha2.h" +#include "sha256avx.h" +#include "sha256x8.h" +#include "utils.h" + +#include "sha512x4.h" + +static void thashx8_512( + unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, + unsigned int inblocks, + const spx_ctx *ctx, + uint32_t addrx8[8 * 8] +); + +/** + * 8-way parallel version of thash; takes 8x as much input and output + */ +void thashx8(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addrx8[8 * 8]) { + if (inblocks > 1) { + thashx8_512( + out0, out1, out2, out3, out4, out5, out6, out7, + in0, in1, in2, in3, in4, in5, in6, in7, + inblocks, ctx, addrx8); + return; + } + PQCLEAN_VLA(unsigned char, bufx8, 8 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)); + unsigned char outbufx8[8 * SPX_SHA256_OUTPUT_BYTES]; + unsigned int i; + + for (i = 0; i < 8; i++) { + memcpy(bufx8 + i * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + addrx8 + i * 8, SPX_SHA256_ADDR_BYTES); + } + + memcpy(bufx8 + SPX_SHA256_ADDR_BYTES + + 0 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), in0, inblocks * SPX_N); + memcpy(bufx8 + SPX_SHA256_ADDR_BYTES + + 1 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), in1, inblocks * SPX_N); + memcpy(bufx8 + SPX_SHA256_ADDR_BYTES + + 2 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), in2, inblocks * SPX_N); + memcpy(bufx8 + SPX_SHA256_ADDR_BYTES + + 3 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), in3, inblocks * SPX_N); + memcpy(bufx8 + SPX_SHA256_ADDR_BYTES + + 4 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), in4, inblocks * SPX_N); + memcpy(bufx8 + SPX_SHA256_ADDR_BYTES + + 5 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), in5, inblocks * SPX_N); + memcpy(bufx8 + SPX_SHA256_ADDR_BYTES + + 6 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), in6, inblocks * SPX_N); + memcpy(bufx8 + SPX_SHA256_ADDR_BYTES + + 7 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), in7, inblocks * SPX_N); + + sha256x8_seeded( + /* out */ + outbufx8 + 0 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 1 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 2 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 3 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 4 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 5 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 6 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 7 * SPX_SHA256_OUTPUT_BYTES, + + /* seed */ + &ctx->statex8_seeded, + + /* in */ + bufx8 + 0 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + 1 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + 2 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + 3 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + 4 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + 5 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + 6 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + 7 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N /* len */ + ); + + memcpy(out0, outbufx8 + 0 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out1, outbufx8 + 1 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out2, outbufx8 + 2 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out3, outbufx8 + 3 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out4, outbufx8 + 4 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out5, outbufx8 + 5 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out6, outbufx8 + 6 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out7, outbufx8 + 7 * SPX_SHA256_OUTPUT_BYTES, SPX_N); +} + +/** + * 2x4-way parallel version of thash; this is for the uses of thash that are + * based on SHA-512 + */ +static void thashx8_512( + unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, + unsigned int inblocks, + const spx_ctx *ctx, + uint32_t addrx8[8 * 8]) { + PQCLEAN_VLA(unsigned char, bufx8, 8 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)); + unsigned char outbuf[4 * SPX_SHA512_OUTPUT_BYTES]; + unsigned int i; + + for (i = 0; i < 8; i++) { + memcpy(bufx8 + i * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + addrx8 + i * 8, SPX_SHA256_ADDR_BYTES); + } + + memcpy(bufx8 + SPX_SHA256_ADDR_BYTES + + 0 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), in0, inblocks * SPX_N); + memcpy(bufx8 + SPX_SHA256_ADDR_BYTES + + 1 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), in1, inblocks * SPX_N); + memcpy(bufx8 + SPX_SHA256_ADDR_BYTES + + 2 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), in2, inblocks * SPX_N); + memcpy(bufx8 + SPX_SHA256_ADDR_BYTES + + 3 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), in3, inblocks * SPX_N); + memcpy(bufx8 + SPX_SHA256_ADDR_BYTES + + 4 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), in4, inblocks * SPX_N); + memcpy(bufx8 + SPX_SHA256_ADDR_BYTES + + 5 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), in5, inblocks * SPX_N); + memcpy(bufx8 + SPX_SHA256_ADDR_BYTES + + 6 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), in6, inblocks * SPX_N); + memcpy(bufx8 + SPX_SHA256_ADDR_BYTES + + 7 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), in7, inblocks * SPX_N); + + sha512x4_seeded( + outbuf + 0 * SPX_SHA512_OUTPUT_BYTES, + outbuf + 1 * SPX_SHA512_OUTPUT_BYTES, + outbuf + 2 * SPX_SHA512_OUTPUT_BYTES, + outbuf + 3 * SPX_SHA512_OUTPUT_BYTES, + &ctx->statex4_seeded_512, /* seed */ + bufx8 + 0 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), /* in */ + bufx8 + 1 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + 2 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + 3 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N /* len */ + ); + + memcpy(out0, outbuf + 0 * SPX_SHA512_OUTPUT_BYTES, SPX_N); + memcpy(out1, outbuf + 1 * SPX_SHA512_OUTPUT_BYTES, SPX_N); + memcpy(out2, outbuf + 2 * SPX_SHA512_OUTPUT_BYTES, SPX_N); + memcpy(out3, outbuf + 3 * SPX_SHA512_OUTPUT_BYTES, SPX_N); + + sha512x4_seeded( + outbuf + 0 * SPX_SHA512_OUTPUT_BYTES, + outbuf + 1 * SPX_SHA512_OUTPUT_BYTES, + outbuf + 2 * SPX_SHA512_OUTPUT_BYTES, + outbuf + 3 * SPX_SHA512_OUTPUT_BYTES, + &ctx->statex4_seeded_512, /* seed */ + bufx8 + 4 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), /* in */ + bufx8 + 5 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + 6 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + 7 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N /* len */ + ); + + memcpy(out4, outbuf + 0 * SPX_SHA512_OUTPUT_BYTES, SPX_N); + memcpy(out5, outbuf + 1 * SPX_SHA512_OUTPUT_BYTES, SPX_N); + memcpy(out6, outbuf + 2 * SPX_SHA512_OUTPUT_BYTES, SPX_N); + memcpy(out7, outbuf + 3 * SPX_SHA512_OUTPUT_BYTES, SPX_N); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/thashx8.h b/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/thashx8.h new file mode 100644 index 0000000000..c02fe9cf3e --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/thashx8.h @@ -0,0 +1,28 @@ +#ifndef SPX_THASHX8_H +#define SPX_THASHX8_H + +#include + +#include "context.h" +#include "params.h" + +#define thashx8 SPX_NAMESPACE(thashx8) +void thashx8(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addrx8[8 * 8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/utils.c b/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/utils.c new file mode 100644 index 0000000000..177b541fb9 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/utils.c @@ -0,0 +1,148 @@ +#include + +#include "utils.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "thash.h" + +/** + * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. + */ +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in) { + int i; + + /* Iterate over out in decreasing order, for big-endianness. */ + for (i = (signed int)outlen - 1; i >= 0; i--) { + out[i] = in & 0xff; + in = in >> 8; + } +} + +void u32_to_bytes(unsigned char *out, uint32_t in) { + out[0] = (unsigned char)(in >> 24); + out[1] = (unsigned char)(in >> 16); + out[2] = (unsigned char)(in >> 8); + out[3] = (unsigned char)in; +} + +/** + * Converts the inlen bytes in 'in' from big-endian byte order to an integer. + */ +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { + unsigned long long retval = 0; + unsigned int i; + + for (i = 0; i < inlen; i++) { + retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); + } + return retval; +} + +/** + * Computes a root node given a leaf and an auth path. + * Expects address to be complete other than the tree_height and tree_index. + */ +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]) { + uint32_t i; + unsigned char buffer[2 * SPX_N]; + + /* If leaf_idx is odd (last bit = 1), current path element is a right child + and auth_path has to go left. Otherwise it is the other way around. */ + if (leaf_idx & 1) { + memcpy(buffer + SPX_N, leaf, SPX_N); + memcpy(buffer, auth_path, SPX_N); + } else { + memcpy(buffer, leaf, SPX_N); + memcpy(buffer + SPX_N, auth_path, SPX_N); + } + auth_path += SPX_N; + + for (i = 0; i < tree_height - 1; i++) { + leaf_idx >>= 1; + idx_offset >>= 1; + /* Set the address of the node we're creating. */ + set_tree_height(addr, i + 1); + set_tree_index(addr, leaf_idx + idx_offset); + + /* Pick the right or left neighbor, depending on parity of the node. */ + if (leaf_idx & 1) { + thash(buffer + SPX_N, buffer, 2, ctx, addr); + memcpy(buffer, auth_path, SPX_N); + } else { + thash(buffer, buffer, 2, ctx, addr); + memcpy(buffer + SPX_N, auth_path, SPX_N); + } + auth_path += SPX_N; + } + + /* The last iteration is exceptional; we do not copy an auth_path node. */ + leaf_idx >>= 1; + idx_offset >>= 1; + set_tree_height(addr, tree_height); + set_tree_index(addr, leaf_idx + idx_offset); + thash(root, buffer, 2, ctx, addr); +} + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx * /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]) { + PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); + PQCLEAN_VLA(unsigned int, heights, tree_height + 1); + unsigned int offset = 0; + uint32_t idx; + uint32_t tree_idx; + + for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { + /* Add the next leaf node to the stack. */ + gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); + offset++; + heights[offset - 1] = 0; + + /* If this is a node we need for the auth path.. */ + if ((leaf_idx ^ 0x1) == idx) { + memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); + } + + /* While the top-most nodes are of equal height.. */ + while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { + /* Compute index of the new node, in the next layer. */ + tree_idx = (idx >> (heights[offset - 1] + 1)); + + /* Set the address of the node we're creating. */ + set_tree_height(tree_addr, heights[offset - 1] + 1); + set_tree_index(tree_addr, + tree_idx + (idx_offset >> (heights[offset - 1] + 1))); + /* Hash the top-most nodes from the stack together. */ + thash(stack + (offset - 2)*SPX_N, + stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); + offset--; + /* Note that the top-most node is now one layer higher. */ + heights[offset - 1]++; + + /* If this is a node we need for the auth path.. */ + if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { + memcpy(auth_path + heights[offset - 1]*SPX_N, + stack + (offset - 1)*SPX_N, SPX_N); + } + } + } + memcpy(root, stack, SPX_N); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/utils.h b/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/utils.h new file mode 100644 index 0000000000..64f5d5a53a --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/utils.h @@ -0,0 +1,58 @@ +#ifndef SPX_UTILS_H +#define SPX_UTILS_H + +#include + +#include "compat.h" +#include "context.h" +#include "params.h" + + +/* To support MSVC use alloca() instead of VLAs. See #20. */ + + +/** + * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. + */ +#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in); +#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) +void u32_to_bytes(unsigned char *out, uint32_t in); + +/** + * Converts the inlen bytes in 'in' from big-endian byte order to an integer. + */ +#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); + +/** + * Computes a root node given a leaf and an auth path. + * Expects address to be complete other than the tree_height and tree_index. + */ +#define compute_root SPX_NAMESPACE(compute_root) +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]); + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +#define treehash SPX_NAMESPACE(treehash) +void treehash(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx *ctx /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]); + + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/utilsx8.c b/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/utilsx8.c new file mode 100644 index 0000000000..f044b9595d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/utilsx8.c @@ -0,0 +1,146 @@ +#include + +#include "utils.h" +#include "utilsx8.h" + +#include "address.h" +#include "params.h" +#include "thashx8.h" + +/* + * Generate the entire Merkle tree, computing the authentication path for leaf_idx, + * and the resulting root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) + * + * This expects tree_addrx8 to be initialized to 8 parallel addr structures for + * the Merkle tree nodes + * + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + * + * This works by using the standard Merkle tree building algorithm, except + * that each 'node' tracked is actually 8 consecutive nodes in the real tree. + * When we combine two logical nodes ABCDEFGH and STUVWXYZ, we perform the H + * operation on adjacent real nodes, forming the parent logical node + * (AB)(CD)(EF)(GH)(ST)(UV)(WX)(YZ) + * + * When we get to the top three levels of the real tree (where there is only + * one logical node), we continue this operation three more times; the right + * most real node will by the actual root (and the other 7 nodes will be + * garbage). We follow the same thashx8 logic so that the 'extract + * authentication path components' part of the loop is still executed (and + * to simplify the code somewhat) + * + * This currently assumes tree_height >= 3; I suspect that doing an adjusting + * idx, addr_idx on the gen_leafx8 call if tree_height < 3 would fix it; since + * we don't actually use such short trees, I haven't bothered + */ +void treehashx8(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, + uint32_t tree_height, + void (*gen_leafx8)( + unsigned char * /* Where to write the leaves */, + const spx_ctx *, + uint32_t idx, void *info), + uint32_t tree_addrx8[8 * 8], + void *info) { + /* This is where we keep the intermediate nodes */ + PQCLEAN_VLA(unsigned char, stackx8, tree_height * 8 * SPX_N); + uint32_t left_adj = 0, prev_left_adj = 0; /* When we're doing the top 3 */ + /* levels, the left-most part of the tree isn't at the beginning */ + /* of current[]. These give the offset of the actual start */ + + uint32_t idx; + uint32_t max_idx = ((uint32_t)1 << (tree_height - 3)) - 1; + for (idx = 0;; idx++) { + unsigned char current[8 * SPX_N]; /* Current logical node */ + gen_leafx8( current, ctx, 8 * idx + idx_offset, + info ); + + /* Now combine the freshly generated right node with previously */ + /* generated left ones */ + uint32_t internal_idx_offset = idx_offset; + uint32_t internal_idx = idx; + uint32_t internal_leaf = leaf_idx; + uint32_t h; /* The height we are in the Merkle tree */ + for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { + + /* Special processing if we're at the top of the tree */ + if (h >= tree_height - 3) { + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[7 * SPX_N], SPX_N ); + return; + } + /* The tree indexing logic is a bit off in this case */ + /* Adjust it so that the left-most node of the part of */ + /* the tree that we're processing has index 0 */ + prev_left_adj = left_adj; + left_adj = (uint32_t)(8 - (1 << (tree_height - h - 1))); + } + + /* Check if we hit the top of the tree */ + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[7 * SPX_N], SPX_N ); + return; + } + + /* + * Check if one of the nodes we have is a part of the + * authentication path; if it is, write it out + */ + if ((((internal_idx << 3) ^ internal_leaf) & ~0x7U) == 0) { + memcpy( &auth_path[ h * SPX_N ], + ¤t[(((internal_leaf & 7) ^ 1) + prev_left_adj) * SPX_N], + SPX_N ); + } + + /* + * Check if we're at a left child; if so, stop going up the stack + * Exception: if we've reached the end of the tree, keep on going + * (so we combine the last 8 nodes into the one root node in three + * more iterations) + */ + if ((internal_idx & 1) == 0 && idx < max_idx) { + break; + } + + /* Ok, we're at a right node (or doing the top 3 levels) */ + /* Now combine the left and right logical nodes together */ + + /* Set the address of the node we're creating. */ + uint32_t j; + internal_idx_offset >>= 1; + for (j = 0; j < 8; j++) { + set_tree_height(tree_addrx8 + j * 8, h + 1); + set_tree_index(tree_addrx8 + j * 8, + (8 / 2) * (internal_idx & ~1U) + j - left_adj + internal_idx_offset ); + } + unsigned char *left = &stackx8[h * 8 * SPX_N]; + thashx8( ¤t[0 * SPX_N], + ¤t[1 * SPX_N], + ¤t[2 * SPX_N], + ¤t[3 * SPX_N], + ¤t[4 * SPX_N], + ¤t[5 * SPX_N], + ¤t[6 * SPX_N], + ¤t[7 * SPX_N], + &left [0 * SPX_N], + &left [2 * SPX_N], + &left [4 * SPX_N], + &left [6 * SPX_N], + ¤t[0 * SPX_N], + ¤t[2 * SPX_N], + ¤t[4 * SPX_N], + ¤t[6 * SPX_N], + 2, ctx, tree_addrx8); + } + + /* We've hit a left child; save the current for when we get the */ + /* corresponding right right */ + memcpy( &stackx8[h * 8 * SPX_N], current, 8 * SPX_N); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/utilsx8.h b/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/utilsx8.h new file mode 100644 index 0000000000..806d1e85be --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/utilsx8.h @@ -0,0 +1,29 @@ +#ifndef SPX_UTILSX8_H +#define SPX_UTILSX8_H + +#include + +#include "params.h" + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + * + * This implementation uses AVX to compute internal nodes 8 at a time (in + * parallel) + */ +#define treehashx8 SPX_NAMESPACE(treehashx8) +void treehashx8(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leafx8)( + unsigned char * /* Where to write the leaves */, + const spx_ctx * /* ctx */, + uint32_t addr_idx, void *info), + uint32_t tree_addrx8[8 * 8], void *info); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/wots.c b/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/wots.c new file mode 100644 index 0000000000..689baf4db9 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/wots.c @@ -0,0 +1,291 @@ +#include +#include + +#include "wots.h" + +#include "address.h" +#include "hash.h" +#include "hashx8.h" +#include "params.h" +#include "thash.h" +#include "thashx8.h" +#include "utils.h" +#include "utilsx8.h" +#include "wotsx8.h" + +// TODO clarify address expectations, and make them more uniform. +// TODO i.e. do we expect types to be set already? +// TODO and do we expect modifications or copies? + +/** + * Computes up the chains + */ +static void gen_chains( + unsigned char *out, + const unsigned char *in, + unsigned int start[SPX_WOTS_LEN], + const unsigned int steps[SPX_WOTS_LEN], + const spx_ctx *ctx, + uint32_t addr[8]) { + uint32_t i, j, k, idx, watching; + int done; + unsigned char empty[SPX_N]; + unsigned char *bufs[8]; + uint32_t addrs[8 * 8]; + + int l; + uint16_t counts[SPX_WOTS_W] = { 0 }; + uint16_t idxs[SPX_WOTS_LEN]; + uint16_t total, newTotal; + + /* set addrs = {addr, addr, ..., addr} */ + for (j = 0; j < 8; j++) { + memcpy(addrs + j * 8, addr, sizeof(uint32_t) * 8); + } + + /* Initialize out with the value at position 'start'. */ + memcpy(out, in, SPX_WOTS_LEN * SPX_N); + + /* Sort the chains in reverse order by steps using counting sort. */ + for (i = 0; i < SPX_WOTS_LEN; i++) { + counts[steps[i]]++; + } + total = 0; + for (l = SPX_WOTS_W - 1; l >= 0; l--) { + newTotal = counts[l] + total; + counts[l] = total; + total = newTotal; + } + for (i = 0; i < SPX_WOTS_LEN; i++) { + idxs[counts[steps[i]]] = (uint16_t)i; + counts[steps[i]]++; + } + + /* We got our work cut out for us: do it! */ + for (i = 0; i < SPX_WOTS_LEN; i += 8) { + for (j = 0; j < 8 && i + j < SPX_WOTS_LEN; j++) { + idx = idxs[i + j]; + set_chain_addr(addrs + j * 8, idx); + bufs[j] = out + SPX_N * idx; + } + + /* As the chains are sorted in reverse order, we know that the first + * chain is the longest and the last one is the shortest. We keep + * an eye on whether the last chain is done and then on the one before, + * et cetera. */ + watching = 7; + done = 0; + while (i + watching >= SPX_WOTS_LEN) { + bufs[watching] = &empty[0]; + watching--; + } + + for (k = 0;; k++) { + while (k == steps[idxs[i + watching]]) { + bufs[watching] = &empty[0]; + if (watching == 0) { + done = 1; + break; + } + watching--; + } + if (done) { + break; + } + for (j = 0; j < watching + 1; j++) { + set_hash_addr(addrs + j * 8, k + start[idxs[i + j]]); + } + + thashx8(bufs[0], bufs[1], bufs[2], bufs[3], + bufs[4], bufs[5], bufs[6], bufs[7], + bufs[0], bufs[1], bufs[2], bufs[3], + bufs[4], bufs[5], bufs[6], bufs[7], 1, ctx, addrs); + } + } +} + +/** + * base_w algorithm as described in draft. + * Interprets an array of bytes as integers in base w. + * This only works when log_w is a divisor of 8. + */ +static void base_w(unsigned int *output, const int out_len, + const unsigned char *input) { + int in = 0; + int out = 0; + unsigned char total = 0; + int bits = 0; + int consumed; + + for (consumed = 0; consumed < out_len; consumed++) { + if (bits == 0) { + total = input[in]; + in++; + bits += 8; + } + bits -= SPX_WOTS_LOGW; + output[out] = (total >> bits) & (SPX_WOTS_W - 1); + out++; + } +} + +/* Computes the WOTS+ checksum over a message (in base_w). */ +static void wots_checksum(unsigned int *csum_base_w, + const unsigned int *msg_base_w) { + unsigned int csum = 0; + unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; + unsigned int i; + + /* Compute checksum. */ + for (i = 0; i < SPX_WOTS_LEN1; i++) { + csum += SPX_WOTS_W - 1 - msg_base_w[i]; + } + + /* Convert checksum to base_w. */ + /* Make sure expected empty zero bits are the least significant bits. */ + csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); + ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); + base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); +} + +/* Takes a message and derives the matching chain lengths. */ +void chain_lengths(unsigned int *lengths, const unsigned char *msg) { + base_w(lengths, SPX_WOTS_LEN1, msg); + wots_checksum(lengths + SPX_WOTS_LEN1, lengths); +} + +/** + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. + * + * Writes the computed public key to 'pk'. + */ +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]) { + unsigned int steps[SPX_WOTS_LEN]; + unsigned int start[SPX_WOTS_LEN]; + uint32_t i; + + chain_lengths(start, msg); + + for (i = 0; i < SPX_WOTS_LEN; i++) { + steps[i] = SPX_WOTS_W - 1 - start[i]; + } + + gen_chains(pk, sig, start, steps, ctx, addr); +} + +/* + * This generates 8 sequential WOTS public keys + * It also generates the WOTS signature if leaf_info indicates + * that we're signing with one of these WOTS keys + */ +void wots_gen_leafx8(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info) { + struct leaf_info_x8 *info = v_info; + uint32_t *leaf_addr = info->leaf_addr; + uint32_t *pk_addr = info->pk_addr; + unsigned int i, j, k; + unsigned char pk_buffer[ 8 * SPX_WOTS_BYTES ]; + unsigned wots_offset = SPX_WOTS_BYTES; + unsigned char *buffer; + uint32_t wots_k_mask; + unsigned wots_sign_index; + + if (((leaf_idx ^ info->wots_sign_leaf) & ~7U) == 0) { + /* We're traversing the leaf that's signing; generate the WOTS */ + /* signature */ + wots_k_mask = 0; + wots_sign_index = info->wots_sign_leaf & 7; /* Which of of the 8 */ + /* slots do the signatures come from */ + } else { + /* Nope, we're just generating pk's; turn off the signature logic */ + wots_k_mask = ~0U; + wots_sign_index = 0; + } + + for (j = 0; j < 8; j++) { + set_keypair_addr( leaf_addr + j * 8, leaf_idx + j ); + set_keypair_addr( pk_addr + j * 8, leaf_idx + j ); + } + + for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { + uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k */ + /* to the step if we're generating a signature, ~0 if we're not */ + + /* Start with the secret seed */ + for (j = 0; j < 8; j++) { + set_chain_addr(leaf_addr + j * 8, i); + set_hash_addr(leaf_addr + j * 8, 0); + set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTSPRF); + } + prf_addrx8(buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + buffer + 2 * wots_offset, + buffer + 3 * wots_offset, + buffer + 4 * wots_offset, + buffer + 5 * wots_offset, + buffer + 6 * wots_offset, + buffer + 7 * wots_offset, + ctx, leaf_addr); + + for (j = 0; j < 8; j++) { + set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTS); + } + + /* Iterate down the WOTS chain */ + for (k = 0;; k++) { + /* Check if one of the values we have needs to be saved as a */ + /* part of the WOTS signature */ + if (k == wots_k) { + memcpy( info->wots_sig + i * SPX_N, + buffer + wots_sign_index * wots_offset, SPX_N ); + } + + /* Check if we hit the top of the chain */ + if (k == SPX_WOTS_W - 1) { + break; + } + + /* Iterate one step on all 8 chains */ + for (j = 0; j < 8; j++) { + set_hash_addr(leaf_addr + j * 8, k); + } + thashx8(buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + buffer + 2 * wots_offset, + buffer + 3 * wots_offset, + buffer + 4 * wots_offset, + buffer + 5 * wots_offset, + buffer + 6 * wots_offset, + buffer + 7 * wots_offset, + buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + buffer + 2 * wots_offset, + buffer + 3 * wots_offset, + buffer + 4 * wots_offset, + buffer + 5 * wots_offset, + buffer + 6 * wots_offset, + buffer + 7 * wots_offset, 1, ctx, leaf_addr); + } + } + + /* Do the final thash to generate the public keys */ + thashx8(dest + 0 * SPX_N, + dest + 1 * SPX_N, + dest + 2 * SPX_N, + dest + 3 * SPX_N, + dest + 4 * SPX_N, + dest + 5 * SPX_N, + dest + 6 * SPX_N, + dest + 7 * SPX_N, + pk_buffer + 0 * wots_offset, + pk_buffer + 1 * wots_offset, + pk_buffer + 2 * wots_offset, + pk_buffer + 3 * wots_offset, + pk_buffer + 4 * wots_offset, + pk_buffer + 5 * wots_offset, + pk_buffer + 6 * wots_offset, + pk_buffer + 7 * wots_offset, SPX_WOTS_LEN, ctx, pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/wots.h b/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/wots.h new file mode 100644 index 0000000000..4e7692eeef --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/wots.h @@ -0,0 +1,25 @@ +#ifndef SPX_WOTS_H +#define SPX_WOTS_H + +#include + +#include "context.h" +#include "params.h" + +/** + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. + * + * Writes the computed public key to 'pk'. + */ +#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]); + +/* + * Compute the chain lengths needed for a given message hash + */ +#define chain_lengths SPX_NAMESPACE(chain_lengths) +void chain_lengths(unsigned int *lengths, const unsigned char *msg); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/wotsx8.h b/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/wotsx8.h new file mode 100644 index 0000000000..10866efb35 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_avx2/wotsx8.h @@ -0,0 +1,42 @@ +#ifndef WOTSX8_H_ +#define WOTSX8_H_ + +#include + +#include "context.h" +#include "params.h" + +/* + * This is here to provide an interface to the internal wots_gen_leafx8 + * routine. While this routine is not referenced in the package outside of + * wots.c, it is called from the stand-alone benchmark code to characterize + * the performance + */ +struct leaf_info_x8 { + unsigned char *wots_sig; + uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ + uint32_t *wots_steps; + uint32_t leaf_addr[8 * 8]; + uint32_t pk_addr[8 * 8]; +}; + +/* Macro to set the leaf_info to something 'benign', that is, it would */ +/* run with the same time as it does during the real signing process */ +/* Used only by the benchmark code */ +#define INITIALIZE_LEAF_INFO_X8(info, addr, step_buffer) { \ + (info).wots_sig = 0; \ + (info).wots_sign_leaf = ~0; \ + (info).wots_steps = step_buffer; \ + int i; \ + for (i=0; i<8; i++) { \ + memcpy( &(info).leaf_addr[8*i], addr, 32 ); \ + memcpy( &(info).pk_addr[8*i], addr, 32 ); \ + } \ + } + +#define wots_gen_leafx8 SPX_NAMESPACE(wots_gen_leafx8) +void wots_gen_leafx8(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info); + +#endif /* WOTSX8_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_clean/LICENSE b/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_clean/LICENSE new file mode 100644 index 0000000000..670154e353 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_clean/LICENSE @@ -0,0 +1,116 @@ +CC0 1.0 Universal + +Statement of Purpose + +The laws of most jurisdictions throughout the world automatically confer +exclusive Copyright and Related Rights (defined below) upon the creator and +subsequent owner(s) (each and all, an "owner") of an original work of +authorship and/or a database (each, a "Work"). + +Certain owners wish to permanently relinquish those rights to a Work for the +purpose of contributing to a commons of creative, cultural and scientific +works ("Commons") that the public can reliably and without fear of later +claims of infringement build upon, modify, incorporate in other works, reuse +and redistribute as freely as possible in any form whatsoever and for any +purposes, including without limitation commercial purposes. These owners may +contribute to the Commons to promote the ideal of a free culture and the +further production of creative, cultural and scientific works, or to gain +reputation or greater distribution for their Work in part through the use and +efforts of others. + +For these and/or other purposes and motivations, and without any expectation +of additional consideration or compensation, the person associating CC0 with a +Work (the "Affirmer"), to the extent that he or she is an owner of Copyright +and Related Rights in the Work, voluntarily elects to apply CC0 to the Work +and publicly distribute the Work under its terms, with knowledge of his or her +Copyright and Related Rights in the Work and the meaning and intended legal +effect of CC0 on those rights. + +1. Copyright and Related Rights. A Work made available under CC0 may be +protected by copyright and related or neighboring rights ("Copyright and +Related Rights"). Copyright and Related Rights include, but are not limited +to, the following: + + i. the right to reproduce, adapt, distribute, perform, display, communicate, + and translate a Work; + + ii. moral rights retained by the original author(s) and/or performer(s); + + iii. publicity and privacy rights pertaining to a person's image or likeness + depicted in a Work; + + iv. rights protecting against unfair competition in regards to a Work, + subject to the limitations in paragraph 4(a), below; + + v. rights protecting the extraction, dissemination, use and reuse of data in + a Work; + + vi. database rights (such as those arising under Directive 96/9/EC of the + European Parliament and of the Council of 11 March 1996 on the legal + protection of databases, and under any national implementation thereof, + including any amended or successor version of such directive); and + + vii. other similar, equivalent or corresponding rights throughout the world + based on applicable law or treaty, and any national implementations thereof. + +2. Waiver. To the greatest extent permitted by, but not in contravention of, +applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and +unconditionally waives, abandons, and surrenders all of Affirmer's Copyright +and Related Rights and associated claims and causes of action, whether now +known or unknown (including existing as well as future claims and causes of +action), in the Work (i) in all territories worldwide, (ii) for the maximum +duration provided by applicable law or treaty (including future time +extensions), (iii) in any current or future medium and for any number of +copies, and (iv) for any purpose whatsoever, including without limitation +commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes +the Waiver for the benefit of each member of the public at large and to the +detriment of Affirmer's heirs and successors, fully intending that such Waiver +shall not be subject to revocation, rescission, cancellation, termination, or +any other legal or equitable action to disrupt the quiet enjoyment of the Work +by the public as contemplated by Affirmer's express Statement of Purpose. + +3. Public License Fallback. Should any part of the Waiver for any reason be +judged legally invalid or ineffective under applicable law, then the Waiver +shall be preserved to the maximum extent permitted taking into account +Affirmer's express Statement of Purpose. In addition, to the extent the Waiver +is so judged Affirmer hereby grants to each affected person a royalty-free, +non transferable, non sublicensable, non exclusive, irrevocable and +unconditional license to exercise Affirmer's Copyright and Related Rights in +the Work (i) in all territories worldwide, (ii) for the maximum duration +provided by applicable law or treaty (including future time extensions), (iii) +in any current or future medium and for any number of copies, and (iv) for any +purpose whatsoever, including without limitation commercial, advertising or +promotional purposes (the "License"). The License shall be deemed effective as +of the date CC0 was applied by Affirmer to the Work. Should any part of the +License for any reason be judged legally invalid or ineffective under +applicable law, such partial invalidity or ineffectiveness shall not +invalidate the remainder of the License, and in such case Affirmer hereby +affirms that he or she will not (i) exercise any of his or her remaining +Copyright and Related Rights in the Work or (ii) assert any associated claims +and causes of action with respect to the Work, in either case contrary to +Affirmer's express Statement of Purpose. + +4. Limitations and Disclaimers. + + a. No trademark or patent rights held by Affirmer are waived, abandoned, + surrendered, licensed or otherwise affected by this document. + + b. Affirmer offers the Work as-is and makes no representations or warranties + of any kind concerning the Work, express, implied, statutory or otherwise, + including without limitation warranties of title, merchantability, fitness + for a particular purpose, non infringement, or the absence of latent or + other defects, accuracy, or the present or absence of errors, whether or not + discoverable, all to the greatest extent permissible under applicable law. + + c. Affirmer disclaims responsibility for clearing rights of other persons + that may apply to the Work or any use thereof, including without limitation + any person's Copyright and Related Rights in the Work. Further, Affirmer + disclaims responsibility for obtaining any necessary consents, permissions + or other rights required for any use of the Work. + + d. Affirmer understands and acknowledges that Creative Commons is not a + party to this document and has no duty or obligation with respect to this + CC0 or use of the Work. + +For more information, please see + diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_clean/address.c b/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_clean/address.c new file mode 100644 index 0000000000..b956e9cb29 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_clean/address.c @@ -0,0 +1,91 @@ +#include +#include + +#include "address.h" +#include "params.h" +#include "utils.h" + +/* + * Specify which level of Merkle tree (the "layer") we're working on + */ +void set_layer_addr(uint32_t addr[8], uint32_t layer) { + ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; +} + +/* + * Specify which Merkle tree within the level (the "tree address") we're working on + */ +void set_tree_addr(uint32_t addr[8], uint64_t tree) { + ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); +} + +/* + * Specify the reason we'll use this address structure for, that is, what + * hash will we compute with it. This is used so that unrelated types of + * hashes don't accidentally get the same address structure. The type will be + * one of the SPX_ADDR_TYPE constants + */ +void set_type(uint32_t addr[8], uint32_t type) { + ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; +} + +/* + * Copy the layer and tree fields of the address structure. This is used + * when we're doing multiple types of hashes within the same Merkle tree + */ +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); +} + +/* These functions are used for OTS addresses. */ + +/* + * Specify which Merkle leaf we're working on; that is, which OTS keypair + * we're talking about. + */ +void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { + ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; +} + +/* + * Copy the layer, tree and keypair fields of the address structure. This is + * used when we're doing multiple things within the same OTS keypair + */ +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); + ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; +} + +/* + * Specify which Merkle chain within the OTS we're working with + * (the chain address) + */ +void set_chain_addr(uint32_t addr[8], uint32_t chain) { + ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; +} + +/* + * Specify where in the Merkle chain we are +* (the hash address) + */ +void set_hash_addr(uint32_t addr[8], uint32_t hash) { + ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; +} + +/* These functions are used for all hash tree addresses (including FORS). */ + +/* + * Specify the height of the node in the Merkle/FORS tree we are in + * (the tree height) + */ +void set_tree_height(uint32_t addr[8], uint32_t tree_height) { + ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; +} + +/* + * Specify the distance from the left edge of the node in the Merkle/FORS tree + * (the tree index) + */ +void set_tree_index(uint32_t addr[8], uint32_t tree_index) { + u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_clean/address.h b/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_clean/address.h new file mode 100644 index 0000000000..24a84eb40c --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_clean/address.h @@ -0,0 +1,52 @@ +#ifndef SPX_ADDRESS_H +#define SPX_ADDRESS_H + +#include + +#include "params.h" + +/* The hash types that are passed to set_type */ +#define SPX_ADDR_TYPE_WOTS 0 +#define SPX_ADDR_TYPE_WOTSPK 1 +#define SPX_ADDR_TYPE_HASHTREE 2 +#define SPX_ADDR_TYPE_FORSTREE 3 +#define SPX_ADDR_TYPE_FORSPK 4 +#define SPX_ADDR_TYPE_WOTSPRF 5 +#define SPX_ADDR_TYPE_FORSPRF 6 + +#define set_layer_addr SPX_NAMESPACE(set_layer_addr) +void set_layer_addr(uint32_t addr[8], uint32_t layer); + +#define set_tree_addr SPX_NAMESPACE(set_tree_addr) +void set_tree_addr(uint32_t addr[8], uint64_t tree); + +#define set_type SPX_NAMESPACE(set_type) +void set_type(uint32_t addr[8], uint32_t type); + +/* Copies the layer and tree part of one address into the other */ +#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); + +/* These functions are used for WOTS and FORS addresses. */ + +#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) +void set_keypair_addr(uint32_t addr[8], uint32_t keypair); + +#define set_chain_addr SPX_NAMESPACE(set_chain_addr) +void set_chain_addr(uint32_t addr[8], uint32_t chain); + +#define set_hash_addr SPX_NAMESPACE(set_hash_addr) +void set_hash_addr(uint32_t addr[8], uint32_t hash); + +#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); + +/* These functions are used for all hash tree addresses (including FORS). */ + +#define set_tree_height SPX_NAMESPACE(set_tree_height) +void set_tree_height(uint32_t addr[8], uint32_t tree_height); + +#define set_tree_index SPX_NAMESPACE(set_tree_index) +void set_tree_index(uint32_t addr[8], uint32_t tree_index); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_clean/api.h b/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_clean/api.h new file mode 100644 index 0000000000..d55cd7a139 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_clean/api.h @@ -0,0 +1,77 @@ +#ifndef PQCLEAN_SPHINCSSHA2192FSIMPLE_CLEAN_API_H +#define PQCLEAN_SPHINCSSHA2192FSIMPLE_CLEAN_API_H + +#include +#include + +#define PQCLEAN_SPHINCSSHA2192FSIMPLE_CLEAN_CRYPTO_ALGNAME "SPHINCS+-sha2-192f-simple" + +#define PQCLEAN_SPHINCSSHA2192FSIMPLE_CLEAN_CRYPTO_SECRETKEYBYTES 96 +#define PQCLEAN_SPHINCSSHA2192FSIMPLE_CLEAN_CRYPTO_PUBLICKEYBYTES 48 +#define PQCLEAN_SPHINCSSHA2192FSIMPLE_CLEAN_CRYPTO_BYTES 35664 + +#define PQCLEAN_SPHINCSSHA2192FSIMPLE_CLEAN_CRYPTO_SEEDBYTES 72 + +/* + * Returns the length of a secret key, in bytes + */ +size_t PQCLEAN_SPHINCSSHA2192FSIMPLE_CLEAN_crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +size_t PQCLEAN_SPHINCSSHA2192FSIMPLE_CLEAN_crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +size_t PQCLEAN_SPHINCSSHA2192FSIMPLE_CLEAN_crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +size_t PQCLEAN_SPHINCSSHA2192FSIMPLE_CLEAN_crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +int PQCLEAN_SPHINCSSHA2192FSIMPLE_CLEAN_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +int PQCLEAN_SPHINCSSHA2192FSIMPLE_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +int PQCLEAN_SPHINCSSHA2192FSIMPLE_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +int PQCLEAN_SPHINCSSHA2192FSIMPLE_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, + const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +int PQCLEAN_SPHINCSSHA2192FSIMPLE_CLEAN_crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +int PQCLEAN_SPHINCSSHA2192FSIMPLE_CLEAN_crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_clean/context.h b/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_clean/context.h new file mode 100644 index 0000000000..97e2e2469e --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_clean/context.h @@ -0,0 +1,28 @@ +#ifndef SPX_CONTEXT_H +#define SPX_CONTEXT_H + +#include +#include + +#include "params.h" +#include "sha2.h" + +typedef struct { + uint8_t pub_seed[SPX_N]; + uint8_t sk_seed[SPX_N]; + + // sha256 state that absorbed pub_seed + sha256ctx state_seeded; + + // sha512 state that absorbed pub_seed + sha512ctx state_seeded_512; + +} spx_ctx; + +#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) +void initialize_hash_function(spx_ctx *ctx); + +#define free_hash_function SPX_NAMESPACE(free_hash_function) +void free_hash_function(spx_ctx *ctx); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_clean/context_sha2.c b/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_clean/context_sha2.c new file mode 100644 index 0000000000..9ca9f4e7ac --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_clean/context_sha2.c @@ -0,0 +1,36 @@ +#include "context.h" + +/** + * Absorb the constant pub_seed using one round of the compression function + * This initializes state_seeded and state_seeded_512, which can then be + * reused in thash + **/ +static void seed_state(spx_ctx *ctx) { + uint8_t block[SPX_SHA512_BLOCK_BYTES]; + size_t i; + + for (i = 0; i < SPX_N; ++i) { + block[i] = ctx->pub_seed[i]; + } + for (i = SPX_N; i < SPX_SHA512_BLOCK_BYTES; ++i) { + block[i] = 0; + } + /* block has been properly initialized for both SHA-256 and SHA-512 */ + + sha256_inc_init(&ctx->state_seeded); + sha256_inc_blocks(&ctx->state_seeded, block, 1); + sha512_inc_init(&ctx->state_seeded_512); + sha512_inc_blocks(&ctx->state_seeded_512, block, 1); +} + + +/* We initialize the state for the hash functions */ +void initialize_hash_function(spx_ctx *ctx) { + seed_state(ctx); +} + +/* Free the incremental hashing context for heap-based SHA2 APIs */ +void free_hash_function(spx_ctx *ctx) { + sha256_inc_ctx_release(&ctx->state_seeded); + sha512_inc_ctx_release(&ctx->state_seeded_512); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_clean/fors.c b/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_clean/fors.c new file mode 100644 index 0000000000..96ca72e986 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_clean/fors.c @@ -0,0 +1,156 @@ +#include +#include +#include + +#include "fors.h" + +#include "address.h" +#include "hash.h" +#include "thash.h" +#include "utils.h" +#include "utilsx1.h" + +static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + prf_addr(sk, ctx, fors_leaf_addr); +} + +static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, + const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + thash(leaf, sk, 1, ctx, fors_leaf_addr); +} + +struct fors_gen_leaf_info { + uint32_t leaf_addrx[8]; +}; + +static void fors_gen_leafx1(unsigned char *leaf, + const spx_ctx *ctx, + uint32_t addr_idx, void *info) { + struct fors_gen_leaf_info *fors_info = info; + uint32_t *fors_leaf_addr = fors_info->leaf_addrx; + + /* Only set the parts that the caller doesn't set */ + set_tree_index(fors_leaf_addr, addr_idx); + set_type(fors_leaf_addr, SPX_ADDR_TYPE_FORSPRF); + fors_gen_sk(leaf, ctx, fors_leaf_addr); + + set_type(fors_leaf_addr, SPX_ADDR_TYPE_FORSTREE); + fors_sk_to_leaf(leaf, leaf, + ctx, fors_leaf_addr); +} + +/** + * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + * Assumes indices has space for SPX_FORS_TREES integers. + */ +static void message_to_indices(uint32_t *indices, const unsigned char *m) { + unsigned int i, j; + unsigned int offset = 0; + + for (i = 0; i < SPX_FORS_TREES; i++) { + indices[i] = 0; + for (j = 0; j < SPX_FORS_HEIGHT; j++) { + indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); + offset++; + } + } +} + +/** + * Signs a message m, deriving the secret key from sk_seed and the FTS address. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + uint32_t fors_tree_addr[8] = {0}; + struct fors_gen_leaf_info fors_info = {0}; + uint32_t *fors_leaf_addr = fors_info.leaf_addrx; + uint32_t fors_pk_addr[8] = {0}; + uint32_t idx_offset; + unsigned int i; + + copy_keypair_addr(fors_tree_addr, fors_addr); + copy_keypair_addr(fors_leaf_addr, fors_addr); + + copy_keypair_addr(fors_pk_addr, fors_addr); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); + + message_to_indices(indices, m); + + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); + + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); + + /* Include the secret key part that produces the selected leaf node. */ + fors_gen_sk(sig, ctx, fors_tree_addr); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + sig += SPX_N; + + /* Compute the authentication path for this leaf node. */ + treehashx1(roots + i * SPX_N, sig, ctx, + indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx1, + fors_tree_addr, &fors_info); + + sig += SPX_N * SPX_FORS_HEIGHT; + } + + /* Hash horizontally across all tree roots to derive the public key. */ + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); +} + +/** + * Derives the FORS public key from a signature. + * This can be used for verification by comparing to a known public key, or to + * subsequently verify a signature on the derived public key. The latter is the + * typical use-case when used as an FTS below an OTS in a hypertree. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + unsigned char leaf[SPX_N]; + uint32_t fors_tree_addr[8] = {0}; + uint32_t fors_pk_addr[8] = {0}; + uint32_t idx_offset; + unsigned int i; + + copy_keypair_addr(fors_tree_addr, fors_addr); + copy_keypair_addr(fors_pk_addr, fors_addr); + + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); + + message_to_indices(indices, m); + + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); + + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + + /* Derive the leaf from the included secret key part. */ + fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); + sig += SPX_N; + + /* Derive the corresponding root node of this tree. */ + compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, + sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); + sig += SPX_N * SPX_FORS_HEIGHT; + } + + /* Hash horizontally across all tree roots to derive the public key. */ + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_clean/fors.h b/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_clean/fors.h new file mode 100644 index 0000000000..509140a178 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_clean/fors.h @@ -0,0 +1,32 @@ +#ifndef SPX_FORS_H +#define SPX_FORS_H + +#include + +#include "context.h" +#include "params.h" + +/** + * Signs a message m, deriving the secret key from sk_seed and the FTS address. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +#define fors_sign SPX_NAMESPACE(fors_sign) +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); + +/** + * Derives the FORS public key from a signature. + * This can be used for verification by comparing to a known public key, or to + * subsequently verify a signature on the derived public key. The latter is the + * typical use-case when used as an FTS below an OTS in a hypertree. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_clean/hash.h b/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_clean/hash.h new file mode 100644 index 0000000000..ffe815f45d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_clean/hash.h @@ -0,0 +1,37 @@ +#ifndef SPX_HASH_H +#define SPX_HASH_H + +#include +#include + +#include "context.h" +#include "params.h" + +#define prf_addr SPX_NAMESPACE(prf_addr) +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]); + +#define gen_message_random SPX_NAMESPACE(gen_message_random) +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); + +#define hash_message SPX_NAMESPACE(hash_message) +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); + + +# define SPX_SHA256_ADDR_BYTES 22 + +# define mgf1_256 SPX_NAMESPACE(mgf1_256) +void mgf1_256(unsigned char *out, unsigned long outlen, + const unsigned char *in, unsigned long inlen); + +# define mgf1_512 SPX_NAMESPACE(mgf1_512) +void mgf1_512(unsigned char *out, unsigned long outlen, + const unsigned char *in, unsigned long inlen); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_clean/hash_sha2.c b/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_clean/hash_sha2.c new file mode 100644 index 0000000000..3d0085c8c1 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_clean/hash_sha2.c @@ -0,0 +1,219 @@ +#include +#include + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "sha2.h" +#include "utils.h" + + + +#define SPX_SHAX_OUTPUT_BYTES SPX_SHA512_OUTPUT_BYTES +#define SPX_SHAX_BLOCK_BYTES SPX_SHA512_BLOCK_BYTES +#define shaX_inc_init sha512_inc_init +#define shaX_inc_blocks sha512_inc_blocks +#define shaX_inc_finalize sha512_inc_finalize +#define shaX sha512 +#define mgf1_X mgf1_512 +#define shaXstate sha512ctx + +/** + * mgf1 function based on the SHA-256 hash function + * Note that inlen should be sufficiently small that it still allows for + * an array to be allocated on the stack. Typically 'in' is merely a seed. + * Outputs outlen number of bytes + */ +void mgf1_256(unsigned char *out, unsigned long outlen, + const unsigned char *in, unsigned long inlen) { + PQCLEAN_VLA(uint8_t, inbuf, inlen + 4); + unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES]; + uint32_t i; + + memcpy(inbuf, in, inlen); + + /* While we can fit in at least another full block of SHA256 output.. */ + for (i = 0; (i + 1)*SPX_SHA256_OUTPUT_BYTES <= outlen; i++) { + u32_to_bytes(inbuf + inlen, i); + sha256(out, inbuf, inlen + 4); + out += SPX_SHA256_OUTPUT_BYTES; + } + /* Until we cannot anymore, and we fill the remainder. */ + if (outlen > i * SPX_SHA256_OUTPUT_BYTES) { + u32_to_bytes(inbuf + inlen, i); + sha256(outbuf, inbuf, inlen + 4); + memcpy(out, outbuf, outlen - i * SPX_SHA256_OUTPUT_BYTES); + } +} + +/* + * mgf1 function based on the SHA-512 hash function + */ +void mgf1_512(unsigned char *out, unsigned long outlen, + const unsigned char *in, unsigned long inlen) { + PQCLEAN_VLA(uint8_t, inbuf, inlen + 4); + unsigned char outbuf[SPX_SHA512_OUTPUT_BYTES]; + uint32_t i; + + memcpy(inbuf, in, inlen); + + /* While we can fit in at least another full block of SHA512 output.. */ + for (i = 0; (i + 1)*SPX_SHA512_OUTPUT_BYTES <= outlen; i++) { + u32_to_bytes(inbuf + inlen, i); + sha512(out, inbuf, inlen + 4); + out += SPX_SHA512_OUTPUT_BYTES; + } + /* Until we cannot anymore, and we fill the remainder. */ + if (outlen > i * SPX_SHA512_OUTPUT_BYTES) { + u32_to_bytes(inbuf + inlen, i); + sha512(outbuf, inbuf, inlen + 4); + memcpy(out, outbuf, outlen - i * SPX_SHA512_OUTPUT_BYTES); + } +} + +/* + * Computes PRF(pk_seed, sk_seed, addr). + */ +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]) { + sha256ctx sha2_state; + unsigned char buf[SPX_SHA256_ADDR_BYTES + SPX_N]; + unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES]; + + /* Retrieve precomputed state containing pub_seed */ + sha256_inc_ctx_clone(&sha2_state, &ctx->state_seeded); + + /* Remainder: ADDR^c ‖ SK.seed */ + memcpy(buf, addr, SPX_SHA256_ADDR_BYTES); + memcpy(buf + SPX_SHA256_ADDR_BYTES, ctx->sk_seed, SPX_N); + + sha256_inc_finalize(outbuf, &sha2_state, buf, SPX_SHA256_ADDR_BYTES + SPX_N); + + memcpy(out, outbuf, SPX_N); +} + +/** + * Computes the message-dependent randomness R, using a secret seed as a key + * for HMAC, and an optional randomization value prefixed to the message. + * This requires m to have at least SPX_SHAX_BLOCK_BYTES + SPX_N space + * available in front of the pointer, i.e. before the message to use for the + * prefix. This is necessary to prevent having to move the message around (and + * allocate memory for it). + */ +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { + (void)ctx; + + unsigned char buf[SPX_SHAX_BLOCK_BYTES + SPX_SHAX_OUTPUT_BYTES]; + shaXstate state; + int i; + + + /* This implements HMAC-SHA */ + for (i = 0; i < SPX_N; i++) { + buf[i] = 0x36 ^ sk_prf[i]; + } + memset(buf + SPX_N, 0x36, SPX_SHAX_BLOCK_BYTES - SPX_N); + + shaX_inc_init(&state); + shaX_inc_blocks(&state, buf, 1); + + memcpy(buf, optrand, SPX_N); + + /* If optrand + message cannot fill up an entire block */ + if (SPX_N + mlen < SPX_SHAX_BLOCK_BYTES) { + memcpy(buf + SPX_N, m, mlen); + shaX_inc_finalize(buf + SPX_SHAX_BLOCK_BYTES, &state, + buf, mlen + SPX_N); + } + /* Otherwise first fill a block, so that finalize only uses the message */ + else { + memcpy(buf + SPX_N, m, SPX_SHAX_BLOCK_BYTES - SPX_N); + shaX_inc_blocks(&state, buf, 1); + + m += SPX_SHAX_BLOCK_BYTES - SPX_N; + mlen -= SPX_SHAX_BLOCK_BYTES - SPX_N; + shaX_inc_finalize(buf + SPX_SHAX_BLOCK_BYTES, &state, m, mlen); + } + + for (i = 0; i < SPX_N; i++) { + buf[i] = 0x5c ^ sk_prf[i]; + } + memset(buf + SPX_N, 0x5c, SPX_SHAX_BLOCK_BYTES - SPX_N); + + shaX(buf, buf, SPX_SHAX_BLOCK_BYTES + SPX_SHAX_OUTPUT_BYTES); + memcpy(R, buf, SPX_N); +} + +/** + * Computes the message hash using R, the public key, and the message. + * Outputs the message digest and the index of the leaf. The index is split in + * the tree index and the leaf index, for convenient copying to an address. + */ +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { + (void)ctx; +#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) +#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) +#define SPX_LEAF_BITS SPX_TREE_HEIGHT +#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) +#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) + + unsigned char seed[2 * SPX_N + SPX_SHAX_OUTPUT_BYTES]; + + /* Round to nearest multiple of SPX_SHAX_BLOCK_BYTES */ +#define SPX_INBLOCKS (((SPX_N + SPX_PK_BYTES + SPX_SHAX_BLOCK_BYTES - 1) & \ + -SPX_SHAX_BLOCK_BYTES) / SPX_SHAX_BLOCK_BYTES) + unsigned char inbuf[SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES]; + + unsigned char buf[SPX_DGST_BYTES]; + unsigned char *bufp = buf; + shaXstate state; + + shaX_inc_init(&state); + + // seed: SHA-X(R ‖ PK.seed ‖ PK.root ‖ M) + memcpy(inbuf, R, SPX_N); + memcpy(inbuf + SPX_N, pk, SPX_PK_BYTES); + + /* If R + pk + message cannot fill up an entire block */ + if (SPX_N + SPX_PK_BYTES + mlen < SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES) { + memcpy(inbuf + SPX_N + SPX_PK_BYTES, m, mlen); + shaX_inc_finalize(seed + 2 * SPX_N, &state, inbuf, SPX_N + SPX_PK_BYTES + mlen); + } + /* Otherwise first fill a block, so that finalize only uses the message */ + else { + memcpy(inbuf + SPX_N + SPX_PK_BYTES, m, + SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES - SPX_N - SPX_PK_BYTES); + shaX_inc_blocks(&state, inbuf, SPX_INBLOCKS); + + m += SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES - SPX_N - SPX_PK_BYTES; + mlen -= SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES - SPX_N - SPX_PK_BYTES; + shaX_inc_finalize(seed + 2 * SPX_N, &state, m, (size_t)mlen); + } + + // H_msg: MGF1-SHA-X(R ‖ PK.seed ‖ seed) + memcpy(seed, R, SPX_N); + memcpy(seed + SPX_N, pk, SPX_N); + + /* By doing this in two steps, we prevent hashing the message twice; + otherwise each iteration in MGF1 would hash the message again. */ + mgf1_X(bufp, SPX_DGST_BYTES, seed, 2 * SPX_N + SPX_SHAX_OUTPUT_BYTES); + + memcpy(digest, bufp, SPX_FORS_MSG_BYTES); + bufp += SPX_FORS_MSG_BYTES; + + + *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); + *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); + bufp += SPX_TREE_BYTES; + + *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); + *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); +} + + diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_clean/merkle.c b/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_clean/merkle.c new file mode 100644 index 0000000000..0c1479fd93 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_clean/merkle.c @@ -0,0 +1,59 @@ +#include +#include + +#include "address.h" +#include "merkle.h" +#include "params.h" +#include "utils.h" +#include "utilsx1.h" +#include "wots.h" +#include "wotsx1.h" + +/* + * This generates a Merkle signature (WOTS signature followed by the Merkle + * authentication path). This is in this file because most of the complexity + * is involved with the WOTS signature; the Merkle authentication path logic + * is mostly hidden in treehashx4 + */ +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf) { + unsigned char *auth_path = sig + SPX_WOTS_BYTES; + struct leaf_info_x1 info = { 0 }; + unsigned steps[ SPX_WOTS_LEN ]; + + info.wots_sig = sig; + chain_lengths(steps, root); + info.wots_steps = steps; + + set_type(&tree_addr[0], SPX_ADDR_TYPE_HASHTREE); + set_type(&info.pk_addr[0], SPX_ADDR_TYPE_WOTSPK); + copy_subtree_addr(&info.leaf_addr[0], wots_addr); + copy_subtree_addr(&info.pk_addr[0], wots_addr); + + info.wots_sign_leaf = idx_leaf; + + treehashx1(root, auth_path, ctx, + idx_leaf, 0, + SPX_TREE_HEIGHT, + wots_gen_leafx1, + tree_addr, &info); +} + +/* Compute root node of the top-most subtree. */ +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { + /* We do not need the auth path in key generation, but it simplifies the + code to have just one treehash routine that computes both root and path + in one function. */ + unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; + uint32_t top_tree_addr[8] = {0}; + uint32_t wots_addr[8] = {0}; + + set_layer_addr(top_tree_addr, SPX_D - 1); + set_layer_addr(wots_addr, SPX_D - 1); + + merkle_sign(auth_path, root, ctx, + wots_addr, top_tree_addr, + (uint32_t)~0 /* ~0 means "don't bother generating an auth path */ ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_clean/merkle.h b/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_clean/merkle.h new file mode 100644 index 0000000000..769cf2e970 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_clean/merkle.h @@ -0,0 +1,21 @@ +#ifndef MERKLE_H_ +#define MERKLE_H_ + +#include + +#include "context.h" +#include "params.h" + +/* Generate a Merkle signature (WOTS signature followed by the Merkle */ +/* authentication path) */ +#define merkle_sign SPX_NAMESPACE(merkle_sign) +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf); + +/* Compute the root node of the top-most subtree. */ +#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); + +#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_clean/nistapi.h b/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_clean/nistapi.h new file mode 100644 index 0000000000..3cb71afad4 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_clean/nistapi.h @@ -0,0 +1,87 @@ +#ifndef SPX_API_H +#define SPX_API_H + +#include +#include + +#include "params.h" + +#define CRYPTO_ALGNAME "SPHINCS+" + +#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES +#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES +#define CRYPTO_BYTES SPX_BYTES +#define CRYPTO_SEEDBYTES (3*SPX_N) + +/* + * Returns the length of a secret key, in bytes + */ +#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) +size_t crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) +size_t crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) +size_t crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) +size_t crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +#define crypto_sign SPX_NAMESPACE(crypto_sign) +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_clean/params.h b/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_clean/params.h new file mode 100644 index 0000000000..c12582312c --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_clean/params.h @@ -0,0 +1,61 @@ +#ifndef SPX_PARAMS_H +#define SPX_PARAMS_H + +#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSSHA2192FSIMPLE_CLEAN_##s + +/* Hash output length in bytes. */ +#define SPX_N 24 +/* Height of the hypertree. */ +#define SPX_FULL_HEIGHT 66 +/* Number of subtree layer. */ +#define SPX_D 22 +/* FORS tree dimensions. */ +#define SPX_FORS_HEIGHT 8 +#define SPX_FORS_TREES 33 +/* Winternitz parameter, */ +#define SPX_WOTS_W 16 + +/* The hash function is defined by linking a different hash.c file, as opposed + to setting a #define constant. */ + +/* This is a SHA2-based parameter set, hence whether we use SHA-256 + * exclusively or we use both SHA-256 and SHA-512 is controlled by + * the following #define */ +#define SPX_SHA512 1 /* Use SHA-512 for H and T_l, l >= 2 */ + +/* For clarity */ +#define SPX_ADDR_BYTES 32 + +/* WOTS parameters. */ +#define SPX_WOTS_LOGW 4 + +#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) + +/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ +#define SPX_WOTS_LEN2 3 + +#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) +#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) +#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES + +/* Subtree size. */ +#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) + +//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT +// #error SPX_D should always divide SPX_FULL_HEIGHT +//#endif + +/* FORS parameters. */ +#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) +#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) +#define SPX_FORS_PK_BYTES SPX_N + +/* Resulting SPX sizes. */ +#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ + SPX_FULL_HEIGHT * SPX_N) +#define SPX_PK_BYTES (2 * SPX_N) +#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) + +#include "sha2_offsets.h" + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_clean/sha2_offsets.h b/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_clean/sha2_offsets.h new file mode 100644 index 0000000000..6e3584f7a4 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_clean/sha2_offsets.h @@ -0,0 +1,27 @@ +#ifndef SHA2_OFFSETS_H_ +#define SHA2_OFFSETS_H_ + +#define SPX_SHA256_BLOCK_BYTES 64 +#define SPX_SHA256_OUTPUT_BYTES 32 + +#define SPX_SHA512_BLOCK_BYTES 128 +#define SPX_SHA512_OUTPUT_BYTES 64 + +/* + * Offsets of various fields in the address structure when we use SHA2 as + * the Sphincs+ hash function + */ + +#define SPX_OFFSET_LAYER 0 /* The byte used to specify the Merkle tree layer */ +#define SPX_OFFSET_TREE 1 /* The start of the 8 byte field used to specify the tree */ +#define SPX_OFFSET_TYPE 9 /* The byte used to specify the hash type (reason) */ +#define SPX_OFFSET_KP_ADDR2 12 /* The high byte used to specify the key pair (which one-time signature) */ +#define SPX_OFFSET_KP_ADDR1 13 /* The low byte used to specify the key pair */ +#define SPX_OFFSET_CHAIN_ADDR 17 /* The byte used to specify the chain address (which Winternitz chain) */ +#define SPX_OFFSET_HASH_ADDR 21 /* The byte used to specify the hash address (where in the Winternitz chain) */ +#define SPX_OFFSET_TREE_HGT 17 /* The byte used to specify the height of this node in the FORS or Merkle tree */ +#define SPX_OFFSET_TREE_INDEX 18 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ + +#define SPX_SHA2 1 + +#endif /* SHA2_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_clean/sign.c b/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_clean/sign.c new file mode 100644 index 0000000000..9d0c7d1b22 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_clean/sign.c @@ -0,0 +1,286 @@ +#include +#include +#include + +#include "address.h" +#include "context.h" +#include "fors.h" +#include "hash.h" +#include "merkle.h" +#include "nistapi.h" +#include "params.h" +#include "randombytes.h" +#include "thash.h" +#include "utils.h" +#include "wots.h" + +/* + * Returns the length of a secret key, in bytes + */ +size_t crypto_sign_secretkeybytes(void) { + return CRYPTO_SECRETKEYBYTES; +} + +/* + * Returns the length of a public key, in bytes + */ +size_t crypto_sign_publickeybytes(void) { + return CRYPTO_PUBLICKEYBYTES; +} + +/* + * Returns the length of a signature, in bytes + */ +size_t crypto_sign_bytes(void) { + return CRYPTO_BYTES; +} + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +size_t crypto_sign_seedbytes(void) { + return CRYPTO_SEEDBYTES; +} + +/* + * Generates an SPX key pair given a seed of length + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [PUB_SEED || root] + */ +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed) { + spx_ctx ctx; + + /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ + memcpy(sk, seed, CRYPTO_SEEDBYTES); + + memcpy(pk, sk + 2 * SPX_N, SPX_N); + + memcpy(ctx.pub_seed, pk, SPX_N); + memcpy(ctx.sk_seed, sk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + /* Compute root node of the top-most subtree. */ + merkle_gen_root(sk + 3 * SPX_N, &ctx); + + // cleanup + free_hash_function(&ctx); + + memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); + + return 0; +} + +/* + * Generates an SPX key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [PUB_SEED || root] + */ +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { + uint8_t seed[CRYPTO_SEEDBYTES]; + randombytes(seed, CRYPTO_SEEDBYTES); + crypto_sign_seed_keypair(pk, sk, seed); + + return 0; +} + +/** + * Returns an array containing a detached signature. + */ +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk) { + spx_ctx ctx; + + const uint8_t *sk_prf = sk + SPX_N; + const uint8_t *pk = sk + 2 * SPX_N; + + uint8_t optrand[SPX_N]; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t root[SPX_N]; + uint32_t i; + uint64_t tree; + uint32_t idx_leaf; + uint32_t wots_addr[8] = {0}; + uint32_t tree_addr[8] = {0}; + + memcpy(ctx.sk_seed, sk, SPX_N); + memcpy(ctx.pub_seed, pk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + + /* Optionally, signing can be made non-deterministic using optrand. + This can help counter side-channel attacks that would benefit from + getting a large number of traces when the signer uses the same nodes. */ + randombytes(optrand, SPX_N); + /* Compute the digest randomization value. */ + gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); + + /* Derive the message digest and leaf index from R, PK and M. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; + + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); + + /* Sign the message hash using FORS. */ + fors_sign(sig, root, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); + sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; + + /* Update the indices for the next layer. */ + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; + } + + free_hash_function(&ctx); + + *siglen = SPX_BYTES; + + return 0; +} + +/** + * Verifies a detached signature and message under a given public key. + */ +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk) { + spx_ctx ctx; + const uint8_t *pub_root = pk + SPX_N; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t wots_pk[SPX_WOTS_BYTES]; + uint8_t root[SPX_N]; + uint8_t leaf[SPX_N]; + unsigned int i; + uint64_t tree; + uint32_t idx_leaf; + uint32_t wots_addr[8] = {0}; + uint32_t tree_addr[8] = {0}; + uint32_t wots_pk_addr[8] = {0}; + + if (siglen != SPX_BYTES) { + return -1; + } + + memcpy(ctx.pub_seed, pk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); + + /* Derive the message digest and leaf index from R || PK || M. */ + /* The additional SPX_N is a result of the hash domain separator. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; + + /* Layer correctly defaults to 0, so no need to set_layer_addr */ + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); + + fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + /* For each subtree.. */ + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + copy_keypair_addr(wots_pk_addr, wots_addr); + + /* The WOTS public key is only correct if the signature was correct. */ + /* Initially, root is the FORS pk, but on subsequent iterations it is + the root of the subtree below the currently processed subtree. */ + wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); + sig += SPX_WOTS_BYTES; + + /* Compute the leaf node using the WOTS public key. */ + thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); + + /* Compute the root node of this subtree. */ + compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, + &ctx, tree_addr); + sig += SPX_TREE_HEIGHT * SPX_N; + + /* Update the indices for the next layer. */ + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; + } + + // cleanup + free_hash_function(&ctx); + + /* Check if the root node equals the root node in the public key. */ + if (memcmp(root, pub_root, SPX_N) != 0) { + return -1; + } + + return 0; +} + + +/** + * Returns an array containing the signature followed by the message. + */ +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk) { + size_t siglen; + + crypto_sign_signature(sm, &siglen, m, mlen, sk); + + memmove(sm + SPX_BYTES, m, mlen); + *smlen = siglen + mlen; + + return 0; +} + +/** + * Verifies a given signature-message pair under a given public key. + */ +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk) { + /* The API caller does not necessarily know what size a signature should be + but SPHINCS+ signatures are always exactly SPX_BYTES. */ + if (smlen < SPX_BYTES) { + memset(m, 0, smlen); + *mlen = 0; + return -1; + } + + *mlen = smlen - SPX_BYTES; + + if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { + memset(m, 0, smlen); + *mlen = 0; + return -1; + } + + /* If verification was successful, move the message to the right place. */ + memmove(m, sm + SPX_BYTES, *mlen); + + return 0; +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_clean/thash.h b/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_clean/thash.h new file mode 100644 index 0000000000..8687ccfb4d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_clean/thash.h @@ -0,0 +1,13 @@ +#ifndef SPX_THASH_H +#define SPX_THASH_H + +#include "context.h" +#include "params.h" + +#include + +#define thash SPX_NAMESPACE(thash) +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_clean/thash_sha2_simple.c b/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_clean/thash_sha2_simple.c new file mode 100644 index 0000000000..87badc4d53 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_clean/thash_sha2_simple.c @@ -0,0 +1,53 @@ +#include +#include + +#include "thash.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "sha2.h" +#include "utils.h" + +static void thash_512(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]); + +/** + * Takes an array of inblocks concatenated arrays of SPX_N bytes. + */ +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]) { + if (inblocks > 1) { + thash_512(out, in, inblocks, ctx, addr); + return; + } + + unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES]; + sha256ctx sha2_state; + PQCLEAN_VLA(uint8_t, buf, SPX_SHA256_ADDR_BYTES + inblocks * SPX_N); + + /* Retrieve precomputed state containing pub_seed */ + sha256_inc_ctx_clone(&sha2_state, &ctx->state_seeded); + + memcpy(buf, addr, SPX_SHA256_ADDR_BYTES); + memcpy(buf + SPX_SHA256_ADDR_BYTES, in, inblocks * SPX_N); + + sha256_inc_finalize(outbuf, &sha2_state, buf, SPX_SHA256_ADDR_BYTES + inblocks * SPX_N); + memcpy(out, outbuf, SPX_N); +} + +static void thash_512(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]) { + unsigned char outbuf[SPX_SHA512_OUTPUT_BYTES]; + sha512ctx sha2_state; + PQCLEAN_VLA(uint8_t, buf, SPX_SHA256_ADDR_BYTES + inblocks * SPX_N); + + /* Retrieve precomputed state containing pub_seed */ + sha512_inc_ctx_clone(&sha2_state, &ctx->state_seeded_512); + + memcpy(buf, addr, SPX_SHA256_ADDR_BYTES); + memcpy(buf + SPX_SHA256_ADDR_BYTES, in, inblocks * SPX_N); + + sha512_inc_finalize(outbuf, &sha2_state, buf, SPX_SHA256_ADDR_BYTES + inblocks * SPX_N); + memcpy(out, outbuf, SPX_N); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_clean/utils.c b/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_clean/utils.c new file mode 100644 index 0000000000..177b541fb9 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_clean/utils.c @@ -0,0 +1,148 @@ +#include + +#include "utils.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "thash.h" + +/** + * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. + */ +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in) { + int i; + + /* Iterate over out in decreasing order, for big-endianness. */ + for (i = (signed int)outlen - 1; i >= 0; i--) { + out[i] = in & 0xff; + in = in >> 8; + } +} + +void u32_to_bytes(unsigned char *out, uint32_t in) { + out[0] = (unsigned char)(in >> 24); + out[1] = (unsigned char)(in >> 16); + out[2] = (unsigned char)(in >> 8); + out[3] = (unsigned char)in; +} + +/** + * Converts the inlen bytes in 'in' from big-endian byte order to an integer. + */ +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { + unsigned long long retval = 0; + unsigned int i; + + for (i = 0; i < inlen; i++) { + retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); + } + return retval; +} + +/** + * Computes a root node given a leaf and an auth path. + * Expects address to be complete other than the tree_height and tree_index. + */ +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]) { + uint32_t i; + unsigned char buffer[2 * SPX_N]; + + /* If leaf_idx is odd (last bit = 1), current path element is a right child + and auth_path has to go left. Otherwise it is the other way around. */ + if (leaf_idx & 1) { + memcpy(buffer + SPX_N, leaf, SPX_N); + memcpy(buffer, auth_path, SPX_N); + } else { + memcpy(buffer, leaf, SPX_N); + memcpy(buffer + SPX_N, auth_path, SPX_N); + } + auth_path += SPX_N; + + for (i = 0; i < tree_height - 1; i++) { + leaf_idx >>= 1; + idx_offset >>= 1; + /* Set the address of the node we're creating. */ + set_tree_height(addr, i + 1); + set_tree_index(addr, leaf_idx + idx_offset); + + /* Pick the right or left neighbor, depending on parity of the node. */ + if (leaf_idx & 1) { + thash(buffer + SPX_N, buffer, 2, ctx, addr); + memcpy(buffer, auth_path, SPX_N); + } else { + thash(buffer, buffer, 2, ctx, addr); + memcpy(buffer + SPX_N, auth_path, SPX_N); + } + auth_path += SPX_N; + } + + /* The last iteration is exceptional; we do not copy an auth_path node. */ + leaf_idx >>= 1; + idx_offset >>= 1; + set_tree_height(addr, tree_height); + set_tree_index(addr, leaf_idx + idx_offset); + thash(root, buffer, 2, ctx, addr); +} + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx * /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]) { + PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); + PQCLEAN_VLA(unsigned int, heights, tree_height + 1); + unsigned int offset = 0; + uint32_t idx; + uint32_t tree_idx; + + for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { + /* Add the next leaf node to the stack. */ + gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); + offset++; + heights[offset - 1] = 0; + + /* If this is a node we need for the auth path.. */ + if ((leaf_idx ^ 0x1) == idx) { + memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); + } + + /* While the top-most nodes are of equal height.. */ + while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { + /* Compute index of the new node, in the next layer. */ + tree_idx = (idx >> (heights[offset - 1] + 1)); + + /* Set the address of the node we're creating. */ + set_tree_height(tree_addr, heights[offset - 1] + 1); + set_tree_index(tree_addr, + tree_idx + (idx_offset >> (heights[offset - 1] + 1))); + /* Hash the top-most nodes from the stack together. */ + thash(stack + (offset - 2)*SPX_N, + stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); + offset--; + /* Note that the top-most node is now one layer higher. */ + heights[offset - 1]++; + + /* If this is a node we need for the auth path.. */ + if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { + memcpy(auth_path + heights[offset - 1]*SPX_N, + stack + (offset - 1)*SPX_N, SPX_N); + } + } + } + memcpy(root, stack, SPX_N); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_clean/utils.h b/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_clean/utils.h new file mode 100644 index 0000000000..64f5d5a53a --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_clean/utils.h @@ -0,0 +1,58 @@ +#ifndef SPX_UTILS_H +#define SPX_UTILS_H + +#include + +#include "compat.h" +#include "context.h" +#include "params.h" + + +/* To support MSVC use alloca() instead of VLAs. See #20. */ + + +/** + * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. + */ +#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in); +#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) +void u32_to_bytes(unsigned char *out, uint32_t in); + +/** + * Converts the inlen bytes in 'in' from big-endian byte order to an integer. + */ +#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); + +/** + * Computes a root node given a leaf and an auth path. + * Expects address to be complete other than the tree_height and tree_index. + */ +#define compute_root SPX_NAMESPACE(compute_root) +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]); + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +#define treehash SPX_NAMESPACE(treehash) +void treehash(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx *ctx /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]); + + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_clean/utilsx1.c b/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_clean/utilsx1.c new file mode 100644 index 0000000000..fccb69b35d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_clean/utilsx1.c @@ -0,0 +1,100 @@ +#include + +#include "utilsx1.h" + +#include "address.h" +#include "params.h" +#include "thash.h" +#include "utils.h" + +/* + * Generate the entire Merkle tree, computing the authentication path for + * leaf_idx, and the resulting root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) + * + * This expects tree_addr to be initialized to the addr structures for the + * Merkle tree nodes + * + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + * + * This works by using the standard Merkle tree building algorithm, + */ +void treehashx1(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, + uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* Where to write the leaves */, + const spx_ctx * /* ctx */, + uint32_t idx, void *info), + uint32_t tree_addr[8], + void *info) { + /* This is where we keep the intermediate nodes */ + PQCLEAN_VLA(uint8_t, stack, tree_height * SPX_N); + + uint32_t idx; + uint32_t max_idx = (uint32_t)((1 << tree_height) - 1); + for (idx = 0;; idx++) { + unsigned char current[2 * SPX_N]; /* Current logical node is at */ + /* index[SPX_N]. We do this to minimize the number of copies */ + /* needed during a thash */ + gen_leaf( ¤t[SPX_N], ctx, idx + idx_offset, + info ); + + /* Now combine the freshly generated right node with previously */ + /* generated left ones */ + uint32_t internal_idx_offset = idx_offset; + uint32_t internal_idx = idx; + uint32_t internal_leaf = leaf_idx; + uint32_t h; /* The height we are in the Merkle tree */ + for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { + + /* Check if we hit the top of the tree */ + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[SPX_N], SPX_N ); + return; + } + + /* + * Check if the node we have is a part of the + * authentication path; if it is, write it out + */ + if ((internal_idx ^ internal_leaf) == 0x01) { + memcpy( &auth_path[ h * SPX_N ], + ¤t[SPX_N], + SPX_N ); + } + + /* + * Check if we're at a left child; if so, stop going up the stack + * Exception: if we've reached the end of the tree, keep on going + * (so we combine the last 4 nodes into the one root node in two + * more iterations) + */ + if ((internal_idx & 1) == 0 && idx < max_idx) { + break; + } + + /* Ok, we're at a right node */ + /* Now combine the left and right logical nodes together */ + + /* Set the address of the node we're creating. */ + internal_idx_offset >>= 1; + set_tree_height(tree_addr, h + 1); + set_tree_index(tree_addr, internal_idx / 2 + internal_idx_offset ); + + unsigned char *left = &stack[h * SPX_N]; + memcpy( ¤t[0], left, SPX_N ); + thash( ¤t[1 * SPX_N], + ¤t[0 * SPX_N], + 2, ctx, tree_addr); + } + + /* We've hit a left child; save the current for when we get the */ + /* corresponding right right */ + memcpy( &stack[h * SPX_N], ¤t[SPX_N], SPX_N); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_clean/utilsx1.h b/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_clean/utilsx1.h new file mode 100644 index 0000000000..e911d17d53 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_clean/utilsx1.h @@ -0,0 +1,27 @@ +#ifndef SPX_UTILSX4_H +#define SPX_UTILSX4_H + +#include + +#include "context.h" +#include "params.h" + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +#define treehashx1 SPX_NAMESPACE(treehashx1) +void treehashx1(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* Where to write the leaf */, + const spx_ctx * /* ctx */, + uint32_t addr_idx, void *info), + uint32_t tree_addrx4[8], void *info); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_clean/wots.c b/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_clean/wots.c new file mode 100644 index 0000000000..249717aaa8 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_clean/wots.c @@ -0,0 +1,108 @@ +#include +#include + +#include "wots.h" +#include "wotsx1.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "thash.h" +#include "utils.h" +#include "utilsx1.h" + +// TODO clarify address expectations, and make them more uniform. +// TODO i.e. do we expect types to be set already? +// TODO and do we expect modifications or copies? + +/** + * Computes the chaining function. + * out and in have to be n-byte arrays. + * + * Interprets in as start-th value of the chain. + * addr has to contain the address of the chain. + */ +static void gen_chain(unsigned char *out, const unsigned char *in, + unsigned int start, unsigned int steps, + const spx_ctx *ctx, uint32_t addr[8]) { + uint32_t i; + + /* Initialize out with the value at position 'start'. */ + memcpy(out, in, SPX_N); + + /* Iterate 'steps' calls to the hash function. */ + for (i = start; i < (start + steps) && i < SPX_WOTS_W; i++) { + set_hash_addr(addr, i); + thash(out, out, 1, ctx, addr); + } +} + +/** + * base_w algorithm as described in draft. + * Interprets an array of bytes as integers in base w. + * This only works when log_w is a divisor of 8. + */ +static void base_w(unsigned int *output, const int out_len, + const unsigned char *input) { + int in = 0; + int out = 0; + unsigned char total = 0; + int bits = 0; + int consumed; + + for (consumed = 0; consumed < out_len; consumed++) { + if (bits == 0) { + total = input[in]; + in++; + bits += 8; + } + bits -= SPX_WOTS_LOGW; + output[out] = (total >> bits) & (SPX_WOTS_W - 1); + out++; + } +} + +/* Computes the WOTS+ checksum over a message (in base_w). */ +static void wots_checksum(unsigned int *csum_base_w, + const unsigned int *msg_base_w) { + unsigned int csum = 0; + unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; + unsigned int i; + + /* Compute checksum. */ + for (i = 0; i < SPX_WOTS_LEN1; i++) { + csum += SPX_WOTS_W - 1 - msg_base_w[i]; + } + + /* Convert checksum to base_w. */ + /* Make sure expected empty zero bits are the least significant bits. */ + csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); + ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); + base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); +} + +/* Takes a message and derives the matching chain lengths. */ +void chain_lengths(unsigned int *lengths, const unsigned char *msg) { + base_w(lengths, SPX_WOTS_LEN1, msg); + wots_checksum(lengths + SPX_WOTS_LEN1, lengths); +} + +/** + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. + * + * Writes the computed public key to 'pk'. + */ +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]) { + unsigned int lengths[SPX_WOTS_LEN]; + uint32_t i; + + chain_lengths(lengths, msg); + + for (i = 0; i < SPX_WOTS_LEN; i++) { + set_chain_addr(addr, i); + gen_chain(pk + i * SPX_N, sig + i * SPX_N, + lengths[i], SPX_WOTS_W - 1 - lengths[i], ctx, addr); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_clean/wots.h b/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_clean/wots.h new file mode 100644 index 0000000000..4e7692eeef --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_clean/wots.h @@ -0,0 +1,25 @@ +#ifndef SPX_WOTS_H +#define SPX_WOTS_H + +#include + +#include "context.h" +#include "params.h" + +/** + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. + * + * Writes the computed public key to 'pk'. + */ +#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]); + +/* + * Compute the chain lengths needed for a given message hash + */ +#define chain_lengths SPX_NAMESPACE(chain_lengths) +void chain_lengths(unsigned int *lengths, const unsigned char *msg); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_clean/wotsx1.c b/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_clean/wotsx1.c new file mode 100644 index 0000000000..3adec78dfb --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_clean/wotsx1.c @@ -0,0 +1,76 @@ +#include +#include + +#include "wots.h" +#include "wotsx1.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "thash.h" +#include "utils.h" + +/* + * This generates a WOTS public key + * It also generates the WOTS signature if leaf_info indicates + * that we're signing with this WOTS key + */ +void wots_gen_leafx1(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info) { + struct leaf_info_x1 *info = v_info; + uint32_t *leaf_addr = info->leaf_addr; + uint32_t *pk_addr = info->pk_addr; + unsigned int i, k; + unsigned char pk_buffer[ SPX_WOTS_BYTES ]; + unsigned char *buffer; + uint32_t wots_k_mask; + + if (leaf_idx == info->wots_sign_leaf) { + /* We're traversing the leaf that's signing; generate the WOTS */ + /* signature */ + wots_k_mask = 0; + } else { + /* Nope, we're just generating pk's; turn off the signature logic */ + wots_k_mask = (uint32_t)~0; + } + + set_keypair_addr( leaf_addr, leaf_idx ); + set_keypair_addr( pk_addr, leaf_idx ); + + for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { + uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k to */ + /* the step if we're generating a signature, ~0 if we're not */ + + /* Start with the secret seed */ + set_chain_addr(leaf_addr, i); + set_hash_addr(leaf_addr, 0); + set_type(leaf_addr, SPX_ADDR_TYPE_WOTSPRF); + + prf_addr(buffer, ctx, leaf_addr); + + set_type(leaf_addr, SPX_ADDR_TYPE_WOTS); + + /* Iterate down the WOTS chain */ + for (k = 0;; k++) { + /* Check if this is the value that needs to be saved as a */ + /* part of the WOTS signature */ + if (k == wots_k) { + memcpy( info->wots_sig + i * SPX_N, buffer, SPX_N ); + } + + /* Check if we hit the top of the chain */ + if (k == SPX_WOTS_W - 1) { + break; + } + + /* Iterate one step on the chain */ + set_hash_addr(leaf_addr, k); + + thash(buffer, buffer, 1, ctx, leaf_addr); + } + } + + /* Do the final thash to generate the public keys */ + thash(dest, pk_buffer, SPX_WOTS_LEN, ctx, pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_clean/wotsx1.h b/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_clean/wotsx1.h new file mode 100644 index 0000000000..e617929f96 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192f-simple_clean/wotsx1.h @@ -0,0 +1,39 @@ +#ifndef WOTSX1_H_ +#define WOTSX1_H_ + +#include + +#include "context.h" +#include "params.h" + +/* + * This is here to provide an interface to the internal wots_gen_leafx1 + * routine. While this routine is not referenced in the package outside of + * wots.c, it is called from the stand-alone benchmark code to characterize + * the performance + */ +struct leaf_info_x1 { + unsigned char *wots_sig; + uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ + uint32_t *wots_steps; + uint32_t leaf_addr[8]; + uint32_t pk_addr[8]; +}; + +/* Macro to set the leaf_info to something 'benign', that is, it would */ +/* run with the same time as it does during the real signing process */ +/* Used only by the benchmark code */ +#define INITIALIZE_LEAF_INFO_X1(info, addr, step_buffer) { \ + (info).wots_sig = 0; \ + (info).wots_sign_leaf = ~0; \ + (info).wots_steps = step_buffer; \ + memcpy( &(info).leaf_addr[0], (addr), 32 ); \ + memcpy( &(info).pk_addr[0], (addr), 32 ); \ + } + +#define wots_gen_leafx1 SPX_NAMESPACE(wots_gen_leafx1) +void wots_gen_leafx1(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info); + +#endif /* WOTSX1_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/LICENSE b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/LICENSE new file mode 100644 index 0000000000..670154e353 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/LICENSE @@ -0,0 +1,116 @@ +CC0 1.0 Universal + +Statement of Purpose + +The laws of most jurisdictions throughout the world automatically confer +exclusive Copyright and Related Rights (defined below) upon the creator and +subsequent owner(s) (each and all, an "owner") of an original work of +authorship and/or a database (each, a "Work"). + +Certain owners wish to permanently relinquish those rights to a Work for the +purpose of contributing to a commons of creative, cultural and scientific +works ("Commons") that the public can reliably and without fear of later +claims of infringement build upon, modify, incorporate in other works, reuse +and redistribute as freely as possible in any form whatsoever and for any +purposes, including without limitation commercial purposes. These owners may +contribute to the Commons to promote the ideal of a free culture and the +further production of creative, cultural and scientific works, or to gain +reputation or greater distribution for their Work in part through the use and +efforts of others. + +For these and/or other purposes and motivations, and without any expectation +of additional consideration or compensation, the person associating CC0 with a +Work (the "Affirmer"), to the extent that he or she is an owner of Copyright +and Related Rights in the Work, voluntarily elects to apply CC0 to the Work +and publicly distribute the Work under its terms, with knowledge of his or her +Copyright and Related Rights in the Work and the meaning and intended legal +effect of CC0 on those rights. + +1. Copyright and Related Rights. A Work made available under CC0 may be +protected by copyright and related or neighboring rights ("Copyright and +Related Rights"). Copyright and Related Rights include, but are not limited +to, the following: + + i. the right to reproduce, adapt, distribute, perform, display, communicate, + and translate a Work; + + ii. moral rights retained by the original author(s) and/or performer(s); + + iii. publicity and privacy rights pertaining to a person's image or likeness + depicted in a Work; + + iv. rights protecting against unfair competition in regards to a Work, + subject to the limitations in paragraph 4(a), below; + + v. rights protecting the extraction, dissemination, use and reuse of data in + a Work; + + vi. database rights (such as those arising under Directive 96/9/EC of the + European Parliament and of the Council of 11 March 1996 on the legal + protection of databases, and under any national implementation thereof, + including any amended or successor version of such directive); and + + vii. other similar, equivalent or corresponding rights throughout the world + based on applicable law or treaty, and any national implementations thereof. + +2. Waiver. To the greatest extent permitted by, but not in contravention of, +applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and +unconditionally waives, abandons, and surrenders all of Affirmer's Copyright +and Related Rights and associated claims and causes of action, whether now +known or unknown (including existing as well as future claims and causes of +action), in the Work (i) in all territories worldwide, (ii) for the maximum +duration provided by applicable law or treaty (including future time +extensions), (iii) in any current or future medium and for any number of +copies, and (iv) for any purpose whatsoever, including without limitation +commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes +the Waiver for the benefit of each member of the public at large and to the +detriment of Affirmer's heirs and successors, fully intending that such Waiver +shall not be subject to revocation, rescission, cancellation, termination, or +any other legal or equitable action to disrupt the quiet enjoyment of the Work +by the public as contemplated by Affirmer's express Statement of Purpose. + +3. Public License Fallback. Should any part of the Waiver for any reason be +judged legally invalid or ineffective under applicable law, then the Waiver +shall be preserved to the maximum extent permitted taking into account +Affirmer's express Statement of Purpose. In addition, to the extent the Waiver +is so judged Affirmer hereby grants to each affected person a royalty-free, +non transferable, non sublicensable, non exclusive, irrevocable and +unconditional license to exercise Affirmer's Copyright and Related Rights in +the Work (i) in all territories worldwide, (ii) for the maximum duration +provided by applicable law or treaty (including future time extensions), (iii) +in any current or future medium and for any number of copies, and (iv) for any +purpose whatsoever, including without limitation commercial, advertising or +promotional purposes (the "License"). The License shall be deemed effective as +of the date CC0 was applied by Affirmer to the Work. Should any part of the +License for any reason be judged legally invalid or ineffective under +applicable law, such partial invalidity or ineffectiveness shall not +invalidate the remainder of the License, and in such case Affirmer hereby +affirms that he or she will not (i) exercise any of his or her remaining +Copyright and Related Rights in the Work or (ii) assert any associated claims +and causes of action with respect to the Work, in either case contrary to +Affirmer's express Statement of Purpose. + +4. Limitations and Disclaimers. + + a. No trademark or patent rights held by Affirmer are waived, abandoned, + surrendered, licensed or otherwise affected by this document. + + b. Affirmer offers the Work as-is and makes no representations or warranties + of any kind concerning the Work, express, implied, statutory or otherwise, + including without limitation warranties of title, merchantability, fitness + for a particular purpose, non infringement, or the absence of latent or + other defects, accuracy, or the present or absence of errors, whether or not + discoverable, all to the greatest extent permissible under applicable law. + + c. Affirmer disclaims responsibility for clearing rights of other persons + that may apply to the Work or any use thereof, including without limitation + any person's Copyright and Related Rights in the Work. Further, Affirmer + disclaims responsibility for obtaining any necessary consents, permissions + or other rights required for any use of the Work. + + d. Affirmer understands and acknowledges that Creative Commons is not a + party to this document and has no duty or obligation with respect to this + CC0 or use of the Work. + +For more information, please see + diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/address.c b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/address.c new file mode 100644 index 0000000000..d49d9f3b6b --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/address.c @@ -0,0 +1,95 @@ +#include +#include + +#include "address.h" +#include "params.h" +#include "utils.h" + +/* + * Specify which level of Merkle tree (the "layer") we're working on + */ +void set_layer_addr(uint32_t addr[8], uint32_t layer) { + ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; +} + +/* + * Specify which Merkle tree within the level (the "tree address") we're working on + */ +void set_tree_addr(uint32_t addr[8], uint64_t tree) { + ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); +} + +/* + * Specify the reason we'll use this address structure for, that is, what + * hash will we compute with it. This is used so that unrelated types of + * hashes don't accidentally get the same address structure. The type will be + * one of the SPX_ADDR_TYPE constants + */ +void set_type(uint32_t addr[8], uint32_t type) { + ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; +} + +/* + * Copy the layer and tree fields of the address structure. This is used + * when we're doing multiple types of hashes within the same Merkle tree + */ +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); +} + +/* These functions are used for OTS addresses. */ + +/* + * Specify which Merkle leaf we're working on; that is, which OTS keypair + * we're talking about. + */ +void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { + /* We have > 256 OTS at the bottom of the Merkle tree; to specify */ + /* which one, we'd need to express it in two bytes */ + ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR2] = (unsigned char)(keypair >> 8); + ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; +} + +/* + * Copy the layer, tree and keypair fields of the address structure. This is + * used when we're doing multiple things within the same OTS keypair + */ +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); + ((unsigned char *)out)[SPX_OFFSET_KP_ADDR2] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR2]; + ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; +} + +/* + * Specify which Merkle chain within the OTS we're working with + * (the chain address) + */ +void set_chain_addr(uint32_t addr[8], uint32_t chain) { + ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; +} + +/* + * Specify where in the Merkle chain we are +* (the hash address) + */ +void set_hash_addr(uint32_t addr[8], uint32_t hash) { + ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; +} + +/* These functions are used for all hash tree addresses (including FORS). */ + +/* + * Specify the height of the node in the Merkle/FORS tree we are in + * (the tree height) + */ +void set_tree_height(uint32_t addr[8], uint32_t tree_height) { + ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; +} + +/* + * Specify the distance from the left edge of the node in the Merkle/FORS tree + * (the tree index) + */ +void set_tree_index(uint32_t addr[8], uint32_t tree_index) { + u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/address.h b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/address.h new file mode 100644 index 0000000000..24a84eb40c --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/address.h @@ -0,0 +1,52 @@ +#ifndef SPX_ADDRESS_H +#define SPX_ADDRESS_H + +#include + +#include "params.h" + +/* The hash types that are passed to set_type */ +#define SPX_ADDR_TYPE_WOTS 0 +#define SPX_ADDR_TYPE_WOTSPK 1 +#define SPX_ADDR_TYPE_HASHTREE 2 +#define SPX_ADDR_TYPE_FORSTREE 3 +#define SPX_ADDR_TYPE_FORSPK 4 +#define SPX_ADDR_TYPE_WOTSPRF 5 +#define SPX_ADDR_TYPE_FORSPRF 6 + +#define set_layer_addr SPX_NAMESPACE(set_layer_addr) +void set_layer_addr(uint32_t addr[8], uint32_t layer); + +#define set_tree_addr SPX_NAMESPACE(set_tree_addr) +void set_tree_addr(uint32_t addr[8], uint64_t tree); + +#define set_type SPX_NAMESPACE(set_type) +void set_type(uint32_t addr[8], uint32_t type); + +/* Copies the layer and tree part of one address into the other */ +#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); + +/* These functions are used for WOTS and FORS addresses. */ + +#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) +void set_keypair_addr(uint32_t addr[8], uint32_t keypair); + +#define set_chain_addr SPX_NAMESPACE(set_chain_addr) +void set_chain_addr(uint32_t addr[8], uint32_t chain); + +#define set_hash_addr SPX_NAMESPACE(set_hash_addr) +void set_hash_addr(uint32_t addr[8], uint32_t hash); + +#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); + +/* These functions are used for all hash tree addresses (including FORS). */ + +#define set_tree_height SPX_NAMESPACE(set_tree_height) +void set_tree_height(uint32_t addr[8], uint32_t tree_height); + +#define set_tree_index SPX_NAMESPACE(set_tree_index) +void set_tree_index(uint32_t addr[8], uint32_t tree_index); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/api.h b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/api.h new file mode 100644 index 0000000000..7c4b1b7987 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/api.h @@ -0,0 +1,77 @@ +#ifndef PQCLEAN_SPHINCSSHA2192SROBUST_AVX2_API_H +#define PQCLEAN_SPHINCSSHA2192SROBUST_AVX2_API_H + +#include +#include + +#define PQCLEAN_SPHINCSSHA2192SROBUST_AVX2_CRYPTO_ALGNAME "SPHINCS+-sha2-192s-robust" + +#define PQCLEAN_SPHINCSSHA2192SROBUST_AVX2_CRYPTO_SECRETKEYBYTES 96 +#define PQCLEAN_SPHINCSSHA2192SROBUST_AVX2_CRYPTO_PUBLICKEYBYTES 48 +#define PQCLEAN_SPHINCSSHA2192SROBUST_AVX2_CRYPTO_BYTES 16224 + +#define PQCLEAN_SPHINCSSHA2192SROBUST_AVX2_CRYPTO_SEEDBYTES 72 + +/* + * Returns the length of a secret key, in bytes + */ +size_t PQCLEAN_SPHINCSSHA2192SROBUST_AVX2_crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +size_t PQCLEAN_SPHINCSSHA2192SROBUST_AVX2_crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +size_t PQCLEAN_SPHINCSSHA2192SROBUST_AVX2_crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +size_t PQCLEAN_SPHINCSSHA2192SROBUST_AVX2_crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +int PQCLEAN_SPHINCSSHA2192SROBUST_AVX2_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +int PQCLEAN_SPHINCSSHA2192SROBUST_AVX2_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +int PQCLEAN_SPHINCSSHA2192SROBUST_AVX2_crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +int PQCLEAN_SPHINCSSHA2192SROBUST_AVX2_crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, + const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +int PQCLEAN_SPHINCSSHA2192SROBUST_AVX2_crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +int PQCLEAN_SPHINCSSHA2192SROBUST_AVX2_crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/context.h b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/context.h new file mode 100644 index 0000000000..d3bf1c3aac --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/context.h @@ -0,0 +1,29 @@ +#ifndef SPX_CONTEXT_H +#define SPX_CONTEXT_H + +#include + +#include "params.h" +#include "sha2.h" +#include "sha256avx.h" +#include "sha512x4.h" + +// funky ordering due to optimal padding +typedef struct { + sha256x8ctx statex8_seeded; + sha512x4ctx statex4_seeded_512; + sha256ctx state_seeded; + sha512ctx state_seeded_512; + + uint8_t pub_seed[SPX_N]; + uint8_t sk_seed[SPX_N]; +} spx_ctx; + + +#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) +void initialize_hash_function(spx_ctx *ctx); + +#define free_hash_function SPX_NAMESPACE(free_hash_function) +void free_hash_function(spx_ctx *ctx); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/context_sha2.c b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/context_sha2.c new file mode 100644 index 0000000000..83c1b6585d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/context_sha2.c @@ -0,0 +1,56 @@ +#include + +#include "context.h" + +/** + * Absorb the constant pub_seed using one round of the compression function + * This initializes state_seeded and state_seeded_512, which can then be + * reused in thash + **/ +static void seed_state(spx_ctx *ctx) { + uint8_t block[SPX_SHA512_BLOCK_BYTES]; + size_t i; + + for (i = 0; i < SPX_N; ++i) { + block[i] = ctx->pub_seed[i]; + } + for (i = SPX_N; i < SPX_SHA512_BLOCK_BYTES; ++i) { + block[i] = 0; + } + /* block has been properly initialized for both SHA-256 and SHA-512 */ + + sha256_inc_init(&ctx->state_seeded); + sha256_inc_blocks(&ctx->state_seeded, block, 1); + + // initialize x8 + sha256_init8x(&ctx->statex8_seeded); + sha256_transform8x(&ctx->statex8_seeded, + block, block, block, block, block, block, block, block); + + ctx->statex8_seeded.datalen = 0; + ctx->statex8_seeded.msglen = 512; + + sha512_inc_init(&ctx->state_seeded_512); + sha512_inc_blocks(&ctx->state_seeded_512, block, 1); + + // initialize x4 + sha512_init4x(&ctx->statex4_seeded_512); + sha512_transform4x(&ctx->statex4_seeded_512, block, block, block, block); + + ctx->statex4_seeded_512.datalen = 0; + ctx->statex4_seeded_512.msglen = 1024; + + +} + + +/* For SHA, we initialize the hash function at the start */ +void initialize_hash_function(spx_ctx *ctx) { + seed_state(ctx); +} + +/* Free the incremental hashing context for heap-based SHA2 APIs */ +void free_hash_function(spx_ctx *ctx) { + sha256_inc_ctx_release(&ctx->state_seeded); + sha512_inc_ctx_release(&ctx->state_seeded_512); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/fors.c b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/fors.c new file mode 100644 index 0000000000..4cab8e7415 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/fors.c @@ -0,0 +1,226 @@ +#include +#include +#include + +#include "fors.h" + + +#include "address.h" +#include "hash.h" +#include "hashx8.h" +#include "thash.h" +#include "thashx8.h" +#include "utils.h" +#include "utilsx8.h" +static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + prf_addr(sk, ctx, fors_leaf_addr); +} + +static void fors_gen_skx8(unsigned char *sk0, + unsigned char *sk1, + unsigned char *sk2, + unsigned char *sk3, + unsigned char *sk4, + unsigned char *sk5, + unsigned char *sk6, + unsigned char *sk7, const spx_ctx *ctx, + uint32_t fors_leaf_addrx8[8 * 8]) { + prf_addrx8(sk0, sk1, sk2, sk3, sk4, sk5, sk6, sk7, + ctx, fors_leaf_addrx8); +} + +static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, + const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + thash(leaf, sk, 1, ctx, fors_leaf_addr); +} + +static void fors_sk_to_leafx8(unsigned char *leaf0, + unsigned char *leaf1, + unsigned char *leaf2, + unsigned char *leaf3, + unsigned char *leaf4, + unsigned char *leaf5, + unsigned char *leaf6, + unsigned char *leaf7, + const unsigned char *sk0, + const unsigned char *sk1, + const unsigned char *sk2, + const unsigned char *sk3, + const unsigned char *sk4, + const unsigned char *sk5, + const unsigned char *sk6, + const unsigned char *sk7, + const spx_ctx *ctx, + uint32_t fors_leaf_addrx8[8 * 8]) { + thashx8(leaf0, leaf1, leaf2, leaf3, leaf4, leaf5, leaf6, leaf7, + sk0, sk1, sk2, sk3, sk4, sk5, sk6, sk7, + 1, ctx, fors_leaf_addrx8); +} + +struct fors_gen_leaf_info { + uint32_t leaf_addrx[8 * 8]; +}; + +static void fors_gen_leafx8(unsigned char *leaf, + const spx_ctx *ctx, + uint32_t addr_idx, void *info) { + struct fors_gen_leaf_info *fors_info = info; + uint32_t *fors_leaf_addrx8 = fors_info->leaf_addrx; + unsigned int j; + + /* Only set the parts that the caller doesn't set */ + for (j = 0; j < 8; j++) { + set_tree_index(fors_leaf_addrx8 + j * 8, addr_idx + j); + set_type(fors_leaf_addrx8 + j * 8, SPX_ADDR_TYPE_FORSPRF); + } + + fors_gen_skx8(leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + leaf + 2 * SPX_N, + leaf + 3 * SPX_N, + leaf + 4 * SPX_N, + leaf + 5 * SPX_N, + leaf + 6 * SPX_N, + leaf + 7 * SPX_N, + ctx, fors_leaf_addrx8); + + for (j = 0; j < 8; j++) { + set_type(fors_leaf_addrx8 + j * 8, SPX_ADDR_TYPE_FORSTREE); + } + + fors_sk_to_leafx8(leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + leaf + 2 * SPX_N, + leaf + 3 * SPX_N, + leaf + 4 * SPX_N, + leaf + 5 * SPX_N, + leaf + 6 * SPX_N, + leaf + 7 * SPX_N, + leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + leaf + 2 * SPX_N, + leaf + 3 * SPX_N, + leaf + 4 * SPX_N, + leaf + 5 * SPX_N, + leaf + 6 * SPX_N, + leaf + 7 * SPX_N, + ctx, fors_leaf_addrx8); +} + +/** + * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + * Assumes indices has space for SPX_FORS_TREES integers. + */ +static void message_to_indices(uint32_t *indices, const unsigned char *m) { + unsigned int i, j; + unsigned int offset = 0; + + for (i = 0; i < SPX_FORS_TREES; i++) { + indices[i] = 0; + for (j = 0; j < SPX_FORS_HEIGHT; j++) { + indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); + offset++; + } + } +} + +/** + * Signs a message m, deriving the secret key from sk_seed and the FTS address. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + uint32_t fors_tree_addr[8 * 8] = {0}; + struct fors_gen_leaf_info fors_info = {0}; + uint32_t *fors_leaf_addr = fors_info.leaf_addrx; + uint32_t fors_pk_addr[8] = {0}; + uint32_t idx_offset; + unsigned int i; + + for (i = 0; i < 8; i++) { + copy_keypair_addr(fors_tree_addr + 8 * i, fors_addr); + set_type(fors_tree_addr + 8 * i, SPX_ADDR_TYPE_FORSTREE); + copy_keypair_addr(fors_leaf_addr + 8 * i, fors_addr); + } + copy_keypair_addr(fors_pk_addr, fors_addr); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); + + message_to_indices(indices, m); + + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); + + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + + /* Include the secret key part that produces the selected leaf node. */ + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); + fors_gen_sk(sig, ctx, fors_tree_addr); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + sig += SPX_N; + + /* Compute the authentication path for this leaf node. */ + treehashx8(roots + i * SPX_N, sig, ctx, + indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx8, + fors_tree_addr, &fors_info); + + sig += SPX_N * SPX_FORS_HEIGHT; + } + + /* Hash horizontally across all tree roots to derive the public key. */ + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); +} + +/** + * Derives the FORS public key from a signature. + * This can be used for verification by comparing to a known public key, or to + * subsequently verify a signature on the derived public key. The latter is the + * typical use-case when used as an FTS below an OTS in a hypertree. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + unsigned char leaf[SPX_N]; + uint32_t fors_tree_addr[8] = {0}; + uint32_t fors_pk_addr[8] = {0}; + uint32_t idx_offset; + unsigned int i; + + copy_keypair_addr(fors_tree_addr, fors_addr); + copy_keypair_addr(fors_pk_addr, fors_addr); + + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); + + message_to_indices(indices, m); + + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); + + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + + /* Derive the leaf from the included secret key part. */ + fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); + sig += SPX_N; + + /* Derive the corresponding root node of this tree. */ + compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, + sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); + sig += SPX_N * SPX_FORS_HEIGHT; + } + + /* Hash horizontally across all tree roots to derive the public key. */ + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/fors.h b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/fors.h new file mode 100644 index 0000000000..509140a178 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/fors.h @@ -0,0 +1,32 @@ +#ifndef SPX_FORS_H +#define SPX_FORS_H + +#include + +#include "context.h" +#include "params.h" + +/** + * Signs a message m, deriving the secret key from sk_seed and the FTS address. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +#define fors_sign SPX_NAMESPACE(fors_sign) +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); + +/** + * Derives the FORS public key from a signature. + * This can be used for verification by comparing to a known public key, or to + * subsequently verify a signature on the derived public key. The latter is the + * typical use-case when used as an FTS below an OTS in a hypertree. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/hash.h b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/hash.h new file mode 100644 index 0000000000..ffe815f45d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/hash.h @@ -0,0 +1,37 @@ +#ifndef SPX_HASH_H +#define SPX_HASH_H + +#include +#include + +#include "context.h" +#include "params.h" + +#define prf_addr SPX_NAMESPACE(prf_addr) +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]); + +#define gen_message_random SPX_NAMESPACE(gen_message_random) +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); + +#define hash_message SPX_NAMESPACE(hash_message) +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); + + +# define SPX_SHA256_ADDR_BYTES 22 + +# define mgf1_256 SPX_NAMESPACE(mgf1_256) +void mgf1_256(unsigned char *out, unsigned long outlen, + const unsigned char *in, unsigned long inlen); + +# define mgf1_512 SPX_NAMESPACE(mgf1_512) +void mgf1_512(unsigned char *out, unsigned long outlen, + const unsigned char *in, unsigned long inlen); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/hash_sha2.c b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/hash_sha2.c new file mode 100644 index 0000000000..3d0085c8c1 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/hash_sha2.c @@ -0,0 +1,219 @@ +#include +#include + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "sha2.h" +#include "utils.h" + + + +#define SPX_SHAX_OUTPUT_BYTES SPX_SHA512_OUTPUT_BYTES +#define SPX_SHAX_BLOCK_BYTES SPX_SHA512_BLOCK_BYTES +#define shaX_inc_init sha512_inc_init +#define shaX_inc_blocks sha512_inc_blocks +#define shaX_inc_finalize sha512_inc_finalize +#define shaX sha512 +#define mgf1_X mgf1_512 +#define shaXstate sha512ctx + +/** + * mgf1 function based on the SHA-256 hash function + * Note that inlen should be sufficiently small that it still allows for + * an array to be allocated on the stack. Typically 'in' is merely a seed. + * Outputs outlen number of bytes + */ +void mgf1_256(unsigned char *out, unsigned long outlen, + const unsigned char *in, unsigned long inlen) { + PQCLEAN_VLA(uint8_t, inbuf, inlen + 4); + unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES]; + uint32_t i; + + memcpy(inbuf, in, inlen); + + /* While we can fit in at least another full block of SHA256 output.. */ + for (i = 0; (i + 1)*SPX_SHA256_OUTPUT_BYTES <= outlen; i++) { + u32_to_bytes(inbuf + inlen, i); + sha256(out, inbuf, inlen + 4); + out += SPX_SHA256_OUTPUT_BYTES; + } + /* Until we cannot anymore, and we fill the remainder. */ + if (outlen > i * SPX_SHA256_OUTPUT_BYTES) { + u32_to_bytes(inbuf + inlen, i); + sha256(outbuf, inbuf, inlen + 4); + memcpy(out, outbuf, outlen - i * SPX_SHA256_OUTPUT_BYTES); + } +} + +/* + * mgf1 function based on the SHA-512 hash function + */ +void mgf1_512(unsigned char *out, unsigned long outlen, + const unsigned char *in, unsigned long inlen) { + PQCLEAN_VLA(uint8_t, inbuf, inlen + 4); + unsigned char outbuf[SPX_SHA512_OUTPUT_BYTES]; + uint32_t i; + + memcpy(inbuf, in, inlen); + + /* While we can fit in at least another full block of SHA512 output.. */ + for (i = 0; (i + 1)*SPX_SHA512_OUTPUT_BYTES <= outlen; i++) { + u32_to_bytes(inbuf + inlen, i); + sha512(out, inbuf, inlen + 4); + out += SPX_SHA512_OUTPUT_BYTES; + } + /* Until we cannot anymore, and we fill the remainder. */ + if (outlen > i * SPX_SHA512_OUTPUT_BYTES) { + u32_to_bytes(inbuf + inlen, i); + sha512(outbuf, inbuf, inlen + 4); + memcpy(out, outbuf, outlen - i * SPX_SHA512_OUTPUT_BYTES); + } +} + +/* + * Computes PRF(pk_seed, sk_seed, addr). + */ +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]) { + sha256ctx sha2_state; + unsigned char buf[SPX_SHA256_ADDR_BYTES + SPX_N]; + unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES]; + + /* Retrieve precomputed state containing pub_seed */ + sha256_inc_ctx_clone(&sha2_state, &ctx->state_seeded); + + /* Remainder: ADDR^c ‖ SK.seed */ + memcpy(buf, addr, SPX_SHA256_ADDR_BYTES); + memcpy(buf + SPX_SHA256_ADDR_BYTES, ctx->sk_seed, SPX_N); + + sha256_inc_finalize(outbuf, &sha2_state, buf, SPX_SHA256_ADDR_BYTES + SPX_N); + + memcpy(out, outbuf, SPX_N); +} + +/** + * Computes the message-dependent randomness R, using a secret seed as a key + * for HMAC, and an optional randomization value prefixed to the message. + * This requires m to have at least SPX_SHAX_BLOCK_BYTES + SPX_N space + * available in front of the pointer, i.e. before the message to use for the + * prefix. This is necessary to prevent having to move the message around (and + * allocate memory for it). + */ +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { + (void)ctx; + + unsigned char buf[SPX_SHAX_BLOCK_BYTES + SPX_SHAX_OUTPUT_BYTES]; + shaXstate state; + int i; + + + /* This implements HMAC-SHA */ + for (i = 0; i < SPX_N; i++) { + buf[i] = 0x36 ^ sk_prf[i]; + } + memset(buf + SPX_N, 0x36, SPX_SHAX_BLOCK_BYTES - SPX_N); + + shaX_inc_init(&state); + shaX_inc_blocks(&state, buf, 1); + + memcpy(buf, optrand, SPX_N); + + /* If optrand + message cannot fill up an entire block */ + if (SPX_N + mlen < SPX_SHAX_BLOCK_BYTES) { + memcpy(buf + SPX_N, m, mlen); + shaX_inc_finalize(buf + SPX_SHAX_BLOCK_BYTES, &state, + buf, mlen + SPX_N); + } + /* Otherwise first fill a block, so that finalize only uses the message */ + else { + memcpy(buf + SPX_N, m, SPX_SHAX_BLOCK_BYTES - SPX_N); + shaX_inc_blocks(&state, buf, 1); + + m += SPX_SHAX_BLOCK_BYTES - SPX_N; + mlen -= SPX_SHAX_BLOCK_BYTES - SPX_N; + shaX_inc_finalize(buf + SPX_SHAX_BLOCK_BYTES, &state, m, mlen); + } + + for (i = 0; i < SPX_N; i++) { + buf[i] = 0x5c ^ sk_prf[i]; + } + memset(buf + SPX_N, 0x5c, SPX_SHAX_BLOCK_BYTES - SPX_N); + + shaX(buf, buf, SPX_SHAX_BLOCK_BYTES + SPX_SHAX_OUTPUT_BYTES); + memcpy(R, buf, SPX_N); +} + +/** + * Computes the message hash using R, the public key, and the message. + * Outputs the message digest and the index of the leaf. The index is split in + * the tree index and the leaf index, for convenient copying to an address. + */ +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { + (void)ctx; +#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) +#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) +#define SPX_LEAF_BITS SPX_TREE_HEIGHT +#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) +#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) + + unsigned char seed[2 * SPX_N + SPX_SHAX_OUTPUT_BYTES]; + + /* Round to nearest multiple of SPX_SHAX_BLOCK_BYTES */ +#define SPX_INBLOCKS (((SPX_N + SPX_PK_BYTES + SPX_SHAX_BLOCK_BYTES - 1) & \ + -SPX_SHAX_BLOCK_BYTES) / SPX_SHAX_BLOCK_BYTES) + unsigned char inbuf[SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES]; + + unsigned char buf[SPX_DGST_BYTES]; + unsigned char *bufp = buf; + shaXstate state; + + shaX_inc_init(&state); + + // seed: SHA-X(R ‖ PK.seed ‖ PK.root ‖ M) + memcpy(inbuf, R, SPX_N); + memcpy(inbuf + SPX_N, pk, SPX_PK_BYTES); + + /* If R + pk + message cannot fill up an entire block */ + if (SPX_N + SPX_PK_BYTES + mlen < SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES) { + memcpy(inbuf + SPX_N + SPX_PK_BYTES, m, mlen); + shaX_inc_finalize(seed + 2 * SPX_N, &state, inbuf, SPX_N + SPX_PK_BYTES + mlen); + } + /* Otherwise first fill a block, so that finalize only uses the message */ + else { + memcpy(inbuf + SPX_N + SPX_PK_BYTES, m, + SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES - SPX_N - SPX_PK_BYTES); + shaX_inc_blocks(&state, inbuf, SPX_INBLOCKS); + + m += SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES - SPX_N - SPX_PK_BYTES; + mlen -= SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES - SPX_N - SPX_PK_BYTES; + shaX_inc_finalize(seed + 2 * SPX_N, &state, m, (size_t)mlen); + } + + // H_msg: MGF1-SHA-X(R ‖ PK.seed ‖ seed) + memcpy(seed, R, SPX_N); + memcpy(seed + SPX_N, pk, SPX_N); + + /* By doing this in two steps, we prevent hashing the message twice; + otherwise each iteration in MGF1 would hash the message again. */ + mgf1_X(bufp, SPX_DGST_BYTES, seed, 2 * SPX_N + SPX_SHAX_OUTPUT_BYTES); + + memcpy(digest, bufp, SPX_FORS_MSG_BYTES); + bufp += SPX_FORS_MSG_BYTES; + + + *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); + *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); + bufp += SPX_TREE_BYTES; + + *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); + *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); +} + + diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/hash_sha2x8.c b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/hash_sha2x8.c new file mode 100644 index 0000000000..e04af7a069 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/hash_sha2x8.c @@ -0,0 +1,75 @@ +#include +#include + +#include "hash.h" +#include "hashx8.h" + +#include "address.h" +#include "params.h" +#include "sha2.h" +#include "sha256avx.h" +#include "sha256x8.h" +#include "utils.h" + +/* + * 8-way parallel version of prf_addr; takes 8x as much input and output + */ +void prf_addrx8(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const spx_ctx *ctx, + const uint32_t addrx8[8 * 8]) { + unsigned char bufx8[8 * (SPX_N + SPX_SHA256_ADDR_BYTES)]; + unsigned char outbufx8[8 * SPX_SHA256_OUTPUT_BYTES]; + unsigned int j; + + for (j = 0; j < 8; j++) { + memcpy(bufx8 + j * (SPX_N + SPX_SHA256_ADDR_BYTES), + addrx8 + j * 8, SPX_SHA256_ADDR_BYTES); + memcpy( + bufx8 + j * (SPX_N + SPX_SHA256_ADDR_BYTES) + SPX_SHA256_ADDR_BYTES, + ctx->sk_seed, + SPX_N + ); + } + + sha256x8_seeded( + /* out */ + outbufx8 + 0 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 1 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 2 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 3 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 4 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 5 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 6 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 7 * SPX_SHA256_OUTPUT_BYTES, + + /* seed */ + &ctx->statex8_seeded, + + /* in */ + bufx8 + 0 * (SPX_SHA256_ADDR_BYTES + SPX_N), + bufx8 + 1 * (SPX_SHA256_ADDR_BYTES + SPX_N), + bufx8 + 2 * (SPX_SHA256_ADDR_BYTES + SPX_N), + bufx8 + 3 * (SPX_SHA256_ADDR_BYTES + SPX_N), + bufx8 + 4 * (SPX_SHA256_ADDR_BYTES + SPX_N), + bufx8 + 5 * (SPX_SHA256_ADDR_BYTES + SPX_N), + bufx8 + 6 * (SPX_SHA256_ADDR_BYTES + SPX_N), + bufx8 + 7 * (SPX_SHA256_ADDR_BYTES + SPX_N), + SPX_SHA256_ADDR_BYTES + SPX_N /* len */ + ); + + memcpy(out0, outbufx8 + 0 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out1, outbufx8 + 1 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out2, outbufx8 + 2 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out3, outbufx8 + 3 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out4, outbufx8 + 4 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out5, outbufx8 + 5 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out6, outbufx8 + 6 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out7, outbufx8 + 7 * SPX_SHA256_OUTPUT_BYTES, SPX_N); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/hashx8.h b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/hashx8.h new file mode 100644 index 0000000000..46503f0a10 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/hashx8.h @@ -0,0 +1,20 @@ +#ifndef SPX_HASHX8_H +#define SPX_HASHX8_H + +#include + +#include "params.h" + +#define prf_addrx8 SPX_NAMESPACE(prf_addrx8) +void prf_addrx8(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const spx_ctx *ctx, + const uint32_t addrx8[8 * 8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/merkle.c b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/merkle.c new file mode 100644 index 0000000000..1f353c8dd8 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/merkle.c @@ -0,0 +1,65 @@ +#include +#include + +#include "merkle.h" + +#include "address.h" +#include "params.h" +#include "utils.h" +#include "utilsx8.h" +#include "wots.h" +#include "wotsx8.h" + +/* + * This generates a Merkle signature (WOTS signature followed by the Merkle + * authentication path). + */ +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf) { + unsigned char *auth_path = sig + SPX_WOTS_BYTES; + uint32_t tree_addrx8[8 * 8] = { 0 }; + int j; + struct leaf_info_x8 info = { 0 }; + unsigned steps[ SPX_WOTS_LEN ]; + + info.wots_sig = sig; + chain_lengths(steps, root); + info.wots_steps = steps; + + for (j = 0; j < 8; j++) { + set_type(&tree_addrx8[8 * j], SPX_ADDR_TYPE_HASHTREE); + set_type(&info.leaf_addr[8 * j], SPX_ADDR_TYPE_WOTS); + set_type(&info.pk_addr[8 * j], SPX_ADDR_TYPE_WOTSPK); + copy_subtree_addr(&tree_addrx8[8 * j], tree_addr); + copy_subtree_addr(&info.leaf_addr[8 * j], wots_addr); + copy_subtree_addr(&info.pk_addr[8 * j], wots_addr); + } + + info.wots_sign_leaf = idx_leaf; + + treehashx8(root, auth_path, ctx, + idx_leaf, 0, + SPX_TREE_HEIGHT, + wots_gen_leafx8, + tree_addrx8, &info); +} + +/* Compute root node of the top-most subtree. */ +/* Again, in this file because wots_gen_leaf is most of the work */ +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { + /* We do not need the auth path in key generation, but it simplifies the + code to have just one treehash routine that computes both root and path + in one function. */ + unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; + uint32_t top_tree_addr[8] = {0}; + uint32_t wots_addr[8] = {0}; + + set_layer_addr(top_tree_addr, SPX_D - 1); + set_layer_addr(wots_addr, SPX_D - 1); + + merkle_sign(auth_path, root, ctx, + wots_addr, top_tree_addr, + ~0U /* ~0 means "don't bother generating an auth path */ ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/merkle.h b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/merkle.h new file mode 100644 index 0000000000..769cf2e970 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/merkle.h @@ -0,0 +1,21 @@ +#ifndef MERKLE_H_ +#define MERKLE_H_ + +#include + +#include "context.h" +#include "params.h" + +/* Generate a Merkle signature (WOTS signature followed by the Merkle */ +/* authentication path) */ +#define merkle_sign SPX_NAMESPACE(merkle_sign) +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf); + +/* Compute the root node of the top-most subtree. */ +#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); + +#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/nistapi.h b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/nistapi.h new file mode 100644 index 0000000000..3cb71afad4 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/nistapi.h @@ -0,0 +1,87 @@ +#ifndef SPX_API_H +#define SPX_API_H + +#include +#include + +#include "params.h" + +#define CRYPTO_ALGNAME "SPHINCS+" + +#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES +#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES +#define CRYPTO_BYTES SPX_BYTES +#define CRYPTO_SEEDBYTES (3*SPX_N) + +/* + * Returns the length of a secret key, in bytes + */ +#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) +size_t crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) +size_t crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) +size_t crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) +size_t crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +#define crypto_sign SPX_NAMESPACE(crypto_sign) +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/params.h b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/params.h new file mode 100644 index 0000000000..c45bfd994c --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/params.h @@ -0,0 +1,61 @@ +#ifndef SPX_PARAMS_H +#define SPX_PARAMS_H + +#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSSHA2192SROBUST_AVX2_##s + +/* Hash output length in bytes. */ +#define SPX_N 24 +/* Height of the hypertree. */ +#define SPX_FULL_HEIGHT 63 +/* Number of subtree layer. */ +#define SPX_D 7 +/* FORS tree dimensions. */ +#define SPX_FORS_HEIGHT 14 +#define SPX_FORS_TREES 17 +/* Winternitz parameter, */ +#define SPX_WOTS_W 16 + +/* The hash function is defined by linking a different hash.c file, as opposed + to setting a #define constant. */ + +/* This is a SHA2-based parameter set, hence whether we use SHA-256 + * exclusively or we use both SHA-256 and SHA-512 is controlled by + * the following #define */ +#define SPX_SHA512 1 /* Use SHA-512 for H and T_l, l >= 2 */ + +/* For clarity */ +#define SPX_ADDR_BYTES 32 + +/* WOTS parameters. */ +#define SPX_WOTS_LOGW 4 + +#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) + +/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ +#define SPX_WOTS_LEN2 3 + +#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) +#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) +#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES + +/* Subtree size. */ +#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) + +//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT +// #error SPX_D should always divide SPX_FULL_HEIGHT +//#endif + +/* FORS parameters. */ +#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) +#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) +#define SPX_FORS_PK_BYTES SPX_N + +/* Resulting SPX sizes. */ +#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ + SPX_FULL_HEIGHT * SPX_N) +#define SPX_PK_BYTES (2 * SPX_N) +#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) + +#include "sha2_offsets.h" + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/sha256avx.c b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/sha256avx.c new file mode 100644 index 0000000000..6bbe6ecc24 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/sha256avx.c @@ -0,0 +1,357 @@ +#include +#include +#include + +#include "sha256avx.h" + +static const unsigned int RC[] = { + 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, + 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, + 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, + 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, + 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, + 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, + 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, + 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, + 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, + 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, + 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, + 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, + 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, + 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, + 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, + 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 +}; + +#define u32 uint32_t +#define u256 __m256i + +#define XOR _mm256_xor_si256 +#define OR _mm256_or_si256 +#define AND _mm256_and_si256 +#define ADD32 _mm256_add_epi32 +#define NOT(x) _mm256_xor_si256(x, _mm256_set_epi32(-1, -1, -1, -1, -1, -1, -1, -1)) + +#define LOAD(src) _mm256_loadu_si256((__m256i *)(src)) +#define STORE(dest,src) _mm256_storeu_si256((__m256i *)(dest),src) + +#define BYTESWAP(x) _mm256_shuffle_epi8(x, _mm256_set_epi8(0xc,0xd,0xe,0xf,0x8,0x9,0xa,0xb,0x4,0x5,0x6,0x7,0x0,0x1,0x2,0x3,0xc,0xd,0xe,0xf,0x8,0x9,0xa,0xb,0x4,0x5,0x6,0x7,0x0,0x1,0x2,0x3)) + +#define SHIFTR32(x, y) _mm256_srli_epi32(x, y) +#define SHIFTL32(x, y) _mm256_slli_epi32(x, y) + +#define ROTR32(x, y) OR(SHIFTR32(x, y), SHIFTL32(x, 32 - (y))) +#define ROTL32(x, y) OR(SHIFTL32(x, y), SHIFTR32(x, 32 - (y))) + +#define XOR3(a, b, c) XOR(XOR(a, b), c) + +#define ADD3_32(a, b, c) ADD32(ADD32(a, b), c) +#define ADD4_32(a, b, c, d) ADD32(ADD32(ADD32(a, b), c), d) +#define ADD5_32(a, b, c, d, e) ADD32(ADD32(ADD32(ADD32(a, b), c), d), e) + +#define MAJ_AVX(a, b, c) XOR3(AND(a, b), AND(a, c), AND(b, c)) +#define CH_AVX(a, b, c) XOR(AND(a, b), AND(NOT(a), c)) + +#define SIGMA1_AVX(x) XOR3(ROTR32(x, 6), ROTR32(x, 11), ROTR32(x, 25)) +#define SIGMA0_AVX(x) XOR3(ROTR32(x, 2), ROTR32(x, 13), ROTR32(x, 22)) + +#define WSIGMA1_AVX(x) XOR3(ROTR32(x, 17), ROTR32(x, 19), SHIFTR32(x, 10)) +#define WSIGMA0_AVX(x) XOR3(ROTR32(x, 7), ROTR32(x, 18), SHIFTR32(x, 3)) + +#define SHA256ROUND_AVX(a, b, c, d, e, f, g, h, rc, w) \ + T0 = ADD5_32(h, SIGMA1_AVX(e), CH_AVX(e, f, g), _mm256_set1_epi32((int)RC[rc]), w); \ + (d) = ADD32(d, T0); \ + T1 = ADD32(SIGMA0_AVX(a), MAJ_AVX(a, b, c)); \ + (h) = ADD32(T0, T1); + +// Transpose 8 vectors containing 32-bit values +static void transpose(u256 s[8]) { + u256 tmp0[8]; + u256 tmp1[8]; + tmp0[0] = _mm256_unpacklo_epi32(s[0], s[1]); + tmp0[1] = _mm256_unpackhi_epi32(s[0], s[1]); + tmp0[2] = _mm256_unpacklo_epi32(s[2], s[3]); + tmp0[3] = _mm256_unpackhi_epi32(s[2], s[3]); + tmp0[4] = _mm256_unpacklo_epi32(s[4], s[5]); + tmp0[5] = _mm256_unpackhi_epi32(s[4], s[5]); + tmp0[6] = _mm256_unpacklo_epi32(s[6], s[7]); + tmp0[7] = _mm256_unpackhi_epi32(s[6], s[7]); + tmp1[0] = _mm256_unpacklo_epi64(tmp0[0], tmp0[2]); + tmp1[1] = _mm256_unpackhi_epi64(tmp0[0], tmp0[2]); + tmp1[2] = _mm256_unpacklo_epi64(tmp0[1], tmp0[3]); + tmp1[3] = _mm256_unpackhi_epi64(tmp0[1], tmp0[3]); + tmp1[4] = _mm256_unpacklo_epi64(tmp0[4], tmp0[6]); + tmp1[5] = _mm256_unpackhi_epi64(tmp0[4], tmp0[6]); + tmp1[6] = _mm256_unpacklo_epi64(tmp0[5], tmp0[7]); + tmp1[7] = _mm256_unpackhi_epi64(tmp0[5], tmp0[7]); + s[0] = _mm256_permute2x128_si256(tmp1[0], tmp1[4], 0x20); + s[1] = _mm256_permute2x128_si256(tmp1[1], tmp1[5], 0x20); + s[2] = _mm256_permute2x128_si256(tmp1[2], tmp1[6], 0x20); + s[3] = _mm256_permute2x128_si256(tmp1[3], tmp1[7], 0x20); + s[4] = _mm256_permute2x128_si256(tmp1[0], tmp1[4], 0x31); + s[5] = _mm256_permute2x128_si256(tmp1[1], tmp1[5], 0x31); + s[6] = _mm256_permute2x128_si256(tmp1[2], tmp1[6], 0x31); + s[7] = _mm256_permute2x128_si256(tmp1[3], tmp1[7], 0x31); +} + +void sha256_ctx_clone8x(sha256x8ctx *out, const sha256x8ctx *in) { + memcpy(out, in, sizeof(sha256x8ctx)); +} + +void sha256_init8x(sha256x8ctx *ctx) { + ctx->s[0] = _mm256_set_epi32((int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667); + ctx->s[1] = _mm256_set_epi32((int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85); + ctx->s[2] = _mm256_set_epi32((int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372); + ctx->s[3] = _mm256_set_epi32((int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a); + ctx->s[4] = _mm256_set_epi32((int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f); + ctx->s[5] = _mm256_set_epi32((int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c); + ctx->s[6] = _mm256_set_epi32((int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab); + ctx->s[7] = _mm256_set_epi32((int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19); + + ctx->datalen = 0; + ctx->msglen = 0; +} + +void sha256_final8x(sha256x8ctx *ctx, + unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7) { + unsigned int i, curlen; + + // Padding + if (ctx->datalen < 56) { + for (i = 0; i < 8; ++i) { + curlen = ctx->datalen; + ctx->msgblocks[64 * i + curlen++] = 0x80; + while (curlen < 64) { + ctx->msgblocks[64 * i + curlen++] = 0x00; + } + } + } else { + for (i = 0; i < 8; ++i) { + curlen = ctx->datalen; + ctx->msgblocks[64 * i + curlen++] = 0x80; + while (curlen < 64) { + ctx->msgblocks[64 * i + curlen++] = 0x00; + } + } + sha256_transform8x(ctx, + &ctx->msgblocks[64 * 0], + &ctx->msgblocks[64 * 1], + &ctx->msgblocks[64 * 2], + &ctx->msgblocks[64 * 3], + &ctx->msgblocks[64 * 4], + &ctx->msgblocks[64 * 5], + &ctx->msgblocks[64 * 6], + &ctx->msgblocks[64 * 7] + ); + memset(ctx->msgblocks, 0, 8 * 64); + } + + // Add length of the message to each block + ctx->msglen += ctx->datalen * 8; + for (i = 0; i < 8; i++) { + ctx->msgblocks[64 * i + 63] = (unsigned char)(ctx->msglen); + ctx->msgblocks[64 * i + 62] = (unsigned char)(ctx->msglen >> 8); + ctx->msgblocks[64 * i + 61] = (unsigned char)(ctx->msglen >> 16); + ctx->msgblocks[64 * i + 60] = (unsigned char)(ctx->msglen >> 24); + ctx->msgblocks[64 * i + 59] = (unsigned char)(ctx->msglen >> 32); + ctx->msgblocks[64 * i + 58] = (unsigned char)(ctx->msglen >> 40); + ctx->msgblocks[64 * i + 57] = (unsigned char)(ctx->msglen >> 48); + ctx->msgblocks[64 * i + 56] = (unsigned char)(ctx->msglen >> 56); + } + sha256_transform8x(ctx, + &ctx->msgblocks[64 * 0], + &ctx->msgblocks[64 * 1], + &ctx->msgblocks[64 * 2], + &ctx->msgblocks[64 * 3], + &ctx->msgblocks[64 * 4], + &ctx->msgblocks[64 * 5], + &ctx->msgblocks[64 * 6], + &ctx->msgblocks[64 * 7] + ); + + // Compute final hash output + transpose(ctx->s); + + // Store Hash value + STORE(out0, BYTESWAP(ctx->s[0])); + STORE(out1, BYTESWAP(ctx->s[1])); + STORE(out2, BYTESWAP(ctx->s[2])); + STORE(out3, BYTESWAP(ctx->s[3])); + STORE(out4, BYTESWAP(ctx->s[4])); + STORE(out5, BYTESWAP(ctx->s[5])); + STORE(out6, BYTESWAP(ctx->s[6])); + STORE(out7, BYTESWAP(ctx->s[7])); +} + +void sha256_transform8x(sha256x8ctx *ctx, + const unsigned char *data0, + const unsigned char *data1, + const unsigned char *data2, + const unsigned char *data3, + const unsigned char *data4, + const unsigned char *data5, + const unsigned char *data6, + const unsigned char *data7) { + u256 s[8], w[64], T0, T1; + + // Load words and transform data correctly + w[0] = BYTESWAP(LOAD(data0)); + w[0 + 8] = BYTESWAP(LOAD(data0 + 32)); + w[1] = BYTESWAP(LOAD(data1)); + w[1 + 8] = BYTESWAP(LOAD(data1 + 32)); + w[2] = BYTESWAP(LOAD(data2)); + w[2 + 8] = BYTESWAP(LOAD(data2 + 32)); + w[3] = BYTESWAP(LOAD(data3)); + w[3 + 8] = BYTESWAP(LOAD(data3 + 32)); + w[4] = BYTESWAP(LOAD(data4)); + w[4 + 8] = BYTESWAP(LOAD(data4 + 32)); + w[5] = BYTESWAP(LOAD(data5)); + w[5 + 8] = BYTESWAP(LOAD(data5 + 32)); + w[6] = BYTESWAP(LOAD(data6)); + w[6 + 8] = BYTESWAP(LOAD(data6 + 32)); + w[7] = BYTESWAP(LOAD(data7)); + w[7 + 8] = BYTESWAP(LOAD(data7 + 32)); + + transpose(w); + transpose(w + 8); + + // Initial State + s[0] = ctx->s[0]; + s[1] = ctx->s[1]; + s[2] = ctx->s[2]; + s[3] = ctx->s[3]; + s[4] = ctx->s[4]; + s[5] = ctx->s[5]; + s[6] = ctx->s[6]; + s[7] = ctx->s[7]; + + SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 0, w[0]); + SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 1, w[1]); + SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 2, w[2]); + SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 3, w[3]); + SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 4, w[4]); + SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 5, w[5]); + SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 6, w[6]); + SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 7, w[7]); + SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 8, w[8]); + SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 9, w[9]); + SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 10, w[10]); + SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 11, w[11]); + SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 12, w[12]); + SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 13, w[13]); + SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 14, w[14]); + SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 15, w[15]); + w[16] = ADD4_32(WSIGMA1_AVX(w[14]), w[0], w[9], WSIGMA0_AVX(w[1])); + SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 16, w[16]); + w[17] = ADD4_32(WSIGMA1_AVX(w[15]), w[1], w[10], WSIGMA0_AVX(w[2])); + SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 17, w[17]); + w[18] = ADD4_32(WSIGMA1_AVX(w[16]), w[2], w[11], WSIGMA0_AVX(w[3])); + SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 18, w[18]); + w[19] = ADD4_32(WSIGMA1_AVX(w[17]), w[3], w[12], WSIGMA0_AVX(w[4])); + SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 19, w[19]); + w[20] = ADD4_32(WSIGMA1_AVX(w[18]), w[4], w[13], WSIGMA0_AVX(w[5])); + SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 20, w[20]); + w[21] = ADD4_32(WSIGMA1_AVX(w[19]), w[5], w[14], WSIGMA0_AVX(w[6])); + SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 21, w[21]); + w[22] = ADD4_32(WSIGMA1_AVX(w[20]), w[6], w[15], WSIGMA0_AVX(w[7])); + SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 22, w[22]); + w[23] = ADD4_32(WSIGMA1_AVX(w[21]), w[7], w[16], WSIGMA0_AVX(w[8])); + SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 23, w[23]); + w[24] = ADD4_32(WSIGMA1_AVX(w[22]), w[8], w[17], WSIGMA0_AVX(w[9])); + SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 24, w[24]); + w[25] = ADD4_32(WSIGMA1_AVX(w[23]), w[9], w[18], WSIGMA0_AVX(w[10])); + SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 25, w[25]); + w[26] = ADD4_32(WSIGMA1_AVX(w[24]), w[10], w[19], WSIGMA0_AVX(w[11])); + SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 26, w[26]); + w[27] = ADD4_32(WSIGMA1_AVX(w[25]), w[11], w[20], WSIGMA0_AVX(w[12])); + SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 27, w[27]); + w[28] = ADD4_32(WSIGMA1_AVX(w[26]), w[12], w[21], WSIGMA0_AVX(w[13])); + SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 28, w[28]); + w[29] = ADD4_32(WSIGMA1_AVX(w[27]), w[13], w[22], WSIGMA0_AVX(w[14])); + SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 29, w[29]); + w[30] = ADD4_32(WSIGMA1_AVX(w[28]), w[14], w[23], WSIGMA0_AVX(w[15])); + SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 30, w[30]); + w[31] = ADD4_32(WSIGMA1_AVX(w[29]), w[15], w[24], WSIGMA0_AVX(w[16])); + SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 31, w[31]); + w[32] = ADD4_32(WSIGMA1_AVX(w[30]), w[16], w[25], WSIGMA0_AVX(w[17])); + SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 32, w[32]); + w[33] = ADD4_32(WSIGMA1_AVX(w[31]), w[17], w[26], WSIGMA0_AVX(w[18])); + SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 33, w[33]); + w[34] = ADD4_32(WSIGMA1_AVX(w[32]), w[18], w[27], WSIGMA0_AVX(w[19])); + SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 34, w[34]); + w[35] = ADD4_32(WSIGMA1_AVX(w[33]), w[19], w[28], WSIGMA0_AVX(w[20])); + SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 35, w[35]); + w[36] = ADD4_32(WSIGMA1_AVX(w[34]), w[20], w[29], WSIGMA0_AVX(w[21])); + SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 36, w[36]); + w[37] = ADD4_32(WSIGMA1_AVX(w[35]), w[21], w[30], WSIGMA0_AVX(w[22])); + SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 37, w[37]); + w[38] = ADD4_32(WSIGMA1_AVX(w[36]), w[22], w[31], WSIGMA0_AVX(w[23])); + SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 38, w[38]); + w[39] = ADD4_32(WSIGMA1_AVX(w[37]), w[23], w[32], WSIGMA0_AVX(w[24])); + SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 39, w[39]); + w[40] = ADD4_32(WSIGMA1_AVX(w[38]), w[24], w[33], WSIGMA0_AVX(w[25])); + SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 40, w[40]); + w[41] = ADD4_32(WSIGMA1_AVX(w[39]), w[25], w[34], WSIGMA0_AVX(w[26])); + SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 41, w[41]); + w[42] = ADD4_32(WSIGMA1_AVX(w[40]), w[26], w[35], WSIGMA0_AVX(w[27])); + SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 42, w[42]); + w[43] = ADD4_32(WSIGMA1_AVX(w[41]), w[27], w[36], WSIGMA0_AVX(w[28])); + SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 43, w[43]); + w[44] = ADD4_32(WSIGMA1_AVX(w[42]), w[28], w[37], WSIGMA0_AVX(w[29])); + SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 44, w[44]); + w[45] = ADD4_32(WSIGMA1_AVX(w[43]), w[29], w[38], WSIGMA0_AVX(w[30])); + SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 45, w[45]); + w[46] = ADD4_32(WSIGMA1_AVX(w[44]), w[30], w[39], WSIGMA0_AVX(w[31])); + SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 46, w[46]); + w[47] = ADD4_32(WSIGMA1_AVX(w[45]), w[31], w[40], WSIGMA0_AVX(w[32])); + SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 47, w[47]); + w[48] = ADD4_32(WSIGMA1_AVX(w[46]), w[32], w[41], WSIGMA0_AVX(w[33])); + SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 48, w[48]); + w[49] = ADD4_32(WSIGMA1_AVX(w[47]), w[33], w[42], WSIGMA0_AVX(w[34])); + SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 49, w[49]); + w[50] = ADD4_32(WSIGMA1_AVX(w[48]), w[34], w[43], WSIGMA0_AVX(w[35])); + SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 50, w[50]); + w[51] = ADD4_32(WSIGMA1_AVX(w[49]), w[35], w[44], WSIGMA0_AVX(w[36])); + SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 51, w[51]); + w[52] = ADD4_32(WSIGMA1_AVX(w[50]), w[36], w[45], WSIGMA0_AVX(w[37])); + SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 52, w[52]); + w[53] = ADD4_32(WSIGMA1_AVX(w[51]), w[37], w[46], WSIGMA0_AVX(w[38])); + SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 53, w[53]); + w[54] = ADD4_32(WSIGMA1_AVX(w[52]), w[38], w[47], WSIGMA0_AVX(w[39])); + SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 54, w[54]); + w[55] = ADD4_32(WSIGMA1_AVX(w[53]), w[39], w[48], WSIGMA0_AVX(w[40])); + SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 55, w[55]); + w[56] = ADD4_32(WSIGMA1_AVX(w[54]), w[40], w[49], WSIGMA0_AVX(w[41])); + SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 56, w[56]); + w[57] = ADD4_32(WSIGMA1_AVX(w[55]), w[41], w[50], WSIGMA0_AVX(w[42])); + SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 57, w[57]); + w[58] = ADD4_32(WSIGMA1_AVX(w[56]), w[42], w[51], WSIGMA0_AVX(w[43])); + SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 58, w[58]); + w[59] = ADD4_32(WSIGMA1_AVX(w[57]), w[43], w[52], WSIGMA0_AVX(w[44])); + SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 59, w[59]); + w[60] = ADD4_32(WSIGMA1_AVX(w[58]), w[44], w[53], WSIGMA0_AVX(w[45])); + SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 60, w[60]); + w[61] = ADD4_32(WSIGMA1_AVX(w[59]), w[45], w[54], WSIGMA0_AVX(w[46])); + SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 61, w[61]); + w[62] = ADD4_32(WSIGMA1_AVX(w[60]), w[46], w[55], WSIGMA0_AVX(w[47])); + SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 62, w[62]); + w[63] = ADD4_32(WSIGMA1_AVX(w[61]), w[47], w[56], WSIGMA0_AVX(w[48])); + SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 63, w[63]); + + // Feed Forward + ctx->s[0] = ADD32(s[0], ctx->s[0]); + ctx->s[1] = ADD32(s[1], ctx->s[1]); + ctx->s[2] = ADD32(s[2], ctx->s[2]); + ctx->s[3] = ADD32(s[3], ctx->s[3]); + ctx->s[4] = ADD32(s[4], ctx->s[4]); + ctx->s[5] = ADD32(s[5], ctx->s[5]); + ctx->s[6] = ADD32(s[6], ctx->s[6]); + ctx->s[7] = ADD32(s[7], ctx->s[7]); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/sha256avx.h b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/sha256avx.h new file mode 100644 index 0000000000..1e3bcf889b --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/sha256avx.h @@ -0,0 +1,44 @@ +#ifndef SHA256AVX_H +#define SHA256AVX_H + +#include +#include + +#include "params.h" + +typedef struct SHA256state { + __m256i s[8]; + unsigned char msgblocks[8 * 64]; + unsigned int datalen; + unsigned long long msglen; +} sha256x8ctx; + +#define sha256_ctx_clone8x SPX_NAMESPACE(sha256_ctx_clone8x) +void sha256_ctx_clone8x(sha256x8ctx *out, const sha256x8ctx *in); + +#define sha256_init8x SPX_NAMESPACE(sha256_init8x) +void sha256_init8x(sha256x8ctx *ctx); + +#define sha256_final8x SPX_NAMESPACE(sha256_final8x) +void sha256_final8x(sha256x8ctx *ctx, + unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7); + +#define sha256_transform8x SPX_NAMESPACE(sha256_transform8x) +void sha256_transform8x(sha256x8ctx *ctx, + const unsigned char *data0, + const unsigned char *data1, + const unsigned char *data2, + const unsigned char *data3, + const unsigned char *data4, + const unsigned char *data5, + const unsigned char *data6, + const unsigned char *data7); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/sha256x8.c b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/sha256x8.c new file mode 100644 index 0000000000..d97750c09b --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/sha256x8.c @@ -0,0 +1,185 @@ +#include + +#include "sha256avx.h" +#include "sha256x8.h" +#include "utils.h" + +// Performs sha256x8 on an initialized (and perhaps seeded) state. +static void _sha256x8( + sha256x8ctx *ctx, + unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, unsigned long long inlen) { + unsigned long long i = 0; + while (inlen - i >= 64) { + sha256_transform8x(ctx, + in0 + i, + in1 + i, + in2 + i, + in3 + i, + in4 + i, + in5 + i, + in6 + i, + in7 + i + ); + i += 64; + ctx->msglen += 512; + } + + size_t bytes_to_copy = (size_t)(inlen - i); + memcpy(&ctx->msgblocks[64 * 0], in0 + i, bytes_to_copy); + memcpy(&ctx->msgblocks[64 * 1], in1 + i, bytes_to_copy); + memcpy(&ctx->msgblocks[64 * 2], in2 + i, bytes_to_copy); + memcpy(&ctx->msgblocks[64 * 3], in3 + i, bytes_to_copy); + memcpy(&ctx->msgblocks[64 * 4], in4 + i, bytes_to_copy); + memcpy(&ctx->msgblocks[64 * 5], in5 + i, bytes_to_copy); + memcpy(&ctx->msgblocks[64 * 6], in6 + i, bytes_to_copy); + memcpy(&ctx->msgblocks[64 * 7], in7 + i, bytes_to_copy); + ctx->datalen = (unsigned int)bytes_to_copy; + + sha256_final8x(ctx, out0, out1, out2, out3, out4, out5, out6, out7); +} + +void sha256x8_seeded( + unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const sha256x8ctx *seed, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, unsigned long long inlen) { + + sha256x8ctx ctx; + sha256_ctx_clone8x(&ctx, seed); + + _sha256x8(&ctx, out0, out1, out2, out3, out4, out5, out6, out7, + in0, in1, in2, in3, in4, in5, in6, in7, inlen); +} + +/* This provides a wrapper around the internals of 8x parallel SHA256 */ +void sha256x8(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, unsigned long long inlen) { + sha256x8ctx ctx; + sha256_init8x(&ctx); + + _sha256x8(&ctx, out0, out1, out2, out3, out4, out5, out6, out7, + in0, in1, in2, in3, in4, in5, in6, in7, inlen); +} + +/** + * Note that inlen should be sufficiently small that it still allows for + * an array to be allocated on the stack. Typically 'in' is merely a seed. + * Outputs outlen number of bytes + */ +void mgf1x8(unsigned char *outx8, unsigned long outlen, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, + unsigned long inlen) { + PQCLEAN_VLA(unsigned char, inbufx8, 8 * (inlen + 4)); + unsigned char outbufx8[8 * SPX_SHA256_OUTPUT_BYTES]; + uint32_t i; + unsigned int j; + + memcpy(inbufx8 + 0 * (inlen + 4), in0, inlen); + memcpy(inbufx8 + 1 * (inlen + 4), in1, inlen); + memcpy(inbufx8 + 2 * (inlen + 4), in2, inlen); + memcpy(inbufx8 + 3 * (inlen + 4), in3, inlen); + memcpy(inbufx8 + 4 * (inlen + 4), in4, inlen); + memcpy(inbufx8 + 5 * (inlen + 4), in5, inlen); + memcpy(inbufx8 + 6 * (inlen + 4), in6, inlen); + memcpy(inbufx8 + 7 * (inlen + 4), in7, inlen); + + /* While we can fit in at least another full block of SHA256 output.. */ + for (i = 0; (i + 1)*SPX_SHA256_OUTPUT_BYTES <= outlen; i++) { + for (j = 0; j < 8; j++) { + u32_to_bytes(inbufx8 + inlen + j * (inlen + 4), i); + } + + sha256x8(outx8 + 0 * outlen, + outx8 + 1 * outlen, + outx8 + 2 * outlen, + outx8 + 3 * outlen, + outx8 + 4 * outlen, + outx8 + 5 * outlen, + outx8 + 6 * outlen, + outx8 + 7 * outlen, + inbufx8 + 0 * (inlen + 4), + inbufx8 + 1 * (inlen + 4), + inbufx8 + 2 * (inlen + 4), + inbufx8 + 3 * (inlen + 4), + inbufx8 + 4 * (inlen + 4), + inbufx8 + 5 * (inlen + 4), + inbufx8 + 6 * (inlen + 4), + inbufx8 + 7 * (inlen + 4), inlen + 4); + outx8 += SPX_SHA256_OUTPUT_BYTES; + } + /* Until we cannot anymore, and we fill the remainder. */ + for (j = 0; j < 8; j++) { + u32_to_bytes(inbufx8 + inlen + j * (inlen + 4), i); + } + sha256x8(outbufx8 + 0 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 1 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 2 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 3 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 4 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 5 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 6 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 7 * SPX_SHA256_OUTPUT_BYTES, + inbufx8 + 0 * (inlen + 4), + inbufx8 + 1 * (inlen + 4), + inbufx8 + 2 * (inlen + 4), + inbufx8 + 3 * (inlen + 4), + inbufx8 + 4 * (inlen + 4), + inbufx8 + 5 * (inlen + 4), + inbufx8 + 6 * (inlen + 4), + inbufx8 + 7 * (inlen + 4), inlen + 4); + + for (j = 0; j < 8; j++) { + memcpy(outx8 + j * outlen, + outbufx8 + j * SPX_SHA256_OUTPUT_BYTES, + outlen - i * SPX_SHA256_OUTPUT_BYTES); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/sha256x8.h b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/sha256x8.h new file mode 100644 index 0000000000..4f7330a6c1 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/sha256x8.h @@ -0,0 +1,64 @@ +#ifndef SPX_SHA256X8_H +#define SPX_SHA256X8_H + +#include "params.h" +#include "sha256avx.h" + + + +#define sha256x8_seeded SPX_NAMESPACE(sha256x8_seeded) +void sha256x8_seeded( + unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const sha256x8ctx *seed, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, unsigned long long inlen); + +/* This provides a wrapper around the internals of 8x parallel SHA256 */ +#define sha256x8 SPX_NAMESPACE(sha256x8) +void sha256x8(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, unsigned long long inlen); + +/** + * Note that inlen should be sufficiently small that it still allows for + * an array to be allocated on the stack. Typically 'in' is merely a seed. + * Outputs outlen number of bytes + */ +#define mgf1x8 SPX_NAMESPACE(mgf1x8) +void mgf1x8(unsigned char *outx8, unsigned long outlen, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, + unsigned long inlen); +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/sha2_offsets.h b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/sha2_offsets.h new file mode 100644 index 0000000000..6e3584f7a4 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/sha2_offsets.h @@ -0,0 +1,27 @@ +#ifndef SHA2_OFFSETS_H_ +#define SHA2_OFFSETS_H_ + +#define SPX_SHA256_BLOCK_BYTES 64 +#define SPX_SHA256_OUTPUT_BYTES 32 + +#define SPX_SHA512_BLOCK_BYTES 128 +#define SPX_SHA512_OUTPUT_BYTES 64 + +/* + * Offsets of various fields in the address structure when we use SHA2 as + * the Sphincs+ hash function + */ + +#define SPX_OFFSET_LAYER 0 /* The byte used to specify the Merkle tree layer */ +#define SPX_OFFSET_TREE 1 /* The start of the 8 byte field used to specify the tree */ +#define SPX_OFFSET_TYPE 9 /* The byte used to specify the hash type (reason) */ +#define SPX_OFFSET_KP_ADDR2 12 /* The high byte used to specify the key pair (which one-time signature) */ +#define SPX_OFFSET_KP_ADDR1 13 /* The low byte used to specify the key pair */ +#define SPX_OFFSET_CHAIN_ADDR 17 /* The byte used to specify the chain address (which Winternitz chain) */ +#define SPX_OFFSET_HASH_ADDR 21 /* The byte used to specify the hash address (where in the Winternitz chain) */ +#define SPX_OFFSET_TREE_HGT 17 /* The byte used to specify the height of this node in the FORS or Merkle tree */ +#define SPX_OFFSET_TREE_INDEX 18 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ + +#define SPX_SHA2 1 + +#endif /* SHA2_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/sha512x4.c b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/sha512x4.c new file mode 100644 index 0000000000..8d33deffdd --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/sha512x4.c @@ -0,0 +1,446 @@ +#include +#include +#include + +/* pull in the entire thing */ +#include "sha512x4.h" +#include "utils.h" + +typedef uint64_t u64; +typedef __m256i u256; + +#define BYTESWAP(x) _mm256_shuffle_epi8(x, _mm256_set_epi8(0x8,0x9,0xa,0xb,0xc,0xd,0xe,0xf,0x0,0x1,0x2,0x3,0x4,0x5,0x6,0x7,0x8,0x9,0xa,0xb,0xc,0xd,0xe,0xf,0x0,0x1,0x2,0x3,0x4,0x5,0x6,0x7)) +#define STORE(dest,src) _mm256_storeu_si256((__m256i *)(dest),src) + +// Transpose 4 vectors containing 64-bit values +// That is, it rearranges the array: +// A B C D +// E F G H +// I J K L +// M N O P +// into +// A E I M +// B F J N +// C G K O +// D H L P +// where each letter stands for 64 bits (and lsbits on the left) +static void transpose(u256 s[4]) { + u256 tmp[4]; + tmp[0] = _mm256_unpacklo_epi64(s[0], s[1]); + tmp[1] = _mm256_unpackhi_epi64(s[0], s[1]); + tmp[2] = _mm256_unpacklo_epi64(s[2], s[3]); + tmp[3] = _mm256_unpackhi_epi64(s[2], s[3]); + // tmp is in the order of + // A E C G + // B F D H + // I M K O + // J N L P + s[0] = _mm256_permute2x128_si256(tmp[0], tmp[2], 0x20); + s[1] = _mm256_permute2x128_si256(tmp[1], tmp[3], 0x20); + s[2] = _mm256_permute2x128_si256(tmp[0], tmp[2], 0x31); + s[3] = _mm256_permute2x128_si256(tmp[1], tmp[3], 0x31); +} + + +void sha512_init4x(sha512x4ctx *ctx) { +#define SET4(x) _mm256_set_epi64x((long long)(x), (long long)(x), (long long)(x), (long long)(x)) + ctx->s[0] = SET4(0x6a09e667f3bcc908ULL); + ctx->s[1] = SET4(0xbb67ae8584caa73bULL); + ctx->s[2] = SET4(0x3c6ef372fe94f82bULL); + ctx->s[3] = SET4(0xa54ff53a5f1d36f1ULL); + ctx->s[4] = SET4(0x510e527fade682d1ULL); + ctx->s[5] = SET4(0x9b05688c2b3e6c1fULL); + ctx->s[6] = SET4(0x1f83d9abfb41bd6bULL); + ctx->s[7] = SET4(0x5be0cd19137e2179ULL); +#undef SET4 + + ctx->datalen = 0; + ctx->msglen = 0; +} + +#define XOR _mm256_xor_si256 +#define OR _mm256_or_si256 +#define AND _mm256_and_si256 +#define ADD64 _mm256_add_epi64 + +#define LOAD(src) _mm256_loadu_si256((__m256i *)(src)) + +#define SHIFTR64(x, y) _mm256_srli_epi64(x, y) +#define SHIFTL64(x, y) _mm256_slli_epi64(x, y) + +#define ROTR64(x, y) OR(SHIFTR64(x, y), SHIFTL64(x, 64 - (y))) + +static u256 XOR3(u256 a, u256 b, u256 c) { + return XOR(XOR(a, b), c); +} + +#define ADD3_64(a, b, c) ADD64(ADD64(a, b), c) +#define ADD4_64(a, b, c, d) ADD64(ADD64(ADD64(a, b), c), d) +#define ADD5_64(a, b, c, d, e) ADD64(ADD64(ADD64(ADD64(a, b), c), d), e) + +static u256 MAJ_AVX(u256 a, u256 b, u256 c) { + return XOR(c, AND(XOR(a, c), XOR(b, c))); +} +static u256 CH_AVX(u256 a, u256 b, u256 c) { + return XOR(c, AND(a, XOR(b, c))); +} +static u256 SIGMA0_AVX(u256 x) { + return XOR3(ROTR64(x, 28), ROTR64(x, 34), ROTR64(x, 39)); +} +static u256 SIGMA1_AVX(u256 x) { + return XOR3(ROTR64(x, 14), ROTR64(x, 18), ROTR64(x, 41)); +} +static u256 GAMMA0_AVX(u256 x) { + return XOR3(ROTR64(x, 1), ROTR64(x, 8), SHIFTR64(x, 7)); +} +static u256 GAMMA1_AVX(u256 x) { + return XOR3(ROTR64(x, 19), ROTR64(x, 61), SHIFTR64(x, 6)); +} + +#define SHA512ROUND_AVX(a, b, c, d, e, f, g, h, rc, w) \ + T0 = ADD5_64(h, w, SIGMA1_AVX(e), CH_AVX(e, f, g), _mm256_set1_epi64x((long long)RC[rc])); \ + T1 = ADD64(SIGMA0_AVX(a), MAJ_AVX(a, b, c)); \ + (d) = ADD64(d, T0); \ + (h) = ADD64(T0, T1); + +static const unsigned long long RC[80] = { + 0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL, + 0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL, + 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL, + 0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL, + 0xd807aa98a3030242ULL, 0x12835b0145706fbeULL, + 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL, + 0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL, + 0x9bdc06a725c71235ULL, 0xc19bf174cf692694ULL, + 0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL, + 0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL, + 0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL, + 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL, + 0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL, + 0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL, + 0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL, + 0x06ca6351e003826fULL, 0x142929670a0e6e70ULL, + 0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL, + 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL, + 0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL, + 0x81c2c92e47edaee6ULL, 0x92722c851482353bULL, + 0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL, + 0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL, + 0xd192e819d6ef5218ULL, 0xd69906245565a910ULL, + 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL, + 0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL, + 0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL, + 0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL, + 0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL, + 0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL, + 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL, + 0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL, + 0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL, + 0xca273eceea26619cULL, 0xd186b8c721c0c207ULL, + 0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL, + 0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL, + 0x113f9804bef90daeULL, 0x1b710b35131c471bULL, + 0x28db77f523047d84ULL, 0x32caab7b40c72493ULL, + 0x3c9ebe0a15c9bebcULL, 0x431d67c49c100d4cULL, + 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL, + 0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL, +}; + +void sha512_transform4x( + sha512x4ctx *ctx, + const unsigned char *d0, + const unsigned char *d1, + const unsigned char *d2, + const unsigned char *d3) { + u256 s0, s1, s2, s3, s4, s5, s6, s7, w[16], T0, T1, nw; + + // Load words and transform data correctly + w[0 ] = BYTESWAP(LOAD(d0 )); + w[0 + 4] = BYTESWAP(LOAD(d0 + 32)); + w[0 + 8] = BYTESWAP(LOAD(d0 + 64)); + w[0 + 12] = BYTESWAP(LOAD(d0 + 96)); + + w[1 ] = BYTESWAP(LOAD(d1 )); + w[1 + 4] = BYTESWAP(LOAD(d1 + 32)); + w[1 + 8] = BYTESWAP(LOAD(d1 + 64)); + w[1 + 12] = BYTESWAP(LOAD(d1 + 96)); + + w[2 ] = BYTESWAP(LOAD(d2 )); + w[2 + 4] = BYTESWAP(LOAD(d2 + 32)); + w[2 + 8] = BYTESWAP(LOAD(d2 + 64)); + w[2 + 12] = BYTESWAP(LOAD(d2 + 96)); + + w[3 ] = BYTESWAP(LOAD(d3 )); + w[3 + 4] = BYTESWAP(LOAD(d3 + 32)); + w[3 + 8] = BYTESWAP(LOAD(d3 + 64)); + w[3 + 12] = BYTESWAP(LOAD(d3 + 96)); + + transpose(w); + transpose(w + 4); + transpose(w + 8); + transpose(w + 12); + + // Initial State + s0 = ctx->s[0]; + s1 = ctx->s[1]; + s2 = ctx->s[2]; + s3 = ctx->s[3]; + s4 = ctx->s[4]; + s5 = ctx->s[5]; + s6 = ctx->s[6]; + s7 = ctx->s[7]; + + // The first 16 rounds (where the w inputs are directly from the data) + SHA512ROUND_AVX(s0, s1, s2, s3, s4, s5, s6, s7, 0, w[0]); + SHA512ROUND_AVX(s7, s0, s1, s2, s3, s4, s5, s6, 1, w[1]); + SHA512ROUND_AVX(s6, s7, s0, s1, s2, s3, s4, s5, 2, w[2]); + SHA512ROUND_AVX(s5, s6, s7, s0, s1, s2, s3, s4, 3, w[3]); + SHA512ROUND_AVX(s4, s5, s6, s7, s0, s1, s2, s3, 4, w[4]); + SHA512ROUND_AVX(s3, s4, s5, s6, s7, s0, s1, s2, 5, w[5]); + SHA512ROUND_AVX(s2, s3, s4, s5, s6, s7, s0, s1, 6, w[6]); + SHA512ROUND_AVX(s1, s2, s3, s4, s5, s6, s7, s0, 7, w[7]); + SHA512ROUND_AVX(s0, s1, s2, s3, s4, s5, s6, s7, 8, w[8]); + SHA512ROUND_AVX(s7, s0, s1, s2, s3, s4, s5, s6, 9, w[9]); + SHA512ROUND_AVX(s6, s7, s0, s1, s2, s3, s4, s5, 10, w[10]); + SHA512ROUND_AVX(s5, s6, s7, s0, s1, s2, s3, s4, 11, w[11]); + SHA512ROUND_AVX(s4, s5, s6, s7, s0, s1, s2, s3, 12, w[12]); + SHA512ROUND_AVX(s3, s4, s5, s6, s7, s0, s1, s2, 13, w[13]); + SHA512ROUND_AVX(s2, s3, s4, s5, s6, s7, s0, s1, 14, w[14]); + SHA512ROUND_AVX(s1, s2, s3, s4, s5, s6, s7, s0, 15, w[15]); + +#define M(i) (((i)+16) & 0xf) +#define NextW(i) \ + w[M(i)] = ADD4_64(GAMMA1_AVX(w[M((i)-2)]), w[M((i)-7)], GAMMA0_AVX(w[M((i)-15)]), w[M((i)-16)]); + + // The remaining 64 rounds (where the w inputs are a linear fix of the data) + for (unsigned i = 16; i < 80; i += 16) { + nw = NextW(0); + SHA512ROUND_AVX(s0, s1, s2, s3, s4, s5, s6, s7, i + 0, nw); + nw = NextW(1); + SHA512ROUND_AVX(s7, s0, s1, s2, s3, s4, s5, s6, i + 1, nw); + nw = NextW(2); + SHA512ROUND_AVX(s6, s7, s0, s1, s2, s3, s4, s5, i + 2, nw); + nw = NextW(3); + SHA512ROUND_AVX(s5, s6, s7, s0, s1, s2, s3, s4, i + 3, nw); + nw = NextW(4); + SHA512ROUND_AVX(s4, s5, s6, s7, s0, s1, s2, s3, i + 4, nw); + nw = NextW(5); + SHA512ROUND_AVX(s3, s4, s5, s6, s7, s0, s1, s2, i + 5, nw); + nw = NextW(6); + SHA512ROUND_AVX(s2, s3, s4, s5, s6, s7, s0, s1, i + 6, nw); + nw = NextW(7); + SHA512ROUND_AVX(s1, s2, s3, s4, s5, s6, s7, s0, i + 7, nw); + nw = NextW(8); + SHA512ROUND_AVX(s0, s1, s2, s3, s4, s5, s6, s7, i + 8, nw); + nw = NextW(9); + SHA512ROUND_AVX(s7, s0, s1, s2, s3, s4, s5, s6, i + 9, nw); + nw = NextW(10); + SHA512ROUND_AVX(s6, s7, s0, s1, s2, s3, s4, s5, i + 10, nw); + nw = NextW(11); + SHA512ROUND_AVX(s5, s6, s7, s0, s1, s2, s3, s4, i + 11, nw); + nw = NextW(12); + SHA512ROUND_AVX(s4, s5, s6, s7, s0, s1, s2, s3, i + 12, nw); + nw = NextW(13); + SHA512ROUND_AVX(s3, s4, s5, s6, s7, s0, s1, s2, i + 13, nw); + nw = NextW(14); + SHA512ROUND_AVX(s2, s3, s4, s5, s6, s7, s0, s1, i + 14, nw); + nw = NextW(15); + SHA512ROUND_AVX(s1, s2, s3, s4, s5, s6, s7, s0, i + 15, nw); + } + + // Feed Forward + ctx->s[0] = ADD64(s0, ctx->s[0]); + ctx->s[1] = ADD64(s1, ctx->s[1]); + ctx->s[2] = ADD64(s2, ctx->s[2]); + ctx->s[3] = ADD64(s3, ctx->s[3]); + ctx->s[4] = ADD64(s4, ctx->s[4]); + ctx->s[5] = ADD64(s5, ctx->s[5]); + ctx->s[6] = ADD64(s6, ctx->s[6]); + ctx->s[7] = ADD64(s7, ctx->s[7]); +} + +static void _sha512x4( + sha512x4ctx *ctx, + unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + unsigned long long inlen) { + unsigned int i = 0; + + while (inlen - i >= 128) { + sha512_transform4x( + ctx, + in0 + i, + in1 + i, + in2 + i, + in3 + i + ); + ctx->msglen += 1024; + i += 128; + } + + ctx->datalen = (unsigned int)(inlen - i); + memcpy(&ctx->msgblocks[128 * 0], in0 + i, ctx->datalen); + memcpy(&ctx->msgblocks[128 * 1], in1 + i, ctx->datalen); + memcpy(&ctx->msgblocks[128 * 2], in2 + i, ctx->datalen); + memcpy(&ctx->msgblocks[128 * 3], in3 + i, ctx->datalen); + + // Padding + unsigned long curlen; + if (ctx->datalen < 112) { + for (i = 0; i < 4; ++i) { + curlen = ctx->datalen; + ctx->msgblocks[128 * i + curlen++] = 0x80; + while (curlen < 128) { + ctx->msgblocks[128 * i + curlen++] = 0x00; + } + } + } else { + for (i = 0; i < 4; ++i) { + curlen = ctx->datalen; + ctx->msgblocks[128 * i + curlen++] = 0x80; + while (curlen < 128) { + ctx->msgblocks[128 * i + curlen++] = 0x00; + } + } + sha512_transform4x( + ctx, + ctx->msgblocks, + ctx->msgblocks + 128, + ctx->msgblocks + 256, + ctx->msgblocks + 384 + ); + memset(ctx->msgblocks, 0, 4 * 128); + } + + // Add length of the message to each block + ctx->msglen += (unsigned long long)(ctx->datalen) * 8; + for (i = 0; i < 4; i++) { + ctx->msgblocks[128 * i + 127] = (unsigned char)(ctx->msglen); + ctx->msgblocks[128 * i + 126] = (unsigned char)(ctx->msglen >> 8); + ctx->msgblocks[128 * i + 125] = (unsigned char)(ctx->msglen >> 16); + ctx->msgblocks[128 * i + 124] = (unsigned char)(ctx->msglen >> 24); + ctx->msgblocks[128 * i + 123] = (unsigned char)(ctx->msglen >> 32); + ctx->msgblocks[128 * i + 122] = (unsigned char)(ctx->msglen >> 40); + ctx->msgblocks[128 * i + 121] = (unsigned char)(ctx->msglen >> 48); + ctx->msgblocks[128 * i + 120] = (unsigned char)(ctx->msglen >> 56); + memset( &ctx->msgblocks[128 * i + 112], 0, 8 ); + } + sha512_transform4x( + ctx, + ctx->msgblocks, + ctx->msgblocks + 128, + ctx->msgblocks + 256, + ctx->msgblocks + 384 + ); + + // Compute final hash output + transpose(ctx->s); + transpose(ctx->s + 4); + + // Store Hash value + __m256i out[2]; + STORE(out, BYTESWAP(ctx->s[0])); + STORE(out + 1, BYTESWAP(ctx->s[4])); + memcpy(out0, out, 64); + + STORE(out, BYTESWAP(ctx->s[1])); + STORE(out + 1, BYTESWAP(ctx->s[5])); + memcpy(out1, out, 64); + + STORE(out, BYTESWAP(ctx->s[2])); + STORE(out + 1, BYTESWAP(ctx->s[6])); + memcpy(out2, out, 64); + + STORE(out, BYTESWAP(ctx->s[3])); + STORE(out + 1, BYTESWAP(ctx->s[7])); + memcpy(out3, out, 64); +} + + +/** + * Note that inlen should be sufficiently small that it still allows for + * an array to be allocated on the stack. Typically 'in' is merely a seed. + * Outputs outlen number of bytes + */ +void mgf1x4_512(unsigned char *outx4, unsigned long outlen, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + unsigned long inlen) { + PQCLEAN_VLA(unsigned char, inbufx4, 4 * (inlen + 4)); + unsigned char outbuf[4 * 64]; + uint32_t i; + unsigned int j; + + memcpy(inbufx4 + 0 * (inlen + 4), in0, inlen); + memcpy(inbufx4 + 1 * (inlen + 4), in1, inlen); + memcpy(inbufx4 + 2 * (inlen + 4), in2, inlen); + memcpy(inbufx4 + 3 * (inlen + 4), in3, inlen); + + /* While we can fit in at least another full block of SHA512 output.. */ + unsigned long remaining = outlen; + for (i = 0; remaining > 0; i++) { + unsigned long this_step = SPX_SHA512_OUTPUT_BYTES; + if (this_step > remaining) { + this_step = remaining; + } + remaining -= this_step; + for (j = 0; j < 4; j++) { + u32_to_bytes(inbufx4 + inlen + j * (inlen + 4), i); + } + + sha512x4ctx ctx; + sha512_init4x(&ctx); + + _sha512x4( + &ctx, + outbuf + 0 * 64, + outbuf + 1 * 64, + outbuf + 2 * 64, + outbuf + 3 * 64, + inbufx4 + 0 * (inlen + 4), + inbufx4 + 1 * (inlen + 4), + inbufx4 + 2 * (inlen + 4), + inbufx4 + 3 * (inlen + 4), + inlen + 4 + ); + + memcpy(outx4 + 0 * outlen, outbuf + 0 * 64, this_step); + memcpy(outx4 + 1 * outlen, outbuf + 1 * 64, this_step); + memcpy(outx4 + 2 * outlen, outbuf + 2 * 64, this_step); + memcpy(outx4 + 3 * outlen, outbuf + 3 * 64, this_step); + outx4 += this_step; + } +} + +void sha512x4_seeded( + unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const sha512x4ctx *seed, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + unsigned long long inlen) { + sha512x4ctx ctx; + sha512_ctx_clone4x(&ctx, seed); + _sha512x4( + &ctx, + out0, out1, out2, out3, + in0, in1, in2, in3, + inlen + ); +} + +void sha512_ctx_clone4x(sha512x4ctx *out, const sha512x4ctx *in) { + memcpy(out, in, sizeof(sha512x4ctx)); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/sha512x4.h b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/sha512x4.h new file mode 100644 index 0000000000..9bbe736514 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/sha512x4.h @@ -0,0 +1,58 @@ +#ifndef SHA512AVX_H +#define SHA512AVX_H + +#include +#include + + +#include "params.h" + +typedef struct SHA512state4x { + __m256i s[8]; + unsigned char msgblocks[4 * 128]; + unsigned int datalen; + unsigned long long msglen; +} sha512x4ctx; + +#define sha512_init4x SPX_NAMESPACE(sha512_init4x) +void sha512_init4x(sha512x4ctx *ctx); + +#define sha512_transform4x SPX_NAMESPACE(sha512_transform4x) +void sha512_transform4x( + sha512x4ctx *ctx, + const unsigned char *d0, + const unsigned char *d1, + const unsigned char *d2, + const unsigned char *d3); + + +#define sha512x4_seeded SPX_NAMESPACE(sha512x4_seeded) +void sha512x4_seeded( + unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const sha512x4ctx *seed, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + unsigned long long inlen); + +#define sha512_ctx_clone4x SPX_NAMESPACE(sha512_ctx_clone4x) +void sha512_ctx_clone4x(sha512x4ctx *out, const sha512x4ctx *in); + +/** + * Note that inlen should be sufficiently small that it still allows for + * an array to be allocated on the stack. Typically 'in' is merely a seed. + * Outputs outlen number of bytes + */ +#define mgf1x4_512 SPX_NAMESPACE(mgf1x4_512) +void mgf1x4_512(unsigned char *outx4, unsigned long outlen, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + unsigned long inlen); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/sign.c b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/sign.c new file mode 100644 index 0000000000..9d0c7d1b22 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/sign.c @@ -0,0 +1,286 @@ +#include +#include +#include + +#include "address.h" +#include "context.h" +#include "fors.h" +#include "hash.h" +#include "merkle.h" +#include "nistapi.h" +#include "params.h" +#include "randombytes.h" +#include "thash.h" +#include "utils.h" +#include "wots.h" + +/* + * Returns the length of a secret key, in bytes + */ +size_t crypto_sign_secretkeybytes(void) { + return CRYPTO_SECRETKEYBYTES; +} + +/* + * Returns the length of a public key, in bytes + */ +size_t crypto_sign_publickeybytes(void) { + return CRYPTO_PUBLICKEYBYTES; +} + +/* + * Returns the length of a signature, in bytes + */ +size_t crypto_sign_bytes(void) { + return CRYPTO_BYTES; +} + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +size_t crypto_sign_seedbytes(void) { + return CRYPTO_SEEDBYTES; +} + +/* + * Generates an SPX key pair given a seed of length + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [PUB_SEED || root] + */ +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed) { + spx_ctx ctx; + + /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ + memcpy(sk, seed, CRYPTO_SEEDBYTES); + + memcpy(pk, sk + 2 * SPX_N, SPX_N); + + memcpy(ctx.pub_seed, pk, SPX_N); + memcpy(ctx.sk_seed, sk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + /* Compute root node of the top-most subtree. */ + merkle_gen_root(sk + 3 * SPX_N, &ctx); + + // cleanup + free_hash_function(&ctx); + + memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); + + return 0; +} + +/* + * Generates an SPX key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [PUB_SEED || root] + */ +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { + uint8_t seed[CRYPTO_SEEDBYTES]; + randombytes(seed, CRYPTO_SEEDBYTES); + crypto_sign_seed_keypair(pk, sk, seed); + + return 0; +} + +/** + * Returns an array containing a detached signature. + */ +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk) { + spx_ctx ctx; + + const uint8_t *sk_prf = sk + SPX_N; + const uint8_t *pk = sk + 2 * SPX_N; + + uint8_t optrand[SPX_N]; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t root[SPX_N]; + uint32_t i; + uint64_t tree; + uint32_t idx_leaf; + uint32_t wots_addr[8] = {0}; + uint32_t tree_addr[8] = {0}; + + memcpy(ctx.sk_seed, sk, SPX_N); + memcpy(ctx.pub_seed, pk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + + /* Optionally, signing can be made non-deterministic using optrand. + This can help counter side-channel attacks that would benefit from + getting a large number of traces when the signer uses the same nodes. */ + randombytes(optrand, SPX_N); + /* Compute the digest randomization value. */ + gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); + + /* Derive the message digest and leaf index from R, PK and M. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; + + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); + + /* Sign the message hash using FORS. */ + fors_sign(sig, root, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); + sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; + + /* Update the indices for the next layer. */ + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; + } + + free_hash_function(&ctx); + + *siglen = SPX_BYTES; + + return 0; +} + +/** + * Verifies a detached signature and message under a given public key. + */ +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk) { + spx_ctx ctx; + const uint8_t *pub_root = pk + SPX_N; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t wots_pk[SPX_WOTS_BYTES]; + uint8_t root[SPX_N]; + uint8_t leaf[SPX_N]; + unsigned int i; + uint64_t tree; + uint32_t idx_leaf; + uint32_t wots_addr[8] = {0}; + uint32_t tree_addr[8] = {0}; + uint32_t wots_pk_addr[8] = {0}; + + if (siglen != SPX_BYTES) { + return -1; + } + + memcpy(ctx.pub_seed, pk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); + + /* Derive the message digest and leaf index from R || PK || M. */ + /* The additional SPX_N is a result of the hash domain separator. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; + + /* Layer correctly defaults to 0, so no need to set_layer_addr */ + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); + + fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + /* For each subtree.. */ + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + copy_keypair_addr(wots_pk_addr, wots_addr); + + /* The WOTS public key is only correct if the signature was correct. */ + /* Initially, root is the FORS pk, but on subsequent iterations it is + the root of the subtree below the currently processed subtree. */ + wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); + sig += SPX_WOTS_BYTES; + + /* Compute the leaf node using the WOTS public key. */ + thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); + + /* Compute the root node of this subtree. */ + compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, + &ctx, tree_addr); + sig += SPX_TREE_HEIGHT * SPX_N; + + /* Update the indices for the next layer. */ + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; + } + + // cleanup + free_hash_function(&ctx); + + /* Check if the root node equals the root node in the public key. */ + if (memcmp(root, pub_root, SPX_N) != 0) { + return -1; + } + + return 0; +} + + +/** + * Returns an array containing the signature followed by the message. + */ +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk) { + size_t siglen; + + crypto_sign_signature(sm, &siglen, m, mlen, sk); + + memmove(sm + SPX_BYTES, m, mlen); + *smlen = siglen + mlen; + + return 0; +} + +/** + * Verifies a given signature-message pair under a given public key. + */ +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk) { + /* The API caller does not necessarily know what size a signature should be + but SPHINCS+ signatures are always exactly SPX_BYTES. */ + if (smlen < SPX_BYTES) { + memset(m, 0, smlen); + *mlen = 0; + return -1; + } + + *mlen = smlen - SPX_BYTES; + + if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { + memset(m, 0, smlen); + *mlen = 0; + return -1; + } + + /* If verification was successful, move the message to the right place. */ + memmove(m, sm + SPX_BYTES, *mlen); + + return 0; +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/thash.h b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/thash.h new file mode 100644 index 0000000000..8687ccfb4d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/thash.h @@ -0,0 +1,13 @@ +#ifndef SPX_THASH_H +#define SPX_THASH_H + +#include "context.h" +#include "params.h" + +#include + +#define thash SPX_NAMESPACE(thash) +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/thash_sha2_robust.c b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/thash_sha2_robust.c new file mode 100644 index 0000000000..3ab891175f --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/thash_sha2_robust.c @@ -0,0 +1,68 @@ +#include +#include + +#include "address.h" +#include "context.h" +#include "hash.h" +#include "params.h" +#include "sha2.h" +#include "thash.h" +#include "utils.h" + +static void thash_512(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]); + +/** + * Takes an array of inblocks concatenated arrays of SPX_N bytes. + */ +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]) { + if (inblocks > 1) { + thash_512(out, in, inblocks, ctx, addr); + return; + } + unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES]; + PQCLEAN_VLA(uint8_t, bitmask, inblocks * SPX_N); + PQCLEAN_VLA(uint8_t, buf, SPX_N + SPX_SHA256_OUTPUT_BYTES + inblocks * SPX_N); + sha256ctx sha2_state; + unsigned int i; + + memcpy(buf, ctx->pub_seed, SPX_N); + memcpy(buf + SPX_N, addr, SPX_SHA256_ADDR_BYTES); + mgf1_256(bitmask, inblocks * SPX_N, buf, SPX_N + SPX_SHA256_ADDR_BYTES); + + /* Retrieve precomputed state containing pub_seed */ + sha256_inc_ctx_clone(&sha2_state, &ctx->state_seeded); + + for (i = 0; i < inblocks * SPX_N; i++) { + buf[SPX_N + SPX_SHA256_ADDR_BYTES + i] = in[i] ^ bitmask[i]; + } + + sha256_inc_finalize(outbuf, &sha2_state, buf + SPX_N, + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N); + memcpy(out, outbuf, SPX_N); +} + +static void thash_512(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]) { + unsigned char outbuf[SPX_SHA512_OUTPUT_BYTES]; + PQCLEAN_VLA(uint8_t, bitmask, inblocks * SPX_N); + PQCLEAN_VLA(uint8_t, buf, SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N); + sha512ctx sha2_state; + unsigned int i; + + memcpy(buf, ctx->pub_seed, SPX_N); + memcpy(buf + SPX_N, addr, SPX_SHA256_ADDR_BYTES); + mgf1_512(bitmask, inblocks * SPX_N, buf, SPX_N + SPX_SHA256_ADDR_BYTES); + + /* Retrieve precomputed state containing pub_seed */ + sha512_inc_ctx_clone(&sha2_state, &ctx->state_seeded_512); + + for (i = 0; i < inblocks * SPX_N; i++) { + buf[SPX_N + SPX_SHA256_ADDR_BYTES + i] = in[i] ^ bitmask[i]; + } + + sha512_inc_finalize(outbuf, &sha2_state, buf + SPX_N, + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N); + memcpy(out, outbuf, SPX_N); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/thash_sha2_robustx8.c b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/thash_sha2_robustx8.c new file mode 100644 index 0000000000..991faa7eeb --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/thash_sha2_robustx8.c @@ -0,0 +1,268 @@ +#include +#include + +#include "thashx8.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "sha2.h" +#include "sha256avx.h" +#include "sha256x8.h" +#include "utils.h" + +#include "sha512x4.h" + +static void thashx8_512( + unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, + unsigned int inblocks, + const spx_ctx *ctx, + uint32_t addrx8[8 * 8] +); + +/** + * 8-way parallel version of thash; takes 8x as much input and output + */ +void thashx8(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addrx8[8 * 8]) { + if (inblocks > 1) { + thashx8_512( + out0, out1, out2, out3, out4, out5, out6, out7, + in0, in1, in2, in3, in4, in5, in6, in7, + inblocks, ctx, addrx8); + return; + } + PQCLEAN_VLA(unsigned char, bufx8, 8 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)); + unsigned char outbufx8[8 * SPX_SHA256_OUTPUT_BYTES]; + PQCLEAN_VLA(unsigned char, bitmaskx8, 8 * (inblocks * SPX_N)); + unsigned int i; + + for (i = 0; i < 8; i++) { + memcpy(bufx8 + i * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + ctx->pub_seed, SPX_N); + memcpy(bufx8 + SPX_N + + i * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + addrx8 + i * 8, SPX_SHA256_ADDR_BYTES); + } + + mgf1x8(bitmaskx8, inblocks * SPX_N, + bufx8 + 0 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + 1 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + 2 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + 3 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + 4 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + 5 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + 6 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + 7 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + SPX_N + SPX_SHA256_ADDR_BYTES); + + for (i = 0; i < inblocks * SPX_N; i++) { + bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + + 0 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = + in0[i] ^ bitmaskx8[i + 0 * (inblocks * SPX_N)]; + bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + + 1 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = + in1[i] ^ bitmaskx8[i + 1 * (inblocks * SPX_N)]; + bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + + 2 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = + in2[i] ^ bitmaskx8[i + 2 * (inblocks * SPX_N)]; + bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + + 3 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = + in3[i] ^ bitmaskx8[i + 3 * (inblocks * SPX_N)]; + bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + + 4 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = + in4[i] ^ bitmaskx8[i + 4 * (inblocks * SPX_N)]; + bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + + 5 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = + in5[i] ^ bitmaskx8[i + 5 * (inblocks * SPX_N)]; + bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + + 6 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = + in6[i] ^ bitmaskx8[i + 6 * (inblocks * SPX_N)]; + bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + + 7 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = + in7[i] ^ bitmaskx8[i + 7 * (inblocks * SPX_N)]; + } + + sha256x8_seeded( + /* out */ + outbufx8 + 0 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 1 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 2 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 3 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 4 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 5 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 6 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 7 * SPX_SHA256_OUTPUT_BYTES, + + /* seed */ + &ctx->statex8_seeded, + + /* in */ + bufx8 + SPX_N + 0 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + SPX_N + 1 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + SPX_N + 2 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + SPX_N + 3 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + SPX_N + 4 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + SPX_N + 5 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + SPX_N + 6 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + SPX_N + 7 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N /* len */ + ); + + memcpy(out0, outbufx8 + 0 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out1, outbufx8 + 1 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out2, outbufx8 + 2 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out3, outbufx8 + 3 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out4, outbufx8 + 4 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out5, outbufx8 + 5 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out6, outbufx8 + 6 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out7, outbufx8 + 7 * SPX_SHA256_OUTPUT_BYTES, SPX_N); +} + +/** + * 2x4-way parallel version of thash; this is for the uses of thash that are + * based on SHA-512 + */ +static void thashx8_512( + unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, + unsigned int inblocks, + const spx_ctx *ctx, + uint32_t addrx8[8 * 8]) { + PQCLEAN_VLA(unsigned char, bufx8, 8 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)); + unsigned char outbuf[4 * SPX_SHA512_OUTPUT_BYTES]; + PQCLEAN_VLA(unsigned char, bitmaskx4, 4 * (inblocks * SPX_N)); + unsigned int i; + + for (i = 0; i < 8; i++) { + memcpy(bufx8 + i * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + ctx->pub_seed, SPX_N); + memcpy(bufx8 + SPX_N + + i * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + addrx8 + i * 8, SPX_SHA256_ADDR_BYTES); + } + + mgf1x4_512(bitmaskx4, inblocks * SPX_N, + bufx8 + 0 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + 1 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + 2 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + 3 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + SPX_N + SPX_SHA256_ADDR_BYTES); + + for (i = 0; i < inblocks * SPX_N; i++) { + bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + + 0 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = + in0[i] ^ bitmaskx4[i + 0 * (inblocks * SPX_N)]; + bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + + 1 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = + in1[i] ^ bitmaskx4[i + 1 * (inblocks * SPX_N)]; + bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + + 2 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = + in2[i] ^ bitmaskx4[i + 2 * (inblocks * SPX_N)]; + bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + + 3 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = + in3[i] ^ bitmaskx4[i + 3 * (inblocks * SPX_N)]; + } + + mgf1x4_512(bitmaskx4, inblocks * SPX_N, + bufx8 + 4 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + 5 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + 6 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + 7 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + SPX_N + SPX_SHA256_ADDR_BYTES); + + for (i = 0; i < inblocks * SPX_N; i++) { + bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + + 4 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = + in4[i] ^ bitmaskx4[i + 0 * (inblocks * SPX_N)]; + bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + + 5 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = + in5[i] ^ bitmaskx4[i + 1 * (inblocks * SPX_N)]; + bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + + 6 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = + in6[i] ^ bitmaskx4[i + 2 * (inblocks * SPX_N)]; + bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + + 7 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = + in7[i] ^ bitmaskx4[i + 3 * (inblocks * SPX_N)]; + } + + sha512x4_seeded( + outbuf + 0 * SPX_SHA512_OUTPUT_BYTES, + outbuf + 1 * SPX_SHA512_OUTPUT_BYTES, + outbuf + 2 * SPX_SHA512_OUTPUT_BYTES, + outbuf + 3 * SPX_SHA512_OUTPUT_BYTES, + &ctx->statex4_seeded_512, /* seed */ + bufx8 + SPX_N + 0 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + SPX_N + 1 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + SPX_N + 2 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + SPX_N + 3 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N /* len */ + ); + + memcpy(out0, outbuf + 0 * SPX_SHA512_OUTPUT_BYTES, SPX_N); + memcpy(out1, outbuf + 1 * SPX_SHA512_OUTPUT_BYTES, SPX_N); + memcpy(out2, outbuf + 2 * SPX_SHA512_OUTPUT_BYTES, SPX_N); + memcpy(out3, outbuf + 3 * SPX_SHA512_OUTPUT_BYTES, SPX_N); + + sha512x4_seeded( + outbuf + 0 * SPX_SHA512_OUTPUT_BYTES, + outbuf + 1 * SPX_SHA512_OUTPUT_BYTES, + outbuf + 2 * SPX_SHA512_OUTPUT_BYTES, + outbuf + 3 * SPX_SHA512_OUTPUT_BYTES, + &ctx->statex4_seeded_512, /* seed */ + bufx8 + SPX_N + 4 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + SPX_N + 5 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + SPX_N + 6 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + SPX_N + 7 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N /* len */ + ); + + memcpy(out4, outbuf + 0 * SPX_SHA512_OUTPUT_BYTES, SPX_N); + memcpy(out5, outbuf + 1 * SPX_SHA512_OUTPUT_BYTES, SPX_N); + memcpy(out6, outbuf + 2 * SPX_SHA512_OUTPUT_BYTES, SPX_N); + memcpy(out7, outbuf + 3 * SPX_SHA512_OUTPUT_BYTES, SPX_N); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/thashx8.h b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/thashx8.h new file mode 100644 index 0000000000..c02fe9cf3e --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/thashx8.h @@ -0,0 +1,28 @@ +#ifndef SPX_THASHX8_H +#define SPX_THASHX8_H + +#include + +#include "context.h" +#include "params.h" + +#define thashx8 SPX_NAMESPACE(thashx8) +void thashx8(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addrx8[8 * 8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/utils.c b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/utils.c new file mode 100644 index 0000000000..177b541fb9 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/utils.c @@ -0,0 +1,148 @@ +#include + +#include "utils.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "thash.h" + +/** + * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. + */ +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in) { + int i; + + /* Iterate over out in decreasing order, for big-endianness. */ + for (i = (signed int)outlen - 1; i >= 0; i--) { + out[i] = in & 0xff; + in = in >> 8; + } +} + +void u32_to_bytes(unsigned char *out, uint32_t in) { + out[0] = (unsigned char)(in >> 24); + out[1] = (unsigned char)(in >> 16); + out[2] = (unsigned char)(in >> 8); + out[3] = (unsigned char)in; +} + +/** + * Converts the inlen bytes in 'in' from big-endian byte order to an integer. + */ +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { + unsigned long long retval = 0; + unsigned int i; + + for (i = 0; i < inlen; i++) { + retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); + } + return retval; +} + +/** + * Computes a root node given a leaf and an auth path. + * Expects address to be complete other than the tree_height and tree_index. + */ +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]) { + uint32_t i; + unsigned char buffer[2 * SPX_N]; + + /* If leaf_idx is odd (last bit = 1), current path element is a right child + and auth_path has to go left. Otherwise it is the other way around. */ + if (leaf_idx & 1) { + memcpy(buffer + SPX_N, leaf, SPX_N); + memcpy(buffer, auth_path, SPX_N); + } else { + memcpy(buffer, leaf, SPX_N); + memcpy(buffer + SPX_N, auth_path, SPX_N); + } + auth_path += SPX_N; + + for (i = 0; i < tree_height - 1; i++) { + leaf_idx >>= 1; + idx_offset >>= 1; + /* Set the address of the node we're creating. */ + set_tree_height(addr, i + 1); + set_tree_index(addr, leaf_idx + idx_offset); + + /* Pick the right or left neighbor, depending on parity of the node. */ + if (leaf_idx & 1) { + thash(buffer + SPX_N, buffer, 2, ctx, addr); + memcpy(buffer, auth_path, SPX_N); + } else { + thash(buffer, buffer, 2, ctx, addr); + memcpy(buffer + SPX_N, auth_path, SPX_N); + } + auth_path += SPX_N; + } + + /* The last iteration is exceptional; we do not copy an auth_path node. */ + leaf_idx >>= 1; + idx_offset >>= 1; + set_tree_height(addr, tree_height); + set_tree_index(addr, leaf_idx + idx_offset); + thash(root, buffer, 2, ctx, addr); +} + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx * /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]) { + PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); + PQCLEAN_VLA(unsigned int, heights, tree_height + 1); + unsigned int offset = 0; + uint32_t idx; + uint32_t tree_idx; + + for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { + /* Add the next leaf node to the stack. */ + gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); + offset++; + heights[offset - 1] = 0; + + /* If this is a node we need for the auth path.. */ + if ((leaf_idx ^ 0x1) == idx) { + memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); + } + + /* While the top-most nodes are of equal height.. */ + while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { + /* Compute index of the new node, in the next layer. */ + tree_idx = (idx >> (heights[offset - 1] + 1)); + + /* Set the address of the node we're creating. */ + set_tree_height(tree_addr, heights[offset - 1] + 1); + set_tree_index(tree_addr, + tree_idx + (idx_offset >> (heights[offset - 1] + 1))); + /* Hash the top-most nodes from the stack together. */ + thash(stack + (offset - 2)*SPX_N, + stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); + offset--; + /* Note that the top-most node is now one layer higher. */ + heights[offset - 1]++; + + /* If this is a node we need for the auth path.. */ + if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { + memcpy(auth_path + heights[offset - 1]*SPX_N, + stack + (offset - 1)*SPX_N, SPX_N); + } + } + } + memcpy(root, stack, SPX_N); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/utils.h b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/utils.h new file mode 100644 index 0000000000..64f5d5a53a --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/utils.h @@ -0,0 +1,58 @@ +#ifndef SPX_UTILS_H +#define SPX_UTILS_H + +#include + +#include "compat.h" +#include "context.h" +#include "params.h" + + +/* To support MSVC use alloca() instead of VLAs. See #20. */ + + +/** + * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. + */ +#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in); +#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) +void u32_to_bytes(unsigned char *out, uint32_t in); + +/** + * Converts the inlen bytes in 'in' from big-endian byte order to an integer. + */ +#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); + +/** + * Computes a root node given a leaf and an auth path. + * Expects address to be complete other than the tree_height and tree_index. + */ +#define compute_root SPX_NAMESPACE(compute_root) +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]); + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +#define treehash SPX_NAMESPACE(treehash) +void treehash(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx *ctx /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]); + + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/utilsx8.c b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/utilsx8.c new file mode 100644 index 0000000000..f044b9595d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/utilsx8.c @@ -0,0 +1,146 @@ +#include + +#include "utils.h" +#include "utilsx8.h" + +#include "address.h" +#include "params.h" +#include "thashx8.h" + +/* + * Generate the entire Merkle tree, computing the authentication path for leaf_idx, + * and the resulting root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) + * + * This expects tree_addrx8 to be initialized to 8 parallel addr structures for + * the Merkle tree nodes + * + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + * + * This works by using the standard Merkle tree building algorithm, except + * that each 'node' tracked is actually 8 consecutive nodes in the real tree. + * When we combine two logical nodes ABCDEFGH and STUVWXYZ, we perform the H + * operation on adjacent real nodes, forming the parent logical node + * (AB)(CD)(EF)(GH)(ST)(UV)(WX)(YZ) + * + * When we get to the top three levels of the real tree (where there is only + * one logical node), we continue this operation three more times; the right + * most real node will by the actual root (and the other 7 nodes will be + * garbage). We follow the same thashx8 logic so that the 'extract + * authentication path components' part of the loop is still executed (and + * to simplify the code somewhat) + * + * This currently assumes tree_height >= 3; I suspect that doing an adjusting + * idx, addr_idx on the gen_leafx8 call if tree_height < 3 would fix it; since + * we don't actually use such short trees, I haven't bothered + */ +void treehashx8(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, + uint32_t tree_height, + void (*gen_leafx8)( + unsigned char * /* Where to write the leaves */, + const spx_ctx *, + uint32_t idx, void *info), + uint32_t tree_addrx8[8 * 8], + void *info) { + /* This is where we keep the intermediate nodes */ + PQCLEAN_VLA(unsigned char, stackx8, tree_height * 8 * SPX_N); + uint32_t left_adj = 0, prev_left_adj = 0; /* When we're doing the top 3 */ + /* levels, the left-most part of the tree isn't at the beginning */ + /* of current[]. These give the offset of the actual start */ + + uint32_t idx; + uint32_t max_idx = ((uint32_t)1 << (tree_height - 3)) - 1; + for (idx = 0;; idx++) { + unsigned char current[8 * SPX_N]; /* Current logical node */ + gen_leafx8( current, ctx, 8 * idx + idx_offset, + info ); + + /* Now combine the freshly generated right node with previously */ + /* generated left ones */ + uint32_t internal_idx_offset = idx_offset; + uint32_t internal_idx = idx; + uint32_t internal_leaf = leaf_idx; + uint32_t h; /* The height we are in the Merkle tree */ + for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { + + /* Special processing if we're at the top of the tree */ + if (h >= tree_height - 3) { + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[7 * SPX_N], SPX_N ); + return; + } + /* The tree indexing logic is a bit off in this case */ + /* Adjust it so that the left-most node of the part of */ + /* the tree that we're processing has index 0 */ + prev_left_adj = left_adj; + left_adj = (uint32_t)(8 - (1 << (tree_height - h - 1))); + } + + /* Check if we hit the top of the tree */ + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[7 * SPX_N], SPX_N ); + return; + } + + /* + * Check if one of the nodes we have is a part of the + * authentication path; if it is, write it out + */ + if ((((internal_idx << 3) ^ internal_leaf) & ~0x7U) == 0) { + memcpy( &auth_path[ h * SPX_N ], + ¤t[(((internal_leaf & 7) ^ 1) + prev_left_adj) * SPX_N], + SPX_N ); + } + + /* + * Check if we're at a left child; if so, stop going up the stack + * Exception: if we've reached the end of the tree, keep on going + * (so we combine the last 8 nodes into the one root node in three + * more iterations) + */ + if ((internal_idx & 1) == 0 && idx < max_idx) { + break; + } + + /* Ok, we're at a right node (or doing the top 3 levels) */ + /* Now combine the left and right logical nodes together */ + + /* Set the address of the node we're creating. */ + uint32_t j; + internal_idx_offset >>= 1; + for (j = 0; j < 8; j++) { + set_tree_height(tree_addrx8 + j * 8, h + 1); + set_tree_index(tree_addrx8 + j * 8, + (8 / 2) * (internal_idx & ~1U) + j - left_adj + internal_idx_offset ); + } + unsigned char *left = &stackx8[h * 8 * SPX_N]; + thashx8( ¤t[0 * SPX_N], + ¤t[1 * SPX_N], + ¤t[2 * SPX_N], + ¤t[3 * SPX_N], + ¤t[4 * SPX_N], + ¤t[5 * SPX_N], + ¤t[6 * SPX_N], + ¤t[7 * SPX_N], + &left [0 * SPX_N], + &left [2 * SPX_N], + &left [4 * SPX_N], + &left [6 * SPX_N], + ¤t[0 * SPX_N], + ¤t[2 * SPX_N], + ¤t[4 * SPX_N], + ¤t[6 * SPX_N], + 2, ctx, tree_addrx8); + } + + /* We've hit a left child; save the current for when we get the */ + /* corresponding right right */ + memcpy( &stackx8[h * 8 * SPX_N], current, 8 * SPX_N); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/utilsx8.h b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/utilsx8.h new file mode 100644 index 0000000000..806d1e85be --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/utilsx8.h @@ -0,0 +1,29 @@ +#ifndef SPX_UTILSX8_H +#define SPX_UTILSX8_H + +#include + +#include "params.h" + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + * + * This implementation uses AVX to compute internal nodes 8 at a time (in + * parallel) + */ +#define treehashx8 SPX_NAMESPACE(treehashx8) +void treehashx8(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leafx8)( + unsigned char * /* Where to write the leaves */, + const spx_ctx * /* ctx */, + uint32_t addr_idx, void *info), + uint32_t tree_addrx8[8 * 8], void *info); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/wots.c b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/wots.c new file mode 100644 index 0000000000..689baf4db9 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/wots.c @@ -0,0 +1,291 @@ +#include +#include + +#include "wots.h" + +#include "address.h" +#include "hash.h" +#include "hashx8.h" +#include "params.h" +#include "thash.h" +#include "thashx8.h" +#include "utils.h" +#include "utilsx8.h" +#include "wotsx8.h" + +// TODO clarify address expectations, and make them more uniform. +// TODO i.e. do we expect types to be set already? +// TODO and do we expect modifications or copies? + +/** + * Computes up the chains + */ +static void gen_chains( + unsigned char *out, + const unsigned char *in, + unsigned int start[SPX_WOTS_LEN], + const unsigned int steps[SPX_WOTS_LEN], + const spx_ctx *ctx, + uint32_t addr[8]) { + uint32_t i, j, k, idx, watching; + int done; + unsigned char empty[SPX_N]; + unsigned char *bufs[8]; + uint32_t addrs[8 * 8]; + + int l; + uint16_t counts[SPX_WOTS_W] = { 0 }; + uint16_t idxs[SPX_WOTS_LEN]; + uint16_t total, newTotal; + + /* set addrs = {addr, addr, ..., addr} */ + for (j = 0; j < 8; j++) { + memcpy(addrs + j * 8, addr, sizeof(uint32_t) * 8); + } + + /* Initialize out with the value at position 'start'. */ + memcpy(out, in, SPX_WOTS_LEN * SPX_N); + + /* Sort the chains in reverse order by steps using counting sort. */ + for (i = 0; i < SPX_WOTS_LEN; i++) { + counts[steps[i]]++; + } + total = 0; + for (l = SPX_WOTS_W - 1; l >= 0; l--) { + newTotal = counts[l] + total; + counts[l] = total; + total = newTotal; + } + for (i = 0; i < SPX_WOTS_LEN; i++) { + idxs[counts[steps[i]]] = (uint16_t)i; + counts[steps[i]]++; + } + + /* We got our work cut out for us: do it! */ + for (i = 0; i < SPX_WOTS_LEN; i += 8) { + for (j = 0; j < 8 && i + j < SPX_WOTS_LEN; j++) { + idx = idxs[i + j]; + set_chain_addr(addrs + j * 8, idx); + bufs[j] = out + SPX_N * idx; + } + + /* As the chains are sorted in reverse order, we know that the first + * chain is the longest and the last one is the shortest. We keep + * an eye on whether the last chain is done and then on the one before, + * et cetera. */ + watching = 7; + done = 0; + while (i + watching >= SPX_WOTS_LEN) { + bufs[watching] = &empty[0]; + watching--; + } + + for (k = 0;; k++) { + while (k == steps[idxs[i + watching]]) { + bufs[watching] = &empty[0]; + if (watching == 0) { + done = 1; + break; + } + watching--; + } + if (done) { + break; + } + for (j = 0; j < watching + 1; j++) { + set_hash_addr(addrs + j * 8, k + start[idxs[i + j]]); + } + + thashx8(bufs[0], bufs[1], bufs[2], bufs[3], + bufs[4], bufs[5], bufs[6], bufs[7], + bufs[0], bufs[1], bufs[2], bufs[3], + bufs[4], bufs[5], bufs[6], bufs[7], 1, ctx, addrs); + } + } +} + +/** + * base_w algorithm as described in draft. + * Interprets an array of bytes as integers in base w. + * This only works when log_w is a divisor of 8. + */ +static void base_w(unsigned int *output, const int out_len, + const unsigned char *input) { + int in = 0; + int out = 0; + unsigned char total = 0; + int bits = 0; + int consumed; + + for (consumed = 0; consumed < out_len; consumed++) { + if (bits == 0) { + total = input[in]; + in++; + bits += 8; + } + bits -= SPX_WOTS_LOGW; + output[out] = (total >> bits) & (SPX_WOTS_W - 1); + out++; + } +} + +/* Computes the WOTS+ checksum over a message (in base_w). */ +static void wots_checksum(unsigned int *csum_base_w, + const unsigned int *msg_base_w) { + unsigned int csum = 0; + unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; + unsigned int i; + + /* Compute checksum. */ + for (i = 0; i < SPX_WOTS_LEN1; i++) { + csum += SPX_WOTS_W - 1 - msg_base_w[i]; + } + + /* Convert checksum to base_w. */ + /* Make sure expected empty zero bits are the least significant bits. */ + csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); + ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); + base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); +} + +/* Takes a message and derives the matching chain lengths. */ +void chain_lengths(unsigned int *lengths, const unsigned char *msg) { + base_w(lengths, SPX_WOTS_LEN1, msg); + wots_checksum(lengths + SPX_WOTS_LEN1, lengths); +} + +/** + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. + * + * Writes the computed public key to 'pk'. + */ +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]) { + unsigned int steps[SPX_WOTS_LEN]; + unsigned int start[SPX_WOTS_LEN]; + uint32_t i; + + chain_lengths(start, msg); + + for (i = 0; i < SPX_WOTS_LEN; i++) { + steps[i] = SPX_WOTS_W - 1 - start[i]; + } + + gen_chains(pk, sig, start, steps, ctx, addr); +} + +/* + * This generates 8 sequential WOTS public keys + * It also generates the WOTS signature if leaf_info indicates + * that we're signing with one of these WOTS keys + */ +void wots_gen_leafx8(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info) { + struct leaf_info_x8 *info = v_info; + uint32_t *leaf_addr = info->leaf_addr; + uint32_t *pk_addr = info->pk_addr; + unsigned int i, j, k; + unsigned char pk_buffer[ 8 * SPX_WOTS_BYTES ]; + unsigned wots_offset = SPX_WOTS_BYTES; + unsigned char *buffer; + uint32_t wots_k_mask; + unsigned wots_sign_index; + + if (((leaf_idx ^ info->wots_sign_leaf) & ~7U) == 0) { + /* We're traversing the leaf that's signing; generate the WOTS */ + /* signature */ + wots_k_mask = 0; + wots_sign_index = info->wots_sign_leaf & 7; /* Which of of the 8 */ + /* slots do the signatures come from */ + } else { + /* Nope, we're just generating pk's; turn off the signature logic */ + wots_k_mask = ~0U; + wots_sign_index = 0; + } + + for (j = 0; j < 8; j++) { + set_keypair_addr( leaf_addr + j * 8, leaf_idx + j ); + set_keypair_addr( pk_addr + j * 8, leaf_idx + j ); + } + + for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { + uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k */ + /* to the step if we're generating a signature, ~0 if we're not */ + + /* Start with the secret seed */ + for (j = 0; j < 8; j++) { + set_chain_addr(leaf_addr + j * 8, i); + set_hash_addr(leaf_addr + j * 8, 0); + set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTSPRF); + } + prf_addrx8(buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + buffer + 2 * wots_offset, + buffer + 3 * wots_offset, + buffer + 4 * wots_offset, + buffer + 5 * wots_offset, + buffer + 6 * wots_offset, + buffer + 7 * wots_offset, + ctx, leaf_addr); + + for (j = 0; j < 8; j++) { + set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTS); + } + + /* Iterate down the WOTS chain */ + for (k = 0;; k++) { + /* Check if one of the values we have needs to be saved as a */ + /* part of the WOTS signature */ + if (k == wots_k) { + memcpy( info->wots_sig + i * SPX_N, + buffer + wots_sign_index * wots_offset, SPX_N ); + } + + /* Check if we hit the top of the chain */ + if (k == SPX_WOTS_W - 1) { + break; + } + + /* Iterate one step on all 8 chains */ + for (j = 0; j < 8; j++) { + set_hash_addr(leaf_addr + j * 8, k); + } + thashx8(buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + buffer + 2 * wots_offset, + buffer + 3 * wots_offset, + buffer + 4 * wots_offset, + buffer + 5 * wots_offset, + buffer + 6 * wots_offset, + buffer + 7 * wots_offset, + buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + buffer + 2 * wots_offset, + buffer + 3 * wots_offset, + buffer + 4 * wots_offset, + buffer + 5 * wots_offset, + buffer + 6 * wots_offset, + buffer + 7 * wots_offset, 1, ctx, leaf_addr); + } + } + + /* Do the final thash to generate the public keys */ + thashx8(dest + 0 * SPX_N, + dest + 1 * SPX_N, + dest + 2 * SPX_N, + dest + 3 * SPX_N, + dest + 4 * SPX_N, + dest + 5 * SPX_N, + dest + 6 * SPX_N, + dest + 7 * SPX_N, + pk_buffer + 0 * wots_offset, + pk_buffer + 1 * wots_offset, + pk_buffer + 2 * wots_offset, + pk_buffer + 3 * wots_offset, + pk_buffer + 4 * wots_offset, + pk_buffer + 5 * wots_offset, + pk_buffer + 6 * wots_offset, + pk_buffer + 7 * wots_offset, SPX_WOTS_LEN, ctx, pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/wots.h b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/wots.h new file mode 100644 index 0000000000..4e7692eeef --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/wots.h @@ -0,0 +1,25 @@ +#ifndef SPX_WOTS_H +#define SPX_WOTS_H + +#include + +#include "context.h" +#include "params.h" + +/** + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. + * + * Writes the computed public key to 'pk'. + */ +#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]); + +/* + * Compute the chain lengths needed for a given message hash + */ +#define chain_lengths SPX_NAMESPACE(chain_lengths) +void chain_lengths(unsigned int *lengths, const unsigned char *msg); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/wotsx8.h b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/wotsx8.h new file mode 100644 index 0000000000..10866efb35 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/wotsx8.h @@ -0,0 +1,42 @@ +#ifndef WOTSX8_H_ +#define WOTSX8_H_ + +#include + +#include "context.h" +#include "params.h" + +/* + * This is here to provide an interface to the internal wots_gen_leafx8 + * routine. While this routine is not referenced in the package outside of + * wots.c, it is called from the stand-alone benchmark code to characterize + * the performance + */ +struct leaf_info_x8 { + unsigned char *wots_sig; + uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ + uint32_t *wots_steps; + uint32_t leaf_addr[8 * 8]; + uint32_t pk_addr[8 * 8]; +}; + +/* Macro to set the leaf_info to something 'benign', that is, it would */ +/* run with the same time as it does during the real signing process */ +/* Used only by the benchmark code */ +#define INITIALIZE_LEAF_INFO_X8(info, addr, step_buffer) { \ + (info).wots_sig = 0; \ + (info).wots_sign_leaf = ~0; \ + (info).wots_steps = step_buffer; \ + int i; \ + for (i=0; i<8; i++) { \ + memcpy( &(info).leaf_addr[8*i], addr, 32 ); \ + memcpy( &(info).pk_addr[8*i], addr, 32 ); \ + } \ + } + +#define wots_gen_leafx8 SPX_NAMESPACE(wots_gen_leafx8) +void wots_gen_leafx8(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info); + +#endif /* WOTSX8_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/LICENSE b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/LICENSE new file mode 100644 index 0000000000..670154e353 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/LICENSE @@ -0,0 +1,116 @@ +CC0 1.0 Universal + +Statement of Purpose + +The laws of most jurisdictions throughout the world automatically confer +exclusive Copyright and Related Rights (defined below) upon the creator and +subsequent owner(s) (each and all, an "owner") of an original work of +authorship and/or a database (each, a "Work"). + +Certain owners wish to permanently relinquish those rights to a Work for the +purpose of contributing to a commons of creative, cultural and scientific +works ("Commons") that the public can reliably and without fear of later +claims of infringement build upon, modify, incorporate in other works, reuse +and redistribute as freely as possible in any form whatsoever and for any +purposes, including without limitation commercial purposes. These owners may +contribute to the Commons to promote the ideal of a free culture and the +further production of creative, cultural and scientific works, or to gain +reputation or greater distribution for their Work in part through the use and +efforts of others. + +For these and/or other purposes and motivations, and without any expectation +of additional consideration or compensation, the person associating CC0 with a +Work (the "Affirmer"), to the extent that he or she is an owner of Copyright +and Related Rights in the Work, voluntarily elects to apply CC0 to the Work +and publicly distribute the Work under its terms, with knowledge of his or her +Copyright and Related Rights in the Work and the meaning and intended legal +effect of CC0 on those rights. + +1. Copyright and Related Rights. A Work made available under CC0 may be +protected by copyright and related or neighboring rights ("Copyright and +Related Rights"). Copyright and Related Rights include, but are not limited +to, the following: + + i. the right to reproduce, adapt, distribute, perform, display, communicate, + and translate a Work; + + ii. moral rights retained by the original author(s) and/or performer(s); + + iii. publicity and privacy rights pertaining to a person's image or likeness + depicted in a Work; + + iv. rights protecting against unfair competition in regards to a Work, + subject to the limitations in paragraph 4(a), below; + + v. rights protecting the extraction, dissemination, use and reuse of data in + a Work; + + vi. database rights (such as those arising under Directive 96/9/EC of the + European Parliament and of the Council of 11 March 1996 on the legal + protection of databases, and under any national implementation thereof, + including any amended or successor version of such directive); and + + vii. other similar, equivalent or corresponding rights throughout the world + based on applicable law or treaty, and any national implementations thereof. + +2. Waiver. To the greatest extent permitted by, but not in contravention of, +applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and +unconditionally waives, abandons, and surrenders all of Affirmer's Copyright +and Related Rights and associated claims and causes of action, whether now +known or unknown (including existing as well as future claims and causes of +action), in the Work (i) in all territories worldwide, (ii) for the maximum +duration provided by applicable law or treaty (including future time +extensions), (iii) in any current or future medium and for any number of +copies, and (iv) for any purpose whatsoever, including without limitation +commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes +the Waiver for the benefit of each member of the public at large and to the +detriment of Affirmer's heirs and successors, fully intending that such Waiver +shall not be subject to revocation, rescission, cancellation, termination, or +any other legal or equitable action to disrupt the quiet enjoyment of the Work +by the public as contemplated by Affirmer's express Statement of Purpose. + +3. Public License Fallback. Should any part of the Waiver for any reason be +judged legally invalid or ineffective under applicable law, then the Waiver +shall be preserved to the maximum extent permitted taking into account +Affirmer's express Statement of Purpose. In addition, to the extent the Waiver +is so judged Affirmer hereby grants to each affected person a royalty-free, +non transferable, non sublicensable, non exclusive, irrevocable and +unconditional license to exercise Affirmer's Copyright and Related Rights in +the Work (i) in all territories worldwide, (ii) for the maximum duration +provided by applicable law or treaty (including future time extensions), (iii) +in any current or future medium and for any number of copies, and (iv) for any +purpose whatsoever, including without limitation commercial, advertising or +promotional purposes (the "License"). The License shall be deemed effective as +of the date CC0 was applied by Affirmer to the Work. Should any part of the +License for any reason be judged legally invalid or ineffective under +applicable law, such partial invalidity or ineffectiveness shall not +invalidate the remainder of the License, and in such case Affirmer hereby +affirms that he or she will not (i) exercise any of his or her remaining +Copyright and Related Rights in the Work or (ii) assert any associated claims +and causes of action with respect to the Work, in either case contrary to +Affirmer's express Statement of Purpose. + +4. Limitations and Disclaimers. + + a. No trademark or patent rights held by Affirmer are waived, abandoned, + surrendered, licensed or otherwise affected by this document. + + b. Affirmer offers the Work as-is and makes no representations or warranties + of any kind concerning the Work, express, implied, statutory or otherwise, + including without limitation warranties of title, merchantability, fitness + for a particular purpose, non infringement, or the absence of latent or + other defects, accuracy, or the present or absence of errors, whether or not + discoverable, all to the greatest extent permissible under applicable law. + + c. Affirmer disclaims responsibility for clearing rights of other persons + that may apply to the Work or any use thereof, including without limitation + any person's Copyright and Related Rights in the Work. Further, Affirmer + disclaims responsibility for obtaining any necessary consents, permissions + or other rights required for any use of the Work. + + d. Affirmer understands and acknowledges that Creative Commons is not a + party to this document and has no duty or obligation with respect to this + CC0 or use of the Work. + +For more information, please see + diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/address.c b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/address.c new file mode 100644 index 0000000000..d49d9f3b6b --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/address.c @@ -0,0 +1,95 @@ +#include +#include + +#include "address.h" +#include "params.h" +#include "utils.h" + +/* + * Specify which level of Merkle tree (the "layer") we're working on + */ +void set_layer_addr(uint32_t addr[8], uint32_t layer) { + ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; +} + +/* + * Specify which Merkle tree within the level (the "tree address") we're working on + */ +void set_tree_addr(uint32_t addr[8], uint64_t tree) { + ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); +} + +/* + * Specify the reason we'll use this address structure for, that is, what + * hash will we compute with it. This is used so that unrelated types of + * hashes don't accidentally get the same address structure. The type will be + * one of the SPX_ADDR_TYPE constants + */ +void set_type(uint32_t addr[8], uint32_t type) { + ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; +} + +/* + * Copy the layer and tree fields of the address structure. This is used + * when we're doing multiple types of hashes within the same Merkle tree + */ +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); +} + +/* These functions are used for OTS addresses. */ + +/* + * Specify which Merkle leaf we're working on; that is, which OTS keypair + * we're talking about. + */ +void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { + /* We have > 256 OTS at the bottom of the Merkle tree; to specify */ + /* which one, we'd need to express it in two bytes */ + ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR2] = (unsigned char)(keypair >> 8); + ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; +} + +/* + * Copy the layer, tree and keypair fields of the address structure. This is + * used when we're doing multiple things within the same OTS keypair + */ +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); + ((unsigned char *)out)[SPX_OFFSET_KP_ADDR2] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR2]; + ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; +} + +/* + * Specify which Merkle chain within the OTS we're working with + * (the chain address) + */ +void set_chain_addr(uint32_t addr[8], uint32_t chain) { + ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; +} + +/* + * Specify where in the Merkle chain we are +* (the hash address) + */ +void set_hash_addr(uint32_t addr[8], uint32_t hash) { + ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; +} + +/* These functions are used for all hash tree addresses (including FORS). */ + +/* + * Specify the height of the node in the Merkle/FORS tree we are in + * (the tree height) + */ +void set_tree_height(uint32_t addr[8], uint32_t tree_height) { + ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; +} + +/* + * Specify the distance from the left edge of the node in the Merkle/FORS tree + * (the tree index) + */ +void set_tree_index(uint32_t addr[8], uint32_t tree_index) { + u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/address.h b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/address.h new file mode 100644 index 0000000000..24a84eb40c --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/address.h @@ -0,0 +1,52 @@ +#ifndef SPX_ADDRESS_H +#define SPX_ADDRESS_H + +#include + +#include "params.h" + +/* The hash types that are passed to set_type */ +#define SPX_ADDR_TYPE_WOTS 0 +#define SPX_ADDR_TYPE_WOTSPK 1 +#define SPX_ADDR_TYPE_HASHTREE 2 +#define SPX_ADDR_TYPE_FORSTREE 3 +#define SPX_ADDR_TYPE_FORSPK 4 +#define SPX_ADDR_TYPE_WOTSPRF 5 +#define SPX_ADDR_TYPE_FORSPRF 6 + +#define set_layer_addr SPX_NAMESPACE(set_layer_addr) +void set_layer_addr(uint32_t addr[8], uint32_t layer); + +#define set_tree_addr SPX_NAMESPACE(set_tree_addr) +void set_tree_addr(uint32_t addr[8], uint64_t tree); + +#define set_type SPX_NAMESPACE(set_type) +void set_type(uint32_t addr[8], uint32_t type); + +/* Copies the layer and tree part of one address into the other */ +#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); + +/* These functions are used for WOTS and FORS addresses. */ + +#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) +void set_keypair_addr(uint32_t addr[8], uint32_t keypair); + +#define set_chain_addr SPX_NAMESPACE(set_chain_addr) +void set_chain_addr(uint32_t addr[8], uint32_t chain); + +#define set_hash_addr SPX_NAMESPACE(set_hash_addr) +void set_hash_addr(uint32_t addr[8], uint32_t hash); + +#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); + +/* These functions are used for all hash tree addresses (including FORS). */ + +#define set_tree_height SPX_NAMESPACE(set_tree_height) +void set_tree_height(uint32_t addr[8], uint32_t tree_height); + +#define set_tree_index SPX_NAMESPACE(set_tree_index) +void set_tree_index(uint32_t addr[8], uint32_t tree_index); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/api.h b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/api.h new file mode 100644 index 0000000000..e1bfec0651 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/api.h @@ -0,0 +1,77 @@ +#ifndef PQCLEAN_SPHINCSSHA2192SROBUST_CLEAN_API_H +#define PQCLEAN_SPHINCSSHA2192SROBUST_CLEAN_API_H + +#include +#include + +#define PQCLEAN_SPHINCSSHA2192SROBUST_CLEAN_CRYPTO_ALGNAME "SPHINCS+-sha2-192s-robust" + +#define PQCLEAN_SPHINCSSHA2192SROBUST_CLEAN_CRYPTO_SECRETKEYBYTES 96 +#define PQCLEAN_SPHINCSSHA2192SROBUST_CLEAN_CRYPTO_PUBLICKEYBYTES 48 +#define PQCLEAN_SPHINCSSHA2192SROBUST_CLEAN_CRYPTO_BYTES 16224 + +#define PQCLEAN_SPHINCSSHA2192SROBUST_CLEAN_CRYPTO_SEEDBYTES 72 + +/* + * Returns the length of a secret key, in bytes + */ +size_t PQCLEAN_SPHINCSSHA2192SROBUST_CLEAN_crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +size_t PQCLEAN_SPHINCSSHA2192SROBUST_CLEAN_crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +size_t PQCLEAN_SPHINCSSHA2192SROBUST_CLEAN_crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +size_t PQCLEAN_SPHINCSSHA2192SROBUST_CLEAN_crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +int PQCLEAN_SPHINCSSHA2192SROBUST_CLEAN_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +int PQCLEAN_SPHINCSSHA2192SROBUST_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +int PQCLEAN_SPHINCSSHA2192SROBUST_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +int PQCLEAN_SPHINCSSHA2192SROBUST_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, + const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +int PQCLEAN_SPHINCSSHA2192SROBUST_CLEAN_crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +int PQCLEAN_SPHINCSSHA2192SROBUST_CLEAN_crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/context.h b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/context.h new file mode 100644 index 0000000000..97e2e2469e --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/context.h @@ -0,0 +1,28 @@ +#ifndef SPX_CONTEXT_H +#define SPX_CONTEXT_H + +#include +#include + +#include "params.h" +#include "sha2.h" + +typedef struct { + uint8_t pub_seed[SPX_N]; + uint8_t sk_seed[SPX_N]; + + // sha256 state that absorbed pub_seed + sha256ctx state_seeded; + + // sha512 state that absorbed pub_seed + sha512ctx state_seeded_512; + +} spx_ctx; + +#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) +void initialize_hash_function(spx_ctx *ctx); + +#define free_hash_function SPX_NAMESPACE(free_hash_function) +void free_hash_function(spx_ctx *ctx); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/context_sha2.c b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/context_sha2.c new file mode 100644 index 0000000000..9ca9f4e7ac --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/context_sha2.c @@ -0,0 +1,36 @@ +#include "context.h" + +/** + * Absorb the constant pub_seed using one round of the compression function + * This initializes state_seeded and state_seeded_512, which can then be + * reused in thash + **/ +static void seed_state(spx_ctx *ctx) { + uint8_t block[SPX_SHA512_BLOCK_BYTES]; + size_t i; + + for (i = 0; i < SPX_N; ++i) { + block[i] = ctx->pub_seed[i]; + } + for (i = SPX_N; i < SPX_SHA512_BLOCK_BYTES; ++i) { + block[i] = 0; + } + /* block has been properly initialized for both SHA-256 and SHA-512 */ + + sha256_inc_init(&ctx->state_seeded); + sha256_inc_blocks(&ctx->state_seeded, block, 1); + sha512_inc_init(&ctx->state_seeded_512); + sha512_inc_blocks(&ctx->state_seeded_512, block, 1); +} + + +/* We initialize the state for the hash functions */ +void initialize_hash_function(spx_ctx *ctx) { + seed_state(ctx); +} + +/* Free the incremental hashing context for heap-based SHA2 APIs */ +void free_hash_function(spx_ctx *ctx) { + sha256_inc_ctx_release(&ctx->state_seeded); + sha512_inc_ctx_release(&ctx->state_seeded_512); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/fors.c b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/fors.c new file mode 100644 index 0000000000..96ca72e986 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/fors.c @@ -0,0 +1,156 @@ +#include +#include +#include + +#include "fors.h" + +#include "address.h" +#include "hash.h" +#include "thash.h" +#include "utils.h" +#include "utilsx1.h" + +static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + prf_addr(sk, ctx, fors_leaf_addr); +} + +static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, + const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + thash(leaf, sk, 1, ctx, fors_leaf_addr); +} + +struct fors_gen_leaf_info { + uint32_t leaf_addrx[8]; +}; + +static void fors_gen_leafx1(unsigned char *leaf, + const spx_ctx *ctx, + uint32_t addr_idx, void *info) { + struct fors_gen_leaf_info *fors_info = info; + uint32_t *fors_leaf_addr = fors_info->leaf_addrx; + + /* Only set the parts that the caller doesn't set */ + set_tree_index(fors_leaf_addr, addr_idx); + set_type(fors_leaf_addr, SPX_ADDR_TYPE_FORSPRF); + fors_gen_sk(leaf, ctx, fors_leaf_addr); + + set_type(fors_leaf_addr, SPX_ADDR_TYPE_FORSTREE); + fors_sk_to_leaf(leaf, leaf, + ctx, fors_leaf_addr); +} + +/** + * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + * Assumes indices has space for SPX_FORS_TREES integers. + */ +static void message_to_indices(uint32_t *indices, const unsigned char *m) { + unsigned int i, j; + unsigned int offset = 0; + + for (i = 0; i < SPX_FORS_TREES; i++) { + indices[i] = 0; + for (j = 0; j < SPX_FORS_HEIGHT; j++) { + indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); + offset++; + } + } +} + +/** + * Signs a message m, deriving the secret key from sk_seed and the FTS address. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + uint32_t fors_tree_addr[8] = {0}; + struct fors_gen_leaf_info fors_info = {0}; + uint32_t *fors_leaf_addr = fors_info.leaf_addrx; + uint32_t fors_pk_addr[8] = {0}; + uint32_t idx_offset; + unsigned int i; + + copy_keypair_addr(fors_tree_addr, fors_addr); + copy_keypair_addr(fors_leaf_addr, fors_addr); + + copy_keypair_addr(fors_pk_addr, fors_addr); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); + + message_to_indices(indices, m); + + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); + + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); + + /* Include the secret key part that produces the selected leaf node. */ + fors_gen_sk(sig, ctx, fors_tree_addr); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + sig += SPX_N; + + /* Compute the authentication path for this leaf node. */ + treehashx1(roots + i * SPX_N, sig, ctx, + indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx1, + fors_tree_addr, &fors_info); + + sig += SPX_N * SPX_FORS_HEIGHT; + } + + /* Hash horizontally across all tree roots to derive the public key. */ + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); +} + +/** + * Derives the FORS public key from a signature. + * This can be used for verification by comparing to a known public key, or to + * subsequently verify a signature on the derived public key. The latter is the + * typical use-case when used as an FTS below an OTS in a hypertree. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + unsigned char leaf[SPX_N]; + uint32_t fors_tree_addr[8] = {0}; + uint32_t fors_pk_addr[8] = {0}; + uint32_t idx_offset; + unsigned int i; + + copy_keypair_addr(fors_tree_addr, fors_addr); + copy_keypair_addr(fors_pk_addr, fors_addr); + + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); + + message_to_indices(indices, m); + + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); + + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + + /* Derive the leaf from the included secret key part. */ + fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); + sig += SPX_N; + + /* Derive the corresponding root node of this tree. */ + compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, + sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); + sig += SPX_N * SPX_FORS_HEIGHT; + } + + /* Hash horizontally across all tree roots to derive the public key. */ + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/fors.h b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/fors.h new file mode 100644 index 0000000000..509140a178 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/fors.h @@ -0,0 +1,32 @@ +#ifndef SPX_FORS_H +#define SPX_FORS_H + +#include + +#include "context.h" +#include "params.h" + +/** + * Signs a message m, deriving the secret key from sk_seed and the FTS address. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +#define fors_sign SPX_NAMESPACE(fors_sign) +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); + +/** + * Derives the FORS public key from a signature. + * This can be used for verification by comparing to a known public key, or to + * subsequently verify a signature on the derived public key. The latter is the + * typical use-case when used as an FTS below an OTS in a hypertree. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/hash.h b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/hash.h new file mode 100644 index 0000000000..ffe815f45d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/hash.h @@ -0,0 +1,37 @@ +#ifndef SPX_HASH_H +#define SPX_HASH_H + +#include +#include + +#include "context.h" +#include "params.h" + +#define prf_addr SPX_NAMESPACE(prf_addr) +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]); + +#define gen_message_random SPX_NAMESPACE(gen_message_random) +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); + +#define hash_message SPX_NAMESPACE(hash_message) +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); + + +# define SPX_SHA256_ADDR_BYTES 22 + +# define mgf1_256 SPX_NAMESPACE(mgf1_256) +void mgf1_256(unsigned char *out, unsigned long outlen, + const unsigned char *in, unsigned long inlen); + +# define mgf1_512 SPX_NAMESPACE(mgf1_512) +void mgf1_512(unsigned char *out, unsigned long outlen, + const unsigned char *in, unsigned long inlen); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/hash_sha2.c b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/hash_sha2.c new file mode 100644 index 0000000000..3d0085c8c1 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/hash_sha2.c @@ -0,0 +1,219 @@ +#include +#include + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "sha2.h" +#include "utils.h" + + + +#define SPX_SHAX_OUTPUT_BYTES SPX_SHA512_OUTPUT_BYTES +#define SPX_SHAX_BLOCK_BYTES SPX_SHA512_BLOCK_BYTES +#define shaX_inc_init sha512_inc_init +#define shaX_inc_blocks sha512_inc_blocks +#define shaX_inc_finalize sha512_inc_finalize +#define shaX sha512 +#define mgf1_X mgf1_512 +#define shaXstate sha512ctx + +/** + * mgf1 function based on the SHA-256 hash function + * Note that inlen should be sufficiently small that it still allows for + * an array to be allocated on the stack. Typically 'in' is merely a seed. + * Outputs outlen number of bytes + */ +void mgf1_256(unsigned char *out, unsigned long outlen, + const unsigned char *in, unsigned long inlen) { + PQCLEAN_VLA(uint8_t, inbuf, inlen + 4); + unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES]; + uint32_t i; + + memcpy(inbuf, in, inlen); + + /* While we can fit in at least another full block of SHA256 output.. */ + for (i = 0; (i + 1)*SPX_SHA256_OUTPUT_BYTES <= outlen; i++) { + u32_to_bytes(inbuf + inlen, i); + sha256(out, inbuf, inlen + 4); + out += SPX_SHA256_OUTPUT_BYTES; + } + /* Until we cannot anymore, and we fill the remainder. */ + if (outlen > i * SPX_SHA256_OUTPUT_BYTES) { + u32_to_bytes(inbuf + inlen, i); + sha256(outbuf, inbuf, inlen + 4); + memcpy(out, outbuf, outlen - i * SPX_SHA256_OUTPUT_BYTES); + } +} + +/* + * mgf1 function based on the SHA-512 hash function + */ +void mgf1_512(unsigned char *out, unsigned long outlen, + const unsigned char *in, unsigned long inlen) { + PQCLEAN_VLA(uint8_t, inbuf, inlen + 4); + unsigned char outbuf[SPX_SHA512_OUTPUT_BYTES]; + uint32_t i; + + memcpy(inbuf, in, inlen); + + /* While we can fit in at least another full block of SHA512 output.. */ + for (i = 0; (i + 1)*SPX_SHA512_OUTPUT_BYTES <= outlen; i++) { + u32_to_bytes(inbuf + inlen, i); + sha512(out, inbuf, inlen + 4); + out += SPX_SHA512_OUTPUT_BYTES; + } + /* Until we cannot anymore, and we fill the remainder. */ + if (outlen > i * SPX_SHA512_OUTPUT_BYTES) { + u32_to_bytes(inbuf + inlen, i); + sha512(outbuf, inbuf, inlen + 4); + memcpy(out, outbuf, outlen - i * SPX_SHA512_OUTPUT_BYTES); + } +} + +/* + * Computes PRF(pk_seed, sk_seed, addr). + */ +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]) { + sha256ctx sha2_state; + unsigned char buf[SPX_SHA256_ADDR_BYTES + SPX_N]; + unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES]; + + /* Retrieve precomputed state containing pub_seed */ + sha256_inc_ctx_clone(&sha2_state, &ctx->state_seeded); + + /* Remainder: ADDR^c ‖ SK.seed */ + memcpy(buf, addr, SPX_SHA256_ADDR_BYTES); + memcpy(buf + SPX_SHA256_ADDR_BYTES, ctx->sk_seed, SPX_N); + + sha256_inc_finalize(outbuf, &sha2_state, buf, SPX_SHA256_ADDR_BYTES + SPX_N); + + memcpy(out, outbuf, SPX_N); +} + +/** + * Computes the message-dependent randomness R, using a secret seed as a key + * for HMAC, and an optional randomization value prefixed to the message. + * This requires m to have at least SPX_SHAX_BLOCK_BYTES + SPX_N space + * available in front of the pointer, i.e. before the message to use for the + * prefix. This is necessary to prevent having to move the message around (and + * allocate memory for it). + */ +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { + (void)ctx; + + unsigned char buf[SPX_SHAX_BLOCK_BYTES + SPX_SHAX_OUTPUT_BYTES]; + shaXstate state; + int i; + + + /* This implements HMAC-SHA */ + for (i = 0; i < SPX_N; i++) { + buf[i] = 0x36 ^ sk_prf[i]; + } + memset(buf + SPX_N, 0x36, SPX_SHAX_BLOCK_BYTES - SPX_N); + + shaX_inc_init(&state); + shaX_inc_blocks(&state, buf, 1); + + memcpy(buf, optrand, SPX_N); + + /* If optrand + message cannot fill up an entire block */ + if (SPX_N + mlen < SPX_SHAX_BLOCK_BYTES) { + memcpy(buf + SPX_N, m, mlen); + shaX_inc_finalize(buf + SPX_SHAX_BLOCK_BYTES, &state, + buf, mlen + SPX_N); + } + /* Otherwise first fill a block, so that finalize only uses the message */ + else { + memcpy(buf + SPX_N, m, SPX_SHAX_BLOCK_BYTES - SPX_N); + shaX_inc_blocks(&state, buf, 1); + + m += SPX_SHAX_BLOCK_BYTES - SPX_N; + mlen -= SPX_SHAX_BLOCK_BYTES - SPX_N; + shaX_inc_finalize(buf + SPX_SHAX_BLOCK_BYTES, &state, m, mlen); + } + + for (i = 0; i < SPX_N; i++) { + buf[i] = 0x5c ^ sk_prf[i]; + } + memset(buf + SPX_N, 0x5c, SPX_SHAX_BLOCK_BYTES - SPX_N); + + shaX(buf, buf, SPX_SHAX_BLOCK_BYTES + SPX_SHAX_OUTPUT_BYTES); + memcpy(R, buf, SPX_N); +} + +/** + * Computes the message hash using R, the public key, and the message. + * Outputs the message digest and the index of the leaf. The index is split in + * the tree index and the leaf index, for convenient copying to an address. + */ +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { + (void)ctx; +#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) +#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) +#define SPX_LEAF_BITS SPX_TREE_HEIGHT +#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) +#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) + + unsigned char seed[2 * SPX_N + SPX_SHAX_OUTPUT_BYTES]; + + /* Round to nearest multiple of SPX_SHAX_BLOCK_BYTES */ +#define SPX_INBLOCKS (((SPX_N + SPX_PK_BYTES + SPX_SHAX_BLOCK_BYTES - 1) & \ + -SPX_SHAX_BLOCK_BYTES) / SPX_SHAX_BLOCK_BYTES) + unsigned char inbuf[SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES]; + + unsigned char buf[SPX_DGST_BYTES]; + unsigned char *bufp = buf; + shaXstate state; + + shaX_inc_init(&state); + + // seed: SHA-X(R ‖ PK.seed ‖ PK.root ‖ M) + memcpy(inbuf, R, SPX_N); + memcpy(inbuf + SPX_N, pk, SPX_PK_BYTES); + + /* If R + pk + message cannot fill up an entire block */ + if (SPX_N + SPX_PK_BYTES + mlen < SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES) { + memcpy(inbuf + SPX_N + SPX_PK_BYTES, m, mlen); + shaX_inc_finalize(seed + 2 * SPX_N, &state, inbuf, SPX_N + SPX_PK_BYTES + mlen); + } + /* Otherwise first fill a block, so that finalize only uses the message */ + else { + memcpy(inbuf + SPX_N + SPX_PK_BYTES, m, + SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES - SPX_N - SPX_PK_BYTES); + shaX_inc_blocks(&state, inbuf, SPX_INBLOCKS); + + m += SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES - SPX_N - SPX_PK_BYTES; + mlen -= SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES - SPX_N - SPX_PK_BYTES; + shaX_inc_finalize(seed + 2 * SPX_N, &state, m, (size_t)mlen); + } + + // H_msg: MGF1-SHA-X(R ‖ PK.seed ‖ seed) + memcpy(seed, R, SPX_N); + memcpy(seed + SPX_N, pk, SPX_N); + + /* By doing this in two steps, we prevent hashing the message twice; + otherwise each iteration in MGF1 would hash the message again. */ + mgf1_X(bufp, SPX_DGST_BYTES, seed, 2 * SPX_N + SPX_SHAX_OUTPUT_BYTES); + + memcpy(digest, bufp, SPX_FORS_MSG_BYTES); + bufp += SPX_FORS_MSG_BYTES; + + + *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); + *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); + bufp += SPX_TREE_BYTES; + + *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); + *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); +} + + diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/merkle.c b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/merkle.c new file mode 100644 index 0000000000..0c1479fd93 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/merkle.c @@ -0,0 +1,59 @@ +#include +#include + +#include "address.h" +#include "merkle.h" +#include "params.h" +#include "utils.h" +#include "utilsx1.h" +#include "wots.h" +#include "wotsx1.h" + +/* + * This generates a Merkle signature (WOTS signature followed by the Merkle + * authentication path). This is in this file because most of the complexity + * is involved with the WOTS signature; the Merkle authentication path logic + * is mostly hidden in treehashx4 + */ +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf) { + unsigned char *auth_path = sig + SPX_WOTS_BYTES; + struct leaf_info_x1 info = { 0 }; + unsigned steps[ SPX_WOTS_LEN ]; + + info.wots_sig = sig; + chain_lengths(steps, root); + info.wots_steps = steps; + + set_type(&tree_addr[0], SPX_ADDR_TYPE_HASHTREE); + set_type(&info.pk_addr[0], SPX_ADDR_TYPE_WOTSPK); + copy_subtree_addr(&info.leaf_addr[0], wots_addr); + copy_subtree_addr(&info.pk_addr[0], wots_addr); + + info.wots_sign_leaf = idx_leaf; + + treehashx1(root, auth_path, ctx, + idx_leaf, 0, + SPX_TREE_HEIGHT, + wots_gen_leafx1, + tree_addr, &info); +} + +/* Compute root node of the top-most subtree. */ +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { + /* We do not need the auth path in key generation, but it simplifies the + code to have just one treehash routine that computes both root and path + in one function. */ + unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; + uint32_t top_tree_addr[8] = {0}; + uint32_t wots_addr[8] = {0}; + + set_layer_addr(top_tree_addr, SPX_D - 1); + set_layer_addr(wots_addr, SPX_D - 1); + + merkle_sign(auth_path, root, ctx, + wots_addr, top_tree_addr, + (uint32_t)~0 /* ~0 means "don't bother generating an auth path */ ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/merkle.h b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/merkle.h new file mode 100644 index 0000000000..769cf2e970 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/merkle.h @@ -0,0 +1,21 @@ +#ifndef MERKLE_H_ +#define MERKLE_H_ + +#include + +#include "context.h" +#include "params.h" + +/* Generate a Merkle signature (WOTS signature followed by the Merkle */ +/* authentication path) */ +#define merkle_sign SPX_NAMESPACE(merkle_sign) +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf); + +/* Compute the root node of the top-most subtree. */ +#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); + +#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/nistapi.h b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/nistapi.h new file mode 100644 index 0000000000..3cb71afad4 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/nistapi.h @@ -0,0 +1,87 @@ +#ifndef SPX_API_H +#define SPX_API_H + +#include +#include + +#include "params.h" + +#define CRYPTO_ALGNAME "SPHINCS+" + +#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES +#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES +#define CRYPTO_BYTES SPX_BYTES +#define CRYPTO_SEEDBYTES (3*SPX_N) + +/* + * Returns the length of a secret key, in bytes + */ +#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) +size_t crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) +size_t crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) +size_t crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) +size_t crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +#define crypto_sign SPX_NAMESPACE(crypto_sign) +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/params.h b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/params.h new file mode 100644 index 0000000000..398458b430 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/params.h @@ -0,0 +1,61 @@ +#ifndef SPX_PARAMS_H +#define SPX_PARAMS_H + +#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSSHA2192SROBUST_CLEAN_##s + +/* Hash output length in bytes. */ +#define SPX_N 24 +/* Height of the hypertree. */ +#define SPX_FULL_HEIGHT 63 +/* Number of subtree layer. */ +#define SPX_D 7 +/* FORS tree dimensions. */ +#define SPX_FORS_HEIGHT 14 +#define SPX_FORS_TREES 17 +/* Winternitz parameter, */ +#define SPX_WOTS_W 16 + +/* The hash function is defined by linking a different hash.c file, as opposed + to setting a #define constant. */ + +/* This is a SHA2-based parameter set, hence whether we use SHA-256 + * exclusively or we use both SHA-256 and SHA-512 is controlled by + * the following #define */ +#define SPX_SHA512 1 /* Use SHA-512 for H and T_l, l >= 2 */ + +/* For clarity */ +#define SPX_ADDR_BYTES 32 + +/* WOTS parameters. */ +#define SPX_WOTS_LOGW 4 + +#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) + +/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ +#define SPX_WOTS_LEN2 3 + +#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) +#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) +#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES + +/* Subtree size. */ +#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) + +//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT +// #error SPX_D should always divide SPX_FULL_HEIGHT +//#endif + +/* FORS parameters. */ +#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) +#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) +#define SPX_FORS_PK_BYTES SPX_N + +/* Resulting SPX sizes. */ +#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ + SPX_FULL_HEIGHT * SPX_N) +#define SPX_PK_BYTES (2 * SPX_N) +#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) + +#include "sha2_offsets.h" + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/sha2_offsets.h b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/sha2_offsets.h new file mode 100644 index 0000000000..6e3584f7a4 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/sha2_offsets.h @@ -0,0 +1,27 @@ +#ifndef SHA2_OFFSETS_H_ +#define SHA2_OFFSETS_H_ + +#define SPX_SHA256_BLOCK_BYTES 64 +#define SPX_SHA256_OUTPUT_BYTES 32 + +#define SPX_SHA512_BLOCK_BYTES 128 +#define SPX_SHA512_OUTPUT_BYTES 64 + +/* + * Offsets of various fields in the address structure when we use SHA2 as + * the Sphincs+ hash function + */ + +#define SPX_OFFSET_LAYER 0 /* The byte used to specify the Merkle tree layer */ +#define SPX_OFFSET_TREE 1 /* The start of the 8 byte field used to specify the tree */ +#define SPX_OFFSET_TYPE 9 /* The byte used to specify the hash type (reason) */ +#define SPX_OFFSET_KP_ADDR2 12 /* The high byte used to specify the key pair (which one-time signature) */ +#define SPX_OFFSET_KP_ADDR1 13 /* The low byte used to specify the key pair */ +#define SPX_OFFSET_CHAIN_ADDR 17 /* The byte used to specify the chain address (which Winternitz chain) */ +#define SPX_OFFSET_HASH_ADDR 21 /* The byte used to specify the hash address (where in the Winternitz chain) */ +#define SPX_OFFSET_TREE_HGT 17 /* The byte used to specify the height of this node in the FORS or Merkle tree */ +#define SPX_OFFSET_TREE_INDEX 18 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ + +#define SPX_SHA2 1 + +#endif /* SHA2_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/sign.c b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/sign.c new file mode 100644 index 0000000000..9d0c7d1b22 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/sign.c @@ -0,0 +1,286 @@ +#include +#include +#include + +#include "address.h" +#include "context.h" +#include "fors.h" +#include "hash.h" +#include "merkle.h" +#include "nistapi.h" +#include "params.h" +#include "randombytes.h" +#include "thash.h" +#include "utils.h" +#include "wots.h" + +/* + * Returns the length of a secret key, in bytes + */ +size_t crypto_sign_secretkeybytes(void) { + return CRYPTO_SECRETKEYBYTES; +} + +/* + * Returns the length of a public key, in bytes + */ +size_t crypto_sign_publickeybytes(void) { + return CRYPTO_PUBLICKEYBYTES; +} + +/* + * Returns the length of a signature, in bytes + */ +size_t crypto_sign_bytes(void) { + return CRYPTO_BYTES; +} + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +size_t crypto_sign_seedbytes(void) { + return CRYPTO_SEEDBYTES; +} + +/* + * Generates an SPX key pair given a seed of length + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [PUB_SEED || root] + */ +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed) { + spx_ctx ctx; + + /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ + memcpy(sk, seed, CRYPTO_SEEDBYTES); + + memcpy(pk, sk + 2 * SPX_N, SPX_N); + + memcpy(ctx.pub_seed, pk, SPX_N); + memcpy(ctx.sk_seed, sk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + /* Compute root node of the top-most subtree. */ + merkle_gen_root(sk + 3 * SPX_N, &ctx); + + // cleanup + free_hash_function(&ctx); + + memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); + + return 0; +} + +/* + * Generates an SPX key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [PUB_SEED || root] + */ +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { + uint8_t seed[CRYPTO_SEEDBYTES]; + randombytes(seed, CRYPTO_SEEDBYTES); + crypto_sign_seed_keypair(pk, sk, seed); + + return 0; +} + +/** + * Returns an array containing a detached signature. + */ +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk) { + spx_ctx ctx; + + const uint8_t *sk_prf = sk + SPX_N; + const uint8_t *pk = sk + 2 * SPX_N; + + uint8_t optrand[SPX_N]; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t root[SPX_N]; + uint32_t i; + uint64_t tree; + uint32_t idx_leaf; + uint32_t wots_addr[8] = {0}; + uint32_t tree_addr[8] = {0}; + + memcpy(ctx.sk_seed, sk, SPX_N); + memcpy(ctx.pub_seed, pk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + + /* Optionally, signing can be made non-deterministic using optrand. + This can help counter side-channel attacks that would benefit from + getting a large number of traces when the signer uses the same nodes. */ + randombytes(optrand, SPX_N); + /* Compute the digest randomization value. */ + gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); + + /* Derive the message digest and leaf index from R, PK and M. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; + + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); + + /* Sign the message hash using FORS. */ + fors_sign(sig, root, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); + sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; + + /* Update the indices for the next layer. */ + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; + } + + free_hash_function(&ctx); + + *siglen = SPX_BYTES; + + return 0; +} + +/** + * Verifies a detached signature and message under a given public key. + */ +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk) { + spx_ctx ctx; + const uint8_t *pub_root = pk + SPX_N; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t wots_pk[SPX_WOTS_BYTES]; + uint8_t root[SPX_N]; + uint8_t leaf[SPX_N]; + unsigned int i; + uint64_t tree; + uint32_t idx_leaf; + uint32_t wots_addr[8] = {0}; + uint32_t tree_addr[8] = {0}; + uint32_t wots_pk_addr[8] = {0}; + + if (siglen != SPX_BYTES) { + return -1; + } + + memcpy(ctx.pub_seed, pk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); + + /* Derive the message digest and leaf index from R || PK || M. */ + /* The additional SPX_N is a result of the hash domain separator. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; + + /* Layer correctly defaults to 0, so no need to set_layer_addr */ + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); + + fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + /* For each subtree.. */ + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + copy_keypair_addr(wots_pk_addr, wots_addr); + + /* The WOTS public key is only correct if the signature was correct. */ + /* Initially, root is the FORS pk, but on subsequent iterations it is + the root of the subtree below the currently processed subtree. */ + wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); + sig += SPX_WOTS_BYTES; + + /* Compute the leaf node using the WOTS public key. */ + thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); + + /* Compute the root node of this subtree. */ + compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, + &ctx, tree_addr); + sig += SPX_TREE_HEIGHT * SPX_N; + + /* Update the indices for the next layer. */ + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; + } + + // cleanup + free_hash_function(&ctx); + + /* Check if the root node equals the root node in the public key. */ + if (memcmp(root, pub_root, SPX_N) != 0) { + return -1; + } + + return 0; +} + + +/** + * Returns an array containing the signature followed by the message. + */ +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk) { + size_t siglen; + + crypto_sign_signature(sm, &siglen, m, mlen, sk); + + memmove(sm + SPX_BYTES, m, mlen); + *smlen = siglen + mlen; + + return 0; +} + +/** + * Verifies a given signature-message pair under a given public key. + */ +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk) { + /* The API caller does not necessarily know what size a signature should be + but SPHINCS+ signatures are always exactly SPX_BYTES. */ + if (smlen < SPX_BYTES) { + memset(m, 0, smlen); + *mlen = 0; + return -1; + } + + *mlen = smlen - SPX_BYTES; + + if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { + memset(m, 0, smlen); + *mlen = 0; + return -1; + } + + /* If verification was successful, move the message to the right place. */ + memmove(m, sm + SPX_BYTES, *mlen); + + return 0; +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/thash.h b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/thash.h new file mode 100644 index 0000000000..8687ccfb4d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/thash.h @@ -0,0 +1,13 @@ +#ifndef SPX_THASH_H +#define SPX_THASH_H + +#include "context.h" +#include "params.h" + +#include + +#define thash SPX_NAMESPACE(thash) +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/thash_sha2_robust.c b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/thash_sha2_robust.c new file mode 100644 index 0000000000..3ab891175f --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/thash_sha2_robust.c @@ -0,0 +1,68 @@ +#include +#include + +#include "address.h" +#include "context.h" +#include "hash.h" +#include "params.h" +#include "sha2.h" +#include "thash.h" +#include "utils.h" + +static void thash_512(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]); + +/** + * Takes an array of inblocks concatenated arrays of SPX_N bytes. + */ +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]) { + if (inblocks > 1) { + thash_512(out, in, inblocks, ctx, addr); + return; + } + unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES]; + PQCLEAN_VLA(uint8_t, bitmask, inblocks * SPX_N); + PQCLEAN_VLA(uint8_t, buf, SPX_N + SPX_SHA256_OUTPUT_BYTES + inblocks * SPX_N); + sha256ctx sha2_state; + unsigned int i; + + memcpy(buf, ctx->pub_seed, SPX_N); + memcpy(buf + SPX_N, addr, SPX_SHA256_ADDR_BYTES); + mgf1_256(bitmask, inblocks * SPX_N, buf, SPX_N + SPX_SHA256_ADDR_BYTES); + + /* Retrieve precomputed state containing pub_seed */ + sha256_inc_ctx_clone(&sha2_state, &ctx->state_seeded); + + for (i = 0; i < inblocks * SPX_N; i++) { + buf[SPX_N + SPX_SHA256_ADDR_BYTES + i] = in[i] ^ bitmask[i]; + } + + sha256_inc_finalize(outbuf, &sha2_state, buf + SPX_N, + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N); + memcpy(out, outbuf, SPX_N); +} + +static void thash_512(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]) { + unsigned char outbuf[SPX_SHA512_OUTPUT_BYTES]; + PQCLEAN_VLA(uint8_t, bitmask, inblocks * SPX_N); + PQCLEAN_VLA(uint8_t, buf, SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N); + sha512ctx sha2_state; + unsigned int i; + + memcpy(buf, ctx->pub_seed, SPX_N); + memcpy(buf + SPX_N, addr, SPX_SHA256_ADDR_BYTES); + mgf1_512(bitmask, inblocks * SPX_N, buf, SPX_N + SPX_SHA256_ADDR_BYTES); + + /* Retrieve precomputed state containing pub_seed */ + sha512_inc_ctx_clone(&sha2_state, &ctx->state_seeded_512); + + for (i = 0; i < inblocks * SPX_N; i++) { + buf[SPX_N + SPX_SHA256_ADDR_BYTES + i] = in[i] ^ bitmask[i]; + } + + sha512_inc_finalize(outbuf, &sha2_state, buf + SPX_N, + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N); + memcpy(out, outbuf, SPX_N); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/utils.c b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/utils.c new file mode 100644 index 0000000000..177b541fb9 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/utils.c @@ -0,0 +1,148 @@ +#include + +#include "utils.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "thash.h" + +/** + * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. + */ +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in) { + int i; + + /* Iterate over out in decreasing order, for big-endianness. */ + for (i = (signed int)outlen - 1; i >= 0; i--) { + out[i] = in & 0xff; + in = in >> 8; + } +} + +void u32_to_bytes(unsigned char *out, uint32_t in) { + out[0] = (unsigned char)(in >> 24); + out[1] = (unsigned char)(in >> 16); + out[2] = (unsigned char)(in >> 8); + out[3] = (unsigned char)in; +} + +/** + * Converts the inlen bytes in 'in' from big-endian byte order to an integer. + */ +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { + unsigned long long retval = 0; + unsigned int i; + + for (i = 0; i < inlen; i++) { + retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); + } + return retval; +} + +/** + * Computes a root node given a leaf and an auth path. + * Expects address to be complete other than the tree_height and tree_index. + */ +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]) { + uint32_t i; + unsigned char buffer[2 * SPX_N]; + + /* If leaf_idx is odd (last bit = 1), current path element is a right child + and auth_path has to go left. Otherwise it is the other way around. */ + if (leaf_idx & 1) { + memcpy(buffer + SPX_N, leaf, SPX_N); + memcpy(buffer, auth_path, SPX_N); + } else { + memcpy(buffer, leaf, SPX_N); + memcpy(buffer + SPX_N, auth_path, SPX_N); + } + auth_path += SPX_N; + + for (i = 0; i < tree_height - 1; i++) { + leaf_idx >>= 1; + idx_offset >>= 1; + /* Set the address of the node we're creating. */ + set_tree_height(addr, i + 1); + set_tree_index(addr, leaf_idx + idx_offset); + + /* Pick the right or left neighbor, depending on parity of the node. */ + if (leaf_idx & 1) { + thash(buffer + SPX_N, buffer, 2, ctx, addr); + memcpy(buffer, auth_path, SPX_N); + } else { + thash(buffer, buffer, 2, ctx, addr); + memcpy(buffer + SPX_N, auth_path, SPX_N); + } + auth_path += SPX_N; + } + + /* The last iteration is exceptional; we do not copy an auth_path node. */ + leaf_idx >>= 1; + idx_offset >>= 1; + set_tree_height(addr, tree_height); + set_tree_index(addr, leaf_idx + idx_offset); + thash(root, buffer, 2, ctx, addr); +} + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx * /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]) { + PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); + PQCLEAN_VLA(unsigned int, heights, tree_height + 1); + unsigned int offset = 0; + uint32_t idx; + uint32_t tree_idx; + + for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { + /* Add the next leaf node to the stack. */ + gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); + offset++; + heights[offset - 1] = 0; + + /* If this is a node we need for the auth path.. */ + if ((leaf_idx ^ 0x1) == idx) { + memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); + } + + /* While the top-most nodes are of equal height.. */ + while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { + /* Compute index of the new node, in the next layer. */ + tree_idx = (idx >> (heights[offset - 1] + 1)); + + /* Set the address of the node we're creating. */ + set_tree_height(tree_addr, heights[offset - 1] + 1); + set_tree_index(tree_addr, + tree_idx + (idx_offset >> (heights[offset - 1] + 1))); + /* Hash the top-most nodes from the stack together. */ + thash(stack + (offset - 2)*SPX_N, + stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); + offset--; + /* Note that the top-most node is now one layer higher. */ + heights[offset - 1]++; + + /* If this is a node we need for the auth path.. */ + if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { + memcpy(auth_path + heights[offset - 1]*SPX_N, + stack + (offset - 1)*SPX_N, SPX_N); + } + } + } + memcpy(root, stack, SPX_N); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/utils.h b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/utils.h new file mode 100644 index 0000000000..64f5d5a53a --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/utils.h @@ -0,0 +1,58 @@ +#ifndef SPX_UTILS_H +#define SPX_UTILS_H + +#include + +#include "compat.h" +#include "context.h" +#include "params.h" + + +/* To support MSVC use alloca() instead of VLAs. See #20. */ + + +/** + * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. + */ +#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in); +#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) +void u32_to_bytes(unsigned char *out, uint32_t in); + +/** + * Converts the inlen bytes in 'in' from big-endian byte order to an integer. + */ +#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); + +/** + * Computes a root node given a leaf and an auth path. + * Expects address to be complete other than the tree_height and tree_index. + */ +#define compute_root SPX_NAMESPACE(compute_root) +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]); + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +#define treehash SPX_NAMESPACE(treehash) +void treehash(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx *ctx /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]); + + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/utilsx1.c b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/utilsx1.c new file mode 100644 index 0000000000..fccb69b35d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/utilsx1.c @@ -0,0 +1,100 @@ +#include + +#include "utilsx1.h" + +#include "address.h" +#include "params.h" +#include "thash.h" +#include "utils.h" + +/* + * Generate the entire Merkle tree, computing the authentication path for + * leaf_idx, and the resulting root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) + * + * This expects tree_addr to be initialized to the addr structures for the + * Merkle tree nodes + * + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + * + * This works by using the standard Merkle tree building algorithm, + */ +void treehashx1(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, + uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* Where to write the leaves */, + const spx_ctx * /* ctx */, + uint32_t idx, void *info), + uint32_t tree_addr[8], + void *info) { + /* This is where we keep the intermediate nodes */ + PQCLEAN_VLA(uint8_t, stack, tree_height * SPX_N); + + uint32_t idx; + uint32_t max_idx = (uint32_t)((1 << tree_height) - 1); + for (idx = 0;; idx++) { + unsigned char current[2 * SPX_N]; /* Current logical node is at */ + /* index[SPX_N]. We do this to minimize the number of copies */ + /* needed during a thash */ + gen_leaf( ¤t[SPX_N], ctx, idx + idx_offset, + info ); + + /* Now combine the freshly generated right node with previously */ + /* generated left ones */ + uint32_t internal_idx_offset = idx_offset; + uint32_t internal_idx = idx; + uint32_t internal_leaf = leaf_idx; + uint32_t h; /* The height we are in the Merkle tree */ + for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { + + /* Check if we hit the top of the tree */ + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[SPX_N], SPX_N ); + return; + } + + /* + * Check if the node we have is a part of the + * authentication path; if it is, write it out + */ + if ((internal_idx ^ internal_leaf) == 0x01) { + memcpy( &auth_path[ h * SPX_N ], + ¤t[SPX_N], + SPX_N ); + } + + /* + * Check if we're at a left child; if so, stop going up the stack + * Exception: if we've reached the end of the tree, keep on going + * (so we combine the last 4 nodes into the one root node in two + * more iterations) + */ + if ((internal_idx & 1) == 0 && idx < max_idx) { + break; + } + + /* Ok, we're at a right node */ + /* Now combine the left and right logical nodes together */ + + /* Set the address of the node we're creating. */ + internal_idx_offset >>= 1; + set_tree_height(tree_addr, h + 1); + set_tree_index(tree_addr, internal_idx / 2 + internal_idx_offset ); + + unsigned char *left = &stack[h * SPX_N]; + memcpy( ¤t[0], left, SPX_N ); + thash( ¤t[1 * SPX_N], + ¤t[0 * SPX_N], + 2, ctx, tree_addr); + } + + /* We've hit a left child; save the current for when we get the */ + /* corresponding right right */ + memcpy( &stack[h * SPX_N], ¤t[SPX_N], SPX_N); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/utilsx1.h b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/utilsx1.h new file mode 100644 index 0000000000..e911d17d53 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/utilsx1.h @@ -0,0 +1,27 @@ +#ifndef SPX_UTILSX4_H +#define SPX_UTILSX4_H + +#include + +#include "context.h" +#include "params.h" + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +#define treehashx1 SPX_NAMESPACE(treehashx1) +void treehashx1(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* Where to write the leaf */, + const spx_ctx * /* ctx */, + uint32_t addr_idx, void *info), + uint32_t tree_addrx4[8], void *info); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/wots.c b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/wots.c new file mode 100644 index 0000000000..249717aaa8 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/wots.c @@ -0,0 +1,108 @@ +#include +#include + +#include "wots.h" +#include "wotsx1.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "thash.h" +#include "utils.h" +#include "utilsx1.h" + +// TODO clarify address expectations, and make them more uniform. +// TODO i.e. do we expect types to be set already? +// TODO and do we expect modifications or copies? + +/** + * Computes the chaining function. + * out and in have to be n-byte arrays. + * + * Interprets in as start-th value of the chain. + * addr has to contain the address of the chain. + */ +static void gen_chain(unsigned char *out, const unsigned char *in, + unsigned int start, unsigned int steps, + const spx_ctx *ctx, uint32_t addr[8]) { + uint32_t i; + + /* Initialize out with the value at position 'start'. */ + memcpy(out, in, SPX_N); + + /* Iterate 'steps' calls to the hash function. */ + for (i = start; i < (start + steps) && i < SPX_WOTS_W; i++) { + set_hash_addr(addr, i); + thash(out, out, 1, ctx, addr); + } +} + +/** + * base_w algorithm as described in draft. + * Interprets an array of bytes as integers in base w. + * This only works when log_w is a divisor of 8. + */ +static void base_w(unsigned int *output, const int out_len, + const unsigned char *input) { + int in = 0; + int out = 0; + unsigned char total = 0; + int bits = 0; + int consumed; + + for (consumed = 0; consumed < out_len; consumed++) { + if (bits == 0) { + total = input[in]; + in++; + bits += 8; + } + bits -= SPX_WOTS_LOGW; + output[out] = (total >> bits) & (SPX_WOTS_W - 1); + out++; + } +} + +/* Computes the WOTS+ checksum over a message (in base_w). */ +static void wots_checksum(unsigned int *csum_base_w, + const unsigned int *msg_base_w) { + unsigned int csum = 0; + unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; + unsigned int i; + + /* Compute checksum. */ + for (i = 0; i < SPX_WOTS_LEN1; i++) { + csum += SPX_WOTS_W - 1 - msg_base_w[i]; + } + + /* Convert checksum to base_w. */ + /* Make sure expected empty zero bits are the least significant bits. */ + csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); + ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); + base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); +} + +/* Takes a message and derives the matching chain lengths. */ +void chain_lengths(unsigned int *lengths, const unsigned char *msg) { + base_w(lengths, SPX_WOTS_LEN1, msg); + wots_checksum(lengths + SPX_WOTS_LEN1, lengths); +} + +/** + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. + * + * Writes the computed public key to 'pk'. + */ +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]) { + unsigned int lengths[SPX_WOTS_LEN]; + uint32_t i; + + chain_lengths(lengths, msg); + + for (i = 0; i < SPX_WOTS_LEN; i++) { + set_chain_addr(addr, i); + gen_chain(pk + i * SPX_N, sig + i * SPX_N, + lengths[i], SPX_WOTS_W - 1 - lengths[i], ctx, addr); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/wots.h b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/wots.h new file mode 100644 index 0000000000..4e7692eeef --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/wots.h @@ -0,0 +1,25 @@ +#ifndef SPX_WOTS_H +#define SPX_WOTS_H + +#include + +#include "context.h" +#include "params.h" + +/** + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. + * + * Writes the computed public key to 'pk'. + */ +#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]); + +/* + * Compute the chain lengths needed for a given message hash + */ +#define chain_lengths SPX_NAMESPACE(chain_lengths) +void chain_lengths(unsigned int *lengths, const unsigned char *msg); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/wotsx1.c b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/wotsx1.c new file mode 100644 index 0000000000..3adec78dfb --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/wotsx1.c @@ -0,0 +1,76 @@ +#include +#include + +#include "wots.h" +#include "wotsx1.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "thash.h" +#include "utils.h" + +/* + * This generates a WOTS public key + * It also generates the WOTS signature if leaf_info indicates + * that we're signing with this WOTS key + */ +void wots_gen_leafx1(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info) { + struct leaf_info_x1 *info = v_info; + uint32_t *leaf_addr = info->leaf_addr; + uint32_t *pk_addr = info->pk_addr; + unsigned int i, k; + unsigned char pk_buffer[ SPX_WOTS_BYTES ]; + unsigned char *buffer; + uint32_t wots_k_mask; + + if (leaf_idx == info->wots_sign_leaf) { + /* We're traversing the leaf that's signing; generate the WOTS */ + /* signature */ + wots_k_mask = 0; + } else { + /* Nope, we're just generating pk's; turn off the signature logic */ + wots_k_mask = (uint32_t)~0; + } + + set_keypair_addr( leaf_addr, leaf_idx ); + set_keypair_addr( pk_addr, leaf_idx ); + + for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { + uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k to */ + /* the step if we're generating a signature, ~0 if we're not */ + + /* Start with the secret seed */ + set_chain_addr(leaf_addr, i); + set_hash_addr(leaf_addr, 0); + set_type(leaf_addr, SPX_ADDR_TYPE_WOTSPRF); + + prf_addr(buffer, ctx, leaf_addr); + + set_type(leaf_addr, SPX_ADDR_TYPE_WOTS); + + /* Iterate down the WOTS chain */ + for (k = 0;; k++) { + /* Check if this is the value that needs to be saved as a */ + /* part of the WOTS signature */ + if (k == wots_k) { + memcpy( info->wots_sig + i * SPX_N, buffer, SPX_N ); + } + + /* Check if we hit the top of the chain */ + if (k == SPX_WOTS_W - 1) { + break; + } + + /* Iterate one step on the chain */ + set_hash_addr(leaf_addr, k); + + thash(buffer, buffer, 1, ctx, leaf_addr); + } + } + + /* Do the final thash to generate the public keys */ + thash(dest, pk_buffer, SPX_WOTS_LEN, ctx, pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/wotsx1.h b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/wotsx1.h new file mode 100644 index 0000000000..e617929f96 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/wotsx1.h @@ -0,0 +1,39 @@ +#ifndef WOTSX1_H_ +#define WOTSX1_H_ + +#include + +#include "context.h" +#include "params.h" + +/* + * This is here to provide an interface to the internal wots_gen_leafx1 + * routine. While this routine is not referenced in the package outside of + * wots.c, it is called from the stand-alone benchmark code to characterize + * the performance + */ +struct leaf_info_x1 { + unsigned char *wots_sig; + uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ + uint32_t *wots_steps; + uint32_t leaf_addr[8]; + uint32_t pk_addr[8]; +}; + +/* Macro to set the leaf_info to something 'benign', that is, it would */ +/* run with the same time as it does during the real signing process */ +/* Used only by the benchmark code */ +#define INITIALIZE_LEAF_INFO_X1(info, addr, step_buffer) { \ + (info).wots_sig = 0; \ + (info).wots_sign_leaf = ~0; \ + (info).wots_steps = step_buffer; \ + memcpy( &(info).leaf_addr[0], (addr), 32 ); \ + memcpy( &(info).pk_addr[0], (addr), 32 ); \ + } + +#define wots_gen_leafx1 SPX_NAMESPACE(wots_gen_leafx1) +void wots_gen_leafx1(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info); + +#endif /* WOTSX1_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/LICENSE b/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/LICENSE new file mode 100644 index 0000000000..670154e353 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/LICENSE @@ -0,0 +1,116 @@ +CC0 1.0 Universal + +Statement of Purpose + +The laws of most jurisdictions throughout the world automatically confer +exclusive Copyright and Related Rights (defined below) upon the creator and +subsequent owner(s) (each and all, an "owner") of an original work of +authorship and/or a database (each, a "Work"). + +Certain owners wish to permanently relinquish those rights to a Work for the +purpose of contributing to a commons of creative, cultural and scientific +works ("Commons") that the public can reliably and without fear of later +claims of infringement build upon, modify, incorporate in other works, reuse +and redistribute as freely as possible in any form whatsoever and for any +purposes, including without limitation commercial purposes. These owners may +contribute to the Commons to promote the ideal of a free culture and the +further production of creative, cultural and scientific works, or to gain +reputation or greater distribution for their Work in part through the use and +efforts of others. + +For these and/or other purposes and motivations, and without any expectation +of additional consideration or compensation, the person associating CC0 with a +Work (the "Affirmer"), to the extent that he or she is an owner of Copyright +and Related Rights in the Work, voluntarily elects to apply CC0 to the Work +and publicly distribute the Work under its terms, with knowledge of his or her +Copyright and Related Rights in the Work and the meaning and intended legal +effect of CC0 on those rights. + +1. Copyright and Related Rights. A Work made available under CC0 may be +protected by copyright and related or neighboring rights ("Copyright and +Related Rights"). Copyright and Related Rights include, but are not limited +to, the following: + + i. the right to reproduce, adapt, distribute, perform, display, communicate, + and translate a Work; + + ii. moral rights retained by the original author(s) and/or performer(s); + + iii. publicity and privacy rights pertaining to a person's image or likeness + depicted in a Work; + + iv. rights protecting against unfair competition in regards to a Work, + subject to the limitations in paragraph 4(a), below; + + v. rights protecting the extraction, dissemination, use and reuse of data in + a Work; + + vi. database rights (such as those arising under Directive 96/9/EC of the + European Parliament and of the Council of 11 March 1996 on the legal + protection of databases, and under any national implementation thereof, + including any amended or successor version of such directive); and + + vii. other similar, equivalent or corresponding rights throughout the world + based on applicable law or treaty, and any national implementations thereof. + +2. Waiver. To the greatest extent permitted by, but not in contravention of, +applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and +unconditionally waives, abandons, and surrenders all of Affirmer's Copyright +and Related Rights and associated claims and causes of action, whether now +known or unknown (including existing as well as future claims and causes of +action), in the Work (i) in all territories worldwide, (ii) for the maximum +duration provided by applicable law or treaty (including future time +extensions), (iii) in any current or future medium and for any number of +copies, and (iv) for any purpose whatsoever, including without limitation +commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes +the Waiver for the benefit of each member of the public at large and to the +detriment of Affirmer's heirs and successors, fully intending that such Waiver +shall not be subject to revocation, rescission, cancellation, termination, or +any other legal or equitable action to disrupt the quiet enjoyment of the Work +by the public as contemplated by Affirmer's express Statement of Purpose. + +3. Public License Fallback. Should any part of the Waiver for any reason be +judged legally invalid or ineffective under applicable law, then the Waiver +shall be preserved to the maximum extent permitted taking into account +Affirmer's express Statement of Purpose. In addition, to the extent the Waiver +is so judged Affirmer hereby grants to each affected person a royalty-free, +non transferable, non sublicensable, non exclusive, irrevocable and +unconditional license to exercise Affirmer's Copyright and Related Rights in +the Work (i) in all territories worldwide, (ii) for the maximum duration +provided by applicable law or treaty (including future time extensions), (iii) +in any current or future medium and for any number of copies, and (iv) for any +purpose whatsoever, including without limitation commercial, advertising or +promotional purposes (the "License"). The License shall be deemed effective as +of the date CC0 was applied by Affirmer to the Work. Should any part of the +License for any reason be judged legally invalid or ineffective under +applicable law, such partial invalidity or ineffectiveness shall not +invalidate the remainder of the License, and in such case Affirmer hereby +affirms that he or she will not (i) exercise any of his or her remaining +Copyright and Related Rights in the Work or (ii) assert any associated claims +and causes of action with respect to the Work, in either case contrary to +Affirmer's express Statement of Purpose. + +4. Limitations and Disclaimers. + + a. No trademark or patent rights held by Affirmer are waived, abandoned, + surrendered, licensed or otherwise affected by this document. + + b. Affirmer offers the Work as-is and makes no representations or warranties + of any kind concerning the Work, express, implied, statutory or otherwise, + including without limitation warranties of title, merchantability, fitness + for a particular purpose, non infringement, or the absence of latent or + other defects, accuracy, or the present or absence of errors, whether or not + discoverable, all to the greatest extent permissible under applicable law. + + c. Affirmer disclaims responsibility for clearing rights of other persons + that may apply to the Work or any use thereof, including without limitation + any person's Copyright and Related Rights in the Work. Further, Affirmer + disclaims responsibility for obtaining any necessary consents, permissions + or other rights required for any use of the Work. + + d. Affirmer understands and acknowledges that Creative Commons is not a + party to this document and has no duty or obligation with respect to this + CC0 or use of the Work. + +For more information, please see + diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/address.c b/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/address.c new file mode 100644 index 0000000000..d49d9f3b6b --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/address.c @@ -0,0 +1,95 @@ +#include +#include + +#include "address.h" +#include "params.h" +#include "utils.h" + +/* + * Specify which level of Merkle tree (the "layer") we're working on + */ +void set_layer_addr(uint32_t addr[8], uint32_t layer) { + ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; +} + +/* + * Specify which Merkle tree within the level (the "tree address") we're working on + */ +void set_tree_addr(uint32_t addr[8], uint64_t tree) { + ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); +} + +/* + * Specify the reason we'll use this address structure for, that is, what + * hash will we compute with it. This is used so that unrelated types of + * hashes don't accidentally get the same address structure. The type will be + * one of the SPX_ADDR_TYPE constants + */ +void set_type(uint32_t addr[8], uint32_t type) { + ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; +} + +/* + * Copy the layer and tree fields of the address structure. This is used + * when we're doing multiple types of hashes within the same Merkle tree + */ +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); +} + +/* These functions are used for OTS addresses. */ + +/* + * Specify which Merkle leaf we're working on; that is, which OTS keypair + * we're talking about. + */ +void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { + /* We have > 256 OTS at the bottom of the Merkle tree; to specify */ + /* which one, we'd need to express it in two bytes */ + ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR2] = (unsigned char)(keypair >> 8); + ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; +} + +/* + * Copy the layer, tree and keypair fields of the address structure. This is + * used when we're doing multiple things within the same OTS keypair + */ +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); + ((unsigned char *)out)[SPX_OFFSET_KP_ADDR2] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR2]; + ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; +} + +/* + * Specify which Merkle chain within the OTS we're working with + * (the chain address) + */ +void set_chain_addr(uint32_t addr[8], uint32_t chain) { + ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; +} + +/* + * Specify where in the Merkle chain we are +* (the hash address) + */ +void set_hash_addr(uint32_t addr[8], uint32_t hash) { + ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; +} + +/* These functions are used for all hash tree addresses (including FORS). */ + +/* + * Specify the height of the node in the Merkle/FORS tree we are in + * (the tree height) + */ +void set_tree_height(uint32_t addr[8], uint32_t tree_height) { + ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; +} + +/* + * Specify the distance from the left edge of the node in the Merkle/FORS tree + * (the tree index) + */ +void set_tree_index(uint32_t addr[8], uint32_t tree_index) { + u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/address.h b/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/address.h new file mode 100644 index 0000000000..24a84eb40c --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/address.h @@ -0,0 +1,52 @@ +#ifndef SPX_ADDRESS_H +#define SPX_ADDRESS_H + +#include + +#include "params.h" + +/* The hash types that are passed to set_type */ +#define SPX_ADDR_TYPE_WOTS 0 +#define SPX_ADDR_TYPE_WOTSPK 1 +#define SPX_ADDR_TYPE_HASHTREE 2 +#define SPX_ADDR_TYPE_FORSTREE 3 +#define SPX_ADDR_TYPE_FORSPK 4 +#define SPX_ADDR_TYPE_WOTSPRF 5 +#define SPX_ADDR_TYPE_FORSPRF 6 + +#define set_layer_addr SPX_NAMESPACE(set_layer_addr) +void set_layer_addr(uint32_t addr[8], uint32_t layer); + +#define set_tree_addr SPX_NAMESPACE(set_tree_addr) +void set_tree_addr(uint32_t addr[8], uint64_t tree); + +#define set_type SPX_NAMESPACE(set_type) +void set_type(uint32_t addr[8], uint32_t type); + +/* Copies the layer and tree part of one address into the other */ +#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); + +/* These functions are used for WOTS and FORS addresses. */ + +#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) +void set_keypair_addr(uint32_t addr[8], uint32_t keypair); + +#define set_chain_addr SPX_NAMESPACE(set_chain_addr) +void set_chain_addr(uint32_t addr[8], uint32_t chain); + +#define set_hash_addr SPX_NAMESPACE(set_hash_addr) +void set_hash_addr(uint32_t addr[8], uint32_t hash); + +#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); + +/* These functions are used for all hash tree addresses (including FORS). */ + +#define set_tree_height SPX_NAMESPACE(set_tree_height) +void set_tree_height(uint32_t addr[8], uint32_t tree_height); + +#define set_tree_index SPX_NAMESPACE(set_tree_index) +void set_tree_index(uint32_t addr[8], uint32_t tree_index); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/api.h b/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/api.h new file mode 100644 index 0000000000..29d1f7f610 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/api.h @@ -0,0 +1,77 @@ +#ifndef PQCLEAN_SPHINCSSHA2192SSIMPLE_AVX2_API_H +#define PQCLEAN_SPHINCSSHA2192SSIMPLE_AVX2_API_H + +#include +#include + +#define PQCLEAN_SPHINCSSHA2192SSIMPLE_AVX2_CRYPTO_ALGNAME "SPHINCS+-sha2-192s-simple" + +#define PQCLEAN_SPHINCSSHA2192SSIMPLE_AVX2_CRYPTO_SECRETKEYBYTES 96 +#define PQCLEAN_SPHINCSSHA2192SSIMPLE_AVX2_CRYPTO_PUBLICKEYBYTES 48 +#define PQCLEAN_SPHINCSSHA2192SSIMPLE_AVX2_CRYPTO_BYTES 16224 + +#define PQCLEAN_SPHINCSSHA2192SSIMPLE_AVX2_CRYPTO_SEEDBYTES 72 + +/* + * Returns the length of a secret key, in bytes + */ +size_t PQCLEAN_SPHINCSSHA2192SSIMPLE_AVX2_crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +size_t PQCLEAN_SPHINCSSHA2192SSIMPLE_AVX2_crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +size_t PQCLEAN_SPHINCSSHA2192SSIMPLE_AVX2_crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +size_t PQCLEAN_SPHINCSSHA2192SSIMPLE_AVX2_crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +int PQCLEAN_SPHINCSSHA2192SSIMPLE_AVX2_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +int PQCLEAN_SPHINCSSHA2192SSIMPLE_AVX2_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +int PQCLEAN_SPHINCSSHA2192SSIMPLE_AVX2_crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +int PQCLEAN_SPHINCSSHA2192SSIMPLE_AVX2_crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, + const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +int PQCLEAN_SPHINCSSHA2192SSIMPLE_AVX2_crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +int PQCLEAN_SPHINCSSHA2192SSIMPLE_AVX2_crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/context.h b/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/context.h new file mode 100644 index 0000000000..d3bf1c3aac --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/context.h @@ -0,0 +1,29 @@ +#ifndef SPX_CONTEXT_H +#define SPX_CONTEXT_H + +#include + +#include "params.h" +#include "sha2.h" +#include "sha256avx.h" +#include "sha512x4.h" + +// funky ordering due to optimal padding +typedef struct { + sha256x8ctx statex8_seeded; + sha512x4ctx statex4_seeded_512; + sha256ctx state_seeded; + sha512ctx state_seeded_512; + + uint8_t pub_seed[SPX_N]; + uint8_t sk_seed[SPX_N]; +} spx_ctx; + + +#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) +void initialize_hash_function(spx_ctx *ctx); + +#define free_hash_function SPX_NAMESPACE(free_hash_function) +void free_hash_function(spx_ctx *ctx); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/context_sha2.c b/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/context_sha2.c new file mode 100644 index 0000000000..83c1b6585d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/context_sha2.c @@ -0,0 +1,56 @@ +#include + +#include "context.h" + +/** + * Absorb the constant pub_seed using one round of the compression function + * This initializes state_seeded and state_seeded_512, which can then be + * reused in thash + **/ +static void seed_state(spx_ctx *ctx) { + uint8_t block[SPX_SHA512_BLOCK_BYTES]; + size_t i; + + for (i = 0; i < SPX_N; ++i) { + block[i] = ctx->pub_seed[i]; + } + for (i = SPX_N; i < SPX_SHA512_BLOCK_BYTES; ++i) { + block[i] = 0; + } + /* block has been properly initialized for both SHA-256 and SHA-512 */ + + sha256_inc_init(&ctx->state_seeded); + sha256_inc_blocks(&ctx->state_seeded, block, 1); + + // initialize x8 + sha256_init8x(&ctx->statex8_seeded); + sha256_transform8x(&ctx->statex8_seeded, + block, block, block, block, block, block, block, block); + + ctx->statex8_seeded.datalen = 0; + ctx->statex8_seeded.msglen = 512; + + sha512_inc_init(&ctx->state_seeded_512); + sha512_inc_blocks(&ctx->state_seeded_512, block, 1); + + // initialize x4 + sha512_init4x(&ctx->statex4_seeded_512); + sha512_transform4x(&ctx->statex4_seeded_512, block, block, block, block); + + ctx->statex4_seeded_512.datalen = 0; + ctx->statex4_seeded_512.msglen = 1024; + + +} + + +/* For SHA, we initialize the hash function at the start */ +void initialize_hash_function(spx_ctx *ctx) { + seed_state(ctx); +} + +/* Free the incremental hashing context for heap-based SHA2 APIs */ +void free_hash_function(spx_ctx *ctx) { + sha256_inc_ctx_release(&ctx->state_seeded); + sha512_inc_ctx_release(&ctx->state_seeded_512); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/fors.c b/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/fors.c new file mode 100644 index 0000000000..4cab8e7415 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/fors.c @@ -0,0 +1,226 @@ +#include +#include +#include + +#include "fors.h" + + +#include "address.h" +#include "hash.h" +#include "hashx8.h" +#include "thash.h" +#include "thashx8.h" +#include "utils.h" +#include "utilsx8.h" +static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + prf_addr(sk, ctx, fors_leaf_addr); +} + +static void fors_gen_skx8(unsigned char *sk0, + unsigned char *sk1, + unsigned char *sk2, + unsigned char *sk3, + unsigned char *sk4, + unsigned char *sk5, + unsigned char *sk6, + unsigned char *sk7, const spx_ctx *ctx, + uint32_t fors_leaf_addrx8[8 * 8]) { + prf_addrx8(sk0, sk1, sk2, sk3, sk4, sk5, sk6, sk7, + ctx, fors_leaf_addrx8); +} + +static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, + const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + thash(leaf, sk, 1, ctx, fors_leaf_addr); +} + +static void fors_sk_to_leafx8(unsigned char *leaf0, + unsigned char *leaf1, + unsigned char *leaf2, + unsigned char *leaf3, + unsigned char *leaf4, + unsigned char *leaf5, + unsigned char *leaf6, + unsigned char *leaf7, + const unsigned char *sk0, + const unsigned char *sk1, + const unsigned char *sk2, + const unsigned char *sk3, + const unsigned char *sk4, + const unsigned char *sk5, + const unsigned char *sk6, + const unsigned char *sk7, + const spx_ctx *ctx, + uint32_t fors_leaf_addrx8[8 * 8]) { + thashx8(leaf0, leaf1, leaf2, leaf3, leaf4, leaf5, leaf6, leaf7, + sk0, sk1, sk2, sk3, sk4, sk5, sk6, sk7, + 1, ctx, fors_leaf_addrx8); +} + +struct fors_gen_leaf_info { + uint32_t leaf_addrx[8 * 8]; +}; + +static void fors_gen_leafx8(unsigned char *leaf, + const spx_ctx *ctx, + uint32_t addr_idx, void *info) { + struct fors_gen_leaf_info *fors_info = info; + uint32_t *fors_leaf_addrx8 = fors_info->leaf_addrx; + unsigned int j; + + /* Only set the parts that the caller doesn't set */ + for (j = 0; j < 8; j++) { + set_tree_index(fors_leaf_addrx8 + j * 8, addr_idx + j); + set_type(fors_leaf_addrx8 + j * 8, SPX_ADDR_TYPE_FORSPRF); + } + + fors_gen_skx8(leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + leaf + 2 * SPX_N, + leaf + 3 * SPX_N, + leaf + 4 * SPX_N, + leaf + 5 * SPX_N, + leaf + 6 * SPX_N, + leaf + 7 * SPX_N, + ctx, fors_leaf_addrx8); + + for (j = 0; j < 8; j++) { + set_type(fors_leaf_addrx8 + j * 8, SPX_ADDR_TYPE_FORSTREE); + } + + fors_sk_to_leafx8(leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + leaf + 2 * SPX_N, + leaf + 3 * SPX_N, + leaf + 4 * SPX_N, + leaf + 5 * SPX_N, + leaf + 6 * SPX_N, + leaf + 7 * SPX_N, + leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + leaf + 2 * SPX_N, + leaf + 3 * SPX_N, + leaf + 4 * SPX_N, + leaf + 5 * SPX_N, + leaf + 6 * SPX_N, + leaf + 7 * SPX_N, + ctx, fors_leaf_addrx8); +} + +/** + * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + * Assumes indices has space for SPX_FORS_TREES integers. + */ +static void message_to_indices(uint32_t *indices, const unsigned char *m) { + unsigned int i, j; + unsigned int offset = 0; + + for (i = 0; i < SPX_FORS_TREES; i++) { + indices[i] = 0; + for (j = 0; j < SPX_FORS_HEIGHT; j++) { + indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); + offset++; + } + } +} + +/** + * Signs a message m, deriving the secret key from sk_seed and the FTS address. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + uint32_t fors_tree_addr[8 * 8] = {0}; + struct fors_gen_leaf_info fors_info = {0}; + uint32_t *fors_leaf_addr = fors_info.leaf_addrx; + uint32_t fors_pk_addr[8] = {0}; + uint32_t idx_offset; + unsigned int i; + + for (i = 0; i < 8; i++) { + copy_keypair_addr(fors_tree_addr + 8 * i, fors_addr); + set_type(fors_tree_addr + 8 * i, SPX_ADDR_TYPE_FORSTREE); + copy_keypair_addr(fors_leaf_addr + 8 * i, fors_addr); + } + copy_keypair_addr(fors_pk_addr, fors_addr); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); + + message_to_indices(indices, m); + + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); + + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + + /* Include the secret key part that produces the selected leaf node. */ + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); + fors_gen_sk(sig, ctx, fors_tree_addr); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + sig += SPX_N; + + /* Compute the authentication path for this leaf node. */ + treehashx8(roots + i * SPX_N, sig, ctx, + indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx8, + fors_tree_addr, &fors_info); + + sig += SPX_N * SPX_FORS_HEIGHT; + } + + /* Hash horizontally across all tree roots to derive the public key. */ + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); +} + +/** + * Derives the FORS public key from a signature. + * This can be used for verification by comparing to a known public key, or to + * subsequently verify a signature on the derived public key. The latter is the + * typical use-case when used as an FTS below an OTS in a hypertree. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + unsigned char leaf[SPX_N]; + uint32_t fors_tree_addr[8] = {0}; + uint32_t fors_pk_addr[8] = {0}; + uint32_t idx_offset; + unsigned int i; + + copy_keypair_addr(fors_tree_addr, fors_addr); + copy_keypair_addr(fors_pk_addr, fors_addr); + + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); + + message_to_indices(indices, m); + + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); + + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + + /* Derive the leaf from the included secret key part. */ + fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); + sig += SPX_N; + + /* Derive the corresponding root node of this tree. */ + compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, + sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); + sig += SPX_N * SPX_FORS_HEIGHT; + } + + /* Hash horizontally across all tree roots to derive the public key. */ + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/fors.h b/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/fors.h new file mode 100644 index 0000000000..509140a178 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/fors.h @@ -0,0 +1,32 @@ +#ifndef SPX_FORS_H +#define SPX_FORS_H + +#include + +#include "context.h" +#include "params.h" + +/** + * Signs a message m, deriving the secret key from sk_seed and the FTS address. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +#define fors_sign SPX_NAMESPACE(fors_sign) +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); + +/** + * Derives the FORS public key from a signature. + * This can be used for verification by comparing to a known public key, or to + * subsequently verify a signature on the derived public key. The latter is the + * typical use-case when used as an FTS below an OTS in a hypertree. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/hash.h b/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/hash.h new file mode 100644 index 0000000000..ffe815f45d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/hash.h @@ -0,0 +1,37 @@ +#ifndef SPX_HASH_H +#define SPX_HASH_H + +#include +#include + +#include "context.h" +#include "params.h" + +#define prf_addr SPX_NAMESPACE(prf_addr) +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]); + +#define gen_message_random SPX_NAMESPACE(gen_message_random) +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); + +#define hash_message SPX_NAMESPACE(hash_message) +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); + + +# define SPX_SHA256_ADDR_BYTES 22 + +# define mgf1_256 SPX_NAMESPACE(mgf1_256) +void mgf1_256(unsigned char *out, unsigned long outlen, + const unsigned char *in, unsigned long inlen); + +# define mgf1_512 SPX_NAMESPACE(mgf1_512) +void mgf1_512(unsigned char *out, unsigned long outlen, + const unsigned char *in, unsigned long inlen); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/hash_sha2.c b/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/hash_sha2.c new file mode 100644 index 0000000000..3d0085c8c1 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/hash_sha2.c @@ -0,0 +1,219 @@ +#include +#include + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "sha2.h" +#include "utils.h" + + + +#define SPX_SHAX_OUTPUT_BYTES SPX_SHA512_OUTPUT_BYTES +#define SPX_SHAX_BLOCK_BYTES SPX_SHA512_BLOCK_BYTES +#define shaX_inc_init sha512_inc_init +#define shaX_inc_blocks sha512_inc_blocks +#define shaX_inc_finalize sha512_inc_finalize +#define shaX sha512 +#define mgf1_X mgf1_512 +#define shaXstate sha512ctx + +/** + * mgf1 function based on the SHA-256 hash function + * Note that inlen should be sufficiently small that it still allows for + * an array to be allocated on the stack. Typically 'in' is merely a seed. + * Outputs outlen number of bytes + */ +void mgf1_256(unsigned char *out, unsigned long outlen, + const unsigned char *in, unsigned long inlen) { + PQCLEAN_VLA(uint8_t, inbuf, inlen + 4); + unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES]; + uint32_t i; + + memcpy(inbuf, in, inlen); + + /* While we can fit in at least another full block of SHA256 output.. */ + for (i = 0; (i + 1)*SPX_SHA256_OUTPUT_BYTES <= outlen; i++) { + u32_to_bytes(inbuf + inlen, i); + sha256(out, inbuf, inlen + 4); + out += SPX_SHA256_OUTPUT_BYTES; + } + /* Until we cannot anymore, and we fill the remainder. */ + if (outlen > i * SPX_SHA256_OUTPUT_BYTES) { + u32_to_bytes(inbuf + inlen, i); + sha256(outbuf, inbuf, inlen + 4); + memcpy(out, outbuf, outlen - i * SPX_SHA256_OUTPUT_BYTES); + } +} + +/* + * mgf1 function based on the SHA-512 hash function + */ +void mgf1_512(unsigned char *out, unsigned long outlen, + const unsigned char *in, unsigned long inlen) { + PQCLEAN_VLA(uint8_t, inbuf, inlen + 4); + unsigned char outbuf[SPX_SHA512_OUTPUT_BYTES]; + uint32_t i; + + memcpy(inbuf, in, inlen); + + /* While we can fit in at least another full block of SHA512 output.. */ + for (i = 0; (i + 1)*SPX_SHA512_OUTPUT_BYTES <= outlen; i++) { + u32_to_bytes(inbuf + inlen, i); + sha512(out, inbuf, inlen + 4); + out += SPX_SHA512_OUTPUT_BYTES; + } + /* Until we cannot anymore, and we fill the remainder. */ + if (outlen > i * SPX_SHA512_OUTPUT_BYTES) { + u32_to_bytes(inbuf + inlen, i); + sha512(outbuf, inbuf, inlen + 4); + memcpy(out, outbuf, outlen - i * SPX_SHA512_OUTPUT_BYTES); + } +} + +/* + * Computes PRF(pk_seed, sk_seed, addr). + */ +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]) { + sha256ctx sha2_state; + unsigned char buf[SPX_SHA256_ADDR_BYTES + SPX_N]; + unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES]; + + /* Retrieve precomputed state containing pub_seed */ + sha256_inc_ctx_clone(&sha2_state, &ctx->state_seeded); + + /* Remainder: ADDR^c ‖ SK.seed */ + memcpy(buf, addr, SPX_SHA256_ADDR_BYTES); + memcpy(buf + SPX_SHA256_ADDR_BYTES, ctx->sk_seed, SPX_N); + + sha256_inc_finalize(outbuf, &sha2_state, buf, SPX_SHA256_ADDR_BYTES + SPX_N); + + memcpy(out, outbuf, SPX_N); +} + +/** + * Computes the message-dependent randomness R, using a secret seed as a key + * for HMAC, and an optional randomization value prefixed to the message. + * This requires m to have at least SPX_SHAX_BLOCK_BYTES + SPX_N space + * available in front of the pointer, i.e. before the message to use for the + * prefix. This is necessary to prevent having to move the message around (and + * allocate memory for it). + */ +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { + (void)ctx; + + unsigned char buf[SPX_SHAX_BLOCK_BYTES + SPX_SHAX_OUTPUT_BYTES]; + shaXstate state; + int i; + + + /* This implements HMAC-SHA */ + for (i = 0; i < SPX_N; i++) { + buf[i] = 0x36 ^ sk_prf[i]; + } + memset(buf + SPX_N, 0x36, SPX_SHAX_BLOCK_BYTES - SPX_N); + + shaX_inc_init(&state); + shaX_inc_blocks(&state, buf, 1); + + memcpy(buf, optrand, SPX_N); + + /* If optrand + message cannot fill up an entire block */ + if (SPX_N + mlen < SPX_SHAX_BLOCK_BYTES) { + memcpy(buf + SPX_N, m, mlen); + shaX_inc_finalize(buf + SPX_SHAX_BLOCK_BYTES, &state, + buf, mlen + SPX_N); + } + /* Otherwise first fill a block, so that finalize only uses the message */ + else { + memcpy(buf + SPX_N, m, SPX_SHAX_BLOCK_BYTES - SPX_N); + shaX_inc_blocks(&state, buf, 1); + + m += SPX_SHAX_BLOCK_BYTES - SPX_N; + mlen -= SPX_SHAX_BLOCK_BYTES - SPX_N; + shaX_inc_finalize(buf + SPX_SHAX_BLOCK_BYTES, &state, m, mlen); + } + + for (i = 0; i < SPX_N; i++) { + buf[i] = 0x5c ^ sk_prf[i]; + } + memset(buf + SPX_N, 0x5c, SPX_SHAX_BLOCK_BYTES - SPX_N); + + shaX(buf, buf, SPX_SHAX_BLOCK_BYTES + SPX_SHAX_OUTPUT_BYTES); + memcpy(R, buf, SPX_N); +} + +/** + * Computes the message hash using R, the public key, and the message. + * Outputs the message digest and the index of the leaf. The index is split in + * the tree index and the leaf index, for convenient copying to an address. + */ +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { + (void)ctx; +#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) +#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) +#define SPX_LEAF_BITS SPX_TREE_HEIGHT +#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) +#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) + + unsigned char seed[2 * SPX_N + SPX_SHAX_OUTPUT_BYTES]; + + /* Round to nearest multiple of SPX_SHAX_BLOCK_BYTES */ +#define SPX_INBLOCKS (((SPX_N + SPX_PK_BYTES + SPX_SHAX_BLOCK_BYTES - 1) & \ + -SPX_SHAX_BLOCK_BYTES) / SPX_SHAX_BLOCK_BYTES) + unsigned char inbuf[SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES]; + + unsigned char buf[SPX_DGST_BYTES]; + unsigned char *bufp = buf; + shaXstate state; + + shaX_inc_init(&state); + + // seed: SHA-X(R ‖ PK.seed ‖ PK.root ‖ M) + memcpy(inbuf, R, SPX_N); + memcpy(inbuf + SPX_N, pk, SPX_PK_BYTES); + + /* If R + pk + message cannot fill up an entire block */ + if (SPX_N + SPX_PK_BYTES + mlen < SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES) { + memcpy(inbuf + SPX_N + SPX_PK_BYTES, m, mlen); + shaX_inc_finalize(seed + 2 * SPX_N, &state, inbuf, SPX_N + SPX_PK_BYTES + mlen); + } + /* Otherwise first fill a block, so that finalize only uses the message */ + else { + memcpy(inbuf + SPX_N + SPX_PK_BYTES, m, + SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES - SPX_N - SPX_PK_BYTES); + shaX_inc_blocks(&state, inbuf, SPX_INBLOCKS); + + m += SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES - SPX_N - SPX_PK_BYTES; + mlen -= SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES - SPX_N - SPX_PK_BYTES; + shaX_inc_finalize(seed + 2 * SPX_N, &state, m, (size_t)mlen); + } + + // H_msg: MGF1-SHA-X(R ‖ PK.seed ‖ seed) + memcpy(seed, R, SPX_N); + memcpy(seed + SPX_N, pk, SPX_N); + + /* By doing this in two steps, we prevent hashing the message twice; + otherwise each iteration in MGF1 would hash the message again. */ + mgf1_X(bufp, SPX_DGST_BYTES, seed, 2 * SPX_N + SPX_SHAX_OUTPUT_BYTES); + + memcpy(digest, bufp, SPX_FORS_MSG_BYTES); + bufp += SPX_FORS_MSG_BYTES; + + + *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); + *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); + bufp += SPX_TREE_BYTES; + + *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); + *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); +} + + diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/hash_sha2x8.c b/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/hash_sha2x8.c new file mode 100644 index 0000000000..e04af7a069 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/hash_sha2x8.c @@ -0,0 +1,75 @@ +#include +#include + +#include "hash.h" +#include "hashx8.h" + +#include "address.h" +#include "params.h" +#include "sha2.h" +#include "sha256avx.h" +#include "sha256x8.h" +#include "utils.h" + +/* + * 8-way parallel version of prf_addr; takes 8x as much input and output + */ +void prf_addrx8(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const spx_ctx *ctx, + const uint32_t addrx8[8 * 8]) { + unsigned char bufx8[8 * (SPX_N + SPX_SHA256_ADDR_BYTES)]; + unsigned char outbufx8[8 * SPX_SHA256_OUTPUT_BYTES]; + unsigned int j; + + for (j = 0; j < 8; j++) { + memcpy(bufx8 + j * (SPX_N + SPX_SHA256_ADDR_BYTES), + addrx8 + j * 8, SPX_SHA256_ADDR_BYTES); + memcpy( + bufx8 + j * (SPX_N + SPX_SHA256_ADDR_BYTES) + SPX_SHA256_ADDR_BYTES, + ctx->sk_seed, + SPX_N + ); + } + + sha256x8_seeded( + /* out */ + outbufx8 + 0 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 1 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 2 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 3 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 4 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 5 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 6 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 7 * SPX_SHA256_OUTPUT_BYTES, + + /* seed */ + &ctx->statex8_seeded, + + /* in */ + bufx8 + 0 * (SPX_SHA256_ADDR_BYTES + SPX_N), + bufx8 + 1 * (SPX_SHA256_ADDR_BYTES + SPX_N), + bufx8 + 2 * (SPX_SHA256_ADDR_BYTES + SPX_N), + bufx8 + 3 * (SPX_SHA256_ADDR_BYTES + SPX_N), + bufx8 + 4 * (SPX_SHA256_ADDR_BYTES + SPX_N), + bufx8 + 5 * (SPX_SHA256_ADDR_BYTES + SPX_N), + bufx8 + 6 * (SPX_SHA256_ADDR_BYTES + SPX_N), + bufx8 + 7 * (SPX_SHA256_ADDR_BYTES + SPX_N), + SPX_SHA256_ADDR_BYTES + SPX_N /* len */ + ); + + memcpy(out0, outbufx8 + 0 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out1, outbufx8 + 1 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out2, outbufx8 + 2 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out3, outbufx8 + 3 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out4, outbufx8 + 4 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out5, outbufx8 + 5 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out6, outbufx8 + 6 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out7, outbufx8 + 7 * SPX_SHA256_OUTPUT_BYTES, SPX_N); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/hashx8.h b/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/hashx8.h new file mode 100644 index 0000000000..46503f0a10 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/hashx8.h @@ -0,0 +1,20 @@ +#ifndef SPX_HASHX8_H +#define SPX_HASHX8_H + +#include + +#include "params.h" + +#define prf_addrx8 SPX_NAMESPACE(prf_addrx8) +void prf_addrx8(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const spx_ctx *ctx, + const uint32_t addrx8[8 * 8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/merkle.c b/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/merkle.c new file mode 100644 index 0000000000..1f353c8dd8 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/merkle.c @@ -0,0 +1,65 @@ +#include +#include + +#include "merkle.h" + +#include "address.h" +#include "params.h" +#include "utils.h" +#include "utilsx8.h" +#include "wots.h" +#include "wotsx8.h" + +/* + * This generates a Merkle signature (WOTS signature followed by the Merkle + * authentication path). + */ +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf) { + unsigned char *auth_path = sig + SPX_WOTS_BYTES; + uint32_t tree_addrx8[8 * 8] = { 0 }; + int j; + struct leaf_info_x8 info = { 0 }; + unsigned steps[ SPX_WOTS_LEN ]; + + info.wots_sig = sig; + chain_lengths(steps, root); + info.wots_steps = steps; + + for (j = 0; j < 8; j++) { + set_type(&tree_addrx8[8 * j], SPX_ADDR_TYPE_HASHTREE); + set_type(&info.leaf_addr[8 * j], SPX_ADDR_TYPE_WOTS); + set_type(&info.pk_addr[8 * j], SPX_ADDR_TYPE_WOTSPK); + copy_subtree_addr(&tree_addrx8[8 * j], tree_addr); + copy_subtree_addr(&info.leaf_addr[8 * j], wots_addr); + copy_subtree_addr(&info.pk_addr[8 * j], wots_addr); + } + + info.wots_sign_leaf = idx_leaf; + + treehashx8(root, auth_path, ctx, + idx_leaf, 0, + SPX_TREE_HEIGHT, + wots_gen_leafx8, + tree_addrx8, &info); +} + +/* Compute root node of the top-most subtree. */ +/* Again, in this file because wots_gen_leaf is most of the work */ +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { + /* We do not need the auth path in key generation, but it simplifies the + code to have just one treehash routine that computes both root and path + in one function. */ + unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; + uint32_t top_tree_addr[8] = {0}; + uint32_t wots_addr[8] = {0}; + + set_layer_addr(top_tree_addr, SPX_D - 1); + set_layer_addr(wots_addr, SPX_D - 1); + + merkle_sign(auth_path, root, ctx, + wots_addr, top_tree_addr, + ~0U /* ~0 means "don't bother generating an auth path */ ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/merkle.h b/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/merkle.h new file mode 100644 index 0000000000..769cf2e970 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/merkle.h @@ -0,0 +1,21 @@ +#ifndef MERKLE_H_ +#define MERKLE_H_ + +#include + +#include "context.h" +#include "params.h" + +/* Generate a Merkle signature (WOTS signature followed by the Merkle */ +/* authentication path) */ +#define merkle_sign SPX_NAMESPACE(merkle_sign) +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf); + +/* Compute the root node of the top-most subtree. */ +#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); + +#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/nistapi.h b/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/nistapi.h new file mode 100644 index 0000000000..3cb71afad4 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/nistapi.h @@ -0,0 +1,87 @@ +#ifndef SPX_API_H +#define SPX_API_H + +#include +#include + +#include "params.h" + +#define CRYPTO_ALGNAME "SPHINCS+" + +#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES +#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES +#define CRYPTO_BYTES SPX_BYTES +#define CRYPTO_SEEDBYTES (3*SPX_N) + +/* + * Returns the length of a secret key, in bytes + */ +#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) +size_t crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) +size_t crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) +size_t crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) +size_t crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +#define crypto_sign SPX_NAMESPACE(crypto_sign) +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/params.h b/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/params.h new file mode 100644 index 0000000000..0e740f2b61 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/params.h @@ -0,0 +1,61 @@ +#ifndef SPX_PARAMS_H +#define SPX_PARAMS_H + +#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSSHA2192SSIMPLE_AVX2_##s + +/* Hash output length in bytes. */ +#define SPX_N 24 +/* Height of the hypertree. */ +#define SPX_FULL_HEIGHT 63 +/* Number of subtree layer. */ +#define SPX_D 7 +/* FORS tree dimensions. */ +#define SPX_FORS_HEIGHT 14 +#define SPX_FORS_TREES 17 +/* Winternitz parameter, */ +#define SPX_WOTS_W 16 + +/* The hash function is defined by linking a different hash.c file, as opposed + to setting a #define constant. */ + +/* This is a SHA2-based parameter set, hence whether we use SHA-256 + * exclusively or we use both SHA-256 and SHA-512 is controlled by + * the following #define */ +#define SPX_SHA512 1 /* Use SHA-512 for H and T_l, l >= 2 */ + +/* For clarity */ +#define SPX_ADDR_BYTES 32 + +/* WOTS parameters. */ +#define SPX_WOTS_LOGW 4 + +#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) + +/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ +#define SPX_WOTS_LEN2 3 + +#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) +#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) +#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES + +/* Subtree size. */ +#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) + +//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT +// #error SPX_D should always divide SPX_FULL_HEIGHT +//#endif + +/* FORS parameters. */ +#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) +#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) +#define SPX_FORS_PK_BYTES SPX_N + +/* Resulting SPX sizes. */ +#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ + SPX_FULL_HEIGHT * SPX_N) +#define SPX_PK_BYTES (2 * SPX_N) +#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) + +#include "sha2_offsets.h" + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/sha256avx.c b/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/sha256avx.c new file mode 100644 index 0000000000..6bbe6ecc24 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/sha256avx.c @@ -0,0 +1,357 @@ +#include +#include +#include + +#include "sha256avx.h" + +static const unsigned int RC[] = { + 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, + 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, + 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, + 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, + 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, + 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, + 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, + 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, + 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, + 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, + 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, + 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, + 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, + 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, + 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, + 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 +}; + +#define u32 uint32_t +#define u256 __m256i + +#define XOR _mm256_xor_si256 +#define OR _mm256_or_si256 +#define AND _mm256_and_si256 +#define ADD32 _mm256_add_epi32 +#define NOT(x) _mm256_xor_si256(x, _mm256_set_epi32(-1, -1, -1, -1, -1, -1, -1, -1)) + +#define LOAD(src) _mm256_loadu_si256((__m256i *)(src)) +#define STORE(dest,src) _mm256_storeu_si256((__m256i *)(dest),src) + +#define BYTESWAP(x) _mm256_shuffle_epi8(x, _mm256_set_epi8(0xc,0xd,0xe,0xf,0x8,0x9,0xa,0xb,0x4,0x5,0x6,0x7,0x0,0x1,0x2,0x3,0xc,0xd,0xe,0xf,0x8,0x9,0xa,0xb,0x4,0x5,0x6,0x7,0x0,0x1,0x2,0x3)) + +#define SHIFTR32(x, y) _mm256_srli_epi32(x, y) +#define SHIFTL32(x, y) _mm256_slli_epi32(x, y) + +#define ROTR32(x, y) OR(SHIFTR32(x, y), SHIFTL32(x, 32 - (y))) +#define ROTL32(x, y) OR(SHIFTL32(x, y), SHIFTR32(x, 32 - (y))) + +#define XOR3(a, b, c) XOR(XOR(a, b), c) + +#define ADD3_32(a, b, c) ADD32(ADD32(a, b), c) +#define ADD4_32(a, b, c, d) ADD32(ADD32(ADD32(a, b), c), d) +#define ADD5_32(a, b, c, d, e) ADD32(ADD32(ADD32(ADD32(a, b), c), d), e) + +#define MAJ_AVX(a, b, c) XOR3(AND(a, b), AND(a, c), AND(b, c)) +#define CH_AVX(a, b, c) XOR(AND(a, b), AND(NOT(a), c)) + +#define SIGMA1_AVX(x) XOR3(ROTR32(x, 6), ROTR32(x, 11), ROTR32(x, 25)) +#define SIGMA0_AVX(x) XOR3(ROTR32(x, 2), ROTR32(x, 13), ROTR32(x, 22)) + +#define WSIGMA1_AVX(x) XOR3(ROTR32(x, 17), ROTR32(x, 19), SHIFTR32(x, 10)) +#define WSIGMA0_AVX(x) XOR3(ROTR32(x, 7), ROTR32(x, 18), SHIFTR32(x, 3)) + +#define SHA256ROUND_AVX(a, b, c, d, e, f, g, h, rc, w) \ + T0 = ADD5_32(h, SIGMA1_AVX(e), CH_AVX(e, f, g), _mm256_set1_epi32((int)RC[rc]), w); \ + (d) = ADD32(d, T0); \ + T1 = ADD32(SIGMA0_AVX(a), MAJ_AVX(a, b, c)); \ + (h) = ADD32(T0, T1); + +// Transpose 8 vectors containing 32-bit values +static void transpose(u256 s[8]) { + u256 tmp0[8]; + u256 tmp1[8]; + tmp0[0] = _mm256_unpacklo_epi32(s[0], s[1]); + tmp0[1] = _mm256_unpackhi_epi32(s[0], s[1]); + tmp0[2] = _mm256_unpacklo_epi32(s[2], s[3]); + tmp0[3] = _mm256_unpackhi_epi32(s[2], s[3]); + tmp0[4] = _mm256_unpacklo_epi32(s[4], s[5]); + tmp0[5] = _mm256_unpackhi_epi32(s[4], s[5]); + tmp0[6] = _mm256_unpacklo_epi32(s[6], s[7]); + tmp0[7] = _mm256_unpackhi_epi32(s[6], s[7]); + tmp1[0] = _mm256_unpacklo_epi64(tmp0[0], tmp0[2]); + tmp1[1] = _mm256_unpackhi_epi64(tmp0[0], tmp0[2]); + tmp1[2] = _mm256_unpacklo_epi64(tmp0[1], tmp0[3]); + tmp1[3] = _mm256_unpackhi_epi64(tmp0[1], tmp0[3]); + tmp1[4] = _mm256_unpacklo_epi64(tmp0[4], tmp0[6]); + tmp1[5] = _mm256_unpackhi_epi64(tmp0[4], tmp0[6]); + tmp1[6] = _mm256_unpacklo_epi64(tmp0[5], tmp0[7]); + tmp1[7] = _mm256_unpackhi_epi64(tmp0[5], tmp0[7]); + s[0] = _mm256_permute2x128_si256(tmp1[0], tmp1[4], 0x20); + s[1] = _mm256_permute2x128_si256(tmp1[1], tmp1[5], 0x20); + s[2] = _mm256_permute2x128_si256(tmp1[2], tmp1[6], 0x20); + s[3] = _mm256_permute2x128_si256(tmp1[3], tmp1[7], 0x20); + s[4] = _mm256_permute2x128_si256(tmp1[0], tmp1[4], 0x31); + s[5] = _mm256_permute2x128_si256(tmp1[1], tmp1[5], 0x31); + s[6] = _mm256_permute2x128_si256(tmp1[2], tmp1[6], 0x31); + s[7] = _mm256_permute2x128_si256(tmp1[3], tmp1[7], 0x31); +} + +void sha256_ctx_clone8x(sha256x8ctx *out, const sha256x8ctx *in) { + memcpy(out, in, sizeof(sha256x8ctx)); +} + +void sha256_init8x(sha256x8ctx *ctx) { + ctx->s[0] = _mm256_set_epi32((int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667); + ctx->s[1] = _mm256_set_epi32((int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85); + ctx->s[2] = _mm256_set_epi32((int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372); + ctx->s[3] = _mm256_set_epi32((int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a); + ctx->s[4] = _mm256_set_epi32((int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f); + ctx->s[5] = _mm256_set_epi32((int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c); + ctx->s[6] = _mm256_set_epi32((int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab); + ctx->s[7] = _mm256_set_epi32((int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19); + + ctx->datalen = 0; + ctx->msglen = 0; +} + +void sha256_final8x(sha256x8ctx *ctx, + unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7) { + unsigned int i, curlen; + + // Padding + if (ctx->datalen < 56) { + for (i = 0; i < 8; ++i) { + curlen = ctx->datalen; + ctx->msgblocks[64 * i + curlen++] = 0x80; + while (curlen < 64) { + ctx->msgblocks[64 * i + curlen++] = 0x00; + } + } + } else { + for (i = 0; i < 8; ++i) { + curlen = ctx->datalen; + ctx->msgblocks[64 * i + curlen++] = 0x80; + while (curlen < 64) { + ctx->msgblocks[64 * i + curlen++] = 0x00; + } + } + sha256_transform8x(ctx, + &ctx->msgblocks[64 * 0], + &ctx->msgblocks[64 * 1], + &ctx->msgblocks[64 * 2], + &ctx->msgblocks[64 * 3], + &ctx->msgblocks[64 * 4], + &ctx->msgblocks[64 * 5], + &ctx->msgblocks[64 * 6], + &ctx->msgblocks[64 * 7] + ); + memset(ctx->msgblocks, 0, 8 * 64); + } + + // Add length of the message to each block + ctx->msglen += ctx->datalen * 8; + for (i = 0; i < 8; i++) { + ctx->msgblocks[64 * i + 63] = (unsigned char)(ctx->msglen); + ctx->msgblocks[64 * i + 62] = (unsigned char)(ctx->msglen >> 8); + ctx->msgblocks[64 * i + 61] = (unsigned char)(ctx->msglen >> 16); + ctx->msgblocks[64 * i + 60] = (unsigned char)(ctx->msglen >> 24); + ctx->msgblocks[64 * i + 59] = (unsigned char)(ctx->msglen >> 32); + ctx->msgblocks[64 * i + 58] = (unsigned char)(ctx->msglen >> 40); + ctx->msgblocks[64 * i + 57] = (unsigned char)(ctx->msglen >> 48); + ctx->msgblocks[64 * i + 56] = (unsigned char)(ctx->msglen >> 56); + } + sha256_transform8x(ctx, + &ctx->msgblocks[64 * 0], + &ctx->msgblocks[64 * 1], + &ctx->msgblocks[64 * 2], + &ctx->msgblocks[64 * 3], + &ctx->msgblocks[64 * 4], + &ctx->msgblocks[64 * 5], + &ctx->msgblocks[64 * 6], + &ctx->msgblocks[64 * 7] + ); + + // Compute final hash output + transpose(ctx->s); + + // Store Hash value + STORE(out0, BYTESWAP(ctx->s[0])); + STORE(out1, BYTESWAP(ctx->s[1])); + STORE(out2, BYTESWAP(ctx->s[2])); + STORE(out3, BYTESWAP(ctx->s[3])); + STORE(out4, BYTESWAP(ctx->s[4])); + STORE(out5, BYTESWAP(ctx->s[5])); + STORE(out6, BYTESWAP(ctx->s[6])); + STORE(out7, BYTESWAP(ctx->s[7])); +} + +void sha256_transform8x(sha256x8ctx *ctx, + const unsigned char *data0, + const unsigned char *data1, + const unsigned char *data2, + const unsigned char *data3, + const unsigned char *data4, + const unsigned char *data5, + const unsigned char *data6, + const unsigned char *data7) { + u256 s[8], w[64], T0, T1; + + // Load words and transform data correctly + w[0] = BYTESWAP(LOAD(data0)); + w[0 + 8] = BYTESWAP(LOAD(data0 + 32)); + w[1] = BYTESWAP(LOAD(data1)); + w[1 + 8] = BYTESWAP(LOAD(data1 + 32)); + w[2] = BYTESWAP(LOAD(data2)); + w[2 + 8] = BYTESWAP(LOAD(data2 + 32)); + w[3] = BYTESWAP(LOAD(data3)); + w[3 + 8] = BYTESWAP(LOAD(data3 + 32)); + w[4] = BYTESWAP(LOAD(data4)); + w[4 + 8] = BYTESWAP(LOAD(data4 + 32)); + w[5] = BYTESWAP(LOAD(data5)); + w[5 + 8] = BYTESWAP(LOAD(data5 + 32)); + w[6] = BYTESWAP(LOAD(data6)); + w[6 + 8] = BYTESWAP(LOAD(data6 + 32)); + w[7] = BYTESWAP(LOAD(data7)); + w[7 + 8] = BYTESWAP(LOAD(data7 + 32)); + + transpose(w); + transpose(w + 8); + + // Initial State + s[0] = ctx->s[0]; + s[1] = ctx->s[1]; + s[2] = ctx->s[2]; + s[3] = ctx->s[3]; + s[4] = ctx->s[4]; + s[5] = ctx->s[5]; + s[6] = ctx->s[6]; + s[7] = ctx->s[7]; + + SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 0, w[0]); + SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 1, w[1]); + SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 2, w[2]); + SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 3, w[3]); + SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 4, w[4]); + SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 5, w[5]); + SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 6, w[6]); + SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 7, w[7]); + SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 8, w[8]); + SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 9, w[9]); + SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 10, w[10]); + SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 11, w[11]); + SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 12, w[12]); + SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 13, w[13]); + SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 14, w[14]); + SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 15, w[15]); + w[16] = ADD4_32(WSIGMA1_AVX(w[14]), w[0], w[9], WSIGMA0_AVX(w[1])); + SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 16, w[16]); + w[17] = ADD4_32(WSIGMA1_AVX(w[15]), w[1], w[10], WSIGMA0_AVX(w[2])); + SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 17, w[17]); + w[18] = ADD4_32(WSIGMA1_AVX(w[16]), w[2], w[11], WSIGMA0_AVX(w[3])); + SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 18, w[18]); + w[19] = ADD4_32(WSIGMA1_AVX(w[17]), w[3], w[12], WSIGMA0_AVX(w[4])); + SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 19, w[19]); + w[20] = ADD4_32(WSIGMA1_AVX(w[18]), w[4], w[13], WSIGMA0_AVX(w[5])); + SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 20, w[20]); + w[21] = ADD4_32(WSIGMA1_AVX(w[19]), w[5], w[14], WSIGMA0_AVX(w[6])); + SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 21, w[21]); + w[22] = ADD4_32(WSIGMA1_AVX(w[20]), w[6], w[15], WSIGMA0_AVX(w[7])); + SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 22, w[22]); + w[23] = ADD4_32(WSIGMA1_AVX(w[21]), w[7], w[16], WSIGMA0_AVX(w[8])); + SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 23, w[23]); + w[24] = ADD4_32(WSIGMA1_AVX(w[22]), w[8], w[17], WSIGMA0_AVX(w[9])); + SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 24, w[24]); + w[25] = ADD4_32(WSIGMA1_AVX(w[23]), w[9], w[18], WSIGMA0_AVX(w[10])); + SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 25, w[25]); + w[26] = ADD4_32(WSIGMA1_AVX(w[24]), w[10], w[19], WSIGMA0_AVX(w[11])); + SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 26, w[26]); + w[27] = ADD4_32(WSIGMA1_AVX(w[25]), w[11], w[20], WSIGMA0_AVX(w[12])); + SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 27, w[27]); + w[28] = ADD4_32(WSIGMA1_AVX(w[26]), w[12], w[21], WSIGMA0_AVX(w[13])); + SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 28, w[28]); + w[29] = ADD4_32(WSIGMA1_AVX(w[27]), w[13], w[22], WSIGMA0_AVX(w[14])); + SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 29, w[29]); + w[30] = ADD4_32(WSIGMA1_AVX(w[28]), w[14], w[23], WSIGMA0_AVX(w[15])); + SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 30, w[30]); + w[31] = ADD4_32(WSIGMA1_AVX(w[29]), w[15], w[24], WSIGMA0_AVX(w[16])); + SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 31, w[31]); + w[32] = ADD4_32(WSIGMA1_AVX(w[30]), w[16], w[25], WSIGMA0_AVX(w[17])); + SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 32, w[32]); + w[33] = ADD4_32(WSIGMA1_AVX(w[31]), w[17], w[26], WSIGMA0_AVX(w[18])); + SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 33, w[33]); + w[34] = ADD4_32(WSIGMA1_AVX(w[32]), w[18], w[27], WSIGMA0_AVX(w[19])); + SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 34, w[34]); + w[35] = ADD4_32(WSIGMA1_AVX(w[33]), w[19], w[28], WSIGMA0_AVX(w[20])); + SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 35, w[35]); + w[36] = ADD4_32(WSIGMA1_AVX(w[34]), w[20], w[29], WSIGMA0_AVX(w[21])); + SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 36, w[36]); + w[37] = ADD4_32(WSIGMA1_AVX(w[35]), w[21], w[30], WSIGMA0_AVX(w[22])); + SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 37, w[37]); + w[38] = ADD4_32(WSIGMA1_AVX(w[36]), w[22], w[31], WSIGMA0_AVX(w[23])); + SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 38, w[38]); + w[39] = ADD4_32(WSIGMA1_AVX(w[37]), w[23], w[32], WSIGMA0_AVX(w[24])); + SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 39, w[39]); + w[40] = ADD4_32(WSIGMA1_AVX(w[38]), w[24], w[33], WSIGMA0_AVX(w[25])); + SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 40, w[40]); + w[41] = ADD4_32(WSIGMA1_AVX(w[39]), w[25], w[34], WSIGMA0_AVX(w[26])); + SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 41, w[41]); + w[42] = ADD4_32(WSIGMA1_AVX(w[40]), w[26], w[35], WSIGMA0_AVX(w[27])); + SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 42, w[42]); + w[43] = ADD4_32(WSIGMA1_AVX(w[41]), w[27], w[36], WSIGMA0_AVX(w[28])); + SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 43, w[43]); + w[44] = ADD4_32(WSIGMA1_AVX(w[42]), w[28], w[37], WSIGMA0_AVX(w[29])); + SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 44, w[44]); + w[45] = ADD4_32(WSIGMA1_AVX(w[43]), w[29], w[38], WSIGMA0_AVX(w[30])); + SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 45, w[45]); + w[46] = ADD4_32(WSIGMA1_AVX(w[44]), w[30], w[39], WSIGMA0_AVX(w[31])); + SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 46, w[46]); + w[47] = ADD4_32(WSIGMA1_AVX(w[45]), w[31], w[40], WSIGMA0_AVX(w[32])); + SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 47, w[47]); + w[48] = ADD4_32(WSIGMA1_AVX(w[46]), w[32], w[41], WSIGMA0_AVX(w[33])); + SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 48, w[48]); + w[49] = ADD4_32(WSIGMA1_AVX(w[47]), w[33], w[42], WSIGMA0_AVX(w[34])); + SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 49, w[49]); + w[50] = ADD4_32(WSIGMA1_AVX(w[48]), w[34], w[43], WSIGMA0_AVX(w[35])); + SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 50, w[50]); + w[51] = ADD4_32(WSIGMA1_AVX(w[49]), w[35], w[44], WSIGMA0_AVX(w[36])); + SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 51, w[51]); + w[52] = ADD4_32(WSIGMA1_AVX(w[50]), w[36], w[45], WSIGMA0_AVX(w[37])); + SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 52, w[52]); + w[53] = ADD4_32(WSIGMA1_AVX(w[51]), w[37], w[46], WSIGMA0_AVX(w[38])); + SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 53, w[53]); + w[54] = ADD4_32(WSIGMA1_AVX(w[52]), w[38], w[47], WSIGMA0_AVX(w[39])); + SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 54, w[54]); + w[55] = ADD4_32(WSIGMA1_AVX(w[53]), w[39], w[48], WSIGMA0_AVX(w[40])); + SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 55, w[55]); + w[56] = ADD4_32(WSIGMA1_AVX(w[54]), w[40], w[49], WSIGMA0_AVX(w[41])); + SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 56, w[56]); + w[57] = ADD4_32(WSIGMA1_AVX(w[55]), w[41], w[50], WSIGMA0_AVX(w[42])); + SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 57, w[57]); + w[58] = ADD4_32(WSIGMA1_AVX(w[56]), w[42], w[51], WSIGMA0_AVX(w[43])); + SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 58, w[58]); + w[59] = ADD4_32(WSIGMA1_AVX(w[57]), w[43], w[52], WSIGMA0_AVX(w[44])); + SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 59, w[59]); + w[60] = ADD4_32(WSIGMA1_AVX(w[58]), w[44], w[53], WSIGMA0_AVX(w[45])); + SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 60, w[60]); + w[61] = ADD4_32(WSIGMA1_AVX(w[59]), w[45], w[54], WSIGMA0_AVX(w[46])); + SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 61, w[61]); + w[62] = ADD4_32(WSIGMA1_AVX(w[60]), w[46], w[55], WSIGMA0_AVX(w[47])); + SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 62, w[62]); + w[63] = ADD4_32(WSIGMA1_AVX(w[61]), w[47], w[56], WSIGMA0_AVX(w[48])); + SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 63, w[63]); + + // Feed Forward + ctx->s[0] = ADD32(s[0], ctx->s[0]); + ctx->s[1] = ADD32(s[1], ctx->s[1]); + ctx->s[2] = ADD32(s[2], ctx->s[2]); + ctx->s[3] = ADD32(s[3], ctx->s[3]); + ctx->s[4] = ADD32(s[4], ctx->s[4]); + ctx->s[5] = ADD32(s[5], ctx->s[5]); + ctx->s[6] = ADD32(s[6], ctx->s[6]); + ctx->s[7] = ADD32(s[7], ctx->s[7]); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/sha256avx.h b/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/sha256avx.h new file mode 100644 index 0000000000..1e3bcf889b --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/sha256avx.h @@ -0,0 +1,44 @@ +#ifndef SHA256AVX_H +#define SHA256AVX_H + +#include +#include + +#include "params.h" + +typedef struct SHA256state { + __m256i s[8]; + unsigned char msgblocks[8 * 64]; + unsigned int datalen; + unsigned long long msglen; +} sha256x8ctx; + +#define sha256_ctx_clone8x SPX_NAMESPACE(sha256_ctx_clone8x) +void sha256_ctx_clone8x(sha256x8ctx *out, const sha256x8ctx *in); + +#define sha256_init8x SPX_NAMESPACE(sha256_init8x) +void sha256_init8x(sha256x8ctx *ctx); + +#define sha256_final8x SPX_NAMESPACE(sha256_final8x) +void sha256_final8x(sha256x8ctx *ctx, + unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7); + +#define sha256_transform8x SPX_NAMESPACE(sha256_transform8x) +void sha256_transform8x(sha256x8ctx *ctx, + const unsigned char *data0, + const unsigned char *data1, + const unsigned char *data2, + const unsigned char *data3, + const unsigned char *data4, + const unsigned char *data5, + const unsigned char *data6, + const unsigned char *data7); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/sha256x8.c b/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/sha256x8.c new file mode 100644 index 0000000000..d97750c09b --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/sha256x8.c @@ -0,0 +1,185 @@ +#include + +#include "sha256avx.h" +#include "sha256x8.h" +#include "utils.h" + +// Performs sha256x8 on an initialized (and perhaps seeded) state. +static void _sha256x8( + sha256x8ctx *ctx, + unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, unsigned long long inlen) { + unsigned long long i = 0; + while (inlen - i >= 64) { + sha256_transform8x(ctx, + in0 + i, + in1 + i, + in2 + i, + in3 + i, + in4 + i, + in5 + i, + in6 + i, + in7 + i + ); + i += 64; + ctx->msglen += 512; + } + + size_t bytes_to_copy = (size_t)(inlen - i); + memcpy(&ctx->msgblocks[64 * 0], in0 + i, bytes_to_copy); + memcpy(&ctx->msgblocks[64 * 1], in1 + i, bytes_to_copy); + memcpy(&ctx->msgblocks[64 * 2], in2 + i, bytes_to_copy); + memcpy(&ctx->msgblocks[64 * 3], in3 + i, bytes_to_copy); + memcpy(&ctx->msgblocks[64 * 4], in4 + i, bytes_to_copy); + memcpy(&ctx->msgblocks[64 * 5], in5 + i, bytes_to_copy); + memcpy(&ctx->msgblocks[64 * 6], in6 + i, bytes_to_copy); + memcpy(&ctx->msgblocks[64 * 7], in7 + i, bytes_to_copy); + ctx->datalen = (unsigned int)bytes_to_copy; + + sha256_final8x(ctx, out0, out1, out2, out3, out4, out5, out6, out7); +} + +void sha256x8_seeded( + unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const sha256x8ctx *seed, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, unsigned long long inlen) { + + sha256x8ctx ctx; + sha256_ctx_clone8x(&ctx, seed); + + _sha256x8(&ctx, out0, out1, out2, out3, out4, out5, out6, out7, + in0, in1, in2, in3, in4, in5, in6, in7, inlen); +} + +/* This provides a wrapper around the internals of 8x parallel SHA256 */ +void sha256x8(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, unsigned long long inlen) { + sha256x8ctx ctx; + sha256_init8x(&ctx); + + _sha256x8(&ctx, out0, out1, out2, out3, out4, out5, out6, out7, + in0, in1, in2, in3, in4, in5, in6, in7, inlen); +} + +/** + * Note that inlen should be sufficiently small that it still allows for + * an array to be allocated on the stack. Typically 'in' is merely a seed. + * Outputs outlen number of bytes + */ +void mgf1x8(unsigned char *outx8, unsigned long outlen, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, + unsigned long inlen) { + PQCLEAN_VLA(unsigned char, inbufx8, 8 * (inlen + 4)); + unsigned char outbufx8[8 * SPX_SHA256_OUTPUT_BYTES]; + uint32_t i; + unsigned int j; + + memcpy(inbufx8 + 0 * (inlen + 4), in0, inlen); + memcpy(inbufx8 + 1 * (inlen + 4), in1, inlen); + memcpy(inbufx8 + 2 * (inlen + 4), in2, inlen); + memcpy(inbufx8 + 3 * (inlen + 4), in3, inlen); + memcpy(inbufx8 + 4 * (inlen + 4), in4, inlen); + memcpy(inbufx8 + 5 * (inlen + 4), in5, inlen); + memcpy(inbufx8 + 6 * (inlen + 4), in6, inlen); + memcpy(inbufx8 + 7 * (inlen + 4), in7, inlen); + + /* While we can fit in at least another full block of SHA256 output.. */ + for (i = 0; (i + 1)*SPX_SHA256_OUTPUT_BYTES <= outlen; i++) { + for (j = 0; j < 8; j++) { + u32_to_bytes(inbufx8 + inlen + j * (inlen + 4), i); + } + + sha256x8(outx8 + 0 * outlen, + outx8 + 1 * outlen, + outx8 + 2 * outlen, + outx8 + 3 * outlen, + outx8 + 4 * outlen, + outx8 + 5 * outlen, + outx8 + 6 * outlen, + outx8 + 7 * outlen, + inbufx8 + 0 * (inlen + 4), + inbufx8 + 1 * (inlen + 4), + inbufx8 + 2 * (inlen + 4), + inbufx8 + 3 * (inlen + 4), + inbufx8 + 4 * (inlen + 4), + inbufx8 + 5 * (inlen + 4), + inbufx8 + 6 * (inlen + 4), + inbufx8 + 7 * (inlen + 4), inlen + 4); + outx8 += SPX_SHA256_OUTPUT_BYTES; + } + /* Until we cannot anymore, and we fill the remainder. */ + for (j = 0; j < 8; j++) { + u32_to_bytes(inbufx8 + inlen + j * (inlen + 4), i); + } + sha256x8(outbufx8 + 0 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 1 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 2 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 3 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 4 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 5 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 6 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 7 * SPX_SHA256_OUTPUT_BYTES, + inbufx8 + 0 * (inlen + 4), + inbufx8 + 1 * (inlen + 4), + inbufx8 + 2 * (inlen + 4), + inbufx8 + 3 * (inlen + 4), + inbufx8 + 4 * (inlen + 4), + inbufx8 + 5 * (inlen + 4), + inbufx8 + 6 * (inlen + 4), + inbufx8 + 7 * (inlen + 4), inlen + 4); + + for (j = 0; j < 8; j++) { + memcpy(outx8 + j * outlen, + outbufx8 + j * SPX_SHA256_OUTPUT_BYTES, + outlen - i * SPX_SHA256_OUTPUT_BYTES); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/sha256x8.h b/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/sha256x8.h new file mode 100644 index 0000000000..4f7330a6c1 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/sha256x8.h @@ -0,0 +1,64 @@ +#ifndef SPX_SHA256X8_H +#define SPX_SHA256X8_H + +#include "params.h" +#include "sha256avx.h" + + + +#define sha256x8_seeded SPX_NAMESPACE(sha256x8_seeded) +void sha256x8_seeded( + unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const sha256x8ctx *seed, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, unsigned long long inlen); + +/* This provides a wrapper around the internals of 8x parallel SHA256 */ +#define sha256x8 SPX_NAMESPACE(sha256x8) +void sha256x8(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, unsigned long long inlen); + +/** + * Note that inlen should be sufficiently small that it still allows for + * an array to be allocated on the stack. Typically 'in' is merely a seed. + * Outputs outlen number of bytes + */ +#define mgf1x8 SPX_NAMESPACE(mgf1x8) +void mgf1x8(unsigned char *outx8, unsigned long outlen, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, + unsigned long inlen); +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/sha2_offsets.h b/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/sha2_offsets.h new file mode 100644 index 0000000000..6e3584f7a4 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/sha2_offsets.h @@ -0,0 +1,27 @@ +#ifndef SHA2_OFFSETS_H_ +#define SHA2_OFFSETS_H_ + +#define SPX_SHA256_BLOCK_BYTES 64 +#define SPX_SHA256_OUTPUT_BYTES 32 + +#define SPX_SHA512_BLOCK_BYTES 128 +#define SPX_SHA512_OUTPUT_BYTES 64 + +/* + * Offsets of various fields in the address structure when we use SHA2 as + * the Sphincs+ hash function + */ + +#define SPX_OFFSET_LAYER 0 /* The byte used to specify the Merkle tree layer */ +#define SPX_OFFSET_TREE 1 /* The start of the 8 byte field used to specify the tree */ +#define SPX_OFFSET_TYPE 9 /* The byte used to specify the hash type (reason) */ +#define SPX_OFFSET_KP_ADDR2 12 /* The high byte used to specify the key pair (which one-time signature) */ +#define SPX_OFFSET_KP_ADDR1 13 /* The low byte used to specify the key pair */ +#define SPX_OFFSET_CHAIN_ADDR 17 /* The byte used to specify the chain address (which Winternitz chain) */ +#define SPX_OFFSET_HASH_ADDR 21 /* The byte used to specify the hash address (where in the Winternitz chain) */ +#define SPX_OFFSET_TREE_HGT 17 /* The byte used to specify the height of this node in the FORS or Merkle tree */ +#define SPX_OFFSET_TREE_INDEX 18 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ + +#define SPX_SHA2 1 + +#endif /* SHA2_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/sha512x4.c b/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/sha512x4.c new file mode 100644 index 0000000000..8d33deffdd --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/sha512x4.c @@ -0,0 +1,446 @@ +#include +#include +#include + +/* pull in the entire thing */ +#include "sha512x4.h" +#include "utils.h" + +typedef uint64_t u64; +typedef __m256i u256; + +#define BYTESWAP(x) _mm256_shuffle_epi8(x, _mm256_set_epi8(0x8,0x9,0xa,0xb,0xc,0xd,0xe,0xf,0x0,0x1,0x2,0x3,0x4,0x5,0x6,0x7,0x8,0x9,0xa,0xb,0xc,0xd,0xe,0xf,0x0,0x1,0x2,0x3,0x4,0x5,0x6,0x7)) +#define STORE(dest,src) _mm256_storeu_si256((__m256i *)(dest),src) + +// Transpose 4 vectors containing 64-bit values +// That is, it rearranges the array: +// A B C D +// E F G H +// I J K L +// M N O P +// into +// A E I M +// B F J N +// C G K O +// D H L P +// where each letter stands for 64 bits (and lsbits on the left) +static void transpose(u256 s[4]) { + u256 tmp[4]; + tmp[0] = _mm256_unpacklo_epi64(s[0], s[1]); + tmp[1] = _mm256_unpackhi_epi64(s[0], s[1]); + tmp[2] = _mm256_unpacklo_epi64(s[2], s[3]); + tmp[3] = _mm256_unpackhi_epi64(s[2], s[3]); + // tmp is in the order of + // A E C G + // B F D H + // I M K O + // J N L P + s[0] = _mm256_permute2x128_si256(tmp[0], tmp[2], 0x20); + s[1] = _mm256_permute2x128_si256(tmp[1], tmp[3], 0x20); + s[2] = _mm256_permute2x128_si256(tmp[0], tmp[2], 0x31); + s[3] = _mm256_permute2x128_si256(tmp[1], tmp[3], 0x31); +} + + +void sha512_init4x(sha512x4ctx *ctx) { +#define SET4(x) _mm256_set_epi64x((long long)(x), (long long)(x), (long long)(x), (long long)(x)) + ctx->s[0] = SET4(0x6a09e667f3bcc908ULL); + ctx->s[1] = SET4(0xbb67ae8584caa73bULL); + ctx->s[2] = SET4(0x3c6ef372fe94f82bULL); + ctx->s[3] = SET4(0xa54ff53a5f1d36f1ULL); + ctx->s[4] = SET4(0x510e527fade682d1ULL); + ctx->s[5] = SET4(0x9b05688c2b3e6c1fULL); + ctx->s[6] = SET4(0x1f83d9abfb41bd6bULL); + ctx->s[7] = SET4(0x5be0cd19137e2179ULL); +#undef SET4 + + ctx->datalen = 0; + ctx->msglen = 0; +} + +#define XOR _mm256_xor_si256 +#define OR _mm256_or_si256 +#define AND _mm256_and_si256 +#define ADD64 _mm256_add_epi64 + +#define LOAD(src) _mm256_loadu_si256((__m256i *)(src)) + +#define SHIFTR64(x, y) _mm256_srli_epi64(x, y) +#define SHIFTL64(x, y) _mm256_slli_epi64(x, y) + +#define ROTR64(x, y) OR(SHIFTR64(x, y), SHIFTL64(x, 64 - (y))) + +static u256 XOR3(u256 a, u256 b, u256 c) { + return XOR(XOR(a, b), c); +} + +#define ADD3_64(a, b, c) ADD64(ADD64(a, b), c) +#define ADD4_64(a, b, c, d) ADD64(ADD64(ADD64(a, b), c), d) +#define ADD5_64(a, b, c, d, e) ADD64(ADD64(ADD64(ADD64(a, b), c), d), e) + +static u256 MAJ_AVX(u256 a, u256 b, u256 c) { + return XOR(c, AND(XOR(a, c), XOR(b, c))); +} +static u256 CH_AVX(u256 a, u256 b, u256 c) { + return XOR(c, AND(a, XOR(b, c))); +} +static u256 SIGMA0_AVX(u256 x) { + return XOR3(ROTR64(x, 28), ROTR64(x, 34), ROTR64(x, 39)); +} +static u256 SIGMA1_AVX(u256 x) { + return XOR3(ROTR64(x, 14), ROTR64(x, 18), ROTR64(x, 41)); +} +static u256 GAMMA0_AVX(u256 x) { + return XOR3(ROTR64(x, 1), ROTR64(x, 8), SHIFTR64(x, 7)); +} +static u256 GAMMA1_AVX(u256 x) { + return XOR3(ROTR64(x, 19), ROTR64(x, 61), SHIFTR64(x, 6)); +} + +#define SHA512ROUND_AVX(a, b, c, d, e, f, g, h, rc, w) \ + T0 = ADD5_64(h, w, SIGMA1_AVX(e), CH_AVX(e, f, g), _mm256_set1_epi64x((long long)RC[rc])); \ + T1 = ADD64(SIGMA0_AVX(a), MAJ_AVX(a, b, c)); \ + (d) = ADD64(d, T0); \ + (h) = ADD64(T0, T1); + +static const unsigned long long RC[80] = { + 0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL, + 0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL, + 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL, + 0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL, + 0xd807aa98a3030242ULL, 0x12835b0145706fbeULL, + 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL, + 0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL, + 0x9bdc06a725c71235ULL, 0xc19bf174cf692694ULL, + 0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL, + 0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL, + 0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL, + 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL, + 0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL, + 0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL, + 0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL, + 0x06ca6351e003826fULL, 0x142929670a0e6e70ULL, + 0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL, + 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL, + 0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL, + 0x81c2c92e47edaee6ULL, 0x92722c851482353bULL, + 0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL, + 0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL, + 0xd192e819d6ef5218ULL, 0xd69906245565a910ULL, + 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL, + 0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL, + 0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL, + 0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL, + 0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL, + 0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL, + 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL, + 0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL, + 0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL, + 0xca273eceea26619cULL, 0xd186b8c721c0c207ULL, + 0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL, + 0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL, + 0x113f9804bef90daeULL, 0x1b710b35131c471bULL, + 0x28db77f523047d84ULL, 0x32caab7b40c72493ULL, + 0x3c9ebe0a15c9bebcULL, 0x431d67c49c100d4cULL, + 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL, + 0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL, +}; + +void sha512_transform4x( + sha512x4ctx *ctx, + const unsigned char *d0, + const unsigned char *d1, + const unsigned char *d2, + const unsigned char *d3) { + u256 s0, s1, s2, s3, s4, s5, s6, s7, w[16], T0, T1, nw; + + // Load words and transform data correctly + w[0 ] = BYTESWAP(LOAD(d0 )); + w[0 + 4] = BYTESWAP(LOAD(d0 + 32)); + w[0 + 8] = BYTESWAP(LOAD(d0 + 64)); + w[0 + 12] = BYTESWAP(LOAD(d0 + 96)); + + w[1 ] = BYTESWAP(LOAD(d1 )); + w[1 + 4] = BYTESWAP(LOAD(d1 + 32)); + w[1 + 8] = BYTESWAP(LOAD(d1 + 64)); + w[1 + 12] = BYTESWAP(LOAD(d1 + 96)); + + w[2 ] = BYTESWAP(LOAD(d2 )); + w[2 + 4] = BYTESWAP(LOAD(d2 + 32)); + w[2 + 8] = BYTESWAP(LOAD(d2 + 64)); + w[2 + 12] = BYTESWAP(LOAD(d2 + 96)); + + w[3 ] = BYTESWAP(LOAD(d3 )); + w[3 + 4] = BYTESWAP(LOAD(d3 + 32)); + w[3 + 8] = BYTESWAP(LOAD(d3 + 64)); + w[3 + 12] = BYTESWAP(LOAD(d3 + 96)); + + transpose(w); + transpose(w + 4); + transpose(w + 8); + transpose(w + 12); + + // Initial State + s0 = ctx->s[0]; + s1 = ctx->s[1]; + s2 = ctx->s[2]; + s3 = ctx->s[3]; + s4 = ctx->s[4]; + s5 = ctx->s[5]; + s6 = ctx->s[6]; + s7 = ctx->s[7]; + + // The first 16 rounds (where the w inputs are directly from the data) + SHA512ROUND_AVX(s0, s1, s2, s3, s4, s5, s6, s7, 0, w[0]); + SHA512ROUND_AVX(s7, s0, s1, s2, s3, s4, s5, s6, 1, w[1]); + SHA512ROUND_AVX(s6, s7, s0, s1, s2, s3, s4, s5, 2, w[2]); + SHA512ROUND_AVX(s5, s6, s7, s0, s1, s2, s3, s4, 3, w[3]); + SHA512ROUND_AVX(s4, s5, s6, s7, s0, s1, s2, s3, 4, w[4]); + SHA512ROUND_AVX(s3, s4, s5, s6, s7, s0, s1, s2, 5, w[5]); + SHA512ROUND_AVX(s2, s3, s4, s5, s6, s7, s0, s1, 6, w[6]); + SHA512ROUND_AVX(s1, s2, s3, s4, s5, s6, s7, s0, 7, w[7]); + SHA512ROUND_AVX(s0, s1, s2, s3, s4, s5, s6, s7, 8, w[8]); + SHA512ROUND_AVX(s7, s0, s1, s2, s3, s4, s5, s6, 9, w[9]); + SHA512ROUND_AVX(s6, s7, s0, s1, s2, s3, s4, s5, 10, w[10]); + SHA512ROUND_AVX(s5, s6, s7, s0, s1, s2, s3, s4, 11, w[11]); + SHA512ROUND_AVX(s4, s5, s6, s7, s0, s1, s2, s3, 12, w[12]); + SHA512ROUND_AVX(s3, s4, s5, s6, s7, s0, s1, s2, 13, w[13]); + SHA512ROUND_AVX(s2, s3, s4, s5, s6, s7, s0, s1, 14, w[14]); + SHA512ROUND_AVX(s1, s2, s3, s4, s5, s6, s7, s0, 15, w[15]); + +#define M(i) (((i)+16) & 0xf) +#define NextW(i) \ + w[M(i)] = ADD4_64(GAMMA1_AVX(w[M((i)-2)]), w[M((i)-7)], GAMMA0_AVX(w[M((i)-15)]), w[M((i)-16)]); + + // The remaining 64 rounds (where the w inputs are a linear fix of the data) + for (unsigned i = 16; i < 80; i += 16) { + nw = NextW(0); + SHA512ROUND_AVX(s0, s1, s2, s3, s4, s5, s6, s7, i + 0, nw); + nw = NextW(1); + SHA512ROUND_AVX(s7, s0, s1, s2, s3, s4, s5, s6, i + 1, nw); + nw = NextW(2); + SHA512ROUND_AVX(s6, s7, s0, s1, s2, s3, s4, s5, i + 2, nw); + nw = NextW(3); + SHA512ROUND_AVX(s5, s6, s7, s0, s1, s2, s3, s4, i + 3, nw); + nw = NextW(4); + SHA512ROUND_AVX(s4, s5, s6, s7, s0, s1, s2, s3, i + 4, nw); + nw = NextW(5); + SHA512ROUND_AVX(s3, s4, s5, s6, s7, s0, s1, s2, i + 5, nw); + nw = NextW(6); + SHA512ROUND_AVX(s2, s3, s4, s5, s6, s7, s0, s1, i + 6, nw); + nw = NextW(7); + SHA512ROUND_AVX(s1, s2, s3, s4, s5, s6, s7, s0, i + 7, nw); + nw = NextW(8); + SHA512ROUND_AVX(s0, s1, s2, s3, s4, s5, s6, s7, i + 8, nw); + nw = NextW(9); + SHA512ROUND_AVX(s7, s0, s1, s2, s3, s4, s5, s6, i + 9, nw); + nw = NextW(10); + SHA512ROUND_AVX(s6, s7, s0, s1, s2, s3, s4, s5, i + 10, nw); + nw = NextW(11); + SHA512ROUND_AVX(s5, s6, s7, s0, s1, s2, s3, s4, i + 11, nw); + nw = NextW(12); + SHA512ROUND_AVX(s4, s5, s6, s7, s0, s1, s2, s3, i + 12, nw); + nw = NextW(13); + SHA512ROUND_AVX(s3, s4, s5, s6, s7, s0, s1, s2, i + 13, nw); + nw = NextW(14); + SHA512ROUND_AVX(s2, s3, s4, s5, s6, s7, s0, s1, i + 14, nw); + nw = NextW(15); + SHA512ROUND_AVX(s1, s2, s3, s4, s5, s6, s7, s0, i + 15, nw); + } + + // Feed Forward + ctx->s[0] = ADD64(s0, ctx->s[0]); + ctx->s[1] = ADD64(s1, ctx->s[1]); + ctx->s[2] = ADD64(s2, ctx->s[2]); + ctx->s[3] = ADD64(s3, ctx->s[3]); + ctx->s[4] = ADD64(s4, ctx->s[4]); + ctx->s[5] = ADD64(s5, ctx->s[5]); + ctx->s[6] = ADD64(s6, ctx->s[6]); + ctx->s[7] = ADD64(s7, ctx->s[7]); +} + +static void _sha512x4( + sha512x4ctx *ctx, + unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + unsigned long long inlen) { + unsigned int i = 0; + + while (inlen - i >= 128) { + sha512_transform4x( + ctx, + in0 + i, + in1 + i, + in2 + i, + in3 + i + ); + ctx->msglen += 1024; + i += 128; + } + + ctx->datalen = (unsigned int)(inlen - i); + memcpy(&ctx->msgblocks[128 * 0], in0 + i, ctx->datalen); + memcpy(&ctx->msgblocks[128 * 1], in1 + i, ctx->datalen); + memcpy(&ctx->msgblocks[128 * 2], in2 + i, ctx->datalen); + memcpy(&ctx->msgblocks[128 * 3], in3 + i, ctx->datalen); + + // Padding + unsigned long curlen; + if (ctx->datalen < 112) { + for (i = 0; i < 4; ++i) { + curlen = ctx->datalen; + ctx->msgblocks[128 * i + curlen++] = 0x80; + while (curlen < 128) { + ctx->msgblocks[128 * i + curlen++] = 0x00; + } + } + } else { + for (i = 0; i < 4; ++i) { + curlen = ctx->datalen; + ctx->msgblocks[128 * i + curlen++] = 0x80; + while (curlen < 128) { + ctx->msgblocks[128 * i + curlen++] = 0x00; + } + } + sha512_transform4x( + ctx, + ctx->msgblocks, + ctx->msgblocks + 128, + ctx->msgblocks + 256, + ctx->msgblocks + 384 + ); + memset(ctx->msgblocks, 0, 4 * 128); + } + + // Add length of the message to each block + ctx->msglen += (unsigned long long)(ctx->datalen) * 8; + for (i = 0; i < 4; i++) { + ctx->msgblocks[128 * i + 127] = (unsigned char)(ctx->msglen); + ctx->msgblocks[128 * i + 126] = (unsigned char)(ctx->msglen >> 8); + ctx->msgblocks[128 * i + 125] = (unsigned char)(ctx->msglen >> 16); + ctx->msgblocks[128 * i + 124] = (unsigned char)(ctx->msglen >> 24); + ctx->msgblocks[128 * i + 123] = (unsigned char)(ctx->msglen >> 32); + ctx->msgblocks[128 * i + 122] = (unsigned char)(ctx->msglen >> 40); + ctx->msgblocks[128 * i + 121] = (unsigned char)(ctx->msglen >> 48); + ctx->msgblocks[128 * i + 120] = (unsigned char)(ctx->msglen >> 56); + memset( &ctx->msgblocks[128 * i + 112], 0, 8 ); + } + sha512_transform4x( + ctx, + ctx->msgblocks, + ctx->msgblocks + 128, + ctx->msgblocks + 256, + ctx->msgblocks + 384 + ); + + // Compute final hash output + transpose(ctx->s); + transpose(ctx->s + 4); + + // Store Hash value + __m256i out[2]; + STORE(out, BYTESWAP(ctx->s[0])); + STORE(out + 1, BYTESWAP(ctx->s[4])); + memcpy(out0, out, 64); + + STORE(out, BYTESWAP(ctx->s[1])); + STORE(out + 1, BYTESWAP(ctx->s[5])); + memcpy(out1, out, 64); + + STORE(out, BYTESWAP(ctx->s[2])); + STORE(out + 1, BYTESWAP(ctx->s[6])); + memcpy(out2, out, 64); + + STORE(out, BYTESWAP(ctx->s[3])); + STORE(out + 1, BYTESWAP(ctx->s[7])); + memcpy(out3, out, 64); +} + + +/** + * Note that inlen should be sufficiently small that it still allows for + * an array to be allocated on the stack. Typically 'in' is merely a seed. + * Outputs outlen number of bytes + */ +void mgf1x4_512(unsigned char *outx4, unsigned long outlen, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + unsigned long inlen) { + PQCLEAN_VLA(unsigned char, inbufx4, 4 * (inlen + 4)); + unsigned char outbuf[4 * 64]; + uint32_t i; + unsigned int j; + + memcpy(inbufx4 + 0 * (inlen + 4), in0, inlen); + memcpy(inbufx4 + 1 * (inlen + 4), in1, inlen); + memcpy(inbufx4 + 2 * (inlen + 4), in2, inlen); + memcpy(inbufx4 + 3 * (inlen + 4), in3, inlen); + + /* While we can fit in at least another full block of SHA512 output.. */ + unsigned long remaining = outlen; + for (i = 0; remaining > 0; i++) { + unsigned long this_step = SPX_SHA512_OUTPUT_BYTES; + if (this_step > remaining) { + this_step = remaining; + } + remaining -= this_step; + for (j = 0; j < 4; j++) { + u32_to_bytes(inbufx4 + inlen + j * (inlen + 4), i); + } + + sha512x4ctx ctx; + sha512_init4x(&ctx); + + _sha512x4( + &ctx, + outbuf + 0 * 64, + outbuf + 1 * 64, + outbuf + 2 * 64, + outbuf + 3 * 64, + inbufx4 + 0 * (inlen + 4), + inbufx4 + 1 * (inlen + 4), + inbufx4 + 2 * (inlen + 4), + inbufx4 + 3 * (inlen + 4), + inlen + 4 + ); + + memcpy(outx4 + 0 * outlen, outbuf + 0 * 64, this_step); + memcpy(outx4 + 1 * outlen, outbuf + 1 * 64, this_step); + memcpy(outx4 + 2 * outlen, outbuf + 2 * 64, this_step); + memcpy(outx4 + 3 * outlen, outbuf + 3 * 64, this_step); + outx4 += this_step; + } +} + +void sha512x4_seeded( + unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const sha512x4ctx *seed, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + unsigned long long inlen) { + sha512x4ctx ctx; + sha512_ctx_clone4x(&ctx, seed); + _sha512x4( + &ctx, + out0, out1, out2, out3, + in0, in1, in2, in3, + inlen + ); +} + +void sha512_ctx_clone4x(sha512x4ctx *out, const sha512x4ctx *in) { + memcpy(out, in, sizeof(sha512x4ctx)); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/sha512x4.h b/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/sha512x4.h new file mode 100644 index 0000000000..9bbe736514 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/sha512x4.h @@ -0,0 +1,58 @@ +#ifndef SHA512AVX_H +#define SHA512AVX_H + +#include +#include + + +#include "params.h" + +typedef struct SHA512state4x { + __m256i s[8]; + unsigned char msgblocks[4 * 128]; + unsigned int datalen; + unsigned long long msglen; +} sha512x4ctx; + +#define sha512_init4x SPX_NAMESPACE(sha512_init4x) +void sha512_init4x(sha512x4ctx *ctx); + +#define sha512_transform4x SPX_NAMESPACE(sha512_transform4x) +void sha512_transform4x( + sha512x4ctx *ctx, + const unsigned char *d0, + const unsigned char *d1, + const unsigned char *d2, + const unsigned char *d3); + + +#define sha512x4_seeded SPX_NAMESPACE(sha512x4_seeded) +void sha512x4_seeded( + unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const sha512x4ctx *seed, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + unsigned long long inlen); + +#define sha512_ctx_clone4x SPX_NAMESPACE(sha512_ctx_clone4x) +void sha512_ctx_clone4x(sha512x4ctx *out, const sha512x4ctx *in); + +/** + * Note that inlen should be sufficiently small that it still allows for + * an array to be allocated on the stack. Typically 'in' is merely a seed. + * Outputs outlen number of bytes + */ +#define mgf1x4_512 SPX_NAMESPACE(mgf1x4_512) +void mgf1x4_512(unsigned char *outx4, unsigned long outlen, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + unsigned long inlen); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/sign.c b/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/sign.c new file mode 100644 index 0000000000..9d0c7d1b22 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/sign.c @@ -0,0 +1,286 @@ +#include +#include +#include + +#include "address.h" +#include "context.h" +#include "fors.h" +#include "hash.h" +#include "merkle.h" +#include "nistapi.h" +#include "params.h" +#include "randombytes.h" +#include "thash.h" +#include "utils.h" +#include "wots.h" + +/* + * Returns the length of a secret key, in bytes + */ +size_t crypto_sign_secretkeybytes(void) { + return CRYPTO_SECRETKEYBYTES; +} + +/* + * Returns the length of a public key, in bytes + */ +size_t crypto_sign_publickeybytes(void) { + return CRYPTO_PUBLICKEYBYTES; +} + +/* + * Returns the length of a signature, in bytes + */ +size_t crypto_sign_bytes(void) { + return CRYPTO_BYTES; +} + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +size_t crypto_sign_seedbytes(void) { + return CRYPTO_SEEDBYTES; +} + +/* + * Generates an SPX key pair given a seed of length + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [PUB_SEED || root] + */ +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed) { + spx_ctx ctx; + + /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ + memcpy(sk, seed, CRYPTO_SEEDBYTES); + + memcpy(pk, sk + 2 * SPX_N, SPX_N); + + memcpy(ctx.pub_seed, pk, SPX_N); + memcpy(ctx.sk_seed, sk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + /* Compute root node of the top-most subtree. */ + merkle_gen_root(sk + 3 * SPX_N, &ctx); + + // cleanup + free_hash_function(&ctx); + + memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); + + return 0; +} + +/* + * Generates an SPX key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [PUB_SEED || root] + */ +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { + uint8_t seed[CRYPTO_SEEDBYTES]; + randombytes(seed, CRYPTO_SEEDBYTES); + crypto_sign_seed_keypair(pk, sk, seed); + + return 0; +} + +/** + * Returns an array containing a detached signature. + */ +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk) { + spx_ctx ctx; + + const uint8_t *sk_prf = sk + SPX_N; + const uint8_t *pk = sk + 2 * SPX_N; + + uint8_t optrand[SPX_N]; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t root[SPX_N]; + uint32_t i; + uint64_t tree; + uint32_t idx_leaf; + uint32_t wots_addr[8] = {0}; + uint32_t tree_addr[8] = {0}; + + memcpy(ctx.sk_seed, sk, SPX_N); + memcpy(ctx.pub_seed, pk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + + /* Optionally, signing can be made non-deterministic using optrand. + This can help counter side-channel attacks that would benefit from + getting a large number of traces when the signer uses the same nodes. */ + randombytes(optrand, SPX_N); + /* Compute the digest randomization value. */ + gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); + + /* Derive the message digest and leaf index from R, PK and M. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; + + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); + + /* Sign the message hash using FORS. */ + fors_sign(sig, root, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); + sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; + + /* Update the indices for the next layer. */ + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; + } + + free_hash_function(&ctx); + + *siglen = SPX_BYTES; + + return 0; +} + +/** + * Verifies a detached signature and message under a given public key. + */ +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk) { + spx_ctx ctx; + const uint8_t *pub_root = pk + SPX_N; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t wots_pk[SPX_WOTS_BYTES]; + uint8_t root[SPX_N]; + uint8_t leaf[SPX_N]; + unsigned int i; + uint64_t tree; + uint32_t idx_leaf; + uint32_t wots_addr[8] = {0}; + uint32_t tree_addr[8] = {0}; + uint32_t wots_pk_addr[8] = {0}; + + if (siglen != SPX_BYTES) { + return -1; + } + + memcpy(ctx.pub_seed, pk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); + + /* Derive the message digest and leaf index from R || PK || M. */ + /* The additional SPX_N is a result of the hash domain separator. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; + + /* Layer correctly defaults to 0, so no need to set_layer_addr */ + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); + + fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + /* For each subtree.. */ + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + copy_keypair_addr(wots_pk_addr, wots_addr); + + /* The WOTS public key is only correct if the signature was correct. */ + /* Initially, root is the FORS pk, but on subsequent iterations it is + the root of the subtree below the currently processed subtree. */ + wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); + sig += SPX_WOTS_BYTES; + + /* Compute the leaf node using the WOTS public key. */ + thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); + + /* Compute the root node of this subtree. */ + compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, + &ctx, tree_addr); + sig += SPX_TREE_HEIGHT * SPX_N; + + /* Update the indices for the next layer. */ + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; + } + + // cleanup + free_hash_function(&ctx); + + /* Check if the root node equals the root node in the public key. */ + if (memcmp(root, pub_root, SPX_N) != 0) { + return -1; + } + + return 0; +} + + +/** + * Returns an array containing the signature followed by the message. + */ +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk) { + size_t siglen; + + crypto_sign_signature(sm, &siglen, m, mlen, sk); + + memmove(sm + SPX_BYTES, m, mlen); + *smlen = siglen + mlen; + + return 0; +} + +/** + * Verifies a given signature-message pair under a given public key. + */ +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk) { + /* The API caller does not necessarily know what size a signature should be + but SPHINCS+ signatures are always exactly SPX_BYTES. */ + if (smlen < SPX_BYTES) { + memset(m, 0, smlen); + *mlen = 0; + return -1; + } + + *mlen = smlen - SPX_BYTES; + + if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { + memset(m, 0, smlen); + *mlen = 0; + return -1; + } + + /* If verification was successful, move the message to the right place. */ + memmove(m, sm + SPX_BYTES, *mlen); + + return 0; +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/thash.h b/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/thash.h new file mode 100644 index 0000000000..8687ccfb4d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/thash.h @@ -0,0 +1,13 @@ +#ifndef SPX_THASH_H +#define SPX_THASH_H + +#include "context.h" +#include "params.h" + +#include + +#define thash SPX_NAMESPACE(thash) +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/thash_sha2_simple.c b/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/thash_sha2_simple.c new file mode 100644 index 0000000000..87badc4d53 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/thash_sha2_simple.c @@ -0,0 +1,53 @@ +#include +#include + +#include "thash.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "sha2.h" +#include "utils.h" + +static void thash_512(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]); + +/** + * Takes an array of inblocks concatenated arrays of SPX_N bytes. + */ +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]) { + if (inblocks > 1) { + thash_512(out, in, inblocks, ctx, addr); + return; + } + + unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES]; + sha256ctx sha2_state; + PQCLEAN_VLA(uint8_t, buf, SPX_SHA256_ADDR_BYTES + inblocks * SPX_N); + + /* Retrieve precomputed state containing pub_seed */ + sha256_inc_ctx_clone(&sha2_state, &ctx->state_seeded); + + memcpy(buf, addr, SPX_SHA256_ADDR_BYTES); + memcpy(buf + SPX_SHA256_ADDR_BYTES, in, inblocks * SPX_N); + + sha256_inc_finalize(outbuf, &sha2_state, buf, SPX_SHA256_ADDR_BYTES + inblocks * SPX_N); + memcpy(out, outbuf, SPX_N); +} + +static void thash_512(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]) { + unsigned char outbuf[SPX_SHA512_OUTPUT_BYTES]; + sha512ctx sha2_state; + PQCLEAN_VLA(uint8_t, buf, SPX_SHA256_ADDR_BYTES + inblocks * SPX_N); + + /* Retrieve precomputed state containing pub_seed */ + sha512_inc_ctx_clone(&sha2_state, &ctx->state_seeded_512); + + memcpy(buf, addr, SPX_SHA256_ADDR_BYTES); + memcpy(buf + SPX_SHA256_ADDR_BYTES, in, inblocks * SPX_N); + + sha512_inc_finalize(outbuf, &sha2_state, buf, SPX_SHA256_ADDR_BYTES + inblocks * SPX_N); + memcpy(out, outbuf, SPX_N); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/thash_sha2_simplex8.c b/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/thash_sha2_simplex8.c new file mode 100644 index 0000000000..9b946f4e4a --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/thash_sha2_simplex8.c @@ -0,0 +1,212 @@ +#include +#include + +#include "thashx8.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "sha2.h" +#include "sha256avx.h" +#include "sha256x8.h" +#include "utils.h" + +#include "sha512x4.h" + +static void thashx8_512( + unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, + unsigned int inblocks, + const spx_ctx *ctx, + uint32_t addrx8[8 * 8] +); + +/** + * 8-way parallel version of thash; takes 8x as much input and output + */ +void thashx8(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addrx8[8 * 8]) { + if (inblocks > 1) { + thashx8_512( + out0, out1, out2, out3, out4, out5, out6, out7, + in0, in1, in2, in3, in4, in5, in6, in7, + inblocks, ctx, addrx8); + return; + } + PQCLEAN_VLA(unsigned char, bufx8, 8 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)); + unsigned char outbufx8[8 * SPX_SHA256_OUTPUT_BYTES]; + unsigned int i; + + for (i = 0; i < 8; i++) { + memcpy(bufx8 + i * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + addrx8 + i * 8, SPX_SHA256_ADDR_BYTES); + } + + memcpy(bufx8 + SPX_SHA256_ADDR_BYTES + + 0 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), in0, inblocks * SPX_N); + memcpy(bufx8 + SPX_SHA256_ADDR_BYTES + + 1 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), in1, inblocks * SPX_N); + memcpy(bufx8 + SPX_SHA256_ADDR_BYTES + + 2 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), in2, inblocks * SPX_N); + memcpy(bufx8 + SPX_SHA256_ADDR_BYTES + + 3 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), in3, inblocks * SPX_N); + memcpy(bufx8 + SPX_SHA256_ADDR_BYTES + + 4 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), in4, inblocks * SPX_N); + memcpy(bufx8 + SPX_SHA256_ADDR_BYTES + + 5 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), in5, inblocks * SPX_N); + memcpy(bufx8 + SPX_SHA256_ADDR_BYTES + + 6 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), in6, inblocks * SPX_N); + memcpy(bufx8 + SPX_SHA256_ADDR_BYTES + + 7 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), in7, inblocks * SPX_N); + + sha256x8_seeded( + /* out */ + outbufx8 + 0 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 1 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 2 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 3 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 4 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 5 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 6 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 7 * SPX_SHA256_OUTPUT_BYTES, + + /* seed */ + &ctx->statex8_seeded, + + /* in */ + bufx8 + 0 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + 1 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + 2 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + 3 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + 4 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + 5 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + 6 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + 7 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N /* len */ + ); + + memcpy(out0, outbufx8 + 0 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out1, outbufx8 + 1 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out2, outbufx8 + 2 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out3, outbufx8 + 3 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out4, outbufx8 + 4 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out5, outbufx8 + 5 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out6, outbufx8 + 6 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out7, outbufx8 + 7 * SPX_SHA256_OUTPUT_BYTES, SPX_N); +} + +/** + * 2x4-way parallel version of thash; this is for the uses of thash that are + * based on SHA-512 + */ +static void thashx8_512( + unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, + unsigned int inblocks, + const spx_ctx *ctx, + uint32_t addrx8[8 * 8]) { + PQCLEAN_VLA(unsigned char, bufx8, 8 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)); + unsigned char outbuf[4 * SPX_SHA512_OUTPUT_BYTES]; + unsigned int i; + + for (i = 0; i < 8; i++) { + memcpy(bufx8 + i * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + addrx8 + i * 8, SPX_SHA256_ADDR_BYTES); + } + + memcpy(bufx8 + SPX_SHA256_ADDR_BYTES + + 0 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), in0, inblocks * SPX_N); + memcpy(bufx8 + SPX_SHA256_ADDR_BYTES + + 1 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), in1, inblocks * SPX_N); + memcpy(bufx8 + SPX_SHA256_ADDR_BYTES + + 2 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), in2, inblocks * SPX_N); + memcpy(bufx8 + SPX_SHA256_ADDR_BYTES + + 3 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), in3, inblocks * SPX_N); + memcpy(bufx8 + SPX_SHA256_ADDR_BYTES + + 4 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), in4, inblocks * SPX_N); + memcpy(bufx8 + SPX_SHA256_ADDR_BYTES + + 5 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), in5, inblocks * SPX_N); + memcpy(bufx8 + SPX_SHA256_ADDR_BYTES + + 6 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), in6, inblocks * SPX_N); + memcpy(bufx8 + SPX_SHA256_ADDR_BYTES + + 7 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), in7, inblocks * SPX_N); + + sha512x4_seeded( + outbuf + 0 * SPX_SHA512_OUTPUT_BYTES, + outbuf + 1 * SPX_SHA512_OUTPUT_BYTES, + outbuf + 2 * SPX_SHA512_OUTPUT_BYTES, + outbuf + 3 * SPX_SHA512_OUTPUT_BYTES, + &ctx->statex4_seeded_512, /* seed */ + bufx8 + 0 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), /* in */ + bufx8 + 1 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + 2 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + 3 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N /* len */ + ); + + memcpy(out0, outbuf + 0 * SPX_SHA512_OUTPUT_BYTES, SPX_N); + memcpy(out1, outbuf + 1 * SPX_SHA512_OUTPUT_BYTES, SPX_N); + memcpy(out2, outbuf + 2 * SPX_SHA512_OUTPUT_BYTES, SPX_N); + memcpy(out3, outbuf + 3 * SPX_SHA512_OUTPUT_BYTES, SPX_N); + + sha512x4_seeded( + outbuf + 0 * SPX_SHA512_OUTPUT_BYTES, + outbuf + 1 * SPX_SHA512_OUTPUT_BYTES, + outbuf + 2 * SPX_SHA512_OUTPUT_BYTES, + outbuf + 3 * SPX_SHA512_OUTPUT_BYTES, + &ctx->statex4_seeded_512, /* seed */ + bufx8 + 4 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), /* in */ + bufx8 + 5 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + 6 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + 7 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N /* len */ + ); + + memcpy(out4, outbuf + 0 * SPX_SHA512_OUTPUT_BYTES, SPX_N); + memcpy(out5, outbuf + 1 * SPX_SHA512_OUTPUT_BYTES, SPX_N); + memcpy(out6, outbuf + 2 * SPX_SHA512_OUTPUT_BYTES, SPX_N); + memcpy(out7, outbuf + 3 * SPX_SHA512_OUTPUT_BYTES, SPX_N); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/thashx8.h b/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/thashx8.h new file mode 100644 index 0000000000..c02fe9cf3e --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/thashx8.h @@ -0,0 +1,28 @@ +#ifndef SPX_THASHX8_H +#define SPX_THASHX8_H + +#include + +#include "context.h" +#include "params.h" + +#define thashx8 SPX_NAMESPACE(thashx8) +void thashx8(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addrx8[8 * 8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/utils.c b/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/utils.c new file mode 100644 index 0000000000..177b541fb9 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/utils.c @@ -0,0 +1,148 @@ +#include + +#include "utils.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "thash.h" + +/** + * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. + */ +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in) { + int i; + + /* Iterate over out in decreasing order, for big-endianness. */ + for (i = (signed int)outlen - 1; i >= 0; i--) { + out[i] = in & 0xff; + in = in >> 8; + } +} + +void u32_to_bytes(unsigned char *out, uint32_t in) { + out[0] = (unsigned char)(in >> 24); + out[1] = (unsigned char)(in >> 16); + out[2] = (unsigned char)(in >> 8); + out[3] = (unsigned char)in; +} + +/** + * Converts the inlen bytes in 'in' from big-endian byte order to an integer. + */ +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { + unsigned long long retval = 0; + unsigned int i; + + for (i = 0; i < inlen; i++) { + retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); + } + return retval; +} + +/** + * Computes a root node given a leaf and an auth path. + * Expects address to be complete other than the tree_height and tree_index. + */ +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]) { + uint32_t i; + unsigned char buffer[2 * SPX_N]; + + /* If leaf_idx is odd (last bit = 1), current path element is a right child + and auth_path has to go left. Otherwise it is the other way around. */ + if (leaf_idx & 1) { + memcpy(buffer + SPX_N, leaf, SPX_N); + memcpy(buffer, auth_path, SPX_N); + } else { + memcpy(buffer, leaf, SPX_N); + memcpy(buffer + SPX_N, auth_path, SPX_N); + } + auth_path += SPX_N; + + for (i = 0; i < tree_height - 1; i++) { + leaf_idx >>= 1; + idx_offset >>= 1; + /* Set the address of the node we're creating. */ + set_tree_height(addr, i + 1); + set_tree_index(addr, leaf_idx + idx_offset); + + /* Pick the right or left neighbor, depending on parity of the node. */ + if (leaf_idx & 1) { + thash(buffer + SPX_N, buffer, 2, ctx, addr); + memcpy(buffer, auth_path, SPX_N); + } else { + thash(buffer, buffer, 2, ctx, addr); + memcpy(buffer + SPX_N, auth_path, SPX_N); + } + auth_path += SPX_N; + } + + /* The last iteration is exceptional; we do not copy an auth_path node. */ + leaf_idx >>= 1; + idx_offset >>= 1; + set_tree_height(addr, tree_height); + set_tree_index(addr, leaf_idx + idx_offset); + thash(root, buffer, 2, ctx, addr); +} + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx * /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]) { + PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); + PQCLEAN_VLA(unsigned int, heights, tree_height + 1); + unsigned int offset = 0; + uint32_t idx; + uint32_t tree_idx; + + for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { + /* Add the next leaf node to the stack. */ + gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); + offset++; + heights[offset - 1] = 0; + + /* If this is a node we need for the auth path.. */ + if ((leaf_idx ^ 0x1) == idx) { + memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); + } + + /* While the top-most nodes are of equal height.. */ + while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { + /* Compute index of the new node, in the next layer. */ + tree_idx = (idx >> (heights[offset - 1] + 1)); + + /* Set the address of the node we're creating. */ + set_tree_height(tree_addr, heights[offset - 1] + 1); + set_tree_index(tree_addr, + tree_idx + (idx_offset >> (heights[offset - 1] + 1))); + /* Hash the top-most nodes from the stack together. */ + thash(stack + (offset - 2)*SPX_N, + stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); + offset--; + /* Note that the top-most node is now one layer higher. */ + heights[offset - 1]++; + + /* If this is a node we need for the auth path.. */ + if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { + memcpy(auth_path + heights[offset - 1]*SPX_N, + stack + (offset - 1)*SPX_N, SPX_N); + } + } + } + memcpy(root, stack, SPX_N); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/utils.h b/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/utils.h new file mode 100644 index 0000000000..64f5d5a53a --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/utils.h @@ -0,0 +1,58 @@ +#ifndef SPX_UTILS_H +#define SPX_UTILS_H + +#include + +#include "compat.h" +#include "context.h" +#include "params.h" + + +/* To support MSVC use alloca() instead of VLAs. See #20. */ + + +/** + * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. + */ +#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in); +#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) +void u32_to_bytes(unsigned char *out, uint32_t in); + +/** + * Converts the inlen bytes in 'in' from big-endian byte order to an integer. + */ +#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); + +/** + * Computes a root node given a leaf and an auth path. + * Expects address to be complete other than the tree_height and tree_index. + */ +#define compute_root SPX_NAMESPACE(compute_root) +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]); + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +#define treehash SPX_NAMESPACE(treehash) +void treehash(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx *ctx /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]); + + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/utilsx8.c b/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/utilsx8.c new file mode 100644 index 0000000000..f044b9595d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/utilsx8.c @@ -0,0 +1,146 @@ +#include + +#include "utils.h" +#include "utilsx8.h" + +#include "address.h" +#include "params.h" +#include "thashx8.h" + +/* + * Generate the entire Merkle tree, computing the authentication path for leaf_idx, + * and the resulting root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) + * + * This expects tree_addrx8 to be initialized to 8 parallel addr structures for + * the Merkle tree nodes + * + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + * + * This works by using the standard Merkle tree building algorithm, except + * that each 'node' tracked is actually 8 consecutive nodes in the real tree. + * When we combine two logical nodes ABCDEFGH and STUVWXYZ, we perform the H + * operation on adjacent real nodes, forming the parent logical node + * (AB)(CD)(EF)(GH)(ST)(UV)(WX)(YZ) + * + * When we get to the top three levels of the real tree (where there is only + * one logical node), we continue this operation three more times; the right + * most real node will by the actual root (and the other 7 nodes will be + * garbage). We follow the same thashx8 logic so that the 'extract + * authentication path components' part of the loop is still executed (and + * to simplify the code somewhat) + * + * This currently assumes tree_height >= 3; I suspect that doing an adjusting + * idx, addr_idx on the gen_leafx8 call if tree_height < 3 would fix it; since + * we don't actually use such short trees, I haven't bothered + */ +void treehashx8(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, + uint32_t tree_height, + void (*gen_leafx8)( + unsigned char * /* Where to write the leaves */, + const spx_ctx *, + uint32_t idx, void *info), + uint32_t tree_addrx8[8 * 8], + void *info) { + /* This is where we keep the intermediate nodes */ + PQCLEAN_VLA(unsigned char, stackx8, tree_height * 8 * SPX_N); + uint32_t left_adj = 0, prev_left_adj = 0; /* When we're doing the top 3 */ + /* levels, the left-most part of the tree isn't at the beginning */ + /* of current[]. These give the offset of the actual start */ + + uint32_t idx; + uint32_t max_idx = ((uint32_t)1 << (tree_height - 3)) - 1; + for (idx = 0;; idx++) { + unsigned char current[8 * SPX_N]; /* Current logical node */ + gen_leafx8( current, ctx, 8 * idx + idx_offset, + info ); + + /* Now combine the freshly generated right node with previously */ + /* generated left ones */ + uint32_t internal_idx_offset = idx_offset; + uint32_t internal_idx = idx; + uint32_t internal_leaf = leaf_idx; + uint32_t h; /* The height we are in the Merkle tree */ + for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { + + /* Special processing if we're at the top of the tree */ + if (h >= tree_height - 3) { + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[7 * SPX_N], SPX_N ); + return; + } + /* The tree indexing logic is a bit off in this case */ + /* Adjust it so that the left-most node of the part of */ + /* the tree that we're processing has index 0 */ + prev_left_adj = left_adj; + left_adj = (uint32_t)(8 - (1 << (tree_height - h - 1))); + } + + /* Check if we hit the top of the tree */ + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[7 * SPX_N], SPX_N ); + return; + } + + /* + * Check if one of the nodes we have is a part of the + * authentication path; if it is, write it out + */ + if ((((internal_idx << 3) ^ internal_leaf) & ~0x7U) == 0) { + memcpy( &auth_path[ h * SPX_N ], + ¤t[(((internal_leaf & 7) ^ 1) + prev_left_adj) * SPX_N], + SPX_N ); + } + + /* + * Check if we're at a left child; if so, stop going up the stack + * Exception: if we've reached the end of the tree, keep on going + * (so we combine the last 8 nodes into the one root node in three + * more iterations) + */ + if ((internal_idx & 1) == 0 && idx < max_idx) { + break; + } + + /* Ok, we're at a right node (or doing the top 3 levels) */ + /* Now combine the left and right logical nodes together */ + + /* Set the address of the node we're creating. */ + uint32_t j; + internal_idx_offset >>= 1; + for (j = 0; j < 8; j++) { + set_tree_height(tree_addrx8 + j * 8, h + 1); + set_tree_index(tree_addrx8 + j * 8, + (8 / 2) * (internal_idx & ~1U) + j - left_adj + internal_idx_offset ); + } + unsigned char *left = &stackx8[h * 8 * SPX_N]; + thashx8( ¤t[0 * SPX_N], + ¤t[1 * SPX_N], + ¤t[2 * SPX_N], + ¤t[3 * SPX_N], + ¤t[4 * SPX_N], + ¤t[5 * SPX_N], + ¤t[6 * SPX_N], + ¤t[7 * SPX_N], + &left [0 * SPX_N], + &left [2 * SPX_N], + &left [4 * SPX_N], + &left [6 * SPX_N], + ¤t[0 * SPX_N], + ¤t[2 * SPX_N], + ¤t[4 * SPX_N], + ¤t[6 * SPX_N], + 2, ctx, tree_addrx8); + } + + /* We've hit a left child; save the current for when we get the */ + /* corresponding right right */ + memcpy( &stackx8[h * 8 * SPX_N], current, 8 * SPX_N); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/utilsx8.h b/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/utilsx8.h new file mode 100644 index 0000000000..806d1e85be --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/utilsx8.h @@ -0,0 +1,29 @@ +#ifndef SPX_UTILSX8_H +#define SPX_UTILSX8_H + +#include + +#include "params.h" + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + * + * This implementation uses AVX to compute internal nodes 8 at a time (in + * parallel) + */ +#define treehashx8 SPX_NAMESPACE(treehashx8) +void treehashx8(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leafx8)( + unsigned char * /* Where to write the leaves */, + const spx_ctx * /* ctx */, + uint32_t addr_idx, void *info), + uint32_t tree_addrx8[8 * 8], void *info); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/wots.c b/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/wots.c new file mode 100644 index 0000000000..689baf4db9 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/wots.c @@ -0,0 +1,291 @@ +#include +#include + +#include "wots.h" + +#include "address.h" +#include "hash.h" +#include "hashx8.h" +#include "params.h" +#include "thash.h" +#include "thashx8.h" +#include "utils.h" +#include "utilsx8.h" +#include "wotsx8.h" + +// TODO clarify address expectations, and make them more uniform. +// TODO i.e. do we expect types to be set already? +// TODO and do we expect modifications or copies? + +/** + * Computes up the chains + */ +static void gen_chains( + unsigned char *out, + const unsigned char *in, + unsigned int start[SPX_WOTS_LEN], + const unsigned int steps[SPX_WOTS_LEN], + const spx_ctx *ctx, + uint32_t addr[8]) { + uint32_t i, j, k, idx, watching; + int done; + unsigned char empty[SPX_N]; + unsigned char *bufs[8]; + uint32_t addrs[8 * 8]; + + int l; + uint16_t counts[SPX_WOTS_W] = { 0 }; + uint16_t idxs[SPX_WOTS_LEN]; + uint16_t total, newTotal; + + /* set addrs = {addr, addr, ..., addr} */ + for (j = 0; j < 8; j++) { + memcpy(addrs + j * 8, addr, sizeof(uint32_t) * 8); + } + + /* Initialize out with the value at position 'start'. */ + memcpy(out, in, SPX_WOTS_LEN * SPX_N); + + /* Sort the chains in reverse order by steps using counting sort. */ + for (i = 0; i < SPX_WOTS_LEN; i++) { + counts[steps[i]]++; + } + total = 0; + for (l = SPX_WOTS_W - 1; l >= 0; l--) { + newTotal = counts[l] + total; + counts[l] = total; + total = newTotal; + } + for (i = 0; i < SPX_WOTS_LEN; i++) { + idxs[counts[steps[i]]] = (uint16_t)i; + counts[steps[i]]++; + } + + /* We got our work cut out for us: do it! */ + for (i = 0; i < SPX_WOTS_LEN; i += 8) { + for (j = 0; j < 8 && i + j < SPX_WOTS_LEN; j++) { + idx = idxs[i + j]; + set_chain_addr(addrs + j * 8, idx); + bufs[j] = out + SPX_N * idx; + } + + /* As the chains are sorted in reverse order, we know that the first + * chain is the longest and the last one is the shortest. We keep + * an eye on whether the last chain is done and then on the one before, + * et cetera. */ + watching = 7; + done = 0; + while (i + watching >= SPX_WOTS_LEN) { + bufs[watching] = &empty[0]; + watching--; + } + + for (k = 0;; k++) { + while (k == steps[idxs[i + watching]]) { + bufs[watching] = &empty[0]; + if (watching == 0) { + done = 1; + break; + } + watching--; + } + if (done) { + break; + } + for (j = 0; j < watching + 1; j++) { + set_hash_addr(addrs + j * 8, k + start[idxs[i + j]]); + } + + thashx8(bufs[0], bufs[1], bufs[2], bufs[3], + bufs[4], bufs[5], bufs[6], bufs[7], + bufs[0], bufs[1], bufs[2], bufs[3], + bufs[4], bufs[5], bufs[6], bufs[7], 1, ctx, addrs); + } + } +} + +/** + * base_w algorithm as described in draft. + * Interprets an array of bytes as integers in base w. + * This only works when log_w is a divisor of 8. + */ +static void base_w(unsigned int *output, const int out_len, + const unsigned char *input) { + int in = 0; + int out = 0; + unsigned char total = 0; + int bits = 0; + int consumed; + + for (consumed = 0; consumed < out_len; consumed++) { + if (bits == 0) { + total = input[in]; + in++; + bits += 8; + } + bits -= SPX_WOTS_LOGW; + output[out] = (total >> bits) & (SPX_WOTS_W - 1); + out++; + } +} + +/* Computes the WOTS+ checksum over a message (in base_w). */ +static void wots_checksum(unsigned int *csum_base_w, + const unsigned int *msg_base_w) { + unsigned int csum = 0; + unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; + unsigned int i; + + /* Compute checksum. */ + for (i = 0; i < SPX_WOTS_LEN1; i++) { + csum += SPX_WOTS_W - 1 - msg_base_w[i]; + } + + /* Convert checksum to base_w. */ + /* Make sure expected empty zero bits are the least significant bits. */ + csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); + ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); + base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); +} + +/* Takes a message and derives the matching chain lengths. */ +void chain_lengths(unsigned int *lengths, const unsigned char *msg) { + base_w(lengths, SPX_WOTS_LEN1, msg); + wots_checksum(lengths + SPX_WOTS_LEN1, lengths); +} + +/** + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. + * + * Writes the computed public key to 'pk'. + */ +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]) { + unsigned int steps[SPX_WOTS_LEN]; + unsigned int start[SPX_WOTS_LEN]; + uint32_t i; + + chain_lengths(start, msg); + + for (i = 0; i < SPX_WOTS_LEN; i++) { + steps[i] = SPX_WOTS_W - 1 - start[i]; + } + + gen_chains(pk, sig, start, steps, ctx, addr); +} + +/* + * This generates 8 sequential WOTS public keys + * It also generates the WOTS signature if leaf_info indicates + * that we're signing with one of these WOTS keys + */ +void wots_gen_leafx8(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info) { + struct leaf_info_x8 *info = v_info; + uint32_t *leaf_addr = info->leaf_addr; + uint32_t *pk_addr = info->pk_addr; + unsigned int i, j, k; + unsigned char pk_buffer[ 8 * SPX_WOTS_BYTES ]; + unsigned wots_offset = SPX_WOTS_BYTES; + unsigned char *buffer; + uint32_t wots_k_mask; + unsigned wots_sign_index; + + if (((leaf_idx ^ info->wots_sign_leaf) & ~7U) == 0) { + /* We're traversing the leaf that's signing; generate the WOTS */ + /* signature */ + wots_k_mask = 0; + wots_sign_index = info->wots_sign_leaf & 7; /* Which of of the 8 */ + /* slots do the signatures come from */ + } else { + /* Nope, we're just generating pk's; turn off the signature logic */ + wots_k_mask = ~0U; + wots_sign_index = 0; + } + + for (j = 0; j < 8; j++) { + set_keypair_addr( leaf_addr + j * 8, leaf_idx + j ); + set_keypair_addr( pk_addr + j * 8, leaf_idx + j ); + } + + for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { + uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k */ + /* to the step if we're generating a signature, ~0 if we're not */ + + /* Start with the secret seed */ + for (j = 0; j < 8; j++) { + set_chain_addr(leaf_addr + j * 8, i); + set_hash_addr(leaf_addr + j * 8, 0); + set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTSPRF); + } + prf_addrx8(buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + buffer + 2 * wots_offset, + buffer + 3 * wots_offset, + buffer + 4 * wots_offset, + buffer + 5 * wots_offset, + buffer + 6 * wots_offset, + buffer + 7 * wots_offset, + ctx, leaf_addr); + + for (j = 0; j < 8; j++) { + set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTS); + } + + /* Iterate down the WOTS chain */ + for (k = 0;; k++) { + /* Check if one of the values we have needs to be saved as a */ + /* part of the WOTS signature */ + if (k == wots_k) { + memcpy( info->wots_sig + i * SPX_N, + buffer + wots_sign_index * wots_offset, SPX_N ); + } + + /* Check if we hit the top of the chain */ + if (k == SPX_WOTS_W - 1) { + break; + } + + /* Iterate one step on all 8 chains */ + for (j = 0; j < 8; j++) { + set_hash_addr(leaf_addr + j * 8, k); + } + thashx8(buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + buffer + 2 * wots_offset, + buffer + 3 * wots_offset, + buffer + 4 * wots_offset, + buffer + 5 * wots_offset, + buffer + 6 * wots_offset, + buffer + 7 * wots_offset, + buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + buffer + 2 * wots_offset, + buffer + 3 * wots_offset, + buffer + 4 * wots_offset, + buffer + 5 * wots_offset, + buffer + 6 * wots_offset, + buffer + 7 * wots_offset, 1, ctx, leaf_addr); + } + } + + /* Do the final thash to generate the public keys */ + thashx8(dest + 0 * SPX_N, + dest + 1 * SPX_N, + dest + 2 * SPX_N, + dest + 3 * SPX_N, + dest + 4 * SPX_N, + dest + 5 * SPX_N, + dest + 6 * SPX_N, + dest + 7 * SPX_N, + pk_buffer + 0 * wots_offset, + pk_buffer + 1 * wots_offset, + pk_buffer + 2 * wots_offset, + pk_buffer + 3 * wots_offset, + pk_buffer + 4 * wots_offset, + pk_buffer + 5 * wots_offset, + pk_buffer + 6 * wots_offset, + pk_buffer + 7 * wots_offset, SPX_WOTS_LEN, ctx, pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/wots.h b/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/wots.h new file mode 100644 index 0000000000..4e7692eeef --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/wots.h @@ -0,0 +1,25 @@ +#ifndef SPX_WOTS_H +#define SPX_WOTS_H + +#include + +#include "context.h" +#include "params.h" + +/** + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. + * + * Writes the computed public key to 'pk'. + */ +#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]); + +/* + * Compute the chain lengths needed for a given message hash + */ +#define chain_lengths SPX_NAMESPACE(chain_lengths) +void chain_lengths(unsigned int *lengths, const unsigned char *msg); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/wotsx8.h b/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/wotsx8.h new file mode 100644 index 0000000000..10866efb35 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_avx2/wotsx8.h @@ -0,0 +1,42 @@ +#ifndef WOTSX8_H_ +#define WOTSX8_H_ + +#include + +#include "context.h" +#include "params.h" + +/* + * This is here to provide an interface to the internal wots_gen_leafx8 + * routine. While this routine is not referenced in the package outside of + * wots.c, it is called from the stand-alone benchmark code to characterize + * the performance + */ +struct leaf_info_x8 { + unsigned char *wots_sig; + uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ + uint32_t *wots_steps; + uint32_t leaf_addr[8 * 8]; + uint32_t pk_addr[8 * 8]; +}; + +/* Macro to set the leaf_info to something 'benign', that is, it would */ +/* run with the same time as it does during the real signing process */ +/* Used only by the benchmark code */ +#define INITIALIZE_LEAF_INFO_X8(info, addr, step_buffer) { \ + (info).wots_sig = 0; \ + (info).wots_sign_leaf = ~0; \ + (info).wots_steps = step_buffer; \ + int i; \ + for (i=0; i<8; i++) { \ + memcpy( &(info).leaf_addr[8*i], addr, 32 ); \ + memcpy( &(info).pk_addr[8*i], addr, 32 ); \ + } \ + } + +#define wots_gen_leafx8 SPX_NAMESPACE(wots_gen_leafx8) +void wots_gen_leafx8(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info); + +#endif /* WOTSX8_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_clean/LICENSE b/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_clean/LICENSE new file mode 100644 index 0000000000..670154e353 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_clean/LICENSE @@ -0,0 +1,116 @@ +CC0 1.0 Universal + +Statement of Purpose + +The laws of most jurisdictions throughout the world automatically confer +exclusive Copyright and Related Rights (defined below) upon the creator and +subsequent owner(s) (each and all, an "owner") of an original work of +authorship and/or a database (each, a "Work"). + +Certain owners wish to permanently relinquish those rights to a Work for the +purpose of contributing to a commons of creative, cultural and scientific +works ("Commons") that the public can reliably and without fear of later +claims of infringement build upon, modify, incorporate in other works, reuse +and redistribute as freely as possible in any form whatsoever and for any +purposes, including without limitation commercial purposes. These owners may +contribute to the Commons to promote the ideal of a free culture and the +further production of creative, cultural and scientific works, or to gain +reputation or greater distribution for their Work in part through the use and +efforts of others. + +For these and/or other purposes and motivations, and without any expectation +of additional consideration or compensation, the person associating CC0 with a +Work (the "Affirmer"), to the extent that he or she is an owner of Copyright +and Related Rights in the Work, voluntarily elects to apply CC0 to the Work +and publicly distribute the Work under its terms, with knowledge of his or her +Copyright and Related Rights in the Work and the meaning and intended legal +effect of CC0 on those rights. + +1. Copyright and Related Rights. A Work made available under CC0 may be +protected by copyright and related or neighboring rights ("Copyright and +Related Rights"). Copyright and Related Rights include, but are not limited +to, the following: + + i. the right to reproduce, adapt, distribute, perform, display, communicate, + and translate a Work; + + ii. moral rights retained by the original author(s) and/or performer(s); + + iii. publicity and privacy rights pertaining to a person's image or likeness + depicted in a Work; + + iv. rights protecting against unfair competition in regards to a Work, + subject to the limitations in paragraph 4(a), below; + + v. rights protecting the extraction, dissemination, use and reuse of data in + a Work; + + vi. database rights (such as those arising under Directive 96/9/EC of the + European Parliament and of the Council of 11 March 1996 on the legal + protection of databases, and under any national implementation thereof, + including any amended or successor version of such directive); and + + vii. other similar, equivalent or corresponding rights throughout the world + based on applicable law or treaty, and any national implementations thereof. + +2. Waiver. To the greatest extent permitted by, but not in contravention of, +applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and +unconditionally waives, abandons, and surrenders all of Affirmer's Copyright +and Related Rights and associated claims and causes of action, whether now +known or unknown (including existing as well as future claims and causes of +action), in the Work (i) in all territories worldwide, (ii) for the maximum +duration provided by applicable law or treaty (including future time +extensions), (iii) in any current or future medium and for any number of +copies, and (iv) for any purpose whatsoever, including without limitation +commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes +the Waiver for the benefit of each member of the public at large and to the +detriment of Affirmer's heirs and successors, fully intending that such Waiver +shall not be subject to revocation, rescission, cancellation, termination, or +any other legal or equitable action to disrupt the quiet enjoyment of the Work +by the public as contemplated by Affirmer's express Statement of Purpose. + +3. Public License Fallback. Should any part of the Waiver for any reason be +judged legally invalid or ineffective under applicable law, then the Waiver +shall be preserved to the maximum extent permitted taking into account +Affirmer's express Statement of Purpose. In addition, to the extent the Waiver +is so judged Affirmer hereby grants to each affected person a royalty-free, +non transferable, non sublicensable, non exclusive, irrevocable and +unconditional license to exercise Affirmer's Copyright and Related Rights in +the Work (i) in all territories worldwide, (ii) for the maximum duration +provided by applicable law or treaty (including future time extensions), (iii) +in any current or future medium and for any number of copies, and (iv) for any +purpose whatsoever, including without limitation commercial, advertising or +promotional purposes (the "License"). The License shall be deemed effective as +of the date CC0 was applied by Affirmer to the Work. Should any part of the +License for any reason be judged legally invalid or ineffective under +applicable law, such partial invalidity or ineffectiveness shall not +invalidate the remainder of the License, and in such case Affirmer hereby +affirms that he or she will not (i) exercise any of his or her remaining +Copyright and Related Rights in the Work or (ii) assert any associated claims +and causes of action with respect to the Work, in either case contrary to +Affirmer's express Statement of Purpose. + +4. Limitations and Disclaimers. + + a. No trademark or patent rights held by Affirmer are waived, abandoned, + surrendered, licensed or otherwise affected by this document. + + b. Affirmer offers the Work as-is and makes no representations or warranties + of any kind concerning the Work, express, implied, statutory or otherwise, + including without limitation warranties of title, merchantability, fitness + for a particular purpose, non infringement, or the absence of latent or + other defects, accuracy, or the present or absence of errors, whether or not + discoverable, all to the greatest extent permissible under applicable law. + + c. Affirmer disclaims responsibility for clearing rights of other persons + that may apply to the Work or any use thereof, including without limitation + any person's Copyright and Related Rights in the Work. Further, Affirmer + disclaims responsibility for obtaining any necessary consents, permissions + or other rights required for any use of the Work. + + d. Affirmer understands and acknowledges that Creative Commons is not a + party to this document and has no duty or obligation with respect to this + CC0 or use of the Work. + +For more information, please see + diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_clean/address.c b/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_clean/address.c new file mode 100644 index 0000000000..d49d9f3b6b --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_clean/address.c @@ -0,0 +1,95 @@ +#include +#include + +#include "address.h" +#include "params.h" +#include "utils.h" + +/* + * Specify which level of Merkle tree (the "layer") we're working on + */ +void set_layer_addr(uint32_t addr[8], uint32_t layer) { + ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; +} + +/* + * Specify which Merkle tree within the level (the "tree address") we're working on + */ +void set_tree_addr(uint32_t addr[8], uint64_t tree) { + ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); +} + +/* + * Specify the reason we'll use this address structure for, that is, what + * hash will we compute with it. This is used so that unrelated types of + * hashes don't accidentally get the same address structure. The type will be + * one of the SPX_ADDR_TYPE constants + */ +void set_type(uint32_t addr[8], uint32_t type) { + ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; +} + +/* + * Copy the layer and tree fields of the address structure. This is used + * when we're doing multiple types of hashes within the same Merkle tree + */ +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); +} + +/* These functions are used for OTS addresses. */ + +/* + * Specify which Merkle leaf we're working on; that is, which OTS keypair + * we're talking about. + */ +void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { + /* We have > 256 OTS at the bottom of the Merkle tree; to specify */ + /* which one, we'd need to express it in two bytes */ + ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR2] = (unsigned char)(keypair >> 8); + ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; +} + +/* + * Copy the layer, tree and keypair fields of the address structure. This is + * used when we're doing multiple things within the same OTS keypair + */ +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); + ((unsigned char *)out)[SPX_OFFSET_KP_ADDR2] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR2]; + ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; +} + +/* + * Specify which Merkle chain within the OTS we're working with + * (the chain address) + */ +void set_chain_addr(uint32_t addr[8], uint32_t chain) { + ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; +} + +/* + * Specify where in the Merkle chain we are +* (the hash address) + */ +void set_hash_addr(uint32_t addr[8], uint32_t hash) { + ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; +} + +/* These functions are used for all hash tree addresses (including FORS). */ + +/* + * Specify the height of the node in the Merkle/FORS tree we are in + * (the tree height) + */ +void set_tree_height(uint32_t addr[8], uint32_t tree_height) { + ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; +} + +/* + * Specify the distance from the left edge of the node in the Merkle/FORS tree + * (the tree index) + */ +void set_tree_index(uint32_t addr[8], uint32_t tree_index) { + u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_clean/address.h b/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_clean/address.h new file mode 100644 index 0000000000..24a84eb40c --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_clean/address.h @@ -0,0 +1,52 @@ +#ifndef SPX_ADDRESS_H +#define SPX_ADDRESS_H + +#include + +#include "params.h" + +/* The hash types that are passed to set_type */ +#define SPX_ADDR_TYPE_WOTS 0 +#define SPX_ADDR_TYPE_WOTSPK 1 +#define SPX_ADDR_TYPE_HASHTREE 2 +#define SPX_ADDR_TYPE_FORSTREE 3 +#define SPX_ADDR_TYPE_FORSPK 4 +#define SPX_ADDR_TYPE_WOTSPRF 5 +#define SPX_ADDR_TYPE_FORSPRF 6 + +#define set_layer_addr SPX_NAMESPACE(set_layer_addr) +void set_layer_addr(uint32_t addr[8], uint32_t layer); + +#define set_tree_addr SPX_NAMESPACE(set_tree_addr) +void set_tree_addr(uint32_t addr[8], uint64_t tree); + +#define set_type SPX_NAMESPACE(set_type) +void set_type(uint32_t addr[8], uint32_t type); + +/* Copies the layer and tree part of one address into the other */ +#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); + +/* These functions are used for WOTS and FORS addresses. */ + +#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) +void set_keypair_addr(uint32_t addr[8], uint32_t keypair); + +#define set_chain_addr SPX_NAMESPACE(set_chain_addr) +void set_chain_addr(uint32_t addr[8], uint32_t chain); + +#define set_hash_addr SPX_NAMESPACE(set_hash_addr) +void set_hash_addr(uint32_t addr[8], uint32_t hash); + +#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); + +/* These functions are used for all hash tree addresses (including FORS). */ + +#define set_tree_height SPX_NAMESPACE(set_tree_height) +void set_tree_height(uint32_t addr[8], uint32_t tree_height); + +#define set_tree_index SPX_NAMESPACE(set_tree_index) +void set_tree_index(uint32_t addr[8], uint32_t tree_index); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_clean/api.h b/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_clean/api.h new file mode 100644 index 0000000000..91fed8cd69 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_clean/api.h @@ -0,0 +1,77 @@ +#ifndef PQCLEAN_SPHINCSSHA2192SSIMPLE_CLEAN_API_H +#define PQCLEAN_SPHINCSSHA2192SSIMPLE_CLEAN_API_H + +#include +#include + +#define PQCLEAN_SPHINCSSHA2192SSIMPLE_CLEAN_CRYPTO_ALGNAME "SPHINCS+-sha2-192s-simple" + +#define PQCLEAN_SPHINCSSHA2192SSIMPLE_CLEAN_CRYPTO_SECRETKEYBYTES 96 +#define PQCLEAN_SPHINCSSHA2192SSIMPLE_CLEAN_CRYPTO_PUBLICKEYBYTES 48 +#define PQCLEAN_SPHINCSSHA2192SSIMPLE_CLEAN_CRYPTO_BYTES 16224 + +#define PQCLEAN_SPHINCSSHA2192SSIMPLE_CLEAN_CRYPTO_SEEDBYTES 72 + +/* + * Returns the length of a secret key, in bytes + */ +size_t PQCLEAN_SPHINCSSHA2192SSIMPLE_CLEAN_crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +size_t PQCLEAN_SPHINCSSHA2192SSIMPLE_CLEAN_crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +size_t PQCLEAN_SPHINCSSHA2192SSIMPLE_CLEAN_crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +size_t PQCLEAN_SPHINCSSHA2192SSIMPLE_CLEAN_crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +int PQCLEAN_SPHINCSSHA2192SSIMPLE_CLEAN_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +int PQCLEAN_SPHINCSSHA2192SSIMPLE_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +int PQCLEAN_SPHINCSSHA2192SSIMPLE_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +int PQCLEAN_SPHINCSSHA2192SSIMPLE_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, + const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +int PQCLEAN_SPHINCSSHA2192SSIMPLE_CLEAN_crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +int PQCLEAN_SPHINCSSHA2192SSIMPLE_CLEAN_crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_clean/context.h b/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_clean/context.h new file mode 100644 index 0000000000..97e2e2469e --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_clean/context.h @@ -0,0 +1,28 @@ +#ifndef SPX_CONTEXT_H +#define SPX_CONTEXT_H + +#include +#include + +#include "params.h" +#include "sha2.h" + +typedef struct { + uint8_t pub_seed[SPX_N]; + uint8_t sk_seed[SPX_N]; + + // sha256 state that absorbed pub_seed + sha256ctx state_seeded; + + // sha512 state that absorbed pub_seed + sha512ctx state_seeded_512; + +} spx_ctx; + +#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) +void initialize_hash_function(spx_ctx *ctx); + +#define free_hash_function SPX_NAMESPACE(free_hash_function) +void free_hash_function(spx_ctx *ctx); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_clean/context_sha2.c b/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_clean/context_sha2.c new file mode 100644 index 0000000000..9ca9f4e7ac --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_clean/context_sha2.c @@ -0,0 +1,36 @@ +#include "context.h" + +/** + * Absorb the constant pub_seed using one round of the compression function + * This initializes state_seeded and state_seeded_512, which can then be + * reused in thash + **/ +static void seed_state(spx_ctx *ctx) { + uint8_t block[SPX_SHA512_BLOCK_BYTES]; + size_t i; + + for (i = 0; i < SPX_N; ++i) { + block[i] = ctx->pub_seed[i]; + } + for (i = SPX_N; i < SPX_SHA512_BLOCK_BYTES; ++i) { + block[i] = 0; + } + /* block has been properly initialized for both SHA-256 and SHA-512 */ + + sha256_inc_init(&ctx->state_seeded); + sha256_inc_blocks(&ctx->state_seeded, block, 1); + sha512_inc_init(&ctx->state_seeded_512); + sha512_inc_blocks(&ctx->state_seeded_512, block, 1); +} + + +/* We initialize the state for the hash functions */ +void initialize_hash_function(spx_ctx *ctx) { + seed_state(ctx); +} + +/* Free the incremental hashing context for heap-based SHA2 APIs */ +void free_hash_function(spx_ctx *ctx) { + sha256_inc_ctx_release(&ctx->state_seeded); + sha512_inc_ctx_release(&ctx->state_seeded_512); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_clean/fors.c b/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_clean/fors.c new file mode 100644 index 0000000000..96ca72e986 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_clean/fors.c @@ -0,0 +1,156 @@ +#include +#include +#include + +#include "fors.h" + +#include "address.h" +#include "hash.h" +#include "thash.h" +#include "utils.h" +#include "utilsx1.h" + +static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + prf_addr(sk, ctx, fors_leaf_addr); +} + +static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, + const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + thash(leaf, sk, 1, ctx, fors_leaf_addr); +} + +struct fors_gen_leaf_info { + uint32_t leaf_addrx[8]; +}; + +static void fors_gen_leafx1(unsigned char *leaf, + const spx_ctx *ctx, + uint32_t addr_idx, void *info) { + struct fors_gen_leaf_info *fors_info = info; + uint32_t *fors_leaf_addr = fors_info->leaf_addrx; + + /* Only set the parts that the caller doesn't set */ + set_tree_index(fors_leaf_addr, addr_idx); + set_type(fors_leaf_addr, SPX_ADDR_TYPE_FORSPRF); + fors_gen_sk(leaf, ctx, fors_leaf_addr); + + set_type(fors_leaf_addr, SPX_ADDR_TYPE_FORSTREE); + fors_sk_to_leaf(leaf, leaf, + ctx, fors_leaf_addr); +} + +/** + * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + * Assumes indices has space for SPX_FORS_TREES integers. + */ +static void message_to_indices(uint32_t *indices, const unsigned char *m) { + unsigned int i, j; + unsigned int offset = 0; + + for (i = 0; i < SPX_FORS_TREES; i++) { + indices[i] = 0; + for (j = 0; j < SPX_FORS_HEIGHT; j++) { + indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); + offset++; + } + } +} + +/** + * Signs a message m, deriving the secret key from sk_seed and the FTS address. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + uint32_t fors_tree_addr[8] = {0}; + struct fors_gen_leaf_info fors_info = {0}; + uint32_t *fors_leaf_addr = fors_info.leaf_addrx; + uint32_t fors_pk_addr[8] = {0}; + uint32_t idx_offset; + unsigned int i; + + copy_keypair_addr(fors_tree_addr, fors_addr); + copy_keypair_addr(fors_leaf_addr, fors_addr); + + copy_keypair_addr(fors_pk_addr, fors_addr); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); + + message_to_indices(indices, m); + + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); + + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); + + /* Include the secret key part that produces the selected leaf node. */ + fors_gen_sk(sig, ctx, fors_tree_addr); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + sig += SPX_N; + + /* Compute the authentication path for this leaf node. */ + treehashx1(roots + i * SPX_N, sig, ctx, + indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx1, + fors_tree_addr, &fors_info); + + sig += SPX_N * SPX_FORS_HEIGHT; + } + + /* Hash horizontally across all tree roots to derive the public key. */ + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); +} + +/** + * Derives the FORS public key from a signature. + * This can be used for verification by comparing to a known public key, or to + * subsequently verify a signature on the derived public key. The latter is the + * typical use-case when used as an FTS below an OTS in a hypertree. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + unsigned char leaf[SPX_N]; + uint32_t fors_tree_addr[8] = {0}; + uint32_t fors_pk_addr[8] = {0}; + uint32_t idx_offset; + unsigned int i; + + copy_keypair_addr(fors_tree_addr, fors_addr); + copy_keypair_addr(fors_pk_addr, fors_addr); + + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); + + message_to_indices(indices, m); + + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); + + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + + /* Derive the leaf from the included secret key part. */ + fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); + sig += SPX_N; + + /* Derive the corresponding root node of this tree. */ + compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, + sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); + sig += SPX_N * SPX_FORS_HEIGHT; + } + + /* Hash horizontally across all tree roots to derive the public key. */ + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_clean/fors.h b/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_clean/fors.h new file mode 100644 index 0000000000..509140a178 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_clean/fors.h @@ -0,0 +1,32 @@ +#ifndef SPX_FORS_H +#define SPX_FORS_H + +#include + +#include "context.h" +#include "params.h" + +/** + * Signs a message m, deriving the secret key from sk_seed and the FTS address. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +#define fors_sign SPX_NAMESPACE(fors_sign) +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); + +/** + * Derives the FORS public key from a signature. + * This can be used for verification by comparing to a known public key, or to + * subsequently verify a signature on the derived public key. The latter is the + * typical use-case when used as an FTS below an OTS in a hypertree. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_clean/hash.h b/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_clean/hash.h new file mode 100644 index 0000000000..ffe815f45d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_clean/hash.h @@ -0,0 +1,37 @@ +#ifndef SPX_HASH_H +#define SPX_HASH_H + +#include +#include + +#include "context.h" +#include "params.h" + +#define prf_addr SPX_NAMESPACE(prf_addr) +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]); + +#define gen_message_random SPX_NAMESPACE(gen_message_random) +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); + +#define hash_message SPX_NAMESPACE(hash_message) +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); + + +# define SPX_SHA256_ADDR_BYTES 22 + +# define mgf1_256 SPX_NAMESPACE(mgf1_256) +void mgf1_256(unsigned char *out, unsigned long outlen, + const unsigned char *in, unsigned long inlen); + +# define mgf1_512 SPX_NAMESPACE(mgf1_512) +void mgf1_512(unsigned char *out, unsigned long outlen, + const unsigned char *in, unsigned long inlen); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_clean/hash_sha2.c b/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_clean/hash_sha2.c new file mode 100644 index 0000000000..3d0085c8c1 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_clean/hash_sha2.c @@ -0,0 +1,219 @@ +#include +#include + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "sha2.h" +#include "utils.h" + + + +#define SPX_SHAX_OUTPUT_BYTES SPX_SHA512_OUTPUT_BYTES +#define SPX_SHAX_BLOCK_BYTES SPX_SHA512_BLOCK_BYTES +#define shaX_inc_init sha512_inc_init +#define shaX_inc_blocks sha512_inc_blocks +#define shaX_inc_finalize sha512_inc_finalize +#define shaX sha512 +#define mgf1_X mgf1_512 +#define shaXstate sha512ctx + +/** + * mgf1 function based on the SHA-256 hash function + * Note that inlen should be sufficiently small that it still allows for + * an array to be allocated on the stack. Typically 'in' is merely a seed. + * Outputs outlen number of bytes + */ +void mgf1_256(unsigned char *out, unsigned long outlen, + const unsigned char *in, unsigned long inlen) { + PQCLEAN_VLA(uint8_t, inbuf, inlen + 4); + unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES]; + uint32_t i; + + memcpy(inbuf, in, inlen); + + /* While we can fit in at least another full block of SHA256 output.. */ + for (i = 0; (i + 1)*SPX_SHA256_OUTPUT_BYTES <= outlen; i++) { + u32_to_bytes(inbuf + inlen, i); + sha256(out, inbuf, inlen + 4); + out += SPX_SHA256_OUTPUT_BYTES; + } + /* Until we cannot anymore, and we fill the remainder. */ + if (outlen > i * SPX_SHA256_OUTPUT_BYTES) { + u32_to_bytes(inbuf + inlen, i); + sha256(outbuf, inbuf, inlen + 4); + memcpy(out, outbuf, outlen - i * SPX_SHA256_OUTPUT_BYTES); + } +} + +/* + * mgf1 function based on the SHA-512 hash function + */ +void mgf1_512(unsigned char *out, unsigned long outlen, + const unsigned char *in, unsigned long inlen) { + PQCLEAN_VLA(uint8_t, inbuf, inlen + 4); + unsigned char outbuf[SPX_SHA512_OUTPUT_BYTES]; + uint32_t i; + + memcpy(inbuf, in, inlen); + + /* While we can fit in at least another full block of SHA512 output.. */ + for (i = 0; (i + 1)*SPX_SHA512_OUTPUT_BYTES <= outlen; i++) { + u32_to_bytes(inbuf + inlen, i); + sha512(out, inbuf, inlen + 4); + out += SPX_SHA512_OUTPUT_BYTES; + } + /* Until we cannot anymore, and we fill the remainder. */ + if (outlen > i * SPX_SHA512_OUTPUT_BYTES) { + u32_to_bytes(inbuf + inlen, i); + sha512(outbuf, inbuf, inlen + 4); + memcpy(out, outbuf, outlen - i * SPX_SHA512_OUTPUT_BYTES); + } +} + +/* + * Computes PRF(pk_seed, sk_seed, addr). + */ +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]) { + sha256ctx sha2_state; + unsigned char buf[SPX_SHA256_ADDR_BYTES + SPX_N]; + unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES]; + + /* Retrieve precomputed state containing pub_seed */ + sha256_inc_ctx_clone(&sha2_state, &ctx->state_seeded); + + /* Remainder: ADDR^c ‖ SK.seed */ + memcpy(buf, addr, SPX_SHA256_ADDR_BYTES); + memcpy(buf + SPX_SHA256_ADDR_BYTES, ctx->sk_seed, SPX_N); + + sha256_inc_finalize(outbuf, &sha2_state, buf, SPX_SHA256_ADDR_BYTES + SPX_N); + + memcpy(out, outbuf, SPX_N); +} + +/** + * Computes the message-dependent randomness R, using a secret seed as a key + * for HMAC, and an optional randomization value prefixed to the message. + * This requires m to have at least SPX_SHAX_BLOCK_BYTES + SPX_N space + * available in front of the pointer, i.e. before the message to use for the + * prefix. This is necessary to prevent having to move the message around (and + * allocate memory for it). + */ +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { + (void)ctx; + + unsigned char buf[SPX_SHAX_BLOCK_BYTES + SPX_SHAX_OUTPUT_BYTES]; + shaXstate state; + int i; + + + /* This implements HMAC-SHA */ + for (i = 0; i < SPX_N; i++) { + buf[i] = 0x36 ^ sk_prf[i]; + } + memset(buf + SPX_N, 0x36, SPX_SHAX_BLOCK_BYTES - SPX_N); + + shaX_inc_init(&state); + shaX_inc_blocks(&state, buf, 1); + + memcpy(buf, optrand, SPX_N); + + /* If optrand + message cannot fill up an entire block */ + if (SPX_N + mlen < SPX_SHAX_BLOCK_BYTES) { + memcpy(buf + SPX_N, m, mlen); + shaX_inc_finalize(buf + SPX_SHAX_BLOCK_BYTES, &state, + buf, mlen + SPX_N); + } + /* Otherwise first fill a block, so that finalize only uses the message */ + else { + memcpy(buf + SPX_N, m, SPX_SHAX_BLOCK_BYTES - SPX_N); + shaX_inc_blocks(&state, buf, 1); + + m += SPX_SHAX_BLOCK_BYTES - SPX_N; + mlen -= SPX_SHAX_BLOCK_BYTES - SPX_N; + shaX_inc_finalize(buf + SPX_SHAX_BLOCK_BYTES, &state, m, mlen); + } + + for (i = 0; i < SPX_N; i++) { + buf[i] = 0x5c ^ sk_prf[i]; + } + memset(buf + SPX_N, 0x5c, SPX_SHAX_BLOCK_BYTES - SPX_N); + + shaX(buf, buf, SPX_SHAX_BLOCK_BYTES + SPX_SHAX_OUTPUT_BYTES); + memcpy(R, buf, SPX_N); +} + +/** + * Computes the message hash using R, the public key, and the message. + * Outputs the message digest and the index of the leaf. The index is split in + * the tree index and the leaf index, for convenient copying to an address. + */ +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { + (void)ctx; +#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) +#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) +#define SPX_LEAF_BITS SPX_TREE_HEIGHT +#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) +#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) + + unsigned char seed[2 * SPX_N + SPX_SHAX_OUTPUT_BYTES]; + + /* Round to nearest multiple of SPX_SHAX_BLOCK_BYTES */ +#define SPX_INBLOCKS (((SPX_N + SPX_PK_BYTES + SPX_SHAX_BLOCK_BYTES - 1) & \ + -SPX_SHAX_BLOCK_BYTES) / SPX_SHAX_BLOCK_BYTES) + unsigned char inbuf[SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES]; + + unsigned char buf[SPX_DGST_BYTES]; + unsigned char *bufp = buf; + shaXstate state; + + shaX_inc_init(&state); + + // seed: SHA-X(R ‖ PK.seed ‖ PK.root ‖ M) + memcpy(inbuf, R, SPX_N); + memcpy(inbuf + SPX_N, pk, SPX_PK_BYTES); + + /* If R + pk + message cannot fill up an entire block */ + if (SPX_N + SPX_PK_BYTES + mlen < SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES) { + memcpy(inbuf + SPX_N + SPX_PK_BYTES, m, mlen); + shaX_inc_finalize(seed + 2 * SPX_N, &state, inbuf, SPX_N + SPX_PK_BYTES + mlen); + } + /* Otherwise first fill a block, so that finalize only uses the message */ + else { + memcpy(inbuf + SPX_N + SPX_PK_BYTES, m, + SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES - SPX_N - SPX_PK_BYTES); + shaX_inc_blocks(&state, inbuf, SPX_INBLOCKS); + + m += SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES - SPX_N - SPX_PK_BYTES; + mlen -= SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES - SPX_N - SPX_PK_BYTES; + shaX_inc_finalize(seed + 2 * SPX_N, &state, m, (size_t)mlen); + } + + // H_msg: MGF1-SHA-X(R ‖ PK.seed ‖ seed) + memcpy(seed, R, SPX_N); + memcpy(seed + SPX_N, pk, SPX_N); + + /* By doing this in two steps, we prevent hashing the message twice; + otherwise each iteration in MGF1 would hash the message again. */ + mgf1_X(bufp, SPX_DGST_BYTES, seed, 2 * SPX_N + SPX_SHAX_OUTPUT_BYTES); + + memcpy(digest, bufp, SPX_FORS_MSG_BYTES); + bufp += SPX_FORS_MSG_BYTES; + + + *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); + *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); + bufp += SPX_TREE_BYTES; + + *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); + *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); +} + + diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_clean/merkle.c b/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_clean/merkle.c new file mode 100644 index 0000000000..0c1479fd93 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_clean/merkle.c @@ -0,0 +1,59 @@ +#include +#include + +#include "address.h" +#include "merkle.h" +#include "params.h" +#include "utils.h" +#include "utilsx1.h" +#include "wots.h" +#include "wotsx1.h" + +/* + * This generates a Merkle signature (WOTS signature followed by the Merkle + * authentication path). This is in this file because most of the complexity + * is involved with the WOTS signature; the Merkle authentication path logic + * is mostly hidden in treehashx4 + */ +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf) { + unsigned char *auth_path = sig + SPX_WOTS_BYTES; + struct leaf_info_x1 info = { 0 }; + unsigned steps[ SPX_WOTS_LEN ]; + + info.wots_sig = sig; + chain_lengths(steps, root); + info.wots_steps = steps; + + set_type(&tree_addr[0], SPX_ADDR_TYPE_HASHTREE); + set_type(&info.pk_addr[0], SPX_ADDR_TYPE_WOTSPK); + copy_subtree_addr(&info.leaf_addr[0], wots_addr); + copy_subtree_addr(&info.pk_addr[0], wots_addr); + + info.wots_sign_leaf = idx_leaf; + + treehashx1(root, auth_path, ctx, + idx_leaf, 0, + SPX_TREE_HEIGHT, + wots_gen_leafx1, + tree_addr, &info); +} + +/* Compute root node of the top-most subtree. */ +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { + /* We do not need the auth path in key generation, but it simplifies the + code to have just one treehash routine that computes both root and path + in one function. */ + unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; + uint32_t top_tree_addr[8] = {0}; + uint32_t wots_addr[8] = {0}; + + set_layer_addr(top_tree_addr, SPX_D - 1); + set_layer_addr(wots_addr, SPX_D - 1); + + merkle_sign(auth_path, root, ctx, + wots_addr, top_tree_addr, + (uint32_t)~0 /* ~0 means "don't bother generating an auth path */ ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_clean/merkle.h b/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_clean/merkle.h new file mode 100644 index 0000000000..769cf2e970 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_clean/merkle.h @@ -0,0 +1,21 @@ +#ifndef MERKLE_H_ +#define MERKLE_H_ + +#include + +#include "context.h" +#include "params.h" + +/* Generate a Merkle signature (WOTS signature followed by the Merkle */ +/* authentication path) */ +#define merkle_sign SPX_NAMESPACE(merkle_sign) +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf); + +/* Compute the root node of the top-most subtree. */ +#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); + +#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_clean/nistapi.h b/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_clean/nistapi.h new file mode 100644 index 0000000000..3cb71afad4 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_clean/nistapi.h @@ -0,0 +1,87 @@ +#ifndef SPX_API_H +#define SPX_API_H + +#include +#include + +#include "params.h" + +#define CRYPTO_ALGNAME "SPHINCS+" + +#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES +#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES +#define CRYPTO_BYTES SPX_BYTES +#define CRYPTO_SEEDBYTES (3*SPX_N) + +/* + * Returns the length of a secret key, in bytes + */ +#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) +size_t crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) +size_t crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) +size_t crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) +size_t crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +#define crypto_sign SPX_NAMESPACE(crypto_sign) +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_clean/params.h b/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_clean/params.h new file mode 100644 index 0000000000..b4499bde46 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_clean/params.h @@ -0,0 +1,61 @@ +#ifndef SPX_PARAMS_H +#define SPX_PARAMS_H + +#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSSHA2192SSIMPLE_CLEAN_##s + +/* Hash output length in bytes. */ +#define SPX_N 24 +/* Height of the hypertree. */ +#define SPX_FULL_HEIGHT 63 +/* Number of subtree layer. */ +#define SPX_D 7 +/* FORS tree dimensions. */ +#define SPX_FORS_HEIGHT 14 +#define SPX_FORS_TREES 17 +/* Winternitz parameter, */ +#define SPX_WOTS_W 16 + +/* The hash function is defined by linking a different hash.c file, as opposed + to setting a #define constant. */ + +/* This is a SHA2-based parameter set, hence whether we use SHA-256 + * exclusively or we use both SHA-256 and SHA-512 is controlled by + * the following #define */ +#define SPX_SHA512 1 /* Use SHA-512 for H and T_l, l >= 2 */ + +/* For clarity */ +#define SPX_ADDR_BYTES 32 + +/* WOTS parameters. */ +#define SPX_WOTS_LOGW 4 + +#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) + +/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ +#define SPX_WOTS_LEN2 3 + +#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) +#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) +#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES + +/* Subtree size. */ +#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) + +//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT +// #error SPX_D should always divide SPX_FULL_HEIGHT +//#endif + +/* FORS parameters. */ +#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) +#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) +#define SPX_FORS_PK_BYTES SPX_N + +/* Resulting SPX sizes. */ +#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ + SPX_FULL_HEIGHT * SPX_N) +#define SPX_PK_BYTES (2 * SPX_N) +#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) + +#include "sha2_offsets.h" + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_clean/sha2_offsets.h b/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_clean/sha2_offsets.h new file mode 100644 index 0000000000..6e3584f7a4 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_clean/sha2_offsets.h @@ -0,0 +1,27 @@ +#ifndef SHA2_OFFSETS_H_ +#define SHA2_OFFSETS_H_ + +#define SPX_SHA256_BLOCK_BYTES 64 +#define SPX_SHA256_OUTPUT_BYTES 32 + +#define SPX_SHA512_BLOCK_BYTES 128 +#define SPX_SHA512_OUTPUT_BYTES 64 + +/* + * Offsets of various fields in the address structure when we use SHA2 as + * the Sphincs+ hash function + */ + +#define SPX_OFFSET_LAYER 0 /* The byte used to specify the Merkle tree layer */ +#define SPX_OFFSET_TREE 1 /* The start of the 8 byte field used to specify the tree */ +#define SPX_OFFSET_TYPE 9 /* The byte used to specify the hash type (reason) */ +#define SPX_OFFSET_KP_ADDR2 12 /* The high byte used to specify the key pair (which one-time signature) */ +#define SPX_OFFSET_KP_ADDR1 13 /* The low byte used to specify the key pair */ +#define SPX_OFFSET_CHAIN_ADDR 17 /* The byte used to specify the chain address (which Winternitz chain) */ +#define SPX_OFFSET_HASH_ADDR 21 /* The byte used to specify the hash address (where in the Winternitz chain) */ +#define SPX_OFFSET_TREE_HGT 17 /* The byte used to specify the height of this node in the FORS or Merkle tree */ +#define SPX_OFFSET_TREE_INDEX 18 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ + +#define SPX_SHA2 1 + +#endif /* SHA2_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_clean/sign.c b/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_clean/sign.c new file mode 100644 index 0000000000..9d0c7d1b22 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_clean/sign.c @@ -0,0 +1,286 @@ +#include +#include +#include + +#include "address.h" +#include "context.h" +#include "fors.h" +#include "hash.h" +#include "merkle.h" +#include "nistapi.h" +#include "params.h" +#include "randombytes.h" +#include "thash.h" +#include "utils.h" +#include "wots.h" + +/* + * Returns the length of a secret key, in bytes + */ +size_t crypto_sign_secretkeybytes(void) { + return CRYPTO_SECRETKEYBYTES; +} + +/* + * Returns the length of a public key, in bytes + */ +size_t crypto_sign_publickeybytes(void) { + return CRYPTO_PUBLICKEYBYTES; +} + +/* + * Returns the length of a signature, in bytes + */ +size_t crypto_sign_bytes(void) { + return CRYPTO_BYTES; +} + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +size_t crypto_sign_seedbytes(void) { + return CRYPTO_SEEDBYTES; +} + +/* + * Generates an SPX key pair given a seed of length + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [PUB_SEED || root] + */ +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed) { + spx_ctx ctx; + + /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ + memcpy(sk, seed, CRYPTO_SEEDBYTES); + + memcpy(pk, sk + 2 * SPX_N, SPX_N); + + memcpy(ctx.pub_seed, pk, SPX_N); + memcpy(ctx.sk_seed, sk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + /* Compute root node of the top-most subtree. */ + merkle_gen_root(sk + 3 * SPX_N, &ctx); + + // cleanup + free_hash_function(&ctx); + + memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); + + return 0; +} + +/* + * Generates an SPX key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [PUB_SEED || root] + */ +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { + uint8_t seed[CRYPTO_SEEDBYTES]; + randombytes(seed, CRYPTO_SEEDBYTES); + crypto_sign_seed_keypair(pk, sk, seed); + + return 0; +} + +/** + * Returns an array containing a detached signature. + */ +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk) { + spx_ctx ctx; + + const uint8_t *sk_prf = sk + SPX_N; + const uint8_t *pk = sk + 2 * SPX_N; + + uint8_t optrand[SPX_N]; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t root[SPX_N]; + uint32_t i; + uint64_t tree; + uint32_t idx_leaf; + uint32_t wots_addr[8] = {0}; + uint32_t tree_addr[8] = {0}; + + memcpy(ctx.sk_seed, sk, SPX_N); + memcpy(ctx.pub_seed, pk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + + /* Optionally, signing can be made non-deterministic using optrand. + This can help counter side-channel attacks that would benefit from + getting a large number of traces when the signer uses the same nodes. */ + randombytes(optrand, SPX_N); + /* Compute the digest randomization value. */ + gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); + + /* Derive the message digest and leaf index from R, PK and M. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; + + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); + + /* Sign the message hash using FORS. */ + fors_sign(sig, root, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); + sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; + + /* Update the indices for the next layer. */ + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; + } + + free_hash_function(&ctx); + + *siglen = SPX_BYTES; + + return 0; +} + +/** + * Verifies a detached signature and message under a given public key. + */ +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk) { + spx_ctx ctx; + const uint8_t *pub_root = pk + SPX_N; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t wots_pk[SPX_WOTS_BYTES]; + uint8_t root[SPX_N]; + uint8_t leaf[SPX_N]; + unsigned int i; + uint64_t tree; + uint32_t idx_leaf; + uint32_t wots_addr[8] = {0}; + uint32_t tree_addr[8] = {0}; + uint32_t wots_pk_addr[8] = {0}; + + if (siglen != SPX_BYTES) { + return -1; + } + + memcpy(ctx.pub_seed, pk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); + + /* Derive the message digest and leaf index from R || PK || M. */ + /* The additional SPX_N is a result of the hash domain separator. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; + + /* Layer correctly defaults to 0, so no need to set_layer_addr */ + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); + + fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + /* For each subtree.. */ + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + copy_keypair_addr(wots_pk_addr, wots_addr); + + /* The WOTS public key is only correct if the signature was correct. */ + /* Initially, root is the FORS pk, but on subsequent iterations it is + the root of the subtree below the currently processed subtree. */ + wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); + sig += SPX_WOTS_BYTES; + + /* Compute the leaf node using the WOTS public key. */ + thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); + + /* Compute the root node of this subtree. */ + compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, + &ctx, tree_addr); + sig += SPX_TREE_HEIGHT * SPX_N; + + /* Update the indices for the next layer. */ + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; + } + + // cleanup + free_hash_function(&ctx); + + /* Check if the root node equals the root node in the public key. */ + if (memcmp(root, pub_root, SPX_N) != 0) { + return -1; + } + + return 0; +} + + +/** + * Returns an array containing the signature followed by the message. + */ +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk) { + size_t siglen; + + crypto_sign_signature(sm, &siglen, m, mlen, sk); + + memmove(sm + SPX_BYTES, m, mlen); + *smlen = siglen + mlen; + + return 0; +} + +/** + * Verifies a given signature-message pair under a given public key. + */ +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk) { + /* The API caller does not necessarily know what size a signature should be + but SPHINCS+ signatures are always exactly SPX_BYTES. */ + if (smlen < SPX_BYTES) { + memset(m, 0, smlen); + *mlen = 0; + return -1; + } + + *mlen = smlen - SPX_BYTES; + + if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { + memset(m, 0, smlen); + *mlen = 0; + return -1; + } + + /* If verification was successful, move the message to the right place. */ + memmove(m, sm + SPX_BYTES, *mlen); + + return 0; +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_clean/thash.h b/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_clean/thash.h new file mode 100644 index 0000000000..8687ccfb4d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_clean/thash.h @@ -0,0 +1,13 @@ +#ifndef SPX_THASH_H +#define SPX_THASH_H + +#include "context.h" +#include "params.h" + +#include + +#define thash SPX_NAMESPACE(thash) +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_clean/thash_sha2_simple.c b/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_clean/thash_sha2_simple.c new file mode 100644 index 0000000000..87badc4d53 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_clean/thash_sha2_simple.c @@ -0,0 +1,53 @@ +#include +#include + +#include "thash.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "sha2.h" +#include "utils.h" + +static void thash_512(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]); + +/** + * Takes an array of inblocks concatenated arrays of SPX_N bytes. + */ +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]) { + if (inblocks > 1) { + thash_512(out, in, inblocks, ctx, addr); + return; + } + + unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES]; + sha256ctx sha2_state; + PQCLEAN_VLA(uint8_t, buf, SPX_SHA256_ADDR_BYTES + inblocks * SPX_N); + + /* Retrieve precomputed state containing pub_seed */ + sha256_inc_ctx_clone(&sha2_state, &ctx->state_seeded); + + memcpy(buf, addr, SPX_SHA256_ADDR_BYTES); + memcpy(buf + SPX_SHA256_ADDR_BYTES, in, inblocks * SPX_N); + + sha256_inc_finalize(outbuf, &sha2_state, buf, SPX_SHA256_ADDR_BYTES + inblocks * SPX_N); + memcpy(out, outbuf, SPX_N); +} + +static void thash_512(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]) { + unsigned char outbuf[SPX_SHA512_OUTPUT_BYTES]; + sha512ctx sha2_state; + PQCLEAN_VLA(uint8_t, buf, SPX_SHA256_ADDR_BYTES + inblocks * SPX_N); + + /* Retrieve precomputed state containing pub_seed */ + sha512_inc_ctx_clone(&sha2_state, &ctx->state_seeded_512); + + memcpy(buf, addr, SPX_SHA256_ADDR_BYTES); + memcpy(buf + SPX_SHA256_ADDR_BYTES, in, inblocks * SPX_N); + + sha512_inc_finalize(outbuf, &sha2_state, buf, SPX_SHA256_ADDR_BYTES + inblocks * SPX_N); + memcpy(out, outbuf, SPX_N); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_clean/utils.c b/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_clean/utils.c new file mode 100644 index 0000000000..177b541fb9 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_clean/utils.c @@ -0,0 +1,148 @@ +#include + +#include "utils.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "thash.h" + +/** + * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. + */ +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in) { + int i; + + /* Iterate over out in decreasing order, for big-endianness. */ + for (i = (signed int)outlen - 1; i >= 0; i--) { + out[i] = in & 0xff; + in = in >> 8; + } +} + +void u32_to_bytes(unsigned char *out, uint32_t in) { + out[0] = (unsigned char)(in >> 24); + out[1] = (unsigned char)(in >> 16); + out[2] = (unsigned char)(in >> 8); + out[3] = (unsigned char)in; +} + +/** + * Converts the inlen bytes in 'in' from big-endian byte order to an integer. + */ +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { + unsigned long long retval = 0; + unsigned int i; + + for (i = 0; i < inlen; i++) { + retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); + } + return retval; +} + +/** + * Computes a root node given a leaf and an auth path. + * Expects address to be complete other than the tree_height and tree_index. + */ +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]) { + uint32_t i; + unsigned char buffer[2 * SPX_N]; + + /* If leaf_idx is odd (last bit = 1), current path element is a right child + and auth_path has to go left. Otherwise it is the other way around. */ + if (leaf_idx & 1) { + memcpy(buffer + SPX_N, leaf, SPX_N); + memcpy(buffer, auth_path, SPX_N); + } else { + memcpy(buffer, leaf, SPX_N); + memcpy(buffer + SPX_N, auth_path, SPX_N); + } + auth_path += SPX_N; + + for (i = 0; i < tree_height - 1; i++) { + leaf_idx >>= 1; + idx_offset >>= 1; + /* Set the address of the node we're creating. */ + set_tree_height(addr, i + 1); + set_tree_index(addr, leaf_idx + idx_offset); + + /* Pick the right or left neighbor, depending on parity of the node. */ + if (leaf_idx & 1) { + thash(buffer + SPX_N, buffer, 2, ctx, addr); + memcpy(buffer, auth_path, SPX_N); + } else { + thash(buffer, buffer, 2, ctx, addr); + memcpy(buffer + SPX_N, auth_path, SPX_N); + } + auth_path += SPX_N; + } + + /* The last iteration is exceptional; we do not copy an auth_path node. */ + leaf_idx >>= 1; + idx_offset >>= 1; + set_tree_height(addr, tree_height); + set_tree_index(addr, leaf_idx + idx_offset); + thash(root, buffer, 2, ctx, addr); +} + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx * /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]) { + PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); + PQCLEAN_VLA(unsigned int, heights, tree_height + 1); + unsigned int offset = 0; + uint32_t idx; + uint32_t tree_idx; + + for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { + /* Add the next leaf node to the stack. */ + gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); + offset++; + heights[offset - 1] = 0; + + /* If this is a node we need for the auth path.. */ + if ((leaf_idx ^ 0x1) == idx) { + memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); + } + + /* While the top-most nodes are of equal height.. */ + while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { + /* Compute index of the new node, in the next layer. */ + tree_idx = (idx >> (heights[offset - 1] + 1)); + + /* Set the address of the node we're creating. */ + set_tree_height(tree_addr, heights[offset - 1] + 1); + set_tree_index(tree_addr, + tree_idx + (idx_offset >> (heights[offset - 1] + 1))); + /* Hash the top-most nodes from the stack together. */ + thash(stack + (offset - 2)*SPX_N, + stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); + offset--; + /* Note that the top-most node is now one layer higher. */ + heights[offset - 1]++; + + /* If this is a node we need for the auth path.. */ + if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { + memcpy(auth_path + heights[offset - 1]*SPX_N, + stack + (offset - 1)*SPX_N, SPX_N); + } + } + } + memcpy(root, stack, SPX_N); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_clean/utils.h b/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_clean/utils.h new file mode 100644 index 0000000000..64f5d5a53a --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_clean/utils.h @@ -0,0 +1,58 @@ +#ifndef SPX_UTILS_H +#define SPX_UTILS_H + +#include + +#include "compat.h" +#include "context.h" +#include "params.h" + + +/* To support MSVC use alloca() instead of VLAs. See #20. */ + + +/** + * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. + */ +#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in); +#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) +void u32_to_bytes(unsigned char *out, uint32_t in); + +/** + * Converts the inlen bytes in 'in' from big-endian byte order to an integer. + */ +#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); + +/** + * Computes a root node given a leaf and an auth path. + * Expects address to be complete other than the tree_height and tree_index. + */ +#define compute_root SPX_NAMESPACE(compute_root) +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]); + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +#define treehash SPX_NAMESPACE(treehash) +void treehash(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx *ctx /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]); + + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_clean/utilsx1.c b/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_clean/utilsx1.c new file mode 100644 index 0000000000..fccb69b35d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_clean/utilsx1.c @@ -0,0 +1,100 @@ +#include + +#include "utilsx1.h" + +#include "address.h" +#include "params.h" +#include "thash.h" +#include "utils.h" + +/* + * Generate the entire Merkle tree, computing the authentication path for + * leaf_idx, and the resulting root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) + * + * This expects tree_addr to be initialized to the addr structures for the + * Merkle tree nodes + * + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + * + * This works by using the standard Merkle tree building algorithm, + */ +void treehashx1(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, + uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* Where to write the leaves */, + const spx_ctx * /* ctx */, + uint32_t idx, void *info), + uint32_t tree_addr[8], + void *info) { + /* This is where we keep the intermediate nodes */ + PQCLEAN_VLA(uint8_t, stack, tree_height * SPX_N); + + uint32_t idx; + uint32_t max_idx = (uint32_t)((1 << tree_height) - 1); + for (idx = 0;; idx++) { + unsigned char current[2 * SPX_N]; /* Current logical node is at */ + /* index[SPX_N]. We do this to minimize the number of copies */ + /* needed during a thash */ + gen_leaf( ¤t[SPX_N], ctx, idx + idx_offset, + info ); + + /* Now combine the freshly generated right node with previously */ + /* generated left ones */ + uint32_t internal_idx_offset = idx_offset; + uint32_t internal_idx = idx; + uint32_t internal_leaf = leaf_idx; + uint32_t h; /* The height we are in the Merkle tree */ + for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { + + /* Check if we hit the top of the tree */ + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[SPX_N], SPX_N ); + return; + } + + /* + * Check if the node we have is a part of the + * authentication path; if it is, write it out + */ + if ((internal_idx ^ internal_leaf) == 0x01) { + memcpy( &auth_path[ h * SPX_N ], + ¤t[SPX_N], + SPX_N ); + } + + /* + * Check if we're at a left child; if so, stop going up the stack + * Exception: if we've reached the end of the tree, keep on going + * (so we combine the last 4 nodes into the one root node in two + * more iterations) + */ + if ((internal_idx & 1) == 0 && idx < max_idx) { + break; + } + + /* Ok, we're at a right node */ + /* Now combine the left and right logical nodes together */ + + /* Set the address of the node we're creating. */ + internal_idx_offset >>= 1; + set_tree_height(tree_addr, h + 1); + set_tree_index(tree_addr, internal_idx / 2 + internal_idx_offset ); + + unsigned char *left = &stack[h * SPX_N]; + memcpy( ¤t[0], left, SPX_N ); + thash( ¤t[1 * SPX_N], + ¤t[0 * SPX_N], + 2, ctx, tree_addr); + } + + /* We've hit a left child; save the current for when we get the */ + /* corresponding right right */ + memcpy( &stack[h * SPX_N], ¤t[SPX_N], SPX_N); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_clean/utilsx1.h b/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_clean/utilsx1.h new file mode 100644 index 0000000000..e911d17d53 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_clean/utilsx1.h @@ -0,0 +1,27 @@ +#ifndef SPX_UTILSX4_H +#define SPX_UTILSX4_H + +#include + +#include "context.h" +#include "params.h" + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +#define treehashx1 SPX_NAMESPACE(treehashx1) +void treehashx1(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* Where to write the leaf */, + const spx_ctx * /* ctx */, + uint32_t addr_idx, void *info), + uint32_t tree_addrx4[8], void *info); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_clean/wots.c b/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_clean/wots.c new file mode 100644 index 0000000000..249717aaa8 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_clean/wots.c @@ -0,0 +1,108 @@ +#include +#include + +#include "wots.h" +#include "wotsx1.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "thash.h" +#include "utils.h" +#include "utilsx1.h" + +// TODO clarify address expectations, and make them more uniform. +// TODO i.e. do we expect types to be set already? +// TODO and do we expect modifications or copies? + +/** + * Computes the chaining function. + * out and in have to be n-byte arrays. + * + * Interprets in as start-th value of the chain. + * addr has to contain the address of the chain. + */ +static void gen_chain(unsigned char *out, const unsigned char *in, + unsigned int start, unsigned int steps, + const spx_ctx *ctx, uint32_t addr[8]) { + uint32_t i; + + /* Initialize out with the value at position 'start'. */ + memcpy(out, in, SPX_N); + + /* Iterate 'steps' calls to the hash function. */ + for (i = start; i < (start + steps) && i < SPX_WOTS_W; i++) { + set_hash_addr(addr, i); + thash(out, out, 1, ctx, addr); + } +} + +/** + * base_w algorithm as described in draft. + * Interprets an array of bytes as integers in base w. + * This only works when log_w is a divisor of 8. + */ +static void base_w(unsigned int *output, const int out_len, + const unsigned char *input) { + int in = 0; + int out = 0; + unsigned char total = 0; + int bits = 0; + int consumed; + + for (consumed = 0; consumed < out_len; consumed++) { + if (bits == 0) { + total = input[in]; + in++; + bits += 8; + } + bits -= SPX_WOTS_LOGW; + output[out] = (total >> bits) & (SPX_WOTS_W - 1); + out++; + } +} + +/* Computes the WOTS+ checksum over a message (in base_w). */ +static void wots_checksum(unsigned int *csum_base_w, + const unsigned int *msg_base_w) { + unsigned int csum = 0; + unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; + unsigned int i; + + /* Compute checksum. */ + for (i = 0; i < SPX_WOTS_LEN1; i++) { + csum += SPX_WOTS_W - 1 - msg_base_w[i]; + } + + /* Convert checksum to base_w. */ + /* Make sure expected empty zero bits are the least significant bits. */ + csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); + ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); + base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); +} + +/* Takes a message and derives the matching chain lengths. */ +void chain_lengths(unsigned int *lengths, const unsigned char *msg) { + base_w(lengths, SPX_WOTS_LEN1, msg); + wots_checksum(lengths + SPX_WOTS_LEN1, lengths); +} + +/** + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. + * + * Writes the computed public key to 'pk'. + */ +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]) { + unsigned int lengths[SPX_WOTS_LEN]; + uint32_t i; + + chain_lengths(lengths, msg); + + for (i = 0; i < SPX_WOTS_LEN; i++) { + set_chain_addr(addr, i); + gen_chain(pk + i * SPX_N, sig + i * SPX_N, + lengths[i], SPX_WOTS_W - 1 - lengths[i], ctx, addr); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_clean/wots.h b/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_clean/wots.h new file mode 100644 index 0000000000..4e7692eeef --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_clean/wots.h @@ -0,0 +1,25 @@ +#ifndef SPX_WOTS_H +#define SPX_WOTS_H + +#include + +#include "context.h" +#include "params.h" + +/** + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. + * + * Writes the computed public key to 'pk'. + */ +#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]); + +/* + * Compute the chain lengths needed for a given message hash + */ +#define chain_lengths SPX_NAMESPACE(chain_lengths) +void chain_lengths(unsigned int *lengths, const unsigned char *msg); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_clean/wotsx1.c b/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_clean/wotsx1.c new file mode 100644 index 0000000000..3adec78dfb --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_clean/wotsx1.c @@ -0,0 +1,76 @@ +#include +#include + +#include "wots.h" +#include "wotsx1.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "thash.h" +#include "utils.h" + +/* + * This generates a WOTS public key + * It also generates the WOTS signature if leaf_info indicates + * that we're signing with this WOTS key + */ +void wots_gen_leafx1(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info) { + struct leaf_info_x1 *info = v_info; + uint32_t *leaf_addr = info->leaf_addr; + uint32_t *pk_addr = info->pk_addr; + unsigned int i, k; + unsigned char pk_buffer[ SPX_WOTS_BYTES ]; + unsigned char *buffer; + uint32_t wots_k_mask; + + if (leaf_idx == info->wots_sign_leaf) { + /* We're traversing the leaf that's signing; generate the WOTS */ + /* signature */ + wots_k_mask = 0; + } else { + /* Nope, we're just generating pk's; turn off the signature logic */ + wots_k_mask = (uint32_t)~0; + } + + set_keypair_addr( leaf_addr, leaf_idx ); + set_keypair_addr( pk_addr, leaf_idx ); + + for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { + uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k to */ + /* the step if we're generating a signature, ~0 if we're not */ + + /* Start with the secret seed */ + set_chain_addr(leaf_addr, i); + set_hash_addr(leaf_addr, 0); + set_type(leaf_addr, SPX_ADDR_TYPE_WOTSPRF); + + prf_addr(buffer, ctx, leaf_addr); + + set_type(leaf_addr, SPX_ADDR_TYPE_WOTS); + + /* Iterate down the WOTS chain */ + for (k = 0;; k++) { + /* Check if this is the value that needs to be saved as a */ + /* part of the WOTS signature */ + if (k == wots_k) { + memcpy( info->wots_sig + i * SPX_N, buffer, SPX_N ); + } + + /* Check if we hit the top of the chain */ + if (k == SPX_WOTS_W - 1) { + break; + } + + /* Iterate one step on the chain */ + set_hash_addr(leaf_addr, k); + + thash(buffer, buffer, 1, ctx, leaf_addr); + } + } + + /* Do the final thash to generate the public keys */ + thash(dest, pk_buffer, SPX_WOTS_LEN, ctx, pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_clean/wotsx1.h b/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_clean/wotsx1.h new file mode 100644 index 0000000000..e617929f96 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-192s-simple_clean/wotsx1.h @@ -0,0 +1,39 @@ +#ifndef WOTSX1_H_ +#define WOTSX1_H_ + +#include + +#include "context.h" +#include "params.h" + +/* + * This is here to provide an interface to the internal wots_gen_leafx1 + * routine. While this routine is not referenced in the package outside of + * wots.c, it is called from the stand-alone benchmark code to characterize + * the performance + */ +struct leaf_info_x1 { + unsigned char *wots_sig; + uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ + uint32_t *wots_steps; + uint32_t leaf_addr[8]; + uint32_t pk_addr[8]; +}; + +/* Macro to set the leaf_info to something 'benign', that is, it would */ +/* run with the same time as it does during the real signing process */ +/* Used only by the benchmark code */ +#define INITIALIZE_LEAF_INFO_X1(info, addr, step_buffer) { \ + (info).wots_sig = 0; \ + (info).wots_sign_leaf = ~0; \ + (info).wots_steps = step_buffer; \ + memcpy( &(info).leaf_addr[0], (addr), 32 ); \ + memcpy( &(info).pk_addr[0], (addr), 32 ); \ + } + +#define wots_gen_leafx1 SPX_NAMESPACE(wots_gen_leafx1) +void wots_gen_leafx1(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info); + +#endif /* WOTSX1_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/LICENSE b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/LICENSE new file mode 100644 index 0000000000..670154e353 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/LICENSE @@ -0,0 +1,116 @@ +CC0 1.0 Universal + +Statement of Purpose + +The laws of most jurisdictions throughout the world automatically confer +exclusive Copyright and Related Rights (defined below) upon the creator and +subsequent owner(s) (each and all, an "owner") of an original work of +authorship and/or a database (each, a "Work"). + +Certain owners wish to permanently relinquish those rights to a Work for the +purpose of contributing to a commons of creative, cultural and scientific +works ("Commons") that the public can reliably and without fear of later +claims of infringement build upon, modify, incorporate in other works, reuse +and redistribute as freely as possible in any form whatsoever and for any +purposes, including without limitation commercial purposes. These owners may +contribute to the Commons to promote the ideal of a free culture and the +further production of creative, cultural and scientific works, or to gain +reputation or greater distribution for their Work in part through the use and +efforts of others. + +For these and/or other purposes and motivations, and without any expectation +of additional consideration or compensation, the person associating CC0 with a +Work (the "Affirmer"), to the extent that he or she is an owner of Copyright +and Related Rights in the Work, voluntarily elects to apply CC0 to the Work +and publicly distribute the Work under its terms, with knowledge of his or her +Copyright and Related Rights in the Work and the meaning and intended legal +effect of CC0 on those rights. + +1. Copyright and Related Rights. A Work made available under CC0 may be +protected by copyright and related or neighboring rights ("Copyright and +Related Rights"). Copyright and Related Rights include, but are not limited +to, the following: + + i. the right to reproduce, adapt, distribute, perform, display, communicate, + and translate a Work; + + ii. moral rights retained by the original author(s) and/or performer(s); + + iii. publicity and privacy rights pertaining to a person's image or likeness + depicted in a Work; + + iv. rights protecting against unfair competition in regards to a Work, + subject to the limitations in paragraph 4(a), below; + + v. rights protecting the extraction, dissemination, use and reuse of data in + a Work; + + vi. database rights (such as those arising under Directive 96/9/EC of the + European Parliament and of the Council of 11 March 1996 on the legal + protection of databases, and under any national implementation thereof, + including any amended or successor version of such directive); and + + vii. other similar, equivalent or corresponding rights throughout the world + based on applicable law or treaty, and any national implementations thereof. + +2. Waiver. To the greatest extent permitted by, but not in contravention of, +applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and +unconditionally waives, abandons, and surrenders all of Affirmer's Copyright +and Related Rights and associated claims and causes of action, whether now +known or unknown (including existing as well as future claims and causes of +action), in the Work (i) in all territories worldwide, (ii) for the maximum +duration provided by applicable law or treaty (including future time +extensions), (iii) in any current or future medium and for any number of +copies, and (iv) for any purpose whatsoever, including without limitation +commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes +the Waiver for the benefit of each member of the public at large and to the +detriment of Affirmer's heirs and successors, fully intending that such Waiver +shall not be subject to revocation, rescission, cancellation, termination, or +any other legal or equitable action to disrupt the quiet enjoyment of the Work +by the public as contemplated by Affirmer's express Statement of Purpose. + +3. Public License Fallback. Should any part of the Waiver for any reason be +judged legally invalid or ineffective under applicable law, then the Waiver +shall be preserved to the maximum extent permitted taking into account +Affirmer's express Statement of Purpose. In addition, to the extent the Waiver +is so judged Affirmer hereby grants to each affected person a royalty-free, +non transferable, non sublicensable, non exclusive, irrevocable and +unconditional license to exercise Affirmer's Copyright and Related Rights in +the Work (i) in all territories worldwide, (ii) for the maximum duration +provided by applicable law or treaty (including future time extensions), (iii) +in any current or future medium and for any number of copies, and (iv) for any +purpose whatsoever, including without limitation commercial, advertising or +promotional purposes (the "License"). The License shall be deemed effective as +of the date CC0 was applied by Affirmer to the Work. Should any part of the +License for any reason be judged legally invalid or ineffective under +applicable law, such partial invalidity or ineffectiveness shall not +invalidate the remainder of the License, and in such case Affirmer hereby +affirms that he or she will not (i) exercise any of his or her remaining +Copyright and Related Rights in the Work or (ii) assert any associated claims +and causes of action with respect to the Work, in either case contrary to +Affirmer's express Statement of Purpose. + +4. Limitations and Disclaimers. + + a. No trademark or patent rights held by Affirmer are waived, abandoned, + surrendered, licensed or otherwise affected by this document. + + b. Affirmer offers the Work as-is and makes no representations or warranties + of any kind concerning the Work, express, implied, statutory or otherwise, + including without limitation warranties of title, merchantability, fitness + for a particular purpose, non infringement, or the absence of latent or + other defects, accuracy, or the present or absence of errors, whether or not + discoverable, all to the greatest extent permissible under applicable law. + + c. Affirmer disclaims responsibility for clearing rights of other persons + that may apply to the Work or any use thereof, including without limitation + any person's Copyright and Related Rights in the Work. Further, Affirmer + disclaims responsibility for obtaining any necessary consents, permissions + or other rights required for any use of the Work. + + d. Affirmer understands and acknowledges that Creative Commons is not a + party to this document and has no duty or obligation with respect to this + CC0 or use of the Work. + +For more information, please see + diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/address.c b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/address.c new file mode 100644 index 0000000000..b956e9cb29 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/address.c @@ -0,0 +1,91 @@ +#include +#include + +#include "address.h" +#include "params.h" +#include "utils.h" + +/* + * Specify which level of Merkle tree (the "layer") we're working on + */ +void set_layer_addr(uint32_t addr[8], uint32_t layer) { + ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; +} + +/* + * Specify which Merkle tree within the level (the "tree address") we're working on + */ +void set_tree_addr(uint32_t addr[8], uint64_t tree) { + ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); +} + +/* + * Specify the reason we'll use this address structure for, that is, what + * hash will we compute with it. This is used so that unrelated types of + * hashes don't accidentally get the same address structure. The type will be + * one of the SPX_ADDR_TYPE constants + */ +void set_type(uint32_t addr[8], uint32_t type) { + ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; +} + +/* + * Copy the layer and tree fields of the address structure. This is used + * when we're doing multiple types of hashes within the same Merkle tree + */ +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); +} + +/* These functions are used for OTS addresses. */ + +/* + * Specify which Merkle leaf we're working on; that is, which OTS keypair + * we're talking about. + */ +void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { + ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; +} + +/* + * Copy the layer, tree and keypair fields of the address structure. This is + * used when we're doing multiple things within the same OTS keypair + */ +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); + ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; +} + +/* + * Specify which Merkle chain within the OTS we're working with + * (the chain address) + */ +void set_chain_addr(uint32_t addr[8], uint32_t chain) { + ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; +} + +/* + * Specify where in the Merkle chain we are +* (the hash address) + */ +void set_hash_addr(uint32_t addr[8], uint32_t hash) { + ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; +} + +/* These functions are used for all hash tree addresses (including FORS). */ + +/* + * Specify the height of the node in the Merkle/FORS tree we are in + * (the tree height) + */ +void set_tree_height(uint32_t addr[8], uint32_t tree_height) { + ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; +} + +/* + * Specify the distance from the left edge of the node in the Merkle/FORS tree + * (the tree index) + */ +void set_tree_index(uint32_t addr[8], uint32_t tree_index) { + u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/address.h b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/address.h new file mode 100644 index 0000000000..24a84eb40c --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/address.h @@ -0,0 +1,52 @@ +#ifndef SPX_ADDRESS_H +#define SPX_ADDRESS_H + +#include + +#include "params.h" + +/* The hash types that are passed to set_type */ +#define SPX_ADDR_TYPE_WOTS 0 +#define SPX_ADDR_TYPE_WOTSPK 1 +#define SPX_ADDR_TYPE_HASHTREE 2 +#define SPX_ADDR_TYPE_FORSTREE 3 +#define SPX_ADDR_TYPE_FORSPK 4 +#define SPX_ADDR_TYPE_WOTSPRF 5 +#define SPX_ADDR_TYPE_FORSPRF 6 + +#define set_layer_addr SPX_NAMESPACE(set_layer_addr) +void set_layer_addr(uint32_t addr[8], uint32_t layer); + +#define set_tree_addr SPX_NAMESPACE(set_tree_addr) +void set_tree_addr(uint32_t addr[8], uint64_t tree); + +#define set_type SPX_NAMESPACE(set_type) +void set_type(uint32_t addr[8], uint32_t type); + +/* Copies the layer and tree part of one address into the other */ +#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); + +/* These functions are used for WOTS and FORS addresses. */ + +#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) +void set_keypair_addr(uint32_t addr[8], uint32_t keypair); + +#define set_chain_addr SPX_NAMESPACE(set_chain_addr) +void set_chain_addr(uint32_t addr[8], uint32_t chain); + +#define set_hash_addr SPX_NAMESPACE(set_hash_addr) +void set_hash_addr(uint32_t addr[8], uint32_t hash); + +#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); + +/* These functions are used for all hash tree addresses (including FORS). */ + +#define set_tree_height SPX_NAMESPACE(set_tree_height) +void set_tree_height(uint32_t addr[8], uint32_t tree_height); + +#define set_tree_index SPX_NAMESPACE(set_tree_index) +void set_tree_index(uint32_t addr[8], uint32_t tree_index); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/api.h b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/api.h new file mode 100644 index 0000000000..e1deefba85 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/api.h @@ -0,0 +1,77 @@ +#ifndef PQCLEAN_SPHINCSSHA2256FROBUST_AVX2_API_H +#define PQCLEAN_SPHINCSSHA2256FROBUST_AVX2_API_H + +#include +#include + +#define PQCLEAN_SPHINCSSHA2256FROBUST_AVX2_CRYPTO_ALGNAME "SPHINCS+-sha2-256f-robust" + +#define PQCLEAN_SPHINCSSHA2256FROBUST_AVX2_CRYPTO_SECRETKEYBYTES 128 +#define PQCLEAN_SPHINCSSHA2256FROBUST_AVX2_CRYPTO_PUBLICKEYBYTES 64 +#define PQCLEAN_SPHINCSSHA2256FROBUST_AVX2_CRYPTO_BYTES 49856 + +#define PQCLEAN_SPHINCSSHA2256FROBUST_AVX2_CRYPTO_SEEDBYTES 96 + +/* + * Returns the length of a secret key, in bytes + */ +size_t PQCLEAN_SPHINCSSHA2256FROBUST_AVX2_crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +size_t PQCLEAN_SPHINCSSHA2256FROBUST_AVX2_crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +size_t PQCLEAN_SPHINCSSHA2256FROBUST_AVX2_crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +size_t PQCLEAN_SPHINCSSHA2256FROBUST_AVX2_crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +int PQCLEAN_SPHINCSSHA2256FROBUST_AVX2_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +int PQCLEAN_SPHINCSSHA2256FROBUST_AVX2_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +int PQCLEAN_SPHINCSSHA2256FROBUST_AVX2_crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +int PQCLEAN_SPHINCSSHA2256FROBUST_AVX2_crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, + const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +int PQCLEAN_SPHINCSSHA2256FROBUST_AVX2_crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +int PQCLEAN_SPHINCSSHA2256FROBUST_AVX2_crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/context.h b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/context.h new file mode 100644 index 0000000000..d3bf1c3aac --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/context.h @@ -0,0 +1,29 @@ +#ifndef SPX_CONTEXT_H +#define SPX_CONTEXT_H + +#include + +#include "params.h" +#include "sha2.h" +#include "sha256avx.h" +#include "sha512x4.h" + +// funky ordering due to optimal padding +typedef struct { + sha256x8ctx statex8_seeded; + sha512x4ctx statex4_seeded_512; + sha256ctx state_seeded; + sha512ctx state_seeded_512; + + uint8_t pub_seed[SPX_N]; + uint8_t sk_seed[SPX_N]; +} spx_ctx; + + +#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) +void initialize_hash_function(spx_ctx *ctx); + +#define free_hash_function SPX_NAMESPACE(free_hash_function) +void free_hash_function(spx_ctx *ctx); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/context_sha2.c b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/context_sha2.c new file mode 100644 index 0000000000..83c1b6585d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/context_sha2.c @@ -0,0 +1,56 @@ +#include + +#include "context.h" + +/** + * Absorb the constant pub_seed using one round of the compression function + * This initializes state_seeded and state_seeded_512, which can then be + * reused in thash + **/ +static void seed_state(spx_ctx *ctx) { + uint8_t block[SPX_SHA512_BLOCK_BYTES]; + size_t i; + + for (i = 0; i < SPX_N; ++i) { + block[i] = ctx->pub_seed[i]; + } + for (i = SPX_N; i < SPX_SHA512_BLOCK_BYTES; ++i) { + block[i] = 0; + } + /* block has been properly initialized for both SHA-256 and SHA-512 */ + + sha256_inc_init(&ctx->state_seeded); + sha256_inc_blocks(&ctx->state_seeded, block, 1); + + // initialize x8 + sha256_init8x(&ctx->statex8_seeded); + sha256_transform8x(&ctx->statex8_seeded, + block, block, block, block, block, block, block, block); + + ctx->statex8_seeded.datalen = 0; + ctx->statex8_seeded.msglen = 512; + + sha512_inc_init(&ctx->state_seeded_512); + sha512_inc_blocks(&ctx->state_seeded_512, block, 1); + + // initialize x4 + sha512_init4x(&ctx->statex4_seeded_512); + sha512_transform4x(&ctx->statex4_seeded_512, block, block, block, block); + + ctx->statex4_seeded_512.datalen = 0; + ctx->statex4_seeded_512.msglen = 1024; + + +} + + +/* For SHA, we initialize the hash function at the start */ +void initialize_hash_function(spx_ctx *ctx) { + seed_state(ctx); +} + +/* Free the incremental hashing context for heap-based SHA2 APIs */ +void free_hash_function(spx_ctx *ctx) { + sha256_inc_ctx_release(&ctx->state_seeded); + sha512_inc_ctx_release(&ctx->state_seeded_512); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/fors.c b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/fors.c new file mode 100644 index 0000000000..4cab8e7415 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/fors.c @@ -0,0 +1,226 @@ +#include +#include +#include + +#include "fors.h" + + +#include "address.h" +#include "hash.h" +#include "hashx8.h" +#include "thash.h" +#include "thashx8.h" +#include "utils.h" +#include "utilsx8.h" +static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + prf_addr(sk, ctx, fors_leaf_addr); +} + +static void fors_gen_skx8(unsigned char *sk0, + unsigned char *sk1, + unsigned char *sk2, + unsigned char *sk3, + unsigned char *sk4, + unsigned char *sk5, + unsigned char *sk6, + unsigned char *sk7, const spx_ctx *ctx, + uint32_t fors_leaf_addrx8[8 * 8]) { + prf_addrx8(sk0, sk1, sk2, sk3, sk4, sk5, sk6, sk7, + ctx, fors_leaf_addrx8); +} + +static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, + const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + thash(leaf, sk, 1, ctx, fors_leaf_addr); +} + +static void fors_sk_to_leafx8(unsigned char *leaf0, + unsigned char *leaf1, + unsigned char *leaf2, + unsigned char *leaf3, + unsigned char *leaf4, + unsigned char *leaf5, + unsigned char *leaf6, + unsigned char *leaf7, + const unsigned char *sk0, + const unsigned char *sk1, + const unsigned char *sk2, + const unsigned char *sk3, + const unsigned char *sk4, + const unsigned char *sk5, + const unsigned char *sk6, + const unsigned char *sk7, + const spx_ctx *ctx, + uint32_t fors_leaf_addrx8[8 * 8]) { + thashx8(leaf0, leaf1, leaf2, leaf3, leaf4, leaf5, leaf6, leaf7, + sk0, sk1, sk2, sk3, sk4, sk5, sk6, sk7, + 1, ctx, fors_leaf_addrx8); +} + +struct fors_gen_leaf_info { + uint32_t leaf_addrx[8 * 8]; +}; + +static void fors_gen_leafx8(unsigned char *leaf, + const spx_ctx *ctx, + uint32_t addr_idx, void *info) { + struct fors_gen_leaf_info *fors_info = info; + uint32_t *fors_leaf_addrx8 = fors_info->leaf_addrx; + unsigned int j; + + /* Only set the parts that the caller doesn't set */ + for (j = 0; j < 8; j++) { + set_tree_index(fors_leaf_addrx8 + j * 8, addr_idx + j); + set_type(fors_leaf_addrx8 + j * 8, SPX_ADDR_TYPE_FORSPRF); + } + + fors_gen_skx8(leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + leaf + 2 * SPX_N, + leaf + 3 * SPX_N, + leaf + 4 * SPX_N, + leaf + 5 * SPX_N, + leaf + 6 * SPX_N, + leaf + 7 * SPX_N, + ctx, fors_leaf_addrx8); + + for (j = 0; j < 8; j++) { + set_type(fors_leaf_addrx8 + j * 8, SPX_ADDR_TYPE_FORSTREE); + } + + fors_sk_to_leafx8(leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + leaf + 2 * SPX_N, + leaf + 3 * SPX_N, + leaf + 4 * SPX_N, + leaf + 5 * SPX_N, + leaf + 6 * SPX_N, + leaf + 7 * SPX_N, + leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + leaf + 2 * SPX_N, + leaf + 3 * SPX_N, + leaf + 4 * SPX_N, + leaf + 5 * SPX_N, + leaf + 6 * SPX_N, + leaf + 7 * SPX_N, + ctx, fors_leaf_addrx8); +} + +/** + * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + * Assumes indices has space for SPX_FORS_TREES integers. + */ +static void message_to_indices(uint32_t *indices, const unsigned char *m) { + unsigned int i, j; + unsigned int offset = 0; + + for (i = 0; i < SPX_FORS_TREES; i++) { + indices[i] = 0; + for (j = 0; j < SPX_FORS_HEIGHT; j++) { + indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); + offset++; + } + } +} + +/** + * Signs a message m, deriving the secret key from sk_seed and the FTS address. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + uint32_t fors_tree_addr[8 * 8] = {0}; + struct fors_gen_leaf_info fors_info = {0}; + uint32_t *fors_leaf_addr = fors_info.leaf_addrx; + uint32_t fors_pk_addr[8] = {0}; + uint32_t idx_offset; + unsigned int i; + + for (i = 0; i < 8; i++) { + copy_keypair_addr(fors_tree_addr + 8 * i, fors_addr); + set_type(fors_tree_addr + 8 * i, SPX_ADDR_TYPE_FORSTREE); + copy_keypair_addr(fors_leaf_addr + 8 * i, fors_addr); + } + copy_keypair_addr(fors_pk_addr, fors_addr); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); + + message_to_indices(indices, m); + + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); + + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + + /* Include the secret key part that produces the selected leaf node. */ + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); + fors_gen_sk(sig, ctx, fors_tree_addr); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + sig += SPX_N; + + /* Compute the authentication path for this leaf node. */ + treehashx8(roots + i * SPX_N, sig, ctx, + indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx8, + fors_tree_addr, &fors_info); + + sig += SPX_N * SPX_FORS_HEIGHT; + } + + /* Hash horizontally across all tree roots to derive the public key. */ + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); +} + +/** + * Derives the FORS public key from a signature. + * This can be used for verification by comparing to a known public key, or to + * subsequently verify a signature on the derived public key. The latter is the + * typical use-case when used as an FTS below an OTS in a hypertree. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + unsigned char leaf[SPX_N]; + uint32_t fors_tree_addr[8] = {0}; + uint32_t fors_pk_addr[8] = {0}; + uint32_t idx_offset; + unsigned int i; + + copy_keypair_addr(fors_tree_addr, fors_addr); + copy_keypair_addr(fors_pk_addr, fors_addr); + + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); + + message_to_indices(indices, m); + + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); + + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + + /* Derive the leaf from the included secret key part. */ + fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); + sig += SPX_N; + + /* Derive the corresponding root node of this tree. */ + compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, + sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); + sig += SPX_N * SPX_FORS_HEIGHT; + } + + /* Hash horizontally across all tree roots to derive the public key. */ + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/fors.h b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/fors.h new file mode 100644 index 0000000000..509140a178 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/fors.h @@ -0,0 +1,32 @@ +#ifndef SPX_FORS_H +#define SPX_FORS_H + +#include + +#include "context.h" +#include "params.h" + +/** + * Signs a message m, deriving the secret key from sk_seed and the FTS address. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +#define fors_sign SPX_NAMESPACE(fors_sign) +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); + +/** + * Derives the FORS public key from a signature. + * This can be used for verification by comparing to a known public key, or to + * subsequently verify a signature on the derived public key. The latter is the + * typical use-case when used as an FTS below an OTS in a hypertree. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/hash.h b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/hash.h new file mode 100644 index 0000000000..ffe815f45d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/hash.h @@ -0,0 +1,37 @@ +#ifndef SPX_HASH_H +#define SPX_HASH_H + +#include +#include + +#include "context.h" +#include "params.h" + +#define prf_addr SPX_NAMESPACE(prf_addr) +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]); + +#define gen_message_random SPX_NAMESPACE(gen_message_random) +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); + +#define hash_message SPX_NAMESPACE(hash_message) +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); + + +# define SPX_SHA256_ADDR_BYTES 22 + +# define mgf1_256 SPX_NAMESPACE(mgf1_256) +void mgf1_256(unsigned char *out, unsigned long outlen, + const unsigned char *in, unsigned long inlen); + +# define mgf1_512 SPX_NAMESPACE(mgf1_512) +void mgf1_512(unsigned char *out, unsigned long outlen, + const unsigned char *in, unsigned long inlen); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/hash_sha2.c b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/hash_sha2.c new file mode 100644 index 0000000000..3d0085c8c1 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/hash_sha2.c @@ -0,0 +1,219 @@ +#include +#include + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "sha2.h" +#include "utils.h" + + + +#define SPX_SHAX_OUTPUT_BYTES SPX_SHA512_OUTPUT_BYTES +#define SPX_SHAX_BLOCK_BYTES SPX_SHA512_BLOCK_BYTES +#define shaX_inc_init sha512_inc_init +#define shaX_inc_blocks sha512_inc_blocks +#define shaX_inc_finalize sha512_inc_finalize +#define shaX sha512 +#define mgf1_X mgf1_512 +#define shaXstate sha512ctx + +/** + * mgf1 function based on the SHA-256 hash function + * Note that inlen should be sufficiently small that it still allows for + * an array to be allocated on the stack. Typically 'in' is merely a seed. + * Outputs outlen number of bytes + */ +void mgf1_256(unsigned char *out, unsigned long outlen, + const unsigned char *in, unsigned long inlen) { + PQCLEAN_VLA(uint8_t, inbuf, inlen + 4); + unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES]; + uint32_t i; + + memcpy(inbuf, in, inlen); + + /* While we can fit in at least another full block of SHA256 output.. */ + for (i = 0; (i + 1)*SPX_SHA256_OUTPUT_BYTES <= outlen; i++) { + u32_to_bytes(inbuf + inlen, i); + sha256(out, inbuf, inlen + 4); + out += SPX_SHA256_OUTPUT_BYTES; + } + /* Until we cannot anymore, and we fill the remainder. */ + if (outlen > i * SPX_SHA256_OUTPUT_BYTES) { + u32_to_bytes(inbuf + inlen, i); + sha256(outbuf, inbuf, inlen + 4); + memcpy(out, outbuf, outlen - i * SPX_SHA256_OUTPUT_BYTES); + } +} + +/* + * mgf1 function based on the SHA-512 hash function + */ +void mgf1_512(unsigned char *out, unsigned long outlen, + const unsigned char *in, unsigned long inlen) { + PQCLEAN_VLA(uint8_t, inbuf, inlen + 4); + unsigned char outbuf[SPX_SHA512_OUTPUT_BYTES]; + uint32_t i; + + memcpy(inbuf, in, inlen); + + /* While we can fit in at least another full block of SHA512 output.. */ + for (i = 0; (i + 1)*SPX_SHA512_OUTPUT_BYTES <= outlen; i++) { + u32_to_bytes(inbuf + inlen, i); + sha512(out, inbuf, inlen + 4); + out += SPX_SHA512_OUTPUT_BYTES; + } + /* Until we cannot anymore, and we fill the remainder. */ + if (outlen > i * SPX_SHA512_OUTPUT_BYTES) { + u32_to_bytes(inbuf + inlen, i); + sha512(outbuf, inbuf, inlen + 4); + memcpy(out, outbuf, outlen - i * SPX_SHA512_OUTPUT_BYTES); + } +} + +/* + * Computes PRF(pk_seed, sk_seed, addr). + */ +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]) { + sha256ctx sha2_state; + unsigned char buf[SPX_SHA256_ADDR_BYTES + SPX_N]; + unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES]; + + /* Retrieve precomputed state containing pub_seed */ + sha256_inc_ctx_clone(&sha2_state, &ctx->state_seeded); + + /* Remainder: ADDR^c ‖ SK.seed */ + memcpy(buf, addr, SPX_SHA256_ADDR_BYTES); + memcpy(buf + SPX_SHA256_ADDR_BYTES, ctx->sk_seed, SPX_N); + + sha256_inc_finalize(outbuf, &sha2_state, buf, SPX_SHA256_ADDR_BYTES + SPX_N); + + memcpy(out, outbuf, SPX_N); +} + +/** + * Computes the message-dependent randomness R, using a secret seed as a key + * for HMAC, and an optional randomization value prefixed to the message. + * This requires m to have at least SPX_SHAX_BLOCK_BYTES + SPX_N space + * available in front of the pointer, i.e. before the message to use for the + * prefix. This is necessary to prevent having to move the message around (and + * allocate memory for it). + */ +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { + (void)ctx; + + unsigned char buf[SPX_SHAX_BLOCK_BYTES + SPX_SHAX_OUTPUT_BYTES]; + shaXstate state; + int i; + + + /* This implements HMAC-SHA */ + for (i = 0; i < SPX_N; i++) { + buf[i] = 0x36 ^ sk_prf[i]; + } + memset(buf + SPX_N, 0x36, SPX_SHAX_BLOCK_BYTES - SPX_N); + + shaX_inc_init(&state); + shaX_inc_blocks(&state, buf, 1); + + memcpy(buf, optrand, SPX_N); + + /* If optrand + message cannot fill up an entire block */ + if (SPX_N + mlen < SPX_SHAX_BLOCK_BYTES) { + memcpy(buf + SPX_N, m, mlen); + shaX_inc_finalize(buf + SPX_SHAX_BLOCK_BYTES, &state, + buf, mlen + SPX_N); + } + /* Otherwise first fill a block, so that finalize only uses the message */ + else { + memcpy(buf + SPX_N, m, SPX_SHAX_BLOCK_BYTES - SPX_N); + shaX_inc_blocks(&state, buf, 1); + + m += SPX_SHAX_BLOCK_BYTES - SPX_N; + mlen -= SPX_SHAX_BLOCK_BYTES - SPX_N; + shaX_inc_finalize(buf + SPX_SHAX_BLOCK_BYTES, &state, m, mlen); + } + + for (i = 0; i < SPX_N; i++) { + buf[i] = 0x5c ^ sk_prf[i]; + } + memset(buf + SPX_N, 0x5c, SPX_SHAX_BLOCK_BYTES - SPX_N); + + shaX(buf, buf, SPX_SHAX_BLOCK_BYTES + SPX_SHAX_OUTPUT_BYTES); + memcpy(R, buf, SPX_N); +} + +/** + * Computes the message hash using R, the public key, and the message. + * Outputs the message digest and the index of the leaf. The index is split in + * the tree index and the leaf index, for convenient copying to an address. + */ +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { + (void)ctx; +#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) +#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) +#define SPX_LEAF_BITS SPX_TREE_HEIGHT +#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) +#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) + + unsigned char seed[2 * SPX_N + SPX_SHAX_OUTPUT_BYTES]; + + /* Round to nearest multiple of SPX_SHAX_BLOCK_BYTES */ +#define SPX_INBLOCKS (((SPX_N + SPX_PK_BYTES + SPX_SHAX_BLOCK_BYTES - 1) & \ + -SPX_SHAX_BLOCK_BYTES) / SPX_SHAX_BLOCK_BYTES) + unsigned char inbuf[SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES]; + + unsigned char buf[SPX_DGST_BYTES]; + unsigned char *bufp = buf; + shaXstate state; + + shaX_inc_init(&state); + + // seed: SHA-X(R ‖ PK.seed ‖ PK.root ‖ M) + memcpy(inbuf, R, SPX_N); + memcpy(inbuf + SPX_N, pk, SPX_PK_BYTES); + + /* If R + pk + message cannot fill up an entire block */ + if (SPX_N + SPX_PK_BYTES + mlen < SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES) { + memcpy(inbuf + SPX_N + SPX_PK_BYTES, m, mlen); + shaX_inc_finalize(seed + 2 * SPX_N, &state, inbuf, SPX_N + SPX_PK_BYTES + mlen); + } + /* Otherwise first fill a block, so that finalize only uses the message */ + else { + memcpy(inbuf + SPX_N + SPX_PK_BYTES, m, + SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES - SPX_N - SPX_PK_BYTES); + shaX_inc_blocks(&state, inbuf, SPX_INBLOCKS); + + m += SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES - SPX_N - SPX_PK_BYTES; + mlen -= SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES - SPX_N - SPX_PK_BYTES; + shaX_inc_finalize(seed + 2 * SPX_N, &state, m, (size_t)mlen); + } + + // H_msg: MGF1-SHA-X(R ‖ PK.seed ‖ seed) + memcpy(seed, R, SPX_N); + memcpy(seed + SPX_N, pk, SPX_N); + + /* By doing this in two steps, we prevent hashing the message twice; + otherwise each iteration in MGF1 would hash the message again. */ + mgf1_X(bufp, SPX_DGST_BYTES, seed, 2 * SPX_N + SPX_SHAX_OUTPUT_BYTES); + + memcpy(digest, bufp, SPX_FORS_MSG_BYTES); + bufp += SPX_FORS_MSG_BYTES; + + + *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); + *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); + bufp += SPX_TREE_BYTES; + + *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); + *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); +} + + diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/hash_sha2x8.c b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/hash_sha2x8.c new file mode 100644 index 0000000000..e04af7a069 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/hash_sha2x8.c @@ -0,0 +1,75 @@ +#include +#include + +#include "hash.h" +#include "hashx8.h" + +#include "address.h" +#include "params.h" +#include "sha2.h" +#include "sha256avx.h" +#include "sha256x8.h" +#include "utils.h" + +/* + * 8-way parallel version of prf_addr; takes 8x as much input and output + */ +void prf_addrx8(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const spx_ctx *ctx, + const uint32_t addrx8[8 * 8]) { + unsigned char bufx8[8 * (SPX_N + SPX_SHA256_ADDR_BYTES)]; + unsigned char outbufx8[8 * SPX_SHA256_OUTPUT_BYTES]; + unsigned int j; + + for (j = 0; j < 8; j++) { + memcpy(bufx8 + j * (SPX_N + SPX_SHA256_ADDR_BYTES), + addrx8 + j * 8, SPX_SHA256_ADDR_BYTES); + memcpy( + bufx8 + j * (SPX_N + SPX_SHA256_ADDR_BYTES) + SPX_SHA256_ADDR_BYTES, + ctx->sk_seed, + SPX_N + ); + } + + sha256x8_seeded( + /* out */ + outbufx8 + 0 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 1 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 2 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 3 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 4 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 5 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 6 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 7 * SPX_SHA256_OUTPUT_BYTES, + + /* seed */ + &ctx->statex8_seeded, + + /* in */ + bufx8 + 0 * (SPX_SHA256_ADDR_BYTES + SPX_N), + bufx8 + 1 * (SPX_SHA256_ADDR_BYTES + SPX_N), + bufx8 + 2 * (SPX_SHA256_ADDR_BYTES + SPX_N), + bufx8 + 3 * (SPX_SHA256_ADDR_BYTES + SPX_N), + bufx8 + 4 * (SPX_SHA256_ADDR_BYTES + SPX_N), + bufx8 + 5 * (SPX_SHA256_ADDR_BYTES + SPX_N), + bufx8 + 6 * (SPX_SHA256_ADDR_BYTES + SPX_N), + bufx8 + 7 * (SPX_SHA256_ADDR_BYTES + SPX_N), + SPX_SHA256_ADDR_BYTES + SPX_N /* len */ + ); + + memcpy(out0, outbufx8 + 0 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out1, outbufx8 + 1 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out2, outbufx8 + 2 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out3, outbufx8 + 3 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out4, outbufx8 + 4 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out5, outbufx8 + 5 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out6, outbufx8 + 6 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out7, outbufx8 + 7 * SPX_SHA256_OUTPUT_BYTES, SPX_N); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/hashx8.h b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/hashx8.h new file mode 100644 index 0000000000..46503f0a10 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/hashx8.h @@ -0,0 +1,20 @@ +#ifndef SPX_HASHX8_H +#define SPX_HASHX8_H + +#include + +#include "params.h" + +#define prf_addrx8 SPX_NAMESPACE(prf_addrx8) +void prf_addrx8(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const spx_ctx *ctx, + const uint32_t addrx8[8 * 8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/merkle.c b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/merkle.c new file mode 100644 index 0000000000..1f353c8dd8 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/merkle.c @@ -0,0 +1,65 @@ +#include +#include + +#include "merkle.h" + +#include "address.h" +#include "params.h" +#include "utils.h" +#include "utilsx8.h" +#include "wots.h" +#include "wotsx8.h" + +/* + * This generates a Merkle signature (WOTS signature followed by the Merkle + * authentication path). + */ +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf) { + unsigned char *auth_path = sig + SPX_WOTS_BYTES; + uint32_t tree_addrx8[8 * 8] = { 0 }; + int j; + struct leaf_info_x8 info = { 0 }; + unsigned steps[ SPX_WOTS_LEN ]; + + info.wots_sig = sig; + chain_lengths(steps, root); + info.wots_steps = steps; + + for (j = 0; j < 8; j++) { + set_type(&tree_addrx8[8 * j], SPX_ADDR_TYPE_HASHTREE); + set_type(&info.leaf_addr[8 * j], SPX_ADDR_TYPE_WOTS); + set_type(&info.pk_addr[8 * j], SPX_ADDR_TYPE_WOTSPK); + copy_subtree_addr(&tree_addrx8[8 * j], tree_addr); + copy_subtree_addr(&info.leaf_addr[8 * j], wots_addr); + copy_subtree_addr(&info.pk_addr[8 * j], wots_addr); + } + + info.wots_sign_leaf = idx_leaf; + + treehashx8(root, auth_path, ctx, + idx_leaf, 0, + SPX_TREE_HEIGHT, + wots_gen_leafx8, + tree_addrx8, &info); +} + +/* Compute root node of the top-most subtree. */ +/* Again, in this file because wots_gen_leaf is most of the work */ +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { + /* We do not need the auth path in key generation, but it simplifies the + code to have just one treehash routine that computes both root and path + in one function. */ + unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; + uint32_t top_tree_addr[8] = {0}; + uint32_t wots_addr[8] = {0}; + + set_layer_addr(top_tree_addr, SPX_D - 1); + set_layer_addr(wots_addr, SPX_D - 1); + + merkle_sign(auth_path, root, ctx, + wots_addr, top_tree_addr, + ~0U /* ~0 means "don't bother generating an auth path */ ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/merkle.h b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/merkle.h new file mode 100644 index 0000000000..769cf2e970 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/merkle.h @@ -0,0 +1,21 @@ +#ifndef MERKLE_H_ +#define MERKLE_H_ + +#include + +#include "context.h" +#include "params.h" + +/* Generate a Merkle signature (WOTS signature followed by the Merkle */ +/* authentication path) */ +#define merkle_sign SPX_NAMESPACE(merkle_sign) +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf); + +/* Compute the root node of the top-most subtree. */ +#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); + +#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/nistapi.h b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/nistapi.h new file mode 100644 index 0000000000..3cb71afad4 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/nistapi.h @@ -0,0 +1,87 @@ +#ifndef SPX_API_H +#define SPX_API_H + +#include +#include + +#include "params.h" + +#define CRYPTO_ALGNAME "SPHINCS+" + +#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES +#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES +#define CRYPTO_BYTES SPX_BYTES +#define CRYPTO_SEEDBYTES (3*SPX_N) + +/* + * Returns the length of a secret key, in bytes + */ +#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) +size_t crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) +size_t crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) +size_t crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) +size_t crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +#define crypto_sign SPX_NAMESPACE(crypto_sign) +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/params.h b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/params.h new file mode 100644 index 0000000000..4d40f55ed9 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/params.h @@ -0,0 +1,61 @@ +#ifndef SPX_PARAMS_H +#define SPX_PARAMS_H + +#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSSHA2256FROBUST_AVX2_##s + +/* Hash output length in bytes. */ +#define SPX_N 32 +/* Height of the hypertree. */ +#define SPX_FULL_HEIGHT 68 +/* Number of subtree layer. */ +#define SPX_D 17 +/* FORS tree dimensions. */ +#define SPX_FORS_HEIGHT 9 +#define SPX_FORS_TREES 35 +/* Winternitz parameter, */ +#define SPX_WOTS_W 16 + +/* The hash function is defined by linking a different hash.c file, as opposed + to setting a #define constant. */ + +/* This is a SHA2-based parameter set, hence whether we use SHA-256 + * exclusively or we use both SHA-256 and SHA-512 is controlled by + * the following #define */ +#define SPX_SHA512 1 /* Use SHA-512 for H and T_l, l >= 2 */ + +/* For clarity */ +#define SPX_ADDR_BYTES 32 + +/* WOTS parameters. */ +#define SPX_WOTS_LOGW 4 + +#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) + +/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ +#define SPX_WOTS_LEN2 3 + +#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) +#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) +#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES + +/* Subtree size. */ +#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) + +//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT +// #error SPX_D should always divide SPX_FULL_HEIGHT +//#endif + +/* FORS parameters. */ +#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) +#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) +#define SPX_FORS_PK_BYTES SPX_N + +/* Resulting SPX sizes. */ +#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ + SPX_FULL_HEIGHT * SPX_N) +#define SPX_PK_BYTES (2 * SPX_N) +#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) + +#include "sha2_offsets.h" + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/sha256avx.c b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/sha256avx.c new file mode 100644 index 0000000000..6bbe6ecc24 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/sha256avx.c @@ -0,0 +1,357 @@ +#include +#include +#include + +#include "sha256avx.h" + +static const unsigned int RC[] = { + 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, + 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, + 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, + 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, + 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, + 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, + 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, + 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, + 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, + 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, + 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, + 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, + 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, + 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, + 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, + 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 +}; + +#define u32 uint32_t +#define u256 __m256i + +#define XOR _mm256_xor_si256 +#define OR _mm256_or_si256 +#define AND _mm256_and_si256 +#define ADD32 _mm256_add_epi32 +#define NOT(x) _mm256_xor_si256(x, _mm256_set_epi32(-1, -1, -1, -1, -1, -1, -1, -1)) + +#define LOAD(src) _mm256_loadu_si256((__m256i *)(src)) +#define STORE(dest,src) _mm256_storeu_si256((__m256i *)(dest),src) + +#define BYTESWAP(x) _mm256_shuffle_epi8(x, _mm256_set_epi8(0xc,0xd,0xe,0xf,0x8,0x9,0xa,0xb,0x4,0x5,0x6,0x7,0x0,0x1,0x2,0x3,0xc,0xd,0xe,0xf,0x8,0x9,0xa,0xb,0x4,0x5,0x6,0x7,0x0,0x1,0x2,0x3)) + +#define SHIFTR32(x, y) _mm256_srli_epi32(x, y) +#define SHIFTL32(x, y) _mm256_slli_epi32(x, y) + +#define ROTR32(x, y) OR(SHIFTR32(x, y), SHIFTL32(x, 32 - (y))) +#define ROTL32(x, y) OR(SHIFTL32(x, y), SHIFTR32(x, 32 - (y))) + +#define XOR3(a, b, c) XOR(XOR(a, b), c) + +#define ADD3_32(a, b, c) ADD32(ADD32(a, b), c) +#define ADD4_32(a, b, c, d) ADD32(ADD32(ADD32(a, b), c), d) +#define ADD5_32(a, b, c, d, e) ADD32(ADD32(ADD32(ADD32(a, b), c), d), e) + +#define MAJ_AVX(a, b, c) XOR3(AND(a, b), AND(a, c), AND(b, c)) +#define CH_AVX(a, b, c) XOR(AND(a, b), AND(NOT(a), c)) + +#define SIGMA1_AVX(x) XOR3(ROTR32(x, 6), ROTR32(x, 11), ROTR32(x, 25)) +#define SIGMA0_AVX(x) XOR3(ROTR32(x, 2), ROTR32(x, 13), ROTR32(x, 22)) + +#define WSIGMA1_AVX(x) XOR3(ROTR32(x, 17), ROTR32(x, 19), SHIFTR32(x, 10)) +#define WSIGMA0_AVX(x) XOR3(ROTR32(x, 7), ROTR32(x, 18), SHIFTR32(x, 3)) + +#define SHA256ROUND_AVX(a, b, c, d, e, f, g, h, rc, w) \ + T0 = ADD5_32(h, SIGMA1_AVX(e), CH_AVX(e, f, g), _mm256_set1_epi32((int)RC[rc]), w); \ + (d) = ADD32(d, T0); \ + T1 = ADD32(SIGMA0_AVX(a), MAJ_AVX(a, b, c)); \ + (h) = ADD32(T0, T1); + +// Transpose 8 vectors containing 32-bit values +static void transpose(u256 s[8]) { + u256 tmp0[8]; + u256 tmp1[8]; + tmp0[0] = _mm256_unpacklo_epi32(s[0], s[1]); + tmp0[1] = _mm256_unpackhi_epi32(s[0], s[1]); + tmp0[2] = _mm256_unpacklo_epi32(s[2], s[3]); + tmp0[3] = _mm256_unpackhi_epi32(s[2], s[3]); + tmp0[4] = _mm256_unpacklo_epi32(s[4], s[5]); + tmp0[5] = _mm256_unpackhi_epi32(s[4], s[5]); + tmp0[6] = _mm256_unpacklo_epi32(s[6], s[7]); + tmp0[7] = _mm256_unpackhi_epi32(s[6], s[7]); + tmp1[0] = _mm256_unpacklo_epi64(tmp0[0], tmp0[2]); + tmp1[1] = _mm256_unpackhi_epi64(tmp0[0], tmp0[2]); + tmp1[2] = _mm256_unpacklo_epi64(tmp0[1], tmp0[3]); + tmp1[3] = _mm256_unpackhi_epi64(tmp0[1], tmp0[3]); + tmp1[4] = _mm256_unpacklo_epi64(tmp0[4], tmp0[6]); + tmp1[5] = _mm256_unpackhi_epi64(tmp0[4], tmp0[6]); + tmp1[6] = _mm256_unpacklo_epi64(tmp0[5], tmp0[7]); + tmp1[7] = _mm256_unpackhi_epi64(tmp0[5], tmp0[7]); + s[0] = _mm256_permute2x128_si256(tmp1[0], tmp1[4], 0x20); + s[1] = _mm256_permute2x128_si256(tmp1[1], tmp1[5], 0x20); + s[2] = _mm256_permute2x128_si256(tmp1[2], tmp1[6], 0x20); + s[3] = _mm256_permute2x128_si256(tmp1[3], tmp1[7], 0x20); + s[4] = _mm256_permute2x128_si256(tmp1[0], tmp1[4], 0x31); + s[5] = _mm256_permute2x128_si256(tmp1[1], tmp1[5], 0x31); + s[6] = _mm256_permute2x128_si256(tmp1[2], tmp1[6], 0x31); + s[7] = _mm256_permute2x128_si256(tmp1[3], tmp1[7], 0x31); +} + +void sha256_ctx_clone8x(sha256x8ctx *out, const sha256x8ctx *in) { + memcpy(out, in, sizeof(sha256x8ctx)); +} + +void sha256_init8x(sha256x8ctx *ctx) { + ctx->s[0] = _mm256_set_epi32((int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667); + ctx->s[1] = _mm256_set_epi32((int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85); + ctx->s[2] = _mm256_set_epi32((int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372); + ctx->s[3] = _mm256_set_epi32((int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a); + ctx->s[4] = _mm256_set_epi32((int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f); + ctx->s[5] = _mm256_set_epi32((int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c); + ctx->s[6] = _mm256_set_epi32((int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab); + ctx->s[7] = _mm256_set_epi32((int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19); + + ctx->datalen = 0; + ctx->msglen = 0; +} + +void sha256_final8x(sha256x8ctx *ctx, + unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7) { + unsigned int i, curlen; + + // Padding + if (ctx->datalen < 56) { + for (i = 0; i < 8; ++i) { + curlen = ctx->datalen; + ctx->msgblocks[64 * i + curlen++] = 0x80; + while (curlen < 64) { + ctx->msgblocks[64 * i + curlen++] = 0x00; + } + } + } else { + for (i = 0; i < 8; ++i) { + curlen = ctx->datalen; + ctx->msgblocks[64 * i + curlen++] = 0x80; + while (curlen < 64) { + ctx->msgblocks[64 * i + curlen++] = 0x00; + } + } + sha256_transform8x(ctx, + &ctx->msgblocks[64 * 0], + &ctx->msgblocks[64 * 1], + &ctx->msgblocks[64 * 2], + &ctx->msgblocks[64 * 3], + &ctx->msgblocks[64 * 4], + &ctx->msgblocks[64 * 5], + &ctx->msgblocks[64 * 6], + &ctx->msgblocks[64 * 7] + ); + memset(ctx->msgblocks, 0, 8 * 64); + } + + // Add length of the message to each block + ctx->msglen += ctx->datalen * 8; + for (i = 0; i < 8; i++) { + ctx->msgblocks[64 * i + 63] = (unsigned char)(ctx->msglen); + ctx->msgblocks[64 * i + 62] = (unsigned char)(ctx->msglen >> 8); + ctx->msgblocks[64 * i + 61] = (unsigned char)(ctx->msglen >> 16); + ctx->msgblocks[64 * i + 60] = (unsigned char)(ctx->msglen >> 24); + ctx->msgblocks[64 * i + 59] = (unsigned char)(ctx->msglen >> 32); + ctx->msgblocks[64 * i + 58] = (unsigned char)(ctx->msglen >> 40); + ctx->msgblocks[64 * i + 57] = (unsigned char)(ctx->msglen >> 48); + ctx->msgblocks[64 * i + 56] = (unsigned char)(ctx->msglen >> 56); + } + sha256_transform8x(ctx, + &ctx->msgblocks[64 * 0], + &ctx->msgblocks[64 * 1], + &ctx->msgblocks[64 * 2], + &ctx->msgblocks[64 * 3], + &ctx->msgblocks[64 * 4], + &ctx->msgblocks[64 * 5], + &ctx->msgblocks[64 * 6], + &ctx->msgblocks[64 * 7] + ); + + // Compute final hash output + transpose(ctx->s); + + // Store Hash value + STORE(out0, BYTESWAP(ctx->s[0])); + STORE(out1, BYTESWAP(ctx->s[1])); + STORE(out2, BYTESWAP(ctx->s[2])); + STORE(out3, BYTESWAP(ctx->s[3])); + STORE(out4, BYTESWAP(ctx->s[4])); + STORE(out5, BYTESWAP(ctx->s[5])); + STORE(out6, BYTESWAP(ctx->s[6])); + STORE(out7, BYTESWAP(ctx->s[7])); +} + +void sha256_transform8x(sha256x8ctx *ctx, + const unsigned char *data0, + const unsigned char *data1, + const unsigned char *data2, + const unsigned char *data3, + const unsigned char *data4, + const unsigned char *data5, + const unsigned char *data6, + const unsigned char *data7) { + u256 s[8], w[64], T0, T1; + + // Load words and transform data correctly + w[0] = BYTESWAP(LOAD(data0)); + w[0 + 8] = BYTESWAP(LOAD(data0 + 32)); + w[1] = BYTESWAP(LOAD(data1)); + w[1 + 8] = BYTESWAP(LOAD(data1 + 32)); + w[2] = BYTESWAP(LOAD(data2)); + w[2 + 8] = BYTESWAP(LOAD(data2 + 32)); + w[3] = BYTESWAP(LOAD(data3)); + w[3 + 8] = BYTESWAP(LOAD(data3 + 32)); + w[4] = BYTESWAP(LOAD(data4)); + w[4 + 8] = BYTESWAP(LOAD(data4 + 32)); + w[5] = BYTESWAP(LOAD(data5)); + w[5 + 8] = BYTESWAP(LOAD(data5 + 32)); + w[6] = BYTESWAP(LOAD(data6)); + w[6 + 8] = BYTESWAP(LOAD(data6 + 32)); + w[7] = BYTESWAP(LOAD(data7)); + w[7 + 8] = BYTESWAP(LOAD(data7 + 32)); + + transpose(w); + transpose(w + 8); + + // Initial State + s[0] = ctx->s[0]; + s[1] = ctx->s[1]; + s[2] = ctx->s[2]; + s[3] = ctx->s[3]; + s[4] = ctx->s[4]; + s[5] = ctx->s[5]; + s[6] = ctx->s[6]; + s[7] = ctx->s[7]; + + SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 0, w[0]); + SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 1, w[1]); + SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 2, w[2]); + SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 3, w[3]); + SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 4, w[4]); + SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 5, w[5]); + SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 6, w[6]); + SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 7, w[7]); + SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 8, w[8]); + SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 9, w[9]); + SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 10, w[10]); + SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 11, w[11]); + SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 12, w[12]); + SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 13, w[13]); + SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 14, w[14]); + SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 15, w[15]); + w[16] = ADD4_32(WSIGMA1_AVX(w[14]), w[0], w[9], WSIGMA0_AVX(w[1])); + SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 16, w[16]); + w[17] = ADD4_32(WSIGMA1_AVX(w[15]), w[1], w[10], WSIGMA0_AVX(w[2])); + SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 17, w[17]); + w[18] = ADD4_32(WSIGMA1_AVX(w[16]), w[2], w[11], WSIGMA0_AVX(w[3])); + SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 18, w[18]); + w[19] = ADD4_32(WSIGMA1_AVX(w[17]), w[3], w[12], WSIGMA0_AVX(w[4])); + SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 19, w[19]); + w[20] = ADD4_32(WSIGMA1_AVX(w[18]), w[4], w[13], WSIGMA0_AVX(w[5])); + SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 20, w[20]); + w[21] = ADD4_32(WSIGMA1_AVX(w[19]), w[5], w[14], WSIGMA0_AVX(w[6])); + SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 21, w[21]); + w[22] = ADD4_32(WSIGMA1_AVX(w[20]), w[6], w[15], WSIGMA0_AVX(w[7])); + SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 22, w[22]); + w[23] = ADD4_32(WSIGMA1_AVX(w[21]), w[7], w[16], WSIGMA0_AVX(w[8])); + SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 23, w[23]); + w[24] = ADD4_32(WSIGMA1_AVX(w[22]), w[8], w[17], WSIGMA0_AVX(w[9])); + SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 24, w[24]); + w[25] = ADD4_32(WSIGMA1_AVX(w[23]), w[9], w[18], WSIGMA0_AVX(w[10])); + SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 25, w[25]); + w[26] = ADD4_32(WSIGMA1_AVX(w[24]), w[10], w[19], WSIGMA0_AVX(w[11])); + SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 26, w[26]); + w[27] = ADD4_32(WSIGMA1_AVX(w[25]), w[11], w[20], WSIGMA0_AVX(w[12])); + SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 27, w[27]); + w[28] = ADD4_32(WSIGMA1_AVX(w[26]), w[12], w[21], WSIGMA0_AVX(w[13])); + SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 28, w[28]); + w[29] = ADD4_32(WSIGMA1_AVX(w[27]), w[13], w[22], WSIGMA0_AVX(w[14])); + SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 29, w[29]); + w[30] = ADD4_32(WSIGMA1_AVX(w[28]), w[14], w[23], WSIGMA0_AVX(w[15])); + SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 30, w[30]); + w[31] = ADD4_32(WSIGMA1_AVX(w[29]), w[15], w[24], WSIGMA0_AVX(w[16])); + SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 31, w[31]); + w[32] = ADD4_32(WSIGMA1_AVX(w[30]), w[16], w[25], WSIGMA0_AVX(w[17])); + SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 32, w[32]); + w[33] = ADD4_32(WSIGMA1_AVX(w[31]), w[17], w[26], WSIGMA0_AVX(w[18])); + SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 33, w[33]); + w[34] = ADD4_32(WSIGMA1_AVX(w[32]), w[18], w[27], WSIGMA0_AVX(w[19])); + SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 34, w[34]); + w[35] = ADD4_32(WSIGMA1_AVX(w[33]), w[19], w[28], WSIGMA0_AVX(w[20])); + SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 35, w[35]); + w[36] = ADD4_32(WSIGMA1_AVX(w[34]), w[20], w[29], WSIGMA0_AVX(w[21])); + SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 36, w[36]); + w[37] = ADD4_32(WSIGMA1_AVX(w[35]), w[21], w[30], WSIGMA0_AVX(w[22])); + SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 37, w[37]); + w[38] = ADD4_32(WSIGMA1_AVX(w[36]), w[22], w[31], WSIGMA0_AVX(w[23])); + SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 38, w[38]); + w[39] = ADD4_32(WSIGMA1_AVX(w[37]), w[23], w[32], WSIGMA0_AVX(w[24])); + SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 39, w[39]); + w[40] = ADD4_32(WSIGMA1_AVX(w[38]), w[24], w[33], WSIGMA0_AVX(w[25])); + SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 40, w[40]); + w[41] = ADD4_32(WSIGMA1_AVX(w[39]), w[25], w[34], WSIGMA0_AVX(w[26])); + SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 41, w[41]); + w[42] = ADD4_32(WSIGMA1_AVX(w[40]), w[26], w[35], WSIGMA0_AVX(w[27])); + SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 42, w[42]); + w[43] = ADD4_32(WSIGMA1_AVX(w[41]), w[27], w[36], WSIGMA0_AVX(w[28])); + SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 43, w[43]); + w[44] = ADD4_32(WSIGMA1_AVX(w[42]), w[28], w[37], WSIGMA0_AVX(w[29])); + SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 44, w[44]); + w[45] = ADD4_32(WSIGMA1_AVX(w[43]), w[29], w[38], WSIGMA0_AVX(w[30])); + SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 45, w[45]); + w[46] = ADD4_32(WSIGMA1_AVX(w[44]), w[30], w[39], WSIGMA0_AVX(w[31])); + SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 46, w[46]); + w[47] = ADD4_32(WSIGMA1_AVX(w[45]), w[31], w[40], WSIGMA0_AVX(w[32])); + SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 47, w[47]); + w[48] = ADD4_32(WSIGMA1_AVX(w[46]), w[32], w[41], WSIGMA0_AVX(w[33])); + SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 48, w[48]); + w[49] = ADD4_32(WSIGMA1_AVX(w[47]), w[33], w[42], WSIGMA0_AVX(w[34])); + SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 49, w[49]); + w[50] = ADD4_32(WSIGMA1_AVX(w[48]), w[34], w[43], WSIGMA0_AVX(w[35])); + SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 50, w[50]); + w[51] = ADD4_32(WSIGMA1_AVX(w[49]), w[35], w[44], WSIGMA0_AVX(w[36])); + SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 51, w[51]); + w[52] = ADD4_32(WSIGMA1_AVX(w[50]), w[36], w[45], WSIGMA0_AVX(w[37])); + SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 52, w[52]); + w[53] = ADD4_32(WSIGMA1_AVX(w[51]), w[37], w[46], WSIGMA0_AVX(w[38])); + SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 53, w[53]); + w[54] = ADD4_32(WSIGMA1_AVX(w[52]), w[38], w[47], WSIGMA0_AVX(w[39])); + SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 54, w[54]); + w[55] = ADD4_32(WSIGMA1_AVX(w[53]), w[39], w[48], WSIGMA0_AVX(w[40])); + SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 55, w[55]); + w[56] = ADD4_32(WSIGMA1_AVX(w[54]), w[40], w[49], WSIGMA0_AVX(w[41])); + SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 56, w[56]); + w[57] = ADD4_32(WSIGMA1_AVX(w[55]), w[41], w[50], WSIGMA0_AVX(w[42])); + SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 57, w[57]); + w[58] = ADD4_32(WSIGMA1_AVX(w[56]), w[42], w[51], WSIGMA0_AVX(w[43])); + SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 58, w[58]); + w[59] = ADD4_32(WSIGMA1_AVX(w[57]), w[43], w[52], WSIGMA0_AVX(w[44])); + SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 59, w[59]); + w[60] = ADD4_32(WSIGMA1_AVX(w[58]), w[44], w[53], WSIGMA0_AVX(w[45])); + SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 60, w[60]); + w[61] = ADD4_32(WSIGMA1_AVX(w[59]), w[45], w[54], WSIGMA0_AVX(w[46])); + SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 61, w[61]); + w[62] = ADD4_32(WSIGMA1_AVX(w[60]), w[46], w[55], WSIGMA0_AVX(w[47])); + SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 62, w[62]); + w[63] = ADD4_32(WSIGMA1_AVX(w[61]), w[47], w[56], WSIGMA0_AVX(w[48])); + SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 63, w[63]); + + // Feed Forward + ctx->s[0] = ADD32(s[0], ctx->s[0]); + ctx->s[1] = ADD32(s[1], ctx->s[1]); + ctx->s[2] = ADD32(s[2], ctx->s[2]); + ctx->s[3] = ADD32(s[3], ctx->s[3]); + ctx->s[4] = ADD32(s[4], ctx->s[4]); + ctx->s[5] = ADD32(s[5], ctx->s[5]); + ctx->s[6] = ADD32(s[6], ctx->s[6]); + ctx->s[7] = ADD32(s[7], ctx->s[7]); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/sha256avx.h b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/sha256avx.h new file mode 100644 index 0000000000..1e3bcf889b --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/sha256avx.h @@ -0,0 +1,44 @@ +#ifndef SHA256AVX_H +#define SHA256AVX_H + +#include +#include + +#include "params.h" + +typedef struct SHA256state { + __m256i s[8]; + unsigned char msgblocks[8 * 64]; + unsigned int datalen; + unsigned long long msglen; +} sha256x8ctx; + +#define sha256_ctx_clone8x SPX_NAMESPACE(sha256_ctx_clone8x) +void sha256_ctx_clone8x(sha256x8ctx *out, const sha256x8ctx *in); + +#define sha256_init8x SPX_NAMESPACE(sha256_init8x) +void sha256_init8x(sha256x8ctx *ctx); + +#define sha256_final8x SPX_NAMESPACE(sha256_final8x) +void sha256_final8x(sha256x8ctx *ctx, + unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7); + +#define sha256_transform8x SPX_NAMESPACE(sha256_transform8x) +void sha256_transform8x(sha256x8ctx *ctx, + const unsigned char *data0, + const unsigned char *data1, + const unsigned char *data2, + const unsigned char *data3, + const unsigned char *data4, + const unsigned char *data5, + const unsigned char *data6, + const unsigned char *data7); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/sha256x8.c b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/sha256x8.c new file mode 100644 index 0000000000..d97750c09b --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/sha256x8.c @@ -0,0 +1,185 @@ +#include + +#include "sha256avx.h" +#include "sha256x8.h" +#include "utils.h" + +// Performs sha256x8 on an initialized (and perhaps seeded) state. +static void _sha256x8( + sha256x8ctx *ctx, + unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, unsigned long long inlen) { + unsigned long long i = 0; + while (inlen - i >= 64) { + sha256_transform8x(ctx, + in0 + i, + in1 + i, + in2 + i, + in3 + i, + in4 + i, + in5 + i, + in6 + i, + in7 + i + ); + i += 64; + ctx->msglen += 512; + } + + size_t bytes_to_copy = (size_t)(inlen - i); + memcpy(&ctx->msgblocks[64 * 0], in0 + i, bytes_to_copy); + memcpy(&ctx->msgblocks[64 * 1], in1 + i, bytes_to_copy); + memcpy(&ctx->msgblocks[64 * 2], in2 + i, bytes_to_copy); + memcpy(&ctx->msgblocks[64 * 3], in3 + i, bytes_to_copy); + memcpy(&ctx->msgblocks[64 * 4], in4 + i, bytes_to_copy); + memcpy(&ctx->msgblocks[64 * 5], in5 + i, bytes_to_copy); + memcpy(&ctx->msgblocks[64 * 6], in6 + i, bytes_to_copy); + memcpy(&ctx->msgblocks[64 * 7], in7 + i, bytes_to_copy); + ctx->datalen = (unsigned int)bytes_to_copy; + + sha256_final8x(ctx, out0, out1, out2, out3, out4, out5, out6, out7); +} + +void sha256x8_seeded( + unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const sha256x8ctx *seed, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, unsigned long long inlen) { + + sha256x8ctx ctx; + sha256_ctx_clone8x(&ctx, seed); + + _sha256x8(&ctx, out0, out1, out2, out3, out4, out5, out6, out7, + in0, in1, in2, in3, in4, in5, in6, in7, inlen); +} + +/* This provides a wrapper around the internals of 8x parallel SHA256 */ +void sha256x8(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, unsigned long long inlen) { + sha256x8ctx ctx; + sha256_init8x(&ctx); + + _sha256x8(&ctx, out0, out1, out2, out3, out4, out5, out6, out7, + in0, in1, in2, in3, in4, in5, in6, in7, inlen); +} + +/** + * Note that inlen should be sufficiently small that it still allows for + * an array to be allocated on the stack. Typically 'in' is merely a seed. + * Outputs outlen number of bytes + */ +void mgf1x8(unsigned char *outx8, unsigned long outlen, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, + unsigned long inlen) { + PQCLEAN_VLA(unsigned char, inbufx8, 8 * (inlen + 4)); + unsigned char outbufx8[8 * SPX_SHA256_OUTPUT_BYTES]; + uint32_t i; + unsigned int j; + + memcpy(inbufx8 + 0 * (inlen + 4), in0, inlen); + memcpy(inbufx8 + 1 * (inlen + 4), in1, inlen); + memcpy(inbufx8 + 2 * (inlen + 4), in2, inlen); + memcpy(inbufx8 + 3 * (inlen + 4), in3, inlen); + memcpy(inbufx8 + 4 * (inlen + 4), in4, inlen); + memcpy(inbufx8 + 5 * (inlen + 4), in5, inlen); + memcpy(inbufx8 + 6 * (inlen + 4), in6, inlen); + memcpy(inbufx8 + 7 * (inlen + 4), in7, inlen); + + /* While we can fit in at least another full block of SHA256 output.. */ + for (i = 0; (i + 1)*SPX_SHA256_OUTPUT_BYTES <= outlen; i++) { + for (j = 0; j < 8; j++) { + u32_to_bytes(inbufx8 + inlen + j * (inlen + 4), i); + } + + sha256x8(outx8 + 0 * outlen, + outx8 + 1 * outlen, + outx8 + 2 * outlen, + outx8 + 3 * outlen, + outx8 + 4 * outlen, + outx8 + 5 * outlen, + outx8 + 6 * outlen, + outx8 + 7 * outlen, + inbufx8 + 0 * (inlen + 4), + inbufx8 + 1 * (inlen + 4), + inbufx8 + 2 * (inlen + 4), + inbufx8 + 3 * (inlen + 4), + inbufx8 + 4 * (inlen + 4), + inbufx8 + 5 * (inlen + 4), + inbufx8 + 6 * (inlen + 4), + inbufx8 + 7 * (inlen + 4), inlen + 4); + outx8 += SPX_SHA256_OUTPUT_BYTES; + } + /* Until we cannot anymore, and we fill the remainder. */ + for (j = 0; j < 8; j++) { + u32_to_bytes(inbufx8 + inlen + j * (inlen + 4), i); + } + sha256x8(outbufx8 + 0 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 1 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 2 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 3 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 4 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 5 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 6 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 7 * SPX_SHA256_OUTPUT_BYTES, + inbufx8 + 0 * (inlen + 4), + inbufx8 + 1 * (inlen + 4), + inbufx8 + 2 * (inlen + 4), + inbufx8 + 3 * (inlen + 4), + inbufx8 + 4 * (inlen + 4), + inbufx8 + 5 * (inlen + 4), + inbufx8 + 6 * (inlen + 4), + inbufx8 + 7 * (inlen + 4), inlen + 4); + + for (j = 0; j < 8; j++) { + memcpy(outx8 + j * outlen, + outbufx8 + j * SPX_SHA256_OUTPUT_BYTES, + outlen - i * SPX_SHA256_OUTPUT_BYTES); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/sha256x8.h b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/sha256x8.h new file mode 100644 index 0000000000..4f7330a6c1 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/sha256x8.h @@ -0,0 +1,64 @@ +#ifndef SPX_SHA256X8_H +#define SPX_SHA256X8_H + +#include "params.h" +#include "sha256avx.h" + + + +#define sha256x8_seeded SPX_NAMESPACE(sha256x8_seeded) +void sha256x8_seeded( + unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const sha256x8ctx *seed, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, unsigned long long inlen); + +/* This provides a wrapper around the internals of 8x parallel SHA256 */ +#define sha256x8 SPX_NAMESPACE(sha256x8) +void sha256x8(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, unsigned long long inlen); + +/** + * Note that inlen should be sufficiently small that it still allows for + * an array to be allocated on the stack. Typically 'in' is merely a seed. + * Outputs outlen number of bytes + */ +#define mgf1x8 SPX_NAMESPACE(mgf1x8) +void mgf1x8(unsigned char *outx8, unsigned long outlen, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, + unsigned long inlen); +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/sha2_offsets.h b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/sha2_offsets.h new file mode 100644 index 0000000000..6e3584f7a4 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/sha2_offsets.h @@ -0,0 +1,27 @@ +#ifndef SHA2_OFFSETS_H_ +#define SHA2_OFFSETS_H_ + +#define SPX_SHA256_BLOCK_BYTES 64 +#define SPX_SHA256_OUTPUT_BYTES 32 + +#define SPX_SHA512_BLOCK_BYTES 128 +#define SPX_SHA512_OUTPUT_BYTES 64 + +/* + * Offsets of various fields in the address structure when we use SHA2 as + * the Sphincs+ hash function + */ + +#define SPX_OFFSET_LAYER 0 /* The byte used to specify the Merkle tree layer */ +#define SPX_OFFSET_TREE 1 /* The start of the 8 byte field used to specify the tree */ +#define SPX_OFFSET_TYPE 9 /* The byte used to specify the hash type (reason) */ +#define SPX_OFFSET_KP_ADDR2 12 /* The high byte used to specify the key pair (which one-time signature) */ +#define SPX_OFFSET_KP_ADDR1 13 /* The low byte used to specify the key pair */ +#define SPX_OFFSET_CHAIN_ADDR 17 /* The byte used to specify the chain address (which Winternitz chain) */ +#define SPX_OFFSET_HASH_ADDR 21 /* The byte used to specify the hash address (where in the Winternitz chain) */ +#define SPX_OFFSET_TREE_HGT 17 /* The byte used to specify the height of this node in the FORS or Merkle tree */ +#define SPX_OFFSET_TREE_INDEX 18 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ + +#define SPX_SHA2 1 + +#endif /* SHA2_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/sha512x4.c b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/sha512x4.c new file mode 100644 index 0000000000..8d33deffdd --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/sha512x4.c @@ -0,0 +1,446 @@ +#include +#include +#include + +/* pull in the entire thing */ +#include "sha512x4.h" +#include "utils.h" + +typedef uint64_t u64; +typedef __m256i u256; + +#define BYTESWAP(x) _mm256_shuffle_epi8(x, _mm256_set_epi8(0x8,0x9,0xa,0xb,0xc,0xd,0xe,0xf,0x0,0x1,0x2,0x3,0x4,0x5,0x6,0x7,0x8,0x9,0xa,0xb,0xc,0xd,0xe,0xf,0x0,0x1,0x2,0x3,0x4,0x5,0x6,0x7)) +#define STORE(dest,src) _mm256_storeu_si256((__m256i *)(dest),src) + +// Transpose 4 vectors containing 64-bit values +// That is, it rearranges the array: +// A B C D +// E F G H +// I J K L +// M N O P +// into +// A E I M +// B F J N +// C G K O +// D H L P +// where each letter stands for 64 bits (and lsbits on the left) +static void transpose(u256 s[4]) { + u256 tmp[4]; + tmp[0] = _mm256_unpacklo_epi64(s[0], s[1]); + tmp[1] = _mm256_unpackhi_epi64(s[0], s[1]); + tmp[2] = _mm256_unpacklo_epi64(s[2], s[3]); + tmp[3] = _mm256_unpackhi_epi64(s[2], s[3]); + // tmp is in the order of + // A E C G + // B F D H + // I M K O + // J N L P + s[0] = _mm256_permute2x128_si256(tmp[0], tmp[2], 0x20); + s[1] = _mm256_permute2x128_si256(tmp[1], tmp[3], 0x20); + s[2] = _mm256_permute2x128_si256(tmp[0], tmp[2], 0x31); + s[3] = _mm256_permute2x128_si256(tmp[1], tmp[3], 0x31); +} + + +void sha512_init4x(sha512x4ctx *ctx) { +#define SET4(x) _mm256_set_epi64x((long long)(x), (long long)(x), (long long)(x), (long long)(x)) + ctx->s[0] = SET4(0x6a09e667f3bcc908ULL); + ctx->s[1] = SET4(0xbb67ae8584caa73bULL); + ctx->s[2] = SET4(0x3c6ef372fe94f82bULL); + ctx->s[3] = SET4(0xa54ff53a5f1d36f1ULL); + ctx->s[4] = SET4(0x510e527fade682d1ULL); + ctx->s[5] = SET4(0x9b05688c2b3e6c1fULL); + ctx->s[6] = SET4(0x1f83d9abfb41bd6bULL); + ctx->s[7] = SET4(0x5be0cd19137e2179ULL); +#undef SET4 + + ctx->datalen = 0; + ctx->msglen = 0; +} + +#define XOR _mm256_xor_si256 +#define OR _mm256_or_si256 +#define AND _mm256_and_si256 +#define ADD64 _mm256_add_epi64 + +#define LOAD(src) _mm256_loadu_si256((__m256i *)(src)) + +#define SHIFTR64(x, y) _mm256_srli_epi64(x, y) +#define SHIFTL64(x, y) _mm256_slli_epi64(x, y) + +#define ROTR64(x, y) OR(SHIFTR64(x, y), SHIFTL64(x, 64 - (y))) + +static u256 XOR3(u256 a, u256 b, u256 c) { + return XOR(XOR(a, b), c); +} + +#define ADD3_64(a, b, c) ADD64(ADD64(a, b), c) +#define ADD4_64(a, b, c, d) ADD64(ADD64(ADD64(a, b), c), d) +#define ADD5_64(a, b, c, d, e) ADD64(ADD64(ADD64(ADD64(a, b), c), d), e) + +static u256 MAJ_AVX(u256 a, u256 b, u256 c) { + return XOR(c, AND(XOR(a, c), XOR(b, c))); +} +static u256 CH_AVX(u256 a, u256 b, u256 c) { + return XOR(c, AND(a, XOR(b, c))); +} +static u256 SIGMA0_AVX(u256 x) { + return XOR3(ROTR64(x, 28), ROTR64(x, 34), ROTR64(x, 39)); +} +static u256 SIGMA1_AVX(u256 x) { + return XOR3(ROTR64(x, 14), ROTR64(x, 18), ROTR64(x, 41)); +} +static u256 GAMMA0_AVX(u256 x) { + return XOR3(ROTR64(x, 1), ROTR64(x, 8), SHIFTR64(x, 7)); +} +static u256 GAMMA1_AVX(u256 x) { + return XOR3(ROTR64(x, 19), ROTR64(x, 61), SHIFTR64(x, 6)); +} + +#define SHA512ROUND_AVX(a, b, c, d, e, f, g, h, rc, w) \ + T0 = ADD5_64(h, w, SIGMA1_AVX(e), CH_AVX(e, f, g), _mm256_set1_epi64x((long long)RC[rc])); \ + T1 = ADD64(SIGMA0_AVX(a), MAJ_AVX(a, b, c)); \ + (d) = ADD64(d, T0); \ + (h) = ADD64(T0, T1); + +static const unsigned long long RC[80] = { + 0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL, + 0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL, + 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL, + 0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL, + 0xd807aa98a3030242ULL, 0x12835b0145706fbeULL, + 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL, + 0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL, + 0x9bdc06a725c71235ULL, 0xc19bf174cf692694ULL, + 0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL, + 0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL, + 0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL, + 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL, + 0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL, + 0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL, + 0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL, + 0x06ca6351e003826fULL, 0x142929670a0e6e70ULL, + 0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL, + 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL, + 0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL, + 0x81c2c92e47edaee6ULL, 0x92722c851482353bULL, + 0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL, + 0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL, + 0xd192e819d6ef5218ULL, 0xd69906245565a910ULL, + 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL, + 0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL, + 0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL, + 0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL, + 0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL, + 0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL, + 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL, + 0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL, + 0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL, + 0xca273eceea26619cULL, 0xd186b8c721c0c207ULL, + 0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL, + 0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL, + 0x113f9804bef90daeULL, 0x1b710b35131c471bULL, + 0x28db77f523047d84ULL, 0x32caab7b40c72493ULL, + 0x3c9ebe0a15c9bebcULL, 0x431d67c49c100d4cULL, + 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL, + 0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL, +}; + +void sha512_transform4x( + sha512x4ctx *ctx, + const unsigned char *d0, + const unsigned char *d1, + const unsigned char *d2, + const unsigned char *d3) { + u256 s0, s1, s2, s3, s4, s5, s6, s7, w[16], T0, T1, nw; + + // Load words and transform data correctly + w[0 ] = BYTESWAP(LOAD(d0 )); + w[0 + 4] = BYTESWAP(LOAD(d0 + 32)); + w[0 + 8] = BYTESWAP(LOAD(d0 + 64)); + w[0 + 12] = BYTESWAP(LOAD(d0 + 96)); + + w[1 ] = BYTESWAP(LOAD(d1 )); + w[1 + 4] = BYTESWAP(LOAD(d1 + 32)); + w[1 + 8] = BYTESWAP(LOAD(d1 + 64)); + w[1 + 12] = BYTESWAP(LOAD(d1 + 96)); + + w[2 ] = BYTESWAP(LOAD(d2 )); + w[2 + 4] = BYTESWAP(LOAD(d2 + 32)); + w[2 + 8] = BYTESWAP(LOAD(d2 + 64)); + w[2 + 12] = BYTESWAP(LOAD(d2 + 96)); + + w[3 ] = BYTESWAP(LOAD(d3 )); + w[3 + 4] = BYTESWAP(LOAD(d3 + 32)); + w[3 + 8] = BYTESWAP(LOAD(d3 + 64)); + w[3 + 12] = BYTESWAP(LOAD(d3 + 96)); + + transpose(w); + transpose(w + 4); + transpose(w + 8); + transpose(w + 12); + + // Initial State + s0 = ctx->s[0]; + s1 = ctx->s[1]; + s2 = ctx->s[2]; + s3 = ctx->s[3]; + s4 = ctx->s[4]; + s5 = ctx->s[5]; + s6 = ctx->s[6]; + s7 = ctx->s[7]; + + // The first 16 rounds (where the w inputs are directly from the data) + SHA512ROUND_AVX(s0, s1, s2, s3, s4, s5, s6, s7, 0, w[0]); + SHA512ROUND_AVX(s7, s0, s1, s2, s3, s4, s5, s6, 1, w[1]); + SHA512ROUND_AVX(s6, s7, s0, s1, s2, s3, s4, s5, 2, w[2]); + SHA512ROUND_AVX(s5, s6, s7, s0, s1, s2, s3, s4, 3, w[3]); + SHA512ROUND_AVX(s4, s5, s6, s7, s0, s1, s2, s3, 4, w[4]); + SHA512ROUND_AVX(s3, s4, s5, s6, s7, s0, s1, s2, 5, w[5]); + SHA512ROUND_AVX(s2, s3, s4, s5, s6, s7, s0, s1, 6, w[6]); + SHA512ROUND_AVX(s1, s2, s3, s4, s5, s6, s7, s0, 7, w[7]); + SHA512ROUND_AVX(s0, s1, s2, s3, s4, s5, s6, s7, 8, w[8]); + SHA512ROUND_AVX(s7, s0, s1, s2, s3, s4, s5, s6, 9, w[9]); + SHA512ROUND_AVX(s6, s7, s0, s1, s2, s3, s4, s5, 10, w[10]); + SHA512ROUND_AVX(s5, s6, s7, s0, s1, s2, s3, s4, 11, w[11]); + SHA512ROUND_AVX(s4, s5, s6, s7, s0, s1, s2, s3, 12, w[12]); + SHA512ROUND_AVX(s3, s4, s5, s6, s7, s0, s1, s2, 13, w[13]); + SHA512ROUND_AVX(s2, s3, s4, s5, s6, s7, s0, s1, 14, w[14]); + SHA512ROUND_AVX(s1, s2, s3, s4, s5, s6, s7, s0, 15, w[15]); + +#define M(i) (((i)+16) & 0xf) +#define NextW(i) \ + w[M(i)] = ADD4_64(GAMMA1_AVX(w[M((i)-2)]), w[M((i)-7)], GAMMA0_AVX(w[M((i)-15)]), w[M((i)-16)]); + + // The remaining 64 rounds (where the w inputs are a linear fix of the data) + for (unsigned i = 16; i < 80; i += 16) { + nw = NextW(0); + SHA512ROUND_AVX(s0, s1, s2, s3, s4, s5, s6, s7, i + 0, nw); + nw = NextW(1); + SHA512ROUND_AVX(s7, s0, s1, s2, s3, s4, s5, s6, i + 1, nw); + nw = NextW(2); + SHA512ROUND_AVX(s6, s7, s0, s1, s2, s3, s4, s5, i + 2, nw); + nw = NextW(3); + SHA512ROUND_AVX(s5, s6, s7, s0, s1, s2, s3, s4, i + 3, nw); + nw = NextW(4); + SHA512ROUND_AVX(s4, s5, s6, s7, s0, s1, s2, s3, i + 4, nw); + nw = NextW(5); + SHA512ROUND_AVX(s3, s4, s5, s6, s7, s0, s1, s2, i + 5, nw); + nw = NextW(6); + SHA512ROUND_AVX(s2, s3, s4, s5, s6, s7, s0, s1, i + 6, nw); + nw = NextW(7); + SHA512ROUND_AVX(s1, s2, s3, s4, s5, s6, s7, s0, i + 7, nw); + nw = NextW(8); + SHA512ROUND_AVX(s0, s1, s2, s3, s4, s5, s6, s7, i + 8, nw); + nw = NextW(9); + SHA512ROUND_AVX(s7, s0, s1, s2, s3, s4, s5, s6, i + 9, nw); + nw = NextW(10); + SHA512ROUND_AVX(s6, s7, s0, s1, s2, s3, s4, s5, i + 10, nw); + nw = NextW(11); + SHA512ROUND_AVX(s5, s6, s7, s0, s1, s2, s3, s4, i + 11, nw); + nw = NextW(12); + SHA512ROUND_AVX(s4, s5, s6, s7, s0, s1, s2, s3, i + 12, nw); + nw = NextW(13); + SHA512ROUND_AVX(s3, s4, s5, s6, s7, s0, s1, s2, i + 13, nw); + nw = NextW(14); + SHA512ROUND_AVX(s2, s3, s4, s5, s6, s7, s0, s1, i + 14, nw); + nw = NextW(15); + SHA512ROUND_AVX(s1, s2, s3, s4, s5, s6, s7, s0, i + 15, nw); + } + + // Feed Forward + ctx->s[0] = ADD64(s0, ctx->s[0]); + ctx->s[1] = ADD64(s1, ctx->s[1]); + ctx->s[2] = ADD64(s2, ctx->s[2]); + ctx->s[3] = ADD64(s3, ctx->s[3]); + ctx->s[4] = ADD64(s4, ctx->s[4]); + ctx->s[5] = ADD64(s5, ctx->s[5]); + ctx->s[6] = ADD64(s6, ctx->s[6]); + ctx->s[7] = ADD64(s7, ctx->s[7]); +} + +static void _sha512x4( + sha512x4ctx *ctx, + unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + unsigned long long inlen) { + unsigned int i = 0; + + while (inlen - i >= 128) { + sha512_transform4x( + ctx, + in0 + i, + in1 + i, + in2 + i, + in3 + i + ); + ctx->msglen += 1024; + i += 128; + } + + ctx->datalen = (unsigned int)(inlen - i); + memcpy(&ctx->msgblocks[128 * 0], in0 + i, ctx->datalen); + memcpy(&ctx->msgblocks[128 * 1], in1 + i, ctx->datalen); + memcpy(&ctx->msgblocks[128 * 2], in2 + i, ctx->datalen); + memcpy(&ctx->msgblocks[128 * 3], in3 + i, ctx->datalen); + + // Padding + unsigned long curlen; + if (ctx->datalen < 112) { + for (i = 0; i < 4; ++i) { + curlen = ctx->datalen; + ctx->msgblocks[128 * i + curlen++] = 0x80; + while (curlen < 128) { + ctx->msgblocks[128 * i + curlen++] = 0x00; + } + } + } else { + for (i = 0; i < 4; ++i) { + curlen = ctx->datalen; + ctx->msgblocks[128 * i + curlen++] = 0x80; + while (curlen < 128) { + ctx->msgblocks[128 * i + curlen++] = 0x00; + } + } + sha512_transform4x( + ctx, + ctx->msgblocks, + ctx->msgblocks + 128, + ctx->msgblocks + 256, + ctx->msgblocks + 384 + ); + memset(ctx->msgblocks, 0, 4 * 128); + } + + // Add length of the message to each block + ctx->msglen += (unsigned long long)(ctx->datalen) * 8; + for (i = 0; i < 4; i++) { + ctx->msgblocks[128 * i + 127] = (unsigned char)(ctx->msglen); + ctx->msgblocks[128 * i + 126] = (unsigned char)(ctx->msglen >> 8); + ctx->msgblocks[128 * i + 125] = (unsigned char)(ctx->msglen >> 16); + ctx->msgblocks[128 * i + 124] = (unsigned char)(ctx->msglen >> 24); + ctx->msgblocks[128 * i + 123] = (unsigned char)(ctx->msglen >> 32); + ctx->msgblocks[128 * i + 122] = (unsigned char)(ctx->msglen >> 40); + ctx->msgblocks[128 * i + 121] = (unsigned char)(ctx->msglen >> 48); + ctx->msgblocks[128 * i + 120] = (unsigned char)(ctx->msglen >> 56); + memset( &ctx->msgblocks[128 * i + 112], 0, 8 ); + } + sha512_transform4x( + ctx, + ctx->msgblocks, + ctx->msgblocks + 128, + ctx->msgblocks + 256, + ctx->msgblocks + 384 + ); + + // Compute final hash output + transpose(ctx->s); + transpose(ctx->s + 4); + + // Store Hash value + __m256i out[2]; + STORE(out, BYTESWAP(ctx->s[0])); + STORE(out + 1, BYTESWAP(ctx->s[4])); + memcpy(out0, out, 64); + + STORE(out, BYTESWAP(ctx->s[1])); + STORE(out + 1, BYTESWAP(ctx->s[5])); + memcpy(out1, out, 64); + + STORE(out, BYTESWAP(ctx->s[2])); + STORE(out + 1, BYTESWAP(ctx->s[6])); + memcpy(out2, out, 64); + + STORE(out, BYTESWAP(ctx->s[3])); + STORE(out + 1, BYTESWAP(ctx->s[7])); + memcpy(out3, out, 64); +} + + +/** + * Note that inlen should be sufficiently small that it still allows for + * an array to be allocated on the stack. Typically 'in' is merely a seed. + * Outputs outlen number of bytes + */ +void mgf1x4_512(unsigned char *outx4, unsigned long outlen, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + unsigned long inlen) { + PQCLEAN_VLA(unsigned char, inbufx4, 4 * (inlen + 4)); + unsigned char outbuf[4 * 64]; + uint32_t i; + unsigned int j; + + memcpy(inbufx4 + 0 * (inlen + 4), in0, inlen); + memcpy(inbufx4 + 1 * (inlen + 4), in1, inlen); + memcpy(inbufx4 + 2 * (inlen + 4), in2, inlen); + memcpy(inbufx4 + 3 * (inlen + 4), in3, inlen); + + /* While we can fit in at least another full block of SHA512 output.. */ + unsigned long remaining = outlen; + for (i = 0; remaining > 0; i++) { + unsigned long this_step = SPX_SHA512_OUTPUT_BYTES; + if (this_step > remaining) { + this_step = remaining; + } + remaining -= this_step; + for (j = 0; j < 4; j++) { + u32_to_bytes(inbufx4 + inlen + j * (inlen + 4), i); + } + + sha512x4ctx ctx; + sha512_init4x(&ctx); + + _sha512x4( + &ctx, + outbuf + 0 * 64, + outbuf + 1 * 64, + outbuf + 2 * 64, + outbuf + 3 * 64, + inbufx4 + 0 * (inlen + 4), + inbufx4 + 1 * (inlen + 4), + inbufx4 + 2 * (inlen + 4), + inbufx4 + 3 * (inlen + 4), + inlen + 4 + ); + + memcpy(outx4 + 0 * outlen, outbuf + 0 * 64, this_step); + memcpy(outx4 + 1 * outlen, outbuf + 1 * 64, this_step); + memcpy(outx4 + 2 * outlen, outbuf + 2 * 64, this_step); + memcpy(outx4 + 3 * outlen, outbuf + 3 * 64, this_step); + outx4 += this_step; + } +} + +void sha512x4_seeded( + unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const sha512x4ctx *seed, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + unsigned long long inlen) { + sha512x4ctx ctx; + sha512_ctx_clone4x(&ctx, seed); + _sha512x4( + &ctx, + out0, out1, out2, out3, + in0, in1, in2, in3, + inlen + ); +} + +void sha512_ctx_clone4x(sha512x4ctx *out, const sha512x4ctx *in) { + memcpy(out, in, sizeof(sha512x4ctx)); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/sha512x4.h b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/sha512x4.h new file mode 100644 index 0000000000..9bbe736514 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/sha512x4.h @@ -0,0 +1,58 @@ +#ifndef SHA512AVX_H +#define SHA512AVX_H + +#include +#include + + +#include "params.h" + +typedef struct SHA512state4x { + __m256i s[8]; + unsigned char msgblocks[4 * 128]; + unsigned int datalen; + unsigned long long msglen; +} sha512x4ctx; + +#define sha512_init4x SPX_NAMESPACE(sha512_init4x) +void sha512_init4x(sha512x4ctx *ctx); + +#define sha512_transform4x SPX_NAMESPACE(sha512_transform4x) +void sha512_transform4x( + sha512x4ctx *ctx, + const unsigned char *d0, + const unsigned char *d1, + const unsigned char *d2, + const unsigned char *d3); + + +#define sha512x4_seeded SPX_NAMESPACE(sha512x4_seeded) +void sha512x4_seeded( + unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const sha512x4ctx *seed, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + unsigned long long inlen); + +#define sha512_ctx_clone4x SPX_NAMESPACE(sha512_ctx_clone4x) +void sha512_ctx_clone4x(sha512x4ctx *out, const sha512x4ctx *in); + +/** + * Note that inlen should be sufficiently small that it still allows for + * an array to be allocated on the stack. Typically 'in' is merely a seed. + * Outputs outlen number of bytes + */ +#define mgf1x4_512 SPX_NAMESPACE(mgf1x4_512) +void mgf1x4_512(unsigned char *outx4, unsigned long outlen, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + unsigned long inlen); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/sign.c b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/sign.c new file mode 100644 index 0000000000..9d0c7d1b22 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/sign.c @@ -0,0 +1,286 @@ +#include +#include +#include + +#include "address.h" +#include "context.h" +#include "fors.h" +#include "hash.h" +#include "merkle.h" +#include "nistapi.h" +#include "params.h" +#include "randombytes.h" +#include "thash.h" +#include "utils.h" +#include "wots.h" + +/* + * Returns the length of a secret key, in bytes + */ +size_t crypto_sign_secretkeybytes(void) { + return CRYPTO_SECRETKEYBYTES; +} + +/* + * Returns the length of a public key, in bytes + */ +size_t crypto_sign_publickeybytes(void) { + return CRYPTO_PUBLICKEYBYTES; +} + +/* + * Returns the length of a signature, in bytes + */ +size_t crypto_sign_bytes(void) { + return CRYPTO_BYTES; +} + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +size_t crypto_sign_seedbytes(void) { + return CRYPTO_SEEDBYTES; +} + +/* + * Generates an SPX key pair given a seed of length + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [PUB_SEED || root] + */ +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed) { + spx_ctx ctx; + + /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ + memcpy(sk, seed, CRYPTO_SEEDBYTES); + + memcpy(pk, sk + 2 * SPX_N, SPX_N); + + memcpy(ctx.pub_seed, pk, SPX_N); + memcpy(ctx.sk_seed, sk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + /* Compute root node of the top-most subtree. */ + merkle_gen_root(sk + 3 * SPX_N, &ctx); + + // cleanup + free_hash_function(&ctx); + + memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); + + return 0; +} + +/* + * Generates an SPX key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [PUB_SEED || root] + */ +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { + uint8_t seed[CRYPTO_SEEDBYTES]; + randombytes(seed, CRYPTO_SEEDBYTES); + crypto_sign_seed_keypair(pk, sk, seed); + + return 0; +} + +/** + * Returns an array containing a detached signature. + */ +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk) { + spx_ctx ctx; + + const uint8_t *sk_prf = sk + SPX_N; + const uint8_t *pk = sk + 2 * SPX_N; + + uint8_t optrand[SPX_N]; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t root[SPX_N]; + uint32_t i; + uint64_t tree; + uint32_t idx_leaf; + uint32_t wots_addr[8] = {0}; + uint32_t tree_addr[8] = {0}; + + memcpy(ctx.sk_seed, sk, SPX_N); + memcpy(ctx.pub_seed, pk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + + /* Optionally, signing can be made non-deterministic using optrand. + This can help counter side-channel attacks that would benefit from + getting a large number of traces when the signer uses the same nodes. */ + randombytes(optrand, SPX_N); + /* Compute the digest randomization value. */ + gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); + + /* Derive the message digest and leaf index from R, PK and M. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; + + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); + + /* Sign the message hash using FORS. */ + fors_sign(sig, root, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); + sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; + + /* Update the indices for the next layer. */ + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; + } + + free_hash_function(&ctx); + + *siglen = SPX_BYTES; + + return 0; +} + +/** + * Verifies a detached signature and message under a given public key. + */ +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk) { + spx_ctx ctx; + const uint8_t *pub_root = pk + SPX_N; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t wots_pk[SPX_WOTS_BYTES]; + uint8_t root[SPX_N]; + uint8_t leaf[SPX_N]; + unsigned int i; + uint64_t tree; + uint32_t idx_leaf; + uint32_t wots_addr[8] = {0}; + uint32_t tree_addr[8] = {0}; + uint32_t wots_pk_addr[8] = {0}; + + if (siglen != SPX_BYTES) { + return -1; + } + + memcpy(ctx.pub_seed, pk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); + + /* Derive the message digest and leaf index from R || PK || M. */ + /* The additional SPX_N is a result of the hash domain separator. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; + + /* Layer correctly defaults to 0, so no need to set_layer_addr */ + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); + + fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + /* For each subtree.. */ + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + copy_keypair_addr(wots_pk_addr, wots_addr); + + /* The WOTS public key is only correct if the signature was correct. */ + /* Initially, root is the FORS pk, but on subsequent iterations it is + the root of the subtree below the currently processed subtree. */ + wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); + sig += SPX_WOTS_BYTES; + + /* Compute the leaf node using the WOTS public key. */ + thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); + + /* Compute the root node of this subtree. */ + compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, + &ctx, tree_addr); + sig += SPX_TREE_HEIGHT * SPX_N; + + /* Update the indices for the next layer. */ + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; + } + + // cleanup + free_hash_function(&ctx); + + /* Check if the root node equals the root node in the public key. */ + if (memcmp(root, pub_root, SPX_N) != 0) { + return -1; + } + + return 0; +} + + +/** + * Returns an array containing the signature followed by the message. + */ +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk) { + size_t siglen; + + crypto_sign_signature(sm, &siglen, m, mlen, sk); + + memmove(sm + SPX_BYTES, m, mlen); + *smlen = siglen + mlen; + + return 0; +} + +/** + * Verifies a given signature-message pair under a given public key. + */ +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk) { + /* The API caller does not necessarily know what size a signature should be + but SPHINCS+ signatures are always exactly SPX_BYTES. */ + if (smlen < SPX_BYTES) { + memset(m, 0, smlen); + *mlen = 0; + return -1; + } + + *mlen = smlen - SPX_BYTES; + + if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { + memset(m, 0, smlen); + *mlen = 0; + return -1; + } + + /* If verification was successful, move the message to the right place. */ + memmove(m, sm + SPX_BYTES, *mlen); + + return 0; +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/thash.h b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/thash.h new file mode 100644 index 0000000000..8687ccfb4d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/thash.h @@ -0,0 +1,13 @@ +#ifndef SPX_THASH_H +#define SPX_THASH_H + +#include "context.h" +#include "params.h" + +#include + +#define thash SPX_NAMESPACE(thash) +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/thash_sha2_robust.c b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/thash_sha2_robust.c new file mode 100644 index 0000000000..3ab891175f --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/thash_sha2_robust.c @@ -0,0 +1,68 @@ +#include +#include + +#include "address.h" +#include "context.h" +#include "hash.h" +#include "params.h" +#include "sha2.h" +#include "thash.h" +#include "utils.h" + +static void thash_512(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]); + +/** + * Takes an array of inblocks concatenated arrays of SPX_N bytes. + */ +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]) { + if (inblocks > 1) { + thash_512(out, in, inblocks, ctx, addr); + return; + } + unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES]; + PQCLEAN_VLA(uint8_t, bitmask, inblocks * SPX_N); + PQCLEAN_VLA(uint8_t, buf, SPX_N + SPX_SHA256_OUTPUT_BYTES + inblocks * SPX_N); + sha256ctx sha2_state; + unsigned int i; + + memcpy(buf, ctx->pub_seed, SPX_N); + memcpy(buf + SPX_N, addr, SPX_SHA256_ADDR_BYTES); + mgf1_256(bitmask, inblocks * SPX_N, buf, SPX_N + SPX_SHA256_ADDR_BYTES); + + /* Retrieve precomputed state containing pub_seed */ + sha256_inc_ctx_clone(&sha2_state, &ctx->state_seeded); + + for (i = 0; i < inblocks * SPX_N; i++) { + buf[SPX_N + SPX_SHA256_ADDR_BYTES + i] = in[i] ^ bitmask[i]; + } + + sha256_inc_finalize(outbuf, &sha2_state, buf + SPX_N, + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N); + memcpy(out, outbuf, SPX_N); +} + +static void thash_512(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]) { + unsigned char outbuf[SPX_SHA512_OUTPUT_BYTES]; + PQCLEAN_VLA(uint8_t, bitmask, inblocks * SPX_N); + PQCLEAN_VLA(uint8_t, buf, SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N); + sha512ctx sha2_state; + unsigned int i; + + memcpy(buf, ctx->pub_seed, SPX_N); + memcpy(buf + SPX_N, addr, SPX_SHA256_ADDR_BYTES); + mgf1_512(bitmask, inblocks * SPX_N, buf, SPX_N + SPX_SHA256_ADDR_BYTES); + + /* Retrieve precomputed state containing pub_seed */ + sha512_inc_ctx_clone(&sha2_state, &ctx->state_seeded_512); + + for (i = 0; i < inblocks * SPX_N; i++) { + buf[SPX_N + SPX_SHA256_ADDR_BYTES + i] = in[i] ^ bitmask[i]; + } + + sha512_inc_finalize(outbuf, &sha2_state, buf + SPX_N, + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N); + memcpy(out, outbuf, SPX_N); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/thash_sha2_robustx8.c b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/thash_sha2_robustx8.c new file mode 100644 index 0000000000..991faa7eeb --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/thash_sha2_robustx8.c @@ -0,0 +1,268 @@ +#include +#include + +#include "thashx8.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "sha2.h" +#include "sha256avx.h" +#include "sha256x8.h" +#include "utils.h" + +#include "sha512x4.h" + +static void thashx8_512( + unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, + unsigned int inblocks, + const spx_ctx *ctx, + uint32_t addrx8[8 * 8] +); + +/** + * 8-way parallel version of thash; takes 8x as much input and output + */ +void thashx8(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addrx8[8 * 8]) { + if (inblocks > 1) { + thashx8_512( + out0, out1, out2, out3, out4, out5, out6, out7, + in0, in1, in2, in3, in4, in5, in6, in7, + inblocks, ctx, addrx8); + return; + } + PQCLEAN_VLA(unsigned char, bufx8, 8 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)); + unsigned char outbufx8[8 * SPX_SHA256_OUTPUT_BYTES]; + PQCLEAN_VLA(unsigned char, bitmaskx8, 8 * (inblocks * SPX_N)); + unsigned int i; + + for (i = 0; i < 8; i++) { + memcpy(bufx8 + i * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + ctx->pub_seed, SPX_N); + memcpy(bufx8 + SPX_N + + i * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + addrx8 + i * 8, SPX_SHA256_ADDR_BYTES); + } + + mgf1x8(bitmaskx8, inblocks * SPX_N, + bufx8 + 0 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + 1 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + 2 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + 3 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + 4 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + 5 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + 6 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + 7 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + SPX_N + SPX_SHA256_ADDR_BYTES); + + for (i = 0; i < inblocks * SPX_N; i++) { + bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + + 0 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = + in0[i] ^ bitmaskx8[i + 0 * (inblocks * SPX_N)]; + bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + + 1 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = + in1[i] ^ bitmaskx8[i + 1 * (inblocks * SPX_N)]; + bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + + 2 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = + in2[i] ^ bitmaskx8[i + 2 * (inblocks * SPX_N)]; + bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + + 3 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = + in3[i] ^ bitmaskx8[i + 3 * (inblocks * SPX_N)]; + bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + + 4 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = + in4[i] ^ bitmaskx8[i + 4 * (inblocks * SPX_N)]; + bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + + 5 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = + in5[i] ^ bitmaskx8[i + 5 * (inblocks * SPX_N)]; + bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + + 6 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = + in6[i] ^ bitmaskx8[i + 6 * (inblocks * SPX_N)]; + bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + + 7 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = + in7[i] ^ bitmaskx8[i + 7 * (inblocks * SPX_N)]; + } + + sha256x8_seeded( + /* out */ + outbufx8 + 0 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 1 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 2 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 3 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 4 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 5 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 6 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 7 * SPX_SHA256_OUTPUT_BYTES, + + /* seed */ + &ctx->statex8_seeded, + + /* in */ + bufx8 + SPX_N + 0 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + SPX_N + 1 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + SPX_N + 2 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + SPX_N + 3 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + SPX_N + 4 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + SPX_N + 5 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + SPX_N + 6 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + SPX_N + 7 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N /* len */ + ); + + memcpy(out0, outbufx8 + 0 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out1, outbufx8 + 1 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out2, outbufx8 + 2 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out3, outbufx8 + 3 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out4, outbufx8 + 4 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out5, outbufx8 + 5 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out6, outbufx8 + 6 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out7, outbufx8 + 7 * SPX_SHA256_OUTPUT_BYTES, SPX_N); +} + +/** + * 2x4-way parallel version of thash; this is for the uses of thash that are + * based on SHA-512 + */ +static void thashx8_512( + unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, + unsigned int inblocks, + const spx_ctx *ctx, + uint32_t addrx8[8 * 8]) { + PQCLEAN_VLA(unsigned char, bufx8, 8 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)); + unsigned char outbuf[4 * SPX_SHA512_OUTPUT_BYTES]; + PQCLEAN_VLA(unsigned char, bitmaskx4, 4 * (inblocks * SPX_N)); + unsigned int i; + + for (i = 0; i < 8; i++) { + memcpy(bufx8 + i * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + ctx->pub_seed, SPX_N); + memcpy(bufx8 + SPX_N + + i * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + addrx8 + i * 8, SPX_SHA256_ADDR_BYTES); + } + + mgf1x4_512(bitmaskx4, inblocks * SPX_N, + bufx8 + 0 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + 1 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + 2 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + 3 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + SPX_N + SPX_SHA256_ADDR_BYTES); + + for (i = 0; i < inblocks * SPX_N; i++) { + bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + + 0 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = + in0[i] ^ bitmaskx4[i + 0 * (inblocks * SPX_N)]; + bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + + 1 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = + in1[i] ^ bitmaskx4[i + 1 * (inblocks * SPX_N)]; + bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + + 2 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = + in2[i] ^ bitmaskx4[i + 2 * (inblocks * SPX_N)]; + bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + + 3 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = + in3[i] ^ bitmaskx4[i + 3 * (inblocks * SPX_N)]; + } + + mgf1x4_512(bitmaskx4, inblocks * SPX_N, + bufx8 + 4 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + 5 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + 6 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + 7 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + SPX_N + SPX_SHA256_ADDR_BYTES); + + for (i = 0; i < inblocks * SPX_N; i++) { + bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + + 4 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = + in4[i] ^ bitmaskx4[i + 0 * (inblocks * SPX_N)]; + bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + + 5 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = + in5[i] ^ bitmaskx4[i + 1 * (inblocks * SPX_N)]; + bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + + 6 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = + in6[i] ^ bitmaskx4[i + 2 * (inblocks * SPX_N)]; + bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + + 7 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = + in7[i] ^ bitmaskx4[i + 3 * (inblocks * SPX_N)]; + } + + sha512x4_seeded( + outbuf + 0 * SPX_SHA512_OUTPUT_BYTES, + outbuf + 1 * SPX_SHA512_OUTPUT_BYTES, + outbuf + 2 * SPX_SHA512_OUTPUT_BYTES, + outbuf + 3 * SPX_SHA512_OUTPUT_BYTES, + &ctx->statex4_seeded_512, /* seed */ + bufx8 + SPX_N + 0 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + SPX_N + 1 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + SPX_N + 2 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + SPX_N + 3 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N /* len */ + ); + + memcpy(out0, outbuf + 0 * SPX_SHA512_OUTPUT_BYTES, SPX_N); + memcpy(out1, outbuf + 1 * SPX_SHA512_OUTPUT_BYTES, SPX_N); + memcpy(out2, outbuf + 2 * SPX_SHA512_OUTPUT_BYTES, SPX_N); + memcpy(out3, outbuf + 3 * SPX_SHA512_OUTPUT_BYTES, SPX_N); + + sha512x4_seeded( + outbuf + 0 * SPX_SHA512_OUTPUT_BYTES, + outbuf + 1 * SPX_SHA512_OUTPUT_BYTES, + outbuf + 2 * SPX_SHA512_OUTPUT_BYTES, + outbuf + 3 * SPX_SHA512_OUTPUT_BYTES, + &ctx->statex4_seeded_512, /* seed */ + bufx8 + SPX_N + 4 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + SPX_N + 5 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + SPX_N + 6 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + SPX_N + 7 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N /* len */ + ); + + memcpy(out4, outbuf + 0 * SPX_SHA512_OUTPUT_BYTES, SPX_N); + memcpy(out5, outbuf + 1 * SPX_SHA512_OUTPUT_BYTES, SPX_N); + memcpy(out6, outbuf + 2 * SPX_SHA512_OUTPUT_BYTES, SPX_N); + memcpy(out7, outbuf + 3 * SPX_SHA512_OUTPUT_BYTES, SPX_N); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/thashx8.h b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/thashx8.h new file mode 100644 index 0000000000..c02fe9cf3e --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/thashx8.h @@ -0,0 +1,28 @@ +#ifndef SPX_THASHX8_H +#define SPX_THASHX8_H + +#include + +#include "context.h" +#include "params.h" + +#define thashx8 SPX_NAMESPACE(thashx8) +void thashx8(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addrx8[8 * 8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/utils.c b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/utils.c new file mode 100644 index 0000000000..177b541fb9 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/utils.c @@ -0,0 +1,148 @@ +#include + +#include "utils.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "thash.h" + +/** + * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. + */ +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in) { + int i; + + /* Iterate over out in decreasing order, for big-endianness. */ + for (i = (signed int)outlen - 1; i >= 0; i--) { + out[i] = in & 0xff; + in = in >> 8; + } +} + +void u32_to_bytes(unsigned char *out, uint32_t in) { + out[0] = (unsigned char)(in >> 24); + out[1] = (unsigned char)(in >> 16); + out[2] = (unsigned char)(in >> 8); + out[3] = (unsigned char)in; +} + +/** + * Converts the inlen bytes in 'in' from big-endian byte order to an integer. + */ +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { + unsigned long long retval = 0; + unsigned int i; + + for (i = 0; i < inlen; i++) { + retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); + } + return retval; +} + +/** + * Computes a root node given a leaf and an auth path. + * Expects address to be complete other than the tree_height and tree_index. + */ +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]) { + uint32_t i; + unsigned char buffer[2 * SPX_N]; + + /* If leaf_idx is odd (last bit = 1), current path element is a right child + and auth_path has to go left. Otherwise it is the other way around. */ + if (leaf_idx & 1) { + memcpy(buffer + SPX_N, leaf, SPX_N); + memcpy(buffer, auth_path, SPX_N); + } else { + memcpy(buffer, leaf, SPX_N); + memcpy(buffer + SPX_N, auth_path, SPX_N); + } + auth_path += SPX_N; + + for (i = 0; i < tree_height - 1; i++) { + leaf_idx >>= 1; + idx_offset >>= 1; + /* Set the address of the node we're creating. */ + set_tree_height(addr, i + 1); + set_tree_index(addr, leaf_idx + idx_offset); + + /* Pick the right or left neighbor, depending on parity of the node. */ + if (leaf_idx & 1) { + thash(buffer + SPX_N, buffer, 2, ctx, addr); + memcpy(buffer, auth_path, SPX_N); + } else { + thash(buffer, buffer, 2, ctx, addr); + memcpy(buffer + SPX_N, auth_path, SPX_N); + } + auth_path += SPX_N; + } + + /* The last iteration is exceptional; we do not copy an auth_path node. */ + leaf_idx >>= 1; + idx_offset >>= 1; + set_tree_height(addr, tree_height); + set_tree_index(addr, leaf_idx + idx_offset); + thash(root, buffer, 2, ctx, addr); +} + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx * /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]) { + PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); + PQCLEAN_VLA(unsigned int, heights, tree_height + 1); + unsigned int offset = 0; + uint32_t idx; + uint32_t tree_idx; + + for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { + /* Add the next leaf node to the stack. */ + gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); + offset++; + heights[offset - 1] = 0; + + /* If this is a node we need for the auth path.. */ + if ((leaf_idx ^ 0x1) == idx) { + memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); + } + + /* While the top-most nodes are of equal height.. */ + while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { + /* Compute index of the new node, in the next layer. */ + tree_idx = (idx >> (heights[offset - 1] + 1)); + + /* Set the address of the node we're creating. */ + set_tree_height(tree_addr, heights[offset - 1] + 1); + set_tree_index(tree_addr, + tree_idx + (idx_offset >> (heights[offset - 1] + 1))); + /* Hash the top-most nodes from the stack together. */ + thash(stack + (offset - 2)*SPX_N, + stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); + offset--; + /* Note that the top-most node is now one layer higher. */ + heights[offset - 1]++; + + /* If this is a node we need for the auth path.. */ + if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { + memcpy(auth_path + heights[offset - 1]*SPX_N, + stack + (offset - 1)*SPX_N, SPX_N); + } + } + } + memcpy(root, stack, SPX_N); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/utils.h b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/utils.h new file mode 100644 index 0000000000..64f5d5a53a --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/utils.h @@ -0,0 +1,58 @@ +#ifndef SPX_UTILS_H +#define SPX_UTILS_H + +#include + +#include "compat.h" +#include "context.h" +#include "params.h" + + +/* To support MSVC use alloca() instead of VLAs. See #20. */ + + +/** + * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. + */ +#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in); +#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) +void u32_to_bytes(unsigned char *out, uint32_t in); + +/** + * Converts the inlen bytes in 'in' from big-endian byte order to an integer. + */ +#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); + +/** + * Computes a root node given a leaf and an auth path. + * Expects address to be complete other than the tree_height and tree_index. + */ +#define compute_root SPX_NAMESPACE(compute_root) +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]); + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +#define treehash SPX_NAMESPACE(treehash) +void treehash(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx *ctx /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]); + + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/utilsx8.c b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/utilsx8.c new file mode 100644 index 0000000000..f044b9595d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/utilsx8.c @@ -0,0 +1,146 @@ +#include + +#include "utils.h" +#include "utilsx8.h" + +#include "address.h" +#include "params.h" +#include "thashx8.h" + +/* + * Generate the entire Merkle tree, computing the authentication path for leaf_idx, + * and the resulting root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) + * + * This expects tree_addrx8 to be initialized to 8 parallel addr structures for + * the Merkle tree nodes + * + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + * + * This works by using the standard Merkle tree building algorithm, except + * that each 'node' tracked is actually 8 consecutive nodes in the real tree. + * When we combine two logical nodes ABCDEFGH and STUVWXYZ, we perform the H + * operation on adjacent real nodes, forming the parent logical node + * (AB)(CD)(EF)(GH)(ST)(UV)(WX)(YZ) + * + * When we get to the top three levels of the real tree (where there is only + * one logical node), we continue this operation three more times; the right + * most real node will by the actual root (and the other 7 nodes will be + * garbage). We follow the same thashx8 logic so that the 'extract + * authentication path components' part of the loop is still executed (and + * to simplify the code somewhat) + * + * This currently assumes tree_height >= 3; I suspect that doing an adjusting + * idx, addr_idx on the gen_leafx8 call if tree_height < 3 would fix it; since + * we don't actually use such short trees, I haven't bothered + */ +void treehashx8(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, + uint32_t tree_height, + void (*gen_leafx8)( + unsigned char * /* Where to write the leaves */, + const spx_ctx *, + uint32_t idx, void *info), + uint32_t tree_addrx8[8 * 8], + void *info) { + /* This is where we keep the intermediate nodes */ + PQCLEAN_VLA(unsigned char, stackx8, tree_height * 8 * SPX_N); + uint32_t left_adj = 0, prev_left_adj = 0; /* When we're doing the top 3 */ + /* levels, the left-most part of the tree isn't at the beginning */ + /* of current[]. These give the offset of the actual start */ + + uint32_t idx; + uint32_t max_idx = ((uint32_t)1 << (tree_height - 3)) - 1; + for (idx = 0;; idx++) { + unsigned char current[8 * SPX_N]; /* Current logical node */ + gen_leafx8( current, ctx, 8 * idx + idx_offset, + info ); + + /* Now combine the freshly generated right node with previously */ + /* generated left ones */ + uint32_t internal_idx_offset = idx_offset; + uint32_t internal_idx = idx; + uint32_t internal_leaf = leaf_idx; + uint32_t h; /* The height we are in the Merkle tree */ + for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { + + /* Special processing if we're at the top of the tree */ + if (h >= tree_height - 3) { + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[7 * SPX_N], SPX_N ); + return; + } + /* The tree indexing logic is a bit off in this case */ + /* Adjust it so that the left-most node of the part of */ + /* the tree that we're processing has index 0 */ + prev_left_adj = left_adj; + left_adj = (uint32_t)(8 - (1 << (tree_height - h - 1))); + } + + /* Check if we hit the top of the tree */ + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[7 * SPX_N], SPX_N ); + return; + } + + /* + * Check if one of the nodes we have is a part of the + * authentication path; if it is, write it out + */ + if ((((internal_idx << 3) ^ internal_leaf) & ~0x7U) == 0) { + memcpy( &auth_path[ h * SPX_N ], + ¤t[(((internal_leaf & 7) ^ 1) + prev_left_adj) * SPX_N], + SPX_N ); + } + + /* + * Check if we're at a left child; if so, stop going up the stack + * Exception: if we've reached the end of the tree, keep on going + * (so we combine the last 8 nodes into the one root node in three + * more iterations) + */ + if ((internal_idx & 1) == 0 && idx < max_idx) { + break; + } + + /* Ok, we're at a right node (or doing the top 3 levels) */ + /* Now combine the left and right logical nodes together */ + + /* Set the address of the node we're creating. */ + uint32_t j; + internal_idx_offset >>= 1; + for (j = 0; j < 8; j++) { + set_tree_height(tree_addrx8 + j * 8, h + 1); + set_tree_index(tree_addrx8 + j * 8, + (8 / 2) * (internal_idx & ~1U) + j - left_adj + internal_idx_offset ); + } + unsigned char *left = &stackx8[h * 8 * SPX_N]; + thashx8( ¤t[0 * SPX_N], + ¤t[1 * SPX_N], + ¤t[2 * SPX_N], + ¤t[3 * SPX_N], + ¤t[4 * SPX_N], + ¤t[5 * SPX_N], + ¤t[6 * SPX_N], + ¤t[7 * SPX_N], + &left [0 * SPX_N], + &left [2 * SPX_N], + &left [4 * SPX_N], + &left [6 * SPX_N], + ¤t[0 * SPX_N], + ¤t[2 * SPX_N], + ¤t[4 * SPX_N], + ¤t[6 * SPX_N], + 2, ctx, tree_addrx8); + } + + /* We've hit a left child; save the current for when we get the */ + /* corresponding right right */ + memcpy( &stackx8[h * 8 * SPX_N], current, 8 * SPX_N); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/utilsx8.h b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/utilsx8.h new file mode 100644 index 0000000000..806d1e85be --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/utilsx8.h @@ -0,0 +1,29 @@ +#ifndef SPX_UTILSX8_H +#define SPX_UTILSX8_H + +#include + +#include "params.h" + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + * + * This implementation uses AVX to compute internal nodes 8 at a time (in + * parallel) + */ +#define treehashx8 SPX_NAMESPACE(treehashx8) +void treehashx8(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leafx8)( + unsigned char * /* Where to write the leaves */, + const spx_ctx * /* ctx */, + uint32_t addr_idx, void *info), + uint32_t tree_addrx8[8 * 8], void *info); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/wots.c b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/wots.c new file mode 100644 index 0000000000..689baf4db9 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/wots.c @@ -0,0 +1,291 @@ +#include +#include + +#include "wots.h" + +#include "address.h" +#include "hash.h" +#include "hashx8.h" +#include "params.h" +#include "thash.h" +#include "thashx8.h" +#include "utils.h" +#include "utilsx8.h" +#include "wotsx8.h" + +// TODO clarify address expectations, and make them more uniform. +// TODO i.e. do we expect types to be set already? +// TODO and do we expect modifications or copies? + +/** + * Computes up the chains + */ +static void gen_chains( + unsigned char *out, + const unsigned char *in, + unsigned int start[SPX_WOTS_LEN], + const unsigned int steps[SPX_WOTS_LEN], + const spx_ctx *ctx, + uint32_t addr[8]) { + uint32_t i, j, k, idx, watching; + int done; + unsigned char empty[SPX_N]; + unsigned char *bufs[8]; + uint32_t addrs[8 * 8]; + + int l; + uint16_t counts[SPX_WOTS_W] = { 0 }; + uint16_t idxs[SPX_WOTS_LEN]; + uint16_t total, newTotal; + + /* set addrs = {addr, addr, ..., addr} */ + for (j = 0; j < 8; j++) { + memcpy(addrs + j * 8, addr, sizeof(uint32_t) * 8); + } + + /* Initialize out with the value at position 'start'. */ + memcpy(out, in, SPX_WOTS_LEN * SPX_N); + + /* Sort the chains in reverse order by steps using counting sort. */ + for (i = 0; i < SPX_WOTS_LEN; i++) { + counts[steps[i]]++; + } + total = 0; + for (l = SPX_WOTS_W - 1; l >= 0; l--) { + newTotal = counts[l] + total; + counts[l] = total; + total = newTotal; + } + for (i = 0; i < SPX_WOTS_LEN; i++) { + idxs[counts[steps[i]]] = (uint16_t)i; + counts[steps[i]]++; + } + + /* We got our work cut out for us: do it! */ + for (i = 0; i < SPX_WOTS_LEN; i += 8) { + for (j = 0; j < 8 && i + j < SPX_WOTS_LEN; j++) { + idx = idxs[i + j]; + set_chain_addr(addrs + j * 8, idx); + bufs[j] = out + SPX_N * idx; + } + + /* As the chains are sorted in reverse order, we know that the first + * chain is the longest and the last one is the shortest. We keep + * an eye on whether the last chain is done and then on the one before, + * et cetera. */ + watching = 7; + done = 0; + while (i + watching >= SPX_WOTS_LEN) { + bufs[watching] = &empty[0]; + watching--; + } + + for (k = 0;; k++) { + while (k == steps[idxs[i + watching]]) { + bufs[watching] = &empty[0]; + if (watching == 0) { + done = 1; + break; + } + watching--; + } + if (done) { + break; + } + for (j = 0; j < watching + 1; j++) { + set_hash_addr(addrs + j * 8, k + start[idxs[i + j]]); + } + + thashx8(bufs[0], bufs[1], bufs[2], bufs[3], + bufs[4], bufs[5], bufs[6], bufs[7], + bufs[0], bufs[1], bufs[2], bufs[3], + bufs[4], bufs[5], bufs[6], bufs[7], 1, ctx, addrs); + } + } +} + +/** + * base_w algorithm as described in draft. + * Interprets an array of bytes as integers in base w. + * This only works when log_w is a divisor of 8. + */ +static void base_w(unsigned int *output, const int out_len, + const unsigned char *input) { + int in = 0; + int out = 0; + unsigned char total = 0; + int bits = 0; + int consumed; + + for (consumed = 0; consumed < out_len; consumed++) { + if (bits == 0) { + total = input[in]; + in++; + bits += 8; + } + bits -= SPX_WOTS_LOGW; + output[out] = (total >> bits) & (SPX_WOTS_W - 1); + out++; + } +} + +/* Computes the WOTS+ checksum over a message (in base_w). */ +static void wots_checksum(unsigned int *csum_base_w, + const unsigned int *msg_base_w) { + unsigned int csum = 0; + unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; + unsigned int i; + + /* Compute checksum. */ + for (i = 0; i < SPX_WOTS_LEN1; i++) { + csum += SPX_WOTS_W - 1 - msg_base_w[i]; + } + + /* Convert checksum to base_w. */ + /* Make sure expected empty zero bits are the least significant bits. */ + csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); + ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); + base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); +} + +/* Takes a message and derives the matching chain lengths. */ +void chain_lengths(unsigned int *lengths, const unsigned char *msg) { + base_w(lengths, SPX_WOTS_LEN1, msg); + wots_checksum(lengths + SPX_WOTS_LEN1, lengths); +} + +/** + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. + * + * Writes the computed public key to 'pk'. + */ +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]) { + unsigned int steps[SPX_WOTS_LEN]; + unsigned int start[SPX_WOTS_LEN]; + uint32_t i; + + chain_lengths(start, msg); + + for (i = 0; i < SPX_WOTS_LEN; i++) { + steps[i] = SPX_WOTS_W - 1 - start[i]; + } + + gen_chains(pk, sig, start, steps, ctx, addr); +} + +/* + * This generates 8 sequential WOTS public keys + * It also generates the WOTS signature if leaf_info indicates + * that we're signing with one of these WOTS keys + */ +void wots_gen_leafx8(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info) { + struct leaf_info_x8 *info = v_info; + uint32_t *leaf_addr = info->leaf_addr; + uint32_t *pk_addr = info->pk_addr; + unsigned int i, j, k; + unsigned char pk_buffer[ 8 * SPX_WOTS_BYTES ]; + unsigned wots_offset = SPX_WOTS_BYTES; + unsigned char *buffer; + uint32_t wots_k_mask; + unsigned wots_sign_index; + + if (((leaf_idx ^ info->wots_sign_leaf) & ~7U) == 0) { + /* We're traversing the leaf that's signing; generate the WOTS */ + /* signature */ + wots_k_mask = 0; + wots_sign_index = info->wots_sign_leaf & 7; /* Which of of the 8 */ + /* slots do the signatures come from */ + } else { + /* Nope, we're just generating pk's; turn off the signature logic */ + wots_k_mask = ~0U; + wots_sign_index = 0; + } + + for (j = 0; j < 8; j++) { + set_keypair_addr( leaf_addr + j * 8, leaf_idx + j ); + set_keypair_addr( pk_addr + j * 8, leaf_idx + j ); + } + + for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { + uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k */ + /* to the step if we're generating a signature, ~0 if we're not */ + + /* Start with the secret seed */ + for (j = 0; j < 8; j++) { + set_chain_addr(leaf_addr + j * 8, i); + set_hash_addr(leaf_addr + j * 8, 0); + set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTSPRF); + } + prf_addrx8(buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + buffer + 2 * wots_offset, + buffer + 3 * wots_offset, + buffer + 4 * wots_offset, + buffer + 5 * wots_offset, + buffer + 6 * wots_offset, + buffer + 7 * wots_offset, + ctx, leaf_addr); + + for (j = 0; j < 8; j++) { + set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTS); + } + + /* Iterate down the WOTS chain */ + for (k = 0;; k++) { + /* Check if one of the values we have needs to be saved as a */ + /* part of the WOTS signature */ + if (k == wots_k) { + memcpy( info->wots_sig + i * SPX_N, + buffer + wots_sign_index * wots_offset, SPX_N ); + } + + /* Check if we hit the top of the chain */ + if (k == SPX_WOTS_W - 1) { + break; + } + + /* Iterate one step on all 8 chains */ + for (j = 0; j < 8; j++) { + set_hash_addr(leaf_addr + j * 8, k); + } + thashx8(buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + buffer + 2 * wots_offset, + buffer + 3 * wots_offset, + buffer + 4 * wots_offset, + buffer + 5 * wots_offset, + buffer + 6 * wots_offset, + buffer + 7 * wots_offset, + buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + buffer + 2 * wots_offset, + buffer + 3 * wots_offset, + buffer + 4 * wots_offset, + buffer + 5 * wots_offset, + buffer + 6 * wots_offset, + buffer + 7 * wots_offset, 1, ctx, leaf_addr); + } + } + + /* Do the final thash to generate the public keys */ + thashx8(dest + 0 * SPX_N, + dest + 1 * SPX_N, + dest + 2 * SPX_N, + dest + 3 * SPX_N, + dest + 4 * SPX_N, + dest + 5 * SPX_N, + dest + 6 * SPX_N, + dest + 7 * SPX_N, + pk_buffer + 0 * wots_offset, + pk_buffer + 1 * wots_offset, + pk_buffer + 2 * wots_offset, + pk_buffer + 3 * wots_offset, + pk_buffer + 4 * wots_offset, + pk_buffer + 5 * wots_offset, + pk_buffer + 6 * wots_offset, + pk_buffer + 7 * wots_offset, SPX_WOTS_LEN, ctx, pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/wots.h b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/wots.h new file mode 100644 index 0000000000..4e7692eeef --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/wots.h @@ -0,0 +1,25 @@ +#ifndef SPX_WOTS_H +#define SPX_WOTS_H + +#include + +#include "context.h" +#include "params.h" + +/** + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. + * + * Writes the computed public key to 'pk'. + */ +#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]); + +/* + * Compute the chain lengths needed for a given message hash + */ +#define chain_lengths SPX_NAMESPACE(chain_lengths) +void chain_lengths(unsigned int *lengths, const unsigned char *msg); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/wotsx8.h b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/wotsx8.h new file mode 100644 index 0000000000..10866efb35 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/wotsx8.h @@ -0,0 +1,42 @@ +#ifndef WOTSX8_H_ +#define WOTSX8_H_ + +#include + +#include "context.h" +#include "params.h" + +/* + * This is here to provide an interface to the internal wots_gen_leafx8 + * routine. While this routine is not referenced in the package outside of + * wots.c, it is called from the stand-alone benchmark code to characterize + * the performance + */ +struct leaf_info_x8 { + unsigned char *wots_sig; + uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ + uint32_t *wots_steps; + uint32_t leaf_addr[8 * 8]; + uint32_t pk_addr[8 * 8]; +}; + +/* Macro to set the leaf_info to something 'benign', that is, it would */ +/* run with the same time as it does during the real signing process */ +/* Used only by the benchmark code */ +#define INITIALIZE_LEAF_INFO_X8(info, addr, step_buffer) { \ + (info).wots_sig = 0; \ + (info).wots_sign_leaf = ~0; \ + (info).wots_steps = step_buffer; \ + int i; \ + for (i=0; i<8; i++) { \ + memcpy( &(info).leaf_addr[8*i], addr, 32 ); \ + memcpy( &(info).pk_addr[8*i], addr, 32 ); \ + } \ + } + +#define wots_gen_leafx8 SPX_NAMESPACE(wots_gen_leafx8) +void wots_gen_leafx8(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info); + +#endif /* WOTSX8_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/LICENSE b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/LICENSE new file mode 100644 index 0000000000..670154e353 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/LICENSE @@ -0,0 +1,116 @@ +CC0 1.0 Universal + +Statement of Purpose + +The laws of most jurisdictions throughout the world automatically confer +exclusive Copyright and Related Rights (defined below) upon the creator and +subsequent owner(s) (each and all, an "owner") of an original work of +authorship and/or a database (each, a "Work"). + +Certain owners wish to permanently relinquish those rights to a Work for the +purpose of contributing to a commons of creative, cultural and scientific +works ("Commons") that the public can reliably and without fear of later +claims of infringement build upon, modify, incorporate in other works, reuse +and redistribute as freely as possible in any form whatsoever and for any +purposes, including without limitation commercial purposes. These owners may +contribute to the Commons to promote the ideal of a free culture and the +further production of creative, cultural and scientific works, or to gain +reputation or greater distribution for their Work in part through the use and +efforts of others. + +For these and/or other purposes and motivations, and without any expectation +of additional consideration or compensation, the person associating CC0 with a +Work (the "Affirmer"), to the extent that he or she is an owner of Copyright +and Related Rights in the Work, voluntarily elects to apply CC0 to the Work +and publicly distribute the Work under its terms, with knowledge of his or her +Copyright and Related Rights in the Work and the meaning and intended legal +effect of CC0 on those rights. + +1. Copyright and Related Rights. A Work made available under CC0 may be +protected by copyright and related or neighboring rights ("Copyright and +Related Rights"). Copyright and Related Rights include, but are not limited +to, the following: + + i. the right to reproduce, adapt, distribute, perform, display, communicate, + and translate a Work; + + ii. moral rights retained by the original author(s) and/or performer(s); + + iii. publicity and privacy rights pertaining to a person's image or likeness + depicted in a Work; + + iv. rights protecting against unfair competition in regards to a Work, + subject to the limitations in paragraph 4(a), below; + + v. rights protecting the extraction, dissemination, use and reuse of data in + a Work; + + vi. database rights (such as those arising under Directive 96/9/EC of the + European Parliament and of the Council of 11 March 1996 on the legal + protection of databases, and under any national implementation thereof, + including any amended or successor version of such directive); and + + vii. other similar, equivalent or corresponding rights throughout the world + based on applicable law or treaty, and any national implementations thereof. + +2. Waiver. To the greatest extent permitted by, but not in contravention of, +applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and +unconditionally waives, abandons, and surrenders all of Affirmer's Copyright +and Related Rights and associated claims and causes of action, whether now +known or unknown (including existing as well as future claims and causes of +action), in the Work (i) in all territories worldwide, (ii) for the maximum +duration provided by applicable law or treaty (including future time +extensions), (iii) in any current or future medium and for any number of +copies, and (iv) for any purpose whatsoever, including without limitation +commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes +the Waiver for the benefit of each member of the public at large and to the +detriment of Affirmer's heirs and successors, fully intending that such Waiver +shall not be subject to revocation, rescission, cancellation, termination, or +any other legal or equitable action to disrupt the quiet enjoyment of the Work +by the public as contemplated by Affirmer's express Statement of Purpose. + +3. Public License Fallback. Should any part of the Waiver for any reason be +judged legally invalid or ineffective under applicable law, then the Waiver +shall be preserved to the maximum extent permitted taking into account +Affirmer's express Statement of Purpose. In addition, to the extent the Waiver +is so judged Affirmer hereby grants to each affected person a royalty-free, +non transferable, non sublicensable, non exclusive, irrevocable and +unconditional license to exercise Affirmer's Copyright and Related Rights in +the Work (i) in all territories worldwide, (ii) for the maximum duration +provided by applicable law or treaty (including future time extensions), (iii) +in any current or future medium and for any number of copies, and (iv) for any +purpose whatsoever, including without limitation commercial, advertising or +promotional purposes (the "License"). The License shall be deemed effective as +of the date CC0 was applied by Affirmer to the Work. Should any part of the +License for any reason be judged legally invalid or ineffective under +applicable law, such partial invalidity or ineffectiveness shall not +invalidate the remainder of the License, and in such case Affirmer hereby +affirms that he or she will not (i) exercise any of his or her remaining +Copyright and Related Rights in the Work or (ii) assert any associated claims +and causes of action with respect to the Work, in either case contrary to +Affirmer's express Statement of Purpose. + +4. Limitations and Disclaimers. + + a. No trademark or patent rights held by Affirmer are waived, abandoned, + surrendered, licensed or otherwise affected by this document. + + b. Affirmer offers the Work as-is and makes no representations or warranties + of any kind concerning the Work, express, implied, statutory or otherwise, + including without limitation warranties of title, merchantability, fitness + for a particular purpose, non infringement, or the absence of latent or + other defects, accuracy, or the present or absence of errors, whether or not + discoverable, all to the greatest extent permissible under applicable law. + + c. Affirmer disclaims responsibility for clearing rights of other persons + that may apply to the Work or any use thereof, including without limitation + any person's Copyright and Related Rights in the Work. Further, Affirmer + disclaims responsibility for obtaining any necessary consents, permissions + or other rights required for any use of the Work. + + d. Affirmer understands and acknowledges that Creative Commons is not a + party to this document and has no duty or obligation with respect to this + CC0 or use of the Work. + +For more information, please see + diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/address.c b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/address.c new file mode 100644 index 0000000000..b956e9cb29 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/address.c @@ -0,0 +1,91 @@ +#include +#include + +#include "address.h" +#include "params.h" +#include "utils.h" + +/* + * Specify which level of Merkle tree (the "layer") we're working on + */ +void set_layer_addr(uint32_t addr[8], uint32_t layer) { + ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; +} + +/* + * Specify which Merkle tree within the level (the "tree address") we're working on + */ +void set_tree_addr(uint32_t addr[8], uint64_t tree) { + ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); +} + +/* + * Specify the reason we'll use this address structure for, that is, what + * hash will we compute with it. This is used so that unrelated types of + * hashes don't accidentally get the same address structure. The type will be + * one of the SPX_ADDR_TYPE constants + */ +void set_type(uint32_t addr[8], uint32_t type) { + ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; +} + +/* + * Copy the layer and tree fields of the address structure. This is used + * when we're doing multiple types of hashes within the same Merkle tree + */ +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); +} + +/* These functions are used for OTS addresses. */ + +/* + * Specify which Merkle leaf we're working on; that is, which OTS keypair + * we're talking about. + */ +void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { + ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; +} + +/* + * Copy the layer, tree and keypair fields of the address structure. This is + * used when we're doing multiple things within the same OTS keypair + */ +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); + ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; +} + +/* + * Specify which Merkle chain within the OTS we're working with + * (the chain address) + */ +void set_chain_addr(uint32_t addr[8], uint32_t chain) { + ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; +} + +/* + * Specify where in the Merkle chain we are +* (the hash address) + */ +void set_hash_addr(uint32_t addr[8], uint32_t hash) { + ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; +} + +/* These functions are used for all hash tree addresses (including FORS). */ + +/* + * Specify the height of the node in the Merkle/FORS tree we are in + * (the tree height) + */ +void set_tree_height(uint32_t addr[8], uint32_t tree_height) { + ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; +} + +/* + * Specify the distance from the left edge of the node in the Merkle/FORS tree + * (the tree index) + */ +void set_tree_index(uint32_t addr[8], uint32_t tree_index) { + u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/address.h b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/address.h new file mode 100644 index 0000000000..24a84eb40c --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/address.h @@ -0,0 +1,52 @@ +#ifndef SPX_ADDRESS_H +#define SPX_ADDRESS_H + +#include + +#include "params.h" + +/* The hash types that are passed to set_type */ +#define SPX_ADDR_TYPE_WOTS 0 +#define SPX_ADDR_TYPE_WOTSPK 1 +#define SPX_ADDR_TYPE_HASHTREE 2 +#define SPX_ADDR_TYPE_FORSTREE 3 +#define SPX_ADDR_TYPE_FORSPK 4 +#define SPX_ADDR_TYPE_WOTSPRF 5 +#define SPX_ADDR_TYPE_FORSPRF 6 + +#define set_layer_addr SPX_NAMESPACE(set_layer_addr) +void set_layer_addr(uint32_t addr[8], uint32_t layer); + +#define set_tree_addr SPX_NAMESPACE(set_tree_addr) +void set_tree_addr(uint32_t addr[8], uint64_t tree); + +#define set_type SPX_NAMESPACE(set_type) +void set_type(uint32_t addr[8], uint32_t type); + +/* Copies the layer and tree part of one address into the other */ +#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); + +/* These functions are used for WOTS and FORS addresses. */ + +#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) +void set_keypair_addr(uint32_t addr[8], uint32_t keypair); + +#define set_chain_addr SPX_NAMESPACE(set_chain_addr) +void set_chain_addr(uint32_t addr[8], uint32_t chain); + +#define set_hash_addr SPX_NAMESPACE(set_hash_addr) +void set_hash_addr(uint32_t addr[8], uint32_t hash); + +#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); + +/* These functions are used for all hash tree addresses (including FORS). */ + +#define set_tree_height SPX_NAMESPACE(set_tree_height) +void set_tree_height(uint32_t addr[8], uint32_t tree_height); + +#define set_tree_index SPX_NAMESPACE(set_tree_index) +void set_tree_index(uint32_t addr[8], uint32_t tree_index); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/api.h b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/api.h new file mode 100644 index 0000000000..a250a782ac --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/api.h @@ -0,0 +1,77 @@ +#ifndef PQCLEAN_SPHINCSSHA2256FROBUST_CLEAN_API_H +#define PQCLEAN_SPHINCSSHA2256FROBUST_CLEAN_API_H + +#include +#include + +#define PQCLEAN_SPHINCSSHA2256FROBUST_CLEAN_CRYPTO_ALGNAME "SPHINCS+-sha2-256f-robust" + +#define PQCLEAN_SPHINCSSHA2256FROBUST_CLEAN_CRYPTO_SECRETKEYBYTES 128 +#define PQCLEAN_SPHINCSSHA2256FROBUST_CLEAN_CRYPTO_PUBLICKEYBYTES 64 +#define PQCLEAN_SPHINCSSHA2256FROBUST_CLEAN_CRYPTO_BYTES 49856 + +#define PQCLEAN_SPHINCSSHA2256FROBUST_CLEAN_CRYPTO_SEEDBYTES 96 + +/* + * Returns the length of a secret key, in bytes + */ +size_t PQCLEAN_SPHINCSSHA2256FROBUST_CLEAN_crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +size_t PQCLEAN_SPHINCSSHA2256FROBUST_CLEAN_crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +size_t PQCLEAN_SPHINCSSHA2256FROBUST_CLEAN_crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +size_t PQCLEAN_SPHINCSSHA2256FROBUST_CLEAN_crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +int PQCLEAN_SPHINCSSHA2256FROBUST_CLEAN_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +int PQCLEAN_SPHINCSSHA2256FROBUST_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +int PQCLEAN_SPHINCSSHA2256FROBUST_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +int PQCLEAN_SPHINCSSHA2256FROBUST_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, + const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +int PQCLEAN_SPHINCSSHA2256FROBUST_CLEAN_crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +int PQCLEAN_SPHINCSSHA2256FROBUST_CLEAN_crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/context.h b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/context.h new file mode 100644 index 0000000000..97e2e2469e --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/context.h @@ -0,0 +1,28 @@ +#ifndef SPX_CONTEXT_H +#define SPX_CONTEXT_H + +#include +#include + +#include "params.h" +#include "sha2.h" + +typedef struct { + uint8_t pub_seed[SPX_N]; + uint8_t sk_seed[SPX_N]; + + // sha256 state that absorbed pub_seed + sha256ctx state_seeded; + + // sha512 state that absorbed pub_seed + sha512ctx state_seeded_512; + +} spx_ctx; + +#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) +void initialize_hash_function(spx_ctx *ctx); + +#define free_hash_function SPX_NAMESPACE(free_hash_function) +void free_hash_function(spx_ctx *ctx); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/context_sha2.c b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/context_sha2.c new file mode 100644 index 0000000000..9ca9f4e7ac --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/context_sha2.c @@ -0,0 +1,36 @@ +#include "context.h" + +/** + * Absorb the constant pub_seed using one round of the compression function + * This initializes state_seeded and state_seeded_512, which can then be + * reused in thash + **/ +static void seed_state(spx_ctx *ctx) { + uint8_t block[SPX_SHA512_BLOCK_BYTES]; + size_t i; + + for (i = 0; i < SPX_N; ++i) { + block[i] = ctx->pub_seed[i]; + } + for (i = SPX_N; i < SPX_SHA512_BLOCK_BYTES; ++i) { + block[i] = 0; + } + /* block has been properly initialized for both SHA-256 and SHA-512 */ + + sha256_inc_init(&ctx->state_seeded); + sha256_inc_blocks(&ctx->state_seeded, block, 1); + sha512_inc_init(&ctx->state_seeded_512); + sha512_inc_blocks(&ctx->state_seeded_512, block, 1); +} + + +/* We initialize the state for the hash functions */ +void initialize_hash_function(spx_ctx *ctx) { + seed_state(ctx); +} + +/* Free the incremental hashing context for heap-based SHA2 APIs */ +void free_hash_function(spx_ctx *ctx) { + sha256_inc_ctx_release(&ctx->state_seeded); + sha512_inc_ctx_release(&ctx->state_seeded_512); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/fors.c b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/fors.c new file mode 100644 index 0000000000..96ca72e986 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/fors.c @@ -0,0 +1,156 @@ +#include +#include +#include + +#include "fors.h" + +#include "address.h" +#include "hash.h" +#include "thash.h" +#include "utils.h" +#include "utilsx1.h" + +static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + prf_addr(sk, ctx, fors_leaf_addr); +} + +static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, + const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + thash(leaf, sk, 1, ctx, fors_leaf_addr); +} + +struct fors_gen_leaf_info { + uint32_t leaf_addrx[8]; +}; + +static void fors_gen_leafx1(unsigned char *leaf, + const spx_ctx *ctx, + uint32_t addr_idx, void *info) { + struct fors_gen_leaf_info *fors_info = info; + uint32_t *fors_leaf_addr = fors_info->leaf_addrx; + + /* Only set the parts that the caller doesn't set */ + set_tree_index(fors_leaf_addr, addr_idx); + set_type(fors_leaf_addr, SPX_ADDR_TYPE_FORSPRF); + fors_gen_sk(leaf, ctx, fors_leaf_addr); + + set_type(fors_leaf_addr, SPX_ADDR_TYPE_FORSTREE); + fors_sk_to_leaf(leaf, leaf, + ctx, fors_leaf_addr); +} + +/** + * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + * Assumes indices has space for SPX_FORS_TREES integers. + */ +static void message_to_indices(uint32_t *indices, const unsigned char *m) { + unsigned int i, j; + unsigned int offset = 0; + + for (i = 0; i < SPX_FORS_TREES; i++) { + indices[i] = 0; + for (j = 0; j < SPX_FORS_HEIGHT; j++) { + indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); + offset++; + } + } +} + +/** + * Signs a message m, deriving the secret key from sk_seed and the FTS address. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + uint32_t fors_tree_addr[8] = {0}; + struct fors_gen_leaf_info fors_info = {0}; + uint32_t *fors_leaf_addr = fors_info.leaf_addrx; + uint32_t fors_pk_addr[8] = {0}; + uint32_t idx_offset; + unsigned int i; + + copy_keypair_addr(fors_tree_addr, fors_addr); + copy_keypair_addr(fors_leaf_addr, fors_addr); + + copy_keypair_addr(fors_pk_addr, fors_addr); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); + + message_to_indices(indices, m); + + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); + + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); + + /* Include the secret key part that produces the selected leaf node. */ + fors_gen_sk(sig, ctx, fors_tree_addr); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + sig += SPX_N; + + /* Compute the authentication path for this leaf node. */ + treehashx1(roots + i * SPX_N, sig, ctx, + indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx1, + fors_tree_addr, &fors_info); + + sig += SPX_N * SPX_FORS_HEIGHT; + } + + /* Hash horizontally across all tree roots to derive the public key. */ + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); +} + +/** + * Derives the FORS public key from a signature. + * This can be used for verification by comparing to a known public key, or to + * subsequently verify a signature on the derived public key. The latter is the + * typical use-case when used as an FTS below an OTS in a hypertree. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + unsigned char leaf[SPX_N]; + uint32_t fors_tree_addr[8] = {0}; + uint32_t fors_pk_addr[8] = {0}; + uint32_t idx_offset; + unsigned int i; + + copy_keypair_addr(fors_tree_addr, fors_addr); + copy_keypair_addr(fors_pk_addr, fors_addr); + + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); + + message_to_indices(indices, m); + + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); + + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + + /* Derive the leaf from the included secret key part. */ + fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); + sig += SPX_N; + + /* Derive the corresponding root node of this tree. */ + compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, + sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); + sig += SPX_N * SPX_FORS_HEIGHT; + } + + /* Hash horizontally across all tree roots to derive the public key. */ + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/fors.h b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/fors.h new file mode 100644 index 0000000000..509140a178 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/fors.h @@ -0,0 +1,32 @@ +#ifndef SPX_FORS_H +#define SPX_FORS_H + +#include + +#include "context.h" +#include "params.h" + +/** + * Signs a message m, deriving the secret key from sk_seed and the FTS address. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +#define fors_sign SPX_NAMESPACE(fors_sign) +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); + +/** + * Derives the FORS public key from a signature. + * This can be used for verification by comparing to a known public key, or to + * subsequently verify a signature on the derived public key. The latter is the + * typical use-case when used as an FTS below an OTS in a hypertree. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/hash.h b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/hash.h new file mode 100644 index 0000000000..ffe815f45d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/hash.h @@ -0,0 +1,37 @@ +#ifndef SPX_HASH_H +#define SPX_HASH_H + +#include +#include + +#include "context.h" +#include "params.h" + +#define prf_addr SPX_NAMESPACE(prf_addr) +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]); + +#define gen_message_random SPX_NAMESPACE(gen_message_random) +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); + +#define hash_message SPX_NAMESPACE(hash_message) +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); + + +# define SPX_SHA256_ADDR_BYTES 22 + +# define mgf1_256 SPX_NAMESPACE(mgf1_256) +void mgf1_256(unsigned char *out, unsigned long outlen, + const unsigned char *in, unsigned long inlen); + +# define mgf1_512 SPX_NAMESPACE(mgf1_512) +void mgf1_512(unsigned char *out, unsigned long outlen, + const unsigned char *in, unsigned long inlen); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/hash_sha2.c b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/hash_sha2.c new file mode 100644 index 0000000000..3d0085c8c1 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/hash_sha2.c @@ -0,0 +1,219 @@ +#include +#include + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "sha2.h" +#include "utils.h" + + + +#define SPX_SHAX_OUTPUT_BYTES SPX_SHA512_OUTPUT_BYTES +#define SPX_SHAX_BLOCK_BYTES SPX_SHA512_BLOCK_BYTES +#define shaX_inc_init sha512_inc_init +#define shaX_inc_blocks sha512_inc_blocks +#define shaX_inc_finalize sha512_inc_finalize +#define shaX sha512 +#define mgf1_X mgf1_512 +#define shaXstate sha512ctx + +/** + * mgf1 function based on the SHA-256 hash function + * Note that inlen should be sufficiently small that it still allows for + * an array to be allocated on the stack. Typically 'in' is merely a seed. + * Outputs outlen number of bytes + */ +void mgf1_256(unsigned char *out, unsigned long outlen, + const unsigned char *in, unsigned long inlen) { + PQCLEAN_VLA(uint8_t, inbuf, inlen + 4); + unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES]; + uint32_t i; + + memcpy(inbuf, in, inlen); + + /* While we can fit in at least another full block of SHA256 output.. */ + for (i = 0; (i + 1)*SPX_SHA256_OUTPUT_BYTES <= outlen; i++) { + u32_to_bytes(inbuf + inlen, i); + sha256(out, inbuf, inlen + 4); + out += SPX_SHA256_OUTPUT_BYTES; + } + /* Until we cannot anymore, and we fill the remainder. */ + if (outlen > i * SPX_SHA256_OUTPUT_BYTES) { + u32_to_bytes(inbuf + inlen, i); + sha256(outbuf, inbuf, inlen + 4); + memcpy(out, outbuf, outlen - i * SPX_SHA256_OUTPUT_BYTES); + } +} + +/* + * mgf1 function based on the SHA-512 hash function + */ +void mgf1_512(unsigned char *out, unsigned long outlen, + const unsigned char *in, unsigned long inlen) { + PQCLEAN_VLA(uint8_t, inbuf, inlen + 4); + unsigned char outbuf[SPX_SHA512_OUTPUT_BYTES]; + uint32_t i; + + memcpy(inbuf, in, inlen); + + /* While we can fit in at least another full block of SHA512 output.. */ + for (i = 0; (i + 1)*SPX_SHA512_OUTPUT_BYTES <= outlen; i++) { + u32_to_bytes(inbuf + inlen, i); + sha512(out, inbuf, inlen + 4); + out += SPX_SHA512_OUTPUT_BYTES; + } + /* Until we cannot anymore, and we fill the remainder. */ + if (outlen > i * SPX_SHA512_OUTPUT_BYTES) { + u32_to_bytes(inbuf + inlen, i); + sha512(outbuf, inbuf, inlen + 4); + memcpy(out, outbuf, outlen - i * SPX_SHA512_OUTPUT_BYTES); + } +} + +/* + * Computes PRF(pk_seed, sk_seed, addr). + */ +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]) { + sha256ctx sha2_state; + unsigned char buf[SPX_SHA256_ADDR_BYTES + SPX_N]; + unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES]; + + /* Retrieve precomputed state containing pub_seed */ + sha256_inc_ctx_clone(&sha2_state, &ctx->state_seeded); + + /* Remainder: ADDR^c ‖ SK.seed */ + memcpy(buf, addr, SPX_SHA256_ADDR_BYTES); + memcpy(buf + SPX_SHA256_ADDR_BYTES, ctx->sk_seed, SPX_N); + + sha256_inc_finalize(outbuf, &sha2_state, buf, SPX_SHA256_ADDR_BYTES + SPX_N); + + memcpy(out, outbuf, SPX_N); +} + +/** + * Computes the message-dependent randomness R, using a secret seed as a key + * for HMAC, and an optional randomization value prefixed to the message. + * This requires m to have at least SPX_SHAX_BLOCK_BYTES + SPX_N space + * available in front of the pointer, i.e. before the message to use for the + * prefix. This is necessary to prevent having to move the message around (and + * allocate memory for it). + */ +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { + (void)ctx; + + unsigned char buf[SPX_SHAX_BLOCK_BYTES + SPX_SHAX_OUTPUT_BYTES]; + shaXstate state; + int i; + + + /* This implements HMAC-SHA */ + for (i = 0; i < SPX_N; i++) { + buf[i] = 0x36 ^ sk_prf[i]; + } + memset(buf + SPX_N, 0x36, SPX_SHAX_BLOCK_BYTES - SPX_N); + + shaX_inc_init(&state); + shaX_inc_blocks(&state, buf, 1); + + memcpy(buf, optrand, SPX_N); + + /* If optrand + message cannot fill up an entire block */ + if (SPX_N + mlen < SPX_SHAX_BLOCK_BYTES) { + memcpy(buf + SPX_N, m, mlen); + shaX_inc_finalize(buf + SPX_SHAX_BLOCK_BYTES, &state, + buf, mlen + SPX_N); + } + /* Otherwise first fill a block, so that finalize only uses the message */ + else { + memcpy(buf + SPX_N, m, SPX_SHAX_BLOCK_BYTES - SPX_N); + shaX_inc_blocks(&state, buf, 1); + + m += SPX_SHAX_BLOCK_BYTES - SPX_N; + mlen -= SPX_SHAX_BLOCK_BYTES - SPX_N; + shaX_inc_finalize(buf + SPX_SHAX_BLOCK_BYTES, &state, m, mlen); + } + + for (i = 0; i < SPX_N; i++) { + buf[i] = 0x5c ^ sk_prf[i]; + } + memset(buf + SPX_N, 0x5c, SPX_SHAX_BLOCK_BYTES - SPX_N); + + shaX(buf, buf, SPX_SHAX_BLOCK_BYTES + SPX_SHAX_OUTPUT_BYTES); + memcpy(R, buf, SPX_N); +} + +/** + * Computes the message hash using R, the public key, and the message. + * Outputs the message digest and the index of the leaf. The index is split in + * the tree index and the leaf index, for convenient copying to an address. + */ +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { + (void)ctx; +#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) +#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) +#define SPX_LEAF_BITS SPX_TREE_HEIGHT +#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) +#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) + + unsigned char seed[2 * SPX_N + SPX_SHAX_OUTPUT_BYTES]; + + /* Round to nearest multiple of SPX_SHAX_BLOCK_BYTES */ +#define SPX_INBLOCKS (((SPX_N + SPX_PK_BYTES + SPX_SHAX_BLOCK_BYTES - 1) & \ + -SPX_SHAX_BLOCK_BYTES) / SPX_SHAX_BLOCK_BYTES) + unsigned char inbuf[SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES]; + + unsigned char buf[SPX_DGST_BYTES]; + unsigned char *bufp = buf; + shaXstate state; + + shaX_inc_init(&state); + + // seed: SHA-X(R ‖ PK.seed ‖ PK.root ‖ M) + memcpy(inbuf, R, SPX_N); + memcpy(inbuf + SPX_N, pk, SPX_PK_BYTES); + + /* If R + pk + message cannot fill up an entire block */ + if (SPX_N + SPX_PK_BYTES + mlen < SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES) { + memcpy(inbuf + SPX_N + SPX_PK_BYTES, m, mlen); + shaX_inc_finalize(seed + 2 * SPX_N, &state, inbuf, SPX_N + SPX_PK_BYTES + mlen); + } + /* Otherwise first fill a block, so that finalize only uses the message */ + else { + memcpy(inbuf + SPX_N + SPX_PK_BYTES, m, + SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES - SPX_N - SPX_PK_BYTES); + shaX_inc_blocks(&state, inbuf, SPX_INBLOCKS); + + m += SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES - SPX_N - SPX_PK_BYTES; + mlen -= SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES - SPX_N - SPX_PK_BYTES; + shaX_inc_finalize(seed + 2 * SPX_N, &state, m, (size_t)mlen); + } + + // H_msg: MGF1-SHA-X(R ‖ PK.seed ‖ seed) + memcpy(seed, R, SPX_N); + memcpy(seed + SPX_N, pk, SPX_N); + + /* By doing this in two steps, we prevent hashing the message twice; + otherwise each iteration in MGF1 would hash the message again. */ + mgf1_X(bufp, SPX_DGST_BYTES, seed, 2 * SPX_N + SPX_SHAX_OUTPUT_BYTES); + + memcpy(digest, bufp, SPX_FORS_MSG_BYTES); + bufp += SPX_FORS_MSG_BYTES; + + + *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); + *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); + bufp += SPX_TREE_BYTES; + + *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); + *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); +} + + diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/merkle.c b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/merkle.c new file mode 100644 index 0000000000..0c1479fd93 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/merkle.c @@ -0,0 +1,59 @@ +#include +#include + +#include "address.h" +#include "merkle.h" +#include "params.h" +#include "utils.h" +#include "utilsx1.h" +#include "wots.h" +#include "wotsx1.h" + +/* + * This generates a Merkle signature (WOTS signature followed by the Merkle + * authentication path). This is in this file because most of the complexity + * is involved with the WOTS signature; the Merkle authentication path logic + * is mostly hidden in treehashx4 + */ +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf) { + unsigned char *auth_path = sig + SPX_WOTS_BYTES; + struct leaf_info_x1 info = { 0 }; + unsigned steps[ SPX_WOTS_LEN ]; + + info.wots_sig = sig; + chain_lengths(steps, root); + info.wots_steps = steps; + + set_type(&tree_addr[0], SPX_ADDR_TYPE_HASHTREE); + set_type(&info.pk_addr[0], SPX_ADDR_TYPE_WOTSPK); + copy_subtree_addr(&info.leaf_addr[0], wots_addr); + copy_subtree_addr(&info.pk_addr[0], wots_addr); + + info.wots_sign_leaf = idx_leaf; + + treehashx1(root, auth_path, ctx, + idx_leaf, 0, + SPX_TREE_HEIGHT, + wots_gen_leafx1, + tree_addr, &info); +} + +/* Compute root node of the top-most subtree. */ +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { + /* We do not need the auth path in key generation, but it simplifies the + code to have just one treehash routine that computes both root and path + in one function. */ + unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; + uint32_t top_tree_addr[8] = {0}; + uint32_t wots_addr[8] = {0}; + + set_layer_addr(top_tree_addr, SPX_D - 1); + set_layer_addr(wots_addr, SPX_D - 1); + + merkle_sign(auth_path, root, ctx, + wots_addr, top_tree_addr, + (uint32_t)~0 /* ~0 means "don't bother generating an auth path */ ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/merkle.h b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/merkle.h new file mode 100644 index 0000000000..769cf2e970 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/merkle.h @@ -0,0 +1,21 @@ +#ifndef MERKLE_H_ +#define MERKLE_H_ + +#include + +#include "context.h" +#include "params.h" + +/* Generate a Merkle signature (WOTS signature followed by the Merkle */ +/* authentication path) */ +#define merkle_sign SPX_NAMESPACE(merkle_sign) +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf); + +/* Compute the root node of the top-most subtree. */ +#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); + +#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/nistapi.h b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/nistapi.h new file mode 100644 index 0000000000..3cb71afad4 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/nistapi.h @@ -0,0 +1,87 @@ +#ifndef SPX_API_H +#define SPX_API_H + +#include +#include + +#include "params.h" + +#define CRYPTO_ALGNAME "SPHINCS+" + +#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES +#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES +#define CRYPTO_BYTES SPX_BYTES +#define CRYPTO_SEEDBYTES (3*SPX_N) + +/* + * Returns the length of a secret key, in bytes + */ +#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) +size_t crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) +size_t crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) +size_t crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) +size_t crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +#define crypto_sign SPX_NAMESPACE(crypto_sign) +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/params.h b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/params.h new file mode 100644 index 0000000000..0a47af7089 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/params.h @@ -0,0 +1,61 @@ +#ifndef SPX_PARAMS_H +#define SPX_PARAMS_H + +#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSSHA2256FROBUST_CLEAN_##s + +/* Hash output length in bytes. */ +#define SPX_N 32 +/* Height of the hypertree. */ +#define SPX_FULL_HEIGHT 68 +/* Number of subtree layer. */ +#define SPX_D 17 +/* FORS tree dimensions. */ +#define SPX_FORS_HEIGHT 9 +#define SPX_FORS_TREES 35 +/* Winternitz parameter, */ +#define SPX_WOTS_W 16 + +/* The hash function is defined by linking a different hash.c file, as opposed + to setting a #define constant. */ + +/* This is a SHA2-based parameter set, hence whether we use SHA-256 + * exclusively or we use both SHA-256 and SHA-512 is controlled by + * the following #define */ +#define SPX_SHA512 1 /* Use SHA-512 for H and T_l, l >= 2 */ + +/* For clarity */ +#define SPX_ADDR_BYTES 32 + +/* WOTS parameters. */ +#define SPX_WOTS_LOGW 4 + +#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) + +/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ +#define SPX_WOTS_LEN2 3 + +#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) +#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) +#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES + +/* Subtree size. */ +#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) + +//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT +// #error SPX_D should always divide SPX_FULL_HEIGHT +//#endif + +/* FORS parameters. */ +#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) +#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) +#define SPX_FORS_PK_BYTES SPX_N + +/* Resulting SPX sizes. */ +#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ + SPX_FULL_HEIGHT * SPX_N) +#define SPX_PK_BYTES (2 * SPX_N) +#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) + +#include "sha2_offsets.h" + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/sha2_offsets.h b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/sha2_offsets.h new file mode 100644 index 0000000000..6e3584f7a4 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/sha2_offsets.h @@ -0,0 +1,27 @@ +#ifndef SHA2_OFFSETS_H_ +#define SHA2_OFFSETS_H_ + +#define SPX_SHA256_BLOCK_BYTES 64 +#define SPX_SHA256_OUTPUT_BYTES 32 + +#define SPX_SHA512_BLOCK_BYTES 128 +#define SPX_SHA512_OUTPUT_BYTES 64 + +/* + * Offsets of various fields in the address structure when we use SHA2 as + * the Sphincs+ hash function + */ + +#define SPX_OFFSET_LAYER 0 /* The byte used to specify the Merkle tree layer */ +#define SPX_OFFSET_TREE 1 /* The start of the 8 byte field used to specify the tree */ +#define SPX_OFFSET_TYPE 9 /* The byte used to specify the hash type (reason) */ +#define SPX_OFFSET_KP_ADDR2 12 /* The high byte used to specify the key pair (which one-time signature) */ +#define SPX_OFFSET_KP_ADDR1 13 /* The low byte used to specify the key pair */ +#define SPX_OFFSET_CHAIN_ADDR 17 /* The byte used to specify the chain address (which Winternitz chain) */ +#define SPX_OFFSET_HASH_ADDR 21 /* The byte used to specify the hash address (where in the Winternitz chain) */ +#define SPX_OFFSET_TREE_HGT 17 /* The byte used to specify the height of this node in the FORS or Merkle tree */ +#define SPX_OFFSET_TREE_INDEX 18 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ + +#define SPX_SHA2 1 + +#endif /* SHA2_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/sign.c b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/sign.c new file mode 100644 index 0000000000..9d0c7d1b22 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/sign.c @@ -0,0 +1,286 @@ +#include +#include +#include + +#include "address.h" +#include "context.h" +#include "fors.h" +#include "hash.h" +#include "merkle.h" +#include "nistapi.h" +#include "params.h" +#include "randombytes.h" +#include "thash.h" +#include "utils.h" +#include "wots.h" + +/* + * Returns the length of a secret key, in bytes + */ +size_t crypto_sign_secretkeybytes(void) { + return CRYPTO_SECRETKEYBYTES; +} + +/* + * Returns the length of a public key, in bytes + */ +size_t crypto_sign_publickeybytes(void) { + return CRYPTO_PUBLICKEYBYTES; +} + +/* + * Returns the length of a signature, in bytes + */ +size_t crypto_sign_bytes(void) { + return CRYPTO_BYTES; +} + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +size_t crypto_sign_seedbytes(void) { + return CRYPTO_SEEDBYTES; +} + +/* + * Generates an SPX key pair given a seed of length + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [PUB_SEED || root] + */ +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed) { + spx_ctx ctx; + + /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ + memcpy(sk, seed, CRYPTO_SEEDBYTES); + + memcpy(pk, sk + 2 * SPX_N, SPX_N); + + memcpy(ctx.pub_seed, pk, SPX_N); + memcpy(ctx.sk_seed, sk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + /* Compute root node of the top-most subtree. */ + merkle_gen_root(sk + 3 * SPX_N, &ctx); + + // cleanup + free_hash_function(&ctx); + + memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); + + return 0; +} + +/* + * Generates an SPX key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [PUB_SEED || root] + */ +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { + uint8_t seed[CRYPTO_SEEDBYTES]; + randombytes(seed, CRYPTO_SEEDBYTES); + crypto_sign_seed_keypair(pk, sk, seed); + + return 0; +} + +/** + * Returns an array containing a detached signature. + */ +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk) { + spx_ctx ctx; + + const uint8_t *sk_prf = sk + SPX_N; + const uint8_t *pk = sk + 2 * SPX_N; + + uint8_t optrand[SPX_N]; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t root[SPX_N]; + uint32_t i; + uint64_t tree; + uint32_t idx_leaf; + uint32_t wots_addr[8] = {0}; + uint32_t tree_addr[8] = {0}; + + memcpy(ctx.sk_seed, sk, SPX_N); + memcpy(ctx.pub_seed, pk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + + /* Optionally, signing can be made non-deterministic using optrand. + This can help counter side-channel attacks that would benefit from + getting a large number of traces when the signer uses the same nodes. */ + randombytes(optrand, SPX_N); + /* Compute the digest randomization value. */ + gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); + + /* Derive the message digest and leaf index from R, PK and M. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; + + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); + + /* Sign the message hash using FORS. */ + fors_sign(sig, root, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); + sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; + + /* Update the indices for the next layer. */ + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; + } + + free_hash_function(&ctx); + + *siglen = SPX_BYTES; + + return 0; +} + +/** + * Verifies a detached signature and message under a given public key. + */ +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk) { + spx_ctx ctx; + const uint8_t *pub_root = pk + SPX_N; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t wots_pk[SPX_WOTS_BYTES]; + uint8_t root[SPX_N]; + uint8_t leaf[SPX_N]; + unsigned int i; + uint64_t tree; + uint32_t idx_leaf; + uint32_t wots_addr[8] = {0}; + uint32_t tree_addr[8] = {0}; + uint32_t wots_pk_addr[8] = {0}; + + if (siglen != SPX_BYTES) { + return -1; + } + + memcpy(ctx.pub_seed, pk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); + + /* Derive the message digest and leaf index from R || PK || M. */ + /* The additional SPX_N is a result of the hash domain separator. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; + + /* Layer correctly defaults to 0, so no need to set_layer_addr */ + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); + + fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + /* For each subtree.. */ + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + copy_keypair_addr(wots_pk_addr, wots_addr); + + /* The WOTS public key is only correct if the signature was correct. */ + /* Initially, root is the FORS pk, but on subsequent iterations it is + the root of the subtree below the currently processed subtree. */ + wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); + sig += SPX_WOTS_BYTES; + + /* Compute the leaf node using the WOTS public key. */ + thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); + + /* Compute the root node of this subtree. */ + compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, + &ctx, tree_addr); + sig += SPX_TREE_HEIGHT * SPX_N; + + /* Update the indices for the next layer. */ + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; + } + + // cleanup + free_hash_function(&ctx); + + /* Check if the root node equals the root node in the public key. */ + if (memcmp(root, pub_root, SPX_N) != 0) { + return -1; + } + + return 0; +} + + +/** + * Returns an array containing the signature followed by the message. + */ +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk) { + size_t siglen; + + crypto_sign_signature(sm, &siglen, m, mlen, sk); + + memmove(sm + SPX_BYTES, m, mlen); + *smlen = siglen + mlen; + + return 0; +} + +/** + * Verifies a given signature-message pair under a given public key. + */ +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk) { + /* The API caller does not necessarily know what size a signature should be + but SPHINCS+ signatures are always exactly SPX_BYTES. */ + if (smlen < SPX_BYTES) { + memset(m, 0, smlen); + *mlen = 0; + return -1; + } + + *mlen = smlen - SPX_BYTES; + + if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { + memset(m, 0, smlen); + *mlen = 0; + return -1; + } + + /* If verification was successful, move the message to the right place. */ + memmove(m, sm + SPX_BYTES, *mlen); + + return 0; +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/thash.h b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/thash.h new file mode 100644 index 0000000000..8687ccfb4d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/thash.h @@ -0,0 +1,13 @@ +#ifndef SPX_THASH_H +#define SPX_THASH_H + +#include "context.h" +#include "params.h" + +#include + +#define thash SPX_NAMESPACE(thash) +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/thash_sha2_robust.c b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/thash_sha2_robust.c new file mode 100644 index 0000000000..3ab891175f --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/thash_sha2_robust.c @@ -0,0 +1,68 @@ +#include +#include + +#include "address.h" +#include "context.h" +#include "hash.h" +#include "params.h" +#include "sha2.h" +#include "thash.h" +#include "utils.h" + +static void thash_512(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]); + +/** + * Takes an array of inblocks concatenated arrays of SPX_N bytes. + */ +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]) { + if (inblocks > 1) { + thash_512(out, in, inblocks, ctx, addr); + return; + } + unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES]; + PQCLEAN_VLA(uint8_t, bitmask, inblocks * SPX_N); + PQCLEAN_VLA(uint8_t, buf, SPX_N + SPX_SHA256_OUTPUT_BYTES + inblocks * SPX_N); + sha256ctx sha2_state; + unsigned int i; + + memcpy(buf, ctx->pub_seed, SPX_N); + memcpy(buf + SPX_N, addr, SPX_SHA256_ADDR_BYTES); + mgf1_256(bitmask, inblocks * SPX_N, buf, SPX_N + SPX_SHA256_ADDR_BYTES); + + /* Retrieve precomputed state containing pub_seed */ + sha256_inc_ctx_clone(&sha2_state, &ctx->state_seeded); + + for (i = 0; i < inblocks * SPX_N; i++) { + buf[SPX_N + SPX_SHA256_ADDR_BYTES + i] = in[i] ^ bitmask[i]; + } + + sha256_inc_finalize(outbuf, &sha2_state, buf + SPX_N, + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N); + memcpy(out, outbuf, SPX_N); +} + +static void thash_512(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]) { + unsigned char outbuf[SPX_SHA512_OUTPUT_BYTES]; + PQCLEAN_VLA(uint8_t, bitmask, inblocks * SPX_N); + PQCLEAN_VLA(uint8_t, buf, SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N); + sha512ctx sha2_state; + unsigned int i; + + memcpy(buf, ctx->pub_seed, SPX_N); + memcpy(buf + SPX_N, addr, SPX_SHA256_ADDR_BYTES); + mgf1_512(bitmask, inblocks * SPX_N, buf, SPX_N + SPX_SHA256_ADDR_BYTES); + + /* Retrieve precomputed state containing pub_seed */ + sha512_inc_ctx_clone(&sha2_state, &ctx->state_seeded_512); + + for (i = 0; i < inblocks * SPX_N; i++) { + buf[SPX_N + SPX_SHA256_ADDR_BYTES + i] = in[i] ^ bitmask[i]; + } + + sha512_inc_finalize(outbuf, &sha2_state, buf + SPX_N, + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N); + memcpy(out, outbuf, SPX_N); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/utils.c b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/utils.c new file mode 100644 index 0000000000..177b541fb9 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/utils.c @@ -0,0 +1,148 @@ +#include + +#include "utils.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "thash.h" + +/** + * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. + */ +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in) { + int i; + + /* Iterate over out in decreasing order, for big-endianness. */ + for (i = (signed int)outlen - 1; i >= 0; i--) { + out[i] = in & 0xff; + in = in >> 8; + } +} + +void u32_to_bytes(unsigned char *out, uint32_t in) { + out[0] = (unsigned char)(in >> 24); + out[1] = (unsigned char)(in >> 16); + out[2] = (unsigned char)(in >> 8); + out[3] = (unsigned char)in; +} + +/** + * Converts the inlen bytes in 'in' from big-endian byte order to an integer. + */ +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { + unsigned long long retval = 0; + unsigned int i; + + for (i = 0; i < inlen; i++) { + retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); + } + return retval; +} + +/** + * Computes a root node given a leaf and an auth path. + * Expects address to be complete other than the tree_height and tree_index. + */ +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]) { + uint32_t i; + unsigned char buffer[2 * SPX_N]; + + /* If leaf_idx is odd (last bit = 1), current path element is a right child + and auth_path has to go left. Otherwise it is the other way around. */ + if (leaf_idx & 1) { + memcpy(buffer + SPX_N, leaf, SPX_N); + memcpy(buffer, auth_path, SPX_N); + } else { + memcpy(buffer, leaf, SPX_N); + memcpy(buffer + SPX_N, auth_path, SPX_N); + } + auth_path += SPX_N; + + for (i = 0; i < tree_height - 1; i++) { + leaf_idx >>= 1; + idx_offset >>= 1; + /* Set the address of the node we're creating. */ + set_tree_height(addr, i + 1); + set_tree_index(addr, leaf_idx + idx_offset); + + /* Pick the right or left neighbor, depending on parity of the node. */ + if (leaf_idx & 1) { + thash(buffer + SPX_N, buffer, 2, ctx, addr); + memcpy(buffer, auth_path, SPX_N); + } else { + thash(buffer, buffer, 2, ctx, addr); + memcpy(buffer + SPX_N, auth_path, SPX_N); + } + auth_path += SPX_N; + } + + /* The last iteration is exceptional; we do not copy an auth_path node. */ + leaf_idx >>= 1; + idx_offset >>= 1; + set_tree_height(addr, tree_height); + set_tree_index(addr, leaf_idx + idx_offset); + thash(root, buffer, 2, ctx, addr); +} + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx * /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]) { + PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); + PQCLEAN_VLA(unsigned int, heights, tree_height + 1); + unsigned int offset = 0; + uint32_t idx; + uint32_t tree_idx; + + for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { + /* Add the next leaf node to the stack. */ + gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); + offset++; + heights[offset - 1] = 0; + + /* If this is a node we need for the auth path.. */ + if ((leaf_idx ^ 0x1) == idx) { + memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); + } + + /* While the top-most nodes are of equal height.. */ + while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { + /* Compute index of the new node, in the next layer. */ + tree_idx = (idx >> (heights[offset - 1] + 1)); + + /* Set the address of the node we're creating. */ + set_tree_height(tree_addr, heights[offset - 1] + 1); + set_tree_index(tree_addr, + tree_idx + (idx_offset >> (heights[offset - 1] + 1))); + /* Hash the top-most nodes from the stack together. */ + thash(stack + (offset - 2)*SPX_N, + stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); + offset--; + /* Note that the top-most node is now one layer higher. */ + heights[offset - 1]++; + + /* If this is a node we need for the auth path.. */ + if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { + memcpy(auth_path + heights[offset - 1]*SPX_N, + stack + (offset - 1)*SPX_N, SPX_N); + } + } + } + memcpy(root, stack, SPX_N); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/utils.h b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/utils.h new file mode 100644 index 0000000000..64f5d5a53a --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/utils.h @@ -0,0 +1,58 @@ +#ifndef SPX_UTILS_H +#define SPX_UTILS_H + +#include + +#include "compat.h" +#include "context.h" +#include "params.h" + + +/* To support MSVC use alloca() instead of VLAs. See #20. */ + + +/** + * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. + */ +#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in); +#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) +void u32_to_bytes(unsigned char *out, uint32_t in); + +/** + * Converts the inlen bytes in 'in' from big-endian byte order to an integer. + */ +#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); + +/** + * Computes a root node given a leaf and an auth path. + * Expects address to be complete other than the tree_height and tree_index. + */ +#define compute_root SPX_NAMESPACE(compute_root) +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]); + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +#define treehash SPX_NAMESPACE(treehash) +void treehash(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx *ctx /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]); + + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/utilsx1.c b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/utilsx1.c new file mode 100644 index 0000000000..fccb69b35d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/utilsx1.c @@ -0,0 +1,100 @@ +#include + +#include "utilsx1.h" + +#include "address.h" +#include "params.h" +#include "thash.h" +#include "utils.h" + +/* + * Generate the entire Merkle tree, computing the authentication path for + * leaf_idx, and the resulting root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) + * + * This expects tree_addr to be initialized to the addr structures for the + * Merkle tree nodes + * + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + * + * This works by using the standard Merkle tree building algorithm, + */ +void treehashx1(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, + uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* Where to write the leaves */, + const spx_ctx * /* ctx */, + uint32_t idx, void *info), + uint32_t tree_addr[8], + void *info) { + /* This is where we keep the intermediate nodes */ + PQCLEAN_VLA(uint8_t, stack, tree_height * SPX_N); + + uint32_t idx; + uint32_t max_idx = (uint32_t)((1 << tree_height) - 1); + for (idx = 0;; idx++) { + unsigned char current[2 * SPX_N]; /* Current logical node is at */ + /* index[SPX_N]. We do this to minimize the number of copies */ + /* needed during a thash */ + gen_leaf( ¤t[SPX_N], ctx, idx + idx_offset, + info ); + + /* Now combine the freshly generated right node with previously */ + /* generated left ones */ + uint32_t internal_idx_offset = idx_offset; + uint32_t internal_idx = idx; + uint32_t internal_leaf = leaf_idx; + uint32_t h; /* The height we are in the Merkle tree */ + for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { + + /* Check if we hit the top of the tree */ + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[SPX_N], SPX_N ); + return; + } + + /* + * Check if the node we have is a part of the + * authentication path; if it is, write it out + */ + if ((internal_idx ^ internal_leaf) == 0x01) { + memcpy( &auth_path[ h * SPX_N ], + ¤t[SPX_N], + SPX_N ); + } + + /* + * Check if we're at a left child; if so, stop going up the stack + * Exception: if we've reached the end of the tree, keep on going + * (so we combine the last 4 nodes into the one root node in two + * more iterations) + */ + if ((internal_idx & 1) == 0 && idx < max_idx) { + break; + } + + /* Ok, we're at a right node */ + /* Now combine the left and right logical nodes together */ + + /* Set the address of the node we're creating. */ + internal_idx_offset >>= 1; + set_tree_height(tree_addr, h + 1); + set_tree_index(tree_addr, internal_idx / 2 + internal_idx_offset ); + + unsigned char *left = &stack[h * SPX_N]; + memcpy( ¤t[0], left, SPX_N ); + thash( ¤t[1 * SPX_N], + ¤t[0 * SPX_N], + 2, ctx, tree_addr); + } + + /* We've hit a left child; save the current for when we get the */ + /* corresponding right right */ + memcpy( &stack[h * SPX_N], ¤t[SPX_N], SPX_N); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/utilsx1.h b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/utilsx1.h new file mode 100644 index 0000000000..e911d17d53 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/utilsx1.h @@ -0,0 +1,27 @@ +#ifndef SPX_UTILSX4_H +#define SPX_UTILSX4_H + +#include + +#include "context.h" +#include "params.h" + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +#define treehashx1 SPX_NAMESPACE(treehashx1) +void treehashx1(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* Where to write the leaf */, + const spx_ctx * /* ctx */, + uint32_t addr_idx, void *info), + uint32_t tree_addrx4[8], void *info); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/wots.c b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/wots.c new file mode 100644 index 0000000000..249717aaa8 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/wots.c @@ -0,0 +1,108 @@ +#include +#include + +#include "wots.h" +#include "wotsx1.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "thash.h" +#include "utils.h" +#include "utilsx1.h" + +// TODO clarify address expectations, and make them more uniform. +// TODO i.e. do we expect types to be set already? +// TODO and do we expect modifications or copies? + +/** + * Computes the chaining function. + * out and in have to be n-byte arrays. + * + * Interprets in as start-th value of the chain. + * addr has to contain the address of the chain. + */ +static void gen_chain(unsigned char *out, const unsigned char *in, + unsigned int start, unsigned int steps, + const spx_ctx *ctx, uint32_t addr[8]) { + uint32_t i; + + /* Initialize out with the value at position 'start'. */ + memcpy(out, in, SPX_N); + + /* Iterate 'steps' calls to the hash function. */ + for (i = start; i < (start + steps) && i < SPX_WOTS_W; i++) { + set_hash_addr(addr, i); + thash(out, out, 1, ctx, addr); + } +} + +/** + * base_w algorithm as described in draft. + * Interprets an array of bytes as integers in base w. + * This only works when log_w is a divisor of 8. + */ +static void base_w(unsigned int *output, const int out_len, + const unsigned char *input) { + int in = 0; + int out = 0; + unsigned char total = 0; + int bits = 0; + int consumed; + + for (consumed = 0; consumed < out_len; consumed++) { + if (bits == 0) { + total = input[in]; + in++; + bits += 8; + } + bits -= SPX_WOTS_LOGW; + output[out] = (total >> bits) & (SPX_WOTS_W - 1); + out++; + } +} + +/* Computes the WOTS+ checksum over a message (in base_w). */ +static void wots_checksum(unsigned int *csum_base_w, + const unsigned int *msg_base_w) { + unsigned int csum = 0; + unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; + unsigned int i; + + /* Compute checksum. */ + for (i = 0; i < SPX_WOTS_LEN1; i++) { + csum += SPX_WOTS_W - 1 - msg_base_w[i]; + } + + /* Convert checksum to base_w. */ + /* Make sure expected empty zero bits are the least significant bits. */ + csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); + ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); + base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); +} + +/* Takes a message and derives the matching chain lengths. */ +void chain_lengths(unsigned int *lengths, const unsigned char *msg) { + base_w(lengths, SPX_WOTS_LEN1, msg); + wots_checksum(lengths + SPX_WOTS_LEN1, lengths); +} + +/** + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. + * + * Writes the computed public key to 'pk'. + */ +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]) { + unsigned int lengths[SPX_WOTS_LEN]; + uint32_t i; + + chain_lengths(lengths, msg); + + for (i = 0; i < SPX_WOTS_LEN; i++) { + set_chain_addr(addr, i); + gen_chain(pk + i * SPX_N, sig + i * SPX_N, + lengths[i], SPX_WOTS_W - 1 - lengths[i], ctx, addr); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/wots.h b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/wots.h new file mode 100644 index 0000000000..4e7692eeef --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/wots.h @@ -0,0 +1,25 @@ +#ifndef SPX_WOTS_H +#define SPX_WOTS_H + +#include + +#include "context.h" +#include "params.h" + +/** + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. + * + * Writes the computed public key to 'pk'. + */ +#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]); + +/* + * Compute the chain lengths needed for a given message hash + */ +#define chain_lengths SPX_NAMESPACE(chain_lengths) +void chain_lengths(unsigned int *lengths, const unsigned char *msg); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/wotsx1.c b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/wotsx1.c new file mode 100644 index 0000000000..3adec78dfb --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/wotsx1.c @@ -0,0 +1,76 @@ +#include +#include + +#include "wots.h" +#include "wotsx1.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "thash.h" +#include "utils.h" + +/* + * This generates a WOTS public key + * It also generates the WOTS signature if leaf_info indicates + * that we're signing with this WOTS key + */ +void wots_gen_leafx1(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info) { + struct leaf_info_x1 *info = v_info; + uint32_t *leaf_addr = info->leaf_addr; + uint32_t *pk_addr = info->pk_addr; + unsigned int i, k; + unsigned char pk_buffer[ SPX_WOTS_BYTES ]; + unsigned char *buffer; + uint32_t wots_k_mask; + + if (leaf_idx == info->wots_sign_leaf) { + /* We're traversing the leaf that's signing; generate the WOTS */ + /* signature */ + wots_k_mask = 0; + } else { + /* Nope, we're just generating pk's; turn off the signature logic */ + wots_k_mask = (uint32_t)~0; + } + + set_keypair_addr( leaf_addr, leaf_idx ); + set_keypair_addr( pk_addr, leaf_idx ); + + for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { + uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k to */ + /* the step if we're generating a signature, ~0 if we're not */ + + /* Start with the secret seed */ + set_chain_addr(leaf_addr, i); + set_hash_addr(leaf_addr, 0); + set_type(leaf_addr, SPX_ADDR_TYPE_WOTSPRF); + + prf_addr(buffer, ctx, leaf_addr); + + set_type(leaf_addr, SPX_ADDR_TYPE_WOTS); + + /* Iterate down the WOTS chain */ + for (k = 0;; k++) { + /* Check if this is the value that needs to be saved as a */ + /* part of the WOTS signature */ + if (k == wots_k) { + memcpy( info->wots_sig + i * SPX_N, buffer, SPX_N ); + } + + /* Check if we hit the top of the chain */ + if (k == SPX_WOTS_W - 1) { + break; + } + + /* Iterate one step on the chain */ + set_hash_addr(leaf_addr, k); + + thash(buffer, buffer, 1, ctx, leaf_addr); + } + } + + /* Do the final thash to generate the public keys */ + thash(dest, pk_buffer, SPX_WOTS_LEN, ctx, pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/wotsx1.h b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/wotsx1.h new file mode 100644 index 0000000000..e617929f96 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/wotsx1.h @@ -0,0 +1,39 @@ +#ifndef WOTSX1_H_ +#define WOTSX1_H_ + +#include + +#include "context.h" +#include "params.h" + +/* + * This is here to provide an interface to the internal wots_gen_leafx1 + * routine. While this routine is not referenced in the package outside of + * wots.c, it is called from the stand-alone benchmark code to characterize + * the performance + */ +struct leaf_info_x1 { + unsigned char *wots_sig; + uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ + uint32_t *wots_steps; + uint32_t leaf_addr[8]; + uint32_t pk_addr[8]; +}; + +/* Macro to set the leaf_info to something 'benign', that is, it would */ +/* run with the same time as it does during the real signing process */ +/* Used only by the benchmark code */ +#define INITIALIZE_LEAF_INFO_X1(info, addr, step_buffer) { \ + (info).wots_sig = 0; \ + (info).wots_sign_leaf = ~0; \ + (info).wots_steps = step_buffer; \ + memcpy( &(info).leaf_addr[0], (addr), 32 ); \ + memcpy( &(info).pk_addr[0], (addr), 32 ); \ + } + +#define wots_gen_leafx1 SPX_NAMESPACE(wots_gen_leafx1) +void wots_gen_leafx1(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info); + +#endif /* WOTSX1_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/LICENSE b/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/LICENSE new file mode 100644 index 0000000000..670154e353 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/LICENSE @@ -0,0 +1,116 @@ +CC0 1.0 Universal + +Statement of Purpose + +The laws of most jurisdictions throughout the world automatically confer +exclusive Copyright and Related Rights (defined below) upon the creator and +subsequent owner(s) (each and all, an "owner") of an original work of +authorship and/or a database (each, a "Work"). + +Certain owners wish to permanently relinquish those rights to a Work for the +purpose of contributing to a commons of creative, cultural and scientific +works ("Commons") that the public can reliably and without fear of later +claims of infringement build upon, modify, incorporate in other works, reuse +and redistribute as freely as possible in any form whatsoever and for any +purposes, including without limitation commercial purposes. These owners may +contribute to the Commons to promote the ideal of a free culture and the +further production of creative, cultural and scientific works, or to gain +reputation or greater distribution for their Work in part through the use and +efforts of others. + +For these and/or other purposes and motivations, and without any expectation +of additional consideration or compensation, the person associating CC0 with a +Work (the "Affirmer"), to the extent that he or she is an owner of Copyright +and Related Rights in the Work, voluntarily elects to apply CC0 to the Work +and publicly distribute the Work under its terms, with knowledge of his or her +Copyright and Related Rights in the Work and the meaning and intended legal +effect of CC0 on those rights. + +1. Copyright and Related Rights. A Work made available under CC0 may be +protected by copyright and related or neighboring rights ("Copyright and +Related Rights"). Copyright and Related Rights include, but are not limited +to, the following: + + i. the right to reproduce, adapt, distribute, perform, display, communicate, + and translate a Work; + + ii. moral rights retained by the original author(s) and/or performer(s); + + iii. publicity and privacy rights pertaining to a person's image or likeness + depicted in a Work; + + iv. rights protecting against unfair competition in regards to a Work, + subject to the limitations in paragraph 4(a), below; + + v. rights protecting the extraction, dissemination, use and reuse of data in + a Work; + + vi. database rights (such as those arising under Directive 96/9/EC of the + European Parliament and of the Council of 11 March 1996 on the legal + protection of databases, and under any national implementation thereof, + including any amended or successor version of such directive); and + + vii. other similar, equivalent or corresponding rights throughout the world + based on applicable law or treaty, and any national implementations thereof. + +2. Waiver. To the greatest extent permitted by, but not in contravention of, +applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and +unconditionally waives, abandons, and surrenders all of Affirmer's Copyright +and Related Rights and associated claims and causes of action, whether now +known or unknown (including existing as well as future claims and causes of +action), in the Work (i) in all territories worldwide, (ii) for the maximum +duration provided by applicable law or treaty (including future time +extensions), (iii) in any current or future medium and for any number of +copies, and (iv) for any purpose whatsoever, including without limitation +commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes +the Waiver for the benefit of each member of the public at large and to the +detriment of Affirmer's heirs and successors, fully intending that such Waiver +shall not be subject to revocation, rescission, cancellation, termination, or +any other legal or equitable action to disrupt the quiet enjoyment of the Work +by the public as contemplated by Affirmer's express Statement of Purpose. + +3. Public License Fallback. Should any part of the Waiver for any reason be +judged legally invalid or ineffective under applicable law, then the Waiver +shall be preserved to the maximum extent permitted taking into account +Affirmer's express Statement of Purpose. In addition, to the extent the Waiver +is so judged Affirmer hereby grants to each affected person a royalty-free, +non transferable, non sublicensable, non exclusive, irrevocable and +unconditional license to exercise Affirmer's Copyright and Related Rights in +the Work (i) in all territories worldwide, (ii) for the maximum duration +provided by applicable law or treaty (including future time extensions), (iii) +in any current or future medium and for any number of copies, and (iv) for any +purpose whatsoever, including without limitation commercial, advertising or +promotional purposes (the "License"). The License shall be deemed effective as +of the date CC0 was applied by Affirmer to the Work. Should any part of the +License for any reason be judged legally invalid or ineffective under +applicable law, such partial invalidity or ineffectiveness shall not +invalidate the remainder of the License, and in such case Affirmer hereby +affirms that he or she will not (i) exercise any of his or her remaining +Copyright and Related Rights in the Work or (ii) assert any associated claims +and causes of action with respect to the Work, in either case contrary to +Affirmer's express Statement of Purpose. + +4. Limitations and Disclaimers. + + a. No trademark or patent rights held by Affirmer are waived, abandoned, + surrendered, licensed or otherwise affected by this document. + + b. Affirmer offers the Work as-is and makes no representations or warranties + of any kind concerning the Work, express, implied, statutory or otherwise, + including without limitation warranties of title, merchantability, fitness + for a particular purpose, non infringement, or the absence of latent or + other defects, accuracy, or the present or absence of errors, whether or not + discoverable, all to the greatest extent permissible under applicable law. + + c. Affirmer disclaims responsibility for clearing rights of other persons + that may apply to the Work or any use thereof, including without limitation + any person's Copyright and Related Rights in the Work. Further, Affirmer + disclaims responsibility for obtaining any necessary consents, permissions + or other rights required for any use of the Work. + + d. Affirmer understands and acknowledges that Creative Commons is not a + party to this document and has no duty or obligation with respect to this + CC0 or use of the Work. + +For more information, please see + diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/address.c b/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/address.c new file mode 100644 index 0000000000..b956e9cb29 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/address.c @@ -0,0 +1,91 @@ +#include +#include + +#include "address.h" +#include "params.h" +#include "utils.h" + +/* + * Specify which level of Merkle tree (the "layer") we're working on + */ +void set_layer_addr(uint32_t addr[8], uint32_t layer) { + ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; +} + +/* + * Specify which Merkle tree within the level (the "tree address") we're working on + */ +void set_tree_addr(uint32_t addr[8], uint64_t tree) { + ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); +} + +/* + * Specify the reason we'll use this address structure for, that is, what + * hash will we compute with it. This is used so that unrelated types of + * hashes don't accidentally get the same address structure. The type will be + * one of the SPX_ADDR_TYPE constants + */ +void set_type(uint32_t addr[8], uint32_t type) { + ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; +} + +/* + * Copy the layer and tree fields of the address structure. This is used + * when we're doing multiple types of hashes within the same Merkle tree + */ +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); +} + +/* These functions are used for OTS addresses. */ + +/* + * Specify which Merkle leaf we're working on; that is, which OTS keypair + * we're talking about. + */ +void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { + ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; +} + +/* + * Copy the layer, tree and keypair fields of the address structure. This is + * used when we're doing multiple things within the same OTS keypair + */ +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); + ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; +} + +/* + * Specify which Merkle chain within the OTS we're working with + * (the chain address) + */ +void set_chain_addr(uint32_t addr[8], uint32_t chain) { + ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; +} + +/* + * Specify where in the Merkle chain we are +* (the hash address) + */ +void set_hash_addr(uint32_t addr[8], uint32_t hash) { + ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; +} + +/* These functions are used for all hash tree addresses (including FORS). */ + +/* + * Specify the height of the node in the Merkle/FORS tree we are in + * (the tree height) + */ +void set_tree_height(uint32_t addr[8], uint32_t tree_height) { + ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; +} + +/* + * Specify the distance from the left edge of the node in the Merkle/FORS tree + * (the tree index) + */ +void set_tree_index(uint32_t addr[8], uint32_t tree_index) { + u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/address.h b/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/address.h new file mode 100644 index 0000000000..24a84eb40c --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/address.h @@ -0,0 +1,52 @@ +#ifndef SPX_ADDRESS_H +#define SPX_ADDRESS_H + +#include + +#include "params.h" + +/* The hash types that are passed to set_type */ +#define SPX_ADDR_TYPE_WOTS 0 +#define SPX_ADDR_TYPE_WOTSPK 1 +#define SPX_ADDR_TYPE_HASHTREE 2 +#define SPX_ADDR_TYPE_FORSTREE 3 +#define SPX_ADDR_TYPE_FORSPK 4 +#define SPX_ADDR_TYPE_WOTSPRF 5 +#define SPX_ADDR_TYPE_FORSPRF 6 + +#define set_layer_addr SPX_NAMESPACE(set_layer_addr) +void set_layer_addr(uint32_t addr[8], uint32_t layer); + +#define set_tree_addr SPX_NAMESPACE(set_tree_addr) +void set_tree_addr(uint32_t addr[8], uint64_t tree); + +#define set_type SPX_NAMESPACE(set_type) +void set_type(uint32_t addr[8], uint32_t type); + +/* Copies the layer and tree part of one address into the other */ +#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); + +/* These functions are used for WOTS and FORS addresses. */ + +#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) +void set_keypair_addr(uint32_t addr[8], uint32_t keypair); + +#define set_chain_addr SPX_NAMESPACE(set_chain_addr) +void set_chain_addr(uint32_t addr[8], uint32_t chain); + +#define set_hash_addr SPX_NAMESPACE(set_hash_addr) +void set_hash_addr(uint32_t addr[8], uint32_t hash); + +#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); + +/* These functions are used for all hash tree addresses (including FORS). */ + +#define set_tree_height SPX_NAMESPACE(set_tree_height) +void set_tree_height(uint32_t addr[8], uint32_t tree_height); + +#define set_tree_index SPX_NAMESPACE(set_tree_index) +void set_tree_index(uint32_t addr[8], uint32_t tree_index); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/api.h b/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/api.h new file mode 100644 index 0000000000..34701b8539 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/api.h @@ -0,0 +1,77 @@ +#ifndef PQCLEAN_SPHINCSSHA2256FSIMPLE_AVX2_API_H +#define PQCLEAN_SPHINCSSHA2256FSIMPLE_AVX2_API_H + +#include +#include + +#define PQCLEAN_SPHINCSSHA2256FSIMPLE_AVX2_CRYPTO_ALGNAME "SPHINCS+-sha2-256f-simple" + +#define PQCLEAN_SPHINCSSHA2256FSIMPLE_AVX2_CRYPTO_SECRETKEYBYTES 128 +#define PQCLEAN_SPHINCSSHA2256FSIMPLE_AVX2_CRYPTO_PUBLICKEYBYTES 64 +#define PQCLEAN_SPHINCSSHA2256FSIMPLE_AVX2_CRYPTO_BYTES 49856 + +#define PQCLEAN_SPHINCSSHA2256FSIMPLE_AVX2_CRYPTO_SEEDBYTES 96 + +/* + * Returns the length of a secret key, in bytes + */ +size_t PQCLEAN_SPHINCSSHA2256FSIMPLE_AVX2_crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +size_t PQCLEAN_SPHINCSSHA2256FSIMPLE_AVX2_crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +size_t PQCLEAN_SPHINCSSHA2256FSIMPLE_AVX2_crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +size_t PQCLEAN_SPHINCSSHA2256FSIMPLE_AVX2_crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +int PQCLEAN_SPHINCSSHA2256FSIMPLE_AVX2_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +int PQCLEAN_SPHINCSSHA2256FSIMPLE_AVX2_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +int PQCLEAN_SPHINCSSHA2256FSIMPLE_AVX2_crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +int PQCLEAN_SPHINCSSHA2256FSIMPLE_AVX2_crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, + const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +int PQCLEAN_SPHINCSSHA2256FSIMPLE_AVX2_crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +int PQCLEAN_SPHINCSSHA2256FSIMPLE_AVX2_crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/context.h b/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/context.h new file mode 100644 index 0000000000..d3bf1c3aac --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/context.h @@ -0,0 +1,29 @@ +#ifndef SPX_CONTEXT_H +#define SPX_CONTEXT_H + +#include + +#include "params.h" +#include "sha2.h" +#include "sha256avx.h" +#include "sha512x4.h" + +// funky ordering due to optimal padding +typedef struct { + sha256x8ctx statex8_seeded; + sha512x4ctx statex4_seeded_512; + sha256ctx state_seeded; + sha512ctx state_seeded_512; + + uint8_t pub_seed[SPX_N]; + uint8_t sk_seed[SPX_N]; +} spx_ctx; + + +#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) +void initialize_hash_function(spx_ctx *ctx); + +#define free_hash_function SPX_NAMESPACE(free_hash_function) +void free_hash_function(spx_ctx *ctx); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/context_sha2.c b/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/context_sha2.c new file mode 100644 index 0000000000..83c1b6585d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/context_sha2.c @@ -0,0 +1,56 @@ +#include + +#include "context.h" + +/** + * Absorb the constant pub_seed using one round of the compression function + * This initializes state_seeded and state_seeded_512, which can then be + * reused in thash + **/ +static void seed_state(spx_ctx *ctx) { + uint8_t block[SPX_SHA512_BLOCK_BYTES]; + size_t i; + + for (i = 0; i < SPX_N; ++i) { + block[i] = ctx->pub_seed[i]; + } + for (i = SPX_N; i < SPX_SHA512_BLOCK_BYTES; ++i) { + block[i] = 0; + } + /* block has been properly initialized for both SHA-256 and SHA-512 */ + + sha256_inc_init(&ctx->state_seeded); + sha256_inc_blocks(&ctx->state_seeded, block, 1); + + // initialize x8 + sha256_init8x(&ctx->statex8_seeded); + sha256_transform8x(&ctx->statex8_seeded, + block, block, block, block, block, block, block, block); + + ctx->statex8_seeded.datalen = 0; + ctx->statex8_seeded.msglen = 512; + + sha512_inc_init(&ctx->state_seeded_512); + sha512_inc_blocks(&ctx->state_seeded_512, block, 1); + + // initialize x4 + sha512_init4x(&ctx->statex4_seeded_512); + sha512_transform4x(&ctx->statex4_seeded_512, block, block, block, block); + + ctx->statex4_seeded_512.datalen = 0; + ctx->statex4_seeded_512.msglen = 1024; + + +} + + +/* For SHA, we initialize the hash function at the start */ +void initialize_hash_function(spx_ctx *ctx) { + seed_state(ctx); +} + +/* Free the incremental hashing context for heap-based SHA2 APIs */ +void free_hash_function(spx_ctx *ctx) { + sha256_inc_ctx_release(&ctx->state_seeded); + sha512_inc_ctx_release(&ctx->state_seeded_512); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/fors.c b/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/fors.c new file mode 100644 index 0000000000..4cab8e7415 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/fors.c @@ -0,0 +1,226 @@ +#include +#include +#include + +#include "fors.h" + + +#include "address.h" +#include "hash.h" +#include "hashx8.h" +#include "thash.h" +#include "thashx8.h" +#include "utils.h" +#include "utilsx8.h" +static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + prf_addr(sk, ctx, fors_leaf_addr); +} + +static void fors_gen_skx8(unsigned char *sk0, + unsigned char *sk1, + unsigned char *sk2, + unsigned char *sk3, + unsigned char *sk4, + unsigned char *sk5, + unsigned char *sk6, + unsigned char *sk7, const spx_ctx *ctx, + uint32_t fors_leaf_addrx8[8 * 8]) { + prf_addrx8(sk0, sk1, sk2, sk3, sk4, sk5, sk6, sk7, + ctx, fors_leaf_addrx8); +} + +static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, + const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + thash(leaf, sk, 1, ctx, fors_leaf_addr); +} + +static void fors_sk_to_leafx8(unsigned char *leaf0, + unsigned char *leaf1, + unsigned char *leaf2, + unsigned char *leaf3, + unsigned char *leaf4, + unsigned char *leaf5, + unsigned char *leaf6, + unsigned char *leaf7, + const unsigned char *sk0, + const unsigned char *sk1, + const unsigned char *sk2, + const unsigned char *sk3, + const unsigned char *sk4, + const unsigned char *sk5, + const unsigned char *sk6, + const unsigned char *sk7, + const spx_ctx *ctx, + uint32_t fors_leaf_addrx8[8 * 8]) { + thashx8(leaf0, leaf1, leaf2, leaf3, leaf4, leaf5, leaf6, leaf7, + sk0, sk1, sk2, sk3, sk4, sk5, sk6, sk7, + 1, ctx, fors_leaf_addrx8); +} + +struct fors_gen_leaf_info { + uint32_t leaf_addrx[8 * 8]; +}; + +static void fors_gen_leafx8(unsigned char *leaf, + const spx_ctx *ctx, + uint32_t addr_idx, void *info) { + struct fors_gen_leaf_info *fors_info = info; + uint32_t *fors_leaf_addrx8 = fors_info->leaf_addrx; + unsigned int j; + + /* Only set the parts that the caller doesn't set */ + for (j = 0; j < 8; j++) { + set_tree_index(fors_leaf_addrx8 + j * 8, addr_idx + j); + set_type(fors_leaf_addrx8 + j * 8, SPX_ADDR_TYPE_FORSPRF); + } + + fors_gen_skx8(leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + leaf + 2 * SPX_N, + leaf + 3 * SPX_N, + leaf + 4 * SPX_N, + leaf + 5 * SPX_N, + leaf + 6 * SPX_N, + leaf + 7 * SPX_N, + ctx, fors_leaf_addrx8); + + for (j = 0; j < 8; j++) { + set_type(fors_leaf_addrx8 + j * 8, SPX_ADDR_TYPE_FORSTREE); + } + + fors_sk_to_leafx8(leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + leaf + 2 * SPX_N, + leaf + 3 * SPX_N, + leaf + 4 * SPX_N, + leaf + 5 * SPX_N, + leaf + 6 * SPX_N, + leaf + 7 * SPX_N, + leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + leaf + 2 * SPX_N, + leaf + 3 * SPX_N, + leaf + 4 * SPX_N, + leaf + 5 * SPX_N, + leaf + 6 * SPX_N, + leaf + 7 * SPX_N, + ctx, fors_leaf_addrx8); +} + +/** + * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + * Assumes indices has space for SPX_FORS_TREES integers. + */ +static void message_to_indices(uint32_t *indices, const unsigned char *m) { + unsigned int i, j; + unsigned int offset = 0; + + for (i = 0; i < SPX_FORS_TREES; i++) { + indices[i] = 0; + for (j = 0; j < SPX_FORS_HEIGHT; j++) { + indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); + offset++; + } + } +} + +/** + * Signs a message m, deriving the secret key from sk_seed and the FTS address. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + uint32_t fors_tree_addr[8 * 8] = {0}; + struct fors_gen_leaf_info fors_info = {0}; + uint32_t *fors_leaf_addr = fors_info.leaf_addrx; + uint32_t fors_pk_addr[8] = {0}; + uint32_t idx_offset; + unsigned int i; + + for (i = 0; i < 8; i++) { + copy_keypair_addr(fors_tree_addr + 8 * i, fors_addr); + set_type(fors_tree_addr + 8 * i, SPX_ADDR_TYPE_FORSTREE); + copy_keypair_addr(fors_leaf_addr + 8 * i, fors_addr); + } + copy_keypair_addr(fors_pk_addr, fors_addr); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); + + message_to_indices(indices, m); + + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); + + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + + /* Include the secret key part that produces the selected leaf node. */ + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); + fors_gen_sk(sig, ctx, fors_tree_addr); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + sig += SPX_N; + + /* Compute the authentication path for this leaf node. */ + treehashx8(roots + i * SPX_N, sig, ctx, + indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx8, + fors_tree_addr, &fors_info); + + sig += SPX_N * SPX_FORS_HEIGHT; + } + + /* Hash horizontally across all tree roots to derive the public key. */ + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); +} + +/** + * Derives the FORS public key from a signature. + * This can be used for verification by comparing to a known public key, or to + * subsequently verify a signature on the derived public key. The latter is the + * typical use-case when used as an FTS below an OTS in a hypertree. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + unsigned char leaf[SPX_N]; + uint32_t fors_tree_addr[8] = {0}; + uint32_t fors_pk_addr[8] = {0}; + uint32_t idx_offset; + unsigned int i; + + copy_keypair_addr(fors_tree_addr, fors_addr); + copy_keypair_addr(fors_pk_addr, fors_addr); + + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); + + message_to_indices(indices, m); + + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); + + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + + /* Derive the leaf from the included secret key part. */ + fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); + sig += SPX_N; + + /* Derive the corresponding root node of this tree. */ + compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, + sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); + sig += SPX_N * SPX_FORS_HEIGHT; + } + + /* Hash horizontally across all tree roots to derive the public key. */ + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/fors.h b/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/fors.h new file mode 100644 index 0000000000..509140a178 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/fors.h @@ -0,0 +1,32 @@ +#ifndef SPX_FORS_H +#define SPX_FORS_H + +#include + +#include "context.h" +#include "params.h" + +/** + * Signs a message m, deriving the secret key from sk_seed and the FTS address. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +#define fors_sign SPX_NAMESPACE(fors_sign) +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); + +/** + * Derives the FORS public key from a signature. + * This can be used for verification by comparing to a known public key, or to + * subsequently verify a signature on the derived public key. The latter is the + * typical use-case when used as an FTS below an OTS in a hypertree. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/hash.h b/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/hash.h new file mode 100644 index 0000000000..ffe815f45d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/hash.h @@ -0,0 +1,37 @@ +#ifndef SPX_HASH_H +#define SPX_HASH_H + +#include +#include + +#include "context.h" +#include "params.h" + +#define prf_addr SPX_NAMESPACE(prf_addr) +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]); + +#define gen_message_random SPX_NAMESPACE(gen_message_random) +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); + +#define hash_message SPX_NAMESPACE(hash_message) +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); + + +# define SPX_SHA256_ADDR_BYTES 22 + +# define mgf1_256 SPX_NAMESPACE(mgf1_256) +void mgf1_256(unsigned char *out, unsigned long outlen, + const unsigned char *in, unsigned long inlen); + +# define mgf1_512 SPX_NAMESPACE(mgf1_512) +void mgf1_512(unsigned char *out, unsigned long outlen, + const unsigned char *in, unsigned long inlen); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/hash_sha2.c b/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/hash_sha2.c new file mode 100644 index 0000000000..3d0085c8c1 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/hash_sha2.c @@ -0,0 +1,219 @@ +#include +#include + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "sha2.h" +#include "utils.h" + + + +#define SPX_SHAX_OUTPUT_BYTES SPX_SHA512_OUTPUT_BYTES +#define SPX_SHAX_BLOCK_BYTES SPX_SHA512_BLOCK_BYTES +#define shaX_inc_init sha512_inc_init +#define shaX_inc_blocks sha512_inc_blocks +#define shaX_inc_finalize sha512_inc_finalize +#define shaX sha512 +#define mgf1_X mgf1_512 +#define shaXstate sha512ctx + +/** + * mgf1 function based on the SHA-256 hash function + * Note that inlen should be sufficiently small that it still allows for + * an array to be allocated on the stack. Typically 'in' is merely a seed. + * Outputs outlen number of bytes + */ +void mgf1_256(unsigned char *out, unsigned long outlen, + const unsigned char *in, unsigned long inlen) { + PQCLEAN_VLA(uint8_t, inbuf, inlen + 4); + unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES]; + uint32_t i; + + memcpy(inbuf, in, inlen); + + /* While we can fit in at least another full block of SHA256 output.. */ + for (i = 0; (i + 1)*SPX_SHA256_OUTPUT_BYTES <= outlen; i++) { + u32_to_bytes(inbuf + inlen, i); + sha256(out, inbuf, inlen + 4); + out += SPX_SHA256_OUTPUT_BYTES; + } + /* Until we cannot anymore, and we fill the remainder. */ + if (outlen > i * SPX_SHA256_OUTPUT_BYTES) { + u32_to_bytes(inbuf + inlen, i); + sha256(outbuf, inbuf, inlen + 4); + memcpy(out, outbuf, outlen - i * SPX_SHA256_OUTPUT_BYTES); + } +} + +/* + * mgf1 function based on the SHA-512 hash function + */ +void mgf1_512(unsigned char *out, unsigned long outlen, + const unsigned char *in, unsigned long inlen) { + PQCLEAN_VLA(uint8_t, inbuf, inlen + 4); + unsigned char outbuf[SPX_SHA512_OUTPUT_BYTES]; + uint32_t i; + + memcpy(inbuf, in, inlen); + + /* While we can fit in at least another full block of SHA512 output.. */ + for (i = 0; (i + 1)*SPX_SHA512_OUTPUT_BYTES <= outlen; i++) { + u32_to_bytes(inbuf + inlen, i); + sha512(out, inbuf, inlen + 4); + out += SPX_SHA512_OUTPUT_BYTES; + } + /* Until we cannot anymore, and we fill the remainder. */ + if (outlen > i * SPX_SHA512_OUTPUT_BYTES) { + u32_to_bytes(inbuf + inlen, i); + sha512(outbuf, inbuf, inlen + 4); + memcpy(out, outbuf, outlen - i * SPX_SHA512_OUTPUT_BYTES); + } +} + +/* + * Computes PRF(pk_seed, sk_seed, addr). + */ +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]) { + sha256ctx sha2_state; + unsigned char buf[SPX_SHA256_ADDR_BYTES + SPX_N]; + unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES]; + + /* Retrieve precomputed state containing pub_seed */ + sha256_inc_ctx_clone(&sha2_state, &ctx->state_seeded); + + /* Remainder: ADDR^c ‖ SK.seed */ + memcpy(buf, addr, SPX_SHA256_ADDR_BYTES); + memcpy(buf + SPX_SHA256_ADDR_BYTES, ctx->sk_seed, SPX_N); + + sha256_inc_finalize(outbuf, &sha2_state, buf, SPX_SHA256_ADDR_BYTES + SPX_N); + + memcpy(out, outbuf, SPX_N); +} + +/** + * Computes the message-dependent randomness R, using a secret seed as a key + * for HMAC, and an optional randomization value prefixed to the message. + * This requires m to have at least SPX_SHAX_BLOCK_BYTES + SPX_N space + * available in front of the pointer, i.e. before the message to use for the + * prefix. This is necessary to prevent having to move the message around (and + * allocate memory for it). + */ +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { + (void)ctx; + + unsigned char buf[SPX_SHAX_BLOCK_BYTES + SPX_SHAX_OUTPUT_BYTES]; + shaXstate state; + int i; + + + /* This implements HMAC-SHA */ + for (i = 0; i < SPX_N; i++) { + buf[i] = 0x36 ^ sk_prf[i]; + } + memset(buf + SPX_N, 0x36, SPX_SHAX_BLOCK_BYTES - SPX_N); + + shaX_inc_init(&state); + shaX_inc_blocks(&state, buf, 1); + + memcpy(buf, optrand, SPX_N); + + /* If optrand + message cannot fill up an entire block */ + if (SPX_N + mlen < SPX_SHAX_BLOCK_BYTES) { + memcpy(buf + SPX_N, m, mlen); + shaX_inc_finalize(buf + SPX_SHAX_BLOCK_BYTES, &state, + buf, mlen + SPX_N); + } + /* Otherwise first fill a block, so that finalize only uses the message */ + else { + memcpy(buf + SPX_N, m, SPX_SHAX_BLOCK_BYTES - SPX_N); + shaX_inc_blocks(&state, buf, 1); + + m += SPX_SHAX_BLOCK_BYTES - SPX_N; + mlen -= SPX_SHAX_BLOCK_BYTES - SPX_N; + shaX_inc_finalize(buf + SPX_SHAX_BLOCK_BYTES, &state, m, mlen); + } + + for (i = 0; i < SPX_N; i++) { + buf[i] = 0x5c ^ sk_prf[i]; + } + memset(buf + SPX_N, 0x5c, SPX_SHAX_BLOCK_BYTES - SPX_N); + + shaX(buf, buf, SPX_SHAX_BLOCK_BYTES + SPX_SHAX_OUTPUT_BYTES); + memcpy(R, buf, SPX_N); +} + +/** + * Computes the message hash using R, the public key, and the message. + * Outputs the message digest and the index of the leaf. The index is split in + * the tree index and the leaf index, for convenient copying to an address. + */ +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { + (void)ctx; +#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) +#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) +#define SPX_LEAF_BITS SPX_TREE_HEIGHT +#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) +#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) + + unsigned char seed[2 * SPX_N + SPX_SHAX_OUTPUT_BYTES]; + + /* Round to nearest multiple of SPX_SHAX_BLOCK_BYTES */ +#define SPX_INBLOCKS (((SPX_N + SPX_PK_BYTES + SPX_SHAX_BLOCK_BYTES - 1) & \ + -SPX_SHAX_BLOCK_BYTES) / SPX_SHAX_BLOCK_BYTES) + unsigned char inbuf[SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES]; + + unsigned char buf[SPX_DGST_BYTES]; + unsigned char *bufp = buf; + shaXstate state; + + shaX_inc_init(&state); + + // seed: SHA-X(R ‖ PK.seed ‖ PK.root ‖ M) + memcpy(inbuf, R, SPX_N); + memcpy(inbuf + SPX_N, pk, SPX_PK_BYTES); + + /* If R + pk + message cannot fill up an entire block */ + if (SPX_N + SPX_PK_BYTES + mlen < SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES) { + memcpy(inbuf + SPX_N + SPX_PK_BYTES, m, mlen); + shaX_inc_finalize(seed + 2 * SPX_N, &state, inbuf, SPX_N + SPX_PK_BYTES + mlen); + } + /* Otherwise first fill a block, so that finalize only uses the message */ + else { + memcpy(inbuf + SPX_N + SPX_PK_BYTES, m, + SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES - SPX_N - SPX_PK_BYTES); + shaX_inc_blocks(&state, inbuf, SPX_INBLOCKS); + + m += SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES - SPX_N - SPX_PK_BYTES; + mlen -= SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES - SPX_N - SPX_PK_BYTES; + shaX_inc_finalize(seed + 2 * SPX_N, &state, m, (size_t)mlen); + } + + // H_msg: MGF1-SHA-X(R ‖ PK.seed ‖ seed) + memcpy(seed, R, SPX_N); + memcpy(seed + SPX_N, pk, SPX_N); + + /* By doing this in two steps, we prevent hashing the message twice; + otherwise each iteration in MGF1 would hash the message again. */ + mgf1_X(bufp, SPX_DGST_BYTES, seed, 2 * SPX_N + SPX_SHAX_OUTPUT_BYTES); + + memcpy(digest, bufp, SPX_FORS_MSG_BYTES); + bufp += SPX_FORS_MSG_BYTES; + + + *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); + *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); + bufp += SPX_TREE_BYTES; + + *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); + *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); +} + + diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/hash_sha2x8.c b/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/hash_sha2x8.c new file mode 100644 index 0000000000..e04af7a069 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/hash_sha2x8.c @@ -0,0 +1,75 @@ +#include +#include + +#include "hash.h" +#include "hashx8.h" + +#include "address.h" +#include "params.h" +#include "sha2.h" +#include "sha256avx.h" +#include "sha256x8.h" +#include "utils.h" + +/* + * 8-way parallel version of prf_addr; takes 8x as much input and output + */ +void prf_addrx8(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const spx_ctx *ctx, + const uint32_t addrx8[8 * 8]) { + unsigned char bufx8[8 * (SPX_N + SPX_SHA256_ADDR_BYTES)]; + unsigned char outbufx8[8 * SPX_SHA256_OUTPUT_BYTES]; + unsigned int j; + + for (j = 0; j < 8; j++) { + memcpy(bufx8 + j * (SPX_N + SPX_SHA256_ADDR_BYTES), + addrx8 + j * 8, SPX_SHA256_ADDR_BYTES); + memcpy( + bufx8 + j * (SPX_N + SPX_SHA256_ADDR_BYTES) + SPX_SHA256_ADDR_BYTES, + ctx->sk_seed, + SPX_N + ); + } + + sha256x8_seeded( + /* out */ + outbufx8 + 0 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 1 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 2 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 3 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 4 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 5 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 6 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 7 * SPX_SHA256_OUTPUT_BYTES, + + /* seed */ + &ctx->statex8_seeded, + + /* in */ + bufx8 + 0 * (SPX_SHA256_ADDR_BYTES + SPX_N), + bufx8 + 1 * (SPX_SHA256_ADDR_BYTES + SPX_N), + bufx8 + 2 * (SPX_SHA256_ADDR_BYTES + SPX_N), + bufx8 + 3 * (SPX_SHA256_ADDR_BYTES + SPX_N), + bufx8 + 4 * (SPX_SHA256_ADDR_BYTES + SPX_N), + bufx8 + 5 * (SPX_SHA256_ADDR_BYTES + SPX_N), + bufx8 + 6 * (SPX_SHA256_ADDR_BYTES + SPX_N), + bufx8 + 7 * (SPX_SHA256_ADDR_BYTES + SPX_N), + SPX_SHA256_ADDR_BYTES + SPX_N /* len */ + ); + + memcpy(out0, outbufx8 + 0 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out1, outbufx8 + 1 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out2, outbufx8 + 2 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out3, outbufx8 + 3 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out4, outbufx8 + 4 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out5, outbufx8 + 5 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out6, outbufx8 + 6 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out7, outbufx8 + 7 * SPX_SHA256_OUTPUT_BYTES, SPX_N); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/hashx8.h b/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/hashx8.h new file mode 100644 index 0000000000..46503f0a10 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/hashx8.h @@ -0,0 +1,20 @@ +#ifndef SPX_HASHX8_H +#define SPX_HASHX8_H + +#include + +#include "params.h" + +#define prf_addrx8 SPX_NAMESPACE(prf_addrx8) +void prf_addrx8(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const spx_ctx *ctx, + const uint32_t addrx8[8 * 8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/merkle.c b/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/merkle.c new file mode 100644 index 0000000000..1f353c8dd8 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/merkle.c @@ -0,0 +1,65 @@ +#include +#include + +#include "merkle.h" + +#include "address.h" +#include "params.h" +#include "utils.h" +#include "utilsx8.h" +#include "wots.h" +#include "wotsx8.h" + +/* + * This generates a Merkle signature (WOTS signature followed by the Merkle + * authentication path). + */ +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf) { + unsigned char *auth_path = sig + SPX_WOTS_BYTES; + uint32_t tree_addrx8[8 * 8] = { 0 }; + int j; + struct leaf_info_x8 info = { 0 }; + unsigned steps[ SPX_WOTS_LEN ]; + + info.wots_sig = sig; + chain_lengths(steps, root); + info.wots_steps = steps; + + for (j = 0; j < 8; j++) { + set_type(&tree_addrx8[8 * j], SPX_ADDR_TYPE_HASHTREE); + set_type(&info.leaf_addr[8 * j], SPX_ADDR_TYPE_WOTS); + set_type(&info.pk_addr[8 * j], SPX_ADDR_TYPE_WOTSPK); + copy_subtree_addr(&tree_addrx8[8 * j], tree_addr); + copy_subtree_addr(&info.leaf_addr[8 * j], wots_addr); + copy_subtree_addr(&info.pk_addr[8 * j], wots_addr); + } + + info.wots_sign_leaf = idx_leaf; + + treehashx8(root, auth_path, ctx, + idx_leaf, 0, + SPX_TREE_HEIGHT, + wots_gen_leafx8, + tree_addrx8, &info); +} + +/* Compute root node of the top-most subtree. */ +/* Again, in this file because wots_gen_leaf is most of the work */ +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { + /* We do not need the auth path in key generation, but it simplifies the + code to have just one treehash routine that computes both root and path + in one function. */ + unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; + uint32_t top_tree_addr[8] = {0}; + uint32_t wots_addr[8] = {0}; + + set_layer_addr(top_tree_addr, SPX_D - 1); + set_layer_addr(wots_addr, SPX_D - 1); + + merkle_sign(auth_path, root, ctx, + wots_addr, top_tree_addr, + ~0U /* ~0 means "don't bother generating an auth path */ ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/merkle.h b/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/merkle.h new file mode 100644 index 0000000000..769cf2e970 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/merkle.h @@ -0,0 +1,21 @@ +#ifndef MERKLE_H_ +#define MERKLE_H_ + +#include + +#include "context.h" +#include "params.h" + +/* Generate a Merkle signature (WOTS signature followed by the Merkle */ +/* authentication path) */ +#define merkle_sign SPX_NAMESPACE(merkle_sign) +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf); + +/* Compute the root node of the top-most subtree. */ +#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); + +#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/nistapi.h b/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/nistapi.h new file mode 100644 index 0000000000..3cb71afad4 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/nistapi.h @@ -0,0 +1,87 @@ +#ifndef SPX_API_H +#define SPX_API_H + +#include +#include + +#include "params.h" + +#define CRYPTO_ALGNAME "SPHINCS+" + +#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES +#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES +#define CRYPTO_BYTES SPX_BYTES +#define CRYPTO_SEEDBYTES (3*SPX_N) + +/* + * Returns the length of a secret key, in bytes + */ +#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) +size_t crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) +size_t crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) +size_t crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) +size_t crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +#define crypto_sign SPX_NAMESPACE(crypto_sign) +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/params.h b/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/params.h new file mode 100644 index 0000000000..84264cc67d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/params.h @@ -0,0 +1,61 @@ +#ifndef SPX_PARAMS_H +#define SPX_PARAMS_H + +#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSSHA2256FSIMPLE_AVX2_##s + +/* Hash output length in bytes. */ +#define SPX_N 32 +/* Height of the hypertree. */ +#define SPX_FULL_HEIGHT 68 +/* Number of subtree layer. */ +#define SPX_D 17 +/* FORS tree dimensions. */ +#define SPX_FORS_HEIGHT 9 +#define SPX_FORS_TREES 35 +/* Winternitz parameter, */ +#define SPX_WOTS_W 16 + +/* The hash function is defined by linking a different hash.c file, as opposed + to setting a #define constant. */ + +/* This is a SHA2-based parameter set, hence whether we use SHA-256 + * exclusively or we use both SHA-256 and SHA-512 is controlled by + * the following #define */ +#define SPX_SHA512 1 /* Use SHA-512 for H and T_l, l >= 2 */ + +/* For clarity */ +#define SPX_ADDR_BYTES 32 + +/* WOTS parameters. */ +#define SPX_WOTS_LOGW 4 + +#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) + +/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ +#define SPX_WOTS_LEN2 3 + +#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) +#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) +#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES + +/* Subtree size. */ +#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) + +//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT +// #error SPX_D should always divide SPX_FULL_HEIGHT +//#endif + +/* FORS parameters. */ +#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) +#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) +#define SPX_FORS_PK_BYTES SPX_N + +/* Resulting SPX sizes. */ +#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ + SPX_FULL_HEIGHT * SPX_N) +#define SPX_PK_BYTES (2 * SPX_N) +#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) + +#include "sha2_offsets.h" + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/sha256avx.c b/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/sha256avx.c new file mode 100644 index 0000000000..6bbe6ecc24 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/sha256avx.c @@ -0,0 +1,357 @@ +#include +#include +#include + +#include "sha256avx.h" + +static const unsigned int RC[] = { + 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, + 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, + 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, + 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, + 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, + 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, + 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, + 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, + 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, + 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, + 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, + 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, + 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, + 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, + 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, + 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 +}; + +#define u32 uint32_t +#define u256 __m256i + +#define XOR _mm256_xor_si256 +#define OR _mm256_or_si256 +#define AND _mm256_and_si256 +#define ADD32 _mm256_add_epi32 +#define NOT(x) _mm256_xor_si256(x, _mm256_set_epi32(-1, -1, -1, -1, -1, -1, -1, -1)) + +#define LOAD(src) _mm256_loadu_si256((__m256i *)(src)) +#define STORE(dest,src) _mm256_storeu_si256((__m256i *)(dest),src) + +#define BYTESWAP(x) _mm256_shuffle_epi8(x, _mm256_set_epi8(0xc,0xd,0xe,0xf,0x8,0x9,0xa,0xb,0x4,0x5,0x6,0x7,0x0,0x1,0x2,0x3,0xc,0xd,0xe,0xf,0x8,0x9,0xa,0xb,0x4,0x5,0x6,0x7,0x0,0x1,0x2,0x3)) + +#define SHIFTR32(x, y) _mm256_srli_epi32(x, y) +#define SHIFTL32(x, y) _mm256_slli_epi32(x, y) + +#define ROTR32(x, y) OR(SHIFTR32(x, y), SHIFTL32(x, 32 - (y))) +#define ROTL32(x, y) OR(SHIFTL32(x, y), SHIFTR32(x, 32 - (y))) + +#define XOR3(a, b, c) XOR(XOR(a, b), c) + +#define ADD3_32(a, b, c) ADD32(ADD32(a, b), c) +#define ADD4_32(a, b, c, d) ADD32(ADD32(ADD32(a, b), c), d) +#define ADD5_32(a, b, c, d, e) ADD32(ADD32(ADD32(ADD32(a, b), c), d), e) + +#define MAJ_AVX(a, b, c) XOR3(AND(a, b), AND(a, c), AND(b, c)) +#define CH_AVX(a, b, c) XOR(AND(a, b), AND(NOT(a), c)) + +#define SIGMA1_AVX(x) XOR3(ROTR32(x, 6), ROTR32(x, 11), ROTR32(x, 25)) +#define SIGMA0_AVX(x) XOR3(ROTR32(x, 2), ROTR32(x, 13), ROTR32(x, 22)) + +#define WSIGMA1_AVX(x) XOR3(ROTR32(x, 17), ROTR32(x, 19), SHIFTR32(x, 10)) +#define WSIGMA0_AVX(x) XOR3(ROTR32(x, 7), ROTR32(x, 18), SHIFTR32(x, 3)) + +#define SHA256ROUND_AVX(a, b, c, d, e, f, g, h, rc, w) \ + T0 = ADD5_32(h, SIGMA1_AVX(e), CH_AVX(e, f, g), _mm256_set1_epi32((int)RC[rc]), w); \ + (d) = ADD32(d, T0); \ + T1 = ADD32(SIGMA0_AVX(a), MAJ_AVX(a, b, c)); \ + (h) = ADD32(T0, T1); + +// Transpose 8 vectors containing 32-bit values +static void transpose(u256 s[8]) { + u256 tmp0[8]; + u256 tmp1[8]; + tmp0[0] = _mm256_unpacklo_epi32(s[0], s[1]); + tmp0[1] = _mm256_unpackhi_epi32(s[0], s[1]); + tmp0[2] = _mm256_unpacklo_epi32(s[2], s[3]); + tmp0[3] = _mm256_unpackhi_epi32(s[2], s[3]); + tmp0[4] = _mm256_unpacklo_epi32(s[4], s[5]); + tmp0[5] = _mm256_unpackhi_epi32(s[4], s[5]); + tmp0[6] = _mm256_unpacklo_epi32(s[6], s[7]); + tmp0[7] = _mm256_unpackhi_epi32(s[6], s[7]); + tmp1[0] = _mm256_unpacklo_epi64(tmp0[0], tmp0[2]); + tmp1[1] = _mm256_unpackhi_epi64(tmp0[0], tmp0[2]); + tmp1[2] = _mm256_unpacklo_epi64(tmp0[1], tmp0[3]); + tmp1[3] = _mm256_unpackhi_epi64(tmp0[1], tmp0[3]); + tmp1[4] = _mm256_unpacklo_epi64(tmp0[4], tmp0[6]); + tmp1[5] = _mm256_unpackhi_epi64(tmp0[4], tmp0[6]); + tmp1[6] = _mm256_unpacklo_epi64(tmp0[5], tmp0[7]); + tmp1[7] = _mm256_unpackhi_epi64(tmp0[5], tmp0[7]); + s[0] = _mm256_permute2x128_si256(tmp1[0], tmp1[4], 0x20); + s[1] = _mm256_permute2x128_si256(tmp1[1], tmp1[5], 0x20); + s[2] = _mm256_permute2x128_si256(tmp1[2], tmp1[6], 0x20); + s[3] = _mm256_permute2x128_si256(tmp1[3], tmp1[7], 0x20); + s[4] = _mm256_permute2x128_si256(tmp1[0], tmp1[4], 0x31); + s[5] = _mm256_permute2x128_si256(tmp1[1], tmp1[5], 0x31); + s[6] = _mm256_permute2x128_si256(tmp1[2], tmp1[6], 0x31); + s[7] = _mm256_permute2x128_si256(tmp1[3], tmp1[7], 0x31); +} + +void sha256_ctx_clone8x(sha256x8ctx *out, const sha256x8ctx *in) { + memcpy(out, in, sizeof(sha256x8ctx)); +} + +void sha256_init8x(sha256x8ctx *ctx) { + ctx->s[0] = _mm256_set_epi32((int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667); + ctx->s[1] = _mm256_set_epi32((int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85); + ctx->s[2] = _mm256_set_epi32((int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372); + ctx->s[3] = _mm256_set_epi32((int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a); + ctx->s[4] = _mm256_set_epi32((int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f); + ctx->s[5] = _mm256_set_epi32((int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c); + ctx->s[6] = _mm256_set_epi32((int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab); + ctx->s[7] = _mm256_set_epi32((int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19); + + ctx->datalen = 0; + ctx->msglen = 0; +} + +void sha256_final8x(sha256x8ctx *ctx, + unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7) { + unsigned int i, curlen; + + // Padding + if (ctx->datalen < 56) { + for (i = 0; i < 8; ++i) { + curlen = ctx->datalen; + ctx->msgblocks[64 * i + curlen++] = 0x80; + while (curlen < 64) { + ctx->msgblocks[64 * i + curlen++] = 0x00; + } + } + } else { + for (i = 0; i < 8; ++i) { + curlen = ctx->datalen; + ctx->msgblocks[64 * i + curlen++] = 0x80; + while (curlen < 64) { + ctx->msgblocks[64 * i + curlen++] = 0x00; + } + } + sha256_transform8x(ctx, + &ctx->msgblocks[64 * 0], + &ctx->msgblocks[64 * 1], + &ctx->msgblocks[64 * 2], + &ctx->msgblocks[64 * 3], + &ctx->msgblocks[64 * 4], + &ctx->msgblocks[64 * 5], + &ctx->msgblocks[64 * 6], + &ctx->msgblocks[64 * 7] + ); + memset(ctx->msgblocks, 0, 8 * 64); + } + + // Add length of the message to each block + ctx->msglen += ctx->datalen * 8; + for (i = 0; i < 8; i++) { + ctx->msgblocks[64 * i + 63] = (unsigned char)(ctx->msglen); + ctx->msgblocks[64 * i + 62] = (unsigned char)(ctx->msglen >> 8); + ctx->msgblocks[64 * i + 61] = (unsigned char)(ctx->msglen >> 16); + ctx->msgblocks[64 * i + 60] = (unsigned char)(ctx->msglen >> 24); + ctx->msgblocks[64 * i + 59] = (unsigned char)(ctx->msglen >> 32); + ctx->msgblocks[64 * i + 58] = (unsigned char)(ctx->msglen >> 40); + ctx->msgblocks[64 * i + 57] = (unsigned char)(ctx->msglen >> 48); + ctx->msgblocks[64 * i + 56] = (unsigned char)(ctx->msglen >> 56); + } + sha256_transform8x(ctx, + &ctx->msgblocks[64 * 0], + &ctx->msgblocks[64 * 1], + &ctx->msgblocks[64 * 2], + &ctx->msgblocks[64 * 3], + &ctx->msgblocks[64 * 4], + &ctx->msgblocks[64 * 5], + &ctx->msgblocks[64 * 6], + &ctx->msgblocks[64 * 7] + ); + + // Compute final hash output + transpose(ctx->s); + + // Store Hash value + STORE(out0, BYTESWAP(ctx->s[0])); + STORE(out1, BYTESWAP(ctx->s[1])); + STORE(out2, BYTESWAP(ctx->s[2])); + STORE(out3, BYTESWAP(ctx->s[3])); + STORE(out4, BYTESWAP(ctx->s[4])); + STORE(out5, BYTESWAP(ctx->s[5])); + STORE(out6, BYTESWAP(ctx->s[6])); + STORE(out7, BYTESWAP(ctx->s[7])); +} + +void sha256_transform8x(sha256x8ctx *ctx, + const unsigned char *data0, + const unsigned char *data1, + const unsigned char *data2, + const unsigned char *data3, + const unsigned char *data4, + const unsigned char *data5, + const unsigned char *data6, + const unsigned char *data7) { + u256 s[8], w[64], T0, T1; + + // Load words and transform data correctly + w[0] = BYTESWAP(LOAD(data0)); + w[0 + 8] = BYTESWAP(LOAD(data0 + 32)); + w[1] = BYTESWAP(LOAD(data1)); + w[1 + 8] = BYTESWAP(LOAD(data1 + 32)); + w[2] = BYTESWAP(LOAD(data2)); + w[2 + 8] = BYTESWAP(LOAD(data2 + 32)); + w[3] = BYTESWAP(LOAD(data3)); + w[3 + 8] = BYTESWAP(LOAD(data3 + 32)); + w[4] = BYTESWAP(LOAD(data4)); + w[4 + 8] = BYTESWAP(LOAD(data4 + 32)); + w[5] = BYTESWAP(LOAD(data5)); + w[5 + 8] = BYTESWAP(LOAD(data5 + 32)); + w[6] = BYTESWAP(LOAD(data6)); + w[6 + 8] = BYTESWAP(LOAD(data6 + 32)); + w[7] = BYTESWAP(LOAD(data7)); + w[7 + 8] = BYTESWAP(LOAD(data7 + 32)); + + transpose(w); + transpose(w + 8); + + // Initial State + s[0] = ctx->s[0]; + s[1] = ctx->s[1]; + s[2] = ctx->s[2]; + s[3] = ctx->s[3]; + s[4] = ctx->s[4]; + s[5] = ctx->s[5]; + s[6] = ctx->s[6]; + s[7] = ctx->s[7]; + + SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 0, w[0]); + SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 1, w[1]); + SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 2, w[2]); + SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 3, w[3]); + SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 4, w[4]); + SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 5, w[5]); + SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 6, w[6]); + SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 7, w[7]); + SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 8, w[8]); + SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 9, w[9]); + SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 10, w[10]); + SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 11, w[11]); + SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 12, w[12]); + SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 13, w[13]); + SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 14, w[14]); + SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 15, w[15]); + w[16] = ADD4_32(WSIGMA1_AVX(w[14]), w[0], w[9], WSIGMA0_AVX(w[1])); + SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 16, w[16]); + w[17] = ADD4_32(WSIGMA1_AVX(w[15]), w[1], w[10], WSIGMA0_AVX(w[2])); + SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 17, w[17]); + w[18] = ADD4_32(WSIGMA1_AVX(w[16]), w[2], w[11], WSIGMA0_AVX(w[3])); + SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 18, w[18]); + w[19] = ADD4_32(WSIGMA1_AVX(w[17]), w[3], w[12], WSIGMA0_AVX(w[4])); + SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 19, w[19]); + w[20] = ADD4_32(WSIGMA1_AVX(w[18]), w[4], w[13], WSIGMA0_AVX(w[5])); + SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 20, w[20]); + w[21] = ADD4_32(WSIGMA1_AVX(w[19]), w[5], w[14], WSIGMA0_AVX(w[6])); + SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 21, w[21]); + w[22] = ADD4_32(WSIGMA1_AVX(w[20]), w[6], w[15], WSIGMA0_AVX(w[7])); + SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 22, w[22]); + w[23] = ADD4_32(WSIGMA1_AVX(w[21]), w[7], w[16], WSIGMA0_AVX(w[8])); + SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 23, w[23]); + w[24] = ADD4_32(WSIGMA1_AVX(w[22]), w[8], w[17], WSIGMA0_AVX(w[9])); + SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 24, w[24]); + w[25] = ADD4_32(WSIGMA1_AVX(w[23]), w[9], w[18], WSIGMA0_AVX(w[10])); + SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 25, w[25]); + w[26] = ADD4_32(WSIGMA1_AVX(w[24]), w[10], w[19], WSIGMA0_AVX(w[11])); + SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 26, w[26]); + w[27] = ADD4_32(WSIGMA1_AVX(w[25]), w[11], w[20], WSIGMA0_AVX(w[12])); + SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 27, w[27]); + w[28] = ADD4_32(WSIGMA1_AVX(w[26]), w[12], w[21], WSIGMA0_AVX(w[13])); + SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 28, w[28]); + w[29] = ADD4_32(WSIGMA1_AVX(w[27]), w[13], w[22], WSIGMA0_AVX(w[14])); + SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 29, w[29]); + w[30] = ADD4_32(WSIGMA1_AVX(w[28]), w[14], w[23], WSIGMA0_AVX(w[15])); + SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 30, w[30]); + w[31] = ADD4_32(WSIGMA1_AVX(w[29]), w[15], w[24], WSIGMA0_AVX(w[16])); + SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 31, w[31]); + w[32] = ADD4_32(WSIGMA1_AVX(w[30]), w[16], w[25], WSIGMA0_AVX(w[17])); + SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 32, w[32]); + w[33] = ADD4_32(WSIGMA1_AVX(w[31]), w[17], w[26], WSIGMA0_AVX(w[18])); + SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 33, w[33]); + w[34] = ADD4_32(WSIGMA1_AVX(w[32]), w[18], w[27], WSIGMA0_AVX(w[19])); + SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 34, w[34]); + w[35] = ADD4_32(WSIGMA1_AVX(w[33]), w[19], w[28], WSIGMA0_AVX(w[20])); + SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 35, w[35]); + w[36] = ADD4_32(WSIGMA1_AVX(w[34]), w[20], w[29], WSIGMA0_AVX(w[21])); + SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 36, w[36]); + w[37] = ADD4_32(WSIGMA1_AVX(w[35]), w[21], w[30], WSIGMA0_AVX(w[22])); + SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 37, w[37]); + w[38] = ADD4_32(WSIGMA1_AVX(w[36]), w[22], w[31], WSIGMA0_AVX(w[23])); + SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 38, w[38]); + w[39] = ADD4_32(WSIGMA1_AVX(w[37]), w[23], w[32], WSIGMA0_AVX(w[24])); + SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 39, w[39]); + w[40] = ADD4_32(WSIGMA1_AVX(w[38]), w[24], w[33], WSIGMA0_AVX(w[25])); + SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 40, w[40]); + w[41] = ADD4_32(WSIGMA1_AVX(w[39]), w[25], w[34], WSIGMA0_AVX(w[26])); + SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 41, w[41]); + w[42] = ADD4_32(WSIGMA1_AVX(w[40]), w[26], w[35], WSIGMA0_AVX(w[27])); + SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 42, w[42]); + w[43] = ADD4_32(WSIGMA1_AVX(w[41]), w[27], w[36], WSIGMA0_AVX(w[28])); + SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 43, w[43]); + w[44] = ADD4_32(WSIGMA1_AVX(w[42]), w[28], w[37], WSIGMA0_AVX(w[29])); + SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 44, w[44]); + w[45] = ADD4_32(WSIGMA1_AVX(w[43]), w[29], w[38], WSIGMA0_AVX(w[30])); + SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 45, w[45]); + w[46] = ADD4_32(WSIGMA1_AVX(w[44]), w[30], w[39], WSIGMA0_AVX(w[31])); + SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 46, w[46]); + w[47] = ADD4_32(WSIGMA1_AVX(w[45]), w[31], w[40], WSIGMA0_AVX(w[32])); + SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 47, w[47]); + w[48] = ADD4_32(WSIGMA1_AVX(w[46]), w[32], w[41], WSIGMA0_AVX(w[33])); + SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 48, w[48]); + w[49] = ADD4_32(WSIGMA1_AVX(w[47]), w[33], w[42], WSIGMA0_AVX(w[34])); + SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 49, w[49]); + w[50] = ADD4_32(WSIGMA1_AVX(w[48]), w[34], w[43], WSIGMA0_AVX(w[35])); + SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 50, w[50]); + w[51] = ADD4_32(WSIGMA1_AVX(w[49]), w[35], w[44], WSIGMA0_AVX(w[36])); + SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 51, w[51]); + w[52] = ADD4_32(WSIGMA1_AVX(w[50]), w[36], w[45], WSIGMA0_AVX(w[37])); + SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 52, w[52]); + w[53] = ADD4_32(WSIGMA1_AVX(w[51]), w[37], w[46], WSIGMA0_AVX(w[38])); + SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 53, w[53]); + w[54] = ADD4_32(WSIGMA1_AVX(w[52]), w[38], w[47], WSIGMA0_AVX(w[39])); + SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 54, w[54]); + w[55] = ADD4_32(WSIGMA1_AVX(w[53]), w[39], w[48], WSIGMA0_AVX(w[40])); + SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 55, w[55]); + w[56] = ADD4_32(WSIGMA1_AVX(w[54]), w[40], w[49], WSIGMA0_AVX(w[41])); + SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 56, w[56]); + w[57] = ADD4_32(WSIGMA1_AVX(w[55]), w[41], w[50], WSIGMA0_AVX(w[42])); + SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 57, w[57]); + w[58] = ADD4_32(WSIGMA1_AVX(w[56]), w[42], w[51], WSIGMA0_AVX(w[43])); + SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 58, w[58]); + w[59] = ADD4_32(WSIGMA1_AVX(w[57]), w[43], w[52], WSIGMA0_AVX(w[44])); + SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 59, w[59]); + w[60] = ADD4_32(WSIGMA1_AVX(w[58]), w[44], w[53], WSIGMA0_AVX(w[45])); + SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 60, w[60]); + w[61] = ADD4_32(WSIGMA1_AVX(w[59]), w[45], w[54], WSIGMA0_AVX(w[46])); + SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 61, w[61]); + w[62] = ADD4_32(WSIGMA1_AVX(w[60]), w[46], w[55], WSIGMA0_AVX(w[47])); + SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 62, w[62]); + w[63] = ADD4_32(WSIGMA1_AVX(w[61]), w[47], w[56], WSIGMA0_AVX(w[48])); + SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 63, w[63]); + + // Feed Forward + ctx->s[0] = ADD32(s[0], ctx->s[0]); + ctx->s[1] = ADD32(s[1], ctx->s[1]); + ctx->s[2] = ADD32(s[2], ctx->s[2]); + ctx->s[3] = ADD32(s[3], ctx->s[3]); + ctx->s[4] = ADD32(s[4], ctx->s[4]); + ctx->s[5] = ADD32(s[5], ctx->s[5]); + ctx->s[6] = ADD32(s[6], ctx->s[6]); + ctx->s[7] = ADD32(s[7], ctx->s[7]); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/sha256avx.h b/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/sha256avx.h new file mode 100644 index 0000000000..1e3bcf889b --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/sha256avx.h @@ -0,0 +1,44 @@ +#ifndef SHA256AVX_H +#define SHA256AVX_H + +#include +#include + +#include "params.h" + +typedef struct SHA256state { + __m256i s[8]; + unsigned char msgblocks[8 * 64]; + unsigned int datalen; + unsigned long long msglen; +} sha256x8ctx; + +#define sha256_ctx_clone8x SPX_NAMESPACE(sha256_ctx_clone8x) +void sha256_ctx_clone8x(sha256x8ctx *out, const sha256x8ctx *in); + +#define sha256_init8x SPX_NAMESPACE(sha256_init8x) +void sha256_init8x(sha256x8ctx *ctx); + +#define sha256_final8x SPX_NAMESPACE(sha256_final8x) +void sha256_final8x(sha256x8ctx *ctx, + unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7); + +#define sha256_transform8x SPX_NAMESPACE(sha256_transform8x) +void sha256_transform8x(sha256x8ctx *ctx, + const unsigned char *data0, + const unsigned char *data1, + const unsigned char *data2, + const unsigned char *data3, + const unsigned char *data4, + const unsigned char *data5, + const unsigned char *data6, + const unsigned char *data7); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/sha256x8.c b/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/sha256x8.c new file mode 100644 index 0000000000..d97750c09b --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/sha256x8.c @@ -0,0 +1,185 @@ +#include + +#include "sha256avx.h" +#include "sha256x8.h" +#include "utils.h" + +// Performs sha256x8 on an initialized (and perhaps seeded) state. +static void _sha256x8( + sha256x8ctx *ctx, + unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, unsigned long long inlen) { + unsigned long long i = 0; + while (inlen - i >= 64) { + sha256_transform8x(ctx, + in0 + i, + in1 + i, + in2 + i, + in3 + i, + in4 + i, + in5 + i, + in6 + i, + in7 + i + ); + i += 64; + ctx->msglen += 512; + } + + size_t bytes_to_copy = (size_t)(inlen - i); + memcpy(&ctx->msgblocks[64 * 0], in0 + i, bytes_to_copy); + memcpy(&ctx->msgblocks[64 * 1], in1 + i, bytes_to_copy); + memcpy(&ctx->msgblocks[64 * 2], in2 + i, bytes_to_copy); + memcpy(&ctx->msgblocks[64 * 3], in3 + i, bytes_to_copy); + memcpy(&ctx->msgblocks[64 * 4], in4 + i, bytes_to_copy); + memcpy(&ctx->msgblocks[64 * 5], in5 + i, bytes_to_copy); + memcpy(&ctx->msgblocks[64 * 6], in6 + i, bytes_to_copy); + memcpy(&ctx->msgblocks[64 * 7], in7 + i, bytes_to_copy); + ctx->datalen = (unsigned int)bytes_to_copy; + + sha256_final8x(ctx, out0, out1, out2, out3, out4, out5, out6, out7); +} + +void sha256x8_seeded( + unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const sha256x8ctx *seed, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, unsigned long long inlen) { + + sha256x8ctx ctx; + sha256_ctx_clone8x(&ctx, seed); + + _sha256x8(&ctx, out0, out1, out2, out3, out4, out5, out6, out7, + in0, in1, in2, in3, in4, in5, in6, in7, inlen); +} + +/* This provides a wrapper around the internals of 8x parallel SHA256 */ +void sha256x8(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, unsigned long long inlen) { + sha256x8ctx ctx; + sha256_init8x(&ctx); + + _sha256x8(&ctx, out0, out1, out2, out3, out4, out5, out6, out7, + in0, in1, in2, in3, in4, in5, in6, in7, inlen); +} + +/** + * Note that inlen should be sufficiently small that it still allows for + * an array to be allocated on the stack. Typically 'in' is merely a seed. + * Outputs outlen number of bytes + */ +void mgf1x8(unsigned char *outx8, unsigned long outlen, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, + unsigned long inlen) { + PQCLEAN_VLA(unsigned char, inbufx8, 8 * (inlen + 4)); + unsigned char outbufx8[8 * SPX_SHA256_OUTPUT_BYTES]; + uint32_t i; + unsigned int j; + + memcpy(inbufx8 + 0 * (inlen + 4), in0, inlen); + memcpy(inbufx8 + 1 * (inlen + 4), in1, inlen); + memcpy(inbufx8 + 2 * (inlen + 4), in2, inlen); + memcpy(inbufx8 + 3 * (inlen + 4), in3, inlen); + memcpy(inbufx8 + 4 * (inlen + 4), in4, inlen); + memcpy(inbufx8 + 5 * (inlen + 4), in5, inlen); + memcpy(inbufx8 + 6 * (inlen + 4), in6, inlen); + memcpy(inbufx8 + 7 * (inlen + 4), in7, inlen); + + /* While we can fit in at least another full block of SHA256 output.. */ + for (i = 0; (i + 1)*SPX_SHA256_OUTPUT_BYTES <= outlen; i++) { + for (j = 0; j < 8; j++) { + u32_to_bytes(inbufx8 + inlen + j * (inlen + 4), i); + } + + sha256x8(outx8 + 0 * outlen, + outx8 + 1 * outlen, + outx8 + 2 * outlen, + outx8 + 3 * outlen, + outx8 + 4 * outlen, + outx8 + 5 * outlen, + outx8 + 6 * outlen, + outx8 + 7 * outlen, + inbufx8 + 0 * (inlen + 4), + inbufx8 + 1 * (inlen + 4), + inbufx8 + 2 * (inlen + 4), + inbufx8 + 3 * (inlen + 4), + inbufx8 + 4 * (inlen + 4), + inbufx8 + 5 * (inlen + 4), + inbufx8 + 6 * (inlen + 4), + inbufx8 + 7 * (inlen + 4), inlen + 4); + outx8 += SPX_SHA256_OUTPUT_BYTES; + } + /* Until we cannot anymore, and we fill the remainder. */ + for (j = 0; j < 8; j++) { + u32_to_bytes(inbufx8 + inlen + j * (inlen + 4), i); + } + sha256x8(outbufx8 + 0 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 1 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 2 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 3 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 4 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 5 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 6 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 7 * SPX_SHA256_OUTPUT_BYTES, + inbufx8 + 0 * (inlen + 4), + inbufx8 + 1 * (inlen + 4), + inbufx8 + 2 * (inlen + 4), + inbufx8 + 3 * (inlen + 4), + inbufx8 + 4 * (inlen + 4), + inbufx8 + 5 * (inlen + 4), + inbufx8 + 6 * (inlen + 4), + inbufx8 + 7 * (inlen + 4), inlen + 4); + + for (j = 0; j < 8; j++) { + memcpy(outx8 + j * outlen, + outbufx8 + j * SPX_SHA256_OUTPUT_BYTES, + outlen - i * SPX_SHA256_OUTPUT_BYTES); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/sha256x8.h b/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/sha256x8.h new file mode 100644 index 0000000000..4f7330a6c1 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/sha256x8.h @@ -0,0 +1,64 @@ +#ifndef SPX_SHA256X8_H +#define SPX_SHA256X8_H + +#include "params.h" +#include "sha256avx.h" + + + +#define sha256x8_seeded SPX_NAMESPACE(sha256x8_seeded) +void sha256x8_seeded( + unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const sha256x8ctx *seed, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, unsigned long long inlen); + +/* This provides a wrapper around the internals of 8x parallel SHA256 */ +#define sha256x8 SPX_NAMESPACE(sha256x8) +void sha256x8(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, unsigned long long inlen); + +/** + * Note that inlen should be sufficiently small that it still allows for + * an array to be allocated on the stack. Typically 'in' is merely a seed. + * Outputs outlen number of bytes + */ +#define mgf1x8 SPX_NAMESPACE(mgf1x8) +void mgf1x8(unsigned char *outx8, unsigned long outlen, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, + unsigned long inlen); +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/sha2_offsets.h b/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/sha2_offsets.h new file mode 100644 index 0000000000..6e3584f7a4 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/sha2_offsets.h @@ -0,0 +1,27 @@ +#ifndef SHA2_OFFSETS_H_ +#define SHA2_OFFSETS_H_ + +#define SPX_SHA256_BLOCK_BYTES 64 +#define SPX_SHA256_OUTPUT_BYTES 32 + +#define SPX_SHA512_BLOCK_BYTES 128 +#define SPX_SHA512_OUTPUT_BYTES 64 + +/* + * Offsets of various fields in the address structure when we use SHA2 as + * the Sphincs+ hash function + */ + +#define SPX_OFFSET_LAYER 0 /* The byte used to specify the Merkle tree layer */ +#define SPX_OFFSET_TREE 1 /* The start of the 8 byte field used to specify the tree */ +#define SPX_OFFSET_TYPE 9 /* The byte used to specify the hash type (reason) */ +#define SPX_OFFSET_KP_ADDR2 12 /* The high byte used to specify the key pair (which one-time signature) */ +#define SPX_OFFSET_KP_ADDR1 13 /* The low byte used to specify the key pair */ +#define SPX_OFFSET_CHAIN_ADDR 17 /* The byte used to specify the chain address (which Winternitz chain) */ +#define SPX_OFFSET_HASH_ADDR 21 /* The byte used to specify the hash address (where in the Winternitz chain) */ +#define SPX_OFFSET_TREE_HGT 17 /* The byte used to specify the height of this node in the FORS or Merkle tree */ +#define SPX_OFFSET_TREE_INDEX 18 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ + +#define SPX_SHA2 1 + +#endif /* SHA2_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/sha512x4.c b/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/sha512x4.c new file mode 100644 index 0000000000..8d33deffdd --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/sha512x4.c @@ -0,0 +1,446 @@ +#include +#include +#include + +/* pull in the entire thing */ +#include "sha512x4.h" +#include "utils.h" + +typedef uint64_t u64; +typedef __m256i u256; + +#define BYTESWAP(x) _mm256_shuffle_epi8(x, _mm256_set_epi8(0x8,0x9,0xa,0xb,0xc,0xd,0xe,0xf,0x0,0x1,0x2,0x3,0x4,0x5,0x6,0x7,0x8,0x9,0xa,0xb,0xc,0xd,0xe,0xf,0x0,0x1,0x2,0x3,0x4,0x5,0x6,0x7)) +#define STORE(dest,src) _mm256_storeu_si256((__m256i *)(dest),src) + +// Transpose 4 vectors containing 64-bit values +// That is, it rearranges the array: +// A B C D +// E F G H +// I J K L +// M N O P +// into +// A E I M +// B F J N +// C G K O +// D H L P +// where each letter stands for 64 bits (and lsbits on the left) +static void transpose(u256 s[4]) { + u256 tmp[4]; + tmp[0] = _mm256_unpacklo_epi64(s[0], s[1]); + tmp[1] = _mm256_unpackhi_epi64(s[0], s[1]); + tmp[2] = _mm256_unpacklo_epi64(s[2], s[3]); + tmp[3] = _mm256_unpackhi_epi64(s[2], s[3]); + // tmp is in the order of + // A E C G + // B F D H + // I M K O + // J N L P + s[0] = _mm256_permute2x128_si256(tmp[0], tmp[2], 0x20); + s[1] = _mm256_permute2x128_si256(tmp[1], tmp[3], 0x20); + s[2] = _mm256_permute2x128_si256(tmp[0], tmp[2], 0x31); + s[3] = _mm256_permute2x128_si256(tmp[1], tmp[3], 0x31); +} + + +void sha512_init4x(sha512x4ctx *ctx) { +#define SET4(x) _mm256_set_epi64x((long long)(x), (long long)(x), (long long)(x), (long long)(x)) + ctx->s[0] = SET4(0x6a09e667f3bcc908ULL); + ctx->s[1] = SET4(0xbb67ae8584caa73bULL); + ctx->s[2] = SET4(0x3c6ef372fe94f82bULL); + ctx->s[3] = SET4(0xa54ff53a5f1d36f1ULL); + ctx->s[4] = SET4(0x510e527fade682d1ULL); + ctx->s[5] = SET4(0x9b05688c2b3e6c1fULL); + ctx->s[6] = SET4(0x1f83d9abfb41bd6bULL); + ctx->s[7] = SET4(0x5be0cd19137e2179ULL); +#undef SET4 + + ctx->datalen = 0; + ctx->msglen = 0; +} + +#define XOR _mm256_xor_si256 +#define OR _mm256_or_si256 +#define AND _mm256_and_si256 +#define ADD64 _mm256_add_epi64 + +#define LOAD(src) _mm256_loadu_si256((__m256i *)(src)) + +#define SHIFTR64(x, y) _mm256_srli_epi64(x, y) +#define SHIFTL64(x, y) _mm256_slli_epi64(x, y) + +#define ROTR64(x, y) OR(SHIFTR64(x, y), SHIFTL64(x, 64 - (y))) + +static u256 XOR3(u256 a, u256 b, u256 c) { + return XOR(XOR(a, b), c); +} + +#define ADD3_64(a, b, c) ADD64(ADD64(a, b), c) +#define ADD4_64(a, b, c, d) ADD64(ADD64(ADD64(a, b), c), d) +#define ADD5_64(a, b, c, d, e) ADD64(ADD64(ADD64(ADD64(a, b), c), d), e) + +static u256 MAJ_AVX(u256 a, u256 b, u256 c) { + return XOR(c, AND(XOR(a, c), XOR(b, c))); +} +static u256 CH_AVX(u256 a, u256 b, u256 c) { + return XOR(c, AND(a, XOR(b, c))); +} +static u256 SIGMA0_AVX(u256 x) { + return XOR3(ROTR64(x, 28), ROTR64(x, 34), ROTR64(x, 39)); +} +static u256 SIGMA1_AVX(u256 x) { + return XOR3(ROTR64(x, 14), ROTR64(x, 18), ROTR64(x, 41)); +} +static u256 GAMMA0_AVX(u256 x) { + return XOR3(ROTR64(x, 1), ROTR64(x, 8), SHIFTR64(x, 7)); +} +static u256 GAMMA1_AVX(u256 x) { + return XOR3(ROTR64(x, 19), ROTR64(x, 61), SHIFTR64(x, 6)); +} + +#define SHA512ROUND_AVX(a, b, c, d, e, f, g, h, rc, w) \ + T0 = ADD5_64(h, w, SIGMA1_AVX(e), CH_AVX(e, f, g), _mm256_set1_epi64x((long long)RC[rc])); \ + T1 = ADD64(SIGMA0_AVX(a), MAJ_AVX(a, b, c)); \ + (d) = ADD64(d, T0); \ + (h) = ADD64(T0, T1); + +static const unsigned long long RC[80] = { + 0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL, + 0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL, + 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL, + 0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL, + 0xd807aa98a3030242ULL, 0x12835b0145706fbeULL, + 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL, + 0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL, + 0x9bdc06a725c71235ULL, 0xc19bf174cf692694ULL, + 0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL, + 0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL, + 0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL, + 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL, + 0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL, + 0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL, + 0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL, + 0x06ca6351e003826fULL, 0x142929670a0e6e70ULL, + 0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL, + 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL, + 0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL, + 0x81c2c92e47edaee6ULL, 0x92722c851482353bULL, + 0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL, + 0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL, + 0xd192e819d6ef5218ULL, 0xd69906245565a910ULL, + 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL, + 0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL, + 0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL, + 0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL, + 0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL, + 0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL, + 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL, + 0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL, + 0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL, + 0xca273eceea26619cULL, 0xd186b8c721c0c207ULL, + 0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL, + 0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL, + 0x113f9804bef90daeULL, 0x1b710b35131c471bULL, + 0x28db77f523047d84ULL, 0x32caab7b40c72493ULL, + 0x3c9ebe0a15c9bebcULL, 0x431d67c49c100d4cULL, + 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL, + 0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL, +}; + +void sha512_transform4x( + sha512x4ctx *ctx, + const unsigned char *d0, + const unsigned char *d1, + const unsigned char *d2, + const unsigned char *d3) { + u256 s0, s1, s2, s3, s4, s5, s6, s7, w[16], T0, T1, nw; + + // Load words and transform data correctly + w[0 ] = BYTESWAP(LOAD(d0 )); + w[0 + 4] = BYTESWAP(LOAD(d0 + 32)); + w[0 + 8] = BYTESWAP(LOAD(d0 + 64)); + w[0 + 12] = BYTESWAP(LOAD(d0 + 96)); + + w[1 ] = BYTESWAP(LOAD(d1 )); + w[1 + 4] = BYTESWAP(LOAD(d1 + 32)); + w[1 + 8] = BYTESWAP(LOAD(d1 + 64)); + w[1 + 12] = BYTESWAP(LOAD(d1 + 96)); + + w[2 ] = BYTESWAP(LOAD(d2 )); + w[2 + 4] = BYTESWAP(LOAD(d2 + 32)); + w[2 + 8] = BYTESWAP(LOAD(d2 + 64)); + w[2 + 12] = BYTESWAP(LOAD(d2 + 96)); + + w[3 ] = BYTESWAP(LOAD(d3 )); + w[3 + 4] = BYTESWAP(LOAD(d3 + 32)); + w[3 + 8] = BYTESWAP(LOAD(d3 + 64)); + w[3 + 12] = BYTESWAP(LOAD(d3 + 96)); + + transpose(w); + transpose(w + 4); + transpose(w + 8); + transpose(w + 12); + + // Initial State + s0 = ctx->s[0]; + s1 = ctx->s[1]; + s2 = ctx->s[2]; + s3 = ctx->s[3]; + s4 = ctx->s[4]; + s5 = ctx->s[5]; + s6 = ctx->s[6]; + s7 = ctx->s[7]; + + // The first 16 rounds (where the w inputs are directly from the data) + SHA512ROUND_AVX(s0, s1, s2, s3, s4, s5, s6, s7, 0, w[0]); + SHA512ROUND_AVX(s7, s0, s1, s2, s3, s4, s5, s6, 1, w[1]); + SHA512ROUND_AVX(s6, s7, s0, s1, s2, s3, s4, s5, 2, w[2]); + SHA512ROUND_AVX(s5, s6, s7, s0, s1, s2, s3, s4, 3, w[3]); + SHA512ROUND_AVX(s4, s5, s6, s7, s0, s1, s2, s3, 4, w[4]); + SHA512ROUND_AVX(s3, s4, s5, s6, s7, s0, s1, s2, 5, w[5]); + SHA512ROUND_AVX(s2, s3, s4, s5, s6, s7, s0, s1, 6, w[6]); + SHA512ROUND_AVX(s1, s2, s3, s4, s5, s6, s7, s0, 7, w[7]); + SHA512ROUND_AVX(s0, s1, s2, s3, s4, s5, s6, s7, 8, w[8]); + SHA512ROUND_AVX(s7, s0, s1, s2, s3, s4, s5, s6, 9, w[9]); + SHA512ROUND_AVX(s6, s7, s0, s1, s2, s3, s4, s5, 10, w[10]); + SHA512ROUND_AVX(s5, s6, s7, s0, s1, s2, s3, s4, 11, w[11]); + SHA512ROUND_AVX(s4, s5, s6, s7, s0, s1, s2, s3, 12, w[12]); + SHA512ROUND_AVX(s3, s4, s5, s6, s7, s0, s1, s2, 13, w[13]); + SHA512ROUND_AVX(s2, s3, s4, s5, s6, s7, s0, s1, 14, w[14]); + SHA512ROUND_AVX(s1, s2, s3, s4, s5, s6, s7, s0, 15, w[15]); + +#define M(i) (((i)+16) & 0xf) +#define NextW(i) \ + w[M(i)] = ADD4_64(GAMMA1_AVX(w[M((i)-2)]), w[M((i)-7)], GAMMA0_AVX(w[M((i)-15)]), w[M((i)-16)]); + + // The remaining 64 rounds (where the w inputs are a linear fix of the data) + for (unsigned i = 16; i < 80; i += 16) { + nw = NextW(0); + SHA512ROUND_AVX(s0, s1, s2, s3, s4, s5, s6, s7, i + 0, nw); + nw = NextW(1); + SHA512ROUND_AVX(s7, s0, s1, s2, s3, s4, s5, s6, i + 1, nw); + nw = NextW(2); + SHA512ROUND_AVX(s6, s7, s0, s1, s2, s3, s4, s5, i + 2, nw); + nw = NextW(3); + SHA512ROUND_AVX(s5, s6, s7, s0, s1, s2, s3, s4, i + 3, nw); + nw = NextW(4); + SHA512ROUND_AVX(s4, s5, s6, s7, s0, s1, s2, s3, i + 4, nw); + nw = NextW(5); + SHA512ROUND_AVX(s3, s4, s5, s6, s7, s0, s1, s2, i + 5, nw); + nw = NextW(6); + SHA512ROUND_AVX(s2, s3, s4, s5, s6, s7, s0, s1, i + 6, nw); + nw = NextW(7); + SHA512ROUND_AVX(s1, s2, s3, s4, s5, s6, s7, s0, i + 7, nw); + nw = NextW(8); + SHA512ROUND_AVX(s0, s1, s2, s3, s4, s5, s6, s7, i + 8, nw); + nw = NextW(9); + SHA512ROUND_AVX(s7, s0, s1, s2, s3, s4, s5, s6, i + 9, nw); + nw = NextW(10); + SHA512ROUND_AVX(s6, s7, s0, s1, s2, s3, s4, s5, i + 10, nw); + nw = NextW(11); + SHA512ROUND_AVX(s5, s6, s7, s0, s1, s2, s3, s4, i + 11, nw); + nw = NextW(12); + SHA512ROUND_AVX(s4, s5, s6, s7, s0, s1, s2, s3, i + 12, nw); + nw = NextW(13); + SHA512ROUND_AVX(s3, s4, s5, s6, s7, s0, s1, s2, i + 13, nw); + nw = NextW(14); + SHA512ROUND_AVX(s2, s3, s4, s5, s6, s7, s0, s1, i + 14, nw); + nw = NextW(15); + SHA512ROUND_AVX(s1, s2, s3, s4, s5, s6, s7, s0, i + 15, nw); + } + + // Feed Forward + ctx->s[0] = ADD64(s0, ctx->s[0]); + ctx->s[1] = ADD64(s1, ctx->s[1]); + ctx->s[2] = ADD64(s2, ctx->s[2]); + ctx->s[3] = ADD64(s3, ctx->s[3]); + ctx->s[4] = ADD64(s4, ctx->s[4]); + ctx->s[5] = ADD64(s5, ctx->s[5]); + ctx->s[6] = ADD64(s6, ctx->s[6]); + ctx->s[7] = ADD64(s7, ctx->s[7]); +} + +static void _sha512x4( + sha512x4ctx *ctx, + unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + unsigned long long inlen) { + unsigned int i = 0; + + while (inlen - i >= 128) { + sha512_transform4x( + ctx, + in0 + i, + in1 + i, + in2 + i, + in3 + i + ); + ctx->msglen += 1024; + i += 128; + } + + ctx->datalen = (unsigned int)(inlen - i); + memcpy(&ctx->msgblocks[128 * 0], in0 + i, ctx->datalen); + memcpy(&ctx->msgblocks[128 * 1], in1 + i, ctx->datalen); + memcpy(&ctx->msgblocks[128 * 2], in2 + i, ctx->datalen); + memcpy(&ctx->msgblocks[128 * 3], in3 + i, ctx->datalen); + + // Padding + unsigned long curlen; + if (ctx->datalen < 112) { + for (i = 0; i < 4; ++i) { + curlen = ctx->datalen; + ctx->msgblocks[128 * i + curlen++] = 0x80; + while (curlen < 128) { + ctx->msgblocks[128 * i + curlen++] = 0x00; + } + } + } else { + for (i = 0; i < 4; ++i) { + curlen = ctx->datalen; + ctx->msgblocks[128 * i + curlen++] = 0x80; + while (curlen < 128) { + ctx->msgblocks[128 * i + curlen++] = 0x00; + } + } + sha512_transform4x( + ctx, + ctx->msgblocks, + ctx->msgblocks + 128, + ctx->msgblocks + 256, + ctx->msgblocks + 384 + ); + memset(ctx->msgblocks, 0, 4 * 128); + } + + // Add length of the message to each block + ctx->msglen += (unsigned long long)(ctx->datalen) * 8; + for (i = 0; i < 4; i++) { + ctx->msgblocks[128 * i + 127] = (unsigned char)(ctx->msglen); + ctx->msgblocks[128 * i + 126] = (unsigned char)(ctx->msglen >> 8); + ctx->msgblocks[128 * i + 125] = (unsigned char)(ctx->msglen >> 16); + ctx->msgblocks[128 * i + 124] = (unsigned char)(ctx->msglen >> 24); + ctx->msgblocks[128 * i + 123] = (unsigned char)(ctx->msglen >> 32); + ctx->msgblocks[128 * i + 122] = (unsigned char)(ctx->msglen >> 40); + ctx->msgblocks[128 * i + 121] = (unsigned char)(ctx->msglen >> 48); + ctx->msgblocks[128 * i + 120] = (unsigned char)(ctx->msglen >> 56); + memset( &ctx->msgblocks[128 * i + 112], 0, 8 ); + } + sha512_transform4x( + ctx, + ctx->msgblocks, + ctx->msgblocks + 128, + ctx->msgblocks + 256, + ctx->msgblocks + 384 + ); + + // Compute final hash output + transpose(ctx->s); + transpose(ctx->s + 4); + + // Store Hash value + __m256i out[2]; + STORE(out, BYTESWAP(ctx->s[0])); + STORE(out + 1, BYTESWAP(ctx->s[4])); + memcpy(out0, out, 64); + + STORE(out, BYTESWAP(ctx->s[1])); + STORE(out + 1, BYTESWAP(ctx->s[5])); + memcpy(out1, out, 64); + + STORE(out, BYTESWAP(ctx->s[2])); + STORE(out + 1, BYTESWAP(ctx->s[6])); + memcpy(out2, out, 64); + + STORE(out, BYTESWAP(ctx->s[3])); + STORE(out + 1, BYTESWAP(ctx->s[7])); + memcpy(out3, out, 64); +} + + +/** + * Note that inlen should be sufficiently small that it still allows for + * an array to be allocated on the stack. Typically 'in' is merely a seed. + * Outputs outlen number of bytes + */ +void mgf1x4_512(unsigned char *outx4, unsigned long outlen, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + unsigned long inlen) { + PQCLEAN_VLA(unsigned char, inbufx4, 4 * (inlen + 4)); + unsigned char outbuf[4 * 64]; + uint32_t i; + unsigned int j; + + memcpy(inbufx4 + 0 * (inlen + 4), in0, inlen); + memcpy(inbufx4 + 1 * (inlen + 4), in1, inlen); + memcpy(inbufx4 + 2 * (inlen + 4), in2, inlen); + memcpy(inbufx4 + 3 * (inlen + 4), in3, inlen); + + /* While we can fit in at least another full block of SHA512 output.. */ + unsigned long remaining = outlen; + for (i = 0; remaining > 0; i++) { + unsigned long this_step = SPX_SHA512_OUTPUT_BYTES; + if (this_step > remaining) { + this_step = remaining; + } + remaining -= this_step; + for (j = 0; j < 4; j++) { + u32_to_bytes(inbufx4 + inlen + j * (inlen + 4), i); + } + + sha512x4ctx ctx; + sha512_init4x(&ctx); + + _sha512x4( + &ctx, + outbuf + 0 * 64, + outbuf + 1 * 64, + outbuf + 2 * 64, + outbuf + 3 * 64, + inbufx4 + 0 * (inlen + 4), + inbufx4 + 1 * (inlen + 4), + inbufx4 + 2 * (inlen + 4), + inbufx4 + 3 * (inlen + 4), + inlen + 4 + ); + + memcpy(outx4 + 0 * outlen, outbuf + 0 * 64, this_step); + memcpy(outx4 + 1 * outlen, outbuf + 1 * 64, this_step); + memcpy(outx4 + 2 * outlen, outbuf + 2 * 64, this_step); + memcpy(outx4 + 3 * outlen, outbuf + 3 * 64, this_step); + outx4 += this_step; + } +} + +void sha512x4_seeded( + unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const sha512x4ctx *seed, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + unsigned long long inlen) { + sha512x4ctx ctx; + sha512_ctx_clone4x(&ctx, seed); + _sha512x4( + &ctx, + out0, out1, out2, out3, + in0, in1, in2, in3, + inlen + ); +} + +void sha512_ctx_clone4x(sha512x4ctx *out, const sha512x4ctx *in) { + memcpy(out, in, sizeof(sha512x4ctx)); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/sha512x4.h b/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/sha512x4.h new file mode 100644 index 0000000000..9bbe736514 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/sha512x4.h @@ -0,0 +1,58 @@ +#ifndef SHA512AVX_H +#define SHA512AVX_H + +#include +#include + + +#include "params.h" + +typedef struct SHA512state4x { + __m256i s[8]; + unsigned char msgblocks[4 * 128]; + unsigned int datalen; + unsigned long long msglen; +} sha512x4ctx; + +#define sha512_init4x SPX_NAMESPACE(sha512_init4x) +void sha512_init4x(sha512x4ctx *ctx); + +#define sha512_transform4x SPX_NAMESPACE(sha512_transform4x) +void sha512_transform4x( + sha512x4ctx *ctx, + const unsigned char *d0, + const unsigned char *d1, + const unsigned char *d2, + const unsigned char *d3); + + +#define sha512x4_seeded SPX_NAMESPACE(sha512x4_seeded) +void sha512x4_seeded( + unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const sha512x4ctx *seed, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + unsigned long long inlen); + +#define sha512_ctx_clone4x SPX_NAMESPACE(sha512_ctx_clone4x) +void sha512_ctx_clone4x(sha512x4ctx *out, const sha512x4ctx *in); + +/** + * Note that inlen should be sufficiently small that it still allows for + * an array to be allocated on the stack. Typically 'in' is merely a seed. + * Outputs outlen number of bytes + */ +#define mgf1x4_512 SPX_NAMESPACE(mgf1x4_512) +void mgf1x4_512(unsigned char *outx4, unsigned long outlen, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + unsigned long inlen); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/sign.c b/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/sign.c new file mode 100644 index 0000000000..9d0c7d1b22 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/sign.c @@ -0,0 +1,286 @@ +#include +#include +#include + +#include "address.h" +#include "context.h" +#include "fors.h" +#include "hash.h" +#include "merkle.h" +#include "nistapi.h" +#include "params.h" +#include "randombytes.h" +#include "thash.h" +#include "utils.h" +#include "wots.h" + +/* + * Returns the length of a secret key, in bytes + */ +size_t crypto_sign_secretkeybytes(void) { + return CRYPTO_SECRETKEYBYTES; +} + +/* + * Returns the length of a public key, in bytes + */ +size_t crypto_sign_publickeybytes(void) { + return CRYPTO_PUBLICKEYBYTES; +} + +/* + * Returns the length of a signature, in bytes + */ +size_t crypto_sign_bytes(void) { + return CRYPTO_BYTES; +} + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +size_t crypto_sign_seedbytes(void) { + return CRYPTO_SEEDBYTES; +} + +/* + * Generates an SPX key pair given a seed of length + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [PUB_SEED || root] + */ +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed) { + spx_ctx ctx; + + /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ + memcpy(sk, seed, CRYPTO_SEEDBYTES); + + memcpy(pk, sk + 2 * SPX_N, SPX_N); + + memcpy(ctx.pub_seed, pk, SPX_N); + memcpy(ctx.sk_seed, sk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + /* Compute root node of the top-most subtree. */ + merkle_gen_root(sk + 3 * SPX_N, &ctx); + + // cleanup + free_hash_function(&ctx); + + memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); + + return 0; +} + +/* + * Generates an SPX key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [PUB_SEED || root] + */ +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { + uint8_t seed[CRYPTO_SEEDBYTES]; + randombytes(seed, CRYPTO_SEEDBYTES); + crypto_sign_seed_keypair(pk, sk, seed); + + return 0; +} + +/** + * Returns an array containing a detached signature. + */ +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk) { + spx_ctx ctx; + + const uint8_t *sk_prf = sk + SPX_N; + const uint8_t *pk = sk + 2 * SPX_N; + + uint8_t optrand[SPX_N]; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t root[SPX_N]; + uint32_t i; + uint64_t tree; + uint32_t idx_leaf; + uint32_t wots_addr[8] = {0}; + uint32_t tree_addr[8] = {0}; + + memcpy(ctx.sk_seed, sk, SPX_N); + memcpy(ctx.pub_seed, pk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + + /* Optionally, signing can be made non-deterministic using optrand. + This can help counter side-channel attacks that would benefit from + getting a large number of traces when the signer uses the same nodes. */ + randombytes(optrand, SPX_N); + /* Compute the digest randomization value. */ + gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); + + /* Derive the message digest and leaf index from R, PK and M. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; + + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); + + /* Sign the message hash using FORS. */ + fors_sign(sig, root, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); + sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; + + /* Update the indices for the next layer. */ + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; + } + + free_hash_function(&ctx); + + *siglen = SPX_BYTES; + + return 0; +} + +/** + * Verifies a detached signature and message under a given public key. + */ +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk) { + spx_ctx ctx; + const uint8_t *pub_root = pk + SPX_N; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t wots_pk[SPX_WOTS_BYTES]; + uint8_t root[SPX_N]; + uint8_t leaf[SPX_N]; + unsigned int i; + uint64_t tree; + uint32_t idx_leaf; + uint32_t wots_addr[8] = {0}; + uint32_t tree_addr[8] = {0}; + uint32_t wots_pk_addr[8] = {0}; + + if (siglen != SPX_BYTES) { + return -1; + } + + memcpy(ctx.pub_seed, pk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); + + /* Derive the message digest and leaf index from R || PK || M. */ + /* The additional SPX_N is a result of the hash domain separator. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; + + /* Layer correctly defaults to 0, so no need to set_layer_addr */ + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); + + fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + /* For each subtree.. */ + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + copy_keypair_addr(wots_pk_addr, wots_addr); + + /* The WOTS public key is only correct if the signature was correct. */ + /* Initially, root is the FORS pk, but on subsequent iterations it is + the root of the subtree below the currently processed subtree. */ + wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); + sig += SPX_WOTS_BYTES; + + /* Compute the leaf node using the WOTS public key. */ + thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); + + /* Compute the root node of this subtree. */ + compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, + &ctx, tree_addr); + sig += SPX_TREE_HEIGHT * SPX_N; + + /* Update the indices for the next layer. */ + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; + } + + // cleanup + free_hash_function(&ctx); + + /* Check if the root node equals the root node in the public key. */ + if (memcmp(root, pub_root, SPX_N) != 0) { + return -1; + } + + return 0; +} + + +/** + * Returns an array containing the signature followed by the message. + */ +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk) { + size_t siglen; + + crypto_sign_signature(sm, &siglen, m, mlen, sk); + + memmove(sm + SPX_BYTES, m, mlen); + *smlen = siglen + mlen; + + return 0; +} + +/** + * Verifies a given signature-message pair under a given public key. + */ +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk) { + /* The API caller does not necessarily know what size a signature should be + but SPHINCS+ signatures are always exactly SPX_BYTES. */ + if (smlen < SPX_BYTES) { + memset(m, 0, smlen); + *mlen = 0; + return -1; + } + + *mlen = smlen - SPX_BYTES; + + if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { + memset(m, 0, smlen); + *mlen = 0; + return -1; + } + + /* If verification was successful, move the message to the right place. */ + memmove(m, sm + SPX_BYTES, *mlen); + + return 0; +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/thash.h b/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/thash.h new file mode 100644 index 0000000000..8687ccfb4d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/thash.h @@ -0,0 +1,13 @@ +#ifndef SPX_THASH_H +#define SPX_THASH_H + +#include "context.h" +#include "params.h" + +#include + +#define thash SPX_NAMESPACE(thash) +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/thash_sha2_simple.c b/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/thash_sha2_simple.c new file mode 100644 index 0000000000..87badc4d53 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/thash_sha2_simple.c @@ -0,0 +1,53 @@ +#include +#include + +#include "thash.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "sha2.h" +#include "utils.h" + +static void thash_512(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]); + +/** + * Takes an array of inblocks concatenated arrays of SPX_N bytes. + */ +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]) { + if (inblocks > 1) { + thash_512(out, in, inblocks, ctx, addr); + return; + } + + unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES]; + sha256ctx sha2_state; + PQCLEAN_VLA(uint8_t, buf, SPX_SHA256_ADDR_BYTES + inblocks * SPX_N); + + /* Retrieve precomputed state containing pub_seed */ + sha256_inc_ctx_clone(&sha2_state, &ctx->state_seeded); + + memcpy(buf, addr, SPX_SHA256_ADDR_BYTES); + memcpy(buf + SPX_SHA256_ADDR_BYTES, in, inblocks * SPX_N); + + sha256_inc_finalize(outbuf, &sha2_state, buf, SPX_SHA256_ADDR_BYTES + inblocks * SPX_N); + memcpy(out, outbuf, SPX_N); +} + +static void thash_512(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]) { + unsigned char outbuf[SPX_SHA512_OUTPUT_BYTES]; + sha512ctx sha2_state; + PQCLEAN_VLA(uint8_t, buf, SPX_SHA256_ADDR_BYTES + inblocks * SPX_N); + + /* Retrieve precomputed state containing pub_seed */ + sha512_inc_ctx_clone(&sha2_state, &ctx->state_seeded_512); + + memcpy(buf, addr, SPX_SHA256_ADDR_BYTES); + memcpy(buf + SPX_SHA256_ADDR_BYTES, in, inblocks * SPX_N); + + sha512_inc_finalize(outbuf, &sha2_state, buf, SPX_SHA256_ADDR_BYTES + inblocks * SPX_N); + memcpy(out, outbuf, SPX_N); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/thash_sha2_simplex8.c b/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/thash_sha2_simplex8.c new file mode 100644 index 0000000000..9b946f4e4a --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/thash_sha2_simplex8.c @@ -0,0 +1,212 @@ +#include +#include + +#include "thashx8.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "sha2.h" +#include "sha256avx.h" +#include "sha256x8.h" +#include "utils.h" + +#include "sha512x4.h" + +static void thashx8_512( + unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, + unsigned int inblocks, + const spx_ctx *ctx, + uint32_t addrx8[8 * 8] +); + +/** + * 8-way parallel version of thash; takes 8x as much input and output + */ +void thashx8(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addrx8[8 * 8]) { + if (inblocks > 1) { + thashx8_512( + out0, out1, out2, out3, out4, out5, out6, out7, + in0, in1, in2, in3, in4, in5, in6, in7, + inblocks, ctx, addrx8); + return; + } + PQCLEAN_VLA(unsigned char, bufx8, 8 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)); + unsigned char outbufx8[8 * SPX_SHA256_OUTPUT_BYTES]; + unsigned int i; + + for (i = 0; i < 8; i++) { + memcpy(bufx8 + i * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + addrx8 + i * 8, SPX_SHA256_ADDR_BYTES); + } + + memcpy(bufx8 + SPX_SHA256_ADDR_BYTES + + 0 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), in0, inblocks * SPX_N); + memcpy(bufx8 + SPX_SHA256_ADDR_BYTES + + 1 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), in1, inblocks * SPX_N); + memcpy(bufx8 + SPX_SHA256_ADDR_BYTES + + 2 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), in2, inblocks * SPX_N); + memcpy(bufx8 + SPX_SHA256_ADDR_BYTES + + 3 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), in3, inblocks * SPX_N); + memcpy(bufx8 + SPX_SHA256_ADDR_BYTES + + 4 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), in4, inblocks * SPX_N); + memcpy(bufx8 + SPX_SHA256_ADDR_BYTES + + 5 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), in5, inblocks * SPX_N); + memcpy(bufx8 + SPX_SHA256_ADDR_BYTES + + 6 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), in6, inblocks * SPX_N); + memcpy(bufx8 + SPX_SHA256_ADDR_BYTES + + 7 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), in7, inblocks * SPX_N); + + sha256x8_seeded( + /* out */ + outbufx8 + 0 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 1 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 2 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 3 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 4 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 5 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 6 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 7 * SPX_SHA256_OUTPUT_BYTES, + + /* seed */ + &ctx->statex8_seeded, + + /* in */ + bufx8 + 0 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + 1 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + 2 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + 3 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + 4 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + 5 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + 6 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + 7 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N /* len */ + ); + + memcpy(out0, outbufx8 + 0 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out1, outbufx8 + 1 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out2, outbufx8 + 2 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out3, outbufx8 + 3 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out4, outbufx8 + 4 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out5, outbufx8 + 5 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out6, outbufx8 + 6 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out7, outbufx8 + 7 * SPX_SHA256_OUTPUT_BYTES, SPX_N); +} + +/** + * 2x4-way parallel version of thash; this is for the uses of thash that are + * based on SHA-512 + */ +static void thashx8_512( + unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, + unsigned int inblocks, + const spx_ctx *ctx, + uint32_t addrx8[8 * 8]) { + PQCLEAN_VLA(unsigned char, bufx8, 8 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)); + unsigned char outbuf[4 * SPX_SHA512_OUTPUT_BYTES]; + unsigned int i; + + for (i = 0; i < 8; i++) { + memcpy(bufx8 + i * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + addrx8 + i * 8, SPX_SHA256_ADDR_BYTES); + } + + memcpy(bufx8 + SPX_SHA256_ADDR_BYTES + + 0 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), in0, inblocks * SPX_N); + memcpy(bufx8 + SPX_SHA256_ADDR_BYTES + + 1 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), in1, inblocks * SPX_N); + memcpy(bufx8 + SPX_SHA256_ADDR_BYTES + + 2 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), in2, inblocks * SPX_N); + memcpy(bufx8 + SPX_SHA256_ADDR_BYTES + + 3 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), in3, inblocks * SPX_N); + memcpy(bufx8 + SPX_SHA256_ADDR_BYTES + + 4 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), in4, inblocks * SPX_N); + memcpy(bufx8 + SPX_SHA256_ADDR_BYTES + + 5 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), in5, inblocks * SPX_N); + memcpy(bufx8 + SPX_SHA256_ADDR_BYTES + + 6 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), in6, inblocks * SPX_N); + memcpy(bufx8 + SPX_SHA256_ADDR_BYTES + + 7 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), in7, inblocks * SPX_N); + + sha512x4_seeded( + outbuf + 0 * SPX_SHA512_OUTPUT_BYTES, + outbuf + 1 * SPX_SHA512_OUTPUT_BYTES, + outbuf + 2 * SPX_SHA512_OUTPUT_BYTES, + outbuf + 3 * SPX_SHA512_OUTPUT_BYTES, + &ctx->statex4_seeded_512, /* seed */ + bufx8 + 0 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), /* in */ + bufx8 + 1 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + 2 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + 3 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N /* len */ + ); + + memcpy(out0, outbuf + 0 * SPX_SHA512_OUTPUT_BYTES, SPX_N); + memcpy(out1, outbuf + 1 * SPX_SHA512_OUTPUT_BYTES, SPX_N); + memcpy(out2, outbuf + 2 * SPX_SHA512_OUTPUT_BYTES, SPX_N); + memcpy(out3, outbuf + 3 * SPX_SHA512_OUTPUT_BYTES, SPX_N); + + sha512x4_seeded( + outbuf + 0 * SPX_SHA512_OUTPUT_BYTES, + outbuf + 1 * SPX_SHA512_OUTPUT_BYTES, + outbuf + 2 * SPX_SHA512_OUTPUT_BYTES, + outbuf + 3 * SPX_SHA512_OUTPUT_BYTES, + &ctx->statex4_seeded_512, /* seed */ + bufx8 + 4 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), /* in */ + bufx8 + 5 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + 6 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + 7 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N /* len */ + ); + + memcpy(out4, outbuf + 0 * SPX_SHA512_OUTPUT_BYTES, SPX_N); + memcpy(out5, outbuf + 1 * SPX_SHA512_OUTPUT_BYTES, SPX_N); + memcpy(out6, outbuf + 2 * SPX_SHA512_OUTPUT_BYTES, SPX_N); + memcpy(out7, outbuf + 3 * SPX_SHA512_OUTPUT_BYTES, SPX_N); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/thashx8.h b/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/thashx8.h new file mode 100644 index 0000000000..c02fe9cf3e --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/thashx8.h @@ -0,0 +1,28 @@ +#ifndef SPX_THASHX8_H +#define SPX_THASHX8_H + +#include + +#include "context.h" +#include "params.h" + +#define thashx8 SPX_NAMESPACE(thashx8) +void thashx8(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addrx8[8 * 8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/utils.c b/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/utils.c new file mode 100644 index 0000000000..177b541fb9 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/utils.c @@ -0,0 +1,148 @@ +#include + +#include "utils.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "thash.h" + +/** + * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. + */ +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in) { + int i; + + /* Iterate over out in decreasing order, for big-endianness. */ + for (i = (signed int)outlen - 1; i >= 0; i--) { + out[i] = in & 0xff; + in = in >> 8; + } +} + +void u32_to_bytes(unsigned char *out, uint32_t in) { + out[0] = (unsigned char)(in >> 24); + out[1] = (unsigned char)(in >> 16); + out[2] = (unsigned char)(in >> 8); + out[3] = (unsigned char)in; +} + +/** + * Converts the inlen bytes in 'in' from big-endian byte order to an integer. + */ +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { + unsigned long long retval = 0; + unsigned int i; + + for (i = 0; i < inlen; i++) { + retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); + } + return retval; +} + +/** + * Computes a root node given a leaf and an auth path. + * Expects address to be complete other than the tree_height and tree_index. + */ +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]) { + uint32_t i; + unsigned char buffer[2 * SPX_N]; + + /* If leaf_idx is odd (last bit = 1), current path element is a right child + and auth_path has to go left. Otherwise it is the other way around. */ + if (leaf_idx & 1) { + memcpy(buffer + SPX_N, leaf, SPX_N); + memcpy(buffer, auth_path, SPX_N); + } else { + memcpy(buffer, leaf, SPX_N); + memcpy(buffer + SPX_N, auth_path, SPX_N); + } + auth_path += SPX_N; + + for (i = 0; i < tree_height - 1; i++) { + leaf_idx >>= 1; + idx_offset >>= 1; + /* Set the address of the node we're creating. */ + set_tree_height(addr, i + 1); + set_tree_index(addr, leaf_idx + idx_offset); + + /* Pick the right or left neighbor, depending on parity of the node. */ + if (leaf_idx & 1) { + thash(buffer + SPX_N, buffer, 2, ctx, addr); + memcpy(buffer, auth_path, SPX_N); + } else { + thash(buffer, buffer, 2, ctx, addr); + memcpy(buffer + SPX_N, auth_path, SPX_N); + } + auth_path += SPX_N; + } + + /* The last iteration is exceptional; we do not copy an auth_path node. */ + leaf_idx >>= 1; + idx_offset >>= 1; + set_tree_height(addr, tree_height); + set_tree_index(addr, leaf_idx + idx_offset); + thash(root, buffer, 2, ctx, addr); +} + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx * /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]) { + PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); + PQCLEAN_VLA(unsigned int, heights, tree_height + 1); + unsigned int offset = 0; + uint32_t idx; + uint32_t tree_idx; + + for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { + /* Add the next leaf node to the stack. */ + gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); + offset++; + heights[offset - 1] = 0; + + /* If this is a node we need for the auth path.. */ + if ((leaf_idx ^ 0x1) == idx) { + memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); + } + + /* While the top-most nodes are of equal height.. */ + while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { + /* Compute index of the new node, in the next layer. */ + tree_idx = (idx >> (heights[offset - 1] + 1)); + + /* Set the address of the node we're creating. */ + set_tree_height(tree_addr, heights[offset - 1] + 1); + set_tree_index(tree_addr, + tree_idx + (idx_offset >> (heights[offset - 1] + 1))); + /* Hash the top-most nodes from the stack together. */ + thash(stack + (offset - 2)*SPX_N, + stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); + offset--; + /* Note that the top-most node is now one layer higher. */ + heights[offset - 1]++; + + /* If this is a node we need for the auth path.. */ + if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { + memcpy(auth_path + heights[offset - 1]*SPX_N, + stack + (offset - 1)*SPX_N, SPX_N); + } + } + } + memcpy(root, stack, SPX_N); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/utils.h b/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/utils.h new file mode 100644 index 0000000000..64f5d5a53a --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/utils.h @@ -0,0 +1,58 @@ +#ifndef SPX_UTILS_H +#define SPX_UTILS_H + +#include + +#include "compat.h" +#include "context.h" +#include "params.h" + + +/* To support MSVC use alloca() instead of VLAs. See #20. */ + + +/** + * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. + */ +#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in); +#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) +void u32_to_bytes(unsigned char *out, uint32_t in); + +/** + * Converts the inlen bytes in 'in' from big-endian byte order to an integer. + */ +#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); + +/** + * Computes a root node given a leaf and an auth path. + * Expects address to be complete other than the tree_height and tree_index. + */ +#define compute_root SPX_NAMESPACE(compute_root) +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]); + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +#define treehash SPX_NAMESPACE(treehash) +void treehash(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx *ctx /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]); + + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/utilsx8.c b/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/utilsx8.c new file mode 100644 index 0000000000..f044b9595d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/utilsx8.c @@ -0,0 +1,146 @@ +#include + +#include "utils.h" +#include "utilsx8.h" + +#include "address.h" +#include "params.h" +#include "thashx8.h" + +/* + * Generate the entire Merkle tree, computing the authentication path for leaf_idx, + * and the resulting root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) + * + * This expects tree_addrx8 to be initialized to 8 parallel addr structures for + * the Merkle tree nodes + * + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + * + * This works by using the standard Merkle tree building algorithm, except + * that each 'node' tracked is actually 8 consecutive nodes in the real tree. + * When we combine two logical nodes ABCDEFGH and STUVWXYZ, we perform the H + * operation on adjacent real nodes, forming the parent logical node + * (AB)(CD)(EF)(GH)(ST)(UV)(WX)(YZ) + * + * When we get to the top three levels of the real tree (where there is only + * one logical node), we continue this operation three more times; the right + * most real node will by the actual root (and the other 7 nodes will be + * garbage). We follow the same thashx8 logic so that the 'extract + * authentication path components' part of the loop is still executed (and + * to simplify the code somewhat) + * + * This currently assumes tree_height >= 3; I suspect that doing an adjusting + * idx, addr_idx on the gen_leafx8 call if tree_height < 3 would fix it; since + * we don't actually use such short trees, I haven't bothered + */ +void treehashx8(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, + uint32_t tree_height, + void (*gen_leafx8)( + unsigned char * /* Where to write the leaves */, + const spx_ctx *, + uint32_t idx, void *info), + uint32_t tree_addrx8[8 * 8], + void *info) { + /* This is where we keep the intermediate nodes */ + PQCLEAN_VLA(unsigned char, stackx8, tree_height * 8 * SPX_N); + uint32_t left_adj = 0, prev_left_adj = 0; /* When we're doing the top 3 */ + /* levels, the left-most part of the tree isn't at the beginning */ + /* of current[]. These give the offset of the actual start */ + + uint32_t idx; + uint32_t max_idx = ((uint32_t)1 << (tree_height - 3)) - 1; + for (idx = 0;; idx++) { + unsigned char current[8 * SPX_N]; /* Current logical node */ + gen_leafx8( current, ctx, 8 * idx + idx_offset, + info ); + + /* Now combine the freshly generated right node with previously */ + /* generated left ones */ + uint32_t internal_idx_offset = idx_offset; + uint32_t internal_idx = idx; + uint32_t internal_leaf = leaf_idx; + uint32_t h; /* The height we are in the Merkle tree */ + for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { + + /* Special processing if we're at the top of the tree */ + if (h >= tree_height - 3) { + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[7 * SPX_N], SPX_N ); + return; + } + /* The tree indexing logic is a bit off in this case */ + /* Adjust it so that the left-most node of the part of */ + /* the tree that we're processing has index 0 */ + prev_left_adj = left_adj; + left_adj = (uint32_t)(8 - (1 << (tree_height - h - 1))); + } + + /* Check if we hit the top of the tree */ + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[7 * SPX_N], SPX_N ); + return; + } + + /* + * Check if one of the nodes we have is a part of the + * authentication path; if it is, write it out + */ + if ((((internal_idx << 3) ^ internal_leaf) & ~0x7U) == 0) { + memcpy( &auth_path[ h * SPX_N ], + ¤t[(((internal_leaf & 7) ^ 1) + prev_left_adj) * SPX_N], + SPX_N ); + } + + /* + * Check if we're at a left child; if so, stop going up the stack + * Exception: if we've reached the end of the tree, keep on going + * (so we combine the last 8 nodes into the one root node in three + * more iterations) + */ + if ((internal_idx & 1) == 0 && idx < max_idx) { + break; + } + + /* Ok, we're at a right node (or doing the top 3 levels) */ + /* Now combine the left and right logical nodes together */ + + /* Set the address of the node we're creating. */ + uint32_t j; + internal_idx_offset >>= 1; + for (j = 0; j < 8; j++) { + set_tree_height(tree_addrx8 + j * 8, h + 1); + set_tree_index(tree_addrx8 + j * 8, + (8 / 2) * (internal_idx & ~1U) + j - left_adj + internal_idx_offset ); + } + unsigned char *left = &stackx8[h * 8 * SPX_N]; + thashx8( ¤t[0 * SPX_N], + ¤t[1 * SPX_N], + ¤t[2 * SPX_N], + ¤t[3 * SPX_N], + ¤t[4 * SPX_N], + ¤t[5 * SPX_N], + ¤t[6 * SPX_N], + ¤t[7 * SPX_N], + &left [0 * SPX_N], + &left [2 * SPX_N], + &left [4 * SPX_N], + &left [6 * SPX_N], + ¤t[0 * SPX_N], + ¤t[2 * SPX_N], + ¤t[4 * SPX_N], + ¤t[6 * SPX_N], + 2, ctx, tree_addrx8); + } + + /* We've hit a left child; save the current for when we get the */ + /* corresponding right right */ + memcpy( &stackx8[h * 8 * SPX_N], current, 8 * SPX_N); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/utilsx8.h b/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/utilsx8.h new file mode 100644 index 0000000000..806d1e85be --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/utilsx8.h @@ -0,0 +1,29 @@ +#ifndef SPX_UTILSX8_H +#define SPX_UTILSX8_H + +#include + +#include "params.h" + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + * + * This implementation uses AVX to compute internal nodes 8 at a time (in + * parallel) + */ +#define treehashx8 SPX_NAMESPACE(treehashx8) +void treehashx8(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leafx8)( + unsigned char * /* Where to write the leaves */, + const spx_ctx * /* ctx */, + uint32_t addr_idx, void *info), + uint32_t tree_addrx8[8 * 8], void *info); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/wots.c b/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/wots.c new file mode 100644 index 0000000000..689baf4db9 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/wots.c @@ -0,0 +1,291 @@ +#include +#include + +#include "wots.h" + +#include "address.h" +#include "hash.h" +#include "hashx8.h" +#include "params.h" +#include "thash.h" +#include "thashx8.h" +#include "utils.h" +#include "utilsx8.h" +#include "wotsx8.h" + +// TODO clarify address expectations, and make them more uniform. +// TODO i.e. do we expect types to be set already? +// TODO and do we expect modifications or copies? + +/** + * Computes up the chains + */ +static void gen_chains( + unsigned char *out, + const unsigned char *in, + unsigned int start[SPX_WOTS_LEN], + const unsigned int steps[SPX_WOTS_LEN], + const spx_ctx *ctx, + uint32_t addr[8]) { + uint32_t i, j, k, idx, watching; + int done; + unsigned char empty[SPX_N]; + unsigned char *bufs[8]; + uint32_t addrs[8 * 8]; + + int l; + uint16_t counts[SPX_WOTS_W] = { 0 }; + uint16_t idxs[SPX_WOTS_LEN]; + uint16_t total, newTotal; + + /* set addrs = {addr, addr, ..., addr} */ + for (j = 0; j < 8; j++) { + memcpy(addrs + j * 8, addr, sizeof(uint32_t) * 8); + } + + /* Initialize out with the value at position 'start'. */ + memcpy(out, in, SPX_WOTS_LEN * SPX_N); + + /* Sort the chains in reverse order by steps using counting sort. */ + for (i = 0; i < SPX_WOTS_LEN; i++) { + counts[steps[i]]++; + } + total = 0; + for (l = SPX_WOTS_W - 1; l >= 0; l--) { + newTotal = counts[l] + total; + counts[l] = total; + total = newTotal; + } + for (i = 0; i < SPX_WOTS_LEN; i++) { + idxs[counts[steps[i]]] = (uint16_t)i; + counts[steps[i]]++; + } + + /* We got our work cut out for us: do it! */ + for (i = 0; i < SPX_WOTS_LEN; i += 8) { + for (j = 0; j < 8 && i + j < SPX_WOTS_LEN; j++) { + idx = idxs[i + j]; + set_chain_addr(addrs + j * 8, idx); + bufs[j] = out + SPX_N * idx; + } + + /* As the chains are sorted in reverse order, we know that the first + * chain is the longest and the last one is the shortest. We keep + * an eye on whether the last chain is done and then on the one before, + * et cetera. */ + watching = 7; + done = 0; + while (i + watching >= SPX_WOTS_LEN) { + bufs[watching] = &empty[0]; + watching--; + } + + for (k = 0;; k++) { + while (k == steps[idxs[i + watching]]) { + bufs[watching] = &empty[0]; + if (watching == 0) { + done = 1; + break; + } + watching--; + } + if (done) { + break; + } + for (j = 0; j < watching + 1; j++) { + set_hash_addr(addrs + j * 8, k + start[idxs[i + j]]); + } + + thashx8(bufs[0], bufs[1], bufs[2], bufs[3], + bufs[4], bufs[5], bufs[6], bufs[7], + bufs[0], bufs[1], bufs[2], bufs[3], + bufs[4], bufs[5], bufs[6], bufs[7], 1, ctx, addrs); + } + } +} + +/** + * base_w algorithm as described in draft. + * Interprets an array of bytes as integers in base w. + * This only works when log_w is a divisor of 8. + */ +static void base_w(unsigned int *output, const int out_len, + const unsigned char *input) { + int in = 0; + int out = 0; + unsigned char total = 0; + int bits = 0; + int consumed; + + for (consumed = 0; consumed < out_len; consumed++) { + if (bits == 0) { + total = input[in]; + in++; + bits += 8; + } + bits -= SPX_WOTS_LOGW; + output[out] = (total >> bits) & (SPX_WOTS_W - 1); + out++; + } +} + +/* Computes the WOTS+ checksum over a message (in base_w). */ +static void wots_checksum(unsigned int *csum_base_w, + const unsigned int *msg_base_w) { + unsigned int csum = 0; + unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; + unsigned int i; + + /* Compute checksum. */ + for (i = 0; i < SPX_WOTS_LEN1; i++) { + csum += SPX_WOTS_W - 1 - msg_base_w[i]; + } + + /* Convert checksum to base_w. */ + /* Make sure expected empty zero bits are the least significant bits. */ + csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); + ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); + base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); +} + +/* Takes a message and derives the matching chain lengths. */ +void chain_lengths(unsigned int *lengths, const unsigned char *msg) { + base_w(lengths, SPX_WOTS_LEN1, msg); + wots_checksum(lengths + SPX_WOTS_LEN1, lengths); +} + +/** + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. + * + * Writes the computed public key to 'pk'. + */ +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]) { + unsigned int steps[SPX_WOTS_LEN]; + unsigned int start[SPX_WOTS_LEN]; + uint32_t i; + + chain_lengths(start, msg); + + for (i = 0; i < SPX_WOTS_LEN; i++) { + steps[i] = SPX_WOTS_W - 1 - start[i]; + } + + gen_chains(pk, sig, start, steps, ctx, addr); +} + +/* + * This generates 8 sequential WOTS public keys + * It also generates the WOTS signature if leaf_info indicates + * that we're signing with one of these WOTS keys + */ +void wots_gen_leafx8(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info) { + struct leaf_info_x8 *info = v_info; + uint32_t *leaf_addr = info->leaf_addr; + uint32_t *pk_addr = info->pk_addr; + unsigned int i, j, k; + unsigned char pk_buffer[ 8 * SPX_WOTS_BYTES ]; + unsigned wots_offset = SPX_WOTS_BYTES; + unsigned char *buffer; + uint32_t wots_k_mask; + unsigned wots_sign_index; + + if (((leaf_idx ^ info->wots_sign_leaf) & ~7U) == 0) { + /* We're traversing the leaf that's signing; generate the WOTS */ + /* signature */ + wots_k_mask = 0; + wots_sign_index = info->wots_sign_leaf & 7; /* Which of of the 8 */ + /* slots do the signatures come from */ + } else { + /* Nope, we're just generating pk's; turn off the signature logic */ + wots_k_mask = ~0U; + wots_sign_index = 0; + } + + for (j = 0; j < 8; j++) { + set_keypair_addr( leaf_addr + j * 8, leaf_idx + j ); + set_keypair_addr( pk_addr + j * 8, leaf_idx + j ); + } + + for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { + uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k */ + /* to the step if we're generating a signature, ~0 if we're not */ + + /* Start with the secret seed */ + for (j = 0; j < 8; j++) { + set_chain_addr(leaf_addr + j * 8, i); + set_hash_addr(leaf_addr + j * 8, 0); + set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTSPRF); + } + prf_addrx8(buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + buffer + 2 * wots_offset, + buffer + 3 * wots_offset, + buffer + 4 * wots_offset, + buffer + 5 * wots_offset, + buffer + 6 * wots_offset, + buffer + 7 * wots_offset, + ctx, leaf_addr); + + for (j = 0; j < 8; j++) { + set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTS); + } + + /* Iterate down the WOTS chain */ + for (k = 0;; k++) { + /* Check if one of the values we have needs to be saved as a */ + /* part of the WOTS signature */ + if (k == wots_k) { + memcpy( info->wots_sig + i * SPX_N, + buffer + wots_sign_index * wots_offset, SPX_N ); + } + + /* Check if we hit the top of the chain */ + if (k == SPX_WOTS_W - 1) { + break; + } + + /* Iterate one step on all 8 chains */ + for (j = 0; j < 8; j++) { + set_hash_addr(leaf_addr + j * 8, k); + } + thashx8(buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + buffer + 2 * wots_offset, + buffer + 3 * wots_offset, + buffer + 4 * wots_offset, + buffer + 5 * wots_offset, + buffer + 6 * wots_offset, + buffer + 7 * wots_offset, + buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + buffer + 2 * wots_offset, + buffer + 3 * wots_offset, + buffer + 4 * wots_offset, + buffer + 5 * wots_offset, + buffer + 6 * wots_offset, + buffer + 7 * wots_offset, 1, ctx, leaf_addr); + } + } + + /* Do the final thash to generate the public keys */ + thashx8(dest + 0 * SPX_N, + dest + 1 * SPX_N, + dest + 2 * SPX_N, + dest + 3 * SPX_N, + dest + 4 * SPX_N, + dest + 5 * SPX_N, + dest + 6 * SPX_N, + dest + 7 * SPX_N, + pk_buffer + 0 * wots_offset, + pk_buffer + 1 * wots_offset, + pk_buffer + 2 * wots_offset, + pk_buffer + 3 * wots_offset, + pk_buffer + 4 * wots_offset, + pk_buffer + 5 * wots_offset, + pk_buffer + 6 * wots_offset, + pk_buffer + 7 * wots_offset, SPX_WOTS_LEN, ctx, pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/wots.h b/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/wots.h new file mode 100644 index 0000000000..4e7692eeef --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/wots.h @@ -0,0 +1,25 @@ +#ifndef SPX_WOTS_H +#define SPX_WOTS_H + +#include + +#include "context.h" +#include "params.h" + +/** + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. + * + * Writes the computed public key to 'pk'. + */ +#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]); + +/* + * Compute the chain lengths needed for a given message hash + */ +#define chain_lengths SPX_NAMESPACE(chain_lengths) +void chain_lengths(unsigned int *lengths, const unsigned char *msg); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/wotsx8.h b/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/wotsx8.h new file mode 100644 index 0000000000..10866efb35 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_avx2/wotsx8.h @@ -0,0 +1,42 @@ +#ifndef WOTSX8_H_ +#define WOTSX8_H_ + +#include + +#include "context.h" +#include "params.h" + +/* + * This is here to provide an interface to the internal wots_gen_leafx8 + * routine. While this routine is not referenced in the package outside of + * wots.c, it is called from the stand-alone benchmark code to characterize + * the performance + */ +struct leaf_info_x8 { + unsigned char *wots_sig; + uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ + uint32_t *wots_steps; + uint32_t leaf_addr[8 * 8]; + uint32_t pk_addr[8 * 8]; +}; + +/* Macro to set the leaf_info to something 'benign', that is, it would */ +/* run with the same time as it does during the real signing process */ +/* Used only by the benchmark code */ +#define INITIALIZE_LEAF_INFO_X8(info, addr, step_buffer) { \ + (info).wots_sig = 0; \ + (info).wots_sign_leaf = ~0; \ + (info).wots_steps = step_buffer; \ + int i; \ + for (i=0; i<8; i++) { \ + memcpy( &(info).leaf_addr[8*i], addr, 32 ); \ + memcpy( &(info).pk_addr[8*i], addr, 32 ); \ + } \ + } + +#define wots_gen_leafx8 SPX_NAMESPACE(wots_gen_leafx8) +void wots_gen_leafx8(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info); + +#endif /* WOTSX8_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_clean/LICENSE b/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_clean/LICENSE new file mode 100644 index 0000000000..670154e353 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_clean/LICENSE @@ -0,0 +1,116 @@ +CC0 1.0 Universal + +Statement of Purpose + +The laws of most jurisdictions throughout the world automatically confer +exclusive Copyright and Related Rights (defined below) upon the creator and +subsequent owner(s) (each and all, an "owner") of an original work of +authorship and/or a database (each, a "Work"). + +Certain owners wish to permanently relinquish those rights to a Work for the +purpose of contributing to a commons of creative, cultural and scientific +works ("Commons") that the public can reliably and without fear of later +claims of infringement build upon, modify, incorporate in other works, reuse +and redistribute as freely as possible in any form whatsoever and for any +purposes, including without limitation commercial purposes. These owners may +contribute to the Commons to promote the ideal of a free culture and the +further production of creative, cultural and scientific works, or to gain +reputation or greater distribution for their Work in part through the use and +efforts of others. + +For these and/or other purposes and motivations, and without any expectation +of additional consideration or compensation, the person associating CC0 with a +Work (the "Affirmer"), to the extent that he or she is an owner of Copyright +and Related Rights in the Work, voluntarily elects to apply CC0 to the Work +and publicly distribute the Work under its terms, with knowledge of his or her +Copyright and Related Rights in the Work and the meaning and intended legal +effect of CC0 on those rights. + +1. Copyright and Related Rights. A Work made available under CC0 may be +protected by copyright and related or neighboring rights ("Copyright and +Related Rights"). Copyright and Related Rights include, but are not limited +to, the following: + + i. the right to reproduce, adapt, distribute, perform, display, communicate, + and translate a Work; + + ii. moral rights retained by the original author(s) and/or performer(s); + + iii. publicity and privacy rights pertaining to a person's image or likeness + depicted in a Work; + + iv. rights protecting against unfair competition in regards to a Work, + subject to the limitations in paragraph 4(a), below; + + v. rights protecting the extraction, dissemination, use and reuse of data in + a Work; + + vi. database rights (such as those arising under Directive 96/9/EC of the + European Parliament and of the Council of 11 March 1996 on the legal + protection of databases, and under any national implementation thereof, + including any amended or successor version of such directive); and + + vii. other similar, equivalent or corresponding rights throughout the world + based on applicable law or treaty, and any national implementations thereof. + +2. Waiver. To the greatest extent permitted by, but not in contravention of, +applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and +unconditionally waives, abandons, and surrenders all of Affirmer's Copyright +and Related Rights and associated claims and causes of action, whether now +known or unknown (including existing as well as future claims and causes of +action), in the Work (i) in all territories worldwide, (ii) for the maximum +duration provided by applicable law or treaty (including future time +extensions), (iii) in any current or future medium and for any number of +copies, and (iv) for any purpose whatsoever, including without limitation +commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes +the Waiver for the benefit of each member of the public at large and to the +detriment of Affirmer's heirs and successors, fully intending that such Waiver +shall not be subject to revocation, rescission, cancellation, termination, or +any other legal or equitable action to disrupt the quiet enjoyment of the Work +by the public as contemplated by Affirmer's express Statement of Purpose. + +3. Public License Fallback. Should any part of the Waiver for any reason be +judged legally invalid or ineffective under applicable law, then the Waiver +shall be preserved to the maximum extent permitted taking into account +Affirmer's express Statement of Purpose. In addition, to the extent the Waiver +is so judged Affirmer hereby grants to each affected person a royalty-free, +non transferable, non sublicensable, non exclusive, irrevocable and +unconditional license to exercise Affirmer's Copyright and Related Rights in +the Work (i) in all territories worldwide, (ii) for the maximum duration +provided by applicable law or treaty (including future time extensions), (iii) +in any current or future medium and for any number of copies, and (iv) for any +purpose whatsoever, including without limitation commercial, advertising or +promotional purposes (the "License"). The License shall be deemed effective as +of the date CC0 was applied by Affirmer to the Work. Should any part of the +License for any reason be judged legally invalid or ineffective under +applicable law, such partial invalidity or ineffectiveness shall not +invalidate the remainder of the License, and in such case Affirmer hereby +affirms that he or she will not (i) exercise any of his or her remaining +Copyright and Related Rights in the Work or (ii) assert any associated claims +and causes of action with respect to the Work, in either case contrary to +Affirmer's express Statement of Purpose. + +4. Limitations and Disclaimers. + + a. No trademark or patent rights held by Affirmer are waived, abandoned, + surrendered, licensed or otherwise affected by this document. + + b. Affirmer offers the Work as-is and makes no representations or warranties + of any kind concerning the Work, express, implied, statutory or otherwise, + including without limitation warranties of title, merchantability, fitness + for a particular purpose, non infringement, or the absence of latent or + other defects, accuracy, or the present or absence of errors, whether or not + discoverable, all to the greatest extent permissible under applicable law. + + c. Affirmer disclaims responsibility for clearing rights of other persons + that may apply to the Work or any use thereof, including without limitation + any person's Copyright and Related Rights in the Work. Further, Affirmer + disclaims responsibility for obtaining any necessary consents, permissions + or other rights required for any use of the Work. + + d. Affirmer understands and acknowledges that Creative Commons is not a + party to this document and has no duty or obligation with respect to this + CC0 or use of the Work. + +For more information, please see + diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_clean/address.c b/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_clean/address.c new file mode 100644 index 0000000000..b956e9cb29 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_clean/address.c @@ -0,0 +1,91 @@ +#include +#include + +#include "address.h" +#include "params.h" +#include "utils.h" + +/* + * Specify which level of Merkle tree (the "layer") we're working on + */ +void set_layer_addr(uint32_t addr[8], uint32_t layer) { + ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; +} + +/* + * Specify which Merkle tree within the level (the "tree address") we're working on + */ +void set_tree_addr(uint32_t addr[8], uint64_t tree) { + ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); +} + +/* + * Specify the reason we'll use this address structure for, that is, what + * hash will we compute with it. This is used so that unrelated types of + * hashes don't accidentally get the same address structure. The type will be + * one of the SPX_ADDR_TYPE constants + */ +void set_type(uint32_t addr[8], uint32_t type) { + ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; +} + +/* + * Copy the layer and tree fields of the address structure. This is used + * when we're doing multiple types of hashes within the same Merkle tree + */ +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); +} + +/* These functions are used for OTS addresses. */ + +/* + * Specify which Merkle leaf we're working on; that is, which OTS keypair + * we're talking about. + */ +void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { + ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; +} + +/* + * Copy the layer, tree and keypair fields of the address structure. This is + * used when we're doing multiple things within the same OTS keypair + */ +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); + ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; +} + +/* + * Specify which Merkle chain within the OTS we're working with + * (the chain address) + */ +void set_chain_addr(uint32_t addr[8], uint32_t chain) { + ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; +} + +/* + * Specify where in the Merkle chain we are +* (the hash address) + */ +void set_hash_addr(uint32_t addr[8], uint32_t hash) { + ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; +} + +/* These functions are used for all hash tree addresses (including FORS). */ + +/* + * Specify the height of the node in the Merkle/FORS tree we are in + * (the tree height) + */ +void set_tree_height(uint32_t addr[8], uint32_t tree_height) { + ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; +} + +/* + * Specify the distance from the left edge of the node in the Merkle/FORS tree + * (the tree index) + */ +void set_tree_index(uint32_t addr[8], uint32_t tree_index) { + u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_clean/address.h b/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_clean/address.h new file mode 100644 index 0000000000..24a84eb40c --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_clean/address.h @@ -0,0 +1,52 @@ +#ifndef SPX_ADDRESS_H +#define SPX_ADDRESS_H + +#include + +#include "params.h" + +/* The hash types that are passed to set_type */ +#define SPX_ADDR_TYPE_WOTS 0 +#define SPX_ADDR_TYPE_WOTSPK 1 +#define SPX_ADDR_TYPE_HASHTREE 2 +#define SPX_ADDR_TYPE_FORSTREE 3 +#define SPX_ADDR_TYPE_FORSPK 4 +#define SPX_ADDR_TYPE_WOTSPRF 5 +#define SPX_ADDR_TYPE_FORSPRF 6 + +#define set_layer_addr SPX_NAMESPACE(set_layer_addr) +void set_layer_addr(uint32_t addr[8], uint32_t layer); + +#define set_tree_addr SPX_NAMESPACE(set_tree_addr) +void set_tree_addr(uint32_t addr[8], uint64_t tree); + +#define set_type SPX_NAMESPACE(set_type) +void set_type(uint32_t addr[8], uint32_t type); + +/* Copies the layer and tree part of one address into the other */ +#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); + +/* These functions are used for WOTS and FORS addresses. */ + +#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) +void set_keypair_addr(uint32_t addr[8], uint32_t keypair); + +#define set_chain_addr SPX_NAMESPACE(set_chain_addr) +void set_chain_addr(uint32_t addr[8], uint32_t chain); + +#define set_hash_addr SPX_NAMESPACE(set_hash_addr) +void set_hash_addr(uint32_t addr[8], uint32_t hash); + +#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); + +/* These functions are used for all hash tree addresses (including FORS). */ + +#define set_tree_height SPX_NAMESPACE(set_tree_height) +void set_tree_height(uint32_t addr[8], uint32_t tree_height); + +#define set_tree_index SPX_NAMESPACE(set_tree_index) +void set_tree_index(uint32_t addr[8], uint32_t tree_index); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_clean/api.h b/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_clean/api.h new file mode 100644 index 0000000000..7504eaebd6 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_clean/api.h @@ -0,0 +1,77 @@ +#ifndef PQCLEAN_SPHINCSSHA2256FSIMPLE_CLEAN_API_H +#define PQCLEAN_SPHINCSSHA2256FSIMPLE_CLEAN_API_H + +#include +#include + +#define PQCLEAN_SPHINCSSHA2256FSIMPLE_CLEAN_CRYPTO_ALGNAME "SPHINCS+-sha2-256f-simple" + +#define PQCLEAN_SPHINCSSHA2256FSIMPLE_CLEAN_CRYPTO_SECRETKEYBYTES 128 +#define PQCLEAN_SPHINCSSHA2256FSIMPLE_CLEAN_CRYPTO_PUBLICKEYBYTES 64 +#define PQCLEAN_SPHINCSSHA2256FSIMPLE_CLEAN_CRYPTO_BYTES 49856 + +#define PQCLEAN_SPHINCSSHA2256FSIMPLE_CLEAN_CRYPTO_SEEDBYTES 96 + +/* + * Returns the length of a secret key, in bytes + */ +size_t PQCLEAN_SPHINCSSHA2256FSIMPLE_CLEAN_crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +size_t PQCLEAN_SPHINCSSHA2256FSIMPLE_CLEAN_crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +size_t PQCLEAN_SPHINCSSHA2256FSIMPLE_CLEAN_crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +size_t PQCLEAN_SPHINCSSHA2256FSIMPLE_CLEAN_crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +int PQCLEAN_SPHINCSSHA2256FSIMPLE_CLEAN_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +int PQCLEAN_SPHINCSSHA2256FSIMPLE_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +int PQCLEAN_SPHINCSSHA2256FSIMPLE_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +int PQCLEAN_SPHINCSSHA2256FSIMPLE_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, + const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +int PQCLEAN_SPHINCSSHA2256FSIMPLE_CLEAN_crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +int PQCLEAN_SPHINCSSHA2256FSIMPLE_CLEAN_crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_clean/context.h b/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_clean/context.h new file mode 100644 index 0000000000..97e2e2469e --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_clean/context.h @@ -0,0 +1,28 @@ +#ifndef SPX_CONTEXT_H +#define SPX_CONTEXT_H + +#include +#include + +#include "params.h" +#include "sha2.h" + +typedef struct { + uint8_t pub_seed[SPX_N]; + uint8_t sk_seed[SPX_N]; + + // sha256 state that absorbed pub_seed + sha256ctx state_seeded; + + // sha512 state that absorbed pub_seed + sha512ctx state_seeded_512; + +} spx_ctx; + +#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) +void initialize_hash_function(spx_ctx *ctx); + +#define free_hash_function SPX_NAMESPACE(free_hash_function) +void free_hash_function(spx_ctx *ctx); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_clean/context_sha2.c b/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_clean/context_sha2.c new file mode 100644 index 0000000000..9ca9f4e7ac --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_clean/context_sha2.c @@ -0,0 +1,36 @@ +#include "context.h" + +/** + * Absorb the constant pub_seed using one round of the compression function + * This initializes state_seeded and state_seeded_512, which can then be + * reused in thash + **/ +static void seed_state(spx_ctx *ctx) { + uint8_t block[SPX_SHA512_BLOCK_BYTES]; + size_t i; + + for (i = 0; i < SPX_N; ++i) { + block[i] = ctx->pub_seed[i]; + } + for (i = SPX_N; i < SPX_SHA512_BLOCK_BYTES; ++i) { + block[i] = 0; + } + /* block has been properly initialized for both SHA-256 and SHA-512 */ + + sha256_inc_init(&ctx->state_seeded); + sha256_inc_blocks(&ctx->state_seeded, block, 1); + sha512_inc_init(&ctx->state_seeded_512); + sha512_inc_blocks(&ctx->state_seeded_512, block, 1); +} + + +/* We initialize the state for the hash functions */ +void initialize_hash_function(spx_ctx *ctx) { + seed_state(ctx); +} + +/* Free the incremental hashing context for heap-based SHA2 APIs */ +void free_hash_function(spx_ctx *ctx) { + sha256_inc_ctx_release(&ctx->state_seeded); + sha512_inc_ctx_release(&ctx->state_seeded_512); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_clean/fors.c b/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_clean/fors.c new file mode 100644 index 0000000000..96ca72e986 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_clean/fors.c @@ -0,0 +1,156 @@ +#include +#include +#include + +#include "fors.h" + +#include "address.h" +#include "hash.h" +#include "thash.h" +#include "utils.h" +#include "utilsx1.h" + +static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + prf_addr(sk, ctx, fors_leaf_addr); +} + +static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, + const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + thash(leaf, sk, 1, ctx, fors_leaf_addr); +} + +struct fors_gen_leaf_info { + uint32_t leaf_addrx[8]; +}; + +static void fors_gen_leafx1(unsigned char *leaf, + const spx_ctx *ctx, + uint32_t addr_idx, void *info) { + struct fors_gen_leaf_info *fors_info = info; + uint32_t *fors_leaf_addr = fors_info->leaf_addrx; + + /* Only set the parts that the caller doesn't set */ + set_tree_index(fors_leaf_addr, addr_idx); + set_type(fors_leaf_addr, SPX_ADDR_TYPE_FORSPRF); + fors_gen_sk(leaf, ctx, fors_leaf_addr); + + set_type(fors_leaf_addr, SPX_ADDR_TYPE_FORSTREE); + fors_sk_to_leaf(leaf, leaf, + ctx, fors_leaf_addr); +} + +/** + * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + * Assumes indices has space for SPX_FORS_TREES integers. + */ +static void message_to_indices(uint32_t *indices, const unsigned char *m) { + unsigned int i, j; + unsigned int offset = 0; + + for (i = 0; i < SPX_FORS_TREES; i++) { + indices[i] = 0; + for (j = 0; j < SPX_FORS_HEIGHT; j++) { + indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); + offset++; + } + } +} + +/** + * Signs a message m, deriving the secret key from sk_seed and the FTS address. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + uint32_t fors_tree_addr[8] = {0}; + struct fors_gen_leaf_info fors_info = {0}; + uint32_t *fors_leaf_addr = fors_info.leaf_addrx; + uint32_t fors_pk_addr[8] = {0}; + uint32_t idx_offset; + unsigned int i; + + copy_keypair_addr(fors_tree_addr, fors_addr); + copy_keypair_addr(fors_leaf_addr, fors_addr); + + copy_keypair_addr(fors_pk_addr, fors_addr); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); + + message_to_indices(indices, m); + + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); + + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); + + /* Include the secret key part that produces the selected leaf node. */ + fors_gen_sk(sig, ctx, fors_tree_addr); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + sig += SPX_N; + + /* Compute the authentication path for this leaf node. */ + treehashx1(roots + i * SPX_N, sig, ctx, + indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx1, + fors_tree_addr, &fors_info); + + sig += SPX_N * SPX_FORS_HEIGHT; + } + + /* Hash horizontally across all tree roots to derive the public key. */ + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); +} + +/** + * Derives the FORS public key from a signature. + * This can be used for verification by comparing to a known public key, or to + * subsequently verify a signature on the derived public key. The latter is the + * typical use-case when used as an FTS below an OTS in a hypertree. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + unsigned char leaf[SPX_N]; + uint32_t fors_tree_addr[8] = {0}; + uint32_t fors_pk_addr[8] = {0}; + uint32_t idx_offset; + unsigned int i; + + copy_keypair_addr(fors_tree_addr, fors_addr); + copy_keypair_addr(fors_pk_addr, fors_addr); + + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); + + message_to_indices(indices, m); + + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); + + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + + /* Derive the leaf from the included secret key part. */ + fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); + sig += SPX_N; + + /* Derive the corresponding root node of this tree. */ + compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, + sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); + sig += SPX_N * SPX_FORS_HEIGHT; + } + + /* Hash horizontally across all tree roots to derive the public key. */ + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_clean/fors.h b/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_clean/fors.h new file mode 100644 index 0000000000..509140a178 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_clean/fors.h @@ -0,0 +1,32 @@ +#ifndef SPX_FORS_H +#define SPX_FORS_H + +#include + +#include "context.h" +#include "params.h" + +/** + * Signs a message m, deriving the secret key from sk_seed and the FTS address. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +#define fors_sign SPX_NAMESPACE(fors_sign) +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); + +/** + * Derives the FORS public key from a signature. + * This can be used for verification by comparing to a known public key, or to + * subsequently verify a signature on the derived public key. The latter is the + * typical use-case when used as an FTS below an OTS in a hypertree. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_clean/hash.h b/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_clean/hash.h new file mode 100644 index 0000000000..ffe815f45d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_clean/hash.h @@ -0,0 +1,37 @@ +#ifndef SPX_HASH_H +#define SPX_HASH_H + +#include +#include + +#include "context.h" +#include "params.h" + +#define prf_addr SPX_NAMESPACE(prf_addr) +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]); + +#define gen_message_random SPX_NAMESPACE(gen_message_random) +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); + +#define hash_message SPX_NAMESPACE(hash_message) +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); + + +# define SPX_SHA256_ADDR_BYTES 22 + +# define mgf1_256 SPX_NAMESPACE(mgf1_256) +void mgf1_256(unsigned char *out, unsigned long outlen, + const unsigned char *in, unsigned long inlen); + +# define mgf1_512 SPX_NAMESPACE(mgf1_512) +void mgf1_512(unsigned char *out, unsigned long outlen, + const unsigned char *in, unsigned long inlen); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_clean/hash_sha2.c b/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_clean/hash_sha2.c new file mode 100644 index 0000000000..3d0085c8c1 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_clean/hash_sha2.c @@ -0,0 +1,219 @@ +#include +#include + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "sha2.h" +#include "utils.h" + + + +#define SPX_SHAX_OUTPUT_BYTES SPX_SHA512_OUTPUT_BYTES +#define SPX_SHAX_BLOCK_BYTES SPX_SHA512_BLOCK_BYTES +#define shaX_inc_init sha512_inc_init +#define shaX_inc_blocks sha512_inc_blocks +#define shaX_inc_finalize sha512_inc_finalize +#define shaX sha512 +#define mgf1_X mgf1_512 +#define shaXstate sha512ctx + +/** + * mgf1 function based on the SHA-256 hash function + * Note that inlen should be sufficiently small that it still allows for + * an array to be allocated on the stack. Typically 'in' is merely a seed. + * Outputs outlen number of bytes + */ +void mgf1_256(unsigned char *out, unsigned long outlen, + const unsigned char *in, unsigned long inlen) { + PQCLEAN_VLA(uint8_t, inbuf, inlen + 4); + unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES]; + uint32_t i; + + memcpy(inbuf, in, inlen); + + /* While we can fit in at least another full block of SHA256 output.. */ + for (i = 0; (i + 1)*SPX_SHA256_OUTPUT_BYTES <= outlen; i++) { + u32_to_bytes(inbuf + inlen, i); + sha256(out, inbuf, inlen + 4); + out += SPX_SHA256_OUTPUT_BYTES; + } + /* Until we cannot anymore, and we fill the remainder. */ + if (outlen > i * SPX_SHA256_OUTPUT_BYTES) { + u32_to_bytes(inbuf + inlen, i); + sha256(outbuf, inbuf, inlen + 4); + memcpy(out, outbuf, outlen - i * SPX_SHA256_OUTPUT_BYTES); + } +} + +/* + * mgf1 function based on the SHA-512 hash function + */ +void mgf1_512(unsigned char *out, unsigned long outlen, + const unsigned char *in, unsigned long inlen) { + PQCLEAN_VLA(uint8_t, inbuf, inlen + 4); + unsigned char outbuf[SPX_SHA512_OUTPUT_BYTES]; + uint32_t i; + + memcpy(inbuf, in, inlen); + + /* While we can fit in at least another full block of SHA512 output.. */ + for (i = 0; (i + 1)*SPX_SHA512_OUTPUT_BYTES <= outlen; i++) { + u32_to_bytes(inbuf + inlen, i); + sha512(out, inbuf, inlen + 4); + out += SPX_SHA512_OUTPUT_BYTES; + } + /* Until we cannot anymore, and we fill the remainder. */ + if (outlen > i * SPX_SHA512_OUTPUT_BYTES) { + u32_to_bytes(inbuf + inlen, i); + sha512(outbuf, inbuf, inlen + 4); + memcpy(out, outbuf, outlen - i * SPX_SHA512_OUTPUT_BYTES); + } +} + +/* + * Computes PRF(pk_seed, sk_seed, addr). + */ +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]) { + sha256ctx sha2_state; + unsigned char buf[SPX_SHA256_ADDR_BYTES + SPX_N]; + unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES]; + + /* Retrieve precomputed state containing pub_seed */ + sha256_inc_ctx_clone(&sha2_state, &ctx->state_seeded); + + /* Remainder: ADDR^c ‖ SK.seed */ + memcpy(buf, addr, SPX_SHA256_ADDR_BYTES); + memcpy(buf + SPX_SHA256_ADDR_BYTES, ctx->sk_seed, SPX_N); + + sha256_inc_finalize(outbuf, &sha2_state, buf, SPX_SHA256_ADDR_BYTES + SPX_N); + + memcpy(out, outbuf, SPX_N); +} + +/** + * Computes the message-dependent randomness R, using a secret seed as a key + * for HMAC, and an optional randomization value prefixed to the message. + * This requires m to have at least SPX_SHAX_BLOCK_BYTES + SPX_N space + * available in front of the pointer, i.e. before the message to use for the + * prefix. This is necessary to prevent having to move the message around (and + * allocate memory for it). + */ +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { + (void)ctx; + + unsigned char buf[SPX_SHAX_BLOCK_BYTES + SPX_SHAX_OUTPUT_BYTES]; + shaXstate state; + int i; + + + /* This implements HMAC-SHA */ + for (i = 0; i < SPX_N; i++) { + buf[i] = 0x36 ^ sk_prf[i]; + } + memset(buf + SPX_N, 0x36, SPX_SHAX_BLOCK_BYTES - SPX_N); + + shaX_inc_init(&state); + shaX_inc_blocks(&state, buf, 1); + + memcpy(buf, optrand, SPX_N); + + /* If optrand + message cannot fill up an entire block */ + if (SPX_N + mlen < SPX_SHAX_BLOCK_BYTES) { + memcpy(buf + SPX_N, m, mlen); + shaX_inc_finalize(buf + SPX_SHAX_BLOCK_BYTES, &state, + buf, mlen + SPX_N); + } + /* Otherwise first fill a block, so that finalize only uses the message */ + else { + memcpy(buf + SPX_N, m, SPX_SHAX_BLOCK_BYTES - SPX_N); + shaX_inc_blocks(&state, buf, 1); + + m += SPX_SHAX_BLOCK_BYTES - SPX_N; + mlen -= SPX_SHAX_BLOCK_BYTES - SPX_N; + shaX_inc_finalize(buf + SPX_SHAX_BLOCK_BYTES, &state, m, mlen); + } + + for (i = 0; i < SPX_N; i++) { + buf[i] = 0x5c ^ sk_prf[i]; + } + memset(buf + SPX_N, 0x5c, SPX_SHAX_BLOCK_BYTES - SPX_N); + + shaX(buf, buf, SPX_SHAX_BLOCK_BYTES + SPX_SHAX_OUTPUT_BYTES); + memcpy(R, buf, SPX_N); +} + +/** + * Computes the message hash using R, the public key, and the message. + * Outputs the message digest and the index of the leaf. The index is split in + * the tree index and the leaf index, for convenient copying to an address. + */ +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { + (void)ctx; +#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) +#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) +#define SPX_LEAF_BITS SPX_TREE_HEIGHT +#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) +#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) + + unsigned char seed[2 * SPX_N + SPX_SHAX_OUTPUT_BYTES]; + + /* Round to nearest multiple of SPX_SHAX_BLOCK_BYTES */ +#define SPX_INBLOCKS (((SPX_N + SPX_PK_BYTES + SPX_SHAX_BLOCK_BYTES - 1) & \ + -SPX_SHAX_BLOCK_BYTES) / SPX_SHAX_BLOCK_BYTES) + unsigned char inbuf[SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES]; + + unsigned char buf[SPX_DGST_BYTES]; + unsigned char *bufp = buf; + shaXstate state; + + shaX_inc_init(&state); + + // seed: SHA-X(R ‖ PK.seed ‖ PK.root ‖ M) + memcpy(inbuf, R, SPX_N); + memcpy(inbuf + SPX_N, pk, SPX_PK_BYTES); + + /* If R + pk + message cannot fill up an entire block */ + if (SPX_N + SPX_PK_BYTES + mlen < SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES) { + memcpy(inbuf + SPX_N + SPX_PK_BYTES, m, mlen); + shaX_inc_finalize(seed + 2 * SPX_N, &state, inbuf, SPX_N + SPX_PK_BYTES + mlen); + } + /* Otherwise first fill a block, so that finalize only uses the message */ + else { + memcpy(inbuf + SPX_N + SPX_PK_BYTES, m, + SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES - SPX_N - SPX_PK_BYTES); + shaX_inc_blocks(&state, inbuf, SPX_INBLOCKS); + + m += SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES - SPX_N - SPX_PK_BYTES; + mlen -= SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES - SPX_N - SPX_PK_BYTES; + shaX_inc_finalize(seed + 2 * SPX_N, &state, m, (size_t)mlen); + } + + // H_msg: MGF1-SHA-X(R ‖ PK.seed ‖ seed) + memcpy(seed, R, SPX_N); + memcpy(seed + SPX_N, pk, SPX_N); + + /* By doing this in two steps, we prevent hashing the message twice; + otherwise each iteration in MGF1 would hash the message again. */ + mgf1_X(bufp, SPX_DGST_BYTES, seed, 2 * SPX_N + SPX_SHAX_OUTPUT_BYTES); + + memcpy(digest, bufp, SPX_FORS_MSG_BYTES); + bufp += SPX_FORS_MSG_BYTES; + + + *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); + *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); + bufp += SPX_TREE_BYTES; + + *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); + *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); +} + + diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_clean/merkle.c b/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_clean/merkle.c new file mode 100644 index 0000000000..0c1479fd93 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_clean/merkle.c @@ -0,0 +1,59 @@ +#include +#include + +#include "address.h" +#include "merkle.h" +#include "params.h" +#include "utils.h" +#include "utilsx1.h" +#include "wots.h" +#include "wotsx1.h" + +/* + * This generates a Merkle signature (WOTS signature followed by the Merkle + * authentication path). This is in this file because most of the complexity + * is involved with the WOTS signature; the Merkle authentication path logic + * is mostly hidden in treehashx4 + */ +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf) { + unsigned char *auth_path = sig + SPX_WOTS_BYTES; + struct leaf_info_x1 info = { 0 }; + unsigned steps[ SPX_WOTS_LEN ]; + + info.wots_sig = sig; + chain_lengths(steps, root); + info.wots_steps = steps; + + set_type(&tree_addr[0], SPX_ADDR_TYPE_HASHTREE); + set_type(&info.pk_addr[0], SPX_ADDR_TYPE_WOTSPK); + copy_subtree_addr(&info.leaf_addr[0], wots_addr); + copy_subtree_addr(&info.pk_addr[0], wots_addr); + + info.wots_sign_leaf = idx_leaf; + + treehashx1(root, auth_path, ctx, + idx_leaf, 0, + SPX_TREE_HEIGHT, + wots_gen_leafx1, + tree_addr, &info); +} + +/* Compute root node of the top-most subtree. */ +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { + /* We do not need the auth path in key generation, but it simplifies the + code to have just one treehash routine that computes both root and path + in one function. */ + unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; + uint32_t top_tree_addr[8] = {0}; + uint32_t wots_addr[8] = {0}; + + set_layer_addr(top_tree_addr, SPX_D - 1); + set_layer_addr(wots_addr, SPX_D - 1); + + merkle_sign(auth_path, root, ctx, + wots_addr, top_tree_addr, + (uint32_t)~0 /* ~0 means "don't bother generating an auth path */ ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_clean/merkle.h b/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_clean/merkle.h new file mode 100644 index 0000000000..769cf2e970 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_clean/merkle.h @@ -0,0 +1,21 @@ +#ifndef MERKLE_H_ +#define MERKLE_H_ + +#include + +#include "context.h" +#include "params.h" + +/* Generate a Merkle signature (WOTS signature followed by the Merkle */ +/* authentication path) */ +#define merkle_sign SPX_NAMESPACE(merkle_sign) +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf); + +/* Compute the root node of the top-most subtree. */ +#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); + +#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_clean/nistapi.h b/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_clean/nistapi.h new file mode 100644 index 0000000000..3cb71afad4 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_clean/nistapi.h @@ -0,0 +1,87 @@ +#ifndef SPX_API_H +#define SPX_API_H + +#include +#include + +#include "params.h" + +#define CRYPTO_ALGNAME "SPHINCS+" + +#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES +#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES +#define CRYPTO_BYTES SPX_BYTES +#define CRYPTO_SEEDBYTES (3*SPX_N) + +/* + * Returns the length of a secret key, in bytes + */ +#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) +size_t crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) +size_t crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) +size_t crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) +size_t crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +#define crypto_sign SPX_NAMESPACE(crypto_sign) +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_clean/params.h b/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_clean/params.h new file mode 100644 index 0000000000..a3078f9290 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_clean/params.h @@ -0,0 +1,61 @@ +#ifndef SPX_PARAMS_H +#define SPX_PARAMS_H + +#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSSHA2256FSIMPLE_CLEAN_##s + +/* Hash output length in bytes. */ +#define SPX_N 32 +/* Height of the hypertree. */ +#define SPX_FULL_HEIGHT 68 +/* Number of subtree layer. */ +#define SPX_D 17 +/* FORS tree dimensions. */ +#define SPX_FORS_HEIGHT 9 +#define SPX_FORS_TREES 35 +/* Winternitz parameter, */ +#define SPX_WOTS_W 16 + +/* The hash function is defined by linking a different hash.c file, as opposed + to setting a #define constant. */ + +/* This is a SHA2-based parameter set, hence whether we use SHA-256 + * exclusively or we use both SHA-256 and SHA-512 is controlled by + * the following #define */ +#define SPX_SHA512 1 /* Use SHA-512 for H and T_l, l >= 2 */ + +/* For clarity */ +#define SPX_ADDR_BYTES 32 + +/* WOTS parameters. */ +#define SPX_WOTS_LOGW 4 + +#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) + +/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ +#define SPX_WOTS_LEN2 3 + +#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) +#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) +#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES + +/* Subtree size. */ +#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) + +//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT +// #error SPX_D should always divide SPX_FULL_HEIGHT +//#endif + +/* FORS parameters. */ +#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) +#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) +#define SPX_FORS_PK_BYTES SPX_N + +/* Resulting SPX sizes. */ +#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ + SPX_FULL_HEIGHT * SPX_N) +#define SPX_PK_BYTES (2 * SPX_N) +#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) + +#include "sha2_offsets.h" + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_clean/sha2_offsets.h b/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_clean/sha2_offsets.h new file mode 100644 index 0000000000..6e3584f7a4 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_clean/sha2_offsets.h @@ -0,0 +1,27 @@ +#ifndef SHA2_OFFSETS_H_ +#define SHA2_OFFSETS_H_ + +#define SPX_SHA256_BLOCK_BYTES 64 +#define SPX_SHA256_OUTPUT_BYTES 32 + +#define SPX_SHA512_BLOCK_BYTES 128 +#define SPX_SHA512_OUTPUT_BYTES 64 + +/* + * Offsets of various fields in the address structure when we use SHA2 as + * the Sphincs+ hash function + */ + +#define SPX_OFFSET_LAYER 0 /* The byte used to specify the Merkle tree layer */ +#define SPX_OFFSET_TREE 1 /* The start of the 8 byte field used to specify the tree */ +#define SPX_OFFSET_TYPE 9 /* The byte used to specify the hash type (reason) */ +#define SPX_OFFSET_KP_ADDR2 12 /* The high byte used to specify the key pair (which one-time signature) */ +#define SPX_OFFSET_KP_ADDR1 13 /* The low byte used to specify the key pair */ +#define SPX_OFFSET_CHAIN_ADDR 17 /* The byte used to specify the chain address (which Winternitz chain) */ +#define SPX_OFFSET_HASH_ADDR 21 /* The byte used to specify the hash address (where in the Winternitz chain) */ +#define SPX_OFFSET_TREE_HGT 17 /* The byte used to specify the height of this node in the FORS or Merkle tree */ +#define SPX_OFFSET_TREE_INDEX 18 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ + +#define SPX_SHA2 1 + +#endif /* SHA2_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_clean/sign.c b/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_clean/sign.c new file mode 100644 index 0000000000..9d0c7d1b22 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_clean/sign.c @@ -0,0 +1,286 @@ +#include +#include +#include + +#include "address.h" +#include "context.h" +#include "fors.h" +#include "hash.h" +#include "merkle.h" +#include "nistapi.h" +#include "params.h" +#include "randombytes.h" +#include "thash.h" +#include "utils.h" +#include "wots.h" + +/* + * Returns the length of a secret key, in bytes + */ +size_t crypto_sign_secretkeybytes(void) { + return CRYPTO_SECRETKEYBYTES; +} + +/* + * Returns the length of a public key, in bytes + */ +size_t crypto_sign_publickeybytes(void) { + return CRYPTO_PUBLICKEYBYTES; +} + +/* + * Returns the length of a signature, in bytes + */ +size_t crypto_sign_bytes(void) { + return CRYPTO_BYTES; +} + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +size_t crypto_sign_seedbytes(void) { + return CRYPTO_SEEDBYTES; +} + +/* + * Generates an SPX key pair given a seed of length + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [PUB_SEED || root] + */ +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed) { + spx_ctx ctx; + + /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ + memcpy(sk, seed, CRYPTO_SEEDBYTES); + + memcpy(pk, sk + 2 * SPX_N, SPX_N); + + memcpy(ctx.pub_seed, pk, SPX_N); + memcpy(ctx.sk_seed, sk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + /* Compute root node of the top-most subtree. */ + merkle_gen_root(sk + 3 * SPX_N, &ctx); + + // cleanup + free_hash_function(&ctx); + + memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); + + return 0; +} + +/* + * Generates an SPX key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [PUB_SEED || root] + */ +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { + uint8_t seed[CRYPTO_SEEDBYTES]; + randombytes(seed, CRYPTO_SEEDBYTES); + crypto_sign_seed_keypair(pk, sk, seed); + + return 0; +} + +/** + * Returns an array containing a detached signature. + */ +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk) { + spx_ctx ctx; + + const uint8_t *sk_prf = sk + SPX_N; + const uint8_t *pk = sk + 2 * SPX_N; + + uint8_t optrand[SPX_N]; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t root[SPX_N]; + uint32_t i; + uint64_t tree; + uint32_t idx_leaf; + uint32_t wots_addr[8] = {0}; + uint32_t tree_addr[8] = {0}; + + memcpy(ctx.sk_seed, sk, SPX_N); + memcpy(ctx.pub_seed, pk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + + /* Optionally, signing can be made non-deterministic using optrand. + This can help counter side-channel attacks that would benefit from + getting a large number of traces when the signer uses the same nodes. */ + randombytes(optrand, SPX_N); + /* Compute the digest randomization value. */ + gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); + + /* Derive the message digest and leaf index from R, PK and M. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; + + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); + + /* Sign the message hash using FORS. */ + fors_sign(sig, root, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); + sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; + + /* Update the indices for the next layer. */ + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; + } + + free_hash_function(&ctx); + + *siglen = SPX_BYTES; + + return 0; +} + +/** + * Verifies a detached signature and message under a given public key. + */ +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk) { + spx_ctx ctx; + const uint8_t *pub_root = pk + SPX_N; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t wots_pk[SPX_WOTS_BYTES]; + uint8_t root[SPX_N]; + uint8_t leaf[SPX_N]; + unsigned int i; + uint64_t tree; + uint32_t idx_leaf; + uint32_t wots_addr[8] = {0}; + uint32_t tree_addr[8] = {0}; + uint32_t wots_pk_addr[8] = {0}; + + if (siglen != SPX_BYTES) { + return -1; + } + + memcpy(ctx.pub_seed, pk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); + + /* Derive the message digest and leaf index from R || PK || M. */ + /* The additional SPX_N is a result of the hash domain separator. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; + + /* Layer correctly defaults to 0, so no need to set_layer_addr */ + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); + + fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + /* For each subtree.. */ + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + copy_keypair_addr(wots_pk_addr, wots_addr); + + /* The WOTS public key is only correct if the signature was correct. */ + /* Initially, root is the FORS pk, but on subsequent iterations it is + the root of the subtree below the currently processed subtree. */ + wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); + sig += SPX_WOTS_BYTES; + + /* Compute the leaf node using the WOTS public key. */ + thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); + + /* Compute the root node of this subtree. */ + compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, + &ctx, tree_addr); + sig += SPX_TREE_HEIGHT * SPX_N; + + /* Update the indices for the next layer. */ + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; + } + + // cleanup + free_hash_function(&ctx); + + /* Check if the root node equals the root node in the public key. */ + if (memcmp(root, pub_root, SPX_N) != 0) { + return -1; + } + + return 0; +} + + +/** + * Returns an array containing the signature followed by the message. + */ +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk) { + size_t siglen; + + crypto_sign_signature(sm, &siglen, m, mlen, sk); + + memmove(sm + SPX_BYTES, m, mlen); + *smlen = siglen + mlen; + + return 0; +} + +/** + * Verifies a given signature-message pair under a given public key. + */ +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk) { + /* The API caller does not necessarily know what size a signature should be + but SPHINCS+ signatures are always exactly SPX_BYTES. */ + if (smlen < SPX_BYTES) { + memset(m, 0, smlen); + *mlen = 0; + return -1; + } + + *mlen = smlen - SPX_BYTES; + + if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { + memset(m, 0, smlen); + *mlen = 0; + return -1; + } + + /* If verification was successful, move the message to the right place. */ + memmove(m, sm + SPX_BYTES, *mlen); + + return 0; +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_clean/thash.h b/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_clean/thash.h new file mode 100644 index 0000000000..8687ccfb4d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_clean/thash.h @@ -0,0 +1,13 @@ +#ifndef SPX_THASH_H +#define SPX_THASH_H + +#include "context.h" +#include "params.h" + +#include + +#define thash SPX_NAMESPACE(thash) +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_clean/thash_sha2_simple.c b/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_clean/thash_sha2_simple.c new file mode 100644 index 0000000000..87badc4d53 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_clean/thash_sha2_simple.c @@ -0,0 +1,53 @@ +#include +#include + +#include "thash.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "sha2.h" +#include "utils.h" + +static void thash_512(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]); + +/** + * Takes an array of inblocks concatenated arrays of SPX_N bytes. + */ +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]) { + if (inblocks > 1) { + thash_512(out, in, inblocks, ctx, addr); + return; + } + + unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES]; + sha256ctx sha2_state; + PQCLEAN_VLA(uint8_t, buf, SPX_SHA256_ADDR_BYTES + inblocks * SPX_N); + + /* Retrieve precomputed state containing pub_seed */ + sha256_inc_ctx_clone(&sha2_state, &ctx->state_seeded); + + memcpy(buf, addr, SPX_SHA256_ADDR_BYTES); + memcpy(buf + SPX_SHA256_ADDR_BYTES, in, inblocks * SPX_N); + + sha256_inc_finalize(outbuf, &sha2_state, buf, SPX_SHA256_ADDR_BYTES + inblocks * SPX_N); + memcpy(out, outbuf, SPX_N); +} + +static void thash_512(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]) { + unsigned char outbuf[SPX_SHA512_OUTPUT_BYTES]; + sha512ctx sha2_state; + PQCLEAN_VLA(uint8_t, buf, SPX_SHA256_ADDR_BYTES + inblocks * SPX_N); + + /* Retrieve precomputed state containing pub_seed */ + sha512_inc_ctx_clone(&sha2_state, &ctx->state_seeded_512); + + memcpy(buf, addr, SPX_SHA256_ADDR_BYTES); + memcpy(buf + SPX_SHA256_ADDR_BYTES, in, inblocks * SPX_N); + + sha512_inc_finalize(outbuf, &sha2_state, buf, SPX_SHA256_ADDR_BYTES + inblocks * SPX_N); + memcpy(out, outbuf, SPX_N); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_clean/utils.c b/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_clean/utils.c new file mode 100644 index 0000000000..177b541fb9 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_clean/utils.c @@ -0,0 +1,148 @@ +#include + +#include "utils.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "thash.h" + +/** + * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. + */ +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in) { + int i; + + /* Iterate over out in decreasing order, for big-endianness. */ + for (i = (signed int)outlen - 1; i >= 0; i--) { + out[i] = in & 0xff; + in = in >> 8; + } +} + +void u32_to_bytes(unsigned char *out, uint32_t in) { + out[0] = (unsigned char)(in >> 24); + out[1] = (unsigned char)(in >> 16); + out[2] = (unsigned char)(in >> 8); + out[3] = (unsigned char)in; +} + +/** + * Converts the inlen bytes in 'in' from big-endian byte order to an integer. + */ +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { + unsigned long long retval = 0; + unsigned int i; + + for (i = 0; i < inlen; i++) { + retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); + } + return retval; +} + +/** + * Computes a root node given a leaf and an auth path. + * Expects address to be complete other than the tree_height and tree_index. + */ +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]) { + uint32_t i; + unsigned char buffer[2 * SPX_N]; + + /* If leaf_idx is odd (last bit = 1), current path element is a right child + and auth_path has to go left. Otherwise it is the other way around. */ + if (leaf_idx & 1) { + memcpy(buffer + SPX_N, leaf, SPX_N); + memcpy(buffer, auth_path, SPX_N); + } else { + memcpy(buffer, leaf, SPX_N); + memcpy(buffer + SPX_N, auth_path, SPX_N); + } + auth_path += SPX_N; + + for (i = 0; i < tree_height - 1; i++) { + leaf_idx >>= 1; + idx_offset >>= 1; + /* Set the address of the node we're creating. */ + set_tree_height(addr, i + 1); + set_tree_index(addr, leaf_idx + idx_offset); + + /* Pick the right or left neighbor, depending on parity of the node. */ + if (leaf_idx & 1) { + thash(buffer + SPX_N, buffer, 2, ctx, addr); + memcpy(buffer, auth_path, SPX_N); + } else { + thash(buffer, buffer, 2, ctx, addr); + memcpy(buffer + SPX_N, auth_path, SPX_N); + } + auth_path += SPX_N; + } + + /* The last iteration is exceptional; we do not copy an auth_path node. */ + leaf_idx >>= 1; + idx_offset >>= 1; + set_tree_height(addr, tree_height); + set_tree_index(addr, leaf_idx + idx_offset); + thash(root, buffer, 2, ctx, addr); +} + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx * /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]) { + PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); + PQCLEAN_VLA(unsigned int, heights, tree_height + 1); + unsigned int offset = 0; + uint32_t idx; + uint32_t tree_idx; + + for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { + /* Add the next leaf node to the stack. */ + gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); + offset++; + heights[offset - 1] = 0; + + /* If this is a node we need for the auth path.. */ + if ((leaf_idx ^ 0x1) == idx) { + memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); + } + + /* While the top-most nodes are of equal height.. */ + while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { + /* Compute index of the new node, in the next layer. */ + tree_idx = (idx >> (heights[offset - 1] + 1)); + + /* Set the address of the node we're creating. */ + set_tree_height(tree_addr, heights[offset - 1] + 1); + set_tree_index(tree_addr, + tree_idx + (idx_offset >> (heights[offset - 1] + 1))); + /* Hash the top-most nodes from the stack together. */ + thash(stack + (offset - 2)*SPX_N, + stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); + offset--; + /* Note that the top-most node is now one layer higher. */ + heights[offset - 1]++; + + /* If this is a node we need for the auth path.. */ + if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { + memcpy(auth_path + heights[offset - 1]*SPX_N, + stack + (offset - 1)*SPX_N, SPX_N); + } + } + } + memcpy(root, stack, SPX_N); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_clean/utils.h b/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_clean/utils.h new file mode 100644 index 0000000000..64f5d5a53a --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_clean/utils.h @@ -0,0 +1,58 @@ +#ifndef SPX_UTILS_H +#define SPX_UTILS_H + +#include + +#include "compat.h" +#include "context.h" +#include "params.h" + + +/* To support MSVC use alloca() instead of VLAs. See #20. */ + + +/** + * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. + */ +#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in); +#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) +void u32_to_bytes(unsigned char *out, uint32_t in); + +/** + * Converts the inlen bytes in 'in' from big-endian byte order to an integer. + */ +#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); + +/** + * Computes a root node given a leaf and an auth path. + * Expects address to be complete other than the tree_height and tree_index. + */ +#define compute_root SPX_NAMESPACE(compute_root) +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]); + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +#define treehash SPX_NAMESPACE(treehash) +void treehash(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx *ctx /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]); + + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_clean/utilsx1.c b/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_clean/utilsx1.c new file mode 100644 index 0000000000..fccb69b35d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_clean/utilsx1.c @@ -0,0 +1,100 @@ +#include + +#include "utilsx1.h" + +#include "address.h" +#include "params.h" +#include "thash.h" +#include "utils.h" + +/* + * Generate the entire Merkle tree, computing the authentication path for + * leaf_idx, and the resulting root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) + * + * This expects tree_addr to be initialized to the addr structures for the + * Merkle tree nodes + * + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + * + * This works by using the standard Merkle tree building algorithm, + */ +void treehashx1(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, + uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* Where to write the leaves */, + const spx_ctx * /* ctx */, + uint32_t idx, void *info), + uint32_t tree_addr[8], + void *info) { + /* This is where we keep the intermediate nodes */ + PQCLEAN_VLA(uint8_t, stack, tree_height * SPX_N); + + uint32_t idx; + uint32_t max_idx = (uint32_t)((1 << tree_height) - 1); + for (idx = 0;; idx++) { + unsigned char current[2 * SPX_N]; /* Current logical node is at */ + /* index[SPX_N]. We do this to minimize the number of copies */ + /* needed during a thash */ + gen_leaf( ¤t[SPX_N], ctx, idx + idx_offset, + info ); + + /* Now combine the freshly generated right node with previously */ + /* generated left ones */ + uint32_t internal_idx_offset = idx_offset; + uint32_t internal_idx = idx; + uint32_t internal_leaf = leaf_idx; + uint32_t h; /* The height we are in the Merkle tree */ + for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { + + /* Check if we hit the top of the tree */ + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[SPX_N], SPX_N ); + return; + } + + /* + * Check if the node we have is a part of the + * authentication path; if it is, write it out + */ + if ((internal_idx ^ internal_leaf) == 0x01) { + memcpy( &auth_path[ h * SPX_N ], + ¤t[SPX_N], + SPX_N ); + } + + /* + * Check if we're at a left child; if so, stop going up the stack + * Exception: if we've reached the end of the tree, keep on going + * (so we combine the last 4 nodes into the one root node in two + * more iterations) + */ + if ((internal_idx & 1) == 0 && idx < max_idx) { + break; + } + + /* Ok, we're at a right node */ + /* Now combine the left and right logical nodes together */ + + /* Set the address of the node we're creating. */ + internal_idx_offset >>= 1; + set_tree_height(tree_addr, h + 1); + set_tree_index(tree_addr, internal_idx / 2 + internal_idx_offset ); + + unsigned char *left = &stack[h * SPX_N]; + memcpy( ¤t[0], left, SPX_N ); + thash( ¤t[1 * SPX_N], + ¤t[0 * SPX_N], + 2, ctx, tree_addr); + } + + /* We've hit a left child; save the current for when we get the */ + /* corresponding right right */ + memcpy( &stack[h * SPX_N], ¤t[SPX_N], SPX_N); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_clean/utilsx1.h b/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_clean/utilsx1.h new file mode 100644 index 0000000000..e911d17d53 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_clean/utilsx1.h @@ -0,0 +1,27 @@ +#ifndef SPX_UTILSX4_H +#define SPX_UTILSX4_H + +#include + +#include "context.h" +#include "params.h" + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +#define treehashx1 SPX_NAMESPACE(treehashx1) +void treehashx1(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* Where to write the leaf */, + const spx_ctx * /* ctx */, + uint32_t addr_idx, void *info), + uint32_t tree_addrx4[8], void *info); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_clean/wots.c b/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_clean/wots.c new file mode 100644 index 0000000000..249717aaa8 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_clean/wots.c @@ -0,0 +1,108 @@ +#include +#include + +#include "wots.h" +#include "wotsx1.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "thash.h" +#include "utils.h" +#include "utilsx1.h" + +// TODO clarify address expectations, and make them more uniform. +// TODO i.e. do we expect types to be set already? +// TODO and do we expect modifications or copies? + +/** + * Computes the chaining function. + * out and in have to be n-byte arrays. + * + * Interprets in as start-th value of the chain. + * addr has to contain the address of the chain. + */ +static void gen_chain(unsigned char *out, const unsigned char *in, + unsigned int start, unsigned int steps, + const spx_ctx *ctx, uint32_t addr[8]) { + uint32_t i; + + /* Initialize out with the value at position 'start'. */ + memcpy(out, in, SPX_N); + + /* Iterate 'steps' calls to the hash function. */ + for (i = start; i < (start + steps) && i < SPX_WOTS_W; i++) { + set_hash_addr(addr, i); + thash(out, out, 1, ctx, addr); + } +} + +/** + * base_w algorithm as described in draft. + * Interprets an array of bytes as integers in base w. + * This only works when log_w is a divisor of 8. + */ +static void base_w(unsigned int *output, const int out_len, + const unsigned char *input) { + int in = 0; + int out = 0; + unsigned char total = 0; + int bits = 0; + int consumed; + + for (consumed = 0; consumed < out_len; consumed++) { + if (bits == 0) { + total = input[in]; + in++; + bits += 8; + } + bits -= SPX_WOTS_LOGW; + output[out] = (total >> bits) & (SPX_WOTS_W - 1); + out++; + } +} + +/* Computes the WOTS+ checksum over a message (in base_w). */ +static void wots_checksum(unsigned int *csum_base_w, + const unsigned int *msg_base_w) { + unsigned int csum = 0; + unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; + unsigned int i; + + /* Compute checksum. */ + for (i = 0; i < SPX_WOTS_LEN1; i++) { + csum += SPX_WOTS_W - 1 - msg_base_w[i]; + } + + /* Convert checksum to base_w. */ + /* Make sure expected empty zero bits are the least significant bits. */ + csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); + ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); + base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); +} + +/* Takes a message and derives the matching chain lengths. */ +void chain_lengths(unsigned int *lengths, const unsigned char *msg) { + base_w(lengths, SPX_WOTS_LEN1, msg); + wots_checksum(lengths + SPX_WOTS_LEN1, lengths); +} + +/** + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. + * + * Writes the computed public key to 'pk'. + */ +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]) { + unsigned int lengths[SPX_WOTS_LEN]; + uint32_t i; + + chain_lengths(lengths, msg); + + for (i = 0; i < SPX_WOTS_LEN; i++) { + set_chain_addr(addr, i); + gen_chain(pk + i * SPX_N, sig + i * SPX_N, + lengths[i], SPX_WOTS_W - 1 - lengths[i], ctx, addr); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_clean/wots.h b/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_clean/wots.h new file mode 100644 index 0000000000..4e7692eeef --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_clean/wots.h @@ -0,0 +1,25 @@ +#ifndef SPX_WOTS_H +#define SPX_WOTS_H + +#include + +#include "context.h" +#include "params.h" + +/** + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. + * + * Writes the computed public key to 'pk'. + */ +#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]); + +/* + * Compute the chain lengths needed for a given message hash + */ +#define chain_lengths SPX_NAMESPACE(chain_lengths) +void chain_lengths(unsigned int *lengths, const unsigned char *msg); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_clean/wotsx1.c b/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_clean/wotsx1.c new file mode 100644 index 0000000000..3adec78dfb --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_clean/wotsx1.c @@ -0,0 +1,76 @@ +#include +#include + +#include "wots.h" +#include "wotsx1.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "thash.h" +#include "utils.h" + +/* + * This generates a WOTS public key + * It also generates the WOTS signature if leaf_info indicates + * that we're signing with this WOTS key + */ +void wots_gen_leafx1(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info) { + struct leaf_info_x1 *info = v_info; + uint32_t *leaf_addr = info->leaf_addr; + uint32_t *pk_addr = info->pk_addr; + unsigned int i, k; + unsigned char pk_buffer[ SPX_WOTS_BYTES ]; + unsigned char *buffer; + uint32_t wots_k_mask; + + if (leaf_idx == info->wots_sign_leaf) { + /* We're traversing the leaf that's signing; generate the WOTS */ + /* signature */ + wots_k_mask = 0; + } else { + /* Nope, we're just generating pk's; turn off the signature logic */ + wots_k_mask = (uint32_t)~0; + } + + set_keypair_addr( leaf_addr, leaf_idx ); + set_keypair_addr( pk_addr, leaf_idx ); + + for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { + uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k to */ + /* the step if we're generating a signature, ~0 if we're not */ + + /* Start with the secret seed */ + set_chain_addr(leaf_addr, i); + set_hash_addr(leaf_addr, 0); + set_type(leaf_addr, SPX_ADDR_TYPE_WOTSPRF); + + prf_addr(buffer, ctx, leaf_addr); + + set_type(leaf_addr, SPX_ADDR_TYPE_WOTS); + + /* Iterate down the WOTS chain */ + for (k = 0;; k++) { + /* Check if this is the value that needs to be saved as a */ + /* part of the WOTS signature */ + if (k == wots_k) { + memcpy( info->wots_sig + i * SPX_N, buffer, SPX_N ); + } + + /* Check if we hit the top of the chain */ + if (k == SPX_WOTS_W - 1) { + break; + } + + /* Iterate one step on the chain */ + set_hash_addr(leaf_addr, k); + + thash(buffer, buffer, 1, ctx, leaf_addr); + } + } + + /* Do the final thash to generate the public keys */ + thash(dest, pk_buffer, SPX_WOTS_LEN, ctx, pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_clean/wotsx1.h b/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_clean/wotsx1.h new file mode 100644 index 0000000000..e617929f96 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256f-simple_clean/wotsx1.h @@ -0,0 +1,39 @@ +#ifndef WOTSX1_H_ +#define WOTSX1_H_ + +#include + +#include "context.h" +#include "params.h" + +/* + * This is here to provide an interface to the internal wots_gen_leafx1 + * routine. While this routine is not referenced in the package outside of + * wots.c, it is called from the stand-alone benchmark code to characterize + * the performance + */ +struct leaf_info_x1 { + unsigned char *wots_sig; + uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ + uint32_t *wots_steps; + uint32_t leaf_addr[8]; + uint32_t pk_addr[8]; +}; + +/* Macro to set the leaf_info to something 'benign', that is, it would */ +/* run with the same time as it does during the real signing process */ +/* Used only by the benchmark code */ +#define INITIALIZE_LEAF_INFO_X1(info, addr, step_buffer) { \ + (info).wots_sig = 0; \ + (info).wots_sign_leaf = ~0; \ + (info).wots_steps = step_buffer; \ + memcpy( &(info).leaf_addr[0], (addr), 32 ); \ + memcpy( &(info).pk_addr[0], (addr), 32 ); \ + } + +#define wots_gen_leafx1 SPX_NAMESPACE(wots_gen_leafx1) +void wots_gen_leafx1(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info); + +#endif /* WOTSX1_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/LICENSE b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/LICENSE new file mode 100644 index 0000000000..670154e353 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/LICENSE @@ -0,0 +1,116 @@ +CC0 1.0 Universal + +Statement of Purpose + +The laws of most jurisdictions throughout the world automatically confer +exclusive Copyright and Related Rights (defined below) upon the creator and +subsequent owner(s) (each and all, an "owner") of an original work of +authorship and/or a database (each, a "Work"). + +Certain owners wish to permanently relinquish those rights to a Work for the +purpose of contributing to a commons of creative, cultural and scientific +works ("Commons") that the public can reliably and without fear of later +claims of infringement build upon, modify, incorporate in other works, reuse +and redistribute as freely as possible in any form whatsoever and for any +purposes, including without limitation commercial purposes. These owners may +contribute to the Commons to promote the ideal of a free culture and the +further production of creative, cultural and scientific works, or to gain +reputation or greater distribution for their Work in part through the use and +efforts of others. + +For these and/or other purposes and motivations, and without any expectation +of additional consideration or compensation, the person associating CC0 with a +Work (the "Affirmer"), to the extent that he or she is an owner of Copyright +and Related Rights in the Work, voluntarily elects to apply CC0 to the Work +and publicly distribute the Work under its terms, with knowledge of his or her +Copyright and Related Rights in the Work and the meaning and intended legal +effect of CC0 on those rights. + +1. Copyright and Related Rights. A Work made available under CC0 may be +protected by copyright and related or neighboring rights ("Copyright and +Related Rights"). Copyright and Related Rights include, but are not limited +to, the following: + + i. the right to reproduce, adapt, distribute, perform, display, communicate, + and translate a Work; + + ii. moral rights retained by the original author(s) and/or performer(s); + + iii. publicity and privacy rights pertaining to a person's image or likeness + depicted in a Work; + + iv. rights protecting against unfair competition in regards to a Work, + subject to the limitations in paragraph 4(a), below; + + v. rights protecting the extraction, dissemination, use and reuse of data in + a Work; + + vi. database rights (such as those arising under Directive 96/9/EC of the + European Parliament and of the Council of 11 March 1996 on the legal + protection of databases, and under any national implementation thereof, + including any amended or successor version of such directive); and + + vii. other similar, equivalent or corresponding rights throughout the world + based on applicable law or treaty, and any national implementations thereof. + +2. Waiver. To the greatest extent permitted by, but not in contravention of, +applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and +unconditionally waives, abandons, and surrenders all of Affirmer's Copyright +and Related Rights and associated claims and causes of action, whether now +known or unknown (including existing as well as future claims and causes of +action), in the Work (i) in all territories worldwide, (ii) for the maximum +duration provided by applicable law or treaty (including future time +extensions), (iii) in any current or future medium and for any number of +copies, and (iv) for any purpose whatsoever, including without limitation +commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes +the Waiver for the benefit of each member of the public at large and to the +detriment of Affirmer's heirs and successors, fully intending that such Waiver +shall not be subject to revocation, rescission, cancellation, termination, or +any other legal or equitable action to disrupt the quiet enjoyment of the Work +by the public as contemplated by Affirmer's express Statement of Purpose. + +3. Public License Fallback. Should any part of the Waiver for any reason be +judged legally invalid or ineffective under applicable law, then the Waiver +shall be preserved to the maximum extent permitted taking into account +Affirmer's express Statement of Purpose. In addition, to the extent the Waiver +is so judged Affirmer hereby grants to each affected person a royalty-free, +non transferable, non sublicensable, non exclusive, irrevocable and +unconditional license to exercise Affirmer's Copyright and Related Rights in +the Work (i) in all territories worldwide, (ii) for the maximum duration +provided by applicable law or treaty (including future time extensions), (iii) +in any current or future medium and for any number of copies, and (iv) for any +purpose whatsoever, including without limitation commercial, advertising or +promotional purposes (the "License"). The License shall be deemed effective as +of the date CC0 was applied by Affirmer to the Work. Should any part of the +License for any reason be judged legally invalid or ineffective under +applicable law, such partial invalidity or ineffectiveness shall not +invalidate the remainder of the License, and in such case Affirmer hereby +affirms that he or she will not (i) exercise any of his or her remaining +Copyright and Related Rights in the Work or (ii) assert any associated claims +and causes of action with respect to the Work, in either case contrary to +Affirmer's express Statement of Purpose. + +4. Limitations and Disclaimers. + + a. No trademark or patent rights held by Affirmer are waived, abandoned, + surrendered, licensed or otherwise affected by this document. + + b. Affirmer offers the Work as-is and makes no representations or warranties + of any kind concerning the Work, express, implied, statutory or otherwise, + including without limitation warranties of title, merchantability, fitness + for a particular purpose, non infringement, or the absence of latent or + other defects, accuracy, or the present or absence of errors, whether or not + discoverable, all to the greatest extent permissible under applicable law. + + c. Affirmer disclaims responsibility for clearing rights of other persons + that may apply to the Work or any use thereof, including without limitation + any person's Copyright and Related Rights in the Work. Further, Affirmer + disclaims responsibility for obtaining any necessary consents, permissions + or other rights required for any use of the Work. + + d. Affirmer understands and acknowledges that Creative Commons is not a + party to this document and has no duty or obligation with respect to this + CC0 or use of the Work. + +For more information, please see + diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/address.c b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/address.c new file mode 100644 index 0000000000..b956e9cb29 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/address.c @@ -0,0 +1,91 @@ +#include +#include + +#include "address.h" +#include "params.h" +#include "utils.h" + +/* + * Specify which level of Merkle tree (the "layer") we're working on + */ +void set_layer_addr(uint32_t addr[8], uint32_t layer) { + ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; +} + +/* + * Specify which Merkle tree within the level (the "tree address") we're working on + */ +void set_tree_addr(uint32_t addr[8], uint64_t tree) { + ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); +} + +/* + * Specify the reason we'll use this address structure for, that is, what + * hash will we compute with it. This is used so that unrelated types of + * hashes don't accidentally get the same address structure. The type will be + * one of the SPX_ADDR_TYPE constants + */ +void set_type(uint32_t addr[8], uint32_t type) { + ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; +} + +/* + * Copy the layer and tree fields of the address structure. This is used + * when we're doing multiple types of hashes within the same Merkle tree + */ +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); +} + +/* These functions are used for OTS addresses. */ + +/* + * Specify which Merkle leaf we're working on; that is, which OTS keypair + * we're talking about. + */ +void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { + ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; +} + +/* + * Copy the layer, tree and keypair fields of the address structure. This is + * used when we're doing multiple things within the same OTS keypair + */ +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); + ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; +} + +/* + * Specify which Merkle chain within the OTS we're working with + * (the chain address) + */ +void set_chain_addr(uint32_t addr[8], uint32_t chain) { + ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; +} + +/* + * Specify where in the Merkle chain we are +* (the hash address) + */ +void set_hash_addr(uint32_t addr[8], uint32_t hash) { + ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; +} + +/* These functions are used for all hash tree addresses (including FORS). */ + +/* + * Specify the height of the node in the Merkle/FORS tree we are in + * (the tree height) + */ +void set_tree_height(uint32_t addr[8], uint32_t tree_height) { + ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; +} + +/* + * Specify the distance from the left edge of the node in the Merkle/FORS tree + * (the tree index) + */ +void set_tree_index(uint32_t addr[8], uint32_t tree_index) { + u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/address.h b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/address.h new file mode 100644 index 0000000000..24a84eb40c --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/address.h @@ -0,0 +1,52 @@ +#ifndef SPX_ADDRESS_H +#define SPX_ADDRESS_H + +#include + +#include "params.h" + +/* The hash types that are passed to set_type */ +#define SPX_ADDR_TYPE_WOTS 0 +#define SPX_ADDR_TYPE_WOTSPK 1 +#define SPX_ADDR_TYPE_HASHTREE 2 +#define SPX_ADDR_TYPE_FORSTREE 3 +#define SPX_ADDR_TYPE_FORSPK 4 +#define SPX_ADDR_TYPE_WOTSPRF 5 +#define SPX_ADDR_TYPE_FORSPRF 6 + +#define set_layer_addr SPX_NAMESPACE(set_layer_addr) +void set_layer_addr(uint32_t addr[8], uint32_t layer); + +#define set_tree_addr SPX_NAMESPACE(set_tree_addr) +void set_tree_addr(uint32_t addr[8], uint64_t tree); + +#define set_type SPX_NAMESPACE(set_type) +void set_type(uint32_t addr[8], uint32_t type); + +/* Copies the layer and tree part of one address into the other */ +#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); + +/* These functions are used for WOTS and FORS addresses. */ + +#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) +void set_keypair_addr(uint32_t addr[8], uint32_t keypair); + +#define set_chain_addr SPX_NAMESPACE(set_chain_addr) +void set_chain_addr(uint32_t addr[8], uint32_t chain); + +#define set_hash_addr SPX_NAMESPACE(set_hash_addr) +void set_hash_addr(uint32_t addr[8], uint32_t hash); + +#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); + +/* These functions are used for all hash tree addresses (including FORS). */ + +#define set_tree_height SPX_NAMESPACE(set_tree_height) +void set_tree_height(uint32_t addr[8], uint32_t tree_height); + +#define set_tree_index SPX_NAMESPACE(set_tree_index) +void set_tree_index(uint32_t addr[8], uint32_t tree_index); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/api.h b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/api.h new file mode 100644 index 0000000000..9427be0824 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/api.h @@ -0,0 +1,77 @@ +#ifndef PQCLEAN_SPHINCSSHA2256SROBUST_AVX2_API_H +#define PQCLEAN_SPHINCSSHA2256SROBUST_AVX2_API_H + +#include +#include + +#define PQCLEAN_SPHINCSSHA2256SROBUST_AVX2_CRYPTO_ALGNAME "SPHINCS+-sha2-256s-robust" + +#define PQCLEAN_SPHINCSSHA2256SROBUST_AVX2_CRYPTO_SECRETKEYBYTES 128 +#define PQCLEAN_SPHINCSSHA2256SROBUST_AVX2_CRYPTO_PUBLICKEYBYTES 64 +#define PQCLEAN_SPHINCSSHA2256SROBUST_AVX2_CRYPTO_BYTES 29792 + +#define PQCLEAN_SPHINCSSHA2256SROBUST_AVX2_CRYPTO_SEEDBYTES 96 + +/* + * Returns the length of a secret key, in bytes + */ +size_t PQCLEAN_SPHINCSSHA2256SROBUST_AVX2_crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +size_t PQCLEAN_SPHINCSSHA2256SROBUST_AVX2_crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +size_t PQCLEAN_SPHINCSSHA2256SROBUST_AVX2_crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +size_t PQCLEAN_SPHINCSSHA2256SROBUST_AVX2_crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +int PQCLEAN_SPHINCSSHA2256SROBUST_AVX2_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +int PQCLEAN_SPHINCSSHA2256SROBUST_AVX2_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +int PQCLEAN_SPHINCSSHA2256SROBUST_AVX2_crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +int PQCLEAN_SPHINCSSHA2256SROBUST_AVX2_crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, + const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +int PQCLEAN_SPHINCSSHA2256SROBUST_AVX2_crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +int PQCLEAN_SPHINCSSHA2256SROBUST_AVX2_crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/context.h b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/context.h new file mode 100644 index 0000000000..d3bf1c3aac --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/context.h @@ -0,0 +1,29 @@ +#ifndef SPX_CONTEXT_H +#define SPX_CONTEXT_H + +#include + +#include "params.h" +#include "sha2.h" +#include "sha256avx.h" +#include "sha512x4.h" + +// funky ordering due to optimal padding +typedef struct { + sha256x8ctx statex8_seeded; + sha512x4ctx statex4_seeded_512; + sha256ctx state_seeded; + sha512ctx state_seeded_512; + + uint8_t pub_seed[SPX_N]; + uint8_t sk_seed[SPX_N]; +} spx_ctx; + + +#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) +void initialize_hash_function(spx_ctx *ctx); + +#define free_hash_function SPX_NAMESPACE(free_hash_function) +void free_hash_function(spx_ctx *ctx); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/context_sha2.c b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/context_sha2.c new file mode 100644 index 0000000000..83c1b6585d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/context_sha2.c @@ -0,0 +1,56 @@ +#include + +#include "context.h" + +/** + * Absorb the constant pub_seed using one round of the compression function + * This initializes state_seeded and state_seeded_512, which can then be + * reused in thash + **/ +static void seed_state(spx_ctx *ctx) { + uint8_t block[SPX_SHA512_BLOCK_BYTES]; + size_t i; + + for (i = 0; i < SPX_N; ++i) { + block[i] = ctx->pub_seed[i]; + } + for (i = SPX_N; i < SPX_SHA512_BLOCK_BYTES; ++i) { + block[i] = 0; + } + /* block has been properly initialized for both SHA-256 and SHA-512 */ + + sha256_inc_init(&ctx->state_seeded); + sha256_inc_blocks(&ctx->state_seeded, block, 1); + + // initialize x8 + sha256_init8x(&ctx->statex8_seeded); + sha256_transform8x(&ctx->statex8_seeded, + block, block, block, block, block, block, block, block); + + ctx->statex8_seeded.datalen = 0; + ctx->statex8_seeded.msglen = 512; + + sha512_inc_init(&ctx->state_seeded_512); + sha512_inc_blocks(&ctx->state_seeded_512, block, 1); + + // initialize x4 + sha512_init4x(&ctx->statex4_seeded_512); + sha512_transform4x(&ctx->statex4_seeded_512, block, block, block, block); + + ctx->statex4_seeded_512.datalen = 0; + ctx->statex4_seeded_512.msglen = 1024; + + +} + + +/* For SHA, we initialize the hash function at the start */ +void initialize_hash_function(spx_ctx *ctx) { + seed_state(ctx); +} + +/* Free the incremental hashing context for heap-based SHA2 APIs */ +void free_hash_function(spx_ctx *ctx) { + sha256_inc_ctx_release(&ctx->state_seeded); + sha512_inc_ctx_release(&ctx->state_seeded_512); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/fors.c b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/fors.c new file mode 100644 index 0000000000..4cab8e7415 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/fors.c @@ -0,0 +1,226 @@ +#include +#include +#include + +#include "fors.h" + + +#include "address.h" +#include "hash.h" +#include "hashx8.h" +#include "thash.h" +#include "thashx8.h" +#include "utils.h" +#include "utilsx8.h" +static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + prf_addr(sk, ctx, fors_leaf_addr); +} + +static void fors_gen_skx8(unsigned char *sk0, + unsigned char *sk1, + unsigned char *sk2, + unsigned char *sk3, + unsigned char *sk4, + unsigned char *sk5, + unsigned char *sk6, + unsigned char *sk7, const spx_ctx *ctx, + uint32_t fors_leaf_addrx8[8 * 8]) { + prf_addrx8(sk0, sk1, sk2, sk3, sk4, sk5, sk6, sk7, + ctx, fors_leaf_addrx8); +} + +static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, + const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + thash(leaf, sk, 1, ctx, fors_leaf_addr); +} + +static void fors_sk_to_leafx8(unsigned char *leaf0, + unsigned char *leaf1, + unsigned char *leaf2, + unsigned char *leaf3, + unsigned char *leaf4, + unsigned char *leaf5, + unsigned char *leaf6, + unsigned char *leaf7, + const unsigned char *sk0, + const unsigned char *sk1, + const unsigned char *sk2, + const unsigned char *sk3, + const unsigned char *sk4, + const unsigned char *sk5, + const unsigned char *sk6, + const unsigned char *sk7, + const spx_ctx *ctx, + uint32_t fors_leaf_addrx8[8 * 8]) { + thashx8(leaf0, leaf1, leaf2, leaf3, leaf4, leaf5, leaf6, leaf7, + sk0, sk1, sk2, sk3, sk4, sk5, sk6, sk7, + 1, ctx, fors_leaf_addrx8); +} + +struct fors_gen_leaf_info { + uint32_t leaf_addrx[8 * 8]; +}; + +static void fors_gen_leafx8(unsigned char *leaf, + const spx_ctx *ctx, + uint32_t addr_idx, void *info) { + struct fors_gen_leaf_info *fors_info = info; + uint32_t *fors_leaf_addrx8 = fors_info->leaf_addrx; + unsigned int j; + + /* Only set the parts that the caller doesn't set */ + for (j = 0; j < 8; j++) { + set_tree_index(fors_leaf_addrx8 + j * 8, addr_idx + j); + set_type(fors_leaf_addrx8 + j * 8, SPX_ADDR_TYPE_FORSPRF); + } + + fors_gen_skx8(leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + leaf + 2 * SPX_N, + leaf + 3 * SPX_N, + leaf + 4 * SPX_N, + leaf + 5 * SPX_N, + leaf + 6 * SPX_N, + leaf + 7 * SPX_N, + ctx, fors_leaf_addrx8); + + for (j = 0; j < 8; j++) { + set_type(fors_leaf_addrx8 + j * 8, SPX_ADDR_TYPE_FORSTREE); + } + + fors_sk_to_leafx8(leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + leaf + 2 * SPX_N, + leaf + 3 * SPX_N, + leaf + 4 * SPX_N, + leaf + 5 * SPX_N, + leaf + 6 * SPX_N, + leaf + 7 * SPX_N, + leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + leaf + 2 * SPX_N, + leaf + 3 * SPX_N, + leaf + 4 * SPX_N, + leaf + 5 * SPX_N, + leaf + 6 * SPX_N, + leaf + 7 * SPX_N, + ctx, fors_leaf_addrx8); +} + +/** + * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + * Assumes indices has space for SPX_FORS_TREES integers. + */ +static void message_to_indices(uint32_t *indices, const unsigned char *m) { + unsigned int i, j; + unsigned int offset = 0; + + for (i = 0; i < SPX_FORS_TREES; i++) { + indices[i] = 0; + for (j = 0; j < SPX_FORS_HEIGHT; j++) { + indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); + offset++; + } + } +} + +/** + * Signs a message m, deriving the secret key from sk_seed and the FTS address. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + uint32_t fors_tree_addr[8 * 8] = {0}; + struct fors_gen_leaf_info fors_info = {0}; + uint32_t *fors_leaf_addr = fors_info.leaf_addrx; + uint32_t fors_pk_addr[8] = {0}; + uint32_t idx_offset; + unsigned int i; + + for (i = 0; i < 8; i++) { + copy_keypair_addr(fors_tree_addr + 8 * i, fors_addr); + set_type(fors_tree_addr + 8 * i, SPX_ADDR_TYPE_FORSTREE); + copy_keypair_addr(fors_leaf_addr + 8 * i, fors_addr); + } + copy_keypair_addr(fors_pk_addr, fors_addr); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); + + message_to_indices(indices, m); + + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); + + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + + /* Include the secret key part that produces the selected leaf node. */ + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); + fors_gen_sk(sig, ctx, fors_tree_addr); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + sig += SPX_N; + + /* Compute the authentication path for this leaf node. */ + treehashx8(roots + i * SPX_N, sig, ctx, + indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx8, + fors_tree_addr, &fors_info); + + sig += SPX_N * SPX_FORS_HEIGHT; + } + + /* Hash horizontally across all tree roots to derive the public key. */ + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); +} + +/** + * Derives the FORS public key from a signature. + * This can be used for verification by comparing to a known public key, or to + * subsequently verify a signature on the derived public key. The latter is the + * typical use-case when used as an FTS below an OTS in a hypertree. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + unsigned char leaf[SPX_N]; + uint32_t fors_tree_addr[8] = {0}; + uint32_t fors_pk_addr[8] = {0}; + uint32_t idx_offset; + unsigned int i; + + copy_keypair_addr(fors_tree_addr, fors_addr); + copy_keypair_addr(fors_pk_addr, fors_addr); + + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); + + message_to_indices(indices, m); + + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); + + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + + /* Derive the leaf from the included secret key part. */ + fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); + sig += SPX_N; + + /* Derive the corresponding root node of this tree. */ + compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, + sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); + sig += SPX_N * SPX_FORS_HEIGHT; + } + + /* Hash horizontally across all tree roots to derive the public key. */ + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/fors.h b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/fors.h new file mode 100644 index 0000000000..509140a178 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/fors.h @@ -0,0 +1,32 @@ +#ifndef SPX_FORS_H +#define SPX_FORS_H + +#include + +#include "context.h" +#include "params.h" + +/** + * Signs a message m, deriving the secret key from sk_seed and the FTS address. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +#define fors_sign SPX_NAMESPACE(fors_sign) +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); + +/** + * Derives the FORS public key from a signature. + * This can be used for verification by comparing to a known public key, or to + * subsequently verify a signature on the derived public key. The latter is the + * typical use-case when used as an FTS below an OTS in a hypertree. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/hash.h b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/hash.h new file mode 100644 index 0000000000..ffe815f45d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/hash.h @@ -0,0 +1,37 @@ +#ifndef SPX_HASH_H +#define SPX_HASH_H + +#include +#include + +#include "context.h" +#include "params.h" + +#define prf_addr SPX_NAMESPACE(prf_addr) +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]); + +#define gen_message_random SPX_NAMESPACE(gen_message_random) +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); + +#define hash_message SPX_NAMESPACE(hash_message) +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); + + +# define SPX_SHA256_ADDR_BYTES 22 + +# define mgf1_256 SPX_NAMESPACE(mgf1_256) +void mgf1_256(unsigned char *out, unsigned long outlen, + const unsigned char *in, unsigned long inlen); + +# define mgf1_512 SPX_NAMESPACE(mgf1_512) +void mgf1_512(unsigned char *out, unsigned long outlen, + const unsigned char *in, unsigned long inlen); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/hash_sha2.c b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/hash_sha2.c new file mode 100644 index 0000000000..3d0085c8c1 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/hash_sha2.c @@ -0,0 +1,219 @@ +#include +#include + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "sha2.h" +#include "utils.h" + + + +#define SPX_SHAX_OUTPUT_BYTES SPX_SHA512_OUTPUT_BYTES +#define SPX_SHAX_BLOCK_BYTES SPX_SHA512_BLOCK_BYTES +#define shaX_inc_init sha512_inc_init +#define shaX_inc_blocks sha512_inc_blocks +#define shaX_inc_finalize sha512_inc_finalize +#define shaX sha512 +#define mgf1_X mgf1_512 +#define shaXstate sha512ctx + +/** + * mgf1 function based on the SHA-256 hash function + * Note that inlen should be sufficiently small that it still allows for + * an array to be allocated on the stack. Typically 'in' is merely a seed. + * Outputs outlen number of bytes + */ +void mgf1_256(unsigned char *out, unsigned long outlen, + const unsigned char *in, unsigned long inlen) { + PQCLEAN_VLA(uint8_t, inbuf, inlen + 4); + unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES]; + uint32_t i; + + memcpy(inbuf, in, inlen); + + /* While we can fit in at least another full block of SHA256 output.. */ + for (i = 0; (i + 1)*SPX_SHA256_OUTPUT_BYTES <= outlen; i++) { + u32_to_bytes(inbuf + inlen, i); + sha256(out, inbuf, inlen + 4); + out += SPX_SHA256_OUTPUT_BYTES; + } + /* Until we cannot anymore, and we fill the remainder. */ + if (outlen > i * SPX_SHA256_OUTPUT_BYTES) { + u32_to_bytes(inbuf + inlen, i); + sha256(outbuf, inbuf, inlen + 4); + memcpy(out, outbuf, outlen - i * SPX_SHA256_OUTPUT_BYTES); + } +} + +/* + * mgf1 function based on the SHA-512 hash function + */ +void mgf1_512(unsigned char *out, unsigned long outlen, + const unsigned char *in, unsigned long inlen) { + PQCLEAN_VLA(uint8_t, inbuf, inlen + 4); + unsigned char outbuf[SPX_SHA512_OUTPUT_BYTES]; + uint32_t i; + + memcpy(inbuf, in, inlen); + + /* While we can fit in at least another full block of SHA512 output.. */ + for (i = 0; (i + 1)*SPX_SHA512_OUTPUT_BYTES <= outlen; i++) { + u32_to_bytes(inbuf + inlen, i); + sha512(out, inbuf, inlen + 4); + out += SPX_SHA512_OUTPUT_BYTES; + } + /* Until we cannot anymore, and we fill the remainder. */ + if (outlen > i * SPX_SHA512_OUTPUT_BYTES) { + u32_to_bytes(inbuf + inlen, i); + sha512(outbuf, inbuf, inlen + 4); + memcpy(out, outbuf, outlen - i * SPX_SHA512_OUTPUT_BYTES); + } +} + +/* + * Computes PRF(pk_seed, sk_seed, addr). + */ +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]) { + sha256ctx sha2_state; + unsigned char buf[SPX_SHA256_ADDR_BYTES + SPX_N]; + unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES]; + + /* Retrieve precomputed state containing pub_seed */ + sha256_inc_ctx_clone(&sha2_state, &ctx->state_seeded); + + /* Remainder: ADDR^c ‖ SK.seed */ + memcpy(buf, addr, SPX_SHA256_ADDR_BYTES); + memcpy(buf + SPX_SHA256_ADDR_BYTES, ctx->sk_seed, SPX_N); + + sha256_inc_finalize(outbuf, &sha2_state, buf, SPX_SHA256_ADDR_BYTES + SPX_N); + + memcpy(out, outbuf, SPX_N); +} + +/** + * Computes the message-dependent randomness R, using a secret seed as a key + * for HMAC, and an optional randomization value prefixed to the message. + * This requires m to have at least SPX_SHAX_BLOCK_BYTES + SPX_N space + * available in front of the pointer, i.e. before the message to use for the + * prefix. This is necessary to prevent having to move the message around (and + * allocate memory for it). + */ +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { + (void)ctx; + + unsigned char buf[SPX_SHAX_BLOCK_BYTES + SPX_SHAX_OUTPUT_BYTES]; + shaXstate state; + int i; + + + /* This implements HMAC-SHA */ + for (i = 0; i < SPX_N; i++) { + buf[i] = 0x36 ^ sk_prf[i]; + } + memset(buf + SPX_N, 0x36, SPX_SHAX_BLOCK_BYTES - SPX_N); + + shaX_inc_init(&state); + shaX_inc_blocks(&state, buf, 1); + + memcpy(buf, optrand, SPX_N); + + /* If optrand + message cannot fill up an entire block */ + if (SPX_N + mlen < SPX_SHAX_BLOCK_BYTES) { + memcpy(buf + SPX_N, m, mlen); + shaX_inc_finalize(buf + SPX_SHAX_BLOCK_BYTES, &state, + buf, mlen + SPX_N); + } + /* Otherwise first fill a block, so that finalize only uses the message */ + else { + memcpy(buf + SPX_N, m, SPX_SHAX_BLOCK_BYTES - SPX_N); + shaX_inc_blocks(&state, buf, 1); + + m += SPX_SHAX_BLOCK_BYTES - SPX_N; + mlen -= SPX_SHAX_BLOCK_BYTES - SPX_N; + shaX_inc_finalize(buf + SPX_SHAX_BLOCK_BYTES, &state, m, mlen); + } + + for (i = 0; i < SPX_N; i++) { + buf[i] = 0x5c ^ sk_prf[i]; + } + memset(buf + SPX_N, 0x5c, SPX_SHAX_BLOCK_BYTES - SPX_N); + + shaX(buf, buf, SPX_SHAX_BLOCK_BYTES + SPX_SHAX_OUTPUT_BYTES); + memcpy(R, buf, SPX_N); +} + +/** + * Computes the message hash using R, the public key, and the message. + * Outputs the message digest and the index of the leaf. The index is split in + * the tree index and the leaf index, for convenient copying to an address. + */ +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { + (void)ctx; +#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) +#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) +#define SPX_LEAF_BITS SPX_TREE_HEIGHT +#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) +#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) + + unsigned char seed[2 * SPX_N + SPX_SHAX_OUTPUT_BYTES]; + + /* Round to nearest multiple of SPX_SHAX_BLOCK_BYTES */ +#define SPX_INBLOCKS (((SPX_N + SPX_PK_BYTES + SPX_SHAX_BLOCK_BYTES - 1) & \ + -SPX_SHAX_BLOCK_BYTES) / SPX_SHAX_BLOCK_BYTES) + unsigned char inbuf[SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES]; + + unsigned char buf[SPX_DGST_BYTES]; + unsigned char *bufp = buf; + shaXstate state; + + shaX_inc_init(&state); + + // seed: SHA-X(R ‖ PK.seed ‖ PK.root ‖ M) + memcpy(inbuf, R, SPX_N); + memcpy(inbuf + SPX_N, pk, SPX_PK_BYTES); + + /* If R + pk + message cannot fill up an entire block */ + if (SPX_N + SPX_PK_BYTES + mlen < SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES) { + memcpy(inbuf + SPX_N + SPX_PK_BYTES, m, mlen); + shaX_inc_finalize(seed + 2 * SPX_N, &state, inbuf, SPX_N + SPX_PK_BYTES + mlen); + } + /* Otherwise first fill a block, so that finalize only uses the message */ + else { + memcpy(inbuf + SPX_N + SPX_PK_BYTES, m, + SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES - SPX_N - SPX_PK_BYTES); + shaX_inc_blocks(&state, inbuf, SPX_INBLOCKS); + + m += SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES - SPX_N - SPX_PK_BYTES; + mlen -= SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES - SPX_N - SPX_PK_BYTES; + shaX_inc_finalize(seed + 2 * SPX_N, &state, m, (size_t)mlen); + } + + // H_msg: MGF1-SHA-X(R ‖ PK.seed ‖ seed) + memcpy(seed, R, SPX_N); + memcpy(seed + SPX_N, pk, SPX_N); + + /* By doing this in two steps, we prevent hashing the message twice; + otherwise each iteration in MGF1 would hash the message again. */ + mgf1_X(bufp, SPX_DGST_BYTES, seed, 2 * SPX_N + SPX_SHAX_OUTPUT_BYTES); + + memcpy(digest, bufp, SPX_FORS_MSG_BYTES); + bufp += SPX_FORS_MSG_BYTES; + + + *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); + *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); + bufp += SPX_TREE_BYTES; + + *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); + *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); +} + + diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/hash_sha2x8.c b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/hash_sha2x8.c new file mode 100644 index 0000000000..e04af7a069 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/hash_sha2x8.c @@ -0,0 +1,75 @@ +#include +#include + +#include "hash.h" +#include "hashx8.h" + +#include "address.h" +#include "params.h" +#include "sha2.h" +#include "sha256avx.h" +#include "sha256x8.h" +#include "utils.h" + +/* + * 8-way parallel version of prf_addr; takes 8x as much input and output + */ +void prf_addrx8(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const spx_ctx *ctx, + const uint32_t addrx8[8 * 8]) { + unsigned char bufx8[8 * (SPX_N + SPX_SHA256_ADDR_BYTES)]; + unsigned char outbufx8[8 * SPX_SHA256_OUTPUT_BYTES]; + unsigned int j; + + for (j = 0; j < 8; j++) { + memcpy(bufx8 + j * (SPX_N + SPX_SHA256_ADDR_BYTES), + addrx8 + j * 8, SPX_SHA256_ADDR_BYTES); + memcpy( + bufx8 + j * (SPX_N + SPX_SHA256_ADDR_BYTES) + SPX_SHA256_ADDR_BYTES, + ctx->sk_seed, + SPX_N + ); + } + + sha256x8_seeded( + /* out */ + outbufx8 + 0 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 1 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 2 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 3 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 4 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 5 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 6 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 7 * SPX_SHA256_OUTPUT_BYTES, + + /* seed */ + &ctx->statex8_seeded, + + /* in */ + bufx8 + 0 * (SPX_SHA256_ADDR_BYTES + SPX_N), + bufx8 + 1 * (SPX_SHA256_ADDR_BYTES + SPX_N), + bufx8 + 2 * (SPX_SHA256_ADDR_BYTES + SPX_N), + bufx8 + 3 * (SPX_SHA256_ADDR_BYTES + SPX_N), + bufx8 + 4 * (SPX_SHA256_ADDR_BYTES + SPX_N), + bufx8 + 5 * (SPX_SHA256_ADDR_BYTES + SPX_N), + bufx8 + 6 * (SPX_SHA256_ADDR_BYTES + SPX_N), + bufx8 + 7 * (SPX_SHA256_ADDR_BYTES + SPX_N), + SPX_SHA256_ADDR_BYTES + SPX_N /* len */ + ); + + memcpy(out0, outbufx8 + 0 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out1, outbufx8 + 1 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out2, outbufx8 + 2 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out3, outbufx8 + 3 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out4, outbufx8 + 4 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out5, outbufx8 + 5 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out6, outbufx8 + 6 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out7, outbufx8 + 7 * SPX_SHA256_OUTPUT_BYTES, SPX_N); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/hashx8.h b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/hashx8.h new file mode 100644 index 0000000000..46503f0a10 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/hashx8.h @@ -0,0 +1,20 @@ +#ifndef SPX_HASHX8_H +#define SPX_HASHX8_H + +#include + +#include "params.h" + +#define prf_addrx8 SPX_NAMESPACE(prf_addrx8) +void prf_addrx8(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const spx_ctx *ctx, + const uint32_t addrx8[8 * 8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/merkle.c b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/merkle.c new file mode 100644 index 0000000000..1f353c8dd8 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/merkle.c @@ -0,0 +1,65 @@ +#include +#include + +#include "merkle.h" + +#include "address.h" +#include "params.h" +#include "utils.h" +#include "utilsx8.h" +#include "wots.h" +#include "wotsx8.h" + +/* + * This generates a Merkle signature (WOTS signature followed by the Merkle + * authentication path). + */ +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf) { + unsigned char *auth_path = sig + SPX_WOTS_BYTES; + uint32_t tree_addrx8[8 * 8] = { 0 }; + int j; + struct leaf_info_x8 info = { 0 }; + unsigned steps[ SPX_WOTS_LEN ]; + + info.wots_sig = sig; + chain_lengths(steps, root); + info.wots_steps = steps; + + for (j = 0; j < 8; j++) { + set_type(&tree_addrx8[8 * j], SPX_ADDR_TYPE_HASHTREE); + set_type(&info.leaf_addr[8 * j], SPX_ADDR_TYPE_WOTS); + set_type(&info.pk_addr[8 * j], SPX_ADDR_TYPE_WOTSPK); + copy_subtree_addr(&tree_addrx8[8 * j], tree_addr); + copy_subtree_addr(&info.leaf_addr[8 * j], wots_addr); + copy_subtree_addr(&info.pk_addr[8 * j], wots_addr); + } + + info.wots_sign_leaf = idx_leaf; + + treehashx8(root, auth_path, ctx, + idx_leaf, 0, + SPX_TREE_HEIGHT, + wots_gen_leafx8, + tree_addrx8, &info); +} + +/* Compute root node of the top-most subtree. */ +/* Again, in this file because wots_gen_leaf is most of the work */ +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { + /* We do not need the auth path in key generation, but it simplifies the + code to have just one treehash routine that computes both root and path + in one function. */ + unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; + uint32_t top_tree_addr[8] = {0}; + uint32_t wots_addr[8] = {0}; + + set_layer_addr(top_tree_addr, SPX_D - 1); + set_layer_addr(wots_addr, SPX_D - 1); + + merkle_sign(auth_path, root, ctx, + wots_addr, top_tree_addr, + ~0U /* ~0 means "don't bother generating an auth path */ ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/merkle.h b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/merkle.h new file mode 100644 index 0000000000..769cf2e970 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/merkle.h @@ -0,0 +1,21 @@ +#ifndef MERKLE_H_ +#define MERKLE_H_ + +#include + +#include "context.h" +#include "params.h" + +/* Generate a Merkle signature (WOTS signature followed by the Merkle */ +/* authentication path) */ +#define merkle_sign SPX_NAMESPACE(merkle_sign) +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf); + +/* Compute the root node of the top-most subtree. */ +#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); + +#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/nistapi.h b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/nistapi.h new file mode 100644 index 0000000000..3cb71afad4 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/nistapi.h @@ -0,0 +1,87 @@ +#ifndef SPX_API_H +#define SPX_API_H + +#include +#include + +#include "params.h" + +#define CRYPTO_ALGNAME "SPHINCS+" + +#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES +#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES +#define CRYPTO_BYTES SPX_BYTES +#define CRYPTO_SEEDBYTES (3*SPX_N) + +/* + * Returns the length of a secret key, in bytes + */ +#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) +size_t crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) +size_t crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) +size_t crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) +size_t crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +#define crypto_sign SPX_NAMESPACE(crypto_sign) +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/params.h b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/params.h new file mode 100644 index 0000000000..a81d22b014 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/params.h @@ -0,0 +1,61 @@ +#ifndef SPX_PARAMS_H +#define SPX_PARAMS_H + +#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSSHA2256SROBUST_AVX2_##s + +/* Hash output length in bytes. */ +#define SPX_N 32 +/* Height of the hypertree. */ +#define SPX_FULL_HEIGHT 64 +/* Number of subtree layer. */ +#define SPX_D 8 +/* FORS tree dimensions. */ +#define SPX_FORS_HEIGHT 14 +#define SPX_FORS_TREES 22 +/* Winternitz parameter, */ +#define SPX_WOTS_W 16 + +/* The hash function is defined by linking a different hash.c file, as opposed + to setting a #define constant. */ + +/* This is a SHA2-based parameter set, hence whether we use SHA-256 + * exclusively or we use both SHA-256 and SHA-512 is controlled by + * the following #define */ +#define SPX_SHA512 1 /* Use SHA-512 for H and T_l, l >= 2 */ + +/* For clarity */ +#define SPX_ADDR_BYTES 32 + +/* WOTS parameters. */ +#define SPX_WOTS_LOGW 4 + +#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) + +/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ +#define SPX_WOTS_LEN2 3 + +#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) +#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) +#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES + +/* Subtree size. */ +#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) + +//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT +// #error SPX_D should always divide SPX_FULL_HEIGHT +//#endif + +/* FORS parameters. */ +#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) +#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) +#define SPX_FORS_PK_BYTES SPX_N + +/* Resulting SPX sizes. */ +#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ + SPX_FULL_HEIGHT * SPX_N) +#define SPX_PK_BYTES (2 * SPX_N) +#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) + +#include "sha2_offsets.h" + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/sha256avx.c b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/sha256avx.c new file mode 100644 index 0000000000..6bbe6ecc24 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/sha256avx.c @@ -0,0 +1,357 @@ +#include +#include +#include + +#include "sha256avx.h" + +static const unsigned int RC[] = { + 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, + 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, + 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, + 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, + 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, + 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, + 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, + 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, + 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, + 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, + 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, + 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, + 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, + 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, + 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, + 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 +}; + +#define u32 uint32_t +#define u256 __m256i + +#define XOR _mm256_xor_si256 +#define OR _mm256_or_si256 +#define AND _mm256_and_si256 +#define ADD32 _mm256_add_epi32 +#define NOT(x) _mm256_xor_si256(x, _mm256_set_epi32(-1, -1, -1, -1, -1, -1, -1, -1)) + +#define LOAD(src) _mm256_loadu_si256((__m256i *)(src)) +#define STORE(dest,src) _mm256_storeu_si256((__m256i *)(dest),src) + +#define BYTESWAP(x) _mm256_shuffle_epi8(x, _mm256_set_epi8(0xc,0xd,0xe,0xf,0x8,0x9,0xa,0xb,0x4,0x5,0x6,0x7,0x0,0x1,0x2,0x3,0xc,0xd,0xe,0xf,0x8,0x9,0xa,0xb,0x4,0x5,0x6,0x7,0x0,0x1,0x2,0x3)) + +#define SHIFTR32(x, y) _mm256_srli_epi32(x, y) +#define SHIFTL32(x, y) _mm256_slli_epi32(x, y) + +#define ROTR32(x, y) OR(SHIFTR32(x, y), SHIFTL32(x, 32 - (y))) +#define ROTL32(x, y) OR(SHIFTL32(x, y), SHIFTR32(x, 32 - (y))) + +#define XOR3(a, b, c) XOR(XOR(a, b), c) + +#define ADD3_32(a, b, c) ADD32(ADD32(a, b), c) +#define ADD4_32(a, b, c, d) ADD32(ADD32(ADD32(a, b), c), d) +#define ADD5_32(a, b, c, d, e) ADD32(ADD32(ADD32(ADD32(a, b), c), d), e) + +#define MAJ_AVX(a, b, c) XOR3(AND(a, b), AND(a, c), AND(b, c)) +#define CH_AVX(a, b, c) XOR(AND(a, b), AND(NOT(a), c)) + +#define SIGMA1_AVX(x) XOR3(ROTR32(x, 6), ROTR32(x, 11), ROTR32(x, 25)) +#define SIGMA0_AVX(x) XOR3(ROTR32(x, 2), ROTR32(x, 13), ROTR32(x, 22)) + +#define WSIGMA1_AVX(x) XOR3(ROTR32(x, 17), ROTR32(x, 19), SHIFTR32(x, 10)) +#define WSIGMA0_AVX(x) XOR3(ROTR32(x, 7), ROTR32(x, 18), SHIFTR32(x, 3)) + +#define SHA256ROUND_AVX(a, b, c, d, e, f, g, h, rc, w) \ + T0 = ADD5_32(h, SIGMA1_AVX(e), CH_AVX(e, f, g), _mm256_set1_epi32((int)RC[rc]), w); \ + (d) = ADD32(d, T0); \ + T1 = ADD32(SIGMA0_AVX(a), MAJ_AVX(a, b, c)); \ + (h) = ADD32(T0, T1); + +// Transpose 8 vectors containing 32-bit values +static void transpose(u256 s[8]) { + u256 tmp0[8]; + u256 tmp1[8]; + tmp0[0] = _mm256_unpacklo_epi32(s[0], s[1]); + tmp0[1] = _mm256_unpackhi_epi32(s[0], s[1]); + tmp0[2] = _mm256_unpacklo_epi32(s[2], s[3]); + tmp0[3] = _mm256_unpackhi_epi32(s[2], s[3]); + tmp0[4] = _mm256_unpacklo_epi32(s[4], s[5]); + tmp0[5] = _mm256_unpackhi_epi32(s[4], s[5]); + tmp0[6] = _mm256_unpacklo_epi32(s[6], s[7]); + tmp0[7] = _mm256_unpackhi_epi32(s[6], s[7]); + tmp1[0] = _mm256_unpacklo_epi64(tmp0[0], tmp0[2]); + tmp1[1] = _mm256_unpackhi_epi64(tmp0[0], tmp0[2]); + tmp1[2] = _mm256_unpacklo_epi64(tmp0[1], tmp0[3]); + tmp1[3] = _mm256_unpackhi_epi64(tmp0[1], tmp0[3]); + tmp1[4] = _mm256_unpacklo_epi64(tmp0[4], tmp0[6]); + tmp1[5] = _mm256_unpackhi_epi64(tmp0[4], tmp0[6]); + tmp1[6] = _mm256_unpacklo_epi64(tmp0[5], tmp0[7]); + tmp1[7] = _mm256_unpackhi_epi64(tmp0[5], tmp0[7]); + s[0] = _mm256_permute2x128_si256(tmp1[0], tmp1[4], 0x20); + s[1] = _mm256_permute2x128_si256(tmp1[1], tmp1[5], 0x20); + s[2] = _mm256_permute2x128_si256(tmp1[2], tmp1[6], 0x20); + s[3] = _mm256_permute2x128_si256(tmp1[3], tmp1[7], 0x20); + s[4] = _mm256_permute2x128_si256(tmp1[0], tmp1[4], 0x31); + s[5] = _mm256_permute2x128_si256(tmp1[1], tmp1[5], 0x31); + s[6] = _mm256_permute2x128_si256(tmp1[2], tmp1[6], 0x31); + s[7] = _mm256_permute2x128_si256(tmp1[3], tmp1[7], 0x31); +} + +void sha256_ctx_clone8x(sha256x8ctx *out, const sha256x8ctx *in) { + memcpy(out, in, sizeof(sha256x8ctx)); +} + +void sha256_init8x(sha256x8ctx *ctx) { + ctx->s[0] = _mm256_set_epi32((int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667); + ctx->s[1] = _mm256_set_epi32((int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85); + ctx->s[2] = _mm256_set_epi32((int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372); + ctx->s[3] = _mm256_set_epi32((int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a); + ctx->s[4] = _mm256_set_epi32((int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f); + ctx->s[5] = _mm256_set_epi32((int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c); + ctx->s[6] = _mm256_set_epi32((int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab); + ctx->s[7] = _mm256_set_epi32((int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19); + + ctx->datalen = 0; + ctx->msglen = 0; +} + +void sha256_final8x(sha256x8ctx *ctx, + unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7) { + unsigned int i, curlen; + + // Padding + if (ctx->datalen < 56) { + for (i = 0; i < 8; ++i) { + curlen = ctx->datalen; + ctx->msgblocks[64 * i + curlen++] = 0x80; + while (curlen < 64) { + ctx->msgblocks[64 * i + curlen++] = 0x00; + } + } + } else { + for (i = 0; i < 8; ++i) { + curlen = ctx->datalen; + ctx->msgblocks[64 * i + curlen++] = 0x80; + while (curlen < 64) { + ctx->msgblocks[64 * i + curlen++] = 0x00; + } + } + sha256_transform8x(ctx, + &ctx->msgblocks[64 * 0], + &ctx->msgblocks[64 * 1], + &ctx->msgblocks[64 * 2], + &ctx->msgblocks[64 * 3], + &ctx->msgblocks[64 * 4], + &ctx->msgblocks[64 * 5], + &ctx->msgblocks[64 * 6], + &ctx->msgblocks[64 * 7] + ); + memset(ctx->msgblocks, 0, 8 * 64); + } + + // Add length of the message to each block + ctx->msglen += ctx->datalen * 8; + for (i = 0; i < 8; i++) { + ctx->msgblocks[64 * i + 63] = (unsigned char)(ctx->msglen); + ctx->msgblocks[64 * i + 62] = (unsigned char)(ctx->msglen >> 8); + ctx->msgblocks[64 * i + 61] = (unsigned char)(ctx->msglen >> 16); + ctx->msgblocks[64 * i + 60] = (unsigned char)(ctx->msglen >> 24); + ctx->msgblocks[64 * i + 59] = (unsigned char)(ctx->msglen >> 32); + ctx->msgblocks[64 * i + 58] = (unsigned char)(ctx->msglen >> 40); + ctx->msgblocks[64 * i + 57] = (unsigned char)(ctx->msglen >> 48); + ctx->msgblocks[64 * i + 56] = (unsigned char)(ctx->msglen >> 56); + } + sha256_transform8x(ctx, + &ctx->msgblocks[64 * 0], + &ctx->msgblocks[64 * 1], + &ctx->msgblocks[64 * 2], + &ctx->msgblocks[64 * 3], + &ctx->msgblocks[64 * 4], + &ctx->msgblocks[64 * 5], + &ctx->msgblocks[64 * 6], + &ctx->msgblocks[64 * 7] + ); + + // Compute final hash output + transpose(ctx->s); + + // Store Hash value + STORE(out0, BYTESWAP(ctx->s[0])); + STORE(out1, BYTESWAP(ctx->s[1])); + STORE(out2, BYTESWAP(ctx->s[2])); + STORE(out3, BYTESWAP(ctx->s[3])); + STORE(out4, BYTESWAP(ctx->s[4])); + STORE(out5, BYTESWAP(ctx->s[5])); + STORE(out6, BYTESWAP(ctx->s[6])); + STORE(out7, BYTESWAP(ctx->s[7])); +} + +void sha256_transform8x(sha256x8ctx *ctx, + const unsigned char *data0, + const unsigned char *data1, + const unsigned char *data2, + const unsigned char *data3, + const unsigned char *data4, + const unsigned char *data5, + const unsigned char *data6, + const unsigned char *data7) { + u256 s[8], w[64], T0, T1; + + // Load words and transform data correctly + w[0] = BYTESWAP(LOAD(data0)); + w[0 + 8] = BYTESWAP(LOAD(data0 + 32)); + w[1] = BYTESWAP(LOAD(data1)); + w[1 + 8] = BYTESWAP(LOAD(data1 + 32)); + w[2] = BYTESWAP(LOAD(data2)); + w[2 + 8] = BYTESWAP(LOAD(data2 + 32)); + w[3] = BYTESWAP(LOAD(data3)); + w[3 + 8] = BYTESWAP(LOAD(data3 + 32)); + w[4] = BYTESWAP(LOAD(data4)); + w[4 + 8] = BYTESWAP(LOAD(data4 + 32)); + w[5] = BYTESWAP(LOAD(data5)); + w[5 + 8] = BYTESWAP(LOAD(data5 + 32)); + w[6] = BYTESWAP(LOAD(data6)); + w[6 + 8] = BYTESWAP(LOAD(data6 + 32)); + w[7] = BYTESWAP(LOAD(data7)); + w[7 + 8] = BYTESWAP(LOAD(data7 + 32)); + + transpose(w); + transpose(w + 8); + + // Initial State + s[0] = ctx->s[0]; + s[1] = ctx->s[1]; + s[2] = ctx->s[2]; + s[3] = ctx->s[3]; + s[4] = ctx->s[4]; + s[5] = ctx->s[5]; + s[6] = ctx->s[6]; + s[7] = ctx->s[7]; + + SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 0, w[0]); + SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 1, w[1]); + SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 2, w[2]); + SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 3, w[3]); + SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 4, w[4]); + SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 5, w[5]); + SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 6, w[6]); + SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 7, w[7]); + SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 8, w[8]); + SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 9, w[9]); + SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 10, w[10]); + SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 11, w[11]); + SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 12, w[12]); + SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 13, w[13]); + SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 14, w[14]); + SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 15, w[15]); + w[16] = ADD4_32(WSIGMA1_AVX(w[14]), w[0], w[9], WSIGMA0_AVX(w[1])); + SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 16, w[16]); + w[17] = ADD4_32(WSIGMA1_AVX(w[15]), w[1], w[10], WSIGMA0_AVX(w[2])); + SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 17, w[17]); + w[18] = ADD4_32(WSIGMA1_AVX(w[16]), w[2], w[11], WSIGMA0_AVX(w[3])); + SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 18, w[18]); + w[19] = ADD4_32(WSIGMA1_AVX(w[17]), w[3], w[12], WSIGMA0_AVX(w[4])); + SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 19, w[19]); + w[20] = ADD4_32(WSIGMA1_AVX(w[18]), w[4], w[13], WSIGMA0_AVX(w[5])); + SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 20, w[20]); + w[21] = ADD4_32(WSIGMA1_AVX(w[19]), w[5], w[14], WSIGMA0_AVX(w[6])); + SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 21, w[21]); + w[22] = ADD4_32(WSIGMA1_AVX(w[20]), w[6], w[15], WSIGMA0_AVX(w[7])); + SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 22, w[22]); + w[23] = ADD4_32(WSIGMA1_AVX(w[21]), w[7], w[16], WSIGMA0_AVX(w[8])); + SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 23, w[23]); + w[24] = ADD4_32(WSIGMA1_AVX(w[22]), w[8], w[17], WSIGMA0_AVX(w[9])); + SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 24, w[24]); + w[25] = ADD4_32(WSIGMA1_AVX(w[23]), w[9], w[18], WSIGMA0_AVX(w[10])); + SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 25, w[25]); + w[26] = ADD4_32(WSIGMA1_AVX(w[24]), w[10], w[19], WSIGMA0_AVX(w[11])); + SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 26, w[26]); + w[27] = ADD4_32(WSIGMA1_AVX(w[25]), w[11], w[20], WSIGMA0_AVX(w[12])); + SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 27, w[27]); + w[28] = ADD4_32(WSIGMA1_AVX(w[26]), w[12], w[21], WSIGMA0_AVX(w[13])); + SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 28, w[28]); + w[29] = ADD4_32(WSIGMA1_AVX(w[27]), w[13], w[22], WSIGMA0_AVX(w[14])); + SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 29, w[29]); + w[30] = ADD4_32(WSIGMA1_AVX(w[28]), w[14], w[23], WSIGMA0_AVX(w[15])); + SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 30, w[30]); + w[31] = ADD4_32(WSIGMA1_AVX(w[29]), w[15], w[24], WSIGMA0_AVX(w[16])); + SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 31, w[31]); + w[32] = ADD4_32(WSIGMA1_AVX(w[30]), w[16], w[25], WSIGMA0_AVX(w[17])); + SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 32, w[32]); + w[33] = ADD4_32(WSIGMA1_AVX(w[31]), w[17], w[26], WSIGMA0_AVX(w[18])); + SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 33, w[33]); + w[34] = ADD4_32(WSIGMA1_AVX(w[32]), w[18], w[27], WSIGMA0_AVX(w[19])); + SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 34, w[34]); + w[35] = ADD4_32(WSIGMA1_AVX(w[33]), w[19], w[28], WSIGMA0_AVX(w[20])); + SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 35, w[35]); + w[36] = ADD4_32(WSIGMA1_AVX(w[34]), w[20], w[29], WSIGMA0_AVX(w[21])); + SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 36, w[36]); + w[37] = ADD4_32(WSIGMA1_AVX(w[35]), w[21], w[30], WSIGMA0_AVX(w[22])); + SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 37, w[37]); + w[38] = ADD4_32(WSIGMA1_AVX(w[36]), w[22], w[31], WSIGMA0_AVX(w[23])); + SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 38, w[38]); + w[39] = ADD4_32(WSIGMA1_AVX(w[37]), w[23], w[32], WSIGMA0_AVX(w[24])); + SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 39, w[39]); + w[40] = ADD4_32(WSIGMA1_AVX(w[38]), w[24], w[33], WSIGMA0_AVX(w[25])); + SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 40, w[40]); + w[41] = ADD4_32(WSIGMA1_AVX(w[39]), w[25], w[34], WSIGMA0_AVX(w[26])); + SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 41, w[41]); + w[42] = ADD4_32(WSIGMA1_AVX(w[40]), w[26], w[35], WSIGMA0_AVX(w[27])); + SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 42, w[42]); + w[43] = ADD4_32(WSIGMA1_AVX(w[41]), w[27], w[36], WSIGMA0_AVX(w[28])); + SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 43, w[43]); + w[44] = ADD4_32(WSIGMA1_AVX(w[42]), w[28], w[37], WSIGMA0_AVX(w[29])); + SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 44, w[44]); + w[45] = ADD4_32(WSIGMA1_AVX(w[43]), w[29], w[38], WSIGMA0_AVX(w[30])); + SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 45, w[45]); + w[46] = ADD4_32(WSIGMA1_AVX(w[44]), w[30], w[39], WSIGMA0_AVX(w[31])); + SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 46, w[46]); + w[47] = ADD4_32(WSIGMA1_AVX(w[45]), w[31], w[40], WSIGMA0_AVX(w[32])); + SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 47, w[47]); + w[48] = ADD4_32(WSIGMA1_AVX(w[46]), w[32], w[41], WSIGMA0_AVX(w[33])); + SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 48, w[48]); + w[49] = ADD4_32(WSIGMA1_AVX(w[47]), w[33], w[42], WSIGMA0_AVX(w[34])); + SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 49, w[49]); + w[50] = ADD4_32(WSIGMA1_AVX(w[48]), w[34], w[43], WSIGMA0_AVX(w[35])); + SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 50, w[50]); + w[51] = ADD4_32(WSIGMA1_AVX(w[49]), w[35], w[44], WSIGMA0_AVX(w[36])); + SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 51, w[51]); + w[52] = ADD4_32(WSIGMA1_AVX(w[50]), w[36], w[45], WSIGMA0_AVX(w[37])); + SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 52, w[52]); + w[53] = ADD4_32(WSIGMA1_AVX(w[51]), w[37], w[46], WSIGMA0_AVX(w[38])); + SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 53, w[53]); + w[54] = ADD4_32(WSIGMA1_AVX(w[52]), w[38], w[47], WSIGMA0_AVX(w[39])); + SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 54, w[54]); + w[55] = ADD4_32(WSIGMA1_AVX(w[53]), w[39], w[48], WSIGMA0_AVX(w[40])); + SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 55, w[55]); + w[56] = ADD4_32(WSIGMA1_AVX(w[54]), w[40], w[49], WSIGMA0_AVX(w[41])); + SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 56, w[56]); + w[57] = ADD4_32(WSIGMA1_AVX(w[55]), w[41], w[50], WSIGMA0_AVX(w[42])); + SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 57, w[57]); + w[58] = ADD4_32(WSIGMA1_AVX(w[56]), w[42], w[51], WSIGMA0_AVX(w[43])); + SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 58, w[58]); + w[59] = ADD4_32(WSIGMA1_AVX(w[57]), w[43], w[52], WSIGMA0_AVX(w[44])); + SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 59, w[59]); + w[60] = ADD4_32(WSIGMA1_AVX(w[58]), w[44], w[53], WSIGMA0_AVX(w[45])); + SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 60, w[60]); + w[61] = ADD4_32(WSIGMA1_AVX(w[59]), w[45], w[54], WSIGMA0_AVX(w[46])); + SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 61, w[61]); + w[62] = ADD4_32(WSIGMA1_AVX(w[60]), w[46], w[55], WSIGMA0_AVX(w[47])); + SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 62, w[62]); + w[63] = ADD4_32(WSIGMA1_AVX(w[61]), w[47], w[56], WSIGMA0_AVX(w[48])); + SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 63, w[63]); + + // Feed Forward + ctx->s[0] = ADD32(s[0], ctx->s[0]); + ctx->s[1] = ADD32(s[1], ctx->s[1]); + ctx->s[2] = ADD32(s[2], ctx->s[2]); + ctx->s[3] = ADD32(s[3], ctx->s[3]); + ctx->s[4] = ADD32(s[4], ctx->s[4]); + ctx->s[5] = ADD32(s[5], ctx->s[5]); + ctx->s[6] = ADD32(s[6], ctx->s[6]); + ctx->s[7] = ADD32(s[7], ctx->s[7]); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/sha256avx.h b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/sha256avx.h new file mode 100644 index 0000000000..1e3bcf889b --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/sha256avx.h @@ -0,0 +1,44 @@ +#ifndef SHA256AVX_H +#define SHA256AVX_H + +#include +#include + +#include "params.h" + +typedef struct SHA256state { + __m256i s[8]; + unsigned char msgblocks[8 * 64]; + unsigned int datalen; + unsigned long long msglen; +} sha256x8ctx; + +#define sha256_ctx_clone8x SPX_NAMESPACE(sha256_ctx_clone8x) +void sha256_ctx_clone8x(sha256x8ctx *out, const sha256x8ctx *in); + +#define sha256_init8x SPX_NAMESPACE(sha256_init8x) +void sha256_init8x(sha256x8ctx *ctx); + +#define sha256_final8x SPX_NAMESPACE(sha256_final8x) +void sha256_final8x(sha256x8ctx *ctx, + unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7); + +#define sha256_transform8x SPX_NAMESPACE(sha256_transform8x) +void sha256_transform8x(sha256x8ctx *ctx, + const unsigned char *data0, + const unsigned char *data1, + const unsigned char *data2, + const unsigned char *data3, + const unsigned char *data4, + const unsigned char *data5, + const unsigned char *data6, + const unsigned char *data7); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/sha256x8.c b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/sha256x8.c new file mode 100644 index 0000000000..d97750c09b --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/sha256x8.c @@ -0,0 +1,185 @@ +#include + +#include "sha256avx.h" +#include "sha256x8.h" +#include "utils.h" + +// Performs sha256x8 on an initialized (and perhaps seeded) state. +static void _sha256x8( + sha256x8ctx *ctx, + unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, unsigned long long inlen) { + unsigned long long i = 0; + while (inlen - i >= 64) { + sha256_transform8x(ctx, + in0 + i, + in1 + i, + in2 + i, + in3 + i, + in4 + i, + in5 + i, + in6 + i, + in7 + i + ); + i += 64; + ctx->msglen += 512; + } + + size_t bytes_to_copy = (size_t)(inlen - i); + memcpy(&ctx->msgblocks[64 * 0], in0 + i, bytes_to_copy); + memcpy(&ctx->msgblocks[64 * 1], in1 + i, bytes_to_copy); + memcpy(&ctx->msgblocks[64 * 2], in2 + i, bytes_to_copy); + memcpy(&ctx->msgblocks[64 * 3], in3 + i, bytes_to_copy); + memcpy(&ctx->msgblocks[64 * 4], in4 + i, bytes_to_copy); + memcpy(&ctx->msgblocks[64 * 5], in5 + i, bytes_to_copy); + memcpy(&ctx->msgblocks[64 * 6], in6 + i, bytes_to_copy); + memcpy(&ctx->msgblocks[64 * 7], in7 + i, bytes_to_copy); + ctx->datalen = (unsigned int)bytes_to_copy; + + sha256_final8x(ctx, out0, out1, out2, out3, out4, out5, out6, out7); +} + +void sha256x8_seeded( + unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const sha256x8ctx *seed, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, unsigned long long inlen) { + + sha256x8ctx ctx; + sha256_ctx_clone8x(&ctx, seed); + + _sha256x8(&ctx, out0, out1, out2, out3, out4, out5, out6, out7, + in0, in1, in2, in3, in4, in5, in6, in7, inlen); +} + +/* This provides a wrapper around the internals of 8x parallel SHA256 */ +void sha256x8(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, unsigned long long inlen) { + sha256x8ctx ctx; + sha256_init8x(&ctx); + + _sha256x8(&ctx, out0, out1, out2, out3, out4, out5, out6, out7, + in0, in1, in2, in3, in4, in5, in6, in7, inlen); +} + +/** + * Note that inlen should be sufficiently small that it still allows for + * an array to be allocated on the stack. Typically 'in' is merely a seed. + * Outputs outlen number of bytes + */ +void mgf1x8(unsigned char *outx8, unsigned long outlen, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, + unsigned long inlen) { + PQCLEAN_VLA(unsigned char, inbufx8, 8 * (inlen + 4)); + unsigned char outbufx8[8 * SPX_SHA256_OUTPUT_BYTES]; + uint32_t i; + unsigned int j; + + memcpy(inbufx8 + 0 * (inlen + 4), in0, inlen); + memcpy(inbufx8 + 1 * (inlen + 4), in1, inlen); + memcpy(inbufx8 + 2 * (inlen + 4), in2, inlen); + memcpy(inbufx8 + 3 * (inlen + 4), in3, inlen); + memcpy(inbufx8 + 4 * (inlen + 4), in4, inlen); + memcpy(inbufx8 + 5 * (inlen + 4), in5, inlen); + memcpy(inbufx8 + 6 * (inlen + 4), in6, inlen); + memcpy(inbufx8 + 7 * (inlen + 4), in7, inlen); + + /* While we can fit in at least another full block of SHA256 output.. */ + for (i = 0; (i + 1)*SPX_SHA256_OUTPUT_BYTES <= outlen; i++) { + for (j = 0; j < 8; j++) { + u32_to_bytes(inbufx8 + inlen + j * (inlen + 4), i); + } + + sha256x8(outx8 + 0 * outlen, + outx8 + 1 * outlen, + outx8 + 2 * outlen, + outx8 + 3 * outlen, + outx8 + 4 * outlen, + outx8 + 5 * outlen, + outx8 + 6 * outlen, + outx8 + 7 * outlen, + inbufx8 + 0 * (inlen + 4), + inbufx8 + 1 * (inlen + 4), + inbufx8 + 2 * (inlen + 4), + inbufx8 + 3 * (inlen + 4), + inbufx8 + 4 * (inlen + 4), + inbufx8 + 5 * (inlen + 4), + inbufx8 + 6 * (inlen + 4), + inbufx8 + 7 * (inlen + 4), inlen + 4); + outx8 += SPX_SHA256_OUTPUT_BYTES; + } + /* Until we cannot anymore, and we fill the remainder. */ + for (j = 0; j < 8; j++) { + u32_to_bytes(inbufx8 + inlen + j * (inlen + 4), i); + } + sha256x8(outbufx8 + 0 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 1 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 2 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 3 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 4 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 5 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 6 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 7 * SPX_SHA256_OUTPUT_BYTES, + inbufx8 + 0 * (inlen + 4), + inbufx8 + 1 * (inlen + 4), + inbufx8 + 2 * (inlen + 4), + inbufx8 + 3 * (inlen + 4), + inbufx8 + 4 * (inlen + 4), + inbufx8 + 5 * (inlen + 4), + inbufx8 + 6 * (inlen + 4), + inbufx8 + 7 * (inlen + 4), inlen + 4); + + for (j = 0; j < 8; j++) { + memcpy(outx8 + j * outlen, + outbufx8 + j * SPX_SHA256_OUTPUT_BYTES, + outlen - i * SPX_SHA256_OUTPUT_BYTES); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/sha256x8.h b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/sha256x8.h new file mode 100644 index 0000000000..4f7330a6c1 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/sha256x8.h @@ -0,0 +1,64 @@ +#ifndef SPX_SHA256X8_H +#define SPX_SHA256X8_H + +#include "params.h" +#include "sha256avx.h" + + + +#define sha256x8_seeded SPX_NAMESPACE(sha256x8_seeded) +void sha256x8_seeded( + unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const sha256x8ctx *seed, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, unsigned long long inlen); + +/* This provides a wrapper around the internals of 8x parallel SHA256 */ +#define sha256x8 SPX_NAMESPACE(sha256x8) +void sha256x8(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, unsigned long long inlen); + +/** + * Note that inlen should be sufficiently small that it still allows for + * an array to be allocated on the stack. Typically 'in' is merely a seed. + * Outputs outlen number of bytes + */ +#define mgf1x8 SPX_NAMESPACE(mgf1x8) +void mgf1x8(unsigned char *outx8, unsigned long outlen, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, + unsigned long inlen); +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/sha2_offsets.h b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/sha2_offsets.h new file mode 100644 index 0000000000..6e3584f7a4 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/sha2_offsets.h @@ -0,0 +1,27 @@ +#ifndef SHA2_OFFSETS_H_ +#define SHA2_OFFSETS_H_ + +#define SPX_SHA256_BLOCK_BYTES 64 +#define SPX_SHA256_OUTPUT_BYTES 32 + +#define SPX_SHA512_BLOCK_BYTES 128 +#define SPX_SHA512_OUTPUT_BYTES 64 + +/* + * Offsets of various fields in the address structure when we use SHA2 as + * the Sphincs+ hash function + */ + +#define SPX_OFFSET_LAYER 0 /* The byte used to specify the Merkle tree layer */ +#define SPX_OFFSET_TREE 1 /* The start of the 8 byte field used to specify the tree */ +#define SPX_OFFSET_TYPE 9 /* The byte used to specify the hash type (reason) */ +#define SPX_OFFSET_KP_ADDR2 12 /* The high byte used to specify the key pair (which one-time signature) */ +#define SPX_OFFSET_KP_ADDR1 13 /* The low byte used to specify the key pair */ +#define SPX_OFFSET_CHAIN_ADDR 17 /* The byte used to specify the chain address (which Winternitz chain) */ +#define SPX_OFFSET_HASH_ADDR 21 /* The byte used to specify the hash address (where in the Winternitz chain) */ +#define SPX_OFFSET_TREE_HGT 17 /* The byte used to specify the height of this node in the FORS or Merkle tree */ +#define SPX_OFFSET_TREE_INDEX 18 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ + +#define SPX_SHA2 1 + +#endif /* SHA2_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/sha512x4.c b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/sha512x4.c new file mode 100644 index 0000000000..8d33deffdd --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/sha512x4.c @@ -0,0 +1,446 @@ +#include +#include +#include + +/* pull in the entire thing */ +#include "sha512x4.h" +#include "utils.h" + +typedef uint64_t u64; +typedef __m256i u256; + +#define BYTESWAP(x) _mm256_shuffle_epi8(x, _mm256_set_epi8(0x8,0x9,0xa,0xb,0xc,0xd,0xe,0xf,0x0,0x1,0x2,0x3,0x4,0x5,0x6,0x7,0x8,0x9,0xa,0xb,0xc,0xd,0xe,0xf,0x0,0x1,0x2,0x3,0x4,0x5,0x6,0x7)) +#define STORE(dest,src) _mm256_storeu_si256((__m256i *)(dest),src) + +// Transpose 4 vectors containing 64-bit values +// That is, it rearranges the array: +// A B C D +// E F G H +// I J K L +// M N O P +// into +// A E I M +// B F J N +// C G K O +// D H L P +// where each letter stands for 64 bits (and lsbits on the left) +static void transpose(u256 s[4]) { + u256 tmp[4]; + tmp[0] = _mm256_unpacklo_epi64(s[0], s[1]); + tmp[1] = _mm256_unpackhi_epi64(s[0], s[1]); + tmp[2] = _mm256_unpacklo_epi64(s[2], s[3]); + tmp[3] = _mm256_unpackhi_epi64(s[2], s[3]); + // tmp is in the order of + // A E C G + // B F D H + // I M K O + // J N L P + s[0] = _mm256_permute2x128_si256(tmp[0], tmp[2], 0x20); + s[1] = _mm256_permute2x128_si256(tmp[1], tmp[3], 0x20); + s[2] = _mm256_permute2x128_si256(tmp[0], tmp[2], 0x31); + s[3] = _mm256_permute2x128_si256(tmp[1], tmp[3], 0x31); +} + + +void sha512_init4x(sha512x4ctx *ctx) { +#define SET4(x) _mm256_set_epi64x((long long)(x), (long long)(x), (long long)(x), (long long)(x)) + ctx->s[0] = SET4(0x6a09e667f3bcc908ULL); + ctx->s[1] = SET4(0xbb67ae8584caa73bULL); + ctx->s[2] = SET4(0x3c6ef372fe94f82bULL); + ctx->s[3] = SET4(0xa54ff53a5f1d36f1ULL); + ctx->s[4] = SET4(0x510e527fade682d1ULL); + ctx->s[5] = SET4(0x9b05688c2b3e6c1fULL); + ctx->s[6] = SET4(0x1f83d9abfb41bd6bULL); + ctx->s[7] = SET4(0x5be0cd19137e2179ULL); +#undef SET4 + + ctx->datalen = 0; + ctx->msglen = 0; +} + +#define XOR _mm256_xor_si256 +#define OR _mm256_or_si256 +#define AND _mm256_and_si256 +#define ADD64 _mm256_add_epi64 + +#define LOAD(src) _mm256_loadu_si256((__m256i *)(src)) + +#define SHIFTR64(x, y) _mm256_srli_epi64(x, y) +#define SHIFTL64(x, y) _mm256_slli_epi64(x, y) + +#define ROTR64(x, y) OR(SHIFTR64(x, y), SHIFTL64(x, 64 - (y))) + +static u256 XOR3(u256 a, u256 b, u256 c) { + return XOR(XOR(a, b), c); +} + +#define ADD3_64(a, b, c) ADD64(ADD64(a, b), c) +#define ADD4_64(a, b, c, d) ADD64(ADD64(ADD64(a, b), c), d) +#define ADD5_64(a, b, c, d, e) ADD64(ADD64(ADD64(ADD64(a, b), c), d), e) + +static u256 MAJ_AVX(u256 a, u256 b, u256 c) { + return XOR(c, AND(XOR(a, c), XOR(b, c))); +} +static u256 CH_AVX(u256 a, u256 b, u256 c) { + return XOR(c, AND(a, XOR(b, c))); +} +static u256 SIGMA0_AVX(u256 x) { + return XOR3(ROTR64(x, 28), ROTR64(x, 34), ROTR64(x, 39)); +} +static u256 SIGMA1_AVX(u256 x) { + return XOR3(ROTR64(x, 14), ROTR64(x, 18), ROTR64(x, 41)); +} +static u256 GAMMA0_AVX(u256 x) { + return XOR3(ROTR64(x, 1), ROTR64(x, 8), SHIFTR64(x, 7)); +} +static u256 GAMMA1_AVX(u256 x) { + return XOR3(ROTR64(x, 19), ROTR64(x, 61), SHIFTR64(x, 6)); +} + +#define SHA512ROUND_AVX(a, b, c, d, e, f, g, h, rc, w) \ + T0 = ADD5_64(h, w, SIGMA1_AVX(e), CH_AVX(e, f, g), _mm256_set1_epi64x((long long)RC[rc])); \ + T1 = ADD64(SIGMA0_AVX(a), MAJ_AVX(a, b, c)); \ + (d) = ADD64(d, T0); \ + (h) = ADD64(T0, T1); + +static const unsigned long long RC[80] = { + 0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL, + 0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL, + 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL, + 0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL, + 0xd807aa98a3030242ULL, 0x12835b0145706fbeULL, + 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL, + 0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL, + 0x9bdc06a725c71235ULL, 0xc19bf174cf692694ULL, + 0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL, + 0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL, + 0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL, + 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL, + 0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL, + 0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL, + 0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL, + 0x06ca6351e003826fULL, 0x142929670a0e6e70ULL, + 0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL, + 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL, + 0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL, + 0x81c2c92e47edaee6ULL, 0x92722c851482353bULL, + 0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL, + 0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL, + 0xd192e819d6ef5218ULL, 0xd69906245565a910ULL, + 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL, + 0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL, + 0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL, + 0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL, + 0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL, + 0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL, + 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL, + 0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL, + 0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL, + 0xca273eceea26619cULL, 0xd186b8c721c0c207ULL, + 0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL, + 0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL, + 0x113f9804bef90daeULL, 0x1b710b35131c471bULL, + 0x28db77f523047d84ULL, 0x32caab7b40c72493ULL, + 0x3c9ebe0a15c9bebcULL, 0x431d67c49c100d4cULL, + 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL, + 0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL, +}; + +void sha512_transform4x( + sha512x4ctx *ctx, + const unsigned char *d0, + const unsigned char *d1, + const unsigned char *d2, + const unsigned char *d3) { + u256 s0, s1, s2, s3, s4, s5, s6, s7, w[16], T0, T1, nw; + + // Load words and transform data correctly + w[0 ] = BYTESWAP(LOAD(d0 )); + w[0 + 4] = BYTESWAP(LOAD(d0 + 32)); + w[0 + 8] = BYTESWAP(LOAD(d0 + 64)); + w[0 + 12] = BYTESWAP(LOAD(d0 + 96)); + + w[1 ] = BYTESWAP(LOAD(d1 )); + w[1 + 4] = BYTESWAP(LOAD(d1 + 32)); + w[1 + 8] = BYTESWAP(LOAD(d1 + 64)); + w[1 + 12] = BYTESWAP(LOAD(d1 + 96)); + + w[2 ] = BYTESWAP(LOAD(d2 )); + w[2 + 4] = BYTESWAP(LOAD(d2 + 32)); + w[2 + 8] = BYTESWAP(LOAD(d2 + 64)); + w[2 + 12] = BYTESWAP(LOAD(d2 + 96)); + + w[3 ] = BYTESWAP(LOAD(d3 )); + w[3 + 4] = BYTESWAP(LOAD(d3 + 32)); + w[3 + 8] = BYTESWAP(LOAD(d3 + 64)); + w[3 + 12] = BYTESWAP(LOAD(d3 + 96)); + + transpose(w); + transpose(w + 4); + transpose(w + 8); + transpose(w + 12); + + // Initial State + s0 = ctx->s[0]; + s1 = ctx->s[1]; + s2 = ctx->s[2]; + s3 = ctx->s[3]; + s4 = ctx->s[4]; + s5 = ctx->s[5]; + s6 = ctx->s[6]; + s7 = ctx->s[7]; + + // The first 16 rounds (where the w inputs are directly from the data) + SHA512ROUND_AVX(s0, s1, s2, s3, s4, s5, s6, s7, 0, w[0]); + SHA512ROUND_AVX(s7, s0, s1, s2, s3, s4, s5, s6, 1, w[1]); + SHA512ROUND_AVX(s6, s7, s0, s1, s2, s3, s4, s5, 2, w[2]); + SHA512ROUND_AVX(s5, s6, s7, s0, s1, s2, s3, s4, 3, w[3]); + SHA512ROUND_AVX(s4, s5, s6, s7, s0, s1, s2, s3, 4, w[4]); + SHA512ROUND_AVX(s3, s4, s5, s6, s7, s0, s1, s2, 5, w[5]); + SHA512ROUND_AVX(s2, s3, s4, s5, s6, s7, s0, s1, 6, w[6]); + SHA512ROUND_AVX(s1, s2, s3, s4, s5, s6, s7, s0, 7, w[7]); + SHA512ROUND_AVX(s0, s1, s2, s3, s4, s5, s6, s7, 8, w[8]); + SHA512ROUND_AVX(s7, s0, s1, s2, s3, s4, s5, s6, 9, w[9]); + SHA512ROUND_AVX(s6, s7, s0, s1, s2, s3, s4, s5, 10, w[10]); + SHA512ROUND_AVX(s5, s6, s7, s0, s1, s2, s3, s4, 11, w[11]); + SHA512ROUND_AVX(s4, s5, s6, s7, s0, s1, s2, s3, 12, w[12]); + SHA512ROUND_AVX(s3, s4, s5, s6, s7, s0, s1, s2, 13, w[13]); + SHA512ROUND_AVX(s2, s3, s4, s5, s6, s7, s0, s1, 14, w[14]); + SHA512ROUND_AVX(s1, s2, s3, s4, s5, s6, s7, s0, 15, w[15]); + +#define M(i) (((i)+16) & 0xf) +#define NextW(i) \ + w[M(i)] = ADD4_64(GAMMA1_AVX(w[M((i)-2)]), w[M((i)-7)], GAMMA0_AVX(w[M((i)-15)]), w[M((i)-16)]); + + // The remaining 64 rounds (where the w inputs are a linear fix of the data) + for (unsigned i = 16; i < 80; i += 16) { + nw = NextW(0); + SHA512ROUND_AVX(s0, s1, s2, s3, s4, s5, s6, s7, i + 0, nw); + nw = NextW(1); + SHA512ROUND_AVX(s7, s0, s1, s2, s3, s4, s5, s6, i + 1, nw); + nw = NextW(2); + SHA512ROUND_AVX(s6, s7, s0, s1, s2, s3, s4, s5, i + 2, nw); + nw = NextW(3); + SHA512ROUND_AVX(s5, s6, s7, s0, s1, s2, s3, s4, i + 3, nw); + nw = NextW(4); + SHA512ROUND_AVX(s4, s5, s6, s7, s0, s1, s2, s3, i + 4, nw); + nw = NextW(5); + SHA512ROUND_AVX(s3, s4, s5, s6, s7, s0, s1, s2, i + 5, nw); + nw = NextW(6); + SHA512ROUND_AVX(s2, s3, s4, s5, s6, s7, s0, s1, i + 6, nw); + nw = NextW(7); + SHA512ROUND_AVX(s1, s2, s3, s4, s5, s6, s7, s0, i + 7, nw); + nw = NextW(8); + SHA512ROUND_AVX(s0, s1, s2, s3, s4, s5, s6, s7, i + 8, nw); + nw = NextW(9); + SHA512ROUND_AVX(s7, s0, s1, s2, s3, s4, s5, s6, i + 9, nw); + nw = NextW(10); + SHA512ROUND_AVX(s6, s7, s0, s1, s2, s3, s4, s5, i + 10, nw); + nw = NextW(11); + SHA512ROUND_AVX(s5, s6, s7, s0, s1, s2, s3, s4, i + 11, nw); + nw = NextW(12); + SHA512ROUND_AVX(s4, s5, s6, s7, s0, s1, s2, s3, i + 12, nw); + nw = NextW(13); + SHA512ROUND_AVX(s3, s4, s5, s6, s7, s0, s1, s2, i + 13, nw); + nw = NextW(14); + SHA512ROUND_AVX(s2, s3, s4, s5, s6, s7, s0, s1, i + 14, nw); + nw = NextW(15); + SHA512ROUND_AVX(s1, s2, s3, s4, s5, s6, s7, s0, i + 15, nw); + } + + // Feed Forward + ctx->s[0] = ADD64(s0, ctx->s[0]); + ctx->s[1] = ADD64(s1, ctx->s[1]); + ctx->s[2] = ADD64(s2, ctx->s[2]); + ctx->s[3] = ADD64(s3, ctx->s[3]); + ctx->s[4] = ADD64(s4, ctx->s[4]); + ctx->s[5] = ADD64(s5, ctx->s[5]); + ctx->s[6] = ADD64(s6, ctx->s[6]); + ctx->s[7] = ADD64(s7, ctx->s[7]); +} + +static void _sha512x4( + sha512x4ctx *ctx, + unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + unsigned long long inlen) { + unsigned int i = 0; + + while (inlen - i >= 128) { + sha512_transform4x( + ctx, + in0 + i, + in1 + i, + in2 + i, + in3 + i + ); + ctx->msglen += 1024; + i += 128; + } + + ctx->datalen = (unsigned int)(inlen - i); + memcpy(&ctx->msgblocks[128 * 0], in0 + i, ctx->datalen); + memcpy(&ctx->msgblocks[128 * 1], in1 + i, ctx->datalen); + memcpy(&ctx->msgblocks[128 * 2], in2 + i, ctx->datalen); + memcpy(&ctx->msgblocks[128 * 3], in3 + i, ctx->datalen); + + // Padding + unsigned long curlen; + if (ctx->datalen < 112) { + for (i = 0; i < 4; ++i) { + curlen = ctx->datalen; + ctx->msgblocks[128 * i + curlen++] = 0x80; + while (curlen < 128) { + ctx->msgblocks[128 * i + curlen++] = 0x00; + } + } + } else { + for (i = 0; i < 4; ++i) { + curlen = ctx->datalen; + ctx->msgblocks[128 * i + curlen++] = 0x80; + while (curlen < 128) { + ctx->msgblocks[128 * i + curlen++] = 0x00; + } + } + sha512_transform4x( + ctx, + ctx->msgblocks, + ctx->msgblocks + 128, + ctx->msgblocks + 256, + ctx->msgblocks + 384 + ); + memset(ctx->msgblocks, 0, 4 * 128); + } + + // Add length of the message to each block + ctx->msglen += (unsigned long long)(ctx->datalen) * 8; + for (i = 0; i < 4; i++) { + ctx->msgblocks[128 * i + 127] = (unsigned char)(ctx->msglen); + ctx->msgblocks[128 * i + 126] = (unsigned char)(ctx->msglen >> 8); + ctx->msgblocks[128 * i + 125] = (unsigned char)(ctx->msglen >> 16); + ctx->msgblocks[128 * i + 124] = (unsigned char)(ctx->msglen >> 24); + ctx->msgblocks[128 * i + 123] = (unsigned char)(ctx->msglen >> 32); + ctx->msgblocks[128 * i + 122] = (unsigned char)(ctx->msglen >> 40); + ctx->msgblocks[128 * i + 121] = (unsigned char)(ctx->msglen >> 48); + ctx->msgblocks[128 * i + 120] = (unsigned char)(ctx->msglen >> 56); + memset( &ctx->msgblocks[128 * i + 112], 0, 8 ); + } + sha512_transform4x( + ctx, + ctx->msgblocks, + ctx->msgblocks + 128, + ctx->msgblocks + 256, + ctx->msgblocks + 384 + ); + + // Compute final hash output + transpose(ctx->s); + transpose(ctx->s + 4); + + // Store Hash value + __m256i out[2]; + STORE(out, BYTESWAP(ctx->s[0])); + STORE(out + 1, BYTESWAP(ctx->s[4])); + memcpy(out0, out, 64); + + STORE(out, BYTESWAP(ctx->s[1])); + STORE(out + 1, BYTESWAP(ctx->s[5])); + memcpy(out1, out, 64); + + STORE(out, BYTESWAP(ctx->s[2])); + STORE(out + 1, BYTESWAP(ctx->s[6])); + memcpy(out2, out, 64); + + STORE(out, BYTESWAP(ctx->s[3])); + STORE(out + 1, BYTESWAP(ctx->s[7])); + memcpy(out3, out, 64); +} + + +/** + * Note that inlen should be sufficiently small that it still allows for + * an array to be allocated on the stack. Typically 'in' is merely a seed. + * Outputs outlen number of bytes + */ +void mgf1x4_512(unsigned char *outx4, unsigned long outlen, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + unsigned long inlen) { + PQCLEAN_VLA(unsigned char, inbufx4, 4 * (inlen + 4)); + unsigned char outbuf[4 * 64]; + uint32_t i; + unsigned int j; + + memcpy(inbufx4 + 0 * (inlen + 4), in0, inlen); + memcpy(inbufx4 + 1 * (inlen + 4), in1, inlen); + memcpy(inbufx4 + 2 * (inlen + 4), in2, inlen); + memcpy(inbufx4 + 3 * (inlen + 4), in3, inlen); + + /* While we can fit in at least another full block of SHA512 output.. */ + unsigned long remaining = outlen; + for (i = 0; remaining > 0; i++) { + unsigned long this_step = SPX_SHA512_OUTPUT_BYTES; + if (this_step > remaining) { + this_step = remaining; + } + remaining -= this_step; + for (j = 0; j < 4; j++) { + u32_to_bytes(inbufx4 + inlen + j * (inlen + 4), i); + } + + sha512x4ctx ctx; + sha512_init4x(&ctx); + + _sha512x4( + &ctx, + outbuf + 0 * 64, + outbuf + 1 * 64, + outbuf + 2 * 64, + outbuf + 3 * 64, + inbufx4 + 0 * (inlen + 4), + inbufx4 + 1 * (inlen + 4), + inbufx4 + 2 * (inlen + 4), + inbufx4 + 3 * (inlen + 4), + inlen + 4 + ); + + memcpy(outx4 + 0 * outlen, outbuf + 0 * 64, this_step); + memcpy(outx4 + 1 * outlen, outbuf + 1 * 64, this_step); + memcpy(outx4 + 2 * outlen, outbuf + 2 * 64, this_step); + memcpy(outx4 + 3 * outlen, outbuf + 3 * 64, this_step); + outx4 += this_step; + } +} + +void sha512x4_seeded( + unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const sha512x4ctx *seed, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + unsigned long long inlen) { + sha512x4ctx ctx; + sha512_ctx_clone4x(&ctx, seed); + _sha512x4( + &ctx, + out0, out1, out2, out3, + in0, in1, in2, in3, + inlen + ); +} + +void sha512_ctx_clone4x(sha512x4ctx *out, const sha512x4ctx *in) { + memcpy(out, in, sizeof(sha512x4ctx)); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/sha512x4.h b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/sha512x4.h new file mode 100644 index 0000000000..9bbe736514 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/sha512x4.h @@ -0,0 +1,58 @@ +#ifndef SHA512AVX_H +#define SHA512AVX_H + +#include +#include + + +#include "params.h" + +typedef struct SHA512state4x { + __m256i s[8]; + unsigned char msgblocks[4 * 128]; + unsigned int datalen; + unsigned long long msglen; +} sha512x4ctx; + +#define sha512_init4x SPX_NAMESPACE(sha512_init4x) +void sha512_init4x(sha512x4ctx *ctx); + +#define sha512_transform4x SPX_NAMESPACE(sha512_transform4x) +void sha512_transform4x( + sha512x4ctx *ctx, + const unsigned char *d0, + const unsigned char *d1, + const unsigned char *d2, + const unsigned char *d3); + + +#define sha512x4_seeded SPX_NAMESPACE(sha512x4_seeded) +void sha512x4_seeded( + unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const sha512x4ctx *seed, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + unsigned long long inlen); + +#define sha512_ctx_clone4x SPX_NAMESPACE(sha512_ctx_clone4x) +void sha512_ctx_clone4x(sha512x4ctx *out, const sha512x4ctx *in); + +/** + * Note that inlen should be sufficiently small that it still allows for + * an array to be allocated on the stack. Typically 'in' is merely a seed. + * Outputs outlen number of bytes + */ +#define mgf1x4_512 SPX_NAMESPACE(mgf1x4_512) +void mgf1x4_512(unsigned char *outx4, unsigned long outlen, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + unsigned long inlen); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/sign.c b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/sign.c new file mode 100644 index 0000000000..9d0c7d1b22 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/sign.c @@ -0,0 +1,286 @@ +#include +#include +#include + +#include "address.h" +#include "context.h" +#include "fors.h" +#include "hash.h" +#include "merkle.h" +#include "nistapi.h" +#include "params.h" +#include "randombytes.h" +#include "thash.h" +#include "utils.h" +#include "wots.h" + +/* + * Returns the length of a secret key, in bytes + */ +size_t crypto_sign_secretkeybytes(void) { + return CRYPTO_SECRETKEYBYTES; +} + +/* + * Returns the length of a public key, in bytes + */ +size_t crypto_sign_publickeybytes(void) { + return CRYPTO_PUBLICKEYBYTES; +} + +/* + * Returns the length of a signature, in bytes + */ +size_t crypto_sign_bytes(void) { + return CRYPTO_BYTES; +} + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +size_t crypto_sign_seedbytes(void) { + return CRYPTO_SEEDBYTES; +} + +/* + * Generates an SPX key pair given a seed of length + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [PUB_SEED || root] + */ +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed) { + spx_ctx ctx; + + /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ + memcpy(sk, seed, CRYPTO_SEEDBYTES); + + memcpy(pk, sk + 2 * SPX_N, SPX_N); + + memcpy(ctx.pub_seed, pk, SPX_N); + memcpy(ctx.sk_seed, sk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + /* Compute root node of the top-most subtree. */ + merkle_gen_root(sk + 3 * SPX_N, &ctx); + + // cleanup + free_hash_function(&ctx); + + memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); + + return 0; +} + +/* + * Generates an SPX key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [PUB_SEED || root] + */ +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { + uint8_t seed[CRYPTO_SEEDBYTES]; + randombytes(seed, CRYPTO_SEEDBYTES); + crypto_sign_seed_keypair(pk, sk, seed); + + return 0; +} + +/** + * Returns an array containing a detached signature. + */ +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk) { + spx_ctx ctx; + + const uint8_t *sk_prf = sk + SPX_N; + const uint8_t *pk = sk + 2 * SPX_N; + + uint8_t optrand[SPX_N]; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t root[SPX_N]; + uint32_t i; + uint64_t tree; + uint32_t idx_leaf; + uint32_t wots_addr[8] = {0}; + uint32_t tree_addr[8] = {0}; + + memcpy(ctx.sk_seed, sk, SPX_N); + memcpy(ctx.pub_seed, pk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + + /* Optionally, signing can be made non-deterministic using optrand. + This can help counter side-channel attacks that would benefit from + getting a large number of traces when the signer uses the same nodes. */ + randombytes(optrand, SPX_N); + /* Compute the digest randomization value. */ + gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); + + /* Derive the message digest and leaf index from R, PK and M. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; + + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); + + /* Sign the message hash using FORS. */ + fors_sign(sig, root, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); + sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; + + /* Update the indices for the next layer. */ + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; + } + + free_hash_function(&ctx); + + *siglen = SPX_BYTES; + + return 0; +} + +/** + * Verifies a detached signature and message under a given public key. + */ +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk) { + spx_ctx ctx; + const uint8_t *pub_root = pk + SPX_N; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t wots_pk[SPX_WOTS_BYTES]; + uint8_t root[SPX_N]; + uint8_t leaf[SPX_N]; + unsigned int i; + uint64_t tree; + uint32_t idx_leaf; + uint32_t wots_addr[8] = {0}; + uint32_t tree_addr[8] = {0}; + uint32_t wots_pk_addr[8] = {0}; + + if (siglen != SPX_BYTES) { + return -1; + } + + memcpy(ctx.pub_seed, pk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); + + /* Derive the message digest and leaf index from R || PK || M. */ + /* The additional SPX_N is a result of the hash domain separator. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; + + /* Layer correctly defaults to 0, so no need to set_layer_addr */ + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); + + fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + /* For each subtree.. */ + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + copy_keypair_addr(wots_pk_addr, wots_addr); + + /* The WOTS public key is only correct if the signature was correct. */ + /* Initially, root is the FORS pk, but on subsequent iterations it is + the root of the subtree below the currently processed subtree. */ + wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); + sig += SPX_WOTS_BYTES; + + /* Compute the leaf node using the WOTS public key. */ + thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); + + /* Compute the root node of this subtree. */ + compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, + &ctx, tree_addr); + sig += SPX_TREE_HEIGHT * SPX_N; + + /* Update the indices for the next layer. */ + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; + } + + // cleanup + free_hash_function(&ctx); + + /* Check if the root node equals the root node in the public key. */ + if (memcmp(root, pub_root, SPX_N) != 0) { + return -1; + } + + return 0; +} + + +/** + * Returns an array containing the signature followed by the message. + */ +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk) { + size_t siglen; + + crypto_sign_signature(sm, &siglen, m, mlen, sk); + + memmove(sm + SPX_BYTES, m, mlen); + *smlen = siglen + mlen; + + return 0; +} + +/** + * Verifies a given signature-message pair under a given public key. + */ +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk) { + /* The API caller does not necessarily know what size a signature should be + but SPHINCS+ signatures are always exactly SPX_BYTES. */ + if (smlen < SPX_BYTES) { + memset(m, 0, smlen); + *mlen = 0; + return -1; + } + + *mlen = smlen - SPX_BYTES; + + if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { + memset(m, 0, smlen); + *mlen = 0; + return -1; + } + + /* If verification was successful, move the message to the right place. */ + memmove(m, sm + SPX_BYTES, *mlen); + + return 0; +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/thash.h b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/thash.h new file mode 100644 index 0000000000..8687ccfb4d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/thash.h @@ -0,0 +1,13 @@ +#ifndef SPX_THASH_H +#define SPX_THASH_H + +#include "context.h" +#include "params.h" + +#include + +#define thash SPX_NAMESPACE(thash) +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/thash_sha2_robust.c b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/thash_sha2_robust.c new file mode 100644 index 0000000000..3ab891175f --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/thash_sha2_robust.c @@ -0,0 +1,68 @@ +#include +#include + +#include "address.h" +#include "context.h" +#include "hash.h" +#include "params.h" +#include "sha2.h" +#include "thash.h" +#include "utils.h" + +static void thash_512(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]); + +/** + * Takes an array of inblocks concatenated arrays of SPX_N bytes. + */ +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]) { + if (inblocks > 1) { + thash_512(out, in, inblocks, ctx, addr); + return; + } + unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES]; + PQCLEAN_VLA(uint8_t, bitmask, inblocks * SPX_N); + PQCLEAN_VLA(uint8_t, buf, SPX_N + SPX_SHA256_OUTPUT_BYTES + inblocks * SPX_N); + sha256ctx sha2_state; + unsigned int i; + + memcpy(buf, ctx->pub_seed, SPX_N); + memcpy(buf + SPX_N, addr, SPX_SHA256_ADDR_BYTES); + mgf1_256(bitmask, inblocks * SPX_N, buf, SPX_N + SPX_SHA256_ADDR_BYTES); + + /* Retrieve precomputed state containing pub_seed */ + sha256_inc_ctx_clone(&sha2_state, &ctx->state_seeded); + + for (i = 0; i < inblocks * SPX_N; i++) { + buf[SPX_N + SPX_SHA256_ADDR_BYTES + i] = in[i] ^ bitmask[i]; + } + + sha256_inc_finalize(outbuf, &sha2_state, buf + SPX_N, + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N); + memcpy(out, outbuf, SPX_N); +} + +static void thash_512(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]) { + unsigned char outbuf[SPX_SHA512_OUTPUT_BYTES]; + PQCLEAN_VLA(uint8_t, bitmask, inblocks * SPX_N); + PQCLEAN_VLA(uint8_t, buf, SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N); + sha512ctx sha2_state; + unsigned int i; + + memcpy(buf, ctx->pub_seed, SPX_N); + memcpy(buf + SPX_N, addr, SPX_SHA256_ADDR_BYTES); + mgf1_512(bitmask, inblocks * SPX_N, buf, SPX_N + SPX_SHA256_ADDR_BYTES); + + /* Retrieve precomputed state containing pub_seed */ + sha512_inc_ctx_clone(&sha2_state, &ctx->state_seeded_512); + + for (i = 0; i < inblocks * SPX_N; i++) { + buf[SPX_N + SPX_SHA256_ADDR_BYTES + i] = in[i] ^ bitmask[i]; + } + + sha512_inc_finalize(outbuf, &sha2_state, buf + SPX_N, + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N); + memcpy(out, outbuf, SPX_N); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/thash_sha2_robustx8.c b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/thash_sha2_robustx8.c new file mode 100644 index 0000000000..991faa7eeb --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/thash_sha2_robustx8.c @@ -0,0 +1,268 @@ +#include +#include + +#include "thashx8.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "sha2.h" +#include "sha256avx.h" +#include "sha256x8.h" +#include "utils.h" + +#include "sha512x4.h" + +static void thashx8_512( + unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, + unsigned int inblocks, + const spx_ctx *ctx, + uint32_t addrx8[8 * 8] +); + +/** + * 8-way parallel version of thash; takes 8x as much input and output + */ +void thashx8(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addrx8[8 * 8]) { + if (inblocks > 1) { + thashx8_512( + out0, out1, out2, out3, out4, out5, out6, out7, + in0, in1, in2, in3, in4, in5, in6, in7, + inblocks, ctx, addrx8); + return; + } + PQCLEAN_VLA(unsigned char, bufx8, 8 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)); + unsigned char outbufx8[8 * SPX_SHA256_OUTPUT_BYTES]; + PQCLEAN_VLA(unsigned char, bitmaskx8, 8 * (inblocks * SPX_N)); + unsigned int i; + + for (i = 0; i < 8; i++) { + memcpy(bufx8 + i * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + ctx->pub_seed, SPX_N); + memcpy(bufx8 + SPX_N + + i * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + addrx8 + i * 8, SPX_SHA256_ADDR_BYTES); + } + + mgf1x8(bitmaskx8, inblocks * SPX_N, + bufx8 + 0 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + 1 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + 2 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + 3 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + 4 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + 5 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + 6 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + 7 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + SPX_N + SPX_SHA256_ADDR_BYTES); + + for (i = 0; i < inblocks * SPX_N; i++) { + bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + + 0 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = + in0[i] ^ bitmaskx8[i + 0 * (inblocks * SPX_N)]; + bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + + 1 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = + in1[i] ^ bitmaskx8[i + 1 * (inblocks * SPX_N)]; + bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + + 2 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = + in2[i] ^ bitmaskx8[i + 2 * (inblocks * SPX_N)]; + bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + + 3 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = + in3[i] ^ bitmaskx8[i + 3 * (inblocks * SPX_N)]; + bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + + 4 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = + in4[i] ^ bitmaskx8[i + 4 * (inblocks * SPX_N)]; + bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + + 5 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = + in5[i] ^ bitmaskx8[i + 5 * (inblocks * SPX_N)]; + bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + + 6 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = + in6[i] ^ bitmaskx8[i + 6 * (inblocks * SPX_N)]; + bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + + 7 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = + in7[i] ^ bitmaskx8[i + 7 * (inblocks * SPX_N)]; + } + + sha256x8_seeded( + /* out */ + outbufx8 + 0 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 1 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 2 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 3 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 4 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 5 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 6 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 7 * SPX_SHA256_OUTPUT_BYTES, + + /* seed */ + &ctx->statex8_seeded, + + /* in */ + bufx8 + SPX_N + 0 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + SPX_N + 1 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + SPX_N + 2 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + SPX_N + 3 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + SPX_N + 4 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + SPX_N + 5 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + SPX_N + 6 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + SPX_N + 7 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N /* len */ + ); + + memcpy(out0, outbufx8 + 0 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out1, outbufx8 + 1 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out2, outbufx8 + 2 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out3, outbufx8 + 3 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out4, outbufx8 + 4 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out5, outbufx8 + 5 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out6, outbufx8 + 6 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out7, outbufx8 + 7 * SPX_SHA256_OUTPUT_BYTES, SPX_N); +} + +/** + * 2x4-way parallel version of thash; this is for the uses of thash that are + * based on SHA-512 + */ +static void thashx8_512( + unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, + unsigned int inblocks, + const spx_ctx *ctx, + uint32_t addrx8[8 * 8]) { + PQCLEAN_VLA(unsigned char, bufx8, 8 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)); + unsigned char outbuf[4 * SPX_SHA512_OUTPUT_BYTES]; + PQCLEAN_VLA(unsigned char, bitmaskx4, 4 * (inblocks * SPX_N)); + unsigned int i; + + for (i = 0; i < 8; i++) { + memcpy(bufx8 + i * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + ctx->pub_seed, SPX_N); + memcpy(bufx8 + SPX_N + + i * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + addrx8 + i * 8, SPX_SHA256_ADDR_BYTES); + } + + mgf1x4_512(bitmaskx4, inblocks * SPX_N, + bufx8 + 0 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + 1 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + 2 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + 3 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + SPX_N + SPX_SHA256_ADDR_BYTES); + + for (i = 0; i < inblocks * SPX_N; i++) { + bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + + 0 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = + in0[i] ^ bitmaskx4[i + 0 * (inblocks * SPX_N)]; + bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + + 1 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = + in1[i] ^ bitmaskx4[i + 1 * (inblocks * SPX_N)]; + bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + + 2 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = + in2[i] ^ bitmaskx4[i + 2 * (inblocks * SPX_N)]; + bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + + 3 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = + in3[i] ^ bitmaskx4[i + 3 * (inblocks * SPX_N)]; + } + + mgf1x4_512(bitmaskx4, inblocks * SPX_N, + bufx8 + 4 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + 5 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + 6 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + 7 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + SPX_N + SPX_SHA256_ADDR_BYTES); + + for (i = 0; i < inblocks * SPX_N; i++) { + bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + + 4 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = + in4[i] ^ bitmaskx4[i + 0 * (inblocks * SPX_N)]; + bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + + 5 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = + in5[i] ^ bitmaskx4[i + 1 * (inblocks * SPX_N)]; + bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + + 6 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = + in6[i] ^ bitmaskx4[i + 2 * (inblocks * SPX_N)]; + bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + + 7 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = + in7[i] ^ bitmaskx4[i + 3 * (inblocks * SPX_N)]; + } + + sha512x4_seeded( + outbuf + 0 * SPX_SHA512_OUTPUT_BYTES, + outbuf + 1 * SPX_SHA512_OUTPUT_BYTES, + outbuf + 2 * SPX_SHA512_OUTPUT_BYTES, + outbuf + 3 * SPX_SHA512_OUTPUT_BYTES, + &ctx->statex4_seeded_512, /* seed */ + bufx8 + SPX_N + 0 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + SPX_N + 1 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + SPX_N + 2 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + SPX_N + 3 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N /* len */ + ); + + memcpy(out0, outbuf + 0 * SPX_SHA512_OUTPUT_BYTES, SPX_N); + memcpy(out1, outbuf + 1 * SPX_SHA512_OUTPUT_BYTES, SPX_N); + memcpy(out2, outbuf + 2 * SPX_SHA512_OUTPUT_BYTES, SPX_N); + memcpy(out3, outbuf + 3 * SPX_SHA512_OUTPUT_BYTES, SPX_N); + + sha512x4_seeded( + outbuf + 0 * SPX_SHA512_OUTPUT_BYTES, + outbuf + 1 * SPX_SHA512_OUTPUT_BYTES, + outbuf + 2 * SPX_SHA512_OUTPUT_BYTES, + outbuf + 3 * SPX_SHA512_OUTPUT_BYTES, + &ctx->statex4_seeded_512, /* seed */ + bufx8 + SPX_N + 4 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + SPX_N + 5 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + SPX_N + 6 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + SPX_N + 7 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N /* len */ + ); + + memcpy(out4, outbuf + 0 * SPX_SHA512_OUTPUT_BYTES, SPX_N); + memcpy(out5, outbuf + 1 * SPX_SHA512_OUTPUT_BYTES, SPX_N); + memcpy(out6, outbuf + 2 * SPX_SHA512_OUTPUT_BYTES, SPX_N); + memcpy(out7, outbuf + 3 * SPX_SHA512_OUTPUT_BYTES, SPX_N); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/thashx8.h b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/thashx8.h new file mode 100644 index 0000000000..c02fe9cf3e --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/thashx8.h @@ -0,0 +1,28 @@ +#ifndef SPX_THASHX8_H +#define SPX_THASHX8_H + +#include + +#include "context.h" +#include "params.h" + +#define thashx8 SPX_NAMESPACE(thashx8) +void thashx8(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addrx8[8 * 8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/utils.c b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/utils.c new file mode 100644 index 0000000000..177b541fb9 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/utils.c @@ -0,0 +1,148 @@ +#include + +#include "utils.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "thash.h" + +/** + * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. + */ +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in) { + int i; + + /* Iterate over out in decreasing order, for big-endianness. */ + for (i = (signed int)outlen - 1; i >= 0; i--) { + out[i] = in & 0xff; + in = in >> 8; + } +} + +void u32_to_bytes(unsigned char *out, uint32_t in) { + out[0] = (unsigned char)(in >> 24); + out[1] = (unsigned char)(in >> 16); + out[2] = (unsigned char)(in >> 8); + out[3] = (unsigned char)in; +} + +/** + * Converts the inlen bytes in 'in' from big-endian byte order to an integer. + */ +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { + unsigned long long retval = 0; + unsigned int i; + + for (i = 0; i < inlen; i++) { + retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); + } + return retval; +} + +/** + * Computes a root node given a leaf and an auth path. + * Expects address to be complete other than the tree_height and tree_index. + */ +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]) { + uint32_t i; + unsigned char buffer[2 * SPX_N]; + + /* If leaf_idx is odd (last bit = 1), current path element is a right child + and auth_path has to go left. Otherwise it is the other way around. */ + if (leaf_idx & 1) { + memcpy(buffer + SPX_N, leaf, SPX_N); + memcpy(buffer, auth_path, SPX_N); + } else { + memcpy(buffer, leaf, SPX_N); + memcpy(buffer + SPX_N, auth_path, SPX_N); + } + auth_path += SPX_N; + + for (i = 0; i < tree_height - 1; i++) { + leaf_idx >>= 1; + idx_offset >>= 1; + /* Set the address of the node we're creating. */ + set_tree_height(addr, i + 1); + set_tree_index(addr, leaf_idx + idx_offset); + + /* Pick the right or left neighbor, depending on parity of the node. */ + if (leaf_idx & 1) { + thash(buffer + SPX_N, buffer, 2, ctx, addr); + memcpy(buffer, auth_path, SPX_N); + } else { + thash(buffer, buffer, 2, ctx, addr); + memcpy(buffer + SPX_N, auth_path, SPX_N); + } + auth_path += SPX_N; + } + + /* The last iteration is exceptional; we do not copy an auth_path node. */ + leaf_idx >>= 1; + idx_offset >>= 1; + set_tree_height(addr, tree_height); + set_tree_index(addr, leaf_idx + idx_offset); + thash(root, buffer, 2, ctx, addr); +} + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx * /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]) { + PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); + PQCLEAN_VLA(unsigned int, heights, tree_height + 1); + unsigned int offset = 0; + uint32_t idx; + uint32_t tree_idx; + + for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { + /* Add the next leaf node to the stack. */ + gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); + offset++; + heights[offset - 1] = 0; + + /* If this is a node we need for the auth path.. */ + if ((leaf_idx ^ 0x1) == idx) { + memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); + } + + /* While the top-most nodes are of equal height.. */ + while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { + /* Compute index of the new node, in the next layer. */ + tree_idx = (idx >> (heights[offset - 1] + 1)); + + /* Set the address of the node we're creating. */ + set_tree_height(tree_addr, heights[offset - 1] + 1); + set_tree_index(tree_addr, + tree_idx + (idx_offset >> (heights[offset - 1] + 1))); + /* Hash the top-most nodes from the stack together. */ + thash(stack + (offset - 2)*SPX_N, + stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); + offset--; + /* Note that the top-most node is now one layer higher. */ + heights[offset - 1]++; + + /* If this is a node we need for the auth path.. */ + if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { + memcpy(auth_path + heights[offset - 1]*SPX_N, + stack + (offset - 1)*SPX_N, SPX_N); + } + } + } + memcpy(root, stack, SPX_N); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/utils.h b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/utils.h new file mode 100644 index 0000000000..64f5d5a53a --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/utils.h @@ -0,0 +1,58 @@ +#ifndef SPX_UTILS_H +#define SPX_UTILS_H + +#include + +#include "compat.h" +#include "context.h" +#include "params.h" + + +/* To support MSVC use alloca() instead of VLAs. See #20. */ + + +/** + * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. + */ +#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in); +#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) +void u32_to_bytes(unsigned char *out, uint32_t in); + +/** + * Converts the inlen bytes in 'in' from big-endian byte order to an integer. + */ +#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); + +/** + * Computes a root node given a leaf and an auth path. + * Expects address to be complete other than the tree_height and tree_index. + */ +#define compute_root SPX_NAMESPACE(compute_root) +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]); + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +#define treehash SPX_NAMESPACE(treehash) +void treehash(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx *ctx /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]); + + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/utilsx8.c b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/utilsx8.c new file mode 100644 index 0000000000..f044b9595d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/utilsx8.c @@ -0,0 +1,146 @@ +#include + +#include "utils.h" +#include "utilsx8.h" + +#include "address.h" +#include "params.h" +#include "thashx8.h" + +/* + * Generate the entire Merkle tree, computing the authentication path for leaf_idx, + * and the resulting root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) + * + * This expects tree_addrx8 to be initialized to 8 parallel addr structures for + * the Merkle tree nodes + * + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + * + * This works by using the standard Merkle tree building algorithm, except + * that each 'node' tracked is actually 8 consecutive nodes in the real tree. + * When we combine two logical nodes ABCDEFGH and STUVWXYZ, we perform the H + * operation on adjacent real nodes, forming the parent logical node + * (AB)(CD)(EF)(GH)(ST)(UV)(WX)(YZ) + * + * When we get to the top three levels of the real tree (where there is only + * one logical node), we continue this operation three more times; the right + * most real node will by the actual root (and the other 7 nodes will be + * garbage). We follow the same thashx8 logic so that the 'extract + * authentication path components' part of the loop is still executed (and + * to simplify the code somewhat) + * + * This currently assumes tree_height >= 3; I suspect that doing an adjusting + * idx, addr_idx on the gen_leafx8 call if tree_height < 3 would fix it; since + * we don't actually use such short trees, I haven't bothered + */ +void treehashx8(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, + uint32_t tree_height, + void (*gen_leafx8)( + unsigned char * /* Where to write the leaves */, + const spx_ctx *, + uint32_t idx, void *info), + uint32_t tree_addrx8[8 * 8], + void *info) { + /* This is where we keep the intermediate nodes */ + PQCLEAN_VLA(unsigned char, stackx8, tree_height * 8 * SPX_N); + uint32_t left_adj = 0, prev_left_adj = 0; /* When we're doing the top 3 */ + /* levels, the left-most part of the tree isn't at the beginning */ + /* of current[]. These give the offset of the actual start */ + + uint32_t idx; + uint32_t max_idx = ((uint32_t)1 << (tree_height - 3)) - 1; + for (idx = 0;; idx++) { + unsigned char current[8 * SPX_N]; /* Current logical node */ + gen_leafx8( current, ctx, 8 * idx + idx_offset, + info ); + + /* Now combine the freshly generated right node with previously */ + /* generated left ones */ + uint32_t internal_idx_offset = idx_offset; + uint32_t internal_idx = idx; + uint32_t internal_leaf = leaf_idx; + uint32_t h; /* The height we are in the Merkle tree */ + for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { + + /* Special processing if we're at the top of the tree */ + if (h >= tree_height - 3) { + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[7 * SPX_N], SPX_N ); + return; + } + /* The tree indexing logic is a bit off in this case */ + /* Adjust it so that the left-most node of the part of */ + /* the tree that we're processing has index 0 */ + prev_left_adj = left_adj; + left_adj = (uint32_t)(8 - (1 << (tree_height - h - 1))); + } + + /* Check if we hit the top of the tree */ + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[7 * SPX_N], SPX_N ); + return; + } + + /* + * Check if one of the nodes we have is a part of the + * authentication path; if it is, write it out + */ + if ((((internal_idx << 3) ^ internal_leaf) & ~0x7U) == 0) { + memcpy( &auth_path[ h * SPX_N ], + ¤t[(((internal_leaf & 7) ^ 1) + prev_left_adj) * SPX_N], + SPX_N ); + } + + /* + * Check if we're at a left child; if so, stop going up the stack + * Exception: if we've reached the end of the tree, keep on going + * (so we combine the last 8 nodes into the one root node in three + * more iterations) + */ + if ((internal_idx & 1) == 0 && idx < max_idx) { + break; + } + + /* Ok, we're at a right node (or doing the top 3 levels) */ + /* Now combine the left and right logical nodes together */ + + /* Set the address of the node we're creating. */ + uint32_t j; + internal_idx_offset >>= 1; + for (j = 0; j < 8; j++) { + set_tree_height(tree_addrx8 + j * 8, h + 1); + set_tree_index(tree_addrx8 + j * 8, + (8 / 2) * (internal_idx & ~1U) + j - left_adj + internal_idx_offset ); + } + unsigned char *left = &stackx8[h * 8 * SPX_N]; + thashx8( ¤t[0 * SPX_N], + ¤t[1 * SPX_N], + ¤t[2 * SPX_N], + ¤t[3 * SPX_N], + ¤t[4 * SPX_N], + ¤t[5 * SPX_N], + ¤t[6 * SPX_N], + ¤t[7 * SPX_N], + &left [0 * SPX_N], + &left [2 * SPX_N], + &left [4 * SPX_N], + &left [6 * SPX_N], + ¤t[0 * SPX_N], + ¤t[2 * SPX_N], + ¤t[4 * SPX_N], + ¤t[6 * SPX_N], + 2, ctx, tree_addrx8); + } + + /* We've hit a left child; save the current for when we get the */ + /* corresponding right right */ + memcpy( &stackx8[h * 8 * SPX_N], current, 8 * SPX_N); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/utilsx8.h b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/utilsx8.h new file mode 100644 index 0000000000..806d1e85be --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/utilsx8.h @@ -0,0 +1,29 @@ +#ifndef SPX_UTILSX8_H +#define SPX_UTILSX8_H + +#include + +#include "params.h" + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + * + * This implementation uses AVX to compute internal nodes 8 at a time (in + * parallel) + */ +#define treehashx8 SPX_NAMESPACE(treehashx8) +void treehashx8(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leafx8)( + unsigned char * /* Where to write the leaves */, + const spx_ctx * /* ctx */, + uint32_t addr_idx, void *info), + uint32_t tree_addrx8[8 * 8], void *info); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/wots.c b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/wots.c new file mode 100644 index 0000000000..689baf4db9 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/wots.c @@ -0,0 +1,291 @@ +#include +#include + +#include "wots.h" + +#include "address.h" +#include "hash.h" +#include "hashx8.h" +#include "params.h" +#include "thash.h" +#include "thashx8.h" +#include "utils.h" +#include "utilsx8.h" +#include "wotsx8.h" + +// TODO clarify address expectations, and make them more uniform. +// TODO i.e. do we expect types to be set already? +// TODO and do we expect modifications or copies? + +/** + * Computes up the chains + */ +static void gen_chains( + unsigned char *out, + const unsigned char *in, + unsigned int start[SPX_WOTS_LEN], + const unsigned int steps[SPX_WOTS_LEN], + const spx_ctx *ctx, + uint32_t addr[8]) { + uint32_t i, j, k, idx, watching; + int done; + unsigned char empty[SPX_N]; + unsigned char *bufs[8]; + uint32_t addrs[8 * 8]; + + int l; + uint16_t counts[SPX_WOTS_W] = { 0 }; + uint16_t idxs[SPX_WOTS_LEN]; + uint16_t total, newTotal; + + /* set addrs = {addr, addr, ..., addr} */ + for (j = 0; j < 8; j++) { + memcpy(addrs + j * 8, addr, sizeof(uint32_t) * 8); + } + + /* Initialize out with the value at position 'start'. */ + memcpy(out, in, SPX_WOTS_LEN * SPX_N); + + /* Sort the chains in reverse order by steps using counting sort. */ + for (i = 0; i < SPX_WOTS_LEN; i++) { + counts[steps[i]]++; + } + total = 0; + for (l = SPX_WOTS_W - 1; l >= 0; l--) { + newTotal = counts[l] + total; + counts[l] = total; + total = newTotal; + } + for (i = 0; i < SPX_WOTS_LEN; i++) { + idxs[counts[steps[i]]] = (uint16_t)i; + counts[steps[i]]++; + } + + /* We got our work cut out for us: do it! */ + for (i = 0; i < SPX_WOTS_LEN; i += 8) { + for (j = 0; j < 8 && i + j < SPX_WOTS_LEN; j++) { + idx = idxs[i + j]; + set_chain_addr(addrs + j * 8, idx); + bufs[j] = out + SPX_N * idx; + } + + /* As the chains are sorted in reverse order, we know that the first + * chain is the longest and the last one is the shortest. We keep + * an eye on whether the last chain is done and then on the one before, + * et cetera. */ + watching = 7; + done = 0; + while (i + watching >= SPX_WOTS_LEN) { + bufs[watching] = &empty[0]; + watching--; + } + + for (k = 0;; k++) { + while (k == steps[idxs[i + watching]]) { + bufs[watching] = &empty[0]; + if (watching == 0) { + done = 1; + break; + } + watching--; + } + if (done) { + break; + } + for (j = 0; j < watching + 1; j++) { + set_hash_addr(addrs + j * 8, k + start[idxs[i + j]]); + } + + thashx8(bufs[0], bufs[1], bufs[2], bufs[3], + bufs[4], bufs[5], bufs[6], bufs[7], + bufs[0], bufs[1], bufs[2], bufs[3], + bufs[4], bufs[5], bufs[6], bufs[7], 1, ctx, addrs); + } + } +} + +/** + * base_w algorithm as described in draft. + * Interprets an array of bytes as integers in base w. + * This only works when log_w is a divisor of 8. + */ +static void base_w(unsigned int *output, const int out_len, + const unsigned char *input) { + int in = 0; + int out = 0; + unsigned char total = 0; + int bits = 0; + int consumed; + + for (consumed = 0; consumed < out_len; consumed++) { + if (bits == 0) { + total = input[in]; + in++; + bits += 8; + } + bits -= SPX_WOTS_LOGW; + output[out] = (total >> bits) & (SPX_WOTS_W - 1); + out++; + } +} + +/* Computes the WOTS+ checksum over a message (in base_w). */ +static void wots_checksum(unsigned int *csum_base_w, + const unsigned int *msg_base_w) { + unsigned int csum = 0; + unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; + unsigned int i; + + /* Compute checksum. */ + for (i = 0; i < SPX_WOTS_LEN1; i++) { + csum += SPX_WOTS_W - 1 - msg_base_w[i]; + } + + /* Convert checksum to base_w. */ + /* Make sure expected empty zero bits are the least significant bits. */ + csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); + ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); + base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); +} + +/* Takes a message and derives the matching chain lengths. */ +void chain_lengths(unsigned int *lengths, const unsigned char *msg) { + base_w(lengths, SPX_WOTS_LEN1, msg); + wots_checksum(lengths + SPX_WOTS_LEN1, lengths); +} + +/** + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. + * + * Writes the computed public key to 'pk'. + */ +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]) { + unsigned int steps[SPX_WOTS_LEN]; + unsigned int start[SPX_WOTS_LEN]; + uint32_t i; + + chain_lengths(start, msg); + + for (i = 0; i < SPX_WOTS_LEN; i++) { + steps[i] = SPX_WOTS_W - 1 - start[i]; + } + + gen_chains(pk, sig, start, steps, ctx, addr); +} + +/* + * This generates 8 sequential WOTS public keys + * It also generates the WOTS signature if leaf_info indicates + * that we're signing with one of these WOTS keys + */ +void wots_gen_leafx8(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info) { + struct leaf_info_x8 *info = v_info; + uint32_t *leaf_addr = info->leaf_addr; + uint32_t *pk_addr = info->pk_addr; + unsigned int i, j, k; + unsigned char pk_buffer[ 8 * SPX_WOTS_BYTES ]; + unsigned wots_offset = SPX_WOTS_BYTES; + unsigned char *buffer; + uint32_t wots_k_mask; + unsigned wots_sign_index; + + if (((leaf_idx ^ info->wots_sign_leaf) & ~7U) == 0) { + /* We're traversing the leaf that's signing; generate the WOTS */ + /* signature */ + wots_k_mask = 0; + wots_sign_index = info->wots_sign_leaf & 7; /* Which of of the 8 */ + /* slots do the signatures come from */ + } else { + /* Nope, we're just generating pk's; turn off the signature logic */ + wots_k_mask = ~0U; + wots_sign_index = 0; + } + + for (j = 0; j < 8; j++) { + set_keypair_addr( leaf_addr + j * 8, leaf_idx + j ); + set_keypair_addr( pk_addr + j * 8, leaf_idx + j ); + } + + for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { + uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k */ + /* to the step if we're generating a signature, ~0 if we're not */ + + /* Start with the secret seed */ + for (j = 0; j < 8; j++) { + set_chain_addr(leaf_addr + j * 8, i); + set_hash_addr(leaf_addr + j * 8, 0); + set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTSPRF); + } + prf_addrx8(buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + buffer + 2 * wots_offset, + buffer + 3 * wots_offset, + buffer + 4 * wots_offset, + buffer + 5 * wots_offset, + buffer + 6 * wots_offset, + buffer + 7 * wots_offset, + ctx, leaf_addr); + + for (j = 0; j < 8; j++) { + set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTS); + } + + /* Iterate down the WOTS chain */ + for (k = 0;; k++) { + /* Check if one of the values we have needs to be saved as a */ + /* part of the WOTS signature */ + if (k == wots_k) { + memcpy( info->wots_sig + i * SPX_N, + buffer + wots_sign_index * wots_offset, SPX_N ); + } + + /* Check if we hit the top of the chain */ + if (k == SPX_WOTS_W - 1) { + break; + } + + /* Iterate one step on all 8 chains */ + for (j = 0; j < 8; j++) { + set_hash_addr(leaf_addr + j * 8, k); + } + thashx8(buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + buffer + 2 * wots_offset, + buffer + 3 * wots_offset, + buffer + 4 * wots_offset, + buffer + 5 * wots_offset, + buffer + 6 * wots_offset, + buffer + 7 * wots_offset, + buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + buffer + 2 * wots_offset, + buffer + 3 * wots_offset, + buffer + 4 * wots_offset, + buffer + 5 * wots_offset, + buffer + 6 * wots_offset, + buffer + 7 * wots_offset, 1, ctx, leaf_addr); + } + } + + /* Do the final thash to generate the public keys */ + thashx8(dest + 0 * SPX_N, + dest + 1 * SPX_N, + dest + 2 * SPX_N, + dest + 3 * SPX_N, + dest + 4 * SPX_N, + dest + 5 * SPX_N, + dest + 6 * SPX_N, + dest + 7 * SPX_N, + pk_buffer + 0 * wots_offset, + pk_buffer + 1 * wots_offset, + pk_buffer + 2 * wots_offset, + pk_buffer + 3 * wots_offset, + pk_buffer + 4 * wots_offset, + pk_buffer + 5 * wots_offset, + pk_buffer + 6 * wots_offset, + pk_buffer + 7 * wots_offset, SPX_WOTS_LEN, ctx, pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/wots.h b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/wots.h new file mode 100644 index 0000000000..4e7692eeef --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/wots.h @@ -0,0 +1,25 @@ +#ifndef SPX_WOTS_H +#define SPX_WOTS_H + +#include + +#include "context.h" +#include "params.h" + +/** + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. + * + * Writes the computed public key to 'pk'. + */ +#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]); + +/* + * Compute the chain lengths needed for a given message hash + */ +#define chain_lengths SPX_NAMESPACE(chain_lengths) +void chain_lengths(unsigned int *lengths, const unsigned char *msg); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/wotsx8.h b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/wotsx8.h new file mode 100644 index 0000000000..10866efb35 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/wotsx8.h @@ -0,0 +1,42 @@ +#ifndef WOTSX8_H_ +#define WOTSX8_H_ + +#include + +#include "context.h" +#include "params.h" + +/* + * This is here to provide an interface to the internal wots_gen_leafx8 + * routine. While this routine is not referenced in the package outside of + * wots.c, it is called from the stand-alone benchmark code to characterize + * the performance + */ +struct leaf_info_x8 { + unsigned char *wots_sig; + uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ + uint32_t *wots_steps; + uint32_t leaf_addr[8 * 8]; + uint32_t pk_addr[8 * 8]; +}; + +/* Macro to set the leaf_info to something 'benign', that is, it would */ +/* run with the same time as it does during the real signing process */ +/* Used only by the benchmark code */ +#define INITIALIZE_LEAF_INFO_X8(info, addr, step_buffer) { \ + (info).wots_sig = 0; \ + (info).wots_sign_leaf = ~0; \ + (info).wots_steps = step_buffer; \ + int i; \ + for (i=0; i<8; i++) { \ + memcpy( &(info).leaf_addr[8*i], addr, 32 ); \ + memcpy( &(info).pk_addr[8*i], addr, 32 ); \ + } \ + } + +#define wots_gen_leafx8 SPX_NAMESPACE(wots_gen_leafx8) +void wots_gen_leafx8(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info); + +#endif /* WOTSX8_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/LICENSE b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/LICENSE new file mode 100644 index 0000000000..670154e353 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/LICENSE @@ -0,0 +1,116 @@ +CC0 1.0 Universal + +Statement of Purpose + +The laws of most jurisdictions throughout the world automatically confer +exclusive Copyright and Related Rights (defined below) upon the creator and +subsequent owner(s) (each and all, an "owner") of an original work of +authorship and/or a database (each, a "Work"). + +Certain owners wish to permanently relinquish those rights to a Work for the +purpose of contributing to a commons of creative, cultural and scientific +works ("Commons") that the public can reliably and without fear of later +claims of infringement build upon, modify, incorporate in other works, reuse +and redistribute as freely as possible in any form whatsoever and for any +purposes, including without limitation commercial purposes. These owners may +contribute to the Commons to promote the ideal of a free culture and the +further production of creative, cultural and scientific works, or to gain +reputation or greater distribution for their Work in part through the use and +efforts of others. + +For these and/or other purposes and motivations, and without any expectation +of additional consideration or compensation, the person associating CC0 with a +Work (the "Affirmer"), to the extent that he or she is an owner of Copyright +and Related Rights in the Work, voluntarily elects to apply CC0 to the Work +and publicly distribute the Work under its terms, with knowledge of his or her +Copyright and Related Rights in the Work and the meaning and intended legal +effect of CC0 on those rights. + +1. Copyright and Related Rights. A Work made available under CC0 may be +protected by copyright and related or neighboring rights ("Copyright and +Related Rights"). Copyright and Related Rights include, but are not limited +to, the following: + + i. the right to reproduce, adapt, distribute, perform, display, communicate, + and translate a Work; + + ii. moral rights retained by the original author(s) and/or performer(s); + + iii. publicity and privacy rights pertaining to a person's image or likeness + depicted in a Work; + + iv. rights protecting against unfair competition in regards to a Work, + subject to the limitations in paragraph 4(a), below; + + v. rights protecting the extraction, dissemination, use and reuse of data in + a Work; + + vi. database rights (such as those arising under Directive 96/9/EC of the + European Parliament and of the Council of 11 March 1996 on the legal + protection of databases, and under any national implementation thereof, + including any amended or successor version of such directive); and + + vii. other similar, equivalent or corresponding rights throughout the world + based on applicable law or treaty, and any national implementations thereof. + +2. Waiver. To the greatest extent permitted by, but not in contravention of, +applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and +unconditionally waives, abandons, and surrenders all of Affirmer's Copyright +and Related Rights and associated claims and causes of action, whether now +known or unknown (including existing as well as future claims and causes of +action), in the Work (i) in all territories worldwide, (ii) for the maximum +duration provided by applicable law or treaty (including future time +extensions), (iii) in any current or future medium and for any number of +copies, and (iv) for any purpose whatsoever, including without limitation +commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes +the Waiver for the benefit of each member of the public at large and to the +detriment of Affirmer's heirs and successors, fully intending that such Waiver +shall not be subject to revocation, rescission, cancellation, termination, or +any other legal or equitable action to disrupt the quiet enjoyment of the Work +by the public as contemplated by Affirmer's express Statement of Purpose. + +3. Public License Fallback. Should any part of the Waiver for any reason be +judged legally invalid or ineffective under applicable law, then the Waiver +shall be preserved to the maximum extent permitted taking into account +Affirmer's express Statement of Purpose. In addition, to the extent the Waiver +is so judged Affirmer hereby grants to each affected person a royalty-free, +non transferable, non sublicensable, non exclusive, irrevocable and +unconditional license to exercise Affirmer's Copyright and Related Rights in +the Work (i) in all territories worldwide, (ii) for the maximum duration +provided by applicable law or treaty (including future time extensions), (iii) +in any current or future medium and for any number of copies, and (iv) for any +purpose whatsoever, including without limitation commercial, advertising or +promotional purposes (the "License"). The License shall be deemed effective as +of the date CC0 was applied by Affirmer to the Work. Should any part of the +License for any reason be judged legally invalid or ineffective under +applicable law, such partial invalidity or ineffectiveness shall not +invalidate the remainder of the License, and in such case Affirmer hereby +affirms that he or she will not (i) exercise any of his or her remaining +Copyright and Related Rights in the Work or (ii) assert any associated claims +and causes of action with respect to the Work, in either case contrary to +Affirmer's express Statement of Purpose. + +4. Limitations and Disclaimers. + + a. No trademark or patent rights held by Affirmer are waived, abandoned, + surrendered, licensed or otherwise affected by this document. + + b. Affirmer offers the Work as-is and makes no representations or warranties + of any kind concerning the Work, express, implied, statutory or otherwise, + including without limitation warranties of title, merchantability, fitness + for a particular purpose, non infringement, or the absence of latent or + other defects, accuracy, or the present or absence of errors, whether or not + discoverable, all to the greatest extent permissible under applicable law. + + c. Affirmer disclaims responsibility for clearing rights of other persons + that may apply to the Work or any use thereof, including without limitation + any person's Copyright and Related Rights in the Work. Further, Affirmer + disclaims responsibility for obtaining any necessary consents, permissions + or other rights required for any use of the Work. + + d. Affirmer understands and acknowledges that Creative Commons is not a + party to this document and has no duty or obligation with respect to this + CC0 or use of the Work. + +For more information, please see + diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/address.c b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/address.c new file mode 100644 index 0000000000..b956e9cb29 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/address.c @@ -0,0 +1,91 @@ +#include +#include + +#include "address.h" +#include "params.h" +#include "utils.h" + +/* + * Specify which level of Merkle tree (the "layer") we're working on + */ +void set_layer_addr(uint32_t addr[8], uint32_t layer) { + ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; +} + +/* + * Specify which Merkle tree within the level (the "tree address") we're working on + */ +void set_tree_addr(uint32_t addr[8], uint64_t tree) { + ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); +} + +/* + * Specify the reason we'll use this address structure for, that is, what + * hash will we compute with it. This is used so that unrelated types of + * hashes don't accidentally get the same address structure. The type will be + * one of the SPX_ADDR_TYPE constants + */ +void set_type(uint32_t addr[8], uint32_t type) { + ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; +} + +/* + * Copy the layer and tree fields of the address structure. This is used + * when we're doing multiple types of hashes within the same Merkle tree + */ +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); +} + +/* These functions are used for OTS addresses. */ + +/* + * Specify which Merkle leaf we're working on; that is, which OTS keypair + * we're talking about. + */ +void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { + ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; +} + +/* + * Copy the layer, tree and keypair fields of the address structure. This is + * used when we're doing multiple things within the same OTS keypair + */ +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); + ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; +} + +/* + * Specify which Merkle chain within the OTS we're working with + * (the chain address) + */ +void set_chain_addr(uint32_t addr[8], uint32_t chain) { + ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; +} + +/* + * Specify where in the Merkle chain we are +* (the hash address) + */ +void set_hash_addr(uint32_t addr[8], uint32_t hash) { + ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; +} + +/* These functions are used for all hash tree addresses (including FORS). */ + +/* + * Specify the height of the node in the Merkle/FORS tree we are in + * (the tree height) + */ +void set_tree_height(uint32_t addr[8], uint32_t tree_height) { + ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; +} + +/* + * Specify the distance from the left edge of the node in the Merkle/FORS tree + * (the tree index) + */ +void set_tree_index(uint32_t addr[8], uint32_t tree_index) { + u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/address.h b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/address.h new file mode 100644 index 0000000000..24a84eb40c --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/address.h @@ -0,0 +1,52 @@ +#ifndef SPX_ADDRESS_H +#define SPX_ADDRESS_H + +#include + +#include "params.h" + +/* The hash types that are passed to set_type */ +#define SPX_ADDR_TYPE_WOTS 0 +#define SPX_ADDR_TYPE_WOTSPK 1 +#define SPX_ADDR_TYPE_HASHTREE 2 +#define SPX_ADDR_TYPE_FORSTREE 3 +#define SPX_ADDR_TYPE_FORSPK 4 +#define SPX_ADDR_TYPE_WOTSPRF 5 +#define SPX_ADDR_TYPE_FORSPRF 6 + +#define set_layer_addr SPX_NAMESPACE(set_layer_addr) +void set_layer_addr(uint32_t addr[8], uint32_t layer); + +#define set_tree_addr SPX_NAMESPACE(set_tree_addr) +void set_tree_addr(uint32_t addr[8], uint64_t tree); + +#define set_type SPX_NAMESPACE(set_type) +void set_type(uint32_t addr[8], uint32_t type); + +/* Copies the layer and tree part of one address into the other */ +#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); + +/* These functions are used for WOTS and FORS addresses. */ + +#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) +void set_keypair_addr(uint32_t addr[8], uint32_t keypair); + +#define set_chain_addr SPX_NAMESPACE(set_chain_addr) +void set_chain_addr(uint32_t addr[8], uint32_t chain); + +#define set_hash_addr SPX_NAMESPACE(set_hash_addr) +void set_hash_addr(uint32_t addr[8], uint32_t hash); + +#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); + +/* These functions are used for all hash tree addresses (including FORS). */ + +#define set_tree_height SPX_NAMESPACE(set_tree_height) +void set_tree_height(uint32_t addr[8], uint32_t tree_height); + +#define set_tree_index SPX_NAMESPACE(set_tree_index) +void set_tree_index(uint32_t addr[8], uint32_t tree_index); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/api.h b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/api.h new file mode 100644 index 0000000000..068ef4812e --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/api.h @@ -0,0 +1,77 @@ +#ifndef PQCLEAN_SPHINCSSHA2256SROBUST_CLEAN_API_H +#define PQCLEAN_SPHINCSSHA2256SROBUST_CLEAN_API_H + +#include +#include + +#define PQCLEAN_SPHINCSSHA2256SROBUST_CLEAN_CRYPTO_ALGNAME "SPHINCS+-sha2-256s-robust" + +#define PQCLEAN_SPHINCSSHA2256SROBUST_CLEAN_CRYPTO_SECRETKEYBYTES 128 +#define PQCLEAN_SPHINCSSHA2256SROBUST_CLEAN_CRYPTO_PUBLICKEYBYTES 64 +#define PQCLEAN_SPHINCSSHA2256SROBUST_CLEAN_CRYPTO_BYTES 29792 + +#define PQCLEAN_SPHINCSSHA2256SROBUST_CLEAN_CRYPTO_SEEDBYTES 96 + +/* + * Returns the length of a secret key, in bytes + */ +size_t PQCLEAN_SPHINCSSHA2256SROBUST_CLEAN_crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +size_t PQCLEAN_SPHINCSSHA2256SROBUST_CLEAN_crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +size_t PQCLEAN_SPHINCSSHA2256SROBUST_CLEAN_crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +size_t PQCLEAN_SPHINCSSHA2256SROBUST_CLEAN_crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +int PQCLEAN_SPHINCSSHA2256SROBUST_CLEAN_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +int PQCLEAN_SPHINCSSHA2256SROBUST_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +int PQCLEAN_SPHINCSSHA2256SROBUST_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +int PQCLEAN_SPHINCSSHA2256SROBUST_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, + const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +int PQCLEAN_SPHINCSSHA2256SROBUST_CLEAN_crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +int PQCLEAN_SPHINCSSHA2256SROBUST_CLEAN_crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/context.h b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/context.h new file mode 100644 index 0000000000..97e2e2469e --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/context.h @@ -0,0 +1,28 @@ +#ifndef SPX_CONTEXT_H +#define SPX_CONTEXT_H + +#include +#include + +#include "params.h" +#include "sha2.h" + +typedef struct { + uint8_t pub_seed[SPX_N]; + uint8_t sk_seed[SPX_N]; + + // sha256 state that absorbed pub_seed + sha256ctx state_seeded; + + // sha512 state that absorbed pub_seed + sha512ctx state_seeded_512; + +} spx_ctx; + +#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) +void initialize_hash_function(spx_ctx *ctx); + +#define free_hash_function SPX_NAMESPACE(free_hash_function) +void free_hash_function(spx_ctx *ctx); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/context_sha2.c b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/context_sha2.c new file mode 100644 index 0000000000..9ca9f4e7ac --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/context_sha2.c @@ -0,0 +1,36 @@ +#include "context.h" + +/** + * Absorb the constant pub_seed using one round of the compression function + * This initializes state_seeded and state_seeded_512, which can then be + * reused in thash + **/ +static void seed_state(spx_ctx *ctx) { + uint8_t block[SPX_SHA512_BLOCK_BYTES]; + size_t i; + + for (i = 0; i < SPX_N; ++i) { + block[i] = ctx->pub_seed[i]; + } + for (i = SPX_N; i < SPX_SHA512_BLOCK_BYTES; ++i) { + block[i] = 0; + } + /* block has been properly initialized for both SHA-256 and SHA-512 */ + + sha256_inc_init(&ctx->state_seeded); + sha256_inc_blocks(&ctx->state_seeded, block, 1); + sha512_inc_init(&ctx->state_seeded_512); + sha512_inc_blocks(&ctx->state_seeded_512, block, 1); +} + + +/* We initialize the state for the hash functions */ +void initialize_hash_function(spx_ctx *ctx) { + seed_state(ctx); +} + +/* Free the incremental hashing context for heap-based SHA2 APIs */ +void free_hash_function(spx_ctx *ctx) { + sha256_inc_ctx_release(&ctx->state_seeded); + sha512_inc_ctx_release(&ctx->state_seeded_512); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/fors.c b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/fors.c new file mode 100644 index 0000000000..96ca72e986 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/fors.c @@ -0,0 +1,156 @@ +#include +#include +#include + +#include "fors.h" + +#include "address.h" +#include "hash.h" +#include "thash.h" +#include "utils.h" +#include "utilsx1.h" + +static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + prf_addr(sk, ctx, fors_leaf_addr); +} + +static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, + const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + thash(leaf, sk, 1, ctx, fors_leaf_addr); +} + +struct fors_gen_leaf_info { + uint32_t leaf_addrx[8]; +}; + +static void fors_gen_leafx1(unsigned char *leaf, + const spx_ctx *ctx, + uint32_t addr_idx, void *info) { + struct fors_gen_leaf_info *fors_info = info; + uint32_t *fors_leaf_addr = fors_info->leaf_addrx; + + /* Only set the parts that the caller doesn't set */ + set_tree_index(fors_leaf_addr, addr_idx); + set_type(fors_leaf_addr, SPX_ADDR_TYPE_FORSPRF); + fors_gen_sk(leaf, ctx, fors_leaf_addr); + + set_type(fors_leaf_addr, SPX_ADDR_TYPE_FORSTREE); + fors_sk_to_leaf(leaf, leaf, + ctx, fors_leaf_addr); +} + +/** + * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + * Assumes indices has space for SPX_FORS_TREES integers. + */ +static void message_to_indices(uint32_t *indices, const unsigned char *m) { + unsigned int i, j; + unsigned int offset = 0; + + for (i = 0; i < SPX_FORS_TREES; i++) { + indices[i] = 0; + for (j = 0; j < SPX_FORS_HEIGHT; j++) { + indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); + offset++; + } + } +} + +/** + * Signs a message m, deriving the secret key from sk_seed and the FTS address. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + uint32_t fors_tree_addr[8] = {0}; + struct fors_gen_leaf_info fors_info = {0}; + uint32_t *fors_leaf_addr = fors_info.leaf_addrx; + uint32_t fors_pk_addr[8] = {0}; + uint32_t idx_offset; + unsigned int i; + + copy_keypair_addr(fors_tree_addr, fors_addr); + copy_keypair_addr(fors_leaf_addr, fors_addr); + + copy_keypair_addr(fors_pk_addr, fors_addr); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); + + message_to_indices(indices, m); + + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); + + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); + + /* Include the secret key part that produces the selected leaf node. */ + fors_gen_sk(sig, ctx, fors_tree_addr); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + sig += SPX_N; + + /* Compute the authentication path for this leaf node. */ + treehashx1(roots + i * SPX_N, sig, ctx, + indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx1, + fors_tree_addr, &fors_info); + + sig += SPX_N * SPX_FORS_HEIGHT; + } + + /* Hash horizontally across all tree roots to derive the public key. */ + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); +} + +/** + * Derives the FORS public key from a signature. + * This can be used for verification by comparing to a known public key, or to + * subsequently verify a signature on the derived public key. The latter is the + * typical use-case when used as an FTS below an OTS in a hypertree. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + unsigned char leaf[SPX_N]; + uint32_t fors_tree_addr[8] = {0}; + uint32_t fors_pk_addr[8] = {0}; + uint32_t idx_offset; + unsigned int i; + + copy_keypair_addr(fors_tree_addr, fors_addr); + copy_keypair_addr(fors_pk_addr, fors_addr); + + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); + + message_to_indices(indices, m); + + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); + + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + + /* Derive the leaf from the included secret key part. */ + fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); + sig += SPX_N; + + /* Derive the corresponding root node of this tree. */ + compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, + sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); + sig += SPX_N * SPX_FORS_HEIGHT; + } + + /* Hash horizontally across all tree roots to derive the public key. */ + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/fors.h b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/fors.h new file mode 100644 index 0000000000..509140a178 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/fors.h @@ -0,0 +1,32 @@ +#ifndef SPX_FORS_H +#define SPX_FORS_H + +#include + +#include "context.h" +#include "params.h" + +/** + * Signs a message m, deriving the secret key from sk_seed and the FTS address. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +#define fors_sign SPX_NAMESPACE(fors_sign) +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); + +/** + * Derives the FORS public key from a signature. + * This can be used for verification by comparing to a known public key, or to + * subsequently verify a signature on the derived public key. The latter is the + * typical use-case when used as an FTS below an OTS in a hypertree. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/hash.h b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/hash.h new file mode 100644 index 0000000000..ffe815f45d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/hash.h @@ -0,0 +1,37 @@ +#ifndef SPX_HASH_H +#define SPX_HASH_H + +#include +#include + +#include "context.h" +#include "params.h" + +#define prf_addr SPX_NAMESPACE(prf_addr) +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]); + +#define gen_message_random SPX_NAMESPACE(gen_message_random) +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); + +#define hash_message SPX_NAMESPACE(hash_message) +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); + + +# define SPX_SHA256_ADDR_BYTES 22 + +# define mgf1_256 SPX_NAMESPACE(mgf1_256) +void mgf1_256(unsigned char *out, unsigned long outlen, + const unsigned char *in, unsigned long inlen); + +# define mgf1_512 SPX_NAMESPACE(mgf1_512) +void mgf1_512(unsigned char *out, unsigned long outlen, + const unsigned char *in, unsigned long inlen); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/hash_sha2.c b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/hash_sha2.c new file mode 100644 index 0000000000..3d0085c8c1 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/hash_sha2.c @@ -0,0 +1,219 @@ +#include +#include + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "sha2.h" +#include "utils.h" + + + +#define SPX_SHAX_OUTPUT_BYTES SPX_SHA512_OUTPUT_BYTES +#define SPX_SHAX_BLOCK_BYTES SPX_SHA512_BLOCK_BYTES +#define shaX_inc_init sha512_inc_init +#define shaX_inc_blocks sha512_inc_blocks +#define shaX_inc_finalize sha512_inc_finalize +#define shaX sha512 +#define mgf1_X mgf1_512 +#define shaXstate sha512ctx + +/** + * mgf1 function based on the SHA-256 hash function + * Note that inlen should be sufficiently small that it still allows for + * an array to be allocated on the stack. Typically 'in' is merely a seed. + * Outputs outlen number of bytes + */ +void mgf1_256(unsigned char *out, unsigned long outlen, + const unsigned char *in, unsigned long inlen) { + PQCLEAN_VLA(uint8_t, inbuf, inlen + 4); + unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES]; + uint32_t i; + + memcpy(inbuf, in, inlen); + + /* While we can fit in at least another full block of SHA256 output.. */ + for (i = 0; (i + 1)*SPX_SHA256_OUTPUT_BYTES <= outlen; i++) { + u32_to_bytes(inbuf + inlen, i); + sha256(out, inbuf, inlen + 4); + out += SPX_SHA256_OUTPUT_BYTES; + } + /* Until we cannot anymore, and we fill the remainder. */ + if (outlen > i * SPX_SHA256_OUTPUT_BYTES) { + u32_to_bytes(inbuf + inlen, i); + sha256(outbuf, inbuf, inlen + 4); + memcpy(out, outbuf, outlen - i * SPX_SHA256_OUTPUT_BYTES); + } +} + +/* + * mgf1 function based on the SHA-512 hash function + */ +void mgf1_512(unsigned char *out, unsigned long outlen, + const unsigned char *in, unsigned long inlen) { + PQCLEAN_VLA(uint8_t, inbuf, inlen + 4); + unsigned char outbuf[SPX_SHA512_OUTPUT_BYTES]; + uint32_t i; + + memcpy(inbuf, in, inlen); + + /* While we can fit in at least another full block of SHA512 output.. */ + for (i = 0; (i + 1)*SPX_SHA512_OUTPUT_BYTES <= outlen; i++) { + u32_to_bytes(inbuf + inlen, i); + sha512(out, inbuf, inlen + 4); + out += SPX_SHA512_OUTPUT_BYTES; + } + /* Until we cannot anymore, and we fill the remainder. */ + if (outlen > i * SPX_SHA512_OUTPUT_BYTES) { + u32_to_bytes(inbuf + inlen, i); + sha512(outbuf, inbuf, inlen + 4); + memcpy(out, outbuf, outlen - i * SPX_SHA512_OUTPUT_BYTES); + } +} + +/* + * Computes PRF(pk_seed, sk_seed, addr). + */ +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]) { + sha256ctx sha2_state; + unsigned char buf[SPX_SHA256_ADDR_BYTES + SPX_N]; + unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES]; + + /* Retrieve precomputed state containing pub_seed */ + sha256_inc_ctx_clone(&sha2_state, &ctx->state_seeded); + + /* Remainder: ADDR^c ‖ SK.seed */ + memcpy(buf, addr, SPX_SHA256_ADDR_BYTES); + memcpy(buf + SPX_SHA256_ADDR_BYTES, ctx->sk_seed, SPX_N); + + sha256_inc_finalize(outbuf, &sha2_state, buf, SPX_SHA256_ADDR_BYTES + SPX_N); + + memcpy(out, outbuf, SPX_N); +} + +/** + * Computes the message-dependent randomness R, using a secret seed as a key + * for HMAC, and an optional randomization value prefixed to the message. + * This requires m to have at least SPX_SHAX_BLOCK_BYTES + SPX_N space + * available in front of the pointer, i.e. before the message to use for the + * prefix. This is necessary to prevent having to move the message around (and + * allocate memory for it). + */ +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { + (void)ctx; + + unsigned char buf[SPX_SHAX_BLOCK_BYTES + SPX_SHAX_OUTPUT_BYTES]; + shaXstate state; + int i; + + + /* This implements HMAC-SHA */ + for (i = 0; i < SPX_N; i++) { + buf[i] = 0x36 ^ sk_prf[i]; + } + memset(buf + SPX_N, 0x36, SPX_SHAX_BLOCK_BYTES - SPX_N); + + shaX_inc_init(&state); + shaX_inc_blocks(&state, buf, 1); + + memcpy(buf, optrand, SPX_N); + + /* If optrand + message cannot fill up an entire block */ + if (SPX_N + mlen < SPX_SHAX_BLOCK_BYTES) { + memcpy(buf + SPX_N, m, mlen); + shaX_inc_finalize(buf + SPX_SHAX_BLOCK_BYTES, &state, + buf, mlen + SPX_N); + } + /* Otherwise first fill a block, so that finalize only uses the message */ + else { + memcpy(buf + SPX_N, m, SPX_SHAX_BLOCK_BYTES - SPX_N); + shaX_inc_blocks(&state, buf, 1); + + m += SPX_SHAX_BLOCK_BYTES - SPX_N; + mlen -= SPX_SHAX_BLOCK_BYTES - SPX_N; + shaX_inc_finalize(buf + SPX_SHAX_BLOCK_BYTES, &state, m, mlen); + } + + for (i = 0; i < SPX_N; i++) { + buf[i] = 0x5c ^ sk_prf[i]; + } + memset(buf + SPX_N, 0x5c, SPX_SHAX_BLOCK_BYTES - SPX_N); + + shaX(buf, buf, SPX_SHAX_BLOCK_BYTES + SPX_SHAX_OUTPUT_BYTES); + memcpy(R, buf, SPX_N); +} + +/** + * Computes the message hash using R, the public key, and the message. + * Outputs the message digest and the index of the leaf. The index is split in + * the tree index and the leaf index, for convenient copying to an address. + */ +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { + (void)ctx; +#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) +#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) +#define SPX_LEAF_BITS SPX_TREE_HEIGHT +#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) +#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) + + unsigned char seed[2 * SPX_N + SPX_SHAX_OUTPUT_BYTES]; + + /* Round to nearest multiple of SPX_SHAX_BLOCK_BYTES */ +#define SPX_INBLOCKS (((SPX_N + SPX_PK_BYTES + SPX_SHAX_BLOCK_BYTES - 1) & \ + -SPX_SHAX_BLOCK_BYTES) / SPX_SHAX_BLOCK_BYTES) + unsigned char inbuf[SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES]; + + unsigned char buf[SPX_DGST_BYTES]; + unsigned char *bufp = buf; + shaXstate state; + + shaX_inc_init(&state); + + // seed: SHA-X(R ‖ PK.seed ‖ PK.root ‖ M) + memcpy(inbuf, R, SPX_N); + memcpy(inbuf + SPX_N, pk, SPX_PK_BYTES); + + /* If R + pk + message cannot fill up an entire block */ + if (SPX_N + SPX_PK_BYTES + mlen < SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES) { + memcpy(inbuf + SPX_N + SPX_PK_BYTES, m, mlen); + shaX_inc_finalize(seed + 2 * SPX_N, &state, inbuf, SPX_N + SPX_PK_BYTES + mlen); + } + /* Otherwise first fill a block, so that finalize only uses the message */ + else { + memcpy(inbuf + SPX_N + SPX_PK_BYTES, m, + SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES - SPX_N - SPX_PK_BYTES); + shaX_inc_blocks(&state, inbuf, SPX_INBLOCKS); + + m += SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES - SPX_N - SPX_PK_BYTES; + mlen -= SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES - SPX_N - SPX_PK_BYTES; + shaX_inc_finalize(seed + 2 * SPX_N, &state, m, (size_t)mlen); + } + + // H_msg: MGF1-SHA-X(R ‖ PK.seed ‖ seed) + memcpy(seed, R, SPX_N); + memcpy(seed + SPX_N, pk, SPX_N); + + /* By doing this in two steps, we prevent hashing the message twice; + otherwise each iteration in MGF1 would hash the message again. */ + mgf1_X(bufp, SPX_DGST_BYTES, seed, 2 * SPX_N + SPX_SHAX_OUTPUT_BYTES); + + memcpy(digest, bufp, SPX_FORS_MSG_BYTES); + bufp += SPX_FORS_MSG_BYTES; + + + *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); + *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); + bufp += SPX_TREE_BYTES; + + *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); + *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); +} + + diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/merkle.c b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/merkle.c new file mode 100644 index 0000000000..0c1479fd93 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/merkle.c @@ -0,0 +1,59 @@ +#include +#include + +#include "address.h" +#include "merkle.h" +#include "params.h" +#include "utils.h" +#include "utilsx1.h" +#include "wots.h" +#include "wotsx1.h" + +/* + * This generates a Merkle signature (WOTS signature followed by the Merkle + * authentication path). This is in this file because most of the complexity + * is involved with the WOTS signature; the Merkle authentication path logic + * is mostly hidden in treehashx4 + */ +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf) { + unsigned char *auth_path = sig + SPX_WOTS_BYTES; + struct leaf_info_x1 info = { 0 }; + unsigned steps[ SPX_WOTS_LEN ]; + + info.wots_sig = sig; + chain_lengths(steps, root); + info.wots_steps = steps; + + set_type(&tree_addr[0], SPX_ADDR_TYPE_HASHTREE); + set_type(&info.pk_addr[0], SPX_ADDR_TYPE_WOTSPK); + copy_subtree_addr(&info.leaf_addr[0], wots_addr); + copy_subtree_addr(&info.pk_addr[0], wots_addr); + + info.wots_sign_leaf = idx_leaf; + + treehashx1(root, auth_path, ctx, + idx_leaf, 0, + SPX_TREE_HEIGHT, + wots_gen_leafx1, + tree_addr, &info); +} + +/* Compute root node of the top-most subtree. */ +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { + /* We do not need the auth path in key generation, but it simplifies the + code to have just one treehash routine that computes both root and path + in one function. */ + unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; + uint32_t top_tree_addr[8] = {0}; + uint32_t wots_addr[8] = {0}; + + set_layer_addr(top_tree_addr, SPX_D - 1); + set_layer_addr(wots_addr, SPX_D - 1); + + merkle_sign(auth_path, root, ctx, + wots_addr, top_tree_addr, + (uint32_t)~0 /* ~0 means "don't bother generating an auth path */ ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/merkle.h b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/merkle.h new file mode 100644 index 0000000000..769cf2e970 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/merkle.h @@ -0,0 +1,21 @@ +#ifndef MERKLE_H_ +#define MERKLE_H_ + +#include + +#include "context.h" +#include "params.h" + +/* Generate a Merkle signature (WOTS signature followed by the Merkle */ +/* authentication path) */ +#define merkle_sign SPX_NAMESPACE(merkle_sign) +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf); + +/* Compute the root node of the top-most subtree. */ +#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); + +#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/nistapi.h b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/nistapi.h new file mode 100644 index 0000000000..3cb71afad4 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/nistapi.h @@ -0,0 +1,87 @@ +#ifndef SPX_API_H +#define SPX_API_H + +#include +#include + +#include "params.h" + +#define CRYPTO_ALGNAME "SPHINCS+" + +#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES +#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES +#define CRYPTO_BYTES SPX_BYTES +#define CRYPTO_SEEDBYTES (3*SPX_N) + +/* + * Returns the length of a secret key, in bytes + */ +#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) +size_t crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) +size_t crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) +size_t crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) +size_t crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +#define crypto_sign SPX_NAMESPACE(crypto_sign) +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/params.h b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/params.h new file mode 100644 index 0000000000..0ded8edbc4 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/params.h @@ -0,0 +1,61 @@ +#ifndef SPX_PARAMS_H +#define SPX_PARAMS_H + +#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSSHA2256SROBUST_CLEAN_##s + +/* Hash output length in bytes. */ +#define SPX_N 32 +/* Height of the hypertree. */ +#define SPX_FULL_HEIGHT 64 +/* Number of subtree layer. */ +#define SPX_D 8 +/* FORS tree dimensions. */ +#define SPX_FORS_HEIGHT 14 +#define SPX_FORS_TREES 22 +/* Winternitz parameter, */ +#define SPX_WOTS_W 16 + +/* The hash function is defined by linking a different hash.c file, as opposed + to setting a #define constant. */ + +/* This is a SHA2-based parameter set, hence whether we use SHA-256 + * exclusively or we use both SHA-256 and SHA-512 is controlled by + * the following #define */ +#define SPX_SHA512 1 /* Use SHA-512 for H and T_l, l >= 2 */ + +/* For clarity */ +#define SPX_ADDR_BYTES 32 + +/* WOTS parameters. */ +#define SPX_WOTS_LOGW 4 + +#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) + +/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ +#define SPX_WOTS_LEN2 3 + +#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) +#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) +#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES + +/* Subtree size. */ +#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) + +//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT +// #error SPX_D should always divide SPX_FULL_HEIGHT +//#endif + +/* FORS parameters. */ +#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) +#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) +#define SPX_FORS_PK_BYTES SPX_N + +/* Resulting SPX sizes. */ +#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ + SPX_FULL_HEIGHT * SPX_N) +#define SPX_PK_BYTES (2 * SPX_N) +#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) + +#include "sha2_offsets.h" + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/sha2_offsets.h b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/sha2_offsets.h new file mode 100644 index 0000000000..6e3584f7a4 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/sha2_offsets.h @@ -0,0 +1,27 @@ +#ifndef SHA2_OFFSETS_H_ +#define SHA2_OFFSETS_H_ + +#define SPX_SHA256_BLOCK_BYTES 64 +#define SPX_SHA256_OUTPUT_BYTES 32 + +#define SPX_SHA512_BLOCK_BYTES 128 +#define SPX_SHA512_OUTPUT_BYTES 64 + +/* + * Offsets of various fields in the address structure when we use SHA2 as + * the Sphincs+ hash function + */ + +#define SPX_OFFSET_LAYER 0 /* The byte used to specify the Merkle tree layer */ +#define SPX_OFFSET_TREE 1 /* The start of the 8 byte field used to specify the tree */ +#define SPX_OFFSET_TYPE 9 /* The byte used to specify the hash type (reason) */ +#define SPX_OFFSET_KP_ADDR2 12 /* The high byte used to specify the key pair (which one-time signature) */ +#define SPX_OFFSET_KP_ADDR1 13 /* The low byte used to specify the key pair */ +#define SPX_OFFSET_CHAIN_ADDR 17 /* The byte used to specify the chain address (which Winternitz chain) */ +#define SPX_OFFSET_HASH_ADDR 21 /* The byte used to specify the hash address (where in the Winternitz chain) */ +#define SPX_OFFSET_TREE_HGT 17 /* The byte used to specify the height of this node in the FORS or Merkle tree */ +#define SPX_OFFSET_TREE_INDEX 18 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ + +#define SPX_SHA2 1 + +#endif /* SHA2_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/sign.c b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/sign.c new file mode 100644 index 0000000000..9d0c7d1b22 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/sign.c @@ -0,0 +1,286 @@ +#include +#include +#include + +#include "address.h" +#include "context.h" +#include "fors.h" +#include "hash.h" +#include "merkle.h" +#include "nistapi.h" +#include "params.h" +#include "randombytes.h" +#include "thash.h" +#include "utils.h" +#include "wots.h" + +/* + * Returns the length of a secret key, in bytes + */ +size_t crypto_sign_secretkeybytes(void) { + return CRYPTO_SECRETKEYBYTES; +} + +/* + * Returns the length of a public key, in bytes + */ +size_t crypto_sign_publickeybytes(void) { + return CRYPTO_PUBLICKEYBYTES; +} + +/* + * Returns the length of a signature, in bytes + */ +size_t crypto_sign_bytes(void) { + return CRYPTO_BYTES; +} + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +size_t crypto_sign_seedbytes(void) { + return CRYPTO_SEEDBYTES; +} + +/* + * Generates an SPX key pair given a seed of length + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [PUB_SEED || root] + */ +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed) { + spx_ctx ctx; + + /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ + memcpy(sk, seed, CRYPTO_SEEDBYTES); + + memcpy(pk, sk + 2 * SPX_N, SPX_N); + + memcpy(ctx.pub_seed, pk, SPX_N); + memcpy(ctx.sk_seed, sk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + /* Compute root node of the top-most subtree. */ + merkle_gen_root(sk + 3 * SPX_N, &ctx); + + // cleanup + free_hash_function(&ctx); + + memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); + + return 0; +} + +/* + * Generates an SPX key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [PUB_SEED || root] + */ +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { + uint8_t seed[CRYPTO_SEEDBYTES]; + randombytes(seed, CRYPTO_SEEDBYTES); + crypto_sign_seed_keypair(pk, sk, seed); + + return 0; +} + +/** + * Returns an array containing a detached signature. + */ +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk) { + spx_ctx ctx; + + const uint8_t *sk_prf = sk + SPX_N; + const uint8_t *pk = sk + 2 * SPX_N; + + uint8_t optrand[SPX_N]; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t root[SPX_N]; + uint32_t i; + uint64_t tree; + uint32_t idx_leaf; + uint32_t wots_addr[8] = {0}; + uint32_t tree_addr[8] = {0}; + + memcpy(ctx.sk_seed, sk, SPX_N); + memcpy(ctx.pub_seed, pk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + + /* Optionally, signing can be made non-deterministic using optrand. + This can help counter side-channel attacks that would benefit from + getting a large number of traces when the signer uses the same nodes. */ + randombytes(optrand, SPX_N); + /* Compute the digest randomization value. */ + gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); + + /* Derive the message digest and leaf index from R, PK and M. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; + + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); + + /* Sign the message hash using FORS. */ + fors_sign(sig, root, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); + sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; + + /* Update the indices for the next layer. */ + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; + } + + free_hash_function(&ctx); + + *siglen = SPX_BYTES; + + return 0; +} + +/** + * Verifies a detached signature and message under a given public key. + */ +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk) { + spx_ctx ctx; + const uint8_t *pub_root = pk + SPX_N; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t wots_pk[SPX_WOTS_BYTES]; + uint8_t root[SPX_N]; + uint8_t leaf[SPX_N]; + unsigned int i; + uint64_t tree; + uint32_t idx_leaf; + uint32_t wots_addr[8] = {0}; + uint32_t tree_addr[8] = {0}; + uint32_t wots_pk_addr[8] = {0}; + + if (siglen != SPX_BYTES) { + return -1; + } + + memcpy(ctx.pub_seed, pk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); + + /* Derive the message digest and leaf index from R || PK || M. */ + /* The additional SPX_N is a result of the hash domain separator. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; + + /* Layer correctly defaults to 0, so no need to set_layer_addr */ + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); + + fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + /* For each subtree.. */ + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + copy_keypair_addr(wots_pk_addr, wots_addr); + + /* The WOTS public key is only correct if the signature was correct. */ + /* Initially, root is the FORS pk, but on subsequent iterations it is + the root of the subtree below the currently processed subtree. */ + wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); + sig += SPX_WOTS_BYTES; + + /* Compute the leaf node using the WOTS public key. */ + thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); + + /* Compute the root node of this subtree. */ + compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, + &ctx, tree_addr); + sig += SPX_TREE_HEIGHT * SPX_N; + + /* Update the indices for the next layer. */ + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; + } + + // cleanup + free_hash_function(&ctx); + + /* Check if the root node equals the root node in the public key. */ + if (memcmp(root, pub_root, SPX_N) != 0) { + return -1; + } + + return 0; +} + + +/** + * Returns an array containing the signature followed by the message. + */ +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk) { + size_t siglen; + + crypto_sign_signature(sm, &siglen, m, mlen, sk); + + memmove(sm + SPX_BYTES, m, mlen); + *smlen = siglen + mlen; + + return 0; +} + +/** + * Verifies a given signature-message pair under a given public key. + */ +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk) { + /* The API caller does not necessarily know what size a signature should be + but SPHINCS+ signatures are always exactly SPX_BYTES. */ + if (smlen < SPX_BYTES) { + memset(m, 0, smlen); + *mlen = 0; + return -1; + } + + *mlen = smlen - SPX_BYTES; + + if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { + memset(m, 0, smlen); + *mlen = 0; + return -1; + } + + /* If verification was successful, move the message to the right place. */ + memmove(m, sm + SPX_BYTES, *mlen); + + return 0; +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/thash.h b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/thash.h new file mode 100644 index 0000000000..8687ccfb4d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/thash.h @@ -0,0 +1,13 @@ +#ifndef SPX_THASH_H +#define SPX_THASH_H + +#include "context.h" +#include "params.h" + +#include + +#define thash SPX_NAMESPACE(thash) +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/thash_sha2_robust.c b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/thash_sha2_robust.c new file mode 100644 index 0000000000..3ab891175f --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/thash_sha2_robust.c @@ -0,0 +1,68 @@ +#include +#include + +#include "address.h" +#include "context.h" +#include "hash.h" +#include "params.h" +#include "sha2.h" +#include "thash.h" +#include "utils.h" + +static void thash_512(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]); + +/** + * Takes an array of inblocks concatenated arrays of SPX_N bytes. + */ +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]) { + if (inblocks > 1) { + thash_512(out, in, inblocks, ctx, addr); + return; + } + unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES]; + PQCLEAN_VLA(uint8_t, bitmask, inblocks * SPX_N); + PQCLEAN_VLA(uint8_t, buf, SPX_N + SPX_SHA256_OUTPUT_BYTES + inblocks * SPX_N); + sha256ctx sha2_state; + unsigned int i; + + memcpy(buf, ctx->pub_seed, SPX_N); + memcpy(buf + SPX_N, addr, SPX_SHA256_ADDR_BYTES); + mgf1_256(bitmask, inblocks * SPX_N, buf, SPX_N + SPX_SHA256_ADDR_BYTES); + + /* Retrieve precomputed state containing pub_seed */ + sha256_inc_ctx_clone(&sha2_state, &ctx->state_seeded); + + for (i = 0; i < inblocks * SPX_N; i++) { + buf[SPX_N + SPX_SHA256_ADDR_BYTES + i] = in[i] ^ bitmask[i]; + } + + sha256_inc_finalize(outbuf, &sha2_state, buf + SPX_N, + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N); + memcpy(out, outbuf, SPX_N); +} + +static void thash_512(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]) { + unsigned char outbuf[SPX_SHA512_OUTPUT_BYTES]; + PQCLEAN_VLA(uint8_t, bitmask, inblocks * SPX_N); + PQCLEAN_VLA(uint8_t, buf, SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N); + sha512ctx sha2_state; + unsigned int i; + + memcpy(buf, ctx->pub_seed, SPX_N); + memcpy(buf + SPX_N, addr, SPX_SHA256_ADDR_BYTES); + mgf1_512(bitmask, inblocks * SPX_N, buf, SPX_N + SPX_SHA256_ADDR_BYTES); + + /* Retrieve precomputed state containing pub_seed */ + sha512_inc_ctx_clone(&sha2_state, &ctx->state_seeded_512); + + for (i = 0; i < inblocks * SPX_N; i++) { + buf[SPX_N + SPX_SHA256_ADDR_BYTES + i] = in[i] ^ bitmask[i]; + } + + sha512_inc_finalize(outbuf, &sha2_state, buf + SPX_N, + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N); + memcpy(out, outbuf, SPX_N); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/utils.c b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/utils.c new file mode 100644 index 0000000000..177b541fb9 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/utils.c @@ -0,0 +1,148 @@ +#include + +#include "utils.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "thash.h" + +/** + * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. + */ +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in) { + int i; + + /* Iterate over out in decreasing order, for big-endianness. */ + for (i = (signed int)outlen - 1; i >= 0; i--) { + out[i] = in & 0xff; + in = in >> 8; + } +} + +void u32_to_bytes(unsigned char *out, uint32_t in) { + out[0] = (unsigned char)(in >> 24); + out[1] = (unsigned char)(in >> 16); + out[2] = (unsigned char)(in >> 8); + out[3] = (unsigned char)in; +} + +/** + * Converts the inlen bytes in 'in' from big-endian byte order to an integer. + */ +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { + unsigned long long retval = 0; + unsigned int i; + + for (i = 0; i < inlen; i++) { + retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); + } + return retval; +} + +/** + * Computes a root node given a leaf and an auth path. + * Expects address to be complete other than the tree_height and tree_index. + */ +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]) { + uint32_t i; + unsigned char buffer[2 * SPX_N]; + + /* If leaf_idx is odd (last bit = 1), current path element is a right child + and auth_path has to go left. Otherwise it is the other way around. */ + if (leaf_idx & 1) { + memcpy(buffer + SPX_N, leaf, SPX_N); + memcpy(buffer, auth_path, SPX_N); + } else { + memcpy(buffer, leaf, SPX_N); + memcpy(buffer + SPX_N, auth_path, SPX_N); + } + auth_path += SPX_N; + + for (i = 0; i < tree_height - 1; i++) { + leaf_idx >>= 1; + idx_offset >>= 1; + /* Set the address of the node we're creating. */ + set_tree_height(addr, i + 1); + set_tree_index(addr, leaf_idx + idx_offset); + + /* Pick the right or left neighbor, depending on parity of the node. */ + if (leaf_idx & 1) { + thash(buffer + SPX_N, buffer, 2, ctx, addr); + memcpy(buffer, auth_path, SPX_N); + } else { + thash(buffer, buffer, 2, ctx, addr); + memcpy(buffer + SPX_N, auth_path, SPX_N); + } + auth_path += SPX_N; + } + + /* The last iteration is exceptional; we do not copy an auth_path node. */ + leaf_idx >>= 1; + idx_offset >>= 1; + set_tree_height(addr, tree_height); + set_tree_index(addr, leaf_idx + idx_offset); + thash(root, buffer, 2, ctx, addr); +} + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx * /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]) { + PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); + PQCLEAN_VLA(unsigned int, heights, tree_height + 1); + unsigned int offset = 0; + uint32_t idx; + uint32_t tree_idx; + + for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { + /* Add the next leaf node to the stack. */ + gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); + offset++; + heights[offset - 1] = 0; + + /* If this is a node we need for the auth path.. */ + if ((leaf_idx ^ 0x1) == idx) { + memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); + } + + /* While the top-most nodes are of equal height.. */ + while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { + /* Compute index of the new node, in the next layer. */ + tree_idx = (idx >> (heights[offset - 1] + 1)); + + /* Set the address of the node we're creating. */ + set_tree_height(tree_addr, heights[offset - 1] + 1); + set_tree_index(tree_addr, + tree_idx + (idx_offset >> (heights[offset - 1] + 1))); + /* Hash the top-most nodes from the stack together. */ + thash(stack + (offset - 2)*SPX_N, + stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); + offset--; + /* Note that the top-most node is now one layer higher. */ + heights[offset - 1]++; + + /* If this is a node we need for the auth path.. */ + if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { + memcpy(auth_path + heights[offset - 1]*SPX_N, + stack + (offset - 1)*SPX_N, SPX_N); + } + } + } + memcpy(root, stack, SPX_N); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/utils.h b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/utils.h new file mode 100644 index 0000000000..64f5d5a53a --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/utils.h @@ -0,0 +1,58 @@ +#ifndef SPX_UTILS_H +#define SPX_UTILS_H + +#include + +#include "compat.h" +#include "context.h" +#include "params.h" + + +/* To support MSVC use alloca() instead of VLAs. See #20. */ + + +/** + * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. + */ +#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in); +#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) +void u32_to_bytes(unsigned char *out, uint32_t in); + +/** + * Converts the inlen bytes in 'in' from big-endian byte order to an integer. + */ +#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); + +/** + * Computes a root node given a leaf and an auth path. + * Expects address to be complete other than the tree_height and tree_index. + */ +#define compute_root SPX_NAMESPACE(compute_root) +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]); + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +#define treehash SPX_NAMESPACE(treehash) +void treehash(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx *ctx /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]); + + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/utilsx1.c b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/utilsx1.c new file mode 100644 index 0000000000..fccb69b35d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/utilsx1.c @@ -0,0 +1,100 @@ +#include + +#include "utilsx1.h" + +#include "address.h" +#include "params.h" +#include "thash.h" +#include "utils.h" + +/* + * Generate the entire Merkle tree, computing the authentication path for + * leaf_idx, and the resulting root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) + * + * This expects tree_addr to be initialized to the addr structures for the + * Merkle tree nodes + * + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + * + * This works by using the standard Merkle tree building algorithm, + */ +void treehashx1(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, + uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* Where to write the leaves */, + const spx_ctx * /* ctx */, + uint32_t idx, void *info), + uint32_t tree_addr[8], + void *info) { + /* This is where we keep the intermediate nodes */ + PQCLEAN_VLA(uint8_t, stack, tree_height * SPX_N); + + uint32_t idx; + uint32_t max_idx = (uint32_t)((1 << tree_height) - 1); + for (idx = 0;; idx++) { + unsigned char current[2 * SPX_N]; /* Current logical node is at */ + /* index[SPX_N]. We do this to minimize the number of copies */ + /* needed during a thash */ + gen_leaf( ¤t[SPX_N], ctx, idx + idx_offset, + info ); + + /* Now combine the freshly generated right node with previously */ + /* generated left ones */ + uint32_t internal_idx_offset = idx_offset; + uint32_t internal_idx = idx; + uint32_t internal_leaf = leaf_idx; + uint32_t h; /* The height we are in the Merkle tree */ + for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { + + /* Check if we hit the top of the tree */ + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[SPX_N], SPX_N ); + return; + } + + /* + * Check if the node we have is a part of the + * authentication path; if it is, write it out + */ + if ((internal_idx ^ internal_leaf) == 0x01) { + memcpy( &auth_path[ h * SPX_N ], + ¤t[SPX_N], + SPX_N ); + } + + /* + * Check if we're at a left child; if so, stop going up the stack + * Exception: if we've reached the end of the tree, keep on going + * (so we combine the last 4 nodes into the one root node in two + * more iterations) + */ + if ((internal_idx & 1) == 0 && idx < max_idx) { + break; + } + + /* Ok, we're at a right node */ + /* Now combine the left and right logical nodes together */ + + /* Set the address of the node we're creating. */ + internal_idx_offset >>= 1; + set_tree_height(tree_addr, h + 1); + set_tree_index(tree_addr, internal_idx / 2 + internal_idx_offset ); + + unsigned char *left = &stack[h * SPX_N]; + memcpy( ¤t[0], left, SPX_N ); + thash( ¤t[1 * SPX_N], + ¤t[0 * SPX_N], + 2, ctx, tree_addr); + } + + /* We've hit a left child; save the current for when we get the */ + /* corresponding right right */ + memcpy( &stack[h * SPX_N], ¤t[SPX_N], SPX_N); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/utilsx1.h b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/utilsx1.h new file mode 100644 index 0000000000..e911d17d53 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/utilsx1.h @@ -0,0 +1,27 @@ +#ifndef SPX_UTILSX4_H +#define SPX_UTILSX4_H + +#include + +#include "context.h" +#include "params.h" + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +#define treehashx1 SPX_NAMESPACE(treehashx1) +void treehashx1(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* Where to write the leaf */, + const spx_ctx * /* ctx */, + uint32_t addr_idx, void *info), + uint32_t tree_addrx4[8], void *info); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/wots.c b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/wots.c new file mode 100644 index 0000000000..249717aaa8 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/wots.c @@ -0,0 +1,108 @@ +#include +#include + +#include "wots.h" +#include "wotsx1.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "thash.h" +#include "utils.h" +#include "utilsx1.h" + +// TODO clarify address expectations, and make them more uniform. +// TODO i.e. do we expect types to be set already? +// TODO and do we expect modifications or copies? + +/** + * Computes the chaining function. + * out and in have to be n-byte arrays. + * + * Interprets in as start-th value of the chain. + * addr has to contain the address of the chain. + */ +static void gen_chain(unsigned char *out, const unsigned char *in, + unsigned int start, unsigned int steps, + const spx_ctx *ctx, uint32_t addr[8]) { + uint32_t i; + + /* Initialize out with the value at position 'start'. */ + memcpy(out, in, SPX_N); + + /* Iterate 'steps' calls to the hash function. */ + for (i = start; i < (start + steps) && i < SPX_WOTS_W; i++) { + set_hash_addr(addr, i); + thash(out, out, 1, ctx, addr); + } +} + +/** + * base_w algorithm as described in draft. + * Interprets an array of bytes as integers in base w. + * This only works when log_w is a divisor of 8. + */ +static void base_w(unsigned int *output, const int out_len, + const unsigned char *input) { + int in = 0; + int out = 0; + unsigned char total = 0; + int bits = 0; + int consumed; + + for (consumed = 0; consumed < out_len; consumed++) { + if (bits == 0) { + total = input[in]; + in++; + bits += 8; + } + bits -= SPX_WOTS_LOGW; + output[out] = (total >> bits) & (SPX_WOTS_W - 1); + out++; + } +} + +/* Computes the WOTS+ checksum over a message (in base_w). */ +static void wots_checksum(unsigned int *csum_base_w, + const unsigned int *msg_base_w) { + unsigned int csum = 0; + unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; + unsigned int i; + + /* Compute checksum. */ + for (i = 0; i < SPX_WOTS_LEN1; i++) { + csum += SPX_WOTS_W - 1 - msg_base_w[i]; + } + + /* Convert checksum to base_w. */ + /* Make sure expected empty zero bits are the least significant bits. */ + csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); + ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); + base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); +} + +/* Takes a message and derives the matching chain lengths. */ +void chain_lengths(unsigned int *lengths, const unsigned char *msg) { + base_w(lengths, SPX_WOTS_LEN1, msg); + wots_checksum(lengths + SPX_WOTS_LEN1, lengths); +} + +/** + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. + * + * Writes the computed public key to 'pk'. + */ +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]) { + unsigned int lengths[SPX_WOTS_LEN]; + uint32_t i; + + chain_lengths(lengths, msg); + + for (i = 0; i < SPX_WOTS_LEN; i++) { + set_chain_addr(addr, i); + gen_chain(pk + i * SPX_N, sig + i * SPX_N, + lengths[i], SPX_WOTS_W - 1 - lengths[i], ctx, addr); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/wots.h b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/wots.h new file mode 100644 index 0000000000..4e7692eeef --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/wots.h @@ -0,0 +1,25 @@ +#ifndef SPX_WOTS_H +#define SPX_WOTS_H + +#include + +#include "context.h" +#include "params.h" + +/** + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. + * + * Writes the computed public key to 'pk'. + */ +#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]); + +/* + * Compute the chain lengths needed for a given message hash + */ +#define chain_lengths SPX_NAMESPACE(chain_lengths) +void chain_lengths(unsigned int *lengths, const unsigned char *msg); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/wotsx1.c b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/wotsx1.c new file mode 100644 index 0000000000..3adec78dfb --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/wotsx1.c @@ -0,0 +1,76 @@ +#include +#include + +#include "wots.h" +#include "wotsx1.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "thash.h" +#include "utils.h" + +/* + * This generates a WOTS public key + * It also generates the WOTS signature if leaf_info indicates + * that we're signing with this WOTS key + */ +void wots_gen_leafx1(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info) { + struct leaf_info_x1 *info = v_info; + uint32_t *leaf_addr = info->leaf_addr; + uint32_t *pk_addr = info->pk_addr; + unsigned int i, k; + unsigned char pk_buffer[ SPX_WOTS_BYTES ]; + unsigned char *buffer; + uint32_t wots_k_mask; + + if (leaf_idx == info->wots_sign_leaf) { + /* We're traversing the leaf that's signing; generate the WOTS */ + /* signature */ + wots_k_mask = 0; + } else { + /* Nope, we're just generating pk's; turn off the signature logic */ + wots_k_mask = (uint32_t)~0; + } + + set_keypair_addr( leaf_addr, leaf_idx ); + set_keypair_addr( pk_addr, leaf_idx ); + + for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { + uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k to */ + /* the step if we're generating a signature, ~0 if we're not */ + + /* Start with the secret seed */ + set_chain_addr(leaf_addr, i); + set_hash_addr(leaf_addr, 0); + set_type(leaf_addr, SPX_ADDR_TYPE_WOTSPRF); + + prf_addr(buffer, ctx, leaf_addr); + + set_type(leaf_addr, SPX_ADDR_TYPE_WOTS); + + /* Iterate down the WOTS chain */ + for (k = 0;; k++) { + /* Check if this is the value that needs to be saved as a */ + /* part of the WOTS signature */ + if (k == wots_k) { + memcpy( info->wots_sig + i * SPX_N, buffer, SPX_N ); + } + + /* Check if we hit the top of the chain */ + if (k == SPX_WOTS_W - 1) { + break; + } + + /* Iterate one step on the chain */ + set_hash_addr(leaf_addr, k); + + thash(buffer, buffer, 1, ctx, leaf_addr); + } + } + + /* Do the final thash to generate the public keys */ + thash(dest, pk_buffer, SPX_WOTS_LEN, ctx, pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/wotsx1.h b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/wotsx1.h new file mode 100644 index 0000000000..e617929f96 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/wotsx1.h @@ -0,0 +1,39 @@ +#ifndef WOTSX1_H_ +#define WOTSX1_H_ + +#include + +#include "context.h" +#include "params.h" + +/* + * This is here to provide an interface to the internal wots_gen_leafx1 + * routine. While this routine is not referenced in the package outside of + * wots.c, it is called from the stand-alone benchmark code to characterize + * the performance + */ +struct leaf_info_x1 { + unsigned char *wots_sig; + uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ + uint32_t *wots_steps; + uint32_t leaf_addr[8]; + uint32_t pk_addr[8]; +}; + +/* Macro to set the leaf_info to something 'benign', that is, it would */ +/* run with the same time as it does during the real signing process */ +/* Used only by the benchmark code */ +#define INITIALIZE_LEAF_INFO_X1(info, addr, step_buffer) { \ + (info).wots_sig = 0; \ + (info).wots_sign_leaf = ~0; \ + (info).wots_steps = step_buffer; \ + memcpy( &(info).leaf_addr[0], (addr), 32 ); \ + memcpy( &(info).pk_addr[0], (addr), 32 ); \ + } + +#define wots_gen_leafx1 SPX_NAMESPACE(wots_gen_leafx1) +void wots_gen_leafx1(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info); + +#endif /* WOTSX1_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/LICENSE b/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/LICENSE new file mode 100644 index 0000000000..670154e353 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/LICENSE @@ -0,0 +1,116 @@ +CC0 1.0 Universal + +Statement of Purpose + +The laws of most jurisdictions throughout the world automatically confer +exclusive Copyright and Related Rights (defined below) upon the creator and +subsequent owner(s) (each and all, an "owner") of an original work of +authorship and/or a database (each, a "Work"). + +Certain owners wish to permanently relinquish those rights to a Work for the +purpose of contributing to a commons of creative, cultural and scientific +works ("Commons") that the public can reliably and without fear of later +claims of infringement build upon, modify, incorporate in other works, reuse +and redistribute as freely as possible in any form whatsoever and for any +purposes, including without limitation commercial purposes. These owners may +contribute to the Commons to promote the ideal of a free culture and the +further production of creative, cultural and scientific works, or to gain +reputation or greater distribution for their Work in part through the use and +efforts of others. + +For these and/or other purposes and motivations, and without any expectation +of additional consideration or compensation, the person associating CC0 with a +Work (the "Affirmer"), to the extent that he or she is an owner of Copyright +and Related Rights in the Work, voluntarily elects to apply CC0 to the Work +and publicly distribute the Work under its terms, with knowledge of his or her +Copyright and Related Rights in the Work and the meaning and intended legal +effect of CC0 on those rights. + +1. Copyright and Related Rights. A Work made available under CC0 may be +protected by copyright and related or neighboring rights ("Copyright and +Related Rights"). Copyright and Related Rights include, but are not limited +to, the following: + + i. the right to reproduce, adapt, distribute, perform, display, communicate, + and translate a Work; + + ii. moral rights retained by the original author(s) and/or performer(s); + + iii. publicity and privacy rights pertaining to a person's image or likeness + depicted in a Work; + + iv. rights protecting against unfair competition in regards to a Work, + subject to the limitations in paragraph 4(a), below; + + v. rights protecting the extraction, dissemination, use and reuse of data in + a Work; + + vi. database rights (such as those arising under Directive 96/9/EC of the + European Parliament and of the Council of 11 March 1996 on the legal + protection of databases, and under any national implementation thereof, + including any amended or successor version of such directive); and + + vii. other similar, equivalent or corresponding rights throughout the world + based on applicable law or treaty, and any national implementations thereof. + +2. Waiver. To the greatest extent permitted by, but not in contravention of, +applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and +unconditionally waives, abandons, and surrenders all of Affirmer's Copyright +and Related Rights and associated claims and causes of action, whether now +known or unknown (including existing as well as future claims and causes of +action), in the Work (i) in all territories worldwide, (ii) for the maximum +duration provided by applicable law or treaty (including future time +extensions), (iii) in any current or future medium and for any number of +copies, and (iv) for any purpose whatsoever, including without limitation +commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes +the Waiver for the benefit of each member of the public at large and to the +detriment of Affirmer's heirs and successors, fully intending that such Waiver +shall not be subject to revocation, rescission, cancellation, termination, or +any other legal or equitable action to disrupt the quiet enjoyment of the Work +by the public as contemplated by Affirmer's express Statement of Purpose. + +3. Public License Fallback. Should any part of the Waiver for any reason be +judged legally invalid or ineffective under applicable law, then the Waiver +shall be preserved to the maximum extent permitted taking into account +Affirmer's express Statement of Purpose. In addition, to the extent the Waiver +is so judged Affirmer hereby grants to each affected person a royalty-free, +non transferable, non sublicensable, non exclusive, irrevocable and +unconditional license to exercise Affirmer's Copyright and Related Rights in +the Work (i) in all territories worldwide, (ii) for the maximum duration +provided by applicable law or treaty (including future time extensions), (iii) +in any current or future medium and for any number of copies, and (iv) for any +purpose whatsoever, including without limitation commercial, advertising or +promotional purposes (the "License"). The License shall be deemed effective as +of the date CC0 was applied by Affirmer to the Work. Should any part of the +License for any reason be judged legally invalid or ineffective under +applicable law, such partial invalidity or ineffectiveness shall not +invalidate the remainder of the License, and in such case Affirmer hereby +affirms that he or she will not (i) exercise any of his or her remaining +Copyright and Related Rights in the Work or (ii) assert any associated claims +and causes of action with respect to the Work, in either case contrary to +Affirmer's express Statement of Purpose. + +4. Limitations and Disclaimers. + + a. No trademark or patent rights held by Affirmer are waived, abandoned, + surrendered, licensed or otherwise affected by this document. + + b. Affirmer offers the Work as-is and makes no representations or warranties + of any kind concerning the Work, express, implied, statutory or otherwise, + including without limitation warranties of title, merchantability, fitness + for a particular purpose, non infringement, or the absence of latent or + other defects, accuracy, or the present or absence of errors, whether or not + discoverable, all to the greatest extent permissible under applicable law. + + c. Affirmer disclaims responsibility for clearing rights of other persons + that may apply to the Work or any use thereof, including without limitation + any person's Copyright and Related Rights in the Work. Further, Affirmer + disclaims responsibility for obtaining any necessary consents, permissions + or other rights required for any use of the Work. + + d. Affirmer understands and acknowledges that Creative Commons is not a + party to this document and has no duty or obligation with respect to this + CC0 or use of the Work. + +For more information, please see + diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/address.c b/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/address.c new file mode 100644 index 0000000000..b956e9cb29 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/address.c @@ -0,0 +1,91 @@ +#include +#include + +#include "address.h" +#include "params.h" +#include "utils.h" + +/* + * Specify which level of Merkle tree (the "layer") we're working on + */ +void set_layer_addr(uint32_t addr[8], uint32_t layer) { + ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; +} + +/* + * Specify which Merkle tree within the level (the "tree address") we're working on + */ +void set_tree_addr(uint32_t addr[8], uint64_t tree) { + ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); +} + +/* + * Specify the reason we'll use this address structure for, that is, what + * hash will we compute with it. This is used so that unrelated types of + * hashes don't accidentally get the same address structure. The type will be + * one of the SPX_ADDR_TYPE constants + */ +void set_type(uint32_t addr[8], uint32_t type) { + ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; +} + +/* + * Copy the layer and tree fields of the address structure. This is used + * when we're doing multiple types of hashes within the same Merkle tree + */ +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); +} + +/* These functions are used for OTS addresses. */ + +/* + * Specify which Merkle leaf we're working on; that is, which OTS keypair + * we're talking about. + */ +void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { + ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; +} + +/* + * Copy the layer, tree and keypair fields of the address structure. This is + * used when we're doing multiple things within the same OTS keypair + */ +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); + ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; +} + +/* + * Specify which Merkle chain within the OTS we're working with + * (the chain address) + */ +void set_chain_addr(uint32_t addr[8], uint32_t chain) { + ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; +} + +/* + * Specify where in the Merkle chain we are +* (the hash address) + */ +void set_hash_addr(uint32_t addr[8], uint32_t hash) { + ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; +} + +/* These functions are used for all hash tree addresses (including FORS). */ + +/* + * Specify the height of the node in the Merkle/FORS tree we are in + * (the tree height) + */ +void set_tree_height(uint32_t addr[8], uint32_t tree_height) { + ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; +} + +/* + * Specify the distance from the left edge of the node in the Merkle/FORS tree + * (the tree index) + */ +void set_tree_index(uint32_t addr[8], uint32_t tree_index) { + u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/address.h b/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/address.h new file mode 100644 index 0000000000..24a84eb40c --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/address.h @@ -0,0 +1,52 @@ +#ifndef SPX_ADDRESS_H +#define SPX_ADDRESS_H + +#include + +#include "params.h" + +/* The hash types that are passed to set_type */ +#define SPX_ADDR_TYPE_WOTS 0 +#define SPX_ADDR_TYPE_WOTSPK 1 +#define SPX_ADDR_TYPE_HASHTREE 2 +#define SPX_ADDR_TYPE_FORSTREE 3 +#define SPX_ADDR_TYPE_FORSPK 4 +#define SPX_ADDR_TYPE_WOTSPRF 5 +#define SPX_ADDR_TYPE_FORSPRF 6 + +#define set_layer_addr SPX_NAMESPACE(set_layer_addr) +void set_layer_addr(uint32_t addr[8], uint32_t layer); + +#define set_tree_addr SPX_NAMESPACE(set_tree_addr) +void set_tree_addr(uint32_t addr[8], uint64_t tree); + +#define set_type SPX_NAMESPACE(set_type) +void set_type(uint32_t addr[8], uint32_t type); + +/* Copies the layer and tree part of one address into the other */ +#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); + +/* These functions are used for WOTS and FORS addresses. */ + +#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) +void set_keypair_addr(uint32_t addr[8], uint32_t keypair); + +#define set_chain_addr SPX_NAMESPACE(set_chain_addr) +void set_chain_addr(uint32_t addr[8], uint32_t chain); + +#define set_hash_addr SPX_NAMESPACE(set_hash_addr) +void set_hash_addr(uint32_t addr[8], uint32_t hash); + +#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); + +/* These functions are used for all hash tree addresses (including FORS). */ + +#define set_tree_height SPX_NAMESPACE(set_tree_height) +void set_tree_height(uint32_t addr[8], uint32_t tree_height); + +#define set_tree_index SPX_NAMESPACE(set_tree_index) +void set_tree_index(uint32_t addr[8], uint32_t tree_index); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/api.h b/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/api.h new file mode 100644 index 0000000000..ac4c3ceb64 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/api.h @@ -0,0 +1,77 @@ +#ifndef PQCLEAN_SPHINCSSHA2256SSIMPLE_AVX2_API_H +#define PQCLEAN_SPHINCSSHA2256SSIMPLE_AVX2_API_H + +#include +#include + +#define PQCLEAN_SPHINCSSHA2256SSIMPLE_AVX2_CRYPTO_ALGNAME "SPHINCS+-sha2-256s-simple" + +#define PQCLEAN_SPHINCSSHA2256SSIMPLE_AVX2_CRYPTO_SECRETKEYBYTES 128 +#define PQCLEAN_SPHINCSSHA2256SSIMPLE_AVX2_CRYPTO_PUBLICKEYBYTES 64 +#define PQCLEAN_SPHINCSSHA2256SSIMPLE_AVX2_CRYPTO_BYTES 29792 + +#define PQCLEAN_SPHINCSSHA2256SSIMPLE_AVX2_CRYPTO_SEEDBYTES 96 + +/* + * Returns the length of a secret key, in bytes + */ +size_t PQCLEAN_SPHINCSSHA2256SSIMPLE_AVX2_crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +size_t PQCLEAN_SPHINCSSHA2256SSIMPLE_AVX2_crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +size_t PQCLEAN_SPHINCSSHA2256SSIMPLE_AVX2_crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +size_t PQCLEAN_SPHINCSSHA2256SSIMPLE_AVX2_crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +int PQCLEAN_SPHINCSSHA2256SSIMPLE_AVX2_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +int PQCLEAN_SPHINCSSHA2256SSIMPLE_AVX2_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +int PQCLEAN_SPHINCSSHA2256SSIMPLE_AVX2_crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +int PQCLEAN_SPHINCSSHA2256SSIMPLE_AVX2_crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, + const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +int PQCLEAN_SPHINCSSHA2256SSIMPLE_AVX2_crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +int PQCLEAN_SPHINCSSHA2256SSIMPLE_AVX2_crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/context.h b/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/context.h new file mode 100644 index 0000000000..d3bf1c3aac --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/context.h @@ -0,0 +1,29 @@ +#ifndef SPX_CONTEXT_H +#define SPX_CONTEXT_H + +#include + +#include "params.h" +#include "sha2.h" +#include "sha256avx.h" +#include "sha512x4.h" + +// funky ordering due to optimal padding +typedef struct { + sha256x8ctx statex8_seeded; + sha512x4ctx statex4_seeded_512; + sha256ctx state_seeded; + sha512ctx state_seeded_512; + + uint8_t pub_seed[SPX_N]; + uint8_t sk_seed[SPX_N]; +} spx_ctx; + + +#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) +void initialize_hash_function(spx_ctx *ctx); + +#define free_hash_function SPX_NAMESPACE(free_hash_function) +void free_hash_function(spx_ctx *ctx); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/context_sha2.c b/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/context_sha2.c new file mode 100644 index 0000000000..83c1b6585d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/context_sha2.c @@ -0,0 +1,56 @@ +#include + +#include "context.h" + +/** + * Absorb the constant pub_seed using one round of the compression function + * This initializes state_seeded and state_seeded_512, which can then be + * reused in thash + **/ +static void seed_state(spx_ctx *ctx) { + uint8_t block[SPX_SHA512_BLOCK_BYTES]; + size_t i; + + for (i = 0; i < SPX_N; ++i) { + block[i] = ctx->pub_seed[i]; + } + for (i = SPX_N; i < SPX_SHA512_BLOCK_BYTES; ++i) { + block[i] = 0; + } + /* block has been properly initialized for both SHA-256 and SHA-512 */ + + sha256_inc_init(&ctx->state_seeded); + sha256_inc_blocks(&ctx->state_seeded, block, 1); + + // initialize x8 + sha256_init8x(&ctx->statex8_seeded); + sha256_transform8x(&ctx->statex8_seeded, + block, block, block, block, block, block, block, block); + + ctx->statex8_seeded.datalen = 0; + ctx->statex8_seeded.msglen = 512; + + sha512_inc_init(&ctx->state_seeded_512); + sha512_inc_blocks(&ctx->state_seeded_512, block, 1); + + // initialize x4 + sha512_init4x(&ctx->statex4_seeded_512); + sha512_transform4x(&ctx->statex4_seeded_512, block, block, block, block); + + ctx->statex4_seeded_512.datalen = 0; + ctx->statex4_seeded_512.msglen = 1024; + + +} + + +/* For SHA, we initialize the hash function at the start */ +void initialize_hash_function(spx_ctx *ctx) { + seed_state(ctx); +} + +/* Free the incremental hashing context for heap-based SHA2 APIs */ +void free_hash_function(spx_ctx *ctx) { + sha256_inc_ctx_release(&ctx->state_seeded); + sha512_inc_ctx_release(&ctx->state_seeded_512); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/fors.c b/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/fors.c new file mode 100644 index 0000000000..4cab8e7415 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/fors.c @@ -0,0 +1,226 @@ +#include +#include +#include + +#include "fors.h" + + +#include "address.h" +#include "hash.h" +#include "hashx8.h" +#include "thash.h" +#include "thashx8.h" +#include "utils.h" +#include "utilsx8.h" +static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + prf_addr(sk, ctx, fors_leaf_addr); +} + +static void fors_gen_skx8(unsigned char *sk0, + unsigned char *sk1, + unsigned char *sk2, + unsigned char *sk3, + unsigned char *sk4, + unsigned char *sk5, + unsigned char *sk6, + unsigned char *sk7, const spx_ctx *ctx, + uint32_t fors_leaf_addrx8[8 * 8]) { + prf_addrx8(sk0, sk1, sk2, sk3, sk4, sk5, sk6, sk7, + ctx, fors_leaf_addrx8); +} + +static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, + const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + thash(leaf, sk, 1, ctx, fors_leaf_addr); +} + +static void fors_sk_to_leafx8(unsigned char *leaf0, + unsigned char *leaf1, + unsigned char *leaf2, + unsigned char *leaf3, + unsigned char *leaf4, + unsigned char *leaf5, + unsigned char *leaf6, + unsigned char *leaf7, + const unsigned char *sk0, + const unsigned char *sk1, + const unsigned char *sk2, + const unsigned char *sk3, + const unsigned char *sk4, + const unsigned char *sk5, + const unsigned char *sk6, + const unsigned char *sk7, + const spx_ctx *ctx, + uint32_t fors_leaf_addrx8[8 * 8]) { + thashx8(leaf0, leaf1, leaf2, leaf3, leaf4, leaf5, leaf6, leaf7, + sk0, sk1, sk2, sk3, sk4, sk5, sk6, sk7, + 1, ctx, fors_leaf_addrx8); +} + +struct fors_gen_leaf_info { + uint32_t leaf_addrx[8 * 8]; +}; + +static void fors_gen_leafx8(unsigned char *leaf, + const spx_ctx *ctx, + uint32_t addr_idx, void *info) { + struct fors_gen_leaf_info *fors_info = info; + uint32_t *fors_leaf_addrx8 = fors_info->leaf_addrx; + unsigned int j; + + /* Only set the parts that the caller doesn't set */ + for (j = 0; j < 8; j++) { + set_tree_index(fors_leaf_addrx8 + j * 8, addr_idx + j); + set_type(fors_leaf_addrx8 + j * 8, SPX_ADDR_TYPE_FORSPRF); + } + + fors_gen_skx8(leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + leaf + 2 * SPX_N, + leaf + 3 * SPX_N, + leaf + 4 * SPX_N, + leaf + 5 * SPX_N, + leaf + 6 * SPX_N, + leaf + 7 * SPX_N, + ctx, fors_leaf_addrx8); + + for (j = 0; j < 8; j++) { + set_type(fors_leaf_addrx8 + j * 8, SPX_ADDR_TYPE_FORSTREE); + } + + fors_sk_to_leafx8(leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + leaf + 2 * SPX_N, + leaf + 3 * SPX_N, + leaf + 4 * SPX_N, + leaf + 5 * SPX_N, + leaf + 6 * SPX_N, + leaf + 7 * SPX_N, + leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + leaf + 2 * SPX_N, + leaf + 3 * SPX_N, + leaf + 4 * SPX_N, + leaf + 5 * SPX_N, + leaf + 6 * SPX_N, + leaf + 7 * SPX_N, + ctx, fors_leaf_addrx8); +} + +/** + * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + * Assumes indices has space for SPX_FORS_TREES integers. + */ +static void message_to_indices(uint32_t *indices, const unsigned char *m) { + unsigned int i, j; + unsigned int offset = 0; + + for (i = 0; i < SPX_FORS_TREES; i++) { + indices[i] = 0; + for (j = 0; j < SPX_FORS_HEIGHT; j++) { + indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); + offset++; + } + } +} + +/** + * Signs a message m, deriving the secret key from sk_seed and the FTS address. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + uint32_t fors_tree_addr[8 * 8] = {0}; + struct fors_gen_leaf_info fors_info = {0}; + uint32_t *fors_leaf_addr = fors_info.leaf_addrx; + uint32_t fors_pk_addr[8] = {0}; + uint32_t idx_offset; + unsigned int i; + + for (i = 0; i < 8; i++) { + copy_keypair_addr(fors_tree_addr + 8 * i, fors_addr); + set_type(fors_tree_addr + 8 * i, SPX_ADDR_TYPE_FORSTREE); + copy_keypair_addr(fors_leaf_addr + 8 * i, fors_addr); + } + copy_keypair_addr(fors_pk_addr, fors_addr); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); + + message_to_indices(indices, m); + + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); + + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + + /* Include the secret key part that produces the selected leaf node. */ + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); + fors_gen_sk(sig, ctx, fors_tree_addr); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + sig += SPX_N; + + /* Compute the authentication path for this leaf node. */ + treehashx8(roots + i * SPX_N, sig, ctx, + indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx8, + fors_tree_addr, &fors_info); + + sig += SPX_N * SPX_FORS_HEIGHT; + } + + /* Hash horizontally across all tree roots to derive the public key. */ + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); +} + +/** + * Derives the FORS public key from a signature. + * This can be used for verification by comparing to a known public key, or to + * subsequently verify a signature on the derived public key. The latter is the + * typical use-case when used as an FTS below an OTS in a hypertree. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + unsigned char leaf[SPX_N]; + uint32_t fors_tree_addr[8] = {0}; + uint32_t fors_pk_addr[8] = {0}; + uint32_t idx_offset; + unsigned int i; + + copy_keypair_addr(fors_tree_addr, fors_addr); + copy_keypair_addr(fors_pk_addr, fors_addr); + + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); + + message_to_indices(indices, m); + + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); + + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + + /* Derive the leaf from the included secret key part. */ + fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); + sig += SPX_N; + + /* Derive the corresponding root node of this tree. */ + compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, + sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); + sig += SPX_N * SPX_FORS_HEIGHT; + } + + /* Hash horizontally across all tree roots to derive the public key. */ + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/fors.h b/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/fors.h new file mode 100644 index 0000000000..509140a178 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/fors.h @@ -0,0 +1,32 @@ +#ifndef SPX_FORS_H +#define SPX_FORS_H + +#include + +#include "context.h" +#include "params.h" + +/** + * Signs a message m, deriving the secret key from sk_seed and the FTS address. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +#define fors_sign SPX_NAMESPACE(fors_sign) +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); + +/** + * Derives the FORS public key from a signature. + * This can be used for verification by comparing to a known public key, or to + * subsequently verify a signature on the derived public key. The latter is the + * typical use-case when used as an FTS below an OTS in a hypertree. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/hash.h b/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/hash.h new file mode 100644 index 0000000000..ffe815f45d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/hash.h @@ -0,0 +1,37 @@ +#ifndef SPX_HASH_H +#define SPX_HASH_H + +#include +#include + +#include "context.h" +#include "params.h" + +#define prf_addr SPX_NAMESPACE(prf_addr) +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]); + +#define gen_message_random SPX_NAMESPACE(gen_message_random) +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); + +#define hash_message SPX_NAMESPACE(hash_message) +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); + + +# define SPX_SHA256_ADDR_BYTES 22 + +# define mgf1_256 SPX_NAMESPACE(mgf1_256) +void mgf1_256(unsigned char *out, unsigned long outlen, + const unsigned char *in, unsigned long inlen); + +# define mgf1_512 SPX_NAMESPACE(mgf1_512) +void mgf1_512(unsigned char *out, unsigned long outlen, + const unsigned char *in, unsigned long inlen); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/hash_sha2.c b/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/hash_sha2.c new file mode 100644 index 0000000000..3d0085c8c1 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/hash_sha2.c @@ -0,0 +1,219 @@ +#include +#include + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "sha2.h" +#include "utils.h" + + + +#define SPX_SHAX_OUTPUT_BYTES SPX_SHA512_OUTPUT_BYTES +#define SPX_SHAX_BLOCK_BYTES SPX_SHA512_BLOCK_BYTES +#define shaX_inc_init sha512_inc_init +#define shaX_inc_blocks sha512_inc_blocks +#define shaX_inc_finalize sha512_inc_finalize +#define shaX sha512 +#define mgf1_X mgf1_512 +#define shaXstate sha512ctx + +/** + * mgf1 function based on the SHA-256 hash function + * Note that inlen should be sufficiently small that it still allows for + * an array to be allocated on the stack. Typically 'in' is merely a seed. + * Outputs outlen number of bytes + */ +void mgf1_256(unsigned char *out, unsigned long outlen, + const unsigned char *in, unsigned long inlen) { + PQCLEAN_VLA(uint8_t, inbuf, inlen + 4); + unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES]; + uint32_t i; + + memcpy(inbuf, in, inlen); + + /* While we can fit in at least another full block of SHA256 output.. */ + for (i = 0; (i + 1)*SPX_SHA256_OUTPUT_BYTES <= outlen; i++) { + u32_to_bytes(inbuf + inlen, i); + sha256(out, inbuf, inlen + 4); + out += SPX_SHA256_OUTPUT_BYTES; + } + /* Until we cannot anymore, and we fill the remainder. */ + if (outlen > i * SPX_SHA256_OUTPUT_BYTES) { + u32_to_bytes(inbuf + inlen, i); + sha256(outbuf, inbuf, inlen + 4); + memcpy(out, outbuf, outlen - i * SPX_SHA256_OUTPUT_BYTES); + } +} + +/* + * mgf1 function based on the SHA-512 hash function + */ +void mgf1_512(unsigned char *out, unsigned long outlen, + const unsigned char *in, unsigned long inlen) { + PQCLEAN_VLA(uint8_t, inbuf, inlen + 4); + unsigned char outbuf[SPX_SHA512_OUTPUT_BYTES]; + uint32_t i; + + memcpy(inbuf, in, inlen); + + /* While we can fit in at least another full block of SHA512 output.. */ + for (i = 0; (i + 1)*SPX_SHA512_OUTPUT_BYTES <= outlen; i++) { + u32_to_bytes(inbuf + inlen, i); + sha512(out, inbuf, inlen + 4); + out += SPX_SHA512_OUTPUT_BYTES; + } + /* Until we cannot anymore, and we fill the remainder. */ + if (outlen > i * SPX_SHA512_OUTPUT_BYTES) { + u32_to_bytes(inbuf + inlen, i); + sha512(outbuf, inbuf, inlen + 4); + memcpy(out, outbuf, outlen - i * SPX_SHA512_OUTPUT_BYTES); + } +} + +/* + * Computes PRF(pk_seed, sk_seed, addr). + */ +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]) { + sha256ctx sha2_state; + unsigned char buf[SPX_SHA256_ADDR_BYTES + SPX_N]; + unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES]; + + /* Retrieve precomputed state containing pub_seed */ + sha256_inc_ctx_clone(&sha2_state, &ctx->state_seeded); + + /* Remainder: ADDR^c ‖ SK.seed */ + memcpy(buf, addr, SPX_SHA256_ADDR_BYTES); + memcpy(buf + SPX_SHA256_ADDR_BYTES, ctx->sk_seed, SPX_N); + + sha256_inc_finalize(outbuf, &sha2_state, buf, SPX_SHA256_ADDR_BYTES + SPX_N); + + memcpy(out, outbuf, SPX_N); +} + +/** + * Computes the message-dependent randomness R, using a secret seed as a key + * for HMAC, and an optional randomization value prefixed to the message. + * This requires m to have at least SPX_SHAX_BLOCK_BYTES + SPX_N space + * available in front of the pointer, i.e. before the message to use for the + * prefix. This is necessary to prevent having to move the message around (and + * allocate memory for it). + */ +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { + (void)ctx; + + unsigned char buf[SPX_SHAX_BLOCK_BYTES + SPX_SHAX_OUTPUT_BYTES]; + shaXstate state; + int i; + + + /* This implements HMAC-SHA */ + for (i = 0; i < SPX_N; i++) { + buf[i] = 0x36 ^ sk_prf[i]; + } + memset(buf + SPX_N, 0x36, SPX_SHAX_BLOCK_BYTES - SPX_N); + + shaX_inc_init(&state); + shaX_inc_blocks(&state, buf, 1); + + memcpy(buf, optrand, SPX_N); + + /* If optrand + message cannot fill up an entire block */ + if (SPX_N + mlen < SPX_SHAX_BLOCK_BYTES) { + memcpy(buf + SPX_N, m, mlen); + shaX_inc_finalize(buf + SPX_SHAX_BLOCK_BYTES, &state, + buf, mlen + SPX_N); + } + /* Otherwise first fill a block, so that finalize only uses the message */ + else { + memcpy(buf + SPX_N, m, SPX_SHAX_BLOCK_BYTES - SPX_N); + shaX_inc_blocks(&state, buf, 1); + + m += SPX_SHAX_BLOCK_BYTES - SPX_N; + mlen -= SPX_SHAX_BLOCK_BYTES - SPX_N; + shaX_inc_finalize(buf + SPX_SHAX_BLOCK_BYTES, &state, m, mlen); + } + + for (i = 0; i < SPX_N; i++) { + buf[i] = 0x5c ^ sk_prf[i]; + } + memset(buf + SPX_N, 0x5c, SPX_SHAX_BLOCK_BYTES - SPX_N); + + shaX(buf, buf, SPX_SHAX_BLOCK_BYTES + SPX_SHAX_OUTPUT_BYTES); + memcpy(R, buf, SPX_N); +} + +/** + * Computes the message hash using R, the public key, and the message. + * Outputs the message digest and the index of the leaf. The index is split in + * the tree index and the leaf index, for convenient copying to an address. + */ +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { + (void)ctx; +#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) +#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) +#define SPX_LEAF_BITS SPX_TREE_HEIGHT +#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) +#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) + + unsigned char seed[2 * SPX_N + SPX_SHAX_OUTPUT_BYTES]; + + /* Round to nearest multiple of SPX_SHAX_BLOCK_BYTES */ +#define SPX_INBLOCKS (((SPX_N + SPX_PK_BYTES + SPX_SHAX_BLOCK_BYTES - 1) & \ + -SPX_SHAX_BLOCK_BYTES) / SPX_SHAX_BLOCK_BYTES) + unsigned char inbuf[SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES]; + + unsigned char buf[SPX_DGST_BYTES]; + unsigned char *bufp = buf; + shaXstate state; + + shaX_inc_init(&state); + + // seed: SHA-X(R ‖ PK.seed ‖ PK.root ‖ M) + memcpy(inbuf, R, SPX_N); + memcpy(inbuf + SPX_N, pk, SPX_PK_BYTES); + + /* If R + pk + message cannot fill up an entire block */ + if (SPX_N + SPX_PK_BYTES + mlen < SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES) { + memcpy(inbuf + SPX_N + SPX_PK_BYTES, m, mlen); + shaX_inc_finalize(seed + 2 * SPX_N, &state, inbuf, SPX_N + SPX_PK_BYTES + mlen); + } + /* Otherwise first fill a block, so that finalize only uses the message */ + else { + memcpy(inbuf + SPX_N + SPX_PK_BYTES, m, + SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES - SPX_N - SPX_PK_BYTES); + shaX_inc_blocks(&state, inbuf, SPX_INBLOCKS); + + m += SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES - SPX_N - SPX_PK_BYTES; + mlen -= SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES - SPX_N - SPX_PK_BYTES; + shaX_inc_finalize(seed + 2 * SPX_N, &state, m, (size_t)mlen); + } + + // H_msg: MGF1-SHA-X(R ‖ PK.seed ‖ seed) + memcpy(seed, R, SPX_N); + memcpy(seed + SPX_N, pk, SPX_N); + + /* By doing this in two steps, we prevent hashing the message twice; + otherwise each iteration in MGF1 would hash the message again. */ + mgf1_X(bufp, SPX_DGST_BYTES, seed, 2 * SPX_N + SPX_SHAX_OUTPUT_BYTES); + + memcpy(digest, bufp, SPX_FORS_MSG_BYTES); + bufp += SPX_FORS_MSG_BYTES; + + + *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); + *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); + bufp += SPX_TREE_BYTES; + + *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); + *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); +} + + diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/hash_sha2x8.c b/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/hash_sha2x8.c new file mode 100644 index 0000000000..e04af7a069 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/hash_sha2x8.c @@ -0,0 +1,75 @@ +#include +#include + +#include "hash.h" +#include "hashx8.h" + +#include "address.h" +#include "params.h" +#include "sha2.h" +#include "sha256avx.h" +#include "sha256x8.h" +#include "utils.h" + +/* + * 8-way parallel version of prf_addr; takes 8x as much input and output + */ +void prf_addrx8(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const spx_ctx *ctx, + const uint32_t addrx8[8 * 8]) { + unsigned char bufx8[8 * (SPX_N + SPX_SHA256_ADDR_BYTES)]; + unsigned char outbufx8[8 * SPX_SHA256_OUTPUT_BYTES]; + unsigned int j; + + for (j = 0; j < 8; j++) { + memcpy(bufx8 + j * (SPX_N + SPX_SHA256_ADDR_BYTES), + addrx8 + j * 8, SPX_SHA256_ADDR_BYTES); + memcpy( + bufx8 + j * (SPX_N + SPX_SHA256_ADDR_BYTES) + SPX_SHA256_ADDR_BYTES, + ctx->sk_seed, + SPX_N + ); + } + + sha256x8_seeded( + /* out */ + outbufx8 + 0 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 1 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 2 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 3 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 4 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 5 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 6 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 7 * SPX_SHA256_OUTPUT_BYTES, + + /* seed */ + &ctx->statex8_seeded, + + /* in */ + bufx8 + 0 * (SPX_SHA256_ADDR_BYTES + SPX_N), + bufx8 + 1 * (SPX_SHA256_ADDR_BYTES + SPX_N), + bufx8 + 2 * (SPX_SHA256_ADDR_BYTES + SPX_N), + bufx8 + 3 * (SPX_SHA256_ADDR_BYTES + SPX_N), + bufx8 + 4 * (SPX_SHA256_ADDR_BYTES + SPX_N), + bufx8 + 5 * (SPX_SHA256_ADDR_BYTES + SPX_N), + bufx8 + 6 * (SPX_SHA256_ADDR_BYTES + SPX_N), + bufx8 + 7 * (SPX_SHA256_ADDR_BYTES + SPX_N), + SPX_SHA256_ADDR_BYTES + SPX_N /* len */ + ); + + memcpy(out0, outbufx8 + 0 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out1, outbufx8 + 1 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out2, outbufx8 + 2 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out3, outbufx8 + 3 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out4, outbufx8 + 4 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out5, outbufx8 + 5 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out6, outbufx8 + 6 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out7, outbufx8 + 7 * SPX_SHA256_OUTPUT_BYTES, SPX_N); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/hashx8.h b/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/hashx8.h new file mode 100644 index 0000000000..46503f0a10 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/hashx8.h @@ -0,0 +1,20 @@ +#ifndef SPX_HASHX8_H +#define SPX_HASHX8_H + +#include + +#include "params.h" + +#define prf_addrx8 SPX_NAMESPACE(prf_addrx8) +void prf_addrx8(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const spx_ctx *ctx, + const uint32_t addrx8[8 * 8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/merkle.c b/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/merkle.c new file mode 100644 index 0000000000..1f353c8dd8 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/merkle.c @@ -0,0 +1,65 @@ +#include +#include + +#include "merkle.h" + +#include "address.h" +#include "params.h" +#include "utils.h" +#include "utilsx8.h" +#include "wots.h" +#include "wotsx8.h" + +/* + * This generates a Merkle signature (WOTS signature followed by the Merkle + * authentication path). + */ +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf) { + unsigned char *auth_path = sig + SPX_WOTS_BYTES; + uint32_t tree_addrx8[8 * 8] = { 0 }; + int j; + struct leaf_info_x8 info = { 0 }; + unsigned steps[ SPX_WOTS_LEN ]; + + info.wots_sig = sig; + chain_lengths(steps, root); + info.wots_steps = steps; + + for (j = 0; j < 8; j++) { + set_type(&tree_addrx8[8 * j], SPX_ADDR_TYPE_HASHTREE); + set_type(&info.leaf_addr[8 * j], SPX_ADDR_TYPE_WOTS); + set_type(&info.pk_addr[8 * j], SPX_ADDR_TYPE_WOTSPK); + copy_subtree_addr(&tree_addrx8[8 * j], tree_addr); + copy_subtree_addr(&info.leaf_addr[8 * j], wots_addr); + copy_subtree_addr(&info.pk_addr[8 * j], wots_addr); + } + + info.wots_sign_leaf = idx_leaf; + + treehashx8(root, auth_path, ctx, + idx_leaf, 0, + SPX_TREE_HEIGHT, + wots_gen_leafx8, + tree_addrx8, &info); +} + +/* Compute root node of the top-most subtree. */ +/* Again, in this file because wots_gen_leaf is most of the work */ +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { + /* We do not need the auth path in key generation, but it simplifies the + code to have just one treehash routine that computes both root and path + in one function. */ + unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; + uint32_t top_tree_addr[8] = {0}; + uint32_t wots_addr[8] = {0}; + + set_layer_addr(top_tree_addr, SPX_D - 1); + set_layer_addr(wots_addr, SPX_D - 1); + + merkle_sign(auth_path, root, ctx, + wots_addr, top_tree_addr, + ~0U /* ~0 means "don't bother generating an auth path */ ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/merkle.h b/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/merkle.h new file mode 100644 index 0000000000..769cf2e970 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/merkle.h @@ -0,0 +1,21 @@ +#ifndef MERKLE_H_ +#define MERKLE_H_ + +#include + +#include "context.h" +#include "params.h" + +/* Generate a Merkle signature (WOTS signature followed by the Merkle */ +/* authentication path) */ +#define merkle_sign SPX_NAMESPACE(merkle_sign) +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf); + +/* Compute the root node of the top-most subtree. */ +#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); + +#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/nistapi.h b/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/nistapi.h new file mode 100644 index 0000000000..3cb71afad4 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/nistapi.h @@ -0,0 +1,87 @@ +#ifndef SPX_API_H +#define SPX_API_H + +#include +#include + +#include "params.h" + +#define CRYPTO_ALGNAME "SPHINCS+" + +#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES +#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES +#define CRYPTO_BYTES SPX_BYTES +#define CRYPTO_SEEDBYTES (3*SPX_N) + +/* + * Returns the length of a secret key, in bytes + */ +#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) +size_t crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) +size_t crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) +size_t crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) +size_t crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +#define crypto_sign SPX_NAMESPACE(crypto_sign) +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/params.h b/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/params.h new file mode 100644 index 0000000000..90b02b7a53 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/params.h @@ -0,0 +1,61 @@ +#ifndef SPX_PARAMS_H +#define SPX_PARAMS_H + +#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSSHA2256SSIMPLE_AVX2_##s + +/* Hash output length in bytes. */ +#define SPX_N 32 +/* Height of the hypertree. */ +#define SPX_FULL_HEIGHT 64 +/* Number of subtree layer. */ +#define SPX_D 8 +/* FORS tree dimensions. */ +#define SPX_FORS_HEIGHT 14 +#define SPX_FORS_TREES 22 +/* Winternitz parameter, */ +#define SPX_WOTS_W 16 + +/* The hash function is defined by linking a different hash.c file, as opposed + to setting a #define constant. */ + +/* This is a SHA2-based parameter set, hence whether we use SHA-256 + * exclusively or we use both SHA-256 and SHA-512 is controlled by + * the following #define */ +#define SPX_SHA512 1 /* Use SHA-512 for H and T_l, l >= 2 */ + +/* For clarity */ +#define SPX_ADDR_BYTES 32 + +/* WOTS parameters. */ +#define SPX_WOTS_LOGW 4 + +#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) + +/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ +#define SPX_WOTS_LEN2 3 + +#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) +#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) +#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES + +/* Subtree size. */ +#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) + +//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT +// #error SPX_D should always divide SPX_FULL_HEIGHT +//#endif + +/* FORS parameters. */ +#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) +#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) +#define SPX_FORS_PK_BYTES SPX_N + +/* Resulting SPX sizes. */ +#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ + SPX_FULL_HEIGHT * SPX_N) +#define SPX_PK_BYTES (2 * SPX_N) +#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) + +#include "sha2_offsets.h" + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/sha256avx.c b/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/sha256avx.c new file mode 100644 index 0000000000..6bbe6ecc24 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/sha256avx.c @@ -0,0 +1,357 @@ +#include +#include +#include + +#include "sha256avx.h" + +static const unsigned int RC[] = { + 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, + 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, + 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, + 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, + 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, + 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, + 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, + 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, + 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, + 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, + 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, + 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, + 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, + 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, + 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, + 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 +}; + +#define u32 uint32_t +#define u256 __m256i + +#define XOR _mm256_xor_si256 +#define OR _mm256_or_si256 +#define AND _mm256_and_si256 +#define ADD32 _mm256_add_epi32 +#define NOT(x) _mm256_xor_si256(x, _mm256_set_epi32(-1, -1, -1, -1, -1, -1, -1, -1)) + +#define LOAD(src) _mm256_loadu_si256((__m256i *)(src)) +#define STORE(dest,src) _mm256_storeu_si256((__m256i *)(dest),src) + +#define BYTESWAP(x) _mm256_shuffle_epi8(x, _mm256_set_epi8(0xc,0xd,0xe,0xf,0x8,0x9,0xa,0xb,0x4,0x5,0x6,0x7,0x0,0x1,0x2,0x3,0xc,0xd,0xe,0xf,0x8,0x9,0xa,0xb,0x4,0x5,0x6,0x7,0x0,0x1,0x2,0x3)) + +#define SHIFTR32(x, y) _mm256_srli_epi32(x, y) +#define SHIFTL32(x, y) _mm256_slli_epi32(x, y) + +#define ROTR32(x, y) OR(SHIFTR32(x, y), SHIFTL32(x, 32 - (y))) +#define ROTL32(x, y) OR(SHIFTL32(x, y), SHIFTR32(x, 32 - (y))) + +#define XOR3(a, b, c) XOR(XOR(a, b), c) + +#define ADD3_32(a, b, c) ADD32(ADD32(a, b), c) +#define ADD4_32(a, b, c, d) ADD32(ADD32(ADD32(a, b), c), d) +#define ADD5_32(a, b, c, d, e) ADD32(ADD32(ADD32(ADD32(a, b), c), d), e) + +#define MAJ_AVX(a, b, c) XOR3(AND(a, b), AND(a, c), AND(b, c)) +#define CH_AVX(a, b, c) XOR(AND(a, b), AND(NOT(a), c)) + +#define SIGMA1_AVX(x) XOR3(ROTR32(x, 6), ROTR32(x, 11), ROTR32(x, 25)) +#define SIGMA0_AVX(x) XOR3(ROTR32(x, 2), ROTR32(x, 13), ROTR32(x, 22)) + +#define WSIGMA1_AVX(x) XOR3(ROTR32(x, 17), ROTR32(x, 19), SHIFTR32(x, 10)) +#define WSIGMA0_AVX(x) XOR3(ROTR32(x, 7), ROTR32(x, 18), SHIFTR32(x, 3)) + +#define SHA256ROUND_AVX(a, b, c, d, e, f, g, h, rc, w) \ + T0 = ADD5_32(h, SIGMA1_AVX(e), CH_AVX(e, f, g), _mm256_set1_epi32((int)RC[rc]), w); \ + (d) = ADD32(d, T0); \ + T1 = ADD32(SIGMA0_AVX(a), MAJ_AVX(a, b, c)); \ + (h) = ADD32(T0, T1); + +// Transpose 8 vectors containing 32-bit values +static void transpose(u256 s[8]) { + u256 tmp0[8]; + u256 tmp1[8]; + tmp0[0] = _mm256_unpacklo_epi32(s[0], s[1]); + tmp0[1] = _mm256_unpackhi_epi32(s[0], s[1]); + tmp0[2] = _mm256_unpacklo_epi32(s[2], s[3]); + tmp0[3] = _mm256_unpackhi_epi32(s[2], s[3]); + tmp0[4] = _mm256_unpacklo_epi32(s[4], s[5]); + tmp0[5] = _mm256_unpackhi_epi32(s[4], s[5]); + tmp0[6] = _mm256_unpacklo_epi32(s[6], s[7]); + tmp0[7] = _mm256_unpackhi_epi32(s[6], s[7]); + tmp1[0] = _mm256_unpacklo_epi64(tmp0[0], tmp0[2]); + tmp1[1] = _mm256_unpackhi_epi64(tmp0[0], tmp0[2]); + tmp1[2] = _mm256_unpacklo_epi64(tmp0[1], tmp0[3]); + tmp1[3] = _mm256_unpackhi_epi64(tmp0[1], tmp0[3]); + tmp1[4] = _mm256_unpacklo_epi64(tmp0[4], tmp0[6]); + tmp1[5] = _mm256_unpackhi_epi64(tmp0[4], tmp0[6]); + tmp1[6] = _mm256_unpacklo_epi64(tmp0[5], tmp0[7]); + tmp1[7] = _mm256_unpackhi_epi64(tmp0[5], tmp0[7]); + s[0] = _mm256_permute2x128_si256(tmp1[0], tmp1[4], 0x20); + s[1] = _mm256_permute2x128_si256(tmp1[1], tmp1[5], 0x20); + s[2] = _mm256_permute2x128_si256(tmp1[2], tmp1[6], 0x20); + s[3] = _mm256_permute2x128_si256(tmp1[3], tmp1[7], 0x20); + s[4] = _mm256_permute2x128_si256(tmp1[0], tmp1[4], 0x31); + s[5] = _mm256_permute2x128_si256(tmp1[1], tmp1[5], 0x31); + s[6] = _mm256_permute2x128_si256(tmp1[2], tmp1[6], 0x31); + s[7] = _mm256_permute2x128_si256(tmp1[3], tmp1[7], 0x31); +} + +void sha256_ctx_clone8x(sha256x8ctx *out, const sha256x8ctx *in) { + memcpy(out, in, sizeof(sha256x8ctx)); +} + +void sha256_init8x(sha256x8ctx *ctx) { + ctx->s[0] = _mm256_set_epi32((int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667); + ctx->s[1] = _mm256_set_epi32((int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85); + ctx->s[2] = _mm256_set_epi32((int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372); + ctx->s[3] = _mm256_set_epi32((int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a); + ctx->s[4] = _mm256_set_epi32((int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f); + ctx->s[5] = _mm256_set_epi32((int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c); + ctx->s[6] = _mm256_set_epi32((int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab); + ctx->s[7] = _mm256_set_epi32((int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19); + + ctx->datalen = 0; + ctx->msglen = 0; +} + +void sha256_final8x(sha256x8ctx *ctx, + unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7) { + unsigned int i, curlen; + + // Padding + if (ctx->datalen < 56) { + for (i = 0; i < 8; ++i) { + curlen = ctx->datalen; + ctx->msgblocks[64 * i + curlen++] = 0x80; + while (curlen < 64) { + ctx->msgblocks[64 * i + curlen++] = 0x00; + } + } + } else { + for (i = 0; i < 8; ++i) { + curlen = ctx->datalen; + ctx->msgblocks[64 * i + curlen++] = 0x80; + while (curlen < 64) { + ctx->msgblocks[64 * i + curlen++] = 0x00; + } + } + sha256_transform8x(ctx, + &ctx->msgblocks[64 * 0], + &ctx->msgblocks[64 * 1], + &ctx->msgblocks[64 * 2], + &ctx->msgblocks[64 * 3], + &ctx->msgblocks[64 * 4], + &ctx->msgblocks[64 * 5], + &ctx->msgblocks[64 * 6], + &ctx->msgblocks[64 * 7] + ); + memset(ctx->msgblocks, 0, 8 * 64); + } + + // Add length of the message to each block + ctx->msglen += ctx->datalen * 8; + for (i = 0; i < 8; i++) { + ctx->msgblocks[64 * i + 63] = (unsigned char)(ctx->msglen); + ctx->msgblocks[64 * i + 62] = (unsigned char)(ctx->msglen >> 8); + ctx->msgblocks[64 * i + 61] = (unsigned char)(ctx->msglen >> 16); + ctx->msgblocks[64 * i + 60] = (unsigned char)(ctx->msglen >> 24); + ctx->msgblocks[64 * i + 59] = (unsigned char)(ctx->msglen >> 32); + ctx->msgblocks[64 * i + 58] = (unsigned char)(ctx->msglen >> 40); + ctx->msgblocks[64 * i + 57] = (unsigned char)(ctx->msglen >> 48); + ctx->msgblocks[64 * i + 56] = (unsigned char)(ctx->msglen >> 56); + } + sha256_transform8x(ctx, + &ctx->msgblocks[64 * 0], + &ctx->msgblocks[64 * 1], + &ctx->msgblocks[64 * 2], + &ctx->msgblocks[64 * 3], + &ctx->msgblocks[64 * 4], + &ctx->msgblocks[64 * 5], + &ctx->msgblocks[64 * 6], + &ctx->msgblocks[64 * 7] + ); + + // Compute final hash output + transpose(ctx->s); + + // Store Hash value + STORE(out0, BYTESWAP(ctx->s[0])); + STORE(out1, BYTESWAP(ctx->s[1])); + STORE(out2, BYTESWAP(ctx->s[2])); + STORE(out3, BYTESWAP(ctx->s[3])); + STORE(out4, BYTESWAP(ctx->s[4])); + STORE(out5, BYTESWAP(ctx->s[5])); + STORE(out6, BYTESWAP(ctx->s[6])); + STORE(out7, BYTESWAP(ctx->s[7])); +} + +void sha256_transform8x(sha256x8ctx *ctx, + const unsigned char *data0, + const unsigned char *data1, + const unsigned char *data2, + const unsigned char *data3, + const unsigned char *data4, + const unsigned char *data5, + const unsigned char *data6, + const unsigned char *data7) { + u256 s[8], w[64], T0, T1; + + // Load words and transform data correctly + w[0] = BYTESWAP(LOAD(data0)); + w[0 + 8] = BYTESWAP(LOAD(data0 + 32)); + w[1] = BYTESWAP(LOAD(data1)); + w[1 + 8] = BYTESWAP(LOAD(data1 + 32)); + w[2] = BYTESWAP(LOAD(data2)); + w[2 + 8] = BYTESWAP(LOAD(data2 + 32)); + w[3] = BYTESWAP(LOAD(data3)); + w[3 + 8] = BYTESWAP(LOAD(data3 + 32)); + w[4] = BYTESWAP(LOAD(data4)); + w[4 + 8] = BYTESWAP(LOAD(data4 + 32)); + w[5] = BYTESWAP(LOAD(data5)); + w[5 + 8] = BYTESWAP(LOAD(data5 + 32)); + w[6] = BYTESWAP(LOAD(data6)); + w[6 + 8] = BYTESWAP(LOAD(data6 + 32)); + w[7] = BYTESWAP(LOAD(data7)); + w[7 + 8] = BYTESWAP(LOAD(data7 + 32)); + + transpose(w); + transpose(w + 8); + + // Initial State + s[0] = ctx->s[0]; + s[1] = ctx->s[1]; + s[2] = ctx->s[2]; + s[3] = ctx->s[3]; + s[4] = ctx->s[4]; + s[5] = ctx->s[5]; + s[6] = ctx->s[6]; + s[7] = ctx->s[7]; + + SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 0, w[0]); + SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 1, w[1]); + SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 2, w[2]); + SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 3, w[3]); + SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 4, w[4]); + SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 5, w[5]); + SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 6, w[6]); + SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 7, w[7]); + SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 8, w[8]); + SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 9, w[9]); + SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 10, w[10]); + SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 11, w[11]); + SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 12, w[12]); + SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 13, w[13]); + SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 14, w[14]); + SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 15, w[15]); + w[16] = ADD4_32(WSIGMA1_AVX(w[14]), w[0], w[9], WSIGMA0_AVX(w[1])); + SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 16, w[16]); + w[17] = ADD4_32(WSIGMA1_AVX(w[15]), w[1], w[10], WSIGMA0_AVX(w[2])); + SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 17, w[17]); + w[18] = ADD4_32(WSIGMA1_AVX(w[16]), w[2], w[11], WSIGMA0_AVX(w[3])); + SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 18, w[18]); + w[19] = ADD4_32(WSIGMA1_AVX(w[17]), w[3], w[12], WSIGMA0_AVX(w[4])); + SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 19, w[19]); + w[20] = ADD4_32(WSIGMA1_AVX(w[18]), w[4], w[13], WSIGMA0_AVX(w[5])); + SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 20, w[20]); + w[21] = ADD4_32(WSIGMA1_AVX(w[19]), w[5], w[14], WSIGMA0_AVX(w[6])); + SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 21, w[21]); + w[22] = ADD4_32(WSIGMA1_AVX(w[20]), w[6], w[15], WSIGMA0_AVX(w[7])); + SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 22, w[22]); + w[23] = ADD4_32(WSIGMA1_AVX(w[21]), w[7], w[16], WSIGMA0_AVX(w[8])); + SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 23, w[23]); + w[24] = ADD4_32(WSIGMA1_AVX(w[22]), w[8], w[17], WSIGMA0_AVX(w[9])); + SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 24, w[24]); + w[25] = ADD4_32(WSIGMA1_AVX(w[23]), w[9], w[18], WSIGMA0_AVX(w[10])); + SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 25, w[25]); + w[26] = ADD4_32(WSIGMA1_AVX(w[24]), w[10], w[19], WSIGMA0_AVX(w[11])); + SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 26, w[26]); + w[27] = ADD4_32(WSIGMA1_AVX(w[25]), w[11], w[20], WSIGMA0_AVX(w[12])); + SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 27, w[27]); + w[28] = ADD4_32(WSIGMA1_AVX(w[26]), w[12], w[21], WSIGMA0_AVX(w[13])); + SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 28, w[28]); + w[29] = ADD4_32(WSIGMA1_AVX(w[27]), w[13], w[22], WSIGMA0_AVX(w[14])); + SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 29, w[29]); + w[30] = ADD4_32(WSIGMA1_AVX(w[28]), w[14], w[23], WSIGMA0_AVX(w[15])); + SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 30, w[30]); + w[31] = ADD4_32(WSIGMA1_AVX(w[29]), w[15], w[24], WSIGMA0_AVX(w[16])); + SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 31, w[31]); + w[32] = ADD4_32(WSIGMA1_AVX(w[30]), w[16], w[25], WSIGMA0_AVX(w[17])); + SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 32, w[32]); + w[33] = ADD4_32(WSIGMA1_AVX(w[31]), w[17], w[26], WSIGMA0_AVX(w[18])); + SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 33, w[33]); + w[34] = ADD4_32(WSIGMA1_AVX(w[32]), w[18], w[27], WSIGMA0_AVX(w[19])); + SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 34, w[34]); + w[35] = ADD4_32(WSIGMA1_AVX(w[33]), w[19], w[28], WSIGMA0_AVX(w[20])); + SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 35, w[35]); + w[36] = ADD4_32(WSIGMA1_AVX(w[34]), w[20], w[29], WSIGMA0_AVX(w[21])); + SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 36, w[36]); + w[37] = ADD4_32(WSIGMA1_AVX(w[35]), w[21], w[30], WSIGMA0_AVX(w[22])); + SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 37, w[37]); + w[38] = ADD4_32(WSIGMA1_AVX(w[36]), w[22], w[31], WSIGMA0_AVX(w[23])); + SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 38, w[38]); + w[39] = ADD4_32(WSIGMA1_AVX(w[37]), w[23], w[32], WSIGMA0_AVX(w[24])); + SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 39, w[39]); + w[40] = ADD4_32(WSIGMA1_AVX(w[38]), w[24], w[33], WSIGMA0_AVX(w[25])); + SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 40, w[40]); + w[41] = ADD4_32(WSIGMA1_AVX(w[39]), w[25], w[34], WSIGMA0_AVX(w[26])); + SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 41, w[41]); + w[42] = ADD4_32(WSIGMA1_AVX(w[40]), w[26], w[35], WSIGMA0_AVX(w[27])); + SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 42, w[42]); + w[43] = ADD4_32(WSIGMA1_AVX(w[41]), w[27], w[36], WSIGMA0_AVX(w[28])); + SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 43, w[43]); + w[44] = ADD4_32(WSIGMA1_AVX(w[42]), w[28], w[37], WSIGMA0_AVX(w[29])); + SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 44, w[44]); + w[45] = ADD4_32(WSIGMA1_AVX(w[43]), w[29], w[38], WSIGMA0_AVX(w[30])); + SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 45, w[45]); + w[46] = ADD4_32(WSIGMA1_AVX(w[44]), w[30], w[39], WSIGMA0_AVX(w[31])); + SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 46, w[46]); + w[47] = ADD4_32(WSIGMA1_AVX(w[45]), w[31], w[40], WSIGMA0_AVX(w[32])); + SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 47, w[47]); + w[48] = ADD4_32(WSIGMA1_AVX(w[46]), w[32], w[41], WSIGMA0_AVX(w[33])); + SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 48, w[48]); + w[49] = ADD4_32(WSIGMA1_AVX(w[47]), w[33], w[42], WSIGMA0_AVX(w[34])); + SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 49, w[49]); + w[50] = ADD4_32(WSIGMA1_AVX(w[48]), w[34], w[43], WSIGMA0_AVX(w[35])); + SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 50, w[50]); + w[51] = ADD4_32(WSIGMA1_AVX(w[49]), w[35], w[44], WSIGMA0_AVX(w[36])); + SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 51, w[51]); + w[52] = ADD4_32(WSIGMA1_AVX(w[50]), w[36], w[45], WSIGMA0_AVX(w[37])); + SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 52, w[52]); + w[53] = ADD4_32(WSIGMA1_AVX(w[51]), w[37], w[46], WSIGMA0_AVX(w[38])); + SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 53, w[53]); + w[54] = ADD4_32(WSIGMA1_AVX(w[52]), w[38], w[47], WSIGMA0_AVX(w[39])); + SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 54, w[54]); + w[55] = ADD4_32(WSIGMA1_AVX(w[53]), w[39], w[48], WSIGMA0_AVX(w[40])); + SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 55, w[55]); + w[56] = ADD4_32(WSIGMA1_AVX(w[54]), w[40], w[49], WSIGMA0_AVX(w[41])); + SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 56, w[56]); + w[57] = ADD4_32(WSIGMA1_AVX(w[55]), w[41], w[50], WSIGMA0_AVX(w[42])); + SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 57, w[57]); + w[58] = ADD4_32(WSIGMA1_AVX(w[56]), w[42], w[51], WSIGMA0_AVX(w[43])); + SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 58, w[58]); + w[59] = ADD4_32(WSIGMA1_AVX(w[57]), w[43], w[52], WSIGMA0_AVX(w[44])); + SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 59, w[59]); + w[60] = ADD4_32(WSIGMA1_AVX(w[58]), w[44], w[53], WSIGMA0_AVX(w[45])); + SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 60, w[60]); + w[61] = ADD4_32(WSIGMA1_AVX(w[59]), w[45], w[54], WSIGMA0_AVX(w[46])); + SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 61, w[61]); + w[62] = ADD4_32(WSIGMA1_AVX(w[60]), w[46], w[55], WSIGMA0_AVX(w[47])); + SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 62, w[62]); + w[63] = ADD4_32(WSIGMA1_AVX(w[61]), w[47], w[56], WSIGMA0_AVX(w[48])); + SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 63, w[63]); + + // Feed Forward + ctx->s[0] = ADD32(s[0], ctx->s[0]); + ctx->s[1] = ADD32(s[1], ctx->s[1]); + ctx->s[2] = ADD32(s[2], ctx->s[2]); + ctx->s[3] = ADD32(s[3], ctx->s[3]); + ctx->s[4] = ADD32(s[4], ctx->s[4]); + ctx->s[5] = ADD32(s[5], ctx->s[5]); + ctx->s[6] = ADD32(s[6], ctx->s[6]); + ctx->s[7] = ADD32(s[7], ctx->s[7]); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/sha256avx.h b/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/sha256avx.h new file mode 100644 index 0000000000..1e3bcf889b --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/sha256avx.h @@ -0,0 +1,44 @@ +#ifndef SHA256AVX_H +#define SHA256AVX_H + +#include +#include + +#include "params.h" + +typedef struct SHA256state { + __m256i s[8]; + unsigned char msgblocks[8 * 64]; + unsigned int datalen; + unsigned long long msglen; +} sha256x8ctx; + +#define sha256_ctx_clone8x SPX_NAMESPACE(sha256_ctx_clone8x) +void sha256_ctx_clone8x(sha256x8ctx *out, const sha256x8ctx *in); + +#define sha256_init8x SPX_NAMESPACE(sha256_init8x) +void sha256_init8x(sha256x8ctx *ctx); + +#define sha256_final8x SPX_NAMESPACE(sha256_final8x) +void sha256_final8x(sha256x8ctx *ctx, + unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7); + +#define sha256_transform8x SPX_NAMESPACE(sha256_transform8x) +void sha256_transform8x(sha256x8ctx *ctx, + const unsigned char *data0, + const unsigned char *data1, + const unsigned char *data2, + const unsigned char *data3, + const unsigned char *data4, + const unsigned char *data5, + const unsigned char *data6, + const unsigned char *data7); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/sha256x8.c b/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/sha256x8.c new file mode 100644 index 0000000000..d97750c09b --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/sha256x8.c @@ -0,0 +1,185 @@ +#include + +#include "sha256avx.h" +#include "sha256x8.h" +#include "utils.h" + +// Performs sha256x8 on an initialized (and perhaps seeded) state. +static void _sha256x8( + sha256x8ctx *ctx, + unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, unsigned long long inlen) { + unsigned long long i = 0; + while (inlen - i >= 64) { + sha256_transform8x(ctx, + in0 + i, + in1 + i, + in2 + i, + in3 + i, + in4 + i, + in5 + i, + in6 + i, + in7 + i + ); + i += 64; + ctx->msglen += 512; + } + + size_t bytes_to_copy = (size_t)(inlen - i); + memcpy(&ctx->msgblocks[64 * 0], in0 + i, bytes_to_copy); + memcpy(&ctx->msgblocks[64 * 1], in1 + i, bytes_to_copy); + memcpy(&ctx->msgblocks[64 * 2], in2 + i, bytes_to_copy); + memcpy(&ctx->msgblocks[64 * 3], in3 + i, bytes_to_copy); + memcpy(&ctx->msgblocks[64 * 4], in4 + i, bytes_to_copy); + memcpy(&ctx->msgblocks[64 * 5], in5 + i, bytes_to_copy); + memcpy(&ctx->msgblocks[64 * 6], in6 + i, bytes_to_copy); + memcpy(&ctx->msgblocks[64 * 7], in7 + i, bytes_to_copy); + ctx->datalen = (unsigned int)bytes_to_copy; + + sha256_final8x(ctx, out0, out1, out2, out3, out4, out5, out6, out7); +} + +void sha256x8_seeded( + unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const sha256x8ctx *seed, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, unsigned long long inlen) { + + sha256x8ctx ctx; + sha256_ctx_clone8x(&ctx, seed); + + _sha256x8(&ctx, out0, out1, out2, out3, out4, out5, out6, out7, + in0, in1, in2, in3, in4, in5, in6, in7, inlen); +} + +/* This provides a wrapper around the internals of 8x parallel SHA256 */ +void sha256x8(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, unsigned long long inlen) { + sha256x8ctx ctx; + sha256_init8x(&ctx); + + _sha256x8(&ctx, out0, out1, out2, out3, out4, out5, out6, out7, + in0, in1, in2, in3, in4, in5, in6, in7, inlen); +} + +/** + * Note that inlen should be sufficiently small that it still allows for + * an array to be allocated on the stack. Typically 'in' is merely a seed. + * Outputs outlen number of bytes + */ +void mgf1x8(unsigned char *outx8, unsigned long outlen, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, + unsigned long inlen) { + PQCLEAN_VLA(unsigned char, inbufx8, 8 * (inlen + 4)); + unsigned char outbufx8[8 * SPX_SHA256_OUTPUT_BYTES]; + uint32_t i; + unsigned int j; + + memcpy(inbufx8 + 0 * (inlen + 4), in0, inlen); + memcpy(inbufx8 + 1 * (inlen + 4), in1, inlen); + memcpy(inbufx8 + 2 * (inlen + 4), in2, inlen); + memcpy(inbufx8 + 3 * (inlen + 4), in3, inlen); + memcpy(inbufx8 + 4 * (inlen + 4), in4, inlen); + memcpy(inbufx8 + 5 * (inlen + 4), in5, inlen); + memcpy(inbufx8 + 6 * (inlen + 4), in6, inlen); + memcpy(inbufx8 + 7 * (inlen + 4), in7, inlen); + + /* While we can fit in at least another full block of SHA256 output.. */ + for (i = 0; (i + 1)*SPX_SHA256_OUTPUT_BYTES <= outlen; i++) { + for (j = 0; j < 8; j++) { + u32_to_bytes(inbufx8 + inlen + j * (inlen + 4), i); + } + + sha256x8(outx8 + 0 * outlen, + outx8 + 1 * outlen, + outx8 + 2 * outlen, + outx8 + 3 * outlen, + outx8 + 4 * outlen, + outx8 + 5 * outlen, + outx8 + 6 * outlen, + outx8 + 7 * outlen, + inbufx8 + 0 * (inlen + 4), + inbufx8 + 1 * (inlen + 4), + inbufx8 + 2 * (inlen + 4), + inbufx8 + 3 * (inlen + 4), + inbufx8 + 4 * (inlen + 4), + inbufx8 + 5 * (inlen + 4), + inbufx8 + 6 * (inlen + 4), + inbufx8 + 7 * (inlen + 4), inlen + 4); + outx8 += SPX_SHA256_OUTPUT_BYTES; + } + /* Until we cannot anymore, and we fill the remainder. */ + for (j = 0; j < 8; j++) { + u32_to_bytes(inbufx8 + inlen + j * (inlen + 4), i); + } + sha256x8(outbufx8 + 0 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 1 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 2 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 3 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 4 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 5 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 6 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 7 * SPX_SHA256_OUTPUT_BYTES, + inbufx8 + 0 * (inlen + 4), + inbufx8 + 1 * (inlen + 4), + inbufx8 + 2 * (inlen + 4), + inbufx8 + 3 * (inlen + 4), + inbufx8 + 4 * (inlen + 4), + inbufx8 + 5 * (inlen + 4), + inbufx8 + 6 * (inlen + 4), + inbufx8 + 7 * (inlen + 4), inlen + 4); + + for (j = 0; j < 8; j++) { + memcpy(outx8 + j * outlen, + outbufx8 + j * SPX_SHA256_OUTPUT_BYTES, + outlen - i * SPX_SHA256_OUTPUT_BYTES); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/sha256x8.h b/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/sha256x8.h new file mode 100644 index 0000000000..4f7330a6c1 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/sha256x8.h @@ -0,0 +1,64 @@ +#ifndef SPX_SHA256X8_H +#define SPX_SHA256X8_H + +#include "params.h" +#include "sha256avx.h" + + + +#define sha256x8_seeded SPX_NAMESPACE(sha256x8_seeded) +void sha256x8_seeded( + unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const sha256x8ctx *seed, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, unsigned long long inlen); + +/* This provides a wrapper around the internals of 8x parallel SHA256 */ +#define sha256x8 SPX_NAMESPACE(sha256x8) +void sha256x8(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, unsigned long long inlen); + +/** + * Note that inlen should be sufficiently small that it still allows for + * an array to be allocated on the stack. Typically 'in' is merely a seed. + * Outputs outlen number of bytes + */ +#define mgf1x8 SPX_NAMESPACE(mgf1x8) +void mgf1x8(unsigned char *outx8, unsigned long outlen, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, + unsigned long inlen); +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/sha2_offsets.h b/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/sha2_offsets.h new file mode 100644 index 0000000000..6e3584f7a4 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/sha2_offsets.h @@ -0,0 +1,27 @@ +#ifndef SHA2_OFFSETS_H_ +#define SHA2_OFFSETS_H_ + +#define SPX_SHA256_BLOCK_BYTES 64 +#define SPX_SHA256_OUTPUT_BYTES 32 + +#define SPX_SHA512_BLOCK_BYTES 128 +#define SPX_SHA512_OUTPUT_BYTES 64 + +/* + * Offsets of various fields in the address structure when we use SHA2 as + * the Sphincs+ hash function + */ + +#define SPX_OFFSET_LAYER 0 /* The byte used to specify the Merkle tree layer */ +#define SPX_OFFSET_TREE 1 /* The start of the 8 byte field used to specify the tree */ +#define SPX_OFFSET_TYPE 9 /* The byte used to specify the hash type (reason) */ +#define SPX_OFFSET_KP_ADDR2 12 /* The high byte used to specify the key pair (which one-time signature) */ +#define SPX_OFFSET_KP_ADDR1 13 /* The low byte used to specify the key pair */ +#define SPX_OFFSET_CHAIN_ADDR 17 /* The byte used to specify the chain address (which Winternitz chain) */ +#define SPX_OFFSET_HASH_ADDR 21 /* The byte used to specify the hash address (where in the Winternitz chain) */ +#define SPX_OFFSET_TREE_HGT 17 /* The byte used to specify the height of this node in the FORS or Merkle tree */ +#define SPX_OFFSET_TREE_INDEX 18 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ + +#define SPX_SHA2 1 + +#endif /* SHA2_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/sha512x4.c b/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/sha512x4.c new file mode 100644 index 0000000000..8d33deffdd --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/sha512x4.c @@ -0,0 +1,446 @@ +#include +#include +#include + +/* pull in the entire thing */ +#include "sha512x4.h" +#include "utils.h" + +typedef uint64_t u64; +typedef __m256i u256; + +#define BYTESWAP(x) _mm256_shuffle_epi8(x, _mm256_set_epi8(0x8,0x9,0xa,0xb,0xc,0xd,0xe,0xf,0x0,0x1,0x2,0x3,0x4,0x5,0x6,0x7,0x8,0x9,0xa,0xb,0xc,0xd,0xe,0xf,0x0,0x1,0x2,0x3,0x4,0x5,0x6,0x7)) +#define STORE(dest,src) _mm256_storeu_si256((__m256i *)(dest),src) + +// Transpose 4 vectors containing 64-bit values +// That is, it rearranges the array: +// A B C D +// E F G H +// I J K L +// M N O P +// into +// A E I M +// B F J N +// C G K O +// D H L P +// where each letter stands for 64 bits (and lsbits on the left) +static void transpose(u256 s[4]) { + u256 tmp[4]; + tmp[0] = _mm256_unpacklo_epi64(s[0], s[1]); + tmp[1] = _mm256_unpackhi_epi64(s[0], s[1]); + tmp[2] = _mm256_unpacklo_epi64(s[2], s[3]); + tmp[3] = _mm256_unpackhi_epi64(s[2], s[3]); + // tmp is in the order of + // A E C G + // B F D H + // I M K O + // J N L P + s[0] = _mm256_permute2x128_si256(tmp[0], tmp[2], 0x20); + s[1] = _mm256_permute2x128_si256(tmp[1], tmp[3], 0x20); + s[2] = _mm256_permute2x128_si256(tmp[0], tmp[2], 0x31); + s[3] = _mm256_permute2x128_si256(tmp[1], tmp[3], 0x31); +} + + +void sha512_init4x(sha512x4ctx *ctx) { +#define SET4(x) _mm256_set_epi64x((long long)(x), (long long)(x), (long long)(x), (long long)(x)) + ctx->s[0] = SET4(0x6a09e667f3bcc908ULL); + ctx->s[1] = SET4(0xbb67ae8584caa73bULL); + ctx->s[2] = SET4(0x3c6ef372fe94f82bULL); + ctx->s[3] = SET4(0xa54ff53a5f1d36f1ULL); + ctx->s[4] = SET4(0x510e527fade682d1ULL); + ctx->s[5] = SET4(0x9b05688c2b3e6c1fULL); + ctx->s[6] = SET4(0x1f83d9abfb41bd6bULL); + ctx->s[7] = SET4(0x5be0cd19137e2179ULL); +#undef SET4 + + ctx->datalen = 0; + ctx->msglen = 0; +} + +#define XOR _mm256_xor_si256 +#define OR _mm256_or_si256 +#define AND _mm256_and_si256 +#define ADD64 _mm256_add_epi64 + +#define LOAD(src) _mm256_loadu_si256((__m256i *)(src)) + +#define SHIFTR64(x, y) _mm256_srli_epi64(x, y) +#define SHIFTL64(x, y) _mm256_slli_epi64(x, y) + +#define ROTR64(x, y) OR(SHIFTR64(x, y), SHIFTL64(x, 64 - (y))) + +static u256 XOR3(u256 a, u256 b, u256 c) { + return XOR(XOR(a, b), c); +} + +#define ADD3_64(a, b, c) ADD64(ADD64(a, b), c) +#define ADD4_64(a, b, c, d) ADD64(ADD64(ADD64(a, b), c), d) +#define ADD5_64(a, b, c, d, e) ADD64(ADD64(ADD64(ADD64(a, b), c), d), e) + +static u256 MAJ_AVX(u256 a, u256 b, u256 c) { + return XOR(c, AND(XOR(a, c), XOR(b, c))); +} +static u256 CH_AVX(u256 a, u256 b, u256 c) { + return XOR(c, AND(a, XOR(b, c))); +} +static u256 SIGMA0_AVX(u256 x) { + return XOR3(ROTR64(x, 28), ROTR64(x, 34), ROTR64(x, 39)); +} +static u256 SIGMA1_AVX(u256 x) { + return XOR3(ROTR64(x, 14), ROTR64(x, 18), ROTR64(x, 41)); +} +static u256 GAMMA0_AVX(u256 x) { + return XOR3(ROTR64(x, 1), ROTR64(x, 8), SHIFTR64(x, 7)); +} +static u256 GAMMA1_AVX(u256 x) { + return XOR3(ROTR64(x, 19), ROTR64(x, 61), SHIFTR64(x, 6)); +} + +#define SHA512ROUND_AVX(a, b, c, d, e, f, g, h, rc, w) \ + T0 = ADD5_64(h, w, SIGMA1_AVX(e), CH_AVX(e, f, g), _mm256_set1_epi64x((long long)RC[rc])); \ + T1 = ADD64(SIGMA0_AVX(a), MAJ_AVX(a, b, c)); \ + (d) = ADD64(d, T0); \ + (h) = ADD64(T0, T1); + +static const unsigned long long RC[80] = { + 0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL, + 0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL, + 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL, + 0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL, + 0xd807aa98a3030242ULL, 0x12835b0145706fbeULL, + 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL, + 0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL, + 0x9bdc06a725c71235ULL, 0xc19bf174cf692694ULL, + 0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL, + 0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL, + 0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL, + 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL, + 0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL, + 0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL, + 0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL, + 0x06ca6351e003826fULL, 0x142929670a0e6e70ULL, + 0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL, + 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL, + 0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL, + 0x81c2c92e47edaee6ULL, 0x92722c851482353bULL, + 0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL, + 0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL, + 0xd192e819d6ef5218ULL, 0xd69906245565a910ULL, + 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL, + 0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL, + 0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL, + 0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL, + 0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL, + 0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL, + 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL, + 0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL, + 0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL, + 0xca273eceea26619cULL, 0xd186b8c721c0c207ULL, + 0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL, + 0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL, + 0x113f9804bef90daeULL, 0x1b710b35131c471bULL, + 0x28db77f523047d84ULL, 0x32caab7b40c72493ULL, + 0x3c9ebe0a15c9bebcULL, 0x431d67c49c100d4cULL, + 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL, + 0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL, +}; + +void sha512_transform4x( + sha512x4ctx *ctx, + const unsigned char *d0, + const unsigned char *d1, + const unsigned char *d2, + const unsigned char *d3) { + u256 s0, s1, s2, s3, s4, s5, s6, s7, w[16], T0, T1, nw; + + // Load words and transform data correctly + w[0 ] = BYTESWAP(LOAD(d0 )); + w[0 + 4] = BYTESWAP(LOAD(d0 + 32)); + w[0 + 8] = BYTESWAP(LOAD(d0 + 64)); + w[0 + 12] = BYTESWAP(LOAD(d0 + 96)); + + w[1 ] = BYTESWAP(LOAD(d1 )); + w[1 + 4] = BYTESWAP(LOAD(d1 + 32)); + w[1 + 8] = BYTESWAP(LOAD(d1 + 64)); + w[1 + 12] = BYTESWAP(LOAD(d1 + 96)); + + w[2 ] = BYTESWAP(LOAD(d2 )); + w[2 + 4] = BYTESWAP(LOAD(d2 + 32)); + w[2 + 8] = BYTESWAP(LOAD(d2 + 64)); + w[2 + 12] = BYTESWAP(LOAD(d2 + 96)); + + w[3 ] = BYTESWAP(LOAD(d3 )); + w[3 + 4] = BYTESWAP(LOAD(d3 + 32)); + w[3 + 8] = BYTESWAP(LOAD(d3 + 64)); + w[3 + 12] = BYTESWAP(LOAD(d3 + 96)); + + transpose(w); + transpose(w + 4); + transpose(w + 8); + transpose(w + 12); + + // Initial State + s0 = ctx->s[0]; + s1 = ctx->s[1]; + s2 = ctx->s[2]; + s3 = ctx->s[3]; + s4 = ctx->s[4]; + s5 = ctx->s[5]; + s6 = ctx->s[6]; + s7 = ctx->s[7]; + + // The first 16 rounds (where the w inputs are directly from the data) + SHA512ROUND_AVX(s0, s1, s2, s3, s4, s5, s6, s7, 0, w[0]); + SHA512ROUND_AVX(s7, s0, s1, s2, s3, s4, s5, s6, 1, w[1]); + SHA512ROUND_AVX(s6, s7, s0, s1, s2, s3, s4, s5, 2, w[2]); + SHA512ROUND_AVX(s5, s6, s7, s0, s1, s2, s3, s4, 3, w[3]); + SHA512ROUND_AVX(s4, s5, s6, s7, s0, s1, s2, s3, 4, w[4]); + SHA512ROUND_AVX(s3, s4, s5, s6, s7, s0, s1, s2, 5, w[5]); + SHA512ROUND_AVX(s2, s3, s4, s5, s6, s7, s0, s1, 6, w[6]); + SHA512ROUND_AVX(s1, s2, s3, s4, s5, s6, s7, s0, 7, w[7]); + SHA512ROUND_AVX(s0, s1, s2, s3, s4, s5, s6, s7, 8, w[8]); + SHA512ROUND_AVX(s7, s0, s1, s2, s3, s4, s5, s6, 9, w[9]); + SHA512ROUND_AVX(s6, s7, s0, s1, s2, s3, s4, s5, 10, w[10]); + SHA512ROUND_AVX(s5, s6, s7, s0, s1, s2, s3, s4, 11, w[11]); + SHA512ROUND_AVX(s4, s5, s6, s7, s0, s1, s2, s3, 12, w[12]); + SHA512ROUND_AVX(s3, s4, s5, s6, s7, s0, s1, s2, 13, w[13]); + SHA512ROUND_AVX(s2, s3, s4, s5, s6, s7, s0, s1, 14, w[14]); + SHA512ROUND_AVX(s1, s2, s3, s4, s5, s6, s7, s0, 15, w[15]); + +#define M(i) (((i)+16) & 0xf) +#define NextW(i) \ + w[M(i)] = ADD4_64(GAMMA1_AVX(w[M((i)-2)]), w[M((i)-7)], GAMMA0_AVX(w[M((i)-15)]), w[M((i)-16)]); + + // The remaining 64 rounds (where the w inputs are a linear fix of the data) + for (unsigned i = 16; i < 80; i += 16) { + nw = NextW(0); + SHA512ROUND_AVX(s0, s1, s2, s3, s4, s5, s6, s7, i + 0, nw); + nw = NextW(1); + SHA512ROUND_AVX(s7, s0, s1, s2, s3, s4, s5, s6, i + 1, nw); + nw = NextW(2); + SHA512ROUND_AVX(s6, s7, s0, s1, s2, s3, s4, s5, i + 2, nw); + nw = NextW(3); + SHA512ROUND_AVX(s5, s6, s7, s0, s1, s2, s3, s4, i + 3, nw); + nw = NextW(4); + SHA512ROUND_AVX(s4, s5, s6, s7, s0, s1, s2, s3, i + 4, nw); + nw = NextW(5); + SHA512ROUND_AVX(s3, s4, s5, s6, s7, s0, s1, s2, i + 5, nw); + nw = NextW(6); + SHA512ROUND_AVX(s2, s3, s4, s5, s6, s7, s0, s1, i + 6, nw); + nw = NextW(7); + SHA512ROUND_AVX(s1, s2, s3, s4, s5, s6, s7, s0, i + 7, nw); + nw = NextW(8); + SHA512ROUND_AVX(s0, s1, s2, s3, s4, s5, s6, s7, i + 8, nw); + nw = NextW(9); + SHA512ROUND_AVX(s7, s0, s1, s2, s3, s4, s5, s6, i + 9, nw); + nw = NextW(10); + SHA512ROUND_AVX(s6, s7, s0, s1, s2, s3, s4, s5, i + 10, nw); + nw = NextW(11); + SHA512ROUND_AVX(s5, s6, s7, s0, s1, s2, s3, s4, i + 11, nw); + nw = NextW(12); + SHA512ROUND_AVX(s4, s5, s6, s7, s0, s1, s2, s3, i + 12, nw); + nw = NextW(13); + SHA512ROUND_AVX(s3, s4, s5, s6, s7, s0, s1, s2, i + 13, nw); + nw = NextW(14); + SHA512ROUND_AVX(s2, s3, s4, s5, s6, s7, s0, s1, i + 14, nw); + nw = NextW(15); + SHA512ROUND_AVX(s1, s2, s3, s4, s5, s6, s7, s0, i + 15, nw); + } + + // Feed Forward + ctx->s[0] = ADD64(s0, ctx->s[0]); + ctx->s[1] = ADD64(s1, ctx->s[1]); + ctx->s[2] = ADD64(s2, ctx->s[2]); + ctx->s[3] = ADD64(s3, ctx->s[3]); + ctx->s[4] = ADD64(s4, ctx->s[4]); + ctx->s[5] = ADD64(s5, ctx->s[5]); + ctx->s[6] = ADD64(s6, ctx->s[6]); + ctx->s[7] = ADD64(s7, ctx->s[7]); +} + +static void _sha512x4( + sha512x4ctx *ctx, + unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + unsigned long long inlen) { + unsigned int i = 0; + + while (inlen - i >= 128) { + sha512_transform4x( + ctx, + in0 + i, + in1 + i, + in2 + i, + in3 + i + ); + ctx->msglen += 1024; + i += 128; + } + + ctx->datalen = (unsigned int)(inlen - i); + memcpy(&ctx->msgblocks[128 * 0], in0 + i, ctx->datalen); + memcpy(&ctx->msgblocks[128 * 1], in1 + i, ctx->datalen); + memcpy(&ctx->msgblocks[128 * 2], in2 + i, ctx->datalen); + memcpy(&ctx->msgblocks[128 * 3], in3 + i, ctx->datalen); + + // Padding + unsigned long curlen; + if (ctx->datalen < 112) { + for (i = 0; i < 4; ++i) { + curlen = ctx->datalen; + ctx->msgblocks[128 * i + curlen++] = 0x80; + while (curlen < 128) { + ctx->msgblocks[128 * i + curlen++] = 0x00; + } + } + } else { + for (i = 0; i < 4; ++i) { + curlen = ctx->datalen; + ctx->msgblocks[128 * i + curlen++] = 0x80; + while (curlen < 128) { + ctx->msgblocks[128 * i + curlen++] = 0x00; + } + } + sha512_transform4x( + ctx, + ctx->msgblocks, + ctx->msgblocks + 128, + ctx->msgblocks + 256, + ctx->msgblocks + 384 + ); + memset(ctx->msgblocks, 0, 4 * 128); + } + + // Add length of the message to each block + ctx->msglen += (unsigned long long)(ctx->datalen) * 8; + for (i = 0; i < 4; i++) { + ctx->msgblocks[128 * i + 127] = (unsigned char)(ctx->msglen); + ctx->msgblocks[128 * i + 126] = (unsigned char)(ctx->msglen >> 8); + ctx->msgblocks[128 * i + 125] = (unsigned char)(ctx->msglen >> 16); + ctx->msgblocks[128 * i + 124] = (unsigned char)(ctx->msglen >> 24); + ctx->msgblocks[128 * i + 123] = (unsigned char)(ctx->msglen >> 32); + ctx->msgblocks[128 * i + 122] = (unsigned char)(ctx->msglen >> 40); + ctx->msgblocks[128 * i + 121] = (unsigned char)(ctx->msglen >> 48); + ctx->msgblocks[128 * i + 120] = (unsigned char)(ctx->msglen >> 56); + memset( &ctx->msgblocks[128 * i + 112], 0, 8 ); + } + sha512_transform4x( + ctx, + ctx->msgblocks, + ctx->msgblocks + 128, + ctx->msgblocks + 256, + ctx->msgblocks + 384 + ); + + // Compute final hash output + transpose(ctx->s); + transpose(ctx->s + 4); + + // Store Hash value + __m256i out[2]; + STORE(out, BYTESWAP(ctx->s[0])); + STORE(out + 1, BYTESWAP(ctx->s[4])); + memcpy(out0, out, 64); + + STORE(out, BYTESWAP(ctx->s[1])); + STORE(out + 1, BYTESWAP(ctx->s[5])); + memcpy(out1, out, 64); + + STORE(out, BYTESWAP(ctx->s[2])); + STORE(out + 1, BYTESWAP(ctx->s[6])); + memcpy(out2, out, 64); + + STORE(out, BYTESWAP(ctx->s[3])); + STORE(out + 1, BYTESWAP(ctx->s[7])); + memcpy(out3, out, 64); +} + + +/** + * Note that inlen should be sufficiently small that it still allows for + * an array to be allocated on the stack. Typically 'in' is merely a seed. + * Outputs outlen number of bytes + */ +void mgf1x4_512(unsigned char *outx4, unsigned long outlen, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + unsigned long inlen) { + PQCLEAN_VLA(unsigned char, inbufx4, 4 * (inlen + 4)); + unsigned char outbuf[4 * 64]; + uint32_t i; + unsigned int j; + + memcpy(inbufx4 + 0 * (inlen + 4), in0, inlen); + memcpy(inbufx4 + 1 * (inlen + 4), in1, inlen); + memcpy(inbufx4 + 2 * (inlen + 4), in2, inlen); + memcpy(inbufx4 + 3 * (inlen + 4), in3, inlen); + + /* While we can fit in at least another full block of SHA512 output.. */ + unsigned long remaining = outlen; + for (i = 0; remaining > 0; i++) { + unsigned long this_step = SPX_SHA512_OUTPUT_BYTES; + if (this_step > remaining) { + this_step = remaining; + } + remaining -= this_step; + for (j = 0; j < 4; j++) { + u32_to_bytes(inbufx4 + inlen + j * (inlen + 4), i); + } + + sha512x4ctx ctx; + sha512_init4x(&ctx); + + _sha512x4( + &ctx, + outbuf + 0 * 64, + outbuf + 1 * 64, + outbuf + 2 * 64, + outbuf + 3 * 64, + inbufx4 + 0 * (inlen + 4), + inbufx4 + 1 * (inlen + 4), + inbufx4 + 2 * (inlen + 4), + inbufx4 + 3 * (inlen + 4), + inlen + 4 + ); + + memcpy(outx4 + 0 * outlen, outbuf + 0 * 64, this_step); + memcpy(outx4 + 1 * outlen, outbuf + 1 * 64, this_step); + memcpy(outx4 + 2 * outlen, outbuf + 2 * 64, this_step); + memcpy(outx4 + 3 * outlen, outbuf + 3 * 64, this_step); + outx4 += this_step; + } +} + +void sha512x4_seeded( + unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const sha512x4ctx *seed, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + unsigned long long inlen) { + sha512x4ctx ctx; + sha512_ctx_clone4x(&ctx, seed); + _sha512x4( + &ctx, + out0, out1, out2, out3, + in0, in1, in2, in3, + inlen + ); +} + +void sha512_ctx_clone4x(sha512x4ctx *out, const sha512x4ctx *in) { + memcpy(out, in, sizeof(sha512x4ctx)); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/sha512x4.h b/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/sha512x4.h new file mode 100644 index 0000000000..9bbe736514 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/sha512x4.h @@ -0,0 +1,58 @@ +#ifndef SHA512AVX_H +#define SHA512AVX_H + +#include +#include + + +#include "params.h" + +typedef struct SHA512state4x { + __m256i s[8]; + unsigned char msgblocks[4 * 128]; + unsigned int datalen; + unsigned long long msglen; +} sha512x4ctx; + +#define sha512_init4x SPX_NAMESPACE(sha512_init4x) +void sha512_init4x(sha512x4ctx *ctx); + +#define sha512_transform4x SPX_NAMESPACE(sha512_transform4x) +void sha512_transform4x( + sha512x4ctx *ctx, + const unsigned char *d0, + const unsigned char *d1, + const unsigned char *d2, + const unsigned char *d3); + + +#define sha512x4_seeded SPX_NAMESPACE(sha512x4_seeded) +void sha512x4_seeded( + unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const sha512x4ctx *seed, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + unsigned long long inlen); + +#define sha512_ctx_clone4x SPX_NAMESPACE(sha512_ctx_clone4x) +void sha512_ctx_clone4x(sha512x4ctx *out, const sha512x4ctx *in); + +/** + * Note that inlen should be sufficiently small that it still allows for + * an array to be allocated on the stack. Typically 'in' is merely a seed. + * Outputs outlen number of bytes + */ +#define mgf1x4_512 SPX_NAMESPACE(mgf1x4_512) +void mgf1x4_512(unsigned char *outx4, unsigned long outlen, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + unsigned long inlen); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/sign.c b/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/sign.c new file mode 100644 index 0000000000..9d0c7d1b22 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/sign.c @@ -0,0 +1,286 @@ +#include +#include +#include + +#include "address.h" +#include "context.h" +#include "fors.h" +#include "hash.h" +#include "merkle.h" +#include "nistapi.h" +#include "params.h" +#include "randombytes.h" +#include "thash.h" +#include "utils.h" +#include "wots.h" + +/* + * Returns the length of a secret key, in bytes + */ +size_t crypto_sign_secretkeybytes(void) { + return CRYPTO_SECRETKEYBYTES; +} + +/* + * Returns the length of a public key, in bytes + */ +size_t crypto_sign_publickeybytes(void) { + return CRYPTO_PUBLICKEYBYTES; +} + +/* + * Returns the length of a signature, in bytes + */ +size_t crypto_sign_bytes(void) { + return CRYPTO_BYTES; +} + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +size_t crypto_sign_seedbytes(void) { + return CRYPTO_SEEDBYTES; +} + +/* + * Generates an SPX key pair given a seed of length + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [PUB_SEED || root] + */ +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed) { + spx_ctx ctx; + + /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ + memcpy(sk, seed, CRYPTO_SEEDBYTES); + + memcpy(pk, sk + 2 * SPX_N, SPX_N); + + memcpy(ctx.pub_seed, pk, SPX_N); + memcpy(ctx.sk_seed, sk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + /* Compute root node of the top-most subtree. */ + merkle_gen_root(sk + 3 * SPX_N, &ctx); + + // cleanup + free_hash_function(&ctx); + + memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); + + return 0; +} + +/* + * Generates an SPX key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [PUB_SEED || root] + */ +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { + uint8_t seed[CRYPTO_SEEDBYTES]; + randombytes(seed, CRYPTO_SEEDBYTES); + crypto_sign_seed_keypair(pk, sk, seed); + + return 0; +} + +/** + * Returns an array containing a detached signature. + */ +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk) { + spx_ctx ctx; + + const uint8_t *sk_prf = sk + SPX_N; + const uint8_t *pk = sk + 2 * SPX_N; + + uint8_t optrand[SPX_N]; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t root[SPX_N]; + uint32_t i; + uint64_t tree; + uint32_t idx_leaf; + uint32_t wots_addr[8] = {0}; + uint32_t tree_addr[8] = {0}; + + memcpy(ctx.sk_seed, sk, SPX_N); + memcpy(ctx.pub_seed, pk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + + /* Optionally, signing can be made non-deterministic using optrand. + This can help counter side-channel attacks that would benefit from + getting a large number of traces when the signer uses the same nodes. */ + randombytes(optrand, SPX_N); + /* Compute the digest randomization value. */ + gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); + + /* Derive the message digest and leaf index from R, PK and M. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; + + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); + + /* Sign the message hash using FORS. */ + fors_sign(sig, root, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); + sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; + + /* Update the indices for the next layer. */ + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; + } + + free_hash_function(&ctx); + + *siglen = SPX_BYTES; + + return 0; +} + +/** + * Verifies a detached signature and message under a given public key. + */ +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk) { + spx_ctx ctx; + const uint8_t *pub_root = pk + SPX_N; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t wots_pk[SPX_WOTS_BYTES]; + uint8_t root[SPX_N]; + uint8_t leaf[SPX_N]; + unsigned int i; + uint64_t tree; + uint32_t idx_leaf; + uint32_t wots_addr[8] = {0}; + uint32_t tree_addr[8] = {0}; + uint32_t wots_pk_addr[8] = {0}; + + if (siglen != SPX_BYTES) { + return -1; + } + + memcpy(ctx.pub_seed, pk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); + + /* Derive the message digest and leaf index from R || PK || M. */ + /* The additional SPX_N is a result of the hash domain separator. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; + + /* Layer correctly defaults to 0, so no need to set_layer_addr */ + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); + + fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + /* For each subtree.. */ + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + copy_keypair_addr(wots_pk_addr, wots_addr); + + /* The WOTS public key is only correct if the signature was correct. */ + /* Initially, root is the FORS pk, but on subsequent iterations it is + the root of the subtree below the currently processed subtree. */ + wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); + sig += SPX_WOTS_BYTES; + + /* Compute the leaf node using the WOTS public key. */ + thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); + + /* Compute the root node of this subtree. */ + compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, + &ctx, tree_addr); + sig += SPX_TREE_HEIGHT * SPX_N; + + /* Update the indices for the next layer. */ + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; + } + + // cleanup + free_hash_function(&ctx); + + /* Check if the root node equals the root node in the public key. */ + if (memcmp(root, pub_root, SPX_N) != 0) { + return -1; + } + + return 0; +} + + +/** + * Returns an array containing the signature followed by the message. + */ +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk) { + size_t siglen; + + crypto_sign_signature(sm, &siglen, m, mlen, sk); + + memmove(sm + SPX_BYTES, m, mlen); + *smlen = siglen + mlen; + + return 0; +} + +/** + * Verifies a given signature-message pair under a given public key. + */ +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk) { + /* The API caller does not necessarily know what size a signature should be + but SPHINCS+ signatures are always exactly SPX_BYTES. */ + if (smlen < SPX_BYTES) { + memset(m, 0, smlen); + *mlen = 0; + return -1; + } + + *mlen = smlen - SPX_BYTES; + + if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { + memset(m, 0, smlen); + *mlen = 0; + return -1; + } + + /* If verification was successful, move the message to the right place. */ + memmove(m, sm + SPX_BYTES, *mlen); + + return 0; +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/thash.h b/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/thash.h new file mode 100644 index 0000000000..8687ccfb4d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/thash.h @@ -0,0 +1,13 @@ +#ifndef SPX_THASH_H +#define SPX_THASH_H + +#include "context.h" +#include "params.h" + +#include + +#define thash SPX_NAMESPACE(thash) +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/thash_sha2_simple.c b/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/thash_sha2_simple.c new file mode 100644 index 0000000000..87badc4d53 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/thash_sha2_simple.c @@ -0,0 +1,53 @@ +#include +#include + +#include "thash.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "sha2.h" +#include "utils.h" + +static void thash_512(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]); + +/** + * Takes an array of inblocks concatenated arrays of SPX_N bytes. + */ +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]) { + if (inblocks > 1) { + thash_512(out, in, inblocks, ctx, addr); + return; + } + + unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES]; + sha256ctx sha2_state; + PQCLEAN_VLA(uint8_t, buf, SPX_SHA256_ADDR_BYTES + inblocks * SPX_N); + + /* Retrieve precomputed state containing pub_seed */ + sha256_inc_ctx_clone(&sha2_state, &ctx->state_seeded); + + memcpy(buf, addr, SPX_SHA256_ADDR_BYTES); + memcpy(buf + SPX_SHA256_ADDR_BYTES, in, inblocks * SPX_N); + + sha256_inc_finalize(outbuf, &sha2_state, buf, SPX_SHA256_ADDR_BYTES + inblocks * SPX_N); + memcpy(out, outbuf, SPX_N); +} + +static void thash_512(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]) { + unsigned char outbuf[SPX_SHA512_OUTPUT_BYTES]; + sha512ctx sha2_state; + PQCLEAN_VLA(uint8_t, buf, SPX_SHA256_ADDR_BYTES + inblocks * SPX_N); + + /* Retrieve precomputed state containing pub_seed */ + sha512_inc_ctx_clone(&sha2_state, &ctx->state_seeded_512); + + memcpy(buf, addr, SPX_SHA256_ADDR_BYTES); + memcpy(buf + SPX_SHA256_ADDR_BYTES, in, inblocks * SPX_N); + + sha512_inc_finalize(outbuf, &sha2_state, buf, SPX_SHA256_ADDR_BYTES + inblocks * SPX_N); + memcpy(out, outbuf, SPX_N); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/thash_sha2_simplex8.c b/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/thash_sha2_simplex8.c new file mode 100644 index 0000000000..9b946f4e4a --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/thash_sha2_simplex8.c @@ -0,0 +1,212 @@ +#include +#include + +#include "thashx8.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "sha2.h" +#include "sha256avx.h" +#include "sha256x8.h" +#include "utils.h" + +#include "sha512x4.h" + +static void thashx8_512( + unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, + unsigned int inblocks, + const spx_ctx *ctx, + uint32_t addrx8[8 * 8] +); + +/** + * 8-way parallel version of thash; takes 8x as much input and output + */ +void thashx8(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addrx8[8 * 8]) { + if (inblocks > 1) { + thashx8_512( + out0, out1, out2, out3, out4, out5, out6, out7, + in0, in1, in2, in3, in4, in5, in6, in7, + inblocks, ctx, addrx8); + return; + } + PQCLEAN_VLA(unsigned char, bufx8, 8 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)); + unsigned char outbufx8[8 * SPX_SHA256_OUTPUT_BYTES]; + unsigned int i; + + for (i = 0; i < 8; i++) { + memcpy(bufx8 + i * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + addrx8 + i * 8, SPX_SHA256_ADDR_BYTES); + } + + memcpy(bufx8 + SPX_SHA256_ADDR_BYTES + + 0 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), in0, inblocks * SPX_N); + memcpy(bufx8 + SPX_SHA256_ADDR_BYTES + + 1 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), in1, inblocks * SPX_N); + memcpy(bufx8 + SPX_SHA256_ADDR_BYTES + + 2 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), in2, inblocks * SPX_N); + memcpy(bufx8 + SPX_SHA256_ADDR_BYTES + + 3 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), in3, inblocks * SPX_N); + memcpy(bufx8 + SPX_SHA256_ADDR_BYTES + + 4 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), in4, inblocks * SPX_N); + memcpy(bufx8 + SPX_SHA256_ADDR_BYTES + + 5 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), in5, inblocks * SPX_N); + memcpy(bufx8 + SPX_SHA256_ADDR_BYTES + + 6 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), in6, inblocks * SPX_N); + memcpy(bufx8 + SPX_SHA256_ADDR_BYTES + + 7 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), in7, inblocks * SPX_N); + + sha256x8_seeded( + /* out */ + outbufx8 + 0 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 1 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 2 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 3 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 4 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 5 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 6 * SPX_SHA256_OUTPUT_BYTES, + outbufx8 + 7 * SPX_SHA256_OUTPUT_BYTES, + + /* seed */ + &ctx->statex8_seeded, + + /* in */ + bufx8 + 0 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + 1 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + 2 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + 3 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + 4 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + 5 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + 6 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + 7 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N /* len */ + ); + + memcpy(out0, outbufx8 + 0 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out1, outbufx8 + 1 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out2, outbufx8 + 2 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out3, outbufx8 + 3 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out4, outbufx8 + 4 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out5, outbufx8 + 5 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out6, outbufx8 + 6 * SPX_SHA256_OUTPUT_BYTES, SPX_N); + memcpy(out7, outbufx8 + 7 * SPX_SHA256_OUTPUT_BYTES, SPX_N); +} + +/** + * 2x4-way parallel version of thash; this is for the uses of thash that are + * based on SHA-512 + */ +static void thashx8_512( + unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, + unsigned int inblocks, + const spx_ctx *ctx, + uint32_t addrx8[8 * 8]) { + PQCLEAN_VLA(unsigned char, bufx8, 8 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)); + unsigned char outbuf[4 * SPX_SHA512_OUTPUT_BYTES]; + unsigned int i; + + for (i = 0; i < 8; i++) { + memcpy(bufx8 + i * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + addrx8 + i * 8, SPX_SHA256_ADDR_BYTES); + } + + memcpy(bufx8 + SPX_SHA256_ADDR_BYTES + + 0 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), in0, inblocks * SPX_N); + memcpy(bufx8 + SPX_SHA256_ADDR_BYTES + + 1 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), in1, inblocks * SPX_N); + memcpy(bufx8 + SPX_SHA256_ADDR_BYTES + + 2 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), in2, inblocks * SPX_N); + memcpy(bufx8 + SPX_SHA256_ADDR_BYTES + + 3 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), in3, inblocks * SPX_N); + memcpy(bufx8 + SPX_SHA256_ADDR_BYTES + + 4 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), in4, inblocks * SPX_N); + memcpy(bufx8 + SPX_SHA256_ADDR_BYTES + + 5 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), in5, inblocks * SPX_N); + memcpy(bufx8 + SPX_SHA256_ADDR_BYTES + + 6 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), in6, inblocks * SPX_N); + memcpy(bufx8 + SPX_SHA256_ADDR_BYTES + + 7 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), in7, inblocks * SPX_N); + + sha512x4_seeded( + outbuf + 0 * SPX_SHA512_OUTPUT_BYTES, + outbuf + 1 * SPX_SHA512_OUTPUT_BYTES, + outbuf + 2 * SPX_SHA512_OUTPUT_BYTES, + outbuf + 3 * SPX_SHA512_OUTPUT_BYTES, + &ctx->statex4_seeded_512, /* seed */ + bufx8 + 0 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), /* in */ + bufx8 + 1 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + 2 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + 3 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N /* len */ + ); + + memcpy(out0, outbuf + 0 * SPX_SHA512_OUTPUT_BYTES, SPX_N); + memcpy(out1, outbuf + 1 * SPX_SHA512_OUTPUT_BYTES, SPX_N); + memcpy(out2, outbuf + 2 * SPX_SHA512_OUTPUT_BYTES, SPX_N); + memcpy(out3, outbuf + 3 * SPX_SHA512_OUTPUT_BYTES, SPX_N); + + sha512x4_seeded( + outbuf + 0 * SPX_SHA512_OUTPUT_BYTES, + outbuf + 1 * SPX_SHA512_OUTPUT_BYTES, + outbuf + 2 * SPX_SHA512_OUTPUT_BYTES, + outbuf + 3 * SPX_SHA512_OUTPUT_BYTES, + &ctx->statex4_seeded_512, /* seed */ + bufx8 + 4 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), /* in */ + bufx8 + 5 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + 6 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + bufx8 + 7 * (SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N /* len */ + ); + + memcpy(out4, outbuf + 0 * SPX_SHA512_OUTPUT_BYTES, SPX_N); + memcpy(out5, outbuf + 1 * SPX_SHA512_OUTPUT_BYTES, SPX_N); + memcpy(out6, outbuf + 2 * SPX_SHA512_OUTPUT_BYTES, SPX_N); + memcpy(out7, outbuf + 3 * SPX_SHA512_OUTPUT_BYTES, SPX_N); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/thashx8.h b/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/thashx8.h new file mode 100644 index 0000000000..c02fe9cf3e --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/thashx8.h @@ -0,0 +1,28 @@ +#ifndef SPX_THASHX8_H +#define SPX_THASHX8_H + +#include + +#include "context.h" +#include "params.h" + +#define thashx8 SPX_NAMESPACE(thashx8) +void thashx8(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + unsigned char *out4, + unsigned char *out5, + unsigned char *out6, + unsigned char *out7, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, + const unsigned char *in4, + const unsigned char *in5, + const unsigned char *in6, + const unsigned char *in7, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addrx8[8 * 8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/utils.c b/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/utils.c new file mode 100644 index 0000000000..177b541fb9 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/utils.c @@ -0,0 +1,148 @@ +#include + +#include "utils.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "thash.h" + +/** + * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. + */ +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in) { + int i; + + /* Iterate over out in decreasing order, for big-endianness. */ + for (i = (signed int)outlen - 1; i >= 0; i--) { + out[i] = in & 0xff; + in = in >> 8; + } +} + +void u32_to_bytes(unsigned char *out, uint32_t in) { + out[0] = (unsigned char)(in >> 24); + out[1] = (unsigned char)(in >> 16); + out[2] = (unsigned char)(in >> 8); + out[3] = (unsigned char)in; +} + +/** + * Converts the inlen bytes in 'in' from big-endian byte order to an integer. + */ +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { + unsigned long long retval = 0; + unsigned int i; + + for (i = 0; i < inlen; i++) { + retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); + } + return retval; +} + +/** + * Computes a root node given a leaf and an auth path. + * Expects address to be complete other than the tree_height and tree_index. + */ +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]) { + uint32_t i; + unsigned char buffer[2 * SPX_N]; + + /* If leaf_idx is odd (last bit = 1), current path element is a right child + and auth_path has to go left. Otherwise it is the other way around. */ + if (leaf_idx & 1) { + memcpy(buffer + SPX_N, leaf, SPX_N); + memcpy(buffer, auth_path, SPX_N); + } else { + memcpy(buffer, leaf, SPX_N); + memcpy(buffer + SPX_N, auth_path, SPX_N); + } + auth_path += SPX_N; + + for (i = 0; i < tree_height - 1; i++) { + leaf_idx >>= 1; + idx_offset >>= 1; + /* Set the address of the node we're creating. */ + set_tree_height(addr, i + 1); + set_tree_index(addr, leaf_idx + idx_offset); + + /* Pick the right or left neighbor, depending on parity of the node. */ + if (leaf_idx & 1) { + thash(buffer + SPX_N, buffer, 2, ctx, addr); + memcpy(buffer, auth_path, SPX_N); + } else { + thash(buffer, buffer, 2, ctx, addr); + memcpy(buffer + SPX_N, auth_path, SPX_N); + } + auth_path += SPX_N; + } + + /* The last iteration is exceptional; we do not copy an auth_path node. */ + leaf_idx >>= 1; + idx_offset >>= 1; + set_tree_height(addr, tree_height); + set_tree_index(addr, leaf_idx + idx_offset); + thash(root, buffer, 2, ctx, addr); +} + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx * /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]) { + PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); + PQCLEAN_VLA(unsigned int, heights, tree_height + 1); + unsigned int offset = 0; + uint32_t idx; + uint32_t tree_idx; + + for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { + /* Add the next leaf node to the stack. */ + gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); + offset++; + heights[offset - 1] = 0; + + /* If this is a node we need for the auth path.. */ + if ((leaf_idx ^ 0x1) == idx) { + memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); + } + + /* While the top-most nodes are of equal height.. */ + while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { + /* Compute index of the new node, in the next layer. */ + tree_idx = (idx >> (heights[offset - 1] + 1)); + + /* Set the address of the node we're creating. */ + set_tree_height(tree_addr, heights[offset - 1] + 1); + set_tree_index(tree_addr, + tree_idx + (idx_offset >> (heights[offset - 1] + 1))); + /* Hash the top-most nodes from the stack together. */ + thash(stack + (offset - 2)*SPX_N, + stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); + offset--; + /* Note that the top-most node is now one layer higher. */ + heights[offset - 1]++; + + /* If this is a node we need for the auth path.. */ + if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { + memcpy(auth_path + heights[offset - 1]*SPX_N, + stack + (offset - 1)*SPX_N, SPX_N); + } + } + } + memcpy(root, stack, SPX_N); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/utils.h b/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/utils.h new file mode 100644 index 0000000000..64f5d5a53a --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/utils.h @@ -0,0 +1,58 @@ +#ifndef SPX_UTILS_H +#define SPX_UTILS_H + +#include + +#include "compat.h" +#include "context.h" +#include "params.h" + + +/* To support MSVC use alloca() instead of VLAs. See #20. */ + + +/** + * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. + */ +#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in); +#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) +void u32_to_bytes(unsigned char *out, uint32_t in); + +/** + * Converts the inlen bytes in 'in' from big-endian byte order to an integer. + */ +#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); + +/** + * Computes a root node given a leaf and an auth path. + * Expects address to be complete other than the tree_height and tree_index. + */ +#define compute_root SPX_NAMESPACE(compute_root) +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]); + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +#define treehash SPX_NAMESPACE(treehash) +void treehash(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx *ctx /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]); + + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/utilsx8.c b/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/utilsx8.c new file mode 100644 index 0000000000..f044b9595d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/utilsx8.c @@ -0,0 +1,146 @@ +#include + +#include "utils.h" +#include "utilsx8.h" + +#include "address.h" +#include "params.h" +#include "thashx8.h" + +/* + * Generate the entire Merkle tree, computing the authentication path for leaf_idx, + * and the resulting root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) + * + * This expects tree_addrx8 to be initialized to 8 parallel addr structures for + * the Merkle tree nodes + * + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + * + * This works by using the standard Merkle tree building algorithm, except + * that each 'node' tracked is actually 8 consecutive nodes in the real tree. + * When we combine two logical nodes ABCDEFGH and STUVWXYZ, we perform the H + * operation on adjacent real nodes, forming the parent logical node + * (AB)(CD)(EF)(GH)(ST)(UV)(WX)(YZ) + * + * When we get to the top three levels of the real tree (where there is only + * one logical node), we continue this operation three more times; the right + * most real node will by the actual root (and the other 7 nodes will be + * garbage). We follow the same thashx8 logic so that the 'extract + * authentication path components' part of the loop is still executed (and + * to simplify the code somewhat) + * + * This currently assumes tree_height >= 3; I suspect that doing an adjusting + * idx, addr_idx on the gen_leafx8 call if tree_height < 3 would fix it; since + * we don't actually use such short trees, I haven't bothered + */ +void treehashx8(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, + uint32_t tree_height, + void (*gen_leafx8)( + unsigned char * /* Where to write the leaves */, + const spx_ctx *, + uint32_t idx, void *info), + uint32_t tree_addrx8[8 * 8], + void *info) { + /* This is where we keep the intermediate nodes */ + PQCLEAN_VLA(unsigned char, stackx8, tree_height * 8 * SPX_N); + uint32_t left_adj = 0, prev_left_adj = 0; /* When we're doing the top 3 */ + /* levels, the left-most part of the tree isn't at the beginning */ + /* of current[]. These give the offset of the actual start */ + + uint32_t idx; + uint32_t max_idx = ((uint32_t)1 << (tree_height - 3)) - 1; + for (idx = 0;; idx++) { + unsigned char current[8 * SPX_N]; /* Current logical node */ + gen_leafx8( current, ctx, 8 * idx + idx_offset, + info ); + + /* Now combine the freshly generated right node with previously */ + /* generated left ones */ + uint32_t internal_idx_offset = idx_offset; + uint32_t internal_idx = idx; + uint32_t internal_leaf = leaf_idx; + uint32_t h; /* The height we are in the Merkle tree */ + for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { + + /* Special processing if we're at the top of the tree */ + if (h >= tree_height - 3) { + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[7 * SPX_N], SPX_N ); + return; + } + /* The tree indexing logic is a bit off in this case */ + /* Adjust it so that the left-most node of the part of */ + /* the tree that we're processing has index 0 */ + prev_left_adj = left_adj; + left_adj = (uint32_t)(8 - (1 << (tree_height - h - 1))); + } + + /* Check if we hit the top of the tree */ + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[7 * SPX_N], SPX_N ); + return; + } + + /* + * Check if one of the nodes we have is a part of the + * authentication path; if it is, write it out + */ + if ((((internal_idx << 3) ^ internal_leaf) & ~0x7U) == 0) { + memcpy( &auth_path[ h * SPX_N ], + ¤t[(((internal_leaf & 7) ^ 1) + prev_left_adj) * SPX_N], + SPX_N ); + } + + /* + * Check if we're at a left child; if so, stop going up the stack + * Exception: if we've reached the end of the tree, keep on going + * (so we combine the last 8 nodes into the one root node in three + * more iterations) + */ + if ((internal_idx & 1) == 0 && idx < max_idx) { + break; + } + + /* Ok, we're at a right node (or doing the top 3 levels) */ + /* Now combine the left and right logical nodes together */ + + /* Set the address of the node we're creating. */ + uint32_t j; + internal_idx_offset >>= 1; + for (j = 0; j < 8; j++) { + set_tree_height(tree_addrx8 + j * 8, h + 1); + set_tree_index(tree_addrx8 + j * 8, + (8 / 2) * (internal_idx & ~1U) + j - left_adj + internal_idx_offset ); + } + unsigned char *left = &stackx8[h * 8 * SPX_N]; + thashx8( ¤t[0 * SPX_N], + ¤t[1 * SPX_N], + ¤t[2 * SPX_N], + ¤t[3 * SPX_N], + ¤t[4 * SPX_N], + ¤t[5 * SPX_N], + ¤t[6 * SPX_N], + ¤t[7 * SPX_N], + &left [0 * SPX_N], + &left [2 * SPX_N], + &left [4 * SPX_N], + &left [6 * SPX_N], + ¤t[0 * SPX_N], + ¤t[2 * SPX_N], + ¤t[4 * SPX_N], + ¤t[6 * SPX_N], + 2, ctx, tree_addrx8); + } + + /* We've hit a left child; save the current for when we get the */ + /* corresponding right right */ + memcpy( &stackx8[h * 8 * SPX_N], current, 8 * SPX_N); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/utilsx8.h b/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/utilsx8.h new file mode 100644 index 0000000000..806d1e85be --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/utilsx8.h @@ -0,0 +1,29 @@ +#ifndef SPX_UTILSX8_H +#define SPX_UTILSX8_H + +#include + +#include "params.h" + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + * + * This implementation uses AVX to compute internal nodes 8 at a time (in + * parallel) + */ +#define treehashx8 SPX_NAMESPACE(treehashx8) +void treehashx8(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leafx8)( + unsigned char * /* Where to write the leaves */, + const spx_ctx * /* ctx */, + uint32_t addr_idx, void *info), + uint32_t tree_addrx8[8 * 8], void *info); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/wots.c b/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/wots.c new file mode 100644 index 0000000000..689baf4db9 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/wots.c @@ -0,0 +1,291 @@ +#include +#include + +#include "wots.h" + +#include "address.h" +#include "hash.h" +#include "hashx8.h" +#include "params.h" +#include "thash.h" +#include "thashx8.h" +#include "utils.h" +#include "utilsx8.h" +#include "wotsx8.h" + +// TODO clarify address expectations, and make them more uniform. +// TODO i.e. do we expect types to be set already? +// TODO and do we expect modifications or copies? + +/** + * Computes up the chains + */ +static void gen_chains( + unsigned char *out, + const unsigned char *in, + unsigned int start[SPX_WOTS_LEN], + const unsigned int steps[SPX_WOTS_LEN], + const spx_ctx *ctx, + uint32_t addr[8]) { + uint32_t i, j, k, idx, watching; + int done; + unsigned char empty[SPX_N]; + unsigned char *bufs[8]; + uint32_t addrs[8 * 8]; + + int l; + uint16_t counts[SPX_WOTS_W] = { 0 }; + uint16_t idxs[SPX_WOTS_LEN]; + uint16_t total, newTotal; + + /* set addrs = {addr, addr, ..., addr} */ + for (j = 0; j < 8; j++) { + memcpy(addrs + j * 8, addr, sizeof(uint32_t) * 8); + } + + /* Initialize out with the value at position 'start'. */ + memcpy(out, in, SPX_WOTS_LEN * SPX_N); + + /* Sort the chains in reverse order by steps using counting sort. */ + for (i = 0; i < SPX_WOTS_LEN; i++) { + counts[steps[i]]++; + } + total = 0; + for (l = SPX_WOTS_W - 1; l >= 0; l--) { + newTotal = counts[l] + total; + counts[l] = total; + total = newTotal; + } + for (i = 0; i < SPX_WOTS_LEN; i++) { + idxs[counts[steps[i]]] = (uint16_t)i; + counts[steps[i]]++; + } + + /* We got our work cut out for us: do it! */ + for (i = 0; i < SPX_WOTS_LEN; i += 8) { + for (j = 0; j < 8 && i + j < SPX_WOTS_LEN; j++) { + idx = idxs[i + j]; + set_chain_addr(addrs + j * 8, idx); + bufs[j] = out + SPX_N * idx; + } + + /* As the chains are sorted in reverse order, we know that the first + * chain is the longest and the last one is the shortest. We keep + * an eye on whether the last chain is done and then on the one before, + * et cetera. */ + watching = 7; + done = 0; + while (i + watching >= SPX_WOTS_LEN) { + bufs[watching] = &empty[0]; + watching--; + } + + for (k = 0;; k++) { + while (k == steps[idxs[i + watching]]) { + bufs[watching] = &empty[0]; + if (watching == 0) { + done = 1; + break; + } + watching--; + } + if (done) { + break; + } + for (j = 0; j < watching + 1; j++) { + set_hash_addr(addrs + j * 8, k + start[idxs[i + j]]); + } + + thashx8(bufs[0], bufs[1], bufs[2], bufs[3], + bufs[4], bufs[5], bufs[6], bufs[7], + bufs[0], bufs[1], bufs[2], bufs[3], + bufs[4], bufs[5], bufs[6], bufs[7], 1, ctx, addrs); + } + } +} + +/** + * base_w algorithm as described in draft. + * Interprets an array of bytes as integers in base w. + * This only works when log_w is a divisor of 8. + */ +static void base_w(unsigned int *output, const int out_len, + const unsigned char *input) { + int in = 0; + int out = 0; + unsigned char total = 0; + int bits = 0; + int consumed; + + for (consumed = 0; consumed < out_len; consumed++) { + if (bits == 0) { + total = input[in]; + in++; + bits += 8; + } + bits -= SPX_WOTS_LOGW; + output[out] = (total >> bits) & (SPX_WOTS_W - 1); + out++; + } +} + +/* Computes the WOTS+ checksum over a message (in base_w). */ +static void wots_checksum(unsigned int *csum_base_w, + const unsigned int *msg_base_w) { + unsigned int csum = 0; + unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; + unsigned int i; + + /* Compute checksum. */ + for (i = 0; i < SPX_WOTS_LEN1; i++) { + csum += SPX_WOTS_W - 1 - msg_base_w[i]; + } + + /* Convert checksum to base_w. */ + /* Make sure expected empty zero bits are the least significant bits. */ + csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); + ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); + base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); +} + +/* Takes a message and derives the matching chain lengths. */ +void chain_lengths(unsigned int *lengths, const unsigned char *msg) { + base_w(lengths, SPX_WOTS_LEN1, msg); + wots_checksum(lengths + SPX_WOTS_LEN1, lengths); +} + +/** + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. + * + * Writes the computed public key to 'pk'. + */ +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]) { + unsigned int steps[SPX_WOTS_LEN]; + unsigned int start[SPX_WOTS_LEN]; + uint32_t i; + + chain_lengths(start, msg); + + for (i = 0; i < SPX_WOTS_LEN; i++) { + steps[i] = SPX_WOTS_W - 1 - start[i]; + } + + gen_chains(pk, sig, start, steps, ctx, addr); +} + +/* + * This generates 8 sequential WOTS public keys + * It also generates the WOTS signature if leaf_info indicates + * that we're signing with one of these WOTS keys + */ +void wots_gen_leafx8(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info) { + struct leaf_info_x8 *info = v_info; + uint32_t *leaf_addr = info->leaf_addr; + uint32_t *pk_addr = info->pk_addr; + unsigned int i, j, k; + unsigned char pk_buffer[ 8 * SPX_WOTS_BYTES ]; + unsigned wots_offset = SPX_WOTS_BYTES; + unsigned char *buffer; + uint32_t wots_k_mask; + unsigned wots_sign_index; + + if (((leaf_idx ^ info->wots_sign_leaf) & ~7U) == 0) { + /* We're traversing the leaf that's signing; generate the WOTS */ + /* signature */ + wots_k_mask = 0; + wots_sign_index = info->wots_sign_leaf & 7; /* Which of of the 8 */ + /* slots do the signatures come from */ + } else { + /* Nope, we're just generating pk's; turn off the signature logic */ + wots_k_mask = ~0U; + wots_sign_index = 0; + } + + for (j = 0; j < 8; j++) { + set_keypair_addr( leaf_addr + j * 8, leaf_idx + j ); + set_keypair_addr( pk_addr + j * 8, leaf_idx + j ); + } + + for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { + uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k */ + /* to the step if we're generating a signature, ~0 if we're not */ + + /* Start with the secret seed */ + for (j = 0; j < 8; j++) { + set_chain_addr(leaf_addr + j * 8, i); + set_hash_addr(leaf_addr + j * 8, 0); + set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTSPRF); + } + prf_addrx8(buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + buffer + 2 * wots_offset, + buffer + 3 * wots_offset, + buffer + 4 * wots_offset, + buffer + 5 * wots_offset, + buffer + 6 * wots_offset, + buffer + 7 * wots_offset, + ctx, leaf_addr); + + for (j = 0; j < 8; j++) { + set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTS); + } + + /* Iterate down the WOTS chain */ + for (k = 0;; k++) { + /* Check if one of the values we have needs to be saved as a */ + /* part of the WOTS signature */ + if (k == wots_k) { + memcpy( info->wots_sig + i * SPX_N, + buffer + wots_sign_index * wots_offset, SPX_N ); + } + + /* Check if we hit the top of the chain */ + if (k == SPX_WOTS_W - 1) { + break; + } + + /* Iterate one step on all 8 chains */ + for (j = 0; j < 8; j++) { + set_hash_addr(leaf_addr + j * 8, k); + } + thashx8(buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + buffer + 2 * wots_offset, + buffer + 3 * wots_offset, + buffer + 4 * wots_offset, + buffer + 5 * wots_offset, + buffer + 6 * wots_offset, + buffer + 7 * wots_offset, + buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + buffer + 2 * wots_offset, + buffer + 3 * wots_offset, + buffer + 4 * wots_offset, + buffer + 5 * wots_offset, + buffer + 6 * wots_offset, + buffer + 7 * wots_offset, 1, ctx, leaf_addr); + } + } + + /* Do the final thash to generate the public keys */ + thashx8(dest + 0 * SPX_N, + dest + 1 * SPX_N, + dest + 2 * SPX_N, + dest + 3 * SPX_N, + dest + 4 * SPX_N, + dest + 5 * SPX_N, + dest + 6 * SPX_N, + dest + 7 * SPX_N, + pk_buffer + 0 * wots_offset, + pk_buffer + 1 * wots_offset, + pk_buffer + 2 * wots_offset, + pk_buffer + 3 * wots_offset, + pk_buffer + 4 * wots_offset, + pk_buffer + 5 * wots_offset, + pk_buffer + 6 * wots_offset, + pk_buffer + 7 * wots_offset, SPX_WOTS_LEN, ctx, pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/wots.h b/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/wots.h new file mode 100644 index 0000000000..4e7692eeef --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/wots.h @@ -0,0 +1,25 @@ +#ifndef SPX_WOTS_H +#define SPX_WOTS_H + +#include + +#include "context.h" +#include "params.h" + +/** + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. + * + * Writes the computed public key to 'pk'. + */ +#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]); + +/* + * Compute the chain lengths needed for a given message hash + */ +#define chain_lengths SPX_NAMESPACE(chain_lengths) +void chain_lengths(unsigned int *lengths, const unsigned char *msg); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/wotsx8.h b/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/wotsx8.h new file mode 100644 index 0000000000..10866efb35 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_avx2/wotsx8.h @@ -0,0 +1,42 @@ +#ifndef WOTSX8_H_ +#define WOTSX8_H_ + +#include + +#include "context.h" +#include "params.h" + +/* + * This is here to provide an interface to the internal wots_gen_leafx8 + * routine. While this routine is not referenced in the package outside of + * wots.c, it is called from the stand-alone benchmark code to characterize + * the performance + */ +struct leaf_info_x8 { + unsigned char *wots_sig; + uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ + uint32_t *wots_steps; + uint32_t leaf_addr[8 * 8]; + uint32_t pk_addr[8 * 8]; +}; + +/* Macro to set the leaf_info to something 'benign', that is, it would */ +/* run with the same time as it does during the real signing process */ +/* Used only by the benchmark code */ +#define INITIALIZE_LEAF_INFO_X8(info, addr, step_buffer) { \ + (info).wots_sig = 0; \ + (info).wots_sign_leaf = ~0; \ + (info).wots_steps = step_buffer; \ + int i; \ + for (i=0; i<8; i++) { \ + memcpy( &(info).leaf_addr[8*i], addr, 32 ); \ + memcpy( &(info).pk_addr[8*i], addr, 32 ); \ + } \ + } + +#define wots_gen_leafx8 SPX_NAMESPACE(wots_gen_leafx8) +void wots_gen_leafx8(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info); + +#endif /* WOTSX8_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_clean/LICENSE b/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_clean/LICENSE new file mode 100644 index 0000000000..670154e353 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_clean/LICENSE @@ -0,0 +1,116 @@ +CC0 1.0 Universal + +Statement of Purpose + +The laws of most jurisdictions throughout the world automatically confer +exclusive Copyright and Related Rights (defined below) upon the creator and +subsequent owner(s) (each and all, an "owner") of an original work of +authorship and/or a database (each, a "Work"). + +Certain owners wish to permanently relinquish those rights to a Work for the +purpose of contributing to a commons of creative, cultural and scientific +works ("Commons") that the public can reliably and without fear of later +claims of infringement build upon, modify, incorporate in other works, reuse +and redistribute as freely as possible in any form whatsoever and for any +purposes, including without limitation commercial purposes. These owners may +contribute to the Commons to promote the ideal of a free culture and the +further production of creative, cultural and scientific works, or to gain +reputation or greater distribution for their Work in part through the use and +efforts of others. + +For these and/or other purposes and motivations, and without any expectation +of additional consideration or compensation, the person associating CC0 with a +Work (the "Affirmer"), to the extent that he or she is an owner of Copyright +and Related Rights in the Work, voluntarily elects to apply CC0 to the Work +and publicly distribute the Work under its terms, with knowledge of his or her +Copyright and Related Rights in the Work and the meaning and intended legal +effect of CC0 on those rights. + +1. Copyright and Related Rights. A Work made available under CC0 may be +protected by copyright and related or neighboring rights ("Copyright and +Related Rights"). Copyright and Related Rights include, but are not limited +to, the following: + + i. the right to reproduce, adapt, distribute, perform, display, communicate, + and translate a Work; + + ii. moral rights retained by the original author(s) and/or performer(s); + + iii. publicity and privacy rights pertaining to a person's image or likeness + depicted in a Work; + + iv. rights protecting against unfair competition in regards to a Work, + subject to the limitations in paragraph 4(a), below; + + v. rights protecting the extraction, dissemination, use and reuse of data in + a Work; + + vi. database rights (such as those arising under Directive 96/9/EC of the + European Parliament and of the Council of 11 March 1996 on the legal + protection of databases, and under any national implementation thereof, + including any amended or successor version of such directive); and + + vii. other similar, equivalent or corresponding rights throughout the world + based on applicable law or treaty, and any national implementations thereof. + +2. Waiver. To the greatest extent permitted by, but not in contravention of, +applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and +unconditionally waives, abandons, and surrenders all of Affirmer's Copyright +and Related Rights and associated claims and causes of action, whether now +known or unknown (including existing as well as future claims and causes of +action), in the Work (i) in all territories worldwide, (ii) for the maximum +duration provided by applicable law or treaty (including future time +extensions), (iii) in any current or future medium and for any number of +copies, and (iv) for any purpose whatsoever, including without limitation +commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes +the Waiver for the benefit of each member of the public at large and to the +detriment of Affirmer's heirs and successors, fully intending that such Waiver +shall not be subject to revocation, rescission, cancellation, termination, or +any other legal or equitable action to disrupt the quiet enjoyment of the Work +by the public as contemplated by Affirmer's express Statement of Purpose. + +3. Public License Fallback. Should any part of the Waiver for any reason be +judged legally invalid or ineffective under applicable law, then the Waiver +shall be preserved to the maximum extent permitted taking into account +Affirmer's express Statement of Purpose. In addition, to the extent the Waiver +is so judged Affirmer hereby grants to each affected person a royalty-free, +non transferable, non sublicensable, non exclusive, irrevocable and +unconditional license to exercise Affirmer's Copyright and Related Rights in +the Work (i) in all territories worldwide, (ii) for the maximum duration +provided by applicable law or treaty (including future time extensions), (iii) +in any current or future medium and for any number of copies, and (iv) for any +purpose whatsoever, including without limitation commercial, advertising or +promotional purposes (the "License"). The License shall be deemed effective as +of the date CC0 was applied by Affirmer to the Work. Should any part of the +License for any reason be judged legally invalid or ineffective under +applicable law, such partial invalidity or ineffectiveness shall not +invalidate the remainder of the License, and in such case Affirmer hereby +affirms that he or she will not (i) exercise any of his or her remaining +Copyright and Related Rights in the Work or (ii) assert any associated claims +and causes of action with respect to the Work, in either case contrary to +Affirmer's express Statement of Purpose. + +4. Limitations and Disclaimers. + + a. No trademark or patent rights held by Affirmer are waived, abandoned, + surrendered, licensed or otherwise affected by this document. + + b. Affirmer offers the Work as-is and makes no representations or warranties + of any kind concerning the Work, express, implied, statutory or otherwise, + including without limitation warranties of title, merchantability, fitness + for a particular purpose, non infringement, or the absence of latent or + other defects, accuracy, or the present or absence of errors, whether or not + discoverable, all to the greatest extent permissible under applicable law. + + c. Affirmer disclaims responsibility for clearing rights of other persons + that may apply to the Work or any use thereof, including without limitation + any person's Copyright and Related Rights in the Work. Further, Affirmer + disclaims responsibility for obtaining any necessary consents, permissions + or other rights required for any use of the Work. + + d. Affirmer understands and acknowledges that Creative Commons is not a + party to this document and has no duty or obligation with respect to this + CC0 or use of the Work. + +For more information, please see + diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_clean/address.c b/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_clean/address.c new file mode 100644 index 0000000000..b956e9cb29 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_clean/address.c @@ -0,0 +1,91 @@ +#include +#include + +#include "address.h" +#include "params.h" +#include "utils.h" + +/* + * Specify which level of Merkle tree (the "layer") we're working on + */ +void set_layer_addr(uint32_t addr[8], uint32_t layer) { + ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; +} + +/* + * Specify which Merkle tree within the level (the "tree address") we're working on + */ +void set_tree_addr(uint32_t addr[8], uint64_t tree) { + ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); +} + +/* + * Specify the reason we'll use this address structure for, that is, what + * hash will we compute with it. This is used so that unrelated types of + * hashes don't accidentally get the same address structure. The type will be + * one of the SPX_ADDR_TYPE constants + */ +void set_type(uint32_t addr[8], uint32_t type) { + ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; +} + +/* + * Copy the layer and tree fields of the address structure. This is used + * when we're doing multiple types of hashes within the same Merkle tree + */ +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); +} + +/* These functions are used for OTS addresses. */ + +/* + * Specify which Merkle leaf we're working on; that is, which OTS keypair + * we're talking about. + */ +void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { + ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; +} + +/* + * Copy the layer, tree and keypair fields of the address structure. This is + * used when we're doing multiple things within the same OTS keypair + */ +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); + ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; +} + +/* + * Specify which Merkle chain within the OTS we're working with + * (the chain address) + */ +void set_chain_addr(uint32_t addr[8], uint32_t chain) { + ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; +} + +/* + * Specify where in the Merkle chain we are +* (the hash address) + */ +void set_hash_addr(uint32_t addr[8], uint32_t hash) { + ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; +} + +/* These functions are used for all hash tree addresses (including FORS). */ + +/* + * Specify the height of the node in the Merkle/FORS tree we are in + * (the tree height) + */ +void set_tree_height(uint32_t addr[8], uint32_t tree_height) { + ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; +} + +/* + * Specify the distance from the left edge of the node in the Merkle/FORS tree + * (the tree index) + */ +void set_tree_index(uint32_t addr[8], uint32_t tree_index) { + u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_clean/address.h b/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_clean/address.h new file mode 100644 index 0000000000..24a84eb40c --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_clean/address.h @@ -0,0 +1,52 @@ +#ifndef SPX_ADDRESS_H +#define SPX_ADDRESS_H + +#include + +#include "params.h" + +/* The hash types that are passed to set_type */ +#define SPX_ADDR_TYPE_WOTS 0 +#define SPX_ADDR_TYPE_WOTSPK 1 +#define SPX_ADDR_TYPE_HASHTREE 2 +#define SPX_ADDR_TYPE_FORSTREE 3 +#define SPX_ADDR_TYPE_FORSPK 4 +#define SPX_ADDR_TYPE_WOTSPRF 5 +#define SPX_ADDR_TYPE_FORSPRF 6 + +#define set_layer_addr SPX_NAMESPACE(set_layer_addr) +void set_layer_addr(uint32_t addr[8], uint32_t layer); + +#define set_tree_addr SPX_NAMESPACE(set_tree_addr) +void set_tree_addr(uint32_t addr[8], uint64_t tree); + +#define set_type SPX_NAMESPACE(set_type) +void set_type(uint32_t addr[8], uint32_t type); + +/* Copies the layer and tree part of one address into the other */ +#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); + +/* These functions are used for WOTS and FORS addresses. */ + +#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) +void set_keypair_addr(uint32_t addr[8], uint32_t keypair); + +#define set_chain_addr SPX_NAMESPACE(set_chain_addr) +void set_chain_addr(uint32_t addr[8], uint32_t chain); + +#define set_hash_addr SPX_NAMESPACE(set_hash_addr) +void set_hash_addr(uint32_t addr[8], uint32_t hash); + +#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); + +/* These functions are used for all hash tree addresses (including FORS). */ + +#define set_tree_height SPX_NAMESPACE(set_tree_height) +void set_tree_height(uint32_t addr[8], uint32_t tree_height); + +#define set_tree_index SPX_NAMESPACE(set_tree_index) +void set_tree_index(uint32_t addr[8], uint32_t tree_index); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_clean/api.h b/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_clean/api.h new file mode 100644 index 0000000000..56f58bf29a --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_clean/api.h @@ -0,0 +1,77 @@ +#ifndef PQCLEAN_SPHINCSSHA2256SSIMPLE_CLEAN_API_H +#define PQCLEAN_SPHINCSSHA2256SSIMPLE_CLEAN_API_H + +#include +#include + +#define PQCLEAN_SPHINCSSHA2256SSIMPLE_CLEAN_CRYPTO_ALGNAME "SPHINCS+-sha2-256s-simple" + +#define PQCLEAN_SPHINCSSHA2256SSIMPLE_CLEAN_CRYPTO_SECRETKEYBYTES 128 +#define PQCLEAN_SPHINCSSHA2256SSIMPLE_CLEAN_CRYPTO_PUBLICKEYBYTES 64 +#define PQCLEAN_SPHINCSSHA2256SSIMPLE_CLEAN_CRYPTO_BYTES 29792 + +#define PQCLEAN_SPHINCSSHA2256SSIMPLE_CLEAN_CRYPTO_SEEDBYTES 96 + +/* + * Returns the length of a secret key, in bytes + */ +size_t PQCLEAN_SPHINCSSHA2256SSIMPLE_CLEAN_crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +size_t PQCLEAN_SPHINCSSHA2256SSIMPLE_CLEAN_crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +size_t PQCLEAN_SPHINCSSHA2256SSIMPLE_CLEAN_crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +size_t PQCLEAN_SPHINCSSHA2256SSIMPLE_CLEAN_crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +int PQCLEAN_SPHINCSSHA2256SSIMPLE_CLEAN_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +int PQCLEAN_SPHINCSSHA2256SSIMPLE_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +int PQCLEAN_SPHINCSSHA2256SSIMPLE_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +int PQCLEAN_SPHINCSSHA2256SSIMPLE_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, + const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +int PQCLEAN_SPHINCSSHA2256SSIMPLE_CLEAN_crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +int PQCLEAN_SPHINCSSHA2256SSIMPLE_CLEAN_crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_clean/context.h b/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_clean/context.h new file mode 100644 index 0000000000..97e2e2469e --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_clean/context.h @@ -0,0 +1,28 @@ +#ifndef SPX_CONTEXT_H +#define SPX_CONTEXT_H + +#include +#include + +#include "params.h" +#include "sha2.h" + +typedef struct { + uint8_t pub_seed[SPX_N]; + uint8_t sk_seed[SPX_N]; + + // sha256 state that absorbed pub_seed + sha256ctx state_seeded; + + // sha512 state that absorbed pub_seed + sha512ctx state_seeded_512; + +} spx_ctx; + +#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) +void initialize_hash_function(spx_ctx *ctx); + +#define free_hash_function SPX_NAMESPACE(free_hash_function) +void free_hash_function(spx_ctx *ctx); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_clean/context_sha2.c b/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_clean/context_sha2.c new file mode 100644 index 0000000000..9ca9f4e7ac --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_clean/context_sha2.c @@ -0,0 +1,36 @@ +#include "context.h" + +/** + * Absorb the constant pub_seed using one round of the compression function + * This initializes state_seeded and state_seeded_512, which can then be + * reused in thash + **/ +static void seed_state(spx_ctx *ctx) { + uint8_t block[SPX_SHA512_BLOCK_BYTES]; + size_t i; + + for (i = 0; i < SPX_N; ++i) { + block[i] = ctx->pub_seed[i]; + } + for (i = SPX_N; i < SPX_SHA512_BLOCK_BYTES; ++i) { + block[i] = 0; + } + /* block has been properly initialized for both SHA-256 and SHA-512 */ + + sha256_inc_init(&ctx->state_seeded); + sha256_inc_blocks(&ctx->state_seeded, block, 1); + sha512_inc_init(&ctx->state_seeded_512); + sha512_inc_blocks(&ctx->state_seeded_512, block, 1); +} + + +/* We initialize the state for the hash functions */ +void initialize_hash_function(spx_ctx *ctx) { + seed_state(ctx); +} + +/* Free the incremental hashing context for heap-based SHA2 APIs */ +void free_hash_function(spx_ctx *ctx) { + sha256_inc_ctx_release(&ctx->state_seeded); + sha512_inc_ctx_release(&ctx->state_seeded_512); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_clean/fors.c b/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_clean/fors.c new file mode 100644 index 0000000000..96ca72e986 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_clean/fors.c @@ -0,0 +1,156 @@ +#include +#include +#include + +#include "fors.h" + +#include "address.h" +#include "hash.h" +#include "thash.h" +#include "utils.h" +#include "utilsx1.h" + +static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + prf_addr(sk, ctx, fors_leaf_addr); +} + +static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, + const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + thash(leaf, sk, 1, ctx, fors_leaf_addr); +} + +struct fors_gen_leaf_info { + uint32_t leaf_addrx[8]; +}; + +static void fors_gen_leafx1(unsigned char *leaf, + const spx_ctx *ctx, + uint32_t addr_idx, void *info) { + struct fors_gen_leaf_info *fors_info = info; + uint32_t *fors_leaf_addr = fors_info->leaf_addrx; + + /* Only set the parts that the caller doesn't set */ + set_tree_index(fors_leaf_addr, addr_idx); + set_type(fors_leaf_addr, SPX_ADDR_TYPE_FORSPRF); + fors_gen_sk(leaf, ctx, fors_leaf_addr); + + set_type(fors_leaf_addr, SPX_ADDR_TYPE_FORSTREE); + fors_sk_to_leaf(leaf, leaf, + ctx, fors_leaf_addr); +} + +/** + * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + * Assumes indices has space for SPX_FORS_TREES integers. + */ +static void message_to_indices(uint32_t *indices, const unsigned char *m) { + unsigned int i, j; + unsigned int offset = 0; + + for (i = 0; i < SPX_FORS_TREES; i++) { + indices[i] = 0; + for (j = 0; j < SPX_FORS_HEIGHT; j++) { + indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); + offset++; + } + } +} + +/** + * Signs a message m, deriving the secret key from sk_seed and the FTS address. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + uint32_t fors_tree_addr[8] = {0}; + struct fors_gen_leaf_info fors_info = {0}; + uint32_t *fors_leaf_addr = fors_info.leaf_addrx; + uint32_t fors_pk_addr[8] = {0}; + uint32_t idx_offset; + unsigned int i; + + copy_keypair_addr(fors_tree_addr, fors_addr); + copy_keypair_addr(fors_leaf_addr, fors_addr); + + copy_keypair_addr(fors_pk_addr, fors_addr); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); + + message_to_indices(indices, m); + + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); + + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); + + /* Include the secret key part that produces the selected leaf node. */ + fors_gen_sk(sig, ctx, fors_tree_addr); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + sig += SPX_N; + + /* Compute the authentication path for this leaf node. */ + treehashx1(roots + i * SPX_N, sig, ctx, + indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx1, + fors_tree_addr, &fors_info); + + sig += SPX_N * SPX_FORS_HEIGHT; + } + + /* Hash horizontally across all tree roots to derive the public key. */ + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); +} + +/** + * Derives the FORS public key from a signature. + * This can be used for verification by comparing to a known public key, or to + * subsequently verify a signature on the derived public key. The latter is the + * typical use-case when used as an FTS below an OTS in a hypertree. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + unsigned char leaf[SPX_N]; + uint32_t fors_tree_addr[8] = {0}; + uint32_t fors_pk_addr[8] = {0}; + uint32_t idx_offset; + unsigned int i; + + copy_keypair_addr(fors_tree_addr, fors_addr); + copy_keypair_addr(fors_pk_addr, fors_addr); + + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); + + message_to_indices(indices, m); + + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); + + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + + /* Derive the leaf from the included secret key part. */ + fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); + sig += SPX_N; + + /* Derive the corresponding root node of this tree. */ + compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, + sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); + sig += SPX_N * SPX_FORS_HEIGHT; + } + + /* Hash horizontally across all tree roots to derive the public key. */ + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_clean/fors.h b/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_clean/fors.h new file mode 100644 index 0000000000..509140a178 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_clean/fors.h @@ -0,0 +1,32 @@ +#ifndef SPX_FORS_H +#define SPX_FORS_H + +#include + +#include "context.h" +#include "params.h" + +/** + * Signs a message m, deriving the secret key from sk_seed and the FTS address. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +#define fors_sign SPX_NAMESPACE(fors_sign) +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); + +/** + * Derives the FORS public key from a signature. + * This can be used for verification by comparing to a known public key, or to + * subsequently verify a signature on the derived public key. The latter is the + * typical use-case when used as an FTS below an OTS in a hypertree. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_clean/hash.h b/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_clean/hash.h new file mode 100644 index 0000000000..ffe815f45d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_clean/hash.h @@ -0,0 +1,37 @@ +#ifndef SPX_HASH_H +#define SPX_HASH_H + +#include +#include + +#include "context.h" +#include "params.h" + +#define prf_addr SPX_NAMESPACE(prf_addr) +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]); + +#define gen_message_random SPX_NAMESPACE(gen_message_random) +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); + +#define hash_message SPX_NAMESPACE(hash_message) +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); + + +# define SPX_SHA256_ADDR_BYTES 22 + +# define mgf1_256 SPX_NAMESPACE(mgf1_256) +void mgf1_256(unsigned char *out, unsigned long outlen, + const unsigned char *in, unsigned long inlen); + +# define mgf1_512 SPX_NAMESPACE(mgf1_512) +void mgf1_512(unsigned char *out, unsigned long outlen, + const unsigned char *in, unsigned long inlen); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_clean/hash_sha2.c b/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_clean/hash_sha2.c new file mode 100644 index 0000000000..3d0085c8c1 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_clean/hash_sha2.c @@ -0,0 +1,219 @@ +#include +#include + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "sha2.h" +#include "utils.h" + + + +#define SPX_SHAX_OUTPUT_BYTES SPX_SHA512_OUTPUT_BYTES +#define SPX_SHAX_BLOCK_BYTES SPX_SHA512_BLOCK_BYTES +#define shaX_inc_init sha512_inc_init +#define shaX_inc_blocks sha512_inc_blocks +#define shaX_inc_finalize sha512_inc_finalize +#define shaX sha512 +#define mgf1_X mgf1_512 +#define shaXstate sha512ctx + +/** + * mgf1 function based on the SHA-256 hash function + * Note that inlen should be sufficiently small that it still allows for + * an array to be allocated on the stack. Typically 'in' is merely a seed. + * Outputs outlen number of bytes + */ +void mgf1_256(unsigned char *out, unsigned long outlen, + const unsigned char *in, unsigned long inlen) { + PQCLEAN_VLA(uint8_t, inbuf, inlen + 4); + unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES]; + uint32_t i; + + memcpy(inbuf, in, inlen); + + /* While we can fit in at least another full block of SHA256 output.. */ + for (i = 0; (i + 1)*SPX_SHA256_OUTPUT_BYTES <= outlen; i++) { + u32_to_bytes(inbuf + inlen, i); + sha256(out, inbuf, inlen + 4); + out += SPX_SHA256_OUTPUT_BYTES; + } + /* Until we cannot anymore, and we fill the remainder. */ + if (outlen > i * SPX_SHA256_OUTPUT_BYTES) { + u32_to_bytes(inbuf + inlen, i); + sha256(outbuf, inbuf, inlen + 4); + memcpy(out, outbuf, outlen - i * SPX_SHA256_OUTPUT_BYTES); + } +} + +/* + * mgf1 function based on the SHA-512 hash function + */ +void mgf1_512(unsigned char *out, unsigned long outlen, + const unsigned char *in, unsigned long inlen) { + PQCLEAN_VLA(uint8_t, inbuf, inlen + 4); + unsigned char outbuf[SPX_SHA512_OUTPUT_BYTES]; + uint32_t i; + + memcpy(inbuf, in, inlen); + + /* While we can fit in at least another full block of SHA512 output.. */ + for (i = 0; (i + 1)*SPX_SHA512_OUTPUT_BYTES <= outlen; i++) { + u32_to_bytes(inbuf + inlen, i); + sha512(out, inbuf, inlen + 4); + out += SPX_SHA512_OUTPUT_BYTES; + } + /* Until we cannot anymore, and we fill the remainder. */ + if (outlen > i * SPX_SHA512_OUTPUT_BYTES) { + u32_to_bytes(inbuf + inlen, i); + sha512(outbuf, inbuf, inlen + 4); + memcpy(out, outbuf, outlen - i * SPX_SHA512_OUTPUT_BYTES); + } +} + +/* + * Computes PRF(pk_seed, sk_seed, addr). + */ +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]) { + sha256ctx sha2_state; + unsigned char buf[SPX_SHA256_ADDR_BYTES + SPX_N]; + unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES]; + + /* Retrieve precomputed state containing pub_seed */ + sha256_inc_ctx_clone(&sha2_state, &ctx->state_seeded); + + /* Remainder: ADDR^c ‖ SK.seed */ + memcpy(buf, addr, SPX_SHA256_ADDR_BYTES); + memcpy(buf + SPX_SHA256_ADDR_BYTES, ctx->sk_seed, SPX_N); + + sha256_inc_finalize(outbuf, &sha2_state, buf, SPX_SHA256_ADDR_BYTES + SPX_N); + + memcpy(out, outbuf, SPX_N); +} + +/** + * Computes the message-dependent randomness R, using a secret seed as a key + * for HMAC, and an optional randomization value prefixed to the message. + * This requires m to have at least SPX_SHAX_BLOCK_BYTES + SPX_N space + * available in front of the pointer, i.e. before the message to use for the + * prefix. This is necessary to prevent having to move the message around (and + * allocate memory for it). + */ +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { + (void)ctx; + + unsigned char buf[SPX_SHAX_BLOCK_BYTES + SPX_SHAX_OUTPUT_BYTES]; + shaXstate state; + int i; + + + /* This implements HMAC-SHA */ + for (i = 0; i < SPX_N; i++) { + buf[i] = 0x36 ^ sk_prf[i]; + } + memset(buf + SPX_N, 0x36, SPX_SHAX_BLOCK_BYTES - SPX_N); + + shaX_inc_init(&state); + shaX_inc_blocks(&state, buf, 1); + + memcpy(buf, optrand, SPX_N); + + /* If optrand + message cannot fill up an entire block */ + if (SPX_N + mlen < SPX_SHAX_BLOCK_BYTES) { + memcpy(buf + SPX_N, m, mlen); + shaX_inc_finalize(buf + SPX_SHAX_BLOCK_BYTES, &state, + buf, mlen + SPX_N); + } + /* Otherwise first fill a block, so that finalize only uses the message */ + else { + memcpy(buf + SPX_N, m, SPX_SHAX_BLOCK_BYTES - SPX_N); + shaX_inc_blocks(&state, buf, 1); + + m += SPX_SHAX_BLOCK_BYTES - SPX_N; + mlen -= SPX_SHAX_BLOCK_BYTES - SPX_N; + shaX_inc_finalize(buf + SPX_SHAX_BLOCK_BYTES, &state, m, mlen); + } + + for (i = 0; i < SPX_N; i++) { + buf[i] = 0x5c ^ sk_prf[i]; + } + memset(buf + SPX_N, 0x5c, SPX_SHAX_BLOCK_BYTES - SPX_N); + + shaX(buf, buf, SPX_SHAX_BLOCK_BYTES + SPX_SHAX_OUTPUT_BYTES); + memcpy(R, buf, SPX_N); +} + +/** + * Computes the message hash using R, the public key, and the message. + * Outputs the message digest and the index of the leaf. The index is split in + * the tree index and the leaf index, for convenient copying to an address. + */ +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { + (void)ctx; +#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) +#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) +#define SPX_LEAF_BITS SPX_TREE_HEIGHT +#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) +#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) + + unsigned char seed[2 * SPX_N + SPX_SHAX_OUTPUT_BYTES]; + + /* Round to nearest multiple of SPX_SHAX_BLOCK_BYTES */ +#define SPX_INBLOCKS (((SPX_N + SPX_PK_BYTES + SPX_SHAX_BLOCK_BYTES - 1) & \ + -SPX_SHAX_BLOCK_BYTES) / SPX_SHAX_BLOCK_BYTES) + unsigned char inbuf[SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES]; + + unsigned char buf[SPX_DGST_BYTES]; + unsigned char *bufp = buf; + shaXstate state; + + shaX_inc_init(&state); + + // seed: SHA-X(R ‖ PK.seed ‖ PK.root ‖ M) + memcpy(inbuf, R, SPX_N); + memcpy(inbuf + SPX_N, pk, SPX_PK_BYTES); + + /* If R + pk + message cannot fill up an entire block */ + if (SPX_N + SPX_PK_BYTES + mlen < SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES) { + memcpy(inbuf + SPX_N + SPX_PK_BYTES, m, mlen); + shaX_inc_finalize(seed + 2 * SPX_N, &state, inbuf, SPX_N + SPX_PK_BYTES + mlen); + } + /* Otherwise first fill a block, so that finalize only uses the message */ + else { + memcpy(inbuf + SPX_N + SPX_PK_BYTES, m, + SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES - SPX_N - SPX_PK_BYTES); + shaX_inc_blocks(&state, inbuf, SPX_INBLOCKS); + + m += SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES - SPX_N - SPX_PK_BYTES; + mlen -= SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES - SPX_N - SPX_PK_BYTES; + shaX_inc_finalize(seed + 2 * SPX_N, &state, m, (size_t)mlen); + } + + // H_msg: MGF1-SHA-X(R ‖ PK.seed ‖ seed) + memcpy(seed, R, SPX_N); + memcpy(seed + SPX_N, pk, SPX_N); + + /* By doing this in two steps, we prevent hashing the message twice; + otherwise each iteration in MGF1 would hash the message again. */ + mgf1_X(bufp, SPX_DGST_BYTES, seed, 2 * SPX_N + SPX_SHAX_OUTPUT_BYTES); + + memcpy(digest, bufp, SPX_FORS_MSG_BYTES); + bufp += SPX_FORS_MSG_BYTES; + + + *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); + *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); + bufp += SPX_TREE_BYTES; + + *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); + *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); +} + + diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_clean/merkle.c b/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_clean/merkle.c new file mode 100644 index 0000000000..0c1479fd93 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_clean/merkle.c @@ -0,0 +1,59 @@ +#include +#include + +#include "address.h" +#include "merkle.h" +#include "params.h" +#include "utils.h" +#include "utilsx1.h" +#include "wots.h" +#include "wotsx1.h" + +/* + * This generates a Merkle signature (WOTS signature followed by the Merkle + * authentication path). This is in this file because most of the complexity + * is involved with the WOTS signature; the Merkle authentication path logic + * is mostly hidden in treehashx4 + */ +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf) { + unsigned char *auth_path = sig + SPX_WOTS_BYTES; + struct leaf_info_x1 info = { 0 }; + unsigned steps[ SPX_WOTS_LEN ]; + + info.wots_sig = sig; + chain_lengths(steps, root); + info.wots_steps = steps; + + set_type(&tree_addr[0], SPX_ADDR_TYPE_HASHTREE); + set_type(&info.pk_addr[0], SPX_ADDR_TYPE_WOTSPK); + copy_subtree_addr(&info.leaf_addr[0], wots_addr); + copy_subtree_addr(&info.pk_addr[0], wots_addr); + + info.wots_sign_leaf = idx_leaf; + + treehashx1(root, auth_path, ctx, + idx_leaf, 0, + SPX_TREE_HEIGHT, + wots_gen_leafx1, + tree_addr, &info); +} + +/* Compute root node of the top-most subtree. */ +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { + /* We do not need the auth path in key generation, but it simplifies the + code to have just one treehash routine that computes both root and path + in one function. */ + unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; + uint32_t top_tree_addr[8] = {0}; + uint32_t wots_addr[8] = {0}; + + set_layer_addr(top_tree_addr, SPX_D - 1); + set_layer_addr(wots_addr, SPX_D - 1); + + merkle_sign(auth_path, root, ctx, + wots_addr, top_tree_addr, + (uint32_t)~0 /* ~0 means "don't bother generating an auth path */ ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_clean/merkle.h b/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_clean/merkle.h new file mode 100644 index 0000000000..769cf2e970 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_clean/merkle.h @@ -0,0 +1,21 @@ +#ifndef MERKLE_H_ +#define MERKLE_H_ + +#include + +#include "context.h" +#include "params.h" + +/* Generate a Merkle signature (WOTS signature followed by the Merkle */ +/* authentication path) */ +#define merkle_sign SPX_NAMESPACE(merkle_sign) +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf); + +/* Compute the root node of the top-most subtree. */ +#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); + +#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_clean/nistapi.h b/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_clean/nistapi.h new file mode 100644 index 0000000000..3cb71afad4 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_clean/nistapi.h @@ -0,0 +1,87 @@ +#ifndef SPX_API_H +#define SPX_API_H + +#include +#include + +#include "params.h" + +#define CRYPTO_ALGNAME "SPHINCS+" + +#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES +#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES +#define CRYPTO_BYTES SPX_BYTES +#define CRYPTO_SEEDBYTES (3*SPX_N) + +/* + * Returns the length of a secret key, in bytes + */ +#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) +size_t crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) +size_t crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) +size_t crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) +size_t crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +#define crypto_sign SPX_NAMESPACE(crypto_sign) +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_clean/params.h b/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_clean/params.h new file mode 100644 index 0000000000..6ebcdac445 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_clean/params.h @@ -0,0 +1,61 @@ +#ifndef SPX_PARAMS_H +#define SPX_PARAMS_H + +#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSSHA2256SSIMPLE_CLEAN_##s + +/* Hash output length in bytes. */ +#define SPX_N 32 +/* Height of the hypertree. */ +#define SPX_FULL_HEIGHT 64 +/* Number of subtree layer. */ +#define SPX_D 8 +/* FORS tree dimensions. */ +#define SPX_FORS_HEIGHT 14 +#define SPX_FORS_TREES 22 +/* Winternitz parameter, */ +#define SPX_WOTS_W 16 + +/* The hash function is defined by linking a different hash.c file, as opposed + to setting a #define constant. */ + +/* This is a SHA2-based parameter set, hence whether we use SHA-256 + * exclusively or we use both SHA-256 and SHA-512 is controlled by + * the following #define */ +#define SPX_SHA512 1 /* Use SHA-512 for H and T_l, l >= 2 */ + +/* For clarity */ +#define SPX_ADDR_BYTES 32 + +/* WOTS parameters. */ +#define SPX_WOTS_LOGW 4 + +#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) + +/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ +#define SPX_WOTS_LEN2 3 + +#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) +#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) +#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES + +/* Subtree size. */ +#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) + +//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT +// #error SPX_D should always divide SPX_FULL_HEIGHT +//#endif + +/* FORS parameters. */ +#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) +#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) +#define SPX_FORS_PK_BYTES SPX_N + +/* Resulting SPX sizes. */ +#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ + SPX_FULL_HEIGHT * SPX_N) +#define SPX_PK_BYTES (2 * SPX_N) +#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) + +#include "sha2_offsets.h" + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_clean/sha2_offsets.h b/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_clean/sha2_offsets.h new file mode 100644 index 0000000000..6e3584f7a4 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_clean/sha2_offsets.h @@ -0,0 +1,27 @@ +#ifndef SHA2_OFFSETS_H_ +#define SHA2_OFFSETS_H_ + +#define SPX_SHA256_BLOCK_BYTES 64 +#define SPX_SHA256_OUTPUT_BYTES 32 + +#define SPX_SHA512_BLOCK_BYTES 128 +#define SPX_SHA512_OUTPUT_BYTES 64 + +/* + * Offsets of various fields in the address structure when we use SHA2 as + * the Sphincs+ hash function + */ + +#define SPX_OFFSET_LAYER 0 /* The byte used to specify the Merkle tree layer */ +#define SPX_OFFSET_TREE 1 /* The start of the 8 byte field used to specify the tree */ +#define SPX_OFFSET_TYPE 9 /* The byte used to specify the hash type (reason) */ +#define SPX_OFFSET_KP_ADDR2 12 /* The high byte used to specify the key pair (which one-time signature) */ +#define SPX_OFFSET_KP_ADDR1 13 /* The low byte used to specify the key pair */ +#define SPX_OFFSET_CHAIN_ADDR 17 /* The byte used to specify the chain address (which Winternitz chain) */ +#define SPX_OFFSET_HASH_ADDR 21 /* The byte used to specify the hash address (where in the Winternitz chain) */ +#define SPX_OFFSET_TREE_HGT 17 /* The byte used to specify the height of this node in the FORS or Merkle tree */ +#define SPX_OFFSET_TREE_INDEX 18 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ + +#define SPX_SHA2 1 + +#endif /* SHA2_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_clean/sign.c b/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_clean/sign.c new file mode 100644 index 0000000000..9d0c7d1b22 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_clean/sign.c @@ -0,0 +1,286 @@ +#include +#include +#include + +#include "address.h" +#include "context.h" +#include "fors.h" +#include "hash.h" +#include "merkle.h" +#include "nistapi.h" +#include "params.h" +#include "randombytes.h" +#include "thash.h" +#include "utils.h" +#include "wots.h" + +/* + * Returns the length of a secret key, in bytes + */ +size_t crypto_sign_secretkeybytes(void) { + return CRYPTO_SECRETKEYBYTES; +} + +/* + * Returns the length of a public key, in bytes + */ +size_t crypto_sign_publickeybytes(void) { + return CRYPTO_PUBLICKEYBYTES; +} + +/* + * Returns the length of a signature, in bytes + */ +size_t crypto_sign_bytes(void) { + return CRYPTO_BYTES; +} + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +size_t crypto_sign_seedbytes(void) { + return CRYPTO_SEEDBYTES; +} + +/* + * Generates an SPX key pair given a seed of length + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [PUB_SEED || root] + */ +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed) { + spx_ctx ctx; + + /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ + memcpy(sk, seed, CRYPTO_SEEDBYTES); + + memcpy(pk, sk + 2 * SPX_N, SPX_N); + + memcpy(ctx.pub_seed, pk, SPX_N); + memcpy(ctx.sk_seed, sk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + /* Compute root node of the top-most subtree. */ + merkle_gen_root(sk + 3 * SPX_N, &ctx); + + // cleanup + free_hash_function(&ctx); + + memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); + + return 0; +} + +/* + * Generates an SPX key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [PUB_SEED || root] + */ +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { + uint8_t seed[CRYPTO_SEEDBYTES]; + randombytes(seed, CRYPTO_SEEDBYTES); + crypto_sign_seed_keypair(pk, sk, seed); + + return 0; +} + +/** + * Returns an array containing a detached signature. + */ +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk) { + spx_ctx ctx; + + const uint8_t *sk_prf = sk + SPX_N; + const uint8_t *pk = sk + 2 * SPX_N; + + uint8_t optrand[SPX_N]; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t root[SPX_N]; + uint32_t i; + uint64_t tree; + uint32_t idx_leaf; + uint32_t wots_addr[8] = {0}; + uint32_t tree_addr[8] = {0}; + + memcpy(ctx.sk_seed, sk, SPX_N); + memcpy(ctx.pub_seed, pk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + + /* Optionally, signing can be made non-deterministic using optrand. + This can help counter side-channel attacks that would benefit from + getting a large number of traces when the signer uses the same nodes. */ + randombytes(optrand, SPX_N); + /* Compute the digest randomization value. */ + gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); + + /* Derive the message digest and leaf index from R, PK and M. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; + + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); + + /* Sign the message hash using FORS. */ + fors_sign(sig, root, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); + sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; + + /* Update the indices for the next layer. */ + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; + } + + free_hash_function(&ctx); + + *siglen = SPX_BYTES; + + return 0; +} + +/** + * Verifies a detached signature and message under a given public key. + */ +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk) { + spx_ctx ctx; + const uint8_t *pub_root = pk + SPX_N; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t wots_pk[SPX_WOTS_BYTES]; + uint8_t root[SPX_N]; + uint8_t leaf[SPX_N]; + unsigned int i; + uint64_t tree; + uint32_t idx_leaf; + uint32_t wots_addr[8] = {0}; + uint32_t tree_addr[8] = {0}; + uint32_t wots_pk_addr[8] = {0}; + + if (siglen != SPX_BYTES) { + return -1; + } + + memcpy(ctx.pub_seed, pk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); + + /* Derive the message digest and leaf index from R || PK || M. */ + /* The additional SPX_N is a result of the hash domain separator. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; + + /* Layer correctly defaults to 0, so no need to set_layer_addr */ + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); + + fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + /* For each subtree.. */ + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + copy_keypair_addr(wots_pk_addr, wots_addr); + + /* The WOTS public key is only correct if the signature was correct. */ + /* Initially, root is the FORS pk, but on subsequent iterations it is + the root of the subtree below the currently processed subtree. */ + wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); + sig += SPX_WOTS_BYTES; + + /* Compute the leaf node using the WOTS public key. */ + thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); + + /* Compute the root node of this subtree. */ + compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, + &ctx, tree_addr); + sig += SPX_TREE_HEIGHT * SPX_N; + + /* Update the indices for the next layer. */ + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; + } + + // cleanup + free_hash_function(&ctx); + + /* Check if the root node equals the root node in the public key. */ + if (memcmp(root, pub_root, SPX_N) != 0) { + return -1; + } + + return 0; +} + + +/** + * Returns an array containing the signature followed by the message. + */ +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk) { + size_t siglen; + + crypto_sign_signature(sm, &siglen, m, mlen, sk); + + memmove(sm + SPX_BYTES, m, mlen); + *smlen = siglen + mlen; + + return 0; +} + +/** + * Verifies a given signature-message pair under a given public key. + */ +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk) { + /* The API caller does not necessarily know what size a signature should be + but SPHINCS+ signatures are always exactly SPX_BYTES. */ + if (smlen < SPX_BYTES) { + memset(m, 0, smlen); + *mlen = 0; + return -1; + } + + *mlen = smlen - SPX_BYTES; + + if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { + memset(m, 0, smlen); + *mlen = 0; + return -1; + } + + /* If verification was successful, move the message to the right place. */ + memmove(m, sm + SPX_BYTES, *mlen); + + return 0; +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_clean/thash.h b/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_clean/thash.h new file mode 100644 index 0000000000..8687ccfb4d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_clean/thash.h @@ -0,0 +1,13 @@ +#ifndef SPX_THASH_H +#define SPX_THASH_H + +#include "context.h" +#include "params.h" + +#include + +#define thash SPX_NAMESPACE(thash) +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_clean/thash_sha2_simple.c b/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_clean/thash_sha2_simple.c new file mode 100644 index 0000000000..87badc4d53 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_clean/thash_sha2_simple.c @@ -0,0 +1,53 @@ +#include +#include + +#include "thash.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "sha2.h" +#include "utils.h" + +static void thash_512(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]); + +/** + * Takes an array of inblocks concatenated arrays of SPX_N bytes. + */ +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]) { + if (inblocks > 1) { + thash_512(out, in, inblocks, ctx, addr); + return; + } + + unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES]; + sha256ctx sha2_state; + PQCLEAN_VLA(uint8_t, buf, SPX_SHA256_ADDR_BYTES + inblocks * SPX_N); + + /* Retrieve precomputed state containing pub_seed */ + sha256_inc_ctx_clone(&sha2_state, &ctx->state_seeded); + + memcpy(buf, addr, SPX_SHA256_ADDR_BYTES); + memcpy(buf + SPX_SHA256_ADDR_BYTES, in, inblocks * SPX_N); + + sha256_inc_finalize(outbuf, &sha2_state, buf, SPX_SHA256_ADDR_BYTES + inblocks * SPX_N); + memcpy(out, outbuf, SPX_N); +} + +static void thash_512(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]) { + unsigned char outbuf[SPX_SHA512_OUTPUT_BYTES]; + sha512ctx sha2_state; + PQCLEAN_VLA(uint8_t, buf, SPX_SHA256_ADDR_BYTES + inblocks * SPX_N); + + /* Retrieve precomputed state containing pub_seed */ + sha512_inc_ctx_clone(&sha2_state, &ctx->state_seeded_512); + + memcpy(buf, addr, SPX_SHA256_ADDR_BYTES); + memcpy(buf + SPX_SHA256_ADDR_BYTES, in, inblocks * SPX_N); + + sha512_inc_finalize(outbuf, &sha2_state, buf, SPX_SHA256_ADDR_BYTES + inblocks * SPX_N); + memcpy(out, outbuf, SPX_N); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_clean/utils.c b/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_clean/utils.c new file mode 100644 index 0000000000..177b541fb9 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_clean/utils.c @@ -0,0 +1,148 @@ +#include + +#include "utils.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "thash.h" + +/** + * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. + */ +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in) { + int i; + + /* Iterate over out in decreasing order, for big-endianness. */ + for (i = (signed int)outlen - 1; i >= 0; i--) { + out[i] = in & 0xff; + in = in >> 8; + } +} + +void u32_to_bytes(unsigned char *out, uint32_t in) { + out[0] = (unsigned char)(in >> 24); + out[1] = (unsigned char)(in >> 16); + out[2] = (unsigned char)(in >> 8); + out[3] = (unsigned char)in; +} + +/** + * Converts the inlen bytes in 'in' from big-endian byte order to an integer. + */ +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { + unsigned long long retval = 0; + unsigned int i; + + for (i = 0; i < inlen; i++) { + retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); + } + return retval; +} + +/** + * Computes a root node given a leaf and an auth path. + * Expects address to be complete other than the tree_height and tree_index. + */ +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]) { + uint32_t i; + unsigned char buffer[2 * SPX_N]; + + /* If leaf_idx is odd (last bit = 1), current path element is a right child + and auth_path has to go left. Otherwise it is the other way around. */ + if (leaf_idx & 1) { + memcpy(buffer + SPX_N, leaf, SPX_N); + memcpy(buffer, auth_path, SPX_N); + } else { + memcpy(buffer, leaf, SPX_N); + memcpy(buffer + SPX_N, auth_path, SPX_N); + } + auth_path += SPX_N; + + for (i = 0; i < tree_height - 1; i++) { + leaf_idx >>= 1; + idx_offset >>= 1; + /* Set the address of the node we're creating. */ + set_tree_height(addr, i + 1); + set_tree_index(addr, leaf_idx + idx_offset); + + /* Pick the right or left neighbor, depending on parity of the node. */ + if (leaf_idx & 1) { + thash(buffer + SPX_N, buffer, 2, ctx, addr); + memcpy(buffer, auth_path, SPX_N); + } else { + thash(buffer, buffer, 2, ctx, addr); + memcpy(buffer + SPX_N, auth_path, SPX_N); + } + auth_path += SPX_N; + } + + /* The last iteration is exceptional; we do not copy an auth_path node. */ + leaf_idx >>= 1; + idx_offset >>= 1; + set_tree_height(addr, tree_height); + set_tree_index(addr, leaf_idx + idx_offset); + thash(root, buffer, 2, ctx, addr); +} + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx * /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]) { + PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); + PQCLEAN_VLA(unsigned int, heights, tree_height + 1); + unsigned int offset = 0; + uint32_t idx; + uint32_t tree_idx; + + for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { + /* Add the next leaf node to the stack. */ + gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); + offset++; + heights[offset - 1] = 0; + + /* If this is a node we need for the auth path.. */ + if ((leaf_idx ^ 0x1) == idx) { + memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); + } + + /* While the top-most nodes are of equal height.. */ + while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { + /* Compute index of the new node, in the next layer. */ + tree_idx = (idx >> (heights[offset - 1] + 1)); + + /* Set the address of the node we're creating. */ + set_tree_height(tree_addr, heights[offset - 1] + 1); + set_tree_index(tree_addr, + tree_idx + (idx_offset >> (heights[offset - 1] + 1))); + /* Hash the top-most nodes from the stack together. */ + thash(stack + (offset - 2)*SPX_N, + stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); + offset--; + /* Note that the top-most node is now one layer higher. */ + heights[offset - 1]++; + + /* If this is a node we need for the auth path.. */ + if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { + memcpy(auth_path + heights[offset - 1]*SPX_N, + stack + (offset - 1)*SPX_N, SPX_N); + } + } + } + memcpy(root, stack, SPX_N); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_clean/utils.h b/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_clean/utils.h new file mode 100644 index 0000000000..64f5d5a53a --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_clean/utils.h @@ -0,0 +1,58 @@ +#ifndef SPX_UTILS_H +#define SPX_UTILS_H + +#include + +#include "compat.h" +#include "context.h" +#include "params.h" + + +/* To support MSVC use alloca() instead of VLAs. See #20. */ + + +/** + * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. + */ +#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in); +#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) +void u32_to_bytes(unsigned char *out, uint32_t in); + +/** + * Converts the inlen bytes in 'in' from big-endian byte order to an integer. + */ +#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); + +/** + * Computes a root node given a leaf and an auth path. + * Expects address to be complete other than the tree_height and tree_index. + */ +#define compute_root SPX_NAMESPACE(compute_root) +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]); + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +#define treehash SPX_NAMESPACE(treehash) +void treehash(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx *ctx /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]); + + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_clean/utilsx1.c b/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_clean/utilsx1.c new file mode 100644 index 0000000000..fccb69b35d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_clean/utilsx1.c @@ -0,0 +1,100 @@ +#include + +#include "utilsx1.h" + +#include "address.h" +#include "params.h" +#include "thash.h" +#include "utils.h" + +/* + * Generate the entire Merkle tree, computing the authentication path for + * leaf_idx, and the resulting root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) + * + * This expects tree_addr to be initialized to the addr structures for the + * Merkle tree nodes + * + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + * + * This works by using the standard Merkle tree building algorithm, + */ +void treehashx1(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, + uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* Where to write the leaves */, + const spx_ctx * /* ctx */, + uint32_t idx, void *info), + uint32_t tree_addr[8], + void *info) { + /* This is where we keep the intermediate nodes */ + PQCLEAN_VLA(uint8_t, stack, tree_height * SPX_N); + + uint32_t idx; + uint32_t max_idx = (uint32_t)((1 << tree_height) - 1); + for (idx = 0;; idx++) { + unsigned char current[2 * SPX_N]; /* Current logical node is at */ + /* index[SPX_N]. We do this to minimize the number of copies */ + /* needed during a thash */ + gen_leaf( ¤t[SPX_N], ctx, idx + idx_offset, + info ); + + /* Now combine the freshly generated right node with previously */ + /* generated left ones */ + uint32_t internal_idx_offset = idx_offset; + uint32_t internal_idx = idx; + uint32_t internal_leaf = leaf_idx; + uint32_t h; /* The height we are in the Merkle tree */ + for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { + + /* Check if we hit the top of the tree */ + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[SPX_N], SPX_N ); + return; + } + + /* + * Check if the node we have is a part of the + * authentication path; if it is, write it out + */ + if ((internal_idx ^ internal_leaf) == 0x01) { + memcpy( &auth_path[ h * SPX_N ], + ¤t[SPX_N], + SPX_N ); + } + + /* + * Check if we're at a left child; if so, stop going up the stack + * Exception: if we've reached the end of the tree, keep on going + * (so we combine the last 4 nodes into the one root node in two + * more iterations) + */ + if ((internal_idx & 1) == 0 && idx < max_idx) { + break; + } + + /* Ok, we're at a right node */ + /* Now combine the left and right logical nodes together */ + + /* Set the address of the node we're creating. */ + internal_idx_offset >>= 1; + set_tree_height(tree_addr, h + 1); + set_tree_index(tree_addr, internal_idx / 2 + internal_idx_offset ); + + unsigned char *left = &stack[h * SPX_N]; + memcpy( ¤t[0], left, SPX_N ); + thash( ¤t[1 * SPX_N], + ¤t[0 * SPX_N], + 2, ctx, tree_addr); + } + + /* We've hit a left child; save the current for when we get the */ + /* corresponding right right */ + memcpy( &stack[h * SPX_N], ¤t[SPX_N], SPX_N); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_clean/utilsx1.h b/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_clean/utilsx1.h new file mode 100644 index 0000000000..e911d17d53 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_clean/utilsx1.h @@ -0,0 +1,27 @@ +#ifndef SPX_UTILSX4_H +#define SPX_UTILSX4_H + +#include + +#include "context.h" +#include "params.h" + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +#define treehashx1 SPX_NAMESPACE(treehashx1) +void treehashx1(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* Where to write the leaf */, + const spx_ctx * /* ctx */, + uint32_t addr_idx, void *info), + uint32_t tree_addrx4[8], void *info); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_clean/wots.c b/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_clean/wots.c new file mode 100644 index 0000000000..249717aaa8 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_clean/wots.c @@ -0,0 +1,108 @@ +#include +#include + +#include "wots.h" +#include "wotsx1.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "thash.h" +#include "utils.h" +#include "utilsx1.h" + +// TODO clarify address expectations, and make them more uniform. +// TODO i.e. do we expect types to be set already? +// TODO and do we expect modifications or copies? + +/** + * Computes the chaining function. + * out and in have to be n-byte arrays. + * + * Interprets in as start-th value of the chain. + * addr has to contain the address of the chain. + */ +static void gen_chain(unsigned char *out, const unsigned char *in, + unsigned int start, unsigned int steps, + const spx_ctx *ctx, uint32_t addr[8]) { + uint32_t i; + + /* Initialize out with the value at position 'start'. */ + memcpy(out, in, SPX_N); + + /* Iterate 'steps' calls to the hash function. */ + for (i = start; i < (start + steps) && i < SPX_WOTS_W; i++) { + set_hash_addr(addr, i); + thash(out, out, 1, ctx, addr); + } +} + +/** + * base_w algorithm as described in draft. + * Interprets an array of bytes as integers in base w. + * This only works when log_w is a divisor of 8. + */ +static void base_w(unsigned int *output, const int out_len, + const unsigned char *input) { + int in = 0; + int out = 0; + unsigned char total = 0; + int bits = 0; + int consumed; + + for (consumed = 0; consumed < out_len; consumed++) { + if (bits == 0) { + total = input[in]; + in++; + bits += 8; + } + bits -= SPX_WOTS_LOGW; + output[out] = (total >> bits) & (SPX_WOTS_W - 1); + out++; + } +} + +/* Computes the WOTS+ checksum over a message (in base_w). */ +static void wots_checksum(unsigned int *csum_base_w, + const unsigned int *msg_base_w) { + unsigned int csum = 0; + unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; + unsigned int i; + + /* Compute checksum. */ + for (i = 0; i < SPX_WOTS_LEN1; i++) { + csum += SPX_WOTS_W - 1 - msg_base_w[i]; + } + + /* Convert checksum to base_w. */ + /* Make sure expected empty zero bits are the least significant bits. */ + csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); + ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); + base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); +} + +/* Takes a message and derives the matching chain lengths. */ +void chain_lengths(unsigned int *lengths, const unsigned char *msg) { + base_w(lengths, SPX_WOTS_LEN1, msg); + wots_checksum(lengths + SPX_WOTS_LEN1, lengths); +} + +/** + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. + * + * Writes the computed public key to 'pk'. + */ +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]) { + unsigned int lengths[SPX_WOTS_LEN]; + uint32_t i; + + chain_lengths(lengths, msg); + + for (i = 0; i < SPX_WOTS_LEN; i++) { + set_chain_addr(addr, i); + gen_chain(pk + i * SPX_N, sig + i * SPX_N, + lengths[i], SPX_WOTS_W - 1 - lengths[i], ctx, addr); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_clean/wots.h b/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_clean/wots.h new file mode 100644 index 0000000000..4e7692eeef --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_clean/wots.h @@ -0,0 +1,25 @@ +#ifndef SPX_WOTS_H +#define SPX_WOTS_H + +#include + +#include "context.h" +#include "params.h" + +/** + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. + * + * Writes the computed public key to 'pk'. + */ +#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]); + +/* + * Compute the chain lengths needed for a given message hash + */ +#define chain_lengths SPX_NAMESPACE(chain_lengths) +void chain_lengths(unsigned int *lengths, const unsigned char *msg); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_clean/wotsx1.c b/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_clean/wotsx1.c new file mode 100644 index 0000000000..3adec78dfb --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_clean/wotsx1.c @@ -0,0 +1,76 @@ +#include +#include + +#include "wots.h" +#include "wotsx1.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "thash.h" +#include "utils.h" + +/* + * This generates a WOTS public key + * It also generates the WOTS signature if leaf_info indicates + * that we're signing with this WOTS key + */ +void wots_gen_leafx1(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info) { + struct leaf_info_x1 *info = v_info; + uint32_t *leaf_addr = info->leaf_addr; + uint32_t *pk_addr = info->pk_addr; + unsigned int i, k; + unsigned char pk_buffer[ SPX_WOTS_BYTES ]; + unsigned char *buffer; + uint32_t wots_k_mask; + + if (leaf_idx == info->wots_sign_leaf) { + /* We're traversing the leaf that's signing; generate the WOTS */ + /* signature */ + wots_k_mask = 0; + } else { + /* Nope, we're just generating pk's; turn off the signature logic */ + wots_k_mask = (uint32_t)~0; + } + + set_keypair_addr( leaf_addr, leaf_idx ); + set_keypair_addr( pk_addr, leaf_idx ); + + for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { + uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k to */ + /* the step if we're generating a signature, ~0 if we're not */ + + /* Start with the secret seed */ + set_chain_addr(leaf_addr, i); + set_hash_addr(leaf_addr, 0); + set_type(leaf_addr, SPX_ADDR_TYPE_WOTSPRF); + + prf_addr(buffer, ctx, leaf_addr); + + set_type(leaf_addr, SPX_ADDR_TYPE_WOTS); + + /* Iterate down the WOTS chain */ + for (k = 0;; k++) { + /* Check if this is the value that needs to be saved as a */ + /* part of the WOTS signature */ + if (k == wots_k) { + memcpy( info->wots_sig + i * SPX_N, buffer, SPX_N ); + } + + /* Check if we hit the top of the chain */ + if (k == SPX_WOTS_W - 1) { + break; + } + + /* Iterate one step on the chain */ + set_hash_addr(leaf_addr, k); + + thash(buffer, buffer, 1, ctx, leaf_addr); + } + } + + /* Do the final thash to generate the public keys */ + thash(dest, pk_buffer, SPX_WOTS_LEN, ctx, pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_clean/wotsx1.h b/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_clean/wotsx1.h new file mode 100644 index 0000000000..e617929f96 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-sha2-256s-simple_clean/wotsx1.h @@ -0,0 +1,39 @@ +#ifndef WOTSX1_H_ +#define WOTSX1_H_ + +#include + +#include "context.h" +#include "params.h" + +/* + * This is here to provide an interface to the internal wots_gen_leafx1 + * routine. While this routine is not referenced in the package outside of + * wots.c, it is called from the stand-alone benchmark code to characterize + * the performance + */ +struct leaf_info_x1 { + unsigned char *wots_sig; + uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ + uint32_t *wots_steps; + uint32_t leaf_addr[8]; + uint32_t pk_addr[8]; +}; + +/* Macro to set the leaf_info to something 'benign', that is, it would */ +/* run with the same time as it does during the real signing process */ +/* Used only by the benchmark code */ +#define INITIALIZE_LEAF_INFO_X1(info, addr, step_buffer) { \ + (info).wots_sig = 0; \ + (info).wots_sign_leaf = ~0; \ + (info).wots_steps = step_buffer; \ + memcpy( &(info).leaf_addr[0], (addr), 32 ); \ + memcpy( &(info).pk_addr[0], (addr), 32 ); \ + } + +#define wots_gen_leafx1 SPX_NAMESPACE(wots_gen_leafx1) +void wots_gen_leafx1(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info); + +#endif /* WOTSX1_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/LICENSE b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/LICENSE new file mode 100644 index 0000000000..670154e353 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/LICENSE @@ -0,0 +1,116 @@ +CC0 1.0 Universal + +Statement of Purpose + +The laws of most jurisdictions throughout the world automatically confer +exclusive Copyright and Related Rights (defined below) upon the creator and +subsequent owner(s) (each and all, an "owner") of an original work of +authorship and/or a database (each, a "Work"). + +Certain owners wish to permanently relinquish those rights to a Work for the +purpose of contributing to a commons of creative, cultural and scientific +works ("Commons") that the public can reliably and without fear of later +claims of infringement build upon, modify, incorporate in other works, reuse +and redistribute as freely as possible in any form whatsoever and for any +purposes, including without limitation commercial purposes. These owners may +contribute to the Commons to promote the ideal of a free culture and the +further production of creative, cultural and scientific works, or to gain +reputation or greater distribution for their Work in part through the use and +efforts of others. + +For these and/or other purposes and motivations, and without any expectation +of additional consideration or compensation, the person associating CC0 with a +Work (the "Affirmer"), to the extent that he or she is an owner of Copyright +and Related Rights in the Work, voluntarily elects to apply CC0 to the Work +and publicly distribute the Work under its terms, with knowledge of his or her +Copyright and Related Rights in the Work and the meaning and intended legal +effect of CC0 on those rights. + +1. Copyright and Related Rights. A Work made available under CC0 may be +protected by copyright and related or neighboring rights ("Copyright and +Related Rights"). Copyright and Related Rights include, but are not limited +to, the following: + + i. the right to reproduce, adapt, distribute, perform, display, communicate, + and translate a Work; + + ii. moral rights retained by the original author(s) and/or performer(s); + + iii. publicity and privacy rights pertaining to a person's image or likeness + depicted in a Work; + + iv. rights protecting against unfair competition in regards to a Work, + subject to the limitations in paragraph 4(a), below; + + v. rights protecting the extraction, dissemination, use and reuse of data in + a Work; + + vi. database rights (such as those arising under Directive 96/9/EC of the + European Parliament and of the Council of 11 March 1996 on the legal + protection of databases, and under any national implementation thereof, + including any amended or successor version of such directive); and + + vii. other similar, equivalent or corresponding rights throughout the world + based on applicable law or treaty, and any national implementations thereof. + +2. Waiver. To the greatest extent permitted by, but not in contravention of, +applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and +unconditionally waives, abandons, and surrenders all of Affirmer's Copyright +and Related Rights and associated claims and causes of action, whether now +known or unknown (including existing as well as future claims and causes of +action), in the Work (i) in all territories worldwide, (ii) for the maximum +duration provided by applicable law or treaty (including future time +extensions), (iii) in any current or future medium and for any number of +copies, and (iv) for any purpose whatsoever, including without limitation +commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes +the Waiver for the benefit of each member of the public at large and to the +detriment of Affirmer's heirs and successors, fully intending that such Waiver +shall not be subject to revocation, rescission, cancellation, termination, or +any other legal or equitable action to disrupt the quiet enjoyment of the Work +by the public as contemplated by Affirmer's express Statement of Purpose. + +3. Public License Fallback. Should any part of the Waiver for any reason be +judged legally invalid or ineffective under applicable law, then the Waiver +shall be preserved to the maximum extent permitted taking into account +Affirmer's express Statement of Purpose. In addition, to the extent the Waiver +is so judged Affirmer hereby grants to each affected person a royalty-free, +non transferable, non sublicensable, non exclusive, irrevocable and +unconditional license to exercise Affirmer's Copyright and Related Rights in +the Work (i) in all territories worldwide, (ii) for the maximum duration +provided by applicable law or treaty (including future time extensions), (iii) +in any current or future medium and for any number of copies, and (iv) for any +purpose whatsoever, including without limitation commercial, advertising or +promotional purposes (the "License"). The License shall be deemed effective as +of the date CC0 was applied by Affirmer to the Work. Should any part of the +License for any reason be judged legally invalid or ineffective under +applicable law, such partial invalidity or ineffectiveness shall not +invalidate the remainder of the License, and in such case Affirmer hereby +affirms that he or she will not (i) exercise any of his or her remaining +Copyright and Related Rights in the Work or (ii) assert any associated claims +and causes of action with respect to the Work, in either case contrary to +Affirmer's express Statement of Purpose. + +4. Limitations and Disclaimers. + + a. No trademark or patent rights held by Affirmer are waived, abandoned, + surrendered, licensed or otherwise affected by this document. + + b. Affirmer offers the Work as-is and makes no representations or warranties + of any kind concerning the Work, express, implied, statutory or otherwise, + including without limitation warranties of title, merchantability, fitness + for a particular purpose, non infringement, or the absence of latent or + other defects, accuracy, or the present or absence of errors, whether or not + discoverable, all to the greatest extent permissible under applicable law. + + c. Affirmer disclaims responsibility for clearing rights of other persons + that may apply to the Work or any use thereof, including without limitation + any person's Copyright and Related Rights in the Work. Further, Affirmer + disclaims responsibility for obtaining any necessary consents, permissions + or other rights required for any use of the Work. + + d. Affirmer understands and acknowledges that Creative Commons is not a + party to this document and has no duty or obligation with respect to this + CC0 or use of the Work. + +For more information, please see + diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/address.c b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/address.c new file mode 100644 index 0000000000..b956e9cb29 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/address.c @@ -0,0 +1,91 @@ +#include +#include + +#include "address.h" +#include "params.h" +#include "utils.h" + +/* + * Specify which level of Merkle tree (the "layer") we're working on + */ +void set_layer_addr(uint32_t addr[8], uint32_t layer) { + ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; +} + +/* + * Specify which Merkle tree within the level (the "tree address") we're working on + */ +void set_tree_addr(uint32_t addr[8], uint64_t tree) { + ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); +} + +/* + * Specify the reason we'll use this address structure for, that is, what + * hash will we compute with it. This is used so that unrelated types of + * hashes don't accidentally get the same address structure. The type will be + * one of the SPX_ADDR_TYPE constants + */ +void set_type(uint32_t addr[8], uint32_t type) { + ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; +} + +/* + * Copy the layer and tree fields of the address structure. This is used + * when we're doing multiple types of hashes within the same Merkle tree + */ +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); +} + +/* These functions are used for OTS addresses. */ + +/* + * Specify which Merkle leaf we're working on; that is, which OTS keypair + * we're talking about. + */ +void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { + ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; +} + +/* + * Copy the layer, tree and keypair fields of the address structure. This is + * used when we're doing multiple things within the same OTS keypair + */ +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); + ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; +} + +/* + * Specify which Merkle chain within the OTS we're working with + * (the chain address) + */ +void set_chain_addr(uint32_t addr[8], uint32_t chain) { + ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; +} + +/* + * Specify where in the Merkle chain we are +* (the hash address) + */ +void set_hash_addr(uint32_t addr[8], uint32_t hash) { + ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; +} + +/* These functions are used for all hash tree addresses (including FORS). */ + +/* + * Specify the height of the node in the Merkle/FORS tree we are in + * (the tree height) + */ +void set_tree_height(uint32_t addr[8], uint32_t tree_height) { + ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; +} + +/* + * Specify the distance from the left edge of the node in the Merkle/FORS tree + * (the tree index) + */ +void set_tree_index(uint32_t addr[8], uint32_t tree_index) { + u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/address.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/address.h new file mode 100644 index 0000000000..24a84eb40c --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/address.h @@ -0,0 +1,52 @@ +#ifndef SPX_ADDRESS_H +#define SPX_ADDRESS_H + +#include + +#include "params.h" + +/* The hash types that are passed to set_type */ +#define SPX_ADDR_TYPE_WOTS 0 +#define SPX_ADDR_TYPE_WOTSPK 1 +#define SPX_ADDR_TYPE_HASHTREE 2 +#define SPX_ADDR_TYPE_FORSTREE 3 +#define SPX_ADDR_TYPE_FORSPK 4 +#define SPX_ADDR_TYPE_WOTSPRF 5 +#define SPX_ADDR_TYPE_FORSPRF 6 + +#define set_layer_addr SPX_NAMESPACE(set_layer_addr) +void set_layer_addr(uint32_t addr[8], uint32_t layer); + +#define set_tree_addr SPX_NAMESPACE(set_tree_addr) +void set_tree_addr(uint32_t addr[8], uint64_t tree); + +#define set_type SPX_NAMESPACE(set_type) +void set_type(uint32_t addr[8], uint32_t type); + +/* Copies the layer and tree part of one address into the other */ +#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); + +/* These functions are used for WOTS and FORS addresses. */ + +#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) +void set_keypair_addr(uint32_t addr[8], uint32_t keypair); + +#define set_chain_addr SPX_NAMESPACE(set_chain_addr) +void set_chain_addr(uint32_t addr[8], uint32_t chain); + +#define set_hash_addr SPX_NAMESPACE(set_hash_addr) +void set_hash_addr(uint32_t addr[8], uint32_t hash); + +#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); + +/* These functions are used for all hash tree addresses (including FORS). */ + +#define set_tree_height SPX_NAMESPACE(set_tree_height) +void set_tree_height(uint32_t addr[8], uint32_t tree_height); + +#define set_tree_index SPX_NAMESPACE(set_tree_index) +void set_tree_index(uint32_t addr[8], uint32_t tree_index); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/api.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/api.h new file mode 100644 index 0000000000..d32deebff0 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/api.h @@ -0,0 +1,77 @@ +#ifndef PQCLEAN_SPHINCSSHAKE128FROBUST_AARCH64_API_H +#define PQCLEAN_SPHINCSSHAKE128FROBUST_AARCH64_API_H + +#include +#include + +#define PQCLEAN_SPHINCSSHAKE128FROBUST_AARCH64_CRYPTO_ALGNAME "SPHINCS+-shake-128f-robust" + +#define PQCLEAN_SPHINCSSHAKE128FROBUST_AARCH64_CRYPTO_SECRETKEYBYTES 64 +#define PQCLEAN_SPHINCSSHAKE128FROBUST_AARCH64_CRYPTO_PUBLICKEYBYTES 32 +#define PQCLEAN_SPHINCSSHAKE128FROBUST_AARCH64_CRYPTO_BYTES 17088 + +#define PQCLEAN_SPHINCSSHAKE128FROBUST_AARCH64_CRYPTO_SEEDBYTES 48 + +/* + * Returns the length of a secret key, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE128FROBUST_AARCH64_crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE128FROBUST_AARCH64_crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE128FROBUST_AARCH64_crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE128FROBUST_AARCH64_crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +int PQCLEAN_SPHINCSSHAKE128FROBUST_AARCH64_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +int PQCLEAN_SPHINCSSHAKE128FROBUST_AARCH64_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +int PQCLEAN_SPHINCSSHAKE128FROBUST_AARCH64_crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +int PQCLEAN_SPHINCSSHAKE128FROBUST_AARCH64_crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, + const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +int PQCLEAN_SPHINCSSHAKE128FROBUST_AARCH64_crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +int PQCLEAN_SPHINCSSHAKE128FROBUST_AARCH64_crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/context.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/context.h new file mode 100644 index 0000000000..6e0a33f3b7 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/context.h @@ -0,0 +1,19 @@ +#ifndef SPX_CONTEXT_H +#define SPX_CONTEXT_H + +#include + +#include "params.h" + +typedef struct { + uint8_t pub_seed[SPX_N]; + uint8_t sk_seed[SPX_N]; +} spx_ctx; + +#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) +void initialize_hash_function(spx_ctx *ctx); + +#define free_hash_function SPX_NAMESPACE(free_hash_function) +void free_hash_function(spx_ctx *ctx); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/context_shake.c b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/context_shake.c new file mode 100644 index 0000000000..9614a103d3 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/context_shake.c @@ -0,0 +1,12 @@ +#include "context.h" + +/* For SHAKE256, there is no immediate reason to initialize at the start, + so this function is an empty operation. */ +void initialize_hash_function(spx_ctx *ctx) { + (void)ctx; /* Suppress an 'unused parameter' warning. */ +} + +// in case the hash function api is heap-based. +void free_hash_function(spx_ctx *ctx) { + (void)ctx; +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/f1600x2.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/f1600x2.h new file mode 100644 index 0000000000..70d1af9f14 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/f1600x2.h @@ -0,0 +1,11 @@ +#ifndef SPX_F1600X2_H +#define SPX_F1600X2_H + +#include + +extern uint64_t f1600_RC[24]; +extern void _f1600x2(uint64_t *a, uint64_t *rc); + +#define f1600x2(s) do {_f1600x2((s), f1600_RC);} while(0) + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/f1600x2.s b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/f1600x2.s new file mode 100644 index 0000000000..640ed791ed --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/f1600x2.s @@ -0,0 +1,143 @@ +# From https://github.com/bwesterb/armed-keccak + +.macro round + # Execute theta, but without xoring into the state yet. + # Compute parities p[i] = a[i] ^ a[5+i] ^ ... ^ a[20+i]. + eor3.16b v25, v0, v5, v10 + eor3.16b v26, v1, v6, v11 + eor3.16b v27, v2, v7, v12 + eor3.16b v28, v3, v8, v13 + eor3.16b v29, v4, v9, v14 + + eor3.16b v25, v25, v15, v20 + eor3.16b v26, v26, v16, v21 + eor3.16b v27, v27, v17, v22 + eor3.16b v28, v28, v18, v23 + eor3.16b v29, v29, v19, v24 + + # d[0] = rotl(p[1], 1) ^ p[4] + rax1.2d v30, v29, v26 + # d[3] = rotl(p[4], 1) ^ p[2] + rax1.2d v29, v27, v29 + # d[1] = rotl(p[2], 1) ^ p[0] + rax1.2d v27, v25, v27 + # d[4] = rotl(p[0], 1) ^ p[3] + rax1.2d v25, v28, v25 + # d[2] = rotl(p[3], 1) ^ p[1] + rax1.2d v28, v26, v28 + + # Xor parities from step theta into the state at the same time + # as executing rho and pi. + eor.16b v0, v0, v30 + mov.16b v31, v1 + xar.2d v1, v6, v27, 20 + xar.2d v6, v9, v25, 44 + xar.2d v9, v22, v28, 3 + xar.2d v22, v14, v25, 25 + xar.2d v14, v20, v30, 46 + xar.2d v20, v2, v28, 2 + xar.2d v2, v12, v28, 21 + xar.2d v12, v13, v29, 39 + xar.2d v13, v19, v25, 56 + xar.2d v19, v23, v29, 8 + xar.2d v23, v15, v30, 23 + xar.2d v15, v4, v25, 37 + xar.2d v4, v24, v25, 50 + xar.2d v24, v21, v27, 62 + xar.2d v21, v8, v29, 9 + xar.2d v8, v16, v27, 19 + xar.2d v16, v5, v30, 28 + xar.2d v5, v3, v29, 36 + xar.2d v3, v18, v29, 43 + xar.2d v18, v17, v28, 49 + xar.2d v17, v11, v27, 54 + xar.2d v11, v7, v28, 58 + xar.2d v7, v10, v30, 61 + xar.2d v10, v31, v27, 63 + + # Chi + bcax.16b v25, v0, v2, v1 + bcax.16b v26, v1, v3, v2 + bcax.16b v2, v2, v4, v3 + bcax.16b v3, v3, v0, v4 + bcax.16b v4, v4, v1, v0 + mov.16b v0, v25 + mov.16b v1, v26 + + bcax.16b v25, v5, v7, v6 + bcax.16b v26, v6, v8, v7 + bcax.16b v7, v7, v9, v8 + bcax.16b v8, v8, v5, v9 + bcax.16b v9, v9, v6, v5 + mov.16b v5, v25 + mov.16b v6, v26 + + bcax.16b v25, v10, v12, v11 + bcax.16b v26, v11, v13, v12 + bcax.16b v12, v12, v14, v13 + bcax.16b v13, v13, v10, v14 + bcax.16b v14, v14, v11, v10 + mov.16b v10, v25 + mov.16b v11, v26 + + bcax.16b v25, v15, v17, v16 + bcax.16b v26, v16, v18, v17 + bcax.16b v17, v17, v19, v18 + bcax.16b v18, v18, v15, v19 + bcax.16b v19, v19, v16, v15 + mov.16b v15, v25 + mov.16b v16, v26 + + bcax.16b v25, v20, v22, v21 + bcax.16b v26, v21, v23, v22 + bcax.16b v22, v22, v24, v23 + bcax.16b v23, v23, v20, v24 + bcax.16b v24, v24, v21, v20 + mov.16b v20, v25 + mov.16b v21, v26 + + # iota + ld1r {v25.2d}, [x1], #8 + eor.16b v0, v0, v25 +.endm + +.align 4 +.global __f1600x2 +__f1600x2: + stp d8, d9, [sp,#-16]! + stp d10, d11, [sp,#-16]! + stp d12, d13, [sp,#-16]! + stp d14, d15, [sp,#-16]! + + mov x2, x0 + mov x3, #24 + + ld1.2d {v0, v1, v2, v3}, [x0], #64 + ld1.2d {v4, v5, v6, v7}, [x0], #64 + ld1.2d {v8, v9, v10, v11}, [x0], #64 + ld1.2d {v12, v13, v14, v15}, [x0], #64 + ld1.2d {v16, v17, v18, v19}, [x0], #64 + ld1.2d {v20, v21, v22, v23}, [x0], #64 + ld1.2d {v24}, [x0] + +loop: + round + + subs x3, x3, #1 + cbnz x3, loop + + mov x0, x2 + st1.2d {v0, v1, v2, v3}, [x0], #64 + st1.2d {v4, v5, v6, v7}, [x0], #64 + st1.2d {v8, v9, v10, v11}, [x0], #64 + st1.2d {v12, v13, v14, v15}, [x0], #64 + st1.2d {v16, v17, v18, v19}, [x0], #64 + st1.2d {v20, v21, v22, v23}, [x0], #64 + st1.2d {v24}, [x0] + + ldp d14, d15, [sp], #16 + ldp d12, d13, [sp], #16 + ldp d10, d11, [sp], #16 + ldp d8, d9, [sp], #16 + + ret lr diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/f1600x2_const.c b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/f1600x2_const.c new file mode 100644 index 0000000000..e49c0ba149 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/f1600x2_const.c @@ -0,0 +1,30 @@ +#include "f1600x2.h" + +uint64_t f1600_RC[24] = { + 0x0000000000000001, + 0x0000000000008082, + 0x800000000000808A, + 0x8000000080008000, + 0x000000000000808B, + 0x0000000080000001, + 0x8000000080008081, + 0x8000000000008009, + 0x000000000000008A, + 0x0000000000000088, + 0x0000000080008009, + 0x000000008000000A, + 0x000000008000808B, + 0x800000000000008B, + 0x8000000000008089, + 0x8000000000008003, + 0x8000000000008002, + 0x8000000000000080, + 0x000000000000800A, + 0x800000008000000A, + 0x8000000080008081, + 0x8000000000008080, + 0x0000000080000001, + 0x8000000080008008, +}; + + diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/fips202x2.c b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/fips202x2.c new file mode 100644 index 0000000000..4718c343bc --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/fips202x2.c @@ -0,0 +1,148 @@ +#include +#include + +#include "fips202x2.h" +#include "f1600x2.h" +#include "fips202.h" + +uint64_t load64(const unsigned char *x) { + unsigned long long r = 0, i; + + for (i = 0; i < 8; ++i) { + r |= (unsigned long long)x[i] << 8 * i; + } + return r; +} + +void store64(uint8_t *x, uint64_t u) { + unsigned int i; + + for (i = 0; i < 8; ++i) { + x[i] = (uint8_t)u; + u >>= 8; + } +} + +static void keccak_absorb2x(uint64_t *s, + unsigned int r, + const unsigned char *m0, + const unsigned char *m1, + unsigned long long int mlen, + unsigned char p) { + unsigned long long i; + unsigned char t0[200]; + unsigned char t1[200]; + + while (mlen >= r) { + for (i = 0; i < r / 8; ++i) { + s[2 * i + 0] ^= load64(m0 + 8 * i); + s[2 * i + 1] ^= load64(m1 + 8 * i); + } + + f1600x2(s); + mlen -= r; + m0 += r; + m1 += r; + } + + for (i = 0; i < r; ++i) { + t0[i] = 0; + t1[i] = 0; + } + for (i = 0; i < mlen; ++i) { + t0[i] = m0[i]; + t1[i] = m1[i]; + } + + t0[i] = p; + t1[i] = p; + + t0[r - 1] |= 128; + t1[r - 1] |= 128; + + for (i = 0; i < r / 8; ++i) { + s[2 * i + 0] ^= load64(t0 + 8 * i); + s[2 * i + 1] ^= load64(t1 + 8 * i); + } +} + + +static void keccak_squeezeblocks2x(unsigned char *h0, + unsigned char *h1, + unsigned long long int nblocks, + uint64_t *s, + unsigned int r) { + unsigned int i; + + while (nblocks > 0) { + f1600x2(s); + for (i = 0; i < (r >> 3); i++) { + store64(h0 + 8 * i, s[2 * i + 0]); + store64(h1 + 8 * i, s[2 * i + 1]); + } + h0 += r; + h1 += r; + nblocks--; + } +} + + + +void shake128x2(unsigned char *out0, + unsigned char *out1, + unsigned long long outlen, + unsigned char *in0, + unsigned char *in1, + unsigned long long inlen) { + uint64_t s[50] = {0}; + unsigned char t0[SHAKE128_RATE]; + unsigned char t1[SHAKE128_RATE]; + unsigned int i; + + /* absorb 4 message of identical length in parallel */ + keccak_absorb2x(s, SHAKE128_RATE, in0, in1, inlen, 0x1F); + + /* Squeeze output */ + keccak_squeezeblocks2x(out0, out1, outlen / SHAKE128_RATE, s, SHAKE128_RATE); + + out0 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; + out1 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; + + if (outlen % SHAKE128_RATE) { + keccak_squeezeblocks2x(t0, t1, 1, s, SHAKE128_RATE); + for (i = 0; i < outlen % SHAKE128_RATE; i++) { + out0[i] = t0[i]; + out1[i] = t1[i]; + } + } +} + + +void shake256x2(unsigned char *out0, + unsigned char *out1, + unsigned long long outlen, + unsigned char *in0, + unsigned char *in1, + unsigned long long inlen) { + uint64_t s[50] = {0}; + unsigned char t0[SHAKE256_RATE]; + unsigned char t1[SHAKE256_RATE]; + unsigned int i; + + /* absorb 2 message of identical length in parallel */ + keccak_absorb2x(s, SHAKE256_RATE, in0, in1, inlen, 0x1F); + + /* Squeeze output */ + keccak_squeezeblocks2x(out0, out1, outlen / SHAKE256_RATE, s, SHAKE256_RATE); + + out0 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; + out1 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; + + if (outlen % SHAKE256_RATE) { + keccak_squeezeblocks2x(t0, t1, 1, s, SHAKE256_RATE); + for (i = 0; i < outlen % SHAKE256_RATE; i++) { + out0[i] = t0[i]; + out1[i] = t1[i]; + } + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/fips202x2.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/fips202x2.h new file mode 100644 index 0000000000..7ba58b35d8 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/fips202x2.h @@ -0,0 +1,24 @@ +#ifndef SPX_FIPS202X2_H +#define SPX_FIPS202X2_H + +#include + +uint64_t load64(const unsigned char *x); +void store64(uint8_t *x, uint64_t u); + + +void shake128x2(unsigned char *out0, + unsigned char *out1, + unsigned long long outlen, + unsigned char *in0, + unsigned char *in1, + unsigned long long inlen); + +void shake256x2(unsigned char *out0, + unsigned char *out1, + unsigned long long outlen, + unsigned char *in0, + unsigned char *in1, + unsigned long long inlen); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/fors.c b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/fors.c new file mode 100644 index 0000000000..39193d04e2 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/fors.c @@ -0,0 +1,191 @@ +#include +#include +#include + +#include "fors.h" + +#include "address.h" +#include "hash.h" +#include "hashx2.h" +#include "thash.h" +#include "thashx2.h" +#include "utils.h" +#include "utilsx2.h" + +static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + prf_addr(sk, ctx, fors_leaf_addr); +} + +static void fors_gen_skx2(unsigned char *sk0, + unsigned char *sk1, + const spx_ctx *ctx, + uint32_t fors_leaf_addrx2[2 * 8]) { + prf_addrx2(sk0, sk1, + ctx, fors_leaf_addrx2); +} + +static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, + const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + thash(leaf, sk, 1, ctx, fors_leaf_addr); +} + +static void fors_sk_to_leafx2(unsigned char *leaf0, + unsigned char *leaf1, + const unsigned char *sk0, + const unsigned char *sk1, + const spx_ctx *ctx, + uint32_t fors_leaf_addrx2[2 * 8]) { + thashx2(leaf0, leaf1, + sk0, sk1, + 1, ctx, fors_leaf_addrx2); +} + +struct fors_gen_leaf_info { + uint32_t leaf_addrx[2 * 8]; +}; + +static void fors_gen_leafx2(unsigned char *leaf, + const spx_ctx *ctx, + uint32_t addr_idx, void *info) { + struct fors_gen_leaf_info *fors_info = info; + uint32_t *fors_leaf_addrx2 = fors_info->leaf_addrx; + unsigned int j; + + /* Only set the parts that the caller doesn't set */ + for (j = 0; j < 2; j++) { + set_tree_index(fors_leaf_addrx2 + j * 8, addr_idx + j); + set_type(fors_leaf_addrx2 + j * 8, SPX_ADDR_TYPE_FORSPRF); + } + + fors_gen_skx2(leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + ctx, fors_leaf_addrx2); + + for (j = 0; j < 2; j++) { + set_type(fors_leaf_addrx2 + j * 8, SPX_ADDR_TYPE_FORSTREE); + } + + fors_sk_to_leafx2(leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + ctx, fors_leaf_addrx2); +} + +/** + * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + * Assumes indices has space for SPX_FORS_TREES integers. + */ +static void message_to_indices(uint32_t *indices, const unsigned char *m) { + unsigned int i, j; + unsigned int offset = 0; + + for (i = 0; i < SPX_FORS_TREES; i++) { + indices[i] = 0; + for (j = 0; j < SPX_FORS_HEIGHT; j++) { + indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); + offset++; + } + } +} + +/** + * Signs a message m, deriving the secret key from sk_seed and the FTS address. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + uint32_t fors_tree_addr[2 * 8] = {0}; + struct fors_gen_leaf_info fors_info = {0}; + uint32_t *fors_leaf_addr = fors_info.leaf_addrx; + uint32_t fors_pk_addr[8] = {0}; + uint32_t idx_offset; + unsigned int i; + + for (i = 0; i < 2; i++) { + copy_keypair_addr(fors_tree_addr + 8 * i, fors_addr); + set_type(fors_tree_addr + 8 * i, SPX_ADDR_TYPE_FORSTREE); + copy_keypair_addr(fors_leaf_addr + 8 * i, fors_addr); + } + copy_keypair_addr(fors_pk_addr, fors_addr); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); + + message_to_indices(indices, m); + + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); + + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + + /* Include the secret key part that produces the selected leaf node. */ + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); + fors_gen_sk(sig, ctx, fors_tree_addr); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + sig += SPX_N; + + /* Compute the authentication path for this leaf node. */ + treehashx2(roots + i * SPX_N, sig, ctx, + indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx2, + fors_tree_addr, &fors_info); + + sig += SPX_N * SPX_FORS_HEIGHT; + } + + /* Hash horizontally across all tree roots to derive the public key. */ + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); +} + +/** + * Derives the FORS public key from a signature. + * This can be used for verification by comparing to a known public key, or to + * subsequently verify a signature on the derived public key. The latter is the + * typical use-case when used as an FTS below an OTS in a hypertree. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + unsigned char leaf[SPX_N]; + uint32_t fors_tree_addr[8] = {0}; + uint32_t fors_pk_addr[8] = {0}; + uint32_t idx_offset; + unsigned int i; + + copy_keypair_addr(fors_tree_addr, fors_addr); + copy_keypair_addr(fors_pk_addr, fors_addr); + + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); + + message_to_indices(indices, m); + + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); + + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + + /* Derive the leaf from the included secret key part. */ + fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); + sig += SPX_N; + + /* Derive the corresponding root node of this tree. */ + compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, + sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); + sig += SPX_N * SPX_FORS_HEIGHT; + } + + /* Hash horizontally across all tree roots to derive the public key. */ + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/fors.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/fors.h new file mode 100644 index 0000000000..509140a178 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/fors.h @@ -0,0 +1,32 @@ +#ifndef SPX_FORS_H +#define SPX_FORS_H + +#include + +#include "context.h" +#include "params.h" + +/** + * Signs a message m, deriving the secret key from sk_seed and the FTS address. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +#define fors_sign SPX_NAMESPACE(fors_sign) +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); + +/** + * Derives the FORS public key from a signature. + * This can be used for verification by comparing to a known public key, or to + * subsequently verify a signature on the derived public key. The latter is the + * typical use-case when used as an FTS below an OTS in a hypertree. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/hash.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/hash.h new file mode 100644 index 0000000000..f7c87d4c3c --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/hash.h @@ -0,0 +1,28 @@ +#ifndef SPX_HASH_H +#define SPX_HASH_H + +#include +#include + +#include "context.h" +#include "params.h" + +#define prf_addr SPX_NAMESPACE(prf_addr) +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]); + +#define gen_message_random SPX_NAMESPACE(gen_message_random) +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); + +#define hash_message SPX_NAMESPACE(hash_message) +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); + + + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/hash_shake.c b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/hash_shake.c new file mode 100644 index 0000000000..ff5e7ec918 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/hash_shake.c @@ -0,0 +1,83 @@ +#include +#include + +#include "hash.h" + +#include "address.h" +#include "fips202.h" +#include "params.h" +#include "utils.h" + +/* + * Computes PRF(pk_seed, sk_seed, addr) + */ +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]) { + unsigned char buf[2 * SPX_N + SPX_ADDR_BYTES]; + + memcpy(buf, ctx->pub_seed, SPX_N); + memcpy(buf + SPX_N, addr, SPX_ADDR_BYTES); + memcpy(buf + SPX_N + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); + + shake256(out, SPX_N, buf, 2 * SPX_N + SPX_ADDR_BYTES); +} + +/** + * Computes the message-dependent randomness R, using a secret seed and an + * optional randomization value as well as the message. + */ +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { + (void)ctx; + shake256incctx s_inc; + + shake256_inc_init(&s_inc); + shake256_inc_absorb(&s_inc, sk_prf, SPX_N); + shake256_inc_absorb(&s_inc, optrand, SPX_N); + shake256_inc_absorb(&s_inc, m, mlen); + shake256_inc_finalize(&s_inc); + shake256_inc_squeeze(R, SPX_N, &s_inc); + shake256_inc_ctx_release(&s_inc); +} + +/** + * Computes the message hash using R, the public key, and the message. + * Outputs the message digest and the index of the leaf. The index is split in + * the tree index and the leaf index, for convenient copying to an address. + */ +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { + (void)ctx; +#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) +#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) +#define SPX_LEAF_BITS SPX_TREE_HEIGHT +#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) +#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) + + unsigned char buf[SPX_DGST_BYTES]; + unsigned char *bufp = buf; + shake256incctx s_inc; + + shake256_inc_init(&s_inc); + shake256_inc_absorb(&s_inc, R, SPX_N); + shake256_inc_absorb(&s_inc, pk, SPX_PK_BYTES); + shake256_inc_absorb(&s_inc, m, mlen); + shake256_inc_finalize(&s_inc); + shake256_inc_squeeze(buf, SPX_DGST_BYTES, &s_inc); + shake256_inc_ctx_release(&s_inc); + + memcpy(digest, bufp, SPX_FORS_MSG_BYTES); + bufp += SPX_FORS_MSG_BYTES; + + + *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); + *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); + bufp += SPX_TREE_BYTES; + + *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); + *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/hash_shakex2.c b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/hash_shakex2.c new file mode 100644 index 0000000000..99571916a2 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/hash_shakex2.c @@ -0,0 +1,52 @@ +#include +#include + +#include "hashx2.h" + +#include "address.h" +#include "f1600x2.h" +#include "fips202x2.h" +#include "params.h" + +/* + * 2-way parallel version of prf_addr; takes 2x as much input and output + */ +void prf_addrx2(unsigned char *out0, + unsigned char *out1, + const spx_ctx *ctx, + const uint32_t addrx2[2 * 8]) { + /* As we write and read only a few quadwords, it is more efficient to + * build and extract from the fourway SHAKE256 state by hand. */ + uint64_t state[50] = {0}; + + for (int i = 0; i < SPX_N / 8; i++) { + uint64_t x = load64(ctx->pub_seed + 8 * i); + state[2 * i] = x; + state[2 * i + 1] = x; + } + for (int i = 0; i < 4; i++) { + state[2 * (SPX_N / 8 + i)] = (((uint64_t)addrx2[1 + 2 * i]) << 32) + | (uint64_t)addrx2[2 * i]; + state[2 * (SPX_N / 8 + i) + 1] = (((uint64_t)addrx2[8 + 1 + 2 * i]) << 32) + | (uint64_t)addrx2[8 + 2 * i]; + } + for (int i = 0; i < SPX_N / 8; i++) { + uint64_t x = load64(ctx->sk_seed + 8 * i); + state[2 * (SPX_N / 8 + i + 4)] = x; + state[2 * (SPX_N / 8 + i + 4) + 1] = x; + } + + /* SHAKE domain separator and padding. */ + state[2 * (SPX_N / 4 + 4)] = 0x1f; + state[2 * (SPX_N / 4 + 4) + 1] = 0x1f; + + state[2 * 16] = 0x80ULL << 56; + state[2 * 16 + 1] = 0x80ULL << 56; + + f1600x2(state); + + for (int i = 0; i < SPX_N / 8; i++) { + store64(out0 + 8 * i, state[2 * i]); + store64(out1 + 8 * i, state[2 * i + 1]); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/hashx2.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/hashx2.h new file mode 100644 index 0000000000..99b8873a9b --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/hashx2.h @@ -0,0 +1,14 @@ +#ifndef SPX_HASHX2_H +#define SPX_HASHX2_H + +#include "context.h" +#include "params.h" +#include + +#define prf_addrx2 SPX_NAMESPACE(prf_addrx2) +void prf_addrx2(unsigned char *out0, + unsigned char *out1, + const spx_ctx *ctx, + const uint32_t addrx2[2 * 8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/merkle.c b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/merkle.c new file mode 100644 index 0000000000..c94ee23939 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/merkle.c @@ -0,0 +1,64 @@ +#include +#include + +#include "merkle.h" + +#include "address.h" +#include "params.h" +#include "utils.h" +#include "utilsx2.h" +#include "wots.h" +#include "wotsx2.h" + +/* + * This generates a Merkle signature (WOTS signature followed by the Merkle + * authentication path). + */ +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf) { + unsigned char *auth_path = sig + SPX_WOTS_BYTES; + uint32_t tree_addrx2[2 * 8] = { 0 }; + int j; + struct leaf_info_x2 info = { 0 }; + unsigned steps[ SPX_WOTS_LEN ]; + + info.wots_sig = sig; + chain_lengths(steps, root); + info.wots_steps = steps; + + for (j = 0; j < 2; j++) { + set_type(&tree_addrx2[8 * j], SPX_ADDR_TYPE_HASHTREE); + set_type(&info.leaf_addr[8 * j], SPX_ADDR_TYPE_WOTS); + set_type(&info.pk_addr[8 * j], SPX_ADDR_TYPE_WOTSPK); + copy_subtree_addr(&tree_addrx2[8 * j], tree_addr); + copy_subtree_addr(&info.leaf_addr[8 * j], wots_addr); + copy_subtree_addr(&info.pk_addr[8 * j], wots_addr); + } + + info.wots_sign_leaf = idx_leaf; + + treehashx2(root, auth_path, ctx, + idx_leaf, 0, + SPX_TREE_HEIGHT, + wots_gen_leafx2, + tree_addrx2, &info); +} + +/* Compute root node of the top-most subtree. */ +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { + /* We do not need the auth path in key generation, but it simplifies the + code to have just one treehash routine that computes both root and path + in one function. */ + unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; + uint32_t top_tree_addr[8] = {0}; + uint32_t wots_addr[8] = {0}; + + set_layer_addr(top_tree_addr, SPX_D - 1); + set_layer_addr(wots_addr, SPX_D - 1); + + merkle_sign(auth_path, root, ctx, + wots_addr, top_tree_addr, + ~0 /* ~0 means "don't bother generating an auth path */ ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/merkle.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/merkle.h new file mode 100644 index 0000000000..769cf2e970 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/merkle.h @@ -0,0 +1,21 @@ +#ifndef MERKLE_H_ +#define MERKLE_H_ + +#include + +#include "context.h" +#include "params.h" + +/* Generate a Merkle signature (WOTS signature followed by the Merkle */ +/* authentication path) */ +#define merkle_sign SPX_NAMESPACE(merkle_sign) +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf); + +/* Compute the root node of the top-most subtree. */ +#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); + +#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/nistapi.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/nistapi.h new file mode 100644 index 0000000000..3cb71afad4 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/nistapi.h @@ -0,0 +1,87 @@ +#ifndef SPX_API_H +#define SPX_API_H + +#include +#include + +#include "params.h" + +#define CRYPTO_ALGNAME "SPHINCS+" + +#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES +#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES +#define CRYPTO_BYTES SPX_BYTES +#define CRYPTO_SEEDBYTES (3*SPX_N) + +/* + * Returns the length of a secret key, in bytes + */ +#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) +size_t crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) +size_t crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) +size_t crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) +size_t crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +#define crypto_sign SPX_NAMESPACE(crypto_sign) +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/params.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/params.h new file mode 100644 index 0000000000..8a7a4affa7 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/params.h @@ -0,0 +1,56 @@ +#ifndef SPX_PARAMS_H +#define SPX_PARAMS_H + +#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSSHAKE128FROBUST_AARCH64_##s + +/* Hash output length in bytes. */ +#define SPX_N 16 +/* Height of the hypertree. */ +#define SPX_FULL_HEIGHT 66 +/* Number of subtree layer. */ +#define SPX_D 22 +/* FORS tree dimensions. */ +#define SPX_FORS_HEIGHT 6 +#define SPX_FORS_TREES 33 +/* Winternitz parameter, */ +#define SPX_WOTS_W 16 + +/* The hash function is defined by linking a different hash.c file, as opposed + to setting a #define constant. */ + +/* For clarity */ +#define SPX_ADDR_BYTES 32 + +/* WOTS parameters. */ +#define SPX_WOTS_LOGW 4 + +#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) + +/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ +#define SPX_WOTS_LEN2 3 + +#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) +#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) +#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES + +/* Subtree size. */ +#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) + +//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT +// #error SPX_D should always divide SPX_FULL_HEIGHT +//#endif + +/* FORS parameters. */ +#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) +#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) +#define SPX_FORS_PK_BYTES SPX_N + +/* Resulting SPX sizes. */ +#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ + SPX_FULL_HEIGHT * SPX_N) +#define SPX_PK_BYTES (2 * SPX_N) +#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) + +#include "shake_offsets.h" + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/shake_offsets.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/shake_offsets.h new file mode 100644 index 0000000000..6b28d95d91 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/shake_offsets.h @@ -0,0 +1,21 @@ +#ifndef SHAKE_OFFSETS_H_ +#define SHAKE_OFFSETS_H_ + +/* + * Offsets of various fields in the address structure when we use SHAKE as + * the Sphincs+ hash function + */ + +#define SPX_OFFSET_LAYER 3 /* The byte used to specify the Merkle tree layer */ +#define SPX_OFFSET_TREE 8 /* The start of the 8 byte field used to specify the tree */ +#define SPX_OFFSET_TYPE 19 /* The byte used to specify the hash type (reason) */ +#define SPX_OFFSET_KP_ADDR2 22 /* The high byte used to specify the key pair (which one-time signature) */ +#define SPX_OFFSET_KP_ADDR1 23 /* The low byte used to specify the key pair */ +#define SPX_OFFSET_CHAIN_ADDR 27 /* The byte used to specify the chain address (which Winternitz chain) */ +#define SPX_OFFSET_HASH_ADDR 31 /* The byte used to specify the hash address (where in the Winternitz chain) */ +#define SPX_OFFSET_TREE_HGT 27 /* The byte used to specify the height of this node in the FORS or Merkle tree */ +#define SPX_OFFSET_TREE_INDEX 28 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ + +#define SPX_SHAKE 1 + +#endif /* SHAKE_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/sign.c b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/sign.c new file mode 100644 index 0000000000..9d0c7d1b22 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/sign.c @@ -0,0 +1,286 @@ +#include +#include +#include + +#include "address.h" +#include "context.h" +#include "fors.h" +#include "hash.h" +#include "merkle.h" +#include "nistapi.h" +#include "params.h" +#include "randombytes.h" +#include "thash.h" +#include "utils.h" +#include "wots.h" + +/* + * Returns the length of a secret key, in bytes + */ +size_t crypto_sign_secretkeybytes(void) { + return CRYPTO_SECRETKEYBYTES; +} + +/* + * Returns the length of a public key, in bytes + */ +size_t crypto_sign_publickeybytes(void) { + return CRYPTO_PUBLICKEYBYTES; +} + +/* + * Returns the length of a signature, in bytes + */ +size_t crypto_sign_bytes(void) { + return CRYPTO_BYTES; +} + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +size_t crypto_sign_seedbytes(void) { + return CRYPTO_SEEDBYTES; +} + +/* + * Generates an SPX key pair given a seed of length + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [PUB_SEED || root] + */ +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed) { + spx_ctx ctx; + + /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ + memcpy(sk, seed, CRYPTO_SEEDBYTES); + + memcpy(pk, sk + 2 * SPX_N, SPX_N); + + memcpy(ctx.pub_seed, pk, SPX_N); + memcpy(ctx.sk_seed, sk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + /* Compute root node of the top-most subtree. */ + merkle_gen_root(sk + 3 * SPX_N, &ctx); + + // cleanup + free_hash_function(&ctx); + + memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); + + return 0; +} + +/* + * Generates an SPX key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [PUB_SEED || root] + */ +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { + uint8_t seed[CRYPTO_SEEDBYTES]; + randombytes(seed, CRYPTO_SEEDBYTES); + crypto_sign_seed_keypair(pk, sk, seed); + + return 0; +} + +/** + * Returns an array containing a detached signature. + */ +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk) { + spx_ctx ctx; + + const uint8_t *sk_prf = sk + SPX_N; + const uint8_t *pk = sk + 2 * SPX_N; + + uint8_t optrand[SPX_N]; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t root[SPX_N]; + uint32_t i; + uint64_t tree; + uint32_t idx_leaf; + uint32_t wots_addr[8] = {0}; + uint32_t tree_addr[8] = {0}; + + memcpy(ctx.sk_seed, sk, SPX_N); + memcpy(ctx.pub_seed, pk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + + /* Optionally, signing can be made non-deterministic using optrand. + This can help counter side-channel attacks that would benefit from + getting a large number of traces when the signer uses the same nodes. */ + randombytes(optrand, SPX_N); + /* Compute the digest randomization value. */ + gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); + + /* Derive the message digest and leaf index from R, PK and M. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; + + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); + + /* Sign the message hash using FORS. */ + fors_sign(sig, root, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); + sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; + + /* Update the indices for the next layer. */ + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; + } + + free_hash_function(&ctx); + + *siglen = SPX_BYTES; + + return 0; +} + +/** + * Verifies a detached signature and message under a given public key. + */ +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk) { + spx_ctx ctx; + const uint8_t *pub_root = pk + SPX_N; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t wots_pk[SPX_WOTS_BYTES]; + uint8_t root[SPX_N]; + uint8_t leaf[SPX_N]; + unsigned int i; + uint64_t tree; + uint32_t idx_leaf; + uint32_t wots_addr[8] = {0}; + uint32_t tree_addr[8] = {0}; + uint32_t wots_pk_addr[8] = {0}; + + if (siglen != SPX_BYTES) { + return -1; + } + + memcpy(ctx.pub_seed, pk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); + + /* Derive the message digest and leaf index from R || PK || M. */ + /* The additional SPX_N is a result of the hash domain separator. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; + + /* Layer correctly defaults to 0, so no need to set_layer_addr */ + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); + + fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + /* For each subtree.. */ + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + copy_keypair_addr(wots_pk_addr, wots_addr); + + /* The WOTS public key is only correct if the signature was correct. */ + /* Initially, root is the FORS pk, but on subsequent iterations it is + the root of the subtree below the currently processed subtree. */ + wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); + sig += SPX_WOTS_BYTES; + + /* Compute the leaf node using the WOTS public key. */ + thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); + + /* Compute the root node of this subtree. */ + compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, + &ctx, tree_addr); + sig += SPX_TREE_HEIGHT * SPX_N; + + /* Update the indices for the next layer. */ + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; + } + + // cleanup + free_hash_function(&ctx); + + /* Check if the root node equals the root node in the public key. */ + if (memcmp(root, pub_root, SPX_N) != 0) { + return -1; + } + + return 0; +} + + +/** + * Returns an array containing the signature followed by the message. + */ +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk) { + size_t siglen; + + crypto_sign_signature(sm, &siglen, m, mlen, sk); + + memmove(sm + SPX_BYTES, m, mlen); + *smlen = siglen + mlen; + + return 0; +} + +/** + * Verifies a given signature-message pair under a given public key. + */ +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk) { + /* The API caller does not necessarily know what size a signature should be + but SPHINCS+ signatures are always exactly SPX_BYTES. */ + if (smlen < SPX_BYTES) { + memset(m, 0, smlen); + *mlen = 0; + return -1; + } + + *mlen = smlen - SPX_BYTES; + + if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { + memset(m, 0, smlen); + *mlen = 0; + return -1; + } + + /* If verification was successful, move the message to the right place. */ + memmove(m, sm + SPX_BYTES, *mlen); + + return 0; +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/thash.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/thash.h new file mode 100644 index 0000000000..8687ccfb4d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/thash.h @@ -0,0 +1,13 @@ +#ifndef SPX_THASH_H +#define SPX_THASH_H + +#include "context.h" +#include "params.h" + +#include + +#define thash SPX_NAMESPACE(thash) +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/thash_shake_robustx2.c b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/thash_shake_robustx2.c new file mode 100644 index 0000000000..454fc0f4e2 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/thash_shake_robustx2.c @@ -0,0 +1,112 @@ +#include +#include + +#include "thash.h" +#include "thashx2.h" + +#include "address.h" +#include "params.h" +#include "utils.h" + +#include "f1600x2.h" +#include "fips202x2.h" + + +void thash(unsigned char *out, + const unsigned char *in, + unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]) { + uint32_t addrx2 [2 * 8] = { + addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], addr[6], addr[7], + addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], addr[6], addr[7] + }; + thashx2(out, out, in, in, inblocks, ctx, addrx2); +} + +/** + * 2-way parallel version of thash; takes 2x as much input and output + */ +void thashx2(unsigned char *out0, + unsigned char *out1, + const unsigned char *in0, + const unsigned char *in1, + unsigned int inblocks, + const spx_ctx *ctx, uint32_t addrx2[2 * 8]) { + if (inblocks == 1 || inblocks == 2) { + /* As we write and read only a few quadwords, it is more efficient to + * build and extract from the twoway SHAKE256 state by hand. */ + uint64_t state[50] = {0}; + uint64_t state2[50]; + + for (int i = 0; i < SPX_N / 8; i++) { + uint64_t x = load64(ctx->pub_seed + 8 * i); + state[2 * i] = x; + state[2 * i + 1] = x; + } + for (int i = 0; i < 4; i++) { + state[2 * (SPX_N / 8 + i)] = (((uint64_t)addrx2[1 + 2 * i]) << 32) + | (uint64_t)addrx2[2 * i]; + state[2 * (SPX_N / 8 + i) + 1] = (((uint64_t)addrx2[8 + 1 + 2 * i]) << 32) + | (uint64_t)addrx2[8 + 2 * i]; + } + + /* Domain separator and padding. */ + state[2 * 16] = 0x80ULL << 56; + state[2 * 16 + 1] = 0x80ULL << 56; + + state[2 * ((SPX_N / 8) + 4)] ^= 0x1f; + state[2 * ((SPX_N / 8) + 4) + 1] ^= 0x1f; + + /* We will permutate state2 with f1600x2 to compute the bitmask, + * but first we'll copy it to state2 which will be used to compute + * the final output, as its input is almost identical. */ + memcpy(state2, state, 400); + + f1600x2(state); + + /* By copying from state, state2 already contains the pub_seed + * and address. We just need to copy in the input blocks xorred with + * the bitmask we just computed. */ + for (unsigned int i = 0; i < (SPX_N / 8) * inblocks; i++) { + state2[2 * (SPX_N / 8 + 4 + i)] = state[2 * i] ^ load64(in0 + 8 * i); + state2[2 * (SPX_N / 8 + 4 + i) + 1] = state[2 * i + 1] ^ load64(in1 + 8 * i); + } + + /* Domain separator and start of padding. Note that the quadwords + * around are already zeroed for state from which we copied. + * We do a XOR instead of a set as this might be the 16th quadword + * when N=32 and inblocks=2, which already contains the end + * of the padding. */ + state2[2 * ((SPX_N / 8) * (1 + inblocks) + 4)] ^= 0x1f; + state2[2 * ((SPX_N / 8) * (1 + inblocks) + 4) + 1] ^= 0x1f; + + f1600x2(state2); + + for (int i = 0; i < SPX_N / 8; i++) { + store64(out0 + 8 * i, state2[2 * i]); + store64(out1 + 8 * i, state2[2 * i + 1]); + } + } else { + PQCLEAN_VLA(unsigned char, buf0, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, buf1, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, bitmask0, inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, bitmask1, inblocks * SPX_N); + unsigned int i; + + memcpy(buf0, ctx->pub_seed, SPX_N); + memcpy(buf1, ctx->pub_seed, SPX_N); + memcpy(buf0 + SPX_N, addrx2 + 0 * 8, SPX_ADDR_BYTES); + memcpy(buf1 + SPX_N, addrx2 + 1 * 8, SPX_ADDR_BYTES); + + shake256x2(bitmask0, bitmask1, inblocks * SPX_N, + buf0, buf1, SPX_N + SPX_ADDR_BYTES); + + for (i = 0; i < inblocks * SPX_N; i++) { + buf0[SPX_N + SPX_ADDR_BYTES + i] = in0[i] ^ bitmask0[i]; + buf1[SPX_N + SPX_ADDR_BYTES + i] = in1[i] ^ bitmask1[i]; + } + + shake256x2(out0, out1, SPX_N, + buf0, buf1, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/thashx2.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/thashx2.h new file mode 100644 index 0000000000..040375e618 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/thashx2.h @@ -0,0 +1,16 @@ +#ifndef SPX_THASHX2_H +#define SPX_THASHX2_H + +#include "context.h" +#include "params.h" +#include + +#define thashx2 SPX_NAMESPACE(thashx2) +void thashx2(unsigned char *out0, + unsigned char *out1, + const unsigned char *in0, + const unsigned char *in1, + unsigned int inblocks, + const spx_ctx *ctx, uint32_t addrx2[2 * 8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/utils.c b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/utils.c new file mode 100644 index 0000000000..177b541fb9 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/utils.c @@ -0,0 +1,148 @@ +#include + +#include "utils.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "thash.h" + +/** + * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. + */ +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in) { + int i; + + /* Iterate over out in decreasing order, for big-endianness. */ + for (i = (signed int)outlen - 1; i >= 0; i--) { + out[i] = in & 0xff; + in = in >> 8; + } +} + +void u32_to_bytes(unsigned char *out, uint32_t in) { + out[0] = (unsigned char)(in >> 24); + out[1] = (unsigned char)(in >> 16); + out[2] = (unsigned char)(in >> 8); + out[3] = (unsigned char)in; +} + +/** + * Converts the inlen bytes in 'in' from big-endian byte order to an integer. + */ +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { + unsigned long long retval = 0; + unsigned int i; + + for (i = 0; i < inlen; i++) { + retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); + } + return retval; +} + +/** + * Computes a root node given a leaf and an auth path. + * Expects address to be complete other than the tree_height and tree_index. + */ +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]) { + uint32_t i; + unsigned char buffer[2 * SPX_N]; + + /* If leaf_idx is odd (last bit = 1), current path element is a right child + and auth_path has to go left. Otherwise it is the other way around. */ + if (leaf_idx & 1) { + memcpy(buffer + SPX_N, leaf, SPX_N); + memcpy(buffer, auth_path, SPX_N); + } else { + memcpy(buffer, leaf, SPX_N); + memcpy(buffer + SPX_N, auth_path, SPX_N); + } + auth_path += SPX_N; + + for (i = 0; i < tree_height - 1; i++) { + leaf_idx >>= 1; + idx_offset >>= 1; + /* Set the address of the node we're creating. */ + set_tree_height(addr, i + 1); + set_tree_index(addr, leaf_idx + idx_offset); + + /* Pick the right or left neighbor, depending on parity of the node. */ + if (leaf_idx & 1) { + thash(buffer + SPX_N, buffer, 2, ctx, addr); + memcpy(buffer, auth_path, SPX_N); + } else { + thash(buffer, buffer, 2, ctx, addr); + memcpy(buffer + SPX_N, auth_path, SPX_N); + } + auth_path += SPX_N; + } + + /* The last iteration is exceptional; we do not copy an auth_path node. */ + leaf_idx >>= 1; + idx_offset >>= 1; + set_tree_height(addr, tree_height); + set_tree_index(addr, leaf_idx + idx_offset); + thash(root, buffer, 2, ctx, addr); +} + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx * /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]) { + PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); + PQCLEAN_VLA(unsigned int, heights, tree_height + 1); + unsigned int offset = 0; + uint32_t idx; + uint32_t tree_idx; + + for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { + /* Add the next leaf node to the stack. */ + gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); + offset++; + heights[offset - 1] = 0; + + /* If this is a node we need for the auth path.. */ + if ((leaf_idx ^ 0x1) == idx) { + memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); + } + + /* While the top-most nodes are of equal height.. */ + while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { + /* Compute index of the new node, in the next layer. */ + tree_idx = (idx >> (heights[offset - 1] + 1)); + + /* Set the address of the node we're creating. */ + set_tree_height(tree_addr, heights[offset - 1] + 1); + set_tree_index(tree_addr, + tree_idx + (idx_offset >> (heights[offset - 1] + 1))); + /* Hash the top-most nodes from the stack together. */ + thash(stack + (offset - 2)*SPX_N, + stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); + offset--; + /* Note that the top-most node is now one layer higher. */ + heights[offset - 1]++; + + /* If this is a node we need for the auth path.. */ + if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { + memcpy(auth_path + heights[offset - 1]*SPX_N, + stack + (offset - 1)*SPX_N, SPX_N); + } + } + } + memcpy(root, stack, SPX_N); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/utils.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/utils.h new file mode 100644 index 0000000000..64f5d5a53a --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/utils.h @@ -0,0 +1,58 @@ +#ifndef SPX_UTILS_H +#define SPX_UTILS_H + +#include + +#include "compat.h" +#include "context.h" +#include "params.h" + + +/* To support MSVC use alloca() instead of VLAs. See #20. */ + + +/** + * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. + */ +#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in); +#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) +void u32_to_bytes(unsigned char *out, uint32_t in); + +/** + * Converts the inlen bytes in 'in' from big-endian byte order to an integer. + */ +#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); + +/** + * Computes a root node given a leaf and an auth path. + * Expects address to be complete other than the tree_height and tree_index. + */ +#define compute_root SPX_NAMESPACE(compute_root) +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]); + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +#define treehash SPX_NAMESPACE(treehash) +void treehash(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx *ctx /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]); + + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/utilsx2.c b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/utilsx2.c new file mode 100644 index 0000000000..8736474e4f --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/utilsx2.c @@ -0,0 +1,130 @@ +#include + +#include "utilsx2.h" + +#include "address.h" +#include "params.h" +#include "thashx2.h" +#include "utils.h" + +/* + * Generate the entire Merkle tree, computing the authentication path for leaf_idx, + * and the resulting root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) + * + * This expects tree_addrx2 to be initialized to 2 parallel addr structures for + * the Merkle tree nodes + * + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + * + * This works by using the standard Merkle tree building algorithm, except + * that each 'node' tracked is actually 2 consecutive nodes in the real tree. + * When we combine two logical nodes AB and WX, we perform the H + * operation on adjacent real nodes, forming the parent logical node + * (AB)(WX) + * + * When we get to the top level of the real tree (where there is only + * one logical node), we continue this operation one more time; the right + * most real node will by the actual root (and the other node will be + * garbage). We follow the same thashx2 logic so that the 'extract + * authentication path components' part of the loop is still executed (and + * to simplify the code somewhat) + */ +void treehashx2(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, + uint32_t tree_height, + void (*gen_leafx2)( + unsigned char * /* Where to write the leaves */, + const spx_ctx *, + uint32_t idx, void *info), + uint32_t tree_addrx2[2 * 8], + void *info) { + /* This is where we keep the intermediate nodes */ + unsigned char stackx2[tree_height * 2 * SPX_N]; + uint32_t left_adj = 0, prev_left_adj = 0; /* When we're doing the top */ + /* level, the left-most part of the tree isn't at the beginning */ + /* of current[]. These give the offset of the actual start */ + + uint32_t idx; + uint32_t max_idx = (1 << (tree_height - 1)) - 1; + for (idx = 0;; idx++) { + unsigned char current[2 * SPX_N]; /* Current logical node */ + gen_leafx2( current, ctx, 2 * idx + idx_offset, + info ); + + /* Now combine the freshly generated right node with previously */ + /* generated left ones */ + uint32_t internal_idx_offset = idx_offset; + uint32_t internal_idx = idx; + uint32_t internal_leaf = leaf_idx; + uint32_t h; /* The height we are in the Merkle tree */ + for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { + + /* Special processing if we're at the top of the tree */ + if (h >= tree_height - 1) { + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[1 * SPX_N], SPX_N ); + return; + } + /* The tree indexing logic is a bit off in this case */ + /* Adjust it so that the left-most node of the part of */ + /* the tree that we're processing has index 0 */ + prev_left_adj = left_adj; + left_adj = 2 - (1 << (tree_height - h - 1)); + } + + /* Check if we hit the top of the tree */ + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[1 * SPX_N], SPX_N ); + return; + } + + /* + * Check if one of the nodes we have is a part of the + * authentication path; if it is, write it out + */ + if ((((internal_idx << 1) ^ internal_leaf) & ~0x1) == 0) { + memcpy( &auth_path[ h * SPX_N ], + ¤t[(((internal_leaf & 1) ^ 1) + prev_left_adj) * SPX_N], + SPX_N ); + } + + /* + * Check if we're at a left child; if so, stop going up the stack + * Exception: if we've reached the end of the tree, keep on going + * (so we combine the last 2 nodes into the one root node in two + * more iterations) + */ + if ((internal_idx & 1) == 0 && idx < max_idx) { + break; + } + + /* Ok, we're at a right node (or doing the top 3 levels) */ + /* Now combine the left and right logical nodes together */ + + /* Set the address of the node we're creating. */ + int j; + internal_idx_offset >>= 1; + for (j = 0; j < 2; j++) { + set_tree_height(tree_addrx2 + j * 8, h + 1); + set_tree_index(tree_addrx2 + j * 8, + (2 / 2) * (internal_idx & ~1) + j - left_adj + internal_idx_offset ); + } + unsigned char *left = &stackx2[h * 2 * SPX_N]; + thashx2( ¤t[0 * SPX_N], + ¤t[1 * SPX_N], + &left [0 * SPX_N], + ¤t[0 * SPX_N], + 2, ctx, tree_addrx2); + } + + /* We've hit a left child; save the current for when we get the */ + /* corresponding right right */ + memcpy( &stackx2[h * 2 * SPX_N], current, 2 * SPX_N); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/utilsx2.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/utilsx2.h new file mode 100644 index 0000000000..e09faddc43 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/utilsx2.h @@ -0,0 +1,30 @@ +#ifndef SPX_UTILSX2_H +#define SPX_UTILSX2_H + +#include + +#include "context.h" +#include "params.h" + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + * + * This implementation uses SIMD to compute internal nodes 2 at a time (in + * parallel) + */ +#define treehashx2 SPX_NAMESPACE(treehashx2) +void treehashx2(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leafx2)( + unsigned char * /* Where to write the leaves */, + const spx_ctx * /* ctx */, + uint32_t addr_idx, void *info), + uint32_t tree_addrx2[2 * 8], void *info); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/wots.c b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/wots.c new file mode 100644 index 0000000000..3babe45e95 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/wots.c @@ -0,0 +1,259 @@ +#include +#include + +#include "wots.h" +#include "wotsx2.h" + +#include "address.h" +#include "hash.h" +#include "hashx2.h" +#include "params.h" +#include "thashx2.h" +#include "utils.h" +#include "utilsx2.h" + +// TODO clarify address expectations, and make them more uniform. +// TODO i.e. do we expect types to be set already? +// TODO and do we expect modifications or copies? + +/** + * Computes up the chains + */ +static void gen_chains( + unsigned char *out, + const unsigned char *in, + unsigned int start[SPX_WOTS_LEN], + const unsigned int steps[SPX_WOTS_LEN], + const spx_ctx *ctx, + uint32_t addr[8]) { + uint32_t i, j, k, idx, watching; + int done; + unsigned char empty[SPX_N]; + unsigned char *bufs[4]; + uint32_t addrs[8 * 2]; + + int l; + uint16_t counts[SPX_WOTS_W] = { 0 }; + uint16_t idxs[SPX_WOTS_LEN]; + uint16_t total, newTotal; + + /* set addrs = {addr, addr} */ + for (j = 0; j < 2; j++) { + memcpy(addrs + j * 8, addr, sizeof(uint32_t) * 8); + } + + /* Initialize out with the value at position 'start'. */ + memcpy(out, in, SPX_WOTS_LEN * SPX_N); + + /* Sort the chains in reverse order by steps using counting sort. */ + for (i = 0; i < SPX_WOTS_LEN; i++) { + counts[steps[i]]++; + } + total = 0; + for (l = SPX_WOTS_W - 1; l >= 0; l--) { + newTotal = counts[l] + total; + counts[l] = total; + total = newTotal; + } + for (i = 0; i < SPX_WOTS_LEN; i++) { + idxs[counts[steps[i]]] = i; + counts[steps[i]]++; + } + + /* We got our work cut out for us: do it! */ + for (i = 0; i < SPX_WOTS_LEN; i += 2) { + for (j = 0; j < 2 && i + j < SPX_WOTS_LEN; j++) { + idx = idxs[i + j]; + set_chain_addr(addrs + j * 8, idx); + bufs[j] = out + SPX_N * idx; + } + + /* As the chains are sorted in reverse order, we know that the first + * chain is the longest and the last one is the shortest. We keep + * an eye on whether the last chain is done and then on the one before, + * et cetera. */ + watching = 1; + done = 0; + while (i + watching >= SPX_WOTS_LEN) { + bufs[watching] = &empty[0]; + watching--; + } + + for (k = 0;; k++) { + while (k == steps[idxs[i + watching]]) { + bufs[watching] = &empty[0]; + if (watching == 0) { + done = 1; + break; + } + watching--; + } + if (done) { + break; + } + for (j = 0; j < watching + 1; j++) { + set_hash_addr(addrs + j * 8, k + start[idxs[i + j]]); + } + + thashx2(bufs[0], bufs[1], + bufs[0], bufs[1], 1, ctx, addrs); + } + } +} + +/** + * base_w algorithm as described in draft. + * Interprets an array of bytes as integers in base w. + * This only works when log_w is a divisor of 8. + */ +static void base_w(unsigned int *output, const int out_len, + const unsigned char *input) { + int in = 0; + int out = 0; + unsigned char total = 0; + int bits = 0; + int consumed; + + for (consumed = 0; consumed < out_len; consumed++) { + if (bits == 0) { + total = input[in]; + in++; + bits += 8; + } + bits -= SPX_WOTS_LOGW; + output[out] = (total >> bits) & (SPX_WOTS_W - 1); + out++; + } +} + +/* Computes the WOTS+ checksum over a message (in base_w). */ +static void wots_checksum(unsigned int *csum_base_w, + const unsigned int *msg_base_w) { + unsigned int csum = 0; + unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; + unsigned int i; + + /* Compute checksum. */ + for (i = 0; i < SPX_WOTS_LEN1; i++) { + csum += SPX_WOTS_W - 1 - msg_base_w[i]; + } + + /* Convert checksum to base_w. */ + /* Make sure expected empty zero bits are the least significant bits. */ + csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); + ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); + base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); +} + +/* Takes a message and derives the matching chain lengths. */ +void chain_lengths(unsigned int *lengths, const unsigned char *msg) { + base_w(lengths, SPX_WOTS_LEN1, msg); + wots_checksum(lengths + SPX_WOTS_LEN1, lengths); +} + +/** + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. + * + * Writes the computed public key to 'pk'. + */ +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]) { + unsigned int steps[SPX_WOTS_LEN]; + unsigned int start[SPX_WOTS_LEN]; + uint32_t i; + + chain_lengths(start, msg); + + for (i = 0; i < SPX_WOTS_LEN; i++) { + steps[i] = SPX_WOTS_W - 1 - start[i]; + } + + gen_chains(pk, sig, start, steps, ctx, addr); +} + +/* + * This generates 2 sequential WOTS public keys + * It also generates the WOTS signature if leaf_info indicates + * that we're signing with one of these WOTS keys + */ +void wots_gen_leafx2(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info) { + struct leaf_info_x2 *info = v_info; + uint32_t *leaf_addr = info->leaf_addr; + uint32_t *pk_addr = info->pk_addr; + unsigned int i, j, k; + unsigned char pk_buffer[ 2 * SPX_WOTS_BYTES ]; + unsigned wots_offset = SPX_WOTS_BYTES; + unsigned char *buffer; + uint32_t wots_k_mask; + unsigned wots_sign_index; + + if (((leaf_idx ^ info->wots_sign_leaf) & ~1) == 0) { + /* We're traversing the leaf that's signing; generate the WOTS */ + /* signature */ + wots_k_mask = 0; + wots_sign_index = info->wots_sign_leaf & 1; /* Which of of the 2 */ + /* slots do the signatures come from */ + } else { + /* Nope, we're just generating pk's; turn off the signature logic */ + wots_k_mask = ~0; + wots_sign_index = 0; + } + + for (j = 0; j < 2; j++) { + set_keypair_addr( leaf_addr + j * 8, leaf_idx + j ); + set_keypair_addr( pk_addr + j * 8, leaf_idx + j ); + } + + for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { + uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k to */ + /* the step if we're generating a signature, ~0 if we're not */ + + /* Start with the secret seed */ + for (j = 0; j < 2; j++) { + set_chain_addr(leaf_addr + j * 8, i); + set_hash_addr(leaf_addr + j * 8, 0); + set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTSPRF); + } + prf_addrx2(buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + ctx, leaf_addr); + for (j = 0; j < 2; j++) { + set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTS); + } + + /* Iterate down the WOTS chain */ + for (k = 0;; k++) { + /* Check if one of the values we have needs to be saved as a */ + /* part of the WOTS signature */ + if (k == wots_k) { + memcpy( info->wots_sig + i * SPX_N, + buffer + wots_sign_index * wots_offset, SPX_N ); + } + + /* Check if we hit the top of the chain */ + if (k == SPX_WOTS_W - 1) { + break; + } + + /* Iterate one step on all 4 chains */ + for (j = 0; j < 2; j++) { + set_hash_addr(leaf_addr + j * 8, k); + } + thashx2(buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + 1, ctx, leaf_addr); + } + } + + /* Do the final thash to generate the public keys */ + thashx2(dest + 0 * SPX_N, + dest + 1 * SPX_N, + pk_buffer + 0 * wots_offset, + pk_buffer + 1 * wots_offset, + SPX_WOTS_LEN, ctx, pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/wots.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/wots.h new file mode 100644 index 0000000000..4e7692eeef --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/wots.h @@ -0,0 +1,25 @@ +#ifndef SPX_WOTS_H +#define SPX_WOTS_H + +#include + +#include "context.h" +#include "params.h" + +/** + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. + * + * Writes the computed public key to 'pk'. + */ +#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]); + +/* + * Compute the chain lengths needed for a given message hash + */ +#define chain_lengths SPX_NAMESPACE(chain_lengths) +void chain_lengths(unsigned int *lengths, const unsigned char *msg); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/wotsx2.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/wotsx2.h new file mode 100644 index 0000000000..b58bb61f84 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/wotsx2.h @@ -0,0 +1,40 @@ +#ifndef WOTSX2_H_ +#define WOTSX2_H_ + +#include "params.h" +#include + +/* + * This is here to provide an interface to the internal wots_gen_leafx2 + * routine. While this routine is not referenced in the package outside of + * wots.c, it is called from the stand-alone benchmark code to characterize + * the performance + */ +struct leaf_info_x2 { + unsigned char *wots_sig; + uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ + uint32_t *wots_steps; + uint32_t leaf_addr[2 * 8]; + uint32_t pk_addr[2 * 8]; +}; + +/* Macro to set the leaf_info to something 'benign', that is, it would */ +/* run with the same time as it does during the real signing process */ +/* Used only by the benchmark code */ +#define INITIALIZE_LEAF_INFO_X2(info, addr, step_buffer) { \ + (info).wots_sig = 0; \ + (info).wots_sign_leaf = ~0; \ + (info).wots_steps = step_buffer; \ + int i; \ + for (i=0; i<2; i++) { \ + memcpy( &(info).leaf_addr[8*i], addr, 32 ); \ + memcpy( &(info).pk_addr[8*i], addr, 32 ); \ + } \ + } + +#define wots_gen_leafx2 SPX_NAMESPACE(wots_gen_leafx2) +void wots_gen_leafx2(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info); + +#endif /* WOTSX2_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/LICENSE b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/LICENSE new file mode 100644 index 0000000000..670154e353 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/LICENSE @@ -0,0 +1,116 @@ +CC0 1.0 Universal + +Statement of Purpose + +The laws of most jurisdictions throughout the world automatically confer +exclusive Copyright and Related Rights (defined below) upon the creator and +subsequent owner(s) (each and all, an "owner") of an original work of +authorship and/or a database (each, a "Work"). + +Certain owners wish to permanently relinquish those rights to a Work for the +purpose of contributing to a commons of creative, cultural and scientific +works ("Commons") that the public can reliably and without fear of later +claims of infringement build upon, modify, incorporate in other works, reuse +and redistribute as freely as possible in any form whatsoever and for any +purposes, including without limitation commercial purposes. These owners may +contribute to the Commons to promote the ideal of a free culture and the +further production of creative, cultural and scientific works, or to gain +reputation or greater distribution for their Work in part through the use and +efforts of others. + +For these and/or other purposes and motivations, and without any expectation +of additional consideration or compensation, the person associating CC0 with a +Work (the "Affirmer"), to the extent that he or she is an owner of Copyright +and Related Rights in the Work, voluntarily elects to apply CC0 to the Work +and publicly distribute the Work under its terms, with knowledge of his or her +Copyright and Related Rights in the Work and the meaning and intended legal +effect of CC0 on those rights. + +1. Copyright and Related Rights. A Work made available under CC0 may be +protected by copyright and related or neighboring rights ("Copyright and +Related Rights"). Copyright and Related Rights include, but are not limited +to, the following: + + i. the right to reproduce, adapt, distribute, perform, display, communicate, + and translate a Work; + + ii. moral rights retained by the original author(s) and/or performer(s); + + iii. publicity and privacy rights pertaining to a person's image or likeness + depicted in a Work; + + iv. rights protecting against unfair competition in regards to a Work, + subject to the limitations in paragraph 4(a), below; + + v. rights protecting the extraction, dissemination, use and reuse of data in + a Work; + + vi. database rights (such as those arising under Directive 96/9/EC of the + European Parliament and of the Council of 11 March 1996 on the legal + protection of databases, and under any national implementation thereof, + including any amended or successor version of such directive); and + + vii. other similar, equivalent or corresponding rights throughout the world + based on applicable law or treaty, and any national implementations thereof. + +2. Waiver. To the greatest extent permitted by, but not in contravention of, +applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and +unconditionally waives, abandons, and surrenders all of Affirmer's Copyright +and Related Rights and associated claims and causes of action, whether now +known or unknown (including existing as well as future claims and causes of +action), in the Work (i) in all territories worldwide, (ii) for the maximum +duration provided by applicable law or treaty (including future time +extensions), (iii) in any current or future medium and for any number of +copies, and (iv) for any purpose whatsoever, including without limitation +commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes +the Waiver for the benefit of each member of the public at large and to the +detriment of Affirmer's heirs and successors, fully intending that such Waiver +shall not be subject to revocation, rescission, cancellation, termination, or +any other legal or equitable action to disrupt the quiet enjoyment of the Work +by the public as contemplated by Affirmer's express Statement of Purpose. + +3. Public License Fallback. Should any part of the Waiver for any reason be +judged legally invalid or ineffective under applicable law, then the Waiver +shall be preserved to the maximum extent permitted taking into account +Affirmer's express Statement of Purpose. In addition, to the extent the Waiver +is so judged Affirmer hereby grants to each affected person a royalty-free, +non transferable, non sublicensable, non exclusive, irrevocable and +unconditional license to exercise Affirmer's Copyright and Related Rights in +the Work (i) in all territories worldwide, (ii) for the maximum duration +provided by applicable law or treaty (including future time extensions), (iii) +in any current or future medium and for any number of copies, and (iv) for any +purpose whatsoever, including without limitation commercial, advertising or +promotional purposes (the "License"). The License shall be deemed effective as +of the date CC0 was applied by Affirmer to the Work. Should any part of the +License for any reason be judged legally invalid or ineffective under +applicable law, such partial invalidity or ineffectiveness shall not +invalidate the remainder of the License, and in such case Affirmer hereby +affirms that he or she will not (i) exercise any of his or her remaining +Copyright and Related Rights in the Work or (ii) assert any associated claims +and causes of action with respect to the Work, in either case contrary to +Affirmer's express Statement of Purpose. + +4. Limitations and Disclaimers. + + a. No trademark or patent rights held by Affirmer are waived, abandoned, + surrendered, licensed or otherwise affected by this document. + + b. Affirmer offers the Work as-is and makes no representations or warranties + of any kind concerning the Work, express, implied, statutory or otherwise, + including without limitation warranties of title, merchantability, fitness + for a particular purpose, non infringement, or the absence of latent or + other defects, accuracy, or the present or absence of errors, whether or not + discoverable, all to the greatest extent permissible under applicable law. + + c. Affirmer disclaims responsibility for clearing rights of other persons + that may apply to the Work or any use thereof, including without limitation + any person's Copyright and Related Rights in the Work. Further, Affirmer + disclaims responsibility for obtaining any necessary consents, permissions + or other rights required for any use of the Work. + + d. Affirmer understands and acknowledges that Creative Commons is not a + party to this document and has no duty or obligation with respect to this + CC0 or use of the Work. + +For more information, please see + diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/address.c b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/address.c new file mode 100644 index 0000000000..b956e9cb29 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/address.c @@ -0,0 +1,91 @@ +#include +#include + +#include "address.h" +#include "params.h" +#include "utils.h" + +/* + * Specify which level of Merkle tree (the "layer") we're working on + */ +void set_layer_addr(uint32_t addr[8], uint32_t layer) { + ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; +} + +/* + * Specify which Merkle tree within the level (the "tree address") we're working on + */ +void set_tree_addr(uint32_t addr[8], uint64_t tree) { + ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); +} + +/* + * Specify the reason we'll use this address structure for, that is, what + * hash will we compute with it. This is used so that unrelated types of + * hashes don't accidentally get the same address structure. The type will be + * one of the SPX_ADDR_TYPE constants + */ +void set_type(uint32_t addr[8], uint32_t type) { + ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; +} + +/* + * Copy the layer and tree fields of the address structure. This is used + * when we're doing multiple types of hashes within the same Merkle tree + */ +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); +} + +/* These functions are used for OTS addresses. */ + +/* + * Specify which Merkle leaf we're working on; that is, which OTS keypair + * we're talking about. + */ +void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { + ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; +} + +/* + * Copy the layer, tree and keypair fields of the address structure. This is + * used when we're doing multiple things within the same OTS keypair + */ +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); + ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; +} + +/* + * Specify which Merkle chain within the OTS we're working with + * (the chain address) + */ +void set_chain_addr(uint32_t addr[8], uint32_t chain) { + ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; +} + +/* + * Specify where in the Merkle chain we are +* (the hash address) + */ +void set_hash_addr(uint32_t addr[8], uint32_t hash) { + ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; +} + +/* These functions are used for all hash tree addresses (including FORS). */ + +/* + * Specify the height of the node in the Merkle/FORS tree we are in + * (the tree height) + */ +void set_tree_height(uint32_t addr[8], uint32_t tree_height) { + ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; +} + +/* + * Specify the distance from the left edge of the node in the Merkle/FORS tree + * (the tree index) + */ +void set_tree_index(uint32_t addr[8], uint32_t tree_index) { + u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/address.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/address.h new file mode 100644 index 0000000000..24a84eb40c --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/address.h @@ -0,0 +1,52 @@ +#ifndef SPX_ADDRESS_H +#define SPX_ADDRESS_H + +#include + +#include "params.h" + +/* The hash types that are passed to set_type */ +#define SPX_ADDR_TYPE_WOTS 0 +#define SPX_ADDR_TYPE_WOTSPK 1 +#define SPX_ADDR_TYPE_HASHTREE 2 +#define SPX_ADDR_TYPE_FORSTREE 3 +#define SPX_ADDR_TYPE_FORSPK 4 +#define SPX_ADDR_TYPE_WOTSPRF 5 +#define SPX_ADDR_TYPE_FORSPRF 6 + +#define set_layer_addr SPX_NAMESPACE(set_layer_addr) +void set_layer_addr(uint32_t addr[8], uint32_t layer); + +#define set_tree_addr SPX_NAMESPACE(set_tree_addr) +void set_tree_addr(uint32_t addr[8], uint64_t tree); + +#define set_type SPX_NAMESPACE(set_type) +void set_type(uint32_t addr[8], uint32_t type); + +/* Copies the layer and tree part of one address into the other */ +#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); + +/* These functions are used for WOTS and FORS addresses. */ + +#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) +void set_keypair_addr(uint32_t addr[8], uint32_t keypair); + +#define set_chain_addr SPX_NAMESPACE(set_chain_addr) +void set_chain_addr(uint32_t addr[8], uint32_t chain); + +#define set_hash_addr SPX_NAMESPACE(set_hash_addr) +void set_hash_addr(uint32_t addr[8], uint32_t hash); + +#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); + +/* These functions are used for all hash tree addresses (including FORS). */ + +#define set_tree_height SPX_NAMESPACE(set_tree_height) +void set_tree_height(uint32_t addr[8], uint32_t tree_height); + +#define set_tree_index SPX_NAMESPACE(set_tree_index) +void set_tree_index(uint32_t addr[8], uint32_t tree_index); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/api.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/api.h new file mode 100644 index 0000000000..5c0a570b8c --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/api.h @@ -0,0 +1,77 @@ +#ifndef PQCLEAN_SPHINCSSHAKE128FROBUST_AVX2_API_H +#define PQCLEAN_SPHINCSSHAKE128FROBUST_AVX2_API_H + +#include +#include + +#define PQCLEAN_SPHINCSSHAKE128FROBUST_AVX2_CRYPTO_ALGNAME "SPHINCS+-shake-128f-robust" + +#define PQCLEAN_SPHINCSSHAKE128FROBUST_AVX2_CRYPTO_SECRETKEYBYTES 64 +#define PQCLEAN_SPHINCSSHAKE128FROBUST_AVX2_CRYPTO_PUBLICKEYBYTES 32 +#define PQCLEAN_SPHINCSSHAKE128FROBUST_AVX2_CRYPTO_BYTES 17088 + +#define PQCLEAN_SPHINCSSHAKE128FROBUST_AVX2_CRYPTO_SEEDBYTES 48 + +/* + * Returns the length of a secret key, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE128FROBUST_AVX2_crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE128FROBUST_AVX2_crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE128FROBUST_AVX2_crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE128FROBUST_AVX2_crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +int PQCLEAN_SPHINCSSHAKE128FROBUST_AVX2_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +int PQCLEAN_SPHINCSSHAKE128FROBUST_AVX2_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +int PQCLEAN_SPHINCSSHAKE128FROBUST_AVX2_crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +int PQCLEAN_SPHINCSSHAKE128FROBUST_AVX2_crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, + const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +int PQCLEAN_SPHINCSSHAKE128FROBUST_AVX2_crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +int PQCLEAN_SPHINCSSHAKE128FROBUST_AVX2_crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/context.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/context.h new file mode 100644 index 0000000000..6e0a33f3b7 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/context.h @@ -0,0 +1,19 @@ +#ifndef SPX_CONTEXT_H +#define SPX_CONTEXT_H + +#include + +#include "params.h" + +typedef struct { + uint8_t pub_seed[SPX_N]; + uint8_t sk_seed[SPX_N]; +} spx_ctx; + +#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) +void initialize_hash_function(spx_ctx *ctx); + +#define free_hash_function SPX_NAMESPACE(free_hash_function) +void free_hash_function(spx_ctx *ctx); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/context_shake.c b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/context_shake.c new file mode 100644 index 0000000000..9614a103d3 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/context_shake.c @@ -0,0 +1,12 @@ +#include "context.h" + +/* For SHAKE256, there is no immediate reason to initialize at the start, + so this function is an empty operation. */ +void initialize_hash_function(spx_ctx *ctx) { + (void)ctx; /* Suppress an 'unused parameter' warning. */ +} + +// in case the hash function api is heap-based. +void free_hash_function(spx_ctx *ctx) { + (void)ctx; +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/fips202x4.c b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/fips202x4.c new file mode 100644 index 0000000000..1e06fef186 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/fips202x4.c @@ -0,0 +1,210 @@ +#include +#include +#include + +#include "fips202.h" +#include "fips202x4.h" + +#define NROUNDS 24 +#define ROL(a, offset) (((a) << (offset)) ^ ((a) >> (64-(offset)))) + +static uint64_t load64(const unsigned char *x) { + unsigned long long r = 0, i; + + for (i = 0; i < 8; ++i) { + r |= (unsigned long long)x[i] << 8 * i; + } + return r; +} + +static void store64(uint8_t *x, uint64_t u) { + unsigned int i; + + for (i = 0; i < 8; ++i) { + x[i] = (uint8_t)u; + u >>= 8; + } +} + +/* Use implementation from the Keccak Code Package */ +extern void KeccakP1600times4_PermuteAll_24rounds(__m256i *s); +#define KeccakF1600_StatePermute4x KeccakP1600times4_PermuteAll_24rounds + +static void keccak_absorb4x(__m256i *s, + unsigned int r, + const unsigned char *m0, + const unsigned char *m1, + const unsigned char *m2, + const unsigned char *m3, + unsigned long long int mlen, + unsigned char p) { + unsigned long long i; + unsigned char t0[200]; + unsigned char t1[200]; + unsigned char t2[200]; + unsigned char t3[200]; + + unsigned long long *ss = (unsigned long long *)s; + + + while (mlen >= r) { + for (i = 0; i < r / 8; ++i) { + ss[4 * i + 0] ^= load64(m0 + 8 * i); + ss[4 * i + 1] ^= load64(m1 + 8 * i); + ss[4 * i + 2] ^= load64(m2 + 8 * i); + ss[4 * i + 3] ^= load64(m3 + 8 * i); + } + + KeccakF1600_StatePermute4x(s); + mlen -= r; + m0 += r; + m1 += r; + m2 += r; + m3 += r; + } + + for (i = 0; i < r; ++i) { + t0[i] = 0; + t1[i] = 0; + t2[i] = 0; + t3[i] = 0; + } + for (i = 0; i < mlen; ++i) { + t0[i] = m0[i]; + t1[i] = m1[i]; + t2[i] = m2[i]; + t3[i] = m3[i]; + } + + t0[i] = p; + t1[i] = p; + t2[i] = p; + t3[i] = p; + + t0[r - 1] |= 128; + t1[r - 1] |= 128; + t2[r - 1] |= 128; + t3[r - 1] |= 128; + + for (i = 0; i < r / 8; ++i) { + ss[4 * i + 0] ^= load64(t0 + 8 * i); + ss[4 * i + 1] ^= load64(t1 + 8 * i); + ss[4 * i + 2] ^= load64(t2 + 8 * i); + ss[4 * i + 3] ^= load64(t3 + 8 * i); + } +} + + +static void keccak_squeezeblocks4x(unsigned char *h0, + unsigned char *h1, + unsigned char *h2, + unsigned char *h3, + unsigned long long int nblocks, + __m256i *s, + unsigned int r) { + unsigned int i; + + unsigned long long *ss = (unsigned long long *)s; + + while (nblocks > 0) { + KeccakF1600_StatePermute4x(s); + for (i = 0; i < (r >> 3); i++) { + store64(h0 + 8 * i, ss[4 * i + 0]); + store64(h1 + 8 * i, ss[4 * i + 1]); + store64(h2 + 8 * i, ss[4 * i + 2]); + store64(h3 + 8 * i, ss[4 * i + 3]); + } + h0 += r; + h1 += r; + h2 += r; + h3 += r; + nblocks--; + } +} + + + +void shake128x4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, unsigned long long outlen, + unsigned char *in0, + unsigned char *in1, + unsigned char *in2, + unsigned char *in3, unsigned long long inlen) { + __m256i s[25]; + unsigned char t0[SHAKE128_RATE]; + unsigned char t1[SHAKE128_RATE]; + unsigned char t2[SHAKE128_RATE]; + unsigned char t3[SHAKE128_RATE]; + unsigned int i; + + /* zero state */ + for (i = 0; i < 25; i++) { + s[i] = _mm256_xor_si256(s[i], s[i]); + } + + /* absorb 4 message of identical length in parallel */ + keccak_absorb4x(s, SHAKE128_RATE, in0, in1, in2, in3, inlen, 0x1F); + + /* Squeeze output */ + keccak_squeezeblocks4x(out0, out1, out2, out3, outlen / SHAKE128_RATE, s, SHAKE128_RATE); + + out0 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; + out1 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; + out2 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; + out3 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; + + if (outlen % SHAKE128_RATE) { + keccak_squeezeblocks4x(t0, t1, t2, t3, 1, s, SHAKE128_RATE); + for (i = 0; i < outlen % SHAKE128_RATE; i++) { + out0[i] = t0[i]; + out1[i] = t1[i]; + out2[i] = t2[i]; + out3[i] = t3[i]; + } + } +} + + +void shake256x4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, unsigned long long outlen, + unsigned char *in0, + unsigned char *in1, + unsigned char *in2, + unsigned char *in3, unsigned long long inlen) { + __m256i s[25]; + unsigned char t0[SHAKE256_RATE]; + unsigned char t1[SHAKE256_RATE]; + unsigned char t2[SHAKE256_RATE]; + unsigned char t3[SHAKE256_RATE]; + unsigned int i; + + /* zero state */ + for (i = 0; i < 25; i++) { + s[i] = _mm256_xor_si256(s[i], s[i]); + } + + /* absorb 4 message of identical length in parallel */ + keccak_absorb4x(s, SHAKE256_RATE, in0, in1, in2, in3, inlen, 0x1F); + + /* Squeeze output */ + keccak_squeezeblocks4x(out0, out1, out2, out3, outlen / SHAKE256_RATE, s, SHAKE256_RATE); + + out0 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; + out1 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; + out2 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; + out3 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; + + if (outlen % SHAKE256_RATE) { + keccak_squeezeblocks4x(t0, t1, t2, t3, 1, s, SHAKE256_RATE); + for (i = 0; i < outlen % SHAKE256_RATE; i++) { + out0[i] = t0[i]; + out1[i] = t1[i]; + out2[i] = t2[i]; + out3[i] = t3[i]; + } + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/fips202x4.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/fips202x4.h new file mode 100644 index 0000000000..2b93c9cd0d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/fips202x4.h @@ -0,0 +1,28 @@ +#ifndef SPX_FIPS202X4_H +#define SPX_FIPS202X4_H + +#include + +#include "params.h" + +#define shake128x4 SPX_NAMESPACE(shake128x4) +void shake128x4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, unsigned long long outlen, + unsigned char *in0, + unsigned char *in1, + unsigned char *in2, + unsigned char *in3, unsigned long long inlen); + +#define shake256x4 SPX_NAMESPACE(shake256x4) +void shake256x4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, unsigned long long outlen, + unsigned char *in0, + unsigned char *in1, + unsigned char *in2, + unsigned char *in3, unsigned long long inlen); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/fors.c b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/fors.c new file mode 100644 index 0000000000..f1b0639cfc --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/fors.c @@ -0,0 +1,202 @@ +#include +#include +#include + +#include "fors.h" + +#include "address.h" +#include "hash.h" +#include "hashx4.h" +#include "thash.h" +#include "thashx4.h" +#include "utils.h" +#include "utilsx4.h" + +static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + prf_addr(sk, ctx, fors_leaf_addr); +} + +static void fors_gen_skx4(unsigned char *sk0, + unsigned char *sk1, + unsigned char *sk2, + unsigned char *sk3, const spx_ctx *ctx, + uint32_t fors_leaf_addrx4[4 * 8]) { + prf_addrx4(sk0, sk1, sk2, sk3, + ctx, fors_leaf_addrx4); +} + +static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, + const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + thash(leaf, sk, 1, ctx, fors_leaf_addr); +} + +static void fors_sk_to_leafx4(unsigned char *leaf0, + unsigned char *leaf1, + unsigned char *leaf2, + unsigned char *leaf3, + const unsigned char *sk0, + const unsigned char *sk1, + const unsigned char *sk2, + const unsigned char *sk3, + const spx_ctx *ctx, + uint32_t fors_leaf_addrx4[4 * 8]) { + thashx4(leaf0, leaf1, leaf2, leaf3, + sk0, sk1, sk2, sk3, + 1, ctx, fors_leaf_addrx4); +} + +struct fors_gen_leaf_info { + uint32_t leaf_addrx[4 * 8]; +}; + +static void fors_gen_leafx4(unsigned char *leaf, + const spx_ctx *ctx, + uint32_t addr_idx, void *info) { + struct fors_gen_leaf_info *fors_info = info; + uint32_t *fors_leaf_addrx4 = fors_info->leaf_addrx; + unsigned int j; + + /* Only set the parts that the caller doesn't set */ + for (j = 0; j < 4; j++) { + set_tree_index(fors_leaf_addrx4 + j * 8, addr_idx + j); + set_type(fors_leaf_addrx4 + j * 8, SPX_ADDR_TYPE_FORSPRF); + } + + fors_gen_skx4(leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + leaf + 2 * SPX_N, + leaf + 3 * SPX_N, + ctx, fors_leaf_addrx4); + + for (j = 0; j < 4; j++) { + set_type(fors_leaf_addrx4 + j * 8, SPX_ADDR_TYPE_FORSTREE); + } + + fors_sk_to_leafx4(leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + leaf + 2 * SPX_N, + leaf + 3 * SPX_N, + leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + leaf + 2 * SPX_N, + leaf + 3 * SPX_N, + ctx, fors_leaf_addrx4); +} + +/** + * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + * Assumes indices has space for SPX_FORS_TREES integers. + */ +static void message_to_indices(uint32_t *indices, const unsigned char *m) { + unsigned int i, j; + unsigned int offset = 0; + + for (i = 0; i < SPX_FORS_TREES; i++) { + indices[i] = 0; + for (j = 0; j < SPX_FORS_HEIGHT; j++) { + indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); + offset++; + } + } +} + +/** + * Signs a message m, deriving the secret key from sk_seed and the FTS address. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + uint32_t fors_tree_addr[4 * 8] = {0}; + struct fors_gen_leaf_info fors_info = {0}; + uint32_t *fors_leaf_addr = fors_info.leaf_addrx; + uint32_t fors_pk_addr[8] = {0}; + uint32_t idx_offset; + unsigned int i; + + for (i = 0; i < 4; i++) { + copy_keypair_addr(fors_tree_addr + 8 * i, fors_addr); + set_type(fors_tree_addr + 8 * i, SPX_ADDR_TYPE_FORSTREE); + copy_keypair_addr(fors_leaf_addr + 8 * i, fors_addr); + } + copy_keypair_addr(fors_pk_addr, fors_addr); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); + + message_to_indices(indices, m); + + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); + + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + + /* Include the secret key part that produces the selected leaf node. */ + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); + fors_gen_sk(sig, ctx, fors_tree_addr); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + sig += SPX_N; + + /* Compute the authentication path for this leaf node. */ + treehashx4(roots + i * SPX_N, sig, ctx, + indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx4, + fors_tree_addr, &fors_info); + + sig += SPX_N * SPX_FORS_HEIGHT; + } + + /* Hash horizontally across all tree roots to derive the public key. */ + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); +} + +/** + * Derives the FORS public key from a signature. + * This can be used for verification by comparing to a known public key, or to + * subsequently verify a signature on the derived public key. The latter is the + * typical use-case when used as an FTS below an OTS in a hypertree. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + unsigned char leaf[SPX_N]; + uint32_t fors_tree_addr[8] = {0}; + uint32_t fors_pk_addr[8] = {0}; + uint32_t idx_offset; + unsigned int i; + + copy_keypair_addr(fors_tree_addr, fors_addr); + copy_keypair_addr(fors_pk_addr, fors_addr); + + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); + + message_to_indices(indices, m); + + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); + + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + + /* Derive the leaf from the included secret key part. */ + fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); + sig += SPX_N; + + /* Derive the corresponding root node of this tree. */ + compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, + sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); + sig += SPX_N * SPX_FORS_HEIGHT; + } + + /* Hash horizontally across all tree roots to derive the public key. */ + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/fors.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/fors.h new file mode 100644 index 0000000000..509140a178 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/fors.h @@ -0,0 +1,32 @@ +#ifndef SPX_FORS_H +#define SPX_FORS_H + +#include + +#include "context.h" +#include "params.h" + +/** + * Signs a message m, deriving the secret key from sk_seed and the FTS address. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +#define fors_sign SPX_NAMESPACE(fors_sign) +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); + +/** + * Derives the FORS public key from a signature. + * This can be used for verification by comparing to a known public key, or to + * subsequently verify a signature on the derived public key. The latter is the + * typical use-case when used as an FTS below an OTS in a hypertree. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/hash.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/hash.h new file mode 100644 index 0000000000..f7c87d4c3c --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/hash.h @@ -0,0 +1,28 @@ +#ifndef SPX_HASH_H +#define SPX_HASH_H + +#include +#include + +#include "context.h" +#include "params.h" + +#define prf_addr SPX_NAMESPACE(prf_addr) +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]); + +#define gen_message_random SPX_NAMESPACE(gen_message_random) +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); + +#define hash_message SPX_NAMESPACE(hash_message) +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); + + + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/hash_shake.c b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/hash_shake.c new file mode 100644 index 0000000000..ff5e7ec918 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/hash_shake.c @@ -0,0 +1,83 @@ +#include +#include + +#include "hash.h" + +#include "address.h" +#include "fips202.h" +#include "params.h" +#include "utils.h" + +/* + * Computes PRF(pk_seed, sk_seed, addr) + */ +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]) { + unsigned char buf[2 * SPX_N + SPX_ADDR_BYTES]; + + memcpy(buf, ctx->pub_seed, SPX_N); + memcpy(buf + SPX_N, addr, SPX_ADDR_BYTES); + memcpy(buf + SPX_N + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); + + shake256(out, SPX_N, buf, 2 * SPX_N + SPX_ADDR_BYTES); +} + +/** + * Computes the message-dependent randomness R, using a secret seed and an + * optional randomization value as well as the message. + */ +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { + (void)ctx; + shake256incctx s_inc; + + shake256_inc_init(&s_inc); + shake256_inc_absorb(&s_inc, sk_prf, SPX_N); + shake256_inc_absorb(&s_inc, optrand, SPX_N); + shake256_inc_absorb(&s_inc, m, mlen); + shake256_inc_finalize(&s_inc); + shake256_inc_squeeze(R, SPX_N, &s_inc); + shake256_inc_ctx_release(&s_inc); +} + +/** + * Computes the message hash using R, the public key, and the message. + * Outputs the message digest and the index of the leaf. The index is split in + * the tree index and the leaf index, for convenient copying to an address. + */ +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { + (void)ctx; +#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) +#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) +#define SPX_LEAF_BITS SPX_TREE_HEIGHT +#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) +#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) + + unsigned char buf[SPX_DGST_BYTES]; + unsigned char *bufp = buf; + shake256incctx s_inc; + + shake256_inc_init(&s_inc); + shake256_inc_absorb(&s_inc, R, SPX_N); + shake256_inc_absorb(&s_inc, pk, SPX_PK_BYTES); + shake256_inc_absorb(&s_inc, m, mlen); + shake256_inc_finalize(&s_inc); + shake256_inc_squeeze(buf, SPX_DGST_BYTES, &s_inc); + shake256_inc_ctx_release(&s_inc); + + memcpy(digest, bufp, SPX_FORS_MSG_BYTES); + bufp += SPX_FORS_MSG_BYTES; + + + *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); + *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); + bufp += SPX_TREE_BYTES; + + *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); + *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/hash_shakex4.c b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/hash_shakex4.c new file mode 100644 index 0000000000..bbd22eb117 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/hash_shakex4.c @@ -0,0 +1,64 @@ +#include +#include + +#include "hashx4.h" + +#include "address.h" +#include "fips202x4.h" +#include "params.h" + +extern void KeccakP1600times4_PermuteAll_24rounds(__m256i *s); + +/* + * 4-way parallel version of prf_addr; takes 4x as much input and output + */ +void prf_addrx4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const spx_ctx *ctx, + const uint32_t addrx4[4 * 8]) { + /* As we write and read only a few quadwords, it is more efficient to + * build and extract from the fourway SHAKE256 state by hand. */ + __m256i state[25]; + + for (int i = 0; i < SPX_N / 8; i++) { + state[i] = _mm256_set1_epi64x(((int64_t *)ctx->pub_seed)[i]); + } + for (int i = 0; i < 4; i++) { + state[SPX_N / 8 + i] = _mm256_set_epi32( + (int)addrx4[3 * 8 + 1 + 2 * i], + (int)addrx4[3 * 8 + 2 * i], + (int)addrx4[2 * 8 + 1 + 2 * i], + (int)addrx4[2 * 8 + 2 * i], + (int)addrx4[8 + 1 + 2 * i], + (int)addrx4[8 + 2 * i], + (int)addrx4[1 + 2 * i], + (int)addrx4[2 * i] + ); + } + for (int i = 0; i < SPX_N / 8; i++) { + state[SPX_N / 8 + i + 4] = _mm256_set1_epi64x(((int64_t *)ctx->sk_seed)[i]); + } + + /* SHAKE domain separator and padding. */ + state[SPX_N / 4 + 4] = _mm256_set1_epi64x(0x1f); + for (int i = SPX_N / 4 + 5; i < 16; i++) { + state[i] = _mm256_set1_epi64x(0); + } + // shift unsigned and then cast to avoid UB + state[16] = _mm256_set1_epi64x((long long)(0x80ULL << 56)); + + for (int i = 17; i < 25; i++) { + state[i] = _mm256_set1_epi64x(0); + } + + KeccakP1600times4_PermuteAll_24rounds(&state[0]); + + for (int i = 0; i < SPX_N / 8; i++) { + ((int64_t *)out0)[i] = _mm256_extract_epi64(state[i], 0); + ((int64_t *)out1)[i] = _mm256_extract_epi64(state[i], 1); + ((int64_t *)out2)[i] = _mm256_extract_epi64(state[i], 2); + ((int64_t *)out3)[i] = _mm256_extract_epi64(state[i], 3); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/hashx4.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/hashx4.h new file mode 100644 index 0000000000..3751a0ebd0 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/hashx4.h @@ -0,0 +1,17 @@ +#ifndef SPX_HASHX4_H +#define SPX_HASHX4_H + +#include + +#include "context.h" +#include "params.h" + +#define prf_addrx4 SPX_NAMESPACE(prf_addrx4) +void prf_addrx4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const spx_ctx *ctx, + const uint32_t addrx4[4 * 8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/merkle.c b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/merkle.c new file mode 100644 index 0000000000..f57811c1ac --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/merkle.c @@ -0,0 +1,64 @@ +#include +#include + +#include "merkle.h" + +#include "address.h" +#include "params.h" +#include "utils.h" +#include "utilsx4.h" +#include "wots.h" +#include "wotsx4.h" + +/* + * This generates a Merkle signature (WOTS signature followed by the Merkle + * authentication path). + */ +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf) { + unsigned char *auth_path = sig + SPX_WOTS_BYTES; + uint32_t tree_addrx4[4 * 8] = { 0 }; + int j; + struct leaf_info_x4 info = { 0 }; + unsigned steps[ SPX_WOTS_LEN ]; + + info.wots_sig = sig; + chain_lengths(steps, root); + info.wots_steps = steps; + + for (j = 0; j < 4; j++) { + set_type(&tree_addrx4[8 * j], SPX_ADDR_TYPE_HASHTREE); + set_type(&info.leaf_addr[8 * j], SPX_ADDR_TYPE_WOTS); + set_type(&info.pk_addr[8 * j], SPX_ADDR_TYPE_WOTSPK); + copy_subtree_addr(&tree_addrx4[8 * j], tree_addr); + copy_subtree_addr(&info.leaf_addr[8 * j], wots_addr); + copy_subtree_addr(&info.pk_addr[8 * j], wots_addr); + } + + info.wots_sign_leaf = idx_leaf; + + treehashx4(root, auth_path, ctx, + idx_leaf, 0, + SPX_TREE_HEIGHT, + wots_gen_leafx4, + tree_addrx4, &info); +} + +/* Compute root node of the top-most subtree. */ +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { + /* We do not need the auth path in key generation, but it simplifies the + code to have just one treehash routine that computes both root and path + in one function. */ + unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; + uint32_t top_tree_addr[8] = {0}; + uint32_t wots_addr[8] = {0}; + + set_layer_addr(top_tree_addr, SPX_D - 1); + set_layer_addr(wots_addr, SPX_D - 1); + + merkle_sign(auth_path, root, ctx, + wots_addr, top_tree_addr, + ~0U /* ~0 means "don't bother generating an auth path */ ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/merkle.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/merkle.h new file mode 100644 index 0000000000..769cf2e970 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/merkle.h @@ -0,0 +1,21 @@ +#ifndef MERKLE_H_ +#define MERKLE_H_ + +#include + +#include "context.h" +#include "params.h" + +/* Generate a Merkle signature (WOTS signature followed by the Merkle */ +/* authentication path) */ +#define merkle_sign SPX_NAMESPACE(merkle_sign) +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf); + +/* Compute the root node of the top-most subtree. */ +#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); + +#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/nistapi.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/nistapi.h new file mode 100644 index 0000000000..3cb71afad4 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/nistapi.h @@ -0,0 +1,87 @@ +#ifndef SPX_API_H +#define SPX_API_H + +#include +#include + +#include "params.h" + +#define CRYPTO_ALGNAME "SPHINCS+" + +#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES +#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES +#define CRYPTO_BYTES SPX_BYTES +#define CRYPTO_SEEDBYTES (3*SPX_N) + +/* + * Returns the length of a secret key, in bytes + */ +#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) +size_t crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) +size_t crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) +size_t crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) +size_t crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +#define crypto_sign SPX_NAMESPACE(crypto_sign) +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/params.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/params.h new file mode 100644 index 0000000000..e32fba8f77 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/params.h @@ -0,0 +1,56 @@ +#ifndef SPX_PARAMS_H +#define SPX_PARAMS_H + +#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSSHAKE128FROBUST_AVX2_##s + +/* Hash output length in bytes. */ +#define SPX_N 16 +/* Height of the hypertree. */ +#define SPX_FULL_HEIGHT 66 +/* Number of subtree layer. */ +#define SPX_D 22 +/* FORS tree dimensions. */ +#define SPX_FORS_HEIGHT 6 +#define SPX_FORS_TREES 33 +/* Winternitz parameter, */ +#define SPX_WOTS_W 16 + +/* The hash function is defined by linking a different hash.c file, as opposed + to setting a #define constant. */ + +/* For clarity */ +#define SPX_ADDR_BYTES 32 + +/* WOTS parameters. */ +#define SPX_WOTS_LOGW 4 + +#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) + +/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ +#define SPX_WOTS_LEN2 3 + +#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) +#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) +#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES + +/* Subtree size. */ +#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) + +//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT +// #error SPX_D should always divide SPX_FULL_HEIGHT +//#endif + +/* FORS parameters. */ +#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) +#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) +#define SPX_FORS_PK_BYTES SPX_N + +/* Resulting SPX sizes. */ +#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ + SPX_FULL_HEIGHT * SPX_N) +#define SPX_PK_BYTES (2 * SPX_N) +#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) + +#include "shake_offsets.h" + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/shake_offsets.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/shake_offsets.h new file mode 100644 index 0000000000..6b28d95d91 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/shake_offsets.h @@ -0,0 +1,21 @@ +#ifndef SHAKE_OFFSETS_H_ +#define SHAKE_OFFSETS_H_ + +/* + * Offsets of various fields in the address structure when we use SHAKE as + * the Sphincs+ hash function + */ + +#define SPX_OFFSET_LAYER 3 /* The byte used to specify the Merkle tree layer */ +#define SPX_OFFSET_TREE 8 /* The start of the 8 byte field used to specify the tree */ +#define SPX_OFFSET_TYPE 19 /* The byte used to specify the hash type (reason) */ +#define SPX_OFFSET_KP_ADDR2 22 /* The high byte used to specify the key pair (which one-time signature) */ +#define SPX_OFFSET_KP_ADDR1 23 /* The low byte used to specify the key pair */ +#define SPX_OFFSET_CHAIN_ADDR 27 /* The byte used to specify the chain address (which Winternitz chain) */ +#define SPX_OFFSET_HASH_ADDR 31 /* The byte used to specify the hash address (where in the Winternitz chain) */ +#define SPX_OFFSET_TREE_HGT 27 /* The byte used to specify the height of this node in the FORS or Merkle tree */ +#define SPX_OFFSET_TREE_INDEX 28 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ + +#define SPX_SHAKE 1 + +#endif /* SHAKE_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/sign.c b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/sign.c new file mode 100644 index 0000000000..9d0c7d1b22 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/sign.c @@ -0,0 +1,286 @@ +#include +#include +#include + +#include "address.h" +#include "context.h" +#include "fors.h" +#include "hash.h" +#include "merkle.h" +#include "nistapi.h" +#include "params.h" +#include "randombytes.h" +#include "thash.h" +#include "utils.h" +#include "wots.h" + +/* + * Returns the length of a secret key, in bytes + */ +size_t crypto_sign_secretkeybytes(void) { + return CRYPTO_SECRETKEYBYTES; +} + +/* + * Returns the length of a public key, in bytes + */ +size_t crypto_sign_publickeybytes(void) { + return CRYPTO_PUBLICKEYBYTES; +} + +/* + * Returns the length of a signature, in bytes + */ +size_t crypto_sign_bytes(void) { + return CRYPTO_BYTES; +} + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +size_t crypto_sign_seedbytes(void) { + return CRYPTO_SEEDBYTES; +} + +/* + * Generates an SPX key pair given a seed of length + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [PUB_SEED || root] + */ +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed) { + spx_ctx ctx; + + /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ + memcpy(sk, seed, CRYPTO_SEEDBYTES); + + memcpy(pk, sk + 2 * SPX_N, SPX_N); + + memcpy(ctx.pub_seed, pk, SPX_N); + memcpy(ctx.sk_seed, sk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + /* Compute root node of the top-most subtree. */ + merkle_gen_root(sk + 3 * SPX_N, &ctx); + + // cleanup + free_hash_function(&ctx); + + memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); + + return 0; +} + +/* + * Generates an SPX key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [PUB_SEED || root] + */ +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { + uint8_t seed[CRYPTO_SEEDBYTES]; + randombytes(seed, CRYPTO_SEEDBYTES); + crypto_sign_seed_keypair(pk, sk, seed); + + return 0; +} + +/** + * Returns an array containing a detached signature. + */ +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk) { + spx_ctx ctx; + + const uint8_t *sk_prf = sk + SPX_N; + const uint8_t *pk = sk + 2 * SPX_N; + + uint8_t optrand[SPX_N]; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t root[SPX_N]; + uint32_t i; + uint64_t tree; + uint32_t idx_leaf; + uint32_t wots_addr[8] = {0}; + uint32_t tree_addr[8] = {0}; + + memcpy(ctx.sk_seed, sk, SPX_N); + memcpy(ctx.pub_seed, pk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + + /* Optionally, signing can be made non-deterministic using optrand. + This can help counter side-channel attacks that would benefit from + getting a large number of traces when the signer uses the same nodes. */ + randombytes(optrand, SPX_N); + /* Compute the digest randomization value. */ + gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); + + /* Derive the message digest and leaf index from R, PK and M. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; + + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); + + /* Sign the message hash using FORS. */ + fors_sign(sig, root, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); + sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; + + /* Update the indices for the next layer. */ + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; + } + + free_hash_function(&ctx); + + *siglen = SPX_BYTES; + + return 0; +} + +/** + * Verifies a detached signature and message under a given public key. + */ +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk) { + spx_ctx ctx; + const uint8_t *pub_root = pk + SPX_N; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t wots_pk[SPX_WOTS_BYTES]; + uint8_t root[SPX_N]; + uint8_t leaf[SPX_N]; + unsigned int i; + uint64_t tree; + uint32_t idx_leaf; + uint32_t wots_addr[8] = {0}; + uint32_t tree_addr[8] = {0}; + uint32_t wots_pk_addr[8] = {0}; + + if (siglen != SPX_BYTES) { + return -1; + } + + memcpy(ctx.pub_seed, pk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); + + /* Derive the message digest and leaf index from R || PK || M. */ + /* The additional SPX_N is a result of the hash domain separator. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; + + /* Layer correctly defaults to 0, so no need to set_layer_addr */ + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); + + fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + /* For each subtree.. */ + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + copy_keypair_addr(wots_pk_addr, wots_addr); + + /* The WOTS public key is only correct if the signature was correct. */ + /* Initially, root is the FORS pk, but on subsequent iterations it is + the root of the subtree below the currently processed subtree. */ + wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); + sig += SPX_WOTS_BYTES; + + /* Compute the leaf node using the WOTS public key. */ + thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); + + /* Compute the root node of this subtree. */ + compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, + &ctx, tree_addr); + sig += SPX_TREE_HEIGHT * SPX_N; + + /* Update the indices for the next layer. */ + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; + } + + // cleanup + free_hash_function(&ctx); + + /* Check if the root node equals the root node in the public key. */ + if (memcmp(root, pub_root, SPX_N) != 0) { + return -1; + } + + return 0; +} + + +/** + * Returns an array containing the signature followed by the message. + */ +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk) { + size_t siglen; + + crypto_sign_signature(sm, &siglen, m, mlen, sk); + + memmove(sm + SPX_BYTES, m, mlen); + *smlen = siglen + mlen; + + return 0; +} + +/** + * Verifies a given signature-message pair under a given public key. + */ +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk) { + /* The API caller does not necessarily know what size a signature should be + but SPHINCS+ signatures are always exactly SPX_BYTES. */ + if (smlen < SPX_BYTES) { + memset(m, 0, smlen); + *mlen = 0; + return -1; + } + + *mlen = smlen - SPX_BYTES; + + if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { + memset(m, 0, smlen); + *mlen = 0; + return -1; + } + + /* If verification was successful, move the message to the right place. */ + memmove(m, sm + SPX_BYTES, *mlen); + + return 0; +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/thash.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/thash.h new file mode 100644 index 0000000000..8687ccfb4d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/thash.h @@ -0,0 +1,13 @@ +#ifndef SPX_THASH_H +#define SPX_THASH_H + +#include "context.h" +#include "params.h" + +#include + +#define thash SPX_NAMESPACE(thash) +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/thash_shake_robust.c b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/thash_shake_robust.c new file mode 100644 index 0000000000..696d53c5cc --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/thash_shake_robust.c @@ -0,0 +1,31 @@ +#include +#include + +#include "thash.h" + +#include "address.h" +#include "params.h" +#include "utils.h" + +#include "fips202.h" + +/** + * Takes an array of inblocks concatenated arrays of SPX_N bytes. + */ +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]) { + PQCLEAN_VLA(uint8_t, buf, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); + PQCLEAN_VLA(uint8_t, bitmask, inblocks * SPX_N); + unsigned int i; + + memcpy(buf, ctx->pub_seed, SPX_N); + memcpy(buf + SPX_N, addr, SPX_ADDR_BYTES); + + shake256(bitmask, inblocks * SPX_N, buf, SPX_N + SPX_ADDR_BYTES); + + for (i = 0; i < inblocks * SPX_N; i++) { + buf[SPX_N + SPX_ADDR_BYTES + i] = in[i] ^ bitmask[i]; + } + + shake256(out, SPX_N, buf, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/thash_shake_robustx4.c b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/thash_shake_robustx4.c new file mode 100644 index 0000000000..ce2946b745 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/thash_shake_robustx4.c @@ -0,0 +1,131 @@ +#include +#include + +#include "thashx4.h" + +#include "address.h" +#include "params.h" +#include "utils.h" + +#include "fips202x4.h" + +extern void KeccakP1600times4_PermuteAll_24rounds(__m256i *s); + +/** + * 4-way parallel version of thash; takes 4x as much input and output + */ +void thashx4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addrx4[4 * 8]) { + if (inblocks == 1 || inblocks == 2) { + /* As we write and read only a few quadwords, it is more efficient to + * build and extract from the fourway SHAKE256 state by hand. */ + __m256i state[25]; + for (int i = 0; i < SPX_N / 8; i++) { + state[i] = _mm256_set1_epi64x(((int64_t *)ctx->pub_seed)[i]); + } + for (int i = 0; i < 4; i++) { + state[SPX_N / 8 + i] = _mm256_set_epi32( + (int)addrx4[3 * 8 + 1 + 2 * i], + (int)addrx4[3 * 8 + 2 * i], + (int)addrx4[2 * 8 + 1 + 2 * i], + (int)addrx4[2 * 8 + 2 * i], + (int)addrx4[8 + 1 + 2 * i], + (int)addrx4[8 + 2 * i], + (int)addrx4[1 + 2 * i], + (int)addrx4[2 * i] + ); + } + + /* SHAKE domain separator and padding */ + state[SPX_N / 8 + 4] = _mm256_set1_epi64x(0x1f); + for (int i = SPX_N / 8 + 5; i < 16; i++) { + state[i] = _mm256_set1_epi64x(0); + } + state[16] = _mm256_set1_epi64x((long long)(0x80ULL << 56)); + + for (int i = 17; i < 25; i++) { + state[i] = _mm256_set1_epi64x(0); + } + + /* We will permutate state2 with f1600x4 to compute the bitmask, + * but first we'll copy it to state2 which will be used to compute + * the final output, as its input is alsmost identical. */ + __m256i state2[25]; + memcpy(state2, state, 800); + + KeccakP1600times4_PermuteAll_24rounds(&state[0]); + + /* By copying from state, state2 already contains the pub_seed + * and addres. We just need to copy in the input blocks xorred with + * the bitmask we just computed. */ + for (unsigned int i = 0; i < (SPX_N / 8) * inblocks; i++) { + state2[SPX_N / 8 + 4 + i] = _mm256_xor_si256( + state[i], + _mm256_set_epi64x( + ((int64_t *)in3)[i], + ((int64_t *)in2)[i], + ((int64_t *)in1)[i], + ((int64_t *)in0)[i] + ) + ); + } + + /* Domain separator and start of padding. Note that the quadwords + * around are already zeroed for state from which we copied. + * We do a XOR instead of a set as this might be the 16th quadword + * when N=32 and inblocks=2, which already contains the end + * of the padding. */ + state2[(SPX_N / 8) * (1 + inblocks) + 4] = _mm256_xor_si256( + state2[(SPX_N / 8) * (1 + inblocks) + 4], + _mm256_set1_epi64x(0x1f) + ); + + KeccakP1600times4_PermuteAll_24rounds(&state2[0]); + + for (int i = 0; i < SPX_N / 8; i++) { + ((int64_t *)out0)[i] = _mm256_extract_epi64(state2[i], 0); + ((int64_t *)out1)[i] = _mm256_extract_epi64(state2[i], 1); + ((int64_t *)out2)[i] = _mm256_extract_epi64(state2[i], 2); + ((int64_t *)out3)[i] = _mm256_extract_epi64(state2[i], 3); + } + } else { + PQCLEAN_VLA(unsigned char, buf0, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, buf1, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, buf2, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, buf3, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, bitmask0, inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, bitmask1, inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, bitmask2, inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, bitmask3, inblocks * SPX_N); + unsigned int i; + + memcpy(buf0, ctx->pub_seed, SPX_N); + memcpy(buf1, ctx->pub_seed, SPX_N); + memcpy(buf2, ctx->pub_seed, SPX_N); + memcpy(buf3, ctx->pub_seed, SPX_N); + memcpy(buf0 + SPX_N, addrx4 + 0 * 8, SPX_ADDR_BYTES); + memcpy(buf1 + SPX_N, addrx4 + 1 * 8, SPX_ADDR_BYTES); + memcpy(buf2 + SPX_N, addrx4 + 2 * 8, SPX_ADDR_BYTES); + memcpy(buf3 + SPX_N, addrx4 + 3 * 8, SPX_ADDR_BYTES); + + shake256x4(bitmask0, bitmask1, bitmask2, bitmask3, inblocks * SPX_N, + buf0, buf1, buf2, buf3, SPX_N + SPX_ADDR_BYTES); + + for (i = 0; i < inblocks * SPX_N; i++) { + buf0[SPX_N + SPX_ADDR_BYTES + i] = in0[i] ^ bitmask0[i]; + buf1[SPX_N + SPX_ADDR_BYTES + i] = in1[i] ^ bitmask1[i]; + buf2[SPX_N + SPX_ADDR_BYTES + i] = in2[i] ^ bitmask2[i]; + buf3[SPX_N + SPX_ADDR_BYTES + i] = in3[i] ^ bitmask3[i]; + } + + shake256x4(out0, out1, out2, out3, SPX_N, + buf0, buf1, buf2, buf3, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/thashx4.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/thashx4.h new file mode 100644 index 0000000000..64798a3727 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/thashx4.h @@ -0,0 +1,20 @@ +#ifndef SPX_THASHX4_H +#define SPX_THASHX4_H + +#include + +#include "context.h" +#include "params.h" + +#define thashx4 SPX_NAMESPACE(thashx4) +void thashx4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addrx4[4 * 8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/utils.c b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/utils.c new file mode 100644 index 0000000000..177b541fb9 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/utils.c @@ -0,0 +1,148 @@ +#include + +#include "utils.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "thash.h" + +/** + * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. + */ +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in) { + int i; + + /* Iterate over out in decreasing order, for big-endianness. */ + for (i = (signed int)outlen - 1; i >= 0; i--) { + out[i] = in & 0xff; + in = in >> 8; + } +} + +void u32_to_bytes(unsigned char *out, uint32_t in) { + out[0] = (unsigned char)(in >> 24); + out[1] = (unsigned char)(in >> 16); + out[2] = (unsigned char)(in >> 8); + out[3] = (unsigned char)in; +} + +/** + * Converts the inlen bytes in 'in' from big-endian byte order to an integer. + */ +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { + unsigned long long retval = 0; + unsigned int i; + + for (i = 0; i < inlen; i++) { + retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); + } + return retval; +} + +/** + * Computes a root node given a leaf and an auth path. + * Expects address to be complete other than the tree_height and tree_index. + */ +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]) { + uint32_t i; + unsigned char buffer[2 * SPX_N]; + + /* If leaf_idx is odd (last bit = 1), current path element is a right child + and auth_path has to go left. Otherwise it is the other way around. */ + if (leaf_idx & 1) { + memcpy(buffer + SPX_N, leaf, SPX_N); + memcpy(buffer, auth_path, SPX_N); + } else { + memcpy(buffer, leaf, SPX_N); + memcpy(buffer + SPX_N, auth_path, SPX_N); + } + auth_path += SPX_N; + + for (i = 0; i < tree_height - 1; i++) { + leaf_idx >>= 1; + idx_offset >>= 1; + /* Set the address of the node we're creating. */ + set_tree_height(addr, i + 1); + set_tree_index(addr, leaf_idx + idx_offset); + + /* Pick the right or left neighbor, depending on parity of the node. */ + if (leaf_idx & 1) { + thash(buffer + SPX_N, buffer, 2, ctx, addr); + memcpy(buffer, auth_path, SPX_N); + } else { + thash(buffer, buffer, 2, ctx, addr); + memcpy(buffer + SPX_N, auth_path, SPX_N); + } + auth_path += SPX_N; + } + + /* The last iteration is exceptional; we do not copy an auth_path node. */ + leaf_idx >>= 1; + idx_offset >>= 1; + set_tree_height(addr, tree_height); + set_tree_index(addr, leaf_idx + idx_offset); + thash(root, buffer, 2, ctx, addr); +} + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx * /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]) { + PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); + PQCLEAN_VLA(unsigned int, heights, tree_height + 1); + unsigned int offset = 0; + uint32_t idx; + uint32_t tree_idx; + + for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { + /* Add the next leaf node to the stack. */ + gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); + offset++; + heights[offset - 1] = 0; + + /* If this is a node we need for the auth path.. */ + if ((leaf_idx ^ 0x1) == idx) { + memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); + } + + /* While the top-most nodes are of equal height.. */ + while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { + /* Compute index of the new node, in the next layer. */ + tree_idx = (idx >> (heights[offset - 1] + 1)); + + /* Set the address of the node we're creating. */ + set_tree_height(tree_addr, heights[offset - 1] + 1); + set_tree_index(tree_addr, + tree_idx + (idx_offset >> (heights[offset - 1] + 1))); + /* Hash the top-most nodes from the stack together. */ + thash(stack + (offset - 2)*SPX_N, + stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); + offset--; + /* Note that the top-most node is now one layer higher. */ + heights[offset - 1]++; + + /* If this is a node we need for the auth path.. */ + if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { + memcpy(auth_path + heights[offset - 1]*SPX_N, + stack + (offset - 1)*SPX_N, SPX_N); + } + } + } + memcpy(root, stack, SPX_N); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/utils.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/utils.h new file mode 100644 index 0000000000..64f5d5a53a --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/utils.h @@ -0,0 +1,58 @@ +#ifndef SPX_UTILS_H +#define SPX_UTILS_H + +#include + +#include "compat.h" +#include "context.h" +#include "params.h" + + +/* To support MSVC use alloca() instead of VLAs. See #20. */ + + +/** + * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. + */ +#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in); +#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) +void u32_to_bytes(unsigned char *out, uint32_t in); + +/** + * Converts the inlen bytes in 'in' from big-endian byte order to an integer. + */ +#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); + +/** + * Computes a root node given a leaf and an auth path. + * Expects address to be complete other than the tree_height and tree_index. + */ +#define compute_root SPX_NAMESPACE(compute_root) +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]); + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +#define treehash SPX_NAMESPACE(treehash) +void treehash(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx *ctx /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]); + + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/utilsx4.c b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/utilsx4.c new file mode 100644 index 0000000000..1638677194 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/utilsx4.c @@ -0,0 +1,138 @@ +#include + +#include "utilsx4.h" + +#include "address.h" +#include "params.h" +#include "thashx4.h" +#include "utils.h" + +/* + * Generate the entire Merkle tree, computing the authentication path for leaf_idx, + * and the resulting root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) + * + * This expects tree_addrx4 to be initialized to 4 parallel addr structures for + * the Merkle tree nodes + * + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + * + * This works by using the standard Merkle tree building algorithm, except + * that each 'node' tracked is actually 4 consecutive nodes in the real tree. + * When we combine two logical nodes ABCD and WXYZ, we perform the H + * operation on adjacent real nodes, forming the parent logical node + * (AB)(CD)(WX)(YZ) + * + * When we get to the top two levels of the real tree (where there is only + * one logical node), we continue this operation two more times; the right + * most real node will by the actual root (and the other 3 nodes will be + * garbage). We follow the same thashx4 logic so that the 'extract + * authentication path components' part of the loop is still executed (and + * to simplify the code somewhat) + * + * This currently assumes tree_height >= 2; I suspect that doing an adjusting + * idx, addr_idx on the gen_leafx4 call if tree_height < 2 would fix it; since + * we don't actually use such short trees, I haven't bothered + */ +void treehashx4(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, + uint32_t tree_height, + void (*gen_leafx4)( + unsigned char * /* Where to write the leaves */, + const spx_ctx *, + uint32_t idx, void *info), + uint32_t tree_addrx4[4 * 8], + void *info) { + /* This is where we keep the intermediate nodes */ + PQCLEAN_VLA(unsigned char, stackx4, tree_height * 4 * SPX_N); + uint32_t left_adj = 0, prev_left_adj = 0; /* When we're doing the top 3 */ + /* levels, the left-most part of the tree isn't at the beginning */ + /* of current[]. These give the offset of the actual start */ + + uint32_t idx; + uint32_t max_idx = (1U << (tree_height - 2)) - 1; + for (idx = 0;; idx++) { + unsigned char current[4 * SPX_N]; /* Current logical node */ + gen_leafx4( current, ctx, 4 * idx + idx_offset, + info ); + + /* Now combine the freshly generated right node with previously */ + /* generated left ones */ + uint32_t internal_idx_offset = idx_offset; + uint32_t internal_idx = idx; + uint32_t internal_leaf = leaf_idx; + uint32_t h; /* The height we are in the Merkle tree */ + for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { + + /* Special processing if we're at the top of the tree */ + if (h >= tree_height - 2) { + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[3 * SPX_N], SPX_N ); + return; + } + /* The tree indexing logic is a bit off in this case */ + /* Adjust it so that the left-most node of the part of */ + /* the tree that we're processing has index 0 */ + prev_left_adj = left_adj; + left_adj = 4U - (1 << (tree_height - h - 1)); + } + + /* Check if we hit the top of the tree */ + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[3 * SPX_N], SPX_N ); + return; + } + + /* + * Check if one of the nodes we have is a part of the + * authentication path; if it is, write it out + */ + if ((((internal_idx << 2) ^ internal_leaf) & ~0x3U) == 0) { + memcpy( &auth_path[ h * SPX_N ], + ¤t[(((internal_leaf & 3) ^ 1) + prev_left_adj) * SPX_N], + SPX_N ); + } + + /* + * Check if we're at a left child; if so, stop going up the stack + * Exception: if we've reached the end of the tree, keep on going + * (so we combine the last 4 nodes into the one root node in two + * more iterations) + */ + if ((internal_idx & 1) == 0 && idx < max_idx) { + break; + } + + /* Ok, we're at a right node (or doing the top 3 levels) */ + /* Now combine the left and right logical nodes together */ + + /* Set the address of the node we're creating. */ + unsigned int j; + internal_idx_offset >>= 1; + for (j = 0; j < 4; j++) { + set_tree_height(tree_addrx4 + j * 8, h + 1); + set_tree_index(tree_addrx4 + j * 8, + (4 / 2) * (internal_idx & ~1U) + j - left_adj + internal_idx_offset ); + } + unsigned char *left = &stackx4[h * 4 * SPX_N]; + thashx4( ¤t[0 * SPX_N], + ¤t[1 * SPX_N], + ¤t[2 * SPX_N], + ¤t[3 * SPX_N], + &left [0 * SPX_N], + &left [2 * SPX_N], + ¤t[0 * SPX_N], + ¤t[2 * SPX_N], + 2, ctx, tree_addrx4); + } + + /* We've hit a left child; save the current for when we get the */ + /* corresponding right right */ + memcpy( &stackx4[h * 4 * SPX_N], current, 4 * SPX_N); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/utilsx4.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/utilsx4.h new file mode 100644 index 0000000000..facb874b18 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/utilsx4.h @@ -0,0 +1,30 @@ +#ifndef SPX_UTILSX4_H +#define SPX_UTILSX4_H + +#include + +#include "context.h" +#include "params.h" + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + * + * This implementation uses AVX to compute internal nodes 4 at a time (in + * parallel) + */ +#define treehashx4 SPX_NAMESPACE(treehashx4) +void treehashx4(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leafx4)( + unsigned char * /* Where to write the leaves */, + const spx_ctx * /* ctx */, + uint32_t addr_idx, void *info), + uint32_t tree_addrx4[4 * 8], void *info); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/wots.c b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/wots.c new file mode 100644 index 0000000000..4d5041ce05 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/wots.c @@ -0,0 +1,269 @@ +#include +#include + +#include "wots.h" + +#include "address.h" +#include "hash.h" +#include "hashx4.h" +#include "params.h" +#include "thash.h" +#include "thashx4.h" +#include "utils.h" +#include "utilsx4.h" +#include "wotsx4.h" + +// TODO clarify address expectations, and make them more uniform. +// TODO i.e. do we expect types to be set already? +// TODO and do we expect modifications or copies? + +/** + * Computes up the chains + */ +static void gen_chains( + unsigned char *out, + const unsigned char *in, + unsigned int start[SPX_WOTS_LEN], + const unsigned int steps[SPX_WOTS_LEN], + const spx_ctx *ctx, + uint32_t addr[8]) { + uint32_t i, j, k, idx, watching; + int done; + unsigned char empty[SPX_N]; + unsigned char *bufs[4]; + uint32_t addrs[8 * 4]; + + int l; + uint16_t counts[SPX_WOTS_W] = { 0 }; + uint16_t idxs[SPX_WOTS_LEN]; + uint16_t total, newTotal; + + /* set addrs = {addr, addr, addr, addr} */ + for (j = 0; j < 4; j++) { + memcpy(addrs + j * 8, addr, sizeof(uint32_t) * 8); + } + + /* Initialize out with the value at position 'start'. */ + memcpy(out, in, SPX_WOTS_LEN * SPX_N); + + /* Sort the chains in reverse order by steps using counting sort. */ + for (i = 0; i < SPX_WOTS_LEN; i++) { + counts[steps[i]]++; + } + total = 0; + for (l = SPX_WOTS_W - 1; l >= 0; l--) { + newTotal = counts[l] + total; + counts[l] = total; + total = newTotal; + } + for (i = 0; i < SPX_WOTS_LEN; i++) { + idxs[counts[steps[i]]] = (uint16_t)i; + counts[steps[i]]++; + } + + /* We got our work cut out for us: do it! */ + for (i = 0; i < SPX_WOTS_LEN; i += 4) { + for (j = 0; j < 4 && i + j < SPX_WOTS_LEN; j++) { + idx = idxs[i + j]; + set_chain_addr(addrs + j * 8, idx); + bufs[j] = out + SPX_N * idx; + } + + /* As the chains are sorted in reverse order, we know that the first + * chain is the longest and the last one is the shortest. We keep + * an eye on whether the last chain is done and then on the one before, + * et cetera. */ + watching = 3; + done = 0; + while (i + watching >= SPX_WOTS_LEN) { + bufs[watching] = &empty[0]; + watching--; + } + + for (k = 0;; k++) { + while (k == steps[idxs[i + watching]]) { + bufs[watching] = &empty[0]; + if (watching == 0) { + done = 1; + break; + } + watching--; + } + if (done) { + break; + } + for (j = 0; j < watching + 1; j++) { + set_hash_addr(addrs + j * 8, k + start[idxs[i + j]]); + } + + thashx4(bufs[0], bufs[1], bufs[2], bufs[3], + bufs[0], bufs[1], bufs[2], bufs[3], 1, ctx, addrs); + } + } +} + +/** + * base_w algorithm as described in draft. + * Interprets an array of bytes as integers in base w. + * This only works when log_w is a divisor of 8. + */ +static void base_w(unsigned int *output, const int out_len, + const unsigned char *input) { + int in = 0; + int out = 0; + unsigned char total = 0; + int bits = 0; + int consumed; + + for (consumed = 0; consumed < out_len; consumed++) { + if (bits == 0) { + total = input[in]; + in++; + bits += 8; + } + bits -= SPX_WOTS_LOGW; + output[out] = (total >> bits) & (SPX_WOTS_W - 1); + out++; + } +} + +/* Computes the WOTS+ checksum over a message (in base_w). */ +static void wots_checksum(unsigned int *csum_base_w, + const unsigned int *msg_base_w) { + unsigned int csum = 0; + unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; + unsigned int i; + + /* Compute checksum. */ + for (i = 0; i < SPX_WOTS_LEN1; i++) { + csum += SPX_WOTS_W - 1 - msg_base_w[i]; + } + + /* Convert checksum to base_w. */ + /* Make sure expected empty zero bits are the least significant bits. */ + csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); + ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); + base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); +} + +/* Takes a message and derives the matching chain lengths. */ +void chain_lengths(unsigned int *lengths, const unsigned char *msg) { + base_w(lengths, SPX_WOTS_LEN1, msg); + wots_checksum(lengths + SPX_WOTS_LEN1, lengths); +} + +/** + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. + * + * Writes the computed public key to 'pk'. + */ +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]) { + unsigned int steps[SPX_WOTS_LEN]; + unsigned int start[SPX_WOTS_LEN]; + uint32_t i; + + chain_lengths(start, msg); + + for (i = 0; i < SPX_WOTS_LEN; i++) { + steps[i] = SPX_WOTS_W - 1 - start[i]; + } + + gen_chains(pk, sig, start, steps, ctx, addr); +} + +/* + * This generates 4 sequential WOTS public keys + * It also generates the WOTS signature if leaf_info indicates + * that we're signing with one of these WOTS keys + */ +void wots_gen_leafx4(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info) { + struct leaf_info_x4 *info = v_info; + uint32_t *leaf_addr = info->leaf_addr; + uint32_t *pk_addr = info->pk_addr; + unsigned int i, j, k; + unsigned char pk_buffer[ 4 * SPX_WOTS_BYTES ]; + unsigned wots_offset = SPX_WOTS_BYTES; + unsigned char *buffer; + uint32_t wots_k_mask; + unsigned wots_sign_index; + + if (((leaf_idx ^ info->wots_sign_leaf) & ~3U) == 0) { + /* We're traversing the leaf that's signing; generate the WOTS */ + /* signature */ + wots_k_mask = 0; + wots_sign_index = info->wots_sign_leaf & 3; /* Which of of the 4 */ + /* 4 slots do the signatures come from */ + } else { + /* Nope, we're just generating pk's; turn off the signature logic */ + wots_k_mask = (uint32_t)~0; + wots_sign_index = 0; + } + + for (j = 0; j < 4; j++) { + set_keypair_addr( leaf_addr + j * 8, leaf_idx + j ); + set_keypair_addr( pk_addr + j * 8, leaf_idx + j ); + } + + for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { + uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k to */ + /* the step if we're generating a signature, ~0 if we're not */ + + /* Start with the secret seed */ + for (j = 0; j < 4; j++) { + set_chain_addr(leaf_addr + j * 8, i); + set_hash_addr(leaf_addr + j * 8, 0); + set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTSPRF); + } + prf_addrx4(buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + buffer + 2 * wots_offset, + buffer + 3 * wots_offset, + ctx, leaf_addr); + + for (j = 0; j < 4; j++) { + set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTS); + } + + /* Iterate down the WOTS chain */ + for (k = 0;; k++) { + /* Check if one of the values we have needs to be saved as a */ + /* part of the WOTS signature */ + if (k == wots_k) { + memcpy( info->wots_sig + i * SPX_N, + buffer + wots_sign_index * wots_offset, SPX_N ); + } + + /* Check if we hit the top of the chain */ + if (k == SPX_WOTS_W - 1) { + break; + } + + /* Iterate one step on all 4 chains */ + for (j = 0; j < 4; j++) { + set_hash_addr(leaf_addr + j * 8, k); + } + thashx4(buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + buffer + 2 * wots_offset, + buffer + 3 * wots_offset, + buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + buffer + 2 * wots_offset, + buffer + 3 * wots_offset, 1, ctx, leaf_addr); + } + } + + /* Do the final thash to generate the public keys */ + thashx4(dest + 0 * SPX_N, + dest + 1 * SPX_N, + dest + 2 * SPX_N, + dest + 3 * SPX_N, + pk_buffer + 0 * wots_offset, + pk_buffer + 1 * wots_offset, + pk_buffer + 2 * wots_offset, + pk_buffer + 3 * wots_offset, SPX_WOTS_LEN, ctx, pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/wots.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/wots.h new file mode 100644 index 0000000000..4e7692eeef --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/wots.h @@ -0,0 +1,25 @@ +#ifndef SPX_WOTS_H +#define SPX_WOTS_H + +#include + +#include "context.h" +#include "params.h" + +/** + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. + * + * Writes the computed public key to 'pk'. + */ +#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]); + +/* + * Compute the chain lengths needed for a given message hash + */ +#define chain_lengths SPX_NAMESPACE(chain_lengths) +void chain_lengths(unsigned int *lengths, const unsigned char *msg); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/wotsx4.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/wotsx4.h new file mode 100644 index 0000000000..cd634f1743 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/wotsx4.h @@ -0,0 +1,41 @@ +#ifndef WOTSX4_H_ +#define WOTSX4_H_ + +#include + +#include "params.h" + +/* + * This is here to provide an interface to the internal wots_gen_leafx4 + * routine. While this routine is not referenced in the package outside of + * wots.c, it is called from the stand-alone benchmark code to characterize + * the performance + */ +struct leaf_info_x4 { + unsigned char *wots_sig; + uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ + uint32_t *wots_steps; + uint32_t leaf_addr[4 * 8]; + uint32_t pk_addr[4 * 8]; +}; + +/* Macro to set the leaf_info to something 'benign', that is, it would */ +/* run with the same time as it does during the real signing process */ +/* Used only by the benchmark code */ +#define INITIALIZE_LEAF_INFO_X4(info, addr, step_buffer) { \ + (info).wots_sig = 0; \ + (info).wots_sign_leaf = ~0; \ + (info).wots_steps = step_buffer; \ + int i; \ + for (i=0; i<4; i++) { \ + memcpy( &(info).leaf_addr[8*i], addr, 32 ); \ + memcpy( &(info).pk_addr[8*i], addr, 32 ); \ + } \ + } + +#define wots_gen_leafx4 SPX_NAMESPACE(wots_gen_leafx4) +void wots_gen_leafx4(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info); + +#endif /* WOTSX4_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/LICENSE b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/LICENSE new file mode 100644 index 0000000000..670154e353 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/LICENSE @@ -0,0 +1,116 @@ +CC0 1.0 Universal + +Statement of Purpose + +The laws of most jurisdictions throughout the world automatically confer +exclusive Copyright and Related Rights (defined below) upon the creator and +subsequent owner(s) (each and all, an "owner") of an original work of +authorship and/or a database (each, a "Work"). + +Certain owners wish to permanently relinquish those rights to a Work for the +purpose of contributing to a commons of creative, cultural and scientific +works ("Commons") that the public can reliably and without fear of later +claims of infringement build upon, modify, incorporate in other works, reuse +and redistribute as freely as possible in any form whatsoever and for any +purposes, including without limitation commercial purposes. These owners may +contribute to the Commons to promote the ideal of a free culture and the +further production of creative, cultural and scientific works, or to gain +reputation or greater distribution for their Work in part through the use and +efforts of others. + +For these and/or other purposes and motivations, and without any expectation +of additional consideration or compensation, the person associating CC0 with a +Work (the "Affirmer"), to the extent that he or she is an owner of Copyright +and Related Rights in the Work, voluntarily elects to apply CC0 to the Work +and publicly distribute the Work under its terms, with knowledge of his or her +Copyright and Related Rights in the Work and the meaning and intended legal +effect of CC0 on those rights. + +1. Copyright and Related Rights. A Work made available under CC0 may be +protected by copyright and related or neighboring rights ("Copyright and +Related Rights"). Copyright and Related Rights include, but are not limited +to, the following: + + i. the right to reproduce, adapt, distribute, perform, display, communicate, + and translate a Work; + + ii. moral rights retained by the original author(s) and/or performer(s); + + iii. publicity and privacy rights pertaining to a person's image or likeness + depicted in a Work; + + iv. rights protecting against unfair competition in regards to a Work, + subject to the limitations in paragraph 4(a), below; + + v. rights protecting the extraction, dissemination, use and reuse of data in + a Work; + + vi. database rights (such as those arising under Directive 96/9/EC of the + European Parliament and of the Council of 11 March 1996 on the legal + protection of databases, and under any national implementation thereof, + including any amended or successor version of such directive); and + + vii. other similar, equivalent or corresponding rights throughout the world + based on applicable law or treaty, and any national implementations thereof. + +2. Waiver. To the greatest extent permitted by, but not in contravention of, +applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and +unconditionally waives, abandons, and surrenders all of Affirmer's Copyright +and Related Rights and associated claims and causes of action, whether now +known or unknown (including existing as well as future claims and causes of +action), in the Work (i) in all territories worldwide, (ii) for the maximum +duration provided by applicable law or treaty (including future time +extensions), (iii) in any current or future medium and for any number of +copies, and (iv) for any purpose whatsoever, including without limitation +commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes +the Waiver for the benefit of each member of the public at large and to the +detriment of Affirmer's heirs and successors, fully intending that such Waiver +shall not be subject to revocation, rescission, cancellation, termination, or +any other legal or equitable action to disrupt the quiet enjoyment of the Work +by the public as contemplated by Affirmer's express Statement of Purpose. + +3. Public License Fallback. Should any part of the Waiver for any reason be +judged legally invalid or ineffective under applicable law, then the Waiver +shall be preserved to the maximum extent permitted taking into account +Affirmer's express Statement of Purpose. In addition, to the extent the Waiver +is so judged Affirmer hereby grants to each affected person a royalty-free, +non transferable, non sublicensable, non exclusive, irrevocable and +unconditional license to exercise Affirmer's Copyright and Related Rights in +the Work (i) in all territories worldwide, (ii) for the maximum duration +provided by applicable law or treaty (including future time extensions), (iii) +in any current or future medium and for any number of copies, and (iv) for any +purpose whatsoever, including without limitation commercial, advertising or +promotional purposes (the "License"). The License shall be deemed effective as +of the date CC0 was applied by Affirmer to the Work. Should any part of the +License for any reason be judged legally invalid or ineffective under +applicable law, such partial invalidity or ineffectiveness shall not +invalidate the remainder of the License, and in such case Affirmer hereby +affirms that he or she will not (i) exercise any of his or her remaining +Copyright and Related Rights in the Work or (ii) assert any associated claims +and causes of action with respect to the Work, in either case contrary to +Affirmer's express Statement of Purpose. + +4. Limitations and Disclaimers. + + a. No trademark or patent rights held by Affirmer are waived, abandoned, + surrendered, licensed or otherwise affected by this document. + + b. Affirmer offers the Work as-is and makes no representations or warranties + of any kind concerning the Work, express, implied, statutory or otherwise, + including without limitation warranties of title, merchantability, fitness + for a particular purpose, non infringement, or the absence of latent or + other defects, accuracy, or the present or absence of errors, whether or not + discoverable, all to the greatest extent permissible under applicable law. + + c. Affirmer disclaims responsibility for clearing rights of other persons + that may apply to the Work or any use thereof, including without limitation + any person's Copyright and Related Rights in the Work. Further, Affirmer + disclaims responsibility for obtaining any necessary consents, permissions + or other rights required for any use of the Work. + + d. Affirmer understands and acknowledges that Creative Commons is not a + party to this document and has no duty or obligation with respect to this + CC0 or use of the Work. + +For more information, please see + diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/address.c b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/address.c new file mode 100644 index 0000000000..b956e9cb29 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/address.c @@ -0,0 +1,91 @@ +#include +#include + +#include "address.h" +#include "params.h" +#include "utils.h" + +/* + * Specify which level of Merkle tree (the "layer") we're working on + */ +void set_layer_addr(uint32_t addr[8], uint32_t layer) { + ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; +} + +/* + * Specify which Merkle tree within the level (the "tree address") we're working on + */ +void set_tree_addr(uint32_t addr[8], uint64_t tree) { + ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); +} + +/* + * Specify the reason we'll use this address structure for, that is, what + * hash will we compute with it. This is used so that unrelated types of + * hashes don't accidentally get the same address structure. The type will be + * one of the SPX_ADDR_TYPE constants + */ +void set_type(uint32_t addr[8], uint32_t type) { + ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; +} + +/* + * Copy the layer and tree fields of the address structure. This is used + * when we're doing multiple types of hashes within the same Merkle tree + */ +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); +} + +/* These functions are used for OTS addresses. */ + +/* + * Specify which Merkle leaf we're working on; that is, which OTS keypair + * we're talking about. + */ +void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { + ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; +} + +/* + * Copy the layer, tree and keypair fields of the address structure. This is + * used when we're doing multiple things within the same OTS keypair + */ +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); + ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; +} + +/* + * Specify which Merkle chain within the OTS we're working with + * (the chain address) + */ +void set_chain_addr(uint32_t addr[8], uint32_t chain) { + ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; +} + +/* + * Specify where in the Merkle chain we are +* (the hash address) + */ +void set_hash_addr(uint32_t addr[8], uint32_t hash) { + ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; +} + +/* These functions are used for all hash tree addresses (including FORS). */ + +/* + * Specify the height of the node in the Merkle/FORS tree we are in + * (the tree height) + */ +void set_tree_height(uint32_t addr[8], uint32_t tree_height) { + ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; +} + +/* + * Specify the distance from the left edge of the node in the Merkle/FORS tree + * (the tree index) + */ +void set_tree_index(uint32_t addr[8], uint32_t tree_index) { + u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/address.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/address.h new file mode 100644 index 0000000000..24a84eb40c --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/address.h @@ -0,0 +1,52 @@ +#ifndef SPX_ADDRESS_H +#define SPX_ADDRESS_H + +#include + +#include "params.h" + +/* The hash types that are passed to set_type */ +#define SPX_ADDR_TYPE_WOTS 0 +#define SPX_ADDR_TYPE_WOTSPK 1 +#define SPX_ADDR_TYPE_HASHTREE 2 +#define SPX_ADDR_TYPE_FORSTREE 3 +#define SPX_ADDR_TYPE_FORSPK 4 +#define SPX_ADDR_TYPE_WOTSPRF 5 +#define SPX_ADDR_TYPE_FORSPRF 6 + +#define set_layer_addr SPX_NAMESPACE(set_layer_addr) +void set_layer_addr(uint32_t addr[8], uint32_t layer); + +#define set_tree_addr SPX_NAMESPACE(set_tree_addr) +void set_tree_addr(uint32_t addr[8], uint64_t tree); + +#define set_type SPX_NAMESPACE(set_type) +void set_type(uint32_t addr[8], uint32_t type); + +/* Copies the layer and tree part of one address into the other */ +#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); + +/* These functions are used for WOTS and FORS addresses. */ + +#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) +void set_keypair_addr(uint32_t addr[8], uint32_t keypair); + +#define set_chain_addr SPX_NAMESPACE(set_chain_addr) +void set_chain_addr(uint32_t addr[8], uint32_t chain); + +#define set_hash_addr SPX_NAMESPACE(set_hash_addr) +void set_hash_addr(uint32_t addr[8], uint32_t hash); + +#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); + +/* These functions are used for all hash tree addresses (including FORS). */ + +#define set_tree_height SPX_NAMESPACE(set_tree_height) +void set_tree_height(uint32_t addr[8], uint32_t tree_height); + +#define set_tree_index SPX_NAMESPACE(set_tree_index) +void set_tree_index(uint32_t addr[8], uint32_t tree_index); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/api.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/api.h new file mode 100644 index 0000000000..5cf2a43ded --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/api.h @@ -0,0 +1,77 @@ +#ifndef PQCLEAN_SPHINCSSHAKE128FROBUST_CLEAN_API_H +#define PQCLEAN_SPHINCSSHAKE128FROBUST_CLEAN_API_H + +#include +#include + +#define PQCLEAN_SPHINCSSHAKE128FROBUST_CLEAN_CRYPTO_ALGNAME "SPHINCS+-shake-128f-robust" + +#define PQCLEAN_SPHINCSSHAKE128FROBUST_CLEAN_CRYPTO_SECRETKEYBYTES 64 +#define PQCLEAN_SPHINCSSHAKE128FROBUST_CLEAN_CRYPTO_PUBLICKEYBYTES 32 +#define PQCLEAN_SPHINCSSHAKE128FROBUST_CLEAN_CRYPTO_BYTES 17088 + +#define PQCLEAN_SPHINCSSHAKE128FROBUST_CLEAN_CRYPTO_SEEDBYTES 48 + +/* + * Returns the length of a secret key, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE128FROBUST_CLEAN_crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE128FROBUST_CLEAN_crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE128FROBUST_CLEAN_crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE128FROBUST_CLEAN_crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +int PQCLEAN_SPHINCSSHAKE128FROBUST_CLEAN_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +int PQCLEAN_SPHINCSSHAKE128FROBUST_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +int PQCLEAN_SPHINCSSHAKE128FROBUST_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +int PQCLEAN_SPHINCSSHAKE128FROBUST_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, + const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +int PQCLEAN_SPHINCSSHAKE128FROBUST_CLEAN_crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +int PQCLEAN_SPHINCSSHAKE128FROBUST_CLEAN_crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/context.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/context.h new file mode 100644 index 0000000000..9f8a40ab4e --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/context.h @@ -0,0 +1,22 @@ +#ifndef SPX_CONTEXT_H +#define SPX_CONTEXT_H + +#include +#include + +#include "params.h" + +typedef struct { + uint8_t pub_seed[SPX_N]; + uint8_t sk_seed[SPX_N]; + + +} spx_ctx; + +#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) +void initialize_hash_function(spx_ctx *ctx); + +#define free_hash_function SPX_NAMESPACE(free_hash_function) +void free_hash_function(spx_ctx *ctx); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/context_shake.c b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/context_shake.c new file mode 100644 index 0000000000..9614a103d3 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/context_shake.c @@ -0,0 +1,12 @@ +#include "context.h" + +/* For SHAKE256, there is no immediate reason to initialize at the start, + so this function is an empty operation. */ +void initialize_hash_function(spx_ctx *ctx) { + (void)ctx; /* Suppress an 'unused parameter' warning. */ +} + +// in case the hash function api is heap-based. +void free_hash_function(spx_ctx *ctx) { + (void)ctx; +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/fors.c b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/fors.c new file mode 100644 index 0000000000..96ca72e986 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/fors.c @@ -0,0 +1,156 @@ +#include +#include +#include + +#include "fors.h" + +#include "address.h" +#include "hash.h" +#include "thash.h" +#include "utils.h" +#include "utilsx1.h" + +static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + prf_addr(sk, ctx, fors_leaf_addr); +} + +static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, + const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + thash(leaf, sk, 1, ctx, fors_leaf_addr); +} + +struct fors_gen_leaf_info { + uint32_t leaf_addrx[8]; +}; + +static void fors_gen_leafx1(unsigned char *leaf, + const spx_ctx *ctx, + uint32_t addr_idx, void *info) { + struct fors_gen_leaf_info *fors_info = info; + uint32_t *fors_leaf_addr = fors_info->leaf_addrx; + + /* Only set the parts that the caller doesn't set */ + set_tree_index(fors_leaf_addr, addr_idx); + set_type(fors_leaf_addr, SPX_ADDR_TYPE_FORSPRF); + fors_gen_sk(leaf, ctx, fors_leaf_addr); + + set_type(fors_leaf_addr, SPX_ADDR_TYPE_FORSTREE); + fors_sk_to_leaf(leaf, leaf, + ctx, fors_leaf_addr); +} + +/** + * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + * Assumes indices has space for SPX_FORS_TREES integers. + */ +static void message_to_indices(uint32_t *indices, const unsigned char *m) { + unsigned int i, j; + unsigned int offset = 0; + + for (i = 0; i < SPX_FORS_TREES; i++) { + indices[i] = 0; + for (j = 0; j < SPX_FORS_HEIGHT; j++) { + indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); + offset++; + } + } +} + +/** + * Signs a message m, deriving the secret key from sk_seed and the FTS address. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + uint32_t fors_tree_addr[8] = {0}; + struct fors_gen_leaf_info fors_info = {0}; + uint32_t *fors_leaf_addr = fors_info.leaf_addrx; + uint32_t fors_pk_addr[8] = {0}; + uint32_t idx_offset; + unsigned int i; + + copy_keypair_addr(fors_tree_addr, fors_addr); + copy_keypair_addr(fors_leaf_addr, fors_addr); + + copy_keypair_addr(fors_pk_addr, fors_addr); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); + + message_to_indices(indices, m); + + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); + + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); + + /* Include the secret key part that produces the selected leaf node. */ + fors_gen_sk(sig, ctx, fors_tree_addr); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + sig += SPX_N; + + /* Compute the authentication path for this leaf node. */ + treehashx1(roots + i * SPX_N, sig, ctx, + indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx1, + fors_tree_addr, &fors_info); + + sig += SPX_N * SPX_FORS_HEIGHT; + } + + /* Hash horizontally across all tree roots to derive the public key. */ + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); +} + +/** + * Derives the FORS public key from a signature. + * This can be used for verification by comparing to a known public key, or to + * subsequently verify a signature on the derived public key. The latter is the + * typical use-case when used as an FTS below an OTS in a hypertree. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + unsigned char leaf[SPX_N]; + uint32_t fors_tree_addr[8] = {0}; + uint32_t fors_pk_addr[8] = {0}; + uint32_t idx_offset; + unsigned int i; + + copy_keypair_addr(fors_tree_addr, fors_addr); + copy_keypair_addr(fors_pk_addr, fors_addr); + + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); + + message_to_indices(indices, m); + + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); + + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + + /* Derive the leaf from the included secret key part. */ + fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); + sig += SPX_N; + + /* Derive the corresponding root node of this tree. */ + compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, + sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); + sig += SPX_N * SPX_FORS_HEIGHT; + } + + /* Hash horizontally across all tree roots to derive the public key. */ + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/fors.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/fors.h new file mode 100644 index 0000000000..509140a178 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/fors.h @@ -0,0 +1,32 @@ +#ifndef SPX_FORS_H +#define SPX_FORS_H + +#include + +#include "context.h" +#include "params.h" + +/** + * Signs a message m, deriving the secret key from sk_seed and the FTS address. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +#define fors_sign SPX_NAMESPACE(fors_sign) +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); + +/** + * Derives the FORS public key from a signature. + * This can be used for verification by comparing to a known public key, or to + * subsequently verify a signature on the derived public key. The latter is the + * typical use-case when used as an FTS below an OTS in a hypertree. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/hash.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/hash.h new file mode 100644 index 0000000000..f7c87d4c3c --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/hash.h @@ -0,0 +1,28 @@ +#ifndef SPX_HASH_H +#define SPX_HASH_H + +#include +#include + +#include "context.h" +#include "params.h" + +#define prf_addr SPX_NAMESPACE(prf_addr) +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]); + +#define gen_message_random SPX_NAMESPACE(gen_message_random) +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); + +#define hash_message SPX_NAMESPACE(hash_message) +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); + + + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/hash_shake.c b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/hash_shake.c new file mode 100644 index 0000000000..ff5e7ec918 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/hash_shake.c @@ -0,0 +1,83 @@ +#include +#include + +#include "hash.h" + +#include "address.h" +#include "fips202.h" +#include "params.h" +#include "utils.h" + +/* + * Computes PRF(pk_seed, sk_seed, addr) + */ +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]) { + unsigned char buf[2 * SPX_N + SPX_ADDR_BYTES]; + + memcpy(buf, ctx->pub_seed, SPX_N); + memcpy(buf + SPX_N, addr, SPX_ADDR_BYTES); + memcpy(buf + SPX_N + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); + + shake256(out, SPX_N, buf, 2 * SPX_N + SPX_ADDR_BYTES); +} + +/** + * Computes the message-dependent randomness R, using a secret seed and an + * optional randomization value as well as the message. + */ +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { + (void)ctx; + shake256incctx s_inc; + + shake256_inc_init(&s_inc); + shake256_inc_absorb(&s_inc, sk_prf, SPX_N); + shake256_inc_absorb(&s_inc, optrand, SPX_N); + shake256_inc_absorb(&s_inc, m, mlen); + shake256_inc_finalize(&s_inc); + shake256_inc_squeeze(R, SPX_N, &s_inc); + shake256_inc_ctx_release(&s_inc); +} + +/** + * Computes the message hash using R, the public key, and the message. + * Outputs the message digest and the index of the leaf. The index is split in + * the tree index and the leaf index, for convenient copying to an address. + */ +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { + (void)ctx; +#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) +#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) +#define SPX_LEAF_BITS SPX_TREE_HEIGHT +#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) +#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) + + unsigned char buf[SPX_DGST_BYTES]; + unsigned char *bufp = buf; + shake256incctx s_inc; + + shake256_inc_init(&s_inc); + shake256_inc_absorb(&s_inc, R, SPX_N); + shake256_inc_absorb(&s_inc, pk, SPX_PK_BYTES); + shake256_inc_absorb(&s_inc, m, mlen); + shake256_inc_finalize(&s_inc); + shake256_inc_squeeze(buf, SPX_DGST_BYTES, &s_inc); + shake256_inc_ctx_release(&s_inc); + + memcpy(digest, bufp, SPX_FORS_MSG_BYTES); + bufp += SPX_FORS_MSG_BYTES; + + + *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); + *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); + bufp += SPX_TREE_BYTES; + + *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); + *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/merkle.c b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/merkle.c new file mode 100644 index 0000000000..0c1479fd93 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/merkle.c @@ -0,0 +1,59 @@ +#include +#include + +#include "address.h" +#include "merkle.h" +#include "params.h" +#include "utils.h" +#include "utilsx1.h" +#include "wots.h" +#include "wotsx1.h" + +/* + * This generates a Merkle signature (WOTS signature followed by the Merkle + * authentication path). This is in this file because most of the complexity + * is involved with the WOTS signature; the Merkle authentication path logic + * is mostly hidden in treehashx4 + */ +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf) { + unsigned char *auth_path = sig + SPX_WOTS_BYTES; + struct leaf_info_x1 info = { 0 }; + unsigned steps[ SPX_WOTS_LEN ]; + + info.wots_sig = sig; + chain_lengths(steps, root); + info.wots_steps = steps; + + set_type(&tree_addr[0], SPX_ADDR_TYPE_HASHTREE); + set_type(&info.pk_addr[0], SPX_ADDR_TYPE_WOTSPK); + copy_subtree_addr(&info.leaf_addr[0], wots_addr); + copy_subtree_addr(&info.pk_addr[0], wots_addr); + + info.wots_sign_leaf = idx_leaf; + + treehashx1(root, auth_path, ctx, + idx_leaf, 0, + SPX_TREE_HEIGHT, + wots_gen_leafx1, + tree_addr, &info); +} + +/* Compute root node of the top-most subtree. */ +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { + /* We do not need the auth path in key generation, but it simplifies the + code to have just one treehash routine that computes both root and path + in one function. */ + unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; + uint32_t top_tree_addr[8] = {0}; + uint32_t wots_addr[8] = {0}; + + set_layer_addr(top_tree_addr, SPX_D - 1); + set_layer_addr(wots_addr, SPX_D - 1); + + merkle_sign(auth_path, root, ctx, + wots_addr, top_tree_addr, + (uint32_t)~0 /* ~0 means "don't bother generating an auth path */ ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/merkle.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/merkle.h new file mode 100644 index 0000000000..769cf2e970 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/merkle.h @@ -0,0 +1,21 @@ +#ifndef MERKLE_H_ +#define MERKLE_H_ + +#include + +#include "context.h" +#include "params.h" + +/* Generate a Merkle signature (WOTS signature followed by the Merkle */ +/* authentication path) */ +#define merkle_sign SPX_NAMESPACE(merkle_sign) +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf); + +/* Compute the root node of the top-most subtree. */ +#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); + +#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/nistapi.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/nistapi.h new file mode 100644 index 0000000000..3cb71afad4 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/nistapi.h @@ -0,0 +1,87 @@ +#ifndef SPX_API_H +#define SPX_API_H + +#include +#include + +#include "params.h" + +#define CRYPTO_ALGNAME "SPHINCS+" + +#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES +#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES +#define CRYPTO_BYTES SPX_BYTES +#define CRYPTO_SEEDBYTES (3*SPX_N) + +/* + * Returns the length of a secret key, in bytes + */ +#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) +size_t crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) +size_t crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) +size_t crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) +size_t crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +#define crypto_sign SPX_NAMESPACE(crypto_sign) +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/params.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/params.h new file mode 100644 index 0000000000..8be4f22f30 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/params.h @@ -0,0 +1,56 @@ +#ifndef SPX_PARAMS_H +#define SPX_PARAMS_H + +#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSSHAKE128FROBUST_CLEAN_##s + +/* Hash output length in bytes. */ +#define SPX_N 16 +/* Height of the hypertree. */ +#define SPX_FULL_HEIGHT 66 +/* Number of subtree layer. */ +#define SPX_D 22 +/* FORS tree dimensions. */ +#define SPX_FORS_HEIGHT 6 +#define SPX_FORS_TREES 33 +/* Winternitz parameter, */ +#define SPX_WOTS_W 16 + +/* The hash function is defined by linking a different hash.c file, as opposed + to setting a #define constant. */ + +/* For clarity */ +#define SPX_ADDR_BYTES 32 + +/* WOTS parameters. */ +#define SPX_WOTS_LOGW 4 + +#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) + +/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ +#define SPX_WOTS_LEN2 3 + +#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) +#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) +#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES + +/* Subtree size. */ +#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) + +//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT +// #error SPX_D should always divide SPX_FULL_HEIGHT +//#endif + +/* FORS parameters. */ +#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) +#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) +#define SPX_FORS_PK_BYTES SPX_N + +/* Resulting SPX sizes. */ +#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ + SPX_FULL_HEIGHT * SPX_N) +#define SPX_PK_BYTES (2 * SPX_N) +#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) + +#include "shake_offsets.h" + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/shake_offsets.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/shake_offsets.h new file mode 100644 index 0000000000..6b28d95d91 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/shake_offsets.h @@ -0,0 +1,21 @@ +#ifndef SHAKE_OFFSETS_H_ +#define SHAKE_OFFSETS_H_ + +/* + * Offsets of various fields in the address structure when we use SHAKE as + * the Sphincs+ hash function + */ + +#define SPX_OFFSET_LAYER 3 /* The byte used to specify the Merkle tree layer */ +#define SPX_OFFSET_TREE 8 /* The start of the 8 byte field used to specify the tree */ +#define SPX_OFFSET_TYPE 19 /* The byte used to specify the hash type (reason) */ +#define SPX_OFFSET_KP_ADDR2 22 /* The high byte used to specify the key pair (which one-time signature) */ +#define SPX_OFFSET_KP_ADDR1 23 /* The low byte used to specify the key pair */ +#define SPX_OFFSET_CHAIN_ADDR 27 /* The byte used to specify the chain address (which Winternitz chain) */ +#define SPX_OFFSET_HASH_ADDR 31 /* The byte used to specify the hash address (where in the Winternitz chain) */ +#define SPX_OFFSET_TREE_HGT 27 /* The byte used to specify the height of this node in the FORS or Merkle tree */ +#define SPX_OFFSET_TREE_INDEX 28 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ + +#define SPX_SHAKE 1 + +#endif /* SHAKE_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/sign.c b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/sign.c new file mode 100644 index 0000000000..9d0c7d1b22 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/sign.c @@ -0,0 +1,286 @@ +#include +#include +#include + +#include "address.h" +#include "context.h" +#include "fors.h" +#include "hash.h" +#include "merkle.h" +#include "nistapi.h" +#include "params.h" +#include "randombytes.h" +#include "thash.h" +#include "utils.h" +#include "wots.h" + +/* + * Returns the length of a secret key, in bytes + */ +size_t crypto_sign_secretkeybytes(void) { + return CRYPTO_SECRETKEYBYTES; +} + +/* + * Returns the length of a public key, in bytes + */ +size_t crypto_sign_publickeybytes(void) { + return CRYPTO_PUBLICKEYBYTES; +} + +/* + * Returns the length of a signature, in bytes + */ +size_t crypto_sign_bytes(void) { + return CRYPTO_BYTES; +} + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +size_t crypto_sign_seedbytes(void) { + return CRYPTO_SEEDBYTES; +} + +/* + * Generates an SPX key pair given a seed of length + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [PUB_SEED || root] + */ +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed) { + spx_ctx ctx; + + /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ + memcpy(sk, seed, CRYPTO_SEEDBYTES); + + memcpy(pk, sk + 2 * SPX_N, SPX_N); + + memcpy(ctx.pub_seed, pk, SPX_N); + memcpy(ctx.sk_seed, sk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + /* Compute root node of the top-most subtree. */ + merkle_gen_root(sk + 3 * SPX_N, &ctx); + + // cleanup + free_hash_function(&ctx); + + memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); + + return 0; +} + +/* + * Generates an SPX key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [PUB_SEED || root] + */ +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { + uint8_t seed[CRYPTO_SEEDBYTES]; + randombytes(seed, CRYPTO_SEEDBYTES); + crypto_sign_seed_keypair(pk, sk, seed); + + return 0; +} + +/** + * Returns an array containing a detached signature. + */ +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk) { + spx_ctx ctx; + + const uint8_t *sk_prf = sk + SPX_N; + const uint8_t *pk = sk + 2 * SPX_N; + + uint8_t optrand[SPX_N]; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t root[SPX_N]; + uint32_t i; + uint64_t tree; + uint32_t idx_leaf; + uint32_t wots_addr[8] = {0}; + uint32_t tree_addr[8] = {0}; + + memcpy(ctx.sk_seed, sk, SPX_N); + memcpy(ctx.pub_seed, pk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + + /* Optionally, signing can be made non-deterministic using optrand. + This can help counter side-channel attacks that would benefit from + getting a large number of traces when the signer uses the same nodes. */ + randombytes(optrand, SPX_N); + /* Compute the digest randomization value. */ + gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); + + /* Derive the message digest and leaf index from R, PK and M. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; + + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); + + /* Sign the message hash using FORS. */ + fors_sign(sig, root, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); + sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; + + /* Update the indices for the next layer. */ + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; + } + + free_hash_function(&ctx); + + *siglen = SPX_BYTES; + + return 0; +} + +/** + * Verifies a detached signature and message under a given public key. + */ +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk) { + spx_ctx ctx; + const uint8_t *pub_root = pk + SPX_N; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t wots_pk[SPX_WOTS_BYTES]; + uint8_t root[SPX_N]; + uint8_t leaf[SPX_N]; + unsigned int i; + uint64_t tree; + uint32_t idx_leaf; + uint32_t wots_addr[8] = {0}; + uint32_t tree_addr[8] = {0}; + uint32_t wots_pk_addr[8] = {0}; + + if (siglen != SPX_BYTES) { + return -1; + } + + memcpy(ctx.pub_seed, pk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); + + /* Derive the message digest and leaf index from R || PK || M. */ + /* The additional SPX_N is a result of the hash domain separator. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; + + /* Layer correctly defaults to 0, so no need to set_layer_addr */ + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); + + fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + /* For each subtree.. */ + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + copy_keypair_addr(wots_pk_addr, wots_addr); + + /* The WOTS public key is only correct if the signature was correct. */ + /* Initially, root is the FORS pk, but on subsequent iterations it is + the root of the subtree below the currently processed subtree. */ + wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); + sig += SPX_WOTS_BYTES; + + /* Compute the leaf node using the WOTS public key. */ + thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); + + /* Compute the root node of this subtree. */ + compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, + &ctx, tree_addr); + sig += SPX_TREE_HEIGHT * SPX_N; + + /* Update the indices for the next layer. */ + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; + } + + // cleanup + free_hash_function(&ctx); + + /* Check if the root node equals the root node in the public key. */ + if (memcmp(root, pub_root, SPX_N) != 0) { + return -1; + } + + return 0; +} + + +/** + * Returns an array containing the signature followed by the message. + */ +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk) { + size_t siglen; + + crypto_sign_signature(sm, &siglen, m, mlen, sk); + + memmove(sm + SPX_BYTES, m, mlen); + *smlen = siglen + mlen; + + return 0; +} + +/** + * Verifies a given signature-message pair under a given public key. + */ +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk) { + /* The API caller does not necessarily know what size a signature should be + but SPHINCS+ signatures are always exactly SPX_BYTES. */ + if (smlen < SPX_BYTES) { + memset(m, 0, smlen); + *mlen = 0; + return -1; + } + + *mlen = smlen - SPX_BYTES; + + if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { + memset(m, 0, smlen); + *mlen = 0; + return -1; + } + + /* If verification was successful, move the message to the right place. */ + memmove(m, sm + SPX_BYTES, *mlen); + + return 0; +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/thash.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/thash.h new file mode 100644 index 0000000000..8687ccfb4d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/thash.h @@ -0,0 +1,13 @@ +#ifndef SPX_THASH_H +#define SPX_THASH_H + +#include "context.h" +#include "params.h" + +#include + +#define thash SPX_NAMESPACE(thash) +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/thash_shake_robust.c b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/thash_shake_robust.c new file mode 100644 index 0000000000..696d53c5cc --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/thash_shake_robust.c @@ -0,0 +1,31 @@ +#include +#include + +#include "thash.h" + +#include "address.h" +#include "params.h" +#include "utils.h" + +#include "fips202.h" + +/** + * Takes an array of inblocks concatenated arrays of SPX_N bytes. + */ +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]) { + PQCLEAN_VLA(uint8_t, buf, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); + PQCLEAN_VLA(uint8_t, bitmask, inblocks * SPX_N); + unsigned int i; + + memcpy(buf, ctx->pub_seed, SPX_N); + memcpy(buf + SPX_N, addr, SPX_ADDR_BYTES); + + shake256(bitmask, inblocks * SPX_N, buf, SPX_N + SPX_ADDR_BYTES); + + for (i = 0; i < inblocks * SPX_N; i++) { + buf[SPX_N + SPX_ADDR_BYTES + i] = in[i] ^ bitmask[i]; + } + + shake256(out, SPX_N, buf, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/utils.c b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/utils.c new file mode 100644 index 0000000000..177b541fb9 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/utils.c @@ -0,0 +1,148 @@ +#include + +#include "utils.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "thash.h" + +/** + * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. + */ +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in) { + int i; + + /* Iterate over out in decreasing order, for big-endianness. */ + for (i = (signed int)outlen - 1; i >= 0; i--) { + out[i] = in & 0xff; + in = in >> 8; + } +} + +void u32_to_bytes(unsigned char *out, uint32_t in) { + out[0] = (unsigned char)(in >> 24); + out[1] = (unsigned char)(in >> 16); + out[2] = (unsigned char)(in >> 8); + out[3] = (unsigned char)in; +} + +/** + * Converts the inlen bytes in 'in' from big-endian byte order to an integer. + */ +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { + unsigned long long retval = 0; + unsigned int i; + + for (i = 0; i < inlen; i++) { + retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); + } + return retval; +} + +/** + * Computes a root node given a leaf and an auth path. + * Expects address to be complete other than the tree_height and tree_index. + */ +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]) { + uint32_t i; + unsigned char buffer[2 * SPX_N]; + + /* If leaf_idx is odd (last bit = 1), current path element is a right child + and auth_path has to go left. Otherwise it is the other way around. */ + if (leaf_idx & 1) { + memcpy(buffer + SPX_N, leaf, SPX_N); + memcpy(buffer, auth_path, SPX_N); + } else { + memcpy(buffer, leaf, SPX_N); + memcpy(buffer + SPX_N, auth_path, SPX_N); + } + auth_path += SPX_N; + + for (i = 0; i < tree_height - 1; i++) { + leaf_idx >>= 1; + idx_offset >>= 1; + /* Set the address of the node we're creating. */ + set_tree_height(addr, i + 1); + set_tree_index(addr, leaf_idx + idx_offset); + + /* Pick the right or left neighbor, depending on parity of the node. */ + if (leaf_idx & 1) { + thash(buffer + SPX_N, buffer, 2, ctx, addr); + memcpy(buffer, auth_path, SPX_N); + } else { + thash(buffer, buffer, 2, ctx, addr); + memcpy(buffer + SPX_N, auth_path, SPX_N); + } + auth_path += SPX_N; + } + + /* The last iteration is exceptional; we do not copy an auth_path node. */ + leaf_idx >>= 1; + idx_offset >>= 1; + set_tree_height(addr, tree_height); + set_tree_index(addr, leaf_idx + idx_offset); + thash(root, buffer, 2, ctx, addr); +} + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx * /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]) { + PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); + PQCLEAN_VLA(unsigned int, heights, tree_height + 1); + unsigned int offset = 0; + uint32_t idx; + uint32_t tree_idx; + + for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { + /* Add the next leaf node to the stack. */ + gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); + offset++; + heights[offset - 1] = 0; + + /* If this is a node we need for the auth path.. */ + if ((leaf_idx ^ 0x1) == idx) { + memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); + } + + /* While the top-most nodes are of equal height.. */ + while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { + /* Compute index of the new node, in the next layer. */ + tree_idx = (idx >> (heights[offset - 1] + 1)); + + /* Set the address of the node we're creating. */ + set_tree_height(tree_addr, heights[offset - 1] + 1); + set_tree_index(tree_addr, + tree_idx + (idx_offset >> (heights[offset - 1] + 1))); + /* Hash the top-most nodes from the stack together. */ + thash(stack + (offset - 2)*SPX_N, + stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); + offset--; + /* Note that the top-most node is now one layer higher. */ + heights[offset - 1]++; + + /* If this is a node we need for the auth path.. */ + if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { + memcpy(auth_path + heights[offset - 1]*SPX_N, + stack + (offset - 1)*SPX_N, SPX_N); + } + } + } + memcpy(root, stack, SPX_N); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/utils.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/utils.h new file mode 100644 index 0000000000..64f5d5a53a --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/utils.h @@ -0,0 +1,58 @@ +#ifndef SPX_UTILS_H +#define SPX_UTILS_H + +#include + +#include "compat.h" +#include "context.h" +#include "params.h" + + +/* To support MSVC use alloca() instead of VLAs. See #20. */ + + +/** + * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. + */ +#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in); +#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) +void u32_to_bytes(unsigned char *out, uint32_t in); + +/** + * Converts the inlen bytes in 'in' from big-endian byte order to an integer. + */ +#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); + +/** + * Computes a root node given a leaf and an auth path. + * Expects address to be complete other than the tree_height and tree_index. + */ +#define compute_root SPX_NAMESPACE(compute_root) +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]); + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +#define treehash SPX_NAMESPACE(treehash) +void treehash(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx *ctx /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]); + + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/utilsx1.c b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/utilsx1.c new file mode 100644 index 0000000000..fccb69b35d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/utilsx1.c @@ -0,0 +1,100 @@ +#include + +#include "utilsx1.h" + +#include "address.h" +#include "params.h" +#include "thash.h" +#include "utils.h" + +/* + * Generate the entire Merkle tree, computing the authentication path for + * leaf_idx, and the resulting root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) + * + * This expects tree_addr to be initialized to the addr structures for the + * Merkle tree nodes + * + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + * + * This works by using the standard Merkle tree building algorithm, + */ +void treehashx1(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, + uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* Where to write the leaves */, + const spx_ctx * /* ctx */, + uint32_t idx, void *info), + uint32_t tree_addr[8], + void *info) { + /* This is where we keep the intermediate nodes */ + PQCLEAN_VLA(uint8_t, stack, tree_height * SPX_N); + + uint32_t idx; + uint32_t max_idx = (uint32_t)((1 << tree_height) - 1); + for (idx = 0;; idx++) { + unsigned char current[2 * SPX_N]; /* Current logical node is at */ + /* index[SPX_N]. We do this to minimize the number of copies */ + /* needed during a thash */ + gen_leaf( ¤t[SPX_N], ctx, idx + idx_offset, + info ); + + /* Now combine the freshly generated right node with previously */ + /* generated left ones */ + uint32_t internal_idx_offset = idx_offset; + uint32_t internal_idx = idx; + uint32_t internal_leaf = leaf_idx; + uint32_t h; /* The height we are in the Merkle tree */ + for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { + + /* Check if we hit the top of the tree */ + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[SPX_N], SPX_N ); + return; + } + + /* + * Check if the node we have is a part of the + * authentication path; if it is, write it out + */ + if ((internal_idx ^ internal_leaf) == 0x01) { + memcpy( &auth_path[ h * SPX_N ], + ¤t[SPX_N], + SPX_N ); + } + + /* + * Check if we're at a left child; if so, stop going up the stack + * Exception: if we've reached the end of the tree, keep on going + * (so we combine the last 4 nodes into the one root node in two + * more iterations) + */ + if ((internal_idx & 1) == 0 && idx < max_idx) { + break; + } + + /* Ok, we're at a right node */ + /* Now combine the left and right logical nodes together */ + + /* Set the address of the node we're creating. */ + internal_idx_offset >>= 1; + set_tree_height(tree_addr, h + 1); + set_tree_index(tree_addr, internal_idx / 2 + internal_idx_offset ); + + unsigned char *left = &stack[h * SPX_N]; + memcpy( ¤t[0], left, SPX_N ); + thash( ¤t[1 * SPX_N], + ¤t[0 * SPX_N], + 2, ctx, tree_addr); + } + + /* We've hit a left child; save the current for when we get the */ + /* corresponding right right */ + memcpy( &stack[h * SPX_N], ¤t[SPX_N], SPX_N); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/utilsx1.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/utilsx1.h new file mode 100644 index 0000000000..e911d17d53 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/utilsx1.h @@ -0,0 +1,27 @@ +#ifndef SPX_UTILSX4_H +#define SPX_UTILSX4_H + +#include + +#include "context.h" +#include "params.h" + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +#define treehashx1 SPX_NAMESPACE(treehashx1) +void treehashx1(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* Where to write the leaf */, + const spx_ctx * /* ctx */, + uint32_t addr_idx, void *info), + uint32_t tree_addrx4[8], void *info); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/wots.c b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/wots.c new file mode 100644 index 0000000000..249717aaa8 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/wots.c @@ -0,0 +1,108 @@ +#include +#include + +#include "wots.h" +#include "wotsx1.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "thash.h" +#include "utils.h" +#include "utilsx1.h" + +// TODO clarify address expectations, and make them more uniform. +// TODO i.e. do we expect types to be set already? +// TODO and do we expect modifications or copies? + +/** + * Computes the chaining function. + * out and in have to be n-byte arrays. + * + * Interprets in as start-th value of the chain. + * addr has to contain the address of the chain. + */ +static void gen_chain(unsigned char *out, const unsigned char *in, + unsigned int start, unsigned int steps, + const spx_ctx *ctx, uint32_t addr[8]) { + uint32_t i; + + /* Initialize out with the value at position 'start'. */ + memcpy(out, in, SPX_N); + + /* Iterate 'steps' calls to the hash function. */ + for (i = start; i < (start + steps) && i < SPX_WOTS_W; i++) { + set_hash_addr(addr, i); + thash(out, out, 1, ctx, addr); + } +} + +/** + * base_w algorithm as described in draft. + * Interprets an array of bytes as integers in base w. + * This only works when log_w is a divisor of 8. + */ +static void base_w(unsigned int *output, const int out_len, + const unsigned char *input) { + int in = 0; + int out = 0; + unsigned char total = 0; + int bits = 0; + int consumed; + + for (consumed = 0; consumed < out_len; consumed++) { + if (bits == 0) { + total = input[in]; + in++; + bits += 8; + } + bits -= SPX_WOTS_LOGW; + output[out] = (total >> bits) & (SPX_WOTS_W - 1); + out++; + } +} + +/* Computes the WOTS+ checksum over a message (in base_w). */ +static void wots_checksum(unsigned int *csum_base_w, + const unsigned int *msg_base_w) { + unsigned int csum = 0; + unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; + unsigned int i; + + /* Compute checksum. */ + for (i = 0; i < SPX_WOTS_LEN1; i++) { + csum += SPX_WOTS_W - 1 - msg_base_w[i]; + } + + /* Convert checksum to base_w. */ + /* Make sure expected empty zero bits are the least significant bits. */ + csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); + ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); + base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); +} + +/* Takes a message and derives the matching chain lengths. */ +void chain_lengths(unsigned int *lengths, const unsigned char *msg) { + base_w(lengths, SPX_WOTS_LEN1, msg); + wots_checksum(lengths + SPX_WOTS_LEN1, lengths); +} + +/** + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. + * + * Writes the computed public key to 'pk'. + */ +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]) { + unsigned int lengths[SPX_WOTS_LEN]; + uint32_t i; + + chain_lengths(lengths, msg); + + for (i = 0; i < SPX_WOTS_LEN; i++) { + set_chain_addr(addr, i); + gen_chain(pk + i * SPX_N, sig + i * SPX_N, + lengths[i], SPX_WOTS_W - 1 - lengths[i], ctx, addr); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/wots.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/wots.h new file mode 100644 index 0000000000..4e7692eeef --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/wots.h @@ -0,0 +1,25 @@ +#ifndef SPX_WOTS_H +#define SPX_WOTS_H + +#include + +#include "context.h" +#include "params.h" + +/** + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. + * + * Writes the computed public key to 'pk'. + */ +#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]); + +/* + * Compute the chain lengths needed for a given message hash + */ +#define chain_lengths SPX_NAMESPACE(chain_lengths) +void chain_lengths(unsigned int *lengths, const unsigned char *msg); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/wotsx1.c b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/wotsx1.c new file mode 100644 index 0000000000..3adec78dfb --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/wotsx1.c @@ -0,0 +1,76 @@ +#include +#include + +#include "wots.h" +#include "wotsx1.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "thash.h" +#include "utils.h" + +/* + * This generates a WOTS public key + * It also generates the WOTS signature if leaf_info indicates + * that we're signing with this WOTS key + */ +void wots_gen_leafx1(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info) { + struct leaf_info_x1 *info = v_info; + uint32_t *leaf_addr = info->leaf_addr; + uint32_t *pk_addr = info->pk_addr; + unsigned int i, k; + unsigned char pk_buffer[ SPX_WOTS_BYTES ]; + unsigned char *buffer; + uint32_t wots_k_mask; + + if (leaf_idx == info->wots_sign_leaf) { + /* We're traversing the leaf that's signing; generate the WOTS */ + /* signature */ + wots_k_mask = 0; + } else { + /* Nope, we're just generating pk's; turn off the signature logic */ + wots_k_mask = (uint32_t)~0; + } + + set_keypair_addr( leaf_addr, leaf_idx ); + set_keypair_addr( pk_addr, leaf_idx ); + + for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { + uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k to */ + /* the step if we're generating a signature, ~0 if we're not */ + + /* Start with the secret seed */ + set_chain_addr(leaf_addr, i); + set_hash_addr(leaf_addr, 0); + set_type(leaf_addr, SPX_ADDR_TYPE_WOTSPRF); + + prf_addr(buffer, ctx, leaf_addr); + + set_type(leaf_addr, SPX_ADDR_TYPE_WOTS); + + /* Iterate down the WOTS chain */ + for (k = 0;; k++) { + /* Check if this is the value that needs to be saved as a */ + /* part of the WOTS signature */ + if (k == wots_k) { + memcpy( info->wots_sig + i * SPX_N, buffer, SPX_N ); + } + + /* Check if we hit the top of the chain */ + if (k == SPX_WOTS_W - 1) { + break; + } + + /* Iterate one step on the chain */ + set_hash_addr(leaf_addr, k); + + thash(buffer, buffer, 1, ctx, leaf_addr); + } + } + + /* Do the final thash to generate the public keys */ + thash(dest, pk_buffer, SPX_WOTS_LEN, ctx, pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/wotsx1.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/wotsx1.h new file mode 100644 index 0000000000..e617929f96 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/wotsx1.h @@ -0,0 +1,39 @@ +#ifndef WOTSX1_H_ +#define WOTSX1_H_ + +#include + +#include "context.h" +#include "params.h" + +/* + * This is here to provide an interface to the internal wots_gen_leafx1 + * routine. While this routine is not referenced in the package outside of + * wots.c, it is called from the stand-alone benchmark code to characterize + * the performance + */ +struct leaf_info_x1 { + unsigned char *wots_sig; + uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ + uint32_t *wots_steps; + uint32_t leaf_addr[8]; + uint32_t pk_addr[8]; +}; + +/* Macro to set the leaf_info to something 'benign', that is, it would */ +/* run with the same time as it does during the real signing process */ +/* Used only by the benchmark code */ +#define INITIALIZE_LEAF_INFO_X1(info, addr, step_buffer) { \ + (info).wots_sig = 0; \ + (info).wots_sign_leaf = ~0; \ + (info).wots_steps = step_buffer; \ + memcpy( &(info).leaf_addr[0], (addr), 32 ); \ + memcpy( &(info).pk_addr[0], (addr), 32 ); \ + } + +#define wots_gen_leafx1 SPX_NAMESPACE(wots_gen_leafx1) +void wots_gen_leafx1(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info); + +#endif /* WOTSX1_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/LICENSE b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/LICENSE new file mode 100644 index 0000000000..670154e353 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/LICENSE @@ -0,0 +1,116 @@ +CC0 1.0 Universal + +Statement of Purpose + +The laws of most jurisdictions throughout the world automatically confer +exclusive Copyright and Related Rights (defined below) upon the creator and +subsequent owner(s) (each and all, an "owner") of an original work of +authorship and/or a database (each, a "Work"). + +Certain owners wish to permanently relinquish those rights to a Work for the +purpose of contributing to a commons of creative, cultural and scientific +works ("Commons") that the public can reliably and without fear of later +claims of infringement build upon, modify, incorporate in other works, reuse +and redistribute as freely as possible in any form whatsoever and for any +purposes, including without limitation commercial purposes. These owners may +contribute to the Commons to promote the ideal of a free culture and the +further production of creative, cultural and scientific works, or to gain +reputation or greater distribution for their Work in part through the use and +efforts of others. + +For these and/or other purposes and motivations, and without any expectation +of additional consideration or compensation, the person associating CC0 with a +Work (the "Affirmer"), to the extent that he or she is an owner of Copyright +and Related Rights in the Work, voluntarily elects to apply CC0 to the Work +and publicly distribute the Work under its terms, with knowledge of his or her +Copyright and Related Rights in the Work and the meaning and intended legal +effect of CC0 on those rights. + +1. Copyright and Related Rights. A Work made available under CC0 may be +protected by copyright and related or neighboring rights ("Copyright and +Related Rights"). Copyright and Related Rights include, but are not limited +to, the following: + + i. the right to reproduce, adapt, distribute, perform, display, communicate, + and translate a Work; + + ii. moral rights retained by the original author(s) and/or performer(s); + + iii. publicity and privacy rights pertaining to a person's image or likeness + depicted in a Work; + + iv. rights protecting against unfair competition in regards to a Work, + subject to the limitations in paragraph 4(a), below; + + v. rights protecting the extraction, dissemination, use and reuse of data in + a Work; + + vi. database rights (such as those arising under Directive 96/9/EC of the + European Parliament and of the Council of 11 March 1996 on the legal + protection of databases, and under any national implementation thereof, + including any amended or successor version of such directive); and + + vii. other similar, equivalent or corresponding rights throughout the world + based on applicable law or treaty, and any national implementations thereof. + +2. Waiver. To the greatest extent permitted by, but not in contravention of, +applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and +unconditionally waives, abandons, and surrenders all of Affirmer's Copyright +and Related Rights and associated claims and causes of action, whether now +known or unknown (including existing as well as future claims and causes of +action), in the Work (i) in all territories worldwide, (ii) for the maximum +duration provided by applicable law or treaty (including future time +extensions), (iii) in any current or future medium and for any number of +copies, and (iv) for any purpose whatsoever, including without limitation +commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes +the Waiver for the benefit of each member of the public at large and to the +detriment of Affirmer's heirs and successors, fully intending that such Waiver +shall not be subject to revocation, rescission, cancellation, termination, or +any other legal or equitable action to disrupt the quiet enjoyment of the Work +by the public as contemplated by Affirmer's express Statement of Purpose. + +3. Public License Fallback. Should any part of the Waiver for any reason be +judged legally invalid or ineffective under applicable law, then the Waiver +shall be preserved to the maximum extent permitted taking into account +Affirmer's express Statement of Purpose. In addition, to the extent the Waiver +is so judged Affirmer hereby grants to each affected person a royalty-free, +non transferable, non sublicensable, non exclusive, irrevocable and +unconditional license to exercise Affirmer's Copyright and Related Rights in +the Work (i) in all territories worldwide, (ii) for the maximum duration +provided by applicable law or treaty (including future time extensions), (iii) +in any current or future medium and for any number of copies, and (iv) for any +purpose whatsoever, including without limitation commercial, advertising or +promotional purposes (the "License"). The License shall be deemed effective as +of the date CC0 was applied by Affirmer to the Work. Should any part of the +License for any reason be judged legally invalid or ineffective under +applicable law, such partial invalidity or ineffectiveness shall not +invalidate the remainder of the License, and in such case Affirmer hereby +affirms that he or she will not (i) exercise any of his or her remaining +Copyright and Related Rights in the Work or (ii) assert any associated claims +and causes of action with respect to the Work, in either case contrary to +Affirmer's express Statement of Purpose. + +4. Limitations and Disclaimers. + + a. No trademark or patent rights held by Affirmer are waived, abandoned, + surrendered, licensed or otherwise affected by this document. + + b. Affirmer offers the Work as-is and makes no representations or warranties + of any kind concerning the Work, express, implied, statutory or otherwise, + including without limitation warranties of title, merchantability, fitness + for a particular purpose, non infringement, or the absence of latent or + other defects, accuracy, or the present or absence of errors, whether or not + discoverable, all to the greatest extent permissible under applicable law. + + c. Affirmer disclaims responsibility for clearing rights of other persons + that may apply to the Work or any use thereof, including without limitation + any person's Copyright and Related Rights in the Work. Further, Affirmer + disclaims responsibility for obtaining any necessary consents, permissions + or other rights required for any use of the Work. + + d. Affirmer understands and acknowledges that Creative Commons is not a + party to this document and has no duty or obligation with respect to this + CC0 or use of the Work. + +For more information, please see + diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/address.c b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/address.c new file mode 100644 index 0000000000..b956e9cb29 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/address.c @@ -0,0 +1,91 @@ +#include +#include + +#include "address.h" +#include "params.h" +#include "utils.h" + +/* + * Specify which level of Merkle tree (the "layer") we're working on + */ +void set_layer_addr(uint32_t addr[8], uint32_t layer) { + ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; +} + +/* + * Specify which Merkle tree within the level (the "tree address") we're working on + */ +void set_tree_addr(uint32_t addr[8], uint64_t tree) { + ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); +} + +/* + * Specify the reason we'll use this address structure for, that is, what + * hash will we compute with it. This is used so that unrelated types of + * hashes don't accidentally get the same address structure. The type will be + * one of the SPX_ADDR_TYPE constants + */ +void set_type(uint32_t addr[8], uint32_t type) { + ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; +} + +/* + * Copy the layer and tree fields of the address structure. This is used + * when we're doing multiple types of hashes within the same Merkle tree + */ +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); +} + +/* These functions are used for OTS addresses. */ + +/* + * Specify which Merkle leaf we're working on; that is, which OTS keypair + * we're talking about. + */ +void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { + ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; +} + +/* + * Copy the layer, tree and keypair fields of the address structure. This is + * used when we're doing multiple things within the same OTS keypair + */ +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); + ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; +} + +/* + * Specify which Merkle chain within the OTS we're working with + * (the chain address) + */ +void set_chain_addr(uint32_t addr[8], uint32_t chain) { + ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; +} + +/* + * Specify where in the Merkle chain we are +* (the hash address) + */ +void set_hash_addr(uint32_t addr[8], uint32_t hash) { + ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; +} + +/* These functions are used for all hash tree addresses (including FORS). */ + +/* + * Specify the height of the node in the Merkle/FORS tree we are in + * (the tree height) + */ +void set_tree_height(uint32_t addr[8], uint32_t tree_height) { + ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; +} + +/* + * Specify the distance from the left edge of the node in the Merkle/FORS tree + * (the tree index) + */ +void set_tree_index(uint32_t addr[8], uint32_t tree_index) { + u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/address.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/address.h new file mode 100644 index 0000000000..24a84eb40c --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/address.h @@ -0,0 +1,52 @@ +#ifndef SPX_ADDRESS_H +#define SPX_ADDRESS_H + +#include + +#include "params.h" + +/* The hash types that are passed to set_type */ +#define SPX_ADDR_TYPE_WOTS 0 +#define SPX_ADDR_TYPE_WOTSPK 1 +#define SPX_ADDR_TYPE_HASHTREE 2 +#define SPX_ADDR_TYPE_FORSTREE 3 +#define SPX_ADDR_TYPE_FORSPK 4 +#define SPX_ADDR_TYPE_WOTSPRF 5 +#define SPX_ADDR_TYPE_FORSPRF 6 + +#define set_layer_addr SPX_NAMESPACE(set_layer_addr) +void set_layer_addr(uint32_t addr[8], uint32_t layer); + +#define set_tree_addr SPX_NAMESPACE(set_tree_addr) +void set_tree_addr(uint32_t addr[8], uint64_t tree); + +#define set_type SPX_NAMESPACE(set_type) +void set_type(uint32_t addr[8], uint32_t type); + +/* Copies the layer and tree part of one address into the other */ +#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); + +/* These functions are used for WOTS and FORS addresses. */ + +#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) +void set_keypair_addr(uint32_t addr[8], uint32_t keypair); + +#define set_chain_addr SPX_NAMESPACE(set_chain_addr) +void set_chain_addr(uint32_t addr[8], uint32_t chain); + +#define set_hash_addr SPX_NAMESPACE(set_hash_addr) +void set_hash_addr(uint32_t addr[8], uint32_t hash); + +#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); + +/* These functions are used for all hash tree addresses (including FORS). */ + +#define set_tree_height SPX_NAMESPACE(set_tree_height) +void set_tree_height(uint32_t addr[8], uint32_t tree_height); + +#define set_tree_index SPX_NAMESPACE(set_tree_index) +void set_tree_index(uint32_t addr[8], uint32_t tree_index); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/api.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/api.h new file mode 100644 index 0000000000..8de96f7e64 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/api.h @@ -0,0 +1,77 @@ +#ifndef PQCLEAN_SPHINCSSHAKE128FSIMPLE_AARCH64_API_H +#define PQCLEAN_SPHINCSSHAKE128FSIMPLE_AARCH64_API_H + +#include +#include + +#define PQCLEAN_SPHINCSSHAKE128FSIMPLE_AARCH64_CRYPTO_ALGNAME "SPHINCS+-shake-128f-simple" + +#define PQCLEAN_SPHINCSSHAKE128FSIMPLE_AARCH64_CRYPTO_SECRETKEYBYTES 64 +#define PQCLEAN_SPHINCSSHAKE128FSIMPLE_AARCH64_CRYPTO_PUBLICKEYBYTES 32 +#define PQCLEAN_SPHINCSSHAKE128FSIMPLE_AARCH64_CRYPTO_BYTES 17088 + +#define PQCLEAN_SPHINCSSHAKE128FSIMPLE_AARCH64_CRYPTO_SEEDBYTES 48 + +/* + * Returns the length of a secret key, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE128FSIMPLE_AARCH64_crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE128FSIMPLE_AARCH64_crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE128FSIMPLE_AARCH64_crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE128FSIMPLE_AARCH64_crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +int PQCLEAN_SPHINCSSHAKE128FSIMPLE_AARCH64_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +int PQCLEAN_SPHINCSSHAKE128FSIMPLE_AARCH64_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +int PQCLEAN_SPHINCSSHAKE128FSIMPLE_AARCH64_crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +int PQCLEAN_SPHINCSSHAKE128FSIMPLE_AARCH64_crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, + const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +int PQCLEAN_SPHINCSSHAKE128FSIMPLE_AARCH64_crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +int PQCLEAN_SPHINCSSHAKE128FSIMPLE_AARCH64_crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/context.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/context.h new file mode 100644 index 0000000000..6e0a33f3b7 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/context.h @@ -0,0 +1,19 @@ +#ifndef SPX_CONTEXT_H +#define SPX_CONTEXT_H + +#include + +#include "params.h" + +typedef struct { + uint8_t pub_seed[SPX_N]; + uint8_t sk_seed[SPX_N]; +} spx_ctx; + +#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) +void initialize_hash_function(spx_ctx *ctx); + +#define free_hash_function SPX_NAMESPACE(free_hash_function) +void free_hash_function(spx_ctx *ctx); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/context_shake.c b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/context_shake.c new file mode 100644 index 0000000000..9614a103d3 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/context_shake.c @@ -0,0 +1,12 @@ +#include "context.h" + +/* For SHAKE256, there is no immediate reason to initialize at the start, + so this function is an empty operation. */ +void initialize_hash_function(spx_ctx *ctx) { + (void)ctx; /* Suppress an 'unused parameter' warning. */ +} + +// in case the hash function api is heap-based. +void free_hash_function(spx_ctx *ctx) { + (void)ctx; +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/f1600x2.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/f1600x2.h new file mode 100644 index 0000000000..70d1af9f14 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/f1600x2.h @@ -0,0 +1,11 @@ +#ifndef SPX_F1600X2_H +#define SPX_F1600X2_H + +#include + +extern uint64_t f1600_RC[24]; +extern void _f1600x2(uint64_t *a, uint64_t *rc); + +#define f1600x2(s) do {_f1600x2((s), f1600_RC);} while(0) + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/f1600x2.s b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/f1600x2.s new file mode 100644 index 0000000000..640ed791ed --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/f1600x2.s @@ -0,0 +1,143 @@ +# From https://github.com/bwesterb/armed-keccak + +.macro round + # Execute theta, but without xoring into the state yet. + # Compute parities p[i] = a[i] ^ a[5+i] ^ ... ^ a[20+i]. + eor3.16b v25, v0, v5, v10 + eor3.16b v26, v1, v6, v11 + eor3.16b v27, v2, v7, v12 + eor3.16b v28, v3, v8, v13 + eor3.16b v29, v4, v9, v14 + + eor3.16b v25, v25, v15, v20 + eor3.16b v26, v26, v16, v21 + eor3.16b v27, v27, v17, v22 + eor3.16b v28, v28, v18, v23 + eor3.16b v29, v29, v19, v24 + + # d[0] = rotl(p[1], 1) ^ p[4] + rax1.2d v30, v29, v26 + # d[3] = rotl(p[4], 1) ^ p[2] + rax1.2d v29, v27, v29 + # d[1] = rotl(p[2], 1) ^ p[0] + rax1.2d v27, v25, v27 + # d[4] = rotl(p[0], 1) ^ p[3] + rax1.2d v25, v28, v25 + # d[2] = rotl(p[3], 1) ^ p[1] + rax1.2d v28, v26, v28 + + # Xor parities from step theta into the state at the same time + # as executing rho and pi. + eor.16b v0, v0, v30 + mov.16b v31, v1 + xar.2d v1, v6, v27, 20 + xar.2d v6, v9, v25, 44 + xar.2d v9, v22, v28, 3 + xar.2d v22, v14, v25, 25 + xar.2d v14, v20, v30, 46 + xar.2d v20, v2, v28, 2 + xar.2d v2, v12, v28, 21 + xar.2d v12, v13, v29, 39 + xar.2d v13, v19, v25, 56 + xar.2d v19, v23, v29, 8 + xar.2d v23, v15, v30, 23 + xar.2d v15, v4, v25, 37 + xar.2d v4, v24, v25, 50 + xar.2d v24, v21, v27, 62 + xar.2d v21, v8, v29, 9 + xar.2d v8, v16, v27, 19 + xar.2d v16, v5, v30, 28 + xar.2d v5, v3, v29, 36 + xar.2d v3, v18, v29, 43 + xar.2d v18, v17, v28, 49 + xar.2d v17, v11, v27, 54 + xar.2d v11, v7, v28, 58 + xar.2d v7, v10, v30, 61 + xar.2d v10, v31, v27, 63 + + # Chi + bcax.16b v25, v0, v2, v1 + bcax.16b v26, v1, v3, v2 + bcax.16b v2, v2, v4, v3 + bcax.16b v3, v3, v0, v4 + bcax.16b v4, v4, v1, v0 + mov.16b v0, v25 + mov.16b v1, v26 + + bcax.16b v25, v5, v7, v6 + bcax.16b v26, v6, v8, v7 + bcax.16b v7, v7, v9, v8 + bcax.16b v8, v8, v5, v9 + bcax.16b v9, v9, v6, v5 + mov.16b v5, v25 + mov.16b v6, v26 + + bcax.16b v25, v10, v12, v11 + bcax.16b v26, v11, v13, v12 + bcax.16b v12, v12, v14, v13 + bcax.16b v13, v13, v10, v14 + bcax.16b v14, v14, v11, v10 + mov.16b v10, v25 + mov.16b v11, v26 + + bcax.16b v25, v15, v17, v16 + bcax.16b v26, v16, v18, v17 + bcax.16b v17, v17, v19, v18 + bcax.16b v18, v18, v15, v19 + bcax.16b v19, v19, v16, v15 + mov.16b v15, v25 + mov.16b v16, v26 + + bcax.16b v25, v20, v22, v21 + bcax.16b v26, v21, v23, v22 + bcax.16b v22, v22, v24, v23 + bcax.16b v23, v23, v20, v24 + bcax.16b v24, v24, v21, v20 + mov.16b v20, v25 + mov.16b v21, v26 + + # iota + ld1r {v25.2d}, [x1], #8 + eor.16b v0, v0, v25 +.endm + +.align 4 +.global __f1600x2 +__f1600x2: + stp d8, d9, [sp,#-16]! + stp d10, d11, [sp,#-16]! + stp d12, d13, [sp,#-16]! + stp d14, d15, [sp,#-16]! + + mov x2, x0 + mov x3, #24 + + ld1.2d {v0, v1, v2, v3}, [x0], #64 + ld1.2d {v4, v5, v6, v7}, [x0], #64 + ld1.2d {v8, v9, v10, v11}, [x0], #64 + ld1.2d {v12, v13, v14, v15}, [x0], #64 + ld1.2d {v16, v17, v18, v19}, [x0], #64 + ld1.2d {v20, v21, v22, v23}, [x0], #64 + ld1.2d {v24}, [x0] + +loop: + round + + subs x3, x3, #1 + cbnz x3, loop + + mov x0, x2 + st1.2d {v0, v1, v2, v3}, [x0], #64 + st1.2d {v4, v5, v6, v7}, [x0], #64 + st1.2d {v8, v9, v10, v11}, [x0], #64 + st1.2d {v12, v13, v14, v15}, [x0], #64 + st1.2d {v16, v17, v18, v19}, [x0], #64 + st1.2d {v20, v21, v22, v23}, [x0], #64 + st1.2d {v24}, [x0] + + ldp d14, d15, [sp], #16 + ldp d12, d13, [sp], #16 + ldp d10, d11, [sp], #16 + ldp d8, d9, [sp], #16 + + ret lr diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/f1600x2_const.c b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/f1600x2_const.c new file mode 100644 index 0000000000..e49c0ba149 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/f1600x2_const.c @@ -0,0 +1,30 @@ +#include "f1600x2.h" + +uint64_t f1600_RC[24] = { + 0x0000000000000001, + 0x0000000000008082, + 0x800000000000808A, + 0x8000000080008000, + 0x000000000000808B, + 0x0000000080000001, + 0x8000000080008081, + 0x8000000000008009, + 0x000000000000008A, + 0x0000000000000088, + 0x0000000080008009, + 0x000000008000000A, + 0x000000008000808B, + 0x800000000000008B, + 0x8000000000008089, + 0x8000000000008003, + 0x8000000000008002, + 0x8000000000000080, + 0x000000000000800A, + 0x800000008000000A, + 0x8000000080008081, + 0x8000000000008080, + 0x0000000080000001, + 0x8000000080008008, +}; + + diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/fips202x2.c b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/fips202x2.c new file mode 100644 index 0000000000..4718c343bc --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/fips202x2.c @@ -0,0 +1,148 @@ +#include +#include + +#include "fips202x2.h" +#include "f1600x2.h" +#include "fips202.h" + +uint64_t load64(const unsigned char *x) { + unsigned long long r = 0, i; + + for (i = 0; i < 8; ++i) { + r |= (unsigned long long)x[i] << 8 * i; + } + return r; +} + +void store64(uint8_t *x, uint64_t u) { + unsigned int i; + + for (i = 0; i < 8; ++i) { + x[i] = (uint8_t)u; + u >>= 8; + } +} + +static void keccak_absorb2x(uint64_t *s, + unsigned int r, + const unsigned char *m0, + const unsigned char *m1, + unsigned long long int mlen, + unsigned char p) { + unsigned long long i; + unsigned char t0[200]; + unsigned char t1[200]; + + while (mlen >= r) { + for (i = 0; i < r / 8; ++i) { + s[2 * i + 0] ^= load64(m0 + 8 * i); + s[2 * i + 1] ^= load64(m1 + 8 * i); + } + + f1600x2(s); + mlen -= r; + m0 += r; + m1 += r; + } + + for (i = 0; i < r; ++i) { + t0[i] = 0; + t1[i] = 0; + } + for (i = 0; i < mlen; ++i) { + t0[i] = m0[i]; + t1[i] = m1[i]; + } + + t0[i] = p; + t1[i] = p; + + t0[r - 1] |= 128; + t1[r - 1] |= 128; + + for (i = 0; i < r / 8; ++i) { + s[2 * i + 0] ^= load64(t0 + 8 * i); + s[2 * i + 1] ^= load64(t1 + 8 * i); + } +} + + +static void keccak_squeezeblocks2x(unsigned char *h0, + unsigned char *h1, + unsigned long long int nblocks, + uint64_t *s, + unsigned int r) { + unsigned int i; + + while (nblocks > 0) { + f1600x2(s); + for (i = 0; i < (r >> 3); i++) { + store64(h0 + 8 * i, s[2 * i + 0]); + store64(h1 + 8 * i, s[2 * i + 1]); + } + h0 += r; + h1 += r; + nblocks--; + } +} + + + +void shake128x2(unsigned char *out0, + unsigned char *out1, + unsigned long long outlen, + unsigned char *in0, + unsigned char *in1, + unsigned long long inlen) { + uint64_t s[50] = {0}; + unsigned char t0[SHAKE128_RATE]; + unsigned char t1[SHAKE128_RATE]; + unsigned int i; + + /* absorb 4 message of identical length in parallel */ + keccak_absorb2x(s, SHAKE128_RATE, in0, in1, inlen, 0x1F); + + /* Squeeze output */ + keccak_squeezeblocks2x(out0, out1, outlen / SHAKE128_RATE, s, SHAKE128_RATE); + + out0 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; + out1 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; + + if (outlen % SHAKE128_RATE) { + keccak_squeezeblocks2x(t0, t1, 1, s, SHAKE128_RATE); + for (i = 0; i < outlen % SHAKE128_RATE; i++) { + out0[i] = t0[i]; + out1[i] = t1[i]; + } + } +} + + +void shake256x2(unsigned char *out0, + unsigned char *out1, + unsigned long long outlen, + unsigned char *in0, + unsigned char *in1, + unsigned long long inlen) { + uint64_t s[50] = {0}; + unsigned char t0[SHAKE256_RATE]; + unsigned char t1[SHAKE256_RATE]; + unsigned int i; + + /* absorb 2 message of identical length in parallel */ + keccak_absorb2x(s, SHAKE256_RATE, in0, in1, inlen, 0x1F); + + /* Squeeze output */ + keccak_squeezeblocks2x(out0, out1, outlen / SHAKE256_RATE, s, SHAKE256_RATE); + + out0 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; + out1 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; + + if (outlen % SHAKE256_RATE) { + keccak_squeezeblocks2x(t0, t1, 1, s, SHAKE256_RATE); + for (i = 0; i < outlen % SHAKE256_RATE; i++) { + out0[i] = t0[i]; + out1[i] = t1[i]; + } + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/fips202x2.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/fips202x2.h new file mode 100644 index 0000000000..7ba58b35d8 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/fips202x2.h @@ -0,0 +1,24 @@ +#ifndef SPX_FIPS202X2_H +#define SPX_FIPS202X2_H + +#include + +uint64_t load64(const unsigned char *x); +void store64(uint8_t *x, uint64_t u); + + +void shake128x2(unsigned char *out0, + unsigned char *out1, + unsigned long long outlen, + unsigned char *in0, + unsigned char *in1, + unsigned long long inlen); + +void shake256x2(unsigned char *out0, + unsigned char *out1, + unsigned long long outlen, + unsigned char *in0, + unsigned char *in1, + unsigned long long inlen); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/fors.c b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/fors.c new file mode 100644 index 0000000000..39193d04e2 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/fors.c @@ -0,0 +1,191 @@ +#include +#include +#include + +#include "fors.h" + +#include "address.h" +#include "hash.h" +#include "hashx2.h" +#include "thash.h" +#include "thashx2.h" +#include "utils.h" +#include "utilsx2.h" + +static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + prf_addr(sk, ctx, fors_leaf_addr); +} + +static void fors_gen_skx2(unsigned char *sk0, + unsigned char *sk1, + const spx_ctx *ctx, + uint32_t fors_leaf_addrx2[2 * 8]) { + prf_addrx2(sk0, sk1, + ctx, fors_leaf_addrx2); +} + +static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, + const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + thash(leaf, sk, 1, ctx, fors_leaf_addr); +} + +static void fors_sk_to_leafx2(unsigned char *leaf0, + unsigned char *leaf1, + const unsigned char *sk0, + const unsigned char *sk1, + const spx_ctx *ctx, + uint32_t fors_leaf_addrx2[2 * 8]) { + thashx2(leaf0, leaf1, + sk0, sk1, + 1, ctx, fors_leaf_addrx2); +} + +struct fors_gen_leaf_info { + uint32_t leaf_addrx[2 * 8]; +}; + +static void fors_gen_leafx2(unsigned char *leaf, + const spx_ctx *ctx, + uint32_t addr_idx, void *info) { + struct fors_gen_leaf_info *fors_info = info; + uint32_t *fors_leaf_addrx2 = fors_info->leaf_addrx; + unsigned int j; + + /* Only set the parts that the caller doesn't set */ + for (j = 0; j < 2; j++) { + set_tree_index(fors_leaf_addrx2 + j * 8, addr_idx + j); + set_type(fors_leaf_addrx2 + j * 8, SPX_ADDR_TYPE_FORSPRF); + } + + fors_gen_skx2(leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + ctx, fors_leaf_addrx2); + + for (j = 0; j < 2; j++) { + set_type(fors_leaf_addrx2 + j * 8, SPX_ADDR_TYPE_FORSTREE); + } + + fors_sk_to_leafx2(leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + ctx, fors_leaf_addrx2); +} + +/** + * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + * Assumes indices has space for SPX_FORS_TREES integers. + */ +static void message_to_indices(uint32_t *indices, const unsigned char *m) { + unsigned int i, j; + unsigned int offset = 0; + + for (i = 0; i < SPX_FORS_TREES; i++) { + indices[i] = 0; + for (j = 0; j < SPX_FORS_HEIGHT; j++) { + indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); + offset++; + } + } +} + +/** + * Signs a message m, deriving the secret key from sk_seed and the FTS address. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + uint32_t fors_tree_addr[2 * 8] = {0}; + struct fors_gen_leaf_info fors_info = {0}; + uint32_t *fors_leaf_addr = fors_info.leaf_addrx; + uint32_t fors_pk_addr[8] = {0}; + uint32_t idx_offset; + unsigned int i; + + for (i = 0; i < 2; i++) { + copy_keypair_addr(fors_tree_addr + 8 * i, fors_addr); + set_type(fors_tree_addr + 8 * i, SPX_ADDR_TYPE_FORSTREE); + copy_keypair_addr(fors_leaf_addr + 8 * i, fors_addr); + } + copy_keypair_addr(fors_pk_addr, fors_addr); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); + + message_to_indices(indices, m); + + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); + + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + + /* Include the secret key part that produces the selected leaf node. */ + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); + fors_gen_sk(sig, ctx, fors_tree_addr); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + sig += SPX_N; + + /* Compute the authentication path for this leaf node. */ + treehashx2(roots + i * SPX_N, sig, ctx, + indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx2, + fors_tree_addr, &fors_info); + + sig += SPX_N * SPX_FORS_HEIGHT; + } + + /* Hash horizontally across all tree roots to derive the public key. */ + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); +} + +/** + * Derives the FORS public key from a signature. + * This can be used for verification by comparing to a known public key, or to + * subsequently verify a signature on the derived public key. The latter is the + * typical use-case when used as an FTS below an OTS in a hypertree. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + unsigned char leaf[SPX_N]; + uint32_t fors_tree_addr[8] = {0}; + uint32_t fors_pk_addr[8] = {0}; + uint32_t idx_offset; + unsigned int i; + + copy_keypair_addr(fors_tree_addr, fors_addr); + copy_keypair_addr(fors_pk_addr, fors_addr); + + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); + + message_to_indices(indices, m); + + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); + + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + + /* Derive the leaf from the included secret key part. */ + fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); + sig += SPX_N; + + /* Derive the corresponding root node of this tree. */ + compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, + sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); + sig += SPX_N * SPX_FORS_HEIGHT; + } + + /* Hash horizontally across all tree roots to derive the public key. */ + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/fors.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/fors.h new file mode 100644 index 0000000000..509140a178 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/fors.h @@ -0,0 +1,32 @@ +#ifndef SPX_FORS_H +#define SPX_FORS_H + +#include + +#include "context.h" +#include "params.h" + +/** + * Signs a message m, deriving the secret key from sk_seed and the FTS address. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +#define fors_sign SPX_NAMESPACE(fors_sign) +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); + +/** + * Derives the FORS public key from a signature. + * This can be used for verification by comparing to a known public key, or to + * subsequently verify a signature on the derived public key. The latter is the + * typical use-case when used as an FTS below an OTS in a hypertree. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/hash.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/hash.h new file mode 100644 index 0000000000..f7c87d4c3c --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/hash.h @@ -0,0 +1,28 @@ +#ifndef SPX_HASH_H +#define SPX_HASH_H + +#include +#include + +#include "context.h" +#include "params.h" + +#define prf_addr SPX_NAMESPACE(prf_addr) +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]); + +#define gen_message_random SPX_NAMESPACE(gen_message_random) +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); + +#define hash_message SPX_NAMESPACE(hash_message) +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); + + + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/hash_shake.c b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/hash_shake.c new file mode 100644 index 0000000000..ff5e7ec918 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/hash_shake.c @@ -0,0 +1,83 @@ +#include +#include + +#include "hash.h" + +#include "address.h" +#include "fips202.h" +#include "params.h" +#include "utils.h" + +/* + * Computes PRF(pk_seed, sk_seed, addr) + */ +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]) { + unsigned char buf[2 * SPX_N + SPX_ADDR_BYTES]; + + memcpy(buf, ctx->pub_seed, SPX_N); + memcpy(buf + SPX_N, addr, SPX_ADDR_BYTES); + memcpy(buf + SPX_N + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); + + shake256(out, SPX_N, buf, 2 * SPX_N + SPX_ADDR_BYTES); +} + +/** + * Computes the message-dependent randomness R, using a secret seed and an + * optional randomization value as well as the message. + */ +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { + (void)ctx; + shake256incctx s_inc; + + shake256_inc_init(&s_inc); + shake256_inc_absorb(&s_inc, sk_prf, SPX_N); + shake256_inc_absorb(&s_inc, optrand, SPX_N); + shake256_inc_absorb(&s_inc, m, mlen); + shake256_inc_finalize(&s_inc); + shake256_inc_squeeze(R, SPX_N, &s_inc); + shake256_inc_ctx_release(&s_inc); +} + +/** + * Computes the message hash using R, the public key, and the message. + * Outputs the message digest and the index of the leaf. The index is split in + * the tree index and the leaf index, for convenient copying to an address. + */ +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { + (void)ctx; +#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) +#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) +#define SPX_LEAF_BITS SPX_TREE_HEIGHT +#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) +#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) + + unsigned char buf[SPX_DGST_BYTES]; + unsigned char *bufp = buf; + shake256incctx s_inc; + + shake256_inc_init(&s_inc); + shake256_inc_absorb(&s_inc, R, SPX_N); + shake256_inc_absorb(&s_inc, pk, SPX_PK_BYTES); + shake256_inc_absorb(&s_inc, m, mlen); + shake256_inc_finalize(&s_inc); + shake256_inc_squeeze(buf, SPX_DGST_BYTES, &s_inc); + shake256_inc_ctx_release(&s_inc); + + memcpy(digest, bufp, SPX_FORS_MSG_BYTES); + bufp += SPX_FORS_MSG_BYTES; + + + *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); + *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); + bufp += SPX_TREE_BYTES; + + *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); + *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/hash_shakex2.c b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/hash_shakex2.c new file mode 100644 index 0000000000..99571916a2 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/hash_shakex2.c @@ -0,0 +1,52 @@ +#include +#include + +#include "hashx2.h" + +#include "address.h" +#include "f1600x2.h" +#include "fips202x2.h" +#include "params.h" + +/* + * 2-way parallel version of prf_addr; takes 2x as much input and output + */ +void prf_addrx2(unsigned char *out0, + unsigned char *out1, + const spx_ctx *ctx, + const uint32_t addrx2[2 * 8]) { + /* As we write and read only a few quadwords, it is more efficient to + * build and extract from the fourway SHAKE256 state by hand. */ + uint64_t state[50] = {0}; + + for (int i = 0; i < SPX_N / 8; i++) { + uint64_t x = load64(ctx->pub_seed + 8 * i); + state[2 * i] = x; + state[2 * i + 1] = x; + } + for (int i = 0; i < 4; i++) { + state[2 * (SPX_N / 8 + i)] = (((uint64_t)addrx2[1 + 2 * i]) << 32) + | (uint64_t)addrx2[2 * i]; + state[2 * (SPX_N / 8 + i) + 1] = (((uint64_t)addrx2[8 + 1 + 2 * i]) << 32) + | (uint64_t)addrx2[8 + 2 * i]; + } + for (int i = 0; i < SPX_N / 8; i++) { + uint64_t x = load64(ctx->sk_seed + 8 * i); + state[2 * (SPX_N / 8 + i + 4)] = x; + state[2 * (SPX_N / 8 + i + 4) + 1] = x; + } + + /* SHAKE domain separator and padding. */ + state[2 * (SPX_N / 4 + 4)] = 0x1f; + state[2 * (SPX_N / 4 + 4) + 1] = 0x1f; + + state[2 * 16] = 0x80ULL << 56; + state[2 * 16 + 1] = 0x80ULL << 56; + + f1600x2(state); + + for (int i = 0; i < SPX_N / 8; i++) { + store64(out0 + 8 * i, state[2 * i]); + store64(out1 + 8 * i, state[2 * i + 1]); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/hashx2.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/hashx2.h new file mode 100644 index 0000000000..99b8873a9b --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/hashx2.h @@ -0,0 +1,14 @@ +#ifndef SPX_HASHX2_H +#define SPX_HASHX2_H + +#include "context.h" +#include "params.h" +#include + +#define prf_addrx2 SPX_NAMESPACE(prf_addrx2) +void prf_addrx2(unsigned char *out0, + unsigned char *out1, + const spx_ctx *ctx, + const uint32_t addrx2[2 * 8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/merkle.c b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/merkle.c new file mode 100644 index 0000000000..c94ee23939 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/merkle.c @@ -0,0 +1,64 @@ +#include +#include + +#include "merkle.h" + +#include "address.h" +#include "params.h" +#include "utils.h" +#include "utilsx2.h" +#include "wots.h" +#include "wotsx2.h" + +/* + * This generates a Merkle signature (WOTS signature followed by the Merkle + * authentication path). + */ +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf) { + unsigned char *auth_path = sig + SPX_WOTS_BYTES; + uint32_t tree_addrx2[2 * 8] = { 0 }; + int j; + struct leaf_info_x2 info = { 0 }; + unsigned steps[ SPX_WOTS_LEN ]; + + info.wots_sig = sig; + chain_lengths(steps, root); + info.wots_steps = steps; + + for (j = 0; j < 2; j++) { + set_type(&tree_addrx2[8 * j], SPX_ADDR_TYPE_HASHTREE); + set_type(&info.leaf_addr[8 * j], SPX_ADDR_TYPE_WOTS); + set_type(&info.pk_addr[8 * j], SPX_ADDR_TYPE_WOTSPK); + copy_subtree_addr(&tree_addrx2[8 * j], tree_addr); + copy_subtree_addr(&info.leaf_addr[8 * j], wots_addr); + copy_subtree_addr(&info.pk_addr[8 * j], wots_addr); + } + + info.wots_sign_leaf = idx_leaf; + + treehashx2(root, auth_path, ctx, + idx_leaf, 0, + SPX_TREE_HEIGHT, + wots_gen_leafx2, + tree_addrx2, &info); +} + +/* Compute root node of the top-most subtree. */ +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { + /* We do not need the auth path in key generation, but it simplifies the + code to have just one treehash routine that computes both root and path + in one function. */ + unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; + uint32_t top_tree_addr[8] = {0}; + uint32_t wots_addr[8] = {0}; + + set_layer_addr(top_tree_addr, SPX_D - 1); + set_layer_addr(wots_addr, SPX_D - 1); + + merkle_sign(auth_path, root, ctx, + wots_addr, top_tree_addr, + ~0 /* ~0 means "don't bother generating an auth path */ ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/merkle.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/merkle.h new file mode 100644 index 0000000000..769cf2e970 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/merkle.h @@ -0,0 +1,21 @@ +#ifndef MERKLE_H_ +#define MERKLE_H_ + +#include + +#include "context.h" +#include "params.h" + +/* Generate a Merkle signature (WOTS signature followed by the Merkle */ +/* authentication path) */ +#define merkle_sign SPX_NAMESPACE(merkle_sign) +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf); + +/* Compute the root node of the top-most subtree. */ +#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); + +#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/nistapi.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/nistapi.h new file mode 100644 index 0000000000..3cb71afad4 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/nistapi.h @@ -0,0 +1,87 @@ +#ifndef SPX_API_H +#define SPX_API_H + +#include +#include + +#include "params.h" + +#define CRYPTO_ALGNAME "SPHINCS+" + +#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES +#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES +#define CRYPTO_BYTES SPX_BYTES +#define CRYPTO_SEEDBYTES (3*SPX_N) + +/* + * Returns the length of a secret key, in bytes + */ +#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) +size_t crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) +size_t crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) +size_t crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) +size_t crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +#define crypto_sign SPX_NAMESPACE(crypto_sign) +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/params.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/params.h new file mode 100644 index 0000000000..c28eb3ec56 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/params.h @@ -0,0 +1,56 @@ +#ifndef SPX_PARAMS_H +#define SPX_PARAMS_H + +#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSSHAKE128FSIMPLE_AARCH64_##s + +/* Hash output length in bytes. */ +#define SPX_N 16 +/* Height of the hypertree. */ +#define SPX_FULL_HEIGHT 66 +/* Number of subtree layer. */ +#define SPX_D 22 +/* FORS tree dimensions. */ +#define SPX_FORS_HEIGHT 6 +#define SPX_FORS_TREES 33 +/* Winternitz parameter, */ +#define SPX_WOTS_W 16 + +/* The hash function is defined by linking a different hash.c file, as opposed + to setting a #define constant. */ + +/* For clarity */ +#define SPX_ADDR_BYTES 32 + +/* WOTS parameters. */ +#define SPX_WOTS_LOGW 4 + +#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) + +/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ +#define SPX_WOTS_LEN2 3 + +#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) +#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) +#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES + +/* Subtree size. */ +#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) + +//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT +// #error SPX_D should always divide SPX_FULL_HEIGHT +//#endif + +/* FORS parameters. */ +#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) +#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) +#define SPX_FORS_PK_BYTES SPX_N + +/* Resulting SPX sizes. */ +#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ + SPX_FULL_HEIGHT * SPX_N) +#define SPX_PK_BYTES (2 * SPX_N) +#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) + +#include "shake_offsets.h" + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/shake_offsets.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/shake_offsets.h new file mode 100644 index 0000000000..6b28d95d91 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/shake_offsets.h @@ -0,0 +1,21 @@ +#ifndef SHAKE_OFFSETS_H_ +#define SHAKE_OFFSETS_H_ + +/* + * Offsets of various fields in the address structure when we use SHAKE as + * the Sphincs+ hash function + */ + +#define SPX_OFFSET_LAYER 3 /* The byte used to specify the Merkle tree layer */ +#define SPX_OFFSET_TREE 8 /* The start of the 8 byte field used to specify the tree */ +#define SPX_OFFSET_TYPE 19 /* The byte used to specify the hash type (reason) */ +#define SPX_OFFSET_KP_ADDR2 22 /* The high byte used to specify the key pair (which one-time signature) */ +#define SPX_OFFSET_KP_ADDR1 23 /* The low byte used to specify the key pair */ +#define SPX_OFFSET_CHAIN_ADDR 27 /* The byte used to specify the chain address (which Winternitz chain) */ +#define SPX_OFFSET_HASH_ADDR 31 /* The byte used to specify the hash address (where in the Winternitz chain) */ +#define SPX_OFFSET_TREE_HGT 27 /* The byte used to specify the height of this node in the FORS or Merkle tree */ +#define SPX_OFFSET_TREE_INDEX 28 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ + +#define SPX_SHAKE 1 + +#endif /* SHAKE_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/sign.c b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/sign.c new file mode 100644 index 0000000000..9d0c7d1b22 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/sign.c @@ -0,0 +1,286 @@ +#include +#include +#include + +#include "address.h" +#include "context.h" +#include "fors.h" +#include "hash.h" +#include "merkle.h" +#include "nistapi.h" +#include "params.h" +#include "randombytes.h" +#include "thash.h" +#include "utils.h" +#include "wots.h" + +/* + * Returns the length of a secret key, in bytes + */ +size_t crypto_sign_secretkeybytes(void) { + return CRYPTO_SECRETKEYBYTES; +} + +/* + * Returns the length of a public key, in bytes + */ +size_t crypto_sign_publickeybytes(void) { + return CRYPTO_PUBLICKEYBYTES; +} + +/* + * Returns the length of a signature, in bytes + */ +size_t crypto_sign_bytes(void) { + return CRYPTO_BYTES; +} + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +size_t crypto_sign_seedbytes(void) { + return CRYPTO_SEEDBYTES; +} + +/* + * Generates an SPX key pair given a seed of length + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [PUB_SEED || root] + */ +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed) { + spx_ctx ctx; + + /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ + memcpy(sk, seed, CRYPTO_SEEDBYTES); + + memcpy(pk, sk + 2 * SPX_N, SPX_N); + + memcpy(ctx.pub_seed, pk, SPX_N); + memcpy(ctx.sk_seed, sk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + /* Compute root node of the top-most subtree. */ + merkle_gen_root(sk + 3 * SPX_N, &ctx); + + // cleanup + free_hash_function(&ctx); + + memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); + + return 0; +} + +/* + * Generates an SPX key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [PUB_SEED || root] + */ +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { + uint8_t seed[CRYPTO_SEEDBYTES]; + randombytes(seed, CRYPTO_SEEDBYTES); + crypto_sign_seed_keypair(pk, sk, seed); + + return 0; +} + +/** + * Returns an array containing a detached signature. + */ +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk) { + spx_ctx ctx; + + const uint8_t *sk_prf = sk + SPX_N; + const uint8_t *pk = sk + 2 * SPX_N; + + uint8_t optrand[SPX_N]; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t root[SPX_N]; + uint32_t i; + uint64_t tree; + uint32_t idx_leaf; + uint32_t wots_addr[8] = {0}; + uint32_t tree_addr[8] = {0}; + + memcpy(ctx.sk_seed, sk, SPX_N); + memcpy(ctx.pub_seed, pk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + + /* Optionally, signing can be made non-deterministic using optrand. + This can help counter side-channel attacks that would benefit from + getting a large number of traces when the signer uses the same nodes. */ + randombytes(optrand, SPX_N); + /* Compute the digest randomization value. */ + gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); + + /* Derive the message digest and leaf index from R, PK and M. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; + + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); + + /* Sign the message hash using FORS. */ + fors_sign(sig, root, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); + sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; + + /* Update the indices for the next layer. */ + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; + } + + free_hash_function(&ctx); + + *siglen = SPX_BYTES; + + return 0; +} + +/** + * Verifies a detached signature and message under a given public key. + */ +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk) { + spx_ctx ctx; + const uint8_t *pub_root = pk + SPX_N; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t wots_pk[SPX_WOTS_BYTES]; + uint8_t root[SPX_N]; + uint8_t leaf[SPX_N]; + unsigned int i; + uint64_t tree; + uint32_t idx_leaf; + uint32_t wots_addr[8] = {0}; + uint32_t tree_addr[8] = {0}; + uint32_t wots_pk_addr[8] = {0}; + + if (siglen != SPX_BYTES) { + return -1; + } + + memcpy(ctx.pub_seed, pk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); + + /* Derive the message digest and leaf index from R || PK || M. */ + /* The additional SPX_N is a result of the hash domain separator. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; + + /* Layer correctly defaults to 0, so no need to set_layer_addr */ + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); + + fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + /* For each subtree.. */ + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + copy_keypair_addr(wots_pk_addr, wots_addr); + + /* The WOTS public key is only correct if the signature was correct. */ + /* Initially, root is the FORS pk, but on subsequent iterations it is + the root of the subtree below the currently processed subtree. */ + wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); + sig += SPX_WOTS_BYTES; + + /* Compute the leaf node using the WOTS public key. */ + thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); + + /* Compute the root node of this subtree. */ + compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, + &ctx, tree_addr); + sig += SPX_TREE_HEIGHT * SPX_N; + + /* Update the indices for the next layer. */ + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; + } + + // cleanup + free_hash_function(&ctx); + + /* Check if the root node equals the root node in the public key. */ + if (memcmp(root, pub_root, SPX_N) != 0) { + return -1; + } + + return 0; +} + + +/** + * Returns an array containing the signature followed by the message. + */ +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk) { + size_t siglen; + + crypto_sign_signature(sm, &siglen, m, mlen, sk); + + memmove(sm + SPX_BYTES, m, mlen); + *smlen = siglen + mlen; + + return 0; +} + +/** + * Verifies a given signature-message pair under a given public key. + */ +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk) { + /* The API caller does not necessarily know what size a signature should be + but SPHINCS+ signatures are always exactly SPX_BYTES. */ + if (smlen < SPX_BYTES) { + memset(m, 0, smlen); + *mlen = 0; + return -1; + } + + *mlen = smlen - SPX_BYTES; + + if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { + memset(m, 0, smlen); + *mlen = 0; + return -1; + } + + /* If verification was successful, move the message to the right place. */ + memmove(m, sm + SPX_BYTES, *mlen); + + return 0; +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/thash.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/thash.h new file mode 100644 index 0000000000..8687ccfb4d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/thash.h @@ -0,0 +1,13 @@ +#ifndef SPX_THASH_H +#define SPX_THASH_H + +#include "context.h" +#include "params.h" + +#include + +#define thash SPX_NAMESPACE(thash) +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/thash_shake_simplex2.c b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/thash_shake_simplex2.c new file mode 100644 index 0000000000..892e453690 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/thash_shake_simplex2.c @@ -0,0 +1,83 @@ +#include +#include + +#include "thash.h" +#include "thashx2.h" + +#include "address.h" +#include "params.h" +#include "utils.h" + +#include "f1600x2.h" +#include "fips202x2.h" + + +void thash(unsigned char *out, + const unsigned char *in, + unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]) { + uint32_t addrx2 [2 * 8] = { + addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], addr[6], addr[7], + addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], addr[6], addr[7] + }; + thashx2(out, out, in, in, inblocks, ctx, addrx2); +} + +/** + * 2-way parallel version of thash; takes 2x as much input and output + */ +void thashx2(unsigned char *out0, + unsigned char *out1, + const unsigned char *in0, + const unsigned char *in1, + unsigned int inblocks, + const spx_ctx *ctx, uint32_t addrx2[2 * 8]) { + if (inblocks == 1 || inblocks == 2) { + /* As we write and read only a few quadwords, it is more efficient to + * build and extract from the twoway SHAKE256 state by hand. */ + uint64_t state[50] = {0}; + for (int i = 0; i < SPX_N / 8; i++) { + uint64_t x = load64(ctx->pub_seed + 8 * i); + state[2 * i] = x; + state[2 * i + 1] = x; + } + for (int i = 0; i < 4; i++) { + state[2 * (SPX_N / 8 + i)] = (((uint64_t)addrx2[1 + 2 * i]) << 32) + | (uint64_t)addrx2[2 * i]; + state[2 * (SPX_N / 8 + i) + 1] = (((uint64_t)addrx2[8 + 1 + 2 * i]) << 32) + | (uint64_t)addrx2[8 + 2 * i]; + } + + for (unsigned int i = 0; i < (SPX_N / 8) * inblocks; i++) { + state[2 * (SPX_N / 8 + 4 + i)] = load64(in0 + 8 * i); + state[2 * (SPX_N / 8 + 4 + i) + 1] = load64(in1 + 8 * i); + } + + /* Domain separator and padding. */ + state[2 * 16] = 0x80ULL << 56; + state[2 * 16 + 1] = 0x80ULL << 56; + + state[2 * ((SPX_N / 8) * (1 + inblocks) + 4)] ^= 0x1f; + state[2 * ((SPX_N / 8) * (1 + inblocks) + 4) + 1] ^= 0x1f; + + f1600x2(state); + + for (int i = 0; i < SPX_N / 8; i++) { + store64(out0 + 8 * i, state[2 * i]); + store64(out1 + 8 * i, state[2 * i + 1]); + } + } else { + PQCLEAN_VLA(unsigned char, buf0, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, buf1, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); + + memcpy(buf0, ctx->pub_seed, SPX_N); + memcpy(buf1, ctx->pub_seed, SPX_N); + memcpy(buf0 + SPX_N, addrx2 + 0 * 8, SPX_ADDR_BYTES); + memcpy(buf1 + SPX_N, addrx2 + 1 * 8, SPX_ADDR_BYTES); + memcpy(buf0 + SPX_N + SPX_ADDR_BYTES, in0, inblocks * SPX_N); + memcpy(buf1 + SPX_N + SPX_ADDR_BYTES, in1, inblocks * SPX_N); + + shake256x2(out0, out1, SPX_N, + buf0, buf1, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/thashx2.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/thashx2.h new file mode 100644 index 0000000000..040375e618 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/thashx2.h @@ -0,0 +1,16 @@ +#ifndef SPX_THASHX2_H +#define SPX_THASHX2_H + +#include "context.h" +#include "params.h" +#include + +#define thashx2 SPX_NAMESPACE(thashx2) +void thashx2(unsigned char *out0, + unsigned char *out1, + const unsigned char *in0, + const unsigned char *in1, + unsigned int inblocks, + const spx_ctx *ctx, uint32_t addrx2[2 * 8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/utils.c b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/utils.c new file mode 100644 index 0000000000..177b541fb9 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/utils.c @@ -0,0 +1,148 @@ +#include + +#include "utils.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "thash.h" + +/** + * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. + */ +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in) { + int i; + + /* Iterate over out in decreasing order, for big-endianness. */ + for (i = (signed int)outlen - 1; i >= 0; i--) { + out[i] = in & 0xff; + in = in >> 8; + } +} + +void u32_to_bytes(unsigned char *out, uint32_t in) { + out[0] = (unsigned char)(in >> 24); + out[1] = (unsigned char)(in >> 16); + out[2] = (unsigned char)(in >> 8); + out[3] = (unsigned char)in; +} + +/** + * Converts the inlen bytes in 'in' from big-endian byte order to an integer. + */ +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { + unsigned long long retval = 0; + unsigned int i; + + for (i = 0; i < inlen; i++) { + retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); + } + return retval; +} + +/** + * Computes a root node given a leaf and an auth path. + * Expects address to be complete other than the tree_height and tree_index. + */ +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]) { + uint32_t i; + unsigned char buffer[2 * SPX_N]; + + /* If leaf_idx is odd (last bit = 1), current path element is a right child + and auth_path has to go left. Otherwise it is the other way around. */ + if (leaf_idx & 1) { + memcpy(buffer + SPX_N, leaf, SPX_N); + memcpy(buffer, auth_path, SPX_N); + } else { + memcpy(buffer, leaf, SPX_N); + memcpy(buffer + SPX_N, auth_path, SPX_N); + } + auth_path += SPX_N; + + for (i = 0; i < tree_height - 1; i++) { + leaf_idx >>= 1; + idx_offset >>= 1; + /* Set the address of the node we're creating. */ + set_tree_height(addr, i + 1); + set_tree_index(addr, leaf_idx + idx_offset); + + /* Pick the right or left neighbor, depending on parity of the node. */ + if (leaf_idx & 1) { + thash(buffer + SPX_N, buffer, 2, ctx, addr); + memcpy(buffer, auth_path, SPX_N); + } else { + thash(buffer, buffer, 2, ctx, addr); + memcpy(buffer + SPX_N, auth_path, SPX_N); + } + auth_path += SPX_N; + } + + /* The last iteration is exceptional; we do not copy an auth_path node. */ + leaf_idx >>= 1; + idx_offset >>= 1; + set_tree_height(addr, tree_height); + set_tree_index(addr, leaf_idx + idx_offset); + thash(root, buffer, 2, ctx, addr); +} + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx * /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]) { + PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); + PQCLEAN_VLA(unsigned int, heights, tree_height + 1); + unsigned int offset = 0; + uint32_t idx; + uint32_t tree_idx; + + for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { + /* Add the next leaf node to the stack. */ + gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); + offset++; + heights[offset - 1] = 0; + + /* If this is a node we need for the auth path.. */ + if ((leaf_idx ^ 0x1) == idx) { + memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); + } + + /* While the top-most nodes are of equal height.. */ + while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { + /* Compute index of the new node, in the next layer. */ + tree_idx = (idx >> (heights[offset - 1] + 1)); + + /* Set the address of the node we're creating. */ + set_tree_height(tree_addr, heights[offset - 1] + 1); + set_tree_index(tree_addr, + tree_idx + (idx_offset >> (heights[offset - 1] + 1))); + /* Hash the top-most nodes from the stack together. */ + thash(stack + (offset - 2)*SPX_N, + stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); + offset--; + /* Note that the top-most node is now one layer higher. */ + heights[offset - 1]++; + + /* If this is a node we need for the auth path.. */ + if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { + memcpy(auth_path + heights[offset - 1]*SPX_N, + stack + (offset - 1)*SPX_N, SPX_N); + } + } + } + memcpy(root, stack, SPX_N); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/utils.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/utils.h new file mode 100644 index 0000000000..64f5d5a53a --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/utils.h @@ -0,0 +1,58 @@ +#ifndef SPX_UTILS_H +#define SPX_UTILS_H + +#include + +#include "compat.h" +#include "context.h" +#include "params.h" + + +/* To support MSVC use alloca() instead of VLAs. See #20. */ + + +/** + * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. + */ +#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in); +#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) +void u32_to_bytes(unsigned char *out, uint32_t in); + +/** + * Converts the inlen bytes in 'in' from big-endian byte order to an integer. + */ +#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); + +/** + * Computes a root node given a leaf and an auth path. + * Expects address to be complete other than the tree_height and tree_index. + */ +#define compute_root SPX_NAMESPACE(compute_root) +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]); + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +#define treehash SPX_NAMESPACE(treehash) +void treehash(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx *ctx /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]); + + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/utilsx2.c b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/utilsx2.c new file mode 100644 index 0000000000..8736474e4f --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/utilsx2.c @@ -0,0 +1,130 @@ +#include + +#include "utilsx2.h" + +#include "address.h" +#include "params.h" +#include "thashx2.h" +#include "utils.h" + +/* + * Generate the entire Merkle tree, computing the authentication path for leaf_idx, + * and the resulting root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) + * + * This expects tree_addrx2 to be initialized to 2 parallel addr structures for + * the Merkle tree nodes + * + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + * + * This works by using the standard Merkle tree building algorithm, except + * that each 'node' tracked is actually 2 consecutive nodes in the real tree. + * When we combine two logical nodes AB and WX, we perform the H + * operation on adjacent real nodes, forming the parent logical node + * (AB)(WX) + * + * When we get to the top level of the real tree (where there is only + * one logical node), we continue this operation one more time; the right + * most real node will by the actual root (and the other node will be + * garbage). We follow the same thashx2 logic so that the 'extract + * authentication path components' part of the loop is still executed (and + * to simplify the code somewhat) + */ +void treehashx2(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, + uint32_t tree_height, + void (*gen_leafx2)( + unsigned char * /* Where to write the leaves */, + const spx_ctx *, + uint32_t idx, void *info), + uint32_t tree_addrx2[2 * 8], + void *info) { + /* This is where we keep the intermediate nodes */ + unsigned char stackx2[tree_height * 2 * SPX_N]; + uint32_t left_adj = 0, prev_left_adj = 0; /* When we're doing the top */ + /* level, the left-most part of the tree isn't at the beginning */ + /* of current[]. These give the offset of the actual start */ + + uint32_t idx; + uint32_t max_idx = (1 << (tree_height - 1)) - 1; + for (idx = 0;; idx++) { + unsigned char current[2 * SPX_N]; /* Current logical node */ + gen_leafx2( current, ctx, 2 * idx + idx_offset, + info ); + + /* Now combine the freshly generated right node with previously */ + /* generated left ones */ + uint32_t internal_idx_offset = idx_offset; + uint32_t internal_idx = idx; + uint32_t internal_leaf = leaf_idx; + uint32_t h; /* The height we are in the Merkle tree */ + for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { + + /* Special processing if we're at the top of the tree */ + if (h >= tree_height - 1) { + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[1 * SPX_N], SPX_N ); + return; + } + /* The tree indexing logic is a bit off in this case */ + /* Adjust it so that the left-most node of the part of */ + /* the tree that we're processing has index 0 */ + prev_left_adj = left_adj; + left_adj = 2 - (1 << (tree_height - h - 1)); + } + + /* Check if we hit the top of the tree */ + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[1 * SPX_N], SPX_N ); + return; + } + + /* + * Check if one of the nodes we have is a part of the + * authentication path; if it is, write it out + */ + if ((((internal_idx << 1) ^ internal_leaf) & ~0x1) == 0) { + memcpy( &auth_path[ h * SPX_N ], + ¤t[(((internal_leaf & 1) ^ 1) + prev_left_adj) * SPX_N], + SPX_N ); + } + + /* + * Check if we're at a left child; if so, stop going up the stack + * Exception: if we've reached the end of the tree, keep on going + * (so we combine the last 2 nodes into the one root node in two + * more iterations) + */ + if ((internal_idx & 1) == 0 && idx < max_idx) { + break; + } + + /* Ok, we're at a right node (or doing the top 3 levels) */ + /* Now combine the left and right logical nodes together */ + + /* Set the address of the node we're creating. */ + int j; + internal_idx_offset >>= 1; + for (j = 0; j < 2; j++) { + set_tree_height(tree_addrx2 + j * 8, h + 1); + set_tree_index(tree_addrx2 + j * 8, + (2 / 2) * (internal_idx & ~1) + j - left_adj + internal_idx_offset ); + } + unsigned char *left = &stackx2[h * 2 * SPX_N]; + thashx2( ¤t[0 * SPX_N], + ¤t[1 * SPX_N], + &left [0 * SPX_N], + ¤t[0 * SPX_N], + 2, ctx, tree_addrx2); + } + + /* We've hit a left child; save the current for when we get the */ + /* corresponding right right */ + memcpy( &stackx2[h * 2 * SPX_N], current, 2 * SPX_N); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/utilsx2.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/utilsx2.h new file mode 100644 index 0000000000..e09faddc43 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/utilsx2.h @@ -0,0 +1,30 @@ +#ifndef SPX_UTILSX2_H +#define SPX_UTILSX2_H + +#include + +#include "context.h" +#include "params.h" + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + * + * This implementation uses SIMD to compute internal nodes 2 at a time (in + * parallel) + */ +#define treehashx2 SPX_NAMESPACE(treehashx2) +void treehashx2(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leafx2)( + unsigned char * /* Where to write the leaves */, + const spx_ctx * /* ctx */, + uint32_t addr_idx, void *info), + uint32_t tree_addrx2[2 * 8], void *info); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/wots.c b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/wots.c new file mode 100644 index 0000000000..3babe45e95 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/wots.c @@ -0,0 +1,259 @@ +#include +#include + +#include "wots.h" +#include "wotsx2.h" + +#include "address.h" +#include "hash.h" +#include "hashx2.h" +#include "params.h" +#include "thashx2.h" +#include "utils.h" +#include "utilsx2.h" + +// TODO clarify address expectations, and make them more uniform. +// TODO i.e. do we expect types to be set already? +// TODO and do we expect modifications or copies? + +/** + * Computes up the chains + */ +static void gen_chains( + unsigned char *out, + const unsigned char *in, + unsigned int start[SPX_WOTS_LEN], + const unsigned int steps[SPX_WOTS_LEN], + const spx_ctx *ctx, + uint32_t addr[8]) { + uint32_t i, j, k, idx, watching; + int done; + unsigned char empty[SPX_N]; + unsigned char *bufs[4]; + uint32_t addrs[8 * 2]; + + int l; + uint16_t counts[SPX_WOTS_W] = { 0 }; + uint16_t idxs[SPX_WOTS_LEN]; + uint16_t total, newTotal; + + /* set addrs = {addr, addr} */ + for (j = 0; j < 2; j++) { + memcpy(addrs + j * 8, addr, sizeof(uint32_t) * 8); + } + + /* Initialize out with the value at position 'start'. */ + memcpy(out, in, SPX_WOTS_LEN * SPX_N); + + /* Sort the chains in reverse order by steps using counting sort. */ + for (i = 0; i < SPX_WOTS_LEN; i++) { + counts[steps[i]]++; + } + total = 0; + for (l = SPX_WOTS_W - 1; l >= 0; l--) { + newTotal = counts[l] + total; + counts[l] = total; + total = newTotal; + } + for (i = 0; i < SPX_WOTS_LEN; i++) { + idxs[counts[steps[i]]] = i; + counts[steps[i]]++; + } + + /* We got our work cut out for us: do it! */ + for (i = 0; i < SPX_WOTS_LEN; i += 2) { + for (j = 0; j < 2 && i + j < SPX_WOTS_LEN; j++) { + idx = idxs[i + j]; + set_chain_addr(addrs + j * 8, idx); + bufs[j] = out + SPX_N * idx; + } + + /* As the chains are sorted in reverse order, we know that the first + * chain is the longest and the last one is the shortest. We keep + * an eye on whether the last chain is done and then on the one before, + * et cetera. */ + watching = 1; + done = 0; + while (i + watching >= SPX_WOTS_LEN) { + bufs[watching] = &empty[0]; + watching--; + } + + for (k = 0;; k++) { + while (k == steps[idxs[i + watching]]) { + bufs[watching] = &empty[0]; + if (watching == 0) { + done = 1; + break; + } + watching--; + } + if (done) { + break; + } + for (j = 0; j < watching + 1; j++) { + set_hash_addr(addrs + j * 8, k + start[idxs[i + j]]); + } + + thashx2(bufs[0], bufs[1], + bufs[0], bufs[1], 1, ctx, addrs); + } + } +} + +/** + * base_w algorithm as described in draft. + * Interprets an array of bytes as integers in base w. + * This only works when log_w is a divisor of 8. + */ +static void base_w(unsigned int *output, const int out_len, + const unsigned char *input) { + int in = 0; + int out = 0; + unsigned char total = 0; + int bits = 0; + int consumed; + + for (consumed = 0; consumed < out_len; consumed++) { + if (bits == 0) { + total = input[in]; + in++; + bits += 8; + } + bits -= SPX_WOTS_LOGW; + output[out] = (total >> bits) & (SPX_WOTS_W - 1); + out++; + } +} + +/* Computes the WOTS+ checksum over a message (in base_w). */ +static void wots_checksum(unsigned int *csum_base_w, + const unsigned int *msg_base_w) { + unsigned int csum = 0; + unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; + unsigned int i; + + /* Compute checksum. */ + for (i = 0; i < SPX_WOTS_LEN1; i++) { + csum += SPX_WOTS_W - 1 - msg_base_w[i]; + } + + /* Convert checksum to base_w. */ + /* Make sure expected empty zero bits are the least significant bits. */ + csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); + ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); + base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); +} + +/* Takes a message and derives the matching chain lengths. */ +void chain_lengths(unsigned int *lengths, const unsigned char *msg) { + base_w(lengths, SPX_WOTS_LEN1, msg); + wots_checksum(lengths + SPX_WOTS_LEN1, lengths); +} + +/** + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. + * + * Writes the computed public key to 'pk'. + */ +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]) { + unsigned int steps[SPX_WOTS_LEN]; + unsigned int start[SPX_WOTS_LEN]; + uint32_t i; + + chain_lengths(start, msg); + + for (i = 0; i < SPX_WOTS_LEN; i++) { + steps[i] = SPX_WOTS_W - 1 - start[i]; + } + + gen_chains(pk, sig, start, steps, ctx, addr); +} + +/* + * This generates 2 sequential WOTS public keys + * It also generates the WOTS signature if leaf_info indicates + * that we're signing with one of these WOTS keys + */ +void wots_gen_leafx2(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info) { + struct leaf_info_x2 *info = v_info; + uint32_t *leaf_addr = info->leaf_addr; + uint32_t *pk_addr = info->pk_addr; + unsigned int i, j, k; + unsigned char pk_buffer[ 2 * SPX_WOTS_BYTES ]; + unsigned wots_offset = SPX_WOTS_BYTES; + unsigned char *buffer; + uint32_t wots_k_mask; + unsigned wots_sign_index; + + if (((leaf_idx ^ info->wots_sign_leaf) & ~1) == 0) { + /* We're traversing the leaf that's signing; generate the WOTS */ + /* signature */ + wots_k_mask = 0; + wots_sign_index = info->wots_sign_leaf & 1; /* Which of of the 2 */ + /* slots do the signatures come from */ + } else { + /* Nope, we're just generating pk's; turn off the signature logic */ + wots_k_mask = ~0; + wots_sign_index = 0; + } + + for (j = 0; j < 2; j++) { + set_keypair_addr( leaf_addr + j * 8, leaf_idx + j ); + set_keypair_addr( pk_addr + j * 8, leaf_idx + j ); + } + + for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { + uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k to */ + /* the step if we're generating a signature, ~0 if we're not */ + + /* Start with the secret seed */ + for (j = 0; j < 2; j++) { + set_chain_addr(leaf_addr + j * 8, i); + set_hash_addr(leaf_addr + j * 8, 0); + set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTSPRF); + } + prf_addrx2(buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + ctx, leaf_addr); + for (j = 0; j < 2; j++) { + set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTS); + } + + /* Iterate down the WOTS chain */ + for (k = 0;; k++) { + /* Check if one of the values we have needs to be saved as a */ + /* part of the WOTS signature */ + if (k == wots_k) { + memcpy( info->wots_sig + i * SPX_N, + buffer + wots_sign_index * wots_offset, SPX_N ); + } + + /* Check if we hit the top of the chain */ + if (k == SPX_WOTS_W - 1) { + break; + } + + /* Iterate one step on all 4 chains */ + for (j = 0; j < 2; j++) { + set_hash_addr(leaf_addr + j * 8, k); + } + thashx2(buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + 1, ctx, leaf_addr); + } + } + + /* Do the final thash to generate the public keys */ + thashx2(dest + 0 * SPX_N, + dest + 1 * SPX_N, + pk_buffer + 0 * wots_offset, + pk_buffer + 1 * wots_offset, + SPX_WOTS_LEN, ctx, pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/wots.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/wots.h new file mode 100644 index 0000000000..4e7692eeef --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/wots.h @@ -0,0 +1,25 @@ +#ifndef SPX_WOTS_H +#define SPX_WOTS_H + +#include + +#include "context.h" +#include "params.h" + +/** + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. + * + * Writes the computed public key to 'pk'. + */ +#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]); + +/* + * Compute the chain lengths needed for a given message hash + */ +#define chain_lengths SPX_NAMESPACE(chain_lengths) +void chain_lengths(unsigned int *lengths, const unsigned char *msg); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/wotsx2.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/wotsx2.h new file mode 100644 index 0000000000..b58bb61f84 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_aarch64/wotsx2.h @@ -0,0 +1,40 @@ +#ifndef WOTSX2_H_ +#define WOTSX2_H_ + +#include "params.h" +#include + +/* + * This is here to provide an interface to the internal wots_gen_leafx2 + * routine. While this routine is not referenced in the package outside of + * wots.c, it is called from the stand-alone benchmark code to characterize + * the performance + */ +struct leaf_info_x2 { + unsigned char *wots_sig; + uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ + uint32_t *wots_steps; + uint32_t leaf_addr[2 * 8]; + uint32_t pk_addr[2 * 8]; +}; + +/* Macro to set the leaf_info to something 'benign', that is, it would */ +/* run with the same time as it does during the real signing process */ +/* Used only by the benchmark code */ +#define INITIALIZE_LEAF_INFO_X2(info, addr, step_buffer) { \ + (info).wots_sig = 0; \ + (info).wots_sign_leaf = ~0; \ + (info).wots_steps = step_buffer; \ + int i; \ + for (i=0; i<2; i++) { \ + memcpy( &(info).leaf_addr[8*i], addr, 32 ); \ + memcpy( &(info).pk_addr[8*i], addr, 32 ); \ + } \ + } + +#define wots_gen_leafx2 SPX_NAMESPACE(wots_gen_leafx2) +void wots_gen_leafx2(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info); + +#endif /* WOTSX2_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/LICENSE b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/LICENSE new file mode 100644 index 0000000000..670154e353 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/LICENSE @@ -0,0 +1,116 @@ +CC0 1.0 Universal + +Statement of Purpose + +The laws of most jurisdictions throughout the world automatically confer +exclusive Copyright and Related Rights (defined below) upon the creator and +subsequent owner(s) (each and all, an "owner") of an original work of +authorship and/or a database (each, a "Work"). + +Certain owners wish to permanently relinquish those rights to a Work for the +purpose of contributing to a commons of creative, cultural and scientific +works ("Commons") that the public can reliably and without fear of later +claims of infringement build upon, modify, incorporate in other works, reuse +and redistribute as freely as possible in any form whatsoever and for any +purposes, including without limitation commercial purposes. These owners may +contribute to the Commons to promote the ideal of a free culture and the +further production of creative, cultural and scientific works, or to gain +reputation or greater distribution for their Work in part through the use and +efforts of others. + +For these and/or other purposes and motivations, and without any expectation +of additional consideration or compensation, the person associating CC0 with a +Work (the "Affirmer"), to the extent that he or she is an owner of Copyright +and Related Rights in the Work, voluntarily elects to apply CC0 to the Work +and publicly distribute the Work under its terms, with knowledge of his or her +Copyright and Related Rights in the Work and the meaning and intended legal +effect of CC0 on those rights. + +1. Copyright and Related Rights. A Work made available under CC0 may be +protected by copyright and related or neighboring rights ("Copyright and +Related Rights"). Copyright and Related Rights include, but are not limited +to, the following: + + i. the right to reproduce, adapt, distribute, perform, display, communicate, + and translate a Work; + + ii. moral rights retained by the original author(s) and/or performer(s); + + iii. publicity and privacy rights pertaining to a person's image or likeness + depicted in a Work; + + iv. rights protecting against unfair competition in regards to a Work, + subject to the limitations in paragraph 4(a), below; + + v. rights protecting the extraction, dissemination, use and reuse of data in + a Work; + + vi. database rights (such as those arising under Directive 96/9/EC of the + European Parliament and of the Council of 11 March 1996 on the legal + protection of databases, and under any national implementation thereof, + including any amended or successor version of such directive); and + + vii. other similar, equivalent or corresponding rights throughout the world + based on applicable law or treaty, and any national implementations thereof. + +2. Waiver. To the greatest extent permitted by, but not in contravention of, +applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and +unconditionally waives, abandons, and surrenders all of Affirmer's Copyright +and Related Rights and associated claims and causes of action, whether now +known or unknown (including existing as well as future claims and causes of +action), in the Work (i) in all territories worldwide, (ii) for the maximum +duration provided by applicable law or treaty (including future time +extensions), (iii) in any current or future medium and for any number of +copies, and (iv) for any purpose whatsoever, including without limitation +commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes +the Waiver for the benefit of each member of the public at large and to the +detriment of Affirmer's heirs and successors, fully intending that such Waiver +shall not be subject to revocation, rescission, cancellation, termination, or +any other legal or equitable action to disrupt the quiet enjoyment of the Work +by the public as contemplated by Affirmer's express Statement of Purpose. + +3. Public License Fallback. Should any part of the Waiver for any reason be +judged legally invalid or ineffective under applicable law, then the Waiver +shall be preserved to the maximum extent permitted taking into account +Affirmer's express Statement of Purpose. In addition, to the extent the Waiver +is so judged Affirmer hereby grants to each affected person a royalty-free, +non transferable, non sublicensable, non exclusive, irrevocable and +unconditional license to exercise Affirmer's Copyright and Related Rights in +the Work (i) in all territories worldwide, (ii) for the maximum duration +provided by applicable law or treaty (including future time extensions), (iii) +in any current or future medium and for any number of copies, and (iv) for any +purpose whatsoever, including without limitation commercial, advertising or +promotional purposes (the "License"). The License shall be deemed effective as +of the date CC0 was applied by Affirmer to the Work. Should any part of the +License for any reason be judged legally invalid or ineffective under +applicable law, such partial invalidity or ineffectiveness shall not +invalidate the remainder of the License, and in such case Affirmer hereby +affirms that he or she will not (i) exercise any of his or her remaining +Copyright and Related Rights in the Work or (ii) assert any associated claims +and causes of action with respect to the Work, in either case contrary to +Affirmer's express Statement of Purpose. + +4. Limitations and Disclaimers. + + a. No trademark or patent rights held by Affirmer are waived, abandoned, + surrendered, licensed or otherwise affected by this document. + + b. Affirmer offers the Work as-is and makes no representations or warranties + of any kind concerning the Work, express, implied, statutory or otherwise, + including without limitation warranties of title, merchantability, fitness + for a particular purpose, non infringement, or the absence of latent or + other defects, accuracy, or the present or absence of errors, whether or not + discoverable, all to the greatest extent permissible under applicable law. + + c. Affirmer disclaims responsibility for clearing rights of other persons + that may apply to the Work or any use thereof, including without limitation + any person's Copyright and Related Rights in the Work. Further, Affirmer + disclaims responsibility for obtaining any necessary consents, permissions + or other rights required for any use of the Work. + + d. Affirmer understands and acknowledges that Creative Commons is not a + party to this document and has no duty or obligation with respect to this + CC0 or use of the Work. + +For more information, please see + diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/address.c b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/address.c new file mode 100644 index 0000000000..b956e9cb29 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/address.c @@ -0,0 +1,91 @@ +#include +#include + +#include "address.h" +#include "params.h" +#include "utils.h" + +/* + * Specify which level of Merkle tree (the "layer") we're working on + */ +void set_layer_addr(uint32_t addr[8], uint32_t layer) { + ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; +} + +/* + * Specify which Merkle tree within the level (the "tree address") we're working on + */ +void set_tree_addr(uint32_t addr[8], uint64_t tree) { + ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); +} + +/* + * Specify the reason we'll use this address structure for, that is, what + * hash will we compute with it. This is used so that unrelated types of + * hashes don't accidentally get the same address structure. The type will be + * one of the SPX_ADDR_TYPE constants + */ +void set_type(uint32_t addr[8], uint32_t type) { + ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; +} + +/* + * Copy the layer and tree fields of the address structure. This is used + * when we're doing multiple types of hashes within the same Merkle tree + */ +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); +} + +/* These functions are used for OTS addresses. */ + +/* + * Specify which Merkle leaf we're working on; that is, which OTS keypair + * we're talking about. + */ +void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { + ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; +} + +/* + * Copy the layer, tree and keypair fields of the address structure. This is + * used when we're doing multiple things within the same OTS keypair + */ +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); + ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; +} + +/* + * Specify which Merkle chain within the OTS we're working with + * (the chain address) + */ +void set_chain_addr(uint32_t addr[8], uint32_t chain) { + ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; +} + +/* + * Specify where in the Merkle chain we are +* (the hash address) + */ +void set_hash_addr(uint32_t addr[8], uint32_t hash) { + ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; +} + +/* These functions are used for all hash tree addresses (including FORS). */ + +/* + * Specify the height of the node in the Merkle/FORS tree we are in + * (the tree height) + */ +void set_tree_height(uint32_t addr[8], uint32_t tree_height) { + ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; +} + +/* + * Specify the distance from the left edge of the node in the Merkle/FORS tree + * (the tree index) + */ +void set_tree_index(uint32_t addr[8], uint32_t tree_index) { + u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/address.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/address.h new file mode 100644 index 0000000000..24a84eb40c --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/address.h @@ -0,0 +1,52 @@ +#ifndef SPX_ADDRESS_H +#define SPX_ADDRESS_H + +#include + +#include "params.h" + +/* The hash types that are passed to set_type */ +#define SPX_ADDR_TYPE_WOTS 0 +#define SPX_ADDR_TYPE_WOTSPK 1 +#define SPX_ADDR_TYPE_HASHTREE 2 +#define SPX_ADDR_TYPE_FORSTREE 3 +#define SPX_ADDR_TYPE_FORSPK 4 +#define SPX_ADDR_TYPE_WOTSPRF 5 +#define SPX_ADDR_TYPE_FORSPRF 6 + +#define set_layer_addr SPX_NAMESPACE(set_layer_addr) +void set_layer_addr(uint32_t addr[8], uint32_t layer); + +#define set_tree_addr SPX_NAMESPACE(set_tree_addr) +void set_tree_addr(uint32_t addr[8], uint64_t tree); + +#define set_type SPX_NAMESPACE(set_type) +void set_type(uint32_t addr[8], uint32_t type); + +/* Copies the layer and tree part of one address into the other */ +#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); + +/* These functions are used for WOTS and FORS addresses. */ + +#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) +void set_keypair_addr(uint32_t addr[8], uint32_t keypair); + +#define set_chain_addr SPX_NAMESPACE(set_chain_addr) +void set_chain_addr(uint32_t addr[8], uint32_t chain); + +#define set_hash_addr SPX_NAMESPACE(set_hash_addr) +void set_hash_addr(uint32_t addr[8], uint32_t hash); + +#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); + +/* These functions are used for all hash tree addresses (including FORS). */ + +#define set_tree_height SPX_NAMESPACE(set_tree_height) +void set_tree_height(uint32_t addr[8], uint32_t tree_height); + +#define set_tree_index SPX_NAMESPACE(set_tree_index) +void set_tree_index(uint32_t addr[8], uint32_t tree_index); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/api.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/api.h new file mode 100644 index 0000000000..3230031a82 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/api.h @@ -0,0 +1,77 @@ +#ifndef PQCLEAN_SPHINCSSHAKE128FSIMPLE_AVX2_API_H +#define PQCLEAN_SPHINCSSHAKE128FSIMPLE_AVX2_API_H + +#include +#include + +#define PQCLEAN_SPHINCSSHAKE128FSIMPLE_AVX2_CRYPTO_ALGNAME "SPHINCS+-shake-128f-simple" + +#define PQCLEAN_SPHINCSSHAKE128FSIMPLE_AVX2_CRYPTO_SECRETKEYBYTES 64 +#define PQCLEAN_SPHINCSSHAKE128FSIMPLE_AVX2_CRYPTO_PUBLICKEYBYTES 32 +#define PQCLEAN_SPHINCSSHAKE128FSIMPLE_AVX2_CRYPTO_BYTES 17088 + +#define PQCLEAN_SPHINCSSHAKE128FSIMPLE_AVX2_CRYPTO_SEEDBYTES 48 + +/* + * Returns the length of a secret key, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE128FSIMPLE_AVX2_crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE128FSIMPLE_AVX2_crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE128FSIMPLE_AVX2_crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE128FSIMPLE_AVX2_crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +int PQCLEAN_SPHINCSSHAKE128FSIMPLE_AVX2_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +int PQCLEAN_SPHINCSSHAKE128FSIMPLE_AVX2_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +int PQCLEAN_SPHINCSSHAKE128FSIMPLE_AVX2_crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +int PQCLEAN_SPHINCSSHAKE128FSIMPLE_AVX2_crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, + const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +int PQCLEAN_SPHINCSSHAKE128FSIMPLE_AVX2_crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +int PQCLEAN_SPHINCSSHAKE128FSIMPLE_AVX2_crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/context.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/context.h new file mode 100644 index 0000000000..6e0a33f3b7 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/context.h @@ -0,0 +1,19 @@ +#ifndef SPX_CONTEXT_H +#define SPX_CONTEXT_H + +#include + +#include "params.h" + +typedef struct { + uint8_t pub_seed[SPX_N]; + uint8_t sk_seed[SPX_N]; +} spx_ctx; + +#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) +void initialize_hash_function(spx_ctx *ctx); + +#define free_hash_function SPX_NAMESPACE(free_hash_function) +void free_hash_function(spx_ctx *ctx); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/context_shake.c b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/context_shake.c new file mode 100644 index 0000000000..9614a103d3 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/context_shake.c @@ -0,0 +1,12 @@ +#include "context.h" + +/* For SHAKE256, there is no immediate reason to initialize at the start, + so this function is an empty operation. */ +void initialize_hash_function(spx_ctx *ctx) { + (void)ctx; /* Suppress an 'unused parameter' warning. */ +} + +// in case the hash function api is heap-based. +void free_hash_function(spx_ctx *ctx) { + (void)ctx; +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/fips202x4.c b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/fips202x4.c new file mode 100644 index 0000000000..1e06fef186 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/fips202x4.c @@ -0,0 +1,210 @@ +#include +#include +#include + +#include "fips202.h" +#include "fips202x4.h" + +#define NROUNDS 24 +#define ROL(a, offset) (((a) << (offset)) ^ ((a) >> (64-(offset)))) + +static uint64_t load64(const unsigned char *x) { + unsigned long long r = 0, i; + + for (i = 0; i < 8; ++i) { + r |= (unsigned long long)x[i] << 8 * i; + } + return r; +} + +static void store64(uint8_t *x, uint64_t u) { + unsigned int i; + + for (i = 0; i < 8; ++i) { + x[i] = (uint8_t)u; + u >>= 8; + } +} + +/* Use implementation from the Keccak Code Package */ +extern void KeccakP1600times4_PermuteAll_24rounds(__m256i *s); +#define KeccakF1600_StatePermute4x KeccakP1600times4_PermuteAll_24rounds + +static void keccak_absorb4x(__m256i *s, + unsigned int r, + const unsigned char *m0, + const unsigned char *m1, + const unsigned char *m2, + const unsigned char *m3, + unsigned long long int mlen, + unsigned char p) { + unsigned long long i; + unsigned char t0[200]; + unsigned char t1[200]; + unsigned char t2[200]; + unsigned char t3[200]; + + unsigned long long *ss = (unsigned long long *)s; + + + while (mlen >= r) { + for (i = 0; i < r / 8; ++i) { + ss[4 * i + 0] ^= load64(m0 + 8 * i); + ss[4 * i + 1] ^= load64(m1 + 8 * i); + ss[4 * i + 2] ^= load64(m2 + 8 * i); + ss[4 * i + 3] ^= load64(m3 + 8 * i); + } + + KeccakF1600_StatePermute4x(s); + mlen -= r; + m0 += r; + m1 += r; + m2 += r; + m3 += r; + } + + for (i = 0; i < r; ++i) { + t0[i] = 0; + t1[i] = 0; + t2[i] = 0; + t3[i] = 0; + } + for (i = 0; i < mlen; ++i) { + t0[i] = m0[i]; + t1[i] = m1[i]; + t2[i] = m2[i]; + t3[i] = m3[i]; + } + + t0[i] = p; + t1[i] = p; + t2[i] = p; + t3[i] = p; + + t0[r - 1] |= 128; + t1[r - 1] |= 128; + t2[r - 1] |= 128; + t3[r - 1] |= 128; + + for (i = 0; i < r / 8; ++i) { + ss[4 * i + 0] ^= load64(t0 + 8 * i); + ss[4 * i + 1] ^= load64(t1 + 8 * i); + ss[4 * i + 2] ^= load64(t2 + 8 * i); + ss[4 * i + 3] ^= load64(t3 + 8 * i); + } +} + + +static void keccak_squeezeblocks4x(unsigned char *h0, + unsigned char *h1, + unsigned char *h2, + unsigned char *h3, + unsigned long long int nblocks, + __m256i *s, + unsigned int r) { + unsigned int i; + + unsigned long long *ss = (unsigned long long *)s; + + while (nblocks > 0) { + KeccakF1600_StatePermute4x(s); + for (i = 0; i < (r >> 3); i++) { + store64(h0 + 8 * i, ss[4 * i + 0]); + store64(h1 + 8 * i, ss[4 * i + 1]); + store64(h2 + 8 * i, ss[4 * i + 2]); + store64(h3 + 8 * i, ss[4 * i + 3]); + } + h0 += r; + h1 += r; + h2 += r; + h3 += r; + nblocks--; + } +} + + + +void shake128x4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, unsigned long long outlen, + unsigned char *in0, + unsigned char *in1, + unsigned char *in2, + unsigned char *in3, unsigned long long inlen) { + __m256i s[25]; + unsigned char t0[SHAKE128_RATE]; + unsigned char t1[SHAKE128_RATE]; + unsigned char t2[SHAKE128_RATE]; + unsigned char t3[SHAKE128_RATE]; + unsigned int i; + + /* zero state */ + for (i = 0; i < 25; i++) { + s[i] = _mm256_xor_si256(s[i], s[i]); + } + + /* absorb 4 message of identical length in parallel */ + keccak_absorb4x(s, SHAKE128_RATE, in0, in1, in2, in3, inlen, 0x1F); + + /* Squeeze output */ + keccak_squeezeblocks4x(out0, out1, out2, out3, outlen / SHAKE128_RATE, s, SHAKE128_RATE); + + out0 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; + out1 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; + out2 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; + out3 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; + + if (outlen % SHAKE128_RATE) { + keccak_squeezeblocks4x(t0, t1, t2, t3, 1, s, SHAKE128_RATE); + for (i = 0; i < outlen % SHAKE128_RATE; i++) { + out0[i] = t0[i]; + out1[i] = t1[i]; + out2[i] = t2[i]; + out3[i] = t3[i]; + } + } +} + + +void shake256x4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, unsigned long long outlen, + unsigned char *in0, + unsigned char *in1, + unsigned char *in2, + unsigned char *in3, unsigned long long inlen) { + __m256i s[25]; + unsigned char t0[SHAKE256_RATE]; + unsigned char t1[SHAKE256_RATE]; + unsigned char t2[SHAKE256_RATE]; + unsigned char t3[SHAKE256_RATE]; + unsigned int i; + + /* zero state */ + for (i = 0; i < 25; i++) { + s[i] = _mm256_xor_si256(s[i], s[i]); + } + + /* absorb 4 message of identical length in parallel */ + keccak_absorb4x(s, SHAKE256_RATE, in0, in1, in2, in3, inlen, 0x1F); + + /* Squeeze output */ + keccak_squeezeblocks4x(out0, out1, out2, out3, outlen / SHAKE256_RATE, s, SHAKE256_RATE); + + out0 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; + out1 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; + out2 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; + out3 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; + + if (outlen % SHAKE256_RATE) { + keccak_squeezeblocks4x(t0, t1, t2, t3, 1, s, SHAKE256_RATE); + for (i = 0; i < outlen % SHAKE256_RATE; i++) { + out0[i] = t0[i]; + out1[i] = t1[i]; + out2[i] = t2[i]; + out3[i] = t3[i]; + } + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/fips202x4.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/fips202x4.h new file mode 100644 index 0000000000..2b93c9cd0d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/fips202x4.h @@ -0,0 +1,28 @@ +#ifndef SPX_FIPS202X4_H +#define SPX_FIPS202X4_H + +#include + +#include "params.h" + +#define shake128x4 SPX_NAMESPACE(shake128x4) +void shake128x4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, unsigned long long outlen, + unsigned char *in0, + unsigned char *in1, + unsigned char *in2, + unsigned char *in3, unsigned long long inlen); + +#define shake256x4 SPX_NAMESPACE(shake256x4) +void shake256x4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, unsigned long long outlen, + unsigned char *in0, + unsigned char *in1, + unsigned char *in2, + unsigned char *in3, unsigned long long inlen); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/fors.c b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/fors.c new file mode 100644 index 0000000000..f1b0639cfc --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/fors.c @@ -0,0 +1,202 @@ +#include +#include +#include + +#include "fors.h" + +#include "address.h" +#include "hash.h" +#include "hashx4.h" +#include "thash.h" +#include "thashx4.h" +#include "utils.h" +#include "utilsx4.h" + +static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + prf_addr(sk, ctx, fors_leaf_addr); +} + +static void fors_gen_skx4(unsigned char *sk0, + unsigned char *sk1, + unsigned char *sk2, + unsigned char *sk3, const spx_ctx *ctx, + uint32_t fors_leaf_addrx4[4 * 8]) { + prf_addrx4(sk0, sk1, sk2, sk3, + ctx, fors_leaf_addrx4); +} + +static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, + const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + thash(leaf, sk, 1, ctx, fors_leaf_addr); +} + +static void fors_sk_to_leafx4(unsigned char *leaf0, + unsigned char *leaf1, + unsigned char *leaf2, + unsigned char *leaf3, + const unsigned char *sk0, + const unsigned char *sk1, + const unsigned char *sk2, + const unsigned char *sk3, + const spx_ctx *ctx, + uint32_t fors_leaf_addrx4[4 * 8]) { + thashx4(leaf0, leaf1, leaf2, leaf3, + sk0, sk1, sk2, sk3, + 1, ctx, fors_leaf_addrx4); +} + +struct fors_gen_leaf_info { + uint32_t leaf_addrx[4 * 8]; +}; + +static void fors_gen_leafx4(unsigned char *leaf, + const spx_ctx *ctx, + uint32_t addr_idx, void *info) { + struct fors_gen_leaf_info *fors_info = info; + uint32_t *fors_leaf_addrx4 = fors_info->leaf_addrx; + unsigned int j; + + /* Only set the parts that the caller doesn't set */ + for (j = 0; j < 4; j++) { + set_tree_index(fors_leaf_addrx4 + j * 8, addr_idx + j); + set_type(fors_leaf_addrx4 + j * 8, SPX_ADDR_TYPE_FORSPRF); + } + + fors_gen_skx4(leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + leaf + 2 * SPX_N, + leaf + 3 * SPX_N, + ctx, fors_leaf_addrx4); + + for (j = 0; j < 4; j++) { + set_type(fors_leaf_addrx4 + j * 8, SPX_ADDR_TYPE_FORSTREE); + } + + fors_sk_to_leafx4(leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + leaf + 2 * SPX_N, + leaf + 3 * SPX_N, + leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + leaf + 2 * SPX_N, + leaf + 3 * SPX_N, + ctx, fors_leaf_addrx4); +} + +/** + * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + * Assumes indices has space for SPX_FORS_TREES integers. + */ +static void message_to_indices(uint32_t *indices, const unsigned char *m) { + unsigned int i, j; + unsigned int offset = 0; + + for (i = 0; i < SPX_FORS_TREES; i++) { + indices[i] = 0; + for (j = 0; j < SPX_FORS_HEIGHT; j++) { + indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); + offset++; + } + } +} + +/** + * Signs a message m, deriving the secret key from sk_seed and the FTS address. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + uint32_t fors_tree_addr[4 * 8] = {0}; + struct fors_gen_leaf_info fors_info = {0}; + uint32_t *fors_leaf_addr = fors_info.leaf_addrx; + uint32_t fors_pk_addr[8] = {0}; + uint32_t idx_offset; + unsigned int i; + + for (i = 0; i < 4; i++) { + copy_keypair_addr(fors_tree_addr + 8 * i, fors_addr); + set_type(fors_tree_addr + 8 * i, SPX_ADDR_TYPE_FORSTREE); + copy_keypair_addr(fors_leaf_addr + 8 * i, fors_addr); + } + copy_keypair_addr(fors_pk_addr, fors_addr); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); + + message_to_indices(indices, m); + + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); + + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + + /* Include the secret key part that produces the selected leaf node. */ + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); + fors_gen_sk(sig, ctx, fors_tree_addr); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + sig += SPX_N; + + /* Compute the authentication path for this leaf node. */ + treehashx4(roots + i * SPX_N, sig, ctx, + indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx4, + fors_tree_addr, &fors_info); + + sig += SPX_N * SPX_FORS_HEIGHT; + } + + /* Hash horizontally across all tree roots to derive the public key. */ + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); +} + +/** + * Derives the FORS public key from a signature. + * This can be used for verification by comparing to a known public key, or to + * subsequently verify a signature on the derived public key. The latter is the + * typical use-case when used as an FTS below an OTS in a hypertree. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + unsigned char leaf[SPX_N]; + uint32_t fors_tree_addr[8] = {0}; + uint32_t fors_pk_addr[8] = {0}; + uint32_t idx_offset; + unsigned int i; + + copy_keypair_addr(fors_tree_addr, fors_addr); + copy_keypair_addr(fors_pk_addr, fors_addr); + + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); + + message_to_indices(indices, m); + + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); + + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + + /* Derive the leaf from the included secret key part. */ + fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); + sig += SPX_N; + + /* Derive the corresponding root node of this tree. */ + compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, + sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); + sig += SPX_N * SPX_FORS_HEIGHT; + } + + /* Hash horizontally across all tree roots to derive the public key. */ + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/fors.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/fors.h new file mode 100644 index 0000000000..509140a178 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/fors.h @@ -0,0 +1,32 @@ +#ifndef SPX_FORS_H +#define SPX_FORS_H + +#include + +#include "context.h" +#include "params.h" + +/** + * Signs a message m, deriving the secret key from sk_seed and the FTS address. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +#define fors_sign SPX_NAMESPACE(fors_sign) +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); + +/** + * Derives the FORS public key from a signature. + * This can be used for verification by comparing to a known public key, or to + * subsequently verify a signature on the derived public key. The latter is the + * typical use-case when used as an FTS below an OTS in a hypertree. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/hash.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/hash.h new file mode 100644 index 0000000000..f7c87d4c3c --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/hash.h @@ -0,0 +1,28 @@ +#ifndef SPX_HASH_H +#define SPX_HASH_H + +#include +#include + +#include "context.h" +#include "params.h" + +#define prf_addr SPX_NAMESPACE(prf_addr) +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]); + +#define gen_message_random SPX_NAMESPACE(gen_message_random) +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); + +#define hash_message SPX_NAMESPACE(hash_message) +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); + + + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/hash_shake.c b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/hash_shake.c new file mode 100644 index 0000000000..ff5e7ec918 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/hash_shake.c @@ -0,0 +1,83 @@ +#include +#include + +#include "hash.h" + +#include "address.h" +#include "fips202.h" +#include "params.h" +#include "utils.h" + +/* + * Computes PRF(pk_seed, sk_seed, addr) + */ +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]) { + unsigned char buf[2 * SPX_N + SPX_ADDR_BYTES]; + + memcpy(buf, ctx->pub_seed, SPX_N); + memcpy(buf + SPX_N, addr, SPX_ADDR_BYTES); + memcpy(buf + SPX_N + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); + + shake256(out, SPX_N, buf, 2 * SPX_N + SPX_ADDR_BYTES); +} + +/** + * Computes the message-dependent randomness R, using a secret seed and an + * optional randomization value as well as the message. + */ +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { + (void)ctx; + shake256incctx s_inc; + + shake256_inc_init(&s_inc); + shake256_inc_absorb(&s_inc, sk_prf, SPX_N); + shake256_inc_absorb(&s_inc, optrand, SPX_N); + shake256_inc_absorb(&s_inc, m, mlen); + shake256_inc_finalize(&s_inc); + shake256_inc_squeeze(R, SPX_N, &s_inc); + shake256_inc_ctx_release(&s_inc); +} + +/** + * Computes the message hash using R, the public key, and the message. + * Outputs the message digest and the index of the leaf. The index is split in + * the tree index and the leaf index, for convenient copying to an address. + */ +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { + (void)ctx; +#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) +#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) +#define SPX_LEAF_BITS SPX_TREE_HEIGHT +#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) +#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) + + unsigned char buf[SPX_DGST_BYTES]; + unsigned char *bufp = buf; + shake256incctx s_inc; + + shake256_inc_init(&s_inc); + shake256_inc_absorb(&s_inc, R, SPX_N); + shake256_inc_absorb(&s_inc, pk, SPX_PK_BYTES); + shake256_inc_absorb(&s_inc, m, mlen); + shake256_inc_finalize(&s_inc); + shake256_inc_squeeze(buf, SPX_DGST_BYTES, &s_inc); + shake256_inc_ctx_release(&s_inc); + + memcpy(digest, bufp, SPX_FORS_MSG_BYTES); + bufp += SPX_FORS_MSG_BYTES; + + + *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); + *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); + bufp += SPX_TREE_BYTES; + + *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); + *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/hash_shakex4.c b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/hash_shakex4.c new file mode 100644 index 0000000000..bbd22eb117 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/hash_shakex4.c @@ -0,0 +1,64 @@ +#include +#include + +#include "hashx4.h" + +#include "address.h" +#include "fips202x4.h" +#include "params.h" + +extern void KeccakP1600times4_PermuteAll_24rounds(__m256i *s); + +/* + * 4-way parallel version of prf_addr; takes 4x as much input and output + */ +void prf_addrx4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const spx_ctx *ctx, + const uint32_t addrx4[4 * 8]) { + /* As we write and read only a few quadwords, it is more efficient to + * build and extract from the fourway SHAKE256 state by hand. */ + __m256i state[25]; + + for (int i = 0; i < SPX_N / 8; i++) { + state[i] = _mm256_set1_epi64x(((int64_t *)ctx->pub_seed)[i]); + } + for (int i = 0; i < 4; i++) { + state[SPX_N / 8 + i] = _mm256_set_epi32( + (int)addrx4[3 * 8 + 1 + 2 * i], + (int)addrx4[3 * 8 + 2 * i], + (int)addrx4[2 * 8 + 1 + 2 * i], + (int)addrx4[2 * 8 + 2 * i], + (int)addrx4[8 + 1 + 2 * i], + (int)addrx4[8 + 2 * i], + (int)addrx4[1 + 2 * i], + (int)addrx4[2 * i] + ); + } + for (int i = 0; i < SPX_N / 8; i++) { + state[SPX_N / 8 + i + 4] = _mm256_set1_epi64x(((int64_t *)ctx->sk_seed)[i]); + } + + /* SHAKE domain separator and padding. */ + state[SPX_N / 4 + 4] = _mm256_set1_epi64x(0x1f); + for (int i = SPX_N / 4 + 5; i < 16; i++) { + state[i] = _mm256_set1_epi64x(0); + } + // shift unsigned and then cast to avoid UB + state[16] = _mm256_set1_epi64x((long long)(0x80ULL << 56)); + + for (int i = 17; i < 25; i++) { + state[i] = _mm256_set1_epi64x(0); + } + + KeccakP1600times4_PermuteAll_24rounds(&state[0]); + + for (int i = 0; i < SPX_N / 8; i++) { + ((int64_t *)out0)[i] = _mm256_extract_epi64(state[i], 0); + ((int64_t *)out1)[i] = _mm256_extract_epi64(state[i], 1); + ((int64_t *)out2)[i] = _mm256_extract_epi64(state[i], 2); + ((int64_t *)out3)[i] = _mm256_extract_epi64(state[i], 3); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/hashx4.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/hashx4.h new file mode 100644 index 0000000000..3751a0ebd0 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/hashx4.h @@ -0,0 +1,17 @@ +#ifndef SPX_HASHX4_H +#define SPX_HASHX4_H + +#include + +#include "context.h" +#include "params.h" + +#define prf_addrx4 SPX_NAMESPACE(prf_addrx4) +void prf_addrx4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const spx_ctx *ctx, + const uint32_t addrx4[4 * 8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/merkle.c b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/merkle.c new file mode 100644 index 0000000000..f57811c1ac --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/merkle.c @@ -0,0 +1,64 @@ +#include +#include + +#include "merkle.h" + +#include "address.h" +#include "params.h" +#include "utils.h" +#include "utilsx4.h" +#include "wots.h" +#include "wotsx4.h" + +/* + * This generates a Merkle signature (WOTS signature followed by the Merkle + * authentication path). + */ +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf) { + unsigned char *auth_path = sig + SPX_WOTS_BYTES; + uint32_t tree_addrx4[4 * 8] = { 0 }; + int j; + struct leaf_info_x4 info = { 0 }; + unsigned steps[ SPX_WOTS_LEN ]; + + info.wots_sig = sig; + chain_lengths(steps, root); + info.wots_steps = steps; + + for (j = 0; j < 4; j++) { + set_type(&tree_addrx4[8 * j], SPX_ADDR_TYPE_HASHTREE); + set_type(&info.leaf_addr[8 * j], SPX_ADDR_TYPE_WOTS); + set_type(&info.pk_addr[8 * j], SPX_ADDR_TYPE_WOTSPK); + copy_subtree_addr(&tree_addrx4[8 * j], tree_addr); + copy_subtree_addr(&info.leaf_addr[8 * j], wots_addr); + copy_subtree_addr(&info.pk_addr[8 * j], wots_addr); + } + + info.wots_sign_leaf = idx_leaf; + + treehashx4(root, auth_path, ctx, + idx_leaf, 0, + SPX_TREE_HEIGHT, + wots_gen_leafx4, + tree_addrx4, &info); +} + +/* Compute root node of the top-most subtree. */ +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { + /* We do not need the auth path in key generation, but it simplifies the + code to have just one treehash routine that computes both root and path + in one function. */ + unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; + uint32_t top_tree_addr[8] = {0}; + uint32_t wots_addr[8] = {0}; + + set_layer_addr(top_tree_addr, SPX_D - 1); + set_layer_addr(wots_addr, SPX_D - 1); + + merkle_sign(auth_path, root, ctx, + wots_addr, top_tree_addr, + ~0U /* ~0 means "don't bother generating an auth path */ ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/merkle.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/merkle.h new file mode 100644 index 0000000000..769cf2e970 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/merkle.h @@ -0,0 +1,21 @@ +#ifndef MERKLE_H_ +#define MERKLE_H_ + +#include + +#include "context.h" +#include "params.h" + +/* Generate a Merkle signature (WOTS signature followed by the Merkle */ +/* authentication path) */ +#define merkle_sign SPX_NAMESPACE(merkle_sign) +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf); + +/* Compute the root node of the top-most subtree. */ +#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); + +#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/nistapi.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/nistapi.h new file mode 100644 index 0000000000..3cb71afad4 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/nistapi.h @@ -0,0 +1,87 @@ +#ifndef SPX_API_H +#define SPX_API_H + +#include +#include + +#include "params.h" + +#define CRYPTO_ALGNAME "SPHINCS+" + +#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES +#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES +#define CRYPTO_BYTES SPX_BYTES +#define CRYPTO_SEEDBYTES (3*SPX_N) + +/* + * Returns the length of a secret key, in bytes + */ +#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) +size_t crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) +size_t crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) +size_t crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) +size_t crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +#define crypto_sign SPX_NAMESPACE(crypto_sign) +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/params.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/params.h new file mode 100644 index 0000000000..93508c9430 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/params.h @@ -0,0 +1,56 @@ +#ifndef SPX_PARAMS_H +#define SPX_PARAMS_H + +#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSSHAKE128FSIMPLE_AVX2_##s + +/* Hash output length in bytes. */ +#define SPX_N 16 +/* Height of the hypertree. */ +#define SPX_FULL_HEIGHT 66 +/* Number of subtree layer. */ +#define SPX_D 22 +/* FORS tree dimensions. */ +#define SPX_FORS_HEIGHT 6 +#define SPX_FORS_TREES 33 +/* Winternitz parameter, */ +#define SPX_WOTS_W 16 + +/* The hash function is defined by linking a different hash.c file, as opposed + to setting a #define constant. */ + +/* For clarity */ +#define SPX_ADDR_BYTES 32 + +/* WOTS parameters. */ +#define SPX_WOTS_LOGW 4 + +#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) + +/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ +#define SPX_WOTS_LEN2 3 + +#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) +#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) +#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES + +/* Subtree size. */ +#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) + +//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT +// #error SPX_D should always divide SPX_FULL_HEIGHT +//#endif + +/* FORS parameters. */ +#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) +#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) +#define SPX_FORS_PK_BYTES SPX_N + +/* Resulting SPX sizes. */ +#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ + SPX_FULL_HEIGHT * SPX_N) +#define SPX_PK_BYTES (2 * SPX_N) +#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) + +#include "shake_offsets.h" + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/shake_offsets.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/shake_offsets.h new file mode 100644 index 0000000000..6b28d95d91 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/shake_offsets.h @@ -0,0 +1,21 @@ +#ifndef SHAKE_OFFSETS_H_ +#define SHAKE_OFFSETS_H_ + +/* + * Offsets of various fields in the address structure when we use SHAKE as + * the Sphincs+ hash function + */ + +#define SPX_OFFSET_LAYER 3 /* The byte used to specify the Merkle tree layer */ +#define SPX_OFFSET_TREE 8 /* The start of the 8 byte field used to specify the tree */ +#define SPX_OFFSET_TYPE 19 /* The byte used to specify the hash type (reason) */ +#define SPX_OFFSET_KP_ADDR2 22 /* The high byte used to specify the key pair (which one-time signature) */ +#define SPX_OFFSET_KP_ADDR1 23 /* The low byte used to specify the key pair */ +#define SPX_OFFSET_CHAIN_ADDR 27 /* The byte used to specify the chain address (which Winternitz chain) */ +#define SPX_OFFSET_HASH_ADDR 31 /* The byte used to specify the hash address (where in the Winternitz chain) */ +#define SPX_OFFSET_TREE_HGT 27 /* The byte used to specify the height of this node in the FORS or Merkle tree */ +#define SPX_OFFSET_TREE_INDEX 28 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ + +#define SPX_SHAKE 1 + +#endif /* SHAKE_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/sign.c b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/sign.c new file mode 100644 index 0000000000..9d0c7d1b22 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/sign.c @@ -0,0 +1,286 @@ +#include +#include +#include + +#include "address.h" +#include "context.h" +#include "fors.h" +#include "hash.h" +#include "merkle.h" +#include "nistapi.h" +#include "params.h" +#include "randombytes.h" +#include "thash.h" +#include "utils.h" +#include "wots.h" + +/* + * Returns the length of a secret key, in bytes + */ +size_t crypto_sign_secretkeybytes(void) { + return CRYPTO_SECRETKEYBYTES; +} + +/* + * Returns the length of a public key, in bytes + */ +size_t crypto_sign_publickeybytes(void) { + return CRYPTO_PUBLICKEYBYTES; +} + +/* + * Returns the length of a signature, in bytes + */ +size_t crypto_sign_bytes(void) { + return CRYPTO_BYTES; +} + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +size_t crypto_sign_seedbytes(void) { + return CRYPTO_SEEDBYTES; +} + +/* + * Generates an SPX key pair given a seed of length + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [PUB_SEED || root] + */ +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed) { + spx_ctx ctx; + + /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ + memcpy(sk, seed, CRYPTO_SEEDBYTES); + + memcpy(pk, sk + 2 * SPX_N, SPX_N); + + memcpy(ctx.pub_seed, pk, SPX_N); + memcpy(ctx.sk_seed, sk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + /* Compute root node of the top-most subtree. */ + merkle_gen_root(sk + 3 * SPX_N, &ctx); + + // cleanup + free_hash_function(&ctx); + + memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); + + return 0; +} + +/* + * Generates an SPX key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [PUB_SEED || root] + */ +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { + uint8_t seed[CRYPTO_SEEDBYTES]; + randombytes(seed, CRYPTO_SEEDBYTES); + crypto_sign_seed_keypair(pk, sk, seed); + + return 0; +} + +/** + * Returns an array containing a detached signature. + */ +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk) { + spx_ctx ctx; + + const uint8_t *sk_prf = sk + SPX_N; + const uint8_t *pk = sk + 2 * SPX_N; + + uint8_t optrand[SPX_N]; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t root[SPX_N]; + uint32_t i; + uint64_t tree; + uint32_t idx_leaf; + uint32_t wots_addr[8] = {0}; + uint32_t tree_addr[8] = {0}; + + memcpy(ctx.sk_seed, sk, SPX_N); + memcpy(ctx.pub_seed, pk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + + /* Optionally, signing can be made non-deterministic using optrand. + This can help counter side-channel attacks that would benefit from + getting a large number of traces when the signer uses the same nodes. */ + randombytes(optrand, SPX_N); + /* Compute the digest randomization value. */ + gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); + + /* Derive the message digest and leaf index from R, PK and M. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; + + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); + + /* Sign the message hash using FORS. */ + fors_sign(sig, root, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); + sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; + + /* Update the indices for the next layer. */ + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; + } + + free_hash_function(&ctx); + + *siglen = SPX_BYTES; + + return 0; +} + +/** + * Verifies a detached signature and message under a given public key. + */ +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk) { + spx_ctx ctx; + const uint8_t *pub_root = pk + SPX_N; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t wots_pk[SPX_WOTS_BYTES]; + uint8_t root[SPX_N]; + uint8_t leaf[SPX_N]; + unsigned int i; + uint64_t tree; + uint32_t idx_leaf; + uint32_t wots_addr[8] = {0}; + uint32_t tree_addr[8] = {0}; + uint32_t wots_pk_addr[8] = {0}; + + if (siglen != SPX_BYTES) { + return -1; + } + + memcpy(ctx.pub_seed, pk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); + + /* Derive the message digest and leaf index from R || PK || M. */ + /* The additional SPX_N is a result of the hash domain separator. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; + + /* Layer correctly defaults to 0, so no need to set_layer_addr */ + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); + + fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + /* For each subtree.. */ + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + copy_keypair_addr(wots_pk_addr, wots_addr); + + /* The WOTS public key is only correct if the signature was correct. */ + /* Initially, root is the FORS pk, but on subsequent iterations it is + the root of the subtree below the currently processed subtree. */ + wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); + sig += SPX_WOTS_BYTES; + + /* Compute the leaf node using the WOTS public key. */ + thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); + + /* Compute the root node of this subtree. */ + compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, + &ctx, tree_addr); + sig += SPX_TREE_HEIGHT * SPX_N; + + /* Update the indices for the next layer. */ + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; + } + + // cleanup + free_hash_function(&ctx); + + /* Check if the root node equals the root node in the public key. */ + if (memcmp(root, pub_root, SPX_N) != 0) { + return -1; + } + + return 0; +} + + +/** + * Returns an array containing the signature followed by the message. + */ +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk) { + size_t siglen; + + crypto_sign_signature(sm, &siglen, m, mlen, sk); + + memmove(sm + SPX_BYTES, m, mlen); + *smlen = siglen + mlen; + + return 0; +} + +/** + * Verifies a given signature-message pair under a given public key. + */ +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk) { + /* The API caller does not necessarily know what size a signature should be + but SPHINCS+ signatures are always exactly SPX_BYTES. */ + if (smlen < SPX_BYTES) { + memset(m, 0, smlen); + *mlen = 0; + return -1; + } + + *mlen = smlen - SPX_BYTES; + + if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { + memset(m, 0, smlen); + *mlen = 0; + return -1; + } + + /* If verification was successful, move the message to the right place. */ + memmove(m, sm + SPX_BYTES, *mlen); + + return 0; +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/thash.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/thash.h new file mode 100644 index 0000000000..8687ccfb4d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/thash.h @@ -0,0 +1,13 @@ +#ifndef SPX_THASH_H +#define SPX_THASH_H + +#include "context.h" +#include "params.h" + +#include + +#define thash SPX_NAMESPACE(thash) +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/thash_shake_simple.c b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/thash_shake_simple.c new file mode 100644 index 0000000000..98470395e9 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/thash_shake_simple.c @@ -0,0 +1,24 @@ +#include +#include + +#include "thash.h" + +#include "address.h" +#include "params.h" +#include "utils.h" + +#include "fips202.h" + +/** + * Takes an array of inblocks concatenated arrays of SPX_N bytes. + */ +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]) { + PQCLEAN_VLA(uint8_t, buf, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); + + memcpy(buf, ctx->pub_seed, SPX_N); + memcpy(buf + SPX_N, addr, SPX_ADDR_BYTES); + memcpy(buf + SPX_N + SPX_ADDR_BYTES, in, inblocks * SPX_N); + + shake256(out, SPX_N, buf, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/thash_shake_simplex4.c b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/thash_shake_simplex4.c new file mode 100644 index 0000000000..89dc9a4224 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/thash_shake_simplex4.c @@ -0,0 +1,98 @@ +#include +#include + +#include "thashx4.h" + +#include "address.h" +#include "params.h" +#include "utils.h" + +#include "fips202x4.h" + +extern void KeccakP1600times4_PermuteAll_24rounds(__m256i *s); + +/** + * 4-way parallel version of thash; takes 4x as much input and output + */ +void thashx4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addrx4[4 * 8]) { + if (inblocks == 1 || inblocks == 2) { + /* As we write and read only a few quadwords, it is more efficient to + * build and extract from the fourway SHAKE256 state by hand. */ + __m256i state[25]; + for (int i = 0; i < SPX_N / 8; i++) { + state[i] = _mm256_set1_epi64x(((int64_t *)ctx->pub_seed)[i]); + } + for (int i = 0; i < 4; i++) { + state[SPX_N / 8 + i] = _mm256_set_epi32( + (int)addrx4[3 * 8 + 1 + 2 * i], + (int)addrx4[3 * 8 + 2 * i], + (int)addrx4[2 * 8 + 1 + 2 * i], + (int)addrx4[2 * 8 + 2 * i], + (int)addrx4[8 + 1 + 2 * i], + (int)addrx4[8 + 2 * i], + (int)addrx4[1 + 2 * i], + (int)addrx4[2 * i] + ); + } + + for (unsigned int i = 0; i < (SPX_N / 8) * inblocks; i++) { + state[SPX_N / 8 + 4 + i] = _mm256_set_epi64x( + ((int64_t *)in3)[i], + ((int64_t *)in2)[i], + ((int64_t *)in1)[i], + ((int64_t *)in0)[i] + ); + } + + /* Domain separator and padding. */ + for (size_t i = (SPX_N / 8) * (1 + inblocks) + 4; i < 16; i++) { + state[i] = _mm256_set1_epi64x(0); + } + state[16] = _mm256_set1_epi64x((long long)(0x80ULL << 56)); + state[(SPX_N / 8) * (1 + inblocks) + 4] = _mm256_xor_si256( + state[(SPX_N / 8) * (1 + inblocks) + 4], + _mm256_set1_epi64x(0x1f) + ); + for (int i = 17; i < 25; i++) { + state[i] = _mm256_set1_epi64x(0); + } + + KeccakP1600times4_PermuteAll_24rounds(&state[0]); + + for (int i = 0; i < SPX_N / 8; i++) { + ((int64_t *)out0)[i] = _mm256_extract_epi64(state[i], 0); + ((int64_t *)out1)[i] = _mm256_extract_epi64(state[i], 1); + ((int64_t *)out2)[i] = _mm256_extract_epi64(state[i], 2); + ((int64_t *)out3)[i] = _mm256_extract_epi64(state[i], 3); + } + } else { + PQCLEAN_VLA(unsigned char, buf0, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, buf1, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, buf2, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, buf3, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); + + memcpy(buf0, ctx->pub_seed, SPX_N); + memcpy(buf1, ctx->pub_seed, SPX_N); + memcpy(buf2, ctx->pub_seed, SPX_N); + memcpy(buf3, ctx->pub_seed, SPX_N); + memcpy(buf0 + SPX_N, addrx4 + 0 * 8, SPX_ADDR_BYTES); + memcpy(buf1 + SPX_N, addrx4 + 1 * 8, SPX_ADDR_BYTES); + memcpy(buf2 + SPX_N, addrx4 + 2 * 8, SPX_ADDR_BYTES); + memcpy(buf3 + SPX_N, addrx4 + 3 * 8, SPX_ADDR_BYTES); + memcpy(buf0 + SPX_N + SPX_ADDR_BYTES, in0, inblocks * SPX_N); + memcpy(buf1 + SPX_N + SPX_ADDR_BYTES, in1, inblocks * SPX_N); + memcpy(buf2 + SPX_N + SPX_ADDR_BYTES, in2, inblocks * SPX_N); + memcpy(buf3 + SPX_N + SPX_ADDR_BYTES, in3, inblocks * SPX_N); + + shake256x4(out0, out1, out2, out3, SPX_N, + buf0, buf1, buf2, buf3, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/thashx4.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/thashx4.h new file mode 100644 index 0000000000..64798a3727 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/thashx4.h @@ -0,0 +1,20 @@ +#ifndef SPX_THASHX4_H +#define SPX_THASHX4_H + +#include + +#include "context.h" +#include "params.h" + +#define thashx4 SPX_NAMESPACE(thashx4) +void thashx4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addrx4[4 * 8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/utils.c b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/utils.c new file mode 100644 index 0000000000..177b541fb9 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/utils.c @@ -0,0 +1,148 @@ +#include + +#include "utils.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "thash.h" + +/** + * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. + */ +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in) { + int i; + + /* Iterate over out in decreasing order, for big-endianness. */ + for (i = (signed int)outlen - 1; i >= 0; i--) { + out[i] = in & 0xff; + in = in >> 8; + } +} + +void u32_to_bytes(unsigned char *out, uint32_t in) { + out[0] = (unsigned char)(in >> 24); + out[1] = (unsigned char)(in >> 16); + out[2] = (unsigned char)(in >> 8); + out[3] = (unsigned char)in; +} + +/** + * Converts the inlen bytes in 'in' from big-endian byte order to an integer. + */ +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { + unsigned long long retval = 0; + unsigned int i; + + for (i = 0; i < inlen; i++) { + retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); + } + return retval; +} + +/** + * Computes a root node given a leaf and an auth path. + * Expects address to be complete other than the tree_height and tree_index. + */ +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]) { + uint32_t i; + unsigned char buffer[2 * SPX_N]; + + /* If leaf_idx is odd (last bit = 1), current path element is a right child + and auth_path has to go left. Otherwise it is the other way around. */ + if (leaf_idx & 1) { + memcpy(buffer + SPX_N, leaf, SPX_N); + memcpy(buffer, auth_path, SPX_N); + } else { + memcpy(buffer, leaf, SPX_N); + memcpy(buffer + SPX_N, auth_path, SPX_N); + } + auth_path += SPX_N; + + for (i = 0; i < tree_height - 1; i++) { + leaf_idx >>= 1; + idx_offset >>= 1; + /* Set the address of the node we're creating. */ + set_tree_height(addr, i + 1); + set_tree_index(addr, leaf_idx + idx_offset); + + /* Pick the right or left neighbor, depending on parity of the node. */ + if (leaf_idx & 1) { + thash(buffer + SPX_N, buffer, 2, ctx, addr); + memcpy(buffer, auth_path, SPX_N); + } else { + thash(buffer, buffer, 2, ctx, addr); + memcpy(buffer + SPX_N, auth_path, SPX_N); + } + auth_path += SPX_N; + } + + /* The last iteration is exceptional; we do not copy an auth_path node. */ + leaf_idx >>= 1; + idx_offset >>= 1; + set_tree_height(addr, tree_height); + set_tree_index(addr, leaf_idx + idx_offset); + thash(root, buffer, 2, ctx, addr); +} + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx * /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]) { + PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); + PQCLEAN_VLA(unsigned int, heights, tree_height + 1); + unsigned int offset = 0; + uint32_t idx; + uint32_t tree_idx; + + for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { + /* Add the next leaf node to the stack. */ + gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); + offset++; + heights[offset - 1] = 0; + + /* If this is a node we need for the auth path.. */ + if ((leaf_idx ^ 0x1) == idx) { + memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); + } + + /* While the top-most nodes are of equal height.. */ + while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { + /* Compute index of the new node, in the next layer. */ + tree_idx = (idx >> (heights[offset - 1] + 1)); + + /* Set the address of the node we're creating. */ + set_tree_height(tree_addr, heights[offset - 1] + 1); + set_tree_index(tree_addr, + tree_idx + (idx_offset >> (heights[offset - 1] + 1))); + /* Hash the top-most nodes from the stack together. */ + thash(stack + (offset - 2)*SPX_N, + stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); + offset--; + /* Note that the top-most node is now one layer higher. */ + heights[offset - 1]++; + + /* If this is a node we need for the auth path.. */ + if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { + memcpy(auth_path + heights[offset - 1]*SPX_N, + stack + (offset - 1)*SPX_N, SPX_N); + } + } + } + memcpy(root, stack, SPX_N); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/utils.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/utils.h new file mode 100644 index 0000000000..64f5d5a53a --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/utils.h @@ -0,0 +1,58 @@ +#ifndef SPX_UTILS_H +#define SPX_UTILS_H + +#include + +#include "compat.h" +#include "context.h" +#include "params.h" + + +/* To support MSVC use alloca() instead of VLAs. See #20. */ + + +/** + * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. + */ +#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in); +#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) +void u32_to_bytes(unsigned char *out, uint32_t in); + +/** + * Converts the inlen bytes in 'in' from big-endian byte order to an integer. + */ +#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); + +/** + * Computes a root node given a leaf and an auth path. + * Expects address to be complete other than the tree_height and tree_index. + */ +#define compute_root SPX_NAMESPACE(compute_root) +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]); + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +#define treehash SPX_NAMESPACE(treehash) +void treehash(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx *ctx /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]); + + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/utilsx4.c b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/utilsx4.c new file mode 100644 index 0000000000..1638677194 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/utilsx4.c @@ -0,0 +1,138 @@ +#include + +#include "utilsx4.h" + +#include "address.h" +#include "params.h" +#include "thashx4.h" +#include "utils.h" + +/* + * Generate the entire Merkle tree, computing the authentication path for leaf_idx, + * and the resulting root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) + * + * This expects tree_addrx4 to be initialized to 4 parallel addr structures for + * the Merkle tree nodes + * + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + * + * This works by using the standard Merkle tree building algorithm, except + * that each 'node' tracked is actually 4 consecutive nodes in the real tree. + * When we combine two logical nodes ABCD and WXYZ, we perform the H + * operation on adjacent real nodes, forming the parent logical node + * (AB)(CD)(WX)(YZ) + * + * When we get to the top two levels of the real tree (where there is only + * one logical node), we continue this operation two more times; the right + * most real node will by the actual root (and the other 3 nodes will be + * garbage). We follow the same thashx4 logic so that the 'extract + * authentication path components' part of the loop is still executed (and + * to simplify the code somewhat) + * + * This currently assumes tree_height >= 2; I suspect that doing an adjusting + * idx, addr_idx on the gen_leafx4 call if tree_height < 2 would fix it; since + * we don't actually use such short trees, I haven't bothered + */ +void treehashx4(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, + uint32_t tree_height, + void (*gen_leafx4)( + unsigned char * /* Where to write the leaves */, + const spx_ctx *, + uint32_t idx, void *info), + uint32_t tree_addrx4[4 * 8], + void *info) { + /* This is where we keep the intermediate nodes */ + PQCLEAN_VLA(unsigned char, stackx4, tree_height * 4 * SPX_N); + uint32_t left_adj = 0, prev_left_adj = 0; /* When we're doing the top 3 */ + /* levels, the left-most part of the tree isn't at the beginning */ + /* of current[]. These give the offset of the actual start */ + + uint32_t idx; + uint32_t max_idx = (1U << (tree_height - 2)) - 1; + for (idx = 0;; idx++) { + unsigned char current[4 * SPX_N]; /* Current logical node */ + gen_leafx4( current, ctx, 4 * idx + idx_offset, + info ); + + /* Now combine the freshly generated right node with previously */ + /* generated left ones */ + uint32_t internal_idx_offset = idx_offset; + uint32_t internal_idx = idx; + uint32_t internal_leaf = leaf_idx; + uint32_t h; /* The height we are in the Merkle tree */ + for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { + + /* Special processing if we're at the top of the tree */ + if (h >= tree_height - 2) { + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[3 * SPX_N], SPX_N ); + return; + } + /* The tree indexing logic is a bit off in this case */ + /* Adjust it so that the left-most node of the part of */ + /* the tree that we're processing has index 0 */ + prev_left_adj = left_adj; + left_adj = 4U - (1 << (tree_height - h - 1)); + } + + /* Check if we hit the top of the tree */ + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[3 * SPX_N], SPX_N ); + return; + } + + /* + * Check if one of the nodes we have is a part of the + * authentication path; if it is, write it out + */ + if ((((internal_idx << 2) ^ internal_leaf) & ~0x3U) == 0) { + memcpy( &auth_path[ h * SPX_N ], + ¤t[(((internal_leaf & 3) ^ 1) + prev_left_adj) * SPX_N], + SPX_N ); + } + + /* + * Check if we're at a left child; if so, stop going up the stack + * Exception: if we've reached the end of the tree, keep on going + * (so we combine the last 4 nodes into the one root node in two + * more iterations) + */ + if ((internal_idx & 1) == 0 && idx < max_idx) { + break; + } + + /* Ok, we're at a right node (or doing the top 3 levels) */ + /* Now combine the left and right logical nodes together */ + + /* Set the address of the node we're creating. */ + unsigned int j; + internal_idx_offset >>= 1; + for (j = 0; j < 4; j++) { + set_tree_height(tree_addrx4 + j * 8, h + 1); + set_tree_index(tree_addrx4 + j * 8, + (4 / 2) * (internal_idx & ~1U) + j - left_adj + internal_idx_offset ); + } + unsigned char *left = &stackx4[h * 4 * SPX_N]; + thashx4( ¤t[0 * SPX_N], + ¤t[1 * SPX_N], + ¤t[2 * SPX_N], + ¤t[3 * SPX_N], + &left [0 * SPX_N], + &left [2 * SPX_N], + ¤t[0 * SPX_N], + ¤t[2 * SPX_N], + 2, ctx, tree_addrx4); + } + + /* We've hit a left child; save the current for when we get the */ + /* corresponding right right */ + memcpy( &stackx4[h * 4 * SPX_N], current, 4 * SPX_N); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/utilsx4.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/utilsx4.h new file mode 100644 index 0000000000..facb874b18 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/utilsx4.h @@ -0,0 +1,30 @@ +#ifndef SPX_UTILSX4_H +#define SPX_UTILSX4_H + +#include + +#include "context.h" +#include "params.h" + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + * + * This implementation uses AVX to compute internal nodes 4 at a time (in + * parallel) + */ +#define treehashx4 SPX_NAMESPACE(treehashx4) +void treehashx4(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leafx4)( + unsigned char * /* Where to write the leaves */, + const spx_ctx * /* ctx */, + uint32_t addr_idx, void *info), + uint32_t tree_addrx4[4 * 8], void *info); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/wots.c b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/wots.c new file mode 100644 index 0000000000..4d5041ce05 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/wots.c @@ -0,0 +1,269 @@ +#include +#include + +#include "wots.h" + +#include "address.h" +#include "hash.h" +#include "hashx4.h" +#include "params.h" +#include "thash.h" +#include "thashx4.h" +#include "utils.h" +#include "utilsx4.h" +#include "wotsx4.h" + +// TODO clarify address expectations, and make them more uniform. +// TODO i.e. do we expect types to be set already? +// TODO and do we expect modifications or copies? + +/** + * Computes up the chains + */ +static void gen_chains( + unsigned char *out, + const unsigned char *in, + unsigned int start[SPX_WOTS_LEN], + const unsigned int steps[SPX_WOTS_LEN], + const spx_ctx *ctx, + uint32_t addr[8]) { + uint32_t i, j, k, idx, watching; + int done; + unsigned char empty[SPX_N]; + unsigned char *bufs[4]; + uint32_t addrs[8 * 4]; + + int l; + uint16_t counts[SPX_WOTS_W] = { 0 }; + uint16_t idxs[SPX_WOTS_LEN]; + uint16_t total, newTotal; + + /* set addrs = {addr, addr, addr, addr} */ + for (j = 0; j < 4; j++) { + memcpy(addrs + j * 8, addr, sizeof(uint32_t) * 8); + } + + /* Initialize out with the value at position 'start'. */ + memcpy(out, in, SPX_WOTS_LEN * SPX_N); + + /* Sort the chains in reverse order by steps using counting sort. */ + for (i = 0; i < SPX_WOTS_LEN; i++) { + counts[steps[i]]++; + } + total = 0; + for (l = SPX_WOTS_W - 1; l >= 0; l--) { + newTotal = counts[l] + total; + counts[l] = total; + total = newTotal; + } + for (i = 0; i < SPX_WOTS_LEN; i++) { + idxs[counts[steps[i]]] = (uint16_t)i; + counts[steps[i]]++; + } + + /* We got our work cut out for us: do it! */ + for (i = 0; i < SPX_WOTS_LEN; i += 4) { + for (j = 0; j < 4 && i + j < SPX_WOTS_LEN; j++) { + idx = idxs[i + j]; + set_chain_addr(addrs + j * 8, idx); + bufs[j] = out + SPX_N * idx; + } + + /* As the chains are sorted in reverse order, we know that the first + * chain is the longest and the last one is the shortest. We keep + * an eye on whether the last chain is done and then on the one before, + * et cetera. */ + watching = 3; + done = 0; + while (i + watching >= SPX_WOTS_LEN) { + bufs[watching] = &empty[0]; + watching--; + } + + for (k = 0;; k++) { + while (k == steps[idxs[i + watching]]) { + bufs[watching] = &empty[0]; + if (watching == 0) { + done = 1; + break; + } + watching--; + } + if (done) { + break; + } + for (j = 0; j < watching + 1; j++) { + set_hash_addr(addrs + j * 8, k + start[idxs[i + j]]); + } + + thashx4(bufs[0], bufs[1], bufs[2], bufs[3], + bufs[0], bufs[1], bufs[2], bufs[3], 1, ctx, addrs); + } + } +} + +/** + * base_w algorithm as described in draft. + * Interprets an array of bytes as integers in base w. + * This only works when log_w is a divisor of 8. + */ +static void base_w(unsigned int *output, const int out_len, + const unsigned char *input) { + int in = 0; + int out = 0; + unsigned char total = 0; + int bits = 0; + int consumed; + + for (consumed = 0; consumed < out_len; consumed++) { + if (bits == 0) { + total = input[in]; + in++; + bits += 8; + } + bits -= SPX_WOTS_LOGW; + output[out] = (total >> bits) & (SPX_WOTS_W - 1); + out++; + } +} + +/* Computes the WOTS+ checksum over a message (in base_w). */ +static void wots_checksum(unsigned int *csum_base_w, + const unsigned int *msg_base_w) { + unsigned int csum = 0; + unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; + unsigned int i; + + /* Compute checksum. */ + for (i = 0; i < SPX_WOTS_LEN1; i++) { + csum += SPX_WOTS_W - 1 - msg_base_w[i]; + } + + /* Convert checksum to base_w. */ + /* Make sure expected empty zero bits are the least significant bits. */ + csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); + ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); + base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); +} + +/* Takes a message and derives the matching chain lengths. */ +void chain_lengths(unsigned int *lengths, const unsigned char *msg) { + base_w(lengths, SPX_WOTS_LEN1, msg); + wots_checksum(lengths + SPX_WOTS_LEN1, lengths); +} + +/** + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. + * + * Writes the computed public key to 'pk'. + */ +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]) { + unsigned int steps[SPX_WOTS_LEN]; + unsigned int start[SPX_WOTS_LEN]; + uint32_t i; + + chain_lengths(start, msg); + + for (i = 0; i < SPX_WOTS_LEN; i++) { + steps[i] = SPX_WOTS_W - 1 - start[i]; + } + + gen_chains(pk, sig, start, steps, ctx, addr); +} + +/* + * This generates 4 sequential WOTS public keys + * It also generates the WOTS signature if leaf_info indicates + * that we're signing with one of these WOTS keys + */ +void wots_gen_leafx4(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info) { + struct leaf_info_x4 *info = v_info; + uint32_t *leaf_addr = info->leaf_addr; + uint32_t *pk_addr = info->pk_addr; + unsigned int i, j, k; + unsigned char pk_buffer[ 4 * SPX_WOTS_BYTES ]; + unsigned wots_offset = SPX_WOTS_BYTES; + unsigned char *buffer; + uint32_t wots_k_mask; + unsigned wots_sign_index; + + if (((leaf_idx ^ info->wots_sign_leaf) & ~3U) == 0) { + /* We're traversing the leaf that's signing; generate the WOTS */ + /* signature */ + wots_k_mask = 0; + wots_sign_index = info->wots_sign_leaf & 3; /* Which of of the 4 */ + /* 4 slots do the signatures come from */ + } else { + /* Nope, we're just generating pk's; turn off the signature logic */ + wots_k_mask = (uint32_t)~0; + wots_sign_index = 0; + } + + for (j = 0; j < 4; j++) { + set_keypair_addr( leaf_addr + j * 8, leaf_idx + j ); + set_keypair_addr( pk_addr + j * 8, leaf_idx + j ); + } + + for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { + uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k to */ + /* the step if we're generating a signature, ~0 if we're not */ + + /* Start with the secret seed */ + for (j = 0; j < 4; j++) { + set_chain_addr(leaf_addr + j * 8, i); + set_hash_addr(leaf_addr + j * 8, 0); + set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTSPRF); + } + prf_addrx4(buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + buffer + 2 * wots_offset, + buffer + 3 * wots_offset, + ctx, leaf_addr); + + for (j = 0; j < 4; j++) { + set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTS); + } + + /* Iterate down the WOTS chain */ + for (k = 0;; k++) { + /* Check if one of the values we have needs to be saved as a */ + /* part of the WOTS signature */ + if (k == wots_k) { + memcpy( info->wots_sig + i * SPX_N, + buffer + wots_sign_index * wots_offset, SPX_N ); + } + + /* Check if we hit the top of the chain */ + if (k == SPX_WOTS_W - 1) { + break; + } + + /* Iterate one step on all 4 chains */ + for (j = 0; j < 4; j++) { + set_hash_addr(leaf_addr + j * 8, k); + } + thashx4(buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + buffer + 2 * wots_offset, + buffer + 3 * wots_offset, + buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + buffer + 2 * wots_offset, + buffer + 3 * wots_offset, 1, ctx, leaf_addr); + } + } + + /* Do the final thash to generate the public keys */ + thashx4(dest + 0 * SPX_N, + dest + 1 * SPX_N, + dest + 2 * SPX_N, + dest + 3 * SPX_N, + pk_buffer + 0 * wots_offset, + pk_buffer + 1 * wots_offset, + pk_buffer + 2 * wots_offset, + pk_buffer + 3 * wots_offset, SPX_WOTS_LEN, ctx, pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/wots.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/wots.h new file mode 100644 index 0000000000..4e7692eeef --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/wots.h @@ -0,0 +1,25 @@ +#ifndef SPX_WOTS_H +#define SPX_WOTS_H + +#include + +#include "context.h" +#include "params.h" + +/** + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. + * + * Writes the computed public key to 'pk'. + */ +#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]); + +/* + * Compute the chain lengths needed for a given message hash + */ +#define chain_lengths SPX_NAMESPACE(chain_lengths) +void chain_lengths(unsigned int *lengths, const unsigned char *msg); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/wotsx4.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/wotsx4.h new file mode 100644 index 0000000000..cd634f1743 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/wotsx4.h @@ -0,0 +1,41 @@ +#ifndef WOTSX4_H_ +#define WOTSX4_H_ + +#include + +#include "params.h" + +/* + * This is here to provide an interface to the internal wots_gen_leafx4 + * routine. While this routine is not referenced in the package outside of + * wots.c, it is called from the stand-alone benchmark code to characterize + * the performance + */ +struct leaf_info_x4 { + unsigned char *wots_sig; + uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ + uint32_t *wots_steps; + uint32_t leaf_addr[4 * 8]; + uint32_t pk_addr[4 * 8]; +}; + +/* Macro to set the leaf_info to something 'benign', that is, it would */ +/* run with the same time as it does during the real signing process */ +/* Used only by the benchmark code */ +#define INITIALIZE_LEAF_INFO_X4(info, addr, step_buffer) { \ + (info).wots_sig = 0; \ + (info).wots_sign_leaf = ~0; \ + (info).wots_steps = step_buffer; \ + int i; \ + for (i=0; i<4; i++) { \ + memcpy( &(info).leaf_addr[8*i], addr, 32 ); \ + memcpy( &(info).pk_addr[8*i], addr, 32 ); \ + } \ + } + +#define wots_gen_leafx4 SPX_NAMESPACE(wots_gen_leafx4) +void wots_gen_leafx4(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info); + +#endif /* WOTSX4_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_clean/LICENSE b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_clean/LICENSE new file mode 100644 index 0000000000..670154e353 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_clean/LICENSE @@ -0,0 +1,116 @@ +CC0 1.0 Universal + +Statement of Purpose + +The laws of most jurisdictions throughout the world automatically confer +exclusive Copyright and Related Rights (defined below) upon the creator and +subsequent owner(s) (each and all, an "owner") of an original work of +authorship and/or a database (each, a "Work"). + +Certain owners wish to permanently relinquish those rights to a Work for the +purpose of contributing to a commons of creative, cultural and scientific +works ("Commons") that the public can reliably and without fear of later +claims of infringement build upon, modify, incorporate in other works, reuse +and redistribute as freely as possible in any form whatsoever and for any +purposes, including without limitation commercial purposes. These owners may +contribute to the Commons to promote the ideal of a free culture and the +further production of creative, cultural and scientific works, or to gain +reputation or greater distribution for their Work in part through the use and +efforts of others. + +For these and/or other purposes and motivations, and without any expectation +of additional consideration or compensation, the person associating CC0 with a +Work (the "Affirmer"), to the extent that he or she is an owner of Copyright +and Related Rights in the Work, voluntarily elects to apply CC0 to the Work +and publicly distribute the Work under its terms, with knowledge of his or her +Copyright and Related Rights in the Work and the meaning and intended legal +effect of CC0 on those rights. + +1. Copyright and Related Rights. A Work made available under CC0 may be +protected by copyright and related or neighboring rights ("Copyright and +Related Rights"). Copyright and Related Rights include, but are not limited +to, the following: + + i. the right to reproduce, adapt, distribute, perform, display, communicate, + and translate a Work; + + ii. moral rights retained by the original author(s) and/or performer(s); + + iii. publicity and privacy rights pertaining to a person's image or likeness + depicted in a Work; + + iv. rights protecting against unfair competition in regards to a Work, + subject to the limitations in paragraph 4(a), below; + + v. rights protecting the extraction, dissemination, use and reuse of data in + a Work; + + vi. database rights (such as those arising under Directive 96/9/EC of the + European Parliament and of the Council of 11 March 1996 on the legal + protection of databases, and under any national implementation thereof, + including any amended or successor version of such directive); and + + vii. other similar, equivalent or corresponding rights throughout the world + based on applicable law or treaty, and any national implementations thereof. + +2. Waiver. To the greatest extent permitted by, but not in contravention of, +applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and +unconditionally waives, abandons, and surrenders all of Affirmer's Copyright +and Related Rights and associated claims and causes of action, whether now +known or unknown (including existing as well as future claims and causes of +action), in the Work (i) in all territories worldwide, (ii) for the maximum +duration provided by applicable law or treaty (including future time +extensions), (iii) in any current or future medium and for any number of +copies, and (iv) for any purpose whatsoever, including without limitation +commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes +the Waiver for the benefit of each member of the public at large and to the +detriment of Affirmer's heirs and successors, fully intending that such Waiver +shall not be subject to revocation, rescission, cancellation, termination, or +any other legal or equitable action to disrupt the quiet enjoyment of the Work +by the public as contemplated by Affirmer's express Statement of Purpose. + +3. Public License Fallback. Should any part of the Waiver for any reason be +judged legally invalid or ineffective under applicable law, then the Waiver +shall be preserved to the maximum extent permitted taking into account +Affirmer's express Statement of Purpose. In addition, to the extent the Waiver +is so judged Affirmer hereby grants to each affected person a royalty-free, +non transferable, non sublicensable, non exclusive, irrevocable and +unconditional license to exercise Affirmer's Copyright and Related Rights in +the Work (i) in all territories worldwide, (ii) for the maximum duration +provided by applicable law or treaty (including future time extensions), (iii) +in any current or future medium and for any number of copies, and (iv) for any +purpose whatsoever, including without limitation commercial, advertising or +promotional purposes (the "License"). The License shall be deemed effective as +of the date CC0 was applied by Affirmer to the Work. Should any part of the +License for any reason be judged legally invalid or ineffective under +applicable law, such partial invalidity or ineffectiveness shall not +invalidate the remainder of the License, and in such case Affirmer hereby +affirms that he or she will not (i) exercise any of his or her remaining +Copyright and Related Rights in the Work or (ii) assert any associated claims +and causes of action with respect to the Work, in either case contrary to +Affirmer's express Statement of Purpose. + +4. Limitations and Disclaimers. + + a. No trademark or patent rights held by Affirmer are waived, abandoned, + surrendered, licensed or otherwise affected by this document. + + b. Affirmer offers the Work as-is and makes no representations or warranties + of any kind concerning the Work, express, implied, statutory or otherwise, + including without limitation warranties of title, merchantability, fitness + for a particular purpose, non infringement, or the absence of latent or + other defects, accuracy, or the present or absence of errors, whether or not + discoverable, all to the greatest extent permissible under applicable law. + + c. Affirmer disclaims responsibility for clearing rights of other persons + that may apply to the Work or any use thereof, including without limitation + any person's Copyright and Related Rights in the Work. Further, Affirmer + disclaims responsibility for obtaining any necessary consents, permissions + or other rights required for any use of the Work. + + d. Affirmer understands and acknowledges that Creative Commons is not a + party to this document and has no duty or obligation with respect to this + CC0 or use of the Work. + +For more information, please see + diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_clean/address.c b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_clean/address.c new file mode 100644 index 0000000000..b956e9cb29 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_clean/address.c @@ -0,0 +1,91 @@ +#include +#include + +#include "address.h" +#include "params.h" +#include "utils.h" + +/* + * Specify which level of Merkle tree (the "layer") we're working on + */ +void set_layer_addr(uint32_t addr[8], uint32_t layer) { + ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; +} + +/* + * Specify which Merkle tree within the level (the "tree address") we're working on + */ +void set_tree_addr(uint32_t addr[8], uint64_t tree) { + ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); +} + +/* + * Specify the reason we'll use this address structure for, that is, what + * hash will we compute with it. This is used so that unrelated types of + * hashes don't accidentally get the same address structure. The type will be + * one of the SPX_ADDR_TYPE constants + */ +void set_type(uint32_t addr[8], uint32_t type) { + ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; +} + +/* + * Copy the layer and tree fields of the address structure. This is used + * when we're doing multiple types of hashes within the same Merkle tree + */ +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); +} + +/* These functions are used for OTS addresses. */ + +/* + * Specify which Merkle leaf we're working on; that is, which OTS keypair + * we're talking about. + */ +void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { + ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; +} + +/* + * Copy the layer, tree and keypair fields of the address structure. This is + * used when we're doing multiple things within the same OTS keypair + */ +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); + ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; +} + +/* + * Specify which Merkle chain within the OTS we're working with + * (the chain address) + */ +void set_chain_addr(uint32_t addr[8], uint32_t chain) { + ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; +} + +/* + * Specify where in the Merkle chain we are +* (the hash address) + */ +void set_hash_addr(uint32_t addr[8], uint32_t hash) { + ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; +} + +/* These functions are used for all hash tree addresses (including FORS). */ + +/* + * Specify the height of the node in the Merkle/FORS tree we are in + * (the tree height) + */ +void set_tree_height(uint32_t addr[8], uint32_t tree_height) { + ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; +} + +/* + * Specify the distance from the left edge of the node in the Merkle/FORS tree + * (the tree index) + */ +void set_tree_index(uint32_t addr[8], uint32_t tree_index) { + u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_clean/address.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_clean/address.h new file mode 100644 index 0000000000..24a84eb40c --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_clean/address.h @@ -0,0 +1,52 @@ +#ifndef SPX_ADDRESS_H +#define SPX_ADDRESS_H + +#include + +#include "params.h" + +/* The hash types that are passed to set_type */ +#define SPX_ADDR_TYPE_WOTS 0 +#define SPX_ADDR_TYPE_WOTSPK 1 +#define SPX_ADDR_TYPE_HASHTREE 2 +#define SPX_ADDR_TYPE_FORSTREE 3 +#define SPX_ADDR_TYPE_FORSPK 4 +#define SPX_ADDR_TYPE_WOTSPRF 5 +#define SPX_ADDR_TYPE_FORSPRF 6 + +#define set_layer_addr SPX_NAMESPACE(set_layer_addr) +void set_layer_addr(uint32_t addr[8], uint32_t layer); + +#define set_tree_addr SPX_NAMESPACE(set_tree_addr) +void set_tree_addr(uint32_t addr[8], uint64_t tree); + +#define set_type SPX_NAMESPACE(set_type) +void set_type(uint32_t addr[8], uint32_t type); + +/* Copies the layer and tree part of one address into the other */ +#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); + +/* These functions are used for WOTS and FORS addresses. */ + +#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) +void set_keypair_addr(uint32_t addr[8], uint32_t keypair); + +#define set_chain_addr SPX_NAMESPACE(set_chain_addr) +void set_chain_addr(uint32_t addr[8], uint32_t chain); + +#define set_hash_addr SPX_NAMESPACE(set_hash_addr) +void set_hash_addr(uint32_t addr[8], uint32_t hash); + +#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); + +/* These functions are used for all hash tree addresses (including FORS). */ + +#define set_tree_height SPX_NAMESPACE(set_tree_height) +void set_tree_height(uint32_t addr[8], uint32_t tree_height); + +#define set_tree_index SPX_NAMESPACE(set_tree_index) +void set_tree_index(uint32_t addr[8], uint32_t tree_index); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_clean/api.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_clean/api.h new file mode 100644 index 0000000000..5f95eb137d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_clean/api.h @@ -0,0 +1,77 @@ +#ifndef PQCLEAN_SPHINCSSHAKE128FSIMPLE_CLEAN_API_H +#define PQCLEAN_SPHINCSSHAKE128FSIMPLE_CLEAN_API_H + +#include +#include + +#define PQCLEAN_SPHINCSSHAKE128FSIMPLE_CLEAN_CRYPTO_ALGNAME "SPHINCS+-shake-128f-simple" + +#define PQCLEAN_SPHINCSSHAKE128FSIMPLE_CLEAN_CRYPTO_SECRETKEYBYTES 64 +#define PQCLEAN_SPHINCSSHAKE128FSIMPLE_CLEAN_CRYPTO_PUBLICKEYBYTES 32 +#define PQCLEAN_SPHINCSSHAKE128FSIMPLE_CLEAN_CRYPTO_BYTES 17088 + +#define PQCLEAN_SPHINCSSHAKE128FSIMPLE_CLEAN_CRYPTO_SEEDBYTES 48 + +/* + * Returns the length of a secret key, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE128FSIMPLE_CLEAN_crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE128FSIMPLE_CLEAN_crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE128FSIMPLE_CLEAN_crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE128FSIMPLE_CLEAN_crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +int PQCLEAN_SPHINCSSHAKE128FSIMPLE_CLEAN_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +int PQCLEAN_SPHINCSSHAKE128FSIMPLE_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +int PQCLEAN_SPHINCSSHAKE128FSIMPLE_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +int PQCLEAN_SPHINCSSHAKE128FSIMPLE_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, + const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +int PQCLEAN_SPHINCSSHAKE128FSIMPLE_CLEAN_crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +int PQCLEAN_SPHINCSSHAKE128FSIMPLE_CLEAN_crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_clean/context.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_clean/context.h new file mode 100644 index 0000000000..9f8a40ab4e --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_clean/context.h @@ -0,0 +1,22 @@ +#ifndef SPX_CONTEXT_H +#define SPX_CONTEXT_H + +#include +#include + +#include "params.h" + +typedef struct { + uint8_t pub_seed[SPX_N]; + uint8_t sk_seed[SPX_N]; + + +} spx_ctx; + +#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) +void initialize_hash_function(spx_ctx *ctx); + +#define free_hash_function SPX_NAMESPACE(free_hash_function) +void free_hash_function(spx_ctx *ctx); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_clean/context_shake.c b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_clean/context_shake.c new file mode 100644 index 0000000000..9614a103d3 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_clean/context_shake.c @@ -0,0 +1,12 @@ +#include "context.h" + +/* For SHAKE256, there is no immediate reason to initialize at the start, + so this function is an empty operation. */ +void initialize_hash_function(spx_ctx *ctx) { + (void)ctx; /* Suppress an 'unused parameter' warning. */ +} + +// in case the hash function api is heap-based. +void free_hash_function(spx_ctx *ctx) { + (void)ctx; +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_clean/fors.c b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_clean/fors.c new file mode 100644 index 0000000000..96ca72e986 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_clean/fors.c @@ -0,0 +1,156 @@ +#include +#include +#include + +#include "fors.h" + +#include "address.h" +#include "hash.h" +#include "thash.h" +#include "utils.h" +#include "utilsx1.h" + +static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + prf_addr(sk, ctx, fors_leaf_addr); +} + +static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, + const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + thash(leaf, sk, 1, ctx, fors_leaf_addr); +} + +struct fors_gen_leaf_info { + uint32_t leaf_addrx[8]; +}; + +static void fors_gen_leafx1(unsigned char *leaf, + const spx_ctx *ctx, + uint32_t addr_idx, void *info) { + struct fors_gen_leaf_info *fors_info = info; + uint32_t *fors_leaf_addr = fors_info->leaf_addrx; + + /* Only set the parts that the caller doesn't set */ + set_tree_index(fors_leaf_addr, addr_idx); + set_type(fors_leaf_addr, SPX_ADDR_TYPE_FORSPRF); + fors_gen_sk(leaf, ctx, fors_leaf_addr); + + set_type(fors_leaf_addr, SPX_ADDR_TYPE_FORSTREE); + fors_sk_to_leaf(leaf, leaf, + ctx, fors_leaf_addr); +} + +/** + * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + * Assumes indices has space for SPX_FORS_TREES integers. + */ +static void message_to_indices(uint32_t *indices, const unsigned char *m) { + unsigned int i, j; + unsigned int offset = 0; + + for (i = 0; i < SPX_FORS_TREES; i++) { + indices[i] = 0; + for (j = 0; j < SPX_FORS_HEIGHT; j++) { + indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); + offset++; + } + } +} + +/** + * Signs a message m, deriving the secret key from sk_seed and the FTS address. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + uint32_t fors_tree_addr[8] = {0}; + struct fors_gen_leaf_info fors_info = {0}; + uint32_t *fors_leaf_addr = fors_info.leaf_addrx; + uint32_t fors_pk_addr[8] = {0}; + uint32_t idx_offset; + unsigned int i; + + copy_keypair_addr(fors_tree_addr, fors_addr); + copy_keypair_addr(fors_leaf_addr, fors_addr); + + copy_keypair_addr(fors_pk_addr, fors_addr); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); + + message_to_indices(indices, m); + + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); + + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); + + /* Include the secret key part that produces the selected leaf node. */ + fors_gen_sk(sig, ctx, fors_tree_addr); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + sig += SPX_N; + + /* Compute the authentication path for this leaf node. */ + treehashx1(roots + i * SPX_N, sig, ctx, + indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx1, + fors_tree_addr, &fors_info); + + sig += SPX_N * SPX_FORS_HEIGHT; + } + + /* Hash horizontally across all tree roots to derive the public key. */ + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); +} + +/** + * Derives the FORS public key from a signature. + * This can be used for verification by comparing to a known public key, or to + * subsequently verify a signature on the derived public key. The latter is the + * typical use-case when used as an FTS below an OTS in a hypertree. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + unsigned char leaf[SPX_N]; + uint32_t fors_tree_addr[8] = {0}; + uint32_t fors_pk_addr[8] = {0}; + uint32_t idx_offset; + unsigned int i; + + copy_keypair_addr(fors_tree_addr, fors_addr); + copy_keypair_addr(fors_pk_addr, fors_addr); + + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); + + message_to_indices(indices, m); + + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); + + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + + /* Derive the leaf from the included secret key part. */ + fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); + sig += SPX_N; + + /* Derive the corresponding root node of this tree. */ + compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, + sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); + sig += SPX_N * SPX_FORS_HEIGHT; + } + + /* Hash horizontally across all tree roots to derive the public key. */ + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_clean/fors.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_clean/fors.h new file mode 100644 index 0000000000..509140a178 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_clean/fors.h @@ -0,0 +1,32 @@ +#ifndef SPX_FORS_H +#define SPX_FORS_H + +#include + +#include "context.h" +#include "params.h" + +/** + * Signs a message m, deriving the secret key from sk_seed and the FTS address. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +#define fors_sign SPX_NAMESPACE(fors_sign) +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); + +/** + * Derives the FORS public key from a signature. + * This can be used for verification by comparing to a known public key, or to + * subsequently verify a signature on the derived public key. The latter is the + * typical use-case when used as an FTS below an OTS in a hypertree. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_clean/hash.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_clean/hash.h new file mode 100644 index 0000000000..f7c87d4c3c --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_clean/hash.h @@ -0,0 +1,28 @@ +#ifndef SPX_HASH_H +#define SPX_HASH_H + +#include +#include + +#include "context.h" +#include "params.h" + +#define prf_addr SPX_NAMESPACE(prf_addr) +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]); + +#define gen_message_random SPX_NAMESPACE(gen_message_random) +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); + +#define hash_message SPX_NAMESPACE(hash_message) +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); + + + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_clean/hash_shake.c b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_clean/hash_shake.c new file mode 100644 index 0000000000..ff5e7ec918 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_clean/hash_shake.c @@ -0,0 +1,83 @@ +#include +#include + +#include "hash.h" + +#include "address.h" +#include "fips202.h" +#include "params.h" +#include "utils.h" + +/* + * Computes PRF(pk_seed, sk_seed, addr) + */ +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]) { + unsigned char buf[2 * SPX_N + SPX_ADDR_BYTES]; + + memcpy(buf, ctx->pub_seed, SPX_N); + memcpy(buf + SPX_N, addr, SPX_ADDR_BYTES); + memcpy(buf + SPX_N + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); + + shake256(out, SPX_N, buf, 2 * SPX_N + SPX_ADDR_BYTES); +} + +/** + * Computes the message-dependent randomness R, using a secret seed and an + * optional randomization value as well as the message. + */ +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { + (void)ctx; + shake256incctx s_inc; + + shake256_inc_init(&s_inc); + shake256_inc_absorb(&s_inc, sk_prf, SPX_N); + shake256_inc_absorb(&s_inc, optrand, SPX_N); + shake256_inc_absorb(&s_inc, m, mlen); + shake256_inc_finalize(&s_inc); + shake256_inc_squeeze(R, SPX_N, &s_inc); + shake256_inc_ctx_release(&s_inc); +} + +/** + * Computes the message hash using R, the public key, and the message. + * Outputs the message digest and the index of the leaf. The index is split in + * the tree index and the leaf index, for convenient copying to an address. + */ +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { + (void)ctx; +#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) +#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) +#define SPX_LEAF_BITS SPX_TREE_HEIGHT +#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) +#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) + + unsigned char buf[SPX_DGST_BYTES]; + unsigned char *bufp = buf; + shake256incctx s_inc; + + shake256_inc_init(&s_inc); + shake256_inc_absorb(&s_inc, R, SPX_N); + shake256_inc_absorb(&s_inc, pk, SPX_PK_BYTES); + shake256_inc_absorb(&s_inc, m, mlen); + shake256_inc_finalize(&s_inc); + shake256_inc_squeeze(buf, SPX_DGST_BYTES, &s_inc); + shake256_inc_ctx_release(&s_inc); + + memcpy(digest, bufp, SPX_FORS_MSG_BYTES); + bufp += SPX_FORS_MSG_BYTES; + + + *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); + *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); + bufp += SPX_TREE_BYTES; + + *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); + *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_clean/merkle.c b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_clean/merkle.c new file mode 100644 index 0000000000..0c1479fd93 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_clean/merkle.c @@ -0,0 +1,59 @@ +#include +#include + +#include "address.h" +#include "merkle.h" +#include "params.h" +#include "utils.h" +#include "utilsx1.h" +#include "wots.h" +#include "wotsx1.h" + +/* + * This generates a Merkle signature (WOTS signature followed by the Merkle + * authentication path). This is in this file because most of the complexity + * is involved with the WOTS signature; the Merkle authentication path logic + * is mostly hidden in treehashx4 + */ +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf) { + unsigned char *auth_path = sig + SPX_WOTS_BYTES; + struct leaf_info_x1 info = { 0 }; + unsigned steps[ SPX_WOTS_LEN ]; + + info.wots_sig = sig; + chain_lengths(steps, root); + info.wots_steps = steps; + + set_type(&tree_addr[0], SPX_ADDR_TYPE_HASHTREE); + set_type(&info.pk_addr[0], SPX_ADDR_TYPE_WOTSPK); + copy_subtree_addr(&info.leaf_addr[0], wots_addr); + copy_subtree_addr(&info.pk_addr[0], wots_addr); + + info.wots_sign_leaf = idx_leaf; + + treehashx1(root, auth_path, ctx, + idx_leaf, 0, + SPX_TREE_HEIGHT, + wots_gen_leafx1, + tree_addr, &info); +} + +/* Compute root node of the top-most subtree. */ +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { + /* We do not need the auth path in key generation, but it simplifies the + code to have just one treehash routine that computes both root and path + in one function. */ + unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; + uint32_t top_tree_addr[8] = {0}; + uint32_t wots_addr[8] = {0}; + + set_layer_addr(top_tree_addr, SPX_D - 1); + set_layer_addr(wots_addr, SPX_D - 1); + + merkle_sign(auth_path, root, ctx, + wots_addr, top_tree_addr, + (uint32_t)~0 /* ~0 means "don't bother generating an auth path */ ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_clean/merkle.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_clean/merkle.h new file mode 100644 index 0000000000..769cf2e970 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_clean/merkle.h @@ -0,0 +1,21 @@ +#ifndef MERKLE_H_ +#define MERKLE_H_ + +#include + +#include "context.h" +#include "params.h" + +/* Generate a Merkle signature (WOTS signature followed by the Merkle */ +/* authentication path) */ +#define merkle_sign SPX_NAMESPACE(merkle_sign) +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf); + +/* Compute the root node of the top-most subtree. */ +#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); + +#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_clean/nistapi.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_clean/nistapi.h new file mode 100644 index 0000000000..3cb71afad4 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_clean/nistapi.h @@ -0,0 +1,87 @@ +#ifndef SPX_API_H +#define SPX_API_H + +#include +#include + +#include "params.h" + +#define CRYPTO_ALGNAME "SPHINCS+" + +#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES +#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES +#define CRYPTO_BYTES SPX_BYTES +#define CRYPTO_SEEDBYTES (3*SPX_N) + +/* + * Returns the length of a secret key, in bytes + */ +#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) +size_t crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) +size_t crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) +size_t crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) +size_t crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +#define crypto_sign SPX_NAMESPACE(crypto_sign) +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_clean/params.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_clean/params.h new file mode 100644 index 0000000000..865ed51f78 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_clean/params.h @@ -0,0 +1,56 @@ +#ifndef SPX_PARAMS_H +#define SPX_PARAMS_H + +#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSSHAKE128FSIMPLE_CLEAN_##s + +/* Hash output length in bytes. */ +#define SPX_N 16 +/* Height of the hypertree. */ +#define SPX_FULL_HEIGHT 66 +/* Number of subtree layer. */ +#define SPX_D 22 +/* FORS tree dimensions. */ +#define SPX_FORS_HEIGHT 6 +#define SPX_FORS_TREES 33 +/* Winternitz parameter, */ +#define SPX_WOTS_W 16 + +/* The hash function is defined by linking a different hash.c file, as opposed + to setting a #define constant. */ + +/* For clarity */ +#define SPX_ADDR_BYTES 32 + +/* WOTS parameters. */ +#define SPX_WOTS_LOGW 4 + +#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) + +/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ +#define SPX_WOTS_LEN2 3 + +#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) +#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) +#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES + +/* Subtree size. */ +#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) + +//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT +// #error SPX_D should always divide SPX_FULL_HEIGHT +//#endif + +/* FORS parameters. */ +#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) +#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) +#define SPX_FORS_PK_BYTES SPX_N + +/* Resulting SPX sizes. */ +#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ + SPX_FULL_HEIGHT * SPX_N) +#define SPX_PK_BYTES (2 * SPX_N) +#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) + +#include "shake_offsets.h" + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_clean/shake_offsets.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_clean/shake_offsets.h new file mode 100644 index 0000000000..6b28d95d91 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_clean/shake_offsets.h @@ -0,0 +1,21 @@ +#ifndef SHAKE_OFFSETS_H_ +#define SHAKE_OFFSETS_H_ + +/* + * Offsets of various fields in the address structure when we use SHAKE as + * the Sphincs+ hash function + */ + +#define SPX_OFFSET_LAYER 3 /* The byte used to specify the Merkle tree layer */ +#define SPX_OFFSET_TREE 8 /* The start of the 8 byte field used to specify the tree */ +#define SPX_OFFSET_TYPE 19 /* The byte used to specify the hash type (reason) */ +#define SPX_OFFSET_KP_ADDR2 22 /* The high byte used to specify the key pair (which one-time signature) */ +#define SPX_OFFSET_KP_ADDR1 23 /* The low byte used to specify the key pair */ +#define SPX_OFFSET_CHAIN_ADDR 27 /* The byte used to specify the chain address (which Winternitz chain) */ +#define SPX_OFFSET_HASH_ADDR 31 /* The byte used to specify the hash address (where in the Winternitz chain) */ +#define SPX_OFFSET_TREE_HGT 27 /* The byte used to specify the height of this node in the FORS or Merkle tree */ +#define SPX_OFFSET_TREE_INDEX 28 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ + +#define SPX_SHAKE 1 + +#endif /* SHAKE_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_clean/sign.c b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_clean/sign.c new file mode 100644 index 0000000000..9d0c7d1b22 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_clean/sign.c @@ -0,0 +1,286 @@ +#include +#include +#include + +#include "address.h" +#include "context.h" +#include "fors.h" +#include "hash.h" +#include "merkle.h" +#include "nistapi.h" +#include "params.h" +#include "randombytes.h" +#include "thash.h" +#include "utils.h" +#include "wots.h" + +/* + * Returns the length of a secret key, in bytes + */ +size_t crypto_sign_secretkeybytes(void) { + return CRYPTO_SECRETKEYBYTES; +} + +/* + * Returns the length of a public key, in bytes + */ +size_t crypto_sign_publickeybytes(void) { + return CRYPTO_PUBLICKEYBYTES; +} + +/* + * Returns the length of a signature, in bytes + */ +size_t crypto_sign_bytes(void) { + return CRYPTO_BYTES; +} + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +size_t crypto_sign_seedbytes(void) { + return CRYPTO_SEEDBYTES; +} + +/* + * Generates an SPX key pair given a seed of length + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [PUB_SEED || root] + */ +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed) { + spx_ctx ctx; + + /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ + memcpy(sk, seed, CRYPTO_SEEDBYTES); + + memcpy(pk, sk + 2 * SPX_N, SPX_N); + + memcpy(ctx.pub_seed, pk, SPX_N); + memcpy(ctx.sk_seed, sk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + /* Compute root node of the top-most subtree. */ + merkle_gen_root(sk + 3 * SPX_N, &ctx); + + // cleanup + free_hash_function(&ctx); + + memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); + + return 0; +} + +/* + * Generates an SPX key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [PUB_SEED || root] + */ +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { + uint8_t seed[CRYPTO_SEEDBYTES]; + randombytes(seed, CRYPTO_SEEDBYTES); + crypto_sign_seed_keypair(pk, sk, seed); + + return 0; +} + +/** + * Returns an array containing a detached signature. + */ +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk) { + spx_ctx ctx; + + const uint8_t *sk_prf = sk + SPX_N; + const uint8_t *pk = sk + 2 * SPX_N; + + uint8_t optrand[SPX_N]; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t root[SPX_N]; + uint32_t i; + uint64_t tree; + uint32_t idx_leaf; + uint32_t wots_addr[8] = {0}; + uint32_t tree_addr[8] = {0}; + + memcpy(ctx.sk_seed, sk, SPX_N); + memcpy(ctx.pub_seed, pk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + + /* Optionally, signing can be made non-deterministic using optrand. + This can help counter side-channel attacks that would benefit from + getting a large number of traces when the signer uses the same nodes. */ + randombytes(optrand, SPX_N); + /* Compute the digest randomization value. */ + gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); + + /* Derive the message digest and leaf index from R, PK and M. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; + + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); + + /* Sign the message hash using FORS. */ + fors_sign(sig, root, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); + sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; + + /* Update the indices for the next layer. */ + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; + } + + free_hash_function(&ctx); + + *siglen = SPX_BYTES; + + return 0; +} + +/** + * Verifies a detached signature and message under a given public key. + */ +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk) { + spx_ctx ctx; + const uint8_t *pub_root = pk + SPX_N; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t wots_pk[SPX_WOTS_BYTES]; + uint8_t root[SPX_N]; + uint8_t leaf[SPX_N]; + unsigned int i; + uint64_t tree; + uint32_t idx_leaf; + uint32_t wots_addr[8] = {0}; + uint32_t tree_addr[8] = {0}; + uint32_t wots_pk_addr[8] = {0}; + + if (siglen != SPX_BYTES) { + return -1; + } + + memcpy(ctx.pub_seed, pk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); + + /* Derive the message digest and leaf index from R || PK || M. */ + /* The additional SPX_N is a result of the hash domain separator. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; + + /* Layer correctly defaults to 0, so no need to set_layer_addr */ + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); + + fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + /* For each subtree.. */ + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + copy_keypair_addr(wots_pk_addr, wots_addr); + + /* The WOTS public key is only correct if the signature was correct. */ + /* Initially, root is the FORS pk, but on subsequent iterations it is + the root of the subtree below the currently processed subtree. */ + wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); + sig += SPX_WOTS_BYTES; + + /* Compute the leaf node using the WOTS public key. */ + thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); + + /* Compute the root node of this subtree. */ + compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, + &ctx, tree_addr); + sig += SPX_TREE_HEIGHT * SPX_N; + + /* Update the indices for the next layer. */ + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; + } + + // cleanup + free_hash_function(&ctx); + + /* Check if the root node equals the root node in the public key. */ + if (memcmp(root, pub_root, SPX_N) != 0) { + return -1; + } + + return 0; +} + + +/** + * Returns an array containing the signature followed by the message. + */ +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk) { + size_t siglen; + + crypto_sign_signature(sm, &siglen, m, mlen, sk); + + memmove(sm + SPX_BYTES, m, mlen); + *smlen = siglen + mlen; + + return 0; +} + +/** + * Verifies a given signature-message pair under a given public key. + */ +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk) { + /* The API caller does not necessarily know what size a signature should be + but SPHINCS+ signatures are always exactly SPX_BYTES. */ + if (smlen < SPX_BYTES) { + memset(m, 0, smlen); + *mlen = 0; + return -1; + } + + *mlen = smlen - SPX_BYTES; + + if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { + memset(m, 0, smlen); + *mlen = 0; + return -1; + } + + /* If verification was successful, move the message to the right place. */ + memmove(m, sm + SPX_BYTES, *mlen); + + return 0; +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_clean/thash.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_clean/thash.h new file mode 100644 index 0000000000..8687ccfb4d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_clean/thash.h @@ -0,0 +1,13 @@ +#ifndef SPX_THASH_H +#define SPX_THASH_H + +#include "context.h" +#include "params.h" + +#include + +#define thash SPX_NAMESPACE(thash) +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_clean/thash_shake_simple.c b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_clean/thash_shake_simple.c new file mode 100644 index 0000000000..98470395e9 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_clean/thash_shake_simple.c @@ -0,0 +1,24 @@ +#include +#include + +#include "thash.h" + +#include "address.h" +#include "params.h" +#include "utils.h" + +#include "fips202.h" + +/** + * Takes an array of inblocks concatenated arrays of SPX_N bytes. + */ +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]) { + PQCLEAN_VLA(uint8_t, buf, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); + + memcpy(buf, ctx->pub_seed, SPX_N); + memcpy(buf + SPX_N, addr, SPX_ADDR_BYTES); + memcpy(buf + SPX_N + SPX_ADDR_BYTES, in, inblocks * SPX_N); + + shake256(out, SPX_N, buf, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_clean/utils.c b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_clean/utils.c new file mode 100644 index 0000000000..177b541fb9 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_clean/utils.c @@ -0,0 +1,148 @@ +#include + +#include "utils.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "thash.h" + +/** + * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. + */ +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in) { + int i; + + /* Iterate over out in decreasing order, for big-endianness. */ + for (i = (signed int)outlen - 1; i >= 0; i--) { + out[i] = in & 0xff; + in = in >> 8; + } +} + +void u32_to_bytes(unsigned char *out, uint32_t in) { + out[0] = (unsigned char)(in >> 24); + out[1] = (unsigned char)(in >> 16); + out[2] = (unsigned char)(in >> 8); + out[3] = (unsigned char)in; +} + +/** + * Converts the inlen bytes in 'in' from big-endian byte order to an integer. + */ +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { + unsigned long long retval = 0; + unsigned int i; + + for (i = 0; i < inlen; i++) { + retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); + } + return retval; +} + +/** + * Computes a root node given a leaf and an auth path. + * Expects address to be complete other than the tree_height and tree_index. + */ +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]) { + uint32_t i; + unsigned char buffer[2 * SPX_N]; + + /* If leaf_idx is odd (last bit = 1), current path element is a right child + and auth_path has to go left. Otherwise it is the other way around. */ + if (leaf_idx & 1) { + memcpy(buffer + SPX_N, leaf, SPX_N); + memcpy(buffer, auth_path, SPX_N); + } else { + memcpy(buffer, leaf, SPX_N); + memcpy(buffer + SPX_N, auth_path, SPX_N); + } + auth_path += SPX_N; + + for (i = 0; i < tree_height - 1; i++) { + leaf_idx >>= 1; + idx_offset >>= 1; + /* Set the address of the node we're creating. */ + set_tree_height(addr, i + 1); + set_tree_index(addr, leaf_idx + idx_offset); + + /* Pick the right or left neighbor, depending on parity of the node. */ + if (leaf_idx & 1) { + thash(buffer + SPX_N, buffer, 2, ctx, addr); + memcpy(buffer, auth_path, SPX_N); + } else { + thash(buffer, buffer, 2, ctx, addr); + memcpy(buffer + SPX_N, auth_path, SPX_N); + } + auth_path += SPX_N; + } + + /* The last iteration is exceptional; we do not copy an auth_path node. */ + leaf_idx >>= 1; + idx_offset >>= 1; + set_tree_height(addr, tree_height); + set_tree_index(addr, leaf_idx + idx_offset); + thash(root, buffer, 2, ctx, addr); +} + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx * /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]) { + PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); + PQCLEAN_VLA(unsigned int, heights, tree_height + 1); + unsigned int offset = 0; + uint32_t idx; + uint32_t tree_idx; + + for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { + /* Add the next leaf node to the stack. */ + gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); + offset++; + heights[offset - 1] = 0; + + /* If this is a node we need for the auth path.. */ + if ((leaf_idx ^ 0x1) == idx) { + memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); + } + + /* While the top-most nodes are of equal height.. */ + while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { + /* Compute index of the new node, in the next layer. */ + tree_idx = (idx >> (heights[offset - 1] + 1)); + + /* Set the address of the node we're creating. */ + set_tree_height(tree_addr, heights[offset - 1] + 1); + set_tree_index(tree_addr, + tree_idx + (idx_offset >> (heights[offset - 1] + 1))); + /* Hash the top-most nodes from the stack together. */ + thash(stack + (offset - 2)*SPX_N, + stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); + offset--; + /* Note that the top-most node is now one layer higher. */ + heights[offset - 1]++; + + /* If this is a node we need for the auth path.. */ + if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { + memcpy(auth_path + heights[offset - 1]*SPX_N, + stack + (offset - 1)*SPX_N, SPX_N); + } + } + } + memcpy(root, stack, SPX_N); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_clean/utils.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_clean/utils.h new file mode 100644 index 0000000000..64f5d5a53a --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_clean/utils.h @@ -0,0 +1,58 @@ +#ifndef SPX_UTILS_H +#define SPX_UTILS_H + +#include + +#include "compat.h" +#include "context.h" +#include "params.h" + + +/* To support MSVC use alloca() instead of VLAs. See #20. */ + + +/** + * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. + */ +#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in); +#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) +void u32_to_bytes(unsigned char *out, uint32_t in); + +/** + * Converts the inlen bytes in 'in' from big-endian byte order to an integer. + */ +#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); + +/** + * Computes a root node given a leaf and an auth path. + * Expects address to be complete other than the tree_height and tree_index. + */ +#define compute_root SPX_NAMESPACE(compute_root) +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]); + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +#define treehash SPX_NAMESPACE(treehash) +void treehash(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx *ctx /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]); + + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_clean/utilsx1.c b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_clean/utilsx1.c new file mode 100644 index 0000000000..fccb69b35d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_clean/utilsx1.c @@ -0,0 +1,100 @@ +#include + +#include "utilsx1.h" + +#include "address.h" +#include "params.h" +#include "thash.h" +#include "utils.h" + +/* + * Generate the entire Merkle tree, computing the authentication path for + * leaf_idx, and the resulting root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) + * + * This expects tree_addr to be initialized to the addr structures for the + * Merkle tree nodes + * + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + * + * This works by using the standard Merkle tree building algorithm, + */ +void treehashx1(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, + uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* Where to write the leaves */, + const spx_ctx * /* ctx */, + uint32_t idx, void *info), + uint32_t tree_addr[8], + void *info) { + /* This is where we keep the intermediate nodes */ + PQCLEAN_VLA(uint8_t, stack, tree_height * SPX_N); + + uint32_t idx; + uint32_t max_idx = (uint32_t)((1 << tree_height) - 1); + for (idx = 0;; idx++) { + unsigned char current[2 * SPX_N]; /* Current logical node is at */ + /* index[SPX_N]. We do this to minimize the number of copies */ + /* needed during a thash */ + gen_leaf( ¤t[SPX_N], ctx, idx + idx_offset, + info ); + + /* Now combine the freshly generated right node with previously */ + /* generated left ones */ + uint32_t internal_idx_offset = idx_offset; + uint32_t internal_idx = idx; + uint32_t internal_leaf = leaf_idx; + uint32_t h; /* The height we are in the Merkle tree */ + for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { + + /* Check if we hit the top of the tree */ + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[SPX_N], SPX_N ); + return; + } + + /* + * Check if the node we have is a part of the + * authentication path; if it is, write it out + */ + if ((internal_idx ^ internal_leaf) == 0x01) { + memcpy( &auth_path[ h * SPX_N ], + ¤t[SPX_N], + SPX_N ); + } + + /* + * Check if we're at a left child; if so, stop going up the stack + * Exception: if we've reached the end of the tree, keep on going + * (so we combine the last 4 nodes into the one root node in two + * more iterations) + */ + if ((internal_idx & 1) == 0 && idx < max_idx) { + break; + } + + /* Ok, we're at a right node */ + /* Now combine the left and right logical nodes together */ + + /* Set the address of the node we're creating. */ + internal_idx_offset >>= 1; + set_tree_height(tree_addr, h + 1); + set_tree_index(tree_addr, internal_idx / 2 + internal_idx_offset ); + + unsigned char *left = &stack[h * SPX_N]; + memcpy( ¤t[0], left, SPX_N ); + thash( ¤t[1 * SPX_N], + ¤t[0 * SPX_N], + 2, ctx, tree_addr); + } + + /* We've hit a left child; save the current for when we get the */ + /* corresponding right right */ + memcpy( &stack[h * SPX_N], ¤t[SPX_N], SPX_N); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_clean/utilsx1.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_clean/utilsx1.h new file mode 100644 index 0000000000..e911d17d53 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_clean/utilsx1.h @@ -0,0 +1,27 @@ +#ifndef SPX_UTILSX4_H +#define SPX_UTILSX4_H + +#include + +#include "context.h" +#include "params.h" + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +#define treehashx1 SPX_NAMESPACE(treehashx1) +void treehashx1(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* Where to write the leaf */, + const spx_ctx * /* ctx */, + uint32_t addr_idx, void *info), + uint32_t tree_addrx4[8], void *info); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_clean/wots.c b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_clean/wots.c new file mode 100644 index 0000000000..249717aaa8 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_clean/wots.c @@ -0,0 +1,108 @@ +#include +#include + +#include "wots.h" +#include "wotsx1.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "thash.h" +#include "utils.h" +#include "utilsx1.h" + +// TODO clarify address expectations, and make them more uniform. +// TODO i.e. do we expect types to be set already? +// TODO and do we expect modifications or copies? + +/** + * Computes the chaining function. + * out and in have to be n-byte arrays. + * + * Interprets in as start-th value of the chain. + * addr has to contain the address of the chain. + */ +static void gen_chain(unsigned char *out, const unsigned char *in, + unsigned int start, unsigned int steps, + const spx_ctx *ctx, uint32_t addr[8]) { + uint32_t i; + + /* Initialize out with the value at position 'start'. */ + memcpy(out, in, SPX_N); + + /* Iterate 'steps' calls to the hash function. */ + for (i = start; i < (start + steps) && i < SPX_WOTS_W; i++) { + set_hash_addr(addr, i); + thash(out, out, 1, ctx, addr); + } +} + +/** + * base_w algorithm as described in draft. + * Interprets an array of bytes as integers in base w. + * This only works when log_w is a divisor of 8. + */ +static void base_w(unsigned int *output, const int out_len, + const unsigned char *input) { + int in = 0; + int out = 0; + unsigned char total = 0; + int bits = 0; + int consumed; + + for (consumed = 0; consumed < out_len; consumed++) { + if (bits == 0) { + total = input[in]; + in++; + bits += 8; + } + bits -= SPX_WOTS_LOGW; + output[out] = (total >> bits) & (SPX_WOTS_W - 1); + out++; + } +} + +/* Computes the WOTS+ checksum over a message (in base_w). */ +static void wots_checksum(unsigned int *csum_base_w, + const unsigned int *msg_base_w) { + unsigned int csum = 0; + unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; + unsigned int i; + + /* Compute checksum. */ + for (i = 0; i < SPX_WOTS_LEN1; i++) { + csum += SPX_WOTS_W - 1 - msg_base_w[i]; + } + + /* Convert checksum to base_w. */ + /* Make sure expected empty zero bits are the least significant bits. */ + csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); + ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); + base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); +} + +/* Takes a message and derives the matching chain lengths. */ +void chain_lengths(unsigned int *lengths, const unsigned char *msg) { + base_w(lengths, SPX_WOTS_LEN1, msg); + wots_checksum(lengths + SPX_WOTS_LEN1, lengths); +} + +/** + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. + * + * Writes the computed public key to 'pk'. + */ +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]) { + unsigned int lengths[SPX_WOTS_LEN]; + uint32_t i; + + chain_lengths(lengths, msg); + + for (i = 0; i < SPX_WOTS_LEN; i++) { + set_chain_addr(addr, i); + gen_chain(pk + i * SPX_N, sig + i * SPX_N, + lengths[i], SPX_WOTS_W - 1 - lengths[i], ctx, addr); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_clean/wots.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_clean/wots.h new file mode 100644 index 0000000000..4e7692eeef --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_clean/wots.h @@ -0,0 +1,25 @@ +#ifndef SPX_WOTS_H +#define SPX_WOTS_H + +#include + +#include "context.h" +#include "params.h" + +/** + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. + * + * Writes the computed public key to 'pk'. + */ +#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]); + +/* + * Compute the chain lengths needed for a given message hash + */ +#define chain_lengths SPX_NAMESPACE(chain_lengths) +void chain_lengths(unsigned int *lengths, const unsigned char *msg); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_clean/wotsx1.c b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_clean/wotsx1.c new file mode 100644 index 0000000000..3adec78dfb --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_clean/wotsx1.c @@ -0,0 +1,76 @@ +#include +#include + +#include "wots.h" +#include "wotsx1.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "thash.h" +#include "utils.h" + +/* + * This generates a WOTS public key + * It also generates the WOTS signature if leaf_info indicates + * that we're signing with this WOTS key + */ +void wots_gen_leafx1(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info) { + struct leaf_info_x1 *info = v_info; + uint32_t *leaf_addr = info->leaf_addr; + uint32_t *pk_addr = info->pk_addr; + unsigned int i, k; + unsigned char pk_buffer[ SPX_WOTS_BYTES ]; + unsigned char *buffer; + uint32_t wots_k_mask; + + if (leaf_idx == info->wots_sign_leaf) { + /* We're traversing the leaf that's signing; generate the WOTS */ + /* signature */ + wots_k_mask = 0; + } else { + /* Nope, we're just generating pk's; turn off the signature logic */ + wots_k_mask = (uint32_t)~0; + } + + set_keypair_addr( leaf_addr, leaf_idx ); + set_keypair_addr( pk_addr, leaf_idx ); + + for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { + uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k to */ + /* the step if we're generating a signature, ~0 if we're not */ + + /* Start with the secret seed */ + set_chain_addr(leaf_addr, i); + set_hash_addr(leaf_addr, 0); + set_type(leaf_addr, SPX_ADDR_TYPE_WOTSPRF); + + prf_addr(buffer, ctx, leaf_addr); + + set_type(leaf_addr, SPX_ADDR_TYPE_WOTS); + + /* Iterate down the WOTS chain */ + for (k = 0;; k++) { + /* Check if this is the value that needs to be saved as a */ + /* part of the WOTS signature */ + if (k == wots_k) { + memcpy( info->wots_sig + i * SPX_N, buffer, SPX_N ); + } + + /* Check if we hit the top of the chain */ + if (k == SPX_WOTS_W - 1) { + break; + } + + /* Iterate one step on the chain */ + set_hash_addr(leaf_addr, k); + + thash(buffer, buffer, 1, ctx, leaf_addr); + } + } + + /* Do the final thash to generate the public keys */ + thash(dest, pk_buffer, SPX_WOTS_LEN, ctx, pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_clean/wotsx1.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_clean/wotsx1.h new file mode 100644 index 0000000000..e617929f96 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_clean/wotsx1.h @@ -0,0 +1,39 @@ +#ifndef WOTSX1_H_ +#define WOTSX1_H_ + +#include + +#include "context.h" +#include "params.h" + +/* + * This is here to provide an interface to the internal wots_gen_leafx1 + * routine. While this routine is not referenced in the package outside of + * wots.c, it is called from the stand-alone benchmark code to characterize + * the performance + */ +struct leaf_info_x1 { + unsigned char *wots_sig; + uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ + uint32_t *wots_steps; + uint32_t leaf_addr[8]; + uint32_t pk_addr[8]; +}; + +/* Macro to set the leaf_info to something 'benign', that is, it would */ +/* run with the same time as it does during the real signing process */ +/* Used only by the benchmark code */ +#define INITIALIZE_LEAF_INFO_X1(info, addr, step_buffer) { \ + (info).wots_sig = 0; \ + (info).wots_sign_leaf = ~0; \ + (info).wots_steps = step_buffer; \ + memcpy( &(info).leaf_addr[0], (addr), 32 ); \ + memcpy( &(info).pk_addr[0], (addr), 32 ); \ + } + +#define wots_gen_leafx1 SPX_NAMESPACE(wots_gen_leafx1) +void wots_gen_leafx1(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info); + +#endif /* WOTSX1_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/LICENSE b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/LICENSE new file mode 100644 index 0000000000..670154e353 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/LICENSE @@ -0,0 +1,116 @@ +CC0 1.0 Universal + +Statement of Purpose + +The laws of most jurisdictions throughout the world automatically confer +exclusive Copyright and Related Rights (defined below) upon the creator and +subsequent owner(s) (each and all, an "owner") of an original work of +authorship and/or a database (each, a "Work"). + +Certain owners wish to permanently relinquish those rights to a Work for the +purpose of contributing to a commons of creative, cultural and scientific +works ("Commons") that the public can reliably and without fear of later +claims of infringement build upon, modify, incorporate in other works, reuse +and redistribute as freely as possible in any form whatsoever and for any +purposes, including without limitation commercial purposes. These owners may +contribute to the Commons to promote the ideal of a free culture and the +further production of creative, cultural and scientific works, or to gain +reputation or greater distribution for their Work in part through the use and +efforts of others. + +For these and/or other purposes and motivations, and without any expectation +of additional consideration or compensation, the person associating CC0 with a +Work (the "Affirmer"), to the extent that he or she is an owner of Copyright +and Related Rights in the Work, voluntarily elects to apply CC0 to the Work +and publicly distribute the Work under its terms, with knowledge of his or her +Copyright and Related Rights in the Work and the meaning and intended legal +effect of CC0 on those rights. + +1. Copyright and Related Rights. A Work made available under CC0 may be +protected by copyright and related or neighboring rights ("Copyright and +Related Rights"). Copyright and Related Rights include, but are not limited +to, the following: + + i. the right to reproduce, adapt, distribute, perform, display, communicate, + and translate a Work; + + ii. moral rights retained by the original author(s) and/or performer(s); + + iii. publicity and privacy rights pertaining to a person's image or likeness + depicted in a Work; + + iv. rights protecting against unfair competition in regards to a Work, + subject to the limitations in paragraph 4(a), below; + + v. rights protecting the extraction, dissemination, use and reuse of data in + a Work; + + vi. database rights (such as those arising under Directive 96/9/EC of the + European Parliament and of the Council of 11 March 1996 on the legal + protection of databases, and under any national implementation thereof, + including any amended or successor version of such directive); and + + vii. other similar, equivalent or corresponding rights throughout the world + based on applicable law or treaty, and any national implementations thereof. + +2. Waiver. To the greatest extent permitted by, but not in contravention of, +applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and +unconditionally waives, abandons, and surrenders all of Affirmer's Copyright +and Related Rights and associated claims and causes of action, whether now +known or unknown (including existing as well as future claims and causes of +action), in the Work (i) in all territories worldwide, (ii) for the maximum +duration provided by applicable law or treaty (including future time +extensions), (iii) in any current or future medium and for any number of +copies, and (iv) for any purpose whatsoever, including without limitation +commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes +the Waiver for the benefit of each member of the public at large and to the +detriment of Affirmer's heirs and successors, fully intending that such Waiver +shall not be subject to revocation, rescission, cancellation, termination, or +any other legal or equitable action to disrupt the quiet enjoyment of the Work +by the public as contemplated by Affirmer's express Statement of Purpose. + +3. Public License Fallback. Should any part of the Waiver for any reason be +judged legally invalid or ineffective under applicable law, then the Waiver +shall be preserved to the maximum extent permitted taking into account +Affirmer's express Statement of Purpose. In addition, to the extent the Waiver +is so judged Affirmer hereby grants to each affected person a royalty-free, +non transferable, non sublicensable, non exclusive, irrevocable and +unconditional license to exercise Affirmer's Copyright and Related Rights in +the Work (i) in all territories worldwide, (ii) for the maximum duration +provided by applicable law or treaty (including future time extensions), (iii) +in any current or future medium and for any number of copies, and (iv) for any +purpose whatsoever, including without limitation commercial, advertising or +promotional purposes (the "License"). The License shall be deemed effective as +of the date CC0 was applied by Affirmer to the Work. Should any part of the +License for any reason be judged legally invalid or ineffective under +applicable law, such partial invalidity or ineffectiveness shall not +invalidate the remainder of the License, and in such case Affirmer hereby +affirms that he or she will not (i) exercise any of his or her remaining +Copyright and Related Rights in the Work or (ii) assert any associated claims +and causes of action with respect to the Work, in either case contrary to +Affirmer's express Statement of Purpose. + +4. Limitations and Disclaimers. + + a. No trademark or patent rights held by Affirmer are waived, abandoned, + surrendered, licensed or otherwise affected by this document. + + b. Affirmer offers the Work as-is and makes no representations or warranties + of any kind concerning the Work, express, implied, statutory or otherwise, + including without limitation warranties of title, merchantability, fitness + for a particular purpose, non infringement, or the absence of latent or + other defects, accuracy, or the present or absence of errors, whether or not + discoverable, all to the greatest extent permissible under applicable law. + + c. Affirmer disclaims responsibility for clearing rights of other persons + that may apply to the Work or any use thereof, including without limitation + any person's Copyright and Related Rights in the Work. Further, Affirmer + disclaims responsibility for obtaining any necessary consents, permissions + or other rights required for any use of the Work. + + d. Affirmer understands and acknowledges that Creative Commons is not a + party to this document and has no duty or obligation with respect to this + CC0 or use of the Work. + +For more information, please see + diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/address.c b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/address.c new file mode 100644 index 0000000000..d49d9f3b6b --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/address.c @@ -0,0 +1,95 @@ +#include +#include + +#include "address.h" +#include "params.h" +#include "utils.h" + +/* + * Specify which level of Merkle tree (the "layer") we're working on + */ +void set_layer_addr(uint32_t addr[8], uint32_t layer) { + ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; +} + +/* + * Specify which Merkle tree within the level (the "tree address") we're working on + */ +void set_tree_addr(uint32_t addr[8], uint64_t tree) { + ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); +} + +/* + * Specify the reason we'll use this address structure for, that is, what + * hash will we compute with it. This is used so that unrelated types of + * hashes don't accidentally get the same address structure. The type will be + * one of the SPX_ADDR_TYPE constants + */ +void set_type(uint32_t addr[8], uint32_t type) { + ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; +} + +/* + * Copy the layer and tree fields of the address structure. This is used + * when we're doing multiple types of hashes within the same Merkle tree + */ +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); +} + +/* These functions are used for OTS addresses. */ + +/* + * Specify which Merkle leaf we're working on; that is, which OTS keypair + * we're talking about. + */ +void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { + /* We have > 256 OTS at the bottom of the Merkle tree; to specify */ + /* which one, we'd need to express it in two bytes */ + ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR2] = (unsigned char)(keypair >> 8); + ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; +} + +/* + * Copy the layer, tree and keypair fields of the address structure. This is + * used when we're doing multiple things within the same OTS keypair + */ +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); + ((unsigned char *)out)[SPX_OFFSET_KP_ADDR2] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR2]; + ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; +} + +/* + * Specify which Merkle chain within the OTS we're working with + * (the chain address) + */ +void set_chain_addr(uint32_t addr[8], uint32_t chain) { + ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; +} + +/* + * Specify where in the Merkle chain we are +* (the hash address) + */ +void set_hash_addr(uint32_t addr[8], uint32_t hash) { + ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; +} + +/* These functions are used for all hash tree addresses (including FORS). */ + +/* + * Specify the height of the node in the Merkle/FORS tree we are in + * (the tree height) + */ +void set_tree_height(uint32_t addr[8], uint32_t tree_height) { + ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; +} + +/* + * Specify the distance from the left edge of the node in the Merkle/FORS tree + * (the tree index) + */ +void set_tree_index(uint32_t addr[8], uint32_t tree_index) { + u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/address.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/address.h new file mode 100644 index 0000000000..24a84eb40c --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/address.h @@ -0,0 +1,52 @@ +#ifndef SPX_ADDRESS_H +#define SPX_ADDRESS_H + +#include + +#include "params.h" + +/* The hash types that are passed to set_type */ +#define SPX_ADDR_TYPE_WOTS 0 +#define SPX_ADDR_TYPE_WOTSPK 1 +#define SPX_ADDR_TYPE_HASHTREE 2 +#define SPX_ADDR_TYPE_FORSTREE 3 +#define SPX_ADDR_TYPE_FORSPK 4 +#define SPX_ADDR_TYPE_WOTSPRF 5 +#define SPX_ADDR_TYPE_FORSPRF 6 + +#define set_layer_addr SPX_NAMESPACE(set_layer_addr) +void set_layer_addr(uint32_t addr[8], uint32_t layer); + +#define set_tree_addr SPX_NAMESPACE(set_tree_addr) +void set_tree_addr(uint32_t addr[8], uint64_t tree); + +#define set_type SPX_NAMESPACE(set_type) +void set_type(uint32_t addr[8], uint32_t type); + +/* Copies the layer and tree part of one address into the other */ +#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); + +/* These functions are used for WOTS and FORS addresses. */ + +#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) +void set_keypair_addr(uint32_t addr[8], uint32_t keypair); + +#define set_chain_addr SPX_NAMESPACE(set_chain_addr) +void set_chain_addr(uint32_t addr[8], uint32_t chain); + +#define set_hash_addr SPX_NAMESPACE(set_hash_addr) +void set_hash_addr(uint32_t addr[8], uint32_t hash); + +#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); + +/* These functions are used for all hash tree addresses (including FORS). */ + +#define set_tree_height SPX_NAMESPACE(set_tree_height) +void set_tree_height(uint32_t addr[8], uint32_t tree_height); + +#define set_tree_index SPX_NAMESPACE(set_tree_index) +void set_tree_index(uint32_t addr[8], uint32_t tree_index); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/api.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/api.h new file mode 100644 index 0000000000..dcdc028fb5 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/api.h @@ -0,0 +1,77 @@ +#ifndef PQCLEAN_SPHINCSSHAKE128SROBUST_AARCH64_API_H +#define PQCLEAN_SPHINCSSHAKE128SROBUST_AARCH64_API_H + +#include +#include + +#define PQCLEAN_SPHINCSSHAKE128SROBUST_AARCH64_CRYPTO_ALGNAME "SPHINCS+-shake-128s-robust" + +#define PQCLEAN_SPHINCSSHAKE128SROBUST_AARCH64_CRYPTO_SECRETKEYBYTES 64 +#define PQCLEAN_SPHINCSSHAKE128SROBUST_AARCH64_CRYPTO_PUBLICKEYBYTES 32 +#define PQCLEAN_SPHINCSSHAKE128SROBUST_AARCH64_CRYPTO_BYTES 7856 + +#define PQCLEAN_SPHINCSSHAKE128SROBUST_AARCH64_CRYPTO_SEEDBYTES 48 + +/* + * Returns the length of a secret key, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE128SROBUST_AARCH64_crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE128SROBUST_AARCH64_crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE128SROBUST_AARCH64_crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE128SROBUST_AARCH64_crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +int PQCLEAN_SPHINCSSHAKE128SROBUST_AARCH64_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +int PQCLEAN_SPHINCSSHAKE128SROBUST_AARCH64_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +int PQCLEAN_SPHINCSSHAKE128SROBUST_AARCH64_crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +int PQCLEAN_SPHINCSSHAKE128SROBUST_AARCH64_crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, + const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +int PQCLEAN_SPHINCSSHAKE128SROBUST_AARCH64_crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +int PQCLEAN_SPHINCSSHAKE128SROBUST_AARCH64_crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/context.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/context.h new file mode 100644 index 0000000000..6e0a33f3b7 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/context.h @@ -0,0 +1,19 @@ +#ifndef SPX_CONTEXT_H +#define SPX_CONTEXT_H + +#include + +#include "params.h" + +typedef struct { + uint8_t pub_seed[SPX_N]; + uint8_t sk_seed[SPX_N]; +} spx_ctx; + +#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) +void initialize_hash_function(spx_ctx *ctx); + +#define free_hash_function SPX_NAMESPACE(free_hash_function) +void free_hash_function(spx_ctx *ctx); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/context_shake.c b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/context_shake.c new file mode 100644 index 0000000000..9614a103d3 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/context_shake.c @@ -0,0 +1,12 @@ +#include "context.h" + +/* For SHAKE256, there is no immediate reason to initialize at the start, + so this function is an empty operation. */ +void initialize_hash_function(spx_ctx *ctx) { + (void)ctx; /* Suppress an 'unused parameter' warning. */ +} + +// in case the hash function api is heap-based. +void free_hash_function(spx_ctx *ctx) { + (void)ctx; +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/f1600x2.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/f1600x2.h new file mode 100644 index 0000000000..70d1af9f14 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/f1600x2.h @@ -0,0 +1,11 @@ +#ifndef SPX_F1600X2_H +#define SPX_F1600X2_H + +#include + +extern uint64_t f1600_RC[24]; +extern void _f1600x2(uint64_t *a, uint64_t *rc); + +#define f1600x2(s) do {_f1600x2((s), f1600_RC);} while(0) + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/f1600x2.s b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/f1600x2.s new file mode 100644 index 0000000000..640ed791ed --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/f1600x2.s @@ -0,0 +1,143 @@ +# From https://github.com/bwesterb/armed-keccak + +.macro round + # Execute theta, but without xoring into the state yet. + # Compute parities p[i] = a[i] ^ a[5+i] ^ ... ^ a[20+i]. + eor3.16b v25, v0, v5, v10 + eor3.16b v26, v1, v6, v11 + eor3.16b v27, v2, v7, v12 + eor3.16b v28, v3, v8, v13 + eor3.16b v29, v4, v9, v14 + + eor3.16b v25, v25, v15, v20 + eor3.16b v26, v26, v16, v21 + eor3.16b v27, v27, v17, v22 + eor3.16b v28, v28, v18, v23 + eor3.16b v29, v29, v19, v24 + + # d[0] = rotl(p[1], 1) ^ p[4] + rax1.2d v30, v29, v26 + # d[3] = rotl(p[4], 1) ^ p[2] + rax1.2d v29, v27, v29 + # d[1] = rotl(p[2], 1) ^ p[0] + rax1.2d v27, v25, v27 + # d[4] = rotl(p[0], 1) ^ p[3] + rax1.2d v25, v28, v25 + # d[2] = rotl(p[3], 1) ^ p[1] + rax1.2d v28, v26, v28 + + # Xor parities from step theta into the state at the same time + # as executing rho and pi. + eor.16b v0, v0, v30 + mov.16b v31, v1 + xar.2d v1, v6, v27, 20 + xar.2d v6, v9, v25, 44 + xar.2d v9, v22, v28, 3 + xar.2d v22, v14, v25, 25 + xar.2d v14, v20, v30, 46 + xar.2d v20, v2, v28, 2 + xar.2d v2, v12, v28, 21 + xar.2d v12, v13, v29, 39 + xar.2d v13, v19, v25, 56 + xar.2d v19, v23, v29, 8 + xar.2d v23, v15, v30, 23 + xar.2d v15, v4, v25, 37 + xar.2d v4, v24, v25, 50 + xar.2d v24, v21, v27, 62 + xar.2d v21, v8, v29, 9 + xar.2d v8, v16, v27, 19 + xar.2d v16, v5, v30, 28 + xar.2d v5, v3, v29, 36 + xar.2d v3, v18, v29, 43 + xar.2d v18, v17, v28, 49 + xar.2d v17, v11, v27, 54 + xar.2d v11, v7, v28, 58 + xar.2d v7, v10, v30, 61 + xar.2d v10, v31, v27, 63 + + # Chi + bcax.16b v25, v0, v2, v1 + bcax.16b v26, v1, v3, v2 + bcax.16b v2, v2, v4, v3 + bcax.16b v3, v3, v0, v4 + bcax.16b v4, v4, v1, v0 + mov.16b v0, v25 + mov.16b v1, v26 + + bcax.16b v25, v5, v7, v6 + bcax.16b v26, v6, v8, v7 + bcax.16b v7, v7, v9, v8 + bcax.16b v8, v8, v5, v9 + bcax.16b v9, v9, v6, v5 + mov.16b v5, v25 + mov.16b v6, v26 + + bcax.16b v25, v10, v12, v11 + bcax.16b v26, v11, v13, v12 + bcax.16b v12, v12, v14, v13 + bcax.16b v13, v13, v10, v14 + bcax.16b v14, v14, v11, v10 + mov.16b v10, v25 + mov.16b v11, v26 + + bcax.16b v25, v15, v17, v16 + bcax.16b v26, v16, v18, v17 + bcax.16b v17, v17, v19, v18 + bcax.16b v18, v18, v15, v19 + bcax.16b v19, v19, v16, v15 + mov.16b v15, v25 + mov.16b v16, v26 + + bcax.16b v25, v20, v22, v21 + bcax.16b v26, v21, v23, v22 + bcax.16b v22, v22, v24, v23 + bcax.16b v23, v23, v20, v24 + bcax.16b v24, v24, v21, v20 + mov.16b v20, v25 + mov.16b v21, v26 + + # iota + ld1r {v25.2d}, [x1], #8 + eor.16b v0, v0, v25 +.endm + +.align 4 +.global __f1600x2 +__f1600x2: + stp d8, d9, [sp,#-16]! + stp d10, d11, [sp,#-16]! + stp d12, d13, [sp,#-16]! + stp d14, d15, [sp,#-16]! + + mov x2, x0 + mov x3, #24 + + ld1.2d {v0, v1, v2, v3}, [x0], #64 + ld1.2d {v4, v5, v6, v7}, [x0], #64 + ld1.2d {v8, v9, v10, v11}, [x0], #64 + ld1.2d {v12, v13, v14, v15}, [x0], #64 + ld1.2d {v16, v17, v18, v19}, [x0], #64 + ld1.2d {v20, v21, v22, v23}, [x0], #64 + ld1.2d {v24}, [x0] + +loop: + round + + subs x3, x3, #1 + cbnz x3, loop + + mov x0, x2 + st1.2d {v0, v1, v2, v3}, [x0], #64 + st1.2d {v4, v5, v6, v7}, [x0], #64 + st1.2d {v8, v9, v10, v11}, [x0], #64 + st1.2d {v12, v13, v14, v15}, [x0], #64 + st1.2d {v16, v17, v18, v19}, [x0], #64 + st1.2d {v20, v21, v22, v23}, [x0], #64 + st1.2d {v24}, [x0] + + ldp d14, d15, [sp], #16 + ldp d12, d13, [sp], #16 + ldp d10, d11, [sp], #16 + ldp d8, d9, [sp], #16 + + ret lr diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/f1600x2_const.c b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/f1600x2_const.c new file mode 100644 index 0000000000..e49c0ba149 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/f1600x2_const.c @@ -0,0 +1,30 @@ +#include "f1600x2.h" + +uint64_t f1600_RC[24] = { + 0x0000000000000001, + 0x0000000000008082, + 0x800000000000808A, + 0x8000000080008000, + 0x000000000000808B, + 0x0000000080000001, + 0x8000000080008081, + 0x8000000000008009, + 0x000000000000008A, + 0x0000000000000088, + 0x0000000080008009, + 0x000000008000000A, + 0x000000008000808B, + 0x800000000000008B, + 0x8000000000008089, + 0x8000000000008003, + 0x8000000000008002, + 0x8000000000000080, + 0x000000000000800A, + 0x800000008000000A, + 0x8000000080008081, + 0x8000000000008080, + 0x0000000080000001, + 0x8000000080008008, +}; + + diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/fips202x2.c b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/fips202x2.c new file mode 100644 index 0000000000..4718c343bc --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/fips202x2.c @@ -0,0 +1,148 @@ +#include +#include + +#include "fips202x2.h" +#include "f1600x2.h" +#include "fips202.h" + +uint64_t load64(const unsigned char *x) { + unsigned long long r = 0, i; + + for (i = 0; i < 8; ++i) { + r |= (unsigned long long)x[i] << 8 * i; + } + return r; +} + +void store64(uint8_t *x, uint64_t u) { + unsigned int i; + + for (i = 0; i < 8; ++i) { + x[i] = (uint8_t)u; + u >>= 8; + } +} + +static void keccak_absorb2x(uint64_t *s, + unsigned int r, + const unsigned char *m0, + const unsigned char *m1, + unsigned long long int mlen, + unsigned char p) { + unsigned long long i; + unsigned char t0[200]; + unsigned char t1[200]; + + while (mlen >= r) { + for (i = 0; i < r / 8; ++i) { + s[2 * i + 0] ^= load64(m0 + 8 * i); + s[2 * i + 1] ^= load64(m1 + 8 * i); + } + + f1600x2(s); + mlen -= r; + m0 += r; + m1 += r; + } + + for (i = 0; i < r; ++i) { + t0[i] = 0; + t1[i] = 0; + } + for (i = 0; i < mlen; ++i) { + t0[i] = m0[i]; + t1[i] = m1[i]; + } + + t0[i] = p; + t1[i] = p; + + t0[r - 1] |= 128; + t1[r - 1] |= 128; + + for (i = 0; i < r / 8; ++i) { + s[2 * i + 0] ^= load64(t0 + 8 * i); + s[2 * i + 1] ^= load64(t1 + 8 * i); + } +} + + +static void keccak_squeezeblocks2x(unsigned char *h0, + unsigned char *h1, + unsigned long long int nblocks, + uint64_t *s, + unsigned int r) { + unsigned int i; + + while (nblocks > 0) { + f1600x2(s); + for (i = 0; i < (r >> 3); i++) { + store64(h0 + 8 * i, s[2 * i + 0]); + store64(h1 + 8 * i, s[2 * i + 1]); + } + h0 += r; + h1 += r; + nblocks--; + } +} + + + +void shake128x2(unsigned char *out0, + unsigned char *out1, + unsigned long long outlen, + unsigned char *in0, + unsigned char *in1, + unsigned long long inlen) { + uint64_t s[50] = {0}; + unsigned char t0[SHAKE128_RATE]; + unsigned char t1[SHAKE128_RATE]; + unsigned int i; + + /* absorb 4 message of identical length in parallel */ + keccak_absorb2x(s, SHAKE128_RATE, in0, in1, inlen, 0x1F); + + /* Squeeze output */ + keccak_squeezeblocks2x(out0, out1, outlen / SHAKE128_RATE, s, SHAKE128_RATE); + + out0 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; + out1 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; + + if (outlen % SHAKE128_RATE) { + keccak_squeezeblocks2x(t0, t1, 1, s, SHAKE128_RATE); + for (i = 0; i < outlen % SHAKE128_RATE; i++) { + out0[i] = t0[i]; + out1[i] = t1[i]; + } + } +} + + +void shake256x2(unsigned char *out0, + unsigned char *out1, + unsigned long long outlen, + unsigned char *in0, + unsigned char *in1, + unsigned long long inlen) { + uint64_t s[50] = {0}; + unsigned char t0[SHAKE256_RATE]; + unsigned char t1[SHAKE256_RATE]; + unsigned int i; + + /* absorb 2 message of identical length in parallel */ + keccak_absorb2x(s, SHAKE256_RATE, in0, in1, inlen, 0x1F); + + /* Squeeze output */ + keccak_squeezeblocks2x(out0, out1, outlen / SHAKE256_RATE, s, SHAKE256_RATE); + + out0 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; + out1 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; + + if (outlen % SHAKE256_RATE) { + keccak_squeezeblocks2x(t0, t1, 1, s, SHAKE256_RATE); + for (i = 0; i < outlen % SHAKE256_RATE; i++) { + out0[i] = t0[i]; + out1[i] = t1[i]; + } + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/fips202x2.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/fips202x2.h new file mode 100644 index 0000000000..7ba58b35d8 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/fips202x2.h @@ -0,0 +1,24 @@ +#ifndef SPX_FIPS202X2_H +#define SPX_FIPS202X2_H + +#include + +uint64_t load64(const unsigned char *x); +void store64(uint8_t *x, uint64_t u); + + +void shake128x2(unsigned char *out0, + unsigned char *out1, + unsigned long long outlen, + unsigned char *in0, + unsigned char *in1, + unsigned long long inlen); + +void shake256x2(unsigned char *out0, + unsigned char *out1, + unsigned long long outlen, + unsigned char *in0, + unsigned char *in1, + unsigned long long inlen); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/fors.c b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/fors.c new file mode 100644 index 0000000000..39193d04e2 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/fors.c @@ -0,0 +1,191 @@ +#include +#include +#include + +#include "fors.h" + +#include "address.h" +#include "hash.h" +#include "hashx2.h" +#include "thash.h" +#include "thashx2.h" +#include "utils.h" +#include "utilsx2.h" + +static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + prf_addr(sk, ctx, fors_leaf_addr); +} + +static void fors_gen_skx2(unsigned char *sk0, + unsigned char *sk1, + const spx_ctx *ctx, + uint32_t fors_leaf_addrx2[2 * 8]) { + prf_addrx2(sk0, sk1, + ctx, fors_leaf_addrx2); +} + +static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, + const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + thash(leaf, sk, 1, ctx, fors_leaf_addr); +} + +static void fors_sk_to_leafx2(unsigned char *leaf0, + unsigned char *leaf1, + const unsigned char *sk0, + const unsigned char *sk1, + const spx_ctx *ctx, + uint32_t fors_leaf_addrx2[2 * 8]) { + thashx2(leaf0, leaf1, + sk0, sk1, + 1, ctx, fors_leaf_addrx2); +} + +struct fors_gen_leaf_info { + uint32_t leaf_addrx[2 * 8]; +}; + +static void fors_gen_leafx2(unsigned char *leaf, + const spx_ctx *ctx, + uint32_t addr_idx, void *info) { + struct fors_gen_leaf_info *fors_info = info; + uint32_t *fors_leaf_addrx2 = fors_info->leaf_addrx; + unsigned int j; + + /* Only set the parts that the caller doesn't set */ + for (j = 0; j < 2; j++) { + set_tree_index(fors_leaf_addrx2 + j * 8, addr_idx + j); + set_type(fors_leaf_addrx2 + j * 8, SPX_ADDR_TYPE_FORSPRF); + } + + fors_gen_skx2(leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + ctx, fors_leaf_addrx2); + + for (j = 0; j < 2; j++) { + set_type(fors_leaf_addrx2 + j * 8, SPX_ADDR_TYPE_FORSTREE); + } + + fors_sk_to_leafx2(leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + ctx, fors_leaf_addrx2); +} + +/** + * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + * Assumes indices has space for SPX_FORS_TREES integers. + */ +static void message_to_indices(uint32_t *indices, const unsigned char *m) { + unsigned int i, j; + unsigned int offset = 0; + + for (i = 0; i < SPX_FORS_TREES; i++) { + indices[i] = 0; + for (j = 0; j < SPX_FORS_HEIGHT; j++) { + indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); + offset++; + } + } +} + +/** + * Signs a message m, deriving the secret key from sk_seed and the FTS address. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + uint32_t fors_tree_addr[2 * 8] = {0}; + struct fors_gen_leaf_info fors_info = {0}; + uint32_t *fors_leaf_addr = fors_info.leaf_addrx; + uint32_t fors_pk_addr[8] = {0}; + uint32_t idx_offset; + unsigned int i; + + for (i = 0; i < 2; i++) { + copy_keypair_addr(fors_tree_addr + 8 * i, fors_addr); + set_type(fors_tree_addr + 8 * i, SPX_ADDR_TYPE_FORSTREE); + copy_keypair_addr(fors_leaf_addr + 8 * i, fors_addr); + } + copy_keypair_addr(fors_pk_addr, fors_addr); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); + + message_to_indices(indices, m); + + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); + + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + + /* Include the secret key part that produces the selected leaf node. */ + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); + fors_gen_sk(sig, ctx, fors_tree_addr); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + sig += SPX_N; + + /* Compute the authentication path for this leaf node. */ + treehashx2(roots + i * SPX_N, sig, ctx, + indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx2, + fors_tree_addr, &fors_info); + + sig += SPX_N * SPX_FORS_HEIGHT; + } + + /* Hash horizontally across all tree roots to derive the public key. */ + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); +} + +/** + * Derives the FORS public key from a signature. + * This can be used for verification by comparing to a known public key, or to + * subsequently verify a signature on the derived public key. The latter is the + * typical use-case when used as an FTS below an OTS in a hypertree. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + unsigned char leaf[SPX_N]; + uint32_t fors_tree_addr[8] = {0}; + uint32_t fors_pk_addr[8] = {0}; + uint32_t idx_offset; + unsigned int i; + + copy_keypair_addr(fors_tree_addr, fors_addr); + copy_keypair_addr(fors_pk_addr, fors_addr); + + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); + + message_to_indices(indices, m); + + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); + + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + + /* Derive the leaf from the included secret key part. */ + fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); + sig += SPX_N; + + /* Derive the corresponding root node of this tree. */ + compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, + sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); + sig += SPX_N * SPX_FORS_HEIGHT; + } + + /* Hash horizontally across all tree roots to derive the public key. */ + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/fors.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/fors.h new file mode 100644 index 0000000000..509140a178 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/fors.h @@ -0,0 +1,32 @@ +#ifndef SPX_FORS_H +#define SPX_FORS_H + +#include + +#include "context.h" +#include "params.h" + +/** + * Signs a message m, deriving the secret key from sk_seed and the FTS address. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +#define fors_sign SPX_NAMESPACE(fors_sign) +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); + +/** + * Derives the FORS public key from a signature. + * This can be used for verification by comparing to a known public key, or to + * subsequently verify a signature on the derived public key. The latter is the + * typical use-case when used as an FTS below an OTS in a hypertree. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/hash.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/hash.h new file mode 100644 index 0000000000..f7c87d4c3c --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/hash.h @@ -0,0 +1,28 @@ +#ifndef SPX_HASH_H +#define SPX_HASH_H + +#include +#include + +#include "context.h" +#include "params.h" + +#define prf_addr SPX_NAMESPACE(prf_addr) +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]); + +#define gen_message_random SPX_NAMESPACE(gen_message_random) +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); + +#define hash_message SPX_NAMESPACE(hash_message) +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); + + + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/hash_shake.c b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/hash_shake.c new file mode 100644 index 0000000000..ff5e7ec918 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/hash_shake.c @@ -0,0 +1,83 @@ +#include +#include + +#include "hash.h" + +#include "address.h" +#include "fips202.h" +#include "params.h" +#include "utils.h" + +/* + * Computes PRF(pk_seed, sk_seed, addr) + */ +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]) { + unsigned char buf[2 * SPX_N + SPX_ADDR_BYTES]; + + memcpy(buf, ctx->pub_seed, SPX_N); + memcpy(buf + SPX_N, addr, SPX_ADDR_BYTES); + memcpy(buf + SPX_N + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); + + shake256(out, SPX_N, buf, 2 * SPX_N + SPX_ADDR_BYTES); +} + +/** + * Computes the message-dependent randomness R, using a secret seed and an + * optional randomization value as well as the message. + */ +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { + (void)ctx; + shake256incctx s_inc; + + shake256_inc_init(&s_inc); + shake256_inc_absorb(&s_inc, sk_prf, SPX_N); + shake256_inc_absorb(&s_inc, optrand, SPX_N); + shake256_inc_absorb(&s_inc, m, mlen); + shake256_inc_finalize(&s_inc); + shake256_inc_squeeze(R, SPX_N, &s_inc); + shake256_inc_ctx_release(&s_inc); +} + +/** + * Computes the message hash using R, the public key, and the message. + * Outputs the message digest and the index of the leaf. The index is split in + * the tree index and the leaf index, for convenient copying to an address. + */ +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { + (void)ctx; +#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) +#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) +#define SPX_LEAF_BITS SPX_TREE_HEIGHT +#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) +#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) + + unsigned char buf[SPX_DGST_BYTES]; + unsigned char *bufp = buf; + shake256incctx s_inc; + + shake256_inc_init(&s_inc); + shake256_inc_absorb(&s_inc, R, SPX_N); + shake256_inc_absorb(&s_inc, pk, SPX_PK_BYTES); + shake256_inc_absorb(&s_inc, m, mlen); + shake256_inc_finalize(&s_inc); + shake256_inc_squeeze(buf, SPX_DGST_BYTES, &s_inc); + shake256_inc_ctx_release(&s_inc); + + memcpy(digest, bufp, SPX_FORS_MSG_BYTES); + bufp += SPX_FORS_MSG_BYTES; + + + *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); + *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); + bufp += SPX_TREE_BYTES; + + *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); + *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/hash_shakex2.c b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/hash_shakex2.c new file mode 100644 index 0000000000..99571916a2 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/hash_shakex2.c @@ -0,0 +1,52 @@ +#include +#include + +#include "hashx2.h" + +#include "address.h" +#include "f1600x2.h" +#include "fips202x2.h" +#include "params.h" + +/* + * 2-way parallel version of prf_addr; takes 2x as much input and output + */ +void prf_addrx2(unsigned char *out0, + unsigned char *out1, + const spx_ctx *ctx, + const uint32_t addrx2[2 * 8]) { + /* As we write and read only a few quadwords, it is more efficient to + * build and extract from the fourway SHAKE256 state by hand. */ + uint64_t state[50] = {0}; + + for (int i = 0; i < SPX_N / 8; i++) { + uint64_t x = load64(ctx->pub_seed + 8 * i); + state[2 * i] = x; + state[2 * i + 1] = x; + } + for (int i = 0; i < 4; i++) { + state[2 * (SPX_N / 8 + i)] = (((uint64_t)addrx2[1 + 2 * i]) << 32) + | (uint64_t)addrx2[2 * i]; + state[2 * (SPX_N / 8 + i) + 1] = (((uint64_t)addrx2[8 + 1 + 2 * i]) << 32) + | (uint64_t)addrx2[8 + 2 * i]; + } + for (int i = 0; i < SPX_N / 8; i++) { + uint64_t x = load64(ctx->sk_seed + 8 * i); + state[2 * (SPX_N / 8 + i + 4)] = x; + state[2 * (SPX_N / 8 + i + 4) + 1] = x; + } + + /* SHAKE domain separator and padding. */ + state[2 * (SPX_N / 4 + 4)] = 0x1f; + state[2 * (SPX_N / 4 + 4) + 1] = 0x1f; + + state[2 * 16] = 0x80ULL << 56; + state[2 * 16 + 1] = 0x80ULL << 56; + + f1600x2(state); + + for (int i = 0; i < SPX_N / 8; i++) { + store64(out0 + 8 * i, state[2 * i]); + store64(out1 + 8 * i, state[2 * i + 1]); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/hashx2.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/hashx2.h new file mode 100644 index 0000000000..99b8873a9b --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/hashx2.h @@ -0,0 +1,14 @@ +#ifndef SPX_HASHX2_H +#define SPX_HASHX2_H + +#include "context.h" +#include "params.h" +#include + +#define prf_addrx2 SPX_NAMESPACE(prf_addrx2) +void prf_addrx2(unsigned char *out0, + unsigned char *out1, + const spx_ctx *ctx, + const uint32_t addrx2[2 * 8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/merkle.c b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/merkle.c new file mode 100644 index 0000000000..c94ee23939 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/merkle.c @@ -0,0 +1,64 @@ +#include +#include + +#include "merkle.h" + +#include "address.h" +#include "params.h" +#include "utils.h" +#include "utilsx2.h" +#include "wots.h" +#include "wotsx2.h" + +/* + * This generates a Merkle signature (WOTS signature followed by the Merkle + * authentication path). + */ +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf) { + unsigned char *auth_path = sig + SPX_WOTS_BYTES; + uint32_t tree_addrx2[2 * 8] = { 0 }; + int j; + struct leaf_info_x2 info = { 0 }; + unsigned steps[ SPX_WOTS_LEN ]; + + info.wots_sig = sig; + chain_lengths(steps, root); + info.wots_steps = steps; + + for (j = 0; j < 2; j++) { + set_type(&tree_addrx2[8 * j], SPX_ADDR_TYPE_HASHTREE); + set_type(&info.leaf_addr[8 * j], SPX_ADDR_TYPE_WOTS); + set_type(&info.pk_addr[8 * j], SPX_ADDR_TYPE_WOTSPK); + copy_subtree_addr(&tree_addrx2[8 * j], tree_addr); + copy_subtree_addr(&info.leaf_addr[8 * j], wots_addr); + copy_subtree_addr(&info.pk_addr[8 * j], wots_addr); + } + + info.wots_sign_leaf = idx_leaf; + + treehashx2(root, auth_path, ctx, + idx_leaf, 0, + SPX_TREE_HEIGHT, + wots_gen_leafx2, + tree_addrx2, &info); +} + +/* Compute root node of the top-most subtree. */ +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { + /* We do not need the auth path in key generation, but it simplifies the + code to have just one treehash routine that computes both root and path + in one function. */ + unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; + uint32_t top_tree_addr[8] = {0}; + uint32_t wots_addr[8] = {0}; + + set_layer_addr(top_tree_addr, SPX_D - 1); + set_layer_addr(wots_addr, SPX_D - 1); + + merkle_sign(auth_path, root, ctx, + wots_addr, top_tree_addr, + ~0 /* ~0 means "don't bother generating an auth path */ ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/merkle.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/merkle.h new file mode 100644 index 0000000000..769cf2e970 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/merkle.h @@ -0,0 +1,21 @@ +#ifndef MERKLE_H_ +#define MERKLE_H_ + +#include + +#include "context.h" +#include "params.h" + +/* Generate a Merkle signature (WOTS signature followed by the Merkle */ +/* authentication path) */ +#define merkle_sign SPX_NAMESPACE(merkle_sign) +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf); + +/* Compute the root node of the top-most subtree. */ +#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); + +#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/nistapi.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/nistapi.h new file mode 100644 index 0000000000..3cb71afad4 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/nistapi.h @@ -0,0 +1,87 @@ +#ifndef SPX_API_H +#define SPX_API_H + +#include +#include + +#include "params.h" + +#define CRYPTO_ALGNAME "SPHINCS+" + +#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES +#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES +#define CRYPTO_BYTES SPX_BYTES +#define CRYPTO_SEEDBYTES (3*SPX_N) + +/* + * Returns the length of a secret key, in bytes + */ +#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) +size_t crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) +size_t crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) +size_t crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) +size_t crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +#define crypto_sign SPX_NAMESPACE(crypto_sign) +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/params.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/params.h new file mode 100644 index 0000000000..7565ba5a9a --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/params.h @@ -0,0 +1,56 @@ +#ifndef SPX_PARAMS_H +#define SPX_PARAMS_H + +#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSSHAKE128SROBUST_AARCH64_##s + +/* Hash output length in bytes. */ +#define SPX_N 16 +/* Height of the hypertree. */ +#define SPX_FULL_HEIGHT 63 +/* Number of subtree layer. */ +#define SPX_D 7 +/* FORS tree dimensions. */ +#define SPX_FORS_HEIGHT 12 +#define SPX_FORS_TREES 14 +/* Winternitz parameter, */ +#define SPX_WOTS_W 16 + +/* The hash function is defined by linking a different hash.c file, as opposed + to setting a #define constant. */ + +/* For clarity */ +#define SPX_ADDR_BYTES 32 + +/* WOTS parameters. */ +#define SPX_WOTS_LOGW 4 + +#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) + +/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ +#define SPX_WOTS_LEN2 3 + +#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) +#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) +#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES + +/* Subtree size. */ +#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) + +//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT +// #error SPX_D should always divide SPX_FULL_HEIGHT +//#endif + +/* FORS parameters. */ +#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) +#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) +#define SPX_FORS_PK_BYTES SPX_N + +/* Resulting SPX sizes. */ +#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ + SPX_FULL_HEIGHT * SPX_N) +#define SPX_PK_BYTES (2 * SPX_N) +#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) + +#include "shake_offsets.h" + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/shake_offsets.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/shake_offsets.h new file mode 100644 index 0000000000..6b28d95d91 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/shake_offsets.h @@ -0,0 +1,21 @@ +#ifndef SHAKE_OFFSETS_H_ +#define SHAKE_OFFSETS_H_ + +/* + * Offsets of various fields in the address structure when we use SHAKE as + * the Sphincs+ hash function + */ + +#define SPX_OFFSET_LAYER 3 /* The byte used to specify the Merkle tree layer */ +#define SPX_OFFSET_TREE 8 /* The start of the 8 byte field used to specify the tree */ +#define SPX_OFFSET_TYPE 19 /* The byte used to specify the hash type (reason) */ +#define SPX_OFFSET_KP_ADDR2 22 /* The high byte used to specify the key pair (which one-time signature) */ +#define SPX_OFFSET_KP_ADDR1 23 /* The low byte used to specify the key pair */ +#define SPX_OFFSET_CHAIN_ADDR 27 /* The byte used to specify the chain address (which Winternitz chain) */ +#define SPX_OFFSET_HASH_ADDR 31 /* The byte used to specify the hash address (where in the Winternitz chain) */ +#define SPX_OFFSET_TREE_HGT 27 /* The byte used to specify the height of this node in the FORS or Merkle tree */ +#define SPX_OFFSET_TREE_INDEX 28 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ + +#define SPX_SHAKE 1 + +#endif /* SHAKE_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/sign.c b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/sign.c new file mode 100644 index 0000000000..9d0c7d1b22 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/sign.c @@ -0,0 +1,286 @@ +#include +#include +#include + +#include "address.h" +#include "context.h" +#include "fors.h" +#include "hash.h" +#include "merkle.h" +#include "nistapi.h" +#include "params.h" +#include "randombytes.h" +#include "thash.h" +#include "utils.h" +#include "wots.h" + +/* + * Returns the length of a secret key, in bytes + */ +size_t crypto_sign_secretkeybytes(void) { + return CRYPTO_SECRETKEYBYTES; +} + +/* + * Returns the length of a public key, in bytes + */ +size_t crypto_sign_publickeybytes(void) { + return CRYPTO_PUBLICKEYBYTES; +} + +/* + * Returns the length of a signature, in bytes + */ +size_t crypto_sign_bytes(void) { + return CRYPTO_BYTES; +} + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +size_t crypto_sign_seedbytes(void) { + return CRYPTO_SEEDBYTES; +} + +/* + * Generates an SPX key pair given a seed of length + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [PUB_SEED || root] + */ +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed) { + spx_ctx ctx; + + /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ + memcpy(sk, seed, CRYPTO_SEEDBYTES); + + memcpy(pk, sk + 2 * SPX_N, SPX_N); + + memcpy(ctx.pub_seed, pk, SPX_N); + memcpy(ctx.sk_seed, sk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + /* Compute root node of the top-most subtree. */ + merkle_gen_root(sk + 3 * SPX_N, &ctx); + + // cleanup + free_hash_function(&ctx); + + memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); + + return 0; +} + +/* + * Generates an SPX key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [PUB_SEED || root] + */ +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { + uint8_t seed[CRYPTO_SEEDBYTES]; + randombytes(seed, CRYPTO_SEEDBYTES); + crypto_sign_seed_keypair(pk, sk, seed); + + return 0; +} + +/** + * Returns an array containing a detached signature. + */ +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk) { + spx_ctx ctx; + + const uint8_t *sk_prf = sk + SPX_N; + const uint8_t *pk = sk + 2 * SPX_N; + + uint8_t optrand[SPX_N]; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t root[SPX_N]; + uint32_t i; + uint64_t tree; + uint32_t idx_leaf; + uint32_t wots_addr[8] = {0}; + uint32_t tree_addr[8] = {0}; + + memcpy(ctx.sk_seed, sk, SPX_N); + memcpy(ctx.pub_seed, pk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + + /* Optionally, signing can be made non-deterministic using optrand. + This can help counter side-channel attacks that would benefit from + getting a large number of traces when the signer uses the same nodes. */ + randombytes(optrand, SPX_N); + /* Compute the digest randomization value. */ + gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); + + /* Derive the message digest and leaf index from R, PK and M. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; + + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); + + /* Sign the message hash using FORS. */ + fors_sign(sig, root, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); + sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; + + /* Update the indices for the next layer. */ + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; + } + + free_hash_function(&ctx); + + *siglen = SPX_BYTES; + + return 0; +} + +/** + * Verifies a detached signature and message under a given public key. + */ +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk) { + spx_ctx ctx; + const uint8_t *pub_root = pk + SPX_N; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t wots_pk[SPX_WOTS_BYTES]; + uint8_t root[SPX_N]; + uint8_t leaf[SPX_N]; + unsigned int i; + uint64_t tree; + uint32_t idx_leaf; + uint32_t wots_addr[8] = {0}; + uint32_t tree_addr[8] = {0}; + uint32_t wots_pk_addr[8] = {0}; + + if (siglen != SPX_BYTES) { + return -1; + } + + memcpy(ctx.pub_seed, pk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); + + /* Derive the message digest and leaf index from R || PK || M. */ + /* The additional SPX_N is a result of the hash domain separator. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; + + /* Layer correctly defaults to 0, so no need to set_layer_addr */ + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); + + fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + /* For each subtree.. */ + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + copy_keypair_addr(wots_pk_addr, wots_addr); + + /* The WOTS public key is only correct if the signature was correct. */ + /* Initially, root is the FORS pk, but on subsequent iterations it is + the root of the subtree below the currently processed subtree. */ + wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); + sig += SPX_WOTS_BYTES; + + /* Compute the leaf node using the WOTS public key. */ + thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); + + /* Compute the root node of this subtree. */ + compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, + &ctx, tree_addr); + sig += SPX_TREE_HEIGHT * SPX_N; + + /* Update the indices for the next layer. */ + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; + } + + // cleanup + free_hash_function(&ctx); + + /* Check if the root node equals the root node in the public key. */ + if (memcmp(root, pub_root, SPX_N) != 0) { + return -1; + } + + return 0; +} + + +/** + * Returns an array containing the signature followed by the message. + */ +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk) { + size_t siglen; + + crypto_sign_signature(sm, &siglen, m, mlen, sk); + + memmove(sm + SPX_BYTES, m, mlen); + *smlen = siglen + mlen; + + return 0; +} + +/** + * Verifies a given signature-message pair under a given public key. + */ +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk) { + /* The API caller does not necessarily know what size a signature should be + but SPHINCS+ signatures are always exactly SPX_BYTES. */ + if (smlen < SPX_BYTES) { + memset(m, 0, smlen); + *mlen = 0; + return -1; + } + + *mlen = smlen - SPX_BYTES; + + if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { + memset(m, 0, smlen); + *mlen = 0; + return -1; + } + + /* If verification was successful, move the message to the right place. */ + memmove(m, sm + SPX_BYTES, *mlen); + + return 0; +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/thash.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/thash.h new file mode 100644 index 0000000000..8687ccfb4d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/thash.h @@ -0,0 +1,13 @@ +#ifndef SPX_THASH_H +#define SPX_THASH_H + +#include "context.h" +#include "params.h" + +#include + +#define thash SPX_NAMESPACE(thash) +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/thash_shake_robustx2.c b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/thash_shake_robustx2.c new file mode 100644 index 0000000000..454fc0f4e2 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/thash_shake_robustx2.c @@ -0,0 +1,112 @@ +#include +#include + +#include "thash.h" +#include "thashx2.h" + +#include "address.h" +#include "params.h" +#include "utils.h" + +#include "f1600x2.h" +#include "fips202x2.h" + + +void thash(unsigned char *out, + const unsigned char *in, + unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]) { + uint32_t addrx2 [2 * 8] = { + addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], addr[6], addr[7], + addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], addr[6], addr[7] + }; + thashx2(out, out, in, in, inblocks, ctx, addrx2); +} + +/** + * 2-way parallel version of thash; takes 2x as much input and output + */ +void thashx2(unsigned char *out0, + unsigned char *out1, + const unsigned char *in0, + const unsigned char *in1, + unsigned int inblocks, + const spx_ctx *ctx, uint32_t addrx2[2 * 8]) { + if (inblocks == 1 || inblocks == 2) { + /* As we write and read only a few quadwords, it is more efficient to + * build and extract from the twoway SHAKE256 state by hand. */ + uint64_t state[50] = {0}; + uint64_t state2[50]; + + for (int i = 0; i < SPX_N / 8; i++) { + uint64_t x = load64(ctx->pub_seed + 8 * i); + state[2 * i] = x; + state[2 * i + 1] = x; + } + for (int i = 0; i < 4; i++) { + state[2 * (SPX_N / 8 + i)] = (((uint64_t)addrx2[1 + 2 * i]) << 32) + | (uint64_t)addrx2[2 * i]; + state[2 * (SPX_N / 8 + i) + 1] = (((uint64_t)addrx2[8 + 1 + 2 * i]) << 32) + | (uint64_t)addrx2[8 + 2 * i]; + } + + /* Domain separator and padding. */ + state[2 * 16] = 0x80ULL << 56; + state[2 * 16 + 1] = 0x80ULL << 56; + + state[2 * ((SPX_N / 8) + 4)] ^= 0x1f; + state[2 * ((SPX_N / 8) + 4) + 1] ^= 0x1f; + + /* We will permutate state2 with f1600x2 to compute the bitmask, + * but first we'll copy it to state2 which will be used to compute + * the final output, as its input is almost identical. */ + memcpy(state2, state, 400); + + f1600x2(state); + + /* By copying from state, state2 already contains the pub_seed + * and address. We just need to copy in the input blocks xorred with + * the bitmask we just computed. */ + for (unsigned int i = 0; i < (SPX_N / 8) * inblocks; i++) { + state2[2 * (SPX_N / 8 + 4 + i)] = state[2 * i] ^ load64(in0 + 8 * i); + state2[2 * (SPX_N / 8 + 4 + i) + 1] = state[2 * i + 1] ^ load64(in1 + 8 * i); + } + + /* Domain separator and start of padding. Note that the quadwords + * around are already zeroed for state from which we copied. + * We do a XOR instead of a set as this might be the 16th quadword + * when N=32 and inblocks=2, which already contains the end + * of the padding. */ + state2[2 * ((SPX_N / 8) * (1 + inblocks) + 4)] ^= 0x1f; + state2[2 * ((SPX_N / 8) * (1 + inblocks) + 4) + 1] ^= 0x1f; + + f1600x2(state2); + + for (int i = 0; i < SPX_N / 8; i++) { + store64(out0 + 8 * i, state2[2 * i]); + store64(out1 + 8 * i, state2[2 * i + 1]); + } + } else { + PQCLEAN_VLA(unsigned char, buf0, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, buf1, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, bitmask0, inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, bitmask1, inblocks * SPX_N); + unsigned int i; + + memcpy(buf0, ctx->pub_seed, SPX_N); + memcpy(buf1, ctx->pub_seed, SPX_N); + memcpy(buf0 + SPX_N, addrx2 + 0 * 8, SPX_ADDR_BYTES); + memcpy(buf1 + SPX_N, addrx2 + 1 * 8, SPX_ADDR_BYTES); + + shake256x2(bitmask0, bitmask1, inblocks * SPX_N, + buf0, buf1, SPX_N + SPX_ADDR_BYTES); + + for (i = 0; i < inblocks * SPX_N; i++) { + buf0[SPX_N + SPX_ADDR_BYTES + i] = in0[i] ^ bitmask0[i]; + buf1[SPX_N + SPX_ADDR_BYTES + i] = in1[i] ^ bitmask1[i]; + } + + shake256x2(out0, out1, SPX_N, + buf0, buf1, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/thashx2.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/thashx2.h new file mode 100644 index 0000000000..040375e618 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/thashx2.h @@ -0,0 +1,16 @@ +#ifndef SPX_THASHX2_H +#define SPX_THASHX2_H + +#include "context.h" +#include "params.h" +#include + +#define thashx2 SPX_NAMESPACE(thashx2) +void thashx2(unsigned char *out0, + unsigned char *out1, + const unsigned char *in0, + const unsigned char *in1, + unsigned int inblocks, + const spx_ctx *ctx, uint32_t addrx2[2 * 8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/utils.c b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/utils.c new file mode 100644 index 0000000000..177b541fb9 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/utils.c @@ -0,0 +1,148 @@ +#include + +#include "utils.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "thash.h" + +/** + * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. + */ +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in) { + int i; + + /* Iterate over out in decreasing order, for big-endianness. */ + for (i = (signed int)outlen - 1; i >= 0; i--) { + out[i] = in & 0xff; + in = in >> 8; + } +} + +void u32_to_bytes(unsigned char *out, uint32_t in) { + out[0] = (unsigned char)(in >> 24); + out[1] = (unsigned char)(in >> 16); + out[2] = (unsigned char)(in >> 8); + out[3] = (unsigned char)in; +} + +/** + * Converts the inlen bytes in 'in' from big-endian byte order to an integer. + */ +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { + unsigned long long retval = 0; + unsigned int i; + + for (i = 0; i < inlen; i++) { + retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); + } + return retval; +} + +/** + * Computes a root node given a leaf and an auth path. + * Expects address to be complete other than the tree_height and tree_index. + */ +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]) { + uint32_t i; + unsigned char buffer[2 * SPX_N]; + + /* If leaf_idx is odd (last bit = 1), current path element is a right child + and auth_path has to go left. Otherwise it is the other way around. */ + if (leaf_idx & 1) { + memcpy(buffer + SPX_N, leaf, SPX_N); + memcpy(buffer, auth_path, SPX_N); + } else { + memcpy(buffer, leaf, SPX_N); + memcpy(buffer + SPX_N, auth_path, SPX_N); + } + auth_path += SPX_N; + + for (i = 0; i < tree_height - 1; i++) { + leaf_idx >>= 1; + idx_offset >>= 1; + /* Set the address of the node we're creating. */ + set_tree_height(addr, i + 1); + set_tree_index(addr, leaf_idx + idx_offset); + + /* Pick the right or left neighbor, depending on parity of the node. */ + if (leaf_idx & 1) { + thash(buffer + SPX_N, buffer, 2, ctx, addr); + memcpy(buffer, auth_path, SPX_N); + } else { + thash(buffer, buffer, 2, ctx, addr); + memcpy(buffer + SPX_N, auth_path, SPX_N); + } + auth_path += SPX_N; + } + + /* The last iteration is exceptional; we do not copy an auth_path node. */ + leaf_idx >>= 1; + idx_offset >>= 1; + set_tree_height(addr, tree_height); + set_tree_index(addr, leaf_idx + idx_offset); + thash(root, buffer, 2, ctx, addr); +} + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx * /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]) { + PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); + PQCLEAN_VLA(unsigned int, heights, tree_height + 1); + unsigned int offset = 0; + uint32_t idx; + uint32_t tree_idx; + + for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { + /* Add the next leaf node to the stack. */ + gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); + offset++; + heights[offset - 1] = 0; + + /* If this is a node we need for the auth path.. */ + if ((leaf_idx ^ 0x1) == idx) { + memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); + } + + /* While the top-most nodes are of equal height.. */ + while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { + /* Compute index of the new node, in the next layer. */ + tree_idx = (idx >> (heights[offset - 1] + 1)); + + /* Set the address of the node we're creating. */ + set_tree_height(tree_addr, heights[offset - 1] + 1); + set_tree_index(tree_addr, + tree_idx + (idx_offset >> (heights[offset - 1] + 1))); + /* Hash the top-most nodes from the stack together. */ + thash(stack + (offset - 2)*SPX_N, + stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); + offset--; + /* Note that the top-most node is now one layer higher. */ + heights[offset - 1]++; + + /* If this is a node we need for the auth path.. */ + if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { + memcpy(auth_path + heights[offset - 1]*SPX_N, + stack + (offset - 1)*SPX_N, SPX_N); + } + } + } + memcpy(root, stack, SPX_N); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/utils.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/utils.h new file mode 100644 index 0000000000..64f5d5a53a --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/utils.h @@ -0,0 +1,58 @@ +#ifndef SPX_UTILS_H +#define SPX_UTILS_H + +#include + +#include "compat.h" +#include "context.h" +#include "params.h" + + +/* To support MSVC use alloca() instead of VLAs. See #20. */ + + +/** + * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. + */ +#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in); +#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) +void u32_to_bytes(unsigned char *out, uint32_t in); + +/** + * Converts the inlen bytes in 'in' from big-endian byte order to an integer. + */ +#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); + +/** + * Computes a root node given a leaf and an auth path. + * Expects address to be complete other than the tree_height and tree_index. + */ +#define compute_root SPX_NAMESPACE(compute_root) +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]); + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +#define treehash SPX_NAMESPACE(treehash) +void treehash(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx *ctx /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]); + + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/utilsx2.c b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/utilsx2.c new file mode 100644 index 0000000000..8736474e4f --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/utilsx2.c @@ -0,0 +1,130 @@ +#include + +#include "utilsx2.h" + +#include "address.h" +#include "params.h" +#include "thashx2.h" +#include "utils.h" + +/* + * Generate the entire Merkle tree, computing the authentication path for leaf_idx, + * and the resulting root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) + * + * This expects tree_addrx2 to be initialized to 2 parallel addr structures for + * the Merkle tree nodes + * + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + * + * This works by using the standard Merkle tree building algorithm, except + * that each 'node' tracked is actually 2 consecutive nodes in the real tree. + * When we combine two logical nodes AB and WX, we perform the H + * operation on adjacent real nodes, forming the parent logical node + * (AB)(WX) + * + * When we get to the top level of the real tree (where there is only + * one logical node), we continue this operation one more time; the right + * most real node will by the actual root (and the other node will be + * garbage). We follow the same thashx2 logic so that the 'extract + * authentication path components' part of the loop is still executed (and + * to simplify the code somewhat) + */ +void treehashx2(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, + uint32_t tree_height, + void (*gen_leafx2)( + unsigned char * /* Where to write the leaves */, + const spx_ctx *, + uint32_t idx, void *info), + uint32_t tree_addrx2[2 * 8], + void *info) { + /* This is where we keep the intermediate nodes */ + unsigned char stackx2[tree_height * 2 * SPX_N]; + uint32_t left_adj = 0, prev_left_adj = 0; /* When we're doing the top */ + /* level, the left-most part of the tree isn't at the beginning */ + /* of current[]. These give the offset of the actual start */ + + uint32_t idx; + uint32_t max_idx = (1 << (tree_height - 1)) - 1; + for (idx = 0;; idx++) { + unsigned char current[2 * SPX_N]; /* Current logical node */ + gen_leafx2( current, ctx, 2 * idx + idx_offset, + info ); + + /* Now combine the freshly generated right node with previously */ + /* generated left ones */ + uint32_t internal_idx_offset = idx_offset; + uint32_t internal_idx = idx; + uint32_t internal_leaf = leaf_idx; + uint32_t h; /* The height we are in the Merkle tree */ + for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { + + /* Special processing if we're at the top of the tree */ + if (h >= tree_height - 1) { + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[1 * SPX_N], SPX_N ); + return; + } + /* The tree indexing logic is a bit off in this case */ + /* Adjust it so that the left-most node of the part of */ + /* the tree that we're processing has index 0 */ + prev_left_adj = left_adj; + left_adj = 2 - (1 << (tree_height - h - 1)); + } + + /* Check if we hit the top of the tree */ + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[1 * SPX_N], SPX_N ); + return; + } + + /* + * Check if one of the nodes we have is a part of the + * authentication path; if it is, write it out + */ + if ((((internal_idx << 1) ^ internal_leaf) & ~0x1) == 0) { + memcpy( &auth_path[ h * SPX_N ], + ¤t[(((internal_leaf & 1) ^ 1) + prev_left_adj) * SPX_N], + SPX_N ); + } + + /* + * Check if we're at a left child; if so, stop going up the stack + * Exception: if we've reached the end of the tree, keep on going + * (so we combine the last 2 nodes into the one root node in two + * more iterations) + */ + if ((internal_idx & 1) == 0 && idx < max_idx) { + break; + } + + /* Ok, we're at a right node (or doing the top 3 levels) */ + /* Now combine the left and right logical nodes together */ + + /* Set the address of the node we're creating. */ + int j; + internal_idx_offset >>= 1; + for (j = 0; j < 2; j++) { + set_tree_height(tree_addrx2 + j * 8, h + 1); + set_tree_index(tree_addrx2 + j * 8, + (2 / 2) * (internal_idx & ~1) + j - left_adj + internal_idx_offset ); + } + unsigned char *left = &stackx2[h * 2 * SPX_N]; + thashx2( ¤t[0 * SPX_N], + ¤t[1 * SPX_N], + &left [0 * SPX_N], + ¤t[0 * SPX_N], + 2, ctx, tree_addrx2); + } + + /* We've hit a left child; save the current for when we get the */ + /* corresponding right right */ + memcpy( &stackx2[h * 2 * SPX_N], current, 2 * SPX_N); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/utilsx2.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/utilsx2.h new file mode 100644 index 0000000000..e09faddc43 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/utilsx2.h @@ -0,0 +1,30 @@ +#ifndef SPX_UTILSX2_H +#define SPX_UTILSX2_H + +#include + +#include "context.h" +#include "params.h" + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + * + * This implementation uses SIMD to compute internal nodes 2 at a time (in + * parallel) + */ +#define treehashx2 SPX_NAMESPACE(treehashx2) +void treehashx2(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leafx2)( + unsigned char * /* Where to write the leaves */, + const spx_ctx * /* ctx */, + uint32_t addr_idx, void *info), + uint32_t tree_addrx2[2 * 8], void *info); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/wots.c b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/wots.c new file mode 100644 index 0000000000..3babe45e95 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/wots.c @@ -0,0 +1,259 @@ +#include +#include + +#include "wots.h" +#include "wotsx2.h" + +#include "address.h" +#include "hash.h" +#include "hashx2.h" +#include "params.h" +#include "thashx2.h" +#include "utils.h" +#include "utilsx2.h" + +// TODO clarify address expectations, and make them more uniform. +// TODO i.e. do we expect types to be set already? +// TODO and do we expect modifications or copies? + +/** + * Computes up the chains + */ +static void gen_chains( + unsigned char *out, + const unsigned char *in, + unsigned int start[SPX_WOTS_LEN], + const unsigned int steps[SPX_WOTS_LEN], + const spx_ctx *ctx, + uint32_t addr[8]) { + uint32_t i, j, k, idx, watching; + int done; + unsigned char empty[SPX_N]; + unsigned char *bufs[4]; + uint32_t addrs[8 * 2]; + + int l; + uint16_t counts[SPX_WOTS_W] = { 0 }; + uint16_t idxs[SPX_WOTS_LEN]; + uint16_t total, newTotal; + + /* set addrs = {addr, addr} */ + for (j = 0; j < 2; j++) { + memcpy(addrs + j * 8, addr, sizeof(uint32_t) * 8); + } + + /* Initialize out with the value at position 'start'. */ + memcpy(out, in, SPX_WOTS_LEN * SPX_N); + + /* Sort the chains in reverse order by steps using counting sort. */ + for (i = 0; i < SPX_WOTS_LEN; i++) { + counts[steps[i]]++; + } + total = 0; + for (l = SPX_WOTS_W - 1; l >= 0; l--) { + newTotal = counts[l] + total; + counts[l] = total; + total = newTotal; + } + for (i = 0; i < SPX_WOTS_LEN; i++) { + idxs[counts[steps[i]]] = i; + counts[steps[i]]++; + } + + /* We got our work cut out for us: do it! */ + for (i = 0; i < SPX_WOTS_LEN; i += 2) { + for (j = 0; j < 2 && i + j < SPX_WOTS_LEN; j++) { + idx = idxs[i + j]; + set_chain_addr(addrs + j * 8, idx); + bufs[j] = out + SPX_N * idx; + } + + /* As the chains are sorted in reverse order, we know that the first + * chain is the longest and the last one is the shortest. We keep + * an eye on whether the last chain is done and then on the one before, + * et cetera. */ + watching = 1; + done = 0; + while (i + watching >= SPX_WOTS_LEN) { + bufs[watching] = &empty[0]; + watching--; + } + + for (k = 0;; k++) { + while (k == steps[idxs[i + watching]]) { + bufs[watching] = &empty[0]; + if (watching == 0) { + done = 1; + break; + } + watching--; + } + if (done) { + break; + } + for (j = 0; j < watching + 1; j++) { + set_hash_addr(addrs + j * 8, k + start[idxs[i + j]]); + } + + thashx2(bufs[0], bufs[1], + bufs[0], bufs[1], 1, ctx, addrs); + } + } +} + +/** + * base_w algorithm as described in draft. + * Interprets an array of bytes as integers in base w. + * This only works when log_w is a divisor of 8. + */ +static void base_w(unsigned int *output, const int out_len, + const unsigned char *input) { + int in = 0; + int out = 0; + unsigned char total = 0; + int bits = 0; + int consumed; + + for (consumed = 0; consumed < out_len; consumed++) { + if (bits == 0) { + total = input[in]; + in++; + bits += 8; + } + bits -= SPX_WOTS_LOGW; + output[out] = (total >> bits) & (SPX_WOTS_W - 1); + out++; + } +} + +/* Computes the WOTS+ checksum over a message (in base_w). */ +static void wots_checksum(unsigned int *csum_base_w, + const unsigned int *msg_base_w) { + unsigned int csum = 0; + unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; + unsigned int i; + + /* Compute checksum. */ + for (i = 0; i < SPX_WOTS_LEN1; i++) { + csum += SPX_WOTS_W - 1 - msg_base_w[i]; + } + + /* Convert checksum to base_w. */ + /* Make sure expected empty zero bits are the least significant bits. */ + csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); + ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); + base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); +} + +/* Takes a message and derives the matching chain lengths. */ +void chain_lengths(unsigned int *lengths, const unsigned char *msg) { + base_w(lengths, SPX_WOTS_LEN1, msg); + wots_checksum(lengths + SPX_WOTS_LEN1, lengths); +} + +/** + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. + * + * Writes the computed public key to 'pk'. + */ +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]) { + unsigned int steps[SPX_WOTS_LEN]; + unsigned int start[SPX_WOTS_LEN]; + uint32_t i; + + chain_lengths(start, msg); + + for (i = 0; i < SPX_WOTS_LEN; i++) { + steps[i] = SPX_WOTS_W - 1 - start[i]; + } + + gen_chains(pk, sig, start, steps, ctx, addr); +} + +/* + * This generates 2 sequential WOTS public keys + * It also generates the WOTS signature if leaf_info indicates + * that we're signing with one of these WOTS keys + */ +void wots_gen_leafx2(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info) { + struct leaf_info_x2 *info = v_info; + uint32_t *leaf_addr = info->leaf_addr; + uint32_t *pk_addr = info->pk_addr; + unsigned int i, j, k; + unsigned char pk_buffer[ 2 * SPX_WOTS_BYTES ]; + unsigned wots_offset = SPX_WOTS_BYTES; + unsigned char *buffer; + uint32_t wots_k_mask; + unsigned wots_sign_index; + + if (((leaf_idx ^ info->wots_sign_leaf) & ~1) == 0) { + /* We're traversing the leaf that's signing; generate the WOTS */ + /* signature */ + wots_k_mask = 0; + wots_sign_index = info->wots_sign_leaf & 1; /* Which of of the 2 */ + /* slots do the signatures come from */ + } else { + /* Nope, we're just generating pk's; turn off the signature logic */ + wots_k_mask = ~0; + wots_sign_index = 0; + } + + for (j = 0; j < 2; j++) { + set_keypair_addr( leaf_addr + j * 8, leaf_idx + j ); + set_keypair_addr( pk_addr + j * 8, leaf_idx + j ); + } + + for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { + uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k to */ + /* the step if we're generating a signature, ~0 if we're not */ + + /* Start with the secret seed */ + for (j = 0; j < 2; j++) { + set_chain_addr(leaf_addr + j * 8, i); + set_hash_addr(leaf_addr + j * 8, 0); + set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTSPRF); + } + prf_addrx2(buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + ctx, leaf_addr); + for (j = 0; j < 2; j++) { + set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTS); + } + + /* Iterate down the WOTS chain */ + for (k = 0;; k++) { + /* Check if one of the values we have needs to be saved as a */ + /* part of the WOTS signature */ + if (k == wots_k) { + memcpy( info->wots_sig + i * SPX_N, + buffer + wots_sign_index * wots_offset, SPX_N ); + } + + /* Check if we hit the top of the chain */ + if (k == SPX_WOTS_W - 1) { + break; + } + + /* Iterate one step on all 4 chains */ + for (j = 0; j < 2; j++) { + set_hash_addr(leaf_addr + j * 8, k); + } + thashx2(buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + 1, ctx, leaf_addr); + } + } + + /* Do the final thash to generate the public keys */ + thashx2(dest + 0 * SPX_N, + dest + 1 * SPX_N, + pk_buffer + 0 * wots_offset, + pk_buffer + 1 * wots_offset, + SPX_WOTS_LEN, ctx, pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/wots.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/wots.h new file mode 100644 index 0000000000..4e7692eeef --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/wots.h @@ -0,0 +1,25 @@ +#ifndef SPX_WOTS_H +#define SPX_WOTS_H + +#include + +#include "context.h" +#include "params.h" + +/** + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. + * + * Writes the computed public key to 'pk'. + */ +#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]); + +/* + * Compute the chain lengths needed for a given message hash + */ +#define chain_lengths SPX_NAMESPACE(chain_lengths) +void chain_lengths(unsigned int *lengths, const unsigned char *msg); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/wotsx2.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/wotsx2.h new file mode 100644 index 0000000000..b58bb61f84 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/wotsx2.h @@ -0,0 +1,40 @@ +#ifndef WOTSX2_H_ +#define WOTSX2_H_ + +#include "params.h" +#include + +/* + * This is here to provide an interface to the internal wots_gen_leafx2 + * routine. While this routine is not referenced in the package outside of + * wots.c, it is called from the stand-alone benchmark code to characterize + * the performance + */ +struct leaf_info_x2 { + unsigned char *wots_sig; + uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ + uint32_t *wots_steps; + uint32_t leaf_addr[2 * 8]; + uint32_t pk_addr[2 * 8]; +}; + +/* Macro to set the leaf_info to something 'benign', that is, it would */ +/* run with the same time as it does during the real signing process */ +/* Used only by the benchmark code */ +#define INITIALIZE_LEAF_INFO_X2(info, addr, step_buffer) { \ + (info).wots_sig = 0; \ + (info).wots_sign_leaf = ~0; \ + (info).wots_steps = step_buffer; \ + int i; \ + for (i=0; i<2; i++) { \ + memcpy( &(info).leaf_addr[8*i], addr, 32 ); \ + memcpy( &(info).pk_addr[8*i], addr, 32 ); \ + } \ + } + +#define wots_gen_leafx2 SPX_NAMESPACE(wots_gen_leafx2) +void wots_gen_leafx2(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info); + +#endif /* WOTSX2_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/LICENSE b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/LICENSE new file mode 100644 index 0000000000..670154e353 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/LICENSE @@ -0,0 +1,116 @@ +CC0 1.0 Universal + +Statement of Purpose + +The laws of most jurisdictions throughout the world automatically confer +exclusive Copyright and Related Rights (defined below) upon the creator and +subsequent owner(s) (each and all, an "owner") of an original work of +authorship and/or a database (each, a "Work"). + +Certain owners wish to permanently relinquish those rights to a Work for the +purpose of contributing to a commons of creative, cultural and scientific +works ("Commons") that the public can reliably and without fear of later +claims of infringement build upon, modify, incorporate in other works, reuse +and redistribute as freely as possible in any form whatsoever and for any +purposes, including without limitation commercial purposes. These owners may +contribute to the Commons to promote the ideal of a free culture and the +further production of creative, cultural and scientific works, or to gain +reputation or greater distribution for their Work in part through the use and +efforts of others. + +For these and/or other purposes and motivations, and without any expectation +of additional consideration or compensation, the person associating CC0 with a +Work (the "Affirmer"), to the extent that he or she is an owner of Copyright +and Related Rights in the Work, voluntarily elects to apply CC0 to the Work +and publicly distribute the Work under its terms, with knowledge of his or her +Copyright and Related Rights in the Work and the meaning and intended legal +effect of CC0 on those rights. + +1. Copyright and Related Rights. A Work made available under CC0 may be +protected by copyright and related or neighboring rights ("Copyright and +Related Rights"). Copyright and Related Rights include, but are not limited +to, the following: + + i. the right to reproduce, adapt, distribute, perform, display, communicate, + and translate a Work; + + ii. moral rights retained by the original author(s) and/or performer(s); + + iii. publicity and privacy rights pertaining to a person's image or likeness + depicted in a Work; + + iv. rights protecting against unfair competition in regards to a Work, + subject to the limitations in paragraph 4(a), below; + + v. rights protecting the extraction, dissemination, use and reuse of data in + a Work; + + vi. database rights (such as those arising under Directive 96/9/EC of the + European Parliament and of the Council of 11 March 1996 on the legal + protection of databases, and under any national implementation thereof, + including any amended or successor version of such directive); and + + vii. other similar, equivalent or corresponding rights throughout the world + based on applicable law or treaty, and any national implementations thereof. + +2. Waiver. To the greatest extent permitted by, but not in contravention of, +applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and +unconditionally waives, abandons, and surrenders all of Affirmer's Copyright +and Related Rights and associated claims and causes of action, whether now +known or unknown (including existing as well as future claims and causes of +action), in the Work (i) in all territories worldwide, (ii) for the maximum +duration provided by applicable law or treaty (including future time +extensions), (iii) in any current or future medium and for any number of +copies, and (iv) for any purpose whatsoever, including without limitation +commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes +the Waiver for the benefit of each member of the public at large and to the +detriment of Affirmer's heirs and successors, fully intending that such Waiver +shall not be subject to revocation, rescission, cancellation, termination, or +any other legal or equitable action to disrupt the quiet enjoyment of the Work +by the public as contemplated by Affirmer's express Statement of Purpose. + +3. Public License Fallback. Should any part of the Waiver for any reason be +judged legally invalid or ineffective under applicable law, then the Waiver +shall be preserved to the maximum extent permitted taking into account +Affirmer's express Statement of Purpose. In addition, to the extent the Waiver +is so judged Affirmer hereby grants to each affected person a royalty-free, +non transferable, non sublicensable, non exclusive, irrevocable and +unconditional license to exercise Affirmer's Copyright and Related Rights in +the Work (i) in all territories worldwide, (ii) for the maximum duration +provided by applicable law or treaty (including future time extensions), (iii) +in any current or future medium and for any number of copies, and (iv) for any +purpose whatsoever, including without limitation commercial, advertising or +promotional purposes (the "License"). The License shall be deemed effective as +of the date CC0 was applied by Affirmer to the Work. Should any part of the +License for any reason be judged legally invalid or ineffective under +applicable law, such partial invalidity or ineffectiveness shall not +invalidate the remainder of the License, and in such case Affirmer hereby +affirms that he or she will not (i) exercise any of his or her remaining +Copyright and Related Rights in the Work or (ii) assert any associated claims +and causes of action with respect to the Work, in either case contrary to +Affirmer's express Statement of Purpose. + +4. Limitations and Disclaimers. + + a. No trademark or patent rights held by Affirmer are waived, abandoned, + surrendered, licensed or otherwise affected by this document. + + b. Affirmer offers the Work as-is and makes no representations or warranties + of any kind concerning the Work, express, implied, statutory or otherwise, + including without limitation warranties of title, merchantability, fitness + for a particular purpose, non infringement, or the absence of latent or + other defects, accuracy, or the present or absence of errors, whether or not + discoverable, all to the greatest extent permissible under applicable law. + + c. Affirmer disclaims responsibility for clearing rights of other persons + that may apply to the Work or any use thereof, including without limitation + any person's Copyright and Related Rights in the Work. Further, Affirmer + disclaims responsibility for obtaining any necessary consents, permissions + or other rights required for any use of the Work. + + d. Affirmer understands and acknowledges that Creative Commons is not a + party to this document and has no duty or obligation with respect to this + CC0 or use of the Work. + +For more information, please see + diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/address.c b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/address.c new file mode 100644 index 0000000000..d49d9f3b6b --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/address.c @@ -0,0 +1,95 @@ +#include +#include + +#include "address.h" +#include "params.h" +#include "utils.h" + +/* + * Specify which level of Merkle tree (the "layer") we're working on + */ +void set_layer_addr(uint32_t addr[8], uint32_t layer) { + ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; +} + +/* + * Specify which Merkle tree within the level (the "tree address") we're working on + */ +void set_tree_addr(uint32_t addr[8], uint64_t tree) { + ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); +} + +/* + * Specify the reason we'll use this address structure for, that is, what + * hash will we compute with it. This is used so that unrelated types of + * hashes don't accidentally get the same address structure. The type will be + * one of the SPX_ADDR_TYPE constants + */ +void set_type(uint32_t addr[8], uint32_t type) { + ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; +} + +/* + * Copy the layer and tree fields of the address structure. This is used + * when we're doing multiple types of hashes within the same Merkle tree + */ +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); +} + +/* These functions are used for OTS addresses. */ + +/* + * Specify which Merkle leaf we're working on; that is, which OTS keypair + * we're talking about. + */ +void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { + /* We have > 256 OTS at the bottom of the Merkle tree; to specify */ + /* which one, we'd need to express it in two bytes */ + ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR2] = (unsigned char)(keypair >> 8); + ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; +} + +/* + * Copy the layer, tree and keypair fields of the address structure. This is + * used when we're doing multiple things within the same OTS keypair + */ +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); + ((unsigned char *)out)[SPX_OFFSET_KP_ADDR2] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR2]; + ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; +} + +/* + * Specify which Merkle chain within the OTS we're working with + * (the chain address) + */ +void set_chain_addr(uint32_t addr[8], uint32_t chain) { + ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; +} + +/* + * Specify where in the Merkle chain we are +* (the hash address) + */ +void set_hash_addr(uint32_t addr[8], uint32_t hash) { + ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; +} + +/* These functions are used for all hash tree addresses (including FORS). */ + +/* + * Specify the height of the node in the Merkle/FORS tree we are in + * (the tree height) + */ +void set_tree_height(uint32_t addr[8], uint32_t tree_height) { + ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; +} + +/* + * Specify the distance from the left edge of the node in the Merkle/FORS tree + * (the tree index) + */ +void set_tree_index(uint32_t addr[8], uint32_t tree_index) { + u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/address.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/address.h new file mode 100644 index 0000000000..24a84eb40c --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/address.h @@ -0,0 +1,52 @@ +#ifndef SPX_ADDRESS_H +#define SPX_ADDRESS_H + +#include + +#include "params.h" + +/* The hash types that are passed to set_type */ +#define SPX_ADDR_TYPE_WOTS 0 +#define SPX_ADDR_TYPE_WOTSPK 1 +#define SPX_ADDR_TYPE_HASHTREE 2 +#define SPX_ADDR_TYPE_FORSTREE 3 +#define SPX_ADDR_TYPE_FORSPK 4 +#define SPX_ADDR_TYPE_WOTSPRF 5 +#define SPX_ADDR_TYPE_FORSPRF 6 + +#define set_layer_addr SPX_NAMESPACE(set_layer_addr) +void set_layer_addr(uint32_t addr[8], uint32_t layer); + +#define set_tree_addr SPX_NAMESPACE(set_tree_addr) +void set_tree_addr(uint32_t addr[8], uint64_t tree); + +#define set_type SPX_NAMESPACE(set_type) +void set_type(uint32_t addr[8], uint32_t type); + +/* Copies the layer and tree part of one address into the other */ +#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); + +/* These functions are used for WOTS and FORS addresses. */ + +#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) +void set_keypair_addr(uint32_t addr[8], uint32_t keypair); + +#define set_chain_addr SPX_NAMESPACE(set_chain_addr) +void set_chain_addr(uint32_t addr[8], uint32_t chain); + +#define set_hash_addr SPX_NAMESPACE(set_hash_addr) +void set_hash_addr(uint32_t addr[8], uint32_t hash); + +#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); + +/* These functions are used for all hash tree addresses (including FORS). */ + +#define set_tree_height SPX_NAMESPACE(set_tree_height) +void set_tree_height(uint32_t addr[8], uint32_t tree_height); + +#define set_tree_index SPX_NAMESPACE(set_tree_index) +void set_tree_index(uint32_t addr[8], uint32_t tree_index); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/api.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/api.h new file mode 100644 index 0000000000..854dc65500 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/api.h @@ -0,0 +1,77 @@ +#ifndef PQCLEAN_SPHINCSSHAKE128SROBUST_AVX2_API_H +#define PQCLEAN_SPHINCSSHAKE128SROBUST_AVX2_API_H + +#include +#include + +#define PQCLEAN_SPHINCSSHAKE128SROBUST_AVX2_CRYPTO_ALGNAME "SPHINCS+-shake-128s-robust" + +#define PQCLEAN_SPHINCSSHAKE128SROBUST_AVX2_CRYPTO_SECRETKEYBYTES 64 +#define PQCLEAN_SPHINCSSHAKE128SROBUST_AVX2_CRYPTO_PUBLICKEYBYTES 32 +#define PQCLEAN_SPHINCSSHAKE128SROBUST_AVX2_CRYPTO_BYTES 7856 + +#define PQCLEAN_SPHINCSSHAKE128SROBUST_AVX2_CRYPTO_SEEDBYTES 48 + +/* + * Returns the length of a secret key, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE128SROBUST_AVX2_crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE128SROBUST_AVX2_crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE128SROBUST_AVX2_crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE128SROBUST_AVX2_crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +int PQCLEAN_SPHINCSSHAKE128SROBUST_AVX2_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +int PQCLEAN_SPHINCSSHAKE128SROBUST_AVX2_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +int PQCLEAN_SPHINCSSHAKE128SROBUST_AVX2_crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +int PQCLEAN_SPHINCSSHAKE128SROBUST_AVX2_crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, + const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +int PQCLEAN_SPHINCSSHAKE128SROBUST_AVX2_crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +int PQCLEAN_SPHINCSSHAKE128SROBUST_AVX2_crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/context.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/context.h new file mode 100644 index 0000000000..6e0a33f3b7 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/context.h @@ -0,0 +1,19 @@ +#ifndef SPX_CONTEXT_H +#define SPX_CONTEXT_H + +#include + +#include "params.h" + +typedef struct { + uint8_t pub_seed[SPX_N]; + uint8_t sk_seed[SPX_N]; +} spx_ctx; + +#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) +void initialize_hash_function(spx_ctx *ctx); + +#define free_hash_function SPX_NAMESPACE(free_hash_function) +void free_hash_function(spx_ctx *ctx); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/context_shake.c b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/context_shake.c new file mode 100644 index 0000000000..9614a103d3 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/context_shake.c @@ -0,0 +1,12 @@ +#include "context.h" + +/* For SHAKE256, there is no immediate reason to initialize at the start, + so this function is an empty operation. */ +void initialize_hash_function(spx_ctx *ctx) { + (void)ctx; /* Suppress an 'unused parameter' warning. */ +} + +// in case the hash function api is heap-based. +void free_hash_function(spx_ctx *ctx) { + (void)ctx; +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/fips202x4.c b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/fips202x4.c new file mode 100644 index 0000000000..1e06fef186 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/fips202x4.c @@ -0,0 +1,210 @@ +#include +#include +#include + +#include "fips202.h" +#include "fips202x4.h" + +#define NROUNDS 24 +#define ROL(a, offset) (((a) << (offset)) ^ ((a) >> (64-(offset)))) + +static uint64_t load64(const unsigned char *x) { + unsigned long long r = 0, i; + + for (i = 0; i < 8; ++i) { + r |= (unsigned long long)x[i] << 8 * i; + } + return r; +} + +static void store64(uint8_t *x, uint64_t u) { + unsigned int i; + + for (i = 0; i < 8; ++i) { + x[i] = (uint8_t)u; + u >>= 8; + } +} + +/* Use implementation from the Keccak Code Package */ +extern void KeccakP1600times4_PermuteAll_24rounds(__m256i *s); +#define KeccakF1600_StatePermute4x KeccakP1600times4_PermuteAll_24rounds + +static void keccak_absorb4x(__m256i *s, + unsigned int r, + const unsigned char *m0, + const unsigned char *m1, + const unsigned char *m2, + const unsigned char *m3, + unsigned long long int mlen, + unsigned char p) { + unsigned long long i; + unsigned char t0[200]; + unsigned char t1[200]; + unsigned char t2[200]; + unsigned char t3[200]; + + unsigned long long *ss = (unsigned long long *)s; + + + while (mlen >= r) { + for (i = 0; i < r / 8; ++i) { + ss[4 * i + 0] ^= load64(m0 + 8 * i); + ss[4 * i + 1] ^= load64(m1 + 8 * i); + ss[4 * i + 2] ^= load64(m2 + 8 * i); + ss[4 * i + 3] ^= load64(m3 + 8 * i); + } + + KeccakF1600_StatePermute4x(s); + mlen -= r; + m0 += r; + m1 += r; + m2 += r; + m3 += r; + } + + for (i = 0; i < r; ++i) { + t0[i] = 0; + t1[i] = 0; + t2[i] = 0; + t3[i] = 0; + } + for (i = 0; i < mlen; ++i) { + t0[i] = m0[i]; + t1[i] = m1[i]; + t2[i] = m2[i]; + t3[i] = m3[i]; + } + + t0[i] = p; + t1[i] = p; + t2[i] = p; + t3[i] = p; + + t0[r - 1] |= 128; + t1[r - 1] |= 128; + t2[r - 1] |= 128; + t3[r - 1] |= 128; + + for (i = 0; i < r / 8; ++i) { + ss[4 * i + 0] ^= load64(t0 + 8 * i); + ss[4 * i + 1] ^= load64(t1 + 8 * i); + ss[4 * i + 2] ^= load64(t2 + 8 * i); + ss[4 * i + 3] ^= load64(t3 + 8 * i); + } +} + + +static void keccak_squeezeblocks4x(unsigned char *h0, + unsigned char *h1, + unsigned char *h2, + unsigned char *h3, + unsigned long long int nblocks, + __m256i *s, + unsigned int r) { + unsigned int i; + + unsigned long long *ss = (unsigned long long *)s; + + while (nblocks > 0) { + KeccakF1600_StatePermute4x(s); + for (i = 0; i < (r >> 3); i++) { + store64(h0 + 8 * i, ss[4 * i + 0]); + store64(h1 + 8 * i, ss[4 * i + 1]); + store64(h2 + 8 * i, ss[4 * i + 2]); + store64(h3 + 8 * i, ss[4 * i + 3]); + } + h0 += r; + h1 += r; + h2 += r; + h3 += r; + nblocks--; + } +} + + + +void shake128x4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, unsigned long long outlen, + unsigned char *in0, + unsigned char *in1, + unsigned char *in2, + unsigned char *in3, unsigned long long inlen) { + __m256i s[25]; + unsigned char t0[SHAKE128_RATE]; + unsigned char t1[SHAKE128_RATE]; + unsigned char t2[SHAKE128_RATE]; + unsigned char t3[SHAKE128_RATE]; + unsigned int i; + + /* zero state */ + for (i = 0; i < 25; i++) { + s[i] = _mm256_xor_si256(s[i], s[i]); + } + + /* absorb 4 message of identical length in parallel */ + keccak_absorb4x(s, SHAKE128_RATE, in0, in1, in2, in3, inlen, 0x1F); + + /* Squeeze output */ + keccak_squeezeblocks4x(out0, out1, out2, out3, outlen / SHAKE128_RATE, s, SHAKE128_RATE); + + out0 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; + out1 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; + out2 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; + out3 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; + + if (outlen % SHAKE128_RATE) { + keccak_squeezeblocks4x(t0, t1, t2, t3, 1, s, SHAKE128_RATE); + for (i = 0; i < outlen % SHAKE128_RATE; i++) { + out0[i] = t0[i]; + out1[i] = t1[i]; + out2[i] = t2[i]; + out3[i] = t3[i]; + } + } +} + + +void shake256x4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, unsigned long long outlen, + unsigned char *in0, + unsigned char *in1, + unsigned char *in2, + unsigned char *in3, unsigned long long inlen) { + __m256i s[25]; + unsigned char t0[SHAKE256_RATE]; + unsigned char t1[SHAKE256_RATE]; + unsigned char t2[SHAKE256_RATE]; + unsigned char t3[SHAKE256_RATE]; + unsigned int i; + + /* zero state */ + for (i = 0; i < 25; i++) { + s[i] = _mm256_xor_si256(s[i], s[i]); + } + + /* absorb 4 message of identical length in parallel */ + keccak_absorb4x(s, SHAKE256_RATE, in0, in1, in2, in3, inlen, 0x1F); + + /* Squeeze output */ + keccak_squeezeblocks4x(out0, out1, out2, out3, outlen / SHAKE256_RATE, s, SHAKE256_RATE); + + out0 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; + out1 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; + out2 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; + out3 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; + + if (outlen % SHAKE256_RATE) { + keccak_squeezeblocks4x(t0, t1, t2, t3, 1, s, SHAKE256_RATE); + for (i = 0; i < outlen % SHAKE256_RATE; i++) { + out0[i] = t0[i]; + out1[i] = t1[i]; + out2[i] = t2[i]; + out3[i] = t3[i]; + } + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/fips202x4.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/fips202x4.h new file mode 100644 index 0000000000..2b93c9cd0d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/fips202x4.h @@ -0,0 +1,28 @@ +#ifndef SPX_FIPS202X4_H +#define SPX_FIPS202X4_H + +#include + +#include "params.h" + +#define shake128x4 SPX_NAMESPACE(shake128x4) +void shake128x4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, unsigned long long outlen, + unsigned char *in0, + unsigned char *in1, + unsigned char *in2, + unsigned char *in3, unsigned long long inlen); + +#define shake256x4 SPX_NAMESPACE(shake256x4) +void shake256x4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, unsigned long long outlen, + unsigned char *in0, + unsigned char *in1, + unsigned char *in2, + unsigned char *in3, unsigned long long inlen); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/fors.c b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/fors.c new file mode 100644 index 0000000000..f1b0639cfc --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/fors.c @@ -0,0 +1,202 @@ +#include +#include +#include + +#include "fors.h" + +#include "address.h" +#include "hash.h" +#include "hashx4.h" +#include "thash.h" +#include "thashx4.h" +#include "utils.h" +#include "utilsx4.h" + +static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + prf_addr(sk, ctx, fors_leaf_addr); +} + +static void fors_gen_skx4(unsigned char *sk0, + unsigned char *sk1, + unsigned char *sk2, + unsigned char *sk3, const spx_ctx *ctx, + uint32_t fors_leaf_addrx4[4 * 8]) { + prf_addrx4(sk0, sk1, sk2, sk3, + ctx, fors_leaf_addrx4); +} + +static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, + const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + thash(leaf, sk, 1, ctx, fors_leaf_addr); +} + +static void fors_sk_to_leafx4(unsigned char *leaf0, + unsigned char *leaf1, + unsigned char *leaf2, + unsigned char *leaf3, + const unsigned char *sk0, + const unsigned char *sk1, + const unsigned char *sk2, + const unsigned char *sk3, + const spx_ctx *ctx, + uint32_t fors_leaf_addrx4[4 * 8]) { + thashx4(leaf0, leaf1, leaf2, leaf3, + sk0, sk1, sk2, sk3, + 1, ctx, fors_leaf_addrx4); +} + +struct fors_gen_leaf_info { + uint32_t leaf_addrx[4 * 8]; +}; + +static void fors_gen_leafx4(unsigned char *leaf, + const spx_ctx *ctx, + uint32_t addr_idx, void *info) { + struct fors_gen_leaf_info *fors_info = info; + uint32_t *fors_leaf_addrx4 = fors_info->leaf_addrx; + unsigned int j; + + /* Only set the parts that the caller doesn't set */ + for (j = 0; j < 4; j++) { + set_tree_index(fors_leaf_addrx4 + j * 8, addr_idx + j); + set_type(fors_leaf_addrx4 + j * 8, SPX_ADDR_TYPE_FORSPRF); + } + + fors_gen_skx4(leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + leaf + 2 * SPX_N, + leaf + 3 * SPX_N, + ctx, fors_leaf_addrx4); + + for (j = 0; j < 4; j++) { + set_type(fors_leaf_addrx4 + j * 8, SPX_ADDR_TYPE_FORSTREE); + } + + fors_sk_to_leafx4(leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + leaf + 2 * SPX_N, + leaf + 3 * SPX_N, + leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + leaf + 2 * SPX_N, + leaf + 3 * SPX_N, + ctx, fors_leaf_addrx4); +} + +/** + * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + * Assumes indices has space for SPX_FORS_TREES integers. + */ +static void message_to_indices(uint32_t *indices, const unsigned char *m) { + unsigned int i, j; + unsigned int offset = 0; + + for (i = 0; i < SPX_FORS_TREES; i++) { + indices[i] = 0; + for (j = 0; j < SPX_FORS_HEIGHT; j++) { + indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); + offset++; + } + } +} + +/** + * Signs a message m, deriving the secret key from sk_seed and the FTS address. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + uint32_t fors_tree_addr[4 * 8] = {0}; + struct fors_gen_leaf_info fors_info = {0}; + uint32_t *fors_leaf_addr = fors_info.leaf_addrx; + uint32_t fors_pk_addr[8] = {0}; + uint32_t idx_offset; + unsigned int i; + + for (i = 0; i < 4; i++) { + copy_keypair_addr(fors_tree_addr + 8 * i, fors_addr); + set_type(fors_tree_addr + 8 * i, SPX_ADDR_TYPE_FORSTREE); + copy_keypair_addr(fors_leaf_addr + 8 * i, fors_addr); + } + copy_keypair_addr(fors_pk_addr, fors_addr); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); + + message_to_indices(indices, m); + + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); + + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + + /* Include the secret key part that produces the selected leaf node. */ + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); + fors_gen_sk(sig, ctx, fors_tree_addr); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + sig += SPX_N; + + /* Compute the authentication path for this leaf node. */ + treehashx4(roots + i * SPX_N, sig, ctx, + indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx4, + fors_tree_addr, &fors_info); + + sig += SPX_N * SPX_FORS_HEIGHT; + } + + /* Hash horizontally across all tree roots to derive the public key. */ + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); +} + +/** + * Derives the FORS public key from a signature. + * This can be used for verification by comparing to a known public key, or to + * subsequently verify a signature on the derived public key. The latter is the + * typical use-case when used as an FTS below an OTS in a hypertree. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + unsigned char leaf[SPX_N]; + uint32_t fors_tree_addr[8] = {0}; + uint32_t fors_pk_addr[8] = {0}; + uint32_t idx_offset; + unsigned int i; + + copy_keypair_addr(fors_tree_addr, fors_addr); + copy_keypair_addr(fors_pk_addr, fors_addr); + + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); + + message_to_indices(indices, m); + + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); + + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + + /* Derive the leaf from the included secret key part. */ + fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); + sig += SPX_N; + + /* Derive the corresponding root node of this tree. */ + compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, + sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); + sig += SPX_N * SPX_FORS_HEIGHT; + } + + /* Hash horizontally across all tree roots to derive the public key. */ + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/fors.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/fors.h new file mode 100644 index 0000000000..509140a178 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/fors.h @@ -0,0 +1,32 @@ +#ifndef SPX_FORS_H +#define SPX_FORS_H + +#include + +#include "context.h" +#include "params.h" + +/** + * Signs a message m, deriving the secret key from sk_seed and the FTS address. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +#define fors_sign SPX_NAMESPACE(fors_sign) +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); + +/** + * Derives the FORS public key from a signature. + * This can be used for verification by comparing to a known public key, or to + * subsequently verify a signature on the derived public key. The latter is the + * typical use-case when used as an FTS below an OTS in a hypertree. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/hash.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/hash.h new file mode 100644 index 0000000000..f7c87d4c3c --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/hash.h @@ -0,0 +1,28 @@ +#ifndef SPX_HASH_H +#define SPX_HASH_H + +#include +#include + +#include "context.h" +#include "params.h" + +#define prf_addr SPX_NAMESPACE(prf_addr) +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]); + +#define gen_message_random SPX_NAMESPACE(gen_message_random) +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); + +#define hash_message SPX_NAMESPACE(hash_message) +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); + + + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/hash_shake.c b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/hash_shake.c new file mode 100644 index 0000000000..ff5e7ec918 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/hash_shake.c @@ -0,0 +1,83 @@ +#include +#include + +#include "hash.h" + +#include "address.h" +#include "fips202.h" +#include "params.h" +#include "utils.h" + +/* + * Computes PRF(pk_seed, sk_seed, addr) + */ +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]) { + unsigned char buf[2 * SPX_N + SPX_ADDR_BYTES]; + + memcpy(buf, ctx->pub_seed, SPX_N); + memcpy(buf + SPX_N, addr, SPX_ADDR_BYTES); + memcpy(buf + SPX_N + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); + + shake256(out, SPX_N, buf, 2 * SPX_N + SPX_ADDR_BYTES); +} + +/** + * Computes the message-dependent randomness R, using a secret seed and an + * optional randomization value as well as the message. + */ +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { + (void)ctx; + shake256incctx s_inc; + + shake256_inc_init(&s_inc); + shake256_inc_absorb(&s_inc, sk_prf, SPX_N); + shake256_inc_absorb(&s_inc, optrand, SPX_N); + shake256_inc_absorb(&s_inc, m, mlen); + shake256_inc_finalize(&s_inc); + shake256_inc_squeeze(R, SPX_N, &s_inc); + shake256_inc_ctx_release(&s_inc); +} + +/** + * Computes the message hash using R, the public key, and the message. + * Outputs the message digest and the index of the leaf. The index is split in + * the tree index and the leaf index, for convenient copying to an address. + */ +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { + (void)ctx; +#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) +#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) +#define SPX_LEAF_BITS SPX_TREE_HEIGHT +#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) +#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) + + unsigned char buf[SPX_DGST_BYTES]; + unsigned char *bufp = buf; + shake256incctx s_inc; + + shake256_inc_init(&s_inc); + shake256_inc_absorb(&s_inc, R, SPX_N); + shake256_inc_absorb(&s_inc, pk, SPX_PK_BYTES); + shake256_inc_absorb(&s_inc, m, mlen); + shake256_inc_finalize(&s_inc); + shake256_inc_squeeze(buf, SPX_DGST_BYTES, &s_inc); + shake256_inc_ctx_release(&s_inc); + + memcpy(digest, bufp, SPX_FORS_MSG_BYTES); + bufp += SPX_FORS_MSG_BYTES; + + + *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); + *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); + bufp += SPX_TREE_BYTES; + + *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); + *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/hash_shakex4.c b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/hash_shakex4.c new file mode 100644 index 0000000000..bbd22eb117 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/hash_shakex4.c @@ -0,0 +1,64 @@ +#include +#include + +#include "hashx4.h" + +#include "address.h" +#include "fips202x4.h" +#include "params.h" + +extern void KeccakP1600times4_PermuteAll_24rounds(__m256i *s); + +/* + * 4-way parallel version of prf_addr; takes 4x as much input and output + */ +void prf_addrx4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const spx_ctx *ctx, + const uint32_t addrx4[4 * 8]) { + /* As we write and read only a few quadwords, it is more efficient to + * build and extract from the fourway SHAKE256 state by hand. */ + __m256i state[25]; + + for (int i = 0; i < SPX_N / 8; i++) { + state[i] = _mm256_set1_epi64x(((int64_t *)ctx->pub_seed)[i]); + } + for (int i = 0; i < 4; i++) { + state[SPX_N / 8 + i] = _mm256_set_epi32( + (int)addrx4[3 * 8 + 1 + 2 * i], + (int)addrx4[3 * 8 + 2 * i], + (int)addrx4[2 * 8 + 1 + 2 * i], + (int)addrx4[2 * 8 + 2 * i], + (int)addrx4[8 + 1 + 2 * i], + (int)addrx4[8 + 2 * i], + (int)addrx4[1 + 2 * i], + (int)addrx4[2 * i] + ); + } + for (int i = 0; i < SPX_N / 8; i++) { + state[SPX_N / 8 + i + 4] = _mm256_set1_epi64x(((int64_t *)ctx->sk_seed)[i]); + } + + /* SHAKE domain separator and padding. */ + state[SPX_N / 4 + 4] = _mm256_set1_epi64x(0x1f); + for (int i = SPX_N / 4 + 5; i < 16; i++) { + state[i] = _mm256_set1_epi64x(0); + } + // shift unsigned and then cast to avoid UB + state[16] = _mm256_set1_epi64x((long long)(0x80ULL << 56)); + + for (int i = 17; i < 25; i++) { + state[i] = _mm256_set1_epi64x(0); + } + + KeccakP1600times4_PermuteAll_24rounds(&state[0]); + + for (int i = 0; i < SPX_N / 8; i++) { + ((int64_t *)out0)[i] = _mm256_extract_epi64(state[i], 0); + ((int64_t *)out1)[i] = _mm256_extract_epi64(state[i], 1); + ((int64_t *)out2)[i] = _mm256_extract_epi64(state[i], 2); + ((int64_t *)out3)[i] = _mm256_extract_epi64(state[i], 3); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/hashx4.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/hashx4.h new file mode 100644 index 0000000000..3751a0ebd0 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/hashx4.h @@ -0,0 +1,17 @@ +#ifndef SPX_HASHX4_H +#define SPX_HASHX4_H + +#include + +#include "context.h" +#include "params.h" + +#define prf_addrx4 SPX_NAMESPACE(prf_addrx4) +void prf_addrx4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const spx_ctx *ctx, + const uint32_t addrx4[4 * 8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/merkle.c b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/merkle.c new file mode 100644 index 0000000000..f57811c1ac --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/merkle.c @@ -0,0 +1,64 @@ +#include +#include + +#include "merkle.h" + +#include "address.h" +#include "params.h" +#include "utils.h" +#include "utilsx4.h" +#include "wots.h" +#include "wotsx4.h" + +/* + * This generates a Merkle signature (WOTS signature followed by the Merkle + * authentication path). + */ +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf) { + unsigned char *auth_path = sig + SPX_WOTS_BYTES; + uint32_t tree_addrx4[4 * 8] = { 0 }; + int j; + struct leaf_info_x4 info = { 0 }; + unsigned steps[ SPX_WOTS_LEN ]; + + info.wots_sig = sig; + chain_lengths(steps, root); + info.wots_steps = steps; + + for (j = 0; j < 4; j++) { + set_type(&tree_addrx4[8 * j], SPX_ADDR_TYPE_HASHTREE); + set_type(&info.leaf_addr[8 * j], SPX_ADDR_TYPE_WOTS); + set_type(&info.pk_addr[8 * j], SPX_ADDR_TYPE_WOTSPK); + copy_subtree_addr(&tree_addrx4[8 * j], tree_addr); + copy_subtree_addr(&info.leaf_addr[8 * j], wots_addr); + copy_subtree_addr(&info.pk_addr[8 * j], wots_addr); + } + + info.wots_sign_leaf = idx_leaf; + + treehashx4(root, auth_path, ctx, + idx_leaf, 0, + SPX_TREE_HEIGHT, + wots_gen_leafx4, + tree_addrx4, &info); +} + +/* Compute root node of the top-most subtree. */ +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { + /* We do not need the auth path in key generation, but it simplifies the + code to have just one treehash routine that computes both root and path + in one function. */ + unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; + uint32_t top_tree_addr[8] = {0}; + uint32_t wots_addr[8] = {0}; + + set_layer_addr(top_tree_addr, SPX_D - 1); + set_layer_addr(wots_addr, SPX_D - 1); + + merkle_sign(auth_path, root, ctx, + wots_addr, top_tree_addr, + ~0U /* ~0 means "don't bother generating an auth path */ ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/merkle.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/merkle.h new file mode 100644 index 0000000000..769cf2e970 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/merkle.h @@ -0,0 +1,21 @@ +#ifndef MERKLE_H_ +#define MERKLE_H_ + +#include + +#include "context.h" +#include "params.h" + +/* Generate a Merkle signature (WOTS signature followed by the Merkle */ +/* authentication path) */ +#define merkle_sign SPX_NAMESPACE(merkle_sign) +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf); + +/* Compute the root node of the top-most subtree. */ +#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); + +#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/nistapi.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/nistapi.h new file mode 100644 index 0000000000..3cb71afad4 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/nistapi.h @@ -0,0 +1,87 @@ +#ifndef SPX_API_H +#define SPX_API_H + +#include +#include + +#include "params.h" + +#define CRYPTO_ALGNAME "SPHINCS+" + +#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES +#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES +#define CRYPTO_BYTES SPX_BYTES +#define CRYPTO_SEEDBYTES (3*SPX_N) + +/* + * Returns the length of a secret key, in bytes + */ +#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) +size_t crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) +size_t crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) +size_t crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) +size_t crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +#define crypto_sign SPX_NAMESPACE(crypto_sign) +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/params.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/params.h new file mode 100644 index 0000000000..200d84e284 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/params.h @@ -0,0 +1,56 @@ +#ifndef SPX_PARAMS_H +#define SPX_PARAMS_H + +#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSSHAKE128SROBUST_AVX2_##s + +/* Hash output length in bytes. */ +#define SPX_N 16 +/* Height of the hypertree. */ +#define SPX_FULL_HEIGHT 63 +/* Number of subtree layer. */ +#define SPX_D 7 +/* FORS tree dimensions. */ +#define SPX_FORS_HEIGHT 12 +#define SPX_FORS_TREES 14 +/* Winternitz parameter, */ +#define SPX_WOTS_W 16 + +/* The hash function is defined by linking a different hash.c file, as opposed + to setting a #define constant. */ + +/* For clarity */ +#define SPX_ADDR_BYTES 32 + +/* WOTS parameters. */ +#define SPX_WOTS_LOGW 4 + +#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) + +/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ +#define SPX_WOTS_LEN2 3 + +#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) +#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) +#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES + +/* Subtree size. */ +#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) + +//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT +// #error SPX_D should always divide SPX_FULL_HEIGHT +//#endif + +/* FORS parameters. */ +#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) +#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) +#define SPX_FORS_PK_BYTES SPX_N + +/* Resulting SPX sizes. */ +#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ + SPX_FULL_HEIGHT * SPX_N) +#define SPX_PK_BYTES (2 * SPX_N) +#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) + +#include "shake_offsets.h" + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/shake_offsets.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/shake_offsets.h new file mode 100644 index 0000000000..6b28d95d91 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/shake_offsets.h @@ -0,0 +1,21 @@ +#ifndef SHAKE_OFFSETS_H_ +#define SHAKE_OFFSETS_H_ + +/* + * Offsets of various fields in the address structure when we use SHAKE as + * the Sphincs+ hash function + */ + +#define SPX_OFFSET_LAYER 3 /* The byte used to specify the Merkle tree layer */ +#define SPX_OFFSET_TREE 8 /* The start of the 8 byte field used to specify the tree */ +#define SPX_OFFSET_TYPE 19 /* The byte used to specify the hash type (reason) */ +#define SPX_OFFSET_KP_ADDR2 22 /* The high byte used to specify the key pair (which one-time signature) */ +#define SPX_OFFSET_KP_ADDR1 23 /* The low byte used to specify the key pair */ +#define SPX_OFFSET_CHAIN_ADDR 27 /* The byte used to specify the chain address (which Winternitz chain) */ +#define SPX_OFFSET_HASH_ADDR 31 /* The byte used to specify the hash address (where in the Winternitz chain) */ +#define SPX_OFFSET_TREE_HGT 27 /* The byte used to specify the height of this node in the FORS or Merkle tree */ +#define SPX_OFFSET_TREE_INDEX 28 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ + +#define SPX_SHAKE 1 + +#endif /* SHAKE_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/sign.c b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/sign.c new file mode 100644 index 0000000000..9d0c7d1b22 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/sign.c @@ -0,0 +1,286 @@ +#include +#include +#include + +#include "address.h" +#include "context.h" +#include "fors.h" +#include "hash.h" +#include "merkle.h" +#include "nistapi.h" +#include "params.h" +#include "randombytes.h" +#include "thash.h" +#include "utils.h" +#include "wots.h" + +/* + * Returns the length of a secret key, in bytes + */ +size_t crypto_sign_secretkeybytes(void) { + return CRYPTO_SECRETKEYBYTES; +} + +/* + * Returns the length of a public key, in bytes + */ +size_t crypto_sign_publickeybytes(void) { + return CRYPTO_PUBLICKEYBYTES; +} + +/* + * Returns the length of a signature, in bytes + */ +size_t crypto_sign_bytes(void) { + return CRYPTO_BYTES; +} + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +size_t crypto_sign_seedbytes(void) { + return CRYPTO_SEEDBYTES; +} + +/* + * Generates an SPX key pair given a seed of length + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [PUB_SEED || root] + */ +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed) { + spx_ctx ctx; + + /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ + memcpy(sk, seed, CRYPTO_SEEDBYTES); + + memcpy(pk, sk + 2 * SPX_N, SPX_N); + + memcpy(ctx.pub_seed, pk, SPX_N); + memcpy(ctx.sk_seed, sk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + /* Compute root node of the top-most subtree. */ + merkle_gen_root(sk + 3 * SPX_N, &ctx); + + // cleanup + free_hash_function(&ctx); + + memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); + + return 0; +} + +/* + * Generates an SPX key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [PUB_SEED || root] + */ +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { + uint8_t seed[CRYPTO_SEEDBYTES]; + randombytes(seed, CRYPTO_SEEDBYTES); + crypto_sign_seed_keypair(pk, sk, seed); + + return 0; +} + +/** + * Returns an array containing a detached signature. + */ +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk) { + spx_ctx ctx; + + const uint8_t *sk_prf = sk + SPX_N; + const uint8_t *pk = sk + 2 * SPX_N; + + uint8_t optrand[SPX_N]; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t root[SPX_N]; + uint32_t i; + uint64_t tree; + uint32_t idx_leaf; + uint32_t wots_addr[8] = {0}; + uint32_t tree_addr[8] = {0}; + + memcpy(ctx.sk_seed, sk, SPX_N); + memcpy(ctx.pub_seed, pk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + + /* Optionally, signing can be made non-deterministic using optrand. + This can help counter side-channel attacks that would benefit from + getting a large number of traces when the signer uses the same nodes. */ + randombytes(optrand, SPX_N); + /* Compute the digest randomization value. */ + gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); + + /* Derive the message digest and leaf index from R, PK and M. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; + + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); + + /* Sign the message hash using FORS. */ + fors_sign(sig, root, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); + sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; + + /* Update the indices for the next layer. */ + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; + } + + free_hash_function(&ctx); + + *siglen = SPX_BYTES; + + return 0; +} + +/** + * Verifies a detached signature and message under a given public key. + */ +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk) { + spx_ctx ctx; + const uint8_t *pub_root = pk + SPX_N; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t wots_pk[SPX_WOTS_BYTES]; + uint8_t root[SPX_N]; + uint8_t leaf[SPX_N]; + unsigned int i; + uint64_t tree; + uint32_t idx_leaf; + uint32_t wots_addr[8] = {0}; + uint32_t tree_addr[8] = {0}; + uint32_t wots_pk_addr[8] = {0}; + + if (siglen != SPX_BYTES) { + return -1; + } + + memcpy(ctx.pub_seed, pk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); + + /* Derive the message digest and leaf index from R || PK || M. */ + /* The additional SPX_N is a result of the hash domain separator. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; + + /* Layer correctly defaults to 0, so no need to set_layer_addr */ + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); + + fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + /* For each subtree.. */ + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + copy_keypair_addr(wots_pk_addr, wots_addr); + + /* The WOTS public key is only correct if the signature was correct. */ + /* Initially, root is the FORS pk, but on subsequent iterations it is + the root of the subtree below the currently processed subtree. */ + wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); + sig += SPX_WOTS_BYTES; + + /* Compute the leaf node using the WOTS public key. */ + thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); + + /* Compute the root node of this subtree. */ + compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, + &ctx, tree_addr); + sig += SPX_TREE_HEIGHT * SPX_N; + + /* Update the indices for the next layer. */ + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; + } + + // cleanup + free_hash_function(&ctx); + + /* Check if the root node equals the root node in the public key. */ + if (memcmp(root, pub_root, SPX_N) != 0) { + return -1; + } + + return 0; +} + + +/** + * Returns an array containing the signature followed by the message. + */ +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk) { + size_t siglen; + + crypto_sign_signature(sm, &siglen, m, mlen, sk); + + memmove(sm + SPX_BYTES, m, mlen); + *smlen = siglen + mlen; + + return 0; +} + +/** + * Verifies a given signature-message pair under a given public key. + */ +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk) { + /* The API caller does not necessarily know what size a signature should be + but SPHINCS+ signatures are always exactly SPX_BYTES. */ + if (smlen < SPX_BYTES) { + memset(m, 0, smlen); + *mlen = 0; + return -1; + } + + *mlen = smlen - SPX_BYTES; + + if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { + memset(m, 0, smlen); + *mlen = 0; + return -1; + } + + /* If verification was successful, move the message to the right place. */ + memmove(m, sm + SPX_BYTES, *mlen); + + return 0; +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/thash.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/thash.h new file mode 100644 index 0000000000..8687ccfb4d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/thash.h @@ -0,0 +1,13 @@ +#ifndef SPX_THASH_H +#define SPX_THASH_H + +#include "context.h" +#include "params.h" + +#include + +#define thash SPX_NAMESPACE(thash) +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/thash_shake_robust.c b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/thash_shake_robust.c new file mode 100644 index 0000000000..696d53c5cc --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/thash_shake_robust.c @@ -0,0 +1,31 @@ +#include +#include + +#include "thash.h" + +#include "address.h" +#include "params.h" +#include "utils.h" + +#include "fips202.h" + +/** + * Takes an array of inblocks concatenated arrays of SPX_N bytes. + */ +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]) { + PQCLEAN_VLA(uint8_t, buf, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); + PQCLEAN_VLA(uint8_t, bitmask, inblocks * SPX_N); + unsigned int i; + + memcpy(buf, ctx->pub_seed, SPX_N); + memcpy(buf + SPX_N, addr, SPX_ADDR_BYTES); + + shake256(bitmask, inblocks * SPX_N, buf, SPX_N + SPX_ADDR_BYTES); + + for (i = 0; i < inblocks * SPX_N; i++) { + buf[SPX_N + SPX_ADDR_BYTES + i] = in[i] ^ bitmask[i]; + } + + shake256(out, SPX_N, buf, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/thash_shake_robustx4.c b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/thash_shake_robustx4.c new file mode 100644 index 0000000000..ce2946b745 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/thash_shake_robustx4.c @@ -0,0 +1,131 @@ +#include +#include + +#include "thashx4.h" + +#include "address.h" +#include "params.h" +#include "utils.h" + +#include "fips202x4.h" + +extern void KeccakP1600times4_PermuteAll_24rounds(__m256i *s); + +/** + * 4-way parallel version of thash; takes 4x as much input and output + */ +void thashx4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addrx4[4 * 8]) { + if (inblocks == 1 || inblocks == 2) { + /* As we write and read only a few quadwords, it is more efficient to + * build and extract from the fourway SHAKE256 state by hand. */ + __m256i state[25]; + for (int i = 0; i < SPX_N / 8; i++) { + state[i] = _mm256_set1_epi64x(((int64_t *)ctx->pub_seed)[i]); + } + for (int i = 0; i < 4; i++) { + state[SPX_N / 8 + i] = _mm256_set_epi32( + (int)addrx4[3 * 8 + 1 + 2 * i], + (int)addrx4[3 * 8 + 2 * i], + (int)addrx4[2 * 8 + 1 + 2 * i], + (int)addrx4[2 * 8 + 2 * i], + (int)addrx4[8 + 1 + 2 * i], + (int)addrx4[8 + 2 * i], + (int)addrx4[1 + 2 * i], + (int)addrx4[2 * i] + ); + } + + /* SHAKE domain separator and padding */ + state[SPX_N / 8 + 4] = _mm256_set1_epi64x(0x1f); + for (int i = SPX_N / 8 + 5; i < 16; i++) { + state[i] = _mm256_set1_epi64x(0); + } + state[16] = _mm256_set1_epi64x((long long)(0x80ULL << 56)); + + for (int i = 17; i < 25; i++) { + state[i] = _mm256_set1_epi64x(0); + } + + /* We will permutate state2 with f1600x4 to compute the bitmask, + * but first we'll copy it to state2 which will be used to compute + * the final output, as its input is alsmost identical. */ + __m256i state2[25]; + memcpy(state2, state, 800); + + KeccakP1600times4_PermuteAll_24rounds(&state[0]); + + /* By copying from state, state2 already contains the pub_seed + * and addres. We just need to copy in the input blocks xorred with + * the bitmask we just computed. */ + for (unsigned int i = 0; i < (SPX_N / 8) * inblocks; i++) { + state2[SPX_N / 8 + 4 + i] = _mm256_xor_si256( + state[i], + _mm256_set_epi64x( + ((int64_t *)in3)[i], + ((int64_t *)in2)[i], + ((int64_t *)in1)[i], + ((int64_t *)in0)[i] + ) + ); + } + + /* Domain separator and start of padding. Note that the quadwords + * around are already zeroed for state from which we copied. + * We do a XOR instead of a set as this might be the 16th quadword + * when N=32 and inblocks=2, which already contains the end + * of the padding. */ + state2[(SPX_N / 8) * (1 + inblocks) + 4] = _mm256_xor_si256( + state2[(SPX_N / 8) * (1 + inblocks) + 4], + _mm256_set1_epi64x(0x1f) + ); + + KeccakP1600times4_PermuteAll_24rounds(&state2[0]); + + for (int i = 0; i < SPX_N / 8; i++) { + ((int64_t *)out0)[i] = _mm256_extract_epi64(state2[i], 0); + ((int64_t *)out1)[i] = _mm256_extract_epi64(state2[i], 1); + ((int64_t *)out2)[i] = _mm256_extract_epi64(state2[i], 2); + ((int64_t *)out3)[i] = _mm256_extract_epi64(state2[i], 3); + } + } else { + PQCLEAN_VLA(unsigned char, buf0, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, buf1, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, buf2, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, buf3, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, bitmask0, inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, bitmask1, inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, bitmask2, inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, bitmask3, inblocks * SPX_N); + unsigned int i; + + memcpy(buf0, ctx->pub_seed, SPX_N); + memcpy(buf1, ctx->pub_seed, SPX_N); + memcpy(buf2, ctx->pub_seed, SPX_N); + memcpy(buf3, ctx->pub_seed, SPX_N); + memcpy(buf0 + SPX_N, addrx4 + 0 * 8, SPX_ADDR_BYTES); + memcpy(buf1 + SPX_N, addrx4 + 1 * 8, SPX_ADDR_BYTES); + memcpy(buf2 + SPX_N, addrx4 + 2 * 8, SPX_ADDR_BYTES); + memcpy(buf3 + SPX_N, addrx4 + 3 * 8, SPX_ADDR_BYTES); + + shake256x4(bitmask0, bitmask1, bitmask2, bitmask3, inblocks * SPX_N, + buf0, buf1, buf2, buf3, SPX_N + SPX_ADDR_BYTES); + + for (i = 0; i < inblocks * SPX_N; i++) { + buf0[SPX_N + SPX_ADDR_BYTES + i] = in0[i] ^ bitmask0[i]; + buf1[SPX_N + SPX_ADDR_BYTES + i] = in1[i] ^ bitmask1[i]; + buf2[SPX_N + SPX_ADDR_BYTES + i] = in2[i] ^ bitmask2[i]; + buf3[SPX_N + SPX_ADDR_BYTES + i] = in3[i] ^ bitmask3[i]; + } + + shake256x4(out0, out1, out2, out3, SPX_N, + buf0, buf1, buf2, buf3, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/thashx4.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/thashx4.h new file mode 100644 index 0000000000..64798a3727 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/thashx4.h @@ -0,0 +1,20 @@ +#ifndef SPX_THASHX4_H +#define SPX_THASHX4_H + +#include + +#include "context.h" +#include "params.h" + +#define thashx4 SPX_NAMESPACE(thashx4) +void thashx4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addrx4[4 * 8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/utils.c b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/utils.c new file mode 100644 index 0000000000..177b541fb9 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/utils.c @@ -0,0 +1,148 @@ +#include + +#include "utils.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "thash.h" + +/** + * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. + */ +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in) { + int i; + + /* Iterate over out in decreasing order, for big-endianness. */ + for (i = (signed int)outlen - 1; i >= 0; i--) { + out[i] = in & 0xff; + in = in >> 8; + } +} + +void u32_to_bytes(unsigned char *out, uint32_t in) { + out[0] = (unsigned char)(in >> 24); + out[1] = (unsigned char)(in >> 16); + out[2] = (unsigned char)(in >> 8); + out[3] = (unsigned char)in; +} + +/** + * Converts the inlen bytes in 'in' from big-endian byte order to an integer. + */ +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { + unsigned long long retval = 0; + unsigned int i; + + for (i = 0; i < inlen; i++) { + retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); + } + return retval; +} + +/** + * Computes a root node given a leaf and an auth path. + * Expects address to be complete other than the tree_height and tree_index. + */ +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]) { + uint32_t i; + unsigned char buffer[2 * SPX_N]; + + /* If leaf_idx is odd (last bit = 1), current path element is a right child + and auth_path has to go left. Otherwise it is the other way around. */ + if (leaf_idx & 1) { + memcpy(buffer + SPX_N, leaf, SPX_N); + memcpy(buffer, auth_path, SPX_N); + } else { + memcpy(buffer, leaf, SPX_N); + memcpy(buffer + SPX_N, auth_path, SPX_N); + } + auth_path += SPX_N; + + for (i = 0; i < tree_height - 1; i++) { + leaf_idx >>= 1; + idx_offset >>= 1; + /* Set the address of the node we're creating. */ + set_tree_height(addr, i + 1); + set_tree_index(addr, leaf_idx + idx_offset); + + /* Pick the right or left neighbor, depending on parity of the node. */ + if (leaf_idx & 1) { + thash(buffer + SPX_N, buffer, 2, ctx, addr); + memcpy(buffer, auth_path, SPX_N); + } else { + thash(buffer, buffer, 2, ctx, addr); + memcpy(buffer + SPX_N, auth_path, SPX_N); + } + auth_path += SPX_N; + } + + /* The last iteration is exceptional; we do not copy an auth_path node. */ + leaf_idx >>= 1; + idx_offset >>= 1; + set_tree_height(addr, tree_height); + set_tree_index(addr, leaf_idx + idx_offset); + thash(root, buffer, 2, ctx, addr); +} + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx * /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]) { + PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); + PQCLEAN_VLA(unsigned int, heights, tree_height + 1); + unsigned int offset = 0; + uint32_t idx; + uint32_t tree_idx; + + for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { + /* Add the next leaf node to the stack. */ + gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); + offset++; + heights[offset - 1] = 0; + + /* If this is a node we need for the auth path.. */ + if ((leaf_idx ^ 0x1) == idx) { + memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); + } + + /* While the top-most nodes are of equal height.. */ + while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { + /* Compute index of the new node, in the next layer. */ + tree_idx = (idx >> (heights[offset - 1] + 1)); + + /* Set the address of the node we're creating. */ + set_tree_height(tree_addr, heights[offset - 1] + 1); + set_tree_index(tree_addr, + tree_idx + (idx_offset >> (heights[offset - 1] + 1))); + /* Hash the top-most nodes from the stack together. */ + thash(stack + (offset - 2)*SPX_N, + stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); + offset--; + /* Note that the top-most node is now one layer higher. */ + heights[offset - 1]++; + + /* If this is a node we need for the auth path.. */ + if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { + memcpy(auth_path + heights[offset - 1]*SPX_N, + stack + (offset - 1)*SPX_N, SPX_N); + } + } + } + memcpy(root, stack, SPX_N); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/utils.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/utils.h new file mode 100644 index 0000000000..64f5d5a53a --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/utils.h @@ -0,0 +1,58 @@ +#ifndef SPX_UTILS_H +#define SPX_UTILS_H + +#include + +#include "compat.h" +#include "context.h" +#include "params.h" + + +/* To support MSVC use alloca() instead of VLAs. See #20. */ + + +/** + * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. + */ +#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in); +#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) +void u32_to_bytes(unsigned char *out, uint32_t in); + +/** + * Converts the inlen bytes in 'in' from big-endian byte order to an integer. + */ +#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); + +/** + * Computes a root node given a leaf and an auth path. + * Expects address to be complete other than the tree_height and tree_index. + */ +#define compute_root SPX_NAMESPACE(compute_root) +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]); + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +#define treehash SPX_NAMESPACE(treehash) +void treehash(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx *ctx /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]); + + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/utilsx4.c b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/utilsx4.c new file mode 100644 index 0000000000..1638677194 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/utilsx4.c @@ -0,0 +1,138 @@ +#include + +#include "utilsx4.h" + +#include "address.h" +#include "params.h" +#include "thashx4.h" +#include "utils.h" + +/* + * Generate the entire Merkle tree, computing the authentication path for leaf_idx, + * and the resulting root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) + * + * This expects tree_addrx4 to be initialized to 4 parallel addr structures for + * the Merkle tree nodes + * + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + * + * This works by using the standard Merkle tree building algorithm, except + * that each 'node' tracked is actually 4 consecutive nodes in the real tree. + * When we combine two logical nodes ABCD and WXYZ, we perform the H + * operation on adjacent real nodes, forming the parent logical node + * (AB)(CD)(WX)(YZ) + * + * When we get to the top two levels of the real tree (where there is only + * one logical node), we continue this operation two more times; the right + * most real node will by the actual root (and the other 3 nodes will be + * garbage). We follow the same thashx4 logic so that the 'extract + * authentication path components' part of the loop is still executed (and + * to simplify the code somewhat) + * + * This currently assumes tree_height >= 2; I suspect that doing an adjusting + * idx, addr_idx on the gen_leafx4 call if tree_height < 2 would fix it; since + * we don't actually use such short trees, I haven't bothered + */ +void treehashx4(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, + uint32_t tree_height, + void (*gen_leafx4)( + unsigned char * /* Where to write the leaves */, + const spx_ctx *, + uint32_t idx, void *info), + uint32_t tree_addrx4[4 * 8], + void *info) { + /* This is where we keep the intermediate nodes */ + PQCLEAN_VLA(unsigned char, stackx4, tree_height * 4 * SPX_N); + uint32_t left_adj = 0, prev_left_adj = 0; /* When we're doing the top 3 */ + /* levels, the left-most part of the tree isn't at the beginning */ + /* of current[]. These give the offset of the actual start */ + + uint32_t idx; + uint32_t max_idx = (1U << (tree_height - 2)) - 1; + for (idx = 0;; idx++) { + unsigned char current[4 * SPX_N]; /* Current logical node */ + gen_leafx4( current, ctx, 4 * idx + idx_offset, + info ); + + /* Now combine the freshly generated right node with previously */ + /* generated left ones */ + uint32_t internal_idx_offset = idx_offset; + uint32_t internal_idx = idx; + uint32_t internal_leaf = leaf_idx; + uint32_t h; /* The height we are in the Merkle tree */ + for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { + + /* Special processing if we're at the top of the tree */ + if (h >= tree_height - 2) { + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[3 * SPX_N], SPX_N ); + return; + } + /* The tree indexing logic is a bit off in this case */ + /* Adjust it so that the left-most node of the part of */ + /* the tree that we're processing has index 0 */ + prev_left_adj = left_adj; + left_adj = 4U - (1 << (tree_height - h - 1)); + } + + /* Check if we hit the top of the tree */ + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[3 * SPX_N], SPX_N ); + return; + } + + /* + * Check if one of the nodes we have is a part of the + * authentication path; if it is, write it out + */ + if ((((internal_idx << 2) ^ internal_leaf) & ~0x3U) == 0) { + memcpy( &auth_path[ h * SPX_N ], + ¤t[(((internal_leaf & 3) ^ 1) + prev_left_adj) * SPX_N], + SPX_N ); + } + + /* + * Check if we're at a left child; if so, stop going up the stack + * Exception: if we've reached the end of the tree, keep on going + * (so we combine the last 4 nodes into the one root node in two + * more iterations) + */ + if ((internal_idx & 1) == 0 && idx < max_idx) { + break; + } + + /* Ok, we're at a right node (or doing the top 3 levels) */ + /* Now combine the left and right logical nodes together */ + + /* Set the address of the node we're creating. */ + unsigned int j; + internal_idx_offset >>= 1; + for (j = 0; j < 4; j++) { + set_tree_height(tree_addrx4 + j * 8, h + 1); + set_tree_index(tree_addrx4 + j * 8, + (4 / 2) * (internal_idx & ~1U) + j - left_adj + internal_idx_offset ); + } + unsigned char *left = &stackx4[h * 4 * SPX_N]; + thashx4( ¤t[0 * SPX_N], + ¤t[1 * SPX_N], + ¤t[2 * SPX_N], + ¤t[3 * SPX_N], + &left [0 * SPX_N], + &left [2 * SPX_N], + ¤t[0 * SPX_N], + ¤t[2 * SPX_N], + 2, ctx, tree_addrx4); + } + + /* We've hit a left child; save the current for when we get the */ + /* corresponding right right */ + memcpy( &stackx4[h * 4 * SPX_N], current, 4 * SPX_N); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/utilsx4.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/utilsx4.h new file mode 100644 index 0000000000..facb874b18 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/utilsx4.h @@ -0,0 +1,30 @@ +#ifndef SPX_UTILSX4_H +#define SPX_UTILSX4_H + +#include + +#include "context.h" +#include "params.h" + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + * + * This implementation uses AVX to compute internal nodes 4 at a time (in + * parallel) + */ +#define treehashx4 SPX_NAMESPACE(treehashx4) +void treehashx4(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leafx4)( + unsigned char * /* Where to write the leaves */, + const spx_ctx * /* ctx */, + uint32_t addr_idx, void *info), + uint32_t tree_addrx4[4 * 8], void *info); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/wots.c b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/wots.c new file mode 100644 index 0000000000..4d5041ce05 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/wots.c @@ -0,0 +1,269 @@ +#include +#include + +#include "wots.h" + +#include "address.h" +#include "hash.h" +#include "hashx4.h" +#include "params.h" +#include "thash.h" +#include "thashx4.h" +#include "utils.h" +#include "utilsx4.h" +#include "wotsx4.h" + +// TODO clarify address expectations, and make them more uniform. +// TODO i.e. do we expect types to be set already? +// TODO and do we expect modifications or copies? + +/** + * Computes up the chains + */ +static void gen_chains( + unsigned char *out, + const unsigned char *in, + unsigned int start[SPX_WOTS_LEN], + const unsigned int steps[SPX_WOTS_LEN], + const spx_ctx *ctx, + uint32_t addr[8]) { + uint32_t i, j, k, idx, watching; + int done; + unsigned char empty[SPX_N]; + unsigned char *bufs[4]; + uint32_t addrs[8 * 4]; + + int l; + uint16_t counts[SPX_WOTS_W] = { 0 }; + uint16_t idxs[SPX_WOTS_LEN]; + uint16_t total, newTotal; + + /* set addrs = {addr, addr, addr, addr} */ + for (j = 0; j < 4; j++) { + memcpy(addrs + j * 8, addr, sizeof(uint32_t) * 8); + } + + /* Initialize out with the value at position 'start'. */ + memcpy(out, in, SPX_WOTS_LEN * SPX_N); + + /* Sort the chains in reverse order by steps using counting sort. */ + for (i = 0; i < SPX_WOTS_LEN; i++) { + counts[steps[i]]++; + } + total = 0; + for (l = SPX_WOTS_W - 1; l >= 0; l--) { + newTotal = counts[l] + total; + counts[l] = total; + total = newTotal; + } + for (i = 0; i < SPX_WOTS_LEN; i++) { + idxs[counts[steps[i]]] = (uint16_t)i; + counts[steps[i]]++; + } + + /* We got our work cut out for us: do it! */ + for (i = 0; i < SPX_WOTS_LEN; i += 4) { + for (j = 0; j < 4 && i + j < SPX_WOTS_LEN; j++) { + idx = idxs[i + j]; + set_chain_addr(addrs + j * 8, idx); + bufs[j] = out + SPX_N * idx; + } + + /* As the chains are sorted in reverse order, we know that the first + * chain is the longest and the last one is the shortest. We keep + * an eye on whether the last chain is done and then on the one before, + * et cetera. */ + watching = 3; + done = 0; + while (i + watching >= SPX_WOTS_LEN) { + bufs[watching] = &empty[0]; + watching--; + } + + for (k = 0;; k++) { + while (k == steps[idxs[i + watching]]) { + bufs[watching] = &empty[0]; + if (watching == 0) { + done = 1; + break; + } + watching--; + } + if (done) { + break; + } + for (j = 0; j < watching + 1; j++) { + set_hash_addr(addrs + j * 8, k + start[idxs[i + j]]); + } + + thashx4(bufs[0], bufs[1], bufs[2], bufs[3], + bufs[0], bufs[1], bufs[2], bufs[3], 1, ctx, addrs); + } + } +} + +/** + * base_w algorithm as described in draft. + * Interprets an array of bytes as integers in base w. + * This only works when log_w is a divisor of 8. + */ +static void base_w(unsigned int *output, const int out_len, + const unsigned char *input) { + int in = 0; + int out = 0; + unsigned char total = 0; + int bits = 0; + int consumed; + + for (consumed = 0; consumed < out_len; consumed++) { + if (bits == 0) { + total = input[in]; + in++; + bits += 8; + } + bits -= SPX_WOTS_LOGW; + output[out] = (total >> bits) & (SPX_WOTS_W - 1); + out++; + } +} + +/* Computes the WOTS+ checksum over a message (in base_w). */ +static void wots_checksum(unsigned int *csum_base_w, + const unsigned int *msg_base_w) { + unsigned int csum = 0; + unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; + unsigned int i; + + /* Compute checksum. */ + for (i = 0; i < SPX_WOTS_LEN1; i++) { + csum += SPX_WOTS_W - 1 - msg_base_w[i]; + } + + /* Convert checksum to base_w. */ + /* Make sure expected empty zero bits are the least significant bits. */ + csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); + ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); + base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); +} + +/* Takes a message and derives the matching chain lengths. */ +void chain_lengths(unsigned int *lengths, const unsigned char *msg) { + base_w(lengths, SPX_WOTS_LEN1, msg); + wots_checksum(lengths + SPX_WOTS_LEN1, lengths); +} + +/** + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. + * + * Writes the computed public key to 'pk'. + */ +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]) { + unsigned int steps[SPX_WOTS_LEN]; + unsigned int start[SPX_WOTS_LEN]; + uint32_t i; + + chain_lengths(start, msg); + + for (i = 0; i < SPX_WOTS_LEN; i++) { + steps[i] = SPX_WOTS_W - 1 - start[i]; + } + + gen_chains(pk, sig, start, steps, ctx, addr); +} + +/* + * This generates 4 sequential WOTS public keys + * It also generates the WOTS signature if leaf_info indicates + * that we're signing with one of these WOTS keys + */ +void wots_gen_leafx4(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info) { + struct leaf_info_x4 *info = v_info; + uint32_t *leaf_addr = info->leaf_addr; + uint32_t *pk_addr = info->pk_addr; + unsigned int i, j, k; + unsigned char pk_buffer[ 4 * SPX_WOTS_BYTES ]; + unsigned wots_offset = SPX_WOTS_BYTES; + unsigned char *buffer; + uint32_t wots_k_mask; + unsigned wots_sign_index; + + if (((leaf_idx ^ info->wots_sign_leaf) & ~3U) == 0) { + /* We're traversing the leaf that's signing; generate the WOTS */ + /* signature */ + wots_k_mask = 0; + wots_sign_index = info->wots_sign_leaf & 3; /* Which of of the 4 */ + /* 4 slots do the signatures come from */ + } else { + /* Nope, we're just generating pk's; turn off the signature logic */ + wots_k_mask = (uint32_t)~0; + wots_sign_index = 0; + } + + for (j = 0; j < 4; j++) { + set_keypair_addr( leaf_addr + j * 8, leaf_idx + j ); + set_keypair_addr( pk_addr + j * 8, leaf_idx + j ); + } + + for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { + uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k to */ + /* the step if we're generating a signature, ~0 if we're not */ + + /* Start with the secret seed */ + for (j = 0; j < 4; j++) { + set_chain_addr(leaf_addr + j * 8, i); + set_hash_addr(leaf_addr + j * 8, 0); + set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTSPRF); + } + prf_addrx4(buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + buffer + 2 * wots_offset, + buffer + 3 * wots_offset, + ctx, leaf_addr); + + for (j = 0; j < 4; j++) { + set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTS); + } + + /* Iterate down the WOTS chain */ + for (k = 0;; k++) { + /* Check if one of the values we have needs to be saved as a */ + /* part of the WOTS signature */ + if (k == wots_k) { + memcpy( info->wots_sig + i * SPX_N, + buffer + wots_sign_index * wots_offset, SPX_N ); + } + + /* Check if we hit the top of the chain */ + if (k == SPX_WOTS_W - 1) { + break; + } + + /* Iterate one step on all 4 chains */ + for (j = 0; j < 4; j++) { + set_hash_addr(leaf_addr + j * 8, k); + } + thashx4(buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + buffer + 2 * wots_offset, + buffer + 3 * wots_offset, + buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + buffer + 2 * wots_offset, + buffer + 3 * wots_offset, 1, ctx, leaf_addr); + } + } + + /* Do the final thash to generate the public keys */ + thashx4(dest + 0 * SPX_N, + dest + 1 * SPX_N, + dest + 2 * SPX_N, + dest + 3 * SPX_N, + pk_buffer + 0 * wots_offset, + pk_buffer + 1 * wots_offset, + pk_buffer + 2 * wots_offset, + pk_buffer + 3 * wots_offset, SPX_WOTS_LEN, ctx, pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/wots.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/wots.h new file mode 100644 index 0000000000..4e7692eeef --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/wots.h @@ -0,0 +1,25 @@ +#ifndef SPX_WOTS_H +#define SPX_WOTS_H + +#include + +#include "context.h" +#include "params.h" + +/** + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. + * + * Writes the computed public key to 'pk'. + */ +#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]); + +/* + * Compute the chain lengths needed for a given message hash + */ +#define chain_lengths SPX_NAMESPACE(chain_lengths) +void chain_lengths(unsigned int *lengths, const unsigned char *msg); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/wotsx4.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/wotsx4.h new file mode 100644 index 0000000000..cd634f1743 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/wotsx4.h @@ -0,0 +1,41 @@ +#ifndef WOTSX4_H_ +#define WOTSX4_H_ + +#include + +#include "params.h" + +/* + * This is here to provide an interface to the internal wots_gen_leafx4 + * routine. While this routine is not referenced in the package outside of + * wots.c, it is called from the stand-alone benchmark code to characterize + * the performance + */ +struct leaf_info_x4 { + unsigned char *wots_sig; + uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ + uint32_t *wots_steps; + uint32_t leaf_addr[4 * 8]; + uint32_t pk_addr[4 * 8]; +}; + +/* Macro to set the leaf_info to something 'benign', that is, it would */ +/* run with the same time as it does during the real signing process */ +/* Used only by the benchmark code */ +#define INITIALIZE_LEAF_INFO_X4(info, addr, step_buffer) { \ + (info).wots_sig = 0; \ + (info).wots_sign_leaf = ~0; \ + (info).wots_steps = step_buffer; \ + int i; \ + for (i=0; i<4; i++) { \ + memcpy( &(info).leaf_addr[8*i], addr, 32 ); \ + memcpy( &(info).pk_addr[8*i], addr, 32 ); \ + } \ + } + +#define wots_gen_leafx4 SPX_NAMESPACE(wots_gen_leafx4) +void wots_gen_leafx4(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info); + +#endif /* WOTSX4_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/LICENSE b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/LICENSE new file mode 100644 index 0000000000..670154e353 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/LICENSE @@ -0,0 +1,116 @@ +CC0 1.0 Universal + +Statement of Purpose + +The laws of most jurisdictions throughout the world automatically confer +exclusive Copyright and Related Rights (defined below) upon the creator and +subsequent owner(s) (each and all, an "owner") of an original work of +authorship and/or a database (each, a "Work"). + +Certain owners wish to permanently relinquish those rights to a Work for the +purpose of contributing to a commons of creative, cultural and scientific +works ("Commons") that the public can reliably and without fear of later +claims of infringement build upon, modify, incorporate in other works, reuse +and redistribute as freely as possible in any form whatsoever and for any +purposes, including without limitation commercial purposes. These owners may +contribute to the Commons to promote the ideal of a free culture and the +further production of creative, cultural and scientific works, or to gain +reputation or greater distribution for their Work in part through the use and +efforts of others. + +For these and/or other purposes and motivations, and without any expectation +of additional consideration or compensation, the person associating CC0 with a +Work (the "Affirmer"), to the extent that he or she is an owner of Copyright +and Related Rights in the Work, voluntarily elects to apply CC0 to the Work +and publicly distribute the Work under its terms, with knowledge of his or her +Copyright and Related Rights in the Work and the meaning and intended legal +effect of CC0 on those rights. + +1. Copyright and Related Rights. A Work made available under CC0 may be +protected by copyright and related or neighboring rights ("Copyright and +Related Rights"). Copyright and Related Rights include, but are not limited +to, the following: + + i. the right to reproduce, adapt, distribute, perform, display, communicate, + and translate a Work; + + ii. moral rights retained by the original author(s) and/or performer(s); + + iii. publicity and privacy rights pertaining to a person's image or likeness + depicted in a Work; + + iv. rights protecting against unfair competition in regards to a Work, + subject to the limitations in paragraph 4(a), below; + + v. rights protecting the extraction, dissemination, use and reuse of data in + a Work; + + vi. database rights (such as those arising under Directive 96/9/EC of the + European Parliament and of the Council of 11 March 1996 on the legal + protection of databases, and under any national implementation thereof, + including any amended or successor version of such directive); and + + vii. other similar, equivalent or corresponding rights throughout the world + based on applicable law or treaty, and any national implementations thereof. + +2. Waiver. To the greatest extent permitted by, but not in contravention of, +applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and +unconditionally waives, abandons, and surrenders all of Affirmer's Copyright +and Related Rights and associated claims and causes of action, whether now +known or unknown (including existing as well as future claims and causes of +action), in the Work (i) in all territories worldwide, (ii) for the maximum +duration provided by applicable law or treaty (including future time +extensions), (iii) in any current or future medium and for any number of +copies, and (iv) for any purpose whatsoever, including without limitation +commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes +the Waiver for the benefit of each member of the public at large and to the +detriment of Affirmer's heirs and successors, fully intending that such Waiver +shall not be subject to revocation, rescission, cancellation, termination, or +any other legal or equitable action to disrupt the quiet enjoyment of the Work +by the public as contemplated by Affirmer's express Statement of Purpose. + +3. Public License Fallback. Should any part of the Waiver for any reason be +judged legally invalid or ineffective under applicable law, then the Waiver +shall be preserved to the maximum extent permitted taking into account +Affirmer's express Statement of Purpose. In addition, to the extent the Waiver +is so judged Affirmer hereby grants to each affected person a royalty-free, +non transferable, non sublicensable, non exclusive, irrevocable and +unconditional license to exercise Affirmer's Copyright and Related Rights in +the Work (i) in all territories worldwide, (ii) for the maximum duration +provided by applicable law or treaty (including future time extensions), (iii) +in any current or future medium and for any number of copies, and (iv) for any +purpose whatsoever, including without limitation commercial, advertising or +promotional purposes (the "License"). The License shall be deemed effective as +of the date CC0 was applied by Affirmer to the Work. Should any part of the +License for any reason be judged legally invalid or ineffective under +applicable law, such partial invalidity or ineffectiveness shall not +invalidate the remainder of the License, and in such case Affirmer hereby +affirms that he or she will not (i) exercise any of his or her remaining +Copyright and Related Rights in the Work or (ii) assert any associated claims +and causes of action with respect to the Work, in either case contrary to +Affirmer's express Statement of Purpose. + +4. Limitations and Disclaimers. + + a. No trademark or patent rights held by Affirmer are waived, abandoned, + surrendered, licensed or otherwise affected by this document. + + b. Affirmer offers the Work as-is and makes no representations or warranties + of any kind concerning the Work, express, implied, statutory or otherwise, + including without limitation warranties of title, merchantability, fitness + for a particular purpose, non infringement, or the absence of latent or + other defects, accuracy, or the present or absence of errors, whether or not + discoverable, all to the greatest extent permissible under applicable law. + + c. Affirmer disclaims responsibility for clearing rights of other persons + that may apply to the Work or any use thereof, including without limitation + any person's Copyright and Related Rights in the Work. Further, Affirmer + disclaims responsibility for obtaining any necessary consents, permissions + or other rights required for any use of the Work. + + d. Affirmer understands and acknowledges that Creative Commons is not a + party to this document and has no duty or obligation with respect to this + CC0 or use of the Work. + +For more information, please see + diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/address.c b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/address.c new file mode 100644 index 0000000000..d49d9f3b6b --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/address.c @@ -0,0 +1,95 @@ +#include +#include + +#include "address.h" +#include "params.h" +#include "utils.h" + +/* + * Specify which level of Merkle tree (the "layer") we're working on + */ +void set_layer_addr(uint32_t addr[8], uint32_t layer) { + ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; +} + +/* + * Specify which Merkle tree within the level (the "tree address") we're working on + */ +void set_tree_addr(uint32_t addr[8], uint64_t tree) { + ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); +} + +/* + * Specify the reason we'll use this address structure for, that is, what + * hash will we compute with it. This is used so that unrelated types of + * hashes don't accidentally get the same address structure. The type will be + * one of the SPX_ADDR_TYPE constants + */ +void set_type(uint32_t addr[8], uint32_t type) { + ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; +} + +/* + * Copy the layer and tree fields of the address structure. This is used + * when we're doing multiple types of hashes within the same Merkle tree + */ +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); +} + +/* These functions are used for OTS addresses. */ + +/* + * Specify which Merkle leaf we're working on; that is, which OTS keypair + * we're talking about. + */ +void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { + /* We have > 256 OTS at the bottom of the Merkle tree; to specify */ + /* which one, we'd need to express it in two bytes */ + ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR2] = (unsigned char)(keypair >> 8); + ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; +} + +/* + * Copy the layer, tree and keypair fields of the address structure. This is + * used when we're doing multiple things within the same OTS keypair + */ +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); + ((unsigned char *)out)[SPX_OFFSET_KP_ADDR2] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR2]; + ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; +} + +/* + * Specify which Merkle chain within the OTS we're working with + * (the chain address) + */ +void set_chain_addr(uint32_t addr[8], uint32_t chain) { + ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; +} + +/* + * Specify where in the Merkle chain we are +* (the hash address) + */ +void set_hash_addr(uint32_t addr[8], uint32_t hash) { + ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; +} + +/* These functions are used for all hash tree addresses (including FORS). */ + +/* + * Specify the height of the node in the Merkle/FORS tree we are in + * (the tree height) + */ +void set_tree_height(uint32_t addr[8], uint32_t tree_height) { + ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; +} + +/* + * Specify the distance from the left edge of the node in the Merkle/FORS tree + * (the tree index) + */ +void set_tree_index(uint32_t addr[8], uint32_t tree_index) { + u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/address.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/address.h new file mode 100644 index 0000000000..24a84eb40c --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/address.h @@ -0,0 +1,52 @@ +#ifndef SPX_ADDRESS_H +#define SPX_ADDRESS_H + +#include + +#include "params.h" + +/* The hash types that are passed to set_type */ +#define SPX_ADDR_TYPE_WOTS 0 +#define SPX_ADDR_TYPE_WOTSPK 1 +#define SPX_ADDR_TYPE_HASHTREE 2 +#define SPX_ADDR_TYPE_FORSTREE 3 +#define SPX_ADDR_TYPE_FORSPK 4 +#define SPX_ADDR_TYPE_WOTSPRF 5 +#define SPX_ADDR_TYPE_FORSPRF 6 + +#define set_layer_addr SPX_NAMESPACE(set_layer_addr) +void set_layer_addr(uint32_t addr[8], uint32_t layer); + +#define set_tree_addr SPX_NAMESPACE(set_tree_addr) +void set_tree_addr(uint32_t addr[8], uint64_t tree); + +#define set_type SPX_NAMESPACE(set_type) +void set_type(uint32_t addr[8], uint32_t type); + +/* Copies the layer and tree part of one address into the other */ +#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); + +/* These functions are used for WOTS and FORS addresses. */ + +#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) +void set_keypair_addr(uint32_t addr[8], uint32_t keypair); + +#define set_chain_addr SPX_NAMESPACE(set_chain_addr) +void set_chain_addr(uint32_t addr[8], uint32_t chain); + +#define set_hash_addr SPX_NAMESPACE(set_hash_addr) +void set_hash_addr(uint32_t addr[8], uint32_t hash); + +#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); + +/* These functions are used for all hash tree addresses (including FORS). */ + +#define set_tree_height SPX_NAMESPACE(set_tree_height) +void set_tree_height(uint32_t addr[8], uint32_t tree_height); + +#define set_tree_index SPX_NAMESPACE(set_tree_index) +void set_tree_index(uint32_t addr[8], uint32_t tree_index); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/api.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/api.h new file mode 100644 index 0000000000..3b1a5a9f0c --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/api.h @@ -0,0 +1,77 @@ +#ifndef PQCLEAN_SPHINCSSHAKE128SROBUST_CLEAN_API_H +#define PQCLEAN_SPHINCSSHAKE128SROBUST_CLEAN_API_H + +#include +#include + +#define PQCLEAN_SPHINCSSHAKE128SROBUST_CLEAN_CRYPTO_ALGNAME "SPHINCS+-shake-128s-robust" + +#define PQCLEAN_SPHINCSSHAKE128SROBUST_CLEAN_CRYPTO_SECRETKEYBYTES 64 +#define PQCLEAN_SPHINCSSHAKE128SROBUST_CLEAN_CRYPTO_PUBLICKEYBYTES 32 +#define PQCLEAN_SPHINCSSHAKE128SROBUST_CLEAN_CRYPTO_BYTES 7856 + +#define PQCLEAN_SPHINCSSHAKE128SROBUST_CLEAN_CRYPTO_SEEDBYTES 48 + +/* + * Returns the length of a secret key, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE128SROBUST_CLEAN_crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE128SROBUST_CLEAN_crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE128SROBUST_CLEAN_crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE128SROBUST_CLEAN_crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +int PQCLEAN_SPHINCSSHAKE128SROBUST_CLEAN_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +int PQCLEAN_SPHINCSSHAKE128SROBUST_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +int PQCLEAN_SPHINCSSHAKE128SROBUST_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +int PQCLEAN_SPHINCSSHAKE128SROBUST_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, + const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +int PQCLEAN_SPHINCSSHAKE128SROBUST_CLEAN_crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +int PQCLEAN_SPHINCSSHAKE128SROBUST_CLEAN_crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/context.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/context.h new file mode 100644 index 0000000000..9f8a40ab4e --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/context.h @@ -0,0 +1,22 @@ +#ifndef SPX_CONTEXT_H +#define SPX_CONTEXT_H + +#include +#include + +#include "params.h" + +typedef struct { + uint8_t pub_seed[SPX_N]; + uint8_t sk_seed[SPX_N]; + + +} spx_ctx; + +#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) +void initialize_hash_function(spx_ctx *ctx); + +#define free_hash_function SPX_NAMESPACE(free_hash_function) +void free_hash_function(spx_ctx *ctx); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/context_shake.c b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/context_shake.c new file mode 100644 index 0000000000..9614a103d3 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/context_shake.c @@ -0,0 +1,12 @@ +#include "context.h" + +/* For SHAKE256, there is no immediate reason to initialize at the start, + so this function is an empty operation. */ +void initialize_hash_function(spx_ctx *ctx) { + (void)ctx; /* Suppress an 'unused parameter' warning. */ +} + +// in case the hash function api is heap-based. +void free_hash_function(spx_ctx *ctx) { + (void)ctx; +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/fors.c b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/fors.c new file mode 100644 index 0000000000..96ca72e986 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/fors.c @@ -0,0 +1,156 @@ +#include +#include +#include + +#include "fors.h" + +#include "address.h" +#include "hash.h" +#include "thash.h" +#include "utils.h" +#include "utilsx1.h" + +static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + prf_addr(sk, ctx, fors_leaf_addr); +} + +static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, + const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + thash(leaf, sk, 1, ctx, fors_leaf_addr); +} + +struct fors_gen_leaf_info { + uint32_t leaf_addrx[8]; +}; + +static void fors_gen_leafx1(unsigned char *leaf, + const spx_ctx *ctx, + uint32_t addr_idx, void *info) { + struct fors_gen_leaf_info *fors_info = info; + uint32_t *fors_leaf_addr = fors_info->leaf_addrx; + + /* Only set the parts that the caller doesn't set */ + set_tree_index(fors_leaf_addr, addr_idx); + set_type(fors_leaf_addr, SPX_ADDR_TYPE_FORSPRF); + fors_gen_sk(leaf, ctx, fors_leaf_addr); + + set_type(fors_leaf_addr, SPX_ADDR_TYPE_FORSTREE); + fors_sk_to_leaf(leaf, leaf, + ctx, fors_leaf_addr); +} + +/** + * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + * Assumes indices has space for SPX_FORS_TREES integers. + */ +static void message_to_indices(uint32_t *indices, const unsigned char *m) { + unsigned int i, j; + unsigned int offset = 0; + + for (i = 0; i < SPX_FORS_TREES; i++) { + indices[i] = 0; + for (j = 0; j < SPX_FORS_HEIGHT; j++) { + indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); + offset++; + } + } +} + +/** + * Signs a message m, deriving the secret key from sk_seed and the FTS address. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + uint32_t fors_tree_addr[8] = {0}; + struct fors_gen_leaf_info fors_info = {0}; + uint32_t *fors_leaf_addr = fors_info.leaf_addrx; + uint32_t fors_pk_addr[8] = {0}; + uint32_t idx_offset; + unsigned int i; + + copy_keypair_addr(fors_tree_addr, fors_addr); + copy_keypair_addr(fors_leaf_addr, fors_addr); + + copy_keypair_addr(fors_pk_addr, fors_addr); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); + + message_to_indices(indices, m); + + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); + + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); + + /* Include the secret key part that produces the selected leaf node. */ + fors_gen_sk(sig, ctx, fors_tree_addr); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + sig += SPX_N; + + /* Compute the authentication path for this leaf node. */ + treehashx1(roots + i * SPX_N, sig, ctx, + indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx1, + fors_tree_addr, &fors_info); + + sig += SPX_N * SPX_FORS_HEIGHT; + } + + /* Hash horizontally across all tree roots to derive the public key. */ + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); +} + +/** + * Derives the FORS public key from a signature. + * This can be used for verification by comparing to a known public key, or to + * subsequently verify a signature on the derived public key. The latter is the + * typical use-case when used as an FTS below an OTS in a hypertree. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + unsigned char leaf[SPX_N]; + uint32_t fors_tree_addr[8] = {0}; + uint32_t fors_pk_addr[8] = {0}; + uint32_t idx_offset; + unsigned int i; + + copy_keypair_addr(fors_tree_addr, fors_addr); + copy_keypair_addr(fors_pk_addr, fors_addr); + + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); + + message_to_indices(indices, m); + + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); + + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + + /* Derive the leaf from the included secret key part. */ + fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); + sig += SPX_N; + + /* Derive the corresponding root node of this tree. */ + compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, + sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); + sig += SPX_N * SPX_FORS_HEIGHT; + } + + /* Hash horizontally across all tree roots to derive the public key. */ + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/fors.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/fors.h new file mode 100644 index 0000000000..509140a178 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/fors.h @@ -0,0 +1,32 @@ +#ifndef SPX_FORS_H +#define SPX_FORS_H + +#include + +#include "context.h" +#include "params.h" + +/** + * Signs a message m, deriving the secret key from sk_seed and the FTS address. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +#define fors_sign SPX_NAMESPACE(fors_sign) +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); + +/** + * Derives the FORS public key from a signature. + * This can be used for verification by comparing to a known public key, or to + * subsequently verify a signature on the derived public key. The latter is the + * typical use-case when used as an FTS below an OTS in a hypertree. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/hash.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/hash.h new file mode 100644 index 0000000000..f7c87d4c3c --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/hash.h @@ -0,0 +1,28 @@ +#ifndef SPX_HASH_H +#define SPX_HASH_H + +#include +#include + +#include "context.h" +#include "params.h" + +#define prf_addr SPX_NAMESPACE(prf_addr) +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]); + +#define gen_message_random SPX_NAMESPACE(gen_message_random) +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); + +#define hash_message SPX_NAMESPACE(hash_message) +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); + + + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/hash_shake.c b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/hash_shake.c new file mode 100644 index 0000000000..ff5e7ec918 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/hash_shake.c @@ -0,0 +1,83 @@ +#include +#include + +#include "hash.h" + +#include "address.h" +#include "fips202.h" +#include "params.h" +#include "utils.h" + +/* + * Computes PRF(pk_seed, sk_seed, addr) + */ +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]) { + unsigned char buf[2 * SPX_N + SPX_ADDR_BYTES]; + + memcpy(buf, ctx->pub_seed, SPX_N); + memcpy(buf + SPX_N, addr, SPX_ADDR_BYTES); + memcpy(buf + SPX_N + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); + + shake256(out, SPX_N, buf, 2 * SPX_N + SPX_ADDR_BYTES); +} + +/** + * Computes the message-dependent randomness R, using a secret seed and an + * optional randomization value as well as the message. + */ +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { + (void)ctx; + shake256incctx s_inc; + + shake256_inc_init(&s_inc); + shake256_inc_absorb(&s_inc, sk_prf, SPX_N); + shake256_inc_absorb(&s_inc, optrand, SPX_N); + shake256_inc_absorb(&s_inc, m, mlen); + shake256_inc_finalize(&s_inc); + shake256_inc_squeeze(R, SPX_N, &s_inc); + shake256_inc_ctx_release(&s_inc); +} + +/** + * Computes the message hash using R, the public key, and the message. + * Outputs the message digest and the index of the leaf. The index is split in + * the tree index and the leaf index, for convenient copying to an address. + */ +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { + (void)ctx; +#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) +#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) +#define SPX_LEAF_BITS SPX_TREE_HEIGHT +#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) +#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) + + unsigned char buf[SPX_DGST_BYTES]; + unsigned char *bufp = buf; + shake256incctx s_inc; + + shake256_inc_init(&s_inc); + shake256_inc_absorb(&s_inc, R, SPX_N); + shake256_inc_absorb(&s_inc, pk, SPX_PK_BYTES); + shake256_inc_absorb(&s_inc, m, mlen); + shake256_inc_finalize(&s_inc); + shake256_inc_squeeze(buf, SPX_DGST_BYTES, &s_inc); + shake256_inc_ctx_release(&s_inc); + + memcpy(digest, bufp, SPX_FORS_MSG_BYTES); + bufp += SPX_FORS_MSG_BYTES; + + + *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); + *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); + bufp += SPX_TREE_BYTES; + + *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); + *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/merkle.c b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/merkle.c new file mode 100644 index 0000000000..0c1479fd93 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/merkle.c @@ -0,0 +1,59 @@ +#include +#include + +#include "address.h" +#include "merkle.h" +#include "params.h" +#include "utils.h" +#include "utilsx1.h" +#include "wots.h" +#include "wotsx1.h" + +/* + * This generates a Merkle signature (WOTS signature followed by the Merkle + * authentication path). This is in this file because most of the complexity + * is involved with the WOTS signature; the Merkle authentication path logic + * is mostly hidden in treehashx4 + */ +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf) { + unsigned char *auth_path = sig + SPX_WOTS_BYTES; + struct leaf_info_x1 info = { 0 }; + unsigned steps[ SPX_WOTS_LEN ]; + + info.wots_sig = sig; + chain_lengths(steps, root); + info.wots_steps = steps; + + set_type(&tree_addr[0], SPX_ADDR_TYPE_HASHTREE); + set_type(&info.pk_addr[0], SPX_ADDR_TYPE_WOTSPK); + copy_subtree_addr(&info.leaf_addr[0], wots_addr); + copy_subtree_addr(&info.pk_addr[0], wots_addr); + + info.wots_sign_leaf = idx_leaf; + + treehashx1(root, auth_path, ctx, + idx_leaf, 0, + SPX_TREE_HEIGHT, + wots_gen_leafx1, + tree_addr, &info); +} + +/* Compute root node of the top-most subtree. */ +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { + /* We do not need the auth path in key generation, but it simplifies the + code to have just one treehash routine that computes both root and path + in one function. */ + unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; + uint32_t top_tree_addr[8] = {0}; + uint32_t wots_addr[8] = {0}; + + set_layer_addr(top_tree_addr, SPX_D - 1); + set_layer_addr(wots_addr, SPX_D - 1); + + merkle_sign(auth_path, root, ctx, + wots_addr, top_tree_addr, + (uint32_t)~0 /* ~0 means "don't bother generating an auth path */ ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/merkle.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/merkle.h new file mode 100644 index 0000000000..769cf2e970 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/merkle.h @@ -0,0 +1,21 @@ +#ifndef MERKLE_H_ +#define MERKLE_H_ + +#include + +#include "context.h" +#include "params.h" + +/* Generate a Merkle signature (WOTS signature followed by the Merkle */ +/* authentication path) */ +#define merkle_sign SPX_NAMESPACE(merkle_sign) +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf); + +/* Compute the root node of the top-most subtree. */ +#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); + +#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/nistapi.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/nistapi.h new file mode 100644 index 0000000000..3cb71afad4 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/nistapi.h @@ -0,0 +1,87 @@ +#ifndef SPX_API_H +#define SPX_API_H + +#include +#include + +#include "params.h" + +#define CRYPTO_ALGNAME "SPHINCS+" + +#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES +#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES +#define CRYPTO_BYTES SPX_BYTES +#define CRYPTO_SEEDBYTES (3*SPX_N) + +/* + * Returns the length of a secret key, in bytes + */ +#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) +size_t crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) +size_t crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) +size_t crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) +size_t crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +#define crypto_sign SPX_NAMESPACE(crypto_sign) +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/params.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/params.h new file mode 100644 index 0000000000..99778d7efc --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/params.h @@ -0,0 +1,56 @@ +#ifndef SPX_PARAMS_H +#define SPX_PARAMS_H + +#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSSHAKE128SROBUST_CLEAN_##s + +/* Hash output length in bytes. */ +#define SPX_N 16 +/* Height of the hypertree. */ +#define SPX_FULL_HEIGHT 63 +/* Number of subtree layer. */ +#define SPX_D 7 +/* FORS tree dimensions. */ +#define SPX_FORS_HEIGHT 12 +#define SPX_FORS_TREES 14 +/* Winternitz parameter, */ +#define SPX_WOTS_W 16 + +/* The hash function is defined by linking a different hash.c file, as opposed + to setting a #define constant. */ + +/* For clarity */ +#define SPX_ADDR_BYTES 32 + +/* WOTS parameters. */ +#define SPX_WOTS_LOGW 4 + +#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) + +/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ +#define SPX_WOTS_LEN2 3 + +#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) +#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) +#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES + +/* Subtree size. */ +#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) + +//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT +// #error SPX_D should always divide SPX_FULL_HEIGHT +//#endif + +/* FORS parameters. */ +#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) +#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) +#define SPX_FORS_PK_BYTES SPX_N + +/* Resulting SPX sizes. */ +#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ + SPX_FULL_HEIGHT * SPX_N) +#define SPX_PK_BYTES (2 * SPX_N) +#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) + +#include "shake_offsets.h" + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/shake_offsets.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/shake_offsets.h new file mode 100644 index 0000000000..6b28d95d91 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/shake_offsets.h @@ -0,0 +1,21 @@ +#ifndef SHAKE_OFFSETS_H_ +#define SHAKE_OFFSETS_H_ + +/* + * Offsets of various fields in the address structure when we use SHAKE as + * the Sphincs+ hash function + */ + +#define SPX_OFFSET_LAYER 3 /* The byte used to specify the Merkle tree layer */ +#define SPX_OFFSET_TREE 8 /* The start of the 8 byte field used to specify the tree */ +#define SPX_OFFSET_TYPE 19 /* The byte used to specify the hash type (reason) */ +#define SPX_OFFSET_KP_ADDR2 22 /* The high byte used to specify the key pair (which one-time signature) */ +#define SPX_OFFSET_KP_ADDR1 23 /* The low byte used to specify the key pair */ +#define SPX_OFFSET_CHAIN_ADDR 27 /* The byte used to specify the chain address (which Winternitz chain) */ +#define SPX_OFFSET_HASH_ADDR 31 /* The byte used to specify the hash address (where in the Winternitz chain) */ +#define SPX_OFFSET_TREE_HGT 27 /* The byte used to specify the height of this node in the FORS or Merkle tree */ +#define SPX_OFFSET_TREE_INDEX 28 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ + +#define SPX_SHAKE 1 + +#endif /* SHAKE_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/sign.c b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/sign.c new file mode 100644 index 0000000000..9d0c7d1b22 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/sign.c @@ -0,0 +1,286 @@ +#include +#include +#include + +#include "address.h" +#include "context.h" +#include "fors.h" +#include "hash.h" +#include "merkle.h" +#include "nistapi.h" +#include "params.h" +#include "randombytes.h" +#include "thash.h" +#include "utils.h" +#include "wots.h" + +/* + * Returns the length of a secret key, in bytes + */ +size_t crypto_sign_secretkeybytes(void) { + return CRYPTO_SECRETKEYBYTES; +} + +/* + * Returns the length of a public key, in bytes + */ +size_t crypto_sign_publickeybytes(void) { + return CRYPTO_PUBLICKEYBYTES; +} + +/* + * Returns the length of a signature, in bytes + */ +size_t crypto_sign_bytes(void) { + return CRYPTO_BYTES; +} + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +size_t crypto_sign_seedbytes(void) { + return CRYPTO_SEEDBYTES; +} + +/* + * Generates an SPX key pair given a seed of length + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [PUB_SEED || root] + */ +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed) { + spx_ctx ctx; + + /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ + memcpy(sk, seed, CRYPTO_SEEDBYTES); + + memcpy(pk, sk + 2 * SPX_N, SPX_N); + + memcpy(ctx.pub_seed, pk, SPX_N); + memcpy(ctx.sk_seed, sk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + /* Compute root node of the top-most subtree. */ + merkle_gen_root(sk + 3 * SPX_N, &ctx); + + // cleanup + free_hash_function(&ctx); + + memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); + + return 0; +} + +/* + * Generates an SPX key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [PUB_SEED || root] + */ +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { + uint8_t seed[CRYPTO_SEEDBYTES]; + randombytes(seed, CRYPTO_SEEDBYTES); + crypto_sign_seed_keypair(pk, sk, seed); + + return 0; +} + +/** + * Returns an array containing a detached signature. + */ +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk) { + spx_ctx ctx; + + const uint8_t *sk_prf = sk + SPX_N; + const uint8_t *pk = sk + 2 * SPX_N; + + uint8_t optrand[SPX_N]; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t root[SPX_N]; + uint32_t i; + uint64_t tree; + uint32_t idx_leaf; + uint32_t wots_addr[8] = {0}; + uint32_t tree_addr[8] = {0}; + + memcpy(ctx.sk_seed, sk, SPX_N); + memcpy(ctx.pub_seed, pk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + + /* Optionally, signing can be made non-deterministic using optrand. + This can help counter side-channel attacks that would benefit from + getting a large number of traces when the signer uses the same nodes. */ + randombytes(optrand, SPX_N); + /* Compute the digest randomization value. */ + gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); + + /* Derive the message digest and leaf index from R, PK and M. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; + + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); + + /* Sign the message hash using FORS. */ + fors_sign(sig, root, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); + sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; + + /* Update the indices for the next layer. */ + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; + } + + free_hash_function(&ctx); + + *siglen = SPX_BYTES; + + return 0; +} + +/** + * Verifies a detached signature and message under a given public key. + */ +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk) { + spx_ctx ctx; + const uint8_t *pub_root = pk + SPX_N; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t wots_pk[SPX_WOTS_BYTES]; + uint8_t root[SPX_N]; + uint8_t leaf[SPX_N]; + unsigned int i; + uint64_t tree; + uint32_t idx_leaf; + uint32_t wots_addr[8] = {0}; + uint32_t tree_addr[8] = {0}; + uint32_t wots_pk_addr[8] = {0}; + + if (siglen != SPX_BYTES) { + return -1; + } + + memcpy(ctx.pub_seed, pk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); + + /* Derive the message digest and leaf index from R || PK || M. */ + /* The additional SPX_N is a result of the hash domain separator. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; + + /* Layer correctly defaults to 0, so no need to set_layer_addr */ + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); + + fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + /* For each subtree.. */ + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + copy_keypair_addr(wots_pk_addr, wots_addr); + + /* The WOTS public key is only correct if the signature was correct. */ + /* Initially, root is the FORS pk, but on subsequent iterations it is + the root of the subtree below the currently processed subtree. */ + wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); + sig += SPX_WOTS_BYTES; + + /* Compute the leaf node using the WOTS public key. */ + thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); + + /* Compute the root node of this subtree. */ + compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, + &ctx, tree_addr); + sig += SPX_TREE_HEIGHT * SPX_N; + + /* Update the indices for the next layer. */ + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; + } + + // cleanup + free_hash_function(&ctx); + + /* Check if the root node equals the root node in the public key. */ + if (memcmp(root, pub_root, SPX_N) != 0) { + return -1; + } + + return 0; +} + + +/** + * Returns an array containing the signature followed by the message. + */ +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk) { + size_t siglen; + + crypto_sign_signature(sm, &siglen, m, mlen, sk); + + memmove(sm + SPX_BYTES, m, mlen); + *smlen = siglen + mlen; + + return 0; +} + +/** + * Verifies a given signature-message pair under a given public key. + */ +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk) { + /* The API caller does not necessarily know what size a signature should be + but SPHINCS+ signatures are always exactly SPX_BYTES. */ + if (smlen < SPX_BYTES) { + memset(m, 0, smlen); + *mlen = 0; + return -1; + } + + *mlen = smlen - SPX_BYTES; + + if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { + memset(m, 0, smlen); + *mlen = 0; + return -1; + } + + /* If verification was successful, move the message to the right place. */ + memmove(m, sm + SPX_BYTES, *mlen); + + return 0; +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/thash.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/thash.h new file mode 100644 index 0000000000..8687ccfb4d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/thash.h @@ -0,0 +1,13 @@ +#ifndef SPX_THASH_H +#define SPX_THASH_H + +#include "context.h" +#include "params.h" + +#include + +#define thash SPX_NAMESPACE(thash) +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/thash_shake_robust.c b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/thash_shake_robust.c new file mode 100644 index 0000000000..696d53c5cc --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/thash_shake_robust.c @@ -0,0 +1,31 @@ +#include +#include + +#include "thash.h" + +#include "address.h" +#include "params.h" +#include "utils.h" + +#include "fips202.h" + +/** + * Takes an array of inblocks concatenated arrays of SPX_N bytes. + */ +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]) { + PQCLEAN_VLA(uint8_t, buf, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); + PQCLEAN_VLA(uint8_t, bitmask, inblocks * SPX_N); + unsigned int i; + + memcpy(buf, ctx->pub_seed, SPX_N); + memcpy(buf + SPX_N, addr, SPX_ADDR_BYTES); + + shake256(bitmask, inblocks * SPX_N, buf, SPX_N + SPX_ADDR_BYTES); + + for (i = 0; i < inblocks * SPX_N; i++) { + buf[SPX_N + SPX_ADDR_BYTES + i] = in[i] ^ bitmask[i]; + } + + shake256(out, SPX_N, buf, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/utils.c b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/utils.c new file mode 100644 index 0000000000..177b541fb9 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/utils.c @@ -0,0 +1,148 @@ +#include + +#include "utils.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "thash.h" + +/** + * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. + */ +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in) { + int i; + + /* Iterate over out in decreasing order, for big-endianness. */ + for (i = (signed int)outlen - 1; i >= 0; i--) { + out[i] = in & 0xff; + in = in >> 8; + } +} + +void u32_to_bytes(unsigned char *out, uint32_t in) { + out[0] = (unsigned char)(in >> 24); + out[1] = (unsigned char)(in >> 16); + out[2] = (unsigned char)(in >> 8); + out[3] = (unsigned char)in; +} + +/** + * Converts the inlen bytes in 'in' from big-endian byte order to an integer. + */ +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { + unsigned long long retval = 0; + unsigned int i; + + for (i = 0; i < inlen; i++) { + retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); + } + return retval; +} + +/** + * Computes a root node given a leaf and an auth path. + * Expects address to be complete other than the tree_height and tree_index. + */ +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]) { + uint32_t i; + unsigned char buffer[2 * SPX_N]; + + /* If leaf_idx is odd (last bit = 1), current path element is a right child + and auth_path has to go left. Otherwise it is the other way around. */ + if (leaf_idx & 1) { + memcpy(buffer + SPX_N, leaf, SPX_N); + memcpy(buffer, auth_path, SPX_N); + } else { + memcpy(buffer, leaf, SPX_N); + memcpy(buffer + SPX_N, auth_path, SPX_N); + } + auth_path += SPX_N; + + for (i = 0; i < tree_height - 1; i++) { + leaf_idx >>= 1; + idx_offset >>= 1; + /* Set the address of the node we're creating. */ + set_tree_height(addr, i + 1); + set_tree_index(addr, leaf_idx + idx_offset); + + /* Pick the right or left neighbor, depending on parity of the node. */ + if (leaf_idx & 1) { + thash(buffer + SPX_N, buffer, 2, ctx, addr); + memcpy(buffer, auth_path, SPX_N); + } else { + thash(buffer, buffer, 2, ctx, addr); + memcpy(buffer + SPX_N, auth_path, SPX_N); + } + auth_path += SPX_N; + } + + /* The last iteration is exceptional; we do not copy an auth_path node. */ + leaf_idx >>= 1; + idx_offset >>= 1; + set_tree_height(addr, tree_height); + set_tree_index(addr, leaf_idx + idx_offset); + thash(root, buffer, 2, ctx, addr); +} + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx * /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]) { + PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); + PQCLEAN_VLA(unsigned int, heights, tree_height + 1); + unsigned int offset = 0; + uint32_t idx; + uint32_t tree_idx; + + for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { + /* Add the next leaf node to the stack. */ + gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); + offset++; + heights[offset - 1] = 0; + + /* If this is a node we need for the auth path.. */ + if ((leaf_idx ^ 0x1) == idx) { + memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); + } + + /* While the top-most nodes are of equal height.. */ + while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { + /* Compute index of the new node, in the next layer. */ + tree_idx = (idx >> (heights[offset - 1] + 1)); + + /* Set the address of the node we're creating. */ + set_tree_height(tree_addr, heights[offset - 1] + 1); + set_tree_index(tree_addr, + tree_idx + (idx_offset >> (heights[offset - 1] + 1))); + /* Hash the top-most nodes from the stack together. */ + thash(stack + (offset - 2)*SPX_N, + stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); + offset--; + /* Note that the top-most node is now one layer higher. */ + heights[offset - 1]++; + + /* If this is a node we need for the auth path.. */ + if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { + memcpy(auth_path + heights[offset - 1]*SPX_N, + stack + (offset - 1)*SPX_N, SPX_N); + } + } + } + memcpy(root, stack, SPX_N); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/utils.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/utils.h new file mode 100644 index 0000000000..64f5d5a53a --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/utils.h @@ -0,0 +1,58 @@ +#ifndef SPX_UTILS_H +#define SPX_UTILS_H + +#include + +#include "compat.h" +#include "context.h" +#include "params.h" + + +/* To support MSVC use alloca() instead of VLAs. See #20. */ + + +/** + * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. + */ +#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in); +#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) +void u32_to_bytes(unsigned char *out, uint32_t in); + +/** + * Converts the inlen bytes in 'in' from big-endian byte order to an integer. + */ +#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); + +/** + * Computes a root node given a leaf and an auth path. + * Expects address to be complete other than the tree_height and tree_index. + */ +#define compute_root SPX_NAMESPACE(compute_root) +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]); + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +#define treehash SPX_NAMESPACE(treehash) +void treehash(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx *ctx /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]); + + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/utilsx1.c b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/utilsx1.c new file mode 100644 index 0000000000..fccb69b35d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/utilsx1.c @@ -0,0 +1,100 @@ +#include + +#include "utilsx1.h" + +#include "address.h" +#include "params.h" +#include "thash.h" +#include "utils.h" + +/* + * Generate the entire Merkle tree, computing the authentication path for + * leaf_idx, and the resulting root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) + * + * This expects tree_addr to be initialized to the addr structures for the + * Merkle tree nodes + * + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + * + * This works by using the standard Merkle tree building algorithm, + */ +void treehashx1(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, + uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* Where to write the leaves */, + const spx_ctx * /* ctx */, + uint32_t idx, void *info), + uint32_t tree_addr[8], + void *info) { + /* This is where we keep the intermediate nodes */ + PQCLEAN_VLA(uint8_t, stack, tree_height * SPX_N); + + uint32_t idx; + uint32_t max_idx = (uint32_t)((1 << tree_height) - 1); + for (idx = 0;; idx++) { + unsigned char current[2 * SPX_N]; /* Current logical node is at */ + /* index[SPX_N]. We do this to minimize the number of copies */ + /* needed during a thash */ + gen_leaf( ¤t[SPX_N], ctx, idx + idx_offset, + info ); + + /* Now combine the freshly generated right node with previously */ + /* generated left ones */ + uint32_t internal_idx_offset = idx_offset; + uint32_t internal_idx = idx; + uint32_t internal_leaf = leaf_idx; + uint32_t h; /* The height we are in the Merkle tree */ + for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { + + /* Check if we hit the top of the tree */ + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[SPX_N], SPX_N ); + return; + } + + /* + * Check if the node we have is a part of the + * authentication path; if it is, write it out + */ + if ((internal_idx ^ internal_leaf) == 0x01) { + memcpy( &auth_path[ h * SPX_N ], + ¤t[SPX_N], + SPX_N ); + } + + /* + * Check if we're at a left child; if so, stop going up the stack + * Exception: if we've reached the end of the tree, keep on going + * (so we combine the last 4 nodes into the one root node in two + * more iterations) + */ + if ((internal_idx & 1) == 0 && idx < max_idx) { + break; + } + + /* Ok, we're at a right node */ + /* Now combine the left and right logical nodes together */ + + /* Set the address of the node we're creating. */ + internal_idx_offset >>= 1; + set_tree_height(tree_addr, h + 1); + set_tree_index(tree_addr, internal_idx / 2 + internal_idx_offset ); + + unsigned char *left = &stack[h * SPX_N]; + memcpy( ¤t[0], left, SPX_N ); + thash( ¤t[1 * SPX_N], + ¤t[0 * SPX_N], + 2, ctx, tree_addr); + } + + /* We've hit a left child; save the current for when we get the */ + /* corresponding right right */ + memcpy( &stack[h * SPX_N], ¤t[SPX_N], SPX_N); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/utilsx1.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/utilsx1.h new file mode 100644 index 0000000000..e911d17d53 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/utilsx1.h @@ -0,0 +1,27 @@ +#ifndef SPX_UTILSX4_H +#define SPX_UTILSX4_H + +#include + +#include "context.h" +#include "params.h" + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +#define treehashx1 SPX_NAMESPACE(treehashx1) +void treehashx1(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* Where to write the leaf */, + const spx_ctx * /* ctx */, + uint32_t addr_idx, void *info), + uint32_t tree_addrx4[8], void *info); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/wots.c b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/wots.c new file mode 100644 index 0000000000..249717aaa8 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/wots.c @@ -0,0 +1,108 @@ +#include +#include + +#include "wots.h" +#include "wotsx1.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "thash.h" +#include "utils.h" +#include "utilsx1.h" + +// TODO clarify address expectations, and make them more uniform. +// TODO i.e. do we expect types to be set already? +// TODO and do we expect modifications or copies? + +/** + * Computes the chaining function. + * out and in have to be n-byte arrays. + * + * Interprets in as start-th value of the chain. + * addr has to contain the address of the chain. + */ +static void gen_chain(unsigned char *out, const unsigned char *in, + unsigned int start, unsigned int steps, + const spx_ctx *ctx, uint32_t addr[8]) { + uint32_t i; + + /* Initialize out with the value at position 'start'. */ + memcpy(out, in, SPX_N); + + /* Iterate 'steps' calls to the hash function. */ + for (i = start; i < (start + steps) && i < SPX_WOTS_W; i++) { + set_hash_addr(addr, i); + thash(out, out, 1, ctx, addr); + } +} + +/** + * base_w algorithm as described in draft. + * Interprets an array of bytes as integers in base w. + * This only works when log_w is a divisor of 8. + */ +static void base_w(unsigned int *output, const int out_len, + const unsigned char *input) { + int in = 0; + int out = 0; + unsigned char total = 0; + int bits = 0; + int consumed; + + for (consumed = 0; consumed < out_len; consumed++) { + if (bits == 0) { + total = input[in]; + in++; + bits += 8; + } + bits -= SPX_WOTS_LOGW; + output[out] = (total >> bits) & (SPX_WOTS_W - 1); + out++; + } +} + +/* Computes the WOTS+ checksum over a message (in base_w). */ +static void wots_checksum(unsigned int *csum_base_w, + const unsigned int *msg_base_w) { + unsigned int csum = 0; + unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; + unsigned int i; + + /* Compute checksum. */ + for (i = 0; i < SPX_WOTS_LEN1; i++) { + csum += SPX_WOTS_W - 1 - msg_base_w[i]; + } + + /* Convert checksum to base_w. */ + /* Make sure expected empty zero bits are the least significant bits. */ + csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); + ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); + base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); +} + +/* Takes a message and derives the matching chain lengths. */ +void chain_lengths(unsigned int *lengths, const unsigned char *msg) { + base_w(lengths, SPX_WOTS_LEN1, msg); + wots_checksum(lengths + SPX_WOTS_LEN1, lengths); +} + +/** + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. + * + * Writes the computed public key to 'pk'. + */ +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]) { + unsigned int lengths[SPX_WOTS_LEN]; + uint32_t i; + + chain_lengths(lengths, msg); + + for (i = 0; i < SPX_WOTS_LEN; i++) { + set_chain_addr(addr, i); + gen_chain(pk + i * SPX_N, sig + i * SPX_N, + lengths[i], SPX_WOTS_W - 1 - lengths[i], ctx, addr); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/wots.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/wots.h new file mode 100644 index 0000000000..4e7692eeef --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/wots.h @@ -0,0 +1,25 @@ +#ifndef SPX_WOTS_H +#define SPX_WOTS_H + +#include + +#include "context.h" +#include "params.h" + +/** + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. + * + * Writes the computed public key to 'pk'. + */ +#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]); + +/* + * Compute the chain lengths needed for a given message hash + */ +#define chain_lengths SPX_NAMESPACE(chain_lengths) +void chain_lengths(unsigned int *lengths, const unsigned char *msg); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/wotsx1.c b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/wotsx1.c new file mode 100644 index 0000000000..3adec78dfb --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/wotsx1.c @@ -0,0 +1,76 @@ +#include +#include + +#include "wots.h" +#include "wotsx1.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "thash.h" +#include "utils.h" + +/* + * This generates a WOTS public key + * It also generates the WOTS signature if leaf_info indicates + * that we're signing with this WOTS key + */ +void wots_gen_leafx1(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info) { + struct leaf_info_x1 *info = v_info; + uint32_t *leaf_addr = info->leaf_addr; + uint32_t *pk_addr = info->pk_addr; + unsigned int i, k; + unsigned char pk_buffer[ SPX_WOTS_BYTES ]; + unsigned char *buffer; + uint32_t wots_k_mask; + + if (leaf_idx == info->wots_sign_leaf) { + /* We're traversing the leaf that's signing; generate the WOTS */ + /* signature */ + wots_k_mask = 0; + } else { + /* Nope, we're just generating pk's; turn off the signature logic */ + wots_k_mask = (uint32_t)~0; + } + + set_keypair_addr( leaf_addr, leaf_idx ); + set_keypair_addr( pk_addr, leaf_idx ); + + for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { + uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k to */ + /* the step if we're generating a signature, ~0 if we're not */ + + /* Start with the secret seed */ + set_chain_addr(leaf_addr, i); + set_hash_addr(leaf_addr, 0); + set_type(leaf_addr, SPX_ADDR_TYPE_WOTSPRF); + + prf_addr(buffer, ctx, leaf_addr); + + set_type(leaf_addr, SPX_ADDR_TYPE_WOTS); + + /* Iterate down the WOTS chain */ + for (k = 0;; k++) { + /* Check if this is the value that needs to be saved as a */ + /* part of the WOTS signature */ + if (k == wots_k) { + memcpy( info->wots_sig + i * SPX_N, buffer, SPX_N ); + } + + /* Check if we hit the top of the chain */ + if (k == SPX_WOTS_W - 1) { + break; + } + + /* Iterate one step on the chain */ + set_hash_addr(leaf_addr, k); + + thash(buffer, buffer, 1, ctx, leaf_addr); + } + } + + /* Do the final thash to generate the public keys */ + thash(dest, pk_buffer, SPX_WOTS_LEN, ctx, pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/wotsx1.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/wotsx1.h new file mode 100644 index 0000000000..e617929f96 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/wotsx1.h @@ -0,0 +1,39 @@ +#ifndef WOTSX1_H_ +#define WOTSX1_H_ + +#include + +#include "context.h" +#include "params.h" + +/* + * This is here to provide an interface to the internal wots_gen_leafx1 + * routine. While this routine is not referenced in the package outside of + * wots.c, it is called from the stand-alone benchmark code to characterize + * the performance + */ +struct leaf_info_x1 { + unsigned char *wots_sig; + uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ + uint32_t *wots_steps; + uint32_t leaf_addr[8]; + uint32_t pk_addr[8]; +}; + +/* Macro to set the leaf_info to something 'benign', that is, it would */ +/* run with the same time as it does during the real signing process */ +/* Used only by the benchmark code */ +#define INITIALIZE_LEAF_INFO_X1(info, addr, step_buffer) { \ + (info).wots_sig = 0; \ + (info).wots_sign_leaf = ~0; \ + (info).wots_steps = step_buffer; \ + memcpy( &(info).leaf_addr[0], (addr), 32 ); \ + memcpy( &(info).pk_addr[0], (addr), 32 ); \ + } + +#define wots_gen_leafx1 SPX_NAMESPACE(wots_gen_leafx1) +void wots_gen_leafx1(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info); + +#endif /* WOTSX1_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/LICENSE b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/LICENSE new file mode 100644 index 0000000000..670154e353 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/LICENSE @@ -0,0 +1,116 @@ +CC0 1.0 Universal + +Statement of Purpose + +The laws of most jurisdictions throughout the world automatically confer +exclusive Copyright and Related Rights (defined below) upon the creator and +subsequent owner(s) (each and all, an "owner") of an original work of +authorship and/or a database (each, a "Work"). + +Certain owners wish to permanently relinquish those rights to a Work for the +purpose of contributing to a commons of creative, cultural and scientific +works ("Commons") that the public can reliably and without fear of later +claims of infringement build upon, modify, incorporate in other works, reuse +and redistribute as freely as possible in any form whatsoever and for any +purposes, including without limitation commercial purposes. These owners may +contribute to the Commons to promote the ideal of a free culture and the +further production of creative, cultural and scientific works, or to gain +reputation or greater distribution for their Work in part through the use and +efforts of others. + +For these and/or other purposes and motivations, and without any expectation +of additional consideration or compensation, the person associating CC0 with a +Work (the "Affirmer"), to the extent that he or she is an owner of Copyright +and Related Rights in the Work, voluntarily elects to apply CC0 to the Work +and publicly distribute the Work under its terms, with knowledge of his or her +Copyright and Related Rights in the Work and the meaning and intended legal +effect of CC0 on those rights. + +1. Copyright and Related Rights. A Work made available under CC0 may be +protected by copyright and related or neighboring rights ("Copyright and +Related Rights"). Copyright and Related Rights include, but are not limited +to, the following: + + i. the right to reproduce, adapt, distribute, perform, display, communicate, + and translate a Work; + + ii. moral rights retained by the original author(s) and/or performer(s); + + iii. publicity and privacy rights pertaining to a person's image or likeness + depicted in a Work; + + iv. rights protecting against unfair competition in regards to a Work, + subject to the limitations in paragraph 4(a), below; + + v. rights protecting the extraction, dissemination, use and reuse of data in + a Work; + + vi. database rights (such as those arising under Directive 96/9/EC of the + European Parliament and of the Council of 11 March 1996 on the legal + protection of databases, and under any national implementation thereof, + including any amended or successor version of such directive); and + + vii. other similar, equivalent or corresponding rights throughout the world + based on applicable law or treaty, and any national implementations thereof. + +2. Waiver. To the greatest extent permitted by, but not in contravention of, +applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and +unconditionally waives, abandons, and surrenders all of Affirmer's Copyright +and Related Rights and associated claims and causes of action, whether now +known or unknown (including existing as well as future claims and causes of +action), in the Work (i) in all territories worldwide, (ii) for the maximum +duration provided by applicable law or treaty (including future time +extensions), (iii) in any current or future medium and for any number of +copies, and (iv) for any purpose whatsoever, including without limitation +commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes +the Waiver for the benefit of each member of the public at large and to the +detriment of Affirmer's heirs and successors, fully intending that such Waiver +shall not be subject to revocation, rescission, cancellation, termination, or +any other legal or equitable action to disrupt the quiet enjoyment of the Work +by the public as contemplated by Affirmer's express Statement of Purpose. + +3. Public License Fallback. Should any part of the Waiver for any reason be +judged legally invalid or ineffective under applicable law, then the Waiver +shall be preserved to the maximum extent permitted taking into account +Affirmer's express Statement of Purpose. In addition, to the extent the Waiver +is so judged Affirmer hereby grants to each affected person a royalty-free, +non transferable, non sublicensable, non exclusive, irrevocable and +unconditional license to exercise Affirmer's Copyright and Related Rights in +the Work (i) in all territories worldwide, (ii) for the maximum duration +provided by applicable law or treaty (including future time extensions), (iii) +in any current or future medium and for any number of copies, and (iv) for any +purpose whatsoever, including without limitation commercial, advertising or +promotional purposes (the "License"). The License shall be deemed effective as +of the date CC0 was applied by Affirmer to the Work. Should any part of the +License for any reason be judged legally invalid or ineffective under +applicable law, such partial invalidity or ineffectiveness shall not +invalidate the remainder of the License, and in such case Affirmer hereby +affirms that he or she will not (i) exercise any of his or her remaining +Copyright and Related Rights in the Work or (ii) assert any associated claims +and causes of action with respect to the Work, in either case contrary to +Affirmer's express Statement of Purpose. + +4. Limitations and Disclaimers. + + a. No trademark or patent rights held by Affirmer are waived, abandoned, + surrendered, licensed or otherwise affected by this document. + + b. Affirmer offers the Work as-is and makes no representations or warranties + of any kind concerning the Work, express, implied, statutory or otherwise, + including without limitation warranties of title, merchantability, fitness + for a particular purpose, non infringement, or the absence of latent or + other defects, accuracy, or the present or absence of errors, whether or not + discoverable, all to the greatest extent permissible under applicable law. + + c. Affirmer disclaims responsibility for clearing rights of other persons + that may apply to the Work or any use thereof, including without limitation + any person's Copyright and Related Rights in the Work. Further, Affirmer + disclaims responsibility for obtaining any necessary consents, permissions + or other rights required for any use of the Work. + + d. Affirmer understands and acknowledges that Creative Commons is not a + party to this document and has no duty or obligation with respect to this + CC0 or use of the Work. + +For more information, please see + diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/address.c b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/address.c new file mode 100644 index 0000000000..d49d9f3b6b --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/address.c @@ -0,0 +1,95 @@ +#include +#include + +#include "address.h" +#include "params.h" +#include "utils.h" + +/* + * Specify which level of Merkle tree (the "layer") we're working on + */ +void set_layer_addr(uint32_t addr[8], uint32_t layer) { + ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; +} + +/* + * Specify which Merkle tree within the level (the "tree address") we're working on + */ +void set_tree_addr(uint32_t addr[8], uint64_t tree) { + ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); +} + +/* + * Specify the reason we'll use this address structure for, that is, what + * hash will we compute with it. This is used so that unrelated types of + * hashes don't accidentally get the same address structure. The type will be + * one of the SPX_ADDR_TYPE constants + */ +void set_type(uint32_t addr[8], uint32_t type) { + ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; +} + +/* + * Copy the layer and tree fields of the address structure. This is used + * when we're doing multiple types of hashes within the same Merkle tree + */ +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); +} + +/* These functions are used for OTS addresses. */ + +/* + * Specify which Merkle leaf we're working on; that is, which OTS keypair + * we're talking about. + */ +void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { + /* We have > 256 OTS at the bottom of the Merkle tree; to specify */ + /* which one, we'd need to express it in two bytes */ + ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR2] = (unsigned char)(keypair >> 8); + ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; +} + +/* + * Copy the layer, tree and keypair fields of the address structure. This is + * used when we're doing multiple things within the same OTS keypair + */ +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); + ((unsigned char *)out)[SPX_OFFSET_KP_ADDR2] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR2]; + ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; +} + +/* + * Specify which Merkle chain within the OTS we're working with + * (the chain address) + */ +void set_chain_addr(uint32_t addr[8], uint32_t chain) { + ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; +} + +/* + * Specify where in the Merkle chain we are +* (the hash address) + */ +void set_hash_addr(uint32_t addr[8], uint32_t hash) { + ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; +} + +/* These functions are used for all hash tree addresses (including FORS). */ + +/* + * Specify the height of the node in the Merkle/FORS tree we are in + * (the tree height) + */ +void set_tree_height(uint32_t addr[8], uint32_t tree_height) { + ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; +} + +/* + * Specify the distance from the left edge of the node in the Merkle/FORS tree + * (the tree index) + */ +void set_tree_index(uint32_t addr[8], uint32_t tree_index) { + u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/address.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/address.h new file mode 100644 index 0000000000..24a84eb40c --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/address.h @@ -0,0 +1,52 @@ +#ifndef SPX_ADDRESS_H +#define SPX_ADDRESS_H + +#include + +#include "params.h" + +/* The hash types that are passed to set_type */ +#define SPX_ADDR_TYPE_WOTS 0 +#define SPX_ADDR_TYPE_WOTSPK 1 +#define SPX_ADDR_TYPE_HASHTREE 2 +#define SPX_ADDR_TYPE_FORSTREE 3 +#define SPX_ADDR_TYPE_FORSPK 4 +#define SPX_ADDR_TYPE_WOTSPRF 5 +#define SPX_ADDR_TYPE_FORSPRF 6 + +#define set_layer_addr SPX_NAMESPACE(set_layer_addr) +void set_layer_addr(uint32_t addr[8], uint32_t layer); + +#define set_tree_addr SPX_NAMESPACE(set_tree_addr) +void set_tree_addr(uint32_t addr[8], uint64_t tree); + +#define set_type SPX_NAMESPACE(set_type) +void set_type(uint32_t addr[8], uint32_t type); + +/* Copies the layer and tree part of one address into the other */ +#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); + +/* These functions are used for WOTS and FORS addresses. */ + +#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) +void set_keypair_addr(uint32_t addr[8], uint32_t keypair); + +#define set_chain_addr SPX_NAMESPACE(set_chain_addr) +void set_chain_addr(uint32_t addr[8], uint32_t chain); + +#define set_hash_addr SPX_NAMESPACE(set_hash_addr) +void set_hash_addr(uint32_t addr[8], uint32_t hash); + +#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); + +/* These functions are used for all hash tree addresses (including FORS). */ + +#define set_tree_height SPX_NAMESPACE(set_tree_height) +void set_tree_height(uint32_t addr[8], uint32_t tree_height); + +#define set_tree_index SPX_NAMESPACE(set_tree_index) +void set_tree_index(uint32_t addr[8], uint32_t tree_index); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/api.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/api.h new file mode 100644 index 0000000000..2db63eec43 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/api.h @@ -0,0 +1,77 @@ +#ifndef PQCLEAN_SPHINCSSHAKE128SSIMPLE_AARCH64_API_H +#define PQCLEAN_SPHINCSSHAKE128SSIMPLE_AARCH64_API_H + +#include +#include + +#define PQCLEAN_SPHINCSSHAKE128SSIMPLE_AARCH64_CRYPTO_ALGNAME "SPHINCS+-shake-128s-simple" + +#define PQCLEAN_SPHINCSSHAKE128SSIMPLE_AARCH64_CRYPTO_SECRETKEYBYTES 64 +#define PQCLEAN_SPHINCSSHAKE128SSIMPLE_AARCH64_CRYPTO_PUBLICKEYBYTES 32 +#define PQCLEAN_SPHINCSSHAKE128SSIMPLE_AARCH64_CRYPTO_BYTES 7856 + +#define PQCLEAN_SPHINCSSHAKE128SSIMPLE_AARCH64_CRYPTO_SEEDBYTES 48 + +/* + * Returns the length of a secret key, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE128SSIMPLE_AARCH64_crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE128SSIMPLE_AARCH64_crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE128SSIMPLE_AARCH64_crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE128SSIMPLE_AARCH64_crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +int PQCLEAN_SPHINCSSHAKE128SSIMPLE_AARCH64_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +int PQCLEAN_SPHINCSSHAKE128SSIMPLE_AARCH64_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +int PQCLEAN_SPHINCSSHAKE128SSIMPLE_AARCH64_crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +int PQCLEAN_SPHINCSSHAKE128SSIMPLE_AARCH64_crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, + const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +int PQCLEAN_SPHINCSSHAKE128SSIMPLE_AARCH64_crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +int PQCLEAN_SPHINCSSHAKE128SSIMPLE_AARCH64_crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/context.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/context.h new file mode 100644 index 0000000000..6e0a33f3b7 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/context.h @@ -0,0 +1,19 @@ +#ifndef SPX_CONTEXT_H +#define SPX_CONTEXT_H + +#include + +#include "params.h" + +typedef struct { + uint8_t pub_seed[SPX_N]; + uint8_t sk_seed[SPX_N]; +} spx_ctx; + +#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) +void initialize_hash_function(spx_ctx *ctx); + +#define free_hash_function SPX_NAMESPACE(free_hash_function) +void free_hash_function(spx_ctx *ctx); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/context_shake.c b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/context_shake.c new file mode 100644 index 0000000000..9614a103d3 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/context_shake.c @@ -0,0 +1,12 @@ +#include "context.h" + +/* For SHAKE256, there is no immediate reason to initialize at the start, + so this function is an empty operation. */ +void initialize_hash_function(spx_ctx *ctx) { + (void)ctx; /* Suppress an 'unused parameter' warning. */ +} + +// in case the hash function api is heap-based. +void free_hash_function(spx_ctx *ctx) { + (void)ctx; +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/f1600x2.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/f1600x2.h new file mode 100644 index 0000000000..70d1af9f14 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/f1600x2.h @@ -0,0 +1,11 @@ +#ifndef SPX_F1600X2_H +#define SPX_F1600X2_H + +#include + +extern uint64_t f1600_RC[24]; +extern void _f1600x2(uint64_t *a, uint64_t *rc); + +#define f1600x2(s) do {_f1600x2((s), f1600_RC);} while(0) + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/f1600x2.s b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/f1600x2.s new file mode 100644 index 0000000000..640ed791ed --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/f1600x2.s @@ -0,0 +1,143 @@ +# From https://github.com/bwesterb/armed-keccak + +.macro round + # Execute theta, but without xoring into the state yet. + # Compute parities p[i] = a[i] ^ a[5+i] ^ ... ^ a[20+i]. + eor3.16b v25, v0, v5, v10 + eor3.16b v26, v1, v6, v11 + eor3.16b v27, v2, v7, v12 + eor3.16b v28, v3, v8, v13 + eor3.16b v29, v4, v9, v14 + + eor3.16b v25, v25, v15, v20 + eor3.16b v26, v26, v16, v21 + eor3.16b v27, v27, v17, v22 + eor3.16b v28, v28, v18, v23 + eor3.16b v29, v29, v19, v24 + + # d[0] = rotl(p[1], 1) ^ p[4] + rax1.2d v30, v29, v26 + # d[3] = rotl(p[4], 1) ^ p[2] + rax1.2d v29, v27, v29 + # d[1] = rotl(p[2], 1) ^ p[0] + rax1.2d v27, v25, v27 + # d[4] = rotl(p[0], 1) ^ p[3] + rax1.2d v25, v28, v25 + # d[2] = rotl(p[3], 1) ^ p[1] + rax1.2d v28, v26, v28 + + # Xor parities from step theta into the state at the same time + # as executing rho and pi. + eor.16b v0, v0, v30 + mov.16b v31, v1 + xar.2d v1, v6, v27, 20 + xar.2d v6, v9, v25, 44 + xar.2d v9, v22, v28, 3 + xar.2d v22, v14, v25, 25 + xar.2d v14, v20, v30, 46 + xar.2d v20, v2, v28, 2 + xar.2d v2, v12, v28, 21 + xar.2d v12, v13, v29, 39 + xar.2d v13, v19, v25, 56 + xar.2d v19, v23, v29, 8 + xar.2d v23, v15, v30, 23 + xar.2d v15, v4, v25, 37 + xar.2d v4, v24, v25, 50 + xar.2d v24, v21, v27, 62 + xar.2d v21, v8, v29, 9 + xar.2d v8, v16, v27, 19 + xar.2d v16, v5, v30, 28 + xar.2d v5, v3, v29, 36 + xar.2d v3, v18, v29, 43 + xar.2d v18, v17, v28, 49 + xar.2d v17, v11, v27, 54 + xar.2d v11, v7, v28, 58 + xar.2d v7, v10, v30, 61 + xar.2d v10, v31, v27, 63 + + # Chi + bcax.16b v25, v0, v2, v1 + bcax.16b v26, v1, v3, v2 + bcax.16b v2, v2, v4, v3 + bcax.16b v3, v3, v0, v4 + bcax.16b v4, v4, v1, v0 + mov.16b v0, v25 + mov.16b v1, v26 + + bcax.16b v25, v5, v7, v6 + bcax.16b v26, v6, v8, v7 + bcax.16b v7, v7, v9, v8 + bcax.16b v8, v8, v5, v9 + bcax.16b v9, v9, v6, v5 + mov.16b v5, v25 + mov.16b v6, v26 + + bcax.16b v25, v10, v12, v11 + bcax.16b v26, v11, v13, v12 + bcax.16b v12, v12, v14, v13 + bcax.16b v13, v13, v10, v14 + bcax.16b v14, v14, v11, v10 + mov.16b v10, v25 + mov.16b v11, v26 + + bcax.16b v25, v15, v17, v16 + bcax.16b v26, v16, v18, v17 + bcax.16b v17, v17, v19, v18 + bcax.16b v18, v18, v15, v19 + bcax.16b v19, v19, v16, v15 + mov.16b v15, v25 + mov.16b v16, v26 + + bcax.16b v25, v20, v22, v21 + bcax.16b v26, v21, v23, v22 + bcax.16b v22, v22, v24, v23 + bcax.16b v23, v23, v20, v24 + bcax.16b v24, v24, v21, v20 + mov.16b v20, v25 + mov.16b v21, v26 + + # iota + ld1r {v25.2d}, [x1], #8 + eor.16b v0, v0, v25 +.endm + +.align 4 +.global __f1600x2 +__f1600x2: + stp d8, d9, [sp,#-16]! + stp d10, d11, [sp,#-16]! + stp d12, d13, [sp,#-16]! + stp d14, d15, [sp,#-16]! + + mov x2, x0 + mov x3, #24 + + ld1.2d {v0, v1, v2, v3}, [x0], #64 + ld1.2d {v4, v5, v6, v7}, [x0], #64 + ld1.2d {v8, v9, v10, v11}, [x0], #64 + ld1.2d {v12, v13, v14, v15}, [x0], #64 + ld1.2d {v16, v17, v18, v19}, [x0], #64 + ld1.2d {v20, v21, v22, v23}, [x0], #64 + ld1.2d {v24}, [x0] + +loop: + round + + subs x3, x3, #1 + cbnz x3, loop + + mov x0, x2 + st1.2d {v0, v1, v2, v3}, [x0], #64 + st1.2d {v4, v5, v6, v7}, [x0], #64 + st1.2d {v8, v9, v10, v11}, [x0], #64 + st1.2d {v12, v13, v14, v15}, [x0], #64 + st1.2d {v16, v17, v18, v19}, [x0], #64 + st1.2d {v20, v21, v22, v23}, [x0], #64 + st1.2d {v24}, [x0] + + ldp d14, d15, [sp], #16 + ldp d12, d13, [sp], #16 + ldp d10, d11, [sp], #16 + ldp d8, d9, [sp], #16 + + ret lr diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/f1600x2_const.c b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/f1600x2_const.c new file mode 100644 index 0000000000..e49c0ba149 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/f1600x2_const.c @@ -0,0 +1,30 @@ +#include "f1600x2.h" + +uint64_t f1600_RC[24] = { + 0x0000000000000001, + 0x0000000000008082, + 0x800000000000808A, + 0x8000000080008000, + 0x000000000000808B, + 0x0000000080000001, + 0x8000000080008081, + 0x8000000000008009, + 0x000000000000008A, + 0x0000000000000088, + 0x0000000080008009, + 0x000000008000000A, + 0x000000008000808B, + 0x800000000000008B, + 0x8000000000008089, + 0x8000000000008003, + 0x8000000000008002, + 0x8000000000000080, + 0x000000000000800A, + 0x800000008000000A, + 0x8000000080008081, + 0x8000000000008080, + 0x0000000080000001, + 0x8000000080008008, +}; + + diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/fips202x2.c b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/fips202x2.c new file mode 100644 index 0000000000..4718c343bc --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/fips202x2.c @@ -0,0 +1,148 @@ +#include +#include + +#include "fips202x2.h" +#include "f1600x2.h" +#include "fips202.h" + +uint64_t load64(const unsigned char *x) { + unsigned long long r = 0, i; + + for (i = 0; i < 8; ++i) { + r |= (unsigned long long)x[i] << 8 * i; + } + return r; +} + +void store64(uint8_t *x, uint64_t u) { + unsigned int i; + + for (i = 0; i < 8; ++i) { + x[i] = (uint8_t)u; + u >>= 8; + } +} + +static void keccak_absorb2x(uint64_t *s, + unsigned int r, + const unsigned char *m0, + const unsigned char *m1, + unsigned long long int mlen, + unsigned char p) { + unsigned long long i; + unsigned char t0[200]; + unsigned char t1[200]; + + while (mlen >= r) { + for (i = 0; i < r / 8; ++i) { + s[2 * i + 0] ^= load64(m0 + 8 * i); + s[2 * i + 1] ^= load64(m1 + 8 * i); + } + + f1600x2(s); + mlen -= r; + m0 += r; + m1 += r; + } + + for (i = 0; i < r; ++i) { + t0[i] = 0; + t1[i] = 0; + } + for (i = 0; i < mlen; ++i) { + t0[i] = m0[i]; + t1[i] = m1[i]; + } + + t0[i] = p; + t1[i] = p; + + t0[r - 1] |= 128; + t1[r - 1] |= 128; + + for (i = 0; i < r / 8; ++i) { + s[2 * i + 0] ^= load64(t0 + 8 * i); + s[2 * i + 1] ^= load64(t1 + 8 * i); + } +} + + +static void keccak_squeezeblocks2x(unsigned char *h0, + unsigned char *h1, + unsigned long long int nblocks, + uint64_t *s, + unsigned int r) { + unsigned int i; + + while (nblocks > 0) { + f1600x2(s); + for (i = 0; i < (r >> 3); i++) { + store64(h0 + 8 * i, s[2 * i + 0]); + store64(h1 + 8 * i, s[2 * i + 1]); + } + h0 += r; + h1 += r; + nblocks--; + } +} + + + +void shake128x2(unsigned char *out0, + unsigned char *out1, + unsigned long long outlen, + unsigned char *in0, + unsigned char *in1, + unsigned long long inlen) { + uint64_t s[50] = {0}; + unsigned char t0[SHAKE128_RATE]; + unsigned char t1[SHAKE128_RATE]; + unsigned int i; + + /* absorb 4 message of identical length in parallel */ + keccak_absorb2x(s, SHAKE128_RATE, in0, in1, inlen, 0x1F); + + /* Squeeze output */ + keccak_squeezeblocks2x(out0, out1, outlen / SHAKE128_RATE, s, SHAKE128_RATE); + + out0 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; + out1 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; + + if (outlen % SHAKE128_RATE) { + keccak_squeezeblocks2x(t0, t1, 1, s, SHAKE128_RATE); + for (i = 0; i < outlen % SHAKE128_RATE; i++) { + out0[i] = t0[i]; + out1[i] = t1[i]; + } + } +} + + +void shake256x2(unsigned char *out0, + unsigned char *out1, + unsigned long long outlen, + unsigned char *in0, + unsigned char *in1, + unsigned long long inlen) { + uint64_t s[50] = {0}; + unsigned char t0[SHAKE256_RATE]; + unsigned char t1[SHAKE256_RATE]; + unsigned int i; + + /* absorb 2 message of identical length in parallel */ + keccak_absorb2x(s, SHAKE256_RATE, in0, in1, inlen, 0x1F); + + /* Squeeze output */ + keccak_squeezeblocks2x(out0, out1, outlen / SHAKE256_RATE, s, SHAKE256_RATE); + + out0 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; + out1 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; + + if (outlen % SHAKE256_RATE) { + keccak_squeezeblocks2x(t0, t1, 1, s, SHAKE256_RATE); + for (i = 0; i < outlen % SHAKE256_RATE; i++) { + out0[i] = t0[i]; + out1[i] = t1[i]; + } + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/fips202x2.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/fips202x2.h new file mode 100644 index 0000000000..7ba58b35d8 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/fips202x2.h @@ -0,0 +1,24 @@ +#ifndef SPX_FIPS202X2_H +#define SPX_FIPS202X2_H + +#include + +uint64_t load64(const unsigned char *x); +void store64(uint8_t *x, uint64_t u); + + +void shake128x2(unsigned char *out0, + unsigned char *out1, + unsigned long long outlen, + unsigned char *in0, + unsigned char *in1, + unsigned long long inlen); + +void shake256x2(unsigned char *out0, + unsigned char *out1, + unsigned long long outlen, + unsigned char *in0, + unsigned char *in1, + unsigned long long inlen); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/fors.c b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/fors.c new file mode 100644 index 0000000000..39193d04e2 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/fors.c @@ -0,0 +1,191 @@ +#include +#include +#include + +#include "fors.h" + +#include "address.h" +#include "hash.h" +#include "hashx2.h" +#include "thash.h" +#include "thashx2.h" +#include "utils.h" +#include "utilsx2.h" + +static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + prf_addr(sk, ctx, fors_leaf_addr); +} + +static void fors_gen_skx2(unsigned char *sk0, + unsigned char *sk1, + const spx_ctx *ctx, + uint32_t fors_leaf_addrx2[2 * 8]) { + prf_addrx2(sk0, sk1, + ctx, fors_leaf_addrx2); +} + +static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, + const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + thash(leaf, sk, 1, ctx, fors_leaf_addr); +} + +static void fors_sk_to_leafx2(unsigned char *leaf0, + unsigned char *leaf1, + const unsigned char *sk0, + const unsigned char *sk1, + const spx_ctx *ctx, + uint32_t fors_leaf_addrx2[2 * 8]) { + thashx2(leaf0, leaf1, + sk0, sk1, + 1, ctx, fors_leaf_addrx2); +} + +struct fors_gen_leaf_info { + uint32_t leaf_addrx[2 * 8]; +}; + +static void fors_gen_leafx2(unsigned char *leaf, + const spx_ctx *ctx, + uint32_t addr_idx, void *info) { + struct fors_gen_leaf_info *fors_info = info; + uint32_t *fors_leaf_addrx2 = fors_info->leaf_addrx; + unsigned int j; + + /* Only set the parts that the caller doesn't set */ + for (j = 0; j < 2; j++) { + set_tree_index(fors_leaf_addrx2 + j * 8, addr_idx + j); + set_type(fors_leaf_addrx2 + j * 8, SPX_ADDR_TYPE_FORSPRF); + } + + fors_gen_skx2(leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + ctx, fors_leaf_addrx2); + + for (j = 0; j < 2; j++) { + set_type(fors_leaf_addrx2 + j * 8, SPX_ADDR_TYPE_FORSTREE); + } + + fors_sk_to_leafx2(leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + ctx, fors_leaf_addrx2); +} + +/** + * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + * Assumes indices has space for SPX_FORS_TREES integers. + */ +static void message_to_indices(uint32_t *indices, const unsigned char *m) { + unsigned int i, j; + unsigned int offset = 0; + + for (i = 0; i < SPX_FORS_TREES; i++) { + indices[i] = 0; + for (j = 0; j < SPX_FORS_HEIGHT; j++) { + indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); + offset++; + } + } +} + +/** + * Signs a message m, deriving the secret key from sk_seed and the FTS address. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + uint32_t fors_tree_addr[2 * 8] = {0}; + struct fors_gen_leaf_info fors_info = {0}; + uint32_t *fors_leaf_addr = fors_info.leaf_addrx; + uint32_t fors_pk_addr[8] = {0}; + uint32_t idx_offset; + unsigned int i; + + for (i = 0; i < 2; i++) { + copy_keypair_addr(fors_tree_addr + 8 * i, fors_addr); + set_type(fors_tree_addr + 8 * i, SPX_ADDR_TYPE_FORSTREE); + copy_keypair_addr(fors_leaf_addr + 8 * i, fors_addr); + } + copy_keypair_addr(fors_pk_addr, fors_addr); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); + + message_to_indices(indices, m); + + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); + + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + + /* Include the secret key part that produces the selected leaf node. */ + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); + fors_gen_sk(sig, ctx, fors_tree_addr); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + sig += SPX_N; + + /* Compute the authentication path for this leaf node. */ + treehashx2(roots + i * SPX_N, sig, ctx, + indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx2, + fors_tree_addr, &fors_info); + + sig += SPX_N * SPX_FORS_HEIGHT; + } + + /* Hash horizontally across all tree roots to derive the public key. */ + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); +} + +/** + * Derives the FORS public key from a signature. + * This can be used for verification by comparing to a known public key, or to + * subsequently verify a signature on the derived public key. The latter is the + * typical use-case when used as an FTS below an OTS in a hypertree. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + unsigned char leaf[SPX_N]; + uint32_t fors_tree_addr[8] = {0}; + uint32_t fors_pk_addr[8] = {0}; + uint32_t idx_offset; + unsigned int i; + + copy_keypair_addr(fors_tree_addr, fors_addr); + copy_keypair_addr(fors_pk_addr, fors_addr); + + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); + + message_to_indices(indices, m); + + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); + + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + + /* Derive the leaf from the included secret key part. */ + fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); + sig += SPX_N; + + /* Derive the corresponding root node of this tree. */ + compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, + sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); + sig += SPX_N * SPX_FORS_HEIGHT; + } + + /* Hash horizontally across all tree roots to derive the public key. */ + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/fors.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/fors.h new file mode 100644 index 0000000000..509140a178 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/fors.h @@ -0,0 +1,32 @@ +#ifndef SPX_FORS_H +#define SPX_FORS_H + +#include + +#include "context.h" +#include "params.h" + +/** + * Signs a message m, deriving the secret key from sk_seed and the FTS address. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +#define fors_sign SPX_NAMESPACE(fors_sign) +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); + +/** + * Derives the FORS public key from a signature. + * This can be used for verification by comparing to a known public key, or to + * subsequently verify a signature on the derived public key. The latter is the + * typical use-case when used as an FTS below an OTS in a hypertree. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/hash.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/hash.h new file mode 100644 index 0000000000..f7c87d4c3c --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/hash.h @@ -0,0 +1,28 @@ +#ifndef SPX_HASH_H +#define SPX_HASH_H + +#include +#include + +#include "context.h" +#include "params.h" + +#define prf_addr SPX_NAMESPACE(prf_addr) +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]); + +#define gen_message_random SPX_NAMESPACE(gen_message_random) +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); + +#define hash_message SPX_NAMESPACE(hash_message) +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); + + + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/hash_shake.c b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/hash_shake.c new file mode 100644 index 0000000000..ff5e7ec918 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/hash_shake.c @@ -0,0 +1,83 @@ +#include +#include + +#include "hash.h" + +#include "address.h" +#include "fips202.h" +#include "params.h" +#include "utils.h" + +/* + * Computes PRF(pk_seed, sk_seed, addr) + */ +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]) { + unsigned char buf[2 * SPX_N + SPX_ADDR_BYTES]; + + memcpy(buf, ctx->pub_seed, SPX_N); + memcpy(buf + SPX_N, addr, SPX_ADDR_BYTES); + memcpy(buf + SPX_N + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); + + shake256(out, SPX_N, buf, 2 * SPX_N + SPX_ADDR_BYTES); +} + +/** + * Computes the message-dependent randomness R, using a secret seed and an + * optional randomization value as well as the message. + */ +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { + (void)ctx; + shake256incctx s_inc; + + shake256_inc_init(&s_inc); + shake256_inc_absorb(&s_inc, sk_prf, SPX_N); + shake256_inc_absorb(&s_inc, optrand, SPX_N); + shake256_inc_absorb(&s_inc, m, mlen); + shake256_inc_finalize(&s_inc); + shake256_inc_squeeze(R, SPX_N, &s_inc); + shake256_inc_ctx_release(&s_inc); +} + +/** + * Computes the message hash using R, the public key, and the message. + * Outputs the message digest and the index of the leaf. The index is split in + * the tree index and the leaf index, for convenient copying to an address. + */ +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { + (void)ctx; +#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) +#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) +#define SPX_LEAF_BITS SPX_TREE_HEIGHT +#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) +#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) + + unsigned char buf[SPX_DGST_BYTES]; + unsigned char *bufp = buf; + shake256incctx s_inc; + + shake256_inc_init(&s_inc); + shake256_inc_absorb(&s_inc, R, SPX_N); + shake256_inc_absorb(&s_inc, pk, SPX_PK_BYTES); + shake256_inc_absorb(&s_inc, m, mlen); + shake256_inc_finalize(&s_inc); + shake256_inc_squeeze(buf, SPX_DGST_BYTES, &s_inc); + shake256_inc_ctx_release(&s_inc); + + memcpy(digest, bufp, SPX_FORS_MSG_BYTES); + bufp += SPX_FORS_MSG_BYTES; + + + *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); + *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); + bufp += SPX_TREE_BYTES; + + *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); + *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/hash_shakex2.c b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/hash_shakex2.c new file mode 100644 index 0000000000..99571916a2 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/hash_shakex2.c @@ -0,0 +1,52 @@ +#include +#include + +#include "hashx2.h" + +#include "address.h" +#include "f1600x2.h" +#include "fips202x2.h" +#include "params.h" + +/* + * 2-way parallel version of prf_addr; takes 2x as much input and output + */ +void prf_addrx2(unsigned char *out0, + unsigned char *out1, + const spx_ctx *ctx, + const uint32_t addrx2[2 * 8]) { + /* As we write and read only a few quadwords, it is more efficient to + * build and extract from the fourway SHAKE256 state by hand. */ + uint64_t state[50] = {0}; + + for (int i = 0; i < SPX_N / 8; i++) { + uint64_t x = load64(ctx->pub_seed + 8 * i); + state[2 * i] = x; + state[2 * i + 1] = x; + } + for (int i = 0; i < 4; i++) { + state[2 * (SPX_N / 8 + i)] = (((uint64_t)addrx2[1 + 2 * i]) << 32) + | (uint64_t)addrx2[2 * i]; + state[2 * (SPX_N / 8 + i) + 1] = (((uint64_t)addrx2[8 + 1 + 2 * i]) << 32) + | (uint64_t)addrx2[8 + 2 * i]; + } + for (int i = 0; i < SPX_N / 8; i++) { + uint64_t x = load64(ctx->sk_seed + 8 * i); + state[2 * (SPX_N / 8 + i + 4)] = x; + state[2 * (SPX_N / 8 + i + 4) + 1] = x; + } + + /* SHAKE domain separator and padding. */ + state[2 * (SPX_N / 4 + 4)] = 0x1f; + state[2 * (SPX_N / 4 + 4) + 1] = 0x1f; + + state[2 * 16] = 0x80ULL << 56; + state[2 * 16 + 1] = 0x80ULL << 56; + + f1600x2(state); + + for (int i = 0; i < SPX_N / 8; i++) { + store64(out0 + 8 * i, state[2 * i]); + store64(out1 + 8 * i, state[2 * i + 1]); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/hashx2.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/hashx2.h new file mode 100644 index 0000000000..99b8873a9b --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/hashx2.h @@ -0,0 +1,14 @@ +#ifndef SPX_HASHX2_H +#define SPX_HASHX2_H + +#include "context.h" +#include "params.h" +#include + +#define prf_addrx2 SPX_NAMESPACE(prf_addrx2) +void prf_addrx2(unsigned char *out0, + unsigned char *out1, + const spx_ctx *ctx, + const uint32_t addrx2[2 * 8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/merkle.c b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/merkle.c new file mode 100644 index 0000000000..c94ee23939 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/merkle.c @@ -0,0 +1,64 @@ +#include +#include + +#include "merkle.h" + +#include "address.h" +#include "params.h" +#include "utils.h" +#include "utilsx2.h" +#include "wots.h" +#include "wotsx2.h" + +/* + * This generates a Merkle signature (WOTS signature followed by the Merkle + * authentication path). + */ +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf) { + unsigned char *auth_path = sig + SPX_WOTS_BYTES; + uint32_t tree_addrx2[2 * 8] = { 0 }; + int j; + struct leaf_info_x2 info = { 0 }; + unsigned steps[ SPX_WOTS_LEN ]; + + info.wots_sig = sig; + chain_lengths(steps, root); + info.wots_steps = steps; + + for (j = 0; j < 2; j++) { + set_type(&tree_addrx2[8 * j], SPX_ADDR_TYPE_HASHTREE); + set_type(&info.leaf_addr[8 * j], SPX_ADDR_TYPE_WOTS); + set_type(&info.pk_addr[8 * j], SPX_ADDR_TYPE_WOTSPK); + copy_subtree_addr(&tree_addrx2[8 * j], tree_addr); + copy_subtree_addr(&info.leaf_addr[8 * j], wots_addr); + copy_subtree_addr(&info.pk_addr[8 * j], wots_addr); + } + + info.wots_sign_leaf = idx_leaf; + + treehashx2(root, auth_path, ctx, + idx_leaf, 0, + SPX_TREE_HEIGHT, + wots_gen_leafx2, + tree_addrx2, &info); +} + +/* Compute root node of the top-most subtree. */ +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { + /* We do not need the auth path in key generation, but it simplifies the + code to have just one treehash routine that computes both root and path + in one function. */ + unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; + uint32_t top_tree_addr[8] = {0}; + uint32_t wots_addr[8] = {0}; + + set_layer_addr(top_tree_addr, SPX_D - 1); + set_layer_addr(wots_addr, SPX_D - 1); + + merkle_sign(auth_path, root, ctx, + wots_addr, top_tree_addr, + ~0 /* ~0 means "don't bother generating an auth path */ ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/merkle.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/merkle.h new file mode 100644 index 0000000000..769cf2e970 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/merkle.h @@ -0,0 +1,21 @@ +#ifndef MERKLE_H_ +#define MERKLE_H_ + +#include + +#include "context.h" +#include "params.h" + +/* Generate a Merkle signature (WOTS signature followed by the Merkle */ +/* authentication path) */ +#define merkle_sign SPX_NAMESPACE(merkle_sign) +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf); + +/* Compute the root node of the top-most subtree. */ +#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); + +#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/nistapi.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/nistapi.h new file mode 100644 index 0000000000..3cb71afad4 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/nistapi.h @@ -0,0 +1,87 @@ +#ifndef SPX_API_H +#define SPX_API_H + +#include +#include + +#include "params.h" + +#define CRYPTO_ALGNAME "SPHINCS+" + +#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES +#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES +#define CRYPTO_BYTES SPX_BYTES +#define CRYPTO_SEEDBYTES (3*SPX_N) + +/* + * Returns the length of a secret key, in bytes + */ +#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) +size_t crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) +size_t crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) +size_t crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) +size_t crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +#define crypto_sign SPX_NAMESPACE(crypto_sign) +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/params.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/params.h new file mode 100644 index 0000000000..b269c9f84b --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/params.h @@ -0,0 +1,56 @@ +#ifndef SPX_PARAMS_H +#define SPX_PARAMS_H + +#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSSHAKE128SSIMPLE_AARCH64_##s + +/* Hash output length in bytes. */ +#define SPX_N 16 +/* Height of the hypertree. */ +#define SPX_FULL_HEIGHT 63 +/* Number of subtree layer. */ +#define SPX_D 7 +/* FORS tree dimensions. */ +#define SPX_FORS_HEIGHT 12 +#define SPX_FORS_TREES 14 +/* Winternitz parameter, */ +#define SPX_WOTS_W 16 + +/* The hash function is defined by linking a different hash.c file, as opposed + to setting a #define constant. */ + +/* For clarity */ +#define SPX_ADDR_BYTES 32 + +/* WOTS parameters. */ +#define SPX_WOTS_LOGW 4 + +#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) + +/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ +#define SPX_WOTS_LEN2 3 + +#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) +#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) +#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES + +/* Subtree size. */ +#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) + +//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT +// #error SPX_D should always divide SPX_FULL_HEIGHT +//#endif + +/* FORS parameters. */ +#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) +#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) +#define SPX_FORS_PK_BYTES SPX_N + +/* Resulting SPX sizes. */ +#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ + SPX_FULL_HEIGHT * SPX_N) +#define SPX_PK_BYTES (2 * SPX_N) +#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) + +#include "shake_offsets.h" + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/shake_offsets.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/shake_offsets.h new file mode 100644 index 0000000000..6b28d95d91 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/shake_offsets.h @@ -0,0 +1,21 @@ +#ifndef SHAKE_OFFSETS_H_ +#define SHAKE_OFFSETS_H_ + +/* + * Offsets of various fields in the address structure when we use SHAKE as + * the Sphincs+ hash function + */ + +#define SPX_OFFSET_LAYER 3 /* The byte used to specify the Merkle tree layer */ +#define SPX_OFFSET_TREE 8 /* The start of the 8 byte field used to specify the tree */ +#define SPX_OFFSET_TYPE 19 /* The byte used to specify the hash type (reason) */ +#define SPX_OFFSET_KP_ADDR2 22 /* The high byte used to specify the key pair (which one-time signature) */ +#define SPX_OFFSET_KP_ADDR1 23 /* The low byte used to specify the key pair */ +#define SPX_OFFSET_CHAIN_ADDR 27 /* The byte used to specify the chain address (which Winternitz chain) */ +#define SPX_OFFSET_HASH_ADDR 31 /* The byte used to specify the hash address (where in the Winternitz chain) */ +#define SPX_OFFSET_TREE_HGT 27 /* The byte used to specify the height of this node in the FORS or Merkle tree */ +#define SPX_OFFSET_TREE_INDEX 28 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ + +#define SPX_SHAKE 1 + +#endif /* SHAKE_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/sign.c b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/sign.c new file mode 100644 index 0000000000..9d0c7d1b22 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/sign.c @@ -0,0 +1,286 @@ +#include +#include +#include + +#include "address.h" +#include "context.h" +#include "fors.h" +#include "hash.h" +#include "merkle.h" +#include "nistapi.h" +#include "params.h" +#include "randombytes.h" +#include "thash.h" +#include "utils.h" +#include "wots.h" + +/* + * Returns the length of a secret key, in bytes + */ +size_t crypto_sign_secretkeybytes(void) { + return CRYPTO_SECRETKEYBYTES; +} + +/* + * Returns the length of a public key, in bytes + */ +size_t crypto_sign_publickeybytes(void) { + return CRYPTO_PUBLICKEYBYTES; +} + +/* + * Returns the length of a signature, in bytes + */ +size_t crypto_sign_bytes(void) { + return CRYPTO_BYTES; +} + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +size_t crypto_sign_seedbytes(void) { + return CRYPTO_SEEDBYTES; +} + +/* + * Generates an SPX key pair given a seed of length + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [PUB_SEED || root] + */ +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed) { + spx_ctx ctx; + + /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ + memcpy(sk, seed, CRYPTO_SEEDBYTES); + + memcpy(pk, sk + 2 * SPX_N, SPX_N); + + memcpy(ctx.pub_seed, pk, SPX_N); + memcpy(ctx.sk_seed, sk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + /* Compute root node of the top-most subtree. */ + merkle_gen_root(sk + 3 * SPX_N, &ctx); + + // cleanup + free_hash_function(&ctx); + + memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); + + return 0; +} + +/* + * Generates an SPX key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [PUB_SEED || root] + */ +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { + uint8_t seed[CRYPTO_SEEDBYTES]; + randombytes(seed, CRYPTO_SEEDBYTES); + crypto_sign_seed_keypair(pk, sk, seed); + + return 0; +} + +/** + * Returns an array containing a detached signature. + */ +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk) { + spx_ctx ctx; + + const uint8_t *sk_prf = sk + SPX_N; + const uint8_t *pk = sk + 2 * SPX_N; + + uint8_t optrand[SPX_N]; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t root[SPX_N]; + uint32_t i; + uint64_t tree; + uint32_t idx_leaf; + uint32_t wots_addr[8] = {0}; + uint32_t tree_addr[8] = {0}; + + memcpy(ctx.sk_seed, sk, SPX_N); + memcpy(ctx.pub_seed, pk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + + /* Optionally, signing can be made non-deterministic using optrand. + This can help counter side-channel attacks that would benefit from + getting a large number of traces when the signer uses the same nodes. */ + randombytes(optrand, SPX_N); + /* Compute the digest randomization value. */ + gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); + + /* Derive the message digest and leaf index from R, PK and M. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; + + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); + + /* Sign the message hash using FORS. */ + fors_sign(sig, root, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); + sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; + + /* Update the indices for the next layer. */ + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; + } + + free_hash_function(&ctx); + + *siglen = SPX_BYTES; + + return 0; +} + +/** + * Verifies a detached signature and message under a given public key. + */ +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk) { + spx_ctx ctx; + const uint8_t *pub_root = pk + SPX_N; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t wots_pk[SPX_WOTS_BYTES]; + uint8_t root[SPX_N]; + uint8_t leaf[SPX_N]; + unsigned int i; + uint64_t tree; + uint32_t idx_leaf; + uint32_t wots_addr[8] = {0}; + uint32_t tree_addr[8] = {0}; + uint32_t wots_pk_addr[8] = {0}; + + if (siglen != SPX_BYTES) { + return -1; + } + + memcpy(ctx.pub_seed, pk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); + + /* Derive the message digest and leaf index from R || PK || M. */ + /* The additional SPX_N is a result of the hash domain separator. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; + + /* Layer correctly defaults to 0, so no need to set_layer_addr */ + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); + + fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + /* For each subtree.. */ + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + copy_keypair_addr(wots_pk_addr, wots_addr); + + /* The WOTS public key is only correct if the signature was correct. */ + /* Initially, root is the FORS pk, but on subsequent iterations it is + the root of the subtree below the currently processed subtree. */ + wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); + sig += SPX_WOTS_BYTES; + + /* Compute the leaf node using the WOTS public key. */ + thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); + + /* Compute the root node of this subtree. */ + compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, + &ctx, tree_addr); + sig += SPX_TREE_HEIGHT * SPX_N; + + /* Update the indices for the next layer. */ + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; + } + + // cleanup + free_hash_function(&ctx); + + /* Check if the root node equals the root node in the public key. */ + if (memcmp(root, pub_root, SPX_N) != 0) { + return -1; + } + + return 0; +} + + +/** + * Returns an array containing the signature followed by the message. + */ +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk) { + size_t siglen; + + crypto_sign_signature(sm, &siglen, m, mlen, sk); + + memmove(sm + SPX_BYTES, m, mlen); + *smlen = siglen + mlen; + + return 0; +} + +/** + * Verifies a given signature-message pair under a given public key. + */ +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk) { + /* The API caller does not necessarily know what size a signature should be + but SPHINCS+ signatures are always exactly SPX_BYTES. */ + if (smlen < SPX_BYTES) { + memset(m, 0, smlen); + *mlen = 0; + return -1; + } + + *mlen = smlen - SPX_BYTES; + + if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { + memset(m, 0, smlen); + *mlen = 0; + return -1; + } + + /* If verification was successful, move the message to the right place. */ + memmove(m, sm + SPX_BYTES, *mlen); + + return 0; +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/thash.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/thash.h new file mode 100644 index 0000000000..8687ccfb4d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/thash.h @@ -0,0 +1,13 @@ +#ifndef SPX_THASH_H +#define SPX_THASH_H + +#include "context.h" +#include "params.h" + +#include + +#define thash SPX_NAMESPACE(thash) +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/thash_shake_simplex2.c b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/thash_shake_simplex2.c new file mode 100644 index 0000000000..892e453690 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/thash_shake_simplex2.c @@ -0,0 +1,83 @@ +#include +#include + +#include "thash.h" +#include "thashx2.h" + +#include "address.h" +#include "params.h" +#include "utils.h" + +#include "f1600x2.h" +#include "fips202x2.h" + + +void thash(unsigned char *out, + const unsigned char *in, + unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]) { + uint32_t addrx2 [2 * 8] = { + addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], addr[6], addr[7], + addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], addr[6], addr[7] + }; + thashx2(out, out, in, in, inblocks, ctx, addrx2); +} + +/** + * 2-way parallel version of thash; takes 2x as much input and output + */ +void thashx2(unsigned char *out0, + unsigned char *out1, + const unsigned char *in0, + const unsigned char *in1, + unsigned int inblocks, + const spx_ctx *ctx, uint32_t addrx2[2 * 8]) { + if (inblocks == 1 || inblocks == 2) { + /* As we write and read only a few quadwords, it is more efficient to + * build and extract from the twoway SHAKE256 state by hand. */ + uint64_t state[50] = {0}; + for (int i = 0; i < SPX_N / 8; i++) { + uint64_t x = load64(ctx->pub_seed + 8 * i); + state[2 * i] = x; + state[2 * i + 1] = x; + } + for (int i = 0; i < 4; i++) { + state[2 * (SPX_N / 8 + i)] = (((uint64_t)addrx2[1 + 2 * i]) << 32) + | (uint64_t)addrx2[2 * i]; + state[2 * (SPX_N / 8 + i) + 1] = (((uint64_t)addrx2[8 + 1 + 2 * i]) << 32) + | (uint64_t)addrx2[8 + 2 * i]; + } + + for (unsigned int i = 0; i < (SPX_N / 8) * inblocks; i++) { + state[2 * (SPX_N / 8 + 4 + i)] = load64(in0 + 8 * i); + state[2 * (SPX_N / 8 + 4 + i) + 1] = load64(in1 + 8 * i); + } + + /* Domain separator and padding. */ + state[2 * 16] = 0x80ULL << 56; + state[2 * 16 + 1] = 0x80ULL << 56; + + state[2 * ((SPX_N / 8) * (1 + inblocks) + 4)] ^= 0x1f; + state[2 * ((SPX_N / 8) * (1 + inblocks) + 4) + 1] ^= 0x1f; + + f1600x2(state); + + for (int i = 0; i < SPX_N / 8; i++) { + store64(out0 + 8 * i, state[2 * i]); + store64(out1 + 8 * i, state[2 * i + 1]); + } + } else { + PQCLEAN_VLA(unsigned char, buf0, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, buf1, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); + + memcpy(buf0, ctx->pub_seed, SPX_N); + memcpy(buf1, ctx->pub_seed, SPX_N); + memcpy(buf0 + SPX_N, addrx2 + 0 * 8, SPX_ADDR_BYTES); + memcpy(buf1 + SPX_N, addrx2 + 1 * 8, SPX_ADDR_BYTES); + memcpy(buf0 + SPX_N + SPX_ADDR_BYTES, in0, inblocks * SPX_N); + memcpy(buf1 + SPX_N + SPX_ADDR_BYTES, in1, inblocks * SPX_N); + + shake256x2(out0, out1, SPX_N, + buf0, buf1, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/thashx2.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/thashx2.h new file mode 100644 index 0000000000..040375e618 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/thashx2.h @@ -0,0 +1,16 @@ +#ifndef SPX_THASHX2_H +#define SPX_THASHX2_H + +#include "context.h" +#include "params.h" +#include + +#define thashx2 SPX_NAMESPACE(thashx2) +void thashx2(unsigned char *out0, + unsigned char *out1, + const unsigned char *in0, + const unsigned char *in1, + unsigned int inblocks, + const spx_ctx *ctx, uint32_t addrx2[2 * 8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/utils.c b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/utils.c new file mode 100644 index 0000000000..177b541fb9 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/utils.c @@ -0,0 +1,148 @@ +#include + +#include "utils.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "thash.h" + +/** + * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. + */ +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in) { + int i; + + /* Iterate over out in decreasing order, for big-endianness. */ + for (i = (signed int)outlen - 1; i >= 0; i--) { + out[i] = in & 0xff; + in = in >> 8; + } +} + +void u32_to_bytes(unsigned char *out, uint32_t in) { + out[0] = (unsigned char)(in >> 24); + out[1] = (unsigned char)(in >> 16); + out[2] = (unsigned char)(in >> 8); + out[3] = (unsigned char)in; +} + +/** + * Converts the inlen bytes in 'in' from big-endian byte order to an integer. + */ +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { + unsigned long long retval = 0; + unsigned int i; + + for (i = 0; i < inlen; i++) { + retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); + } + return retval; +} + +/** + * Computes a root node given a leaf and an auth path. + * Expects address to be complete other than the tree_height and tree_index. + */ +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]) { + uint32_t i; + unsigned char buffer[2 * SPX_N]; + + /* If leaf_idx is odd (last bit = 1), current path element is a right child + and auth_path has to go left. Otherwise it is the other way around. */ + if (leaf_idx & 1) { + memcpy(buffer + SPX_N, leaf, SPX_N); + memcpy(buffer, auth_path, SPX_N); + } else { + memcpy(buffer, leaf, SPX_N); + memcpy(buffer + SPX_N, auth_path, SPX_N); + } + auth_path += SPX_N; + + for (i = 0; i < tree_height - 1; i++) { + leaf_idx >>= 1; + idx_offset >>= 1; + /* Set the address of the node we're creating. */ + set_tree_height(addr, i + 1); + set_tree_index(addr, leaf_idx + idx_offset); + + /* Pick the right or left neighbor, depending on parity of the node. */ + if (leaf_idx & 1) { + thash(buffer + SPX_N, buffer, 2, ctx, addr); + memcpy(buffer, auth_path, SPX_N); + } else { + thash(buffer, buffer, 2, ctx, addr); + memcpy(buffer + SPX_N, auth_path, SPX_N); + } + auth_path += SPX_N; + } + + /* The last iteration is exceptional; we do not copy an auth_path node. */ + leaf_idx >>= 1; + idx_offset >>= 1; + set_tree_height(addr, tree_height); + set_tree_index(addr, leaf_idx + idx_offset); + thash(root, buffer, 2, ctx, addr); +} + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx * /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]) { + PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); + PQCLEAN_VLA(unsigned int, heights, tree_height + 1); + unsigned int offset = 0; + uint32_t idx; + uint32_t tree_idx; + + for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { + /* Add the next leaf node to the stack. */ + gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); + offset++; + heights[offset - 1] = 0; + + /* If this is a node we need for the auth path.. */ + if ((leaf_idx ^ 0x1) == idx) { + memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); + } + + /* While the top-most nodes are of equal height.. */ + while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { + /* Compute index of the new node, in the next layer. */ + tree_idx = (idx >> (heights[offset - 1] + 1)); + + /* Set the address of the node we're creating. */ + set_tree_height(tree_addr, heights[offset - 1] + 1); + set_tree_index(tree_addr, + tree_idx + (idx_offset >> (heights[offset - 1] + 1))); + /* Hash the top-most nodes from the stack together. */ + thash(stack + (offset - 2)*SPX_N, + stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); + offset--; + /* Note that the top-most node is now one layer higher. */ + heights[offset - 1]++; + + /* If this is a node we need for the auth path.. */ + if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { + memcpy(auth_path + heights[offset - 1]*SPX_N, + stack + (offset - 1)*SPX_N, SPX_N); + } + } + } + memcpy(root, stack, SPX_N); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/utils.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/utils.h new file mode 100644 index 0000000000..64f5d5a53a --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/utils.h @@ -0,0 +1,58 @@ +#ifndef SPX_UTILS_H +#define SPX_UTILS_H + +#include + +#include "compat.h" +#include "context.h" +#include "params.h" + + +/* To support MSVC use alloca() instead of VLAs. See #20. */ + + +/** + * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. + */ +#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in); +#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) +void u32_to_bytes(unsigned char *out, uint32_t in); + +/** + * Converts the inlen bytes in 'in' from big-endian byte order to an integer. + */ +#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); + +/** + * Computes a root node given a leaf and an auth path. + * Expects address to be complete other than the tree_height and tree_index. + */ +#define compute_root SPX_NAMESPACE(compute_root) +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]); + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +#define treehash SPX_NAMESPACE(treehash) +void treehash(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx *ctx /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]); + + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/utilsx2.c b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/utilsx2.c new file mode 100644 index 0000000000..8736474e4f --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/utilsx2.c @@ -0,0 +1,130 @@ +#include + +#include "utilsx2.h" + +#include "address.h" +#include "params.h" +#include "thashx2.h" +#include "utils.h" + +/* + * Generate the entire Merkle tree, computing the authentication path for leaf_idx, + * and the resulting root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) + * + * This expects tree_addrx2 to be initialized to 2 parallel addr structures for + * the Merkle tree nodes + * + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + * + * This works by using the standard Merkle tree building algorithm, except + * that each 'node' tracked is actually 2 consecutive nodes in the real tree. + * When we combine two logical nodes AB and WX, we perform the H + * operation on adjacent real nodes, forming the parent logical node + * (AB)(WX) + * + * When we get to the top level of the real tree (where there is only + * one logical node), we continue this operation one more time; the right + * most real node will by the actual root (and the other node will be + * garbage). We follow the same thashx2 logic so that the 'extract + * authentication path components' part of the loop is still executed (and + * to simplify the code somewhat) + */ +void treehashx2(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, + uint32_t tree_height, + void (*gen_leafx2)( + unsigned char * /* Where to write the leaves */, + const spx_ctx *, + uint32_t idx, void *info), + uint32_t tree_addrx2[2 * 8], + void *info) { + /* This is where we keep the intermediate nodes */ + unsigned char stackx2[tree_height * 2 * SPX_N]; + uint32_t left_adj = 0, prev_left_adj = 0; /* When we're doing the top */ + /* level, the left-most part of the tree isn't at the beginning */ + /* of current[]. These give the offset of the actual start */ + + uint32_t idx; + uint32_t max_idx = (1 << (tree_height - 1)) - 1; + for (idx = 0;; idx++) { + unsigned char current[2 * SPX_N]; /* Current logical node */ + gen_leafx2( current, ctx, 2 * idx + idx_offset, + info ); + + /* Now combine the freshly generated right node with previously */ + /* generated left ones */ + uint32_t internal_idx_offset = idx_offset; + uint32_t internal_idx = idx; + uint32_t internal_leaf = leaf_idx; + uint32_t h; /* The height we are in the Merkle tree */ + for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { + + /* Special processing if we're at the top of the tree */ + if (h >= tree_height - 1) { + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[1 * SPX_N], SPX_N ); + return; + } + /* The tree indexing logic is a bit off in this case */ + /* Adjust it so that the left-most node of the part of */ + /* the tree that we're processing has index 0 */ + prev_left_adj = left_adj; + left_adj = 2 - (1 << (tree_height - h - 1)); + } + + /* Check if we hit the top of the tree */ + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[1 * SPX_N], SPX_N ); + return; + } + + /* + * Check if one of the nodes we have is a part of the + * authentication path; if it is, write it out + */ + if ((((internal_idx << 1) ^ internal_leaf) & ~0x1) == 0) { + memcpy( &auth_path[ h * SPX_N ], + ¤t[(((internal_leaf & 1) ^ 1) + prev_left_adj) * SPX_N], + SPX_N ); + } + + /* + * Check if we're at a left child; if so, stop going up the stack + * Exception: if we've reached the end of the tree, keep on going + * (so we combine the last 2 nodes into the one root node in two + * more iterations) + */ + if ((internal_idx & 1) == 0 && idx < max_idx) { + break; + } + + /* Ok, we're at a right node (or doing the top 3 levels) */ + /* Now combine the left and right logical nodes together */ + + /* Set the address of the node we're creating. */ + int j; + internal_idx_offset >>= 1; + for (j = 0; j < 2; j++) { + set_tree_height(tree_addrx2 + j * 8, h + 1); + set_tree_index(tree_addrx2 + j * 8, + (2 / 2) * (internal_idx & ~1) + j - left_adj + internal_idx_offset ); + } + unsigned char *left = &stackx2[h * 2 * SPX_N]; + thashx2( ¤t[0 * SPX_N], + ¤t[1 * SPX_N], + &left [0 * SPX_N], + ¤t[0 * SPX_N], + 2, ctx, tree_addrx2); + } + + /* We've hit a left child; save the current for when we get the */ + /* corresponding right right */ + memcpy( &stackx2[h * 2 * SPX_N], current, 2 * SPX_N); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/utilsx2.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/utilsx2.h new file mode 100644 index 0000000000..e09faddc43 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/utilsx2.h @@ -0,0 +1,30 @@ +#ifndef SPX_UTILSX2_H +#define SPX_UTILSX2_H + +#include + +#include "context.h" +#include "params.h" + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + * + * This implementation uses SIMD to compute internal nodes 2 at a time (in + * parallel) + */ +#define treehashx2 SPX_NAMESPACE(treehashx2) +void treehashx2(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leafx2)( + unsigned char * /* Where to write the leaves */, + const spx_ctx * /* ctx */, + uint32_t addr_idx, void *info), + uint32_t tree_addrx2[2 * 8], void *info); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/wots.c b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/wots.c new file mode 100644 index 0000000000..3babe45e95 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/wots.c @@ -0,0 +1,259 @@ +#include +#include + +#include "wots.h" +#include "wotsx2.h" + +#include "address.h" +#include "hash.h" +#include "hashx2.h" +#include "params.h" +#include "thashx2.h" +#include "utils.h" +#include "utilsx2.h" + +// TODO clarify address expectations, and make them more uniform. +// TODO i.e. do we expect types to be set already? +// TODO and do we expect modifications or copies? + +/** + * Computes up the chains + */ +static void gen_chains( + unsigned char *out, + const unsigned char *in, + unsigned int start[SPX_WOTS_LEN], + const unsigned int steps[SPX_WOTS_LEN], + const spx_ctx *ctx, + uint32_t addr[8]) { + uint32_t i, j, k, idx, watching; + int done; + unsigned char empty[SPX_N]; + unsigned char *bufs[4]; + uint32_t addrs[8 * 2]; + + int l; + uint16_t counts[SPX_WOTS_W] = { 0 }; + uint16_t idxs[SPX_WOTS_LEN]; + uint16_t total, newTotal; + + /* set addrs = {addr, addr} */ + for (j = 0; j < 2; j++) { + memcpy(addrs + j * 8, addr, sizeof(uint32_t) * 8); + } + + /* Initialize out with the value at position 'start'. */ + memcpy(out, in, SPX_WOTS_LEN * SPX_N); + + /* Sort the chains in reverse order by steps using counting sort. */ + for (i = 0; i < SPX_WOTS_LEN; i++) { + counts[steps[i]]++; + } + total = 0; + for (l = SPX_WOTS_W - 1; l >= 0; l--) { + newTotal = counts[l] + total; + counts[l] = total; + total = newTotal; + } + for (i = 0; i < SPX_WOTS_LEN; i++) { + idxs[counts[steps[i]]] = i; + counts[steps[i]]++; + } + + /* We got our work cut out for us: do it! */ + for (i = 0; i < SPX_WOTS_LEN; i += 2) { + for (j = 0; j < 2 && i + j < SPX_WOTS_LEN; j++) { + idx = idxs[i + j]; + set_chain_addr(addrs + j * 8, idx); + bufs[j] = out + SPX_N * idx; + } + + /* As the chains are sorted in reverse order, we know that the first + * chain is the longest and the last one is the shortest. We keep + * an eye on whether the last chain is done and then on the one before, + * et cetera. */ + watching = 1; + done = 0; + while (i + watching >= SPX_WOTS_LEN) { + bufs[watching] = &empty[0]; + watching--; + } + + for (k = 0;; k++) { + while (k == steps[idxs[i + watching]]) { + bufs[watching] = &empty[0]; + if (watching == 0) { + done = 1; + break; + } + watching--; + } + if (done) { + break; + } + for (j = 0; j < watching + 1; j++) { + set_hash_addr(addrs + j * 8, k + start[idxs[i + j]]); + } + + thashx2(bufs[0], bufs[1], + bufs[0], bufs[1], 1, ctx, addrs); + } + } +} + +/** + * base_w algorithm as described in draft. + * Interprets an array of bytes as integers in base w. + * This only works when log_w is a divisor of 8. + */ +static void base_w(unsigned int *output, const int out_len, + const unsigned char *input) { + int in = 0; + int out = 0; + unsigned char total = 0; + int bits = 0; + int consumed; + + for (consumed = 0; consumed < out_len; consumed++) { + if (bits == 0) { + total = input[in]; + in++; + bits += 8; + } + bits -= SPX_WOTS_LOGW; + output[out] = (total >> bits) & (SPX_WOTS_W - 1); + out++; + } +} + +/* Computes the WOTS+ checksum over a message (in base_w). */ +static void wots_checksum(unsigned int *csum_base_w, + const unsigned int *msg_base_w) { + unsigned int csum = 0; + unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; + unsigned int i; + + /* Compute checksum. */ + for (i = 0; i < SPX_WOTS_LEN1; i++) { + csum += SPX_WOTS_W - 1 - msg_base_w[i]; + } + + /* Convert checksum to base_w. */ + /* Make sure expected empty zero bits are the least significant bits. */ + csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); + ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); + base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); +} + +/* Takes a message and derives the matching chain lengths. */ +void chain_lengths(unsigned int *lengths, const unsigned char *msg) { + base_w(lengths, SPX_WOTS_LEN1, msg); + wots_checksum(lengths + SPX_WOTS_LEN1, lengths); +} + +/** + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. + * + * Writes the computed public key to 'pk'. + */ +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]) { + unsigned int steps[SPX_WOTS_LEN]; + unsigned int start[SPX_WOTS_LEN]; + uint32_t i; + + chain_lengths(start, msg); + + for (i = 0; i < SPX_WOTS_LEN; i++) { + steps[i] = SPX_WOTS_W - 1 - start[i]; + } + + gen_chains(pk, sig, start, steps, ctx, addr); +} + +/* + * This generates 2 sequential WOTS public keys + * It also generates the WOTS signature if leaf_info indicates + * that we're signing with one of these WOTS keys + */ +void wots_gen_leafx2(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info) { + struct leaf_info_x2 *info = v_info; + uint32_t *leaf_addr = info->leaf_addr; + uint32_t *pk_addr = info->pk_addr; + unsigned int i, j, k; + unsigned char pk_buffer[ 2 * SPX_WOTS_BYTES ]; + unsigned wots_offset = SPX_WOTS_BYTES; + unsigned char *buffer; + uint32_t wots_k_mask; + unsigned wots_sign_index; + + if (((leaf_idx ^ info->wots_sign_leaf) & ~1) == 0) { + /* We're traversing the leaf that's signing; generate the WOTS */ + /* signature */ + wots_k_mask = 0; + wots_sign_index = info->wots_sign_leaf & 1; /* Which of of the 2 */ + /* slots do the signatures come from */ + } else { + /* Nope, we're just generating pk's; turn off the signature logic */ + wots_k_mask = ~0; + wots_sign_index = 0; + } + + for (j = 0; j < 2; j++) { + set_keypair_addr( leaf_addr + j * 8, leaf_idx + j ); + set_keypair_addr( pk_addr + j * 8, leaf_idx + j ); + } + + for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { + uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k to */ + /* the step if we're generating a signature, ~0 if we're not */ + + /* Start with the secret seed */ + for (j = 0; j < 2; j++) { + set_chain_addr(leaf_addr + j * 8, i); + set_hash_addr(leaf_addr + j * 8, 0); + set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTSPRF); + } + prf_addrx2(buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + ctx, leaf_addr); + for (j = 0; j < 2; j++) { + set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTS); + } + + /* Iterate down the WOTS chain */ + for (k = 0;; k++) { + /* Check if one of the values we have needs to be saved as a */ + /* part of the WOTS signature */ + if (k == wots_k) { + memcpy( info->wots_sig + i * SPX_N, + buffer + wots_sign_index * wots_offset, SPX_N ); + } + + /* Check if we hit the top of the chain */ + if (k == SPX_WOTS_W - 1) { + break; + } + + /* Iterate one step on all 4 chains */ + for (j = 0; j < 2; j++) { + set_hash_addr(leaf_addr + j * 8, k); + } + thashx2(buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + 1, ctx, leaf_addr); + } + } + + /* Do the final thash to generate the public keys */ + thashx2(dest + 0 * SPX_N, + dest + 1 * SPX_N, + pk_buffer + 0 * wots_offset, + pk_buffer + 1 * wots_offset, + SPX_WOTS_LEN, ctx, pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/wots.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/wots.h new file mode 100644 index 0000000000..4e7692eeef --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/wots.h @@ -0,0 +1,25 @@ +#ifndef SPX_WOTS_H +#define SPX_WOTS_H + +#include + +#include "context.h" +#include "params.h" + +/** + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. + * + * Writes the computed public key to 'pk'. + */ +#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]); + +/* + * Compute the chain lengths needed for a given message hash + */ +#define chain_lengths SPX_NAMESPACE(chain_lengths) +void chain_lengths(unsigned int *lengths, const unsigned char *msg); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/wotsx2.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/wotsx2.h new file mode 100644 index 0000000000..b58bb61f84 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_aarch64/wotsx2.h @@ -0,0 +1,40 @@ +#ifndef WOTSX2_H_ +#define WOTSX2_H_ + +#include "params.h" +#include + +/* + * This is here to provide an interface to the internal wots_gen_leafx2 + * routine. While this routine is not referenced in the package outside of + * wots.c, it is called from the stand-alone benchmark code to characterize + * the performance + */ +struct leaf_info_x2 { + unsigned char *wots_sig; + uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ + uint32_t *wots_steps; + uint32_t leaf_addr[2 * 8]; + uint32_t pk_addr[2 * 8]; +}; + +/* Macro to set the leaf_info to something 'benign', that is, it would */ +/* run with the same time as it does during the real signing process */ +/* Used only by the benchmark code */ +#define INITIALIZE_LEAF_INFO_X2(info, addr, step_buffer) { \ + (info).wots_sig = 0; \ + (info).wots_sign_leaf = ~0; \ + (info).wots_steps = step_buffer; \ + int i; \ + for (i=0; i<2; i++) { \ + memcpy( &(info).leaf_addr[8*i], addr, 32 ); \ + memcpy( &(info).pk_addr[8*i], addr, 32 ); \ + } \ + } + +#define wots_gen_leafx2 SPX_NAMESPACE(wots_gen_leafx2) +void wots_gen_leafx2(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info); + +#endif /* WOTSX2_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/LICENSE b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/LICENSE new file mode 100644 index 0000000000..670154e353 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/LICENSE @@ -0,0 +1,116 @@ +CC0 1.0 Universal + +Statement of Purpose + +The laws of most jurisdictions throughout the world automatically confer +exclusive Copyright and Related Rights (defined below) upon the creator and +subsequent owner(s) (each and all, an "owner") of an original work of +authorship and/or a database (each, a "Work"). + +Certain owners wish to permanently relinquish those rights to a Work for the +purpose of contributing to a commons of creative, cultural and scientific +works ("Commons") that the public can reliably and without fear of later +claims of infringement build upon, modify, incorporate in other works, reuse +and redistribute as freely as possible in any form whatsoever and for any +purposes, including without limitation commercial purposes. These owners may +contribute to the Commons to promote the ideal of a free culture and the +further production of creative, cultural and scientific works, or to gain +reputation or greater distribution for their Work in part through the use and +efforts of others. + +For these and/or other purposes and motivations, and without any expectation +of additional consideration or compensation, the person associating CC0 with a +Work (the "Affirmer"), to the extent that he or she is an owner of Copyright +and Related Rights in the Work, voluntarily elects to apply CC0 to the Work +and publicly distribute the Work under its terms, with knowledge of his or her +Copyright and Related Rights in the Work and the meaning and intended legal +effect of CC0 on those rights. + +1. Copyright and Related Rights. A Work made available under CC0 may be +protected by copyright and related or neighboring rights ("Copyright and +Related Rights"). Copyright and Related Rights include, but are not limited +to, the following: + + i. the right to reproduce, adapt, distribute, perform, display, communicate, + and translate a Work; + + ii. moral rights retained by the original author(s) and/or performer(s); + + iii. publicity and privacy rights pertaining to a person's image or likeness + depicted in a Work; + + iv. rights protecting against unfair competition in regards to a Work, + subject to the limitations in paragraph 4(a), below; + + v. rights protecting the extraction, dissemination, use and reuse of data in + a Work; + + vi. database rights (such as those arising under Directive 96/9/EC of the + European Parliament and of the Council of 11 March 1996 on the legal + protection of databases, and under any national implementation thereof, + including any amended or successor version of such directive); and + + vii. other similar, equivalent or corresponding rights throughout the world + based on applicable law or treaty, and any national implementations thereof. + +2. Waiver. To the greatest extent permitted by, but not in contravention of, +applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and +unconditionally waives, abandons, and surrenders all of Affirmer's Copyright +and Related Rights and associated claims and causes of action, whether now +known or unknown (including existing as well as future claims and causes of +action), in the Work (i) in all territories worldwide, (ii) for the maximum +duration provided by applicable law or treaty (including future time +extensions), (iii) in any current or future medium and for any number of +copies, and (iv) for any purpose whatsoever, including without limitation +commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes +the Waiver for the benefit of each member of the public at large and to the +detriment of Affirmer's heirs and successors, fully intending that such Waiver +shall not be subject to revocation, rescission, cancellation, termination, or +any other legal or equitable action to disrupt the quiet enjoyment of the Work +by the public as contemplated by Affirmer's express Statement of Purpose. + +3. Public License Fallback. Should any part of the Waiver for any reason be +judged legally invalid or ineffective under applicable law, then the Waiver +shall be preserved to the maximum extent permitted taking into account +Affirmer's express Statement of Purpose. In addition, to the extent the Waiver +is so judged Affirmer hereby grants to each affected person a royalty-free, +non transferable, non sublicensable, non exclusive, irrevocable and +unconditional license to exercise Affirmer's Copyright and Related Rights in +the Work (i) in all territories worldwide, (ii) for the maximum duration +provided by applicable law or treaty (including future time extensions), (iii) +in any current or future medium and for any number of copies, and (iv) for any +purpose whatsoever, including without limitation commercial, advertising or +promotional purposes (the "License"). The License shall be deemed effective as +of the date CC0 was applied by Affirmer to the Work. Should any part of the +License for any reason be judged legally invalid or ineffective under +applicable law, such partial invalidity or ineffectiveness shall not +invalidate the remainder of the License, and in such case Affirmer hereby +affirms that he or she will not (i) exercise any of his or her remaining +Copyright and Related Rights in the Work or (ii) assert any associated claims +and causes of action with respect to the Work, in either case contrary to +Affirmer's express Statement of Purpose. + +4. Limitations and Disclaimers. + + a. No trademark or patent rights held by Affirmer are waived, abandoned, + surrendered, licensed or otherwise affected by this document. + + b. Affirmer offers the Work as-is and makes no representations or warranties + of any kind concerning the Work, express, implied, statutory or otherwise, + including without limitation warranties of title, merchantability, fitness + for a particular purpose, non infringement, or the absence of latent or + other defects, accuracy, or the present or absence of errors, whether or not + discoverable, all to the greatest extent permissible under applicable law. + + c. Affirmer disclaims responsibility for clearing rights of other persons + that may apply to the Work or any use thereof, including without limitation + any person's Copyright and Related Rights in the Work. Further, Affirmer + disclaims responsibility for obtaining any necessary consents, permissions + or other rights required for any use of the Work. + + d. Affirmer understands and acknowledges that Creative Commons is not a + party to this document and has no duty or obligation with respect to this + CC0 or use of the Work. + +For more information, please see + diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/address.c b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/address.c new file mode 100644 index 0000000000..d49d9f3b6b --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/address.c @@ -0,0 +1,95 @@ +#include +#include + +#include "address.h" +#include "params.h" +#include "utils.h" + +/* + * Specify which level of Merkle tree (the "layer") we're working on + */ +void set_layer_addr(uint32_t addr[8], uint32_t layer) { + ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; +} + +/* + * Specify which Merkle tree within the level (the "tree address") we're working on + */ +void set_tree_addr(uint32_t addr[8], uint64_t tree) { + ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); +} + +/* + * Specify the reason we'll use this address structure for, that is, what + * hash will we compute with it. This is used so that unrelated types of + * hashes don't accidentally get the same address structure. The type will be + * one of the SPX_ADDR_TYPE constants + */ +void set_type(uint32_t addr[8], uint32_t type) { + ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; +} + +/* + * Copy the layer and tree fields of the address structure. This is used + * when we're doing multiple types of hashes within the same Merkle tree + */ +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); +} + +/* These functions are used for OTS addresses. */ + +/* + * Specify which Merkle leaf we're working on; that is, which OTS keypair + * we're talking about. + */ +void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { + /* We have > 256 OTS at the bottom of the Merkle tree; to specify */ + /* which one, we'd need to express it in two bytes */ + ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR2] = (unsigned char)(keypair >> 8); + ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; +} + +/* + * Copy the layer, tree and keypair fields of the address structure. This is + * used when we're doing multiple things within the same OTS keypair + */ +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); + ((unsigned char *)out)[SPX_OFFSET_KP_ADDR2] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR2]; + ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; +} + +/* + * Specify which Merkle chain within the OTS we're working with + * (the chain address) + */ +void set_chain_addr(uint32_t addr[8], uint32_t chain) { + ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; +} + +/* + * Specify where in the Merkle chain we are +* (the hash address) + */ +void set_hash_addr(uint32_t addr[8], uint32_t hash) { + ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; +} + +/* These functions are used for all hash tree addresses (including FORS). */ + +/* + * Specify the height of the node in the Merkle/FORS tree we are in + * (the tree height) + */ +void set_tree_height(uint32_t addr[8], uint32_t tree_height) { + ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; +} + +/* + * Specify the distance from the left edge of the node in the Merkle/FORS tree + * (the tree index) + */ +void set_tree_index(uint32_t addr[8], uint32_t tree_index) { + u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/address.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/address.h new file mode 100644 index 0000000000..24a84eb40c --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/address.h @@ -0,0 +1,52 @@ +#ifndef SPX_ADDRESS_H +#define SPX_ADDRESS_H + +#include + +#include "params.h" + +/* The hash types that are passed to set_type */ +#define SPX_ADDR_TYPE_WOTS 0 +#define SPX_ADDR_TYPE_WOTSPK 1 +#define SPX_ADDR_TYPE_HASHTREE 2 +#define SPX_ADDR_TYPE_FORSTREE 3 +#define SPX_ADDR_TYPE_FORSPK 4 +#define SPX_ADDR_TYPE_WOTSPRF 5 +#define SPX_ADDR_TYPE_FORSPRF 6 + +#define set_layer_addr SPX_NAMESPACE(set_layer_addr) +void set_layer_addr(uint32_t addr[8], uint32_t layer); + +#define set_tree_addr SPX_NAMESPACE(set_tree_addr) +void set_tree_addr(uint32_t addr[8], uint64_t tree); + +#define set_type SPX_NAMESPACE(set_type) +void set_type(uint32_t addr[8], uint32_t type); + +/* Copies the layer and tree part of one address into the other */ +#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); + +/* These functions are used for WOTS and FORS addresses. */ + +#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) +void set_keypair_addr(uint32_t addr[8], uint32_t keypair); + +#define set_chain_addr SPX_NAMESPACE(set_chain_addr) +void set_chain_addr(uint32_t addr[8], uint32_t chain); + +#define set_hash_addr SPX_NAMESPACE(set_hash_addr) +void set_hash_addr(uint32_t addr[8], uint32_t hash); + +#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); + +/* These functions are used for all hash tree addresses (including FORS). */ + +#define set_tree_height SPX_NAMESPACE(set_tree_height) +void set_tree_height(uint32_t addr[8], uint32_t tree_height); + +#define set_tree_index SPX_NAMESPACE(set_tree_index) +void set_tree_index(uint32_t addr[8], uint32_t tree_index); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/api.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/api.h new file mode 100644 index 0000000000..96aeb5eb9c --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/api.h @@ -0,0 +1,77 @@ +#ifndef PQCLEAN_SPHINCSSHAKE128SSIMPLE_AVX2_API_H +#define PQCLEAN_SPHINCSSHAKE128SSIMPLE_AVX2_API_H + +#include +#include + +#define PQCLEAN_SPHINCSSHAKE128SSIMPLE_AVX2_CRYPTO_ALGNAME "SPHINCS+-shake-128s-simple" + +#define PQCLEAN_SPHINCSSHAKE128SSIMPLE_AVX2_CRYPTO_SECRETKEYBYTES 64 +#define PQCLEAN_SPHINCSSHAKE128SSIMPLE_AVX2_CRYPTO_PUBLICKEYBYTES 32 +#define PQCLEAN_SPHINCSSHAKE128SSIMPLE_AVX2_CRYPTO_BYTES 7856 + +#define PQCLEAN_SPHINCSSHAKE128SSIMPLE_AVX2_CRYPTO_SEEDBYTES 48 + +/* + * Returns the length of a secret key, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE128SSIMPLE_AVX2_crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE128SSIMPLE_AVX2_crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE128SSIMPLE_AVX2_crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE128SSIMPLE_AVX2_crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +int PQCLEAN_SPHINCSSHAKE128SSIMPLE_AVX2_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +int PQCLEAN_SPHINCSSHAKE128SSIMPLE_AVX2_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +int PQCLEAN_SPHINCSSHAKE128SSIMPLE_AVX2_crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +int PQCLEAN_SPHINCSSHAKE128SSIMPLE_AVX2_crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, + const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +int PQCLEAN_SPHINCSSHAKE128SSIMPLE_AVX2_crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +int PQCLEAN_SPHINCSSHAKE128SSIMPLE_AVX2_crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/context.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/context.h new file mode 100644 index 0000000000..6e0a33f3b7 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/context.h @@ -0,0 +1,19 @@ +#ifndef SPX_CONTEXT_H +#define SPX_CONTEXT_H + +#include + +#include "params.h" + +typedef struct { + uint8_t pub_seed[SPX_N]; + uint8_t sk_seed[SPX_N]; +} spx_ctx; + +#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) +void initialize_hash_function(spx_ctx *ctx); + +#define free_hash_function SPX_NAMESPACE(free_hash_function) +void free_hash_function(spx_ctx *ctx); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/context_shake.c b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/context_shake.c new file mode 100644 index 0000000000..9614a103d3 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/context_shake.c @@ -0,0 +1,12 @@ +#include "context.h" + +/* For SHAKE256, there is no immediate reason to initialize at the start, + so this function is an empty operation. */ +void initialize_hash_function(spx_ctx *ctx) { + (void)ctx; /* Suppress an 'unused parameter' warning. */ +} + +// in case the hash function api is heap-based. +void free_hash_function(spx_ctx *ctx) { + (void)ctx; +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/fips202x4.c b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/fips202x4.c new file mode 100644 index 0000000000..1e06fef186 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/fips202x4.c @@ -0,0 +1,210 @@ +#include +#include +#include + +#include "fips202.h" +#include "fips202x4.h" + +#define NROUNDS 24 +#define ROL(a, offset) (((a) << (offset)) ^ ((a) >> (64-(offset)))) + +static uint64_t load64(const unsigned char *x) { + unsigned long long r = 0, i; + + for (i = 0; i < 8; ++i) { + r |= (unsigned long long)x[i] << 8 * i; + } + return r; +} + +static void store64(uint8_t *x, uint64_t u) { + unsigned int i; + + for (i = 0; i < 8; ++i) { + x[i] = (uint8_t)u; + u >>= 8; + } +} + +/* Use implementation from the Keccak Code Package */ +extern void KeccakP1600times4_PermuteAll_24rounds(__m256i *s); +#define KeccakF1600_StatePermute4x KeccakP1600times4_PermuteAll_24rounds + +static void keccak_absorb4x(__m256i *s, + unsigned int r, + const unsigned char *m0, + const unsigned char *m1, + const unsigned char *m2, + const unsigned char *m3, + unsigned long long int mlen, + unsigned char p) { + unsigned long long i; + unsigned char t0[200]; + unsigned char t1[200]; + unsigned char t2[200]; + unsigned char t3[200]; + + unsigned long long *ss = (unsigned long long *)s; + + + while (mlen >= r) { + for (i = 0; i < r / 8; ++i) { + ss[4 * i + 0] ^= load64(m0 + 8 * i); + ss[4 * i + 1] ^= load64(m1 + 8 * i); + ss[4 * i + 2] ^= load64(m2 + 8 * i); + ss[4 * i + 3] ^= load64(m3 + 8 * i); + } + + KeccakF1600_StatePermute4x(s); + mlen -= r; + m0 += r; + m1 += r; + m2 += r; + m3 += r; + } + + for (i = 0; i < r; ++i) { + t0[i] = 0; + t1[i] = 0; + t2[i] = 0; + t3[i] = 0; + } + for (i = 0; i < mlen; ++i) { + t0[i] = m0[i]; + t1[i] = m1[i]; + t2[i] = m2[i]; + t3[i] = m3[i]; + } + + t0[i] = p; + t1[i] = p; + t2[i] = p; + t3[i] = p; + + t0[r - 1] |= 128; + t1[r - 1] |= 128; + t2[r - 1] |= 128; + t3[r - 1] |= 128; + + for (i = 0; i < r / 8; ++i) { + ss[4 * i + 0] ^= load64(t0 + 8 * i); + ss[4 * i + 1] ^= load64(t1 + 8 * i); + ss[4 * i + 2] ^= load64(t2 + 8 * i); + ss[4 * i + 3] ^= load64(t3 + 8 * i); + } +} + + +static void keccak_squeezeblocks4x(unsigned char *h0, + unsigned char *h1, + unsigned char *h2, + unsigned char *h3, + unsigned long long int nblocks, + __m256i *s, + unsigned int r) { + unsigned int i; + + unsigned long long *ss = (unsigned long long *)s; + + while (nblocks > 0) { + KeccakF1600_StatePermute4x(s); + for (i = 0; i < (r >> 3); i++) { + store64(h0 + 8 * i, ss[4 * i + 0]); + store64(h1 + 8 * i, ss[4 * i + 1]); + store64(h2 + 8 * i, ss[4 * i + 2]); + store64(h3 + 8 * i, ss[4 * i + 3]); + } + h0 += r; + h1 += r; + h2 += r; + h3 += r; + nblocks--; + } +} + + + +void shake128x4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, unsigned long long outlen, + unsigned char *in0, + unsigned char *in1, + unsigned char *in2, + unsigned char *in3, unsigned long long inlen) { + __m256i s[25]; + unsigned char t0[SHAKE128_RATE]; + unsigned char t1[SHAKE128_RATE]; + unsigned char t2[SHAKE128_RATE]; + unsigned char t3[SHAKE128_RATE]; + unsigned int i; + + /* zero state */ + for (i = 0; i < 25; i++) { + s[i] = _mm256_xor_si256(s[i], s[i]); + } + + /* absorb 4 message of identical length in parallel */ + keccak_absorb4x(s, SHAKE128_RATE, in0, in1, in2, in3, inlen, 0x1F); + + /* Squeeze output */ + keccak_squeezeblocks4x(out0, out1, out2, out3, outlen / SHAKE128_RATE, s, SHAKE128_RATE); + + out0 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; + out1 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; + out2 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; + out3 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; + + if (outlen % SHAKE128_RATE) { + keccak_squeezeblocks4x(t0, t1, t2, t3, 1, s, SHAKE128_RATE); + for (i = 0; i < outlen % SHAKE128_RATE; i++) { + out0[i] = t0[i]; + out1[i] = t1[i]; + out2[i] = t2[i]; + out3[i] = t3[i]; + } + } +} + + +void shake256x4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, unsigned long long outlen, + unsigned char *in0, + unsigned char *in1, + unsigned char *in2, + unsigned char *in3, unsigned long long inlen) { + __m256i s[25]; + unsigned char t0[SHAKE256_RATE]; + unsigned char t1[SHAKE256_RATE]; + unsigned char t2[SHAKE256_RATE]; + unsigned char t3[SHAKE256_RATE]; + unsigned int i; + + /* zero state */ + for (i = 0; i < 25; i++) { + s[i] = _mm256_xor_si256(s[i], s[i]); + } + + /* absorb 4 message of identical length in parallel */ + keccak_absorb4x(s, SHAKE256_RATE, in0, in1, in2, in3, inlen, 0x1F); + + /* Squeeze output */ + keccak_squeezeblocks4x(out0, out1, out2, out3, outlen / SHAKE256_RATE, s, SHAKE256_RATE); + + out0 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; + out1 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; + out2 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; + out3 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; + + if (outlen % SHAKE256_RATE) { + keccak_squeezeblocks4x(t0, t1, t2, t3, 1, s, SHAKE256_RATE); + for (i = 0; i < outlen % SHAKE256_RATE; i++) { + out0[i] = t0[i]; + out1[i] = t1[i]; + out2[i] = t2[i]; + out3[i] = t3[i]; + } + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/fips202x4.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/fips202x4.h new file mode 100644 index 0000000000..2b93c9cd0d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/fips202x4.h @@ -0,0 +1,28 @@ +#ifndef SPX_FIPS202X4_H +#define SPX_FIPS202X4_H + +#include + +#include "params.h" + +#define shake128x4 SPX_NAMESPACE(shake128x4) +void shake128x4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, unsigned long long outlen, + unsigned char *in0, + unsigned char *in1, + unsigned char *in2, + unsigned char *in3, unsigned long long inlen); + +#define shake256x4 SPX_NAMESPACE(shake256x4) +void shake256x4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, unsigned long long outlen, + unsigned char *in0, + unsigned char *in1, + unsigned char *in2, + unsigned char *in3, unsigned long long inlen); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/fors.c b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/fors.c new file mode 100644 index 0000000000..f1b0639cfc --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/fors.c @@ -0,0 +1,202 @@ +#include +#include +#include + +#include "fors.h" + +#include "address.h" +#include "hash.h" +#include "hashx4.h" +#include "thash.h" +#include "thashx4.h" +#include "utils.h" +#include "utilsx4.h" + +static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + prf_addr(sk, ctx, fors_leaf_addr); +} + +static void fors_gen_skx4(unsigned char *sk0, + unsigned char *sk1, + unsigned char *sk2, + unsigned char *sk3, const spx_ctx *ctx, + uint32_t fors_leaf_addrx4[4 * 8]) { + prf_addrx4(sk0, sk1, sk2, sk3, + ctx, fors_leaf_addrx4); +} + +static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, + const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + thash(leaf, sk, 1, ctx, fors_leaf_addr); +} + +static void fors_sk_to_leafx4(unsigned char *leaf0, + unsigned char *leaf1, + unsigned char *leaf2, + unsigned char *leaf3, + const unsigned char *sk0, + const unsigned char *sk1, + const unsigned char *sk2, + const unsigned char *sk3, + const spx_ctx *ctx, + uint32_t fors_leaf_addrx4[4 * 8]) { + thashx4(leaf0, leaf1, leaf2, leaf3, + sk0, sk1, sk2, sk3, + 1, ctx, fors_leaf_addrx4); +} + +struct fors_gen_leaf_info { + uint32_t leaf_addrx[4 * 8]; +}; + +static void fors_gen_leafx4(unsigned char *leaf, + const spx_ctx *ctx, + uint32_t addr_idx, void *info) { + struct fors_gen_leaf_info *fors_info = info; + uint32_t *fors_leaf_addrx4 = fors_info->leaf_addrx; + unsigned int j; + + /* Only set the parts that the caller doesn't set */ + for (j = 0; j < 4; j++) { + set_tree_index(fors_leaf_addrx4 + j * 8, addr_idx + j); + set_type(fors_leaf_addrx4 + j * 8, SPX_ADDR_TYPE_FORSPRF); + } + + fors_gen_skx4(leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + leaf + 2 * SPX_N, + leaf + 3 * SPX_N, + ctx, fors_leaf_addrx4); + + for (j = 0; j < 4; j++) { + set_type(fors_leaf_addrx4 + j * 8, SPX_ADDR_TYPE_FORSTREE); + } + + fors_sk_to_leafx4(leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + leaf + 2 * SPX_N, + leaf + 3 * SPX_N, + leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + leaf + 2 * SPX_N, + leaf + 3 * SPX_N, + ctx, fors_leaf_addrx4); +} + +/** + * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + * Assumes indices has space for SPX_FORS_TREES integers. + */ +static void message_to_indices(uint32_t *indices, const unsigned char *m) { + unsigned int i, j; + unsigned int offset = 0; + + for (i = 0; i < SPX_FORS_TREES; i++) { + indices[i] = 0; + for (j = 0; j < SPX_FORS_HEIGHT; j++) { + indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); + offset++; + } + } +} + +/** + * Signs a message m, deriving the secret key from sk_seed and the FTS address. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + uint32_t fors_tree_addr[4 * 8] = {0}; + struct fors_gen_leaf_info fors_info = {0}; + uint32_t *fors_leaf_addr = fors_info.leaf_addrx; + uint32_t fors_pk_addr[8] = {0}; + uint32_t idx_offset; + unsigned int i; + + for (i = 0; i < 4; i++) { + copy_keypair_addr(fors_tree_addr + 8 * i, fors_addr); + set_type(fors_tree_addr + 8 * i, SPX_ADDR_TYPE_FORSTREE); + copy_keypair_addr(fors_leaf_addr + 8 * i, fors_addr); + } + copy_keypair_addr(fors_pk_addr, fors_addr); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); + + message_to_indices(indices, m); + + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); + + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + + /* Include the secret key part that produces the selected leaf node. */ + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); + fors_gen_sk(sig, ctx, fors_tree_addr); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + sig += SPX_N; + + /* Compute the authentication path for this leaf node. */ + treehashx4(roots + i * SPX_N, sig, ctx, + indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx4, + fors_tree_addr, &fors_info); + + sig += SPX_N * SPX_FORS_HEIGHT; + } + + /* Hash horizontally across all tree roots to derive the public key. */ + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); +} + +/** + * Derives the FORS public key from a signature. + * This can be used for verification by comparing to a known public key, or to + * subsequently verify a signature on the derived public key. The latter is the + * typical use-case when used as an FTS below an OTS in a hypertree. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + unsigned char leaf[SPX_N]; + uint32_t fors_tree_addr[8] = {0}; + uint32_t fors_pk_addr[8] = {0}; + uint32_t idx_offset; + unsigned int i; + + copy_keypair_addr(fors_tree_addr, fors_addr); + copy_keypair_addr(fors_pk_addr, fors_addr); + + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); + + message_to_indices(indices, m); + + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); + + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + + /* Derive the leaf from the included secret key part. */ + fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); + sig += SPX_N; + + /* Derive the corresponding root node of this tree. */ + compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, + sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); + sig += SPX_N * SPX_FORS_HEIGHT; + } + + /* Hash horizontally across all tree roots to derive the public key. */ + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/fors.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/fors.h new file mode 100644 index 0000000000..509140a178 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/fors.h @@ -0,0 +1,32 @@ +#ifndef SPX_FORS_H +#define SPX_FORS_H + +#include + +#include "context.h" +#include "params.h" + +/** + * Signs a message m, deriving the secret key from sk_seed and the FTS address. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +#define fors_sign SPX_NAMESPACE(fors_sign) +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); + +/** + * Derives the FORS public key from a signature. + * This can be used for verification by comparing to a known public key, or to + * subsequently verify a signature on the derived public key. The latter is the + * typical use-case when used as an FTS below an OTS in a hypertree. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/hash.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/hash.h new file mode 100644 index 0000000000..f7c87d4c3c --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/hash.h @@ -0,0 +1,28 @@ +#ifndef SPX_HASH_H +#define SPX_HASH_H + +#include +#include + +#include "context.h" +#include "params.h" + +#define prf_addr SPX_NAMESPACE(prf_addr) +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]); + +#define gen_message_random SPX_NAMESPACE(gen_message_random) +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); + +#define hash_message SPX_NAMESPACE(hash_message) +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); + + + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/hash_shake.c b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/hash_shake.c new file mode 100644 index 0000000000..ff5e7ec918 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/hash_shake.c @@ -0,0 +1,83 @@ +#include +#include + +#include "hash.h" + +#include "address.h" +#include "fips202.h" +#include "params.h" +#include "utils.h" + +/* + * Computes PRF(pk_seed, sk_seed, addr) + */ +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]) { + unsigned char buf[2 * SPX_N + SPX_ADDR_BYTES]; + + memcpy(buf, ctx->pub_seed, SPX_N); + memcpy(buf + SPX_N, addr, SPX_ADDR_BYTES); + memcpy(buf + SPX_N + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); + + shake256(out, SPX_N, buf, 2 * SPX_N + SPX_ADDR_BYTES); +} + +/** + * Computes the message-dependent randomness R, using a secret seed and an + * optional randomization value as well as the message. + */ +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { + (void)ctx; + shake256incctx s_inc; + + shake256_inc_init(&s_inc); + shake256_inc_absorb(&s_inc, sk_prf, SPX_N); + shake256_inc_absorb(&s_inc, optrand, SPX_N); + shake256_inc_absorb(&s_inc, m, mlen); + shake256_inc_finalize(&s_inc); + shake256_inc_squeeze(R, SPX_N, &s_inc); + shake256_inc_ctx_release(&s_inc); +} + +/** + * Computes the message hash using R, the public key, and the message. + * Outputs the message digest and the index of the leaf. The index is split in + * the tree index and the leaf index, for convenient copying to an address. + */ +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { + (void)ctx; +#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) +#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) +#define SPX_LEAF_BITS SPX_TREE_HEIGHT +#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) +#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) + + unsigned char buf[SPX_DGST_BYTES]; + unsigned char *bufp = buf; + shake256incctx s_inc; + + shake256_inc_init(&s_inc); + shake256_inc_absorb(&s_inc, R, SPX_N); + shake256_inc_absorb(&s_inc, pk, SPX_PK_BYTES); + shake256_inc_absorb(&s_inc, m, mlen); + shake256_inc_finalize(&s_inc); + shake256_inc_squeeze(buf, SPX_DGST_BYTES, &s_inc); + shake256_inc_ctx_release(&s_inc); + + memcpy(digest, bufp, SPX_FORS_MSG_BYTES); + bufp += SPX_FORS_MSG_BYTES; + + + *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); + *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); + bufp += SPX_TREE_BYTES; + + *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); + *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/hash_shakex4.c b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/hash_shakex4.c new file mode 100644 index 0000000000..bbd22eb117 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/hash_shakex4.c @@ -0,0 +1,64 @@ +#include +#include + +#include "hashx4.h" + +#include "address.h" +#include "fips202x4.h" +#include "params.h" + +extern void KeccakP1600times4_PermuteAll_24rounds(__m256i *s); + +/* + * 4-way parallel version of prf_addr; takes 4x as much input and output + */ +void prf_addrx4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const spx_ctx *ctx, + const uint32_t addrx4[4 * 8]) { + /* As we write and read only a few quadwords, it is more efficient to + * build and extract from the fourway SHAKE256 state by hand. */ + __m256i state[25]; + + for (int i = 0; i < SPX_N / 8; i++) { + state[i] = _mm256_set1_epi64x(((int64_t *)ctx->pub_seed)[i]); + } + for (int i = 0; i < 4; i++) { + state[SPX_N / 8 + i] = _mm256_set_epi32( + (int)addrx4[3 * 8 + 1 + 2 * i], + (int)addrx4[3 * 8 + 2 * i], + (int)addrx4[2 * 8 + 1 + 2 * i], + (int)addrx4[2 * 8 + 2 * i], + (int)addrx4[8 + 1 + 2 * i], + (int)addrx4[8 + 2 * i], + (int)addrx4[1 + 2 * i], + (int)addrx4[2 * i] + ); + } + for (int i = 0; i < SPX_N / 8; i++) { + state[SPX_N / 8 + i + 4] = _mm256_set1_epi64x(((int64_t *)ctx->sk_seed)[i]); + } + + /* SHAKE domain separator and padding. */ + state[SPX_N / 4 + 4] = _mm256_set1_epi64x(0x1f); + for (int i = SPX_N / 4 + 5; i < 16; i++) { + state[i] = _mm256_set1_epi64x(0); + } + // shift unsigned and then cast to avoid UB + state[16] = _mm256_set1_epi64x((long long)(0x80ULL << 56)); + + for (int i = 17; i < 25; i++) { + state[i] = _mm256_set1_epi64x(0); + } + + KeccakP1600times4_PermuteAll_24rounds(&state[0]); + + for (int i = 0; i < SPX_N / 8; i++) { + ((int64_t *)out0)[i] = _mm256_extract_epi64(state[i], 0); + ((int64_t *)out1)[i] = _mm256_extract_epi64(state[i], 1); + ((int64_t *)out2)[i] = _mm256_extract_epi64(state[i], 2); + ((int64_t *)out3)[i] = _mm256_extract_epi64(state[i], 3); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/hashx4.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/hashx4.h new file mode 100644 index 0000000000..3751a0ebd0 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/hashx4.h @@ -0,0 +1,17 @@ +#ifndef SPX_HASHX4_H +#define SPX_HASHX4_H + +#include + +#include "context.h" +#include "params.h" + +#define prf_addrx4 SPX_NAMESPACE(prf_addrx4) +void prf_addrx4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const spx_ctx *ctx, + const uint32_t addrx4[4 * 8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/merkle.c b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/merkle.c new file mode 100644 index 0000000000..f57811c1ac --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/merkle.c @@ -0,0 +1,64 @@ +#include +#include + +#include "merkle.h" + +#include "address.h" +#include "params.h" +#include "utils.h" +#include "utilsx4.h" +#include "wots.h" +#include "wotsx4.h" + +/* + * This generates a Merkle signature (WOTS signature followed by the Merkle + * authentication path). + */ +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf) { + unsigned char *auth_path = sig + SPX_WOTS_BYTES; + uint32_t tree_addrx4[4 * 8] = { 0 }; + int j; + struct leaf_info_x4 info = { 0 }; + unsigned steps[ SPX_WOTS_LEN ]; + + info.wots_sig = sig; + chain_lengths(steps, root); + info.wots_steps = steps; + + for (j = 0; j < 4; j++) { + set_type(&tree_addrx4[8 * j], SPX_ADDR_TYPE_HASHTREE); + set_type(&info.leaf_addr[8 * j], SPX_ADDR_TYPE_WOTS); + set_type(&info.pk_addr[8 * j], SPX_ADDR_TYPE_WOTSPK); + copy_subtree_addr(&tree_addrx4[8 * j], tree_addr); + copy_subtree_addr(&info.leaf_addr[8 * j], wots_addr); + copy_subtree_addr(&info.pk_addr[8 * j], wots_addr); + } + + info.wots_sign_leaf = idx_leaf; + + treehashx4(root, auth_path, ctx, + idx_leaf, 0, + SPX_TREE_HEIGHT, + wots_gen_leafx4, + tree_addrx4, &info); +} + +/* Compute root node of the top-most subtree. */ +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { + /* We do not need the auth path in key generation, but it simplifies the + code to have just one treehash routine that computes both root and path + in one function. */ + unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; + uint32_t top_tree_addr[8] = {0}; + uint32_t wots_addr[8] = {0}; + + set_layer_addr(top_tree_addr, SPX_D - 1); + set_layer_addr(wots_addr, SPX_D - 1); + + merkle_sign(auth_path, root, ctx, + wots_addr, top_tree_addr, + ~0U /* ~0 means "don't bother generating an auth path */ ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/merkle.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/merkle.h new file mode 100644 index 0000000000..769cf2e970 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/merkle.h @@ -0,0 +1,21 @@ +#ifndef MERKLE_H_ +#define MERKLE_H_ + +#include + +#include "context.h" +#include "params.h" + +/* Generate a Merkle signature (WOTS signature followed by the Merkle */ +/* authentication path) */ +#define merkle_sign SPX_NAMESPACE(merkle_sign) +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf); + +/* Compute the root node of the top-most subtree. */ +#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); + +#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/nistapi.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/nistapi.h new file mode 100644 index 0000000000..3cb71afad4 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/nistapi.h @@ -0,0 +1,87 @@ +#ifndef SPX_API_H +#define SPX_API_H + +#include +#include + +#include "params.h" + +#define CRYPTO_ALGNAME "SPHINCS+" + +#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES +#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES +#define CRYPTO_BYTES SPX_BYTES +#define CRYPTO_SEEDBYTES (3*SPX_N) + +/* + * Returns the length of a secret key, in bytes + */ +#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) +size_t crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) +size_t crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) +size_t crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) +size_t crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +#define crypto_sign SPX_NAMESPACE(crypto_sign) +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/params.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/params.h new file mode 100644 index 0000000000..4a7618dc05 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/params.h @@ -0,0 +1,56 @@ +#ifndef SPX_PARAMS_H +#define SPX_PARAMS_H + +#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSSHAKE128SSIMPLE_AVX2_##s + +/* Hash output length in bytes. */ +#define SPX_N 16 +/* Height of the hypertree. */ +#define SPX_FULL_HEIGHT 63 +/* Number of subtree layer. */ +#define SPX_D 7 +/* FORS tree dimensions. */ +#define SPX_FORS_HEIGHT 12 +#define SPX_FORS_TREES 14 +/* Winternitz parameter, */ +#define SPX_WOTS_W 16 + +/* The hash function is defined by linking a different hash.c file, as opposed + to setting a #define constant. */ + +/* For clarity */ +#define SPX_ADDR_BYTES 32 + +/* WOTS parameters. */ +#define SPX_WOTS_LOGW 4 + +#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) + +/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ +#define SPX_WOTS_LEN2 3 + +#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) +#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) +#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES + +/* Subtree size. */ +#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) + +//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT +// #error SPX_D should always divide SPX_FULL_HEIGHT +//#endif + +/* FORS parameters. */ +#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) +#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) +#define SPX_FORS_PK_BYTES SPX_N + +/* Resulting SPX sizes. */ +#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ + SPX_FULL_HEIGHT * SPX_N) +#define SPX_PK_BYTES (2 * SPX_N) +#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) + +#include "shake_offsets.h" + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/shake_offsets.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/shake_offsets.h new file mode 100644 index 0000000000..6b28d95d91 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/shake_offsets.h @@ -0,0 +1,21 @@ +#ifndef SHAKE_OFFSETS_H_ +#define SHAKE_OFFSETS_H_ + +/* + * Offsets of various fields in the address structure when we use SHAKE as + * the Sphincs+ hash function + */ + +#define SPX_OFFSET_LAYER 3 /* The byte used to specify the Merkle tree layer */ +#define SPX_OFFSET_TREE 8 /* The start of the 8 byte field used to specify the tree */ +#define SPX_OFFSET_TYPE 19 /* The byte used to specify the hash type (reason) */ +#define SPX_OFFSET_KP_ADDR2 22 /* The high byte used to specify the key pair (which one-time signature) */ +#define SPX_OFFSET_KP_ADDR1 23 /* The low byte used to specify the key pair */ +#define SPX_OFFSET_CHAIN_ADDR 27 /* The byte used to specify the chain address (which Winternitz chain) */ +#define SPX_OFFSET_HASH_ADDR 31 /* The byte used to specify the hash address (where in the Winternitz chain) */ +#define SPX_OFFSET_TREE_HGT 27 /* The byte used to specify the height of this node in the FORS or Merkle tree */ +#define SPX_OFFSET_TREE_INDEX 28 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ + +#define SPX_SHAKE 1 + +#endif /* SHAKE_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/sign.c b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/sign.c new file mode 100644 index 0000000000..9d0c7d1b22 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/sign.c @@ -0,0 +1,286 @@ +#include +#include +#include + +#include "address.h" +#include "context.h" +#include "fors.h" +#include "hash.h" +#include "merkle.h" +#include "nistapi.h" +#include "params.h" +#include "randombytes.h" +#include "thash.h" +#include "utils.h" +#include "wots.h" + +/* + * Returns the length of a secret key, in bytes + */ +size_t crypto_sign_secretkeybytes(void) { + return CRYPTO_SECRETKEYBYTES; +} + +/* + * Returns the length of a public key, in bytes + */ +size_t crypto_sign_publickeybytes(void) { + return CRYPTO_PUBLICKEYBYTES; +} + +/* + * Returns the length of a signature, in bytes + */ +size_t crypto_sign_bytes(void) { + return CRYPTO_BYTES; +} + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +size_t crypto_sign_seedbytes(void) { + return CRYPTO_SEEDBYTES; +} + +/* + * Generates an SPX key pair given a seed of length + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [PUB_SEED || root] + */ +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed) { + spx_ctx ctx; + + /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ + memcpy(sk, seed, CRYPTO_SEEDBYTES); + + memcpy(pk, sk + 2 * SPX_N, SPX_N); + + memcpy(ctx.pub_seed, pk, SPX_N); + memcpy(ctx.sk_seed, sk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + /* Compute root node of the top-most subtree. */ + merkle_gen_root(sk + 3 * SPX_N, &ctx); + + // cleanup + free_hash_function(&ctx); + + memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); + + return 0; +} + +/* + * Generates an SPX key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [PUB_SEED || root] + */ +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { + uint8_t seed[CRYPTO_SEEDBYTES]; + randombytes(seed, CRYPTO_SEEDBYTES); + crypto_sign_seed_keypair(pk, sk, seed); + + return 0; +} + +/** + * Returns an array containing a detached signature. + */ +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk) { + spx_ctx ctx; + + const uint8_t *sk_prf = sk + SPX_N; + const uint8_t *pk = sk + 2 * SPX_N; + + uint8_t optrand[SPX_N]; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t root[SPX_N]; + uint32_t i; + uint64_t tree; + uint32_t idx_leaf; + uint32_t wots_addr[8] = {0}; + uint32_t tree_addr[8] = {0}; + + memcpy(ctx.sk_seed, sk, SPX_N); + memcpy(ctx.pub_seed, pk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + + /* Optionally, signing can be made non-deterministic using optrand. + This can help counter side-channel attacks that would benefit from + getting a large number of traces when the signer uses the same nodes. */ + randombytes(optrand, SPX_N); + /* Compute the digest randomization value. */ + gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); + + /* Derive the message digest and leaf index from R, PK and M. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; + + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); + + /* Sign the message hash using FORS. */ + fors_sign(sig, root, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); + sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; + + /* Update the indices for the next layer. */ + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; + } + + free_hash_function(&ctx); + + *siglen = SPX_BYTES; + + return 0; +} + +/** + * Verifies a detached signature and message under a given public key. + */ +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk) { + spx_ctx ctx; + const uint8_t *pub_root = pk + SPX_N; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t wots_pk[SPX_WOTS_BYTES]; + uint8_t root[SPX_N]; + uint8_t leaf[SPX_N]; + unsigned int i; + uint64_t tree; + uint32_t idx_leaf; + uint32_t wots_addr[8] = {0}; + uint32_t tree_addr[8] = {0}; + uint32_t wots_pk_addr[8] = {0}; + + if (siglen != SPX_BYTES) { + return -1; + } + + memcpy(ctx.pub_seed, pk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); + + /* Derive the message digest and leaf index from R || PK || M. */ + /* The additional SPX_N is a result of the hash domain separator. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; + + /* Layer correctly defaults to 0, so no need to set_layer_addr */ + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); + + fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + /* For each subtree.. */ + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + copy_keypair_addr(wots_pk_addr, wots_addr); + + /* The WOTS public key is only correct if the signature was correct. */ + /* Initially, root is the FORS pk, but on subsequent iterations it is + the root of the subtree below the currently processed subtree. */ + wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); + sig += SPX_WOTS_BYTES; + + /* Compute the leaf node using the WOTS public key. */ + thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); + + /* Compute the root node of this subtree. */ + compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, + &ctx, tree_addr); + sig += SPX_TREE_HEIGHT * SPX_N; + + /* Update the indices for the next layer. */ + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; + } + + // cleanup + free_hash_function(&ctx); + + /* Check if the root node equals the root node in the public key. */ + if (memcmp(root, pub_root, SPX_N) != 0) { + return -1; + } + + return 0; +} + + +/** + * Returns an array containing the signature followed by the message. + */ +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk) { + size_t siglen; + + crypto_sign_signature(sm, &siglen, m, mlen, sk); + + memmove(sm + SPX_BYTES, m, mlen); + *smlen = siglen + mlen; + + return 0; +} + +/** + * Verifies a given signature-message pair under a given public key. + */ +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk) { + /* The API caller does not necessarily know what size a signature should be + but SPHINCS+ signatures are always exactly SPX_BYTES. */ + if (smlen < SPX_BYTES) { + memset(m, 0, smlen); + *mlen = 0; + return -1; + } + + *mlen = smlen - SPX_BYTES; + + if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { + memset(m, 0, smlen); + *mlen = 0; + return -1; + } + + /* If verification was successful, move the message to the right place. */ + memmove(m, sm + SPX_BYTES, *mlen); + + return 0; +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/thash.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/thash.h new file mode 100644 index 0000000000..8687ccfb4d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/thash.h @@ -0,0 +1,13 @@ +#ifndef SPX_THASH_H +#define SPX_THASH_H + +#include "context.h" +#include "params.h" + +#include + +#define thash SPX_NAMESPACE(thash) +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/thash_shake_simple.c b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/thash_shake_simple.c new file mode 100644 index 0000000000..98470395e9 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/thash_shake_simple.c @@ -0,0 +1,24 @@ +#include +#include + +#include "thash.h" + +#include "address.h" +#include "params.h" +#include "utils.h" + +#include "fips202.h" + +/** + * Takes an array of inblocks concatenated arrays of SPX_N bytes. + */ +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]) { + PQCLEAN_VLA(uint8_t, buf, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); + + memcpy(buf, ctx->pub_seed, SPX_N); + memcpy(buf + SPX_N, addr, SPX_ADDR_BYTES); + memcpy(buf + SPX_N + SPX_ADDR_BYTES, in, inblocks * SPX_N); + + shake256(out, SPX_N, buf, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/thash_shake_simplex4.c b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/thash_shake_simplex4.c new file mode 100644 index 0000000000..89dc9a4224 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/thash_shake_simplex4.c @@ -0,0 +1,98 @@ +#include +#include + +#include "thashx4.h" + +#include "address.h" +#include "params.h" +#include "utils.h" + +#include "fips202x4.h" + +extern void KeccakP1600times4_PermuteAll_24rounds(__m256i *s); + +/** + * 4-way parallel version of thash; takes 4x as much input and output + */ +void thashx4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addrx4[4 * 8]) { + if (inblocks == 1 || inblocks == 2) { + /* As we write and read only a few quadwords, it is more efficient to + * build and extract from the fourway SHAKE256 state by hand. */ + __m256i state[25]; + for (int i = 0; i < SPX_N / 8; i++) { + state[i] = _mm256_set1_epi64x(((int64_t *)ctx->pub_seed)[i]); + } + for (int i = 0; i < 4; i++) { + state[SPX_N / 8 + i] = _mm256_set_epi32( + (int)addrx4[3 * 8 + 1 + 2 * i], + (int)addrx4[3 * 8 + 2 * i], + (int)addrx4[2 * 8 + 1 + 2 * i], + (int)addrx4[2 * 8 + 2 * i], + (int)addrx4[8 + 1 + 2 * i], + (int)addrx4[8 + 2 * i], + (int)addrx4[1 + 2 * i], + (int)addrx4[2 * i] + ); + } + + for (unsigned int i = 0; i < (SPX_N / 8) * inblocks; i++) { + state[SPX_N / 8 + 4 + i] = _mm256_set_epi64x( + ((int64_t *)in3)[i], + ((int64_t *)in2)[i], + ((int64_t *)in1)[i], + ((int64_t *)in0)[i] + ); + } + + /* Domain separator and padding. */ + for (size_t i = (SPX_N / 8) * (1 + inblocks) + 4; i < 16; i++) { + state[i] = _mm256_set1_epi64x(0); + } + state[16] = _mm256_set1_epi64x((long long)(0x80ULL << 56)); + state[(SPX_N / 8) * (1 + inblocks) + 4] = _mm256_xor_si256( + state[(SPX_N / 8) * (1 + inblocks) + 4], + _mm256_set1_epi64x(0x1f) + ); + for (int i = 17; i < 25; i++) { + state[i] = _mm256_set1_epi64x(0); + } + + KeccakP1600times4_PermuteAll_24rounds(&state[0]); + + for (int i = 0; i < SPX_N / 8; i++) { + ((int64_t *)out0)[i] = _mm256_extract_epi64(state[i], 0); + ((int64_t *)out1)[i] = _mm256_extract_epi64(state[i], 1); + ((int64_t *)out2)[i] = _mm256_extract_epi64(state[i], 2); + ((int64_t *)out3)[i] = _mm256_extract_epi64(state[i], 3); + } + } else { + PQCLEAN_VLA(unsigned char, buf0, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, buf1, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, buf2, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, buf3, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); + + memcpy(buf0, ctx->pub_seed, SPX_N); + memcpy(buf1, ctx->pub_seed, SPX_N); + memcpy(buf2, ctx->pub_seed, SPX_N); + memcpy(buf3, ctx->pub_seed, SPX_N); + memcpy(buf0 + SPX_N, addrx4 + 0 * 8, SPX_ADDR_BYTES); + memcpy(buf1 + SPX_N, addrx4 + 1 * 8, SPX_ADDR_BYTES); + memcpy(buf2 + SPX_N, addrx4 + 2 * 8, SPX_ADDR_BYTES); + memcpy(buf3 + SPX_N, addrx4 + 3 * 8, SPX_ADDR_BYTES); + memcpy(buf0 + SPX_N + SPX_ADDR_BYTES, in0, inblocks * SPX_N); + memcpy(buf1 + SPX_N + SPX_ADDR_BYTES, in1, inblocks * SPX_N); + memcpy(buf2 + SPX_N + SPX_ADDR_BYTES, in2, inblocks * SPX_N); + memcpy(buf3 + SPX_N + SPX_ADDR_BYTES, in3, inblocks * SPX_N); + + shake256x4(out0, out1, out2, out3, SPX_N, + buf0, buf1, buf2, buf3, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/thashx4.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/thashx4.h new file mode 100644 index 0000000000..64798a3727 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/thashx4.h @@ -0,0 +1,20 @@ +#ifndef SPX_THASHX4_H +#define SPX_THASHX4_H + +#include + +#include "context.h" +#include "params.h" + +#define thashx4 SPX_NAMESPACE(thashx4) +void thashx4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addrx4[4 * 8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/utils.c b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/utils.c new file mode 100644 index 0000000000..177b541fb9 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/utils.c @@ -0,0 +1,148 @@ +#include + +#include "utils.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "thash.h" + +/** + * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. + */ +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in) { + int i; + + /* Iterate over out in decreasing order, for big-endianness. */ + for (i = (signed int)outlen - 1; i >= 0; i--) { + out[i] = in & 0xff; + in = in >> 8; + } +} + +void u32_to_bytes(unsigned char *out, uint32_t in) { + out[0] = (unsigned char)(in >> 24); + out[1] = (unsigned char)(in >> 16); + out[2] = (unsigned char)(in >> 8); + out[3] = (unsigned char)in; +} + +/** + * Converts the inlen bytes in 'in' from big-endian byte order to an integer. + */ +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { + unsigned long long retval = 0; + unsigned int i; + + for (i = 0; i < inlen; i++) { + retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); + } + return retval; +} + +/** + * Computes a root node given a leaf and an auth path. + * Expects address to be complete other than the tree_height and tree_index. + */ +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]) { + uint32_t i; + unsigned char buffer[2 * SPX_N]; + + /* If leaf_idx is odd (last bit = 1), current path element is a right child + and auth_path has to go left. Otherwise it is the other way around. */ + if (leaf_idx & 1) { + memcpy(buffer + SPX_N, leaf, SPX_N); + memcpy(buffer, auth_path, SPX_N); + } else { + memcpy(buffer, leaf, SPX_N); + memcpy(buffer + SPX_N, auth_path, SPX_N); + } + auth_path += SPX_N; + + for (i = 0; i < tree_height - 1; i++) { + leaf_idx >>= 1; + idx_offset >>= 1; + /* Set the address of the node we're creating. */ + set_tree_height(addr, i + 1); + set_tree_index(addr, leaf_idx + idx_offset); + + /* Pick the right or left neighbor, depending on parity of the node. */ + if (leaf_idx & 1) { + thash(buffer + SPX_N, buffer, 2, ctx, addr); + memcpy(buffer, auth_path, SPX_N); + } else { + thash(buffer, buffer, 2, ctx, addr); + memcpy(buffer + SPX_N, auth_path, SPX_N); + } + auth_path += SPX_N; + } + + /* The last iteration is exceptional; we do not copy an auth_path node. */ + leaf_idx >>= 1; + idx_offset >>= 1; + set_tree_height(addr, tree_height); + set_tree_index(addr, leaf_idx + idx_offset); + thash(root, buffer, 2, ctx, addr); +} + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx * /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]) { + PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); + PQCLEAN_VLA(unsigned int, heights, tree_height + 1); + unsigned int offset = 0; + uint32_t idx; + uint32_t tree_idx; + + for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { + /* Add the next leaf node to the stack. */ + gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); + offset++; + heights[offset - 1] = 0; + + /* If this is a node we need for the auth path.. */ + if ((leaf_idx ^ 0x1) == idx) { + memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); + } + + /* While the top-most nodes are of equal height.. */ + while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { + /* Compute index of the new node, in the next layer. */ + tree_idx = (idx >> (heights[offset - 1] + 1)); + + /* Set the address of the node we're creating. */ + set_tree_height(tree_addr, heights[offset - 1] + 1); + set_tree_index(tree_addr, + tree_idx + (idx_offset >> (heights[offset - 1] + 1))); + /* Hash the top-most nodes from the stack together. */ + thash(stack + (offset - 2)*SPX_N, + stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); + offset--; + /* Note that the top-most node is now one layer higher. */ + heights[offset - 1]++; + + /* If this is a node we need for the auth path.. */ + if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { + memcpy(auth_path + heights[offset - 1]*SPX_N, + stack + (offset - 1)*SPX_N, SPX_N); + } + } + } + memcpy(root, stack, SPX_N); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/utils.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/utils.h new file mode 100644 index 0000000000..64f5d5a53a --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/utils.h @@ -0,0 +1,58 @@ +#ifndef SPX_UTILS_H +#define SPX_UTILS_H + +#include + +#include "compat.h" +#include "context.h" +#include "params.h" + + +/* To support MSVC use alloca() instead of VLAs. See #20. */ + + +/** + * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. + */ +#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in); +#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) +void u32_to_bytes(unsigned char *out, uint32_t in); + +/** + * Converts the inlen bytes in 'in' from big-endian byte order to an integer. + */ +#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); + +/** + * Computes a root node given a leaf and an auth path. + * Expects address to be complete other than the tree_height and tree_index. + */ +#define compute_root SPX_NAMESPACE(compute_root) +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]); + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +#define treehash SPX_NAMESPACE(treehash) +void treehash(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx *ctx /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]); + + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/utilsx4.c b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/utilsx4.c new file mode 100644 index 0000000000..1638677194 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/utilsx4.c @@ -0,0 +1,138 @@ +#include + +#include "utilsx4.h" + +#include "address.h" +#include "params.h" +#include "thashx4.h" +#include "utils.h" + +/* + * Generate the entire Merkle tree, computing the authentication path for leaf_idx, + * and the resulting root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) + * + * This expects tree_addrx4 to be initialized to 4 parallel addr structures for + * the Merkle tree nodes + * + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + * + * This works by using the standard Merkle tree building algorithm, except + * that each 'node' tracked is actually 4 consecutive nodes in the real tree. + * When we combine two logical nodes ABCD and WXYZ, we perform the H + * operation on adjacent real nodes, forming the parent logical node + * (AB)(CD)(WX)(YZ) + * + * When we get to the top two levels of the real tree (where there is only + * one logical node), we continue this operation two more times; the right + * most real node will by the actual root (and the other 3 nodes will be + * garbage). We follow the same thashx4 logic so that the 'extract + * authentication path components' part of the loop is still executed (and + * to simplify the code somewhat) + * + * This currently assumes tree_height >= 2; I suspect that doing an adjusting + * idx, addr_idx on the gen_leafx4 call if tree_height < 2 would fix it; since + * we don't actually use such short trees, I haven't bothered + */ +void treehashx4(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, + uint32_t tree_height, + void (*gen_leafx4)( + unsigned char * /* Where to write the leaves */, + const spx_ctx *, + uint32_t idx, void *info), + uint32_t tree_addrx4[4 * 8], + void *info) { + /* This is where we keep the intermediate nodes */ + PQCLEAN_VLA(unsigned char, stackx4, tree_height * 4 * SPX_N); + uint32_t left_adj = 0, prev_left_adj = 0; /* When we're doing the top 3 */ + /* levels, the left-most part of the tree isn't at the beginning */ + /* of current[]. These give the offset of the actual start */ + + uint32_t idx; + uint32_t max_idx = (1U << (tree_height - 2)) - 1; + for (idx = 0;; idx++) { + unsigned char current[4 * SPX_N]; /* Current logical node */ + gen_leafx4( current, ctx, 4 * idx + idx_offset, + info ); + + /* Now combine the freshly generated right node with previously */ + /* generated left ones */ + uint32_t internal_idx_offset = idx_offset; + uint32_t internal_idx = idx; + uint32_t internal_leaf = leaf_idx; + uint32_t h; /* The height we are in the Merkle tree */ + for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { + + /* Special processing if we're at the top of the tree */ + if (h >= tree_height - 2) { + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[3 * SPX_N], SPX_N ); + return; + } + /* The tree indexing logic is a bit off in this case */ + /* Adjust it so that the left-most node of the part of */ + /* the tree that we're processing has index 0 */ + prev_left_adj = left_adj; + left_adj = 4U - (1 << (tree_height - h - 1)); + } + + /* Check if we hit the top of the tree */ + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[3 * SPX_N], SPX_N ); + return; + } + + /* + * Check if one of the nodes we have is a part of the + * authentication path; if it is, write it out + */ + if ((((internal_idx << 2) ^ internal_leaf) & ~0x3U) == 0) { + memcpy( &auth_path[ h * SPX_N ], + ¤t[(((internal_leaf & 3) ^ 1) + prev_left_adj) * SPX_N], + SPX_N ); + } + + /* + * Check if we're at a left child; if so, stop going up the stack + * Exception: if we've reached the end of the tree, keep on going + * (so we combine the last 4 nodes into the one root node in two + * more iterations) + */ + if ((internal_idx & 1) == 0 && idx < max_idx) { + break; + } + + /* Ok, we're at a right node (or doing the top 3 levels) */ + /* Now combine the left and right logical nodes together */ + + /* Set the address of the node we're creating. */ + unsigned int j; + internal_idx_offset >>= 1; + for (j = 0; j < 4; j++) { + set_tree_height(tree_addrx4 + j * 8, h + 1); + set_tree_index(tree_addrx4 + j * 8, + (4 / 2) * (internal_idx & ~1U) + j - left_adj + internal_idx_offset ); + } + unsigned char *left = &stackx4[h * 4 * SPX_N]; + thashx4( ¤t[0 * SPX_N], + ¤t[1 * SPX_N], + ¤t[2 * SPX_N], + ¤t[3 * SPX_N], + &left [0 * SPX_N], + &left [2 * SPX_N], + ¤t[0 * SPX_N], + ¤t[2 * SPX_N], + 2, ctx, tree_addrx4); + } + + /* We've hit a left child; save the current for when we get the */ + /* corresponding right right */ + memcpy( &stackx4[h * 4 * SPX_N], current, 4 * SPX_N); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/utilsx4.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/utilsx4.h new file mode 100644 index 0000000000..facb874b18 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/utilsx4.h @@ -0,0 +1,30 @@ +#ifndef SPX_UTILSX4_H +#define SPX_UTILSX4_H + +#include + +#include "context.h" +#include "params.h" + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + * + * This implementation uses AVX to compute internal nodes 4 at a time (in + * parallel) + */ +#define treehashx4 SPX_NAMESPACE(treehashx4) +void treehashx4(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leafx4)( + unsigned char * /* Where to write the leaves */, + const spx_ctx * /* ctx */, + uint32_t addr_idx, void *info), + uint32_t tree_addrx4[4 * 8], void *info); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/wots.c b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/wots.c new file mode 100644 index 0000000000..4d5041ce05 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/wots.c @@ -0,0 +1,269 @@ +#include +#include + +#include "wots.h" + +#include "address.h" +#include "hash.h" +#include "hashx4.h" +#include "params.h" +#include "thash.h" +#include "thashx4.h" +#include "utils.h" +#include "utilsx4.h" +#include "wotsx4.h" + +// TODO clarify address expectations, and make them more uniform. +// TODO i.e. do we expect types to be set already? +// TODO and do we expect modifications or copies? + +/** + * Computes up the chains + */ +static void gen_chains( + unsigned char *out, + const unsigned char *in, + unsigned int start[SPX_WOTS_LEN], + const unsigned int steps[SPX_WOTS_LEN], + const spx_ctx *ctx, + uint32_t addr[8]) { + uint32_t i, j, k, idx, watching; + int done; + unsigned char empty[SPX_N]; + unsigned char *bufs[4]; + uint32_t addrs[8 * 4]; + + int l; + uint16_t counts[SPX_WOTS_W] = { 0 }; + uint16_t idxs[SPX_WOTS_LEN]; + uint16_t total, newTotal; + + /* set addrs = {addr, addr, addr, addr} */ + for (j = 0; j < 4; j++) { + memcpy(addrs + j * 8, addr, sizeof(uint32_t) * 8); + } + + /* Initialize out with the value at position 'start'. */ + memcpy(out, in, SPX_WOTS_LEN * SPX_N); + + /* Sort the chains in reverse order by steps using counting sort. */ + for (i = 0; i < SPX_WOTS_LEN; i++) { + counts[steps[i]]++; + } + total = 0; + for (l = SPX_WOTS_W - 1; l >= 0; l--) { + newTotal = counts[l] + total; + counts[l] = total; + total = newTotal; + } + for (i = 0; i < SPX_WOTS_LEN; i++) { + idxs[counts[steps[i]]] = (uint16_t)i; + counts[steps[i]]++; + } + + /* We got our work cut out for us: do it! */ + for (i = 0; i < SPX_WOTS_LEN; i += 4) { + for (j = 0; j < 4 && i + j < SPX_WOTS_LEN; j++) { + idx = idxs[i + j]; + set_chain_addr(addrs + j * 8, idx); + bufs[j] = out + SPX_N * idx; + } + + /* As the chains are sorted in reverse order, we know that the first + * chain is the longest and the last one is the shortest. We keep + * an eye on whether the last chain is done and then on the one before, + * et cetera. */ + watching = 3; + done = 0; + while (i + watching >= SPX_WOTS_LEN) { + bufs[watching] = &empty[0]; + watching--; + } + + for (k = 0;; k++) { + while (k == steps[idxs[i + watching]]) { + bufs[watching] = &empty[0]; + if (watching == 0) { + done = 1; + break; + } + watching--; + } + if (done) { + break; + } + for (j = 0; j < watching + 1; j++) { + set_hash_addr(addrs + j * 8, k + start[idxs[i + j]]); + } + + thashx4(bufs[0], bufs[1], bufs[2], bufs[3], + bufs[0], bufs[1], bufs[2], bufs[3], 1, ctx, addrs); + } + } +} + +/** + * base_w algorithm as described in draft. + * Interprets an array of bytes as integers in base w. + * This only works when log_w is a divisor of 8. + */ +static void base_w(unsigned int *output, const int out_len, + const unsigned char *input) { + int in = 0; + int out = 0; + unsigned char total = 0; + int bits = 0; + int consumed; + + for (consumed = 0; consumed < out_len; consumed++) { + if (bits == 0) { + total = input[in]; + in++; + bits += 8; + } + bits -= SPX_WOTS_LOGW; + output[out] = (total >> bits) & (SPX_WOTS_W - 1); + out++; + } +} + +/* Computes the WOTS+ checksum over a message (in base_w). */ +static void wots_checksum(unsigned int *csum_base_w, + const unsigned int *msg_base_w) { + unsigned int csum = 0; + unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; + unsigned int i; + + /* Compute checksum. */ + for (i = 0; i < SPX_WOTS_LEN1; i++) { + csum += SPX_WOTS_W - 1 - msg_base_w[i]; + } + + /* Convert checksum to base_w. */ + /* Make sure expected empty zero bits are the least significant bits. */ + csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); + ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); + base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); +} + +/* Takes a message and derives the matching chain lengths. */ +void chain_lengths(unsigned int *lengths, const unsigned char *msg) { + base_w(lengths, SPX_WOTS_LEN1, msg); + wots_checksum(lengths + SPX_WOTS_LEN1, lengths); +} + +/** + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. + * + * Writes the computed public key to 'pk'. + */ +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]) { + unsigned int steps[SPX_WOTS_LEN]; + unsigned int start[SPX_WOTS_LEN]; + uint32_t i; + + chain_lengths(start, msg); + + for (i = 0; i < SPX_WOTS_LEN; i++) { + steps[i] = SPX_WOTS_W - 1 - start[i]; + } + + gen_chains(pk, sig, start, steps, ctx, addr); +} + +/* + * This generates 4 sequential WOTS public keys + * It also generates the WOTS signature if leaf_info indicates + * that we're signing with one of these WOTS keys + */ +void wots_gen_leafx4(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info) { + struct leaf_info_x4 *info = v_info; + uint32_t *leaf_addr = info->leaf_addr; + uint32_t *pk_addr = info->pk_addr; + unsigned int i, j, k; + unsigned char pk_buffer[ 4 * SPX_WOTS_BYTES ]; + unsigned wots_offset = SPX_WOTS_BYTES; + unsigned char *buffer; + uint32_t wots_k_mask; + unsigned wots_sign_index; + + if (((leaf_idx ^ info->wots_sign_leaf) & ~3U) == 0) { + /* We're traversing the leaf that's signing; generate the WOTS */ + /* signature */ + wots_k_mask = 0; + wots_sign_index = info->wots_sign_leaf & 3; /* Which of of the 4 */ + /* 4 slots do the signatures come from */ + } else { + /* Nope, we're just generating pk's; turn off the signature logic */ + wots_k_mask = (uint32_t)~0; + wots_sign_index = 0; + } + + for (j = 0; j < 4; j++) { + set_keypair_addr( leaf_addr + j * 8, leaf_idx + j ); + set_keypair_addr( pk_addr + j * 8, leaf_idx + j ); + } + + for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { + uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k to */ + /* the step if we're generating a signature, ~0 if we're not */ + + /* Start with the secret seed */ + for (j = 0; j < 4; j++) { + set_chain_addr(leaf_addr + j * 8, i); + set_hash_addr(leaf_addr + j * 8, 0); + set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTSPRF); + } + prf_addrx4(buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + buffer + 2 * wots_offset, + buffer + 3 * wots_offset, + ctx, leaf_addr); + + for (j = 0; j < 4; j++) { + set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTS); + } + + /* Iterate down the WOTS chain */ + for (k = 0;; k++) { + /* Check if one of the values we have needs to be saved as a */ + /* part of the WOTS signature */ + if (k == wots_k) { + memcpy( info->wots_sig + i * SPX_N, + buffer + wots_sign_index * wots_offset, SPX_N ); + } + + /* Check if we hit the top of the chain */ + if (k == SPX_WOTS_W - 1) { + break; + } + + /* Iterate one step on all 4 chains */ + for (j = 0; j < 4; j++) { + set_hash_addr(leaf_addr + j * 8, k); + } + thashx4(buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + buffer + 2 * wots_offset, + buffer + 3 * wots_offset, + buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + buffer + 2 * wots_offset, + buffer + 3 * wots_offset, 1, ctx, leaf_addr); + } + } + + /* Do the final thash to generate the public keys */ + thashx4(dest + 0 * SPX_N, + dest + 1 * SPX_N, + dest + 2 * SPX_N, + dest + 3 * SPX_N, + pk_buffer + 0 * wots_offset, + pk_buffer + 1 * wots_offset, + pk_buffer + 2 * wots_offset, + pk_buffer + 3 * wots_offset, SPX_WOTS_LEN, ctx, pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/wots.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/wots.h new file mode 100644 index 0000000000..4e7692eeef --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/wots.h @@ -0,0 +1,25 @@ +#ifndef SPX_WOTS_H +#define SPX_WOTS_H + +#include + +#include "context.h" +#include "params.h" + +/** + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. + * + * Writes the computed public key to 'pk'. + */ +#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]); + +/* + * Compute the chain lengths needed for a given message hash + */ +#define chain_lengths SPX_NAMESPACE(chain_lengths) +void chain_lengths(unsigned int *lengths, const unsigned char *msg); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/wotsx4.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/wotsx4.h new file mode 100644 index 0000000000..cd634f1743 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/wotsx4.h @@ -0,0 +1,41 @@ +#ifndef WOTSX4_H_ +#define WOTSX4_H_ + +#include + +#include "params.h" + +/* + * This is here to provide an interface to the internal wots_gen_leafx4 + * routine. While this routine is not referenced in the package outside of + * wots.c, it is called from the stand-alone benchmark code to characterize + * the performance + */ +struct leaf_info_x4 { + unsigned char *wots_sig; + uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ + uint32_t *wots_steps; + uint32_t leaf_addr[4 * 8]; + uint32_t pk_addr[4 * 8]; +}; + +/* Macro to set the leaf_info to something 'benign', that is, it would */ +/* run with the same time as it does during the real signing process */ +/* Used only by the benchmark code */ +#define INITIALIZE_LEAF_INFO_X4(info, addr, step_buffer) { \ + (info).wots_sig = 0; \ + (info).wots_sign_leaf = ~0; \ + (info).wots_steps = step_buffer; \ + int i; \ + for (i=0; i<4; i++) { \ + memcpy( &(info).leaf_addr[8*i], addr, 32 ); \ + memcpy( &(info).pk_addr[8*i], addr, 32 ); \ + } \ + } + +#define wots_gen_leafx4 SPX_NAMESPACE(wots_gen_leafx4) +void wots_gen_leafx4(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info); + +#endif /* WOTSX4_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_clean/LICENSE b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_clean/LICENSE new file mode 100644 index 0000000000..670154e353 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_clean/LICENSE @@ -0,0 +1,116 @@ +CC0 1.0 Universal + +Statement of Purpose + +The laws of most jurisdictions throughout the world automatically confer +exclusive Copyright and Related Rights (defined below) upon the creator and +subsequent owner(s) (each and all, an "owner") of an original work of +authorship and/or a database (each, a "Work"). + +Certain owners wish to permanently relinquish those rights to a Work for the +purpose of contributing to a commons of creative, cultural and scientific +works ("Commons") that the public can reliably and without fear of later +claims of infringement build upon, modify, incorporate in other works, reuse +and redistribute as freely as possible in any form whatsoever and for any +purposes, including without limitation commercial purposes. These owners may +contribute to the Commons to promote the ideal of a free culture and the +further production of creative, cultural and scientific works, or to gain +reputation or greater distribution for their Work in part through the use and +efforts of others. + +For these and/or other purposes and motivations, and without any expectation +of additional consideration or compensation, the person associating CC0 with a +Work (the "Affirmer"), to the extent that he or she is an owner of Copyright +and Related Rights in the Work, voluntarily elects to apply CC0 to the Work +and publicly distribute the Work under its terms, with knowledge of his or her +Copyright and Related Rights in the Work and the meaning and intended legal +effect of CC0 on those rights. + +1. Copyright and Related Rights. A Work made available under CC0 may be +protected by copyright and related or neighboring rights ("Copyright and +Related Rights"). Copyright and Related Rights include, but are not limited +to, the following: + + i. the right to reproduce, adapt, distribute, perform, display, communicate, + and translate a Work; + + ii. moral rights retained by the original author(s) and/or performer(s); + + iii. publicity and privacy rights pertaining to a person's image or likeness + depicted in a Work; + + iv. rights protecting against unfair competition in regards to a Work, + subject to the limitations in paragraph 4(a), below; + + v. rights protecting the extraction, dissemination, use and reuse of data in + a Work; + + vi. database rights (such as those arising under Directive 96/9/EC of the + European Parliament and of the Council of 11 March 1996 on the legal + protection of databases, and under any national implementation thereof, + including any amended or successor version of such directive); and + + vii. other similar, equivalent or corresponding rights throughout the world + based on applicable law or treaty, and any national implementations thereof. + +2. Waiver. To the greatest extent permitted by, but not in contravention of, +applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and +unconditionally waives, abandons, and surrenders all of Affirmer's Copyright +and Related Rights and associated claims and causes of action, whether now +known or unknown (including existing as well as future claims and causes of +action), in the Work (i) in all territories worldwide, (ii) for the maximum +duration provided by applicable law or treaty (including future time +extensions), (iii) in any current or future medium and for any number of +copies, and (iv) for any purpose whatsoever, including without limitation +commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes +the Waiver for the benefit of each member of the public at large and to the +detriment of Affirmer's heirs and successors, fully intending that such Waiver +shall not be subject to revocation, rescission, cancellation, termination, or +any other legal or equitable action to disrupt the quiet enjoyment of the Work +by the public as contemplated by Affirmer's express Statement of Purpose. + +3. Public License Fallback. Should any part of the Waiver for any reason be +judged legally invalid or ineffective under applicable law, then the Waiver +shall be preserved to the maximum extent permitted taking into account +Affirmer's express Statement of Purpose. In addition, to the extent the Waiver +is so judged Affirmer hereby grants to each affected person a royalty-free, +non transferable, non sublicensable, non exclusive, irrevocable and +unconditional license to exercise Affirmer's Copyright and Related Rights in +the Work (i) in all territories worldwide, (ii) for the maximum duration +provided by applicable law or treaty (including future time extensions), (iii) +in any current or future medium and for any number of copies, and (iv) for any +purpose whatsoever, including without limitation commercial, advertising or +promotional purposes (the "License"). The License shall be deemed effective as +of the date CC0 was applied by Affirmer to the Work. Should any part of the +License for any reason be judged legally invalid or ineffective under +applicable law, such partial invalidity or ineffectiveness shall not +invalidate the remainder of the License, and in such case Affirmer hereby +affirms that he or she will not (i) exercise any of his or her remaining +Copyright and Related Rights in the Work or (ii) assert any associated claims +and causes of action with respect to the Work, in either case contrary to +Affirmer's express Statement of Purpose. + +4. Limitations and Disclaimers. + + a. No trademark or patent rights held by Affirmer are waived, abandoned, + surrendered, licensed or otherwise affected by this document. + + b. Affirmer offers the Work as-is and makes no representations or warranties + of any kind concerning the Work, express, implied, statutory or otherwise, + including without limitation warranties of title, merchantability, fitness + for a particular purpose, non infringement, or the absence of latent or + other defects, accuracy, or the present or absence of errors, whether or not + discoverable, all to the greatest extent permissible under applicable law. + + c. Affirmer disclaims responsibility for clearing rights of other persons + that may apply to the Work or any use thereof, including without limitation + any person's Copyright and Related Rights in the Work. Further, Affirmer + disclaims responsibility for obtaining any necessary consents, permissions + or other rights required for any use of the Work. + + d. Affirmer understands and acknowledges that Creative Commons is not a + party to this document and has no duty or obligation with respect to this + CC0 or use of the Work. + +For more information, please see + diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_clean/address.c b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_clean/address.c new file mode 100644 index 0000000000..d49d9f3b6b --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_clean/address.c @@ -0,0 +1,95 @@ +#include +#include + +#include "address.h" +#include "params.h" +#include "utils.h" + +/* + * Specify which level of Merkle tree (the "layer") we're working on + */ +void set_layer_addr(uint32_t addr[8], uint32_t layer) { + ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; +} + +/* + * Specify which Merkle tree within the level (the "tree address") we're working on + */ +void set_tree_addr(uint32_t addr[8], uint64_t tree) { + ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); +} + +/* + * Specify the reason we'll use this address structure for, that is, what + * hash will we compute with it. This is used so that unrelated types of + * hashes don't accidentally get the same address structure. The type will be + * one of the SPX_ADDR_TYPE constants + */ +void set_type(uint32_t addr[8], uint32_t type) { + ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; +} + +/* + * Copy the layer and tree fields of the address structure. This is used + * when we're doing multiple types of hashes within the same Merkle tree + */ +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); +} + +/* These functions are used for OTS addresses. */ + +/* + * Specify which Merkle leaf we're working on; that is, which OTS keypair + * we're talking about. + */ +void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { + /* We have > 256 OTS at the bottom of the Merkle tree; to specify */ + /* which one, we'd need to express it in two bytes */ + ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR2] = (unsigned char)(keypair >> 8); + ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; +} + +/* + * Copy the layer, tree and keypair fields of the address structure. This is + * used when we're doing multiple things within the same OTS keypair + */ +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); + ((unsigned char *)out)[SPX_OFFSET_KP_ADDR2] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR2]; + ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; +} + +/* + * Specify which Merkle chain within the OTS we're working with + * (the chain address) + */ +void set_chain_addr(uint32_t addr[8], uint32_t chain) { + ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; +} + +/* + * Specify where in the Merkle chain we are +* (the hash address) + */ +void set_hash_addr(uint32_t addr[8], uint32_t hash) { + ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; +} + +/* These functions are used for all hash tree addresses (including FORS). */ + +/* + * Specify the height of the node in the Merkle/FORS tree we are in + * (the tree height) + */ +void set_tree_height(uint32_t addr[8], uint32_t tree_height) { + ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; +} + +/* + * Specify the distance from the left edge of the node in the Merkle/FORS tree + * (the tree index) + */ +void set_tree_index(uint32_t addr[8], uint32_t tree_index) { + u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_clean/address.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_clean/address.h new file mode 100644 index 0000000000..24a84eb40c --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_clean/address.h @@ -0,0 +1,52 @@ +#ifndef SPX_ADDRESS_H +#define SPX_ADDRESS_H + +#include + +#include "params.h" + +/* The hash types that are passed to set_type */ +#define SPX_ADDR_TYPE_WOTS 0 +#define SPX_ADDR_TYPE_WOTSPK 1 +#define SPX_ADDR_TYPE_HASHTREE 2 +#define SPX_ADDR_TYPE_FORSTREE 3 +#define SPX_ADDR_TYPE_FORSPK 4 +#define SPX_ADDR_TYPE_WOTSPRF 5 +#define SPX_ADDR_TYPE_FORSPRF 6 + +#define set_layer_addr SPX_NAMESPACE(set_layer_addr) +void set_layer_addr(uint32_t addr[8], uint32_t layer); + +#define set_tree_addr SPX_NAMESPACE(set_tree_addr) +void set_tree_addr(uint32_t addr[8], uint64_t tree); + +#define set_type SPX_NAMESPACE(set_type) +void set_type(uint32_t addr[8], uint32_t type); + +/* Copies the layer and tree part of one address into the other */ +#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); + +/* These functions are used for WOTS and FORS addresses. */ + +#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) +void set_keypair_addr(uint32_t addr[8], uint32_t keypair); + +#define set_chain_addr SPX_NAMESPACE(set_chain_addr) +void set_chain_addr(uint32_t addr[8], uint32_t chain); + +#define set_hash_addr SPX_NAMESPACE(set_hash_addr) +void set_hash_addr(uint32_t addr[8], uint32_t hash); + +#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); + +/* These functions are used for all hash tree addresses (including FORS). */ + +#define set_tree_height SPX_NAMESPACE(set_tree_height) +void set_tree_height(uint32_t addr[8], uint32_t tree_height); + +#define set_tree_index SPX_NAMESPACE(set_tree_index) +void set_tree_index(uint32_t addr[8], uint32_t tree_index); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_clean/api.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_clean/api.h new file mode 100644 index 0000000000..623c9b61ad --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_clean/api.h @@ -0,0 +1,77 @@ +#ifndef PQCLEAN_SPHINCSSHAKE128SSIMPLE_CLEAN_API_H +#define PQCLEAN_SPHINCSSHAKE128SSIMPLE_CLEAN_API_H + +#include +#include + +#define PQCLEAN_SPHINCSSHAKE128SSIMPLE_CLEAN_CRYPTO_ALGNAME "SPHINCS+-shake-128s-simple" + +#define PQCLEAN_SPHINCSSHAKE128SSIMPLE_CLEAN_CRYPTO_SECRETKEYBYTES 64 +#define PQCLEAN_SPHINCSSHAKE128SSIMPLE_CLEAN_CRYPTO_PUBLICKEYBYTES 32 +#define PQCLEAN_SPHINCSSHAKE128SSIMPLE_CLEAN_CRYPTO_BYTES 7856 + +#define PQCLEAN_SPHINCSSHAKE128SSIMPLE_CLEAN_CRYPTO_SEEDBYTES 48 + +/* + * Returns the length of a secret key, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE128SSIMPLE_CLEAN_crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE128SSIMPLE_CLEAN_crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE128SSIMPLE_CLEAN_crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE128SSIMPLE_CLEAN_crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +int PQCLEAN_SPHINCSSHAKE128SSIMPLE_CLEAN_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +int PQCLEAN_SPHINCSSHAKE128SSIMPLE_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +int PQCLEAN_SPHINCSSHAKE128SSIMPLE_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +int PQCLEAN_SPHINCSSHAKE128SSIMPLE_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, + const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +int PQCLEAN_SPHINCSSHAKE128SSIMPLE_CLEAN_crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +int PQCLEAN_SPHINCSSHAKE128SSIMPLE_CLEAN_crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_clean/context.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_clean/context.h new file mode 100644 index 0000000000..9f8a40ab4e --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_clean/context.h @@ -0,0 +1,22 @@ +#ifndef SPX_CONTEXT_H +#define SPX_CONTEXT_H + +#include +#include + +#include "params.h" + +typedef struct { + uint8_t pub_seed[SPX_N]; + uint8_t sk_seed[SPX_N]; + + +} spx_ctx; + +#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) +void initialize_hash_function(spx_ctx *ctx); + +#define free_hash_function SPX_NAMESPACE(free_hash_function) +void free_hash_function(spx_ctx *ctx); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_clean/context_shake.c b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_clean/context_shake.c new file mode 100644 index 0000000000..9614a103d3 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_clean/context_shake.c @@ -0,0 +1,12 @@ +#include "context.h" + +/* For SHAKE256, there is no immediate reason to initialize at the start, + so this function is an empty operation. */ +void initialize_hash_function(spx_ctx *ctx) { + (void)ctx; /* Suppress an 'unused parameter' warning. */ +} + +// in case the hash function api is heap-based. +void free_hash_function(spx_ctx *ctx) { + (void)ctx; +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_clean/fors.c b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_clean/fors.c new file mode 100644 index 0000000000..96ca72e986 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_clean/fors.c @@ -0,0 +1,156 @@ +#include +#include +#include + +#include "fors.h" + +#include "address.h" +#include "hash.h" +#include "thash.h" +#include "utils.h" +#include "utilsx1.h" + +static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + prf_addr(sk, ctx, fors_leaf_addr); +} + +static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, + const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + thash(leaf, sk, 1, ctx, fors_leaf_addr); +} + +struct fors_gen_leaf_info { + uint32_t leaf_addrx[8]; +}; + +static void fors_gen_leafx1(unsigned char *leaf, + const spx_ctx *ctx, + uint32_t addr_idx, void *info) { + struct fors_gen_leaf_info *fors_info = info; + uint32_t *fors_leaf_addr = fors_info->leaf_addrx; + + /* Only set the parts that the caller doesn't set */ + set_tree_index(fors_leaf_addr, addr_idx); + set_type(fors_leaf_addr, SPX_ADDR_TYPE_FORSPRF); + fors_gen_sk(leaf, ctx, fors_leaf_addr); + + set_type(fors_leaf_addr, SPX_ADDR_TYPE_FORSTREE); + fors_sk_to_leaf(leaf, leaf, + ctx, fors_leaf_addr); +} + +/** + * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + * Assumes indices has space for SPX_FORS_TREES integers. + */ +static void message_to_indices(uint32_t *indices, const unsigned char *m) { + unsigned int i, j; + unsigned int offset = 0; + + for (i = 0; i < SPX_FORS_TREES; i++) { + indices[i] = 0; + for (j = 0; j < SPX_FORS_HEIGHT; j++) { + indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); + offset++; + } + } +} + +/** + * Signs a message m, deriving the secret key from sk_seed and the FTS address. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + uint32_t fors_tree_addr[8] = {0}; + struct fors_gen_leaf_info fors_info = {0}; + uint32_t *fors_leaf_addr = fors_info.leaf_addrx; + uint32_t fors_pk_addr[8] = {0}; + uint32_t idx_offset; + unsigned int i; + + copy_keypair_addr(fors_tree_addr, fors_addr); + copy_keypair_addr(fors_leaf_addr, fors_addr); + + copy_keypair_addr(fors_pk_addr, fors_addr); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); + + message_to_indices(indices, m); + + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); + + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); + + /* Include the secret key part that produces the selected leaf node. */ + fors_gen_sk(sig, ctx, fors_tree_addr); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + sig += SPX_N; + + /* Compute the authentication path for this leaf node. */ + treehashx1(roots + i * SPX_N, sig, ctx, + indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx1, + fors_tree_addr, &fors_info); + + sig += SPX_N * SPX_FORS_HEIGHT; + } + + /* Hash horizontally across all tree roots to derive the public key. */ + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); +} + +/** + * Derives the FORS public key from a signature. + * This can be used for verification by comparing to a known public key, or to + * subsequently verify a signature on the derived public key. The latter is the + * typical use-case when used as an FTS below an OTS in a hypertree. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + unsigned char leaf[SPX_N]; + uint32_t fors_tree_addr[8] = {0}; + uint32_t fors_pk_addr[8] = {0}; + uint32_t idx_offset; + unsigned int i; + + copy_keypair_addr(fors_tree_addr, fors_addr); + copy_keypair_addr(fors_pk_addr, fors_addr); + + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); + + message_to_indices(indices, m); + + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); + + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + + /* Derive the leaf from the included secret key part. */ + fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); + sig += SPX_N; + + /* Derive the corresponding root node of this tree. */ + compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, + sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); + sig += SPX_N * SPX_FORS_HEIGHT; + } + + /* Hash horizontally across all tree roots to derive the public key. */ + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_clean/fors.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_clean/fors.h new file mode 100644 index 0000000000..509140a178 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_clean/fors.h @@ -0,0 +1,32 @@ +#ifndef SPX_FORS_H +#define SPX_FORS_H + +#include + +#include "context.h" +#include "params.h" + +/** + * Signs a message m, deriving the secret key from sk_seed and the FTS address. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +#define fors_sign SPX_NAMESPACE(fors_sign) +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); + +/** + * Derives the FORS public key from a signature. + * This can be used for verification by comparing to a known public key, or to + * subsequently verify a signature on the derived public key. The latter is the + * typical use-case when used as an FTS below an OTS in a hypertree. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_clean/hash.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_clean/hash.h new file mode 100644 index 0000000000..f7c87d4c3c --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_clean/hash.h @@ -0,0 +1,28 @@ +#ifndef SPX_HASH_H +#define SPX_HASH_H + +#include +#include + +#include "context.h" +#include "params.h" + +#define prf_addr SPX_NAMESPACE(prf_addr) +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]); + +#define gen_message_random SPX_NAMESPACE(gen_message_random) +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); + +#define hash_message SPX_NAMESPACE(hash_message) +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); + + + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_clean/hash_shake.c b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_clean/hash_shake.c new file mode 100644 index 0000000000..ff5e7ec918 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_clean/hash_shake.c @@ -0,0 +1,83 @@ +#include +#include + +#include "hash.h" + +#include "address.h" +#include "fips202.h" +#include "params.h" +#include "utils.h" + +/* + * Computes PRF(pk_seed, sk_seed, addr) + */ +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]) { + unsigned char buf[2 * SPX_N + SPX_ADDR_BYTES]; + + memcpy(buf, ctx->pub_seed, SPX_N); + memcpy(buf + SPX_N, addr, SPX_ADDR_BYTES); + memcpy(buf + SPX_N + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); + + shake256(out, SPX_N, buf, 2 * SPX_N + SPX_ADDR_BYTES); +} + +/** + * Computes the message-dependent randomness R, using a secret seed and an + * optional randomization value as well as the message. + */ +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { + (void)ctx; + shake256incctx s_inc; + + shake256_inc_init(&s_inc); + shake256_inc_absorb(&s_inc, sk_prf, SPX_N); + shake256_inc_absorb(&s_inc, optrand, SPX_N); + shake256_inc_absorb(&s_inc, m, mlen); + shake256_inc_finalize(&s_inc); + shake256_inc_squeeze(R, SPX_N, &s_inc); + shake256_inc_ctx_release(&s_inc); +} + +/** + * Computes the message hash using R, the public key, and the message. + * Outputs the message digest and the index of the leaf. The index is split in + * the tree index and the leaf index, for convenient copying to an address. + */ +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { + (void)ctx; +#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) +#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) +#define SPX_LEAF_BITS SPX_TREE_HEIGHT +#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) +#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) + + unsigned char buf[SPX_DGST_BYTES]; + unsigned char *bufp = buf; + shake256incctx s_inc; + + shake256_inc_init(&s_inc); + shake256_inc_absorb(&s_inc, R, SPX_N); + shake256_inc_absorb(&s_inc, pk, SPX_PK_BYTES); + shake256_inc_absorb(&s_inc, m, mlen); + shake256_inc_finalize(&s_inc); + shake256_inc_squeeze(buf, SPX_DGST_BYTES, &s_inc); + shake256_inc_ctx_release(&s_inc); + + memcpy(digest, bufp, SPX_FORS_MSG_BYTES); + bufp += SPX_FORS_MSG_BYTES; + + + *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); + *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); + bufp += SPX_TREE_BYTES; + + *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); + *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_clean/merkle.c b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_clean/merkle.c new file mode 100644 index 0000000000..0c1479fd93 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_clean/merkle.c @@ -0,0 +1,59 @@ +#include +#include + +#include "address.h" +#include "merkle.h" +#include "params.h" +#include "utils.h" +#include "utilsx1.h" +#include "wots.h" +#include "wotsx1.h" + +/* + * This generates a Merkle signature (WOTS signature followed by the Merkle + * authentication path). This is in this file because most of the complexity + * is involved with the WOTS signature; the Merkle authentication path logic + * is mostly hidden in treehashx4 + */ +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf) { + unsigned char *auth_path = sig + SPX_WOTS_BYTES; + struct leaf_info_x1 info = { 0 }; + unsigned steps[ SPX_WOTS_LEN ]; + + info.wots_sig = sig; + chain_lengths(steps, root); + info.wots_steps = steps; + + set_type(&tree_addr[0], SPX_ADDR_TYPE_HASHTREE); + set_type(&info.pk_addr[0], SPX_ADDR_TYPE_WOTSPK); + copy_subtree_addr(&info.leaf_addr[0], wots_addr); + copy_subtree_addr(&info.pk_addr[0], wots_addr); + + info.wots_sign_leaf = idx_leaf; + + treehashx1(root, auth_path, ctx, + idx_leaf, 0, + SPX_TREE_HEIGHT, + wots_gen_leafx1, + tree_addr, &info); +} + +/* Compute root node of the top-most subtree. */ +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { + /* We do not need the auth path in key generation, but it simplifies the + code to have just one treehash routine that computes both root and path + in one function. */ + unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; + uint32_t top_tree_addr[8] = {0}; + uint32_t wots_addr[8] = {0}; + + set_layer_addr(top_tree_addr, SPX_D - 1); + set_layer_addr(wots_addr, SPX_D - 1); + + merkle_sign(auth_path, root, ctx, + wots_addr, top_tree_addr, + (uint32_t)~0 /* ~0 means "don't bother generating an auth path */ ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_clean/merkle.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_clean/merkle.h new file mode 100644 index 0000000000..769cf2e970 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_clean/merkle.h @@ -0,0 +1,21 @@ +#ifndef MERKLE_H_ +#define MERKLE_H_ + +#include + +#include "context.h" +#include "params.h" + +/* Generate a Merkle signature (WOTS signature followed by the Merkle */ +/* authentication path) */ +#define merkle_sign SPX_NAMESPACE(merkle_sign) +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf); + +/* Compute the root node of the top-most subtree. */ +#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); + +#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_clean/nistapi.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_clean/nistapi.h new file mode 100644 index 0000000000..3cb71afad4 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_clean/nistapi.h @@ -0,0 +1,87 @@ +#ifndef SPX_API_H +#define SPX_API_H + +#include +#include + +#include "params.h" + +#define CRYPTO_ALGNAME "SPHINCS+" + +#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES +#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES +#define CRYPTO_BYTES SPX_BYTES +#define CRYPTO_SEEDBYTES (3*SPX_N) + +/* + * Returns the length of a secret key, in bytes + */ +#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) +size_t crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) +size_t crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) +size_t crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) +size_t crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +#define crypto_sign SPX_NAMESPACE(crypto_sign) +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_clean/params.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_clean/params.h new file mode 100644 index 0000000000..db5131a941 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_clean/params.h @@ -0,0 +1,56 @@ +#ifndef SPX_PARAMS_H +#define SPX_PARAMS_H + +#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSSHAKE128SSIMPLE_CLEAN_##s + +/* Hash output length in bytes. */ +#define SPX_N 16 +/* Height of the hypertree. */ +#define SPX_FULL_HEIGHT 63 +/* Number of subtree layer. */ +#define SPX_D 7 +/* FORS tree dimensions. */ +#define SPX_FORS_HEIGHT 12 +#define SPX_FORS_TREES 14 +/* Winternitz parameter, */ +#define SPX_WOTS_W 16 + +/* The hash function is defined by linking a different hash.c file, as opposed + to setting a #define constant. */ + +/* For clarity */ +#define SPX_ADDR_BYTES 32 + +/* WOTS parameters. */ +#define SPX_WOTS_LOGW 4 + +#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) + +/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ +#define SPX_WOTS_LEN2 3 + +#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) +#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) +#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES + +/* Subtree size. */ +#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) + +//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT +// #error SPX_D should always divide SPX_FULL_HEIGHT +//#endif + +/* FORS parameters. */ +#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) +#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) +#define SPX_FORS_PK_BYTES SPX_N + +/* Resulting SPX sizes. */ +#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ + SPX_FULL_HEIGHT * SPX_N) +#define SPX_PK_BYTES (2 * SPX_N) +#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) + +#include "shake_offsets.h" + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_clean/shake_offsets.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_clean/shake_offsets.h new file mode 100644 index 0000000000..6b28d95d91 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_clean/shake_offsets.h @@ -0,0 +1,21 @@ +#ifndef SHAKE_OFFSETS_H_ +#define SHAKE_OFFSETS_H_ + +/* + * Offsets of various fields in the address structure when we use SHAKE as + * the Sphincs+ hash function + */ + +#define SPX_OFFSET_LAYER 3 /* The byte used to specify the Merkle tree layer */ +#define SPX_OFFSET_TREE 8 /* The start of the 8 byte field used to specify the tree */ +#define SPX_OFFSET_TYPE 19 /* The byte used to specify the hash type (reason) */ +#define SPX_OFFSET_KP_ADDR2 22 /* The high byte used to specify the key pair (which one-time signature) */ +#define SPX_OFFSET_KP_ADDR1 23 /* The low byte used to specify the key pair */ +#define SPX_OFFSET_CHAIN_ADDR 27 /* The byte used to specify the chain address (which Winternitz chain) */ +#define SPX_OFFSET_HASH_ADDR 31 /* The byte used to specify the hash address (where in the Winternitz chain) */ +#define SPX_OFFSET_TREE_HGT 27 /* The byte used to specify the height of this node in the FORS or Merkle tree */ +#define SPX_OFFSET_TREE_INDEX 28 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ + +#define SPX_SHAKE 1 + +#endif /* SHAKE_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_clean/sign.c b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_clean/sign.c new file mode 100644 index 0000000000..9d0c7d1b22 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_clean/sign.c @@ -0,0 +1,286 @@ +#include +#include +#include + +#include "address.h" +#include "context.h" +#include "fors.h" +#include "hash.h" +#include "merkle.h" +#include "nistapi.h" +#include "params.h" +#include "randombytes.h" +#include "thash.h" +#include "utils.h" +#include "wots.h" + +/* + * Returns the length of a secret key, in bytes + */ +size_t crypto_sign_secretkeybytes(void) { + return CRYPTO_SECRETKEYBYTES; +} + +/* + * Returns the length of a public key, in bytes + */ +size_t crypto_sign_publickeybytes(void) { + return CRYPTO_PUBLICKEYBYTES; +} + +/* + * Returns the length of a signature, in bytes + */ +size_t crypto_sign_bytes(void) { + return CRYPTO_BYTES; +} + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +size_t crypto_sign_seedbytes(void) { + return CRYPTO_SEEDBYTES; +} + +/* + * Generates an SPX key pair given a seed of length + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [PUB_SEED || root] + */ +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed) { + spx_ctx ctx; + + /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ + memcpy(sk, seed, CRYPTO_SEEDBYTES); + + memcpy(pk, sk + 2 * SPX_N, SPX_N); + + memcpy(ctx.pub_seed, pk, SPX_N); + memcpy(ctx.sk_seed, sk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + /* Compute root node of the top-most subtree. */ + merkle_gen_root(sk + 3 * SPX_N, &ctx); + + // cleanup + free_hash_function(&ctx); + + memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); + + return 0; +} + +/* + * Generates an SPX key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [PUB_SEED || root] + */ +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { + uint8_t seed[CRYPTO_SEEDBYTES]; + randombytes(seed, CRYPTO_SEEDBYTES); + crypto_sign_seed_keypair(pk, sk, seed); + + return 0; +} + +/** + * Returns an array containing a detached signature. + */ +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk) { + spx_ctx ctx; + + const uint8_t *sk_prf = sk + SPX_N; + const uint8_t *pk = sk + 2 * SPX_N; + + uint8_t optrand[SPX_N]; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t root[SPX_N]; + uint32_t i; + uint64_t tree; + uint32_t idx_leaf; + uint32_t wots_addr[8] = {0}; + uint32_t tree_addr[8] = {0}; + + memcpy(ctx.sk_seed, sk, SPX_N); + memcpy(ctx.pub_seed, pk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + + /* Optionally, signing can be made non-deterministic using optrand. + This can help counter side-channel attacks that would benefit from + getting a large number of traces when the signer uses the same nodes. */ + randombytes(optrand, SPX_N); + /* Compute the digest randomization value. */ + gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); + + /* Derive the message digest and leaf index from R, PK and M. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; + + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); + + /* Sign the message hash using FORS. */ + fors_sign(sig, root, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); + sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; + + /* Update the indices for the next layer. */ + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; + } + + free_hash_function(&ctx); + + *siglen = SPX_BYTES; + + return 0; +} + +/** + * Verifies a detached signature and message under a given public key. + */ +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk) { + spx_ctx ctx; + const uint8_t *pub_root = pk + SPX_N; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t wots_pk[SPX_WOTS_BYTES]; + uint8_t root[SPX_N]; + uint8_t leaf[SPX_N]; + unsigned int i; + uint64_t tree; + uint32_t idx_leaf; + uint32_t wots_addr[8] = {0}; + uint32_t tree_addr[8] = {0}; + uint32_t wots_pk_addr[8] = {0}; + + if (siglen != SPX_BYTES) { + return -1; + } + + memcpy(ctx.pub_seed, pk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); + + /* Derive the message digest and leaf index from R || PK || M. */ + /* The additional SPX_N is a result of the hash domain separator. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; + + /* Layer correctly defaults to 0, so no need to set_layer_addr */ + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); + + fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + /* For each subtree.. */ + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + copy_keypair_addr(wots_pk_addr, wots_addr); + + /* The WOTS public key is only correct if the signature was correct. */ + /* Initially, root is the FORS pk, but on subsequent iterations it is + the root of the subtree below the currently processed subtree. */ + wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); + sig += SPX_WOTS_BYTES; + + /* Compute the leaf node using the WOTS public key. */ + thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); + + /* Compute the root node of this subtree. */ + compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, + &ctx, tree_addr); + sig += SPX_TREE_HEIGHT * SPX_N; + + /* Update the indices for the next layer. */ + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; + } + + // cleanup + free_hash_function(&ctx); + + /* Check if the root node equals the root node in the public key. */ + if (memcmp(root, pub_root, SPX_N) != 0) { + return -1; + } + + return 0; +} + + +/** + * Returns an array containing the signature followed by the message. + */ +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk) { + size_t siglen; + + crypto_sign_signature(sm, &siglen, m, mlen, sk); + + memmove(sm + SPX_BYTES, m, mlen); + *smlen = siglen + mlen; + + return 0; +} + +/** + * Verifies a given signature-message pair under a given public key. + */ +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk) { + /* The API caller does not necessarily know what size a signature should be + but SPHINCS+ signatures are always exactly SPX_BYTES. */ + if (smlen < SPX_BYTES) { + memset(m, 0, smlen); + *mlen = 0; + return -1; + } + + *mlen = smlen - SPX_BYTES; + + if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { + memset(m, 0, smlen); + *mlen = 0; + return -1; + } + + /* If verification was successful, move the message to the right place. */ + memmove(m, sm + SPX_BYTES, *mlen); + + return 0; +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_clean/thash.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_clean/thash.h new file mode 100644 index 0000000000..8687ccfb4d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_clean/thash.h @@ -0,0 +1,13 @@ +#ifndef SPX_THASH_H +#define SPX_THASH_H + +#include "context.h" +#include "params.h" + +#include + +#define thash SPX_NAMESPACE(thash) +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_clean/thash_shake_simple.c b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_clean/thash_shake_simple.c new file mode 100644 index 0000000000..98470395e9 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_clean/thash_shake_simple.c @@ -0,0 +1,24 @@ +#include +#include + +#include "thash.h" + +#include "address.h" +#include "params.h" +#include "utils.h" + +#include "fips202.h" + +/** + * Takes an array of inblocks concatenated arrays of SPX_N bytes. + */ +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]) { + PQCLEAN_VLA(uint8_t, buf, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); + + memcpy(buf, ctx->pub_seed, SPX_N); + memcpy(buf + SPX_N, addr, SPX_ADDR_BYTES); + memcpy(buf + SPX_N + SPX_ADDR_BYTES, in, inblocks * SPX_N); + + shake256(out, SPX_N, buf, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_clean/utils.c b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_clean/utils.c new file mode 100644 index 0000000000..177b541fb9 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_clean/utils.c @@ -0,0 +1,148 @@ +#include + +#include "utils.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "thash.h" + +/** + * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. + */ +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in) { + int i; + + /* Iterate over out in decreasing order, for big-endianness. */ + for (i = (signed int)outlen - 1; i >= 0; i--) { + out[i] = in & 0xff; + in = in >> 8; + } +} + +void u32_to_bytes(unsigned char *out, uint32_t in) { + out[0] = (unsigned char)(in >> 24); + out[1] = (unsigned char)(in >> 16); + out[2] = (unsigned char)(in >> 8); + out[3] = (unsigned char)in; +} + +/** + * Converts the inlen bytes in 'in' from big-endian byte order to an integer. + */ +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { + unsigned long long retval = 0; + unsigned int i; + + for (i = 0; i < inlen; i++) { + retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); + } + return retval; +} + +/** + * Computes a root node given a leaf and an auth path. + * Expects address to be complete other than the tree_height and tree_index. + */ +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]) { + uint32_t i; + unsigned char buffer[2 * SPX_N]; + + /* If leaf_idx is odd (last bit = 1), current path element is a right child + and auth_path has to go left. Otherwise it is the other way around. */ + if (leaf_idx & 1) { + memcpy(buffer + SPX_N, leaf, SPX_N); + memcpy(buffer, auth_path, SPX_N); + } else { + memcpy(buffer, leaf, SPX_N); + memcpy(buffer + SPX_N, auth_path, SPX_N); + } + auth_path += SPX_N; + + for (i = 0; i < tree_height - 1; i++) { + leaf_idx >>= 1; + idx_offset >>= 1; + /* Set the address of the node we're creating. */ + set_tree_height(addr, i + 1); + set_tree_index(addr, leaf_idx + idx_offset); + + /* Pick the right or left neighbor, depending on parity of the node. */ + if (leaf_idx & 1) { + thash(buffer + SPX_N, buffer, 2, ctx, addr); + memcpy(buffer, auth_path, SPX_N); + } else { + thash(buffer, buffer, 2, ctx, addr); + memcpy(buffer + SPX_N, auth_path, SPX_N); + } + auth_path += SPX_N; + } + + /* The last iteration is exceptional; we do not copy an auth_path node. */ + leaf_idx >>= 1; + idx_offset >>= 1; + set_tree_height(addr, tree_height); + set_tree_index(addr, leaf_idx + idx_offset); + thash(root, buffer, 2, ctx, addr); +} + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx * /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]) { + PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); + PQCLEAN_VLA(unsigned int, heights, tree_height + 1); + unsigned int offset = 0; + uint32_t idx; + uint32_t tree_idx; + + for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { + /* Add the next leaf node to the stack. */ + gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); + offset++; + heights[offset - 1] = 0; + + /* If this is a node we need for the auth path.. */ + if ((leaf_idx ^ 0x1) == idx) { + memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); + } + + /* While the top-most nodes are of equal height.. */ + while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { + /* Compute index of the new node, in the next layer. */ + tree_idx = (idx >> (heights[offset - 1] + 1)); + + /* Set the address of the node we're creating. */ + set_tree_height(tree_addr, heights[offset - 1] + 1); + set_tree_index(tree_addr, + tree_idx + (idx_offset >> (heights[offset - 1] + 1))); + /* Hash the top-most nodes from the stack together. */ + thash(stack + (offset - 2)*SPX_N, + stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); + offset--; + /* Note that the top-most node is now one layer higher. */ + heights[offset - 1]++; + + /* If this is a node we need for the auth path.. */ + if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { + memcpy(auth_path + heights[offset - 1]*SPX_N, + stack + (offset - 1)*SPX_N, SPX_N); + } + } + } + memcpy(root, stack, SPX_N); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_clean/utils.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_clean/utils.h new file mode 100644 index 0000000000..64f5d5a53a --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_clean/utils.h @@ -0,0 +1,58 @@ +#ifndef SPX_UTILS_H +#define SPX_UTILS_H + +#include + +#include "compat.h" +#include "context.h" +#include "params.h" + + +/* To support MSVC use alloca() instead of VLAs. See #20. */ + + +/** + * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. + */ +#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in); +#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) +void u32_to_bytes(unsigned char *out, uint32_t in); + +/** + * Converts the inlen bytes in 'in' from big-endian byte order to an integer. + */ +#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); + +/** + * Computes a root node given a leaf and an auth path. + * Expects address to be complete other than the tree_height and tree_index. + */ +#define compute_root SPX_NAMESPACE(compute_root) +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]); + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +#define treehash SPX_NAMESPACE(treehash) +void treehash(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx *ctx /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]); + + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_clean/utilsx1.c b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_clean/utilsx1.c new file mode 100644 index 0000000000..fccb69b35d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_clean/utilsx1.c @@ -0,0 +1,100 @@ +#include + +#include "utilsx1.h" + +#include "address.h" +#include "params.h" +#include "thash.h" +#include "utils.h" + +/* + * Generate the entire Merkle tree, computing the authentication path for + * leaf_idx, and the resulting root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) + * + * This expects tree_addr to be initialized to the addr structures for the + * Merkle tree nodes + * + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + * + * This works by using the standard Merkle tree building algorithm, + */ +void treehashx1(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, + uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* Where to write the leaves */, + const spx_ctx * /* ctx */, + uint32_t idx, void *info), + uint32_t tree_addr[8], + void *info) { + /* This is where we keep the intermediate nodes */ + PQCLEAN_VLA(uint8_t, stack, tree_height * SPX_N); + + uint32_t idx; + uint32_t max_idx = (uint32_t)((1 << tree_height) - 1); + for (idx = 0;; idx++) { + unsigned char current[2 * SPX_N]; /* Current logical node is at */ + /* index[SPX_N]. We do this to minimize the number of copies */ + /* needed during a thash */ + gen_leaf( ¤t[SPX_N], ctx, idx + idx_offset, + info ); + + /* Now combine the freshly generated right node with previously */ + /* generated left ones */ + uint32_t internal_idx_offset = idx_offset; + uint32_t internal_idx = idx; + uint32_t internal_leaf = leaf_idx; + uint32_t h; /* The height we are in the Merkle tree */ + for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { + + /* Check if we hit the top of the tree */ + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[SPX_N], SPX_N ); + return; + } + + /* + * Check if the node we have is a part of the + * authentication path; if it is, write it out + */ + if ((internal_idx ^ internal_leaf) == 0x01) { + memcpy( &auth_path[ h * SPX_N ], + ¤t[SPX_N], + SPX_N ); + } + + /* + * Check if we're at a left child; if so, stop going up the stack + * Exception: if we've reached the end of the tree, keep on going + * (so we combine the last 4 nodes into the one root node in two + * more iterations) + */ + if ((internal_idx & 1) == 0 && idx < max_idx) { + break; + } + + /* Ok, we're at a right node */ + /* Now combine the left and right logical nodes together */ + + /* Set the address of the node we're creating. */ + internal_idx_offset >>= 1; + set_tree_height(tree_addr, h + 1); + set_tree_index(tree_addr, internal_idx / 2 + internal_idx_offset ); + + unsigned char *left = &stack[h * SPX_N]; + memcpy( ¤t[0], left, SPX_N ); + thash( ¤t[1 * SPX_N], + ¤t[0 * SPX_N], + 2, ctx, tree_addr); + } + + /* We've hit a left child; save the current for when we get the */ + /* corresponding right right */ + memcpy( &stack[h * SPX_N], ¤t[SPX_N], SPX_N); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_clean/utilsx1.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_clean/utilsx1.h new file mode 100644 index 0000000000..e911d17d53 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_clean/utilsx1.h @@ -0,0 +1,27 @@ +#ifndef SPX_UTILSX4_H +#define SPX_UTILSX4_H + +#include + +#include "context.h" +#include "params.h" + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +#define treehashx1 SPX_NAMESPACE(treehashx1) +void treehashx1(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* Where to write the leaf */, + const spx_ctx * /* ctx */, + uint32_t addr_idx, void *info), + uint32_t tree_addrx4[8], void *info); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_clean/wots.c b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_clean/wots.c new file mode 100644 index 0000000000..249717aaa8 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_clean/wots.c @@ -0,0 +1,108 @@ +#include +#include + +#include "wots.h" +#include "wotsx1.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "thash.h" +#include "utils.h" +#include "utilsx1.h" + +// TODO clarify address expectations, and make them more uniform. +// TODO i.e. do we expect types to be set already? +// TODO and do we expect modifications or copies? + +/** + * Computes the chaining function. + * out and in have to be n-byte arrays. + * + * Interprets in as start-th value of the chain. + * addr has to contain the address of the chain. + */ +static void gen_chain(unsigned char *out, const unsigned char *in, + unsigned int start, unsigned int steps, + const spx_ctx *ctx, uint32_t addr[8]) { + uint32_t i; + + /* Initialize out with the value at position 'start'. */ + memcpy(out, in, SPX_N); + + /* Iterate 'steps' calls to the hash function. */ + for (i = start; i < (start + steps) && i < SPX_WOTS_W; i++) { + set_hash_addr(addr, i); + thash(out, out, 1, ctx, addr); + } +} + +/** + * base_w algorithm as described in draft. + * Interprets an array of bytes as integers in base w. + * This only works when log_w is a divisor of 8. + */ +static void base_w(unsigned int *output, const int out_len, + const unsigned char *input) { + int in = 0; + int out = 0; + unsigned char total = 0; + int bits = 0; + int consumed; + + for (consumed = 0; consumed < out_len; consumed++) { + if (bits == 0) { + total = input[in]; + in++; + bits += 8; + } + bits -= SPX_WOTS_LOGW; + output[out] = (total >> bits) & (SPX_WOTS_W - 1); + out++; + } +} + +/* Computes the WOTS+ checksum over a message (in base_w). */ +static void wots_checksum(unsigned int *csum_base_w, + const unsigned int *msg_base_w) { + unsigned int csum = 0; + unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; + unsigned int i; + + /* Compute checksum. */ + for (i = 0; i < SPX_WOTS_LEN1; i++) { + csum += SPX_WOTS_W - 1 - msg_base_w[i]; + } + + /* Convert checksum to base_w. */ + /* Make sure expected empty zero bits are the least significant bits. */ + csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); + ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); + base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); +} + +/* Takes a message and derives the matching chain lengths. */ +void chain_lengths(unsigned int *lengths, const unsigned char *msg) { + base_w(lengths, SPX_WOTS_LEN1, msg); + wots_checksum(lengths + SPX_WOTS_LEN1, lengths); +} + +/** + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. + * + * Writes the computed public key to 'pk'. + */ +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]) { + unsigned int lengths[SPX_WOTS_LEN]; + uint32_t i; + + chain_lengths(lengths, msg); + + for (i = 0; i < SPX_WOTS_LEN; i++) { + set_chain_addr(addr, i); + gen_chain(pk + i * SPX_N, sig + i * SPX_N, + lengths[i], SPX_WOTS_W - 1 - lengths[i], ctx, addr); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_clean/wots.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_clean/wots.h new file mode 100644 index 0000000000..4e7692eeef --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_clean/wots.h @@ -0,0 +1,25 @@ +#ifndef SPX_WOTS_H +#define SPX_WOTS_H + +#include + +#include "context.h" +#include "params.h" + +/** + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. + * + * Writes the computed public key to 'pk'. + */ +#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]); + +/* + * Compute the chain lengths needed for a given message hash + */ +#define chain_lengths SPX_NAMESPACE(chain_lengths) +void chain_lengths(unsigned int *lengths, const unsigned char *msg); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_clean/wotsx1.c b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_clean/wotsx1.c new file mode 100644 index 0000000000..3adec78dfb --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_clean/wotsx1.c @@ -0,0 +1,76 @@ +#include +#include + +#include "wots.h" +#include "wotsx1.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "thash.h" +#include "utils.h" + +/* + * This generates a WOTS public key + * It also generates the WOTS signature if leaf_info indicates + * that we're signing with this WOTS key + */ +void wots_gen_leafx1(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info) { + struct leaf_info_x1 *info = v_info; + uint32_t *leaf_addr = info->leaf_addr; + uint32_t *pk_addr = info->pk_addr; + unsigned int i, k; + unsigned char pk_buffer[ SPX_WOTS_BYTES ]; + unsigned char *buffer; + uint32_t wots_k_mask; + + if (leaf_idx == info->wots_sign_leaf) { + /* We're traversing the leaf that's signing; generate the WOTS */ + /* signature */ + wots_k_mask = 0; + } else { + /* Nope, we're just generating pk's; turn off the signature logic */ + wots_k_mask = (uint32_t)~0; + } + + set_keypair_addr( leaf_addr, leaf_idx ); + set_keypair_addr( pk_addr, leaf_idx ); + + for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { + uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k to */ + /* the step if we're generating a signature, ~0 if we're not */ + + /* Start with the secret seed */ + set_chain_addr(leaf_addr, i); + set_hash_addr(leaf_addr, 0); + set_type(leaf_addr, SPX_ADDR_TYPE_WOTSPRF); + + prf_addr(buffer, ctx, leaf_addr); + + set_type(leaf_addr, SPX_ADDR_TYPE_WOTS); + + /* Iterate down the WOTS chain */ + for (k = 0;; k++) { + /* Check if this is the value that needs to be saved as a */ + /* part of the WOTS signature */ + if (k == wots_k) { + memcpy( info->wots_sig + i * SPX_N, buffer, SPX_N ); + } + + /* Check if we hit the top of the chain */ + if (k == SPX_WOTS_W - 1) { + break; + } + + /* Iterate one step on the chain */ + set_hash_addr(leaf_addr, k); + + thash(buffer, buffer, 1, ctx, leaf_addr); + } + } + + /* Do the final thash to generate the public keys */ + thash(dest, pk_buffer, SPX_WOTS_LEN, ctx, pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_clean/wotsx1.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_clean/wotsx1.h new file mode 100644 index 0000000000..e617929f96 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_clean/wotsx1.h @@ -0,0 +1,39 @@ +#ifndef WOTSX1_H_ +#define WOTSX1_H_ + +#include + +#include "context.h" +#include "params.h" + +/* + * This is here to provide an interface to the internal wots_gen_leafx1 + * routine. While this routine is not referenced in the package outside of + * wots.c, it is called from the stand-alone benchmark code to characterize + * the performance + */ +struct leaf_info_x1 { + unsigned char *wots_sig; + uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ + uint32_t *wots_steps; + uint32_t leaf_addr[8]; + uint32_t pk_addr[8]; +}; + +/* Macro to set the leaf_info to something 'benign', that is, it would */ +/* run with the same time as it does during the real signing process */ +/* Used only by the benchmark code */ +#define INITIALIZE_LEAF_INFO_X1(info, addr, step_buffer) { \ + (info).wots_sig = 0; \ + (info).wots_sign_leaf = ~0; \ + (info).wots_steps = step_buffer; \ + memcpy( &(info).leaf_addr[0], (addr), 32 ); \ + memcpy( &(info).pk_addr[0], (addr), 32 ); \ + } + +#define wots_gen_leafx1 SPX_NAMESPACE(wots_gen_leafx1) +void wots_gen_leafx1(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info); + +#endif /* WOTSX1_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/LICENSE b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/LICENSE new file mode 100644 index 0000000000..670154e353 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/LICENSE @@ -0,0 +1,116 @@ +CC0 1.0 Universal + +Statement of Purpose + +The laws of most jurisdictions throughout the world automatically confer +exclusive Copyright and Related Rights (defined below) upon the creator and +subsequent owner(s) (each and all, an "owner") of an original work of +authorship and/or a database (each, a "Work"). + +Certain owners wish to permanently relinquish those rights to a Work for the +purpose of contributing to a commons of creative, cultural and scientific +works ("Commons") that the public can reliably and without fear of later +claims of infringement build upon, modify, incorporate in other works, reuse +and redistribute as freely as possible in any form whatsoever and for any +purposes, including without limitation commercial purposes. These owners may +contribute to the Commons to promote the ideal of a free culture and the +further production of creative, cultural and scientific works, or to gain +reputation or greater distribution for their Work in part through the use and +efforts of others. + +For these and/or other purposes and motivations, and without any expectation +of additional consideration or compensation, the person associating CC0 with a +Work (the "Affirmer"), to the extent that he or she is an owner of Copyright +and Related Rights in the Work, voluntarily elects to apply CC0 to the Work +and publicly distribute the Work under its terms, with knowledge of his or her +Copyright and Related Rights in the Work and the meaning and intended legal +effect of CC0 on those rights. + +1. Copyright and Related Rights. A Work made available under CC0 may be +protected by copyright and related or neighboring rights ("Copyright and +Related Rights"). Copyright and Related Rights include, but are not limited +to, the following: + + i. the right to reproduce, adapt, distribute, perform, display, communicate, + and translate a Work; + + ii. moral rights retained by the original author(s) and/or performer(s); + + iii. publicity and privacy rights pertaining to a person's image or likeness + depicted in a Work; + + iv. rights protecting against unfair competition in regards to a Work, + subject to the limitations in paragraph 4(a), below; + + v. rights protecting the extraction, dissemination, use and reuse of data in + a Work; + + vi. database rights (such as those arising under Directive 96/9/EC of the + European Parliament and of the Council of 11 March 1996 on the legal + protection of databases, and under any national implementation thereof, + including any amended or successor version of such directive); and + + vii. other similar, equivalent or corresponding rights throughout the world + based on applicable law or treaty, and any national implementations thereof. + +2. Waiver. To the greatest extent permitted by, but not in contravention of, +applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and +unconditionally waives, abandons, and surrenders all of Affirmer's Copyright +and Related Rights and associated claims and causes of action, whether now +known or unknown (including existing as well as future claims and causes of +action), in the Work (i) in all territories worldwide, (ii) for the maximum +duration provided by applicable law or treaty (including future time +extensions), (iii) in any current or future medium and for any number of +copies, and (iv) for any purpose whatsoever, including without limitation +commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes +the Waiver for the benefit of each member of the public at large and to the +detriment of Affirmer's heirs and successors, fully intending that such Waiver +shall not be subject to revocation, rescission, cancellation, termination, or +any other legal or equitable action to disrupt the quiet enjoyment of the Work +by the public as contemplated by Affirmer's express Statement of Purpose. + +3. Public License Fallback. Should any part of the Waiver for any reason be +judged legally invalid or ineffective under applicable law, then the Waiver +shall be preserved to the maximum extent permitted taking into account +Affirmer's express Statement of Purpose. In addition, to the extent the Waiver +is so judged Affirmer hereby grants to each affected person a royalty-free, +non transferable, non sublicensable, non exclusive, irrevocable and +unconditional license to exercise Affirmer's Copyright and Related Rights in +the Work (i) in all territories worldwide, (ii) for the maximum duration +provided by applicable law or treaty (including future time extensions), (iii) +in any current or future medium and for any number of copies, and (iv) for any +purpose whatsoever, including without limitation commercial, advertising or +promotional purposes (the "License"). The License shall be deemed effective as +of the date CC0 was applied by Affirmer to the Work. Should any part of the +License for any reason be judged legally invalid or ineffective under +applicable law, such partial invalidity or ineffectiveness shall not +invalidate the remainder of the License, and in such case Affirmer hereby +affirms that he or she will not (i) exercise any of his or her remaining +Copyright and Related Rights in the Work or (ii) assert any associated claims +and causes of action with respect to the Work, in either case contrary to +Affirmer's express Statement of Purpose. + +4. Limitations and Disclaimers. + + a. No trademark or patent rights held by Affirmer are waived, abandoned, + surrendered, licensed or otherwise affected by this document. + + b. Affirmer offers the Work as-is and makes no representations or warranties + of any kind concerning the Work, express, implied, statutory or otherwise, + including without limitation warranties of title, merchantability, fitness + for a particular purpose, non infringement, or the absence of latent or + other defects, accuracy, or the present or absence of errors, whether or not + discoverable, all to the greatest extent permissible under applicable law. + + c. Affirmer disclaims responsibility for clearing rights of other persons + that may apply to the Work or any use thereof, including without limitation + any person's Copyright and Related Rights in the Work. Further, Affirmer + disclaims responsibility for obtaining any necessary consents, permissions + or other rights required for any use of the Work. + + d. Affirmer understands and acknowledges that Creative Commons is not a + party to this document and has no duty or obligation with respect to this + CC0 or use of the Work. + +For more information, please see + diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/address.c b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/address.c new file mode 100644 index 0000000000..b956e9cb29 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/address.c @@ -0,0 +1,91 @@ +#include +#include + +#include "address.h" +#include "params.h" +#include "utils.h" + +/* + * Specify which level of Merkle tree (the "layer") we're working on + */ +void set_layer_addr(uint32_t addr[8], uint32_t layer) { + ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; +} + +/* + * Specify which Merkle tree within the level (the "tree address") we're working on + */ +void set_tree_addr(uint32_t addr[8], uint64_t tree) { + ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); +} + +/* + * Specify the reason we'll use this address structure for, that is, what + * hash will we compute with it. This is used so that unrelated types of + * hashes don't accidentally get the same address structure. The type will be + * one of the SPX_ADDR_TYPE constants + */ +void set_type(uint32_t addr[8], uint32_t type) { + ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; +} + +/* + * Copy the layer and tree fields of the address structure. This is used + * when we're doing multiple types of hashes within the same Merkle tree + */ +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); +} + +/* These functions are used for OTS addresses. */ + +/* + * Specify which Merkle leaf we're working on; that is, which OTS keypair + * we're talking about. + */ +void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { + ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; +} + +/* + * Copy the layer, tree and keypair fields of the address structure. This is + * used when we're doing multiple things within the same OTS keypair + */ +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); + ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; +} + +/* + * Specify which Merkle chain within the OTS we're working with + * (the chain address) + */ +void set_chain_addr(uint32_t addr[8], uint32_t chain) { + ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; +} + +/* + * Specify where in the Merkle chain we are +* (the hash address) + */ +void set_hash_addr(uint32_t addr[8], uint32_t hash) { + ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; +} + +/* These functions are used for all hash tree addresses (including FORS). */ + +/* + * Specify the height of the node in the Merkle/FORS tree we are in + * (the tree height) + */ +void set_tree_height(uint32_t addr[8], uint32_t tree_height) { + ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; +} + +/* + * Specify the distance from the left edge of the node in the Merkle/FORS tree + * (the tree index) + */ +void set_tree_index(uint32_t addr[8], uint32_t tree_index) { + u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/address.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/address.h new file mode 100644 index 0000000000..24a84eb40c --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/address.h @@ -0,0 +1,52 @@ +#ifndef SPX_ADDRESS_H +#define SPX_ADDRESS_H + +#include + +#include "params.h" + +/* The hash types that are passed to set_type */ +#define SPX_ADDR_TYPE_WOTS 0 +#define SPX_ADDR_TYPE_WOTSPK 1 +#define SPX_ADDR_TYPE_HASHTREE 2 +#define SPX_ADDR_TYPE_FORSTREE 3 +#define SPX_ADDR_TYPE_FORSPK 4 +#define SPX_ADDR_TYPE_WOTSPRF 5 +#define SPX_ADDR_TYPE_FORSPRF 6 + +#define set_layer_addr SPX_NAMESPACE(set_layer_addr) +void set_layer_addr(uint32_t addr[8], uint32_t layer); + +#define set_tree_addr SPX_NAMESPACE(set_tree_addr) +void set_tree_addr(uint32_t addr[8], uint64_t tree); + +#define set_type SPX_NAMESPACE(set_type) +void set_type(uint32_t addr[8], uint32_t type); + +/* Copies the layer and tree part of one address into the other */ +#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); + +/* These functions are used for WOTS and FORS addresses. */ + +#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) +void set_keypair_addr(uint32_t addr[8], uint32_t keypair); + +#define set_chain_addr SPX_NAMESPACE(set_chain_addr) +void set_chain_addr(uint32_t addr[8], uint32_t chain); + +#define set_hash_addr SPX_NAMESPACE(set_hash_addr) +void set_hash_addr(uint32_t addr[8], uint32_t hash); + +#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); + +/* These functions are used for all hash tree addresses (including FORS). */ + +#define set_tree_height SPX_NAMESPACE(set_tree_height) +void set_tree_height(uint32_t addr[8], uint32_t tree_height); + +#define set_tree_index SPX_NAMESPACE(set_tree_index) +void set_tree_index(uint32_t addr[8], uint32_t tree_index); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/api.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/api.h new file mode 100644 index 0000000000..b119511c75 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/api.h @@ -0,0 +1,77 @@ +#ifndef PQCLEAN_SPHINCSSHAKE192FROBUST_AARCH64_API_H +#define PQCLEAN_SPHINCSSHAKE192FROBUST_AARCH64_API_H + +#include +#include + +#define PQCLEAN_SPHINCSSHAKE192FROBUST_AARCH64_CRYPTO_ALGNAME "SPHINCS+-shake-192f-robust" + +#define PQCLEAN_SPHINCSSHAKE192FROBUST_AARCH64_CRYPTO_SECRETKEYBYTES 96 +#define PQCLEAN_SPHINCSSHAKE192FROBUST_AARCH64_CRYPTO_PUBLICKEYBYTES 48 +#define PQCLEAN_SPHINCSSHAKE192FROBUST_AARCH64_CRYPTO_BYTES 35664 + +#define PQCLEAN_SPHINCSSHAKE192FROBUST_AARCH64_CRYPTO_SEEDBYTES 72 + +/* + * Returns the length of a secret key, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE192FROBUST_AARCH64_crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE192FROBUST_AARCH64_crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE192FROBUST_AARCH64_crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE192FROBUST_AARCH64_crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +int PQCLEAN_SPHINCSSHAKE192FROBUST_AARCH64_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +int PQCLEAN_SPHINCSSHAKE192FROBUST_AARCH64_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +int PQCLEAN_SPHINCSSHAKE192FROBUST_AARCH64_crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +int PQCLEAN_SPHINCSSHAKE192FROBUST_AARCH64_crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, + const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +int PQCLEAN_SPHINCSSHAKE192FROBUST_AARCH64_crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +int PQCLEAN_SPHINCSSHAKE192FROBUST_AARCH64_crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/context.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/context.h new file mode 100644 index 0000000000..6e0a33f3b7 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/context.h @@ -0,0 +1,19 @@ +#ifndef SPX_CONTEXT_H +#define SPX_CONTEXT_H + +#include + +#include "params.h" + +typedef struct { + uint8_t pub_seed[SPX_N]; + uint8_t sk_seed[SPX_N]; +} spx_ctx; + +#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) +void initialize_hash_function(spx_ctx *ctx); + +#define free_hash_function SPX_NAMESPACE(free_hash_function) +void free_hash_function(spx_ctx *ctx); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/context_shake.c b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/context_shake.c new file mode 100644 index 0000000000..9614a103d3 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/context_shake.c @@ -0,0 +1,12 @@ +#include "context.h" + +/* For SHAKE256, there is no immediate reason to initialize at the start, + so this function is an empty operation. */ +void initialize_hash_function(spx_ctx *ctx) { + (void)ctx; /* Suppress an 'unused parameter' warning. */ +} + +// in case the hash function api is heap-based. +void free_hash_function(spx_ctx *ctx) { + (void)ctx; +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/f1600x2.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/f1600x2.h new file mode 100644 index 0000000000..70d1af9f14 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/f1600x2.h @@ -0,0 +1,11 @@ +#ifndef SPX_F1600X2_H +#define SPX_F1600X2_H + +#include + +extern uint64_t f1600_RC[24]; +extern void _f1600x2(uint64_t *a, uint64_t *rc); + +#define f1600x2(s) do {_f1600x2((s), f1600_RC);} while(0) + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/f1600x2.s b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/f1600x2.s new file mode 100644 index 0000000000..640ed791ed --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/f1600x2.s @@ -0,0 +1,143 @@ +# From https://github.com/bwesterb/armed-keccak + +.macro round + # Execute theta, but without xoring into the state yet. + # Compute parities p[i] = a[i] ^ a[5+i] ^ ... ^ a[20+i]. + eor3.16b v25, v0, v5, v10 + eor3.16b v26, v1, v6, v11 + eor3.16b v27, v2, v7, v12 + eor3.16b v28, v3, v8, v13 + eor3.16b v29, v4, v9, v14 + + eor3.16b v25, v25, v15, v20 + eor3.16b v26, v26, v16, v21 + eor3.16b v27, v27, v17, v22 + eor3.16b v28, v28, v18, v23 + eor3.16b v29, v29, v19, v24 + + # d[0] = rotl(p[1], 1) ^ p[4] + rax1.2d v30, v29, v26 + # d[3] = rotl(p[4], 1) ^ p[2] + rax1.2d v29, v27, v29 + # d[1] = rotl(p[2], 1) ^ p[0] + rax1.2d v27, v25, v27 + # d[4] = rotl(p[0], 1) ^ p[3] + rax1.2d v25, v28, v25 + # d[2] = rotl(p[3], 1) ^ p[1] + rax1.2d v28, v26, v28 + + # Xor parities from step theta into the state at the same time + # as executing rho and pi. + eor.16b v0, v0, v30 + mov.16b v31, v1 + xar.2d v1, v6, v27, 20 + xar.2d v6, v9, v25, 44 + xar.2d v9, v22, v28, 3 + xar.2d v22, v14, v25, 25 + xar.2d v14, v20, v30, 46 + xar.2d v20, v2, v28, 2 + xar.2d v2, v12, v28, 21 + xar.2d v12, v13, v29, 39 + xar.2d v13, v19, v25, 56 + xar.2d v19, v23, v29, 8 + xar.2d v23, v15, v30, 23 + xar.2d v15, v4, v25, 37 + xar.2d v4, v24, v25, 50 + xar.2d v24, v21, v27, 62 + xar.2d v21, v8, v29, 9 + xar.2d v8, v16, v27, 19 + xar.2d v16, v5, v30, 28 + xar.2d v5, v3, v29, 36 + xar.2d v3, v18, v29, 43 + xar.2d v18, v17, v28, 49 + xar.2d v17, v11, v27, 54 + xar.2d v11, v7, v28, 58 + xar.2d v7, v10, v30, 61 + xar.2d v10, v31, v27, 63 + + # Chi + bcax.16b v25, v0, v2, v1 + bcax.16b v26, v1, v3, v2 + bcax.16b v2, v2, v4, v3 + bcax.16b v3, v3, v0, v4 + bcax.16b v4, v4, v1, v0 + mov.16b v0, v25 + mov.16b v1, v26 + + bcax.16b v25, v5, v7, v6 + bcax.16b v26, v6, v8, v7 + bcax.16b v7, v7, v9, v8 + bcax.16b v8, v8, v5, v9 + bcax.16b v9, v9, v6, v5 + mov.16b v5, v25 + mov.16b v6, v26 + + bcax.16b v25, v10, v12, v11 + bcax.16b v26, v11, v13, v12 + bcax.16b v12, v12, v14, v13 + bcax.16b v13, v13, v10, v14 + bcax.16b v14, v14, v11, v10 + mov.16b v10, v25 + mov.16b v11, v26 + + bcax.16b v25, v15, v17, v16 + bcax.16b v26, v16, v18, v17 + bcax.16b v17, v17, v19, v18 + bcax.16b v18, v18, v15, v19 + bcax.16b v19, v19, v16, v15 + mov.16b v15, v25 + mov.16b v16, v26 + + bcax.16b v25, v20, v22, v21 + bcax.16b v26, v21, v23, v22 + bcax.16b v22, v22, v24, v23 + bcax.16b v23, v23, v20, v24 + bcax.16b v24, v24, v21, v20 + mov.16b v20, v25 + mov.16b v21, v26 + + # iota + ld1r {v25.2d}, [x1], #8 + eor.16b v0, v0, v25 +.endm + +.align 4 +.global __f1600x2 +__f1600x2: + stp d8, d9, [sp,#-16]! + stp d10, d11, [sp,#-16]! + stp d12, d13, [sp,#-16]! + stp d14, d15, [sp,#-16]! + + mov x2, x0 + mov x3, #24 + + ld1.2d {v0, v1, v2, v3}, [x0], #64 + ld1.2d {v4, v5, v6, v7}, [x0], #64 + ld1.2d {v8, v9, v10, v11}, [x0], #64 + ld1.2d {v12, v13, v14, v15}, [x0], #64 + ld1.2d {v16, v17, v18, v19}, [x0], #64 + ld1.2d {v20, v21, v22, v23}, [x0], #64 + ld1.2d {v24}, [x0] + +loop: + round + + subs x3, x3, #1 + cbnz x3, loop + + mov x0, x2 + st1.2d {v0, v1, v2, v3}, [x0], #64 + st1.2d {v4, v5, v6, v7}, [x0], #64 + st1.2d {v8, v9, v10, v11}, [x0], #64 + st1.2d {v12, v13, v14, v15}, [x0], #64 + st1.2d {v16, v17, v18, v19}, [x0], #64 + st1.2d {v20, v21, v22, v23}, [x0], #64 + st1.2d {v24}, [x0] + + ldp d14, d15, [sp], #16 + ldp d12, d13, [sp], #16 + ldp d10, d11, [sp], #16 + ldp d8, d9, [sp], #16 + + ret lr diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/f1600x2_const.c b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/f1600x2_const.c new file mode 100644 index 0000000000..e49c0ba149 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/f1600x2_const.c @@ -0,0 +1,30 @@ +#include "f1600x2.h" + +uint64_t f1600_RC[24] = { + 0x0000000000000001, + 0x0000000000008082, + 0x800000000000808A, + 0x8000000080008000, + 0x000000000000808B, + 0x0000000080000001, + 0x8000000080008081, + 0x8000000000008009, + 0x000000000000008A, + 0x0000000000000088, + 0x0000000080008009, + 0x000000008000000A, + 0x000000008000808B, + 0x800000000000008B, + 0x8000000000008089, + 0x8000000000008003, + 0x8000000000008002, + 0x8000000000000080, + 0x000000000000800A, + 0x800000008000000A, + 0x8000000080008081, + 0x8000000000008080, + 0x0000000080000001, + 0x8000000080008008, +}; + + diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/fips202x2.c b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/fips202x2.c new file mode 100644 index 0000000000..4718c343bc --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/fips202x2.c @@ -0,0 +1,148 @@ +#include +#include + +#include "fips202x2.h" +#include "f1600x2.h" +#include "fips202.h" + +uint64_t load64(const unsigned char *x) { + unsigned long long r = 0, i; + + for (i = 0; i < 8; ++i) { + r |= (unsigned long long)x[i] << 8 * i; + } + return r; +} + +void store64(uint8_t *x, uint64_t u) { + unsigned int i; + + for (i = 0; i < 8; ++i) { + x[i] = (uint8_t)u; + u >>= 8; + } +} + +static void keccak_absorb2x(uint64_t *s, + unsigned int r, + const unsigned char *m0, + const unsigned char *m1, + unsigned long long int mlen, + unsigned char p) { + unsigned long long i; + unsigned char t0[200]; + unsigned char t1[200]; + + while (mlen >= r) { + for (i = 0; i < r / 8; ++i) { + s[2 * i + 0] ^= load64(m0 + 8 * i); + s[2 * i + 1] ^= load64(m1 + 8 * i); + } + + f1600x2(s); + mlen -= r; + m0 += r; + m1 += r; + } + + for (i = 0; i < r; ++i) { + t0[i] = 0; + t1[i] = 0; + } + for (i = 0; i < mlen; ++i) { + t0[i] = m0[i]; + t1[i] = m1[i]; + } + + t0[i] = p; + t1[i] = p; + + t0[r - 1] |= 128; + t1[r - 1] |= 128; + + for (i = 0; i < r / 8; ++i) { + s[2 * i + 0] ^= load64(t0 + 8 * i); + s[2 * i + 1] ^= load64(t1 + 8 * i); + } +} + + +static void keccak_squeezeblocks2x(unsigned char *h0, + unsigned char *h1, + unsigned long long int nblocks, + uint64_t *s, + unsigned int r) { + unsigned int i; + + while (nblocks > 0) { + f1600x2(s); + for (i = 0; i < (r >> 3); i++) { + store64(h0 + 8 * i, s[2 * i + 0]); + store64(h1 + 8 * i, s[2 * i + 1]); + } + h0 += r; + h1 += r; + nblocks--; + } +} + + + +void shake128x2(unsigned char *out0, + unsigned char *out1, + unsigned long long outlen, + unsigned char *in0, + unsigned char *in1, + unsigned long long inlen) { + uint64_t s[50] = {0}; + unsigned char t0[SHAKE128_RATE]; + unsigned char t1[SHAKE128_RATE]; + unsigned int i; + + /* absorb 4 message of identical length in parallel */ + keccak_absorb2x(s, SHAKE128_RATE, in0, in1, inlen, 0x1F); + + /* Squeeze output */ + keccak_squeezeblocks2x(out0, out1, outlen / SHAKE128_RATE, s, SHAKE128_RATE); + + out0 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; + out1 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; + + if (outlen % SHAKE128_RATE) { + keccak_squeezeblocks2x(t0, t1, 1, s, SHAKE128_RATE); + for (i = 0; i < outlen % SHAKE128_RATE; i++) { + out0[i] = t0[i]; + out1[i] = t1[i]; + } + } +} + + +void shake256x2(unsigned char *out0, + unsigned char *out1, + unsigned long long outlen, + unsigned char *in0, + unsigned char *in1, + unsigned long long inlen) { + uint64_t s[50] = {0}; + unsigned char t0[SHAKE256_RATE]; + unsigned char t1[SHAKE256_RATE]; + unsigned int i; + + /* absorb 2 message of identical length in parallel */ + keccak_absorb2x(s, SHAKE256_RATE, in0, in1, inlen, 0x1F); + + /* Squeeze output */ + keccak_squeezeblocks2x(out0, out1, outlen / SHAKE256_RATE, s, SHAKE256_RATE); + + out0 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; + out1 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; + + if (outlen % SHAKE256_RATE) { + keccak_squeezeblocks2x(t0, t1, 1, s, SHAKE256_RATE); + for (i = 0; i < outlen % SHAKE256_RATE; i++) { + out0[i] = t0[i]; + out1[i] = t1[i]; + } + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/fips202x2.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/fips202x2.h new file mode 100644 index 0000000000..7ba58b35d8 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/fips202x2.h @@ -0,0 +1,24 @@ +#ifndef SPX_FIPS202X2_H +#define SPX_FIPS202X2_H + +#include + +uint64_t load64(const unsigned char *x); +void store64(uint8_t *x, uint64_t u); + + +void shake128x2(unsigned char *out0, + unsigned char *out1, + unsigned long long outlen, + unsigned char *in0, + unsigned char *in1, + unsigned long long inlen); + +void shake256x2(unsigned char *out0, + unsigned char *out1, + unsigned long long outlen, + unsigned char *in0, + unsigned char *in1, + unsigned long long inlen); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/fors.c b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/fors.c new file mode 100644 index 0000000000..39193d04e2 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/fors.c @@ -0,0 +1,191 @@ +#include +#include +#include + +#include "fors.h" + +#include "address.h" +#include "hash.h" +#include "hashx2.h" +#include "thash.h" +#include "thashx2.h" +#include "utils.h" +#include "utilsx2.h" + +static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + prf_addr(sk, ctx, fors_leaf_addr); +} + +static void fors_gen_skx2(unsigned char *sk0, + unsigned char *sk1, + const spx_ctx *ctx, + uint32_t fors_leaf_addrx2[2 * 8]) { + prf_addrx2(sk0, sk1, + ctx, fors_leaf_addrx2); +} + +static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, + const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + thash(leaf, sk, 1, ctx, fors_leaf_addr); +} + +static void fors_sk_to_leafx2(unsigned char *leaf0, + unsigned char *leaf1, + const unsigned char *sk0, + const unsigned char *sk1, + const spx_ctx *ctx, + uint32_t fors_leaf_addrx2[2 * 8]) { + thashx2(leaf0, leaf1, + sk0, sk1, + 1, ctx, fors_leaf_addrx2); +} + +struct fors_gen_leaf_info { + uint32_t leaf_addrx[2 * 8]; +}; + +static void fors_gen_leafx2(unsigned char *leaf, + const spx_ctx *ctx, + uint32_t addr_idx, void *info) { + struct fors_gen_leaf_info *fors_info = info; + uint32_t *fors_leaf_addrx2 = fors_info->leaf_addrx; + unsigned int j; + + /* Only set the parts that the caller doesn't set */ + for (j = 0; j < 2; j++) { + set_tree_index(fors_leaf_addrx2 + j * 8, addr_idx + j); + set_type(fors_leaf_addrx2 + j * 8, SPX_ADDR_TYPE_FORSPRF); + } + + fors_gen_skx2(leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + ctx, fors_leaf_addrx2); + + for (j = 0; j < 2; j++) { + set_type(fors_leaf_addrx2 + j * 8, SPX_ADDR_TYPE_FORSTREE); + } + + fors_sk_to_leafx2(leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + ctx, fors_leaf_addrx2); +} + +/** + * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + * Assumes indices has space for SPX_FORS_TREES integers. + */ +static void message_to_indices(uint32_t *indices, const unsigned char *m) { + unsigned int i, j; + unsigned int offset = 0; + + for (i = 0; i < SPX_FORS_TREES; i++) { + indices[i] = 0; + for (j = 0; j < SPX_FORS_HEIGHT; j++) { + indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); + offset++; + } + } +} + +/** + * Signs a message m, deriving the secret key from sk_seed and the FTS address. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + uint32_t fors_tree_addr[2 * 8] = {0}; + struct fors_gen_leaf_info fors_info = {0}; + uint32_t *fors_leaf_addr = fors_info.leaf_addrx; + uint32_t fors_pk_addr[8] = {0}; + uint32_t idx_offset; + unsigned int i; + + for (i = 0; i < 2; i++) { + copy_keypair_addr(fors_tree_addr + 8 * i, fors_addr); + set_type(fors_tree_addr + 8 * i, SPX_ADDR_TYPE_FORSTREE); + copy_keypair_addr(fors_leaf_addr + 8 * i, fors_addr); + } + copy_keypair_addr(fors_pk_addr, fors_addr); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); + + message_to_indices(indices, m); + + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); + + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + + /* Include the secret key part that produces the selected leaf node. */ + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); + fors_gen_sk(sig, ctx, fors_tree_addr); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + sig += SPX_N; + + /* Compute the authentication path for this leaf node. */ + treehashx2(roots + i * SPX_N, sig, ctx, + indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx2, + fors_tree_addr, &fors_info); + + sig += SPX_N * SPX_FORS_HEIGHT; + } + + /* Hash horizontally across all tree roots to derive the public key. */ + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); +} + +/** + * Derives the FORS public key from a signature. + * This can be used for verification by comparing to a known public key, or to + * subsequently verify a signature on the derived public key. The latter is the + * typical use-case when used as an FTS below an OTS in a hypertree. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + unsigned char leaf[SPX_N]; + uint32_t fors_tree_addr[8] = {0}; + uint32_t fors_pk_addr[8] = {0}; + uint32_t idx_offset; + unsigned int i; + + copy_keypair_addr(fors_tree_addr, fors_addr); + copy_keypair_addr(fors_pk_addr, fors_addr); + + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); + + message_to_indices(indices, m); + + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); + + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + + /* Derive the leaf from the included secret key part. */ + fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); + sig += SPX_N; + + /* Derive the corresponding root node of this tree. */ + compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, + sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); + sig += SPX_N * SPX_FORS_HEIGHT; + } + + /* Hash horizontally across all tree roots to derive the public key. */ + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/fors.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/fors.h new file mode 100644 index 0000000000..509140a178 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/fors.h @@ -0,0 +1,32 @@ +#ifndef SPX_FORS_H +#define SPX_FORS_H + +#include + +#include "context.h" +#include "params.h" + +/** + * Signs a message m, deriving the secret key from sk_seed and the FTS address. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +#define fors_sign SPX_NAMESPACE(fors_sign) +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); + +/** + * Derives the FORS public key from a signature. + * This can be used for verification by comparing to a known public key, or to + * subsequently verify a signature on the derived public key. The latter is the + * typical use-case when used as an FTS below an OTS in a hypertree. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/hash.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/hash.h new file mode 100644 index 0000000000..f7c87d4c3c --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/hash.h @@ -0,0 +1,28 @@ +#ifndef SPX_HASH_H +#define SPX_HASH_H + +#include +#include + +#include "context.h" +#include "params.h" + +#define prf_addr SPX_NAMESPACE(prf_addr) +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]); + +#define gen_message_random SPX_NAMESPACE(gen_message_random) +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); + +#define hash_message SPX_NAMESPACE(hash_message) +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); + + + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/hash_shake.c b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/hash_shake.c new file mode 100644 index 0000000000..ff5e7ec918 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/hash_shake.c @@ -0,0 +1,83 @@ +#include +#include + +#include "hash.h" + +#include "address.h" +#include "fips202.h" +#include "params.h" +#include "utils.h" + +/* + * Computes PRF(pk_seed, sk_seed, addr) + */ +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]) { + unsigned char buf[2 * SPX_N + SPX_ADDR_BYTES]; + + memcpy(buf, ctx->pub_seed, SPX_N); + memcpy(buf + SPX_N, addr, SPX_ADDR_BYTES); + memcpy(buf + SPX_N + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); + + shake256(out, SPX_N, buf, 2 * SPX_N + SPX_ADDR_BYTES); +} + +/** + * Computes the message-dependent randomness R, using a secret seed and an + * optional randomization value as well as the message. + */ +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { + (void)ctx; + shake256incctx s_inc; + + shake256_inc_init(&s_inc); + shake256_inc_absorb(&s_inc, sk_prf, SPX_N); + shake256_inc_absorb(&s_inc, optrand, SPX_N); + shake256_inc_absorb(&s_inc, m, mlen); + shake256_inc_finalize(&s_inc); + shake256_inc_squeeze(R, SPX_N, &s_inc); + shake256_inc_ctx_release(&s_inc); +} + +/** + * Computes the message hash using R, the public key, and the message. + * Outputs the message digest and the index of the leaf. The index is split in + * the tree index and the leaf index, for convenient copying to an address. + */ +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { + (void)ctx; +#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) +#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) +#define SPX_LEAF_BITS SPX_TREE_HEIGHT +#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) +#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) + + unsigned char buf[SPX_DGST_BYTES]; + unsigned char *bufp = buf; + shake256incctx s_inc; + + shake256_inc_init(&s_inc); + shake256_inc_absorb(&s_inc, R, SPX_N); + shake256_inc_absorb(&s_inc, pk, SPX_PK_BYTES); + shake256_inc_absorb(&s_inc, m, mlen); + shake256_inc_finalize(&s_inc); + shake256_inc_squeeze(buf, SPX_DGST_BYTES, &s_inc); + shake256_inc_ctx_release(&s_inc); + + memcpy(digest, bufp, SPX_FORS_MSG_BYTES); + bufp += SPX_FORS_MSG_BYTES; + + + *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); + *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); + bufp += SPX_TREE_BYTES; + + *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); + *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/hash_shakex2.c b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/hash_shakex2.c new file mode 100644 index 0000000000..99571916a2 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/hash_shakex2.c @@ -0,0 +1,52 @@ +#include +#include + +#include "hashx2.h" + +#include "address.h" +#include "f1600x2.h" +#include "fips202x2.h" +#include "params.h" + +/* + * 2-way parallel version of prf_addr; takes 2x as much input and output + */ +void prf_addrx2(unsigned char *out0, + unsigned char *out1, + const spx_ctx *ctx, + const uint32_t addrx2[2 * 8]) { + /* As we write and read only a few quadwords, it is more efficient to + * build and extract from the fourway SHAKE256 state by hand. */ + uint64_t state[50] = {0}; + + for (int i = 0; i < SPX_N / 8; i++) { + uint64_t x = load64(ctx->pub_seed + 8 * i); + state[2 * i] = x; + state[2 * i + 1] = x; + } + for (int i = 0; i < 4; i++) { + state[2 * (SPX_N / 8 + i)] = (((uint64_t)addrx2[1 + 2 * i]) << 32) + | (uint64_t)addrx2[2 * i]; + state[2 * (SPX_N / 8 + i) + 1] = (((uint64_t)addrx2[8 + 1 + 2 * i]) << 32) + | (uint64_t)addrx2[8 + 2 * i]; + } + for (int i = 0; i < SPX_N / 8; i++) { + uint64_t x = load64(ctx->sk_seed + 8 * i); + state[2 * (SPX_N / 8 + i + 4)] = x; + state[2 * (SPX_N / 8 + i + 4) + 1] = x; + } + + /* SHAKE domain separator and padding. */ + state[2 * (SPX_N / 4 + 4)] = 0x1f; + state[2 * (SPX_N / 4 + 4) + 1] = 0x1f; + + state[2 * 16] = 0x80ULL << 56; + state[2 * 16 + 1] = 0x80ULL << 56; + + f1600x2(state); + + for (int i = 0; i < SPX_N / 8; i++) { + store64(out0 + 8 * i, state[2 * i]); + store64(out1 + 8 * i, state[2 * i + 1]); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/hashx2.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/hashx2.h new file mode 100644 index 0000000000..99b8873a9b --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/hashx2.h @@ -0,0 +1,14 @@ +#ifndef SPX_HASHX2_H +#define SPX_HASHX2_H + +#include "context.h" +#include "params.h" +#include + +#define prf_addrx2 SPX_NAMESPACE(prf_addrx2) +void prf_addrx2(unsigned char *out0, + unsigned char *out1, + const spx_ctx *ctx, + const uint32_t addrx2[2 * 8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/merkle.c b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/merkle.c new file mode 100644 index 0000000000..c94ee23939 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/merkle.c @@ -0,0 +1,64 @@ +#include +#include + +#include "merkle.h" + +#include "address.h" +#include "params.h" +#include "utils.h" +#include "utilsx2.h" +#include "wots.h" +#include "wotsx2.h" + +/* + * This generates a Merkle signature (WOTS signature followed by the Merkle + * authentication path). + */ +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf) { + unsigned char *auth_path = sig + SPX_WOTS_BYTES; + uint32_t tree_addrx2[2 * 8] = { 0 }; + int j; + struct leaf_info_x2 info = { 0 }; + unsigned steps[ SPX_WOTS_LEN ]; + + info.wots_sig = sig; + chain_lengths(steps, root); + info.wots_steps = steps; + + for (j = 0; j < 2; j++) { + set_type(&tree_addrx2[8 * j], SPX_ADDR_TYPE_HASHTREE); + set_type(&info.leaf_addr[8 * j], SPX_ADDR_TYPE_WOTS); + set_type(&info.pk_addr[8 * j], SPX_ADDR_TYPE_WOTSPK); + copy_subtree_addr(&tree_addrx2[8 * j], tree_addr); + copy_subtree_addr(&info.leaf_addr[8 * j], wots_addr); + copy_subtree_addr(&info.pk_addr[8 * j], wots_addr); + } + + info.wots_sign_leaf = idx_leaf; + + treehashx2(root, auth_path, ctx, + idx_leaf, 0, + SPX_TREE_HEIGHT, + wots_gen_leafx2, + tree_addrx2, &info); +} + +/* Compute root node of the top-most subtree. */ +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { + /* We do not need the auth path in key generation, but it simplifies the + code to have just one treehash routine that computes both root and path + in one function. */ + unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; + uint32_t top_tree_addr[8] = {0}; + uint32_t wots_addr[8] = {0}; + + set_layer_addr(top_tree_addr, SPX_D - 1); + set_layer_addr(wots_addr, SPX_D - 1); + + merkle_sign(auth_path, root, ctx, + wots_addr, top_tree_addr, + ~0 /* ~0 means "don't bother generating an auth path */ ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/merkle.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/merkle.h new file mode 100644 index 0000000000..769cf2e970 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/merkle.h @@ -0,0 +1,21 @@ +#ifndef MERKLE_H_ +#define MERKLE_H_ + +#include + +#include "context.h" +#include "params.h" + +/* Generate a Merkle signature (WOTS signature followed by the Merkle */ +/* authentication path) */ +#define merkle_sign SPX_NAMESPACE(merkle_sign) +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf); + +/* Compute the root node of the top-most subtree. */ +#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); + +#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/nistapi.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/nistapi.h new file mode 100644 index 0000000000..3cb71afad4 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/nistapi.h @@ -0,0 +1,87 @@ +#ifndef SPX_API_H +#define SPX_API_H + +#include +#include + +#include "params.h" + +#define CRYPTO_ALGNAME "SPHINCS+" + +#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES +#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES +#define CRYPTO_BYTES SPX_BYTES +#define CRYPTO_SEEDBYTES (3*SPX_N) + +/* + * Returns the length of a secret key, in bytes + */ +#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) +size_t crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) +size_t crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) +size_t crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) +size_t crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +#define crypto_sign SPX_NAMESPACE(crypto_sign) +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/params.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/params.h new file mode 100644 index 0000000000..efa39d84b6 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/params.h @@ -0,0 +1,56 @@ +#ifndef SPX_PARAMS_H +#define SPX_PARAMS_H + +#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSSHAKE192FROBUST_AARCH64_##s + +/* Hash output length in bytes. */ +#define SPX_N 24 +/* Height of the hypertree. */ +#define SPX_FULL_HEIGHT 66 +/* Number of subtree layer. */ +#define SPX_D 22 +/* FORS tree dimensions. */ +#define SPX_FORS_HEIGHT 8 +#define SPX_FORS_TREES 33 +/* Winternitz parameter, */ +#define SPX_WOTS_W 16 + +/* The hash function is defined by linking a different hash.c file, as opposed + to setting a #define constant. */ + +/* For clarity */ +#define SPX_ADDR_BYTES 32 + +/* WOTS parameters. */ +#define SPX_WOTS_LOGW 4 + +#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) + +/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ +#define SPX_WOTS_LEN2 3 + +#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) +#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) +#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES + +/* Subtree size. */ +#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) + +//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT +// #error SPX_D should always divide SPX_FULL_HEIGHT +//#endif + +/* FORS parameters. */ +#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) +#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) +#define SPX_FORS_PK_BYTES SPX_N + +/* Resulting SPX sizes. */ +#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ + SPX_FULL_HEIGHT * SPX_N) +#define SPX_PK_BYTES (2 * SPX_N) +#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) + +#include "shake_offsets.h" + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/shake_offsets.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/shake_offsets.h new file mode 100644 index 0000000000..6b28d95d91 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/shake_offsets.h @@ -0,0 +1,21 @@ +#ifndef SHAKE_OFFSETS_H_ +#define SHAKE_OFFSETS_H_ + +/* + * Offsets of various fields in the address structure when we use SHAKE as + * the Sphincs+ hash function + */ + +#define SPX_OFFSET_LAYER 3 /* The byte used to specify the Merkle tree layer */ +#define SPX_OFFSET_TREE 8 /* The start of the 8 byte field used to specify the tree */ +#define SPX_OFFSET_TYPE 19 /* The byte used to specify the hash type (reason) */ +#define SPX_OFFSET_KP_ADDR2 22 /* The high byte used to specify the key pair (which one-time signature) */ +#define SPX_OFFSET_KP_ADDR1 23 /* The low byte used to specify the key pair */ +#define SPX_OFFSET_CHAIN_ADDR 27 /* The byte used to specify the chain address (which Winternitz chain) */ +#define SPX_OFFSET_HASH_ADDR 31 /* The byte used to specify the hash address (where in the Winternitz chain) */ +#define SPX_OFFSET_TREE_HGT 27 /* The byte used to specify the height of this node in the FORS or Merkle tree */ +#define SPX_OFFSET_TREE_INDEX 28 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ + +#define SPX_SHAKE 1 + +#endif /* SHAKE_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/sign.c b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/sign.c new file mode 100644 index 0000000000..9d0c7d1b22 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/sign.c @@ -0,0 +1,286 @@ +#include +#include +#include + +#include "address.h" +#include "context.h" +#include "fors.h" +#include "hash.h" +#include "merkle.h" +#include "nistapi.h" +#include "params.h" +#include "randombytes.h" +#include "thash.h" +#include "utils.h" +#include "wots.h" + +/* + * Returns the length of a secret key, in bytes + */ +size_t crypto_sign_secretkeybytes(void) { + return CRYPTO_SECRETKEYBYTES; +} + +/* + * Returns the length of a public key, in bytes + */ +size_t crypto_sign_publickeybytes(void) { + return CRYPTO_PUBLICKEYBYTES; +} + +/* + * Returns the length of a signature, in bytes + */ +size_t crypto_sign_bytes(void) { + return CRYPTO_BYTES; +} + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +size_t crypto_sign_seedbytes(void) { + return CRYPTO_SEEDBYTES; +} + +/* + * Generates an SPX key pair given a seed of length + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [PUB_SEED || root] + */ +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed) { + spx_ctx ctx; + + /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ + memcpy(sk, seed, CRYPTO_SEEDBYTES); + + memcpy(pk, sk + 2 * SPX_N, SPX_N); + + memcpy(ctx.pub_seed, pk, SPX_N); + memcpy(ctx.sk_seed, sk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + /* Compute root node of the top-most subtree. */ + merkle_gen_root(sk + 3 * SPX_N, &ctx); + + // cleanup + free_hash_function(&ctx); + + memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); + + return 0; +} + +/* + * Generates an SPX key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [PUB_SEED || root] + */ +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { + uint8_t seed[CRYPTO_SEEDBYTES]; + randombytes(seed, CRYPTO_SEEDBYTES); + crypto_sign_seed_keypair(pk, sk, seed); + + return 0; +} + +/** + * Returns an array containing a detached signature. + */ +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk) { + spx_ctx ctx; + + const uint8_t *sk_prf = sk + SPX_N; + const uint8_t *pk = sk + 2 * SPX_N; + + uint8_t optrand[SPX_N]; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t root[SPX_N]; + uint32_t i; + uint64_t tree; + uint32_t idx_leaf; + uint32_t wots_addr[8] = {0}; + uint32_t tree_addr[8] = {0}; + + memcpy(ctx.sk_seed, sk, SPX_N); + memcpy(ctx.pub_seed, pk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + + /* Optionally, signing can be made non-deterministic using optrand. + This can help counter side-channel attacks that would benefit from + getting a large number of traces when the signer uses the same nodes. */ + randombytes(optrand, SPX_N); + /* Compute the digest randomization value. */ + gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); + + /* Derive the message digest and leaf index from R, PK and M. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; + + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); + + /* Sign the message hash using FORS. */ + fors_sign(sig, root, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); + sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; + + /* Update the indices for the next layer. */ + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; + } + + free_hash_function(&ctx); + + *siglen = SPX_BYTES; + + return 0; +} + +/** + * Verifies a detached signature and message under a given public key. + */ +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk) { + spx_ctx ctx; + const uint8_t *pub_root = pk + SPX_N; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t wots_pk[SPX_WOTS_BYTES]; + uint8_t root[SPX_N]; + uint8_t leaf[SPX_N]; + unsigned int i; + uint64_t tree; + uint32_t idx_leaf; + uint32_t wots_addr[8] = {0}; + uint32_t tree_addr[8] = {0}; + uint32_t wots_pk_addr[8] = {0}; + + if (siglen != SPX_BYTES) { + return -1; + } + + memcpy(ctx.pub_seed, pk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); + + /* Derive the message digest and leaf index from R || PK || M. */ + /* The additional SPX_N is a result of the hash domain separator. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; + + /* Layer correctly defaults to 0, so no need to set_layer_addr */ + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); + + fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + /* For each subtree.. */ + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + copy_keypair_addr(wots_pk_addr, wots_addr); + + /* The WOTS public key is only correct if the signature was correct. */ + /* Initially, root is the FORS pk, but on subsequent iterations it is + the root of the subtree below the currently processed subtree. */ + wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); + sig += SPX_WOTS_BYTES; + + /* Compute the leaf node using the WOTS public key. */ + thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); + + /* Compute the root node of this subtree. */ + compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, + &ctx, tree_addr); + sig += SPX_TREE_HEIGHT * SPX_N; + + /* Update the indices for the next layer. */ + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; + } + + // cleanup + free_hash_function(&ctx); + + /* Check if the root node equals the root node in the public key. */ + if (memcmp(root, pub_root, SPX_N) != 0) { + return -1; + } + + return 0; +} + + +/** + * Returns an array containing the signature followed by the message. + */ +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk) { + size_t siglen; + + crypto_sign_signature(sm, &siglen, m, mlen, sk); + + memmove(sm + SPX_BYTES, m, mlen); + *smlen = siglen + mlen; + + return 0; +} + +/** + * Verifies a given signature-message pair under a given public key. + */ +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk) { + /* The API caller does not necessarily know what size a signature should be + but SPHINCS+ signatures are always exactly SPX_BYTES. */ + if (smlen < SPX_BYTES) { + memset(m, 0, smlen); + *mlen = 0; + return -1; + } + + *mlen = smlen - SPX_BYTES; + + if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { + memset(m, 0, smlen); + *mlen = 0; + return -1; + } + + /* If verification was successful, move the message to the right place. */ + memmove(m, sm + SPX_BYTES, *mlen); + + return 0; +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/thash.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/thash.h new file mode 100644 index 0000000000..8687ccfb4d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/thash.h @@ -0,0 +1,13 @@ +#ifndef SPX_THASH_H +#define SPX_THASH_H + +#include "context.h" +#include "params.h" + +#include + +#define thash SPX_NAMESPACE(thash) +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/thash_shake_robustx2.c b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/thash_shake_robustx2.c new file mode 100644 index 0000000000..454fc0f4e2 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/thash_shake_robustx2.c @@ -0,0 +1,112 @@ +#include +#include + +#include "thash.h" +#include "thashx2.h" + +#include "address.h" +#include "params.h" +#include "utils.h" + +#include "f1600x2.h" +#include "fips202x2.h" + + +void thash(unsigned char *out, + const unsigned char *in, + unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]) { + uint32_t addrx2 [2 * 8] = { + addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], addr[6], addr[7], + addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], addr[6], addr[7] + }; + thashx2(out, out, in, in, inblocks, ctx, addrx2); +} + +/** + * 2-way parallel version of thash; takes 2x as much input and output + */ +void thashx2(unsigned char *out0, + unsigned char *out1, + const unsigned char *in0, + const unsigned char *in1, + unsigned int inblocks, + const spx_ctx *ctx, uint32_t addrx2[2 * 8]) { + if (inblocks == 1 || inblocks == 2) { + /* As we write and read only a few quadwords, it is more efficient to + * build and extract from the twoway SHAKE256 state by hand. */ + uint64_t state[50] = {0}; + uint64_t state2[50]; + + for (int i = 0; i < SPX_N / 8; i++) { + uint64_t x = load64(ctx->pub_seed + 8 * i); + state[2 * i] = x; + state[2 * i + 1] = x; + } + for (int i = 0; i < 4; i++) { + state[2 * (SPX_N / 8 + i)] = (((uint64_t)addrx2[1 + 2 * i]) << 32) + | (uint64_t)addrx2[2 * i]; + state[2 * (SPX_N / 8 + i) + 1] = (((uint64_t)addrx2[8 + 1 + 2 * i]) << 32) + | (uint64_t)addrx2[8 + 2 * i]; + } + + /* Domain separator and padding. */ + state[2 * 16] = 0x80ULL << 56; + state[2 * 16 + 1] = 0x80ULL << 56; + + state[2 * ((SPX_N / 8) + 4)] ^= 0x1f; + state[2 * ((SPX_N / 8) + 4) + 1] ^= 0x1f; + + /* We will permutate state2 with f1600x2 to compute the bitmask, + * but first we'll copy it to state2 which will be used to compute + * the final output, as its input is almost identical. */ + memcpy(state2, state, 400); + + f1600x2(state); + + /* By copying from state, state2 already contains the pub_seed + * and address. We just need to copy in the input blocks xorred with + * the bitmask we just computed. */ + for (unsigned int i = 0; i < (SPX_N / 8) * inblocks; i++) { + state2[2 * (SPX_N / 8 + 4 + i)] = state[2 * i] ^ load64(in0 + 8 * i); + state2[2 * (SPX_N / 8 + 4 + i) + 1] = state[2 * i + 1] ^ load64(in1 + 8 * i); + } + + /* Domain separator and start of padding. Note that the quadwords + * around are already zeroed for state from which we copied. + * We do a XOR instead of a set as this might be the 16th quadword + * when N=32 and inblocks=2, which already contains the end + * of the padding. */ + state2[2 * ((SPX_N / 8) * (1 + inblocks) + 4)] ^= 0x1f; + state2[2 * ((SPX_N / 8) * (1 + inblocks) + 4) + 1] ^= 0x1f; + + f1600x2(state2); + + for (int i = 0; i < SPX_N / 8; i++) { + store64(out0 + 8 * i, state2[2 * i]); + store64(out1 + 8 * i, state2[2 * i + 1]); + } + } else { + PQCLEAN_VLA(unsigned char, buf0, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, buf1, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, bitmask0, inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, bitmask1, inblocks * SPX_N); + unsigned int i; + + memcpy(buf0, ctx->pub_seed, SPX_N); + memcpy(buf1, ctx->pub_seed, SPX_N); + memcpy(buf0 + SPX_N, addrx2 + 0 * 8, SPX_ADDR_BYTES); + memcpy(buf1 + SPX_N, addrx2 + 1 * 8, SPX_ADDR_BYTES); + + shake256x2(bitmask0, bitmask1, inblocks * SPX_N, + buf0, buf1, SPX_N + SPX_ADDR_BYTES); + + for (i = 0; i < inblocks * SPX_N; i++) { + buf0[SPX_N + SPX_ADDR_BYTES + i] = in0[i] ^ bitmask0[i]; + buf1[SPX_N + SPX_ADDR_BYTES + i] = in1[i] ^ bitmask1[i]; + } + + shake256x2(out0, out1, SPX_N, + buf0, buf1, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/thashx2.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/thashx2.h new file mode 100644 index 0000000000..040375e618 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/thashx2.h @@ -0,0 +1,16 @@ +#ifndef SPX_THASHX2_H +#define SPX_THASHX2_H + +#include "context.h" +#include "params.h" +#include + +#define thashx2 SPX_NAMESPACE(thashx2) +void thashx2(unsigned char *out0, + unsigned char *out1, + const unsigned char *in0, + const unsigned char *in1, + unsigned int inblocks, + const spx_ctx *ctx, uint32_t addrx2[2 * 8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/utils.c b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/utils.c new file mode 100644 index 0000000000..177b541fb9 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/utils.c @@ -0,0 +1,148 @@ +#include + +#include "utils.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "thash.h" + +/** + * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. + */ +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in) { + int i; + + /* Iterate over out in decreasing order, for big-endianness. */ + for (i = (signed int)outlen - 1; i >= 0; i--) { + out[i] = in & 0xff; + in = in >> 8; + } +} + +void u32_to_bytes(unsigned char *out, uint32_t in) { + out[0] = (unsigned char)(in >> 24); + out[1] = (unsigned char)(in >> 16); + out[2] = (unsigned char)(in >> 8); + out[3] = (unsigned char)in; +} + +/** + * Converts the inlen bytes in 'in' from big-endian byte order to an integer. + */ +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { + unsigned long long retval = 0; + unsigned int i; + + for (i = 0; i < inlen; i++) { + retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); + } + return retval; +} + +/** + * Computes a root node given a leaf and an auth path. + * Expects address to be complete other than the tree_height and tree_index. + */ +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]) { + uint32_t i; + unsigned char buffer[2 * SPX_N]; + + /* If leaf_idx is odd (last bit = 1), current path element is a right child + and auth_path has to go left. Otherwise it is the other way around. */ + if (leaf_idx & 1) { + memcpy(buffer + SPX_N, leaf, SPX_N); + memcpy(buffer, auth_path, SPX_N); + } else { + memcpy(buffer, leaf, SPX_N); + memcpy(buffer + SPX_N, auth_path, SPX_N); + } + auth_path += SPX_N; + + for (i = 0; i < tree_height - 1; i++) { + leaf_idx >>= 1; + idx_offset >>= 1; + /* Set the address of the node we're creating. */ + set_tree_height(addr, i + 1); + set_tree_index(addr, leaf_idx + idx_offset); + + /* Pick the right or left neighbor, depending on parity of the node. */ + if (leaf_idx & 1) { + thash(buffer + SPX_N, buffer, 2, ctx, addr); + memcpy(buffer, auth_path, SPX_N); + } else { + thash(buffer, buffer, 2, ctx, addr); + memcpy(buffer + SPX_N, auth_path, SPX_N); + } + auth_path += SPX_N; + } + + /* The last iteration is exceptional; we do not copy an auth_path node. */ + leaf_idx >>= 1; + idx_offset >>= 1; + set_tree_height(addr, tree_height); + set_tree_index(addr, leaf_idx + idx_offset); + thash(root, buffer, 2, ctx, addr); +} + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx * /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]) { + PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); + PQCLEAN_VLA(unsigned int, heights, tree_height + 1); + unsigned int offset = 0; + uint32_t idx; + uint32_t tree_idx; + + for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { + /* Add the next leaf node to the stack. */ + gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); + offset++; + heights[offset - 1] = 0; + + /* If this is a node we need for the auth path.. */ + if ((leaf_idx ^ 0x1) == idx) { + memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); + } + + /* While the top-most nodes are of equal height.. */ + while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { + /* Compute index of the new node, in the next layer. */ + tree_idx = (idx >> (heights[offset - 1] + 1)); + + /* Set the address of the node we're creating. */ + set_tree_height(tree_addr, heights[offset - 1] + 1); + set_tree_index(tree_addr, + tree_idx + (idx_offset >> (heights[offset - 1] + 1))); + /* Hash the top-most nodes from the stack together. */ + thash(stack + (offset - 2)*SPX_N, + stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); + offset--; + /* Note that the top-most node is now one layer higher. */ + heights[offset - 1]++; + + /* If this is a node we need for the auth path.. */ + if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { + memcpy(auth_path + heights[offset - 1]*SPX_N, + stack + (offset - 1)*SPX_N, SPX_N); + } + } + } + memcpy(root, stack, SPX_N); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/utils.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/utils.h new file mode 100644 index 0000000000..64f5d5a53a --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/utils.h @@ -0,0 +1,58 @@ +#ifndef SPX_UTILS_H +#define SPX_UTILS_H + +#include + +#include "compat.h" +#include "context.h" +#include "params.h" + + +/* To support MSVC use alloca() instead of VLAs. See #20. */ + + +/** + * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. + */ +#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in); +#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) +void u32_to_bytes(unsigned char *out, uint32_t in); + +/** + * Converts the inlen bytes in 'in' from big-endian byte order to an integer. + */ +#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); + +/** + * Computes a root node given a leaf and an auth path. + * Expects address to be complete other than the tree_height and tree_index. + */ +#define compute_root SPX_NAMESPACE(compute_root) +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]); + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +#define treehash SPX_NAMESPACE(treehash) +void treehash(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx *ctx /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]); + + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/utilsx2.c b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/utilsx2.c new file mode 100644 index 0000000000..8736474e4f --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/utilsx2.c @@ -0,0 +1,130 @@ +#include + +#include "utilsx2.h" + +#include "address.h" +#include "params.h" +#include "thashx2.h" +#include "utils.h" + +/* + * Generate the entire Merkle tree, computing the authentication path for leaf_idx, + * and the resulting root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) + * + * This expects tree_addrx2 to be initialized to 2 parallel addr structures for + * the Merkle tree nodes + * + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + * + * This works by using the standard Merkle tree building algorithm, except + * that each 'node' tracked is actually 2 consecutive nodes in the real tree. + * When we combine two logical nodes AB and WX, we perform the H + * operation on adjacent real nodes, forming the parent logical node + * (AB)(WX) + * + * When we get to the top level of the real tree (where there is only + * one logical node), we continue this operation one more time; the right + * most real node will by the actual root (and the other node will be + * garbage). We follow the same thashx2 logic so that the 'extract + * authentication path components' part of the loop is still executed (and + * to simplify the code somewhat) + */ +void treehashx2(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, + uint32_t tree_height, + void (*gen_leafx2)( + unsigned char * /* Where to write the leaves */, + const spx_ctx *, + uint32_t idx, void *info), + uint32_t tree_addrx2[2 * 8], + void *info) { + /* This is where we keep the intermediate nodes */ + unsigned char stackx2[tree_height * 2 * SPX_N]; + uint32_t left_adj = 0, prev_left_adj = 0; /* When we're doing the top */ + /* level, the left-most part of the tree isn't at the beginning */ + /* of current[]. These give the offset of the actual start */ + + uint32_t idx; + uint32_t max_idx = (1 << (tree_height - 1)) - 1; + for (idx = 0;; idx++) { + unsigned char current[2 * SPX_N]; /* Current logical node */ + gen_leafx2( current, ctx, 2 * idx + idx_offset, + info ); + + /* Now combine the freshly generated right node with previously */ + /* generated left ones */ + uint32_t internal_idx_offset = idx_offset; + uint32_t internal_idx = idx; + uint32_t internal_leaf = leaf_idx; + uint32_t h; /* The height we are in the Merkle tree */ + for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { + + /* Special processing if we're at the top of the tree */ + if (h >= tree_height - 1) { + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[1 * SPX_N], SPX_N ); + return; + } + /* The tree indexing logic is a bit off in this case */ + /* Adjust it so that the left-most node of the part of */ + /* the tree that we're processing has index 0 */ + prev_left_adj = left_adj; + left_adj = 2 - (1 << (tree_height - h - 1)); + } + + /* Check if we hit the top of the tree */ + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[1 * SPX_N], SPX_N ); + return; + } + + /* + * Check if one of the nodes we have is a part of the + * authentication path; if it is, write it out + */ + if ((((internal_idx << 1) ^ internal_leaf) & ~0x1) == 0) { + memcpy( &auth_path[ h * SPX_N ], + ¤t[(((internal_leaf & 1) ^ 1) + prev_left_adj) * SPX_N], + SPX_N ); + } + + /* + * Check if we're at a left child; if so, stop going up the stack + * Exception: if we've reached the end of the tree, keep on going + * (so we combine the last 2 nodes into the one root node in two + * more iterations) + */ + if ((internal_idx & 1) == 0 && idx < max_idx) { + break; + } + + /* Ok, we're at a right node (or doing the top 3 levels) */ + /* Now combine the left and right logical nodes together */ + + /* Set the address of the node we're creating. */ + int j; + internal_idx_offset >>= 1; + for (j = 0; j < 2; j++) { + set_tree_height(tree_addrx2 + j * 8, h + 1); + set_tree_index(tree_addrx2 + j * 8, + (2 / 2) * (internal_idx & ~1) + j - left_adj + internal_idx_offset ); + } + unsigned char *left = &stackx2[h * 2 * SPX_N]; + thashx2( ¤t[0 * SPX_N], + ¤t[1 * SPX_N], + &left [0 * SPX_N], + ¤t[0 * SPX_N], + 2, ctx, tree_addrx2); + } + + /* We've hit a left child; save the current for when we get the */ + /* corresponding right right */ + memcpy( &stackx2[h * 2 * SPX_N], current, 2 * SPX_N); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/utilsx2.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/utilsx2.h new file mode 100644 index 0000000000..e09faddc43 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/utilsx2.h @@ -0,0 +1,30 @@ +#ifndef SPX_UTILSX2_H +#define SPX_UTILSX2_H + +#include + +#include "context.h" +#include "params.h" + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + * + * This implementation uses SIMD to compute internal nodes 2 at a time (in + * parallel) + */ +#define treehashx2 SPX_NAMESPACE(treehashx2) +void treehashx2(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leafx2)( + unsigned char * /* Where to write the leaves */, + const spx_ctx * /* ctx */, + uint32_t addr_idx, void *info), + uint32_t tree_addrx2[2 * 8], void *info); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/wots.c b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/wots.c new file mode 100644 index 0000000000..3babe45e95 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/wots.c @@ -0,0 +1,259 @@ +#include +#include + +#include "wots.h" +#include "wotsx2.h" + +#include "address.h" +#include "hash.h" +#include "hashx2.h" +#include "params.h" +#include "thashx2.h" +#include "utils.h" +#include "utilsx2.h" + +// TODO clarify address expectations, and make them more uniform. +// TODO i.e. do we expect types to be set already? +// TODO and do we expect modifications or copies? + +/** + * Computes up the chains + */ +static void gen_chains( + unsigned char *out, + const unsigned char *in, + unsigned int start[SPX_WOTS_LEN], + const unsigned int steps[SPX_WOTS_LEN], + const spx_ctx *ctx, + uint32_t addr[8]) { + uint32_t i, j, k, idx, watching; + int done; + unsigned char empty[SPX_N]; + unsigned char *bufs[4]; + uint32_t addrs[8 * 2]; + + int l; + uint16_t counts[SPX_WOTS_W] = { 0 }; + uint16_t idxs[SPX_WOTS_LEN]; + uint16_t total, newTotal; + + /* set addrs = {addr, addr} */ + for (j = 0; j < 2; j++) { + memcpy(addrs + j * 8, addr, sizeof(uint32_t) * 8); + } + + /* Initialize out with the value at position 'start'. */ + memcpy(out, in, SPX_WOTS_LEN * SPX_N); + + /* Sort the chains in reverse order by steps using counting sort. */ + for (i = 0; i < SPX_WOTS_LEN; i++) { + counts[steps[i]]++; + } + total = 0; + for (l = SPX_WOTS_W - 1; l >= 0; l--) { + newTotal = counts[l] + total; + counts[l] = total; + total = newTotal; + } + for (i = 0; i < SPX_WOTS_LEN; i++) { + idxs[counts[steps[i]]] = i; + counts[steps[i]]++; + } + + /* We got our work cut out for us: do it! */ + for (i = 0; i < SPX_WOTS_LEN; i += 2) { + for (j = 0; j < 2 && i + j < SPX_WOTS_LEN; j++) { + idx = idxs[i + j]; + set_chain_addr(addrs + j * 8, idx); + bufs[j] = out + SPX_N * idx; + } + + /* As the chains are sorted in reverse order, we know that the first + * chain is the longest and the last one is the shortest. We keep + * an eye on whether the last chain is done and then on the one before, + * et cetera. */ + watching = 1; + done = 0; + while (i + watching >= SPX_WOTS_LEN) { + bufs[watching] = &empty[0]; + watching--; + } + + for (k = 0;; k++) { + while (k == steps[idxs[i + watching]]) { + bufs[watching] = &empty[0]; + if (watching == 0) { + done = 1; + break; + } + watching--; + } + if (done) { + break; + } + for (j = 0; j < watching + 1; j++) { + set_hash_addr(addrs + j * 8, k + start[idxs[i + j]]); + } + + thashx2(bufs[0], bufs[1], + bufs[0], bufs[1], 1, ctx, addrs); + } + } +} + +/** + * base_w algorithm as described in draft. + * Interprets an array of bytes as integers in base w. + * This only works when log_w is a divisor of 8. + */ +static void base_w(unsigned int *output, const int out_len, + const unsigned char *input) { + int in = 0; + int out = 0; + unsigned char total = 0; + int bits = 0; + int consumed; + + for (consumed = 0; consumed < out_len; consumed++) { + if (bits == 0) { + total = input[in]; + in++; + bits += 8; + } + bits -= SPX_WOTS_LOGW; + output[out] = (total >> bits) & (SPX_WOTS_W - 1); + out++; + } +} + +/* Computes the WOTS+ checksum over a message (in base_w). */ +static void wots_checksum(unsigned int *csum_base_w, + const unsigned int *msg_base_w) { + unsigned int csum = 0; + unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; + unsigned int i; + + /* Compute checksum. */ + for (i = 0; i < SPX_WOTS_LEN1; i++) { + csum += SPX_WOTS_W - 1 - msg_base_w[i]; + } + + /* Convert checksum to base_w. */ + /* Make sure expected empty zero bits are the least significant bits. */ + csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); + ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); + base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); +} + +/* Takes a message and derives the matching chain lengths. */ +void chain_lengths(unsigned int *lengths, const unsigned char *msg) { + base_w(lengths, SPX_WOTS_LEN1, msg); + wots_checksum(lengths + SPX_WOTS_LEN1, lengths); +} + +/** + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. + * + * Writes the computed public key to 'pk'. + */ +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]) { + unsigned int steps[SPX_WOTS_LEN]; + unsigned int start[SPX_WOTS_LEN]; + uint32_t i; + + chain_lengths(start, msg); + + for (i = 0; i < SPX_WOTS_LEN; i++) { + steps[i] = SPX_WOTS_W - 1 - start[i]; + } + + gen_chains(pk, sig, start, steps, ctx, addr); +} + +/* + * This generates 2 sequential WOTS public keys + * It also generates the WOTS signature if leaf_info indicates + * that we're signing with one of these WOTS keys + */ +void wots_gen_leafx2(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info) { + struct leaf_info_x2 *info = v_info; + uint32_t *leaf_addr = info->leaf_addr; + uint32_t *pk_addr = info->pk_addr; + unsigned int i, j, k; + unsigned char pk_buffer[ 2 * SPX_WOTS_BYTES ]; + unsigned wots_offset = SPX_WOTS_BYTES; + unsigned char *buffer; + uint32_t wots_k_mask; + unsigned wots_sign_index; + + if (((leaf_idx ^ info->wots_sign_leaf) & ~1) == 0) { + /* We're traversing the leaf that's signing; generate the WOTS */ + /* signature */ + wots_k_mask = 0; + wots_sign_index = info->wots_sign_leaf & 1; /* Which of of the 2 */ + /* slots do the signatures come from */ + } else { + /* Nope, we're just generating pk's; turn off the signature logic */ + wots_k_mask = ~0; + wots_sign_index = 0; + } + + for (j = 0; j < 2; j++) { + set_keypair_addr( leaf_addr + j * 8, leaf_idx + j ); + set_keypair_addr( pk_addr + j * 8, leaf_idx + j ); + } + + for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { + uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k to */ + /* the step if we're generating a signature, ~0 if we're not */ + + /* Start with the secret seed */ + for (j = 0; j < 2; j++) { + set_chain_addr(leaf_addr + j * 8, i); + set_hash_addr(leaf_addr + j * 8, 0); + set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTSPRF); + } + prf_addrx2(buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + ctx, leaf_addr); + for (j = 0; j < 2; j++) { + set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTS); + } + + /* Iterate down the WOTS chain */ + for (k = 0;; k++) { + /* Check if one of the values we have needs to be saved as a */ + /* part of the WOTS signature */ + if (k == wots_k) { + memcpy( info->wots_sig + i * SPX_N, + buffer + wots_sign_index * wots_offset, SPX_N ); + } + + /* Check if we hit the top of the chain */ + if (k == SPX_WOTS_W - 1) { + break; + } + + /* Iterate one step on all 4 chains */ + for (j = 0; j < 2; j++) { + set_hash_addr(leaf_addr + j * 8, k); + } + thashx2(buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + 1, ctx, leaf_addr); + } + } + + /* Do the final thash to generate the public keys */ + thashx2(dest + 0 * SPX_N, + dest + 1 * SPX_N, + pk_buffer + 0 * wots_offset, + pk_buffer + 1 * wots_offset, + SPX_WOTS_LEN, ctx, pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/wots.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/wots.h new file mode 100644 index 0000000000..4e7692eeef --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/wots.h @@ -0,0 +1,25 @@ +#ifndef SPX_WOTS_H +#define SPX_WOTS_H + +#include + +#include "context.h" +#include "params.h" + +/** + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. + * + * Writes the computed public key to 'pk'. + */ +#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]); + +/* + * Compute the chain lengths needed for a given message hash + */ +#define chain_lengths SPX_NAMESPACE(chain_lengths) +void chain_lengths(unsigned int *lengths, const unsigned char *msg); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/wotsx2.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/wotsx2.h new file mode 100644 index 0000000000..b58bb61f84 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/wotsx2.h @@ -0,0 +1,40 @@ +#ifndef WOTSX2_H_ +#define WOTSX2_H_ + +#include "params.h" +#include + +/* + * This is here to provide an interface to the internal wots_gen_leafx2 + * routine. While this routine is not referenced in the package outside of + * wots.c, it is called from the stand-alone benchmark code to characterize + * the performance + */ +struct leaf_info_x2 { + unsigned char *wots_sig; + uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ + uint32_t *wots_steps; + uint32_t leaf_addr[2 * 8]; + uint32_t pk_addr[2 * 8]; +}; + +/* Macro to set the leaf_info to something 'benign', that is, it would */ +/* run with the same time as it does during the real signing process */ +/* Used only by the benchmark code */ +#define INITIALIZE_LEAF_INFO_X2(info, addr, step_buffer) { \ + (info).wots_sig = 0; \ + (info).wots_sign_leaf = ~0; \ + (info).wots_steps = step_buffer; \ + int i; \ + for (i=0; i<2; i++) { \ + memcpy( &(info).leaf_addr[8*i], addr, 32 ); \ + memcpy( &(info).pk_addr[8*i], addr, 32 ); \ + } \ + } + +#define wots_gen_leafx2 SPX_NAMESPACE(wots_gen_leafx2) +void wots_gen_leafx2(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info); + +#endif /* WOTSX2_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/LICENSE b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/LICENSE new file mode 100644 index 0000000000..670154e353 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/LICENSE @@ -0,0 +1,116 @@ +CC0 1.0 Universal + +Statement of Purpose + +The laws of most jurisdictions throughout the world automatically confer +exclusive Copyright and Related Rights (defined below) upon the creator and +subsequent owner(s) (each and all, an "owner") of an original work of +authorship and/or a database (each, a "Work"). + +Certain owners wish to permanently relinquish those rights to a Work for the +purpose of contributing to a commons of creative, cultural and scientific +works ("Commons") that the public can reliably and without fear of later +claims of infringement build upon, modify, incorporate in other works, reuse +and redistribute as freely as possible in any form whatsoever and for any +purposes, including without limitation commercial purposes. These owners may +contribute to the Commons to promote the ideal of a free culture and the +further production of creative, cultural and scientific works, or to gain +reputation or greater distribution for their Work in part through the use and +efforts of others. + +For these and/or other purposes and motivations, and without any expectation +of additional consideration or compensation, the person associating CC0 with a +Work (the "Affirmer"), to the extent that he or she is an owner of Copyright +and Related Rights in the Work, voluntarily elects to apply CC0 to the Work +and publicly distribute the Work under its terms, with knowledge of his or her +Copyright and Related Rights in the Work and the meaning and intended legal +effect of CC0 on those rights. + +1. Copyright and Related Rights. A Work made available under CC0 may be +protected by copyright and related or neighboring rights ("Copyright and +Related Rights"). Copyright and Related Rights include, but are not limited +to, the following: + + i. the right to reproduce, adapt, distribute, perform, display, communicate, + and translate a Work; + + ii. moral rights retained by the original author(s) and/or performer(s); + + iii. publicity and privacy rights pertaining to a person's image or likeness + depicted in a Work; + + iv. rights protecting against unfair competition in regards to a Work, + subject to the limitations in paragraph 4(a), below; + + v. rights protecting the extraction, dissemination, use and reuse of data in + a Work; + + vi. database rights (such as those arising under Directive 96/9/EC of the + European Parliament and of the Council of 11 March 1996 on the legal + protection of databases, and under any national implementation thereof, + including any amended or successor version of such directive); and + + vii. other similar, equivalent or corresponding rights throughout the world + based on applicable law or treaty, and any national implementations thereof. + +2. Waiver. To the greatest extent permitted by, but not in contravention of, +applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and +unconditionally waives, abandons, and surrenders all of Affirmer's Copyright +and Related Rights and associated claims and causes of action, whether now +known or unknown (including existing as well as future claims and causes of +action), in the Work (i) in all territories worldwide, (ii) for the maximum +duration provided by applicable law or treaty (including future time +extensions), (iii) in any current or future medium and for any number of +copies, and (iv) for any purpose whatsoever, including without limitation +commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes +the Waiver for the benefit of each member of the public at large and to the +detriment of Affirmer's heirs and successors, fully intending that such Waiver +shall not be subject to revocation, rescission, cancellation, termination, or +any other legal or equitable action to disrupt the quiet enjoyment of the Work +by the public as contemplated by Affirmer's express Statement of Purpose. + +3. Public License Fallback. Should any part of the Waiver for any reason be +judged legally invalid or ineffective under applicable law, then the Waiver +shall be preserved to the maximum extent permitted taking into account +Affirmer's express Statement of Purpose. In addition, to the extent the Waiver +is so judged Affirmer hereby grants to each affected person a royalty-free, +non transferable, non sublicensable, non exclusive, irrevocable and +unconditional license to exercise Affirmer's Copyright and Related Rights in +the Work (i) in all territories worldwide, (ii) for the maximum duration +provided by applicable law or treaty (including future time extensions), (iii) +in any current or future medium and for any number of copies, and (iv) for any +purpose whatsoever, including without limitation commercial, advertising or +promotional purposes (the "License"). The License shall be deemed effective as +of the date CC0 was applied by Affirmer to the Work. Should any part of the +License for any reason be judged legally invalid or ineffective under +applicable law, such partial invalidity or ineffectiveness shall not +invalidate the remainder of the License, and in such case Affirmer hereby +affirms that he or she will not (i) exercise any of his or her remaining +Copyright and Related Rights in the Work or (ii) assert any associated claims +and causes of action with respect to the Work, in either case contrary to +Affirmer's express Statement of Purpose. + +4. Limitations and Disclaimers. + + a. No trademark or patent rights held by Affirmer are waived, abandoned, + surrendered, licensed or otherwise affected by this document. + + b. Affirmer offers the Work as-is and makes no representations or warranties + of any kind concerning the Work, express, implied, statutory or otherwise, + including without limitation warranties of title, merchantability, fitness + for a particular purpose, non infringement, or the absence of latent or + other defects, accuracy, or the present or absence of errors, whether or not + discoverable, all to the greatest extent permissible under applicable law. + + c. Affirmer disclaims responsibility for clearing rights of other persons + that may apply to the Work or any use thereof, including without limitation + any person's Copyright and Related Rights in the Work. Further, Affirmer + disclaims responsibility for obtaining any necessary consents, permissions + or other rights required for any use of the Work. + + d. Affirmer understands and acknowledges that Creative Commons is not a + party to this document and has no duty or obligation with respect to this + CC0 or use of the Work. + +For more information, please see + diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/address.c b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/address.c new file mode 100644 index 0000000000..b956e9cb29 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/address.c @@ -0,0 +1,91 @@ +#include +#include + +#include "address.h" +#include "params.h" +#include "utils.h" + +/* + * Specify which level of Merkle tree (the "layer") we're working on + */ +void set_layer_addr(uint32_t addr[8], uint32_t layer) { + ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; +} + +/* + * Specify which Merkle tree within the level (the "tree address") we're working on + */ +void set_tree_addr(uint32_t addr[8], uint64_t tree) { + ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); +} + +/* + * Specify the reason we'll use this address structure for, that is, what + * hash will we compute with it. This is used so that unrelated types of + * hashes don't accidentally get the same address structure. The type will be + * one of the SPX_ADDR_TYPE constants + */ +void set_type(uint32_t addr[8], uint32_t type) { + ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; +} + +/* + * Copy the layer and tree fields of the address structure. This is used + * when we're doing multiple types of hashes within the same Merkle tree + */ +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); +} + +/* These functions are used for OTS addresses. */ + +/* + * Specify which Merkle leaf we're working on; that is, which OTS keypair + * we're talking about. + */ +void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { + ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; +} + +/* + * Copy the layer, tree and keypair fields of the address structure. This is + * used when we're doing multiple things within the same OTS keypair + */ +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); + ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; +} + +/* + * Specify which Merkle chain within the OTS we're working with + * (the chain address) + */ +void set_chain_addr(uint32_t addr[8], uint32_t chain) { + ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; +} + +/* + * Specify where in the Merkle chain we are +* (the hash address) + */ +void set_hash_addr(uint32_t addr[8], uint32_t hash) { + ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; +} + +/* These functions are used for all hash tree addresses (including FORS). */ + +/* + * Specify the height of the node in the Merkle/FORS tree we are in + * (the tree height) + */ +void set_tree_height(uint32_t addr[8], uint32_t tree_height) { + ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; +} + +/* + * Specify the distance from the left edge of the node in the Merkle/FORS tree + * (the tree index) + */ +void set_tree_index(uint32_t addr[8], uint32_t tree_index) { + u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/address.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/address.h new file mode 100644 index 0000000000..24a84eb40c --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/address.h @@ -0,0 +1,52 @@ +#ifndef SPX_ADDRESS_H +#define SPX_ADDRESS_H + +#include + +#include "params.h" + +/* The hash types that are passed to set_type */ +#define SPX_ADDR_TYPE_WOTS 0 +#define SPX_ADDR_TYPE_WOTSPK 1 +#define SPX_ADDR_TYPE_HASHTREE 2 +#define SPX_ADDR_TYPE_FORSTREE 3 +#define SPX_ADDR_TYPE_FORSPK 4 +#define SPX_ADDR_TYPE_WOTSPRF 5 +#define SPX_ADDR_TYPE_FORSPRF 6 + +#define set_layer_addr SPX_NAMESPACE(set_layer_addr) +void set_layer_addr(uint32_t addr[8], uint32_t layer); + +#define set_tree_addr SPX_NAMESPACE(set_tree_addr) +void set_tree_addr(uint32_t addr[8], uint64_t tree); + +#define set_type SPX_NAMESPACE(set_type) +void set_type(uint32_t addr[8], uint32_t type); + +/* Copies the layer and tree part of one address into the other */ +#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); + +/* These functions are used for WOTS and FORS addresses. */ + +#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) +void set_keypair_addr(uint32_t addr[8], uint32_t keypair); + +#define set_chain_addr SPX_NAMESPACE(set_chain_addr) +void set_chain_addr(uint32_t addr[8], uint32_t chain); + +#define set_hash_addr SPX_NAMESPACE(set_hash_addr) +void set_hash_addr(uint32_t addr[8], uint32_t hash); + +#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); + +/* These functions are used for all hash tree addresses (including FORS). */ + +#define set_tree_height SPX_NAMESPACE(set_tree_height) +void set_tree_height(uint32_t addr[8], uint32_t tree_height); + +#define set_tree_index SPX_NAMESPACE(set_tree_index) +void set_tree_index(uint32_t addr[8], uint32_t tree_index); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/api.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/api.h new file mode 100644 index 0000000000..af0477315e --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/api.h @@ -0,0 +1,77 @@ +#ifndef PQCLEAN_SPHINCSSHAKE192FROBUST_AVX2_API_H +#define PQCLEAN_SPHINCSSHAKE192FROBUST_AVX2_API_H + +#include +#include + +#define PQCLEAN_SPHINCSSHAKE192FROBUST_AVX2_CRYPTO_ALGNAME "SPHINCS+-shake-192f-robust" + +#define PQCLEAN_SPHINCSSHAKE192FROBUST_AVX2_CRYPTO_SECRETKEYBYTES 96 +#define PQCLEAN_SPHINCSSHAKE192FROBUST_AVX2_CRYPTO_PUBLICKEYBYTES 48 +#define PQCLEAN_SPHINCSSHAKE192FROBUST_AVX2_CRYPTO_BYTES 35664 + +#define PQCLEAN_SPHINCSSHAKE192FROBUST_AVX2_CRYPTO_SEEDBYTES 72 + +/* + * Returns the length of a secret key, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE192FROBUST_AVX2_crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE192FROBUST_AVX2_crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE192FROBUST_AVX2_crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE192FROBUST_AVX2_crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +int PQCLEAN_SPHINCSSHAKE192FROBUST_AVX2_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +int PQCLEAN_SPHINCSSHAKE192FROBUST_AVX2_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +int PQCLEAN_SPHINCSSHAKE192FROBUST_AVX2_crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +int PQCLEAN_SPHINCSSHAKE192FROBUST_AVX2_crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, + const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +int PQCLEAN_SPHINCSSHAKE192FROBUST_AVX2_crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +int PQCLEAN_SPHINCSSHAKE192FROBUST_AVX2_crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/context.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/context.h new file mode 100644 index 0000000000..6e0a33f3b7 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/context.h @@ -0,0 +1,19 @@ +#ifndef SPX_CONTEXT_H +#define SPX_CONTEXT_H + +#include + +#include "params.h" + +typedef struct { + uint8_t pub_seed[SPX_N]; + uint8_t sk_seed[SPX_N]; +} spx_ctx; + +#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) +void initialize_hash_function(spx_ctx *ctx); + +#define free_hash_function SPX_NAMESPACE(free_hash_function) +void free_hash_function(spx_ctx *ctx); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/context_shake.c b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/context_shake.c new file mode 100644 index 0000000000..9614a103d3 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/context_shake.c @@ -0,0 +1,12 @@ +#include "context.h" + +/* For SHAKE256, there is no immediate reason to initialize at the start, + so this function is an empty operation. */ +void initialize_hash_function(spx_ctx *ctx) { + (void)ctx; /* Suppress an 'unused parameter' warning. */ +} + +// in case the hash function api is heap-based. +void free_hash_function(spx_ctx *ctx) { + (void)ctx; +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/fips202x4.c b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/fips202x4.c new file mode 100644 index 0000000000..1e06fef186 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/fips202x4.c @@ -0,0 +1,210 @@ +#include +#include +#include + +#include "fips202.h" +#include "fips202x4.h" + +#define NROUNDS 24 +#define ROL(a, offset) (((a) << (offset)) ^ ((a) >> (64-(offset)))) + +static uint64_t load64(const unsigned char *x) { + unsigned long long r = 0, i; + + for (i = 0; i < 8; ++i) { + r |= (unsigned long long)x[i] << 8 * i; + } + return r; +} + +static void store64(uint8_t *x, uint64_t u) { + unsigned int i; + + for (i = 0; i < 8; ++i) { + x[i] = (uint8_t)u; + u >>= 8; + } +} + +/* Use implementation from the Keccak Code Package */ +extern void KeccakP1600times4_PermuteAll_24rounds(__m256i *s); +#define KeccakF1600_StatePermute4x KeccakP1600times4_PermuteAll_24rounds + +static void keccak_absorb4x(__m256i *s, + unsigned int r, + const unsigned char *m0, + const unsigned char *m1, + const unsigned char *m2, + const unsigned char *m3, + unsigned long long int mlen, + unsigned char p) { + unsigned long long i; + unsigned char t0[200]; + unsigned char t1[200]; + unsigned char t2[200]; + unsigned char t3[200]; + + unsigned long long *ss = (unsigned long long *)s; + + + while (mlen >= r) { + for (i = 0; i < r / 8; ++i) { + ss[4 * i + 0] ^= load64(m0 + 8 * i); + ss[4 * i + 1] ^= load64(m1 + 8 * i); + ss[4 * i + 2] ^= load64(m2 + 8 * i); + ss[4 * i + 3] ^= load64(m3 + 8 * i); + } + + KeccakF1600_StatePermute4x(s); + mlen -= r; + m0 += r; + m1 += r; + m2 += r; + m3 += r; + } + + for (i = 0; i < r; ++i) { + t0[i] = 0; + t1[i] = 0; + t2[i] = 0; + t3[i] = 0; + } + for (i = 0; i < mlen; ++i) { + t0[i] = m0[i]; + t1[i] = m1[i]; + t2[i] = m2[i]; + t3[i] = m3[i]; + } + + t0[i] = p; + t1[i] = p; + t2[i] = p; + t3[i] = p; + + t0[r - 1] |= 128; + t1[r - 1] |= 128; + t2[r - 1] |= 128; + t3[r - 1] |= 128; + + for (i = 0; i < r / 8; ++i) { + ss[4 * i + 0] ^= load64(t0 + 8 * i); + ss[4 * i + 1] ^= load64(t1 + 8 * i); + ss[4 * i + 2] ^= load64(t2 + 8 * i); + ss[4 * i + 3] ^= load64(t3 + 8 * i); + } +} + + +static void keccak_squeezeblocks4x(unsigned char *h0, + unsigned char *h1, + unsigned char *h2, + unsigned char *h3, + unsigned long long int nblocks, + __m256i *s, + unsigned int r) { + unsigned int i; + + unsigned long long *ss = (unsigned long long *)s; + + while (nblocks > 0) { + KeccakF1600_StatePermute4x(s); + for (i = 0; i < (r >> 3); i++) { + store64(h0 + 8 * i, ss[4 * i + 0]); + store64(h1 + 8 * i, ss[4 * i + 1]); + store64(h2 + 8 * i, ss[4 * i + 2]); + store64(h3 + 8 * i, ss[4 * i + 3]); + } + h0 += r; + h1 += r; + h2 += r; + h3 += r; + nblocks--; + } +} + + + +void shake128x4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, unsigned long long outlen, + unsigned char *in0, + unsigned char *in1, + unsigned char *in2, + unsigned char *in3, unsigned long long inlen) { + __m256i s[25]; + unsigned char t0[SHAKE128_RATE]; + unsigned char t1[SHAKE128_RATE]; + unsigned char t2[SHAKE128_RATE]; + unsigned char t3[SHAKE128_RATE]; + unsigned int i; + + /* zero state */ + for (i = 0; i < 25; i++) { + s[i] = _mm256_xor_si256(s[i], s[i]); + } + + /* absorb 4 message of identical length in parallel */ + keccak_absorb4x(s, SHAKE128_RATE, in0, in1, in2, in3, inlen, 0x1F); + + /* Squeeze output */ + keccak_squeezeblocks4x(out0, out1, out2, out3, outlen / SHAKE128_RATE, s, SHAKE128_RATE); + + out0 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; + out1 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; + out2 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; + out3 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; + + if (outlen % SHAKE128_RATE) { + keccak_squeezeblocks4x(t0, t1, t2, t3, 1, s, SHAKE128_RATE); + for (i = 0; i < outlen % SHAKE128_RATE; i++) { + out0[i] = t0[i]; + out1[i] = t1[i]; + out2[i] = t2[i]; + out3[i] = t3[i]; + } + } +} + + +void shake256x4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, unsigned long long outlen, + unsigned char *in0, + unsigned char *in1, + unsigned char *in2, + unsigned char *in3, unsigned long long inlen) { + __m256i s[25]; + unsigned char t0[SHAKE256_RATE]; + unsigned char t1[SHAKE256_RATE]; + unsigned char t2[SHAKE256_RATE]; + unsigned char t3[SHAKE256_RATE]; + unsigned int i; + + /* zero state */ + for (i = 0; i < 25; i++) { + s[i] = _mm256_xor_si256(s[i], s[i]); + } + + /* absorb 4 message of identical length in parallel */ + keccak_absorb4x(s, SHAKE256_RATE, in0, in1, in2, in3, inlen, 0x1F); + + /* Squeeze output */ + keccak_squeezeblocks4x(out0, out1, out2, out3, outlen / SHAKE256_RATE, s, SHAKE256_RATE); + + out0 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; + out1 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; + out2 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; + out3 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; + + if (outlen % SHAKE256_RATE) { + keccak_squeezeblocks4x(t0, t1, t2, t3, 1, s, SHAKE256_RATE); + for (i = 0; i < outlen % SHAKE256_RATE; i++) { + out0[i] = t0[i]; + out1[i] = t1[i]; + out2[i] = t2[i]; + out3[i] = t3[i]; + } + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/fips202x4.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/fips202x4.h new file mode 100644 index 0000000000..2b93c9cd0d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/fips202x4.h @@ -0,0 +1,28 @@ +#ifndef SPX_FIPS202X4_H +#define SPX_FIPS202X4_H + +#include + +#include "params.h" + +#define shake128x4 SPX_NAMESPACE(shake128x4) +void shake128x4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, unsigned long long outlen, + unsigned char *in0, + unsigned char *in1, + unsigned char *in2, + unsigned char *in3, unsigned long long inlen); + +#define shake256x4 SPX_NAMESPACE(shake256x4) +void shake256x4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, unsigned long long outlen, + unsigned char *in0, + unsigned char *in1, + unsigned char *in2, + unsigned char *in3, unsigned long long inlen); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/fors.c b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/fors.c new file mode 100644 index 0000000000..f1b0639cfc --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/fors.c @@ -0,0 +1,202 @@ +#include +#include +#include + +#include "fors.h" + +#include "address.h" +#include "hash.h" +#include "hashx4.h" +#include "thash.h" +#include "thashx4.h" +#include "utils.h" +#include "utilsx4.h" + +static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + prf_addr(sk, ctx, fors_leaf_addr); +} + +static void fors_gen_skx4(unsigned char *sk0, + unsigned char *sk1, + unsigned char *sk2, + unsigned char *sk3, const spx_ctx *ctx, + uint32_t fors_leaf_addrx4[4 * 8]) { + prf_addrx4(sk0, sk1, sk2, sk3, + ctx, fors_leaf_addrx4); +} + +static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, + const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + thash(leaf, sk, 1, ctx, fors_leaf_addr); +} + +static void fors_sk_to_leafx4(unsigned char *leaf0, + unsigned char *leaf1, + unsigned char *leaf2, + unsigned char *leaf3, + const unsigned char *sk0, + const unsigned char *sk1, + const unsigned char *sk2, + const unsigned char *sk3, + const spx_ctx *ctx, + uint32_t fors_leaf_addrx4[4 * 8]) { + thashx4(leaf0, leaf1, leaf2, leaf3, + sk0, sk1, sk2, sk3, + 1, ctx, fors_leaf_addrx4); +} + +struct fors_gen_leaf_info { + uint32_t leaf_addrx[4 * 8]; +}; + +static void fors_gen_leafx4(unsigned char *leaf, + const spx_ctx *ctx, + uint32_t addr_idx, void *info) { + struct fors_gen_leaf_info *fors_info = info; + uint32_t *fors_leaf_addrx4 = fors_info->leaf_addrx; + unsigned int j; + + /* Only set the parts that the caller doesn't set */ + for (j = 0; j < 4; j++) { + set_tree_index(fors_leaf_addrx4 + j * 8, addr_idx + j); + set_type(fors_leaf_addrx4 + j * 8, SPX_ADDR_TYPE_FORSPRF); + } + + fors_gen_skx4(leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + leaf + 2 * SPX_N, + leaf + 3 * SPX_N, + ctx, fors_leaf_addrx4); + + for (j = 0; j < 4; j++) { + set_type(fors_leaf_addrx4 + j * 8, SPX_ADDR_TYPE_FORSTREE); + } + + fors_sk_to_leafx4(leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + leaf + 2 * SPX_N, + leaf + 3 * SPX_N, + leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + leaf + 2 * SPX_N, + leaf + 3 * SPX_N, + ctx, fors_leaf_addrx4); +} + +/** + * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + * Assumes indices has space for SPX_FORS_TREES integers. + */ +static void message_to_indices(uint32_t *indices, const unsigned char *m) { + unsigned int i, j; + unsigned int offset = 0; + + for (i = 0; i < SPX_FORS_TREES; i++) { + indices[i] = 0; + for (j = 0; j < SPX_FORS_HEIGHT; j++) { + indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); + offset++; + } + } +} + +/** + * Signs a message m, deriving the secret key from sk_seed and the FTS address. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + uint32_t fors_tree_addr[4 * 8] = {0}; + struct fors_gen_leaf_info fors_info = {0}; + uint32_t *fors_leaf_addr = fors_info.leaf_addrx; + uint32_t fors_pk_addr[8] = {0}; + uint32_t idx_offset; + unsigned int i; + + for (i = 0; i < 4; i++) { + copy_keypair_addr(fors_tree_addr + 8 * i, fors_addr); + set_type(fors_tree_addr + 8 * i, SPX_ADDR_TYPE_FORSTREE); + copy_keypair_addr(fors_leaf_addr + 8 * i, fors_addr); + } + copy_keypair_addr(fors_pk_addr, fors_addr); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); + + message_to_indices(indices, m); + + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); + + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + + /* Include the secret key part that produces the selected leaf node. */ + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); + fors_gen_sk(sig, ctx, fors_tree_addr); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + sig += SPX_N; + + /* Compute the authentication path for this leaf node. */ + treehashx4(roots + i * SPX_N, sig, ctx, + indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx4, + fors_tree_addr, &fors_info); + + sig += SPX_N * SPX_FORS_HEIGHT; + } + + /* Hash horizontally across all tree roots to derive the public key. */ + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); +} + +/** + * Derives the FORS public key from a signature. + * This can be used for verification by comparing to a known public key, or to + * subsequently verify a signature on the derived public key. The latter is the + * typical use-case when used as an FTS below an OTS in a hypertree. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + unsigned char leaf[SPX_N]; + uint32_t fors_tree_addr[8] = {0}; + uint32_t fors_pk_addr[8] = {0}; + uint32_t idx_offset; + unsigned int i; + + copy_keypair_addr(fors_tree_addr, fors_addr); + copy_keypair_addr(fors_pk_addr, fors_addr); + + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); + + message_to_indices(indices, m); + + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); + + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + + /* Derive the leaf from the included secret key part. */ + fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); + sig += SPX_N; + + /* Derive the corresponding root node of this tree. */ + compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, + sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); + sig += SPX_N * SPX_FORS_HEIGHT; + } + + /* Hash horizontally across all tree roots to derive the public key. */ + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/fors.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/fors.h new file mode 100644 index 0000000000..509140a178 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/fors.h @@ -0,0 +1,32 @@ +#ifndef SPX_FORS_H +#define SPX_FORS_H + +#include + +#include "context.h" +#include "params.h" + +/** + * Signs a message m, deriving the secret key from sk_seed and the FTS address. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +#define fors_sign SPX_NAMESPACE(fors_sign) +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); + +/** + * Derives the FORS public key from a signature. + * This can be used for verification by comparing to a known public key, or to + * subsequently verify a signature on the derived public key. The latter is the + * typical use-case when used as an FTS below an OTS in a hypertree. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/hash.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/hash.h new file mode 100644 index 0000000000..f7c87d4c3c --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/hash.h @@ -0,0 +1,28 @@ +#ifndef SPX_HASH_H +#define SPX_HASH_H + +#include +#include + +#include "context.h" +#include "params.h" + +#define prf_addr SPX_NAMESPACE(prf_addr) +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]); + +#define gen_message_random SPX_NAMESPACE(gen_message_random) +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); + +#define hash_message SPX_NAMESPACE(hash_message) +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); + + + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/hash_shake.c b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/hash_shake.c new file mode 100644 index 0000000000..ff5e7ec918 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/hash_shake.c @@ -0,0 +1,83 @@ +#include +#include + +#include "hash.h" + +#include "address.h" +#include "fips202.h" +#include "params.h" +#include "utils.h" + +/* + * Computes PRF(pk_seed, sk_seed, addr) + */ +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]) { + unsigned char buf[2 * SPX_N + SPX_ADDR_BYTES]; + + memcpy(buf, ctx->pub_seed, SPX_N); + memcpy(buf + SPX_N, addr, SPX_ADDR_BYTES); + memcpy(buf + SPX_N + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); + + shake256(out, SPX_N, buf, 2 * SPX_N + SPX_ADDR_BYTES); +} + +/** + * Computes the message-dependent randomness R, using a secret seed and an + * optional randomization value as well as the message. + */ +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { + (void)ctx; + shake256incctx s_inc; + + shake256_inc_init(&s_inc); + shake256_inc_absorb(&s_inc, sk_prf, SPX_N); + shake256_inc_absorb(&s_inc, optrand, SPX_N); + shake256_inc_absorb(&s_inc, m, mlen); + shake256_inc_finalize(&s_inc); + shake256_inc_squeeze(R, SPX_N, &s_inc); + shake256_inc_ctx_release(&s_inc); +} + +/** + * Computes the message hash using R, the public key, and the message. + * Outputs the message digest and the index of the leaf. The index is split in + * the tree index and the leaf index, for convenient copying to an address. + */ +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { + (void)ctx; +#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) +#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) +#define SPX_LEAF_BITS SPX_TREE_HEIGHT +#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) +#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) + + unsigned char buf[SPX_DGST_BYTES]; + unsigned char *bufp = buf; + shake256incctx s_inc; + + shake256_inc_init(&s_inc); + shake256_inc_absorb(&s_inc, R, SPX_N); + shake256_inc_absorb(&s_inc, pk, SPX_PK_BYTES); + shake256_inc_absorb(&s_inc, m, mlen); + shake256_inc_finalize(&s_inc); + shake256_inc_squeeze(buf, SPX_DGST_BYTES, &s_inc); + shake256_inc_ctx_release(&s_inc); + + memcpy(digest, bufp, SPX_FORS_MSG_BYTES); + bufp += SPX_FORS_MSG_BYTES; + + + *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); + *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); + bufp += SPX_TREE_BYTES; + + *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); + *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/hash_shakex4.c b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/hash_shakex4.c new file mode 100644 index 0000000000..bbd22eb117 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/hash_shakex4.c @@ -0,0 +1,64 @@ +#include +#include + +#include "hashx4.h" + +#include "address.h" +#include "fips202x4.h" +#include "params.h" + +extern void KeccakP1600times4_PermuteAll_24rounds(__m256i *s); + +/* + * 4-way parallel version of prf_addr; takes 4x as much input and output + */ +void prf_addrx4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const spx_ctx *ctx, + const uint32_t addrx4[4 * 8]) { + /* As we write and read only a few quadwords, it is more efficient to + * build and extract from the fourway SHAKE256 state by hand. */ + __m256i state[25]; + + for (int i = 0; i < SPX_N / 8; i++) { + state[i] = _mm256_set1_epi64x(((int64_t *)ctx->pub_seed)[i]); + } + for (int i = 0; i < 4; i++) { + state[SPX_N / 8 + i] = _mm256_set_epi32( + (int)addrx4[3 * 8 + 1 + 2 * i], + (int)addrx4[3 * 8 + 2 * i], + (int)addrx4[2 * 8 + 1 + 2 * i], + (int)addrx4[2 * 8 + 2 * i], + (int)addrx4[8 + 1 + 2 * i], + (int)addrx4[8 + 2 * i], + (int)addrx4[1 + 2 * i], + (int)addrx4[2 * i] + ); + } + for (int i = 0; i < SPX_N / 8; i++) { + state[SPX_N / 8 + i + 4] = _mm256_set1_epi64x(((int64_t *)ctx->sk_seed)[i]); + } + + /* SHAKE domain separator and padding. */ + state[SPX_N / 4 + 4] = _mm256_set1_epi64x(0x1f); + for (int i = SPX_N / 4 + 5; i < 16; i++) { + state[i] = _mm256_set1_epi64x(0); + } + // shift unsigned and then cast to avoid UB + state[16] = _mm256_set1_epi64x((long long)(0x80ULL << 56)); + + for (int i = 17; i < 25; i++) { + state[i] = _mm256_set1_epi64x(0); + } + + KeccakP1600times4_PermuteAll_24rounds(&state[0]); + + for (int i = 0; i < SPX_N / 8; i++) { + ((int64_t *)out0)[i] = _mm256_extract_epi64(state[i], 0); + ((int64_t *)out1)[i] = _mm256_extract_epi64(state[i], 1); + ((int64_t *)out2)[i] = _mm256_extract_epi64(state[i], 2); + ((int64_t *)out3)[i] = _mm256_extract_epi64(state[i], 3); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/hashx4.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/hashx4.h new file mode 100644 index 0000000000..3751a0ebd0 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/hashx4.h @@ -0,0 +1,17 @@ +#ifndef SPX_HASHX4_H +#define SPX_HASHX4_H + +#include + +#include "context.h" +#include "params.h" + +#define prf_addrx4 SPX_NAMESPACE(prf_addrx4) +void prf_addrx4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const spx_ctx *ctx, + const uint32_t addrx4[4 * 8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/merkle.c b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/merkle.c new file mode 100644 index 0000000000..f57811c1ac --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/merkle.c @@ -0,0 +1,64 @@ +#include +#include + +#include "merkle.h" + +#include "address.h" +#include "params.h" +#include "utils.h" +#include "utilsx4.h" +#include "wots.h" +#include "wotsx4.h" + +/* + * This generates a Merkle signature (WOTS signature followed by the Merkle + * authentication path). + */ +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf) { + unsigned char *auth_path = sig + SPX_WOTS_BYTES; + uint32_t tree_addrx4[4 * 8] = { 0 }; + int j; + struct leaf_info_x4 info = { 0 }; + unsigned steps[ SPX_WOTS_LEN ]; + + info.wots_sig = sig; + chain_lengths(steps, root); + info.wots_steps = steps; + + for (j = 0; j < 4; j++) { + set_type(&tree_addrx4[8 * j], SPX_ADDR_TYPE_HASHTREE); + set_type(&info.leaf_addr[8 * j], SPX_ADDR_TYPE_WOTS); + set_type(&info.pk_addr[8 * j], SPX_ADDR_TYPE_WOTSPK); + copy_subtree_addr(&tree_addrx4[8 * j], tree_addr); + copy_subtree_addr(&info.leaf_addr[8 * j], wots_addr); + copy_subtree_addr(&info.pk_addr[8 * j], wots_addr); + } + + info.wots_sign_leaf = idx_leaf; + + treehashx4(root, auth_path, ctx, + idx_leaf, 0, + SPX_TREE_HEIGHT, + wots_gen_leafx4, + tree_addrx4, &info); +} + +/* Compute root node of the top-most subtree. */ +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { + /* We do not need the auth path in key generation, but it simplifies the + code to have just one treehash routine that computes both root and path + in one function. */ + unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; + uint32_t top_tree_addr[8] = {0}; + uint32_t wots_addr[8] = {0}; + + set_layer_addr(top_tree_addr, SPX_D - 1); + set_layer_addr(wots_addr, SPX_D - 1); + + merkle_sign(auth_path, root, ctx, + wots_addr, top_tree_addr, + ~0U /* ~0 means "don't bother generating an auth path */ ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/merkle.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/merkle.h new file mode 100644 index 0000000000..769cf2e970 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/merkle.h @@ -0,0 +1,21 @@ +#ifndef MERKLE_H_ +#define MERKLE_H_ + +#include + +#include "context.h" +#include "params.h" + +/* Generate a Merkle signature (WOTS signature followed by the Merkle */ +/* authentication path) */ +#define merkle_sign SPX_NAMESPACE(merkle_sign) +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf); + +/* Compute the root node of the top-most subtree. */ +#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); + +#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/nistapi.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/nistapi.h new file mode 100644 index 0000000000..3cb71afad4 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/nistapi.h @@ -0,0 +1,87 @@ +#ifndef SPX_API_H +#define SPX_API_H + +#include +#include + +#include "params.h" + +#define CRYPTO_ALGNAME "SPHINCS+" + +#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES +#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES +#define CRYPTO_BYTES SPX_BYTES +#define CRYPTO_SEEDBYTES (3*SPX_N) + +/* + * Returns the length of a secret key, in bytes + */ +#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) +size_t crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) +size_t crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) +size_t crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) +size_t crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +#define crypto_sign SPX_NAMESPACE(crypto_sign) +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/params.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/params.h new file mode 100644 index 0000000000..e76c9ad6ad --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/params.h @@ -0,0 +1,56 @@ +#ifndef SPX_PARAMS_H +#define SPX_PARAMS_H + +#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSSHAKE192FROBUST_AVX2_##s + +/* Hash output length in bytes. */ +#define SPX_N 24 +/* Height of the hypertree. */ +#define SPX_FULL_HEIGHT 66 +/* Number of subtree layer. */ +#define SPX_D 22 +/* FORS tree dimensions. */ +#define SPX_FORS_HEIGHT 8 +#define SPX_FORS_TREES 33 +/* Winternitz parameter, */ +#define SPX_WOTS_W 16 + +/* The hash function is defined by linking a different hash.c file, as opposed + to setting a #define constant. */ + +/* For clarity */ +#define SPX_ADDR_BYTES 32 + +/* WOTS parameters. */ +#define SPX_WOTS_LOGW 4 + +#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) + +/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ +#define SPX_WOTS_LEN2 3 + +#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) +#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) +#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES + +/* Subtree size. */ +#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) + +//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT +// #error SPX_D should always divide SPX_FULL_HEIGHT +//#endif + +/* FORS parameters. */ +#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) +#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) +#define SPX_FORS_PK_BYTES SPX_N + +/* Resulting SPX sizes. */ +#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ + SPX_FULL_HEIGHT * SPX_N) +#define SPX_PK_BYTES (2 * SPX_N) +#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) + +#include "shake_offsets.h" + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/shake_offsets.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/shake_offsets.h new file mode 100644 index 0000000000..6b28d95d91 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/shake_offsets.h @@ -0,0 +1,21 @@ +#ifndef SHAKE_OFFSETS_H_ +#define SHAKE_OFFSETS_H_ + +/* + * Offsets of various fields in the address structure when we use SHAKE as + * the Sphincs+ hash function + */ + +#define SPX_OFFSET_LAYER 3 /* The byte used to specify the Merkle tree layer */ +#define SPX_OFFSET_TREE 8 /* The start of the 8 byte field used to specify the tree */ +#define SPX_OFFSET_TYPE 19 /* The byte used to specify the hash type (reason) */ +#define SPX_OFFSET_KP_ADDR2 22 /* The high byte used to specify the key pair (which one-time signature) */ +#define SPX_OFFSET_KP_ADDR1 23 /* The low byte used to specify the key pair */ +#define SPX_OFFSET_CHAIN_ADDR 27 /* The byte used to specify the chain address (which Winternitz chain) */ +#define SPX_OFFSET_HASH_ADDR 31 /* The byte used to specify the hash address (where in the Winternitz chain) */ +#define SPX_OFFSET_TREE_HGT 27 /* The byte used to specify the height of this node in the FORS or Merkle tree */ +#define SPX_OFFSET_TREE_INDEX 28 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ + +#define SPX_SHAKE 1 + +#endif /* SHAKE_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/sign.c b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/sign.c new file mode 100644 index 0000000000..9d0c7d1b22 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/sign.c @@ -0,0 +1,286 @@ +#include +#include +#include + +#include "address.h" +#include "context.h" +#include "fors.h" +#include "hash.h" +#include "merkle.h" +#include "nistapi.h" +#include "params.h" +#include "randombytes.h" +#include "thash.h" +#include "utils.h" +#include "wots.h" + +/* + * Returns the length of a secret key, in bytes + */ +size_t crypto_sign_secretkeybytes(void) { + return CRYPTO_SECRETKEYBYTES; +} + +/* + * Returns the length of a public key, in bytes + */ +size_t crypto_sign_publickeybytes(void) { + return CRYPTO_PUBLICKEYBYTES; +} + +/* + * Returns the length of a signature, in bytes + */ +size_t crypto_sign_bytes(void) { + return CRYPTO_BYTES; +} + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +size_t crypto_sign_seedbytes(void) { + return CRYPTO_SEEDBYTES; +} + +/* + * Generates an SPX key pair given a seed of length + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [PUB_SEED || root] + */ +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed) { + spx_ctx ctx; + + /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ + memcpy(sk, seed, CRYPTO_SEEDBYTES); + + memcpy(pk, sk + 2 * SPX_N, SPX_N); + + memcpy(ctx.pub_seed, pk, SPX_N); + memcpy(ctx.sk_seed, sk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + /* Compute root node of the top-most subtree. */ + merkle_gen_root(sk + 3 * SPX_N, &ctx); + + // cleanup + free_hash_function(&ctx); + + memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); + + return 0; +} + +/* + * Generates an SPX key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [PUB_SEED || root] + */ +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { + uint8_t seed[CRYPTO_SEEDBYTES]; + randombytes(seed, CRYPTO_SEEDBYTES); + crypto_sign_seed_keypair(pk, sk, seed); + + return 0; +} + +/** + * Returns an array containing a detached signature. + */ +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk) { + spx_ctx ctx; + + const uint8_t *sk_prf = sk + SPX_N; + const uint8_t *pk = sk + 2 * SPX_N; + + uint8_t optrand[SPX_N]; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t root[SPX_N]; + uint32_t i; + uint64_t tree; + uint32_t idx_leaf; + uint32_t wots_addr[8] = {0}; + uint32_t tree_addr[8] = {0}; + + memcpy(ctx.sk_seed, sk, SPX_N); + memcpy(ctx.pub_seed, pk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + + /* Optionally, signing can be made non-deterministic using optrand. + This can help counter side-channel attacks that would benefit from + getting a large number of traces when the signer uses the same nodes. */ + randombytes(optrand, SPX_N); + /* Compute the digest randomization value. */ + gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); + + /* Derive the message digest and leaf index from R, PK and M. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; + + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); + + /* Sign the message hash using FORS. */ + fors_sign(sig, root, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); + sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; + + /* Update the indices for the next layer. */ + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; + } + + free_hash_function(&ctx); + + *siglen = SPX_BYTES; + + return 0; +} + +/** + * Verifies a detached signature and message under a given public key. + */ +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk) { + spx_ctx ctx; + const uint8_t *pub_root = pk + SPX_N; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t wots_pk[SPX_WOTS_BYTES]; + uint8_t root[SPX_N]; + uint8_t leaf[SPX_N]; + unsigned int i; + uint64_t tree; + uint32_t idx_leaf; + uint32_t wots_addr[8] = {0}; + uint32_t tree_addr[8] = {0}; + uint32_t wots_pk_addr[8] = {0}; + + if (siglen != SPX_BYTES) { + return -1; + } + + memcpy(ctx.pub_seed, pk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); + + /* Derive the message digest and leaf index from R || PK || M. */ + /* The additional SPX_N is a result of the hash domain separator. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; + + /* Layer correctly defaults to 0, so no need to set_layer_addr */ + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); + + fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + /* For each subtree.. */ + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + copy_keypair_addr(wots_pk_addr, wots_addr); + + /* The WOTS public key is only correct if the signature was correct. */ + /* Initially, root is the FORS pk, but on subsequent iterations it is + the root of the subtree below the currently processed subtree. */ + wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); + sig += SPX_WOTS_BYTES; + + /* Compute the leaf node using the WOTS public key. */ + thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); + + /* Compute the root node of this subtree. */ + compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, + &ctx, tree_addr); + sig += SPX_TREE_HEIGHT * SPX_N; + + /* Update the indices for the next layer. */ + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; + } + + // cleanup + free_hash_function(&ctx); + + /* Check if the root node equals the root node in the public key. */ + if (memcmp(root, pub_root, SPX_N) != 0) { + return -1; + } + + return 0; +} + + +/** + * Returns an array containing the signature followed by the message. + */ +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk) { + size_t siglen; + + crypto_sign_signature(sm, &siglen, m, mlen, sk); + + memmove(sm + SPX_BYTES, m, mlen); + *smlen = siglen + mlen; + + return 0; +} + +/** + * Verifies a given signature-message pair under a given public key. + */ +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk) { + /* The API caller does not necessarily know what size a signature should be + but SPHINCS+ signatures are always exactly SPX_BYTES. */ + if (smlen < SPX_BYTES) { + memset(m, 0, smlen); + *mlen = 0; + return -1; + } + + *mlen = smlen - SPX_BYTES; + + if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { + memset(m, 0, smlen); + *mlen = 0; + return -1; + } + + /* If verification was successful, move the message to the right place. */ + memmove(m, sm + SPX_BYTES, *mlen); + + return 0; +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/thash.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/thash.h new file mode 100644 index 0000000000..8687ccfb4d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/thash.h @@ -0,0 +1,13 @@ +#ifndef SPX_THASH_H +#define SPX_THASH_H + +#include "context.h" +#include "params.h" + +#include + +#define thash SPX_NAMESPACE(thash) +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/thash_shake_robust.c b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/thash_shake_robust.c new file mode 100644 index 0000000000..696d53c5cc --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/thash_shake_robust.c @@ -0,0 +1,31 @@ +#include +#include + +#include "thash.h" + +#include "address.h" +#include "params.h" +#include "utils.h" + +#include "fips202.h" + +/** + * Takes an array of inblocks concatenated arrays of SPX_N bytes. + */ +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]) { + PQCLEAN_VLA(uint8_t, buf, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); + PQCLEAN_VLA(uint8_t, bitmask, inblocks * SPX_N); + unsigned int i; + + memcpy(buf, ctx->pub_seed, SPX_N); + memcpy(buf + SPX_N, addr, SPX_ADDR_BYTES); + + shake256(bitmask, inblocks * SPX_N, buf, SPX_N + SPX_ADDR_BYTES); + + for (i = 0; i < inblocks * SPX_N; i++) { + buf[SPX_N + SPX_ADDR_BYTES + i] = in[i] ^ bitmask[i]; + } + + shake256(out, SPX_N, buf, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/thash_shake_robustx4.c b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/thash_shake_robustx4.c new file mode 100644 index 0000000000..ce2946b745 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/thash_shake_robustx4.c @@ -0,0 +1,131 @@ +#include +#include + +#include "thashx4.h" + +#include "address.h" +#include "params.h" +#include "utils.h" + +#include "fips202x4.h" + +extern void KeccakP1600times4_PermuteAll_24rounds(__m256i *s); + +/** + * 4-way parallel version of thash; takes 4x as much input and output + */ +void thashx4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addrx4[4 * 8]) { + if (inblocks == 1 || inblocks == 2) { + /* As we write and read only a few quadwords, it is more efficient to + * build and extract from the fourway SHAKE256 state by hand. */ + __m256i state[25]; + for (int i = 0; i < SPX_N / 8; i++) { + state[i] = _mm256_set1_epi64x(((int64_t *)ctx->pub_seed)[i]); + } + for (int i = 0; i < 4; i++) { + state[SPX_N / 8 + i] = _mm256_set_epi32( + (int)addrx4[3 * 8 + 1 + 2 * i], + (int)addrx4[3 * 8 + 2 * i], + (int)addrx4[2 * 8 + 1 + 2 * i], + (int)addrx4[2 * 8 + 2 * i], + (int)addrx4[8 + 1 + 2 * i], + (int)addrx4[8 + 2 * i], + (int)addrx4[1 + 2 * i], + (int)addrx4[2 * i] + ); + } + + /* SHAKE domain separator and padding */ + state[SPX_N / 8 + 4] = _mm256_set1_epi64x(0x1f); + for (int i = SPX_N / 8 + 5; i < 16; i++) { + state[i] = _mm256_set1_epi64x(0); + } + state[16] = _mm256_set1_epi64x((long long)(0x80ULL << 56)); + + for (int i = 17; i < 25; i++) { + state[i] = _mm256_set1_epi64x(0); + } + + /* We will permutate state2 with f1600x4 to compute the bitmask, + * but first we'll copy it to state2 which will be used to compute + * the final output, as its input is alsmost identical. */ + __m256i state2[25]; + memcpy(state2, state, 800); + + KeccakP1600times4_PermuteAll_24rounds(&state[0]); + + /* By copying from state, state2 already contains the pub_seed + * and addres. We just need to copy in the input blocks xorred with + * the bitmask we just computed. */ + for (unsigned int i = 0; i < (SPX_N / 8) * inblocks; i++) { + state2[SPX_N / 8 + 4 + i] = _mm256_xor_si256( + state[i], + _mm256_set_epi64x( + ((int64_t *)in3)[i], + ((int64_t *)in2)[i], + ((int64_t *)in1)[i], + ((int64_t *)in0)[i] + ) + ); + } + + /* Domain separator and start of padding. Note that the quadwords + * around are already zeroed for state from which we copied. + * We do a XOR instead of a set as this might be the 16th quadword + * when N=32 and inblocks=2, which already contains the end + * of the padding. */ + state2[(SPX_N / 8) * (1 + inblocks) + 4] = _mm256_xor_si256( + state2[(SPX_N / 8) * (1 + inblocks) + 4], + _mm256_set1_epi64x(0x1f) + ); + + KeccakP1600times4_PermuteAll_24rounds(&state2[0]); + + for (int i = 0; i < SPX_N / 8; i++) { + ((int64_t *)out0)[i] = _mm256_extract_epi64(state2[i], 0); + ((int64_t *)out1)[i] = _mm256_extract_epi64(state2[i], 1); + ((int64_t *)out2)[i] = _mm256_extract_epi64(state2[i], 2); + ((int64_t *)out3)[i] = _mm256_extract_epi64(state2[i], 3); + } + } else { + PQCLEAN_VLA(unsigned char, buf0, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, buf1, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, buf2, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, buf3, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, bitmask0, inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, bitmask1, inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, bitmask2, inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, bitmask3, inblocks * SPX_N); + unsigned int i; + + memcpy(buf0, ctx->pub_seed, SPX_N); + memcpy(buf1, ctx->pub_seed, SPX_N); + memcpy(buf2, ctx->pub_seed, SPX_N); + memcpy(buf3, ctx->pub_seed, SPX_N); + memcpy(buf0 + SPX_N, addrx4 + 0 * 8, SPX_ADDR_BYTES); + memcpy(buf1 + SPX_N, addrx4 + 1 * 8, SPX_ADDR_BYTES); + memcpy(buf2 + SPX_N, addrx4 + 2 * 8, SPX_ADDR_BYTES); + memcpy(buf3 + SPX_N, addrx4 + 3 * 8, SPX_ADDR_BYTES); + + shake256x4(bitmask0, bitmask1, bitmask2, bitmask3, inblocks * SPX_N, + buf0, buf1, buf2, buf3, SPX_N + SPX_ADDR_BYTES); + + for (i = 0; i < inblocks * SPX_N; i++) { + buf0[SPX_N + SPX_ADDR_BYTES + i] = in0[i] ^ bitmask0[i]; + buf1[SPX_N + SPX_ADDR_BYTES + i] = in1[i] ^ bitmask1[i]; + buf2[SPX_N + SPX_ADDR_BYTES + i] = in2[i] ^ bitmask2[i]; + buf3[SPX_N + SPX_ADDR_BYTES + i] = in3[i] ^ bitmask3[i]; + } + + shake256x4(out0, out1, out2, out3, SPX_N, + buf0, buf1, buf2, buf3, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/thashx4.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/thashx4.h new file mode 100644 index 0000000000..64798a3727 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/thashx4.h @@ -0,0 +1,20 @@ +#ifndef SPX_THASHX4_H +#define SPX_THASHX4_H + +#include + +#include "context.h" +#include "params.h" + +#define thashx4 SPX_NAMESPACE(thashx4) +void thashx4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addrx4[4 * 8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/utils.c b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/utils.c new file mode 100644 index 0000000000..177b541fb9 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/utils.c @@ -0,0 +1,148 @@ +#include + +#include "utils.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "thash.h" + +/** + * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. + */ +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in) { + int i; + + /* Iterate over out in decreasing order, for big-endianness. */ + for (i = (signed int)outlen - 1; i >= 0; i--) { + out[i] = in & 0xff; + in = in >> 8; + } +} + +void u32_to_bytes(unsigned char *out, uint32_t in) { + out[0] = (unsigned char)(in >> 24); + out[1] = (unsigned char)(in >> 16); + out[2] = (unsigned char)(in >> 8); + out[3] = (unsigned char)in; +} + +/** + * Converts the inlen bytes in 'in' from big-endian byte order to an integer. + */ +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { + unsigned long long retval = 0; + unsigned int i; + + for (i = 0; i < inlen; i++) { + retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); + } + return retval; +} + +/** + * Computes a root node given a leaf and an auth path. + * Expects address to be complete other than the tree_height and tree_index. + */ +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]) { + uint32_t i; + unsigned char buffer[2 * SPX_N]; + + /* If leaf_idx is odd (last bit = 1), current path element is a right child + and auth_path has to go left. Otherwise it is the other way around. */ + if (leaf_idx & 1) { + memcpy(buffer + SPX_N, leaf, SPX_N); + memcpy(buffer, auth_path, SPX_N); + } else { + memcpy(buffer, leaf, SPX_N); + memcpy(buffer + SPX_N, auth_path, SPX_N); + } + auth_path += SPX_N; + + for (i = 0; i < tree_height - 1; i++) { + leaf_idx >>= 1; + idx_offset >>= 1; + /* Set the address of the node we're creating. */ + set_tree_height(addr, i + 1); + set_tree_index(addr, leaf_idx + idx_offset); + + /* Pick the right or left neighbor, depending on parity of the node. */ + if (leaf_idx & 1) { + thash(buffer + SPX_N, buffer, 2, ctx, addr); + memcpy(buffer, auth_path, SPX_N); + } else { + thash(buffer, buffer, 2, ctx, addr); + memcpy(buffer + SPX_N, auth_path, SPX_N); + } + auth_path += SPX_N; + } + + /* The last iteration is exceptional; we do not copy an auth_path node. */ + leaf_idx >>= 1; + idx_offset >>= 1; + set_tree_height(addr, tree_height); + set_tree_index(addr, leaf_idx + idx_offset); + thash(root, buffer, 2, ctx, addr); +} + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx * /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]) { + PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); + PQCLEAN_VLA(unsigned int, heights, tree_height + 1); + unsigned int offset = 0; + uint32_t idx; + uint32_t tree_idx; + + for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { + /* Add the next leaf node to the stack. */ + gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); + offset++; + heights[offset - 1] = 0; + + /* If this is a node we need for the auth path.. */ + if ((leaf_idx ^ 0x1) == idx) { + memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); + } + + /* While the top-most nodes are of equal height.. */ + while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { + /* Compute index of the new node, in the next layer. */ + tree_idx = (idx >> (heights[offset - 1] + 1)); + + /* Set the address of the node we're creating. */ + set_tree_height(tree_addr, heights[offset - 1] + 1); + set_tree_index(tree_addr, + tree_idx + (idx_offset >> (heights[offset - 1] + 1))); + /* Hash the top-most nodes from the stack together. */ + thash(stack + (offset - 2)*SPX_N, + stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); + offset--; + /* Note that the top-most node is now one layer higher. */ + heights[offset - 1]++; + + /* If this is a node we need for the auth path.. */ + if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { + memcpy(auth_path + heights[offset - 1]*SPX_N, + stack + (offset - 1)*SPX_N, SPX_N); + } + } + } + memcpy(root, stack, SPX_N); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/utils.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/utils.h new file mode 100644 index 0000000000..64f5d5a53a --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/utils.h @@ -0,0 +1,58 @@ +#ifndef SPX_UTILS_H +#define SPX_UTILS_H + +#include + +#include "compat.h" +#include "context.h" +#include "params.h" + + +/* To support MSVC use alloca() instead of VLAs. See #20. */ + + +/** + * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. + */ +#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in); +#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) +void u32_to_bytes(unsigned char *out, uint32_t in); + +/** + * Converts the inlen bytes in 'in' from big-endian byte order to an integer. + */ +#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); + +/** + * Computes a root node given a leaf and an auth path. + * Expects address to be complete other than the tree_height and tree_index. + */ +#define compute_root SPX_NAMESPACE(compute_root) +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]); + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +#define treehash SPX_NAMESPACE(treehash) +void treehash(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx *ctx /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]); + + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/utilsx4.c b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/utilsx4.c new file mode 100644 index 0000000000..1638677194 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/utilsx4.c @@ -0,0 +1,138 @@ +#include + +#include "utilsx4.h" + +#include "address.h" +#include "params.h" +#include "thashx4.h" +#include "utils.h" + +/* + * Generate the entire Merkle tree, computing the authentication path for leaf_idx, + * and the resulting root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) + * + * This expects tree_addrx4 to be initialized to 4 parallel addr structures for + * the Merkle tree nodes + * + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + * + * This works by using the standard Merkle tree building algorithm, except + * that each 'node' tracked is actually 4 consecutive nodes in the real tree. + * When we combine two logical nodes ABCD and WXYZ, we perform the H + * operation on adjacent real nodes, forming the parent logical node + * (AB)(CD)(WX)(YZ) + * + * When we get to the top two levels of the real tree (where there is only + * one logical node), we continue this operation two more times; the right + * most real node will by the actual root (and the other 3 nodes will be + * garbage). We follow the same thashx4 logic so that the 'extract + * authentication path components' part of the loop is still executed (and + * to simplify the code somewhat) + * + * This currently assumes tree_height >= 2; I suspect that doing an adjusting + * idx, addr_idx on the gen_leafx4 call if tree_height < 2 would fix it; since + * we don't actually use such short trees, I haven't bothered + */ +void treehashx4(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, + uint32_t tree_height, + void (*gen_leafx4)( + unsigned char * /* Where to write the leaves */, + const spx_ctx *, + uint32_t idx, void *info), + uint32_t tree_addrx4[4 * 8], + void *info) { + /* This is where we keep the intermediate nodes */ + PQCLEAN_VLA(unsigned char, stackx4, tree_height * 4 * SPX_N); + uint32_t left_adj = 0, prev_left_adj = 0; /* When we're doing the top 3 */ + /* levels, the left-most part of the tree isn't at the beginning */ + /* of current[]. These give the offset of the actual start */ + + uint32_t idx; + uint32_t max_idx = (1U << (tree_height - 2)) - 1; + for (idx = 0;; idx++) { + unsigned char current[4 * SPX_N]; /* Current logical node */ + gen_leafx4( current, ctx, 4 * idx + idx_offset, + info ); + + /* Now combine the freshly generated right node with previously */ + /* generated left ones */ + uint32_t internal_idx_offset = idx_offset; + uint32_t internal_idx = idx; + uint32_t internal_leaf = leaf_idx; + uint32_t h; /* The height we are in the Merkle tree */ + for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { + + /* Special processing if we're at the top of the tree */ + if (h >= tree_height - 2) { + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[3 * SPX_N], SPX_N ); + return; + } + /* The tree indexing logic is a bit off in this case */ + /* Adjust it so that the left-most node of the part of */ + /* the tree that we're processing has index 0 */ + prev_left_adj = left_adj; + left_adj = 4U - (1 << (tree_height - h - 1)); + } + + /* Check if we hit the top of the tree */ + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[3 * SPX_N], SPX_N ); + return; + } + + /* + * Check if one of the nodes we have is a part of the + * authentication path; if it is, write it out + */ + if ((((internal_idx << 2) ^ internal_leaf) & ~0x3U) == 0) { + memcpy( &auth_path[ h * SPX_N ], + ¤t[(((internal_leaf & 3) ^ 1) + prev_left_adj) * SPX_N], + SPX_N ); + } + + /* + * Check if we're at a left child; if so, stop going up the stack + * Exception: if we've reached the end of the tree, keep on going + * (so we combine the last 4 nodes into the one root node in two + * more iterations) + */ + if ((internal_idx & 1) == 0 && idx < max_idx) { + break; + } + + /* Ok, we're at a right node (or doing the top 3 levels) */ + /* Now combine the left and right logical nodes together */ + + /* Set the address of the node we're creating. */ + unsigned int j; + internal_idx_offset >>= 1; + for (j = 0; j < 4; j++) { + set_tree_height(tree_addrx4 + j * 8, h + 1); + set_tree_index(tree_addrx4 + j * 8, + (4 / 2) * (internal_idx & ~1U) + j - left_adj + internal_idx_offset ); + } + unsigned char *left = &stackx4[h * 4 * SPX_N]; + thashx4( ¤t[0 * SPX_N], + ¤t[1 * SPX_N], + ¤t[2 * SPX_N], + ¤t[3 * SPX_N], + &left [0 * SPX_N], + &left [2 * SPX_N], + ¤t[0 * SPX_N], + ¤t[2 * SPX_N], + 2, ctx, tree_addrx4); + } + + /* We've hit a left child; save the current for when we get the */ + /* corresponding right right */ + memcpy( &stackx4[h * 4 * SPX_N], current, 4 * SPX_N); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/utilsx4.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/utilsx4.h new file mode 100644 index 0000000000..facb874b18 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/utilsx4.h @@ -0,0 +1,30 @@ +#ifndef SPX_UTILSX4_H +#define SPX_UTILSX4_H + +#include + +#include "context.h" +#include "params.h" + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + * + * This implementation uses AVX to compute internal nodes 4 at a time (in + * parallel) + */ +#define treehashx4 SPX_NAMESPACE(treehashx4) +void treehashx4(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leafx4)( + unsigned char * /* Where to write the leaves */, + const spx_ctx * /* ctx */, + uint32_t addr_idx, void *info), + uint32_t tree_addrx4[4 * 8], void *info); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/wots.c b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/wots.c new file mode 100644 index 0000000000..4d5041ce05 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/wots.c @@ -0,0 +1,269 @@ +#include +#include + +#include "wots.h" + +#include "address.h" +#include "hash.h" +#include "hashx4.h" +#include "params.h" +#include "thash.h" +#include "thashx4.h" +#include "utils.h" +#include "utilsx4.h" +#include "wotsx4.h" + +// TODO clarify address expectations, and make them more uniform. +// TODO i.e. do we expect types to be set already? +// TODO and do we expect modifications or copies? + +/** + * Computes up the chains + */ +static void gen_chains( + unsigned char *out, + const unsigned char *in, + unsigned int start[SPX_WOTS_LEN], + const unsigned int steps[SPX_WOTS_LEN], + const spx_ctx *ctx, + uint32_t addr[8]) { + uint32_t i, j, k, idx, watching; + int done; + unsigned char empty[SPX_N]; + unsigned char *bufs[4]; + uint32_t addrs[8 * 4]; + + int l; + uint16_t counts[SPX_WOTS_W] = { 0 }; + uint16_t idxs[SPX_WOTS_LEN]; + uint16_t total, newTotal; + + /* set addrs = {addr, addr, addr, addr} */ + for (j = 0; j < 4; j++) { + memcpy(addrs + j * 8, addr, sizeof(uint32_t) * 8); + } + + /* Initialize out with the value at position 'start'. */ + memcpy(out, in, SPX_WOTS_LEN * SPX_N); + + /* Sort the chains in reverse order by steps using counting sort. */ + for (i = 0; i < SPX_WOTS_LEN; i++) { + counts[steps[i]]++; + } + total = 0; + for (l = SPX_WOTS_W - 1; l >= 0; l--) { + newTotal = counts[l] + total; + counts[l] = total; + total = newTotal; + } + for (i = 0; i < SPX_WOTS_LEN; i++) { + idxs[counts[steps[i]]] = (uint16_t)i; + counts[steps[i]]++; + } + + /* We got our work cut out for us: do it! */ + for (i = 0; i < SPX_WOTS_LEN; i += 4) { + for (j = 0; j < 4 && i + j < SPX_WOTS_LEN; j++) { + idx = idxs[i + j]; + set_chain_addr(addrs + j * 8, idx); + bufs[j] = out + SPX_N * idx; + } + + /* As the chains are sorted in reverse order, we know that the first + * chain is the longest and the last one is the shortest. We keep + * an eye on whether the last chain is done and then on the one before, + * et cetera. */ + watching = 3; + done = 0; + while (i + watching >= SPX_WOTS_LEN) { + bufs[watching] = &empty[0]; + watching--; + } + + for (k = 0;; k++) { + while (k == steps[idxs[i + watching]]) { + bufs[watching] = &empty[0]; + if (watching == 0) { + done = 1; + break; + } + watching--; + } + if (done) { + break; + } + for (j = 0; j < watching + 1; j++) { + set_hash_addr(addrs + j * 8, k + start[idxs[i + j]]); + } + + thashx4(bufs[0], bufs[1], bufs[2], bufs[3], + bufs[0], bufs[1], bufs[2], bufs[3], 1, ctx, addrs); + } + } +} + +/** + * base_w algorithm as described in draft. + * Interprets an array of bytes as integers in base w. + * This only works when log_w is a divisor of 8. + */ +static void base_w(unsigned int *output, const int out_len, + const unsigned char *input) { + int in = 0; + int out = 0; + unsigned char total = 0; + int bits = 0; + int consumed; + + for (consumed = 0; consumed < out_len; consumed++) { + if (bits == 0) { + total = input[in]; + in++; + bits += 8; + } + bits -= SPX_WOTS_LOGW; + output[out] = (total >> bits) & (SPX_WOTS_W - 1); + out++; + } +} + +/* Computes the WOTS+ checksum over a message (in base_w). */ +static void wots_checksum(unsigned int *csum_base_w, + const unsigned int *msg_base_w) { + unsigned int csum = 0; + unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; + unsigned int i; + + /* Compute checksum. */ + for (i = 0; i < SPX_WOTS_LEN1; i++) { + csum += SPX_WOTS_W - 1 - msg_base_w[i]; + } + + /* Convert checksum to base_w. */ + /* Make sure expected empty zero bits are the least significant bits. */ + csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); + ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); + base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); +} + +/* Takes a message and derives the matching chain lengths. */ +void chain_lengths(unsigned int *lengths, const unsigned char *msg) { + base_w(lengths, SPX_WOTS_LEN1, msg); + wots_checksum(lengths + SPX_WOTS_LEN1, lengths); +} + +/** + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. + * + * Writes the computed public key to 'pk'. + */ +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]) { + unsigned int steps[SPX_WOTS_LEN]; + unsigned int start[SPX_WOTS_LEN]; + uint32_t i; + + chain_lengths(start, msg); + + for (i = 0; i < SPX_WOTS_LEN; i++) { + steps[i] = SPX_WOTS_W - 1 - start[i]; + } + + gen_chains(pk, sig, start, steps, ctx, addr); +} + +/* + * This generates 4 sequential WOTS public keys + * It also generates the WOTS signature if leaf_info indicates + * that we're signing with one of these WOTS keys + */ +void wots_gen_leafx4(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info) { + struct leaf_info_x4 *info = v_info; + uint32_t *leaf_addr = info->leaf_addr; + uint32_t *pk_addr = info->pk_addr; + unsigned int i, j, k; + unsigned char pk_buffer[ 4 * SPX_WOTS_BYTES ]; + unsigned wots_offset = SPX_WOTS_BYTES; + unsigned char *buffer; + uint32_t wots_k_mask; + unsigned wots_sign_index; + + if (((leaf_idx ^ info->wots_sign_leaf) & ~3U) == 0) { + /* We're traversing the leaf that's signing; generate the WOTS */ + /* signature */ + wots_k_mask = 0; + wots_sign_index = info->wots_sign_leaf & 3; /* Which of of the 4 */ + /* 4 slots do the signatures come from */ + } else { + /* Nope, we're just generating pk's; turn off the signature logic */ + wots_k_mask = (uint32_t)~0; + wots_sign_index = 0; + } + + for (j = 0; j < 4; j++) { + set_keypair_addr( leaf_addr + j * 8, leaf_idx + j ); + set_keypair_addr( pk_addr + j * 8, leaf_idx + j ); + } + + for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { + uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k to */ + /* the step if we're generating a signature, ~0 if we're not */ + + /* Start with the secret seed */ + for (j = 0; j < 4; j++) { + set_chain_addr(leaf_addr + j * 8, i); + set_hash_addr(leaf_addr + j * 8, 0); + set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTSPRF); + } + prf_addrx4(buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + buffer + 2 * wots_offset, + buffer + 3 * wots_offset, + ctx, leaf_addr); + + for (j = 0; j < 4; j++) { + set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTS); + } + + /* Iterate down the WOTS chain */ + for (k = 0;; k++) { + /* Check if one of the values we have needs to be saved as a */ + /* part of the WOTS signature */ + if (k == wots_k) { + memcpy( info->wots_sig + i * SPX_N, + buffer + wots_sign_index * wots_offset, SPX_N ); + } + + /* Check if we hit the top of the chain */ + if (k == SPX_WOTS_W - 1) { + break; + } + + /* Iterate one step on all 4 chains */ + for (j = 0; j < 4; j++) { + set_hash_addr(leaf_addr + j * 8, k); + } + thashx4(buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + buffer + 2 * wots_offset, + buffer + 3 * wots_offset, + buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + buffer + 2 * wots_offset, + buffer + 3 * wots_offset, 1, ctx, leaf_addr); + } + } + + /* Do the final thash to generate the public keys */ + thashx4(dest + 0 * SPX_N, + dest + 1 * SPX_N, + dest + 2 * SPX_N, + dest + 3 * SPX_N, + pk_buffer + 0 * wots_offset, + pk_buffer + 1 * wots_offset, + pk_buffer + 2 * wots_offset, + pk_buffer + 3 * wots_offset, SPX_WOTS_LEN, ctx, pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/wots.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/wots.h new file mode 100644 index 0000000000..4e7692eeef --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/wots.h @@ -0,0 +1,25 @@ +#ifndef SPX_WOTS_H +#define SPX_WOTS_H + +#include + +#include "context.h" +#include "params.h" + +/** + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. + * + * Writes the computed public key to 'pk'. + */ +#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]); + +/* + * Compute the chain lengths needed for a given message hash + */ +#define chain_lengths SPX_NAMESPACE(chain_lengths) +void chain_lengths(unsigned int *lengths, const unsigned char *msg); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/wotsx4.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/wotsx4.h new file mode 100644 index 0000000000..cd634f1743 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/wotsx4.h @@ -0,0 +1,41 @@ +#ifndef WOTSX4_H_ +#define WOTSX4_H_ + +#include + +#include "params.h" + +/* + * This is here to provide an interface to the internal wots_gen_leafx4 + * routine. While this routine is not referenced in the package outside of + * wots.c, it is called from the stand-alone benchmark code to characterize + * the performance + */ +struct leaf_info_x4 { + unsigned char *wots_sig; + uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ + uint32_t *wots_steps; + uint32_t leaf_addr[4 * 8]; + uint32_t pk_addr[4 * 8]; +}; + +/* Macro to set the leaf_info to something 'benign', that is, it would */ +/* run with the same time as it does during the real signing process */ +/* Used only by the benchmark code */ +#define INITIALIZE_LEAF_INFO_X4(info, addr, step_buffer) { \ + (info).wots_sig = 0; \ + (info).wots_sign_leaf = ~0; \ + (info).wots_steps = step_buffer; \ + int i; \ + for (i=0; i<4; i++) { \ + memcpy( &(info).leaf_addr[8*i], addr, 32 ); \ + memcpy( &(info).pk_addr[8*i], addr, 32 ); \ + } \ + } + +#define wots_gen_leafx4 SPX_NAMESPACE(wots_gen_leafx4) +void wots_gen_leafx4(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info); + +#endif /* WOTSX4_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/LICENSE b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/LICENSE new file mode 100644 index 0000000000..670154e353 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/LICENSE @@ -0,0 +1,116 @@ +CC0 1.0 Universal + +Statement of Purpose + +The laws of most jurisdictions throughout the world automatically confer +exclusive Copyright and Related Rights (defined below) upon the creator and +subsequent owner(s) (each and all, an "owner") of an original work of +authorship and/or a database (each, a "Work"). + +Certain owners wish to permanently relinquish those rights to a Work for the +purpose of contributing to a commons of creative, cultural and scientific +works ("Commons") that the public can reliably and without fear of later +claims of infringement build upon, modify, incorporate in other works, reuse +and redistribute as freely as possible in any form whatsoever and for any +purposes, including without limitation commercial purposes. These owners may +contribute to the Commons to promote the ideal of a free culture and the +further production of creative, cultural and scientific works, or to gain +reputation or greater distribution for their Work in part through the use and +efforts of others. + +For these and/or other purposes and motivations, and without any expectation +of additional consideration or compensation, the person associating CC0 with a +Work (the "Affirmer"), to the extent that he or she is an owner of Copyright +and Related Rights in the Work, voluntarily elects to apply CC0 to the Work +and publicly distribute the Work under its terms, with knowledge of his or her +Copyright and Related Rights in the Work and the meaning and intended legal +effect of CC0 on those rights. + +1. Copyright and Related Rights. A Work made available under CC0 may be +protected by copyright and related or neighboring rights ("Copyright and +Related Rights"). Copyright and Related Rights include, but are not limited +to, the following: + + i. the right to reproduce, adapt, distribute, perform, display, communicate, + and translate a Work; + + ii. moral rights retained by the original author(s) and/or performer(s); + + iii. publicity and privacy rights pertaining to a person's image or likeness + depicted in a Work; + + iv. rights protecting against unfair competition in regards to a Work, + subject to the limitations in paragraph 4(a), below; + + v. rights protecting the extraction, dissemination, use and reuse of data in + a Work; + + vi. database rights (such as those arising under Directive 96/9/EC of the + European Parliament and of the Council of 11 March 1996 on the legal + protection of databases, and under any national implementation thereof, + including any amended or successor version of such directive); and + + vii. other similar, equivalent or corresponding rights throughout the world + based on applicable law or treaty, and any national implementations thereof. + +2. Waiver. To the greatest extent permitted by, but not in contravention of, +applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and +unconditionally waives, abandons, and surrenders all of Affirmer's Copyright +and Related Rights and associated claims and causes of action, whether now +known or unknown (including existing as well as future claims and causes of +action), in the Work (i) in all territories worldwide, (ii) for the maximum +duration provided by applicable law or treaty (including future time +extensions), (iii) in any current or future medium and for any number of +copies, and (iv) for any purpose whatsoever, including without limitation +commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes +the Waiver for the benefit of each member of the public at large and to the +detriment of Affirmer's heirs and successors, fully intending that such Waiver +shall not be subject to revocation, rescission, cancellation, termination, or +any other legal or equitable action to disrupt the quiet enjoyment of the Work +by the public as contemplated by Affirmer's express Statement of Purpose. + +3. Public License Fallback. Should any part of the Waiver for any reason be +judged legally invalid or ineffective under applicable law, then the Waiver +shall be preserved to the maximum extent permitted taking into account +Affirmer's express Statement of Purpose. In addition, to the extent the Waiver +is so judged Affirmer hereby grants to each affected person a royalty-free, +non transferable, non sublicensable, non exclusive, irrevocable and +unconditional license to exercise Affirmer's Copyright and Related Rights in +the Work (i) in all territories worldwide, (ii) for the maximum duration +provided by applicable law or treaty (including future time extensions), (iii) +in any current or future medium and for any number of copies, and (iv) for any +purpose whatsoever, including without limitation commercial, advertising or +promotional purposes (the "License"). The License shall be deemed effective as +of the date CC0 was applied by Affirmer to the Work. Should any part of the +License for any reason be judged legally invalid or ineffective under +applicable law, such partial invalidity or ineffectiveness shall not +invalidate the remainder of the License, and in such case Affirmer hereby +affirms that he or she will not (i) exercise any of his or her remaining +Copyright and Related Rights in the Work or (ii) assert any associated claims +and causes of action with respect to the Work, in either case contrary to +Affirmer's express Statement of Purpose. + +4. Limitations and Disclaimers. + + a. No trademark or patent rights held by Affirmer are waived, abandoned, + surrendered, licensed or otherwise affected by this document. + + b. Affirmer offers the Work as-is and makes no representations or warranties + of any kind concerning the Work, express, implied, statutory or otherwise, + including without limitation warranties of title, merchantability, fitness + for a particular purpose, non infringement, or the absence of latent or + other defects, accuracy, or the present or absence of errors, whether or not + discoverable, all to the greatest extent permissible under applicable law. + + c. Affirmer disclaims responsibility for clearing rights of other persons + that may apply to the Work or any use thereof, including without limitation + any person's Copyright and Related Rights in the Work. Further, Affirmer + disclaims responsibility for obtaining any necessary consents, permissions + or other rights required for any use of the Work. + + d. Affirmer understands and acknowledges that Creative Commons is not a + party to this document and has no duty or obligation with respect to this + CC0 or use of the Work. + +For more information, please see + diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/address.c b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/address.c new file mode 100644 index 0000000000..b956e9cb29 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/address.c @@ -0,0 +1,91 @@ +#include +#include + +#include "address.h" +#include "params.h" +#include "utils.h" + +/* + * Specify which level of Merkle tree (the "layer") we're working on + */ +void set_layer_addr(uint32_t addr[8], uint32_t layer) { + ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; +} + +/* + * Specify which Merkle tree within the level (the "tree address") we're working on + */ +void set_tree_addr(uint32_t addr[8], uint64_t tree) { + ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); +} + +/* + * Specify the reason we'll use this address structure for, that is, what + * hash will we compute with it. This is used so that unrelated types of + * hashes don't accidentally get the same address structure. The type will be + * one of the SPX_ADDR_TYPE constants + */ +void set_type(uint32_t addr[8], uint32_t type) { + ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; +} + +/* + * Copy the layer and tree fields of the address structure. This is used + * when we're doing multiple types of hashes within the same Merkle tree + */ +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); +} + +/* These functions are used for OTS addresses. */ + +/* + * Specify which Merkle leaf we're working on; that is, which OTS keypair + * we're talking about. + */ +void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { + ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; +} + +/* + * Copy the layer, tree and keypair fields of the address structure. This is + * used when we're doing multiple things within the same OTS keypair + */ +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); + ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; +} + +/* + * Specify which Merkle chain within the OTS we're working with + * (the chain address) + */ +void set_chain_addr(uint32_t addr[8], uint32_t chain) { + ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; +} + +/* + * Specify where in the Merkle chain we are +* (the hash address) + */ +void set_hash_addr(uint32_t addr[8], uint32_t hash) { + ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; +} + +/* These functions are used for all hash tree addresses (including FORS). */ + +/* + * Specify the height of the node in the Merkle/FORS tree we are in + * (the tree height) + */ +void set_tree_height(uint32_t addr[8], uint32_t tree_height) { + ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; +} + +/* + * Specify the distance from the left edge of the node in the Merkle/FORS tree + * (the tree index) + */ +void set_tree_index(uint32_t addr[8], uint32_t tree_index) { + u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/address.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/address.h new file mode 100644 index 0000000000..24a84eb40c --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/address.h @@ -0,0 +1,52 @@ +#ifndef SPX_ADDRESS_H +#define SPX_ADDRESS_H + +#include + +#include "params.h" + +/* The hash types that are passed to set_type */ +#define SPX_ADDR_TYPE_WOTS 0 +#define SPX_ADDR_TYPE_WOTSPK 1 +#define SPX_ADDR_TYPE_HASHTREE 2 +#define SPX_ADDR_TYPE_FORSTREE 3 +#define SPX_ADDR_TYPE_FORSPK 4 +#define SPX_ADDR_TYPE_WOTSPRF 5 +#define SPX_ADDR_TYPE_FORSPRF 6 + +#define set_layer_addr SPX_NAMESPACE(set_layer_addr) +void set_layer_addr(uint32_t addr[8], uint32_t layer); + +#define set_tree_addr SPX_NAMESPACE(set_tree_addr) +void set_tree_addr(uint32_t addr[8], uint64_t tree); + +#define set_type SPX_NAMESPACE(set_type) +void set_type(uint32_t addr[8], uint32_t type); + +/* Copies the layer and tree part of one address into the other */ +#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); + +/* These functions are used for WOTS and FORS addresses. */ + +#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) +void set_keypair_addr(uint32_t addr[8], uint32_t keypair); + +#define set_chain_addr SPX_NAMESPACE(set_chain_addr) +void set_chain_addr(uint32_t addr[8], uint32_t chain); + +#define set_hash_addr SPX_NAMESPACE(set_hash_addr) +void set_hash_addr(uint32_t addr[8], uint32_t hash); + +#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); + +/* These functions are used for all hash tree addresses (including FORS). */ + +#define set_tree_height SPX_NAMESPACE(set_tree_height) +void set_tree_height(uint32_t addr[8], uint32_t tree_height); + +#define set_tree_index SPX_NAMESPACE(set_tree_index) +void set_tree_index(uint32_t addr[8], uint32_t tree_index); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/api.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/api.h new file mode 100644 index 0000000000..67614f9c03 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/api.h @@ -0,0 +1,77 @@ +#ifndef PQCLEAN_SPHINCSSHAKE192FROBUST_CLEAN_API_H +#define PQCLEAN_SPHINCSSHAKE192FROBUST_CLEAN_API_H + +#include +#include + +#define PQCLEAN_SPHINCSSHAKE192FROBUST_CLEAN_CRYPTO_ALGNAME "SPHINCS+-shake-192f-robust" + +#define PQCLEAN_SPHINCSSHAKE192FROBUST_CLEAN_CRYPTO_SECRETKEYBYTES 96 +#define PQCLEAN_SPHINCSSHAKE192FROBUST_CLEAN_CRYPTO_PUBLICKEYBYTES 48 +#define PQCLEAN_SPHINCSSHAKE192FROBUST_CLEAN_CRYPTO_BYTES 35664 + +#define PQCLEAN_SPHINCSSHAKE192FROBUST_CLEAN_CRYPTO_SEEDBYTES 72 + +/* + * Returns the length of a secret key, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE192FROBUST_CLEAN_crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE192FROBUST_CLEAN_crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE192FROBUST_CLEAN_crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE192FROBUST_CLEAN_crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +int PQCLEAN_SPHINCSSHAKE192FROBUST_CLEAN_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +int PQCLEAN_SPHINCSSHAKE192FROBUST_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +int PQCLEAN_SPHINCSSHAKE192FROBUST_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +int PQCLEAN_SPHINCSSHAKE192FROBUST_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, + const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +int PQCLEAN_SPHINCSSHAKE192FROBUST_CLEAN_crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +int PQCLEAN_SPHINCSSHAKE192FROBUST_CLEAN_crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/context.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/context.h new file mode 100644 index 0000000000..9f8a40ab4e --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/context.h @@ -0,0 +1,22 @@ +#ifndef SPX_CONTEXT_H +#define SPX_CONTEXT_H + +#include +#include + +#include "params.h" + +typedef struct { + uint8_t pub_seed[SPX_N]; + uint8_t sk_seed[SPX_N]; + + +} spx_ctx; + +#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) +void initialize_hash_function(spx_ctx *ctx); + +#define free_hash_function SPX_NAMESPACE(free_hash_function) +void free_hash_function(spx_ctx *ctx); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/context_shake.c b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/context_shake.c new file mode 100644 index 0000000000..9614a103d3 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/context_shake.c @@ -0,0 +1,12 @@ +#include "context.h" + +/* For SHAKE256, there is no immediate reason to initialize at the start, + so this function is an empty operation. */ +void initialize_hash_function(spx_ctx *ctx) { + (void)ctx; /* Suppress an 'unused parameter' warning. */ +} + +// in case the hash function api is heap-based. +void free_hash_function(spx_ctx *ctx) { + (void)ctx; +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/fors.c b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/fors.c new file mode 100644 index 0000000000..96ca72e986 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/fors.c @@ -0,0 +1,156 @@ +#include +#include +#include + +#include "fors.h" + +#include "address.h" +#include "hash.h" +#include "thash.h" +#include "utils.h" +#include "utilsx1.h" + +static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + prf_addr(sk, ctx, fors_leaf_addr); +} + +static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, + const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + thash(leaf, sk, 1, ctx, fors_leaf_addr); +} + +struct fors_gen_leaf_info { + uint32_t leaf_addrx[8]; +}; + +static void fors_gen_leafx1(unsigned char *leaf, + const spx_ctx *ctx, + uint32_t addr_idx, void *info) { + struct fors_gen_leaf_info *fors_info = info; + uint32_t *fors_leaf_addr = fors_info->leaf_addrx; + + /* Only set the parts that the caller doesn't set */ + set_tree_index(fors_leaf_addr, addr_idx); + set_type(fors_leaf_addr, SPX_ADDR_TYPE_FORSPRF); + fors_gen_sk(leaf, ctx, fors_leaf_addr); + + set_type(fors_leaf_addr, SPX_ADDR_TYPE_FORSTREE); + fors_sk_to_leaf(leaf, leaf, + ctx, fors_leaf_addr); +} + +/** + * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + * Assumes indices has space for SPX_FORS_TREES integers. + */ +static void message_to_indices(uint32_t *indices, const unsigned char *m) { + unsigned int i, j; + unsigned int offset = 0; + + for (i = 0; i < SPX_FORS_TREES; i++) { + indices[i] = 0; + for (j = 0; j < SPX_FORS_HEIGHT; j++) { + indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); + offset++; + } + } +} + +/** + * Signs a message m, deriving the secret key from sk_seed and the FTS address. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + uint32_t fors_tree_addr[8] = {0}; + struct fors_gen_leaf_info fors_info = {0}; + uint32_t *fors_leaf_addr = fors_info.leaf_addrx; + uint32_t fors_pk_addr[8] = {0}; + uint32_t idx_offset; + unsigned int i; + + copy_keypair_addr(fors_tree_addr, fors_addr); + copy_keypair_addr(fors_leaf_addr, fors_addr); + + copy_keypair_addr(fors_pk_addr, fors_addr); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); + + message_to_indices(indices, m); + + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); + + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); + + /* Include the secret key part that produces the selected leaf node. */ + fors_gen_sk(sig, ctx, fors_tree_addr); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + sig += SPX_N; + + /* Compute the authentication path for this leaf node. */ + treehashx1(roots + i * SPX_N, sig, ctx, + indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx1, + fors_tree_addr, &fors_info); + + sig += SPX_N * SPX_FORS_HEIGHT; + } + + /* Hash horizontally across all tree roots to derive the public key. */ + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); +} + +/** + * Derives the FORS public key from a signature. + * This can be used for verification by comparing to a known public key, or to + * subsequently verify a signature on the derived public key. The latter is the + * typical use-case when used as an FTS below an OTS in a hypertree. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + unsigned char leaf[SPX_N]; + uint32_t fors_tree_addr[8] = {0}; + uint32_t fors_pk_addr[8] = {0}; + uint32_t idx_offset; + unsigned int i; + + copy_keypair_addr(fors_tree_addr, fors_addr); + copy_keypair_addr(fors_pk_addr, fors_addr); + + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); + + message_to_indices(indices, m); + + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); + + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + + /* Derive the leaf from the included secret key part. */ + fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); + sig += SPX_N; + + /* Derive the corresponding root node of this tree. */ + compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, + sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); + sig += SPX_N * SPX_FORS_HEIGHT; + } + + /* Hash horizontally across all tree roots to derive the public key. */ + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/fors.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/fors.h new file mode 100644 index 0000000000..509140a178 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/fors.h @@ -0,0 +1,32 @@ +#ifndef SPX_FORS_H +#define SPX_FORS_H + +#include + +#include "context.h" +#include "params.h" + +/** + * Signs a message m, deriving the secret key from sk_seed and the FTS address. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +#define fors_sign SPX_NAMESPACE(fors_sign) +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); + +/** + * Derives the FORS public key from a signature. + * This can be used for verification by comparing to a known public key, or to + * subsequently verify a signature on the derived public key. The latter is the + * typical use-case when used as an FTS below an OTS in a hypertree. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/hash.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/hash.h new file mode 100644 index 0000000000..f7c87d4c3c --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/hash.h @@ -0,0 +1,28 @@ +#ifndef SPX_HASH_H +#define SPX_HASH_H + +#include +#include + +#include "context.h" +#include "params.h" + +#define prf_addr SPX_NAMESPACE(prf_addr) +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]); + +#define gen_message_random SPX_NAMESPACE(gen_message_random) +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); + +#define hash_message SPX_NAMESPACE(hash_message) +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); + + + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/hash_shake.c b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/hash_shake.c new file mode 100644 index 0000000000..ff5e7ec918 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/hash_shake.c @@ -0,0 +1,83 @@ +#include +#include + +#include "hash.h" + +#include "address.h" +#include "fips202.h" +#include "params.h" +#include "utils.h" + +/* + * Computes PRF(pk_seed, sk_seed, addr) + */ +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]) { + unsigned char buf[2 * SPX_N + SPX_ADDR_BYTES]; + + memcpy(buf, ctx->pub_seed, SPX_N); + memcpy(buf + SPX_N, addr, SPX_ADDR_BYTES); + memcpy(buf + SPX_N + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); + + shake256(out, SPX_N, buf, 2 * SPX_N + SPX_ADDR_BYTES); +} + +/** + * Computes the message-dependent randomness R, using a secret seed and an + * optional randomization value as well as the message. + */ +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { + (void)ctx; + shake256incctx s_inc; + + shake256_inc_init(&s_inc); + shake256_inc_absorb(&s_inc, sk_prf, SPX_N); + shake256_inc_absorb(&s_inc, optrand, SPX_N); + shake256_inc_absorb(&s_inc, m, mlen); + shake256_inc_finalize(&s_inc); + shake256_inc_squeeze(R, SPX_N, &s_inc); + shake256_inc_ctx_release(&s_inc); +} + +/** + * Computes the message hash using R, the public key, and the message. + * Outputs the message digest and the index of the leaf. The index is split in + * the tree index and the leaf index, for convenient copying to an address. + */ +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { + (void)ctx; +#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) +#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) +#define SPX_LEAF_BITS SPX_TREE_HEIGHT +#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) +#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) + + unsigned char buf[SPX_DGST_BYTES]; + unsigned char *bufp = buf; + shake256incctx s_inc; + + shake256_inc_init(&s_inc); + shake256_inc_absorb(&s_inc, R, SPX_N); + shake256_inc_absorb(&s_inc, pk, SPX_PK_BYTES); + shake256_inc_absorb(&s_inc, m, mlen); + shake256_inc_finalize(&s_inc); + shake256_inc_squeeze(buf, SPX_DGST_BYTES, &s_inc); + shake256_inc_ctx_release(&s_inc); + + memcpy(digest, bufp, SPX_FORS_MSG_BYTES); + bufp += SPX_FORS_MSG_BYTES; + + + *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); + *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); + bufp += SPX_TREE_BYTES; + + *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); + *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/merkle.c b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/merkle.c new file mode 100644 index 0000000000..0c1479fd93 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/merkle.c @@ -0,0 +1,59 @@ +#include +#include + +#include "address.h" +#include "merkle.h" +#include "params.h" +#include "utils.h" +#include "utilsx1.h" +#include "wots.h" +#include "wotsx1.h" + +/* + * This generates a Merkle signature (WOTS signature followed by the Merkle + * authentication path). This is in this file because most of the complexity + * is involved with the WOTS signature; the Merkle authentication path logic + * is mostly hidden in treehashx4 + */ +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf) { + unsigned char *auth_path = sig + SPX_WOTS_BYTES; + struct leaf_info_x1 info = { 0 }; + unsigned steps[ SPX_WOTS_LEN ]; + + info.wots_sig = sig; + chain_lengths(steps, root); + info.wots_steps = steps; + + set_type(&tree_addr[0], SPX_ADDR_TYPE_HASHTREE); + set_type(&info.pk_addr[0], SPX_ADDR_TYPE_WOTSPK); + copy_subtree_addr(&info.leaf_addr[0], wots_addr); + copy_subtree_addr(&info.pk_addr[0], wots_addr); + + info.wots_sign_leaf = idx_leaf; + + treehashx1(root, auth_path, ctx, + idx_leaf, 0, + SPX_TREE_HEIGHT, + wots_gen_leafx1, + tree_addr, &info); +} + +/* Compute root node of the top-most subtree. */ +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { + /* We do not need the auth path in key generation, but it simplifies the + code to have just one treehash routine that computes both root and path + in one function. */ + unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; + uint32_t top_tree_addr[8] = {0}; + uint32_t wots_addr[8] = {0}; + + set_layer_addr(top_tree_addr, SPX_D - 1); + set_layer_addr(wots_addr, SPX_D - 1); + + merkle_sign(auth_path, root, ctx, + wots_addr, top_tree_addr, + (uint32_t)~0 /* ~0 means "don't bother generating an auth path */ ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/merkle.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/merkle.h new file mode 100644 index 0000000000..769cf2e970 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/merkle.h @@ -0,0 +1,21 @@ +#ifndef MERKLE_H_ +#define MERKLE_H_ + +#include + +#include "context.h" +#include "params.h" + +/* Generate a Merkle signature (WOTS signature followed by the Merkle */ +/* authentication path) */ +#define merkle_sign SPX_NAMESPACE(merkle_sign) +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf); + +/* Compute the root node of the top-most subtree. */ +#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); + +#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/nistapi.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/nistapi.h new file mode 100644 index 0000000000..3cb71afad4 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/nistapi.h @@ -0,0 +1,87 @@ +#ifndef SPX_API_H +#define SPX_API_H + +#include +#include + +#include "params.h" + +#define CRYPTO_ALGNAME "SPHINCS+" + +#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES +#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES +#define CRYPTO_BYTES SPX_BYTES +#define CRYPTO_SEEDBYTES (3*SPX_N) + +/* + * Returns the length of a secret key, in bytes + */ +#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) +size_t crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) +size_t crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) +size_t crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) +size_t crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +#define crypto_sign SPX_NAMESPACE(crypto_sign) +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/params.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/params.h new file mode 100644 index 0000000000..120dc08b61 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/params.h @@ -0,0 +1,56 @@ +#ifndef SPX_PARAMS_H +#define SPX_PARAMS_H + +#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSSHAKE192FROBUST_CLEAN_##s + +/* Hash output length in bytes. */ +#define SPX_N 24 +/* Height of the hypertree. */ +#define SPX_FULL_HEIGHT 66 +/* Number of subtree layer. */ +#define SPX_D 22 +/* FORS tree dimensions. */ +#define SPX_FORS_HEIGHT 8 +#define SPX_FORS_TREES 33 +/* Winternitz parameter, */ +#define SPX_WOTS_W 16 + +/* The hash function is defined by linking a different hash.c file, as opposed + to setting a #define constant. */ + +/* For clarity */ +#define SPX_ADDR_BYTES 32 + +/* WOTS parameters. */ +#define SPX_WOTS_LOGW 4 + +#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) + +/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ +#define SPX_WOTS_LEN2 3 + +#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) +#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) +#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES + +/* Subtree size. */ +#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) + +//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT +// #error SPX_D should always divide SPX_FULL_HEIGHT +//#endif + +/* FORS parameters. */ +#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) +#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) +#define SPX_FORS_PK_BYTES SPX_N + +/* Resulting SPX sizes. */ +#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ + SPX_FULL_HEIGHT * SPX_N) +#define SPX_PK_BYTES (2 * SPX_N) +#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) + +#include "shake_offsets.h" + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/shake_offsets.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/shake_offsets.h new file mode 100644 index 0000000000..6b28d95d91 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/shake_offsets.h @@ -0,0 +1,21 @@ +#ifndef SHAKE_OFFSETS_H_ +#define SHAKE_OFFSETS_H_ + +/* + * Offsets of various fields in the address structure when we use SHAKE as + * the Sphincs+ hash function + */ + +#define SPX_OFFSET_LAYER 3 /* The byte used to specify the Merkle tree layer */ +#define SPX_OFFSET_TREE 8 /* The start of the 8 byte field used to specify the tree */ +#define SPX_OFFSET_TYPE 19 /* The byte used to specify the hash type (reason) */ +#define SPX_OFFSET_KP_ADDR2 22 /* The high byte used to specify the key pair (which one-time signature) */ +#define SPX_OFFSET_KP_ADDR1 23 /* The low byte used to specify the key pair */ +#define SPX_OFFSET_CHAIN_ADDR 27 /* The byte used to specify the chain address (which Winternitz chain) */ +#define SPX_OFFSET_HASH_ADDR 31 /* The byte used to specify the hash address (where in the Winternitz chain) */ +#define SPX_OFFSET_TREE_HGT 27 /* The byte used to specify the height of this node in the FORS or Merkle tree */ +#define SPX_OFFSET_TREE_INDEX 28 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ + +#define SPX_SHAKE 1 + +#endif /* SHAKE_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/sign.c b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/sign.c new file mode 100644 index 0000000000..9d0c7d1b22 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/sign.c @@ -0,0 +1,286 @@ +#include +#include +#include + +#include "address.h" +#include "context.h" +#include "fors.h" +#include "hash.h" +#include "merkle.h" +#include "nistapi.h" +#include "params.h" +#include "randombytes.h" +#include "thash.h" +#include "utils.h" +#include "wots.h" + +/* + * Returns the length of a secret key, in bytes + */ +size_t crypto_sign_secretkeybytes(void) { + return CRYPTO_SECRETKEYBYTES; +} + +/* + * Returns the length of a public key, in bytes + */ +size_t crypto_sign_publickeybytes(void) { + return CRYPTO_PUBLICKEYBYTES; +} + +/* + * Returns the length of a signature, in bytes + */ +size_t crypto_sign_bytes(void) { + return CRYPTO_BYTES; +} + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +size_t crypto_sign_seedbytes(void) { + return CRYPTO_SEEDBYTES; +} + +/* + * Generates an SPX key pair given a seed of length + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [PUB_SEED || root] + */ +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed) { + spx_ctx ctx; + + /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ + memcpy(sk, seed, CRYPTO_SEEDBYTES); + + memcpy(pk, sk + 2 * SPX_N, SPX_N); + + memcpy(ctx.pub_seed, pk, SPX_N); + memcpy(ctx.sk_seed, sk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + /* Compute root node of the top-most subtree. */ + merkle_gen_root(sk + 3 * SPX_N, &ctx); + + // cleanup + free_hash_function(&ctx); + + memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); + + return 0; +} + +/* + * Generates an SPX key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [PUB_SEED || root] + */ +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { + uint8_t seed[CRYPTO_SEEDBYTES]; + randombytes(seed, CRYPTO_SEEDBYTES); + crypto_sign_seed_keypair(pk, sk, seed); + + return 0; +} + +/** + * Returns an array containing a detached signature. + */ +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk) { + spx_ctx ctx; + + const uint8_t *sk_prf = sk + SPX_N; + const uint8_t *pk = sk + 2 * SPX_N; + + uint8_t optrand[SPX_N]; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t root[SPX_N]; + uint32_t i; + uint64_t tree; + uint32_t idx_leaf; + uint32_t wots_addr[8] = {0}; + uint32_t tree_addr[8] = {0}; + + memcpy(ctx.sk_seed, sk, SPX_N); + memcpy(ctx.pub_seed, pk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + + /* Optionally, signing can be made non-deterministic using optrand. + This can help counter side-channel attacks that would benefit from + getting a large number of traces when the signer uses the same nodes. */ + randombytes(optrand, SPX_N); + /* Compute the digest randomization value. */ + gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); + + /* Derive the message digest and leaf index from R, PK and M. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; + + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); + + /* Sign the message hash using FORS. */ + fors_sign(sig, root, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); + sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; + + /* Update the indices for the next layer. */ + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; + } + + free_hash_function(&ctx); + + *siglen = SPX_BYTES; + + return 0; +} + +/** + * Verifies a detached signature and message under a given public key. + */ +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk) { + spx_ctx ctx; + const uint8_t *pub_root = pk + SPX_N; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t wots_pk[SPX_WOTS_BYTES]; + uint8_t root[SPX_N]; + uint8_t leaf[SPX_N]; + unsigned int i; + uint64_t tree; + uint32_t idx_leaf; + uint32_t wots_addr[8] = {0}; + uint32_t tree_addr[8] = {0}; + uint32_t wots_pk_addr[8] = {0}; + + if (siglen != SPX_BYTES) { + return -1; + } + + memcpy(ctx.pub_seed, pk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); + + /* Derive the message digest and leaf index from R || PK || M. */ + /* The additional SPX_N is a result of the hash domain separator. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; + + /* Layer correctly defaults to 0, so no need to set_layer_addr */ + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); + + fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + /* For each subtree.. */ + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + copy_keypair_addr(wots_pk_addr, wots_addr); + + /* The WOTS public key is only correct if the signature was correct. */ + /* Initially, root is the FORS pk, but on subsequent iterations it is + the root of the subtree below the currently processed subtree. */ + wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); + sig += SPX_WOTS_BYTES; + + /* Compute the leaf node using the WOTS public key. */ + thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); + + /* Compute the root node of this subtree. */ + compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, + &ctx, tree_addr); + sig += SPX_TREE_HEIGHT * SPX_N; + + /* Update the indices for the next layer. */ + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; + } + + // cleanup + free_hash_function(&ctx); + + /* Check if the root node equals the root node in the public key. */ + if (memcmp(root, pub_root, SPX_N) != 0) { + return -1; + } + + return 0; +} + + +/** + * Returns an array containing the signature followed by the message. + */ +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk) { + size_t siglen; + + crypto_sign_signature(sm, &siglen, m, mlen, sk); + + memmove(sm + SPX_BYTES, m, mlen); + *smlen = siglen + mlen; + + return 0; +} + +/** + * Verifies a given signature-message pair under a given public key. + */ +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk) { + /* The API caller does not necessarily know what size a signature should be + but SPHINCS+ signatures are always exactly SPX_BYTES. */ + if (smlen < SPX_BYTES) { + memset(m, 0, smlen); + *mlen = 0; + return -1; + } + + *mlen = smlen - SPX_BYTES; + + if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { + memset(m, 0, smlen); + *mlen = 0; + return -1; + } + + /* If verification was successful, move the message to the right place. */ + memmove(m, sm + SPX_BYTES, *mlen); + + return 0; +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/thash.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/thash.h new file mode 100644 index 0000000000..8687ccfb4d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/thash.h @@ -0,0 +1,13 @@ +#ifndef SPX_THASH_H +#define SPX_THASH_H + +#include "context.h" +#include "params.h" + +#include + +#define thash SPX_NAMESPACE(thash) +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/thash_shake_robust.c b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/thash_shake_robust.c new file mode 100644 index 0000000000..696d53c5cc --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/thash_shake_robust.c @@ -0,0 +1,31 @@ +#include +#include + +#include "thash.h" + +#include "address.h" +#include "params.h" +#include "utils.h" + +#include "fips202.h" + +/** + * Takes an array of inblocks concatenated arrays of SPX_N bytes. + */ +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]) { + PQCLEAN_VLA(uint8_t, buf, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); + PQCLEAN_VLA(uint8_t, bitmask, inblocks * SPX_N); + unsigned int i; + + memcpy(buf, ctx->pub_seed, SPX_N); + memcpy(buf + SPX_N, addr, SPX_ADDR_BYTES); + + shake256(bitmask, inblocks * SPX_N, buf, SPX_N + SPX_ADDR_BYTES); + + for (i = 0; i < inblocks * SPX_N; i++) { + buf[SPX_N + SPX_ADDR_BYTES + i] = in[i] ^ bitmask[i]; + } + + shake256(out, SPX_N, buf, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/utils.c b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/utils.c new file mode 100644 index 0000000000..177b541fb9 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/utils.c @@ -0,0 +1,148 @@ +#include + +#include "utils.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "thash.h" + +/** + * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. + */ +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in) { + int i; + + /* Iterate over out in decreasing order, for big-endianness. */ + for (i = (signed int)outlen - 1; i >= 0; i--) { + out[i] = in & 0xff; + in = in >> 8; + } +} + +void u32_to_bytes(unsigned char *out, uint32_t in) { + out[0] = (unsigned char)(in >> 24); + out[1] = (unsigned char)(in >> 16); + out[2] = (unsigned char)(in >> 8); + out[3] = (unsigned char)in; +} + +/** + * Converts the inlen bytes in 'in' from big-endian byte order to an integer. + */ +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { + unsigned long long retval = 0; + unsigned int i; + + for (i = 0; i < inlen; i++) { + retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); + } + return retval; +} + +/** + * Computes a root node given a leaf and an auth path. + * Expects address to be complete other than the tree_height and tree_index. + */ +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]) { + uint32_t i; + unsigned char buffer[2 * SPX_N]; + + /* If leaf_idx is odd (last bit = 1), current path element is a right child + and auth_path has to go left. Otherwise it is the other way around. */ + if (leaf_idx & 1) { + memcpy(buffer + SPX_N, leaf, SPX_N); + memcpy(buffer, auth_path, SPX_N); + } else { + memcpy(buffer, leaf, SPX_N); + memcpy(buffer + SPX_N, auth_path, SPX_N); + } + auth_path += SPX_N; + + for (i = 0; i < tree_height - 1; i++) { + leaf_idx >>= 1; + idx_offset >>= 1; + /* Set the address of the node we're creating. */ + set_tree_height(addr, i + 1); + set_tree_index(addr, leaf_idx + idx_offset); + + /* Pick the right or left neighbor, depending on parity of the node. */ + if (leaf_idx & 1) { + thash(buffer + SPX_N, buffer, 2, ctx, addr); + memcpy(buffer, auth_path, SPX_N); + } else { + thash(buffer, buffer, 2, ctx, addr); + memcpy(buffer + SPX_N, auth_path, SPX_N); + } + auth_path += SPX_N; + } + + /* The last iteration is exceptional; we do not copy an auth_path node. */ + leaf_idx >>= 1; + idx_offset >>= 1; + set_tree_height(addr, tree_height); + set_tree_index(addr, leaf_idx + idx_offset); + thash(root, buffer, 2, ctx, addr); +} + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx * /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]) { + PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); + PQCLEAN_VLA(unsigned int, heights, tree_height + 1); + unsigned int offset = 0; + uint32_t idx; + uint32_t tree_idx; + + for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { + /* Add the next leaf node to the stack. */ + gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); + offset++; + heights[offset - 1] = 0; + + /* If this is a node we need for the auth path.. */ + if ((leaf_idx ^ 0x1) == idx) { + memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); + } + + /* While the top-most nodes are of equal height.. */ + while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { + /* Compute index of the new node, in the next layer. */ + tree_idx = (idx >> (heights[offset - 1] + 1)); + + /* Set the address of the node we're creating. */ + set_tree_height(tree_addr, heights[offset - 1] + 1); + set_tree_index(tree_addr, + tree_idx + (idx_offset >> (heights[offset - 1] + 1))); + /* Hash the top-most nodes from the stack together. */ + thash(stack + (offset - 2)*SPX_N, + stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); + offset--; + /* Note that the top-most node is now one layer higher. */ + heights[offset - 1]++; + + /* If this is a node we need for the auth path.. */ + if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { + memcpy(auth_path + heights[offset - 1]*SPX_N, + stack + (offset - 1)*SPX_N, SPX_N); + } + } + } + memcpy(root, stack, SPX_N); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/utils.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/utils.h new file mode 100644 index 0000000000..64f5d5a53a --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/utils.h @@ -0,0 +1,58 @@ +#ifndef SPX_UTILS_H +#define SPX_UTILS_H + +#include + +#include "compat.h" +#include "context.h" +#include "params.h" + + +/* To support MSVC use alloca() instead of VLAs. See #20. */ + + +/** + * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. + */ +#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in); +#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) +void u32_to_bytes(unsigned char *out, uint32_t in); + +/** + * Converts the inlen bytes in 'in' from big-endian byte order to an integer. + */ +#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); + +/** + * Computes a root node given a leaf and an auth path. + * Expects address to be complete other than the tree_height and tree_index. + */ +#define compute_root SPX_NAMESPACE(compute_root) +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]); + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +#define treehash SPX_NAMESPACE(treehash) +void treehash(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx *ctx /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]); + + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/utilsx1.c b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/utilsx1.c new file mode 100644 index 0000000000..fccb69b35d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/utilsx1.c @@ -0,0 +1,100 @@ +#include + +#include "utilsx1.h" + +#include "address.h" +#include "params.h" +#include "thash.h" +#include "utils.h" + +/* + * Generate the entire Merkle tree, computing the authentication path for + * leaf_idx, and the resulting root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) + * + * This expects tree_addr to be initialized to the addr structures for the + * Merkle tree nodes + * + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + * + * This works by using the standard Merkle tree building algorithm, + */ +void treehashx1(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, + uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* Where to write the leaves */, + const spx_ctx * /* ctx */, + uint32_t idx, void *info), + uint32_t tree_addr[8], + void *info) { + /* This is where we keep the intermediate nodes */ + PQCLEAN_VLA(uint8_t, stack, tree_height * SPX_N); + + uint32_t idx; + uint32_t max_idx = (uint32_t)((1 << tree_height) - 1); + for (idx = 0;; idx++) { + unsigned char current[2 * SPX_N]; /* Current logical node is at */ + /* index[SPX_N]. We do this to minimize the number of copies */ + /* needed during a thash */ + gen_leaf( ¤t[SPX_N], ctx, idx + idx_offset, + info ); + + /* Now combine the freshly generated right node with previously */ + /* generated left ones */ + uint32_t internal_idx_offset = idx_offset; + uint32_t internal_idx = idx; + uint32_t internal_leaf = leaf_idx; + uint32_t h; /* The height we are in the Merkle tree */ + for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { + + /* Check if we hit the top of the tree */ + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[SPX_N], SPX_N ); + return; + } + + /* + * Check if the node we have is a part of the + * authentication path; if it is, write it out + */ + if ((internal_idx ^ internal_leaf) == 0x01) { + memcpy( &auth_path[ h * SPX_N ], + ¤t[SPX_N], + SPX_N ); + } + + /* + * Check if we're at a left child; if so, stop going up the stack + * Exception: if we've reached the end of the tree, keep on going + * (so we combine the last 4 nodes into the one root node in two + * more iterations) + */ + if ((internal_idx & 1) == 0 && idx < max_idx) { + break; + } + + /* Ok, we're at a right node */ + /* Now combine the left and right logical nodes together */ + + /* Set the address of the node we're creating. */ + internal_idx_offset >>= 1; + set_tree_height(tree_addr, h + 1); + set_tree_index(tree_addr, internal_idx / 2 + internal_idx_offset ); + + unsigned char *left = &stack[h * SPX_N]; + memcpy( ¤t[0], left, SPX_N ); + thash( ¤t[1 * SPX_N], + ¤t[0 * SPX_N], + 2, ctx, tree_addr); + } + + /* We've hit a left child; save the current for when we get the */ + /* corresponding right right */ + memcpy( &stack[h * SPX_N], ¤t[SPX_N], SPX_N); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/utilsx1.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/utilsx1.h new file mode 100644 index 0000000000..e911d17d53 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/utilsx1.h @@ -0,0 +1,27 @@ +#ifndef SPX_UTILSX4_H +#define SPX_UTILSX4_H + +#include + +#include "context.h" +#include "params.h" + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +#define treehashx1 SPX_NAMESPACE(treehashx1) +void treehashx1(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* Where to write the leaf */, + const spx_ctx * /* ctx */, + uint32_t addr_idx, void *info), + uint32_t tree_addrx4[8], void *info); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/wots.c b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/wots.c new file mode 100644 index 0000000000..249717aaa8 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/wots.c @@ -0,0 +1,108 @@ +#include +#include + +#include "wots.h" +#include "wotsx1.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "thash.h" +#include "utils.h" +#include "utilsx1.h" + +// TODO clarify address expectations, and make them more uniform. +// TODO i.e. do we expect types to be set already? +// TODO and do we expect modifications or copies? + +/** + * Computes the chaining function. + * out and in have to be n-byte arrays. + * + * Interprets in as start-th value of the chain. + * addr has to contain the address of the chain. + */ +static void gen_chain(unsigned char *out, const unsigned char *in, + unsigned int start, unsigned int steps, + const spx_ctx *ctx, uint32_t addr[8]) { + uint32_t i; + + /* Initialize out with the value at position 'start'. */ + memcpy(out, in, SPX_N); + + /* Iterate 'steps' calls to the hash function. */ + for (i = start; i < (start + steps) && i < SPX_WOTS_W; i++) { + set_hash_addr(addr, i); + thash(out, out, 1, ctx, addr); + } +} + +/** + * base_w algorithm as described in draft. + * Interprets an array of bytes as integers in base w. + * This only works when log_w is a divisor of 8. + */ +static void base_w(unsigned int *output, const int out_len, + const unsigned char *input) { + int in = 0; + int out = 0; + unsigned char total = 0; + int bits = 0; + int consumed; + + for (consumed = 0; consumed < out_len; consumed++) { + if (bits == 0) { + total = input[in]; + in++; + bits += 8; + } + bits -= SPX_WOTS_LOGW; + output[out] = (total >> bits) & (SPX_WOTS_W - 1); + out++; + } +} + +/* Computes the WOTS+ checksum over a message (in base_w). */ +static void wots_checksum(unsigned int *csum_base_w, + const unsigned int *msg_base_w) { + unsigned int csum = 0; + unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; + unsigned int i; + + /* Compute checksum. */ + for (i = 0; i < SPX_WOTS_LEN1; i++) { + csum += SPX_WOTS_W - 1 - msg_base_w[i]; + } + + /* Convert checksum to base_w. */ + /* Make sure expected empty zero bits are the least significant bits. */ + csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); + ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); + base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); +} + +/* Takes a message and derives the matching chain lengths. */ +void chain_lengths(unsigned int *lengths, const unsigned char *msg) { + base_w(lengths, SPX_WOTS_LEN1, msg); + wots_checksum(lengths + SPX_WOTS_LEN1, lengths); +} + +/** + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. + * + * Writes the computed public key to 'pk'. + */ +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]) { + unsigned int lengths[SPX_WOTS_LEN]; + uint32_t i; + + chain_lengths(lengths, msg); + + for (i = 0; i < SPX_WOTS_LEN; i++) { + set_chain_addr(addr, i); + gen_chain(pk + i * SPX_N, sig + i * SPX_N, + lengths[i], SPX_WOTS_W - 1 - lengths[i], ctx, addr); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/wots.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/wots.h new file mode 100644 index 0000000000..4e7692eeef --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/wots.h @@ -0,0 +1,25 @@ +#ifndef SPX_WOTS_H +#define SPX_WOTS_H + +#include + +#include "context.h" +#include "params.h" + +/** + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. + * + * Writes the computed public key to 'pk'. + */ +#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]); + +/* + * Compute the chain lengths needed for a given message hash + */ +#define chain_lengths SPX_NAMESPACE(chain_lengths) +void chain_lengths(unsigned int *lengths, const unsigned char *msg); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/wotsx1.c b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/wotsx1.c new file mode 100644 index 0000000000..3adec78dfb --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/wotsx1.c @@ -0,0 +1,76 @@ +#include +#include + +#include "wots.h" +#include "wotsx1.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "thash.h" +#include "utils.h" + +/* + * This generates a WOTS public key + * It also generates the WOTS signature if leaf_info indicates + * that we're signing with this WOTS key + */ +void wots_gen_leafx1(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info) { + struct leaf_info_x1 *info = v_info; + uint32_t *leaf_addr = info->leaf_addr; + uint32_t *pk_addr = info->pk_addr; + unsigned int i, k; + unsigned char pk_buffer[ SPX_WOTS_BYTES ]; + unsigned char *buffer; + uint32_t wots_k_mask; + + if (leaf_idx == info->wots_sign_leaf) { + /* We're traversing the leaf that's signing; generate the WOTS */ + /* signature */ + wots_k_mask = 0; + } else { + /* Nope, we're just generating pk's; turn off the signature logic */ + wots_k_mask = (uint32_t)~0; + } + + set_keypair_addr( leaf_addr, leaf_idx ); + set_keypair_addr( pk_addr, leaf_idx ); + + for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { + uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k to */ + /* the step if we're generating a signature, ~0 if we're not */ + + /* Start with the secret seed */ + set_chain_addr(leaf_addr, i); + set_hash_addr(leaf_addr, 0); + set_type(leaf_addr, SPX_ADDR_TYPE_WOTSPRF); + + prf_addr(buffer, ctx, leaf_addr); + + set_type(leaf_addr, SPX_ADDR_TYPE_WOTS); + + /* Iterate down the WOTS chain */ + for (k = 0;; k++) { + /* Check if this is the value that needs to be saved as a */ + /* part of the WOTS signature */ + if (k == wots_k) { + memcpy( info->wots_sig + i * SPX_N, buffer, SPX_N ); + } + + /* Check if we hit the top of the chain */ + if (k == SPX_WOTS_W - 1) { + break; + } + + /* Iterate one step on the chain */ + set_hash_addr(leaf_addr, k); + + thash(buffer, buffer, 1, ctx, leaf_addr); + } + } + + /* Do the final thash to generate the public keys */ + thash(dest, pk_buffer, SPX_WOTS_LEN, ctx, pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/wotsx1.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/wotsx1.h new file mode 100644 index 0000000000..e617929f96 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/wotsx1.h @@ -0,0 +1,39 @@ +#ifndef WOTSX1_H_ +#define WOTSX1_H_ + +#include + +#include "context.h" +#include "params.h" + +/* + * This is here to provide an interface to the internal wots_gen_leafx1 + * routine. While this routine is not referenced in the package outside of + * wots.c, it is called from the stand-alone benchmark code to characterize + * the performance + */ +struct leaf_info_x1 { + unsigned char *wots_sig; + uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ + uint32_t *wots_steps; + uint32_t leaf_addr[8]; + uint32_t pk_addr[8]; +}; + +/* Macro to set the leaf_info to something 'benign', that is, it would */ +/* run with the same time as it does during the real signing process */ +/* Used only by the benchmark code */ +#define INITIALIZE_LEAF_INFO_X1(info, addr, step_buffer) { \ + (info).wots_sig = 0; \ + (info).wots_sign_leaf = ~0; \ + (info).wots_steps = step_buffer; \ + memcpy( &(info).leaf_addr[0], (addr), 32 ); \ + memcpy( &(info).pk_addr[0], (addr), 32 ); \ + } + +#define wots_gen_leafx1 SPX_NAMESPACE(wots_gen_leafx1) +void wots_gen_leafx1(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info); + +#endif /* WOTSX1_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/LICENSE b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/LICENSE new file mode 100644 index 0000000000..670154e353 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/LICENSE @@ -0,0 +1,116 @@ +CC0 1.0 Universal + +Statement of Purpose + +The laws of most jurisdictions throughout the world automatically confer +exclusive Copyright and Related Rights (defined below) upon the creator and +subsequent owner(s) (each and all, an "owner") of an original work of +authorship and/or a database (each, a "Work"). + +Certain owners wish to permanently relinquish those rights to a Work for the +purpose of contributing to a commons of creative, cultural and scientific +works ("Commons") that the public can reliably and without fear of later +claims of infringement build upon, modify, incorporate in other works, reuse +and redistribute as freely as possible in any form whatsoever and for any +purposes, including without limitation commercial purposes. These owners may +contribute to the Commons to promote the ideal of a free culture and the +further production of creative, cultural and scientific works, or to gain +reputation or greater distribution for their Work in part through the use and +efforts of others. + +For these and/or other purposes and motivations, and without any expectation +of additional consideration or compensation, the person associating CC0 with a +Work (the "Affirmer"), to the extent that he or she is an owner of Copyright +and Related Rights in the Work, voluntarily elects to apply CC0 to the Work +and publicly distribute the Work under its terms, with knowledge of his or her +Copyright and Related Rights in the Work and the meaning and intended legal +effect of CC0 on those rights. + +1. Copyright and Related Rights. A Work made available under CC0 may be +protected by copyright and related or neighboring rights ("Copyright and +Related Rights"). Copyright and Related Rights include, but are not limited +to, the following: + + i. the right to reproduce, adapt, distribute, perform, display, communicate, + and translate a Work; + + ii. moral rights retained by the original author(s) and/or performer(s); + + iii. publicity and privacy rights pertaining to a person's image or likeness + depicted in a Work; + + iv. rights protecting against unfair competition in regards to a Work, + subject to the limitations in paragraph 4(a), below; + + v. rights protecting the extraction, dissemination, use and reuse of data in + a Work; + + vi. database rights (such as those arising under Directive 96/9/EC of the + European Parliament and of the Council of 11 March 1996 on the legal + protection of databases, and under any national implementation thereof, + including any amended or successor version of such directive); and + + vii. other similar, equivalent or corresponding rights throughout the world + based on applicable law or treaty, and any national implementations thereof. + +2. Waiver. To the greatest extent permitted by, but not in contravention of, +applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and +unconditionally waives, abandons, and surrenders all of Affirmer's Copyright +and Related Rights and associated claims and causes of action, whether now +known or unknown (including existing as well as future claims and causes of +action), in the Work (i) in all territories worldwide, (ii) for the maximum +duration provided by applicable law or treaty (including future time +extensions), (iii) in any current or future medium and for any number of +copies, and (iv) for any purpose whatsoever, including without limitation +commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes +the Waiver for the benefit of each member of the public at large and to the +detriment of Affirmer's heirs and successors, fully intending that such Waiver +shall not be subject to revocation, rescission, cancellation, termination, or +any other legal or equitable action to disrupt the quiet enjoyment of the Work +by the public as contemplated by Affirmer's express Statement of Purpose. + +3. Public License Fallback. Should any part of the Waiver for any reason be +judged legally invalid or ineffective under applicable law, then the Waiver +shall be preserved to the maximum extent permitted taking into account +Affirmer's express Statement of Purpose. In addition, to the extent the Waiver +is so judged Affirmer hereby grants to each affected person a royalty-free, +non transferable, non sublicensable, non exclusive, irrevocable and +unconditional license to exercise Affirmer's Copyright and Related Rights in +the Work (i) in all territories worldwide, (ii) for the maximum duration +provided by applicable law or treaty (including future time extensions), (iii) +in any current or future medium and for any number of copies, and (iv) for any +purpose whatsoever, including without limitation commercial, advertising or +promotional purposes (the "License"). The License shall be deemed effective as +of the date CC0 was applied by Affirmer to the Work. Should any part of the +License for any reason be judged legally invalid or ineffective under +applicable law, such partial invalidity or ineffectiveness shall not +invalidate the remainder of the License, and in such case Affirmer hereby +affirms that he or she will not (i) exercise any of his or her remaining +Copyright and Related Rights in the Work or (ii) assert any associated claims +and causes of action with respect to the Work, in either case contrary to +Affirmer's express Statement of Purpose. + +4. Limitations and Disclaimers. + + a. No trademark or patent rights held by Affirmer are waived, abandoned, + surrendered, licensed or otherwise affected by this document. + + b. Affirmer offers the Work as-is and makes no representations or warranties + of any kind concerning the Work, express, implied, statutory or otherwise, + including without limitation warranties of title, merchantability, fitness + for a particular purpose, non infringement, or the absence of latent or + other defects, accuracy, or the present or absence of errors, whether or not + discoverable, all to the greatest extent permissible under applicable law. + + c. Affirmer disclaims responsibility for clearing rights of other persons + that may apply to the Work or any use thereof, including without limitation + any person's Copyright and Related Rights in the Work. Further, Affirmer + disclaims responsibility for obtaining any necessary consents, permissions + or other rights required for any use of the Work. + + d. Affirmer understands and acknowledges that Creative Commons is not a + party to this document and has no duty or obligation with respect to this + CC0 or use of the Work. + +For more information, please see + diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/address.c b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/address.c new file mode 100644 index 0000000000..b956e9cb29 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/address.c @@ -0,0 +1,91 @@ +#include +#include + +#include "address.h" +#include "params.h" +#include "utils.h" + +/* + * Specify which level of Merkle tree (the "layer") we're working on + */ +void set_layer_addr(uint32_t addr[8], uint32_t layer) { + ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; +} + +/* + * Specify which Merkle tree within the level (the "tree address") we're working on + */ +void set_tree_addr(uint32_t addr[8], uint64_t tree) { + ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); +} + +/* + * Specify the reason we'll use this address structure for, that is, what + * hash will we compute with it. This is used so that unrelated types of + * hashes don't accidentally get the same address structure. The type will be + * one of the SPX_ADDR_TYPE constants + */ +void set_type(uint32_t addr[8], uint32_t type) { + ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; +} + +/* + * Copy the layer and tree fields of the address structure. This is used + * when we're doing multiple types of hashes within the same Merkle tree + */ +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); +} + +/* These functions are used for OTS addresses. */ + +/* + * Specify which Merkle leaf we're working on; that is, which OTS keypair + * we're talking about. + */ +void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { + ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; +} + +/* + * Copy the layer, tree and keypair fields of the address structure. This is + * used when we're doing multiple things within the same OTS keypair + */ +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); + ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; +} + +/* + * Specify which Merkle chain within the OTS we're working with + * (the chain address) + */ +void set_chain_addr(uint32_t addr[8], uint32_t chain) { + ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; +} + +/* + * Specify where in the Merkle chain we are +* (the hash address) + */ +void set_hash_addr(uint32_t addr[8], uint32_t hash) { + ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; +} + +/* These functions are used for all hash tree addresses (including FORS). */ + +/* + * Specify the height of the node in the Merkle/FORS tree we are in + * (the tree height) + */ +void set_tree_height(uint32_t addr[8], uint32_t tree_height) { + ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; +} + +/* + * Specify the distance from the left edge of the node in the Merkle/FORS tree + * (the tree index) + */ +void set_tree_index(uint32_t addr[8], uint32_t tree_index) { + u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/address.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/address.h new file mode 100644 index 0000000000..24a84eb40c --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/address.h @@ -0,0 +1,52 @@ +#ifndef SPX_ADDRESS_H +#define SPX_ADDRESS_H + +#include + +#include "params.h" + +/* The hash types that are passed to set_type */ +#define SPX_ADDR_TYPE_WOTS 0 +#define SPX_ADDR_TYPE_WOTSPK 1 +#define SPX_ADDR_TYPE_HASHTREE 2 +#define SPX_ADDR_TYPE_FORSTREE 3 +#define SPX_ADDR_TYPE_FORSPK 4 +#define SPX_ADDR_TYPE_WOTSPRF 5 +#define SPX_ADDR_TYPE_FORSPRF 6 + +#define set_layer_addr SPX_NAMESPACE(set_layer_addr) +void set_layer_addr(uint32_t addr[8], uint32_t layer); + +#define set_tree_addr SPX_NAMESPACE(set_tree_addr) +void set_tree_addr(uint32_t addr[8], uint64_t tree); + +#define set_type SPX_NAMESPACE(set_type) +void set_type(uint32_t addr[8], uint32_t type); + +/* Copies the layer and tree part of one address into the other */ +#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); + +/* These functions are used for WOTS and FORS addresses. */ + +#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) +void set_keypair_addr(uint32_t addr[8], uint32_t keypair); + +#define set_chain_addr SPX_NAMESPACE(set_chain_addr) +void set_chain_addr(uint32_t addr[8], uint32_t chain); + +#define set_hash_addr SPX_NAMESPACE(set_hash_addr) +void set_hash_addr(uint32_t addr[8], uint32_t hash); + +#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); + +/* These functions are used for all hash tree addresses (including FORS). */ + +#define set_tree_height SPX_NAMESPACE(set_tree_height) +void set_tree_height(uint32_t addr[8], uint32_t tree_height); + +#define set_tree_index SPX_NAMESPACE(set_tree_index) +void set_tree_index(uint32_t addr[8], uint32_t tree_index); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/api.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/api.h new file mode 100644 index 0000000000..3e80e17f5d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/api.h @@ -0,0 +1,77 @@ +#ifndef PQCLEAN_SPHINCSSHAKE192FSIMPLE_AARCH64_API_H +#define PQCLEAN_SPHINCSSHAKE192FSIMPLE_AARCH64_API_H + +#include +#include + +#define PQCLEAN_SPHINCSSHAKE192FSIMPLE_AARCH64_CRYPTO_ALGNAME "SPHINCS+-shake-192f-simple" + +#define PQCLEAN_SPHINCSSHAKE192FSIMPLE_AARCH64_CRYPTO_SECRETKEYBYTES 96 +#define PQCLEAN_SPHINCSSHAKE192FSIMPLE_AARCH64_CRYPTO_PUBLICKEYBYTES 48 +#define PQCLEAN_SPHINCSSHAKE192FSIMPLE_AARCH64_CRYPTO_BYTES 35664 + +#define PQCLEAN_SPHINCSSHAKE192FSIMPLE_AARCH64_CRYPTO_SEEDBYTES 72 + +/* + * Returns the length of a secret key, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE192FSIMPLE_AARCH64_crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE192FSIMPLE_AARCH64_crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE192FSIMPLE_AARCH64_crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE192FSIMPLE_AARCH64_crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +int PQCLEAN_SPHINCSSHAKE192FSIMPLE_AARCH64_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +int PQCLEAN_SPHINCSSHAKE192FSIMPLE_AARCH64_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +int PQCLEAN_SPHINCSSHAKE192FSIMPLE_AARCH64_crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +int PQCLEAN_SPHINCSSHAKE192FSIMPLE_AARCH64_crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, + const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +int PQCLEAN_SPHINCSSHAKE192FSIMPLE_AARCH64_crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +int PQCLEAN_SPHINCSSHAKE192FSIMPLE_AARCH64_crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/context.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/context.h new file mode 100644 index 0000000000..6e0a33f3b7 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/context.h @@ -0,0 +1,19 @@ +#ifndef SPX_CONTEXT_H +#define SPX_CONTEXT_H + +#include + +#include "params.h" + +typedef struct { + uint8_t pub_seed[SPX_N]; + uint8_t sk_seed[SPX_N]; +} spx_ctx; + +#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) +void initialize_hash_function(spx_ctx *ctx); + +#define free_hash_function SPX_NAMESPACE(free_hash_function) +void free_hash_function(spx_ctx *ctx); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/context_shake.c b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/context_shake.c new file mode 100644 index 0000000000..9614a103d3 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/context_shake.c @@ -0,0 +1,12 @@ +#include "context.h" + +/* For SHAKE256, there is no immediate reason to initialize at the start, + so this function is an empty operation. */ +void initialize_hash_function(spx_ctx *ctx) { + (void)ctx; /* Suppress an 'unused parameter' warning. */ +} + +// in case the hash function api is heap-based. +void free_hash_function(spx_ctx *ctx) { + (void)ctx; +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/f1600x2.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/f1600x2.h new file mode 100644 index 0000000000..70d1af9f14 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/f1600x2.h @@ -0,0 +1,11 @@ +#ifndef SPX_F1600X2_H +#define SPX_F1600X2_H + +#include + +extern uint64_t f1600_RC[24]; +extern void _f1600x2(uint64_t *a, uint64_t *rc); + +#define f1600x2(s) do {_f1600x2((s), f1600_RC);} while(0) + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/f1600x2.s b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/f1600x2.s new file mode 100644 index 0000000000..640ed791ed --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/f1600x2.s @@ -0,0 +1,143 @@ +# From https://github.com/bwesterb/armed-keccak + +.macro round + # Execute theta, but without xoring into the state yet. + # Compute parities p[i] = a[i] ^ a[5+i] ^ ... ^ a[20+i]. + eor3.16b v25, v0, v5, v10 + eor3.16b v26, v1, v6, v11 + eor3.16b v27, v2, v7, v12 + eor3.16b v28, v3, v8, v13 + eor3.16b v29, v4, v9, v14 + + eor3.16b v25, v25, v15, v20 + eor3.16b v26, v26, v16, v21 + eor3.16b v27, v27, v17, v22 + eor3.16b v28, v28, v18, v23 + eor3.16b v29, v29, v19, v24 + + # d[0] = rotl(p[1], 1) ^ p[4] + rax1.2d v30, v29, v26 + # d[3] = rotl(p[4], 1) ^ p[2] + rax1.2d v29, v27, v29 + # d[1] = rotl(p[2], 1) ^ p[0] + rax1.2d v27, v25, v27 + # d[4] = rotl(p[0], 1) ^ p[3] + rax1.2d v25, v28, v25 + # d[2] = rotl(p[3], 1) ^ p[1] + rax1.2d v28, v26, v28 + + # Xor parities from step theta into the state at the same time + # as executing rho and pi. + eor.16b v0, v0, v30 + mov.16b v31, v1 + xar.2d v1, v6, v27, 20 + xar.2d v6, v9, v25, 44 + xar.2d v9, v22, v28, 3 + xar.2d v22, v14, v25, 25 + xar.2d v14, v20, v30, 46 + xar.2d v20, v2, v28, 2 + xar.2d v2, v12, v28, 21 + xar.2d v12, v13, v29, 39 + xar.2d v13, v19, v25, 56 + xar.2d v19, v23, v29, 8 + xar.2d v23, v15, v30, 23 + xar.2d v15, v4, v25, 37 + xar.2d v4, v24, v25, 50 + xar.2d v24, v21, v27, 62 + xar.2d v21, v8, v29, 9 + xar.2d v8, v16, v27, 19 + xar.2d v16, v5, v30, 28 + xar.2d v5, v3, v29, 36 + xar.2d v3, v18, v29, 43 + xar.2d v18, v17, v28, 49 + xar.2d v17, v11, v27, 54 + xar.2d v11, v7, v28, 58 + xar.2d v7, v10, v30, 61 + xar.2d v10, v31, v27, 63 + + # Chi + bcax.16b v25, v0, v2, v1 + bcax.16b v26, v1, v3, v2 + bcax.16b v2, v2, v4, v3 + bcax.16b v3, v3, v0, v4 + bcax.16b v4, v4, v1, v0 + mov.16b v0, v25 + mov.16b v1, v26 + + bcax.16b v25, v5, v7, v6 + bcax.16b v26, v6, v8, v7 + bcax.16b v7, v7, v9, v8 + bcax.16b v8, v8, v5, v9 + bcax.16b v9, v9, v6, v5 + mov.16b v5, v25 + mov.16b v6, v26 + + bcax.16b v25, v10, v12, v11 + bcax.16b v26, v11, v13, v12 + bcax.16b v12, v12, v14, v13 + bcax.16b v13, v13, v10, v14 + bcax.16b v14, v14, v11, v10 + mov.16b v10, v25 + mov.16b v11, v26 + + bcax.16b v25, v15, v17, v16 + bcax.16b v26, v16, v18, v17 + bcax.16b v17, v17, v19, v18 + bcax.16b v18, v18, v15, v19 + bcax.16b v19, v19, v16, v15 + mov.16b v15, v25 + mov.16b v16, v26 + + bcax.16b v25, v20, v22, v21 + bcax.16b v26, v21, v23, v22 + bcax.16b v22, v22, v24, v23 + bcax.16b v23, v23, v20, v24 + bcax.16b v24, v24, v21, v20 + mov.16b v20, v25 + mov.16b v21, v26 + + # iota + ld1r {v25.2d}, [x1], #8 + eor.16b v0, v0, v25 +.endm + +.align 4 +.global __f1600x2 +__f1600x2: + stp d8, d9, [sp,#-16]! + stp d10, d11, [sp,#-16]! + stp d12, d13, [sp,#-16]! + stp d14, d15, [sp,#-16]! + + mov x2, x0 + mov x3, #24 + + ld1.2d {v0, v1, v2, v3}, [x0], #64 + ld1.2d {v4, v5, v6, v7}, [x0], #64 + ld1.2d {v8, v9, v10, v11}, [x0], #64 + ld1.2d {v12, v13, v14, v15}, [x0], #64 + ld1.2d {v16, v17, v18, v19}, [x0], #64 + ld1.2d {v20, v21, v22, v23}, [x0], #64 + ld1.2d {v24}, [x0] + +loop: + round + + subs x3, x3, #1 + cbnz x3, loop + + mov x0, x2 + st1.2d {v0, v1, v2, v3}, [x0], #64 + st1.2d {v4, v5, v6, v7}, [x0], #64 + st1.2d {v8, v9, v10, v11}, [x0], #64 + st1.2d {v12, v13, v14, v15}, [x0], #64 + st1.2d {v16, v17, v18, v19}, [x0], #64 + st1.2d {v20, v21, v22, v23}, [x0], #64 + st1.2d {v24}, [x0] + + ldp d14, d15, [sp], #16 + ldp d12, d13, [sp], #16 + ldp d10, d11, [sp], #16 + ldp d8, d9, [sp], #16 + + ret lr diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/f1600x2_const.c b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/f1600x2_const.c new file mode 100644 index 0000000000..e49c0ba149 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/f1600x2_const.c @@ -0,0 +1,30 @@ +#include "f1600x2.h" + +uint64_t f1600_RC[24] = { + 0x0000000000000001, + 0x0000000000008082, + 0x800000000000808A, + 0x8000000080008000, + 0x000000000000808B, + 0x0000000080000001, + 0x8000000080008081, + 0x8000000000008009, + 0x000000000000008A, + 0x0000000000000088, + 0x0000000080008009, + 0x000000008000000A, + 0x000000008000808B, + 0x800000000000008B, + 0x8000000000008089, + 0x8000000000008003, + 0x8000000000008002, + 0x8000000000000080, + 0x000000000000800A, + 0x800000008000000A, + 0x8000000080008081, + 0x8000000000008080, + 0x0000000080000001, + 0x8000000080008008, +}; + + diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/fips202x2.c b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/fips202x2.c new file mode 100644 index 0000000000..4718c343bc --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/fips202x2.c @@ -0,0 +1,148 @@ +#include +#include + +#include "fips202x2.h" +#include "f1600x2.h" +#include "fips202.h" + +uint64_t load64(const unsigned char *x) { + unsigned long long r = 0, i; + + for (i = 0; i < 8; ++i) { + r |= (unsigned long long)x[i] << 8 * i; + } + return r; +} + +void store64(uint8_t *x, uint64_t u) { + unsigned int i; + + for (i = 0; i < 8; ++i) { + x[i] = (uint8_t)u; + u >>= 8; + } +} + +static void keccak_absorb2x(uint64_t *s, + unsigned int r, + const unsigned char *m0, + const unsigned char *m1, + unsigned long long int mlen, + unsigned char p) { + unsigned long long i; + unsigned char t0[200]; + unsigned char t1[200]; + + while (mlen >= r) { + for (i = 0; i < r / 8; ++i) { + s[2 * i + 0] ^= load64(m0 + 8 * i); + s[2 * i + 1] ^= load64(m1 + 8 * i); + } + + f1600x2(s); + mlen -= r; + m0 += r; + m1 += r; + } + + for (i = 0; i < r; ++i) { + t0[i] = 0; + t1[i] = 0; + } + for (i = 0; i < mlen; ++i) { + t0[i] = m0[i]; + t1[i] = m1[i]; + } + + t0[i] = p; + t1[i] = p; + + t0[r - 1] |= 128; + t1[r - 1] |= 128; + + for (i = 0; i < r / 8; ++i) { + s[2 * i + 0] ^= load64(t0 + 8 * i); + s[2 * i + 1] ^= load64(t1 + 8 * i); + } +} + + +static void keccak_squeezeblocks2x(unsigned char *h0, + unsigned char *h1, + unsigned long long int nblocks, + uint64_t *s, + unsigned int r) { + unsigned int i; + + while (nblocks > 0) { + f1600x2(s); + for (i = 0; i < (r >> 3); i++) { + store64(h0 + 8 * i, s[2 * i + 0]); + store64(h1 + 8 * i, s[2 * i + 1]); + } + h0 += r; + h1 += r; + nblocks--; + } +} + + + +void shake128x2(unsigned char *out0, + unsigned char *out1, + unsigned long long outlen, + unsigned char *in0, + unsigned char *in1, + unsigned long long inlen) { + uint64_t s[50] = {0}; + unsigned char t0[SHAKE128_RATE]; + unsigned char t1[SHAKE128_RATE]; + unsigned int i; + + /* absorb 4 message of identical length in parallel */ + keccak_absorb2x(s, SHAKE128_RATE, in0, in1, inlen, 0x1F); + + /* Squeeze output */ + keccak_squeezeblocks2x(out0, out1, outlen / SHAKE128_RATE, s, SHAKE128_RATE); + + out0 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; + out1 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; + + if (outlen % SHAKE128_RATE) { + keccak_squeezeblocks2x(t0, t1, 1, s, SHAKE128_RATE); + for (i = 0; i < outlen % SHAKE128_RATE; i++) { + out0[i] = t0[i]; + out1[i] = t1[i]; + } + } +} + + +void shake256x2(unsigned char *out0, + unsigned char *out1, + unsigned long long outlen, + unsigned char *in0, + unsigned char *in1, + unsigned long long inlen) { + uint64_t s[50] = {0}; + unsigned char t0[SHAKE256_RATE]; + unsigned char t1[SHAKE256_RATE]; + unsigned int i; + + /* absorb 2 message of identical length in parallel */ + keccak_absorb2x(s, SHAKE256_RATE, in0, in1, inlen, 0x1F); + + /* Squeeze output */ + keccak_squeezeblocks2x(out0, out1, outlen / SHAKE256_RATE, s, SHAKE256_RATE); + + out0 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; + out1 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; + + if (outlen % SHAKE256_RATE) { + keccak_squeezeblocks2x(t0, t1, 1, s, SHAKE256_RATE); + for (i = 0; i < outlen % SHAKE256_RATE; i++) { + out0[i] = t0[i]; + out1[i] = t1[i]; + } + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/fips202x2.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/fips202x2.h new file mode 100644 index 0000000000..7ba58b35d8 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/fips202x2.h @@ -0,0 +1,24 @@ +#ifndef SPX_FIPS202X2_H +#define SPX_FIPS202X2_H + +#include + +uint64_t load64(const unsigned char *x); +void store64(uint8_t *x, uint64_t u); + + +void shake128x2(unsigned char *out0, + unsigned char *out1, + unsigned long long outlen, + unsigned char *in0, + unsigned char *in1, + unsigned long long inlen); + +void shake256x2(unsigned char *out0, + unsigned char *out1, + unsigned long long outlen, + unsigned char *in0, + unsigned char *in1, + unsigned long long inlen); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/fors.c b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/fors.c new file mode 100644 index 0000000000..39193d04e2 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/fors.c @@ -0,0 +1,191 @@ +#include +#include +#include + +#include "fors.h" + +#include "address.h" +#include "hash.h" +#include "hashx2.h" +#include "thash.h" +#include "thashx2.h" +#include "utils.h" +#include "utilsx2.h" + +static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + prf_addr(sk, ctx, fors_leaf_addr); +} + +static void fors_gen_skx2(unsigned char *sk0, + unsigned char *sk1, + const spx_ctx *ctx, + uint32_t fors_leaf_addrx2[2 * 8]) { + prf_addrx2(sk0, sk1, + ctx, fors_leaf_addrx2); +} + +static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, + const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + thash(leaf, sk, 1, ctx, fors_leaf_addr); +} + +static void fors_sk_to_leafx2(unsigned char *leaf0, + unsigned char *leaf1, + const unsigned char *sk0, + const unsigned char *sk1, + const spx_ctx *ctx, + uint32_t fors_leaf_addrx2[2 * 8]) { + thashx2(leaf0, leaf1, + sk0, sk1, + 1, ctx, fors_leaf_addrx2); +} + +struct fors_gen_leaf_info { + uint32_t leaf_addrx[2 * 8]; +}; + +static void fors_gen_leafx2(unsigned char *leaf, + const spx_ctx *ctx, + uint32_t addr_idx, void *info) { + struct fors_gen_leaf_info *fors_info = info; + uint32_t *fors_leaf_addrx2 = fors_info->leaf_addrx; + unsigned int j; + + /* Only set the parts that the caller doesn't set */ + for (j = 0; j < 2; j++) { + set_tree_index(fors_leaf_addrx2 + j * 8, addr_idx + j); + set_type(fors_leaf_addrx2 + j * 8, SPX_ADDR_TYPE_FORSPRF); + } + + fors_gen_skx2(leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + ctx, fors_leaf_addrx2); + + for (j = 0; j < 2; j++) { + set_type(fors_leaf_addrx2 + j * 8, SPX_ADDR_TYPE_FORSTREE); + } + + fors_sk_to_leafx2(leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + ctx, fors_leaf_addrx2); +} + +/** + * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + * Assumes indices has space for SPX_FORS_TREES integers. + */ +static void message_to_indices(uint32_t *indices, const unsigned char *m) { + unsigned int i, j; + unsigned int offset = 0; + + for (i = 0; i < SPX_FORS_TREES; i++) { + indices[i] = 0; + for (j = 0; j < SPX_FORS_HEIGHT; j++) { + indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); + offset++; + } + } +} + +/** + * Signs a message m, deriving the secret key from sk_seed and the FTS address. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + uint32_t fors_tree_addr[2 * 8] = {0}; + struct fors_gen_leaf_info fors_info = {0}; + uint32_t *fors_leaf_addr = fors_info.leaf_addrx; + uint32_t fors_pk_addr[8] = {0}; + uint32_t idx_offset; + unsigned int i; + + for (i = 0; i < 2; i++) { + copy_keypair_addr(fors_tree_addr + 8 * i, fors_addr); + set_type(fors_tree_addr + 8 * i, SPX_ADDR_TYPE_FORSTREE); + copy_keypair_addr(fors_leaf_addr + 8 * i, fors_addr); + } + copy_keypair_addr(fors_pk_addr, fors_addr); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); + + message_to_indices(indices, m); + + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); + + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + + /* Include the secret key part that produces the selected leaf node. */ + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); + fors_gen_sk(sig, ctx, fors_tree_addr); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + sig += SPX_N; + + /* Compute the authentication path for this leaf node. */ + treehashx2(roots + i * SPX_N, sig, ctx, + indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx2, + fors_tree_addr, &fors_info); + + sig += SPX_N * SPX_FORS_HEIGHT; + } + + /* Hash horizontally across all tree roots to derive the public key. */ + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); +} + +/** + * Derives the FORS public key from a signature. + * This can be used for verification by comparing to a known public key, or to + * subsequently verify a signature on the derived public key. The latter is the + * typical use-case when used as an FTS below an OTS in a hypertree. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + unsigned char leaf[SPX_N]; + uint32_t fors_tree_addr[8] = {0}; + uint32_t fors_pk_addr[8] = {0}; + uint32_t idx_offset; + unsigned int i; + + copy_keypair_addr(fors_tree_addr, fors_addr); + copy_keypair_addr(fors_pk_addr, fors_addr); + + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); + + message_to_indices(indices, m); + + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); + + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + + /* Derive the leaf from the included secret key part. */ + fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); + sig += SPX_N; + + /* Derive the corresponding root node of this tree. */ + compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, + sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); + sig += SPX_N * SPX_FORS_HEIGHT; + } + + /* Hash horizontally across all tree roots to derive the public key. */ + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/fors.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/fors.h new file mode 100644 index 0000000000..509140a178 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/fors.h @@ -0,0 +1,32 @@ +#ifndef SPX_FORS_H +#define SPX_FORS_H + +#include + +#include "context.h" +#include "params.h" + +/** + * Signs a message m, deriving the secret key from sk_seed and the FTS address. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +#define fors_sign SPX_NAMESPACE(fors_sign) +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); + +/** + * Derives the FORS public key from a signature. + * This can be used for verification by comparing to a known public key, or to + * subsequently verify a signature on the derived public key. The latter is the + * typical use-case when used as an FTS below an OTS in a hypertree. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/hash.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/hash.h new file mode 100644 index 0000000000..f7c87d4c3c --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/hash.h @@ -0,0 +1,28 @@ +#ifndef SPX_HASH_H +#define SPX_HASH_H + +#include +#include + +#include "context.h" +#include "params.h" + +#define prf_addr SPX_NAMESPACE(prf_addr) +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]); + +#define gen_message_random SPX_NAMESPACE(gen_message_random) +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); + +#define hash_message SPX_NAMESPACE(hash_message) +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); + + + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/hash_shake.c b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/hash_shake.c new file mode 100644 index 0000000000..ff5e7ec918 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/hash_shake.c @@ -0,0 +1,83 @@ +#include +#include + +#include "hash.h" + +#include "address.h" +#include "fips202.h" +#include "params.h" +#include "utils.h" + +/* + * Computes PRF(pk_seed, sk_seed, addr) + */ +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]) { + unsigned char buf[2 * SPX_N + SPX_ADDR_BYTES]; + + memcpy(buf, ctx->pub_seed, SPX_N); + memcpy(buf + SPX_N, addr, SPX_ADDR_BYTES); + memcpy(buf + SPX_N + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); + + shake256(out, SPX_N, buf, 2 * SPX_N + SPX_ADDR_BYTES); +} + +/** + * Computes the message-dependent randomness R, using a secret seed and an + * optional randomization value as well as the message. + */ +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { + (void)ctx; + shake256incctx s_inc; + + shake256_inc_init(&s_inc); + shake256_inc_absorb(&s_inc, sk_prf, SPX_N); + shake256_inc_absorb(&s_inc, optrand, SPX_N); + shake256_inc_absorb(&s_inc, m, mlen); + shake256_inc_finalize(&s_inc); + shake256_inc_squeeze(R, SPX_N, &s_inc); + shake256_inc_ctx_release(&s_inc); +} + +/** + * Computes the message hash using R, the public key, and the message. + * Outputs the message digest and the index of the leaf. The index is split in + * the tree index and the leaf index, for convenient copying to an address. + */ +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { + (void)ctx; +#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) +#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) +#define SPX_LEAF_BITS SPX_TREE_HEIGHT +#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) +#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) + + unsigned char buf[SPX_DGST_BYTES]; + unsigned char *bufp = buf; + shake256incctx s_inc; + + shake256_inc_init(&s_inc); + shake256_inc_absorb(&s_inc, R, SPX_N); + shake256_inc_absorb(&s_inc, pk, SPX_PK_BYTES); + shake256_inc_absorb(&s_inc, m, mlen); + shake256_inc_finalize(&s_inc); + shake256_inc_squeeze(buf, SPX_DGST_BYTES, &s_inc); + shake256_inc_ctx_release(&s_inc); + + memcpy(digest, bufp, SPX_FORS_MSG_BYTES); + bufp += SPX_FORS_MSG_BYTES; + + + *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); + *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); + bufp += SPX_TREE_BYTES; + + *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); + *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/hash_shakex2.c b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/hash_shakex2.c new file mode 100644 index 0000000000..99571916a2 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/hash_shakex2.c @@ -0,0 +1,52 @@ +#include +#include + +#include "hashx2.h" + +#include "address.h" +#include "f1600x2.h" +#include "fips202x2.h" +#include "params.h" + +/* + * 2-way parallel version of prf_addr; takes 2x as much input and output + */ +void prf_addrx2(unsigned char *out0, + unsigned char *out1, + const spx_ctx *ctx, + const uint32_t addrx2[2 * 8]) { + /* As we write and read only a few quadwords, it is more efficient to + * build and extract from the fourway SHAKE256 state by hand. */ + uint64_t state[50] = {0}; + + for (int i = 0; i < SPX_N / 8; i++) { + uint64_t x = load64(ctx->pub_seed + 8 * i); + state[2 * i] = x; + state[2 * i + 1] = x; + } + for (int i = 0; i < 4; i++) { + state[2 * (SPX_N / 8 + i)] = (((uint64_t)addrx2[1 + 2 * i]) << 32) + | (uint64_t)addrx2[2 * i]; + state[2 * (SPX_N / 8 + i) + 1] = (((uint64_t)addrx2[8 + 1 + 2 * i]) << 32) + | (uint64_t)addrx2[8 + 2 * i]; + } + for (int i = 0; i < SPX_N / 8; i++) { + uint64_t x = load64(ctx->sk_seed + 8 * i); + state[2 * (SPX_N / 8 + i + 4)] = x; + state[2 * (SPX_N / 8 + i + 4) + 1] = x; + } + + /* SHAKE domain separator and padding. */ + state[2 * (SPX_N / 4 + 4)] = 0x1f; + state[2 * (SPX_N / 4 + 4) + 1] = 0x1f; + + state[2 * 16] = 0x80ULL << 56; + state[2 * 16 + 1] = 0x80ULL << 56; + + f1600x2(state); + + for (int i = 0; i < SPX_N / 8; i++) { + store64(out0 + 8 * i, state[2 * i]); + store64(out1 + 8 * i, state[2 * i + 1]); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/hashx2.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/hashx2.h new file mode 100644 index 0000000000..99b8873a9b --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/hashx2.h @@ -0,0 +1,14 @@ +#ifndef SPX_HASHX2_H +#define SPX_HASHX2_H + +#include "context.h" +#include "params.h" +#include + +#define prf_addrx2 SPX_NAMESPACE(prf_addrx2) +void prf_addrx2(unsigned char *out0, + unsigned char *out1, + const spx_ctx *ctx, + const uint32_t addrx2[2 * 8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/merkle.c b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/merkle.c new file mode 100644 index 0000000000..c94ee23939 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/merkle.c @@ -0,0 +1,64 @@ +#include +#include + +#include "merkle.h" + +#include "address.h" +#include "params.h" +#include "utils.h" +#include "utilsx2.h" +#include "wots.h" +#include "wotsx2.h" + +/* + * This generates a Merkle signature (WOTS signature followed by the Merkle + * authentication path). + */ +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf) { + unsigned char *auth_path = sig + SPX_WOTS_BYTES; + uint32_t tree_addrx2[2 * 8] = { 0 }; + int j; + struct leaf_info_x2 info = { 0 }; + unsigned steps[ SPX_WOTS_LEN ]; + + info.wots_sig = sig; + chain_lengths(steps, root); + info.wots_steps = steps; + + for (j = 0; j < 2; j++) { + set_type(&tree_addrx2[8 * j], SPX_ADDR_TYPE_HASHTREE); + set_type(&info.leaf_addr[8 * j], SPX_ADDR_TYPE_WOTS); + set_type(&info.pk_addr[8 * j], SPX_ADDR_TYPE_WOTSPK); + copy_subtree_addr(&tree_addrx2[8 * j], tree_addr); + copy_subtree_addr(&info.leaf_addr[8 * j], wots_addr); + copy_subtree_addr(&info.pk_addr[8 * j], wots_addr); + } + + info.wots_sign_leaf = idx_leaf; + + treehashx2(root, auth_path, ctx, + idx_leaf, 0, + SPX_TREE_HEIGHT, + wots_gen_leafx2, + tree_addrx2, &info); +} + +/* Compute root node of the top-most subtree. */ +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { + /* We do not need the auth path in key generation, but it simplifies the + code to have just one treehash routine that computes both root and path + in one function. */ + unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; + uint32_t top_tree_addr[8] = {0}; + uint32_t wots_addr[8] = {0}; + + set_layer_addr(top_tree_addr, SPX_D - 1); + set_layer_addr(wots_addr, SPX_D - 1); + + merkle_sign(auth_path, root, ctx, + wots_addr, top_tree_addr, + ~0 /* ~0 means "don't bother generating an auth path */ ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/merkle.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/merkle.h new file mode 100644 index 0000000000..769cf2e970 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/merkle.h @@ -0,0 +1,21 @@ +#ifndef MERKLE_H_ +#define MERKLE_H_ + +#include + +#include "context.h" +#include "params.h" + +/* Generate a Merkle signature (WOTS signature followed by the Merkle */ +/* authentication path) */ +#define merkle_sign SPX_NAMESPACE(merkle_sign) +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf); + +/* Compute the root node of the top-most subtree. */ +#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); + +#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/nistapi.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/nistapi.h new file mode 100644 index 0000000000..3cb71afad4 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/nistapi.h @@ -0,0 +1,87 @@ +#ifndef SPX_API_H +#define SPX_API_H + +#include +#include + +#include "params.h" + +#define CRYPTO_ALGNAME "SPHINCS+" + +#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES +#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES +#define CRYPTO_BYTES SPX_BYTES +#define CRYPTO_SEEDBYTES (3*SPX_N) + +/* + * Returns the length of a secret key, in bytes + */ +#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) +size_t crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) +size_t crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) +size_t crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) +size_t crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +#define crypto_sign SPX_NAMESPACE(crypto_sign) +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/params.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/params.h new file mode 100644 index 0000000000..6a93983ca4 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/params.h @@ -0,0 +1,56 @@ +#ifndef SPX_PARAMS_H +#define SPX_PARAMS_H + +#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSSHAKE192FSIMPLE_AARCH64_##s + +/* Hash output length in bytes. */ +#define SPX_N 24 +/* Height of the hypertree. */ +#define SPX_FULL_HEIGHT 66 +/* Number of subtree layer. */ +#define SPX_D 22 +/* FORS tree dimensions. */ +#define SPX_FORS_HEIGHT 8 +#define SPX_FORS_TREES 33 +/* Winternitz parameter, */ +#define SPX_WOTS_W 16 + +/* The hash function is defined by linking a different hash.c file, as opposed + to setting a #define constant. */ + +/* For clarity */ +#define SPX_ADDR_BYTES 32 + +/* WOTS parameters. */ +#define SPX_WOTS_LOGW 4 + +#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) + +/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ +#define SPX_WOTS_LEN2 3 + +#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) +#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) +#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES + +/* Subtree size. */ +#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) + +//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT +// #error SPX_D should always divide SPX_FULL_HEIGHT +//#endif + +/* FORS parameters. */ +#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) +#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) +#define SPX_FORS_PK_BYTES SPX_N + +/* Resulting SPX sizes. */ +#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ + SPX_FULL_HEIGHT * SPX_N) +#define SPX_PK_BYTES (2 * SPX_N) +#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) + +#include "shake_offsets.h" + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/shake_offsets.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/shake_offsets.h new file mode 100644 index 0000000000..6b28d95d91 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/shake_offsets.h @@ -0,0 +1,21 @@ +#ifndef SHAKE_OFFSETS_H_ +#define SHAKE_OFFSETS_H_ + +/* + * Offsets of various fields in the address structure when we use SHAKE as + * the Sphincs+ hash function + */ + +#define SPX_OFFSET_LAYER 3 /* The byte used to specify the Merkle tree layer */ +#define SPX_OFFSET_TREE 8 /* The start of the 8 byte field used to specify the tree */ +#define SPX_OFFSET_TYPE 19 /* The byte used to specify the hash type (reason) */ +#define SPX_OFFSET_KP_ADDR2 22 /* The high byte used to specify the key pair (which one-time signature) */ +#define SPX_OFFSET_KP_ADDR1 23 /* The low byte used to specify the key pair */ +#define SPX_OFFSET_CHAIN_ADDR 27 /* The byte used to specify the chain address (which Winternitz chain) */ +#define SPX_OFFSET_HASH_ADDR 31 /* The byte used to specify the hash address (where in the Winternitz chain) */ +#define SPX_OFFSET_TREE_HGT 27 /* The byte used to specify the height of this node in the FORS or Merkle tree */ +#define SPX_OFFSET_TREE_INDEX 28 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ + +#define SPX_SHAKE 1 + +#endif /* SHAKE_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/sign.c b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/sign.c new file mode 100644 index 0000000000..9d0c7d1b22 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/sign.c @@ -0,0 +1,286 @@ +#include +#include +#include + +#include "address.h" +#include "context.h" +#include "fors.h" +#include "hash.h" +#include "merkle.h" +#include "nistapi.h" +#include "params.h" +#include "randombytes.h" +#include "thash.h" +#include "utils.h" +#include "wots.h" + +/* + * Returns the length of a secret key, in bytes + */ +size_t crypto_sign_secretkeybytes(void) { + return CRYPTO_SECRETKEYBYTES; +} + +/* + * Returns the length of a public key, in bytes + */ +size_t crypto_sign_publickeybytes(void) { + return CRYPTO_PUBLICKEYBYTES; +} + +/* + * Returns the length of a signature, in bytes + */ +size_t crypto_sign_bytes(void) { + return CRYPTO_BYTES; +} + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +size_t crypto_sign_seedbytes(void) { + return CRYPTO_SEEDBYTES; +} + +/* + * Generates an SPX key pair given a seed of length + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [PUB_SEED || root] + */ +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed) { + spx_ctx ctx; + + /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ + memcpy(sk, seed, CRYPTO_SEEDBYTES); + + memcpy(pk, sk + 2 * SPX_N, SPX_N); + + memcpy(ctx.pub_seed, pk, SPX_N); + memcpy(ctx.sk_seed, sk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + /* Compute root node of the top-most subtree. */ + merkle_gen_root(sk + 3 * SPX_N, &ctx); + + // cleanup + free_hash_function(&ctx); + + memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); + + return 0; +} + +/* + * Generates an SPX key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [PUB_SEED || root] + */ +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { + uint8_t seed[CRYPTO_SEEDBYTES]; + randombytes(seed, CRYPTO_SEEDBYTES); + crypto_sign_seed_keypair(pk, sk, seed); + + return 0; +} + +/** + * Returns an array containing a detached signature. + */ +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk) { + spx_ctx ctx; + + const uint8_t *sk_prf = sk + SPX_N; + const uint8_t *pk = sk + 2 * SPX_N; + + uint8_t optrand[SPX_N]; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t root[SPX_N]; + uint32_t i; + uint64_t tree; + uint32_t idx_leaf; + uint32_t wots_addr[8] = {0}; + uint32_t tree_addr[8] = {0}; + + memcpy(ctx.sk_seed, sk, SPX_N); + memcpy(ctx.pub_seed, pk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + + /* Optionally, signing can be made non-deterministic using optrand. + This can help counter side-channel attacks that would benefit from + getting a large number of traces when the signer uses the same nodes. */ + randombytes(optrand, SPX_N); + /* Compute the digest randomization value. */ + gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); + + /* Derive the message digest and leaf index from R, PK and M. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; + + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); + + /* Sign the message hash using FORS. */ + fors_sign(sig, root, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); + sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; + + /* Update the indices for the next layer. */ + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; + } + + free_hash_function(&ctx); + + *siglen = SPX_BYTES; + + return 0; +} + +/** + * Verifies a detached signature and message under a given public key. + */ +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk) { + spx_ctx ctx; + const uint8_t *pub_root = pk + SPX_N; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t wots_pk[SPX_WOTS_BYTES]; + uint8_t root[SPX_N]; + uint8_t leaf[SPX_N]; + unsigned int i; + uint64_t tree; + uint32_t idx_leaf; + uint32_t wots_addr[8] = {0}; + uint32_t tree_addr[8] = {0}; + uint32_t wots_pk_addr[8] = {0}; + + if (siglen != SPX_BYTES) { + return -1; + } + + memcpy(ctx.pub_seed, pk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); + + /* Derive the message digest and leaf index from R || PK || M. */ + /* The additional SPX_N is a result of the hash domain separator. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; + + /* Layer correctly defaults to 0, so no need to set_layer_addr */ + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); + + fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + /* For each subtree.. */ + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + copy_keypair_addr(wots_pk_addr, wots_addr); + + /* The WOTS public key is only correct if the signature was correct. */ + /* Initially, root is the FORS pk, but on subsequent iterations it is + the root of the subtree below the currently processed subtree. */ + wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); + sig += SPX_WOTS_BYTES; + + /* Compute the leaf node using the WOTS public key. */ + thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); + + /* Compute the root node of this subtree. */ + compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, + &ctx, tree_addr); + sig += SPX_TREE_HEIGHT * SPX_N; + + /* Update the indices for the next layer. */ + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; + } + + // cleanup + free_hash_function(&ctx); + + /* Check if the root node equals the root node in the public key. */ + if (memcmp(root, pub_root, SPX_N) != 0) { + return -1; + } + + return 0; +} + + +/** + * Returns an array containing the signature followed by the message. + */ +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk) { + size_t siglen; + + crypto_sign_signature(sm, &siglen, m, mlen, sk); + + memmove(sm + SPX_BYTES, m, mlen); + *smlen = siglen + mlen; + + return 0; +} + +/** + * Verifies a given signature-message pair under a given public key. + */ +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk) { + /* The API caller does not necessarily know what size a signature should be + but SPHINCS+ signatures are always exactly SPX_BYTES. */ + if (smlen < SPX_BYTES) { + memset(m, 0, smlen); + *mlen = 0; + return -1; + } + + *mlen = smlen - SPX_BYTES; + + if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { + memset(m, 0, smlen); + *mlen = 0; + return -1; + } + + /* If verification was successful, move the message to the right place. */ + memmove(m, sm + SPX_BYTES, *mlen); + + return 0; +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/thash.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/thash.h new file mode 100644 index 0000000000..8687ccfb4d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/thash.h @@ -0,0 +1,13 @@ +#ifndef SPX_THASH_H +#define SPX_THASH_H + +#include "context.h" +#include "params.h" + +#include + +#define thash SPX_NAMESPACE(thash) +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/thash_shake_simplex2.c b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/thash_shake_simplex2.c new file mode 100644 index 0000000000..892e453690 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/thash_shake_simplex2.c @@ -0,0 +1,83 @@ +#include +#include + +#include "thash.h" +#include "thashx2.h" + +#include "address.h" +#include "params.h" +#include "utils.h" + +#include "f1600x2.h" +#include "fips202x2.h" + + +void thash(unsigned char *out, + const unsigned char *in, + unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]) { + uint32_t addrx2 [2 * 8] = { + addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], addr[6], addr[7], + addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], addr[6], addr[7] + }; + thashx2(out, out, in, in, inblocks, ctx, addrx2); +} + +/** + * 2-way parallel version of thash; takes 2x as much input and output + */ +void thashx2(unsigned char *out0, + unsigned char *out1, + const unsigned char *in0, + const unsigned char *in1, + unsigned int inblocks, + const spx_ctx *ctx, uint32_t addrx2[2 * 8]) { + if (inblocks == 1 || inblocks == 2) { + /* As we write and read only a few quadwords, it is more efficient to + * build and extract from the twoway SHAKE256 state by hand. */ + uint64_t state[50] = {0}; + for (int i = 0; i < SPX_N / 8; i++) { + uint64_t x = load64(ctx->pub_seed + 8 * i); + state[2 * i] = x; + state[2 * i + 1] = x; + } + for (int i = 0; i < 4; i++) { + state[2 * (SPX_N / 8 + i)] = (((uint64_t)addrx2[1 + 2 * i]) << 32) + | (uint64_t)addrx2[2 * i]; + state[2 * (SPX_N / 8 + i) + 1] = (((uint64_t)addrx2[8 + 1 + 2 * i]) << 32) + | (uint64_t)addrx2[8 + 2 * i]; + } + + for (unsigned int i = 0; i < (SPX_N / 8) * inblocks; i++) { + state[2 * (SPX_N / 8 + 4 + i)] = load64(in0 + 8 * i); + state[2 * (SPX_N / 8 + 4 + i) + 1] = load64(in1 + 8 * i); + } + + /* Domain separator and padding. */ + state[2 * 16] = 0x80ULL << 56; + state[2 * 16 + 1] = 0x80ULL << 56; + + state[2 * ((SPX_N / 8) * (1 + inblocks) + 4)] ^= 0x1f; + state[2 * ((SPX_N / 8) * (1 + inblocks) + 4) + 1] ^= 0x1f; + + f1600x2(state); + + for (int i = 0; i < SPX_N / 8; i++) { + store64(out0 + 8 * i, state[2 * i]); + store64(out1 + 8 * i, state[2 * i + 1]); + } + } else { + PQCLEAN_VLA(unsigned char, buf0, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, buf1, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); + + memcpy(buf0, ctx->pub_seed, SPX_N); + memcpy(buf1, ctx->pub_seed, SPX_N); + memcpy(buf0 + SPX_N, addrx2 + 0 * 8, SPX_ADDR_BYTES); + memcpy(buf1 + SPX_N, addrx2 + 1 * 8, SPX_ADDR_BYTES); + memcpy(buf0 + SPX_N + SPX_ADDR_BYTES, in0, inblocks * SPX_N); + memcpy(buf1 + SPX_N + SPX_ADDR_BYTES, in1, inblocks * SPX_N); + + shake256x2(out0, out1, SPX_N, + buf0, buf1, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/thashx2.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/thashx2.h new file mode 100644 index 0000000000..040375e618 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/thashx2.h @@ -0,0 +1,16 @@ +#ifndef SPX_THASHX2_H +#define SPX_THASHX2_H + +#include "context.h" +#include "params.h" +#include + +#define thashx2 SPX_NAMESPACE(thashx2) +void thashx2(unsigned char *out0, + unsigned char *out1, + const unsigned char *in0, + const unsigned char *in1, + unsigned int inblocks, + const spx_ctx *ctx, uint32_t addrx2[2 * 8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/utils.c b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/utils.c new file mode 100644 index 0000000000..177b541fb9 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/utils.c @@ -0,0 +1,148 @@ +#include + +#include "utils.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "thash.h" + +/** + * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. + */ +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in) { + int i; + + /* Iterate over out in decreasing order, for big-endianness. */ + for (i = (signed int)outlen - 1; i >= 0; i--) { + out[i] = in & 0xff; + in = in >> 8; + } +} + +void u32_to_bytes(unsigned char *out, uint32_t in) { + out[0] = (unsigned char)(in >> 24); + out[1] = (unsigned char)(in >> 16); + out[2] = (unsigned char)(in >> 8); + out[3] = (unsigned char)in; +} + +/** + * Converts the inlen bytes in 'in' from big-endian byte order to an integer. + */ +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { + unsigned long long retval = 0; + unsigned int i; + + for (i = 0; i < inlen; i++) { + retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); + } + return retval; +} + +/** + * Computes a root node given a leaf and an auth path. + * Expects address to be complete other than the tree_height and tree_index. + */ +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]) { + uint32_t i; + unsigned char buffer[2 * SPX_N]; + + /* If leaf_idx is odd (last bit = 1), current path element is a right child + and auth_path has to go left. Otherwise it is the other way around. */ + if (leaf_idx & 1) { + memcpy(buffer + SPX_N, leaf, SPX_N); + memcpy(buffer, auth_path, SPX_N); + } else { + memcpy(buffer, leaf, SPX_N); + memcpy(buffer + SPX_N, auth_path, SPX_N); + } + auth_path += SPX_N; + + for (i = 0; i < tree_height - 1; i++) { + leaf_idx >>= 1; + idx_offset >>= 1; + /* Set the address of the node we're creating. */ + set_tree_height(addr, i + 1); + set_tree_index(addr, leaf_idx + idx_offset); + + /* Pick the right or left neighbor, depending on parity of the node. */ + if (leaf_idx & 1) { + thash(buffer + SPX_N, buffer, 2, ctx, addr); + memcpy(buffer, auth_path, SPX_N); + } else { + thash(buffer, buffer, 2, ctx, addr); + memcpy(buffer + SPX_N, auth_path, SPX_N); + } + auth_path += SPX_N; + } + + /* The last iteration is exceptional; we do not copy an auth_path node. */ + leaf_idx >>= 1; + idx_offset >>= 1; + set_tree_height(addr, tree_height); + set_tree_index(addr, leaf_idx + idx_offset); + thash(root, buffer, 2, ctx, addr); +} + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx * /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]) { + PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); + PQCLEAN_VLA(unsigned int, heights, tree_height + 1); + unsigned int offset = 0; + uint32_t idx; + uint32_t tree_idx; + + for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { + /* Add the next leaf node to the stack. */ + gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); + offset++; + heights[offset - 1] = 0; + + /* If this is a node we need for the auth path.. */ + if ((leaf_idx ^ 0x1) == idx) { + memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); + } + + /* While the top-most nodes are of equal height.. */ + while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { + /* Compute index of the new node, in the next layer. */ + tree_idx = (idx >> (heights[offset - 1] + 1)); + + /* Set the address of the node we're creating. */ + set_tree_height(tree_addr, heights[offset - 1] + 1); + set_tree_index(tree_addr, + tree_idx + (idx_offset >> (heights[offset - 1] + 1))); + /* Hash the top-most nodes from the stack together. */ + thash(stack + (offset - 2)*SPX_N, + stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); + offset--; + /* Note that the top-most node is now one layer higher. */ + heights[offset - 1]++; + + /* If this is a node we need for the auth path.. */ + if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { + memcpy(auth_path + heights[offset - 1]*SPX_N, + stack + (offset - 1)*SPX_N, SPX_N); + } + } + } + memcpy(root, stack, SPX_N); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/utils.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/utils.h new file mode 100644 index 0000000000..64f5d5a53a --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/utils.h @@ -0,0 +1,58 @@ +#ifndef SPX_UTILS_H +#define SPX_UTILS_H + +#include + +#include "compat.h" +#include "context.h" +#include "params.h" + + +/* To support MSVC use alloca() instead of VLAs. See #20. */ + + +/** + * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. + */ +#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in); +#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) +void u32_to_bytes(unsigned char *out, uint32_t in); + +/** + * Converts the inlen bytes in 'in' from big-endian byte order to an integer. + */ +#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); + +/** + * Computes a root node given a leaf and an auth path. + * Expects address to be complete other than the tree_height and tree_index. + */ +#define compute_root SPX_NAMESPACE(compute_root) +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]); + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +#define treehash SPX_NAMESPACE(treehash) +void treehash(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx *ctx /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]); + + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/utilsx2.c b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/utilsx2.c new file mode 100644 index 0000000000..8736474e4f --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/utilsx2.c @@ -0,0 +1,130 @@ +#include + +#include "utilsx2.h" + +#include "address.h" +#include "params.h" +#include "thashx2.h" +#include "utils.h" + +/* + * Generate the entire Merkle tree, computing the authentication path for leaf_idx, + * and the resulting root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) + * + * This expects tree_addrx2 to be initialized to 2 parallel addr structures for + * the Merkle tree nodes + * + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + * + * This works by using the standard Merkle tree building algorithm, except + * that each 'node' tracked is actually 2 consecutive nodes in the real tree. + * When we combine two logical nodes AB and WX, we perform the H + * operation on adjacent real nodes, forming the parent logical node + * (AB)(WX) + * + * When we get to the top level of the real tree (where there is only + * one logical node), we continue this operation one more time; the right + * most real node will by the actual root (and the other node will be + * garbage). We follow the same thashx2 logic so that the 'extract + * authentication path components' part of the loop is still executed (and + * to simplify the code somewhat) + */ +void treehashx2(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, + uint32_t tree_height, + void (*gen_leafx2)( + unsigned char * /* Where to write the leaves */, + const spx_ctx *, + uint32_t idx, void *info), + uint32_t tree_addrx2[2 * 8], + void *info) { + /* This is where we keep the intermediate nodes */ + unsigned char stackx2[tree_height * 2 * SPX_N]; + uint32_t left_adj = 0, prev_left_adj = 0; /* When we're doing the top */ + /* level, the left-most part of the tree isn't at the beginning */ + /* of current[]. These give the offset of the actual start */ + + uint32_t idx; + uint32_t max_idx = (1 << (tree_height - 1)) - 1; + for (idx = 0;; idx++) { + unsigned char current[2 * SPX_N]; /* Current logical node */ + gen_leafx2( current, ctx, 2 * idx + idx_offset, + info ); + + /* Now combine the freshly generated right node with previously */ + /* generated left ones */ + uint32_t internal_idx_offset = idx_offset; + uint32_t internal_idx = idx; + uint32_t internal_leaf = leaf_idx; + uint32_t h; /* The height we are in the Merkle tree */ + for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { + + /* Special processing if we're at the top of the tree */ + if (h >= tree_height - 1) { + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[1 * SPX_N], SPX_N ); + return; + } + /* The tree indexing logic is a bit off in this case */ + /* Adjust it so that the left-most node of the part of */ + /* the tree that we're processing has index 0 */ + prev_left_adj = left_adj; + left_adj = 2 - (1 << (tree_height - h - 1)); + } + + /* Check if we hit the top of the tree */ + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[1 * SPX_N], SPX_N ); + return; + } + + /* + * Check if one of the nodes we have is a part of the + * authentication path; if it is, write it out + */ + if ((((internal_idx << 1) ^ internal_leaf) & ~0x1) == 0) { + memcpy( &auth_path[ h * SPX_N ], + ¤t[(((internal_leaf & 1) ^ 1) + prev_left_adj) * SPX_N], + SPX_N ); + } + + /* + * Check if we're at a left child; if so, stop going up the stack + * Exception: if we've reached the end of the tree, keep on going + * (so we combine the last 2 nodes into the one root node in two + * more iterations) + */ + if ((internal_idx & 1) == 0 && idx < max_idx) { + break; + } + + /* Ok, we're at a right node (or doing the top 3 levels) */ + /* Now combine the left and right logical nodes together */ + + /* Set the address of the node we're creating. */ + int j; + internal_idx_offset >>= 1; + for (j = 0; j < 2; j++) { + set_tree_height(tree_addrx2 + j * 8, h + 1); + set_tree_index(tree_addrx2 + j * 8, + (2 / 2) * (internal_idx & ~1) + j - left_adj + internal_idx_offset ); + } + unsigned char *left = &stackx2[h * 2 * SPX_N]; + thashx2( ¤t[0 * SPX_N], + ¤t[1 * SPX_N], + &left [0 * SPX_N], + ¤t[0 * SPX_N], + 2, ctx, tree_addrx2); + } + + /* We've hit a left child; save the current for when we get the */ + /* corresponding right right */ + memcpy( &stackx2[h * 2 * SPX_N], current, 2 * SPX_N); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/utilsx2.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/utilsx2.h new file mode 100644 index 0000000000..e09faddc43 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/utilsx2.h @@ -0,0 +1,30 @@ +#ifndef SPX_UTILSX2_H +#define SPX_UTILSX2_H + +#include + +#include "context.h" +#include "params.h" + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + * + * This implementation uses SIMD to compute internal nodes 2 at a time (in + * parallel) + */ +#define treehashx2 SPX_NAMESPACE(treehashx2) +void treehashx2(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leafx2)( + unsigned char * /* Where to write the leaves */, + const spx_ctx * /* ctx */, + uint32_t addr_idx, void *info), + uint32_t tree_addrx2[2 * 8], void *info); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/wots.c b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/wots.c new file mode 100644 index 0000000000..3babe45e95 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/wots.c @@ -0,0 +1,259 @@ +#include +#include + +#include "wots.h" +#include "wotsx2.h" + +#include "address.h" +#include "hash.h" +#include "hashx2.h" +#include "params.h" +#include "thashx2.h" +#include "utils.h" +#include "utilsx2.h" + +// TODO clarify address expectations, and make them more uniform. +// TODO i.e. do we expect types to be set already? +// TODO and do we expect modifications or copies? + +/** + * Computes up the chains + */ +static void gen_chains( + unsigned char *out, + const unsigned char *in, + unsigned int start[SPX_WOTS_LEN], + const unsigned int steps[SPX_WOTS_LEN], + const spx_ctx *ctx, + uint32_t addr[8]) { + uint32_t i, j, k, idx, watching; + int done; + unsigned char empty[SPX_N]; + unsigned char *bufs[4]; + uint32_t addrs[8 * 2]; + + int l; + uint16_t counts[SPX_WOTS_W] = { 0 }; + uint16_t idxs[SPX_WOTS_LEN]; + uint16_t total, newTotal; + + /* set addrs = {addr, addr} */ + for (j = 0; j < 2; j++) { + memcpy(addrs + j * 8, addr, sizeof(uint32_t) * 8); + } + + /* Initialize out with the value at position 'start'. */ + memcpy(out, in, SPX_WOTS_LEN * SPX_N); + + /* Sort the chains in reverse order by steps using counting sort. */ + for (i = 0; i < SPX_WOTS_LEN; i++) { + counts[steps[i]]++; + } + total = 0; + for (l = SPX_WOTS_W - 1; l >= 0; l--) { + newTotal = counts[l] + total; + counts[l] = total; + total = newTotal; + } + for (i = 0; i < SPX_WOTS_LEN; i++) { + idxs[counts[steps[i]]] = i; + counts[steps[i]]++; + } + + /* We got our work cut out for us: do it! */ + for (i = 0; i < SPX_WOTS_LEN; i += 2) { + for (j = 0; j < 2 && i + j < SPX_WOTS_LEN; j++) { + idx = idxs[i + j]; + set_chain_addr(addrs + j * 8, idx); + bufs[j] = out + SPX_N * idx; + } + + /* As the chains are sorted in reverse order, we know that the first + * chain is the longest and the last one is the shortest. We keep + * an eye on whether the last chain is done and then on the one before, + * et cetera. */ + watching = 1; + done = 0; + while (i + watching >= SPX_WOTS_LEN) { + bufs[watching] = &empty[0]; + watching--; + } + + for (k = 0;; k++) { + while (k == steps[idxs[i + watching]]) { + bufs[watching] = &empty[0]; + if (watching == 0) { + done = 1; + break; + } + watching--; + } + if (done) { + break; + } + for (j = 0; j < watching + 1; j++) { + set_hash_addr(addrs + j * 8, k + start[idxs[i + j]]); + } + + thashx2(bufs[0], bufs[1], + bufs[0], bufs[1], 1, ctx, addrs); + } + } +} + +/** + * base_w algorithm as described in draft. + * Interprets an array of bytes as integers in base w. + * This only works when log_w is a divisor of 8. + */ +static void base_w(unsigned int *output, const int out_len, + const unsigned char *input) { + int in = 0; + int out = 0; + unsigned char total = 0; + int bits = 0; + int consumed; + + for (consumed = 0; consumed < out_len; consumed++) { + if (bits == 0) { + total = input[in]; + in++; + bits += 8; + } + bits -= SPX_WOTS_LOGW; + output[out] = (total >> bits) & (SPX_WOTS_W - 1); + out++; + } +} + +/* Computes the WOTS+ checksum over a message (in base_w). */ +static void wots_checksum(unsigned int *csum_base_w, + const unsigned int *msg_base_w) { + unsigned int csum = 0; + unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; + unsigned int i; + + /* Compute checksum. */ + for (i = 0; i < SPX_WOTS_LEN1; i++) { + csum += SPX_WOTS_W - 1 - msg_base_w[i]; + } + + /* Convert checksum to base_w. */ + /* Make sure expected empty zero bits are the least significant bits. */ + csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); + ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); + base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); +} + +/* Takes a message and derives the matching chain lengths. */ +void chain_lengths(unsigned int *lengths, const unsigned char *msg) { + base_w(lengths, SPX_WOTS_LEN1, msg); + wots_checksum(lengths + SPX_WOTS_LEN1, lengths); +} + +/** + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. + * + * Writes the computed public key to 'pk'. + */ +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]) { + unsigned int steps[SPX_WOTS_LEN]; + unsigned int start[SPX_WOTS_LEN]; + uint32_t i; + + chain_lengths(start, msg); + + for (i = 0; i < SPX_WOTS_LEN; i++) { + steps[i] = SPX_WOTS_W - 1 - start[i]; + } + + gen_chains(pk, sig, start, steps, ctx, addr); +} + +/* + * This generates 2 sequential WOTS public keys + * It also generates the WOTS signature if leaf_info indicates + * that we're signing with one of these WOTS keys + */ +void wots_gen_leafx2(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info) { + struct leaf_info_x2 *info = v_info; + uint32_t *leaf_addr = info->leaf_addr; + uint32_t *pk_addr = info->pk_addr; + unsigned int i, j, k; + unsigned char pk_buffer[ 2 * SPX_WOTS_BYTES ]; + unsigned wots_offset = SPX_WOTS_BYTES; + unsigned char *buffer; + uint32_t wots_k_mask; + unsigned wots_sign_index; + + if (((leaf_idx ^ info->wots_sign_leaf) & ~1) == 0) { + /* We're traversing the leaf that's signing; generate the WOTS */ + /* signature */ + wots_k_mask = 0; + wots_sign_index = info->wots_sign_leaf & 1; /* Which of of the 2 */ + /* slots do the signatures come from */ + } else { + /* Nope, we're just generating pk's; turn off the signature logic */ + wots_k_mask = ~0; + wots_sign_index = 0; + } + + for (j = 0; j < 2; j++) { + set_keypair_addr( leaf_addr + j * 8, leaf_idx + j ); + set_keypair_addr( pk_addr + j * 8, leaf_idx + j ); + } + + for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { + uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k to */ + /* the step if we're generating a signature, ~0 if we're not */ + + /* Start with the secret seed */ + for (j = 0; j < 2; j++) { + set_chain_addr(leaf_addr + j * 8, i); + set_hash_addr(leaf_addr + j * 8, 0); + set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTSPRF); + } + prf_addrx2(buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + ctx, leaf_addr); + for (j = 0; j < 2; j++) { + set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTS); + } + + /* Iterate down the WOTS chain */ + for (k = 0;; k++) { + /* Check if one of the values we have needs to be saved as a */ + /* part of the WOTS signature */ + if (k == wots_k) { + memcpy( info->wots_sig + i * SPX_N, + buffer + wots_sign_index * wots_offset, SPX_N ); + } + + /* Check if we hit the top of the chain */ + if (k == SPX_WOTS_W - 1) { + break; + } + + /* Iterate one step on all 4 chains */ + for (j = 0; j < 2; j++) { + set_hash_addr(leaf_addr + j * 8, k); + } + thashx2(buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + 1, ctx, leaf_addr); + } + } + + /* Do the final thash to generate the public keys */ + thashx2(dest + 0 * SPX_N, + dest + 1 * SPX_N, + pk_buffer + 0 * wots_offset, + pk_buffer + 1 * wots_offset, + SPX_WOTS_LEN, ctx, pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/wots.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/wots.h new file mode 100644 index 0000000000..4e7692eeef --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/wots.h @@ -0,0 +1,25 @@ +#ifndef SPX_WOTS_H +#define SPX_WOTS_H + +#include + +#include "context.h" +#include "params.h" + +/** + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. + * + * Writes the computed public key to 'pk'. + */ +#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]); + +/* + * Compute the chain lengths needed for a given message hash + */ +#define chain_lengths SPX_NAMESPACE(chain_lengths) +void chain_lengths(unsigned int *lengths, const unsigned char *msg); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/wotsx2.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/wotsx2.h new file mode 100644 index 0000000000..b58bb61f84 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_aarch64/wotsx2.h @@ -0,0 +1,40 @@ +#ifndef WOTSX2_H_ +#define WOTSX2_H_ + +#include "params.h" +#include + +/* + * This is here to provide an interface to the internal wots_gen_leafx2 + * routine. While this routine is not referenced in the package outside of + * wots.c, it is called from the stand-alone benchmark code to characterize + * the performance + */ +struct leaf_info_x2 { + unsigned char *wots_sig; + uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ + uint32_t *wots_steps; + uint32_t leaf_addr[2 * 8]; + uint32_t pk_addr[2 * 8]; +}; + +/* Macro to set the leaf_info to something 'benign', that is, it would */ +/* run with the same time as it does during the real signing process */ +/* Used only by the benchmark code */ +#define INITIALIZE_LEAF_INFO_X2(info, addr, step_buffer) { \ + (info).wots_sig = 0; \ + (info).wots_sign_leaf = ~0; \ + (info).wots_steps = step_buffer; \ + int i; \ + for (i=0; i<2; i++) { \ + memcpy( &(info).leaf_addr[8*i], addr, 32 ); \ + memcpy( &(info).pk_addr[8*i], addr, 32 ); \ + } \ + } + +#define wots_gen_leafx2 SPX_NAMESPACE(wots_gen_leafx2) +void wots_gen_leafx2(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info); + +#endif /* WOTSX2_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/LICENSE b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/LICENSE new file mode 100644 index 0000000000..670154e353 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/LICENSE @@ -0,0 +1,116 @@ +CC0 1.0 Universal + +Statement of Purpose + +The laws of most jurisdictions throughout the world automatically confer +exclusive Copyright and Related Rights (defined below) upon the creator and +subsequent owner(s) (each and all, an "owner") of an original work of +authorship and/or a database (each, a "Work"). + +Certain owners wish to permanently relinquish those rights to a Work for the +purpose of contributing to a commons of creative, cultural and scientific +works ("Commons") that the public can reliably and without fear of later +claims of infringement build upon, modify, incorporate in other works, reuse +and redistribute as freely as possible in any form whatsoever and for any +purposes, including without limitation commercial purposes. These owners may +contribute to the Commons to promote the ideal of a free culture and the +further production of creative, cultural and scientific works, or to gain +reputation or greater distribution for their Work in part through the use and +efforts of others. + +For these and/or other purposes and motivations, and without any expectation +of additional consideration or compensation, the person associating CC0 with a +Work (the "Affirmer"), to the extent that he or she is an owner of Copyright +and Related Rights in the Work, voluntarily elects to apply CC0 to the Work +and publicly distribute the Work under its terms, with knowledge of his or her +Copyright and Related Rights in the Work and the meaning and intended legal +effect of CC0 on those rights. + +1. Copyright and Related Rights. A Work made available under CC0 may be +protected by copyright and related or neighboring rights ("Copyright and +Related Rights"). Copyright and Related Rights include, but are not limited +to, the following: + + i. the right to reproduce, adapt, distribute, perform, display, communicate, + and translate a Work; + + ii. moral rights retained by the original author(s) and/or performer(s); + + iii. publicity and privacy rights pertaining to a person's image or likeness + depicted in a Work; + + iv. rights protecting against unfair competition in regards to a Work, + subject to the limitations in paragraph 4(a), below; + + v. rights protecting the extraction, dissemination, use and reuse of data in + a Work; + + vi. database rights (such as those arising under Directive 96/9/EC of the + European Parliament and of the Council of 11 March 1996 on the legal + protection of databases, and under any national implementation thereof, + including any amended or successor version of such directive); and + + vii. other similar, equivalent or corresponding rights throughout the world + based on applicable law or treaty, and any national implementations thereof. + +2. Waiver. To the greatest extent permitted by, but not in contravention of, +applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and +unconditionally waives, abandons, and surrenders all of Affirmer's Copyright +and Related Rights and associated claims and causes of action, whether now +known or unknown (including existing as well as future claims and causes of +action), in the Work (i) in all territories worldwide, (ii) for the maximum +duration provided by applicable law or treaty (including future time +extensions), (iii) in any current or future medium and for any number of +copies, and (iv) for any purpose whatsoever, including without limitation +commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes +the Waiver for the benefit of each member of the public at large and to the +detriment of Affirmer's heirs and successors, fully intending that such Waiver +shall not be subject to revocation, rescission, cancellation, termination, or +any other legal or equitable action to disrupt the quiet enjoyment of the Work +by the public as contemplated by Affirmer's express Statement of Purpose. + +3. Public License Fallback. Should any part of the Waiver for any reason be +judged legally invalid or ineffective under applicable law, then the Waiver +shall be preserved to the maximum extent permitted taking into account +Affirmer's express Statement of Purpose. In addition, to the extent the Waiver +is so judged Affirmer hereby grants to each affected person a royalty-free, +non transferable, non sublicensable, non exclusive, irrevocable and +unconditional license to exercise Affirmer's Copyright and Related Rights in +the Work (i) in all territories worldwide, (ii) for the maximum duration +provided by applicable law or treaty (including future time extensions), (iii) +in any current or future medium and for any number of copies, and (iv) for any +purpose whatsoever, including without limitation commercial, advertising or +promotional purposes (the "License"). The License shall be deemed effective as +of the date CC0 was applied by Affirmer to the Work. Should any part of the +License for any reason be judged legally invalid or ineffective under +applicable law, such partial invalidity or ineffectiveness shall not +invalidate the remainder of the License, and in such case Affirmer hereby +affirms that he or she will not (i) exercise any of his or her remaining +Copyright and Related Rights in the Work or (ii) assert any associated claims +and causes of action with respect to the Work, in either case contrary to +Affirmer's express Statement of Purpose. + +4. Limitations and Disclaimers. + + a. No trademark or patent rights held by Affirmer are waived, abandoned, + surrendered, licensed or otherwise affected by this document. + + b. Affirmer offers the Work as-is and makes no representations or warranties + of any kind concerning the Work, express, implied, statutory or otherwise, + including without limitation warranties of title, merchantability, fitness + for a particular purpose, non infringement, or the absence of latent or + other defects, accuracy, or the present or absence of errors, whether or not + discoverable, all to the greatest extent permissible under applicable law. + + c. Affirmer disclaims responsibility for clearing rights of other persons + that may apply to the Work or any use thereof, including without limitation + any person's Copyright and Related Rights in the Work. Further, Affirmer + disclaims responsibility for obtaining any necessary consents, permissions + or other rights required for any use of the Work. + + d. Affirmer understands and acknowledges that Creative Commons is not a + party to this document and has no duty or obligation with respect to this + CC0 or use of the Work. + +For more information, please see + diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/address.c b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/address.c new file mode 100644 index 0000000000..b956e9cb29 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/address.c @@ -0,0 +1,91 @@ +#include +#include + +#include "address.h" +#include "params.h" +#include "utils.h" + +/* + * Specify which level of Merkle tree (the "layer") we're working on + */ +void set_layer_addr(uint32_t addr[8], uint32_t layer) { + ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; +} + +/* + * Specify which Merkle tree within the level (the "tree address") we're working on + */ +void set_tree_addr(uint32_t addr[8], uint64_t tree) { + ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); +} + +/* + * Specify the reason we'll use this address structure for, that is, what + * hash will we compute with it. This is used so that unrelated types of + * hashes don't accidentally get the same address structure. The type will be + * one of the SPX_ADDR_TYPE constants + */ +void set_type(uint32_t addr[8], uint32_t type) { + ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; +} + +/* + * Copy the layer and tree fields of the address structure. This is used + * when we're doing multiple types of hashes within the same Merkle tree + */ +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); +} + +/* These functions are used for OTS addresses. */ + +/* + * Specify which Merkle leaf we're working on; that is, which OTS keypair + * we're talking about. + */ +void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { + ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; +} + +/* + * Copy the layer, tree and keypair fields of the address structure. This is + * used when we're doing multiple things within the same OTS keypair + */ +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); + ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; +} + +/* + * Specify which Merkle chain within the OTS we're working with + * (the chain address) + */ +void set_chain_addr(uint32_t addr[8], uint32_t chain) { + ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; +} + +/* + * Specify where in the Merkle chain we are +* (the hash address) + */ +void set_hash_addr(uint32_t addr[8], uint32_t hash) { + ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; +} + +/* These functions are used for all hash tree addresses (including FORS). */ + +/* + * Specify the height of the node in the Merkle/FORS tree we are in + * (the tree height) + */ +void set_tree_height(uint32_t addr[8], uint32_t tree_height) { + ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; +} + +/* + * Specify the distance from the left edge of the node in the Merkle/FORS tree + * (the tree index) + */ +void set_tree_index(uint32_t addr[8], uint32_t tree_index) { + u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/address.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/address.h new file mode 100644 index 0000000000..24a84eb40c --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/address.h @@ -0,0 +1,52 @@ +#ifndef SPX_ADDRESS_H +#define SPX_ADDRESS_H + +#include + +#include "params.h" + +/* The hash types that are passed to set_type */ +#define SPX_ADDR_TYPE_WOTS 0 +#define SPX_ADDR_TYPE_WOTSPK 1 +#define SPX_ADDR_TYPE_HASHTREE 2 +#define SPX_ADDR_TYPE_FORSTREE 3 +#define SPX_ADDR_TYPE_FORSPK 4 +#define SPX_ADDR_TYPE_WOTSPRF 5 +#define SPX_ADDR_TYPE_FORSPRF 6 + +#define set_layer_addr SPX_NAMESPACE(set_layer_addr) +void set_layer_addr(uint32_t addr[8], uint32_t layer); + +#define set_tree_addr SPX_NAMESPACE(set_tree_addr) +void set_tree_addr(uint32_t addr[8], uint64_t tree); + +#define set_type SPX_NAMESPACE(set_type) +void set_type(uint32_t addr[8], uint32_t type); + +/* Copies the layer and tree part of one address into the other */ +#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); + +/* These functions are used for WOTS and FORS addresses. */ + +#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) +void set_keypair_addr(uint32_t addr[8], uint32_t keypair); + +#define set_chain_addr SPX_NAMESPACE(set_chain_addr) +void set_chain_addr(uint32_t addr[8], uint32_t chain); + +#define set_hash_addr SPX_NAMESPACE(set_hash_addr) +void set_hash_addr(uint32_t addr[8], uint32_t hash); + +#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); + +/* These functions are used for all hash tree addresses (including FORS). */ + +#define set_tree_height SPX_NAMESPACE(set_tree_height) +void set_tree_height(uint32_t addr[8], uint32_t tree_height); + +#define set_tree_index SPX_NAMESPACE(set_tree_index) +void set_tree_index(uint32_t addr[8], uint32_t tree_index); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/api.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/api.h new file mode 100644 index 0000000000..f702ab25c4 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/api.h @@ -0,0 +1,77 @@ +#ifndef PQCLEAN_SPHINCSSHAKE192FSIMPLE_AVX2_API_H +#define PQCLEAN_SPHINCSSHAKE192FSIMPLE_AVX2_API_H + +#include +#include + +#define PQCLEAN_SPHINCSSHAKE192FSIMPLE_AVX2_CRYPTO_ALGNAME "SPHINCS+-shake-192f-simple" + +#define PQCLEAN_SPHINCSSHAKE192FSIMPLE_AVX2_CRYPTO_SECRETKEYBYTES 96 +#define PQCLEAN_SPHINCSSHAKE192FSIMPLE_AVX2_CRYPTO_PUBLICKEYBYTES 48 +#define PQCLEAN_SPHINCSSHAKE192FSIMPLE_AVX2_CRYPTO_BYTES 35664 + +#define PQCLEAN_SPHINCSSHAKE192FSIMPLE_AVX2_CRYPTO_SEEDBYTES 72 + +/* + * Returns the length of a secret key, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE192FSIMPLE_AVX2_crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE192FSIMPLE_AVX2_crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE192FSIMPLE_AVX2_crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE192FSIMPLE_AVX2_crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +int PQCLEAN_SPHINCSSHAKE192FSIMPLE_AVX2_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +int PQCLEAN_SPHINCSSHAKE192FSIMPLE_AVX2_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +int PQCLEAN_SPHINCSSHAKE192FSIMPLE_AVX2_crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +int PQCLEAN_SPHINCSSHAKE192FSIMPLE_AVX2_crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, + const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +int PQCLEAN_SPHINCSSHAKE192FSIMPLE_AVX2_crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +int PQCLEAN_SPHINCSSHAKE192FSIMPLE_AVX2_crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/context.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/context.h new file mode 100644 index 0000000000..6e0a33f3b7 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/context.h @@ -0,0 +1,19 @@ +#ifndef SPX_CONTEXT_H +#define SPX_CONTEXT_H + +#include + +#include "params.h" + +typedef struct { + uint8_t pub_seed[SPX_N]; + uint8_t sk_seed[SPX_N]; +} spx_ctx; + +#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) +void initialize_hash_function(spx_ctx *ctx); + +#define free_hash_function SPX_NAMESPACE(free_hash_function) +void free_hash_function(spx_ctx *ctx); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/context_shake.c b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/context_shake.c new file mode 100644 index 0000000000..9614a103d3 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/context_shake.c @@ -0,0 +1,12 @@ +#include "context.h" + +/* For SHAKE256, there is no immediate reason to initialize at the start, + so this function is an empty operation. */ +void initialize_hash_function(spx_ctx *ctx) { + (void)ctx; /* Suppress an 'unused parameter' warning. */ +} + +// in case the hash function api is heap-based. +void free_hash_function(spx_ctx *ctx) { + (void)ctx; +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/fips202x4.c b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/fips202x4.c new file mode 100644 index 0000000000..1e06fef186 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/fips202x4.c @@ -0,0 +1,210 @@ +#include +#include +#include + +#include "fips202.h" +#include "fips202x4.h" + +#define NROUNDS 24 +#define ROL(a, offset) (((a) << (offset)) ^ ((a) >> (64-(offset)))) + +static uint64_t load64(const unsigned char *x) { + unsigned long long r = 0, i; + + for (i = 0; i < 8; ++i) { + r |= (unsigned long long)x[i] << 8 * i; + } + return r; +} + +static void store64(uint8_t *x, uint64_t u) { + unsigned int i; + + for (i = 0; i < 8; ++i) { + x[i] = (uint8_t)u; + u >>= 8; + } +} + +/* Use implementation from the Keccak Code Package */ +extern void KeccakP1600times4_PermuteAll_24rounds(__m256i *s); +#define KeccakF1600_StatePermute4x KeccakP1600times4_PermuteAll_24rounds + +static void keccak_absorb4x(__m256i *s, + unsigned int r, + const unsigned char *m0, + const unsigned char *m1, + const unsigned char *m2, + const unsigned char *m3, + unsigned long long int mlen, + unsigned char p) { + unsigned long long i; + unsigned char t0[200]; + unsigned char t1[200]; + unsigned char t2[200]; + unsigned char t3[200]; + + unsigned long long *ss = (unsigned long long *)s; + + + while (mlen >= r) { + for (i = 0; i < r / 8; ++i) { + ss[4 * i + 0] ^= load64(m0 + 8 * i); + ss[4 * i + 1] ^= load64(m1 + 8 * i); + ss[4 * i + 2] ^= load64(m2 + 8 * i); + ss[4 * i + 3] ^= load64(m3 + 8 * i); + } + + KeccakF1600_StatePermute4x(s); + mlen -= r; + m0 += r; + m1 += r; + m2 += r; + m3 += r; + } + + for (i = 0; i < r; ++i) { + t0[i] = 0; + t1[i] = 0; + t2[i] = 0; + t3[i] = 0; + } + for (i = 0; i < mlen; ++i) { + t0[i] = m0[i]; + t1[i] = m1[i]; + t2[i] = m2[i]; + t3[i] = m3[i]; + } + + t0[i] = p; + t1[i] = p; + t2[i] = p; + t3[i] = p; + + t0[r - 1] |= 128; + t1[r - 1] |= 128; + t2[r - 1] |= 128; + t3[r - 1] |= 128; + + for (i = 0; i < r / 8; ++i) { + ss[4 * i + 0] ^= load64(t0 + 8 * i); + ss[4 * i + 1] ^= load64(t1 + 8 * i); + ss[4 * i + 2] ^= load64(t2 + 8 * i); + ss[4 * i + 3] ^= load64(t3 + 8 * i); + } +} + + +static void keccak_squeezeblocks4x(unsigned char *h0, + unsigned char *h1, + unsigned char *h2, + unsigned char *h3, + unsigned long long int nblocks, + __m256i *s, + unsigned int r) { + unsigned int i; + + unsigned long long *ss = (unsigned long long *)s; + + while (nblocks > 0) { + KeccakF1600_StatePermute4x(s); + for (i = 0; i < (r >> 3); i++) { + store64(h0 + 8 * i, ss[4 * i + 0]); + store64(h1 + 8 * i, ss[4 * i + 1]); + store64(h2 + 8 * i, ss[4 * i + 2]); + store64(h3 + 8 * i, ss[4 * i + 3]); + } + h0 += r; + h1 += r; + h2 += r; + h3 += r; + nblocks--; + } +} + + + +void shake128x4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, unsigned long long outlen, + unsigned char *in0, + unsigned char *in1, + unsigned char *in2, + unsigned char *in3, unsigned long long inlen) { + __m256i s[25]; + unsigned char t0[SHAKE128_RATE]; + unsigned char t1[SHAKE128_RATE]; + unsigned char t2[SHAKE128_RATE]; + unsigned char t3[SHAKE128_RATE]; + unsigned int i; + + /* zero state */ + for (i = 0; i < 25; i++) { + s[i] = _mm256_xor_si256(s[i], s[i]); + } + + /* absorb 4 message of identical length in parallel */ + keccak_absorb4x(s, SHAKE128_RATE, in0, in1, in2, in3, inlen, 0x1F); + + /* Squeeze output */ + keccak_squeezeblocks4x(out0, out1, out2, out3, outlen / SHAKE128_RATE, s, SHAKE128_RATE); + + out0 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; + out1 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; + out2 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; + out3 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; + + if (outlen % SHAKE128_RATE) { + keccak_squeezeblocks4x(t0, t1, t2, t3, 1, s, SHAKE128_RATE); + for (i = 0; i < outlen % SHAKE128_RATE; i++) { + out0[i] = t0[i]; + out1[i] = t1[i]; + out2[i] = t2[i]; + out3[i] = t3[i]; + } + } +} + + +void shake256x4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, unsigned long long outlen, + unsigned char *in0, + unsigned char *in1, + unsigned char *in2, + unsigned char *in3, unsigned long long inlen) { + __m256i s[25]; + unsigned char t0[SHAKE256_RATE]; + unsigned char t1[SHAKE256_RATE]; + unsigned char t2[SHAKE256_RATE]; + unsigned char t3[SHAKE256_RATE]; + unsigned int i; + + /* zero state */ + for (i = 0; i < 25; i++) { + s[i] = _mm256_xor_si256(s[i], s[i]); + } + + /* absorb 4 message of identical length in parallel */ + keccak_absorb4x(s, SHAKE256_RATE, in0, in1, in2, in3, inlen, 0x1F); + + /* Squeeze output */ + keccak_squeezeblocks4x(out0, out1, out2, out3, outlen / SHAKE256_RATE, s, SHAKE256_RATE); + + out0 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; + out1 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; + out2 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; + out3 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; + + if (outlen % SHAKE256_RATE) { + keccak_squeezeblocks4x(t0, t1, t2, t3, 1, s, SHAKE256_RATE); + for (i = 0; i < outlen % SHAKE256_RATE; i++) { + out0[i] = t0[i]; + out1[i] = t1[i]; + out2[i] = t2[i]; + out3[i] = t3[i]; + } + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/fips202x4.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/fips202x4.h new file mode 100644 index 0000000000..2b93c9cd0d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/fips202x4.h @@ -0,0 +1,28 @@ +#ifndef SPX_FIPS202X4_H +#define SPX_FIPS202X4_H + +#include + +#include "params.h" + +#define shake128x4 SPX_NAMESPACE(shake128x4) +void shake128x4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, unsigned long long outlen, + unsigned char *in0, + unsigned char *in1, + unsigned char *in2, + unsigned char *in3, unsigned long long inlen); + +#define shake256x4 SPX_NAMESPACE(shake256x4) +void shake256x4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, unsigned long long outlen, + unsigned char *in0, + unsigned char *in1, + unsigned char *in2, + unsigned char *in3, unsigned long long inlen); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/fors.c b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/fors.c new file mode 100644 index 0000000000..f1b0639cfc --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/fors.c @@ -0,0 +1,202 @@ +#include +#include +#include + +#include "fors.h" + +#include "address.h" +#include "hash.h" +#include "hashx4.h" +#include "thash.h" +#include "thashx4.h" +#include "utils.h" +#include "utilsx4.h" + +static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + prf_addr(sk, ctx, fors_leaf_addr); +} + +static void fors_gen_skx4(unsigned char *sk0, + unsigned char *sk1, + unsigned char *sk2, + unsigned char *sk3, const spx_ctx *ctx, + uint32_t fors_leaf_addrx4[4 * 8]) { + prf_addrx4(sk0, sk1, sk2, sk3, + ctx, fors_leaf_addrx4); +} + +static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, + const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + thash(leaf, sk, 1, ctx, fors_leaf_addr); +} + +static void fors_sk_to_leafx4(unsigned char *leaf0, + unsigned char *leaf1, + unsigned char *leaf2, + unsigned char *leaf3, + const unsigned char *sk0, + const unsigned char *sk1, + const unsigned char *sk2, + const unsigned char *sk3, + const spx_ctx *ctx, + uint32_t fors_leaf_addrx4[4 * 8]) { + thashx4(leaf0, leaf1, leaf2, leaf3, + sk0, sk1, sk2, sk3, + 1, ctx, fors_leaf_addrx4); +} + +struct fors_gen_leaf_info { + uint32_t leaf_addrx[4 * 8]; +}; + +static void fors_gen_leafx4(unsigned char *leaf, + const spx_ctx *ctx, + uint32_t addr_idx, void *info) { + struct fors_gen_leaf_info *fors_info = info; + uint32_t *fors_leaf_addrx4 = fors_info->leaf_addrx; + unsigned int j; + + /* Only set the parts that the caller doesn't set */ + for (j = 0; j < 4; j++) { + set_tree_index(fors_leaf_addrx4 + j * 8, addr_idx + j); + set_type(fors_leaf_addrx4 + j * 8, SPX_ADDR_TYPE_FORSPRF); + } + + fors_gen_skx4(leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + leaf + 2 * SPX_N, + leaf + 3 * SPX_N, + ctx, fors_leaf_addrx4); + + for (j = 0; j < 4; j++) { + set_type(fors_leaf_addrx4 + j * 8, SPX_ADDR_TYPE_FORSTREE); + } + + fors_sk_to_leafx4(leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + leaf + 2 * SPX_N, + leaf + 3 * SPX_N, + leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + leaf + 2 * SPX_N, + leaf + 3 * SPX_N, + ctx, fors_leaf_addrx4); +} + +/** + * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + * Assumes indices has space for SPX_FORS_TREES integers. + */ +static void message_to_indices(uint32_t *indices, const unsigned char *m) { + unsigned int i, j; + unsigned int offset = 0; + + for (i = 0; i < SPX_FORS_TREES; i++) { + indices[i] = 0; + for (j = 0; j < SPX_FORS_HEIGHT; j++) { + indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); + offset++; + } + } +} + +/** + * Signs a message m, deriving the secret key from sk_seed and the FTS address. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + uint32_t fors_tree_addr[4 * 8] = {0}; + struct fors_gen_leaf_info fors_info = {0}; + uint32_t *fors_leaf_addr = fors_info.leaf_addrx; + uint32_t fors_pk_addr[8] = {0}; + uint32_t idx_offset; + unsigned int i; + + for (i = 0; i < 4; i++) { + copy_keypair_addr(fors_tree_addr + 8 * i, fors_addr); + set_type(fors_tree_addr + 8 * i, SPX_ADDR_TYPE_FORSTREE); + copy_keypair_addr(fors_leaf_addr + 8 * i, fors_addr); + } + copy_keypair_addr(fors_pk_addr, fors_addr); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); + + message_to_indices(indices, m); + + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); + + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + + /* Include the secret key part that produces the selected leaf node. */ + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); + fors_gen_sk(sig, ctx, fors_tree_addr); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + sig += SPX_N; + + /* Compute the authentication path for this leaf node. */ + treehashx4(roots + i * SPX_N, sig, ctx, + indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx4, + fors_tree_addr, &fors_info); + + sig += SPX_N * SPX_FORS_HEIGHT; + } + + /* Hash horizontally across all tree roots to derive the public key. */ + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); +} + +/** + * Derives the FORS public key from a signature. + * This can be used for verification by comparing to a known public key, or to + * subsequently verify a signature on the derived public key. The latter is the + * typical use-case when used as an FTS below an OTS in a hypertree. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + unsigned char leaf[SPX_N]; + uint32_t fors_tree_addr[8] = {0}; + uint32_t fors_pk_addr[8] = {0}; + uint32_t idx_offset; + unsigned int i; + + copy_keypair_addr(fors_tree_addr, fors_addr); + copy_keypair_addr(fors_pk_addr, fors_addr); + + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); + + message_to_indices(indices, m); + + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); + + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + + /* Derive the leaf from the included secret key part. */ + fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); + sig += SPX_N; + + /* Derive the corresponding root node of this tree. */ + compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, + sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); + sig += SPX_N * SPX_FORS_HEIGHT; + } + + /* Hash horizontally across all tree roots to derive the public key. */ + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/fors.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/fors.h new file mode 100644 index 0000000000..509140a178 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/fors.h @@ -0,0 +1,32 @@ +#ifndef SPX_FORS_H +#define SPX_FORS_H + +#include + +#include "context.h" +#include "params.h" + +/** + * Signs a message m, deriving the secret key from sk_seed and the FTS address. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +#define fors_sign SPX_NAMESPACE(fors_sign) +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); + +/** + * Derives the FORS public key from a signature. + * This can be used for verification by comparing to a known public key, or to + * subsequently verify a signature on the derived public key. The latter is the + * typical use-case when used as an FTS below an OTS in a hypertree. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/hash.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/hash.h new file mode 100644 index 0000000000..f7c87d4c3c --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/hash.h @@ -0,0 +1,28 @@ +#ifndef SPX_HASH_H +#define SPX_HASH_H + +#include +#include + +#include "context.h" +#include "params.h" + +#define prf_addr SPX_NAMESPACE(prf_addr) +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]); + +#define gen_message_random SPX_NAMESPACE(gen_message_random) +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); + +#define hash_message SPX_NAMESPACE(hash_message) +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); + + + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/hash_shake.c b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/hash_shake.c new file mode 100644 index 0000000000..ff5e7ec918 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/hash_shake.c @@ -0,0 +1,83 @@ +#include +#include + +#include "hash.h" + +#include "address.h" +#include "fips202.h" +#include "params.h" +#include "utils.h" + +/* + * Computes PRF(pk_seed, sk_seed, addr) + */ +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]) { + unsigned char buf[2 * SPX_N + SPX_ADDR_BYTES]; + + memcpy(buf, ctx->pub_seed, SPX_N); + memcpy(buf + SPX_N, addr, SPX_ADDR_BYTES); + memcpy(buf + SPX_N + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); + + shake256(out, SPX_N, buf, 2 * SPX_N + SPX_ADDR_BYTES); +} + +/** + * Computes the message-dependent randomness R, using a secret seed and an + * optional randomization value as well as the message. + */ +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { + (void)ctx; + shake256incctx s_inc; + + shake256_inc_init(&s_inc); + shake256_inc_absorb(&s_inc, sk_prf, SPX_N); + shake256_inc_absorb(&s_inc, optrand, SPX_N); + shake256_inc_absorb(&s_inc, m, mlen); + shake256_inc_finalize(&s_inc); + shake256_inc_squeeze(R, SPX_N, &s_inc); + shake256_inc_ctx_release(&s_inc); +} + +/** + * Computes the message hash using R, the public key, and the message. + * Outputs the message digest and the index of the leaf. The index is split in + * the tree index and the leaf index, for convenient copying to an address. + */ +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { + (void)ctx; +#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) +#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) +#define SPX_LEAF_BITS SPX_TREE_HEIGHT +#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) +#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) + + unsigned char buf[SPX_DGST_BYTES]; + unsigned char *bufp = buf; + shake256incctx s_inc; + + shake256_inc_init(&s_inc); + shake256_inc_absorb(&s_inc, R, SPX_N); + shake256_inc_absorb(&s_inc, pk, SPX_PK_BYTES); + shake256_inc_absorb(&s_inc, m, mlen); + shake256_inc_finalize(&s_inc); + shake256_inc_squeeze(buf, SPX_DGST_BYTES, &s_inc); + shake256_inc_ctx_release(&s_inc); + + memcpy(digest, bufp, SPX_FORS_MSG_BYTES); + bufp += SPX_FORS_MSG_BYTES; + + + *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); + *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); + bufp += SPX_TREE_BYTES; + + *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); + *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/hash_shakex4.c b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/hash_shakex4.c new file mode 100644 index 0000000000..bbd22eb117 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/hash_shakex4.c @@ -0,0 +1,64 @@ +#include +#include + +#include "hashx4.h" + +#include "address.h" +#include "fips202x4.h" +#include "params.h" + +extern void KeccakP1600times4_PermuteAll_24rounds(__m256i *s); + +/* + * 4-way parallel version of prf_addr; takes 4x as much input and output + */ +void prf_addrx4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const spx_ctx *ctx, + const uint32_t addrx4[4 * 8]) { + /* As we write and read only a few quadwords, it is more efficient to + * build and extract from the fourway SHAKE256 state by hand. */ + __m256i state[25]; + + for (int i = 0; i < SPX_N / 8; i++) { + state[i] = _mm256_set1_epi64x(((int64_t *)ctx->pub_seed)[i]); + } + for (int i = 0; i < 4; i++) { + state[SPX_N / 8 + i] = _mm256_set_epi32( + (int)addrx4[3 * 8 + 1 + 2 * i], + (int)addrx4[3 * 8 + 2 * i], + (int)addrx4[2 * 8 + 1 + 2 * i], + (int)addrx4[2 * 8 + 2 * i], + (int)addrx4[8 + 1 + 2 * i], + (int)addrx4[8 + 2 * i], + (int)addrx4[1 + 2 * i], + (int)addrx4[2 * i] + ); + } + for (int i = 0; i < SPX_N / 8; i++) { + state[SPX_N / 8 + i + 4] = _mm256_set1_epi64x(((int64_t *)ctx->sk_seed)[i]); + } + + /* SHAKE domain separator and padding. */ + state[SPX_N / 4 + 4] = _mm256_set1_epi64x(0x1f); + for (int i = SPX_N / 4 + 5; i < 16; i++) { + state[i] = _mm256_set1_epi64x(0); + } + // shift unsigned and then cast to avoid UB + state[16] = _mm256_set1_epi64x((long long)(0x80ULL << 56)); + + for (int i = 17; i < 25; i++) { + state[i] = _mm256_set1_epi64x(0); + } + + KeccakP1600times4_PermuteAll_24rounds(&state[0]); + + for (int i = 0; i < SPX_N / 8; i++) { + ((int64_t *)out0)[i] = _mm256_extract_epi64(state[i], 0); + ((int64_t *)out1)[i] = _mm256_extract_epi64(state[i], 1); + ((int64_t *)out2)[i] = _mm256_extract_epi64(state[i], 2); + ((int64_t *)out3)[i] = _mm256_extract_epi64(state[i], 3); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/hashx4.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/hashx4.h new file mode 100644 index 0000000000..3751a0ebd0 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/hashx4.h @@ -0,0 +1,17 @@ +#ifndef SPX_HASHX4_H +#define SPX_HASHX4_H + +#include + +#include "context.h" +#include "params.h" + +#define prf_addrx4 SPX_NAMESPACE(prf_addrx4) +void prf_addrx4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const spx_ctx *ctx, + const uint32_t addrx4[4 * 8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/merkle.c b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/merkle.c new file mode 100644 index 0000000000..f57811c1ac --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/merkle.c @@ -0,0 +1,64 @@ +#include +#include + +#include "merkle.h" + +#include "address.h" +#include "params.h" +#include "utils.h" +#include "utilsx4.h" +#include "wots.h" +#include "wotsx4.h" + +/* + * This generates a Merkle signature (WOTS signature followed by the Merkle + * authentication path). + */ +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf) { + unsigned char *auth_path = sig + SPX_WOTS_BYTES; + uint32_t tree_addrx4[4 * 8] = { 0 }; + int j; + struct leaf_info_x4 info = { 0 }; + unsigned steps[ SPX_WOTS_LEN ]; + + info.wots_sig = sig; + chain_lengths(steps, root); + info.wots_steps = steps; + + for (j = 0; j < 4; j++) { + set_type(&tree_addrx4[8 * j], SPX_ADDR_TYPE_HASHTREE); + set_type(&info.leaf_addr[8 * j], SPX_ADDR_TYPE_WOTS); + set_type(&info.pk_addr[8 * j], SPX_ADDR_TYPE_WOTSPK); + copy_subtree_addr(&tree_addrx4[8 * j], tree_addr); + copy_subtree_addr(&info.leaf_addr[8 * j], wots_addr); + copy_subtree_addr(&info.pk_addr[8 * j], wots_addr); + } + + info.wots_sign_leaf = idx_leaf; + + treehashx4(root, auth_path, ctx, + idx_leaf, 0, + SPX_TREE_HEIGHT, + wots_gen_leafx4, + tree_addrx4, &info); +} + +/* Compute root node of the top-most subtree. */ +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { + /* We do not need the auth path in key generation, but it simplifies the + code to have just one treehash routine that computes both root and path + in one function. */ + unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; + uint32_t top_tree_addr[8] = {0}; + uint32_t wots_addr[8] = {0}; + + set_layer_addr(top_tree_addr, SPX_D - 1); + set_layer_addr(wots_addr, SPX_D - 1); + + merkle_sign(auth_path, root, ctx, + wots_addr, top_tree_addr, + ~0U /* ~0 means "don't bother generating an auth path */ ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/merkle.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/merkle.h new file mode 100644 index 0000000000..769cf2e970 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/merkle.h @@ -0,0 +1,21 @@ +#ifndef MERKLE_H_ +#define MERKLE_H_ + +#include + +#include "context.h" +#include "params.h" + +/* Generate a Merkle signature (WOTS signature followed by the Merkle */ +/* authentication path) */ +#define merkle_sign SPX_NAMESPACE(merkle_sign) +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf); + +/* Compute the root node of the top-most subtree. */ +#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); + +#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/nistapi.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/nistapi.h new file mode 100644 index 0000000000..3cb71afad4 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/nistapi.h @@ -0,0 +1,87 @@ +#ifndef SPX_API_H +#define SPX_API_H + +#include +#include + +#include "params.h" + +#define CRYPTO_ALGNAME "SPHINCS+" + +#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES +#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES +#define CRYPTO_BYTES SPX_BYTES +#define CRYPTO_SEEDBYTES (3*SPX_N) + +/* + * Returns the length of a secret key, in bytes + */ +#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) +size_t crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) +size_t crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) +size_t crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) +size_t crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +#define crypto_sign SPX_NAMESPACE(crypto_sign) +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/params.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/params.h new file mode 100644 index 0000000000..f5cceeee2a --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/params.h @@ -0,0 +1,56 @@ +#ifndef SPX_PARAMS_H +#define SPX_PARAMS_H + +#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSSHAKE192FSIMPLE_AVX2_##s + +/* Hash output length in bytes. */ +#define SPX_N 24 +/* Height of the hypertree. */ +#define SPX_FULL_HEIGHT 66 +/* Number of subtree layer. */ +#define SPX_D 22 +/* FORS tree dimensions. */ +#define SPX_FORS_HEIGHT 8 +#define SPX_FORS_TREES 33 +/* Winternitz parameter, */ +#define SPX_WOTS_W 16 + +/* The hash function is defined by linking a different hash.c file, as opposed + to setting a #define constant. */ + +/* For clarity */ +#define SPX_ADDR_BYTES 32 + +/* WOTS parameters. */ +#define SPX_WOTS_LOGW 4 + +#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) + +/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ +#define SPX_WOTS_LEN2 3 + +#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) +#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) +#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES + +/* Subtree size. */ +#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) + +//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT +// #error SPX_D should always divide SPX_FULL_HEIGHT +//#endif + +/* FORS parameters. */ +#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) +#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) +#define SPX_FORS_PK_BYTES SPX_N + +/* Resulting SPX sizes. */ +#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ + SPX_FULL_HEIGHT * SPX_N) +#define SPX_PK_BYTES (2 * SPX_N) +#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) + +#include "shake_offsets.h" + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/shake_offsets.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/shake_offsets.h new file mode 100644 index 0000000000..6b28d95d91 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/shake_offsets.h @@ -0,0 +1,21 @@ +#ifndef SHAKE_OFFSETS_H_ +#define SHAKE_OFFSETS_H_ + +/* + * Offsets of various fields in the address structure when we use SHAKE as + * the Sphincs+ hash function + */ + +#define SPX_OFFSET_LAYER 3 /* The byte used to specify the Merkle tree layer */ +#define SPX_OFFSET_TREE 8 /* The start of the 8 byte field used to specify the tree */ +#define SPX_OFFSET_TYPE 19 /* The byte used to specify the hash type (reason) */ +#define SPX_OFFSET_KP_ADDR2 22 /* The high byte used to specify the key pair (which one-time signature) */ +#define SPX_OFFSET_KP_ADDR1 23 /* The low byte used to specify the key pair */ +#define SPX_OFFSET_CHAIN_ADDR 27 /* The byte used to specify the chain address (which Winternitz chain) */ +#define SPX_OFFSET_HASH_ADDR 31 /* The byte used to specify the hash address (where in the Winternitz chain) */ +#define SPX_OFFSET_TREE_HGT 27 /* The byte used to specify the height of this node in the FORS or Merkle tree */ +#define SPX_OFFSET_TREE_INDEX 28 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ + +#define SPX_SHAKE 1 + +#endif /* SHAKE_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/sign.c b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/sign.c new file mode 100644 index 0000000000..9d0c7d1b22 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/sign.c @@ -0,0 +1,286 @@ +#include +#include +#include + +#include "address.h" +#include "context.h" +#include "fors.h" +#include "hash.h" +#include "merkle.h" +#include "nistapi.h" +#include "params.h" +#include "randombytes.h" +#include "thash.h" +#include "utils.h" +#include "wots.h" + +/* + * Returns the length of a secret key, in bytes + */ +size_t crypto_sign_secretkeybytes(void) { + return CRYPTO_SECRETKEYBYTES; +} + +/* + * Returns the length of a public key, in bytes + */ +size_t crypto_sign_publickeybytes(void) { + return CRYPTO_PUBLICKEYBYTES; +} + +/* + * Returns the length of a signature, in bytes + */ +size_t crypto_sign_bytes(void) { + return CRYPTO_BYTES; +} + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +size_t crypto_sign_seedbytes(void) { + return CRYPTO_SEEDBYTES; +} + +/* + * Generates an SPX key pair given a seed of length + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [PUB_SEED || root] + */ +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed) { + spx_ctx ctx; + + /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ + memcpy(sk, seed, CRYPTO_SEEDBYTES); + + memcpy(pk, sk + 2 * SPX_N, SPX_N); + + memcpy(ctx.pub_seed, pk, SPX_N); + memcpy(ctx.sk_seed, sk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + /* Compute root node of the top-most subtree. */ + merkle_gen_root(sk + 3 * SPX_N, &ctx); + + // cleanup + free_hash_function(&ctx); + + memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); + + return 0; +} + +/* + * Generates an SPX key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [PUB_SEED || root] + */ +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { + uint8_t seed[CRYPTO_SEEDBYTES]; + randombytes(seed, CRYPTO_SEEDBYTES); + crypto_sign_seed_keypair(pk, sk, seed); + + return 0; +} + +/** + * Returns an array containing a detached signature. + */ +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk) { + spx_ctx ctx; + + const uint8_t *sk_prf = sk + SPX_N; + const uint8_t *pk = sk + 2 * SPX_N; + + uint8_t optrand[SPX_N]; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t root[SPX_N]; + uint32_t i; + uint64_t tree; + uint32_t idx_leaf; + uint32_t wots_addr[8] = {0}; + uint32_t tree_addr[8] = {0}; + + memcpy(ctx.sk_seed, sk, SPX_N); + memcpy(ctx.pub_seed, pk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + + /* Optionally, signing can be made non-deterministic using optrand. + This can help counter side-channel attacks that would benefit from + getting a large number of traces when the signer uses the same nodes. */ + randombytes(optrand, SPX_N); + /* Compute the digest randomization value. */ + gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); + + /* Derive the message digest and leaf index from R, PK and M. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; + + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); + + /* Sign the message hash using FORS. */ + fors_sign(sig, root, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); + sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; + + /* Update the indices for the next layer. */ + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; + } + + free_hash_function(&ctx); + + *siglen = SPX_BYTES; + + return 0; +} + +/** + * Verifies a detached signature and message under a given public key. + */ +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk) { + spx_ctx ctx; + const uint8_t *pub_root = pk + SPX_N; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t wots_pk[SPX_WOTS_BYTES]; + uint8_t root[SPX_N]; + uint8_t leaf[SPX_N]; + unsigned int i; + uint64_t tree; + uint32_t idx_leaf; + uint32_t wots_addr[8] = {0}; + uint32_t tree_addr[8] = {0}; + uint32_t wots_pk_addr[8] = {0}; + + if (siglen != SPX_BYTES) { + return -1; + } + + memcpy(ctx.pub_seed, pk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); + + /* Derive the message digest and leaf index from R || PK || M. */ + /* The additional SPX_N is a result of the hash domain separator. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; + + /* Layer correctly defaults to 0, so no need to set_layer_addr */ + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); + + fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + /* For each subtree.. */ + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + copy_keypair_addr(wots_pk_addr, wots_addr); + + /* The WOTS public key is only correct if the signature was correct. */ + /* Initially, root is the FORS pk, but on subsequent iterations it is + the root of the subtree below the currently processed subtree. */ + wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); + sig += SPX_WOTS_BYTES; + + /* Compute the leaf node using the WOTS public key. */ + thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); + + /* Compute the root node of this subtree. */ + compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, + &ctx, tree_addr); + sig += SPX_TREE_HEIGHT * SPX_N; + + /* Update the indices for the next layer. */ + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; + } + + // cleanup + free_hash_function(&ctx); + + /* Check if the root node equals the root node in the public key. */ + if (memcmp(root, pub_root, SPX_N) != 0) { + return -1; + } + + return 0; +} + + +/** + * Returns an array containing the signature followed by the message. + */ +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk) { + size_t siglen; + + crypto_sign_signature(sm, &siglen, m, mlen, sk); + + memmove(sm + SPX_BYTES, m, mlen); + *smlen = siglen + mlen; + + return 0; +} + +/** + * Verifies a given signature-message pair under a given public key. + */ +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk) { + /* The API caller does not necessarily know what size a signature should be + but SPHINCS+ signatures are always exactly SPX_BYTES. */ + if (smlen < SPX_BYTES) { + memset(m, 0, smlen); + *mlen = 0; + return -1; + } + + *mlen = smlen - SPX_BYTES; + + if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { + memset(m, 0, smlen); + *mlen = 0; + return -1; + } + + /* If verification was successful, move the message to the right place. */ + memmove(m, sm + SPX_BYTES, *mlen); + + return 0; +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/thash.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/thash.h new file mode 100644 index 0000000000..8687ccfb4d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/thash.h @@ -0,0 +1,13 @@ +#ifndef SPX_THASH_H +#define SPX_THASH_H + +#include "context.h" +#include "params.h" + +#include + +#define thash SPX_NAMESPACE(thash) +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/thash_shake_simple.c b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/thash_shake_simple.c new file mode 100644 index 0000000000..98470395e9 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/thash_shake_simple.c @@ -0,0 +1,24 @@ +#include +#include + +#include "thash.h" + +#include "address.h" +#include "params.h" +#include "utils.h" + +#include "fips202.h" + +/** + * Takes an array of inblocks concatenated arrays of SPX_N bytes. + */ +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]) { + PQCLEAN_VLA(uint8_t, buf, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); + + memcpy(buf, ctx->pub_seed, SPX_N); + memcpy(buf + SPX_N, addr, SPX_ADDR_BYTES); + memcpy(buf + SPX_N + SPX_ADDR_BYTES, in, inblocks * SPX_N); + + shake256(out, SPX_N, buf, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/thash_shake_simplex4.c b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/thash_shake_simplex4.c new file mode 100644 index 0000000000..89dc9a4224 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/thash_shake_simplex4.c @@ -0,0 +1,98 @@ +#include +#include + +#include "thashx4.h" + +#include "address.h" +#include "params.h" +#include "utils.h" + +#include "fips202x4.h" + +extern void KeccakP1600times4_PermuteAll_24rounds(__m256i *s); + +/** + * 4-way parallel version of thash; takes 4x as much input and output + */ +void thashx4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addrx4[4 * 8]) { + if (inblocks == 1 || inblocks == 2) { + /* As we write and read only a few quadwords, it is more efficient to + * build and extract from the fourway SHAKE256 state by hand. */ + __m256i state[25]; + for (int i = 0; i < SPX_N / 8; i++) { + state[i] = _mm256_set1_epi64x(((int64_t *)ctx->pub_seed)[i]); + } + for (int i = 0; i < 4; i++) { + state[SPX_N / 8 + i] = _mm256_set_epi32( + (int)addrx4[3 * 8 + 1 + 2 * i], + (int)addrx4[3 * 8 + 2 * i], + (int)addrx4[2 * 8 + 1 + 2 * i], + (int)addrx4[2 * 8 + 2 * i], + (int)addrx4[8 + 1 + 2 * i], + (int)addrx4[8 + 2 * i], + (int)addrx4[1 + 2 * i], + (int)addrx4[2 * i] + ); + } + + for (unsigned int i = 0; i < (SPX_N / 8) * inblocks; i++) { + state[SPX_N / 8 + 4 + i] = _mm256_set_epi64x( + ((int64_t *)in3)[i], + ((int64_t *)in2)[i], + ((int64_t *)in1)[i], + ((int64_t *)in0)[i] + ); + } + + /* Domain separator and padding. */ + for (size_t i = (SPX_N / 8) * (1 + inblocks) + 4; i < 16; i++) { + state[i] = _mm256_set1_epi64x(0); + } + state[16] = _mm256_set1_epi64x((long long)(0x80ULL << 56)); + state[(SPX_N / 8) * (1 + inblocks) + 4] = _mm256_xor_si256( + state[(SPX_N / 8) * (1 + inblocks) + 4], + _mm256_set1_epi64x(0x1f) + ); + for (int i = 17; i < 25; i++) { + state[i] = _mm256_set1_epi64x(0); + } + + KeccakP1600times4_PermuteAll_24rounds(&state[0]); + + for (int i = 0; i < SPX_N / 8; i++) { + ((int64_t *)out0)[i] = _mm256_extract_epi64(state[i], 0); + ((int64_t *)out1)[i] = _mm256_extract_epi64(state[i], 1); + ((int64_t *)out2)[i] = _mm256_extract_epi64(state[i], 2); + ((int64_t *)out3)[i] = _mm256_extract_epi64(state[i], 3); + } + } else { + PQCLEAN_VLA(unsigned char, buf0, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, buf1, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, buf2, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, buf3, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); + + memcpy(buf0, ctx->pub_seed, SPX_N); + memcpy(buf1, ctx->pub_seed, SPX_N); + memcpy(buf2, ctx->pub_seed, SPX_N); + memcpy(buf3, ctx->pub_seed, SPX_N); + memcpy(buf0 + SPX_N, addrx4 + 0 * 8, SPX_ADDR_BYTES); + memcpy(buf1 + SPX_N, addrx4 + 1 * 8, SPX_ADDR_BYTES); + memcpy(buf2 + SPX_N, addrx4 + 2 * 8, SPX_ADDR_BYTES); + memcpy(buf3 + SPX_N, addrx4 + 3 * 8, SPX_ADDR_BYTES); + memcpy(buf0 + SPX_N + SPX_ADDR_BYTES, in0, inblocks * SPX_N); + memcpy(buf1 + SPX_N + SPX_ADDR_BYTES, in1, inblocks * SPX_N); + memcpy(buf2 + SPX_N + SPX_ADDR_BYTES, in2, inblocks * SPX_N); + memcpy(buf3 + SPX_N + SPX_ADDR_BYTES, in3, inblocks * SPX_N); + + shake256x4(out0, out1, out2, out3, SPX_N, + buf0, buf1, buf2, buf3, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/thashx4.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/thashx4.h new file mode 100644 index 0000000000..64798a3727 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/thashx4.h @@ -0,0 +1,20 @@ +#ifndef SPX_THASHX4_H +#define SPX_THASHX4_H + +#include + +#include "context.h" +#include "params.h" + +#define thashx4 SPX_NAMESPACE(thashx4) +void thashx4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addrx4[4 * 8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/utils.c b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/utils.c new file mode 100644 index 0000000000..177b541fb9 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/utils.c @@ -0,0 +1,148 @@ +#include + +#include "utils.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "thash.h" + +/** + * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. + */ +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in) { + int i; + + /* Iterate over out in decreasing order, for big-endianness. */ + for (i = (signed int)outlen - 1; i >= 0; i--) { + out[i] = in & 0xff; + in = in >> 8; + } +} + +void u32_to_bytes(unsigned char *out, uint32_t in) { + out[0] = (unsigned char)(in >> 24); + out[1] = (unsigned char)(in >> 16); + out[2] = (unsigned char)(in >> 8); + out[3] = (unsigned char)in; +} + +/** + * Converts the inlen bytes in 'in' from big-endian byte order to an integer. + */ +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { + unsigned long long retval = 0; + unsigned int i; + + for (i = 0; i < inlen; i++) { + retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); + } + return retval; +} + +/** + * Computes a root node given a leaf and an auth path. + * Expects address to be complete other than the tree_height and tree_index. + */ +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]) { + uint32_t i; + unsigned char buffer[2 * SPX_N]; + + /* If leaf_idx is odd (last bit = 1), current path element is a right child + and auth_path has to go left. Otherwise it is the other way around. */ + if (leaf_idx & 1) { + memcpy(buffer + SPX_N, leaf, SPX_N); + memcpy(buffer, auth_path, SPX_N); + } else { + memcpy(buffer, leaf, SPX_N); + memcpy(buffer + SPX_N, auth_path, SPX_N); + } + auth_path += SPX_N; + + for (i = 0; i < tree_height - 1; i++) { + leaf_idx >>= 1; + idx_offset >>= 1; + /* Set the address of the node we're creating. */ + set_tree_height(addr, i + 1); + set_tree_index(addr, leaf_idx + idx_offset); + + /* Pick the right or left neighbor, depending on parity of the node. */ + if (leaf_idx & 1) { + thash(buffer + SPX_N, buffer, 2, ctx, addr); + memcpy(buffer, auth_path, SPX_N); + } else { + thash(buffer, buffer, 2, ctx, addr); + memcpy(buffer + SPX_N, auth_path, SPX_N); + } + auth_path += SPX_N; + } + + /* The last iteration is exceptional; we do not copy an auth_path node. */ + leaf_idx >>= 1; + idx_offset >>= 1; + set_tree_height(addr, tree_height); + set_tree_index(addr, leaf_idx + idx_offset); + thash(root, buffer, 2, ctx, addr); +} + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx * /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]) { + PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); + PQCLEAN_VLA(unsigned int, heights, tree_height + 1); + unsigned int offset = 0; + uint32_t idx; + uint32_t tree_idx; + + for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { + /* Add the next leaf node to the stack. */ + gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); + offset++; + heights[offset - 1] = 0; + + /* If this is a node we need for the auth path.. */ + if ((leaf_idx ^ 0x1) == idx) { + memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); + } + + /* While the top-most nodes are of equal height.. */ + while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { + /* Compute index of the new node, in the next layer. */ + tree_idx = (idx >> (heights[offset - 1] + 1)); + + /* Set the address of the node we're creating. */ + set_tree_height(tree_addr, heights[offset - 1] + 1); + set_tree_index(tree_addr, + tree_idx + (idx_offset >> (heights[offset - 1] + 1))); + /* Hash the top-most nodes from the stack together. */ + thash(stack + (offset - 2)*SPX_N, + stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); + offset--; + /* Note that the top-most node is now one layer higher. */ + heights[offset - 1]++; + + /* If this is a node we need for the auth path.. */ + if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { + memcpy(auth_path + heights[offset - 1]*SPX_N, + stack + (offset - 1)*SPX_N, SPX_N); + } + } + } + memcpy(root, stack, SPX_N); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/utils.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/utils.h new file mode 100644 index 0000000000..64f5d5a53a --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/utils.h @@ -0,0 +1,58 @@ +#ifndef SPX_UTILS_H +#define SPX_UTILS_H + +#include + +#include "compat.h" +#include "context.h" +#include "params.h" + + +/* To support MSVC use alloca() instead of VLAs. See #20. */ + + +/** + * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. + */ +#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in); +#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) +void u32_to_bytes(unsigned char *out, uint32_t in); + +/** + * Converts the inlen bytes in 'in' from big-endian byte order to an integer. + */ +#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); + +/** + * Computes a root node given a leaf and an auth path. + * Expects address to be complete other than the tree_height and tree_index. + */ +#define compute_root SPX_NAMESPACE(compute_root) +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]); + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +#define treehash SPX_NAMESPACE(treehash) +void treehash(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx *ctx /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]); + + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/utilsx4.c b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/utilsx4.c new file mode 100644 index 0000000000..1638677194 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/utilsx4.c @@ -0,0 +1,138 @@ +#include + +#include "utilsx4.h" + +#include "address.h" +#include "params.h" +#include "thashx4.h" +#include "utils.h" + +/* + * Generate the entire Merkle tree, computing the authentication path for leaf_idx, + * and the resulting root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) + * + * This expects tree_addrx4 to be initialized to 4 parallel addr structures for + * the Merkle tree nodes + * + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + * + * This works by using the standard Merkle tree building algorithm, except + * that each 'node' tracked is actually 4 consecutive nodes in the real tree. + * When we combine two logical nodes ABCD and WXYZ, we perform the H + * operation on adjacent real nodes, forming the parent logical node + * (AB)(CD)(WX)(YZ) + * + * When we get to the top two levels of the real tree (where there is only + * one logical node), we continue this operation two more times; the right + * most real node will by the actual root (and the other 3 nodes will be + * garbage). We follow the same thashx4 logic so that the 'extract + * authentication path components' part of the loop is still executed (and + * to simplify the code somewhat) + * + * This currently assumes tree_height >= 2; I suspect that doing an adjusting + * idx, addr_idx on the gen_leafx4 call if tree_height < 2 would fix it; since + * we don't actually use such short trees, I haven't bothered + */ +void treehashx4(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, + uint32_t tree_height, + void (*gen_leafx4)( + unsigned char * /* Where to write the leaves */, + const spx_ctx *, + uint32_t idx, void *info), + uint32_t tree_addrx4[4 * 8], + void *info) { + /* This is where we keep the intermediate nodes */ + PQCLEAN_VLA(unsigned char, stackx4, tree_height * 4 * SPX_N); + uint32_t left_adj = 0, prev_left_adj = 0; /* When we're doing the top 3 */ + /* levels, the left-most part of the tree isn't at the beginning */ + /* of current[]. These give the offset of the actual start */ + + uint32_t idx; + uint32_t max_idx = (1U << (tree_height - 2)) - 1; + for (idx = 0;; idx++) { + unsigned char current[4 * SPX_N]; /* Current logical node */ + gen_leafx4( current, ctx, 4 * idx + idx_offset, + info ); + + /* Now combine the freshly generated right node with previously */ + /* generated left ones */ + uint32_t internal_idx_offset = idx_offset; + uint32_t internal_idx = idx; + uint32_t internal_leaf = leaf_idx; + uint32_t h; /* The height we are in the Merkle tree */ + for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { + + /* Special processing if we're at the top of the tree */ + if (h >= tree_height - 2) { + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[3 * SPX_N], SPX_N ); + return; + } + /* The tree indexing logic is a bit off in this case */ + /* Adjust it so that the left-most node of the part of */ + /* the tree that we're processing has index 0 */ + prev_left_adj = left_adj; + left_adj = 4U - (1 << (tree_height - h - 1)); + } + + /* Check if we hit the top of the tree */ + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[3 * SPX_N], SPX_N ); + return; + } + + /* + * Check if one of the nodes we have is a part of the + * authentication path; if it is, write it out + */ + if ((((internal_idx << 2) ^ internal_leaf) & ~0x3U) == 0) { + memcpy( &auth_path[ h * SPX_N ], + ¤t[(((internal_leaf & 3) ^ 1) + prev_left_adj) * SPX_N], + SPX_N ); + } + + /* + * Check if we're at a left child; if so, stop going up the stack + * Exception: if we've reached the end of the tree, keep on going + * (so we combine the last 4 nodes into the one root node in two + * more iterations) + */ + if ((internal_idx & 1) == 0 && idx < max_idx) { + break; + } + + /* Ok, we're at a right node (or doing the top 3 levels) */ + /* Now combine the left and right logical nodes together */ + + /* Set the address of the node we're creating. */ + unsigned int j; + internal_idx_offset >>= 1; + for (j = 0; j < 4; j++) { + set_tree_height(tree_addrx4 + j * 8, h + 1); + set_tree_index(tree_addrx4 + j * 8, + (4 / 2) * (internal_idx & ~1U) + j - left_adj + internal_idx_offset ); + } + unsigned char *left = &stackx4[h * 4 * SPX_N]; + thashx4( ¤t[0 * SPX_N], + ¤t[1 * SPX_N], + ¤t[2 * SPX_N], + ¤t[3 * SPX_N], + &left [0 * SPX_N], + &left [2 * SPX_N], + ¤t[0 * SPX_N], + ¤t[2 * SPX_N], + 2, ctx, tree_addrx4); + } + + /* We've hit a left child; save the current for when we get the */ + /* corresponding right right */ + memcpy( &stackx4[h * 4 * SPX_N], current, 4 * SPX_N); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/utilsx4.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/utilsx4.h new file mode 100644 index 0000000000..facb874b18 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/utilsx4.h @@ -0,0 +1,30 @@ +#ifndef SPX_UTILSX4_H +#define SPX_UTILSX4_H + +#include + +#include "context.h" +#include "params.h" + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + * + * This implementation uses AVX to compute internal nodes 4 at a time (in + * parallel) + */ +#define treehashx4 SPX_NAMESPACE(treehashx4) +void treehashx4(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leafx4)( + unsigned char * /* Where to write the leaves */, + const spx_ctx * /* ctx */, + uint32_t addr_idx, void *info), + uint32_t tree_addrx4[4 * 8], void *info); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/wots.c b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/wots.c new file mode 100644 index 0000000000..4d5041ce05 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/wots.c @@ -0,0 +1,269 @@ +#include +#include + +#include "wots.h" + +#include "address.h" +#include "hash.h" +#include "hashx4.h" +#include "params.h" +#include "thash.h" +#include "thashx4.h" +#include "utils.h" +#include "utilsx4.h" +#include "wotsx4.h" + +// TODO clarify address expectations, and make them more uniform. +// TODO i.e. do we expect types to be set already? +// TODO and do we expect modifications or copies? + +/** + * Computes up the chains + */ +static void gen_chains( + unsigned char *out, + const unsigned char *in, + unsigned int start[SPX_WOTS_LEN], + const unsigned int steps[SPX_WOTS_LEN], + const spx_ctx *ctx, + uint32_t addr[8]) { + uint32_t i, j, k, idx, watching; + int done; + unsigned char empty[SPX_N]; + unsigned char *bufs[4]; + uint32_t addrs[8 * 4]; + + int l; + uint16_t counts[SPX_WOTS_W] = { 0 }; + uint16_t idxs[SPX_WOTS_LEN]; + uint16_t total, newTotal; + + /* set addrs = {addr, addr, addr, addr} */ + for (j = 0; j < 4; j++) { + memcpy(addrs + j * 8, addr, sizeof(uint32_t) * 8); + } + + /* Initialize out with the value at position 'start'. */ + memcpy(out, in, SPX_WOTS_LEN * SPX_N); + + /* Sort the chains in reverse order by steps using counting sort. */ + for (i = 0; i < SPX_WOTS_LEN; i++) { + counts[steps[i]]++; + } + total = 0; + for (l = SPX_WOTS_W - 1; l >= 0; l--) { + newTotal = counts[l] + total; + counts[l] = total; + total = newTotal; + } + for (i = 0; i < SPX_WOTS_LEN; i++) { + idxs[counts[steps[i]]] = (uint16_t)i; + counts[steps[i]]++; + } + + /* We got our work cut out for us: do it! */ + for (i = 0; i < SPX_WOTS_LEN; i += 4) { + for (j = 0; j < 4 && i + j < SPX_WOTS_LEN; j++) { + idx = idxs[i + j]; + set_chain_addr(addrs + j * 8, idx); + bufs[j] = out + SPX_N * idx; + } + + /* As the chains are sorted in reverse order, we know that the first + * chain is the longest and the last one is the shortest. We keep + * an eye on whether the last chain is done and then on the one before, + * et cetera. */ + watching = 3; + done = 0; + while (i + watching >= SPX_WOTS_LEN) { + bufs[watching] = &empty[0]; + watching--; + } + + for (k = 0;; k++) { + while (k == steps[idxs[i + watching]]) { + bufs[watching] = &empty[0]; + if (watching == 0) { + done = 1; + break; + } + watching--; + } + if (done) { + break; + } + for (j = 0; j < watching + 1; j++) { + set_hash_addr(addrs + j * 8, k + start[idxs[i + j]]); + } + + thashx4(bufs[0], bufs[1], bufs[2], bufs[3], + bufs[0], bufs[1], bufs[2], bufs[3], 1, ctx, addrs); + } + } +} + +/** + * base_w algorithm as described in draft. + * Interprets an array of bytes as integers in base w. + * This only works when log_w is a divisor of 8. + */ +static void base_w(unsigned int *output, const int out_len, + const unsigned char *input) { + int in = 0; + int out = 0; + unsigned char total = 0; + int bits = 0; + int consumed; + + for (consumed = 0; consumed < out_len; consumed++) { + if (bits == 0) { + total = input[in]; + in++; + bits += 8; + } + bits -= SPX_WOTS_LOGW; + output[out] = (total >> bits) & (SPX_WOTS_W - 1); + out++; + } +} + +/* Computes the WOTS+ checksum over a message (in base_w). */ +static void wots_checksum(unsigned int *csum_base_w, + const unsigned int *msg_base_w) { + unsigned int csum = 0; + unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; + unsigned int i; + + /* Compute checksum. */ + for (i = 0; i < SPX_WOTS_LEN1; i++) { + csum += SPX_WOTS_W - 1 - msg_base_w[i]; + } + + /* Convert checksum to base_w. */ + /* Make sure expected empty zero bits are the least significant bits. */ + csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); + ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); + base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); +} + +/* Takes a message and derives the matching chain lengths. */ +void chain_lengths(unsigned int *lengths, const unsigned char *msg) { + base_w(lengths, SPX_WOTS_LEN1, msg); + wots_checksum(lengths + SPX_WOTS_LEN1, lengths); +} + +/** + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. + * + * Writes the computed public key to 'pk'. + */ +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]) { + unsigned int steps[SPX_WOTS_LEN]; + unsigned int start[SPX_WOTS_LEN]; + uint32_t i; + + chain_lengths(start, msg); + + for (i = 0; i < SPX_WOTS_LEN; i++) { + steps[i] = SPX_WOTS_W - 1 - start[i]; + } + + gen_chains(pk, sig, start, steps, ctx, addr); +} + +/* + * This generates 4 sequential WOTS public keys + * It also generates the WOTS signature if leaf_info indicates + * that we're signing with one of these WOTS keys + */ +void wots_gen_leafx4(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info) { + struct leaf_info_x4 *info = v_info; + uint32_t *leaf_addr = info->leaf_addr; + uint32_t *pk_addr = info->pk_addr; + unsigned int i, j, k; + unsigned char pk_buffer[ 4 * SPX_WOTS_BYTES ]; + unsigned wots_offset = SPX_WOTS_BYTES; + unsigned char *buffer; + uint32_t wots_k_mask; + unsigned wots_sign_index; + + if (((leaf_idx ^ info->wots_sign_leaf) & ~3U) == 0) { + /* We're traversing the leaf that's signing; generate the WOTS */ + /* signature */ + wots_k_mask = 0; + wots_sign_index = info->wots_sign_leaf & 3; /* Which of of the 4 */ + /* 4 slots do the signatures come from */ + } else { + /* Nope, we're just generating pk's; turn off the signature logic */ + wots_k_mask = (uint32_t)~0; + wots_sign_index = 0; + } + + for (j = 0; j < 4; j++) { + set_keypair_addr( leaf_addr + j * 8, leaf_idx + j ); + set_keypair_addr( pk_addr + j * 8, leaf_idx + j ); + } + + for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { + uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k to */ + /* the step if we're generating a signature, ~0 if we're not */ + + /* Start with the secret seed */ + for (j = 0; j < 4; j++) { + set_chain_addr(leaf_addr + j * 8, i); + set_hash_addr(leaf_addr + j * 8, 0); + set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTSPRF); + } + prf_addrx4(buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + buffer + 2 * wots_offset, + buffer + 3 * wots_offset, + ctx, leaf_addr); + + for (j = 0; j < 4; j++) { + set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTS); + } + + /* Iterate down the WOTS chain */ + for (k = 0;; k++) { + /* Check if one of the values we have needs to be saved as a */ + /* part of the WOTS signature */ + if (k == wots_k) { + memcpy( info->wots_sig + i * SPX_N, + buffer + wots_sign_index * wots_offset, SPX_N ); + } + + /* Check if we hit the top of the chain */ + if (k == SPX_WOTS_W - 1) { + break; + } + + /* Iterate one step on all 4 chains */ + for (j = 0; j < 4; j++) { + set_hash_addr(leaf_addr + j * 8, k); + } + thashx4(buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + buffer + 2 * wots_offset, + buffer + 3 * wots_offset, + buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + buffer + 2 * wots_offset, + buffer + 3 * wots_offset, 1, ctx, leaf_addr); + } + } + + /* Do the final thash to generate the public keys */ + thashx4(dest + 0 * SPX_N, + dest + 1 * SPX_N, + dest + 2 * SPX_N, + dest + 3 * SPX_N, + pk_buffer + 0 * wots_offset, + pk_buffer + 1 * wots_offset, + pk_buffer + 2 * wots_offset, + pk_buffer + 3 * wots_offset, SPX_WOTS_LEN, ctx, pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/wots.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/wots.h new file mode 100644 index 0000000000..4e7692eeef --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/wots.h @@ -0,0 +1,25 @@ +#ifndef SPX_WOTS_H +#define SPX_WOTS_H + +#include + +#include "context.h" +#include "params.h" + +/** + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. + * + * Writes the computed public key to 'pk'. + */ +#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]); + +/* + * Compute the chain lengths needed for a given message hash + */ +#define chain_lengths SPX_NAMESPACE(chain_lengths) +void chain_lengths(unsigned int *lengths, const unsigned char *msg); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/wotsx4.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/wotsx4.h new file mode 100644 index 0000000000..cd634f1743 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/wotsx4.h @@ -0,0 +1,41 @@ +#ifndef WOTSX4_H_ +#define WOTSX4_H_ + +#include + +#include "params.h" + +/* + * This is here to provide an interface to the internal wots_gen_leafx4 + * routine. While this routine is not referenced in the package outside of + * wots.c, it is called from the stand-alone benchmark code to characterize + * the performance + */ +struct leaf_info_x4 { + unsigned char *wots_sig; + uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ + uint32_t *wots_steps; + uint32_t leaf_addr[4 * 8]; + uint32_t pk_addr[4 * 8]; +}; + +/* Macro to set the leaf_info to something 'benign', that is, it would */ +/* run with the same time as it does during the real signing process */ +/* Used only by the benchmark code */ +#define INITIALIZE_LEAF_INFO_X4(info, addr, step_buffer) { \ + (info).wots_sig = 0; \ + (info).wots_sign_leaf = ~0; \ + (info).wots_steps = step_buffer; \ + int i; \ + for (i=0; i<4; i++) { \ + memcpy( &(info).leaf_addr[8*i], addr, 32 ); \ + memcpy( &(info).pk_addr[8*i], addr, 32 ); \ + } \ + } + +#define wots_gen_leafx4 SPX_NAMESPACE(wots_gen_leafx4) +void wots_gen_leafx4(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info); + +#endif /* WOTSX4_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_clean/LICENSE b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_clean/LICENSE new file mode 100644 index 0000000000..670154e353 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_clean/LICENSE @@ -0,0 +1,116 @@ +CC0 1.0 Universal + +Statement of Purpose + +The laws of most jurisdictions throughout the world automatically confer +exclusive Copyright and Related Rights (defined below) upon the creator and +subsequent owner(s) (each and all, an "owner") of an original work of +authorship and/or a database (each, a "Work"). + +Certain owners wish to permanently relinquish those rights to a Work for the +purpose of contributing to a commons of creative, cultural and scientific +works ("Commons") that the public can reliably and without fear of later +claims of infringement build upon, modify, incorporate in other works, reuse +and redistribute as freely as possible in any form whatsoever and for any +purposes, including without limitation commercial purposes. These owners may +contribute to the Commons to promote the ideal of a free culture and the +further production of creative, cultural and scientific works, or to gain +reputation or greater distribution for their Work in part through the use and +efforts of others. + +For these and/or other purposes and motivations, and without any expectation +of additional consideration or compensation, the person associating CC0 with a +Work (the "Affirmer"), to the extent that he or she is an owner of Copyright +and Related Rights in the Work, voluntarily elects to apply CC0 to the Work +and publicly distribute the Work under its terms, with knowledge of his or her +Copyright and Related Rights in the Work and the meaning and intended legal +effect of CC0 on those rights. + +1. Copyright and Related Rights. A Work made available under CC0 may be +protected by copyright and related or neighboring rights ("Copyright and +Related Rights"). Copyright and Related Rights include, but are not limited +to, the following: + + i. the right to reproduce, adapt, distribute, perform, display, communicate, + and translate a Work; + + ii. moral rights retained by the original author(s) and/or performer(s); + + iii. publicity and privacy rights pertaining to a person's image or likeness + depicted in a Work; + + iv. rights protecting against unfair competition in regards to a Work, + subject to the limitations in paragraph 4(a), below; + + v. rights protecting the extraction, dissemination, use and reuse of data in + a Work; + + vi. database rights (such as those arising under Directive 96/9/EC of the + European Parliament and of the Council of 11 March 1996 on the legal + protection of databases, and under any national implementation thereof, + including any amended or successor version of such directive); and + + vii. other similar, equivalent or corresponding rights throughout the world + based on applicable law or treaty, and any national implementations thereof. + +2. Waiver. To the greatest extent permitted by, but not in contravention of, +applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and +unconditionally waives, abandons, and surrenders all of Affirmer's Copyright +and Related Rights and associated claims and causes of action, whether now +known or unknown (including existing as well as future claims and causes of +action), in the Work (i) in all territories worldwide, (ii) for the maximum +duration provided by applicable law or treaty (including future time +extensions), (iii) in any current or future medium and for any number of +copies, and (iv) for any purpose whatsoever, including without limitation +commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes +the Waiver for the benefit of each member of the public at large and to the +detriment of Affirmer's heirs and successors, fully intending that such Waiver +shall not be subject to revocation, rescission, cancellation, termination, or +any other legal or equitable action to disrupt the quiet enjoyment of the Work +by the public as contemplated by Affirmer's express Statement of Purpose. + +3. Public License Fallback. Should any part of the Waiver for any reason be +judged legally invalid or ineffective under applicable law, then the Waiver +shall be preserved to the maximum extent permitted taking into account +Affirmer's express Statement of Purpose. In addition, to the extent the Waiver +is so judged Affirmer hereby grants to each affected person a royalty-free, +non transferable, non sublicensable, non exclusive, irrevocable and +unconditional license to exercise Affirmer's Copyright and Related Rights in +the Work (i) in all territories worldwide, (ii) for the maximum duration +provided by applicable law or treaty (including future time extensions), (iii) +in any current or future medium and for any number of copies, and (iv) for any +purpose whatsoever, including without limitation commercial, advertising or +promotional purposes (the "License"). The License shall be deemed effective as +of the date CC0 was applied by Affirmer to the Work. Should any part of the +License for any reason be judged legally invalid or ineffective under +applicable law, such partial invalidity or ineffectiveness shall not +invalidate the remainder of the License, and in such case Affirmer hereby +affirms that he or she will not (i) exercise any of his or her remaining +Copyright and Related Rights in the Work or (ii) assert any associated claims +and causes of action with respect to the Work, in either case contrary to +Affirmer's express Statement of Purpose. + +4. Limitations and Disclaimers. + + a. No trademark or patent rights held by Affirmer are waived, abandoned, + surrendered, licensed or otherwise affected by this document. + + b. Affirmer offers the Work as-is and makes no representations or warranties + of any kind concerning the Work, express, implied, statutory or otherwise, + including without limitation warranties of title, merchantability, fitness + for a particular purpose, non infringement, or the absence of latent or + other defects, accuracy, or the present or absence of errors, whether or not + discoverable, all to the greatest extent permissible under applicable law. + + c. Affirmer disclaims responsibility for clearing rights of other persons + that may apply to the Work or any use thereof, including without limitation + any person's Copyright and Related Rights in the Work. Further, Affirmer + disclaims responsibility for obtaining any necessary consents, permissions + or other rights required for any use of the Work. + + d. Affirmer understands and acknowledges that Creative Commons is not a + party to this document and has no duty or obligation with respect to this + CC0 or use of the Work. + +For more information, please see + diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_clean/address.c b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_clean/address.c new file mode 100644 index 0000000000..b956e9cb29 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_clean/address.c @@ -0,0 +1,91 @@ +#include +#include + +#include "address.h" +#include "params.h" +#include "utils.h" + +/* + * Specify which level of Merkle tree (the "layer") we're working on + */ +void set_layer_addr(uint32_t addr[8], uint32_t layer) { + ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; +} + +/* + * Specify which Merkle tree within the level (the "tree address") we're working on + */ +void set_tree_addr(uint32_t addr[8], uint64_t tree) { + ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); +} + +/* + * Specify the reason we'll use this address structure for, that is, what + * hash will we compute with it. This is used so that unrelated types of + * hashes don't accidentally get the same address structure. The type will be + * one of the SPX_ADDR_TYPE constants + */ +void set_type(uint32_t addr[8], uint32_t type) { + ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; +} + +/* + * Copy the layer and tree fields of the address structure. This is used + * when we're doing multiple types of hashes within the same Merkle tree + */ +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); +} + +/* These functions are used for OTS addresses. */ + +/* + * Specify which Merkle leaf we're working on; that is, which OTS keypair + * we're talking about. + */ +void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { + ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; +} + +/* + * Copy the layer, tree and keypair fields of the address structure. This is + * used when we're doing multiple things within the same OTS keypair + */ +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); + ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; +} + +/* + * Specify which Merkle chain within the OTS we're working with + * (the chain address) + */ +void set_chain_addr(uint32_t addr[8], uint32_t chain) { + ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; +} + +/* + * Specify where in the Merkle chain we are +* (the hash address) + */ +void set_hash_addr(uint32_t addr[8], uint32_t hash) { + ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; +} + +/* These functions are used for all hash tree addresses (including FORS). */ + +/* + * Specify the height of the node in the Merkle/FORS tree we are in + * (the tree height) + */ +void set_tree_height(uint32_t addr[8], uint32_t tree_height) { + ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; +} + +/* + * Specify the distance from the left edge of the node in the Merkle/FORS tree + * (the tree index) + */ +void set_tree_index(uint32_t addr[8], uint32_t tree_index) { + u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_clean/address.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_clean/address.h new file mode 100644 index 0000000000..24a84eb40c --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_clean/address.h @@ -0,0 +1,52 @@ +#ifndef SPX_ADDRESS_H +#define SPX_ADDRESS_H + +#include + +#include "params.h" + +/* The hash types that are passed to set_type */ +#define SPX_ADDR_TYPE_WOTS 0 +#define SPX_ADDR_TYPE_WOTSPK 1 +#define SPX_ADDR_TYPE_HASHTREE 2 +#define SPX_ADDR_TYPE_FORSTREE 3 +#define SPX_ADDR_TYPE_FORSPK 4 +#define SPX_ADDR_TYPE_WOTSPRF 5 +#define SPX_ADDR_TYPE_FORSPRF 6 + +#define set_layer_addr SPX_NAMESPACE(set_layer_addr) +void set_layer_addr(uint32_t addr[8], uint32_t layer); + +#define set_tree_addr SPX_NAMESPACE(set_tree_addr) +void set_tree_addr(uint32_t addr[8], uint64_t tree); + +#define set_type SPX_NAMESPACE(set_type) +void set_type(uint32_t addr[8], uint32_t type); + +/* Copies the layer and tree part of one address into the other */ +#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); + +/* These functions are used for WOTS and FORS addresses. */ + +#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) +void set_keypair_addr(uint32_t addr[8], uint32_t keypair); + +#define set_chain_addr SPX_NAMESPACE(set_chain_addr) +void set_chain_addr(uint32_t addr[8], uint32_t chain); + +#define set_hash_addr SPX_NAMESPACE(set_hash_addr) +void set_hash_addr(uint32_t addr[8], uint32_t hash); + +#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); + +/* These functions are used for all hash tree addresses (including FORS). */ + +#define set_tree_height SPX_NAMESPACE(set_tree_height) +void set_tree_height(uint32_t addr[8], uint32_t tree_height); + +#define set_tree_index SPX_NAMESPACE(set_tree_index) +void set_tree_index(uint32_t addr[8], uint32_t tree_index); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_clean/api.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_clean/api.h new file mode 100644 index 0000000000..80b54dbacd --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_clean/api.h @@ -0,0 +1,77 @@ +#ifndef PQCLEAN_SPHINCSSHAKE192FSIMPLE_CLEAN_API_H +#define PQCLEAN_SPHINCSSHAKE192FSIMPLE_CLEAN_API_H + +#include +#include + +#define PQCLEAN_SPHINCSSHAKE192FSIMPLE_CLEAN_CRYPTO_ALGNAME "SPHINCS+-shake-192f-simple" + +#define PQCLEAN_SPHINCSSHAKE192FSIMPLE_CLEAN_CRYPTO_SECRETKEYBYTES 96 +#define PQCLEAN_SPHINCSSHAKE192FSIMPLE_CLEAN_CRYPTO_PUBLICKEYBYTES 48 +#define PQCLEAN_SPHINCSSHAKE192FSIMPLE_CLEAN_CRYPTO_BYTES 35664 + +#define PQCLEAN_SPHINCSSHAKE192FSIMPLE_CLEAN_CRYPTO_SEEDBYTES 72 + +/* + * Returns the length of a secret key, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE192FSIMPLE_CLEAN_crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE192FSIMPLE_CLEAN_crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE192FSIMPLE_CLEAN_crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE192FSIMPLE_CLEAN_crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +int PQCLEAN_SPHINCSSHAKE192FSIMPLE_CLEAN_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +int PQCLEAN_SPHINCSSHAKE192FSIMPLE_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +int PQCLEAN_SPHINCSSHAKE192FSIMPLE_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +int PQCLEAN_SPHINCSSHAKE192FSIMPLE_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, + const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +int PQCLEAN_SPHINCSSHAKE192FSIMPLE_CLEAN_crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +int PQCLEAN_SPHINCSSHAKE192FSIMPLE_CLEAN_crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_clean/context.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_clean/context.h new file mode 100644 index 0000000000..9f8a40ab4e --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_clean/context.h @@ -0,0 +1,22 @@ +#ifndef SPX_CONTEXT_H +#define SPX_CONTEXT_H + +#include +#include + +#include "params.h" + +typedef struct { + uint8_t pub_seed[SPX_N]; + uint8_t sk_seed[SPX_N]; + + +} spx_ctx; + +#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) +void initialize_hash_function(spx_ctx *ctx); + +#define free_hash_function SPX_NAMESPACE(free_hash_function) +void free_hash_function(spx_ctx *ctx); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_clean/context_shake.c b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_clean/context_shake.c new file mode 100644 index 0000000000..9614a103d3 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_clean/context_shake.c @@ -0,0 +1,12 @@ +#include "context.h" + +/* For SHAKE256, there is no immediate reason to initialize at the start, + so this function is an empty operation. */ +void initialize_hash_function(spx_ctx *ctx) { + (void)ctx; /* Suppress an 'unused parameter' warning. */ +} + +// in case the hash function api is heap-based. +void free_hash_function(spx_ctx *ctx) { + (void)ctx; +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_clean/fors.c b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_clean/fors.c new file mode 100644 index 0000000000..96ca72e986 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_clean/fors.c @@ -0,0 +1,156 @@ +#include +#include +#include + +#include "fors.h" + +#include "address.h" +#include "hash.h" +#include "thash.h" +#include "utils.h" +#include "utilsx1.h" + +static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + prf_addr(sk, ctx, fors_leaf_addr); +} + +static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, + const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + thash(leaf, sk, 1, ctx, fors_leaf_addr); +} + +struct fors_gen_leaf_info { + uint32_t leaf_addrx[8]; +}; + +static void fors_gen_leafx1(unsigned char *leaf, + const spx_ctx *ctx, + uint32_t addr_idx, void *info) { + struct fors_gen_leaf_info *fors_info = info; + uint32_t *fors_leaf_addr = fors_info->leaf_addrx; + + /* Only set the parts that the caller doesn't set */ + set_tree_index(fors_leaf_addr, addr_idx); + set_type(fors_leaf_addr, SPX_ADDR_TYPE_FORSPRF); + fors_gen_sk(leaf, ctx, fors_leaf_addr); + + set_type(fors_leaf_addr, SPX_ADDR_TYPE_FORSTREE); + fors_sk_to_leaf(leaf, leaf, + ctx, fors_leaf_addr); +} + +/** + * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + * Assumes indices has space for SPX_FORS_TREES integers. + */ +static void message_to_indices(uint32_t *indices, const unsigned char *m) { + unsigned int i, j; + unsigned int offset = 0; + + for (i = 0; i < SPX_FORS_TREES; i++) { + indices[i] = 0; + for (j = 0; j < SPX_FORS_HEIGHT; j++) { + indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); + offset++; + } + } +} + +/** + * Signs a message m, deriving the secret key from sk_seed and the FTS address. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + uint32_t fors_tree_addr[8] = {0}; + struct fors_gen_leaf_info fors_info = {0}; + uint32_t *fors_leaf_addr = fors_info.leaf_addrx; + uint32_t fors_pk_addr[8] = {0}; + uint32_t idx_offset; + unsigned int i; + + copy_keypair_addr(fors_tree_addr, fors_addr); + copy_keypair_addr(fors_leaf_addr, fors_addr); + + copy_keypair_addr(fors_pk_addr, fors_addr); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); + + message_to_indices(indices, m); + + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); + + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); + + /* Include the secret key part that produces the selected leaf node. */ + fors_gen_sk(sig, ctx, fors_tree_addr); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + sig += SPX_N; + + /* Compute the authentication path for this leaf node. */ + treehashx1(roots + i * SPX_N, sig, ctx, + indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx1, + fors_tree_addr, &fors_info); + + sig += SPX_N * SPX_FORS_HEIGHT; + } + + /* Hash horizontally across all tree roots to derive the public key. */ + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); +} + +/** + * Derives the FORS public key from a signature. + * This can be used for verification by comparing to a known public key, or to + * subsequently verify a signature on the derived public key. The latter is the + * typical use-case when used as an FTS below an OTS in a hypertree. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + unsigned char leaf[SPX_N]; + uint32_t fors_tree_addr[8] = {0}; + uint32_t fors_pk_addr[8] = {0}; + uint32_t idx_offset; + unsigned int i; + + copy_keypair_addr(fors_tree_addr, fors_addr); + copy_keypair_addr(fors_pk_addr, fors_addr); + + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); + + message_to_indices(indices, m); + + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); + + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + + /* Derive the leaf from the included secret key part. */ + fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); + sig += SPX_N; + + /* Derive the corresponding root node of this tree. */ + compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, + sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); + sig += SPX_N * SPX_FORS_HEIGHT; + } + + /* Hash horizontally across all tree roots to derive the public key. */ + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_clean/fors.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_clean/fors.h new file mode 100644 index 0000000000..509140a178 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_clean/fors.h @@ -0,0 +1,32 @@ +#ifndef SPX_FORS_H +#define SPX_FORS_H + +#include + +#include "context.h" +#include "params.h" + +/** + * Signs a message m, deriving the secret key from sk_seed and the FTS address. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +#define fors_sign SPX_NAMESPACE(fors_sign) +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); + +/** + * Derives the FORS public key from a signature. + * This can be used for verification by comparing to a known public key, or to + * subsequently verify a signature on the derived public key. The latter is the + * typical use-case when used as an FTS below an OTS in a hypertree. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_clean/hash.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_clean/hash.h new file mode 100644 index 0000000000..f7c87d4c3c --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_clean/hash.h @@ -0,0 +1,28 @@ +#ifndef SPX_HASH_H +#define SPX_HASH_H + +#include +#include + +#include "context.h" +#include "params.h" + +#define prf_addr SPX_NAMESPACE(prf_addr) +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]); + +#define gen_message_random SPX_NAMESPACE(gen_message_random) +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); + +#define hash_message SPX_NAMESPACE(hash_message) +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); + + + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_clean/hash_shake.c b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_clean/hash_shake.c new file mode 100644 index 0000000000..ff5e7ec918 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_clean/hash_shake.c @@ -0,0 +1,83 @@ +#include +#include + +#include "hash.h" + +#include "address.h" +#include "fips202.h" +#include "params.h" +#include "utils.h" + +/* + * Computes PRF(pk_seed, sk_seed, addr) + */ +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]) { + unsigned char buf[2 * SPX_N + SPX_ADDR_BYTES]; + + memcpy(buf, ctx->pub_seed, SPX_N); + memcpy(buf + SPX_N, addr, SPX_ADDR_BYTES); + memcpy(buf + SPX_N + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); + + shake256(out, SPX_N, buf, 2 * SPX_N + SPX_ADDR_BYTES); +} + +/** + * Computes the message-dependent randomness R, using a secret seed and an + * optional randomization value as well as the message. + */ +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { + (void)ctx; + shake256incctx s_inc; + + shake256_inc_init(&s_inc); + shake256_inc_absorb(&s_inc, sk_prf, SPX_N); + shake256_inc_absorb(&s_inc, optrand, SPX_N); + shake256_inc_absorb(&s_inc, m, mlen); + shake256_inc_finalize(&s_inc); + shake256_inc_squeeze(R, SPX_N, &s_inc); + shake256_inc_ctx_release(&s_inc); +} + +/** + * Computes the message hash using R, the public key, and the message. + * Outputs the message digest and the index of the leaf. The index is split in + * the tree index and the leaf index, for convenient copying to an address. + */ +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { + (void)ctx; +#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) +#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) +#define SPX_LEAF_BITS SPX_TREE_HEIGHT +#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) +#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) + + unsigned char buf[SPX_DGST_BYTES]; + unsigned char *bufp = buf; + shake256incctx s_inc; + + shake256_inc_init(&s_inc); + shake256_inc_absorb(&s_inc, R, SPX_N); + shake256_inc_absorb(&s_inc, pk, SPX_PK_BYTES); + shake256_inc_absorb(&s_inc, m, mlen); + shake256_inc_finalize(&s_inc); + shake256_inc_squeeze(buf, SPX_DGST_BYTES, &s_inc); + shake256_inc_ctx_release(&s_inc); + + memcpy(digest, bufp, SPX_FORS_MSG_BYTES); + bufp += SPX_FORS_MSG_BYTES; + + + *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); + *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); + bufp += SPX_TREE_BYTES; + + *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); + *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_clean/merkle.c b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_clean/merkle.c new file mode 100644 index 0000000000..0c1479fd93 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_clean/merkle.c @@ -0,0 +1,59 @@ +#include +#include + +#include "address.h" +#include "merkle.h" +#include "params.h" +#include "utils.h" +#include "utilsx1.h" +#include "wots.h" +#include "wotsx1.h" + +/* + * This generates a Merkle signature (WOTS signature followed by the Merkle + * authentication path). This is in this file because most of the complexity + * is involved with the WOTS signature; the Merkle authentication path logic + * is mostly hidden in treehashx4 + */ +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf) { + unsigned char *auth_path = sig + SPX_WOTS_BYTES; + struct leaf_info_x1 info = { 0 }; + unsigned steps[ SPX_WOTS_LEN ]; + + info.wots_sig = sig; + chain_lengths(steps, root); + info.wots_steps = steps; + + set_type(&tree_addr[0], SPX_ADDR_TYPE_HASHTREE); + set_type(&info.pk_addr[0], SPX_ADDR_TYPE_WOTSPK); + copy_subtree_addr(&info.leaf_addr[0], wots_addr); + copy_subtree_addr(&info.pk_addr[0], wots_addr); + + info.wots_sign_leaf = idx_leaf; + + treehashx1(root, auth_path, ctx, + idx_leaf, 0, + SPX_TREE_HEIGHT, + wots_gen_leafx1, + tree_addr, &info); +} + +/* Compute root node of the top-most subtree. */ +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { + /* We do not need the auth path in key generation, but it simplifies the + code to have just one treehash routine that computes both root and path + in one function. */ + unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; + uint32_t top_tree_addr[8] = {0}; + uint32_t wots_addr[8] = {0}; + + set_layer_addr(top_tree_addr, SPX_D - 1); + set_layer_addr(wots_addr, SPX_D - 1); + + merkle_sign(auth_path, root, ctx, + wots_addr, top_tree_addr, + (uint32_t)~0 /* ~0 means "don't bother generating an auth path */ ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_clean/merkle.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_clean/merkle.h new file mode 100644 index 0000000000..769cf2e970 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_clean/merkle.h @@ -0,0 +1,21 @@ +#ifndef MERKLE_H_ +#define MERKLE_H_ + +#include + +#include "context.h" +#include "params.h" + +/* Generate a Merkle signature (WOTS signature followed by the Merkle */ +/* authentication path) */ +#define merkle_sign SPX_NAMESPACE(merkle_sign) +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf); + +/* Compute the root node of the top-most subtree. */ +#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); + +#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_clean/nistapi.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_clean/nistapi.h new file mode 100644 index 0000000000..3cb71afad4 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_clean/nistapi.h @@ -0,0 +1,87 @@ +#ifndef SPX_API_H +#define SPX_API_H + +#include +#include + +#include "params.h" + +#define CRYPTO_ALGNAME "SPHINCS+" + +#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES +#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES +#define CRYPTO_BYTES SPX_BYTES +#define CRYPTO_SEEDBYTES (3*SPX_N) + +/* + * Returns the length of a secret key, in bytes + */ +#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) +size_t crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) +size_t crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) +size_t crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) +size_t crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +#define crypto_sign SPX_NAMESPACE(crypto_sign) +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_clean/params.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_clean/params.h new file mode 100644 index 0000000000..12830977d4 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_clean/params.h @@ -0,0 +1,56 @@ +#ifndef SPX_PARAMS_H +#define SPX_PARAMS_H + +#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSSHAKE192FSIMPLE_CLEAN_##s + +/* Hash output length in bytes. */ +#define SPX_N 24 +/* Height of the hypertree. */ +#define SPX_FULL_HEIGHT 66 +/* Number of subtree layer. */ +#define SPX_D 22 +/* FORS tree dimensions. */ +#define SPX_FORS_HEIGHT 8 +#define SPX_FORS_TREES 33 +/* Winternitz parameter, */ +#define SPX_WOTS_W 16 + +/* The hash function is defined by linking a different hash.c file, as opposed + to setting a #define constant. */ + +/* For clarity */ +#define SPX_ADDR_BYTES 32 + +/* WOTS parameters. */ +#define SPX_WOTS_LOGW 4 + +#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) + +/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ +#define SPX_WOTS_LEN2 3 + +#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) +#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) +#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES + +/* Subtree size. */ +#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) + +//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT +// #error SPX_D should always divide SPX_FULL_HEIGHT +//#endif + +/* FORS parameters. */ +#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) +#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) +#define SPX_FORS_PK_BYTES SPX_N + +/* Resulting SPX sizes. */ +#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ + SPX_FULL_HEIGHT * SPX_N) +#define SPX_PK_BYTES (2 * SPX_N) +#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) + +#include "shake_offsets.h" + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_clean/shake_offsets.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_clean/shake_offsets.h new file mode 100644 index 0000000000..6b28d95d91 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_clean/shake_offsets.h @@ -0,0 +1,21 @@ +#ifndef SHAKE_OFFSETS_H_ +#define SHAKE_OFFSETS_H_ + +/* + * Offsets of various fields in the address structure when we use SHAKE as + * the Sphincs+ hash function + */ + +#define SPX_OFFSET_LAYER 3 /* The byte used to specify the Merkle tree layer */ +#define SPX_OFFSET_TREE 8 /* The start of the 8 byte field used to specify the tree */ +#define SPX_OFFSET_TYPE 19 /* The byte used to specify the hash type (reason) */ +#define SPX_OFFSET_KP_ADDR2 22 /* The high byte used to specify the key pair (which one-time signature) */ +#define SPX_OFFSET_KP_ADDR1 23 /* The low byte used to specify the key pair */ +#define SPX_OFFSET_CHAIN_ADDR 27 /* The byte used to specify the chain address (which Winternitz chain) */ +#define SPX_OFFSET_HASH_ADDR 31 /* The byte used to specify the hash address (where in the Winternitz chain) */ +#define SPX_OFFSET_TREE_HGT 27 /* The byte used to specify the height of this node in the FORS or Merkle tree */ +#define SPX_OFFSET_TREE_INDEX 28 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ + +#define SPX_SHAKE 1 + +#endif /* SHAKE_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_clean/sign.c b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_clean/sign.c new file mode 100644 index 0000000000..9d0c7d1b22 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_clean/sign.c @@ -0,0 +1,286 @@ +#include +#include +#include + +#include "address.h" +#include "context.h" +#include "fors.h" +#include "hash.h" +#include "merkle.h" +#include "nistapi.h" +#include "params.h" +#include "randombytes.h" +#include "thash.h" +#include "utils.h" +#include "wots.h" + +/* + * Returns the length of a secret key, in bytes + */ +size_t crypto_sign_secretkeybytes(void) { + return CRYPTO_SECRETKEYBYTES; +} + +/* + * Returns the length of a public key, in bytes + */ +size_t crypto_sign_publickeybytes(void) { + return CRYPTO_PUBLICKEYBYTES; +} + +/* + * Returns the length of a signature, in bytes + */ +size_t crypto_sign_bytes(void) { + return CRYPTO_BYTES; +} + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +size_t crypto_sign_seedbytes(void) { + return CRYPTO_SEEDBYTES; +} + +/* + * Generates an SPX key pair given a seed of length + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [PUB_SEED || root] + */ +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed) { + spx_ctx ctx; + + /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ + memcpy(sk, seed, CRYPTO_SEEDBYTES); + + memcpy(pk, sk + 2 * SPX_N, SPX_N); + + memcpy(ctx.pub_seed, pk, SPX_N); + memcpy(ctx.sk_seed, sk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + /* Compute root node of the top-most subtree. */ + merkle_gen_root(sk + 3 * SPX_N, &ctx); + + // cleanup + free_hash_function(&ctx); + + memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); + + return 0; +} + +/* + * Generates an SPX key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [PUB_SEED || root] + */ +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { + uint8_t seed[CRYPTO_SEEDBYTES]; + randombytes(seed, CRYPTO_SEEDBYTES); + crypto_sign_seed_keypair(pk, sk, seed); + + return 0; +} + +/** + * Returns an array containing a detached signature. + */ +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk) { + spx_ctx ctx; + + const uint8_t *sk_prf = sk + SPX_N; + const uint8_t *pk = sk + 2 * SPX_N; + + uint8_t optrand[SPX_N]; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t root[SPX_N]; + uint32_t i; + uint64_t tree; + uint32_t idx_leaf; + uint32_t wots_addr[8] = {0}; + uint32_t tree_addr[8] = {0}; + + memcpy(ctx.sk_seed, sk, SPX_N); + memcpy(ctx.pub_seed, pk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + + /* Optionally, signing can be made non-deterministic using optrand. + This can help counter side-channel attacks that would benefit from + getting a large number of traces when the signer uses the same nodes. */ + randombytes(optrand, SPX_N); + /* Compute the digest randomization value. */ + gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); + + /* Derive the message digest and leaf index from R, PK and M. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; + + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); + + /* Sign the message hash using FORS. */ + fors_sign(sig, root, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); + sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; + + /* Update the indices for the next layer. */ + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; + } + + free_hash_function(&ctx); + + *siglen = SPX_BYTES; + + return 0; +} + +/** + * Verifies a detached signature and message under a given public key. + */ +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk) { + spx_ctx ctx; + const uint8_t *pub_root = pk + SPX_N; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t wots_pk[SPX_WOTS_BYTES]; + uint8_t root[SPX_N]; + uint8_t leaf[SPX_N]; + unsigned int i; + uint64_t tree; + uint32_t idx_leaf; + uint32_t wots_addr[8] = {0}; + uint32_t tree_addr[8] = {0}; + uint32_t wots_pk_addr[8] = {0}; + + if (siglen != SPX_BYTES) { + return -1; + } + + memcpy(ctx.pub_seed, pk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); + + /* Derive the message digest and leaf index from R || PK || M. */ + /* The additional SPX_N is a result of the hash domain separator. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; + + /* Layer correctly defaults to 0, so no need to set_layer_addr */ + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); + + fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + /* For each subtree.. */ + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + copy_keypair_addr(wots_pk_addr, wots_addr); + + /* The WOTS public key is only correct if the signature was correct. */ + /* Initially, root is the FORS pk, but on subsequent iterations it is + the root of the subtree below the currently processed subtree. */ + wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); + sig += SPX_WOTS_BYTES; + + /* Compute the leaf node using the WOTS public key. */ + thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); + + /* Compute the root node of this subtree. */ + compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, + &ctx, tree_addr); + sig += SPX_TREE_HEIGHT * SPX_N; + + /* Update the indices for the next layer. */ + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; + } + + // cleanup + free_hash_function(&ctx); + + /* Check if the root node equals the root node in the public key. */ + if (memcmp(root, pub_root, SPX_N) != 0) { + return -1; + } + + return 0; +} + + +/** + * Returns an array containing the signature followed by the message. + */ +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk) { + size_t siglen; + + crypto_sign_signature(sm, &siglen, m, mlen, sk); + + memmove(sm + SPX_BYTES, m, mlen); + *smlen = siglen + mlen; + + return 0; +} + +/** + * Verifies a given signature-message pair under a given public key. + */ +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk) { + /* The API caller does not necessarily know what size a signature should be + but SPHINCS+ signatures are always exactly SPX_BYTES. */ + if (smlen < SPX_BYTES) { + memset(m, 0, smlen); + *mlen = 0; + return -1; + } + + *mlen = smlen - SPX_BYTES; + + if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { + memset(m, 0, smlen); + *mlen = 0; + return -1; + } + + /* If verification was successful, move the message to the right place. */ + memmove(m, sm + SPX_BYTES, *mlen); + + return 0; +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_clean/thash.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_clean/thash.h new file mode 100644 index 0000000000..8687ccfb4d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_clean/thash.h @@ -0,0 +1,13 @@ +#ifndef SPX_THASH_H +#define SPX_THASH_H + +#include "context.h" +#include "params.h" + +#include + +#define thash SPX_NAMESPACE(thash) +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_clean/thash_shake_simple.c b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_clean/thash_shake_simple.c new file mode 100644 index 0000000000..98470395e9 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_clean/thash_shake_simple.c @@ -0,0 +1,24 @@ +#include +#include + +#include "thash.h" + +#include "address.h" +#include "params.h" +#include "utils.h" + +#include "fips202.h" + +/** + * Takes an array of inblocks concatenated arrays of SPX_N bytes. + */ +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]) { + PQCLEAN_VLA(uint8_t, buf, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); + + memcpy(buf, ctx->pub_seed, SPX_N); + memcpy(buf + SPX_N, addr, SPX_ADDR_BYTES); + memcpy(buf + SPX_N + SPX_ADDR_BYTES, in, inblocks * SPX_N); + + shake256(out, SPX_N, buf, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_clean/utils.c b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_clean/utils.c new file mode 100644 index 0000000000..177b541fb9 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_clean/utils.c @@ -0,0 +1,148 @@ +#include + +#include "utils.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "thash.h" + +/** + * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. + */ +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in) { + int i; + + /* Iterate over out in decreasing order, for big-endianness. */ + for (i = (signed int)outlen - 1; i >= 0; i--) { + out[i] = in & 0xff; + in = in >> 8; + } +} + +void u32_to_bytes(unsigned char *out, uint32_t in) { + out[0] = (unsigned char)(in >> 24); + out[1] = (unsigned char)(in >> 16); + out[2] = (unsigned char)(in >> 8); + out[3] = (unsigned char)in; +} + +/** + * Converts the inlen bytes in 'in' from big-endian byte order to an integer. + */ +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { + unsigned long long retval = 0; + unsigned int i; + + for (i = 0; i < inlen; i++) { + retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); + } + return retval; +} + +/** + * Computes a root node given a leaf and an auth path. + * Expects address to be complete other than the tree_height and tree_index. + */ +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]) { + uint32_t i; + unsigned char buffer[2 * SPX_N]; + + /* If leaf_idx is odd (last bit = 1), current path element is a right child + and auth_path has to go left. Otherwise it is the other way around. */ + if (leaf_idx & 1) { + memcpy(buffer + SPX_N, leaf, SPX_N); + memcpy(buffer, auth_path, SPX_N); + } else { + memcpy(buffer, leaf, SPX_N); + memcpy(buffer + SPX_N, auth_path, SPX_N); + } + auth_path += SPX_N; + + for (i = 0; i < tree_height - 1; i++) { + leaf_idx >>= 1; + idx_offset >>= 1; + /* Set the address of the node we're creating. */ + set_tree_height(addr, i + 1); + set_tree_index(addr, leaf_idx + idx_offset); + + /* Pick the right or left neighbor, depending on parity of the node. */ + if (leaf_idx & 1) { + thash(buffer + SPX_N, buffer, 2, ctx, addr); + memcpy(buffer, auth_path, SPX_N); + } else { + thash(buffer, buffer, 2, ctx, addr); + memcpy(buffer + SPX_N, auth_path, SPX_N); + } + auth_path += SPX_N; + } + + /* The last iteration is exceptional; we do not copy an auth_path node. */ + leaf_idx >>= 1; + idx_offset >>= 1; + set_tree_height(addr, tree_height); + set_tree_index(addr, leaf_idx + idx_offset); + thash(root, buffer, 2, ctx, addr); +} + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx * /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]) { + PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); + PQCLEAN_VLA(unsigned int, heights, tree_height + 1); + unsigned int offset = 0; + uint32_t idx; + uint32_t tree_idx; + + for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { + /* Add the next leaf node to the stack. */ + gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); + offset++; + heights[offset - 1] = 0; + + /* If this is a node we need for the auth path.. */ + if ((leaf_idx ^ 0x1) == idx) { + memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); + } + + /* While the top-most nodes are of equal height.. */ + while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { + /* Compute index of the new node, in the next layer. */ + tree_idx = (idx >> (heights[offset - 1] + 1)); + + /* Set the address of the node we're creating. */ + set_tree_height(tree_addr, heights[offset - 1] + 1); + set_tree_index(tree_addr, + tree_idx + (idx_offset >> (heights[offset - 1] + 1))); + /* Hash the top-most nodes from the stack together. */ + thash(stack + (offset - 2)*SPX_N, + stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); + offset--; + /* Note that the top-most node is now one layer higher. */ + heights[offset - 1]++; + + /* If this is a node we need for the auth path.. */ + if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { + memcpy(auth_path + heights[offset - 1]*SPX_N, + stack + (offset - 1)*SPX_N, SPX_N); + } + } + } + memcpy(root, stack, SPX_N); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_clean/utils.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_clean/utils.h new file mode 100644 index 0000000000..64f5d5a53a --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_clean/utils.h @@ -0,0 +1,58 @@ +#ifndef SPX_UTILS_H +#define SPX_UTILS_H + +#include + +#include "compat.h" +#include "context.h" +#include "params.h" + + +/* To support MSVC use alloca() instead of VLAs. See #20. */ + + +/** + * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. + */ +#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in); +#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) +void u32_to_bytes(unsigned char *out, uint32_t in); + +/** + * Converts the inlen bytes in 'in' from big-endian byte order to an integer. + */ +#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); + +/** + * Computes a root node given a leaf and an auth path. + * Expects address to be complete other than the tree_height and tree_index. + */ +#define compute_root SPX_NAMESPACE(compute_root) +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]); + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +#define treehash SPX_NAMESPACE(treehash) +void treehash(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx *ctx /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]); + + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_clean/utilsx1.c b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_clean/utilsx1.c new file mode 100644 index 0000000000..fccb69b35d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_clean/utilsx1.c @@ -0,0 +1,100 @@ +#include + +#include "utilsx1.h" + +#include "address.h" +#include "params.h" +#include "thash.h" +#include "utils.h" + +/* + * Generate the entire Merkle tree, computing the authentication path for + * leaf_idx, and the resulting root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) + * + * This expects tree_addr to be initialized to the addr structures for the + * Merkle tree nodes + * + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + * + * This works by using the standard Merkle tree building algorithm, + */ +void treehashx1(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, + uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* Where to write the leaves */, + const spx_ctx * /* ctx */, + uint32_t idx, void *info), + uint32_t tree_addr[8], + void *info) { + /* This is where we keep the intermediate nodes */ + PQCLEAN_VLA(uint8_t, stack, tree_height * SPX_N); + + uint32_t idx; + uint32_t max_idx = (uint32_t)((1 << tree_height) - 1); + for (idx = 0;; idx++) { + unsigned char current[2 * SPX_N]; /* Current logical node is at */ + /* index[SPX_N]. We do this to minimize the number of copies */ + /* needed during a thash */ + gen_leaf( ¤t[SPX_N], ctx, idx + idx_offset, + info ); + + /* Now combine the freshly generated right node with previously */ + /* generated left ones */ + uint32_t internal_idx_offset = idx_offset; + uint32_t internal_idx = idx; + uint32_t internal_leaf = leaf_idx; + uint32_t h; /* The height we are in the Merkle tree */ + for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { + + /* Check if we hit the top of the tree */ + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[SPX_N], SPX_N ); + return; + } + + /* + * Check if the node we have is a part of the + * authentication path; if it is, write it out + */ + if ((internal_idx ^ internal_leaf) == 0x01) { + memcpy( &auth_path[ h * SPX_N ], + ¤t[SPX_N], + SPX_N ); + } + + /* + * Check if we're at a left child; if so, stop going up the stack + * Exception: if we've reached the end of the tree, keep on going + * (so we combine the last 4 nodes into the one root node in two + * more iterations) + */ + if ((internal_idx & 1) == 0 && idx < max_idx) { + break; + } + + /* Ok, we're at a right node */ + /* Now combine the left and right logical nodes together */ + + /* Set the address of the node we're creating. */ + internal_idx_offset >>= 1; + set_tree_height(tree_addr, h + 1); + set_tree_index(tree_addr, internal_idx / 2 + internal_idx_offset ); + + unsigned char *left = &stack[h * SPX_N]; + memcpy( ¤t[0], left, SPX_N ); + thash( ¤t[1 * SPX_N], + ¤t[0 * SPX_N], + 2, ctx, tree_addr); + } + + /* We've hit a left child; save the current for when we get the */ + /* corresponding right right */ + memcpy( &stack[h * SPX_N], ¤t[SPX_N], SPX_N); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_clean/utilsx1.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_clean/utilsx1.h new file mode 100644 index 0000000000..e911d17d53 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_clean/utilsx1.h @@ -0,0 +1,27 @@ +#ifndef SPX_UTILSX4_H +#define SPX_UTILSX4_H + +#include + +#include "context.h" +#include "params.h" + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +#define treehashx1 SPX_NAMESPACE(treehashx1) +void treehashx1(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* Where to write the leaf */, + const spx_ctx * /* ctx */, + uint32_t addr_idx, void *info), + uint32_t tree_addrx4[8], void *info); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_clean/wots.c b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_clean/wots.c new file mode 100644 index 0000000000..249717aaa8 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_clean/wots.c @@ -0,0 +1,108 @@ +#include +#include + +#include "wots.h" +#include "wotsx1.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "thash.h" +#include "utils.h" +#include "utilsx1.h" + +// TODO clarify address expectations, and make them more uniform. +// TODO i.e. do we expect types to be set already? +// TODO and do we expect modifications or copies? + +/** + * Computes the chaining function. + * out and in have to be n-byte arrays. + * + * Interprets in as start-th value of the chain. + * addr has to contain the address of the chain. + */ +static void gen_chain(unsigned char *out, const unsigned char *in, + unsigned int start, unsigned int steps, + const spx_ctx *ctx, uint32_t addr[8]) { + uint32_t i; + + /* Initialize out with the value at position 'start'. */ + memcpy(out, in, SPX_N); + + /* Iterate 'steps' calls to the hash function. */ + for (i = start; i < (start + steps) && i < SPX_WOTS_W; i++) { + set_hash_addr(addr, i); + thash(out, out, 1, ctx, addr); + } +} + +/** + * base_w algorithm as described in draft. + * Interprets an array of bytes as integers in base w. + * This only works when log_w is a divisor of 8. + */ +static void base_w(unsigned int *output, const int out_len, + const unsigned char *input) { + int in = 0; + int out = 0; + unsigned char total = 0; + int bits = 0; + int consumed; + + for (consumed = 0; consumed < out_len; consumed++) { + if (bits == 0) { + total = input[in]; + in++; + bits += 8; + } + bits -= SPX_WOTS_LOGW; + output[out] = (total >> bits) & (SPX_WOTS_W - 1); + out++; + } +} + +/* Computes the WOTS+ checksum over a message (in base_w). */ +static void wots_checksum(unsigned int *csum_base_w, + const unsigned int *msg_base_w) { + unsigned int csum = 0; + unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; + unsigned int i; + + /* Compute checksum. */ + for (i = 0; i < SPX_WOTS_LEN1; i++) { + csum += SPX_WOTS_W - 1 - msg_base_w[i]; + } + + /* Convert checksum to base_w. */ + /* Make sure expected empty zero bits are the least significant bits. */ + csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); + ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); + base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); +} + +/* Takes a message and derives the matching chain lengths. */ +void chain_lengths(unsigned int *lengths, const unsigned char *msg) { + base_w(lengths, SPX_WOTS_LEN1, msg); + wots_checksum(lengths + SPX_WOTS_LEN1, lengths); +} + +/** + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. + * + * Writes the computed public key to 'pk'. + */ +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]) { + unsigned int lengths[SPX_WOTS_LEN]; + uint32_t i; + + chain_lengths(lengths, msg); + + for (i = 0; i < SPX_WOTS_LEN; i++) { + set_chain_addr(addr, i); + gen_chain(pk + i * SPX_N, sig + i * SPX_N, + lengths[i], SPX_WOTS_W - 1 - lengths[i], ctx, addr); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_clean/wots.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_clean/wots.h new file mode 100644 index 0000000000..4e7692eeef --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_clean/wots.h @@ -0,0 +1,25 @@ +#ifndef SPX_WOTS_H +#define SPX_WOTS_H + +#include + +#include "context.h" +#include "params.h" + +/** + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. + * + * Writes the computed public key to 'pk'. + */ +#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]); + +/* + * Compute the chain lengths needed for a given message hash + */ +#define chain_lengths SPX_NAMESPACE(chain_lengths) +void chain_lengths(unsigned int *lengths, const unsigned char *msg); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_clean/wotsx1.c b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_clean/wotsx1.c new file mode 100644 index 0000000000..3adec78dfb --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_clean/wotsx1.c @@ -0,0 +1,76 @@ +#include +#include + +#include "wots.h" +#include "wotsx1.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "thash.h" +#include "utils.h" + +/* + * This generates a WOTS public key + * It also generates the WOTS signature if leaf_info indicates + * that we're signing with this WOTS key + */ +void wots_gen_leafx1(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info) { + struct leaf_info_x1 *info = v_info; + uint32_t *leaf_addr = info->leaf_addr; + uint32_t *pk_addr = info->pk_addr; + unsigned int i, k; + unsigned char pk_buffer[ SPX_WOTS_BYTES ]; + unsigned char *buffer; + uint32_t wots_k_mask; + + if (leaf_idx == info->wots_sign_leaf) { + /* We're traversing the leaf that's signing; generate the WOTS */ + /* signature */ + wots_k_mask = 0; + } else { + /* Nope, we're just generating pk's; turn off the signature logic */ + wots_k_mask = (uint32_t)~0; + } + + set_keypair_addr( leaf_addr, leaf_idx ); + set_keypair_addr( pk_addr, leaf_idx ); + + for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { + uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k to */ + /* the step if we're generating a signature, ~0 if we're not */ + + /* Start with the secret seed */ + set_chain_addr(leaf_addr, i); + set_hash_addr(leaf_addr, 0); + set_type(leaf_addr, SPX_ADDR_TYPE_WOTSPRF); + + prf_addr(buffer, ctx, leaf_addr); + + set_type(leaf_addr, SPX_ADDR_TYPE_WOTS); + + /* Iterate down the WOTS chain */ + for (k = 0;; k++) { + /* Check if this is the value that needs to be saved as a */ + /* part of the WOTS signature */ + if (k == wots_k) { + memcpy( info->wots_sig + i * SPX_N, buffer, SPX_N ); + } + + /* Check if we hit the top of the chain */ + if (k == SPX_WOTS_W - 1) { + break; + } + + /* Iterate one step on the chain */ + set_hash_addr(leaf_addr, k); + + thash(buffer, buffer, 1, ctx, leaf_addr); + } + } + + /* Do the final thash to generate the public keys */ + thash(dest, pk_buffer, SPX_WOTS_LEN, ctx, pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_clean/wotsx1.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_clean/wotsx1.h new file mode 100644 index 0000000000..e617929f96 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_clean/wotsx1.h @@ -0,0 +1,39 @@ +#ifndef WOTSX1_H_ +#define WOTSX1_H_ + +#include + +#include "context.h" +#include "params.h" + +/* + * This is here to provide an interface to the internal wots_gen_leafx1 + * routine. While this routine is not referenced in the package outside of + * wots.c, it is called from the stand-alone benchmark code to characterize + * the performance + */ +struct leaf_info_x1 { + unsigned char *wots_sig; + uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ + uint32_t *wots_steps; + uint32_t leaf_addr[8]; + uint32_t pk_addr[8]; +}; + +/* Macro to set the leaf_info to something 'benign', that is, it would */ +/* run with the same time as it does during the real signing process */ +/* Used only by the benchmark code */ +#define INITIALIZE_LEAF_INFO_X1(info, addr, step_buffer) { \ + (info).wots_sig = 0; \ + (info).wots_sign_leaf = ~0; \ + (info).wots_steps = step_buffer; \ + memcpy( &(info).leaf_addr[0], (addr), 32 ); \ + memcpy( &(info).pk_addr[0], (addr), 32 ); \ + } + +#define wots_gen_leafx1 SPX_NAMESPACE(wots_gen_leafx1) +void wots_gen_leafx1(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info); + +#endif /* WOTSX1_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/LICENSE b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/LICENSE new file mode 100644 index 0000000000..670154e353 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/LICENSE @@ -0,0 +1,116 @@ +CC0 1.0 Universal + +Statement of Purpose + +The laws of most jurisdictions throughout the world automatically confer +exclusive Copyright and Related Rights (defined below) upon the creator and +subsequent owner(s) (each and all, an "owner") of an original work of +authorship and/or a database (each, a "Work"). + +Certain owners wish to permanently relinquish those rights to a Work for the +purpose of contributing to a commons of creative, cultural and scientific +works ("Commons") that the public can reliably and without fear of later +claims of infringement build upon, modify, incorporate in other works, reuse +and redistribute as freely as possible in any form whatsoever and for any +purposes, including without limitation commercial purposes. These owners may +contribute to the Commons to promote the ideal of a free culture and the +further production of creative, cultural and scientific works, or to gain +reputation or greater distribution for their Work in part through the use and +efforts of others. + +For these and/or other purposes and motivations, and without any expectation +of additional consideration or compensation, the person associating CC0 with a +Work (the "Affirmer"), to the extent that he or she is an owner of Copyright +and Related Rights in the Work, voluntarily elects to apply CC0 to the Work +and publicly distribute the Work under its terms, with knowledge of his or her +Copyright and Related Rights in the Work and the meaning and intended legal +effect of CC0 on those rights. + +1. Copyright and Related Rights. A Work made available under CC0 may be +protected by copyright and related or neighboring rights ("Copyright and +Related Rights"). Copyright and Related Rights include, but are not limited +to, the following: + + i. the right to reproduce, adapt, distribute, perform, display, communicate, + and translate a Work; + + ii. moral rights retained by the original author(s) and/or performer(s); + + iii. publicity and privacy rights pertaining to a person's image or likeness + depicted in a Work; + + iv. rights protecting against unfair competition in regards to a Work, + subject to the limitations in paragraph 4(a), below; + + v. rights protecting the extraction, dissemination, use and reuse of data in + a Work; + + vi. database rights (such as those arising under Directive 96/9/EC of the + European Parliament and of the Council of 11 March 1996 on the legal + protection of databases, and under any national implementation thereof, + including any amended or successor version of such directive); and + + vii. other similar, equivalent or corresponding rights throughout the world + based on applicable law or treaty, and any national implementations thereof. + +2. Waiver. To the greatest extent permitted by, but not in contravention of, +applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and +unconditionally waives, abandons, and surrenders all of Affirmer's Copyright +and Related Rights and associated claims and causes of action, whether now +known or unknown (including existing as well as future claims and causes of +action), in the Work (i) in all territories worldwide, (ii) for the maximum +duration provided by applicable law or treaty (including future time +extensions), (iii) in any current or future medium and for any number of +copies, and (iv) for any purpose whatsoever, including without limitation +commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes +the Waiver for the benefit of each member of the public at large and to the +detriment of Affirmer's heirs and successors, fully intending that such Waiver +shall not be subject to revocation, rescission, cancellation, termination, or +any other legal or equitable action to disrupt the quiet enjoyment of the Work +by the public as contemplated by Affirmer's express Statement of Purpose. + +3. Public License Fallback. Should any part of the Waiver for any reason be +judged legally invalid or ineffective under applicable law, then the Waiver +shall be preserved to the maximum extent permitted taking into account +Affirmer's express Statement of Purpose. In addition, to the extent the Waiver +is so judged Affirmer hereby grants to each affected person a royalty-free, +non transferable, non sublicensable, non exclusive, irrevocable and +unconditional license to exercise Affirmer's Copyright and Related Rights in +the Work (i) in all territories worldwide, (ii) for the maximum duration +provided by applicable law or treaty (including future time extensions), (iii) +in any current or future medium and for any number of copies, and (iv) for any +purpose whatsoever, including without limitation commercial, advertising or +promotional purposes (the "License"). The License shall be deemed effective as +of the date CC0 was applied by Affirmer to the Work. Should any part of the +License for any reason be judged legally invalid or ineffective under +applicable law, such partial invalidity or ineffectiveness shall not +invalidate the remainder of the License, and in such case Affirmer hereby +affirms that he or she will not (i) exercise any of his or her remaining +Copyright and Related Rights in the Work or (ii) assert any associated claims +and causes of action with respect to the Work, in either case contrary to +Affirmer's express Statement of Purpose. + +4. Limitations and Disclaimers. + + a. No trademark or patent rights held by Affirmer are waived, abandoned, + surrendered, licensed or otherwise affected by this document. + + b. Affirmer offers the Work as-is and makes no representations or warranties + of any kind concerning the Work, express, implied, statutory or otherwise, + including without limitation warranties of title, merchantability, fitness + for a particular purpose, non infringement, or the absence of latent or + other defects, accuracy, or the present or absence of errors, whether or not + discoverable, all to the greatest extent permissible under applicable law. + + c. Affirmer disclaims responsibility for clearing rights of other persons + that may apply to the Work or any use thereof, including without limitation + any person's Copyright and Related Rights in the Work. Further, Affirmer + disclaims responsibility for obtaining any necessary consents, permissions + or other rights required for any use of the Work. + + d. Affirmer understands and acknowledges that Creative Commons is not a + party to this document and has no duty or obligation with respect to this + CC0 or use of the Work. + +For more information, please see + diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/address.c b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/address.c new file mode 100644 index 0000000000..d49d9f3b6b --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/address.c @@ -0,0 +1,95 @@ +#include +#include + +#include "address.h" +#include "params.h" +#include "utils.h" + +/* + * Specify which level of Merkle tree (the "layer") we're working on + */ +void set_layer_addr(uint32_t addr[8], uint32_t layer) { + ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; +} + +/* + * Specify which Merkle tree within the level (the "tree address") we're working on + */ +void set_tree_addr(uint32_t addr[8], uint64_t tree) { + ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); +} + +/* + * Specify the reason we'll use this address structure for, that is, what + * hash will we compute with it. This is used so that unrelated types of + * hashes don't accidentally get the same address structure. The type will be + * one of the SPX_ADDR_TYPE constants + */ +void set_type(uint32_t addr[8], uint32_t type) { + ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; +} + +/* + * Copy the layer and tree fields of the address structure. This is used + * when we're doing multiple types of hashes within the same Merkle tree + */ +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); +} + +/* These functions are used for OTS addresses. */ + +/* + * Specify which Merkle leaf we're working on; that is, which OTS keypair + * we're talking about. + */ +void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { + /* We have > 256 OTS at the bottom of the Merkle tree; to specify */ + /* which one, we'd need to express it in two bytes */ + ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR2] = (unsigned char)(keypair >> 8); + ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; +} + +/* + * Copy the layer, tree and keypair fields of the address structure. This is + * used when we're doing multiple things within the same OTS keypair + */ +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); + ((unsigned char *)out)[SPX_OFFSET_KP_ADDR2] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR2]; + ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; +} + +/* + * Specify which Merkle chain within the OTS we're working with + * (the chain address) + */ +void set_chain_addr(uint32_t addr[8], uint32_t chain) { + ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; +} + +/* + * Specify where in the Merkle chain we are +* (the hash address) + */ +void set_hash_addr(uint32_t addr[8], uint32_t hash) { + ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; +} + +/* These functions are used for all hash tree addresses (including FORS). */ + +/* + * Specify the height of the node in the Merkle/FORS tree we are in + * (the tree height) + */ +void set_tree_height(uint32_t addr[8], uint32_t tree_height) { + ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; +} + +/* + * Specify the distance from the left edge of the node in the Merkle/FORS tree + * (the tree index) + */ +void set_tree_index(uint32_t addr[8], uint32_t tree_index) { + u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/address.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/address.h new file mode 100644 index 0000000000..24a84eb40c --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/address.h @@ -0,0 +1,52 @@ +#ifndef SPX_ADDRESS_H +#define SPX_ADDRESS_H + +#include + +#include "params.h" + +/* The hash types that are passed to set_type */ +#define SPX_ADDR_TYPE_WOTS 0 +#define SPX_ADDR_TYPE_WOTSPK 1 +#define SPX_ADDR_TYPE_HASHTREE 2 +#define SPX_ADDR_TYPE_FORSTREE 3 +#define SPX_ADDR_TYPE_FORSPK 4 +#define SPX_ADDR_TYPE_WOTSPRF 5 +#define SPX_ADDR_TYPE_FORSPRF 6 + +#define set_layer_addr SPX_NAMESPACE(set_layer_addr) +void set_layer_addr(uint32_t addr[8], uint32_t layer); + +#define set_tree_addr SPX_NAMESPACE(set_tree_addr) +void set_tree_addr(uint32_t addr[8], uint64_t tree); + +#define set_type SPX_NAMESPACE(set_type) +void set_type(uint32_t addr[8], uint32_t type); + +/* Copies the layer and tree part of one address into the other */ +#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); + +/* These functions are used for WOTS and FORS addresses. */ + +#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) +void set_keypair_addr(uint32_t addr[8], uint32_t keypair); + +#define set_chain_addr SPX_NAMESPACE(set_chain_addr) +void set_chain_addr(uint32_t addr[8], uint32_t chain); + +#define set_hash_addr SPX_NAMESPACE(set_hash_addr) +void set_hash_addr(uint32_t addr[8], uint32_t hash); + +#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); + +/* These functions are used for all hash tree addresses (including FORS). */ + +#define set_tree_height SPX_NAMESPACE(set_tree_height) +void set_tree_height(uint32_t addr[8], uint32_t tree_height); + +#define set_tree_index SPX_NAMESPACE(set_tree_index) +void set_tree_index(uint32_t addr[8], uint32_t tree_index); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/api.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/api.h new file mode 100644 index 0000000000..11a6733200 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/api.h @@ -0,0 +1,77 @@ +#ifndef PQCLEAN_SPHINCSSHAKE192SROBUST_AARCH64_API_H +#define PQCLEAN_SPHINCSSHAKE192SROBUST_AARCH64_API_H + +#include +#include + +#define PQCLEAN_SPHINCSSHAKE192SROBUST_AARCH64_CRYPTO_ALGNAME "SPHINCS+-shake-192s-robust" + +#define PQCLEAN_SPHINCSSHAKE192SROBUST_AARCH64_CRYPTO_SECRETKEYBYTES 96 +#define PQCLEAN_SPHINCSSHAKE192SROBUST_AARCH64_CRYPTO_PUBLICKEYBYTES 48 +#define PQCLEAN_SPHINCSSHAKE192SROBUST_AARCH64_CRYPTO_BYTES 16224 + +#define PQCLEAN_SPHINCSSHAKE192SROBUST_AARCH64_CRYPTO_SEEDBYTES 72 + +/* + * Returns the length of a secret key, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE192SROBUST_AARCH64_crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE192SROBUST_AARCH64_crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE192SROBUST_AARCH64_crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE192SROBUST_AARCH64_crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +int PQCLEAN_SPHINCSSHAKE192SROBUST_AARCH64_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +int PQCLEAN_SPHINCSSHAKE192SROBUST_AARCH64_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +int PQCLEAN_SPHINCSSHAKE192SROBUST_AARCH64_crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +int PQCLEAN_SPHINCSSHAKE192SROBUST_AARCH64_crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, + const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +int PQCLEAN_SPHINCSSHAKE192SROBUST_AARCH64_crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +int PQCLEAN_SPHINCSSHAKE192SROBUST_AARCH64_crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/context.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/context.h new file mode 100644 index 0000000000..6e0a33f3b7 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/context.h @@ -0,0 +1,19 @@ +#ifndef SPX_CONTEXT_H +#define SPX_CONTEXT_H + +#include + +#include "params.h" + +typedef struct { + uint8_t pub_seed[SPX_N]; + uint8_t sk_seed[SPX_N]; +} spx_ctx; + +#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) +void initialize_hash_function(spx_ctx *ctx); + +#define free_hash_function SPX_NAMESPACE(free_hash_function) +void free_hash_function(spx_ctx *ctx); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/context_shake.c b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/context_shake.c new file mode 100644 index 0000000000..9614a103d3 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/context_shake.c @@ -0,0 +1,12 @@ +#include "context.h" + +/* For SHAKE256, there is no immediate reason to initialize at the start, + so this function is an empty operation. */ +void initialize_hash_function(spx_ctx *ctx) { + (void)ctx; /* Suppress an 'unused parameter' warning. */ +} + +// in case the hash function api is heap-based. +void free_hash_function(spx_ctx *ctx) { + (void)ctx; +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/f1600x2.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/f1600x2.h new file mode 100644 index 0000000000..70d1af9f14 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/f1600x2.h @@ -0,0 +1,11 @@ +#ifndef SPX_F1600X2_H +#define SPX_F1600X2_H + +#include + +extern uint64_t f1600_RC[24]; +extern void _f1600x2(uint64_t *a, uint64_t *rc); + +#define f1600x2(s) do {_f1600x2((s), f1600_RC);} while(0) + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/f1600x2.s b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/f1600x2.s new file mode 100644 index 0000000000..640ed791ed --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/f1600x2.s @@ -0,0 +1,143 @@ +# From https://github.com/bwesterb/armed-keccak + +.macro round + # Execute theta, but without xoring into the state yet. + # Compute parities p[i] = a[i] ^ a[5+i] ^ ... ^ a[20+i]. + eor3.16b v25, v0, v5, v10 + eor3.16b v26, v1, v6, v11 + eor3.16b v27, v2, v7, v12 + eor3.16b v28, v3, v8, v13 + eor3.16b v29, v4, v9, v14 + + eor3.16b v25, v25, v15, v20 + eor3.16b v26, v26, v16, v21 + eor3.16b v27, v27, v17, v22 + eor3.16b v28, v28, v18, v23 + eor3.16b v29, v29, v19, v24 + + # d[0] = rotl(p[1], 1) ^ p[4] + rax1.2d v30, v29, v26 + # d[3] = rotl(p[4], 1) ^ p[2] + rax1.2d v29, v27, v29 + # d[1] = rotl(p[2], 1) ^ p[0] + rax1.2d v27, v25, v27 + # d[4] = rotl(p[0], 1) ^ p[3] + rax1.2d v25, v28, v25 + # d[2] = rotl(p[3], 1) ^ p[1] + rax1.2d v28, v26, v28 + + # Xor parities from step theta into the state at the same time + # as executing rho and pi. + eor.16b v0, v0, v30 + mov.16b v31, v1 + xar.2d v1, v6, v27, 20 + xar.2d v6, v9, v25, 44 + xar.2d v9, v22, v28, 3 + xar.2d v22, v14, v25, 25 + xar.2d v14, v20, v30, 46 + xar.2d v20, v2, v28, 2 + xar.2d v2, v12, v28, 21 + xar.2d v12, v13, v29, 39 + xar.2d v13, v19, v25, 56 + xar.2d v19, v23, v29, 8 + xar.2d v23, v15, v30, 23 + xar.2d v15, v4, v25, 37 + xar.2d v4, v24, v25, 50 + xar.2d v24, v21, v27, 62 + xar.2d v21, v8, v29, 9 + xar.2d v8, v16, v27, 19 + xar.2d v16, v5, v30, 28 + xar.2d v5, v3, v29, 36 + xar.2d v3, v18, v29, 43 + xar.2d v18, v17, v28, 49 + xar.2d v17, v11, v27, 54 + xar.2d v11, v7, v28, 58 + xar.2d v7, v10, v30, 61 + xar.2d v10, v31, v27, 63 + + # Chi + bcax.16b v25, v0, v2, v1 + bcax.16b v26, v1, v3, v2 + bcax.16b v2, v2, v4, v3 + bcax.16b v3, v3, v0, v4 + bcax.16b v4, v4, v1, v0 + mov.16b v0, v25 + mov.16b v1, v26 + + bcax.16b v25, v5, v7, v6 + bcax.16b v26, v6, v8, v7 + bcax.16b v7, v7, v9, v8 + bcax.16b v8, v8, v5, v9 + bcax.16b v9, v9, v6, v5 + mov.16b v5, v25 + mov.16b v6, v26 + + bcax.16b v25, v10, v12, v11 + bcax.16b v26, v11, v13, v12 + bcax.16b v12, v12, v14, v13 + bcax.16b v13, v13, v10, v14 + bcax.16b v14, v14, v11, v10 + mov.16b v10, v25 + mov.16b v11, v26 + + bcax.16b v25, v15, v17, v16 + bcax.16b v26, v16, v18, v17 + bcax.16b v17, v17, v19, v18 + bcax.16b v18, v18, v15, v19 + bcax.16b v19, v19, v16, v15 + mov.16b v15, v25 + mov.16b v16, v26 + + bcax.16b v25, v20, v22, v21 + bcax.16b v26, v21, v23, v22 + bcax.16b v22, v22, v24, v23 + bcax.16b v23, v23, v20, v24 + bcax.16b v24, v24, v21, v20 + mov.16b v20, v25 + mov.16b v21, v26 + + # iota + ld1r {v25.2d}, [x1], #8 + eor.16b v0, v0, v25 +.endm + +.align 4 +.global __f1600x2 +__f1600x2: + stp d8, d9, [sp,#-16]! + stp d10, d11, [sp,#-16]! + stp d12, d13, [sp,#-16]! + stp d14, d15, [sp,#-16]! + + mov x2, x0 + mov x3, #24 + + ld1.2d {v0, v1, v2, v3}, [x0], #64 + ld1.2d {v4, v5, v6, v7}, [x0], #64 + ld1.2d {v8, v9, v10, v11}, [x0], #64 + ld1.2d {v12, v13, v14, v15}, [x0], #64 + ld1.2d {v16, v17, v18, v19}, [x0], #64 + ld1.2d {v20, v21, v22, v23}, [x0], #64 + ld1.2d {v24}, [x0] + +loop: + round + + subs x3, x3, #1 + cbnz x3, loop + + mov x0, x2 + st1.2d {v0, v1, v2, v3}, [x0], #64 + st1.2d {v4, v5, v6, v7}, [x0], #64 + st1.2d {v8, v9, v10, v11}, [x0], #64 + st1.2d {v12, v13, v14, v15}, [x0], #64 + st1.2d {v16, v17, v18, v19}, [x0], #64 + st1.2d {v20, v21, v22, v23}, [x0], #64 + st1.2d {v24}, [x0] + + ldp d14, d15, [sp], #16 + ldp d12, d13, [sp], #16 + ldp d10, d11, [sp], #16 + ldp d8, d9, [sp], #16 + + ret lr diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/f1600x2_const.c b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/f1600x2_const.c new file mode 100644 index 0000000000..e49c0ba149 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/f1600x2_const.c @@ -0,0 +1,30 @@ +#include "f1600x2.h" + +uint64_t f1600_RC[24] = { + 0x0000000000000001, + 0x0000000000008082, + 0x800000000000808A, + 0x8000000080008000, + 0x000000000000808B, + 0x0000000080000001, + 0x8000000080008081, + 0x8000000000008009, + 0x000000000000008A, + 0x0000000000000088, + 0x0000000080008009, + 0x000000008000000A, + 0x000000008000808B, + 0x800000000000008B, + 0x8000000000008089, + 0x8000000000008003, + 0x8000000000008002, + 0x8000000000000080, + 0x000000000000800A, + 0x800000008000000A, + 0x8000000080008081, + 0x8000000000008080, + 0x0000000080000001, + 0x8000000080008008, +}; + + diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/fips202x2.c b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/fips202x2.c new file mode 100644 index 0000000000..4718c343bc --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/fips202x2.c @@ -0,0 +1,148 @@ +#include +#include + +#include "fips202x2.h" +#include "f1600x2.h" +#include "fips202.h" + +uint64_t load64(const unsigned char *x) { + unsigned long long r = 0, i; + + for (i = 0; i < 8; ++i) { + r |= (unsigned long long)x[i] << 8 * i; + } + return r; +} + +void store64(uint8_t *x, uint64_t u) { + unsigned int i; + + for (i = 0; i < 8; ++i) { + x[i] = (uint8_t)u; + u >>= 8; + } +} + +static void keccak_absorb2x(uint64_t *s, + unsigned int r, + const unsigned char *m0, + const unsigned char *m1, + unsigned long long int mlen, + unsigned char p) { + unsigned long long i; + unsigned char t0[200]; + unsigned char t1[200]; + + while (mlen >= r) { + for (i = 0; i < r / 8; ++i) { + s[2 * i + 0] ^= load64(m0 + 8 * i); + s[2 * i + 1] ^= load64(m1 + 8 * i); + } + + f1600x2(s); + mlen -= r; + m0 += r; + m1 += r; + } + + for (i = 0; i < r; ++i) { + t0[i] = 0; + t1[i] = 0; + } + for (i = 0; i < mlen; ++i) { + t0[i] = m0[i]; + t1[i] = m1[i]; + } + + t0[i] = p; + t1[i] = p; + + t0[r - 1] |= 128; + t1[r - 1] |= 128; + + for (i = 0; i < r / 8; ++i) { + s[2 * i + 0] ^= load64(t0 + 8 * i); + s[2 * i + 1] ^= load64(t1 + 8 * i); + } +} + + +static void keccak_squeezeblocks2x(unsigned char *h0, + unsigned char *h1, + unsigned long long int nblocks, + uint64_t *s, + unsigned int r) { + unsigned int i; + + while (nblocks > 0) { + f1600x2(s); + for (i = 0; i < (r >> 3); i++) { + store64(h0 + 8 * i, s[2 * i + 0]); + store64(h1 + 8 * i, s[2 * i + 1]); + } + h0 += r; + h1 += r; + nblocks--; + } +} + + + +void shake128x2(unsigned char *out0, + unsigned char *out1, + unsigned long long outlen, + unsigned char *in0, + unsigned char *in1, + unsigned long long inlen) { + uint64_t s[50] = {0}; + unsigned char t0[SHAKE128_RATE]; + unsigned char t1[SHAKE128_RATE]; + unsigned int i; + + /* absorb 4 message of identical length in parallel */ + keccak_absorb2x(s, SHAKE128_RATE, in0, in1, inlen, 0x1F); + + /* Squeeze output */ + keccak_squeezeblocks2x(out0, out1, outlen / SHAKE128_RATE, s, SHAKE128_RATE); + + out0 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; + out1 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; + + if (outlen % SHAKE128_RATE) { + keccak_squeezeblocks2x(t0, t1, 1, s, SHAKE128_RATE); + for (i = 0; i < outlen % SHAKE128_RATE; i++) { + out0[i] = t0[i]; + out1[i] = t1[i]; + } + } +} + + +void shake256x2(unsigned char *out0, + unsigned char *out1, + unsigned long long outlen, + unsigned char *in0, + unsigned char *in1, + unsigned long long inlen) { + uint64_t s[50] = {0}; + unsigned char t0[SHAKE256_RATE]; + unsigned char t1[SHAKE256_RATE]; + unsigned int i; + + /* absorb 2 message of identical length in parallel */ + keccak_absorb2x(s, SHAKE256_RATE, in0, in1, inlen, 0x1F); + + /* Squeeze output */ + keccak_squeezeblocks2x(out0, out1, outlen / SHAKE256_RATE, s, SHAKE256_RATE); + + out0 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; + out1 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; + + if (outlen % SHAKE256_RATE) { + keccak_squeezeblocks2x(t0, t1, 1, s, SHAKE256_RATE); + for (i = 0; i < outlen % SHAKE256_RATE; i++) { + out0[i] = t0[i]; + out1[i] = t1[i]; + } + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/fips202x2.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/fips202x2.h new file mode 100644 index 0000000000..7ba58b35d8 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/fips202x2.h @@ -0,0 +1,24 @@ +#ifndef SPX_FIPS202X2_H +#define SPX_FIPS202X2_H + +#include + +uint64_t load64(const unsigned char *x); +void store64(uint8_t *x, uint64_t u); + + +void shake128x2(unsigned char *out0, + unsigned char *out1, + unsigned long long outlen, + unsigned char *in0, + unsigned char *in1, + unsigned long long inlen); + +void shake256x2(unsigned char *out0, + unsigned char *out1, + unsigned long long outlen, + unsigned char *in0, + unsigned char *in1, + unsigned long long inlen); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/fors.c b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/fors.c new file mode 100644 index 0000000000..39193d04e2 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/fors.c @@ -0,0 +1,191 @@ +#include +#include +#include + +#include "fors.h" + +#include "address.h" +#include "hash.h" +#include "hashx2.h" +#include "thash.h" +#include "thashx2.h" +#include "utils.h" +#include "utilsx2.h" + +static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + prf_addr(sk, ctx, fors_leaf_addr); +} + +static void fors_gen_skx2(unsigned char *sk0, + unsigned char *sk1, + const spx_ctx *ctx, + uint32_t fors_leaf_addrx2[2 * 8]) { + prf_addrx2(sk0, sk1, + ctx, fors_leaf_addrx2); +} + +static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, + const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + thash(leaf, sk, 1, ctx, fors_leaf_addr); +} + +static void fors_sk_to_leafx2(unsigned char *leaf0, + unsigned char *leaf1, + const unsigned char *sk0, + const unsigned char *sk1, + const spx_ctx *ctx, + uint32_t fors_leaf_addrx2[2 * 8]) { + thashx2(leaf0, leaf1, + sk0, sk1, + 1, ctx, fors_leaf_addrx2); +} + +struct fors_gen_leaf_info { + uint32_t leaf_addrx[2 * 8]; +}; + +static void fors_gen_leafx2(unsigned char *leaf, + const spx_ctx *ctx, + uint32_t addr_idx, void *info) { + struct fors_gen_leaf_info *fors_info = info; + uint32_t *fors_leaf_addrx2 = fors_info->leaf_addrx; + unsigned int j; + + /* Only set the parts that the caller doesn't set */ + for (j = 0; j < 2; j++) { + set_tree_index(fors_leaf_addrx2 + j * 8, addr_idx + j); + set_type(fors_leaf_addrx2 + j * 8, SPX_ADDR_TYPE_FORSPRF); + } + + fors_gen_skx2(leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + ctx, fors_leaf_addrx2); + + for (j = 0; j < 2; j++) { + set_type(fors_leaf_addrx2 + j * 8, SPX_ADDR_TYPE_FORSTREE); + } + + fors_sk_to_leafx2(leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + ctx, fors_leaf_addrx2); +} + +/** + * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + * Assumes indices has space for SPX_FORS_TREES integers. + */ +static void message_to_indices(uint32_t *indices, const unsigned char *m) { + unsigned int i, j; + unsigned int offset = 0; + + for (i = 0; i < SPX_FORS_TREES; i++) { + indices[i] = 0; + for (j = 0; j < SPX_FORS_HEIGHT; j++) { + indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); + offset++; + } + } +} + +/** + * Signs a message m, deriving the secret key from sk_seed and the FTS address. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + uint32_t fors_tree_addr[2 * 8] = {0}; + struct fors_gen_leaf_info fors_info = {0}; + uint32_t *fors_leaf_addr = fors_info.leaf_addrx; + uint32_t fors_pk_addr[8] = {0}; + uint32_t idx_offset; + unsigned int i; + + for (i = 0; i < 2; i++) { + copy_keypair_addr(fors_tree_addr + 8 * i, fors_addr); + set_type(fors_tree_addr + 8 * i, SPX_ADDR_TYPE_FORSTREE); + copy_keypair_addr(fors_leaf_addr + 8 * i, fors_addr); + } + copy_keypair_addr(fors_pk_addr, fors_addr); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); + + message_to_indices(indices, m); + + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); + + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + + /* Include the secret key part that produces the selected leaf node. */ + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); + fors_gen_sk(sig, ctx, fors_tree_addr); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + sig += SPX_N; + + /* Compute the authentication path for this leaf node. */ + treehashx2(roots + i * SPX_N, sig, ctx, + indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx2, + fors_tree_addr, &fors_info); + + sig += SPX_N * SPX_FORS_HEIGHT; + } + + /* Hash horizontally across all tree roots to derive the public key. */ + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); +} + +/** + * Derives the FORS public key from a signature. + * This can be used for verification by comparing to a known public key, or to + * subsequently verify a signature on the derived public key. The latter is the + * typical use-case when used as an FTS below an OTS in a hypertree. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + unsigned char leaf[SPX_N]; + uint32_t fors_tree_addr[8] = {0}; + uint32_t fors_pk_addr[8] = {0}; + uint32_t idx_offset; + unsigned int i; + + copy_keypair_addr(fors_tree_addr, fors_addr); + copy_keypair_addr(fors_pk_addr, fors_addr); + + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); + + message_to_indices(indices, m); + + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); + + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + + /* Derive the leaf from the included secret key part. */ + fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); + sig += SPX_N; + + /* Derive the corresponding root node of this tree. */ + compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, + sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); + sig += SPX_N * SPX_FORS_HEIGHT; + } + + /* Hash horizontally across all tree roots to derive the public key. */ + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/fors.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/fors.h new file mode 100644 index 0000000000..509140a178 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/fors.h @@ -0,0 +1,32 @@ +#ifndef SPX_FORS_H +#define SPX_FORS_H + +#include + +#include "context.h" +#include "params.h" + +/** + * Signs a message m, deriving the secret key from sk_seed and the FTS address. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +#define fors_sign SPX_NAMESPACE(fors_sign) +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); + +/** + * Derives the FORS public key from a signature. + * This can be used for verification by comparing to a known public key, or to + * subsequently verify a signature on the derived public key. The latter is the + * typical use-case when used as an FTS below an OTS in a hypertree. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/hash.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/hash.h new file mode 100644 index 0000000000..f7c87d4c3c --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/hash.h @@ -0,0 +1,28 @@ +#ifndef SPX_HASH_H +#define SPX_HASH_H + +#include +#include + +#include "context.h" +#include "params.h" + +#define prf_addr SPX_NAMESPACE(prf_addr) +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]); + +#define gen_message_random SPX_NAMESPACE(gen_message_random) +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); + +#define hash_message SPX_NAMESPACE(hash_message) +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); + + + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/hash_shake.c b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/hash_shake.c new file mode 100644 index 0000000000..ff5e7ec918 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/hash_shake.c @@ -0,0 +1,83 @@ +#include +#include + +#include "hash.h" + +#include "address.h" +#include "fips202.h" +#include "params.h" +#include "utils.h" + +/* + * Computes PRF(pk_seed, sk_seed, addr) + */ +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]) { + unsigned char buf[2 * SPX_N + SPX_ADDR_BYTES]; + + memcpy(buf, ctx->pub_seed, SPX_N); + memcpy(buf + SPX_N, addr, SPX_ADDR_BYTES); + memcpy(buf + SPX_N + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); + + shake256(out, SPX_N, buf, 2 * SPX_N + SPX_ADDR_BYTES); +} + +/** + * Computes the message-dependent randomness R, using a secret seed and an + * optional randomization value as well as the message. + */ +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { + (void)ctx; + shake256incctx s_inc; + + shake256_inc_init(&s_inc); + shake256_inc_absorb(&s_inc, sk_prf, SPX_N); + shake256_inc_absorb(&s_inc, optrand, SPX_N); + shake256_inc_absorb(&s_inc, m, mlen); + shake256_inc_finalize(&s_inc); + shake256_inc_squeeze(R, SPX_N, &s_inc); + shake256_inc_ctx_release(&s_inc); +} + +/** + * Computes the message hash using R, the public key, and the message. + * Outputs the message digest and the index of the leaf. The index is split in + * the tree index and the leaf index, for convenient copying to an address. + */ +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { + (void)ctx; +#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) +#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) +#define SPX_LEAF_BITS SPX_TREE_HEIGHT +#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) +#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) + + unsigned char buf[SPX_DGST_BYTES]; + unsigned char *bufp = buf; + shake256incctx s_inc; + + shake256_inc_init(&s_inc); + shake256_inc_absorb(&s_inc, R, SPX_N); + shake256_inc_absorb(&s_inc, pk, SPX_PK_BYTES); + shake256_inc_absorb(&s_inc, m, mlen); + shake256_inc_finalize(&s_inc); + shake256_inc_squeeze(buf, SPX_DGST_BYTES, &s_inc); + shake256_inc_ctx_release(&s_inc); + + memcpy(digest, bufp, SPX_FORS_MSG_BYTES); + bufp += SPX_FORS_MSG_BYTES; + + + *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); + *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); + bufp += SPX_TREE_BYTES; + + *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); + *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/hash_shakex2.c b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/hash_shakex2.c new file mode 100644 index 0000000000..99571916a2 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/hash_shakex2.c @@ -0,0 +1,52 @@ +#include +#include + +#include "hashx2.h" + +#include "address.h" +#include "f1600x2.h" +#include "fips202x2.h" +#include "params.h" + +/* + * 2-way parallel version of prf_addr; takes 2x as much input and output + */ +void prf_addrx2(unsigned char *out0, + unsigned char *out1, + const spx_ctx *ctx, + const uint32_t addrx2[2 * 8]) { + /* As we write and read only a few quadwords, it is more efficient to + * build and extract from the fourway SHAKE256 state by hand. */ + uint64_t state[50] = {0}; + + for (int i = 0; i < SPX_N / 8; i++) { + uint64_t x = load64(ctx->pub_seed + 8 * i); + state[2 * i] = x; + state[2 * i + 1] = x; + } + for (int i = 0; i < 4; i++) { + state[2 * (SPX_N / 8 + i)] = (((uint64_t)addrx2[1 + 2 * i]) << 32) + | (uint64_t)addrx2[2 * i]; + state[2 * (SPX_N / 8 + i) + 1] = (((uint64_t)addrx2[8 + 1 + 2 * i]) << 32) + | (uint64_t)addrx2[8 + 2 * i]; + } + for (int i = 0; i < SPX_N / 8; i++) { + uint64_t x = load64(ctx->sk_seed + 8 * i); + state[2 * (SPX_N / 8 + i + 4)] = x; + state[2 * (SPX_N / 8 + i + 4) + 1] = x; + } + + /* SHAKE domain separator and padding. */ + state[2 * (SPX_N / 4 + 4)] = 0x1f; + state[2 * (SPX_N / 4 + 4) + 1] = 0x1f; + + state[2 * 16] = 0x80ULL << 56; + state[2 * 16 + 1] = 0x80ULL << 56; + + f1600x2(state); + + for (int i = 0; i < SPX_N / 8; i++) { + store64(out0 + 8 * i, state[2 * i]); + store64(out1 + 8 * i, state[2 * i + 1]); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/hashx2.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/hashx2.h new file mode 100644 index 0000000000..99b8873a9b --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/hashx2.h @@ -0,0 +1,14 @@ +#ifndef SPX_HASHX2_H +#define SPX_HASHX2_H + +#include "context.h" +#include "params.h" +#include + +#define prf_addrx2 SPX_NAMESPACE(prf_addrx2) +void prf_addrx2(unsigned char *out0, + unsigned char *out1, + const spx_ctx *ctx, + const uint32_t addrx2[2 * 8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/merkle.c b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/merkle.c new file mode 100644 index 0000000000..c94ee23939 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/merkle.c @@ -0,0 +1,64 @@ +#include +#include + +#include "merkle.h" + +#include "address.h" +#include "params.h" +#include "utils.h" +#include "utilsx2.h" +#include "wots.h" +#include "wotsx2.h" + +/* + * This generates a Merkle signature (WOTS signature followed by the Merkle + * authentication path). + */ +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf) { + unsigned char *auth_path = sig + SPX_WOTS_BYTES; + uint32_t tree_addrx2[2 * 8] = { 0 }; + int j; + struct leaf_info_x2 info = { 0 }; + unsigned steps[ SPX_WOTS_LEN ]; + + info.wots_sig = sig; + chain_lengths(steps, root); + info.wots_steps = steps; + + for (j = 0; j < 2; j++) { + set_type(&tree_addrx2[8 * j], SPX_ADDR_TYPE_HASHTREE); + set_type(&info.leaf_addr[8 * j], SPX_ADDR_TYPE_WOTS); + set_type(&info.pk_addr[8 * j], SPX_ADDR_TYPE_WOTSPK); + copy_subtree_addr(&tree_addrx2[8 * j], tree_addr); + copy_subtree_addr(&info.leaf_addr[8 * j], wots_addr); + copy_subtree_addr(&info.pk_addr[8 * j], wots_addr); + } + + info.wots_sign_leaf = idx_leaf; + + treehashx2(root, auth_path, ctx, + idx_leaf, 0, + SPX_TREE_HEIGHT, + wots_gen_leafx2, + tree_addrx2, &info); +} + +/* Compute root node of the top-most subtree. */ +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { + /* We do not need the auth path in key generation, but it simplifies the + code to have just one treehash routine that computes both root and path + in one function. */ + unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; + uint32_t top_tree_addr[8] = {0}; + uint32_t wots_addr[8] = {0}; + + set_layer_addr(top_tree_addr, SPX_D - 1); + set_layer_addr(wots_addr, SPX_D - 1); + + merkle_sign(auth_path, root, ctx, + wots_addr, top_tree_addr, + ~0 /* ~0 means "don't bother generating an auth path */ ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/merkle.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/merkle.h new file mode 100644 index 0000000000..769cf2e970 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/merkle.h @@ -0,0 +1,21 @@ +#ifndef MERKLE_H_ +#define MERKLE_H_ + +#include + +#include "context.h" +#include "params.h" + +/* Generate a Merkle signature (WOTS signature followed by the Merkle */ +/* authentication path) */ +#define merkle_sign SPX_NAMESPACE(merkle_sign) +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf); + +/* Compute the root node of the top-most subtree. */ +#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); + +#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/nistapi.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/nistapi.h new file mode 100644 index 0000000000..3cb71afad4 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/nistapi.h @@ -0,0 +1,87 @@ +#ifndef SPX_API_H +#define SPX_API_H + +#include +#include + +#include "params.h" + +#define CRYPTO_ALGNAME "SPHINCS+" + +#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES +#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES +#define CRYPTO_BYTES SPX_BYTES +#define CRYPTO_SEEDBYTES (3*SPX_N) + +/* + * Returns the length of a secret key, in bytes + */ +#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) +size_t crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) +size_t crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) +size_t crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) +size_t crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +#define crypto_sign SPX_NAMESPACE(crypto_sign) +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/params.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/params.h new file mode 100644 index 0000000000..a170327186 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/params.h @@ -0,0 +1,56 @@ +#ifndef SPX_PARAMS_H +#define SPX_PARAMS_H + +#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSSHAKE192SROBUST_AARCH64_##s + +/* Hash output length in bytes. */ +#define SPX_N 24 +/* Height of the hypertree. */ +#define SPX_FULL_HEIGHT 63 +/* Number of subtree layer. */ +#define SPX_D 7 +/* FORS tree dimensions. */ +#define SPX_FORS_HEIGHT 14 +#define SPX_FORS_TREES 17 +/* Winternitz parameter, */ +#define SPX_WOTS_W 16 + +/* The hash function is defined by linking a different hash.c file, as opposed + to setting a #define constant. */ + +/* For clarity */ +#define SPX_ADDR_BYTES 32 + +/* WOTS parameters. */ +#define SPX_WOTS_LOGW 4 + +#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) + +/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ +#define SPX_WOTS_LEN2 3 + +#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) +#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) +#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES + +/* Subtree size. */ +#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) + +//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT +// #error SPX_D should always divide SPX_FULL_HEIGHT +//#endif + +/* FORS parameters. */ +#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) +#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) +#define SPX_FORS_PK_BYTES SPX_N + +/* Resulting SPX sizes. */ +#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ + SPX_FULL_HEIGHT * SPX_N) +#define SPX_PK_BYTES (2 * SPX_N) +#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) + +#include "shake_offsets.h" + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/shake_offsets.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/shake_offsets.h new file mode 100644 index 0000000000..6b28d95d91 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/shake_offsets.h @@ -0,0 +1,21 @@ +#ifndef SHAKE_OFFSETS_H_ +#define SHAKE_OFFSETS_H_ + +/* + * Offsets of various fields in the address structure when we use SHAKE as + * the Sphincs+ hash function + */ + +#define SPX_OFFSET_LAYER 3 /* The byte used to specify the Merkle tree layer */ +#define SPX_OFFSET_TREE 8 /* The start of the 8 byte field used to specify the tree */ +#define SPX_OFFSET_TYPE 19 /* The byte used to specify the hash type (reason) */ +#define SPX_OFFSET_KP_ADDR2 22 /* The high byte used to specify the key pair (which one-time signature) */ +#define SPX_OFFSET_KP_ADDR1 23 /* The low byte used to specify the key pair */ +#define SPX_OFFSET_CHAIN_ADDR 27 /* The byte used to specify the chain address (which Winternitz chain) */ +#define SPX_OFFSET_HASH_ADDR 31 /* The byte used to specify the hash address (where in the Winternitz chain) */ +#define SPX_OFFSET_TREE_HGT 27 /* The byte used to specify the height of this node in the FORS or Merkle tree */ +#define SPX_OFFSET_TREE_INDEX 28 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ + +#define SPX_SHAKE 1 + +#endif /* SHAKE_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/sign.c b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/sign.c new file mode 100644 index 0000000000..9d0c7d1b22 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/sign.c @@ -0,0 +1,286 @@ +#include +#include +#include + +#include "address.h" +#include "context.h" +#include "fors.h" +#include "hash.h" +#include "merkle.h" +#include "nistapi.h" +#include "params.h" +#include "randombytes.h" +#include "thash.h" +#include "utils.h" +#include "wots.h" + +/* + * Returns the length of a secret key, in bytes + */ +size_t crypto_sign_secretkeybytes(void) { + return CRYPTO_SECRETKEYBYTES; +} + +/* + * Returns the length of a public key, in bytes + */ +size_t crypto_sign_publickeybytes(void) { + return CRYPTO_PUBLICKEYBYTES; +} + +/* + * Returns the length of a signature, in bytes + */ +size_t crypto_sign_bytes(void) { + return CRYPTO_BYTES; +} + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +size_t crypto_sign_seedbytes(void) { + return CRYPTO_SEEDBYTES; +} + +/* + * Generates an SPX key pair given a seed of length + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [PUB_SEED || root] + */ +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed) { + spx_ctx ctx; + + /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ + memcpy(sk, seed, CRYPTO_SEEDBYTES); + + memcpy(pk, sk + 2 * SPX_N, SPX_N); + + memcpy(ctx.pub_seed, pk, SPX_N); + memcpy(ctx.sk_seed, sk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + /* Compute root node of the top-most subtree. */ + merkle_gen_root(sk + 3 * SPX_N, &ctx); + + // cleanup + free_hash_function(&ctx); + + memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); + + return 0; +} + +/* + * Generates an SPX key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [PUB_SEED || root] + */ +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { + uint8_t seed[CRYPTO_SEEDBYTES]; + randombytes(seed, CRYPTO_SEEDBYTES); + crypto_sign_seed_keypair(pk, sk, seed); + + return 0; +} + +/** + * Returns an array containing a detached signature. + */ +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk) { + spx_ctx ctx; + + const uint8_t *sk_prf = sk + SPX_N; + const uint8_t *pk = sk + 2 * SPX_N; + + uint8_t optrand[SPX_N]; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t root[SPX_N]; + uint32_t i; + uint64_t tree; + uint32_t idx_leaf; + uint32_t wots_addr[8] = {0}; + uint32_t tree_addr[8] = {0}; + + memcpy(ctx.sk_seed, sk, SPX_N); + memcpy(ctx.pub_seed, pk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + + /* Optionally, signing can be made non-deterministic using optrand. + This can help counter side-channel attacks that would benefit from + getting a large number of traces when the signer uses the same nodes. */ + randombytes(optrand, SPX_N); + /* Compute the digest randomization value. */ + gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); + + /* Derive the message digest and leaf index from R, PK and M. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; + + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); + + /* Sign the message hash using FORS. */ + fors_sign(sig, root, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); + sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; + + /* Update the indices for the next layer. */ + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; + } + + free_hash_function(&ctx); + + *siglen = SPX_BYTES; + + return 0; +} + +/** + * Verifies a detached signature and message under a given public key. + */ +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk) { + spx_ctx ctx; + const uint8_t *pub_root = pk + SPX_N; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t wots_pk[SPX_WOTS_BYTES]; + uint8_t root[SPX_N]; + uint8_t leaf[SPX_N]; + unsigned int i; + uint64_t tree; + uint32_t idx_leaf; + uint32_t wots_addr[8] = {0}; + uint32_t tree_addr[8] = {0}; + uint32_t wots_pk_addr[8] = {0}; + + if (siglen != SPX_BYTES) { + return -1; + } + + memcpy(ctx.pub_seed, pk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); + + /* Derive the message digest and leaf index from R || PK || M. */ + /* The additional SPX_N is a result of the hash domain separator. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; + + /* Layer correctly defaults to 0, so no need to set_layer_addr */ + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); + + fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + /* For each subtree.. */ + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + copy_keypair_addr(wots_pk_addr, wots_addr); + + /* The WOTS public key is only correct if the signature was correct. */ + /* Initially, root is the FORS pk, but on subsequent iterations it is + the root of the subtree below the currently processed subtree. */ + wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); + sig += SPX_WOTS_BYTES; + + /* Compute the leaf node using the WOTS public key. */ + thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); + + /* Compute the root node of this subtree. */ + compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, + &ctx, tree_addr); + sig += SPX_TREE_HEIGHT * SPX_N; + + /* Update the indices for the next layer. */ + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; + } + + // cleanup + free_hash_function(&ctx); + + /* Check if the root node equals the root node in the public key. */ + if (memcmp(root, pub_root, SPX_N) != 0) { + return -1; + } + + return 0; +} + + +/** + * Returns an array containing the signature followed by the message. + */ +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk) { + size_t siglen; + + crypto_sign_signature(sm, &siglen, m, mlen, sk); + + memmove(sm + SPX_BYTES, m, mlen); + *smlen = siglen + mlen; + + return 0; +} + +/** + * Verifies a given signature-message pair under a given public key. + */ +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk) { + /* The API caller does not necessarily know what size a signature should be + but SPHINCS+ signatures are always exactly SPX_BYTES. */ + if (smlen < SPX_BYTES) { + memset(m, 0, smlen); + *mlen = 0; + return -1; + } + + *mlen = smlen - SPX_BYTES; + + if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { + memset(m, 0, smlen); + *mlen = 0; + return -1; + } + + /* If verification was successful, move the message to the right place. */ + memmove(m, sm + SPX_BYTES, *mlen); + + return 0; +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/thash.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/thash.h new file mode 100644 index 0000000000..8687ccfb4d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/thash.h @@ -0,0 +1,13 @@ +#ifndef SPX_THASH_H +#define SPX_THASH_H + +#include "context.h" +#include "params.h" + +#include + +#define thash SPX_NAMESPACE(thash) +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/thash_shake_robustx2.c b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/thash_shake_robustx2.c new file mode 100644 index 0000000000..454fc0f4e2 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/thash_shake_robustx2.c @@ -0,0 +1,112 @@ +#include +#include + +#include "thash.h" +#include "thashx2.h" + +#include "address.h" +#include "params.h" +#include "utils.h" + +#include "f1600x2.h" +#include "fips202x2.h" + + +void thash(unsigned char *out, + const unsigned char *in, + unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]) { + uint32_t addrx2 [2 * 8] = { + addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], addr[6], addr[7], + addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], addr[6], addr[7] + }; + thashx2(out, out, in, in, inblocks, ctx, addrx2); +} + +/** + * 2-way parallel version of thash; takes 2x as much input and output + */ +void thashx2(unsigned char *out0, + unsigned char *out1, + const unsigned char *in0, + const unsigned char *in1, + unsigned int inblocks, + const spx_ctx *ctx, uint32_t addrx2[2 * 8]) { + if (inblocks == 1 || inblocks == 2) { + /* As we write and read only a few quadwords, it is more efficient to + * build and extract from the twoway SHAKE256 state by hand. */ + uint64_t state[50] = {0}; + uint64_t state2[50]; + + for (int i = 0; i < SPX_N / 8; i++) { + uint64_t x = load64(ctx->pub_seed + 8 * i); + state[2 * i] = x; + state[2 * i + 1] = x; + } + for (int i = 0; i < 4; i++) { + state[2 * (SPX_N / 8 + i)] = (((uint64_t)addrx2[1 + 2 * i]) << 32) + | (uint64_t)addrx2[2 * i]; + state[2 * (SPX_N / 8 + i) + 1] = (((uint64_t)addrx2[8 + 1 + 2 * i]) << 32) + | (uint64_t)addrx2[8 + 2 * i]; + } + + /* Domain separator and padding. */ + state[2 * 16] = 0x80ULL << 56; + state[2 * 16 + 1] = 0x80ULL << 56; + + state[2 * ((SPX_N / 8) + 4)] ^= 0x1f; + state[2 * ((SPX_N / 8) + 4) + 1] ^= 0x1f; + + /* We will permutate state2 with f1600x2 to compute the bitmask, + * but first we'll copy it to state2 which will be used to compute + * the final output, as its input is almost identical. */ + memcpy(state2, state, 400); + + f1600x2(state); + + /* By copying from state, state2 already contains the pub_seed + * and address. We just need to copy in the input blocks xorred with + * the bitmask we just computed. */ + for (unsigned int i = 0; i < (SPX_N / 8) * inblocks; i++) { + state2[2 * (SPX_N / 8 + 4 + i)] = state[2 * i] ^ load64(in0 + 8 * i); + state2[2 * (SPX_N / 8 + 4 + i) + 1] = state[2 * i + 1] ^ load64(in1 + 8 * i); + } + + /* Domain separator and start of padding. Note that the quadwords + * around are already zeroed for state from which we copied. + * We do a XOR instead of a set as this might be the 16th quadword + * when N=32 and inblocks=2, which already contains the end + * of the padding. */ + state2[2 * ((SPX_N / 8) * (1 + inblocks) + 4)] ^= 0x1f; + state2[2 * ((SPX_N / 8) * (1 + inblocks) + 4) + 1] ^= 0x1f; + + f1600x2(state2); + + for (int i = 0; i < SPX_N / 8; i++) { + store64(out0 + 8 * i, state2[2 * i]); + store64(out1 + 8 * i, state2[2 * i + 1]); + } + } else { + PQCLEAN_VLA(unsigned char, buf0, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, buf1, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, bitmask0, inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, bitmask1, inblocks * SPX_N); + unsigned int i; + + memcpy(buf0, ctx->pub_seed, SPX_N); + memcpy(buf1, ctx->pub_seed, SPX_N); + memcpy(buf0 + SPX_N, addrx2 + 0 * 8, SPX_ADDR_BYTES); + memcpy(buf1 + SPX_N, addrx2 + 1 * 8, SPX_ADDR_BYTES); + + shake256x2(bitmask0, bitmask1, inblocks * SPX_N, + buf0, buf1, SPX_N + SPX_ADDR_BYTES); + + for (i = 0; i < inblocks * SPX_N; i++) { + buf0[SPX_N + SPX_ADDR_BYTES + i] = in0[i] ^ bitmask0[i]; + buf1[SPX_N + SPX_ADDR_BYTES + i] = in1[i] ^ bitmask1[i]; + } + + shake256x2(out0, out1, SPX_N, + buf0, buf1, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/thashx2.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/thashx2.h new file mode 100644 index 0000000000..040375e618 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/thashx2.h @@ -0,0 +1,16 @@ +#ifndef SPX_THASHX2_H +#define SPX_THASHX2_H + +#include "context.h" +#include "params.h" +#include + +#define thashx2 SPX_NAMESPACE(thashx2) +void thashx2(unsigned char *out0, + unsigned char *out1, + const unsigned char *in0, + const unsigned char *in1, + unsigned int inblocks, + const spx_ctx *ctx, uint32_t addrx2[2 * 8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/utils.c b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/utils.c new file mode 100644 index 0000000000..177b541fb9 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/utils.c @@ -0,0 +1,148 @@ +#include + +#include "utils.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "thash.h" + +/** + * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. + */ +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in) { + int i; + + /* Iterate over out in decreasing order, for big-endianness. */ + for (i = (signed int)outlen - 1; i >= 0; i--) { + out[i] = in & 0xff; + in = in >> 8; + } +} + +void u32_to_bytes(unsigned char *out, uint32_t in) { + out[0] = (unsigned char)(in >> 24); + out[1] = (unsigned char)(in >> 16); + out[2] = (unsigned char)(in >> 8); + out[3] = (unsigned char)in; +} + +/** + * Converts the inlen bytes in 'in' from big-endian byte order to an integer. + */ +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { + unsigned long long retval = 0; + unsigned int i; + + for (i = 0; i < inlen; i++) { + retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); + } + return retval; +} + +/** + * Computes a root node given a leaf and an auth path. + * Expects address to be complete other than the tree_height and tree_index. + */ +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]) { + uint32_t i; + unsigned char buffer[2 * SPX_N]; + + /* If leaf_idx is odd (last bit = 1), current path element is a right child + and auth_path has to go left. Otherwise it is the other way around. */ + if (leaf_idx & 1) { + memcpy(buffer + SPX_N, leaf, SPX_N); + memcpy(buffer, auth_path, SPX_N); + } else { + memcpy(buffer, leaf, SPX_N); + memcpy(buffer + SPX_N, auth_path, SPX_N); + } + auth_path += SPX_N; + + for (i = 0; i < tree_height - 1; i++) { + leaf_idx >>= 1; + idx_offset >>= 1; + /* Set the address of the node we're creating. */ + set_tree_height(addr, i + 1); + set_tree_index(addr, leaf_idx + idx_offset); + + /* Pick the right or left neighbor, depending on parity of the node. */ + if (leaf_idx & 1) { + thash(buffer + SPX_N, buffer, 2, ctx, addr); + memcpy(buffer, auth_path, SPX_N); + } else { + thash(buffer, buffer, 2, ctx, addr); + memcpy(buffer + SPX_N, auth_path, SPX_N); + } + auth_path += SPX_N; + } + + /* The last iteration is exceptional; we do not copy an auth_path node. */ + leaf_idx >>= 1; + idx_offset >>= 1; + set_tree_height(addr, tree_height); + set_tree_index(addr, leaf_idx + idx_offset); + thash(root, buffer, 2, ctx, addr); +} + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx * /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]) { + PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); + PQCLEAN_VLA(unsigned int, heights, tree_height + 1); + unsigned int offset = 0; + uint32_t idx; + uint32_t tree_idx; + + for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { + /* Add the next leaf node to the stack. */ + gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); + offset++; + heights[offset - 1] = 0; + + /* If this is a node we need for the auth path.. */ + if ((leaf_idx ^ 0x1) == idx) { + memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); + } + + /* While the top-most nodes are of equal height.. */ + while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { + /* Compute index of the new node, in the next layer. */ + tree_idx = (idx >> (heights[offset - 1] + 1)); + + /* Set the address of the node we're creating. */ + set_tree_height(tree_addr, heights[offset - 1] + 1); + set_tree_index(tree_addr, + tree_idx + (idx_offset >> (heights[offset - 1] + 1))); + /* Hash the top-most nodes from the stack together. */ + thash(stack + (offset - 2)*SPX_N, + stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); + offset--; + /* Note that the top-most node is now one layer higher. */ + heights[offset - 1]++; + + /* If this is a node we need for the auth path.. */ + if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { + memcpy(auth_path + heights[offset - 1]*SPX_N, + stack + (offset - 1)*SPX_N, SPX_N); + } + } + } + memcpy(root, stack, SPX_N); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/utils.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/utils.h new file mode 100644 index 0000000000..64f5d5a53a --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/utils.h @@ -0,0 +1,58 @@ +#ifndef SPX_UTILS_H +#define SPX_UTILS_H + +#include + +#include "compat.h" +#include "context.h" +#include "params.h" + + +/* To support MSVC use alloca() instead of VLAs. See #20. */ + + +/** + * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. + */ +#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in); +#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) +void u32_to_bytes(unsigned char *out, uint32_t in); + +/** + * Converts the inlen bytes in 'in' from big-endian byte order to an integer. + */ +#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); + +/** + * Computes a root node given a leaf and an auth path. + * Expects address to be complete other than the tree_height and tree_index. + */ +#define compute_root SPX_NAMESPACE(compute_root) +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]); + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +#define treehash SPX_NAMESPACE(treehash) +void treehash(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx *ctx /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]); + + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/utilsx2.c b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/utilsx2.c new file mode 100644 index 0000000000..8736474e4f --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/utilsx2.c @@ -0,0 +1,130 @@ +#include + +#include "utilsx2.h" + +#include "address.h" +#include "params.h" +#include "thashx2.h" +#include "utils.h" + +/* + * Generate the entire Merkle tree, computing the authentication path for leaf_idx, + * and the resulting root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) + * + * This expects tree_addrx2 to be initialized to 2 parallel addr structures for + * the Merkle tree nodes + * + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + * + * This works by using the standard Merkle tree building algorithm, except + * that each 'node' tracked is actually 2 consecutive nodes in the real tree. + * When we combine two logical nodes AB and WX, we perform the H + * operation on adjacent real nodes, forming the parent logical node + * (AB)(WX) + * + * When we get to the top level of the real tree (where there is only + * one logical node), we continue this operation one more time; the right + * most real node will by the actual root (and the other node will be + * garbage). We follow the same thashx2 logic so that the 'extract + * authentication path components' part of the loop is still executed (and + * to simplify the code somewhat) + */ +void treehashx2(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, + uint32_t tree_height, + void (*gen_leafx2)( + unsigned char * /* Where to write the leaves */, + const spx_ctx *, + uint32_t idx, void *info), + uint32_t tree_addrx2[2 * 8], + void *info) { + /* This is where we keep the intermediate nodes */ + unsigned char stackx2[tree_height * 2 * SPX_N]; + uint32_t left_adj = 0, prev_left_adj = 0; /* When we're doing the top */ + /* level, the left-most part of the tree isn't at the beginning */ + /* of current[]. These give the offset of the actual start */ + + uint32_t idx; + uint32_t max_idx = (1 << (tree_height - 1)) - 1; + for (idx = 0;; idx++) { + unsigned char current[2 * SPX_N]; /* Current logical node */ + gen_leafx2( current, ctx, 2 * idx + idx_offset, + info ); + + /* Now combine the freshly generated right node with previously */ + /* generated left ones */ + uint32_t internal_idx_offset = idx_offset; + uint32_t internal_idx = idx; + uint32_t internal_leaf = leaf_idx; + uint32_t h; /* The height we are in the Merkle tree */ + for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { + + /* Special processing if we're at the top of the tree */ + if (h >= tree_height - 1) { + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[1 * SPX_N], SPX_N ); + return; + } + /* The tree indexing logic is a bit off in this case */ + /* Adjust it so that the left-most node of the part of */ + /* the tree that we're processing has index 0 */ + prev_left_adj = left_adj; + left_adj = 2 - (1 << (tree_height - h - 1)); + } + + /* Check if we hit the top of the tree */ + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[1 * SPX_N], SPX_N ); + return; + } + + /* + * Check if one of the nodes we have is a part of the + * authentication path; if it is, write it out + */ + if ((((internal_idx << 1) ^ internal_leaf) & ~0x1) == 0) { + memcpy( &auth_path[ h * SPX_N ], + ¤t[(((internal_leaf & 1) ^ 1) + prev_left_adj) * SPX_N], + SPX_N ); + } + + /* + * Check if we're at a left child; if so, stop going up the stack + * Exception: if we've reached the end of the tree, keep on going + * (so we combine the last 2 nodes into the one root node in two + * more iterations) + */ + if ((internal_idx & 1) == 0 && idx < max_idx) { + break; + } + + /* Ok, we're at a right node (or doing the top 3 levels) */ + /* Now combine the left and right logical nodes together */ + + /* Set the address of the node we're creating. */ + int j; + internal_idx_offset >>= 1; + for (j = 0; j < 2; j++) { + set_tree_height(tree_addrx2 + j * 8, h + 1); + set_tree_index(tree_addrx2 + j * 8, + (2 / 2) * (internal_idx & ~1) + j - left_adj + internal_idx_offset ); + } + unsigned char *left = &stackx2[h * 2 * SPX_N]; + thashx2( ¤t[0 * SPX_N], + ¤t[1 * SPX_N], + &left [0 * SPX_N], + ¤t[0 * SPX_N], + 2, ctx, tree_addrx2); + } + + /* We've hit a left child; save the current for when we get the */ + /* corresponding right right */ + memcpy( &stackx2[h * 2 * SPX_N], current, 2 * SPX_N); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/utilsx2.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/utilsx2.h new file mode 100644 index 0000000000..e09faddc43 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/utilsx2.h @@ -0,0 +1,30 @@ +#ifndef SPX_UTILSX2_H +#define SPX_UTILSX2_H + +#include + +#include "context.h" +#include "params.h" + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + * + * This implementation uses SIMD to compute internal nodes 2 at a time (in + * parallel) + */ +#define treehashx2 SPX_NAMESPACE(treehashx2) +void treehashx2(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leafx2)( + unsigned char * /* Where to write the leaves */, + const spx_ctx * /* ctx */, + uint32_t addr_idx, void *info), + uint32_t tree_addrx2[2 * 8], void *info); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/wots.c b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/wots.c new file mode 100644 index 0000000000..3babe45e95 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/wots.c @@ -0,0 +1,259 @@ +#include +#include + +#include "wots.h" +#include "wotsx2.h" + +#include "address.h" +#include "hash.h" +#include "hashx2.h" +#include "params.h" +#include "thashx2.h" +#include "utils.h" +#include "utilsx2.h" + +// TODO clarify address expectations, and make them more uniform. +// TODO i.e. do we expect types to be set already? +// TODO and do we expect modifications or copies? + +/** + * Computes up the chains + */ +static void gen_chains( + unsigned char *out, + const unsigned char *in, + unsigned int start[SPX_WOTS_LEN], + const unsigned int steps[SPX_WOTS_LEN], + const spx_ctx *ctx, + uint32_t addr[8]) { + uint32_t i, j, k, idx, watching; + int done; + unsigned char empty[SPX_N]; + unsigned char *bufs[4]; + uint32_t addrs[8 * 2]; + + int l; + uint16_t counts[SPX_WOTS_W] = { 0 }; + uint16_t idxs[SPX_WOTS_LEN]; + uint16_t total, newTotal; + + /* set addrs = {addr, addr} */ + for (j = 0; j < 2; j++) { + memcpy(addrs + j * 8, addr, sizeof(uint32_t) * 8); + } + + /* Initialize out with the value at position 'start'. */ + memcpy(out, in, SPX_WOTS_LEN * SPX_N); + + /* Sort the chains in reverse order by steps using counting sort. */ + for (i = 0; i < SPX_WOTS_LEN; i++) { + counts[steps[i]]++; + } + total = 0; + for (l = SPX_WOTS_W - 1; l >= 0; l--) { + newTotal = counts[l] + total; + counts[l] = total; + total = newTotal; + } + for (i = 0; i < SPX_WOTS_LEN; i++) { + idxs[counts[steps[i]]] = i; + counts[steps[i]]++; + } + + /* We got our work cut out for us: do it! */ + for (i = 0; i < SPX_WOTS_LEN; i += 2) { + for (j = 0; j < 2 && i + j < SPX_WOTS_LEN; j++) { + idx = idxs[i + j]; + set_chain_addr(addrs + j * 8, idx); + bufs[j] = out + SPX_N * idx; + } + + /* As the chains are sorted in reverse order, we know that the first + * chain is the longest and the last one is the shortest. We keep + * an eye on whether the last chain is done and then on the one before, + * et cetera. */ + watching = 1; + done = 0; + while (i + watching >= SPX_WOTS_LEN) { + bufs[watching] = &empty[0]; + watching--; + } + + for (k = 0;; k++) { + while (k == steps[idxs[i + watching]]) { + bufs[watching] = &empty[0]; + if (watching == 0) { + done = 1; + break; + } + watching--; + } + if (done) { + break; + } + for (j = 0; j < watching + 1; j++) { + set_hash_addr(addrs + j * 8, k + start[idxs[i + j]]); + } + + thashx2(bufs[0], bufs[1], + bufs[0], bufs[1], 1, ctx, addrs); + } + } +} + +/** + * base_w algorithm as described in draft. + * Interprets an array of bytes as integers in base w. + * This only works when log_w is a divisor of 8. + */ +static void base_w(unsigned int *output, const int out_len, + const unsigned char *input) { + int in = 0; + int out = 0; + unsigned char total = 0; + int bits = 0; + int consumed; + + for (consumed = 0; consumed < out_len; consumed++) { + if (bits == 0) { + total = input[in]; + in++; + bits += 8; + } + bits -= SPX_WOTS_LOGW; + output[out] = (total >> bits) & (SPX_WOTS_W - 1); + out++; + } +} + +/* Computes the WOTS+ checksum over a message (in base_w). */ +static void wots_checksum(unsigned int *csum_base_w, + const unsigned int *msg_base_w) { + unsigned int csum = 0; + unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; + unsigned int i; + + /* Compute checksum. */ + for (i = 0; i < SPX_WOTS_LEN1; i++) { + csum += SPX_WOTS_W - 1 - msg_base_w[i]; + } + + /* Convert checksum to base_w. */ + /* Make sure expected empty zero bits are the least significant bits. */ + csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); + ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); + base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); +} + +/* Takes a message and derives the matching chain lengths. */ +void chain_lengths(unsigned int *lengths, const unsigned char *msg) { + base_w(lengths, SPX_WOTS_LEN1, msg); + wots_checksum(lengths + SPX_WOTS_LEN1, lengths); +} + +/** + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. + * + * Writes the computed public key to 'pk'. + */ +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]) { + unsigned int steps[SPX_WOTS_LEN]; + unsigned int start[SPX_WOTS_LEN]; + uint32_t i; + + chain_lengths(start, msg); + + for (i = 0; i < SPX_WOTS_LEN; i++) { + steps[i] = SPX_WOTS_W - 1 - start[i]; + } + + gen_chains(pk, sig, start, steps, ctx, addr); +} + +/* + * This generates 2 sequential WOTS public keys + * It also generates the WOTS signature if leaf_info indicates + * that we're signing with one of these WOTS keys + */ +void wots_gen_leafx2(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info) { + struct leaf_info_x2 *info = v_info; + uint32_t *leaf_addr = info->leaf_addr; + uint32_t *pk_addr = info->pk_addr; + unsigned int i, j, k; + unsigned char pk_buffer[ 2 * SPX_WOTS_BYTES ]; + unsigned wots_offset = SPX_WOTS_BYTES; + unsigned char *buffer; + uint32_t wots_k_mask; + unsigned wots_sign_index; + + if (((leaf_idx ^ info->wots_sign_leaf) & ~1) == 0) { + /* We're traversing the leaf that's signing; generate the WOTS */ + /* signature */ + wots_k_mask = 0; + wots_sign_index = info->wots_sign_leaf & 1; /* Which of of the 2 */ + /* slots do the signatures come from */ + } else { + /* Nope, we're just generating pk's; turn off the signature logic */ + wots_k_mask = ~0; + wots_sign_index = 0; + } + + for (j = 0; j < 2; j++) { + set_keypair_addr( leaf_addr + j * 8, leaf_idx + j ); + set_keypair_addr( pk_addr + j * 8, leaf_idx + j ); + } + + for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { + uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k to */ + /* the step if we're generating a signature, ~0 if we're not */ + + /* Start with the secret seed */ + for (j = 0; j < 2; j++) { + set_chain_addr(leaf_addr + j * 8, i); + set_hash_addr(leaf_addr + j * 8, 0); + set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTSPRF); + } + prf_addrx2(buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + ctx, leaf_addr); + for (j = 0; j < 2; j++) { + set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTS); + } + + /* Iterate down the WOTS chain */ + for (k = 0;; k++) { + /* Check if one of the values we have needs to be saved as a */ + /* part of the WOTS signature */ + if (k == wots_k) { + memcpy( info->wots_sig + i * SPX_N, + buffer + wots_sign_index * wots_offset, SPX_N ); + } + + /* Check if we hit the top of the chain */ + if (k == SPX_WOTS_W - 1) { + break; + } + + /* Iterate one step on all 4 chains */ + for (j = 0; j < 2; j++) { + set_hash_addr(leaf_addr + j * 8, k); + } + thashx2(buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + 1, ctx, leaf_addr); + } + } + + /* Do the final thash to generate the public keys */ + thashx2(dest + 0 * SPX_N, + dest + 1 * SPX_N, + pk_buffer + 0 * wots_offset, + pk_buffer + 1 * wots_offset, + SPX_WOTS_LEN, ctx, pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/wots.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/wots.h new file mode 100644 index 0000000000..4e7692eeef --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/wots.h @@ -0,0 +1,25 @@ +#ifndef SPX_WOTS_H +#define SPX_WOTS_H + +#include + +#include "context.h" +#include "params.h" + +/** + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. + * + * Writes the computed public key to 'pk'. + */ +#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]); + +/* + * Compute the chain lengths needed for a given message hash + */ +#define chain_lengths SPX_NAMESPACE(chain_lengths) +void chain_lengths(unsigned int *lengths, const unsigned char *msg); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/wotsx2.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/wotsx2.h new file mode 100644 index 0000000000..b58bb61f84 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/wotsx2.h @@ -0,0 +1,40 @@ +#ifndef WOTSX2_H_ +#define WOTSX2_H_ + +#include "params.h" +#include + +/* + * This is here to provide an interface to the internal wots_gen_leafx2 + * routine. While this routine is not referenced in the package outside of + * wots.c, it is called from the stand-alone benchmark code to characterize + * the performance + */ +struct leaf_info_x2 { + unsigned char *wots_sig; + uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ + uint32_t *wots_steps; + uint32_t leaf_addr[2 * 8]; + uint32_t pk_addr[2 * 8]; +}; + +/* Macro to set the leaf_info to something 'benign', that is, it would */ +/* run with the same time as it does during the real signing process */ +/* Used only by the benchmark code */ +#define INITIALIZE_LEAF_INFO_X2(info, addr, step_buffer) { \ + (info).wots_sig = 0; \ + (info).wots_sign_leaf = ~0; \ + (info).wots_steps = step_buffer; \ + int i; \ + for (i=0; i<2; i++) { \ + memcpy( &(info).leaf_addr[8*i], addr, 32 ); \ + memcpy( &(info).pk_addr[8*i], addr, 32 ); \ + } \ + } + +#define wots_gen_leafx2 SPX_NAMESPACE(wots_gen_leafx2) +void wots_gen_leafx2(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info); + +#endif /* WOTSX2_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/LICENSE b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/LICENSE new file mode 100644 index 0000000000..670154e353 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/LICENSE @@ -0,0 +1,116 @@ +CC0 1.0 Universal + +Statement of Purpose + +The laws of most jurisdictions throughout the world automatically confer +exclusive Copyright and Related Rights (defined below) upon the creator and +subsequent owner(s) (each and all, an "owner") of an original work of +authorship and/or a database (each, a "Work"). + +Certain owners wish to permanently relinquish those rights to a Work for the +purpose of contributing to a commons of creative, cultural and scientific +works ("Commons") that the public can reliably and without fear of later +claims of infringement build upon, modify, incorporate in other works, reuse +and redistribute as freely as possible in any form whatsoever and for any +purposes, including without limitation commercial purposes. These owners may +contribute to the Commons to promote the ideal of a free culture and the +further production of creative, cultural and scientific works, or to gain +reputation or greater distribution for their Work in part through the use and +efforts of others. + +For these and/or other purposes and motivations, and without any expectation +of additional consideration or compensation, the person associating CC0 with a +Work (the "Affirmer"), to the extent that he or she is an owner of Copyright +and Related Rights in the Work, voluntarily elects to apply CC0 to the Work +and publicly distribute the Work under its terms, with knowledge of his or her +Copyright and Related Rights in the Work and the meaning and intended legal +effect of CC0 on those rights. + +1. Copyright and Related Rights. A Work made available under CC0 may be +protected by copyright and related or neighboring rights ("Copyright and +Related Rights"). Copyright and Related Rights include, but are not limited +to, the following: + + i. the right to reproduce, adapt, distribute, perform, display, communicate, + and translate a Work; + + ii. moral rights retained by the original author(s) and/or performer(s); + + iii. publicity and privacy rights pertaining to a person's image or likeness + depicted in a Work; + + iv. rights protecting against unfair competition in regards to a Work, + subject to the limitations in paragraph 4(a), below; + + v. rights protecting the extraction, dissemination, use and reuse of data in + a Work; + + vi. database rights (such as those arising under Directive 96/9/EC of the + European Parliament and of the Council of 11 March 1996 on the legal + protection of databases, and under any national implementation thereof, + including any amended or successor version of such directive); and + + vii. other similar, equivalent or corresponding rights throughout the world + based on applicable law or treaty, and any national implementations thereof. + +2. Waiver. To the greatest extent permitted by, but not in contravention of, +applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and +unconditionally waives, abandons, and surrenders all of Affirmer's Copyright +and Related Rights and associated claims and causes of action, whether now +known or unknown (including existing as well as future claims and causes of +action), in the Work (i) in all territories worldwide, (ii) for the maximum +duration provided by applicable law or treaty (including future time +extensions), (iii) in any current or future medium and for any number of +copies, and (iv) for any purpose whatsoever, including without limitation +commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes +the Waiver for the benefit of each member of the public at large and to the +detriment of Affirmer's heirs and successors, fully intending that such Waiver +shall not be subject to revocation, rescission, cancellation, termination, or +any other legal or equitable action to disrupt the quiet enjoyment of the Work +by the public as contemplated by Affirmer's express Statement of Purpose. + +3. Public License Fallback. Should any part of the Waiver for any reason be +judged legally invalid or ineffective under applicable law, then the Waiver +shall be preserved to the maximum extent permitted taking into account +Affirmer's express Statement of Purpose. In addition, to the extent the Waiver +is so judged Affirmer hereby grants to each affected person a royalty-free, +non transferable, non sublicensable, non exclusive, irrevocable and +unconditional license to exercise Affirmer's Copyright and Related Rights in +the Work (i) in all territories worldwide, (ii) for the maximum duration +provided by applicable law or treaty (including future time extensions), (iii) +in any current or future medium and for any number of copies, and (iv) for any +purpose whatsoever, including without limitation commercial, advertising or +promotional purposes (the "License"). The License shall be deemed effective as +of the date CC0 was applied by Affirmer to the Work. Should any part of the +License for any reason be judged legally invalid or ineffective under +applicable law, such partial invalidity or ineffectiveness shall not +invalidate the remainder of the License, and in such case Affirmer hereby +affirms that he or she will not (i) exercise any of his or her remaining +Copyright and Related Rights in the Work or (ii) assert any associated claims +and causes of action with respect to the Work, in either case contrary to +Affirmer's express Statement of Purpose. + +4. Limitations and Disclaimers. + + a. No trademark or patent rights held by Affirmer are waived, abandoned, + surrendered, licensed or otherwise affected by this document. + + b. Affirmer offers the Work as-is and makes no representations or warranties + of any kind concerning the Work, express, implied, statutory or otherwise, + including without limitation warranties of title, merchantability, fitness + for a particular purpose, non infringement, or the absence of latent or + other defects, accuracy, or the present or absence of errors, whether or not + discoverable, all to the greatest extent permissible under applicable law. + + c. Affirmer disclaims responsibility for clearing rights of other persons + that may apply to the Work or any use thereof, including without limitation + any person's Copyright and Related Rights in the Work. Further, Affirmer + disclaims responsibility for obtaining any necessary consents, permissions + or other rights required for any use of the Work. + + d. Affirmer understands and acknowledges that Creative Commons is not a + party to this document and has no duty or obligation with respect to this + CC0 or use of the Work. + +For more information, please see + diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/address.c b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/address.c new file mode 100644 index 0000000000..d49d9f3b6b --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/address.c @@ -0,0 +1,95 @@ +#include +#include + +#include "address.h" +#include "params.h" +#include "utils.h" + +/* + * Specify which level of Merkle tree (the "layer") we're working on + */ +void set_layer_addr(uint32_t addr[8], uint32_t layer) { + ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; +} + +/* + * Specify which Merkle tree within the level (the "tree address") we're working on + */ +void set_tree_addr(uint32_t addr[8], uint64_t tree) { + ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); +} + +/* + * Specify the reason we'll use this address structure for, that is, what + * hash will we compute with it. This is used so that unrelated types of + * hashes don't accidentally get the same address structure. The type will be + * one of the SPX_ADDR_TYPE constants + */ +void set_type(uint32_t addr[8], uint32_t type) { + ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; +} + +/* + * Copy the layer and tree fields of the address structure. This is used + * when we're doing multiple types of hashes within the same Merkle tree + */ +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); +} + +/* These functions are used for OTS addresses. */ + +/* + * Specify which Merkle leaf we're working on; that is, which OTS keypair + * we're talking about. + */ +void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { + /* We have > 256 OTS at the bottom of the Merkle tree; to specify */ + /* which one, we'd need to express it in two bytes */ + ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR2] = (unsigned char)(keypair >> 8); + ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; +} + +/* + * Copy the layer, tree and keypair fields of the address structure. This is + * used when we're doing multiple things within the same OTS keypair + */ +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); + ((unsigned char *)out)[SPX_OFFSET_KP_ADDR2] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR2]; + ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; +} + +/* + * Specify which Merkle chain within the OTS we're working with + * (the chain address) + */ +void set_chain_addr(uint32_t addr[8], uint32_t chain) { + ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; +} + +/* + * Specify where in the Merkle chain we are +* (the hash address) + */ +void set_hash_addr(uint32_t addr[8], uint32_t hash) { + ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; +} + +/* These functions are used for all hash tree addresses (including FORS). */ + +/* + * Specify the height of the node in the Merkle/FORS tree we are in + * (the tree height) + */ +void set_tree_height(uint32_t addr[8], uint32_t tree_height) { + ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; +} + +/* + * Specify the distance from the left edge of the node in the Merkle/FORS tree + * (the tree index) + */ +void set_tree_index(uint32_t addr[8], uint32_t tree_index) { + u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/address.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/address.h new file mode 100644 index 0000000000..24a84eb40c --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/address.h @@ -0,0 +1,52 @@ +#ifndef SPX_ADDRESS_H +#define SPX_ADDRESS_H + +#include + +#include "params.h" + +/* The hash types that are passed to set_type */ +#define SPX_ADDR_TYPE_WOTS 0 +#define SPX_ADDR_TYPE_WOTSPK 1 +#define SPX_ADDR_TYPE_HASHTREE 2 +#define SPX_ADDR_TYPE_FORSTREE 3 +#define SPX_ADDR_TYPE_FORSPK 4 +#define SPX_ADDR_TYPE_WOTSPRF 5 +#define SPX_ADDR_TYPE_FORSPRF 6 + +#define set_layer_addr SPX_NAMESPACE(set_layer_addr) +void set_layer_addr(uint32_t addr[8], uint32_t layer); + +#define set_tree_addr SPX_NAMESPACE(set_tree_addr) +void set_tree_addr(uint32_t addr[8], uint64_t tree); + +#define set_type SPX_NAMESPACE(set_type) +void set_type(uint32_t addr[8], uint32_t type); + +/* Copies the layer and tree part of one address into the other */ +#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); + +/* These functions are used for WOTS and FORS addresses. */ + +#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) +void set_keypair_addr(uint32_t addr[8], uint32_t keypair); + +#define set_chain_addr SPX_NAMESPACE(set_chain_addr) +void set_chain_addr(uint32_t addr[8], uint32_t chain); + +#define set_hash_addr SPX_NAMESPACE(set_hash_addr) +void set_hash_addr(uint32_t addr[8], uint32_t hash); + +#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); + +/* These functions are used for all hash tree addresses (including FORS). */ + +#define set_tree_height SPX_NAMESPACE(set_tree_height) +void set_tree_height(uint32_t addr[8], uint32_t tree_height); + +#define set_tree_index SPX_NAMESPACE(set_tree_index) +void set_tree_index(uint32_t addr[8], uint32_t tree_index); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/api.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/api.h new file mode 100644 index 0000000000..192201f167 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/api.h @@ -0,0 +1,77 @@ +#ifndef PQCLEAN_SPHINCSSHAKE192SROBUST_AVX2_API_H +#define PQCLEAN_SPHINCSSHAKE192SROBUST_AVX2_API_H + +#include +#include + +#define PQCLEAN_SPHINCSSHAKE192SROBUST_AVX2_CRYPTO_ALGNAME "SPHINCS+-shake-192s-robust" + +#define PQCLEAN_SPHINCSSHAKE192SROBUST_AVX2_CRYPTO_SECRETKEYBYTES 96 +#define PQCLEAN_SPHINCSSHAKE192SROBUST_AVX2_CRYPTO_PUBLICKEYBYTES 48 +#define PQCLEAN_SPHINCSSHAKE192SROBUST_AVX2_CRYPTO_BYTES 16224 + +#define PQCLEAN_SPHINCSSHAKE192SROBUST_AVX2_CRYPTO_SEEDBYTES 72 + +/* + * Returns the length of a secret key, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE192SROBUST_AVX2_crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE192SROBUST_AVX2_crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE192SROBUST_AVX2_crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE192SROBUST_AVX2_crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +int PQCLEAN_SPHINCSSHAKE192SROBUST_AVX2_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +int PQCLEAN_SPHINCSSHAKE192SROBUST_AVX2_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +int PQCLEAN_SPHINCSSHAKE192SROBUST_AVX2_crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +int PQCLEAN_SPHINCSSHAKE192SROBUST_AVX2_crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, + const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +int PQCLEAN_SPHINCSSHAKE192SROBUST_AVX2_crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +int PQCLEAN_SPHINCSSHAKE192SROBUST_AVX2_crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/context.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/context.h new file mode 100644 index 0000000000..6e0a33f3b7 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/context.h @@ -0,0 +1,19 @@ +#ifndef SPX_CONTEXT_H +#define SPX_CONTEXT_H + +#include + +#include "params.h" + +typedef struct { + uint8_t pub_seed[SPX_N]; + uint8_t sk_seed[SPX_N]; +} spx_ctx; + +#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) +void initialize_hash_function(spx_ctx *ctx); + +#define free_hash_function SPX_NAMESPACE(free_hash_function) +void free_hash_function(spx_ctx *ctx); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/context_shake.c b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/context_shake.c new file mode 100644 index 0000000000..9614a103d3 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/context_shake.c @@ -0,0 +1,12 @@ +#include "context.h" + +/* For SHAKE256, there is no immediate reason to initialize at the start, + so this function is an empty operation. */ +void initialize_hash_function(spx_ctx *ctx) { + (void)ctx; /* Suppress an 'unused parameter' warning. */ +} + +// in case the hash function api is heap-based. +void free_hash_function(spx_ctx *ctx) { + (void)ctx; +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/fips202x4.c b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/fips202x4.c new file mode 100644 index 0000000000..1e06fef186 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/fips202x4.c @@ -0,0 +1,210 @@ +#include +#include +#include + +#include "fips202.h" +#include "fips202x4.h" + +#define NROUNDS 24 +#define ROL(a, offset) (((a) << (offset)) ^ ((a) >> (64-(offset)))) + +static uint64_t load64(const unsigned char *x) { + unsigned long long r = 0, i; + + for (i = 0; i < 8; ++i) { + r |= (unsigned long long)x[i] << 8 * i; + } + return r; +} + +static void store64(uint8_t *x, uint64_t u) { + unsigned int i; + + for (i = 0; i < 8; ++i) { + x[i] = (uint8_t)u; + u >>= 8; + } +} + +/* Use implementation from the Keccak Code Package */ +extern void KeccakP1600times4_PermuteAll_24rounds(__m256i *s); +#define KeccakF1600_StatePermute4x KeccakP1600times4_PermuteAll_24rounds + +static void keccak_absorb4x(__m256i *s, + unsigned int r, + const unsigned char *m0, + const unsigned char *m1, + const unsigned char *m2, + const unsigned char *m3, + unsigned long long int mlen, + unsigned char p) { + unsigned long long i; + unsigned char t0[200]; + unsigned char t1[200]; + unsigned char t2[200]; + unsigned char t3[200]; + + unsigned long long *ss = (unsigned long long *)s; + + + while (mlen >= r) { + for (i = 0; i < r / 8; ++i) { + ss[4 * i + 0] ^= load64(m0 + 8 * i); + ss[4 * i + 1] ^= load64(m1 + 8 * i); + ss[4 * i + 2] ^= load64(m2 + 8 * i); + ss[4 * i + 3] ^= load64(m3 + 8 * i); + } + + KeccakF1600_StatePermute4x(s); + mlen -= r; + m0 += r; + m1 += r; + m2 += r; + m3 += r; + } + + for (i = 0; i < r; ++i) { + t0[i] = 0; + t1[i] = 0; + t2[i] = 0; + t3[i] = 0; + } + for (i = 0; i < mlen; ++i) { + t0[i] = m0[i]; + t1[i] = m1[i]; + t2[i] = m2[i]; + t3[i] = m3[i]; + } + + t0[i] = p; + t1[i] = p; + t2[i] = p; + t3[i] = p; + + t0[r - 1] |= 128; + t1[r - 1] |= 128; + t2[r - 1] |= 128; + t3[r - 1] |= 128; + + for (i = 0; i < r / 8; ++i) { + ss[4 * i + 0] ^= load64(t0 + 8 * i); + ss[4 * i + 1] ^= load64(t1 + 8 * i); + ss[4 * i + 2] ^= load64(t2 + 8 * i); + ss[4 * i + 3] ^= load64(t3 + 8 * i); + } +} + + +static void keccak_squeezeblocks4x(unsigned char *h0, + unsigned char *h1, + unsigned char *h2, + unsigned char *h3, + unsigned long long int nblocks, + __m256i *s, + unsigned int r) { + unsigned int i; + + unsigned long long *ss = (unsigned long long *)s; + + while (nblocks > 0) { + KeccakF1600_StatePermute4x(s); + for (i = 0; i < (r >> 3); i++) { + store64(h0 + 8 * i, ss[4 * i + 0]); + store64(h1 + 8 * i, ss[4 * i + 1]); + store64(h2 + 8 * i, ss[4 * i + 2]); + store64(h3 + 8 * i, ss[4 * i + 3]); + } + h0 += r; + h1 += r; + h2 += r; + h3 += r; + nblocks--; + } +} + + + +void shake128x4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, unsigned long long outlen, + unsigned char *in0, + unsigned char *in1, + unsigned char *in2, + unsigned char *in3, unsigned long long inlen) { + __m256i s[25]; + unsigned char t0[SHAKE128_RATE]; + unsigned char t1[SHAKE128_RATE]; + unsigned char t2[SHAKE128_RATE]; + unsigned char t3[SHAKE128_RATE]; + unsigned int i; + + /* zero state */ + for (i = 0; i < 25; i++) { + s[i] = _mm256_xor_si256(s[i], s[i]); + } + + /* absorb 4 message of identical length in parallel */ + keccak_absorb4x(s, SHAKE128_RATE, in0, in1, in2, in3, inlen, 0x1F); + + /* Squeeze output */ + keccak_squeezeblocks4x(out0, out1, out2, out3, outlen / SHAKE128_RATE, s, SHAKE128_RATE); + + out0 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; + out1 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; + out2 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; + out3 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; + + if (outlen % SHAKE128_RATE) { + keccak_squeezeblocks4x(t0, t1, t2, t3, 1, s, SHAKE128_RATE); + for (i = 0; i < outlen % SHAKE128_RATE; i++) { + out0[i] = t0[i]; + out1[i] = t1[i]; + out2[i] = t2[i]; + out3[i] = t3[i]; + } + } +} + + +void shake256x4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, unsigned long long outlen, + unsigned char *in0, + unsigned char *in1, + unsigned char *in2, + unsigned char *in3, unsigned long long inlen) { + __m256i s[25]; + unsigned char t0[SHAKE256_RATE]; + unsigned char t1[SHAKE256_RATE]; + unsigned char t2[SHAKE256_RATE]; + unsigned char t3[SHAKE256_RATE]; + unsigned int i; + + /* zero state */ + for (i = 0; i < 25; i++) { + s[i] = _mm256_xor_si256(s[i], s[i]); + } + + /* absorb 4 message of identical length in parallel */ + keccak_absorb4x(s, SHAKE256_RATE, in0, in1, in2, in3, inlen, 0x1F); + + /* Squeeze output */ + keccak_squeezeblocks4x(out0, out1, out2, out3, outlen / SHAKE256_RATE, s, SHAKE256_RATE); + + out0 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; + out1 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; + out2 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; + out3 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; + + if (outlen % SHAKE256_RATE) { + keccak_squeezeblocks4x(t0, t1, t2, t3, 1, s, SHAKE256_RATE); + for (i = 0; i < outlen % SHAKE256_RATE; i++) { + out0[i] = t0[i]; + out1[i] = t1[i]; + out2[i] = t2[i]; + out3[i] = t3[i]; + } + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/fips202x4.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/fips202x4.h new file mode 100644 index 0000000000..2b93c9cd0d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/fips202x4.h @@ -0,0 +1,28 @@ +#ifndef SPX_FIPS202X4_H +#define SPX_FIPS202X4_H + +#include + +#include "params.h" + +#define shake128x4 SPX_NAMESPACE(shake128x4) +void shake128x4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, unsigned long long outlen, + unsigned char *in0, + unsigned char *in1, + unsigned char *in2, + unsigned char *in3, unsigned long long inlen); + +#define shake256x4 SPX_NAMESPACE(shake256x4) +void shake256x4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, unsigned long long outlen, + unsigned char *in0, + unsigned char *in1, + unsigned char *in2, + unsigned char *in3, unsigned long long inlen); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/fors.c b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/fors.c new file mode 100644 index 0000000000..f1b0639cfc --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/fors.c @@ -0,0 +1,202 @@ +#include +#include +#include + +#include "fors.h" + +#include "address.h" +#include "hash.h" +#include "hashx4.h" +#include "thash.h" +#include "thashx4.h" +#include "utils.h" +#include "utilsx4.h" + +static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + prf_addr(sk, ctx, fors_leaf_addr); +} + +static void fors_gen_skx4(unsigned char *sk0, + unsigned char *sk1, + unsigned char *sk2, + unsigned char *sk3, const spx_ctx *ctx, + uint32_t fors_leaf_addrx4[4 * 8]) { + prf_addrx4(sk0, sk1, sk2, sk3, + ctx, fors_leaf_addrx4); +} + +static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, + const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + thash(leaf, sk, 1, ctx, fors_leaf_addr); +} + +static void fors_sk_to_leafx4(unsigned char *leaf0, + unsigned char *leaf1, + unsigned char *leaf2, + unsigned char *leaf3, + const unsigned char *sk0, + const unsigned char *sk1, + const unsigned char *sk2, + const unsigned char *sk3, + const spx_ctx *ctx, + uint32_t fors_leaf_addrx4[4 * 8]) { + thashx4(leaf0, leaf1, leaf2, leaf3, + sk0, sk1, sk2, sk3, + 1, ctx, fors_leaf_addrx4); +} + +struct fors_gen_leaf_info { + uint32_t leaf_addrx[4 * 8]; +}; + +static void fors_gen_leafx4(unsigned char *leaf, + const spx_ctx *ctx, + uint32_t addr_idx, void *info) { + struct fors_gen_leaf_info *fors_info = info; + uint32_t *fors_leaf_addrx4 = fors_info->leaf_addrx; + unsigned int j; + + /* Only set the parts that the caller doesn't set */ + for (j = 0; j < 4; j++) { + set_tree_index(fors_leaf_addrx4 + j * 8, addr_idx + j); + set_type(fors_leaf_addrx4 + j * 8, SPX_ADDR_TYPE_FORSPRF); + } + + fors_gen_skx4(leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + leaf + 2 * SPX_N, + leaf + 3 * SPX_N, + ctx, fors_leaf_addrx4); + + for (j = 0; j < 4; j++) { + set_type(fors_leaf_addrx4 + j * 8, SPX_ADDR_TYPE_FORSTREE); + } + + fors_sk_to_leafx4(leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + leaf + 2 * SPX_N, + leaf + 3 * SPX_N, + leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + leaf + 2 * SPX_N, + leaf + 3 * SPX_N, + ctx, fors_leaf_addrx4); +} + +/** + * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + * Assumes indices has space for SPX_FORS_TREES integers. + */ +static void message_to_indices(uint32_t *indices, const unsigned char *m) { + unsigned int i, j; + unsigned int offset = 0; + + for (i = 0; i < SPX_FORS_TREES; i++) { + indices[i] = 0; + for (j = 0; j < SPX_FORS_HEIGHT; j++) { + indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); + offset++; + } + } +} + +/** + * Signs a message m, deriving the secret key from sk_seed and the FTS address. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + uint32_t fors_tree_addr[4 * 8] = {0}; + struct fors_gen_leaf_info fors_info = {0}; + uint32_t *fors_leaf_addr = fors_info.leaf_addrx; + uint32_t fors_pk_addr[8] = {0}; + uint32_t idx_offset; + unsigned int i; + + for (i = 0; i < 4; i++) { + copy_keypair_addr(fors_tree_addr + 8 * i, fors_addr); + set_type(fors_tree_addr + 8 * i, SPX_ADDR_TYPE_FORSTREE); + copy_keypair_addr(fors_leaf_addr + 8 * i, fors_addr); + } + copy_keypair_addr(fors_pk_addr, fors_addr); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); + + message_to_indices(indices, m); + + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); + + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + + /* Include the secret key part that produces the selected leaf node. */ + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); + fors_gen_sk(sig, ctx, fors_tree_addr); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + sig += SPX_N; + + /* Compute the authentication path for this leaf node. */ + treehashx4(roots + i * SPX_N, sig, ctx, + indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx4, + fors_tree_addr, &fors_info); + + sig += SPX_N * SPX_FORS_HEIGHT; + } + + /* Hash horizontally across all tree roots to derive the public key. */ + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); +} + +/** + * Derives the FORS public key from a signature. + * This can be used for verification by comparing to a known public key, or to + * subsequently verify a signature on the derived public key. The latter is the + * typical use-case when used as an FTS below an OTS in a hypertree. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + unsigned char leaf[SPX_N]; + uint32_t fors_tree_addr[8] = {0}; + uint32_t fors_pk_addr[8] = {0}; + uint32_t idx_offset; + unsigned int i; + + copy_keypair_addr(fors_tree_addr, fors_addr); + copy_keypair_addr(fors_pk_addr, fors_addr); + + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); + + message_to_indices(indices, m); + + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); + + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + + /* Derive the leaf from the included secret key part. */ + fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); + sig += SPX_N; + + /* Derive the corresponding root node of this tree. */ + compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, + sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); + sig += SPX_N * SPX_FORS_HEIGHT; + } + + /* Hash horizontally across all tree roots to derive the public key. */ + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/fors.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/fors.h new file mode 100644 index 0000000000..509140a178 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/fors.h @@ -0,0 +1,32 @@ +#ifndef SPX_FORS_H +#define SPX_FORS_H + +#include + +#include "context.h" +#include "params.h" + +/** + * Signs a message m, deriving the secret key from sk_seed and the FTS address. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +#define fors_sign SPX_NAMESPACE(fors_sign) +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); + +/** + * Derives the FORS public key from a signature. + * This can be used for verification by comparing to a known public key, or to + * subsequently verify a signature on the derived public key. The latter is the + * typical use-case when used as an FTS below an OTS in a hypertree. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/hash.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/hash.h new file mode 100644 index 0000000000..f7c87d4c3c --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/hash.h @@ -0,0 +1,28 @@ +#ifndef SPX_HASH_H +#define SPX_HASH_H + +#include +#include + +#include "context.h" +#include "params.h" + +#define prf_addr SPX_NAMESPACE(prf_addr) +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]); + +#define gen_message_random SPX_NAMESPACE(gen_message_random) +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); + +#define hash_message SPX_NAMESPACE(hash_message) +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); + + + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/hash_shake.c b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/hash_shake.c new file mode 100644 index 0000000000..ff5e7ec918 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/hash_shake.c @@ -0,0 +1,83 @@ +#include +#include + +#include "hash.h" + +#include "address.h" +#include "fips202.h" +#include "params.h" +#include "utils.h" + +/* + * Computes PRF(pk_seed, sk_seed, addr) + */ +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]) { + unsigned char buf[2 * SPX_N + SPX_ADDR_BYTES]; + + memcpy(buf, ctx->pub_seed, SPX_N); + memcpy(buf + SPX_N, addr, SPX_ADDR_BYTES); + memcpy(buf + SPX_N + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); + + shake256(out, SPX_N, buf, 2 * SPX_N + SPX_ADDR_BYTES); +} + +/** + * Computes the message-dependent randomness R, using a secret seed and an + * optional randomization value as well as the message. + */ +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { + (void)ctx; + shake256incctx s_inc; + + shake256_inc_init(&s_inc); + shake256_inc_absorb(&s_inc, sk_prf, SPX_N); + shake256_inc_absorb(&s_inc, optrand, SPX_N); + shake256_inc_absorb(&s_inc, m, mlen); + shake256_inc_finalize(&s_inc); + shake256_inc_squeeze(R, SPX_N, &s_inc); + shake256_inc_ctx_release(&s_inc); +} + +/** + * Computes the message hash using R, the public key, and the message. + * Outputs the message digest and the index of the leaf. The index is split in + * the tree index and the leaf index, for convenient copying to an address. + */ +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { + (void)ctx; +#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) +#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) +#define SPX_LEAF_BITS SPX_TREE_HEIGHT +#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) +#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) + + unsigned char buf[SPX_DGST_BYTES]; + unsigned char *bufp = buf; + shake256incctx s_inc; + + shake256_inc_init(&s_inc); + shake256_inc_absorb(&s_inc, R, SPX_N); + shake256_inc_absorb(&s_inc, pk, SPX_PK_BYTES); + shake256_inc_absorb(&s_inc, m, mlen); + shake256_inc_finalize(&s_inc); + shake256_inc_squeeze(buf, SPX_DGST_BYTES, &s_inc); + shake256_inc_ctx_release(&s_inc); + + memcpy(digest, bufp, SPX_FORS_MSG_BYTES); + bufp += SPX_FORS_MSG_BYTES; + + + *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); + *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); + bufp += SPX_TREE_BYTES; + + *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); + *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/hash_shakex4.c b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/hash_shakex4.c new file mode 100644 index 0000000000..bbd22eb117 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/hash_shakex4.c @@ -0,0 +1,64 @@ +#include +#include + +#include "hashx4.h" + +#include "address.h" +#include "fips202x4.h" +#include "params.h" + +extern void KeccakP1600times4_PermuteAll_24rounds(__m256i *s); + +/* + * 4-way parallel version of prf_addr; takes 4x as much input and output + */ +void prf_addrx4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const spx_ctx *ctx, + const uint32_t addrx4[4 * 8]) { + /* As we write and read only a few quadwords, it is more efficient to + * build and extract from the fourway SHAKE256 state by hand. */ + __m256i state[25]; + + for (int i = 0; i < SPX_N / 8; i++) { + state[i] = _mm256_set1_epi64x(((int64_t *)ctx->pub_seed)[i]); + } + for (int i = 0; i < 4; i++) { + state[SPX_N / 8 + i] = _mm256_set_epi32( + (int)addrx4[3 * 8 + 1 + 2 * i], + (int)addrx4[3 * 8 + 2 * i], + (int)addrx4[2 * 8 + 1 + 2 * i], + (int)addrx4[2 * 8 + 2 * i], + (int)addrx4[8 + 1 + 2 * i], + (int)addrx4[8 + 2 * i], + (int)addrx4[1 + 2 * i], + (int)addrx4[2 * i] + ); + } + for (int i = 0; i < SPX_N / 8; i++) { + state[SPX_N / 8 + i + 4] = _mm256_set1_epi64x(((int64_t *)ctx->sk_seed)[i]); + } + + /* SHAKE domain separator and padding. */ + state[SPX_N / 4 + 4] = _mm256_set1_epi64x(0x1f); + for (int i = SPX_N / 4 + 5; i < 16; i++) { + state[i] = _mm256_set1_epi64x(0); + } + // shift unsigned and then cast to avoid UB + state[16] = _mm256_set1_epi64x((long long)(0x80ULL << 56)); + + for (int i = 17; i < 25; i++) { + state[i] = _mm256_set1_epi64x(0); + } + + KeccakP1600times4_PermuteAll_24rounds(&state[0]); + + for (int i = 0; i < SPX_N / 8; i++) { + ((int64_t *)out0)[i] = _mm256_extract_epi64(state[i], 0); + ((int64_t *)out1)[i] = _mm256_extract_epi64(state[i], 1); + ((int64_t *)out2)[i] = _mm256_extract_epi64(state[i], 2); + ((int64_t *)out3)[i] = _mm256_extract_epi64(state[i], 3); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/hashx4.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/hashx4.h new file mode 100644 index 0000000000..3751a0ebd0 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/hashx4.h @@ -0,0 +1,17 @@ +#ifndef SPX_HASHX4_H +#define SPX_HASHX4_H + +#include + +#include "context.h" +#include "params.h" + +#define prf_addrx4 SPX_NAMESPACE(prf_addrx4) +void prf_addrx4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const spx_ctx *ctx, + const uint32_t addrx4[4 * 8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/merkle.c b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/merkle.c new file mode 100644 index 0000000000..f57811c1ac --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/merkle.c @@ -0,0 +1,64 @@ +#include +#include + +#include "merkle.h" + +#include "address.h" +#include "params.h" +#include "utils.h" +#include "utilsx4.h" +#include "wots.h" +#include "wotsx4.h" + +/* + * This generates a Merkle signature (WOTS signature followed by the Merkle + * authentication path). + */ +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf) { + unsigned char *auth_path = sig + SPX_WOTS_BYTES; + uint32_t tree_addrx4[4 * 8] = { 0 }; + int j; + struct leaf_info_x4 info = { 0 }; + unsigned steps[ SPX_WOTS_LEN ]; + + info.wots_sig = sig; + chain_lengths(steps, root); + info.wots_steps = steps; + + for (j = 0; j < 4; j++) { + set_type(&tree_addrx4[8 * j], SPX_ADDR_TYPE_HASHTREE); + set_type(&info.leaf_addr[8 * j], SPX_ADDR_TYPE_WOTS); + set_type(&info.pk_addr[8 * j], SPX_ADDR_TYPE_WOTSPK); + copy_subtree_addr(&tree_addrx4[8 * j], tree_addr); + copy_subtree_addr(&info.leaf_addr[8 * j], wots_addr); + copy_subtree_addr(&info.pk_addr[8 * j], wots_addr); + } + + info.wots_sign_leaf = idx_leaf; + + treehashx4(root, auth_path, ctx, + idx_leaf, 0, + SPX_TREE_HEIGHT, + wots_gen_leafx4, + tree_addrx4, &info); +} + +/* Compute root node of the top-most subtree. */ +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { + /* We do not need the auth path in key generation, but it simplifies the + code to have just one treehash routine that computes both root and path + in one function. */ + unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; + uint32_t top_tree_addr[8] = {0}; + uint32_t wots_addr[8] = {0}; + + set_layer_addr(top_tree_addr, SPX_D - 1); + set_layer_addr(wots_addr, SPX_D - 1); + + merkle_sign(auth_path, root, ctx, + wots_addr, top_tree_addr, + ~0U /* ~0 means "don't bother generating an auth path */ ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/merkle.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/merkle.h new file mode 100644 index 0000000000..769cf2e970 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/merkle.h @@ -0,0 +1,21 @@ +#ifndef MERKLE_H_ +#define MERKLE_H_ + +#include + +#include "context.h" +#include "params.h" + +/* Generate a Merkle signature (WOTS signature followed by the Merkle */ +/* authentication path) */ +#define merkle_sign SPX_NAMESPACE(merkle_sign) +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf); + +/* Compute the root node of the top-most subtree. */ +#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); + +#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/nistapi.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/nistapi.h new file mode 100644 index 0000000000..3cb71afad4 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/nistapi.h @@ -0,0 +1,87 @@ +#ifndef SPX_API_H +#define SPX_API_H + +#include +#include + +#include "params.h" + +#define CRYPTO_ALGNAME "SPHINCS+" + +#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES +#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES +#define CRYPTO_BYTES SPX_BYTES +#define CRYPTO_SEEDBYTES (3*SPX_N) + +/* + * Returns the length of a secret key, in bytes + */ +#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) +size_t crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) +size_t crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) +size_t crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) +size_t crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +#define crypto_sign SPX_NAMESPACE(crypto_sign) +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/params.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/params.h new file mode 100644 index 0000000000..ae70c8358f --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/params.h @@ -0,0 +1,56 @@ +#ifndef SPX_PARAMS_H +#define SPX_PARAMS_H + +#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSSHAKE192SROBUST_AVX2_##s + +/* Hash output length in bytes. */ +#define SPX_N 24 +/* Height of the hypertree. */ +#define SPX_FULL_HEIGHT 63 +/* Number of subtree layer. */ +#define SPX_D 7 +/* FORS tree dimensions. */ +#define SPX_FORS_HEIGHT 14 +#define SPX_FORS_TREES 17 +/* Winternitz parameter, */ +#define SPX_WOTS_W 16 + +/* The hash function is defined by linking a different hash.c file, as opposed + to setting a #define constant. */ + +/* For clarity */ +#define SPX_ADDR_BYTES 32 + +/* WOTS parameters. */ +#define SPX_WOTS_LOGW 4 + +#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) + +/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ +#define SPX_WOTS_LEN2 3 + +#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) +#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) +#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES + +/* Subtree size. */ +#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) + +//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT +// #error SPX_D should always divide SPX_FULL_HEIGHT +//#endif + +/* FORS parameters. */ +#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) +#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) +#define SPX_FORS_PK_BYTES SPX_N + +/* Resulting SPX sizes. */ +#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ + SPX_FULL_HEIGHT * SPX_N) +#define SPX_PK_BYTES (2 * SPX_N) +#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) + +#include "shake_offsets.h" + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/shake_offsets.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/shake_offsets.h new file mode 100644 index 0000000000..6b28d95d91 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/shake_offsets.h @@ -0,0 +1,21 @@ +#ifndef SHAKE_OFFSETS_H_ +#define SHAKE_OFFSETS_H_ + +/* + * Offsets of various fields in the address structure when we use SHAKE as + * the Sphincs+ hash function + */ + +#define SPX_OFFSET_LAYER 3 /* The byte used to specify the Merkle tree layer */ +#define SPX_OFFSET_TREE 8 /* The start of the 8 byte field used to specify the tree */ +#define SPX_OFFSET_TYPE 19 /* The byte used to specify the hash type (reason) */ +#define SPX_OFFSET_KP_ADDR2 22 /* The high byte used to specify the key pair (which one-time signature) */ +#define SPX_OFFSET_KP_ADDR1 23 /* The low byte used to specify the key pair */ +#define SPX_OFFSET_CHAIN_ADDR 27 /* The byte used to specify the chain address (which Winternitz chain) */ +#define SPX_OFFSET_HASH_ADDR 31 /* The byte used to specify the hash address (where in the Winternitz chain) */ +#define SPX_OFFSET_TREE_HGT 27 /* The byte used to specify the height of this node in the FORS or Merkle tree */ +#define SPX_OFFSET_TREE_INDEX 28 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ + +#define SPX_SHAKE 1 + +#endif /* SHAKE_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/sign.c b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/sign.c new file mode 100644 index 0000000000..9d0c7d1b22 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/sign.c @@ -0,0 +1,286 @@ +#include +#include +#include + +#include "address.h" +#include "context.h" +#include "fors.h" +#include "hash.h" +#include "merkle.h" +#include "nistapi.h" +#include "params.h" +#include "randombytes.h" +#include "thash.h" +#include "utils.h" +#include "wots.h" + +/* + * Returns the length of a secret key, in bytes + */ +size_t crypto_sign_secretkeybytes(void) { + return CRYPTO_SECRETKEYBYTES; +} + +/* + * Returns the length of a public key, in bytes + */ +size_t crypto_sign_publickeybytes(void) { + return CRYPTO_PUBLICKEYBYTES; +} + +/* + * Returns the length of a signature, in bytes + */ +size_t crypto_sign_bytes(void) { + return CRYPTO_BYTES; +} + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +size_t crypto_sign_seedbytes(void) { + return CRYPTO_SEEDBYTES; +} + +/* + * Generates an SPX key pair given a seed of length + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [PUB_SEED || root] + */ +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed) { + spx_ctx ctx; + + /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ + memcpy(sk, seed, CRYPTO_SEEDBYTES); + + memcpy(pk, sk + 2 * SPX_N, SPX_N); + + memcpy(ctx.pub_seed, pk, SPX_N); + memcpy(ctx.sk_seed, sk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + /* Compute root node of the top-most subtree. */ + merkle_gen_root(sk + 3 * SPX_N, &ctx); + + // cleanup + free_hash_function(&ctx); + + memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); + + return 0; +} + +/* + * Generates an SPX key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [PUB_SEED || root] + */ +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { + uint8_t seed[CRYPTO_SEEDBYTES]; + randombytes(seed, CRYPTO_SEEDBYTES); + crypto_sign_seed_keypair(pk, sk, seed); + + return 0; +} + +/** + * Returns an array containing a detached signature. + */ +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk) { + spx_ctx ctx; + + const uint8_t *sk_prf = sk + SPX_N; + const uint8_t *pk = sk + 2 * SPX_N; + + uint8_t optrand[SPX_N]; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t root[SPX_N]; + uint32_t i; + uint64_t tree; + uint32_t idx_leaf; + uint32_t wots_addr[8] = {0}; + uint32_t tree_addr[8] = {0}; + + memcpy(ctx.sk_seed, sk, SPX_N); + memcpy(ctx.pub_seed, pk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + + /* Optionally, signing can be made non-deterministic using optrand. + This can help counter side-channel attacks that would benefit from + getting a large number of traces when the signer uses the same nodes. */ + randombytes(optrand, SPX_N); + /* Compute the digest randomization value. */ + gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); + + /* Derive the message digest and leaf index from R, PK and M. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; + + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); + + /* Sign the message hash using FORS. */ + fors_sign(sig, root, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); + sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; + + /* Update the indices for the next layer. */ + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; + } + + free_hash_function(&ctx); + + *siglen = SPX_BYTES; + + return 0; +} + +/** + * Verifies a detached signature and message under a given public key. + */ +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk) { + spx_ctx ctx; + const uint8_t *pub_root = pk + SPX_N; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t wots_pk[SPX_WOTS_BYTES]; + uint8_t root[SPX_N]; + uint8_t leaf[SPX_N]; + unsigned int i; + uint64_t tree; + uint32_t idx_leaf; + uint32_t wots_addr[8] = {0}; + uint32_t tree_addr[8] = {0}; + uint32_t wots_pk_addr[8] = {0}; + + if (siglen != SPX_BYTES) { + return -1; + } + + memcpy(ctx.pub_seed, pk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); + + /* Derive the message digest and leaf index from R || PK || M. */ + /* The additional SPX_N is a result of the hash domain separator. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; + + /* Layer correctly defaults to 0, so no need to set_layer_addr */ + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); + + fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + /* For each subtree.. */ + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + copy_keypair_addr(wots_pk_addr, wots_addr); + + /* The WOTS public key is only correct if the signature was correct. */ + /* Initially, root is the FORS pk, but on subsequent iterations it is + the root of the subtree below the currently processed subtree. */ + wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); + sig += SPX_WOTS_BYTES; + + /* Compute the leaf node using the WOTS public key. */ + thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); + + /* Compute the root node of this subtree. */ + compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, + &ctx, tree_addr); + sig += SPX_TREE_HEIGHT * SPX_N; + + /* Update the indices for the next layer. */ + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; + } + + // cleanup + free_hash_function(&ctx); + + /* Check if the root node equals the root node in the public key. */ + if (memcmp(root, pub_root, SPX_N) != 0) { + return -1; + } + + return 0; +} + + +/** + * Returns an array containing the signature followed by the message. + */ +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk) { + size_t siglen; + + crypto_sign_signature(sm, &siglen, m, mlen, sk); + + memmove(sm + SPX_BYTES, m, mlen); + *smlen = siglen + mlen; + + return 0; +} + +/** + * Verifies a given signature-message pair under a given public key. + */ +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk) { + /* The API caller does not necessarily know what size a signature should be + but SPHINCS+ signatures are always exactly SPX_BYTES. */ + if (smlen < SPX_BYTES) { + memset(m, 0, smlen); + *mlen = 0; + return -1; + } + + *mlen = smlen - SPX_BYTES; + + if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { + memset(m, 0, smlen); + *mlen = 0; + return -1; + } + + /* If verification was successful, move the message to the right place. */ + memmove(m, sm + SPX_BYTES, *mlen); + + return 0; +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/thash.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/thash.h new file mode 100644 index 0000000000..8687ccfb4d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/thash.h @@ -0,0 +1,13 @@ +#ifndef SPX_THASH_H +#define SPX_THASH_H + +#include "context.h" +#include "params.h" + +#include + +#define thash SPX_NAMESPACE(thash) +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/thash_shake_robust.c b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/thash_shake_robust.c new file mode 100644 index 0000000000..696d53c5cc --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/thash_shake_robust.c @@ -0,0 +1,31 @@ +#include +#include + +#include "thash.h" + +#include "address.h" +#include "params.h" +#include "utils.h" + +#include "fips202.h" + +/** + * Takes an array of inblocks concatenated arrays of SPX_N bytes. + */ +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]) { + PQCLEAN_VLA(uint8_t, buf, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); + PQCLEAN_VLA(uint8_t, bitmask, inblocks * SPX_N); + unsigned int i; + + memcpy(buf, ctx->pub_seed, SPX_N); + memcpy(buf + SPX_N, addr, SPX_ADDR_BYTES); + + shake256(bitmask, inblocks * SPX_N, buf, SPX_N + SPX_ADDR_BYTES); + + for (i = 0; i < inblocks * SPX_N; i++) { + buf[SPX_N + SPX_ADDR_BYTES + i] = in[i] ^ bitmask[i]; + } + + shake256(out, SPX_N, buf, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/thash_shake_robustx4.c b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/thash_shake_robustx4.c new file mode 100644 index 0000000000..ce2946b745 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/thash_shake_robustx4.c @@ -0,0 +1,131 @@ +#include +#include + +#include "thashx4.h" + +#include "address.h" +#include "params.h" +#include "utils.h" + +#include "fips202x4.h" + +extern void KeccakP1600times4_PermuteAll_24rounds(__m256i *s); + +/** + * 4-way parallel version of thash; takes 4x as much input and output + */ +void thashx4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addrx4[4 * 8]) { + if (inblocks == 1 || inblocks == 2) { + /* As we write and read only a few quadwords, it is more efficient to + * build and extract from the fourway SHAKE256 state by hand. */ + __m256i state[25]; + for (int i = 0; i < SPX_N / 8; i++) { + state[i] = _mm256_set1_epi64x(((int64_t *)ctx->pub_seed)[i]); + } + for (int i = 0; i < 4; i++) { + state[SPX_N / 8 + i] = _mm256_set_epi32( + (int)addrx4[3 * 8 + 1 + 2 * i], + (int)addrx4[3 * 8 + 2 * i], + (int)addrx4[2 * 8 + 1 + 2 * i], + (int)addrx4[2 * 8 + 2 * i], + (int)addrx4[8 + 1 + 2 * i], + (int)addrx4[8 + 2 * i], + (int)addrx4[1 + 2 * i], + (int)addrx4[2 * i] + ); + } + + /* SHAKE domain separator and padding */ + state[SPX_N / 8 + 4] = _mm256_set1_epi64x(0x1f); + for (int i = SPX_N / 8 + 5; i < 16; i++) { + state[i] = _mm256_set1_epi64x(0); + } + state[16] = _mm256_set1_epi64x((long long)(0x80ULL << 56)); + + for (int i = 17; i < 25; i++) { + state[i] = _mm256_set1_epi64x(0); + } + + /* We will permutate state2 with f1600x4 to compute the bitmask, + * but first we'll copy it to state2 which will be used to compute + * the final output, as its input is alsmost identical. */ + __m256i state2[25]; + memcpy(state2, state, 800); + + KeccakP1600times4_PermuteAll_24rounds(&state[0]); + + /* By copying from state, state2 already contains the pub_seed + * and addres. We just need to copy in the input blocks xorred with + * the bitmask we just computed. */ + for (unsigned int i = 0; i < (SPX_N / 8) * inblocks; i++) { + state2[SPX_N / 8 + 4 + i] = _mm256_xor_si256( + state[i], + _mm256_set_epi64x( + ((int64_t *)in3)[i], + ((int64_t *)in2)[i], + ((int64_t *)in1)[i], + ((int64_t *)in0)[i] + ) + ); + } + + /* Domain separator and start of padding. Note that the quadwords + * around are already zeroed for state from which we copied. + * We do a XOR instead of a set as this might be the 16th quadword + * when N=32 and inblocks=2, which already contains the end + * of the padding. */ + state2[(SPX_N / 8) * (1 + inblocks) + 4] = _mm256_xor_si256( + state2[(SPX_N / 8) * (1 + inblocks) + 4], + _mm256_set1_epi64x(0x1f) + ); + + KeccakP1600times4_PermuteAll_24rounds(&state2[0]); + + for (int i = 0; i < SPX_N / 8; i++) { + ((int64_t *)out0)[i] = _mm256_extract_epi64(state2[i], 0); + ((int64_t *)out1)[i] = _mm256_extract_epi64(state2[i], 1); + ((int64_t *)out2)[i] = _mm256_extract_epi64(state2[i], 2); + ((int64_t *)out3)[i] = _mm256_extract_epi64(state2[i], 3); + } + } else { + PQCLEAN_VLA(unsigned char, buf0, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, buf1, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, buf2, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, buf3, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, bitmask0, inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, bitmask1, inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, bitmask2, inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, bitmask3, inblocks * SPX_N); + unsigned int i; + + memcpy(buf0, ctx->pub_seed, SPX_N); + memcpy(buf1, ctx->pub_seed, SPX_N); + memcpy(buf2, ctx->pub_seed, SPX_N); + memcpy(buf3, ctx->pub_seed, SPX_N); + memcpy(buf0 + SPX_N, addrx4 + 0 * 8, SPX_ADDR_BYTES); + memcpy(buf1 + SPX_N, addrx4 + 1 * 8, SPX_ADDR_BYTES); + memcpy(buf2 + SPX_N, addrx4 + 2 * 8, SPX_ADDR_BYTES); + memcpy(buf3 + SPX_N, addrx4 + 3 * 8, SPX_ADDR_BYTES); + + shake256x4(bitmask0, bitmask1, bitmask2, bitmask3, inblocks * SPX_N, + buf0, buf1, buf2, buf3, SPX_N + SPX_ADDR_BYTES); + + for (i = 0; i < inblocks * SPX_N; i++) { + buf0[SPX_N + SPX_ADDR_BYTES + i] = in0[i] ^ bitmask0[i]; + buf1[SPX_N + SPX_ADDR_BYTES + i] = in1[i] ^ bitmask1[i]; + buf2[SPX_N + SPX_ADDR_BYTES + i] = in2[i] ^ bitmask2[i]; + buf3[SPX_N + SPX_ADDR_BYTES + i] = in3[i] ^ bitmask3[i]; + } + + shake256x4(out0, out1, out2, out3, SPX_N, + buf0, buf1, buf2, buf3, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/thashx4.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/thashx4.h new file mode 100644 index 0000000000..64798a3727 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/thashx4.h @@ -0,0 +1,20 @@ +#ifndef SPX_THASHX4_H +#define SPX_THASHX4_H + +#include + +#include "context.h" +#include "params.h" + +#define thashx4 SPX_NAMESPACE(thashx4) +void thashx4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addrx4[4 * 8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/utils.c b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/utils.c new file mode 100644 index 0000000000..177b541fb9 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/utils.c @@ -0,0 +1,148 @@ +#include + +#include "utils.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "thash.h" + +/** + * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. + */ +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in) { + int i; + + /* Iterate over out in decreasing order, for big-endianness. */ + for (i = (signed int)outlen - 1; i >= 0; i--) { + out[i] = in & 0xff; + in = in >> 8; + } +} + +void u32_to_bytes(unsigned char *out, uint32_t in) { + out[0] = (unsigned char)(in >> 24); + out[1] = (unsigned char)(in >> 16); + out[2] = (unsigned char)(in >> 8); + out[3] = (unsigned char)in; +} + +/** + * Converts the inlen bytes in 'in' from big-endian byte order to an integer. + */ +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { + unsigned long long retval = 0; + unsigned int i; + + for (i = 0; i < inlen; i++) { + retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); + } + return retval; +} + +/** + * Computes a root node given a leaf and an auth path. + * Expects address to be complete other than the tree_height and tree_index. + */ +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]) { + uint32_t i; + unsigned char buffer[2 * SPX_N]; + + /* If leaf_idx is odd (last bit = 1), current path element is a right child + and auth_path has to go left. Otherwise it is the other way around. */ + if (leaf_idx & 1) { + memcpy(buffer + SPX_N, leaf, SPX_N); + memcpy(buffer, auth_path, SPX_N); + } else { + memcpy(buffer, leaf, SPX_N); + memcpy(buffer + SPX_N, auth_path, SPX_N); + } + auth_path += SPX_N; + + for (i = 0; i < tree_height - 1; i++) { + leaf_idx >>= 1; + idx_offset >>= 1; + /* Set the address of the node we're creating. */ + set_tree_height(addr, i + 1); + set_tree_index(addr, leaf_idx + idx_offset); + + /* Pick the right or left neighbor, depending on parity of the node. */ + if (leaf_idx & 1) { + thash(buffer + SPX_N, buffer, 2, ctx, addr); + memcpy(buffer, auth_path, SPX_N); + } else { + thash(buffer, buffer, 2, ctx, addr); + memcpy(buffer + SPX_N, auth_path, SPX_N); + } + auth_path += SPX_N; + } + + /* The last iteration is exceptional; we do not copy an auth_path node. */ + leaf_idx >>= 1; + idx_offset >>= 1; + set_tree_height(addr, tree_height); + set_tree_index(addr, leaf_idx + idx_offset); + thash(root, buffer, 2, ctx, addr); +} + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx * /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]) { + PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); + PQCLEAN_VLA(unsigned int, heights, tree_height + 1); + unsigned int offset = 0; + uint32_t idx; + uint32_t tree_idx; + + for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { + /* Add the next leaf node to the stack. */ + gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); + offset++; + heights[offset - 1] = 0; + + /* If this is a node we need for the auth path.. */ + if ((leaf_idx ^ 0x1) == idx) { + memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); + } + + /* While the top-most nodes are of equal height.. */ + while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { + /* Compute index of the new node, in the next layer. */ + tree_idx = (idx >> (heights[offset - 1] + 1)); + + /* Set the address of the node we're creating. */ + set_tree_height(tree_addr, heights[offset - 1] + 1); + set_tree_index(tree_addr, + tree_idx + (idx_offset >> (heights[offset - 1] + 1))); + /* Hash the top-most nodes from the stack together. */ + thash(stack + (offset - 2)*SPX_N, + stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); + offset--; + /* Note that the top-most node is now one layer higher. */ + heights[offset - 1]++; + + /* If this is a node we need for the auth path.. */ + if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { + memcpy(auth_path + heights[offset - 1]*SPX_N, + stack + (offset - 1)*SPX_N, SPX_N); + } + } + } + memcpy(root, stack, SPX_N); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/utils.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/utils.h new file mode 100644 index 0000000000..64f5d5a53a --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/utils.h @@ -0,0 +1,58 @@ +#ifndef SPX_UTILS_H +#define SPX_UTILS_H + +#include + +#include "compat.h" +#include "context.h" +#include "params.h" + + +/* To support MSVC use alloca() instead of VLAs. See #20. */ + + +/** + * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. + */ +#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in); +#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) +void u32_to_bytes(unsigned char *out, uint32_t in); + +/** + * Converts the inlen bytes in 'in' from big-endian byte order to an integer. + */ +#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); + +/** + * Computes a root node given a leaf and an auth path. + * Expects address to be complete other than the tree_height and tree_index. + */ +#define compute_root SPX_NAMESPACE(compute_root) +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]); + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +#define treehash SPX_NAMESPACE(treehash) +void treehash(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx *ctx /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]); + + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/utilsx4.c b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/utilsx4.c new file mode 100644 index 0000000000..1638677194 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/utilsx4.c @@ -0,0 +1,138 @@ +#include + +#include "utilsx4.h" + +#include "address.h" +#include "params.h" +#include "thashx4.h" +#include "utils.h" + +/* + * Generate the entire Merkle tree, computing the authentication path for leaf_idx, + * and the resulting root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) + * + * This expects tree_addrx4 to be initialized to 4 parallel addr structures for + * the Merkle tree nodes + * + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + * + * This works by using the standard Merkle tree building algorithm, except + * that each 'node' tracked is actually 4 consecutive nodes in the real tree. + * When we combine two logical nodes ABCD and WXYZ, we perform the H + * operation on adjacent real nodes, forming the parent logical node + * (AB)(CD)(WX)(YZ) + * + * When we get to the top two levels of the real tree (where there is only + * one logical node), we continue this operation two more times; the right + * most real node will by the actual root (and the other 3 nodes will be + * garbage). We follow the same thashx4 logic so that the 'extract + * authentication path components' part of the loop is still executed (and + * to simplify the code somewhat) + * + * This currently assumes tree_height >= 2; I suspect that doing an adjusting + * idx, addr_idx on the gen_leafx4 call if tree_height < 2 would fix it; since + * we don't actually use such short trees, I haven't bothered + */ +void treehashx4(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, + uint32_t tree_height, + void (*gen_leafx4)( + unsigned char * /* Where to write the leaves */, + const spx_ctx *, + uint32_t idx, void *info), + uint32_t tree_addrx4[4 * 8], + void *info) { + /* This is where we keep the intermediate nodes */ + PQCLEAN_VLA(unsigned char, stackx4, tree_height * 4 * SPX_N); + uint32_t left_adj = 0, prev_left_adj = 0; /* When we're doing the top 3 */ + /* levels, the left-most part of the tree isn't at the beginning */ + /* of current[]. These give the offset of the actual start */ + + uint32_t idx; + uint32_t max_idx = (1U << (tree_height - 2)) - 1; + for (idx = 0;; idx++) { + unsigned char current[4 * SPX_N]; /* Current logical node */ + gen_leafx4( current, ctx, 4 * idx + idx_offset, + info ); + + /* Now combine the freshly generated right node with previously */ + /* generated left ones */ + uint32_t internal_idx_offset = idx_offset; + uint32_t internal_idx = idx; + uint32_t internal_leaf = leaf_idx; + uint32_t h; /* The height we are in the Merkle tree */ + for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { + + /* Special processing if we're at the top of the tree */ + if (h >= tree_height - 2) { + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[3 * SPX_N], SPX_N ); + return; + } + /* The tree indexing logic is a bit off in this case */ + /* Adjust it so that the left-most node of the part of */ + /* the tree that we're processing has index 0 */ + prev_left_adj = left_adj; + left_adj = 4U - (1 << (tree_height - h - 1)); + } + + /* Check if we hit the top of the tree */ + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[3 * SPX_N], SPX_N ); + return; + } + + /* + * Check if one of the nodes we have is a part of the + * authentication path; if it is, write it out + */ + if ((((internal_idx << 2) ^ internal_leaf) & ~0x3U) == 0) { + memcpy( &auth_path[ h * SPX_N ], + ¤t[(((internal_leaf & 3) ^ 1) + prev_left_adj) * SPX_N], + SPX_N ); + } + + /* + * Check if we're at a left child; if so, stop going up the stack + * Exception: if we've reached the end of the tree, keep on going + * (so we combine the last 4 nodes into the one root node in two + * more iterations) + */ + if ((internal_idx & 1) == 0 && idx < max_idx) { + break; + } + + /* Ok, we're at a right node (or doing the top 3 levels) */ + /* Now combine the left and right logical nodes together */ + + /* Set the address of the node we're creating. */ + unsigned int j; + internal_idx_offset >>= 1; + for (j = 0; j < 4; j++) { + set_tree_height(tree_addrx4 + j * 8, h + 1); + set_tree_index(tree_addrx4 + j * 8, + (4 / 2) * (internal_idx & ~1U) + j - left_adj + internal_idx_offset ); + } + unsigned char *left = &stackx4[h * 4 * SPX_N]; + thashx4( ¤t[0 * SPX_N], + ¤t[1 * SPX_N], + ¤t[2 * SPX_N], + ¤t[3 * SPX_N], + &left [0 * SPX_N], + &left [2 * SPX_N], + ¤t[0 * SPX_N], + ¤t[2 * SPX_N], + 2, ctx, tree_addrx4); + } + + /* We've hit a left child; save the current for when we get the */ + /* corresponding right right */ + memcpy( &stackx4[h * 4 * SPX_N], current, 4 * SPX_N); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/utilsx4.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/utilsx4.h new file mode 100644 index 0000000000..facb874b18 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/utilsx4.h @@ -0,0 +1,30 @@ +#ifndef SPX_UTILSX4_H +#define SPX_UTILSX4_H + +#include + +#include "context.h" +#include "params.h" + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + * + * This implementation uses AVX to compute internal nodes 4 at a time (in + * parallel) + */ +#define treehashx4 SPX_NAMESPACE(treehashx4) +void treehashx4(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leafx4)( + unsigned char * /* Where to write the leaves */, + const spx_ctx * /* ctx */, + uint32_t addr_idx, void *info), + uint32_t tree_addrx4[4 * 8], void *info); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/wots.c b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/wots.c new file mode 100644 index 0000000000..4d5041ce05 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/wots.c @@ -0,0 +1,269 @@ +#include +#include + +#include "wots.h" + +#include "address.h" +#include "hash.h" +#include "hashx4.h" +#include "params.h" +#include "thash.h" +#include "thashx4.h" +#include "utils.h" +#include "utilsx4.h" +#include "wotsx4.h" + +// TODO clarify address expectations, and make them more uniform. +// TODO i.e. do we expect types to be set already? +// TODO and do we expect modifications or copies? + +/** + * Computes up the chains + */ +static void gen_chains( + unsigned char *out, + const unsigned char *in, + unsigned int start[SPX_WOTS_LEN], + const unsigned int steps[SPX_WOTS_LEN], + const spx_ctx *ctx, + uint32_t addr[8]) { + uint32_t i, j, k, idx, watching; + int done; + unsigned char empty[SPX_N]; + unsigned char *bufs[4]; + uint32_t addrs[8 * 4]; + + int l; + uint16_t counts[SPX_WOTS_W] = { 0 }; + uint16_t idxs[SPX_WOTS_LEN]; + uint16_t total, newTotal; + + /* set addrs = {addr, addr, addr, addr} */ + for (j = 0; j < 4; j++) { + memcpy(addrs + j * 8, addr, sizeof(uint32_t) * 8); + } + + /* Initialize out with the value at position 'start'. */ + memcpy(out, in, SPX_WOTS_LEN * SPX_N); + + /* Sort the chains in reverse order by steps using counting sort. */ + for (i = 0; i < SPX_WOTS_LEN; i++) { + counts[steps[i]]++; + } + total = 0; + for (l = SPX_WOTS_W - 1; l >= 0; l--) { + newTotal = counts[l] + total; + counts[l] = total; + total = newTotal; + } + for (i = 0; i < SPX_WOTS_LEN; i++) { + idxs[counts[steps[i]]] = (uint16_t)i; + counts[steps[i]]++; + } + + /* We got our work cut out for us: do it! */ + for (i = 0; i < SPX_WOTS_LEN; i += 4) { + for (j = 0; j < 4 && i + j < SPX_WOTS_LEN; j++) { + idx = idxs[i + j]; + set_chain_addr(addrs + j * 8, idx); + bufs[j] = out + SPX_N * idx; + } + + /* As the chains are sorted in reverse order, we know that the first + * chain is the longest and the last one is the shortest. We keep + * an eye on whether the last chain is done and then on the one before, + * et cetera. */ + watching = 3; + done = 0; + while (i + watching >= SPX_WOTS_LEN) { + bufs[watching] = &empty[0]; + watching--; + } + + for (k = 0;; k++) { + while (k == steps[idxs[i + watching]]) { + bufs[watching] = &empty[0]; + if (watching == 0) { + done = 1; + break; + } + watching--; + } + if (done) { + break; + } + for (j = 0; j < watching + 1; j++) { + set_hash_addr(addrs + j * 8, k + start[idxs[i + j]]); + } + + thashx4(bufs[0], bufs[1], bufs[2], bufs[3], + bufs[0], bufs[1], bufs[2], bufs[3], 1, ctx, addrs); + } + } +} + +/** + * base_w algorithm as described in draft. + * Interprets an array of bytes as integers in base w. + * This only works when log_w is a divisor of 8. + */ +static void base_w(unsigned int *output, const int out_len, + const unsigned char *input) { + int in = 0; + int out = 0; + unsigned char total = 0; + int bits = 0; + int consumed; + + for (consumed = 0; consumed < out_len; consumed++) { + if (bits == 0) { + total = input[in]; + in++; + bits += 8; + } + bits -= SPX_WOTS_LOGW; + output[out] = (total >> bits) & (SPX_WOTS_W - 1); + out++; + } +} + +/* Computes the WOTS+ checksum over a message (in base_w). */ +static void wots_checksum(unsigned int *csum_base_w, + const unsigned int *msg_base_w) { + unsigned int csum = 0; + unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; + unsigned int i; + + /* Compute checksum. */ + for (i = 0; i < SPX_WOTS_LEN1; i++) { + csum += SPX_WOTS_W - 1 - msg_base_w[i]; + } + + /* Convert checksum to base_w. */ + /* Make sure expected empty zero bits are the least significant bits. */ + csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); + ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); + base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); +} + +/* Takes a message and derives the matching chain lengths. */ +void chain_lengths(unsigned int *lengths, const unsigned char *msg) { + base_w(lengths, SPX_WOTS_LEN1, msg); + wots_checksum(lengths + SPX_WOTS_LEN1, lengths); +} + +/** + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. + * + * Writes the computed public key to 'pk'. + */ +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]) { + unsigned int steps[SPX_WOTS_LEN]; + unsigned int start[SPX_WOTS_LEN]; + uint32_t i; + + chain_lengths(start, msg); + + for (i = 0; i < SPX_WOTS_LEN; i++) { + steps[i] = SPX_WOTS_W - 1 - start[i]; + } + + gen_chains(pk, sig, start, steps, ctx, addr); +} + +/* + * This generates 4 sequential WOTS public keys + * It also generates the WOTS signature if leaf_info indicates + * that we're signing with one of these WOTS keys + */ +void wots_gen_leafx4(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info) { + struct leaf_info_x4 *info = v_info; + uint32_t *leaf_addr = info->leaf_addr; + uint32_t *pk_addr = info->pk_addr; + unsigned int i, j, k; + unsigned char pk_buffer[ 4 * SPX_WOTS_BYTES ]; + unsigned wots_offset = SPX_WOTS_BYTES; + unsigned char *buffer; + uint32_t wots_k_mask; + unsigned wots_sign_index; + + if (((leaf_idx ^ info->wots_sign_leaf) & ~3U) == 0) { + /* We're traversing the leaf that's signing; generate the WOTS */ + /* signature */ + wots_k_mask = 0; + wots_sign_index = info->wots_sign_leaf & 3; /* Which of of the 4 */ + /* 4 slots do the signatures come from */ + } else { + /* Nope, we're just generating pk's; turn off the signature logic */ + wots_k_mask = (uint32_t)~0; + wots_sign_index = 0; + } + + for (j = 0; j < 4; j++) { + set_keypair_addr( leaf_addr + j * 8, leaf_idx + j ); + set_keypair_addr( pk_addr + j * 8, leaf_idx + j ); + } + + for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { + uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k to */ + /* the step if we're generating a signature, ~0 if we're not */ + + /* Start with the secret seed */ + for (j = 0; j < 4; j++) { + set_chain_addr(leaf_addr + j * 8, i); + set_hash_addr(leaf_addr + j * 8, 0); + set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTSPRF); + } + prf_addrx4(buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + buffer + 2 * wots_offset, + buffer + 3 * wots_offset, + ctx, leaf_addr); + + for (j = 0; j < 4; j++) { + set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTS); + } + + /* Iterate down the WOTS chain */ + for (k = 0;; k++) { + /* Check if one of the values we have needs to be saved as a */ + /* part of the WOTS signature */ + if (k == wots_k) { + memcpy( info->wots_sig + i * SPX_N, + buffer + wots_sign_index * wots_offset, SPX_N ); + } + + /* Check if we hit the top of the chain */ + if (k == SPX_WOTS_W - 1) { + break; + } + + /* Iterate one step on all 4 chains */ + for (j = 0; j < 4; j++) { + set_hash_addr(leaf_addr + j * 8, k); + } + thashx4(buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + buffer + 2 * wots_offset, + buffer + 3 * wots_offset, + buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + buffer + 2 * wots_offset, + buffer + 3 * wots_offset, 1, ctx, leaf_addr); + } + } + + /* Do the final thash to generate the public keys */ + thashx4(dest + 0 * SPX_N, + dest + 1 * SPX_N, + dest + 2 * SPX_N, + dest + 3 * SPX_N, + pk_buffer + 0 * wots_offset, + pk_buffer + 1 * wots_offset, + pk_buffer + 2 * wots_offset, + pk_buffer + 3 * wots_offset, SPX_WOTS_LEN, ctx, pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/wots.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/wots.h new file mode 100644 index 0000000000..4e7692eeef --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/wots.h @@ -0,0 +1,25 @@ +#ifndef SPX_WOTS_H +#define SPX_WOTS_H + +#include + +#include "context.h" +#include "params.h" + +/** + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. + * + * Writes the computed public key to 'pk'. + */ +#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]); + +/* + * Compute the chain lengths needed for a given message hash + */ +#define chain_lengths SPX_NAMESPACE(chain_lengths) +void chain_lengths(unsigned int *lengths, const unsigned char *msg); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/wotsx4.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/wotsx4.h new file mode 100644 index 0000000000..cd634f1743 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/wotsx4.h @@ -0,0 +1,41 @@ +#ifndef WOTSX4_H_ +#define WOTSX4_H_ + +#include + +#include "params.h" + +/* + * This is here to provide an interface to the internal wots_gen_leafx4 + * routine. While this routine is not referenced in the package outside of + * wots.c, it is called from the stand-alone benchmark code to characterize + * the performance + */ +struct leaf_info_x4 { + unsigned char *wots_sig; + uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ + uint32_t *wots_steps; + uint32_t leaf_addr[4 * 8]; + uint32_t pk_addr[4 * 8]; +}; + +/* Macro to set the leaf_info to something 'benign', that is, it would */ +/* run with the same time as it does during the real signing process */ +/* Used only by the benchmark code */ +#define INITIALIZE_LEAF_INFO_X4(info, addr, step_buffer) { \ + (info).wots_sig = 0; \ + (info).wots_sign_leaf = ~0; \ + (info).wots_steps = step_buffer; \ + int i; \ + for (i=0; i<4; i++) { \ + memcpy( &(info).leaf_addr[8*i], addr, 32 ); \ + memcpy( &(info).pk_addr[8*i], addr, 32 ); \ + } \ + } + +#define wots_gen_leafx4 SPX_NAMESPACE(wots_gen_leafx4) +void wots_gen_leafx4(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info); + +#endif /* WOTSX4_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/LICENSE b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/LICENSE new file mode 100644 index 0000000000..670154e353 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/LICENSE @@ -0,0 +1,116 @@ +CC0 1.0 Universal + +Statement of Purpose + +The laws of most jurisdictions throughout the world automatically confer +exclusive Copyright and Related Rights (defined below) upon the creator and +subsequent owner(s) (each and all, an "owner") of an original work of +authorship and/or a database (each, a "Work"). + +Certain owners wish to permanently relinquish those rights to a Work for the +purpose of contributing to a commons of creative, cultural and scientific +works ("Commons") that the public can reliably and without fear of later +claims of infringement build upon, modify, incorporate in other works, reuse +and redistribute as freely as possible in any form whatsoever and for any +purposes, including without limitation commercial purposes. These owners may +contribute to the Commons to promote the ideal of a free culture and the +further production of creative, cultural and scientific works, or to gain +reputation or greater distribution for their Work in part through the use and +efforts of others. + +For these and/or other purposes and motivations, and without any expectation +of additional consideration or compensation, the person associating CC0 with a +Work (the "Affirmer"), to the extent that he or she is an owner of Copyright +and Related Rights in the Work, voluntarily elects to apply CC0 to the Work +and publicly distribute the Work under its terms, with knowledge of his or her +Copyright and Related Rights in the Work and the meaning and intended legal +effect of CC0 on those rights. + +1. Copyright and Related Rights. A Work made available under CC0 may be +protected by copyright and related or neighboring rights ("Copyright and +Related Rights"). Copyright and Related Rights include, but are not limited +to, the following: + + i. the right to reproduce, adapt, distribute, perform, display, communicate, + and translate a Work; + + ii. moral rights retained by the original author(s) and/or performer(s); + + iii. publicity and privacy rights pertaining to a person's image or likeness + depicted in a Work; + + iv. rights protecting against unfair competition in regards to a Work, + subject to the limitations in paragraph 4(a), below; + + v. rights protecting the extraction, dissemination, use and reuse of data in + a Work; + + vi. database rights (such as those arising under Directive 96/9/EC of the + European Parliament and of the Council of 11 March 1996 on the legal + protection of databases, and under any national implementation thereof, + including any amended or successor version of such directive); and + + vii. other similar, equivalent or corresponding rights throughout the world + based on applicable law or treaty, and any national implementations thereof. + +2. Waiver. To the greatest extent permitted by, but not in contravention of, +applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and +unconditionally waives, abandons, and surrenders all of Affirmer's Copyright +and Related Rights and associated claims and causes of action, whether now +known or unknown (including existing as well as future claims and causes of +action), in the Work (i) in all territories worldwide, (ii) for the maximum +duration provided by applicable law or treaty (including future time +extensions), (iii) in any current or future medium and for any number of +copies, and (iv) for any purpose whatsoever, including without limitation +commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes +the Waiver for the benefit of each member of the public at large and to the +detriment of Affirmer's heirs and successors, fully intending that such Waiver +shall not be subject to revocation, rescission, cancellation, termination, or +any other legal or equitable action to disrupt the quiet enjoyment of the Work +by the public as contemplated by Affirmer's express Statement of Purpose. + +3. Public License Fallback. Should any part of the Waiver for any reason be +judged legally invalid or ineffective under applicable law, then the Waiver +shall be preserved to the maximum extent permitted taking into account +Affirmer's express Statement of Purpose. In addition, to the extent the Waiver +is so judged Affirmer hereby grants to each affected person a royalty-free, +non transferable, non sublicensable, non exclusive, irrevocable and +unconditional license to exercise Affirmer's Copyright and Related Rights in +the Work (i) in all territories worldwide, (ii) for the maximum duration +provided by applicable law or treaty (including future time extensions), (iii) +in any current or future medium and for any number of copies, and (iv) for any +purpose whatsoever, including without limitation commercial, advertising or +promotional purposes (the "License"). The License shall be deemed effective as +of the date CC0 was applied by Affirmer to the Work. Should any part of the +License for any reason be judged legally invalid or ineffective under +applicable law, such partial invalidity or ineffectiveness shall not +invalidate the remainder of the License, and in such case Affirmer hereby +affirms that he or she will not (i) exercise any of his or her remaining +Copyright and Related Rights in the Work or (ii) assert any associated claims +and causes of action with respect to the Work, in either case contrary to +Affirmer's express Statement of Purpose. + +4. Limitations and Disclaimers. + + a. No trademark or patent rights held by Affirmer are waived, abandoned, + surrendered, licensed or otherwise affected by this document. + + b. Affirmer offers the Work as-is and makes no representations or warranties + of any kind concerning the Work, express, implied, statutory or otherwise, + including without limitation warranties of title, merchantability, fitness + for a particular purpose, non infringement, or the absence of latent or + other defects, accuracy, or the present or absence of errors, whether or not + discoverable, all to the greatest extent permissible under applicable law. + + c. Affirmer disclaims responsibility for clearing rights of other persons + that may apply to the Work or any use thereof, including without limitation + any person's Copyright and Related Rights in the Work. Further, Affirmer + disclaims responsibility for obtaining any necessary consents, permissions + or other rights required for any use of the Work. + + d. Affirmer understands and acknowledges that Creative Commons is not a + party to this document and has no duty or obligation with respect to this + CC0 or use of the Work. + +For more information, please see + diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/address.c b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/address.c new file mode 100644 index 0000000000..d49d9f3b6b --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/address.c @@ -0,0 +1,95 @@ +#include +#include + +#include "address.h" +#include "params.h" +#include "utils.h" + +/* + * Specify which level of Merkle tree (the "layer") we're working on + */ +void set_layer_addr(uint32_t addr[8], uint32_t layer) { + ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; +} + +/* + * Specify which Merkle tree within the level (the "tree address") we're working on + */ +void set_tree_addr(uint32_t addr[8], uint64_t tree) { + ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); +} + +/* + * Specify the reason we'll use this address structure for, that is, what + * hash will we compute with it. This is used so that unrelated types of + * hashes don't accidentally get the same address structure. The type will be + * one of the SPX_ADDR_TYPE constants + */ +void set_type(uint32_t addr[8], uint32_t type) { + ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; +} + +/* + * Copy the layer and tree fields of the address structure. This is used + * when we're doing multiple types of hashes within the same Merkle tree + */ +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); +} + +/* These functions are used for OTS addresses. */ + +/* + * Specify which Merkle leaf we're working on; that is, which OTS keypair + * we're talking about. + */ +void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { + /* We have > 256 OTS at the bottom of the Merkle tree; to specify */ + /* which one, we'd need to express it in two bytes */ + ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR2] = (unsigned char)(keypair >> 8); + ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; +} + +/* + * Copy the layer, tree and keypair fields of the address structure. This is + * used when we're doing multiple things within the same OTS keypair + */ +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); + ((unsigned char *)out)[SPX_OFFSET_KP_ADDR2] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR2]; + ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; +} + +/* + * Specify which Merkle chain within the OTS we're working with + * (the chain address) + */ +void set_chain_addr(uint32_t addr[8], uint32_t chain) { + ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; +} + +/* + * Specify where in the Merkle chain we are +* (the hash address) + */ +void set_hash_addr(uint32_t addr[8], uint32_t hash) { + ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; +} + +/* These functions are used for all hash tree addresses (including FORS). */ + +/* + * Specify the height of the node in the Merkle/FORS tree we are in + * (the tree height) + */ +void set_tree_height(uint32_t addr[8], uint32_t tree_height) { + ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; +} + +/* + * Specify the distance from the left edge of the node in the Merkle/FORS tree + * (the tree index) + */ +void set_tree_index(uint32_t addr[8], uint32_t tree_index) { + u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/address.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/address.h new file mode 100644 index 0000000000..24a84eb40c --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/address.h @@ -0,0 +1,52 @@ +#ifndef SPX_ADDRESS_H +#define SPX_ADDRESS_H + +#include + +#include "params.h" + +/* The hash types that are passed to set_type */ +#define SPX_ADDR_TYPE_WOTS 0 +#define SPX_ADDR_TYPE_WOTSPK 1 +#define SPX_ADDR_TYPE_HASHTREE 2 +#define SPX_ADDR_TYPE_FORSTREE 3 +#define SPX_ADDR_TYPE_FORSPK 4 +#define SPX_ADDR_TYPE_WOTSPRF 5 +#define SPX_ADDR_TYPE_FORSPRF 6 + +#define set_layer_addr SPX_NAMESPACE(set_layer_addr) +void set_layer_addr(uint32_t addr[8], uint32_t layer); + +#define set_tree_addr SPX_NAMESPACE(set_tree_addr) +void set_tree_addr(uint32_t addr[8], uint64_t tree); + +#define set_type SPX_NAMESPACE(set_type) +void set_type(uint32_t addr[8], uint32_t type); + +/* Copies the layer and tree part of one address into the other */ +#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); + +/* These functions are used for WOTS and FORS addresses. */ + +#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) +void set_keypair_addr(uint32_t addr[8], uint32_t keypair); + +#define set_chain_addr SPX_NAMESPACE(set_chain_addr) +void set_chain_addr(uint32_t addr[8], uint32_t chain); + +#define set_hash_addr SPX_NAMESPACE(set_hash_addr) +void set_hash_addr(uint32_t addr[8], uint32_t hash); + +#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); + +/* These functions are used for all hash tree addresses (including FORS). */ + +#define set_tree_height SPX_NAMESPACE(set_tree_height) +void set_tree_height(uint32_t addr[8], uint32_t tree_height); + +#define set_tree_index SPX_NAMESPACE(set_tree_index) +void set_tree_index(uint32_t addr[8], uint32_t tree_index); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/api.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/api.h new file mode 100644 index 0000000000..7de1885b77 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/api.h @@ -0,0 +1,77 @@ +#ifndef PQCLEAN_SPHINCSSHAKE192SROBUST_CLEAN_API_H +#define PQCLEAN_SPHINCSSHAKE192SROBUST_CLEAN_API_H + +#include +#include + +#define PQCLEAN_SPHINCSSHAKE192SROBUST_CLEAN_CRYPTO_ALGNAME "SPHINCS+-shake-192s-robust" + +#define PQCLEAN_SPHINCSSHAKE192SROBUST_CLEAN_CRYPTO_SECRETKEYBYTES 96 +#define PQCLEAN_SPHINCSSHAKE192SROBUST_CLEAN_CRYPTO_PUBLICKEYBYTES 48 +#define PQCLEAN_SPHINCSSHAKE192SROBUST_CLEAN_CRYPTO_BYTES 16224 + +#define PQCLEAN_SPHINCSSHAKE192SROBUST_CLEAN_CRYPTO_SEEDBYTES 72 + +/* + * Returns the length of a secret key, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE192SROBUST_CLEAN_crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE192SROBUST_CLEAN_crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE192SROBUST_CLEAN_crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE192SROBUST_CLEAN_crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +int PQCLEAN_SPHINCSSHAKE192SROBUST_CLEAN_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +int PQCLEAN_SPHINCSSHAKE192SROBUST_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +int PQCLEAN_SPHINCSSHAKE192SROBUST_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +int PQCLEAN_SPHINCSSHAKE192SROBUST_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, + const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +int PQCLEAN_SPHINCSSHAKE192SROBUST_CLEAN_crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +int PQCLEAN_SPHINCSSHAKE192SROBUST_CLEAN_crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/context.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/context.h new file mode 100644 index 0000000000..9f8a40ab4e --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/context.h @@ -0,0 +1,22 @@ +#ifndef SPX_CONTEXT_H +#define SPX_CONTEXT_H + +#include +#include + +#include "params.h" + +typedef struct { + uint8_t pub_seed[SPX_N]; + uint8_t sk_seed[SPX_N]; + + +} spx_ctx; + +#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) +void initialize_hash_function(spx_ctx *ctx); + +#define free_hash_function SPX_NAMESPACE(free_hash_function) +void free_hash_function(spx_ctx *ctx); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/context_shake.c b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/context_shake.c new file mode 100644 index 0000000000..9614a103d3 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/context_shake.c @@ -0,0 +1,12 @@ +#include "context.h" + +/* For SHAKE256, there is no immediate reason to initialize at the start, + so this function is an empty operation. */ +void initialize_hash_function(spx_ctx *ctx) { + (void)ctx; /* Suppress an 'unused parameter' warning. */ +} + +// in case the hash function api is heap-based. +void free_hash_function(spx_ctx *ctx) { + (void)ctx; +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/fors.c b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/fors.c new file mode 100644 index 0000000000..96ca72e986 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/fors.c @@ -0,0 +1,156 @@ +#include +#include +#include + +#include "fors.h" + +#include "address.h" +#include "hash.h" +#include "thash.h" +#include "utils.h" +#include "utilsx1.h" + +static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + prf_addr(sk, ctx, fors_leaf_addr); +} + +static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, + const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + thash(leaf, sk, 1, ctx, fors_leaf_addr); +} + +struct fors_gen_leaf_info { + uint32_t leaf_addrx[8]; +}; + +static void fors_gen_leafx1(unsigned char *leaf, + const spx_ctx *ctx, + uint32_t addr_idx, void *info) { + struct fors_gen_leaf_info *fors_info = info; + uint32_t *fors_leaf_addr = fors_info->leaf_addrx; + + /* Only set the parts that the caller doesn't set */ + set_tree_index(fors_leaf_addr, addr_idx); + set_type(fors_leaf_addr, SPX_ADDR_TYPE_FORSPRF); + fors_gen_sk(leaf, ctx, fors_leaf_addr); + + set_type(fors_leaf_addr, SPX_ADDR_TYPE_FORSTREE); + fors_sk_to_leaf(leaf, leaf, + ctx, fors_leaf_addr); +} + +/** + * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + * Assumes indices has space for SPX_FORS_TREES integers. + */ +static void message_to_indices(uint32_t *indices, const unsigned char *m) { + unsigned int i, j; + unsigned int offset = 0; + + for (i = 0; i < SPX_FORS_TREES; i++) { + indices[i] = 0; + for (j = 0; j < SPX_FORS_HEIGHT; j++) { + indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); + offset++; + } + } +} + +/** + * Signs a message m, deriving the secret key from sk_seed and the FTS address. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + uint32_t fors_tree_addr[8] = {0}; + struct fors_gen_leaf_info fors_info = {0}; + uint32_t *fors_leaf_addr = fors_info.leaf_addrx; + uint32_t fors_pk_addr[8] = {0}; + uint32_t idx_offset; + unsigned int i; + + copy_keypair_addr(fors_tree_addr, fors_addr); + copy_keypair_addr(fors_leaf_addr, fors_addr); + + copy_keypair_addr(fors_pk_addr, fors_addr); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); + + message_to_indices(indices, m); + + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); + + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); + + /* Include the secret key part that produces the selected leaf node. */ + fors_gen_sk(sig, ctx, fors_tree_addr); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + sig += SPX_N; + + /* Compute the authentication path for this leaf node. */ + treehashx1(roots + i * SPX_N, sig, ctx, + indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx1, + fors_tree_addr, &fors_info); + + sig += SPX_N * SPX_FORS_HEIGHT; + } + + /* Hash horizontally across all tree roots to derive the public key. */ + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); +} + +/** + * Derives the FORS public key from a signature. + * This can be used for verification by comparing to a known public key, or to + * subsequently verify a signature on the derived public key. The latter is the + * typical use-case when used as an FTS below an OTS in a hypertree. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + unsigned char leaf[SPX_N]; + uint32_t fors_tree_addr[8] = {0}; + uint32_t fors_pk_addr[8] = {0}; + uint32_t idx_offset; + unsigned int i; + + copy_keypair_addr(fors_tree_addr, fors_addr); + copy_keypair_addr(fors_pk_addr, fors_addr); + + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); + + message_to_indices(indices, m); + + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); + + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + + /* Derive the leaf from the included secret key part. */ + fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); + sig += SPX_N; + + /* Derive the corresponding root node of this tree. */ + compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, + sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); + sig += SPX_N * SPX_FORS_HEIGHT; + } + + /* Hash horizontally across all tree roots to derive the public key. */ + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/fors.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/fors.h new file mode 100644 index 0000000000..509140a178 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/fors.h @@ -0,0 +1,32 @@ +#ifndef SPX_FORS_H +#define SPX_FORS_H + +#include + +#include "context.h" +#include "params.h" + +/** + * Signs a message m, deriving the secret key from sk_seed and the FTS address. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +#define fors_sign SPX_NAMESPACE(fors_sign) +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); + +/** + * Derives the FORS public key from a signature. + * This can be used for verification by comparing to a known public key, or to + * subsequently verify a signature on the derived public key. The latter is the + * typical use-case when used as an FTS below an OTS in a hypertree. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/hash.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/hash.h new file mode 100644 index 0000000000..f7c87d4c3c --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/hash.h @@ -0,0 +1,28 @@ +#ifndef SPX_HASH_H +#define SPX_HASH_H + +#include +#include + +#include "context.h" +#include "params.h" + +#define prf_addr SPX_NAMESPACE(prf_addr) +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]); + +#define gen_message_random SPX_NAMESPACE(gen_message_random) +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); + +#define hash_message SPX_NAMESPACE(hash_message) +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); + + + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/hash_shake.c b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/hash_shake.c new file mode 100644 index 0000000000..ff5e7ec918 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/hash_shake.c @@ -0,0 +1,83 @@ +#include +#include + +#include "hash.h" + +#include "address.h" +#include "fips202.h" +#include "params.h" +#include "utils.h" + +/* + * Computes PRF(pk_seed, sk_seed, addr) + */ +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]) { + unsigned char buf[2 * SPX_N + SPX_ADDR_BYTES]; + + memcpy(buf, ctx->pub_seed, SPX_N); + memcpy(buf + SPX_N, addr, SPX_ADDR_BYTES); + memcpy(buf + SPX_N + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); + + shake256(out, SPX_N, buf, 2 * SPX_N + SPX_ADDR_BYTES); +} + +/** + * Computes the message-dependent randomness R, using a secret seed and an + * optional randomization value as well as the message. + */ +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { + (void)ctx; + shake256incctx s_inc; + + shake256_inc_init(&s_inc); + shake256_inc_absorb(&s_inc, sk_prf, SPX_N); + shake256_inc_absorb(&s_inc, optrand, SPX_N); + shake256_inc_absorb(&s_inc, m, mlen); + shake256_inc_finalize(&s_inc); + shake256_inc_squeeze(R, SPX_N, &s_inc); + shake256_inc_ctx_release(&s_inc); +} + +/** + * Computes the message hash using R, the public key, and the message. + * Outputs the message digest and the index of the leaf. The index is split in + * the tree index and the leaf index, for convenient copying to an address. + */ +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { + (void)ctx; +#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) +#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) +#define SPX_LEAF_BITS SPX_TREE_HEIGHT +#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) +#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) + + unsigned char buf[SPX_DGST_BYTES]; + unsigned char *bufp = buf; + shake256incctx s_inc; + + shake256_inc_init(&s_inc); + shake256_inc_absorb(&s_inc, R, SPX_N); + shake256_inc_absorb(&s_inc, pk, SPX_PK_BYTES); + shake256_inc_absorb(&s_inc, m, mlen); + shake256_inc_finalize(&s_inc); + shake256_inc_squeeze(buf, SPX_DGST_BYTES, &s_inc); + shake256_inc_ctx_release(&s_inc); + + memcpy(digest, bufp, SPX_FORS_MSG_BYTES); + bufp += SPX_FORS_MSG_BYTES; + + + *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); + *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); + bufp += SPX_TREE_BYTES; + + *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); + *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/merkle.c b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/merkle.c new file mode 100644 index 0000000000..0c1479fd93 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/merkle.c @@ -0,0 +1,59 @@ +#include +#include + +#include "address.h" +#include "merkle.h" +#include "params.h" +#include "utils.h" +#include "utilsx1.h" +#include "wots.h" +#include "wotsx1.h" + +/* + * This generates a Merkle signature (WOTS signature followed by the Merkle + * authentication path). This is in this file because most of the complexity + * is involved with the WOTS signature; the Merkle authentication path logic + * is mostly hidden in treehashx4 + */ +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf) { + unsigned char *auth_path = sig + SPX_WOTS_BYTES; + struct leaf_info_x1 info = { 0 }; + unsigned steps[ SPX_WOTS_LEN ]; + + info.wots_sig = sig; + chain_lengths(steps, root); + info.wots_steps = steps; + + set_type(&tree_addr[0], SPX_ADDR_TYPE_HASHTREE); + set_type(&info.pk_addr[0], SPX_ADDR_TYPE_WOTSPK); + copy_subtree_addr(&info.leaf_addr[0], wots_addr); + copy_subtree_addr(&info.pk_addr[0], wots_addr); + + info.wots_sign_leaf = idx_leaf; + + treehashx1(root, auth_path, ctx, + idx_leaf, 0, + SPX_TREE_HEIGHT, + wots_gen_leafx1, + tree_addr, &info); +} + +/* Compute root node of the top-most subtree. */ +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { + /* We do not need the auth path in key generation, but it simplifies the + code to have just one treehash routine that computes both root and path + in one function. */ + unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; + uint32_t top_tree_addr[8] = {0}; + uint32_t wots_addr[8] = {0}; + + set_layer_addr(top_tree_addr, SPX_D - 1); + set_layer_addr(wots_addr, SPX_D - 1); + + merkle_sign(auth_path, root, ctx, + wots_addr, top_tree_addr, + (uint32_t)~0 /* ~0 means "don't bother generating an auth path */ ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/merkle.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/merkle.h new file mode 100644 index 0000000000..769cf2e970 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/merkle.h @@ -0,0 +1,21 @@ +#ifndef MERKLE_H_ +#define MERKLE_H_ + +#include + +#include "context.h" +#include "params.h" + +/* Generate a Merkle signature (WOTS signature followed by the Merkle */ +/* authentication path) */ +#define merkle_sign SPX_NAMESPACE(merkle_sign) +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf); + +/* Compute the root node of the top-most subtree. */ +#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); + +#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/nistapi.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/nistapi.h new file mode 100644 index 0000000000..3cb71afad4 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/nistapi.h @@ -0,0 +1,87 @@ +#ifndef SPX_API_H +#define SPX_API_H + +#include +#include + +#include "params.h" + +#define CRYPTO_ALGNAME "SPHINCS+" + +#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES +#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES +#define CRYPTO_BYTES SPX_BYTES +#define CRYPTO_SEEDBYTES (3*SPX_N) + +/* + * Returns the length of a secret key, in bytes + */ +#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) +size_t crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) +size_t crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) +size_t crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) +size_t crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +#define crypto_sign SPX_NAMESPACE(crypto_sign) +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/params.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/params.h new file mode 100644 index 0000000000..aa0173dce4 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/params.h @@ -0,0 +1,56 @@ +#ifndef SPX_PARAMS_H +#define SPX_PARAMS_H + +#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSSHAKE192SROBUST_CLEAN_##s + +/* Hash output length in bytes. */ +#define SPX_N 24 +/* Height of the hypertree. */ +#define SPX_FULL_HEIGHT 63 +/* Number of subtree layer. */ +#define SPX_D 7 +/* FORS tree dimensions. */ +#define SPX_FORS_HEIGHT 14 +#define SPX_FORS_TREES 17 +/* Winternitz parameter, */ +#define SPX_WOTS_W 16 + +/* The hash function is defined by linking a different hash.c file, as opposed + to setting a #define constant. */ + +/* For clarity */ +#define SPX_ADDR_BYTES 32 + +/* WOTS parameters. */ +#define SPX_WOTS_LOGW 4 + +#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) + +/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ +#define SPX_WOTS_LEN2 3 + +#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) +#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) +#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES + +/* Subtree size. */ +#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) + +//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT +// #error SPX_D should always divide SPX_FULL_HEIGHT +//#endif + +/* FORS parameters. */ +#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) +#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) +#define SPX_FORS_PK_BYTES SPX_N + +/* Resulting SPX sizes. */ +#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ + SPX_FULL_HEIGHT * SPX_N) +#define SPX_PK_BYTES (2 * SPX_N) +#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) + +#include "shake_offsets.h" + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/shake_offsets.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/shake_offsets.h new file mode 100644 index 0000000000..6b28d95d91 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/shake_offsets.h @@ -0,0 +1,21 @@ +#ifndef SHAKE_OFFSETS_H_ +#define SHAKE_OFFSETS_H_ + +/* + * Offsets of various fields in the address structure when we use SHAKE as + * the Sphincs+ hash function + */ + +#define SPX_OFFSET_LAYER 3 /* The byte used to specify the Merkle tree layer */ +#define SPX_OFFSET_TREE 8 /* The start of the 8 byte field used to specify the tree */ +#define SPX_OFFSET_TYPE 19 /* The byte used to specify the hash type (reason) */ +#define SPX_OFFSET_KP_ADDR2 22 /* The high byte used to specify the key pair (which one-time signature) */ +#define SPX_OFFSET_KP_ADDR1 23 /* The low byte used to specify the key pair */ +#define SPX_OFFSET_CHAIN_ADDR 27 /* The byte used to specify the chain address (which Winternitz chain) */ +#define SPX_OFFSET_HASH_ADDR 31 /* The byte used to specify the hash address (where in the Winternitz chain) */ +#define SPX_OFFSET_TREE_HGT 27 /* The byte used to specify the height of this node in the FORS or Merkle tree */ +#define SPX_OFFSET_TREE_INDEX 28 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ + +#define SPX_SHAKE 1 + +#endif /* SHAKE_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/sign.c b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/sign.c new file mode 100644 index 0000000000..9d0c7d1b22 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/sign.c @@ -0,0 +1,286 @@ +#include +#include +#include + +#include "address.h" +#include "context.h" +#include "fors.h" +#include "hash.h" +#include "merkle.h" +#include "nistapi.h" +#include "params.h" +#include "randombytes.h" +#include "thash.h" +#include "utils.h" +#include "wots.h" + +/* + * Returns the length of a secret key, in bytes + */ +size_t crypto_sign_secretkeybytes(void) { + return CRYPTO_SECRETKEYBYTES; +} + +/* + * Returns the length of a public key, in bytes + */ +size_t crypto_sign_publickeybytes(void) { + return CRYPTO_PUBLICKEYBYTES; +} + +/* + * Returns the length of a signature, in bytes + */ +size_t crypto_sign_bytes(void) { + return CRYPTO_BYTES; +} + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +size_t crypto_sign_seedbytes(void) { + return CRYPTO_SEEDBYTES; +} + +/* + * Generates an SPX key pair given a seed of length + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [PUB_SEED || root] + */ +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed) { + spx_ctx ctx; + + /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ + memcpy(sk, seed, CRYPTO_SEEDBYTES); + + memcpy(pk, sk + 2 * SPX_N, SPX_N); + + memcpy(ctx.pub_seed, pk, SPX_N); + memcpy(ctx.sk_seed, sk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + /* Compute root node of the top-most subtree. */ + merkle_gen_root(sk + 3 * SPX_N, &ctx); + + // cleanup + free_hash_function(&ctx); + + memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); + + return 0; +} + +/* + * Generates an SPX key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [PUB_SEED || root] + */ +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { + uint8_t seed[CRYPTO_SEEDBYTES]; + randombytes(seed, CRYPTO_SEEDBYTES); + crypto_sign_seed_keypair(pk, sk, seed); + + return 0; +} + +/** + * Returns an array containing a detached signature. + */ +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk) { + spx_ctx ctx; + + const uint8_t *sk_prf = sk + SPX_N; + const uint8_t *pk = sk + 2 * SPX_N; + + uint8_t optrand[SPX_N]; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t root[SPX_N]; + uint32_t i; + uint64_t tree; + uint32_t idx_leaf; + uint32_t wots_addr[8] = {0}; + uint32_t tree_addr[8] = {0}; + + memcpy(ctx.sk_seed, sk, SPX_N); + memcpy(ctx.pub_seed, pk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + + /* Optionally, signing can be made non-deterministic using optrand. + This can help counter side-channel attacks that would benefit from + getting a large number of traces when the signer uses the same nodes. */ + randombytes(optrand, SPX_N); + /* Compute the digest randomization value. */ + gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); + + /* Derive the message digest and leaf index from R, PK and M. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; + + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); + + /* Sign the message hash using FORS. */ + fors_sign(sig, root, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); + sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; + + /* Update the indices for the next layer. */ + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; + } + + free_hash_function(&ctx); + + *siglen = SPX_BYTES; + + return 0; +} + +/** + * Verifies a detached signature and message under a given public key. + */ +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk) { + spx_ctx ctx; + const uint8_t *pub_root = pk + SPX_N; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t wots_pk[SPX_WOTS_BYTES]; + uint8_t root[SPX_N]; + uint8_t leaf[SPX_N]; + unsigned int i; + uint64_t tree; + uint32_t idx_leaf; + uint32_t wots_addr[8] = {0}; + uint32_t tree_addr[8] = {0}; + uint32_t wots_pk_addr[8] = {0}; + + if (siglen != SPX_BYTES) { + return -1; + } + + memcpy(ctx.pub_seed, pk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); + + /* Derive the message digest and leaf index from R || PK || M. */ + /* The additional SPX_N is a result of the hash domain separator. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; + + /* Layer correctly defaults to 0, so no need to set_layer_addr */ + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); + + fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + /* For each subtree.. */ + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + copy_keypair_addr(wots_pk_addr, wots_addr); + + /* The WOTS public key is only correct if the signature was correct. */ + /* Initially, root is the FORS pk, but on subsequent iterations it is + the root of the subtree below the currently processed subtree. */ + wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); + sig += SPX_WOTS_BYTES; + + /* Compute the leaf node using the WOTS public key. */ + thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); + + /* Compute the root node of this subtree. */ + compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, + &ctx, tree_addr); + sig += SPX_TREE_HEIGHT * SPX_N; + + /* Update the indices for the next layer. */ + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; + } + + // cleanup + free_hash_function(&ctx); + + /* Check if the root node equals the root node in the public key. */ + if (memcmp(root, pub_root, SPX_N) != 0) { + return -1; + } + + return 0; +} + + +/** + * Returns an array containing the signature followed by the message. + */ +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk) { + size_t siglen; + + crypto_sign_signature(sm, &siglen, m, mlen, sk); + + memmove(sm + SPX_BYTES, m, mlen); + *smlen = siglen + mlen; + + return 0; +} + +/** + * Verifies a given signature-message pair under a given public key. + */ +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk) { + /* The API caller does not necessarily know what size a signature should be + but SPHINCS+ signatures are always exactly SPX_BYTES. */ + if (smlen < SPX_BYTES) { + memset(m, 0, smlen); + *mlen = 0; + return -1; + } + + *mlen = smlen - SPX_BYTES; + + if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { + memset(m, 0, smlen); + *mlen = 0; + return -1; + } + + /* If verification was successful, move the message to the right place. */ + memmove(m, sm + SPX_BYTES, *mlen); + + return 0; +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/thash.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/thash.h new file mode 100644 index 0000000000..8687ccfb4d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/thash.h @@ -0,0 +1,13 @@ +#ifndef SPX_THASH_H +#define SPX_THASH_H + +#include "context.h" +#include "params.h" + +#include + +#define thash SPX_NAMESPACE(thash) +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/thash_shake_robust.c b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/thash_shake_robust.c new file mode 100644 index 0000000000..696d53c5cc --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/thash_shake_robust.c @@ -0,0 +1,31 @@ +#include +#include + +#include "thash.h" + +#include "address.h" +#include "params.h" +#include "utils.h" + +#include "fips202.h" + +/** + * Takes an array of inblocks concatenated arrays of SPX_N bytes. + */ +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]) { + PQCLEAN_VLA(uint8_t, buf, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); + PQCLEAN_VLA(uint8_t, bitmask, inblocks * SPX_N); + unsigned int i; + + memcpy(buf, ctx->pub_seed, SPX_N); + memcpy(buf + SPX_N, addr, SPX_ADDR_BYTES); + + shake256(bitmask, inblocks * SPX_N, buf, SPX_N + SPX_ADDR_BYTES); + + for (i = 0; i < inblocks * SPX_N; i++) { + buf[SPX_N + SPX_ADDR_BYTES + i] = in[i] ^ bitmask[i]; + } + + shake256(out, SPX_N, buf, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/utils.c b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/utils.c new file mode 100644 index 0000000000..177b541fb9 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/utils.c @@ -0,0 +1,148 @@ +#include + +#include "utils.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "thash.h" + +/** + * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. + */ +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in) { + int i; + + /* Iterate over out in decreasing order, for big-endianness. */ + for (i = (signed int)outlen - 1; i >= 0; i--) { + out[i] = in & 0xff; + in = in >> 8; + } +} + +void u32_to_bytes(unsigned char *out, uint32_t in) { + out[0] = (unsigned char)(in >> 24); + out[1] = (unsigned char)(in >> 16); + out[2] = (unsigned char)(in >> 8); + out[3] = (unsigned char)in; +} + +/** + * Converts the inlen bytes in 'in' from big-endian byte order to an integer. + */ +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { + unsigned long long retval = 0; + unsigned int i; + + for (i = 0; i < inlen; i++) { + retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); + } + return retval; +} + +/** + * Computes a root node given a leaf and an auth path. + * Expects address to be complete other than the tree_height and tree_index. + */ +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]) { + uint32_t i; + unsigned char buffer[2 * SPX_N]; + + /* If leaf_idx is odd (last bit = 1), current path element is a right child + and auth_path has to go left. Otherwise it is the other way around. */ + if (leaf_idx & 1) { + memcpy(buffer + SPX_N, leaf, SPX_N); + memcpy(buffer, auth_path, SPX_N); + } else { + memcpy(buffer, leaf, SPX_N); + memcpy(buffer + SPX_N, auth_path, SPX_N); + } + auth_path += SPX_N; + + for (i = 0; i < tree_height - 1; i++) { + leaf_idx >>= 1; + idx_offset >>= 1; + /* Set the address of the node we're creating. */ + set_tree_height(addr, i + 1); + set_tree_index(addr, leaf_idx + idx_offset); + + /* Pick the right or left neighbor, depending on parity of the node. */ + if (leaf_idx & 1) { + thash(buffer + SPX_N, buffer, 2, ctx, addr); + memcpy(buffer, auth_path, SPX_N); + } else { + thash(buffer, buffer, 2, ctx, addr); + memcpy(buffer + SPX_N, auth_path, SPX_N); + } + auth_path += SPX_N; + } + + /* The last iteration is exceptional; we do not copy an auth_path node. */ + leaf_idx >>= 1; + idx_offset >>= 1; + set_tree_height(addr, tree_height); + set_tree_index(addr, leaf_idx + idx_offset); + thash(root, buffer, 2, ctx, addr); +} + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx * /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]) { + PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); + PQCLEAN_VLA(unsigned int, heights, tree_height + 1); + unsigned int offset = 0; + uint32_t idx; + uint32_t tree_idx; + + for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { + /* Add the next leaf node to the stack. */ + gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); + offset++; + heights[offset - 1] = 0; + + /* If this is a node we need for the auth path.. */ + if ((leaf_idx ^ 0x1) == idx) { + memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); + } + + /* While the top-most nodes are of equal height.. */ + while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { + /* Compute index of the new node, in the next layer. */ + tree_idx = (idx >> (heights[offset - 1] + 1)); + + /* Set the address of the node we're creating. */ + set_tree_height(tree_addr, heights[offset - 1] + 1); + set_tree_index(tree_addr, + tree_idx + (idx_offset >> (heights[offset - 1] + 1))); + /* Hash the top-most nodes from the stack together. */ + thash(stack + (offset - 2)*SPX_N, + stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); + offset--; + /* Note that the top-most node is now one layer higher. */ + heights[offset - 1]++; + + /* If this is a node we need for the auth path.. */ + if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { + memcpy(auth_path + heights[offset - 1]*SPX_N, + stack + (offset - 1)*SPX_N, SPX_N); + } + } + } + memcpy(root, stack, SPX_N); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/utils.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/utils.h new file mode 100644 index 0000000000..64f5d5a53a --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/utils.h @@ -0,0 +1,58 @@ +#ifndef SPX_UTILS_H +#define SPX_UTILS_H + +#include + +#include "compat.h" +#include "context.h" +#include "params.h" + + +/* To support MSVC use alloca() instead of VLAs. See #20. */ + + +/** + * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. + */ +#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in); +#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) +void u32_to_bytes(unsigned char *out, uint32_t in); + +/** + * Converts the inlen bytes in 'in' from big-endian byte order to an integer. + */ +#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); + +/** + * Computes a root node given a leaf and an auth path. + * Expects address to be complete other than the tree_height and tree_index. + */ +#define compute_root SPX_NAMESPACE(compute_root) +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]); + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +#define treehash SPX_NAMESPACE(treehash) +void treehash(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx *ctx /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]); + + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/utilsx1.c b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/utilsx1.c new file mode 100644 index 0000000000..fccb69b35d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/utilsx1.c @@ -0,0 +1,100 @@ +#include + +#include "utilsx1.h" + +#include "address.h" +#include "params.h" +#include "thash.h" +#include "utils.h" + +/* + * Generate the entire Merkle tree, computing the authentication path for + * leaf_idx, and the resulting root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) + * + * This expects tree_addr to be initialized to the addr structures for the + * Merkle tree nodes + * + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + * + * This works by using the standard Merkle tree building algorithm, + */ +void treehashx1(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, + uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* Where to write the leaves */, + const spx_ctx * /* ctx */, + uint32_t idx, void *info), + uint32_t tree_addr[8], + void *info) { + /* This is where we keep the intermediate nodes */ + PQCLEAN_VLA(uint8_t, stack, tree_height * SPX_N); + + uint32_t idx; + uint32_t max_idx = (uint32_t)((1 << tree_height) - 1); + for (idx = 0;; idx++) { + unsigned char current[2 * SPX_N]; /* Current logical node is at */ + /* index[SPX_N]. We do this to minimize the number of copies */ + /* needed during a thash */ + gen_leaf( ¤t[SPX_N], ctx, idx + idx_offset, + info ); + + /* Now combine the freshly generated right node with previously */ + /* generated left ones */ + uint32_t internal_idx_offset = idx_offset; + uint32_t internal_idx = idx; + uint32_t internal_leaf = leaf_idx; + uint32_t h; /* The height we are in the Merkle tree */ + for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { + + /* Check if we hit the top of the tree */ + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[SPX_N], SPX_N ); + return; + } + + /* + * Check if the node we have is a part of the + * authentication path; if it is, write it out + */ + if ((internal_idx ^ internal_leaf) == 0x01) { + memcpy( &auth_path[ h * SPX_N ], + ¤t[SPX_N], + SPX_N ); + } + + /* + * Check if we're at a left child; if so, stop going up the stack + * Exception: if we've reached the end of the tree, keep on going + * (so we combine the last 4 nodes into the one root node in two + * more iterations) + */ + if ((internal_idx & 1) == 0 && idx < max_idx) { + break; + } + + /* Ok, we're at a right node */ + /* Now combine the left and right logical nodes together */ + + /* Set the address of the node we're creating. */ + internal_idx_offset >>= 1; + set_tree_height(tree_addr, h + 1); + set_tree_index(tree_addr, internal_idx / 2 + internal_idx_offset ); + + unsigned char *left = &stack[h * SPX_N]; + memcpy( ¤t[0], left, SPX_N ); + thash( ¤t[1 * SPX_N], + ¤t[0 * SPX_N], + 2, ctx, tree_addr); + } + + /* We've hit a left child; save the current for when we get the */ + /* corresponding right right */ + memcpy( &stack[h * SPX_N], ¤t[SPX_N], SPX_N); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/utilsx1.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/utilsx1.h new file mode 100644 index 0000000000..e911d17d53 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/utilsx1.h @@ -0,0 +1,27 @@ +#ifndef SPX_UTILSX4_H +#define SPX_UTILSX4_H + +#include + +#include "context.h" +#include "params.h" + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +#define treehashx1 SPX_NAMESPACE(treehashx1) +void treehashx1(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* Where to write the leaf */, + const spx_ctx * /* ctx */, + uint32_t addr_idx, void *info), + uint32_t tree_addrx4[8], void *info); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/wots.c b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/wots.c new file mode 100644 index 0000000000..249717aaa8 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/wots.c @@ -0,0 +1,108 @@ +#include +#include + +#include "wots.h" +#include "wotsx1.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "thash.h" +#include "utils.h" +#include "utilsx1.h" + +// TODO clarify address expectations, and make them more uniform. +// TODO i.e. do we expect types to be set already? +// TODO and do we expect modifications or copies? + +/** + * Computes the chaining function. + * out and in have to be n-byte arrays. + * + * Interprets in as start-th value of the chain. + * addr has to contain the address of the chain. + */ +static void gen_chain(unsigned char *out, const unsigned char *in, + unsigned int start, unsigned int steps, + const spx_ctx *ctx, uint32_t addr[8]) { + uint32_t i; + + /* Initialize out with the value at position 'start'. */ + memcpy(out, in, SPX_N); + + /* Iterate 'steps' calls to the hash function. */ + for (i = start; i < (start + steps) && i < SPX_WOTS_W; i++) { + set_hash_addr(addr, i); + thash(out, out, 1, ctx, addr); + } +} + +/** + * base_w algorithm as described in draft. + * Interprets an array of bytes as integers in base w. + * This only works when log_w is a divisor of 8. + */ +static void base_w(unsigned int *output, const int out_len, + const unsigned char *input) { + int in = 0; + int out = 0; + unsigned char total = 0; + int bits = 0; + int consumed; + + for (consumed = 0; consumed < out_len; consumed++) { + if (bits == 0) { + total = input[in]; + in++; + bits += 8; + } + bits -= SPX_WOTS_LOGW; + output[out] = (total >> bits) & (SPX_WOTS_W - 1); + out++; + } +} + +/* Computes the WOTS+ checksum over a message (in base_w). */ +static void wots_checksum(unsigned int *csum_base_w, + const unsigned int *msg_base_w) { + unsigned int csum = 0; + unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; + unsigned int i; + + /* Compute checksum. */ + for (i = 0; i < SPX_WOTS_LEN1; i++) { + csum += SPX_WOTS_W - 1 - msg_base_w[i]; + } + + /* Convert checksum to base_w. */ + /* Make sure expected empty zero bits are the least significant bits. */ + csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); + ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); + base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); +} + +/* Takes a message and derives the matching chain lengths. */ +void chain_lengths(unsigned int *lengths, const unsigned char *msg) { + base_w(lengths, SPX_WOTS_LEN1, msg); + wots_checksum(lengths + SPX_WOTS_LEN1, lengths); +} + +/** + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. + * + * Writes the computed public key to 'pk'. + */ +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]) { + unsigned int lengths[SPX_WOTS_LEN]; + uint32_t i; + + chain_lengths(lengths, msg); + + for (i = 0; i < SPX_WOTS_LEN; i++) { + set_chain_addr(addr, i); + gen_chain(pk + i * SPX_N, sig + i * SPX_N, + lengths[i], SPX_WOTS_W - 1 - lengths[i], ctx, addr); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/wots.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/wots.h new file mode 100644 index 0000000000..4e7692eeef --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/wots.h @@ -0,0 +1,25 @@ +#ifndef SPX_WOTS_H +#define SPX_WOTS_H + +#include + +#include "context.h" +#include "params.h" + +/** + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. + * + * Writes the computed public key to 'pk'. + */ +#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]); + +/* + * Compute the chain lengths needed for a given message hash + */ +#define chain_lengths SPX_NAMESPACE(chain_lengths) +void chain_lengths(unsigned int *lengths, const unsigned char *msg); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/wotsx1.c b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/wotsx1.c new file mode 100644 index 0000000000..3adec78dfb --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/wotsx1.c @@ -0,0 +1,76 @@ +#include +#include + +#include "wots.h" +#include "wotsx1.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "thash.h" +#include "utils.h" + +/* + * This generates a WOTS public key + * It also generates the WOTS signature if leaf_info indicates + * that we're signing with this WOTS key + */ +void wots_gen_leafx1(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info) { + struct leaf_info_x1 *info = v_info; + uint32_t *leaf_addr = info->leaf_addr; + uint32_t *pk_addr = info->pk_addr; + unsigned int i, k; + unsigned char pk_buffer[ SPX_WOTS_BYTES ]; + unsigned char *buffer; + uint32_t wots_k_mask; + + if (leaf_idx == info->wots_sign_leaf) { + /* We're traversing the leaf that's signing; generate the WOTS */ + /* signature */ + wots_k_mask = 0; + } else { + /* Nope, we're just generating pk's; turn off the signature logic */ + wots_k_mask = (uint32_t)~0; + } + + set_keypair_addr( leaf_addr, leaf_idx ); + set_keypair_addr( pk_addr, leaf_idx ); + + for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { + uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k to */ + /* the step if we're generating a signature, ~0 if we're not */ + + /* Start with the secret seed */ + set_chain_addr(leaf_addr, i); + set_hash_addr(leaf_addr, 0); + set_type(leaf_addr, SPX_ADDR_TYPE_WOTSPRF); + + prf_addr(buffer, ctx, leaf_addr); + + set_type(leaf_addr, SPX_ADDR_TYPE_WOTS); + + /* Iterate down the WOTS chain */ + for (k = 0;; k++) { + /* Check if this is the value that needs to be saved as a */ + /* part of the WOTS signature */ + if (k == wots_k) { + memcpy( info->wots_sig + i * SPX_N, buffer, SPX_N ); + } + + /* Check if we hit the top of the chain */ + if (k == SPX_WOTS_W - 1) { + break; + } + + /* Iterate one step on the chain */ + set_hash_addr(leaf_addr, k); + + thash(buffer, buffer, 1, ctx, leaf_addr); + } + } + + /* Do the final thash to generate the public keys */ + thash(dest, pk_buffer, SPX_WOTS_LEN, ctx, pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/wotsx1.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/wotsx1.h new file mode 100644 index 0000000000..e617929f96 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/wotsx1.h @@ -0,0 +1,39 @@ +#ifndef WOTSX1_H_ +#define WOTSX1_H_ + +#include + +#include "context.h" +#include "params.h" + +/* + * This is here to provide an interface to the internal wots_gen_leafx1 + * routine. While this routine is not referenced in the package outside of + * wots.c, it is called from the stand-alone benchmark code to characterize + * the performance + */ +struct leaf_info_x1 { + unsigned char *wots_sig; + uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ + uint32_t *wots_steps; + uint32_t leaf_addr[8]; + uint32_t pk_addr[8]; +}; + +/* Macro to set the leaf_info to something 'benign', that is, it would */ +/* run with the same time as it does during the real signing process */ +/* Used only by the benchmark code */ +#define INITIALIZE_LEAF_INFO_X1(info, addr, step_buffer) { \ + (info).wots_sig = 0; \ + (info).wots_sign_leaf = ~0; \ + (info).wots_steps = step_buffer; \ + memcpy( &(info).leaf_addr[0], (addr), 32 ); \ + memcpy( &(info).pk_addr[0], (addr), 32 ); \ + } + +#define wots_gen_leafx1 SPX_NAMESPACE(wots_gen_leafx1) +void wots_gen_leafx1(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info); + +#endif /* WOTSX1_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/LICENSE b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/LICENSE new file mode 100644 index 0000000000..670154e353 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/LICENSE @@ -0,0 +1,116 @@ +CC0 1.0 Universal + +Statement of Purpose + +The laws of most jurisdictions throughout the world automatically confer +exclusive Copyright and Related Rights (defined below) upon the creator and +subsequent owner(s) (each and all, an "owner") of an original work of +authorship and/or a database (each, a "Work"). + +Certain owners wish to permanently relinquish those rights to a Work for the +purpose of contributing to a commons of creative, cultural and scientific +works ("Commons") that the public can reliably and without fear of later +claims of infringement build upon, modify, incorporate in other works, reuse +and redistribute as freely as possible in any form whatsoever and for any +purposes, including without limitation commercial purposes. These owners may +contribute to the Commons to promote the ideal of a free culture and the +further production of creative, cultural and scientific works, or to gain +reputation or greater distribution for their Work in part through the use and +efforts of others. + +For these and/or other purposes and motivations, and without any expectation +of additional consideration or compensation, the person associating CC0 with a +Work (the "Affirmer"), to the extent that he or she is an owner of Copyright +and Related Rights in the Work, voluntarily elects to apply CC0 to the Work +and publicly distribute the Work under its terms, with knowledge of his or her +Copyright and Related Rights in the Work and the meaning and intended legal +effect of CC0 on those rights. + +1. Copyright and Related Rights. A Work made available under CC0 may be +protected by copyright and related or neighboring rights ("Copyright and +Related Rights"). Copyright and Related Rights include, but are not limited +to, the following: + + i. the right to reproduce, adapt, distribute, perform, display, communicate, + and translate a Work; + + ii. moral rights retained by the original author(s) and/or performer(s); + + iii. publicity and privacy rights pertaining to a person's image or likeness + depicted in a Work; + + iv. rights protecting against unfair competition in regards to a Work, + subject to the limitations in paragraph 4(a), below; + + v. rights protecting the extraction, dissemination, use and reuse of data in + a Work; + + vi. database rights (such as those arising under Directive 96/9/EC of the + European Parliament and of the Council of 11 March 1996 on the legal + protection of databases, and under any national implementation thereof, + including any amended or successor version of such directive); and + + vii. other similar, equivalent or corresponding rights throughout the world + based on applicable law or treaty, and any national implementations thereof. + +2. Waiver. To the greatest extent permitted by, but not in contravention of, +applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and +unconditionally waives, abandons, and surrenders all of Affirmer's Copyright +and Related Rights and associated claims and causes of action, whether now +known or unknown (including existing as well as future claims and causes of +action), in the Work (i) in all territories worldwide, (ii) for the maximum +duration provided by applicable law or treaty (including future time +extensions), (iii) in any current or future medium and for any number of +copies, and (iv) for any purpose whatsoever, including without limitation +commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes +the Waiver for the benefit of each member of the public at large and to the +detriment of Affirmer's heirs and successors, fully intending that such Waiver +shall not be subject to revocation, rescission, cancellation, termination, or +any other legal or equitable action to disrupt the quiet enjoyment of the Work +by the public as contemplated by Affirmer's express Statement of Purpose. + +3. Public License Fallback. Should any part of the Waiver for any reason be +judged legally invalid or ineffective under applicable law, then the Waiver +shall be preserved to the maximum extent permitted taking into account +Affirmer's express Statement of Purpose. In addition, to the extent the Waiver +is so judged Affirmer hereby grants to each affected person a royalty-free, +non transferable, non sublicensable, non exclusive, irrevocable and +unconditional license to exercise Affirmer's Copyright and Related Rights in +the Work (i) in all territories worldwide, (ii) for the maximum duration +provided by applicable law or treaty (including future time extensions), (iii) +in any current or future medium and for any number of copies, and (iv) for any +purpose whatsoever, including without limitation commercial, advertising or +promotional purposes (the "License"). The License shall be deemed effective as +of the date CC0 was applied by Affirmer to the Work. Should any part of the +License for any reason be judged legally invalid or ineffective under +applicable law, such partial invalidity or ineffectiveness shall not +invalidate the remainder of the License, and in such case Affirmer hereby +affirms that he or she will not (i) exercise any of his or her remaining +Copyright and Related Rights in the Work or (ii) assert any associated claims +and causes of action with respect to the Work, in either case contrary to +Affirmer's express Statement of Purpose. + +4. Limitations and Disclaimers. + + a. No trademark or patent rights held by Affirmer are waived, abandoned, + surrendered, licensed or otherwise affected by this document. + + b. Affirmer offers the Work as-is and makes no representations or warranties + of any kind concerning the Work, express, implied, statutory or otherwise, + including without limitation warranties of title, merchantability, fitness + for a particular purpose, non infringement, or the absence of latent or + other defects, accuracy, or the present or absence of errors, whether or not + discoverable, all to the greatest extent permissible under applicable law. + + c. Affirmer disclaims responsibility for clearing rights of other persons + that may apply to the Work or any use thereof, including without limitation + any person's Copyright and Related Rights in the Work. Further, Affirmer + disclaims responsibility for obtaining any necessary consents, permissions + or other rights required for any use of the Work. + + d. Affirmer understands and acknowledges that Creative Commons is not a + party to this document and has no duty or obligation with respect to this + CC0 or use of the Work. + +For more information, please see + diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/address.c b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/address.c new file mode 100644 index 0000000000..d49d9f3b6b --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/address.c @@ -0,0 +1,95 @@ +#include +#include + +#include "address.h" +#include "params.h" +#include "utils.h" + +/* + * Specify which level of Merkle tree (the "layer") we're working on + */ +void set_layer_addr(uint32_t addr[8], uint32_t layer) { + ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; +} + +/* + * Specify which Merkle tree within the level (the "tree address") we're working on + */ +void set_tree_addr(uint32_t addr[8], uint64_t tree) { + ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); +} + +/* + * Specify the reason we'll use this address structure for, that is, what + * hash will we compute with it. This is used so that unrelated types of + * hashes don't accidentally get the same address structure. The type will be + * one of the SPX_ADDR_TYPE constants + */ +void set_type(uint32_t addr[8], uint32_t type) { + ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; +} + +/* + * Copy the layer and tree fields of the address structure. This is used + * when we're doing multiple types of hashes within the same Merkle tree + */ +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); +} + +/* These functions are used for OTS addresses. */ + +/* + * Specify which Merkle leaf we're working on; that is, which OTS keypair + * we're talking about. + */ +void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { + /* We have > 256 OTS at the bottom of the Merkle tree; to specify */ + /* which one, we'd need to express it in two bytes */ + ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR2] = (unsigned char)(keypair >> 8); + ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; +} + +/* + * Copy the layer, tree and keypair fields of the address structure. This is + * used when we're doing multiple things within the same OTS keypair + */ +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); + ((unsigned char *)out)[SPX_OFFSET_KP_ADDR2] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR2]; + ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; +} + +/* + * Specify which Merkle chain within the OTS we're working with + * (the chain address) + */ +void set_chain_addr(uint32_t addr[8], uint32_t chain) { + ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; +} + +/* + * Specify where in the Merkle chain we are +* (the hash address) + */ +void set_hash_addr(uint32_t addr[8], uint32_t hash) { + ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; +} + +/* These functions are used for all hash tree addresses (including FORS). */ + +/* + * Specify the height of the node in the Merkle/FORS tree we are in + * (the tree height) + */ +void set_tree_height(uint32_t addr[8], uint32_t tree_height) { + ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; +} + +/* + * Specify the distance from the left edge of the node in the Merkle/FORS tree + * (the tree index) + */ +void set_tree_index(uint32_t addr[8], uint32_t tree_index) { + u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/address.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/address.h new file mode 100644 index 0000000000..24a84eb40c --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/address.h @@ -0,0 +1,52 @@ +#ifndef SPX_ADDRESS_H +#define SPX_ADDRESS_H + +#include + +#include "params.h" + +/* The hash types that are passed to set_type */ +#define SPX_ADDR_TYPE_WOTS 0 +#define SPX_ADDR_TYPE_WOTSPK 1 +#define SPX_ADDR_TYPE_HASHTREE 2 +#define SPX_ADDR_TYPE_FORSTREE 3 +#define SPX_ADDR_TYPE_FORSPK 4 +#define SPX_ADDR_TYPE_WOTSPRF 5 +#define SPX_ADDR_TYPE_FORSPRF 6 + +#define set_layer_addr SPX_NAMESPACE(set_layer_addr) +void set_layer_addr(uint32_t addr[8], uint32_t layer); + +#define set_tree_addr SPX_NAMESPACE(set_tree_addr) +void set_tree_addr(uint32_t addr[8], uint64_t tree); + +#define set_type SPX_NAMESPACE(set_type) +void set_type(uint32_t addr[8], uint32_t type); + +/* Copies the layer and tree part of one address into the other */ +#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); + +/* These functions are used for WOTS and FORS addresses. */ + +#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) +void set_keypair_addr(uint32_t addr[8], uint32_t keypair); + +#define set_chain_addr SPX_NAMESPACE(set_chain_addr) +void set_chain_addr(uint32_t addr[8], uint32_t chain); + +#define set_hash_addr SPX_NAMESPACE(set_hash_addr) +void set_hash_addr(uint32_t addr[8], uint32_t hash); + +#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); + +/* These functions are used for all hash tree addresses (including FORS). */ + +#define set_tree_height SPX_NAMESPACE(set_tree_height) +void set_tree_height(uint32_t addr[8], uint32_t tree_height); + +#define set_tree_index SPX_NAMESPACE(set_tree_index) +void set_tree_index(uint32_t addr[8], uint32_t tree_index); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/api.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/api.h new file mode 100644 index 0000000000..59e16cd734 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/api.h @@ -0,0 +1,77 @@ +#ifndef PQCLEAN_SPHINCSSHAKE192SSIMPLE_AARCH64_API_H +#define PQCLEAN_SPHINCSSHAKE192SSIMPLE_AARCH64_API_H + +#include +#include + +#define PQCLEAN_SPHINCSSHAKE192SSIMPLE_AARCH64_CRYPTO_ALGNAME "SPHINCS+-shake-192s-simple" + +#define PQCLEAN_SPHINCSSHAKE192SSIMPLE_AARCH64_CRYPTO_SECRETKEYBYTES 96 +#define PQCLEAN_SPHINCSSHAKE192SSIMPLE_AARCH64_CRYPTO_PUBLICKEYBYTES 48 +#define PQCLEAN_SPHINCSSHAKE192SSIMPLE_AARCH64_CRYPTO_BYTES 16224 + +#define PQCLEAN_SPHINCSSHAKE192SSIMPLE_AARCH64_CRYPTO_SEEDBYTES 72 + +/* + * Returns the length of a secret key, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE192SSIMPLE_AARCH64_crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE192SSIMPLE_AARCH64_crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE192SSIMPLE_AARCH64_crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE192SSIMPLE_AARCH64_crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +int PQCLEAN_SPHINCSSHAKE192SSIMPLE_AARCH64_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +int PQCLEAN_SPHINCSSHAKE192SSIMPLE_AARCH64_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +int PQCLEAN_SPHINCSSHAKE192SSIMPLE_AARCH64_crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +int PQCLEAN_SPHINCSSHAKE192SSIMPLE_AARCH64_crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, + const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +int PQCLEAN_SPHINCSSHAKE192SSIMPLE_AARCH64_crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +int PQCLEAN_SPHINCSSHAKE192SSIMPLE_AARCH64_crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/context.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/context.h new file mode 100644 index 0000000000..6e0a33f3b7 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/context.h @@ -0,0 +1,19 @@ +#ifndef SPX_CONTEXT_H +#define SPX_CONTEXT_H + +#include + +#include "params.h" + +typedef struct { + uint8_t pub_seed[SPX_N]; + uint8_t sk_seed[SPX_N]; +} spx_ctx; + +#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) +void initialize_hash_function(spx_ctx *ctx); + +#define free_hash_function SPX_NAMESPACE(free_hash_function) +void free_hash_function(spx_ctx *ctx); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/context_shake.c b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/context_shake.c new file mode 100644 index 0000000000..9614a103d3 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/context_shake.c @@ -0,0 +1,12 @@ +#include "context.h" + +/* For SHAKE256, there is no immediate reason to initialize at the start, + so this function is an empty operation. */ +void initialize_hash_function(spx_ctx *ctx) { + (void)ctx; /* Suppress an 'unused parameter' warning. */ +} + +// in case the hash function api is heap-based. +void free_hash_function(spx_ctx *ctx) { + (void)ctx; +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/f1600x2.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/f1600x2.h new file mode 100644 index 0000000000..70d1af9f14 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/f1600x2.h @@ -0,0 +1,11 @@ +#ifndef SPX_F1600X2_H +#define SPX_F1600X2_H + +#include + +extern uint64_t f1600_RC[24]; +extern void _f1600x2(uint64_t *a, uint64_t *rc); + +#define f1600x2(s) do {_f1600x2((s), f1600_RC);} while(0) + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/f1600x2.s b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/f1600x2.s new file mode 100644 index 0000000000..640ed791ed --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/f1600x2.s @@ -0,0 +1,143 @@ +# From https://github.com/bwesterb/armed-keccak + +.macro round + # Execute theta, but without xoring into the state yet. + # Compute parities p[i] = a[i] ^ a[5+i] ^ ... ^ a[20+i]. + eor3.16b v25, v0, v5, v10 + eor3.16b v26, v1, v6, v11 + eor3.16b v27, v2, v7, v12 + eor3.16b v28, v3, v8, v13 + eor3.16b v29, v4, v9, v14 + + eor3.16b v25, v25, v15, v20 + eor3.16b v26, v26, v16, v21 + eor3.16b v27, v27, v17, v22 + eor3.16b v28, v28, v18, v23 + eor3.16b v29, v29, v19, v24 + + # d[0] = rotl(p[1], 1) ^ p[4] + rax1.2d v30, v29, v26 + # d[3] = rotl(p[4], 1) ^ p[2] + rax1.2d v29, v27, v29 + # d[1] = rotl(p[2], 1) ^ p[0] + rax1.2d v27, v25, v27 + # d[4] = rotl(p[0], 1) ^ p[3] + rax1.2d v25, v28, v25 + # d[2] = rotl(p[3], 1) ^ p[1] + rax1.2d v28, v26, v28 + + # Xor parities from step theta into the state at the same time + # as executing rho and pi. + eor.16b v0, v0, v30 + mov.16b v31, v1 + xar.2d v1, v6, v27, 20 + xar.2d v6, v9, v25, 44 + xar.2d v9, v22, v28, 3 + xar.2d v22, v14, v25, 25 + xar.2d v14, v20, v30, 46 + xar.2d v20, v2, v28, 2 + xar.2d v2, v12, v28, 21 + xar.2d v12, v13, v29, 39 + xar.2d v13, v19, v25, 56 + xar.2d v19, v23, v29, 8 + xar.2d v23, v15, v30, 23 + xar.2d v15, v4, v25, 37 + xar.2d v4, v24, v25, 50 + xar.2d v24, v21, v27, 62 + xar.2d v21, v8, v29, 9 + xar.2d v8, v16, v27, 19 + xar.2d v16, v5, v30, 28 + xar.2d v5, v3, v29, 36 + xar.2d v3, v18, v29, 43 + xar.2d v18, v17, v28, 49 + xar.2d v17, v11, v27, 54 + xar.2d v11, v7, v28, 58 + xar.2d v7, v10, v30, 61 + xar.2d v10, v31, v27, 63 + + # Chi + bcax.16b v25, v0, v2, v1 + bcax.16b v26, v1, v3, v2 + bcax.16b v2, v2, v4, v3 + bcax.16b v3, v3, v0, v4 + bcax.16b v4, v4, v1, v0 + mov.16b v0, v25 + mov.16b v1, v26 + + bcax.16b v25, v5, v7, v6 + bcax.16b v26, v6, v8, v7 + bcax.16b v7, v7, v9, v8 + bcax.16b v8, v8, v5, v9 + bcax.16b v9, v9, v6, v5 + mov.16b v5, v25 + mov.16b v6, v26 + + bcax.16b v25, v10, v12, v11 + bcax.16b v26, v11, v13, v12 + bcax.16b v12, v12, v14, v13 + bcax.16b v13, v13, v10, v14 + bcax.16b v14, v14, v11, v10 + mov.16b v10, v25 + mov.16b v11, v26 + + bcax.16b v25, v15, v17, v16 + bcax.16b v26, v16, v18, v17 + bcax.16b v17, v17, v19, v18 + bcax.16b v18, v18, v15, v19 + bcax.16b v19, v19, v16, v15 + mov.16b v15, v25 + mov.16b v16, v26 + + bcax.16b v25, v20, v22, v21 + bcax.16b v26, v21, v23, v22 + bcax.16b v22, v22, v24, v23 + bcax.16b v23, v23, v20, v24 + bcax.16b v24, v24, v21, v20 + mov.16b v20, v25 + mov.16b v21, v26 + + # iota + ld1r {v25.2d}, [x1], #8 + eor.16b v0, v0, v25 +.endm + +.align 4 +.global __f1600x2 +__f1600x2: + stp d8, d9, [sp,#-16]! + stp d10, d11, [sp,#-16]! + stp d12, d13, [sp,#-16]! + stp d14, d15, [sp,#-16]! + + mov x2, x0 + mov x3, #24 + + ld1.2d {v0, v1, v2, v3}, [x0], #64 + ld1.2d {v4, v5, v6, v7}, [x0], #64 + ld1.2d {v8, v9, v10, v11}, [x0], #64 + ld1.2d {v12, v13, v14, v15}, [x0], #64 + ld1.2d {v16, v17, v18, v19}, [x0], #64 + ld1.2d {v20, v21, v22, v23}, [x0], #64 + ld1.2d {v24}, [x0] + +loop: + round + + subs x3, x3, #1 + cbnz x3, loop + + mov x0, x2 + st1.2d {v0, v1, v2, v3}, [x0], #64 + st1.2d {v4, v5, v6, v7}, [x0], #64 + st1.2d {v8, v9, v10, v11}, [x0], #64 + st1.2d {v12, v13, v14, v15}, [x0], #64 + st1.2d {v16, v17, v18, v19}, [x0], #64 + st1.2d {v20, v21, v22, v23}, [x0], #64 + st1.2d {v24}, [x0] + + ldp d14, d15, [sp], #16 + ldp d12, d13, [sp], #16 + ldp d10, d11, [sp], #16 + ldp d8, d9, [sp], #16 + + ret lr diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/f1600x2_const.c b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/f1600x2_const.c new file mode 100644 index 0000000000..e49c0ba149 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/f1600x2_const.c @@ -0,0 +1,30 @@ +#include "f1600x2.h" + +uint64_t f1600_RC[24] = { + 0x0000000000000001, + 0x0000000000008082, + 0x800000000000808A, + 0x8000000080008000, + 0x000000000000808B, + 0x0000000080000001, + 0x8000000080008081, + 0x8000000000008009, + 0x000000000000008A, + 0x0000000000000088, + 0x0000000080008009, + 0x000000008000000A, + 0x000000008000808B, + 0x800000000000008B, + 0x8000000000008089, + 0x8000000000008003, + 0x8000000000008002, + 0x8000000000000080, + 0x000000000000800A, + 0x800000008000000A, + 0x8000000080008081, + 0x8000000000008080, + 0x0000000080000001, + 0x8000000080008008, +}; + + diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/fips202x2.c b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/fips202x2.c new file mode 100644 index 0000000000..4718c343bc --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/fips202x2.c @@ -0,0 +1,148 @@ +#include +#include + +#include "fips202x2.h" +#include "f1600x2.h" +#include "fips202.h" + +uint64_t load64(const unsigned char *x) { + unsigned long long r = 0, i; + + for (i = 0; i < 8; ++i) { + r |= (unsigned long long)x[i] << 8 * i; + } + return r; +} + +void store64(uint8_t *x, uint64_t u) { + unsigned int i; + + for (i = 0; i < 8; ++i) { + x[i] = (uint8_t)u; + u >>= 8; + } +} + +static void keccak_absorb2x(uint64_t *s, + unsigned int r, + const unsigned char *m0, + const unsigned char *m1, + unsigned long long int mlen, + unsigned char p) { + unsigned long long i; + unsigned char t0[200]; + unsigned char t1[200]; + + while (mlen >= r) { + for (i = 0; i < r / 8; ++i) { + s[2 * i + 0] ^= load64(m0 + 8 * i); + s[2 * i + 1] ^= load64(m1 + 8 * i); + } + + f1600x2(s); + mlen -= r; + m0 += r; + m1 += r; + } + + for (i = 0; i < r; ++i) { + t0[i] = 0; + t1[i] = 0; + } + for (i = 0; i < mlen; ++i) { + t0[i] = m0[i]; + t1[i] = m1[i]; + } + + t0[i] = p; + t1[i] = p; + + t0[r - 1] |= 128; + t1[r - 1] |= 128; + + for (i = 0; i < r / 8; ++i) { + s[2 * i + 0] ^= load64(t0 + 8 * i); + s[2 * i + 1] ^= load64(t1 + 8 * i); + } +} + + +static void keccak_squeezeblocks2x(unsigned char *h0, + unsigned char *h1, + unsigned long long int nblocks, + uint64_t *s, + unsigned int r) { + unsigned int i; + + while (nblocks > 0) { + f1600x2(s); + for (i = 0; i < (r >> 3); i++) { + store64(h0 + 8 * i, s[2 * i + 0]); + store64(h1 + 8 * i, s[2 * i + 1]); + } + h0 += r; + h1 += r; + nblocks--; + } +} + + + +void shake128x2(unsigned char *out0, + unsigned char *out1, + unsigned long long outlen, + unsigned char *in0, + unsigned char *in1, + unsigned long long inlen) { + uint64_t s[50] = {0}; + unsigned char t0[SHAKE128_RATE]; + unsigned char t1[SHAKE128_RATE]; + unsigned int i; + + /* absorb 4 message of identical length in parallel */ + keccak_absorb2x(s, SHAKE128_RATE, in0, in1, inlen, 0x1F); + + /* Squeeze output */ + keccak_squeezeblocks2x(out0, out1, outlen / SHAKE128_RATE, s, SHAKE128_RATE); + + out0 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; + out1 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; + + if (outlen % SHAKE128_RATE) { + keccak_squeezeblocks2x(t0, t1, 1, s, SHAKE128_RATE); + for (i = 0; i < outlen % SHAKE128_RATE; i++) { + out0[i] = t0[i]; + out1[i] = t1[i]; + } + } +} + + +void shake256x2(unsigned char *out0, + unsigned char *out1, + unsigned long long outlen, + unsigned char *in0, + unsigned char *in1, + unsigned long long inlen) { + uint64_t s[50] = {0}; + unsigned char t0[SHAKE256_RATE]; + unsigned char t1[SHAKE256_RATE]; + unsigned int i; + + /* absorb 2 message of identical length in parallel */ + keccak_absorb2x(s, SHAKE256_RATE, in0, in1, inlen, 0x1F); + + /* Squeeze output */ + keccak_squeezeblocks2x(out0, out1, outlen / SHAKE256_RATE, s, SHAKE256_RATE); + + out0 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; + out1 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; + + if (outlen % SHAKE256_RATE) { + keccak_squeezeblocks2x(t0, t1, 1, s, SHAKE256_RATE); + for (i = 0; i < outlen % SHAKE256_RATE; i++) { + out0[i] = t0[i]; + out1[i] = t1[i]; + } + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/fips202x2.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/fips202x2.h new file mode 100644 index 0000000000..7ba58b35d8 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/fips202x2.h @@ -0,0 +1,24 @@ +#ifndef SPX_FIPS202X2_H +#define SPX_FIPS202X2_H + +#include + +uint64_t load64(const unsigned char *x); +void store64(uint8_t *x, uint64_t u); + + +void shake128x2(unsigned char *out0, + unsigned char *out1, + unsigned long long outlen, + unsigned char *in0, + unsigned char *in1, + unsigned long long inlen); + +void shake256x2(unsigned char *out0, + unsigned char *out1, + unsigned long long outlen, + unsigned char *in0, + unsigned char *in1, + unsigned long long inlen); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/fors.c b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/fors.c new file mode 100644 index 0000000000..39193d04e2 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/fors.c @@ -0,0 +1,191 @@ +#include +#include +#include + +#include "fors.h" + +#include "address.h" +#include "hash.h" +#include "hashx2.h" +#include "thash.h" +#include "thashx2.h" +#include "utils.h" +#include "utilsx2.h" + +static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + prf_addr(sk, ctx, fors_leaf_addr); +} + +static void fors_gen_skx2(unsigned char *sk0, + unsigned char *sk1, + const spx_ctx *ctx, + uint32_t fors_leaf_addrx2[2 * 8]) { + prf_addrx2(sk0, sk1, + ctx, fors_leaf_addrx2); +} + +static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, + const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + thash(leaf, sk, 1, ctx, fors_leaf_addr); +} + +static void fors_sk_to_leafx2(unsigned char *leaf0, + unsigned char *leaf1, + const unsigned char *sk0, + const unsigned char *sk1, + const spx_ctx *ctx, + uint32_t fors_leaf_addrx2[2 * 8]) { + thashx2(leaf0, leaf1, + sk0, sk1, + 1, ctx, fors_leaf_addrx2); +} + +struct fors_gen_leaf_info { + uint32_t leaf_addrx[2 * 8]; +}; + +static void fors_gen_leafx2(unsigned char *leaf, + const spx_ctx *ctx, + uint32_t addr_idx, void *info) { + struct fors_gen_leaf_info *fors_info = info; + uint32_t *fors_leaf_addrx2 = fors_info->leaf_addrx; + unsigned int j; + + /* Only set the parts that the caller doesn't set */ + for (j = 0; j < 2; j++) { + set_tree_index(fors_leaf_addrx2 + j * 8, addr_idx + j); + set_type(fors_leaf_addrx2 + j * 8, SPX_ADDR_TYPE_FORSPRF); + } + + fors_gen_skx2(leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + ctx, fors_leaf_addrx2); + + for (j = 0; j < 2; j++) { + set_type(fors_leaf_addrx2 + j * 8, SPX_ADDR_TYPE_FORSTREE); + } + + fors_sk_to_leafx2(leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + ctx, fors_leaf_addrx2); +} + +/** + * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + * Assumes indices has space for SPX_FORS_TREES integers. + */ +static void message_to_indices(uint32_t *indices, const unsigned char *m) { + unsigned int i, j; + unsigned int offset = 0; + + for (i = 0; i < SPX_FORS_TREES; i++) { + indices[i] = 0; + for (j = 0; j < SPX_FORS_HEIGHT; j++) { + indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); + offset++; + } + } +} + +/** + * Signs a message m, deriving the secret key from sk_seed and the FTS address. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + uint32_t fors_tree_addr[2 * 8] = {0}; + struct fors_gen_leaf_info fors_info = {0}; + uint32_t *fors_leaf_addr = fors_info.leaf_addrx; + uint32_t fors_pk_addr[8] = {0}; + uint32_t idx_offset; + unsigned int i; + + for (i = 0; i < 2; i++) { + copy_keypair_addr(fors_tree_addr + 8 * i, fors_addr); + set_type(fors_tree_addr + 8 * i, SPX_ADDR_TYPE_FORSTREE); + copy_keypair_addr(fors_leaf_addr + 8 * i, fors_addr); + } + copy_keypair_addr(fors_pk_addr, fors_addr); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); + + message_to_indices(indices, m); + + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); + + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + + /* Include the secret key part that produces the selected leaf node. */ + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); + fors_gen_sk(sig, ctx, fors_tree_addr); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + sig += SPX_N; + + /* Compute the authentication path for this leaf node. */ + treehashx2(roots + i * SPX_N, sig, ctx, + indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx2, + fors_tree_addr, &fors_info); + + sig += SPX_N * SPX_FORS_HEIGHT; + } + + /* Hash horizontally across all tree roots to derive the public key. */ + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); +} + +/** + * Derives the FORS public key from a signature. + * This can be used for verification by comparing to a known public key, or to + * subsequently verify a signature on the derived public key. The latter is the + * typical use-case when used as an FTS below an OTS in a hypertree. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + unsigned char leaf[SPX_N]; + uint32_t fors_tree_addr[8] = {0}; + uint32_t fors_pk_addr[8] = {0}; + uint32_t idx_offset; + unsigned int i; + + copy_keypair_addr(fors_tree_addr, fors_addr); + copy_keypair_addr(fors_pk_addr, fors_addr); + + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); + + message_to_indices(indices, m); + + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); + + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + + /* Derive the leaf from the included secret key part. */ + fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); + sig += SPX_N; + + /* Derive the corresponding root node of this tree. */ + compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, + sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); + sig += SPX_N * SPX_FORS_HEIGHT; + } + + /* Hash horizontally across all tree roots to derive the public key. */ + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/fors.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/fors.h new file mode 100644 index 0000000000..509140a178 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/fors.h @@ -0,0 +1,32 @@ +#ifndef SPX_FORS_H +#define SPX_FORS_H + +#include + +#include "context.h" +#include "params.h" + +/** + * Signs a message m, deriving the secret key from sk_seed and the FTS address. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +#define fors_sign SPX_NAMESPACE(fors_sign) +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); + +/** + * Derives the FORS public key from a signature. + * This can be used for verification by comparing to a known public key, or to + * subsequently verify a signature on the derived public key. The latter is the + * typical use-case when used as an FTS below an OTS in a hypertree. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/hash.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/hash.h new file mode 100644 index 0000000000..f7c87d4c3c --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/hash.h @@ -0,0 +1,28 @@ +#ifndef SPX_HASH_H +#define SPX_HASH_H + +#include +#include + +#include "context.h" +#include "params.h" + +#define prf_addr SPX_NAMESPACE(prf_addr) +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]); + +#define gen_message_random SPX_NAMESPACE(gen_message_random) +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); + +#define hash_message SPX_NAMESPACE(hash_message) +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); + + + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/hash_shake.c b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/hash_shake.c new file mode 100644 index 0000000000..ff5e7ec918 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/hash_shake.c @@ -0,0 +1,83 @@ +#include +#include + +#include "hash.h" + +#include "address.h" +#include "fips202.h" +#include "params.h" +#include "utils.h" + +/* + * Computes PRF(pk_seed, sk_seed, addr) + */ +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]) { + unsigned char buf[2 * SPX_N + SPX_ADDR_BYTES]; + + memcpy(buf, ctx->pub_seed, SPX_N); + memcpy(buf + SPX_N, addr, SPX_ADDR_BYTES); + memcpy(buf + SPX_N + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); + + shake256(out, SPX_N, buf, 2 * SPX_N + SPX_ADDR_BYTES); +} + +/** + * Computes the message-dependent randomness R, using a secret seed and an + * optional randomization value as well as the message. + */ +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { + (void)ctx; + shake256incctx s_inc; + + shake256_inc_init(&s_inc); + shake256_inc_absorb(&s_inc, sk_prf, SPX_N); + shake256_inc_absorb(&s_inc, optrand, SPX_N); + shake256_inc_absorb(&s_inc, m, mlen); + shake256_inc_finalize(&s_inc); + shake256_inc_squeeze(R, SPX_N, &s_inc); + shake256_inc_ctx_release(&s_inc); +} + +/** + * Computes the message hash using R, the public key, and the message. + * Outputs the message digest and the index of the leaf. The index is split in + * the tree index and the leaf index, for convenient copying to an address. + */ +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { + (void)ctx; +#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) +#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) +#define SPX_LEAF_BITS SPX_TREE_HEIGHT +#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) +#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) + + unsigned char buf[SPX_DGST_BYTES]; + unsigned char *bufp = buf; + shake256incctx s_inc; + + shake256_inc_init(&s_inc); + shake256_inc_absorb(&s_inc, R, SPX_N); + shake256_inc_absorb(&s_inc, pk, SPX_PK_BYTES); + shake256_inc_absorb(&s_inc, m, mlen); + shake256_inc_finalize(&s_inc); + shake256_inc_squeeze(buf, SPX_DGST_BYTES, &s_inc); + shake256_inc_ctx_release(&s_inc); + + memcpy(digest, bufp, SPX_FORS_MSG_BYTES); + bufp += SPX_FORS_MSG_BYTES; + + + *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); + *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); + bufp += SPX_TREE_BYTES; + + *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); + *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/hash_shakex2.c b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/hash_shakex2.c new file mode 100644 index 0000000000..99571916a2 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/hash_shakex2.c @@ -0,0 +1,52 @@ +#include +#include + +#include "hashx2.h" + +#include "address.h" +#include "f1600x2.h" +#include "fips202x2.h" +#include "params.h" + +/* + * 2-way parallel version of prf_addr; takes 2x as much input and output + */ +void prf_addrx2(unsigned char *out0, + unsigned char *out1, + const spx_ctx *ctx, + const uint32_t addrx2[2 * 8]) { + /* As we write and read only a few quadwords, it is more efficient to + * build and extract from the fourway SHAKE256 state by hand. */ + uint64_t state[50] = {0}; + + for (int i = 0; i < SPX_N / 8; i++) { + uint64_t x = load64(ctx->pub_seed + 8 * i); + state[2 * i] = x; + state[2 * i + 1] = x; + } + for (int i = 0; i < 4; i++) { + state[2 * (SPX_N / 8 + i)] = (((uint64_t)addrx2[1 + 2 * i]) << 32) + | (uint64_t)addrx2[2 * i]; + state[2 * (SPX_N / 8 + i) + 1] = (((uint64_t)addrx2[8 + 1 + 2 * i]) << 32) + | (uint64_t)addrx2[8 + 2 * i]; + } + for (int i = 0; i < SPX_N / 8; i++) { + uint64_t x = load64(ctx->sk_seed + 8 * i); + state[2 * (SPX_N / 8 + i + 4)] = x; + state[2 * (SPX_N / 8 + i + 4) + 1] = x; + } + + /* SHAKE domain separator and padding. */ + state[2 * (SPX_N / 4 + 4)] = 0x1f; + state[2 * (SPX_N / 4 + 4) + 1] = 0x1f; + + state[2 * 16] = 0x80ULL << 56; + state[2 * 16 + 1] = 0x80ULL << 56; + + f1600x2(state); + + for (int i = 0; i < SPX_N / 8; i++) { + store64(out0 + 8 * i, state[2 * i]); + store64(out1 + 8 * i, state[2 * i + 1]); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/hashx2.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/hashx2.h new file mode 100644 index 0000000000..99b8873a9b --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/hashx2.h @@ -0,0 +1,14 @@ +#ifndef SPX_HASHX2_H +#define SPX_HASHX2_H + +#include "context.h" +#include "params.h" +#include + +#define prf_addrx2 SPX_NAMESPACE(prf_addrx2) +void prf_addrx2(unsigned char *out0, + unsigned char *out1, + const spx_ctx *ctx, + const uint32_t addrx2[2 * 8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/merkle.c b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/merkle.c new file mode 100644 index 0000000000..c94ee23939 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/merkle.c @@ -0,0 +1,64 @@ +#include +#include + +#include "merkle.h" + +#include "address.h" +#include "params.h" +#include "utils.h" +#include "utilsx2.h" +#include "wots.h" +#include "wotsx2.h" + +/* + * This generates a Merkle signature (WOTS signature followed by the Merkle + * authentication path). + */ +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf) { + unsigned char *auth_path = sig + SPX_WOTS_BYTES; + uint32_t tree_addrx2[2 * 8] = { 0 }; + int j; + struct leaf_info_x2 info = { 0 }; + unsigned steps[ SPX_WOTS_LEN ]; + + info.wots_sig = sig; + chain_lengths(steps, root); + info.wots_steps = steps; + + for (j = 0; j < 2; j++) { + set_type(&tree_addrx2[8 * j], SPX_ADDR_TYPE_HASHTREE); + set_type(&info.leaf_addr[8 * j], SPX_ADDR_TYPE_WOTS); + set_type(&info.pk_addr[8 * j], SPX_ADDR_TYPE_WOTSPK); + copy_subtree_addr(&tree_addrx2[8 * j], tree_addr); + copy_subtree_addr(&info.leaf_addr[8 * j], wots_addr); + copy_subtree_addr(&info.pk_addr[8 * j], wots_addr); + } + + info.wots_sign_leaf = idx_leaf; + + treehashx2(root, auth_path, ctx, + idx_leaf, 0, + SPX_TREE_HEIGHT, + wots_gen_leafx2, + tree_addrx2, &info); +} + +/* Compute root node of the top-most subtree. */ +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { + /* We do not need the auth path in key generation, but it simplifies the + code to have just one treehash routine that computes both root and path + in one function. */ + unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; + uint32_t top_tree_addr[8] = {0}; + uint32_t wots_addr[8] = {0}; + + set_layer_addr(top_tree_addr, SPX_D - 1); + set_layer_addr(wots_addr, SPX_D - 1); + + merkle_sign(auth_path, root, ctx, + wots_addr, top_tree_addr, + ~0 /* ~0 means "don't bother generating an auth path */ ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/merkle.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/merkle.h new file mode 100644 index 0000000000..769cf2e970 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/merkle.h @@ -0,0 +1,21 @@ +#ifndef MERKLE_H_ +#define MERKLE_H_ + +#include + +#include "context.h" +#include "params.h" + +/* Generate a Merkle signature (WOTS signature followed by the Merkle */ +/* authentication path) */ +#define merkle_sign SPX_NAMESPACE(merkle_sign) +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf); + +/* Compute the root node of the top-most subtree. */ +#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); + +#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/nistapi.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/nistapi.h new file mode 100644 index 0000000000..3cb71afad4 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/nistapi.h @@ -0,0 +1,87 @@ +#ifndef SPX_API_H +#define SPX_API_H + +#include +#include + +#include "params.h" + +#define CRYPTO_ALGNAME "SPHINCS+" + +#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES +#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES +#define CRYPTO_BYTES SPX_BYTES +#define CRYPTO_SEEDBYTES (3*SPX_N) + +/* + * Returns the length of a secret key, in bytes + */ +#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) +size_t crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) +size_t crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) +size_t crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) +size_t crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +#define crypto_sign SPX_NAMESPACE(crypto_sign) +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/params.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/params.h new file mode 100644 index 0000000000..650f74916a --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/params.h @@ -0,0 +1,56 @@ +#ifndef SPX_PARAMS_H +#define SPX_PARAMS_H + +#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSSHAKE192SSIMPLE_AARCH64_##s + +/* Hash output length in bytes. */ +#define SPX_N 24 +/* Height of the hypertree. */ +#define SPX_FULL_HEIGHT 63 +/* Number of subtree layer. */ +#define SPX_D 7 +/* FORS tree dimensions. */ +#define SPX_FORS_HEIGHT 14 +#define SPX_FORS_TREES 17 +/* Winternitz parameter, */ +#define SPX_WOTS_W 16 + +/* The hash function is defined by linking a different hash.c file, as opposed + to setting a #define constant. */ + +/* For clarity */ +#define SPX_ADDR_BYTES 32 + +/* WOTS parameters. */ +#define SPX_WOTS_LOGW 4 + +#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) + +/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ +#define SPX_WOTS_LEN2 3 + +#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) +#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) +#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES + +/* Subtree size. */ +#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) + +//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT +// #error SPX_D should always divide SPX_FULL_HEIGHT +//#endif + +/* FORS parameters. */ +#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) +#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) +#define SPX_FORS_PK_BYTES SPX_N + +/* Resulting SPX sizes. */ +#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ + SPX_FULL_HEIGHT * SPX_N) +#define SPX_PK_BYTES (2 * SPX_N) +#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) + +#include "shake_offsets.h" + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/shake_offsets.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/shake_offsets.h new file mode 100644 index 0000000000..6b28d95d91 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/shake_offsets.h @@ -0,0 +1,21 @@ +#ifndef SHAKE_OFFSETS_H_ +#define SHAKE_OFFSETS_H_ + +/* + * Offsets of various fields in the address structure when we use SHAKE as + * the Sphincs+ hash function + */ + +#define SPX_OFFSET_LAYER 3 /* The byte used to specify the Merkle tree layer */ +#define SPX_OFFSET_TREE 8 /* The start of the 8 byte field used to specify the tree */ +#define SPX_OFFSET_TYPE 19 /* The byte used to specify the hash type (reason) */ +#define SPX_OFFSET_KP_ADDR2 22 /* The high byte used to specify the key pair (which one-time signature) */ +#define SPX_OFFSET_KP_ADDR1 23 /* The low byte used to specify the key pair */ +#define SPX_OFFSET_CHAIN_ADDR 27 /* The byte used to specify the chain address (which Winternitz chain) */ +#define SPX_OFFSET_HASH_ADDR 31 /* The byte used to specify the hash address (where in the Winternitz chain) */ +#define SPX_OFFSET_TREE_HGT 27 /* The byte used to specify the height of this node in the FORS or Merkle tree */ +#define SPX_OFFSET_TREE_INDEX 28 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ + +#define SPX_SHAKE 1 + +#endif /* SHAKE_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/sign.c b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/sign.c new file mode 100644 index 0000000000..9d0c7d1b22 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/sign.c @@ -0,0 +1,286 @@ +#include +#include +#include + +#include "address.h" +#include "context.h" +#include "fors.h" +#include "hash.h" +#include "merkle.h" +#include "nistapi.h" +#include "params.h" +#include "randombytes.h" +#include "thash.h" +#include "utils.h" +#include "wots.h" + +/* + * Returns the length of a secret key, in bytes + */ +size_t crypto_sign_secretkeybytes(void) { + return CRYPTO_SECRETKEYBYTES; +} + +/* + * Returns the length of a public key, in bytes + */ +size_t crypto_sign_publickeybytes(void) { + return CRYPTO_PUBLICKEYBYTES; +} + +/* + * Returns the length of a signature, in bytes + */ +size_t crypto_sign_bytes(void) { + return CRYPTO_BYTES; +} + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +size_t crypto_sign_seedbytes(void) { + return CRYPTO_SEEDBYTES; +} + +/* + * Generates an SPX key pair given a seed of length + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [PUB_SEED || root] + */ +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed) { + spx_ctx ctx; + + /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ + memcpy(sk, seed, CRYPTO_SEEDBYTES); + + memcpy(pk, sk + 2 * SPX_N, SPX_N); + + memcpy(ctx.pub_seed, pk, SPX_N); + memcpy(ctx.sk_seed, sk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + /* Compute root node of the top-most subtree. */ + merkle_gen_root(sk + 3 * SPX_N, &ctx); + + // cleanup + free_hash_function(&ctx); + + memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); + + return 0; +} + +/* + * Generates an SPX key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [PUB_SEED || root] + */ +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { + uint8_t seed[CRYPTO_SEEDBYTES]; + randombytes(seed, CRYPTO_SEEDBYTES); + crypto_sign_seed_keypair(pk, sk, seed); + + return 0; +} + +/** + * Returns an array containing a detached signature. + */ +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk) { + spx_ctx ctx; + + const uint8_t *sk_prf = sk + SPX_N; + const uint8_t *pk = sk + 2 * SPX_N; + + uint8_t optrand[SPX_N]; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t root[SPX_N]; + uint32_t i; + uint64_t tree; + uint32_t idx_leaf; + uint32_t wots_addr[8] = {0}; + uint32_t tree_addr[8] = {0}; + + memcpy(ctx.sk_seed, sk, SPX_N); + memcpy(ctx.pub_seed, pk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + + /* Optionally, signing can be made non-deterministic using optrand. + This can help counter side-channel attacks that would benefit from + getting a large number of traces when the signer uses the same nodes. */ + randombytes(optrand, SPX_N); + /* Compute the digest randomization value. */ + gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); + + /* Derive the message digest and leaf index from R, PK and M. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; + + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); + + /* Sign the message hash using FORS. */ + fors_sign(sig, root, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); + sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; + + /* Update the indices for the next layer. */ + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; + } + + free_hash_function(&ctx); + + *siglen = SPX_BYTES; + + return 0; +} + +/** + * Verifies a detached signature and message under a given public key. + */ +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk) { + spx_ctx ctx; + const uint8_t *pub_root = pk + SPX_N; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t wots_pk[SPX_WOTS_BYTES]; + uint8_t root[SPX_N]; + uint8_t leaf[SPX_N]; + unsigned int i; + uint64_t tree; + uint32_t idx_leaf; + uint32_t wots_addr[8] = {0}; + uint32_t tree_addr[8] = {0}; + uint32_t wots_pk_addr[8] = {0}; + + if (siglen != SPX_BYTES) { + return -1; + } + + memcpy(ctx.pub_seed, pk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); + + /* Derive the message digest and leaf index from R || PK || M. */ + /* The additional SPX_N is a result of the hash domain separator. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; + + /* Layer correctly defaults to 0, so no need to set_layer_addr */ + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); + + fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + /* For each subtree.. */ + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + copy_keypair_addr(wots_pk_addr, wots_addr); + + /* The WOTS public key is only correct if the signature was correct. */ + /* Initially, root is the FORS pk, but on subsequent iterations it is + the root of the subtree below the currently processed subtree. */ + wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); + sig += SPX_WOTS_BYTES; + + /* Compute the leaf node using the WOTS public key. */ + thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); + + /* Compute the root node of this subtree. */ + compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, + &ctx, tree_addr); + sig += SPX_TREE_HEIGHT * SPX_N; + + /* Update the indices for the next layer. */ + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; + } + + // cleanup + free_hash_function(&ctx); + + /* Check if the root node equals the root node in the public key. */ + if (memcmp(root, pub_root, SPX_N) != 0) { + return -1; + } + + return 0; +} + + +/** + * Returns an array containing the signature followed by the message. + */ +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk) { + size_t siglen; + + crypto_sign_signature(sm, &siglen, m, mlen, sk); + + memmove(sm + SPX_BYTES, m, mlen); + *smlen = siglen + mlen; + + return 0; +} + +/** + * Verifies a given signature-message pair under a given public key. + */ +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk) { + /* The API caller does not necessarily know what size a signature should be + but SPHINCS+ signatures are always exactly SPX_BYTES. */ + if (smlen < SPX_BYTES) { + memset(m, 0, smlen); + *mlen = 0; + return -1; + } + + *mlen = smlen - SPX_BYTES; + + if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { + memset(m, 0, smlen); + *mlen = 0; + return -1; + } + + /* If verification was successful, move the message to the right place. */ + memmove(m, sm + SPX_BYTES, *mlen); + + return 0; +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/thash.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/thash.h new file mode 100644 index 0000000000..8687ccfb4d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/thash.h @@ -0,0 +1,13 @@ +#ifndef SPX_THASH_H +#define SPX_THASH_H + +#include "context.h" +#include "params.h" + +#include + +#define thash SPX_NAMESPACE(thash) +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/thash_shake_simplex2.c b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/thash_shake_simplex2.c new file mode 100644 index 0000000000..892e453690 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/thash_shake_simplex2.c @@ -0,0 +1,83 @@ +#include +#include + +#include "thash.h" +#include "thashx2.h" + +#include "address.h" +#include "params.h" +#include "utils.h" + +#include "f1600x2.h" +#include "fips202x2.h" + + +void thash(unsigned char *out, + const unsigned char *in, + unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]) { + uint32_t addrx2 [2 * 8] = { + addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], addr[6], addr[7], + addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], addr[6], addr[7] + }; + thashx2(out, out, in, in, inblocks, ctx, addrx2); +} + +/** + * 2-way parallel version of thash; takes 2x as much input and output + */ +void thashx2(unsigned char *out0, + unsigned char *out1, + const unsigned char *in0, + const unsigned char *in1, + unsigned int inblocks, + const spx_ctx *ctx, uint32_t addrx2[2 * 8]) { + if (inblocks == 1 || inblocks == 2) { + /* As we write and read only a few quadwords, it is more efficient to + * build and extract from the twoway SHAKE256 state by hand. */ + uint64_t state[50] = {0}; + for (int i = 0; i < SPX_N / 8; i++) { + uint64_t x = load64(ctx->pub_seed + 8 * i); + state[2 * i] = x; + state[2 * i + 1] = x; + } + for (int i = 0; i < 4; i++) { + state[2 * (SPX_N / 8 + i)] = (((uint64_t)addrx2[1 + 2 * i]) << 32) + | (uint64_t)addrx2[2 * i]; + state[2 * (SPX_N / 8 + i) + 1] = (((uint64_t)addrx2[8 + 1 + 2 * i]) << 32) + | (uint64_t)addrx2[8 + 2 * i]; + } + + for (unsigned int i = 0; i < (SPX_N / 8) * inblocks; i++) { + state[2 * (SPX_N / 8 + 4 + i)] = load64(in0 + 8 * i); + state[2 * (SPX_N / 8 + 4 + i) + 1] = load64(in1 + 8 * i); + } + + /* Domain separator and padding. */ + state[2 * 16] = 0x80ULL << 56; + state[2 * 16 + 1] = 0x80ULL << 56; + + state[2 * ((SPX_N / 8) * (1 + inblocks) + 4)] ^= 0x1f; + state[2 * ((SPX_N / 8) * (1 + inblocks) + 4) + 1] ^= 0x1f; + + f1600x2(state); + + for (int i = 0; i < SPX_N / 8; i++) { + store64(out0 + 8 * i, state[2 * i]); + store64(out1 + 8 * i, state[2 * i + 1]); + } + } else { + PQCLEAN_VLA(unsigned char, buf0, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, buf1, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); + + memcpy(buf0, ctx->pub_seed, SPX_N); + memcpy(buf1, ctx->pub_seed, SPX_N); + memcpy(buf0 + SPX_N, addrx2 + 0 * 8, SPX_ADDR_BYTES); + memcpy(buf1 + SPX_N, addrx2 + 1 * 8, SPX_ADDR_BYTES); + memcpy(buf0 + SPX_N + SPX_ADDR_BYTES, in0, inblocks * SPX_N); + memcpy(buf1 + SPX_N + SPX_ADDR_BYTES, in1, inblocks * SPX_N); + + shake256x2(out0, out1, SPX_N, + buf0, buf1, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/thashx2.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/thashx2.h new file mode 100644 index 0000000000..040375e618 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/thashx2.h @@ -0,0 +1,16 @@ +#ifndef SPX_THASHX2_H +#define SPX_THASHX2_H + +#include "context.h" +#include "params.h" +#include + +#define thashx2 SPX_NAMESPACE(thashx2) +void thashx2(unsigned char *out0, + unsigned char *out1, + const unsigned char *in0, + const unsigned char *in1, + unsigned int inblocks, + const spx_ctx *ctx, uint32_t addrx2[2 * 8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/utils.c b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/utils.c new file mode 100644 index 0000000000..177b541fb9 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/utils.c @@ -0,0 +1,148 @@ +#include + +#include "utils.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "thash.h" + +/** + * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. + */ +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in) { + int i; + + /* Iterate over out in decreasing order, for big-endianness. */ + for (i = (signed int)outlen - 1; i >= 0; i--) { + out[i] = in & 0xff; + in = in >> 8; + } +} + +void u32_to_bytes(unsigned char *out, uint32_t in) { + out[0] = (unsigned char)(in >> 24); + out[1] = (unsigned char)(in >> 16); + out[2] = (unsigned char)(in >> 8); + out[3] = (unsigned char)in; +} + +/** + * Converts the inlen bytes in 'in' from big-endian byte order to an integer. + */ +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { + unsigned long long retval = 0; + unsigned int i; + + for (i = 0; i < inlen; i++) { + retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); + } + return retval; +} + +/** + * Computes a root node given a leaf and an auth path. + * Expects address to be complete other than the tree_height and tree_index. + */ +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]) { + uint32_t i; + unsigned char buffer[2 * SPX_N]; + + /* If leaf_idx is odd (last bit = 1), current path element is a right child + and auth_path has to go left. Otherwise it is the other way around. */ + if (leaf_idx & 1) { + memcpy(buffer + SPX_N, leaf, SPX_N); + memcpy(buffer, auth_path, SPX_N); + } else { + memcpy(buffer, leaf, SPX_N); + memcpy(buffer + SPX_N, auth_path, SPX_N); + } + auth_path += SPX_N; + + for (i = 0; i < tree_height - 1; i++) { + leaf_idx >>= 1; + idx_offset >>= 1; + /* Set the address of the node we're creating. */ + set_tree_height(addr, i + 1); + set_tree_index(addr, leaf_idx + idx_offset); + + /* Pick the right or left neighbor, depending on parity of the node. */ + if (leaf_idx & 1) { + thash(buffer + SPX_N, buffer, 2, ctx, addr); + memcpy(buffer, auth_path, SPX_N); + } else { + thash(buffer, buffer, 2, ctx, addr); + memcpy(buffer + SPX_N, auth_path, SPX_N); + } + auth_path += SPX_N; + } + + /* The last iteration is exceptional; we do not copy an auth_path node. */ + leaf_idx >>= 1; + idx_offset >>= 1; + set_tree_height(addr, tree_height); + set_tree_index(addr, leaf_idx + idx_offset); + thash(root, buffer, 2, ctx, addr); +} + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx * /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]) { + PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); + PQCLEAN_VLA(unsigned int, heights, tree_height + 1); + unsigned int offset = 0; + uint32_t idx; + uint32_t tree_idx; + + for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { + /* Add the next leaf node to the stack. */ + gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); + offset++; + heights[offset - 1] = 0; + + /* If this is a node we need for the auth path.. */ + if ((leaf_idx ^ 0x1) == idx) { + memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); + } + + /* While the top-most nodes are of equal height.. */ + while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { + /* Compute index of the new node, in the next layer. */ + tree_idx = (idx >> (heights[offset - 1] + 1)); + + /* Set the address of the node we're creating. */ + set_tree_height(tree_addr, heights[offset - 1] + 1); + set_tree_index(tree_addr, + tree_idx + (idx_offset >> (heights[offset - 1] + 1))); + /* Hash the top-most nodes from the stack together. */ + thash(stack + (offset - 2)*SPX_N, + stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); + offset--; + /* Note that the top-most node is now one layer higher. */ + heights[offset - 1]++; + + /* If this is a node we need for the auth path.. */ + if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { + memcpy(auth_path + heights[offset - 1]*SPX_N, + stack + (offset - 1)*SPX_N, SPX_N); + } + } + } + memcpy(root, stack, SPX_N); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/utils.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/utils.h new file mode 100644 index 0000000000..64f5d5a53a --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/utils.h @@ -0,0 +1,58 @@ +#ifndef SPX_UTILS_H +#define SPX_UTILS_H + +#include + +#include "compat.h" +#include "context.h" +#include "params.h" + + +/* To support MSVC use alloca() instead of VLAs. See #20. */ + + +/** + * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. + */ +#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in); +#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) +void u32_to_bytes(unsigned char *out, uint32_t in); + +/** + * Converts the inlen bytes in 'in' from big-endian byte order to an integer. + */ +#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); + +/** + * Computes a root node given a leaf and an auth path. + * Expects address to be complete other than the tree_height and tree_index. + */ +#define compute_root SPX_NAMESPACE(compute_root) +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]); + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +#define treehash SPX_NAMESPACE(treehash) +void treehash(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx *ctx /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]); + + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/utilsx2.c b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/utilsx2.c new file mode 100644 index 0000000000..8736474e4f --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/utilsx2.c @@ -0,0 +1,130 @@ +#include + +#include "utilsx2.h" + +#include "address.h" +#include "params.h" +#include "thashx2.h" +#include "utils.h" + +/* + * Generate the entire Merkle tree, computing the authentication path for leaf_idx, + * and the resulting root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) + * + * This expects tree_addrx2 to be initialized to 2 parallel addr structures for + * the Merkle tree nodes + * + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + * + * This works by using the standard Merkle tree building algorithm, except + * that each 'node' tracked is actually 2 consecutive nodes in the real tree. + * When we combine two logical nodes AB and WX, we perform the H + * operation on adjacent real nodes, forming the parent logical node + * (AB)(WX) + * + * When we get to the top level of the real tree (where there is only + * one logical node), we continue this operation one more time; the right + * most real node will by the actual root (and the other node will be + * garbage). We follow the same thashx2 logic so that the 'extract + * authentication path components' part of the loop is still executed (and + * to simplify the code somewhat) + */ +void treehashx2(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, + uint32_t tree_height, + void (*gen_leafx2)( + unsigned char * /* Where to write the leaves */, + const spx_ctx *, + uint32_t idx, void *info), + uint32_t tree_addrx2[2 * 8], + void *info) { + /* This is where we keep the intermediate nodes */ + unsigned char stackx2[tree_height * 2 * SPX_N]; + uint32_t left_adj = 0, prev_left_adj = 0; /* When we're doing the top */ + /* level, the left-most part of the tree isn't at the beginning */ + /* of current[]. These give the offset of the actual start */ + + uint32_t idx; + uint32_t max_idx = (1 << (tree_height - 1)) - 1; + for (idx = 0;; idx++) { + unsigned char current[2 * SPX_N]; /* Current logical node */ + gen_leafx2( current, ctx, 2 * idx + idx_offset, + info ); + + /* Now combine the freshly generated right node with previously */ + /* generated left ones */ + uint32_t internal_idx_offset = idx_offset; + uint32_t internal_idx = idx; + uint32_t internal_leaf = leaf_idx; + uint32_t h; /* The height we are in the Merkle tree */ + for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { + + /* Special processing if we're at the top of the tree */ + if (h >= tree_height - 1) { + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[1 * SPX_N], SPX_N ); + return; + } + /* The tree indexing logic is a bit off in this case */ + /* Adjust it so that the left-most node of the part of */ + /* the tree that we're processing has index 0 */ + prev_left_adj = left_adj; + left_adj = 2 - (1 << (tree_height - h - 1)); + } + + /* Check if we hit the top of the tree */ + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[1 * SPX_N], SPX_N ); + return; + } + + /* + * Check if one of the nodes we have is a part of the + * authentication path; if it is, write it out + */ + if ((((internal_idx << 1) ^ internal_leaf) & ~0x1) == 0) { + memcpy( &auth_path[ h * SPX_N ], + ¤t[(((internal_leaf & 1) ^ 1) + prev_left_adj) * SPX_N], + SPX_N ); + } + + /* + * Check if we're at a left child; if so, stop going up the stack + * Exception: if we've reached the end of the tree, keep on going + * (so we combine the last 2 nodes into the one root node in two + * more iterations) + */ + if ((internal_idx & 1) == 0 && idx < max_idx) { + break; + } + + /* Ok, we're at a right node (or doing the top 3 levels) */ + /* Now combine the left and right logical nodes together */ + + /* Set the address of the node we're creating. */ + int j; + internal_idx_offset >>= 1; + for (j = 0; j < 2; j++) { + set_tree_height(tree_addrx2 + j * 8, h + 1); + set_tree_index(tree_addrx2 + j * 8, + (2 / 2) * (internal_idx & ~1) + j - left_adj + internal_idx_offset ); + } + unsigned char *left = &stackx2[h * 2 * SPX_N]; + thashx2( ¤t[0 * SPX_N], + ¤t[1 * SPX_N], + &left [0 * SPX_N], + ¤t[0 * SPX_N], + 2, ctx, tree_addrx2); + } + + /* We've hit a left child; save the current for when we get the */ + /* corresponding right right */ + memcpy( &stackx2[h * 2 * SPX_N], current, 2 * SPX_N); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/utilsx2.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/utilsx2.h new file mode 100644 index 0000000000..e09faddc43 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/utilsx2.h @@ -0,0 +1,30 @@ +#ifndef SPX_UTILSX2_H +#define SPX_UTILSX2_H + +#include + +#include "context.h" +#include "params.h" + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + * + * This implementation uses SIMD to compute internal nodes 2 at a time (in + * parallel) + */ +#define treehashx2 SPX_NAMESPACE(treehashx2) +void treehashx2(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leafx2)( + unsigned char * /* Where to write the leaves */, + const spx_ctx * /* ctx */, + uint32_t addr_idx, void *info), + uint32_t tree_addrx2[2 * 8], void *info); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/wots.c b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/wots.c new file mode 100644 index 0000000000..3babe45e95 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/wots.c @@ -0,0 +1,259 @@ +#include +#include + +#include "wots.h" +#include "wotsx2.h" + +#include "address.h" +#include "hash.h" +#include "hashx2.h" +#include "params.h" +#include "thashx2.h" +#include "utils.h" +#include "utilsx2.h" + +// TODO clarify address expectations, and make them more uniform. +// TODO i.e. do we expect types to be set already? +// TODO and do we expect modifications or copies? + +/** + * Computes up the chains + */ +static void gen_chains( + unsigned char *out, + const unsigned char *in, + unsigned int start[SPX_WOTS_LEN], + const unsigned int steps[SPX_WOTS_LEN], + const spx_ctx *ctx, + uint32_t addr[8]) { + uint32_t i, j, k, idx, watching; + int done; + unsigned char empty[SPX_N]; + unsigned char *bufs[4]; + uint32_t addrs[8 * 2]; + + int l; + uint16_t counts[SPX_WOTS_W] = { 0 }; + uint16_t idxs[SPX_WOTS_LEN]; + uint16_t total, newTotal; + + /* set addrs = {addr, addr} */ + for (j = 0; j < 2; j++) { + memcpy(addrs + j * 8, addr, sizeof(uint32_t) * 8); + } + + /* Initialize out with the value at position 'start'. */ + memcpy(out, in, SPX_WOTS_LEN * SPX_N); + + /* Sort the chains in reverse order by steps using counting sort. */ + for (i = 0; i < SPX_WOTS_LEN; i++) { + counts[steps[i]]++; + } + total = 0; + for (l = SPX_WOTS_W - 1; l >= 0; l--) { + newTotal = counts[l] + total; + counts[l] = total; + total = newTotal; + } + for (i = 0; i < SPX_WOTS_LEN; i++) { + idxs[counts[steps[i]]] = i; + counts[steps[i]]++; + } + + /* We got our work cut out for us: do it! */ + for (i = 0; i < SPX_WOTS_LEN; i += 2) { + for (j = 0; j < 2 && i + j < SPX_WOTS_LEN; j++) { + idx = idxs[i + j]; + set_chain_addr(addrs + j * 8, idx); + bufs[j] = out + SPX_N * idx; + } + + /* As the chains are sorted in reverse order, we know that the first + * chain is the longest and the last one is the shortest. We keep + * an eye on whether the last chain is done and then on the one before, + * et cetera. */ + watching = 1; + done = 0; + while (i + watching >= SPX_WOTS_LEN) { + bufs[watching] = &empty[0]; + watching--; + } + + for (k = 0;; k++) { + while (k == steps[idxs[i + watching]]) { + bufs[watching] = &empty[0]; + if (watching == 0) { + done = 1; + break; + } + watching--; + } + if (done) { + break; + } + for (j = 0; j < watching + 1; j++) { + set_hash_addr(addrs + j * 8, k + start[idxs[i + j]]); + } + + thashx2(bufs[0], bufs[1], + bufs[0], bufs[1], 1, ctx, addrs); + } + } +} + +/** + * base_w algorithm as described in draft. + * Interprets an array of bytes as integers in base w. + * This only works when log_w is a divisor of 8. + */ +static void base_w(unsigned int *output, const int out_len, + const unsigned char *input) { + int in = 0; + int out = 0; + unsigned char total = 0; + int bits = 0; + int consumed; + + for (consumed = 0; consumed < out_len; consumed++) { + if (bits == 0) { + total = input[in]; + in++; + bits += 8; + } + bits -= SPX_WOTS_LOGW; + output[out] = (total >> bits) & (SPX_WOTS_W - 1); + out++; + } +} + +/* Computes the WOTS+ checksum over a message (in base_w). */ +static void wots_checksum(unsigned int *csum_base_w, + const unsigned int *msg_base_w) { + unsigned int csum = 0; + unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; + unsigned int i; + + /* Compute checksum. */ + for (i = 0; i < SPX_WOTS_LEN1; i++) { + csum += SPX_WOTS_W - 1 - msg_base_w[i]; + } + + /* Convert checksum to base_w. */ + /* Make sure expected empty zero bits are the least significant bits. */ + csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); + ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); + base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); +} + +/* Takes a message and derives the matching chain lengths. */ +void chain_lengths(unsigned int *lengths, const unsigned char *msg) { + base_w(lengths, SPX_WOTS_LEN1, msg); + wots_checksum(lengths + SPX_WOTS_LEN1, lengths); +} + +/** + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. + * + * Writes the computed public key to 'pk'. + */ +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]) { + unsigned int steps[SPX_WOTS_LEN]; + unsigned int start[SPX_WOTS_LEN]; + uint32_t i; + + chain_lengths(start, msg); + + for (i = 0; i < SPX_WOTS_LEN; i++) { + steps[i] = SPX_WOTS_W - 1 - start[i]; + } + + gen_chains(pk, sig, start, steps, ctx, addr); +} + +/* + * This generates 2 sequential WOTS public keys + * It also generates the WOTS signature if leaf_info indicates + * that we're signing with one of these WOTS keys + */ +void wots_gen_leafx2(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info) { + struct leaf_info_x2 *info = v_info; + uint32_t *leaf_addr = info->leaf_addr; + uint32_t *pk_addr = info->pk_addr; + unsigned int i, j, k; + unsigned char pk_buffer[ 2 * SPX_WOTS_BYTES ]; + unsigned wots_offset = SPX_WOTS_BYTES; + unsigned char *buffer; + uint32_t wots_k_mask; + unsigned wots_sign_index; + + if (((leaf_idx ^ info->wots_sign_leaf) & ~1) == 0) { + /* We're traversing the leaf that's signing; generate the WOTS */ + /* signature */ + wots_k_mask = 0; + wots_sign_index = info->wots_sign_leaf & 1; /* Which of of the 2 */ + /* slots do the signatures come from */ + } else { + /* Nope, we're just generating pk's; turn off the signature logic */ + wots_k_mask = ~0; + wots_sign_index = 0; + } + + for (j = 0; j < 2; j++) { + set_keypair_addr( leaf_addr + j * 8, leaf_idx + j ); + set_keypair_addr( pk_addr + j * 8, leaf_idx + j ); + } + + for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { + uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k to */ + /* the step if we're generating a signature, ~0 if we're not */ + + /* Start with the secret seed */ + for (j = 0; j < 2; j++) { + set_chain_addr(leaf_addr + j * 8, i); + set_hash_addr(leaf_addr + j * 8, 0); + set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTSPRF); + } + prf_addrx2(buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + ctx, leaf_addr); + for (j = 0; j < 2; j++) { + set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTS); + } + + /* Iterate down the WOTS chain */ + for (k = 0;; k++) { + /* Check if one of the values we have needs to be saved as a */ + /* part of the WOTS signature */ + if (k == wots_k) { + memcpy( info->wots_sig + i * SPX_N, + buffer + wots_sign_index * wots_offset, SPX_N ); + } + + /* Check if we hit the top of the chain */ + if (k == SPX_WOTS_W - 1) { + break; + } + + /* Iterate one step on all 4 chains */ + for (j = 0; j < 2; j++) { + set_hash_addr(leaf_addr + j * 8, k); + } + thashx2(buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + 1, ctx, leaf_addr); + } + } + + /* Do the final thash to generate the public keys */ + thashx2(dest + 0 * SPX_N, + dest + 1 * SPX_N, + pk_buffer + 0 * wots_offset, + pk_buffer + 1 * wots_offset, + SPX_WOTS_LEN, ctx, pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/wots.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/wots.h new file mode 100644 index 0000000000..4e7692eeef --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/wots.h @@ -0,0 +1,25 @@ +#ifndef SPX_WOTS_H +#define SPX_WOTS_H + +#include + +#include "context.h" +#include "params.h" + +/** + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. + * + * Writes the computed public key to 'pk'. + */ +#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]); + +/* + * Compute the chain lengths needed for a given message hash + */ +#define chain_lengths SPX_NAMESPACE(chain_lengths) +void chain_lengths(unsigned int *lengths, const unsigned char *msg); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/wotsx2.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/wotsx2.h new file mode 100644 index 0000000000..b58bb61f84 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_aarch64/wotsx2.h @@ -0,0 +1,40 @@ +#ifndef WOTSX2_H_ +#define WOTSX2_H_ + +#include "params.h" +#include + +/* + * This is here to provide an interface to the internal wots_gen_leafx2 + * routine. While this routine is not referenced in the package outside of + * wots.c, it is called from the stand-alone benchmark code to characterize + * the performance + */ +struct leaf_info_x2 { + unsigned char *wots_sig; + uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ + uint32_t *wots_steps; + uint32_t leaf_addr[2 * 8]; + uint32_t pk_addr[2 * 8]; +}; + +/* Macro to set the leaf_info to something 'benign', that is, it would */ +/* run with the same time as it does during the real signing process */ +/* Used only by the benchmark code */ +#define INITIALIZE_LEAF_INFO_X2(info, addr, step_buffer) { \ + (info).wots_sig = 0; \ + (info).wots_sign_leaf = ~0; \ + (info).wots_steps = step_buffer; \ + int i; \ + for (i=0; i<2; i++) { \ + memcpy( &(info).leaf_addr[8*i], addr, 32 ); \ + memcpy( &(info).pk_addr[8*i], addr, 32 ); \ + } \ + } + +#define wots_gen_leafx2 SPX_NAMESPACE(wots_gen_leafx2) +void wots_gen_leafx2(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info); + +#endif /* WOTSX2_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/LICENSE b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/LICENSE new file mode 100644 index 0000000000..670154e353 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/LICENSE @@ -0,0 +1,116 @@ +CC0 1.0 Universal + +Statement of Purpose + +The laws of most jurisdictions throughout the world automatically confer +exclusive Copyright and Related Rights (defined below) upon the creator and +subsequent owner(s) (each and all, an "owner") of an original work of +authorship and/or a database (each, a "Work"). + +Certain owners wish to permanently relinquish those rights to a Work for the +purpose of contributing to a commons of creative, cultural and scientific +works ("Commons") that the public can reliably and without fear of later +claims of infringement build upon, modify, incorporate in other works, reuse +and redistribute as freely as possible in any form whatsoever and for any +purposes, including without limitation commercial purposes. These owners may +contribute to the Commons to promote the ideal of a free culture and the +further production of creative, cultural and scientific works, or to gain +reputation or greater distribution for their Work in part through the use and +efforts of others. + +For these and/or other purposes and motivations, and without any expectation +of additional consideration or compensation, the person associating CC0 with a +Work (the "Affirmer"), to the extent that he or she is an owner of Copyright +and Related Rights in the Work, voluntarily elects to apply CC0 to the Work +and publicly distribute the Work under its terms, with knowledge of his or her +Copyright and Related Rights in the Work and the meaning and intended legal +effect of CC0 on those rights. + +1. Copyright and Related Rights. A Work made available under CC0 may be +protected by copyright and related or neighboring rights ("Copyright and +Related Rights"). Copyright and Related Rights include, but are not limited +to, the following: + + i. the right to reproduce, adapt, distribute, perform, display, communicate, + and translate a Work; + + ii. moral rights retained by the original author(s) and/or performer(s); + + iii. publicity and privacy rights pertaining to a person's image or likeness + depicted in a Work; + + iv. rights protecting against unfair competition in regards to a Work, + subject to the limitations in paragraph 4(a), below; + + v. rights protecting the extraction, dissemination, use and reuse of data in + a Work; + + vi. database rights (such as those arising under Directive 96/9/EC of the + European Parliament and of the Council of 11 March 1996 on the legal + protection of databases, and under any national implementation thereof, + including any amended or successor version of such directive); and + + vii. other similar, equivalent or corresponding rights throughout the world + based on applicable law or treaty, and any national implementations thereof. + +2. Waiver. To the greatest extent permitted by, but not in contravention of, +applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and +unconditionally waives, abandons, and surrenders all of Affirmer's Copyright +and Related Rights and associated claims and causes of action, whether now +known or unknown (including existing as well as future claims and causes of +action), in the Work (i) in all territories worldwide, (ii) for the maximum +duration provided by applicable law or treaty (including future time +extensions), (iii) in any current or future medium and for any number of +copies, and (iv) for any purpose whatsoever, including without limitation +commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes +the Waiver for the benefit of each member of the public at large and to the +detriment of Affirmer's heirs and successors, fully intending that such Waiver +shall not be subject to revocation, rescission, cancellation, termination, or +any other legal or equitable action to disrupt the quiet enjoyment of the Work +by the public as contemplated by Affirmer's express Statement of Purpose. + +3. Public License Fallback. Should any part of the Waiver for any reason be +judged legally invalid or ineffective under applicable law, then the Waiver +shall be preserved to the maximum extent permitted taking into account +Affirmer's express Statement of Purpose. In addition, to the extent the Waiver +is so judged Affirmer hereby grants to each affected person a royalty-free, +non transferable, non sublicensable, non exclusive, irrevocable and +unconditional license to exercise Affirmer's Copyright and Related Rights in +the Work (i) in all territories worldwide, (ii) for the maximum duration +provided by applicable law or treaty (including future time extensions), (iii) +in any current or future medium and for any number of copies, and (iv) for any +purpose whatsoever, including without limitation commercial, advertising or +promotional purposes (the "License"). The License shall be deemed effective as +of the date CC0 was applied by Affirmer to the Work. Should any part of the +License for any reason be judged legally invalid or ineffective under +applicable law, such partial invalidity or ineffectiveness shall not +invalidate the remainder of the License, and in such case Affirmer hereby +affirms that he or she will not (i) exercise any of his or her remaining +Copyright and Related Rights in the Work or (ii) assert any associated claims +and causes of action with respect to the Work, in either case contrary to +Affirmer's express Statement of Purpose. + +4. Limitations and Disclaimers. + + a. No trademark or patent rights held by Affirmer are waived, abandoned, + surrendered, licensed or otherwise affected by this document. + + b. Affirmer offers the Work as-is and makes no representations or warranties + of any kind concerning the Work, express, implied, statutory or otherwise, + including without limitation warranties of title, merchantability, fitness + for a particular purpose, non infringement, or the absence of latent or + other defects, accuracy, or the present or absence of errors, whether or not + discoverable, all to the greatest extent permissible under applicable law. + + c. Affirmer disclaims responsibility for clearing rights of other persons + that may apply to the Work or any use thereof, including without limitation + any person's Copyright and Related Rights in the Work. Further, Affirmer + disclaims responsibility for obtaining any necessary consents, permissions + or other rights required for any use of the Work. + + d. Affirmer understands and acknowledges that Creative Commons is not a + party to this document and has no duty or obligation with respect to this + CC0 or use of the Work. + +For more information, please see + diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/address.c b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/address.c new file mode 100644 index 0000000000..d49d9f3b6b --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/address.c @@ -0,0 +1,95 @@ +#include +#include + +#include "address.h" +#include "params.h" +#include "utils.h" + +/* + * Specify which level of Merkle tree (the "layer") we're working on + */ +void set_layer_addr(uint32_t addr[8], uint32_t layer) { + ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; +} + +/* + * Specify which Merkle tree within the level (the "tree address") we're working on + */ +void set_tree_addr(uint32_t addr[8], uint64_t tree) { + ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); +} + +/* + * Specify the reason we'll use this address structure for, that is, what + * hash will we compute with it. This is used so that unrelated types of + * hashes don't accidentally get the same address structure. The type will be + * one of the SPX_ADDR_TYPE constants + */ +void set_type(uint32_t addr[8], uint32_t type) { + ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; +} + +/* + * Copy the layer and tree fields of the address structure. This is used + * when we're doing multiple types of hashes within the same Merkle tree + */ +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); +} + +/* These functions are used for OTS addresses. */ + +/* + * Specify which Merkle leaf we're working on; that is, which OTS keypair + * we're talking about. + */ +void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { + /* We have > 256 OTS at the bottom of the Merkle tree; to specify */ + /* which one, we'd need to express it in two bytes */ + ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR2] = (unsigned char)(keypair >> 8); + ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; +} + +/* + * Copy the layer, tree and keypair fields of the address structure. This is + * used when we're doing multiple things within the same OTS keypair + */ +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); + ((unsigned char *)out)[SPX_OFFSET_KP_ADDR2] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR2]; + ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; +} + +/* + * Specify which Merkle chain within the OTS we're working with + * (the chain address) + */ +void set_chain_addr(uint32_t addr[8], uint32_t chain) { + ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; +} + +/* + * Specify where in the Merkle chain we are +* (the hash address) + */ +void set_hash_addr(uint32_t addr[8], uint32_t hash) { + ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; +} + +/* These functions are used for all hash tree addresses (including FORS). */ + +/* + * Specify the height of the node in the Merkle/FORS tree we are in + * (the tree height) + */ +void set_tree_height(uint32_t addr[8], uint32_t tree_height) { + ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; +} + +/* + * Specify the distance from the left edge of the node in the Merkle/FORS tree + * (the tree index) + */ +void set_tree_index(uint32_t addr[8], uint32_t tree_index) { + u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/address.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/address.h new file mode 100644 index 0000000000..24a84eb40c --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/address.h @@ -0,0 +1,52 @@ +#ifndef SPX_ADDRESS_H +#define SPX_ADDRESS_H + +#include + +#include "params.h" + +/* The hash types that are passed to set_type */ +#define SPX_ADDR_TYPE_WOTS 0 +#define SPX_ADDR_TYPE_WOTSPK 1 +#define SPX_ADDR_TYPE_HASHTREE 2 +#define SPX_ADDR_TYPE_FORSTREE 3 +#define SPX_ADDR_TYPE_FORSPK 4 +#define SPX_ADDR_TYPE_WOTSPRF 5 +#define SPX_ADDR_TYPE_FORSPRF 6 + +#define set_layer_addr SPX_NAMESPACE(set_layer_addr) +void set_layer_addr(uint32_t addr[8], uint32_t layer); + +#define set_tree_addr SPX_NAMESPACE(set_tree_addr) +void set_tree_addr(uint32_t addr[8], uint64_t tree); + +#define set_type SPX_NAMESPACE(set_type) +void set_type(uint32_t addr[8], uint32_t type); + +/* Copies the layer and tree part of one address into the other */ +#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); + +/* These functions are used for WOTS and FORS addresses. */ + +#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) +void set_keypair_addr(uint32_t addr[8], uint32_t keypair); + +#define set_chain_addr SPX_NAMESPACE(set_chain_addr) +void set_chain_addr(uint32_t addr[8], uint32_t chain); + +#define set_hash_addr SPX_NAMESPACE(set_hash_addr) +void set_hash_addr(uint32_t addr[8], uint32_t hash); + +#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); + +/* These functions are used for all hash tree addresses (including FORS). */ + +#define set_tree_height SPX_NAMESPACE(set_tree_height) +void set_tree_height(uint32_t addr[8], uint32_t tree_height); + +#define set_tree_index SPX_NAMESPACE(set_tree_index) +void set_tree_index(uint32_t addr[8], uint32_t tree_index); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/api.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/api.h new file mode 100644 index 0000000000..9e64ad4d94 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/api.h @@ -0,0 +1,77 @@ +#ifndef PQCLEAN_SPHINCSSHAKE192SSIMPLE_AVX2_API_H +#define PQCLEAN_SPHINCSSHAKE192SSIMPLE_AVX2_API_H + +#include +#include + +#define PQCLEAN_SPHINCSSHAKE192SSIMPLE_AVX2_CRYPTO_ALGNAME "SPHINCS+-shake-192s-simple" + +#define PQCLEAN_SPHINCSSHAKE192SSIMPLE_AVX2_CRYPTO_SECRETKEYBYTES 96 +#define PQCLEAN_SPHINCSSHAKE192SSIMPLE_AVX2_CRYPTO_PUBLICKEYBYTES 48 +#define PQCLEAN_SPHINCSSHAKE192SSIMPLE_AVX2_CRYPTO_BYTES 16224 + +#define PQCLEAN_SPHINCSSHAKE192SSIMPLE_AVX2_CRYPTO_SEEDBYTES 72 + +/* + * Returns the length of a secret key, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE192SSIMPLE_AVX2_crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE192SSIMPLE_AVX2_crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE192SSIMPLE_AVX2_crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE192SSIMPLE_AVX2_crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +int PQCLEAN_SPHINCSSHAKE192SSIMPLE_AVX2_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +int PQCLEAN_SPHINCSSHAKE192SSIMPLE_AVX2_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +int PQCLEAN_SPHINCSSHAKE192SSIMPLE_AVX2_crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +int PQCLEAN_SPHINCSSHAKE192SSIMPLE_AVX2_crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, + const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +int PQCLEAN_SPHINCSSHAKE192SSIMPLE_AVX2_crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +int PQCLEAN_SPHINCSSHAKE192SSIMPLE_AVX2_crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/context.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/context.h new file mode 100644 index 0000000000..6e0a33f3b7 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/context.h @@ -0,0 +1,19 @@ +#ifndef SPX_CONTEXT_H +#define SPX_CONTEXT_H + +#include + +#include "params.h" + +typedef struct { + uint8_t pub_seed[SPX_N]; + uint8_t sk_seed[SPX_N]; +} spx_ctx; + +#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) +void initialize_hash_function(spx_ctx *ctx); + +#define free_hash_function SPX_NAMESPACE(free_hash_function) +void free_hash_function(spx_ctx *ctx); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/context_shake.c b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/context_shake.c new file mode 100644 index 0000000000..9614a103d3 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/context_shake.c @@ -0,0 +1,12 @@ +#include "context.h" + +/* For SHAKE256, there is no immediate reason to initialize at the start, + so this function is an empty operation. */ +void initialize_hash_function(spx_ctx *ctx) { + (void)ctx; /* Suppress an 'unused parameter' warning. */ +} + +// in case the hash function api is heap-based. +void free_hash_function(spx_ctx *ctx) { + (void)ctx; +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/fips202x4.c b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/fips202x4.c new file mode 100644 index 0000000000..1e06fef186 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/fips202x4.c @@ -0,0 +1,210 @@ +#include +#include +#include + +#include "fips202.h" +#include "fips202x4.h" + +#define NROUNDS 24 +#define ROL(a, offset) (((a) << (offset)) ^ ((a) >> (64-(offset)))) + +static uint64_t load64(const unsigned char *x) { + unsigned long long r = 0, i; + + for (i = 0; i < 8; ++i) { + r |= (unsigned long long)x[i] << 8 * i; + } + return r; +} + +static void store64(uint8_t *x, uint64_t u) { + unsigned int i; + + for (i = 0; i < 8; ++i) { + x[i] = (uint8_t)u; + u >>= 8; + } +} + +/* Use implementation from the Keccak Code Package */ +extern void KeccakP1600times4_PermuteAll_24rounds(__m256i *s); +#define KeccakF1600_StatePermute4x KeccakP1600times4_PermuteAll_24rounds + +static void keccak_absorb4x(__m256i *s, + unsigned int r, + const unsigned char *m0, + const unsigned char *m1, + const unsigned char *m2, + const unsigned char *m3, + unsigned long long int mlen, + unsigned char p) { + unsigned long long i; + unsigned char t0[200]; + unsigned char t1[200]; + unsigned char t2[200]; + unsigned char t3[200]; + + unsigned long long *ss = (unsigned long long *)s; + + + while (mlen >= r) { + for (i = 0; i < r / 8; ++i) { + ss[4 * i + 0] ^= load64(m0 + 8 * i); + ss[4 * i + 1] ^= load64(m1 + 8 * i); + ss[4 * i + 2] ^= load64(m2 + 8 * i); + ss[4 * i + 3] ^= load64(m3 + 8 * i); + } + + KeccakF1600_StatePermute4x(s); + mlen -= r; + m0 += r; + m1 += r; + m2 += r; + m3 += r; + } + + for (i = 0; i < r; ++i) { + t0[i] = 0; + t1[i] = 0; + t2[i] = 0; + t3[i] = 0; + } + for (i = 0; i < mlen; ++i) { + t0[i] = m0[i]; + t1[i] = m1[i]; + t2[i] = m2[i]; + t3[i] = m3[i]; + } + + t0[i] = p; + t1[i] = p; + t2[i] = p; + t3[i] = p; + + t0[r - 1] |= 128; + t1[r - 1] |= 128; + t2[r - 1] |= 128; + t3[r - 1] |= 128; + + for (i = 0; i < r / 8; ++i) { + ss[4 * i + 0] ^= load64(t0 + 8 * i); + ss[4 * i + 1] ^= load64(t1 + 8 * i); + ss[4 * i + 2] ^= load64(t2 + 8 * i); + ss[4 * i + 3] ^= load64(t3 + 8 * i); + } +} + + +static void keccak_squeezeblocks4x(unsigned char *h0, + unsigned char *h1, + unsigned char *h2, + unsigned char *h3, + unsigned long long int nblocks, + __m256i *s, + unsigned int r) { + unsigned int i; + + unsigned long long *ss = (unsigned long long *)s; + + while (nblocks > 0) { + KeccakF1600_StatePermute4x(s); + for (i = 0; i < (r >> 3); i++) { + store64(h0 + 8 * i, ss[4 * i + 0]); + store64(h1 + 8 * i, ss[4 * i + 1]); + store64(h2 + 8 * i, ss[4 * i + 2]); + store64(h3 + 8 * i, ss[4 * i + 3]); + } + h0 += r; + h1 += r; + h2 += r; + h3 += r; + nblocks--; + } +} + + + +void shake128x4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, unsigned long long outlen, + unsigned char *in0, + unsigned char *in1, + unsigned char *in2, + unsigned char *in3, unsigned long long inlen) { + __m256i s[25]; + unsigned char t0[SHAKE128_RATE]; + unsigned char t1[SHAKE128_RATE]; + unsigned char t2[SHAKE128_RATE]; + unsigned char t3[SHAKE128_RATE]; + unsigned int i; + + /* zero state */ + for (i = 0; i < 25; i++) { + s[i] = _mm256_xor_si256(s[i], s[i]); + } + + /* absorb 4 message of identical length in parallel */ + keccak_absorb4x(s, SHAKE128_RATE, in0, in1, in2, in3, inlen, 0x1F); + + /* Squeeze output */ + keccak_squeezeblocks4x(out0, out1, out2, out3, outlen / SHAKE128_RATE, s, SHAKE128_RATE); + + out0 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; + out1 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; + out2 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; + out3 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; + + if (outlen % SHAKE128_RATE) { + keccak_squeezeblocks4x(t0, t1, t2, t3, 1, s, SHAKE128_RATE); + for (i = 0; i < outlen % SHAKE128_RATE; i++) { + out0[i] = t0[i]; + out1[i] = t1[i]; + out2[i] = t2[i]; + out3[i] = t3[i]; + } + } +} + + +void shake256x4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, unsigned long long outlen, + unsigned char *in0, + unsigned char *in1, + unsigned char *in2, + unsigned char *in3, unsigned long long inlen) { + __m256i s[25]; + unsigned char t0[SHAKE256_RATE]; + unsigned char t1[SHAKE256_RATE]; + unsigned char t2[SHAKE256_RATE]; + unsigned char t3[SHAKE256_RATE]; + unsigned int i; + + /* zero state */ + for (i = 0; i < 25; i++) { + s[i] = _mm256_xor_si256(s[i], s[i]); + } + + /* absorb 4 message of identical length in parallel */ + keccak_absorb4x(s, SHAKE256_RATE, in0, in1, in2, in3, inlen, 0x1F); + + /* Squeeze output */ + keccak_squeezeblocks4x(out0, out1, out2, out3, outlen / SHAKE256_RATE, s, SHAKE256_RATE); + + out0 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; + out1 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; + out2 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; + out3 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; + + if (outlen % SHAKE256_RATE) { + keccak_squeezeblocks4x(t0, t1, t2, t3, 1, s, SHAKE256_RATE); + for (i = 0; i < outlen % SHAKE256_RATE; i++) { + out0[i] = t0[i]; + out1[i] = t1[i]; + out2[i] = t2[i]; + out3[i] = t3[i]; + } + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/fips202x4.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/fips202x4.h new file mode 100644 index 0000000000..2b93c9cd0d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/fips202x4.h @@ -0,0 +1,28 @@ +#ifndef SPX_FIPS202X4_H +#define SPX_FIPS202X4_H + +#include + +#include "params.h" + +#define shake128x4 SPX_NAMESPACE(shake128x4) +void shake128x4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, unsigned long long outlen, + unsigned char *in0, + unsigned char *in1, + unsigned char *in2, + unsigned char *in3, unsigned long long inlen); + +#define shake256x4 SPX_NAMESPACE(shake256x4) +void shake256x4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, unsigned long long outlen, + unsigned char *in0, + unsigned char *in1, + unsigned char *in2, + unsigned char *in3, unsigned long long inlen); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/fors.c b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/fors.c new file mode 100644 index 0000000000..f1b0639cfc --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/fors.c @@ -0,0 +1,202 @@ +#include +#include +#include + +#include "fors.h" + +#include "address.h" +#include "hash.h" +#include "hashx4.h" +#include "thash.h" +#include "thashx4.h" +#include "utils.h" +#include "utilsx4.h" + +static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + prf_addr(sk, ctx, fors_leaf_addr); +} + +static void fors_gen_skx4(unsigned char *sk0, + unsigned char *sk1, + unsigned char *sk2, + unsigned char *sk3, const spx_ctx *ctx, + uint32_t fors_leaf_addrx4[4 * 8]) { + prf_addrx4(sk0, sk1, sk2, sk3, + ctx, fors_leaf_addrx4); +} + +static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, + const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + thash(leaf, sk, 1, ctx, fors_leaf_addr); +} + +static void fors_sk_to_leafx4(unsigned char *leaf0, + unsigned char *leaf1, + unsigned char *leaf2, + unsigned char *leaf3, + const unsigned char *sk0, + const unsigned char *sk1, + const unsigned char *sk2, + const unsigned char *sk3, + const spx_ctx *ctx, + uint32_t fors_leaf_addrx4[4 * 8]) { + thashx4(leaf0, leaf1, leaf2, leaf3, + sk0, sk1, sk2, sk3, + 1, ctx, fors_leaf_addrx4); +} + +struct fors_gen_leaf_info { + uint32_t leaf_addrx[4 * 8]; +}; + +static void fors_gen_leafx4(unsigned char *leaf, + const spx_ctx *ctx, + uint32_t addr_idx, void *info) { + struct fors_gen_leaf_info *fors_info = info; + uint32_t *fors_leaf_addrx4 = fors_info->leaf_addrx; + unsigned int j; + + /* Only set the parts that the caller doesn't set */ + for (j = 0; j < 4; j++) { + set_tree_index(fors_leaf_addrx4 + j * 8, addr_idx + j); + set_type(fors_leaf_addrx4 + j * 8, SPX_ADDR_TYPE_FORSPRF); + } + + fors_gen_skx4(leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + leaf + 2 * SPX_N, + leaf + 3 * SPX_N, + ctx, fors_leaf_addrx4); + + for (j = 0; j < 4; j++) { + set_type(fors_leaf_addrx4 + j * 8, SPX_ADDR_TYPE_FORSTREE); + } + + fors_sk_to_leafx4(leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + leaf + 2 * SPX_N, + leaf + 3 * SPX_N, + leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + leaf + 2 * SPX_N, + leaf + 3 * SPX_N, + ctx, fors_leaf_addrx4); +} + +/** + * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + * Assumes indices has space for SPX_FORS_TREES integers. + */ +static void message_to_indices(uint32_t *indices, const unsigned char *m) { + unsigned int i, j; + unsigned int offset = 0; + + for (i = 0; i < SPX_FORS_TREES; i++) { + indices[i] = 0; + for (j = 0; j < SPX_FORS_HEIGHT; j++) { + indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); + offset++; + } + } +} + +/** + * Signs a message m, deriving the secret key from sk_seed and the FTS address. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + uint32_t fors_tree_addr[4 * 8] = {0}; + struct fors_gen_leaf_info fors_info = {0}; + uint32_t *fors_leaf_addr = fors_info.leaf_addrx; + uint32_t fors_pk_addr[8] = {0}; + uint32_t idx_offset; + unsigned int i; + + for (i = 0; i < 4; i++) { + copy_keypair_addr(fors_tree_addr + 8 * i, fors_addr); + set_type(fors_tree_addr + 8 * i, SPX_ADDR_TYPE_FORSTREE); + copy_keypair_addr(fors_leaf_addr + 8 * i, fors_addr); + } + copy_keypair_addr(fors_pk_addr, fors_addr); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); + + message_to_indices(indices, m); + + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); + + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + + /* Include the secret key part that produces the selected leaf node. */ + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); + fors_gen_sk(sig, ctx, fors_tree_addr); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + sig += SPX_N; + + /* Compute the authentication path for this leaf node. */ + treehashx4(roots + i * SPX_N, sig, ctx, + indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx4, + fors_tree_addr, &fors_info); + + sig += SPX_N * SPX_FORS_HEIGHT; + } + + /* Hash horizontally across all tree roots to derive the public key. */ + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); +} + +/** + * Derives the FORS public key from a signature. + * This can be used for verification by comparing to a known public key, or to + * subsequently verify a signature on the derived public key. The latter is the + * typical use-case when used as an FTS below an OTS in a hypertree. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + unsigned char leaf[SPX_N]; + uint32_t fors_tree_addr[8] = {0}; + uint32_t fors_pk_addr[8] = {0}; + uint32_t idx_offset; + unsigned int i; + + copy_keypair_addr(fors_tree_addr, fors_addr); + copy_keypair_addr(fors_pk_addr, fors_addr); + + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); + + message_to_indices(indices, m); + + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); + + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + + /* Derive the leaf from the included secret key part. */ + fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); + sig += SPX_N; + + /* Derive the corresponding root node of this tree. */ + compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, + sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); + sig += SPX_N * SPX_FORS_HEIGHT; + } + + /* Hash horizontally across all tree roots to derive the public key. */ + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/fors.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/fors.h new file mode 100644 index 0000000000..509140a178 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/fors.h @@ -0,0 +1,32 @@ +#ifndef SPX_FORS_H +#define SPX_FORS_H + +#include + +#include "context.h" +#include "params.h" + +/** + * Signs a message m, deriving the secret key from sk_seed and the FTS address. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +#define fors_sign SPX_NAMESPACE(fors_sign) +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); + +/** + * Derives the FORS public key from a signature. + * This can be used for verification by comparing to a known public key, or to + * subsequently verify a signature on the derived public key. The latter is the + * typical use-case when used as an FTS below an OTS in a hypertree. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/hash.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/hash.h new file mode 100644 index 0000000000..f7c87d4c3c --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/hash.h @@ -0,0 +1,28 @@ +#ifndef SPX_HASH_H +#define SPX_HASH_H + +#include +#include + +#include "context.h" +#include "params.h" + +#define prf_addr SPX_NAMESPACE(prf_addr) +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]); + +#define gen_message_random SPX_NAMESPACE(gen_message_random) +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); + +#define hash_message SPX_NAMESPACE(hash_message) +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); + + + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/hash_shake.c b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/hash_shake.c new file mode 100644 index 0000000000..ff5e7ec918 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/hash_shake.c @@ -0,0 +1,83 @@ +#include +#include + +#include "hash.h" + +#include "address.h" +#include "fips202.h" +#include "params.h" +#include "utils.h" + +/* + * Computes PRF(pk_seed, sk_seed, addr) + */ +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]) { + unsigned char buf[2 * SPX_N + SPX_ADDR_BYTES]; + + memcpy(buf, ctx->pub_seed, SPX_N); + memcpy(buf + SPX_N, addr, SPX_ADDR_BYTES); + memcpy(buf + SPX_N + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); + + shake256(out, SPX_N, buf, 2 * SPX_N + SPX_ADDR_BYTES); +} + +/** + * Computes the message-dependent randomness R, using a secret seed and an + * optional randomization value as well as the message. + */ +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { + (void)ctx; + shake256incctx s_inc; + + shake256_inc_init(&s_inc); + shake256_inc_absorb(&s_inc, sk_prf, SPX_N); + shake256_inc_absorb(&s_inc, optrand, SPX_N); + shake256_inc_absorb(&s_inc, m, mlen); + shake256_inc_finalize(&s_inc); + shake256_inc_squeeze(R, SPX_N, &s_inc); + shake256_inc_ctx_release(&s_inc); +} + +/** + * Computes the message hash using R, the public key, and the message. + * Outputs the message digest and the index of the leaf. The index is split in + * the tree index and the leaf index, for convenient copying to an address. + */ +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { + (void)ctx; +#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) +#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) +#define SPX_LEAF_BITS SPX_TREE_HEIGHT +#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) +#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) + + unsigned char buf[SPX_DGST_BYTES]; + unsigned char *bufp = buf; + shake256incctx s_inc; + + shake256_inc_init(&s_inc); + shake256_inc_absorb(&s_inc, R, SPX_N); + shake256_inc_absorb(&s_inc, pk, SPX_PK_BYTES); + shake256_inc_absorb(&s_inc, m, mlen); + shake256_inc_finalize(&s_inc); + shake256_inc_squeeze(buf, SPX_DGST_BYTES, &s_inc); + shake256_inc_ctx_release(&s_inc); + + memcpy(digest, bufp, SPX_FORS_MSG_BYTES); + bufp += SPX_FORS_MSG_BYTES; + + + *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); + *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); + bufp += SPX_TREE_BYTES; + + *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); + *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/hash_shakex4.c b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/hash_shakex4.c new file mode 100644 index 0000000000..bbd22eb117 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/hash_shakex4.c @@ -0,0 +1,64 @@ +#include +#include + +#include "hashx4.h" + +#include "address.h" +#include "fips202x4.h" +#include "params.h" + +extern void KeccakP1600times4_PermuteAll_24rounds(__m256i *s); + +/* + * 4-way parallel version of prf_addr; takes 4x as much input and output + */ +void prf_addrx4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const spx_ctx *ctx, + const uint32_t addrx4[4 * 8]) { + /* As we write and read only a few quadwords, it is more efficient to + * build and extract from the fourway SHAKE256 state by hand. */ + __m256i state[25]; + + for (int i = 0; i < SPX_N / 8; i++) { + state[i] = _mm256_set1_epi64x(((int64_t *)ctx->pub_seed)[i]); + } + for (int i = 0; i < 4; i++) { + state[SPX_N / 8 + i] = _mm256_set_epi32( + (int)addrx4[3 * 8 + 1 + 2 * i], + (int)addrx4[3 * 8 + 2 * i], + (int)addrx4[2 * 8 + 1 + 2 * i], + (int)addrx4[2 * 8 + 2 * i], + (int)addrx4[8 + 1 + 2 * i], + (int)addrx4[8 + 2 * i], + (int)addrx4[1 + 2 * i], + (int)addrx4[2 * i] + ); + } + for (int i = 0; i < SPX_N / 8; i++) { + state[SPX_N / 8 + i + 4] = _mm256_set1_epi64x(((int64_t *)ctx->sk_seed)[i]); + } + + /* SHAKE domain separator and padding. */ + state[SPX_N / 4 + 4] = _mm256_set1_epi64x(0x1f); + for (int i = SPX_N / 4 + 5; i < 16; i++) { + state[i] = _mm256_set1_epi64x(0); + } + // shift unsigned and then cast to avoid UB + state[16] = _mm256_set1_epi64x((long long)(0x80ULL << 56)); + + for (int i = 17; i < 25; i++) { + state[i] = _mm256_set1_epi64x(0); + } + + KeccakP1600times4_PermuteAll_24rounds(&state[0]); + + for (int i = 0; i < SPX_N / 8; i++) { + ((int64_t *)out0)[i] = _mm256_extract_epi64(state[i], 0); + ((int64_t *)out1)[i] = _mm256_extract_epi64(state[i], 1); + ((int64_t *)out2)[i] = _mm256_extract_epi64(state[i], 2); + ((int64_t *)out3)[i] = _mm256_extract_epi64(state[i], 3); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/hashx4.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/hashx4.h new file mode 100644 index 0000000000..3751a0ebd0 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/hashx4.h @@ -0,0 +1,17 @@ +#ifndef SPX_HASHX4_H +#define SPX_HASHX4_H + +#include + +#include "context.h" +#include "params.h" + +#define prf_addrx4 SPX_NAMESPACE(prf_addrx4) +void prf_addrx4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const spx_ctx *ctx, + const uint32_t addrx4[4 * 8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/merkle.c b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/merkle.c new file mode 100644 index 0000000000..f57811c1ac --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/merkle.c @@ -0,0 +1,64 @@ +#include +#include + +#include "merkle.h" + +#include "address.h" +#include "params.h" +#include "utils.h" +#include "utilsx4.h" +#include "wots.h" +#include "wotsx4.h" + +/* + * This generates a Merkle signature (WOTS signature followed by the Merkle + * authentication path). + */ +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf) { + unsigned char *auth_path = sig + SPX_WOTS_BYTES; + uint32_t tree_addrx4[4 * 8] = { 0 }; + int j; + struct leaf_info_x4 info = { 0 }; + unsigned steps[ SPX_WOTS_LEN ]; + + info.wots_sig = sig; + chain_lengths(steps, root); + info.wots_steps = steps; + + for (j = 0; j < 4; j++) { + set_type(&tree_addrx4[8 * j], SPX_ADDR_TYPE_HASHTREE); + set_type(&info.leaf_addr[8 * j], SPX_ADDR_TYPE_WOTS); + set_type(&info.pk_addr[8 * j], SPX_ADDR_TYPE_WOTSPK); + copy_subtree_addr(&tree_addrx4[8 * j], tree_addr); + copy_subtree_addr(&info.leaf_addr[8 * j], wots_addr); + copy_subtree_addr(&info.pk_addr[8 * j], wots_addr); + } + + info.wots_sign_leaf = idx_leaf; + + treehashx4(root, auth_path, ctx, + idx_leaf, 0, + SPX_TREE_HEIGHT, + wots_gen_leafx4, + tree_addrx4, &info); +} + +/* Compute root node of the top-most subtree. */ +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { + /* We do not need the auth path in key generation, but it simplifies the + code to have just one treehash routine that computes both root and path + in one function. */ + unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; + uint32_t top_tree_addr[8] = {0}; + uint32_t wots_addr[8] = {0}; + + set_layer_addr(top_tree_addr, SPX_D - 1); + set_layer_addr(wots_addr, SPX_D - 1); + + merkle_sign(auth_path, root, ctx, + wots_addr, top_tree_addr, + ~0U /* ~0 means "don't bother generating an auth path */ ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/merkle.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/merkle.h new file mode 100644 index 0000000000..769cf2e970 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/merkle.h @@ -0,0 +1,21 @@ +#ifndef MERKLE_H_ +#define MERKLE_H_ + +#include + +#include "context.h" +#include "params.h" + +/* Generate a Merkle signature (WOTS signature followed by the Merkle */ +/* authentication path) */ +#define merkle_sign SPX_NAMESPACE(merkle_sign) +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf); + +/* Compute the root node of the top-most subtree. */ +#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); + +#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/nistapi.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/nistapi.h new file mode 100644 index 0000000000..3cb71afad4 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/nistapi.h @@ -0,0 +1,87 @@ +#ifndef SPX_API_H +#define SPX_API_H + +#include +#include + +#include "params.h" + +#define CRYPTO_ALGNAME "SPHINCS+" + +#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES +#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES +#define CRYPTO_BYTES SPX_BYTES +#define CRYPTO_SEEDBYTES (3*SPX_N) + +/* + * Returns the length of a secret key, in bytes + */ +#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) +size_t crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) +size_t crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) +size_t crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) +size_t crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +#define crypto_sign SPX_NAMESPACE(crypto_sign) +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/params.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/params.h new file mode 100644 index 0000000000..90195bc15c --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/params.h @@ -0,0 +1,56 @@ +#ifndef SPX_PARAMS_H +#define SPX_PARAMS_H + +#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSSHAKE192SSIMPLE_AVX2_##s + +/* Hash output length in bytes. */ +#define SPX_N 24 +/* Height of the hypertree. */ +#define SPX_FULL_HEIGHT 63 +/* Number of subtree layer. */ +#define SPX_D 7 +/* FORS tree dimensions. */ +#define SPX_FORS_HEIGHT 14 +#define SPX_FORS_TREES 17 +/* Winternitz parameter, */ +#define SPX_WOTS_W 16 + +/* The hash function is defined by linking a different hash.c file, as opposed + to setting a #define constant. */ + +/* For clarity */ +#define SPX_ADDR_BYTES 32 + +/* WOTS parameters. */ +#define SPX_WOTS_LOGW 4 + +#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) + +/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ +#define SPX_WOTS_LEN2 3 + +#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) +#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) +#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES + +/* Subtree size. */ +#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) + +//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT +// #error SPX_D should always divide SPX_FULL_HEIGHT +//#endif + +/* FORS parameters. */ +#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) +#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) +#define SPX_FORS_PK_BYTES SPX_N + +/* Resulting SPX sizes. */ +#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ + SPX_FULL_HEIGHT * SPX_N) +#define SPX_PK_BYTES (2 * SPX_N) +#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) + +#include "shake_offsets.h" + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/shake_offsets.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/shake_offsets.h new file mode 100644 index 0000000000..6b28d95d91 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/shake_offsets.h @@ -0,0 +1,21 @@ +#ifndef SHAKE_OFFSETS_H_ +#define SHAKE_OFFSETS_H_ + +/* + * Offsets of various fields in the address structure when we use SHAKE as + * the Sphincs+ hash function + */ + +#define SPX_OFFSET_LAYER 3 /* The byte used to specify the Merkle tree layer */ +#define SPX_OFFSET_TREE 8 /* The start of the 8 byte field used to specify the tree */ +#define SPX_OFFSET_TYPE 19 /* The byte used to specify the hash type (reason) */ +#define SPX_OFFSET_KP_ADDR2 22 /* The high byte used to specify the key pair (which one-time signature) */ +#define SPX_OFFSET_KP_ADDR1 23 /* The low byte used to specify the key pair */ +#define SPX_OFFSET_CHAIN_ADDR 27 /* The byte used to specify the chain address (which Winternitz chain) */ +#define SPX_OFFSET_HASH_ADDR 31 /* The byte used to specify the hash address (where in the Winternitz chain) */ +#define SPX_OFFSET_TREE_HGT 27 /* The byte used to specify the height of this node in the FORS or Merkle tree */ +#define SPX_OFFSET_TREE_INDEX 28 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ + +#define SPX_SHAKE 1 + +#endif /* SHAKE_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/sign.c b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/sign.c new file mode 100644 index 0000000000..9d0c7d1b22 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/sign.c @@ -0,0 +1,286 @@ +#include +#include +#include + +#include "address.h" +#include "context.h" +#include "fors.h" +#include "hash.h" +#include "merkle.h" +#include "nistapi.h" +#include "params.h" +#include "randombytes.h" +#include "thash.h" +#include "utils.h" +#include "wots.h" + +/* + * Returns the length of a secret key, in bytes + */ +size_t crypto_sign_secretkeybytes(void) { + return CRYPTO_SECRETKEYBYTES; +} + +/* + * Returns the length of a public key, in bytes + */ +size_t crypto_sign_publickeybytes(void) { + return CRYPTO_PUBLICKEYBYTES; +} + +/* + * Returns the length of a signature, in bytes + */ +size_t crypto_sign_bytes(void) { + return CRYPTO_BYTES; +} + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +size_t crypto_sign_seedbytes(void) { + return CRYPTO_SEEDBYTES; +} + +/* + * Generates an SPX key pair given a seed of length + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [PUB_SEED || root] + */ +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed) { + spx_ctx ctx; + + /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ + memcpy(sk, seed, CRYPTO_SEEDBYTES); + + memcpy(pk, sk + 2 * SPX_N, SPX_N); + + memcpy(ctx.pub_seed, pk, SPX_N); + memcpy(ctx.sk_seed, sk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + /* Compute root node of the top-most subtree. */ + merkle_gen_root(sk + 3 * SPX_N, &ctx); + + // cleanup + free_hash_function(&ctx); + + memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); + + return 0; +} + +/* + * Generates an SPX key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [PUB_SEED || root] + */ +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { + uint8_t seed[CRYPTO_SEEDBYTES]; + randombytes(seed, CRYPTO_SEEDBYTES); + crypto_sign_seed_keypair(pk, sk, seed); + + return 0; +} + +/** + * Returns an array containing a detached signature. + */ +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk) { + spx_ctx ctx; + + const uint8_t *sk_prf = sk + SPX_N; + const uint8_t *pk = sk + 2 * SPX_N; + + uint8_t optrand[SPX_N]; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t root[SPX_N]; + uint32_t i; + uint64_t tree; + uint32_t idx_leaf; + uint32_t wots_addr[8] = {0}; + uint32_t tree_addr[8] = {0}; + + memcpy(ctx.sk_seed, sk, SPX_N); + memcpy(ctx.pub_seed, pk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + + /* Optionally, signing can be made non-deterministic using optrand. + This can help counter side-channel attacks that would benefit from + getting a large number of traces when the signer uses the same nodes. */ + randombytes(optrand, SPX_N); + /* Compute the digest randomization value. */ + gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); + + /* Derive the message digest and leaf index from R, PK and M. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; + + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); + + /* Sign the message hash using FORS. */ + fors_sign(sig, root, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); + sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; + + /* Update the indices for the next layer. */ + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; + } + + free_hash_function(&ctx); + + *siglen = SPX_BYTES; + + return 0; +} + +/** + * Verifies a detached signature and message under a given public key. + */ +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk) { + spx_ctx ctx; + const uint8_t *pub_root = pk + SPX_N; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t wots_pk[SPX_WOTS_BYTES]; + uint8_t root[SPX_N]; + uint8_t leaf[SPX_N]; + unsigned int i; + uint64_t tree; + uint32_t idx_leaf; + uint32_t wots_addr[8] = {0}; + uint32_t tree_addr[8] = {0}; + uint32_t wots_pk_addr[8] = {0}; + + if (siglen != SPX_BYTES) { + return -1; + } + + memcpy(ctx.pub_seed, pk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); + + /* Derive the message digest and leaf index from R || PK || M. */ + /* The additional SPX_N is a result of the hash domain separator. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; + + /* Layer correctly defaults to 0, so no need to set_layer_addr */ + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); + + fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + /* For each subtree.. */ + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + copy_keypair_addr(wots_pk_addr, wots_addr); + + /* The WOTS public key is only correct if the signature was correct. */ + /* Initially, root is the FORS pk, but on subsequent iterations it is + the root of the subtree below the currently processed subtree. */ + wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); + sig += SPX_WOTS_BYTES; + + /* Compute the leaf node using the WOTS public key. */ + thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); + + /* Compute the root node of this subtree. */ + compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, + &ctx, tree_addr); + sig += SPX_TREE_HEIGHT * SPX_N; + + /* Update the indices for the next layer. */ + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; + } + + // cleanup + free_hash_function(&ctx); + + /* Check if the root node equals the root node in the public key. */ + if (memcmp(root, pub_root, SPX_N) != 0) { + return -1; + } + + return 0; +} + + +/** + * Returns an array containing the signature followed by the message. + */ +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk) { + size_t siglen; + + crypto_sign_signature(sm, &siglen, m, mlen, sk); + + memmove(sm + SPX_BYTES, m, mlen); + *smlen = siglen + mlen; + + return 0; +} + +/** + * Verifies a given signature-message pair under a given public key. + */ +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk) { + /* The API caller does not necessarily know what size a signature should be + but SPHINCS+ signatures are always exactly SPX_BYTES. */ + if (smlen < SPX_BYTES) { + memset(m, 0, smlen); + *mlen = 0; + return -1; + } + + *mlen = smlen - SPX_BYTES; + + if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { + memset(m, 0, smlen); + *mlen = 0; + return -1; + } + + /* If verification was successful, move the message to the right place. */ + memmove(m, sm + SPX_BYTES, *mlen); + + return 0; +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/thash.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/thash.h new file mode 100644 index 0000000000..8687ccfb4d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/thash.h @@ -0,0 +1,13 @@ +#ifndef SPX_THASH_H +#define SPX_THASH_H + +#include "context.h" +#include "params.h" + +#include + +#define thash SPX_NAMESPACE(thash) +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/thash_shake_simple.c b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/thash_shake_simple.c new file mode 100644 index 0000000000..98470395e9 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/thash_shake_simple.c @@ -0,0 +1,24 @@ +#include +#include + +#include "thash.h" + +#include "address.h" +#include "params.h" +#include "utils.h" + +#include "fips202.h" + +/** + * Takes an array of inblocks concatenated arrays of SPX_N bytes. + */ +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]) { + PQCLEAN_VLA(uint8_t, buf, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); + + memcpy(buf, ctx->pub_seed, SPX_N); + memcpy(buf + SPX_N, addr, SPX_ADDR_BYTES); + memcpy(buf + SPX_N + SPX_ADDR_BYTES, in, inblocks * SPX_N); + + shake256(out, SPX_N, buf, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/thash_shake_simplex4.c b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/thash_shake_simplex4.c new file mode 100644 index 0000000000..89dc9a4224 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/thash_shake_simplex4.c @@ -0,0 +1,98 @@ +#include +#include + +#include "thashx4.h" + +#include "address.h" +#include "params.h" +#include "utils.h" + +#include "fips202x4.h" + +extern void KeccakP1600times4_PermuteAll_24rounds(__m256i *s); + +/** + * 4-way parallel version of thash; takes 4x as much input and output + */ +void thashx4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addrx4[4 * 8]) { + if (inblocks == 1 || inblocks == 2) { + /* As we write and read only a few quadwords, it is more efficient to + * build and extract from the fourway SHAKE256 state by hand. */ + __m256i state[25]; + for (int i = 0; i < SPX_N / 8; i++) { + state[i] = _mm256_set1_epi64x(((int64_t *)ctx->pub_seed)[i]); + } + for (int i = 0; i < 4; i++) { + state[SPX_N / 8 + i] = _mm256_set_epi32( + (int)addrx4[3 * 8 + 1 + 2 * i], + (int)addrx4[3 * 8 + 2 * i], + (int)addrx4[2 * 8 + 1 + 2 * i], + (int)addrx4[2 * 8 + 2 * i], + (int)addrx4[8 + 1 + 2 * i], + (int)addrx4[8 + 2 * i], + (int)addrx4[1 + 2 * i], + (int)addrx4[2 * i] + ); + } + + for (unsigned int i = 0; i < (SPX_N / 8) * inblocks; i++) { + state[SPX_N / 8 + 4 + i] = _mm256_set_epi64x( + ((int64_t *)in3)[i], + ((int64_t *)in2)[i], + ((int64_t *)in1)[i], + ((int64_t *)in0)[i] + ); + } + + /* Domain separator and padding. */ + for (size_t i = (SPX_N / 8) * (1 + inblocks) + 4; i < 16; i++) { + state[i] = _mm256_set1_epi64x(0); + } + state[16] = _mm256_set1_epi64x((long long)(0x80ULL << 56)); + state[(SPX_N / 8) * (1 + inblocks) + 4] = _mm256_xor_si256( + state[(SPX_N / 8) * (1 + inblocks) + 4], + _mm256_set1_epi64x(0x1f) + ); + for (int i = 17; i < 25; i++) { + state[i] = _mm256_set1_epi64x(0); + } + + KeccakP1600times4_PermuteAll_24rounds(&state[0]); + + for (int i = 0; i < SPX_N / 8; i++) { + ((int64_t *)out0)[i] = _mm256_extract_epi64(state[i], 0); + ((int64_t *)out1)[i] = _mm256_extract_epi64(state[i], 1); + ((int64_t *)out2)[i] = _mm256_extract_epi64(state[i], 2); + ((int64_t *)out3)[i] = _mm256_extract_epi64(state[i], 3); + } + } else { + PQCLEAN_VLA(unsigned char, buf0, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, buf1, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, buf2, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, buf3, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); + + memcpy(buf0, ctx->pub_seed, SPX_N); + memcpy(buf1, ctx->pub_seed, SPX_N); + memcpy(buf2, ctx->pub_seed, SPX_N); + memcpy(buf3, ctx->pub_seed, SPX_N); + memcpy(buf0 + SPX_N, addrx4 + 0 * 8, SPX_ADDR_BYTES); + memcpy(buf1 + SPX_N, addrx4 + 1 * 8, SPX_ADDR_BYTES); + memcpy(buf2 + SPX_N, addrx4 + 2 * 8, SPX_ADDR_BYTES); + memcpy(buf3 + SPX_N, addrx4 + 3 * 8, SPX_ADDR_BYTES); + memcpy(buf0 + SPX_N + SPX_ADDR_BYTES, in0, inblocks * SPX_N); + memcpy(buf1 + SPX_N + SPX_ADDR_BYTES, in1, inblocks * SPX_N); + memcpy(buf2 + SPX_N + SPX_ADDR_BYTES, in2, inblocks * SPX_N); + memcpy(buf3 + SPX_N + SPX_ADDR_BYTES, in3, inblocks * SPX_N); + + shake256x4(out0, out1, out2, out3, SPX_N, + buf0, buf1, buf2, buf3, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/thashx4.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/thashx4.h new file mode 100644 index 0000000000..64798a3727 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/thashx4.h @@ -0,0 +1,20 @@ +#ifndef SPX_THASHX4_H +#define SPX_THASHX4_H + +#include + +#include "context.h" +#include "params.h" + +#define thashx4 SPX_NAMESPACE(thashx4) +void thashx4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addrx4[4 * 8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/utils.c b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/utils.c new file mode 100644 index 0000000000..177b541fb9 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/utils.c @@ -0,0 +1,148 @@ +#include + +#include "utils.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "thash.h" + +/** + * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. + */ +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in) { + int i; + + /* Iterate over out in decreasing order, for big-endianness. */ + for (i = (signed int)outlen - 1; i >= 0; i--) { + out[i] = in & 0xff; + in = in >> 8; + } +} + +void u32_to_bytes(unsigned char *out, uint32_t in) { + out[0] = (unsigned char)(in >> 24); + out[1] = (unsigned char)(in >> 16); + out[2] = (unsigned char)(in >> 8); + out[3] = (unsigned char)in; +} + +/** + * Converts the inlen bytes in 'in' from big-endian byte order to an integer. + */ +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { + unsigned long long retval = 0; + unsigned int i; + + for (i = 0; i < inlen; i++) { + retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); + } + return retval; +} + +/** + * Computes a root node given a leaf and an auth path. + * Expects address to be complete other than the tree_height and tree_index. + */ +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]) { + uint32_t i; + unsigned char buffer[2 * SPX_N]; + + /* If leaf_idx is odd (last bit = 1), current path element is a right child + and auth_path has to go left. Otherwise it is the other way around. */ + if (leaf_idx & 1) { + memcpy(buffer + SPX_N, leaf, SPX_N); + memcpy(buffer, auth_path, SPX_N); + } else { + memcpy(buffer, leaf, SPX_N); + memcpy(buffer + SPX_N, auth_path, SPX_N); + } + auth_path += SPX_N; + + for (i = 0; i < tree_height - 1; i++) { + leaf_idx >>= 1; + idx_offset >>= 1; + /* Set the address of the node we're creating. */ + set_tree_height(addr, i + 1); + set_tree_index(addr, leaf_idx + idx_offset); + + /* Pick the right or left neighbor, depending on parity of the node. */ + if (leaf_idx & 1) { + thash(buffer + SPX_N, buffer, 2, ctx, addr); + memcpy(buffer, auth_path, SPX_N); + } else { + thash(buffer, buffer, 2, ctx, addr); + memcpy(buffer + SPX_N, auth_path, SPX_N); + } + auth_path += SPX_N; + } + + /* The last iteration is exceptional; we do not copy an auth_path node. */ + leaf_idx >>= 1; + idx_offset >>= 1; + set_tree_height(addr, tree_height); + set_tree_index(addr, leaf_idx + idx_offset); + thash(root, buffer, 2, ctx, addr); +} + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx * /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]) { + PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); + PQCLEAN_VLA(unsigned int, heights, tree_height + 1); + unsigned int offset = 0; + uint32_t idx; + uint32_t tree_idx; + + for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { + /* Add the next leaf node to the stack. */ + gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); + offset++; + heights[offset - 1] = 0; + + /* If this is a node we need for the auth path.. */ + if ((leaf_idx ^ 0x1) == idx) { + memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); + } + + /* While the top-most nodes are of equal height.. */ + while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { + /* Compute index of the new node, in the next layer. */ + tree_idx = (idx >> (heights[offset - 1] + 1)); + + /* Set the address of the node we're creating. */ + set_tree_height(tree_addr, heights[offset - 1] + 1); + set_tree_index(tree_addr, + tree_idx + (idx_offset >> (heights[offset - 1] + 1))); + /* Hash the top-most nodes from the stack together. */ + thash(stack + (offset - 2)*SPX_N, + stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); + offset--; + /* Note that the top-most node is now one layer higher. */ + heights[offset - 1]++; + + /* If this is a node we need for the auth path.. */ + if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { + memcpy(auth_path + heights[offset - 1]*SPX_N, + stack + (offset - 1)*SPX_N, SPX_N); + } + } + } + memcpy(root, stack, SPX_N); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/utils.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/utils.h new file mode 100644 index 0000000000..64f5d5a53a --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/utils.h @@ -0,0 +1,58 @@ +#ifndef SPX_UTILS_H +#define SPX_UTILS_H + +#include + +#include "compat.h" +#include "context.h" +#include "params.h" + + +/* To support MSVC use alloca() instead of VLAs. See #20. */ + + +/** + * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. + */ +#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in); +#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) +void u32_to_bytes(unsigned char *out, uint32_t in); + +/** + * Converts the inlen bytes in 'in' from big-endian byte order to an integer. + */ +#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); + +/** + * Computes a root node given a leaf and an auth path. + * Expects address to be complete other than the tree_height and tree_index. + */ +#define compute_root SPX_NAMESPACE(compute_root) +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]); + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +#define treehash SPX_NAMESPACE(treehash) +void treehash(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx *ctx /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]); + + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/utilsx4.c b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/utilsx4.c new file mode 100644 index 0000000000..1638677194 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/utilsx4.c @@ -0,0 +1,138 @@ +#include + +#include "utilsx4.h" + +#include "address.h" +#include "params.h" +#include "thashx4.h" +#include "utils.h" + +/* + * Generate the entire Merkle tree, computing the authentication path for leaf_idx, + * and the resulting root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) + * + * This expects tree_addrx4 to be initialized to 4 parallel addr structures for + * the Merkle tree nodes + * + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + * + * This works by using the standard Merkle tree building algorithm, except + * that each 'node' tracked is actually 4 consecutive nodes in the real tree. + * When we combine two logical nodes ABCD and WXYZ, we perform the H + * operation on adjacent real nodes, forming the parent logical node + * (AB)(CD)(WX)(YZ) + * + * When we get to the top two levels of the real tree (where there is only + * one logical node), we continue this operation two more times; the right + * most real node will by the actual root (and the other 3 nodes will be + * garbage). We follow the same thashx4 logic so that the 'extract + * authentication path components' part of the loop is still executed (and + * to simplify the code somewhat) + * + * This currently assumes tree_height >= 2; I suspect that doing an adjusting + * idx, addr_idx on the gen_leafx4 call if tree_height < 2 would fix it; since + * we don't actually use such short trees, I haven't bothered + */ +void treehashx4(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, + uint32_t tree_height, + void (*gen_leafx4)( + unsigned char * /* Where to write the leaves */, + const spx_ctx *, + uint32_t idx, void *info), + uint32_t tree_addrx4[4 * 8], + void *info) { + /* This is where we keep the intermediate nodes */ + PQCLEAN_VLA(unsigned char, stackx4, tree_height * 4 * SPX_N); + uint32_t left_adj = 0, prev_left_adj = 0; /* When we're doing the top 3 */ + /* levels, the left-most part of the tree isn't at the beginning */ + /* of current[]. These give the offset of the actual start */ + + uint32_t idx; + uint32_t max_idx = (1U << (tree_height - 2)) - 1; + for (idx = 0;; idx++) { + unsigned char current[4 * SPX_N]; /* Current logical node */ + gen_leafx4( current, ctx, 4 * idx + idx_offset, + info ); + + /* Now combine the freshly generated right node with previously */ + /* generated left ones */ + uint32_t internal_idx_offset = idx_offset; + uint32_t internal_idx = idx; + uint32_t internal_leaf = leaf_idx; + uint32_t h; /* The height we are in the Merkle tree */ + for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { + + /* Special processing if we're at the top of the tree */ + if (h >= tree_height - 2) { + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[3 * SPX_N], SPX_N ); + return; + } + /* The tree indexing logic is a bit off in this case */ + /* Adjust it so that the left-most node of the part of */ + /* the tree that we're processing has index 0 */ + prev_left_adj = left_adj; + left_adj = 4U - (1 << (tree_height - h - 1)); + } + + /* Check if we hit the top of the tree */ + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[3 * SPX_N], SPX_N ); + return; + } + + /* + * Check if one of the nodes we have is a part of the + * authentication path; if it is, write it out + */ + if ((((internal_idx << 2) ^ internal_leaf) & ~0x3U) == 0) { + memcpy( &auth_path[ h * SPX_N ], + ¤t[(((internal_leaf & 3) ^ 1) + prev_left_adj) * SPX_N], + SPX_N ); + } + + /* + * Check if we're at a left child; if so, stop going up the stack + * Exception: if we've reached the end of the tree, keep on going + * (so we combine the last 4 nodes into the one root node in two + * more iterations) + */ + if ((internal_idx & 1) == 0 && idx < max_idx) { + break; + } + + /* Ok, we're at a right node (or doing the top 3 levels) */ + /* Now combine the left and right logical nodes together */ + + /* Set the address of the node we're creating. */ + unsigned int j; + internal_idx_offset >>= 1; + for (j = 0; j < 4; j++) { + set_tree_height(tree_addrx4 + j * 8, h + 1); + set_tree_index(tree_addrx4 + j * 8, + (4 / 2) * (internal_idx & ~1U) + j - left_adj + internal_idx_offset ); + } + unsigned char *left = &stackx4[h * 4 * SPX_N]; + thashx4( ¤t[0 * SPX_N], + ¤t[1 * SPX_N], + ¤t[2 * SPX_N], + ¤t[3 * SPX_N], + &left [0 * SPX_N], + &left [2 * SPX_N], + ¤t[0 * SPX_N], + ¤t[2 * SPX_N], + 2, ctx, tree_addrx4); + } + + /* We've hit a left child; save the current for when we get the */ + /* corresponding right right */ + memcpy( &stackx4[h * 4 * SPX_N], current, 4 * SPX_N); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/utilsx4.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/utilsx4.h new file mode 100644 index 0000000000..facb874b18 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/utilsx4.h @@ -0,0 +1,30 @@ +#ifndef SPX_UTILSX4_H +#define SPX_UTILSX4_H + +#include + +#include "context.h" +#include "params.h" + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + * + * This implementation uses AVX to compute internal nodes 4 at a time (in + * parallel) + */ +#define treehashx4 SPX_NAMESPACE(treehashx4) +void treehashx4(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leafx4)( + unsigned char * /* Where to write the leaves */, + const spx_ctx * /* ctx */, + uint32_t addr_idx, void *info), + uint32_t tree_addrx4[4 * 8], void *info); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/wots.c b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/wots.c new file mode 100644 index 0000000000..4d5041ce05 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/wots.c @@ -0,0 +1,269 @@ +#include +#include + +#include "wots.h" + +#include "address.h" +#include "hash.h" +#include "hashx4.h" +#include "params.h" +#include "thash.h" +#include "thashx4.h" +#include "utils.h" +#include "utilsx4.h" +#include "wotsx4.h" + +// TODO clarify address expectations, and make them more uniform. +// TODO i.e. do we expect types to be set already? +// TODO and do we expect modifications or copies? + +/** + * Computes up the chains + */ +static void gen_chains( + unsigned char *out, + const unsigned char *in, + unsigned int start[SPX_WOTS_LEN], + const unsigned int steps[SPX_WOTS_LEN], + const spx_ctx *ctx, + uint32_t addr[8]) { + uint32_t i, j, k, idx, watching; + int done; + unsigned char empty[SPX_N]; + unsigned char *bufs[4]; + uint32_t addrs[8 * 4]; + + int l; + uint16_t counts[SPX_WOTS_W] = { 0 }; + uint16_t idxs[SPX_WOTS_LEN]; + uint16_t total, newTotal; + + /* set addrs = {addr, addr, addr, addr} */ + for (j = 0; j < 4; j++) { + memcpy(addrs + j * 8, addr, sizeof(uint32_t) * 8); + } + + /* Initialize out with the value at position 'start'. */ + memcpy(out, in, SPX_WOTS_LEN * SPX_N); + + /* Sort the chains in reverse order by steps using counting sort. */ + for (i = 0; i < SPX_WOTS_LEN; i++) { + counts[steps[i]]++; + } + total = 0; + for (l = SPX_WOTS_W - 1; l >= 0; l--) { + newTotal = counts[l] + total; + counts[l] = total; + total = newTotal; + } + for (i = 0; i < SPX_WOTS_LEN; i++) { + idxs[counts[steps[i]]] = (uint16_t)i; + counts[steps[i]]++; + } + + /* We got our work cut out for us: do it! */ + for (i = 0; i < SPX_WOTS_LEN; i += 4) { + for (j = 0; j < 4 && i + j < SPX_WOTS_LEN; j++) { + idx = idxs[i + j]; + set_chain_addr(addrs + j * 8, idx); + bufs[j] = out + SPX_N * idx; + } + + /* As the chains are sorted in reverse order, we know that the first + * chain is the longest and the last one is the shortest. We keep + * an eye on whether the last chain is done and then on the one before, + * et cetera. */ + watching = 3; + done = 0; + while (i + watching >= SPX_WOTS_LEN) { + bufs[watching] = &empty[0]; + watching--; + } + + for (k = 0;; k++) { + while (k == steps[idxs[i + watching]]) { + bufs[watching] = &empty[0]; + if (watching == 0) { + done = 1; + break; + } + watching--; + } + if (done) { + break; + } + for (j = 0; j < watching + 1; j++) { + set_hash_addr(addrs + j * 8, k + start[idxs[i + j]]); + } + + thashx4(bufs[0], bufs[1], bufs[2], bufs[3], + bufs[0], bufs[1], bufs[2], bufs[3], 1, ctx, addrs); + } + } +} + +/** + * base_w algorithm as described in draft. + * Interprets an array of bytes as integers in base w. + * This only works when log_w is a divisor of 8. + */ +static void base_w(unsigned int *output, const int out_len, + const unsigned char *input) { + int in = 0; + int out = 0; + unsigned char total = 0; + int bits = 0; + int consumed; + + for (consumed = 0; consumed < out_len; consumed++) { + if (bits == 0) { + total = input[in]; + in++; + bits += 8; + } + bits -= SPX_WOTS_LOGW; + output[out] = (total >> bits) & (SPX_WOTS_W - 1); + out++; + } +} + +/* Computes the WOTS+ checksum over a message (in base_w). */ +static void wots_checksum(unsigned int *csum_base_w, + const unsigned int *msg_base_w) { + unsigned int csum = 0; + unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; + unsigned int i; + + /* Compute checksum. */ + for (i = 0; i < SPX_WOTS_LEN1; i++) { + csum += SPX_WOTS_W - 1 - msg_base_w[i]; + } + + /* Convert checksum to base_w. */ + /* Make sure expected empty zero bits are the least significant bits. */ + csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); + ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); + base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); +} + +/* Takes a message and derives the matching chain lengths. */ +void chain_lengths(unsigned int *lengths, const unsigned char *msg) { + base_w(lengths, SPX_WOTS_LEN1, msg); + wots_checksum(lengths + SPX_WOTS_LEN1, lengths); +} + +/** + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. + * + * Writes the computed public key to 'pk'. + */ +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]) { + unsigned int steps[SPX_WOTS_LEN]; + unsigned int start[SPX_WOTS_LEN]; + uint32_t i; + + chain_lengths(start, msg); + + for (i = 0; i < SPX_WOTS_LEN; i++) { + steps[i] = SPX_WOTS_W - 1 - start[i]; + } + + gen_chains(pk, sig, start, steps, ctx, addr); +} + +/* + * This generates 4 sequential WOTS public keys + * It also generates the WOTS signature if leaf_info indicates + * that we're signing with one of these WOTS keys + */ +void wots_gen_leafx4(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info) { + struct leaf_info_x4 *info = v_info; + uint32_t *leaf_addr = info->leaf_addr; + uint32_t *pk_addr = info->pk_addr; + unsigned int i, j, k; + unsigned char pk_buffer[ 4 * SPX_WOTS_BYTES ]; + unsigned wots_offset = SPX_WOTS_BYTES; + unsigned char *buffer; + uint32_t wots_k_mask; + unsigned wots_sign_index; + + if (((leaf_idx ^ info->wots_sign_leaf) & ~3U) == 0) { + /* We're traversing the leaf that's signing; generate the WOTS */ + /* signature */ + wots_k_mask = 0; + wots_sign_index = info->wots_sign_leaf & 3; /* Which of of the 4 */ + /* 4 slots do the signatures come from */ + } else { + /* Nope, we're just generating pk's; turn off the signature logic */ + wots_k_mask = (uint32_t)~0; + wots_sign_index = 0; + } + + for (j = 0; j < 4; j++) { + set_keypair_addr( leaf_addr + j * 8, leaf_idx + j ); + set_keypair_addr( pk_addr + j * 8, leaf_idx + j ); + } + + for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { + uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k to */ + /* the step if we're generating a signature, ~0 if we're not */ + + /* Start with the secret seed */ + for (j = 0; j < 4; j++) { + set_chain_addr(leaf_addr + j * 8, i); + set_hash_addr(leaf_addr + j * 8, 0); + set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTSPRF); + } + prf_addrx4(buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + buffer + 2 * wots_offset, + buffer + 3 * wots_offset, + ctx, leaf_addr); + + for (j = 0; j < 4; j++) { + set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTS); + } + + /* Iterate down the WOTS chain */ + for (k = 0;; k++) { + /* Check if one of the values we have needs to be saved as a */ + /* part of the WOTS signature */ + if (k == wots_k) { + memcpy( info->wots_sig + i * SPX_N, + buffer + wots_sign_index * wots_offset, SPX_N ); + } + + /* Check if we hit the top of the chain */ + if (k == SPX_WOTS_W - 1) { + break; + } + + /* Iterate one step on all 4 chains */ + for (j = 0; j < 4; j++) { + set_hash_addr(leaf_addr + j * 8, k); + } + thashx4(buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + buffer + 2 * wots_offset, + buffer + 3 * wots_offset, + buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + buffer + 2 * wots_offset, + buffer + 3 * wots_offset, 1, ctx, leaf_addr); + } + } + + /* Do the final thash to generate the public keys */ + thashx4(dest + 0 * SPX_N, + dest + 1 * SPX_N, + dest + 2 * SPX_N, + dest + 3 * SPX_N, + pk_buffer + 0 * wots_offset, + pk_buffer + 1 * wots_offset, + pk_buffer + 2 * wots_offset, + pk_buffer + 3 * wots_offset, SPX_WOTS_LEN, ctx, pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/wots.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/wots.h new file mode 100644 index 0000000000..4e7692eeef --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/wots.h @@ -0,0 +1,25 @@ +#ifndef SPX_WOTS_H +#define SPX_WOTS_H + +#include + +#include "context.h" +#include "params.h" + +/** + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. + * + * Writes the computed public key to 'pk'. + */ +#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]); + +/* + * Compute the chain lengths needed for a given message hash + */ +#define chain_lengths SPX_NAMESPACE(chain_lengths) +void chain_lengths(unsigned int *lengths, const unsigned char *msg); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/wotsx4.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/wotsx4.h new file mode 100644 index 0000000000..cd634f1743 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/wotsx4.h @@ -0,0 +1,41 @@ +#ifndef WOTSX4_H_ +#define WOTSX4_H_ + +#include + +#include "params.h" + +/* + * This is here to provide an interface to the internal wots_gen_leafx4 + * routine. While this routine is not referenced in the package outside of + * wots.c, it is called from the stand-alone benchmark code to characterize + * the performance + */ +struct leaf_info_x4 { + unsigned char *wots_sig; + uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ + uint32_t *wots_steps; + uint32_t leaf_addr[4 * 8]; + uint32_t pk_addr[4 * 8]; +}; + +/* Macro to set the leaf_info to something 'benign', that is, it would */ +/* run with the same time as it does during the real signing process */ +/* Used only by the benchmark code */ +#define INITIALIZE_LEAF_INFO_X4(info, addr, step_buffer) { \ + (info).wots_sig = 0; \ + (info).wots_sign_leaf = ~0; \ + (info).wots_steps = step_buffer; \ + int i; \ + for (i=0; i<4; i++) { \ + memcpy( &(info).leaf_addr[8*i], addr, 32 ); \ + memcpy( &(info).pk_addr[8*i], addr, 32 ); \ + } \ + } + +#define wots_gen_leafx4 SPX_NAMESPACE(wots_gen_leafx4) +void wots_gen_leafx4(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info); + +#endif /* WOTSX4_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_clean/LICENSE b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_clean/LICENSE new file mode 100644 index 0000000000..670154e353 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_clean/LICENSE @@ -0,0 +1,116 @@ +CC0 1.0 Universal + +Statement of Purpose + +The laws of most jurisdictions throughout the world automatically confer +exclusive Copyright and Related Rights (defined below) upon the creator and +subsequent owner(s) (each and all, an "owner") of an original work of +authorship and/or a database (each, a "Work"). + +Certain owners wish to permanently relinquish those rights to a Work for the +purpose of contributing to a commons of creative, cultural and scientific +works ("Commons") that the public can reliably and without fear of later +claims of infringement build upon, modify, incorporate in other works, reuse +and redistribute as freely as possible in any form whatsoever and for any +purposes, including without limitation commercial purposes. These owners may +contribute to the Commons to promote the ideal of a free culture and the +further production of creative, cultural and scientific works, or to gain +reputation or greater distribution for their Work in part through the use and +efforts of others. + +For these and/or other purposes and motivations, and without any expectation +of additional consideration or compensation, the person associating CC0 with a +Work (the "Affirmer"), to the extent that he or she is an owner of Copyright +and Related Rights in the Work, voluntarily elects to apply CC0 to the Work +and publicly distribute the Work under its terms, with knowledge of his or her +Copyright and Related Rights in the Work and the meaning and intended legal +effect of CC0 on those rights. + +1. Copyright and Related Rights. A Work made available under CC0 may be +protected by copyright and related or neighboring rights ("Copyright and +Related Rights"). Copyright and Related Rights include, but are not limited +to, the following: + + i. the right to reproduce, adapt, distribute, perform, display, communicate, + and translate a Work; + + ii. moral rights retained by the original author(s) and/or performer(s); + + iii. publicity and privacy rights pertaining to a person's image or likeness + depicted in a Work; + + iv. rights protecting against unfair competition in regards to a Work, + subject to the limitations in paragraph 4(a), below; + + v. rights protecting the extraction, dissemination, use and reuse of data in + a Work; + + vi. database rights (such as those arising under Directive 96/9/EC of the + European Parliament and of the Council of 11 March 1996 on the legal + protection of databases, and under any national implementation thereof, + including any amended or successor version of such directive); and + + vii. other similar, equivalent or corresponding rights throughout the world + based on applicable law or treaty, and any national implementations thereof. + +2. Waiver. To the greatest extent permitted by, but not in contravention of, +applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and +unconditionally waives, abandons, and surrenders all of Affirmer's Copyright +and Related Rights and associated claims and causes of action, whether now +known or unknown (including existing as well as future claims and causes of +action), in the Work (i) in all territories worldwide, (ii) for the maximum +duration provided by applicable law or treaty (including future time +extensions), (iii) in any current or future medium and for any number of +copies, and (iv) for any purpose whatsoever, including without limitation +commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes +the Waiver for the benefit of each member of the public at large and to the +detriment of Affirmer's heirs and successors, fully intending that such Waiver +shall not be subject to revocation, rescission, cancellation, termination, or +any other legal or equitable action to disrupt the quiet enjoyment of the Work +by the public as contemplated by Affirmer's express Statement of Purpose. + +3. Public License Fallback. Should any part of the Waiver for any reason be +judged legally invalid or ineffective under applicable law, then the Waiver +shall be preserved to the maximum extent permitted taking into account +Affirmer's express Statement of Purpose. In addition, to the extent the Waiver +is so judged Affirmer hereby grants to each affected person a royalty-free, +non transferable, non sublicensable, non exclusive, irrevocable and +unconditional license to exercise Affirmer's Copyright and Related Rights in +the Work (i) in all territories worldwide, (ii) for the maximum duration +provided by applicable law or treaty (including future time extensions), (iii) +in any current or future medium and for any number of copies, and (iv) for any +purpose whatsoever, including without limitation commercial, advertising or +promotional purposes (the "License"). The License shall be deemed effective as +of the date CC0 was applied by Affirmer to the Work. Should any part of the +License for any reason be judged legally invalid or ineffective under +applicable law, such partial invalidity or ineffectiveness shall not +invalidate the remainder of the License, and in such case Affirmer hereby +affirms that he or she will not (i) exercise any of his or her remaining +Copyright and Related Rights in the Work or (ii) assert any associated claims +and causes of action with respect to the Work, in either case contrary to +Affirmer's express Statement of Purpose. + +4. Limitations and Disclaimers. + + a. No trademark or patent rights held by Affirmer are waived, abandoned, + surrendered, licensed or otherwise affected by this document. + + b. Affirmer offers the Work as-is and makes no representations or warranties + of any kind concerning the Work, express, implied, statutory or otherwise, + including without limitation warranties of title, merchantability, fitness + for a particular purpose, non infringement, or the absence of latent or + other defects, accuracy, or the present or absence of errors, whether or not + discoverable, all to the greatest extent permissible under applicable law. + + c. Affirmer disclaims responsibility for clearing rights of other persons + that may apply to the Work or any use thereof, including without limitation + any person's Copyright and Related Rights in the Work. Further, Affirmer + disclaims responsibility for obtaining any necessary consents, permissions + or other rights required for any use of the Work. + + d. Affirmer understands and acknowledges that Creative Commons is not a + party to this document and has no duty or obligation with respect to this + CC0 or use of the Work. + +For more information, please see + diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_clean/address.c b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_clean/address.c new file mode 100644 index 0000000000..d49d9f3b6b --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_clean/address.c @@ -0,0 +1,95 @@ +#include +#include + +#include "address.h" +#include "params.h" +#include "utils.h" + +/* + * Specify which level of Merkle tree (the "layer") we're working on + */ +void set_layer_addr(uint32_t addr[8], uint32_t layer) { + ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; +} + +/* + * Specify which Merkle tree within the level (the "tree address") we're working on + */ +void set_tree_addr(uint32_t addr[8], uint64_t tree) { + ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); +} + +/* + * Specify the reason we'll use this address structure for, that is, what + * hash will we compute with it. This is used so that unrelated types of + * hashes don't accidentally get the same address structure. The type will be + * one of the SPX_ADDR_TYPE constants + */ +void set_type(uint32_t addr[8], uint32_t type) { + ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; +} + +/* + * Copy the layer and tree fields of the address structure. This is used + * when we're doing multiple types of hashes within the same Merkle tree + */ +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); +} + +/* These functions are used for OTS addresses. */ + +/* + * Specify which Merkle leaf we're working on; that is, which OTS keypair + * we're talking about. + */ +void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { + /* We have > 256 OTS at the bottom of the Merkle tree; to specify */ + /* which one, we'd need to express it in two bytes */ + ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR2] = (unsigned char)(keypair >> 8); + ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; +} + +/* + * Copy the layer, tree and keypair fields of the address structure. This is + * used when we're doing multiple things within the same OTS keypair + */ +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); + ((unsigned char *)out)[SPX_OFFSET_KP_ADDR2] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR2]; + ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; +} + +/* + * Specify which Merkle chain within the OTS we're working with + * (the chain address) + */ +void set_chain_addr(uint32_t addr[8], uint32_t chain) { + ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; +} + +/* + * Specify where in the Merkle chain we are +* (the hash address) + */ +void set_hash_addr(uint32_t addr[8], uint32_t hash) { + ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; +} + +/* These functions are used for all hash tree addresses (including FORS). */ + +/* + * Specify the height of the node in the Merkle/FORS tree we are in + * (the tree height) + */ +void set_tree_height(uint32_t addr[8], uint32_t tree_height) { + ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; +} + +/* + * Specify the distance from the left edge of the node in the Merkle/FORS tree + * (the tree index) + */ +void set_tree_index(uint32_t addr[8], uint32_t tree_index) { + u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_clean/address.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_clean/address.h new file mode 100644 index 0000000000..24a84eb40c --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_clean/address.h @@ -0,0 +1,52 @@ +#ifndef SPX_ADDRESS_H +#define SPX_ADDRESS_H + +#include + +#include "params.h" + +/* The hash types that are passed to set_type */ +#define SPX_ADDR_TYPE_WOTS 0 +#define SPX_ADDR_TYPE_WOTSPK 1 +#define SPX_ADDR_TYPE_HASHTREE 2 +#define SPX_ADDR_TYPE_FORSTREE 3 +#define SPX_ADDR_TYPE_FORSPK 4 +#define SPX_ADDR_TYPE_WOTSPRF 5 +#define SPX_ADDR_TYPE_FORSPRF 6 + +#define set_layer_addr SPX_NAMESPACE(set_layer_addr) +void set_layer_addr(uint32_t addr[8], uint32_t layer); + +#define set_tree_addr SPX_NAMESPACE(set_tree_addr) +void set_tree_addr(uint32_t addr[8], uint64_t tree); + +#define set_type SPX_NAMESPACE(set_type) +void set_type(uint32_t addr[8], uint32_t type); + +/* Copies the layer and tree part of one address into the other */ +#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); + +/* These functions are used for WOTS and FORS addresses. */ + +#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) +void set_keypair_addr(uint32_t addr[8], uint32_t keypair); + +#define set_chain_addr SPX_NAMESPACE(set_chain_addr) +void set_chain_addr(uint32_t addr[8], uint32_t chain); + +#define set_hash_addr SPX_NAMESPACE(set_hash_addr) +void set_hash_addr(uint32_t addr[8], uint32_t hash); + +#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); + +/* These functions are used for all hash tree addresses (including FORS). */ + +#define set_tree_height SPX_NAMESPACE(set_tree_height) +void set_tree_height(uint32_t addr[8], uint32_t tree_height); + +#define set_tree_index SPX_NAMESPACE(set_tree_index) +void set_tree_index(uint32_t addr[8], uint32_t tree_index); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_clean/api.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_clean/api.h new file mode 100644 index 0000000000..8208c41bc9 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_clean/api.h @@ -0,0 +1,77 @@ +#ifndef PQCLEAN_SPHINCSSHAKE192SSIMPLE_CLEAN_API_H +#define PQCLEAN_SPHINCSSHAKE192SSIMPLE_CLEAN_API_H + +#include +#include + +#define PQCLEAN_SPHINCSSHAKE192SSIMPLE_CLEAN_CRYPTO_ALGNAME "SPHINCS+-shake-192s-simple" + +#define PQCLEAN_SPHINCSSHAKE192SSIMPLE_CLEAN_CRYPTO_SECRETKEYBYTES 96 +#define PQCLEAN_SPHINCSSHAKE192SSIMPLE_CLEAN_CRYPTO_PUBLICKEYBYTES 48 +#define PQCLEAN_SPHINCSSHAKE192SSIMPLE_CLEAN_CRYPTO_BYTES 16224 + +#define PQCLEAN_SPHINCSSHAKE192SSIMPLE_CLEAN_CRYPTO_SEEDBYTES 72 + +/* + * Returns the length of a secret key, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE192SSIMPLE_CLEAN_crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE192SSIMPLE_CLEAN_crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE192SSIMPLE_CLEAN_crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE192SSIMPLE_CLEAN_crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +int PQCLEAN_SPHINCSSHAKE192SSIMPLE_CLEAN_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +int PQCLEAN_SPHINCSSHAKE192SSIMPLE_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +int PQCLEAN_SPHINCSSHAKE192SSIMPLE_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +int PQCLEAN_SPHINCSSHAKE192SSIMPLE_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, + const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +int PQCLEAN_SPHINCSSHAKE192SSIMPLE_CLEAN_crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +int PQCLEAN_SPHINCSSHAKE192SSIMPLE_CLEAN_crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_clean/context.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_clean/context.h new file mode 100644 index 0000000000..9f8a40ab4e --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_clean/context.h @@ -0,0 +1,22 @@ +#ifndef SPX_CONTEXT_H +#define SPX_CONTEXT_H + +#include +#include + +#include "params.h" + +typedef struct { + uint8_t pub_seed[SPX_N]; + uint8_t sk_seed[SPX_N]; + + +} spx_ctx; + +#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) +void initialize_hash_function(spx_ctx *ctx); + +#define free_hash_function SPX_NAMESPACE(free_hash_function) +void free_hash_function(spx_ctx *ctx); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_clean/context_shake.c b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_clean/context_shake.c new file mode 100644 index 0000000000..9614a103d3 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_clean/context_shake.c @@ -0,0 +1,12 @@ +#include "context.h" + +/* For SHAKE256, there is no immediate reason to initialize at the start, + so this function is an empty operation. */ +void initialize_hash_function(spx_ctx *ctx) { + (void)ctx; /* Suppress an 'unused parameter' warning. */ +} + +// in case the hash function api is heap-based. +void free_hash_function(spx_ctx *ctx) { + (void)ctx; +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_clean/fors.c b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_clean/fors.c new file mode 100644 index 0000000000..96ca72e986 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_clean/fors.c @@ -0,0 +1,156 @@ +#include +#include +#include + +#include "fors.h" + +#include "address.h" +#include "hash.h" +#include "thash.h" +#include "utils.h" +#include "utilsx1.h" + +static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + prf_addr(sk, ctx, fors_leaf_addr); +} + +static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, + const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + thash(leaf, sk, 1, ctx, fors_leaf_addr); +} + +struct fors_gen_leaf_info { + uint32_t leaf_addrx[8]; +}; + +static void fors_gen_leafx1(unsigned char *leaf, + const spx_ctx *ctx, + uint32_t addr_idx, void *info) { + struct fors_gen_leaf_info *fors_info = info; + uint32_t *fors_leaf_addr = fors_info->leaf_addrx; + + /* Only set the parts that the caller doesn't set */ + set_tree_index(fors_leaf_addr, addr_idx); + set_type(fors_leaf_addr, SPX_ADDR_TYPE_FORSPRF); + fors_gen_sk(leaf, ctx, fors_leaf_addr); + + set_type(fors_leaf_addr, SPX_ADDR_TYPE_FORSTREE); + fors_sk_to_leaf(leaf, leaf, + ctx, fors_leaf_addr); +} + +/** + * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + * Assumes indices has space for SPX_FORS_TREES integers. + */ +static void message_to_indices(uint32_t *indices, const unsigned char *m) { + unsigned int i, j; + unsigned int offset = 0; + + for (i = 0; i < SPX_FORS_TREES; i++) { + indices[i] = 0; + for (j = 0; j < SPX_FORS_HEIGHT; j++) { + indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); + offset++; + } + } +} + +/** + * Signs a message m, deriving the secret key from sk_seed and the FTS address. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + uint32_t fors_tree_addr[8] = {0}; + struct fors_gen_leaf_info fors_info = {0}; + uint32_t *fors_leaf_addr = fors_info.leaf_addrx; + uint32_t fors_pk_addr[8] = {0}; + uint32_t idx_offset; + unsigned int i; + + copy_keypair_addr(fors_tree_addr, fors_addr); + copy_keypair_addr(fors_leaf_addr, fors_addr); + + copy_keypair_addr(fors_pk_addr, fors_addr); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); + + message_to_indices(indices, m); + + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); + + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); + + /* Include the secret key part that produces the selected leaf node. */ + fors_gen_sk(sig, ctx, fors_tree_addr); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + sig += SPX_N; + + /* Compute the authentication path for this leaf node. */ + treehashx1(roots + i * SPX_N, sig, ctx, + indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx1, + fors_tree_addr, &fors_info); + + sig += SPX_N * SPX_FORS_HEIGHT; + } + + /* Hash horizontally across all tree roots to derive the public key. */ + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); +} + +/** + * Derives the FORS public key from a signature. + * This can be used for verification by comparing to a known public key, or to + * subsequently verify a signature on the derived public key. The latter is the + * typical use-case when used as an FTS below an OTS in a hypertree. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + unsigned char leaf[SPX_N]; + uint32_t fors_tree_addr[8] = {0}; + uint32_t fors_pk_addr[8] = {0}; + uint32_t idx_offset; + unsigned int i; + + copy_keypair_addr(fors_tree_addr, fors_addr); + copy_keypair_addr(fors_pk_addr, fors_addr); + + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); + + message_to_indices(indices, m); + + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); + + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + + /* Derive the leaf from the included secret key part. */ + fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); + sig += SPX_N; + + /* Derive the corresponding root node of this tree. */ + compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, + sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); + sig += SPX_N * SPX_FORS_HEIGHT; + } + + /* Hash horizontally across all tree roots to derive the public key. */ + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_clean/fors.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_clean/fors.h new file mode 100644 index 0000000000..509140a178 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_clean/fors.h @@ -0,0 +1,32 @@ +#ifndef SPX_FORS_H +#define SPX_FORS_H + +#include + +#include "context.h" +#include "params.h" + +/** + * Signs a message m, deriving the secret key from sk_seed and the FTS address. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +#define fors_sign SPX_NAMESPACE(fors_sign) +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); + +/** + * Derives the FORS public key from a signature. + * This can be used for verification by comparing to a known public key, or to + * subsequently verify a signature on the derived public key. The latter is the + * typical use-case when used as an FTS below an OTS in a hypertree. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_clean/hash.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_clean/hash.h new file mode 100644 index 0000000000..f7c87d4c3c --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_clean/hash.h @@ -0,0 +1,28 @@ +#ifndef SPX_HASH_H +#define SPX_HASH_H + +#include +#include + +#include "context.h" +#include "params.h" + +#define prf_addr SPX_NAMESPACE(prf_addr) +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]); + +#define gen_message_random SPX_NAMESPACE(gen_message_random) +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); + +#define hash_message SPX_NAMESPACE(hash_message) +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); + + + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_clean/hash_shake.c b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_clean/hash_shake.c new file mode 100644 index 0000000000..ff5e7ec918 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_clean/hash_shake.c @@ -0,0 +1,83 @@ +#include +#include + +#include "hash.h" + +#include "address.h" +#include "fips202.h" +#include "params.h" +#include "utils.h" + +/* + * Computes PRF(pk_seed, sk_seed, addr) + */ +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]) { + unsigned char buf[2 * SPX_N + SPX_ADDR_BYTES]; + + memcpy(buf, ctx->pub_seed, SPX_N); + memcpy(buf + SPX_N, addr, SPX_ADDR_BYTES); + memcpy(buf + SPX_N + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); + + shake256(out, SPX_N, buf, 2 * SPX_N + SPX_ADDR_BYTES); +} + +/** + * Computes the message-dependent randomness R, using a secret seed and an + * optional randomization value as well as the message. + */ +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { + (void)ctx; + shake256incctx s_inc; + + shake256_inc_init(&s_inc); + shake256_inc_absorb(&s_inc, sk_prf, SPX_N); + shake256_inc_absorb(&s_inc, optrand, SPX_N); + shake256_inc_absorb(&s_inc, m, mlen); + shake256_inc_finalize(&s_inc); + shake256_inc_squeeze(R, SPX_N, &s_inc); + shake256_inc_ctx_release(&s_inc); +} + +/** + * Computes the message hash using R, the public key, and the message. + * Outputs the message digest and the index of the leaf. The index is split in + * the tree index and the leaf index, for convenient copying to an address. + */ +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { + (void)ctx; +#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) +#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) +#define SPX_LEAF_BITS SPX_TREE_HEIGHT +#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) +#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) + + unsigned char buf[SPX_DGST_BYTES]; + unsigned char *bufp = buf; + shake256incctx s_inc; + + shake256_inc_init(&s_inc); + shake256_inc_absorb(&s_inc, R, SPX_N); + shake256_inc_absorb(&s_inc, pk, SPX_PK_BYTES); + shake256_inc_absorb(&s_inc, m, mlen); + shake256_inc_finalize(&s_inc); + shake256_inc_squeeze(buf, SPX_DGST_BYTES, &s_inc); + shake256_inc_ctx_release(&s_inc); + + memcpy(digest, bufp, SPX_FORS_MSG_BYTES); + bufp += SPX_FORS_MSG_BYTES; + + + *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); + *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); + bufp += SPX_TREE_BYTES; + + *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); + *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_clean/merkle.c b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_clean/merkle.c new file mode 100644 index 0000000000..0c1479fd93 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_clean/merkle.c @@ -0,0 +1,59 @@ +#include +#include + +#include "address.h" +#include "merkle.h" +#include "params.h" +#include "utils.h" +#include "utilsx1.h" +#include "wots.h" +#include "wotsx1.h" + +/* + * This generates a Merkle signature (WOTS signature followed by the Merkle + * authentication path). This is in this file because most of the complexity + * is involved with the WOTS signature; the Merkle authentication path logic + * is mostly hidden in treehashx4 + */ +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf) { + unsigned char *auth_path = sig + SPX_WOTS_BYTES; + struct leaf_info_x1 info = { 0 }; + unsigned steps[ SPX_WOTS_LEN ]; + + info.wots_sig = sig; + chain_lengths(steps, root); + info.wots_steps = steps; + + set_type(&tree_addr[0], SPX_ADDR_TYPE_HASHTREE); + set_type(&info.pk_addr[0], SPX_ADDR_TYPE_WOTSPK); + copy_subtree_addr(&info.leaf_addr[0], wots_addr); + copy_subtree_addr(&info.pk_addr[0], wots_addr); + + info.wots_sign_leaf = idx_leaf; + + treehashx1(root, auth_path, ctx, + idx_leaf, 0, + SPX_TREE_HEIGHT, + wots_gen_leafx1, + tree_addr, &info); +} + +/* Compute root node of the top-most subtree. */ +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { + /* We do not need the auth path in key generation, but it simplifies the + code to have just one treehash routine that computes both root and path + in one function. */ + unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; + uint32_t top_tree_addr[8] = {0}; + uint32_t wots_addr[8] = {0}; + + set_layer_addr(top_tree_addr, SPX_D - 1); + set_layer_addr(wots_addr, SPX_D - 1); + + merkle_sign(auth_path, root, ctx, + wots_addr, top_tree_addr, + (uint32_t)~0 /* ~0 means "don't bother generating an auth path */ ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_clean/merkle.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_clean/merkle.h new file mode 100644 index 0000000000..769cf2e970 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_clean/merkle.h @@ -0,0 +1,21 @@ +#ifndef MERKLE_H_ +#define MERKLE_H_ + +#include + +#include "context.h" +#include "params.h" + +/* Generate a Merkle signature (WOTS signature followed by the Merkle */ +/* authentication path) */ +#define merkle_sign SPX_NAMESPACE(merkle_sign) +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf); + +/* Compute the root node of the top-most subtree. */ +#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); + +#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_clean/nistapi.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_clean/nistapi.h new file mode 100644 index 0000000000..3cb71afad4 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_clean/nistapi.h @@ -0,0 +1,87 @@ +#ifndef SPX_API_H +#define SPX_API_H + +#include +#include + +#include "params.h" + +#define CRYPTO_ALGNAME "SPHINCS+" + +#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES +#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES +#define CRYPTO_BYTES SPX_BYTES +#define CRYPTO_SEEDBYTES (3*SPX_N) + +/* + * Returns the length of a secret key, in bytes + */ +#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) +size_t crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) +size_t crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) +size_t crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) +size_t crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +#define crypto_sign SPX_NAMESPACE(crypto_sign) +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_clean/params.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_clean/params.h new file mode 100644 index 0000000000..b7f6a9077b --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_clean/params.h @@ -0,0 +1,56 @@ +#ifndef SPX_PARAMS_H +#define SPX_PARAMS_H + +#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSSHAKE192SSIMPLE_CLEAN_##s + +/* Hash output length in bytes. */ +#define SPX_N 24 +/* Height of the hypertree. */ +#define SPX_FULL_HEIGHT 63 +/* Number of subtree layer. */ +#define SPX_D 7 +/* FORS tree dimensions. */ +#define SPX_FORS_HEIGHT 14 +#define SPX_FORS_TREES 17 +/* Winternitz parameter, */ +#define SPX_WOTS_W 16 + +/* The hash function is defined by linking a different hash.c file, as opposed + to setting a #define constant. */ + +/* For clarity */ +#define SPX_ADDR_BYTES 32 + +/* WOTS parameters. */ +#define SPX_WOTS_LOGW 4 + +#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) + +/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ +#define SPX_WOTS_LEN2 3 + +#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) +#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) +#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES + +/* Subtree size. */ +#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) + +//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT +// #error SPX_D should always divide SPX_FULL_HEIGHT +//#endif + +/* FORS parameters. */ +#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) +#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) +#define SPX_FORS_PK_BYTES SPX_N + +/* Resulting SPX sizes. */ +#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ + SPX_FULL_HEIGHT * SPX_N) +#define SPX_PK_BYTES (2 * SPX_N) +#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) + +#include "shake_offsets.h" + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_clean/shake_offsets.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_clean/shake_offsets.h new file mode 100644 index 0000000000..6b28d95d91 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_clean/shake_offsets.h @@ -0,0 +1,21 @@ +#ifndef SHAKE_OFFSETS_H_ +#define SHAKE_OFFSETS_H_ + +/* + * Offsets of various fields in the address structure when we use SHAKE as + * the Sphincs+ hash function + */ + +#define SPX_OFFSET_LAYER 3 /* The byte used to specify the Merkle tree layer */ +#define SPX_OFFSET_TREE 8 /* The start of the 8 byte field used to specify the tree */ +#define SPX_OFFSET_TYPE 19 /* The byte used to specify the hash type (reason) */ +#define SPX_OFFSET_KP_ADDR2 22 /* The high byte used to specify the key pair (which one-time signature) */ +#define SPX_OFFSET_KP_ADDR1 23 /* The low byte used to specify the key pair */ +#define SPX_OFFSET_CHAIN_ADDR 27 /* The byte used to specify the chain address (which Winternitz chain) */ +#define SPX_OFFSET_HASH_ADDR 31 /* The byte used to specify the hash address (where in the Winternitz chain) */ +#define SPX_OFFSET_TREE_HGT 27 /* The byte used to specify the height of this node in the FORS or Merkle tree */ +#define SPX_OFFSET_TREE_INDEX 28 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ + +#define SPX_SHAKE 1 + +#endif /* SHAKE_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_clean/sign.c b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_clean/sign.c new file mode 100644 index 0000000000..9d0c7d1b22 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_clean/sign.c @@ -0,0 +1,286 @@ +#include +#include +#include + +#include "address.h" +#include "context.h" +#include "fors.h" +#include "hash.h" +#include "merkle.h" +#include "nistapi.h" +#include "params.h" +#include "randombytes.h" +#include "thash.h" +#include "utils.h" +#include "wots.h" + +/* + * Returns the length of a secret key, in bytes + */ +size_t crypto_sign_secretkeybytes(void) { + return CRYPTO_SECRETKEYBYTES; +} + +/* + * Returns the length of a public key, in bytes + */ +size_t crypto_sign_publickeybytes(void) { + return CRYPTO_PUBLICKEYBYTES; +} + +/* + * Returns the length of a signature, in bytes + */ +size_t crypto_sign_bytes(void) { + return CRYPTO_BYTES; +} + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +size_t crypto_sign_seedbytes(void) { + return CRYPTO_SEEDBYTES; +} + +/* + * Generates an SPX key pair given a seed of length + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [PUB_SEED || root] + */ +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed) { + spx_ctx ctx; + + /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ + memcpy(sk, seed, CRYPTO_SEEDBYTES); + + memcpy(pk, sk + 2 * SPX_N, SPX_N); + + memcpy(ctx.pub_seed, pk, SPX_N); + memcpy(ctx.sk_seed, sk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + /* Compute root node of the top-most subtree. */ + merkle_gen_root(sk + 3 * SPX_N, &ctx); + + // cleanup + free_hash_function(&ctx); + + memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); + + return 0; +} + +/* + * Generates an SPX key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [PUB_SEED || root] + */ +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { + uint8_t seed[CRYPTO_SEEDBYTES]; + randombytes(seed, CRYPTO_SEEDBYTES); + crypto_sign_seed_keypair(pk, sk, seed); + + return 0; +} + +/** + * Returns an array containing a detached signature. + */ +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk) { + spx_ctx ctx; + + const uint8_t *sk_prf = sk + SPX_N; + const uint8_t *pk = sk + 2 * SPX_N; + + uint8_t optrand[SPX_N]; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t root[SPX_N]; + uint32_t i; + uint64_t tree; + uint32_t idx_leaf; + uint32_t wots_addr[8] = {0}; + uint32_t tree_addr[8] = {0}; + + memcpy(ctx.sk_seed, sk, SPX_N); + memcpy(ctx.pub_seed, pk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + + /* Optionally, signing can be made non-deterministic using optrand. + This can help counter side-channel attacks that would benefit from + getting a large number of traces when the signer uses the same nodes. */ + randombytes(optrand, SPX_N); + /* Compute the digest randomization value. */ + gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); + + /* Derive the message digest and leaf index from R, PK and M. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; + + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); + + /* Sign the message hash using FORS. */ + fors_sign(sig, root, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); + sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; + + /* Update the indices for the next layer. */ + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; + } + + free_hash_function(&ctx); + + *siglen = SPX_BYTES; + + return 0; +} + +/** + * Verifies a detached signature and message under a given public key. + */ +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk) { + spx_ctx ctx; + const uint8_t *pub_root = pk + SPX_N; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t wots_pk[SPX_WOTS_BYTES]; + uint8_t root[SPX_N]; + uint8_t leaf[SPX_N]; + unsigned int i; + uint64_t tree; + uint32_t idx_leaf; + uint32_t wots_addr[8] = {0}; + uint32_t tree_addr[8] = {0}; + uint32_t wots_pk_addr[8] = {0}; + + if (siglen != SPX_BYTES) { + return -1; + } + + memcpy(ctx.pub_seed, pk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); + + /* Derive the message digest and leaf index from R || PK || M. */ + /* The additional SPX_N is a result of the hash domain separator. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; + + /* Layer correctly defaults to 0, so no need to set_layer_addr */ + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); + + fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + /* For each subtree.. */ + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + copy_keypair_addr(wots_pk_addr, wots_addr); + + /* The WOTS public key is only correct if the signature was correct. */ + /* Initially, root is the FORS pk, but on subsequent iterations it is + the root of the subtree below the currently processed subtree. */ + wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); + sig += SPX_WOTS_BYTES; + + /* Compute the leaf node using the WOTS public key. */ + thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); + + /* Compute the root node of this subtree. */ + compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, + &ctx, tree_addr); + sig += SPX_TREE_HEIGHT * SPX_N; + + /* Update the indices for the next layer. */ + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; + } + + // cleanup + free_hash_function(&ctx); + + /* Check if the root node equals the root node in the public key. */ + if (memcmp(root, pub_root, SPX_N) != 0) { + return -1; + } + + return 0; +} + + +/** + * Returns an array containing the signature followed by the message. + */ +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk) { + size_t siglen; + + crypto_sign_signature(sm, &siglen, m, mlen, sk); + + memmove(sm + SPX_BYTES, m, mlen); + *smlen = siglen + mlen; + + return 0; +} + +/** + * Verifies a given signature-message pair under a given public key. + */ +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk) { + /* The API caller does not necessarily know what size a signature should be + but SPHINCS+ signatures are always exactly SPX_BYTES. */ + if (smlen < SPX_BYTES) { + memset(m, 0, smlen); + *mlen = 0; + return -1; + } + + *mlen = smlen - SPX_BYTES; + + if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { + memset(m, 0, smlen); + *mlen = 0; + return -1; + } + + /* If verification was successful, move the message to the right place. */ + memmove(m, sm + SPX_BYTES, *mlen); + + return 0; +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_clean/thash.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_clean/thash.h new file mode 100644 index 0000000000..8687ccfb4d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_clean/thash.h @@ -0,0 +1,13 @@ +#ifndef SPX_THASH_H +#define SPX_THASH_H + +#include "context.h" +#include "params.h" + +#include + +#define thash SPX_NAMESPACE(thash) +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_clean/thash_shake_simple.c b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_clean/thash_shake_simple.c new file mode 100644 index 0000000000..98470395e9 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_clean/thash_shake_simple.c @@ -0,0 +1,24 @@ +#include +#include + +#include "thash.h" + +#include "address.h" +#include "params.h" +#include "utils.h" + +#include "fips202.h" + +/** + * Takes an array of inblocks concatenated arrays of SPX_N bytes. + */ +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]) { + PQCLEAN_VLA(uint8_t, buf, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); + + memcpy(buf, ctx->pub_seed, SPX_N); + memcpy(buf + SPX_N, addr, SPX_ADDR_BYTES); + memcpy(buf + SPX_N + SPX_ADDR_BYTES, in, inblocks * SPX_N); + + shake256(out, SPX_N, buf, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_clean/utils.c b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_clean/utils.c new file mode 100644 index 0000000000..177b541fb9 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_clean/utils.c @@ -0,0 +1,148 @@ +#include + +#include "utils.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "thash.h" + +/** + * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. + */ +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in) { + int i; + + /* Iterate over out in decreasing order, for big-endianness. */ + for (i = (signed int)outlen - 1; i >= 0; i--) { + out[i] = in & 0xff; + in = in >> 8; + } +} + +void u32_to_bytes(unsigned char *out, uint32_t in) { + out[0] = (unsigned char)(in >> 24); + out[1] = (unsigned char)(in >> 16); + out[2] = (unsigned char)(in >> 8); + out[3] = (unsigned char)in; +} + +/** + * Converts the inlen bytes in 'in' from big-endian byte order to an integer. + */ +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { + unsigned long long retval = 0; + unsigned int i; + + for (i = 0; i < inlen; i++) { + retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); + } + return retval; +} + +/** + * Computes a root node given a leaf and an auth path. + * Expects address to be complete other than the tree_height and tree_index. + */ +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]) { + uint32_t i; + unsigned char buffer[2 * SPX_N]; + + /* If leaf_idx is odd (last bit = 1), current path element is a right child + and auth_path has to go left. Otherwise it is the other way around. */ + if (leaf_idx & 1) { + memcpy(buffer + SPX_N, leaf, SPX_N); + memcpy(buffer, auth_path, SPX_N); + } else { + memcpy(buffer, leaf, SPX_N); + memcpy(buffer + SPX_N, auth_path, SPX_N); + } + auth_path += SPX_N; + + for (i = 0; i < tree_height - 1; i++) { + leaf_idx >>= 1; + idx_offset >>= 1; + /* Set the address of the node we're creating. */ + set_tree_height(addr, i + 1); + set_tree_index(addr, leaf_idx + idx_offset); + + /* Pick the right or left neighbor, depending on parity of the node. */ + if (leaf_idx & 1) { + thash(buffer + SPX_N, buffer, 2, ctx, addr); + memcpy(buffer, auth_path, SPX_N); + } else { + thash(buffer, buffer, 2, ctx, addr); + memcpy(buffer + SPX_N, auth_path, SPX_N); + } + auth_path += SPX_N; + } + + /* The last iteration is exceptional; we do not copy an auth_path node. */ + leaf_idx >>= 1; + idx_offset >>= 1; + set_tree_height(addr, tree_height); + set_tree_index(addr, leaf_idx + idx_offset); + thash(root, buffer, 2, ctx, addr); +} + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx * /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]) { + PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); + PQCLEAN_VLA(unsigned int, heights, tree_height + 1); + unsigned int offset = 0; + uint32_t idx; + uint32_t tree_idx; + + for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { + /* Add the next leaf node to the stack. */ + gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); + offset++; + heights[offset - 1] = 0; + + /* If this is a node we need for the auth path.. */ + if ((leaf_idx ^ 0x1) == idx) { + memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); + } + + /* While the top-most nodes are of equal height.. */ + while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { + /* Compute index of the new node, in the next layer. */ + tree_idx = (idx >> (heights[offset - 1] + 1)); + + /* Set the address of the node we're creating. */ + set_tree_height(tree_addr, heights[offset - 1] + 1); + set_tree_index(tree_addr, + tree_idx + (idx_offset >> (heights[offset - 1] + 1))); + /* Hash the top-most nodes from the stack together. */ + thash(stack + (offset - 2)*SPX_N, + stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); + offset--; + /* Note that the top-most node is now one layer higher. */ + heights[offset - 1]++; + + /* If this is a node we need for the auth path.. */ + if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { + memcpy(auth_path + heights[offset - 1]*SPX_N, + stack + (offset - 1)*SPX_N, SPX_N); + } + } + } + memcpy(root, stack, SPX_N); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_clean/utils.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_clean/utils.h new file mode 100644 index 0000000000..64f5d5a53a --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_clean/utils.h @@ -0,0 +1,58 @@ +#ifndef SPX_UTILS_H +#define SPX_UTILS_H + +#include + +#include "compat.h" +#include "context.h" +#include "params.h" + + +/* To support MSVC use alloca() instead of VLAs. See #20. */ + + +/** + * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. + */ +#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in); +#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) +void u32_to_bytes(unsigned char *out, uint32_t in); + +/** + * Converts the inlen bytes in 'in' from big-endian byte order to an integer. + */ +#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); + +/** + * Computes a root node given a leaf and an auth path. + * Expects address to be complete other than the tree_height and tree_index. + */ +#define compute_root SPX_NAMESPACE(compute_root) +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]); + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +#define treehash SPX_NAMESPACE(treehash) +void treehash(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx *ctx /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]); + + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_clean/utilsx1.c b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_clean/utilsx1.c new file mode 100644 index 0000000000..fccb69b35d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_clean/utilsx1.c @@ -0,0 +1,100 @@ +#include + +#include "utilsx1.h" + +#include "address.h" +#include "params.h" +#include "thash.h" +#include "utils.h" + +/* + * Generate the entire Merkle tree, computing the authentication path for + * leaf_idx, and the resulting root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) + * + * This expects tree_addr to be initialized to the addr structures for the + * Merkle tree nodes + * + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + * + * This works by using the standard Merkle tree building algorithm, + */ +void treehashx1(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, + uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* Where to write the leaves */, + const spx_ctx * /* ctx */, + uint32_t idx, void *info), + uint32_t tree_addr[8], + void *info) { + /* This is where we keep the intermediate nodes */ + PQCLEAN_VLA(uint8_t, stack, tree_height * SPX_N); + + uint32_t idx; + uint32_t max_idx = (uint32_t)((1 << tree_height) - 1); + for (idx = 0;; idx++) { + unsigned char current[2 * SPX_N]; /* Current logical node is at */ + /* index[SPX_N]. We do this to minimize the number of copies */ + /* needed during a thash */ + gen_leaf( ¤t[SPX_N], ctx, idx + idx_offset, + info ); + + /* Now combine the freshly generated right node with previously */ + /* generated left ones */ + uint32_t internal_idx_offset = idx_offset; + uint32_t internal_idx = idx; + uint32_t internal_leaf = leaf_idx; + uint32_t h; /* The height we are in the Merkle tree */ + for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { + + /* Check if we hit the top of the tree */ + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[SPX_N], SPX_N ); + return; + } + + /* + * Check if the node we have is a part of the + * authentication path; if it is, write it out + */ + if ((internal_idx ^ internal_leaf) == 0x01) { + memcpy( &auth_path[ h * SPX_N ], + ¤t[SPX_N], + SPX_N ); + } + + /* + * Check if we're at a left child; if so, stop going up the stack + * Exception: if we've reached the end of the tree, keep on going + * (so we combine the last 4 nodes into the one root node in two + * more iterations) + */ + if ((internal_idx & 1) == 0 && idx < max_idx) { + break; + } + + /* Ok, we're at a right node */ + /* Now combine the left and right logical nodes together */ + + /* Set the address of the node we're creating. */ + internal_idx_offset >>= 1; + set_tree_height(tree_addr, h + 1); + set_tree_index(tree_addr, internal_idx / 2 + internal_idx_offset ); + + unsigned char *left = &stack[h * SPX_N]; + memcpy( ¤t[0], left, SPX_N ); + thash( ¤t[1 * SPX_N], + ¤t[0 * SPX_N], + 2, ctx, tree_addr); + } + + /* We've hit a left child; save the current for when we get the */ + /* corresponding right right */ + memcpy( &stack[h * SPX_N], ¤t[SPX_N], SPX_N); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_clean/utilsx1.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_clean/utilsx1.h new file mode 100644 index 0000000000..e911d17d53 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_clean/utilsx1.h @@ -0,0 +1,27 @@ +#ifndef SPX_UTILSX4_H +#define SPX_UTILSX4_H + +#include + +#include "context.h" +#include "params.h" + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +#define treehashx1 SPX_NAMESPACE(treehashx1) +void treehashx1(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* Where to write the leaf */, + const spx_ctx * /* ctx */, + uint32_t addr_idx, void *info), + uint32_t tree_addrx4[8], void *info); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_clean/wots.c b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_clean/wots.c new file mode 100644 index 0000000000..249717aaa8 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_clean/wots.c @@ -0,0 +1,108 @@ +#include +#include + +#include "wots.h" +#include "wotsx1.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "thash.h" +#include "utils.h" +#include "utilsx1.h" + +// TODO clarify address expectations, and make them more uniform. +// TODO i.e. do we expect types to be set already? +// TODO and do we expect modifications or copies? + +/** + * Computes the chaining function. + * out and in have to be n-byte arrays. + * + * Interprets in as start-th value of the chain. + * addr has to contain the address of the chain. + */ +static void gen_chain(unsigned char *out, const unsigned char *in, + unsigned int start, unsigned int steps, + const spx_ctx *ctx, uint32_t addr[8]) { + uint32_t i; + + /* Initialize out with the value at position 'start'. */ + memcpy(out, in, SPX_N); + + /* Iterate 'steps' calls to the hash function. */ + for (i = start; i < (start + steps) && i < SPX_WOTS_W; i++) { + set_hash_addr(addr, i); + thash(out, out, 1, ctx, addr); + } +} + +/** + * base_w algorithm as described in draft. + * Interprets an array of bytes as integers in base w. + * This only works when log_w is a divisor of 8. + */ +static void base_w(unsigned int *output, const int out_len, + const unsigned char *input) { + int in = 0; + int out = 0; + unsigned char total = 0; + int bits = 0; + int consumed; + + for (consumed = 0; consumed < out_len; consumed++) { + if (bits == 0) { + total = input[in]; + in++; + bits += 8; + } + bits -= SPX_WOTS_LOGW; + output[out] = (total >> bits) & (SPX_WOTS_W - 1); + out++; + } +} + +/* Computes the WOTS+ checksum over a message (in base_w). */ +static void wots_checksum(unsigned int *csum_base_w, + const unsigned int *msg_base_w) { + unsigned int csum = 0; + unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; + unsigned int i; + + /* Compute checksum. */ + for (i = 0; i < SPX_WOTS_LEN1; i++) { + csum += SPX_WOTS_W - 1 - msg_base_w[i]; + } + + /* Convert checksum to base_w. */ + /* Make sure expected empty zero bits are the least significant bits. */ + csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); + ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); + base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); +} + +/* Takes a message and derives the matching chain lengths. */ +void chain_lengths(unsigned int *lengths, const unsigned char *msg) { + base_w(lengths, SPX_WOTS_LEN1, msg); + wots_checksum(lengths + SPX_WOTS_LEN1, lengths); +} + +/** + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. + * + * Writes the computed public key to 'pk'. + */ +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]) { + unsigned int lengths[SPX_WOTS_LEN]; + uint32_t i; + + chain_lengths(lengths, msg); + + for (i = 0; i < SPX_WOTS_LEN; i++) { + set_chain_addr(addr, i); + gen_chain(pk + i * SPX_N, sig + i * SPX_N, + lengths[i], SPX_WOTS_W - 1 - lengths[i], ctx, addr); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_clean/wots.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_clean/wots.h new file mode 100644 index 0000000000..4e7692eeef --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_clean/wots.h @@ -0,0 +1,25 @@ +#ifndef SPX_WOTS_H +#define SPX_WOTS_H + +#include + +#include "context.h" +#include "params.h" + +/** + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. + * + * Writes the computed public key to 'pk'. + */ +#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]); + +/* + * Compute the chain lengths needed for a given message hash + */ +#define chain_lengths SPX_NAMESPACE(chain_lengths) +void chain_lengths(unsigned int *lengths, const unsigned char *msg); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_clean/wotsx1.c b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_clean/wotsx1.c new file mode 100644 index 0000000000..3adec78dfb --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_clean/wotsx1.c @@ -0,0 +1,76 @@ +#include +#include + +#include "wots.h" +#include "wotsx1.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "thash.h" +#include "utils.h" + +/* + * This generates a WOTS public key + * It also generates the WOTS signature if leaf_info indicates + * that we're signing with this WOTS key + */ +void wots_gen_leafx1(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info) { + struct leaf_info_x1 *info = v_info; + uint32_t *leaf_addr = info->leaf_addr; + uint32_t *pk_addr = info->pk_addr; + unsigned int i, k; + unsigned char pk_buffer[ SPX_WOTS_BYTES ]; + unsigned char *buffer; + uint32_t wots_k_mask; + + if (leaf_idx == info->wots_sign_leaf) { + /* We're traversing the leaf that's signing; generate the WOTS */ + /* signature */ + wots_k_mask = 0; + } else { + /* Nope, we're just generating pk's; turn off the signature logic */ + wots_k_mask = (uint32_t)~0; + } + + set_keypair_addr( leaf_addr, leaf_idx ); + set_keypair_addr( pk_addr, leaf_idx ); + + for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { + uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k to */ + /* the step if we're generating a signature, ~0 if we're not */ + + /* Start with the secret seed */ + set_chain_addr(leaf_addr, i); + set_hash_addr(leaf_addr, 0); + set_type(leaf_addr, SPX_ADDR_TYPE_WOTSPRF); + + prf_addr(buffer, ctx, leaf_addr); + + set_type(leaf_addr, SPX_ADDR_TYPE_WOTS); + + /* Iterate down the WOTS chain */ + for (k = 0;; k++) { + /* Check if this is the value that needs to be saved as a */ + /* part of the WOTS signature */ + if (k == wots_k) { + memcpy( info->wots_sig + i * SPX_N, buffer, SPX_N ); + } + + /* Check if we hit the top of the chain */ + if (k == SPX_WOTS_W - 1) { + break; + } + + /* Iterate one step on the chain */ + set_hash_addr(leaf_addr, k); + + thash(buffer, buffer, 1, ctx, leaf_addr); + } + } + + /* Do the final thash to generate the public keys */ + thash(dest, pk_buffer, SPX_WOTS_LEN, ctx, pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_clean/wotsx1.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_clean/wotsx1.h new file mode 100644 index 0000000000..e617929f96 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_clean/wotsx1.h @@ -0,0 +1,39 @@ +#ifndef WOTSX1_H_ +#define WOTSX1_H_ + +#include + +#include "context.h" +#include "params.h" + +/* + * This is here to provide an interface to the internal wots_gen_leafx1 + * routine. While this routine is not referenced in the package outside of + * wots.c, it is called from the stand-alone benchmark code to characterize + * the performance + */ +struct leaf_info_x1 { + unsigned char *wots_sig; + uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ + uint32_t *wots_steps; + uint32_t leaf_addr[8]; + uint32_t pk_addr[8]; +}; + +/* Macro to set the leaf_info to something 'benign', that is, it would */ +/* run with the same time as it does during the real signing process */ +/* Used only by the benchmark code */ +#define INITIALIZE_LEAF_INFO_X1(info, addr, step_buffer) { \ + (info).wots_sig = 0; \ + (info).wots_sign_leaf = ~0; \ + (info).wots_steps = step_buffer; \ + memcpy( &(info).leaf_addr[0], (addr), 32 ); \ + memcpy( &(info).pk_addr[0], (addr), 32 ); \ + } + +#define wots_gen_leafx1 SPX_NAMESPACE(wots_gen_leafx1) +void wots_gen_leafx1(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info); + +#endif /* WOTSX1_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/LICENSE b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/LICENSE new file mode 100644 index 0000000000..670154e353 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/LICENSE @@ -0,0 +1,116 @@ +CC0 1.0 Universal + +Statement of Purpose + +The laws of most jurisdictions throughout the world automatically confer +exclusive Copyright and Related Rights (defined below) upon the creator and +subsequent owner(s) (each and all, an "owner") of an original work of +authorship and/or a database (each, a "Work"). + +Certain owners wish to permanently relinquish those rights to a Work for the +purpose of contributing to a commons of creative, cultural and scientific +works ("Commons") that the public can reliably and without fear of later +claims of infringement build upon, modify, incorporate in other works, reuse +and redistribute as freely as possible in any form whatsoever and for any +purposes, including without limitation commercial purposes. These owners may +contribute to the Commons to promote the ideal of a free culture and the +further production of creative, cultural and scientific works, or to gain +reputation or greater distribution for their Work in part through the use and +efforts of others. + +For these and/or other purposes and motivations, and without any expectation +of additional consideration or compensation, the person associating CC0 with a +Work (the "Affirmer"), to the extent that he or she is an owner of Copyright +and Related Rights in the Work, voluntarily elects to apply CC0 to the Work +and publicly distribute the Work under its terms, with knowledge of his or her +Copyright and Related Rights in the Work and the meaning and intended legal +effect of CC0 on those rights. + +1. Copyright and Related Rights. A Work made available under CC0 may be +protected by copyright and related or neighboring rights ("Copyright and +Related Rights"). Copyright and Related Rights include, but are not limited +to, the following: + + i. the right to reproduce, adapt, distribute, perform, display, communicate, + and translate a Work; + + ii. moral rights retained by the original author(s) and/or performer(s); + + iii. publicity and privacy rights pertaining to a person's image or likeness + depicted in a Work; + + iv. rights protecting against unfair competition in regards to a Work, + subject to the limitations in paragraph 4(a), below; + + v. rights protecting the extraction, dissemination, use and reuse of data in + a Work; + + vi. database rights (such as those arising under Directive 96/9/EC of the + European Parliament and of the Council of 11 March 1996 on the legal + protection of databases, and under any national implementation thereof, + including any amended or successor version of such directive); and + + vii. other similar, equivalent or corresponding rights throughout the world + based on applicable law or treaty, and any national implementations thereof. + +2. Waiver. To the greatest extent permitted by, but not in contravention of, +applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and +unconditionally waives, abandons, and surrenders all of Affirmer's Copyright +and Related Rights and associated claims and causes of action, whether now +known or unknown (including existing as well as future claims and causes of +action), in the Work (i) in all territories worldwide, (ii) for the maximum +duration provided by applicable law or treaty (including future time +extensions), (iii) in any current or future medium and for any number of +copies, and (iv) for any purpose whatsoever, including without limitation +commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes +the Waiver for the benefit of each member of the public at large and to the +detriment of Affirmer's heirs and successors, fully intending that such Waiver +shall not be subject to revocation, rescission, cancellation, termination, or +any other legal or equitable action to disrupt the quiet enjoyment of the Work +by the public as contemplated by Affirmer's express Statement of Purpose. + +3. Public License Fallback. Should any part of the Waiver for any reason be +judged legally invalid or ineffective under applicable law, then the Waiver +shall be preserved to the maximum extent permitted taking into account +Affirmer's express Statement of Purpose. In addition, to the extent the Waiver +is so judged Affirmer hereby grants to each affected person a royalty-free, +non transferable, non sublicensable, non exclusive, irrevocable and +unconditional license to exercise Affirmer's Copyright and Related Rights in +the Work (i) in all territories worldwide, (ii) for the maximum duration +provided by applicable law or treaty (including future time extensions), (iii) +in any current or future medium and for any number of copies, and (iv) for any +purpose whatsoever, including without limitation commercial, advertising or +promotional purposes (the "License"). The License shall be deemed effective as +of the date CC0 was applied by Affirmer to the Work. Should any part of the +License for any reason be judged legally invalid or ineffective under +applicable law, such partial invalidity or ineffectiveness shall not +invalidate the remainder of the License, and in such case Affirmer hereby +affirms that he or she will not (i) exercise any of his or her remaining +Copyright and Related Rights in the Work or (ii) assert any associated claims +and causes of action with respect to the Work, in either case contrary to +Affirmer's express Statement of Purpose. + +4. Limitations and Disclaimers. + + a. No trademark or patent rights held by Affirmer are waived, abandoned, + surrendered, licensed or otherwise affected by this document. + + b. Affirmer offers the Work as-is and makes no representations or warranties + of any kind concerning the Work, express, implied, statutory or otherwise, + including without limitation warranties of title, merchantability, fitness + for a particular purpose, non infringement, or the absence of latent or + other defects, accuracy, or the present or absence of errors, whether or not + discoverable, all to the greatest extent permissible under applicable law. + + c. Affirmer disclaims responsibility for clearing rights of other persons + that may apply to the Work or any use thereof, including without limitation + any person's Copyright and Related Rights in the Work. Further, Affirmer + disclaims responsibility for obtaining any necessary consents, permissions + or other rights required for any use of the Work. + + d. Affirmer understands and acknowledges that Creative Commons is not a + party to this document and has no duty or obligation with respect to this + CC0 or use of the Work. + +For more information, please see + diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/address.c b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/address.c new file mode 100644 index 0000000000..b956e9cb29 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/address.c @@ -0,0 +1,91 @@ +#include +#include + +#include "address.h" +#include "params.h" +#include "utils.h" + +/* + * Specify which level of Merkle tree (the "layer") we're working on + */ +void set_layer_addr(uint32_t addr[8], uint32_t layer) { + ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; +} + +/* + * Specify which Merkle tree within the level (the "tree address") we're working on + */ +void set_tree_addr(uint32_t addr[8], uint64_t tree) { + ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); +} + +/* + * Specify the reason we'll use this address structure for, that is, what + * hash will we compute with it. This is used so that unrelated types of + * hashes don't accidentally get the same address structure. The type will be + * one of the SPX_ADDR_TYPE constants + */ +void set_type(uint32_t addr[8], uint32_t type) { + ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; +} + +/* + * Copy the layer and tree fields of the address structure. This is used + * when we're doing multiple types of hashes within the same Merkle tree + */ +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); +} + +/* These functions are used for OTS addresses. */ + +/* + * Specify which Merkle leaf we're working on; that is, which OTS keypair + * we're talking about. + */ +void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { + ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; +} + +/* + * Copy the layer, tree and keypair fields of the address structure. This is + * used when we're doing multiple things within the same OTS keypair + */ +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); + ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; +} + +/* + * Specify which Merkle chain within the OTS we're working with + * (the chain address) + */ +void set_chain_addr(uint32_t addr[8], uint32_t chain) { + ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; +} + +/* + * Specify where in the Merkle chain we are +* (the hash address) + */ +void set_hash_addr(uint32_t addr[8], uint32_t hash) { + ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; +} + +/* These functions are used for all hash tree addresses (including FORS). */ + +/* + * Specify the height of the node in the Merkle/FORS tree we are in + * (the tree height) + */ +void set_tree_height(uint32_t addr[8], uint32_t tree_height) { + ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; +} + +/* + * Specify the distance from the left edge of the node in the Merkle/FORS tree + * (the tree index) + */ +void set_tree_index(uint32_t addr[8], uint32_t tree_index) { + u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/address.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/address.h new file mode 100644 index 0000000000..24a84eb40c --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/address.h @@ -0,0 +1,52 @@ +#ifndef SPX_ADDRESS_H +#define SPX_ADDRESS_H + +#include + +#include "params.h" + +/* The hash types that are passed to set_type */ +#define SPX_ADDR_TYPE_WOTS 0 +#define SPX_ADDR_TYPE_WOTSPK 1 +#define SPX_ADDR_TYPE_HASHTREE 2 +#define SPX_ADDR_TYPE_FORSTREE 3 +#define SPX_ADDR_TYPE_FORSPK 4 +#define SPX_ADDR_TYPE_WOTSPRF 5 +#define SPX_ADDR_TYPE_FORSPRF 6 + +#define set_layer_addr SPX_NAMESPACE(set_layer_addr) +void set_layer_addr(uint32_t addr[8], uint32_t layer); + +#define set_tree_addr SPX_NAMESPACE(set_tree_addr) +void set_tree_addr(uint32_t addr[8], uint64_t tree); + +#define set_type SPX_NAMESPACE(set_type) +void set_type(uint32_t addr[8], uint32_t type); + +/* Copies the layer and tree part of one address into the other */ +#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); + +/* These functions are used for WOTS and FORS addresses. */ + +#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) +void set_keypair_addr(uint32_t addr[8], uint32_t keypair); + +#define set_chain_addr SPX_NAMESPACE(set_chain_addr) +void set_chain_addr(uint32_t addr[8], uint32_t chain); + +#define set_hash_addr SPX_NAMESPACE(set_hash_addr) +void set_hash_addr(uint32_t addr[8], uint32_t hash); + +#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); + +/* These functions are used for all hash tree addresses (including FORS). */ + +#define set_tree_height SPX_NAMESPACE(set_tree_height) +void set_tree_height(uint32_t addr[8], uint32_t tree_height); + +#define set_tree_index SPX_NAMESPACE(set_tree_index) +void set_tree_index(uint32_t addr[8], uint32_t tree_index); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/api.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/api.h new file mode 100644 index 0000000000..7787bfd72f --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/api.h @@ -0,0 +1,77 @@ +#ifndef PQCLEAN_SPHINCSSHAKE256FROBUST_AARCH64_API_H +#define PQCLEAN_SPHINCSSHAKE256FROBUST_AARCH64_API_H + +#include +#include + +#define PQCLEAN_SPHINCSSHAKE256FROBUST_AARCH64_CRYPTO_ALGNAME "SPHINCS+-shake-256f-robust" + +#define PQCLEAN_SPHINCSSHAKE256FROBUST_AARCH64_CRYPTO_SECRETKEYBYTES 128 +#define PQCLEAN_SPHINCSSHAKE256FROBUST_AARCH64_CRYPTO_PUBLICKEYBYTES 64 +#define PQCLEAN_SPHINCSSHAKE256FROBUST_AARCH64_CRYPTO_BYTES 49856 + +#define PQCLEAN_SPHINCSSHAKE256FROBUST_AARCH64_CRYPTO_SEEDBYTES 96 + +/* + * Returns the length of a secret key, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE256FROBUST_AARCH64_crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE256FROBUST_AARCH64_crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE256FROBUST_AARCH64_crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE256FROBUST_AARCH64_crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +int PQCLEAN_SPHINCSSHAKE256FROBUST_AARCH64_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +int PQCLEAN_SPHINCSSHAKE256FROBUST_AARCH64_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +int PQCLEAN_SPHINCSSHAKE256FROBUST_AARCH64_crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +int PQCLEAN_SPHINCSSHAKE256FROBUST_AARCH64_crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, + const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +int PQCLEAN_SPHINCSSHAKE256FROBUST_AARCH64_crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +int PQCLEAN_SPHINCSSHAKE256FROBUST_AARCH64_crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/context.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/context.h new file mode 100644 index 0000000000..6e0a33f3b7 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/context.h @@ -0,0 +1,19 @@ +#ifndef SPX_CONTEXT_H +#define SPX_CONTEXT_H + +#include + +#include "params.h" + +typedef struct { + uint8_t pub_seed[SPX_N]; + uint8_t sk_seed[SPX_N]; +} spx_ctx; + +#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) +void initialize_hash_function(spx_ctx *ctx); + +#define free_hash_function SPX_NAMESPACE(free_hash_function) +void free_hash_function(spx_ctx *ctx); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/context_shake.c b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/context_shake.c new file mode 100644 index 0000000000..9614a103d3 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/context_shake.c @@ -0,0 +1,12 @@ +#include "context.h" + +/* For SHAKE256, there is no immediate reason to initialize at the start, + so this function is an empty operation. */ +void initialize_hash_function(spx_ctx *ctx) { + (void)ctx; /* Suppress an 'unused parameter' warning. */ +} + +// in case the hash function api is heap-based. +void free_hash_function(spx_ctx *ctx) { + (void)ctx; +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/f1600x2.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/f1600x2.h new file mode 100644 index 0000000000..70d1af9f14 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/f1600x2.h @@ -0,0 +1,11 @@ +#ifndef SPX_F1600X2_H +#define SPX_F1600X2_H + +#include + +extern uint64_t f1600_RC[24]; +extern void _f1600x2(uint64_t *a, uint64_t *rc); + +#define f1600x2(s) do {_f1600x2((s), f1600_RC);} while(0) + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/f1600x2.s b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/f1600x2.s new file mode 100644 index 0000000000..640ed791ed --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/f1600x2.s @@ -0,0 +1,143 @@ +# From https://github.com/bwesterb/armed-keccak + +.macro round + # Execute theta, but without xoring into the state yet. + # Compute parities p[i] = a[i] ^ a[5+i] ^ ... ^ a[20+i]. + eor3.16b v25, v0, v5, v10 + eor3.16b v26, v1, v6, v11 + eor3.16b v27, v2, v7, v12 + eor3.16b v28, v3, v8, v13 + eor3.16b v29, v4, v9, v14 + + eor3.16b v25, v25, v15, v20 + eor3.16b v26, v26, v16, v21 + eor3.16b v27, v27, v17, v22 + eor3.16b v28, v28, v18, v23 + eor3.16b v29, v29, v19, v24 + + # d[0] = rotl(p[1], 1) ^ p[4] + rax1.2d v30, v29, v26 + # d[3] = rotl(p[4], 1) ^ p[2] + rax1.2d v29, v27, v29 + # d[1] = rotl(p[2], 1) ^ p[0] + rax1.2d v27, v25, v27 + # d[4] = rotl(p[0], 1) ^ p[3] + rax1.2d v25, v28, v25 + # d[2] = rotl(p[3], 1) ^ p[1] + rax1.2d v28, v26, v28 + + # Xor parities from step theta into the state at the same time + # as executing rho and pi. + eor.16b v0, v0, v30 + mov.16b v31, v1 + xar.2d v1, v6, v27, 20 + xar.2d v6, v9, v25, 44 + xar.2d v9, v22, v28, 3 + xar.2d v22, v14, v25, 25 + xar.2d v14, v20, v30, 46 + xar.2d v20, v2, v28, 2 + xar.2d v2, v12, v28, 21 + xar.2d v12, v13, v29, 39 + xar.2d v13, v19, v25, 56 + xar.2d v19, v23, v29, 8 + xar.2d v23, v15, v30, 23 + xar.2d v15, v4, v25, 37 + xar.2d v4, v24, v25, 50 + xar.2d v24, v21, v27, 62 + xar.2d v21, v8, v29, 9 + xar.2d v8, v16, v27, 19 + xar.2d v16, v5, v30, 28 + xar.2d v5, v3, v29, 36 + xar.2d v3, v18, v29, 43 + xar.2d v18, v17, v28, 49 + xar.2d v17, v11, v27, 54 + xar.2d v11, v7, v28, 58 + xar.2d v7, v10, v30, 61 + xar.2d v10, v31, v27, 63 + + # Chi + bcax.16b v25, v0, v2, v1 + bcax.16b v26, v1, v3, v2 + bcax.16b v2, v2, v4, v3 + bcax.16b v3, v3, v0, v4 + bcax.16b v4, v4, v1, v0 + mov.16b v0, v25 + mov.16b v1, v26 + + bcax.16b v25, v5, v7, v6 + bcax.16b v26, v6, v8, v7 + bcax.16b v7, v7, v9, v8 + bcax.16b v8, v8, v5, v9 + bcax.16b v9, v9, v6, v5 + mov.16b v5, v25 + mov.16b v6, v26 + + bcax.16b v25, v10, v12, v11 + bcax.16b v26, v11, v13, v12 + bcax.16b v12, v12, v14, v13 + bcax.16b v13, v13, v10, v14 + bcax.16b v14, v14, v11, v10 + mov.16b v10, v25 + mov.16b v11, v26 + + bcax.16b v25, v15, v17, v16 + bcax.16b v26, v16, v18, v17 + bcax.16b v17, v17, v19, v18 + bcax.16b v18, v18, v15, v19 + bcax.16b v19, v19, v16, v15 + mov.16b v15, v25 + mov.16b v16, v26 + + bcax.16b v25, v20, v22, v21 + bcax.16b v26, v21, v23, v22 + bcax.16b v22, v22, v24, v23 + bcax.16b v23, v23, v20, v24 + bcax.16b v24, v24, v21, v20 + mov.16b v20, v25 + mov.16b v21, v26 + + # iota + ld1r {v25.2d}, [x1], #8 + eor.16b v0, v0, v25 +.endm + +.align 4 +.global __f1600x2 +__f1600x2: + stp d8, d9, [sp,#-16]! + stp d10, d11, [sp,#-16]! + stp d12, d13, [sp,#-16]! + stp d14, d15, [sp,#-16]! + + mov x2, x0 + mov x3, #24 + + ld1.2d {v0, v1, v2, v3}, [x0], #64 + ld1.2d {v4, v5, v6, v7}, [x0], #64 + ld1.2d {v8, v9, v10, v11}, [x0], #64 + ld1.2d {v12, v13, v14, v15}, [x0], #64 + ld1.2d {v16, v17, v18, v19}, [x0], #64 + ld1.2d {v20, v21, v22, v23}, [x0], #64 + ld1.2d {v24}, [x0] + +loop: + round + + subs x3, x3, #1 + cbnz x3, loop + + mov x0, x2 + st1.2d {v0, v1, v2, v3}, [x0], #64 + st1.2d {v4, v5, v6, v7}, [x0], #64 + st1.2d {v8, v9, v10, v11}, [x0], #64 + st1.2d {v12, v13, v14, v15}, [x0], #64 + st1.2d {v16, v17, v18, v19}, [x0], #64 + st1.2d {v20, v21, v22, v23}, [x0], #64 + st1.2d {v24}, [x0] + + ldp d14, d15, [sp], #16 + ldp d12, d13, [sp], #16 + ldp d10, d11, [sp], #16 + ldp d8, d9, [sp], #16 + + ret lr diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/f1600x2_const.c b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/f1600x2_const.c new file mode 100644 index 0000000000..e49c0ba149 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/f1600x2_const.c @@ -0,0 +1,30 @@ +#include "f1600x2.h" + +uint64_t f1600_RC[24] = { + 0x0000000000000001, + 0x0000000000008082, + 0x800000000000808A, + 0x8000000080008000, + 0x000000000000808B, + 0x0000000080000001, + 0x8000000080008081, + 0x8000000000008009, + 0x000000000000008A, + 0x0000000000000088, + 0x0000000080008009, + 0x000000008000000A, + 0x000000008000808B, + 0x800000000000008B, + 0x8000000000008089, + 0x8000000000008003, + 0x8000000000008002, + 0x8000000000000080, + 0x000000000000800A, + 0x800000008000000A, + 0x8000000080008081, + 0x8000000000008080, + 0x0000000080000001, + 0x8000000080008008, +}; + + diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/fips202x2.c b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/fips202x2.c new file mode 100644 index 0000000000..4718c343bc --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/fips202x2.c @@ -0,0 +1,148 @@ +#include +#include + +#include "fips202x2.h" +#include "f1600x2.h" +#include "fips202.h" + +uint64_t load64(const unsigned char *x) { + unsigned long long r = 0, i; + + for (i = 0; i < 8; ++i) { + r |= (unsigned long long)x[i] << 8 * i; + } + return r; +} + +void store64(uint8_t *x, uint64_t u) { + unsigned int i; + + for (i = 0; i < 8; ++i) { + x[i] = (uint8_t)u; + u >>= 8; + } +} + +static void keccak_absorb2x(uint64_t *s, + unsigned int r, + const unsigned char *m0, + const unsigned char *m1, + unsigned long long int mlen, + unsigned char p) { + unsigned long long i; + unsigned char t0[200]; + unsigned char t1[200]; + + while (mlen >= r) { + for (i = 0; i < r / 8; ++i) { + s[2 * i + 0] ^= load64(m0 + 8 * i); + s[2 * i + 1] ^= load64(m1 + 8 * i); + } + + f1600x2(s); + mlen -= r; + m0 += r; + m1 += r; + } + + for (i = 0; i < r; ++i) { + t0[i] = 0; + t1[i] = 0; + } + for (i = 0; i < mlen; ++i) { + t0[i] = m0[i]; + t1[i] = m1[i]; + } + + t0[i] = p; + t1[i] = p; + + t0[r - 1] |= 128; + t1[r - 1] |= 128; + + for (i = 0; i < r / 8; ++i) { + s[2 * i + 0] ^= load64(t0 + 8 * i); + s[2 * i + 1] ^= load64(t1 + 8 * i); + } +} + + +static void keccak_squeezeblocks2x(unsigned char *h0, + unsigned char *h1, + unsigned long long int nblocks, + uint64_t *s, + unsigned int r) { + unsigned int i; + + while (nblocks > 0) { + f1600x2(s); + for (i = 0; i < (r >> 3); i++) { + store64(h0 + 8 * i, s[2 * i + 0]); + store64(h1 + 8 * i, s[2 * i + 1]); + } + h0 += r; + h1 += r; + nblocks--; + } +} + + + +void shake128x2(unsigned char *out0, + unsigned char *out1, + unsigned long long outlen, + unsigned char *in0, + unsigned char *in1, + unsigned long long inlen) { + uint64_t s[50] = {0}; + unsigned char t0[SHAKE128_RATE]; + unsigned char t1[SHAKE128_RATE]; + unsigned int i; + + /* absorb 4 message of identical length in parallel */ + keccak_absorb2x(s, SHAKE128_RATE, in0, in1, inlen, 0x1F); + + /* Squeeze output */ + keccak_squeezeblocks2x(out0, out1, outlen / SHAKE128_RATE, s, SHAKE128_RATE); + + out0 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; + out1 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; + + if (outlen % SHAKE128_RATE) { + keccak_squeezeblocks2x(t0, t1, 1, s, SHAKE128_RATE); + for (i = 0; i < outlen % SHAKE128_RATE; i++) { + out0[i] = t0[i]; + out1[i] = t1[i]; + } + } +} + + +void shake256x2(unsigned char *out0, + unsigned char *out1, + unsigned long long outlen, + unsigned char *in0, + unsigned char *in1, + unsigned long long inlen) { + uint64_t s[50] = {0}; + unsigned char t0[SHAKE256_RATE]; + unsigned char t1[SHAKE256_RATE]; + unsigned int i; + + /* absorb 2 message of identical length in parallel */ + keccak_absorb2x(s, SHAKE256_RATE, in0, in1, inlen, 0x1F); + + /* Squeeze output */ + keccak_squeezeblocks2x(out0, out1, outlen / SHAKE256_RATE, s, SHAKE256_RATE); + + out0 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; + out1 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; + + if (outlen % SHAKE256_RATE) { + keccak_squeezeblocks2x(t0, t1, 1, s, SHAKE256_RATE); + for (i = 0; i < outlen % SHAKE256_RATE; i++) { + out0[i] = t0[i]; + out1[i] = t1[i]; + } + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/fips202x2.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/fips202x2.h new file mode 100644 index 0000000000..7ba58b35d8 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/fips202x2.h @@ -0,0 +1,24 @@ +#ifndef SPX_FIPS202X2_H +#define SPX_FIPS202X2_H + +#include + +uint64_t load64(const unsigned char *x); +void store64(uint8_t *x, uint64_t u); + + +void shake128x2(unsigned char *out0, + unsigned char *out1, + unsigned long long outlen, + unsigned char *in0, + unsigned char *in1, + unsigned long long inlen); + +void shake256x2(unsigned char *out0, + unsigned char *out1, + unsigned long long outlen, + unsigned char *in0, + unsigned char *in1, + unsigned long long inlen); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/fors.c b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/fors.c new file mode 100644 index 0000000000..39193d04e2 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/fors.c @@ -0,0 +1,191 @@ +#include +#include +#include + +#include "fors.h" + +#include "address.h" +#include "hash.h" +#include "hashx2.h" +#include "thash.h" +#include "thashx2.h" +#include "utils.h" +#include "utilsx2.h" + +static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + prf_addr(sk, ctx, fors_leaf_addr); +} + +static void fors_gen_skx2(unsigned char *sk0, + unsigned char *sk1, + const spx_ctx *ctx, + uint32_t fors_leaf_addrx2[2 * 8]) { + prf_addrx2(sk0, sk1, + ctx, fors_leaf_addrx2); +} + +static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, + const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + thash(leaf, sk, 1, ctx, fors_leaf_addr); +} + +static void fors_sk_to_leafx2(unsigned char *leaf0, + unsigned char *leaf1, + const unsigned char *sk0, + const unsigned char *sk1, + const spx_ctx *ctx, + uint32_t fors_leaf_addrx2[2 * 8]) { + thashx2(leaf0, leaf1, + sk0, sk1, + 1, ctx, fors_leaf_addrx2); +} + +struct fors_gen_leaf_info { + uint32_t leaf_addrx[2 * 8]; +}; + +static void fors_gen_leafx2(unsigned char *leaf, + const spx_ctx *ctx, + uint32_t addr_idx, void *info) { + struct fors_gen_leaf_info *fors_info = info; + uint32_t *fors_leaf_addrx2 = fors_info->leaf_addrx; + unsigned int j; + + /* Only set the parts that the caller doesn't set */ + for (j = 0; j < 2; j++) { + set_tree_index(fors_leaf_addrx2 + j * 8, addr_idx + j); + set_type(fors_leaf_addrx2 + j * 8, SPX_ADDR_TYPE_FORSPRF); + } + + fors_gen_skx2(leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + ctx, fors_leaf_addrx2); + + for (j = 0; j < 2; j++) { + set_type(fors_leaf_addrx2 + j * 8, SPX_ADDR_TYPE_FORSTREE); + } + + fors_sk_to_leafx2(leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + ctx, fors_leaf_addrx2); +} + +/** + * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + * Assumes indices has space for SPX_FORS_TREES integers. + */ +static void message_to_indices(uint32_t *indices, const unsigned char *m) { + unsigned int i, j; + unsigned int offset = 0; + + for (i = 0; i < SPX_FORS_TREES; i++) { + indices[i] = 0; + for (j = 0; j < SPX_FORS_HEIGHT; j++) { + indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); + offset++; + } + } +} + +/** + * Signs a message m, deriving the secret key from sk_seed and the FTS address. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + uint32_t fors_tree_addr[2 * 8] = {0}; + struct fors_gen_leaf_info fors_info = {0}; + uint32_t *fors_leaf_addr = fors_info.leaf_addrx; + uint32_t fors_pk_addr[8] = {0}; + uint32_t idx_offset; + unsigned int i; + + for (i = 0; i < 2; i++) { + copy_keypair_addr(fors_tree_addr + 8 * i, fors_addr); + set_type(fors_tree_addr + 8 * i, SPX_ADDR_TYPE_FORSTREE); + copy_keypair_addr(fors_leaf_addr + 8 * i, fors_addr); + } + copy_keypair_addr(fors_pk_addr, fors_addr); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); + + message_to_indices(indices, m); + + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); + + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + + /* Include the secret key part that produces the selected leaf node. */ + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); + fors_gen_sk(sig, ctx, fors_tree_addr); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + sig += SPX_N; + + /* Compute the authentication path for this leaf node. */ + treehashx2(roots + i * SPX_N, sig, ctx, + indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx2, + fors_tree_addr, &fors_info); + + sig += SPX_N * SPX_FORS_HEIGHT; + } + + /* Hash horizontally across all tree roots to derive the public key. */ + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); +} + +/** + * Derives the FORS public key from a signature. + * This can be used for verification by comparing to a known public key, or to + * subsequently verify a signature on the derived public key. The latter is the + * typical use-case when used as an FTS below an OTS in a hypertree. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + unsigned char leaf[SPX_N]; + uint32_t fors_tree_addr[8] = {0}; + uint32_t fors_pk_addr[8] = {0}; + uint32_t idx_offset; + unsigned int i; + + copy_keypair_addr(fors_tree_addr, fors_addr); + copy_keypair_addr(fors_pk_addr, fors_addr); + + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); + + message_to_indices(indices, m); + + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); + + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + + /* Derive the leaf from the included secret key part. */ + fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); + sig += SPX_N; + + /* Derive the corresponding root node of this tree. */ + compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, + sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); + sig += SPX_N * SPX_FORS_HEIGHT; + } + + /* Hash horizontally across all tree roots to derive the public key. */ + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/fors.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/fors.h new file mode 100644 index 0000000000..509140a178 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/fors.h @@ -0,0 +1,32 @@ +#ifndef SPX_FORS_H +#define SPX_FORS_H + +#include + +#include "context.h" +#include "params.h" + +/** + * Signs a message m, deriving the secret key from sk_seed and the FTS address. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +#define fors_sign SPX_NAMESPACE(fors_sign) +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); + +/** + * Derives the FORS public key from a signature. + * This can be used for verification by comparing to a known public key, or to + * subsequently verify a signature on the derived public key. The latter is the + * typical use-case when used as an FTS below an OTS in a hypertree. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/hash.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/hash.h new file mode 100644 index 0000000000..f7c87d4c3c --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/hash.h @@ -0,0 +1,28 @@ +#ifndef SPX_HASH_H +#define SPX_HASH_H + +#include +#include + +#include "context.h" +#include "params.h" + +#define prf_addr SPX_NAMESPACE(prf_addr) +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]); + +#define gen_message_random SPX_NAMESPACE(gen_message_random) +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); + +#define hash_message SPX_NAMESPACE(hash_message) +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); + + + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/hash_shake.c b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/hash_shake.c new file mode 100644 index 0000000000..ff5e7ec918 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/hash_shake.c @@ -0,0 +1,83 @@ +#include +#include + +#include "hash.h" + +#include "address.h" +#include "fips202.h" +#include "params.h" +#include "utils.h" + +/* + * Computes PRF(pk_seed, sk_seed, addr) + */ +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]) { + unsigned char buf[2 * SPX_N + SPX_ADDR_BYTES]; + + memcpy(buf, ctx->pub_seed, SPX_N); + memcpy(buf + SPX_N, addr, SPX_ADDR_BYTES); + memcpy(buf + SPX_N + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); + + shake256(out, SPX_N, buf, 2 * SPX_N + SPX_ADDR_BYTES); +} + +/** + * Computes the message-dependent randomness R, using a secret seed and an + * optional randomization value as well as the message. + */ +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { + (void)ctx; + shake256incctx s_inc; + + shake256_inc_init(&s_inc); + shake256_inc_absorb(&s_inc, sk_prf, SPX_N); + shake256_inc_absorb(&s_inc, optrand, SPX_N); + shake256_inc_absorb(&s_inc, m, mlen); + shake256_inc_finalize(&s_inc); + shake256_inc_squeeze(R, SPX_N, &s_inc); + shake256_inc_ctx_release(&s_inc); +} + +/** + * Computes the message hash using R, the public key, and the message. + * Outputs the message digest and the index of the leaf. The index is split in + * the tree index and the leaf index, for convenient copying to an address. + */ +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { + (void)ctx; +#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) +#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) +#define SPX_LEAF_BITS SPX_TREE_HEIGHT +#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) +#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) + + unsigned char buf[SPX_DGST_BYTES]; + unsigned char *bufp = buf; + shake256incctx s_inc; + + shake256_inc_init(&s_inc); + shake256_inc_absorb(&s_inc, R, SPX_N); + shake256_inc_absorb(&s_inc, pk, SPX_PK_BYTES); + shake256_inc_absorb(&s_inc, m, mlen); + shake256_inc_finalize(&s_inc); + shake256_inc_squeeze(buf, SPX_DGST_BYTES, &s_inc); + shake256_inc_ctx_release(&s_inc); + + memcpy(digest, bufp, SPX_FORS_MSG_BYTES); + bufp += SPX_FORS_MSG_BYTES; + + + *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); + *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); + bufp += SPX_TREE_BYTES; + + *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); + *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/hash_shakex2.c b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/hash_shakex2.c new file mode 100644 index 0000000000..99571916a2 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/hash_shakex2.c @@ -0,0 +1,52 @@ +#include +#include + +#include "hashx2.h" + +#include "address.h" +#include "f1600x2.h" +#include "fips202x2.h" +#include "params.h" + +/* + * 2-way parallel version of prf_addr; takes 2x as much input and output + */ +void prf_addrx2(unsigned char *out0, + unsigned char *out1, + const spx_ctx *ctx, + const uint32_t addrx2[2 * 8]) { + /* As we write and read only a few quadwords, it is more efficient to + * build and extract from the fourway SHAKE256 state by hand. */ + uint64_t state[50] = {0}; + + for (int i = 0; i < SPX_N / 8; i++) { + uint64_t x = load64(ctx->pub_seed + 8 * i); + state[2 * i] = x; + state[2 * i + 1] = x; + } + for (int i = 0; i < 4; i++) { + state[2 * (SPX_N / 8 + i)] = (((uint64_t)addrx2[1 + 2 * i]) << 32) + | (uint64_t)addrx2[2 * i]; + state[2 * (SPX_N / 8 + i) + 1] = (((uint64_t)addrx2[8 + 1 + 2 * i]) << 32) + | (uint64_t)addrx2[8 + 2 * i]; + } + for (int i = 0; i < SPX_N / 8; i++) { + uint64_t x = load64(ctx->sk_seed + 8 * i); + state[2 * (SPX_N / 8 + i + 4)] = x; + state[2 * (SPX_N / 8 + i + 4) + 1] = x; + } + + /* SHAKE domain separator and padding. */ + state[2 * (SPX_N / 4 + 4)] = 0x1f; + state[2 * (SPX_N / 4 + 4) + 1] = 0x1f; + + state[2 * 16] = 0x80ULL << 56; + state[2 * 16 + 1] = 0x80ULL << 56; + + f1600x2(state); + + for (int i = 0; i < SPX_N / 8; i++) { + store64(out0 + 8 * i, state[2 * i]); + store64(out1 + 8 * i, state[2 * i + 1]); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/hashx2.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/hashx2.h new file mode 100644 index 0000000000..99b8873a9b --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/hashx2.h @@ -0,0 +1,14 @@ +#ifndef SPX_HASHX2_H +#define SPX_HASHX2_H + +#include "context.h" +#include "params.h" +#include + +#define prf_addrx2 SPX_NAMESPACE(prf_addrx2) +void prf_addrx2(unsigned char *out0, + unsigned char *out1, + const spx_ctx *ctx, + const uint32_t addrx2[2 * 8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/merkle.c b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/merkle.c new file mode 100644 index 0000000000..c94ee23939 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/merkle.c @@ -0,0 +1,64 @@ +#include +#include + +#include "merkle.h" + +#include "address.h" +#include "params.h" +#include "utils.h" +#include "utilsx2.h" +#include "wots.h" +#include "wotsx2.h" + +/* + * This generates a Merkle signature (WOTS signature followed by the Merkle + * authentication path). + */ +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf) { + unsigned char *auth_path = sig + SPX_WOTS_BYTES; + uint32_t tree_addrx2[2 * 8] = { 0 }; + int j; + struct leaf_info_x2 info = { 0 }; + unsigned steps[ SPX_WOTS_LEN ]; + + info.wots_sig = sig; + chain_lengths(steps, root); + info.wots_steps = steps; + + for (j = 0; j < 2; j++) { + set_type(&tree_addrx2[8 * j], SPX_ADDR_TYPE_HASHTREE); + set_type(&info.leaf_addr[8 * j], SPX_ADDR_TYPE_WOTS); + set_type(&info.pk_addr[8 * j], SPX_ADDR_TYPE_WOTSPK); + copy_subtree_addr(&tree_addrx2[8 * j], tree_addr); + copy_subtree_addr(&info.leaf_addr[8 * j], wots_addr); + copy_subtree_addr(&info.pk_addr[8 * j], wots_addr); + } + + info.wots_sign_leaf = idx_leaf; + + treehashx2(root, auth_path, ctx, + idx_leaf, 0, + SPX_TREE_HEIGHT, + wots_gen_leafx2, + tree_addrx2, &info); +} + +/* Compute root node of the top-most subtree. */ +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { + /* We do not need the auth path in key generation, but it simplifies the + code to have just one treehash routine that computes both root and path + in one function. */ + unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; + uint32_t top_tree_addr[8] = {0}; + uint32_t wots_addr[8] = {0}; + + set_layer_addr(top_tree_addr, SPX_D - 1); + set_layer_addr(wots_addr, SPX_D - 1); + + merkle_sign(auth_path, root, ctx, + wots_addr, top_tree_addr, + ~0 /* ~0 means "don't bother generating an auth path */ ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/merkle.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/merkle.h new file mode 100644 index 0000000000..769cf2e970 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/merkle.h @@ -0,0 +1,21 @@ +#ifndef MERKLE_H_ +#define MERKLE_H_ + +#include + +#include "context.h" +#include "params.h" + +/* Generate a Merkle signature (WOTS signature followed by the Merkle */ +/* authentication path) */ +#define merkle_sign SPX_NAMESPACE(merkle_sign) +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf); + +/* Compute the root node of the top-most subtree. */ +#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); + +#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/nistapi.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/nistapi.h new file mode 100644 index 0000000000..3cb71afad4 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/nistapi.h @@ -0,0 +1,87 @@ +#ifndef SPX_API_H +#define SPX_API_H + +#include +#include + +#include "params.h" + +#define CRYPTO_ALGNAME "SPHINCS+" + +#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES +#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES +#define CRYPTO_BYTES SPX_BYTES +#define CRYPTO_SEEDBYTES (3*SPX_N) + +/* + * Returns the length of a secret key, in bytes + */ +#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) +size_t crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) +size_t crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) +size_t crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) +size_t crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +#define crypto_sign SPX_NAMESPACE(crypto_sign) +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/params.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/params.h new file mode 100644 index 0000000000..7dc7db3106 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/params.h @@ -0,0 +1,56 @@ +#ifndef SPX_PARAMS_H +#define SPX_PARAMS_H + +#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSSHAKE256FROBUST_AARCH64_##s + +/* Hash output length in bytes. */ +#define SPX_N 32 +/* Height of the hypertree. */ +#define SPX_FULL_HEIGHT 68 +/* Number of subtree layer. */ +#define SPX_D 17 +/* FORS tree dimensions. */ +#define SPX_FORS_HEIGHT 9 +#define SPX_FORS_TREES 35 +/* Winternitz parameter, */ +#define SPX_WOTS_W 16 + +/* The hash function is defined by linking a different hash.c file, as opposed + to setting a #define constant. */ + +/* For clarity */ +#define SPX_ADDR_BYTES 32 + +/* WOTS parameters. */ +#define SPX_WOTS_LOGW 4 + +#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) + +/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ +#define SPX_WOTS_LEN2 3 + +#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) +#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) +#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES + +/* Subtree size. */ +#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) + +//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT +// #error SPX_D should always divide SPX_FULL_HEIGHT +//#endif + +/* FORS parameters. */ +#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) +#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) +#define SPX_FORS_PK_BYTES SPX_N + +/* Resulting SPX sizes. */ +#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ + SPX_FULL_HEIGHT * SPX_N) +#define SPX_PK_BYTES (2 * SPX_N) +#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) + +#include "shake_offsets.h" + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/shake_offsets.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/shake_offsets.h new file mode 100644 index 0000000000..6b28d95d91 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/shake_offsets.h @@ -0,0 +1,21 @@ +#ifndef SHAKE_OFFSETS_H_ +#define SHAKE_OFFSETS_H_ + +/* + * Offsets of various fields in the address structure when we use SHAKE as + * the Sphincs+ hash function + */ + +#define SPX_OFFSET_LAYER 3 /* The byte used to specify the Merkle tree layer */ +#define SPX_OFFSET_TREE 8 /* The start of the 8 byte field used to specify the tree */ +#define SPX_OFFSET_TYPE 19 /* The byte used to specify the hash type (reason) */ +#define SPX_OFFSET_KP_ADDR2 22 /* The high byte used to specify the key pair (which one-time signature) */ +#define SPX_OFFSET_KP_ADDR1 23 /* The low byte used to specify the key pair */ +#define SPX_OFFSET_CHAIN_ADDR 27 /* The byte used to specify the chain address (which Winternitz chain) */ +#define SPX_OFFSET_HASH_ADDR 31 /* The byte used to specify the hash address (where in the Winternitz chain) */ +#define SPX_OFFSET_TREE_HGT 27 /* The byte used to specify the height of this node in the FORS or Merkle tree */ +#define SPX_OFFSET_TREE_INDEX 28 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ + +#define SPX_SHAKE 1 + +#endif /* SHAKE_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/sign.c b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/sign.c new file mode 100644 index 0000000000..9d0c7d1b22 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/sign.c @@ -0,0 +1,286 @@ +#include +#include +#include + +#include "address.h" +#include "context.h" +#include "fors.h" +#include "hash.h" +#include "merkle.h" +#include "nistapi.h" +#include "params.h" +#include "randombytes.h" +#include "thash.h" +#include "utils.h" +#include "wots.h" + +/* + * Returns the length of a secret key, in bytes + */ +size_t crypto_sign_secretkeybytes(void) { + return CRYPTO_SECRETKEYBYTES; +} + +/* + * Returns the length of a public key, in bytes + */ +size_t crypto_sign_publickeybytes(void) { + return CRYPTO_PUBLICKEYBYTES; +} + +/* + * Returns the length of a signature, in bytes + */ +size_t crypto_sign_bytes(void) { + return CRYPTO_BYTES; +} + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +size_t crypto_sign_seedbytes(void) { + return CRYPTO_SEEDBYTES; +} + +/* + * Generates an SPX key pair given a seed of length + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [PUB_SEED || root] + */ +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed) { + spx_ctx ctx; + + /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ + memcpy(sk, seed, CRYPTO_SEEDBYTES); + + memcpy(pk, sk + 2 * SPX_N, SPX_N); + + memcpy(ctx.pub_seed, pk, SPX_N); + memcpy(ctx.sk_seed, sk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + /* Compute root node of the top-most subtree. */ + merkle_gen_root(sk + 3 * SPX_N, &ctx); + + // cleanup + free_hash_function(&ctx); + + memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); + + return 0; +} + +/* + * Generates an SPX key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [PUB_SEED || root] + */ +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { + uint8_t seed[CRYPTO_SEEDBYTES]; + randombytes(seed, CRYPTO_SEEDBYTES); + crypto_sign_seed_keypair(pk, sk, seed); + + return 0; +} + +/** + * Returns an array containing a detached signature. + */ +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk) { + spx_ctx ctx; + + const uint8_t *sk_prf = sk + SPX_N; + const uint8_t *pk = sk + 2 * SPX_N; + + uint8_t optrand[SPX_N]; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t root[SPX_N]; + uint32_t i; + uint64_t tree; + uint32_t idx_leaf; + uint32_t wots_addr[8] = {0}; + uint32_t tree_addr[8] = {0}; + + memcpy(ctx.sk_seed, sk, SPX_N); + memcpy(ctx.pub_seed, pk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + + /* Optionally, signing can be made non-deterministic using optrand. + This can help counter side-channel attacks that would benefit from + getting a large number of traces when the signer uses the same nodes. */ + randombytes(optrand, SPX_N); + /* Compute the digest randomization value. */ + gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); + + /* Derive the message digest and leaf index from R, PK and M. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; + + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); + + /* Sign the message hash using FORS. */ + fors_sign(sig, root, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); + sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; + + /* Update the indices for the next layer. */ + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; + } + + free_hash_function(&ctx); + + *siglen = SPX_BYTES; + + return 0; +} + +/** + * Verifies a detached signature and message under a given public key. + */ +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk) { + spx_ctx ctx; + const uint8_t *pub_root = pk + SPX_N; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t wots_pk[SPX_WOTS_BYTES]; + uint8_t root[SPX_N]; + uint8_t leaf[SPX_N]; + unsigned int i; + uint64_t tree; + uint32_t idx_leaf; + uint32_t wots_addr[8] = {0}; + uint32_t tree_addr[8] = {0}; + uint32_t wots_pk_addr[8] = {0}; + + if (siglen != SPX_BYTES) { + return -1; + } + + memcpy(ctx.pub_seed, pk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); + + /* Derive the message digest and leaf index from R || PK || M. */ + /* The additional SPX_N is a result of the hash domain separator. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; + + /* Layer correctly defaults to 0, so no need to set_layer_addr */ + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); + + fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + /* For each subtree.. */ + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + copy_keypair_addr(wots_pk_addr, wots_addr); + + /* The WOTS public key is only correct if the signature was correct. */ + /* Initially, root is the FORS pk, but on subsequent iterations it is + the root of the subtree below the currently processed subtree. */ + wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); + sig += SPX_WOTS_BYTES; + + /* Compute the leaf node using the WOTS public key. */ + thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); + + /* Compute the root node of this subtree. */ + compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, + &ctx, tree_addr); + sig += SPX_TREE_HEIGHT * SPX_N; + + /* Update the indices for the next layer. */ + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; + } + + // cleanup + free_hash_function(&ctx); + + /* Check if the root node equals the root node in the public key. */ + if (memcmp(root, pub_root, SPX_N) != 0) { + return -1; + } + + return 0; +} + + +/** + * Returns an array containing the signature followed by the message. + */ +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk) { + size_t siglen; + + crypto_sign_signature(sm, &siglen, m, mlen, sk); + + memmove(sm + SPX_BYTES, m, mlen); + *smlen = siglen + mlen; + + return 0; +} + +/** + * Verifies a given signature-message pair under a given public key. + */ +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk) { + /* The API caller does not necessarily know what size a signature should be + but SPHINCS+ signatures are always exactly SPX_BYTES. */ + if (smlen < SPX_BYTES) { + memset(m, 0, smlen); + *mlen = 0; + return -1; + } + + *mlen = smlen - SPX_BYTES; + + if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { + memset(m, 0, smlen); + *mlen = 0; + return -1; + } + + /* If verification was successful, move the message to the right place. */ + memmove(m, sm + SPX_BYTES, *mlen); + + return 0; +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/thash.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/thash.h new file mode 100644 index 0000000000..8687ccfb4d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/thash.h @@ -0,0 +1,13 @@ +#ifndef SPX_THASH_H +#define SPX_THASH_H + +#include "context.h" +#include "params.h" + +#include + +#define thash SPX_NAMESPACE(thash) +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/thash_shake_robustx2.c b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/thash_shake_robustx2.c new file mode 100644 index 0000000000..454fc0f4e2 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/thash_shake_robustx2.c @@ -0,0 +1,112 @@ +#include +#include + +#include "thash.h" +#include "thashx2.h" + +#include "address.h" +#include "params.h" +#include "utils.h" + +#include "f1600x2.h" +#include "fips202x2.h" + + +void thash(unsigned char *out, + const unsigned char *in, + unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]) { + uint32_t addrx2 [2 * 8] = { + addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], addr[6], addr[7], + addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], addr[6], addr[7] + }; + thashx2(out, out, in, in, inblocks, ctx, addrx2); +} + +/** + * 2-way parallel version of thash; takes 2x as much input and output + */ +void thashx2(unsigned char *out0, + unsigned char *out1, + const unsigned char *in0, + const unsigned char *in1, + unsigned int inblocks, + const spx_ctx *ctx, uint32_t addrx2[2 * 8]) { + if (inblocks == 1 || inblocks == 2) { + /* As we write and read only a few quadwords, it is more efficient to + * build and extract from the twoway SHAKE256 state by hand. */ + uint64_t state[50] = {0}; + uint64_t state2[50]; + + for (int i = 0; i < SPX_N / 8; i++) { + uint64_t x = load64(ctx->pub_seed + 8 * i); + state[2 * i] = x; + state[2 * i + 1] = x; + } + for (int i = 0; i < 4; i++) { + state[2 * (SPX_N / 8 + i)] = (((uint64_t)addrx2[1 + 2 * i]) << 32) + | (uint64_t)addrx2[2 * i]; + state[2 * (SPX_N / 8 + i) + 1] = (((uint64_t)addrx2[8 + 1 + 2 * i]) << 32) + | (uint64_t)addrx2[8 + 2 * i]; + } + + /* Domain separator and padding. */ + state[2 * 16] = 0x80ULL << 56; + state[2 * 16 + 1] = 0x80ULL << 56; + + state[2 * ((SPX_N / 8) + 4)] ^= 0x1f; + state[2 * ((SPX_N / 8) + 4) + 1] ^= 0x1f; + + /* We will permutate state2 with f1600x2 to compute the bitmask, + * but first we'll copy it to state2 which will be used to compute + * the final output, as its input is almost identical. */ + memcpy(state2, state, 400); + + f1600x2(state); + + /* By copying from state, state2 already contains the pub_seed + * and address. We just need to copy in the input blocks xorred with + * the bitmask we just computed. */ + for (unsigned int i = 0; i < (SPX_N / 8) * inblocks; i++) { + state2[2 * (SPX_N / 8 + 4 + i)] = state[2 * i] ^ load64(in0 + 8 * i); + state2[2 * (SPX_N / 8 + 4 + i) + 1] = state[2 * i + 1] ^ load64(in1 + 8 * i); + } + + /* Domain separator and start of padding. Note that the quadwords + * around are already zeroed for state from which we copied. + * We do a XOR instead of a set as this might be the 16th quadword + * when N=32 and inblocks=2, which already contains the end + * of the padding. */ + state2[2 * ((SPX_N / 8) * (1 + inblocks) + 4)] ^= 0x1f; + state2[2 * ((SPX_N / 8) * (1 + inblocks) + 4) + 1] ^= 0x1f; + + f1600x2(state2); + + for (int i = 0; i < SPX_N / 8; i++) { + store64(out0 + 8 * i, state2[2 * i]); + store64(out1 + 8 * i, state2[2 * i + 1]); + } + } else { + PQCLEAN_VLA(unsigned char, buf0, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, buf1, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, bitmask0, inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, bitmask1, inblocks * SPX_N); + unsigned int i; + + memcpy(buf0, ctx->pub_seed, SPX_N); + memcpy(buf1, ctx->pub_seed, SPX_N); + memcpy(buf0 + SPX_N, addrx2 + 0 * 8, SPX_ADDR_BYTES); + memcpy(buf1 + SPX_N, addrx2 + 1 * 8, SPX_ADDR_BYTES); + + shake256x2(bitmask0, bitmask1, inblocks * SPX_N, + buf0, buf1, SPX_N + SPX_ADDR_BYTES); + + for (i = 0; i < inblocks * SPX_N; i++) { + buf0[SPX_N + SPX_ADDR_BYTES + i] = in0[i] ^ bitmask0[i]; + buf1[SPX_N + SPX_ADDR_BYTES + i] = in1[i] ^ bitmask1[i]; + } + + shake256x2(out0, out1, SPX_N, + buf0, buf1, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/thashx2.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/thashx2.h new file mode 100644 index 0000000000..040375e618 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/thashx2.h @@ -0,0 +1,16 @@ +#ifndef SPX_THASHX2_H +#define SPX_THASHX2_H + +#include "context.h" +#include "params.h" +#include + +#define thashx2 SPX_NAMESPACE(thashx2) +void thashx2(unsigned char *out0, + unsigned char *out1, + const unsigned char *in0, + const unsigned char *in1, + unsigned int inblocks, + const spx_ctx *ctx, uint32_t addrx2[2 * 8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/utils.c b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/utils.c new file mode 100644 index 0000000000..177b541fb9 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/utils.c @@ -0,0 +1,148 @@ +#include + +#include "utils.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "thash.h" + +/** + * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. + */ +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in) { + int i; + + /* Iterate over out in decreasing order, for big-endianness. */ + for (i = (signed int)outlen - 1; i >= 0; i--) { + out[i] = in & 0xff; + in = in >> 8; + } +} + +void u32_to_bytes(unsigned char *out, uint32_t in) { + out[0] = (unsigned char)(in >> 24); + out[1] = (unsigned char)(in >> 16); + out[2] = (unsigned char)(in >> 8); + out[3] = (unsigned char)in; +} + +/** + * Converts the inlen bytes in 'in' from big-endian byte order to an integer. + */ +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { + unsigned long long retval = 0; + unsigned int i; + + for (i = 0; i < inlen; i++) { + retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); + } + return retval; +} + +/** + * Computes a root node given a leaf and an auth path. + * Expects address to be complete other than the tree_height and tree_index. + */ +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]) { + uint32_t i; + unsigned char buffer[2 * SPX_N]; + + /* If leaf_idx is odd (last bit = 1), current path element is a right child + and auth_path has to go left. Otherwise it is the other way around. */ + if (leaf_idx & 1) { + memcpy(buffer + SPX_N, leaf, SPX_N); + memcpy(buffer, auth_path, SPX_N); + } else { + memcpy(buffer, leaf, SPX_N); + memcpy(buffer + SPX_N, auth_path, SPX_N); + } + auth_path += SPX_N; + + for (i = 0; i < tree_height - 1; i++) { + leaf_idx >>= 1; + idx_offset >>= 1; + /* Set the address of the node we're creating. */ + set_tree_height(addr, i + 1); + set_tree_index(addr, leaf_idx + idx_offset); + + /* Pick the right or left neighbor, depending on parity of the node. */ + if (leaf_idx & 1) { + thash(buffer + SPX_N, buffer, 2, ctx, addr); + memcpy(buffer, auth_path, SPX_N); + } else { + thash(buffer, buffer, 2, ctx, addr); + memcpy(buffer + SPX_N, auth_path, SPX_N); + } + auth_path += SPX_N; + } + + /* The last iteration is exceptional; we do not copy an auth_path node. */ + leaf_idx >>= 1; + idx_offset >>= 1; + set_tree_height(addr, tree_height); + set_tree_index(addr, leaf_idx + idx_offset); + thash(root, buffer, 2, ctx, addr); +} + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx * /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]) { + PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); + PQCLEAN_VLA(unsigned int, heights, tree_height + 1); + unsigned int offset = 0; + uint32_t idx; + uint32_t tree_idx; + + for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { + /* Add the next leaf node to the stack. */ + gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); + offset++; + heights[offset - 1] = 0; + + /* If this is a node we need for the auth path.. */ + if ((leaf_idx ^ 0x1) == idx) { + memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); + } + + /* While the top-most nodes are of equal height.. */ + while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { + /* Compute index of the new node, in the next layer. */ + tree_idx = (idx >> (heights[offset - 1] + 1)); + + /* Set the address of the node we're creating. */ + set_tree_height(tree_addr, heights[offset - 1] + 1); + set_tree_index(tree_addr, + tree_idx + (idx_offset >> (heights[offset - 1] + 1))); + /* Hash the top-most nodes from the stack together. */ + thash(stack + (offset - 2)*SPX_N, + stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); + offset--; + /* Note that the top-most node is now one layer higher. */ + heights[offset - 1]++; + + /* If this is a node we need for the auth path.. */ + if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { + memcpy(auth_path + heights[offset - 1]*SPX_N, + stack + (offset - 1)*SPX_N, SPX_N); + } + } + } + memcpy(root, stack, SPX_N); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/utils.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/utils.h new file mode 100644 index 0000000000..64f5d5a53a --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/utils.h @@ -0,0 +1,58 @@ +#ifndef SPX_UTILS_H +#define SPX_UTILS_H + +#include + +#include "compat.h" +#include "context.h" +#include "params.h" + + +/* To support MSVC use alloca() instead of VLAs. See #20. */ + + +/** + * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. + */ +#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in); +#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) +void u32_to_bytes(unsigned char *out, uint32_t in); + +/** + * Converts the inlen bytes in 'in' from big-endian byte order to an integer. + */ +#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); + +/** + * Computes a root node given a leaf and an auth path. + * Expects address to be complete other than the tree_height and tree_index. + */ +#define compute_root SPX_NAMESPACE(compute_root) +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]); + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +#define treehash SPX_NAMESPACE(treehash) +void treehash(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx *ctx /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]); + + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/utilsx2.c b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/utilsx2.c new file mode 100644 index 0000000000..8736474e4f --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/utilsx2.c @@ -0,0 +1,130 @@ +#include + +#include "utilsx2.h" + +#include "address.h" +#include "params.h" +#include "thashx2.h" +#include "utils.h" + +/* + * Generate the entire Merkle tree, computing the authentication path for leaf_idx, + * and the resulting root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) + * + * This expects tree_addrx2 to be initialized to 2 parallel addr structures for + * the Merkle tree nodes + * + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + * + * This works by using the standard Merkle tree building algorithm, except + * that each 'node' tracked is actually 2 consecutive nodes in the real tree. + * When we combine two logical nodes AB and WX, we perform the H + * operation on adjacent real nodes, forming the parent logical node + * (AB)(WX) + * + * When we get to the top level of the real tree (where there is only + * one logical node), we continue this operation one more time; the right + * most real node will by the actual root (and the other node will be + * garbage). We follow the same thashx2 logic so that the 'extract + * authentication path components' part of the loop is still executed (and + * to simplify the code somewhat) + */ +void treehashx2(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, + uint32_t tree_height, + void (*gen_leafx2)( + unsigned char * /* Where to write the leaves */, + const spx_ctx *, + uint32_t idx, void *info), + uint32_t tree_addrx2[2 * 8], + void *info) { + /* This is where we keep the intermediate nodes */ + unsigned char stackx2[tree_height * 2 * SPX_N]; + uint32_t left_adj = 0, prev_left_adj = 0; /* When we're doing the top */ + /* level, the left-most part of the tree isn't at the beginning */ + /* of current[]. These give the offset of the actual start */ + + uint32_t idx; + uint32_t max_idx = (1 << (tree_height - 1)) - 1; + for (idx = 0;; idx++) { + unsigned char current[2 * SPX_N]; /* Current logical node */ + gen_leafx2( current, ctx, 2 * idx + idx_offset, + info ); + + /* Now combine the freshly generated right node with previously */ + /* generated left ones */ + uint32_t internal_idx_offset = idx_offset; + uint32_t internal_idx = idx; + uint32_t internal_leaf = leaf_idx; + uint32_t h; /* The height we are in the Merkle tree */ + for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { + + /* Special processing if we're at the top of the tree */ + if (h >= tree_height - 1) { + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[1 * SPX_N], SPX_N ); + return; + } + /* The tree indexing logic is a bit off in this case */ + /* Adjust it so that the left-most node of the part of */ + /* the tree that we're processing has index 0 */ + prev_left_adj = left_adj; + left_adj = 2 - (1 << (tree_height - h - 1)); + } + + /* Check if we hit the top of the tree */ + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[1 * SPX_N], SPX_N ); + return; + } + + /* + * Check if one of the nodes we have is a part of the + * authentication path; if it is, write it out + */ + if ((((internal_idx << 1) ^ internal_leaf) & ~0x1) == 0) { + memcpy( &auth_path[ h * SPX_N ], + ¤t[(((internal_leaf & 1) ^ 1) + prev_left_adj) * SPX_N], + SPX_N ); + } + + /* + * Check if we're at a left child; if so, stop going up the stack + * Exception: if we've reached the end of the tree, keep on going + * (so we combine the last 2 nodes into the one root node in two + * more iterations) + */ + if ((internal_idx & 1) == 0 && idx < max_idx) { + break; + } + + /* Ok, we're at a right node (or doing the top 3 levels) */ + /* Now combine the left and right logical nodes together */ + + /* Set the address of the node we're creating. */ + int j; + internal_idx_offset >>= 1; + for (j = 0; j < 2; j++) { + set_tree_height(tree_addrx2 + j * 8, h + 1); + set_tree_index(tree_addrx2 + j * 8, + (2 / 2) * (internal_idx & ~1) + j - left_adj + internal_idx_offset ); + } + unsigned char *left = &stackx2[h * 2 * SPX_N]; + thashx2( ¤t[0 * SPX_N], + ¤t[1 * SPX_N], + &left [0 * SPX_N], + ¤t[0 * SPX_N], + 2, ctx, tree_addrx2); + } + + /* We've hit a left child; save the current for when we get the */ + /* corresponding right right */ + memcpy( &stackx2[h * 2 * SPX_N], current, 2 * SPX_N); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/utilsx2.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/utilsx2.h new file mode 100644 index 0000000000..e09faddc43 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/utilsx2.h @@ -0,0 +1,30 @@ +#ifndef SPX_UTILSX2_H +#define SPX_UTILSX2_H + +#include + +#include "context.h" +#include "params.h" + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + * + * This implementation uses SIMD to compute internal nodes 2 at a time (in + * parallel) + */ +#define treehashx2 SPX_NAMESPACE(treehashx2) +void treehashx2(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leafx2)( + unsigned char * /* Where to write the leaves */, + const spx_ctx * /* ctx */, + uint32_t addr_idx, void *info), + uint32_t tree_addrx2[2 * 8], void *info); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/wots.c b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/wots.c new file mode 100644 index 0000000000..3babe45e95 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/wots.c @@ -0,0 +1,259 @@ +#include +#include + +#include "wots.h" +#include "wotsx2.h" + +#include "address.h" +#include "hash.h" +#include "hashx2.h" +#include "params.h" +#include "thashx2.h" +#include "utils.h" +#include "utilsx2.h" + +// TODO clarify address expectations, and make them more uniform. +// TODO i.e. do we expect types to be set already? +// TODO and do we expect modifications or copies? + +/** + * Computes up the chains + */ +static void gen_chains( + unsigned char *out, + const unsigned char *in, + unsigned int start[SPX_WOTS_LEN], + const unsigned int steps[SPX_WOTS_LEN], + const spx_ctx *ctx, + uint32_t addr[8]) { + uint32_t i, j, k, idx, watching; + int done; + unsigned char empty[SPX_N]; + unsigned char *bufs[4]; + uint32_t addrs[8 * 2]; + + int l; + uint16_t counts[SPX_WOTS_W] = { 0 }; + uint16_t idxs[SPX_WOTS_LEN]; + uint16_t total, newTotal; + + /* set addrs = {addr, addr} */ + for (j = 0; j < 2; j++) { + memcpy(addrs + j * 8, addr, sizeof(uint32_t) * 8); + } + + /* Initialize out with the value at position 'start'. */ + memcpy(out, in, SPX_WOTS_LEN * SPX_N); + + /* Sort the chains in reverse order by steps using counting sort. */ + for (i = 0; i < SPX_WOTS_LEN; i++) { + counts[steps[i]]++; + } + total = 0; + for (l = SPX_WOTS_W - 1; l >= 0; l--) { + newTotal = counts[l] + total; + counts[l] = total; + total = newTotal; + } + for (i = 0; i < SPX_WOTS_LEN; i++) { + idxs[counts[steps[i]]] = i; + counts[steps[i]]++; + } + + /* We got our work cut out for us: do it! */ + for (i = 0; i < SPX_WOTS_LEN; i += 2) { + for (j = 0; j < 2 && i + j < SPX_WOTS_LEN; j++) { + idx = idxs[i + j]; + set_chain_addr(addrs + j * 8, idx); + bufs[j] = out + SPX_N * idx; + } + + /* As the chains are sorted in reverse order, we know that the first + * chain is the longest and the last one is the shortest. We keep + * an eye on whether the last chain is done and then on the one before, + * et cetera. */ + watching = 1; + done = 0; + while (i + watching >= SPX_WOTS_LEN) { + bufs[watching] = &empty[0]; + watching--; + } + + for (k = 0;; k++) { + while (k == steps[idxs[i + watching]]) { + bufs[watching] = &empty[0]; + if (watching == 0) { + done = 1; + break; + } + watching--; + } + if (done) { + break; + } + for (j = 0; j < watching + 1; j++) { + set_hash_addr(addrs + j * 8, k + start[idxs[i + j]]); + } + + thashx2(bufs[0], bufs[1], + bufs[0], bufs[1], 1, ctx, addrs); + } + } +} + +/** + * base_w algorithm as described in draft. + * Interprets an array of bytes as integers in base w. + * This only works when log_w is a divisor of 8. + */ +static void base_w(unsigned int *output, const int out_len, + const unsigned char *input) { + int in = 0; + int out = 0; + unsigned char total = 0; + int bits = 0; + int consumed; + + for (consumed = 0; consumed < out_len; consumed++) { + if (bits == 0) { + total = input[in]; + in++; + bits += 8; + } + bits -= SPX_WOTS_LOGW; + output[out] = (total >> bits) & (SPX_WOTS_W - 1); + out++; + } +} + +/* Computes the WOTS+ checksum over a message (in base_w). */ +static void wots_checksum(unsigned int *csum_base_w, + const unsigned int *msg_base_w) { + unsigned int csum = 0; + unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; + unsigned int i; + + /* Compute checksum. */ + for (i = 0; i < SPX_WOTS_LEN1; i++) { + csum += SPX_WOTS_W - 1 - msg_base_w[i]; + } + + /* Convert checksum to base_w. */ + /* Make sure expected empty zero bits are the least significant bits. */ + csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); + ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); + base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); +} + +/* Takes a message and derives the matching chain lengths. */ +void chain_lengths(unsigned int *lengths, const unsigned char *msg) { + base_w(lengths, SPX_WOTS_LEN1, msg); + wots_checksum(lengths + SPX_WOTS_LEN1, lengths); +} + +/** + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. + * + * Writes the computed public key to 'pk'. + */ +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]) { + unsigned int steps[SPX_WOTS_LEN]; + unsigned int start[SPX_WOTS_LEN]; + uint32_t i; + + chain_lengths(start, msg); + + for (i = 0; i < SPX_WOTS_LEN; i++) { + steps[i] = SPX_WOTS_W - 1 - start[i]; + } + + gen_chains(pk, sig, start, steps, ctx, addr); +} + +/* + * This generates 2 sequential WOTS public keys + * It also generates the WOTS signature if leaf_info indicates + * that we're signing with one of these WOTS keys + */ +void wots_gen_leafx2(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info) { + struct leaf_info_x2 *info = v_info; + uint32_t *leaf_addr = info->leaf_addr; + uint32_t *pk_addr = info->pk_addr; + unsigned int i, j, k; + unsigned char pk_buffer[ 2 * SPX_WOTS_BYTES ]; + unsigned wots_offset = SPX_WOTS_BYTES; + unsigned char *buffer; + uint32_t wots_k_mask; + unsigned wots_sign_index; + + if (((leaf_idx ^ info->wots_sign_leaf) & ~1) == 0) { + /* We're traversing the leaf that's signing; generate the WOTS */ + /* signature */ + wots_k_mask = 0; + wots_sign_index = info->wots_sign_leaf & 1; /* Which of of the 2 */ + /* slots do the signatures come from */ + } else { + /* Nope, we're just generating pk's; turn off the signature logic */ + wots_k_mask = ~0; + wots_sign_index = 0; + } + + for (j = 0; j < 2; j++) { + set_keypair_addr( leaf_addr + j * 8, leaf_idx + j ); + set_keypair_addr( pk_addr + j * 8, leaf_idx + j ); + } + + for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { + uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k to */ + /* the step if we're generating a signature, ~0 if we're not */ + + /* Start with the secret seed */ + for (j = 0; j < 2; j++) { + set_chain_addr(leaf_addr + j * 8, i); + set_hash_addr(leaf_addr + j * 8, 0); + set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTSPRF); + } + prf_addrx2(buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + ctx, leaf_addr); + for (j = 0; j < 2; j++) { + set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTS); + } + + /* Iterate down the WOTS chain */ + for (k = 0;; k++) { + /* Check if one of the values we have needs to be saved as a */ + /* part of the WOTS signature */ + if (k == wots_k) { + memcpy( info->wots_sig + i * SPX_N, + buffer + wots_sign_index * wots_offset, SPX_N ); + } + + /* Check if we hit the top of the chain */ + if (k == SPX_WOTS_W - 1) { + break; + } + + /* Iterate one step on all 4 chains */ + for (j = 0; j < 2; j++) { + set_hash_addr(leaf_addr + j * 8, k); + } + thashx2(buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + 1, ctx, leaf_addr); + } + } + + /* Do the final thash to generate the public keys */ + thashx2(dest + 0 * SPX_N, + dest + 1 * SPX_N, + pk_buffer + 0 * wots_offset, + pk_buffer + 1 * wots_offset, + SPX_WOTS_LEN, ctx, pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/wots.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/wots.h new file mode 100644 index 0000000000..4e7692eeef --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/wots.h @@ -0,0 +1,25 @@ +#ifndef SPX_WOTS_H +#define SPX_WOTS_H + +#include + +#include "context.h" +#include "params.h" + +/** + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. + * + * Writes the computed public key to 'pk'. + */ +#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]); + +/* + * Compute the chain lengths needed for a given message hash + */ +#define chain_lengths SPX_NAMESPACE(chain_lengths) +void chain_lengths(unsigned int *lengths, const unsigned char *msg); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/wotsx2.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/wotsx2.h new file mode 100644 index 0000000000..b58bb61f84 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/wotsx2.h @@ -0,0 +1,40 @@ +#ifndef WOTSX2_H_ +#define WOTSX2_H_ + +#include "params.h" +#include + +/* + * This is here to provide an interface to the internal wots_gen_leafx2 + * routine. While this routine is not referenced in the package outside of + * wots.c, it is called from the stand-alone benchmark code to characterize + * the performance + */ +struct leaf_info_x2 { + unsigned char *wots_sig; + uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ + uint32_t *wots_steps; + uint32_t leaf_addr[2 * 8]; + uint32_t pk_addr[2 * 8]; +}; + +/* Macro to set the leaf_info to something 'benign', that is, it would */ +/* run with the same time as it does during the real signing process */ +/* Used only by the benchmark code */ +#define INITIALIZE_LEAF_INFO_X2(info, addr, step_buffer) { \ + (info).wots_sig = 0; \ + (info).wots_sign_leaf = ~0; \ + (info).wots_steps = step_buffer; \ + int i; \ + for (i=0; i<2; i++) { \ + memcpy( &(info).leaf_addr[8*i], addr, 32 ); \ + memcpy( &(info).pk_addr[8*i], addr, 32 ); \ + } \ + } + +#define wots_gen_leafx2 SPX_NAMESPACE(wots_gen_leafx2) +void wots_gen_leafx2(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info); + +#endif /* WOTSX2_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/LICENSE b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/LICENSE new file mode 100644 index 0000000000..670154e353 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/LICENSE @@ -0,0 +1,116 @@ +CC0 1.0 Universal + +Statement of Purpose + +The laws of most jurisdictions throughout the world automatically confer +exclusive Copyright and Related Rights (defined below) upon the creator and +subsequent owner(s) (each and all, an "owner") of an original work of +authorship and/or a database (each, a "Work"). + +Certain owners wish to permanently relinquish those rights to a Work for the +purpose of contributing to a commons of creative, cultural and scientific +works ("Commons") that the public can reliably and without fear of later +claims of infringement build upon, modify, incorporate in other works, reuse +and redistribute as freely as possible in any form whatsoever and for any +purposes, including without limitation commercial purposes. These owners may +contribute to the Commons to promote the ideal of a free culture and the +further production of creative, cultural and scientific works, or to gain +reputation or greater distribution for their Work in part through the use and +efforts of others. + +For these and/or other purposes and motivations, and without any expectation +of additional consideration or compensation, the person associating CC0 with a +Work (the "Affirmer"), to the extent that he or she is an owner of Copyright +and Related Rights in the Work, voluntarily elects to apply CC0 to the Work +and publicly distribute the Work under its terms, with knowledge of his or her +Copyright and Related Rights in the Work and the meaning and intended legal +effect of CC0 on those rights. + +1. Copyright and Related Rights. A Work made available under CC0 may be +protected by copyright and related or neighboring rights ("Copyright and +Related Rights"). Copyright and Related Rights include, but are not limited +to, the following: + + i. the right to reproduce, adapt, distribute, perform, display, communicate, + and translate a Work; + + ii. moral rights retained by the original author(s) and/or performer(s); + + iii. publicity and privacy rights pertaining to a person's image or likeness + depicted in a Work; + + iv. rights protecting against unfair competition in regards to a Work, + subject to the limitations in paragraph 4(a), below; + + v. rights protecting the extraction, dissemination, use and reuse of data in + a Work; + + vi. database rights (such as those arising under Directive 96/9/EC of the + European Parliament and of the Council of 11 March 1996 on the legal + protection of databases, and under any national implementation thereof, + including any amended or successor version of such directive); and + + vii. other similar, equivalent or corresponding rights throughout the world + based on applicable law or treaty, and any national implementations thereof. + +2. Waiver. To the greatest extent permitted by, but not in contravention of, +applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and +unconditionally waives, abandons, and surrenders all of Affirmer's Copyright +and Related Rights and associated claims and causes of action, whether now +known or unknown (including existing as well as future claims and causes of +action), in the Work (i) in all territories worldwide, (ii) for the maximum +duration provided by applicable law or treaty (including future time +extensions), (iii) in any current or future medium and for any number of +copies, and (iv) for any purpose whatsoever, including without limitation +commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes +the Waiver for the benefit of each member of the public at large and to the +detriment of Affirmer's heirs and successors, fully intending that such Waiver +shall not be subject to revocation, rescission, cancellation, termination, or +any other legal or equitable action to disrupt the quiet enjoyment of the Work +by the public as contemplated by Affirmer's express Statement of Purpose. + +3. Public License Fallback. Should any part of the Waiver for any reason be +judged legally invalid or ineffective under applicable law, then the Waiver +shall be preserved to the maximum extent permitted taking into account +Affirmer's express Statement of Purpose. In addition, to the extent the Waiver +is so judged Affirmer hereby grants to each affected person a royalty-free, +non transferable, non sublicensable, non exclusive, irrevocable and +unconditional license to exercise Affirmer's Copyright and Related Rights in +the Work (i) in all territories worldwide, (ii) for the maximum duration +provided by applicable law or treaty (including future time extensions), (iii) +in any current or future medium and for any number of copies, and (iv) for any +purpose whatsoever, including without limitation commercial, advertising or +promotional purposes (the "License"). The License shall be deemed effective as +of the date CC0 was applied by Affirmer to the Work. Should any part of the +License for any reason be judged legally invalid or ineffective under +applicable law, such partial invalidity or ineffectiveness shall not +invalidate the remainder of the License, and in such case Affirmer hereby +affirms that he or she will not (i) exercise any of his or her remaining +Copyright and Related Rights in the Work or (ii) assert any associated claims +and causes of action with respect to the Work, in either case contrary to +Affirmer's express Statement of Purpose. + +4. Limitations and Disclaimers. + + a. No trademark or patent rights held by Affirmer are waived, abandoned, + surrendered, licensed or otherwise affected by this document. + + b. Affirmer offers the Work as-is and makes no representations or warranties + of any kind concerning the Work, express, implied, statutory or otherwise, + including without limitation warranties of title, merchantability, fitness + for a particular purpose, non infringement, or the absence of latent or + other defects, accuracy, or the present or absence of errors, whether or not + discoverable, all to the greatest extent permissible under applicable law. + + c. Affirmer disclaims responsibility for clearing rights of other persons + that may apply to the Work or any use thereof, including without limitation + any person's Copyright and Related Rights in the Work. Further, Affirmer + disclaims responsibility for obtaining any necessary consents, permissions + or other rights required for any use of the Work. + + d. Affirmer understands and acknowledges that Creative Commons is not a + party to this document and has no duty or obligation with respect to this + CC0 or use of the Work. + +For more information, please see + diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/address.c b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/address.c new file mode 100644 index 0000000000..b956e9cb29 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/address.c @@ -0,0 +1,91 @@ +#include +#include + +#include "address.h" +#include "params.h" +#include "utils.h" + +/* + * Specify which level of Merkle tree (the "layer") we're working on + */ +void set_layer_addr(uint32_t addr[8], uint32_t layer) { + ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; +} + +/* + * Specify which Merkle tree within the level (the "tree address") we're working on + */ +void set_tree_addr(uint32_t addr[8], uint64_t tree) { + ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); +} + +/* + * Specify the reason we'll use this address structure for, that is, what + * hash will we compute with it. This is used so that unrelated types of + * hashes don't accidentally get the same address structure. The type will be + * one of the SPX_ADDR_TYPE constants + */ +void set_type(uint32_t addr[8], uint32_t type) { + ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; +} + +/* + * Copy the layer and tree fields of the address structure. This is used + * when we're doing multiple types of hashes within the same Merkle tree + */ +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); +} + +/* These functions are used for OTS addresses. */ + +/* + * Specify which Merkle leaf we're working on; that is, which OTS keypair + * we're talking about. + */ +void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { + ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; +} + +/* + * Copy the layer, tree and keypair fields of the address structure. This is + * used when we're doing multiple things within the same OTS keypair + */ +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); + ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; +} + +/* + * Specify which Merkle chain within the OTS we're working with + * (the chain address) + */ +void set_chain_addr(uint32_t addr[8], uint32_t chain) { + ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; +} + +/* + * Specify where in the Merkle chain we are +* (the hash address) + */ +void set_hash_addr(uint32_t addr[8], uint32_t hash) { + ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; +} + +/* These functions are used for all hash tree addresses (including FORS). */ + +/* + * Specify the height of the node in the Merkle/FORS tree we are in + * (the tree height) + */ +void set_tree_height(uint32_t addr[8], uint32_t tree_height) { + ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; +} + +/* + * Specify the distance from the left edge of the node in the Merkle/FORS tree + * (the tree index) + */ +void set_tree_index(uint32_t addr[8], uint32_t tree_index) { + u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/address.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/address.h new file mode 100644 index 0000000000..24a84eb40c --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/address.h @@ -0,0 +1,52 @@ +#ifndef SPX_ADDRESS_H +#define SPX_ADDRESS_H + +#include + +#include "params.h" + +/* The hash types that are passed to set_type */ +#define SPX_ADDR_TYPE_WOTS 0 +#define SPX_ADDR_TYPE_WOTSPK 1 +#define SPX_ADDR_TYPE_HASHTREE 2 +#define SPX_ADDR_TYPE_FORSTREE 3 +#define SPX_ADDR_TYPE_FORSPK 4 +#define SPX_ADDR_TYPE_WOTSPRF 5 +#define SPX_ADDR_TYPE_FORSPRF 6 + +#define set_layer_addr SPX_NAMESPACE(set_layer_addr) +void set_layer_addr(uint32_t addr[8], uint32_t layer); + +#define set_tree_addr SPX_NAMESPACE(set_tree_addr) +void set_tree_addr(uint32_t addr[8], uint64_t tree); + +#define set_type SPX_NAMESPACE(set_type) +void set_type(uint32_t addr[8], uint32_t type); + +/* Copies the layer and tree part of one address into the other */ +#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); + +/* These functions are used for WOTS and FORS addresses. */ + +#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) +void set_keypair_addr(uint32_t addr[8], uint32_t keypair); + +#define set_chain_addr SPX_NAMESPACE(set_chain_addr) +void set_chain_addr(uint32_t addr[8], uint32_t chain); + +#define set_hash_addr SPX_NAMESPACE(set_hash_addr) +void set_hash_addr(uint32_t addr[8], uint32_t hash); + +#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); + +/* These functions are used for all hash tree addresses (including FORS). */ + +#define set_tree_height SPX_NAMESPACE(set_tree_height) +void set_tree_height(uint32_t addr[8], uint32_t tree_height); + +#define set_tree_index SPX_NAMESPACE(set_tree_index) +void set_tree_index(uint32_t addr[8], uint32_t tree_index); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/api.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/api.h new file mode 100644 index 0000000000..1bf0fd167a --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/api.h @@ -0,0 +1,77 @@ +#ifndef PQCLEAN_SPHINCSSHAKE256FROBUST_AVX2_API_H +#define PQCLEAN_SPHINCSSHAKE256FROBUST_AVX2_API_H + +#include +#include + +#define PQCLEAN_SPHINCSSHAKE256FROBUST_AVX2_CRYPTO_ALGNAME "SPHINCS+-shake-256f-robust" + +#define PQCLEAN_SPHINCSSHAKE256FROBUST_AVX2_CRYPTO_SECRETKEYBYTES 128 +#define PQCLEAN_SPHINCSSHAKE256FROBUST_AVX2_CRYPTO_PUBLICKEYBYTES 64 +#define PQCLEAN_SPHINCSSHAKE256FROBUST_AVX2_CRYPTO_BYTES 49856 + +#define PQCLEAN_SPHINCSSHAKE256FROBUST_AVX2_CRYPTO_SEEDBYTES 96 + +/* + * Returns the length of a secret key, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE256FROBUST_AVX2_crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE256FROBUST_AVX2_crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE256FROBUST_AVX2_crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE256FROBUST_AVX2_crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +int PQCLEAN_SPHINCSSHAKE256FROBUST_AVX2_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +int PQCLEAN_SPHINCSSHAKE256FROBUST_AVX2_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +int PQCLEAN_SPHINCSSHAKE256FROBUST_AVX2_crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +int PQCLEAN_SPHINCSSHAKE256FROBUST_AVX2_crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, + const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +int PQCLEAN_SPHINCSSHAKE256FROBUST_AVX2_crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +int PQCLEAN_SPHINCSSHAKE256FROBUST_AVX2_crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/context.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/context.h new file mode 100644 index 0000000000..6e0a33f3b7 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/context.h @@ -0,0 +1,19 @@ +#ifndef SPX_CONTEXT_H +#define SPX_CONTEXT_H + +#include + +#include "params.h" + +typedef struct { + uint8_t pub_seed[SPX_N]; + uint8_t sk_seed[SPX_N]; +} spx_ctx; + +#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) +void initialize_hash_function(spx_ctx *ctx); + +#define free_hash_function SPX_NAMESPACE(free_hash_function) +void free_hash_function(spx_ctx *ctx); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/context_shake.c b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/context_shake.c new file mode 100644 index 0000000000..9614a103d3 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/context_shake.c @@ -0,0 +1,12 @@ +#include "context.h" + +/* For SHAKE256, there is no immediate reason to initialize at the start, + so this function is an empty operation. */ +void initialize_hash_function(spx_ctx *ctx) { + (void)ctx; /* Suppress an 'unused parameter' warning. */ +} + +// in case the hash function api is heap-based. +void free_hash_function(spx_ctx *ctx) { + (void)ctx; +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/fips202x4.c b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/fips202x4.c new file mode 100644 index 0000000000..1e06fef186 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/fips202x4.c @@ -0,0 +1,210 @@ +#include +#include +#include + +#include "fips202.h" +#include "fips202x4.h" + +#define NROUNDS 24 +#define ROL(a, offset) (((a) << (offset)) ^ ((a) >> (64-(offset)))) + +static uint64_t load64(const unsigned char *x) { + unsigned long long r = 0, i; + + for (i = 0; i < 8; ++i) { + r |= (unsigned long long)x[i] << 8 * i; + } + return r; +} + +static void store64(uint8_t *x, uint64_t u) { + unsigned int i; + + for (i = 0; i < 8; ++i) { + x[i] = (uint8_t)u; + u >>= 8; + } +} + +/* Use implementation from the Keccak Code Package */ +extern void KeccakP1600times4_PermuteAll_24rounds(__m256i *s); +#define KeccakF1600_StatePermute4x KeccakP1600times4_PermuteAll_24rounds + +static void keccak_absorb4x(__m256i *s, + unsigned int r, + const unsigned char *m0, + const unsigned char *m1, + const unsigned char *m2, + const unsigned char *m3, + unsigned long long int mlen, + unsigned char p) { + unsigned long long i; + unsigned char t0[200]; + unsigned char t1[200]; + unsigned char t2[200]; + unsigned char t3[200]; + + unsigned long long *ss = (unsigned long long *)s; + + + while (mlen >= r) { + for (i = 0; i < r / 8; ++i) { + ss[4 * i + 0] ^= load64(m0 + 8 * i); + ss[4 * i + 1] ^= load64(m1 + 8 * i); + ss[4 * i + 2] ^= load64(m2 + 8 * i); + ss[4 * i + 3] ^= load64(m3 + 8 * i); + } + + KeccakF1600_StatePermute4x(s); + mlen -= r; + m0 += r; + m1 += r; + m2 += r; + m3 += r; + } + + for (i = 0; i < r; ++i) { + t0[i] = 0; + t1[i] = 0; + t2[i] = 0; + t3[i] = 0; + } + for (i = 0; i < mlen; ++i) { + t0[i] = m0[i]; + t1[i] = m1[i]; + t2[i] = m2[i]; + t3[i] = m3[i]; + } + + t0[i] = p; + t1[i] = p; + t2[i] = p; + t3[i] = p; + + t0[r - 1] |= 128; + t1[r - 1] |= 128; + t2[r - 1] |= 128; + t3[r - 1] |= 128; + + for (i = 0; i < r / 8; ++i) { + ss[4 * i + 0] ^= load64(t0 + 8 * i); + ss[4 * i + 1] ^= load64(t1 + 8 * i); + ss[4 * i + 2] ^= load64(t2 + 8 * i); + ss[4 * i + 3] ^= load64(t3 + 8 * i); + } +} + + +static void keccak_squeezeblocks4x(unsigned char *h0, + unsigned char *h1, + unsigned char *h2, + unsigned char *h3, + unsigned long long int nblocks, + __m256i *s, + unsigned int r) { + unsigned int i; + + unsigned long long *ss = (unsigned long long *)s; + + while (nblocks > 0) { + KeccakF1600_StatePermute4x(s); + for (i = 0; i < (r >> 3); i++) { + store64(h0 + 8 * i, ss[4 * i + 0]); + store64(h1 + 8 * i, ss[4 * i + 1]); + store64(h2 + 8 * i, ss[4 * i + 2]); + store64(h3 + 8 * i, ss[4 * i + 3]); + } + h0 += r; + h1 += r; + h2 += r; + h3 += r; + nblocks--; + } +} + + + +void shake128x4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, unsigned long long outlen, + unsigned char *in0, + unsigned char *in1, + unsigned char *in2, + unsigned char *in3, unsigned long long inlen) { + __m256i s[25]; + unsigned char t0[SHAKE128_RATE]; + unsigned char t1[SHAKE128_RATE]; + unsigned char t2[SHAKE128_RATE]; + unsigned char t3[SHAKE128_RATE]; + unsigned int i; + + /* zero state */ + for (i = 0; i < 25; i++) { + s[i] = _mm256_xor_si256(s[i], s[i]); + } + + /* absorb 4 message of identical length in parallel */ + keccak_absorb4x(s, SHAKE128_RATE, in0, in1, in2, in3, inlen, 0x1F); + + /* Squeeze output */ + keccak_squeezeblocks4x(out0, out1, out2, out3, outlen / SHAKE128_RATE, s, SHAKE128_RATE); + + out0 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; + out1 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; + out2 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; + out3 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; + + if (outlen % SHAKE128_RATE) { + keccak_squeezeblocks4x(t0, t1, t2, t3, 1, s, SHAKE128_RATE); + for (i = 0; i < outlen % SHAKE128_RATE; i++) { + out0[i] = t0[i]; + out1[i] = t1[i]; + out2[i] = t2[i]; + out3[i] = t3[i]; + } + } +} + + +void shake256x4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, unsigned long long outlen, + unsigned char *in0, + unsigned char *in1, + unsigned char *in2, + unsigned char *in3, unsigned long long inlen) { + __m256i s[25]; + unsigned char t0[SHAKE256_RATE]; + unsigned char t1[SHAKE256_RATE]; + unsigned char t2[SHAKE256_RATE]; + unsigned char t3[SHAKE256_RATE]; + unsigned int i; + + /* zero state */ + for (i = 0; i < 25; i++) { + s[i] = _mm256_xor_si256(s[i], s[i]); + } + + /* absorb 4 message of identical length in parallel */ + keccak_absorb4x(s, SHAKE256_RATE, in0, in1, in2, in3, inlen, 0x1F); + + /* Squeeze output */ + keccak_squeezeblocks4x(out0, out1, out2, out3, outlen / SHAKE256_RATE, s, SHAKE256_RATE); + + out0 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; + out1 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; + out2 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; + out3 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; + + if (outlen % SHAKE256_RATE) { + keccak_squeezeblocks4x(t0, t1, t2, t3, 1, s, SHAKE256_RATE); + for (i = 0; i < outlen % SHAKE256_RATE; i++) { + out0[i] = t0[i]; + out1[i] = t1[i]; + out2[i] = t2[i]; + out3[i] = t3[i]; + } + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/fips202x4.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/fips202x4.h new file mode 100644 index 0000000000..2b93c9cd0d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/fips202x4.h @@ -0,0 +1,28 @@ +#ifndef SPX_FIPS202X4_H +#define SPX_FIPS202X4_H + +#include + +#include "params.h" + +#define shake128x4 SPX_NAMESPACE(shake128x4) +void shake128x4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, unsigned long long outlen, + unsigned char *in0, + unsigned char *in1, + unsigned char *in2, + unsigned char *in3, unsigned long long inlen); + +#define shake256x4 SPX_NAMESPACE(shake256x4) +void shake256x4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, unsigned long long outlen, + unsigned char *in0, + unsigned char *in1, + unsigned char *in2, + unsigned char *in3, unsigned long long inlen); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/fors.c b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/fors.c new file mode 100644 index 0000000000..f1b0639cfc --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/fors.c @@ -0,0 +1,202 @@ +#include +#include +#include + +#include "fors.h" + +#include "address.h" +#include "hash.h" +#include "hashx4.h" +#include "thash.h" +#include "thashx4.h" +#include "utils.h" +#include "utilsx4.h" + +static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + prf_addr(sk, ctx, fors_leaf_addr); +} + +static void fors_gen_skx4(unsigned char *sk0, + unsigned char *sk1, + unsigned char *sk2, + unsigned char *sk3, const spx_ctx *ctx, + uint32_t fors_leaf_addrx4[4 * 8]) { + prf_addrx4(sk0, sk1, sk2, sk3, + ctx, fors_leaf_addrx4); +} + +static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, + const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + thash(leaf, sk, 1, ctx, fors_leaf_addr); +} + +static void fors_sk_to_leafx4(unsigned char *leaf0, + unsigned char *leaf1, + unsigned char *leaf2, + unsigned char *leaf3, + const unsigned char *sk0, + const unsigned char *sk1, + const unsigned char *sk2, + const unsigned char *sk3, + const spx_ctx *ctx, + uint32_t fors_leaf_addrx4[4 * 8]) { + thashx4(leaf0, leaf1, leaf2, leaf3, + sk0, sk1, sk2, sk3, + 1, ctx, fors_leaf_addrx4); +} + +struct fors_gen_leaf_info { + uint32_t leaf_addrx[4 * 8]; +}; + +static void fors_gen_leafx4(unsigned char *leaf, + const spx_ctx *ctx, + uint32_t addr_idx, void *info) { + struct fors_gen_leaf_info *fors_info = info; + uint32_t *fors_leaf_addrx4 = fors_info->leaf_addrx; + unsigned int j; + + /* Only set the parts that the caller doesn't set */ + for (j = 0; j < 4; j++) { + set_tree_index(fors_leaf_addrx4 + j * 8, addr_idx + j); + set_type(fors_leaf_addrx4 + j * 8, SPX_ADDR_TYPE_FORSPRF); + } + + fors_gen_skx4(leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + leaf + 2 * SPX_N, + leaf + 3 * SPX_N, + ctx, fors_leaf_addrx4); + + for (j = 0; j < 4; j++) { + set_type(fors_leaf_addrx4 + j * 8, SPX_ADDR_TYPE_FORSTREE); + } + + fors_sk_to_leafx4(leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + leaf + 2 * SPX_N, + leaf + 3 * SPX_N, + leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + leaf + 2 * SPX_N, + leaf + 3 * SPX_N, + ctx, fors_leaf_addrx4); +} + +/** + * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + * Assumes indices has space for SPX_FORS_TREES integers. + */ +static void message_to_indices(uint32_t *indices, const unsigned char *m) { + unsigned int i, j; + unsigned int offset = 0; + + for (i = 0; i < SPX_FORS_TREES; i++) { + indices[i] = 0; + for (j = 0; j < SPX_FORS_HEIGHT; j++) { + indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); + offset++; + } + } +} + +/** + * Signs a message m, deriving the secret key from sk_seed and the FTS address. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + uint32_t fors_tree_addr[4 * 8] = {0}; + struct fors_gen_leaf_info fors_info = {0}; + uint32_t *fors_leaf_addr = fors_info.leaf_addrx; + uint32_t fors_pk_addr[8] = {0}; + uint32_t idx_offset; + unsigned int i; + + for (i = 0; i < 4; i++) { + copy_keypair_addr(fors_tree_addr + 8 * i, fors_addr); + set_type(fors_tree_addr + 8 * i, SPX_ADDR_TYPE_FORSTREE); + copy_keypair_addr(fors_leaf_addr + 8 * i, fors_addr); + } + copy_keypair_addr(fors_pk_addr, fors_addr); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); + + message_to_indices(indices, m); + + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); + + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + + /* Include the secret key part that produces the selected leaf node. */ + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); + fors_gen_sk(sig, ctx, fors_tree_addr); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + sig += SPX_N; + + /* Compute the authentication path for this leaf node. */ + treehashx4(roots + i * SPX_N, sig, ctx, + indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx4, + fors_tree_addr, &fors_info); + + sig += SPX_N * SPX_FORS_HEIGHT; + } + + /* Hash horizontally across all tree roots to derive the public key. */ + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); +} + +/** + * Derives the FORS public key from a signature. + * This can be used for verification by comparing to a known public key, or to + * subsequently verify a signature on the derived public key. The latter is the + * typical use-case when used as an FTS below an OTS in a hypertree. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + unsigned char leaf[SPX_N]; + uint32_t fors_tree_addr[8] = {0}; + uint32_t fors_pk_addr[8] = {0}; + uint32_t idx_offset; + unsigned int i; + + copy_keypair_addr(fors_tree_addr, fors_addr); + copy_keypair_addr(fors_pk_addr, fors_addr); + + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); + + message_to_indices(indices, m); + + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); + + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + + /* Derive the leaf from the included secret key part. */ + fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); + sig += SPX_N; + + /* Derive the corresponding root node of this tree. */ + compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, + sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); + sig += SPX_N * SPX_FORS_HEIGHT; + } + + /* Hash horizontally across all tree roots to derive the public key. */ + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/fors.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/fors.h new file mode 100644 index 0000000000..509140a178 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/fors.h @@ -0,0 +1,32 @@ +#ifndef SPX_FORS_H +#define SPX_FORS_H + +#include + +#include "context.h" +#include "params.h" + +/** + * Signs a message m, deriving the secret key from sk_seed and the FTS address. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +#define fors_sign SPX_NAMESPACE(fors_sign) +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); + +/** + * Derives the FORS public key from a signature. + * This can be used for verification by comparing to a known public key, or to + * subsequently verify a signature on the derived public key. The latter is the + * typical use-case when used as an FTS below an OTS in a hypertree. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/hash.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/hash.h new file mode 100644 index 0000000000..f7c87d4c3c --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/hash.h @@ -0,0 +1,28 @@ +#ifndef SPX_HASH_H +#define SPX_HASH_H + +#include +#include + +#include "context.h" +#include "params.h" + +#define prf_addr SPX_NAMESPACE(prf_addr) +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]); + +#define gen_message_random SPX_NAMESPACE(gen_message_random) +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); + +#define hash_message SPX_NAMESPACE(hash_message) +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); + + + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/hash_shake.c b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/hash_shake.c new file mode 100644 index 0000000000..ff5e7ec918 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/hash_shake.c @@ -0,0 +1,83 @@ +#include +#include + +#include "hash.h" + +#include "address.h" +#include "fips202.h" +#include "params.h" +#include "utils.h" + +/* + * Computes PRF(pk_seed, sk_seed, addr) + */ +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]) { + unsigned char buf[2 * SPX_N + SPX_ADDR_BYTES]; + + memcpy(buf, ctx->pub_seed, SPX_N); + memcpy(buf + SPX_N, addr, SPX_ADDR_BYTES); + memcpy(buf + SPX_N + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); + + shake256(out, SPX_N, buf, 2 * SPX_N + SPX_ADDR_BYTES); +} + +/** + * Computes the message-dependent randomness R, using a secret seed and an + * optional randomization value as well as the message. + */ +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { + (void)ctx; + shake256incctx s_inc; + + shake256_inc_init(&s_inc); + shake256_inc_absorb(&s_inc, sk_prf, SPX_N); + shake256_inc_absorb(&s_inc, optrand, SPX_N); + shake256_inc_absorb(&s_inc, m, mlen); + shake256_inc_finalize(&s_inc); + shake256_inc_squeeze(R, SPX_N, &s_inc); + shake256_inc_ctx_release(&s_inc); +} + +/** + * Computes the message hash using R, the public key, and the message. + * Outputs the message digest and the index of the leaf. The index is split in + * the tree index and the leaf index, for convenient copying to an address. + */ +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { + (void)ctx; +#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) +#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) +#define SPX_LEAF_BITS SPX_TREE_HEIGHT +#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) +#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) + + unsigned char buf[SPX_DGST_BYTES]; + unsigned char *bufp = buf; + shake256incctx s_inc; + + shake256_inc_init(&s_inc); + shake256_inc_absorb(&s_inc, R, SPX_N); + shake256_inc_absorb(&s_inc, pk, SPX_PK_BYTES); + shake256_inc_absorb(&s_inc, m, mlen); + shake256_inc_finalize(&s_inc); + shake256_inc_squeeze(buf, SPX_DGST_BYTES, &s_inc); + shake256_inc_ctx_release(&s_inc); + + memcpy(digest, bufp, SPX_FORS_MSG_BYTES); + bufp += SPX_FORS_MSG_BYTES; + + + *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); + *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); + bufp += SPX_TREE_BYTES; + + *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); + *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/hash_shakex4.c b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/hash_shakex4.c new file mode 100644 index 0000000000..bbd22eb117 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/hash_shakex4.c @@ -0,0 +1,64 @@ +#include +#include + +#include "hashx4.h" + +#include "address.h" +#include "fips202x4.h" +#include "params.h" + +extern void KeccakP1600times4_PermuteAll_24rounds(__m256i *s); + +/* + * 4-way parallel version of prf_addr; takes 4x as much input and output + */ +void prf_addrx4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const spx_ctx *ctx, + const uint32_t addrx4[4 * 8]) { + /* As we write and read only a few quadwords, it is more efficient to + * build and extract from the fourway SHAKE256 state by hand. */ + __m256i state[25]; + + for (int i = 0; i < SPX_N / 8; i++) { + state[i] = _mm256_set1_epi64x(((int64_t *)ctx->pub_seed)[i]); + } + for (int i = 0; i < 4; i++) { + state[SPX_N / 8 + i] = _mm256_set_epi32( + (int)addrx4[3 * 8 + 1 + 2 * i], + (int)addrx4[3 * 8 + 2 * i], + (int)addrx4[2 * 8 + 1 + 2 * i], + (int)addrx4[2 * 8 + 2 * i], + (int)addrx4[8 + 1 + 2 * i], + (int)addrx4[8 + 2 * i], + (int)addrx4[1 + 2 * i], + (int)addrx4[2 * i] + ); + } + for (int i = 0; i < SPX_N / 8; i++) { + state[SPX_N / 8 + i + 4] = _mm256_set1_epi64x(((int64_t *)ctx->sk_seed)[i]); + } + + /* SHAKE domain separator and padding. */ + state[SPX_N / 4 + 4] = _mm256_set1_epi64x(0x1f); + for (int i = SPX_N / 4 + 5; i < 16; i++) { + state[i] = _mm256_set1_epi64x(0); + } + // shift unsigned and then cast to avoid UB + state[16] = _mm256_set1_epi64x((long long)(0x80ULL << 56)); + + for (int i = 17; i < 25; i++) { + state[i] = _mm256_set1_epi64x(0); + } + + KeccakP1600times4_PermuteAll_24rounds(&state[0]); + + for (int i = 0; i < SPX_N / 8; i++) { + ((int64_t *)out0)[i] = _mm256_extract_epi64(state[i], 0); + ((int64_t *)out1)[i] = _mm256_extract_epi64(state[i], 1); + ((int64_t *)out2)[i] = _mm256_extract_epi64(state[i], 2); + ((int64_t *)out3)[i] = _mm256_extract_epi64(state[i], 3); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/hashx4.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/hashx4.h new file mode 100644 index 0000000000..3751a0ebd0 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/hashx4.h @@ -0,0 +1,17 @@ +#ifndef SPX_HASHX4_H +#define SPX_HASHX4_H + +#include + +#include "context.h" +#include "params.h" + +#define prf_addrx4 SPX_NAMESPACE(prf_addrx4) +void prf_addrx4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const spx_ctx *ctx, + const uint32_t addrx4[4 * 8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/merkle.c b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/merkle.c new file mode 100644 index 0000000000..f57811c1ac --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/merkle.c @@ -0,0 +1,64 @@ +#include +#include + +#include "merkle.h" + +#include "address.h" +#include "params.h" +#include "utils.h" +#include "utilsx4.h" +#include "wots.h" +#include "wotsx4.h" + +/* + * This generates a Merkle signature (WOTS signature followed by the Merkle + * authentication path). + */ +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf) { + unsigned char *auth_path = sig + SPX_WOTS_BYTES; + uint32_t tree_addrx4[4 * 8] = { 0 }; + int j; + struct leaf_info_x4 info = { 0 }; + unsigned steps[ SPX_WOTS_LEN ]; + + info.wots_sig = sig; + chain_lengths(steps, root); + info.wots_steps = steps; + + for (j = 0; j < 4; j++) { + set_type(&tree_addrx4[8 * j], SPX_ADDR_TYPE_HASHTREE); + set_type(&info.leaf_addr[8 * j], SPX_ADDR_TYPE_WOTS); + set_type(&info.pk_addr[8 * j], SPX_ADDR_TYPE_WOTSPK); + copy_subtree_addr(&tree_addrx4[8 * j], tree_addr); + copy_subtree_addr(&info.leaf_addr[8 * j], wots_addr); + copy_subtree_addr(&info.pk_addr[8 * j], wots_addr); + } + + info.wots_sign_leaf = idx_leaf; + + treehashx4(root, auth_path, ctx, + idx_leaf, 0, + SPX_TREE_HEIGHT, + wots_gen_leafx4, + tree_addrx4, &info); +} + +/* Compute root node of the top-most subtree. */ +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { + /* We do not need the auth path in key generation, but it simplifies the + code to have just one treehash routine that computes both root and path + in one function. */ + unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; + uint32_t top_tree_addr[8] = {0}; + uint32_t wots_addr[8] = {0}; + + set_layer_addr(top_tree_addr, SPX_D - 1); + set_layer_addr(wots_addr, SPX_D - 1); + + merkle_sign(auth_path, root, ctx, + wots_addr, top_tree_addr, + ~0U /* ~0 means "don't bother generating an auth path */ ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/merkle.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/merkle.h new file mode 100644 index 0000000000..769cf2e970 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/merkle.h @@ -0,0 +1,21 @@ +#ifndef MERKLE_H_ +#define MERKLE_H_ + +#include + +#include "context.h" +#include "params.h" + +/* Generate a Merkle signature (WOTS signature followed by the Merkle */ +/* authentication path) */ +#define merkle_sign SPX_NAMESPACE(merkle_sign) +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf); + +/* Compute the root node of the top-most subtree. */ +#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); + +#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/nistapi.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/nistapi.h new file mode 100644 index 0000000000..3cb71afad4 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/nistapi.h @@ -0,0 +1,87 @@ +#ifndef SPX_API_H +#define SPX_API_H + +#include +#include + +#include "params.h" + +#define CRYPTO_ALGNAME "SPHINCS+" + +#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES +#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES +#define CRYPTO_BYTES SPX_BYTES +#define CRYPTO_SEEDBYTES (3*SPX_N) + +/* + * Returns the length of a secret key, in bytes + */ +#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) +size_t crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) +size_t crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) +size_t crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) +size_t crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +#define crypto_sign SPX_NAMESPACE(crypto_sign) +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/params.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/params.h new file mode 100644 index 0000000000..897e913f3d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/params.h @@ -0,0 +1,56 @@ +#ifndef SPX_PARAMS_H +#define SPX_PARAMS_H + +#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSSHAKE256FROBUST_AVX2_##s + +/* Hash output length in bytes. */ +#define SPX_N 32 +/* Height of the hypertree. */ +#define SPX_FULL_HEIGHT 68 +/* Number of subtree layer. */ +#define SPX_D 17 +/* FORS tree dimensions. */ +#define SPX_FORS_HEIGHT 9 +#define SPX_FORS_TREES 35 +/* Winternitz parameter, */ +#define SPX_WOTS_W 16 + +/* The hash function is defined by linking a different hash.c file, as opposed + to setting a #define constant. */ + +/* For clarity */ +#define SPX_ADDR_BYTES 32 + +/* WOTS parameters. */ +#define SPX_WOTS_LOGW 4 + +#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) + +/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ +#define SPX_WOTS_LEN2 3 + +#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) +#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) +#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES + +/* Subtree size. */ +#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) + +//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT +// #error SPX_D should always divide SPX_FULL_HEIGHT +//#endif + +/* FORS parameters. */ +#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) +#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) +#define SPX_FORS_PK_BYTES SPX_N + +/* Resulting SPX sizes. */ +#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ + SPX_FULL_HEIGHT * SPX_N) +#define SPX_PK_BYTES (2 * SPX_N) +#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) + +#include "shake_offsets.h" + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/shake_offsets.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/shake_offsets.h new file mode 100644 index 0000000000..6b28d95d91 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/shake_offsets.h @@ -0,0 +1,21 @@ +#ifndef SHAKE_OFFSETS_H_ +#define SHAKE_OFFSETS_H_ + +/* + * Offsets of various fields in the address structure when we use SHAKE as + * the Sphincs+ hash function + */ + +#define SPX_OFFSET_LAYER 3 /* The byte used to specify the Merkle tree layer */ +#define SPX_OFFSET_TREE 8 /* The start of the 8 byte field used to specify the tree */ +#define SPX_OFFSET_TYPE 19 /* The byte used to specify the hash type (reason) */ +#define SPX_OFFSET_KP_ADDR2 22 /* The high byte used to specify the key pair (which one-time signature) */ +#define SPX_OFFSET_KP_ADDR1 23 /* The low byte used to specify the key pair */ +#define SPX_OFFSET_CHAIN_ADDR 27 /* The byte used to specify the chain address (which Winternitz chain) */ +#define SPX_OFFSET_HASH_ADDR 31 /* The byte used to specify the hash address (where in the Winternitz chain) */ +#define SPX_OFFSET_TREE_HGT 27 /* The byte used to specify the height of this node in the FORS or Merkle tree */ +#define SPX_OFFSET_TREE_INDEX 28 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ + +#define SPX_SHAKE 1 + +#endif /* SHAKE_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/sign.c b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/sign.c new file mode 100644 index 0000000000..9d0c7d1b22 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/sign.c @@ -0,0 +1,286 @@ +#include +#include +#include + +#include "address.h" +#include "context.h" +#include "fors.h" +#include "hash.h" +#include "merkle.h" +#include "nistapi.h" +#include "params.h" +#include "randombytes.h" +#include "thash.h" +#include "utils.h" +#include "wots.h" + +/* + * Returns the length of a secret key, in bytes + */ +size_t crypto_sign_secretkeybytes(void) { + return CRYPTO_SECRETKEYBYTES; +} + +/* + * Returns the length of a public key, in bytes + */ +size_t crypto_sign_publickeybytes(void) { + return CRYPTO_PUBLICKEYBYTES; +} + +/* + * Returns the length of a signature, in bytes + */ +size_t crypto_sign_bytes(void) { + return CRYPTO_BYTES; +} + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +size_t crypto_sign_seedbytes(void) { + return CRYPTO_SEEDBYTES; +} + +/* + * Generates an SPX key pair given a seed of length + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [PUB_SEED || root] + */ +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed) { + spx_ctx ctx; + + /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ + memcpy(sk, seed, CRYPTO_SEEDBYTES); + + memcpy(pk, sk + 2 * SPX_N, SPX_N); + + memcpy(ctx.pub_seed, pk, SPX_N); + memcpy(ctx.sk_seed, sk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + /* Compute root node of the top-most subtree. */ + merkle_gen_root(sk + 3 * SPX_N, &ctx); + + // cleanup + free_hash_function(&ctx); + + memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); + + return 0; +} + +/* + * Generates an SPX key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [PUB_SEED || root] + */ +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { + uint8_t seed[CRYPTO_SEEDBYTES]; + randombytes(seed, CRYPTO_SEEDBYTES); + crypto_sign_seed_keypair(pk, sk, seed); + + return 0; +} + +/** + * Returns an array containing a detached signature. + */ +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk) { + spx_ctx ctx; + + const uint8_t *sk_prf = sk + SPX_N; + const uint8_t *pk = sk + 2 * SPX_N; + + uint8_t optrand[SPX_N]; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t root[SPX_N]; + uint32_t i; + uint64_t tree; + uint32_t idx_leaf; + uint32_t wots_addr[8] = {0}; + uint32_t tree_addr[8] = {0}; + + memcpy(ctx.sk_seed, sk, SPX_N); + memcpy(ctx.pub_seed, pk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + + /* Optionally, signing can be made non-deterministic using optrand. + This can help counter side-channel attacks that would benefit from + getting a large number of traces when the signer uses the same nodes. */ + randombytes(optrand, SPX_N); + /* Compute the digest randomization value. */ + gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); + + /* Derive the message digest and leaf index from R, PK and M. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; + + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); + + /* Sign the message hash using FORS. */ + fors_sign(sig, root, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); + sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; + + /* Update the indices for the next layer. */ + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; + } + + free_hash_function(&ctx); + + *siglen = SPX_BYTES; + + return 0; +} + +/** + * Verifies a detached signature and message under a given public key. + */ +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk) { + spx_ctx ctx; + const uint8_t *pub_root = pk + SPX_N; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t wots_pk[SPX_WOTS_BYTES]; + uint8_t root[SPX_N]; + uint8_t leaf[SPX_N]; + unsigned int i; + uint64_t tree; + uint32_t idx_leaf; + uint32_t wots_addr[8] = {0}; + uint32_t tree_addr[8] = {0}; + uint32_t wots_pk_addr[8] = {0}; + + if (siglen != SPX_BYTES) { + return -1; + } + + memcpy(ctx.pub_seed, pk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); + + /* Derive the message digest and leaf index from R || PK || M. */ + /* The additional SPX_N is a result of the hash domain separator. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; + + /* Layer correctly defaults to 0, so no need to set_layer_addr */ + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); + + fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + /* For each subtree.. */ + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + copy_keypair_addr(wots_pk_addr, wots_addr); + + /* The WOTS public key is only correct if the signature was correct. */ + /* Initially, root is the FORS pk, but on subsequent iterations it is + the root of the subtree below the currently processed subtree. */ + wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); + sig += SPX_WOTS_BYTES; + + /* Compute the leaf node using the WOTS public key. */ + thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); + + /* Compute the root node of this subtree. */ + compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, + &ctx, tree_addr); + sig += SPX_TREE_HEIGHT * SPX_N; + + /* Update the indices for the next layer. */ + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; + } + + // cleanup + free_hash_function(&ctx); + + /* Check if the root node equals the root node in the public key. */ + if (memcmp(root, pub_root, SPX_N) != 0) { + return -1; + } + + return 0; +} + + +/** + * Returns an array containing the signature followed by the message. + */ +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk) { + size_t siglen; + + crypto_sign_signature(sm, &siglen, m, mlen, sk); + + memmove(sm + SPX_BYTES, m, mlen); + *smlen = siglen + mlen; + + return 0; +} + +/** + * Verifies a given signature-message pair under a given public key. + */ +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk) { + /* The API caller does not necessarily know what size a signature should be + but SPHINCS+ signatures are always exactly SPX_BYTES. */ + if (smlen < SPX_BYTES) { + memset(m, 0, smlen); + *mlen = 0; + return -1; + } + + *mlen = smlen - SPX_BYTES; + + if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { + memset(m, 0, smlen); + *mlen = 0; + return -1; + } + + /* If verification was successful, move the message to the right place. */ + memmove(m, sm + SPX_BYTES, *mlen); + + return 0; +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/thash.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/thash.h new file mode 100644 index 0000000000..8687ccfb4d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/thash.h @@ -0,0 +1,13 @@ +#ifndef SPX_THASH_H +#define SPX_THASH_H + +#include "context.h" +#include "params.h" + +#include + +#define thash SPX_NAMESPACE(thash) +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/thash_shake_robust.c b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/thash_shake_robust.c new file mode 100644 index 0000000000..696d53c5cc --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/thash_shake_robust.c @@ -0,0 +1,31 @@ +#include +#include + +#include "thash.h" + +#include "address.h" +#include "params.h" +#include "utils.h" + +#include "fips202.h" + +/** + * Takes an array of inblocks concatenated arrays of SPX_N bytes. + */ +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]) { + PQCLEAN_VLA(uint8_t, buf, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); + PQCLEAN_VLA(uint8_t, bitmask, inblocks * SPX_N); + unsigned int i; + + memcpy(buf, ctx->pub_seed, SPX_N); + memcpy(buf + SPX_N, addr, SPX_ADDR_BYTES); + + shake256(bitmask, inblocks * SPX_N, buf, SPX_N + SPX_ADDR_BYTES); + + for (i = 0; i < inblocks * SPX_N; i++) { + buf[SPX_N + SPX_ADDR_BYTES + i] = in[i] ^ bitmask[i]; + } + + shake256(out, SPX_N, buf, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/thash_shake_robustx4.c b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/thash_shake_robustx4.c new file mode 100644 index 0000000000..ce2946b745 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/thash_shake_robustx4.c @@ -0,0 +1,131 @@ +#include +#include + +#include "thashx4.h" + +#include "address.h" +#include "params.h" +#include "utils.h" + +#include "fips202x4.h" + +extern void KeccakP1600times4_PermuteAll_24rounds(__m256i *s); + +/** + * 4-way parallel version of thash; takes 4x as much input and output + */ +void thashx4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addrx4[4 * 8]) { + if (inblocks == 1 || inblocks == 2) { + /* As we write and read only a few quadwords, it is more efficient to + * build and extract from the fourway SHAKE256 state by hand. */ + __m256i state[25]; + for (int i = 0; i < SPX_N / 8; i++) { + state[i] = _mm256_set1_epi64x(((int64_t *)ctx->pub_seed)[i]); + } + for (int i = 0; i < 4; i++) { + state[SPX_N / 8 + i] = _mm256_set_epi32( + (int)addrx4[3 * 8 + 1 + 2 * i], + (int)addrx4[3 * 8 + 2 * i], + (int)addrx4[2 * 8 + 1 + 2 * i], + (int)addrx4[2 * 8 + 2 * i], + (int)addrx4[8 + 1 + 2 * i], + (int)addrx4[8 + 2 * i], + (int)addrx4[1 + 2 * i], + (int)addrx4[2 * i] + ); + } + + /* SHAKE domain separator and padding */ + state[SPX_N / 8 + 4] = _mm256_set1_epi64x(0x1f); + for (int i = SPX_N / 8 + 5; i < 16; i++) { + state[i] = _mm256_set1_epi64x(0); + } + state[16] = _mm256_set1_epi64x((long long)(0x80ULL << 56)); + + for (int i = 17; i < 25; i++) { + state[i] = _mm256_set1_epi64x(0); + } + + /* We will permutate state2 with f1600x4 to compute the bitmask, + * but first we'll copy it to state2 which will be used to compute + * the final output, as its input is alsmost identical. */ + __m256i state2[25]; + memcpy(state2, state, 800); + + KeccakP1600times4_PermuteAll_24rounds(&state[0]); + + /* By copying from state, state2 already contains the pub_seed + * and addres. We just need to copy in the input blocks xorred with + * the bitmask we just computed. */ + for (unsigned int i = 0; i < (SPX_N / 8) * inblocks; i++) { + state2[SPX_N / 8 + 4 + i] = _mm256_xor_si256( + state[i], + _mm256_set_epi64x( + ((int64_t *)in3)[i], + ((int64_t *)in2)[i], + ((int64_t *)in1)[i], + ((int64_t *)in0)[i] + ) + ); + } + + /* Domain separator and start of padding. Note that the quadwords + * around are already zeroed for state from which we copied. + * We do a XOR instead of a set as this might be the 16th quadword + * when N=32 and inblocks=2, which already contains the end + * of the padding. */ + state2[(SPX_N / 8) * (1 + inblocks) + 4] = _mm256_xor_si256( + state2[(SPX_N / 8) * (1 + inblocks) + 4], + _mm256_set1_epi64x(0x1f) + ); + + KeccakP1600times4_PermuteAll_24rounds(&state2[0]); + + for (int i = 0; i < SPX_N / 8; i++) { + ((int64_t *)out0)[i] = _mm256_extract_epi64(state2[i], 0); + ((int64_t *)out1)[i] = _mm256_extract_epi64(state2[i], 1); + ((int64_t *)out2)[i] = _mm256_extract_epi64(state2[i], 2); + ((int64_t *)out3)[i] = _mm256_extract_epi64(state2[i], 3); + } + } else { + PQCLEAN_VLA(unsigned char, buf0, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, buf1, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, buf2, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, buf3, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, bitmask0, inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, bitmask1, inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, bitmask2, inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, bitmask3, inblocks * SPX_N); + unsigned int i; + + memcpy(buf0, ctx->pub_seed, SPX_N); + memcpy(buf1, ctx->pub_seed, SPX_N); + memcpy(buf2, ctx->pub_seed, SPX_N); + memcpy(buf3, ctx->pub_seed, SPX_N); + memcpy(buf0 + SPX_N, addrx4 + 0 * 8, SPX_ADDR_BYTES); + memcpy(buf1 + SPX_N, addrx4 + 1 * 8, SPX_ADDR_BYTES); + memcpy(buf2 + SPX_N, addrx4 + 2 * 8, SPX_ADDR_BYTES); + memcpy(buf3 + SPX_N, addrx4 + 3 * 8, SPX_ADDR_BYTES); + + shake256x4(bitmask0, bitmask1, bitmask2, bitmask3, inblocks * SPX_N, + buf0, buf1, buf2, buf3, SPX_N + SPX_ADDR_BYTES); + + for (i = 0; i < inblocks * SPX_N; i++) { + buf0[SPX_N + SPX_ADDR_BYTES + i] = in0[i] ^ bitmask0[i]; + buf1[SPX_N + SPX_ADDR_BYTES + i] = in1[i] ^ bitmask1[i]; + buf2[SPX_N + SPX_ADDR_BYTES + i] = in2[i] ^ bitmask2[i]; + buf3[SPX_N + SPX_ADDR_BYTES + i] = in3[i] ^ bitmask3[i]; + } + + shake256x4(out0, out1, out2, out3, SPX_N, + buf0, buf1, buf2, buf3, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/thashx4.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/thashx4.h new file mode 100644 index 0000000000..64798a3727 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/thashx4.h @@ -0,0 +1,20 @@ +#ifndef SPX_THASHX4_H +#define SPX_THASHX4_H + +#include + +#include "context.h" +#include "params.h" + +#define thashx4 SPX_NAMESPACE(thashx4) +void thashx4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addrx4[4 * 8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/utils.c b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/utils.c new file mode 100644 index 0000000000..177b541fb9 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/utils.c @@ -0,0 +1,148 @@ +#include + +#include "utils.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "thash.h" + +/** + * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. + */ +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in) { + int i; + + /* Iterate over out in decreasing order, for big-endianness. */ + for (i = (signed int)outlen - 1; i >= 0; i--) { + out[i] = in & 0xff; + in = in >> 8; + } +} + +void u32_to_bytes(unsigned char *out, uint32_t in) { + out[0] = (unsigned char)(in >> 24); + out[1] = (unsigned char)(in >> 16); + out[2] = (unsigned char)(in >> 8); + out[3] = (unsigned char)in; +} + +/** + * Converts the inlen bytes in 'in' from big-endian byte order to an integer. + */ +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { + unsigned long long retval = 0; + unsigned int i; + + for (i = 0; i < inlen; i++) { + retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); + } + return retval; +} + +/** + * Computes a root node given a leaf and an auth path. + * Expects address to be complete other than the tree_height and tree_index. + */ +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]) { + uint32_t i; + unsigned char buffer[2 * SPX_N]; + + /* If leaf_idx is odd (last bit = 1), current path element is a right child + and auth_path has to go left. Otherwise it is the other way around. */ + if (leaf_idx & 1) { + memcpy(buffer + SPX_N, leaf, SPX_N); + memcpy(buffer, auth_path, SPX_N); + } else { + memcpy(buffer, leaf, SPX_N); + memcpy(buffer + SPX_N, auth_path, SPX_N); + } + auth_path += SPX_N; + + for (i = 0; i < tree_height - 1; i++) { + leaf_idx >>= 1; + idx_offset >>= 1; + /* Set the address of the node we're creating. */ + set_tree_height(addr, i + 1); + set_tree_index(addr, leaf_idx + idx_offset); + + /* Pick the right or left neighbor, depending on parity of the node. */ + if (leaf_idx & 1) { + thash(buffer + SPX_N, buffer, 2, ctx, addr); + memcpy(buffer, auth_path, SPX_N); + } else { + thash(buffer, buffer, 2, ctx, addr); + memcpy(buffer + SPX_N, auth_path, SPX_N); + } + auth_path += SPX_N; + } + + /* The last iteration is exceptional; we do not copy an auth_path node. */ + leaf_idx >>= 1; + idx_offset >>= 1; + set_tree_height(addr, tree_height); + set_tree_index(addr, leaf_idx + idx_offset); + thash(root, buffer, 2, ctx, addr); +} + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx * /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]) { + PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); + PQCLEAN_VLA(unsigned int, heights, tree_height + 1); + unsigned int offset = 0; + uint32_t idx; + uint32_t tree_idx; + + for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { + /* Add the next leaf node to the stack. */ + gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); + offset++; + heights[offset - 1] = 0; + + /* If this is a node we need for the auth path.. */ + if ((leaf_idx ^ 0x1) == idx) { + memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); + } + + /* While the top-most nodes are of equal height.. */ + while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { + /* Compute index of the new node, in the next layer. */ + tree_idx = (idx >> (heights[offset - 1] + 1)); + + /* Set the address of the node we're creating. */ + set_tree_height(tree_addr, heights[offset - 1] + 1); + set_tree_index(tree_addr, + tree_idx + (idx_offset >> (heights[offset - 1] + 1))); + /* Hash the top-most nodes from the stack together. */ + thash(stack + (offset - 2)*SPX_N, + stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); + offset--; + /* Note that the top-most node is now one layer higher. */ + heights[offset - 1]++; + + /* If this is a node we need for the auth path.. */ + if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { + memcpy(auth_path + heights[offset - 1]*SPX_N, + stack + (offset - 1)*SPX_N, SPX_N); + } + } + } + memcpy(root, stack, SPX_N); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/utils.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/utils.h new file mode 100644 index 0000000000..64f5d5a53a --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/utils.h @@ -0,0 +1,58 @@ +#ifndef SPX_UTILS_H +#define SPX_UTILS_H + +#include + +#include "compat.h" +#include "context.h" +#include "params.h" + + +/* To support MSVC use alloca() instead of VLAs. See #20. */ + + +/** + * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. + */ +#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in); +#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) +void u32_to_bytes(unsigned char *out, uint32_t in); + +/** + * Converts the inlen bytes in 'in' from big-endian byte order to an integer. + */ +#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); + +/** + * Computes a root node given a leaf and an auth path. + * Expects address to be complete other than the tree_height and tree_index. + */ +#define compute_root SPX_NAMESPACE(compute_root) +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]); + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +#define treehash SPX_NAMESPACE(treehash) +void treehash(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx *ctx /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]); + + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/utilsx4.c b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/utilsx4.c new file mode 100644 index 0000000000..1638677194 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/utilsx4.c @@ -0,0 +1,138 @@ +#include + +#include "utilsx4.h" + +#include "address.h" +#include "params.h" +#include "thashx4.h" +#include "utils.h" + +/* + * Generate the entire Merkle tree, computing the authentication path for leaf_idx, + * and the resulting root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) + * + * This expects tree_addrx4 to be initialized to 4 parallel addr structures for + * the Merkle tree nodes + * + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + * + * This works by using the standard Merkle tree building algorithm, except + * that each 'node' tracked is actually 4 consecutive nodes in the real tree. + * When we combine two logical nodes ABCD and WXYZ, we perform the H + * operation on adjacent real nodes, forming the parent logical node + * (AB)(CD)(WX)(YZ) + * + * When we get to the top two levels of the real tree (where there is only + * one logical node), we continue this operation two more times; the right + * most real node will by the actual root (and the other 3 nodes will be + * garbage). We follow the same thashx4 logic so that the 'extract + * authentication path components' part of the loop is still executed (and + * to simplify the code somewhat) + * + * This currently assumes tree_height >= 2; I suspect that doing an adjusting + * idx, addr_idx on the gen_leafx4 call if tree_height < 2 would fix it; since + * we don't actually use such short trees, I haven't bothered + */ +void treehashx4(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, + uint32_t tree_height, + void (*gen_leafx4)( + unsigned char * /* Where to write the leaves */, + const spx_ctx *, + uint32_t idx, void *info), + uint32_t tree_addrx4[4 * 8], + void *info) { + /* This is where we keep the intermediate nodes */ + PQCLEAN_VLA(unsigned char, stackx4, tree_height * 4 * SPX_N); + uint32_t left_adj = 0, prev_left_adj = 0; /* When we're doing the top 3 */ + /* levels, the left-most part of the tree isn't at the beginning */ + /* of current[]. These give the offset of the actual start */ + + uint32_t idx; + uint32_t max_idx = (1U << (tree_height - 2)) - 1; + for (idx = 0;; idx++) { + unsigned char current[4 * SPX_N]; /* Current logical node */ + gen_leafx4( current, ctx, 4 * idx + idx_offset, + info ); + + /* Now combine the freshly generated right node with previously */ + /* generated left ones */ + uint32_t internal_idx_offset = idx_offset; + uint32_t internal_idx = idx; + uint32_t internal_leaf = leaf_idx; + uint32_t h; /* The height we are in the Merkle tree */ + for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { + + /* Special processing if we're at the top of the tree */ + if (h >= tree_height - 2) { + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[3 * SPX_N], SPX_N ); + return; + } + /* The tree indexing logic is a bit off in this case */ + /* Adjust it so that the left-most node of the part of */ + /* the tree that we're processing has index 0 */ + prev_left_adj = left_adj; + left_adj = 4U - (1 << (tree_height - h - 1)); + } + + /* Check if we hit the top of the tree */ + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[3 * SPX_N], SPX_N ); + return; + } + + /* + * Check if one of the nodes we have is a part of the + * authentication path; if it is, write it out + */ + if ((((internal_idx << 2) ^ internal_leaf) & ~0x3U) == 0) { + memcpy( &auth_path[ h * SPX_N ], + ¤t[(((internal_leaf & 3) ^ 1) + prev_left_adj) * SPX_N], + SPX_N ); + } + + /* + * Check if we're at a left child; if so, stop going up the stack + * Exception: if we've reached the end of the tree, keep on going + * (so we combine the last 4 nodes into the one root node in two + * more iterations) + */ + if ((internal_idx & 1) == 0 && idx < max_idx) { + break; + } + + /* Ok, we're at a right node (or doing the top 3 levels) */ + /* Now combine the left and right logical nodes together */ + + /* Set the address of the node we're creating. */ + unsigned int j; + internal_idx_offset >>= 1; + for (j = 0; j < 4; j++) { + set_tree_height(tree_addrx4 + j * 8, h + 1); + set_tree_index(tree_addrx4 + j * 8, + (4 / 2) * (internal_idx & ~1U) + j - left_adj + internal_idx_offset ); + } + unsigned char *left = &stackx4[h * 4 * SPX_N]; + thashx4( ¤t[0 * SPX_N], + ¤t[1 * SPX_N], + ¤t[2 * SPX_N], + ¤t[3 * SPX_N], + &left [0 * SPX_N], + &left [2 * SPX_N], + ¤t[0 * SPX_N], + ¤t[2 * SPX_N], + 2, ctx, tree_addrx4); + } + + /* We've hit a left child; save the current for when we get the */ + /* corresponding right right */ + memcpy( &stackx4[h * 4 * SPX_N], current, 4 * SPX_N); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/utilsx4.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/utilsx4.h new file mode 100644 index 0000000000..facb874b18 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/utilsx4.h @@ -0,0 +1,30 @@ +#ifndef SPX_UTILSX4_H +#define SPX_UTILSX4_H + +#include + +#include "context.h" +#include "params.h" + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + * + * This implementation uses AVX to compute internal nodes 4 at a time (in + * parallel) + */ +#define treehashx4 SPX_NAMESPACE(treehashx4) +void treehashx4(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leafx4)( + unsigned char * /* Where to write the leaves */, + const spx_ctx * /* ctx */, + uint32_t addr_idx, void *info), + uint32_t tree_addrx4[4 * 8], void *info); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/wots.c b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/wots.c new file mode 100644 index 0000000000..4d5041ce05 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/wots.c @@ -0,0 +1,269 @@ +#include +#include + +#include "wots.h" + +#include "address.h" +#include "hash.h" +#include "hashx4.h" +#include "params.h" +#include "thash.h" +#include "thashx4.h" +#include "utils.h" +#include "utilsx4.h" +#include "wotsx4.h" + +// TODO clarify address expectations, and make them more uniform. +// TODO i.e. do we expect types to be set already? +// TODO and do we expect modifications or copies? + +/** + * Computes up the chains + */ +static void gen_chains( + unsigned char *out, + const unsigned char *in, + unsigned int start[SPX_WOTS_LEN], + const unsigned int steps[SPX_WOTS_LEN], + const spx_ctx *ctx, + uint32_t addr[8]) { + uint32_t i, j, k, idx, watching; + int done; + unsigned char empty[SPX_N]; + unsigned char *bufs[4]; + uint32_t addrs[8 * 4]; + + int l; + uint16_t counts[SPX_WOTS_W] = { 0 }; + uint16_t idxs[SPX_WOTS_LEN]; + uint16_t total, newTotal; + + /* set addrs = {addr, addr, addr, addr} */ + for (j = 0; j < 4; j++) { + memcpy(addrs + j * 8, addr, sizeof(uint32_t) * 8); + } + + /* Initialize out with the value at position 'start'. */ + memcpy(out, in, SPX_WOTS_LEN * SPX_N); + + /* Sort the chains in reverse order by steps using counting sort. */ + for (i = 0; i < SPX_WOTS_LEN; i++) { + counts[steps[i]]++; + } + total = 0; + for (l = SPX_WOTS_W - 1; l >= 0; l--) { + newTotal = counts[l] + total; + counts[l] = total; + total = newTotal; + } + for (i = 0; i < SPX_WOTS_LEN; i++) { + idxs[counts[steps[i]]] = (uint16_t)i; + counts[steps[i]]++; + } + + /* We got our work cut out for us: do it! */ + for (i = 0; i < SPX_WOTS_LEN; i += 4) { + for (j = 0; j < 4 && i + j < SPX_WOTS_LEN; j++) { + idx = idxs[i + j]; + set_chain_addr(addrs + j * 8, idx); + bufs[j] = out + SPX_N * idx; + } + + /* As the chains are sorted in reverse order, we know that the first + * chain is the longest and the last one is the shortest. We keep + * an eye on whether the last chain is done and then on the one before, + * et cetera. */ + watching = 3; + done = 0; + while (i + watching >= SPX_WOTS_LEN) { + bufs[watching] = &empty[0]; + watching--; + } + + for (k = 0;; k++) { + while (k == steps[idxs[i + watching]]) { + bufs[watching] = &empty[0]; + if (watching == 0) { + done = 1; + break; + } + watching--; + } + if (done) { + break; + } + for (j = 0; j < watching + 1; j++) { + set_hash_addr(addrs + j * 8, k + start[idxs[i + j]]); + } + + thashx4(bufs[0], bufs[1], bufs[2], bufs[3], + bufs[0], bufs[1], bufs[2], bufs[3], 1, ctx, addrs); + } + } +} + +/** + * base_w algorithm as described in draft. + * Interprets an array of bytes as integers in base w. + * This only works when log_w is a divisor of 8. + */ +static void base_w(unsigned int *output, const int out_len, + const unsigned char *input) { + int in = 0; + int out = 0; + unsigned char total = 0; + int bits = 0; + int consumed; + + for (consumed = 0; consumed < out_len; consumed++) { + if (bits == 0) { + total = input[in]; + in++; + bits += 8; + } + bits -= SPX_WOTS_LOGW; + output[out] = (total >> bits) & (SPX_WOTS_W - 1); + out++; + } +} + +/* Computes the WOTS+ checksum over a message (in base_w). */ +static void wots_checksum(unsigned int *csum_base_w, + const unsigned int *msg_base_w) { + unsigned int csum = 0; + unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; + unsigned int i; + + /* Compute checksum. */ + for (i = 0; i < SPX_WOTS_LEN1; i++) { + csum += SPX_WOTS_W - 1 - msg_base_w[i]; + } + + /* Convert checksum to base_w. */ + /* Make sure expected empty zero bits are the least significant bits. */ + csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); + ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); + base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); +} + +/* Takes a message and derives the matching chain lengths. */ +void chain_lengths(unsigned int *lengths, const unsigned char *msg) { + base_w(lengths, SPX_WOTS_LEN1, msg); + wots_checksum(lengths + SPX_WOTS_LEN1, lengths); +} + +/** + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. + * + * Writes the computed public key to 'pk'. + */ +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]) { + unsigned int steps[SPX_WOTS_LEN]; + unsigned int start[SPX_WOTS_LEN]; + uint32_t i; + + chain_lengths(start, msg); + + for (i = 0; i < SPX_WOTS_LEN; i++) { + steps[i] = SPX_WOTS_W - 1 - start[i]; + } + + gen_chains(pk, sig, start, steps, ctx, addr); +} + +/* + * This generates 4 sequential WOTS public keys + * It also generates the WOTS signature if leaf_info indicates + * that we're signing with one of these WOTS keys + */ +void wots_gen_leafx4(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info) { + struct leaf_info_x4 *info = v_info; + uint32_t *leaf_addr = info->leaf_addr; + uint32_t *pk_addr = info->pk_addr; + unsigned int i, j, k; + unsigned char pk_buffer[ 4 * SPX_WOTS_BYTES ]; + unsigned wots_offset = SPX_WOTS_BYTES; + unsigned char *buffer; + uint32_t wots_k_mask; + unsigned wots_sign_index; + + if (((leaf_idx ^ info->wots_sign_leaf) & ~3U) == 0) { + /* We're traversing the leaf that's signing; generate the WOTS */ + /* signature */ + wots_k_mask = 0; + wots_sign_index = info->wots_sign_leaf & 3; /* Which of of the 4 */ + /* 4 slots do the signatures come from */ + } else { + /* Nope, we're just generating pk's; turn off the signature logic */ + wots_k_mask = (uint32_t)~0; + wots_sign_index = 0; + } + + for (j = 0; j < 4; j++) { + set_keypair_addr( leaf_addr + j * 8, leaf_idx + j ); + set_keypair_addr( pk_addr + j * 8, leaf_idx + j ); + } + + for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { + uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k to */ + /* the step if we're generating a signature, ~0 if we're not */ + + /* Start with the secret seed */ + for (j = 0; j < 4; j++) { + set_chain_addr(leaf_addr + j * 8, i); + set_hash_addr(leaf_addr + j * 8, 0); + set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTSPRF); + } + prf_addrx4(buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + buffer + 2 * wots_offset, + buffer + 3 * wots_offset, + ctx, leaf_addr); + + for (j = 0; j < 4; j++) { + set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTS); + } + + /* Iterate down the WOTS chain */ + for (k = 0;; k++) { + /* Check if one of the values we have needs to be saved as a */ + /* part of the WOTS signature */ + if (k == wots_k) { + memcpy( info->wots_sig + i * SPX_N, + buffer + wots_sign_index * wots_offset, SPX_N ); + } + + /* Check if we hit the top of the chain */ + if (k == SPX_WOTS_W - 1) { + break; + } + + /* Iterate one step on all 4 chains */ + for (j = 0; j < 4; j++) { + set_hash_addr(leaf_addr + j * 8, k); + } + thashx4(buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + buffer + 2 * wots_offset, + buffer + 3 * wots_offset, + buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + buffer + 2 * wots_offset, + buffer + 3 * wots_offset, 1, ctx, leaf_addr); + } + } + + /* Do the final thash to generate the public keys */ + thashx4(dest + 0 * SPX_N, + dest + 1 * SPX_N, + dest + 2 * SPX_N, + dest + 3 * SPX_N, + pk_buffer + 0 * wots_offset, + pk_buffer + 1 * wots_offset, + pk_buffer + 2 * wots_offset, + pk_buffer + 3 * wots_offset, SPX_WOTS_LEN, ctx, pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/wots.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/wots.h new file mode 100644 index 0000000000..4e7692eeef --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/wots.h @@ -0,0 +1,25 @@ +#ifndef SPX_WOTS_H +#define SPX_WOTS_H + +#include + +#include "context.h" +#include "params.h" + +/** + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. + * + * Writes the computed public key to 'pk'. + */ +#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]); + +/* + * Compute the chain lengths needed for a given message hash + */ +#define chain_lengths SPX_NAMESPACE(chain_lengths) +void chain_lengths(unsigned int *lengths, const unsigned char *msg); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/wotsx4.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/wotsx4.h new file mode 100644 index 0000000000..cd634f1743 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/wotsx4.h @@ -0,0 +1,41 @@ +#ifndef WOTSX4_H_ +#define WOTSX4_H_ + +#include + +#include "params.h" + +/* + * This is here to provide an interface to the internal wots_gen_leafx4 + * routine. While this routine is not referenced in the package outside of + * wots.c, it is called from the stand-alone benchmark code to characterize + * the performance + */ +struct leaf_info_x4 { + unsigned char *wots_sig; + uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ + uint32_t *wots_steps; + uint32_t leaf_addr[4 * 8]; + uint32_t pk_addr[4 * 8]; +}; + +/* Macro to set the leaf_info to something 'benign', that is, it would */ +/* run with the same time as it does during the real signing process */ +/* Used only by the benchmark code */ +#define INITIALIZE_LEAF_INFO_X4(info, addr, step_buffer) { \ + (info).wots_sig = 0; \ + (info).wots_sign_leaf = ~0; \ + (info).wots_steps = step_buffer; \ + int i; \ + for (i=0; i<4; i++) { \ + memcpy( &(info).leaf_addr[8*i], addr, 32 ); \ + memcpy( &(info).pk_addr[8*i], addr, 32 ); \ + } \ + } + +#define wots_gen_leafx4 SPX_NAMESPACE(wots_gen_leafx4) +void wots_gen_leafx4(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info); + +#endif /* WOTSX4_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/LICENSE b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/LICENSE new file mode 100644 index 0000000000..670154e353 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/LICENSE @@ -0,0 +1,116 @@ +CC0 1.0 Universal + +Statement of Purpose + +The laws of most jurisdictions throughout the world automatically confer +exclusive Copyright and Related Rights (defined below) upon the creator and +subsequent owner(s) (each and all, an "owner") of an original work of +authorship and/or a database (each, a "Work"). + +Certain owners wish to permanently relinquish those rights to a Work for the +purpose of contributing to a commons of creative, cultural and scientific +works ("Commons") that the public can reliably and without fear of later +claims of infringement build upon, modify, incorporate in other works, reuse +and redistribute as freely as possible in any form whatsoever and for any +purposes, including without limitation commercial purposes. These owners may +contribute to the Commons to promote the ideal of a free culture and the +further production of creative, cultural and scientific works, or to gain +reputation or greater distribution for their Work in part through the use and +efforts of others. + +For these and/or other purposes and motivations, and without any expectation +of additional consideration or compensation, the person associating CC0 with a +Work (the "Affirmer"), to the extent that he or she is an owner of Copyright +and Related Rights in the Work, voluntarily elects to apply CC0 to the Work +and publicly distribute the Work under its terms, with knowledge of his or her +Copyright and Related Rights in the Work and the meaning and intended legal +effect of CC0 on those rights. + +1. Copyright and Related Rights. A Work made available under CC0 may be +protected by copyright and related or neighboring rights ("Copyright and +Related Rights"). Copyright and Related Rights include, but are not limited +to, the following: + + i. the right to reproduce, adapt, distribute, perform, display, communicate, + and translate a Work; + + ii. moral rights retained by the original author(s) and/or performer(s); + + iii. publicity and privacy rights pertaining to a person's image or likeness + depicted in a Work; + + iv. rights protecting against unfair competition in regards to a Work, + subject to the limitations in paragraph 4(a), below; + + v. rights protecting the extraction, dissemination, use and reuse of data in + a Work; + + vi. database rights (such as those arising under Directive 96/9/EC of the + European Parliament and of the Council of 11 March 1996 on the legal + protection of databases, and under any national implementation thereof, + including any amended or successor version of such directive); and + + vii. other similar, equivalent or corresponding rights throughout the world + based on applicable law or treaty, and any national implementations thereof. + +2. Waiver. To the greatest extent permitted by, but not in contravention of, +applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and +unconditionally waives, abandons, and surrenders all of Affirmer's Copyright +and Related Rights and associated claims and causes of action, whether now +known or unknown (including existing as well as future claims and causes of +action), in the Work (i) in all territories worldwide, (ii) for the maximum +duration provided by applicable law or treaty (including future time +extensions), (iii) in any current or future medium and for any number of +copies, and (iv) for any purpose whatsoever, including without limitation +commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes +the Waiver for the benefit of each member of the public at large and to the +detriment of Affirmer's heirs and successors, fully intending that such Waiver +shall not be subject to revocation, rescission, cancellation, termination, or +any other legal or equitable action to disrupt the quiet enjoyment of the Work +by the public as contemplated by Affirmer's express Statement of Purpose. + +3. Public License Fallback. Should any part of the Waiver for any reason be +judged legally invalid or ineffective under applicable law, then the Waiver +shall be preserved to the maximum extent permitted taking into account +Affirmer's express Statement of Purpose. In addition, to the extent the Waiver +is so judged Affirmer hereby grants to each affected person a royalty-free, +non transferable, non sublicensable, non exclusive, irrevocable and +unconditional license to exercise Affirmer's Copyright and Related Rights in +the Work (i) in all territories worldwide, (ii) for the maximum duration +provided by applicable law or treaty (including future time extensions), (iii) +in any current or future medium and for any number of copies, and (iv) for any +purpose whatsoever, including without limitation commercial, advertising or +promotional purposes (the "License"). The License shall be deemed effective as +of the date CC0 was applied by Affirmer to the Work. Should any part of the +License for any reason be judged legally invalid or ineffective under +applicable law, such partial invalidity or ineffectiveness shall not +invalidate the remainder of the License, and in such case Affirmer hereby +affirms that he or she will not (i) exercise any of his or her remaining +Copyright and Related Rights in the Work or (ii) assert any associated claims +and causes of action with respect to the Work, in either case contrary to +Affirmer's express Statement of Purpose. + +4. Limitations and Disclaimers. + + a. No trademark or patent rights held by Affirmer are waived, abandoned, + surrendered, licensed or otherwise affected by this document. + + b. Affirmer offers the Work as-is and makes no representations or warranties + of any kind concerning the Work, express, implied, statutory or otherwise, + including without limitation warranties of title, merchantability, fitness + for a particular purpose, non infringement, or the absence of latent or + other defects, accuracy, or the present or absence of errors, whether or not + discoverable, all to the greatest extent permissible under applicable law. + + c. Affirmer disclaims responsibility for clearing rights of other persons + that may apply to the Work or any use thereof, including without limitation + any person's Copyright and Related Rights in the Work. Further, Affirmer + disclaims responsibility for obtaining any necessary consents, permissions + or other rights required for any use of the Work. + + d. Affirmer understands and acknowledges that Creative Commons is not a + party to this document and has no duty or obligation with respect to this + CC0 or use of the Work. + +For more information, please see + diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/address.c b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/address.c new file mode 100644 index 0000000000..b956e9cb29 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/address.c @@ -0,0 +1,91 @@ +#include +#include + +#include "address.h" +#include "params.h" +#include "utils.h" + +/* + * Specify which level of Merkle tree (the "layer") we're working on + */ +void set_layer_addr(uint32_t addr[8], uint32_t layer) { + ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; +} + +/* + * Specify which Merkle tree within the level (the "tree address") we're working on + */ +void set_tree_addr(uint32_t addr[8], uint64_t tree) { + ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); +} + +/* + * Specify the reason we'll use this address structure for, that is, what + * hash will we compute with it. This is used so that unrelated types of + * hashes don't accidentally get the same address structure. The type will be + * one of the SPX_ADDR_TYPE constants + */ +void set_type(uint32_t addr[8], uint32_t type) { + ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; +} + +/* + * Copy the layer and tree fields of the address structure. This is used + * when we're doing multiple types of hashes within the same Merkle tree + */ +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); +} + +/* These functions are used for OTS addresses. */ + +/* + * Specify which Merkle leaf we're working on; that is, which OTS keypair + * we're talking about. + */ +void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { + ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; +} + +/* + * Copy the layer, tree and keypair fields of the address structure. This is + * used when we're doing multiple things within the same OTS keypair + */ +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); + ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; +} + +/* + * Specify which Merkle chain within the OTS we're working with + * (the chain address) + */ +void set_chain_addr(uint32_t addr[8], uint32_t chain) { + ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; +} + +/* + * Specify where in the Merkle chain we are +* (the hash address) + */ +void set_hash_addr(uint32_t addr[8], uint32_t hash) { + ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; +} + +/* These functions are used for all hash tree addresses (including FORS). */ + +/* + * Specify the height of the node in the Merkle/FORS tree we are in + * (the tree height) + */ +void set_tree_height(uint32_t addr[8], uint32_t tree_height) { + ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; +} + +/* + * Specify the distance from the left edge of the node in the Merkle/FORS tree + * (the tree index) + */ +void set_tree_index(uint32_t addr[8], uint32_t tree_index) { + u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/address.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/address.h new file mode 100644 index 0000000000..24a84eb40c --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/address.h @@ -0,0 +1,52 @@ +#ifndef SPX_ADDRESS_H +#define SPX_ADDRESS_H + +#include + +#include "params.h" + +/* The hash types that are passed to set_type */ +#define SPX_ADDR_TYPE_WOTS 0 +#define SPX_ADDR_TYPE_WOTSPK 1 +#define SPX_ADDR_TYPE_HASHTREE 2 +#define SPX_ADDR_TYPE_FORSTREE 3 +#define SPX_ADDR_TYPE_FORSPK 4 +#define SPX_ADDR_TYPE_WOTSPRF 5 +#define SPX_ADDR_TYPE_FORSPRF 6 + +#define set_layer_addr SPX_NAMESPACE(set_layer_addr) +void set_layer_addr(uint32_t addr[8], uint32_t layer); + +#define set_tree_addr SPX_NAMESPACE(set_tree_addr) +void set_tree_addr(uint32_t addr[8], uint64_t tree); + +#define set_type SPX_NAMESPACE(set_type) +void set_type(uint32_t addr[8], uint32_t type); + +/* Copies the layer and tree part of one address into the other */ +#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); + +/* These functions are used for WOTS and FORS addresses. */ + +#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) +void set_keypair_addr(uint32_t addr[8], uint32_t keypair); + +#define set_chain_addr SPX_NAMESPACE(set_chain_addr) +void set_chain_addr(uint32_t addr[8], uint32_t chain); + +#define set_hash_addr SPX_NAMESPACE(set_hash_addr) +void set_hash_addr(uint32_t addr[8], uint32_t hash); + +#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); + +/* These functions are used for all hash tree addresses (including FORS). */ + +#define set_tree_height SPX_NAMESPACE(set_tree_height) +void set_tree_height(uint32_t addr[8], uint32_t tree_height); + +#define set_tree_index SPX_NAMESPACE(set_tree_index) +void set_tree_index(uint32_t addr[8], uint32_t tree_index); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/api.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/api.h new file mode 100644 index 0000000000..dc8607f070 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/api.h @@ -0,0 +1,77 @@ +#ifndef PQCLEAN_SPHINCSSHAKE256FROBUST_CLEAN_API_H +#define PQCLEAN_SPHINCSSHAKE256FROBUST_CLEAN_API_H + +#include +#include + +#define PQCLEAN_SPHINCSSHAKE256FROBUST_CLEAN_CRYPTO_ALGNAME "SPHINCS+-shake-256f-robust" + +#define PQCLEAN_SPHINCSSHAKE256FROBUST_CLEAN_CRYPTO_SECRETKEYBYTES 128 +#define PQCLEAN_SPHINCSSHAKE256FROBUST_CLEAN_CRYPTO_PUBLICKEYBYTES 64 +#define PQCLEAN_SPHINCSSHAKE256FROBUST_CLEAN_CRYPTO_BYTES 49856 + +#define PQCLEAN_SPHINCSSHAKE256FROBUST_CLEAN_CRYPTO_SEEDBYTES 96 + +/* + * Returns the length of a secret key, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE256FROBUST_CLEAN_crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE256FROBUST_CLEAN_crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE256FROBUST_CLEAN_crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE256FROBUST_CLEAN_crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +int PQCLEAN_SPHINCSSHAKE256FROBUST_CLEAN_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +int PQCLEAN_SPHINCSSHAKE256FROBUST_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +int PQCLEAN_SPHINCSSHAKE256FROBUST_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +int PQCLEAN_SPHINCSSHAKE256FROBUST_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, + const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +int PQCLEAN_SPHINCSSHAKE256FROBUST_CLEAN_crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +int PQCLEAN_SPHINCSSHAKE256FROBUST_CLEAN_crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/context.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/context.h new file mode 100644 index 0000000000..9f8a40ab4e --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/context.h @@ -0,0 +1,22 @@ +#ifndef SPX_CONTEXT_H +#define SPX_CONTEXT_H + +#include +#include + +#include "params.h" + +typedef struct { + uint8_t pub_seed[SPX_N]; + uint8_t sk_seed[SPX_N]; + + +} spx_ctx; + +#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) +void initialize_hash_function(spx_ctx *ctx); + +#define free_hash_function SPX_NAMESPACE(free_hash_function) +void free_hash_function(spx_ctx *ctx); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/context_shake.c b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/context_shake.c new file mode 100644 index 0000000000..9614a103d3 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/context_shake.c @@ -0,0 +1,12 @@ +#include "context.h" + +/* For SHAKE256, there is no immediate reason to initialize at the start, + so this function is an empty operation. */ +void initialize_hash_function(spx_ctx *ctx) { + (void)ctx; /* Suppress an 'unused parameter' warning. */ +} + +// in case the hash function api is heap-based. +void free_hash_function(spx_ctx *ctx) { + (void)ctx; +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/fors.c b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/fors.c new file mode 100644 index 0000000000..96ca72e986 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/fors.c @@ -0,0 +1,156 @@ +#include +#include +#include + +#include "fors.h" + +#include "address.h" +#include "hash.h" +#include "thash.h" +#include "utils.h" +#include "utilsx1.h" + +static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + prf_addr(sk, ctx, fors_leaf_addr); +} + +static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, + const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + thash(leaf, sk, 1, ctx, fors_leaf_addr); +} + +struct fors_gen_leaf_info { + uint32_t leaf_addrx[8]; +}; + +static void fors_gen_leafx1(unsigned char *leaf, + const spx_ctx *ctx, + uint32_t addr_idx, void *info) { + struct fors_gen_leaf_info *fors_info = info; + uint32_t *fors_leaf_addr = fors_info->leaf_addrx; + + /* Only set the parts that the caller doesn't set */ + set_tree_index(fors_leaf_addr, addr_idx); + set_type(fors_leaf_addr, SPX_ADDR_TYPE_FORSPRF); + fors_gen_sk(leaf, ctx, fors_leaf_addr); + + set_type(fors_leaf_addr, SPX_ADDR_TYPE_FORSTREE); + fors_sk_to_leaf(leaf, leaf, + ctx, fors_leaf_addr); +} + +/** + * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + * Assumes indices has space for SPX_FORS_TREES integers. + */ +static void message_to_indices(uint32_t *indices, const unsigned char *m) { + unsigned int i, j; + unsigned int offset = 0; + + for (i = 0; i < SPX_FORS_TREES; i++) { + indices[i] = 0; + for (j = 0; j < SPX_FORS_HEIGHT; j++) { + indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); + offset++; + } + } +} + +/** + * Signs a message m, deriving the secret key from sk_seed and the FTS address. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + uint32_t fors_tree_addr[8] = {0}; + struct fors_gen_leaf_info fors_info = {0}; + uint32_t *fors_leaf_addr = fors_info.leaf_addrx; + uint32_t fors_pk_addr[8] = {0}; + uint32_t idx_offset; + unsigned int i; + + copy_keypair_addr(fors_tree_addr, fors_addr); + copy_keypair_addr(fors_leaf_addr, fors_addr); + + copy_keypair_addr(fors_pk_addr, fors_addr); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); + + message_to_indices(indices, m); + + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); + + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); + + /* Include the secret key part that produces the selected leaf node. */ + fors_gen_sk(sig, ctx, fors_tree_addr); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + sig += SPX_N; + + /* Compute the authentication path for this leaf node. */ + treehashx1(roots + i * SPX_N, sig, ctx, + indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx1, + fors_tree_addr, &fors_info); + + sig += SPX_N * SPX_FORS_HEIGHT; + } + + /* Hash horizontally across all tree roots to derive the public key. */ + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); +} + +/** + * Derives the FORS public key from a signature. + * This can be used for verification by comparing to a known public key, or to + * subsequently verify a signature on the derived public key. The latter is the + * typical use-case when used as an FTS below an OTS in a hypertree. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + unsigned char leaf[SPX_N]; + uint32_t fors_tree_addr[8] = {0}; + uint32_t fors_pk_addr[8] = {0}; + uint32_t idx_offset; + unsigned int i; + + copy_keypair_addr(fors_tree_addr, fors_addr); + copy_keypair_addr(fors_pk_addr, fors_addr); + + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); + + message_to_indices(indices, m); + + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); + + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + + /* Derive the leaf from the included secret key part. */ + fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); + sig += SPX_N; + + /* Derive the corresponding root node of this tree. */ + compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, + sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); + sig += SPX_N * SPX_FORS_HEIGHT; + } + + /* Hash horizontally across all tree roots to derive the public key. */ + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/fors.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/fors.h new file mode 100644 index 0000000000..509140a178 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/fors.h @@ -0,0 +1,32 @@ +#ifndef SPX_FORS_H +#define SPX_FORS_H + +#include + +#include "context.h" +#include "params.h" + +/** + * Signs a message m, deriving the secret key from sk_seed and the FTS address. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +#define fors_sign SPX_NAMESPACE(fors_sign) +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); + +/** + * Derives the FORS public key from a signature. + * This can be used for verification by comparing to a known public key, or to + * subsequently verify a signature on the derived public key. The latter is the + * typical use-case when used as an FTS below an OTS in a hypertree. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/hash.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/hash.h new file mode 100644 index 0000000000..f7c87d4c3c --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/hash.h @@ -0,0 +1,28 @@ +#ifndef SPX_HASH_H +#define SPX_HASH_H + +#include +#include + +#include "context.h" +#include "params.h" + +#define prf_addr SPX_NAMESPACE(prf_addr) +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]); + +#define gen_message_random SPX_NAMESPACE(gen_message_random) +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); + +#define hash_message SPX_NAMESPACE(hash_message) +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); + + + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/hash_shake.c b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/hash_shake.c new file mode 100644 index 0000000000..ff5e7ec918 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/hash_shake.c @@ -0,0 +1,83 @@ +#include +#include + +#include "hash.h" + +#include "address.h" +#include "fips202.h" +#include "params.h" +#include "utils.h" + +/* + * Computes PRF(pk_seed, sk_seed, addr) + */ +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]) { + unsigned char buf[2 * SPX_N + SPX_ADDR_BYTES]; + + memcpy(buf, ctx->pub_seed, SPX_N); + memcpy(buf + SPX_N, addr, SPX_ADDR_BYTES); + memcpy(buf + SPX_N + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); + + shake256(out, SPX_N, buf, 2 * SPX_N + SPX_ADDR_BYTES); +} + +/** + * Computes the message-dependent randomness R, using a secret seed and an + * optional randomization value as well as the message. + */ +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { + (void)ctx; + shake256incctx s_inc; + + shake256_inc_init(&s_inc); + shake256_inc_absorb(&s_inc, sk_prf, SPX_N); + shake256_inc_absorb(&s_inc, optrand, SPX_N); + shake256_inc_absorb(&s_inc, m, mlen); + shake256_inc_finalize(&s_inc); + shake256_inc_squeeze(R, SPX_N, &s_inc); + shake256_inc_ctx_release(&s_inc); +} + +/** + * Computes the message hash using R, the public key, and the message. + * Outputs the message digest and the index of the leaf. The index is split in + * the tree index and the leaf index, for convenient copying to an address. + */ +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { + (void)ctx; +#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) +#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) +#define SPX_LEAF_BITS SPX_TREE_HEIGHT +#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) +#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) + + unsigned char buf[SPX_DGST_BYTES]; + unsigned char *bufp = buf; + shake256incctx s_inc; + + shake256_inc_init(&s_inc); + shake256_inc_absorb(&s_inc, R, SPX_N); + shake256_inc_absorb(&s_inc, pk, SPX_PK_BYTES); + shake256_inc_absorb(&s_inc, m, mlen); + shake256_inc_finalize(&s_inc); + shake256_inc_squeeze(buf, SPX_DGST_BYTES, &s_inc); + shake256_inc_ctx_release(&s_inc); + + memcpy(digest, bufp, SPX_FORS_MSG_BYTES); + bufp += SPX_FORS_MSG_BYTES; + + + *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); + *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); + bufp += SPX_TREE_BYTES; + + *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); + *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/merkle.c b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/merkle.c new file mode 100644 index 0000000000..0c1479fd93 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/merkle.c @@ -0,0 +1,59 @@ +#include +#include + +#include "address.h" +#include "merkle.h" +#include "params.h" +#include "utils.h" +#include "utilsx1.h" +#include "wots.h" +#include "wotsx1.h" + +/* + * This generates a Merkle signature (WOTS signature followed by the Merkle + * authentication path). This is in this file because most of the complexity + * is involved with the WOTS signature; the Merkle authentication path logic + * is mostly hidden in treehashx4 + */ +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf) { + unsigned char *auth_path = sig + SPX_WOTS_BYTES; + struct leaf_info_x1 info = { 0 }; + unsigned steps[ SPX_WOTS_LEN ]; + + info.wots_sig = sig; + chain_lengths(steps, root); + info.wots_steps = steps; + + set_type(&tree_addr[0], SPX_ADDR_TYPE_HASHTREE); + set_type(&info.pk_addr[0], SPX_ADDR_TYPE_WOTSPK); + copy_subtree_addr(&info.leaf_addr[0], wots_addr); + copy_subtree_addr(&info.pk_addr[0], wots_addr); + + info.wots_sign_leaf = idx_leaf; + + treehashx1(root, auth_path, ctx, + idx_leaf, 0, + SPX_TREE_HEIGHT, + wots_gen_leafx1, + tree_addr, &info); +} + +/* Compute root node of the top-most subtree. */ +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { + /* We do not need the auth path in key generation, but it simplifies the + code to have just one treehash routine that computes both root and path + in one function. */ + unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; + uint32_t top_tree_addr[8] = {0}; + uint32_t wots_addr[8] = {0}; + + set_layer_addr(top_tree_addr, SPX_D - 1); + set_layer_addr(wots_addr, SPX_D - 1); + + merkle_sign(auth_path, root, ctx, + wots_addr, top_tree_addr, + (uint32_t)~0 /* ~0 means "don't bother generating an auth path */ ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/merkle.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/merkle.h new file mode 100644 index 0000000000..769cf2e970 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/merkle.h @@ -0,0 +1,21 @@ +#ifndef MERKLE_H_ +#define MERKLE_H_ + +#include + +#include "context.h" +#include "params.h" + +/* Generate a Merkle signature (WOTS signature followed by the Merkle */ +/* authentication path) */ +#define merkle_sign SPX_NAMESPACE(merkle_sign) +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf); + +/* Compute the root node of the top-most subtree. */ +#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); + +#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/nistapi.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/nistapi.h new file mode 100644 index 0000000000..3cb71afad4 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/nistapi.h @@ -0,0 +1,87 @@ +#ifndef SPX_API_H +#define SPX_API_H + +#include +#include + +#include "params.h" + +#define CRYPTO_ALGNAME "SPHINCS+" + +#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES +#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES +#define CRYPTO_BYTES SPX_BYTES +#define CRYPTO_SEEDBYTES (3*SPX_N) + +/* + * Returns the length of a secret key, in bytes + */ +#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) +size_t crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) +size_t crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) +size_t crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) +size_t crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +#define crypto_sign SPX_NAMESPACE(crypto_sign) +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/params.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/params.h new file mode 100644 index 0000000000..afa749e65a --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/params.h @@ -0,0 +1,56 @@ +#ifndef SPX_PARAMS_H +#define SPX_PARAMS_H + +#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSSHAKE256FROBUST_CLEAN_##s + +/* Hash output length in bytes. */ +#define SPX_N 32 +/* Height of the hypertree. */ +#define SPX_FULL_HEIGHT 68 +/* Number of subtree layer. */ +#define SPX_D 17 +/* FORS tree dimensions. */ +#define SPX_FORS_HEIGHT 9 +#define SPX_FORS_TREES 35 +/* Winternitz parameter, */ +#define SPX_WOTS_W 16 + +/* The hash function is defined by linking a different hash.c file, as opposed + to setting a #define constant. */ + +/* For clarity */ +#define SPX_ADDR_BYTES 32 + +/* WOTS parameters. */ +#define SPX_WOTS_LOGW 4 + +#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) + +/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ +#define SPX_WOTS_LEN2 3 + +#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) +#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) +#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES + +/* Subtree size. */ +#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) + +//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT +// #error SPX_D should always divide SPX_FULL_HEIGHT +//#endif + +/* FORS parameters. */ +#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) +#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) +#define SPX_FORS_PK_BYTES SPX_N + +/* Resulting SPX sizes. */ +#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ + SPX_FULL_HEIGHT * SPX_N) +#define SPX_PK_BYTES (2 * SPX_N) +#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) + +#include "shake_offsets.h" + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/shake_offsets.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/shake_offsets.h new file mode 100644 index 0000000000..6b28d95d91 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/shake_offsets.h @@ -0,0 +1,21 @@ +#ifndef SHAKE_OFFSETS_H_ +#define SHAKE_OFFSETS_H_ + +/* + * Offsets of various fields in the address structure when we use SHAKE as + * the Sphincs+ hash function + */ + +#define SPX_OFFSET_LAYER 3 /* The byte used to specify the Merkle tree layer */ +#define SPX_OFFSET_TREE 8 /* The start of the 8 byte field used to specify the tree */ +#define SPX_OFFSET_TYPE 19 /* The byte used to specify the hash type (reason) */ +#define SPX_OFFSET_KP_ADDR2 22 /* The high byte used to specify the key pair (which one-time signature) */ +#define SPX_OFFSET_KP_ADDR1 23 /* The low byte used to specify the key pair */ +#define SPX_OFFSET_CHAIN_ADDR 27 /* The byte used to specify the chain address (which Winternitz chain) */ +#define SPX_OFFSET_HASH_ADDR 31 /* The byte used to specify the hash address (where in the Winternitz chain) */ +#define SPX_OFFSET_TREE_HGT 27 /* The byte used to specify the height of this node in the FORS or Merkle tree */ +#define SPX_OFFSET_TREE_INDEX 28 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ + +#define SPX_SHAKE 1 + +#endif /* SHAKE_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/sign.c b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/sign.c new file mode 100644 index 0000000000..9d0c7d1b22 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/sign.c @@ -0,0 +1,286 @@ +#include +#include +#include + +#include "address.h" +#include "context.h" +#include "fors.h" +#include "hash.h" +#include "merkle.h" +#include "nistapi.h" +#include "params.h" +#include "randombytes.h" +#include "thash.h" +#include "utils.h" +#include "wots.h" + +/* + * Returns the length of a secret key, in bytes + */ +size_t crypto_sign_secretkeybytes(void) { + return CRYPTO_SECRETKEYBYTES; +} + +/* + * Returns the length of a public key, in bytes + */ +size_t crypto_sign_publickeybytes(void) { + return CRYPTO_PUBLICKEYBYTES; +} + +/* + * Returns the length of a signature, in bytes + */ +size_t crypto_sign_bytes(void) { + return CRYPTO_BYTES; +} + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +size_t crypto_sign_seedbytes(void) { + return CRYPTO_SEEDBYTES; +} + +/* + * Generates an SPX key pair given a seed of length + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [PUB_SEED || root] + */ +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed) { + spx_ctx ctx; + + /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ + memcpy(sk, seed, CRYPTO_SEEDBYTES); + + memcpy(pk, sk + 2 * SPX_N, SPX_N); + + memcpy(ctx.pub_seed, pk, SPX_N); + memcpy(ctx.sk_seed, sk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + /* Compute root node of the top-most subtree. */ + merkle_gen_root(sk + 3 * SPX_N, &ctx); + + // cleanup + free_hash_function(&ctx); + + memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); + + return 0; +} + +/* + * Generates an SPX key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [PUB_SEED || root] + */ +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { + uint8_t seed[CRYPTO_SEEDBYTES]; + randombytes(seed, CRYPTO_SEEDBYTES); + crypto_sign_seed_keypair(pk, sk, seed); + + return 0; +} + +/** + * Returns an array containing a detached signature. + */ +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk) { + spx_ctx ctx; + + const uint8_t *sk_prf = sk + SPX_N; + const uint8_t *pk = sk + 2 * SPX_N; + + uint8_t optrand[SPX_N]; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t root[SPX_N]; + uint32_t i; + uint64_t tree; + uint32_t idx_leaf; + uint32_t wots_addr[8] = {0}; + uint32_t tree_addr[8] = {0}; + + memcpy(ctx.sk_seed, sk, SPX_N); + memcpy(ctx.pub_seed, pk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + + /* Optionally, signing can be made non-deterministic using optrand. + This can help counter side-channel attacks that would benefit from + getting a large number of traces when the signer uses the same nodes. */ + randombytes(optrand, SPX_N); + /* Compute the digest randomization value. */ + gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); + + /* Derive the message digest and leaf index from R, PK and M. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; + + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); + + /* Sign the message hash using FORS. */ + fors_sign(sig, root, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); + sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; + + /* Update the indices for the next layer. */ + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; + } + + free_hash_function(&ctx); + + *siglen = SPX_BYTES; + + return 0; +} + +/** + * Verifies a detached signature and message under a given public key. + */ +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk) { + spx_ctx ctx; + const uint8_t *pub_root = pk + SPX_N; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t wots_pk[SPX_WOTS_BYTES]; + uint8_t root[SPX_N]; + uint8_t leaf[SPX_N]; + unsigned int i; + uint64_t tree; + uint32_t idx_leaf; + uint32_t wots_addr[8] = {0}; + uint32_t tree_addr[8] = {0}; + uint32_t wots_pk_addr[8] = {0}; + + if (siglen != SPX_BYTES) { + return -1; + } + + memcpy(ctx.pub_seed, pk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); + + /* Derive the message digest and leaf index from R || PK || M. */ + /* The additional SPX_N is a result of the hash domain separator. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; + + /* Layer correctly defaults to 0, so no need to set_layer_addr */ + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); + + fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + /* For each subtree.. */ + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + copy_keypair_addr(wots_pk_addr, wots_addr); + + /* The WOTS public key is only correct if the signature was correct. */ + /* Initially, root is the FORS pk, but on subsequent iterations it is + the root of the subtree below the currently processed subtree. */ + wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); + sig += SPX_WOTS_BYTES; + + /* Compute the leaf node using the WOTS public key. */ + thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); + + /* Compute the root node of this subtree. */ + compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, + &ctx, tree_addr); + sig += SPX_TREE_HEIGHT * SPX_N; + + /* Update the indices for the next layer. */ + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; + } + + // cleanup + free_hash_function(&ctx); + + /* Check if the root node equals the root node in the public key. */ + if (memcmp(root, pub_root, SPX_N) != 0) { + return -1; + } + + return 0; +} + + +/** + * Returns an array containing the signature followed by the message. + */ +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk) { + size_t siglen; + + crypto_sign_signature(sm, &siglen, m, mlen, sk); + + memmove(sm + SPX_BYTES, m, mlen); + *smlen = siglen + mlen; + + return 0; +} + +/** + * Verifies a given signature-message pair under a given public key. + */ +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk) { + /* The API caller does not necessarily know what size a signature should be + but SPHINCS+ signatures are always exactly SPX_BYTES. */ + if (smlen < SPX_BYTES) { + memset(m, 0, smlen); + *mlen = 0; + return -1; + } + + *mlen = smlen - SPX_BYTES; + + if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { + memset(m, 0, smlen); + *mlen = 0; + return -1; + } + + /* If verification was successful, move the message to the right place. */ + memmove(m, sm + SPX_BYTES, *mlen); + + return 0; +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/thash.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/thash.h new file mode 100644 index 0000000000..8687ccfb4d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/thash.h @@ -0,0 +1,13 @@ +#ifndef SPX_THASH_H +#define SPX_THASH_H + +#include "context.h" +#include "params.h" + +#include + +#define thash SPX_NAMESPACE(thash) +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/thash_shake_robust.c b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/thash_shake_robust.c new file mode 100644 index 0000000000..696d53c5cc --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/thash_shake_robust.c @@ -0,0 +1,31 @@ +#include +#include + +#include "thash.h" + +#include "address.h" +#include "params.h" +#include "utils.h" + +#include "fips202.h" + +/** + * Takes an array of inblocks concatenated arrays of SPX_N bytes. + */ +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]) { + PQCLEAN_VLA(uint8_t, buf, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); + PQCLEAN_VLA(uint8_t, bitmask, inblocks * SPX_N); + unsigned int i; + + memcpy(buf, ctx->pub_seed, SPX_N); + memcpy(buf + SPX_N, addr, SPX_ADDR_BYTES); + + shake256(bitmask, inblocks * SPX_N, buf, SPX_N + SPX_ADDR_BYTES); + + for (i = 0; i < inblocks * SPX_N; i++) { + buf[SPX_N + SPX_ADDR_BYTES + i] = in[i] ^ bitmask[i]; + } + + shake256(out, SPX_N, buf, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/utils.c b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/utils.c new file mode 100644 index 0000000000..177b541fb9 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/utils.c @@ -0,0 +1,148 @@ +#include + +#include "utils.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "thash.h" + +/** + * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. + */ +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in) { + int i; + + /* Iterate over out in decreasing order, for big-endianness. */ + for (i = (signed int)outlen - 1; i >= 0; i--) { + out[i] = in & 0xff; + in = in >> 8; + } +} + +void u32_to_bytes(unsigned char *out, uint32_t in) { + out[0] = (unsigned char)(in >> 24); + out[1] = (unsigned char)(in >> 16); + out[2] = (unsigned char)(in >> 8); + out[3] = (unsigned char)in; +} + +/** + * Converts the inlen bytes in 'in' from big-endian byte order to an integer. + */ +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { + unsigned long long retval = 0; + unsigned int i; + + for (i = 0; i < inlen; i++) { + retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); + } + return retval; +} + +/** + * Computes a root node given a leaf and an auth path. + * Expects address to be complete other than the tree_height and tree_index. + */ +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]) { + uint32_t i; + unsigned char buffer[2 * SPX_N]; + + /* If leaf_idx is odd (last bit = 1), current path element is a right child + and auth_path has to go left. Otherwise it is the other way around. */ + if (leaf_idx & 1) { + memcpy(buffer + SPX_N, leaf, SPX_N); + memcpy(buffer, auth_path, SPX_N); + } else { + memcpy(buffer, leaf, SPX_N); + memcpy(buffer + SPX_N, auth_path, SPX_N); + } + auth_path += SPX_N; + + for (i = 0; i < tree_height - 1; i++) { + leaf_idx >>= 1; + idx_offset >>= 1; + /* Set the address of the node we're creating. */ + set_tree_height(addr, i + 1); + set_tree_index(addr, leaf_idx + idx_offset); + + /* Pick the right or left neighbor, depending on parity of the node. */ + if (leaf_idx & 1) { + thash(buffer + SPX_N, buffer, 2, ctx, addr); + memcpy(buffer, auth_path, SPX_N); + } else { + thash(buffer, buffer, 2, ctx, addr); + memcpy(buffer + SPX_N, auth_path, SPX_N); + } + auth_path += SPX_N; + } + + /* The last iteration is exceptional; we do not copy an auth_path node. */ + leaf_idx >>= 1; + idx_offset >>= 1; + set_tree_height(addr, tree_height); + set_tree_index(addr, leaf_idx + idx_offset); + thash(root, buffer, 2, ctx, addr); +} + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx * /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]) { + PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); + PQCLEAN_VLA(unsigned int, heights, tree_height + 1); + unsigned int offset = 0; + uint32_t idx; + uint32_t tree_idx; + + for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { + /* Add the next leaf node to the stack. */ + gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); + offset++; + heights[offset - 1] = 0; + + /* If this is a node we need for the auth path.. */ + if ((leaf_idx ^ 0x1) == idx) { + memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); + } + + /* While the top-most nodes are of equal height.. */ + while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { + /* Compute index of the new node, in the next layer. */ + tree_idx = (idx >> (heights[offset - 1] + 1)); + + /* Set the address of the node we're creating. */ + set_tree_height(tree_addr, heights[offset - 1] + 1); + set_tree_index(tree_addr, + tree_idx + (idx_offset >> (heights[offset - 1] + 1))); + /* Hash the top-most nodes from the stack together. */ + thash(stack + (offset - 2)*SPX_N, + stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); + offset--; + /* Note that the top-most node is now one layer higher. */ + heights[offset - 1]++; + + /* If this is a node we need for the auth path.. */ + if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { + memcpy(auth_path + heights[offset - 1]*SPX_N, + stack + (offset - 1)*SPX_N, SPX_N); + } + } + } + memcpy(root, stack, SPX_N); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/utils.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/utils.h new file mode 100644 index 0000000000..64f5d5a53a --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/utils.h @@ -0,0 +1,58 @@ +#ifndef SPX_UTILS_H +#define SPX_UTILS_H + +#include + +#include "compat.h" +#include "context.h" +#include "params.h" + + +/* To support MSVC use alloca() instead of VLAs. See #20. */ + + +/** + * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. + */ +#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in); +#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) +void u32_to_bytes(unsigned char *out, uint32_t in); + +/** + * Converts the inlen bytes in 'in' from big-endian byte order to an integer. + */ +#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); + +/** + * Computes a root node given a leaf and an auth path. + * Expects address to be complete other than the tree_height and tree_index. + */ +#define compute_root SPX_NAMESPACE(compute_root) +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]); + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +#define treehash SPX_NAMESPACE(treehash) +void treehash(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx *ctx /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]); + + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/utilsx1.c b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/utilsx1.c new file mode 100644 index 0000000000..fccb69b35d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/utilsx1.c @@ -0,0 +1,100 @@ +#include + +#include "utilsx1.h" + +#include "address.h" +#include "params.h" +#include "thash.h" +#include "utils.h" + +/* + * Generate the entire Merkle tree, computing the authentication path for + * leaf_idx, and the resulting root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) + * + * This expects tree_addr to be initialized to the addr structures for the + * Merkle tree nodes + * + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + * + * This works by using the standard Merkle tree building algorithm, + */ +void treehashx1(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, + uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* Where to write the leaves */, + const spx_ctx * /* ctx */, + uint32_t idx, void *info), + uint32_t tree_addr[8], + void *info) { + /* This is where we keep the intermediate nodes */ + PQCLEAN_VLA(uint8_t, stack, tree_height * SPX_N); + + uint32_t idx; + uint32_t max_idx = (uint32_t)((1 << tree_height) - 1); + for (idx = 0;; idx++) { + unsigned char current[2 * SPX_N]; /* Current logical node is at */ + /* index[SPX_N]. We do this to minimize the number of copies */ + /* needed during a thash */ + gen_leaf( ¤t[SPX_N], ctx, idx + idx_offset, + info ); + + /* Now combine the freshly generated right node with previously */ + /* generated left ones */ + uint32_t internal_idx_offset = idx_offset; + uint32_t internal_idx = idx; + uint32_t internal_leaf = leaf_idx; + uint32_t h; /* The height we are in the Merkle tree */ + for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { + + /* Check if we hit the top of the tree */ + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[SPX_N], SPX_N ); + return; + } + + /* + * Check if the node we have is a part of the + * authentication path; if it is, write it out + */ + if ((internal_idx ^ internal_leaf) == 0x01) { + memcpy( &auth_path[ h * SPX_N ], + ¤t[SPX_N], + SPX_N ); + } + + /* + * Check if we're at a left child; if so, stop going up the stack + * Exception: if we've reached the end of the tree, keep on going + * (so we combine the last 4 nodes into the one root node in two + * more iterations) + */ + if ((internal_idx & 1) == 0 && idx < max_idx) { + break; + } + + /* Ok, we're at a right node */ + /* Now combine the left and right logical nodes together */ + + /* Set the address of the node we're creating. */ + internal_idx_offset >>= 1; + set_tree_height(tree_addr, h + 1); + set_tree_index(tree_addr, internal_idx / 2 + internal_idx_offset ); + + unsigned char *left = &stack[h * SPX_N]; + memcpy( ¤t[0], left, SPX_N ); + thash( ¤t[1 * SPX_N], + ¤t[0 * SPX_N], + 2, ctx, tree_addr); + } + + /* We've hit a left child; save the current for when we get the */ + /* corresponding right right */ + memcpy( &stack[h * SPX_N], ¤t[SPX_N], SPX_N); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/utilsx1.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/utilsx1.h new file mode 100644 index 0000000000..e911d17d53 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/utilsx1.h @@ -0,0 +1,27 @@ +#ifndef SPX_UTILSX4_H +#define SPX_UTILSX4_H + +#include + +#include "context.h" +#include "params.h" + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +#define treehashx1 SPX_NAMESPACE(treehashx1) +void treehashx1(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* Where to write the leaf */, + const spx_ctx * /* ctx */, + uint32_t addr_idx, void *info), + uint32_t tree_addrx4[8], void *info); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/wots.c b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/wots.c new file mode 100644 index 0000000000..249717aaa8 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/wots.c @@ -0,0 +1,108 @@ +#include +#include + +#include "wots.h" +#include "wotsx1.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "thash.h" +#include "utils.h" +#include "utilsx1.h" + +// TODO clarify address expectations, and make them more uniform. +// TODO i.e. do we expect types to be set already? +// TODO and do we expect modifications or copies? + +/** + * Computes the chaining function. + * out and in have to be n-byte arrays. + * + * Interprets in as start-th value of the chain. + * addr has to contain the address of the chain. + */ +static void gen_chain(unsigned char *out, const unsigned char *in, + unsigned int start, unsigned int steps, + const spx_ctx *ctx, uint32_t addr[8]) { + uint32_t i; + + /* Initialize out with the value at position 'start'. */ + memcpy(out, in, SPX_N); + + /* Iterate 'steps' calls to the hash function. */ + for (i = start; i < (start + steps) && i < SPX_WOTS_W; i++) { + set_hash_addr(addr, i); + thash(out, out, 1, ctx, addr); + } +} + +/** + * base_w algorithm as described in draft. + * Interprets an array of bytes as integers in base w. + * This only works when log_w is a divisor of 8. + */ +static void base_w(unsigned int *output, const int out_len, + const unsigned char *input) { + int in = 0; + int out = 0; + unsigned char total = 0; + int bits = 0; + int consumed; + + for (consumed = 0; consumed < out_len; consumed++) { + if (bits == 0) { + total = input[in]; + in++; + bits += 8; + } + bits -= SPX_WOTS_LOGW; + output[out] = (total >> bits) & (SPX_WOTS_W - 1); + out++; + } +} + +/* Computes the WOTS+ checksum over a message (in base_w). */ +static void wots_checksum(unsigned int *csum_base_w, + const unsigned int *msg_base_w) { + unsigned int csum = 0; + unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; + unsigned int i; + + /* Compute checksum. */ + for (i = 0; i < SPX_WOTS_LEN1; i++) { + csum += SPX_WOTS_W - 1 - msg_base_w[i]; + } + + /* Convert checksum to base_w. */ + /* Make sure expected empty zero bits are the least significant bits. */ + csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); + ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); + base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); +} + +/* Takes a message and derives the matching chain lengths. */ +void chain_lengths(unsigned int *lengths, const unsigned char *msg) { + base_w(lengths, SPX_WOTS_LEN1, msg); + wots_checksum(lengths + SPX_WOTS_LEN1, lengths); +} + +/** + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. + * + * Writes the computed public key to 'pk'. + */ +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]) { + unsigned int lengths[SPX_WOTS_LEN]; + uint32_t i; + + chain_lengths(lengths, msg); + + for (i = 0; i < SPX_WOTS_LEN; i++) { + set_chain_addr(addr, i); + gen_chain(pk + i * SPX_N, sig + i * SPX_N, + lengths[i], SPX_WOTS_W - 1 - lengths[i], ctx, addr); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/wots.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/wots.h new file mode 100644 index 0000000000..4e7692eeef --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/wots.h @@ -0,0 +1,25 @@ +#ifndef SPX_WOTS_H +#define SPX_WOTS_H + +#include + +#include "context.h" +#include "params.h" + +/** + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. + * + * Writes the computed public key to 'pk'. + */ +#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]); + +/* + * Compute the chain lengths needed for a given message hash + */ +#define chain_lengths SPX_NAMESPACE(chain_lengths) +void chain_lengths(unsigned int *lengths, const unsigned char *msg); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/wotsx1.c b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/wotsx1.c new file mode 100644 index 0000000000..3adec78dfb --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/wotsx1.c @@ -0,0 +1,76 @@ +#include +#include + +#include "wots.h" +#include "wotsx1.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "thash.h" +#include "utils.h" + +/* + * This generates a WOTS public key + * It also generates the WOTS signature if leaf_info indicates + * that we're signing with this WOTS key + */ +void wots_gen_leafx1(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info) { + struct leaf_info_x1 *info = v_info; + uint32_t *leaf_addr = info->leaf_addr; + uint32_t *pk_addr = info->pk_addr; + unsigned int i, k; + unsigned char pk_buffer[ SPX_WOTS_BYTES ]; + unsigned char *buffer; + uint32_t wots_k_mask; + + if (leaf_idx == info->wots_sign_leaf) { + /* We're traversing the leaf that's signing; generate the WOTS */ + /* signature */ + wots_k_mask = 0; + } else { + /* Nope, we're just generating pk's; turn off the signature logic */ + wots_k_mask = (uint32_t)~0; + } + + set_keypair_addr( leaf_addr, leaf_idx ); + set_keypair_addr( pk_addr, leaf_idx ); + + for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { + uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k to */ + /* the step if we're generating a signature, ~0 if we're not */ + + /* Start with the secret seed */ + set_chain_addr(leaf_addr, i); + set_hash_addr(leaf_addr, 0); + set_type(leaf_addr, SPX_ADDR_TYPE_WOTSPRF); + + prf_addr(buffer, ctx, leaf_addr); + + set_type(leaf_addr, SPX_ADDR_TYPE_WOTS); + + /* Iterate down the WOTS chain */ + for (k = 0;; k++) { + /* Check if this is the value that needs to be saved as a */ + /* part of the WOTS signature */ + if (k == wots_k) { + memcpy( info->wots_sig + i * SPX_N, buffer, SPX_N ); + } + + /* Check if we hit the top of the chain */ + if (k == SPX_WOTS_W - 1) { + break; + } + + /* Iterate one step on the chain */ + set_hash_addr(leaf_addr, k); + + thash(buffer, buffer, 1, ctx, leaf_addr); + } + } + + /* Do the final thash to generate the public keys */ + thash(dest, pk_buffer, SPX_WOTS_LEN, ctx, pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/wotsx1.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/wotsx1.h new file mode 100644 index 0000000000..e617929f96 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/wotsx1.h @@ -0,0 +1,39 @@ +#ifndef WOTSX1_H_ +#define WOTSX1_H_ + +#include + +#include "context.h" +#include "params.h" + +/* + * This is here to provide an interface to the internal wots_gen_leafx1 + * routine. While this routine is not referenced in the package outside of + * wots.c, it is called from the stand-alone benchmark code to characterize + * the performance + */ +struct leaf_info_x1 { + unsigned char *wots_sig; + uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ + uint32_t *wots_steps; + uint32_t leaf_addr[8]; + uint32_t pk_addr[8]; +}; + +/* Macro to set the leaf_info to something 'benign', that is, it would */ +/* run with the same time as it does during the real signing process */ +/* Used only by the benchmark code */ +#define INITIALIZE_LEAF_INFO_X1(info, addr, step_buffer) { \ + (info).wots_sig = 0; \ + (info).wots_sign_leaf = ~0; \ + (info).wots_steps = step_buffer; \ + memcpy( &(info).leaf_addr[0], (addr), 32 ); \ + memcpy( &(info).pk_addr[0], (addr), 32 ); \ + } + +#define wots_gen_leafx1 SPX_NAMESPACE(wots_gen_leafx1) +void wots_gen_leafx1(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info); + +#endif /* WOTSX1_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/LICENSE b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/LICENSE new file mode 100644 index 0000000000..670154e353 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/LICENSE @@ -0,0 +1,116 @@ +CC0 1.0 Universal + +Statement of Purpose + +The laws of most jurisdictions throughout the world automatically confer +exclusive Copyright and Related Rights (defined below) upon the creator and +subsequent owner(s) (each and all, an "owner") of an original work of +authorship and/or a database (each, a "Work"). + +Certain owners wish to permanently relinquish those rights to a Work for the +purpose of contributing to a commons of creative, cultural and scientific +works ("Commons") that the public can reliably and without fear of later +claims of infringement build upon, modify, incorporate in other works, reuse +and redistribute as freely as possible in any form whatsoever and for any +purposes, including without limitation commercial purposes. These owners may +contribute to the Commons to promote the ideal of a free culture and the +further production of creative, cultural and scientific works, or to gain +reputation or greater distribution for their Work in part through the use and +efforts of others. + +For these and/or other purposes and motivations, and without any expectation +of additional consideration or compensation, the person associating CC0 with a +Work (the "Affirmer"), to the extent that he or she is an owner of Copyright +and Related Rights in the Work, voluntarily elects to apply CC0 to the Work +and publicly distribute the Work under its terms, with knowledge of his or her +Copyright and Related Rights in the Work and the meaning and intended legal +effect of CC0 on those rights. + +1. Copyright and Related Rights. A Work made available under CC0 may be +protected by copyright and related or neighboring rights ("Copyright and +Related Rights"). Copyright and Related Rights include, but are not limited +to, the following: + + i. the right to reproduce, adapt, distribute, perform, display, communicate, + and translate a Work; + + ii. moral rights retained by the original author(s) and/or performer(s); + + iii. publicity and privacy rights pertaining to a person's image or likeness + depicted in a Work; + + iv. rights protecting against unfair competition in regards to a Work, + subject to the limitations in paragraph 4(a), below; + + v. rights protecting the extraction, dissemination, use and reuse of data in + a Work; + + vi. database rights (such as those arising under Directive 96/9/EC of the + European Parliament and of the Council of 11 March 1996 on the legal + protection of databases, and under any national implementation thereof, + including any amended or successor version of such directive); and + + vii. other similar, equivalent or corresponding rights throughout the world + based on applicable law or treaty, and any national implementations thereof. + +2. Waiver. To the greatest extent permitted by, but not in contravention of, +applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and +unconditionally waives, abandons, and surrenders all of Affirmer's Copyright +and Related Rights and associated claims and causes of action, whether now +known or unknown (including existing as well as future claims and causes of +action), in the Work (i) in all territories worldwide, (ii) for the maximum +duration provided by applicable law or treaty (including future time +extensions), (iii) in any current or future medium and for any number of +copies, and (iv) for any purpose whatsoever, including without limitation +commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes +the Waiver for the benefit of each member of the public at large and to the +detriment of Affirmer's heirs and successors, fully intending that such Waiver +shall not be subject to revocation, rescission, cancellation, termination, or +any other legal or equitable action to disrupt the quiet enjoyment of the Work +by the public as contemplated by Affirmer's express Statement of Purpose. + +3. Public License Fallback. Should any part of the Waiver for any reason be +judged legally invalid or ineffective under applicable law, then the Waiver +shall be preserved to the maximum extent permitted taking into account +Affirmer's express Statement of Purpose. In addition, to the extent the Waiver +is so judged Affirmer hereby grants to each affected person a royalty-free, +non transferable, non sublicensable, non exclusive, irrevocable and +unconditional license to exercise Affirmer's Copyright and Related Rights in +the Work (i) in all territories worldwide, (ii) for the maximum duration +provided by applicable law or treaty (including future time extensions), (iii) +in any current or future medium and for any number of copies, and (iv) for any +purpose whatsoever, including without limitation commercial, advertising or +promotional purposes (the "License"). The License shall be deemed effective as +of the date CC0 was applied by Affirmer to the Work. Should any part of the +License for any reason be judged legally invalid or ineffective under +applicable law, such partial invalidity or ineffectiveness shall not +invalidate the remainder of the License, and in such case Affirmer hereby +affirms that he or she will not (i) exercise any of his or her remaining +Copyright and Related Rights in the Work or (ii) assert any associated claims +and causes of action with respect to the Work, in either case contrary to +Affirmer's express Statement of Purpose. + +4. Limitations and Disclaimers. + + a. No trademark or patent rights held by Affirmer are waived, abandoned, + surrendered, licensed or otherwise affected by this document. + + b. Affirmer offers the Work as-is and makes no representations or warranties + of any kind concerning the Work, express, implied, statutory or otherwise, + including without limitation warranties of title, merchantability, fitness + for a particular purpose, non infringement, or the absence of latent or + other defects, accuracy, or the present or absence of errors, whether or not + discoverable, all to the greatest extent permissible under applicable law. + + c. Affirmer disclaims responsibility for clearing rights of other persons + that may apply to the Work or any use thereof, including without limitation + any person's Copyright and Related Rights in the Work. Further, Affirmer + disclaims responsibility for obtaining any necessary consents, permissions + or other rights required for any use of the Work. + + d. Affirmer understands and acknowledges that Creative Commons is not a + party to this document and has no duty or obligation with respect to this + CC0 or use of the Work. + +For more information, please see + diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/address.c b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/address.c new file mode 100644 index 0000000000..b956e9cb29 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/address.c @@ -0,0 +1,91 @@ +#include +#include + +#include "address.h" +#include "params.h" +#include "utils.h" + +/* + * Specify which level of Merkle tree (the "layer") we're working on + */ +void set_layer_addr(uint32_t addr[8], uint32_t layer) { + ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; +} + +/* + * Specify which Merkle tree within the level (the "tree address") we're working on + */ +void set_tree_addr(uint32_t addr[8], uint64_t tree) { + ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); +} + +/* + * Specify the reason we'll use this address structure for, that is, what + * hash will we compute with it. This is used so that unrelated types of + * hashes don't accidentally get the same address structure. The type will be + * one of the SPX_ADDR_TYPE constants + */ +void set_type(uint32_t addr[8], uint32_t type) { + ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; +} + +/* + * Copy the layer and tree fields of the address structure. This is used + * when we're doing multiple types of hashes within the same Merkle tree + */ +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); +} + +/* These functions are used for OTS addresses. */ + +/* + * Specify which Merkle leaf we're working on; that is, which OTS keypair + * we're talking about. + */ +void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { + ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; +} + +/* + * Copy the layer, tree and keypair fields of the address structure. This is + * used when we're doing multiple things within the same OTS keypair + */ +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); + ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; +} + +/* + * Specify which Merkle chain within the OTS we're working with + * (the chain address) + */ +void set_chain_addr(uint32_t addr[8], uint32_t chain) { + ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; +} + +/* + * Specify where in the Merkle chain we are +* (the hash address) + */ +void set_hash_addr(uint32_t addr[8], uint32_t hash) { + ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; +} + +/* These functions are used for all hash tree addresses (including FORS). */ + +/* + * Specify the height of the node in the Merkle/FORS tree we are in + * (the tree height) + */ +void set_tree_height(uint32_t addr[8], uint32_t tree_height) { + ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; +} + +/* + * Specify the distance from the left edge of the node in the Merkle/FORS tree + * (the tree index) + */ +void set_tree_index(uint32_t addr[8], uint32_t tree_index) { + u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/address.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/address.h new file mode 100644 index 0000000000..24a84eb40c --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/address.h @@ -0,0 +1,52 @@ +#ifndef SPX_ADDRESS_H +#define SPX_ADDRESS_H + +#include + +#include "params.h" + +/* The hash types that are passed to set_type */ +#define SPX_ADDR_TYPE_WOTS 0 +#define SPX_ADDR_TYPE_WOTSPK 1 +#define SPX_ADDR_TYPE_HASHTREE 2 +#define SPX_ADDR_TYPE_FORSTREE 3 +#define SPX_ADDR_TYPE_FORSPK 4 +#define SPX_ADDR_TYPE_WOTSPRF 5 +#define SPX_ADDR_TYPE_FORSPRF 6 + +#define set_layer_addr SPX_NAMESPACE(set_layer_addr) +void set_layer_addr(uint32_t addr[8], uint32_t layer); + +#define set_tree_addr SPX_NAMESPACE(set_tree_addr) +void set_tree_addr(uint32_t addr[8], uint64_t tree); + +#define set_type SPX_NAMESPACE(set_type) +void set_type(uint32_t addr[8], uint32_t type); + +/* Copies the layer and tree part of one address into the other */ +#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); + +/* These functions are used for WOTS and FORS addresses. */ + +#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) +void set_keypair_addr(uint32_t addr[8], uint32_t keypair); + +#define set_chain_addr SPX_NAMESPACE(set_chain_addr) +void set_chain_addr(uint32_t addr[8], uint32_t chain); + +#define set_hash_addr SPX_NAMESPACE(set_hash_addr) +void set_hash_addr(uint32_t addr[8], uint32_t hash); + +#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); + +/* These functions are used for all hash tree addresses (including FORS). */ + +#define set_tree_height SPX_NAMESPACE(set_tree_height) +void set_tree_height(uint32_t addr[8], uint32_t tree_height); + +#define set_tree_index SPX_NAMESPACE(set_tree_index) +void set_tree_index(uint32_t addr[8], uint32_t tree_index); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/api.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/api.h new file mode 100644 index 0000000000..3d21ff3dfe --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/api.h @@ -0,0 +1,77 @@ +#ifndef PQCLEAN_SPHINCSSHAKE256FSIMPLE_AARCH64_API_H +#define PQCLEAN_SPHINCSSHAKE256FSIMPLE_AARCH64_API_H + +#include +#include + +#define PQCLEAN_SPHINCSSHAKE256FSIMPLE_AARCH64_CRYPTO_ALGNAME "SPHINCS+-shake-256f-simple" + +#define PQCLEAN_SPHINCSSHAKE256FSIMPLE_AARCH64_CRYPTO_SECRETKEYBYTES 128 +#define PQCLEAN_SPHINCSSHAKE256FSIMPLE_AARCH64_CRYPTO_PUBLICKEYBYTES 64 +#define PQCLEAN_SPHINCSSHAKE256FSIMPLE_AARCH64_CRYPTO_BYTES 49856 + +#define PQCLEAN_SPHINCSSHAKE256FSIMPLE_AARCH64_CRYPTO_SEEDBYTES 96 + +/* + * Returns the length of a secret key, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE256FSIMPLE_AARCH64_crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE256FSIMPLE_AARCH64_crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE256FSIMPLE_AARCH64_crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE256FSIMPLE_AARCH64_crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +int PQCLEAN_SPHINCSSHAKE256FSIMPLE_AARCH64_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +int PQCLEAN_SPHINCSSHAKE256FSIMPLE_AARCH64_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +int PQCLEAN_SPHINCSSHAKE256FSIMPLE_AARCH64_crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +int PQCLEAN_SPHINCSSHAKE256FSIMPLE_AARCH64_crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, + const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +int PQCLEAN_SPHINCSSHAKE256FSIMPLE_AARCH64_crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +int PQCLEAN_SPHINCSSHAKE256FSIMPLE_AARCH64_crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/context.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/context.h new file mode 100644 index 0000000000..6e0a33f3b7 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/context.h @@ -0,0 +1,19 @@ +#ifndef SPX_CONTEXT_H +#define SPX_CONTEXT_H + +#include + +#include "params.h" + +typedef struct { + uint8_t pub_seed[SPX_N]; + uint8_t sk_seed[SPX_N]; +} spx_ctx; + +#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) +void initialize_hash_function(spx_ctx *ctx); + +#define free_hash_function SPX_NAMESPACE(free_hash_function) +void free_hash_function(spx_ctx *ctx); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/context_shake.c b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/context_shake.c new file mode 100644 index 0000000000..9614a103d3 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/context_shake.c @@ -0,0 +1,12 @@ +#include "context.h" + +/* For SHAKE256, there is no immediate reason to initialize at the start, + so this function is an empty operation. */ +void initialize_hash_function(spx_ctx *ctx) { + (void)ctx; /* Suppress an 'unused parameter' warning. */ +} + +// in case the hash function api is heap-based. +void free_hash_function(spx_ctx *ctx) { + (void)ctx; +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/f1600x2.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/f1600x2.h new file mode 100644 index 0000000000..70d1af9f14 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/f1600x2.h @@ -0,0 +1,11 @@ +#ifndef SPX_F1600X2_H +#define SPX_F1600X2_H + +#include + +extern uint64_t f1600_RC[24]; +extern void _f1600x2(uint64_t *a, uint64_t *rc); + +#define f1600x2(s) do {_f1600x2((s), f1600_RC);} while(0) + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/f1600x2.s b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/f1600x2.s new file mode 100644 index 0000000000..640ed791ed --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/f1600x2.s @@ -0,0 +1,143 @@ +# From https://github.com/bwesterb/armed-keccak + +.macro round + # Execute theta, but without xoring into the state yet. + # Compute parities p[i] = a[i] ^ a[5+i] ^ ... ^ a[20+i]. + eor3.16b v25, v0, v5, v10 + eor3.16b v26, v1, v6, v11 + eor3.16b v27, v2, v7, v12 + eor3.16b v28, v3, v8, v13 + eor3.16b v29, v4, v9, v14 + + eor3.16b v25, v25, v15, v20 + eor3.16b v26, v26, v16, v21 + eor3.16b v27, v27, v17, v22 + eor3.16b v28, v28, v18, v23 + eor3.16b v29, v29, v19, v24 + + # d[0] = rotl(p[1], 1) ^ p[4] + rax1.2d v30, v29, v26 + # d[3] = rotl(p[4], 1) ^ p[2] + rax1.2d v29, v27, v29 + # d[1] = rotl(p[2], 1) ^ p[0] + rax1.2d v27, v25, v27 + # d[4] = rotl(p[0], 1) ^ p[3] + rax1.2d v25, v28, v25 + # d[2] = rotl(p[3], 1) ^ p[1] + rax1.2d v28, v26, v28 + + # Xor parities from step theta into the state at the same time + # as executing rho and pi. + eor.16b v0, v0, v30 + mov.16b v31, v1 + xar.2d v1, v6, v27, 20 + xar.2d v6, v9, v25, 44 + xar.2d v9, v22, v28, 3 + xar.2d v22, v14, v25, 25 + xar.2d v14, v20, v30, 46 + xar.2d v20, v2, v28, 2 + xar.2d v2, v12, v28, 21 + xar.2d v12, v13, v29, 39 + xar.2d v13, v19, v25, 56 + xar.2d v19, v23, v29, 8 + xar.2d v23, v15, v30, 23 + xar.2d v15, v4, v25, 37 + xar.2d v4, v24, v25, 50 + xar.2d v24, v21, v27, 62 + xar.2d v21, v8, v29, 9 + xar.2d v8, v16, v27, 19 + xar.2d v16, v5, v30, 28 + xar.2d v5, v3, v29, 36 + xar.2d v3, v18, v29, 43 + xar.2d v18, v17, v28, 49 + xar.2d v17, v11, v27, 54 + xar.2d v11, v7, v28, 58 + xar.2d v7, v10, v30, 61 + xar.2d v10, v31, v27, 63 + + # Chi + bcax.16b v25, v0, v2, v1 + bcax.16b v26, v1, v3, v2 + bcax.16b v2, v2, v4, v3 + bcax.16b v3, v3, v0, v4 + bcax.16b v4, v4, v1, v0 + mov.16b v0, v25 + mov.16b v1, v26 + + bcax.16b v25, v5, v7, v6 + bcax.16b v26, v6, v8, v7 + bcax.16b v7, v7, v9, v8 + bcax.16b v8, v8, v5, v9 + bcax.16b v9, v9, v6, v5 + mov.16b v5, v25 + mov.16b v6, v26 + + bcax.16b v25, v10, v12, v11 + bcax.16b v26, v11, v13, v12 + bcax.16b v12, v12, v14, v13 + bcax.16b v13, v13, v10, v14 + bcax.16b v14, v14, v11, v10 + mov.16b v10, v25 + mov.16b v11, v26 + + bcax.16b v25, v15, v17, v16 + bcax.16b v26, v16, v18, v17 + bcax.16b v17, v17, v19, v18 + bcax.16b v18, v18, v15, v19 + bcax.16b v19, v19, v16, v15 + mov.16b v15, v25 + mov.16b v16, v26 + + bcax.16b v25, v20, v22, v21 + bcax.16b v26, v21, v23, v22 + bcax.16b v22, v22, v24, v23 + bcax.16b v23, v23, v20, v24 + bcax.16b v24, v24, v21, v20 + mov.16b v20, v25 + mov.16b v21, v26 + + # iota + ld1r {v25.2d}, [x1], #8 + eor.16b v0, v0, v25 +.endm + +.align 4 +.global __f1600x2 +__f1600x2: + stp d8, d9, [sp,#-16]! + stp d10, d11, [sp,#-16]! + stp d12, d13, [sp,#-16]! + stp d14, d15, [sp,#-16]! + + mov x2, x0 + mov x3, #24 + + ld1.2d {v0, v1, v2, v3}, [x0], #64 + ld1.2d {v4, v5, v6, v7}, [x0], #64 + ld1.2d {v8, v9, v10, v11}, [x0], #64 + ld1.2d {v12, v13, v14, v15}, [x0], #64 + ld1.2d {v16, v17, v18, v19}, [x0], #64 + ld1.2d {v20, v21, v22, v23}, [x0], #64 + ld1.2d {v24}, [x0] + +loop: + round + + subs x3, x3, #1 + cbnz x3, loop + + mov x0, x2 + st1.2d {v0, v1, v2, v3}, [x0], #64 + st1.2d {v4, v5, v6, v7}, [x0], #64 + st1.2d {v8, v9, v10, v11}, [x0], #64 + st1.2d {v12, v13, v14, v15}, [x0], #64 + st1.2d {v16, v17, v18, v19}, [x0], #64 + st1.2d {v20, v21, v22, v23}, [x0], #64 + st1.2d {v24}, [x0] + + ldp d14, d15, [sp], #16 + ldp d12, d13, [sp], #16 + ldp d10, d11, [sp], #16 + ldp d8, d9, [sp], #16 + + ret lr diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/f1600x2_const.c b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/f1600x2_const.c new file mode 100644 index 0000000000..e49c0ba149 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/f1600x2_const.c @@ -0,0 +1,30 @@ +#include "f1600x2.h" + +uint64_t f1600_RC[24] = { + 0x0000000000000001, + 0x0000000000008082, + 0x800000000000808A, + 0x8000000080008000, + 0x000000000000808B, + 0x0000000080000001, + 0x8000000080008081, + 0x8000000000008009, + 0x000000000000008A, + 0x0000000000000088, + 0x0000000080008009, + 0x000000008000000A, + 0x000000008000808B, + 0x800000000000008B, + 0x8000000000008089, + 0x8000000000008003, + 0x8000000000008002, + 0x8000000000000080, + 0x000000000000800A, + 0x800000008000000A, + 0x8000000080008081, + 0x8000000000008080, + 0x0000000080000001, + 0x8000000080008008, +}; + + diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/fips202x2.c b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/fips202x2.c new file mode 100644 index 0000000000..4718c343bc --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/fips202x2.c @@ -0,0 +1,148 @@ +#include +#include + +#include "fips202x2.h" +#include "f1600x2.h" +#include "fips202.h" + +uint64_t load64(const unsigned char *x) { + unsigned long long r = 0, i; + + for (i = 0; i < 8; ++i) { + r |= (unsigned long long)x[i] << 8 * i; + } + return r; +} + +void store64(uint8_t *x, uint64_t u) { + unsigned int i; + + for (i = 0; i < 8; ++i) { + x[i] = (uint8_t)u; + u >>= 8; + } +} + +static void keccak_absorb2x(uint64_t *s, + unsigned int r, + const unsigned char *m0, + const unsigned char *m1, + unsigned long long int mlen, + unsigned char p) { + unsigned long long i; + unsigned char t0[200]; + unsigned char t1[200]; + + while (mlen >= r) { + for (i = 0; i < r / 8; ++i) { + s[2 * i + 0] ^= load64(m0 + 8 * i); + s[2 * i + 1] ^= load64(m1 + 8 * i); + } + + f1600x2(s); + mlen -= r; + m0 += r; + m1 += r; + } + + for (i = 0; i < r; ++i) { + t0[i] = 0; + t1[i] = 0; + } + for (i = 0; i < mlen; ++i) { + t0[i] = m0[i]; + t1[i] = m1[i]; + } + + t0[i] = p; + t1[i] = p; + + t0[r - 1] |= 128; + t1[r - 1] |= 128; + + for (i = 0; i < r / 8; ++i) { + s[2 * i + 0] ^= load64(t0 + 8 * i); + s[2 * i + 1] ^= load64(t1 + 8 * i); + } +} + + +static void keccak_squeezeblocks2x(unsigned char *h0, + unsigned char *h1, + unsigned long long int nblocks, + uint64_t *s, + unsigned int r) { + unsigned int i; + + while (nblocks > 0) { + f1600x2(s); + for (i = 0; i < (r >> 3); i++) { + store64(h0 + 8 * i, s[2 * i + 0]); + store64(h1 + 8 * i, s[2 * i + 1]); + } + h0 += r; + h1 += r; + nblocks--; + } +} + + + +void shake128x2(unsigned char *out0, + unsigned char *out1, + unsigned long long outlen, + unsigned char *in0, + unsigned char *in1, + unsigned long long inlen) { + uint64_t s[50] = {0}; + unsigned char t0[SHAKE128_RATE]; + unsigned char t1[SHAKE128_RATE]; + unsigned int i; + + /* absorb 4 message of identical length in parallel */ + keccak_absorb2x(s, SHAKE128_RATE, in0, in1, inlen, 0x1F); + + /* Squeeze output */ + keccak_squeezeblocks2x(out0, out1, outlen / SHAKE128_RATE, s, SHAKE128_RATE); + + out0 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; + out1 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; + + if (outlen % SHAKE128_RATE) { + keccak_squeezeblocks2x(t0, t1, 1, s, SHAKE128_RATE); + for (i = 0; i < outlen % SHAKE128_RATE; i++) { + out0[i] = t0[i]; + out1[i] = t1[i]; + } + } +} + + +void shake256x2(unsigned char *out0, + unsigned char *out1, + unsigned long long outlen, + unsigned char *in0, + unsigned char *in1, + unsigned long long inlen) { + uint64_t s[50] = {0}; + unsigned char t0[SHAKE256_RATE]; + unsigned char t1[SHAKE256_RATE]; + unsigned int i; + + /* absorb 2 message of identical length in parallel */ + keccak_absorb2x(s, SHAKE256_RATE, in0, in1, inlen, 0x1F); + + /* Squeeze output */ + keccak_squeezeblocks2x(out0, out1, outlen / SHAKE256_RATE, s, SHAKE256_RATE); + + out0 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; + out1 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; + + if (outlen % SHAKE256_RATE) { + keccak_squeezeblocks2x(t0, t1, 1, s, SHAKE256_RATE); + for (i = 0; i < outlen % SHAKE256_RATE; i++) { + out0[i] = t0[i]; + out1[i] = t1[i]; + } + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/fips202x2.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/fips202x2.h new file mode 100644 index 0000000000..7ba58b35d8 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/fips202x2.h @@ -0,0 +1,24 @@ +#ifndef SPX_FIPS202X2_H +#define SPX_FIPS202X2_H + +#include + +uint64_t load64(const unsigned char *x); +void store64(uint8_t *x, uint64_t u); + + +void shake128x2(unsigned char *out0, + unsigned char *out1, + unsigned long long outlen, + unsigned char *in0, + unsigned char *in1, + unsigned long long inlen); + +void shake256x2(unsigned char *out0, + unsigned char *out1, + unsigned long long outlen, + unsigned char *in0, + unsigned char *in1, + unsigned long long inlen); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/fors.c b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/fors.c new file mode 100644 index 0000000000..39193d04e2 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/fors.c @@ -0,0 +1,191 @@ +#include +#include +#include + +#include "fors.h" + +#include "address.h" +#include "hash.h" +#include "hashx2.h" +#include "thash.h" +#include "thashx2.h" +#include "utils.h" +#include "utilsx2.h" + +static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + prf_addr(sk, ctx, fors_leaf_addr); +} + +static void fors_gen_skx2(unsigned char *sk0, + unsigned char *sk1, + const spx_ctx *ctx, + uint32_t fors_leaf_addrx2[2 * 8]) { + prf_addrx2(sk0, sk1, + ctx, fors_leaf_addrx2); +} + +static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, + const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + thash(leaf, sk, 1, ctx, fors_leaf_addr); +} + +static void fors_sk_to_leafx2(unsigned char *leaf0, + unsigned char *leaf1, + const unsigned char *sk0, + const unsigned char *sk1, + const spx_ctx *ctx, + uint32_t fors_leaf_addrx2[2 * 8]) { + thashx2(leaf0, leaf1, + sk0, sk1, + 1, ctx, fors_leaf_addrx2); +} + +struct fors_gen_leaf_info { + uint32_t leaf_addrx[2 * 8]; +}; + +static void fors_gen_leafx2(unsigned char *leaf, + const spx_ctx *ctx, + uint32_t addr_idx, void *info) { + struct fors_gen_leaf_info *fors_info = info; + uint32_t *fors_leaf_addrx2 = fors_info->leaf_addrx; + unsigned int j; + + /* Only set the parts that the caller doesn't set */ + for (j = 0; j < 2; j++) { + set_tree_index(fors_leaf_addrx2 + j * 8, addr_idx + j); + set_type(fors_leaf_addrx2 + j * 8, SPX_ADDR_TYPE_FORSPRF); + } + + fors_gen_skx2(leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + ctx, fors_leaf_addrx2); + + for (j = 0; j < 2; j++) { + set_type(fors_leaf_addrx2 + j * 8, SPX_ADDR_TYPE_FORSTREE); + } + + fors_sk_to_leafx2(leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + ctx, fors_leaf_addrx2); +} + +/** + * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + * Assumes indices has space for SPX_FORS_TREES integers. + */ +static void message_to_indices(uint32_t *indices, const unsigned char *m) { + unsigned int i, j; + unsigned int offset = 0; + + for (i = 0; i < SPX_FORS_TREES; i++) { + indices[i] = 0; + for (j = 0; j < SPX_FORS_HEIGHT; j++) { + indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); + offset++; + } + } +} + +/** + * Signs a message m, deriving the secret key from sk_seed and the FTS address. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + uint32_t fors_tree_addr[2 * 8] = {0}; + struct fors_gen_leaf_info fors_info = {0}; + uint32_t *fors_leaf_addr = fors_info.leaf_addrx; + uint32_t fors_pk_addr[8] = {0}; + uint32_t idx_offset; + unsigned int i; + + for (i = 0; i < 2; i++) { + copy_keypair_addr(fors_tree_addr + 8 * i, fors_addr); + set_type(fors_tree_addr + 8 * i, SPX_ADDR_TYPE_FORSTREE); + copy_keypair_addr(fors_leaf_addr + 8 * i, fors_addr); + } + copy_keypair_addr(fors_pk_addr, fors_addr); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); + + message_to_indices(indices, m); + + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); + + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + + /* Include the secret key part that produces the selected leaf node. */ + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); + fors_gen_sk(sig, ctx, fors_tree_addr); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + sig += SPX_N; + + /* Compute the authentication path for this leaf node. */ + treehashx2(roots + i * SPX_N, sig, ctx, + indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx2, + fors_tree_addr, &fors_info); + + sig += SPX_N * SPX_FORS_HEIGHT; + } + + /* Hash horizontally across all tree roots to derive the public key. */ + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); +} + +/** + * Derives the FORS public key from a signature. + * This can be used for verification by comparing to a known public key, or to + * subsequently verify a signature on the derived public key. The latter is the + * typical use-case when used as an FTS below an OTS in a hypertree. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + unsigned char leaf[SPX_N]; + uint32_t fors_tree_addr[8] = {0}; + uint32_t fors_pk_addr[8] = {0}; + uint32_t idx_offset; + unsigned int i; + + copy_keypair_addr(fors_tree_addr, fors_addr); + copy_keypair_addr(fors_pk_addr, fors_addr); + + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); + + message_to_indices(indices, m); + + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); + + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + + /* Derive the leaf from the included secret key part. */ + fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); + sig += SPX_N; + + /* Derive the corresponding root node of this tree. */ + compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, + sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); + sig += SPX_N * SPX_FORS_HEIGHT; + } + + /* Hash horizontally across all tree roots to derive the public key. */ + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/fors.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/fors.h new file mode 100644 index 0000000000..509140a178 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/fors.h @@ -0,0 +1,32 @@ +#ifndef SPX_FORS_H +#define SPX_FORS_H + +#include + +#include "context.h" +#include "params.h" + +/** + * Signs a message m, deriving the secret key from sk_seed and the FTS address. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +#define fors_sign SPX_NAMESPACE(fors_sign) +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); + +/** + * Derives the FORS public key from a signature. + * This can be used for verification by comparing to a known public key, or to + * subsequently verify a signature on the derived public key. The latter is the + * typical use-case when used as an FTS below an OTS in a hypertree. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/hash.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/hash.h new file mode 100644 index 0000000000..f7c87d4c3c --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/hash.h @@ -0,0 +1,28 @@ +#ifndef SPX_HASH_H +#define SPX_HASH_H + +#include +#include + +#include "context.h" +#include "params.h" + +#define prf_addr SPX_NAMESPACE(prf_addr) +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]); + +#define gen_message_random SPX_NAMESPACE(gen_message_random) +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); + +#define hash_message SPX_NAMESPACE(hash_message) +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); + + + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/hash_shake.c b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/hash_shake.c new file mode 100644 index 0000000000..ff5e7ec918 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/hash_shake.c @@ -0,0 +1,83 @@ +#include +#include + +#include "hash.h" + +#include "address.h" +#include "fips202.h" +#include "params.h" +#include "utils.h" + +/* + * Computes PRF(pk_seed, sk_seed, addr) + */ +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]) { + unsigned char buf[2 * SPX_N + SPX_ADDR_BYTES]; + + memcpy(buf, ctx->pub_seed, SPX_N); + memcpy(buf + SPX_N, addr, SPX_ADDR_BYTES); + memcpy(buf + SPX_N + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); + + shake256(out, SPX_N, buf, 2 * SPX_N + SPX_ADDR_BYTES); +} + +/** + * Computes the message-dependent randomness R, using a secret seed and an + * optional randomization value as well as the message. + */ +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { + (void)ctx; + shake256incctx s_inc; + + shake256_inc_init(&s_inc); + shake256_inc_absorb(&s_inc, sk_prf, SPX_N); + shake256_inc_absorb(&s_inc, optrand, SPX_N); + shake256_inc_absorb(&s_inc, m, mlen); + shake256_inc_finalize(&s_inc); + shake256_inc_squeeze(R, SPX_N, &s_inc); + shake256_inc_ctx_release(&s_inc); +} + +/** + * Computes the message hash using R, the public key, and the message. + * Outputs the message digest and the index of the leaf. The index is split in + * the tree index and the leaf index, for convenient copying to an address. + */ +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { + (void)ctx; +#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) +#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) +#define SPX_LEAF_BITS SPX_TREE_HEIGHT +#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) +#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) + + unsigned char buf[SPX_DGST_BYTES]; + unsigned char *bufp = buf; + shake256incctx s_inc; + + shake256_inc_init(&s_inc); + shake256_inc_absorb(&s_inc, R, SPX_N); + shake256_inc_absorb(&s_inc, pk, SPX_PK_BYTES); + shake256_inc_absorb(&s_inc, m, mlen); + shake256_inc_finalize(&s_inc); + shake256_inc_squeeze(buf, SPX_DGST_BYTES, &s_inc); + shake256_inc_ctx_release(&s_inc); + + memcpy(digest, bufp, SPX_FORS_MSG_BYTES); + bufp += SPX_FORS_MSG_BYTES; + + + *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); + *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); + bufp += SPX_TREE_BYTES; + + *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); + *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/hash_shakex2.c b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/hash_shakex2.c new file mode 100644 index 0000000000..99571916a2 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/hash_shakex2.c @@ -0,0 +1,52 @@ +#include +#include + +#include "hashx2.h" + +#include "address.h" +#include "f1600x2.h" +#include "fips202x2.h" +#include "params.h" + +/* + * 2-way parallel version of prf_addr; takes 2x as much input and output + */ +void prf_addrx2(unsigned char *out0, + unsigned char *out1, + const spx_ctx *ctx, + const uint32_t addrx2[2 * 8]) { + /* As we write and read only a few quadwords, it is more efficient to + * build and extract from the fourway SHAKE256 state by hand. */ + uint64_t state[50] = {0}; + + for (int i = 0; i < SPX_N / 8; i++) { + uint64_t x = load64(ctx->pub_seed + 8 * i); + state[2 * i] = x; + state[2 * i + 1] = x; + } + for (int i = 0; i < 4; i++) { + state[2 * (SPX_N / 8 + i)] = (((uint64_t)addrx2[1 + 2 * i]) << 32) + | (uint64_t)addrx2[2 * i]; + state[2 * (SPX_N / 8 + i) + 1] = (((uint64_t)addrx2[8 + 1 + 2 * i]) << 32) + | (uint64_t)addrx2[8 + 2 * i]; + } + for (int i = 0; i < SPX_N / 8; i++) { + uint64_t x = load64(ctx->sk_seed + 8 * i); + state[2 * (SPX_N / 8 + i + 4)] = x; + state[2 * (SPX_N / 8 + i + 4) + 1] = x; + } + + /* SHAKE domain separator and padding. */ + state[2 * (SPX_N / 4 + 4)] = 0x1f; + state[2 * (SPX_N / 4 + 4) + 1] = 0x1f; + + state[2 * 16] = 0x80ULL << 56; + state[2 * 16 + 1] = 0x80ULL << 56; + + f1600x2(state); + + for (int i = 0; i < SPX_N / 8; i++) { + store64(out0 + 8 * i, state[2 * i]); + store64(out1 + 8 * i, state[2 * i + 1]); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/hashx2.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/hashx2.h new file mode 100644 index 0000000000..99b8873a9b --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/hashx2.h @@ -0,0 +1,14 @@ +#ifndef SPX_HASHX2_H +#define SPX_HASHX2_H + +#include "context.h" +#include "params.h" +#include + +#define prf_addrx2 SPX_NAMESPACE(prf_addrx2) +void prf_addrx2(unsigned char *out0, + unsigned char *out1, + const spx_ctx *ctx, + const uint32_t addrx2[2 * 8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/merkle.c b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/merkle.c new file mode 100644 index 0000000000..c94ee23939 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/merkle.c @@ -0,0 +1,64 @@ +#include +#include + +#include "merkle.h" + +#include "address.h" +#include "params.h" +#include "utils.h" +#include "utilsx2.h" +#include "wots.h" +#include "wotsx2.h" + +/* + * This generates a Merkle signature (WOTS signature followed by the Merkle + * authentication path). + */ +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf) { + unsigned char *auth_path = sig + SPX_WOTS_BYTES; + uint32_t tree_addrx2[2 * 8] = { 0 }; + int j; + struct leaf_info_x2 info = { 0 }; + unsigned steps[ SPX_WOTS_LEN ]; + + info.wots_sig = sig; + chain_lengths(steps, root); + info.wots_steps = steps; + + for (j = 0; j < 2; j++) { + set_type(&tree_addrx2[8 * j], SPX_ADDR_TYPE_HASHTREE); + set_type(&info.leaf_addr[8 * j], SPX_ADDR_TYPE_WOTS); + set_type(&info.pk_addr[8 * j], SPX_ADDR_TYPE_WOTSPK); + copy_subtree_addr(&tree_addrx2[8 * j], tree_addr); + copy_subtree_addr(&info.leaf_addr[8 * j], wots_addr); + copy_subtree_addr(&info.pk_addr[8 * j], wots_addr); + } + + info.wots_sign_leaf = idx_leaf; + + treehashx2(root, auth_path, ctx, + idx_leaf, 0, + SPX_TREE_HEIGHT, + wots_gen_leafx2, + tree_addrx2, &info); +} + +/* Compute root node of the top-most subtree. */ +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { + /* We do not need the auth path in key generation, but it simplifies the + code to have just one treehash routine that computes both root and path + in one function. */ + unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; + uint32_t top_tree_addr[8] = {0}; + uint32_t wots_addr[8] = {0}; + + set_layer_addr(top_tree_addr, SPX_D - 1); + set_layer_addr(wots_addr, SPX_D - 1); + + merkle_sign(auth_path, root, ctx, + wots_addr, top_tree_addr, + ~0 /* ~0 means "don't bother generating an auth path */ ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/merkle.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/merkle.h new file mode 100644 index 0000000000..769cf2e970 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/merkle.h @@ -0,0 +1,21 @@ +#ifndef MERKLE_H_ +#define MERKLE_H_ + +#include + +#include "context.h" +#include "params.h" + +/* Generate a Merkle signature (WOTS signature followed by the Merkle */ +/* authentication path) */ +#define merkle_sign SPX_NAMESPACE(merkle_sign) +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf); + +/* Compute the root node of the top-most subtree. */ +#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); + +#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/nistapi.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/nistapi.h new file mode 100644 index 0000000000..3cb71afad4 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/nistapi.h @@ -0,0 +1,87 @@ +#ifndef SPX_API_H +#define SPX_API_H + +#include +#include + +#include "params.h" + +#define CRYPTO_ALGNAME "SPHINCS+" + +#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES +#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES +#define CRYPTO_BYTES SPX_BYTES +#define CRYPTO_SEEDBYTES (3*SPX_N) + +/* + * Returns the length of a secret key, in bytes + */ +#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) +size_t crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) +size_t crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) +size_t crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) +size_t crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +#define crypto_sign SPX_NAMESPACE(crypto_sign) +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/params.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/params.h new file mode 100644 index 0000000000..218f392dab --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/params.h @@ -0,0 +1,56 @@ +#ifndef SPX_PARAMS_H +#define SPX_PARAMS_H + +#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSSHAKE256FSIMPLE_AARCH64_##s + +/* Hash output length in bytes. */ +#define SPX_N 32 +/* Height of the hypertree. */ +#define SPX_FULL_HEIGHT 68 +/* Number of subtree layer. */ +#define SPX_D 17 +/* FORS tree dimensions. */ +#define SPX_FORS_HEIGHT 9 +#define SPX_FORS_TREES 35 +/* Winternitz parameter, */ +#define SPX_WOTS_W 16 + +/* The hash function is defined by linking a different hash.c file, as opposed + to setting a #define constant. */ + +/* For clarity */ +#define SPX_ADDR_BYTES 32 + +/* WOTS parameters. */ +#define SPX_WOTS_LOGW 4 + +#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) + +/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ +#define SPX_WOTS_LEN2 3 + +#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) +#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) +#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES + +/* Subtree size. */ +#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) + +//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT +// #error SPX_D should always divide SPX_FULL_HEIGHT +//#endif + +/* FORS parameters. */ +#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) +#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) +#define SPX_FORS_PK_BYTES SPX_N + +/* Resulting SPX sizes. */ +#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ + SPX_FULL_HEIGHT * SPX_N) +#define SPX_PK_BYTES (2 * SPX_N) +#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) + +#include "shake_offsets.h" + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/shake_offsets.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/shake_offsets.h new file mode 100644 index 0000000000..6b28d95d91 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/shake_offsets.h @@ -0,0 +1,21 @@ +#ifndef SHAKE_OFFSETS_H_ +#define SHAKE_OFFSETS_H_ + +/* + * Offsets of various fields in the address structure when we use SHAKE as + * the Sphincs+ hash function + */ + +#define SPX_OFFSET_LAYER 3 /* The byte used to specify the Merkle tree layer */ +#define SPX_OFFSET_TREE 8 /* The start of the 8 byte field used to specify the tree */ +#define SPX_OFFSET_TYPE 19 /* The byte used to specify the hash type (reason) */ +#define SPX_OFFSET_KP_ADDR2 22 /* The high byte used to specify the key pair (which one-time signature) */ +#define SPX_OFFSET_KP_ADDR1 23 /* The low byte used to specify the key pair */ +#define SPX_OFFSET_CHAIN_ADDR 27 /* The byte used to specify the chain address (which Winternitz chain) */ +#define SPX_OFFSET_HASH_ADDR 31 /* The byte used to specify the hash address (where in the Winternitz chain) */ +#define SPX_OFFSET_TREE_HGT 27 /* The byte used to specify the height of this node in the FORS or Merkle tree */ +#define SPX_OFFSET_TREE_INDEX 28 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ + +#define SPX_SHAKE 1 + +#endif /* SHAKE_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/sign.c b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/sign.c new file mode 100644 index 0000000000..9d0c7d1b22 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/sign.c @@ -0,0 +1,286 @@ +#include +#include +#include + +#include "address.h" +#include "context.h" +#include "fors.h" +#include "hash.h" +#include "merkle.h" +#include "nistapi.h" +#include "params.h" +#include "randombytes.h" +#include "thash.h" +#include "utils.h" +#include "wots.h" + +/* + * Returns the length of a secret key, in bytes + */ +size_t crypto_sign_secretkeybytes(void) { + return CRYPTO_SECRETKEYBYTES; +} + +/* + * Returns the length of a public key, in bytes + */ +size_t crypto_sign_publickeybytes(void) { + return CRYPTO_PUBLICKEYBYTES; +} + +/* + * Returns the length of a signature, in bytes + */ +size_t crypto_sign_bytes(void) { + return CRYPTO_BYTES; +} + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +size_t crypto_sign_seedbytes(void) { + return CRYPTO_SEEDBYTES; +} + +/* + * Generates an SPX key pair given a seed of length + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [PUB_SEED || root] + */ +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed) { + spx_ctx ctx; + + /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ + memcpy(sk, seed, CRYPTO_SEEDBYTES); + + memcpy(pk, sk + 2 * SPX_N, SPX_N); + + memcpy(ctx.pub_seed, pk, SPX_N); + memcpy(ctx.sk_seed, sk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + /* Compute root node of the top-most subtree. */ + merkle_gen_root(sk + 3 * SPX_N, &ctx); + + // cleanup + free_hash_function(&ctx); + + memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); + + return 0; +} + +/* + * Generates an SPX key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [PUB_SEED || root] + */ +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { + uint8_t seed[CRYPTO_SEEDBYTES]; + randombytes(seed, CRYPTO_SEEDBYTES); + crypto_sign_seed_keypair(pk, sk, seed); + + return 0; +} + +/** + * Returns an array containing a detached signature. + */ +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk) { + spx_ctx ctx; + + const uint8_t *sk_prf = sk + SPX_N; + const uint8_t *pk = sk + 2 * SPX_N; + + uint8_t optrand[SPX_N]; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t root[SPX_N]; + uint32_t i; + uint64_t tree; + uint32_t idx_leaf; + uint32_t wots_addr[8] = {0}; + uint32_t tree_addr[8] = {0}; + + memcpy(ctx.sk_seed, sk, SPX_N); + memcpy(ctx.pub_seed, pk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + + /* Optionally, signing can be made non-deterministic using optrand. + This can help counter side-channel attacks that would benefit from + getting a large number of traces when the signer uses the same nodes. */ + randombytes(optrand, SPX_N); + /* Compute the digest randomization value. */ + gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); + + /* Derive the message digest and leaf index from R, PK and M. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; + + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); + + /* Sign the message hash using FORS. */ + fors_sign(sig, root, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); + sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; + + /* Update the indices for the next layer. */ + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; + } + + free_hash_function(&ctx); + + *siglen = SPX_BYTES; + + return 0; +} + +/** + * Verifies a detached signature and message under a given public key. + */ +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk) { + spx_ctx ctx; + const uint8_t *pub_root = pk + SPX_N; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t wots_pk[SPX_WOTS_BYTES]; + uint8_t root[SPX_N]; + uint8_t leaf[SPX_N]; + unsigned int i; + uint64_t tree; + uint32_t idx_leaf; + uint32_t wots_addr[8] = {0}; + uint32_t tree_addr[8] = {0}; + uint32_t wots_pk_addr[8] = {0}; + + if (siglen != SPX_BYTES) { + return -1; + } + + memcpy(ctx.pub_seed, pk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); + + /* Derive the message digest and leaf index from R || PK || M. */ + /* The additional SPX_N is a result of the hash domain separator. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; + + /* Layer correctly defaults to 0, so no need to set_layer_addr */ + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); + + fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + /* For each subtree.. */ + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + copy_keypair_addr(wots_pk_addr, wots_addr); + + /* The WOTS public key is only correct if the signature was correct. */ + /* Initially, root is the FORS pk, but on subsequent iterations it is + the root of the subtree below the currently processed subtree. */ + wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); + sig += SPX_WOTS_BYTES; + + /* Compute the leaf node using the WOTS public key. */ + thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); + + /* Compute the root node of this subtree. */ + compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, + &ctx, tree_addr); + sig += SPX_TREE_HEIGHT * SPX_N; + + /* Update the indices for the next layer. */ + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; + } + + // cleanup + free_hash_function(&ctx); + + /* Check if the root node equals the root node in the public key. */ + if (memcmp(root, pub_root, SPX_N) != 0) { + return -1; + } + + return 0; +} + + +/** + * Returns an array containing the signature followed by the message. + */ +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk) { + size_t siglen; + + crypto_sign_signature(sm, &siglen, m, mlen, sk); + + memmove(sm + SPX_BYTES, m, mlen); + *smlen = siglen + mlen; + + return 0; +} + +/** + * Verifies a given signature-message pair under a given public key. + */ +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk) { + /* The API caller does not necessarily know what size a signature should be + but SPHINCS+ signatures are always exactly SPX_BYTES. */ + if (smlen < SPX_BYTES) { + memset(m, 0, smlen); + *mlen = 0; + return -1; + } + + *mlen = smlen - SPX_BYTES; + + if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { + memset(m, 0, smlen); + *mlen = 0; + return -1; + } + + /* If verification was successful, move the message to the right place. */ + memmove(m, sm + SPX_BYTES, *mlen); + + return 0; +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/thash.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/thash.h new file mode 100644 index 0000000000..8687ccfb4d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/thash.h @@ -0,0 +1,13 @@ +#ifndef SPX_THASH_H +#define SPX_THASH_H + +#include "context.h" +#include "params.h" + +#include + +#define thash SPX_NAMESPACE(thash) +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/thash_shake_simplex2.c b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/thash_shake_simplex2.c new file mode 100644 index 0000000000..892e453690 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/thash_shake_simplex2.c @@ -0,0 +1,83 @@ +#include +#include + +#include "thash.h" +#include "thashx2.h" + +#include "address.h" +#include "params.h" +#include "utils.h" + +#include "f1600x2.h" +#include "fips202x2.h" + + +void thash(unsigned char *out, + const unsigned char *in, + unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]) { + uint32_t addrx2 [2 * 8] = { + addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], addr[6], addr[7], + addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], addr[6], addr[7] + }; + thashx2(out, out, in, in, inblocks, ctx, addrx2); +} + +/** + * 2-way parallel version of thash; takes 2x as much input and output + */ +void thashx2(unsigned char *out0, + unsigned char *out1, + const unsigned char *in0, + const unsigned char *in1, + unsigned int inblocks, + const spx_ctx *ctx, uint32_t addrx2[2 * 8]) { + if (inblocks == 1 || inblocks == 2) { + /* As we write and read only a few quadwords, it is more efficient to + * build and extract from the twoway SHAKE256 state by hand. */ + uint64_t state[50] = {0}; + for (int i = 0; i < SPX_N / 8; i++) { + uint64_t x = load64(ctx->pub_seed + 8 * i); + state[2 * i] = x; + state[2 * i + 1] = x; + } + for (int i = 0; i < 4; i++) { + state[2 * (SPX_N / 8 + i)] = (((uint64_t)addrx2[1 + 2 * i]) << 32) + | (uint64_t)addrx2[2 * i]; + state[2 * (SPX_N / 8 + i) + 1] = (((uint64_t)addrx2[8 + 1 + 2 * i]) << 32) + | (uint64_t)addrx2[8 + 2 * i]; + } + + for (unsigned int i = 0; i < (SPX_N / 8) * inblocks; i++) { + state[2 * (SPX_N / 8 + 4 + i)] = load64(in0 + 8 * i); + state[2 * (SPX_N / 8 + 4 + i) + 1] = load64(in1 + 8 * i); + } + + /* Domain separator and padding. */ + state[2 * 16] = 0x80ULL << 56; + state[2 * 16 + 1] = 0x80ULL << 56; + + state[2 * ((SPX_N / 8) * (1 + inblocks) + 4)] ^= 0x1f; + state[2 * ((SPX_N / 8) * (1 + inblocks) + 4) + 1] ^= 0x1f; + + f1600x2(state); + + for (int i = 0; i < SPX_N / 8; i++) { + store64(out0 + 8 * i, state[2 * i]); + store64(out1 + 8 * i, state[2 * i + 1]); + } + } else { + PQCLEAN_VLA(unsigned char, buf0, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, buf1, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); + + memcpy(buf0, ctx->pub_seed, SPX_N); + memcpy(buf1, ctx->pub_seed, SPX_N); + memcpy(buf0 + SPX_N, addrx2 + 0 * 8, SPX_ADDR_BYTES); + memcpy(buf1 + SPX_N, addrx2 + 1 * 8, SPX_ADDR_BYTES); + memcpy(buf0 + SPX_N + SPX_ADDR_BYTES, in0, inblocks * SPX_N); + memcpy(buf1 + SPX_N + SPX_ADDR_BYTES, in1, inblocks * SPX_N); + + shake256x2(out0, out1, SPX_N, + buf0, buf1, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/thashx2.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/thashx2.h new file mode 100644 index 0000000000..040375e618 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/thashx2.h @@ -0,0 +1,16 @@ +#ifndef SPX_THASHX2_H +#define SPX_THASHX2_H + +#include "context.h" +#include "params.h" +#include + +#define thashx2 SPX_NAMESPACE(thashx2) +void thashx2(unsigned char *out0, + unsigned char *out1, + const unsigned char *in0, + const unsigned char *in1, + unsigned int inblocks, + const spx_ctx *ctx, uint32_t addrx2[2 * 8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/utils.c b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/utils.c new file mode 100644 index 0000000000..177b541fb9 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/utils.c @@ -0,0 +1,148 @@ +#include + +#include "utils.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "thash.h" + +/** + * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. + */ +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in) { + int i; + + /* Iterate over out in decreasing order, for big-endianness. */ + for (i = (signed int)outlen - 1; i >= 0; i--) { + out[i] = in & 0xff; + in = in >> 8; + } +} + +void u32_to_bytes(unsigned char *out, uint32_t in) { + out[0] = (unsigned char)(in >> 24); + out[1] = (unsigned char)(in >> 16); + out[2] = (unsigned char)(in >> 8); + out[3] = (unsigned char)in; +} + +/** + * Converts the inlen bytes in 'in' from big-endian byte order to an integer. + */ +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { + unsigned long long retval = 0; + unsigned int i; + + for (i = 0; i < inlen; i++) { + retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); + } + return retval; +} + +/** + * Computes a root node given a leaf and an auth path. + * Expects address to be complete other than the tree_height and tree_index. + */ +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]) { + uint32_t i; + unsigned char buffer[2 * SPX_N]; + + /* If leaf_idx is odd (last bit = 1), current path element is a right child + and auth_path has to go left. Otherwise it is the other way around. */ + if (leaf_idx & 1) { + memcpy(buffer + SPX_N, leaf, SPX_N); + memcpy(buffer, auth_path, SPX_N); + } else { + memcpy(buffer, leaf, SPX_N); + memcpy(buffer + SPX_N, auth_path, SPX_N); + } + auth_path += SPX_N; + + for (i = 0; i < tree_height - 1; i++) { + leaf_idx >>= 1; + idx_offset >>= 1; + /* Set the address of the node we're creating. */ + set_tree_height(addr, i + 1); + set_tree_index(addr, leaf_idx + idx_offset); + + /* Pick the right or left neighbor, depending on parity of the node. */ + if (leaf_idx & 1) { + thash(buffer + SPX_N, buffer, 2, ctx, addr); + memcpy(buffer, auth_path, SPX_N); + } else { + thash(buffer, buffer, 2, ctx, addr); + memcpy(buffer + SPX_N, auth_path, SPX_N); + } + auth_path += SPX_N; + } + + /* The last iteration is exceptional; we do not copy an auth_path node. */ + leaf_idx >>= 1; + idx_offset >>= 1; + set_tree_height(addr, tree_height); + set_tree_index(addr, leaf_idx + idx_offset); + thash(root, buffer, 2, ctx, addr); +} + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx * /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]) { + PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); + PQCLEAN_VLA(unsigned int, heights, tree_height + 1); + unsigned int offset = 0; + uint32_t idx; + uint32_t tree_idx; + + for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { + /* Add the next leaf node to the stack. */ + gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); + offset++; + heights[offset - 1] = 0; + + /* If this is a node we need for the auth path.. */ + if ((leaf_idx ^ 0x1) == idx) { + memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); + } + + /* While the top-most nodes are of equal height.. */ + while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { + /* Compute index of the new node, in the next layer. */ + tree_idx = (idx >> (heights[offset - 1] + 1)); + + /* Set the address of the node we're creating. */ + set_tree_height(tree_addr, heights[offset - 1] + 1); + set_tree_index(tree_addr, + tree_idx + (idx_offset >> (heights[offset - 1] + 1))); + /* Hash the top-most nodes from the stack together. */ + thash(stack + (offset - 2)*SPX_N, + stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); + offset--; + /* Note that the top-most node is now one layer higher. */ + heights[offset - 1]++; + + /* If this is a node we need for the auth path.. */ + if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { + memcpy(auth_path + heights[offset - 1]*SPX_N, + stack + (offset - 1)*SPX_N, SPX_N); + } + } + } + memcpy(root, stack, SPX_N); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/utils.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/utils.h new file mode 100644 index 0000000000..64f5d5a53a --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/utils.h @@ -0,0 +1,58 @@ +#ifndef SPX_UTILS_H +#define SPX_UTILS_H + +#include + +#include "compat.h" +#include "context.h" +#include "params.h" + + +/* To support MSVC use alloca() instead of VLAs. See #20. */ + + +/** + * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. + */ +#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in); +#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) +void u32_to_bytes(unsigned char *out, uint32_t in); + +/** + * Converts the inlen bytes in 'in' from big-endian byte order to an integer. + */ +#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); + +/** + * Computes a root node given a leaf and an auth path. + * Expects address to be complete other than the tree_height and tree_index. + */ +#define compute_root SPX_NAMESPACE(compute_root) +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]); + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +#define treehash SPX_NAMESPACE(treehash) +void treehash(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx *ctx /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]); + + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/utilsx2.c b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/utilsx2.c new file mode 100644 index 0000000000..8736474e4f --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/utilsx2.c @@ -0,0 +1,130 @@ +#include + +#include "utilsx2.h" + +#include "address.h" +#include "params.h" +#include "thashx2.h" +#include "utils.h" + +/* + * Generate the entire Merkle tree, computing the authentication path for leaf_idx, + * and the resulting root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) + * + * This expects tree_addrx2 to be initialized to 2 parallel addr structures for + * the Merkle tree nodes + * + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + * + * This works by using the standard Merkle tree building algorithm, except + * that each 'node' tracked is actually 2 consecutive nodes in the real tree. + * When we combine two logical nodes AB and WX, we perform the H + * operation on adjacent real nodes, forming the parent logical node + * (AB)(WX) + * + * When we get to the top level of the real tree (where there is only + * one logical node), we continue this operation one more time; the right + * most real node will by the actual root (and the other node will be + * garbage). We follow the same thashx2 logic so that the 'extract + * authentication path components' part of the loop is still executed (and + * to simplify the code somewhat) + */ +void treehashx2(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, + uint32_t tree_height, + void (*gen_leafx2)( + unsigned char * /* Where to write the leaves */, + const spx_ctx *, + uint32_t idx, void *info), + uint32_t tree_addrx2[2 * 8], + void *info) { + /* This is where we keep the intermediate nodes */ + unsigned char stackx2[tree_height * 2 * SPX_N]; + uint32_t left_adj = 0, prev_left_adj = 0; /* When we're doing the top */ + /* level, the left-most part of the tree isn't at the beginning */ + /* of current[]. These give the offset of the actual start */ + + uint32_t idx; + uint32_t max_idx = (1 << (tree_height - 1)) - 1; + for (idx = 0;; idx++) { + unsigned char current[2 * SPX_N]; /* Current logical node */ + gen_leafx2( current, ctx, 2 * idx + idx_offset, + info ); + + /* Now combine the freshly generated right node with previously */ + /* generated left ones */ + uint32_t internal_idx_offset = idx_offset; + uint32_t internal_idx = idx; + uint32_t internal_leaf = leaf_idx; + uint32_t h; /* The height we are in the Merkle tree */ + for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { + + /* Special processing if we're at the top of the tree */ + if (h >= tree_height - 1) { + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[1 * SPX_N], SPX_N ); + return; + } + /* The tree indexing logic is a bit off in this case */ + /* Adjust it so that the left-most node of the part of */ + /* the tree that we're processing has index 0 */ + prev_left_adj = left_adj; + left_adj = 2 - (1 << (tree_height - h - 1)); + } + + /* Check if we hit the top of the tree */ + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[1 * SPX_N], SPX_N ); + return; + } + + /* + * Check if one of the nodes we have is a part of the + * authentication path; if it is, write it out + */ + if ((((internal_idx << 1) ^ internal_leaf) & ~0x1) == 0) { + memcpy( &auth_path[ h * SPX_N ], + ¤t[(((internal_leaf & 1) ^ 1) + prev_left_adj) * SPX_N], + SPX_N ); + } + + /* + * Check if we're at a left child; if so, stop going up the stack + * Exception: if we've reached the end of the tree, keep on going + * (so we combine the last 2 nodes into the one root node in two + * more iterations) + */ + if ((internal_idx & 1) == 0 && idx < max_idx) { + break; + } + + /* Ok, we're at a right node (or doing the top 3 levels) */ + /* Now combine the left and right logical nodes together */ + + /* Set the address of the node we're creating. */ + int j; + internal_idx_offset >>= 1; + for (j = 0; j < 2; j++) { + set_tree_height(tree_addrx2 + j * 8, h + 1); + set_tree_index(tree_addrx2 + j * 8, + (2 / 2) * (internal_idx & ~1) + j - left_adj + internal_idx_offset ); + } + unsigned char *left = &stackx2[h * 2 * SPX_N]; + thashx2( ¤t[0 * SPX_N], + ¤t[1 * SPX_N], + &left [0 * SPX_N], + ¤t[0 * SPX_N], + 2, ctx, tree_addrx2); + } + + /* We've hit a left child; save the current for when we get the */ + /* corresponding right right */ + memcpy( &stackx2[h * 2 * SPX_N], current, 2 * SPX_N); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/utilsx2.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/utilsx2.h new file mode 100644 index 0000000000..e09faddc43 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/utilsx2.h @@ -0,0 +1,30 @@ +#ifndef SPX_UTILSX2_H +#define SPX_UTILSX2_H + +#include + +#include "context.h" +#include "params.h" + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + * + * This implementation uses SIMD to compute internal nodes 2 at a time (in + * parallel) + */ +#define treehashx2 SPX_NAMESPACE(treehashx2) +void treehashx2(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leafx2)( + unsigned char * /* Where to write the leaves */, + const spx_ctx * /* ctx */, + uint32_t addr_idx, void *info), + uint32_t tree_addrx2[2 * 8], void *info); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/wots.c b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/wots.c new file mode 100644 index 0000000000..3babe45e95 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/wots.c @@ -0,0 +1,259 @@ +#include +#include + +#include "wots.h" +#include "wotsx2.h" + +#include "address.h" +#include "hash.h" +#include "hashx2.h" +#include "params.h" +#include "thashx2.h" +#include "utils.h" +#include "utilsx2.h" + +// TODO clarify address expectations, and make them more uniform. +// TODO i.e. do we expect types to be set already? +// TODO and do we expect modifications or copies? + +/** + * Computes up the chains + */ +static void gen_chains( + unsigned char *out, + const unsigned char *in, + unsigned int start[SPX_WOTS_LEN], + const unsigned int steps[SPX_WOTS_LEN], + const spx_ctx *ctx, + uint32_t addr[8]) { + uint32_t i, j, k, idx, watching; + int done; + unsigned char empty[SPX_N]; + unsigned char *bufs[4]; + uint32_t addrs[8 * 2]; + + int l; + uint16_t counts[SPX_WOTS_W] = { 0 }; + uint16_t idxs[SPX_WOTS_LEN]; + uint16_t total, newTotal; + + /* set addrs = {addr, addr} */ + for (j = 0; j < 2; j++) { + memcpy(addrs + j * 8, addr, sizeof(uint32_t) * 8); + } + + /* Initialize out with the value at position 'start'. */ + memcpy(out, in, SPX_WOTS_LEN * SPX_N); + + /* Sort the chains in reverse order by steps using counting sort. */ + for (i = 0; i < SPX_WOTS_LEN; i++) { + counts[steps[i]]++; + } + total = 0; + for (l = SPX_WOTS_W - 1; l >= 0; l--) { + newTotal = counts[l] + total; + counts[l] = total; + total = newTotal; + } + for (i = 0; i < SPX_WOTS_LEN; i++) { + idxs[counts[steps[i]]] = i; + counts[steps[i]]++; + } + + /* We got our work cut out for us: do it! */ + for (i = 0; i < SPX_WOTS_LEN; i += 2) { + for (j = 0; j < 2 && i + j < SPX_WOTS_LEN; j++) { + idx = idxs[i + j]; + set_chain_addr(addrs + j * 8, idx); + bufs[j] = out + SPX_N * idx; + } + + /* As the chains are sorted in reverse order, we know that the first + * chain is the longest and the last one is the shortest. We keep + * an eye on whether the last chain is done and then on the one before, + * et cetera. */ + watching = 1; + done = 0; + while (i + watching >= SPX_WOTS_LEN) { + bufs[watching] = &empty[0]; + watching--; + } + + for (k = 0;; k++) { + while (k == steps[idxs[i + watching]]) { + bufs[watching] = &empty[0]; + if (watching == 0) { + done = 1; + break; + } + watching--; + } + if (done) { + break; + } + for (j = 0; j < watching + 1; j++) { + set_hash_addr(addrs + j * 8, k + start[idxs[i + j]]); + } + + thashx2(bufs[0], bufs[1], + bufs[0], bufs[1], 1, ctx, addrs); + } + } +} + +/** + * base_w algorithm as described in draft. + * Interprets an array of bytes as integers in base w. + * This only works when log_w is a divisor of 8. + */ +static void base_w(unsigned int *output, const int out_len, + const unsigned char *input) { + int in = 0; + int out = 0; + unsigned char total = 0; + int bits = 0; + int consumed; + + for (consumed = 0; consumed < out_len; consumed++) { + if (bits == 0) { + total = input[in]; + in++; + bits += 8; + } + bits -= SPX_WOTS_LOGW; + output[out] = (total >> bits) & (SPX_WOTS_W - 1); + out++; + } +} + +/* Computes the WOTS+ checksum over a message (in base_w). */ +static void wots_checksum(unsigned int *csum_base_w, + const unsigned int *msg_base_w) { + unsigned int csum = 0; + unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; + unsigned int i; + + /* Compute checksum. */ + for (i = 0; i < SPX_WOTS_LEN1; i++) { + csum += SPX_WOTS_W - 1 - msg_base_w[i]; + } + + /* Convert checksum to base_w. */ + /* Make sure expected empty zero bits are the least significant bits. */ + csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); + ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); + base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); +} + +/* Takes a message and derives the matching chain lengths. */ +void chain_lengths(unsigned int *lengths, const unsigned char *msg) { + base_w(lengths, SPX_WOTS_LEN1, msg); + wots_checksum(lengths + SPX_WOTS_LEN1, lengths); +} + +/** + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. + * + * Writes the computed public key to 'pk'. + */ +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]) { + unsigned int steps[SPX_WOTS_LEN]; + unsigned int start[SPX_WOTS_LEN]; + uint32_t i; + + chain_lengths(start, msg); + + for (i = 0; i < SPX_WOTS_LEN; i++) { + steps[i] = SPX_WOTS_W - 1 - start[i]; + } + + gen_chains(pk, sig, start, steps, ctx, addr); +} + +/* + * This generates 2 sequential WOTS public keys + * It also generates the WOTS signature if leaf_info indicates + * that we're signing with one of these WOTS keys + */ +void wots_gen_leafx2(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info) { + struct leaf_info_x2 *info = v_info; + uint32_t *leaf_addr = info->leaf_addr; + uint32_t *pk_addr = info->pk_addr; + unsigned int i, j, k; + unsigned char pk_buffer[ 2 * SPX_WOTS_BYTES ]; + unsigned wots_offset = SPX_WOTS_BYTES; + unsigned char *buffer; + uint32_t wots_k_mask; + unsigned wots_sign_index; + + if (((leaf_idx ^ info->wots_sign_leaf) & ~1) == 0) { + /* We're traversing the leaf that's signing; generate the WOTS */ + /* signature */ + wots_k_mask = 0; + wots_sign_index = info->wots_sign_leaf & 1; /* Which of of the 2 */ + /* slots do the signatures come from */ + } else { + /* Nope, we're just generating pk's; turn off the signature logic */ + wots_k_mask = ~0; + wots_sign_index = 0; + } + + for (j = 0; j < 2; j++) { + set_keypair_addr( leaf_addr + j * 8, leaf_idx + j ); + set_keypair_addr( pk_addr + j * 8, leaf_idx + j ); + } + + for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { + uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k to */ + /* the step if we're generating a signature, ~0 if we're not */ + + /* Start with the secret seed */ + for (j = 0; j < 2; j++) { + set_chain_addr(leaf_addr + j * 8, i); + set_hash_addr(leaf_addr + j * 8, 0); + set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTSPRF); + } + prf_addrx2(buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + ctx, leaf_addr); + for (j = 0; j < 2; j++) { + set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTS); + } + + /* Iterate down the WOTS chain */ + for (k = 0;; k++) { + /* Check if one of the values we have needs to be saved as a */ + /* part of the WOTS signature */ + if (k == wots_k) { + memcpy( info->wots_sig + i * SPX_N, + buffer + wots_sign_index * wots_offset, SPX_N ); + } + + /* Check if we hit the top of the chain */ + if (k == SPX_WOTS_W - 1) { + break; + } + + /* Iterate one step on all 4 chains */ + for (j = 0; j < 2; j++) { + set_hash_addr(leaf_addr + j * 8, k); + } + thashx2(buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + 1, ctx, leaf_addr); + } + } + + /* Do the final thash to generate the public keys */ + thashx2(dest + 0 * SPX_N, + dest + 1 * SPX_N, + pk_buffer + 0 * wots_offset, + pk_buffer + 1 * wots_offset, + SPX_WOTS_LEN, ctx, pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/wots.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/wots.h new file mode 100644 index 0000000000..4e7692eeef --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/wots.h @@ -0,0 +1,25 @@ +#ifndef SPX_WOTS_H +#define SPX_WOTS_H + +#include + +#include "context.h" +#include "params.h" + +/** + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. + * + * Writes the computed public key to 'pk'. + */ +#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]); + +/* + * Compute the chain lengths needed for a given message hash + */ +#define chain_lengths SPX_NAMESPACE(chain_lengths) +void chain_lengths(unsigned int *lengths, const unsigned char *msg); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/wotsx2.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/wotsx2.h new file mode 100644 index 0000000000..b58bb61f84 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_aarch64/wotsx2.h @@ -0,0 +1,40 @@ +#ifndef WOTSX2_H_ +#define WOTSX2_H_ + +#include "params.h" +#include + +/* + * This is here to provide an interface to the internal wots_gen_leafx2 + * routine. While this routine is not referenced in the package outside of + * wots.c, it is called from the stand-alone benchmark code to characterize + * the performance + */ +struct leaf_info_x2 { + unsigned char *wots_sig; + uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ + uint32_t *wots_steps; + uint32_t leaf_addr[2 * 8]; + uint32_t pk_addr[2 * 8]; +}; + +/* Macro to set the leaf_info to something 'benign', that is, it would */ +/* run with the same time as it does during the real signing process */ +/* Used only by the benchmark code */ +#define INITIALIZE_LEAF_INFO_X2(info, addr, step_buffer) { \ + (info).wots_sig = 0; \ + (info).wots_sign_leaf = ~0; \ + (info).wots_steps = step_buffer; \ + int i; \ + for (i=0; i<2; i++) { \ + memcpy( &(info).leaf_addr[8*i], addr, 32 ); \ + memcpy( &(info).pk_addr[8*i], addr, 32 ); \ + } \ + } + +#define wots_gen_leafx2 SPX_NAMESPACE(wots_gen_leafx2) +void wots_gen_leafx2(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info); + +#endif /* WOTSX2_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/LICENSE b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/LICENSE new file mode 100644 index 0000000000..670154e353 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/LICENSE @@ -0,0 +1,116 @@ +CC0 1.0 Universal + +Statement of Purpose + +The laws of most jurisdictions throughout the world automatically confer +exclusive Copyright and Related Rights (defined below) upon the creator and +subsequent owner(s) (each and all, an "owner") of an original work of +authorship and/or a database (each, a "Work"). + +Certain owners wish to permanently relinquish those rights to a Work for the +purpose of contributing to a commons of creative, cultural and scientific +works ("Commons") that the public can reliably and without fear of later +claims of infringement build upon, modify, incorporate in other works, reuse +and redistribute as freely as possible in any form whatsoever and for any +purposes, including without limitation commercial purposes. These owners may +contribute to the Commons to promote the ideal of a free culture and the +further production of creative, cultural and scientific works, or to gain +reputation or greater distribution for their Work in part through the use and +efforts of others. + +For these and/or other purposes and motivations, and without any expectation +of additional consideration or compensation, the person associating CC0 with a +Work (the "Affirmer"), to the extent that he or she is an owner of Copyright +and Related Rights in the Work, voluntarily elects to apply CC0 to the Work +and publicly distribute the Work under its terms, with knowledge of his or her +Copyright and Related Rights in the Work and the meaning and intended legal +effect of CC0 on those rights. + +1. Copyright and Related Rights. A Work made available under CC0 may be +protected by copyright and related or neighboring rights ("Copyright and +Related Rights"). Copyright and Related Rights include, but are not limited +to, the following: + + i. the right to reproduce, adapt, distribute, perform, display, communicate, + and translate a Work; + + ii. moral rights retained by the original author(s) and/or performer(s); + + iii. publicity and privacy rights pertaining to a person's image or likeness + depicted in a Work; + + iv. rights protecting against unfair competition in regards to a Work, + subject to the limitations in paragraph 4(a), below; + + v. rights protecting the extraction, dissemination, use and reuse of data in + a Work; + + vi. database rights (such as those arising under Directive 96/9/EC of the + European Parliament and of the Council of 11 March 1996 on the legal + protection of databases, and under any national implementation thereof, + including any amended or successor version of such directive); and + + vii. other similar, equivalent or corresponding rights throughout the world + based on applicable law or treaty, and any national implementations thereof. + +2. Waiver. To the greatest extent permitted by, but not in contravention of, +applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and +unconditionally waives, abandons, and surrenders all of Affirmer's Copyright +and Related Rights and associated claims and causes of action, whether now +known or unknown (including existing as well as future claims and causes of +action), in the Work (i) in all territories worldwide, (ii) for the maximum +duration provided by applicable law or treaty (including future time +extensions), (iii) in any current or future medium and for any number of +copies, and (iv) for any purpose whatsoever, including without limitation +commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes +the Waiver for the benefit of each member of the public at large and to the +detriment of Affirmer's heirs and successors, fully intending that such Waiver +shall not be subject to revocation, rescission, cancellation, termination, or +any other legal or equitable action to disrupt the quiet enjoyment of the Work +by the public as contemplated by Affirmer's express Statement of Purpose. + +3. Public License Fallback. Should any part of the Waiver for any reason be +judged legally invalid or ineffective under applicable law, then the Waiver +shall be preserved to the maximum extent permitted taking into account +Affirmer's express Statement of Purpose. In addition, to the extent the Waiver +is so judged Affirmer hereby grants to each affected person a royalty-free, +non transferable, non sublicensable, non exclusive, irrevocable and +unconditional license to exercise Affirmer's Copyright and Related Rights in +the Work (i) in all territories worldwide, (ii) for the maximum duration +provided by applicable law or treaty (including future time extensions), (iii) +in any current or future medium and for any number of copies, and (iv) for any +purpose whatsoever, including without limitation commercial, advertising or +promotional purposes (the "License"). The License shall be deemed effective as +of the date CC0 was applied by Affirmer to the Work. Should any part of the +License for any reason be judged legally invalid or ineffective under +applicable law, such partial invalidity or ineffectiveness shall not +invalidate the remainder of the License, and in such case Affirmer hereby +affirms that he or she will not (i) exercise any of his or her remaining +Copyright and Related Rights in the Work or (ii) assert any associated claims +and causes of action with respect to the Work, in either case contrary to +Affirmer's express Statement of Purpose. + +4. Limitations and Disclaimers. + + a. No trademark or patent rights held by Affirmer are waived, abandoned, + surrendered, licensed or otherwise affected by this document. + + b. Affirmer offers the Work as-is and makes no representations or warranties + of any kind concerning the Work, express, implied, statutory or otherwise, + including without limitation warranties of title, merchantability, fitness + for a particular purpose, non infringement, or the absence of latent or + other defects, accuracy, or the present or absence of errors, whether or not + discoverable, all to the greatest extent permissible under applicable law. + + c. Affirmer disclaims responsibility for clearing rights of other persons + that may apply to the Work or any use thereof, including without limitation + any person's Copyright and Related Rights in the Work. Further, Affirmer + disclaims responsibility for obtaining any necessary consents, permissions + or other rights required for any use of the Work. + + d. Affirmer understands and acknowledges that Creative Commons is not a + party to this document and has no duty or obligation with respect to this + CC0 or use of the Work. + +For more information, please see + diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/address.c b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/address.c new file mode 100644 index 0000000000..b956e9cb29 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/address.c @@ -0,0 +1,91 @@ +#include +#include + +#include "address.h" +#include "params.h" +#include "utils.h" + +/* + * Specify which level of Merkle tree (the "layer") we're working on + */ +void set_layer_addr(uint32_t addr[8], uint32_t layer) { + ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; +} + +/* + * Specify which Merkle tree within the level (the "tree address") we're working on + */ +void set_tree_addr(uint32_t addr[8], uint64_t tree) { + ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); +} + +/* + * Specify the reason we'll use this address structure for, that is, what + * hash will we compute with it. This is used so that unrelated types of + * hashes don't accidentally get the same address structure. The type will be + * one of the SPX_ADDR_TYPE constants + */ +void set_type(uint32_t addr[8], uint32_t type) { + ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; +} + +/* + * Copy the layer and tree fields of the address structure. This is used + * when we're doing multiple types of hashes within the same Merkle tree + */ +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); +} + +/* These functions are used for OTS addresses. */ + +/* + * Specify which Merkle leaf we're working on; that is, which OTS keypair + * we're talking about. + */ +void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { + ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; +} + +/* + * Copy the layer, tree and keypair fields of the address structure. This is + * used when we're doing multiple things within the same OTS keypair + */ +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); + ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; +} + +/* + * Specify which Merkle chain within the OTS we're working with + * (the chain address) + */ +void set_chain_addr(uint32_t addr[8], uint32_t chain) { + ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; +} + +/* + * Specify where in the Merkle chain we are +* (the hash address) + */ +void set_hash_addr(uint32_t addr[8], uint32_t hash) { + ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; +} + +/* These functions are used for all hash tree addresses (including FORS). */ + +/* + * Specify the height of the node in the Merkle/FORS tree we are in + * (the tree height) + */ +void set_tree_height(uint32_t addr[8], uint32_t tree_height) { + ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; +} + +/* + * Specify the distance from the left edge of the node in the Merkle/FORS tree + * (the tree index) + */ +void set_tree_index(uint32_t addr[8], uint32_t tree_index) { + u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/address.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/address.h new file mode 100644 index 0000000000..24a84eb40c --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/address.h @@ -0,0 +1,52 @@ +#ifndef SPX_ADDRESS_H +#define SPX_ADDRESS_H + +#include + +#include "params.h" + +/* The hash types that are passed to set_type */ +#define SPX_ADDR_TYPE_WOTS 0 +#define SPX_ADDR_TYPE_WOTSPK 1 +#define SPX_ADDR_TYPE_HASHTREE 2 +#define SPX_ADDR_TYPE_FORSTREE 3 +#define SPX_ADDR_TYPE_FORSPK 4 +#define SPX_ADDR_TYPE_WOTSPRF 5 +#define SPX_ADDR_TYPE_FORSPRF 6 + +#define set_layer_addr SPX_NAMESPACE(set_layer_addr) +void set_layer_addr(uint32_t addr[8], uint32_t layer); + +#define set_tree_addr SPX_NAMESPACE(set_tree_addr) +void set_tree_addr(uint32_t addr[8], uint64_t tree); + +#define set_type SPX_NAMESPACE(set_type) +void set_type(uint32_t addr[8], uint32_t type); + +/* Copies the layer and tree part of one address into the other */ +#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); + +/* These functions are used for WOTS and FORS addresses. */ + +#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) +void set_keypair_addr(uint32_t addr[8], uint32_t keypair); + +#define set_chain_addr SPX_NAMESPACE(set_chain_addr) +void set_chain_addr(uint32_t addr[8], uint32_t chain); + +#define set_hash_addr SPX_NAMESPACE(set_hash_addr) +void set_hash_addr(uint32_t addr[8], uint32_t hash); + +#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); + +/* These functions are used for all hash tree addresses (including FORS). */ + +#define set_tree_height SPX_NAMESPACE(set_tree_height) +void set_tree_height(uint32_t addr[8], uint32_t tree_height); + +#define set_tree_index SPX_NAMESPACE(set_tree_index) +void set_tree_index(uint32_t addr[8], uint32_t tree_index); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/api.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/api.h new file mode 100644 index 0000000000..a39c944ded --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/api.h @@ -0,0 +1,77 @@ +#ifndef PQCLEAN_SPHINCSSHAKE256FSIMPLE_AVX2_API_H +#define PQCLEAN_SPHINCSSHAKE256FSIMPLE_AVX2_API_H + +#include +#include + +#define PQCLEAN_SPHINCSSHAKE256FSIMPLE_AVX2_CRYPTO_ALGNAME "SPHINCS+-shake-256f-simple" + +#define PQCLEAN_SPHINCSSHAKE256FSIMPLE_AVX2_CRYPTO_SECRETKEYBYTES 128 +#define PQCLEAN_SPHINCSSHAKE256FSIMPLE_AVX2_CRYPTO_PUBLICKEYBYTES 64 +#define PQCLEAN_SPHINCSSHAKE256FSIMPLE_AVX2_CRYPTO_BYTES 49856 + +#define PQCLEAN_SPHINCSSHAKE256FSIMPLE_AVX2_CRYPTO_SEEDBYTES 96 + +/* + * Returns the length of a secret key, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE256FSIMPLE_AVX2_crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE256FSIMPLE_AVX2_crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE256FSIMPLE_AVX2_crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE256FSIMPLE_AVX2_crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +int PQCLEAN_SPHINCSSHAKE256FSIMPLE_AVX2_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +int PQCLEAN_SPHINCSSHAKE256FSIMPLE_AVX2_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +int PQCLEAN_SPHINCSSHAKE256FSIMPLE_AVX2_crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +int PQCLEAN_SPHINCSSHAKE256FSIMPLE_AVX2_crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, + const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +int PQCLEAN_SPHINCSSHAKE256FSIMPLE_AVX2_crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +int PQCLEAN_SPHINCSSHAKE256FSIMPLE_AVX2_crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/context.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/context.h new file mode 100644 index 0000000000..6e0a33f3b7 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/context.h @@ -0,0 +1,19 @@ +#ifndef SPX_CONTEXT_H +#define SPX_CONTEXT_H + +#include + +#include "params.h" + +typedef struct { + uint8_t pub_seed[SPX_N]; + uint8_t sk_seed[SPX_N]; +} spx_ctx; + +#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) +void initialize_hash_function(spx_ctx *ctx); + +#define free_hash_function SPX_NAMESPACE(free_hash_function) +void free_hash_function(spx_ctx *ctx); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/context_shake.c b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/context_shake.c new file mode 100644 index 0000000000..9614a103d3 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/context_shake.c @@ -0,0 +1,12 @@ +#include "context.h" + +/* For SHAKE256, there is no immediate reason to initialize at the start, + so this function is an empty operation. */ +void initialize_hash_function(spx_ctx *ctx) { + (void)ctx; /* Suppress an 'unused parameter' warning. */ +} + +// in case the hash function api is heap-based. +void free_hash_function(spx_ctx *ctx) { + (void)ctx; +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/fips202x4.c b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/fips202x4.c new file mode 100644 index 0000000000..1e06fef186 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/fips202x4.c @@ -0,0 +1,210 @@ +#include +#include +#include + +#include "fips202.h" +#include "fips202x4.h" + +#define NROUNDS 24 +#define ROL(a, offset) (((a) << (offset)) ^ ((a) >> (64-(offset)))) + +static uint64_t load64(const unsigned char *x) { + unsigned long long r = 0, i; + + for (i = 0; i < 8; ++i) { + r |= (unsigned long long)x[i] << 8 * i; + } + return r; +} + +static void store64(uint8_t *x, uint64_t u) { + unsigned int i; + + for (i = 0; i < 8; ++i) { + x[i] = (uint8_t)u; + u >>= 8; + } +} + +/* Use implementation from the Keccak Code Package */ +extern void KeccakP1600times4_PermuteAll_24rounds(__m256i *s); +#define KeccakF1600_StatePermute4x KeccakP1600times4_PermuteAll_24rounds + +static void keccak_absorb4x(__m256i *s, + unsigned int r, + const unsigned char *m0, + const unsigned char *m1, + const unsigned char *m2, + const unsigned char *m3, + unsigned long long int mlen, + unsigned char p) { + unsigned long long i; + unsigned char t0[200]; + unsigned char t1[200]; + unsigned char t2[200]; + unsigned char t3[200]; + + unsigned long long *ss = (unsigned long long *)s; + + + while (mlen >= r) { + for (i = 0; i < r / 8; ++i) { + ss[4 * i + 0] ^= load64(m0 + 8 * i); + ss[4 * i + 1] ^= load64(m1 + 8 * i); + ss[4 * i + 2] ^= load64(m2 + 8 * i); + ss[4 * i + 3] ^= load64(m3 + 8 * i); + } + + KeccakF1600_StatePermute4x(s); + mlen -= r; + m0 += r; + m1 += r; + m2 += r; + m3 += r; + } + + for (i = 0; i < r; ++i) { + t0[i] = 0; + t1[i] = 0; + t2[i] = 0; + t3[i] = 0; + } + for (i = 0; i < mlen; ++i) { + t0[i] = m0[i]; + t1[i] = m1[i]; + t2[i] = m2[i]; + t3[i] = m3[i]; + } + + t0[i] = p; + t1[i] = p; + t2[i] = p; + t3[i] = p; + + t0[r - 1] |= 128; + t1[r - 1] |= 128; + t2[r - 1] |= 128; + t3[r - 1] |= 128; + + for (i = 0; i < r / 8; ++i) { + ss[4 * i + 0] ^= load64(t0 + 8 * i); + ss[4 * i + 1] ^= load64(t1 + 8 * i); + ss[4 * i + 2] ^= load64(t2 + 8 * i); + ss[4 * i + 3] ^= load64(t3 + 8 * i); + } +} + + +static void keccak_squeezeblocks4x(unsigned char *h0, + unsigned char *h1, + unsigned char *h2, + unsigned char *h3, + unsigned long long int nblocks, + __m256i *s, + unsigned int r) { + unsigned int i; + + unsigned long long *ss = (unsigned long long *)s; + + while (nblocks > 0) { + KeccakF1600_StatePermute4x(s); + for (i = 0; i < (r >> 3); i++) { + store64(h0 + 8 * i, ss[4 * i + 0]); + store64(h1 + 8 * i, ss[4 * i + 1]); + store64(h2 + 8 * i, ss[4 * i + 2]); + store64(h3 + 8 * i, ss[4 * i + 3]); + } + h0 += r; + h1 += r; + h2 += r; + h3 += r; + nblocks--; + } +} + + + +void shake128x4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, unsigned long long outlen, + unsigned char *in0, + unsigned char *in1, + unsigned char *in2, + unsigned char *in3, unsigned long long inlen) { + __m256i s[25]; + unsigned char t0[SHAKE128_RATE]; + unsigned char t1[SHAKE128_RATE]; + unsigned char t2[SHAKE128_RATE]; + unsigned char t3[SHAKE128_RATE]; + unsigned int i; + + /* zero state */ + for (i = 0; i < 25; i++) { + s[i] = _mm256_xor_si256(s[i], s[i]); + } + + /* absorb 4 message of identical length in parallel */ + keccak_absorb4x(s, SHAKE128_RATE, in0, in1, in2, in3, inlen, 0x1F); + + /* Squeeze output */ + keccak_squeezeblocks4x(out0, out1, out2, out3, outlen / SHAKE128_RATE, s, SHAKE128_RATE); + + out0 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; + out1 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; + out2 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; + out3 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; + + if (outlen % SHAKE128_RATE) { + keccak_squeezeblocks4x(t0, t1, t2, t3, 1, s, SHAKE128_RATE); + for (i = 0; i < outlen % SHAKE128_RATE; i++) { + out0[i] = t0[i]; + out1[i] = t1[i]; + out2[i] = t2[i]; + out3[i] = t3[i]; + } + } +} + + +void shake256x4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, unsigned long long outlen, + unsigned char *in0, + unsigned char *in1, + unsigned char *in2, + unsigned char *in3, unsigned long long inlen) { + __m256i s[25]; + unsigned char t0[SHAKE256_RATE]; + unsigned char t1[SHAKE256_RATE]; + unsigned char t2[SHAKE256_RATE]; + unsigned char t3[SHAKE256_RATE]; + unsigned int i; + + /* zero state */ + for (i = 0; i < 25; i++) { + s[i] = _mm256_xor_si256(s[i], s[i]); + } + + /* absorb 4 message of identical length in parallel */ + keccak_absorb4x(s, SHAKE256_RATE, in0, in1, in2, in3, inlen, 0x1F); + + /* Squeeze output */ + keccak_squeezeblocks4x(out0, out1, out2, out3, outlen / SHAKE256_RATE, s, SHAKE256_RATE); + + out0 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; + out1 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; + out2 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; + out3 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; + + if (outlen % SHAKE256_RATE) { + keccak_squeezeblocks4x(t0, t1, t2, t3, 1, s, SHAKE256_RATE); + for (i = 0; i < outlen % SHAKE256_RATE; i++) { + out0[i] = t0[i]; + out1[i] = t1[i]; + out2[i] = t2[i]; + out3[i] = t3[i]; + } + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/fips202x4.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/fips202x4.h new file mode 100644 index 0000000000..2b93c9cd0d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/fips202x4.h @@ -0,0 +1,28 @@ +#ifndef SPX_FIPS202X4_H +#define SPX_FIPS202X4_H + +#include + +#include "params.h" + +#define shake128x4 SPX_NAMESPACE(shake128x4) +void shake128x4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, unsigned long long outlen, + unsigned char *in0, + unsigned char *in1, + unsigned char *in2, + unsigned char *in3, unsigned long long inlen); + +#define shake256x4 SPX_NAMESPACE(shake256x4) +void shake256x4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, unsigned long long outlen, + unsigned char *in0, + unsigned char *in1, + unsigned char *in2, + unsigned char *in3, unsigned long long inlen); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/fors.c b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/fors.c new file mode 100644 index 0000000000..f1b0639cfc --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/fors.c @@ -0,0 +1,202 @@ +#include +#include +#include + +#include "fors.h" + +#include "address.h" +#include "hash.h" +#include "hashx4.h" +#include "thash.h" +#include "thashx4.h" +#include "utils.h" +#include "utilsx4.h" + +static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + prf_addr(sk, ctx, fors_leaf_addr); +} + +static void fors_gen_skx4(unsigned char *sk0, + unsigned char *sk1, + unsigned char *sk2, + unsigned char *sk3, const spx_ctx *ctx, + uint32_t fors_leaf_addrx4[4 * 8]) { + prf_addrx4(sk0, sk1, sk2, sk3, + ctx, fors_leaf_addrx4); +} + +static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, + const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + thash(leaf, sk, 1, ctx, fors_leaf_addr); +} + +static void fors_sk_to_leafx4(unsigned char *leaf0, + unsigned char *leaf1, + unsigned char *leaf2, + unsigned char *leaf3, + const unsigned char *sk0, + const unsigned char *sk1, + const unsigned char *sk2, + const unsigned char *sk3, + const spx_ctx *ctx, + uint32_t fors_leaf_addrx4[4 * 8]) { + thashx4(leaf0, leaf1, leaf2, leaf3, + sk0, sk1, sk2, sk3, + 1, ctx, fors_leaf_addrx4); +} + +struct fors_gen_leaf_info { + uint32_t leaf_addrx[4 * 8]; +}; + +static void fors_gen_leafx4(unsigned char *leaf, + const spx_ctx *ctx, + uint32_t addr_idx, void *info) { + struct fors_gen_leaf_info *fors_info = info; + uint32_t *fors_leaf_addrx4 = fors_info->leaf_addrx; + unsigned int j; + + /* Only set the parts that the caller doesn't set */ + for (j = 0; j < 4; j++) { + set_tree_index(fors_leaf_addrx4 + j * 8, addr_idx + j); + set_type(fors_leaf_addrx4 + j * 8, SPX_ADDR_TYPE_FORSPRF); + } + + fors_gen_skx4(leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + leaf + 2 * SPX_N, + leaf + 3 * SPX_N, + ctx, fors_leaf_addrx4); + + for (j = 0; j < 4; j++) { + set_type(fors_leaf_addrx4 + j * 8, SPX_ADDR_TYPE_FORSTREE); + } + + fors_sk_to_leafx4(leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + leaf + 2 * SPX_N, + leaf + 3 * SPX_N, + leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + leaf + 2 * SPX_N, + leaf + 3 * SPX_N, + ctx, fors_leaf_addrx4); +} + +/** + * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + * Assumes indices has space for SPX_FORS_TREES integers. + */ +static void message_to_indices(uint32_t *indices, const unsigned char *m) { + unsigned int i, j; + unsigned int offset = 0; + + for (i = 0; i < SPX_FORS_TREES; i++) { + indices[i] = 0; + for (j = 0; j < SPX_FORS_HEIGHT; j++) { + indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); + offset++; + } + } +} + +/** + * Signs a message m, deriving the secret key from sk_seed and the FTS address. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + uint32_t fors_tree_addr[4 * 8] = {0}; + struct fors_gen_leaf_info fors_info = {0}; + uint32_t *fors_leaf_addr = fors_info.leaf_addrx; + uint32_t fors_pk_addr[8] = {0}; + uint32_t idx_offset; + unsigned int i; + + for (i = 0; i < 4; i++) { + copy_keypair_addr(fors_tree_addr + 8 * i, fors_addr); + set_type(fors_tree_addr + 8 * i, SPX_ADDR_TYPE_FORSTREE); + copy_keypair_addr(fors_leaf_addr + 8 * i, fors_addr); + } + copy_keypair_addr(fors_pk_addr, fors_addr); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); + + message_to_indices(indices, m); + + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); + + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + + /* Include the secret key part that produces the selected leaf node. */ + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); + fors_gen_sk(sig, ctx, fors_tree_addr); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + sig += SPX_N; + + /* Compute the authentication path for this leaf node. */ + treehashx4(roots + i * SPX_N, sig, ctx, + indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx4, + fors_tree_addr, &fors_info); + + sig += SPX_N * SPX_FORS_HEIGHT; + } + + /* Hash horizontally across all tree roots to derive the public key. */ + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); +} + +/** + * Derives the FORS public key from a signature. + * This can be used for verification by comparing to a known public key, or to + * subsequently verify a signature on the derived public key. The latter is the + * typical use-case when used as an FTS below an OTS in a hypertree. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + unsigned char leaf[SPX_N]; + uint32_t fors_tree_addr[8] = {0}; + uint32_t fors_pk_addr[8] = {0}; + uint32_t idx_offset; + unsigned int i; + + copy_keypair_addr(fors_tree_addr, fors_addr); + copy_keypair_addr(fors_pk_addr, fors_addr); + + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); + + message_to_indices(indices, m); + + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); + + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + + /* Derive the leaf from the included secret key part. */ + fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); + sig += SPX_N; + + /* Derive the corresponding root node of this tree. */ + compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, + sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); + sig += SPX_N * SPX_FORS_HEIGHT; + } + + /* Hash horizontally across all tree roots to derive the public key. */ + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/fors.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/fors.h new file mode 100644 index 0000000000..509140a178 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/fors.h @@ -0,0 +1,32 @@ +#ifndef SPX_FORS_H +#define SPX_FORS_H + +#include + +#include "context.h" +#include "params.h" + +/** + * Signs a message m, deriving the secret key from sk_seed and the FTS address. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +#define fors_sign SPX_NAMESPACE(fors_sign) +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); + +/** + * Derives the FORS public key from a signature. + * This can be used for verification by comparing to a known public key, or to + * subsequently verify a signature on the derived public key. The latter is the + * typical use-case when used as an FTS below an OTS in a hypertree. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/hash.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/hash.h new file mode 100644 index 0000000000..f7c87d4c3c --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/hash.h @@ -0,0 +1,28 @@ +#ifndef SPX_HASH_H +#define SPX_HASH_H + +#include +#include + +#include "context.h" +#include "params.h" + +#define prf_addr SPX_NAMESPACE(prf_addr) +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]); + +#define gen_message_random SPX_NAMESPACE(gen_message_random) +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); + +#define hash_message SPX_NAMESPACE(hash_message) +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); + + + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/hash_shake.c b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/hash_shake.c new file mode 100644 index 0000000000..ff5e7ec918 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/hash_shake.c @@ -0,0 +1,83 @@ +#include +#include + +#include "hash.h" + +#include "address.h" +#include "fips202.h" +#include "params.h" +#include "utils.h" + +/* + * Computes PRF(pk_seed, sk_seed, addr) + */ +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]) { + unsigned char buf[2 * SPX_N + SPX_ADDR_BYTES]; + + memcpy(buf, ctx->pub_seed, SPX_N); + memcpy(buf + SPX_N, addr, SPX_ADDR_BYTES); + memcpy(buf + SPX_N + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); + + shake256(out, SPX_N, buf, 2 * SPX_N + SPX_ADDR_BYTES); +} + +/** + * Computes the message-dependent randomness R, using a secret seed and an + * optional randomization value as well as the message. + */ +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { + (void)ctx; + shake256incctx s_inc; + + shake256_inc_init(&s_inc); + shake256_inc_absorb(&s_inc, sk_prf, SPX_N); + shake256_inc_absorb(&s_inc, optrand, SPX_N); + shake256_inc_absorb(&s_inc, m, mlen); + shake256_inc_finalize(&s_inc); + shake256_inc_squeeze(R, SPX_N, &s_inc); + shake256_inc_ctx_release(&s_inc); +} + +/** + * Computes the message hash using R, the public key, and the message. + * Outputs the message digest and the index of the leaf. The index is split in + * the tree index and the leaf index, for convenient copying to an address. + */ +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { + (void)ctx; +#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) +#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) +#define SPX_LEAF_BITS SPX_TREE_HEIGHT +#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) +#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) + + unsigned char buf[SPX_DGST_BYTES]; + unsigned char *bufp = buf; + shake256incctx s_inc; + + shake256_inc_init(&s_inc); + shake256_inc_absorb(&s_inc, R, SPX_N); + shake256_inc_absorb(&s_inc, pk, SPX_PK_BYTES); + shake256_inc_absorb(&s_inc, m, mlen); + shake256_inc_finalize(&s_inc); + shake256_inc_squeeze(buf, SPX_DGST_BYTES, &s_inc); + shake256_inc_ctx_release(&s_inc); + + memcpy(digest, bufp, SPX_FORS_MSG_BYTES); + bufp += SPX_FORS_MSG_BYTES; + + + *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); + *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); + bufp += SPX_TREE_BYTES; + + *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); + *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/hash_shakex4.c b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/hash_shakex4.c new file mode 100644 index 0000000000..bbd22eb117 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/hash_shakex4.c @@ -0,0 +1,64 @@ +#include +#include + +#include "hashx4.h" + +#include "address.h" +#include "fips202x4.h" +#include "params.h" + +extern void KeccakP1600times4_PermuteAll_24rounds(__m256i *s); + +/* + * 4-way parallel version of prf_addr; takes 4x as much input and output + */ +void prf_addrx4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const spx_ctx *ctx, + const uint32_t addrx4[4 * 8]) { + /* As we write and read only a few quadwords, it is more efficient to + * build and extract from the fourway SHAKE256 state by hand. */ + __m256i state[25]; + + for (int i = 0; i < SPX_N / 8; i++) { + state[i] = _mm256_set1_epi64x(((int64_t *)ctx->pub_seed)[i]); + } + for (int i = 0; i < 4; i++) { + state[SPX_N / 8 + i] = _mm256_set_epi32( + (int)addrx4[3 * 8 + 1 + 2 * i], + (int)addrx4[3 * 8 + 2 * i], + (int)addrx4[2 * 8 + 1 + 2 * i], + (int)addrx4[2 * 8 + 2 * i], + (int)addrx4[8 + 1 + 2 * i], + (int)addrx4[8 + 2 * i], + (int)addrx4[1 + 2 * i], + (int)addrx4[2 * i] + ); + } + for (int i = 0; i < SPX_N / 8; i++) { + state[SPX_N / 8 + i + 4] = _mm256_set1_epi64x(((int64_t *)ctx->sk_seed)[i]); + } + + /* SHAKE domain separator and padding. */ + state[SPX_N / 4 + 4] = _mm256_set1_epi64x(0x1f); + for (int i = SPX_N / 4 + 5; i < 16; i++) { + state[i] = _mm256_set1_epi64x(0); + } + // shift unsigned and then cast to avoid UB + state[16] = _mm256_set1_epi64x((long long)(0x80ULL << 56)); + + for (int i = 17; i < 25; i++) { + state[i] = _mm256_set1_epi64x(0); + } + + KeccakP1600times4_PermuteAll_24rounds(&state[0]); + + for (int i = 0; i < SPX_N / 8; i++) { + ((int64_t *)out0)[i] = _mm256_extract_epi64(state[i], 0); + ((int64_t *)out1)[i] = _mm256_extract_epi64(state[i], 1); + ((int64_t *)out2)[i] = _mm256_extract_epi64(state[i], 2); + ((int64_t *)out3)[i] = _mm256_extract_epi64(state[i], 3); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/hashx4.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/hashx4.h new file mode 100644 index 0000000000..3751a0ebd0 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/hashx4.h @@ -0,0 +1,17 @@ +#ifndef SPX_HASHX4_H +#define SPX_HASHX4_H + +#include + +#include "context.h" +#include "params.h" + +#define prf_addrx4 SPX_NAMESPACE(prf_addrx4) +void prf_addrx4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const spx_ctx *ctx, + const uint32_t addrx4[4 * 8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/merkle.c b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/merkle.c new file mode 100644 index 0000000000..f57811c1ac --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/merkle.c @@ -0,0 +1,64 @@ +#include +#include + +#include "merkle.h" + +#include "address.h" +#include "params.h" +#include "utils.h" +#include "utilsx4.h" +#include "wots.h" +#include "wotsx4.h" + +/* + * This generates a Merkle signature (WOTS signature followed by the Merkle + * authentication path). + */ +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf) { + unsigned char *auth_path = sig + SPX_WOTS_BYTES; + uint32_t tree_addrx4[4 * 8] = { 0 }; + int j; + struct leaf_info_x4 info = { 0 }; + unsigned steps[ SPX_WOTS_LEN ]; + + info.wots_sig = sig; + chain_lengths(steps, root); + info.wots_steps = steps; + + for (j = 0; j < 4; j++) { + set_type(&tree_addrx4[8 * j], SPX_ADDR_TYPE_HASHTREE); + set_type(&info.leaf_addr[8 * j], SPX_ADDR_TYPE_WOTS); + set_type(&info.pk_addr[8 * j], SPX_ADDR_TYPE_WOTSPK); + copy_subtree_addr(&tree_addrx4[8 * j], tree_addr); + copy_subtree_addr(&info.leaf_addr[8 * j], wots_addr); + copy_subtree_addr(&info.pk_addr[8 * j], wots_addr); + } + + info.wots_sign_leaf = idx_leaf; + + treehashx4(root, auth_path, ctx, + idx_leaf, 0, + SPX_TREE_HEIGHT, + wots_gen_leafx4, + tree_addrx4, &info); +} + +/* Compute root node of the top-most subtree. */ +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { + /* We do not need the auth path in key generation, but it simplifies the + code to have just one treehash routine that computes both root and path + in one function. */ + unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; + uint32_t top_tree_addr[8] = {0}; + uint32_t wots_addr[8] = {0}; + + set_layer_addr(top_tree_addr, SPX_D - 1); + set_layer_addr(wots_addr, SPX_D - 1); + + merkle_sign(auth_path, root, ctx, + wots_addr, top_tree_addr, + ~0U /* ~0 means "don't bother generating an auth path */ ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/merkle.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/merkle.h new file mode 100644 index 0000000000..769cf2e970 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/merkle.h @@ -0,0 +1,21 @@ +#ifndef MERKLE_H_ +#define MERKLE_H_ + +#include + +#include "context.h" +#include "params.h" + +/* Generate a Merkle signature (WOTS signature followed by the Merkle */ +/* authentication path) */ +#define merkle_sign SPX_NAMESPACE(merkle_sign) +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf); + +/* Compute the root node of the top-most subtree. */ +#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); + +#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/nistapi.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/nistapi.h new file mode 100644 index 0000000000..3cb71afad4 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/nistapi.h @@ -0,0 +1,87 @@ +#ifndef SPX_API_H +#define SPX_API_H + +#include +#include + +#include "params.h" + +#define CRYPTO_ALGNAME "SPHINCS+" + +#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES +#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES +#define CRYPTO_BYTES SPX_BYTES +#define CRYPTO_SEEDBYTES (3*SPX_N) + +/* + * Returns the length of a secret key, in bytes + */ +#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) +size_t crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) +size_t crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) +size_t crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) +size_t crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +#define crypto_sign SPX_NAMESPACE(crypto_sign) +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/params.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/params.h new file mode 100644 index 0000000000..fd6f0c5f9a --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/params.h @@ -0,0 +1,56 @@ +#ifndef SPX_PARAMS_H +#define SPX_PARAMS_H + +#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSSHAKE256FSIMPLE_AVX2_##s + +/* Hash output length in bytes. */ +#define SPX_N 32 +/* Height of the hypertree. */ +#define SPX_FULL_HEIGHT 68 +/* Number of subtree layer. */ +#define SPX_D 17 +/* FORS tree dimensions. */ +#define SPX_FORS_HEIGHT 9 +#define SPX_FORS_TREES 35 +/* Winternitz parameter, */ +#define SPX_WOTS_W 16 + +/* The hash function is defined by linking a different hash.c file, as opposed + to setting a #define constant. */ + +/* For clarity */ +#define SPX_ADDR_BYTES 32 + +/* WOTS parameters. */ +#define SPX_WOTS_LOGW 4 + +#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) + +/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ +#define SPX_WOTS_LEN2 3 + +#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) +#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) +#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES + +/* Subtree size. */ +#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) + +//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT +// #error SPX_D should always divide SPX_FULL_HEIGHT +//#endif + +/* FORS parameters. */ +#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) +#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) +#define SPX_FORS_PK_BYTES SPX_N + +/* Resulting SPX sizes. */ +#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ + SPX_FULL_HEIGHT * SPX_N) +#define SPX_PK_BYTES (2 * SPX_N) +#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) + +#include "shake_offsets.h" + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/shake_offsets.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/shake_offsets.h new file mode 100644 index 0000000000..6b28d95d91 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/shake_offsets.h @@ -0,0 +1,21 @@ +#ifndef SHAKE_OFFSETS_H_ +#define SHAKE_OFFSETS_H_ + +/* + * Offsets of various fields in the address structure when we use SHAKE as + * the Sphincs+ hash function + */ + +#define SPX_OFFSET_LAYER 3 /* The byte used to specify the Merkle tree layer */ +#define SPX_OFFSET_TREE 8 /* The start of the 8 byte field used to specify the tree */ +#define SPX_OFFSET_TYPE 19 /* The byte used to specify the hash type (reason) */ +#define SPX_OFFSET_KP_ADDR2 22 /* The high byte used to specify the key pair (which one-time signature) */ +#define SPX_OFFSET_KP_ADDR1 23 /* The low byte used to specify the key pair */ +#define SPX_OFFSET_CHAIN_ADDR 27 /* The byte used to specify the chain address (which Winternitz chain) */ +#define SPX_OFFSET_HASH_ADDR 31 /* The byte used to specify the hash address (where in the Winternitz chain) */ +#define SPX_OFFSET_TREE_HGT 27 /* The byte used to specify the height of this node in the FORS or Merkle tree */ +#define SPX_OFFSET_TREE_INDEX 28 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ + +#define SPX_SHAKE 1 + +#endif /* SHAKE_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/sign.c b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/sign.c new file mode 100644 index 0000000000..9d0c7d1b22 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/sign.c @@ -0,0 +1,286 @@ +#include +#include +#include + +#include "address.h" +#include "context.h" +#include "fors.h" +#include "hash.h" +#include "merkle.h" +#include "nistapi.h" +#include "params.h" +#include "randombytes.h" +#include "thash.h" +#include "utils.h" +#include "wots.h" + +/* + * Returns the length of a secret key, in bytes + */ +size_t crypto_sign_secretkeybytes(void) { + return CRYPTO_SECRETKEYBYTES; +} + +/* + * Returns the length of a public key, in bytes + */ +size_t crypto_sign_publickeybytes(void) { + return CRYPTO_PUBLICKEYBYTES; +} + +/* + * Returns the length of a signature, in bytes + */ +size_t crypto_sign_bytes(void) { + return CRYPTO_BYTES; +} + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +size_t crypto_sign_seedbytes(void) { + return CRYPTO_SEEDBYTES; +} + +/* + * Generates an SPX key pair given a seed of length + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [PUB_SEED || root] + */ +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed) { + spx_ctx ctx; + + /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ + memcpy(sk, seed, CRYPTO_SEEDBYTES); + + memcpy(pk, sk + 2 * SPX_N, SPX_N); + + memcpy(ctx.pub_seed, pk, SPX_N); + memcpy(ctx.sk_seed, sk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + /* Compute root node of the top-most subtree. */ + merkle_gen_root(sk + 3 * SPX_N, &ctx); + + // cleanup + free_hash_function(&ctx); + + memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); + + return 0; +} + +/* + * Generates an SPX key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [PUB_SEED || root] + */ +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { + uint8_t seed[CRYPTO_SEEDBYTES]; + randombytes(seed, CRYPTO_SEEDBYTES); + crypto_sign_seed_keypair(pk, sk, seed); + + return 0; +} + +/** + * Returns an array containing a detached signature. + */ +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk) { + spx_ctx ctx; + + const uint8_t *sk_prf = sk + SPX_N; + const uint8_t *pk = sk + 2 * SPX_N; + + uint8_t optrand[SPX_N]; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t root[SPX_N]; + uint32_t i; + uint64_t tree; + uint32_t idx_leaf; + uint32_t wots_addr[8] = {0}; + uint32_t tree_addr[8] = {0}; + + memcpy(ctx.sk_seed, sk, SPX_N); + memcpy(ctx.pub_seed, pk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + + /* Optionally, signing can be made non-deterministic using optrand. + This can help counter side-channel attacks that would benefit from + getting a large number of traces when the signer uses the same nodes. */ + randombytes(optrand, SPX_N); + /* Compute the digest randomization value. */ + gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); + + /* Derive the message digest and leaf index from R, PK and M. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; + + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); + + /* Sign the message hash using FORS. */ + fors_sign(sig, root, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); + sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; + + /* Update the indices for the next layer. */ + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; + } + + free_hash_function(&ctx); + + *siglen = SPX_BYTES; + + return 0; +} + +/** + * Verifies a detached signature and message under a given public key. + */ +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk) { + spx_ctx ctx; + const uint8_t *pub_root = pk + SPX_N; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t wots_pk[SPX_WOTS_BYTES]; + uint8_t root[SPX_N]; + uint8_t leaf[SPX_N]; + unsigned int i; + uint64_t tree; + uint32_t idx_leaf; + uint32_t wots_addr[8] = {0}; + uint32_t tree_addr[8] = {0}; + uint32_t wots_pk_addr[8] = {0}; + + if (siglen != SPX_BYTES) { + return -1; + } + + memcpy(ctx.pub_seed, pk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); + + /* Derive the message digest and leaf index from R || PK || M. */ + /* The additional SPX_N is a result of the hash domain separator. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; + + /* Layer correctly defaults to 0, so no need to set_layer_addr */ + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); + + fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + /* For each subtree.. */ + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + copy_keypair_addr(wots_pk_addr, wots_addr); + + /* The WOTS public key is only correct if the signature was correct. */ + /* Initially, root is the FORS pk, but on subsequent iterations it is + the root of the subtree below the currently processed subtree. */ + wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); + sig += SPX_WOTS_BYTES; + + /* Compute the leaf node using the WOTS public key. */ + thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); + + /* Compute the root node of this subtree. */ + compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, + &ctx, tree_addr); + sig += SPX_TREE_HEIGHT * SPX_N; + + /* Update the indices for the next layer. */ + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; + } + + // cleanup + free_hash_function(&ctx); + + /* Check if the root node equals the root node in the public key. */ + if (memcmp(root, pub_root, SPX_N) != 0) { + return -1; + } + + return 0; +} + + +/** + * Returns an array containing the signature followed by the message. + */ +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk) { + size_t siglen; + + crypto_sign_signature(sm, &siglen, m, mlen, sk); + + memmove(sm + SPX_BYTES, m, mlen); + *smlen = siglen + mlen; + + return 0; +} + +/** + * Verifies a given signature-message pair under a given public key. + */ +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk) { + /* The API caller does not necessarily know what size a signature should be + but SPHINCS+ signatures are always exactly SPX_BYTES. */ + if (smlen < SPX_BYTES) { + memset(m, 0, smlen); + *mlen = 0; + return -1; + } + + *mlen = smlen - SPX_BYTES; + + if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { + memset(m, 0, smlen); + *mlen = 0; + return -1; + } + + /* If verification was successful, move the message to the right place. */ + memmove(m, sm + SPX_BYTES, *mlen); + + return 0; +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/thash.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/thash.h new file mode 100644 index 0000000000..8687ccfb4d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/thash.h @@ -0,0 +1,13 @@ +#ifndef SPX_THASH_H +#define SPX_THASH_H + +#include "context.h" +#include "params.h" + +#include + +#define thash SPX_NAMESPACE(thash) +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/thash_shake_simple.c b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/thash_shake_simple.c new file mode 100644 index 0000000000..98470395e9 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/thash_shake_simple.c @@ -0,0 +1,24 @@ +#include +#include + +#include "thash.h" + +#include "address.h" +#include "params.h" +#include "utils.h" + +#include "fips202.h" + +/** + * Takes an array of inblocks concatenated arrays of SPX_N bytes. + */ +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]) { + PQCLEAN_VLA(uint8_t, buf, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); + + memcpy(buf, ctx->pub_seed, SPX_N); + memcpy(buf + SPX_N, addr, SPX_ADDR_BYTES); + memcpy(buf + SPX_N + SPX_ADDR_BYTES, in, inblocks * SPX_N); + + shake256(out, SPX_N, buf, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/thash_shake_simplex4.c b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/thash_shake_simplex4.c new file mode 100644 index 0000000000..89dc9a4224 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/thash_shake_simplex4.c @@ -0,0 +1,98 @@ +#include +#include + +#include "thashx4.h" + +#include "address.h" +#include "params.h" +#include "utils.h" + +#include "fips202x4.h" + +extern void KeccakP1600times4_PermuteAll_24rounds(__m256i *s); + +/** + * 4-way parallel version of thash; takes 4x as much input and output + */ +void thashx4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addrx4[4 * 8]) { + if (inblocks == 1 || inblocks == 2) { + /* As we write and read only a few quadwords, it is more efficient to + * build and extract from the fourway SHAKE256 state by hand. */ + __m256i state[25]; + for (int i = 0; i < SPX_N / 8; i++) { + state[i] = _mm256_set1_epi64x(((int64_t *)ctx->pub_seed)[i]); + } + for (int i = 0; i < 4; i++) { + state[SPX_N / 8 + i] = _mm256_set_epi32( + (int)addrx4[3 * 8 + 1 + 2 * i], + (int)addrx4[3 * 8 + 2 * i], + (int)addrx4[2 * 8 + 1 + 2 * i], + (int)addrx4[2 * 8 + 2 * i], + (int)addrx4[8 + 1 + 2 * i], + (int)addrx4[8 + 2 * i], + (int)addrx4[1 + 2 * i], + (int)addrx4[2 * i] + ); + } + + for (unsigned int i = 0; i < (SPX_N / 8) * inblocks; i++) { + state[SPX_N / 8 + 4 + i] = _mm256_set_epi64x( + ((int64_t *)in3)[i], + ((int64_t *)in2)[i], + ((int64_t *)in1)[i], + ((int64_t *)in0)[i] + ); + } + + /* Domain separator and padding. */ + for (size_t i = (SPX_N / 8) * (1 + inblocks) + 4; i < 16; i++) { + state[i] = _mm256_set1_epi64x(0); + } + state[16] = _mm256_set1_epi64x((long long)(0x80ULL << 56)); + state[(SPX_N / 8) * (1 + inblocks) + 4] = _mm256_xor_si256( + state[(SPX_N / 8) * (1 + inblocks) + 4], + _mm256_set1_epi64x(0x1f) + ); + for (int i = 17; i < 25; i++) { + state[i] = _mm256_set1_epi64x(0); + } + + KeccakP1600times4_PermuteAll_24rounds(&state[0]); + + for (int i = 0; i < SPX_N / 8; i++) { + ((int64_t *)out0)[i] = _mm256_extract_epi64(state[i], 0); + ((int64_t *)out1)[i] = _mm256_extract_epi64(state[i], 1); + ((int64_t *)out2)[i] = _mm256_extract_epi64(state[i], 2); + ((int64_t *)out3)[i] = _mm256_extract_epi64(state[i], 3); + } + } else { + PQCLEAN_VLA(unsigned char, buf0, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, buf1, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, buf2, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, buf3, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); + + memcpy(buf0, ctx->pub_seed, SPX_N); + memcpy(buf1, ctx->pub_seed, SPX_N); + memcpy(buf2, ctx->pub_seed, SPX_N); + memcpy(buf3, ctx->pub_seed, SPX_N); + memcpy(buf0 + SPX_N, addrx4 + 0 * 8, SPX_ADDR_BYTES); + memcpy(buf1 + SPX_N, addrx4 + 1 * 8, SPX_ADDR_BYTES); + memcpy(buf2 + SPX_N, addrx4 + 2 * 8, SPX_ADDR_BYTES); + memcpy(buf3 + SPX_N, addrx4 + 3 * 8, SPX_ADDR_BYTES); + memcpy(buf0 + SPX_N + SPX_ADDR_BYTES, in0, inblocks * SPX_N); + memcpy(buf1 + SPX_N + SPX_ADDR_BYTES, in1, inblocks * SPX_N); + memcpy(buf2 + SPX_N + SPX_ADDR_BYTES, in2, inblocks * SPX_N); + memcpy(buf3 + SPX_N + SPX_ADDR_BYTES, in3, inblocks * SPX_N); + + shake256x4(out0, out1, out2, out3, SPX_N, + buf0, buf1, buf2, buf3, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/thashx4.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/thashx4.h new file mode 100644 index 0000000000..64798a3727 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/thashx4.h @@ -0,0 +1,20 @@ +#ifndef SPX_THASHX4_H +#define SPX_THASHX4_H + +#include + +#include "context.h" +#include "params.h" + +#define thashx4 SPX_NAMESPACE(thashx4) +void thashx4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addrx4[4 * 8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/utils.c b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/utils.c new file mode 100644 index 0000000000..177b541fb9 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/utils.c @@ -0,0 +1,148 @@ +#include + +#include "utils.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "thash.h" + +/** + * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. + */ +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in) { + int i; + + /* Iterate over out in decreasing order, for big-endianness. */ + for (i = (signed int)outlen - 1; i >= 0; i--) { + out[i] = in & 0xff; + in = in >> 8; + } +} + +void u32_to_bytes(unsigned char *out, uint32_t in) { + out[0] = (unsigned char)(in >> 24); + out[1] = (unsigned char)(in >> 16); + out[2] = (unsigned char)(in >> 8); + out[3] = (unsigned char)in; +} + +/** + * Converts the inlen bytes in 'in' from big-endian byte order to an integer. + */ +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { + unsigned long long retval = 0; + unsigned int i; + + for (i = 0; i < inlen; i++) { + retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); + } + return retval; +} + +/** + * Computes a root node given a leaf and an auth path. + * Expects address to be complete other than the tree_height and tree_index. + */ +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]) { + uint32_t i; + unsigned char buffer[2 * SPX_N]; + + /* If leaf_idx is odd (last bit = 1), current path element is a right child + and auth_path has to go left. Otherwise it is the other way around. */ + if (leaf_idx & 1) { + memcpy(buffer + SPX_N, leaf, SPX_N); + memcpy(buffer, auth_path, SPX_N); + } else { + memcpy(buffer, leaf, SPX_N); + memcpy(buffer + SPX_N, auth_path, SPX_N); + } + auth_path += SPX_N; + + for (i = 0; i < tree_height - 1; i++) { + leaf_idx >>= 1; + idx_offset >>= 1; + /* Set the address of the node we're creating. */ + set_tree_height(addr, i + 1); + set_tree_index(addr, leaf_idx + idx_offset); + + /* Pick the right or left neighbor, depending on parity of the node. */ + if (leaf_idx & 1) { + thash(buffer + SPX_N, buffer, 2, ctx, addr); + memcpy(buffer, auth_path, SPX_N); + } else { + thash(buffer, buffer, 2, ctx, addr); + memcpy(buffer + SPX_N, auth_path, SPX_N); + } + auth_path += SPX_N; + } + + /* The last iteration is exceptional; we do not copy an auth_path node. */ + leaf_idx >>= 1; + idx_offset >>= 1; + set_tree_height(addr, tree_height); + set_tree_index(addr, leaf_idx + idx_offset); + thash(root, buffer, 2, ctx, addr); +} + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx * /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]) { + PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); + PQCLEAN_VLA(unsigned int, heights, tree_height + 1); + unsigned int offset = 0; + uint32_t idx; + uint32_t tree_idx; + + for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { + /* Add the next leaf node to the stack. */ + gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); + offset++; + heights[offset - 1] = 0; + + /* If this is a node we need for the auth path.. */ + if ((leaf_idx ^ 0x1) == idx) { + memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); + } + + /* While the top-most nodes are of equal height.. */ + while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { + /* Compute index of the new node, in the next layer. */ + tree_idx = (idx >> (heights[offset - 1] + 1)); + + /* Set the address of the node we're creating. */ + set_tree_height(tree_addr, heights[offset - 1] + 1); + set_tree_index(tree_addr, + tree_idx + (idx_offset >> (heights[offset - 1] + 1))); + /* Hash the top-most nodes from the stack together. */ + thash(stack + (offset - 2)*SPX_N, + stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); + offset--; + /* Note that the top-most node is now one layer higher. */ + heights[offset - 1]++; + + /* If this is a node we need for the auth path.. */ + if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { + memcpy(auth_path + heights[offset - 1]*SPX_N, + stack + (offset - 1)*SPX_N, SPX_N); + } + } + } + memcpy(root, stack, SPX_N); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/utils.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/utils.h new file mode 100644 index 0000000000..64f5d5a53a --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/utils.h @@ -0,0 +1,58 @@ +#ifndef SPX_UTILS_H +#define SPX_UTILS_H + +#include + +#include "compat.h" +#include "context.h" +#include "params.h" + + +/* To support MSVC use alloca() instead of VLAs. See #20. */ + + +/** + * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. + */ +#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in); +#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) +void u32_to_bytes(unsigned char *out, uint32_t in); + +/** + * Converts the inlen bytes in 'in' from big-endian byte order to an integer. + */ +#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); + +/** + * Computes a root node given a leaf and an auth path. + * Expects address to be complete other than the tree_height and tree_index. + */ +#define compute_root SPX_NAMESPACE(compute_root) +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]); + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +#define treehash SPX_NAMESPACE(treehash) +void treehash(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx *ctx /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]); + + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/utilsx4.c b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/utilsx4.c new file mode 100644 index 0000000000..1638677194 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/utilsx4.c @@ -0,0 +1,138 @@ +#include + +#include "utilsx4.h" + +#include "address.h" +#include "params.h" +#include "thashx4.h" +#include "utils.h" + +/* + * Generate the entire Merkle tree, computing the authentication path for leaf_idx, + * and the resulting root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) + * + * This expects tree_addrx4 to be initialized to 4 parallel addr structures for + * the Merkle tree nodes + * + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + * + * This works by using the standard Merkle tree building algorithm, except + * that each 'node' tracked is actually 4 consecutive nodes in the real tree. + * When we combine two logical nodes ABCD and WXYZ, we perform the H + * operation on adjacent real nodes, forming the parent logical node + * (AB)(CD)(WX)(YZ) + * + * When we get to the top two levels of the real tree (where there is only + * one logical node), we continue this operation two more times; the right + * most real node will by the actual root (and the other 3 nodes will be + * garbage). We follow the same thashx4 logic so that the 'extract + * authentication path components' part of the loop is still executed (and + * to simplify the code somewhat) + * + * This currently assumes tree_height >= 2; I suspect that doing an adjusting + * idx, addr_idx on the gen_leafx4 call if tree_height < 2 would fix it; since + * we don't actually use such short trees, I haven't bothered + */ +void treehashx4(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, + uint32_t tree_height, + void (*gen_leafx4)( + unsigned char * /* Where to write the leaves */, + const spx_ctx *, + uint32_t idx, void *info), + uint32_t tree_addrx4[4 * 8], + void *info) { + /* This is where we keep the intermediate nodes */ + PQCLEAN_VLA(unsigned char, stackx4, tree_height * 4 * SPX_N); + uint32_t left_adj = 0, prev_left_adj = 0; /* When we're doing the top 3 */ + /* levels, the left-most part of the tree isn't at the beginning */ + /* of current[]. These give the offset of the actual start */ + + uint32_t idx; + uint32_t max_idx = (1U << (tree_height - 2)) - 1; + for (idx = 0;; idx++) { + unsigned char current[4 * SPX_N]; /* Current logical node */ + gen_leafx4( current, ctx, 4 * idx + idx_offset, + info ); + + /* Now combine the freshly generated right node with previously */ + /* generated left ones */ + uint32_t internal_idx_offset = idx_offset; + uint32_t internal_idx = idx; + uint32_t internal_leaf = leaf_idx; + uint32_t h; /* The height we are in the Merkle tree */ + for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { + + /* Special processing if we're at the top of the tree */ + if (h >= tree_height - 2) { + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[3 * SPX_N], SPX_N ); + return; + } + /* The tree indexing logic is a bit off in this case */ + /* Adjust it so that the left-most node of the part of */ + /* the tree that we're processing has index 0 */ + prev_left_adj = left_adj; + left_adj = 4U - (1 << (tree_height - h - 1)); + } + + /* Check if we hit the top of the tree */ + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[3 * SPX_N], SPX_N ); + return; + } + + /* + * Check if one of the nodes we have is a part of the + * authentication path; if it is, write it out + */ + if ((((internal_idx << 2) ^ internal_leaf) & ~0x3U) == 0) { + memcpy( &auth_path[ h * SPX_N ], + ¤t[(((internal_leaf & 3) ^ 1) + prev_left_adj) * SPX_N], + SPX_N ); + } + + /* + * Check if we're at a left child; if so, stop going up the stack + * Exception: if we've reached the end of the tree, keep on going + * (so we combine the last 4 nodes into the one root node in two + * more iterations) + */ + if ((internal_idx & 1) == 0 && idx < max_idx) { + break; + } + + /* Ok, we're at a right node (or doing the top 3 levels) */ + /* Now combine the left and right logical nodes together */ + + /* Set the address of the node we're creating. */ + unsigned int j; + internal_idx_offset >>= 1; + for (j = 0; j < 4; j++) { + set_tree_height(tree_addrx4 + j * 8, h + 1); + set_tree_index(tree_addrx4 + j * 8, + (4 / 2) * (internal_idx & ~1U) + j - left_adj + internal_idx_offset ); + } + unsigned char *left = &stackx4[h * 4 * SPX_N]; + thashx4( ¤t[0 * SPX_N], + ¤t[1 * SPX_N], + ¤t[2 * SPX_N], + ¤t[3 * SPX_N], + &left [0 * SPX_N], + &left [2 * SPX_N], + ¤t[0 * SPX_N], + ¤t[2 * SPX_N], + 2, ctx, tree_addrx4); + } + + /* We've hit a left child; save the current for when we get the */ + /* corresponding right right */ + memcpy( &stackx4[h * 4 * SPX_N], current, 4 * SPX_N); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/utilsx4.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/utilsx4.h new file mode 100644 index 0000000000..facb874b18 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/utilsx4.h @@ -0,0 +1,30 @@ +#ifndef SPX_UTILSX4_H +#define SPX_UTILSX4_H + +#include + +#include "context.h" +#include "params.h" + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + * + * This implementation uses AVX to compute internal nodes 4 at a time (in + * parallel) + */ +#define treehashx4 SPX_NAMESPACE(treehashx4) +void treehashx4(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leafx4)( + unsigned char * /* Where to write the leaves */, + const spx_ctx * /* ctx */, + uint32_t addr_idx, void *info), + uint32_t tree_addrx4[4 * 8], void *info); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/wots.c b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/wots.c new file mode 100644 index 0000000000..4d5041ce05 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/wots.c @@ -0,0 +1,269 @@ +#include +#include + +#include "wots.h" + +#include "address.h" +#include "hash.h" +#include "hashx4.h" +#include "params.h" +#include "thash.h" +#include "thashx4.h" +#include "utils.h" +#include "utilsx4.h" +#include "wotsx4.h" + +// TODO clarify address expectations, and make them more uniform. +// TODO i.e. do we expect types to be set already? +// TODO and do we expect modifications or copies? + +/** + * Computes up the chains + */ +static void gen_chains( + unsigned char *out, + const unsigned char *in, + unsigned int start[SPX_WOTS_LEN], + const unsigned int steps[SPX_WOTS_LEN], + const spx_ctx *ctx, + uint32_t addr[8]) { + uint32_t i, j, k, idx, watching; + int done; + unsigned char empty[SPX_N]; + unsigned char *bufs[4]; + uint32_t addrs[8 * 4]; + + int l; + uint16_t counts[SPX_WOTS_W] = { 0 }; + uint16_t idxs[SPX_WOTS_LEN]; + uint16_t total, newTotal; + + /* set addrs = {addr, addr, addr, addr} */ + for (j = 0; j < 4; j++) { + memcpy(addrs + j * 8, addr, sizeof(uint32_t) * 8); + } + + /* Initialize out with the value at position 'start'. */ + memcpy(out, in, SPX_WOTS_LEN * SPX_N); + + /* Sort the chains in reverse order by steps using counting sort. */ + for (i = 0; i < SPX_WOTS_LEN; i++) { + counts[steps[i]]++; + } + total = 0; + for (l = SPX_WOTS_W - 1; l >= 0; l--) { + newTotal = counts[l] + total; + counts[l] = total; + total = newTotal; + } + for (i = 0; i < SPX_WOTS_LEN; i++) { + idxs[counts[steps[i]]] = (uint16_t)i; + counts[steps[i]]++; + } + + /* We got our work cut out for us: do it! */ + for (i = 0; i < SPX_WOTS_LEN; i += 4) { + for (j = 0; j < 4 && i + j < SPX_WOTS_LEN; j++) { + idx = idxs[i + j]; + set_chain_addr(addrs + j * 8, idx); + bufs[j] = out + SPX_N * idx; + } + + /* As the chains are sorted in reverse order, we know that the first + * chain is the longest and the last one is the shortest. We keep + * an eye on whether the last chain is done and then on the one before, + * et cetera. */ + watching = 3; + done = 0; + while (i + watching >= SPX_WOTS_LEN) { + bufs[watching] = &empty[0]; + watching--; + } + + for (k = 0;; k++) { + while (k == steps[idxs[i + watching]]) { + bufs[watching] = &empty[0]; + if (watching == 0) { + done = 1; + break; + } + watching--; + } + if (done) { + break; + } + for (j = 0; j < watching + 1; j++) { + set_hash_addr(addrs + j * 8, k + start[idxs[i + j]]); + } + + thashx4(bufs[0], bufs[1], bufs[2], bufs[3], + bufs[0], bufs[1], bufs[2], bufs[3], 1, ctx, addrs); + } + } +} + +/** + * base_w algorithm as described in draft. + * Interprets an array of bytes as integers in base w. + * This only works when log_w is a divisor of 8. + */ +static void base_w(unsigned int *output, const int out_len, + const unsigned char *input) { + int in = 0; + int out = 0; + unsigned char total = 0; + int bits = 0; + int consumed; + + for (consumed = 0; consumed < out_len; consumed++) { + if (bits == 0) { + total = input[in]; + in++; + bits += 8; + } + bits -= SPX_WOTS_LOGW; + output[out] = (total >> bits) & (SPX_WOTS_W - 1); + out++; + } +} + +/* Computes the WOTS+ checksum over a message (in base_w). */ +static void wots_checksum(unsigned int *csum_base_w, + const unsigned int *msg_base_w) { + unsigned int csum = 0; + unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; + unsigned int i; + + /* Compute checksum. */ + for (i = 0; i < SPX_WOTS_LEN1; i++) { + csum += SPX_WOTS_W - 1 - msg_base_w[i]; + } + + /* Convert checksum to base_w. */ + /* Make sure expected empty zero bits are the least significant bits. */ + csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); + ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); + base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); +} + +/* Takes a message and derives the matching chain lengths. */ +void chain_lengths(unsigned int *lengths, const unsigned char *msg) { + base_w(lengths, SPX_WOTS_LEN1, msg); + wots_checksum(lengths + SPX_WOTS_LEN1, lengths); +} + +/** + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. + * + * Writes the computed public key to 'pk'. + */ +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]) { + unsigned int steps[SPX_WOTS_LEN]; + unsigned int start[SPX_WOTS_LEN]; + uint32_t i; + + chain_lengths(start, msg); + + for (i = 0; i < SPX_WOTS_LEN; i++) { + steps[i] = SPX_WOTS_W - 1 - start[i]; + } + + gen_chains(pk, sig, start, steps, ctx, addr); +} + +/* + * This generates 4 sequential WOTS public keys + * It also generates the WOTS signature if leaf_info indicates + * that we're signing with one of these WOTS keys + */ +void wots_gen_leafx4(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info) { + struct leaf_info_x4 *info = v_info; + uint32_t *leaf_addr = info->leaf_addr; + uint32_t *pk_addr = info->pk_addr; + unsigned int i, j, k; + unsigned char pk_buffer[ 4 * SPX_WOTS_BYTES ]; + unsigned wots_offset = SPX_WOTS_BYTES; + unsigned char *buffer; + uint32_t wots_k_mask; + unsigned wots_sign_index; + + if (((leaf_idx ^ info->wots_sign_leaf) & ~3U) == 0) { + /* We're traversing the leaf that's signing; generate the WOTS */ + /* signature */ + wots_k_mask = 0; + wots_sign_index = info->wots_sign_leaf & 3; /* Which of of the 4 */ + /* 4 slots do the signatures come from */ + } else { + /* Nope, we're just generating pk's; turn off the signature logic */ + wots_k_mask = (uint32_t)~0; + wots_sign_index = 0; + } + + for (j = 0; j < 4; j++) { + set_keypair_addr( leaf_addr + j * 8, leaf_idx + j ); + set_keypair_addr( pk_addr + j * 8, leaf_idx + j ); + } + + for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { + uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k to */ + /* the step if we're generating a signature, ~0 if we're not */ + + /* Start with the secret seed */ + for (j = 0; j < 4; j++) { + set_chain_addr(leaf_addr + j * 8, i); + set_hash_addr(leaf_addr + j * 8, 0); + set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTSPRF); + } + prf_addrx4(buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + buffer + 2 * wots_offset, + buffer + 3 * wots_offset, + ctx, leaf_addr); + + for (j = 0; j < 4; j++) { + set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTS); + } + + /* Iterate down the WOTS chain */ + for (k = 0;; k++) { + /* Check if one of the values we have needs to be saved as a */ + /* part of the WOTS signature */ + if (k == wots_k) { + memcpy( info->wots_sig + i * SPX_N, + buffer + wots_sign_index * wots_offset, SPX_N ); + } + + /* Check if we hit the top of the chain */ + if (k == SPX_WOTS_W - 1) { + break; + } + + /* Iterate one step on all 4 chains */ + for (j = 0; j < 4; j++) { + set_hash_addr(leaf_addr + j * 8, k); + } + thashx4(buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + buffer + 2 * wots_offset, + buffer + 3 * wots_offset, + buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + buffer + 2 * wots_offset, + buffer + 3 * wots_offset, 1, ctx, leaf_addr); + } + } + + /* Do the final thash to generate the public keys */ + thashx4(dest + 0 * SPX_N, + dest + 1 * SPX_N, + dest + 2 * SPX_N, + dest + 3 * SPX_N, + pk_buffer + 0 * wots_offset, + pk_buffer + 1 * wots_offset, + pk_buffer + 2 * wots_offset, + pk_buffer + 3 * wots_offset, SPX_WOTS_LEN, ctx, pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/wots.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/wots.h new file mode 100644 index 0000000000..4e7692eeef --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/wots.h @@ -0,0 +1,25 @@ +#ifndef SPX_WOTS_H +#define SPX_WOTS_H + +#include + +#include "context.h" +#include "params.h" + +/** + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. + * + * Writes the computed public key to 'pk'. + */ +#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]); + +/* + * Compute the chain lengths needed for a given message hash + */ +#define chain_lengths SPX_NAMESPACE(chain_lengths) +void chain_lengths(unsigned int *lengths, const unsigned char *msg); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/wotsx4.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/wotsx4.h new file mode 100644 index 0000000000..cd634f1743 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/wotsx4.h @@ -0,0 +1,41 @@ +#ifndef WOTSX4_H_ +#define WOTSX4_H_ + +#include + +#include "params.h" + +/* + * This is here to provide an interface to the internal wots_gen_leafx4 + * routine. While this routine is not referenced in the package outside of + * wots.c, it is called from the stand-alone benchmark code to characterize + * the performance + */ +struct leaf_info_x4 { + unsigned char *wots_sig; + uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ + uint32_t *wots_steps; + uint32_t leaf_addr[4 * 8]; + uint32_t pk_addr[4 * 8]; +}; + +/* Macro to set the leaf_info to something 'benign', that is, it would */ +/* run with the same time as it does during the real signing process */ +/* Used only by the benchmark code */ +#define INITIALIZE_LEAF_INFO_X4(info, addr, step_buffer) { \ + (info).wots_sig = 0; \ + (info).wots_sign_leaf = ~0; \ + (info).wots_steps = step_buffer; \ + int i; \ + for (i=0; i<4; i++) { \ + memcpy( &(info).leaf_addr[8*i], addr, 32 ); \ + memcpy( &(info).pk_addr[8*i], addr, 32 ); \ + } \ + } + +#define wots_gen_leafx4 SPX_NAMESPACE(wots_gen_leafx4) +void wots_gen_leafx4(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info); + +#endif /* WOTSX4_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_clean/LICENSE b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_clean/LICENSE new file mode 100644 index 0000000000..670154e353 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_clean/LICENSE @@ -0,0 +1,116 @@ +CC0 1.0 Universal + +Statement of Purpose + +The laws of most jurisdictions throughout the world automatically confer +exclusive Copyright and Related Rights (defined below) upon the creator and +subsequent owner(s) (each and all, an "owner") of an original work of +authorship and/or a database (each, a "Work"). + +Certain owners wish to permanently relinquish those rights to a Work for the +purpose of contributing to a commons of creative, cultural and scientific +works ("Commons") that the public can reliably and without fear of later +claims of infringement build upon, modify, incorporate in other works, reuse +and redistribute as freely as possible in any form whatsoever and for any +purposes, including without limitation commercial purposes. These owners may +contribute to the Commons to promote the ideal of a free culture and the +further production of creative, cultural and scientific works, or to gain +reputation or greater distribution for their Work in part through the use and +efforts of others. + +For these and/or other purposes and motivations, and without any expectation +of additional consideration or compensation, the person associating CC0 with a +Work (the "Affirmer"), to the extent that he or she is an owner of Copyright +and Related Rights in the Work, voluntarily elects to apply CC0 to the Work +and publicly distribute the Work under its terms, with knowledge of his or her +Copyright and Related Rights in the Work and the meaning and intended legal +effect of CC0 on those rights. + +1. Copyright and Related Rights. A Work made available under CC0 may be +protected by copyright and related or neighboring rights ("Copyright and +Related Rights"). Copyright and Related Rights include, but are not limited +to, the following: + + i. the right to reproduce, adapt, distribute, perform, display, communicate, + and translate a Work; + + ii. moral rights retained by the original author(s) and/or performer(s); + + iii. publicity and privacy rights pertaining to a person's image or likeness + depicted in a Work; + + iv. rights protecting against unfair competition in regards to a Work, + subject to the limitations in paragraph 4(a), below; + + v. rights protecting the extraction, dissemination, use and reuse of data in + a Work; + + vi. database rights (such as those arising under Directive 96/9/EC of the + European Parliament and of the Council of 11 March 1996 on the legal + protection of databases, and under any national implementation thereof, + including any amended or successor version of such directive); and + + vii. other similar, equivalent or corresponding rights throughout the world + based on applicable law or treaty, and any national implementations thereof. + +2. Waiver. To the greatest extent permitted by, but not in contravention of, +applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and +unconditionally waives, abandons, and surrenders all of Affirmer's Copyright +and Related Rights and associated claims and causes of action, whether now +known or unknown (including existing as well as future claims and causes of +action), in the Work (i) in all territories worldwide, (ii) for the maximum +duration provided by applicable law or treaty (including future time +extensions), (iii) in any current or future medium and for any number of +copies, and (iv) for any purpose whatsoever, including without limitation +commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes +the Waiver for the benefit of each member of the public at large and to the +detriment of Affirmer's heirs and successors, fully intending that such Waiver +shall not be subject to revocation, rescission, cancellation, termination, or +any other legal or equitable action to disrupt the quiet enjoyment of the Work +by the public as contemplated by Affirmer's express Statement of Purpose. + +3. Public License Fallback. Should any part of the Waiver for any reason be +judged legally invalid or ineffective under applicable law, then the Waiver +shall be preserved to the maximum extent permitted taking into account +Affirmer's express Statement of Purpose. In addition, to the extent the Waiver +is so judged Affirmer hereby grants to each affected person a royalty-free, +non transferable, non sublicensable, non exclusive, irrevocable and +unconditional license to exercise Affirmer's Copyright and Related Rights in +the Work (i) in all territories worldwide, (ii) for the maximum duration +provided by applicable law or treaty (including future time extensions), (iii) +in any current or future medium and for any number of copies, and (iv) for any +purpose whatsoever, including without limitation commercial, advertising or +promotional purposes (the "License"). The License shall be deemed effective as +of the date CC0 was applied by Affirmer to the Work. Should any part of the +License for any reason be judged legally invalid or ineffective under +applicable law, such partial invalidity or ineffectiveness shall not +invalidate the remainder of the License, and in such case Affirmer hereby +affirms that he or she will not (i) exercise any of his or her remaining +Copyright and Related Rights in the Work or (ii) assert any associated claims +and causes of action with respect to the Work, in either case contrary to +Affirmer's express Statement of Purpose. + +4. Limitations and Disclaimers. + + a. No trademark or patent rights held by Affirmer are waived, abandoned, + surrendered, licensed or otherwise affected by this document. + + b. Affirmer offers the Work as-is and makes no representations or warranties + of any kind concerning the Work, express, implied, statutory or otherwise, + including without limitation warranties of title, merchantability, fitness + for a particular purpose, non infringement, or the absence of latent or + other defects, accuracy, or the present or absence of errors, whether or not + discoverable, all to the greatest extent permissible under applicable law. + + c. Affirmer disclaims responsibility for clearing rights of other persons + that may apply to the Work or any use thereof, including without limitation + any person's Copyright and Related Rights in the Work. Further, Affirmer + disclaims responsibility for obtaining any necessary consents, permissions + or other rights required for any use of the Work. + + d. Affirmer understands and acknowledges that Creative Commons is not a + party to this document and has no duty or obligation with respect to this + CC0 or use of the Work. + +For more information, please see + diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_clean/address.c b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_clean/address.c new file mode 100644 index 0000000000..b956e9cb29 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_clean/address.c @@ -0,0 +1,91 @@ +#include +#include + +#include "address.h" +#include "params.h" +#include "utils.h" + +/* + * Specify which level of Merkle tree (the "layer") we're working on + */ +void set_layer_addr(uint32_t addr[8], uint32_t layer) { + ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; +} + +/* + * Specify which Merkle tree within the level (the "tree address") we're working on + */ +void set_tree_addr(uint32_t addr[8], uint64_t tree) { + ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); +} + +/* + * Specify the reason we'll use this address structure for, that is, what + * hash will we compute with it. This is used so that unrelated types of + * hashes don't accidentally get the same address structure. The type will be + * one of the SPX_ADDR_TYPE constants + */ +void set_type(uint32_t addr[8], uint32_t type) { + ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; +} + +/* + * Copy the layer and tree fields of the address structure. This is used + * when we're doing multiple types of hashes within the same Merkle tree + */ +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); +} + +/* These functions are used for OTS addresses. */ + +/* + * Specify which Merkle leaf we're working on; that is, which OTS keypair + * we're talking about. + */ +void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { + ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; +} + +/* + * Copy the layer, tree and keypair fields of the address structure. This is + * used when we're doing multiple things within the same OTS keypair + */ +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); + ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; +} + +/* + * Specify which Merkle chain within the OTS we're working with + * (the chain address) + */ +void set_chain_addr(uint32_t addr[8], uint32_t chain) { + ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; +} + +/* + * Specify where in the Merkle chain we are +* (the hash address) + */ +void set_hash_addr(uint32_t addr[8], uint32_t hash) { + ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; +} + +/* These functions are used for all hash tree addresses (including FORS). */ + +/* + * Specify the height of the node in the Merkle/FORS tree we are in + * (the tree height) + */ +void set_tree_height(uint32_t addr[8], uint32_t tree_height) { + ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; +} + +/* + * Specify the distance from the left edge of the node in the Merkle/FORS tree + * (the tree index) + */ +void set_tree_index(uint32_t addr[8], uint32_t tree_index) { + u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_clean/address.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_clean/address.h new file mode 100644 index 0000000000..24a84eb40c --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_clean/address.h @@ -0,0 +1,52 @@ +#ifndef SPX_ADDRESS_H +#define SPX_ADDRESS_H + +#include + +#include "params.h" + +/* The hash types that are passed to set_type */ +#define SPX_ADDR_TYPE_WOTS 0 +#define SPX_ADDR_TYPE_WOTSPK 1 +#define SPX_ADDR_TYPE_HASHTREE 2 +#define SPX_ADDR_TYPE_FORSTREE 3 +#define SPX_ADDR_TYPE_FORSPK 4 +#define SPX_ADDR_TYPE_WOTSPRF 5 +#define SPX_ADDR_TYPE_FORSPRF 6 + +#define set_layer_addr SPX_NAMESPACE(set_layer_addr) +void set_layer_addr(uint32_t addr[8], uint32_t layer); + +#define set_tree_addr SPX_NAMESPACE(set_tree_addr) +void set_tree_addr(uint32_t addr[8], uint64_t tree); + +#define set_type SPX_NAMESPACE(set_type) +void set_type(uint32_t addr[8], uint32_t type); + +/* Copies the layer and tree part of one address into the other */ +#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); + +/* These functions are used for WOTS and FORS addresses. */ + +#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) +void set_keypair_addr(uint32_t addr[8], uint32_t keypair); + +#define set_chain_addr SPX_NAMESPACE(set_chain_addr) +void set_chain_addr(uint32_t addr[8], uint32_t chain); + +#define set_hash_addr SPX_NAMESPACE(set_hash_addr) +void set_hash_addr(uint32_t addr[8], uint32_t hash); + +#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); + +/* These functions are used for all hash tree addresses (including FORS). */ + +#define set_tree_height SPX_NAMESPACE(set_tree_height) +void set_tree_height(uint32_t addr[8], uint32_t tree_height); + +#define set_tree_index SPX_NAMESPACE(set_tree_index) +void set_tree_index(uint32_t addr[8], uint32_t tree_index); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_clean/api.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_clean/api.h new file mode 100644 index 0000000000..fbadf6b6c5 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_clean/api.h @@ -0,0 +1,77 @@ +#ifndef PQCLEAN_SPHINCSSHAKE256FSIMPLE_CLEAN_API_H +#define PQCLEAN_SPHINCSSHAKE256FSIMPLE_CLEAN_API_H + +#include +#include + +#define PQCLEAN_SPHINCSSHAKE256FSIMPLE_CLEAN_CRYPTO_ALGNAME "SPHINCS+-shake-256f-simple" + +#define PQCLEAN_SPHINCSSHAKE256FSIMPLE_CLEAN_CRYPTO_SECRETKEYBYTES 128 +#define PQCLEAN_SPHINCSSHAKE256FSIMPLE_CLEAN_CRYPTO_PUBLICKEYBYTES 64 +#define PQCLEAN_SPHINCSSHAKE256FSIMPLE_CLEAN_CRYPTO_BYTES 49856 + +#define PQCLEAN_SPHINCSSHAKE256FSIMPLE_CLEAN_CRYPTO_SEEDBYTES 96 + +/* + * Returns the length of a secret key, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE256FSIMPLE_CLEAN_crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE256FSIMPLE_CLEAN_crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE256FSIMPLE_CLEAN_crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE256FSIMPLE_CLEAN_crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +int PQCLEAN_SPHINCSSHAKE256FSIMPLE_CLEAN_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +int PQCLEAN_SPHINCSSHAKE256FSIMPLE_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +int PQCLEAN_SPHINCSSHAKE256FSIMPLE_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +int PQCLEAN_SPHINCSSHAKE256FSIMPLE_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, + const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +int PQCLEAN_SPHINCSSHAKE256FSIMPLE_CLEAN_crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +int PQCLEAN_SPHINCSSHAKE256FSIMPLE_CLEAN_crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_clean/context.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_clean/context.h new file mode 100644 index 0000000000..9f8a40ab4e --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_clean/context.h @@ -0,0 +1,22 @@ +#ifndef SPX_CONTEXT_H +#define SPX_CONTEXT_H + +#include +#include + +#include "params.h" + +typedef struct { + uint8_t pub_seed[SPX_N]; + uint8_t sk_seed[SPX_N]; + + +} spx_ctx; + +#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) +void initialize_hash_function(spx_ctx *ctx); + +#define free_hash_function SPX_NAMESPACE(free_hash_function) +void free_hash_function(spx_ctx *ctx); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_clean/context_shake.c b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_clean/context_shake.c new file mode 100644 index 0000000000..9614a103d3 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_clean/context_shake.c @@ -0,0 +1,12 @@ +#include "context.h" + +/* For SHAKE256, there is no immediate reason to initialize at the start, + so this function is an empty operation. */ +void initialize_hash_function(spx_ctx *ctx) { + (void)ctx; /* Suppress an 'unused parameter' warning. */ +} + +// in case the hash function api is heap-based. +void free_hash_function(spx_ctx *ctx) { + (void)ctx; +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_clean/fors.c b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_clean/fors.c new file mode 100644 index 0000000000..96ca72e986 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_clean/fors.c @@ -0,0 +1,156 @@ +#include +#include +#include + +#include "fors.h" + +#include "address.h" +#include "hash.h" +#include "thash.h" +#include "utils.h" +#include "utilsx1.h" + +static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + prf_addr(sk, ctx, fors_leaf_addr); +} + +static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, + const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + thash(leaf, sk, 1, ctx, fors_leaf_addr); +} + +struct fors_gen_leaf_info { + uint32_t leaf_addrx[8]; +}; + +static void fors_gen_leafx1(unsigned char *leaf, + const spx_ctx *ctx, + uint32_t addr_idx, void *info) { + struct fors_gen_leaf_info *fors_info = info; + uint32_t *fors_leaf_addr = fors_info->leaf_addrx; + + /* Only set the parts that the caller doesn't set */ + set_tree_index(fors_leaf_addr, addr_idx); + set_type(fors_leaf_addr, SPX_ADDR_TYPE_FORSPRF); + fors_gen_sk(leaf, ctx, fors_leaf_addr); + + set_type(fors_leaf_addr, SPX_ADDR_TYPE_FORSTREE); + fors_sk_to_leaf(leaf, leaf, + ctx, fors_leaf_addr); +} + +/** + * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + * Assumes indices has space for SPX_FORS_TREES integers. + */ +static void message_to_indices(uint32_t *indices, const unsigned char *m) { + unsigned int i, j; + unsigned int offset = 0; + + for (i = 0; i < SPX_FORS_TREES; i++) { + indices[i] = 0; + for (j = 0; j < SPX_FORS_HEIGHT; j++) { + indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); + offset++; + } + } +} + +/** + * Signs a message m, deriving the secret key from sk_seed and the FTS address. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + uint32_t fors_tree_addr[8] = {0}; + struct fors_gen_leaf_info fors_info = {0}; + uint32_t *fors_leaf_addr = fors_info.leaf_addrx; + uint32_t fors_pk_addr[8] = {0}; + uint32_t idx_offset; + unsigned int i; + + copy_keypair_addr(fors_tree_addr, fors_addr); + copy_keypair_addr(fors_leaf_addr, fors_addr); + + copy_keypair_addr(fors_pk_addr, fors_addr); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); + + message_to_indices(indices, m); + + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); + + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); + + /* Include the secret key part that produces the selected leaf node. */ + fors_gen_sk(sig, ctx, fors_tree_addr); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + sig += SPX_N; + + /* Compute the authentication path for this leaf node. */ + treehashx1(roots + i * SPX_N, sig, ctx, + indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx1, + fors_tree_addr, &fors_info); + + sig += SPX_N * SPX_FORS_HEIGHT; + } + + /* Hash horizontally across all tree roots to derive the public key. */ + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); +} + +/** + * Derives the FORS public key from a signature. + * This can be used for verification by comparing to a known public key, or to + * subsequently verify a signature on the derived public key. The latter is the + * typical use-case when used as an FTS below an OTS in a hypertree. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + unsigned char leaf[SPX_N]; + uint32_t fors_tree_addr[8] = {0}; + uint32_t fors_pk_addr[8] = {0}; + uint32_t idx_offset; + unsigned int i; + + copy_keypair_addr(fors_tree_addr, fors_addr); + copy_keypair_addr(fors_pk_addr, fors_addr); + + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); + + message_to_indices(indices, m); + + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); + + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + + /* Derive the leaf from the included secret key part. */ + fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); + sig += SPX_N; + + /* Derive the corresponding root node of this tree. */ + compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, + sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); + sig += SPX_N * SPX_FORS_HEIGHT; + } + + /* Hash horizontally across all tree roots to derive the public key. */ + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_clean/fors.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_clean/fors.h new file mode 100644 index 0000000000..509140a178 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_clean/fors.h @@ -0,0 +1,32 @@ +#ifndef SPX_FORS_H +#define SPX_FORS_H + +#include + +#include "context.h" +#include "params.h" + +/** + * Signs a message m, deriving the secret key from sk_seed and the FTS address. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +#define fors_sign SPX_NAMESPACE(fors_sign) +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); + +/** + * Derives the FORS public key from a signature. + * This can be used for verification by comparing to a known public key, or to + * subsequently verify a signature on the derived public key. The latter is the + * typical use-case when used as an FTS below an OTS in a hypertree. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_clean/hash.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_clean/hash.h new file mode 100644 index 0000000000..f7c87d4c3c --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_clean/hash.h @@ -0,0 +1,28 @@ +#ifndef SPX_HASH_H +#define SPX_HASH_H + +#include +#include + +#include "context.h" +#include "params.h" + +#define prf_addr SPX_NAMESPACE(prf_addr) +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]); + +#define gen_message_random SPX_NAMESPACE(gen_message_random) +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); + +#define hash_message SPX_NAMESPACE(hash_message) +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); + + + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_clean/hash_shake.c b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_clean/hash_shake.c new file mode 100644 index 0000000000..ff5e7ec918 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_clean/hash_shake.c @@ -0,0 +1,83 @@ +#include +#include + +#include "hash.h" + +#include "address.h" +#include "fips202.h" +#include "params.h" +#include "utils.h" + +/* + * Computes PRF(pk_seed, sk_seed, addr) + */ +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]) { + unsigned char buf[2 * SPX_N + SPX_ADDR_BYTES]; + + memcpy(buf, ctx->pub_seed, SPX_N); + memcpy(buf + SPX_N, addr, SPX_ADDR_BYTES); + memcpy(buf + SPX_N + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); + + shake256(out, SPX_N, buf, 2 * SPX_N + SPX_ADDR_BYTES); +} + +/** + * Computes the message-dependent randomness R, using a secret seed and an + * optional randomization value as well as the message. + */ +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { + (void)ctx; + shake256incctx s_inc; + + shake256_inc_init(&s_inc); + shake256_inc_absorb(&s_inc, sk_prf, SPX_N); + shake256_inc_absorb(&s_inc, optrand, SPX_N); + shake256_inc_absorb(&s_inc, m, mlen); + shake256_inc_finalize(&s_inc); + shake256_inc_squeeze(R, SPX_N, &s_inc); + shake256_inc_ctx_release(&s_inc); +} + +/** + * Computes the message hash using R, the public key, and the message. + * Outputs the message digest and the index of the leaf. The index is split in + * the tree index and the leaf index, for convenient copying to an address. + */ +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { + (void)ctx; +#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) +#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) +#define SPX_LEAF_BITS SPX_TREE_HEIGHT +#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) +#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) + + unsigned char buf[SPX_DGST_BYTES]; + unsigned char *bufp = buf; + shake256incctx s_inc; + + shake256_inc_init(&s_inc); + shake256_inc_absorb(&s_inc, R, SPX_N); + shake256_inc_absorb(&s_inc, pk, SPX_PK_BYTES); + shake256_inc_absorb(&s_inc, m, mlen); + shake256_inc_finalize(&s_inc); + shake256_inc_squeeze(buf, SPX_DGST_BYTES, &s_inc); + shake256_inc_ctx_release(&s_inc); + + memcpy(digest, bufp, SPX_FORS_MSG_BYTES); + bufp += SPX_FORS_MSG_BYTES; + + + *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); + *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); + bufp += SPX_TREE_BYTES; + + *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); + *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_clean/merkle.c b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_clean/merkle.c new file mode 100644 index 0000000000..0c1479fd93 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_clean/merkle.c @@ -0,0 +1,59 @@ +#include +#include + +#include "address.h" +#include "merkle.h" +#include "params.h" +#include "utils.h" +#include "utilsx1.h" +#include "wots.h" +#include "wotsx1.h" + +/* + * This generates a Merkle signature (WOTS signature followed by the Merkle + * authentication path). This is in this file because most of the complexity + * is involved with the WOTS signature; the Merkle authentication path logic + * is mostly hidden in treehashx4 + */ +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf) { + unsigned char *auth_path = sig + SPX_WOTS_BYTES; + struct leaf_info_x1 info = { 0 }; + unsigned steps[ SPX_WOTS_LEN ]; + + info.wots_sig = sig; + chain_lengths(steps, root); + info.wots_steps = steps; + + set_type(&tree_addr[0], SPX_ADDR_TYPE_HASHTREE); + set_type(&info.pk_addr[0], SPX_ADDR_TYPE_WOTSPK); + copy_subtree_addr(&info.leaf_addr[0], wots_addr); + copy_subtree_addr(&info.pk_addr[0], wots_addr); + + info.wots_sign_leaf = idx_leaf; + + treehashx1(root, auth_path, ctx, + idx_leaf, 0, + SPX_TREE_HEIGHT, + wots_gen_leafx1, + tree_addr, &info); +} + +/* Compute root node of the top-most subtree. */ +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { + /* We do not need the auth path in key generation, but it simplifies the + code to have just one treehash routine that computes both root and path + in one function. */ + unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; + uint32_t top_tree_addr[8] = {0}; + uint32_t wots_addr[8] = {0}; + + set_layer_addr(top_tree_addr, SPX_D - 1); + set_layer_addr(wots_addr, SPX_D - 1); + + merkle_sign(auth_path, root, ctx, + wots_addr, top_tree_addr, + (uint32_t)~0 /* ~0 means "don't bother generating an auth path */ ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_clean/merkle.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_clean/merkle.h new file mode 100644 index 0000000000..769cf2e970 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_clean/merkle.h @@ -0,0 +1,21 @@ +#ifndef MERKLE_H_ +#define MERKLE_H_ + +#include + +#include "context.h" +#include "params.h" + +/* Generate a Merkle signature (WOTS signature followed by the Merkle */ +/* authentication path) */ +#define merkle_sign SPX_NAMESPACE(merkle_sign) +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf); + +/* Compute the root node of the top-most subtree. */ +#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); + +#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_clean/nistapi.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_clean/nistapi.h new file mode 100644 index 0000000000..3cb71afad4 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_clean/nistapi.h @@ -0,0 +1,87 @@ +#ifndef SPX_API_H +#define SPX_API_H + +#include +#include + +#include "params.h" + +#define CRYPTO_ALGNAME "SPHINCS+" + +#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES +#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES +#define CRYPTO_BYTES SPX_BYTES +#define CRYPTO_SEEDBYTES (3*SPX_N) + +/* + * Returns the length of a secret key, in bytes + */ +#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) +size_t crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) +size_t crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) +size_t crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) +size_t crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +#define crypto_sign SPX_NAMESPACE(crypto_sign) +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_clean/params.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_clean/params.h new file mode 100644 index 0000000000..10dfc4a345 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_clean/params.h @@ -0,0 +1,56 @@ +#ifndef SPX_PARAMS_H +#define SPX_PARAMS_H + +#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSSHAKE256FSIMPLE_CLEAN_##s + +/* Hash output length in bytes. */ +#define SPX_N 32 +/* Height of the hypertree. */ +#define SPX_FULL_HEIGHT 68 +/* Number of subtree layer. */ +#define SPX_D 17 +/* FORS tree dimensions. */ +#define SPX_FORS_HEIGHT 9 +#define SPX_FORS_TREES 35 +/* Winternitz parameter, */ +#define SPX_WOTS_W 16 + +/* The hash function is defined by linking a different hash.c file, as opposed + to setting a #define constant. */ + +/* For clarity */ +#define SPX_ADDR_BYTES 32 + +/* WOTS parameters. */ +#define SPX_WOTS_LOGW 4 + +#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) + +/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ +#define SPX_WOTS_LEN2 3 + +#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) +#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) +#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES + +/* Subtree size. */ +#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) + +//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT +// #error SPX_D should always divide SPX_FULL_HEIGHT +//#endif + +/* FORS parameters. */ +#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) +#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) +#define SPX_FORS_PK_BYTES SPX_N + +/* Resulting SPX sizes. */ +#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ + SPX_FULL_HEIGHT * SPX_N) +#define SPX_PK_BYTES (2 * SPX_N) +#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) + +#include "shake_offsets.h" + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_clean/shake_offsets.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_clean/shake_offsets.h new file mode 100644 index 0000000000..6b28d95d91 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_clean/shake_offsets.h @@ -0,0 +1,21 @@ +#ifndef SHAKE_OFFSETS_H_ +#define SHAKE_OFFSETS_H_ + +/* + * Offsets of various fields in the address structure when we use SHAKE as + * the Sphincs+ hash function + */ + +#define SPX_OFFSET_LAYER 3 /* The byte used to specify the Merkle tree layer */ +#define SPX_OFFSET_TREE 8 /* The start of the 8 byte field used to specify the tree */ +#define SPX_OFFSET_TYPE 19 /* The byte used to specify the hash type (reason) */ +#define SPX_OFFSET_KP_ADDR2 22 /* The high byte used to specify the key pair (which one-time signature) */ +#define SPX_OFFSET_KP_ADDR1 23 /* The low byte used to specify the key pair */ +#define SPX_OFFSET_CHAIN_ADDR 27 /* The byte used to specify the chain address (which Winternitz chain) */ +#define SPX_OFFSET_HASH_ADDR 31 /* The byte used to specify the hash address (where in the Winternitz chain) */ +#define SPX_OFFSET_TREE_HGT 27 /* The byte used to specify the height of this node in the FORS or Merkle tree */ +#define SPX_OFFSET_TREE_INDEX 28 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ + +#define SPX_SHAKE 1 + +#endif /* SHAKE_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_clean/sign.c b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_clean/sign.c new file mode 100644 index 0000000000..9d0c7d1b22 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_clean/sign.c @@ -0,0 +1,286 @@ +#include +#include +#include + +#include "address.h" +#include "context.h" +#include "fors.h" +#include "hash.h" +#include "merkle.h" +#include "nistapi.h" +#include "params.h" +#include "randombytes.h" +#include "thash.h" +#include "utils.h" +#include "wots.h" + +/* + * Returns the length of a secret key, in bytes + */ +size_t crypto_sign_secretkeybytes(void) { + return CRYPTO_SECRETKEYBYTES; +} + +/* + * Returns the length of a public key, in bytes + */ +size_t crypto_sign_publickeybytes(void) { + return CRYPTO_PUBLICKEYBYTES; +} + +/* + * Returns the length of a signature, in bytes + */ +size_t crypto_sign_bytes(void) { + return CRYPTO_BYTES; +} + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +size_t crypto_sign_seedbytes(void) { + return CRYPTO_SEEDBYTES; +} + +/* + * Generates an SPX key pair given a seed of length + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [PUB_SEED || root] + */ +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed) { + spx_ctx ctx; + + /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ + memcpy(sk, seed, CRYPTO_SEEDBYTES); + + memcpy(pk, sk + 2 * SPX_N, SPX_N); + + memcpy(ctx.pub_seed, pk, SPX_N); + memcpy(ctx.sk_seed, sk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + /* Compute root node of the top-most subtree. */ + merkle_gen_root(sk + 3 * SPX_N, &ctx); + + // cleanup + free_hash_function(&ctx); + + memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); + + return 0; +} + +/* + * Generates an SPX key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [PUB_SEED || root] + */ +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { + uint8_t seed[CRYPTO_SEEDBYTES]; + randombytes(seed, CRYPTO_SEEDBYTES); + crypto_sign_seed_keypair(pk, sk, seed); + + return 0; +} + +/** + * Returns an array containing a detached signature. + */ +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk) { + spx_ctx ctx; + + const uint8_t *sk_prf = sk + SPX_N; + const uint8_t *pk = sk + 2 * SPX_N; + + uint8_t optrand[SPX_N]; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t root[SPX_N]; + uint32_t i; + uint64_t tree; + uint32_t idx_leaf; + uint32_t wots_addr[8] = {0}; + uint32_t tree_addr[8] = {0}; + + memcpy(ctx.sk_seed, sk, SPX_N); + memcpy(ctx.pub_seed, pk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + + /* Optionally, signing can be made non-deterministic using optrand. + This can help counter side-channel attacks that would benefit from + getting a large number of traces when the signer uses the same nodes. */ + randombytes(optrand, SPX_N); + /* Compute the digest randomization value. */ + gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); + + /* Derive the message digest and leaf index from R, PK and M. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; + + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); + + /* Sign the message hash using FORS. */ + fors_sign(sig, root, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); + sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; + + /* Update the indices for the next layer. */ + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; + } + + free_hash_function(&ctx); + + *siglen = SPX_BYTES; + + return 0; +} + +/** + * Verifies a detached signature and message under a given public key. + */ +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk) { + spx_ctx ctx; + const uint8_t *pub_root = pk + SPX_N; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t wots_pk[SPX_WOTS_BYTES]; + uint8_t root[SPX_N]; + uint8_t leaf[SPX_N]; + unsigned int i; + uint64_t tree; + uint32_t idx_leaf; + uint32_t wots_addr[8] = {0}; + uint32_t tree_addr[8] = {0}; + uint32_t wots_pk_addr[8] = {0}; + + if (siglen != SPX_BYTES) { + return -1; + } + + memcpy(ctx.pub_seed, pk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); + + /* Derive the message digest and leaf index from R || PK || M. */ + /* The additional SPX_N is a result of the hash domain separator. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; + + /* Layer correctly defaults to 0, so no need to set_layer_addr */ + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); + + fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + /* For each subtree.. */ + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + copy_keypair_addr(wots_pk_addr, wots_addr); + + /* The WOTS public key is only correct if the signature was correct. */ + /* Initially, root is the FORS pk, but on subsequent iterations it is + the root of the subtree below the currently processed subtree. */ + wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); + sig += SPX_WOTS_BYTES; + + /* Compute the leaf node using the WOTS public key. */ + thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); + + /* Compute the root node of this subtree. */ + compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, + &ctx, tree_addr); + sig += SPX_TREE_HEIGHT * SPX_N; + + /* Update the indices for the next layer. */ + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; + } + + // cleanup + free_hash_function(&ctx); + + /* Check if the root node equals the root node in the public key. */ + if (memcmp(root, pub_root, SPX_N) != 0) { + return -1; + } + + return 0; +} + + +/** + * Returns an array containing the signature followed by the message. + */ +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk) { + size_t siglen; + + crypto_sign_signature(sm, &siglen, m, mlen, sk); + + memmove(sm + SPX_BYTES, m, mlen); + *smlen = siglen + mlen; + + return 0; +} + +/** + * Verifies a given signature-message pair under a given public key. + */ +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk) { + /* The API caller does not necessarily know what size a signature should be + but SPHINCS+ signatures are always exactly SPX_BYTES. */ + if (smlen < SPX_BYTES) { + memset(m, 0, smlen); + *mlen = 0; + return -1; + } + + *mlen = smlen - SPX_BYTES; + + if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { + memset(m, 0, smlen); + *mlen = 0; + return -1; + } + + /* If verification was successful, move the message to the right place. */ + memmove(m, sm + SPX_BYTES, *mlen); + + return 0; +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_clean/thash.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_clean/thash.h new file mode 100644 index 0000000000..8687ccfb4d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_clean/thash.h @@ -0,0 +1,13 @@ +#ifndef SPX_THASH_H +#define SPX_THASH_H + +#include "context.h" +#include "params.h" + +#include + +#define thash SPX_NAMESPACE(thash) +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_clean/thash_shake_simple.c b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_clean/thash_shake_simple.c new file mode 100644 index 0000000000..98470395e9 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_clean/thash_shake_simple.c @@ -0,0 +1,24 @@ +#include +#include + +#include "thash.h" + +#include "address.h" +#include "params.h" +#include "utils.h" + +#include "fips202.h" + +/** + * Takes an array of inblocks concatenated arrays of SPX_N bytes. + */ +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]) { + PQCLEAN_VLA(uint8_t, buf, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); + + memcpy(buf, ctx->pub_seed, SPX_N); + memcpy(buf + SPX_N, addr, SPX_ADDR_BYTES); + memcpy(buf + SPX_N + SPX_ADDR_BYTES, in, inblocks * SPX_N); + + shake256(out, SPX_N, buf, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_clean/utils.c b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_clean/utils.c new file mode 100644 index 0000000000..177b541fb9 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_clean/utils.c @@ -0,0 +1,148 @@ +#include + +#include "utils.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "thash.h" + +/** + * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. + */ +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in) { + int i; + + /* Iterate over out in decreasing order, for big-endianness. */ + for (i = (signed int)outlen - 1; i >= 0; i--) { + out[i] = in & 0xff; + in = in >> 8; + } +} + +void u32_to_bytes(unsigned char *out, uint32_t in) { + out[0] = (unsigned char)(in >> 24); + out[1] = (unsigned char)(in >> 16); + out[2] = (unsigned char)(in >> 8); + out[3] = (unsigned char)in; +} + +/** + * Converts the inlen bytes in 'in' from big-endian byte order to an integer. + */ +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { + unsigned long long retval = 0; + unsigned int i; + + for (i = 0; i < inlen; i++) { + retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); + } + return retval; +} + +/** + * Computes a root node given a leaf and an auth path. + * Expects address to be complete other than the tree_height and tree_index. + */ +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]) { + uint32_t i; + unsigned char buffer[2 * SPX_N]; + + /* If leaf_idx is odd (last bit = 1), current path element is a right child + and auth_path has to go left. Otherwise it is the other way around. */ + if (leaf_idx & 1) { + memcpy(buffer + SPX_N, leaf, SPX_N); + memcpy(buffer, auth_path, SPX_N); + } else { + memcpy(buffer, leaf, SPX_N); + memcpy(buffer + SPX_N, auth_path, SPX_N); + } + auth_path += SPX_N; + + for (i = 0; i < tree_height - 1; i++) { + leaf_idx >>= 1; + idx_offset >>= 1; + /* Set the address of the node we're creating. */ + set_tree_height(addr, i + 1); + set_tree_index(addr, leaf_idx + idx_offset); + + /* Pick the right or left neighbor, depending on parity of the node. */ + if (leaf_idx & 1) { + thash(buffer + SPX_N, buffer, 2, ctx, addr); + memcpy(buffer, auth_path, SPX_N); + } else { + thash(buffer, buffer, 2, ctx, addr); + memcpy(buffer + SPX_N, auth_path, SPX_N); + } + auth_path += SPX_N; + } + + /* The last iteration is exceptional; we do not copy an auth_path node. */ + leaf_idx >>= 1; + idx_offset >>= 1; + set_tree_height(addr, tree_height); + set_tree_index(addr, leaf_idx + idx_offset); + thash(root, buffer, 2, ctx, addr); +} + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx * /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]) { + PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); + PQCLEAN_VLA(unsigned int, heights, tree_height + 1); + unsigned int offset = 0; + uint32_t idx; + uint32_t tree_idx; + + for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { + /* Add the next leaf node to the stack. */ + gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); + offset++; + heights[offset - 1] = 0; + + /* If this is a node we need for the auth path.. */ + if ((leaf_idx ^ 0x1) == idx) { + memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); + } + + /* While the top-most nodes are of equal height.. */ + while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { + /* Compute index of the new node, in the next layer. */ + tree_idx = (idx >> (heights[offset - 1] + 1)); + + /* Set the address of the node we're creating. */ + set_tree_height(tree_addr, heights[offset - 1] + 1); + set_tree_index(tree_addr, + tree_idx + (idx_offset >> (heights[offset - 1] + 1))); + /* Hash the top-most nodes from the stack together. */ + thash(stack + (offset - 2)*SPX_N, + stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); + offset--; + /* Note that the top-most node is now one layer higher. */ + heights[offset - 1]++; + + /* If this is a node we need for the auth path.. */ + if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { + memcpy(auth_path + heights[offset - 1]*SPX_N, + stack + (offset - 1)*SPX_N, SPX_N); + } + } + } + memcpy(root, stack, SPX_N); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_clean/utils.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_clean/utils.h new file mode 100644 index 0000000000..64f5d5a53a --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_clean/utils.h @@ -0,0 +1,58 @@ +#ifndef SPX_UTILS_H +#define SPX_UTILS_H + +#include + +#include "compat.h" +#include "context.h" +#include "params.h" + + +/* To support MSVC use alloca() instead of VLAs. See #20. */ + + +/** + * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. + */ +#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in); +#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) +void u32_to_bytes(unsigned char *out, uint32_t in); + +/** + * Converts the inlen bytes in 'in' from big-endian byte order to an integer. + */ +#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); + +/** + * Computes a root node given a leaf and an auth path. + * Expects address to be complete other than the tree_height and tree_index. + */ +#define compute_root SPX_NAMESPACE(compute_root) +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]); + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +#define treehash SPX_NAMESPACE(treehash) +void treehash(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx *ctx /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]); + + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_clean/utilsx1.c b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_clean/utilsx1.c new file mode 100644 index 0000000000..fccb69b35d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_clean/utilsx1.c @@ -0,0 +1,100 @@ +#include + +#include "utilsx1.h" + +#include "address.h" +#include "params.h" +#include "thash.h" +#include "utils.h" + +/* + * Generate the entire Merkle tree, computing the authentication path for + * leaf_idx, and the resulting root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) + * + * This expects tree_addr to be initialized to the addr structures for the + * Merkle tree nodes + * + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + * + * This works by using the standard Merkle tree building algorithm, + */ +void treehashx1(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, + uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* Where to write the leaves */, + const spx_ctx * /* ctx */, + uint32_t idx, void *info), + uint32_t tree_addr[8], + void *info) { + /* This is where we keep the intermediate nodes */ + PQCLEAN_VLA(uint8_t, stack, tree_height * SPX_N); + + uint32_t idx; + uint32_t max_idx = (uint32_t)((1 << tree_height) - 1); + for (idx = 0;; idx++) { + unsigned char current[2 * SPX_N]; /* Current logical node is at */ + /* index[SPX_N]. We do this to minimize the number of copies */ + /* needed during a thash */ + gen_leaf( ¤t[SPX_N], ctx, idx + idx_offset, + info ); + + /* Now combine the freshly generated right node with previously */ + /* generated left ones */ + uint32_t internal_idx_offset = idx_offset; + uint32_t internal_idx = idx; + uint32_t internal_leaf = leaf_idx; + uint32_t h; /* The height we are in the Merkle tree */ + for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { + + /* Check if we hit the top of the tree */ + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[SPX_N], SPX_N ); + return; + } + + /* + * Check if the node we have is a part of the + * authentication path; if it is, write it out + */ + if ((internal_idx ^ internal_leaf) == 0x01) { + memcpy( &auth_path[ h * SPX_N ], + ¤t[SPX_N], + SPX_N ); + } + + /* + * Check if we're at a left child; if so, stop going up the stack + * Exception: if we've reached the end of the tree, keep on going + * (so we combine the last 4 nodes into the one root node in two + * more iterations) + */ + if ((internal_idx & 1) == 0 && idx < max_idx) { + break; + } + + /* Ok, we're at a right node */ + /* Now combine the left and right logical nodes together */ + + /* Set the address of the node we're creating. */ + internal_idx_offset >>= 1; + set_tree_height(tree_addr, h + 1); + set_tree_index(tree_addr, internal_idx / 2 + internal_idx_offset ); + + unsigned char *left = &stack[h * SPX_N]; + memcpy( ¤t[0], left, SPX_N ); + thash( ¤t[1 * SPX_N], + ¤t[0 * SPX_N], + 2, ctx, tree_addr); + } + + /* We've hit a left child; save the current for when we get the */ + /* corresponding right right */ + memcpy( &stack[h * SPX_N], ¤t[SPX_N], SPX_N); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_clean/utilsx1.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_clean/utilsx1.h new file mode 100644 index 0000000000..e911d17d53 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_clean/utilsx1.h @@ -0,0 +1,27 @@ +#ifndef SPX_UTILSX4_H +#define SPX_UTILSX4_H + +#include + +#include "context.h" +#include "params.h" + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +#define treehashx1 SPX_NAMESPACE(treehashx1) +void treehashx1(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* Where to write the leaf */, + const spx_ctx * /* ctx */, + uint32_t addr_idx, void *info), + uint32_t tree_addrx4[8], void *info); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_clean/wots.c b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_clean/wots.c new file mode 100644 index 0000000000..249717aaa8 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_clean/wots.c @@ -0,0 +1,108 @@ +#include +#include + +#include "wots.h" +#include "wotsx1.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "thash.h" +#include "utils.h" +#include "utilsx1.h" + +// TODO clarify address expectations, and make them more uniform. +// TODO i.e. do we expect types to be set already? +// TODO and do we expect modifications or copies? + +/** + * Computes the chaining function. + * out and in have to be n-byte arrays. + * + * Interprets in as start-th value of the chain. + * addr has to contain the address of the chain. + */ +static void gen_chain(unsigned char *out, const unsigned char *in, + unsigned int start, unsigned int steps, + const spx_ctx *ctx, uint32_t addr[8]) { + uint32_t i; + + /* Initialize out with the value at position 'start'. */ + memcpy(out, in, SPX_N); + + /* Iterate 'steps' calls to the hash function. */ + for (i = start; i < (start + steps) && i < SPX_WOTS_W; i++) { + set_hash_addr(addr, i); + thash(out, out, 1, ctx, addr); + } +} + +/** + * base_w algorithm as described in draft. + * Interprets an array of bytes as integers in base w. + * This only works when log_w is a divisor of 8. + */ +static void base_w(unsigned int *output, const int out_len, + const unsigned char *input) { + int in = 0; + int out = 0; + unsigned char total = 0; + int bits = 0; + int consumed; + + for (consumed = 0; consumed < out_len; consumed++) { + if (bits == 0) { + total = input[in]; + in++; + bits += 8; + } + bits -= SPX_WOTS_LOGW; + output[out] = (total >> bits) & (SPX_WOTS_W - 1); + out++; + } +} + +/* Computes the WOTS+ checksum over a message (in base_w). */ +static void wots_checksum(unsigned int *csum_base_w, + const unsigned int *msg_base_w) { + unsigned int csum = 0; + unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; + unsigned int i; + + /* Compute checksum. */ + for (i = 0; i < SPX_WOTS_LEN1; i++) { + csum += SPX_WOTS_W - 1 - msg_base_w[i]; + } + + /* Convert checksum to base_w. */ + /* Make sure expected empty zero bits are the least significant bits. */ + csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); + ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); + base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); +} + +/* Takes a message and derives the matching chain lengths. */ +void chain_lengths(unsigned int *lengths, const unsigned char *msg) { + base_w(lengths, SPX_WOTS_LEN1, msg); + wots_checksum(lengths + SPX_WOTS_LEN1, lengths); +} + +/** + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. + * + * Writes the computed public key to 'pk'. + */ +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]) { + unsigned int lengths[SPX_WOTS_LEN]; + uint32_t i; + + chain_lengths(lengths, msg); + + for (i = 0; i < SPX_WOTS_LEN; i++) { + set_chain_addr(addr, i); + gen_chain(pk + i * SPX_N, sig + i * SPX_N, + lengths[i], SPX_WOTS_W - 1 - lengths[i], ctx, addr); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_clean/wots.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_clean/wots.h new file mode 100644 index 0000000000..4e7692eeef --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_clean/wots.h @@ -0,0 +1,25 @@ +#ifndef SPX_WOTS_H +#define SPX_WOTS_H + +#include + +#include "context.h" +#include "params.h" + +/** + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. + * + * Writes the computed public key to 'pk'. + */ +#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]); + +/* + * Compute the chain lengths needed for a given message hash + */ +#define chain_lengths SPX_NAMESPACE(chain_lengths) +void chain_lengths(unsigned int *lengths, const unsigned char *msg); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_clean/wotsx1.c b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_clean/wotsx1.c new file mode 100644 index 0000000000..3adec78dfb --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_clean/wotsx1.c @@ -0,0 +1,76 @@ +#include +#include + +#include "wots.h" +#include "wotsx1.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "thash.h" +#include "utils.h" + +/* + * This generates a WOTS public key + * It also generates the WOTS signature if leaf_info indicates + * that we're signing with this WOTS key + */ +void wots_gen_leafx1(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info) { + struct leaf_info_x1 *info = v_info; + uint32_t *leaf_addr = info->leaf_addr; + uint32_t *pk_addr = info->pk_addr; + unsigned int i, k; + unsigned char pk_buffer[ SPX_WOTS_BYTES ]; + unsigned char *buffer; + uint32_t wots_k_mask; + + if (leaf_idx == info->wots_sign_leaf) { + /* We're traversing the leaf that's signing; generate the WOTS */ + /* signature */ + wots_k_mask = 0; + } else { + /* Nope, we're just generating pk's; turn off the signature logic */ + wots_k_mask = (uint32_t)~0; + } + + set_keypair_addr( leaf_addr, leaf_idx ); + set_keypair_addr( pk_addr, leaf_idx ); + + for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { + uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k to */ + /* the step if we're generating a signature, ~0 if we're not */ + + /* Start with the secret seed */ + set_chain_addr(leaf_addr, i); + set_hash_addr(leaf_addr, 0); + set_type(leaf_addr, SPX_ADDR_TYPE_WOTSPRF); + + prf_addr(buffer, ctx, leaf_addr); + + set_type(leaf_addr, SPX_ADDR_TYPE_WOTS); + + /* Iterate down the WOTS chain */ + for (k = 0;; k++) { + /* Check if this is the value that needs to be saved as a */ + /* part of the WOTS signature */ + if (k == wots_k) { + memcpy( info->wots_sig + i * SPX_N, buffer, SPX_N ); + } + + /* Check if we hit the top of the chain */ + if (k == SPX_WOTS_W - 1) { + break; + } + + /* Iterate one step on the chain */ + set_hash_addr(leaf_addr, k); + + thash(buffer, buffer, 1, ctx, leaf_addr); + } + } + + /* Do the final thash to generate the public keys */ + thash(dest, pk_buffer, SPX_WOTS_LEN, ctx, pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_clean/wotsx1.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_clean/wotsx1.h new file mode 100644 index 0000000000..e617929f96 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_clean/wotsx1.h @@ -0,0 +1,39 @@ +#ifndef WOTSX1_H_ +#define WOTSX1_H_ + +#include + +#include "context.h" +#include "params.h" + +/* + * This is here to provide an interface to the internal wots_gen_leafx1 + * routine. While this routine is not referenced in the package outside of + * wots.c, it is called from the stand-alone benchmark code to characterize + * the performance + */ +struct leaf_info_x1 { + unsigned char *wots_sig; + uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ + uint32_t *wots_steps; + uint32_t leaf_addr[8]; + uint32_t pk_addr[8]; +}; + +/* Macro to set the leaf_info to something 'benign', that is, it would */ +/* run with the same time as it does during the real signing process */ +/* Used only by the benchmark code */ +#define INITIALIZE_LEAF_INFO_X1(info, addr, step_buffer) { \ + (info).wots_sig = 0; \ + (info).wots_sign_leaf = ~0; \ + (info).wots_steps = step_buffer; \ + memcpy( &(info).leaf_addr[0], (addr), 32 ); \ + memcpy( &(info).pk_addr[0], (addr), 32 ); \ + } + +#define wots_gen_leafx1 SPX_NAMESPACE(wots_gen_leafx1) +void wots_gen_leafx1(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info); + +#endif /* WOTSX1_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/LICENSE b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/LICENSE new file mode 100644 index 0000000000..670154e353 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/LICENSE @@ -0,0 +1,116 @@ +CC0 1.0 Universal + +Statement of Purpose + +The laws of most jurisdictions throughout the world automatically confer +exclusive Copyright and Related Rights (defined below) upon the creator and +subsequent owner(s) (each and all, an "owner") of an original work of +authorship and/or a database (each, a "Work"). + +Certain owners wish to permanently relinquish those rights to a Work for the +purpose of contributing to a commons of creative, cultural and scientific +works ("Commons") that the public can reliably and without fear of later +claims of infringement build upon, modify, incorporate in other works, reuse +and redistribute as freely as possible in any form whatsoever and for any +purposes, including without limitation commercial purposes. These owners may +contribute to the Commons to promote the ideal of a free culture and the +further production of creative, cultural and scientific works, or to gain +reputation or greater distribution for their Work in part through the use and +efforts of others. + +For these and/or other purposes and motivations, and without any expectation +of additional consideration or compensation, the person associating CC0 with a +Work (the "Affirmer"), to the extent that he or she is an owner of Copyright +and Related Rights in the Work, voluntarily elects to apply CC0 to the Work +and publicly distribute the Work under its terms, with knowledge of his or her +Copyright and Related Rights in the Work and the meaning and intended legal +effect of CC0 on those rights. + +1. Copyright and Related Rights. A Work made available under CC0 may be +protected by copyright and related or neighboring rights ("Copyright and +Related Rights"). Copyright and Related Rights include, but are not limited +to, the following: + + i. the right to reproduce, adapt, distribute, perform, display, communicate, + and translate a Work; + + ii. moral rights retained by the original author(s) and/or performer(s); + + iii. publicity and privacy rights pertaining to a person's image or likeness + depicted in a Work; + + iv. rights protecting against unfair competition in regards to a Work, + subject to the limitations in paragraph 4(a), below; + + v. rights protecting the extraction, dissemination, use and reuse of data in + a Work; + + vi. database rights (such as those arising under Directive 96/9/EC of the + European Parliament and of the Council of 11 March 1996 on the legal + protection of databases, and under any national implementation thereof, + including any amended or successor version of such directive); and + + vii. other similar, equivalent or corresponding rights throughout the world + based on applicable law or treaty, and any national implementations thereof. + +2. Waiver. To the greatest extent permitted by, but not in contravention of, +applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and +unconditionally waives, abandons, and surrenders all of Affirmer's Copyright +and Related Rights and associated claims and causes of action, whether now +known or unknown (including existing as well as future claims and causes of +action), in the Work (i) in all territories worldwide, (ii) for the maximum +duration provided by applicable law or treaty (including future time +extensions), (iii) in any current or future medium and for any number of +copies, and (iv) for any purpose whatsoever, including without limitation +commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes +the Waiver for the benefit of each member of the public at large and to the +detriment of Affirmer's heirs and successors, fully intending that such Waiver +shall not be subject to revocation, rescission, cancellation, termination, or +any other legal or equitable action to disrupt the quiet enjoyment of the Work +by the public as contemplated by Affirmer's express Statement of Purpose. + +3. Public License Fallback. Should any part of the Waiver for any reason be +judged legally invalid or ineffective under applicable law, then the Waiver +shall be preserved to the maximum extent permitted taking into account +Affirmer's express Statement of Purpose. In addition, to the extent the Waiver +is so judged Affirmer hereby grants to each affected person a royalty-free, +non transferable, non sublicensable, non exclusive, irrevocable and +unconditional license to exercise Affirmer's Copyright and Related Rights in +the Work (i) in all territories worldwide, (ii) for the maximum duration +provided by applicable law or treaty (including future time extensions), (iii) +in any current or future medium and for any number of copies, and (iv) for any +purpose whatsoever, including without limitation commercial, advertising or +promotional purposes (the "License"). The License shall be deemed effective as +of the date CC0 was applied by Affirmer to the Work. Should any part of the +License for any reason be judged legally invalid or ineffective under +applicable law, such partial invalidity or ineffectiveness shall not +invalidate the remainder of the License, and in such case Affirmer hereby +affirms that he or she will not (i) exercise any of his or her remaining +Copyright and Related Rights in the Work or (ii) assert any associated claims +and causes of action with respect to the Work, in either case contrary to +Affirmer's express Statement of Purpose. + +4. Limitations and Disclaimers. + + a. No trademark or patent rights held by Affirmer are waived, abandoned, + surrendered, licensed or otherwise affected by this document. + + b. Affirmer offers the Work as-is and makes no representations or warranties + of any kind concerning the Work, express, implied, statutory or otherwise, + including without limitation warranties of title, merchantability, fitness + for a particular purpose, non infringement, or the absence of latent or + other defects, accuracy, or the present or absence of errors, whether or not + discoverable, all to the greatest extent permissible under applicable law. + + c. Affirmer disclaims responsibility for clearing rights of other persons + that may apply to the Work or any use thereof, including without limitation + any person's Copyright and Related Rights in the Work. Further, Affirmer + disclaims responsibility for obtaining any necessary consents, permissions + or other rights required for any use of the Work. + + d. Affirmer understands and acknowledges that Creative Commons is not a + party to this document and has no duty or obligation with respect to this + CC0 or use of the Work. + +For more information, please see + diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/address.c b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/address.c new file mode 100644 index 0000000000..b956e9cb29 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/address.c @@ -0,0 +1,91 @@ +#include +#include + +#include "address.h" +#include "params.h" +#include "utils.h" + +/* + * Specify which level of Merkle tree (the "layer") we're working on + */ +void set_layer_addr(uint32_t addr[8], uint32_t layer) { + ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; +} + +/* + * Specify which Merkle tree within the level (the "tree address") we're working on + */ +void set_tree_addr(uint32_t addr[8], uint64_t tree) { + ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); +} + +/* + * Specify the reason we'll use this address structure for, that is, what + * hash will we compute with it. This is used so that unrelated types of + * hashes don't accidentally get the same address structure. The type will be + * one of the SPX_ADDR_TYPE constants + */ +void set_type(uint32_t addr[8], uint32_t type) { + ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; +} + +/* + * Copy the layer and tree fields of the address structure. This is used + * when we're doing multiple types of hashes within the same Merkle tree + */ +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); +} + +/* These functions are used for OTS addresses. */ + +/* + * Specify which Merkle leaf we're working on; that is, which OTS keypair + * we're talking about. + */ +void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { + ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; +} + +/* + * Copy the layer, tree and keypair fields of the address structure. This is + * used when we're doing multiple things within the same OTS keypair + */ +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); + ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; +} + +/* + * Specify which Merkle chain within the OTS we're working with + * (the chain address) + */ +void set_chain_addr(uint32_t addr[8], uint32_t chain) { + ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; +} + +/* + * Specify where in the Merkle chain we are +* (the hash address) + */ +void set_hash_addr(uint32_t addr[8], uint32_t hash) { + ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; +} + +/* These functions are used for all hash tree addresses (including FORS). */ + +/* + * Specify the height of the node in the Merkle/FORS tree we are in + * (the tree height) + */ +void set_tree_height(uint32_t addr[8], uint32_t tree_height) { + ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; +} + +/* + * Specify the distance from the left edge of the node in the Merkle/FORS tree + * (the tree index) + */ +void set_tree_index(uint32_t addr[8], uint32_t tree_index) { + u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/address.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/address.h new file mode 100644 index 0000000000..24a84eb40c --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/address.h @@ -0,0 +1,52 @@ +#ifndef SPX_ADDRESS_H +#define SPX_ADDRESS_H + +#include + +#include "params.h" + +/* The hash types that are passed to set_type */ +#define SPX_ADDR_TYPE_WOTS 0 +#define SPX_ADDR_TYPE_WOTSPK 1 +#define SPX_ADDR_TYPE_HASHTREE 2 +#define SPX_ADDR_TYPE_FORSTREE 3 +#define SPX_ADDR_TYPE_FORSPK 4 +#define SPX_ADDR_TYPE_WOTSPRF 5 +#define SPX_ADDR_TYPE_FORSPRF 6 + +#define set_layer_addr SPX_NAMESPACE(set_layer_addr) +void set_layer_addr(uint32_t addr[8], uint32_t layer); + +#define set_tree_addr SPX_NAMESPACE(set_tree_addr) +void set_tree_addr(uint32_t addr[8], uint64_t tree); + +#define set_type SPX_NAMESPACE(set_type) +void set_type(uint32_t addr[8], uint32_t type); + +/* Copies the layer and tree part of one address into the other */ +#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); + +/* These functions are used for WOTS and FORS addresses. */ + +#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) +void set_keypair_addr(uint32_t addr[8], uint32_t keypair); + +#define set_chain_addr SPX_NAMESPACE(set_chain_addr) +void set_chain_addr(uint32_t addr[8], uint32_t chain); + +#define set_hash_addr SPX_NAMESPACE(set_hash_addr) +void set_hash_addr(uint32_t addr[8], uint32_t hash); + +#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); + +/* These functions are used for all hash tree addresses (including FORS). */ + +#define set_tree_height SPX_NAMESPACE(set_tree_height) +void set_tree_height(uint32_t addr[8], uint32_t tree_height); + +#define set_tree_index SPX_NAMESPACE(set_tree_index) +void set_tree_index(uint32_t addr[8], uint32_t tree_index); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/api.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/api.h new file mode 100644 index 0000000000..9916e03a90 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/api.h @@ -0,0 +1,77 @@ +#ifndef PQCLEAN_SPHINCSSHAKE256SROBUST_AARCH64_API_H +#define PQCLEAN_SPHINCSSHAKE256SROBUST_AARCH64_API_H + +#include +#include + +#define PQCLEAN_SPHINCSSHAKE256SROBUST_AARCH64_CRYPTO_ALGNAME "SPHINCS+-shake-256s-robust" + +#define PQCLEAN_SPHINCSSHAKE256SROBUST_AARCH64_CRYPTO_SECRETKEYBYTES 128 +#define PQCLEAN_SPHINCSSHAKE256SROBUST_AARCH64_CRYPTO_PUBLICKEYBYTES 64 +#define PQCLEAN_SPHINCSSHAKE256SROBUST_AARCH64_CRYPTO_BYTES 29792 + +#define PQCLEAN_SPHINCSSHAKE256SROBUST_AARCH64_CRYPTO_SEEDBYTES 96 + +/* + * Returns the length of a secret key, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE256SROBUST_AARCH64_crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE256SROBUST_AARCH64_crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE256SROBUST_AARCH64_crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE256SROBUST_AARCH64_crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +int PQCLEAN_SPHINCSSHAKE256SROBUST_AARCH64_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +int PQCLEAN_SPHINCSSHAKE256SROBUST_AARCH64_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +int PQCLEAN_SPHINCSSHAKE256SROBUST_AARCH64_crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +int PQCLEAN_SPHINCSSHAKE256SROBUST_AARCH64_crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, + const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +int PQCLEAN_SPHINCSSHAKE256SROBUST_AARCH64_crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +int PQCLEAN_SPHINCSSHAKE256SROBUST_AARCH64_crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/context.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/context.h new file mode 100644 index 0000000000..6e0a33f3b7 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/context.h @@ -0,0 +1,19 @@ +#ifndef SPX_CONTEXT_H +#define SPX_CONTEXT_H + +#include + +#include "params.h" + +typedef struct { + uint8_t pub_seed[SPX_N]; + uint8_t sk_seed[SPX_N]; +} spx_ctx; + +#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) +void initialize_hash_function(spx_ctx *ctx); + +#define free_hash_function SPX_NAMESPACE(free_hash_function) +void free_hash_function(spx_ctx *ctx); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/context_shake.c b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/context_shake.c new file mode 100644 index 0000000000..9614a103d3 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/context_shake.c @@ -0,0 +1,12 @@ +#include "context.h" + +/* For SHAKE256, there is no immediate reason to initialize at the start, + so this function is an empty operation. */ +void initialize_hash_function(spx_ctx *ctx) { + (void)ctx; /* Suppress an 'unused parameter' warning. */ +} + +// in case the hash function api is heap-based. +void free_hash_function(spx_ctx *ctx) { + (void)ctx; +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/f1600x2.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/f1600x2.h new file mode 100644 index 0000000000..70d1af9f14 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/f1600x2.h @@ -0,0 +1,11 @@ +#ifndef SPX_F1600X2_H +#define SPX_F1600X2_H + +#include + +extern uint64_t f1600_RC[24]; +extern void _f1600x2(uint64_t *a, uint64_t *rc); + +#define f1600x2(s) do {_f1600x2((s), f1600_RC);} while(0) + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/f1600x2.s b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/f1600x2.s new file mode 100644 index 0000000000..640ed791ed --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/f1600x2.s @@ -0,0 +1,143 @@ +# From https://github.com/bwesterb/armed-keccak + +.macro round + # Execute theta, but without xoring into the state yet. + # Compute parities p[i] = a[i] ^ a[5+i] ^ ... ^ a[20+i]. + eor3.16b v25, v0, v5, v10 + eor3.16b v26, v1, v6, v11 + eor3.16b v27, v2, v7, v12 + eor3.16b v28, v3, v8, v13 + eor3.16b v29, v4, v9, v14 + + eor3.16b v25, v25, v15, v20 + eor3.16b v26, v26, v16, v21 + eor3.16b v27, v27, v17, v22 + eor3.16b v28, v28, v18, v23 + eor3.16b v29, v29, v19, v24 + + # d[0] = rotl(p[1], 1) ^ p[4] + rax1.2d v30, v29, v26 + # d[3] = rotl(p[4], 1) ^ p[2] + rax1.2d v29, v27, v29 + # d[1] = rotl(p[2], 1) ^ p[0] + rax1.2d v27, v25, v27 + # d[4] = rotl(p[0], 1) ^ p[3] + rax1.2d v25, v28, v25 + # d[2] = rotl(p[3], 1) ^ p[1] + rax1.2d v28, v26, v28 + + # Xor parities from step theta into the state at the same time + # as executing rho and pi. + eor.16b v0, v0, v30 + mov.16b v31, v1 + xar.2d v1, v6, v27, 20 + xar.2d v6, v9, v25, 44 + xar.2d v9, v22, v28, 3 + xar.2d v22, v14, v25, 25 + xar.2d v14, v20, v30, 46 + xar.2d v20, v2, v28, 2 + xar.2d v2, v12, v28, 21 + xar.2d v12, v13, v29, 39 + xar.2d v13, v19, v25, 56 + xar.2d v19, v23, v29, 8 + xar.2d v23, v15, v30, 23 + xar.2d v15, v4, v25, 37 + xar.2d v4, v24, v25, 50 + xar.2d v24, v21, v27, 62 + xar.2d v21, v8, v29, 9 + xar.2d v8, v16, v27, 19 + xar.2d v16, v5, v30, 28 + xar.2d v5, v3, v29, 36 + xar.2d v3, v18, v29, 43 + xar.2d v18, v17, v28, 49 + xar.2d v17, v11, v27, 54 + xar.2d v11, v7, v28, 58 + xar.2d v7, v10, v30, 61 + xar.2d v10, v31, v27, 63 + + # Chi + bcax.16b v25, v0, v2, v1 + bcax.16b v26, v1, v3, v2 + bcax.16b v2, v2, v4, v3 + bcax.16b v3, v3, v0, v4 + bcax.16b v4, v4, v1, v0 + mov.16b v0, v25 + mov.16b v1, v26 + + bcax.16b v25, v5, v7, v6 + bcax.16b v26, v6, v8, v7 + bcax.16b v7, v7, v9, v8 + bcax.16b v8, v8, v5, v9 + bcax.16b v9, v9, v6, v5 + mov.16b v5, v25 + mov.16b v6, v26 + + bcax.16b v25, v10, v12, v11 + bcax.16b v26, v11, v13, v12 + bcax.16b v12, v12, v14, v13 + bcax.16b v13, v13, v10, v14 + bcax.16b v14, v14, v11, v10 + mov.16b v10, v25 + mov.16b v11, v26 + + bcax.16b v25, v15, v17, v16 + bcax.16b v26, v16, v18, v17 + bcax.16b v17, v17, v19, v18 + bcax.16b v18, v18, v15, v19 + bcax.16b v19, v19, v16, v15 + mov.16b v15, v25 + mov.16b v16, v26 + + bcax.16b v25, v20, v22, v21 + bcax.16b v26, v21, v23, v22 + bcax.16b v22, v22, v24, v23 + bcax.16b v23, v23, v20, v24 + bcax.16b v24, v24, v21, v20 + mov.16b v20, v25 + mov.16b v21, v26 + + # iota + ld1r {v25.2d}, [x1], #8 + eor.16b v0, v0, v25 +.endm + +.align 4 +.global __f1600x2 +__f1600x2: + stp d8, d9, [sp,#-16]! + stp d10, d11, [sp,#-16]! + stp d12, d13, [sp,#-16]! + stp d14, d15, [sp,#-16]! + + mov x2, x0 + mov x3, #24 + + ld1.2d {v0, v1, v2, v3}, [x0], #64 + ld1.2d {v4, v5, v6, v7}, [x0], #64 + ld1.2d {v8, v9, v10, v11}, [x0], #64 + ld1.2d {v12, v13, v14, v15}, [x0], #64 + ld1.2d {v16, v17, v18, v19}, [x0], #64 + ld1.2d {v20, v21, v22, v23}, [x0], #64 + ld1.2d {v24}, [x0] + +loop: + round + + subs x3, x3, #1 + cbnz x3, loop + + mov x0, x2 + st1.2d {v0, v1, v2, v3}, [x0], #64 + st1.2d {v4, v5, v6, v7}, [x0], #64 + st1.2d {v8, v9, v10, v11}, [x0], #64 + st1.2d {v12, v13, v14, v15}, [x0], #64 + st1.2d {v16, v17, v18, v19}, [x0], #64 + st1.2d {v20, v21, v22, v23}, [x0], #64 + st1.2d {v24}, [x0] + + ldp d14, d15, [sp], #16 + ldp d12, d13, [sp], #16 + ldp d10, d11, [sp], #16 + ldp d8, d9, [sp], #16 + + ret lr diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/f1600x2_const.c b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/f1600x2_const.c new file mode 100644 index 0000000000..e49c0ba149 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/f1600x2_const.c @@ -0,0 +1,30 @@ +#include "f1600x2.h" + +uint64_t f1600_RC[24] = { + 0x0000000000000001, + 0x0000000000008082, + 0x800000000000808A, + 0x8000000080008000, + 0x000000000000808B, + 0x0000000080000001, + 0x8000000080008081, + 0x8000000000008009, + 0x000000000000008A, + 0x0000000000000088, + 0x0000000080008009, + 0x000000008000000A, + 0x000000008000808B, + 0x800000000000008B, + 0x8000000000008089, + 0x8000000000008003, + 0x8000000000008002, + 0x8000000000000080, + 0x000000000000800A, + 0x800000008000000A, + 0x8000000080008081, + 0x8000000000008080, + 0x0000000080000001, + 0x8000000080008008, +}; + + diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/fips202x2.c b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/fips202x2.c new file mode 100644 index 0000000000..4718c343bc --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/fips202x2.c @@ -0,0 +1,148 @@ +#include +#include + +#include "fips202x2.h" +#include "f1600x2.h" +#include "fips202.h" + +uint64_t load64(const unsigned char *x) { + unsigned long long r = 0, i; + + for (i = 0; i < 8; ++i) { + r |= (unsigned long long)x[i] << 8 * i; + } + return r; +} + +void store64(uint8_t *x, uint64_t u) { + unsigned int i; + + for (i = 0; i < 8; ++i) { + x[i] = (uint8_t)u; + u >>= 8; + } +} + +static void keccak_absorb2x(uint64_t *s, + unsigned int r, + const unsigned char *m0, + const unsigned char *m1, + unsigned long long int mlen, + unsigned char p) { + unsigned long long i; + unsigned char t0[200]; + unsigned char t1[200]; + + while (mlen >= r) { + for (i = 0; i < r / 8; ++i) { + s[2 * i + 0] ^= load64(m0 + 8 * i); + s[2 * i + 1] ^= load64(m1 + 8 * i); + } + + f1600x2(s); + mlen -= r; + m0 += r; + m1 += r; + } + + for (i = 0; i < r; ++i) { + t0[i] = 0; + t1[i] = 0; + } + for (i = 0; i < mlen; ++i) { + t0[i] = m0[i]; + t1[i] = m1[i]; + } + + t0[i] = p; + t1[i] = p; + + t0[r - 1] |= 128; + t1[r - 1] |= 128; + + for (i = 0; i < r / 8; ++i) { + s[2 * i + 0] ^= load64(t0 + 8 * i); + s[2 * i + 1] ^= load64(t1 + 8 * i); + } +} + + +static void keccak_squeezeblocks2x(unsigned char *h0, + unsigned char *h1, + unsigned long long int nblocks, + uint64_t *s, + unsigned int r) { + unsigned int i; + + while (nblocks > 0) { + f1600x2(s); + for (i = 0; i < (r >> 3); i++) { + store64(h0 + 8 * i, s[2 * i + 0]); + store64(h1 + 8 * i, s[2 * i + 1]); + } + h0 += r; + h1 += r; + nblocks--; + } +} + + + +void shake128x2(unsigned char *out0, + unsigned char *out1, + unsigned long long outlen, + unsigned char *in0, + unsigned char *in1, + unsigned long long inlen) { + uint64_t s[50] = {0}; + unsigned char t0[SHAKE128_RATE]; + unsigned char t1[SHAKE128_RATE]; + unsigned int i; + + /* absorb 4 message of identical length in parallel */ + keccak_absorb2x(s, SHAKE128_RATE, in0, in1, inlen, 0x1F); + + /* Squeeze output */ + keccak_squeezeblocks2x(out0, out1, outlen / SHAKE128_RATE, s, SHAKE128_RATE); + + out0 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; + out1 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; + + if (outlen % SHAKE128_RATE) { + keccak_squeezeblocks2x(t0, t1, 1, s, SHAKE128_RATE); + for (i = 0; i < outlen % SHAKE128_RATE; i++) { + out0[i] = t0[i]; + out1[i] = t1[i]; + } + } +} + + +void shake256x2(unsigned char *out0, + unsigned char *out1, + unsigned long long outlen, + unsigned char *in0, + unsigned char *in1, + unsigned long long inlen) { + uint64_t s[50] = {0}; + unsigned char t0[SHAKE256_RATE]; + unsigned char t1[SHAKE256_RATE]; + unsigned int i; + + /* absorb 2 message of identical length in parallel */ + keccak_absorb2x(s, SHAKE256_RATE, in0, in1, inlen, 0x1F); + + /* Squeeze output */ + keccak_squeezeblocks2x(out0, out1, outlen / SHAKE256_RATE, s, SHAKE256_RATE); + + out0 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; + out1 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; + + if (outlen % SHAKE256_RATE) { + keccak_squeezeblocks2x(t0, t1, 1, s, SHAKE256_RATE); + for (i = 0; i < outlen % SHAKE256_RATE; i++) { + out0[i] = t0[i]; + out1[i] = t1[i]; + } + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/fips202x2.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/fips202x2.h new file mode 100644 index 0000000000..7ba58b35d8 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/fips202x2.h @@ -0,0 +1,24 @@ +#ifndef SPX_FIPS202X2_H +#define SPX_FIPS202X2_H + +#include + +uint64_t load64(const unsigned char *x); +void store64(uint8_t *x, uint64_t u); + + +void shake128x2(unsigned char *out0, + unsigned char *out1, + unsigned long long outlen, + unsigned char *in0, + unsigned char *in1, + unsigned long long inlen); + +void shake256x2(unsigned char *out0, + unsigned char *out1, + unsigned long long outlen, + unsigned char *in0, + unsigned char *in1, + unsigned long long inlen); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/fors.c b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/fors.c new file mode 100644 index 0000000000..39193d04e2 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/fors.c @@ -0,0 +1,191 @@ +#include +#include +#include + +#include "fors.h" + +#include "address.h" +#include "hash.h" +#include "hashx2.h" +#include "thash.h" +#include "thashx2.h" +#include "utils.h" +#include "utilsx2.h" + +static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + prf_addr(sk, ctx, fors_leaf_addr); +} + +static void fors_gen_skx2(unsigned char *sk0, + unsigned char *sk1, + const spx_ctx *ctx, + uint32_t fors_leaf_addrx2[2 * 8]) { + prf_addrx2(sk0, sk1, + ctx, fors_leaf_addrx2); +} + +static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, + const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + thash(leaf, sk, 1, ctx, fors_leaf_addr); +} + +static void fors_sk_to_leafx2(unsigned char *leaf0, + unsigned char *leaf1, + const unsigned char *sk0, + const unsigned char *sk1, + const spx_ctx *ctx, + uint32_t fors_leaf_addrx2[2 * 8]) { + thashx2(leaf0, leaf1, + sk0, sk1, + 1, ctx, fors_leaf_addrx2); +} + +struct fors_gen_leaf_info { + uint32_t leaf_addrx[2 * 8]; +}; + +static void fors_gen_leafx2(unsigned char *leaf, + const spx_ctx *ctx, + uint32_t addr_idx, void *info) { + struct fors_gen_leaf_info *fors_info = info; + uint32_t *fors_leaf_addrx2 = fors_info->leaf_addrx; + unsigned int j; + + /* Only set the parts that the caller doesn't set */ + for (j = 0; j < 2; j++) { + set_tree_index(fors_leaf_addrx2 + j * 8, addr_idx + j); + set_type(fors_leaf_addrx2 + j * 8, SPX_ADDR_TYPE_FORSPRF); + } + + fors_gen_skx2(leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + ctx, fors_leaf_addrx2); + + for (j = 0; j < 2; j++) { + set_type(fors_leaf_addrx2 + j * 8, SPX_ADDR_TYPE_FORSTREE); + } + + fors_sk_to_leafx2(leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + ctx, fors_leaf_addrx2); +} + +/** + * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + * Assumes indices has space for SPX_FORS_TREES integers. + */ +static void message_to_indices(uint32_t *indices, const unsigned char *m) { + unsigned int i, j; + unsigned int offset = 0; + + for (i = 0; i < SPX_FORS_TREES; i++) { + indices[i] = 0; + for (j = 0; j < SPX_FORS_HEIGHT; j++) { + indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); + offset++; + } + } +} + +/** + * Signs a message m, deriving the secret key from sk_seed and the FTS address. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + uint32_t fors_tree_addr[2 * 8] = {0}; + struct fors_gen_leaf_info fors_info = {0}; + uint32_t *fors_leaf_addr = fors_info.leaf_addrx; + uint32_t fors_pk_addr[8] = {0}; + uint32_t idx_offset; + unsigned int i; + + for (i = 0; i < 2; i++) { + copy_keypair_addr(fors_tree_addr + 8 * i, fors_addr); + set_type(fors_tree_addr + 8 * i, SPX_ADDR_TYPE_FORSTREE); + copy_keypair_addr(fors_leaf_addr + 8 * i, fors_addr); + } + copy_keypair_addr(fors_pk_addr, fors_addr); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); + + message_to_indices(indices, m); + + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); + + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + + /* Include the secret key part that produces the selected leaf node. */ + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); + fors_gen_sk(sig, ctx, fors_tree_addr); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + sig += SPX_N; + + /* Compute the authentication path for this leaf node. */ + treehashx2(roots + i * SPX_N, sig, ctx, + indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx2, + fors_tree_addr, &fors_info); + + sig += SPX_N * SPX_FORS_HEIGHT; + } + + /* Hash horizontally across all tree roots to derive the public key. */ + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); +} + +/** + * Derives the FORS public key from a signature. + * This can be used for verification by comparing to a known public key, or to + * subsequently verify a signature on the derived public key. The latter is the + * typical use-case when used as an FTS below an OTS in a hypertree. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + unsigned char leaf[SPX_N]; + uint32_t fors_tree_addr[8] = {0}; + uint32_t fors_pk_addr[8] = {0}; + uint32_t idx_offset; + unsigned int i; + + copy_keypair_addr(fors_tree_addr, fors_addr); + copy_keypair_addr(fors_pk_addr, fors_addr); + + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); + + message_to_indices(indices, m); + + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); + + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + + /* Derive the leaf from the included secret key part. */ + fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); + sig += SPX_N; + + /* Derive the corresponding root node of this tree. */ + compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, + sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); + sig += SPX_N * SPX_FORS_HEIGHT; + } + + /* Hash horizontally across all tree roots to derive the public key. */ + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/fors.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/fors.h new file mode 100644 index 0000000000..509140a178 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/fors.h @@ -0,0 +1,32 @@ +#ifndef SPX_FORS_H +#define SPX_FORS_H + +#include + +#include "context.h" +#include "params.h" + +/** + * Signs a message m, deriving the secret key from sk_seed and the FTS address. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +#define fors_sign SPX_NAMESPACE(fors_sign) +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); + +/** + * Derives the FORS public key from a signature. + * This can be used for verification by comparing to a known public key, or to + * subsequently verify a signature on the derived public key. The latter is the + * typical use-case when used as an FTS below an OTS in a hypertree. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/hash.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/hash.h new file mode 100644 index 0000000000..f7c87d4c3c --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/hash.h @@ -0,0 +1,28 @@ +#ifndef SPX_HASH_H +#define SPX_HASH_H + +#include +#include + +#include "context.h" +#include "params.h" + +#define prf_addr SPX_NAMESPACE(prf_addr) +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]); + +#define gen_message_random SPX_NAMESPACE(gen_message_random) +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); + +#define hash_message SPX_NAMESPACE(hash_message) +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); + + + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/hash_shake.c b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/hash_shake.c new file mode 100644 index 0000000000..ff5e7ec918 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/hash_shake.c @@ -0,0 +1,83 @@ +#include +#include + +#include "hash.h" + +#include "address.h" +#include "fips202.h" +#include "params.h" +#include "utils.h" + +/* + * Computes PRF(pk_seed, sk_seed, addr) + */ +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]) { + unsigned char buf[2 * SPX_N + SPX_ADDR_BYTES]; + + memcpy(buf, ctx->pub_seed, SPX_N); + memcpy(buf + SPX_N, addr, SPX_ADDR_BYTES); + memcpy(buf + SPX_N + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); + + shake256(out, SPX_N, buf, 2 * SPX_N + SPX_ADDR_BYTES); +} + +/** + * Computes the message-dependent randomness R, using a secret seed and an + * optional randomization value as well as the message. + */ +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { + (void)ctx; + shake256incctx s_inc; + + shake256_inc_init(&s_inc); + shake256_inc_absorb(&s_inc, sk_prf, SPX_N); + shake256_inc_absorb(&s_inc, optrand, SPX_N); + shake256_inc_absorb(&s_inc, m, mlen); + shake256_inc_finalize(&s_inc); + shake256_inc_squeeze(R, SPX_N, &s_inc); + shake256_inc_ctx_release(&s_inc); +} + +/** + * Computes the message hash using R, the public key, and the message. + * Outputs the message digest and the index of the leaf. The index is split in + * the tree index and the leaf index, for convenient copying to an address. + */ +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { + (void)ctx; +#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) +#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) +#define SPX_LEAF_BITS SPX_TREE_HEIGHT +#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) +#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) + + unsigned char buf[SPX_DGST_BYTES]; + unsigned char *bufp = buf; + shake256incctx s_inc; + + shake256_inc_init(&s_inc); + shake256_inc_absorb(&s_inc, R, SPX_N); + shake256_inc_absorb(&s_inc, pk, SPX_PK_BYTES); + shake256_inc_absorb(&s_inc, m, mlen); + shake256_inc_finalize(&s_inc); + shake256_inc_squeeze(buf, SPX_DGST_BYTES, &s_inc); + shake256_inc_ctx_release(&s_inc); + + memcpy(digest, bufp, SPX_FORS_MSG_BYTES); + bufp += SPX_FORS_MSG_BYTES; + + + *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); + *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); + bufp += SPX_TREE_BYTES; + + *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); + *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/hash_shakex2.c b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/hash_shakex2.c new file mode 100644 index 0000000000..99571916a2 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/hash_shakex2.c @@ -0,0 +1,52 @@ +#include +#include + +#include "hashx2.h" + +#include "address.h" +#include "f1600x2.h" +#include "fips202x2.h" +#include "params.h" + +/* + * 2-way parallel version of prf_addr; takes 2x as much input and output + */ +void prf_addrx2(unsigned char *out0, + unsigned char *out1, + const spx_ctx *ctx, + const uint32_t addrx2[2 * 8]) { + /* As we write and read only a few quadwords, it is more efficient to + * build and extract from the fourway SHAKE256 state by hand. */ + uint64_t state[50] = {0}; + + for (int i = 0; i < SPX_N / 8; i++) { + uint64_t x = load64(ctx->pub_seed + 8 * i); + state[2 * i] = x; + state[2 * i + 1] = x; + } + for (int i = 0; i < 4; i++) { + state[2 * (SPX_N / 8 + i)] = (((uint64_t)addrx2[1 + 2 * i]) << 32) + | (uint64_t)addrx2[2 * i]; + state[2 * (SPX_N / 8 + i) + 1] = (((uint64_t)addrx2[8 + 1 + 2 * i]) << 32) + | (uint64_t)addrx2[8 + 2 * i]; + } + for (int i = 0; i < SPX_N / 8; i++) { + uint64_t x = load64(ctx->sk_seed + 8 * i); + state[2 * (SPX_N / 8 + i + 4)] = x; + state[2 * (SPX_N / 8 + i + 4) + 1] = x; + } + + /* SHAKE domain separator and padding. */ + state[2 * (SPX_N / 4 + 4)] = 0x1f; + state[2 * (SPX_N / 4 + 4) + 1] = 0x1f; + + state[2 * 16] = 0x80ULL << 56; + state[2 * 16 + 1] = 0x80ULL << 56; + + f1600x2(state); + + for (int i = 0; i < SPX_N / 8; i++) { + store64(out0 + 8 * i, state[2 * i]); + store64(out1 + 8 * i, state[2 * i + 1]); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/hashx2.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/hashx2.h new file mode 100644 index 0000000000..99b8873a9b --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/hashx2.h @@ -0,0 +1,14 @@ +#ifndef SPX_HASHX2_H +#define SPX_HASHX2_H + +#include "context.h" +#include "params.h" +#include + +#define prf_addrx2 SPX_NAMESPACE(prf_addrx2) +void prf_addrx2(unsigned char *out0, + unsigned char *out1, + const spx_ctx *ctx, + const uint32_t addrx2[2 * 8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/merkle.c b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/merkle.c new file mode 100644 index 0000000000..c94ee23939 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/merkle.c @@ -0,0 +1,64 @@ +#include +#include + +#include "merkle.h" + +#include "address.h" +#include "params.h" +#include "utils.h" +#include "utilsx2.h" +#include "wots.h" +#include "wotsx2.h" + +/* + * This generates a Merkle signature (WOTS signature followed by the Merkle + * authentication path). + */ +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf) { + unsigned char *auth_path = sig + SPX_WOTS_BYTES; + uint32_t tree_addrx2[2 * 8] = { 0 }; + int j; + struct leaf_info_x2 info = { 0 }; + unsigned steps[ SPX_WOTS_LEN ]; + + info.wots_sig = sig; + chain_lengths(steps, root); + info.wots_steps = steps; + + for (j = 0; j < 2; j++) { + set_type(&tree_addrx2[8 * j], SPX_ADDR_TYPE_HASHTREE); + set_type(&info.leaf_addr[8 * j], SPX_ADDR_TYPE_WOTS); + set_type(&info.pk_addr[8 * j], SPX_ADDR_TYPE_WOTSPK); + copy_subtree_addr(&tree_addrx2[8 * j], tree_addr); + copy_subtree_addr(&info.leaf_addr[8 * j], wots_addr); + copy_subtree_addr(&info.pk_addr[8 * j], wots_addr); + } + + info.wots_sign_leaf = idx_leaf; + + treehashx2(root, auth_path, ctx, + idx_leaf, 0, + SPX_TREE_HEIGHT, + wots_gen_leafx2, + tree_addrx2, &info); +} + +/* Compute root node of the top-most subtree. */ +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { + /* We do not need the auth path in key generation, but it simplifies the + code to have just one treehash routine that computes both root and path + in one function. */ + unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; + uint32_t top_tree_addr[8] = {0}; + uint32_t wots_addr[8] = {0}; + + set_layer_addr(top_tree_addr, SPX_D - 1); + set_layer_addr(wots_addr, SPX_D - 1); + + merkle_sign(auth_path, root, ctx, + wots_addr, top_tree_addr, + ~0 /* ~0 means "don't bother generating an auth path */ ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/merkle.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/merkle.h new file mode 100644 index 0000000000..769cf2e970 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/merkle.h @@ -0,0 +1,21 @@ +#ifndef MERKLE_H_ +#define MERKLE_H_ + +#include + +#include "context.h" +#include "params.h" + +/* Generate a Merkle signature (WOTS signature followed by the Merkle */ +/* authentication path) */ +#define merkle_sign SPX_NAMESPACE(merkle_sign) +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf); + +/* Compute the root node of the top-most subtree. */ +#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); + +#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/nistapi.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/nistapi.h new file mode 100644 index 0000000000..3cb71afad4 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/nistapi.h @@ -0,0 +1,87 @@ +#ifndef SPX_API_H +#define SPX_API_H + +#include +#include + +#include "params.h" + +#define CRYPTO_ALGNAME "SPHINCS+" + +#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES +#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES +#define CRYPTO_BYTES SPX_BYTES +#define CRYPTO_SEEDBYTES (3*SPX_N) + +/* + * Returns the length of a secret key, in bytes + */ +#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) +size_t crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) +size_t crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) +size_t crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) +size_t crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +#define crypto_sign SPX_NAMESPACE(crypto_sign) +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/params.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/params.h new file mode 100644 index 0000000000..f17a6c8eb3 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/params.h @@ -0,0 +1,56 @@ +#ifndef SPX_PARAMS_H +#define SPX_PARAMS_H + +#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSSHAKE256SROBUST_AARCH64_##s + +/* Hash output length in bytes. */ +#define SPX_N 32 +/* Height of the hypertree. */ +#define SPX_FULL_HEIGHT 64 +/* Number of subtree layer. */ +#define SPX_D 8 +/* FORS tree dimensions. */ +#define SPX_FORS_HEIGHT 14 +#define SPX_FORS_TREES 22 +/* Winternitz parameter, */ +#define SPX_WOTS_W 16 + +/* The hash function is defined by linking a different hash.c file, as opposed + to setting a #define constant. */ + +/* For clarity */ +#define SPX_ADDR_BYTES 32 + +/* WOTS parameters. */ +#define SPX_WOTS_LOGW 4 + +#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) + +/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ +#define SPX_WOTS_LEN2 3 + +#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) +#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) +#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES + +/* Subtree size. */ +#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) + +//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT +// #error SPX_D should always divide SPX_FULL_HEIGHT +//#endif + +/* FORS parameters. */ +#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) +#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) +#define SPX_FORS_PK_BYTES SPX_N + +/* Resulting SPX sizes. */ +#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ + SPX_FULL_HEIGHT * SPX_N) +#define SPX_PK_BYTES (2 * SPX_N) +#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) + +#include "shake_offsets.h" + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/shake_offsets.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/shake_offsets.h new file mode 100644 index 0000000000..6b28d95d91 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/shake_offsets.h @@ -0,0 +1,21 @@ +#ifndef SHAKE_OFFSETS_H_ +#define SHAKE_OFFSETS_H_ + +/* + * Offsets of various fields in the address structure when we use SHAKE as + * the Sphincs+ hash function + */ + +#define SPX_OFFSET_LAYER 3 /* The byte used to specify the Merkle tree layer */ +#define SPX_OFFSET_TREE 8 /* The start of the 8 byte field used to specify the tree */ +#define SPX_OFFSET_TYPE 19 /* The byte used to specify the hash type (reason) */ +#define SPX_OFFSET_KP_ADDR2 22 /* The high byte used to specify the key pair (which one-time signature) */ +#define SPX_OFFSET_KP_ADDR1 23 /* The low byte used to specify the key pair */ +#define SPX_OFFSET_CHAIN_ADDR 27 /* The byte used to specify the chain address (which Winternitz chain) */ +#define SPX_OFFSET_HASH_ADDR 31 /* The byte used to specify the hash address (where in the Winternitz chain) */ +#define SPX_OFFSET_TREE_HGT 27 /* The byte used to specify the height of this node in the FORS or Merkle tree */ +#define SPX_OFFSET_TREE_INDEX 28 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ + +#define SPX_SHAKE 1 + +#endif /* SHAKE_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/sign.c b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/sign.c new file mode 100644 index 0000000000..9d0c7d1b22 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/sign.c @@ -0,0 +1,286 @@ +#include +#include +#include + +#include "address.h" +#include "context.h" +#include "fors.h" +#include "hash.h" +#include "merkle.h" +#include "nistapi.h" +#include "params.h" +#include "randombytes.h" +#include "thash.h" +#include "utils.h" +#include "wots.h" + +/* + * Returns the length of a secret key, in bytes + */ +size_t crypto_sign_secretkeybytes(void) { + return CRYPTO_SECRETKEYBYTES; +} + +/* + * Returns the length of a public key, in bytes + */ +size_t crypto_sign_publickeybytes(void) { + return CRYPTO_PUBLICKEYBYTES; +} + +/* + * Returns the length of a signature, in bytes + */ +size_t crypto_sign_bytes(void) { + return CRYPTO_BYTES; +} + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +size_t crypto_sign_seedbytes(void) { + return CRYPTO_SEEDBYTES; +} + +/* + * Generates an SPX key pair given a seed of length + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [PUB_SEED || root] + */ +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed) { + spx_ctx ctx; + + /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ + memcpy(sk, seed, CRYPTO_SEEDBYTES); + + memcpy(pk, sk + 2 * SPX_N, SPX_N); + + memcpy(ctx.pub_seed, pk, SPX_N); + memcpy(ctx.sk_seed, sk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + /* Compute root node of the top-most subtree. */ + merkle_gen_root(sk + 3 * SPX_N, &ctx); + + // cleanup + free_hash_function(&ctx); + + memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); + + return 0; +} + +/* + * Generates an SPX key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [PUB_SEED || root] + */ +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { + uint8_t seed[CRYPTO_SEEDBYTES]; + randombytes(seed, CRYPTO_SEEDBYTES); + crypto_sign_seed_keypair(pk, sk, seed); + + return 0; +} + +/** + * Returns an array containing a detached signature. + */ +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk) { + spx_ctx ctx; + + const uint8_t *sk_prf = sk + SPX_N; + const uint8_t *pk = sk + 2 * SPX_N; + + uint8_t optrand[SPX_N]; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t root[SPX_N]; + uint32_t i; + uint64_t tree; + uint32_t idx_leaf; + uint32_t wots_addr[8] = {0}; + uint32_t tree_addr[8] = {0}; + + memcpy(ctx.sk_seed, sk, SPX_N); + memcpy(ctx.pub_seed, pk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + + /* Optionally, signing can be made non-deterministic using optrand. + This can help counter side-channel attacks that would benefit from + getting a large number of traces when the signer uses the same nodes. */ + randombytes(optrand, SPX_N); + /* Compute the digest randomization value. */ + gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); + + /* Derive the message digest and leaf index from R, PK and M. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; + + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); + + /* Sign the message hash using FORS. */ + fors_sign(sig, root, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); + sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; + + /* Update the indices for the next layer. */ + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; + } + + free_hash_function(&ctx); + + *siglen = SPX_BYTES; + + return 0; +} + +/** + * Verifies a detached signature and message under a given public key. + */ +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk) { + spx_ctx ctx; + const uint8_t *pub_root = pk + SPX_N; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t wots_pk[SPX_WOTS_BYTES]; + uint8_t root[SPX_N]; + uint8_t leaf[SPX_N]; + unsigned int i; + uint64_t tree; + uint32_t idx_leaf; + uint32_t wots_addr[8] = {0}; + uint32_t tree_addr[8] = {0}; + uint32_t wots_pk_addr[8] = {0}; + + if (siglen != SPX_BYTES) { + return -1; + } + + memcpy(ctx.pub_seed, pk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); + + /* Derive the message digest and leaf index from R || PK || M. */ + /* The additional SPX_N is a result of the hash domain separator. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; + + /* Layer correctly defaults to 0, so no need to set_layer_addr */ + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); + + fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + /* For each subtree.. */ + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + copy_keypair_addr(wots_pk_addr, wots_addr); + + /* The WOTS public key is only correct if the signature was correct. */ + /* Initially, root is the FORS pk, but on subsequent iterations it is + the root of the subtree below the currently processed subtree. */ + wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); + sig += SPX_WOTS_BYTES; + + /* Compute the leaf node using the WOTS public key. */ + thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); + + /* Compute the root node of this subtree. */ + compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, + &ctx, tree_addr); + sig += SPX_TREE_HEIGHT * SPX_N; + + /* Update the indices for the next layer. */ + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; + } + + // cleanup + free_hash_function(&ctx); + + /* Check if the root node equals the root node in the public key. */ + if (memcmp(root, pub_root, SPX_N) != 0) { + return -1; + } + + return 0; +} + + +/** + * Returns an array containing the signature followed by the message. + */ +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk) { + size_t siglen; + + crypto_sign_signature(sm, &siglen, m, mlen, sk); + + memmove(sm + SPX_BYTES, m, mlen); + *smlen = siglen + mlen; + + return 0; +} + +/** + * Verifies a given signature-message pair under a given public key. + */ +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk) { + /* The API caller does not necessarily know what size a signature should be + but SPHINCS+ signatures are always exactly SPX_BYTES. */ + if (smlen < SPX_BYTES) { + memset(m, 0, smlen); + *mlen = 0; + return -1; + } + + *mlen = smlen - SPX_BYTES; + + if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { + memset(m, 0, smlen); + *mlen = 0; + return -1; + } + + /* If verification was successful, move the message to the right place. */ + memmove(m, sm + SPX_BYTES, *mlen); + + return 0; +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/thash.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/thash.h new file mode 100644 index 0000000000..8687ccfb4d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/thash.h @@ -0,0 +1,13 @@ +#ifndef SPX_THASH_H +#define SPX_THASH_H + +#include "context.h" +#include "params.h" + +#include + +#define thash SPX_NAMESPACE(thash) +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/thash_shake_robustx2.c b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/thash_shake_robustx2.c new file mode 100644 index 0000000000..454fc0f4e2 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/thash_shake_robustx2.c @@ -0,0 +1,112 @@ +#include +#include + +#include "thash.h" +#include "thashx2.h" + +#include "address.h" +#include "params.h" +#include "utils.h" + +#include "f1600x2.h" +#include "fips202x2.h" + + +void thash(unsigned char *out, + const unsigned char *in, + unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]) { + uint32_t addrx2 [2 * 8] = { + addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], addr[6], addr[7], + addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], addr[6], addr[7] + }; + thashx2(out, out, in, in, inblocks, ctx, addrx2); +} + +/** + * 2-way parallel version of thash; takes 2x as much input and output + */ +void thashx2(unsigned char *out0, + unsigned char *out1, + const unsigned char *in0, + const unsigned char *in1, + unsigned int inblocks, + const spx_ctx *ctx, uint32_t addrx2[2 * 8]) { + if (inblocks == 1 || inblocks == 2) { + /* As we write and read only a few quadwords, it is more efficient to + * build and extract from the twoway SHAKE256 state by hand. */ + uint64_t state[50] = {0}; + uint64_t state2[50]; + + for (int i = 0; i < SPX_N / 8; i++) { + uint64_t x = load64(ctx->pub_seed + 8 * i); + state[2 * i] = x; + state[2 * i + 1] = x; + } + for (int i = 0; i < 4; i++) { + state[2 * (SPX_N / 8 + i)] = (((uint64_t)addrx2[1 + 2 * i]) << 32) + | (uint64_t)addrx2[2 * i]; + state[2 * (SPX_N / 8 + i) + 1] = (((uint64_t)addrx2[8 + 1 + 2 * i]) << 32) + | (uint64_t)addrx2[8 + 2 * i]; + } + + /* Domain separator and padding. */ + state[2 * 16] = 0x80ULL << 56; + state[2 * 16 + 1] = 0x80ULL << 56; + + state[2 * ((SPX_N / 8) + 4)] ^= 0x1f; + state[2 * ((SPX_N / 8) + 4) + 1] ^= 0x1f; + + /* We will permutate state2 with f1600x2 to compute the bitmask, + * but first we'll copy it to state2 which will be used to compute + * the final output, as its input is almost identical. */ + memcpy(state2, state, 400); + + f1600x2(state); + + /* By copying from state, state2 already contains the pub_seed + * and address. We just need to copy in the input blocks xorred with + * the bitmask we just computed. */ + for (unsigned int i = 0; i < (SPX_N / 8) * inblocks; i++) { + state2[2 * (SPX_N / 8 + 4 + i)] = state[2 * i] ^ load64(in0 + 8 * i); + state2[2 * (SPX_N / 8 + 4 + i) + 1] = state[2 * i + 1] ^ load64(in1 + 8 * i); + } + + /* Domain separator and start of padding. Note that the quadwords + * around are already zeroed for state from which we copied. + * We do a XOR instead of a set as this might be the 16th quadword + * when N=32 and inblocks=2, which already contains the end + * of the padding. */ + state2[2 * ((SPX_N / 8) * (1 + inblocks) + 4)] ^= 0x1f; + state2[2 * ((SPX_N / 8) * (1 + inblocks) + 4) + 1] ^= 0x1f; + + f1600x2(state2); + + for (int i = 0; i < SPX_N / 8; i++) { + store64(out0 + 8 * i, state2[2 * i]); + store64(out1 + 8 * i, state2[2 * i + 1]); + } + } else { + PQCLEAN_VLA(unsigned char, buf0, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, buf1, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, bitmask0, inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, bitmask1, inblocks * SPX_N); + unsigned int i; + + memcpy(buf0, ctx->pub_seed, SPX_N); + memcpy(buf1, ctx->pub_seed, SPX_N); + memcpy(buf0 + SPX_N, addrx2 + 0 * 8, SPX_ADDR_BYTES); + memcpy(buf1 + SPX_N, addrx2 + 1 * 8, SPX_ADDR_BYTES); + + shake256x2(bitmask0, bitmask1, inblocks * SPX_N, + buf0, buf1, SPX_N + SPX_ADDR_BYTES); + + for (i = 0; i < inblocks * SPX_N; i++) { + buf0[SPX_N + SPX_ADDR_BYTES + i] = in0[i] ^ bitmask0[i]; + buf1[SPX_N + SPX_ADDR_BYTES + i] = in1[i] ^ bitmask1[i]; + } + + shake256x2(out0, out1, SPX_N, + buf0, buf1, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/thashx2.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/thashx2.h new file mode 100644 index 0000000000..040375e618 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/thashx2.h @@ -0,0 +1,16 @@ +#ifndef SPX_THASHX2_H +#define SPX_THASHX2_H + +#include "context.h" +#include "params.h" +#include + +#define thashx2 SPX_NAMESPACE(thashx2) +void thashx2(unsigned char *out0, + unsigned char *out1, + const unsigned char *in0, + const unsigned char *in1, + unsigned int inblocks, + const spx_ctx *ctx, uint32_t addrx2[2 * 8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/utils.c b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/utils.c new file mode 100644 index 0000000000..177b541fb9 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/utils.c @@ -0,0 +1,148 @@ +#include + +#include "utils.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "thash.h" + +/** + * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. + */ +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in) { + int i; + + /* Iterate over out in decreasing order, for big-endianness. */ + for (i = (signed int)outlen - 1; i >= 0; i--) { + out[i] = in & 0xff; + in = in >> 8; + } +} + +void u32_to_bytes(unsigned char *out, uint32_t in) { + out[0] = (unsigned char)(in >> 24); + out[1] = (unsigned char)(in >> 16); + out[2] = (unsigned char)(in >> 8); + out[3] = (unsigned char)in; +} + +/** + * Converts the inlen bytes in 'in' from big-endian byte order to an integer. + */ +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { + unsigned long long retval = 0; + unsigned int i; + + for (i = 0; i < inlen; i++) { + retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); + } + return retval; +} + +/** + * Computes a root node given a leaf and an auth path. + * Expects address to be complete other than the tree_height and tree_index. + */ +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]) { + uint32_t i; + unsigned char buffer[2 * SPX_N]; + + /* If leaf_idx is odd (last bit = 1), current path element is a right child + and auth_path has to go left. Otherwise it is the other way around. */ + if (leaf_idx & 1) { + memcpy(buffer + SPX_N, leaf, SPX_N); + memcpy(buffer, auth_path, SPX_N); + } else { + memcpy(buffer, leaf, SPX_N); + memcpy(buffer + SPX_N, auth_path, SPX_N); + } + auth_path += SPX_N; + + for (i = 0; i < tree_height - 1; i++) { + leaf_idx >>= 1; + idx_offset >>= 1; + /* Set the address of the node we're creating. */ + set_tree_height(addr, i + 1); + set_tree_index(addr, leaf_idx + idx_offset); + + /* Pick the right or left neighbor, depending on parity of the node. */ + if (leaf_idx & 1) { + thash(buffer + SPX_N, buffer, 2, ctx, addr); + memcpy(buffer, auth_path, SPX_N); + } else { + thash(buffer, buffer, 2, ctx, addr); + memcpy(buffer + SPX_N, auth_path, SPX_N); + } + auth_path += SPX_N; + } + + /* The last iteration is exceptional; we do not copy an auth_path node. */ + leaf_idx >>= 1; + idx_offset >>= 1; + set_tree_height(addr, tree_height); + set_tree_index(addr, leaf_idx + idx_offset); + thash(root, buffer, 2, ctx, addr); +} + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx * /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]) { + PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); + PQCLEAN_VLA(unsigned int, heights, tree_height + 1); + unsigned int offset = 0; + uint32_t idx; + uint32_t tree_idx; + + for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { + /* Add the next leaf node to the stack. */ + gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); + offset++; + heights[offset - 1] = 0; + + /* If this is a node we need for the auth path.. */ + if ((leaf_idx ^ 0x1) == idx) { + memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); + } + + /* While the top-most nodes are of equal height.. */ + while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { + /* Compute index of the new node, in the next layer. */ + tree_idx = (idx >> (heights[offset - 1] + 1)); + + /* Set the address of the node we're creating. */ + set_tree_height(tree_addr, heights[offset - 1] + 1); + set_tree_index(tree_addr, + tree_idx + (idx_offset >> (heights[offset - 1] + 1))); + /* Hash the top-most nodes from the stack together. */ + thash(stack + (offset - 2)*SPX_N, + stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); + offset--; + /* Note that the top-most node is now one layer higher. */ + heights[offset - 1]++; + + /* If this is a node we need for the auth path.. */ + if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { + memcpy(auth_path + heights[offset - 1]*SPX_N, + stack + (offset - 1)*SPX_N, SPX_N); + } + } + } + memcpy(root, stack, SPX_N); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/utils.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/utils.h new file mode 100644 index 0000000000..64f5d5a53a --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/utils.h @@ -0,0 +1,58 @@ +#ifndef SPX_UTILS_H +#define SPX_UTILS_H + +#include + +#include "compat.h" +#include "context.h" +#include "params.h" + + +/* To support MSVC use alloca() instead of VLAs. See #20. */ + + +/** + * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. + */ +#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in); +#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) +void u32_to_bytes(unsigned char *out, uint32_t in); + +/** + * Converts the inlen bytes in 'in' from big-endian byte order to an integer. + */ +#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); + +/** + * Computes a root node given a leaf and an auth path. + * Expects address to be complete other than the tree_height and tree_index. + */ +#define compute_root SPX_NAMESPACE(compute_root) +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]); + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +#define treehash SPX_NAMESPACE(treehash) +void treehash(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx *ctx /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]); + + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/utilsx2.c b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/utilsx2.c new file mode 100644 index 0000000000..8736474e4f --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/utilsx2.c @@ -0,0 +1,130 @@ +#include + +#include "utilsx2.h" + +#include "address.h" +#include "params.h" +#include "thashx2.h" +#include "utils.h" + +/* + * Generate the entire Merkle tree, computing the authentication path for leaf_idx, + * and the resulting root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) + * + * This expects tree_addrx2 to be initialized to 2 parallel addr structures for + * the Merkle tree nodes + * + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + * + * This works by using the standard Merkle tree building algorithm, except + * that each 'node' tracked is actually 2 consecutive nodes in the real tree. + * When we combine two logical nodes AB and WX, we perform the H + * operation on adjacent real nodes, forming the parent logical node + * (AB)(WX) + * + * When we get to the top level of the real tree (where there is only + * one logical node), we continue this operation one more time; the right + * most real node will by the actual root (and the other node will be + * garbage). We follow the same thashx2 logic so that the 'extract + * authentication path components' part of the loop is still executed (and + * to simplify the code somewhat) + */ +void treehashx2(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, + uint32_t tree_height, + void (*gen_leafx2)( + unsigned char * /* Where to write the leaves */, + const spx_ctx *, + uint32_t idx, void *info), + uint32_t tree_addrx2[2 * 8], + void *info) { + /* This is where we keep the intermediate nodes */ + unsigned char stackx2[tree_height * 2 * SPX_N]; + uint32_t left_adj = 0, prev_left_adj = 0; /* When we're doing the top */ + /* level, the left-most part of the tree isn't at the beginning */ + /* of current[]. These give the offset of the actual start */ + + uint32_t idx; + uint32_t max_idx = (1 << (tree_height - 1)) - 1; + for (idx = 0;; idx++) { + unsigned char current[2 * SPX_N]; /* Current logical node */ + gen_leafx2( current, ctx, 2 * idx + idx_offset, + info ); + + /* Now combine the freshly generated right node with previously */ + /* generated left ones */ + uint32_t internal_idx_offset = idx_offset; + uint32_t internal_idx = idx; + uint32_t internal_leaf = leaf_idx; + uint32_t h; /* The height we are in the Merkle tree */ + for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { + + /* Special processing if we're at the top of the tree */ + if (h >= tree_height - 1) { + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[1 * SPX_N], SPX_N ); + return; + } + /* The tree indexing logic is a bit off in this case */ + /* Adjust it so that the left-most node of the part of */ + /* the tree that we're processing has index 0 */ + prev_left_adj = left_adj; + left_adj = 2 - (1 << (tree_height - h - 1)); + } + + /* Check if we hit the top of the tree */ + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[1 * SPX_N], SPX_N ); + return; + } + + /* + * Check if one of the nodes we have is a part of the + * authentication path; if it is, write it out + */ + if ((((internal_idx << 1) ^ internal_leaf) & ~0x1) == 0) { + memcpy( &auth_path[ h * SPX_N ], + ¤t[(((internal_leaf & 1) ^ 1) + prev_left_adj) * SPX_N], + SPX_N ); + } + + /* + * Check if we're at a left child; if so, stop going up the stack + * Exception: if we've reached the end of the tree, keep on going + * (so we combine the last 2 nodes into the one root node in two + * more iterations) + */ + if ((internal_idx & 1) == 0 && idx < max_idx) { + break; + } + + /* Ok, we're at a right node (or doing the top 3 levels) */ + /* Now combine the left and right logical nodes together */ + + /* Set the address of the node we're creating. */ + int j; + internal_idx_offset >>= 1; + for (j = 0; j < 2; j++) { + set_tree_height(tree_addrx2 + j * 8, h + 1); + set_tree_index(tree_addrx2 + j * 8, + (2 / 2) * (internal_idx & ~1) + j - left_adj + internal_idx_offset ); + } + unsigned char *left = &stackx2[h * 2 * SPX_N]; + thashx2( ¤t[0 * SPX_N], + ¤t[1 * SPX_N], + &left [0 * SPX_N], + ¤t[0 * SPX_N], + 2, ctx, tree_addrx2); + } + + /* We've hit a left child; save the current for when we get the */ + /* corresponding right right */ + memcpy( &stackx2[h * 2 * SPX_N], current, 2 * SPX_N); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/utilsx2.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/utilsx2.h new file mode 100644 index 0000000000..e09faddc43 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/utilsx2.h @@ -0,0 +1,30 @@ +#ifndef SPX_UTILSX2_H +#define SPX_UTILSX2_H + +#include + +#include "context.h" +#include "params.h" + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + * + * This implementation uses SIMD to compute internal nodes 2 at a time (in + * parallel) + */ +#define treehashx2 SPX_NAMESPACE(treehashx2) +void treehashx2(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leafx2)( + unsigned char * /* Where to write the leaves */, + const spx_ctx * /* ctx */, + uint32_t addr_idx, void *info), + uint32_t tree_addrx2[2 * 8], void *info); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/wots.c b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/wots.c new file mode 100644 index 0000000000..3babe45e95 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/wots.c @@ -0,0 +1,259 @@ +#include +#include + +#include "wots.h" +#include "wotsx2.h" + +#include "address.h" +#include "hash.h" +#include "hashx2.h" +#include "params.h" +#include "thashx2.h" +#include "utils.h" +#include "utilsx2.h" + +// TODO clarify address expectations, and make them more uniform. +// TODO i.e. do we expect types to be set already? +// TODO and do we expect modifications or copies? + +/** + * Computes up the chains + */ +static void gen_chains( + unsigned char *out, + const unsigned char *in, + unsigned int start[SPX_WOTS_LEN], + const unsigned int steps[SPX_WOTS_LEN], + const spx_ctx *ctx, + uint32_t addr[8]) { + uint32_t i, j, k, idx, watching; + int done; + unsigned char empty[SPX_N]; + unsigned char *bufs[4]; + uint32_t addrs[8 * 2]; + + int l; + uint16_t counts[SPX_WOTS_W] = { 0 }; + uint16_t idxs[SPX_WOTS_LEN]; + uint16_t total, newTotal; + + /* set addrs = {addr, addr} */ + for (j = 0; j < 2; j++) { + memcpy(addrs + j * 8, addr, sizeof(uint32_t) * 8); + } + + /* Initialize out with the value at position 'start'. */ + memcpy(out, in, SPX_WOTS_LEN * SPX_N); + + /* Sort the chains in reverse order by steps using counting sort. */ + for (i = 0; i < SPX_WOTS_LEN; i++) { + counts[steps[i]]++; + } + total = 0; + for (l = SPX_WOTS_W - 1; l >= 0; l--) { + newTotal = counts[l] + total; + counts[l] = total; + total = newTotal; + } + for (i = 0; i < SPX_WOTS_LEN; i++) { + idxs[counts[steps[i]]] = i; + counts[steps[i]]++; + } + + /* We got our work cut out for us: do it! */ + for (i = 0; i < SPX_WOTS_LEN; i += 2) { + for (j = 0; j < 2 && i + j < SPX_WOTS_LEN; j++) { + idx = idxs[i + j]; + set_chain_addr(addrs + j * 8, idx); + bufs[j] = out + SPX_N * idx; + } + + /* As the chains are sorted in reverse order, we know that the first + * chain is the longest and the last one is the shortest. We keep + * an eye on whether the last chain is done and then on the one before, + * et cetera. */ + watching = 1; + done = 0; + while (i + watching >= SPX_WOTS_LEN) { + bufs[watching] = &empty[0]; + watching--; + } + + for (k = 0;; k++) { + while (k == steps[idxs[i + watching]]) { + bufs[watching] = &empty[0]; + if (watching == 0) { + done = 1; + break; + } + watching--; + } + if (done) { + break; + } + for (j = 0; j < watching + 1; j++) { + set_hash_addr(addrs + j * 8, k + start[idxs[i + j]]); + } + + thashx2(bufs[0], bufs[1], + bufs[0], bufs[1], 1, ctx, addrs); + } + } +} + +/** + * base_w algorithm as described in draft. + * Interprets an array of bytes as integers in base w. + * This only works when log_w is a divisor of 8. + */ +static void base_w(unsigned int *output, const int out_len, + const unsigned char *input) { + int in = 0; + int out = 0; + unsigned char total = 0; + int bits = 0; + int consumed; + + for (consumed = 0; consumed < out_len; consumed++) { + if (bits == 0) { + total = input[in]; + in++; + bits += 8; + } + bits -= SPX_WOTS_LOGW; + output[out] = (total >> bits) & (SPX_WOTS_W - 1); + out++; + } +} + +/* Computes the WOTS+ checksum over a message (in base_w). */ +static void wots_checksum(unsigned int *csum_base_w, + const unsigned int *msg_base_w) { + unsigned int csum = 0; + unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; + unsigned int i; + + /* Compute checksum. */ + for (i = 0; i < SPX_WOTS_LEN1; i++) { + csum += SPX_WOTS_W - 1 - msg_base_w[i]; + } + + /* Convert checksum to base_w. */ + /* Make sure expected empty zero bits are the least significant bits. */ + csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); + ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); + base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); +} + +/* Takes a message and derives the matching chain lengths. */ +void chain_lengths(unsigned int *lengths, const unsigned char *msg) { + base_w(lengths, SPX_WOTS_LEN1, msg); + wots_checksum(lengths + SPX_WOTS_LEN1, lengths); +} + +/** + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. + * + * Writes the computed public key to 'pk'. + */ +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]) { + unsigned int steps[SPX_WOTS_LEN]; + unsigned int start[SPX_WOTS_LEN]; + uint32_t i; + + chain_lengths(start, msg); + + for (i = 0; i < SPX_WOTS_LEN; i++) { + steps[i] = SPX_WOTS_W - 1 - start[i]; + } + + gen_chains(pk, sig, start, steps, ctx, addr); +} + +/* + * This generates 2 sequential WOTS public keys + * It also generates the WOTS signature if leaf_info indicates + * that we're signing with one of these WOTS keys + */ +void wots_gen_leafx2(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info) { + struct leaf_info_x2 *info = v_info; + uint32_t *leaf_addr = info->leaf_addr; + uint32_t *pk_addr = info->pk_addr; + unsigned int i, j, k; + unsigned char pk_buffer[ 2 * SPX_WOTS_BYTES ]; + unsigned wots_offset = SPX_WOTS_BYTES; + unsigned char *buffer; + uint32_t wots_k_mask; + unsigned wots_sign_index; + + if (((leaf_idx ^ info->wots_sign_leaf) & ~1) == 0) { + /* We're traversing the leaf that's signing; generate the WOTS */ + /* signature */ + wots_k_mask = 0; + wots_sign_index = info->wots_sign_leaf & 1; /* Which of of the 2 */ + /* slots do the signatures come from */ + } else { + /* Nope, we're just generating pk's; turn off the signature logic */ + wots_k_mask = ~0; + wots_sign_index = 0; + } + + for (j = 0; j < 2; j++) { + set_keypair_addr( leaf_addr + j * 8, leaf_idx + j ); + set_keypair_addr( pk_addr + j * 8, leaf_idx + j ); + } + + for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { + uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k to */ + /* the step if we're generating a signature, ~0 if we're not */ + + /* Start with the secret seed */ + for (j = 0; j < 2; j++) { + set_chain_addr(leaf_addr + j * 8, i); + set_hash_addr(leaf_addr + j * 8, 0); + set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTSPRF); + } + prf_addrx2(buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + ctx, leaf_addr); + for (j = 0; j < 2; j++) { + set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTS); + } + + /* Iterate down the WOTS chain */ + for (k = 0;; k++) { + /* Check if one of the values we have needs to be saved as a */ + /* part of the WOTS signature */ + if (k == wots_k) { + memcpy( info->wots_sig + i * SPX_N, + buffer + wots_sign_index * wots_offset, SPX_N ); + } + + /* Check if we hit the top of the chain */ + if (k == SPX_WOTS_W - 1) { + break; + } + + /* Iterate one step on all 4 chains */ + for (j = 0; j < 2; j++) { + set_hash_addr(leaf_addr + j * 8, k); + } + thashx2(buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + 1, ctx, leaf_addr); + } + } + + /* Do the final thash to generate the public keys */ + thashx2(dest + 0 * SPX_N, + dest + 1 * SPX_N, + pk_buffer + 0 * wots_offset, + pk_buffer + 1 * wots_offset, + SPX_WOTS_LEN, ctx, pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/wots.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/wots.h new file mode 100644 index 0000000000..4e7692eeef --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/wots.h @@ -0,0 +1,25 @@ +#ifndef SPX_WOTS_H +#define SPX_WOTS_H + +#include + +#include "context.h" +#include "params.h" + +/** + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. + * + * Writes the computed public key to 'pk'. + */ +#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]); + +/* + * Compute the chain lengths needed for a given message hash + */ +#define chain_lengths SPX_NAMESPACE(chain_lengths) +void chain_lengths(unsigned int *lengths, const unsigned char *msg); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/wotsx2.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/wotsx2.h new file mode 100644 index 0000000000..b58bb61f84 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/wotsx2.h @@ -0,0 +1,40 @@ +#ifndef WOTSX2_H_ +#define WOTSX2_H_ + +#include "params.h" +#include + +/* + * This is here to provide an interface to the internal wots_gen_leafx2 + * routine. While this routine is not referenced in the package outside of + * wots.c, it is called from the stand-alone benchmark code to characterize + * the performance + */ +struct leaf_info_x2 { + unsigned char *wots_sig; + uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ + uint32_t *wots_steps; + uint32_t leaf_addr[2 * 8]; + uint32_t pk_addr[2 * 8]; +}; + +/* Macro to set the leaf_info to something 'benign', that is, it would */ +/* run with the same time as it does during the real signing process */ +/* Used only by the benchmark code */ +#define INITIALIZE_LEAF_INFO_X2(info, addr, step_buffer) { \ + (info).wots_sig = 0; \ + (info).wots_sign_leaf = ~0; \ + (info).wots_steps = step_buffer; \ + int i; \ + for (i=0; i<2; i++) { \ + memcpy( &(info).leaf_addr[8*i], addr, 32 ); \ + memcpy( &(info).pk_addr[8*i], addr, 32 ); \ + } \ + } + +#define wots_gen_leafx2 SPX_NAMESPACE(wots_gen_leafx2) +void wots_gen_leafx2(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info); + +#endif /* WOTSX2_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/LICENSE b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/LICENSE new file mode 100644 index 0000000000..670154e353 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/LICENSE @@ -0,0 +1,116 @@ +CC0 1.0 Universal + +Statement of Purpose + +The laws of most jurisdictions throughout the world automatically confer +exclusive Copyright and Related Rights (defined below) upon the creator and +subsequent owner(s) (each and all, an "owner") of an original work of +authorship and/or a database (each, a "Work"). + +Certain owners wish to permanently relinquish those rights to a Work for the +purpose of contributing to a commons of creative, cultural and scientific +works ("Commons") that the public can reliably and without fear of later +claims of infringement build upon, modify, incorporate in other works, reuse +and redistribute as freely as possible in any form whatsoever and for any +purposes, including without limitation commercial purposes. These owners may +contribute to the Commons to promote the ideal of a free culture and the +further production of creative, cultural and scientific works, or to gain +reputation or greater distribution for their Work in part through the use and +efforts of others. + +For these and/or other purposes and motivations, and without any expectation +of additional consideration or compensation, the person associating CC0 with a +Work (the "Affirmer"), to the extent that he or she is an owner of Copyright +and Related Rights in the Work, voluntarily elects to apply CC0 to the Work +and publicly distribute the Work under its terms, with knowledge of his or her +Copyright and Related Rights in the Work and the meaning and intended legal +effect of CC0 on those rights. + +1. Copyright and Related Rights. A Work made available under CC0 may be +protected by copyright and related or neighboring rights ("Copyright and +Related Rights"). Copyright and Related Rights include, but are not limited +to, the following: + + i. the right to reproduce, adapt, distribute, perform, display, communicate, + and translate a Work; + + ii. moral rights retained by the original author(s) and/or performer(s); + + iii. publicity and privacy rights pertaining to a person's image or likeness + depicted in a Work; + + iv. rights protecting against unfair competition in regards to a Work, + subject to the limitations in paragraph 4(a), below; + + v. rights protecting the extraction, dissemination, use and reuse of data in + a Work; + + vi. database rights (such as those arising under Directive 96/9/EC of the + European Parliament and of the Council of 11 March 1996 on the legal + protection of databases, and under any national implementation thereof, + including any amended or successor version of such directive); and + + vii. other similar, equivalent or corresponding rights throughout the world + based on applicable law or treaty, and any national implementations thereof. + +2. Waiver. To the greatest extent permitted by, but not in contravention of, +applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and +unconditionally waives, abandons, and surrenders all of Affirmer's Copyright +and Related Rights and associated claims and causes of action, whether now +known or unknown (including existing as well as future claims and causes of +action), in the Work (i) in all territories worldwide, (ii) for the maximum +duration provided by applicable law or treaty (including future time +extensions), (iii) in any current or future medium and for any number of +copies, and (iv) for any purpose whatsoever, including without limitation +commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes +the Waiver for the benefit of each member of the public at large and to the +detriment of Affirmer's heirs and successors, fully intending that such Waiver +shall not be subject to revocation, rescission, cancellation, termination, or +any other legal or equitable action to disrupt the quiet enjoyment of the Work +by the public as contemplated by Affirmer's express Statement of Purpose. + +3. Public License Fallback. Should any part of the Waiver for any reason be +judged legally invalid or ineffective under applicable law, then the Waiver +shall be preserved to the maximum extent permitted taking into account +Affirmer's express Statement of Purpose. In addition, to the extent the Waiver +is so judged Affirmer hereby grants to each affected person a royalty-free, +non transferable, non sublicensable, non exclusive, irrevocable and +unconditional license to exercise Affirmer's Copyright and Related Rights in +the Work (i) in all territories worldwide, (ii) for the maximum duration +provided by applicable law or treaty (including future time extensions), (iii) +in any current or future medium and for any number of copies, and (iv) for any +purpose whatsoever, including without limitation commercial, advertising or +promotional purposes (the "License"). The License shall be deemed effective as +of the date CC0 was applied by Affirmer to the Work. Should any part of the +License for any reason be judged legally invalid or ineffective under +applicable law, such partial invalidity or ineffectiveness shall not +invalidate the remainder of the License, and in such case Affirmer hereby +affirms that he or she will not (i) exercise any of his or her remaining +Copyright and Related Rights in the Work or (ii) assert any associated claims +and causes of action with respect to the Work, in either case contrary to +Affirmer's express Statement of Purpose. + +4. Limitations and Disclaimers. + + a. No trademark or patent rights held by Affirmer are waived, abandoned, + surrendered, licensed or otherwise affected by this document. + + b. Affirmer offers the Work as-is and makes no representations or warranties + of any kind concerning the Work, express, implied, statutory or otherwise, + including without limitation warranties of title, merchantability, fitness + for a particular purpose, non infringement, or the absence of latent or + other defects, accuracy, or the present or absence of errors, whether or not + discoverable, all to the greatest extent permissible under applicable law. + + c. Affirmer disclaims responsibility for clearing rights of other persons + that may apply to the Work or any use thereof, including without limitation + any person's Copyright and Related Rights in the Work. Further, Affirmer + disclaims responsibility for obtaining any necessary consents, permissions + or other rights required for any use of the Work. + + d. Affirmer understands and acknowledges that Creative Commons is not a + party to this document and has no duty or obligation with respect to this + CC0 or use of the Work. + +For more information, please see + diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/address.c b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/address.c new file mode 100644 index 0000000000..b956e9cb29 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/address.c @@ -0,0 +1,91 @@ +#include +#include + +#include "address.h" +#include "params.h" +#include "utils.h" + +/* + * Specify which level of Merkle tree (the "layer") we're working on + */ +void set_layer_addr(uint32_t addr[8], uint32_t layer) { + ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; +} + +/* + * Specify which Merkle tree within the level (the "tree address") we're working on + */ +void set_tree_addr(uint32_t addr[8], uint64_t tree) { + ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); +} + +/* + * Specify the reason we'll use this address structure for, that is, what + * hash will we compute with it. This is used so that unrelated types of + * hashes don't accidentally get the same address structure. The type will be + * one of the SPX_ADDR_TYPE constants + */ +void set_type(uint32_t addr[8], uint32_t type) { + ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; +} + +/* + * Copy the layer and tree fields of the address structure. This is used + * when we're doing multiple types of hashes within the same Merkle tree + */ +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); +} + +/* These functions are used for OTS addresses. */ + +/* + * Specify which Merkle leaf we're working on; that is, which OTS keypair + * we're talking about. + */ +void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { + ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; +} + +/* + * Copy the layer, tree and keypair fields of the address structure. This is + * used when we're doing multiple things within the same OTS keypair + */ +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); + ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; +} + +/* + * Specify which Merkle chain within the OTS we're working with + * (the chain address) + */ +void set_chain_addr(uint32_t addr[8], uint32_t chain) { + ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; +} + +/* + * Specify where in the Merkle chain we are +* (the hash address) + */ +void set_hash_addr(uint32_t addr[8], uint32_t hash) { + ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; +} + +/* These functions are used for all hash tree addresses (including FORS). */ + +/* + * Specify the height of the node in the Merkle/FORS tree we are in + * (the tree height) + */ +void set_tree_height(uint32_t addr[8], uint32_t tree_height) { + ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; +} + +/* + * Specify the distance from the left edge of the node in the Merkle/FORS tree + * (the tree index) + */ +void set_tree_index(uint32_t addr[8], uint32_t tree_index) { + u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/address.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/address.h new file mode 100644 index 0000000000..24a84eb40c --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/address.h @@ -0,0 +1,52 @@ +#ifndef SPX_ADDRESS_H +#define SPX_ADDRESS_H + +#include + +#include "params.h" + +/* The hash types that are passed to set_type */ +#define SPX_ADDR_TYPE_WOTS 0 +#define SPX_ADDR_TYPE_WOTSPK 1 +#define SPX_ADDR_TYPE_HASHTREE 2 +#define SPX_ADDR_TYPE_FORSTREE 3 +#define SPX_ADDR_TYPE_FORSPK 4 +#define SPX_ADDR_TYPE_WOTSPRF 5 +#define SPX_ADDR_TYPE_FORSPRF 6 + +#define set_layer_addr SPX_NAMESPACE(set_layer_addr) +void set_layer_addr(uint32_t addr[8], uint32_t layer); + +#define set_tree_addr SPX_NAMESPACE(set_tree_addr) +void set_tree_addr(uint32_t addr[8], uint64_t tree); + +#define set_type SPX_NAMESPACE(set_type) +void set_type(uint32_t addr[8], uint32_t type); + +/* Copies the layer and tree part of one address into the other */ +#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); + +/* These functions are used for WOTS and FORS addresses. */ + +#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) +void set_keypair_addr(uint32_t addr[8], uint32_t keypair); + +#define set_chain_addr SPX_NAMESPACE(set_chain_addr) +void set_chain_addr(uint32_t addr[8], uint32_t chain); + +#define set_hash_addr SPX_NAMESPACE(set_hash_addr) +void set_hash_addr(uint32_t addr[8], uint32_t hash); + +#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); + +/* These functions are used for all hash tree addresses (including FORS). */ + +#define set_tree_height SPX_NAMESPACE(set_tree_height) +void set_tree_height(uint32_t addr[8], uint32_t tree_height); + +#define set_tree_index SPX_NAMESPACE(set_tree_index) +void set_tree_index(uint32_t addr[8], uint32_t tree_index); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/api.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/api.h new file mode 100644 index 0000000000..c3c3bce6c1 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/api.h @@ -0,0 +1,77 @@ +#ifndef PQCLEAN_SPHINCSSHAKE256SROBUST_AVX2_API_H +#define PQCLEAN_SPHINCSSHAKE256SROBUST_AVX2_API_H + +#include +#include + +#define PQCLEAN_SPHINCSSHAKE256SROBUST_AVX2_CRYPTO_ALGNAME "SPHINCS+-shake-256s-robust" + +#define PQCLEAN_SPHINCSSHAKE256SROBUST_AVX2_CRYPTO_SECRETKEYBYTES 128 +#define PQCLEAN_SPHINCSSHAKE256SROBUST_AVX2_CRYPTO_PUBLICKEYBYTES 64 +#define PQCLEAN_SPHINCSSHAKE256SROBUST_AVX2_CRYPTO_BYTES 29792 + +#define PQCLEAN_SPHINCSSHAKE256SROBUST_AVX2_CRYPTO_SEEDBYTES 96 + +/* + * Returns the length of a secret key, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE256SROBUST_AVX2_crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE256SROBUST_AVX2_crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE256SROBUST_AVX2_crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE256SROBUST_AVX2_crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +int PQCLEAN_SPHINCSSHAKE256SROBUST_AVX2_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +int PQCLEAN_SPHINCSSHAKE256SROBUST_AVX2_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +int PQCLEAN_SPHINCSSHAKE256SROBUST_AVX2_crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +int PQCLEAN_SPHINCSSHAKE256SROBUST_AVX2_crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, + const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +int PQCLEAN_SPHINCSSHAKE256SROBUST_AVX2_crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +int PQCLEAN_SPHINCSSHAKE256SROBUST_AVX2_crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/context.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/context.h new file mode 100644 index 0000000000..6e0a33f3b7 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/context.h @@ -0,0 +1,19 @@ +#ifndef SPX_CONTEXT_H +#define SPX_CONTEXT_H + +#include + +#include "params.h" + +typedef struct { + uint8_t pub_seed[SPX_N]; + uint8_t sk_seed[SPX_N]; +} spx_ctx; + +#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) +void initialize_hash_function(spx_ctx *ctx); + +#define free_hash_function SPX_NAMESPACE(free_hash_function) +void free_hash_function(spx_ctx *ctx); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/context_shake.c b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/context_shake.c new file mode 100644 index 0000000000..9614a103d3 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/context_shake.c @@ -0,0 +1,12 @@ +#include "context.h" + +/* For SHAKE256, there is no immediate reason to initialize at the start, + so this function is an empty operation. */ +void initialize_hash_function(spx_ctx *ctx) { + (void)ctx; /* Suppress an 'unused parameter' warning. */ +} + +// in case the hash function api is heap-based. +void free_hash_function(spx_ctx *ctx) { + (void)ctx; +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/fips202x4.c b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/fips202x4.c new file mode 100644 index 0000000000..1e06fef186 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/fips202x4.c @@ -0,0 +1,210 @@ +#include +#include +#include + +#include "fips202.h" +#include "fips202x4.h" + +#define NROUNDS 24 +#define ROL(a, offset) (((a) << (offset)) ^ ((a) >> (64-(offset)))) + +static uint64_t load64(const unsigned char *x) { + unsigned long long r = 0, i; + + for (i = 0; i < 8; ++i) { + r |= (unsigned long long)x[i] << 8 * i; + } + return r; +} + +static void store64(uint8_t *x, uint64_t u) { + unsigned int i; + + for (i = 0; i < 8; ++i) { + x[i] = (uint8_t)u; + u >>= 8; + } +} + +/* Use implementation from the Keccak Code Package */ +extern void KeccakP1600times4_PermuteAll_24rounds(__m256i *s); +#define KeccakF1600_StatePermute4x KeccakP1600times4_PermuteAll_24rounds + +static void keccak_absorb4x(__m256i *s, + unsigned int r, + const unsigned char *m0, + const unsigned char *m1, + const unsigned char *m2, + const unsigned char *m3, + unsigned long long int mlen, + unsigned char p) { + unsigned long long i; + unsigned char t0[200]; + unsigned char t1[200]; + unsigned char t2[200]; + unsigned char t3[200]; + + unsigned long long *ss = (unsigned long long *)s; + + + while (mlen >= r) { + for (i = 0; i < r / 8; ++i) { + ss[4 * i + 0] ^= load64(m0 + 8 * i); + ss[4 * i + 1] ^= load64(m1 + 8 * i); + ss[4 * i + 2] ^= load64(m2 + 8 * i); + ss[4 * i + 3] ^= load64(m3 + 8 * i); + } + + KeccakF1600_StatePermute4x(s); + mlen -= r; + m0 += r; + m1 += r; + m2 += r; + m3 += r; + } + + for (i = 0; i < r; ++i) { + t0[i] = 0; + t1[i] = 0; + t2[i] = 0; + t3[i] = 0; + } + for (i = 0; i < mlen; ++i) { + t0[i] = m0[i]; + t1[i] = m1[i]; + t2[i] = m2[i]; + t3[i] = m3[i]; + } + + t0[i] = p; + t1[i] = p; + t2[i] = p; + t3[i] = p; + + t0[r - 1] |= 128; + t1[r - 1] |= 128; + t2[r - 1] |= 128; + t3[r - 1] |= 128; + + for (i = 0; i < r / 8; ++i) { + ss[4 * i + 0] ^= load64(t0 + 8 * i); + ss[4 * i + 1] ^= load64(t1 + 8 * i); + ss[4 * i + 2] ^= load64(t2 + 8 * i); + ss[4 * i + 3] ^= load64(t3 + 8 * i); + } +} + + +static void keccak_squeezeblocks4x(unsigned char *h0, + unsigned char *h1, + unsigned char *h2, + unsigned char *h3, + unsigned long long int nblocks, + __m256i *s, + unsigned int r) { + unsigned int i; + + unsigned long long *ss = (unsigned long long *)s; + + while (nblocks > 0) { + KeccakF1600_StatePermute4x(s); + for (i = 0; i < (r >> 3); i++) { + store64(h0 + 8 * i, ss[4 * i + 0]); + store64(h1 + 8 * i, ss[4 * i + 1]); + store64(h2 + 8 * i, ss[4 * i + 2]); + store64(h3 + 8 * i, ss[4 * i + 3]); + } + h0 += r; + h1 += r; + h2 += r; + h3 += r; + nblocks--; + } +} + + + +void shake128x4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, unsigned long long outlen, + unsigned char *in0, + unsigned char *in1, + unsigned char *in2, + unsigned char *in3, unsigned long long inlen) { + __m256i s[25]; + unsigned char t0[SHAKE128_RATE]; + unsigned char t1[SHAKE128_RATE]; + unsigned char t2[SHAKE128_RATE]; + unsigned char t3[SHAKE128_RATE]; + unsigned int i; + + /* zero state */ + for (i = 0; i < 25; i++) { + s[i] = _mm256_xor_si256(s[i], s[i]); + } + + /* absorb 4 message of identical length in parallel */ + keccak_absorb4x(s, SHAKE128_RATE, in0, in1, in2, in3, inlen, 0x1F); + + /* Squeeze output */ + keccak_squeezeblocks4x(out0, out1, out2, out3, outlen / SHAKE128_RATE, s, SHAKE128_RATE); + + out0 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; + out1 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; + out2 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; + out3 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; + + if (outlen % SHAKE128_RATE) { + keccak_squeezeblocks4x(t0, t1, t2, t3, 1, s, SHAKE128_RATE); + for (i = 0; i < outlen % SHAKE128_RATE; i++) { + out0[i] = t0[i]; + out1[i] = t1[i]; + out2[i] = t2[i]; + out3[i] = t3[i]; + } + } +} + + +void shake256x4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, unsigned long long outlen, + unsigned char *in0, + unsigned char *in1, + unsigned char *in2, + unsigned char *in3, unsigned long long inlen) { + __m256i s[25]; + unsigned char t0[SHAKE256_RATE]; + unsigned char t1[SHAKE256_RATE]; + unsigned char t2[SHAKE256_RATE]; + unsigned char t3[SHAKE256_RATE]; + unsigned int i; + + /* zero state */ + for (i = 0; i < 25; i++) { + s[i] = _mm256_xor_si256(s[i], s[i]); + } + + /* absorb 4 message of identical length in parallel */ + keccak_absorb4x(s, SHAKE256_RATE, in0, in1, in2, in3, inlen, 0x1F); + + /* Squeeze output */ + keccak_squeezeblocks4x(out0, out1, out2, out3, outlen / SHAKE256_RATE, s, SHAKE256_RATE); + + out0 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; + out1 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; + out2 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; + out3 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; + + if (outlen % SHAKE256_RATE) { + keccak_squeezeblocks4x(t0, t1, t2, t3, 1, s, SHAKE256_RATE); + for (i = 0; i < outlen % SHAKE256_RATE; i++) { + out0[i] = t0[i]; + out1[i] = t1[i]; + out2[i] = t2[i]; + out3[i] = t3[i]; + } + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/fips202x4.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/fips202x4.h new file mode 100644 index 0000000000..2b93c9cd0d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/fips202x4.h @@ -0,0 +1,28 @@ +#ifndef SPX_FIPS202X4_H +#define SPX_FIPS202X4_H + +#include + +#include "params.h" + +#define shake128x4 SPX_NAMESPACE(shake128x4) +void shake128x4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, unsigned long long outlen, + unsigned char *in0, + unsigned char *in1, + unsigned char *in2, + unsigned char *in3, unsigned long long inlen); + +#define shake256x4 SPX_NAMESPACE(shake256x4) +void shake256x4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, unsigned long long outlen, + unsigned char *in0, + unsigned char *in1, + unsigned char *in2, + unsigned char *in3, unsigned long long inlen); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/fors.c b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/fors.c new file mode 100644 index 0000000000..f1b0639cfc --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/fors.c @@ -0,0 +1,202 @@ +#include +#include +#include + +#include "fors.h" + +#include "address.h" +#include "hash.h" +#include "hashx4.h" +#include "thash.h" +#include "thashx4.h" +#include "utils.h" +#include "utilsx4.h" + +static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + prf_addr(sk, ctx, fors_leaf_addr); +} + +static void fors_gen_skx4(unsigned char *sk0, + unsigned char *sk1, + unsigned char *sk2, + unsigned char *sk3, const spx_ctx *ctx, + uint32_t fors_leaf_addrx4[4 * 8]) { + prf_addrx4(sk0, sk1, sk2, sk3, + ctx, fors_leaf_addrx4); +} + +static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, + const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + thash(leaf, sk, 1, ctx, fors_leaf_addr); +} + +static void fors_sk_to_leafx4(unsigned char *leaf0, + unsigned char *leaf1, + unsigned char *leaf2, + unsigned char *leaf3, + const unsigned char *sk0, + const unsigned char *sk1, + const unsigned char *sk2, + const unsigned char *sk3, + const spx_ctx *ctx, + uint32_t fors_leaf_addrx4[4 * 8]) { + thashx4(leaf0, leaf1, leaf2, leaf3, + sk0, sk1, sk2, sk3, + 1, ctx, fors_leaf_addrx4); +} + +struct fors_gen_leaf_info { + uint32_t leaf_addrx[4 * 8]; +}; + +static void fors_gen_leafx4(unsigned char *leaf, + const spx_ctx *ctx, + uint32_t addr_idx, void *info) { + struct fors_gen_leaf_info *fors_info = info; + uint32_t *fors_leaf_addrx4 = fors_info->leaf_addrx; + unsigned int j; + + /* Only set the parts that the caller doesn't set */ + for (j = 0; j < 4; j++) { + set_tree_index(fors_leaf_addrx4 + j * 8, addr_idx + j); + set_type(fors_leaf_addrx4 + j * 8, SPX_ADDR_TYPE_FORSPRF); + } + + fors_gen_skx4(leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + leaf + 2 * SPX_N, + leaf + 3 * SPX_N, + ctx, fors_leaf_addrx4); + + for (j = 0; j < 4; j++) { + set_type(fors_leaf_addrx4 + j * 8, SPX_ADDR_TYPE_FORSTREE); + } + + fors_sk_to_leafx4(leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + leaf + 2 * SPX_N, + leaf + 3 * SPX_N, + leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + leaf + 2 * SPX_N, + leaf + 3 * SPX_N, + ctx, fors_leaf_addrx4); +} + +/** + * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + * Assumes indices has space for SPX_FORS_TREES integers. + */ +static void message_to_indices(uint32_t *indices, const unsigned char *m) { + unsigned int i, j; + unsigned int offset = 0; + + for (i = 0; i < SPX_FORS_TREES; i++) { + indices[i] = 0; + for (j = 0; j < SPX_FORS_HEIGHT; j++) { + indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); + offset++; + } + } +} + +/** + * Signs a message m, deriving the secret key from sk_seed and the FTS address. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + uint32_t fors_tree_addr[4 * 8] = {0}; + struct fors_gen_leaf_info fors_info = {0}; + uint32_t *fors_leaf_addr = fors_info.leaf_addrx; + uint32_t fors_pk_addr[8] = {0}; + uint32_t idx_offset; + unsigned int i; + + for (i = 0; i < 4; i++) { + copy_keypair_addr(fors_tree_addr + 8 * i, fors_addr); + set_type(fors_tree_addr + 8 * i, SPX_ADDR_TYPE_FORSTREE); + copy_keypair_addr(fors_leaf_addr + 8 * i, fors_addr); + } + copy_keypair_addr(fors_pk_addr, fors_addr); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); + + message_to_indices(indices, m); + + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); + + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + + /* Include the secret key part that produces the selected leaf node. */ + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); + fors_gen_sk(sig, ctx, fors_tree_addr); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + sig += SPX_N; + + /* Compute the authentication path for this leaf node. */ + treehashx4(roots + i * SPX_N, sig, ctx, + indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx4, + fors_tree_addr, &fors_info); + + sig += SPX_N * SPX_FORS_HEIGHT; + } + + /* Hash horizontally across all tree roots to derive the public key. */ + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); +} + +/** + * Derives the FORS public key from a signature. + * This can be used for verification by comparing to a known public key, or to + * subsequently verify a signature on the derived public key. The latter is the + * typical use-case when used as an FTS below an OTS in a hypertree. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + unsigned char leaf[SPX_N]; + uint32_t fors_tree_addr[8] = {0}; + uint32_t fors_pk_addr[8] = {0}; + uint32_t idx_offset; + unsigned int i; + + copy_keypair_addr(fors_tree_addr, fors_addr); + copy_keypair_addr(fors_pk_addr, fors_addr); + + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); + + message_to_indices(indices, m); + + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); + + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + + /* Derive the leaf from the included secret key part. */ + fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); + sig += SPX_N; + + /* Derive the corresponding root node of this tree. */ + compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, + sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); + sig += SPX_N * SPX_FORS_HEIGHT; + } + + /* Hash horizontally across all tree roots to derive the public key. */ + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/fors.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/fors.h new file mode 100644 index 0000000000..509140a178 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/fors.h @@ -0,0 +1,32 @@ +#ifndef SPX_FORS_H +#define SPX_FORS_H + +#include + +#include "context.h" +#include "params.h" + +/** + * Signs a message m, deriving the secret key from sk_seed and the FTS address. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +#define fors_sign SPX_NAMESPACE(fors_sign) +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); + +/** + * Derives the FORS public key from a signature. + * This can be used for verification by comparing to a known public key, or to + * subsequently verify a signature on the derived public key. The latter is the + * typical use-case when used as an FTS below an OTS in a hypertree. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/hash.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/hash.h new file mode 100644 index 0000000000..f7c87d4c3c --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/hash.h @@ -0,0 +1,28 @@ +#ifndef SPX_HASH_H +#define SPX_HASH_H + +#include +#include + +#include "context.h" +#include "params.h" + +#define prf_addr SPX_NAMESPACE(prf_addr) +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]); + +#define gen_message_random SPX_NAMESPACE(gen_message_random) +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); + +#define hash_message SPX_NAMESPACE(hash_message) +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); + + + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/hash_shake.c b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/hash_shake.c new file mode 100644 index 0000000000..ff5e7ec918 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/hash_shake.c @@ -0,0 +1,83 @@ +#include +#include + +#include "hash.h" + +#include "address.h" +#include "fips202.h" +#include "params.h" +#include "utils.h" + +/* + * Computes PRF(pk_seed, sk_seed, addr) + */ +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]) { + unsigned char buf[2 * SPX_N + SPX_ADDR_BYTES]; + + memcpy(buf, ctx->pub_seed, SPX_N); + memcpy(buf + SPX_N, addr, SPX_ADDR_BYTES); + memcpy(buf + SPX_N + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); + + shake256(out, SPX_N, buf, 2 * SPX_N + SPX_ADDR_BYTES); +} + +/** + * Computes the message-dependent randomness R, using a secret seed and an + * optional randomization value as well as the message. + */ +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { + (void)ctx; + shake256incctx s_inc; + + shake256_inc_init(&s_inc); + shake256_inc_absorb(&s_inc, sk_prf, SPX_N); + shake256_inc_absorb(&s_inc, optrand, SPX_N); + shake256_inc_absorb(&s_inc, m, mlen); + shake256_inc_finalize(&s_inc); + shake256_inc_squeeze(R, SPX_N, &s_inc); + shake256_inc_ctx_release(&s_inc); +} + +/** + * Computes the message hash using R, the public key, and the message. + * Outputs the message digest and the index of the leaf. The index is split in + * the tree index and the leaf index, for convenient copying to an address. + */ +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { + (void)ctx; +#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) +#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) +#define SPX_LEAF_BITS SPX_TREE_HEIGHT +#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) +#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) + + unsigned char buf[SPX_DGST_BYTES]; + unsigned char *bufp = buf; + shake256incctx s_inc; + + shake256_inc_init(&s_inc); + shake256_inc_absorb(&s_inc, R, SPX_N); + shake256_inc_absorb(&s_inc, pk, SPX_PK_BYTES); + shake256_inc_absorb(&s_inc, m, mlen); + shake256_inc_finalize(&s_inc); + shake256_inc_squeeze(buf, SPX_DGST_BYTES, &s_inc); + shake256_inc_ctx_release(&s_inc); + + memcpy(digest, bufp, SPX_FORS_MSG_BYTES); + bufp += SPX_FORS_MSG_BYTES; + + + *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); + *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); + bufp += SPX_TREE_BYTES; + + *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); + *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/hash_shakex4.c b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/hash_shakex4.c new file mode 100644 index 0000000000..bbd22eb117 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/hash_shakex4.c @@ -0,0 +1,64 @@ +#include +#include + +#include "hashx4.h" + +#include "address.h" +#include "fips202x4.h" +#include "params.h" + +extern void KeccakP1600times4_PermuteAll_24rounds(__m256i *s); + +/* + * 4-way parallel version of prf_addr; takes 4x as much input and output + */ +void prf_addrx4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const spx_ctx *ctx, + const uint32_t addrx4[4 * 8]) { + /* As we write and read only a few quadwords, it is more efficient to + * build and extract from the fourway SHAKE256 state by hand. */ + __m256i state[25]; + + for (int i = 0; i < SPX_N / 8; i++) { + state[i] = _mm256_set1_epi64x(((int64_t *)ctx->pub_seed)[i]); + } + for (int i = 0; i < 4; i++) { + state[SPX_N / 8 + i] = _mm256_set_epi32( + (int)addrx4[3 * 8 + 1 + 2 * i], + (int)addrx4[3 * 8 + 2 * i], + (int)addrx4[2 * 8 + 1 + 2 * i], + (int)addrx4[2 * 8 + 2 * i], + (int)addrx4[8 + 1 + 2 * i], + (int)addrx4[8 + 2 * i], + (int)addrx4[1 + 2 * i], + (int)addrx4[2 * i] + ); + } + for (int i = 0; i < SPX_N / 8; i++) { + state[SPX_N / 8 + i + 4] = _mm256_set1_epi64x(((int64_t *)ctx->sk_seed)[i]); + } + + /* SHAKE domain separator and padding. */ + state[SPX_N / 4 + 4] = _mm256_set1_epi64x(0x1f); + for (int i = SPX_N / 4 + 5; i < 16; i++) { + state[i] = _mm256_set1_epi64x(0); + } + // shift unsigned and then cast to avoid UB + state[16] = _mm256_set1_epi64x((long long)(0x80ULL << 56)); + + for (int i = 17; i < 25; i++) { + state[i] = _mm256_set1_epi64x(0); + } + + KeccakP1600times4_PermuteAll_24rounds(&state[0]); + + for (int i = 0; i < SPX_N / 8; i++) { + ((int64_t *)out0)[i] = _mm256_extract_epi64(state[i], 0); + ((int64_t *)out1)[i] = _mm256_extract_epi64(state[i], 1); + ((int64_t *)out2)[i] = _mm256_extract_epi64(state[i], 2); + ((int64_t *)out3)[i] = _mm256_extract_epi64(state[i], 3); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/hashx4.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/hashx4.h new file mode 100644 index 0000000000..3751a0ebd0 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/hashx4.h @@ -0,0 +1,17 @@ +#ifndef SPX_HASHX4_H +#define SPX_HASHX4_H + +#include + +#include "context.h" +#include "params.h" + +#define prf_addrx4 SPX_NAMESPACE(prf_addrx4) +void prf_addrx4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const spx_ctx *ctx, + const uint32_t addrx4[4 * 8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/merkle.c b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/merkle.c new file mode 100644 index 0000000000..f57811c1ac --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/merkle.c @@ -0,0 +1,64 @@ +#include +#include + +#include "merkle.h" + +#include "address.h" +#include "params.h" +#include "utils.h" +#include "utilsx4.h" +#include "wots.h" +#include "wotsx4.h" + +/* + * This generates a Merkle signature (WOTS signature followed by the Merkle + * authentication path). + */ +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf) { + unsigned char *auth_path = sig + SPX_WOTS_BYTES; + uint32_t tree_addrx4[4 * 8] = { 0 }; + int j; + struct leaf_info_x4 info = { 0 }; + unsigned steps[ SPX_WOTS_LEN ]; + + info.wots_sig = sig; + chain_lengths(steps, root); + info.wots_steps = steps; + + for (j = 0; j < 4; j++) { + set_type(&tree_addrx4[8 * j], SPX_ADDR_TYPE_HASHTREE); + set_type(&info.leaf_addr[8 * j], SPX_ADDR_TYPE_WOTS); + set_type(&info.pk_addr[8 * j], SPX_ADDR_TYPE_WOTSPK); + copy_subtree_addr(&tree_addrx4[8 * j], tree_addr); + copy_subtree_addr(&info.leaf_addr[8 * j], wots_addr); + copy_subtree_addr(&info.pk_addr[8 * j], wots_addr); + } + + info.wots_sign_leaf = idx_leaf; + + treehashx4(root, auth_path, ctx, + idx_leaf, 0, + SPX_TREE_HEIGHT, + wots_gen_leafx4, + tree_addrx4, &info); +} + +/* Compute root node of the top-most subtree. */ +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { + /* We do not need the auth path in key generation, but it simplifies the + code to have just one treehash routine that computes both root and path + in one function. */ + unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; + uint32_t top_tree_addr[8] = {0}; + uint32_t wots_addr[8] = {0}; + + set_layer_addr(top_tree_addr, SPX_D - 1); + set_layer_addr(wots_addr, SPX_D - 1); + + merkle_sign(auth_path, root, ctx, + wots_addr, top_tree_addr, + ~0U /* ~0 means "don't bother generating an auth path */ ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/merkle.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/merkle.h new file mode 100644 index 0000000000..769cf2e970 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/merkle.h @@ -0,0 +1,21 @@ +#ifndef MERKLE_H_ +#define MERKLE_H_ + +#include + +#include "context.h" +#include "params.h" + +/* Generate a Merkle signature (WOTS signature followed by the Merkle */ +/* authentication path) */ +#define merkle_sign SPX_NAMESPACE(merkle_sign) +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf); + +/* Compute the root node of the top-most subtree. */ +#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); + +#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/nistapi.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/nistapi.h new file mode 100644 index 0000000000..3cb71afad4 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/nistapi.h @@ -0,0 +1,87 @@ +#ifndef SPX_API_H +#define SPX_API_H + +#include +#include + +#include "params.h" + +#define CRYPTO_ALGNAME "SPHINCS+" + +#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES +#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES +#define CRYPTO_BYTES SPX_BYTES +#define CRYPTO_SEEDBYTES (3*SPX_N) + +/* + * Returns the length of a secret key, in bytes + */ +#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) +size_t crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) +size_t crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) +size_t crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) +size_t crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +#define crypto_sign SPX_NAMESPACE(crypto_sign) +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/params.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/params.h new file mode 100644 index 0000000000..81887bffca --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/params.h @@ -0,0 +1,56 @@ +#ifndef SPX_PARAMS_H +#define SPX_PARAMS_H + +#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSSHAKE256SROBUST_AVX2_##s + +/* Hash output length in bytes. */ +#define SPX_N 32 +/* Height of the hypertree. */ +#define SPX_FULL_HEIGHT 64 +/* Number of subtree layer. */ +#define SPX_D 8 +/* FORS tree dimensions. */ +#define SPX_FORS_HEIGHT 14 +#define SPX_FORS_TREES 22 +/* Winternitz parameter, */ +#define SPX_WOTS_W 16 + +/* The hash function is defined by linking a different hash.c file, as opposed + to setting a #define constant. */ + +/* For clarity */ +#define SPX_ADDR_BYTES 32 + +/* WOTS parameters. */ +#define SPX_WOTS_LOGW 4 + +#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) + +/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ +#define SPX_WOTS_LEN2 3 + +#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) +#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) +#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES + +/* Subtree size. */ +#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) + +//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT +// #error SPX_D should always divide SPX_FULL_HEIGHT +//#endif + +/* FORS parameters. */ +#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) +#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) +#define SPX_FORS_PK_BYTES SPX_N + +/* Resulting SPX sizes. */ +#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ + SPX_FULL_HEIGHT * SPX_N) +#define SPX_PK_BYTES (2 * SPX_N) +#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) + +#include "shake_offsets.h" + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/shake_offsets.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/shake_offsets.h new file mode 100644 index 0000000000..6b28d95d91 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/shake_offsets.h @@ -0,0 +1,21 @@ +#ifndef SHAKE_OFFSETS_H_ +#define SHAKE_OFFSETS_H_ + +/* + * Offsets of various fields in the address structure when we use SHAKE as + * the Sphincs+ hash function + */ + +#define SPX_OFFSET_LAYER 3 /* The byte used to specify the Merkle tree layer */ +#define SPX_OFFSET_TREE 8 /* The start of the 8 byte field used to specify the tree */ +#define SPX_OFFSET_TYPE 19 /* The byte used to specify the hash type (reason) */ +#define SPX_OFFSET_KP_ADDR2 22 /* The high byte used to specify the key pair (which one-time signature) */ +#define SPX_OFFSET_KP_ADDR1 23 /* The low byte used to specify the key pair */ +#define SPX_OFFSET_CHAIN_ADDR 27 /* The byte used to specify the chain address (which Winternitz chain) */ +#define SPX_OFFSET_HASH_ADDR 31 /* The byte used to specify the hash address (where in the Winternitz chain) */ +#define SPX_OFFSET_TREE_HGT 27 /* The byte used to specify the height of this node in the FORS or Merkle tree */ +#define SPX_OFFSET_TREE_INDEX 28 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ + +#define SPX_SHAKE 1 + +#endif /* SHAKE_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/sign.c b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/sign.c new file mode 100644 index 0000000000..9d0c7d1b22 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/sign.c @@ -0,0 +1,286 @@ +#include +#include +#include + +#include "address.h" +#include "context.h" +#include "fors.h" +#include "hash.h" +#include "merkle.h" +#include "nistapi.h" +#include "params.h" +#include "randombytes.h" +#include "thash.h" +#include "utils.h" +#include "wots.h" + +/* + * Returns the length of a secret key, in bytes + */ +size_t crypto_sign_secretkeybytes(void) { + return CRYPTO_SECRETKEYBYTES; +} + +/* + * Returns the length of a public key, in bytes + */ +size_t crypto_sign_publickeybytes(void) { + return CRYPTO_PUBLICKEYBYTES; +} + +/* + * Returns the length of a signature, in bytes + */ +size_t crypto_sign_bytes(void) { + return CRYPTO_BYTES; +} + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +size_t crypto_sign_seedbytes(void) { + return CRYPTO_SEEDBYTES; +} + +/* + * Generates an SPX key pair given a seed of length + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [PUB_SEED || root] + */ +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed) { + spx_ctx ctx; + + /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ + memcpy(sk, seed, CRYPTO_SEEDBYTES); + + memcpy(pk, sk + 2 * SPX_N, SPX_N); + + memcpy(ctx.pub_seed, pk, SPX_N); + memcpy(ctx.sk_seed, sk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + /* Compute root node of the top-most subtree. */ + merkle_gen_root(sk + 3 * SPX_N, &ctx); + + // cleanup + free_hash_function(&ctx); + + memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); + + return 0; +} + +/* + * Generates an SPX key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [PUB_SEED || root] + */ +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { + uint8_t seed[CRYPTO_SEEDBYTES]; + randombytes(seed, CRYPTO_SEEDBYTES); + crypto_sign_seed_keypair(pk, sk, seed); + + return 0; +} + +/** + * Returns an array containing a detached signature. + */ +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk) { + spx_ctx ctx; + + const uint8_t *sk_prf = sk + SPX_N; + const uint8_t *pk = sk + 2 * SPX_N; + + uint8_t optrand[SPX_N]; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t root[SPX_N]; + uint32_t i; + uint64_t tree; + uint32_t idx_leaf; + uint32_t wots_addr[8] = {0}; + uint32_t tree_addr[8] = {0}; + + memcpy(ctx.sk_seed, sk, SPX_N); + memcpy(ctx.pub_seed, pk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + + /* Optionally, signing can be made non-deterministic using optrand. + This can help counter side-channel attacks that would benefit from + getting a large number of traces when the signer uses the same nodes. */ + randombytes(optrand, SPX_N); + /* Compute the digest randomization value. */ + gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); + + /* Derive the message digest and leaf index from R, PK and M. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; + + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); + + /* Sign the message hash using FORS. */ + fors_sign(sig, root, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); + sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; + + /* Update the indices for the next layer. */ + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; + } + + free_hash_function(&ctx); + + *siglen = SPX_BYTES; + + return 0; +} + +/** + * Verifies a detached signature and message under a given public key. + */ +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk) { + spx_ctx ctx; + const uint8_t *pub_root = pk + SPX_N; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t wots_pk[SPX_WOTS_BYTES]; + uint8_t root[SPX_N]; + uint8_t leaf[SPX_N]; + unsigned int i; + uint64_t tree; + uint32_t idx_leaf; + uint32_t wots_addr[8] = {0}; + uint32_t tree_addr[8] = {0}; + uint32_t wots_pk_addr[8] = {0}; + + if (siglen != SPX_BYTES) { + return -1; + } + + memcpy(ctx.pub_seed, pk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); + + /* Derive the message digest and leaf index from R || PK || M. */ + /* The additional SPX_N is a result of the hash domain separator. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; + + /* Layer correctly defaults to 0, so no need to set_layer_addr */ + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); + + fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + /* For each subtree.. */ + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + copy_keypair_addr(wots_pk_addr, wots_addr); + + /* The WOTS public key is only correct if the signature was correct. */ + /* Initially, root is the FORS pk, but on subsequent iterations it is + the root of the subtree below the currently processed subtree. */ + wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); + sig += SPX_WOTS_BYTES; + + /* Compute the leaf node using the WOTS public key. */ + thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); + + /* Compute the root node of this subtree. */ + compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, + &ctx, tree_addr); + sig += SPX_TREE_HEIGHT * SPX_N; + + /* Update the indices for the next layer. */ + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; + } + + // cleanup + free_hash_function(&ctx); + + /* Check if the root node equals the root node in the public key. */ + if (memcmp(root, pub_root, SPX_N) != 0) { + return -1; + } + + return 0; +} + + +/** + * Returns an array containing the signature followed by the message. + */ +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk) { + size_t siglen; + + crypto_sign_signature(sm, &siglen, m, mlen, sk); + + memmove(sm + SPX_BYTES, m, mlen); + *smlen = siglen + mlen; + + return 0; +} + +/** + * Verifies a given signature-message pair under a given public key. + */ +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk) { + /* The API caller does not necessarily know what size a signature should be + but SPHINCS+ signatures are always exactly SPX_BYTES. */ + if (smlen < SPX_BYTES) { + memset(m, 0, smlen); + *mlen = 0; + return -1; + } + + *mlen = smlen - SPX_BYTES; + + if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { + memset(m, 0, smlen); + *mlen = 0; + return -1; + } + + /* If verification was successful, move the message to the right place. */ + memmove(m, sm + SPX_BYTES, *mlen); + + return 0; +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/thash.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/thash.h new file mode 100644 index 0000000000..8687ccfb4d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/thash.h @@ -0,0 +1,13 @@ +#ifndef SPX_THASH_H +#define SPX_THASH_H + +#include "context.h" +#include "params.h" + +#include + +#define thash SPX_NAMESPACE(thash) +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/thash_shake_robust.c b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/thash_shake_robust.c new file mode 100644 index 0000000000..696d53c5cc --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/thash_shake_robust.c @@ -0,0 +1,31 @@ +#include +#include + +#include "thash.h" + +#include "address.h" +#include "params.h" +#include "utils.h" + +#include "fips202.h" + +/** + * Takes an array of inblocks concatenated arrays of SPX_N bytes. + */ +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]) { + PQCLEAN_VLA(uint8_t, buf, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); + PQCLEAN_VLA(uint8_t, bitmask, inblocks * SPX_N); + unsigned int i; + + memcpy(buf, ctx->pub_seed, SPX_N); + memcpy(buf + SPX_N, addr, SPX_ADDR_BYTES); + + shake256(bitmask, inblocks * SPX_N, buf, SPX_N + SPX_ADDR_BYTES); + + for (i = 0; i < inblocks * SPX_N; i++) { + buf[SPX_N + SPX_ADDR_BYTES + i] = in[i] ^ bitmask[i]; + } + + shake256(out, SPX_N, buf, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/thash_shake_robustx4.c b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/thash_shake_robustx4.c new file mode 100644 index 0000000000..ce2946b745 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/thash_shake_robustx4.c @@ -0,0 +1,131 @@ +#include +#include + +#include "thashx4.h" + +#include "address.h" +#include "params.h" +#include "utils.h" + +#include "fips202x4.h" + +extern void KeccakP1600times4_PermuteAll_24rounds(__m256i *s); + +/** + * 4-way parallel version of thash; takes 4x as much input and output + */ +void thashx4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addrx4[4 * 8]) { + if (inblocks == 1 || inblocks == 2) { + /* As we write and read only a few quadwords, it is more efficient to + * build and extract from the fourway SHAKE256 state by hand. */ + __m256i state[25]; + for (int i = 0; i < SPX_N / 8; i++) { + state[i] = _mm256_set1_epi64x(((int64_t *)ctx->pub_seed)[i]); + } + for (int i = 0; i < 4; i++) { + state[SPX_N / 8 + i] = _mm256_set_epi32( + (int)addrx4[3 * 8 + 1 + 2 * i], + (int)addrx4[3 * 8 + 2 * i], + (int)addrx4[2 * 8 + 1 + 2 * i], + (int)addrx4[2 * 8 + 2 * i], + (int)addrx4[8 + 1 + 2 * i], + (int)addrx4[8 + 2 * i], + (int)addrx4[1 + 2 * i], + (int)addrx4[2 * i] + ); + } + + /* SHAKE domain separator and padding */ + state[SPX_N / 8 + 4] = _mm256_set1_epi64x(0x1f); + for (int i = SPX_N / 8 + 5; i < 16; i++) { + state[i] = _mm256_set1_epi64x(0); + } + state[16] = _mm256_set1_epi64x((long long)(0x80ULL << 56)); + + for (int i = 17; i < 25; i++) { + state[i] = _mm256_set1_epi64x(0); + } + + /* We will permutate state2 with f1600x4 to compute the bitmask, + * but first we'll copy it to state2 which will be used to compute + * the final output, as its input is alsmost identical. */ + __m256i state2[25]; + memcpy(state2, state, 800); + + KeccakP1600times4_PermuteAll_24rounds(&state[0]); + + /* By copying from state, state2 already contains the pub_seed + * and addres. We just need to copy in the input blocks xorred with + * the bitmask we just computed. */ + for (unsigned int i = 0; i < (SPX_N / 8) * inblocks; i++) { + state2[SPX_N / 8 + 4 + i] = _mm256_xor_si256( + state[i], + _mm256_set_epi64x( + ((int64_t *)in3)[i], + ((int64_t *)in2)[i], + ((int64_t *)in1)[i], + ((int64_t *)in0)[i] + ) + ); + } + + /* Domain separator and start of padding. Note that the quadwords + * around are already zeroed for state from which we copied. + * We do a XOR instead of a set as this might be the 16th quadword + * when N=32 and inblocks=2, which already contains the end + * of the padding. */ + state2[(SPX_N / 8) * (1 + inblocks) + 4] = _mm256_xor_si256( + state2[(SPX_N / 8) * (1 + inblocks) + 4], + _mm256_set1_epi64x(0x1f) + ); + + KeccakP1600times4_PermuteAll_24rounds(&state2[0]); + + for (int i = 0; i < SPX_N / 8; i++) { + ((int64_t *)out0)[i] = _mm256_extract_epi64(state2[i], 0); + ((int64_t *)out1)[i] = _mm256_extract_epi64(state2[i], 1); + ((int64_t *)out2)[i] = _mm256_extract_epi64(state2[i], 2); + ((int64_t *)out3)[i] = _mm256_extract_epi64(state2[i], 3); + } + } else { + PQCLEAN_VLA(unsigned char, buf0, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, buf1, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, buf2, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, buf3, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, bitmask0, inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, bitmask1, inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, bitmask2, inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, bitmask3, inblocks * SPX_N); + unsigned int i; + + memcpy(buf0, ctx->pub_seed, SPX_N); + memcpy(buf1, ctx->pub_seed, SPX_N); + memcpy(buf2, ctx->pub_seed, SPX_N); + memcpy(buf3, ctx->pub_seed, SPX_N); + memcpy(buf0 + SPX_N, addrx4 + 0 * 8, SPX_ADDR_BYTES); + memcpy(buf1 + SPX_N, addrx4 + 1 * 8, SPX_ADDR_BYTES); + memcpy(buf2 + SPX_N, addrx4 + 2 * 8, SPX_ADDR_BYTES); + memcpy(buf3 + SPX_N, addrx4 + 3 * 8, SPX_ADDR_BYTES); + + shake256x4(bitmask0, bitmask1, bitmask2, bitmask3, inblocks * SPX_N, + buf0, buf1, buf2, buf3, SPX_N + SPX_ADDR_BYTES); + + for (i = 0; i < inblocks * SPX_N; i++) { + buf0[SPX_N + SPX_ADDR_BYTES + i] = in0[i] ^ bitmask0[i]; + buf1[SPX_N + SPX_ADDR_BYTES + i] = in1[i] ^ bitmask1[i]; + buf2[SPX_N + SPX_ADDR_BYTES + i] = in2[i] ^ bitmask2[i]; + buf3[SPX_N + SPX_ADDR_BYTES + i] = in3[i] ^ bitmask3[i]; + } + + shake256x4(out0, out1, out2, out3, SPX_N, + buf0, buf1, buf2, buf3, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/thashx4.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/thashx4.h new file mode 100644 index 0000000000..64798a3727 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/thashx4.h @@ -0,0 +1,20 @@ +#ifndef SPX_THASHX4_H +#define SPX_THASHX4_H + +#include + +#include "context.h" +#include "params.h" + +#define thashx4 SPX_NAMESPACE(thashx4) +void thashx4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addrx4[4 * 8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/utils.c b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/utils.c new file mode 100644 index 0000000000..177b541fb9 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/utils.c @@ -0,0 +1,148 @@ +#include + +#include "utils.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "thash.h" + +/** + * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. + */ +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in) { + int i; + + /* Iterate over out in decreasing order, for big-endianness. */ + for (i = (signed int)outlen - 1; i >= 0; i--) { + out[i] = in & 0xff; + in = in >> 8; + } +} + +void u32_to_bytes(unsigned char *out, uint32_t in) { + out[0] = (unsigned char)(in >> 24); + out[1] = (unsigned char)(in >> 16); + out[2] = (unsigned char)(in >> 8); + out[3] = (unsigned char)in; +} + +/** + * Converts the inlen bytes in 'in' from big-endian byte order to an integer. + */ +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { + unsigned long long retval = 0; + unsigned int i; + + for (i = 0; i < inlen; i++) { + retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); + } + return retval; +} + +/** + * Computes a root node given a leaf and an auth path. + * Expects address to be complete other than the tree_height and tree_index. + */ +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]) { + uint32_t i; + unsigned char buffer[2 * SPX_N]; + + /* If leaf_idx is odd (last bit = 1), current path element is a right child + and auth_path has to go left. Otherwise it is the other way around. */ + if (leaf_idx & 1) { + memcpy(buffer + SPX_N, leaf, SPX_N); + memcpy(buffer, auth_path, SPX_N); + } else { + memcpy(buffer, leaf, SPX_N); + memcpy(buffer + SPX_N, auth_path, SPX_N); + } + auth_path += SPX_N; + + for (i = 0; i < tree_height - 1; i++) { + leaf_idx >>= 1; + idx_offset >>= 1; + /* Set the address of the node we're creating. */ + set_tree_height(addr, i + 1); + set_tree_index(addr, leaf_idx + idx_offset); + + /* Pick the right or left neighbor, depending on parity of the node. */ + if (leaf_idx & 1) { + thash(buffer + SPX_N, buffer, 2, ctx, addr); + memcpy(buffer, auth_path, SPX_N); + } else { + thash(buffer, buffer, 2, ctx, addr); + memcpy(buffer + SPX_N, auth_path, SPX_N); + } + auth_path += SPX_N; + } + + /* The last iteration is exceptional; we do not copy an auth_path node. */ + leaf_idx >>= 1; + idx_offset >>= 1; + set_tree_height(addr, tree_height); + set_tree_index(addr, leaf_idx + idx_offset); + thash(root, buffer, 2, ctx, addr); +} + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx * /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]) { + PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); + PQCLEAN_VLA(unsigned int, heights, tree_height + 1); + unsigned int offset = 0; + uint32_t idx; + uint32_t tree_idx; + + for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { + /* Add the next leaf node to the stack. */ + gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); + offset++; + heights[offset - 1] = 0; + + /* If this is a node we need for the auth path.. */ + if ((leaf_idx ^ 0x1) == idx) { + memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); + } + + /* While the top-most nodes are of equal height.. */ + while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { + /* Compute index of the new node, in the next layer. */ + tree_idx = (idx >> (heights[offset - 1] + 1)); + + /* Set the address of the node we're creating. */ + set_tree_height(tree_addr, heights[offset - 1] + 1); + set_tree_index(tree_addr, + tree_idx + (idx_offset >> (heights[offset - 1] + 1))); + /* Hash the top-most nodes from the stack together. */ + thash(stack + (offset - 2)*SPX_N, + stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); + offset--; + /* Note that the top-most node is now one layer higher. */ + heights[offset - 1]++; + + /* If this is a node we need for the auth path.. */ + if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { + memcpy(auth_path + heights[offset - 1]*SPX_N, + stack + (offset - 1)*SPX_N, SPX_N); + } + } + } + memcpy(root, stack, SPX_N); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/utils.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/utils.h new file mode 100644 index 0000000000..64f5d5a53a --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/utils.h @@ -0,0 +1,58 @@ +#ifndef SPX_UTILS_H +#define SPX_UTILS_H + +#include + +#include "compat.h" +#include "context.h" +#include "params.h" + + +/* To support MSVC use alloca() instead of VLAs. See #20. */ + + +/** + * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. + */ +#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in); +#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) +void u32_to_bytes(unsigned char *out, uint32_t in); + +/** + * Converts the inlen bytes in 'in' from big-endian byte order to an integer. + */ +#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); + +/** + * Computes a root node given a leaf and an auth path. + * Expects address to be complete other than the tree_height and tree_index. + */ +#define compute_root SPX_NAMESPACE(compute_root) +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]); + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +#define treehash SPX_NAMESPACE(treehash) +void treehash(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx *ctx /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]); + + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/utilsx4.c b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/utilsx4.c new file mode 100644 index 0000000000..1638677194 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/utilsx4.c @@ -0,0 +1,138 @@ +#include + +#include "utilsx4.h" + +#include "address.h" +#include "params.h" +#include "thashx4.h" +#include "utils.h" + +/* + * Generate the entire Merkle tree, computing the authentication path for leaf_idx, + * and the resulting root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) + * + * This expects tree_addrx4 to be initialized to 4 parallel addr structures for + * the Merkle tree nodes + * + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + * + * This works by using the standard Merkle tree building algorithm, except + * that each 'node' tracked is actually 4 consecutive nodes in the real tree. + * When we combine two logical nodes ABCD and WXYZ, we perform the H + * operation on adjacent real nodes, forming the parent logical node + * (AB)(CD)(WX)(YZ) + * + * When we get to the top two levels of the real tree (where there is only + * one logical node), we continue this operation two more times; the right + * most real node will by the actual root (and the other 3 nodes will be + * garbage). We follow the same thashx4 logic so that the 'extract + * authentication path components' part of the loop is still executed (and + * to simplify the code somewhat) + * + * This currently assumes tree_height >= 2; I suspect that doing an adjusting + * idx, addr_idx on the gen_leafx4 call if tree_height < 2 would fix it; since + * we don't actually use such short trees, I haven't bothered + */ +void treehashx4(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, + uint32_t tree_height, + void (*gen_leafx4)( + unsigned char * /* Where to write the leaves */, + const spx_ctx *, + uint32_t idx, void *info), + uint32_t tree_addrx4[4 * 8], + void *info) { + /* This is where we keep the intermediate nodes */ + PQCLEAN_VLA(unsigned char, stackx4, tree_height * 4 * SPX_N); + uint32_t left_adj = 0, prev_left_adj = 0; /* When we're doing the top 3 */ + /* levels, the left-most part of the tree isn't at the beginning */ + /* of current[]. These give the offset of the actual start */ + + uint32_t idx; + uint32_t max_idx = (1U << (tree_height - 2)) - 1; + for (idx = 0;; idx++) { + unsigned char current[4 * SPX_N]; /* Current logical node */ + gen_leafx4( current, ctx, 4 * idx + idx_offset, + info ); + + /* Now combine the freshly generated right node with previously */ + /* generated left ones */ + uint32_t internal_idx_offset = idx_offset; + uint32_t internal_idx = idx; + uint32_t internal_leaf = leaf_idx; + uint32_t h; /* The height we are in the Merkle tree */ + for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { + + /* Special processing if we're at the top of the tree */ + if (h >= tree_height - 2) { + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[3 * SPX_N], SPX_N ); + return; + } + /* The tree indexing logic is a bit off in this case */ + /* Adjust it so that the left-most node of the part of */ + /* the tree that we're processing has index 0 */ + prev_left_adj = left_adj; + left_adj = 4U - (1 << (tree_height - h - 1)); + } + + /* Check if we hit the top of the tree */ + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[3 * SPX_N], SPX_N ); + return; + } + + /* + * Check if one of the nodes we have is a part of the + * authentication path; if it is, write it out + */ + if ((((internal_idx << 2) ^ internal_leaf) & ~0x3U) == 0) { + memcpy( &auth_path[ h * SPX_N ], + ¤t[(((internal_leaf & 3) ^ 1) + prev_left_adj) * SPX_N], + SPX_N ); + } + + /* + * Check if we're at a left child; if so, stop going up the stack + * Exception: if we've reached the end of the tree, keep on going + * (so we combine the last 4 nodes into the one root node in two + * more iterations) + */ + if ((internal_idx & 1) == 0 && idx < max_idx) { + break; + } + + /* Ok, we're at a right node (or doing the top 3 levels) */ + /* Now combine the left and right logical nodes together */ + + /* Set the address of the node we're creating. */ + unsigned int j; + internal_idx_offset >>= 1; + for (j = 0; j < 4; j++) { + set_tree_height(tree_addrx4 + j * 8, h + 1); + set_tree_index(tree_addrx4 + j * 8, + (4 / 2) * (internal_idx & ~1U) + j - left_adj + internal_idx_offset ); + } + unsigned char *left = &stackx4[h * 4 * SPX_N]; + thashx4( ¤t[0 * SPX_N], + ¤t[1 * SPX_N], + ¤t[2 * SPX_N], + ¤t[3 * SPX_N], + &left [0 * SPX_N], + &left [2 * SPX_N], + ¤t[0 * SPX_N], + ¤t[2 * SPX_N], + 2, ctx, tree_addrx4); + } + + /* We've hit a left child; save the current for when we get the */ + /* corresponding right right */ + memcpy( &stackx4[h * 4 * SPX_N], current, 4 * SPX_N); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/utilsx4.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/utilsx4.h new file mode 100644 index 0000000000..facb874b18 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/utilsx4.h @@ -0,0 +1,30 @@ +#ifndef SPX_UTILSX4_H +#define SPX_UTILSX4_H + +#include + +#include "context.h" +#include "params.h" + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + * + * This implementation uses AVX to compute internal nodes 4 at a time (in + * parallel) + */ +#define treehashx4 SPX_NAMESPACE(treehashx4) +void treehashx4(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leafx4)( + unsigned char * /* Where to write the leaves */, + const spx_ctx * /* ctx */, + uint32_t addr_idx, void *info), + uint32_t tree_addrx4[4 * 8], void *info); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/wots.c b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/wots.c new file mode 100644 index 0000000000..4d5041ce05 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/wots.c @@ -0,0 +1,269 @@ +#include +#include + +#include "wots.h" + +#include "address.h" +#include "hash.h" +#include "hashx4.h" +#include "params.h" +#include "thash.h" +#include "thashx4.h" +#include "utils.h" +#include "utilsx4.h" +#include "wotsx4.h" + +// TODO clarify address expectations, and make them more uniform. +// TODO i.e. do we expect types to be set already? +// TODO and do we expect modifications or copies? + +/** + * Computes up the chains + */ +static void gen_chains( + unsigned char *out, + const unsigned char *in, + unsigned int start[SPX_WOTS_LEN], + const unsigned int steps[SPX_WOTS_LEN], + const spx_ctx *ctx, + uint32_t addr[8]) { + uint32_t i, j, k, idx, watching; + int done; + unsigned char empty[SPX_N]; + unsigned char *bufs[4]; + uint32_t addrs[8 * 4]; + + int l; + uint16_t counts[SPX_WOTS_W] = { 0 }; + uint16_t idxs[SPX_WOTS_LEN]; + uint16_t total, newTotal; + + /* set addrs = {addr, addr, addr, addr} */ + for (j = 0; j < 4; j++) { + memcpy(addrs + j * 8, addr, sizeof(uint32_t) * 8); + } + + /* Initialize out with the value at position 'start'. */ + memcpy(out, in, SPX_WOTS_LEN * SPX_N); + + /* Sort the chains in reverse order by steps using counting sort. */ + for (i = 0; i < SPX_WOTS_LEN; i++) { + counts[steps[i]]++; + } + total = 0; + for (l = SPX_WOTS_W - 1; l >= 0; l--) { + newTotal = counts[l] + total; + counts[l] = total; + total = newTotal; + } + for (i = 0; i < SPX_WOTS_LEN; i++) { + idxs[counts[steps[i]]] = (uint16_t)i; + counts[steps[i]]++; + } + + /* We got our work cut out for us: do it! */ + for (i = 0; i < SPX_WOTS_LEN; i += 4) { + for (j = 0; j < 4 && i + j < SPX_WOTS_LEN; j++) { + idx = idxs[i + j]; + set_chain_addr(addrs + j * 8, idx); + bufs[j] = out + SPX_N * idx; + } + + /* As the chains are sorted in reverse order, we know that the first + * chain is the longest and the last one is the shortest. We keep + * an eye on whether the last chain is done and then on the one before, + * et cetera. */ + watching = 3; + done = 0; + while (i + watching >= SPX_WOTS_LEN) { + bufs[watching] = &empty[0]; + watching--; + } + + for (k = 0;; k++) { + while (k == steps[idxs[i + watching]]) { + bufs[watching] = &empty[0]; + if (watching == 0) { + done = 1; + break; + } + watching--; + } + if (done) { + break; + } + for (j = 0; j < watching + 1; j++) { + set_hash_addr(addrs + j * 8, k + start[idxs[i + j]]); + } + + thashx4(bufs[0], bufs[1], bufs[2], bufs[3], + bufs[0], bufs[1], bufs[2], bufs[3], 1, ctx, addrs); + } + } +} + +/** + * base_w algorithm as described in draft. + * Interprets an array of bytes as integers in base w. + * This only works when log_w is a divisor of 8. + */ +static void base_w(unsigned int *output, const int out_len, + const unsigned char *input) { + int in = 0; + int out = 0; + unsigned char total = 0; + int bits = 0; + int consumed; + + for (consumed = 0; consumed < out_len; consumed++) { + if (bits == 0) { + total = input[in]; + in++; + bits += 8; + } + bits -= SPX_WOTS_LOGW; + output[out] = (total >> bits) & (SPX_WOTS_W - 1); + out++; + } +} + +/* Computes the WOTS+ checksum over a message (in base_w). */ +static void wots_checksum(unsigned int *csum_base_w, + const unsigned int *msg_base_w) { + unsigned int csum = 0; + unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; + unsigned int i; + + /* Compute checksum. */ + for (i = 0; i < SPX_WOTS_LEN1; i++) { + csum += SPX_WOTS_W - 1 - msg_base_w[i]; + } + + /* Convert checksum to base_w. */ + /* Make sure expected empty zero bits are the least significant bits. */ + csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); + ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); + base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); +} + +/* Takes a message and derives the matching chain lengths. */ +void chain_lengths(unsigned int *lengths, const unsigned char *msg) { + base_w(lengths, SPX_WOTS_LEN1, msg); + wots_checksum(lengths + SPX_WOTS_LEN1, lengths); +} + +/** + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. + * + * Writes the computed public key to 'pk'. + */ +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]) { + unsigned int steps[SPX_WOTS_LEN]; + unsigned int start[SPX_WOTS_LEN]; + uint32_t i; + + chain_lengths(start, msg); + + for (i = 0; i < SPX_WOTS_LEN; i++) { + steps[i] = SPX_WOTS_W - 1 - start[i]; + } + + gen_chains(pk, sig, start, steps, ctx, addr); +} + +/* + * This generates 4 sequential WOTS public keys + * It also generates the WOTS signature if leaf_info indicates + * that we're signing with one of these WOTS keys + */ +void wots_gen_leafx4(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info) { + struct leaf_info_x4 *info = v_info; + uint32_t *leaf_addr = info->leaf_addr; + uint32_t *pk_addr = info->pk_addr; + unsigned int i, j, k; + unsigned char pk_buffer[ 4 * SPX_WOTS_BYTES ]; + unsigned wots_offset = SPX_WOTS_BYTES; + unsigned char *buffer; + uint32_t wots_k_mask; + unsigned wots_sign_index; + + if (((leaf_idx ^ info->wots_sign_leaf) & ~3U) == 0) { + /* We're traversing the leaf that's signing; generate the WOTS */ + /* signature */ + wots_k_mask = 0; + wots_sign_index = info->wots_sign_leaf & 3; /* Which of of the 4 */ + /* 4 slots do the signatures come from */ + } else { + /* Nope, we're just generating pk's; turn off the signature logic */ + wots_k_mask = (uint32_t)~0; + wots_sign_index = 0; + } + + for (j = 0; j < 4; j++) { + set_keypair_addr( leaf_addr + j * 8, leaf_idx + j ); + set_keypair_addr( pk_addr + j * 8, leaf_idx + j ); + } + + for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { + uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k to */ + /* the step if we're generating a signature, ~0 if we're not */ + + /* Start with the secret seed */ + for (j = 0; j < 4; j++) { + set_chain_addr(leaf_addr + j * 8, i); + set_hash_addr(leaf_addr + j * 8, 0); + set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTSPRF); + } + prf_addrx4(buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + buffer + 2 * wots_offset, + buffer + 3 * wots_offset, + ctx, leaf_addr); + + for (j = 0; j < 4; j++) { + set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTS); + } + + /* Iterate down the WOTS chain */ + for (k = 0;; k++) { + /* Check if one of the values we have needs to be saved as a */ + /* part of the WOTS signature */ + if (k == wots_k) { + memcpy( info->wots_sig + i * SPX_N, + buffer + wots_sign_index * wots_offset, SPX_N ); + } + + /* Check if we hit the top of the chain */ + if (k == SPX_WOTS_W - 1) { + break; + } + + /* Iterate one step on all 4 chains */ + for (j = 0; j < 4; j++) { + set_hash_addr(leaf_addr + j * 8, k); + } + thashx4(buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + buffer + 2 * wots_offset, + buffer + 3 * wots_offset, + buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + buffer + 2 * wots_offset, + buffer + 3 * wots_offset, 1, ctx, leaf_addr); + } + } + + /* Do the final thash to generate the public keys */ + thashx4(dest + 0 * SPX_N, + dest + 1 * SPX_N, + dest + 2 * SPX_N, + dest + 3 * SPX_N, + pk_buffer + 0 * wots_offset, + pk_buffer + 1 * wots_offset, + pk_buffer + 2 * wots_offset, + pk_buffer + 3 * wots_offset, SPX_WOTS_LEN, ctx, pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/wots.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/wots.h new file mode 100644 index 0000000000..4e7692eeef --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/wots.h @@ -0,0 +1,25 @@ +#ifndef SPX_WOTS_H +#define SPX_WOTS_H + +#include + +#include "context.h" +#include "params.h" + +/** + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. + * + * Writes the computed public key to 'pk'. + */ +#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]); + +/* + * Compute the chain lengths needed for a given message hash + */ +#define chain_lengths SPX_NAMESPACE(chain_lengths) +void chain_lengths(unsigned int *lengths, const unsigned char *msg); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/wotsx4.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/wotsx4.h new file mode 100644 index 0000000000..cd634f1743 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/wotsx4.h @@ -0,0 +1,41 @@ +#ifndef WOTSX4_H_ +#define WOTSX4_H_ + +#include + +#include "params.h" + +/* + * This is here to provide an interface to the internal wots_gen_leafx4 + * routine. While this routine is not referenced in the package outside of + * wots.c, it is called from the stand-alone benchmark code to characterize + * the performance + */ +struct leaf_info_x4 { + unsigned char *wots_sig; + uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ + uint32_t *wots_steps; + uint32_t leaf_addr[4 * 8]; + uint32_t pk_addr[4 * 8]; +}; + +/* Macro to set the leaf_info to something 'benign', that is, it would */ +/* run with the same time as it does during the real signing process */ +/* Used only by the benchmark code */ +#define INITIALIZE_LEAF_INFO_X4(info, addr, step_buffer) { \ + (info).wots_sig = 0; \ + (info).wots_sign_leaf = ~0; \ + (info).wots_steps = step_buffer; \ + int i; \ + for (i=0; i<4; i++) { \ + memcpy( &(info).leaf_addr[8*i], addr, 32 ); \ + memcpy( &(info).pk_addr[8*i], addr, 32 ); \ + } \ + } + +#define wots_gen_leafx4 SPX_NAMESPACE(wots_gen_leafx4) +void wots_gen_leafx4(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info); + +#endif /* WOTSX4_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/LICENSE b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/LICENSE new file mode 100644 index 0000000000..670154e353 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/LICENSE @@ -0,0 +1,116 @@ +CC0 1.0 Universal + +Statement of Purpose + +The laws of most jurisdictions throughout the world automatically confer +exclusive Copyright and Related Rights (defined below) upon the creator and +subsequent owner(s) (each and all, an "owner") of an original work of +authorship and/or a database (each, a "Work"). + +Certain owners wish to permanently relinquish those rights to a Work for the +purpose of contributing to a commons of creative, cultural and scientific +works ("Commons") that the public can reliably and without fear of later +claims of infringement build upon, modify, incorporate in other works, reuse +and redistribute as freely as possible in any form whatsoever and for any +purposes, including without limitation commercial purposes. These owners may +contribute to the Commons to promote the ideal of a free culture and the +further production of creative, cultural and scientific works, or to gain +reputation or greater distribution for their Work in part through the use and +efforts of others. + +For these and/or other purposes and motivations, and without any expectation +of additional consideration or compensation, the person associating CC0 with a +Work (the "Affirmer"), to the extent that he or she is an owner of Copyright +and Related Rights in the Work, voluntarily elects to apply CC0 to the Work +and publicly distribute the Work under its terms, with knowledge of his or her +Copyright and Related Rights in the Work and the meaning and intended legal +effect of CC0 on those rights. + +1. Copyright and Related Rights. A Work made available under CC0 may be +protected by copyright and related or neighboring rights ("Copyright and +Related Rights"). Copyright and Related Rights include, but are not limited +to, the following: + + i. the right to reproduce, adapt, distribute, perform, display, communicate, + and translate a Work; + + ii. moral rights retained by the original author(s) and/or performer(s); + + iii. publicity and privacy rights pertaining to a person's image or likeness + depicted in a Work; + + iv. rights protecting against unfair competition in regards to a Work, + subject to the limitations in paragraph 4(a), below; + + v. rights protecting the extraction, dissemination, use and reuse of data in + a Work; + + vi. database rights (such as those arising under Directive 96/9/EC of the + European Parliament and of the Council of 11 March 1996 on the legal + protection of databases, and under any national implementation thereof, + including any amended or successor version of such directive); and + + vii. other similar, equivalent or corresponding rights throughout the world + based on applicable law or treaty, and any national implementations thereof. + +2. Waiver. To the greatest extent permitted by, but not in contravention of, +applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and +unconditionally waives, abandons, and surrenders all of Affirmer's Copyright +and Related Rights and associated claims and causes of action, whether now +known or unknown (including existing as well as future claims and causes of +action), in the Work (i) in all territories worldwide, (ii) for the maximum +duration provided by applicable law or treaty (including future time +extensions), (iii) in any current or future medium and for any number of +copies, and (iv) for any purpose whatsoever, including without limitation +commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes +the Waiver for the benefit of each member of the public at large and to the +detriment of Affirmer's heirs and successors, fully intending that such Waiver +shall not be subject to revocation, rescission, cancellation, termination, or +any other legal or equitable action to disrupt the quiet enjoyment of the Work +by the public as contemplated by Affirmer's express Statement of Purpose. + +3. Public License Fallback. Should any part of the Waiver for any reason be +judged legally invalid or ineffective under applicable law, then the Waiver +shall be preserved to the maximum extent permitted taking into account +Affirmer's express Statement of Purpose. In addition, to the extent the Waiver +is so judged Affirmer hereby grants to each affected person a royalty-free, +non transferable, non sublicensable, non exclusive, irrevocable and +unconditional license to exercise Affirmer's Copyright and Related Rights in +the Work (i) in all territories worldwide, (ii) for the maximum duration +provided by applicable law or treaty (including future time extensions), (iii) +in any current or future medium and for any number of copies, and (iv) for any +purpose whatsoever, including without limitation commercial, advertising or +promotional purposes (the "License"). The License shall be deemed effective as +of the date CC0 was applied by Affirmer to the Work. Should any part of the +License for any reason be judged legally invalid or ineffective under +applicable law, such partial invalidity or ineffectiveness shall not +invalidate the remainder of the License, and in such case Affirmer hereby +affirms that he or she will not (i) exercise any of his or her remaining +Copyright and Related Rights in the Work or (ii) assert any associated claims +and causes of action with respect to the Work, in either case contrary to +Affirmer's express Statement of Purpose. + +4. Limitations and Disclaimers. + + a. No trademark or patent rights held by Affirmer are waived, abandoned, + surrendered, licensed or otherwise affected by this document. + + b. Affirmer offers the Work as-is and makes no representations or warranties + of any kind concerning the Work, express, implied, statutory or otherwise, + including without limitation warranties of title, merchantability, fitness + for a particular purpose, non infringement, or the absence of latent or + other defects, accuracy, or the present or absence of errors, whether or not + discoverable, all to the greatest extent permissible under applicable law. + + c. Affirmer disclaims responsibility for clearing rights of other persons + that may apply to the Work or any use thereof, including without limitation + any person's Copyright and Related Rights in the Work. Further, Affirmer + disclaims responsibility for obtaining any necessary consents, permissions + or other rights required for any use of the Work. + + d. Affirmer understands and acknowledges that Creative Commons is not a + party to this document and has no duty or obligation with respect to this + CC0 or use of the Work. + +For more information, please see + diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/address.c b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/address.c new file mode 100644 index 0000000000..b956e9cb29 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/address.c @@ -0,0 +1,91 @@ +#include +#include + +#include "address.h" +#include "params.h" +#include "utils.h" + +/* + * Specify which level of Merkle tree (the "layer") we're working on + */ +void set_layer_addr(uint32_t addr[8], uint32_t layer) { + ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; +} + +/* + * Specify which Merkle tree within the level (the "tree address") we're working on + */ +void set_tree_addr(uint32_t addr[8], uint64_t tree) { + ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); +} + +/* + * Specify the reason we'll use this address structure for, that is, what + * hash will we compute with it. This is used so that unrelated types of + * hashes don't accidentally get the same address structure. The type will be + * one of the SPX_ADDR_TYPE constants + */ +void set_type(uint32_t addr[8], uint32_t type) { + ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; +} + +/* + * Copy the layer and tree fields of the address structure. This is used + * when we're doing multiple types of hashes within the same Merkle tree + */ +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); +} + +/* These functions are used for OTS addresses. */ + +/* + * Specify which Merkle leaf we're working on; that is, which OTS keypair + * we're talking about. + */ +void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { + ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; +} + +/* + * Copy the layer, tree and keypair fields of the address structure. This is + * used when we're doing multiple things within the same OTS keypair + */ +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); + ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; +} + +/* + * Specify which Merkle chain within the OTS we're working with + * (the chain address) + */ +void set_chain_addr(uint32_t addr[8], uint32_t chain) { + ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; +} + +/* + * Specify where in the Merkle chain we are +* (the hash address) + */ +void set_hash_addr(uint32_t addr[8], uint32_t hash) { + ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; +} + +/* These functions are used for all hash tree addresses (including FORS). */ + +/* + * Specify the height of the node in the Merkle/FORS tree we are in + * (the tree height) + */ +void set_tree_height(uint32_t addr[8], uint32_t tree_height) { + ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; +} + +/* + * Specify the distance from the left edge of the node in the Merkle/FORS tree + * (the tree index) + */ +void set_tree_index(uint32_t addr[8], uint32_t tree_index) { + u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/address.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/address.h new file mode 100644 index 0000000000..24a84eb40c --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/address.h @@ -0,0 +1,52 @@ +#ifndef SPX_ADDRESS_H +#define SPX_ADDRESS_H + +#include + +#include "params.h" + +/* The hash types that are passed to set_type */ +#define SPX_ADDR_TYPE_WOTS 0 +#define SPX_ADDR_TYPE_WOTSPK 1 +#define SPX_ADDR_TYPE_HASHTREE 2 +#define SPX_ADDR_TYPE_FORSTREE 3 +#define SPX_ADDR_TYPE_FORSPK 4 +#define SPX_ADDR_TYPE_WOTSPRF 5 +#define SPX_ADDR_TYPE_FORSPRF 6 + +#define set_layer_addr SPX_NAMESPACE(set_layer_addr) +void set_layer_addr(uint32_t addr[8], uint32_t layer); + +#define set_tree_addr SPX_NAMESPACE(set_tree_addr) +void set_tree_addr(uint32_t addr[8], uint64_t tree); + +#define set_type SPX_NAMESPACE(set_type) +void set_type(uint32_t addr[8], uint32_t type); + +/* Copies the layer and tree part of one address into the other */ +#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); + +/* These functions are used for WOTS and FORS addresses. */ + +#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) +void set_keypair_addr(uint32_t addr[8], uint32_t keypair); + +#define set_chain_addr SPX_NAMESPACE(set_chain_addr) +void set_chain_addr(uint32_t addr[8], uint32_t chain); + +#define set_hash_addr SPX_NAMESPACE(set_hash_addr) +void set_hash_addr(uint32_t addr[8], uint32_t hash); + +#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); + +/* These functions are used for all hash tree addresses (including FORS). */ + +#define set_tree_height SPX_NAMESPACE(set_tree_height) +void set_tree_height(uint32_t addr[8], uint32_t tree_height); + +#define set_tree_index SPX_NAMESPACE(set_tree_index) +void set_tree_index(uint32_t addr[8], uint32_t tree_index); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/api.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/api.h new file mode 100644 index 0000000000..292c1d0693 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/api.h @@ -0,0 +1,77 @@ +#ifndef PQCLEAN_SPHINCSSHAKE256SROBUST_CLEAN_API_H +#define PQCLEAN_SPHINCSSHAKE256SROBUST_CLEAN_API_H + +#include +#include + +#define PQCLEAN_SPHINCSSHAKE256SROBUST_CLEAN_CRYPTO_ALGNAME "SPHINCS+-shake-256s-robust" + +#define PQCLEAN_SPHINCSSHAKE256SROBUST_CLEAN_CRYPTO_SECRETKEYBYTES 128 +#define PQCLEAN_SPHINCSSHAKE256SROBUST_CLEAN_CRYPTO_PUBLICKEYBYTES 64 +#define PQCLEAN_SPHINCSSHAKE256SROBUST_CLEAN_CRYPTO_BYTES 29792 + +#define PQCLEAN_SPHINCSSHAKE256SROBUST_CLEAN_CRYPTO_SEEDBYTES 96 + +/* + * Returns the length of a secret key, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE256SROBUST_CLEAN_crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE256SROBUST_CLEAN_crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE256SROBUST_CLEAN_crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE256SROBUST_CLEAN_crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +int PQCLEAN_SPHINCSSHAKE256SROBUST_CLEAN_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +int PQCLEAN_SPHINCSSHAKE256SROBUST_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +int PQCLEAN_SPHINCSSHAKE256SROBUST_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +int PQCLEAN_SPHINCSSHAKE256SROBUST_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, + const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +int PQCLEAN_SPHINCSSHAKE256SROBUST_CLEAN_crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +int PQCLEAN_SPHINCSSHAKE256SROBUST_CLEAN_crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/context.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/context.h new file mode 100644 index 0000000000..9f8a40ab4e --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/context.h @@ -0,0 +1,22 @@ +#ifndef SPX_CONTEXT_H +#define SPX_CONTEXT_H + +#include +#include + +#include "params.h" + +typedef struct { + uint8_t pub_seed[SPX_N]; + uint8_t sk_seed[SPX_N]; + + +} spx_ctx; + +#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) +void initialize_hash_function(spx_ctx *ctx); + +#define free_hash_function SPX_NAMESPACE(free_hash_function) +void free_hash_function(spx_ctx *ctx); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/context_shake.c b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/context_shake.c new file mode 100644 index 0000000000..9614a103d3 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/context_shake.c @@ -0,0 +1,12 @@ +#include "context.h" + +/* For SHAKE256, there is no immediate reason to initialize at the start, + so this function is an empty operation. */ +void initialize_hash_function(spx_ctx *ctx) { + (void)ctx; /* Suppress an 'unused parameter' warning. */ +} + +// in case the hash function api is heap-based. +void free_hash_function(spx_ctx *ctx) { + (void)ctx; +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/fors.c b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/fors.c new file mode 100644 index 0000000000..96ca72e986 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/fors.c @@ -0,0 +1,156 @@ +#include +#include +#include + +#include "fors.h" + +#include "address.h" +#include "hash.h" +#include "thash.h" +#include "utils.h" +#include "utilsx1.h" + +static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + prf_addr(sk, ctx, fors_leaf_addr); +} + +static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, + const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + thash(leaf, sk, 1, ctx, fors_leaf_addr); +} + +struct fors_gen_leaf_info { + uint32_t leaf_addrx[8]; +}; + +static void fors_gen_leafx1(unsigned char *leaf, + const spx_ctx *ctx, + uint32_t addr_idx, void *info) { + struct fors_gen_leaf_info *fors_info = info; + uint32_t *fors_leaf_addr = fors_info->leaf_addrx; + + /* Only set the parts that the caller doesn't set */ + set_tree_index(fors_leaf_addr, addr_idx); + set_type(fors_leaf_addr, SPX_ADDR_TYPE_FORSPRF); + fors_gen_sk(leaf, ctx, fors_leaf_addr); + + set_type(fors_leaf_addr, SPX_ADDR_TYPE_FORSTREE); + fors_sk_to_leaf(leaf, leaf, + ctx, fors_leaf_addr); +} + +/** + * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + * Assumes indices has space for SPX_FORS_TREES integers. + */ +static void message_to_indices(uint32_t *indices, const unsigned char *m) { + unsigned int i, j; + unsigned int offset = 0; + + for (i = 0; i < SPX_FORS_TREES; i++) { + indices[i] = 0; + for (j = 0; j < SPX_FORS_HEIGHT; j++) { + indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); + offset++; + } + } +} + +/** + * Signs a message m, deriving the secret key from sk_seed and the FTS address. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + uint32_t fors_tree_addr[8] = {0}; + struct fors_gen_leaf_info fors_info = {0}; + uint32_t *fors_leaf_addr = fors_info.leaf_addrx; + uint32_t fors_pk_addr[8] = {0}; + uint32_t idx_offset; + unsigned int i; + + copy_keypair_addr(fors_tree_addr, fors_addr); + copy_keypair_addr(fors_leaf_addr, fors_addr); + + copy_keypair_addr(fors_pk_addr, fors_addr); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); + + message_to_indices(indices, m); + + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); + + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); + + /* Include the secret key part that produces the selected leaf node. */ + fors_gen_sk(sig, ctx, fors_tree_addr); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + sig += SPX_N; + + /* Compute the authentication path for this leaf node. */ + treehashx1(roots + i * SPX_N, sig, ctx, + indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx1, + fors_tree_addr, &fors_info); + + sig += SPX_N * SPX_FORS_HEIGHT; + } + + /* Hash horizontally across all tree roots to derive the public key. */ + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); +} + +/** + * Derives the FORS public key from a signature. + * This can be used for verification by comparing to a known public key, or to + * subsequently verify a signature on the derived public key. The latter is the + * typical use-case when used as an FTS below an OTS in a hypertree. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + unsigned char leaf[SPX_N]; + uint32_t fors_tree_addr[8] = {0}; + uint32_t fors_pk_addr[8] = {0}; + uint32_t idx_offset; + unsigned int i; + + copy_keypair_addr(fors_tree_addr, fors_addr); + copy_keypair_addr(fors_pk_addr, fors_addr); + + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); + + message_to_indices(indices, m); + + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); + + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + + /* Derive the leaf from the included secret key part. */ + fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); + sig += SPX_N; + + /* Derive the corresponding root node of this tree. */ + compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, + sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); + sig += SPX_N * SPX_FORS_HEIGHT; + } + + /* Hash horizontally across all tree roots to derive the public key. */ + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/fors.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/fors.h new file mode 100644 index 0000000000..509140a178 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/fors.h @@ -0,0 +1,32 @@ +#ifndef SPX_FORS_H +#define SPX_FORS_H + +#include + +#include "context.h" +#include "params.h" + +/** + * Signs a message m, deriving the secret key from sk_seed and the FTS address. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +#define fors_sign SPX_NAMESPACE(fors_sign) +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); + +/** + * Derives the FORS public key from a signature. + * This can be used for verification by comparing to a known public key, or to + * subsequently verify a signature on the derived public key. The latter is the + * typical use-case when used as an FTS below an OTS in a hypertree. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/hash.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/hash.h new file mode 100644 index 0000000000..f7c87d4c3c --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/hash.h @@ -0,0 +1,28 @@ +#ifndef SPX_HASH_H +#define SPX_HASH_H + +#include +#include + +#include "context.h" +#include "params.h" + +#define prf_addr SPX_NAMESPACE(prf_addr) +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]); + +#define gen_message_random SPX_NAMESPACE(gen_message_random) +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); + +#define hash_message SPX_NAMESPACE(hash_message) +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); + + + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/hash_shake.c b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/hash_shake.c new file mode 100644 index 0000000000..ff5e7ec918 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/hash_shake.c @@ -0,0 +1,83 @@ +#include +#include + +#include "hash.h" + +#include "address.h" +#include "fips202.h" +#include "params.h" +#include "utils.h" + +/* + * Computes PRF(pk_seed, sk_seed, addr) + */ +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]) { + unsigned char buf[2 * SPX_N + SPX_ADDR_BYTES]; + + memcpy(buf, ctx->pub_seed, SPX_N); + memcpy(buf + SPX_N, addr, SPX_ADDR_BYTES); + memcpy(buf + SPX_N + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); + + shake256(out, SPX_N, buf, 2 * SPX_N + SPX_ADDR_BYTES); +} + +/** + * Computes the message-dependent randomness R, using a secret seed and an + * optional randomization value as well as the message. + */ +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { + (void)ctx; + shake256incctx s_inc; + + shake256_inc_init(&s_inc); + shake256_inc_absorb(&s_inc, sk_prf, SPX_N); + shake256_inc_absorb(&s_inc, optrand, SPX_N); + shake256_inc_absorb(&s_inc, m, mlen); + shake256_inc_finalize(&s_inc); + shake256_inc_squeeze(R, SPX_N, &s_inc); + shake256_inc_ctx_release(&s_inc); +} + +/** + * Computes the message hash using R, the public key, and the message. + * Outputs the message digest and the index of the leaf. The index is split in + * the tree index and the leaf index, for convenient copying to an address. + */ +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { + (void)ctx; +#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) +#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) +#define SPX_LEAF_BITS SPX_TREE_HEIGHT +#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) +#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) + + unsigned char buf[SPX_DGST_BYTES]; + unsigned char *bufp = buf; + shake256incctx s_inc; + + shake256_inc_init(&s_inc); + shake256_inc_absorb(&s_inc, R, SPX_N); + shake256_inc_absorb(&s_inc, pk, SPX_PK_BYTES); + shake256_inc_absorb(&s_inc, m, mlen); + shake256_inc_finalize(&s_inc); + shake256_inc_squeeze(buf, SPX_DGST_BYTES, &s_inc); + shake256_inc_ctx_release(&s_inc); + + memcpy(digest, bufp, SPX_FORS_MSG_BYTES); + bufp += SPX_FORS_MSG_BYTES; + + + *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); + *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); + bufp += SPX_TREE_BYTES; + + *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); + *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/merkle.c b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/merkle.c new file mode 100644 index 0000000000..0c1479fd93 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/merkle.c @@ -0,0 +1,59 @@ +#include +#include + +#include "address.h" +#include "merkle.h" +#include "params.h" +#include "utils.h" +#include "utilsx1.h" +#include "wots.h" +#include "wotsx1.h" + +/* + * This generates a Merkle signature (WOTS signature followed by the Merkle + * authentication path). This is in this file because most of the complexity + * is involved with the WOTS signature; the Merkle authentication path logic + * is mostly hidden in treehashx4 + */ +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf) { + unsigned char *auth_path = sig + SPX_WOTS_BYTES; + struct leaf_info_x1 info = { 0 }; + unsigned steps[ SPX_WOTS_LEN ]; + + info.wots_sig = sig; + chain_lengths(steps, root); + info.wots_steps = steps; + + set_type(&tree_addr[0], SPX_ADDR_TYPE_HASHTREE); + set_type(&info.pk_addr[0], SPX_ADDR_TYPE_WOTSPK); + copy_subtree_addr(&info.leaf_addr[0], wots_addr); + copy_subtree_addr(&info.pk_addr[0], wots_addr); + + info.wots_sign_leaf = idx_leaf; + + treehashx1(root, auth_path, ctx, + idx_leaf, 0, + SPX_TREE_HEIGHT, + wots_gen_leafx1, + tree_addr, &info); +} + +/* Compute root node of the top-most subtree. */ +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { + /* We do not need the auth path in key generation, but it simplifies the + code to have just one treehash routine that computes both root and path + in one function. */ + unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; + uint32_t top_tree_addr[8] = {0}; + uint32_t wots_addr[8] = {0}; + + set_layer_addr(top_tree_addr, SPX_D - 1); + set_layer_addr(wots_addr, SPX_D - 1); + + merkle_sign(auth_path, root, ctx, + wots_addr, top_tree_addr, + (uint32_t)~0 /* ~0 means "don't bother generating an auth path */ ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/merkle.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/merkle.h new file mode 100644 index 0000000000..769cf2e970 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/merkle.h @@ -0,0 +1,21 @@ +#ifndef MERKLE_H_ +#define MERKLE_H_ + +#include + +#include "context.h" +#include "params.h" + +/* Generate a Merkle signature (WOTS signature followed by the Merkle */ +/* authentication path) */ +#define merkle_sign SPX_NAMESPACE(merkle_sign) +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf); + +/* Compute the root node of the top-most subtree. */ +#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); + +#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/nistapi.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/nistapi.h new file mode 100644 index 0000000000..3cb71afad4 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/nistapi.h @@ -0,0 +1,87 @@ +#ifndef SPX_API_H +#define SPX_API_H + +#include +#include + +#include "params.h" + +#define CRYPTO_ALGNAME "SPHINCS+" + +#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES +#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES +#define CRYPTO_BYTES SPX_BYTES +#define CRYPTO_SEEDBYTES (3*SPX_N) + +/* + * Returns the length of a secret key, in bytes + */ +#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) +size_t crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) +size_t crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) +size_t crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) +size_t crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +#define crypto_sign SPX_NAMESPACE(crypto_sign) +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/params.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/params.h new file mode 100644 index 0000000000..a4b3659a94 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/params.h @@ -0,0 +1,56 @@ +#ifndef SPX_PARAMS_H +#define SPX_PARAMS_H + +#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSSHAKE256SROBUST_CLEAN_##s + +/* Hash output length in bytes. */ +#define SPX_N 32 +/* Height of the hypertree. */ +#define SPX_FULL_HEIGHT 64 +/* Number of subtree layer. */ +#define SPX_D 8 +/* FORS tree dimensions. */ +#define SPX_FORS_HEIGHT 14 +#define SPX_FORS_TREES 22 +/* Winternitz parameter, */ +#define SPX_WOTS_W 16 + +/* The hash function is defined by linking a different hash.c file, as opposed + to setting a #define constant. */ + +/* For clarity */ +#define SPX_ADDR_BYTES 32 + +/* WOTS parameters. */ +#define SPX_WOTS_LOGW 4 + +#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) + +/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ +#define SPX_WOTS_LEN2 3 + +#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) +#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) +#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES + +/* Subtree size. */ +#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) + +//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT +// #error SPX_D should always divide SPX_FULL_HEIGHT +//#endif + +/* FORS parameters. */ +#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) +#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) +#define SPX_FORS_PK_BYTES SPX_N + +/* Resulting SPX sizes. */ +#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ + SPX_FULL_HEIGHT * SPX_N) +#define SPX_PK_BYTES (2 * SPX_N) +#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) + +#include "shake_offsets.h" + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/shake_offsets.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/shake_offsets.h new file mode 100644 index 0000000000..6b28d95d91 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/shake_offsets.h @@ -0,0 +1,21 @@ +#ifndef SHAKE_OFFSETS_H_ +#define SHAKE_OFFSETS_H_ + +/* + * Offsets of various fields in the address structure when we use SHAKE as + * the Sphincs+ hash function + */ + +#define SPX_OFFSET_LAYER 3 /* The byte used to specify the Merkle tree layer */ +#define SPX_OFFSET_TREE 8 /* The start of the 8 byte field used to specify the tree */ +#define SPX_OFFSET_TYPE 19 /* The byte used to specify the hash type (reason) */ +#define SPX_OFFSET_KP_ADDR2 22 /* The high byte used to specify the key pair (which one-time signature) */ +#define SPX_OFFSET_KP_ADDR1 23 /* The low byte used to specify the key pair */ +#define SPX_OFFSET_CHAIN_ADDR 27 /* The byte used to specify the chain address (which Winternitz chain) */ +#define SPX_OFFSET_HASH_ADDR 31 /* The byte used to specify the hash address (where in the Winternitz chain) */ +#define SPX_OFFSET_TREE_HGT 27 /* The byte used to specify the height of this node in the FORS or Merkle tree */ +#define SPX_OFFSET_TREE_INDEX 28 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ + +#define SPX_SHAKE 1 + +#endif /* SHAKE_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/sign.c b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/sign.c new file mode 100644 index 0000000000..9d0c7d1b22 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/sign.c @@ -0,0 +1,286 @@ +#include +#include +#include + +#include "address.h" +#include "context.h" +#include "fors.h" +#include "hash.h" +#include "merkle.h" +#include "nistapi.h" +#include "params.h" +#include "randombytes.h" +#include "thash.h" +#include "utils.h" +#include "wots.h" + +/* + * Returns the length of a secret key, in bytes + */ +size_t crypto_sign_secretkeybytes(void) { + return CRYPTO_SECRETKEYBYTES; +} + +/* + * Returns the length of a public key, in bytes + */ +size_t crypto_sign_publickeybytes(void) { + return CRYPTO_PUBLICKEYBYTES; +} + +/* + * Returns the length of a signature, in bytes + */ +size_t crypto_sign_bytes(void) { + return CRYPTO_BYTES; +} + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +size_t crypto_sign_seedbytes(void) { + return CRYPTO_SEEDBYTES; +} + +/* + * Generates an SPX key pair given a seed of length + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [PUB_SEED || root] + */ +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed) { + spx_ctx ctx; + + /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ + memcpy(sk, seed, CRYPTO_SEEDBYTES); + + memcpy(pk, sk + 2 * SPX_N, SPX_N); + + memcpy(ctx.pub_seed, pk, SPX_N); + memcpy(ctx.sk_seed, sk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + /* Compute root node of the top-most subtree. */ + merkle_gen_root(sk + 3 * SPX_N, &ctx); + + // cleanup + free_hash_function(&ctx); + + memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); + + return 0; +} + +/* + * Generates an SPX key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [PUB_SEED || root] + */ +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { + uint8_t seed[CRYPTO_SEEDBYTES]; + randombytes(seed, CRYPTO_SEEDBYTES); + crypto_sign_seed_keypair(pk, sk, seed); + + return 0; +} + +/** + * Returns an array containing a detached signature. + */ +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk) { + spx_ctx ctx; + + const uint8_t *sk_prf = sk + SPX_N; + const uint8_t *pk = sk + 2 * SPX_N; + + uint8_t optrand[SPX_N]; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t root[SPX_N]; + uint32_t i; + uint64_t tree; + uint32_t idx_leaf; + uint32_t wots_addr[8] = {0}; + uint32_t tree_addr[8] = {0}; + + memcpy(ctx.sk_seed, sk, SPX_N); + memcpy(ctx.pub_seed, pk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + + /* Optionally, signing can be made non-deterministic using optrand. + This can help counter side-channel attacks that would benefit from + getting a large number of traces when the signer uses the same nodes. */ + randombytes(optrand, SPX_N); + /* Compute the digest randomization value. */ + gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); + + /* Derive the message digest and leaf index from R, PK and M. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; + + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); + + /* Sign the message hash using FORS. */ + fors_sign(sig, root, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); + sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; + + /* Update the indices for the next layer. */ + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; + } + + free_hash_function(&ctx); + + *siglen = SPX_BYTES; + + return 0; +} + +/** + * Verifies a detached signature and message under a given public key. + */ +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk) { + spx_ctx ctx; + const uint8_t *pub_root = pk + SPX_N; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t wots_pk[SPX_WOTS_BYTES]; + uint8_t root[SPX_N]; + uint8_t leaf[SPX_N]; + unsigned int i; + uint64_t tree; + uint32_t idx_leaf; + uint32_t wots_addr[8] = {0}; + uint32_t tree_addr[8] = {0}; + uint32_t wots_pk_addr[8] = {0}; + + if (siglen != SPX_BYTES) { + return -1; + } + + memcpy(ctx.pub_seed, pk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); + + /* Derive the message digest and leaf index from R || PK || M. */ + /* The additional SPX_N is a result of the hash domain separator. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; + + /* Layer correctly defaults to 0, so no need to set_layer_addr */ + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); + + fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + /* For each subtree.. */ + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + copy_keypair_addr(wots_pk_addr, wots_addr); + + /* The WOTS public key is only correct if the signature was correct. */ + /* Initially, root is the FORS pk, but on subsequent iterations it is + the root of the subtree below the currently processed subtree. */ + wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); + sig += SPX_WOTS_BYTES; + + /* Compute the leaf node using the WOTS public key. */ + thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); + + /* Compute the root node of this subtree. */ + compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, + &ctx, tree_addr); + sig += SPX_TREE_HEIGHT * SPX_N; + + /* Update the indices for the next layer. */ + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; + } + + // cleanup + free_hash_function(&ctx); + + /* Check if the root node equals the root node in the public key. */ + if (memcmp(root, pub_root, SPX_N) != 0) { + return -1; + } + + return 0; +} + + +/** + * Returns an array containing the signature followed by the message. + */ +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk) { + size_t siglen; + + crypto_sign_signature(sm, &siglen, m, mlen, sk); + + memmove(sm + SPX_BYTES, m, mlen); + *smlen = siglen + mlen; + + return 0; +} + +/** + * Verifies a given signature-message pair under a given public key. + */ +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk) { + /* The API caller does not necessarily know what size a signature should be + but SPHINCS+ signatures are always exactly SPX_BYTES. */ + if (smlen < SPX_BYTES) { + memset(m, 0, smlen); + *mlen = 0; + return -1; + } + + *mlen = smlen - SPX_BYTES; + + if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { + memset(m, 0, smlen); + *mlen = 0; + return -1; + } + + /* If verification was successful, move the message to the right place. */ + memmove(m, sm + SPX_BYTES, *mlen); + + return 0; +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/thash.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/thash.h new file mode 100644 index 0000000000..8687ccfb4d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/thash.h @@ -0,0 +1,13 @@ +#ifndef SPX_THASH_H +#define SPX_THASH_H + +#include "context.h" +#include "params.h" + +#include + +#define thash SPX_NAMESPACE(thash) +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/thash_shake_robust.c b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/thash_shake_robust.c new file mode 100644 index 0000000000..696d53c5cc --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/thash_shake_robust.c @@ -0,0 +1,31 @@ +#include +#include + +#include "thash.h" + +#include "address.h" +#include "params.h" +#include "utils.h" + +#include "fips202.h" + +/** + * Takes an array of inblocks concatenated arrays of SPX_N bytes. + */ +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]) { + PQCLEAN_VLA(uint8_t, buf, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); + PQCLEAN_VLA(uint8_t, bitmask, inblocks * SPX_N); + unsigned int i; + + memcpy(buf, ctx->pub_seed, SPX_N); + memcpy(buf + SPX_N, addr, SPX_ADDR_BYTES); + + shake256(bitmask, inblocks * SPX_N, buf, SPX_N + SPX_ADDR_BYTES); + + for (i = 0; i < inblocks * SPX_N; i++) { + buf[SPX_N + SPX_ADDR_BYTES + i] = in[i] ^ bitmask[i]; + } + + shake256(out, SPX_N, buf, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/utils.c b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/utils.c new file mode 100644 index 0000000000..177b541fb9 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/utils.c @@ -0,0 +1,148 @@ +#include + +#include "utils.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "thash.h" + +/** + * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. + */ +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in) { + int i; + + /* Iterate over out in decreasing order, for big-endianness. */ + for (i = (signed int)outlen - 1; i >= 0; i--) { + out[i] = in & 0xff; + in = in >> 8; + } +} + +void u32_to_bytes(unsigned char *out, uint32_t in) { + out[0] = (unsigned char)(in >> 24); + out[1] = (unsigned char)(in >> 16); + out[2] = (unsigned char)(in >> 8); + out[3] = (unsigned char)in; +} + +/** + * Converts the inlen bytes in 'in' from big-endian byte order to an integer. + */ +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { + unsigned long long retval = 0; + unsigned int i; + + for (i = 0; i < inlen; i++) { + retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); + } + return retval; +} + +/** + * Computes a root node given a leaf and an auth path. + * Expects address to be complete other than the tree_height and tree_index. + */ +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]) { + uint32_t i; + unsigned char buffer[2 * SPX_N]; + + /* If leaf_idx is odd (last bit = 1), current path element is a right child + and auth_path has to go left. Otherwise it is the other way around. */ + if (leaf_idx & 1) { + memcpy(buffer + SPX_N, leaf, SPX_N); + memcpy(buffer, auth_path, SPX_N); + } else { + memcpy(buffer, leaf, SPX_N); + memcpy(buffer + SPX_N, auth_path, SPX_N); + } + auth_path += SPX_N; + + for (i = 0; i < tree_height - 1; i++) { + leaf_idx >>= 1; + idx_offset >>= 1; + /* Set the address of the node we're creating. */ + set_tree_height(addr, i + 1); + set_tree_index(addr, leaf_idx + idx_offset); + + /* Pick the right or left neighbor, depending on parity of the node. */ + if (leaf_idx & 1) { + thash(buffer + SPX_N, buffer, 2, ctx, addr); + memcpy(buffer, auth_path, SPX_N); + } else { + thash(buffer, buffer, 2, ctx, addr); + memcpy(buffer + SPX_N, auth_path, SPX_N); + } + auth_path += SPX_N; + } + + /* The last iteration is exceptional; we do not copy an auth_path node. */ + leaf_idx >>= 1; + idx_offset >>= 1; + set_tree_height(addr, tree_height); + set_tree_index(addr, leaf_idx + idx_offset); + thash(root, buffer, 2, ctx, addr); +} + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx * /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]) { + PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); + PQCLEAN_VLA(unsigned int, heights, tree_height + 1); + unsigned int offset = 0; + uint32_t idx; + uint32_t tree_idx; + + for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { + /* Add the next leaf node to the stack. */ + gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); + offset++; + heights[offset - 1] = 0; + + /* If this is a node we need for the auth path.. */ + if ((leaf_idx ^ 0x1) == idx) { + memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); + } + + /* While the top-most nodes are of equal height.. */ + while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { + /* Compute index of the new node, in the next layer. */ + tree_idx = (idx >> (heights[offset - 1] + 1)); + + /* Set the address of the node we're creating. */ + set_tree_height(tree_addr, heights[offset - 1] + 1); + set_tree_index(tree_addr, + tree_idx + (idx_offset >> (heights[offset - 1] + 1))); + /* Hash the top-most nodes from the stack together. */ + thash(stack + (offset - 2)*SPX_N, + stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); + offset--; + /* Note that the top-most node is now one layer higher. */ + heights[offset - 1]++; + + /* If this is a node we need for the auth path.. */ + if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { + memcpy(auth_path + heights[offset - 1]*SPX_N, + stack + (offset - 1)*SPX_N, SPX_N); + } + } + } + memcpy(root, stack, SPX_N); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/utils.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/utils.h new file mode 100644 index 0000000000..64f5d5a53a --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/utils.h @@ -0,0 +1,58 @@ +#ifndef SPX_UTILS_H +#define SPX_UTILS_H + +#include + +#include "compat.h" +#include "context.h" +#include "params.h" + + +/* To support MSVC use alloca() instead of VLAs. See #20. */ + + +/** + * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. + */ +#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in); +#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) +void u32_to_bytes(unsigned char *out, uint32_t in); + +/** + * Converts the inlen bytes in 'in' from big-endian byte order to an integer. + */ +#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); + +/** + * Computes a root node given a leaf and an auth path. + * Expects address to be complete other than the tree_height and tree_index. + */ +#define compute_root SPX_NAMESPACE(compute_root) +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]); + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +#define treehash SPX_NAMESPACE(treehash) +void treehash(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx *ctx /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]); + + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/utilsx1.c b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/utilsx1.c new file mode 100644 index 0000000000..fccb69b35d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/utilsx1.c @@ -0,0 +1,100 @@ +#include + +#include "utilsx1.h" + +#include "address.h" +#include "params.h" +#include "thash.h" +#include "utils.h" + +/* + * Generate the entire Merkle tree, computing the authentication path for + * leaf_idx, and the resulting root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) + * + * This expects tree_addr to be initialized to the addr structures for the + * Merkle tree nodes + * + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + * + * This works by using the standard Merkle tree building algorithm, + */ +void treehashx1(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, + uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* Where to write the leaves */, + const spx_ctx * /* ctx */, + uint32_t idx, void *info), + uint32_t tree_addr[8], + void *info) { + /* This is where we keep the intermediate nodes */ + PQCLEAN_VLA(uint8_t, stack, tree_height * SPX_N); + + uint32_t idx; + uint32_t max_idx = (uint32_t)((1 << tree_height) - 1); + for (idx = 0;; idx++) { + unsigned char current[2 * SPX_N]; /* Current logical node is at */ + /* index[SPX_N]. We do this to minimize the number of copies */ + /* needed during a thash */ + gen_leaf( ¤t[SPX_N], ctx, idx + idx_offset, + info ); + + /* Now combine the freshly generated right node with previously */ + /* generated left ones */ + uint32_t internal_idx_offset = idx_offset; + uint32_t internal_idx = idx; + uint32_t internal_leaf = leaf_idx; + uint32_t h; /* The height we are in the Merkle tree */ + for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { + + /* Check if we hit the top of the tree */ + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[SPX_N], SPX_N ); + return; + } + + /* + * Check if the node we have is a part of the + * authentication path; if it is, write it out + */ + if ((internal_idx ^ internal_leaf) == 0x01) { + memcpy( &auth_path[ h * SPX_N ], + ¤t[SPX_N], + SPX_N ); + } + + /* + * Check if we're at a left child; if so, stop going up the stack + * Exception: if we've reached the end of the tree, keep on going + * (so we combine the last 4 nodes into the one root node in two + * more iterations) + */ + if ((internal_idx & 1) == 0 && idx < max_idx) { + break; + } + + /* Ok, we're at a right node */ + /* Now combine the left and right logical nodes together */ + + /* Set the address of the node we're creating. */ + internal_idx_offset >>= 1; + set_tree_height(tree_addr, h + 1); + set_tree_index(tree_addr, internal_idx / 2 + internal_idx_offset ); + + unsigned char *left = &stack[h * SPX_N]; + memcpy( ¤t[0], left, SPX_N ); + thash( ¤t[1 * SPX_N], + ¤t[0 * SPX_N], + 2, ctx, tree_addr); + } + + /* We've hit a left child; save the current for when we get the */ + /* corresponding right right */ + memcpy( &stack[h * SPX_N], ¤t[SPX_N], SPX_N); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/utilsx1.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/utilsx1.h new file mode 100644 index 0000000000..e911d17d53 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/utilsx1.h @@ -0,0 +1,27 @@ +#ifndef SPX_UTILSX4_H +#define SPX_UTILSX4_H + +#include + +#include "context.h" +#include "params.h" + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +#define treehashx1 SPX_NAMESPACE(treehashx1) +void treehashx1(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* Where to write the leaf */, + const spx_ctx * /* ctx */, + uint32_t addr_idx, void *info), + uint32_t tree_addrx4[8], void *info); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/wots.c b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/wots.c new file mode 100644 index 0000000000..249717aaa8 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/wots.c @@ -0,0 +1,108 @@ +#include +#include + +#include "wots.h" +#include "wotsx1.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "thash.h" +#include "utils.h" +#include "utilsx1.h" + +// TODO clarify address expectations, and make them more uniform. +// TODO i.e. do we expect types to be set already? +// TODO and do we expect modifications or copies? + +/** + * Computes the chaining function. + * out and in have to be n-byte arrays. + * + * Interprets in as start-th value of the chain. + * addr has to contain the address of the chain. + */ +static void gen_chain(unsigned char *out, const unsigned char *in, + unsigned int start, unsigned int steps, + const spx_ctx *ctx, uint32_t addr[8]) { + uint32_t i; + + /* Initialize out with the value at position 'start'. */ + memcpy(out, in, SPX_N); + + /* Iterate 'steps' calls to the hash function. */ + for (i = start; i < (start + steps) && i < SPX_WOTS_W; i++) { + set_hash_addr(addr, i); + thash(out, out, 1, ctx, addr); + } +} + +/** + * base_w algorithm as described in draft. + * Interprets an array of bytes as integers in base w. + * This only works when log_w is a divisor of 8. + */ +static void base_w(unsigned int *output, const int out_len, + const unsigned char *input) { + int in = 0; + int out = 0; + unsigned char total = 0; + int bits = 0; + int consumed; + + for (consumed = 0; consumed < out_len; consumed++) { + if (bits == 0) { + total = input[in]; + in++; + bits += 8; + } + bits -= SPX_WOTS_LOGW; + output[out] = (total >> bits) & (SPX_WOTS_W - 1); + out++; + } +} + +/* Computes the WOTS+ checksum over a message (in base_w). */ +static void wots_checksum(unsigned int *csum_base_w, + const unsigned int *msg_base_w) { + unsigned int csum = 0; + unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; + unsigned int i; + + /* Compute checksum. */ + for (i = 0; i < SPX_WOTS_LEN1; i++) { + csum += SPX_WOTS_W - 1 - msg_base_w[i]; + } + + /* Convert checksum to base_w. */ + /* Make sure expected empty zero bits are the least significant bits. */ + csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); + ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); + base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); +} + +/* Takes a message and derives the matching chain lengths. */ +void chain_lengths(unsigned int *lengths, const unsigned char *msg) { + base_w(lengths, SPX_WOTS_LEN1, msg); + wots_checksum(lengths + SPX_WOTS_LEN1, lengths); +} + +/** + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. + * + * Writes the computed public key to 'pk'. + */ +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]) { + unsigned int lengths[SPX_WOTS_LEN]; + uint32_t i; + + chain_lengths(lengths, msg); + + for (i = 0; i < SPX_WOTS_LEN; i++) { + set_chain_addr(addr, i); + gen_chain(pk + i * SPX_N, sig + i * SPX_N, + lengths[i], SPX_WOTS_W - 1 - lengths[i], ctx, addr); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/wots.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/wots.h new file mode 100644 index 0000000000..4e7692eeef --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/wots.h @@ -0,0 +1,25 @@ +#ifndef SPX_WOTS_H +#define SPX_WOTS_H + +#include + +#include "context.h" +#include "params.h" + +/** + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. + * + * Writes the computed public key to 'pk'. + */ +#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]); + +/* + * Compute the chain lengths needed for a given message hash + */ +#define chain_lengths SPX_NAMESPACE(chain_lengths) +void chain_lengths(unsigned int *lengths, const unsigned char *msg); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/wotsx1.c b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/wotsx1.c new file mode 100644 index 0000000000..3adec78dfb --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/wotsx1.c @@ -0,0 +1,76 @@ +#include +#include + +#include "wots.h" +#include "wotsx1.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "thash.h" +#include "utils.h" + +/* + * This generates a WOTS public key + * It also generates the WOTS signature if leaf_info indicates + * that we're signing with this WOTS key + */ +void wots_gen_leafx1(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info) { + struct leaf_info_x1 *info = v_info; + uint32_t *leaf_addr = info->leaf_addr; + uint32_t *pk_addr = info->pk_addr; + unsigned int i, k; + unsigned char pk_buffer[ SPX_WOTS_BYTES ]; + unsigned char *buffer; + uint32_t wots_k_mask; + + if (leaf_idx == info->wots_sign_leaf) { + /* We're traversing the leaf that's signing; generate the WOTS */ + /* signature */ + wots_k_mask = 0; + } else { + /* Nope, we're just generating pk's; turn off the signature logic */ + wots_k_mask = (uint32_t)~0; + } + + set_keypair_addr( leaf_addr, leaf_idx ); + set_keypair_addr( pk_addr, leaf_idx ); + + for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { + uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k to */ + /* the step if we're generating a signature, ~0 if we're not */ + + /* Start with the secret seed */ + set_chain_addr(leaf_addr, i); + set_hash_addr(leaf_addr, 0); + set_type(leaf_addr, SPX_ADDR_TYPE_WOTSPRF); + + prf_addr(buffer, ctx, leaf_addr); + + set_type(leaf_addr, SPX_ADDR_TYPE_WOTS); + + /* Iterate down the WOTS chain */ + for (k = 0;; k++) { + /* Check if this is the value that needs to be saved as a */ + /* part of the WOTS signature */ + if (k == wots_k) { + memcpy( info->wots_sig + i * SPX_N, buffer, SPX_N ); + } + + /* Check if we hit the top of the chain */ + if (k == SPX_WOTS_W - 1) { + break; + } + + /* Iterate one step on the chain */ + set_hash_addr(leaf_addr, k); + + thash(buffer, buffer, 1, ctx, leaf_addr); + } + } + + /* Do the final thash to generate the public keys */ + thash(dest, pk_buffer, SPX_WOTS_LEN, ctx, pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/wotsx1.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/wotsx1.h new file mode 100644 index 0000000000..e617929f96 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/wotsx1.h @@ -0,0 +1,39 @@ +#ifndef WOTSX1_H_ +#define WOTSX1_H_ + +#include + +#include "context.h" +#include "params.h" + +/* + * This is here to provide an interface to the internal wots_gen_leafx1 + * routine. While this routine is not referenced in the package outside of + * wots.c, it is called from the stand-alone benchmark code to characterize + * the performance + */ +struct leaf_info_x1 { + unsigned char *wots_sig; + uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ + uint32_t *wots_steps; + uint32_t leaf_addr[8]; + uint32_t pk_addr[8]; +}; + +/* Macro to set the leaf_info to something 'benign', that is, it would */ +/* run with the same time as it does during the real signing process */ +/* Used only by the benchmark code */ +#define INITIALIZE_LEAF_INFO_X1(info, addr, step_buffer) { \ + (info).wots_sig = 0; \ + (info).wots_sign_leaf = ~0; \ + (info).wots_steps = step_buffer; \ + memcpy( &(info).leaf_addr[0], (addr), 32 ); \ + memcpy( &(info).pk_addr[0], (addr), 32 ); \ + } + +#define wots_gen_leafx1 SPX_NAMESPACE(wots_gen_leafx1) +void wots_gen_leafx1(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info); + +#endif /* WOTSX1_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/LICENSE b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/LICENSE new file mode 100644 index 0000000000..670154e353 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/LICENSE @@ -0,0 +1,116 @@ +CC0 1.0 Universal + +Statement of Purpose + +The laws of most jurisdictions throughout the world automatically confer +exclusive Copyright and Related Rights (defined below) upon the creator and +subsequent owner(s) (each and all, an "owner") of an original work of +authorship and/or a database (each, a "Work"). + +Certain owners wish to permanently relinquish those rights to a Work for the +purpose of contributing to a commons of creative, cultural and scientific +works ("Commons") that the public can reliably and without fear of later +claims of infringement build upon, modify, incorporate in other works, reuse +and redistribute as freely as possible in any form whatsoever and for any +purposes, including without limitation commercial purposes. These owners may +contribute to the Commons to promote the ideal of a free culture and the +further production of creative, cultural and scientific works, or to gain +reputation or greater distribution for their Work in part through the use and +efforts of others. + +For these and/or other purposes and motivations, and without any expectation +of additional consideration or compensation, the person associating CC0 with a +Work (the "Affirmer"), to the extent that he or she is an owner of Copyright +and Related Rights in the Work, voluntarily elects to apply CC0 to the Work +and publicly distribute the Work under its terms, with knowledge of his or her +Copyright and Related Rights in the Work and the meaning and intended legal +effect of CC0 on those rights. + +1. Copyright and Related Rights. A Work made available under CC0 may be +protected by copyright and related or neighboring rights ("Copyright and +Related Rights"). Copyright and Related Rights include, but are not limited +to, the following: + + i. the right to reproduce, adapt, distribute, perform, display, communicate, + and translate a Work; + + ii. moral rights retained by the original author(s) and/or performer(s); + + iii. publicity and privacy rights pertaining to a person's image or likeness + depicted in a Work; + + iv. rights protecting against unfair competition in regards to a Work, + subject to the limitations in paragraph 4(a), below; + + v. rights protecting the extraction, dissemination, use and reuse of data in + a Work; + + vi. database rights (such as those arising under Directive 96/9/EC of the + European Parliament and of the Council of 11 March 1996 on the legal + protection of databases, and under any national implementation thereof, + including any amended or successor version of such directive); and + + vii. other similar, equivalent or corresponding rights throughout the world + based on applicable law or treaty, and any national implementations thereof. + +2. Waiver. To the greatest extent permitted by, but not in contravention of, +applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and +unconditionally waives, abandons, and surrenders all of Affirmer's Copyright +and Related Rights and associated claims and causes of action, whether now +known or unknown (including existing as well as future claims and causes of +action), in the Work (i) in all territories worldwide, (ii) for the maximum +duration provided by applicable law or treaty (including future time +extensions), (iii) in any current or future medium and for any number of +copies, and (iv) for any purpose whatsoever, including without limitation +commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes +the Waiver for the benefit of each member of the public at large and to the +detriment of Affirmer's heirs and successors, fully intending that such Waiver +shall not be subject to revocation, rescission, cancellation, termination, or +any other legal or equitable action to disrupt the quiet enjoyment of the Work +by the public as contemplated by Affirmer's express Statement of Purpose. + +3. Public License Fallback. Should any part of the Waiver for any reason be +judged legally invalid or ineffective under applicable law, then the Waiver +shall be preserved to the maximum extent permitted taking into account +Affirmer's express Statement of Purpose. In addition, to the extent the Waiver +is so judged Affirmer hereby grants to each affected person a royalty-free, +non transferable, non sublicensable, non exclusive, irrevocable and +unconditional license to exercise Affirmer's Copyright and Related Rights in +the Work (i) in all territories worldwide, (ii) for the maximum duration +provided by applicable law or treaty (including future time extensions), (iii) +in any current or future medium and for any number of copies, and (iv) for any +purpose whatsoever, including without limitation commercial, advertising or +promotional purposes (the "License"). The License shall be deemed effective as +of the date CC0 was applied by Affirmer to the Work. Should any part of the +License for any reason be judged legally invalid or ineffective under +applicable law, such partial invalidity or ineffectiveness shall not +invalidate the remainder of the License, and in such case Affirmer hereby +affirms that he or she will not (i) exercise any of his or her remaining +Copyright and Related Rights in the Work or (ii) assert any associated claims +and causes of action with respect to the Work, in either case contrary to +Affirmer's express Statement of Purpose. + +4. Limitations and Disclaimers. + + a. No trademark or patent rights held by Affirmer are waived, abandoned, + surrendered, licensed or otherwise affected by this document. + + b. Affirmer offers the Work as-is and makes no representations or warranties + of any kind concerning the Work, express, implied, statutory or otherwise, + including without limitation warranties of title, merchantability, fitness + for a particular purpose, non infringement, or the absence of latent or + other defects, accuracy, or the present or absence of errors, whether or not + discoverable, all to the greatest extent permissible under applicable law. + + c. Affirmer disclaims responsibility for clearing rights of other persons + that may apply to the Work or any use thereof, including without limitation + any person's Copyright and Related Rights in the Work. Further, Affirmer + disclaims responsibility for obtaining any necessary consents, permissions + or other rights required for any use of the Work. + + d. Affirmer understands and acknowledges that Creative Commons is not a + party to this document and has no duty or obligation with respect to this + CC0 or use of the Work. + +For more information, please see + diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/address.c b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/address.c new file mode 100644 index 0000000000..b956e9cb29 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/address.c @@ -0,0 +1,91 @@ +#include +#include + +#include "address.h" +#include "params.h" +#include "utils.h" + +/* + * Specify which level of Merkle tree (the "layer") we're working on + */ +void set_layer_addr(uint32_t addr[8], uint32_t layer) { + ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; +} + +/* + * Specify which Merkle tree within the level (the "tree address") we're working on + */ +void set_tree_addr(uint32_t addr[8], uint64_t tree) { + ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); +} + +/* + * Specify the reason we'll use this address structure for, that is, what + * hash will we compute with it. This is used so that unrelated types of + * hashes don't accidentally get the same address structure. The type will be + * one of the SPX_ADDR_TYPE constants + */ +void set_type(uint32_t addr[8], uint32_t type) { + ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; +} + +/* + * Copy the layer and tree fields of the address structure. This is used + * when we're doing multiple types of hashes within the same Merkle tree + */ +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); +} + +/* These functions are used for OTS addresses. */ + +/* + * Specify which Merkle leaf we're working on; that is, which OTS keypair + * we're talking about. + */ +void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { + ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; +} + +/* + * Copy the layer, tree and keypair fields of the address structure. This is + * used when we're doing multiple things within the same OTS keypair + */ +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); + ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; +} + +/* + * Specify which Merkle chain within the OTS we're working with + * (the chain address) + */ +void set_chain_addr(uint32_t addr[8], uint32_t chain) { + ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; +} + +/* + * Specify where in the Merkle chain we are +* (the hash address) + */ +void set_hash_addr(uint32_t addr[8], uint32_t hash) { + ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; +} + +/* These functions are used for all hash tree addresses (including FORS). */ + +/* + * Specify the height of the node in the Merkle/FORS tree we are in + * (the tree height) + */ +void set_tree_height(uint32_t addr[8], uint32_t tree_height) { + ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; +} + +/* + * Specify the distance from the left edge of the node in the Merkle/FORS tree + * (the tree index) + */ +void set_tree_index(uint32_t addr[8], uint32_t tree_index) { + u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/address.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/address.h new file mode 100644 index 0000000000..24a84eb40c --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/address.h @@ -0,0 +1,52 @@ +#ifndef SPX_ADDRESS_H +#define SPX_ADDRESS_H + +#include + +#include "params.h" + +/* The hash types that are passed to set_type */ +#define SPX_ADDR_TYPE_WOTS 0 +#define SPX_ADDR_TYPE_WOTSPK 1 +#define SPX_ADDR_TYPE_HASHTREE 2 +#define SPX_ADDR_TYPE_FORSTREE 3 +#define SPX_ADDR_TYPE_FORSPK 4 +#define SPX_ADDR_TYPE_WOTSPRF 5 +#define SPX_ADDR_TYPE_FORSPRF 6 + +#define set_layer_addr SPX_NAMESPACE(set_layer_addr) +void set_layer_addr(uint32_t addr[8], uint32_t layer); + +#define set_tree_addr SPX_NAMESPACE(set_tree_addr) +void set_tree_addr(uint32_t addr[8], uint64_t tree); + +#define set_type SPX_NAMESPACE(set_type) +void set_type(uint32_t addr[8], uint32_t type); + +/* Copies the layer and tree part of one address into the other */ +#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); + +/* These functions are used for WOTS and FORS addresses. */ + +#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) +void set_keypair_addr(uint32_t addr[8], uint32_t keypair); + +#define set_chain_addr SPX_NAMESPACE(set_chain_addr) +void set_chain_addr(uint32_t addr[8], uint32_t chain); + +#define set_hash_addr SPX_NAMESPACE(set_hash_addr) +void set_hash_addr(uint32_t addr[8], uint32_t hash); + +#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); + +/* These functions are used for all hash tree addresses (including FORS). */ + +#define set_tree_height SPX_NAMESPACE(set_tree_height) +void set_tree_height(uint32_t addr[8], uint32_t tree_height); + +#define set_tree_index SPX_NAMESPACE(set_tree_index) +void set_tree_index(uint32_t addr[8], uint32_t tree_index); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/api.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/api.h new file mode 100644 index 0000000000..00b9ae1655 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/api.h @@ -0,0 +1,77 @@ +#ifndef PQCLEAN_SPHINCSSHAKE256SSIMPLE_AARCH64_API_H +#define PQCLEAN_SPHINCSSHAKE256SSIMPLE_AARCH64_API_H + +#include +#include + +#define PQCLEAN_SPHINCSSHAKE256SSIMPLE_AARCH64_CRYPTO_ALGNAME "SPHINCS+-shake-256s-simple" + +#define PQCLEAN_SPHINCSSHAKE256SSIMPLE_AARCH64_CRYPTO_SECRETKEYBYTES 128 +#define PQCLEAN_SPHINCSSHAKE256SSIMPLE_AARCH64_CRYPTO_PUBLICKEYBYTES 64 +#define PQCLEAN_SPHINCSSHAKE256SSIMPLE_AARCH64_CRYPTO_BYTES 29792 + +#define PQCLEAN_SPHINCSSHAKE256SSIMPLE_AARCH64_CRYPTO_SEEDBYTES 96 + +/* + * Returns the length of a secret key, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE256SSIMPLE_AARCH64_crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE256SSIMPLE_AARCH64_crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE256SSIMPLE_AARCH64_crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE256SSIMPLE_AARCH64_crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +int PQCLEAN_SPHINCSSHAKE256SSIMPLE_AARCH64_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +int PQCLEAN_SPHINCSSHAKE256SSIMPLE_AARCH64_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +int PQCLEAN_SPHINCSSHAKE256SSIMPLE_AARCH64_crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +int PQCLEAN_SPHINCSSHAKE256SSIMPLE_AARCH64_crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, + const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +int PQCLEAN_SPHINCSSHAKE256SSIMPLE_AARCH64_crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +int PQCLEAN_SPHINCSSHAKE256SSIMPLE_AARCH64_crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/context.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/context.h new file mode 100644 index 0000000000..6e0a33f3b7 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/context.h @@ -0,0 +1,19 @@ +#ifndef SPX_CONTEXT_H +#define SPX_CONTEXT_H + +#include + +#include "params.h" + +typedef struct { + uint8_t pub_seed[SPX_N]; + uint8_t sk_seed[SPX_N]; +} spx_ctx; + +#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) +void initialize_hash_function(spx_ctx *ctx); + +#define free_hash_function SPX_NAMESPACE(free_hash_function) +void free_hash_function(spx_ctx *ctx); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/context_shake.c b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/context_shake.c new file mode 100644 index 0000000000..9614a103d3 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/context_shake.c @@ -0,0 +1,12 @@ +#include "context.h" + +/* For SHAKE256, there is no immediate reason to initialize at the start, + so this function is an empty operation. */ +void initialize_hash_function(spx_ctx *ctx) { + (void)ctx; /* Suppress an 'unused parameter' warning. */ +} + +// in case the hash function api is heap-based. +void free_hash_function(spx_ctx *ctx) { + (void)ctx; +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/f1600x2.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/f1600x2.h new file mode 100644 index 0000000000..70d1af9f14 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/f1600x2.h @@ -0,0 +1,11 @@ +#ifndef SPX_F1600X2_H +#define SPX_F1600X2_H + +#include + +extern uint64_t f1600_RC[24]; +extern void _f1600x2(uint64_t *a, uint64_t *rc); + +#define f1600x2(s) do {_f1600x2((s), f1600_RC);} while(0) + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/f1600x2.s b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/f1600x2.s new file mode 100644 index 0000000000..640ed791ed --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/f1600x2.s @@ -0,0 +1,143 @@ +# From https://github.com/bwesterb/armed-keccak + +.macro round + # Execute theta, but without xoring into the state yet. + # Compute parities p[i] = a[i] ^ a[5+i] ^ ... ^ a[20+i]. + eor3.16b v25, v0, v5, v10 + eor3.16b v26, v1, v6, v11 + eor3.16b v27, v2, v7, v12 + eor3.16b v28, v3, v8, v13 + eor3.16b v29, v4, v9, v14 + + eor3.16b v25, v25, v15, v20 + eor3.16b v26, v26, v16, v21 + eor3.16b v27, v27, v17, v22 + eor3.16b v28, v28, v18, v23 + eor3.16b v29, v29, v19, v24 + + # d[0] = rotl(p[1], 1) ^ p[4] + rax1.2d v30, v29, v26 + # d[3] = rotl(p[4], 1) ^ p[2] + rax1.2d v29, v27, v29 + # d[1] = rotl(p[2], 1) ^ p[0] + rax1.2d v27, v25, v27 + # d[4] = rotl(p[0], 1) ^ p[3] + rax1.2d v25, v28, v25 + # d[2] = rotl(p[3], 1) ^ p[1] + rax1.2d v28, v26, v28 + + # Xor parities from step theta into the state at the same time + # as executing rho and pi. + eor.16b v0, v0, v30 + mov.16b v31, v1 + xar.2d v1, v6, v27, 20 + xar.2d v6, v9, v25, 44 + xar.2d v9, v22, v28, 3 + xar.2d v22, v14, v25, 25 + xar.2d v14, v20, v30, 46 + xar.2d v20, v2, v28, 2 + xar.2d v2, v12, v28, 21 + xar.2d v12, v13, v29, 39 + xar.2d v13, v19, v25, 56 + xar.2d v19, v23, v29, 8 + xar.2d v23, v15, v30, 23 + xar.2d v15, v4, v25, 37 + xar.2d v4, v24, v25, 50 + xar.2d v24, v21, v27, 62 + xar.2d v21, v8, v29, 9 + xar.2d v8, v16, v27, 19 + xar.2d v16, v5, v30, 28 + xar.2d v5, v3, v29, 36 + xar.2d v3, v18, v29, 43 + xar.2d v18, v17, v28, 49 + xar.2d v17, v11, v27, 54 + xar.2d v11, v7, v28, 58 + xar.2d v7, v10, v30, 61 + xar.2d v10, v31, v27, 63 + + # Chi + bcax.16b v25, v0, v2, v1 + bcax.16b v26, v1, v3, v2 + bcax.16b v2, v2, v4, v3 + bcax.16b v3, v3, v0, v4 + bcax.16b v4, v4, v1, v0 + mov.16b v0, v25 + mov.16b v1, v26 + + bcax.16b v25, v5, v7, v6 + bcax.16b v26, v6, v8, v7 + bcax.16b v7, v7, v9, v8 + bcax.16b v8, v8, v5, v9 + bcax.16b v9, v9, v6, v5 + mov.16b v5, v25 + mov.16b v6, v26 + + bcax.16b v25, v10, v12, v11 + bcax.16b v26, v11, v13, v12 + bcax.16b v12, v12, v14, v13 + bcax.16b v13, v13, v10, v14 + bcax.16b v14, v14, v11, v10 + mov.16b v10, v25 + mov.16b v11, v26 + + bcax.16b v25, v15, v17, v16 + bcax.16b v26, v16, v18, v17 + bcax.16b v17, v17, v19, v18 + bcax.16b v18, v18, v15, v19 + bcax.16b v19, v19, v16, v15 + mov.16b v15, v25 + mov.16b v16, v26 + + bcax.16b v25, v20, v22, v21 + bcax.16b v26, v21, v23, v22 + bcax.16b v22, v22, v24, v23 + bcax.16b v23, v23, v20, v24 + bcax.16b v24, v24, v21, v20 + mov.16b v20, v25 + mov.16b v21, v26 + + # iota + ld1r {v25.2d}, [x1], #8 + eor.16b v0, v0, v25 +.endm + +.align 4 +.global __f1600x2 +__f1600x2: + stp d8, d9, [sp,#-16]! + stp d10, d11, [sp,#-16]! + stp d12, d13, [sp,#-16]! + stp d14, d15, [sp,#-16]! + + mov x2, x0 + mov x3, #24 + + ld1.2d {v0, v1, v2, v3}, [x0], #64 + ld1.2d {v4, v5, v6, v7}, [x0], #64 + ld1.2d {v8, v9, v10, v11}, [x0], #64 + ld1.2d {v12, v13, v14, v15}, [x0], #64 + ld1.2d {v16, v17, v18, v19}, [x0], #64 + ld1.2d {v20, v21, v22, v23}, [x0], #64 + ld1.2d {v24}, [x0] + +loop: + round + + subs x3, x3, #1 + cbnz x3, loop + + mov x0, x2 + st1.2d {v0, v1, v2, v3}, [x0], #64 + st1.2d {v4, v5, v6, v7}, [x0], #64 + st1.2d {v8, v9, v10, v11}, [x0], #64 + st1.2d {v12, v13, v14, v15}, [x0], #64 + st1.2d {v16, v17, v18, v19}, [x0], #64 + st1.2d {v20, v21, v22, v23}, [x0], #64 + st1.2d {v24}, [x0] + + ldp d14, d15, [sp], #16 + ldp d12, d13, [sp], #16 + ldp d10, d11, [sp], #16 + ldp d8, d9, [sp], #16 + + ret lr diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/f1600x2_const.c b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/f1600x2_const.c new file mode 100644 index 0000000000..e49c0ba149 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/f1600x2_const.c @@ -0,0 +1,30 @@ +#include "f1600x2.h" + +uint64_t f1600_RC[24] = { + 0x0000000000000001, + 0x0000000000008082, + 0x800000000000808A, + 0x8000000080008000, + 0x000000000000808B, + 0x0000000080000001, + 0x8000000080008081, + 0x8000000000008009, + 0x000000000000008A, + 0x0000000000000088, + 0x0000000080008009, + 0x000000008000000A, + 0x000000008000808B, + 0x800000000000008B, + 0x8000000000008089, + 0x8000000000008003, + 0x8000000000008002, + 0x8000000000000080, + 0x000000000000800A, + 0x800000008000000A, + 0x8000000080008081, + 0x8000000000008080, + 0x0000000080000001, + 0x8000000080008008, +}; + + diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/fips202x2.c b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/fips202x2.c new file mode 100644 index 0000000000..4718c343bc --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/fips202x2.c @@ -0,0 +1,148 @@ +#include +#include + +#include "fips202x2.h" +#include "f1600x2.h" +#include "fips202.h" + +uint64_t load64(const unsigned char *x) { + unsigned long long r = 0, i; + + for (i = 0; i < 8; ++i) { + r |= (unsigned long long)x[i] << 8 * i; + } + return r; +} + +void store64(uint8_t *x, uint64_t u) { + unsigned int i; + + for (i = 0; i < 8; ++i) { + x[i] = (uint8_t)u; + u >>= 8; + } +} + +static void keccak_absorb2x(uint64_t *s, + unsigned int r, + const unsigned char *m0, + const unsigned char *m1, + unsigned long long int mlen, + unsigned char p) { + unsigned long long i; + unsigned char t0[200]; + unsigned char t1[200]; + + while (mlen >= r) { + for (i = 0; i < r / 8; ++i) { + s[2 * i + 0] ^= load64(m0 + 8 * i); + s[2 * i + 1] ^= load64(m1 + 8 * i); + } + + f1600x2(s); + mlen -= r; + m0 += r; + m1 += r; + } + + for (i = 0; i < r; ++i) { + t0[i] = 0; + t1[i] = 0; + } + for (i = 0; i < mlen; ++i) { + t0[i] = m0[i]; + t1[i] = m1[i]; + } + + t0[i] = p; + t1[i] = p; + + t0[r - 1] |= 128; + t1[r - 1] |= 128; + + for (i = 0; i < r / 8; ++i) { + s[2 * i + 0] ^= load64(t0 + 8 * i); + s[2 * i + 1] ^= load64(t1 + 8 * i); + } +} + + +static void keccak_squeezeblocks2x(unsigned char *h0, + unsigned char *h1, + unsigned long long int nblocks, + uint64_t *s, + unsigned int r) { + unsigned int i; + + while (nblocks > 0) { + f1600x2(s); + for (i = 0; i < (r >> 3); i++) { + store64(h0 + 8 * i, s[2 * i + 0]); + store64(h1 + 8 * i, s[2 * i + 1]); + } + h0 += r; + h1 += r; + nblocks--; + } +} + + + +void shake128x2(unsigned char *out0, + unsigned char *out1, + unsigned long long outlen, + unsigned char *in0, + unsigned char *in1, + unsigned long long inlen) { + uint64_t s[50] = {0}; + unsigned char t0[SHAKE128_RATE]; + unsigned char t1[SHAKE128_RATE]; + unsigned int i; + + /* absorb 4 message of identical length in parallel */ + keccak_absorb2x(s, SHAKE128_RATE, in0, in1, inlen, 0x1F); + + /* Squeeze output */ + keccak_squeezeblocks2x(out0, out1, outlen / SHAKE128_RATE, s, SHAKE128_RATE); + + out0 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; + out1 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; + + if (outlen % SHAKE128_RATE) { + keccak_squeezeblocks2x(t0, t1, 1, s, SHAKE128_RATE); + for (i = 0; i < outlen % SHAKE128_RATE; i++) { + out0[i] = t0[i]; + out1[i] = t1[i]; + } + } +} + + +void shake256x2(unsigned char *out0, + unsigned char *out1, + unsigned long long outlen, + unsigned char *in0, + unsigned char *in1, + unsigned long long inlen) { + uint64_t s[50] = {0}; + unsigned char t0[SHAKE256_RATE]; + unsigned char t1[SHAKE256_RATE]; + unsigned int i; + + /* absorb 2 message of identical length in parallel */ + keccak_absorb2x(s, SHAKE256_RATE, in0, in1, inlen, 0x1F); + + /* Squeeze output */ + keccak_squeezeblocks2x(out0, out1, outlen / SHAKE256_RATE, s, SHAKE256_RATE); + + out0 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; + out1 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; + + if (outlen % SHAKE256_RATE) { + keccak_squeezeblocks2x(t0, t1, 1, s, SHAKE256_RATE); + for (i = 0; i < outlen % SHAKE256_RATE; i++) { + out0[i] = t0[i]; + out1[i] = t1[i]; + } + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/fips202x2.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/fips202x2.h new file mode 100644 index 0000000000..7ba58b35d8 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/fips202x2.h @@ -0,0 +1,24 @@ +#ifndef SPX_FIPS202X2_H +#define SPX_FIPS202X2_H + +#include + +uint64_t load64(const unsigned char *x); +void store64(uint8_t *x, uint64_t u); + + +void shake128x2(unsigned char *out0, + unsigned char *out1, + unsigned long long outlen, + unsigned char *in0, + unsigned char *in1, + unsigned long long inlen); + +void shake256x2(unsigned char *out0, + unsigned char *out1, + unsigned long long outlen, + unsigned char *in0, + unsigned char *in1, + unsigned long long inlen); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/fors.c b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/fors.c new file mode 100644 index 0000000000..39193d04e2 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/fors.c @@ -0,0 +1,191 @@ +#include +#include +#include + +#include "fors.h" + +#include "address.h" +#include "hash.h" +#include "hashx2.h" +#include "thash.h" +#include "thashx2.h" +#include "utils.h" +#include "utilsx2.h" + +static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + prf_addr(sk, ctx, fors_leaf_addr); +} + +static void fors_gen_skx2(unsigned char *sk0, + unsigned char *sk1, + const spx_ctx *ctx, + uint32_t fors_leaf_addrx2[2 * 8]) { + prf_addrx2(sk0, sk1, + ctx, fors_leaf_addrx2); +} + +static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, + const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + thash(leaf, sk, 1, ctx, fors_leaf_addr); +} + +static void fors_sk_to_leafx2(unsigned char *leaf0, + unsigned char *leaf1, + const unsigned char *sk0, + const unsigned char *sk1, + const spx_ctx *ctx, + uint32_t fors_leaf_addrx2[2 * 8]) { + thashx2(leaf0, leaf1, + sk0, sk1, + 1, ctx, fors_leaf_addrx2); +} + +struct fors_gen_leaf_info { + uint32_t leaf_addrx[2 * 8]; +}; + +static void fors_gen_leafx2(unsigned char *leaf, + const spx_ctx *ctx, + uint32_t addr_idx, void *info) { + struct fors_gen_leaf_info *fors_info = info; + uint32_t *fors_leaf_addrx2 = fors_info->leaf_addrx; + unsigned int j; + + /* Only set the parts that the caller doesn't set */ + for (j = 0; j < 2; j++) { + set_tree_index(fors_leaf_addrx2 + j * 8, addr_idx + j); + set_type(fors_leaf_addrx2 + j * 8, SPX_ADDR_TYPE_FORSPRF); + } + + fors_gen_skx2(leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + ctx, fors_leaf_addrx2); + + for (j = 0; j < 2; j++) { + set_type(fors_leaf_addrx2 + j * 8, SPX_ADDR_TYPE_FORSTREE); + } + + fors_sk_to_leafx2(leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + ctx, fors_leaf_addrx2); +} + +/** + * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + * Assumes indices has space for SPX_FORS_TREES integers. + */ +static void message_to_indices(uint32_t *indices, const unsigned char *m) { + unsigned int i, j; + unsigned int offset = 0; + + for (i = 0; i < SPX_FORS_TREES; i++) { + indices[i] = 0; + for (j = 0; j < SPX_FORS_HEIGHT; j++) { + indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); + offset++; + } + } +} + +/** + * Signs a message m, deriving the secret key from sk_seed and the FTS address. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + uint32_t fors_tree_addr[2 * 8] = {0}; + struct fors_gen_leaf_info fors_info = {0}; + uint32_t *fors_leaf_addr = fors_info.leaf_addrx; + uint32_t fors_pk_addr[8] = {0}; + uint32_t idx_offset; + unsigned int i; + + for (i = 0; i < 2; i++) { + copy_keypair_addr(fors_tree_addr + 8 * i, fors_addr); + set_type(fors_tree_addr + 8 * i, SPX_ADDR_TYPE_FORSTREE); + copy_keypair_addr(fors_leaf_addr + 8 * i, fors_addr); + } + copy_keypair_addr(fors_pk_addr, fors_addr); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); + + message_to_indices(indices, m); + + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); + + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + + /* Include the secret key part that produces the selected leaf node. */ + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); + fors_gen_sk(sig, ctx, fors_tree_addr); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + sig += SPX_N; + + /* Compute the authentication path for this leaf node. */ + treehashx2(roots + i * SPX_N, sig, ctx, + indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx2, + fors_tree_addr, &fors_info); + + sig += SPX_N * SPX_FORS_HEIGHT; + } + + /* Hash horizontally across all tree roots to derive the public key. */ + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); +} + +/** + * Derives the FORS public key from a signature. + * This can be used for verification by comparing to a known public key, or to + * subsequently verify a signature on the derived public key. The latter is the + * typical use-case when used as an FTS below an OTS in a hypertree. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + unsigned char leaf[SPX_N]; + uint32_t fors_tree_addr[8] = {0}; + uint32_t fors_pk_addr[8] = {0}; + uint32_t idx_offset; + unsigned int i; + + copy_keypair_addr(fors_tree_addr, fors_addr); + copy_keypair_addr(fors_pk_addr, fors_addr); + + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); + + message_to_indices(indices, m); + + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); + + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + + /* Derive the leaf from the included secret key part. */ + fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); + sig += SPX_N; + + /* Derive the corresponding root node of this tree. */ + compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, + sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); + sig += SPX_N * SPX_FORS_HEIGHT; + } + + /* Hash horizontally across all tree roots to derive the public key. */ + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/fors.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/fors.h new file mode 100644 index 0000000000..509140a178 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/fors.h @@ -0,0 +1,32 @@ +#ifndef SPX_FORS_H +#define SPX_FORS_H + +#include + +#include "context.h" +#include "params.h" + +/** + * Signs a message m, deriving the secret key from sk_seed and the FTS address. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +#define fors_sign SPX_NAMESPACE(fors_sign) +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); + +/** + * Derives the FORS public key from a signature. + * This can be used for verification by comparing to a known public key, or to + * subsequently verify a signature on the derived public key. The latter is the + * typical use-case when used as an FTS below an OTS in a hypertree. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/hash.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/hash.h new file mode 100644 index 0000000000..f7c87d4c3c --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/hash.h @@ -0,0 +1,28 @@ +#ifndef SPX_HASH_H +#define SPX_HASH_H + +#include +#include + +#include "context.h" +#include "params.h" + +#define prf_addr SPX_NAMESPACE(prf_addr) +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]); + +#define gen_message_random SPX_NAMESPACE(gen_message_random) +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); + +#define hash_message SPX_NAMESPACE(hash_message) +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); + + + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/hash_shake.c b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/hash_shake.c new file mode 100644 index 0000000000..ff5e7ec918 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/hash_shake.c @@ -0,0 +1,83 @@ +#include +#include + +#include "hash.h" + +#include "address.h" +#include "fips202.h" +#include "params.h" +#include "utils.h" + +/* + * Computes PRF(pk_seed, sk_seed, addr) + */ +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]) { + unsigned char buf[2 * SPX_N + SPX_ADDR_BYTES]; + + memcpy(buf, ctx->pub_seed, SPX_N); + memcpy(buf + SPX_N, addr, SPX_ADDR_BYTES); + memcpy(buf + SPX_N + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); + + shake256(out, SPX_N, buf, 2 * SPX_N + SPX_ADDR_BYTES); +} + +/** + * Computes the message-dependent randomness R, using a secret seed and an + * optional randomization value as well as the message. + */ +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { + (void)ctx; + shake256incctx s_inc; + + shake256_inc_init(&s_inc); + shake256_inc_absorb(&s_inc, sk_prf, SPX_N); + shake256_inc_absorb(&s_inc, optrand, SPX_N); + shake256_inc_absorb(&s_inc, m, mlen); + shake256_inc_finalize(&s_inc); + shake256_inc_squeeze(R, SPX_N, &s_inc); + shake256_inc_ctx_release(&s_inc); +} + +/** + * Computes the message hash using R, the public key, and the message. + * Outputs the message digest and the index of the leaf. The index is split in + * the tree index and the leaf index, for convenient copying to an address. + */ +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { + (void)ctx; +#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) +#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) +#define SPX_LEAF_BITS SPX_TREE_HEIGHT +#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) +#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) + + unsigned char buf[SPX_DGST_BYTES]; + unsigned char *bufp = buf; + shake256incctx s_inc; + + shake256_inc_init(&s_inc); + shake256_inc_absorb(&s_inc, R, SPX_N); + shake256_inc_absorb(&s_inc, pk, SPX_PK_BYTES); + shake256_inc_absorb(&s_inc, m, mlen); + shake256_inc_finalize(&s_inc); + shake256_inc_squeeze(buf, SPX_DGST_BYTES, &s_inc); + shake256_inc_ctx_release(&s_inc); + + memcpy(digest, bufp, SPX_FORS_MSG_BYTES); + bufp += SPX_FORS_MSG_BYTES; + + + *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); + *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); + bufp += SPX_TREE_BYTES; + + *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); + *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/hash_shakex2.c b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/hash_shakex2.c new file mode 100644 index 0000000000..99571916a2 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/hash_shakex2.c @@ -0,0 +1,52 @@ +#include +#include + +#include "hashx2.h" + +#include "address.h" +#include "f1600x2.h" +#include "fips202x2.h" +#include "params.h" + +/* + * 2-way parallel version of prf_addr; takes 2x as much input and output + */ +void prf_addrx2(unsigned char *out0, + unsigned char *out1, + const spx_ctx *ctx, + const uint32_t addrx2[2 * 8]) { + /* As we write and read only a few quadwords, it is more efficient to + * build and extract from the fourway SHAKE256 state by hand. */ + uint64_t state[50] = {0}; + + for (int i = 0; i < SPX_N / 8; i++) { + uint64_t x = load64(ctx->pub_seed + 8 * i); + state[2 * i] = x; + state[2 * i + 1] = x; + } + for (int i = 0; i < 4; i++) { + state[2 * (SPX_N / 8 + i)] = (((uint64_t)addrx2[1 + 2 * i]) << 32) + | (uint64_t)addrx2[2 * i]; + state[2 * (SPX_N / 8 + i) + 1] = (((uint64_t)addrx2[8 + 1 + 2 * i]) << 32) + | (uint64_t)addrx2[8 + 2 * i]; + } + for (int i = 0; i < SPX_N / 8; i++) { + uint64_t x = load64(ctx->sk_seed + 8 * i); + state[2 * (SPX_N / 8 + i + 4)] = x; + state[2 * (SPX_N / 8 + i + 4) + 1] = x; + } + + /* SHAKE domain separator and padding. */ + state[2 * (SPX_N / 4 + 4)] = 0x1f; + state[2 * (SPX_N / 4 + 4) + 1] = 0x1f; + + state[2 * 16] = 0x80ULL << 56; + state[2 * 16 + 1] = 0x80ULL << 56; + + f1600x2(state); + + for (int i = 0; i < SPX_N / 8; i++) { + store64(out0 + 8 * i, state[2 * i]); + store64(out1 + 8 * i, state[2 * i + 1]); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/hashx2.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/hashx2.h new file mode 100644 index 0000000000..99b8873a9b --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/hashx2.h @@ -0,0 +1,14 @@ +#ifndef SPX_HASHX2_H +#define SPX_HASHX2_H + +#include "context.h" +#include "params.h" +#include + +#define prf_addrx2 SPX_NAMESPACE(prf_addrx2) +void prf_addrx2(unsigned char *out0, + unsigned char *out1, + const spx_ctx *ctx, + const uint32_t addrx2[2 * 8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/merkle.c b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/merkle.c new file mode 100644 index 0000000000..c94ee23939 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/merkle.c @@ -0,0 +1,64 @@ +#include +#include + +#include "merkle.h" + +#include "address.h" +#include "params.h" +#include "utils.h" +#include "utilsx2.h" +#include "wots.h" +#include "wotsx2.h" + +/* + * This generates a Merkle signature (WOTS signature followed by the Merkle + * authentication path). + */ +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf) { + unsigned char *auth_path = sig + SPX_WOTS_BYTES; + uint32_t tree_addrx2[2 * 8] = { 0 }; + int j; + struct leaf_info_x2 info = { 0 }; + unsigned steps[ SPX_WOTS_LEN ]; + + info.wots_sig = sig; + chain_lengths(steps, root); + info.wots_steps = steps; + + for (j = 0; j < 2; j++) { + set_type(&tree_addrx2[8 * j], SPX_ADDR_TYPE_HASHTREE); + set_type(&info.leaf_addr[8 * j], SPX_ADDR_TYPE_WOTS); + set_type(&info.pk_addr[8 * j], SPX_ADDR_TYPE_WOTSPK); + copy_subtree_addr(&tree_addrx2[8 * j], tree_addr); + copy_subtree_addr(&info.leaf_addr[8 * j], wots_addr); + copy_subtree_addr(&info.pk_addr[8 * j], wots_addr); + } + + info.wots_sign_leaf = idx_leaf; + + treehashx2(root, auth_path, ctx, + idx_leaf, 0, + SPX_TREE_HEIGHT, + wots_gen_leafx2, + tree_addrx2, &info); +} + +/* Compute root node of the top-most subtree. */ +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { + /* We do not need the auth path in key generation, but it simplifies the + code to have just one treehash routine that computes both root and path + in one function. */ + unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; + uint32_t top_tree_addr[8] = {0}; + uint32_t wots_addr[8] = {0}; + + set_layer_addr(top_tree_addr, SPX_D - 1); + set_layer_addr(wots_addr, SPX_D - 1); + + merkle_sign(auth_path, root, ctx, + wots_addr, top_tree_addr, + ~0 /* ~0 means "don't bother generating an auth path */ ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/merkle.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/merkle.h new file mode 100644 index 0000000000..769cf2e970 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/merkle.h @@ -0,0 +1,21 @@ +#ifndef MERKLE_H_ +#define MERKLE_H_ + +#include + +#include "context.h" +#include "params.h" + +/* Generate a Merkle signature (WOTS signature followed by the Merkle */ +/* authentication path) */ +#define merkle_sign SPX_NAMESPACE(merkle_sign) +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf); + +/* Compute the root node of the top-most subtree. */ +#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); + +#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/nistapi.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/nistapi.h new file mode 100644 index 0000000000..3cb71afad4 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/nistapi.h @@ -0,0 +1,87 @@ +#ifndef SPX_API_H +#define SPX_API_H + +#include +#include + +#include "params.h" + +#define CRYPTO_ALGNAME "SPHINCS+" + +#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES +#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES +#define CRYPTO_BYTES SPX_BYTES +#define CRYPTO_SEEDBYTES (3*SPX_N) + +/* + * Returns the length of a secret key, in bytes + */ +#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) +size_t crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) +size_t crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) +size_t crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) +size_t crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +#define crypto_sign SPX_NAMESPACE(crypto_sign) +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/params.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/params.h new file mode 100644 index 0000000000..3541803381 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/params.h @@ -0,0 +1,56 @@ +#ifndef SPX_PARAMS_H +#define SPX_PARAMS_H + +#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSSHAKE256SSIMPLE_AARCH64_##s + +/* Hash output length in bytes. */ +#define SPX_N 32 +/* Height of the hypertree. */ +#define SPX_FULL_HEIGHT 64 +/* Number of subtree layer. */ +#define SPX_D 8 +/* FORS tree dimensions. */ +#define SPX_FORS_HEIGHT 14 +#define SPX_FORS_TREES 22 +/* Winternitz parameter, */ +#define SPX_WOTS_W 16 + +/* The hash function is defined by linking a different hash.c file, as opposed + to setting a #define constant. */ + +/* For clarity */ +#define SPX_ADDR_BYTES 32 + +/* WOTS parameters. */ +#define SPX_WOTS_LOGW 4 + +#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) + +/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ +#define SPX_WOTS_LEN2 3 + +#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) +#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) +#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES + +/* Subtree size. */ +#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) + +//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT +// #error SPX_D should always divide SPX_FULL_HEIGHT +//#endif + +/* FORS parameters. */ +#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) +#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) +#define SPX_FORS_PK_BYTES SPX_N + +/* Resulting SPX sizes. */ +#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ + SPX_FULL_HEIGHT * SPX_N) +#define SPX_PK_BYTES (2 * SPX_N) +#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) + +#include "shake_offsets.h" + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/shake_offsets.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/shake_offsets.h new file mode 100644 index 0000000000..6b28d95d91 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/shake_offsets.h @@ -0,0 +1,21 @@ +#ifndef SHAKE_OFFSETS_H_ +#define SHAKE_OFFSETS_H_ + +/* + * Offsets of various fields in the address structure when we use SHAKE as + * the Sphincs+ hash function + */ + +#define SPX_OFFSET_LAYER 3 /* The byte used to specify the Merkle tree layer */ +#define SPX_OFFSET_TREE 8 /* The start of the 8 byte field used to specify the tree */ +#define SPX_OFFSET_TYPE 19 /* The byte used to specify the hash type (reason) */ +#define SPX_OFFSET_KP_ADDR2 22 /* The high byte used to specify the key pair (which one-time signature) */ +#define SPX_OFFSET_KP_ADDR1 23 /* The low byte used to specify the key pair */ +#define SPX_OFFSET_CHAIN_ADDR 27 /* The byte used to specify the chain address (which Winternitz chain) */ +#define SPX_OFFSET_HASH_ADDR 31 /* The byte used to specify the hash address (where in the Winternitz chain) */ +#define SPX_OFFSET_TREE_HGT 27 /* The byte used to specify the height of this node in the FORS or Merkle tree */ +#define SPX_OFFSET_TREE_INDEX 28 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ + +#define SPX_SHAKE 1 + +#endif /* SHAKE_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/sign.c b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/sign.c new file mode 100644 index 0000000000..9d0c7d1b22 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/sign.c @@ -0,0 +1,286 @@ +#include +#include +#include + +#include "address.h" +#include "context.h" +#include "fors.h" +#include "hash.h" +#include "merkle.h" +#include "nistapi.h" +#include "params.h" +#include "randombytes.h" +#include "thash.h" +#include "utils.h" +#include "wots.h" + +/* + * Returns the length of a secret key, in bytes + */ +size_t crypto_sign_secretkeybytes(void) { + return CRYPTO_SECRETKEYBYTES; +} + +/* + * Returns the length of a public key, in bytes + */ +size_t crypto_sign_publickeybytes(void) { + return CRYPTO_PUBLICKEYBYTES; +} + +/* + * Returns the length of a signature, in bytes + */ +size_t crypto_sign_bytes(void) { + return CRYPTO_BYTES; +} + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +size_t crypto_sign_seedbytes(void) { + return CRYPTO_SEEDBYTES; +} + +/* + * Generates an SPX key pair given a seed of length + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [PUB_SEED || root] + */ +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed) { + spx_ctx ctx; + + /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ + memcpy(sk, seed, CRYPTO_SEEDBYTES); + + memcpy(pk, sk + 2 * SPX_N, SPX_N); + + memcpy(ctx.pub_seed, pk, SPX_N); + memcpy(ctx.sk_seed, sk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + /* Compute root node of the top-most subtree. */ + merkle_gen_root(sk + 3 * SPX_N, &ctx); + + // cleanup + free_hash_function(&ctx); + + memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); + + return 0; +} + +/* + * Generates an SPX key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [PUB_SEED || root] + */ +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { + uint8_t seed[CRYPTO_SEEDBYTES]; + randombytes(seed, CRYPTO_SEEDBYTES); + crypto_sign_seed_keypair(pk, sk, seed); + + return 0; +} + +/** + * Returns an array containing a detached signature. + */ +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk) { + spx_ctx ctx; + + const uint8_t *sk_prf = sk + SPX_N; + const uint8_t *pk = sk + 2 * SPX_N; + + uint8_t optrand[SPX_N]; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t root[SPX_N]; + uint32_t i; + uint64_t tree; + uint32_t idx_leaf; + uint32_t wots_addr[8] = {0}; + uint32_t tree_addr[8] = {0}; + + memcpy(ctx.sk_seed, sk, SPX_N); + memcpy(ctx.pub_seed, pk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + + /* Optionally, signing can be made non-deterministic using optrand. + This can help counter side-channel attacks that would benefit from + getting a large number of traces when the signer uses the same nodes. */ + randombytes(optrand, SPX_N); + /* Compute the digest randomization value. */ + gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); + + /* Derive the message digest and leaf index from R, PK and M. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; + + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); + + /* Sign the message hash using FORS. */ + fors_sign(sig, root, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); + sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; + + /* Update the indices for the next layer. */ + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; + } + + free_hash_function(&ctx); + + *siglen = SPX_BYTES; + + return 0; +} + +/** + * Verifies a detached signature and message under a given public key. + */ +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk) { + spx_ctx ctx; + const uint8_t *pub_root = pk + SPX_N; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t wots_pk[SPX_WOTS_BYTES]; + uint8_t root[SPX_N]; + uint8_t leaf[SPX_N]; + unsigned int i; + uint64_t tree; + uint32_t idx_leaf; + uint32_t wots_addr[8] = {0}; + uint32_t tree_addr[8] = {0}; + uint32_t wots_pk_addr[8] = {0}; + + if (siglen != SPX_BYTES) { + return -1; + } + + memcpy(ctx.pub_seed, pk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); + + /* Derive the message digest and leaf index from R || PK || M. */ + /* The additional SPX_N is a result of the hash domain separator. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; + + /* Layer correctly defaults to 0, so no need to set_layer_addr */ + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); + + fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + /* For each subtree.. */ + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + copy_keypair_addr(wots_pk_addr, wots_addr); + + /* The WOTS public key is only correct if the signature was correct. */ + /* Initially, root is the FORS pk, but on subsequent iterations it is + the root of the subtree below the currently processed subtree. */ + wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); + sig += SPX_WOTS_BYTES; + + /* Compute the leaf node using the WOTS public key. */ + thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); + + /* Compute the root node of this subtree. */ + compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, + &ctx, tree_addr); + sig += SPX_TREE_HEIGHT * SPX_N; + + /* Update the indices for the next layer. */ + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; + } + + // cleanup + free_hash_function(&ctx); + + /* Check if the root node equals the root node in the public key. */ + if (memcmp(root, pub_root, SPX_N) != 0) { + return -1; + } + + return 0; +} + + +/** + * Returns an array containing the signature followed by the message. + */ +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk) { + size_t siglen; + + crypto_sign_signature(sm, &siglen, m, mlen, sk); + + memmove(sm + SPX_BYTES, m, mlen); + *smlen = siglen + mlen; + + return 0; +} + +/** + * Verifies a given signature-message pair under a given public key. + */ +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk) { + /* The API caller does not necessarily know what size a signature should be + but SPHINCS+ signatures are always exactly SPX_BYTES. */ + if (smlen < SPX_BYTES) { + memset(m, 0, smlen); + *mlen = 0; + return -1; + } + + *mlen = smlen - SPX_BYTES; + + if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { + memset(m, 0, smlen); + *mlen = 0; + return -1; + } + + /* If verification was successful, move the message to the right place. */ + memmove(m, sm + SPX_BYTES, *mlen); + + return 0; +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/thash.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/thash.h new file mode 100644 index 0000000000..8687ccfb4d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/thash.h @@ -0,0 +1,13 @@ +#ifndef SPX_THASH_H +#define SPX_THASH_H + +#include "context.h" +#include "params.h" + +#include + +#define thash SPX_NAMESPACE(thash) +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/thash_shake_simplex2.c b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/thash_shake_simplex2.c new file mode 100644 index 0000000000..892e453690 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/thash_shake_simplex2.c @@ -0,0 +1,83 @@ +#include +#include + +#include "thash.h" +#include "thashx2.h" + +#include "address.h" +#include "params.h" +#include "utils.h" + +#include "f1600x2.h" +#include "fips202x2.h" + + +void thash(unsigned char *out, + const unsigned char *in, + unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]) { + uint32_t addrx2 [2 * 8] = { + addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], addr[6], addr[7], + addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], addr[6], addr[7] + }; + thashx2(out, out, in, in, inblocks, ctx, addrx2); +} + +/** + * 2-way parallel version of thash; takes 2x as much input and output + */ +void thashx2(unsigned char *out0, + unsigned char *out1, + const unsigned char *in0, + const unsigned char *in1, + unsigned int inblocks, + const spx_ctx *ctx, uint32_t addrx2[2 * 8]) { + if (inblocks == 1 || inblocks == 2) { + /* As we write and read only a few quadwords, it is more efficient to + * build and extract from the twoway SHAKE256 state by hand. */ + uint64_t state[50] = {0}; + for (int i = 0; i < SPX_N / 8; i++) { + uint64_t x = load64(ctx->pub_seed + 8 * i); + state[2 * i] = x; + state[2 * i + 1] = x; + } + for (int i = 0; i < 4; i++) { + state[2 * (SPX_N / 8 + i)] = (((uint64_t)addrx2[1 + 2 * i]) << 32) + | (uint64_t)addrx2[2 * i]; + state[2 * (SPX_N / 8 + i) + 1] = (((uint64_t)addrx2[8 + 1 + 2 * i]) << 32) + | (uint64_t)addrx2[8 + 2 * i]; + } + + for (unsigned int i = 0; i < (SPX_N / 8) * inblocks; i++) { + state[2 * (SPX_N / 8 + 4 + i)] = load64(in0 + 8 * i); + state[2 * (SPX_N / 8 + 4 + i) + 1] = load64(in1 + 8 * i); + } + + /* Domain separator and padding. */ + state[2 * 16] = 0x80ULL << 56; + state[2 * 16 + 1] = 0x80ULL << 56; + + state[2 * ((SPX_N / 8) * (1 + inblocks) + 4)] ^= 0x1f; + state[2 * ((SPX_N / 8) * (1 + inblocks) + 4) + 1] ^= 0x1f; + + f1600x2(state); + + for (int i = 0; i < SPX_N / 8; i++) { + store64(out0 + 8 * i, state[2 * i]); + store64(out1 + 8 * i, state[2 * i + 1]); + } + } else { + PQCLEAN_VLA(unsigned char, buf0, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, buf1, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); + + memcpy(buf0, ctx->pub_seed, SPX_N); + memcpy(buf1, ctx->pub_seed, SPX_N); + memcpy(buf0 + SPX_N, addrx2 + 0 * 8, SPX_ADDR_BYTES); + memcpy(buf1 + SPX_N, addrx2 + 1 * 8, SPX_ADDR_BYTES); + memcpy(buf0 + SPX_N + SPX_ADDR_BYTES, in0, inblocks * SPX_N); + memcpy(buf1 + SPX_N + SPX_ADDR_BYTES, in1, inblocks * SPX_N); + + shake256x2(out0, out1, SPX_N, + buf0, buf1, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/thashx2.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/thashx2.h new file mode 100644 index 0000000000..040375e618 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/thashx2.h @@ -0,0 +1,16 @@ +#ifndef SPX_THASHX2_H +#define SPX_THASHX2_H + +#include "context.h" +#include "params.h" +#include + +#define thashx2 SPX_NAMESPACE(thashx2) +void thashx2(unsigned char *out0, + unsigned char *out1, + const unsigned char *in0, + const unsigned char *in1, + unsigned int inblocks, + const spx_ctx *ctx, uint32_t addrx2[2 * 8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/utils.c b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/utils.c new file mode 100644 index 0000000000..177b541fb9 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/utils.c @@ -0,0 +1,148 @@ +#include + +#include "utils.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "thash.h" + +/** + * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. + */ +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in) { + int i; + + /* Iterate over out in decreasing order, for big-endianness. */ + for (i = (signed int)outlen - 1; i >= 0; i--) { + out[i] = in & 0xff; + in = in >> 8; + } +} + +void u32_to_bytes(unsigned char *out, uint32_t in) { + out[0] = (unsigned char)(in >> 24); + out[1] = (unsigned char)(in >> 16); + out[2] = (unsigned char)(in >> 8); + out[3] = (unsigned char)in; +} + +/** + * Converts the inlen bytes in 'in' from big-endian byte order to an integer. + */ +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { + unsigned long long retval = 0; + unsigned int i; + + for (i = 0; i < inlen; i++) { + retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); + } + return retval; +} + +/** + * Computes a root node given a leaf and an auth path. + * Expects address to be complete other than the tree_height and tree_index. + */ +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]) { + uint32_t i; + unsigned char buffer[2 * SPX_N]; + + /* If leaf_idx is odd (last bit = 1), current path element is a right child + and auth_path has to go left. Otherwise it is the other way around. */ + if (leaf_idx & 1) { + memcpy(buffer + SPX_N, leaf, SPX_N); + memcpy(buffer, auth_path, SPX_N); + } else { + memcpy(buffer, leaf, SPX_N); + memcpy(buffer + SPX_N, auth_path, SPX_N); + } + auth_path += SPX_N; + + for (i = 0; i < tree_height - 1; i++) { + leaf_idx >>= 1; + idx_offset >>= 1; + /* Set the address of the node we're creating. */ + set_tree_height(addr, i + 1); + set_tree_index(addr, leaf_idx + idx_offset); + + /* Pick the right or left neighbor, depending on parity of the node. */ + if (leaf_idx & 1) { + thash(buffer + SPX_N, buffer, 2, ctx, addr); + memcpy(buffer, auth_path, SPX_N); + } else { + thash(buffer, buffer, 2, ctx, addr); + memcpy(buffer + SPX_N, auth_path, SPX_N); + } + auth_path += SPX_N; + } + + /* The last iteration is exceptional; we do not copy an auth_path node. */ + leaf_idx >>= 1; + idx_offset >>= 1; + set_tree_height(addr, tree_height); + set_tree_index(addr, leaf_idx + idx_offset); + thash(root, buffer, 2, ctx, addr); +} + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx * /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]) { + PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); + PQCLEAN_VLA(unsigned int, heights, tree_height + 1); + unsigned int offset = 0; + uint32_t idx; + uint32_t tree_idx; + + for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { + /* Add the next leaf node to the stack. */ + gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); + offset++; + heights[offset - 1] = 0; + + /* If this is a node we need for the auth path.. */ + if ((leaf_idx ^ 0x1) == idx) { + memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); + } + + /* While the top-most nodes are of equal height.. */ + while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { + /* Compute index of the new node, in the next layer. */ + tree_idx = (idx >> (heights[offset - 1] + 1)); + + /* Set the address of the node we're creating. */ + set_tree_height(tree_addr, heights[offset - 1] + 1); + set_tree_index(tree_addr, + tree_idx + (idx_offset >> (heights[offset - 1] + 1))); + /* Hash the top-most nodes from the stack together. */ + thash(stack + (offset - 2)*SPX_N, + stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); + offset--; + /* Note that the top-most node is now one layer higher. */ + heights[offset - 1]++; + + /* If this is a node we need for the auth path.. */ + if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { + memcpy(auth_path + heights[offset - 1]*SPX_N, + stack + (offset - 1)*SPX_N, SPX_N); + } + } + } + memcpy(root, stack, SPX_N); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/utils.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/utils.h new file mode 100644 index 0000000000..64f5d5a53a --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/utils.h @@ -0,0 +1,58 @@ +#ifndef SPX_UTILS_H +#define SPX_UTILS_H + +#include + +#include "compat.h" +#include "context.h" +#include "params.h" + + +/* To support MSVC use alloca() instead of VLAs. See #20. */ + + +/** + * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. + */ +#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in); +#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) +void u32_to_bytes(unsigned char *out, uint32_t in); + +/** + * Converts the inlen bytes in 'in' from big-endian byte order to an integer. + */ +#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); + +/** + * Computes a root node given a leaf and an auth path. + * Expects address to be complete other than the tree_height and tree_index. + */ +#define compute_root SPX_NAMESPACE(compute_root) +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]); + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +#define treehash SPX_NAMESPACE(treehash) +void treehash(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx *ctx /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]); + + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/utilsx2.c b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/utilsx2.c new file mode 100644 index 0000000000..8736474e4f --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/utilsx2.c @@ -0,0 +1,130 @@ +#include + +#include "utilsx2.h" + +#include "address.h" +#include "params.h" +#include "thashx2.h" +#include "utils.h" + +/* + * Generate the entire Merkle tree, computing the authentication path for leaf_idx, + * and the resulting root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) + * + * This expects tree_addrx2 to be initialized to 2 parallel addr structures for + * the Merkle tree nodes + * + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + * + * This works by using the standard Merkle tree building algorithm, except + * that each 'node' tracked is actually 2 consecutive nodes in the real tree. + * When we combine two logical nodes AB and WX, we perform the H + * operation on adjacent real nodes, forming the parent logical node + * (AB)(WX) + * + * When we get to the top level of the real tree (where there is only + * one logical node), we continue this operation one more time; the right + * most real node will by the actual root (and the other node will be + * garbage). We follow the same thashx2 logic so that the 'extract + * authentication path components' part of the loop is still executed (and + * to simplify the code somewhat) + */ +void treehashx2(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, + uint32_t tree_height, + void (*gen_leafx2)( + unsigned char * /* Where to write the leaves */, + const spx_ctx *, + uint32_t idx, void *info), + uint32_t tree_addrx2[2 * 8], + void *info) { + /* This is where we keep the intermediate nodes */ + unsigned char stackx2[tree_height * 2 * SPX_N]; + uint32_t left_adj = 0, prev_left_adj = 0; /* When we're doing the top */ + /* level, the left-most part of the tree isn't at the beginning */ + /* of current[]. These give the offset of the actual start */ + + uint32_t idx; + uint32_t max_idx = (1 << (tree_height - 1)) - 1; + for (idx = 0;; idx++) { + unsigned char current[2 * SPX_N]; /* Current logical node */ + gen_leafx2( current, ctx, 2 * idx + idx_offset, + info ); + + /* Now combine the freshly generated right node with previously */ + /* generated left ones */ + uint32_t internal_idx_offset = idx_offset; + uint32_t internal_idx = idx; + uint32_t internal_leaf = leaf_idx; + uint32_t h; /* The height we are in the Merkle tree */ + for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { + + /* Special processing if we're at the top of the tree */ + if (h >= tree_height - 1) { + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[1 * SPX_N], SPX_N ); + return; + } + /* The tree indexing logic is a bit off in this case */ + /* Adjust it so that the left-most node of the part of */ + /* the tree that we're processing has index 0 */ + prev_left_adj = left_adj; + left_adj = 2 - (1 << (tree_height - h - 1)); + } + + /* Check if we hit the top of the tree */ + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[1 * SPX_N], SPX_N ); + return; + } + + /* + * Check if one of the nodes we have is a part of the + * authentication path; if it is, write it out + */ + if ((((internal_idx << 1) ^ internal_leaf) & ~0x1) == 0) { + memcpy( &auth_path[ h * SPX_N ], + ¤t[(((internal_leaf & 1) ^ 1) + prev_left_adj) * SPX_N], + SPX_N ); + } + + /* + * Check if we're at a left child; if so, stop going up the stack + * Exception: if we've reached the end of the tree, keep on going + * (so we combine the last 2 nodes into the one root node in two + * more iterations) + */ + if ((internal_idx & 1) == 0 && idx < max_idx) { + break; + } + + /* Ok, we're at a right node (or doing the top 3 levels) */ + /* Now combine the left and right logical nodes together */ + + /* Set the address of the node we're creating. */ + int j; + internal_idx_offset >>= 1; + for (j = 0; j < 2; j++) { + set_tree_height(tree_addrx2 + j * 8, h + 1); + set_tree_index(tree_addrx2 + j * 8, + (2 / 2) * (internal_idx & ~1) + j - left_adj + internal_idx_offset ); + } + unsigned char *left = &stackx2[h * 2 * SPX_N]; + thashx2( ¤t[0 * SPX_N], + ¤t[1 * SPX_N], + &left [0 * SPX_N], + ¤t[0 * SPX_N], + 2, ctx, tree_addrx2); + } + + /* We've hit a left child; save the current for when we get the */ + /* corresponding right right */ + memcpy( &stackx2[h * 2 * SPX_N], current, 2 * SPX_N); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/utilsx2.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/utilsx2.h new file mode 100644 index 0000000000..e09faddc43 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/utilsx2.h @@ -0,0 +1,30 @@ +#ifndef SPX_UTILSX2_H +#define SPX_UTILSX2_H + +#include + +#include "context.h" +#include "params.h" + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + * + * This implementation uses SIMD to compute internal nodes 2 at a time (in + * parallel) + */ +#define treehashx2 SPX_NAMESPACE(treehashx2) +void treehashx2(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leafx2)( + unsigned char * /* Where to write the leaves */, + const spx_ctx * /* ctx */, + uint32_t addr_idx, void *info), + uint32_t tree_addrx2[2 * 8], void *info); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/wots.c b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/wots.c new file mode 100644 index 0000000000..3babe45e95 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/wots.c @@ -0,0 +1,259 @@ +#include +#include + +#include "wots.h" +#include "wotsx2.h" + +#include "address.h" +#include "hash.h" +#include "hashx2.h" +#include "params.h" +#include "thashx2.h" +#include "utils.h" +#include "utilsx2.h" + +// TODO clarify address expectations, and make them more uniform. +// TODO i.e. do we expect types to be set already? +// TODO and do we expect modifications or copies? + +/** + * Computes up the chains + */ +static void gen_chains( + unsigned char *out, + const unsigned char *in, + unsigned int start[SPX_WOTS_LEN], + const unsigned int steps[SPX_WOTS_LEN], + const spx_ctx *ctx, + uint32_t addr[8]) { + uint32_t i, j, k, idx, watching; + int done; + unsigned char empty[SPX_N]; + unsigned char *bufs[4]; + uint32_t addrs[8 * 2]; + + int l; + uint16_t counts[SPX_WOTS_W] = { 0 }; + uint16_t idxs[SPX_WOTS_LEN]; + uint16_t total, newTotal; + + /* set addrs = {addr, addr} */ + for (j = 0; j < 2; j++) { + memcpy(addrs + j * 8, addr, sizeof(uint32_t) * 8); + } + + /* Initialize out with the value at position 'start'. */ + memcpy(out, in, SPX_WOTS_LEN * SPX_N); + + /* Sort the chains in reverse order by steps using counting sort. */ + for (i = 0; i < SPX_WOTS_LEN; i++) { + counts[steps[i]]++; + } + total = 0; + for (l = SPX_WOTS_W - 1; l >= 0; l--) { + newTotal = counts[l] + total; + counts[l] = total; + total = newTotal; + } + for (i = 0; i < SPX_WOTS_LEN; i++) { + idxs[counts[steps[i]]] = i; + counts[steps[i]]++; + } + + /* We got our work cut out for us: do it! */ + for (i = 0; i < SPX_WOTS_LEN; i += 2) { + for (j = 0; j < 2 && i + j < SPX_WOTS_LEN; j++) { + idx = idxs[i + j]; + set_chain_addr(addrs + j * 8, idx); + bufs[j] = out + SPX_N * idx; + } + + /* As the chains are sorted in reverse order, we know that the first + * chain is the longest and the last one is the shortest. We keep + * an eye on whether the last chain is done and then on the one before, + * et cetera. */ + watching = 1; + done = 0; + while (i + watching >= SPX_WOTS_LEN) { + bufs[watching] = &empty[0]; + watching--; + } + + for (k = 0;; k++) { + while (k == steps[idxs[i + watching]]) { + bufs[watching] = &empty[0]; + if (watching == 0) { + done = 1; + break; + } + watching--; + } + if (done) { + break; + } + for (j = 0; j < watching + 1; j++) { + set_hash_addr(addrs + j * 8, k + start[idxs[i + j]]); + } + + thashx2(bufs[0], bufs[1], + bufs[0], bufs[1], 1, ctx, addrs); + } + } +} + +/** + * base_w algorithm as described in draft. + * Interprets an array of bytes as integers in base w. + * This only works when log_w is a divisor of 8. + */ +static void base_w(unsigned int *output, const int out_len, + const unsigned char *input) { + int in = 0; + int out = 0; + unsigned char total = 0; + int bits = 0; + int consumed; + + for (consumed = 0; consumed < out_len; consumed++) { + if (bits == 0) { + total = input[in]; + in++; + bits += 8; + } + bits -= SPX_WOTS_LOGW; + output[out] = (total >> bits) & (SPX_WOTS_W - 1); + out++; + } +} + +/* Computes the WOTS+ checksum over a message (in base_w). */ +static void wots_checksum(unsigned int *csum_base_w, + const unsigned int *msg_base_w) { + unsigned int csum = 0; + unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; + unsigned int i; + + /* Compute checksum. */ + for (i = 0; i < SPX_WOTS_LEN1; i++) { + csum += SPX_WOTS_W - 1 - msg_base_w[i]; + } + + /* Convert checksum to base_w. */ + /* Make sure expected empty zero bits are the least significant bits. */ + csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); + ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); + base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); +} + +/* Takes a message and derives the matching chain lengths. */ +void chain_lengths(unsigned int *lengths, const unsigned char *msg) { + base_w(lengths, SPX_WOTS_LEN1, msg); + wots_checksum(lengths + SPX_WOTS_LEN1, lengths); +} + +/** + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. + * + * Writes the computed public key to 'pk'. + */ +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]) { + unsigned int steps[SPX_WOTS_LEN]; + unsigned int start[SPX_WOTS_LEN]; + uint32_t i; + + chain_lengths(start, msg); + + for (i = 0; i < SPX_WOTS_LEN; i++) { + steps[i] = SPX_WOTS_W - 1 - start[i]; + } + + gen_chains(pk, sig, start, steps, ctx, addr); +} + +/* + * This generates 2 sequential WOTS public keys + * It also generates the WOTS signature if leaf_info indicates + * that we're signing with one of these WOTS keys + */ +void wots_gen_leafx2(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info) { + struct leaf_info_x2 *info = v_info; + uint32_t *leaf_addr = info->leaf_addr; + uint32_t *pk_addr = info->pk_addr; + unsigned int i, j, k; + unsigned char pk_buffer[ 2 * SPX_WOTS_BYTES ]; + unsigned wots_offset = SPX_WOTS_BYTES; + unsigned char *buffer; + uint32_t wots_k_mask; + unsigned wots_sign_index; + + if (((leaf_idx ^ info->wots_sign_leaf) & ~1) == 0) { + /* We're traversing the leaf that's signing; generate the WOTS */ + /* signature */ + wots_k_mask = 0; + wots_sign_index = info->wots_sign_leaf & 1; /* Which of of the 2 */ + /* slots do the signatures come from */ + } else { + /* Nope, we're just generating pk's; turn off the signature logic */ + wots_k_mask = ~0; + wots_sign_index = 0; + } + + for (j = 0; j < 2; j++) { + set_keypair_addr( leaf_addr + j * 8, leaf_idx + j ); + set_keypair_addr( pk_addr + j * 8, leaf_idx + j ); + } + + for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { + uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k to */ + /* the step if we're generating a signature, ~0 if we're not */ + + /* Start with the secret seed */ + for (j = 0; j < 2; j++) { + set_chain_addr(leaf_addr + j * 8, i); + set_hash_addr(leaf_addr + j * 8, 0); + set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTSPRF); + } + prf_addrx2(buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + ctx, leaf_addr); + for (j = 0; j < 2; j++) { + set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTS); + } + + /* Iterate down the WOTS chain */ + for (k = 0;; k++) { + /* Check if one of the values we have needs to be saved as a */ + /* part of the WOTS signature */ + if (k == wots_k) { + memcpy( info->wots_sig + i * SPX_N, + buffer + wots_sign_index * wots_offset, SPX_N ); + } + + /* Check if we hit the top of the chain */ + if (k == SPX_WOTS_W - 1) { + break; + } + + /* Iterate one step on all 4 chains */ + for (j = 0; j < 2; j++) { + set_hash_addr(leaf_addr + j * 8, k); + } + thashx2(buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + 1, ctx, leaf_addr); + } + } + + /* Do the final thash to generate the public keys */ + thashx2(dest + 0 * SPX_N, + dest + 1 * SPX_N, + pk_buffer + 0 * wots_offset, + pk_buffer + 1 * wots_offset, + SPX_WOTS_LEN, ctx, pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/wots.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/wots.h new file mode 100644 index 0000000000..4e7692eeef --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/wots.h @@ -0,0 +1,25 @@ +#ifndef SPX_WOTS_H +#define SPX_WOTS_H + +#include + +#include "context.h" +#include "params.h" + +/** + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. + * + * Writes the computed public key to 'pk'. + */ +#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]); + +/* + * Compute the chain lengths needed for a given message hash + */ +#define chain_lengths SPX_NAMESPACE(chain_lengths) +void chain_lengths(unsigned int *lengths, const unsigned char *msg); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/wotsx2.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/wotsx2.h new file mode 100644 index 0000000000..b58bb61f84 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_aarch64/wotsx2.h @@ -0,0 +1,40 @@ +#ifndef WOTSX2_H_ +#define WOTSX2_H_ + +#include "params.h" +#include + +/* + * This is here to provide an interface to the internal wots_gen_leafx2 + * routine. While this routine is not referenced in the package outside of + * wots.c, it is called from the stand-alone benchmark code to characterize + * the performance + */ +struct leaf_info_x2 { + unsigned char *wots_sig; + uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ + uint32_t *wots_steps; + uint32_t leaf_addr[2 * 8]; + uint32_t pk_addr[2 * 8]; +}; + +/* Macro to set the leaf_info to something 'benign', that is, it would */ +/* run with the same time as it does during the real signing process */ +/* Used only by the benchmark code */ +#define INITIALIZE_LEAF_INFO_X2(info, addr, step_buffer) { \ + (info).wots_sig = 0; \ + (info).wots_sign_leaf = ~0; \ + (info).wots_steps = step_buffer; \ + int i; \ + for (i=0; i<2; i++) { \ + memcpy( &(info).leaf_addr[8*i], addr, 32 ); \ + memcpy( &(info).pk_addr[8*i], addr, 32 ); \ + } \ + } + +#define wots_gen_leafx2 SPX_NAMESPACE(wots_gen_leafx2) +void wots_gen_leafx2(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info); + +#endif /* WOTSX2_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/LICENSE b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/LICENSE new file mode 100644 index 0000000000..670154e353 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/LICENSE @@ -0,0 +1,116 @@ +CC0 1.0 Universal + +Statement of Purpose + +The laws of most jurisdictions throughout the world automatically confer +exclusive Copyright and Related Rights (defined below) upon the creator and +subsequent owner(s) (each and all, an "owner") of an original work of +authorship and/or a database (each, a "Work"). + +Certain owners wish to permanently relinquish those rights to a Work for the +purpose of contributing to a commons of creative, cultural and scientific +works ("Commons") that the public can reliably and without fear of later +claims of infringement build upon, modify, incorporate in other works, reuse +and redistribute as freely as possible in any form whatsoever and for any +purposes, including without limitation commercial purposes. These owners may +contribute to the Commons to promote the ideal of a free culture and the +further production of creative, cultural and scientific works, or to gain +reputation or greater distribution for their Work in part through the use and +efforts of others. + +For these and/or other purposes and motivations, and without any expectation +of additional consideration or compensation, the person associating CC0 with a +Work (the "Affirmer"), to the extent that he or she is an owner of Copyright +and Related Rights in the Work, voluntarily elects to apply CC0 to the Work +and publicly distribute the Work under its terms, with knowledge of his or her +Copyright and Related Rights in the Work and the meaning and intended legal +effect of CC0 on those rights. + +1. Copyright and Related Rights. A Work made available under CC0 may be +protected by copyright and related or neighboring rights ("Copyright and +Related Rights"). Copyright and Related Rights include, but are not limited +to, the following: + + i. the right to reproduce, adapt, distribute, perform, display, communicate, + and translate a Work; + + ii. moral rights retained by the original author(s) and/or performer(s); + + iii. publicity and privacy rights pertaining to a person's image or likeness + depicted in a Work; + + iv. rights protecting against unfair competition in regards to a Work, + subject to the limitations in paragraph 4(a), below; + + v. rights protecting the extraction, dissemination, use and reuse of data in + a Work; + + vi. database rights (such as those arising under Directive 96/9/EC of the + European Parliament and of the Council of 11 March 1996 on the legal + protection of databases, and under any national implementation thereof, + including any amended or successor version of such directive); and + + vii. other similar, equivalent or corresponding rights throughout the world + based on applicable law or treaty, and any national implementations thereof. + +2. Waiver. To the greatest extent permitted by, but not in contravention of, +applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and +unconditionally waives, abandons, and surrenders all of Affirmer's Copyright +and Related Rights and associated claims and causes of action, whether now +known or unknown (including existing as well as future claims and causes of +action), in the Work (i) in all territories worldwide, (ii) for the maximum +duration provided by applicable law or treaty (including future time +extensions), (iii) in any current or future medium and for any number of +copies, and (iv) for any purpose whatsoever, including without limitation +commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes +the Waiver for the benefit of each member of the public at large and to the +detriment of Affirmer's heirs and successors, fully intending that such Waiver +shall not be subject to revocation, rescission, cancellation, termination, or +any other legal or equitable action to disrupt the quiet enjoyment of the Work +by the public as contemplated by Affirmer's express Statement of Purpose. + +3. Public License Fallback. Should any part of the Waiver for any reason be +judged legally invalid or ineffective under applicable law, then the Waiver +shall be preserved to the maximum extent permitted taking into account +Affirmer's express Statement of Purpose. In addition, to the extent the Waiver +is so judged Affirmer hereby grants to each affected person a royalty-free, +non transferable, non sublicensable, non exclusive, irrevocable and +unconditional license to exercise Affirmer's Copyright and Related Rights in +the Work (i) in all territories worldwide, (ii) for the maximum duration +provided by applicable law or treaty (including future time extensions), (iii) +in any current or future medium and for any number of copies, and (iv) for any +purpose whatsoever, including without limitation commercial, advertising or +promotional purposes (the "License"). The License shall be deemed effective as +of the date CC0 was applied by Affirmer to the Work. Should any part of the +License for any reason be judged legally invalid or ineffective under +applicable law, such partial invalidity or ineffectiveness shall not +invalidate the remainder of the License, and in such case Affirmer hereby +affirms that he or she will not (i) exercise any of his or her remaining +Copyright and Related Rights in the Work or (ii) assert any associated claims +and causes of action with respect to the Work, in either case contrary to +Affirmer's express Statement of Purpose. + +4. Limitations and Disclaimers. + + a. No trademark or patent rights held by Affirmer are waived, abandoned, + surrendered, licensed or otherwise affected by this document. + + b. Affirmer offers the Work as-is and makes no representations or warranties + of any kind concerning the Work, express, implied, statutory or otherwise, + including without limitation warranties of title, merchantability, fitness + for a particular purpose, non infringement, or the absence of latent or + other defects, accuracy, or the present or absence of errors, whether or not + discoverable, all to the greatest extent permissible under applicable law. + + c. Affirmer disclaims responsibility for clearing rights of other persons + that may apply to the Work or any use thereof, including without limitation + any person's Copyright and Related Rights in the Work. Further, Affirmer + disclaims responsibility for obtaining any necessary consents, permissions + or other rights required for any use of the Work. + + d. Affirmer understands and acknowledges that Creative Commons is not a + party to this document and has no duty or obligation with respect to this + CC0 or use of the Work. + +For more information, please see + diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/address.c b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/address.c new file mode 100644 index 0000000000..b956e9cb29 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/address.c @@ -0,0 +1,91 @@ +#include +#include + +#include "address.h" +#include "params.h" +#include "utils.h" + +/* + * Specify which level of Merkle tree (the "layer") we're working on + */ +void set_layer_addr(uint32_t addr[8], uint32_t layer) { + ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; +} + +/* + * Specify which Merkle tree within the level (the "tree address") we're working on + */ +void set_tree_addr(uint32_t addr[8], uint64_t tree) { + ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); +} + +/* + * Specify the reason we'll use this address structure for, that is, what + * hash will we compute with it. This is used so that unrelated types of + * hashes don't accidentally get the same address structure. The type will be + * one of the SPX_ADDR_TYPE constants + */ +void set_type(uint32_t addr[8], uint32_t type) { + ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; +} + +/* + * Copy the layer and tree fields of the address structure. This is used + * when we're doing multiple types of hashes within the same Merkle tree + */ +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); +} + +/* These functions are used for OTS addresses. */ + +/* + * Specify which Merkle leaf we're working on; that is, which OTS keypair + * we're talking about. + */ +void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { + ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; +} + +/* + * Copy the layer, tree and keypair fields of the address structure. This is + * used when we're doing multiple things within the same OTS keypair + */ +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); + ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; +} + +/* + * Specify which Merkle chain within the OTS we're working with + * (the chain address) + */ +void set_chain_addr(uint32_t addr[8], uint32_t chain) { + ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; +} + +/* + * Specify where in the Merkle chain we are +* (the hash address) + */ +void set_hash_addr(uint32_t addr[8], uint32_t hash) { + ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; +} + +/* These functions are used for all hash tree addresses (including FORS). */ + +/* + * Specify the height of the node in the Merkle/FORS tree we are in + * (the tree height) + */ +void set_tree_height(uint32_t addr[8], uint32_t tree_height) { + ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; +} + +/* + * Specify the distance from the left edge of the node in the Merkle/FORS tree + * (the tree index) + */ +void set_tree_index(uint32_t addr[8], uint32_t tree_index) { + u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/address.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/address.h new file mode 100644 index 0000000000..24a84eb40c --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/address.h @@ -0,0 +1,52 @@ +#ifndef SPX_ADDRESS_H +#define SPX_ADDRESS_H + +#include + +#include "params.h" + +/* The hash types that are passed to set_type */ +#define SPX_ADDR_TYPE_WOTS 0 +#define SPX_ADDR_TYPE_WOTSPK 1 +#define SPX_ADDR_TYPE_HASHTREE 2 +#define SPX_ADDR_TYPE_FORSTREE 3 +#define SPX_ADDR_TYPE_FORSPK 4 +#define SPX_ADDR_TYPE_WOTSPRF 5 +#define SPX_ADDR_TYPE_FORSPRF 6 + +#define set_layer_addr SPX_NAMESPACE(set_layer_addr) +void set_layer_addr(uint32_t addr[8], uint32_t layer); + +#define set_tree_addr SPX_NAMESPACE(set_tree_addr) +void set_tree_addr(uint32_t addr[8], uint64_t tree); + +#define set_type SPX_NAMESPACE(set_type) +void set_type(uint32_t addr[8], uint32_t type); + +/* Copies the layer and tree part of one address into the other */ +#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); + +/* These functions are used for WOTS and FORS addresses. */ + +#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) +void set_keypair_addr(uint32_t addr[8], uint32_t keypair); + +#define set_chain_addr SPX_NAMESPACE(set_chain_addr) +void set_chain_addr(uint32_t addr[8], uint32_t chain); + +#define set_hash_addr SPX_NAMESPACE(set_hash_addr) +void set_hash_addr(uint32_t addr[8], uint32_t hash); + +#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); + +/* These functions are used for all hash tree addresses (including FORS). */ + +#define set_tree_height SPX_NAMESPACE(set_tree_height) +void set_tree_height(uint32_t addr[8], uint32_t tree_height); + +#define set_tree_index SPX_NAMESPACE(set_tree_index) +void set_tree_index(uint32_t addr[8], uint32_t tree_index); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/api.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/api.h new file mode 100644 index 0000000000..e16ae18fd8 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/api.h @@ -0,0 +1,77 @@ +#ifndef PQCLEAN_SPHINCSSHAKE256SSIMPLE_AVX2_API_H +#define PQCLEAN_SPHINCSSHAKE256SSIMPLE_AVX2_API_H + +#include +#include + +#define PQCLEAN_SPHINCSSHAKE256SSIMPLE_AVX2_CRYPTO_ALGNAME "SPHINCS+-shake-256s-simple" + +#define PQCLEAN_SPHINCSSHAKE256SSIMPLE_AVX2_CRYPTO_SECRETKEYBYTES 128 +#define PQCLEAN_SPHINCSSHAKE256SSIMPLE_AVX2_CRYPTO_PUBLICKEYBYTES 64 +#define PQCLEAN_SPHINCSSHAKE256SSIMPLE_AVX2_CRYPTO_BYTES 29792 + +#define PQCLEAN_SPHINCSSHAKE256SSIMPLE_AVX2_CRYPTO_SEEDBYTES 96 + +/* + * Returns the length of a secret key, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE256SSIMPLE_AVX2_crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE256SSIMPLE_AVX2_crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE256SSIMPLE_AVX2_crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE256SSIMPLE_AVX2_crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +int PQCLEAN_SPHINCSSHAKE256SSIMPLE_AVX2_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +int PQCLEAN_SPHINCSSHAKE256SSIMPLE_AVX2_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +int PQCLEAN_SPHINCSSHAKE256SSIMPLE_AVX2_crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +int PQCLEAN_SPHINCSSHAKE256SSIMPLE_AVX2_crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, + const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +int PQCLEAN_SPHINCSSHAKE256SSIMPLE_AVX2_crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +int PQCLEAN_SPHINCSSHAKE256SSIMPLE_AVX2_crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/context.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/context.h new file mode 100644 index 0000000000..6e0a33f3b7 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/context.h @@ -0,0 +1,19 @@ +#ifndef SPX_CONTEXT_H +#define SPX_CONTEXT_H + +#include + +#include "params.h" + +typedef struct { + uint8_t pub_seed[SPX_N]; + uint8_t sk_seed[SPX_N]; +} spx_ctx; + +#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) +void initialize_hash_function(spx_ctx *ctx); + +#define free_hash_function SPX_NAMESPACE(free_hash_function) +void free_hash_function(spx_ctx *ctx); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/context_shake.c b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/context_shake.c new file mode 100644 index 0000000000..9614a103d3 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/context_shake.c @@ -0,0 +1,12 @@ +#include "context.h" + +/* For SHAKE256, there is no immediate reason to initialize at the start, + so this function is an empty operation. */ +void initialize_hash_function(spx_ctx *ctx) { + (void)ctx; /* Suppress an 'unused parameter' warning. */ +} + +// in case the hash function api is heap-based. +void free_hash_function(spx_ctx *ctx) { + (void)ctx; +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/fips202x4.c b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/fips202x4.c new file mode 100644 index 0000000000..1e06fef186 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/fips202x4.c @@ -0,0 +1,210 @@ +#include +#include +#include + +#include "fips202.h" +#include "fips202x4.h" + +#define NROUNDS 24 +#define ROL(a, offset) (((a) << (offset)) ^ ((a) >> (64-(offset)))) + +static uint64_t load64(const unsigned char *x) { + unsigned long long r = 0, i; + + for (i = 0; i < 8; ++i) { + r |= (unsigned long long)x[i] << 8 * i; + } + return r; +} + +static void store64(uint8_t *x, uint64_t u) { + unsigned int i; + + for (i = 0; i < 8; ++i) { + x[i] = (uint8_t)u; + u >>= 8; + } +} + +/* Use implementation from the Keccak Code Package */ +extern void KeccakP1600times4_PermuteAll_24rounds(__m256i *s); +#define KeccakF1600_StatePermute4x KeccakP1600times4_PermuteAll_24rounds + +static void keccak_absorb4x(__m256i *s, + unsigned int r, + const unsigned char *m0, + const unsigned char *m1, + const unsigned char *m2, + const unsigned char *m3, + unsigned long long int mlen, + unsigned char p) { + unsigned long long i; + unsigned char t0[200]; + unsigned char t1[200]; + unsigned char t2[200]; + unsigned char t3[200]; + + unsigned long long *ss = (unsigned long long *)s; + + + while (mlen >= r) { + for (i = 0; i < r / 8; ++i) { + ss[4 * i + 0] ^= load64(m0 + 8 * i); + ss[4 * i + 1] ^= load64(m1 + 8 * i); + ss[4 * i + 2] ^= load64(m2 + 8 * i); + ss[4 * i + 3] ^= load64(m3 + 8 * i); + } + + KeccakF1600_StatePermute4x(s); + mlen -= r; + m0 += r; + m1 += r; + m2 += r; + m3 += r; + } + + for (i = 0; i < r; ++i) { + t0[i] = 0; + t1[i] = 0; + t2[i] = 0; + t3[i] = 0; + } + for (i = 0; i < mlen; ++i) { + t0[i] = m0[i]; + t1[i] = m1[i]; + t2[i] = m2[i]; + t3[i] = m3[i]; + } + + t0[i] = p; + t1[i] = p; + t2[i] = p; + t3[i] = p; + + t0[r - 1] |= 128; + t1[r - 1] |= 128; + t2[r - 1] |= 128; + t3[r - 1] |= 128; + + for (i = 0; i < r / 8; ++i) { + ss[4 * i + 0] ^= load64(t0 + 8 * i); + ss[4 * i + 1] ^= load64(t1 + 8 * i); + ss[4 * i + 2] ^= load64(t2 + 8 * i); + ss[4 * i + 3] ^= load64(t3 + 8 * i); + } +} + + +static void keccak_squeezeblocks4x(unsigned char *h0, + unsigned char *h1, + unsigned char *h2, + unsigned char *h3, + unsigned long long int nblocks, + __m256i *s, + unsigned int r) { + unsigned int i; + + unsigned long long *ss = (unsigned long long *)s; + + while (nblocks > 0) { + KeccakF1600_StatePermute4x(s); + for (i = 0; i < (r >> 3); i++) { + store64(h0 + 8 * i, ss[4 * i + 0]); + store64(h1 + 8 * i, ss[4 * i + 1]); + store64(h2 + 8 * i, ss[4 * i + 2]); + store64(h3 + 8 * i, ss[4 * i + 3]); + } + h0 += r; + h1 += r; + h2 += r; + h3 += r; + nblocks--; + } +} + + + +void shake128x4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, unsigned long long outlen, + unsigned char *in0, + unsigned char *in1, + unsigned char *in2, + unsigned char *in3, unsigned long long inlen) { + __m256i s[25]; + unsigned char t0[SHAKE128_RATE]; + unsigned char t1[SHAKE128_RATE]; + unsigned char t2[SHAKE128_RATE]; + unsigned char t3[SHAKE128_RATE]; + unsigned int i; + + /* zero state */ + for (i = 0; i < 25; i++) { + s[i] = _mm256_xor_si256(s[i], s[i]); + } + + /* absorb 4 message of identical length in parallel */ + keccak_absorb4x(s, SHAKE128_RATE, in0, in1, in2, in3, inlen, 0x1F); + + /* Squeeze output */ + keccak_squeezeblocks4x(out0, out1, out2, out3, outlen / SHAKE128_RATE, s, SHAKE128_RATE); + + out0 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; + out1 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; + out2 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; + out3 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; + + if (outlen % SHAKE128_RATE) { + keccak_squeezeblocks4x(t0, t1, t2, t3, 1, s, SHAKE128_RATE); + for (i = 0; i < outlen % SHAKE128_RATE; i++) { + out0[i] = t0[i]; + out1[i] = t1[i]; + out2[i] = t2[i]; + out3[i] = t3[i]; + } + } +} + + +void shake256x4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, unsigned long long outlen, + unsigned char *in0, + unsigned char *in1, + unsigned char *in2, + unsigned char *in3, unsigned long long inlen) { + __m256i s[25]; + unsigned char t0[SHAKE256_RATE]; + unsigned char t1[SHAKE256_RATE]; + unsigned char t2[SHAKE256_RATE]; + unsigned char t3[SHAKE256_RATE]; + unsigned int i; + + /* zero state */ + for (i = 0; i < 25; i++) { + s[i] = _mm256_xor_si256(s[i], s[i]); + } + + /* absorb 4 message of identical length in parallel */ + keccak_absorb4x(s, SHAKE256_RATE, in0, in1, in2, in3, inlen, 0x1F); + + /* Squeeze output */ + keccak_squeezeblocks4x(out0, out1, out2, out3, outlen / SHAKE256_RATE, s, SHAKE256_RATE); + + out0 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; + out1 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; + out2 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; + out3 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; + + if (outlen % SHAKE256_RATE) { + keccak_squeezeblocks4x(t0, t1, t2, t3, 1, s, SHAKE256_RATE); + for (i = 0; i < outlen % SHAKE256_RATE; i++) { + out0[i] = t0[i]; + out1[i] = t1[i]; + out2[i] = t2[i]; + out3[i] = t3[i]; + } + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/fips202x4.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/fips202x4.h new file mode 100644 index 0000000000..2b93c9cd0d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/fips202x4.h @@ -0,0 +1,28 @@ +#ifndef SPX_FIPS202X4_H +#define SPX_FIPS202X4_H + +#include + +#include "params.h" + +#define shake128x4 SPX_NAMESPACE(shake128x4) +void shake128x4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, unsigned long long outlen, + unsigned char *in0, + unsigned char *in1, + unsigned char *in2, + unsigned char *in3, unsigned long long inlen); + +#define shake256x4 SPX_NAMESPACE(shake256x4) +void shake256x4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, unsigned long long outlen, + unsigned char *in0, + unsigned char *in1, + unsigned char *in2, + unsigned char *in3, unsigned long long inlen); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/fors.c b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/fors.c new file mode 100644 index 0000000000..f1b0639cfc --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/fors.c @@ -0,0 +1,202 @@ +#include +#include +#include + +#include "fors.h" + +#include "address.h" +#include "hash.h" +#include "hashx4.h" +#include "thash.h" +#include "thashx4.h" +#include "utils.h" +#include "utilsx4.h" + +static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + prf_addr(sk, ctx, fors_leaf_addr); +} + +static void fors_gen_skx4(unsigned char *sk0, + unsigned char *sk1, + unsigned char *sk2, + unsigned char *sk3, const spx_ctx *ctx, + uint32_t fors_leaf_addrx4[4 * 8]) { + prf_addrx4(sk0, sk1, sk2, sk3, + ctx, fors_leaf_addrx4); +} + +static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, + const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + thash(leaf, sk, 1, ctx, fors_leaf_addr); +} + +static void fors_sk_to_leafx4(unsigned char *leaf0, + unsigned char *leaf1, + unsigned char *leaf2, + unsigned char *leaf3, + const unsigned char *sk0, + const unsigned char *sk1, + const unsigned char *sk2, + const unsigned char *sk3, + const spx_ctx *ctx, + uint32_t fors_leaf_addrx4[4 * 8]) { + thashx4(leaf0, leaf1, leaf2, leaf3, + sk0, sk1, sk2, sk3, + 1, ctx, fors_leaf_addrx4); +} + +struct fors_gen_leaf_info { + uint32_t leaf_addrx[4 * 8]; +}; + +static void fors_gen_leafx4(unsigned char *leaf, + const spx_ctx *ctx, + uint32_t addr_idx, void *info) { + struct fors_gen_leaf_info *fors_info = info; + uint32_t *fors_leaf_addrx4 = fors_info->leaf_addrx; + unsigned int j; + + /* Only set the parts that the caller doesn't set */ + for (j = 0; j < 4; j++) { + set_tree_index(fors_leaf_addrx4 + j * 8, addr_idx + j); + set_type(fors_leaf_addrx4 + j * 8, SPX_ADDR_TYPE_FORSPRF); + } + + fors_gen_skx4(leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + leaf + 2 * SPX_N, + leaf + 3 * SPX_N, + ctx, fors_leaf_addrx4); + + for (j = 0; j < 4; j++) { + set_type(fors_leaf_addrx4 + j * 8, SPX_ADDR_TYPE_FORSTREE); + } + + fors_sk_to_leafx4(leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + leaf + 2 * SPX_N, + leaf + 3 * SPX_N, + leaf + 0 * SPX_N, + leaf + 1 * SPX_N, + leaf + 2 * SPX_N, + leaf + 3 * SPX_N, + ctx, fors_leaf_addrx4); +} + +/** + * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + * Assumes indices has space for SPX_FORS_TREES integers. + */ +static void message_to_indices(uint32_t *indices, const unsigned char *m) { + unsigned int i, j; + unsigned int offset = 0; + + for (i = 0; i < SPX_FORS_TREES; i++) { + indices[i] = 0; + for (j = 0; j < SPX_FORS_HEIGHT; j++) { + indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); + offset++; + } + } +} + +/** + * Signs a message m, deriving the secret key from sk_seed and the FTS address. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + uint32_t fors_tree_addr[4 * 8] = {0}; + struct fors_gen_leaf_info fors_info = {0}; + uint32_t *fors_leaf_addr = fors_info.leaf_addrx; + uint32_t fors_pk_addr[8] = {0}; + uint32_t idx_offset; + unsigned int i; + + for (i = 0; i < 4; i++) { + copy_keypair_addr(fors_tree_addr + 8 * i, fors_addr); + set_type(fors_tree_addr + 8 * i, SPX_ADDR_TYPE_FORSTREE); + copy_keypair_addr(fors_leaf_addr + 8 * i, fors_addr); + } + copy_keypair_addr(fors_pk_addr, fors_addr); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); + + message_to_indices(indices, m); + + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); + + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + + /* Include the secret key part that produces the selected leaf node. */ + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); + fors_gen_sk(sig, ctx, fors_tree_addr); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + sig += SPX_N; + + /* Compute the authentication path for this leaf node. */ + treehashx4(roots + i * SPX_N, sig, ctx, + indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx4, + fors_tree_addr, &fors_info); + + sig += SPX_N * SPX_FORS_HEIGHT; + } + + /* Hash horizontally across all tree roots to derive the public key. */ + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); +} + +/** + * Derives the FORS public key from a signature. + * This can be used for verification by comparing to a known public key, or to + * subsequently verify a signature on the derived public key. The latter is the + * typical use-case when used as an FTS below an OTS in a hypertree. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + unsigned char leaf[SPX_N]; + uint32_t fors_tree_addr[8] = {0}; + uint32_t fors_pk_addr[8] = {0}; + uint32_t idx_offset; + unsigned int i; + + copy_keypair_addr(fors_tree_addr, fors_addr); + copy_keypair_addr(fors_pk_addr, fors_addr); + + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); + + message_to_indices(indices, m); + + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); + + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + + /* Derive the leaf from the included secret key part. */ + fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); + sig += SPX_N; + + /* Derive the corresponding root node of this tree. */ + compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, + sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); + sig += SPX_N * SPX_FORS_HEIGHT; + } + + /* Hash horizontally across all tree roots to derive the public key. */ + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/fors.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/fors.h new file mode 100644 index 0000000000..509140a178 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/fors.h @@ -0,0 +1,32 @@ +#ifndef SPX_FORS_H +#define SPX_FORS_H + +#include + +#include "context.h" +#include "params.h" + +/** + * Signs a message m, deriving the secret key from sk_seed and the FTS address. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +#define fors_sign SPX_NAMESPACE(fors_sign) +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); + +/** + * Derives the FORS public key from a signature. + * This can be used for verification by comparing to a known public key, or to + * subsequently verify a signature on the derived public key. The latter is the + * typical use-case when used as an FTS below an OTS in a hypertree. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/hash.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/hash.h new file mode 100644 index 0000000000..f7c87d4c3c --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/hash.h @@ -0,0 +1,28 @@ +#ifndef SPX_HASH_H +#define SPX_HASH_H + +#include +#include + +#include "context.h" +#include "params.h" + +#define prf_addr SPX_NAMESPACE(prf_addr) +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]); + +#define gen_message_random SPX_NAMESPACE(gen_message_random) +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); + +#define hash_message SPX_NAMESPACE(hash_message) +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); + + + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/hash_shake.c b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/hash_shake.c new file mode 100644 index 0000000000..ff5e7ec918 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/hash_shake.c @@ -0,0 +1,83 @@ +#include +#include + +#include "hash.h" + +#include "address.h" +#include "fips202.h" +#include "params.h" +#include "utils.h" + +/* + * Computes PRF(pk_seed, sk_seed, addr) + */ +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]) { + unsigned char buf[2 * SPX_N + SPX_ADDR_BYTES]; + + memcpy(buf, ctx->pub_seed, SPX_N); + memcpy(buf + SPX_N, addr, SPX_ADDR_BYTES); + memcpy(buf + SPX_N + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); + + shake256(out, SPX_N, buf, 2 * SPX_N + SPX_ADDR_BYTES); +} + +/** + * Computes the message-dependent randomness R, using a secret seed and an + * optional randomization value as well as the message. + */ +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { + (void)ctx; + shake256incctx s_inc; + + shake256_inc_init(&s_inc); + shake256_inc_absorb(&s_inc, sk_prf, SPX_N); + shake256_inc_absorb(&s_inc, optrand, SPX_N); + shake256_inc_absorb(&s_inc, m, mlen); + shake256_inc_finalize(&s_inc); + shake256_inc_squeeze(R, SPX_N, &s_inc); + shake256_inc_ctx_release(&s_inc); +} + +/** + * Computes the message hash using R, the public key, and the message. + * Outputs the message digest and the index of the leaf. The index is split in + * the tree index and the leaf index, for convenient copying to an address. + */ +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { + (void)ctx; +#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) +#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) +#define SPX_LEAF_BITS SPX_TREE_HEIGHT +#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) +#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) + + unsigned char buf[SPX_DGST_BYTES]; + unsigned char *bufp = buf; + shake256incctx s_inc; + + shake256_inc_init(&s_inc); + shake256_inc_absorb(&s_inc, R, SPX_N); + shake256_inc_absorb(&s_inc, pk, SPX_PK_BYTES); + shake256_inc_absorb(&s_inc, m, mlen); + shake256_inc_finalize(&s_inc); + shake256_inc_squeeze(buf, SPX_DGST_BYTES, &s_inc); + shake256_inc_ctx_release(&s_inc); + + memcpy(digest, bufp, SPX_FORS_MSG_BYTES); + bufp += SPX_FORS_MSG_BYTES; + + + *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); + *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); + bufp += SPX_TREE_BYTES; + + *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); + *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/hash_shakex4.c b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/hash_shakex4.c new file mode 100644 index 0000000000..bbd22eb117 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/hash_shakex4.c @@ -0,0 +1,64 @@ +#include +#include + +#include "hashx4.h" + +#include "address.h" +#include "fips202x4.h" +#include "params.h" + +extern void KeccakP1600times4_PermuteAll_24rounds(__m256i *s); + +/* + * 4-way parallel version of prf_addr; takes 4x as much input and output + */ +void prf_addrx4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const spx_ctx *ctx, + const uint32_t addrx4[4 * 8]) { + /* As we write and read only a few quadwords, it is more efficient to + * build and extract from the fourway SHAKE256 state by hand. */ + __m256i state[25]; + + for (int i = 0; i < SPX_N / 8; i++) { + state[i] = _mm256_set1_epi64x(((int64_t *)ctx->pub_seed)[i]); + } + for (int i = 0; i < 4; i++) { + state[SPX_N / 8 + i] = _mm256_set_epi32( + (int)addrx4[3 * 8 + 1 + 2 * i], + (int)addrx4[3 * 8 + 2 * i], + (int)addrx4[2 * 8 + 1 + 2 * i], + (int)addrx4[2 * 8 + 2 * i], + (int)addrx4[8 + 1 + 2 * i], + (int)addrx4[8 + 2 * i], + (int)addrx4[1 + 2 * i], + (int)addrx4[2 * i] + ); + } + for (int i = 0; i < SPX_N / 8; i++) { + state[SPX_N / 8 + i + 4] = _mm256_set1_epi64x(((int64_t *)ctx->sk_seed)[i]); + } + + /* SHAKE domain separator and padding. */ + state[SPX_N / 4 + 4] = _mm256_set1_epi64x(0x1f); + for (int i = SPX_N / 4 + 5; i < 16; i++) { + state[i] = _mm256_set1_epi64x(0); + } + // shift unsigned and then cast to avoid UB + state[16] = _mm256_set1_epi64x((long long)(0x80ULL << 56)); + + for (int i = 17; i < 25; i++) { + state[i] = _mm256_set1_epi64x(0); + } + + KeccakP1600times4_PermuteAll_24rounds(&state[0]); + + for (int i = 0; i < SPX_N / 8; i++) { + ((int64_t *)out0)[i] = _mm256_extract_epi64(state[i], 0); + ((int64_t *)out1)[i] = _mm256_extract_epi64(state[i], 1); + ((int64_t *)out2)[i] = _mm256_extract_epi64(state[i], 2); + ((int64_t *)out3)[i] = _mm256_extract_epi64(state[i], 3); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/hashx4.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/hashx4.h new file mode 100644 index 0000000000..3751a0ebd0 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/hashx4.h @@ -0,0 +1,17 @@ +#ifndef SPX_HASHX4_H +#define SPX_HASHX4_H + +#include + +#include "context.h" +#include "params.h" + +#define prf_addrx4 SPX_NAMESPACE(prf_addrx4) +void prf_addrx4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const spx_ctx *ctx, + const uint32_t addrx4[4 * 8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/merkle.c b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/merkle.c new file mode 100644 index 0000000000..f57811c1ac --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/merkle.c @@ -0,0 +1,64 @@ +#include +#include + +#include "merkle.h" + +#include "address.h" +#include "params.h" +#include "utils.h" +#include "utilsx4.h" +#include "wots.h" +#include "wotsx4.h" + +/* + * This generates a Merkle signature (WOTS signature followed by the Merkle + * authentication path). + */ +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf) { + unsigned char *auth_path = sig + SPX_WOTS_BYTES; + uint32_t tree_addrx4[4 * 8] = { 0 }; + int j; + struct leaf_info_x4 info = { 0 }; + unsigned steps[ SPX_WOTS_LEN ]; + + info.wots_sig = sig; + chain_lengths(steps, root); + info.wots_steps = steps; + + for (j = 0; j < 4; j++) { + set_type(&tree_addrx4[8 * j], SPX_ADDR_TYPE_HASHTREE); + set_type(&info.leaf_addr[8 * j], SPX_ADDR_TYPE_WOTS); + set_type(&info.pk_addr[8 * j], SPX_ADDR_TYPE_WOTSPK); + copy_subtree_addr(&tree_addrx4[8 * j], tree_addr); + copy_subtree_addr(&info.leaf_addr[8 * j], wots_addr); + copy_subtree_addr(&info.pk_addr[8 * j], wots_addr); + } + + info.wots_sign_leaf = idx_leaf; + + treehashx4(root, auth_path, ctx, + idx_leaf, 0, + SPX_TREE_HEIGHT, + wots_gen_leafx4, + tree_addrx4, &info); +} + +/* Compute root node of the top-most subtree. */ +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { + /* We do not need the auth path in key generation, but it simplifies the + code to have just one treehash routine that computes both root and path + in one function. */ + unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; + uint32_t top_tree_addr[8] = {0}; + uint32_t wots_addr[8] = {0}; + + set_layer_addr(top_tree_addr, SPX_D - 1); + set_layer_addr(wots_addr, SPX_D - 1); + + merkle_sign(auth_path, root, ctx, + wots_addr, top_tree_addr, + ~0U /* ~0 means "don't bother generating an auth path */ ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/merkle.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/merkle.h new file mode 100644 index 0000000000..769cf2e970 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/merkle.h @@ -0,0 +1,21 @@ +#ifndef MERKLE_H_ +#define MERKLE_H_ + +#include + +#include "context.h" +#include "params.h" + +/* Generate a Merkle signature (WOTS signature followed by the Merkle */ +/* authentication path) */ +#define merkle_sign SPX_NAMESPACE(merkle_sign) +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf); + +/* Compute the root node of the top-most subtree. */ +#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); + +#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/nistapi.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/nistapi.h new file mode 100644 index 0000000000..3cb71afad4 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/nistapi.h @@ -0,0 +1,87 @@ +#ifndef SPX_API_H +#define SPX_API_H + +#include +#include + +#include "params.h" + +#define CRYPTO_ALGNAME "SPHINCS+" + +#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES +#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES +#define CRYPTO_BYTES SPX_BYTES +#define CRYPTO_SEEDBYTES (3*SPX_N) + +/* + * Returns the length of a secret key, in bytes + */ +#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) +size_t crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) +size_t crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) +size_t crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) +size_t crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +#define crypto_sign SPX_NAMESPACE(crypto_sign) +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/params.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/params.h new file mode 100644 index 0000000000..bc7979e219 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/params.h @@ -0,0 +1,56 @@ +#ifndef SPX_PARAMS_H +#define SPX_PARAMS_H + +#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSSHAKE256SSIMPLE_AVX2_##s + +/* Hash output length in bytes. */ +#define SPX_N 32 +/* Height of the hypertree. */ +#define SPX_FULL_HEIGHT 64 +/* Number of subtree layer. */ +#define SPX_D 8 +/* FORS tree dimensions. */ +#define SPX_FORS_HEIGHT 14 +#define SPX_FORS_TREES 22 +/* Winternitz parameter, */ +#define SPX_WOTS_W 16 + +/* The hash function is defined by linking a different hash.c file, as opposed + to setting a #define constant. */ + +/* For clarity */ +#define SPX_ADDR_BYTES 32 + +/* WOTS parameters. */ +#define SPX_WOTS_LOGW 4 + +#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) + +/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ +#define SPX_WOTS_LEN2 3 + +#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) +#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) +#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES + +/* Subtree size. */ +#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) + +//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT +// #error SPX_D should always divide SPX_FULL_HEIGHT +//#endif + +/* FORS parameters. */ +#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) +#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) +#define SPX_FORS_PK_BYTES SPX_N + +/* Resulting SPX sizes. */ +#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ + SPX_FULL_HEIGHT * SPX_N) +#define SPX_PK_BYTES (2 * SPX_N) +#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) + +#include "shake_offsets.h" + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/shake_offsets.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/shake_offsets.h new file mode 100644 index 0000000000..6b28d95d91 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/shake_offsets.h @@ -0,0 +1,21 @@ +#ifndef SHAKE_OFFSETS_H_ +#define SHAKE_OFFSETS_H_ + +/* + * Offsets of various fields in the address structure when we use SHAKE as + * the Sphincs+ hash function + */ + +#define SPX_OFFSET_LAYER 3 /* The byte used to specify the Merkle tree layer */ +#define SPX_OFFSET_TREE 8 /* The start of the 8 byte field used to specify the tree */ +#define SPX_OFFSET_TYPE 19 /* The byte used to specify the hash type (reason) */ +#define SPX_OFFSET_KP_ADDR2 22 /* The high byte used to specify the key pair (which one-time signature) */ +#define SPX_OFFSET_KP_ADDR1 23 /* The low byte used to specify the key pair */ +#define SPX_OFFSET_CHAIN_ADDR 27 /* The byte used to specify the chain address (which Winternitz chain) */ +#define SPX_OFFSET_HASH_ADDR 31 /* The byte used to specify the hash address (where in the Winternitz chain) */ +#define SPX_OFFSET_TREE_HGT 27 /* The byte used to specify the height of this node in the FORS or Merkle tree */ +#define SPX_OFFSET_TREE_INDEX 28 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ + +#define SPX_SHAKE 1 + +#endif /* SHAKE_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/sign.c b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/sign.c new file mode 100644 index 0000000000..9d0c7d1b22 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/sign.c @@ -0,0 +1,286 @@ +#include +#include +#include + +#include "address.h" +#include "context.h" +#include "fors.h" +#include "hash.h" +#include "merkle.h" +#include "nistapi.h" +#include "params.h" +#include "randombytes.h" +#include "thash.h" +#include "utils.h" +#include "wots.h" + +/* + * Returns the length of a secret key, in bytes + */ +size_t crypto_sign_secretkeybytes(void) { + return CRYPTO_SECRETKEYBYTES; +} + +/* + * Returns the length of a public key, in bytes + */ +size_t crypto_sign_publickeybytes(void) { + return CRYPTO_PUBLICKEYBYTES; +} + +/* + * Returns the length of a signature, in bytes + */ +size_t crypto_sign_bytes(void) { + return CRYPTO_BYTES; +} + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +size_t crypto_sign_seedbytes(void) { + return CRYPTO_SEEDBYTES; +} + +/* + * Generates an SPX key pair given a seed of length + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [PUB_SEED || root] + */ +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed) { + spx_ctx ctx; + + /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ + memcpy(sk, seed, CRYPTO_SEEDBYTES); + + memcpy(pk, sk + 2 * SPX_N, SPX_N); + + memcpy(ctx.pub_seed, pk, SPX_N); + memcpy(ctx.sk_seed, sk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + /* Compute root node of the top-most subtree. */ + merkle_gen_root(sk + 3 * SPX_N, &ctx); + + // cleanup + free_hash_function(&ctx); + + memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); + + return 0; +} + +/* + * Generates an SPX key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [PUB_SEED || root] + */ +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { + uint8_t seed[CRYPTO_SEEDBYTES]; + randombytes(seed, CRYPTO_SEEDBYTES); + crypto_sign_seed_keypair(pk, sk, seed); + + return 0; +} + +/** + * Returns an array containing a detached signature. + */ +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk) { + spx_ctx ctx; + + const uint8_t *sk_prf = sk + SPX_N; + const uint8_t *pk = sk + 2 * SPX_N; + + uint8_t optrand[SPX_N]; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t root[SPX_N]; + uint32_t i; + uint64_t tree; + uint32_t idx_leaf; + uint32_t wots_addr[8] = {0}; + uint32_t tree_addr[8] = {0}; + + memcpy(ctx.sk_seed, sk, SPX_N); + memcpy(ctx.pub_seed, pk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + + /* Optionally, signing can be made non-deterministic using optrand. + This can help counter side-channel attacks that would benefit from + getting a large number of traces when the signer uses the same nodes. */ + randombytes(optrand, SPX_N); + /* Compute the digest randomization value. */ + gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); + + /* Derive the message digest and leaf index from R, PK and M. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; + + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); + + /* Sign the message hash using FORS. */ + fors_sign(sig, root, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); + sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; + + /* Update the indices for the next layer. */ + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; + } + + free_hash_function(&ctx); + + *siglen = SPX_BYTES; + + return 0; +} + +/** + * Verifies a detached signature and message under a given public key. + */ +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk) { + spx_ctx ctx; + const uint8_t *pub_root = pk + SPX_N; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t wots_pk[SPX_WOTS_BYTES]; + uint8_t root[SPX_N]; + uint8_t leaf[SPX_N]; + unsigned int i; + uint64_t tree; + uint32_t idx_leaf; + uint32_t wots_addr[8] = {0}; + uint32_t tree_addr[8] = {0}; + uint32_t wots_pk_addr[8] = {0}; + + if (siglen != SPX_BYTES) { + return -1; + } + + memcpy(ctx.pub_seed, pk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); + + /* Derive the message digest and leaf index from R || PK || M. */ + /* The additional SPX_N is a result of the hash domain separator. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; + + /* Layer correctly defaults to 0, so no need to set_layer_addr */ + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); + + fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + /* For each subtree.. */ + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + copy_keypair_addr(wots_pk_addr, wots_addr); + + /* The WOTS public key is only correct if the signature was correct. */ + /* Initially, root is the FORS pk, but on subsequent iterations it is + the root of the subtree below the currently processed subtree. */ + wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); + sig += SPX_WOTS_BYTES; + + /* Compute the leaf node using the WOTS public key. */ + thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); + + /* Compute the root node of this subtree. */ + compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, + &ctx, tree_addr); + sig += SPX_TREE_HEIGHT * SPX_N; + + /* Update the indices for the next layer. */ + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; + } + + // cleanup + free_hash_function(&ctx); + + /* Check if the root node equals the root node in the public key. */ + if (memcmp(root, pub_root, SPX_N) != 0) { + return -1; + } + + return 0; +} + + +/** + * Returns an array containing the signature followed by the message. + */ +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk) { + size_t siglen; + + crypto_sign_signature(sm, &siglen, m, mlen, sk); + + memmove(sm + SPX_BYTES, m, mlen); + *smlen = siglen + mlen; + + return 0; +} + +/** + * Verifies a given signature-message pair under a given public key. + */ +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk) { + /* The API caller does not necessarily know what size a signature should be + but SPHINCS+ signatures are always exactly SPX_BYTES. */ + if (smlen < SPX_BYTES) { + memset(m, 0, smlen); + *mlen = 0; + return -1; + } + + *mlen = smlen - SPX_BYTES; + + if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { + memset(m, 0, smlen); + *mlen = 0; + return -1; + } + + /* If verification was successful, move the message to the right place. */ + memmove(m, sm + SPX_BYTES, *mlen); + + return 0; +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/thash.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/thash.h new file mode 100644 index 0000000000..8687ccfb4d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/thash.h @@ -0,0 +1,13 @@ +#ifndef SPX_THASH_H +#define SPX_THASH_H + +#include "context.h" +#include "params.h" + +#include + +#define thash SPX_NAMESPACE(thash) +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/thash_shake_simple.c b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/thash_shake_simple.c new file mode 100644 index 0000000000..98470395e9 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/thash_shake_simple.c @@ -0,0 +1,24 @@ +#include +#include + +#include "thash.h" + +#include "address.h" +#include "params.h" +#include "utils.h" + +#include "fips202.h" + +/** + * Takes an array of inblocks concatenated arrays of SPX_N bytes. + */ +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]) { + PQCLEAN_VLA(uint8_t, buf, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); + + memcpy(buf, ctx->pub_seed, SPX_N); + memcpy(buf + SPX_N, addr, SPX_ADDR_BYTES); + memcpy(buf + SPX_N + SPX_ADDR_BYTES, in, inblocks * SPX_N); + + shake256(out, SPX_N, buf, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/thash_shake_simplex4.c b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/thash_shake_simplex4.c new file mode 100644 index 0000000000..89dc9a4224 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/thash_shake_simplex4.c @@ -0,0 +1,98 @@ +#include +#include + +#include "thashx4.h" + +#include "address.h" +#include "params.h" +#include "utils.h" + +#include "fips202x4.h" + +extern void KeccakP1600times4_PermuteAll_24rounds(__m256i *s); + +/** + * 4-way parallel version of thash; takes 4x as much input and output + */ +void thashx4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addrx4[4 * 8]) { + if (inblocks == 1 || inblocks == 2) { + /* As we write and read only a few quadwords, it is more efficient to + * build and extract from the fourway SHAKE256 state by hand. */ + __m256i state[25]; + for (int i = 0; i < SPX_N / 8; i++) { + state[i] = _mm256_set1_epi64x(((int64_t *)ctx->pub_seed)[i]); + } + for (int i = 0; i < 4; i++) { + state[SPX_N / 8 + i] = _mm256_set_epi32( + (int)addrx4[3 * 8 + 1 + 2 * i], + (int)addrx4[3 * 8 + 2 * i], + (int)addrx4[2 * 8 + 1 + 2 * i], + (int)addrx4[2 * 8 + 2 * i], + (int)addrx4[8 + 1 + 2 * i], + (int)addrx4[8 + 2 * i], + (int)addrx4[1 + 2 * i], + (int)addrx4[2 * i] + ); + } + + for (unsigned int i = 0; i < (SPX_N / 8) * inblocks; i++) { + state[SPX_N / 8 + 4 + i] = _mm256_set_epi64x( + ((int64_t *)in3)[i], + ((int64_t *)in2)[i], + ((int64_t *)in1)[i], + ((int64_t *)in0)[i] + ); + } + + /* Domain separator and padding. */ + for (size_t i = (SPX_N / 8) * (1 + inblocks) + 4; i < 16; i++) { + state[i] = _mm256_set1_epi64x(0); + } + state[16] = _mm256_set1_epi64x((long long)(0x80ULL << 56)); + state[(SPX_N / 8) * (1 + inblocks) + 4] = _mm256_xor_si256( + state[(SPX_N / 8) * (1 + inblocks) + 4], + _mm256_set1_epi64x(0x1f) + ); + for (int i = 17; i < 25; i++) { + state[i] = _mm256_set1_epi64x(0); + } + + KeccakP1600times4_PermuteAll_24rounds(&state[0]); + + for (int i = 0; i < SPX_N / 8; i++) { + ((int64_t *)out0)[i] = _mm256_extract_epi64(state[i], 0); + ((int64_t *)out1)[i] = _mm256_extract_epi64(state[i], 1); + ((int64_t *)out2)[i] = _mm256_extract_epi64(state[i], 2); + ((int64_t *)out3)[i] = _mm256_extract_epi64(state[i], 3); + } + } else { + PQCLEAN_VLA(unsigned char, buf0, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, buf1, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, buf2, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); + PQCLEAN_VLA(unsigned char, buf3, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); + + memcpy(buf0, ctx->pub_seed, SPX_N); + memcpy(buf1, ctx->pub_seed, SPX_N); + memcpy(buf2, ctx->pub_seed, SPX_N); + memcpy(buf3, ctx->pub_seed, SPX_N); + memcpy(buf0 + SPX_N, addrx4 + 0 * 8, SPX_ADDR_BYTES); + memcpy(buf1 + SPX_N, addrx4 + 1 * 8, SPX_ADDR_BYTES); + memcpy(buf2 + SPX_N, addrx4 + 2 * 8, SPX_ADDR_BYTES); + memcpy(buf3 + SPX_N, addrx4 + 3 * 8, SPX_ADDR_BYTES); + memcpy(buf0 + SPX_N + SPX_ADDR_BYTES, in0, inblocks * SPX_N); + memcpy(buf1 + SPX_N + SPX_ADDR_BYTES, in1, inblocks * SPX_N); + memcpy(buf2 + SPX_N + SPX_ADDR_BYTES, in2, inblocks * SPX_N); + memcpy(buf3 + SPX_N + SPX_ADDR_BYTES, in3, inblocks * SPX_N); + + shake256x4(out0, out1, out2, out3, SPX_N, + buf0, buf1, buf2, buf3, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/thashx4.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/thashx4.h new file mode 100644 index 0000000000..64798a3727 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/thashx4.h @@ -0,0 +1,20 @@ +#ifndef SPX_THASHX4_H +#define SPX_THASHX4_H + +#include + +#include "context.h" +#include "params.h" + +#define thashx4 SPX_NAMESPACE(thashx4) +void thashx4(unsigned char *out0, + unsigned char *out1, + unsigned char *out2, + unsigned char *out3, + const unsigned char *in0, + const unsigned char *in1, + const unsigned char *in2, + const unsigned char *in3, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addrx4[4 * 8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/utils.c b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/utils.c new file mode 100644 index 0000000000..177b541fb9 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/utils.c @@ -0,0 +1,148 @@ +#include + +#include "utils.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "thash.h" + +/** + * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. + */ +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in) { + int i; + + /* Iterate over out in decreasing order, for big-endianness. */ + for (i = (signed int)outlen - 1; i >= 0; i--) { + out[i] = in & 0xff; + in = in >> 8; + } +} + +void u32_to_bytes(unsigned char *out, uint32_t in) { + out[0] = (unsigned char)(in >> 24); + out[1] = (unsigned char)(in >> 16); + out[2] = (unsigned char)(in >> 8); + out[3] = (unsigned char)in; +} + +/** + * Converts the inlen bytes in 'in' from big-endian byte order to an integer. + */ +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { + unsigned long long retval = 0; + unsigned int i; + + for (i = 0; i < inlen; i++) { + retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); + } + return retval; +} + +/** + * Computes a root node given a leaf and an auth path. + * Expects address to be complete other than the tree_height and tree_index. + */ +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]) { + uint32_t i; + unsigned char buffer[2 * SPX_N]; + + /* If leaf_idx is odd (last bit = 1), current path element is a right child + and auth_path has to go left. Otherwise it is the other way around. */ + if (leaf_idx & 1) { + memcpy(buffer + SPX_N, leaf, SPX_N); + memcpy(buffer, auth_path, SPX_N); + } else { + memcpy(buffer, leaf, SPX_N); + memcpy(buffer + SPX_N, auth_path, SPX_N); + } + auth_path += SPX_N; + + for (i = 0; i < tree_height - 1; i++) { + leaf_idx >>= 1; + idx_offset >>= 1; + /* Set the address of the node we're creating. */ + set_tree_height(addr, i + 1); + set_tree_index(addr, leaf_idx + idx_offset); + + /* Pick the right or left neighbor, depending on parity of the node. */ + if (leaf_idx & 1) { + thash(buffer + SPX_N, buffer, 2, ctx, addr); + memcpy(buffer, auth_path, SPX_N); + } else { + thash(buffer, buffer, 2, ctx, addr); + memcpy(buffer + SPX_N, auth_path, SPX_N); + } + auth_path += SPX_N; + } + + /* The last iteration is exceptional; we do not copy an auth_path node. */ + leaf_idx >>= 1; + idx_offset >>= 1; + set_tree_height(addr, tree_height); + set_tree_index(addr, leaf_idx + idx_offset); + thash(root, buffer, 2, ctx, addr); +} + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx * /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]) { + PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); + PQCLEAN_VLA(unsigned int, heights, tree_height + 1); + unsigned int offset = 0; + uint32_t idx; + uint32_t tree_idx; + + for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { + /* Add the next leaf node to the stack. */ + gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); + offset++; + heights[offset - 1] = 0; + + /* If this is a node we need for the auth path.. */ + if ((leaf_idx ^ 0x1) == idx) { + memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); + } + + /* While the top-most nodes are of equal height.. */ + while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { + /* Compute index of the new node, in the next layer. */ + tree_idx = (idx >> (heights[offset - 1] + 1)); + + /* Set the address of the node we're creating. */ + set_tree_height(tree_addr, heights[offset - 1] + 1); + set_tree_index(tree_addr, + tree_idx + (idx_offset >> (heights[offset - 1] + 1))); + /* Hash the top-most nodes from the stack together. */ + thash(stack + (offset - 2)*SPX_N, + stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); + offset--; + /* Note that the top-most node is now one layer higher. */ + heights[offset - 1]++; + + /* If this is a node we need for the auth path.. */ + if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { + memcpy(auth_path + heights[offset - 1]*SPX_N, + stack + (offset - 1)*SPX_N, SPX_N); + } + } + } + memcpy(root, stack, SPX_N); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/utils.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/utils.h new file mode 100644 index 0000000000..64f5d5a53a --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/utils.h @@ -0,0 +1,58 @@ +#ifndef SPX_UTILS_H +#define SPX_UTILS_H + +#include + +#include "compat.h" +#include "context.h" +#include "params.h" + + +/* To support MSVC use alloca() instead of VLAs. See #20. */ + + +/** + * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. + */ +#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in); +#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) +void u32_to_bytes(unsigned char *out, uint32_t in); + +/** + * Converts the inlen bytes in 'in' from big-endian byte order to an integer. + */ +#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); + +/** + * Computes a root node given a leaf and an auth path. + * Expects address to be complete other than the tree_height and tree_index. + */ +#define compute_root SPX_NAMESPACE(compute_root) +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]); + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +#define treehash SPX_NAMESPACE(treehash) +void treehash(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx *ctx /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]); + + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/utilsx4.c b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/utilsx4.c new file mode 100644 index 0000000000..1638677194 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/utilsx4.c @@ -0,0 +1,138 @@ +#include + +#include "utilsx4.h" + +#include "address.h" +#include "params.h" +#include "thashx4.h" +#include "utils.h" + +/* + * Generate the entire Merkle tree, computing the authentication path for leaf_idx, + * and the resulting root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) + * + * This expects tree_addrx4 to be initialized to 4 parallel addr structures for + * the Merkle tree nodes + * + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + * + * This works by using the standard Merkle tree building algorithm, except + * that each 'node' tracked is actually 4 consecutive nodes in the real tree. + * When we combine two logical nodes ABCD and WXYZ, we perform the H + * operation on adjacent real nodes, forming the parent logical node + * (AB)(CD)(WX)(YZ) + * + * When we get to the top two levels of the real tree (where there is only + * one logical node), we continue this operation two more times; the right + * most real node will by the actual root (and the other 3 nodes will be + * garbage). We follow the same thashx4 logic so that the 'extract + * authentication path components' part of the loop is still executed (and + * to simplify the code somewhat) + * + * This currently assumes tree_height >= 2; I suspect that doing an adjusting + * idx, addr_idx on the gen_leafx4 call if tree_height < 2 would fix it; since + * we don't actually use such short trees, I haven't bothered + */ +void treehashx4(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, + uint32_t tree_height, + void (*gen_leafx4)( + unsigned char * /* Where to write the leaves */, + const spx_ctx *, + uint32_t idx, void *info), + uint32_t tree_addrx4[4 * 8], + void *info) { + /* This is where we keep the intermediate nodes */ + PQCLEAN_VLA(unsigned char, stackx4, tree_height * 4 * SPX_N); + uint32_t left_adj = 0, prev_left_adj = 0; /* When we're doing the top 3 */ + /* levels, the left-most part of the tree isn't at the beginning */ + /* of current[]. These give the offset of the actual start */ + + uint32_t idx; + uint32_t max_idx = (1U << (tree_height - 2)) - 1; + for (idx = 0;; idx++) { + unsigned char current[4 * SPX_N]; /* Current logical node */ + gen_leafx4( current, ctx, 4 * idx + idx_offset, + info ); + + /* Now combine the freshly generated right node with previously */ + /* generated left ones */ + uint32_t internal_idx_offset = idx_offset; + uint32_t internal_idx = idx; + uint32_t internal_leaf = leaf_idx; + uint32_t h; /* The height we are in the Merkle tree */ + for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { + + /* Special processing if we're at the top of the tree */ + if (h >= tree_height - 2) { + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[3 * SPX_N], SPX_N ); + return; + } + /* The tree indexing logic is a bit off in this case */ + /* Adjust it so that the left-most node of the part of */ + /* the tree that we're processing has index 0 */ + prev_left_adj = left_adj; + left_adj = 4U - (1 << (tree_height - h - 1)); + } + + /* Check if we hit the top of the tree */ + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[3 * SPX_N], SPX_N ); + return; + } + + /* + * Check if one of the nodes we have is a part of the + * authentication path; if it is, write it out + */ + if ((((internal_idx << 2) ^ internal_leaf) & ~0x3U) == 0) { + memcpy( &auth_path[ h * SPX_N ], + ¤t[(((internal_leaf & 3) ^ 1) + prev_left_adj) * SPX_N], + SPX_N ); + } + + /* + * Check if we're at a left child; if so, stop going up the stack + * Exception: if we've reached the end of the tree, keep on going + * (so we combine the last 4 nodes into the one root node in two + * more iterations) + */ + if ((internal_idx & 1) == 0 && idx < max_idx) { + break; + } + + /* Ok, we're at a right node (or doing the top 3 levels) */ + /* Now combine the left and right logical nodes together */ + + /* Set the address of the node we're creating. */ + unsigned int j; + internal_idx_offset >>= 1; + for (j = 0; j < 4; j++) { + set_tree_height(tree_addrx4 + j * 8, h + 1); + set_tree_index(tree_addrx4 + j * 8, + (4 / 2) * (internal_idx & ~1U) + j - left_adj + internal_idx_offset ); + } + unsigned char *left = &stackx4[h * 4 * SPX_N]; + thashx4( ¤t[0 * SPX_N], + ¤t[1 * SPX_N], + ¤t[2 * SPX_N], + ¤t[3 * SPX_N], + &left [0 * SPX_N], + &left [2 * SPX_N], + ¤t[0 * SPX_N], + ¤t[2 * SPX_N], + 2, ctx, tree_addrx4); + } + + /* We've hit a left child; save the current for when we get the */ + /* corresponding right right */ + memcpy( &stackx4[h * 4 * SPX_N], current, 4 * SPX_N); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/utilsx4.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/utilsx4.h new file mode 100644 index 0000000000..facb874b18 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/utilsx4.h @@ -0,0 +1,30 @@ +#ifndef SPX_UTILSX4_H +#define SPX_UTILSX4_H + +#include + +#include "context.h" +#include "params.h" + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + * + * This implementation uses AVX to compute internal nodes 4 at a time (in + * parallel) + */ +#define treehashx4 SPX_NAMESPACE(treehashx4) +void treehashx4(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leafx4)( + unsigned char * /* Where to write the leaves */, + const spx_ctx * /* ctx */, + uint32_t addr_idx, void *info), + uint32_t tree_addrx4[4 * 8], void *info); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/wots.c b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/wots.c new file mode 100644 index 0000000000..4d5041ce05 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/wots.c @@ -0,0 +1,269 @@ +#include +#include + +#include "wots.h" + +#include "address.h" +#include "hash.h" +#include "hashx4.h" +#include "params.h" +#include "thash.h" +#include "thashx4.h" +#include "utils.h" +#include "utilsx4.h" +#include "wotsx4.h" + +// TODO clarify address expectations, and make them more uniform. +// TODO i.e. do we expect types to be set already? +// TODO and do we expect modifications or copies? + +/** + * Computes up the chains + */ +static void gen_chains( + unsigned char *out, + const unsigned char *in, + unsigned int start[SPX_WOTS_LEN], + const unsigned int steps[SPX_WOTS_LEN], + const spx_ctx *ctx, + uint32_t addr[8]) { + uint32_t i, j, k, idx, watching; + int done; + unsigned char empty[SPX_N]; + unsigned char *bufs[4]; + uint32_t addrs[8 * 4]; + + int l; + uint16_t counts[SPX_WOTS_W] = { 0 }; + uint16_t idxs[SPX_WOTS_LEN]; + uint16_t total, newTotal; + + /* set addrs = {addr, addr, addr, addr} */ + for (j = 0; j < 4; j++) { + memcpy(addrs + j * 8, addr, sizeof(uint32_t) * 8); + } + + /* Initialize out with the value at position 'start'. */ + memcpy(out, in, SPX_WOTS_LEN * SPX_N); + + /* Sort the chains in reverse order by steps using counting sort. */ + for (i = 0; i < SPX_WOTS_LEN; i++) { + counts[steps[i]]++; + } + total = 0; + for (l = SPX_WOTS_W - 1; l >= 0; l--) { + newTotal = counts[l] + total; + counts[l] = total; + total = newTotal; + } + for (i = 0; i < SPX_WOTS_LEN; i++) { + idxs[counts[steps[i]]] = (uint16_t)i; + counts[steps[i]]++; + } + + /* We got our work cut out for us: do it! */ + for (i = 0; i < SPX_WOTS_LEN; i += 4) { + for (j = 0; j < 4 && i + j < SPX_WOTS_LEN; j++) { + idx = idxs[i + j]; + set_chain_addr(addrs + j * 8, idx); + bufs[j] = out + SPX_N * idx; + } + + /* As the chains are sorted in reverse order, we know that the first + * chain is the longest and the last one is the shortest. We keep + * an eye on whether the last chain is done and then on the one before, + * et cetera. */ + watching = 3; + done = 0; + while (i + watching >= SPX_WOTS_LEN) { + bufs[watching] = &empty[0]; + watching--; + } + + for (k = 0;; k++) { + while (k == steps[idxs[i + watching]]) { + bufs[watching] = &empty[0]; + if (watching == 0) { + done = 1; + break; + } + watching--; + } + if (done) { + break; + } + for (j = 0; j < watching + 1; j++) { + set_hash_addr(addrs + j * 8, k + start[idxs[i + j]]); + } + + thashx4(bufs[0], bufs[1], bufs[2], bufs[3], + bufs[0], bufs[1], bufs[2], bufs[3], 1, ctx, addrs); + } + } +} + +/** + * base_w algorithm as described in draft. + * Interprets an array of bytes as integers in base w. + * This only works when log_w is a divisor of 8. + */ +static void base_w(unsigned int *output, const int out_len, + const unsigned char *input) { + int in = 0; + int out = 0; + unsigned char total = 0; + int bits = 0; + int consumed; + + for (consumed = 0; consumed < out_len; consumed++) { + if (bits == 0) { + total = input[in]; + in++; + bits += 8; + } + bits -= SPX_WOTS_LOGW; + output[out] = (total >> bits) & (SPX_WOTS_W - 1); + out++; + } +} + +/* Computes the WOTS+ checksum over a message (in base_w). */ +static void wots_checksum(unsigned int *csum_base_w, + const unsigned int *msg_base_w) { + unsigned int csum = 0; + unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; + unsigned int i; + + /* Compute checksum. */ + for (i = 0; i < SPX_WOTS_LEN1; i++) { + csum += SPX_WOTS_W - 1 - msg_base_w[i]; + } + + /* Convert checksum to base_w. */ + /* Make sure expected empty zero bits are the least significant bits. */ + csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); + ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); + base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); +} + +/* Takes a message and derives the matching chain lengths. */ +void chain_lengths(unsigned int *lengths, const unsigned char *msg) { + base_w(lengths, SPX_WOTS_LEN1, msg); + wots_checksum(lengths + SPX_WOTS_LEN1, lengths); +} + +/** + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. + * + * Writes the computed public key to 'pk'. + */ +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]) { + unsigned int steps[SPX_WOTS_LEN]; + unsigned int start[SPX_WOTS_LEN]; + uint32_t i; + + chain_lengths(start, msg); + + for (i = 0; i < SPX_WOTS_LEN; i++) { + steps[i] = SPX_WOTS_W - 1 - start[i]; + } + + gen_chains(pk, sig, start, steps, ctx, addr); +} + +/* + * This generates 4 sequential WOTS public keys + * It also generates the WOTS signature if leaf_info indicates + * that we're signing with one of these WOTS keys + */ +void wots_gen_leafx4(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info) { + struct leaf_info_x4 *info = v_info; + uint32_t *leaf_addr = info->leaf_addr; + uint32_t *pk_addr = info->pk_addr; + unsigned int i, j, k; + unsigned char pk_buffer[ 4 * SPX_WOTS_BYTES ]; + unsigned wots_offset = SPX_WOTS_BYTES; + unsigned char *buffer; + uint32_t wots_k_mask; + unsigned wots_sign_index; + + if (((leaf_idx ^ info->wots_sign_leaf) & ~3U) == 0) { + /* We're traversing the leaf that's signing; generate the WOTS */ + /* signature */ + wots_k_mask = 0; + wots_sign_index = info->wots_sign_leaf & 3; /* Which of of the 4 */ + /* 4 slots do the signatures come from */ + } else { + /* Nope, we're just generating pk's; turn off the signature logic */ + wots_k_mask = (uint32_t)~0; + wots_sign_index = 0; + } + + for (j = 0; j < 4; j++) { + set_keypair_addr( leaf_addr + j * 8, leaf_idx + j ); + set_keypair_addr( pk_addr + j * 8, leaf_idx + j ); + } + + for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { + uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k to */ + /* the step if we're generating a signature, ~0 if we're not */ + + /* Start with the secret seed */ + for (j = 0; j < 4; j++) { + set_chain_addr(leaf_addr + j * 8, i); + set_hash_addr(leaf_addr + j * 8, 0); + set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTSPRF); + } + prf_addrx4(buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + buffer + 2 * wots_offset, + buffer + 3 * wots_offset, + ctx, leaf_addr); + + for (j = 0; j < 4; j++) { + set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTS); + } + + /* Iterate down the WOTS chain */ + for (k = 0;; k++) { + /* Check if one of the values we have needs to be saved as a */ + /* part of the WOTS signature */ + if (k == wots_k) { + memcpy( info->wots_sig + i * SPX_N, + buffer + wots_sign_index * wots_offset, SPX_N ); + } + + /* Check if we hit the top of the chain */ + if (k == SPX_WOTS_W - 1) { + break; + } + + /* Iterate one step on all 4 chains */ + for (j = 0; j < 4; j++) { + set_hash_addr(leaf_addr + j * 8, k); + } + thashx4(buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + buffer + 2 * wots_offset, + buffer + 3 * wots_offset, + buffer + 0 * wots_offset, + buffer + 1 * wots_offset, + buffer + 2 * wots_offset, + buffer + 3 * wots_offset, 1, ctx, leaf_addr); + } + } + + /* Do the final thash to generate the public keys */ + thashx4(dest + 0 * SPX_N, + dest + 1 * SPX_N, + dest + 2 * SPX_N, + dest + 3 * SPX_N, + pk_buffer + 0 * wots_offset, + pk_buffer + 1 * wots_offset, + pk_buffer + 2 * wots_offset, + pk_buffer + 3 * wots_offset, SPX_WOTS_LEN, ctx, pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/wots.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/wots.h new file mode 100644 index 0000000000..4e7692eeef --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/wots.h @@ -0,0 +1,25 @@ +#ifndef SPX_WOTS_H +#define SPX_WOTS_H + +#include + +#include "context.h" +#include "params.h" + +/** + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. + * + * Writes the computed public key to 'pk'. + */ +#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]); + +/* + * Compute the chain lengths needed for a given message hash + */ +#define chain_lengths SPX_NAMESPACE(chain_lengths) +void chain_lengths(unsigned int *lengths, const unsigned char *msg); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/wotsx4.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/wotsx4.h new file mode 100644 index 0000000000..cd634f1743 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/wotsx4.h @@ -0,0 +1,41 @@ +#ifndef WOTSX4_H_ +#define WOTSX4_H_ + +#include + +#include "params.h" + +/* + * This is here to provide an interface to the internal wots_gen_leafx4 + * routine. While this routine is not referenced in the package outside of + * wots.c, it is called from the stand-alone benchmark code to characterize + * the performance + */ +struct leaf_info_x4 { + unsigned char *wots_sig; + uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ + uint32_t *wots_steps; + uint32_t leaf_addr[4 * 8]; + uint32_t pk_addr[4 * 8]; +}; + +/* Macro to set the leaf_info to something 'benign', that is, it would */ +/* run with the same time as it does during the real signing process */ +/* Used only by the benchmark code */ +#define INITIALIZE_LEAF_INFO_X4(info, addr, step_buffer) { \ + (info).wots_sig = 0; \ + (info).wots_sign_leaf = ~0; \ + (info).wots_steps = step_buffer; \ + int i; \ + for (i=0; i<4; i++) { \ + memcpy( &(info).leaf_addr[8*i], addr, 32 ); \ + memcpy( &(info).pk_addr[8*i], addr, 32 ); \ + } \ + } + +#define wots_gen_leafx4 SPX_NAMESPACE(wots_gen_leafx4) +void wots_gen_leafx4(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info); + +#endif /* WOTSX4_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_clean/LICENSE b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_clean/LICENSE new file mode 100644 index 0000000000..670154e353 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_clean/LICENSE @@ -0,0 +1,116 @@ +CC0 1.0 Universal + +Statement of Purpose + +The laws of most jurisdictions throughout the world automatically confer +exclusive Copyright and Related Rights (defined below) upon the creator and +subsequent owner(s) (each and all, an "owner") of an original work of +authorship and/or a database (each, a "Work"). + +Certain owners wish to permanently relinquish those rights to a Work for the +purpose of contributing to a commons of creative, cultural and scientific +works ("Commons") that the public can reliably and without fear of later +claims of infringement build upon, modify, incorporate in other works, reuse +and redistribute as freely as possible in any form whatsoever and for any +purposes, including without limitation commercial purposes. These owners may +contribute to the Commons to promote the ideal of a free culture and the +further production of creative, cultural and scientific works, or to gain +reputation or greater distribution for their Work in part through the use and +efforts of others. + +For these and/or other purposes and motivations, and without any expectation +of additional consideration or compensation, the person associating CC0 with a +Work (the "Affirmer"), to the extent that he or she is an owner of Copyright +and Related Rights in the Work, voluntarily elects to apply CC0 to the Work +and publicly distribute the Work under its terms, with knowledge of his or her +Copyright and Related Rights in the Work and the meaning and intended legal +effect of CC0 on those rights. + +1. Copyright and Related Rights. A Work made available under CC0 may be +protected by copyright and related or neighboring rights ("Copyright and +Related Rights"). Copyright and Related Rights include, but are not limited +to, the following: + + i. the right to reproduce, adapt, distribute, perform, display, communicate, + and translate a Work; + + ii. moral rights retained by the original author(s) and/or performer(s); + + iii. publicity and privacy rights pertaining to a person's image or likeness + depicted in a Work; + + iv. rights protecting against unfair competition in regards to a Work, + subject to the limitations in paragraph 4(a), below; + + v. rights protecting the extraction, dissemination, use and reuse of data in + a Work; + + vi. database rights (such as those arising under Directive 96/9/EC of the + European Parliament and of the Council of 11 March 1996 on the legal + protection of databases, and under any national implementation thereof, + including any amended or successor version of such directive); and + + vii. other similar, equivalent or corresponding rights throughout the world + based on applicable law or treaty, and any national implementations thereof. + +2. Waiver. To the greatest extent permitted by, but not in contravention of, +applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and +unconditionally waives, abandons, and surrenders all of Affirmer's Copyright +and Related Rights and associated claims and causes of action, whether now +known or unknown (including existing as well as future claims and causes of +action), in the Work (i) in all territories worldwide, (ii) for the maximum +duration provided by applicable law or treaty (including future time +extensions), (iii) in any current or future medium and for any number of +copies, and (iv) for any purpose whatsoever, including without limitation +commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes +the Waiver for the benefit of each member of the public at large and to the +detriment of Affirmer's heirs and successors, fully intending that such Waiver +shall not be subject to revocation, rescission, cancellation, termination, or +any other legal or equitable action to disrupt the quiet enjoyment of the Work +by the public as contemplated by Affirmer's express Statement of Purpose. + +3. Public License Fallback. Should any part of the Waiver for any reason be +judged legally invalid or ineffective under applicable law, then the Waiver +shall be preserved to the maximum extent permitted taking into account +Affirmer's express Statement of Purpose. In addition, to the extent the Waiver +is so judged Affirmer hereby grants to each affected person a royalty-free, +non transferable, non sublicensable, non exclusive, irrevocable and +unconditional license to exercise Affirmer's Copyright and Related Rights in +the Work (i) in all territories worldwide, (ii) for the maximum duration +provided by applicable law or treaty (including future time extensions), (iii) +in any current or future medium and for any number of copies, and (iv) for any +purpose whatsoever, including without limitation commercial, advertising or +promotional purposes (the "License"). The License shall be deemed effective as +of the date CC0 was applied by Affirmer to the Work. Should any part of the +License for any reason be judged legally invalid or ineffective under +applicable law, such partial invalidity or ineffectiveness shall not +invalidate the remainder of the License, and in such case Affirmer hereby +affirms that he or she will not (i) exercise any of his or her remaining +Copyright and Related Rights in the Work or (ii) assert any associated claims +and causes of action with respect to the Work, in either case contrary to +Affirmer's express Statement of Purpose. + +4. Limitations and Disclaimers. + + a. No trademark or patent rights held by Affirmer are waived, abandoned, + surrendered, licensed or otherwise affected by this document. + + b. Affirmer offers the Work as-is and makes no representations or warranties + of any kind concerning the Work, express, implied, statutory or otherwise, + including without limitation warranties of title, merchantability, fitness + for a particular purpose, non infringement, or the absence of latent or + other defects, accuracy, or the present or absence of errors, whether or not + discoverable, all to the greatest extent permissible under applicable law. + + c. Affirmer disclaims responsibility for clearing rights of other persons + that may apply to the Work or any use thereof, including without limitation + any person's Copyright and Related Rights in the Work. Further, Affirmer + disclaims responsibility for obtaining any necessary consents, permissions + or other rights required for any use of the Work. + + d. Affirmer understands and acknowledges that Creative Commons is not a + party to this document and has no duty or obligation with respect to this + CC0 or use of the Work. + +For more information, please see + diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_clean/address.c b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_clean/address.c new file mode 100644 index 0000000000..b956e9cb29 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_clean/address.c @@ -0,0 +1,91 @@ +#include +#include + +#include "address.h" +#include "params.h" +#include "utils.h" + +/* + * Specify which level of Merkle tree (the "layer") we're working on + */ +void set_layer_addr(uint32_t addr[8], uint32_t layer) { + ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; +} + +/* + * Specify which Merkle tree within the level (the "tree address") we're working on + */ +void set_tree_addr(uint32_t addr[8], uint64_t tree) { + ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); +} + +/* + * Specify the reason we'll use this address structure for, that is, what + * hash will we compute with it. This is used so that unrelated types of + * hashes don't accidentally get the same address structure. The type will be + * one of the SPX_ADDR_TYPE constants + */ +void set_type(uint32_t addr[8], uint32_t type) { + ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; +} + +/* + * Copy the layer and tree fields of the address structure. This is used + * when we're doing multiple types of hashes within the same Merkle tree + */ +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); +} + +/* These functions are used for OTS addresses. */ + +/* + * Specify which Merkle leaf we're working on; that is, which OTS keypair + * we're talking about. + */ +void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { + ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; +} + +/* + * Copy the layer, tree and keypair fields of the address structure. This is + * used when we're doing multiple things within the same OTS keypair + */ +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { + memcpy( out, in, SPX_OFFSET_TREE + 8 ); + ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; +} + +/* + * Specify which Merkle chain within the OTS we're working with + * (the chain address) + */ +void set_chain_addr(uint32_t addr[8], uint32_t chain) { + ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; +} + +/* + * Specify where in the Merkle chain we are +* (the hash address) + */ +void set_hash_addr(uint32_t addr[8], uint32_t hash) { + ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; +} + +/* These functions are used for all hash tree addresses (including FORS). */ + +/* + * Specify the height of the node in the Merkle/FORS tree we are in + * (the tree height) + */ +void set_tree_height(uint32_t addr[8], uint32_t tree_height) { + ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; +} + +/* + * Specify the distance from the left edge of the node in the Merkle/FORS tree + * (the tree index) + */ +void set_tree_index(uint32_t addr[8], uint32_t tree_index) { + u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_clean/address.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_clean/address.h new file mode 100644 index 0000000000..24a84eb40c --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_clean/address.h @@ -0,0 +1,52 @@ +#ifndef SPX_ADDRESS_H +#define SPX_ADDRESS_H + +#include + +#include "params.h" + +/* The hash types that are passed to set_type */ +#define SPX_ADDR_TYPE_WOTS 0 +#define SPX_ADDR_TYPE_WOTSPK 1 +#define SPX_ADDR_TYPE_HASHTREE 2 +#define SPX_ADDR_TYPE_FORSTREE 3 +#define SPX_ADDR_TYPE_FORSPK 4 +#define SPX_ADDR_TYPE_WOTSPRF 5 +#define SPX_ADDR_TYPE_FORSPRF 6 + +#define set_layer_addr SPX_NAMESPACE(set_layer_addr) +void set_layer_addr(uint32_t addr[8], uint32_t layer); + +#define set_tree_addr SPX_NAMESPACE(set_tree_addr) +void set_tree_addr(uint32_t addr[8], uint64_t tree); + +#define set_type SPX_NAMESPACE(set_type) +void set_type(uint32_t addr[8], uint32_t type); + +/* Copies the layer and tree part of one address into the other */ +#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) +void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); + +/* These functions are used for WOTS and FORS addresses. */ + +#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) +void set_keypair_addr(uint32_t addr[8], uint32_t keypair); + +#define set_chain_addr SPX_NAMESPACE(set_chain_addr) +void set_chain_addr(uint32_t addr[8], uint32_t chain); + +#define set_hash_addr SPX_NAMESPACE(set_hash_addr) +void set_hash_addr(uint32_t addr[8], uint32_t hash); + +#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) +void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); + +/* These functions are used for all hash tree addresses (including FORS). */ + +#define set_tree_height SPX_NAMESPACE(set_tree_height) +void set_tree_height(uint32_t addr[8], uint32_t tree_height); + +#define set_tree_index SPX_NAMESPACE(set_tree_index) +void set_tree_index(uint32_t addr[8], uint32_t tree_index); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_clean/api.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_clean/api.h new file mode 100644 index 0000000000..bb9b9ca8a9 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_clean/api.h @@ -0,0 +1,77 @@ +#ifndef PQCLEAN_SPHINCSSHAKE256SSIMPLE_CLEAN_API_H +#define PQCLEAN_SPHINCSSHAKE256SSIMPLE_CLEAN_API_H + +#include +#include + +#define PQCLEAN_SPHINCSSHAKE256SSIMPLE_CLEAN_CRYPTO_ALGNAME "SPHINCS+-shake-256s-simple" + +#define PQCLEAN_SPHINCSSHAKE256SSIMPLE_CLEAN_CRYPTO_SECRETKEYBYTES 128 +#define PQCLEAN_SPHINCSSHAKE256SSIMPLE_CLEAN_CRYPTO_PUBLICKEYBYTES 64 +#define PQCLEAN_SPHINCSSHAKE256SSIMPLE_CLEAN_CRYPTO_BYTES 29792 + +#define PQCLEAN_SPHINCSSHAKE256SSIMPLE_CLEAN_CRYPTO_SEEDBYTES 96 + +/* + * Returns the length of a secret key, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE256SSIMPLE_CLEAN_crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE256SSIMPLE_CLEAN_crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE256SSIMPLE_CLEAN_crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +size_t PQCLEAN_SPHINCSSHAKE256SSIMPLE_CLEAN_crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +int PQCLEAN_SPHINCSSHAKE256SSIMPLE_CLEAN_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +int PQCLEAN_SPHINCSSHAKE256SSIMPLE_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +int PQCLEAN_SPHINCSSHAKE256SSIMPLE_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +int PQCLEAN_SPHINCSSHAKE256SSIMPLE_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, + const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +int PQCLEAN_SPHINCSSHAKE256SSIMPLE_CLEAN_crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +int PQCLEAN_SPHINCSSHAKE256SSIMPLE_CLEAN_crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_clean/context.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_clean/context.h new file mode 100644 index 0000000000..9f8a40ab4e --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_clean/context.h @@ -0,0 +1,22 @@ +#ifndef SPX_CONTEXT_H +#define SPX_CONTEXT_H + +#include +#include + +#include "params.h" + +typedef struct { + uint8_t pub_seed[SPX_N]; + uint8_t sk_seed[SPX_N]; + + +} spx_ctx; + +#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) +void initialize_hash_function(spx_ctx *ctx); + +#define free_hash_function SPX_NAMESPACE(free_hash_function) +void free_hash_function(spx_ctx *ctx); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_clean/context_shake.c b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_clean/context_shake.c new file mode 100644 index 0000000000..9614a103d3 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_clean/context_shake.c @@ -0,0 +1,12 @@ +#include "context.h" + +/* For SHAKE256, there is no immediate reason to initialize at the start, + so this function is an empty operation. */ +void initialize_hash_function(spx_ctx *ctx) { + (void)ctx; /* Suppress an 'unused parameter' warning. */ +} + +// in case the hash function api is heap-based. +void free_hash_function(spx_ctx *ctx) { + (void)ctx; +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_clean/fors.c b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_clean/fors.c new file mode 100644 index 0000000000..96ca72e986 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_clean/fors.c @@ -0,0 +1,156 @@ +#include +#include +#include + +#include "fors.h" + +#include "address.h" +#include "hash.h" +#include "thash.h" +#include "utils.h" +#include "utilsx1.h" + +static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + prf_addr(sk, ctx, fors_leaf_addr); +} + +static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, + const spx_ctx *ctx, + uint32_t fors_leaf_addr[8]) { + thash(leaf, sk, 1, ctx, fors_leaf_addr); +} + +struct fors_gen_leaf_info { + uint32_t leaf_addrx[8]; +}; + +static void fors_gen_leafx1(unsigned char *leaf, + const spx_ctx *ctx, + uint32_t addr_idx, void *info) { + struct fors_gen_leaf_info *fors_info = info; + uint32_t *fors_leaf_addr = fors_info->leaf_addrx; + + /* Only set the parts that the caller doesn't set */ + set_tree_index(fors_leaf_addr, addr_idx); + set_type(fors_leaf_addr, SPX_ADDR_TYPE_FORSPRF); + fors_gen_sk(leaf, ctx, fors_leaf_addr); + + set_type(fors_leaf_addr, SPX_ADDR_TYPE_FORSTREE); + fors_sk_to_leaf(leaf, leaf, + ctx, fors_leaf_addr); +} + +/** + * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + * Assumes indices has space for SPX_FORS_TREES integers. + */ +static void message_to_indices(uint32_t *indices, const unsigned char *m) { + unsigned int i, j; + unsigned int offset = 0; + + for (i = 0; i < SPX_FORS_TREES; i++) { + indices[i] = 0; + for (j = 0; j < SPX_FORS_HEIGHT; j++) { + indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); + offset++; + } + } +} + +/** + * Signs a message m, deriving the secret key from sk_seed and the FTS address. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + uint32_t fors_tree_addr[8] = {0}; + struct fors_gen_leaf_info fors_info = {0}; + uint32_t *fors_leaf_addr = fors_info.leaf_addrx; + uint32_t fors_pk_addr[8] = {0}; + uint32_t idx_offset; + unsigned int i; + + copy_keypair_addr(fors_tree_addr, fors_addr); + copy_keypair_addr(fors_leaf_addr, fors_addr); + + copy_keypair_addr(fors_pk_addr, fors_addr); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); + + message_to_indices(indices, m); + + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); + + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); + + /* Include the secret key part that produces the selected leaf node. */ + fors_gen_sk(sig, ctx, fors_tree_addr); + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + sig += SPX_N; + + /* Compute the authentication path for this leaf node. */ + treehashx1(roots + i * SPX_N, sig, ctx, + indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx1, + fors_tree_addr, &fors_info); + + sig += SPX_N * SPX_FORS_HEIGHT; + } + + /* Hash horizontally across all tree roots to derive the public key. */ + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); +} + +/** + * Derives the FORS public key from a signature. + * This can be used for verification by comparing to a known public key, or to + * subsequently verify a signature on the derived public key. The latter is the + * typical use-case when used as an FTS below an OTS in a hypertree. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]) { + uint32_t indices[SPX_FORS_TREES]; + unsigned char roots[SPX_FORS_TREES * SPX_N]; + unsigned char leaf[SPX_N]; + uint32_t fors_tree_addr[8] = {0}; + uint32_t fors_pk_addr[8] = {0}; + uint32_t idx_offset; + unsigned int i; + + copy_keypair_addr(fors_tree_addr, fors_addr); + copy_keypair_addr(fors_pk_addr, fors_addr); + + set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); + set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); + + message_to_indices(indices, m); + + for (i = 0; i < SPX_FORS_TREES; i++) { + idx_offset = i * (1 << SPX_FORS_HEIGHT); + + set_tree_height(fors_tree_addr, 0); + set_tree_index(fors_tree_addr, indices[i] + idx_offset); + + /* Derive the leaf from the included secret key part. */ + fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); + sig += SPX_N; + + /* Derive the corresponding root node of this tree. */ + compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, + sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); + sig += SPX_N * SPX_FORS_HEIGHT; + } + + /* Hash horizontally across all tree roots to derive the public key. */ + thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_clean/fors.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_clean/fors.h new file mode 100644 index 0000000000..509140a178 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_clean/fors.h @@ -0,0 +1,32 @@ +#ifndef SPX_FORS_H +#define SPX_FORS_H + +#include + +#include "context.h" +#include "params.h" + +/** + * Signs a message m, deriving the secret key from sk_seed and the FTS address. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +#define fors_sign SPX_NAMESPACE(fors_sign) +void fors_sign(unsigned char *sig, unsigned char *pk, + const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); + +/** + * Derives the FORS public key from a signature. + * This can be used for verification by comparing to a known public key, or to + * subsequently verify a signature on the derived public key. The latter is the + * typical use-case when used as an FTS below an OTS in a hypertree. + * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. + */ +#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) +void fors_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *m, + const spx_ctx *ctx, + const uint32_t fors_addr[8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_clean/hash.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_clean/hash.h new file mode 100644 index 0000000000..f7c87d4c3c --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_clean/hash.h @@ -0,0 +1,28 @@ +#ifndef SPX_HASH_H +#define SPX_HASH_H + +#include +#include + +#include "context.h" +#include "params.h" + +#define prf_addr SPX_NAMESPACE(prf_addr) +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]); + +#define gen_message_random SPX_NAMESPACE(gen_message_random) +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); + +#define hash_message SPX_NAMESPACE(hash_message) +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx); + + + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_clean/hash_shake.c b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_clean/hash_shake.c new file mode 100644 index 0000000000..ff5e7ec918 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_clean/hash_shake.c @@ -0,0 +1,83 @@ +#include +#include + +#include "hash.h" + +#include "address.h" +#include "fips202.h" +#include "params.h" +#include "utils.h" + +/* + * Computes PRF(pk_seed, sk_seed, addr) + */ +void prf_addr(unsigned char *out, const spx_ctx *ctx, + const uint32_t addr[8]) { + unsigned char buf[2 * SPX_N + SPX_ADDR_BYTES]; + + memcpy(buf, ctx->pub_seed, SPX_N); + memcpy(buf + SPX_N, addr, SPX_ADDR_BYTES); + memcpy(buf + SPX_N + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); + + shake256(out, SPX_N, buf, 2 * SPX_N + SPX_ADDR_BYTES); +} + +/** + * Computes the message-dependent randomness R, using a secret seed and an + * optional randomization value as well as the message. + */ +void gen_message_random(unsigned char *R, const unsigned char *sk_prf, + const unsigned char *optrand, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { + (void)ctx; + shake256incctx s_inc; + + shake256_inc_init(&s_inc); + shake256_inc_absorb(&s_inc, sk_prf, SPX_N); + shake256_inc_absorb(&s_inc, optrand, SPX_N); + shake256_inc_absorb(&s_inc, m, mlen); + shake256_inc_finalize(&s_inc); + shake256_inc_squeeze(R, SPX_N, &s_inc); + shake256_inc_ctx_release(&s_inc); +} + +/** + * Computes the message hash using R, the public key, and the message. + * Outputs the message digest and the index of the leaf. The index is split in + * the tree index and the leaf index, for convenient copying to an address. + */ +void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, + const unsigned char *R, const unsigned char *pk, + const unsigned char *m, size_t mlen, + const spx_ctx *ctx) { + (void)ctx; +#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) +#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) +#define SPX_LEAF_BITS SPX_TREE_HEIGHT +#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) +#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) + + unsigned char buf[SPX_DGST_BYTES]; + unsigned char *bufp = buf; + shake256incctx s_inc; + + shake256_inc_init(&s_inc); + shake256_inc_absorb(&s_inc, R, SPX_N); + shake256_inc_absorb(&s_inc, pk, SPX_PK_BYTES); + shake256_inc_absorb(&s_inc, m, mlen); + shake256_inc_finalize(&s_inc); + shake256_inc_squeeze(buf, SPX_DGST_BYTES, &s_inc); + shake256_inc_ctx_release(&s_inc); + + memcpy(digest, bufp, SPX_FORS_MSG_BYTES); + bufp += SPX_FORS_MSG_BYTES; + + + *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); + *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); + bufp += SPX_TREE_BYTES; + + *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); + *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_clean/merkle.c b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_clean/merkle.c new file mode 100644 index 0000000000..0c1479fd93 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_clean/merkle.c @@ -0,0 +1,59 @@ +#include +#include + +#include "address.h" +#include "merkle.h" +#include "params.h" +#include "utils.h" +#include "utilsx1.h" +#include "wots.h" +#include "wotsx1.h" + +/* + * This generates a Merkle signature (WOTS signature followed by the Merkle + * authentication path). This is in this file because most of the complexity + * is involved with the WOTS signature; the Merkle authentication path logic + * is mostly hidden in treehashx4 + */ +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf) { + unsigned char *auth_path = sig + SPX_WOTS_BYTES; + struct leaf_info_x1 info = { 0 }; + unsigned steps[ SPX_WOTS_LEN ]; + + info.wots_sig = sig; + chain_lengths(steps, root); + info.wots_steps = steps; + + set_type(&tree_addr[0], SPX_ADDR_TYPE_HASHTREE); + set_type(&info.pk_addr[0], SPX_ADDR_TYPE_WOTSPK); + copy_subtree_addr(&info.leaf_addr[0], wots_addr); + copy_subtree_addr(&info.pk_addr[0], wots_addr); + + info.wots_sign_leaf = idx_leaf; + + treehashx1(root, auth_path, ctx, + idx_leaf, 0, + SPX_TREE_HEIGHT, + wots_gen_leafx1, + tree_addr, &info); +} + +/* Compute root node of the top-most subtree. */ +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { + /* We do not need the auth path in key generation, but it simplifies the + code to have just one treehash routine that computes both root and path + in one function. */ + unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; + uint32_t top_tree_addr[8] = {0}; + uint32_t wots_addr[8] = {0}; + + set_layer_addr(top_tree_addr, SPX_D - 1); + set_layer_addr(wots_addr, SPX_D - 1); + + merkle_sign(auth_path, root, ctx, + wots_addr, top_tree_addr, + (uint32_t)~0 /* ~0 means "don't bother generating an auth path */ ); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_clean/merkle.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_clean/merkle.h new file mode 100644 index 0000000000..769cf2e970 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_clean/merkle.h @@ -0,0 +1,21 @@ +#ifndef MERKLE_H_ +#define MERKLE_H_ + +#include + +#include "context.h" +#include "params.h" + +/* Generate a Merkle signature (WOTS signature followed by the Merkle */ +/* authentication path) */ +#define merkle_sign SPX_NAMESPACE(merkle_sign) +void merkle_sign(uint8_t *sig, unsigned char *root, + const spx_ctx *ctx, + uint32_t wots_addr[8], uint32_t tree_addr[8], + uint32_t idx_leaf); + +/* Compute the root node of the top-most subtree. */ +#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) +void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); + +#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_clean/nistapi.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_clean/nistapi.h new file mode 100644 index 0000000000..3cb71afad4 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_clean/nistapi.h @@ -0,0 +1,87 @@ +#ifndef SPX_API_H +#define SPX_API_H + +#include +#include + +#include "params.h" + +#define CRYPTO_ALGNAME "SPHINCS+" + +#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES +#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES +#define CRYPTO_BYTES SPX_BYTES +#define CRYPTO_SEEDBYTES (3*SPX_N) + +/* + * Returns the length of a secret key, in bytes + */ +#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) +size_t crypto_sign_secretkeybytes(void); + +/* + * Returns the length of a public key, in bytes + */ +#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) +size_t crypto_sign_publickeybytes(void); + +/* + * Returns the length of a signature, in bytes + */ +#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) +size_t crypto_sign_bytes(void); + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) +size_t crypto_sign_seedbytes(void); + +/* + * Generates a SPHINCS+ key pair given a seed. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed); + +/* + * Generates a SPHINCS+ key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [root || PUB_SEED] + */ +#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +/** + * Returns an array containing a detached signature. + */ +#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk); + +/** + * Verifies a detached signature and message under a given public key. + */ +#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk); + +/** + * Returns an array containing the signature followed by the message. + */ +#define crypto_sign SPX_NAMESPACE(crypto_sign) +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +/** + * Verifies a given signature-message pair under a given public key. + */ +#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_clean/params.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_clean/params.h new file mode 100644 index 0000000000..af47e01e89 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_clean/params.h @@ -0,0 +1,56 @@ +#ifndef SPX_PARAMS_H +#define SPX_PARAMS_H + +#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSSHAKE256SSIMPLE_CLEAN_##s + +/* Hash output length in bytes. */ +#define SPX_N 32 +/* Height of the hypertree. */ +#define SPX_FULL_HEIGHT 64 +/* Number of subtree layer. */ +#define SPX_D 8 +/* FORS tree dimensions. */ +#define SPX_FORS_HEIGHT 14 +#define SPX_FORS_TREES 22 +/* Winternitz parameter, */ +#define SPX_WOTS_W 16 + +/* The hash function is defined by linking a different hash.c file, as opposed + to setting a #define constant. */ + +/* For clarity */ +#define SPX_ADDR_BYTES 32 + +/* WOTS parameters. */ +#define SPX_WOTS_LOGW 4 + +#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) + +/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ +#define SPX_WOTS_LEN2 3 + +#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) +#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) +#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES + +/* Subtree size. */ +#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) + +//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT +// #error SPX_D should always divide SPX_FULL_HEIGHT +//#endif + +/* FORS parameters. */ +#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) +#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) +#define SPX_FORS_PK_BYTES SPX_N + +/* Resulting SPX sizes. */ +#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ + SPX_FULL_HEIGHT * SPX_N) +#define SPX_PK_BYTES (2 * SPX_N) +#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) + +#include "shake_offsets.h" + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_clean/shake_offsets.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_clean/shake_offsets.h new file mode 100644 index 0000000000..6b28d95d91 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_clean/shake_offsets.h @@ -0,0 +1,21 @@ +#ifndef SHAKE_OFFSETS_H_ +#define SHAKE_OFFSETS_H_ + +/* + * Offsets of various fields in the address structure when we use SHAKE as + * the Sphincs+ hash function + */ + +#define SPX_OFFSET_LAYER 3 /* The byte used to specify the Merkle tree layer */ +#define SPX_OFFSET_TREE 8 /* The start of the 8 byte field used to specify the tree */ +#define SPX_OFFSET_TYPE 19 /* The byte used to specify the hash type (reason) */ +#define SPX_OFFSET_KP_ADDR2 22 /* The high byte used to specify the key pair (which one-time signature) */ +#define SPX_OFFSET_KP_ADDR1 23 /* The low byte used to specify the key pair */ +#define SPX_OFFSET_CHAIN_ADDR 27 /* The byte used to specify the chain address (which Winternitz chain) */ +#define SPX_OFFSET_HASH_ADDR 31 /* The byte used to specify the hash address (where in the Winternitz chain) */ +#define SPX_OFFSET_TREE_HGT 27 /* The byte used to specify the height of this node in the FORS or Merkle tree */ +#define SPX_OFFSET_TREE_INDEX 28 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ + +#define SPX_SHAKE 1 + +#endif /* SHAKE_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_clean/sign.c b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_clean/sign.c new file mode 100644 index 0000000000..9d0c7d1b22 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_clean/sign.c @@ -0,0 +1,286 @@ +#include +#include +#include + +#include "address.h" +#include "context.h" +#include "fors.h" +#include "hash.h" +#include "merkle.h" +#include "nistapi.h" +#include "params.h" +#include "randombytes.h" +#include "thash.h" +#include "utils.h" +#include "wots.h" + +/* + * Returns the length of a secret key, in bytes + */ +size_t crypto_sign_secretkeybytes(void) { + return CRYPTO_SECRETKEYBYTES; +} + +/* + * Returns the length of a public key, in bytes + */ +size_t crypto_sign_publickeybytes(void) { + return CRYPTO_PUBLICKEYBYTES; +} + +/* + * Returns the length of a signature, in bytes + */ +size_t crypto_sign_bytes(void) { + return CRYPTO_BYTES; +} + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +size_t crypto_sign_seedbytes(void) { + return CRYPTO_SEEDBYTES; +} + +/* + * Generates an SPX key pair given a seed of length + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [PUB_SEED || root] + */ +int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, + const uint8_t *seed) { + spx_ctx ctx; + + /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ + memcpy(sk, seed, CRYPTO_SEEDBYTES); + + memcpy(pk, sk + 2 * SPX_N, SPX_N); + + memcpy(ctx.pub_seed, pk, SPX_N); + memcpy(ctx.sk_seed, sk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + /* Compute root node of the top-most subtree. */ + merkle_gen_root(sk + 3 * SPX_N, &ctx); + + // cleanup + free_hash_function(&ctx); + + memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); + + return 0; +} + +/* + * Generates an SPX key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [PUB_SEED || root] + */ +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { + uint8_t seed[CRYPTO_SEEDBYTES]; + randombytes(seed, CRYPTO_SEEDBYTES); + crypto_sign_seed_keypair(pk, sk, seed); + + return 0; +} + +/** + * Returns an array containing a detached signature. + */ +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk) { + spx_ctx ctx; + + const uint8_t *sk_prf = sk + SPX_N; + const uint8_t *pk = sk + 2 * SPX_N; + + uint8_t optrand[SPX_N]; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t root[SPX_N]; + uint32_t i; + uint64_t tree; + uint32_t idx_leaf; + uint32_t wots_addr[8] = {0}; + uint32_t tree_addr[8] = {0}; + + memcpy(ctx.sk_seed, sk, SPX_N); + memcpy(ctx.pub_seed, pk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + + /* Optionally, signing can be made non-deterministic using optrand. + This can help counter side-channel attacks that would benefit from + getting a large number of traces when the signer uses the same nodes. */ + randombytes(optrand, SPX_N); + /* Compute the digest randomization value. */ + gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); + + /* Derive the message digest and leaf index from R, PK and M. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; + + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); + + /* Sign the message hash using FORS. */ + fors_sign(sig, root, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); + sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; + + /* Update the indices for the next layer. */ + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; + } + + free_hash_function(&ctx); + + *siglen = SPX_BYTES; + + return 0; +} + +/** + * Verifies a detached signature and message under a given public key. + */ +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk) { + spx_ctx ctx; + const uint8_t *pub_root = pk + SPX_N; + uint8_t mhash[SPX_FORS_MSG_BYTES]; + uint8_t wots_pk[SPX_WOTS_BYTES]; + uint8_t root[SPX_N]; + uint8_t leaf[SPX_N]; + unsigned int i; + uint64_t tree; + uint32_t idx_leaf; + uint32_t wots_addr[8] = {0}; + uint32_t tree_addr[8] = {0}; + uint32_t wots_pk_addr[8] = {0}; + + if (siglen != SPX_BYTES) { + return -1; + } + + memcpy(ctx.pub_seed, pk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); + + /* Derive the message digest and leaf index from R || PK || M. */ + /* The additional SPX_N is a result of the hash domain separator. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; + + /* Layer correctly defaults to 0, so no need to set_layer_addr */ + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); + + fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + /* For each subtree.. */ + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + copy_keypair_addr(wots_pk_addr, wots_addr); + + /* The WOTS public key is only correct if the signature was correct. */ + /* Initially, root is the FORS pk, but on subsequent iterations it is + the root of the subtree below the currently processed subtree. */ + wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); + sig += SPX_WOTS_BYTES; + + /* Compute the leaf node using the WOTS public key. */ + thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); + + /* Compute the root node of this subtree. */ + compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, + &ctx, tree_addr); + sig += SPX_TREE_HEIGHT * SPX_N; + + /* Update the indices for the next layer. */ + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); + tree = tree >> SPX_TREE_HEIGHT; + } + + // cleanup + free_hash_function(&ctx); + + /* Check if the root node equals the root node in the public key. */ + if (memcmp(root, pub_root, SPX_N) != 0) { + return -1; + } + + return 0; +} + + +/** + * Returns an array containing the signature followed by the message. + */ +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk) { + size_t siglen; + + crypto_sign_signature(sm, &siglen, m, mlen, sk); + + memmove(sm + SPX_BYTES, m, mlen); + *smlen = siglen + mlen; + + return 0; +} + +/** + * Verifies a given signature-message pair under a given public key. + */ +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk) { + /* The API caller does not necessarily know what size a signature should be + but SPHINCS+ signatures are always exactly SPX_BYTES. */ + if (smlen < SPX_BYTES) { + memset(m, 0, smlen); + *mlen = 0; + return -1; + } + + *mlen = smlen - SPX_BYTES; + + if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { + memset(m, 0, smlen); + *mlen = 0; + return -1; + } + + /* If verification was successful, move the message to the right place. */ + memmove(m, sm + SPX_BYTES, *mlen); + + return 0; +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_clean/thash.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_clean/thash.h new file mode 100644 index 0000000000..8687ccfb4d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_clean/thash.h @@ -0,0 +1,13 @@ +#ifndef SPX_THASH_H +#define SPX_THASH_H + +#include "context.h" +#include "params.h" + +#include + +#define thash SPX_NAMESPACE(thash) +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_clean/thash_shake_simple.c b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_clean/thash_shake_simple.c new file mode 100644 index 0000000000..98470395e9 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_clean/thash_shake_simple.c @@ -0,0 +1,24 @@ +#include +#include + +#include "thash.h" + +#include "address.h" +#include "params.h" +#include "utils.h" + +#include "fips202.h" + +/** + * Takes an array of inblocks concatenated arrays of SPX_N bytes. + */ +void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, + const spx_ctx *ctx, uint32_t addr[8]) { + PQCLEAN_VLA(uint8_t, buf, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); + + memcpy(buf, ctx->pub_seed, SPX_N); + memcpy(buf + SPX_N, addr, SPX_ADDR_BYTES); + memcpy(buf + SPX_N + SPX_ADDR_BYTES, in, inblocks * SPX_N); + + shake256(out, SPX_N, buf, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_clean/utils.c b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_clean/utils.c new file mode 100644 index 0000000000..177b541fb9 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_clean/utils.c @@ -0,0 +1,148 @@ +#include + +#include "utils.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "thash.h" + +/** + * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. + */ +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in) { + int i; + + /* Iterate over out in decreasing order, for big-endianness. */ + for (i = (signed int)outlen - 1; i >= 0; i--) { + out[i] = in & 0xff; + in = in >> 8; + } +} + +void u32_to_bytes(unsigned char *out, uint32_t in) { + out[0] = (unsigned char)(in >> 24); + out[1] = (unsigned char)(in >> 16); + out[2] = (unsigned char)(in >> 8); + out[3] = (unsigned char)in; +} + +/** + * Converts the inlen bytes in 'in' from big-endian byte order to an integer. + */ +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { + unsigned long long retval = 0; + unsigned int i; + + for (i = 0; i < inlen; i++) { + retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); + } + return retval; +} + +/** + * Computes a root node given a leaf and an auth path. + * Expects address to be complete other than the tree_height and tree_index. + */ +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]) { + uint32_t i; + unsigned char buffer[2 * SPX_N]; + + /* If leaf_idx is odd (last bit = 1), current path element is a right child + and auth_path has to go left. Otherwise it is the other way around. */ + if (leaf_idx & 1) { + memcpy(buffer + SPX_N, leaf, SPX_N); + memcpy(buffer, auth_path, SPX_N); + } else { + memcpy(buffer, leaf, SPX_N); + memcpy(buffer + SPX_N, auth_path, SPX_N); + } + auth_path += SPX_N; + + for (i = 0; i < tree_height - 1; i++) { + leaf_idx >>= 1; + idx_offset >>= 1; + /* Set the address of the node we're creating. */ + set_tree_height(addr, i + 1); + set_tree_index(addr, leaf_idx + idx_offset); + + /* Pick the right or left neighbor, depending on parity of the node. */ + if (leaf_idx & 1) { + thash(buffer + SPX_N, buffer, 2, ctx, addr); + memcpy(buffer, auth_path, SPX_N); + } else { + thash(buffer, buffer, 2, ctx, addr); + memcpy(buffer + SPX_N, auth_path, SPX_N); + } + auth_path += SPX_N; + } + + /* The last iteration is exceptional; we do not copy an auth_path node. */ + leaf_idx >>= 1; + idx_offset >>= 1; + set_tree_height(addr, tree_height); + set_tree_index(addr, leaf_idx + idx_offset); + thash(root, buffer, 2, ctx, addr); +} + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx * /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]) { + PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); + PQCLEAN_VLA(unsigned int, heights, tree_height + 1); + unsigned int offset = 0; + uint32_t idx; + uint32_t tree_idx; + + for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { + /* Add the next leaf node to the stack. */ + gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); + offset++; + heights[offset - 1] = 0; + + /* If this is a node we need for the auth path.. */ + if ((leaf_idx ^ 0x1) == idx) { + memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); + } + + /* While the top-most nodes are of equal height.. */ + while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { + /* Compute index of the new node, in the next layer. */ + tree_idx = (idx >> (heights[offset - 1] + 1)); + + /* Set the address of the node we're creating. */ + set_tree_height(tree_addr, heights[offset - 1] + 1); + set_tree_index(tree_addr, + tree_idx + (idx_offset >> (heights[offset - 1] + 1))); + /* Hash the top-most nodes from the stack together. */ + thash(stack + (offset - 2)*SPX_N, + stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); + offset--; + /* Note that the top-most node is now one layer higher. */ + heights[offset - 1]++; + + /* If this is a node we need for the auth path.. */ + if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { + memcpy(auth_path + heights[offset - 1]*SPX_N, + stack + (offset - 1)*SPX_N, SPX_N); + } + } + } + memcpy(root, stack, SPX_N); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_clean/utils.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_clean/utils.h new file mode 100644 index 0000000000..64f5d5a53a --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_clean/utils.h @@ -0,0 +1,58 @@ +#ifndef SPX_UTILS_H +#define SPX_UTILS_H + +#include + +#include "compat.h" +#include "context.h" +#include "params.h" + + +/* To support MSVC use alloca() instead of VLAs. See #20. */ + + +/** + * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. + */ +#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) +void ull_to_bytes(unsigned char *out, unsigned int outlen, + unsigned long long in); +#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) +void u32_to_bytes(unsigned char *out, uint32_t in); + +/** + * Converts the inlen bytes in 'in' from big-endian byte order to an integer. + */ +#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) +unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); + +/** + * Computes a root node given a leaf and an auth path. + * Expects address to be complete other than the tree_height and tree_index. + */ +#define compute_root SPX_NAMESPACE(compute_root) +void compute_root(unsigned char *root, const unsigned char *leaf, + uint32_t leaf_idx, uint32_t idx_offset, + const unsigned char *auth_path, uint32_t tree_height, + const spx_ctx *ctx, uint32_t addr[8]); + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +#define treehash SPX_NAMESPACE(treehash) +void treehash(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* leaf */, + const spx_ctx *ctx /* ctx */, + uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), + uint32_t tree_addr[8]); + + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_clean/utilsx1.c b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_clean/utilsx1.c new file mode 100644 index 0000000000..fccb69b35d --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_clean/utilsx1.c @@ -0,0 +1,100 @@ +#include + +#include "utilsx1.h" + +#include "address.h" +#include "params.h" +#include "thash.h" +#include "utils.h" + +/* + * Generate the entire Merkle tree, computing the authentication path for + * leaf_idx, and the resulting root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) + * + * This expects tree_addr to be initialized to the addr structures for the + * Merkle tree nodes + * + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + * + * This works by using the standard Merkle tree building algorithm, + */ +void treehashx1(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, + uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* Where to write the leaves */, + const spx_ctx * /* ctx */, + uint32_t idx, void *info), + uint32_t tree_addr[8], + void *info) { + /* This is where we keep the intermediate nodes */ + PQCLEAN_VLA(uint8_t, stack, tree_height * SPX_N); + + uint32_t idx; + uint32_t max_idx = (uint32_t)((1 << tree_height) - 1); + for (idx = 0;; idx++) { + unsigned char current[2 * SPX_N]; /* Current logical node is at */ + /* index[SPX_N]. We do this to minimize the number of copies */ + /* needed during a thash */ + gen_leaf( ¤t[SPX_N], ctx, idx + idx_offset, + info ); + + /* Now combine the freshly generated right node with previously */ + /* generated left ones */ + uint32_t internal_idx_offset = idx_offset; + uint32_t internal_idx = idx; + uint32_t internal_leaf = leaf_idx; + uint32_t h; /* The height we are in the Merkle tree */ + for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { + + /* Check if we hit the top of the tree */ + if (h == tree_height) { + /* We hit the root; return it */ + memcpy( root, ¤t[SPX_N], SPX_N ); + return; + } + + /* + * Check if the node we have is a part of the + * authentication path; if it is, write it out + */ + if ((internal_idx ^ internal_leaf) == 0x01) { + memcpy( &auth_path[ h * SPX_N ], + ¤t[SPX_N], + SPX_N ); + } + + /* + * Check if we're at a left child; if so, stop going up the stack + * Exception: if we've reached the end of the tree, keep on going + * (so we combine the last 4 nodes into the one root node in two + * more iterations) + */ + if ((internal_idx & 1) == 0 && idx < max_idx) { + break; + } + + /* Ok, we're at a right node */ + /* Now combine the left and right logical nodes together */ + + /* Set the address of the node we're creating. */ + internal_idx_offset >>= 1; + set_tree_height(tree_addr, h + 1); + set_tree_index(tree_addr, internal_idx / 2 + internal_idx_offset ); + + unsigned char *left = &stack[h * SPX_N]; + memcpy( ¤t[0], left, SPX_N ); + thash( ¤t[1 * SPX_N], + ¤t[0 * SPX_N], + 2, ctx, tree_addr); + } + + /* We've hit a left child; save the current for when we get the */ + /* corresponding right right */ + memcpy( &stack[h * SPX_N], ¤t[SPX_N], SPX_N); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_clean/utilsx1.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_clean/utilsx1.h new file mode 100644 index 0000000000..e911d17d53 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_clean/utilsx1.h @@ -0,0 +1,27 @@ +#ifndef SPX_UTILSX4_H +#define SPX_UTILSX4_H + +#include + +#include "context.h" +#include "params.h" + +/** + * For a given leaf index, computes the authentication path and the resulting + * root node using Merkle's TreeHash algorithm. + * Expects the layer and tree parts of the tree_addr to be set, as well as the + * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). + * Applies the offset idx_offset to indices before building addresses, so that + * it is possible to continue counting indices across trees. + */ +#define treehashx1 SPX_NAMESPACE(treehashx1) +void treehashx1(unsigned char *root, unsigned char *auth_path, + const spx_ctx *ctx, + uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, + void (*gen_leaf)( + unsigned char * /* Where to write the leaf */, + const spx_ctx * /* ctx */, + uint32_t addr_idx, void *info), + uint32_t tree_addrx4[8], void *info); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_clean/wots.c b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_clean/wots.c new file mode 100644 index 0000000000..249717aaa8 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_clean/wots.c @@ -0,0 +1,108 @@ +#include +#include + +#include "wots.h" +#include "wotsx1.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "thash.h" +#include "utils.h" +#include "utilsx1.h" + +// TODO clarify address expectations, and make them more uniform. +// TODO i.e. do we expect types to be set already? +// TODO and do we expect modifications or copies? + +/** + * Computes the chaining function. + * out and in have to be n-byte arrays. + * + * Interprets in as start-th value of the chain. + * addr has to contain the address of the chain. + */ +static void gen_chain(unsigned char *out, const unsigned char *in, + unsigned int start, unsigned int steps, + const spx_ctx *ctx, uint32_t addr[8]) { + uint32_t i; + + /* Initialize out with the value at position 'start'. */ + memcpy(out, in, SPX_N); + + /* Iterate 'steps' calls to the hash function. */ + for (i = start; i < (start + steps) && i < SPX_WOTS_W; i++) { + set_hash_addr(addr, i); + thash(out, out, 1, ctx, addr); + } +} + +/** + * base_w algorithm as described in draft. + * Interprets an array of bytes as integers in base w. + * This only works when log_w is a divisor of 8. + */ +static void base_w(unsigned int *output, const int out_len, + const unsigned char *input) { + int in = 0; + int out = 0; + unsigned char total = 0; + int bits = 0; + int consumed; + + for (consumed = 0; consumed < out_len; consumed++) { + if (bits == 0) { + total = input[in]; + in++; + bits += 8; + } + bits -= SPX_WOTS_LOGW; + output[out] = (total >> bits) & (SPX_WOTS_W - 1); + out++; + } +} + +/* Computes the WOTS+ checksum over a message (in base_w). */ +static void wots_checksum(unsigned int *csum_base_w, + const unsigned int *msg_base_w) { + unsigned int csum = 0; + unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; + unsigned int i; + + /* Compute checksum. */ + for (i = 0; i < SPX_WOTS_LEN1; i++) { + csum += SPX_WOTS_W - 1 - msg_base_w[i]; + } + + /* Convert checksum to base_w. */ + /* Make sure expected empty zero bits are the least significant bits. */ + csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); + ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); + base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); +} + +/* Takes a message and derives the matching chain lengths. */ +void chain_lengths(unsigned int *lengths, const unsigned char *msg) { + base_w(lengths, SPX_WOTS_LEN1, msg); + wots_checksum(lengths + SPX_WOTS_LEN1, lengths); +} + +/** + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. + * + * Writes the computed public key to 'pk'. + */ +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]) { + unsigned int lengths[SPX_WOTS_LEN]; + uint32_t i; + + chain_lengths(lengths, msg); + + for (i = 0; i < SPX_WOTS_LEN; i++) { + set_chain_addr(addr, i); + gen_chain(pk + i * SPX_N, sig + i * SPX_N, + lengths[i], SPX_WOTS_W - 1 - lengths[i], ctx, addr); + } +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_clean/wots.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_clean/wots.h new file mode 100644 index 0000000000..4e7692eeef --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_clean/wots.h @@ -0,0 +1,25 @@ +#ifndef SPX_WOTS_H +#define SPX_WOTS_H + +#include + +#include "context.h" +#include "params.h" + +/** + * Takes a WOTS signature and an n-byte message, computes a WOTS public key. + * + * Writes the computed public key to 'pk'. + */ +#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) +void wots_pk_from_sig(unsigned char *pk, + const unsigned char *sig, const unsigned char *msg, + const spx_ctx *ctx, uint32_t addr[8]); + +/* + * Compute the chain lengths needed for a given message hash + */ +#define chain_lengths SPX_NAMESPACE(chain_lengths) +void chain_lengths(unsigned int *lengths, const unsigned char *msg); + +#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_clean/wotsx1.c b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_clean/wotsx1.c new file mode 100644 index 0000000000..3adec78dfb --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_clean/wotsx1.c @@ -0,0 +1,76 @@ +#include +#include + +#include "wots.h" +#include "wotsx1.h" + +#include "address.h" +#include "hash.h" +#include "params.h" +#include "thash.h" +#include "utils.h" + +/* + * This generates a WOTS public key + * It also generates the WOTS signature if leaf_info indicates + * that we're signing with this WOTS key + */ +void wots_gen_leafx1(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info) { + struct leaf_info_x1 *info = v_info; + uint32_t *leaf_addr = info->leaf_addr; + uint32_t *pk_addr = info->pk_addr; + unsigned int i, k; + unsigned char pk_buffer[ SPX_WOTS_BYTES ]; + unsigned char *buffer; + uint32_t wots_k_mask; + + if (leaf_idx == info->wots_sign_leaf) { + /* We're traversing the leaf that's signing; generate the WOTS */ + /* signature */ + wots_k_mask = 0; + } else { + /* Nope, we're just generating pk's; turn off the signature logic */ + wots_k_mask = (uint32_t)~0; + } + + set_keypair_addr( leaf_addr, leaf_idx ); + set_keypair_addr( pk_addr, leaf_idx ); + + for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { + uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k to */ + /* the step if we're generating a signature, ~0 if we're not */ + + /* Start with the secret seed */ + set_chain_addr(leaf_addr, i); + set_hash_addr(leaf_addr, 0); + set_type(leaf_addr, SPX_ADDR_TYPE_WOTSPRF); + + prf_addr(buffer, ctx, leaf_addr); + + set_type(leaf_addr, SPX_ADDR_TYPE_WOTS); + + /* Iterate down the WOTS chain */ + for (k = 0;; k++) { + /* Check if this is the value that needs to be saved as a */ + /* part of the WOTS signature */ + if (k == wots_k) { + memcpy( info->wots_sig + i * SPX_N, buffer, SPX_N ); + } + + /* Check if we hit the top of the chain */ + if (k == SPX_WOTS_W - 1) { + break; + } + + /* Iterate one step on the chain */ + set_hash_addr(leaf_addr, k); + + thash(buffer, buffer, 1, ctx, leaf_addr); + } + } + + /* Do the final thash to generate the public keys */ + thash(dest, pk_buffer, SPX_WOTS_LEN, ctx, pk_addr); +} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_clean/wotsx1.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_clean/wotsx1.h new file mode 100644 index 0000000000..e617929f96 --- /dev/null +++ b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_clean/wotsx1.h @@ -0,0 +1,39 @@ +#ifndef WOTSX1_H_ +#define WOTSX1_H_ + +#include + +#include "context.h" +#include "params.h" + +/* + * This is here to provide an interface to the internal wots_gen_leafx1 + * routine. While this routine is not referenced in the package outside of + * wots.c, it is called from the stand-alone benchmark code to characterize + * the performance + */ +struct leaf_info_x1 { + unsigned char *wots_sig; + uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ + uint32_t *wots_steps; + uint32_t leaf_addr[8]; + uint32_t pk_addr[8]; +}; + +/* Macro to set the leaf_info to something 'benign', that is, it would */ +/* run with the same time as it does during the real signing process */ +/* Used only by the benchmark code */ +#define INITIALIZE_LEAF_INFO_X1(info, addr, step_buffer) { \ + (info).wots_sig = 0; \ + (info).wots_sign_leaf = ~0; \ + (info).wots_steps = step_buffer; \ + memcpy( &(info).leaf_addr[0], (addr), 32 ); \ + memcpy( &(info).pk_addr[0], (addr), 32 ); \ + } + +#define wots_gen_leafx1 SPX_NAMESPACE(wots_gen_leafx1) +void wots_gen_leafx1(unsigned char *dest, + const spx_ctx *ctx, + uint32_t leaf_idx, void *v_info); + +#endif /* WOTSX1_H_ */ diff --git a/src/sig/sphincs/sig_sphincs_haraka_128f_robust.c b/src/sig/sphincs/sig_sphincs_haraka_128f_robust.c index ce81ac57de..8f93b009db 100644 --- a/src/sig/sphincs/sig_sphincs_haraka_128f_robust.c +++ b/src/sig/sphincs/sig_sphincs_haraka_128f_robust.c @@ -13,7 +13,7 @@ OQS_SIG *OQS_SIG_sphincs_haraka_128f_robust_new(void) { return NULL; } sig->method_name = OQS_SIG_alg_sphincs_haraka_128f_robust; - sig->alg_version = "https://github.com/sphincs/sphincsplus/commit/77755c94d0bc744478044d6efbb888dc13156441"; + sig->alg_version = "https://github.com/sphincs/sphincsplus/commit/ed15dd78658f63288c7492c00260d86154b84637"; sig->claimed_nist_level = 1; sig->euf_cma = true; diff --git a/src/sig/sphincs/sig_sphincs_haraka_128f_simple.c b/src/sig/sphincs/sig_sphincs_haraka_128f_simple.c index 8e4fa4a782..db82c248b5 100644 --- a/src/sig/sphincs/sig_sphincs_haraka_128f_simple.c +++ b/src/sig/sphincs/sig_sphincs_haraka_128f_simple.c @@ -13,7 +13,7 @@ OQS_SIG *OQS_SIG_sphincs_haraka_128f_simple_new(void) { return NULL; } sig->method_name = OQS_SIG_alg_sphincs_haraka_128f_simple; - sig->alg_version = "https://github.com/sphincs/sphincsplus/commit/77755c94d0bc744478044d6efbb888dc13156441"; + sig->alg_version = "https://github.com/sphincs/sphincsplus/commit/ed15dd78658f63288c7492c00260d86154b84637"; sig->claimed_nist_level = 1; sig->euf_cma = true; diff --git a/src/sig/sphincs/sig_sphincs_haraka_128s_robust.c b/src/sig/sphincs/sig_sphincs_haraka_128s_robust.c index 8bc44695c7..189c0aac2a 100644 --- a/src/sig/sphincs/sig_sphincs_haraka_128s_robust.c +++ b/src/sig/sphincs/sig_sphincs_haraka_128s_robust.c @@ -13,7 +13,7 @@ OQS_SIG *OQS_SIG_sphincs_haraka_128s_robust_new(void) { return NULL; } sig->method_name = OQS_SIG_alg_sphincs_haraka_128s_robust; - sig->alg_version = "https://github.com/sphincs/sphincsplus/commit/77755c94d0bc744478044d6efbb888dc13156441"; + sig->alg_version = "https://github.com/sphincs/sphincsplus/commit/ed15dd78658f63288c7492c00260d86154b84637"; sig->claimed_nist_level = 1; sig->euf_cma = true; diff --git a/src/sig/sphincs/sig_sphincs_haraka_128s_simple.c b/src/sig/sphincs/sig_sphincs_haraka_128s_simple.c index 5c0d83b4b6..a24127abb4 100644 --- a/src/sig/sphincs/sig_sphincs_haraka_128s_simple.c +++ b/src/sig/sphincs/sig_sphincs_haraka_128s_simple.c @@ -13,7 +13,7 @@ OQS_SIG *OQS_SIG_sphincs_haraka_128s_simple_new(void) { return NULL; } sig->method_name = OQS_SIG_alg_sphincs_haraka_128s_simple; - sig->alg_version = "https://github.com/sphincs/sphincsplus/commit/77755c94d0bc744478044d6efbb888dc13156441"; + sig->alg_version = "https://github.com/sphincs/sphincsplus/commit/ed15dd78658f63288c7492c00260d86154b84637"; sig->claimed_nist_level = 1; sig->euf_cma = true; diff --git a/src/sig/sphincs/sig_sphincs_haraka_192f_robust.c b/src/sig/sphincs/sig_sphincs_haraka_192f_robust.c index 6cee0c895a..9902a80f04 100644 --- a/src/sig/sphincs/sig_sphincs_haraka_192f_robust.c +++ b/src/sig/sphincs/sig_sphincs_haraka_192f_robust.c @@ -13,9 +13,9 @@ OQS_SIG *OQS_SIG_sphincs_haraka_192f_robust_new(void) { return NULL; } sig->method_name = OQS_SIG_alg_sphincs_haraka_192f_robust; - sig->alg_version = "https://github.com/sphincs/sphincsplus/commit/77755c94d0bc744478044d6efbb888dc13156441"; + sig->alg_version = "https://github.com/sphincs/sphincsplus/commit/ed15dd78658f63288c7492c00260d86154b84637"; - sig->claimed_nist_level = 3; + sig->claimed_nist_level = 2; sig->euf_cma = true; sig->length_public_key = OQS_SIG_sphincs_haraka_192f_robust_length_public_key; diff --git a/src/sig/sphincs/sig_sphincs_haraka_192f_simple.c b/src/sig/sphincs/sig_sphincs_haraka_192f_simple.c index aeb1e51881..3d6766b6c7 100644 --- a/src/sig/sphincs/sig_sphincs_haraka_192f_simple.c +++ b/src/sig/sphincs/sig_sphincs_haraka_192f_simple.c @@ -13,9 +13,9 @@ OQS_SIG *OQS_SIG_sphincs_haraka_192f_simple_new(void) { return NULL; } sig->method_name = OQS_SIG_alg_sphincs_haraka_192f_simple; - sig->alg_version = "https://github.com/sphincs/sphincsplus/commit/77755c94d0bc744478044d6efbb888dc13156441"; + sig->alg_version = "https://github.com/sphincs/sphincsplus/commit/ed15dd78658f63288c7492c00260d86154b84637"; - sig->claimed_nist_level = 3; + sig->claimed_nist_level = 2; sig->euf_cma = true; sig->length_public_key = OQS_SIG_sphincs_haraka_192f_simple_length_public_key; diff --git a/src/sig/sphincs/sig_sphincs_haraka_192s_robust.c b/src/sig/sphincs/sig_sphincs_haraka_192s_robust.c index 4dc3f34cfc..156132e466 100644 --- a/src/sig/sphincs/sig_sphincs_haraka_192s_robust.c +++ b/src/sig/sphincs/sig_sphincs_haraka_192s_robust.c @@ -13,9 +13,9 @@ OQS_SIG *OQS_SIG_sphincs_haraka_192s_robust_new(void) { return NULL; } sig->method_name = OQS_SIG_alg_sphincs_haraka_192s_robust; - sig->alg_version = "https://github.com/sphincs/sphincsplus/commit/77755c94d0bc744478044d6efbb888dc13156441"; + sig->alg_version = "https://github.com/sphincs/sphincsplus/commit/ed15dd78658f63288c7492c00260d86154b84637"; - sig->claimed_nist_level = 3; + sig->claimed_nist_level = 2; sig->euf_cma = true; sig->length_public_key = OQS_SIG_sphincs_haraka_192s_robust_length_public_key; diff --git a/src/sig/sphincs/sig_sphincs_haraka_192s_simple.c b/src/sig/sphincs/sig_sphincs_haraka_192s_simple.c index cbad3efe95..a14807f7e1 100644 --- a/src/sig/sphincs/sig_sphincs_haraka_192s_simple.c +++ b/src/sig/sphincs/sig_sphincs_haraka_192s_simple.c @@ -13,9 +13,9 @@ OQS_SIG *OQS_SIG_sphincs_haraka_192s_simple_new(void) { return NULL; } sig->method_name = OQS_SIG_alg_sphincs_haraka_192s_simple; - sig->alg_version = "https://github.com/sphincs/sphincsplus/commit/77755c94d0bc744478044d6efbb888dc13156441"; + sig->alg_version = "https://github.com/sphincs/sphincsplus/commit/ed15dd78658f63288c7492c00260d86154b84637"; - sig->claimed_nist_level = 3; + sig->claimed_nist_level = 2; sig->euf_cma = true; sig->length_public_key = OQS_SIG_sphincs_haraka_192s_simple_length_public_key; diff --git a/src/sig/sphincs/sig_sphincs_haraka_256f_robust.c b/src/sig/sphincs/sig_sphincs_haraka_256f_robust.c index 9c78699169..9da19bca9b 100644 --- a/src/sig/sphincs/sig_sphincs_haraka_256f_robust.c +++ b/src/sig/sphincs/sig_sphincs_haraka_256f_robust.c @@ -13,9 +13,9 @@ OQS_SIG *OQS_SIG_sphincs_haraka_256f_robust_new(void) { return NULL; } sig->method_name = OQS_SIG_alg_sphincs_haraka_256f_robust; - sig->alg_version = "https://github.com/sphincs/sphincsplus/commit/77755c94d0bc744478044d6efbb888dc13156441"; + sig->alg_version = "https://github.com/sphincs/sphincsplus/commit/ed15dd78658f63288c7492c00260d86154b84637"; - sig->claimed_nist_level = 5; + sig->claimed_nist_level = 2; sig->euf_cma = true; sig->length_public_key = OQS_SIG_sphincs_haraka_256f_robust_length_public_key; diff --git a/src/sig/sphincs/sig_sphincs_haraka_256f_simple.c b/src/sig/sphincs/sig_sphincs_haraka_256f_simple.c index 85f51dc2f9..c24c7989cc 100644 --- a/src/sig/sphincs/sig_sphincs_haraka_256f_simple.c +++ b/src/sig/sphincs/sig_sphincs_haraka_256f_simple.c @@ -13,9 +13,9 @@ OQS_SIG *OQS_SIG_sphincs_haraka_256f_simple_new(void) { return NULL; } sig->method_name = OQS_SIG_alg_sphincs_haraka_256f_simple; - sig->alg_version = "https://github.com/sphincs/sphincsplus/commit/77755c94d0bc744478044d6efbb888dc13156441"; + sig->alg_version = "https://github.com/sphincs/sphincsplus/commit/ed15dd78658f63288c7492c00260d86154b84637"; - sig->claimed_nist_level = 5; + sig->claimed_nist_level = 2; sig->euf_cma = true; sig->length_public_key = OQS_SIG_sphincs_haraka_256f_simple_length_public_key; diff --git a/src/sig/sphincs/sig_sphincs_haraka_256s_robust.c b/src/sig/sphincs/sig_sphincs_haraka_256s_robust.c index 4a4ca89461..3953a234f9 100644 --- a/src/sig/sphincs/sig_sphincs_haraka_256s_robust.c +++ b/src/sig/sphincs/sig_sphincs_haraka_256s_robust.c @@ -13,9 +13,9 @@ OQS_SIG *OQS_SIG_sphincs_haraka_256s_robust_new(void) { return NULL; } sig->method_name = OQS_SIG_alg_sphincs_haraka_256s_robust; - sig->alg_version = "https://github.com/sphincs/sphincsplus/commit/77755c94d0bc744478044d6efbb888dc13156441"; + sig->alg_version = "https://github.com/sphincs/sphincsplus/commit/ed15dd78658f63288c7492c00260d86154b84637"; - sig->claimed_nist_level = 5; + sig->claimed_nist_level = 2; sig->euf_cma = true; sig->length_public_key = OQS_SIG_sphincs_haraka_256s_robust_length_public_key; diff --git a/src/sig/sphincs/sig_sphincs_haraka_256s_simple.c b/src/sig/sphincs/sig_sphincs_haraka_256s_simple.c index ed6560416d..95c4f50857 100644 --- a/src/sig/sphincs/sig_sphincs_haraka_256s_simple.c +++ b/src/sig/sphincs/sig_sphincs_haraka_256s_simple.c @@ -13,9 +13,9 @@ OQS_SIG *OQS_SIG_sphincs_haraka_256s_simple_new(void) { return NULL; } sig->method_name = OQS_SIG_alg_sphincs_haraka_256s_simple; - sig->alg_version = "https://github.com/sphincs/sphincsplus/commit/77755c94d0bc744478044d6efbb888dc13156441"; + sig->alg_version = "https://github.com/sphincs/sphincsplus/commit/ed15dd78658f63288c7492c00260d86154b84637"; - sig->claimed_nist_level = 5; + sig->claimed_nist_level = 2; sig->euf_cma = true; sig->length_public_key = OQS_SIG_sphincs_haraka_256s_simple_length_public_key; diff --git a/src/sig/sphincs/sig_sphincs_sha256_128f_robust.c b/src/sig/sphincs/sig_sphincs_sha256_128f_robust.c index 6327b42cbb..b5381800bc 100644 --- a/src/sig/sphincs/sig_sphincs_sha256_128f_robust.c +++ b/src/sig/sphincs/sig_sphincs_sha256_128f_robust.c @@ -13,7 +13,7 @@ OQS_SIG *OQS_SIG_sphincs_sha256_128f_robust_new(void) { return NULL; } sig->method_name = OQS_SIG_alg_sphincs_sha256_128f_robust; - sig->alg_version = "https://github.com/sphincs/sphincsplus/commit/77755c94d0bc744478044d6efbb888dc13156441"; + sig->alg_version = "https://github.com/sphincs/sphincsplus/commit/ed15dd78658f63288c7492c00260d86154b84637"; sig->claimed_nist_level = 1; sig->euf_cma = true; @@ -29,14 +29,14 @@ OQS_SIG *OQS_SIG_sphincs_sha256_128f_robust_new(void) { return sig; } -extern int PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); -extern int PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); -extern int PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); +extern int PQCLEAN_SPHINCSSHA2128FROBUST_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); +extern int PQCLEAN_SPHINCSSHA2128FROBUST_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); +extern int PQCLEAN_SPHINCSSHA2128FROBUST_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); #if defined(OQS_ENABLE_SIG_sphincs_sha256_128f_robust_avx2) -extern int PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); -extern int PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); -extern int PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); +extern int PQCLEAN_SPHINCSSHA2128FROBUST_AVX2_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); +extern int PQCLEAN_SPHINCSSHA2128FROBUST_AVX2_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); +extern int PQCLEAN_SPHINCSSHA2128FROBUST_AVX2_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); #endif OQS_API OQS_STATUS OQS_SIG_sphincs_sha256_128f_robust_keypair(uint8_t *public_key, uint8_t *secret_key) { @@ -44,14 +44,14 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_sha256_128f_robust_keypair(uint8_t *public_ke #if defined(OQS_DIST_BUILD) if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) { #endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_crypto_sign_keypair(public_key, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHA2128FROBUST_AVX2_crypto_sign_keypair(public_key, secret_key); #if defined(OQS_DIST_BUILD) } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_crypto_sign_keypair(public_key, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHA2128FROBUST_CLEAN_crypto_sign_keypair(public_key, secret_key); } #endif /* OQS_DIST_BUILD */ #else - return (OQS_STATUS) PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_crypto_sign_keypair(public_key, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHA2128FROBUST_CLEAN_crypto_sign_keypair(public_key, secret_key); #endif } @@ -60,14 +60,14 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_sha256_128f_robust_sign(uint8_t *signature, s #if defined(OQS_DIST_BUILD) if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) { #endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHA2128FROBUST_AVX2_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); #if defined(OQS_DIST_BUILD) } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHA2128FROBUST_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); } #endif /* OQS_DIST_BUILD */ #else - return (OQS_STATUS) PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHA2128FROBUST_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); #endif } @@ -76,14 +76,14 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_sha256_128f_robust_verify(const uint8_t *mess #if defined(OQS_DIST_BUILD) if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) { #endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_crypto_sign_verify(signature, signature_len, message, message_len, public_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHA2128FROBUST_AVX2_crypto_sign_verify(signature, signature_len, message, message_len, public_key); #if defined(OQS_DIST_BUILD) } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHA2128FROBUST_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); } #endif /* OQS_DIST_BUILD */ #else - return (OQS_STATUS) PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHA2128FROBUST_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); #endif } diff --git a/src/sig/sphincs/sig_sphincs_sha256_128f_simple.c b/src/sig/sphincs/sig_sphincs_sha256_128f_simple.c index 672cf63f47..2b76cfc1d1 100644 --- a/src/sig/sphincs/sig_sphincs_sha256_128f_simple.c +++ b/src/sig/sphincs/sig_sphincs_sha256_128f_simple.c @@ -13,7 +13,7 @@ OQS_SIG *OQS_SIG_sphincs_sha256_128f_simple_new(void) { return NULL; } sig->method_name = OQS_SIG_alg_sphincs_sha256_128f_simple; - sig->alg_version = "https://github.com/sphincs/sphincsplus/commit/77755c94d0bc744478044d6efbb888dc13156441"; + sig->alg_version = "https://github.com/sphincs/sphincsplus/commit/ed15dd78658f63288c7492c00260d86154b84637"; sig->claimed_nist_level = 1; sig->euf_cma = true; @@ -29,14 +29,14 @@ OQS_SIG *OQS_SIG_sphincs_sha256_128f_simple_new(void) { return sig; } -extern int PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); -extern int PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); -extern int PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); +extern int PQCLEAN_SPHINCSSHA2128FSIMPLE_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); +extern int PQCLEAN_SPHINCSSHA2128FSIMPLE_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); +extern int PQCLEAN_SPHINCSSHA2128FSIMPLE_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); #if defined(OQS_ENABLE_SIG_sphincs_sha256_128f_simple_avx2) -extern int PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); -extern int PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); -extern int PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); +extern int PQCLEAN_SPHINCSSHA2128FSIMPLE_AVX2_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); +extern int PQCLEAN_SPHINCSSHA2128FSIMPLE_AVX2_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); +extern int PQCLEAN_SPHINCSSHA2128FSIMPLE_AVX2_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); #endif OQS_API OQS_STATUS OQS_SIG_sphincs_sha256_128f_simple_keypair(uint8_t *public_key, uint8_t *secret_key) { @@ -44,14 +44,14 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_sha256_128f_simple_keypair(uint8_t *public_ke #if defined(OQS_DIST_BUILD) if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) { #endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_crypto_sign_keypair(public_key, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHA2128FSIMPLE_AVX2_crypto_sign_keypair(public_key, secret_key); #if defined(OQS_DIST_BUILD) } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_crypto_sign_keypair(public_key, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHA2128FSIMPLE_CLEAN_crypto_sign_keypair(public_key, secret_key); } #endif /* OQS_DIST_BUILD */ #else - return (OQS_STATUS) PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_crypto_sign_keypair(public_key, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHA2128FSIMPLE_CLEAN_crypto_sign_keypair(public_key, secret_key); #endif } @@ -60,14 +60,14 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_sha256_128f_simple_sign(uint8_t *signature, s #if defined(OQS_DIST_BUILD) if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) { #endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHA2128FSIMPLE_AVX2_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); #if defined(OQS_DIST_BUILD) } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHA2128FSIMPLE_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); } #endif /* OQS_DIST_BUILD */ #else - return (OQS_STATUS) PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHA2128FSIMPLE_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); #endif } @@ -76,14 +76,14 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_sha256_128f_simple_verify(const uint8_t *mess #if defined(OQS_DIST_BUILD) if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) { #endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_crypto_sign_verify(signature, signature_len, message, message_len, public_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHA2128FSIMPLE_AVX2_crypto_sign_verify(signature, signature_len, message, message_len, public_key); #if defined(OQS_DIST_BUILD) } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHA2128FSIMPLE_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); } #endif /* OQS_DIST_BUILD */ #else - return (OQS_STATUS) PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHA2128FSIMPLE_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); #endif } diff --git a/src/sig/sphincs/sig_sphincs_sha256_128s_robust.c b/src/sig/sphincs/sig_sphincs_sha256_128s_robust.c index 323c1e6fdc..df90a5f18f 100644 --- a/src/sig/sphincs/sig_sphincs_sha256_128s_robust.c +++ b/src/sig/sphincs/sig_sphincs_sha256_128s_robust.c @@ -13,7 +13,7 @@ OQS_SIG *OQS_SIG_sphincs_sha256_128s_robust_new(void) { return NULL; } sig->method_name = OQS_SIG_alg_sphincs_sha256_128s_robust; - sig->alg_version = "https://github.com/sphincs/sphincsplus/commit/77755c94d0bc744478044d6efbb888dc13156441"; + sig->alg_version = "https://github.com/sphincs/sphincsplus/commit/ed15dd78658f63288c7492c00260d86154b84637"; sig->claimed_nist_level = 1; sig->euf_cma = true; @@ -29,14 +29,14 @@ OQS_SIG *OQS_SIG_sphincs_sha256_128s_robust_new(void) { return sig; } -extern int PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); -extern int PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); -extern int PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); +extern int PQCLEAN_SPHINCSSHA2128SROBUST_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); +extern int PQCLEAN_SPHINCSSHA2128SROBUST_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); +extern int PQCLEAN_SPHINCSSHA2128SROBUST_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); #if defined(OQS_ENABLE_SIG_sphincs_sha256_128s_robust_avx2) -extern int PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); -extern int PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); -extern int PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); +extern int PQCLEAN_SPHINCSSHA2128SROBUST_AVX2_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); +extern int PQCLEAN_SPHINCSSHA2128SROBUST_AVX2_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); +extern int PQCLEAN_SPHINCSSHA2128SROBUST_AVX2_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); #endif OQS_API OQS_STATUS OQS_SIG_sphincs_sha256_128s_robust_keypair(uint8_t *public_key, uint8_t *secret_key) { @@ -44,14 +44,14 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_sha256_128s_robust_keypair(uint8_t *public_ke #if defined(OQS_DIST_BUILD) if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) { #endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_crypto_sign_keypair(public_key, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHA2128SROBUST_AVX2_crypto_sign_keypair(public_key, secret_key); #if defined(OQS_DIST_BUILD) } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_crypto_sign_keypair(public_key, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHA2128SROBUST_CLEAN_crypto_sign_keypair(public_key, secret_key); } #endif /* OQS_DIST_BUILD */ #else - return (OQS_STATUS) PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_crypto_sign_keypair(public_key, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHA2128SROBUST_CLEAN_crypto_sign_keypair(public_key, secret_key); #endif } @@ -60,14 +60,14 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_sha256_128s_robust_sign(uint8_t *signature, s #if defined(OQS_DIST_BUILD) if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) { #endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHA2128SROBUST_AVX2_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); #if defined(OQS_DIST_BUILD) } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHA2128SROBUST_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); } #endif /* OQS_DIST_BUILD */ #else - return (OQS_STATUS) PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHA2128SROBUST_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); #endif } @@ -76,14 +76,14 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_sha256_128s_robust_verify(const uint8_t *mess #if defined(OQS_DIST_BUILD) if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) { #endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_crypto_sign_verify(signature, signature_len, message, message_len, public_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHA2128SROBUST_AVX2_crypto_sign_verify(signature, signature_len, message, message_len, public_key); #if defined(OQS_DIST_BUILD) } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHA2128SROBUST_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); } #endif /* OQS_DIST_BUILD */ #else - return (OQS_STATUS) PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHA2128SROBUST_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); #endif } diff --git a/src/sig/sphincs/sig_sphincs_sha256_128s_simple.c b/src/sig/sphincs/sig_sphincs_sha256_128s_simple.c index f470ae9532..05b9146416 100644 --- a/src/sig/sphincs/sig_sphincs_sha256_128s_simple.c +++ b/src/sig/sphincs/sig_sphincs_sha256_128s_simple.c @@ -13,7 +13,7 @@ OQS_SIG *OQS_SIG_sphincs_sha256_128s_simple_new(void) { return NULL; } sig->method_name = OQS_SIG_alg_sphincs_sha256_128s_simple; - sig->alg_version = "https://github.com/sphincs/sphincsplus/commit/77755c94d0bc744478044d6efbb888dc13156441"; + sig->alg_version = "https://github.com/sphincs/sphincsplus/commit/ed15dd78658f63288c7492c00260d86154b84637"; sig->claimed_nist_level = 1; sig->euf_cma = true; @@ -29,14 +29,14 @@ OQS_SIG *OQS_SIG_sphincs_sha256_128s_simple_new(void) { return sig; } -extern int PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); -extern int PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); -extern int PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); +extern int PQCLEAN_SPHINCSSHA2128SSIMPLE_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); +extern int PQCLEAN_SPHINCSSHA2128SSIMPLE_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); +extern int PQCLEAN_SPHINCSSHA2128SSIMPLE_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); #if defined(OQS_ENABLE_SIG_sphincs_sha256_128s_simple_avx2) -extern int PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); -extern int PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); -extern int PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); +extern int PQCLEAN_SPHINCSSHA2128SSIMPLE_AVX2_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); +extern int PQCLEAN_SPHINCSSHA2128SSIMPLE_AVX2_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); +extern int PQCLEAN_SPHINCSSHA2128SSIMPLE_AVX2_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); #endif OQS_API OQS_STATUS OQS_SIG_sphincs_sha256_128s_simple_keypair(uint8_t *public_key, uint8_t *secret_key) { @@ -44,14 +44,14 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_sha256_128s_simple_keypair(uint8_t *public_ke #if defined(OQS_DIST_BUILD) if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) { #endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_crypto_sign_keypair(public_key, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHA2128SSIMPLE_AVX2_crypto_sign_keypair(public_key, secret_key); #if defined(OQS_DIST_BUILD) } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_crypto_sign_keypair(public_key, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHA2128SSIMPLE_CLEAN_crypto_sign_keypair(public_key, secret_key); } #endif /* OQS_DIST_BUILD */ #else - return (OQS_STATUS) PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_crypto_sign_keypair(public_key, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHA2128SSIMPLE_CLEAN_crypto_sign_keypair(public_key, secret_key); #endif } @@ -60,14 +60,14 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_sha256_128s_simple_sign(uint8_t *signature, s #if defined(OQS_DIST_BUILD) if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) { #endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHA2128SSIMPLE_AVX2_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); #if defined(OQS_DIST_BUILD) } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHA2128SSIMPLE_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); } #endif /* OQS_DIST_BUILD */ #else - return (OQS_STATUS) PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHA2128SSIMPLE_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); #endif } @@ -76,14 +76,14 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_sha256_128s_simple_verify(const uint8_t *mess #if defined(OQS_DIST_BUILD) if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) { #endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_crypto_sign_verify(signature, signature_len, message, message_len, public_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHA2128SSIMPLE_AVX2_crypto_sign_verify(signature, signature_len, message, message_len, public_key); #if defined(OQS_DIST_BUILD) } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHA2128SSIMPLE_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); } #endif /* OQS_DIST_BUILD */ #else - return (OQS_STATUS) PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHA2128SSIMPLE_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); #endif } diff --git a/src/sig/sphincs/sig_sphincs_sha256_192f_robust.c b/src/sig/sphincs/sig_sphincs_sha256_192f_robust.c index 2e2d26bef7..d0ebaed095 100644 --- a/src/sig/sphincs/sig_sphincs_sha256_192f_robust.c +++ b/src/sig/sphincs/sig_sphincs_sha256_192f_robust.c @@ -13,7 +13,7 @@ OQS_SIG *OQS_SIG_sphincs_sha256_192f_robust_new(void) { return NULL; } sig->method_name = OQS_SIG_alg_sphincs_sha256_192f_robust; - sig->alg_version = "https://github.com/sphincs/sphincsplus/commit/77755c94d0bc744478044d6efbb888dc13156441"; + sig->alg_version = "https://github.com/sphincs/sphincsplus/commit/ed15dd78658f63288c7492c00260d86154b84637"; sig->claimed_nist_level = 3; sig->euf_cma = true; @@ -29,14 +29,14 @@ OQS_SIG *OQS_SIG_sphincs_sha256_192f_robust_new(void) { return sig; } -extern int PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); -extern int PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); -extern int PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); +extern int PQCLEAN_SPHINCSSHA2192FROBUST_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); +extern int PQCLEAN_SPHINCSSHA2192FROBUST_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); +extern int PQCLEAN_SPHINCSSHA2192FROBUST_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); #if defined(OQS_ENABLE_SIG_sphincs_sha256_192f_robust_avx2) -extern int PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); -extern int PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); -extern int PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); +extern int PQCLEAN_SPHINCSSHA2192FROBUST_AVX2_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); +extern int PQCLEAN_SPHINCSSHA2192FROBUST_AVX2_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); +extern int PQCLEAN_SPHINCSSHA2192FROBUST_AVX2_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); #endif OQS_API OQS_STATUS OQS_SIG_sphincs_sha256_192f_robust_keypair(uint8_t *public_key, uint8_t *secret_key) { @@ -44,14 +44,14 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_sha256_192f_robust_keypair(uint8_t *public_ke #if defined(OQS_DIST_BUILD) if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) { #endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_crypto_sign_keypair(public_key, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHA2192FROBUST_AVX2_crypto_sign_keypair(public_key, secret_key); #if defined(OQS_DIST_BUILD) } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_crypto_sign_keypair(public_key, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHA2192FROBUST_CLEAN_crypto_sign_keypair(public_key, secret_key); } #endif /* OQS_DIST_BUILD */ #else - return (OQS_STATUS) PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_crypto_sign_keypair(public_key, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHA2192FROBUST_CLEAN_crypto_sign_keypair(public_key, secret_key); #endif } @@ -60,14 +60,14 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_sha256_192f_robust_sign(uint8_t *signature, s #if defined(OQS_DIST_BUILD) if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) { #endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHA2192FROBUST_AVX2_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); #if defined(OQS_DIST_BUILD) } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHA2192FROBUST_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); } #endif /* OQS_DIST_BUILD */ #else - return (OQS_STATUS) PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHA2192FROBUST_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); #endif } @@ -76,14 +76,14 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_sha256_192f_robust_verify(const uint8_t *mess #if defined(OQS_DIST_BUILD) if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) { #endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_crypto_sign_verify(signature, signature_len, message, message_len, public_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHA2192FROBUST_AVX2_crypto_sign_verify(signature, signature_len, message, message_len, public_key); #if defined(OQS_DIST_BUILD) } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHA2192FROBUST_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); } #endif /* OQS_DIST_BUILD */ #else - return (OQS_STATUS) PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHA2192FROBUST_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); #endif } diff --git a/src/sig/sphincs/sig_sphincs_sha256_192f_simple.c b/src/sig/sphincs/sig_sphincs_sha256_192f_simple.c index 808594e3ba..4a1800f600 100644 --- a/src/sig/sphincs/sig_sphincs_sha256_192f_simple.c +++ b/src/sig/sphincs/sig_sphincs_sha256_192f_simple.c @@ -13,7 +13,7 @@ OQS_SIG *OQS_SIG_sphincs_sha256_192f_simple_new(void) { return NULL; } sig->method_name = OQS_SIG_alg_sphincs_sha256_192f_simple; - sig->alg_version = "https://github.com/sphincs/sphincsplus/commit/77755c94d0bc744478044d6efbb888dc13156441"; + sig->alg_version = "https://github.com/sphincs/sphincsplus/commit/ed15dd78658f63288c7492c00260d86154b84637"; sig->claimed_nist_level = 3; sig->euf_cma = true; @@ -29,14 +29,14 @@ OQS_SIG *OQS_SIG_sphincs_sha256_192f_simple_new(void) { return sig; } -extern int PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); -extern int PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); -extern int PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); +extern int PQCLEAN_SPHINCSSHA2192FSIMPLE_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); +extern int PQCLEAN_SPHINCSSHA2192FSIMPLE_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); +extern int PQCLEAN_SPHINCSSHA2192FSIMPLE_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); #if defined(OQS_ENABLE_SIG_sphincs_sha256_192f_simple_avx2) -extern int PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); -extern int PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); -extern int PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); +extern int PQCLEAN_SPHINCSSHA2192FSIMPLE_AVX2_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); +extern int PQCLEAN_SPHINCSSHA2192FSIMPLE_AVX2_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); +extern int PQCLEAN_SPHINCSSHA2192FSIMPLE_AVX2_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); #endif OQS_API OQS_STATUS OQS_SIG_sphincs_sha256_192f_simple_keypair(uint8_t *public_key, uint8_t *secret_key) { @@ -44,14 +44,14 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_sha256_192f_simple_keypair(uint8_t *public_ke #if defined(OQS_DIST_BUILD) if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) { #endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_crypto_sign_keypair(public_key, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHA2192FSIMPLE_AVX2_crypto_sign_keypair(public_key, secret_key); #if defined(OQS_DIST_BUILD) } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_crypto_sign_keypair(public_key, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHA2192FSIMPLE_CLEAN_crypto_sign_keypair(public_key, secret_key); } #endif /* OQS_DIST_BUILD */ #else - return (OQS_STATUS) PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_crypto_sign_keypair(public_key, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHA2192FSIMPLE_CLEAN_crypto_sign_keypair(public_key, secret_key); #endif } @@ -60,14 +60,14 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_sha256_192f_simple_sign(uint8_t *signature, s #if defined(OQS_DIST_BUILD) if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) { #endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHA2192FSIMPLE_AVX2_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); #if defined(OQS_DIST_BUILD) } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHA2192FSIMPLE_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); } #endif /* OQS_DIST_BUILD */ #else - return (OQS_STATUS) PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHA2192FSIMPLE_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); #endif } @@ -76,14 +76,14 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_sha256_192f_simple_verify(const uint8_t *mess #if defined(OQS_DIST_BUILD) if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) { #endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_crypto_sign_verify(signature, signature_len, message, message_len, public_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHA2192FSIMPLE_AVX2_crypto_sign_verify(signature, signature_len, message, message_len, public_key); #if defined(OQS_DIST_BUILD) } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHA2192FSIMPLE_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); } #endif /* OQS_DIST_BUILD */ #else - return (OQS_STATUS) PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHA2192FSIMPLE_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); #endif } diff --git a/src/sig/sphincs/sig_sphincs_sha256_192s_robust.c b/src/sig/sphincs/sig_sphincs_sha256_192s_robust.c index b42ba27c38..09a60c0cc8 100644 --- a/src/sig/sphincs/sig_sphincs_sha256_192s_robust.c +++ b/src/sig/sphincs/sig_sphincs_sha256_192s_robust.c @@ -13,7 +13,7 @@ OQS_SIG *OQS_SIG_sphincs_sha256_192s_robust_new(void) { return NULL; } sig->method_name = OQS_SIG_alg_sphincs_sha256_192s_robust; - sig->alg_version = "https://github.com/sphincs/sphincsplus/commit/77755c94d0bc744478044d6efbb888dc13156441"; + sig->alg_version = "https://github.com/sphincs/sphincsplus/commit/ed15dd78658f63288c7492c00260d86154b84637"; sig->claimed_nist_level = 3; sig->euf_cma = true; @@ -29,14 +29,14 @@ OQS_SIG *OQS_SIG_sphincs_sha256_192s_robust_new(void) { return sig; } -extern int PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); -extern int PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); -extern int PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); +extern int PQCLEAN_SPHINCSSHA2192SROBUST_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); +extern int PQCLEAN_SPHINCSSHA2192SROBUST_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); +extern int PQCLEAN_SPHINCSSHA2192SROBUST_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); #if defined(OQS_ENABLE_SIG_sphincs_sha256_192s_robust_avx2) -extern int PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); -extern int PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); -extern int PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); +extern int PQCLEAN_SPHINCSSHA2192SROBUST_AVX2_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); +extern int PQCLEAN_SPHINCSSHA2192SROBUST_AVX2_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); +extern int PQCLEAN_SPHINCSSHA2192SROBUST_AVX2_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); #endif OQS_API OQS_STATUS OQS_SIG_sphincs_sha256_192s_robust_keypair(uint8_t *public_key, uint8_t *secret_key) { @@ -44,14 +44,14 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_sha256_192s_robust_keypair(uint8_t *public_ke #if defined(OQS_DIST_BUILD) if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) { #endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_crypto_sign_keypair(public_key, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHA2192SROBUST_AVX2_crypto_sign_keypair(public_key, secret_key); #if defined(OQS_DIST_BUILD) } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_crypto_sign_keypair(public_key, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHA2192SROBUST_CLEAN_crypto_sign_keypair(public_key, secret_key); } #endif /* OQS_DIST_BUILD */ #else - return (OQS_STATUS) PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_crypto_sign_keypair(public_key, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHA2192SROBUST_CLEAN_crypto_sign_keypair(public_key, secret_key); #endif } @@ -60,14 +60,14 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_sha256_192s_robust_sign(uint8_t *signature, s #if defined(OQS_DIST_BUILD) if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) { #endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHA2192SROBUST_AVX2_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); #if defined(OQS_DIST_BUILD) } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHA2192SROBUST_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); } #endif /* OQS_DIST_BUILD */ #else - return (OQS_STATUS) PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHA2192SROBUST_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); #endif } @@ -76,14 +76,14 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_sha256_192s_robust_verify(const uint8_t *mess #if defined(OQS_DIST_BUILD) if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) { #endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_crypto_sign_verify(signature, signature_len, message, message_len, public_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHA2192SROBUST_AVX2_crypto_sign_verify(signature, signature_len, message, message_len, public_key); #if defined(OQS_DIST_BUILD) } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHA2192SROBUST_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); } #endif /* OQS_DIST_BUILD */ #else - return (OQS_STATUS) PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHA2192SROBUST_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); #endif } diff --git a/src/sig/sphincs/sig_sphincs_sha256_192s_simple.c b/src/sig/sphincs/sig_sphincs_sha256_192s_simple.c index dacd7555f8..97c17871e9 100644 --- a/src/sig/sphincs/sig_sphincs_sha256_192s_simple.c +++ b/src/sig/sphincs/sig_sphincs_sha256_192s_simple.c @@ -13,7 +13,7 @@ OQS_SIG *OQS_SIG_sphincs_sha256_192s_simple_new(void) { return NULL; } sig->method_name = OQS_SIG_alg_sphincs_sha256_192s_simple; - sig->alg_version = "https://github.com/sphincs/sphincsplus/commit/77755c94d0bc744478044d6efbb888dc13156441"; + sig->alg_version = "https://github.com/sphincs/sphincsplus/commit/ed15dd78658f63288c7492c00260d86154b84637"; sig->claimed_nist_level = 3; sig->euf_cma = true; @@ -29,14 +29,14 @@ OQS_SIG *OQS_SIG_sphincs_sha256_192s_simple_new(void) { return sig; } -extern int PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); -extern int PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); -extern int PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); +extern int PQCLEAN_SPHINCSSHA2192SSIMPLE_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); +extern int PQCLEAN_SPHINCSSHA2192SSIMPLE_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); +extern int PQCLEAN_SPHINCSSHA2192SSIMPLE_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); #if defined(OQS_ENABLE_SIG_sphincs_sha256_192s_simple_avx2) -extern int PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); -extern int PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); -extern int PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); +extern int PQCLEAN_SPHINCSSHA2192SSIMPLE_AVX2_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); +extern int PQCLEAN_SPHINCSSHA2192SSIMPLE_AVX2_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); +extern int PQCLEAN_SPHINCSSHA2192SSIMPLE_AVX2_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); #endif OQS_API OQS_STATUS OQS_SIG_sphincs_sha256_192s_simple_keypair(uint8_t *public_key, uint8_t *secret_key) { @@ -44,14 +44,14 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_sha256_192s_simple_keypair(uint8_t *public_ke #if defined(OQS_DIST_BUILD) if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) { #endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_crypto_sign_keypair(public_key, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHA2192SSIMPLE_AVX2_crypto_sign_keypair(public_key, secret_key); #if defined(OQS_DIST_BUILD) } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_crypto_sign_keypair(public_key, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHA2192SSIMPLE_CLEAN_crypto_sign_keypair(public_key, secret_key); } #endif /* OQS_DIST_BUILD */ #else - return (OQS_STATUS) PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_crypto_sign_keypair(public_key, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHA2192SSIMPLE_CLEAN_crypto_sign_keypair(public_key, secret_key); #endif } @@ -60,14 +60,14 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_sha256_192s_simple_sign(uint8_t *signature, s #if defined(OQS_DIST_BUILD) if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) { #endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHA2192SSIMPLE_AVX2_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); #if defined(OQS_DIST_BUILD) } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHA2192SSIMPLE_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); } #endif /* OQS_DIST_BUILD */ #else - return (OQS_STATUS) PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHA2192SSIMPLE_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); #endif } @@ -76,14 +76,14 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_sha256_192s_simple_verify(const uint8_t *mess #if defined(OQS_DIST_BUILD) if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) { #endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_crypto_sign_verify(signature, signature_len, message, message_len, public_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHA2192SSIMPLE_AVX2_crypto_sign_verify(signature, signature_len, message, message_len, public_key); #if defined(OQS_DIST_BUILD) } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHA2192SSIMPLE_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); } #endif /* OQS_DIST_BUILD */ #else - return (OQS_STATUS) PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHA2192SSIMPLE_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); #endif } diff --git a/src/sig/sphincs/sig_sphincs_sha256_256f_robust.c b/src/sig/sphincs/sig_sphincs_sha256_256f_robust.c index 367480a0f1..0798e77d52 100644 --- a/src/sig/sphincs/sig_sphincs_sha256_256f_robust.c +++ b/src/sig/sphincs/sig_sphincs_sha256_256f_robust.c @@ -13,7 +13,7 @@ OQS_SIG *OQS_SIG_sphincs_sha256_256f_robust_new(void) { return NULL; } sig->method_name = OQS_SIG_alg_sphincs_sha256_256f_robust; - sig->alg_version = "https://github.com/sphincs/sphincsplus/commit/77755c94d0bc744478044d6efbb888dc13156441"; + sig->alg_version = "https://github.com/sphincs/sphincsplus/commit/ed15dd78658f63288c7492c00260d86154b84637"; sig->claimed_nist_level = 5; sig->euf_cma = true; @@ -29,14 +29,14 @@ OQS_SIG *OQS_SIG_sphincs_sha256_256f_robust_new(void) { return sig; } -extern int PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); -extern int PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); -extern int PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); +extern int PQCLEAN_SPHINCSSHA2256FROBUST_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); +extern int PQCLEAN_SPHINCSSHA2256FROBUST_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); +extern int PQCLEAN_SPHINCSSHA2256FROBUST_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); #if defined(OQS_ENABLE_SIG_sphincs_sha256_256f_robust_avx2) -extern int PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); -extern int PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); -extern int PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); +extern int PQCLEAN_SPHINCSSHA2256FROBUST_AVX2_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); +extern int PQCLEAN_SPHINCSSHA2256FROBUST_AVX2_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); +extern int PQCLEAN_SPHINCSSHA2256FROBUST_AVX2_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); #endif OQS_API OQS_STATUS OQS_SIG_sphincs_sha256_256f_robust_keypair(uint8_t *public_key, uint8_t *secret_key) { @@ -44,14 +44,14 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_sha256_256f_robust_keypair(uint8_t *public_ke #if defined(OQS_DIST_BUILD) if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) { #endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_crypto_sign_keypair(public_key, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHA2256FROBUST_AVX2_crypto_sign_keypair(public_key, secret_key); #if defined(OQS_DIST_BUILD) } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_crypto_sign_keypair(public_key, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHA2256FROBUST_CLEAN_crypto_sign_keypair(public_key, secret_key); } #endif /* OQS_DIST_BUILD */ #else - return (OQS_STATUS) PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_crypto_sign_keypair(public_key, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHA2256FROBUST_CLEAN_crypto_sign_keypair(public_key, secret_key); #endif } @@ -60,14 +60,14 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_sha256_256f_robust_sign(uint8_t *signature, s #if defined(OQS_DIST_BUILD) if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) { #endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHA2256FROBUST_AVX2_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); #if defined(OQS_DIST_BUILD) } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHA2256FROBUST_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); } #endif /* OQS_DIST_BUILD */ #else - return (OQS_STATUS) PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHA2256FROBUST_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); #endif } @@ -76,14 +76,14 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_sha256_256f_robust_verify(const uint8_t *mess #if defined(OQS_DIST_BUILD) if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) { #endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_crypto_sign_verify(signature, signature_len, message, message_len, public_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHA2256FROBUST_AVX2_crypto_sign_verify(signature, signature_len, message, message_len, public_key); #if defined(OQS_DIST_BUILD) } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHA2256FROBUST_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); } #endif /* OQS_DIST_BUILD */ #else - return (OQS_STATUS) PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHA2256FROBUST_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); #endif } diff --git a/src/sig/sphincs/sig_sphincs_sha256_256f_simple.c b/src/sig/sphincs/sig_sphincs_sha256_256f_simple.c index e04bfe3834..9409f48a0a 100644 --- a/src/sig/sphincs/sig_sphincs_sha256_256f_simple.c +++ b/src/sig/sphincs/sig_sphincs_sha256_256f_simple.c @@ -13,7 +13,7 @@ OQS_SIG *OQS_SIG_sphincs_sha256_256f_simple_new(void) { return NULL; } sig->method_name = OQS_SIG_alg_sphincs_sha256_256f_simple; - sig->alg_version = "https://github.com/sphincs/sphincsplus/commit/77755c94d0bc744478044d6efbb888dc13156441"; + sig->alg_version = "https://github.com/sphincs/sphincsplus/commit/ed15dd78658f63288c7492c00260d86154b84637"; sig->claimed_nist_level = 5; sig->euf_cma = true; @@ -29,14 +29,14 @@ OQS_SIG *OQS_SIG_sphincs_sha256_256f_simple_new(void) { return sig; } -extern int PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); -extern int PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); -extern int PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); +extern int PQCLEAN_SPHINCSSHA2256FSIMPLE_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); +extern int PQCLEAN_SPHINCSSHA2256FSIMPLE_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); +extern int PQCLEAN_SPHINCSSHA2256FSIMPLE_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); #if defined(OQS_ENABLE_SIG_sphincs_sha256_256f_simple_avx2) -extern int PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); -extern int PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); -extern int PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); +extern int PQCLEAN_SPHINCSSHA2256FSIMPLE_AVX2_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); +extern int PQCLEAN_SPHINCSSHA2256FSIMPLE_AVX2_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); +extern int PQCLEAN_SPHINCSSHA2256FSIMPLE_AVX2_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); #endif OQS_API OQS_STATUS OQS_SIG_sphincs_sha256_256f_simple_keypair(uint8_t *public_key, uint8_t *secret_key) { @@ -44,14 +44,14 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_sha256_256f_simple_keypair(uint8_t *public_ke #if defined(OQS_DIST_BUILD) if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) { #endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_crypto_sign_keypair(public_key, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHA2256FSIMPLE_AVX2_crypto_sign_keypair(public_key, secret_key); #if defined(OQS_DIST_BUILD) } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_crypto_sign_keypair(public_key, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHA2256FSIMPLE_CLEAN_crypto_sign_keypair(public_key, secret_key); } #endif /* OQS_DIST_BUILD */ #else - return (OQS_STATUS) PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_crypto_sign_keypair(public_key, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHA2256FSIMPLE_CLEAN_crypto_sign_keypair(public_key, secret_key); #endif } @@ -60,14 +60,14 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_sha256_256f_simple_sign(uint8_t *signature, s #if defined(OQS_DIST_BUILD) if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) { #endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHA2256FSIMPLE_AVX2_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); #if defined(OQS_DIST_BUILD) } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHA2256FSIMPLE_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); } #endif /* OQS_DIST_BUILD */ #else - return (OQS_STATUS) PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHA2256FSIMPLE_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); #endif } @@ -76,14 +76,14 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_sha256_256f_simple_verify(const uint8_t *mess #if defined(OQS_DIST_BUILD) if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) { #endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_crypto_sign_verify(signature, signature_len, message, message_len, public_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHA2256FSIMPLE_AVX2_crypto_sign_verify(signature, signature_len, message, message_len, public_key); #if defined(OQS_DIST_BUILD) } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHA2256FSIMPLE_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); } #endif /* OQS_DIST_BUILD */ #else - return (OQS_STATUS) PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHA2256FSIMPLE_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); #endif } diff --git a/src/sig/sphincs/sig_sphincs_sha256_256s_robust.c b/src/sig/sphincs/sig_sphincs_sha256_256s_robust.c index 80d342d78d..f2b4ae772e 100644 --- a/src/sig/sphincs/sig_sphincs_sha256_256s_robust.c +++ b/src/sig/sphincs/sig_sphincs_sha256_256s_robust.c @@ -13,7 +13,7 @@ OQS_SIG *OQS_SIG_sphincs_sha256_256s_robust_new(void) { return NULL; } sig->method_name = OQS_SIG_alg_sphincs_sha256_256s_robust; - sig->alg_version = "https://github.com/sphincs/sphincsplus/commit/77755c94d0bc744478044d6efbb888dc13156441"; + sig->alg_version = "https://github.com/sphincs/sphincsplus/commit/ed15dd78658f63288c7492c00260d86154b84637"; sig->claimed_nist_level = 5; sig->euf_cma = true; @@ -29,14 +29,14 @@ OQS_SIG *OQS_SIG_sphincs_sha256_256s_robust_new(void) { return sig; } -extern int PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); -extern int PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); -extern int PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); +extern int PQCLEAN_SPHINCSSHA2256SROBUST_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); +extern int PQCLEAN_SPHINCSSHA2256SROBUST_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); +extern int PQCLEAN_SPHINCSSHA2256SROBUST_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); #if defined(OQS_ENABLE_SIG_sphincs_sha256_256s_robust_avx2) -extern int PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); -extern int PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); -extern int PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); +extern int PQCLEAN_SPHINCSSHA2256SROBUST_AVX2_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); +extern int PQCLEAN_SPHINCSSHA2256SROBUST_AVX2_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); +extern int PQCLEAN_SPHINCSSHA2256SROBUST_AVX2_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); #endif OQS_API OQS_STATUS OQS_SIG_sphincs_sha256_256s_robust_keypair(uint8_t *public_key, uint8_t *secret_key) { @@ -44,14 +44,14 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_sha256_256s_robust_keypair(uint8_t *public_ke #if defined(OQS_DIST_BUILD) if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) { #endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_crypto_sign_keypair(public_key, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHA2256SROBUST_AVX2_crypto_sign_keypair(public_key, secret_key); #if defined(OQS_DIST_BUILD) } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_crypto_sign_keypair(public_key, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHA2256SROBUST_CLEAN_crypto_sign_keypair(public_key, secret_key); } #endif /* OQS_DIST_BUILD */ #else - return (OQS_STATUS) PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_crypto_sign_keypair(public_key, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHA2256SROBUST_CLEAN_crypto_sign_keypair(public_key, secret_key); #endif } @@ -60,14 +60,14 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_sha256_256s_robust_sign(uint8_t *signature, s #if defined(OQS_DIST_BUILD) if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) { #endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHA2256SROBUST_AVX2_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); #if defined(OQS_DIST_BUILD) } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHA2256SROBUST_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); } #endif /* OQS_DIST_BUILD */ #else - return (OQS_STATUS) PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHA2256SROBUST_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); #endif } @@ -76,14 +76,14 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_sha256_256s_robust_verify(const uint8_t *mess #if defined(OQS_DIST_BUILD) if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) { #endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_crypto_sign_verify(signature, signature_len, message, message_len, public_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHA2256SROBUST_AVX2_crypto_sign_verify(signature, signature_len, message, message_len, public_key); #if defined(OQS_DIST_BUILD) } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHA2256SROBUST_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); } #endif /* OQS_DIST_BUILD */ #else - return (OQS_STATUS) PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHA2256SROBUST_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); #endif } diff --git a/src/sig/sphincs/sig_sphincs_sha256_256s_simple.c b/src/sig/sphincs/sig_sphincs_sha256_256s_simple.c index 71e6d0978e..9da0e3a88c 100644 --- a/src/sig/sphincs/sig_sphincs_sha256_256s_simple.c +++ b/src/sig/sphincs/sig_sphincs_sha256_256s_simple.c @@ -13,7 +13,7 @@ OQS_SIG *OQS_SIG_sphincs_sha256_256s_simple_new(void) { return NULL; } sig->method_name = OQS_SIG_alg_sphincs_sha256_256s_simple; - sig->alg_version = "https://github.com/sphincs/sphincsplus/commit/77755c94d0bc744478044d6efbb888dc13156441"; + sig->alg_version = "https://github.com/sphincs/sphincsplus/commit/ed15dd78658f63288c7492c00260d86154b84637"; sig->claimed_nist_level = 5; sig->euf_cma = true; @@ -29,14 +29,14 @@ OQS_SIG *OQS_SIG_sphincs_sha256_256s_simple_new(void) { return sig; } -extern int PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); -extern int PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); -extern int PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); +extern int PQCLEAN_SPHINCSSHA2256SSIMPLE_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); +extern int PQCLEAN_SPHINCSSHA2256SSIMPLE_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); +extern int PQCLEAN_SPHINCSSHA2256SSIMPLE_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); #if defined(OQS_ENABLE_SIG_sphincs_sha256_256s_simple_avx2) -extern int PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); -extern int PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); -extern int PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); +extern int PQCLEAN_SPHINCSSHA2256SSIMPLE_AVX2_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); +extern int PQCLEAN_SPHINCSSHA2256SSIMPLE_AVX2_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); +extern int PQCLEAN_SPHINCSSHA2256SSIMPLE_AVX2_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); #endif OQS_API OQS_STATUS OQS_SIG_sphincs_sha256_256s_simple_keypair(uint8_t *public_key, uint8_t *secret_key) { @@ -44,14 +44,14 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_sha256_256s_simple_keypair(uint8_t *public_ke #if defined(OQS_DIST_BUILD) if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) { #endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_crypto_sign_keypair(public_key, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHA2256SSIMPLE_AVX2_crypto_sign_keypair(public_key, secret_key); #if defined(OQS_DIST_BUILD) } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_crypto_sign_keypair(public_key, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHA2256SSIMPLE_CLEAN_crypto_sign_keypair(public_key, secret_key); } #endif /* OQS_DIST_BUILD */ #else - return (OQS_STATUS) PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_crypto_sign_keypair(public_key, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHA2256SSIMPLE_CLEAN_crypto_sign_keypair(public_key, secret_key); #endif } @@ -60,14 +60,14 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_sha256_256s_simple_sign(uint8_t *signature, s #if defined(OQS_DIST_BUILD) if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) { #endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHA2256SSIMPLE_AVX2_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); #if defined(OQS_DIST_BUILD) } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHA2256SSIMPLE_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); } #endif /* OQS_DIST_BUILD */ #else - return (OQS_STATUS) PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHA2256SSIMPLE_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); #endif } @@ -76,14 +76,14 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_sha256_256s_simple_verify(const uint8_t *mess #if defined(OQS_DIST_BUILD) if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) { #endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_crypto_sign_verify(signature, signature_len, message, message_len, public_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHA2256SSIMPLE_AVX2_crypto_sign_verify(signature, signature_len, message, message_len, public_key); #if defined(OQS_DIST_BUILD) } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHA2256SSIMPLE_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); } #endif /* OQS_DIST_BUILD */ #else - return (OQS_STATUS) PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHA2256SSIMPLE_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); #endif } diff --git a/src/sig/sphincs/sig_sphincs_shake256_128f_robust.c b/src/sig/sphincs/sig_sphincs_shake256_128f_robust.c index 0d1731738b..af9e1bcf18 100644 --- a/src/sig/sphincs/sig_sphincs_shake256_128f_robust.c +++ b/src/sig/sphincs/sig_sphincs_shake256_128f_robust.c @@ -13,7 +13,7 @@ OQS_SIG *OQS_SIG_sphincs_shake256_128f_robust_new(void) { return NULL; } sig->method_name = OQS_SIG_alg_sphincs_shake256_128f_robust; - sig->alg_version = "https://github.com/sphincs/sphincsplus/commit/77755c94d0bc744478044d6efbb888dc13156441"; + sig->alg_version = "https://github.com/sphincs/sphincsplus/commit/ed15dd78658f63288c7492c00260d86154b84637"; sig->claimed_nist_level = 1; sig->euf_cma = true; @@ -29,14 +29,20 @@ OQS_SIG *OQS_SIG_sphincs_shake256_128f_robust_new(void) { return sig; } -extern int PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); -extern int PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); -extern int PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); +extern int PQCLEAN_SPHINCSSHAKE128FROBUST_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); +extern int PQCLEAN_SPHINCSSHAKE128FROBUST_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); +extern int PQCLEAN_SPHINCSSHAKE128FROBUST_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); #if defined(OQS_ENABLE_SIG_sphincs_shake256_128f_robust_avx2) -extern int PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); -extern int PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); -extern int PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); +extern int PQCLEAN_SPHINCSSHAKE128FROBUST_AVX2_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); +extern int PQCLEAN_SPHINCSSHAKE128FROBUST_AVX2_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); +extern int PQCLEAN_SPHINCSSHAKE128FROBUST_AVX2_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); +#endif + +#if defined(OQS_ENABLE_SIG_sphincs_shake256_128f_robust_aarch64) +extern int PQCLEAN_SPHINCSSHAKE128FROBUST_AARCH64_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); +extern int PQCLEAN_SPHINCSSHAKE128FROBUST_AARCH64_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); +extern int PQCLEAN_SPHINCSSHAKE128FROBUST_AARCH64_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); #endif OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_128f_robust_keypair(uint8_t *public_key, uint8_t *secret_key) { @@ -44,14 +50,24 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_128f_robust_keypair(uint8_t *public_ #if defined(OQS_DIST_BUILD) if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) { #endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_crypto_sign_keypair(public_key, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE128FROBUST_AVX2_crypto_sign_keypair(public_key, secret_key); +#if defined(OQS_DIST_BUILD) + } else { + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE128FROBUST_CLEAN_crypto_sign_keypair(public_key, secret_key); + } +#endif /* OQS_DIST_BUILD */ +#elif defined(OQS_ENABLE_SIG_sphincs_shake256_128f_robust_aarch64) +#if defined(OQS_DIST_BUILD) + if (OQS_CPU_has_extension(OQS_CPU_EXT_SHA3)) { +#endif /* OQS_DIST_BUILD */ + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE128FROBUST_AARCH64_crypto_sign_keypair(public_key, secret_key); #if defined(OQS_DIST_BUILD) } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_crypto_sign_keypair(public_key, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE128FROBUST_CLEAN_crypto_sign_keypair(public_key, secret_key); } #endif /* OQS_DIST_BUILD */ #else - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_crypto_sign_keypair(public_key, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE128FROBUST_CLEAN_crypto_sign_keypair(public_key, secret_key); #endif } @@ -60,14 +76,24 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_128f_robust_sign(uint8_t *signature, #if defined(OQS_DIST_BUILD) if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) { #endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE128FROBUST_AVX2_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); +#if defined(OQS_DIST_BUILD) + } else { + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE128FROBUST_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); + } +#endif /* OQS_DIST_BUILD */ +#elif defined(OQS_ENABLE_SIG_sphincs_shake256_128f_robust_aarch64) +#if defined(OQS_DIST_BUILD) + if (OQS_CPU_has_extension(OQS_CPU_EXT_SHA3)) { +#endif /* OQS_DIST_BUILD */ + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE128FROBUST_AARCH64_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); #if defined(OQS_DIST_BUILD) } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE128FROBUST_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); } #endif /* OQS_DIST_BUILD */ #else - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE128FROBUST_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); #endif } @@ -76,14 +102,24 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_128f_robust_verify(const uint8_t *me #if defined(OQS_DIST_BUILD) if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) { #endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_crypto_sign_verify(signature, signature_len, message, message_len, public_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE128FROBUST_AVX2_crypto_sign_verify(signature, signature_len, message, message_len, public_key); +#if defined(OQS_DIST_BUILD) + } else { + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE128FROBUST_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); + } +#endif /* OQS_DIST_BUILD */ +#elif defined(OQS_ENABLE_SIG_sphincs_shake256_128f_robust_aarch64) +#if defined(OQS_DIST_BUILD) + if (OQS_CPU_has_extension(OQS_CPU_EXT_SHA3)) { +#endif /* OQS_DIST_BUILD */ + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE128FROBUST_AARCH64_crypto_sign_verify(signature, signature_len, message, message_len, public_key); #if defined(OQS_DIST_BUILD) } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE128FROBUST_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); } #endif /* OQS_DIST_BUILD */ #else - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE128FROBUST_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); #endif } diff --git a/src/sig/sphincs/sig_sphincs_shake256_128f_simple.c b/src/sig/sphincs/sig_sphincs_shake256_128f_simple.c index d04c00020d..aa1a01d2fb 100644 --- a/src/sig/sphincs/sig_sphincs_shake256_128f_simple.c +++ b/src/sig/sphincs/sig_sphincs_shake256_128f_simple.c @@ -13,7 +13,7 @@ OQS_SIG *OQS_SIG_sphincs_shake256_128f_simple_new(void) { return NULL; } sig->method_name = OQS_SIG_alg_sphincs_shake256_128f_simple; - sig->alg_version = "https://github.com/sphincs/sphincsplus/commit/77755c94d0bc744478044d6efbb888dc13156441"; + sig->alg_version = "https://github.com/sphincs/sphincsplus/commit/ed15dd78658f63288c7492c00260d86154b84637"; sig->claimed_nist_level = 1; sig->euf_cma = true; @@ -29,14 +29,20 @@ OQS_SIG *OQS_SIG_sphincs_shake256_128f_simple_new(void) { return sig; } -extern int PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); -extern int PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); -extern int PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); +extern int PQCLEAN_SPHINCSSHAKE128FSIMPLE_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); +extern int PQCLEAN_SPHINCSSHAKE128FSIMPLE_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); +extern int PQCLEAN_SPHINCSSHAKE128FSIMPLE_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); #if defined(OQS_ENABLE_SIG_sphincs_shake256_128f_simple_avx2) -extern int PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); -extern int PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); -extern int PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); +extern int PQCLEAN_SPHINCSSHAKE128FSIMPLE_AVX2_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); +extern int PQCLEAN_SPHINCSSHAKE128FSIMPLE_AVX2_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); +extern int PQCLEAN_SPHINCSSHAKE128FSIMPLE_AVX2_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); +#endif + +#if defined(OQS_ENABLE_SIG_sphincs_shake256_128f_simple_aarch64) +extern int PQCLEAN_SPHINCSSHAKE128FSIMPLE_AARCH64_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); +extern int PQCLEAN_SPHINCSSHAKE128FSIMPLE_AARCH64_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); +extern int PQCLEAN_SPHINCSSHAKE128FSIMPLE_AARCH64_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); #endif OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_128f_simple_keypair(uint8_t *public_key, uint8_t *secret_key) { @@ -44,14 +50,24 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_128f_simple_keypair(uint8_t *public_ #if defined(OQS_DIST_BUILD) if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) { #endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_crypto_sign_keypair(public_key, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE128FSIMPLE_AVX2_crypto_sign_keypair(public_key, secret_key); +#if defined(OQS_DIST_BUILD) + } else { + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE128FSIMPLE_CLEAN_crypto_sign_keypair(public_key, secret_key); + } +#endif /* OQS_DIST_BUILD */ +#elif defined(OQS_ENABLE_SIG_sphincs_shake256_128f_simple_aarch64) +#if defined(OQS_DIST_BUILD) + if (OQS_CPU_has_extension(OQS_CPU_EXT_SHA3)) { +#endif /* OQS_DIST_BUILD */ + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE128FSIMPLE_AARCH64_crypto_sign_keypair(public_key, secret_key); #if defined(OQS_DIST_BUILD) } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_crypto_sign_keypair(public_key, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE128FSIMPLE_CLEAN_crypto_sign_keypair(public_key, secret_key); } #endif /* OQS_DIST_BUILD */ #else - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_crypto_sign_keypair(public_key, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE128FSIMPLE_CLEAN_crypto_sign_keypair(public_key, secret_key); #endif } @@ -60,14 +76,24 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_128f_simple_sign(uint8_t *signature, #if defined(OQS_DIST_BUILD) if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) { #endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE128FSIMPLE_AVX2_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); +#if defined(OQS_DIST_BUILD) + } else { + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE128FSIMPLE_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); + } +#endif /* OQS_DIST_BUILD */ +#elif defined(OQS_ENABLE_SIG_sphincs_shake256_128f_simple_aarch64) +#if defined(OQS_DIST_BUILD) + if (OQS_CPU_has_extension(OQS_CPU_EXT_SHA3)) { +#endif /* OQS_DIST_BUILD */ + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE128FSIMPLE_AARCH64_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); #if defined(OQS_DIST_BUILD) } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE128FSIMPLE_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); } #endif /* OQS_DIST_BUILD */ #else - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE128FSIMPLE_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); #endif } @@ -76,14 +102,24 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_128f_simple_verify(const uint8_t *me #if defined(OQS_DIST_BUILD) if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) { #endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_crypto_sign_verify(signature, signature_len, message, message_len, public_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE128FSIMPLE_AVX2_crypto_sign_verify(signature, signature_len, message, message_len, public_key); +#if defined(OQS_DIST_BUILD) + } else { + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE128FSIMPLE_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); + } +#endif /* OQS_DIST_BUILD */ +#elif defined(OQS_ENABLE_SIG_sphincs_shake256_128f_simple_aarch64) +#if defined(OQS_DIST_BUILD) + if (OQS_CPU_has_extension(OQS_CPU_EXT_SHA3)) { +#endif /* OQS_DIST_BUILD */ + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE128FSIMPLE_AARCH64_crypto_sign_verify(signature, signature_len, message, message_len, public_key); #if defined(OQS_DIST_BUILD) } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE128FSIMPLE_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); } #endif /* OQS_DIST_BUILD */ #else - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE128FSIMPLE_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); #endif } diff --git a/src/sig/sphincs/sig_sphincs_shake256_128s_robust.c b/src/sig/sphincs/sig_sphincs_shake256_128s_robust.c index 69990e8f6d..0561673341 100644 --- a/src/sig/sphincs/sig_sphincs_shake256_128s_robust.c +++ b/src/sig/sphincs/sig_sphincs_shake256_128s_robust.c @@ -13,7 +13,7 @@ OQS_SIG *OQS_SIG_sphincs_shake256_128s_robust_new(void) { return NULL; } sig->method_name = OQS_SIG_alg_sphincs_shake256_128s_robust; - sig->alg_version = "https://github.com/sphincs/sphincsplus/commit/77755c94d0bc744478044d6efbb888dc13156441"; + sig->alg_version = "https://github.com/sphincs/sphincsplus/commit/ed15dd78658f63288c7492c00260d86154b84637"; sig->claimed_nist_level = 1; sig->euf_cma = true; @@ -29,14 +29,20 @@ OQS_SIG *OQS_SIG_sphincs_shake256_128s_robust_new(void) { return sig; } -extern int PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); -extern int PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); -extern int PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); +extern int PQCLEAN_SPHINCSSHAKE128SROBUST_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); +extern int PQCLEAN_SPHINCSSHAKE128SROBUST_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); +extern int PQCLEAN_SPHINCSSHAKE128SROBUST_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); #if defined(OQS_ENABLE_SIG_sphincs_shake256_128s_robust_avx2) -extern int PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); -extern int PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); -extern int PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); +extern int PQCLEAN_SPHINCSSHAKE128SROBUST_AVX2_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); +extern int PQCLEAN_SPHINCSSHAKE128SROBUST_AVX2_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); +extern int PQCLEAN_SPHINCSSHAKE128SROBUST_AVX2_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); +#endif + +#if defined(OQS_ENABLE_SIG_sphincs_shake256_128s_robust_aarch64) +extern int PQCLEAN_SPHINCSSHAKE128SROBUST_AARCH64_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); +extern int PQCLEAN_SPHINCSSHAKE128SROBUST_AARCH64_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); +extern int PQCLEAN_SPHINCSSHAKE128SROBUST_AARCH64_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); #endif OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_128s_robust_keypair(uint8_t *public_key, uint8_t *secret_key) { @@ -44,14 +50,24 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_128s_robust_keypair(uint8_t *public_ #if defined(OQS_DIST_BUILD) if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) { #endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_crypto_sign_keypair(public_key, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE128SROBUST_AVX2_crypto_sign_keypair(public_key, secret_key); +#if defined(OQS_DIST_BUILD) + } else { + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE128SROBUST_CLEAN_crypto_sign_keypair(public_key, secret_key); + } +#endif /* OQS_DIST_BUILD */ +#elif defined(OQS_ENABLE_SIG_sphincs_shake256_128s_robust_aarch64) +#if defined(OQS_DIST_BUILD) + if (OQS_CPU_has_extension(OQS_CPU_EXT_SHA3)) { +#endif /* OQS_DIST_BUILD */ + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE128SROBUST_AARCH64_crypto_sign_keypair(public_key, secret_key); #if defined(OQS_DIST_BUILD) } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_crypto_sign_keypair(public_key, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE128SROBUST_CLEAN_crypto_sign_keypair(public_key, secret_key); } #endif /* OQS_DIST_BUILD */ #else - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_crypto_sign_keypair(public_key, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE128SROBUST_CLEAN_crypto_sign_keypair(public_key, secret_key); #endif } @@ -60,14 +76,24 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_128s_robust_sign(uint8_t *signature, #if defined(OQS_DIST_BUILD) if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) { #endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE128SROBUST_AVX2_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); +#if defined(OQS_DIST_BUILD) + } else { + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE128SROBUST_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); + } +#endif /* OQS_DIST_BUILD */ +#elif defined(OQS_ENABLE_SIG_sphincs_shake256_128s_robust_aarch64) +#if defined(OQS_DIST_BUILD) + if (OQS_CPU_has_extension(OQS_CPU_EXT_SHA3)) { +#endif /* OQS_DIST_BUILD */ + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE128SROBUST_AARCH64_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); #if defined(OQS_DIST_BUILD) } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE128SROBUST_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); } #endif /* OQS_DIST_BUILD */ #else - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE128SROBUST_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); #endif } @@ -76,14 +102,24 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_128s_robust_verify(const uint8_t *me #if defined(OQS_DIST_BUILD) if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) { #endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_crypto_sign_verify(signature, signature_len, message, message_len, public_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE128SROBUST_AVX2_crypto_sign_verify(signature, signature_len, message, message_len, public_key); +#if defined(OQS_DIST_BUILD) + } else { + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE128SROBUST_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); + } +#endif /* OQS_DIST_BUILD */ +#elif defined(OQS_ENABLE_SIG_sphincs_shake256_128s_robust_aarch64) +#if defined(OQS_DIST_BUILD) + if (OQS_CPU_has_extension(OQS_CPU_EXT_SHA3)) { +#endif /* OQS_DIST_BUILD */ + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE128SROBUST_AARCH64_crypto_sign_verify(signature, signature_len, message, message_len, public_key); #if defined(OQS_DIST_BUILD) } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE128SROBUST_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); } #endif /* OQS_DIST_BUILD */ #else - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE128SROBUST_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); #endif } diff --git a/src/sig/sphincs/sig_sphincs_shake256_128s_simple.c b/src/sig/sphincs/sig_sphincs_shake256_128s_simple.c index 716b0c142b..c636dcf800 100644 --- a/src/sig/sphincs/sig_sphincs_shake256_128s_simple.c +++ b/src/sig/sphincs/sig_sphincs_shake256_128s_simple.c @@ -13,7 +13,7 @@ OQS_SIG *OQS_SIG_sphincs_shake256_128s_simple_new(void) { return NULL; } sig->method_name = OQS_SIG_alg_sphincs_shake256_128s_simple; - sig->alg_version = "https://github.com/sphincs/sphincsplus/commit/77755c94d0bc744478044d6efbb888dc13156441"; + sig->alg_version = "https://github.com/sphincs/sphincsplus/commit/ed15dd78658f63288c7492c00260d86154b84637"; sig->claimed_nist_level = 1; sig->euf_cma = true; @@ -29,14 +29,20 @@ OQS_SIG *OQS_SIG_sphincs_shake256_128s_simple_new(void) { return sig; } -extern int PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); -extern int PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); -extern int PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); +extern int PQCLEAN_SPHINCSSHAKE128SSIMPLE_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); +extern int PQCLEAN_SPHINCSSHAKE128SSIMPLE_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); +extern int PQCLEAN_SPHINCSSHAKE128SSIMPLE_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); #if defined(OQS_ENABLE_SIG_sphincs_shake256_128s_simple_avx2) -extern int PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); -extern int PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); -extern int PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); +extern int PQCLEAN_SPHINCSSHAKE128SSIMPLE_AVX2_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); +extern int PQCLEAN_SPHINCSSHAKE128SSIMPLE_AVX2_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); +extern int PQCLEAN_SPHINCSSHAKE128SSIMPLE_AVX2_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); +#endif + +#if defined(OQS_ENABLE_SIG_sphincs_shake256_128s_simple_aarch64) +extern int PQCLEAN_SPHINCSSHAKE128SSIMPLE_AARCH64_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); +extern int PQCLEAN_SPHINCSSHAKE128SSIMPLE_AARCH64_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); +extern int PQCLEAN_SPHINCSSHAKE128SSIMPLE_AARCH64_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); #endif OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_128s_simple_keypair(uint8_t *public_key, uint8_t *secret_key) { @@ -44,14 +50,24 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_128s_simple_keypair(uint8_t *public_ #if defined(OQS_DIST_BUILD) if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) { #endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_crypto_sign_keypair(public_key, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE128SSIMPLE_AVX2_crypto_sign_keypair(public_key, secret_key); +#if defined(OQS_DIST_BUILD) + } else { + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE128SSIMPLE_CLEAN_crypto_sign_keypair(public_key, secret_key); + } +#endif /* OQS_DIST_BUILD */ +#elif defined(OQS_ENABLE_SIG_sphincs_shake256_128s_simple_aarch64) +#if defined(OQS_DIST_BUILD) + if (OQS_CPU_has_extension(OQS_CPU_EXT_SHA3)) { +#endif /* OQS_DIST_BUILD */ + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE128SSIMPLE_AARCH64_crypto_sign_keypair(public_key, secret_key); #if defined(OQS_DIST_BUILD) } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_crypto_sign_keypair(public_key, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE128SSIMPLE_CLEAN_crypto_sign_keypair(public_key, secret_key); } #endif /* OQS_DIST_BUILD */ #else - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_crypto_sign_keypair(public_key, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE128SSIMPLE_CLEAN_crypto_sign_keypair(public_key, secret_key); #endif } @@ -60,14 +76,24 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_128s_simple_sign(uint8_t *signature, #if defined(OQS_DIST_BUILD) if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) { #endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE128SSIMPLE_AVX2_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); +#if defined(OQS_DIST_BUILD) + } else { + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE128SSIMPLE_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); + } +#endif /* OQS_DIST_BUILD */ +#elif defined(OQS_ENABLE_SIG_sphincs_shake256_128s_simple_aarch64) +#if defined(OQS_DIST_BUILD) + if (OQS_CPU_has_extension(OQS_CPU_EXT_SHA3)) { +#endif /* OQS_DIST_BUILD */ + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE128SSIMPLE_AARCH64_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); #if defined(OQS_DIST_BUILD) } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE128SSIMPLE_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); } #endif /* OQS_DIST_BUILD */ #else - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE128SSIMPLE_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); #endif } @@ -76,14 +102,24 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_128s_simple_verify(const uint8_t *me #if defined(OQS_DIST_BUILD) if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) { #endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_crypto_sign_verify(signature, signature_len, message, message_len, public_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE128SSIMPLE_AVX2_crypto_sign_verify(signature, signature_len, message, message_len, public_key); +#if defined(OQS_DIST_BUILD) + } else { + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE128SSIMPLE_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); + } +#endif /* OQS_DIST_BUILD */ +#elif defined(OQS_ENABLE_SIG_sphincs_shake256_128s_simple_aarch64) +#if defined(OQS_DIST_BUILD) + if (OQS_CPU_has_extension(OQS_CPU_EXT_SHA3)) { +#endif /* OQS_DIST_BUILD */ + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE128SSIMPLE_AARCH64_crypto_sign_verify(signature, signature_len, message, message_len, public_key); #if defined(OQS_DIST_BUILD) } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE128SSIMPLE_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); } #endif /* OQS_DIST_BUILD */ #else - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE128SSIMPLE_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); #endif } diff --git a/src/sig/sphincs/sig_sphincs_shake256_192f_robust.c b/src/sig/sphincs/sig_sphincs_shake256_192f_robust.c index 411e52bee9..2fe5f3fbd6 100644 --- a/src/sig/sphincs/sig_sphincs_shake256_192f_robust.c +++ b/src/sig/sphincs/sig_sphincs_shake256_192f_robust.c @@ -13,7 +13,7 @@ OQS_SIG *OQS_SIG_sphincs_shake256_192f_robust_new(void) { return NULL; } sig->method_name = OQS_SIG_alg_sphincs_shake256_192f_robust; - sig->alg_version = "https://github.com/sphincs/sphincsplus/commit/77755c94d0bc744478044d6efbb888dc13156441"; + sig->alg_version = "https://github.com/sphincs/sphincsplus/commit/ed15dd78658f63288c7492c00260d86154b84637"; sig->claimed_nist_level = 3; sig->euf_cma = true; @@ -29,14 +29,20 @@ OQS_SIG *OQS_SIG_sphincs_shake256_192f_robust_new(void) { return sig; } -extern int PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); -extern int PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); -extern int PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); +extern int PQCLEAN_SPHINCSSHAKE192FROBUST_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); +extern int PQCLEAN_SPHINCSSHAKE192FROBUST_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); +extern int PQCLEAN_SPHINCSSHAKE192FROBUST_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); #if defined(OQS_ENABLE_SIG_sphincs_shake256_192f_robust_avx2) -extern int PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); -extern int PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); -extern int PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); +extern int PQCLEAN_SPHINCSSHAKE192FROBUST_AVX2_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); +extern int PQCLEAN_SPHINCSSHAKE192FROBUST_AVX2_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); +extern int PQCLEAN_SPHINCSSHAKE192FROBUST_AVX2_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); +#endif + +#if defined(OQS_ENABLE_SIG_sphincs_shake256_192f_robust_aarch64) +extern int PQCLEAN_SPHINCSSHAKE192FROBUST_AARCH64_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); +extern int PQCLEAN_SPHINCSSHAKE192FROBUST_AARCH64_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); +extern int PQCLEAN_SPHINCSSHAKE192FROBUST_AARCH64_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); #endif OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_192f_robust_keypair(uint8_t *public_key, uint8_t *secret_key) { @@ -44,14 +50,24 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_192f_robust_keypair(uint8_t *public_ #if defined(OQS_DIST_BUILD) if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) { #endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_crypto_sign_keypair(public_key, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE192FROBUST_AVX2_crypto_sign_keypair(public_key, secret_key); +#if defined(OQS_DIST_BUILD) + } else { + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE192FROBUST_CLEAN_crypto_sign_keypair(public_key, secret_key); + } +#endif /* OQS_DIST_BUILD */ +#elif defined(OQS_ENABLE_SIG_sphincs_shake256_192f_robust_aarch64) +#if defined(OQS_DIST_BUILD) + if (OQS_CPU_has_extension(OQS_CPU_EXT_SHA3)) { +#endif /* OQS_DIST_BUILD */ + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE192FROBUST_AARCH64_crypto_sign_keypair(public_key, secret_key); #if defined(OQS_DIST_BUILD) } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_crypto_sign_keypair(public_key, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE192FROBUST_CLEAN_crypto_sign_keypair(public_key, secret_key); } #endif /* OQS_DIST_BUILD */ #else - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_crypto_sign_keypair(public_key, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE192FROBUST_CLEAN_crypto_sign_keypair(public_key, secret_key); #endif } @@ -60,14 +76,24 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_192f_robust_sign(uint8_t *signature, #if defined(OQS_DIST_BUILD) if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) { #endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE192FROBUST_AVX2_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); +#if defined(OQS_DIST_BUILD) + } else { + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE192FROBUST_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); + } +#endif /* OQS_DIST_BUILD */ +#elif defined(OQS_ENABLE_SIG_sphincs_shake256_192f_robust_aarch64) +#if defined(OQS_DIST_BUILD) + if (OQS_CPU_has_extension(OQS_CPU_EXT_SHA3)) { +#endif /* OQS_DIST_BUILD */ + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE192FROBUST_AARCH64_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); #if defined(OQS_DIST_BUILD) } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE192FROBUST_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); } #endif /* OQS_DIST_BUILD */ #else - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE192FROBUST_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); #endif } @@ -76,14 +102,24 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_192f_robust_verify(const uint8_t *me #if defined(OQS_DIST_BUILD) if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) { #endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_crypto_sign_verify(signature, signature_len, message, message_len, public_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE192FROBUST_AVX2_crypto_sign_verify(signature, signature_len, message, message_len, public_key); +#if defined(OQS_DIST_BUILD) + } else { + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE192FROBUST_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); + } +#endif /* OQS_DIST_BUILD */ +#elif defined(OQS_ENABLE_SIG_sphincs_shake256_192f_robust_aarch64) +#if defined(OQS_DIST_BUILD) + if (OQS_CPU_has_extension(OQS_CPU_EXT_SHA3)) { +#endif /* OQS_DIST_BUILD */ + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE192FROBUST_AARCH64_crypto_sign_verify(signature, signature_len, message, message_len, public_key); #if defined(OQS_DIST_BUILD) } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE192FROBUST_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); } #endif /* OQS_DIST_BUILD */ #else - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE192FROBUST_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); #endif } diff --git a/src/sig/sphincs/sig_sphincs_shake256_192f_simple.c b/src/sig/sphincs/sig_sphincs_shake256_192f_simple.c index 5d008aaa72..5c03294503 100644 --- a/src/sig/sphincs/sig_sphincs_shake256_192f_simple.c +++ b/src/sig/sphincs/sig_sphincs_shake256_192f_simple.c @@ -13,7 +13,7 @@ OQS_SIG *OQS_SIG_sphincs_shake256_192f_simple_new(void) { return NULL; } sig->method_name = OQS_SIG_alg_sphincs_shake256_192f_simple; - sig->alg_version = "https://github.com/sphincs/sphincsplus/commit/77755c94d0bc744478044d6efbb888dc13156441"; + sig->alg_version = "https://github.com/sphincs/sphincsplus/commit/ed15dd78658f63288c7492c00260d86154b84637"; sig->claimed_nist_level = 3; sig->euf_cma = true; @@ -29,14 +29,20 @@ OQS_SIG *OQS_SIG_sphincs_shake256_192f_simple_new(void) { return sig; } -extern int PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); -extern int PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); -extern int PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); +extern int PQCLEAN_SPHINCSSHAKE192FSIMPLE_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); +extern int PQCLEAN_SPHINCSSHAKE192FSIMPLE_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); +extern int PQCLEAN_SPHINCSSHAKE192FSIMPLE_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); #if defined(OQS_ENABLE_SIG_sphincs_shake256_192f_simple_avx2) -extern int PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); -extern int PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); -extern int PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); +extern int PQCLEAN_SPHINCSSHAKE192FSIMPLE_AVX2_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); +extern int PQCLEAN_SPHINCSSHAKE192FSIMPLE_AVX2_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); +extern int PQCLEAN_SPHINCSSHAKE192FSIMPLE_AVX2_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); +#endif + +#if defined(OQS_ENABLE_SIG_sphincs_shake256_192f_simple_aarch64) +extern int PQCLEAN_SPHINCSSHAKE192FSIMPLE_AARCH64_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); +extern int PQCLEAN_SPHINCSSHAKE192FSIMPLE_AARCH64_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); +extern int PQCLEAN_SPHINCSSHAKE192FSIMPLE_AARCH64_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); #endif OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_192f_simple_keypair(uint8_t *public_key, uint8_t *secret_key) { @@ -44,14 +50,24 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_192f_simple_keypair(uint8_t *public_ #if defined(OQS_DIST_BUILD) if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) { #endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_crypto_sign_keypair(public_key, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE192FSIMPLE_AVX2_crypto_sign_keypair(public_key, secret_key); +#if defined(OQS_DIST_BUILD) + } else { + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE192FSIMPLE_CLEAN_crypto_sign_keypair(public_key, secret_key); + } +#endif /* OQS_DIST_BUILD */ +#elif defined(OQS_ENABLE_SIG_sphincs_shake256_192f_simple_aarch64) +#if defined(OQS_DIST_BUILD) + if (OQS_CPU_has_extension(OQS_CPU_EXT_SHA3)) { +#endif /* OQS_DIST_BUILD */ + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE192FSIMPLE_AARCH64_crypto_sign_keypair(public_key, secret_key); #if defined(OQS_DIST_BUILD) } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_crypto_sign_keypair(public_key, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE192FSIMPLE_CLEAN_crypto_sign_keypair(public_key, secret_key); } #endif /* OQS_DIST_BUILD */ #else - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_crypto_sign_keypair(public_key, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE192FSIMPLE_CLEAN_crypto_sign_keypair(public_key, secret_key); #endif } @@ -60,14 +76,24 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_192f_simple_sign(uint8_t *signature, #if defined(OQS_DIST_BUILD) if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) { #endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE192FSIMPLE_AVX2_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); +#if defined(OQS_DIST_BUILD) + } else { + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE192FSIMPLE_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); + } +#endif /* OQS_DIST_BUILD */ +#elif defined(OQS_ENABLE_SIG_sphincs_shake256_192f_simple_aarch64) +#if defined(OQS_DIST_BUILD) + if (OQS_CPU_has_extension(OQS_CPU_EXT_SHA3)) { +#endif /* OQS_DIST_BUILD */ + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE192FSIMPLE_AARCH64_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); #if defined(OQS_DIST_BUILD) } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE192FSIMPLE_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); } #endif /* OQS_DIST_BUILD */ #else - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE192FSIMPLE_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); #endif } @@ -76,14 +102,24 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_192f_simple_verify(const uint8_t *me #if defined(OQS_DIST_BUILD) if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) { #endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_crypto_sign_verify(signature, signature_len, message, message_len, public_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE192FSIMPLE_AVX2_crypto_sign_verify(signature, signature_len, message, message_len, public_key); +#if defined(OQS_DIST_BUILD) + } else { + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE192FSIMPLE_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); + } +#endif /* OQS_DIST_BUILD */ +#elif defined(OQS_ENABLE_SIG_sphincs_shake256_192f_simple_aarch64) +#if defined(OQS_DIST_BUILD) + if (OQS_CPU_has_extension(OQS_CPU_EXT_SHA3)) { +#endif /* OQS_DIST_BUILD */ + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE192FSIMPLE_AARCH64_crypto_sign_verify(signature, signature_len, message, message_len, public_key); #if defined(OQS_DIST_BUILD) } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE192FSIMPLE_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); } #endif /* OQS_DIST_BUILD */ #else - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE192FSIMPLE_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); #endif } diff --git a/src/sig/sphincs/sig_sphincs_shake256_192s_robust.c b/src/sig/sphincs/sig_sphincs_shake256_192s_robust.c index 81483c4aae..572c102528 100644 --- a/src/sig/sphincs/sig_sphincs_shake256_192s_robust.c +++ b/src/sig/sphincs/sig_sphincs_shake256_192s_robust.c @@ -13,7 +13,7 @@ OQS_SIG *OQS_SIG_sphincs_shake256_192s_robust_new(void) { return NULL; } sig->method_name = OQS_SIG_alg_sphincs_shake256_192s_robust; - sig->alg_version = "https://github.com/sphincs/sphincsplus/commit/77755c94d0bc744478044d6efbb888dc13156441"; + sig->alg_version = "https://github.com/sphincs/sphincsplus/commit/ed15dd78658f63288c7492c00260d86154b84637"; sig->claimed_nist_level = 3; sig->euf_cma = true; @@ -29,14 +29,20 @@ OQS_SIG *OQS_SIG_sphincs_shake256_192s_robust_new(void) { return sig; } -extern int PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); -extern int PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); -extern int PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); +extern int PQCLEAN_SPHINCSSHAKE192SROBUST_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); +extern int PQCLEAN_SPHINCSSHAKE192SROBUST_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); +extern int PQCLEAN_SPHINCSSHAKE192SROBUST_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); #if defined(OQS_ENABLE_SIG_sphincs_shake256_192s_robust_avx2) -extern int PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); -extern int PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); -extern int PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); +extern int PQCLEAN_SPHINCSSHAKE192SROBUST_AVX2_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); +extern int PQCLEAN_SPHINCSSHAKE192SROBUST_AVX2_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); +extern int PQCLEAN_SPHINCSSHAKE192SROBUST_AVX2_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); +#endif + +#if defined(OQS_ENABLE_SIG_sphincs_shake256_192s_robust_aarch64) +extern int PQCLEAN_SPHINCSSHAKE192SROBUST_AARCH64_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); +extern int PQCLEAN_SPHINCSSHAKE192SROBUST_AARCH64_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); +extern int PQCLEAN_SPHINCSSHAKE192SROBUST_AARCH64_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); #endif OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_192s_robust_keypair(uint8_t *public_key, uint8_t *secret_key) { @@ -44,14 +50,24 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_192s_robust_keypair(uint8_t *public_ #if defined(OQS_DIST_BUILD) if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) { #endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_crypto_sign_keypair(public_key, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE192SROBUST_AVX2_crypto_sign_keypair(public_key, secret_key); +#if defined(OQS_DIST_BUILD) + } else { + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE192SROBUST_CLEAN_crypto_sign_keypair(public_key, secret_key); + } +#endif /* OQS_DIST_BUILD */ +#elif defined(OQS_ENABLE_SIG_sphincs_shake256_192s_robust_aarch64) +#if defined(OQS_DIST_BUILD) + if (OQS_CPU_has_extension(OQS_CPU_EXT_SHA3)) { +#endif /* OQS_DIST_BUILD */ + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE192SROBUST_AARCH64_crypto_sign_keypair(public_key, secret_key); #if defined(OQS_DIST_BUILD) } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_crypto_sign_keypair(public_key, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE192SROBUST_CLEAN_crypto_sign_keypair(public_key, secret_key); } #endif /* OQS_DIST_BUILD */ #else - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_crypto_sign_keypair(public_key, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE192SROBUST_CLEAN_crypto_sign_keypair(public_key, secret_key); #endif } @@ -60,14 +76,24 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_192s_robust_sign(uint8_t *signature, #if defined(OQS_DIST_BUILD) if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) { #endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE192SROBUST_AVX2_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); +#if defined(OQS_DIST_BUILD) + } else { + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE192SROBUST_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); + } +#endif /* OQS_DIST_BUILD */ +#elif defined(OQS_ENABLE_SIG_sphincs_shake256_192s_robust_aarch64) +#if defined(OQS_DIST_BUILD) + if (OQS_CPU_has_extension(OQS_CPU_EXT_SHA3)) { +#endif /* OQS_DIST_BUILD */ + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE192SROBUST_AARCH64_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); #if defined(OQS_DIST_BUILD) } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE192SROBUST_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); } #endif /* OQS_DIST_BUILD */ #else - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE192SROBUST_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); #endif } @@ -76,14 +102,24 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_192s_robust_verify(const uint8_t *me #if defined(OQS_DIST_BUILD) if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) { #endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_crypto_sign_verify(signature, signature_len, message, message_len, public_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE192SROBUST_AVX2_crypto_sign_verify(signature, signature_len, message, message_len, public_key); +#if defined(OQS_DIST_BUILD) + } else { + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE192SROBUST_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); + } +#endif /* OQS_DIST_BUILD */ +#elif defined(OQS_ENABLE_SIG_sphincs_shake256_192s_robust_aarch64) +#if defined(OQS_DIST_BUILD) + if (OQS_CPU_has_extension(OQS_CPU_EXT_SHA3)) { +#endif /* OQS_DIST_BUILD */ + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE192SROBUST_AARCH64_crypto_sign_verify(signature, signature_len, message, message_len, public_key); #if defined(OQS_DIST_BUILD) } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE192SROBUST_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); } #endif /* OQS_DIST_BUILD */ #else - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE192SROBUST_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); #endif } diff --git a/src/sig/sphincs/sig_sphincs_shake256_192s_simple.c b/src/sig/sphincs/sig_sphincs_shake256_192s_simple.c index 8eb67df9d2..bc859c315a 100644 --- a/src/sig/sphincs/sig_sphincs_shake256_192s_simple.c +++ b/src/sig/sphincs/sig_sphincs_shake256_192s_simple.c @@ -13,7 +13,7 @@ OQS_SIG *OQS_SIG_sphincs_shake256_192s_simple_new(void) { return NULL; } sig->method_name = OQS_SIG_alg_sphincs_shake256_192s_simple; - sig->alg_version = "https://github.com/sphincs/sphincsplus/commit/77755c94d0bc744478044d6efbb888dc13156441"; + sig->alg_version = "https://github.com/sphincs/sphincsplus/commit/ed15dd78658f63288c7492c00260d86154b84637"; sig->claimed_nist_level = 3; sig->euf_cma = true; @@ -29,14 +29,20 @@ OQS_SIG *OQS_SIG_sphincs_shake256_192s_simple_new(void) { return sig; } -extern int PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); -extern int PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); -extern int PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); +extern int PQCLEAN_SPHINCSSHAKE192SSIMPLE_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); +extern int PQCLEAN_SPHINCSSHAKE192SSIMPLE_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); +extern int PQCLEAN_SPHINCSSHAKE192SSIMPLE_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); #if defined(OQS_ENABLE_SIG_sphincs_shake256_192s_simple_avx2) -extern int PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); -extern int PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); -extern int PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); +extern int PQCLEAN_SPHINCSSHAKE192SSIMPLE_AVX2_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); +extern int PQCLEAN_SPHINCSSHAKE192SSIMPLE_AVX2_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); +extern int PQCLEAN_SPHINCSSHAKE192SSIMPLE_AVX2_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); +#endif + +#if defined(OQS_ENABLE_SIG_sphincs_shake256_192s_simple_aarch64) +extern int PQCLEAN_SPHINCSSHAKE192SSIMPLE_AARCH64_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); +extern int PQCLEAN_SPHINCSSHAKE192SSIMPLE_AARCH64_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); +extern int PQCLEAN_SPHINCSSHAKE192SSIMPLE_AARCH64_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); #endif OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_192s_simple_keypair(uint8_t *public_key, uint8_t *secret_key) { @@ -44,14 +50,24 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_192s_simple_keypair(uint8_t *public_ #if defined(OQS_DIST_BUILD) if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) { #endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_crypto_sign_keypair(public_key, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE192SSIMPLE_AVX2_crypto_sign_keypair(public_key, secret_key); +#if defined(OQS_DIST_BUILD) + } else { + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE192SSIMPLE_CLEAN_crypto_sign_keypair(public_key, secret_key); + } +#endif /* OQS_DIST_BUILD */ +#elif defined(OQS_ENABLE_SIG_sphincs_shake256_192s_simple_aarch64) +#if defined(OQS_DIST_BUILD) + if (OQS_CPU_has_extension(OQS_CPU_EXT_SHA3)) { +#endif /* OQS_DIST_BUILD */ + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE192SSIMPLE_AARCH64_crypto_sign_keypair(public_key, secret_key); #if defined(OQS_DIST_BUILD) } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_crypto_sign_keypair(public_key, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE192SSIMPLE_CLEAN_crypto_sign_keypair(public_key, secret_key); } #endif /* OQS_DIST_BUILD */ #else - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_crypto_sign_keypair(public_key, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE192SSIMPLE_CLEAN_crypto_sign_keypair(public_key, secret_key); #endif } @@ -60,14 +76,24 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_192s_simple_sign(uint8_t *signature, #if defined(OQS_DIST_BUILD) if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) { #endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE192SSIMPLE_AVX2_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); +#if defined(OQS_DIST_BUILD) + } else { + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE192SSIMPLE_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); + } +#endif /* OQS_DIST_BUILD */ +#elif defined(OQS_ENABLE_SIG_sphincs_shake256_192s_simple_aarch64) +#if defined(OQS_DIST_BUILD) + if (OQS_CPU_has_extension(OQS_CPU_EXT_SHA3)) { +#endif /* OQS_DIST_BUILD */ + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE192SSIMPLE_AARCH64_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); #if defined(OQS_DIST_BUILD) } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE192SSIMPLE_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); } #endif /* OQS_DIST_BUILD */ #else - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE192SSIMPLE_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); #endif } @@ -76,14 +102,24 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_192s_simple_verify(const uint8_t *me #if defined(OQS_DIST_BUILD) if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) { #endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_crypto_sign_verify(signature, signature_len, message, message_len, public_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE192SSIMPLE_AVX2_crypto_sign_verify(signature, signature_len, message, message_len, public_key); +#if defined(OQS_DIST_BUILD) + } else { + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE192SSIMPLE_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); + } +#endif /* OQS_DIST_BUILD */ +#elif defined(OQS_ENABLE_SIG_sphincs_shake256_192s_simple_aarch64) +#if defined(OQS_DIST_BUILD) + if (OQS_CPU_has_extension(OQS_CPU_EXT_SHA3)) { +#endif /* OQS_DIST_BUILD */ + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE192SSIMPLE_AARCH64_crypto_sign_verify(signature, signature_len, message, message_len, public_key); #if defined(OQS_DIST_BUILD) } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE192SSIMPLE_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); } #endif /* OQS_DIST_BUILD */ #else - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE192SSIMPLE_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); #endif } diff --git a/src/sig/sphincs/sig_sphincs_shake256_256f_robust.c b/src/sig/sphincs/sig_sphincs_shake256_256f_robust.c index c61e00f4b0..30aae47e8a 100644 --- a/src/sig/sphincs/sig_sphincs_shake256_256f_robust.c +++ b/src/sig/sphincs/sig_sphincs_shake256_256f_robust.c @@ -13,7 +13,7 @@ OQS_SIG *OQS_SIG_sphincs_shake256_256f_robust_new(void) { return NULL; } sig->method_name = OQS_SIG_alg_sphincs_shake256_256f_robust; - sig->alg_version = "https://github.com/sphincs/sphincsplus/commit/77755c94d0bc744478044d6efbb888dc13156441"; + sig->alg_version = "https://github.com/sphincs/sphincsplus/commit/ed15dd78658f63288c7492c00260d86154b84637"; sig->claimed_nist_level = 5; sig->euf_cma = true; @@ -29,14 +29,20 @@ OQS_SIG *OQS_SIG_sphincs_shake256_256f_robust_new(void) { return sig; } -extern int PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); -extern int PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); -extern int PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); +extern int PQCLEAN_SPHINCSSHAKE256FROBUST_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); +extern int PQCLEAN_SPHINCSSHAKE256FROBUST_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); +extern int PQCLEAN_SPHINCSSHAKE256FROBUST_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); #if defined(OQS_ENABLE_SIG_sphincs_shake256_256f_robust_avx2) -extern int PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); -extern int PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); -extern int PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); +extern int PQCLEAN_SPHINCSSHAKE256FROBUST_AVX2_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); +extern int PQCLEAN_SPHINCSSHAKE256FROBUST_AVX2_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); +extern int PQCLEAN_SPHINCSSHAKE256FROBUST_AVX2_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); +#endif + +#if defined(OQS_ENABLE_SIG_sphincs_shake256_256f_robust_aarch64) +extern int PQCLEAN_SPHINCSSHAKE256FROBUST_AARCH64_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); +extern int PQCLEAN_SPHINCSSHAKE256FROBUST_AARCH64_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); +extern int PQCLEAN_SPHINCSSHAKE256FROBUST_AARCH64_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); #endif OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_256f_robust_keypair(uint8_t *public_key, uint8_t *secret_key) { @@ -44,14 +50,24 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_256f_robust_keypair(uint8_t *public_ #if defined(OQS_DIST_BUILD) if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) { #endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_crypto_sign_keypair(public_key, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256FROBUST_AVX2_crypto_sign_keypair(public_key, secret_key); +#if defined(OQS_DIST_BUILD) + } else { + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256FROBUST_CLEAN_crypto_sign_keypair(public_key, secret_key); + } +#endif /* OQS_DIST_BUILD */ +#elif defined(OQS_ENABLE_SIG_sphincs_shake256_256f_robust_aarch64) +#if defined(OQS_DIST_BUILD) + if (OQS_CPU_has_extension(OQS_CPU_EXT_SHA3)) { +#endif /* OQS_DIST_BUILD */ + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256FROBUST_AARCH64_crypto_sign_keypair(public_key, secret_key); #if defined(OQS_DIST_BUILD) } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_crypto_sign_keypair(public_key, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256FROBUST_CLEAN_crypto_sign_keypair(public_key, secret_key); } #endif /* OQS_DIST_BUILD */ #else - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_crypto_sign_keypair(public_key, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256FROBUST_CLEAN_crypto_sign_keypair(public_key, secret_key); #endif } @@ -60,14 +76,24 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_256f_robust_sign(uint8_t *signature, #if defined(OQS_DIST_BUILD) if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) { #endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256FROBUST_AVX2_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); +#if defined(OQS_DIST_BUILD) + } else { + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256FROBUST_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); + } +#endif /* OQS_DIST_BUILD */ +#elif defined(OQS_ENABLE_SIG_sphincs_shake256_256f_robust_aarch64) +#if defined(OQS_DIST_BUILD) + if (OQS_CPU_has_extension(OQS_CPU_EXT_SHA3)) { +#endif /* OQS_DIST_BUILD */ + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256FROBUST_AARCH64_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); #if defined(OQS_DIST_BUILD) } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256FROBUST_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); } #endif /* OQS_DIST_BUILD */ #else - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256FROBUST_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); #endif } @@ -76,14 +102,24 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_256f_robust_verify(const uint8_t *me #if defined(OQS_DIST_BUILD) if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) { #endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_crypto_sign_verify(signature, signature_len, message, message_len, public_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256FROBUST_AVX2_crypto_sign_verify(signature, signature_len, message, message_len, public_key); +#if defined(OQS_DIST_BUILD) + } else { + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256FROBUST_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); + } +#endif /* OQS_DIST_BUILD */ +#elif defined(OQS_ENABLE_SIG_sphincs_shake256_256f_robust_aarch64) +#if defined(OQS_DIST_BUILD) + if (OQS_CPU_has_extension(OQS_CPU_EXT_SHA3)) { +#endif /* OQS_DIST_BUILD */ + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256FROBUST_AARCH64_crypto_sign_verify(signature, signature_len, message, message_len, public_key); #if defined(OQS_DIST_BUILD) } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256FROBUST_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); } #endif /* OQS_DIST_BUILD */ #else - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256FROBUST_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); #endif } diff --git a/src/sig/sphincs/sig_sphincs_shake256_256f_simple.c b/src/sig/sphincs/sig_sphincs_shake256_256f_simple.c index 41e46f35d5..23f5b365d0 100644 --- a/src/sig/sphincs/sig_sphincs_shake256_256f_simple.c +++ b/src/sig/sphincs/sig_sphincs_shake256_256f_simple.c @@ -13,7 +13,7 @@ OQS_SIG *OQS_SIG_sphincs_shake256_256f_simple_new(void) { return NULL; } sig->method_name = OQS_SIG_alg_sphincs_shake256_256f_simple; - sig->alg_version = "https://github.com/sphincs/sphincsplus/commit/77755c94d0bc744478044d6efbb888dc13156441"; + sig->alg_version = "https://github.com/sphincs/sphincsplus/commit/ed15dd78658f63288c7492c00260d86154b84637"; sig->claimed_nist_level = 5; sig->euf_cma = true; @@ -29,14 +29,20 @@ OQS_SIG *OQS_SIG_sphincs_shake256_256f_simple_new(void) { return sig; } -extern int PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); -extern int PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); -extern int PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); +extern int PQCLEAN_SPHINCSSHAKE256FSIMPLE_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); +extern int PQCLEAN_SPHINCSSHAKE256FSIMPLE_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); +extern int PQCLEAN_SPHINCSSHAKE256FSIMPLE_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); #if defined(OQS_ENABLE_SIG_sphincs_shake256_256f_simple_avx2) -extern int PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); -extern int PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); -extern int PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); +extern int PQCLEAN_SPHINCSSHAKE256FSIMPLE_AVX2_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); +extern int PQCLEAN_SPHINCSSHAKE256FSIMPLE_AVX2_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); +extern int PQCLEAN_SPHINCSSHAKE256FSIMPLE_AVX2_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); +#endif + +#if defined(OQS_ENABLE_SIG_sphincs_shake256_256f_simple_aarch64) +extern int PQCLEAN_SPHINCSSHAKE256FSIMPLE_AARCH64_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); +extern int PQCLEAN_SPHINCSSHAKE256FSIMPLE_AARCH64_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); +extern int PQCLEAN_SPHINCSSHAKE256FSIMPLE_AARCH64_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); #endif OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_256f_simple_keypair(uint8_t *public_key, uint8_t *secret_key) { @@ -44,14 +50,24 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_256f_simple_keypair(uint8_t *public_ #if defined(OQS_DIST_BUILD) if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) { #endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_crypto_sign_keypair(public_key, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256FSIMPLE_AVX2_crypto_sign_keypair(public_key, secret_key); +#if defined(OQS_DIST_BUILD) + } else { + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256FSIMPLE_CLEAN_crypto_sign_keypair(public_key, secret_key); + } +#endif /* OQS_DIST_BUILD */ +#elif defined(OQS_ENABLE_SIG_sphincs_shake256_256f_simple_aarch64) +#if defined(OQS_DIST_BUILD) + if (OQS_CPU_has_extension(OQS_CPU_EXT_SHA3)) { +#endif /* OQS_DIST_BUILD */ + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256FSIMPLE_AARCH64_crypto_sign_keypair(public_key, secret_key); #if defined(OQS_DIST_BUILD) } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_crypto_sign_keypair(public_key, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256FSIMPLE_CLEAN_crypto_sign_keypair(public_key, secret_key); } #endif /* OQS_DIST_BUILD */ #else - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_crypto_sign_keypair(public_key, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256FSIMPLE_CLEAN_crypto_sign_keypair(public_key, secret_key); #endif } @@ -60,14 +76,24 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_256f_simple_sign(uint8_t *signature, #if defined(OQS_DIST_BUILD) if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) { #endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256FSIMPLE_AVX2_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); +#if defined(OQS_DIST_BUILD) + } else { + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256FSIMPLE_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); + } +#endif /* OQS_DIST_BUILD */ +#elif defined(OQS_ENABLE_SIG_sphincs_shake256_256f_simple_aarch64) +#if defined(OQS_DIST_BUILD) + if (OQS_CPU_has_extension(OQS_CPU_EXT_SHA3)) { +#endif /* OQS_DIST_BUILD */ + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256FSIMPLE_AARCH64_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); #if defined(OQS_DIST_BUILD) } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256FSIMPLE_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); } #endif /* OQS_DIST_BUILD */ #else - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256FSIMPLE_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); #endif } @@ -76,14 +102,24 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_256f_simple_verify(const uint8_t *me #if defined(OQS_DIST_BUILD) if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) { #endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_crypto_sign_verify(signature, signature_len, message, message_len, public_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256FSIMPLE_AVX2_crypto_sign_verify(signature, signature_len, message, message_len, public_key); +#if defined(OQS_DIST_BUILD) + } else { + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256FSIMPLE_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); + } +#endif /* OQS_DIST_BUILD */ +#elif defined(OQS_ENABLE_SIG_sphincs_shake256_256f_simple_aarch64) +#if defined(OQS_DIST_BUILD) + if (OQS_CPU_has_extension(OQS_CPU_EXT_SHA3)) { +#endif /* OQS_DIST_BUILD */ + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256FSIMPLE_AARCH64_crypto_sign_verify(signature, signature_len, message, message_len, public_key); #if defined(OQS_DIST_BUILD) } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256FSIMPLE_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); } #endif /* OQS_DIST_BUILD */ #else - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256FSIMPLE_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); #endif } diff --git a/src/sig/sphincs/sig_sphincs_shake256_256s_robust.c b/src/sig/sphincs/sig_sphincs_shake256_256s_robust.c index c2ed6078a5..d3af3f79f5 100644 --- a/src/sig/sphincs/sig_sphincs_shake256_256s_robust.c +++ b/src/sig/sphincs/sig_sphincs_shake256_256s_robust.c @@ -13,7 +13,7 @@ OQS_SIG *OQS_SIG_sphincs_shake256_256s_robust_new(void) { return NULL; } sig->method_name = OQS_SIG_alg_sphincs_shake256_256s_robust; - sig->alg_version = "https://github.com/sphincs/sphincsplus/commit/77755c94d0bc744478044d6efbb888dc13156441"; + sig->alg_version = "https://github.com/sphincs/sphincsplus/commit/ed15dd78658f63288c7492c00260d86154b84637"; sig->claimed_nist_level = 5; sig->euf_cma = true; @@ -29,14 +29,20 @@ OQS_SIG *OQS_SIG_sphincs_shake256_256s_robust_new(void) { return sig; } -extern int PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); -extern int PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); -extern int PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); +extern int PQCLEAN_SPHINCSSHAKE256SROBUST_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); +extern int PQCLEAN_SPHINCSSHAKE256SROBUST_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); +extern int PQCLEAN_SPHINCSSHAKE256SROBUST_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); #if defined(OQS_ENABLE_SIG_sphincs_shake256_256s_robust_avx2) -extern int PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); -extern int PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); -extern int PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); +extern int PQCLEAN_SPHINCSSHAKE256SROBUST_AVX2_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); +extern int PQCLEAN_SPHINCSSHAKE256SROBUST_AVX2_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); +extern int PQCLEAN_SPHINCSSHAKE256SROBUST_AVX2_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); +#endif + +#if defined(OQS_ENABLE_SIG_sphincs_shake256_256s_robust_aarch64) +extern int PQCLEAN_SPHINCSSHAKE256SROBUST_AARCH64_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); +extern int PQCLEAN_SPHINCSSHAKE256SROBUST_AARCH64_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); +extern int PQCLEAN_SPHINCSSHAKE256SROBUST_AARCH64_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); #endif OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_256s_robust_keypair(uint8_t *public_key, uint8_t *secret_key) { @@ -44,14 +50,24 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_256s_robust_keypair(uint8_t *public_ #if defined(OQS_DIST_BUILD) if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) { #endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_crypto_sign_keypair(public_key, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256SROBUST_AVX2_crypto_sign_keypair(public_key, secret_key); +#if defined(OQS_DIST_BUILD) + } else { + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256SROBUST_CLEAN_crypto_sign_keypair(public_key, secret_key); + } +#endif /* OQS_DIST_BUILD */ +#elif defined(OQS_ENABLE_SIG_sphincs_shake256_256s_robust_aarch64) +#if defined(OQS_DIST_BUILD) + if (OQS_CPU_has_extension(OQS_CPU_EXT_SHA3)) { +#endif /* OQS_DIST_BUILD */ + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256SROBUST_AARCH64_crypto_sign_keypair(public_key, secret_key); #if defined(OQS_DIST_BUILD) } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_crypto_sign_keypair(public_key, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256SROBUST_CLEAN_crypto_sign_keypair(public_key, secret_key); } #endif /* OQS_DIST_BUILD */ #else - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_crypto_sign_keypair(public_key, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256SROBUST_CLEAN_crypto_sign_keypair(public_key, secret_key); #endif } @@ -60,14 +76,24 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_256s_robust_sign(uint8_t *signature, #if defined(OQS_DIST_BUILD) if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) { #endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256SROBUST_AVX2_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); +#if defined(OQS_DIST_BUILD) + } else { + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256SROBUST_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); + } +#endif /* OQS_DIST_BUILD */ +#elif defined(OQS_ENABLE_SIG_sphincs_shake256_256s_robust_aarch64) +#if defined(OQS_DIST_BUILD) + if (OQS_CPU_has_extension(OQS_CPU_EXT_SHA3)) { +#endif /* OQS_DIST_BUILD */ + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256SROBUST_AARCH64_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); #if defined(OQS_DIST_BUILD) } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256SROBUST_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); } #endif /* OQS_DIST_BUILD */ #else - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256SROBUST_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); #endif } @@ -76,14 +102,24 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_256s_robust_verify(const uint8_t *me #if defined(OQS_DIST_BUILD) if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) { #endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_crypto_sign_verify(signature, signature_len, message, message_len, public_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256SROBUST_AVX2_crypto_sign_verify(signature, signature_len, message, message_len, public_key); +#if defined(OQS_DIST_BUILD) + } else { + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256SROBUST_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); + } +#endif /* OQS_DIST_BUILD */ +#elif defined(OQS_ENABLE_SIG_sphincs_shake256_256s_robust_aarch64) +#if defined(OQS_DIST_BUILD) + if (OQS_CPU_has_extension(OQS_CPU_EXT_SHA3)) { +#endif /* OQS_DIST_BUILD */ + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256SROBUST_AARCH64_crypto_sign_verify(signature, signature_len, message, message_len, public_key); #if defined(OQS_DIST_BUILD) } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256SROBUST_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); } #endif /* OQS_DIST_BUILD */ #else - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256SROBUST_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); #endif } diff --git a/src/sig/sphincs/sig_sphincs_shake256_256s_simple.c b/src/sig/sphincs/sig_sphincs_shake256_256s_simple.c index 21ae73f9db..db904b8945 100644 --- a/src/sig/sphincs/sig_sphincs_shake256_256s_simple.c +++ b/src/sig/sphincs/sig_sphincs_shake256_256s_simple.c @@ -13,7 +13,7 @@ OQS_SIG *OQS_SIG_sphincs_shake256_256s_simple_new(void) { return NULL; } sig->method_name = OQS_SIG_alg_sphincs_shake256_256s_simple; - sig->alg_version = "https://github.com/sphincs/sphincsplus/commit/77755c94d0bc744478044d6efbb888dc13156441"; + sig->alg_version = "https://github.com/sphincs/sphincsplus/commit/ed15dd78658f63288c7492c00260d86154b84637"; sig->claimed_nist_level = 5; sig->euf_cma = true; @@ -29,14 +29,20 @@ OQS_SIG *OQS_SIG_sphincs_shake256_256s_simple_new(void) { return sig; } -extern int PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); -extern int PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); -extern int PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); +extern int PQCLEAN_SPHINCSSHAKE256SSIMPLE_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); +extern int PQCLEAN_SPHINCSSHAKE256SSIMPLE_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); +extern int PQCLEAN_SPHINCSSHAKE256SSIMPLE_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); #if defined(OQS_ENABLE_SIG_sphincs_shake256_256s_simple_avx2) -extern int PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); -extern int PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); -extern int PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); +extern int PQCLEAN_SPHINCSSHAKE256SSIMPLE_AVX2_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); +extern int PQCLEAN_SPHINCSSHAKE256SSIMPLE_AVX2_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); +extern int PQCLEAN_SPHINCSSHAKE256SSIMPLE_AVX2_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); +#endif + +#if defined(OQS_ENABLE_SIG_sphincs_shake256_256s_simple_aarch64) +extern int PQCLEAN_SPHINCSSHAKE256SSIMPLE_AARCH64_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); +extern int PQCLEAN_SPHINCSSHAKE256SSIMPLE_AARCH64_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); +extern int PQCLEAN_SPHINCSSHAKE256SSIMPLE_AARCH64_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); #endif OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_256s_simple_keypair(uint8_t *public_key, uint8_t *secret_key) { @@ -44,14 +50,24 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_256s_simple_keypair(uint8_t *public_ #if defined(OQS_DIST_BUILD) if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) { #endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_crypto_sign_keypair(public_key, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256SSIMPLE_AVX2_crypto_sign_keypair(public_key, secret_key); +#if defined(OQS_DIST_BUILD) + } else { + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256SSIMPLE_CLEAN_crypto_sign_keypair(public_key, secret_key); + } +#endif /* OQS_DIST_BUILD */ +#elif defined(OQS_ENABLE_SIG_sphincs_shake256_256s_simple_aarch64) +#if defined(OQS_DIST_BUILD) + if (OQS_CPU_has_extension(OQS_CPU_EXT_SHA3)) { +#endif /* OQS_DIST_BUILD */ + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256SSIMPLE_AARCH64_crypto_sign_keypair(public_key, secret_key); #if defined(OQS_DIST_BUILD) } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_crypto_sign_keypair(public_key, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256SSIMPLE_CLEAN_crypto_sign_keypair(public_key, secret_key); } #endif /* OQS_DIST_BUILD */ #else - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_crypto_sign_keypair(public_key, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256SSIMPLE_CLEAN_crypto_sign_keypair(public_key, secret_key); #endif } @@ -60,14 +76,24 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_256s_simple_sign(uint8_t *signature, #if defined(OQS_DIST_BUILD) if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) { #endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256SSIMPLE_AVX2_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); +#if defined(OQS_DIST_BUILD) + } else { + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256SSIMPLE_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); + } +#endif /* OQS_DIST_BUILD */ +#elif defined(OQS_ENABLE_SIG_sphincs_shake256_256s_simple_aarch64) +#if defined(OQS_DIST_BUILD) + if (OQS_CPU_has_extension(OQS_CPU_EXT_SHA3)) { +#endif /* OQS_DIST_BUILD */ + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256SSIMPLE_AARCH64_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); #if defined(OQS_DIST_BUILD) } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256SSIMPLE_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); } #endif /* OQS_DIST_BUILD */ #else - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256SSIMPLE_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); #endif } @@ -76,14 +102,24 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_256s_simple_verify(const uint8_t *me #if defined(OQS_DIST_BUILD) if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) { #endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_crypto_sign_verify(signature, signature_len, message, message_len, public_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256SSIMPLE_AVX2_crypto_sign_verify(signature, signature_len, message, message_len, public_key); +#if defined(OQS_DIST_BUILD) + } else { + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256SSIMPLE_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); + } +#endif /* OQS_DIST_BUILD */ +#elif defined(OQS_ENABLE_SIG_sphincs_shake256_256s_simple_aarch64) +#if defined(OQS_DIST_BUILD) + if (OQS_CPU_has_extension(OQS_CPU_EXT_SHA3)) { +#endif /* OQS_DIST_BUILD */ + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256SSIMPLE_AARCH64_crypto_sign_verify(signature, signature_len, message, message_len, public_key); #if defined(OQS_DIST_BUILD) } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256SSIMPLE_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); } #endif /* OQS_DIST_BUILD */ #else - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); + return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256SSIMPLE_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); #endif } diff --git a/tests/KATs/sig/kats.json b/tests/KATs/sig/kats.json index d88270a426..0da24761f3 100644 --- a/tests/KATs/sig/kats.json +++ b/tests/KATs/sig/kats.json @@ -7,40 +7,40 @@ "Dilithium5-AES": "6d5032d970450d9dc94a243fcf303ed84b5562618a228f31dd047d600cbcbf9e", "Falcon-1024": "e699d88eb214fef30597385f40814baeb84ac505d5f05f5c257b0726fc4530b8", "Falcon-512": "da27fe8a462de7307ddf1f9b00072a457d9c5b14e838c148fbe2662094b9a2ca", - "SPHINCS+-Haraka-128f-robust": "a8b966844b0c9bb2d954d95d25777bd548ee3dcb78e0833de8333a033d24cacb", - "SPHINCS+-Haraka-128f-simple": "266fb0a5e65ba0183fe4e462d48ff814842a389fb0785d30f89fa1c126df518b", - "SPHINCS+-Haraka-128s-robust": "ffad452b5ec3217d204ed13f5af76009ce265dd61ce9097714d941fec106dd01", - "SPHINCS+-Haraka-128s-simple": "625422a71b884ecf4d42e21f96091a18635e4862b68d0627e21a4a0033819603", - "SPHINCS+-Haraka-192f-robust": "1d32cab46df0d4e6678a06a9eae7b187c80eaedf56b1e7d221035d7c6f08ef06", - "SPHINCS+-Haraka-192f-simple": "4888059ed11c192b3a07e227e3befc967819d05f85723a7740bbc31eadc37f37", - "SPHINCS+-Haraka-192s-robust": "3d6f746167b234c7e689dff201558ac6ce6883b0c545517fe29c33fd24bfe619", - "SPHINCS+-Haraka-192s-simple": "ce6e8ff33f0264027bfe874c4265dc84de981b5fcb1d8ead2459c85a37f49cbf", - "SPHINCS+-Haraka-256f-robust": "7e346ad1ab94be33b757d833f1a934e23af6251e7aac7072d098ef15dc3264fd", - "SPHINCS+-Haraka-256f-simple": "b7bfc3a28daf35cd4110628c70294d1bcbd2a5da066bdc459891b7684432e037", - "SPHINCS+-Haraka-256s-robust": "a419bdba92da2d07f99c3c3ba4f776b955244a7c3b565816c7fd2151f6c3363f", - "SPHINCS+-Haraka-256s-simple": "0b8c7d3d8001eec6ddb317e0301fef4adc4f5b03301e5f4b93d09881b1a5ba7a", - "SPHINCS+-SHA256-128f-robust": "99c5e790fd3e2afb33b4b7b3666247368b3aa6d8c216c8537626a7fd8a680430", - "SPHINCS+-SHA256-128f-simple": "d08e30ae626e0c203cd66f51fb3a6f39f353e26bd1532ce437c1a428383fbc00", - "SPHINCS+-SHA256-128s-robust": "78c5432a5acc8f01ef5aeebc6659f15641b5dbe66ee7327ab86a1541ce1672ae", - "SPHINCS+-SHA256-128s-simple": "f398be19cd856c2fd5c894e9c6b7f872ce5db63b874b7160cb6efb40a9628773", - "SPHINCS+-SHA256-192f-robust": "9d0898cb264172c31d0fb4901dd56d46728e83e0bf008abccb8b0912c2ebbc52", - "SPHINCS+-SHA256-192f-simple": "306fef951d07b17b27c67ffe9e63185ae5d5fde87619b76872a3ca969299d47c", - "SPHINCS+-SHA256-192s-robust": "37cb7031fbd4436d3b4724fe4147af3a23e2e8240174a2eef99ec17dd3e5a5c9", - "SPHINCS+-SHA256-192s-simple": "45c9c28e85bb3f3b90b16f6deb25a32862613f4f3fcd17de9a46d83b7ff27745", - "SPHINCS+-SHA256-256f-robust": "8006df7b3bf31e1c8a262d2d7fd2279d2fa4b0edb10bcb36c72ecc8a6ada03f5", - "SPHINCS+-SHA256-256f-simple": "a563c2870fc6cb7c4b84b7cd5cd271ccd7bedf741d35592370fc9aea517f366d", - "SPHINCS+-SHA256-256s-robust": "da28ff350ac552f100b35b01ecb494dc02f9dcf542fa2d88439cd427985e9581", - "SPHINCS+-SHA256-256s-simple": "768d61c537b3abacca3ab468623edafb33d28a33dc5a9859f803679a3020b639", - "SPHINCS+-SHAKE256-128f-robust": "39af7b5cee0e03dfa61070d0ac8dcae358a3d9b9a5d0eebb356cb25051a6b4b7", - "SPHINCS+-SHAKE256-128f-simple": "ebebf1a5da339c6e2073f41d7b499b7e5a456ac91c68ef5d15d18643c89d8e7d", - "SPHINCS+-SHAKE256-128s-robust": "094df7ed9198f66c0dfa02429d48320dc942f01bc2f90289519c4fbd37085ad6", - "SPHINCS+-SHAKE256-128s-simple": "260c24c6de710d81f86184fc034d382abe5d705b5352d7329ca662f6def392a4", - "SPHINCS+-SHAKE256-192f-robust": "5cfcf998ad0bedf8e6b961c8891048f456d6422d3b4a26fcb095a913c9efd03e", - "SPHINCS+-SHAKE256-192f-simple": "28528adef75a728d013bb493d85e358a75344c72000792419f1f539c16f24f10", - "SPHINCS+-SHAKE256-192s-robust": "92eed523fc2f48b66826929b49a58d44c46aaa2c286a6d0e822a8d1e34555121", - "SPHINCS+-SHAKE256-192s-simple": "3cb0a4fccbb8d204aaa5c06e5be66a53e8c4ba1cbf1aefef8fdfaa5c63d60094", - "SPHINCS+-SHAKE256-256f-robust": "4bd4c9610754bb66530f492cf2e98e81b0d525339bae56038034e692f46f7927", - "SPHINCS+-SHAKE256-256f-simple": "1ec2691198f9a5c29c45a2bb72b3e04c9127f8e1df19d6c874d8b5bdfab89ef7", - "SPHINCS+-SHAKE256-256s-robust": "09004dba03b2a190a327b5404a4d75c663f025703253b78946d0a99ca1492d6f", - "SPHINCS+-SHAKE256-256s-simple": "f704deaf990987c306082bb28258cfb8c6f03b49940c06df582ef3fb86958e8a" + "SPHINCS+-Haraka-128f-robust": "534da8ce51d5d2105bba0cead748b7fec5135ed4023571cef7ccea20ccab8fbb", + "SPHINCS+-Haraka-128f-simple": "2070a01d6d52e5e3bee764dd356c5dbdc3209f0d87bb7d7b57ac24e1e9eb19fd", + "SPHINCS+-Haraka-128s-robust": "f5b276c0d2b054b5ef1d12a390eacbad5d74e4b843616f13a4bc1ba1254b1714", + "SPHINCS+-Haraka-128s-simple": "8c6ff529df678592b509844de529ef57705b1c1766e169670fbb1119903e4c77", + "SPHINCS+-Haraka-192f-robust": "9d7c25990082c7d04d8737cf29ee14b721f033d131c81962cbc535c95b4a6077", + "SPHINCS+-Haraka-192f-simple": "3fda06fde66e57ece0b2fd8384c0f4e284efb9a6289da226b0bd3a1bda3e13be", + "SPHINCS+-Haraka-192s-robust": "85640bbb27f562ac73c567a3f6c6e7bd1a4e793abbae73d53acf9728e8009bc2", + "SPHINCS+-Haraka-192s-simple": "f430c0f267b35d4ac2deaea074e2368c4c628550101b78ee3a4875a160923712", + "SPHINCS+-Haraka-256f-robust": "febb3162e4d99a0eaab69d55929f84233d76a0070da07e36275579408bb73fff", + "SPHINCS+-Haraka-256f-simple": "224bb32837841d6e72a7dfa000a56681087488f65f847b779d6bcfb4391a8375", + "SPHINCS+-Haraka-256s-robust": "c950c06f1841ea938e9f261b7f49f9afaa43989868351c31bab9263ec42dd352", + "SPHINCS+-Haraka-256s-simple": "8453bee2b32fad4e0c51f346aa031f2cd614b94986516cf93ec99a252bb74d70", + "SPHINCS+-SHA256-128f-robust": "a0d7e90225647805b288b7007196a9086893fb5e1a4f2fe5d363e4e4d0bbcf8a", + "SPHINCS+-SHA256-128f-simple": "cd1e13db3a56c0a6b3486a7b12bcddfda50cf5d1e4d14d3113e6456e969b8114", + "SPHINCS+-SHA256-128s-robust": "c9796ca77310acb22a54c2150864dae66d079d7ed1850d4ea5d5667b60261f58", + "SPHINCS+-SHA256-128s-simple": "08c2e0f08bd96f50d065ca0ced04874c709d192864bfeaccb6daa4bfa9c58a28", + "SPHINCS+-SHA256-192f-robust": "3d7d828912f5f2d4db0b27130cd03003b41ad9ab8282c5367b39afbffc063d42", + "SPHINCS+-SHA256-192f-simple": "fd4e301339b29ed5dc392c628d6c6db3d77a46ea61d16f7ff0e2b414f962f44c", + "SPHINCS+-SHA256-192s-robust": "68b4118d5d1f31ea6bd17bfd339a87b93104bd75c532ea7a513aa8115aec3fdd", + "SPHINCS+-SHA256-192s-simple": "0fa07f3f77752233b382911bcc19e671522bd57069f9edca39b3924ba2713839", + "SPHINCS+-SHA256-256f-robust": "4d0e034db7796df5f13ee6adc916dd44a71a45697649d2e91b2854cf0ee776f6", + "SPHINCS+-SHA256-256f-simple": "bd88b49453162a9b527e14228f037615d0fcbd13d24b48ece41ae1370ed13480", + "SPHINCS+-SHA256-256s-robust": "2f61690d671671a10e6f1d32c699835c55bade752fb8e87dac01412b0b31f227", + "SPHINCS+-SHA256-256s-simple": "05d15a74253962d35912bab3a9ee3230c2e721c798f4e757ecffa529071b0748", + "SPHINCS+-SHAKE256-128f-robust": "98885700274c8a4787a1dacaa63a858be14f86bdc6fddb1520e4140ccb22219d", + "SPHINCS+-SHAKE256-128f-simple": "46f4f87949dc994aa2b63b31c7307f44ca5ed025d7308ff408c8ba33473324dc", + "SPHINCS+-SHAKE256-128s-robust": "80ea155559800f469ee318dee991d86bf81f81e673a893fced5b1000bd3790fb", + "SPHINCS+-SHAKE256-128s-simple": "bae2979565dabad96d885a1e264bc213ab54aff3c3b4308880b788e87702af3b", + "SPHINCS+-SHAKE256-192f-robust": "056bbb6d2880b29941ccabeea2a956805a10c80c0afb29fac52eccb2ffdd8194", + "SPHINCS+-SHAKE256-192f-simple": "60a9d2fd74adbef971a74477eca3170599beb4476d6428ced78b43b9641cc929", + "SPHINCS+-SHAKE256-192s-robust": "9866190cc1d07c9e3af77455ed9d8ff96c49d532f93b3389eacbf128c7f39faa", + "SPHINCS+-SHAKE256-192s-simple": "87aedb87a77cb46f939a3bfd0099b08b0d889c9fa46be00f15c36827c117c838", + "SPHINCS+-SHAKE256-256f-robust": "e8111415e706232e82c85c4db90403c4c42a1770ffc1f60c2bb40ac2fa05a3b3", + "SPHINCS+-SHAKE256-256f-simple": "f6d0825afeb4ce25943c974a0efde5659ceea927d2507b0ea1a92e092f536acd", + "SPHINCS+-SHAKE256-256s-robust": "5d860324e9fe5dc84c0d9e82071d4cf88f71cd02e6fafeca0a59e6b327a18347", + "SPHINCS+-SHAKE256-256s-simple": "37d37c9b43d71341b7dd5da7f8ebbe8bbae3d7bfc53f5378446023cbcf6e04f2" } \ No newline at end of file From fcb0090ecf1a81a330020af4ff8e8ffa75843ce8 Mon Sep 17 00:00:00 2001 From: Douglas Stebila Date: Sat, 18 Mar 2023 11:21:44 -0400 Subject: [PATCH 03/10] Updates to PQClean compatibility shim --- src/common/pqclean_shims/compat.h | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/src/common/pqclean_shims/compat.h b/src/common/pqclean_shims/compat.h index d495f5a51e..99c6fd6c6d 100644 --- a/src/common/pqclean_shims/compat.h +++ b/src/common/pqclean_shims/compat.h @@ -21,11 +21,12 @@ #if defined(__GNUC__) && !defined(__clang__) +#include -#if ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((7) << 16) + (1)) // at least GCC 7.1 +# if !__GNUC_PREREQ(7, 1) // at least GCC 7.1 /* Versions of the GCC pre-7.1 don't have __m256*_u types */ UNALIGNED_VECTOR_POLYFILL_GCC -# endif // GCC >= 7.1 +# endif // __GNUC_PREREQ(7,1) #elif defined(__GNUC__) && defined(__clang__) @@ -34,14 +35,30 @@ UNALIGNED_VECTOR_POLYFILL_GCC UNALIGNED_VECTOR_POLYFILL_GCC # endif -#else -// Neither MSVC nor other compilers seem to have these types +#elif defined(_MSC_VER) +// MSVC simply doesn't have these types #define __m256_u __m256 #define __m256d_u __m256d #define __m256i_u __m256i +#else +#error UNSUPPORTED COMPILER!?!? #endif // compiler selector +/************************ + * Portable VLA support * + ************************/ + +/* To support MSVC use alloca() instead of VLAs. */ +#ifdef _MSC_VER +/* MSVC defines _alloca in malloc.h */ +# include +/* Note: _malloca(), which is recommended over deprecated _alloca, + requires that you call _freea(). So we stick with _alloca */ +# define PQCLEAN_VLA(__t,__x,__s) __t *__x = (__t*)_alloca((__s)*sizeof(__t)) +#else +# define PQCLEAN_VLA(__t,__x,__s) __t __x[__s] +#endif -#endif // OQS_COMMON_COMPAT_H +#endif // PQCLEAN_COMMON_COMPAT_H From 6347f4203f8df6af1f829c3d62e3de42c4c539e3 Mon Sep 17 00:00:00 2001 From: Michael Baentsch <57787676+baentsch@users.noreply.github.com> Date: Sun, 19 Mar 2023 19:03:06 +0100 Subject: [PATCH 04/10] Improves "compilability" on Apple M1 (ARM) (#1421) * correct ARM SHA3 extension addition * correct compile option for ARM SHA * following https://developer.arm.com/documentation/101754/0618/armclang-Reference/armclang-Command-line-Options/-march * correct SHA3 enablement --- .CMake/alg_support.cmake | 24 +++++++++---------- .../copy_from_upstream/copy_from_upstream.py | 3 +++ .../src/sig/family/CMakeLists.txt | 4 ++-- src/sig/sphincs/CMakeLists.txt | 24 +++++++++---------- .../sig_sphincs_shake256_128f_robust.c | 6 ++--- .../sig_sphincs_shake256_128f_simple.c | 6 ++--- .../sig_sphincs_shake256_128s_robust.c | 6 ++--- .../sig_sphincs_shake256_128s_simple.c | 6 ++--- .../sig_sphincs_shake256_192f_robust.c | 6 ++--- .../sig_sphincs_shake256_192f_simple.c | 6 ++--- .../sig_sphincs_shake256_192s_robust.c | 6 ++--- .../sig_sphincs_shake256_192s_simple.c | 6 ++--- .../sig_sphincs_shake256_256f_robust.c | 6 ++--- .../sig_sphincs_shake256_256f_simple.c | 6 ++--- .../sig_sphincs_shake256_256s_robust.c | 6 ++--- .../sig_sphincs_shake256_256s_simple.c | 6 ++--- 16 files changed, 65 insertions(+), 62 deletions(-) diff --git a/.CMake/alg_support.cmake b/.CMake/alg_support.cmake index 48b39c9dbc..34f2549b31 100644 --- a/.CMake/alg_support.cmake +++ b/.CMake/alg_support.cmake @@ -472,7 +472,7 @@ if(OQS_DIST_X86_64_BUILD OR (OQS_USE_AVX2_INSTRUCTIONS)) endif() if(CMAKE_SYSTEM_NAME MATCHES "Linux|Darwin") -if(OQS_DIST_ARM64_V8_BUILD OR (OQS_USE_ARM_NEON_INSTRUCTIONS AND OQS_USE_SHA3_INSTRUCTIONS)) +if(OQS_DIST_ARM64_V8_BUILD OR (OQS_USE_ARM_NEON_INSTRUCTIONS AND OQS_USE_ARM_SHA3_INSTRUCTIONS)) cmake_dependent_option(OQS_ENABLE_SIG_sphincs_shake256_128f_robust_aarch64 "" ON "OQS_ENABLE_SIG_sphincs_shake256_128f_robust" OFF) endif() endif() @@ -483,7 +483,7 @@ if(OQS_DIST_X86_64_BUILD OR (OQS_USE_AVX2_INSTRUCTIONS)) endif() if(CMAKE_SYSTEM_NAME MATCHES "Linux|Darwin") -if(OQS_DIST_ARM64_V8_BUILD OR (OQS_USE_ARM_NEON_INSTRUCTIONS AND OQS_USE_SHA3_INSTRUCTIONS)) +if(OQS_DIST_ARM64_V8_BUILD OR (OQS_USE_ARM_NEON_INSTRUCTIONS AND OQS_USE_ARM_SHA3_INSTRUCTIONS)) cmake_dependent_option(OQS_ENABLE_SIG_sphincs_shake256_128f_simple_aarch64 "" ON "OQS_ENABLE_SIG_sphincs_shake256_128f_simple" OFF) endif() endif() @@ -494,7 +494,7 @@ if(OQS_DIST_X86_64_BUILD OR (OQS_USE_AVX2_INSTRUCTIONS)) endif() if(CMAKE_SYSTEM_NAME MATCHES "Linux|Darwin") -if(OQS_DIST_ARM64_V8_BUILD OR (OQS_USE_ARM_NEON_INSTRUCTIONS AND OQS_USE_SHA3_INSTRUCTIONS)) +if(OQS_DIST_ARM64_V8_BUILD OR (OQS_USE_ARM_NEON_INSTRUCTIONS AND OQS_USE_ARM_SHA3_INSTRUCTIONS)) cmake_dependent_option(OQS_ENABLE_SIG_sphincs_shake256_128s_robust_aarch64 "" ON "OQS_ENABLE_SIG_sphincs_shake256_128s_robust" OFF) endif() endif() @@ -505,7 +505,7 @@ if(OQS_DIST_X86_64_BUILD OR (OQS_USE_AVX2_INSTRUCTIONS)) endif() if(CMAKE_SYSTEM_NAME MATCHES "Linux|Darwin") -if(OQS_DIST_ARM64_V8_BUILD OR (OQS_USE_ARM_NEON_INSTRUCTIONS AND OQS_USE_SHA3_INSTRUCTIONS)) +if(OQS_DIST_ARM64_V8_BUILD OR (OQS_USE_ARM_NEON_INSTRUCTIONS AND OQS_USE_ARM_SHA3_INSTRUCTIONS)) cmake_dependent_option(OQS_ENABLE_SIG_sphincs_shake256_128s_simple_aarch64 "" ON "OQS_ENABLE_SIG_sphincs_shake256_128s_simple" OFF) endif() endif() @@ -516,7 +516,7 @@ if(OQS_DIST_X86_64_BUILD OR (OQS_USE_AVX2_INSTRUCTIONS)) endif() if(CMAKE_SYSTEM_NAME MATCHES "Linux|Darwin") -if(OQS_DIST_ARM64_V8_BUILD OR (OQS_USE_ARM_NEON_INSTRUCTIONS AND OQS_USE_SHA3_INSTRUCTIONS)) +if(OQS_DIST_ARM64_V8_BUILD OR (OQS_USE_ARM_NEON_INSTRUCTIONS AND OQS_USE_ARM_SHA3_INSTRUCTIONS)) cmake_dependent_option(OQS_ENABLE_SIG_sphincs_shake256_192f_robust_aarch64 "" ON "OQS_ENABLE_SIG_sphincs_shake256_192f_robust" OFF) endif() endif() @@ -527,7 +527,7 @@ if(OQS_DIST_X86_64_BUILD OR (OQS_USE_AVX2_INSTRUCTIONS)) endif() if(CMAKE_SYSTEM_NAME MATCHES "Linux|Darwin") -if(OQS_DIST_ARM64_V8_BUILD OR (OQS_USE_ARM_NEON_INSTRUCTIONS AND OQS_USE_SHA3_INSTRUCTIONS)) +if(OQS_DIST_ARM64_V8_BUILD OR (OQS_USE_ARM_NEON_INSTRUCTIONS AND OQS_USE_ARM_SHA3_INSTRUCTIONS)) cmake_dependent_option(OQS_ENABLE_SIG_sphincs_shake256_192f_simple_aarch64 "" ON "OQS_ENABLE_SIG_sphincs_shake256_192f_simple" OFF) endif() endif() @@ -538,7 +538,7 @@ if(OQS_DIST_X86_64_BUILD OR (OQS_USE_AVX2_INSTRUCTIONS)) endif() if(CMAKE_SYSTEM_NAME MATCHES "Linux|Darwin") -if(OQS_DIST_ARM64_V8_BUILD OR (OQS_USE_ARM_NEON_INSTRUCTIONS AND OQS_USE_SHA3_INSTRUCTIONS)) +if(OQS_DIST_ARM64_V8_BUILD OR (OQS_USE_ARM_NEON_INSTRUCTIONS AND OQS_USE_ARM_SHA3_INSTRUCTIONS)) cmake_dependent_option(OQS_ENABLE_SIG_sphincs_shake256_192s_robust_aarch64 "" ON "OQS_ENABLE_SIG_sphincs_shake256_192s_robust" OFF) endif() endif() @@ -549,7 +549,7 @@ if(OQS_DIST_X86_64_BUILD OR (OQS_USE_AVX2_INSTRUCTIONS)) endif() if(CMAKE_SYSTEM_NAME MATCHES "Linux|Darwin") -if(OQS_DIST_ARM64_V8_BUILD OR (OQS_USE_ARM_NEON_INSTRUCTIONS AND OQS_USE_SHA3_INSTRUCTIONS)) +if(OQS_DIST_ARM64_V8_BUILD OR (OQS_USE_ARM_NEON_INSTRUCTIONS AND OQS_USE_ARM_SHA3_INSTRUCTIONS)) cmake_dependent_option(OQS_ENABLE_SIG_sphincs_shake256_192s_simple_aarch64 "" ON "OQS_ENABLE_SIG_sphincs_shake256_192s_simple" OFF) endif() endif() @@ -560,7 +560,7 @@ if(OQS_DIST_X86_64_BUILD OR (OQS_USE_AVX2_INSTRUCTIONS)) endif() if(CMAKE_SYSTEM_NAME MATCHES "Linux|Darwin") -if(OQS_DIST_ARM64_V8_BUILD OR (OQS_USE_ARM_NEON_INSTRUCTIONS AND OQS_USE_SHA3_INSTRUCTIONS)) +if(OQS_DIST_ARM64_V8_BUILD OR (OQS_USE_ARM_NEON_INSTRUCTIONS AND OQS_USE_ARM_SHA3_INSTRUCTIONS)) cmake_dependent_option(OQS_ENABLE_SIG_sphincs_shake256_256f_robust_aarch64 "" ON "OQS_ENABLE_SIG_sphincs_shake256_256f_robust" OFF) endif() endif() @@ -571,7 +571,7 @@ if(OQS_DIST_X86_64_BUILD OR (OQS_USE_AVX2_INSTRUCTIONS)) endif() if(CMAKE_SYSTEM_NAME MATCHES "Linux|Darwin") -if(OQS_DIST_ARM64_V8_BUILD OR (OQS_USE_ARM_NEON_INSTRUCTIONS AND OQS_USE_SHA3_INSTRUCTIONS)) +if(OQS_DIST_ARM64_V8_BUILD OR (OQS_USE_ARM_NEON_INSTRUCTIONS AND OQS_USE_ARM_SHA3_INSTRUCTIONS)) cmake_dependent_option(OQS_ENABLE_SIG_sphincs_shake256_256f_simple_aarch64 "" ON "OQS_ENABLE_SIG_sphincs_shake256_256f_simple" OFF) endif() endif() @@ -582,7 +582,7 @@ if(OQS_DIST_X86_64_BUILD OR (OQS_USE_AVX2_INSTRUCTIONS)) endif() if(CMAKE_SYSTEM_NAME MATCHES "Linux|Darwin") -if(OQS_DIST_ARM64_V8_BUILD OR (OQS_USE_ARM_NEON_INSTRUCTIONS AND OQS_USE_SHA3_INSTRUCTIONS)) +if(OQS_DIST_ARM64_V8_BUILD OR (OQS_USE_ARM_NEON_INSTRUCTIONS AND OQS_USE_ARM_SHA3_INSTRUCTIONS)) cmake_dependent_option(OQS_ENABLE_SIG_sphincs_shake256_256s_robust_aarch64 "" ON "OQS_ENABLE_SIG_sphincs_shake256_256s_robust" OFF) endif() endif() @@ -593,7 +593,7 @@ if(OQS_DIST_X86_64_BUILD OR (OQS_USE_AVX2_INSTRUCTIONS)) endif() if(CMAKE_SYSTEM_NAME MATCHES "Linux|Darwin") -if(OQS_DIST_ARM64_V8_BUILD OR (OQS_USE_ARM_NEON_INSTRUCTIONS AND OQS_USE_SHA3_INSTRUCTIONS)) +if(OQS_DIST_ARM64_V8_BUILD OR (OQS_USE_ARM_NEON_INSTRUCTIONS AND OQS_USE_ARM_SHA3_INSTRUCTIONS)) cmake_dependent_option(OQS_ENABLE_SIG_sphincs_shake256_256s_simple_aarch64 "" ON "OQS_ENABLE_SIG_sphincs_shake256_256s_simple" OFF) endif() endif() diff --git a/scripts/copy_from_upstream/copy_from_upstream.py b/scripts/copy_from_upstream/copy_from_upstream.py index 1d5a2f8e35..c866cd82bf 100755 --- a/scripts/copy_from_upstream/copy_from_upstream.py +++ b/scripts/copy_from_upstream/copy_from_upstream.py @@ -540,6 +540,9 @@ def process_families(instructions, basedir, with_kat, with_generator): if req['architecture'] == 'ARM64_V8' and 'asimd' in req['required_flags']: req['required_flags'].remove('asimd') req['required_flags'].append('arm_neon') + if req['architecture'] == 'ARM64_V8' and 'sha3' in req['required_flags']: + req['required_flags'].remove('sha3') + req['required_flags'].append('arm_sha3') impl['required_flags'] = req['required_flags'] family['all_required_flags'].update(req['required_flags']) except KeyError as ke: diff --git a/scripts/copy_from_upstream/src/sig/family/CMakeLists.txt b/scripts/copy_from_upstream/src/sig/family/CMakeLists.txt index 0b57461795..60e7d8f2cc 100644 --- a/scripts/copy_from_upstream/src/sig/family/CMakeLists.txt +++ b/scripts/copy_from_upstream/src/sig/family/CMakeLists.txt @@ -12,7 +12,7 @@ if({% for used_by in common_deps_usedby[common_dep['name']] -%}OQS_ENABLE_SIG_{{ add_library({{ family }}_{{ common_dep['name'] }} OBJECT {% for source_file in common_dep['sources_addl']|sort -%}{{ upstream_location }}_{{ common_dep['name'] }}/{{ source_file }}{%- if not loop.last %} {% endif -%}{%- endfor -%}) target_include_directories({{ family }}_{{ common_dep['name'] }} PRIVATE ${CMAKE_CURRENT_LIST_DIR}/{{ upstream_location }}_{{ common_dep['name'] }}) {%- if common_dep['required_flags'] %} - target_compile_options({{ family }}_{{ common_dep['name'] }} PRIVATE {%- for flag in common_dep['required_flags'] %}{%- if flag != 'arm_neon' %} -m{%- if flag == 'bmi1' -%} bmi {%- elif flag == 'sse4_1' -%} sse4.1 {%- elif flag == 'pclmulqdq' -%} pclmul {%- else -%}{{ flag }}{%- endif -%}{%- endif -%}{%- endfor -%}) + target_compile_options({{ family }}_{{ common_dep['name'] }} PRIVATE {%- for flag in common_dep['required_flags'] %}{%- if flag == 'arm_sha3' %} -march=armv8-a+crypto+sha3 {%- else -%}{%- if flag != 'arm_neon' %} -m{%- if flag == 'bmi1' -%} bmi {%- elif flag == 'sse4_1' -%} sse4.1 {%- elif flag == 'pclmulqdq' -%} pclmul {%- else -%}{{ flag }}{%- endif -%}{%- endif -%}{%- endif -%}{%- endfor -%}) {%- endif %} {%- if common_dep['compile_opts'] %} target_compile_options({{ family }}_{{ common_dep['name'] }} PUBLIC {{ common_dep['compile_opts'] }}) @@ -41,7 +41,7 @@ if(OQS_ENABLE_SIG_{{ family }}_{{ scheme['scheme_c'] }}_{{ impl['name'] }}) target_include_directories({{ family }}_{{ scheme['scheme'] }}_{{ impl['name'] }} PRIVATE ${CMAKE_CURRENT_LIST_DIR}/{{ impl['upstream']['name'] }}_{{ scheme['pqclean_scheme'] }}_{{ impl['name'] }}) target_include_directories({{ family }}_{{ scheme['scheme'] }}_{{ impl['name'] }} PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) {%- if impl['name'] != scheme['default_implementation'] and impl['required_flags'] %} - target_compile_options({{ family }}_{{ scheme['scheme'] }}_{{ impl['name'] }} PRIVATE {%- for flag in impl['required_flags'] %}{%- if flag != 'arm_neon' %} -m{%- if flag == 'bmi1' -%} bmi {%- elif flag == 'sse4_1' -%} sse4.1 {%- elif flag == 'pclmulqdq' -%} pclmul {%- else -%}{{ flag }}{%- endif -%}{%- endif -%}{%- endfor -%}) + target_compile_options({{ family }}_{{ scheme['scheme'] }}_{{ impl['name'] }} PRIVATE {%- for flag in impl['required_flags'] %}{%- if flag == 'arm_sha3' %} -march=armv8-a+crypto+sha3 {%- else -%}{%- if flag != 'arm_neon' %} -m{%- if flag == 'bmi1' -%} bmi {%- elif flag == 'sse4_1' -%} sse4.1 {%- elif flag == 'pclmulqdq' -%} pclmul {%- else -%}{{ flag }}{%- endif -%}{%- endif -%}{%- endif -%}{%- endfor -%}) {%- endif %} {%- if impl['compile_opts'] %} target_compile_options({{ family }}_{{ scheme['scheme'] }}_{{ impl['name'] }} PUBLIC {{ impl['compile_opts'] }}) diff --git a/src/sig/sphincs/CMakeLists.txt b/src/sig/sphincs/CMakeLists.txt index 85e70ff235..2c5026566d 100644 --- a/src/sig/sphincs/CMakeLists.txt +++ b/src/sig/sphincs/CMakeLists.txt @@ -384,7 +384,7 @@ if(OQS_ENABLE_SIG_sphincs_shake256_128f_robust_aarch64) add_library(sphincs_shake256_128f_robust_aarch64 OBJECT pqclean_sphincs-shake-128f-robust_aarch64/address.c pqclean_sphincs-shake-128f-robust_aarch64/context_shake.c pqclean_sphincs-shake-128f-robust_aarch64/f1600x2.s pqclean_sphincs-shake-128f-robust_aarch64/f1600x2_const.c pqclean_sphincs-shake-128f-robust_aarch64/fips202x2.c pqclean_sphincs-shake-128f-robust_aarch64/fors.c pqclean_sphincs-shake-128f-robust_aarch64/hash_shake.c pqclean_sphincs-shake-128f-robust_aarch64/hash_shakex2.c pqclean_sphincs-shake-128f-robust_aarch64/merkle.c pqclean_sphincs-shake-128f-robust_aarch64/sign.c pqclean_sphincs-shake-128f-robust_aarch64/thash_shake_robustx2.c pqclean_sphincs-shake-128f-robust_aarch64/utils.c pqclean_sphincs-shake-128f-robust_aarch64/utilsx2.c pqclean_sphincs-shake-128f-robust_aarch64/wots.c) target_include_directories(sphincs_shake256_128f_robust_aarch64 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-shake-128f-robust_aarch64) target_include_directories(sphincs_shake256_128f_robust_aarch64 PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) - target_compile_options(sphincs_shake256_128f_robust_aarch64 PRIVATE -msha3) + target_compile_options(sphincs_shake256_128f_robust_aarch64 PRIVATE -march=armv8-a+crypto+sha3) set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) endif() @@ -407,7 +407,7 @@ if(OQS_ENABLE_SIG_sphincs_shake256_128f_simple_aarch64) add_library(sphincs_shake256_128f_simple_aarch64 OBJECT pqclean_sphincs-shake-128f-simple_aarch64/address.c pqclean_sphincs-shake-128f-simple_aarch64/context_shake.c pqclean_sphincs-shake-128f-simple_aarch64/f1600x2.s pqclean_sphincs-shake-128f-simple_aarch64/f1600x2_const.c pqclean_sphincs-shake-128f-simple_aarch64/fips202x2.c pqclean_sphincs-shake-128f-simple_aarch64/fors.c pqclean_sphincs-shake-128f-simple_aarch64/hash_shake.c pqclean_sphincs-shake-128f-simple_aarch64/hash_shakex2.c pqclean_sphincs-shake-128f-simple_aarch64/merkle.c pqclean_sphincs-shake-128f-simple_aarch64/sign.c pqclean_sphincs-shake-128f-simple_aarch64/thash_shake_simplex2.c pqclean_sphincs-shake-128f-simple_aarch64/utils.c pqclean_sphincs-shake-128f-simple_aarch64/utilsx2.c pqclean_sphincs-shake-128f-simple_aarch64/wots.c) target_include_directories(sphincs_shake256_128f_simple_aarch64 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-shake-128f-simple_aarch64) target_include_directories(sphincs_shake256_128f_simple_aarch64 PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) - target_compile_options(sphincs_shake256_128f_simple_aarch64 PRIVATE -msha3) + target_compile_options(sphincs_shake256_128f_simple_aarch64 PRIVATE -march=armv8-a+crypto+sha3) set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) endif() @@ -430,7 +430,7 @@ if(OQS_ENABLE_SIG_sphincs_shake256_128s_robust_aarch64) add_library(sphincs_shake256_128s_robust_aarch64 OBJECT pqclean_sphincs-shake-128s-robust_aarch64/address.c pqclean_sphincs-shake-128s-robust_aarch64/context_shake.c pqclean_sphincs-shake-128s-robust_aarch64/f1600x2.s pqclean_sphincs-shake-128s-robust_aarch64/f1600x2_const.c pqclean_sphincs-shake-128s-robust_aarch64/fips202x2.c pqclean_sphincs-shake-128s-robust_aarch64/fors.c pqclean_sphincs-shake-128s-robust_aarch64/hash_shake.c pqclean_sphincs-shake-128s-robust_aarch64/hash_shakex2.c pqclean_sphincs-shake-128s-robust_aarch64/merkle.c pqclean_sphincs-shake-128s-robust_aarch64/sign.c pqclean_sphincs-shake-128s-robust_aarch64/thash_shake_robustx2.c pqclean_sphincs-shake-128s-robust_aarch64/utils.c pqclean_sphincs-shake-128s-robust_aarch64/utilsx2.c pqclean_sphincs-shake-128s-robust_aarch64/wots.c) target_include_directories(sphincs_shake256_128s_robust_aarch64 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-shake-128s-robust_aarch64) target_include_directories(sphincs_shake256_128s_robust_aarch64 PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) - target_compile_options(sphincs_shake256_128s_robust_aarch64 PRIVATE -msha3) + target_compile_options(sphincs_shake256_128s_robust_aarch64 PRIVATE -march=armv8-a+crypto+sha3) set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) endif() @@ -453,7 +453,7 @@ if(OQS_ENABLE_SIG_sphincs_shake256_128s_simple_aarch64) add_library(sphincs_shake256_128s_simple_aarch64 OBJECT pqclean_sphincs-shake-128s-simple_aarch64/address.c pqclean_sphincs-shake-128s-simple_aarch64/context_shake.c pqclean_sphincs-shake-128s-simple_aarch64/f1600x2.s pqclean_sphincs-shake-128s-simple_aarch64/f1600x2_const.c pqclean_sphincs-shake-128s-simple_aarch64/fips202x2.c pqclean_sphincs-shake-128s-simple_aarch64/fors.c pqclean_sphincs-shake-128s-simple_aarch64/hash_shake.c pqclean_sphincs-shake-128s-simple_aarch64/hash_shakex2.c pqclean_sphincs-shake-128s-simple_aarch64/merkle.c pqclean_sphincs-shake-128s-simple_aarch64/sign.c pqclean_sphincs-shake-128s-simple_aarch64/thash_shake_simplex2.c pqclean_sphincs-shake-128s-simple_aarch64/utils.c pqclean_sphincs-shake-128s-simple_aarch64/utilsx2.c pqclean_sphincs-shake-128s-simple_aarch64/wots.c) target_include_directories(sphincs_shake256_128s_simple_aarch64 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-shake-128s-simple_aarch64) target_include_directories(sphincs_shake256_128s_simple_aarch64 PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) - target_compile_options(sphincs_shake256_128s_simple_aarch64 PRIVATE -msha3) + target_compile_options(sphincs_shake256_128s_simple_aarch64 PRIVATE -march=armv8-a+crypto+sha3) set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) endif() @@ -476,7 +476,7 @@ if(OQS_ENABLE_SIG_sphincs_shake256_192f_robust_aarch64) add_library(sphincs_shake256_192f_robust_aarch64 OBJECT pqclean_sphincs-shake-192f-robust_aarch64/address.c pqclean_sphincs-shake-192f-robust_aarch64/context_shake.c pqclean_sphincs-shake-192f-robust_aarch64/f1600x2.s pqclean_sphincs-shake-192f-robust_aarch64/f1600x2_const.c pqclean_sphincs-shake-192f-robust_aarch64/fips202x2.c pqclean_sphincs-shake-192f-robust_aarch64/fors.c pqclean_sphincs-shake-192f-robust_aarch64/hash_shake.c pqclean_sphincs-shake-192f-robust_aarch64/hash_shakex2.c pqclean_sphincs-shake-192f-robust_aarch64/merkle.c pqclean_sphincs-shake-192f-robust_aarch64/sign.c pqclean_sphincs-shake-192f-robust_aarch64/thash_shake_robustx2.c pqclean_sphincs-shake-192f-robust_aarch64/utils.c pqclean_sphincs-shake-192f-robust_aarch64/utilsx2.c pqclean_sphincs-shake-192f-robust_aarch64/wots.c) target_include_directories(sphincs_shake256_192f_robust_aarch64 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-shake-192f-robust_aarch64) target_include_directories(sphincs_shake256_192f_robust_aarch64 PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) - target_compile_options(sphincs_shake256_192f_robust_aarch64 PRIVATE -msha3) + target_compile_options(sphincs_shake256_192f_robust_aarch64 PRIVATE -march=armv8-a+crypto+sha3) set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) endif() @@ -499,7 +499,7 @@ if(OQS_ENABLE_SIG_sphincs_shake256_192f_simple_aarch64) add_library(sphincs_shake256_192f_simple_aarch64 OBJECT pqclean_sphincs-shake-192f-simple_aarch64/address.c pqclean_sphincs-shake-192f-simple_aarch64/context_shake.c pqclean_sphincs-shake-192f-simple_aarch64/f1600x2.s pqclean_sphincs-shake-192f-simple_aarch64/f1600x2_const.c pqclean_sphincs-shake-192f-simple_aarch64/fips202x2.c pqclean_sphincs-shake-192f-simple_aarch64/fors.c pqclean_sphincs-shake-192f-simple_aarch64/hash_shake.c pqclean_sphincs-shake-192f-simple_aarch64/hash_shakex2.c pqclean_sphincs-shake-192f-simple_aarch64/merkle.c pqclean_sphincs-shake-192f-simple_aarch64/sign.c pqclean_sphincs-shake-192f-simple_aarch64/thash_shake_simplex2.c pqclean_sphincs-shake-192f-simple_aarch64/utils.c pqclean_sphincs-shake-192f-simple_aarch64/utilsx2.c pqclean_sphincs-shake-192f-simple_aarch64/wots.c) target_include_directories(sphincs_shake256_192f_simple_aarch64 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-shake-192f-simple_aarch64) target_include_directories(sphincs_shake256_192f_simple_aarch64 PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) - target_compile_options(sphincs_shake256_192f_simple_aarch64 PRIVATE -msha3) + target_compile_options(sphincs_shake256_192f_simple_aarch64 PRIVATE -march=armv8-a+crypto+sha3) set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) endif() @@ -522,7 +522,7 @@ if(OQS_ENABLE_SIG_sphincs_shake256_192s_robust_aarch64) add_library(sphincs_shake256_192s_robust_aarch64 OBJECT pqclean_sphincs-shake-192s-robust_aarch64/address.c pqclean_sphincs-shake-192s-robust_aarch64/context_shake.c pqclean_sphincs-shake-192s-robust_aarch64/f1600x2.s pqclean_sphincs-shake-192s-robust_aarch64/f1600x2_const.c pqclean_sphincs-shake-192s-robust_aarch64/fips202x2.c pqclean_sphincs-shake-192s-robust_aarch64/fors.c pqclean_sphincs-shake-192s-robust_aarch64/hash_shake.c pqclean_sphincs-shake-192s-robust_aarch64/hash_shakex2.c pqclean_sphincs-shake-192s-robust_aarch64/merkle.c pqclean_sphincs-shake-192s-robust_aarch64/sign.c pqclean_sphincs-shake-192s-robust_aarch64/thash_shake_robustx2.c pqclean_sphincs-shake-192s-robust_aarch64/utils.c pqclean_sphincs-shake-192s-robust_aarch64/utilsx2.c pqclean_sphincs-shake-192s-robust_aarch64/wots.c) target_include_directories(sphincs_shake256_192s_robust_aarch64 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-shake-192s-robust_aarch64) target_include_directories(sphincs_shake256_192s_robust_aarch64 PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) - target_compile_options(sphincs_shake256_192s_robust_aarch64 PRIVATE -msha3) + target_compile_options(sphincs_shake256_192s_robust_aarch64 PRIVATE -march=armv8-a+crypto+sha3) set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) endif() @@ -545,7 +545,7 @@ if(OQS_ENABLE_SIG_sphincs_shake256_192s_simple_aarch64) add_library(sphincs_shake256_192s_simple_aarch64 OBJECT pqclean_sphincs-shake-192s-simple_aarch64/address.c pqclean_sphincs-shake-192s-simple_aarch64/context_shake.c pqclean_sphincs-shake-192s-simple_aarch64/f1600x2.s pqclean_sphincs-shake-192s-simple_aarch64/f1600x2_const.c pqclean_sphincs-shake-192s-simple_aarch64/fips202x2.c pqclean_sphincs-shake-192s-simple_aarch64/fors.c pqclean_sphincs-shake-192s-simple_aarch64/hash_shake.c pqclean_sphincs-shake-192s-simple_aarch64/hash_shakex2.c pqclean_sphincs-shake-192s-simple_aarch64/merkle.c pqclean_sphincs-shake-192s-simple_aarch64/sign.c pqclean_sphincs-shake-192s-simple_aarch64/thash_shake_simplex2.c pqclean_sphincs-shake-192s-simple_aarch64/utils.c pqclean_sphincs-shake-192s-simple_aarch64/utilsx2.c pqclean_sphincs-shake-192s-simple_aarch64/wots.c) target_include_directories(sphincs_shake256_192s_simple_aarch64 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-shake-192s-simple_aarch64) target_include_directories(sphincs_shake256_192s_simple_aarch64 PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) - target_compile_options(sphincs_shake256_192s_simple_aarch64 PRIVATE -msha3) + target_compile_options(sphincs_shake256_192s_simple_aarch64 PRIVATE -march=armv8-a+crypto+sha3) set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) endif() @@ -568,7 +568,7 @@ if(OQS_ENABLE_SIG_sphincs_shake256_256f_robust_aarch64) add_library(sphincs_shake256_256f_robust_aarch64 OBJECT pqclean_sphincs-shake-256f-robust_aarch64/address.c pqclean_sphincs-shake-256f-robust_aarch64/context_shake.c pqclean_sphincs-shake-256f-robust_aarch64/f1600x2.s pqclean_sphincs-shake-256f-robust_aarch64/f1600x2_const.c pqclean_sphincs-shake-256f-robust_aarch64/fips202x2.c pqclean_sphincs-shake-256f-robust_aarch64/fors.c pqclean_sphincs-shake-256f-robust_aarch64/hash_shake.c pqclean_sphincs-shake-256f-robust_aarch64/hash_shakex2.c pqclean_sphincs-shake-256f-robust_aarch64/merkle.c pqclean_sphincs-shake-256f-robust_aarch64/sign.c pqclean_sphincs-shake-256f-robust_aarch64/thash_shake_robustx2.c pqclean_sphincs-shake-256f-robust_aarch64/utils.c pqclean_sphincs-shake-256f-robust_aarch64/utilsx2.c pqclean_sphincs-shake-256f-robust_aarch64/wots.c) target_include_directories(sphincs_shake256_256f_robust_aarch64 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-shake-256f-robust_aarch64) target_include_directories(sphincs_shake256_256f_robust_aarch64 PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) - target_compile_options(sphincs_shake256_256f_robust_aarch64 PRIVATE -msha3) + target_compile_options(sphincs_shake256_256f_robust_aarch64 PRIVATE -march=armv8-a+crypto+sha3) set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) endif() @@ -591,7 +591,7 @@ if(OQS_ENABLE_SIG_sphincs_shake256_256f_simple_aarch64) add_library(sphincs_shake256_256f_simple_aarch64 OBJECT pqclean_sphincs-shake-256f-simple_aarch64/address.c pqclean_sphincs-shake-256f-simple_aarch64/context_shake.c pqclean_sphincs-shake-256f-simple_aarch64/f1600x2.s pqclean_sphincs-shake-256f-simple_aarch64/f1600x2_const.c pqclean_sphincs-shake-256f-simple_aarch64/fips202x2.c pqclean_sphincs-shake-256f-simple_aarch64/fors.c pqclean_sphincs-shake-256f-simple_aarch64/hash_shake.c pqclean_sphincs-shake-256f-simple_aarch64/hash_shakex2.c pqclean_sphincs-shake-256f-simple_aarch64/merkle.c pqclean_sphincs-shake-256f-simple_aarch64/sign.c pqclean_sphincs-shake-256f-simple_aarch64/thash_shake_simplex2.c pqclean_sphincs-shake-256f-simple_aarch64/utils.c pqclean_sphincs-shake-256f-simple_aarch64/utilsx2.c pqclean_sphincs-shake-256f-simple_aarch64/wots.c) target_include_directories(sphincs_shake256_256f_simple_aarch64 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-shake-256f-simple_aarch64) target_include_directories(sphincs_shake256_256f_simple_aarch64 PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) - target_compile_options(sphincs_shake256_256f_simple_aarch64 PRIVATE -msha3) + target_compile_options(sphincs_shake256_256f_simple_aarch64 PRIVATE -march=armv8-a+crypto+sha3) set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) endif() @@ -614,7 +614,7 @@ if(OQS_ENABLE_SIG_sphincs_shake256_256s_robust_aarch64) add_library(sphincs_shake256_256s_robust_aarch64 OBJECT pqclean_sphincs-shake-256s-robust_aarch64/address.c pqclean_sphincs-shake-256s-robust_aarch64/context_shake.c pqclean_sphincs-shake-256s-robust_aarch64/f1600x2.s pqclean_sphincs-shake-256s-robust_aarch64/f1600x2_const.c pqclean_sphincs-shake-256s-robust_aarch64/fips202x2.c pqclean_sphincs-shake-256s-robust_aarch64/fors.c pqclean_sphincs-shake-256s-robust_aarch64/hash_shake.c pqclean_sphincs-shake-256s-robust_aarch64/hash_shakex2.c pqclean_sphincs-shake-256s-robust_aarch64/merkle.c pqclean_sphincs-shake-256s-robust_aarch64/sign.c pqclean_sphincs-shake-256s-robust_aarch64/thash_shake_robustx2.c pqclean_sphincs-shake-256s-robust_aarch64/utils.c pqclean_sphincs-shake-256s-robust_aarch64/utilsx2.c pqclean_sphincs-shake-256s-robust_aarch64/wots.c) target_include_directories(sphincs_shake256_256s_robust_aarch64 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-shake-256s-robust_aarch64) target_include_directories(sphincs_shake256_256s_robust_aarch64 PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) - target_compile_options(sphincs_shake256_256s_robust_aarch64 PRIVATE -msha3) + target_compile_options(sphincs_shake256_256s_robust_aarch64 PRIVATE -march=armv8-a+crypto+sha3) set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) endif() @@ -637,7 +637,7 @@ if(OQS_ENABLE_SIG_sphincs_shake256_256s_simple_aarch64) add_library(sphincs_shake256_256s_simple_aarch64 OBJECT pqclean_sphincs-shake-256s-simple_aarch64/address.c pqclean_sphincs-shake-256s-simple_aarch64/context_shake.c pqclean_sphincs-shake-256s-simple_aarch64/f1600x2.s pqclean_sphincs-shake-256s-simple_aarch64/f1600x2_const.c pqclean_sphincs-shake-256s-simple_aarch64/fips202x2.c pqclean_sphincs-shake-256s-simple_aarch64/fors.c pqclean_sphincs-shake-256s-simple_aarch64/hash_shake.c pqclean_sphincs-shake-256s-simple_aarch64/hash_shakex2.c pqclean_sphincs-shake-256s-simple_aarch64/merkle.c pqclean_sphincs-shake-256s-simple_aarch64/sign.c pqclean_sphincs-shake-256s-simple_aarch64/thash_shake_simplex2.c pqclean_sphincs-shake-256s-simple_aarch64/utils.c pqclean_sphincs-shake-256s-simple_aarch64/utilsx2.c pqclean_sphincs-shake-256s-simple_aarch64/wots.c) target_include_directories(sphincs_shake256_256s_simple_aarch64 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-shake-256s-simple_aarch64) target_include_directories(sphincs_shake256_256s_simple_aarch64 PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) - target_compile_options(sphincs_shake256_256s_simple_aarch64 PRIVATE -msha3) + target_compile_options(sphincs_shake256_256s_simple_aarch64 PRIVATE -march=armv8-a+crypto+sha3) set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) endif() diff --git a/src/sig/sphincs/sig_sphincs_shake256_128f_robust.c b/src/sig/sphincs/sig_sphincs_shake256_128f_robust.c index af9e1bcf18..7b15bd4223 100644 --- a/src/sig/sphincs/sig_sphincs_shake256_128f_robust.c +++ b/src/sig/sphincs/sig_sphincs_shake256_128f_robust.c @@ -58,7 +58,7 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_128f_robust_keypair(uint8_t *public_ #endif /* OQS_DIST_BUILD */ #elif defined(OQS_ENABLE_SIG_sphincs_shake256_128f_robust_aarch64) #if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_SHA3)) { + if (OQS_CPU_has_extension(OQS_CPU_EXT_ARM_SHA3)) { #endif /* OQS_DIST_BUILD */ return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE128FROBUST_AARCH64_crypto_sign_keypair(public_key, secret_key); #if defined(OQS_DIST_BUILD) @@ -84,7 +84,7 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_128f_robust_sign(uint8_t *signature, #endif /* OQS_DIST_BUILD */ #elif defined(OQS_ENABLE_SIG_sphincs_shake256_128f_robust_aarch64) #if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_SHA3)) { + if (OQS_CPU_has_extension(OQS_CPU_EXT_ARM_SHA3)) { #endif /* OQS_DIST_BUILD */ return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE128FROBUST_AARCH64_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); #if defined(OQS_DIST_BUILD) @@ -110,7 +110,7 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_128f_robust_verify(const uint8_t *me #endif /* OQS_DIST_BUILD */ #elif defined(OQS_ENABLE_SIG_sphincs_shake256_128f_robust_aarch64) #if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_SHA3)) { + if (OQS_CPU_has_extension(OQS_CPU_EXT_ARM_SHA3)) { #endif /* OQS_DIST_BUILD */ return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE128FROBUST_AARCH64_crypto_sign_verify(signature, signature_len, message, message_len, public_key); #if defined(OQS_DIST_BUILD) diff --git a/src/sig/sphincs/sig_sphincs_shake256_128f_simple.c b/src/sig/sphincs/sig_sphincs_shake256_128f_simple.c index aa1a01d2fb..b5fe2a4ec5 100644 --- a/src/sig/sphincs/sig_sphincs_shake256_128f_simple.c +++ b/src/sig/sphincs/sig_sphincs_shake256_128f_simple.c @@ -58,7 +58,7 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_128f_simple_keypair(uint8_t *public_ #endif /* OQS_DIST_BUILD */ #elif defined(OQS_ENABLE_SIG_sphincs_shake256_128f_simple_aarch64) #if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_SHA3)) { + if (OQS_CPU_has_extension(OQS_CPU_EXT_ARM_SHA3)) { #endif /* OQS_DIST_BUILD */ return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE128FSIMPLE_AARCH64_crypto_sign_keypair(public_key, secret_key); #if defined(OQS_DIST_BUILD) @@ -84,7 +84,7 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_128f_simple_sign(uint8_t *signature, #endif /* OQS_DIST_BUILD */ #elif defined(OQS_ENABLE_SIG_sphincs_shake256_128f_simple_aarch64) #if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_SHA3)) { + if (OQS_CPU_has_extension(OQS_CPU_EXT_ARM_SHA3)) { #endif /* OQS_DIST_BUILD */ return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE128FSIMPLE_AARCH64_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); #if defined(OQS_DIST_BUILD) @@ -110,7 +110,7 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_128f_simple_verify(const uint8_t *me #endif /* OQS_DIST_BUILD */ #elif defined(OQS_ENABLE_SIG_sphincs_shake256_128f_simple_aarch64) #if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_SHA3)) { + if (OQS_CPU_has_extension(OQS_CPU_EXT_ARM_SHA3)) { #endif /* OQS_DIST_BUILD */ return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE128FSIMPLE_AARCH64_crypto_sign_verify(signature, signature_len, message, message_len, public_key); #if defined(OQS_DIST_BUILD) diff --git a/src/sig/sphincs/sig_sphincs_shake256_128s_robust.c b/src/sig/sphincs/sig_sphincs_shake256_128s_robust.c index 0561673341..d8ee5dfee8 100644 --- a/src/sig/sphincs/sig_sphincs_shake256_128s_robust.c +++ b/src/sig/sphincs/sig_sphincs_shake256_128s_robust.c @@ -58,7 +58,7 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_128s_robust_keypair(uint8_t *public_ #endif /* OQS_DIST_BUILD */ #elif defined(OQS_ENABLE_SIG_sphincs_shake256_128s_robust_aarch64) #if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_SHA3)) { + if (OQS_CPU_has_extension(OQS_CPU_EXT_ARM_SHA3)) { #endif /* OQS_DIST_BUILD */ return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE128SROBUST_AARCH64_crypto_sign_keypair(public_key, secret_key); #if defined(OQS_DIST_BUILD) @@ -84,7 +84,7 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_128s_robust_sign(uint8_t *signature, #endif /* OQS_DIST_BUILD */ #elif defined(OQS_ENABLE_SIG_sphincs_shake256_128s_robust_aarch64) #if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_SHA3)) { + if (OQS_CPU_has_extension(OQS_CPU_EXT_ARM_SHA3)) { #endif /* OQS_DIST_BUILD */ return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE128SROBUST_AARCH64_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); #if defined(OQS_DIST_BUILD) @@ -110,7 +110,7 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_128s_robust_verify(const uint8_t *me #endif /* OQS_DIST_BUILD */ #elif defined(OQS_ENABLE_SIG_sphincs_shake256_128s_robust_aarch64) #if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_SHA3)) { + if (OQS_CPU_has_extension(OQS_CPU_EXT_ARM_SHA3)) { #endif /* OQS_DIST_BUILD */ return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE128SROBUST_AARCH64_crypto_sign_verify(signature, signature_len, message, message_len, public_key); #if defined(OQS_DIST_BUILD) diff --git a/src/sig/sphincs/sig_sphincs_shake256_128s_simple.c b/src/sig/sphincs/sig_sphincs_shake256_128s_simple.c index c636dcf800..3e7c682ab9 100644 --- a/src/sig/sphincs/sig_sphincs_shake256_128s_simple.c +++ b/src/sig/sphincs/sig_sphincs_shake256_128s_simple.c @@ -58,7 +58,7 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_128s_simple_keypair(uint8_t *public_ #endif /* OQS_DIST_BUILD */ #elif defined(OQS_ENABLE_SIG_sphincs_shake256_128s_simple_aarch64) #if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_SHA3)) { + if (OQS_CPU_has_extension(OQS_CPU_EXT_ARM_SHA3)) { #endif /* OQS_DIST_BUILD */ return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE128SSIMPLE_AARCH64_crypto_sign_keypair(public_key, secret_key); #if defined(OQS_DIST_BUILD) @@ -84,7 +84,7 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_128s_simple_sign(uint8_t *signature, #endif /* OQS_DIST_BUILD */ #elif defined(OQS_ENABLE_SIG_sphincs_shake256_128s_simple_aarch64) #if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_SHA3)) { + if (OQS_CPU_has_extension(OQS_CPU_EXT_ARM_SHA3)) { #endif /* OQS_DIST_BUILD */ return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE128SSIMPLE_AARCH64_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); #if defined(OQS_DIST_BUILD) @@ -110,7 +110,7 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_128s_simple_verify(const uint8_t *me #endif /* OQS_DIST_BUILD */ #elif defined(OQS_ENABLE_SIG_sphincs_shake256_128s_simple_aarch64) #if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_SHA3)) { + if (OQS_CPU_has_extension(OQS_CPU_EXT_ARM_SHA3)) { #endif /* OQS_DIST_BUILD */ return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE128SSIMPLE_AARCH64_crypto_sign_verify(signature, signature_len, message, message_len, public_key); #if defined(OQS_DIST_BUILD) diff --git a/src/sig/sphincs/sig_sphincs_shake256_192f_robust.c b/src/sig/sphincs/sig_sphincs_shake256_192f_robust.c index 2fe5f3fbd6..827c3a4ffd 100644 --- a/src/sig/sphincs/sig_sphincs_shake256_192f_robust.c +++ b/src/sig/sphincs/sig_sphincs_shake256_192f_robust.c @@ -58,7 +58,7 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_192f_robust_keypair(uint8_t *public_ #endif /* OQS_DIST_BUILD */ #elif defined(OQS_ENABLE_SIG_sphincs_shake256_192f_robust_aarch64) #if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_SHA3)) { + if (OQS_CPU_has_extension(OQS_CPU_EXT_ARM_SHA3)) { #endif /* OQS_DIST_BUILD */ return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE192FROBUST_AARCH64_crypto_sign_keypair(public_key, secret_key); #if defined(OQS_DIST_BUILD) @@ -84,7 +84,7 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_192f_robust_sign(uint8_t *signature, #endif /* OQS_DIST_BUILD */ #elif defined(OQS_ENABLE_SIG_sphincs_shake256_192f_robust_aarch64) #if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_SHA3)) { + if (OQS_CPU_has_extension(OQS_CPU_EXT_ARM_SHA3)) { #endif /* OQS_DIST_BUILD */ return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE192FROBUST_AARCH64_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); #if defined(OQS_DIST_BUILD) @@ -110,7 +110,7 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_192f_robust_verify(const uint8_t *me #endif /* OQS_DIST_BUILD */ #elif defined(OQS_ENABLE_SIG_sphincs_shake256_192f_robust_aarch64) #if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_SHA3)) { + if (OQS_CPU_has_extension(OQS_CPU_EXT_ARM_SHA3)) { #endif /* OQS_DIST_BUILD */ return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE192FROBUST_AARCH64_crypto_sign_verify(signature, signature_len, message, message_len, public_key); #if defined(OQS_DIST_BUILD) diff --git a/src/sig/sphincs/sig_sphincs_shake256_192f_simple.c b/src/sig/sphincs/sig_sphincs_shake256_192f_simple.c index 5c03294503..8afdabc120 100644 --- a/src/sig/sphincs/sig_sphincs_shake256_192f_simple.c +++ b/src/sig/sphincs/sig_sphincs_shake256_192f_simple.c @@ -58,7 +58,7 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_192f_simple_keypair(uint8_t *public_ #endif /* OQS_DIST_BUILD */ #elif defined(OQS_ENABLE_SIG_sphincs_shake256_192f_simple_aarch64) #if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_SHA3)) { + if (OQS_CPU_has_extension(OQS_CPU_EXT_ARM_SHA3)) { #endif /* OQS_DIST_BUILD */ return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE192FSIMPLE_AARCH64_crypto_sign_keypair(public_key, secret_key); #if defined(OQS_DIST_BUILD) @@ -84,7 +84,7 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_192f_simple_sign(uint8_t *signature, #endif /* OQS_DIST_BUILD */ #elif defined(OQS_ENABLE_SIG_sphincs_shake256_192f_simple_aarch64) #if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_SHA3)) { + if (OQS_CPU_has_extension(OQS_CPU_EXT_ARM_SHA3)) { #endif /* OQS_DIST_BUILD */ return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE192FSIMPLE_AARCH64_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); #if defined(OQS_DIST_BUILD) @@ -110,7 +110,7 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_192f_simple_verify(const uint8_t *me #endif /* OQS_DIST_BUILD */ #elif defined(OQS_ENABLE_SIG_sphincs_shake256_192f_simple_aarch64) #if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_SHA3)) { + if (OQS_CPU_has_extension(OQS_CPU_EXT_ARM_SHA3)) { #endif /* OQS_DIST_BUILD */ return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE192FSIMPLE_AARCH64_crypto_sign_verify(signature, signature_len, message, message_len, public_key); #if defined(OQS_DIST_BUILD) diff --git a/src/sig/sphincs/sig_sphincs_shake256_192s_robust.c b/src/sig/sphincs/sig_sphincs_shake256_192s_robust.c index 572c102528..6299f87b55 100644 --- a/src/sig/sphincs/sig_sphincs_shake256_192s_robust.c +++ b/src/sig/sphincs/sig_sphincs_shake256_192s_robust.c @@ -58,7 +58,7 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_192s_robust_keypair(uint8_t *public_ #endif /* OQS_DIST_BUILD */ #elif defined(OQS_ENABLE_SIG_sphincs_shake256_192s_robust_aarch64) #if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_SHA3)) { + if (OQS_CPU_has_extension(OQS_CPU_EXT_ARM_SHA3)) { #endif /* OQS_DIST_BUILD */ return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE192SROBUST_AARCH64_crypto_sign_keypair(public_key, secret_key); #if defined(OQS_DIST_BUILD) @@ -84,7 +84,7 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_192s_robust_sign(uint8_t *signature, #endif /* OQS_DIST_BUILD */ #elif defined(OQS_ENABLE_SIG_sphincs_shake256_192s_robust_aarch64) #if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_SHA3)) { + if (OQS_CPU_has_extension(OQS_CPU_EXT_ARM_SHA3)) { #endif /* OQS_DIST_BUILD */ return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE192SROBUST_AARCH64_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); #if defined(OQS_DIST_BUILD) @@ -110,7 +110,7 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_192s_robust_verify(const uint8_t *me #endif /* OQS_DIST_BUILD */ #elif defined(OQS_ENABLE_SIG_sphincs_shake256_192s_robust_aarch64) #if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_SHA3)) { + if (OQS_CPU_has_extension(OQS_CPU_EXT_ARM_SHA3)) { #endif /* OQS_DIST_BUILD */ return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE192SROBUST_AARCH64_crypto_sign_verify(signature, signature_len, message, message_len, public_key); #if defined(OQS_DIST_BUILD) diff --git a/src/sig/sphincs/sig_sphincs_shake256_192s_simple.c b/src/sig/sphincs/sig_sphincs_shake256_192s_simple.c index bc859c315a..66fe37f19b 100644 --- a/src/sig/sphincs/sig_sphincs_shake256_192s_simple.c +++ b/src/sig/sphincs/sig_sphincs_shake256_192s_simple.c @@ -58,7 +58,7 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_192s_simple_keypair(uint8_t *public_ #endif /* OQS_DIST_BUILD */ #elif defined(OQS_ENABLE_SIG_sphincs_shake256_192s_simple_aarch64) #if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_SHA3)) { + if (OQS_CPU_has_extension(OQS_CPU_EXT_ARM_SHA3)) { #endif /* OQS_DIST_BUILD */ return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE192SSIMPLE_AARCH64_crypto_sign_keypair(public_key, secret_key); #if defined(OQS_DIST_BUILD) @@ -84,7 +84,7 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_192s_simple_sign(uint8_t *signature, #endif /* OQS_DIST_BUILD */ #elif defined(OQS_ENABLE_SIG_sphincs_shake256_192s_simple_aarch64) #if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_SHA3)) { + if (OQS_CPU_has_extension(OQS_CPU_EXT_ARM_SHA3)) { #endif /* OQS_DIST_BUILD */ return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE192SSIMPLE_AARCH64_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); #if defined(OQS_DIST_BUILD) @@ -110,7 +110,7 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_192s_simple_verify(const uint8_t *me #endif /* OQS_DIST_BUILD */ #elif defined(OQS_ENABLE_SIG_sphincs_shake256_192s_simple_aarch64) #if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_SHA3)) { + if (OQS_CPU_has_extension(OQS_CPU_EXT_ARM_SHA3)) { #endif /* OQS_DIST_BUILD */ return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE192SSIMPLE_AARCH64_crypto_sign_verify(signature, signature_len, message, message_len, public_key); #if defined(OQS_DIST_BUILD) diff --git a/src/sig/sphincs/sig_sphincs_shake256_256f_robust.c b/src/sig/sphincs/sig_sphincs_shake256_256f_robust.c index 30aae47e8a..47cd89e6f9 100644 --- a/src/sig/sphincs/sig_sphincs_shake256_256f_robust.c +++ b/src/sig/sphincs/sig_sphincs_shake256_256f_robust.c @@ -58,7 +58,7 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_256f_robust_keypair(uint8_t *public_ #endif /* OQS_DIST_BUILD */ #elif defined(OQS_ENABLE_SIG_sphincs_shake256_256f_robust_aarch64) #if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_SHA3)) { + if (OQS_CPU_has_extension(OQS_CPU_EXT_ARM_SHA3)) { #endif /* OQS_DIST_BUILD */ return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256FROBUST_AARCH64_crypto_sign_keypair(public_key, secret_key); #if defined(OQS_DIST_BUILD) @@ -84,7 +84,7 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_256f_robust_sign(uint8_t *signature, #endif /* OQS_DIST_BUILD */ #elif defined(OQS_ENABLE_SIG_sphincs_shake256_256f_robust_aarch64) #if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_SHA3)) { + if (OQS_CPU_has_extension(OQS_CPU_EXT_ARM_SHA3)) { #endif /* OQS_DIST_BUILD */ return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256FROBUST_AARCH64_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); #if defined(OQS_DIST_BUILD) @@ -110,7 +110,7 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_256f_robust_verify(const uint8_t *me #endif /* OQS_DIST_BUILD */ #elif defined(OQS_ENABLE_SIG_sphincs_shake256_256f_robust_aarch64) #if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_SHA3)) { + if (OQS_CPU_has_extension(OQS_CPU_EXT_ARM_SHA3)) { #endif /* OQS_DIST_BUILD */ return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256FROBUST_AARCH64_crypto_sign_verify(signature, signature_len, message, message_len, public_key); #if defined(OQS_DIST_BUILD) diff --git a/src/sig/sphincs/sig_sphincs_shake256_256f_simple.c b/src/sig/sphincs/sig_sphincs_shake256_256f_simple.c index 23f5b365d0..e424d1fba1 100644 --- a/src/sig/sphincs/sig_sphincs_shake256_256f_simple.c +++ b/src/sig/sphincs/sig_sphincs_shake256_256f_simple.c @@ -58,7 +58,7 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_256f_simple_keypair(uint8_t *public_ #endif /* OQS_DIST_BUILD */ #elif defined(OQS_ENABLE_SIG_sphincs_shake256_256f_simple_aarch64) #if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_SHA3)) { + if (OQS_CPU_has_extension(OQS_CPU_EXT_ARM_SHA3)) { #endif /* OQS_DIST_BUILD */ return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256FSIMPLE_AARCH64_crypto_sign_keypair(public_key, secret_key); #if defined(OQS_DIST_BUILD) @@ -84,7 +84,7 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_256f_simple_sign(uint8_t *signature, #endif /* OQS_DIST_BUILD */ #elif defined(OQS_ENABLE_SIG_sphincs_shake256_256f_simple_aarch64) #if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_SHA3)) { + if (OQS_CPU_has_extension(OQS_CPU_EXT_ARM_SHA3)) { #endif /* OQS_DIST_BUILD */ return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256FSIMPLE_AARCH64_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); #if defined(OQS_DIST_BUILD) @@ -110,7 +110,7 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_256f_simple_verify(const uint8_t *me #endif /* OQS_DIST_BUILD */ #elif defined(OQS_ENABLE_SIG_sphincs_shake256_256f_simple_aarch64) #if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_SHA3)) { + if (OQS_CPU_has_extension(OQS_CPU_EXT_ARM_SHA3)) { #endif /* OQS_DIST_BUILD */ return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256FSIMPLE_AARCH64_crypto_sign_verify(signature, signature_len, message, message_len, public_key); #if defined(OQS_DIST_BUILD) diff --git a/src/sig/sphincs/sig_sphincs_shake256_256s_robust.c b/src/sig/sphincs/sig_sphincs_shake256_256s_robust.c index d3af3f79f5..aa56dccc26 100644 --- a/src/sig/sphincs/sig_sphincs_shake256_256s_robust.c +++ b/src/sig/sphincs/sig_sphincs_shake256_256s_robust.c @@ -58,7 +58,7 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_256s_robust_keypair(uint8_t *public_ #endif /* OQS_DIST_BUILD */ #elif defined(OQS_ENABLE_SIG_sphincs_shake256_256s_robust_aarch64) #if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_SHA3)) { + if (OQS_CPU_has_extension(OQS_CPU_EXT_ARM_SHA3)) { #endif /* OQS_DIST_BUILD */ return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256SROBUST_AARCH64_crypto_sign_keypair(public_key, secret_key); #if defined(OQS_DIST_BUILD) @@ -84,7 +84,7 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_256s_robust_sign(uint8_t *signature, #endif /* OQS_DIST_BUILD */ #elif defined(OQS_ENABLE_SIG_sphincs_shake256_256s_robust_aarch64) #if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_SHA3)) { + if (OQS_CPU_has_extension(OQS_CPU_EXT_ARM_SHA3)) { #endif /* OQS_DIST_BUILD */ return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256SROBUST_AARCH64_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); #if defined(OQS_DIST_BUILD) @@ -110,7 +110,7 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_256s_robust_verify(const uint8_t *me #endif /* OQS_DIST_BUILD */ #elif defined(OQS_ENABLE_SIG_sphincs_shake256_256s_robust_aarch64) #if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_SHA3)) { + if (OQS_CPU_has_extension(OQS_CPU_EXT_ARM_SHA3)) { #endif /* OQS_DIST_BUILD */ return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256SROBUST_AARCH64_crypto_sign_verify(signature, signature_len, message, message_len, public_key); #if defined(OQS_DIST_BUILD) diff --git a/src/sig/sphincs/sig_sphincs_shake256_256s_simple.c b/src/sig/sphincs/sig_sphincs_shake256_256s_simple.c index db904b8945..fb68fb3f7d 100644 --- a/src/sig/sphincs/sig_sphincs_shake256_256s_simple.c +++ b/src/sig/sphincs/sig_sphincs_shake256_256s_simple.c @@ -58,7 +58,7 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_256s_simple_keypair(uint8_t *public_ #endif /* OQS_DIST_BUILD */ #elif defined(OQS_ENABLE_SIG_sphincs_shake256_256s_simple_aarch64) #if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_SHA3)) { + if (OQS_CPU_has_extension(OQS_CPU_EXT_ARM_SHA3)) { #endif /* OQS_DIST_BUILD */ return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256SSIMPLE_AARCH64_crypto_sign_keypair(public_key, secret_key); #if defined(OQS_DIST_BUILD) @@ -84,7 +84,7 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_256s_simple_sign(uint8_t *signature, #endif /* OQS_DIST_BUILD */ #elif defined(OQS_ENABLE_SIG_sphincs_shake256_256s_simple_aarch64) #if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_SHA3)) { + if (OQS_CPU_has_extension(OQS_CPU_EXT_ARM_SHA3)) { #endif /* OQS_DIST_BUILD */ return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256SSIMPLE_AARCH64_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); #if defined(OQS_DIST_BUILD) @@ -110,7 +110,7 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_256s_simple_verify(const uint8_t *me #endif /* OQS_DIST_BUILD */ #elif defined(OQS_ENABLE_SIG_sphincs_shake256_256s_simple_aarch64) #if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_SHA3)) { + if (OQS_CPU_has_extension(OQS_CPU_EXT_ARM_SHA3)) { #endif /* OQS_DIST_BUILD */ return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256SSIMPLE_AARCH64_crypto_sign_verify(signature, signature_len, message, message_len, public_key); #if defined(OQS_DIST_BUILD) From f19172f44f4960262bbd4e6b1b5683efd7de79c4 Mon Sep 17 00:00:00 2001 From: Douglas Stebila Date: Sun, 19 Mar 2023 14:06:01 -0400 Subject: [PATCH 05/10] Remove SPHINCS+ robust and Haraka variants --- .../copy_from_upstream/copy_from_upstream.yml | 120 ------------------ 1 file changed, 120 deletions(-) diff --git a/scripts/copy_from_upstream/copy_from_upstream.yml b/scripts/copy_from_upstream/copy_from_upstream.yml index acd4ed707b..04e8896e5f 100644 --- a/scripts/copy_from_upstream/copy_from_upstream.yml +++ b/scripts/copy_from_upstream/copy_from_upstream.yml @@ -181,181 +181,61 @@ sigs: default_implementation: clean upstream_location: pqclean schemes: - - - scheme: haraka_128f_robust - pqclean_scheme: sphincs-haraka-128f-robust - pretty_name_full: SPHINCS+-Haraka-128f-robust - signed_msg_order: sig_then_msg - - - scheme: haraka_128f_simple - pqclean_scheme: sphincs-haraka-128f-simple - pretty_name_full: SPHINCS+-Haraka-128f-simple - signed_msg_order: sig_then_msg - - - scheme: haraka_128s_robust - pqclean_scheme: sphincs-haraka-128s-robust - pretty_name_full: SPHINCS+-Haraka-128s-robust - signed_msg_order: sig_then_msg - - - scheme: haraka_128s_simple - pqclean_scheme: sphincs-haraka-128s-simple - pretty_name_full: SPHINCS+-Haraka-128s-simple - signed_msg_order: sig_then_msg - - - scheme: haraka_192f_robust - pqclean_scheme: sphincs-haraka-192f-robust - pretty_name_full: SPHINCS+-Haraka-192f-robust - signed_msg_order: sig_then_msg - - - scheme: haraka_192f_simple - pqclean_scheme: sphincs-haraka-192f-simple - pretty_name_full: SPHINCS+-Haraka-192f-simple - signed_msg_order: sig_then_msg - - - scheme: haraka_192s_robust - pqclean_scheme: sphincs-haraka-192s-robust - pretty_name_full: SPHINCS+-Haraka-192s-robust - signed_msg_order: sig_then_msg - - - scheme: haraka_192s_simple - pqclean_scheme: sphincs-haraka-192s-simple - pretty_name_full: SPHINCS+-Haraka-192s-simple - signed_msg_order: sig_then_msg - - - scheme: haraka_256f_robust - pqclean_scheme: sphincs-haraka-256f-robust - pretty_name_full: SPHINCS+-Haraka-256f-robust - signed_msg_order: sig_then_msg - - - scheme: haraka_256f_simple - pqclean_scheme: sphincs-haraka-256f-simple - pretty_name_full: SPHINCS+-Haraka-256f-simple - signed_msg_order: sig_then_msg - - - scheme: haraka_256s_robust - pqclean_scheme: sphincs-haraka-256s-robust - pretty_name_full: SPHINCS+-Haraka-256s-robust - signed_msg_order: sig_then_msg - - - scheme: haraka_256s_simple - pqclean_scheme: sphincs-haraka-256s-simple - pretty_name_full: SPHINCS+-Haraka-256s-simple - signed_msg_order: sig_then_msg - - - scheme: sha256_128f_robust - pqclean_scheme: sphincs-sha2-128f-robust - pretty_name_full: SPHINCS+-SHA256-128f-robust - signed_msg_order: sig_then_msg - scheme: sha256_128f_simple pqclean_scheme: sphincs-sha2-128f-simple pretty_name_full: SPHINCS+-SHA256-128f-simple signed_msg_order: sig_then_msg - - - scheme: sha256_128s_robust - pqclean_scheme: sphincs-sha2-128s-robust - pretty_name_full: SPHINCS+-SHA256-128s-robust - signed_msg_order: sig_then_msg - scheme: sha256_128s_simple pqclean_scheme: sphincs-sha2-128s-simple pretty_name_full: SPHINCS+-SHA256-128s-simple signed_msg_order: sig_then_msg - - - scheme: sha256_192f_robust - pqclean_scheme: sphincs-sha2-192f-robust - pretty_name_full: SPHINCS+-SHA256-192f-robust - signed_msg_order: sig_then_msg - scheme: sha256_192f_simple pqclean_scheme: sphincs-sha2-192f-simple pretty_name_full: SPHINCS+-SHA256-192f-simple signed_msg_order: sig_then_msg - - - scheme: sha256_192s_robust - pqclean_scheme: sphincs-sha2-192s-robust - pretty_name_full: SPHINCS+-SHA256-192s-robust - signed_msg_order: sig_then_msg - scheme: sha256_192s_simple pqclean_scheme: sphincs-sha2-192s-simple pretty_name_full: SPHINCS+-SHA256-192s-simple signed_msg_order: sig_then_msg - - - scheme: sha256_256f_robust - pqclean_scheme: sphincs-sha2-256f-robust - pretty_name_full: SPHINCS+-SHA256-256f-robust - signed_msg_order: sig_then_msg - scheme: sha256_256f_simple pqclean_scheme: sphincs-sha2-256f-simple pretty_name_full: SPHINCS+-SHA256-256f-simple signed_msg_order: sig_then_msg - - - scheme: sha256_256s_robust - pqclean_scheme: sphincs-sha2-256s-robust - pretty_name_full: SPHINCS+-SHA256-256s-robust - signed_msg_order: sig_then_msg - scheme: sha256_256s_simple pqclean_scheme: sphincs-sha2-256s-simple pretty_name_full: SPHINCS+-SHA256-256s-simple signed_msg_order: sig_then_msg - - - scheme: shake256_128f_robust - pqclean_scheme: sphincs-shake-128f-robust - pretty_name_full: SPHINCS+-SHAKE256-128f-robust - signed_msg_order: sig_then_msg - scheme: shake256_128f_simple pqclean_scheme: sphincs-shake-128f-simple pretty_name_full: SPHINCS+-SHAKE256-128f-simple signed_msg_order: sig_then_msg - - - scheme: shake256_128s_robust - pqclean_scheme: sphincs-shake-128s-robust - pretty_name_full: SPHINCS+-SHAKE256-128s-robust - signed_msg_order: sig_then_msg - scheme: shake256_128s_simple pqclean_scheme: sphincs-shake-128s-simple pretty_name_full: SPHINCS+-SHAKE256-128s-simple signed_msg_order: sig_then_msg - - - scheme: shake256_192f_robust - pqclean_scheme: sphincs-shake-192f-robust - pretty_name_full: SPHINCS+-SHAKE256-192f-robust - signed_msg_order: sig_then_msg - scheme: shake256_192f_simple pqclean_scheme: sphincs-shake-192f-simple pretty_name_full: SPHINCS+-SHAKE256-192f-simple signed_msg_order: sig_then_msg - - - scheme: shake256_192s_robust - pqclean_scheme: sphincs-shake-192s-robust - pretty_name_full: SPHINCS+-SHAKE256-192s-robust - signed_msg_order: sig_then_msg - scheme: shake256_192s_simple pqclean_scheme: sphincs-shake-192s-simple pretty_name_full: SPHINCS+-SHAKE256-192s-simple signed_msg_order: sig_then_msg - - - scheme: shake256_256f_robust - pqclean_scheme: sphincs-shake-256f-robust - pretty_name_full: SPHINCS+-SHAKE256-256f-robust - signed_msg_order: sig_then_msg - scheme: shake256_256f_simple pqclean_scheme: sphincs-shake-256f-simple pretty_name_full: SPHINCS+-SHAKE256-256f-simple signed_msg_order: sig_then_msg - - - scheme: shake256_256s_robust - pqclean_scheme: sphincs-shake-256s-robust - pretty_name_full: SPHINCS+-SHAKE256-256s-robust - signed_msg_order: sig_then_msg - scheme: shake256_256s_simple pqclean_scheme: sphincs-shake-256s-simple From 33427db7456c1ae48f446f8c4acd840b8d7baf9c Mon Sep 17 00:00:00 2001 From: Douglas Stebila Date: Sun, 19 Mar 2023 14:07:02 -0400 Subject: [PATCH 06/10] Apply copy_from_upstream --- .CMake/alg_support.cmake | 156 ------------- src/oqsconfig.h.cmake | 54 ----- src/sig/sig.c | 312 ------------------------- src/sig/sig.h | 50 +--- src/sig/sphincs/CMakeLists.txt | 408 --------------------------------- src/sig/sphincs/sig_sphincs.h | 264 --------------------- tests/kat_sig.c | 240 ------------------- 7 files changed, 1 insertion(+), 1483 deletions(-) diff --git a/.CMake/alg_support.cmake b/.CMake/alg_support.cmake index 34f2549b31..9a57cedf50 100644 --- a/.CMake/alg_support.cmake +++ b/.CMake/alg_support.cmake @@ -346,137 +346,36 @@ endif() option(OQS_ENABLE_SIG_SPHINCS "Enable sphincs algorithm family" ON) -cmake_dependent_option(OQS_ENABLE_SIG_sphincs_haraka_128f_robust "" ON "OQS_ENABLE_SIG_SPHINCS" OFF) -if(OQS_DIST_X86_64_BUILD OR (OQS_USE_AES_INSTRUCTIONS)) - cmake_dependent_option(OQS_ENABLE_SIG_sphincs_haraka_128f_robust_aesni "" ON "OQS_ENABLE_SIG_sphincs_haraka_128f_robust" OFF) -endif() - -cmake_dependent_option(OQS_ENABLE_SIG_sphincs_haraka_128f_simple "" ON "OQS_ENABLE_SIG_SPHINCS" OFF) -if(OQS_DIST_X86_64_BUILD OR (OQS_USE_AES_INSTRUCTIONS)) - cmake_dependent_option(OQS_ENABLE_SIG_sphincs_haraka_128f_simple_aesni "" ON "OQS_ENABLE_SIG_sphincs_haraka_128f_simple" OFF) -endif() - -cmake_dependent_option(OQS_ENABLE_SIG_sphincs_haraka_128s_robust "" ON "OQS_ENABLE_SIG_SPHINCS" OFF) -if(OQS_DIST_X86_64_BUILD OR (OQS_USE_AES_INSTRUCTIONS)) - cmake_dependent_option(OQS_ENABLE_SIG_sphincs_haraka_128s_robust_aesni "" ON "OQS_ENABLE_SIG_sphincs_haraka_128s_robust" OFF) -endif() - -cmake_dependent_option(OQS_ENABLE_SIG_sphincs_haraka_128s_simple "" ON "OQS_ENABLE_SIG_SPHINCS" OFF) -if(OQS_DIST_X86_64_BUILD OR (OQS_USE_AES_INSTRUCTIONS)) - cmake_dependent_option(OQS_ENABLE_SIG_sphincs_haraka_128s_simple_aesni "" ON "OQS_ENABLE_SIG_sphincs_haraka_128s_simple" OFF) -endif() - -cmake_dependent_option(OQS_ENABLE_SIG_sphincs_haraka_192f_robust "" ON "OQS_ENABLE_SIG_SPHINCS" OFF) -if(OQS_DIST_X86_64_BUILD OR (OQS_USE_AES_INSTRUCTIONS)) - cmake_dependent_option(OQS_ENABLE_SIG_sphincs_haraka_192f_robust_aesni "" ON "OQS_ENABLE_SIG_sphincs_haraka_192f_robust" OFF) -endif() - -cmake_dependent_option(OQS_ENABLE_SIG_sphincs_haraka_192f_simple "" ON "OQS_ENABLE_SIG_SPHINCS" OFF) -if(OQS_DIST_X86_64_BUILD OR (OQS_USE_AES_INSTRUCTIONS)) - cmake_dependent_option(OQS_ENABLE_SIG_sphincs_haraka_192f_simple_aesni "" ON "OQS_ENABLE_SIG_sphincs_haraka_192f_simple" OFF) -endif() - -cmake_dependent_option(OQS_ENABLE_SIG_sphincs_haraka_192s_robust "" ON "OQS_ENABLE_SIG_SPHINCS" OFF) -if(OQS_DIST_X86_64_BUILD OR (OQS_USE_AES_INSTRUCTIONS)) - cmake_dependent_option(OQS_ENABLE_SIG_sphincs_haraka_192s_robust_aesni "" ON "OQS_ENABLE_SIG_sphincs_haraka_192s_robust" OFF) -endif() - -cmake_dependent_option(OQS_ENABLE_SIG_sphincs_haraka_192s_simple "" ON "OQS_ENABLE_SIG_SPHINCS" OFF) -if(OQS_DIST_X86_64_BUILD OR (OQS_USE_AES_INSTRUCTIONS)) - cmake_dependent_option(OQS_ENABLE_SIG_sphincs_haraka_192s_simple_aesni "" ON "OQS_ENABLE_SIG_sphincs_haraka_192s_simple" OFF) -endif() - -cmake_dependent_option(OQS_ENABLE_SIG_sphincs_haraka_256f_robust "" ON "OQS_ENABLE_SIG_SPHINCS" OFF) -if(OQS_DIST_X86_64_BUILD OR (OQS_USE_AES_INSTRUCTIONS)) - cmake_dependent_option(OQS_ENABLE_SIG_sphincs_haraka_256f_robust_aesni "" ON "OQS_ENABLE_SIG_sphincs_haraka_256f_robust" OFF) -endif() - -cmake_dependent_option(OQS_ENABLE_SIG_sphincs_haraka_256f_simple "" ON "OQS_ENABLE_SIG_SPHINCS" OFF) -if(OQS_DIST_X86_64_BUILD OR (OQS_USE_AES_INSTRUCTIONS)) - cmake_dependent_option(OQS_ENABLE_SIG_sphincs_haraka_256f_simple_aesni "" ON "OQS_ENABLE_SIG_sphincs_haraka_256f_simple" OFF) -endif() - -cmake_dependent_option(OQS_ENABLE_SIG_sphincs_haraka_256s_robust "" ON "OQS_ENABLE_SIG_SPHINCS" OFF) -if(OQS_DIST_X86_64_BUILD OR (OQS_USE_AES_INSTRUCTIONS)) - cmake_dependent_option(OQS_ENABLE_SIG_sphincs_haraka_256s_robust_aesni "" ON "OQS_ENABLE_SIG_sphincs_haraka_256s_robust" OFF) -endif() - -cmake_dependent_option(OQS_ENABLE_SIG_sphincs_haraka_256s_simple "" ON "OQS_ENABLE_SIG_SPHINCS" OFF) -if(OQS_DIST_X86_64_BUILD OR (OQS_USE_AES_INSTRUCTIONS)) - cmake_dependent_option(OQS_ENABLE_SIG_sphincs_haraka_256s_simple_aesni "" ON "OQS_ENABLE_SIG_sphincs_haraka_256s_simple" OFF) -endif() - -cmake_dependent_option(OQS_ENABLE_SIG_sphincs_sha256_128f_robust "" ON "OQS_ENABLE_SIG_SPHINCS" OFF) -if(OQS_DIST_X86_64_BUILD OR (OQS_USE_AVX2_INSTRUCTIONS)) - cmake_dependent_option(OQS_ENABLE_SIG_sphincs_sha256_128f_robust_avx2 "" ON "OQS_ENABLE_SIG_sphincs_sha256_128f_robust" OFF) -endif() - cmake_dependent_option(OQS_ENABLE_SIG_sphincs_sha256_128f_simple "" ON "OQS_ENABLE_SIG_SPHINCS" OFF) if(OQS_DIST_X86_64_BUILD OR (OQS_USE_AVX2_INSTRUCTIONS)) cmake_dependent_option(OQS_ENABLE_SIG_sphincs_sha256_128f_simple_avx2 "" ON "OQS_ENABLE_SIG_sphincs_sha256_128f_simple" OFF) endif() -cmake_dependent_option(OQS_ENABLE_SIG_sphincs_sha256_128s_robust "" ON "OQS_ENABLE_SIG_SPHINCS" OFF) -if(OQS_DIST_X86_64_BUILD OR (OQS_USE_AVX2_INSTRUCTIONS)) - cmake_dependent_option(OQS_ENABLE_SIG_sphincs_sha256_128s_robust_avx2 "" ON "OQS_ENABLE_SIG_sphincs_sha256_128s_robust" OFF) -endif() - cmake_dependent_option(OQS_ENABLE_SIG_sphincs_sha256_128s_simple "" ON "OQS_ENABLE_SIG_SPHINCS" OFF) if(OQS_DIST_X86_64_BUILD OR (OQS_USE_AVX2_INSTRUCTIONS)) cmake_dependent_option(OQS_ENABLE_SIG_sphincs_sha256_128s_simple_avx2 "" ON "OQS_ENABLE_SIG_sphincs_sha256_128s_simple" OFF) endif() -cmake_dependent_option(OQS_ENABLE_SIG_sphincs_sha256_192f_robust "" ON "OQS_ENABLE_SIG_SPHINCS" OFF) -if(OQS_DIST_X86_64_BUILD OR (OQS_USE_AVX2_INSTRUCTIONS)) - cmake_dependent_option(OQS_ENABLE_SIG_sphincs_sha256_192f_robust_avx2 "" ON "OQS_ENABLE_SIG_sphincs_sha256_192f_robust" OFF) -endif() - cmake_dependent_option(OQS_ENABLE_SIG_sphincs_sha256_192f_simple "" ON "OQS_ENABLE_SIG_SPHINCS" OFF) if(OQS_DIST_X86_64_BUILD OR (OQS_USE_AVX2_INSTRUCTIONS)) cmake_dependent_option(OQS_ENABLE_SIG_sphincs_sha256_192f_simple_avx2 "" ON "OQS_ENABLE_SIG_sphincs_sha256_192f_simple" OFF) endif() -cmake_dependent_option(OQS_ENABLE_SIG_sphincs_sha256_192s_robust "" ON "OQS_ENABLE_SIG_SPHINCS" OFF) -if(OQS_DIST_X86_64_BUILD OR (OQS_USE_AVX2_INSTRUCTIONS)) - cmake_dependent_option(OQS_ENABLE_SIG_sphincs_sha256_192s_robust_avx2 "" ON "OQS_ENABLE_SIG_sphincs_sha256_192s_robust" OFF) -endif() - cmake_dependent_option(OQS_ENABLE_SIG_sphincs_sha256_192s_simple "" ON "OQS_ENABLE_SIG_SPHINCS" OFF) if(OQS_DIST_X86_64_BUILD OR (OQS_USE_AVX2_INSTRUCTIONS)) cmake_dependent_option(OQS_ENABLE_SIG_sphincs_sha256_192s_simple_avx2 "" ON "OQS_ENABLE_SIG_sphincs_sha256_192s_simple" OFF) endif() -cmake_dependent_option(OQS_ENABLE_SIG_sphincs_sha256_256f_robust "" ON "OQS_ENABLE_SIG_SPHINCS" OFF) -if(OQS_DIST_X86_64_BUILD OR (OQS_USE_AVX2_INSTRUCTIONS)) - cmake_dependent_option(OQS_ENABLE_SIG_sphincs_sha256_256f_robust_avx2 "" ON "OQS_ENABLE_SIG_sphincs_sha256_256f_robust" OFF) -endif() - cmake_dependent_option(OQS_ENABLE_SIG_sphincs_sha256_256f_simple "" ON "OQS_ENABLE_SIG_SPHINCS" OFF) if(OQS_DIST_X86_64_BUILD OR (OQS_USE_AVX2_INSTRUCTIONS)) cmake_dependent_option(OQS_ENABLE_SIG_sphincs_sha256_256f_simple_avx2 "" ON "OQS_ENABLE_SIG_sphincs_sha256_256f_simple" OFF) endif() -cmake_dependent_option(OQS_ENABLE_SIG_sphincs_sha256_256s_robust "" ON "OQS_ENABLE_SIG_SPHINCS" OFF) -if(OQS_DIST_X86_64_BUILD OR (OQS_USE_AVX2_INSTRUCTIONS)) - cmake_dependent_option(OQS_ENABLE_SIG_sphincs_sha256_256s_robust_avx2 "" ON "OQS_ENABLE_SIG_sphincs_sha256_256s_robust" OFF) -endif() - cmake_dependent_option(OQS_ENABLE_SIG_sphincs_sha256_256s_simple "" ON "OQS_ENABLE_SIG_SPHINCS" OFF) if(OQS_DIST_X86_64_BUILD OR (OQS_USE_AVX2_INSTRUCTIONS)) cmake_dependent_option(OQS_ENABLE_SIG_sphincs_sha256_256s_simple_avx2 "" ON "OQS_ENABLE_SIG_sphincs_sha256_256s_simple" OFF) endif() -cmake_dependent_option(OQS_ENABLE_SIG_sphincs_shake256_128f_robust "" ON "OQS_ENABLE_SIG_SPHINCS" OFF) -if(OQS_DIST_X86_64_BUILD OR (OQS_USE_AVX2_INSTRUCTIONS)) - cmake_dependent_option(OQS_ENABLE_SIG_sphincs_shake256_128f_robust_avx2 "" ON "OQS_ENABLE_SIG_sphincs_shake256_128f_robust" OFF) -endif() - -if(CMAKE_SYSTEM_NAME MATCHES "Linux|Darwin") -if(OQS_DIST_ARM64_V8_BUILD OR (OQS_USE_ARM_NEON_INSTRUCTIONS AND OQS_USE_ARM_SHA3_INSTRUCTIONS)) - cmake_dependent_option(OQS_ENABLE_SIG_sphincs_shake256_128f_robust_aarch64 "" ON "OQS_ENABLE_SIG_sphincs_shake256_128f_robust" OFF) -endif() -endif() - cmake_dependent_option(OQS_ENABLE_SIG_sphincs_shake256_128f_simple "" ON "OQS_ENABLE_SIG_SPHINCS" OFF) if(OQS_DIST_X86_64_BUILD OR (OQS_USE_AVX2_INSTRUCTIONS)) cmake_dependent_option(OQS_ENABLE_SIG_sphincs_shake256_128f_simple_avx2 "" ON "OQS_ENABLE_SIG_sphincs_shake256_128f_simple" OFF) @@ -488,17 +387,6 @@ if(OQS_DIST_ARM64_V8_BUILD OR (OQS_USE_ARM_NEON_INSTRUCTIONS AND OQS_USE_ARM_SHA endif() endif() -cmake_dependent_option(OQS_ENABLE_SIG_sphincs_shake256_128s_robust "" ON "OQS_ENABLE_SIG_SPHINCS" OFF) -if(OQS_DIST_X86_64_BUILD OR (OQS_USE_AVX2_INSTRUCTIONS)) - cmake_dependent_option(OQS_ENABLE_SIG_sphincs_shake256_128s_robust_avx2 "" ON "OQS_ENABLE_SIG_sphincs_shake256_128s_robust" OFF) -endif() - -if(CMAKE_SYSTEM_NAME MATCHES "Linux|Darwin") -if(OQS_DIST_ARM64_V8_BUILD OR (OQS_USE_ARM_NEON_INSTRUCTIONS AND OQS_USE_ARM_SHA3_INSTRUCTIONS)) - cmake_dependent_option(OQS_ENABLE_SIG_sphincs_shake256_128s_robust_aarch64 "" ON "OQS_ENABLE_SIG_sphincs_shake256_128s_robust" OFF) -endif() -endif() - cmake_dependent_option(OQS_ENABLE_SIG_sphincs_shake256_128s_simple "" ON "OQS_ENABLE_SIG_SPHINCS" OFF) if(OQS_DIST_X86_64_BUILD OR (OQS_USE_AVX2_INSTRUCTIONS)) cmake_dependent_option(OQS_ENABLE_SIG_sphincs_shake256_128s_simple_avx2 "" ON "OQS_ENABLE_SIG_sphincs_shake256_128s_simple" OFF) @@ -510,17 +398,6 @@ if(OQS_DIST_ARM64_V8_BUILD OR (OQS_USE_ARM_NEON_INSTRUCTIONS AND OQS_USE_ARM_SHA endif() endif() -cmake_dependent_option(OQS_ENABLE_SIG_sphincs_shake256_192f_robust "" ON "OQS_ENABLE_SIG_SPHINCS" OFF) -if(OQS_DIST_X86_64_BUILD OR (OQS_USE_AVX2_INSTRUCTIONS)) - cmake_dependent_option(OQS_ENABLE_SIG_sphincs_shake256_192f_robust_avx2 "" ON "OQS_ENABLE_SIG_sphincs_shake256_192f_robust" OFF) -endif() - -if(CMAKE_SYSTEM_NAME MATCHES "Linux|Darwin") -if(OQS_DIST_ARM64_V8_BUILD OR (OQS_USE_ARM_NEON_INSTRUCTIONS AND OQS_USE_ARM_SHA3_INSTRUCTIONS)) - cmake_dependent_option(OQS_ENABLE_SIG_sphincs_shake256_192f_robust_aarch64 "" ON "OQS_ENABLE_SIG_sphincs_shake256_192f_robust" OFF) -endif() -endif() - cmake_dependent_option(OQS_ENABLE_SIG_sphincs_shake256_192f_simple "" ON "OQS_ENABLE_SIG_SPHINCS" OFF) if(OQS_DIST_X86_64_BUILD OR (OQS_USE_AVX2_INSTRUCTIONS)) cmake_dependent_option(OQS_ENABLE_SIG_sphincs_shake256_192f_simple_avx2 "" ON "OQS_ENABLE_SIG_sphincs_shake256_192f_simple" OFF) @@ -532,17 +409,6 @@ if(OQS_DIST_ARM64_V8_BUILD OR (OQS_USE_ARM_NEON_INSTRUCTIONS AND OQS_USE_ARM_SHA endif() endif() -cmake_dependent_option(OQS_ENABLE_SIG_sphincs_shake256_192s_robust "" ON "OQS_ENABLE_SIG_SPHINCS" OFF) -if(OQS_DIST_X86_64_BUILD OR (OQS_USE_AVX2_INSTRUCTIONS)) - cmake_dependent_option(OQS_ENABLE_SIG_sphincs_shake256_192s_robust_avx2 "" ON "OQS_ENABLE_SIG_sphincs_shake256_192s_robust" OFF) -endif() - -if(CMAKE_SYSTEM_NAME MATCHES "Linux|Darwin") -if(OQS_DIST_ARM64_V8_BUILD OR (OQS_USE_ARM_NEON_INSTRUCTIONS AND OQS_USE_ARM_SHA3_INSTRUCTIONS)) - cmake_dependent_option(OQS_ENABLE_SIG_sphincs_shake256_192s_robust_aarch64 "" ON "OQS_ENABLE_SIG_sphincs_shake256_192s_robust" OFF) -endif() -endif() - cmake_dependent_option(OQS_ENABLE_SIG_sphincs_shake256_192s_simple "" ON "OQS_ENABLE_SIG_SPHINCS" OFF) if(OQS_DIST_X86_64_BUILD OR (OQS_USE_AVX2_INSTRUCTIONS)) cmake_dependent_option(OQS_ENABLE_SIG_sphincs_shake256_192s_simple_avx2 "" ON "OQS_ENABLE_SIG_sphincs_shake256_192s_simple" OFF) @@ -554,17 +420,6 @@ if(OQS_DIST_ARM64_V8_BUILD OR (OQS_USE_ARM_NEON_INSTRUCTIONS AND OQS_USE_ARM_SHA endif() endif() -cmake_dependent_option(OQS_ENABLE_SIG_sphincs_shake256_256f_robust "" ON "OQS_ENABLE_SIG_SPHINCS" OFF) -if(OQS_DIST_X86_64_BUILD OR (OQS_USE_AVX2_INSTRUCTIONS)) - cmake_dependent_option(OQS_ENABLE_SIG_sphincs_shake256_256f_robust_avx2 "" ON "OQS_ENABLE_SIG_sphincs_shake256_256f_robust" OFF) -endif() - -if(CMAKE_SYSTEM_NAME MATCHES "Linux|Darwin") -if(OQS_DIST_ARM64_V8_BUILD OR (OQS_USE_ARM_NEON_INSTRUCTIONS AND OQS_USE_ARM_SHA3_INSTRUCTIONS)) - cmake_dependent_option(OQS_ENABLE_SIG_sphincs_shake256_256f_robust_aarch64 "" ON "OQS_ENABLE_SIG_sphincs_shake256_256f_robust" OFF) -endif() -endif() - cmake_dependent_option(OQS_ENABLE_SIG_sphincs_shake256_256f_simple "" ON "OQS_ENABLE_SIG_SPHINCS" OFF) if(OQS_DIST_X86_64_BUILD OR (OQS_USE_AVX2_INSTRUCTIONS)) cmake_dependent_option(OQS_ENABLE_SIG_sphincs_shake256_256f_simple_avx2 "" ON "OQS_ENABLE_SIG_sphincs_shake256_256f_simple" OFF) @@ -576,17 +431,6 @@ if(OQS_DIST_ARM64_V8_BUILD OR (OQS_USE_ARM_NEON_INSTRUCTIONS AND OQS_USE_ARM_SHA endif() endif() -cmake_dependent_option(OQS_ENABLE_SIG_sphincs_shake256_256s_robust "" ON "OQS_ENABLE_SIG_SPHINCS" OFF) -if(OQS_DIST_X86_64_BUILD OR (OQS_USE_AVX2_INSTRUCTIONS)) - cmake_dependent_option(OQS_ENABLE_SIG_sphincs_shake256_256s_robust_avx2 "" ON "OQS_ENABLE_SIG_sphincs_shake256_256s_robust" OFF) -endif() - -if(CMAKE_SYSTEM_NAME MATCHES "Linux|Darwin") -if(OQS_DIST_ARM64_V8_BUILD OR (OQS_USE_ARM_NEON_INSTRUCTIONS AND OQS_USE_ARM_SHA3_INSTRUCTIONS)) - cmake_dependent_option(OQS_ENABLE_SIG_sphincs_shake256_256s_robust_aarch64 "" ON "OQS_ENABLE_SIG_sphincs_shake256_256s_robust" OFF) -endif() -endif() - cmake_dependent_option(OQS_ENABLE_SIG_sphincs_shake256_256s_simple "" ON "OQS_ENABLE_SIG_SPHINCS" OFF) if(OQS_DIST_X86_64_BUILD OR (OQS_USE_AVX2_INSTRUCTIONS)) cmake_dependent_option(OQS_ENABLE_SIG_sphincs_shake256_256s_simple_avx2 "" ON "OQS_ENABLE_SIG_sphincs_shake256_256s_simple" OFF) diff --git a/src/oqsconfig.h.cmake b/src/oqsconfig.h.cmake index bedf439852..bbbe189921 100644 --- a/src/oqsconfig.h.cmake +++ b/src/oqsconfig.h.cmake @@ -140,87 +140,33 @@ #cmakedefine OQS_ENABLE_SIG_falcon_1024_avx2 1 #cmakedefine OQS_ENABLE_SIG_SPHINCS 1 -#cmakedefine OQS_ENABLE_SIG_sphincs_haraka_128f_robust 1 -#cmakedefine OQS_ENABLE_SIG_sphincs_haraka_128f_robust_aesni 1 -#cmakedefine OQS_ENABLE_SIG_sphincs_haraka_128f_simple 1 -#cmakedefine OQS_ENABLE_SIG_sphincs_haraka_128f_simple_aesni 1 -#cmakedefine OQS_ENABLE_SIG_sphincs_haraka_128s_robust 1 -#cmakedefine OQS_ENABLE_SIG_sphincs_haraka_128s_robust_aesni 1 -#cmakedefine OQS_ENABLE_SIG_sphincs_haraka_128s_simple 1 -#cmakedefine OQS_ENABLE_SIG_sphincs_haraka_128s_simple_aesni 1 -#cmakedefine OQS_ENABLE_SIG_sphincs_haraka_192f_robust 1 -#cmakedefine OQS_ENABLE_SIG_sphincs_haraka_192f_robust_aesni 1 -#cmakedefine OQS_ENABLE_SIG_sphincs_haraka_192f_simple 1 -#cmakedefine OQS_ENABLE_SIG_sphincs_haraka_192f_simple_aesni 1 -#cmakedefine OQS_ENABLE_SIG_sphincs_haraka_192s_robust 1 -#cmakedefine OQS_ENABLE_SIG_sphincs_haraka_192s_robust_aesni 1 -#cmakedefine OQS_ENABLE_SIG_sphincs_haraka_192s_simple 1 -#cmakedefine OQS_ENABLE_SIG_sphincs_haraka_192s_simple_aesni 1 -#cmakedefine OQS_ENABLE_SIG_sphincs_haraka_256f_robust 1 -#cmakedefine OQS_ENABLE_SIG_sphincs_haraka_256f_robust_aesni 1 -#cmakedefine OQS_ENABLE_SIG_sphincs_haraka_256f_simple 1 -#cmakedefine OQS_ENABLE_SIG_sphincs_haraka_256f_simple_aesni 1 -#cmakedefine OQS_ENABLE_SIG_sphincs_haraka_256s_robust 1 -#cmakedefine OQS_ENABLE_SIG_sphincs_haraka_256s_robust_aesni 1 -#cmakedefine OQS_ENABLE_SIG_sphincs_haraka_256s_simple 1 -#cmakedefine OQS_ENABLE_SIG_sphincs_haraka_256s_simple_aesni 1 -#cmakedefine OQS_ENABLE_SIG_sphincs_sha256_128f_robust 1 -#cmakedefine OQS_ENABLE_SIG_sphincs_sha256_128f_robust_avx2 1 #cmakedefine OQS_ENABLE_SIG_sphincs_sha256_128f_simple 1 #cmakedefine OQS_ENABLE_SIG_sphincs_sha256_128f_simple_avx2 1 -#cmakedefine OQS_ENABLE_SIG_sphincs_sha256_128s_robust 1 -#cmakedefine OQS_ENABLE_SIG_sphincs_sha256_128s_robust_avx2 1 #cmakedefine OQS_ENABLE_SIG_sphincs_sha256_128s_simple 1 #cmakedefine OQS_ENABLE_SIG_sphincs_sha256_128s_simple_avx2 1 -#cmakedefine OQS_ENABLE_SIG_sphincs_sha256_192f_robust 1 -#cmakedefine OQS_ENABLE_SIG_sphincs_sha256_192f_robust_avx2 1 #cmakedefine OQS_ENABLE_SIG_sphincs_sha256_192f_simple 1 #cmakedefine OQS_ENABLE_SIG_sphincs_sha256_192f_simple_avx2 1 -#cmakedefine OQS_ENABLE_SIG_sphincs_sha256_192s_robust 1 -#cmakedefine OQS_ENABLE_SIG_sphincs_sha256_192s_robust_avx2 1 #cmakedefine OQS_ENABLE_SIG_sphincs_sha256_192s_simple 1 #cmakedefine OQS_ENABLE_SIG_sphincs_sha256_192s_simple_avx2 1 -#cmakedefine OQS_ENABLE_SIG_sphincs_sha256_256f_robust 1 -#cmakedefine OQS_ENABLE_SIG_sphincs_sha256_256f_robust_avx2 1 #cmakedefine OQS_ENABLE_SIG_sphincs_sha256_256f_simple 1 #cmakedefine OQS_ENABLE_SIG_sphincs_sha256_256f_simple_avx2 1 -#cmakedefine OQS_ENABLE_SIG_sphincs_sha256_256s_robust 1 -#cmakedefine OQS_ENABLE_SIG_sphincs_sha256_256s_robust_avx2 1 #cmakedefine OQS_ENABLE_SIG_sphincs_sha256_256s_simple 1 #cmakedefine OQS_ENABLE_SIG_sphincs_sha256_256s_simple_avx2 1 -#cmakedefine OQS_ENABLE_SIG_sphincs_shake256_128f_robust 1 -#cmakedefine OQS_ENABLE_SIG_sphincs_shake256_128f_robust_avx2 1 -#cmakedefine OQS_ENABLE_SIG_sphincs_shake256_128f_robust_aarch64 1 #cmakedefine OQS_ENABLE_SIG_sphincs_shake256_128f_simple 1 #cmakedefine OQS_ENABLE_SIG_sphincs_shake256_128f_simple_avx2 1 #cmakedefine OQS_ENABLE_SIG_sphincs_shake256_128f_simple_aarch64 1 -#cmakedefine OQS_ENABLE_SIG_sphincs_shake256_128s_robust 1 -#cmakedefine OQS_ENABLE_SIG_sphincs_shake256_128s_robust_avx2 1 -#cmakedefine OQS_ENABLE_SIG_sphincs_shake256_128s_robust_aarch64 1 #cmakedefine OQS_ENABLE_SIG_sphincs_shake256_128s_simple 1 #cmakedefine OQS_ENABLE_SIG_sphincs_shake256_128s_simple_avx2 1 #cmakedefine OQS_ENABLE_SIG_sphincs_shake256_128s_simple_aarch64 1 -#cmakedefine OQS_ENABLE_SIG_sphincs_shake256_192f_robust 1 -#cmakedefine OQS_ENABLE_SIG_sphincs_shake256_192f_robust_avx2 1 -#cmakedefine OQS_ENABLE_SIG_sphincs_shake256_192f_robust_aarch64 1 #cmakedefine OQS_ENABLE_SIG_sphincs_shake256_192f_simple 1 #cmakedefine OQS_ENABLE_SIG_sphincs_shake256_192f_simple_avx2 1 #cmakedefine OQS_ENABLE_SIG_sphincs_shake256_192f_simple_aarch64 1 -#cmakedefine OQS_ENABLE_SIG_sphincs_shake256_192s_robust 1 -#cmakedefine OQS_ENABLE_SIG_sphincs_shake256_192s_robust_avx2 1 -#cmakedefine OQS_ENABLE_SIG_sphincs_shake256_192s_robust_aarch64 1 #cmakedefine OQS_ENABLE_SIG_sphincs_shake256_192s_simple 1 #cmakedefine OQS_ENABLE_SIG_sphincs_shake256_192s_simple_avx2 1 #cmakedefine OQS_ENABLE_SIG_sphincs_shake256_192s_simple_aarch64 1 -#cmakedefine OQS_ENABLE_SIG_sphincs_shake256_256f_robust 1 -#cmakedefine OQS_ENABLE_SIG_sphincs_shake256_256f_robust_avx2 1 -#cmakedefine OQS_ENABLE_SIG_sphincs_shake256_256f_robust_aarch64 1 #cmakedefine OQS_ENABLE_SIG_sphincs_shake256_256f_simple 1 #cmakedefine OQS_ENABLE_SIG_sphincs_shake256_256f_simple_avx2 1 #cmakedefine OQS_ENABLE_SIG_sphincs_shake256_256f_simple_aarch64 1 -#cmakedefine OQS_ENABLE_SIG_sphincs_shake256_256s_robust 1 -#cmakedefine OQS_ENABLE_SIG_sphincs_shake256_256s_robust_avx2 1 -#cmakedefine OQS_ENABLE_SIG_sphincs_shake256_256s_robust_aarch64 1 #cmakedefine OQS_ENABLE_SIG_sphincs_shake256_256s_simple 1 #cmakedefine OQS_ENABLE_SIG_sphincs_shake256_256s_simple_avx2 1 #cmakedefine OQS_ENABLE_SIG_sphincs_shake256_256s_simple_aarch64 1 diff --git a/src/sig/sig.c b/src/sig/sig.c index 7642ac494d..4542c877d6 100644 --- a/src/sig/sig.c +++ b/src/sig/sig.c @@ -23,41 +23,17 @@ OQS_API const char *OQS_SIG_alg_identifier(size_t i) { OQS_SIG_alg_dilithium_5_aes, OQS_SIG_alg_falcon_512, OQS_SIG_alg_falcon_1024, - OQS_SIG_alg_sphincs_haraka_128f_robust, - OQS_SIG_alg_sphincs_haraka_128f_simple, - OQS_SIG_alg_sphincs_haraka_128s_robust, - OQS_SIG_alg_sphincs_haraka_128s_simple, - OQS_SIG_alg_sphincs_haraka_192f_robust, - OQS_SIG_alg_sphincs_haraka_192f_simple, - OQS_SIG_alg_sphincs_haraka_192s_robust, - OQS_SIG_alg_sphincs_haraka_192s_simple, - OQS_SIG_alg_sphincs_haraka_256f_robust, - OQS_SIG_alg_sphincs_haraka_256f_simple, - OQS_SIG_alg_sphincs_haraka_256s_robust, - OQS_SIG_alg_sphincs_haraka_256s_simple, - OQS_SIG_alg_sphincs_sha256_128f_robust, OQS_SIG_alg_sphincs_sha256_128f_simple, - OQS_SIG_alg_sphincs_sha256_128s_robust, OQS_SIG_alg_sphincs_sha256_128s_simple, - OQS_SIG_alg_sphincs_sha256_192f_robust, OQS_SIG_alg_sphincs_sha256_192f_simple, - OQS_SIG_alg_sphincs_sha256_192s_robust, OQS_SIG_alg_sphincs_sha256_192s_simple, - OQS_SIG_alg_sphincs_sha256_256f_robust, OQS_SIG_alg_sphincs_sha256_256f_simple, - OQS_SIG_alg_sphincs_sha256_256s_robust, OQS_SIG_alg_sphincs_sha256_256s_simple, - OQS_SIG_alg_sphincs_shake256_128f_robust, OQS_SIG_alg_sphincs_shake256_128f_simple, - OQS_SIG_alg_sphincs_shake256_128s_robust, OQS_SIG_alg_sphincs_shake256_128s_simple, - OQS_SIG_alg_sphincs_shake256_192f_robust, OQS_SIG_alg_sphincs_shake256_192f_simple, - OQS_SIG_alg_sphincs_shake256_192s_robust, OQS_SIG_alg_sphincs_shake256_192s_simple, - OQS_SIG_alg_sphincs_shake256_256f_robust, OQS_SIG_alg_sphincs_shake256_256f_simple, - OQS_SIG_alg_sphincs_shake256_256s_robust, OQS_SIG_alg_sphincs_shake256_256s_simple, ///// OQS_COPY_FROM_UPSTREAM_FRAGMENT_ALG_IDENTIFIER_END }; @@ -125,216 +101,72 @@ OQS_API int OQS_SIG_alg_is_enabled(const char *method_name) { return 1; #else return 0; -#endif - } else if (0 == strcasecmp(method_name, OQS_SIG_alg_sphincs_haraka_128f_robust)) { -#ifdef OQS_ENABLE_SIG_sphincs_haraka_128f_robust - return 1; -#else - return 0; -#endif - } else if (0 == strcasecmp(method_name, OQS_SIG_alg_sphincs_haraka_128f_simple)) { -#ifdef OQS_ENABLE_SIG_sphincs_haraka_128f_simple - return 1; -#else - return 0; -#endif - } else if (0 == strcasecmp(method_name, OQS_SIG_alg_sphincs_haraka_128s_robust)) { -#ifdef OQS_ENABLE_SIG_sphincs_haraka_128s_robust - return 1; -#else - return 0; -#endif - } else if (0 == strcasecmp(method_name, OQS_SIG_alg_sphincs_haraka_128s_simple)) { -#ifdef OQS_ENABLE_SIG_sphincs_haraka_128s_simple - return 1; -#else - return 0; -#endif - } else if (0 == strcasecmp(method_name, OQS_SIG_alg_sphincs_haraka_192f_robust)) { -#ifdef OQS_ENABLE_SIG_sphincs_haraka_192f_robust - return 1; -#else - return 0; -#endif - } else if (0 == strcasecmp(method_name, OQS_SIG_alg_sphincs_haraka_192f_simple)) { -#ifdef OQS_ENABLE_SIG_sphincs_haraka_192f_simple - return 1; -#else - return 0; -#endif - } else if (0 == strcasecmp(method_name, OQS_SIG_alg_sphincs_haraka_192s_robust)) { -#ifdef OQS_ENABLE_SIG_sphincs_haraka_192s_robust - return 1; -#else - return 0; -#endif - } else if (0 == strcasecmp(method_name, OQS_SIG_alg_sphincs_haraka_192s_simple)) { -#ifdef OQS_ENABLE_SIG_sphincs_haraka_192s_simple - return 1; -#else - return 0; -#endif - } else if (0 == strcasecmp(method_name, OQS_SIG_alg_sphincs_haraka_256f_robust)) { -#ifdef OQS_ENABLE_SIG_sphincs_haraka_256f_robust - return 1; -#else - return 0; -#endif - } else if (0 == strcasecmp(method_name, OQS_SIG_alg_sphincs_haraka_256f_simple)) { -#ifdef OQS_ENABLE_SIG_sphincs_haraka_256f_simple - return 1; -#else - return 0; -#endif - } else if (0 == strcasecmp(method_name, OQS_SIG_alg_sphincs_haraka_256s_robust)) { -#ifdef OQS_ENABLE_SIG_sphincs_haraka_256s_robust - return 1; -#else - return 0; -#endif - } else if (0 == strcasecmp(method_name, OQS_SIG_alg_sphincs_haraka_256s_simple)) { -#ifdef OQS_ENABLE_SIG_sphincs_haraka_256s_simple - return 1; -#else - return 0; -#endif - } else if (0 == strcasecmp(method_name, OQS_SIG_alg_sphincs_sha256_128f_robust)) { -#ifdef OQS_ENABLE_SIG_sphincs_sha256_128f_robust - return 1; -#else - return 0; #endif } else if (0 == strcasecmp(method_name, OQS_SIG_alg_sphincs_sha256_128f_simple)) { #ifdef OQS_ENABLE_SIG_sphincs_sha256_128f_simple return 1; #else return 0; -#endif - } else if (0 == strcasecmp(method_name, OQS_SIG_alg_sphincs_sha256_128s_robust)) { -#ifdef OQS_ENABLE_SIG_sphincs_sha256_128s_robust - return 1; -#else - return 0; #endif } else if (0 == strcasecmp(method_name, OQS_SIG_alg_sphincs_sha256_128s_simple)) { #ifdef OQS_ENABLE_SIG_sphincs_sha256_128s_simple return 1; #else return 0; -#endif - } else if (0 == strcasecmp(method_name, OQS_SIG_alg_sphincs_sha256_192f_robust)) { -#ifdef OQS_ENABLE_SIG_sphincs_sha256_192f_robust - return 1; -#else - return 0; #endif } else if (0 == strcasecmp(method_name, OQS_SIG_alg_sphincs_sha256_192f_simple)) { #ifdef OQS_ENABLE_SIG_sphincs_sha256_192f_simple return 1; #else return 0; -#endif - } else if (0 == strcasecmp(method_name, OQS_SIG_alg_sphincs_sha256_192s_robust)) { -#ifdef OQS_ENABLE_SIG_sphincs_sha256_192s_robust - return 1; -#else - return 0; #endif } else if (0 == strcasecmp(method_name, OQS_SIG_alg_sphincs_sha256_192s_simple)) { #ifdef OQS_ENABLE_SIG_sphincs_sha256_192s_simple return 1; #else return 0; -#endif - } else if (0 == strcasecmp(method_name, OQS_SIG_alg_sphincs_sha256_256f_robust)) { -#ifdef OQS_ENABLE_SIG_sphincs_sha256_256f_robust - return 1; -#else - return 0; #endif } else if (0 == strcasecmp(method_name, OQS_SIG_alg_sphincs_sha256_256f_simple)) { #ifdef OQS_ENABLE_SIG_sphincs_sha256_256f_simple return 1; #else return 0; -#endif - } else if (0 == strcasecmp(method_name, OQS_SIG_alg_sphincs_sha256_256s_robust)) { -#ifdef OQS_ENABLE_SIG_sphincs_sha256_256s_robust - return 1; -#else - return 0; #endif } else if (0 == strcasecmp(method_name, OQS_SIG_alg_sphincs_sha256_256s_simple)) { #ifdef OQS_ENABLE_SIG_sphincs_sha256_256s_simple return 1; #else return 0; -#endif - } else if (0 == strcasecmp(method_name, OQS_SIG_alg_sphincs_shake256_128f_robust)) { -#ifdef OQS_ENABLE_SIG_sphincs_shake256_128f_robust - return 1; -#else - return 0; #endif } else if (0 == strcasecmp(method_name, OQS_SIG_alg_sphincs_shake256_128f_simple)) { #ifdef OQS_ENABLE_SIG_sphincs_shake256_128f_simple return 1; #else return 0; -#endif - } else if (0 == strcasecmp(method_name, OQS_SIG_alg_sphincs_shake256_128s_robust)) { -#ifdef OQS_ENABLE_SIG_sphincs_shake256_128s_robust - return 1; -#else - return 0; #endif } else if (0 == strcasecmp(method_name, OQS_SIG_alg_sphincs_shake256_128s_simple)) { #ifdef OQS_ENABLE_SIG_sphincs_shake256_128s_simple return 1; #else return 0; -#endif - } else if (0 == strcasecmp(method_name, OQS_SIG_alg_sphincs_shake256_192f_robust)) { -#ifdef OQS_ENABLE_SIG_sphincs_shake256_192f_robust - return 1; -#else - return 0; #endif } else if (0 == strcasecmp(method_name, OQS_SIG_alg_sphincs_shake256_192f_simple)) { #ifdef OQS_ENABLE_SIG_sphincs_shake256_192f_simple return 1; #else return 0; -#endif - } else if (0 == strcasecmp(method_name, OQS_SIG_alg_sphincs_shake256_192s_robust)) { -#ifdef OQS_ENABLE_SIG_sphincs_shake256_192s_robust - return 1; -#else - return 0; #endif } else if (0 == strcasecmp(method_name, OQS_SIG_alg_sphincs_shake256_192s_simple)) { #ifdef OQS_ENABLE_SIG_sphincs_shake256_192s_simple return 1; #else return 0; -#endif - } else if (0 == strcasecmp(method_name, OQS_SIG_alg_sphincs_shake256_256f_robust)) { -#ifdef OQS_ENABLE_SIG_sphincs_shake256_256f_robust - return 1; -#else - return 0; #endif } else if (0 == strcasecmp(method_name, OQS_SIG_alg_sphincs_shake256_256f_simple)) { #ifdef OQS_ENABLE_SIG_sphincs_shake256_256f_simple return 1; #else return 0; -#endif - } else if (0 == strcasecmp(method_name, OQS_SIG_alg_sphincs_shake256_256s_robust)) { -#ifdef OQS_ENABLE_SIG_sphincs_shake256_256s_robust - return 1; -#else - return 0; #endif } else if (0 == strcasecmp(method_name, OQS_SIG_alg_sphincs_shake256_256s_simple)) { #ifdef OQS_ENABLE_SIG_sphincs_shake256_256s_simple @@ -401,216 +233,72 @@ OQS_API OQS_SIG *OQS_SIG_new(const char *method_name) { return OQS_SIG_falcon_1024_new(); #else return NULL; -#endif - } else if (0 == strcasecmp(method_name, OQS_SIG_alg_sphincs_haraka_128f_robust)) { -#ifdef OQS_ENABLE_SIG_sphincs_haraka_128f_robust - return OQS_SIG_sphincs_haraka_128f_robust_new(); -#else - return NULL; -#endif - } else if (0 == strcasecmp(method_name, OQS_SIG_alg_sphincs_haraka_128f_simple)) { -#ifdef OQS_ENABLE_SIG_sphincs_haraka_128f_simple - return OQS_SIG_sphincs_haraka_128f_simple_new(); -#else - return NULL; -#endif - } else if (0 == strcasecmp(method_name, OQS_SIG_alg_sphincs_haraka_128s_robust)) { -#ifdef OQS_ENABLE_SIG_sphincs_haraka_128s_robust - return OQS_SIG_sphincs_haraka_128s_robust_new(); -#else - return NULL; -#endif - } else if (0 == strcasecmp(method_name, OQS_SIG_alg_sphincs_haraka_128s_simple)) { -#ifdef OQS_ENABLE_SIG_sphincs_haraka_128s_simple - return OQS_SIG_sphincs_haraka_128s_simple_new(); -#else - return NULL; -#endif - } else if (0 == strcasecmp(method_name, OQS_SIG_alg_sphincs_haraka_192f_robust)) { -#ifdef OQS_ENABLE_SIG_sphincs_haraka_192f_robust - return OQS_SIG_sphincs_haraka_192f_robust_new(); -#else - return NULL; -#endif - } else if (0 == strcasecmp(method_name, OQS_SIG_alg_sphincs_haraka_192f_simple)) { -#ifdef OQS_ENABLE_SIG_sphincs_haraka_192f_simple - return OQS_SIG_sphincs_haraka_192f_simple_new(); -#else - return NULL; -#endif - } else if (0 == strcasecmp(method_name, OQS_SIG_alg_sphincs_haraka_192s_robust)) { -#ifdef OQS_ENABLE_SIG_sphincs_haraka_192s_robust - return OQS_SIG_sphincs_haraka_192s_robust_new(); -#else - return NULL; -#endif - } else if (0 == strcasecmp(method_name, OQS_SIG_alg_sphincs_haraka_192s_simple)) { -#ifdef OQS_ENABLE_SIG_sphincs_haraka_192s_simple - return OQS_SIG_sphincs_haraka_192s_simple_new(); -#else - return NULL; -#endif - } else if (0 == strcasecmp(method_name, OQS_SIG_alg_sphincs_haraka_256f_robust)) { -#ifdef OQS_ENABLE_SIG_sphincs_haraka_256f_robust - return OQS_SIG_sphincs_haraka_256f_robust_new(); -#else - return NULL; -#endif - } else if (0 == strcasecmp(method_name, OQS_SIG_alg_sphincs_haraka_256f_simple)) { -#ifdef OQS_ENABLE_SIG_sphincs_haraka_256f_simple - return OQS_SIG_sphincs_haraka_256f_simple_new(); -#else - return NULL; -#endif - } else if (0 == strcasecmp(method_name, OQS_SIG_alg_sphincs_haraka_256s_robust)) { -#ifdef OQS_ENABLE_SIG_sphincs_haraka_256s_robust - return OQS_SIG_sphincs_haraka_256s_robust_new(); -#else - return NULL; -#endif - } else if (0 == strcasecmp(method_name, OQS_SIG_alg_sphincs_haraka_256s_simple)) { -#ifdef OQS_ENABLE_SIG_sphincs_haraka_256s_simple - return OQS_SIG_sphincs_haraka_256s_simple_new(); -#else - return NULL; -#endif - } else if (0 == strcasecmp(method_name, OQS_SIG_alg_sphincs_sha256_128f_robust)) { -#ifdef OQS_ENABLE_SIG_sphincs_sha256_128f_robust - return OQS_SIG_sphincs_sha256_128f_robust_new(); -#else - return NULL; #endif } else if (0 == strcasecmp(method_name, OQS_SIG_alg_sphincs_sha256_128f_simple)) { #ifdef OQS_ENABLE_SIG_sphincs_sha256_128f_simple return OQS_SIG_sphincs_sha256_128f_simple_new(); #else return NULL; -#endif - } else if (0 == strcasecmp(method_name, OQS_SIG_alg_sphincs_sha256_128s_robust)) { -#ifdef OQS_ENABLE_SIG_sphincs_sha256_128s_robust - return OQS_SIG_sphincs_sha256_128s_robust_new(); -#else - return NULL; #endif } else if (0 == strcasecmp(method_name, OQS_SIG_alg_sphincs_sha256_128s_simple)) { #ifdef OQS_ENABLE_SIG_sphincs_sha256_128s_simple return OQS_SIG_sphincs_sha256_128s_simple_new(); #else return NULL; -#endif - } else if (0 == strcasecmp(method_name, OQS_SIG_alg_sphincs_sha256_192f_robust)) { -#ifdef OQS_ENABLE_SIG_sphincs_sha256_192f_robust - return OQS_SIG_sphincs_sha256_192f_robust_new(); -#else - return NULL; #endif } else if (0 == strcasecmp(method_name, OQS_SIG_alg_sphincs_sha256_192f_simple)) { #ifdef OQS_ENABLE_SIG_sphincs_sha256_192f_simple return OQS_SIG_sphincs_sha256_192f_simple_new(); #else return NULL; -#endif - } else if (0 == strcasecmp(method_name, OQS_SIG_alg_sphincs_sha256_192s_robust)) { -#ifdef OQS_ENABLE_SIG_sphincs_sha256_192s_robust - return OQS_SIG_sphincs_sha256_192s_robust_new(); -#else - return NULL; #endif } else if (0 == strcasecmp(method_name, OQS_SIG_alg_sphincs_sha256_192s_simple)) { #ifdef OQS_ENABLE_SIG_sphincs_sha256_192s_simple return OQS_SIG_sphincs_sha256_192s_simple_new(); #else return NULL; -#endif - } else if (0 == strcasecmp(method_name, OQS_SIG_alg_sphincs_sha256_256f_robust)) { -#ifdef OQS_ENABLE_SIG_sphincs_sha256_256f_robust - return OQS_SIG_sphincs_sha256_256f_robust_new(); -#else - return NULL; #endif } else if (0 == strcasecmp(method_name, OQS_SIG_alg_sphincs_sha256_256f_simple)) { #ifdef OQS_ENABLE_SIG_sphincs_sha256_256f_simple return OQS_SIG_sphincs_sha256_256f_simple_new(); #else return NULL; -#endif - } else if (0 == strcasecmp(method_name, OQS_SIG_alg_sphincs_sha256_256s_robust)) { -#ifdef OQS_ENABLE_SIG_sphincs_sha256_256s_robust - return OQS_SIG_sphincs_sha256_256s_robust_new(); -#else - return NULL; #endif } else if (0 == strcasecmp(method_name, OQS_SIG_alg_sphincs_sha256_256s_simple)) { #ifdef OQS_ENABLE_SIG_sphincs_sha256_256s_simple return OQS_SIG_sphincs_sha256_256s_simple_new(); #else return NULL; -#endif - } else if (0 == strcasecmp(method_name, OQS_SIG_alg_sphincs_shake256_128f_robust)) { -#ifdef OQS_ENABLE_SIG_sphincs_shake256_128f_robust - return OQS_SIG_sphincs_shake256_128f_robust_new(); -#else - return NULL; #endif } else if (0 == strcasecmp(method_name, OQS_SIG_alg_sphincs_shake256_128f_simple)) { #ifdef OQS_ENABLE_SIG_sphincs_shake256_128f_simple return OQS_SIG_sphincs_shake256_128f_simple_new(); #else return NULL; -#endif - } else if (0 == strcasecmp(method_name, OQS_SIG_alg_sphincs_shake256_128s_robust)) { -#ifdef OQS_ENABLE_SIG_sphincs_shake256_128s_robust - return OQS_SIG_sphincs_shake256_128s_robust_new(); -#else - return NULL; #endif } else if (0 == strcasecmp(method_name, OQS_SIG_alg_sphincs_shake256_128s_simple)) { #ifdef OQS_ENABLE_SIG_sphincs_shake256_128s_simple return OQS_SIG_sphincs_shake256_128s_simple_new(); #else return NULL; -#endif - } else if (0 == strcasecmp(method_name, OQS_SIG_alg_sphincs_shake256_192f_robust)) { -#ifdef OQS_ENABLE_SIG_sphincs_shake256_192f_robust - return OQS_SIG_sphincs_shake256_192f_robust_new(); -#else - return NULL; #endif } else if (0 == strcasecmp(method_name, OQS_SIG_alg_sphincs_shake256_192f_simple)) { #ifdef OQS_ENABLE_SIG_sphincs_shake256_192f_simple return OQS_SIG_sphincs_shake256_192f_simple_new(); #else return NULL; -#endif - } else if (0 == strcasecmp(method_name, OQS_SIG_alg_sphincs_shake256_192s_robust)) { -#ifdef OQS_ENABLE_SIG_sphincs_shake256_192s_robust - return OQS_SIG_sphincs_shake256_192s_robust_new(); -#else - return NULL; #endif } else if (0 == strcasecmp(method_name, OQS_SIG_alg_sphincs_shake256_192s_simple)) { #ifdef OQS_ENABLE_SIG_sphincs_shake256_192s_simple return OQS_SIG_sphincs_shake256_192s_simple_new(); #else return NULL; -#endif - } else if (0 == strcasecmp(method_name, OQS_SIG_alg_sphincs_shake256_256f_robust)) { -#ifdef OQS_ENABLE_SIG_sphincs_shake256_256f_robust - return OQS_SIG_sphincs_shake256_256f_robust_new(); -#else - return NULL; #endif } else if (0 == strcasecmp(method_name, OQS_SIG_alg_sphincs_shake256_256f_simple)) { #ifdef OQS_ENABLE_SIG_sphincs_shake256_256f_simple return OQS_SIG_sphincs_shake256_256f_simple_new(); #else return NULL; -#endif - } else if (0 == strcasecmp(method_name, OQS_SIG_alg_sphincs_shake256_256s_robust)) { -#ifdef OQS_ENABLE_SIG_sphincs_shake256_256s_robust - return OQS_SIG_sphincs_shake256_256s_robust_new(); -#else - return NULL; #endif } else if (0 == strcasecmp(method_name, OQS_SIG_alg_sphincs_shake256_256s_simple)) { #ifdef OQS_ENABLE_SIG_sphincs_shake256_256s_simple diff --git a/src/sig/sig.h b/src/sig/sig.h index e9ddb3f94d..5ac82c339f 100644 --- a/src/sig/sig.h +++ b/src/sig/sig.h @@ -48,83 +48,35 @@ extern "C" { #define OQS_SIG_alg_falcon_512 "Falcon-512" /** Algorithm identifier for Falcon-1024 */ #define OQS_SIG_alg_falcon_1024 "Falcon-1024" -/** Algorithm identifier for SPHINCS+-Haraka-128f-robust */ -#define OQS_SIG_alg_sphincs_haraka_128f_robust "SPHINCS+-Haraka-128f-robust" -/** Algorithm identifier for SPHINCS+-Haraka-128f-simple */ -#define OQS_SIG_alg_sphincs_haraka_128f_simple "SPHINCS+-Haraka-128f-simple" -/** Algorithm identifier for SPHINCS+-Haraka-128s-robust */ -#define OQS_SIG_alg_sphincs_haraka_128s_robust "SPHINCS+-Haraka-128s-robust" -/** Algorithm identifier for SPHINCS+-Haraka-128s-simple */ -#define OQS_SIG_alg_sphincs_haraka_128s_simple "SPHINCS+-Haraka-128s-simple" -/** Algorithm identifier for SPHINCS+-Haraka-192f-robust */ -#define OQS_SIG_alg_sphincs_haraka_192f_robust "SPHINCS+-Haraka-192f-robust" -/** Algorithm identifier for SPHINCS+-Haraka-192f-simple */ -#define OQS_SIG_alg_sphincs_haraka_192f_simple "SPHINCS+-Haraka-192f-simple" -/** Algorithm identifier for SPHINCS+-Haraka-192s-robust */ -#define OQS_SIG_alg_sphincs_haraka_192s_robust "SPHINCS+-Haraka-192s-robust" -/** Algorithm identifier for SPHINCS+-Haraka-192s-simple */ -#define OQS_SIG_alg_sphincs_haraka_192s_simple "SPHINCS+-Haraka-192s-simple" -/** Algorithm identifier for SPHINCS+-Haraka-256f-robust */ -#define OQS_SIG_alg_sphincs_haraka_256f_robust "SPHINCS+-Haraka-256f-robust" -/** Algorithm identifier for SPHINCS+-Haraka-256f-simple */ -#define OQS_SIG_alg_sphincs_haraka_256f_simple "SPHINCS+-Haraka-256f-simple" -/** Algorithm identifier for SPHINCS+-Haraka-256s-robust */ -#define OQS_SIG_alg_sphincs_haraka_256s_robust "SPHINCS+-Haraka-256s-robust" -/** Algorithm identifier for SPHINCS+-Haraka-256s-simple */ -#define OQS_SIG_alg_sphincs_haraka_256s_simple "SPHINCS+-Haraka-256s-simple" -/** Algorithm identifier for SPHINCS+-SHA256-128f-robust */ -#define OQS_SIG_alg_sphincs_sha256_128f_robust "SPHINCS+-SHA256-128f-robust" /** Algorithm identifier for SPHINCS+-SHA256-128f-simple */ #define OQS_SIG_alg_sphincs_sha256_128f_simple "SPHINCS+-SHA256-128f-simple" -/** Algorithm identifier for SPHINCS+-SHA256-128s-robust */ -#define OQS_SIG_alg_sphincs_sha256_128s_robust "SPHINCS+-SHA256-128s-robust" /** Algorithm identifier for SPHINCS+-SHA256-128s-simple */ #define OQS_SIG_alg_sphincs_sha256_128s_simple "SPHINCS+-SHA256-128s-simple" -/** Algorithm identifier for SPHINCS+-SHA256-192f-robust */ -#define OQS_SIG_alg_sphincs_sha256_192f_robust "SPHINCS+-SHA256-192f-robust" /** Algorithm identifier for SPHINCS+-SHA256-192f-simple */ #define OQS_SIG_alg_sphincs_sha256_192f_simple "SPHINCS+-SHA256-192f-simple" -/** Algorithm identifier for SPHINCS+-SHA256-192s-robust */ -#define OQS_SIG_alg_sphincs_sha256_192s_robust "SPHINCS+-SHA256-192s-robust" /** Algorithm identifier for SPHINCS+-SHA256-192s-simple */ #define OQS_SIG_alg_sphincs_sha256_192s_simple "SPHINCS+-SHA256-192s-simple" -/** Algorithm identifier for SPHINCS+-SHA256-256f-robust */ -#define OQS_SIG_alg_sphincs_sha256_256f_robust "SPHINCS+-SHA256-256f-robust" /** Algorithm identifier for SPHINCS+-SHA256-256f-simple */ #define OQS_SIG_alg_sphincs_sha256_256f_simple "SPHINCS+-SHA256-256f-simple" -/** Algorithm identifier for SPHINCS+-SHA256-256s-robust */ -#define OQS_SIG_alg_sphincs_sha256_256s_robust "SPHINCS+-SHA256-256s-robust" /** Algorithm identifier for SPHINCS+-SHA256-256s-simple */ #define OQS_SIG_alg_sphincs_sha256_256s_simple "SPHINCS+-SHA256-256s-simple" -/** Algorithm identifier for SPHINCS+-SHAKE256-128f-robust */ -#define OQS_SIG_alg_sphincs_shake256_128f_robust "SPHINCS+-SHAKE256-128f-robust" /** Algorithm identifier for SPHINCS+-SHAKE256-128f-simple */ #define OQS_SIG_alg_sphincs_shake256_128f_simple "SPHINCS+-SHAKE256-128f-simple" -/** Algorithm identifier for SPHINCS+-SHAKE256-128s-robust */ -#define OQS_SIG_alg_sphincs_shake256_128s_robust "SPHINCS+-SHAKE256-128s-robust" /** Algorithm identifier for SPHINCS+-SHAKE256-128s-simple */ #define OQS_SIG_alg_sphincs_shake256_128s_simple "SPHINCS+-SHAKE256-128s-simple" -/** Algorithm identifier for SPHINCS+-SHAKE256-192f-robust */ -#define OQS_SIG_alg_sphincs_shake256_192f_robust "SPHINCS+-SHAKE256-192f-robust" /** Algorithm identifier for SPHINCS+-SHAKE256-192f-simple */ #define OQS_SIG_alg_sphincs_shake256_192f_simple "SPHINCS+-SHAKE256-192f-simple" -/** Algorithm identifier for SPHINCS+-SHAKE256-192s-robust */ -#define OQS_SIG_alg_sphincs_shake256_192s_robust "SPHINCS+-SHAKE256-192s-robust" /** Algorithm identifier for SPHINCS+-SHAKE256-192s-simple */ #define OQS_SIG_alg_sphincs_shake256_192s_simple "SPHINCS+-SHAKE256-192s-simple" -/** Algorithm identifier for SPHINCS+-SHAKE256-256f-robust */ -#define OQS_SIG_alg_sphincs_shake256_256f_robust "SPHINCS+-SHAKE256-256f-robust" /** Algorithm identifier for SPHINCS+-SHAKE256-256f-simple */ #define OQS_SIG_alg_sphincs_shake256_256f_simple "SPHINCS+-SHAKE256-256f-simple" -/** Algorithm identifier for SPHINCS+-SHAKE256-256s-robust */ -#define OQS_SIG_alg_sphincs_shake256_256s_robust "SPHINCS+-SHAKE256-256s-robust" /** Algorithm identifier for SPHINCS+-SHAKE256-256s-simple */ #define OQS_SIG_alg_sphincs_shake256_256s_simple "SPHINCS+-SHAKE256-256s-simple" ///// OQS_COPY_FROM_UPSTREAM_FRAGMENT_ALG_IDENTIFIER_END // EDIT-WHEN-ADDING-SIG ///// OQS_COPY_FROM_UPSTREAM_FRAGMENT_ALGS_LENGTH_START /** Number of algorithm identifiers above. */ -#define OQS_SIG_algs_length 44 +#define OQS_SIG_algs_length 20 ///// OQS_COPY_FROM_UPSTREAM_FRAGMENT_ALGS_LENGTH_END /** diff --git a/src/sig/sphincs/CMakeLists.txt b/src/sig/sphincs/CMakeLists.txt index 2c5026566d..74925f503e 100644 --- a/src/sig/sphincs/CMakeLists.txt +++ b/src/sig/sphincs/CMakeLists.txt @@ -5,201 +5,6 @@ set(_SPHINCS_OBJS "") -if(OQS_ENABLE_SIG_sphincs_haraka_128f_robust) - add_library(sphincs_haraka_128f_robust_clean OBJECT sig_sphincs_haraka_128f_robust.c pqclean_sphincs-haraka-128f-robust_clean/address.c pqclean_sphincs-haraka-128f-robust_clean/context_haraka.c pqclean_sphincs-haraka-128f-robust_clean/fors.c pqclean_sphincs-haraka-128f-robust_clean/haraka.c pqclean_sphincs-haraka-128f-robust_clean/hash_haraka.c pqclean_sphincs-haraka-128f-robust_clean/merkle.c pqclean_sphincs-haraka-128f-robust_clean/sign.c pqclean_sphincs-haraka-128f-robust_clean/thash_haraka_robust.c pqclean_sphincs-haraka-128f-robust_clean/utils.c pqclean_sphincs-haraka-128f-robust_clean/utilsx1.c pqclean_sphincs-haraka-128f-robust_clean/wots.c pqclean_sphincs-haraka-128f-robust_clean/wotsx1.c) - target_include_directories(sphincs_haraka_128f_robust_clean PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-haraka-128f-robust_clean) - target_include_directories(sphincs_haraka_128f_robust_clean PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) - set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) -endif() - -if(OQS_ENABLE_SIG_sphincs_haraka_128f_robust_aesni) - add_library(sphincs_haraka_128f_robust_aesni OBJECT pqclean_sphincs-haraka-128f-robust_aesni/address.c pqclean_sphincs-haraka-128f-robust_aesni/context_haraka.c pqclean_sphincs-haraka-128f-robust_aesni/fors.c pqclean_sphincs-haraka-128f-robust_aesni/haraka.c pqclean_sphincs-haraka-128f-robust_aesni/hash_haraka.c pqclean_sphincs-haraka-128f-robust_aesni/hash_harakax4.c pqclean_sphincs-haraka-128f-robust_aesni/merkle.c pqclean_sphincs-haraka-128f-robust_aesni/sign.c pqclean_sphincs-haraka-128f-robust_aesni/thash_haraka_robust.c pqclean_sphincs-haraka-128f-robust_aesni/thash_haraka_robustx4.c pqclean_sphincs-haraka-128f-robust_aesni/utils.c pqclean_sphincs-haraka-128f-robust_aesni/utilsx4.c pqclean_sphincs-haraka-128f-robust_aesni/wots.c) - target_include_directories(sphincs_haraka_128f_robust_aesni PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-haraka-128f-robust_aesni) - target_include_directories(sphincs_haraka_128f_robust_aesni PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) - target_compile_options(sphincs_haraka_128f_robust_aesni PRIVATE -maes) - set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) -endif() - -if(OQS_ENABLE_SIG_sphincs_haraka_128f_simple) - add_library(sphincs_haraka_128f_simple_clean OBJECT sig_sphincs_haraka_128f_simple.c pqclean_sphincs-haraka-128f-simple_clean/address.c pqclean_sphincs-haraka-128f-simple_clean/context_haraka.c pqclean_sphincs-haraka-128f-simple_clean/fors.c pqclean_sphincs-haraka-128f-simple_clean/haraka.c pqclean_sphincs-haraka-128f-simple_clean/hash_haraka.c pqclean_sphincs-haraka-128f-simple_clean/merkle.c pqclean_sphincs-haraka-128f-simple_clean/sign.c pqclean_sphincs-haraka-128f-simple_clean/thash_haraka_simple.c pqclean_sphincs-haraka-128f-simple_clean/utils.c pqclean_sphincs-haraka-128f-simple_clean/utilsx1.c pqclean_sphincs-haraka-128f-simple_clean/wots.c pqclean_sphincs-haraka-128f-simple_clean/wotsx1.c) - target_include_directories(sphincs_haraka_128f_simple_clean PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-haraka-128f-simple_clean) - target_include_directories(sphincs_haraka_128f_simple_clean PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) - set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) -endif() - -if(OQS_ENABLE_SIG_sphincs_haraka_128f_simple_aesni) - add_library(sphincs_haraka_128f_simple_aesni OBJECT pqclean_sphincs-haraka-128f-simple_aesni/address.c pqclean_sphincs-haraka-128f-simple_aesni/context_haraka.c pqclean_sphincs-haraka-128f-simple_aesni/fors.c pqclean_sphincs-haraka-128f-simple_aesni/haraka.c pqclean_sphincs-haraka-128f-simple_aesni/hash_haraka.c pqclean_sphincs-haraka-128f-simple_aesni/hash_harakax4.c pqclean_sphincs-haraka-128f-simple_aesni/merkle.c pqclean_sphincs-haraka-128f-simple_aesni/sign.c pqclean_sphincs-haraka-128f-simple_aesni/thash_haraka_simple.c pqclean_sphincs-haraka-128f-simple_aesni/thash_haraka_simplex4.c pqclean_sphincs-haraka-128f-simple_aesni/utils.c pqclean_sphincs-haraka-128f-simple_aesni/utilsx4.c pqclean_sphincs-haraka-128f-simple_aesni/wots.c) - target_include_directories(sphincs_haraka_128f_simple_aesni PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-haraka-128f-simple_aesni) - target_include_directories(sphincs_haraka_128f_simple_aesni PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) - target_compile_options(sphincs_haraka_128f_simple_aesni PRIVATE -maes) - set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) -endif() - -if(OQS_ENABLE_SIG_sphincs_haraka_128s_robust) - add_library(sphincs_haraka_128s_robust_clean OBJECT sig_sphincs_haraka_128s_robust.c pqclean_sphincs-haraka-128s-robust_clean/address.c pqclean_sphincs-haraka-128s-robust_clean/context_haraka.c pqclean_sphincs-haraka-128s-robust_clean/fors.c pqclean_sphincs-haraka-128s-robust_clean/haraka.c pqclean_sphincs-haraka-128s-robust_clean/hash_haraka.c pqclean_sphincs-haraka-128s-robust_clean/merkle.c pqclean_sphincs-haraka-128s-robust_clean/sign.c pqclean_sphincs-haraka-128s-robust_clean/thash_haraka_robust.c pqclean_sphincs-haraka-128s-robust_clean/utils.c pqclean_sphincs-haraka-128s-robust_clean/utilsx1.c pqclean_sphincs-haraka-128s-robust_clean/wots.c pqclean_sphincs-haraka-128s-robust_clean/wotsx1.c) - target_include_directories(sphincs_haraka_128s_robust_clean PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-haraka-128s-robust_clean) - target_include_directories(sphincs_haraka_128s_robust_clean PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) - set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) -endif() - -if(OQS_ENABLE_SIG_sphincs_haraka_128s_robust_aesni) - add_library(sphincs_haraka_128s_robust_aesni OBJECT pqclean_sphincs-haraka-128s-robust_aesni/address.c pqclean_sphincs-haraka-128s-robust_aesni/context_haraka.c pqclean_sphincs-haraka-128s-robust_aesni/fors.c pqclean_sphincs-haraka-128s-robust_aesni/haraka.c pqclean_sphincs-haraka-128s-robust_aesni/hash_haraka.c pqclean_sphincs-haraka-128s-robust_aesni/hash_harakax4.c pqclean_sphincs-haraka-128s-robust_aesni/merkle.c pqclean_sphincs-haraka-128s-robust_aesni/sign.c pqclean_sphincs-haraka-128s-robust_aesni/thash_haraka_robust.c pqclean_sphincs-haraka-128s-robust_aesni/thash_haraka_robustx4.c pqclean_sphincs-haraka-128s-robust_aesni/utils.c pqclean_sphincs-haraka-128s-robust_aesni/utilsx4.c pqclean_sphincs-haraka-128s-robust_aesni/wots.c) - target_include_directories(sphincs_haraka_128s_robust_aesni PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-haraka-128s-robust_aesni) - target_include_directories(sphincs_haraka_128s_robust_aesni PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) - target_compile_options(sphincs_haraka_128s_robust_aesni PRIVATE -maes) - set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) -endif() - -if(OQS_ENABLE_SIG_sphincs_haraka_128s_simple) - add_library(sphincs_haraka_128s_simple_clean OBJECT sig_sphincs_haraka_128s_simple.c pqclean_sphincs-haraka-128s-simple_clean/address.c pqclean_sphincs-haraka-128s-simple_clean/context_haraka.c pqclean_sphincs-haraka-128s-simple_clean/fors.c pqclean_sphincs-haraka-128s-simple_clean/haraka.c pqclean_sphincs-haraka-128s-simple_clean/hash_haraka.c pqclean_sphincs-haraka-128s-simple_clean/merkle.c pqclean_sphincs-haraka-128s-simple_clean/sign.c pqclean_sphincs-haraka-128s-simple_clean/thash_haraka_simple.c pqclean_sphincs-haraka-128s-simple_clean/utils.c pqclean_sphincs-haraka-128s-simple_clean/utilsx1.c pqclean_sphincs-haraka-128s-simple_clean/wots.c pqclean_sphincs-haraka-128s-simple_clean/wotsx1.c) - target_include_directories(sphincs_haraka_128s_simple_clean PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-haraka-128s-simple_clean) - target_include_directories(sphincs_haraka_128s_simple_clean PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) - set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) -endif() - -if(OQS_ENABLE_SIG_sphincs_haraka_128s_simple_aesni) - add_library(sphincs_haraka_128s_simple_aesni OBJECT pqclean_sphincs-haraka-128s-simple_aesni/address.c pqclean_sphincs-haraka-128s-simple_aesni/context_haraka.c pqclean_sphincs-haraka-128s-simple_aesni/fors.c pqclean_sphincs-haraka-128s-simple_aesni/haraka.c pqclean_sphincs-haraka-128s-simple_aesni/hash_haraka.c pqclean_sphincs-haraka-128s-simple_aesni/hash_harakax4.c pqclean_sphincs-haraka-128s-simple_aesni/merkle.c pqclean_sphincs-haraka-128s-simple_aesni/sign.c pqclean_sphincs-haraka-128s-simple_aesni/thash_haraka_simple.c pqclean_sphincs-haraka-128s-simple_aesni/thash_haraka_simplex4.c pqclean_sphincs-haraka-128s-simple_aesni/utils.c pqclean_sphincs-haraka-128s-simple_aesni/utilsx4.c pqclean_sphincs-haraka-128s-simple_aesni/wots.c) - target_include_directories(sphincs_haraka_128s_simple_aesni PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-haraka-128s-simple_aesni) - target_include_directories(sphincs_haraka_128s_simple_aesni PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) - target_compile_options(sphincs_haraka_128s_simple_aesni PRIVATE -maes) - set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) -endif() - -if(OQS_ENABLE_SIG_sphincs_haraka_192f_robust) - add_library(sphincs_haraka_192f_robust_clean OBJECT sig_sphincs_haraka_192f_robust.c pqclean_sphincs-haraka-192f-robust_clean/address.c pqclean_sphincs-haraka-192f-robust_clean/context_haraka.c pqclean_sphincs-haraka-192f-robust_clean/fors.c pqclean_sphincs-haraka-192f-robust_clean/haraka.c pqclean_sphincs-haraka-192f-robust_clean/hash_haraka.c pqclean_sphincs-haraka-192f-robust_clean/merkle.c pqclean_sphincs-haraka-192f-robust_clean/sign.c pqclean_sphincs-haraka-192f-robust_clean/thash_haraka_robust.c pqclean_sphincs-haraka-192f-robust_clean/utils.c pqclean_sphincs-haraka-192f-robust_clean/utilsx1.c pqclean_sphincs-haraka-192f-robust_clean/wots.c pqclean_sphincs-haraka-192f-robust_clean/wotsx1.c) - target_include_directories(sphincs_haraka_192f_robust_clean PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-haraka-192f-robust_clean) - target_include_directories(sphincs_haraka_192f_robust_clean PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) - set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) -endif() - -if(OQS_ENABLE_SIG_sphincs_haraka_192f_robust_aesni) - add_library(sphincs_haraka_192f_robust_aesni OBJECT pqclean_sphincs-haraka-192f-robust_aesni/address.c pqclean_sphincs-haraka-192f-robust_aesni/context_haraka.c pqclean_sphincs-haraka-192f-robust_aesni/fors.c pqclean_sphincs-haraka-192f-robust_aesni/haraka.c pqclean_sphincs-haraka-192f-robust_aesni/hash_haraka.c pqclean_sphincs-haraka-192f-robust_aesni/hash_harakax4.c pqclean_sphincs-haraka-192f-robust_aesni/merkle.c pqclean_sphincs-haraka-192f-robust_aesni/sign.c pqclean_sphincs-haraka-192f-robust_aesni/thash_haraka_robust.c pqclean_sphincs-haraka-192f-robust_aesni/thash_haraka_robustx4.c pqclean_sphincs-haraka-192f-robust_aesni/utils.c pqclean_sphincs-haraka-192f-robust_aesni/utilsx4.c pqclean_sphincs-haraka-192f-robust_aesni/wots.c) - target_include_directories(sphincs_haraka_192f_robust_aesni PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-haraka-192f-robust_aesni) - target_include_directories(sphincs_haraka_192f_robust_aesni PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) - target_compile_options(sphincs_haraka_192f_robust_aesni PRIVATE -maes) - set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) -endif() - -if(OQS_ENABLE_SIG_sphincs_haraka_192f_simple) - add_library(sphincs_haraka_192f_simple_clean OBJECT sig_sphincs_haraka_192f_simple.c pqclean_sphincs-haraka-192f-simple_clean/address.c pqclean_sphincs-haraka-192f-simple_clean/context_haraka.c pqclean_sphincs-haraka-192f-simple_clean/fors.c pqclean_sphincs-haraka-192f-simple_clean/haraka.c pqclean_sphincs-haraka-192f-simple_clean/hash_haraka.c pqclean_sphincs-haraka-192f-simple_clean/merkle.c pqclean_sphincs-haraka-192f-simple_clean/sign.c pqclean_sphincs-haraka-192f-simple_clean/thash_haraka_simple.c pqclean_sphincs-haraka-192f-simple_clean/utils.c pqclean_sphincs-haraka-192f-simple_clean/utilsx1.c pqclean_sphincs-haraka-192f-simple_clean/wots.c pqclean_sphincs-haraka-192f-simple_clean/wotsx1.c) - target_include_directories(sphincs_haraka_192f_simple_clean PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-haraka-192f-simple_clean) - target_include_directories(sphincs_haraka_192f_simple_clean PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) - set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) -endif() - -if(OQS_ENABLE_SIG_sphincs_haraka_192f_simple_aesni) - add_library(sphincs_haraka_192f_simple_aesni OBJECT pqclean_sphincs-haraka-192f-simple_aesni/address.c pqclean_sphincs-haraka-192f-simple_aesni/context_haraka.c pqclean_sphincs-haraka-192f-simple_aesni/fors.c pqclean_sphincs-haraka-192f-simple_aesni/haraka.c pqclean_sphincs-haraka-192f-simple_aesni/hash_haraka.c pqclean_sphincs-haraka-192f-simple_aesni/hash_harakax4.c pqclean_sphincs-haraka-192f-simple_aesni/merkle.c pqclean_sphincs-haraka-192f-simple_aesni/sign.c pqclean_sphincs-haraka-192f-simple_aesni/thash_haraka_simple.c pqclean_sphincs-haraka-192f-simple_aesni/thash_haraka_simplex4.c pqclean_sphincs-haraka-192f-simple_aesni/utils.c pqclean_sphincs-haraka-192f-simple_aesni/utilsx4.c pqclean_sphincs-haraka-192f-simple_aesni/wots.c) - target_include_directories(sphincs_haraka_192f_simple_aesni PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-haraka-192f-simple_aesni) - target_include_directories(sphincs_haraka_192f_simple_aesni PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) - target_compile_options(sphincs_haraka_192f_simple_aesni PRIVATE -maes) - set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) -endif() - -if(OQS_ENABLE_SIG_sphincs_haraka_192s_robust) - add_library(sphincs_haraka_192s_robust_clean OBJECT sig_sphincs_haraka_192s_robust.c pqclean_sphincs-haraka-192s-robust_clean/address.c pqclean_sphincs-haraka-192s-robust_clean/context_haraka.c pqclean_sphincs-haraka-192s-robust_clean/fors.c pqclean_sphincs-haraka-192s-robust_clean/haraka.c pqclean_sphincs-haraka-192s-robust_clean/hash_haraka.c pqclean_sphincs-haraka-192s-robust_clean/merkle.c pqclean_sphincs-haraka-192s-robust_clean/sign.c pqclean_sphincs-haraka-192s-robust_clean/thash_haraka_robust.c pqclean_sphincs-haraka-192s-robust_clean/utils.c pqclean_sphincs-haraka-192s-robust_clean/utilsx1.c pqclean_sphincs-haraka-192s-robust_clean/wots.c pqclean_sphincs-haraka-192s-robust_clean/wotsx1.c) - target_include_directories(sphincs_haraka_192s_robust_clean PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-haraka-192s-robust_clean) - target_include_directories(sphincs_haraka_192s_robust_clean PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) - set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) -endif() - -if(OQS_ENABLE_SIG_sphincs_haraka_192s_robust_aesni) - add_library(sphincs_haraka_192s_robust_aesni OBJECT pqclean_sphincs-haraka-192s-robust_aesni/address.c pqclean_sphincs-haraka-192s-robust_aesni/context_haraka.c pqclean_sphincs-haraka-192s-robust_aesni/fors.c pqclean_sphincs-haraka-192s-robust_aesni/haraka.c pqclean_sphincs-haraka-192s-robust_aesni/hash_haraka.c pqclean_sphincs-haraka-192s-robust_aesni/hash_harakax4.c pqclean_sphincs-haraka-192s-robust_aesni/merkle.c pqclean_sphincs-haraka-192s-robust_aesni/sign.c pqclean_sphincs-haraka-192s-robust_aesni/thash_haraka_robust.c pqclean_sphincs-haraka-192s-robust_aesni/thash_haraka_robustx4.c pqclean_sphincs-haraka-192s-robust_aesni/utils.c pqclean_sphincs-haraka-192s-robust_aesni/utilsx4.c pqclean_sphincs-haraka-192s-robust_aesni/wots.c) - target_include_directories(sphincs_haraka_192s_robust_aesni PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-haraka-192s-robust_aesni) - target_include_directories(sphincs_haraka_192s_robust_aesni PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) - target_compile_options(sphincs_haraka_192s_robust_aesni PRIVATE -maes) - set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) -endif() - -if(OQS_ENABLE_SIG_sphincs_haraka_192s_simple) - add_library(sphincs_haraka_192s_simple_clean OBJECT sig_sphincs_haraka_192s_simple.c pqclean_sphincs-haraka-192s-simple_clean/address.c pqclean_sphincs-haraka-192s-simple_clean/context_haraka.c pqclean_sphincs-haraka-192s-simple_clean/fors.c pqclean_sphincs-haraka-192s-simple_clean/haraka.c pqclean_sphincs-haraka-192s-simple_clean/hash_haraka.c pqclean_sphincs-haraka-192s-simple_clean/merkle.c pqclean_sphincs-haraka-192s-simple_clean/sign.c pqclean_sphincs-haraka-192s-simple_clean/thash_haraka_simple.c pqclean_sphincs-haraka-192s-simple_clean/utils.c pqclean_sphincs-haraka-192s-simple_clean/utilsx1.c pqclean_sphincs-haraka-192s-simple_clean/wots.c pqclean_sphincs-haraka-192s-simple_clean/wotsx1.c) - target_include_directories(sphincs_haraka_192s_simple_clean PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-haraka-192s-simple_clean) - target_include_directories(sphincs_haraka_192s_simple_clean PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) - set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) -endif() - -if(OQS_ENABLE_SIG_sphincs_haraka_192s_simple_aesni) - add_library(sphincs_haraka_192s_simple_aesni OBJECT pqclean_sphincs-haraka-192s-simple_aesni/address.c pqclean_sphincs-haraka-192s-simple_aesni/context_haraka.c pqclean_sphincs-haraka-192s-simple_aesni/fors.c pqclean_sphincs-haraka-192s-simple_aesni/haraka.c pqclean_sphincs-haraka-192s-simple_aesni/hash_haraka.c pqclean_sphincs-haraka-192s-simple_aesni/hash_harakax4.c pqclean_sphincs-haraka-192s-simple_aesni/merkle.c pqclean_sphincs-haraka-192s-simple_aesni/sign.c pqclean_sphincs-haraka-192s-simple_aesni/thash_haraka_simple.c pqclean_sphincs-haraka-192s-simple_aesni/thash_haraka_simplex4.c pqclean_sphincs-haraka-192s-simple_aesni/utils.c pqclean_sphincs-haraka-192s-simple_aesni/utilsx4.c pqclean_sphincs-haraka-192s-simple_aesni/wots.c) - target_include_directories(sphincs_haraka_192s_simple_aesni PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-haraka-192s-simple_aesni) - target_include_directories(sphincs_haraka_192s_simple_aesni PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) - target_compile_options(sphincs_haraka_192s_simple_aesni PRIVATE -maes) - set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) -endif() - -if(OQS_ENABLE_SIG_sphincs_haraka_256f_robust) - add_library(sphincs_haraka_256f_robust_clean OBJECT sig_sphincs_haraka_256f_robust.c pqclean_sphincs-haraka-256f-robust_clean/address.c pqclean_sphincs-haraka-256f-robust_clean/context_haraka.c pqclean_sphincs-haraka-256f-robust_clean/fors.c pqclean_sphincs-haraka-256f-robust_clean/haraka.c pqclean_sphincs-haraka-256f-robust_clean/hash_haraka.c pqclean_sphincs-haraka-256f-robust_clean/merkle.c pqclean_sphincs-haraka-256f-robust_clean/sign.c pqclean_sphincs-haraka-256f-robust_clean/thash_haraka_robust.c pqclean_sphincs-haraka-256f-robust_clean/utils.c pqclean_sphincs-haraka-256f-robust_clean/utilsx1.c pqclean_sphincs-haraka-256f-robust_clean/wots.c pqclean_sphincs-haraka-256f-robust_clean/wotsx1.c) - target_include_directories(sphincs_haraka_256f_robust_clean PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-haraka-256f-robust_clean) - target_include_directories(sphincs_haraka_256f_robust_clean PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) - set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) -endif() - -if(OQS_ENABLE_SIG_sphincs_haraka_256f_robust_aesni) - add_library(sphincs_haraka_256f_robust_aesni OBJECT pqclean_sphincs-haraka-256f-robust_aesni/address.c pqclean_sphincs-haraka-256f-robust_aesni/context_haraka.c pqclean_sphincs-haraka-256f-robust_aesni/fors.c pqclean_sphincs-haraka-256f-robust_aesni/haraka.c pqclean_sphincs-haraka-256f-robust_aesni/hash_haraka.c pqclean_sphincs-haraka-256f-robust_aesni/hash_harakax4.c pqclean_sphincs-haraka-256f-robust_aesni/merkle.c pqclean_sphincs-haraka-256f-robust_aesni/sign.c pqclean_sphincs-haraka-256f-robust_aesni/thash_haraka_robust.c pqclean_sphincs-haraka-256f-robust_aesni/thash_haraka_robustx4.c pqclean_sphincs-haraka-256f-robust_aesni/utils.c pqclean_sphincs-haraka-256f-robust_aesni/utilsx4.c pqclean_sphincs-haraka-256f-robust_aesni/wots.c) - target_include_directories(sphincs_haraka_256f_robust_aesni PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-haraka-256f-robust_aesni) - target_include_directories(sphincs_haraka_256f_robust_aesni PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) - target_compile_options(sphincs_haraka_256f_robust_aesni PRIVATE -maes) - set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) -endif() - -if(OQS_ENABLE_SIG_sphincs_haraka_256f_simple) - add_library(sphincs_haraka_256f_simple_clean OBJECT sig_sphincs_haraka_256f_simple.c pqclean_sphincs-haraka-256f-simple_clean/address.c pqclean_sphincs-haraka-256f-simple_clean/context_haraka.c pqclean_sphincs-haraka-256f-simple_clean/fors.c pqclean_sphincs-haraka-256f-simple_clean/haraka.c pqclean_sphincs-haraka-256f-simple_clean/hash_haraka.c pqclean_sphincs-haraka-256f-simple_clean/merkle.c pqclean_sphincs-haraka-256f-simple_clean/sign.c pqclean_sphincs-haraka-256f-simple_clean/thash_haraka_simple.c pqclean_sphincs-haraka-256f-simple_clean/utils.c pqclean_sphincs-haraka-256f-simple_clean/utilsx1.c pqclean_sphincs-haraka-256f-simple_clean/wots.c pqclean_sphincs-haraka-256f-simple_clean/wotsx1.c) - target_include_directories(sphincs_haraka_256f_simple_clean PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-haraka-256f-simple_clean) - target_include_directories(sphincs_haraka_256f_simple_clean PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) - set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) -endif() - -if(OQS_ENABLE_SIG_sphincs_haraka_256f_simple_aesni) - add_library(sphincs_haraka_256f_simple_aesni OBJECT pqclean_sphincs-haraka-256f-simple_aesni/address.c pqclean_sphincs-haraka-256f-simple_aesni/context_haraka.c pqclean_sphincs-haraka-256f-simple_aesni/fors.c pqclean_sphincs-haraka-256f-simple_aesni/haraka.c pqclean_sphincs-haraka-256f-simple_aesni/hash_haraka.c pqclean_sphincs-haraka-256f-simple_aesni/hash_harakax4.c pqclean_sphincs-haraka-256f-simple_aesni/merkle.c pqclean_sphincs-haraka-256f-simple_aesni/sign.c pqclean_sphincs-haraka-256f-simple_aesni/thash_haraka_simple.c pqclean_sphincs-haraka-256f-simple_aesni/thash_haraka_simplex4.c pqclean_sphincs-haraka-256f-simple_aesni/utils.c pqclean_sphincs-haraka-256f-simple_aesni/utilsx4.c pqclean_sphincs-haraka-256f-simple_aesni/wots.c) - target_include_directories(sphincs_haraka_256f_simple_aesni PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-haraka-256f-simple_aesni) - target_include_directories(sphincs_haraka_256f_simple_aesni PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) - target_compile_options(sphincs_haraka_256f_simple_aesni PRIVATE -maes) - set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) -endif() - -if(OQS_ENABLE_SIG_sphincs_haraka_256s_robust) - add_library(sphincs_haraka_256s_robust_clean OBJECT sig_sphincs_haraka_256s_robust.c pqclean_sphincs-haraka-256s-robust_clean/address.c pqclean_sphincs-haraka-256s-robust_clean/context_haraka.c pqclean_sphincs-haraka-256s-robust_clean/fors.c pqclean_sphincs-haraka-256s-robust_clean/haraka.c pqclean_sphincs-haraka-256s-robust_clean/hash_haraka.c pqclean_sphincs-haraka-256s-robust_clean/merkle.c pqclean_sphincs-haraka-256s-robust_clean/sign.c pqclean_sphincs-haraka-256s-robust_clean/thash_haraka_robust.c pqclean_sphincs-haraka-256s-robust_clean/utils.c pqclean_sphincs-haraka-256s-robust_clean/utilsx1.c pqclean_sphincs-haraka-256s-robust_clean/wots.c pqclean_sphincs-haraka-256s-robust_clean/wotsx1.c) - target_include_directories(sphincs_haraka_256s_robust_clean PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-haraka-256s-robust_clean) - target_include_directories(sphincs_haraka_256s_robust_clean PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) - set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) -endif() - -if(OQS_ENABLE_SIG_sphincs_haraka_256s_robust_aesni) - add_library(sphincs_haraka_256s_robust_aesni OBJECT pqclean_sphincs-haraka-256s-robust_aesni/address.c pqclean_sphincs-haraka-256s-robust_aesni/context_haraka.c pqclean_sphincs-haraka-256s-robust_aesni/fors.c pqclean_sphincs-haraka-256s-robust_aesni/haraka.c pqclean_sphincs-haraka-256s-robust_aesni/hash_haraka.c pqclean_sphincs-haraka-256s-robust_aesni/hash_harakax4.c pqclean_sphincs-haraka-256s-robust_aesni/merkle.c pqclean_sphincs-haraka-256s-robust_aesni/sign.c pqclean_sphincs-haraka-256s-robust_aesni/thash_haraka_robust.c pqclean_sphincs-haraka-256s-robust_aesni/thash_haraka_robustx4.c pqclean_sphincs-haraka-256s-robust_aesni/utils.c pqclean_sphincs-haraka-256s-robust_aesni/utilsx4.c pqclean_sphincs-haraka-256s-robust_aesni/wots.c) - target_include_directories(sphincs_haraka_256s_robust_aesni PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-haraka-256s-robust_aesni) - target_include_directories(sphincs_haraka_256s_robust_aesni PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) - target_compile_options(sphincs_haraka_256s_robust_aesni PRIVATE -maes) - set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) -endif() - -if(OQS_ENABLE_SIG_sphincs_haraka_256s_simple) - add_library(sphincs_haraka_256s_simple_clean OBJECT sig_sphincs_haraka_256s_simple.c pqclean_sphincs-haraka-256s-simple_clean/address.c pqclean_sphincs-haraka-256s-simple_clean/context_haraka.c pqclean_sphincs-haraka-256s-simple_clean/fors.c pqclean_sphincs-haraka-256s-simple_clean/haraka.c pqclean_sphincs-haraka-256s-simple_clean/hash_haraka.c pqclean_sphincs-haraka-256s-simple_clean/merkle.c pqclean_sphincs-haraka-256s-simple_clean/sign.c pqclean_sphincs-haraka-256s-simple_clean/thash_haraka_simple.c pqclean_sphincs-haraka-256s-simple_clean/utils.c pqclean_sphincs-haraka-256s-simple_clean/utilsx1.c pqclean_sphincs-haraka-256s-simple_clean/wots.c pqclean_sphincs-haraka-256s-simple_clean/wotsx1.c) - target_include_directories(sphincs_haraka_256s_simple_clean PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-haraka-256s-simple_clean) - target_include_directories(sphincs_haraka_256s_simple_clean PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) - set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) -endif() - -if(OQS_ENABLE_SIG_sphincs_haraka_256s_simple_aesni) - add_library(sphincs_haraka_256s_simple_aesni OBJECT pqclean_sphincs-haraka-256s-simple_aesni/address.c pqclean_sphincs-haraka-256s-simple_aesni/context_haraka.c pqclean_sphincs-haraka-256s-simple_aesni/fors.c pqclean_sphincs-haraka-256s-simple_aesni/haraka.c pqclean_sphincs-haraka-256s-simple_aesni/hash_haraka.c pqclean_sphincs-haraka-256s-simple_aesni/hash_harakax4.c pqclean_sphincs-haraka-256s-simple_aesni/merkle.c pqclean_sphincs-haraka-256s-simple_aesni/sign.c pqclean_sphincs-haraka-256s-simple_aesni/thash_haraka_simple.c pqclean_sphincs-haraka-256s-simple_aesni/thash_haraka_simplex4.c pqclean_sphincs-haraka-256s-simple_aesni/utils.c pqclean_sphincs-haraka-256s-simple_aesni/utilsx4.c pqclean_sphincs-haraka-256s-simple_aesni/wots.c) - target_include_directories(sphincs_haraka_256s_simple_aesni PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-haraka-256s-simple_aesni) - target_include_directories(sphincs_haraka_256s_simple_aesni PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) - target_compile_options(sphincs_haraka_256s_simple_aesni PRIVATE -maes) - set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) -endif() - -if(OQS_ENABLE_SIG_sphincs_sha256_128f_robust) - add_library(sphincs_sha256_128f_robust_clean OBJECT sig_sphincs_sha256_128f_robust.c pqclean_sphincs-sha2-128f-robust_clean/address.c pqclean_sphincs-sha2-128f-robust_clean/context_sha2.c pqclean_sphincs-sha2-128f-robust_clean/fors.c pqclean_sphincs-sha2-128f-robust_clean/hash_sha2.c pqclean_sphincs-sha2-128f-robust_clean/merkle.c pqclean_sphincs-sha2-128f-robust_clean/sign.c pqclean_sphincs-sha2-128f-robust_clean/thash_sha2_robust.c pqclean_sphincs-sha2-128f-robust_clean/utils.c pqclean_sphincs-sha2-128f-robust_clean/utilsx1.c pqclean_sphincs-sha2-128f-robust_clean/wots.c pqclean_sphincs-sha2-128f-robust_clean/wotsx1.c) - target_include_directories(sphincs_sha256_128f_robust_clean PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-sha2-128f-robust_clean) - target_include_directories(sphincs_sha256_128f_robust_clean PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) - set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) -endif() - -if(OQS_ENABLE_SIG_sphincs_sha256_128f_robust_avx2) - add_library(sphincs_sha256_128f_robust_avx2 OBJECT pqclean_sphincs-sha2-128f-robust_avx2/address.c pqclean_sphincs-sha2-128f-robust_avx2/context_sha2.c pqclean_sphincs-sha2-128f-robust_avx2/fors.c pqclean_sphincs-sha2-128f-robust_avx2/hash_sha2.c pqclean_sphincs-sha2-128f-robust_avx2/hash_sha2x8.c pqclean_sphincs-sha2-128f-robust_avx2/merkle.c pqclean_sphincs-sha2-128f-robust_avx2/sha256avx.c pqclean_sphincs-sha2-128f-robust_avx2/sha256x8.c pqclean_sphincs-sha2-128f-robust_avx2/sign.c pqclean_sphincs-sha2-128f-robust_avx2/thash_sha2_robust.c pqclean_sphincs-sha2-128f-robust_avx2/thash_sha2_robustx8.c pqclean_sphincs-sha2-128f-robust_avx2/utils.c pqclean_sphincs-sha2-128f-robust_avx2/utilsx8.c pqclean_sphincs-sha2-128f-robust_avx2/wots.c) - target_include_directories(sphincs_sha256_128f_robust_avx2 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-sha2-128f-robust_avx2) - target_include_directories(sphincs_sha256_128f_robust_avx2 PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) - target_compile_options(sphincs_sha256_128f_robust_avx2 PRIVATE -mavx2) - set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) -endif() - if(OQS_ENABLE_SIG_sphincs_sha256_128f_simple) add_library(sphincs_sha256_128f_simple_clean OBJECT sig_sphincs_sha256_128f_simple.c pqclean_sphincs-sha2-128f-simple_clean/address.c pqclean_sphincs-sha2-128f-simple_clean/context_sha2.c pqclean_sphincs-sha2-128f-simple_clean/fors.c pqclean_sphincs-sha2-128f-simple_clean/hash_sha2.c pqclean_sphincs-sha2-128f-simple_clean/merkle.c pqclean_sphincs-sha2-128f-simple_clean/sign.c pqclean_sphincs-sha2-128f-simple_clean/thash_sha2_simple.c pqclean_sphincs-sha2-128f-simple_clean/utils.c pqclean_sphincs-sha2-128f-simple_clean/utilsx1.c pqclean_sphincs-sha2-128f-simple_clean/wots.c pqclean_sphincs-sha2-128f-simple_clean/wotsx1.c) target_include_directories(sphincs_sha256_128f_simple_clean PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-sha2-128f-simple_clean) @@ -215,21 +20,6 @@ if(OQS_ENABLE_SIG_sphincs_sha256_128f_simple_avx2) set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) endif() -if(OQS_ENABLE_SIG_sphincs_sha256_128s_robust) - add_library(sphincs_sha256_128s_robust_clean OBJECT sig_sphincs_sha256_128s_robust.c pqclean_sphincs-sha2-128s-robust_clean/address.c pqclean_sphincs-sha2-128s-robust_clean/context_sha2.c pqclean_sphincs-sha2-128s-robust_clean/fors.c pqclean_sphincs-sha2-128s-robust_clean/hash_sha2.c pqclean_sphincs-sha2-128s-robust_clean/merkle.c pqclean_sphincs-sha2-128s-robust_clean/sign.c pqclean_sphincs-sha2-128s-robust_clean/thash_sha2_robust.c pqclean_sphincs-sha2-128s-robust_clean/utils.c pqclean_sphincs-sha2-128s-robust_clean/utilsx1.c pqclean_sphincs-sha2-128s-robust_clean/wots.c pqclean_sphincs-sha2-128s-robust_clean/wotsx1.c) - target_include_directories(sphincs_sha256_128s_robust_clean PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-sha2-128s-robust_clean) - target_include_directories(sphincs_sha256_128s_robust_clean PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) - set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) -endif() - -if(OQS_ENABLE_SIG_sphincs_sha256_128s_robust_avx2) - add_library(sphincs_sha256_128s_robust_avx2 OBJECT pqclean_sphincs-sha2-128s-robust_avx2/address.c pqclean_sphincs-sha2-128s-robust_avx2/context_sha2.c pqclean_sphincs-sha2-128s-robust_avx2/fors.c pqclean_sphincs-sha2-128s-robust_avx2/hash_sha2.c pqclean_sphincs-sha2-128s-robust_avx2/hash_sha2x8.c pqclean_sphincs-sha2-128s-robust_avx2/merkle.c pqclean_sphincs-sha2-128s-robust_avx2/sha256avx.c pqclean_sphincs-sha2-128s-robust_avx2/sha256x8.c pqclean_sphincs-sha2-128s-robust_avx2/sign.c pqclean_sphincs-sha2-128s-robust_avx2/thash_sha2_robust.c pqclean_sphincs-sha2-128s-robust_avx2/thash_sha2_robustx8.c pqclean_sphincs-sha2-128s-robust_avx2/utils.c pqclean_sphincs-sha2-128s-robust_avx2/utilsx8.c pqclean_sphincs-sha2-128s-robust_avx2/wots.c) - target_include_directories(sphincs_sha256_128s_robust_avx2 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-sha2-128s-robust_avx2) - target_include_directories(sphincs_sha256_128s_robust_avx2 PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) - target_compile_options(sphincs_sha256_128s_robust_avx2 PRIVATE -mavx2) - set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) -endif() - if(OQS_ENABLE_SIG_sphincs_sha256_128s_simple) add_library(sphincs_sha256_128s_simple_clean OBJECT sig_sphincs_sha256_128s_simple.c pqclean_sphincs-sha2-128s-simple_clean/address.c pqclean_sphincs-sha2-128s-simple_clean/context_sha2.c pqclean_sphincs-sha2-128s-simple_clean/fors.c pqclean_sphincs-sha2-128s-simple_clean/hash_sha2.c pqclean_sphincs-sha2-128s-simple_clean/merkle.c pqclean_sphincs-sha2-128s-simple_clean/sign.c pqclean_sphincs-sha2-128s-simple_clean/thash_sha2_simple.c pqclean_sphincs-sha2-128s-simple_clean/utils.c pqclean_sphincs-sha2-128s-simple_clean/utilsx1.c pqclean_sphincs-sha2-128s-simple_clean/wots.c pqclean_sphincs-sha2-128s-simple_clean/wotsx1.c) target_include_directories(sphincs_sha256_128s_simple_clean PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-sha2-128s-simple_clean) @@ -245,21 +35,6 @@ if(OQS_ENABLE_SIG_sphincs_sha256_128s_simple_avx2) set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) endif() -if(OQS_ENABLE_SIG_sphincs_sha256_192f_robust) - add_library(sphincs_sha256_192f_robust_clean OBJECT sig_sphincs_sha256_192f_robust.c pqclean_sphincs-sha2-192f-robust_clean/address.c pqclean_sphincs-sha2-192f-robust_clean/context_sha2.c pqclean_sphincs-sha2-192f-robust_clean/fors.c pqclean_sphincs-sha2-192f-robust_clean/hash_sha2.c pqclean_sphincs-sha2-192f-robust_clean/merkle.c pqclean_sphincs-sha2-192f-robust_clean/sign.c pqclean_sphincs-sha2-192f-robust_clean/thash_sha2_robust.c pqclean_sphincs-sha2-192f-robust_clean/utils.c pqclean_sphincs-sha2-192f-robust_clean/utilsx1.c pqclean_sphincs-sha2-192f-robust_clean/wots.c pqclean_sphincs-sha2-192f-robust_clean/wotsx1.c) - target_include_directories(sphincs_sha256_192f_robust_clean PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-sha2-192f-robust_clean) - target_include_directories(sphincs_sha256_192f_robust_clean PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) - set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) -endif() - -if(OQS_ENABLE_SIG_sphincs_sha256_192f_robust_avx2) - add_library(sphincs_sha256_192f_robust_avx2 OBJECT pqclean_sphincs-sha2-192f-robust_avx2/address.c pqclean_sphincs-sha2-192f-robust_avx2/context_sha2.c pqclean_sphincs-sha2-192f-robust_avx2/fors.c pqclean_sphincs-sha2-192f-robust_avx2/hash_sha2.c pqclean_sphincs-sha2-192f-robust_avx2/hash_sha2x8.c pqclean_sphincs-sha2-192f-robust_avx2/merkle.c pqclean_sphincs-sha2-192f-robust_avx2/sha256avx.c pqclean_sphincs-sha2-192f-robust_avx2/sha256x8.c pqclean_sphincs-sha2-192f-robust_avx2/sha512x4.c pqclean_sphincs-sha2-192f-robust_avx2/sign.c pqclean_sphincs-sha2-192f-robust_avx2/thash_sha2_robust.c pqclean_sphincs-sha2-192f-robust_avx2/thash_sha2_robustx8.c pqclean_sphincs-sha2-192f-robust_avx2/utils.c pqclean_sphincs-sha2-192f-robust_avx2/utilsx8.c pqclean_sphincs-sha2-192f-robust_avx2/wots.c) - target_include_directories(sphincs_sha256_192f_robust_avx2 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-sha2-192f-robust_avx2) - target_include_directories(sphincs_sha256_192f_robust_avx2 PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) - target_compile_options(sphincs_sha256_192f_robust_avx2 PRIVATE -mavx2) - set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) -endif() - if(OQS_ENABLE_SIG_sphincs_sha256_192f_simple) add_library(sphincs_sha256_192f_simple_clean OBJECT sig_sphincs_sha256_192f_simple.c pqclean_sphincs-sha2-192f-simple_clean/address.c pqclean_sphincs-sha2-192f-simple_clean/context_sha2.c pqclean_sphincs-sha2-192f-simple_clean/fors.c pqclean_sphincs-sha2-192f-simple_clean/hash_sha2.c pqclean_sphincs-sha2-192f-simple_clean/merkle.c pqclean_sphincs-sha2-192f-simple_clean/sign.c pqclean_sphincs-sha2-192f-simple_clean/thash_sha2_simple.c pqclean_sphincs-sha2-192f-simple_clean/utils.c pqclean_sphincs-sha2-192f-simple_clean/utilsx1.c pqclean_sphincs-sha2-192f-simple_clean/wots.c pqclean_sphincs-sha2-192f-simple_clean/wotsx1.c) target_include_directories(sphincs_sha256_192f_simple_clean PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-sha2-192f-simple_clean) @@ -275,21 +50,6 @@ if(OQS_ENABLE_SIG_sphincs_sha256_192f_simple_avx2) set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) endif() -if(OQS_ENABLE_SIG_sphincs_sha256_192s_robust) - add_library(sphincs_sha256_192s_robust_clean OBJECT sig_sphincs_sha256_192s_robust.c pqclean_sphincs-sha2-192s-robust_clean/address.c pqclean_sphincs-sha2-192s-robust_clean/context_sha2.c pqclean_sphincs-sha2-192s-robust_clean/fors.c pqclean_sphincs-sha2-192s-robust_clean/hash_sha2.c pqclean_sphincs-sha2-192s-robust_clean/merkle.c pqclean_sphincs-sha2-192s-robust_clean/sign.c pqclean_sphincs-sha2-192s-robust_clean/thash_sha2_robust.c pqclean_sphincs-sha2-192s-robust_clean/utils.c pqclean_sphincs-sha2-192s-robust_clean/utilsx1.c pqclean_sphincs-sha2-192s-robust_clean/wots.c pqclean_sphincs-sha2-192s-robust_clean/wotsx1.c) - target_include_directories(sphincs_sha256_192s_robust_clean PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-sha2-192s-robust_clean) - target_include_directories(sphincs_sha256_192s_robust_clean PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) - set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) -endif() - -if(OQS_ENABLE_SIG_sphincs_sha256_192s_robust_avx2) - add_library(sphincs_sha256_192s_robust_avx2 OBJECT pqclean_sphincs-sha2-192s-robust_avx2/address.c pqclean_sphincs-sha2-192s-robust_avx2/context_sha2.c pqclean_sphincs-sha2-192s-robust_avx2/fors.c pqclean_sphincs-sha2-192s-robust_avx2/hash_sha2.c pqclean_sphincs-sha2-192s-robust_avx2/hash_sha2x8.c pqclean_sphincs-sha2-192s-robust_avx2/merkle.c pqclean_sphincs-sha2-192s-robust_avx2/sha256avx.c pqclean_sphincs-sha2-192s-robust_avx2/sha256x8.c pqclean_sphincs-sha2-192s-robust_avx2/sha512x4.c pqclean_sphincs-sha2-192s-robust_avx2/sign.c pqclean_sphincs-sha2-192s-robust_avx2/thash_sha2_robust.c pqclean_sphincs-sha2-192s-robust_avx2/thash_sha2_robustx8.c pqclean_sphincs-sha2-192s-robust_avx2/utils.c pqclean_sphincs-sha2-192s-robust_avx2/utilsx8.c pqclean_sphincs-sha2-192s-robust_avx2/wots.c) - target_include_directories(sphincs_sha256_192s_robust_avx2 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-sha2-192s-robust_avx2) - target_include_directories(sphincs_sha256_192s_robust_avx2 PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) - target_compile_options(sphincs_sha256_192s_robust_avx2 PRIVATE -mavx2) - set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) -endif() - if(OQS_ENABLE_SIG_sphincs_sha256_192s_simple) add_library(sphincs_sha256_192s_simple_clean OBJECT sig_sphincs_sha256_192s_simple.c pqclean_sphincs-sha2-192s-simple_clean/address.c pqclean_sphincs-sha2-192s-simple_clean/context_sha2.c pqclean_sphincs-sha2-192s-simple_clean/fors.c pqclean_sphincs-sha2-192s-simple_clean/hash_sha2.c pqclean_sphincs-sha2-192s-simple_clean/merkle.c pqclean_sphincs-sha2-192s-simple_clean/sign.c pqclean_sphincs-sha2-192s-simple_clean/thash_sha2_simple.c pqclean_sphincs-sha2-192s-simple_clean/utils.c pqclean_sphincs-sha2-192s-simple_clean/utilsx1.c pqclean_sphincs-sha2-192s-simple_clean/wots.c pqclean_sphincs-sha2-192s-simple_clean/wotsx1.c) target_include_directories(sphincs_sha256_192s_simple_clean PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-sha2-192s-simple_clean) @@ -305,21 +65,6 @@ if(OQS_ENABLE_SIG_sphincs_sha256_192s_simple_avx2) set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) endif() -if(OQS_ENABLE_SIG_sphincs_sha256_256f_robust) - add_library(sphincs_sha256_256f_robust_clean OBJECT sig_sphincs_sha256_256f_robust.c pqclean_sphincs-sha2-256f-robust_clean/address.c pqclean_sphincs-sha2-256f-robust_clean/context_sha2.c pqclean_sphincs-sha2-256f-robust_clean/fors.c pqclean_sphincs-sha2-256f-robust_clean/hash_sha2.c pqclean_sphincs-sha2-256f-robust_clean/merkle.c pqclean_sphincs-sha2-256f-robust_clean/sign.c pqclean_sphincs-sha2-256f-robust_clean/thash_sha2_robust.c pqclean_sphincs-sha2-256f-robust_clean/utils.c pqclean_sphincs-sha2-256f-robust_clean/utilsx1.c pqclean_sphincs-sha2-256f-robust_clean/wots.c pqclean_sphincs-sha2-256f-robust_clean/wotsx1.c) - target_include_directories(sphincs_sha256_256f_robust_clean PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-sha2-256f-robust_clean) - target_include_directories(sphincs_sha256_256f_robust_clean PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) - set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) -endif() - -if(OQS_ENABLE_SIG_sphincs_sha256_256f_robust_avx2) - add_library(sphincs_sha256_256f_robust_avx2 OBJECT pqclean_sphincs-sha2-256f-robust_avx2/address.c pqclean_sphincs-sha2-256f-robust_avx2/context_sha2.c pqclean_sphincs-sha2-256f-robust_avx2/fors.c pqclean_sphincs-sha2-256f-robust_avx2/hash_sha2.c pqclean_sphincs-sha2-256f-robust_avx2/hash_sha2x8.c pqclean_sphincs-sha2-256f-robust_avx2/merkle.c pqclean_sphincs-sha2-256f-robust_avx2/sha256avx.c pqclean_sphincs-sha2-256f-robust_avx2/sha256x8.c pqclean_sphincs-sha2-256f-robust_avx2/sha512x4.c pqclean_sphincs-sha2-256f-robust_avx2/sign.c pqclean_sphincs-sha2-256f-robust_avx2/thash_sha2_robust.c pqclean_sphincs-sha2-256f-robust_avx2/thash_sha2_robustx8.c pqclean_sphincs-sha2-256f-robust_avx2/utils.c pqclean_sphincs-sha2-256f-robust_avx2/utilsx8.c pqclean_sphincs-sha2-256f-robust_avx2/wots.c) - target_include_directories(sphincs_sha256_256f_robust_avx2 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-sha2-256f-robust_avx2) - target_include_directories(sphincs_sha256_256f_robust_avx2 PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) - target_compile_options(sphincs_sha256_256f_robust_avx2 PRIVATE -mavx2) - set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) -endif() - if(OQS_ENABLE_SIG_sphincs_sha256_256f_simple) add_library(sphincs_sha256_256f_simple_clean OBJECT sig_sphincs_sha256_256f_simple.c pqclean_sphincs-sha2-256f-simple_clean/address.c pqclean_sphincs-sha2-256f-simple_clean/context_sha2.c pqclean_sphincs-sha2-256f-simple_clean/fors.c pqclean_sphincs-sha2-256f-simple_clean/hash_sha2.c pqclean_sphincs-sha2-256f-simple_clean/merkle.c pqclean_sphincs-sha2-256f-simple_clean/sign.c pqclean_sphincs-sha2-256f-simple_clean/thash_sha2_simple.c pqclean_sphincs-sha2-256f-simple_clean/utils.c pqclean_sphincs-sha2-256f-simple_clean/utilsx1.c pqclean_sphincs-sha2-256f-simple_clean/wots.c pqclean_sphincs-sha2-256f-simple_clean/wotsx1.c) target_include_directories(sphincs_sha256_256f_simple_clean PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-sha2-256f-simple_clean) @@ -335,21 +80,6 @@ if(OQS_ENABLE_SIG_sphincs_sha256_256f_simple_avx2) set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) endif() -if(OQS_ENABLE_SIG_sphincs_sha256_256s_robust) - add_library(sphincs_sha256_256s_robust_clean OBJECT sig_sphincs_sha256_256s_robust.c pqclean_sphincs-sha2-256s-robust_clean/address.c pqclean_sphincs-sha2-256s-robust_clean/context_sha2.c pqclean_sphincs-sha2-256s-robust_clean/fors.c pqclean_sphincs-sha2-256s-robust_clean/hash_sha2.c pqclean_sphincs-sha2-256s-robust_clean/merkle.c pqclean_sphincs-sha2-256s-robust_clean/sign.c pqclean_sphincs-sha2-256s-robust_clean/thash_sha2_robust.c pqclean_sphincs-sha2-256s-robust_clean/utils.c pqclean_sphincs-sha2-256s-robust_clean/utilsx1.c pqclean_sphincs-sha2-256s-robust_clean/wots.c pqclean_sphincs-sha2-256s-robust_clean/wotsx1.c) - target_include_directories(sphincs_sha256_256s_robust_clean PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-sha2-256s-robust_clean) - target_include_directories(sphincs_sha256_256s_robust_clean PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) - set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) -endif() - -if(OQS_ENABLE_SIG_sphincs_sha256_256s_robust_avx2) - add_library(sphincs_sha256_256s_robust_avx2 OBJECT pqclean_sphincs-sha2-256s-robust_avx2/address.c pqclean_sphincs-sha2-256s-robust_avx2/context_sha2.c pqclean_sphincs-sha2-256s-robust_avx2/fors.c pqclean_sphincs-sha2-256s-robust_avx2/hash_sha2.c pqclean_sphincs-sha2-256s-robust_avx2/hash_sha2x8.c pqclean_sphincs-sha2-256s-robust_avx2/merkle.c pqclean_sphincs-sha2-256s-robust_avx2/sha256avx.c pqclean_sphincs-sha2-256s-robust_avx2/sha256x8.c pqclean_sphincs-sha2-256s-robust_avx2/sha512x4.c pqclean_sphincs-sha2-256s-robust_avx2/sign.c pqclean_sphincs-sha2-256s-robust_avx2/thash_sha2_robust.c pqclean_sphincs-sha2-256s-robust_avx2/thash_sha2_robustx8.c pqclean_sphincs-sha2-256s-robust_avx2/utils.c pqclean_sphincs-sha2-256s-robust_avx2/utilsx8.c pqclean_sphincs-sha2-256s-robust_avx2/wots.c) - target_include_directories(sphincs_sha256_256s_robust_avx2 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-sha2-256s-robust_avx2) - target_include_directories(sphincs_sha256_256s_robust_avx2 PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) - target_compile_options(sphincs_sha256_256s_robust_avx2 PRIVATE -mavx2) - set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) -endif() - if(OQS_ENABLE_SIG_sphincs_sha256_256s_simple) add_library(sphincs_sha256_256s_simple_clean OBJECT sig_sphincs_sha256_256s_simple.c pqclean_sphincs-sha2-256s-simple_clean/address.c pqclean_sphincs-sha2-256s-simple_clean/context_sha2.c pqclean_sphincs-sha2-256s-simple_clean/fors.c pqclean_sphincs-sha2-256s-simple_clean/hash_sha2.c pqclean_sphincs-sha2-256s-simple_clean/merkle.c pqclean_sphincs-sha2-256s-simple_clean/sign.c pqclean_sphincs-sha2-256s-simple_clean/thash_sha2_simple.c pqclean_sphincs-sha2-256s-simple_clean/utils.c pqclean_sphincs-sha2-256s-simple_clean/utilsx1.c pqclean_sphincs-sha2-256s-simple_clean/wots.c pqclean_sphincs-sha2-256s-simple_clean/wotsx1.c) target_include_directories(sphincs_sha256_256s_simple_clean PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-sha2-256s-simple_clean) @@ -365,29 +95,6 @@ if(OQS_ENABLE_SIG_sphincs_sha256_256s_simple_avx2) set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) endif() -if(OQS_ENABLE_SIG_sphincs_shake256_128f_robust) - add_library(sphincs_shake256_128f_robust_clean OBJECT sig_sphincs_shake256_128f_robust.c pqclean_sphincs-shake-128f-robust_clean/address.c pqclean_sphincs-shake-128f-robust_clean/context_shake.c pqclean_sphincs-shake-128f-robust_clean/fors.c pqclean_sphincs-shake-128f-robust_clean/hash_shake.c pqclean_sphincs-shake-128f-robust_clean/merkle.c pqclean_sphincs-shake-128f-robust_clean/sign.c pqclean_sphincs-shake-128f-robust_clean/thash_shake_robust.c pqclean_sphincs-shake-128f-robust_clean/utils.c pqclean_sphincs-shake-128f-robust_clean/utilsx1.c pqclean_sphincs-shake-128f-robust_clean/wots.c pqclean_sphincs-shake-128f-robust_clean/wotsx1.c) - target_include_directories(sphincs_shake256_128f_robust_clean PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-shake-128f-robust_clean) - target_include_directories(sphincs_shake256_128f_robust_clean PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) - set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) -endif() - -if(OQS_ENABLE_SIG_sphincs_shake256_128f_robust_avx2) - add_library(sphincs_shake256_128f_robust_avx2 OBJECT pqclean_sphincs-shake-128f-robust_avx2/address.c pqclean_sphincs-shake-128f-robust_avx2/context_shake.c pqclean_sphincs-shake-128f-robust_avx2/fips202x4.c pqclean_sphincs-shake-128f-robust_avx2/fors.c pqclean_sphincs-shake-128f-robust_avx2/hash_shake.c pqclean_sphincs-shake-128f-robust_avx2/hash_shakex4.c pqclean_sphincs-shake-128f-robust_avx2/merkle.c pqclean_sphincs-shake-128f-robust_avx2/sign.c pqclean_sphincs-shake-128f-robust_avx2/thash_shake_robust.c pqclean_sphincs-shake-128f-robust_avx2/thash_shake_robustx4.c pqclean_sphincs-shake-128f-robust_avx2/utils.c pqclean_sphincs-shake-128f-robust_avx2/utilsx4.c pqclean_sphincs-shake-128f-robust_avx2/wots.c) - target_include_directories(sphincs_shake256_128f_robust_avx2 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-shake-128f-robust_avx2) - target_include_directories(sphincs_shake256_128f_robust_avx2 PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) - target_compile_options(sphincs_shake256_128f_robust_avx2 PRIVATE -mavx2) - set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) -endif() - -if(OQS_ENABLE_SIG_sphincs_shake256_128f_robust_aarch64) - add_library(sphincs_shake256_128f_robust_aarch64 OBJECT pqclean_sphincs-shake-128f-robust_aarch64/address.c pqclean_sphincs-shake-128f-robust_aarch64/context_shake.c pqclean_sphincs-shake-128f-robust_aarch64/f1600x2.s pqclean_sphincs-shake-128f-robust_aarch64/f1600x2_const.c pqclean_sphincs-shake-128f-robust_aarch64/fips202x2.c pqclean_sphincs-shake-128f-robust_aarch64/fors.c pqclean_sphincs-shake-128f-robust_aarch64/hash_shake.c pqclean_sphincs-shake-128f-robust_aarch64/hash_shakex2.c pqclean_sphincs-shake-128f-robust_aarch64/merkle.c pqclean_sphincs-shake-128f-robust_aarch64/sign.c pqclean_sphincs-shake-128f-robust_aarch64/thash_shake_robustx2.c pqclean_sphincs-shake-128f-robust_aarch64/utils.c pqclean_sphincs-shake-128f-robust_aarch64/utilsx2.c pqclean_sphincs-shake-128f-robust_aarch64/wots.c) - target_include_directories(sphincs_shake256_128f_robust_aarch64 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-shake-128f-robust_aarch64) - target_include_directories(sphincs_shake256_128f_robust_aarch64 PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) - target_compile_options(sphincs_shake256_128f_robust_aarch64 PRIVATE -march=armv8-a+crypto+sha3) - set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) -endif() - if(OQS_ENABLE_SIG_sphincs_shake256_128f_simple) add_library(sphincs_shake256_128f_simple_clean OBJECT sig_sphincs_shake256_128f_simple.c pqclean_sphincs-shake-128f-simple_clean/address.c pqclean_sphincs-shake-128f-simple_clean/context_shake.c pqclean_sphincs-shake-128f-simple_clean/fors.c pqclean_sphincs-shake-128f-simple_clean/hash_shake.c pqclean_sphincs-shake-128f-simple_clean/merkle.c pqclean_sphincs-shake-128f-simple_clean/sign.c pqclean_sphincs-shake-128f-simple_clean/thash_shake_simple.c pqclean_sphincs-shake-128f-simple_clean/utils.c pqclean_sphincs-shake-128f-simple_clean/utilsx1.c pqclean_sphincs-shake-128f-simple_clean/wots.c pqclean_sphincs-shake-128f-simple_clean/wotsx1.c) target_include_directories(sphincs_shake256_128f_simple_clean PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-shake-128f-simple_clean) @@ -411,29 +118,6 @@ if(OQS_ENABLE_SIG_sphincs_shake256_128f_simple_aarch64) set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) endif() -if(OQS_ENABLE_SIG_sphincs_shake256_128s_robust) - add_library(sphincs_shake256_128s_robust_clean OBJECT sig_sphincs_shake256_128s_robust.c pqclean_sphincs-shake-128s-robust_clean/address.c pqclean_sphincs-shake-128s-robust_clean/context_shake.c pqclean_sphincs-shake-128s-robust_clean/fors.c pqclean_sphincs-shake-128s-robust_clean/hash_shake.c pqclean_sphincs-shake-128s-robust_clean/merkle.c pqclean_sphincs-shake-128s-robust_clean/sign.c pqclean_sphincs-shake-128s-robust_clean/thash_shake_robust.c pqclean_sphincs-shake-128s-robust_clean/utils.c pqclean_sphincs-shake-128s-robust_clean/utilsx1.c pqclean_sphincs-shake-128s-robust_clean/wots.c pqclean_sphincs-shake-128s-robust_clean/wotsx1.c) - target_include_directories(sphincs_shake256_128s_robust_clean PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-shake-128s-robust_clean) - target_include_directories(sphincs_shake256_128s_robust_clean PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) - set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) -endif() - -if(OQS_ENABLE_SIG_sphincs_shake256_128s_robust_avx2) - add_library(sphincs_shake256_128s_robust_avx2 OBJECT pqclean_sphincs-shake-128s-robust_avx2/address.c pqclean_sphincs-shake-128s-robust_avx2/context_shake.c pqclean_sphincs-shake-128s-robust_avx2/fips202x4.c pqclean_sphincs-shake-128s-robust_avx2/fors.c pqclean_sphincs-shake-128s-robust_avx2/hash_shake.c pqclean_sphincs-shake-128s-robust_avx2/hash_shakex4.c pqclean_sphincs-shake-128s-robust_avx2/merkle.c pqclean_sphincs-shake-128s-robust_avx2/sign.c pqclean_sphincs-shake-128s-robust_avx2/thash_shake_robust.c pqclean_sphincs-shake-128s-robust_avx2/thash_shake_robustx4.c pqclean_sphincs-shake-128s-robust_avx2/utils.c pqclean_sphincs-shake-128s-robust_avx2/utilsx4.c pqclean_sphincs-shake-128s-robust_avx2/wots.c) - target_include_directories(sphincs_shake256_128s_robust_avx2 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-shake-128s-robust_avx2) - target_include_directories(sphincs_shake256_128s_robust_avx2 PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) - target_compile_options(sphincs_shake256_128s_robust_avx2 PRIVATE -mavx2) - set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) -endif() - -if(OQS_ENABLE_SIG_sphincs_shake256_128s_robust_aarch64) - add_library(sphincs_shake256_128s_robust_aarch64 OBJECT pqclean_sphincs-shake-128s-robust_aarch64/address.c pqclean_sphincs-shake-128s-robust_aarch64/context_shake.c pqclean_sphincs-shake-128s-robust_aarch64/f1600x2.s pqclean_sphincs-shake-128s-robust_aarch64/f1600x2_const.c pqclean_sphincs-shake-128s-robust_aarch64/fips202x2.c pqclean_sphincs-shake-128s-robust_aarch64/fors.c pqclean_sphincs-shake-128s-robust_aarch64/hash_shake.c pqclean_sphincs-shake-128s-robust_aarch64/hash_shakex2.c pqclean_sphincs-shake-128s-robust_aarch64/merkle.c pqclean_sphincs-shake-128s-robust_aarch64/sign.c pqclean_sphincs-shake-128s-robust_aarch64/thash_shake_robustx2.c pqclean_sphincs-shake-128s-robust_aarch64/utils.c pqclean_sphincs-shake-128s-robust_aarch64/utilsx2.c pqclean_sphincs-shake-128s-robust_aarch64/wots.c) - target_include_directories(sphincs_shake256_128s_robust_aarch64 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-shake-128s-robust_aarch64) - target_include_directories(sphincs_shake256_128s_robust_aarch64 PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) - target_compile_options(sphincs_shake256_128s_robust_aarch64 PRIVATE -march=armv8-a+crypto+sha3) - set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) -endif() - if(OQS_ENABLE_SIG_sphincs_shake256_128s_simple) add_library(sphincs_shake256_128s_simple_clean OBJECT sig_sphincs_shake256_128s_simple.c pqclean_sphincs-shake-128s-simple_clean/address.c pqclean_sphincs-shake-128s-simple_clean/context_shake.c pqclean_sphincs-shake-128s-simple_clean/fors.c pqclean_sphincs-shake-128s-simple_clean/hash_shake.c pqclean_sphincs-shake-128s-simple_clean/merkle.c pqclean_sphincs-shake-128s-simple_clean/sign.c pqclean_sphincs-shake-128s-simple_clean/thash_shake_simple.c pqclean_sphincs-shake-128s-simple_clean/utils.c pqclean_sphincs-shake-128s-simple_clean/utilsx1.c pqclean_sphincs-shake-128s-simple_clean/wots.c pqclean_sphincs-shake-128s-simple_clean/wotsx1.c) target_include_directories(sphincs_shake256_128s_simple_clean PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-shake-128s-simple_clean) @@ -457,29 +141,6 @@ if(OQS_ENABLE_SIG_sphincs_shake256_128s_simple_aarch64) set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) endif() -if(OQS_ENABLE_SIG_sphincs_shake256_192f_robust) - add_library(sphincs_shake256_192f_robust_clean OBJECT sig_sphincs_shake256_192f_robust.c pqclean_sphincs-shake-192f-robust_clean/address.c pqclean_sphincs-shake-192f-robust_clean/context_shake.c pqclean_sphincs-shake-192f-robust_clean/fors.c pqclean_sphincs-shake-192f-robust_clean/hash_shake.c pqclean_sphincs-shake-192f-robust_clean/merkle.c pqclean_sphincs-shake-192f-robust_clean/sign.c pqclean_sphincs-shake-192f-robust_clean/thash_shake_robust.c pqclean_sphincs-shake-192f-robust_clean/utils.c pqclean_sphincs-shake-192f-robust_clean/utilsx1.c pqclean_sphincs-shake-192f-robust_clean/wots.c pqclean_sphincs-shake-192f-robust_clean/wotsx1.c) - target_include_directories(sphincs_shake256_192f_robust_clean PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-shake-192f-robust_clean) - target_include_directories(sphincs_shake256_192f_robust_clean PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) - set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) -endif() - -if(OQS_ENABLE_SIG_sphincs_shake256_192f_robust_avx2) - add_library(sphincs_shake256_192f_robust_avx2 OBJECT pqclean_sphincs-shake-192f-robust_avx2/address.c pqclean_sphincs-shake-192f-robust_avx2/context_shake.c pqclean_sphincs-shake-192f-robust_avx2/fips202x4.c pqclean_sphincs-shake-192f-robust_avx2/fors.c pqclean_sphincs-shake-192f-robust_avx2/hash_shake.c pqclean_sphincs-shake-192f-robust_avx2/hash_shakex4.c pqclean_sphincs-shake-192f-robust_avx2/merkle.c pqclean_sphincs-shake-192f-robust_avx2/sign.c pqclean_sphincs-shake-192f-robust_avx2/thash_shake_robust.c pqclean_sphincs-shake-192f-robust_avx2/thash_shake_robustx4.c pqclean_sphincs-shake-192f-robust_avx2/utils.c pqclean_sphincs-shake-192f-robust_avx2/utilsx4.c pqclean_sphincs-shake-192f-robust_avx2/wots.c) - target_include_directories(sphincs_shake256_192f_robust_avx2 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-shake-192f-robust_avx2) - target_include_directories(sphincs_shake256_192f_robust_avx2 PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) - target_compile_options(sphincs_shake256_192f_robust_avx2 PRIVATE -mavx2) - set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) -endif() - -if(OQS_ENABLE_SIG_sphincs_shake256_192f_robust_aarch64) - add_library(sphincs_shake256_192f_robust_aarch64 OBJECT pqclean_sphincs-shake-192f-robust_aarch64/address.c pqclean_sphincs-shake-192f-robust_aarch64/context_shake.c pqclean_sphincs-shake-192f-robust_aarch64/f1600x2.s pqclean_sphincs-shake-192f-robust_aarch64/f1600x2_const.c pqclean_sphincs-shake-192f-robust_aarch64/fips202x2.c pqclean_sphincs-shake-192f-robust_aarch64/fors.c pqclean_sphincs-shake-192f-robust_aarch64/hash_shake.c pqclean_sphincs-shake-192f-robust_aarch64/hash_shakex2.c pqclean_sphincs-shake-192f-robust_aarch64/merkle.c pqclean_sphincs-shake-192f-robust_aarch64/sign.c pqclean_sphincs-shake-192f-robust_aarch64/thash_shake_robustx2.c pqclean_sphincs-shake-192f-robust_aarch64/utils.c pqclean_sphincs-shake-192f-robust_aarch64/utilsx2.c pqclean_sphincs-shake-192f-robust_aarch64/wots.c) - target_include_directories(sphincs_shake256_192f_robust_aarch64 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-shake-192f-robust_aarch64) - target_include_directories(sphincs_shake256_192f_robust_aarch64 PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) - target_compile_options(sphincs_shake256_192f_robust_aarch64 PRIVATE -march=armv8-a+crypto+sha3) - set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) -endif() - if(OQS_ENABLE_SIG_sphincs_shake256_192f_simple) add_library(sphincs_shake256_192f_simple_clean OBJECT sig_sphincs_shake256_192f_simple.c pqclean_sphincs-shake-192f-simple_clean/address.c pqclean_sphincs-shake-192f-simple_clean/context_shake.c pqclean_sphincs-shake-192f-simple_clean/fors.c pqclean_sphincs-shake-192f-simple_clean/hash_shake.c pqclean_sphincs-shake-192f-simple_clean/merkle.c pqclean_sphincs-shake-192f-simple_clean/sign.c pqclean_sphincs-shake-192f-simple_clean/thash_shake_simple.c pqclean_sphincs-shake-192f-simple_clean/utils.c pqclean_sphincs-shake-192f-simple_clean/utilsx1.c pqclean_sphincs-shake-192f-simple_clean/wots.c pqclean_sphincs-shake-192f-simple_clean/wotsx1.c) target_include_directories(sphincs_shake256_192f_simple_clean PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-shake-192f-simple_clean) @@ -503,29 +164,6 @@ if(OQS_ENABLE_SIG_sphincs_shake256_192f_simple_aarch64) set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) endif() -if(OQS_ENABLE_SIG_sphincs_shake256_192s_robust) - add_library(sphincs_shake256_192s_robust_clean OBJECT sig_sphincs_shake256_192s_robust.c pqclean_sphincs-shake-192s-robust_clean/address.c pqclean_sphincs-shake-192s-robust_clean/context_shake.c pqclean_sphincs-shake-192s-robust_clean/fors.c pqclean_sphincs-shake-192s-robust_clean/hash_shake.c pqclean_sphincs-shake-192s-robust_clean/merkle.c pqclean_sphincs-shake-192s-robust_clean/sign.c pqclean_sphincs-shake-192s-robust_clean/thash_shake_robust.c pqclean_sphincs-shake-192s-robust_clean/utils.c pqclean_sphincs-shake-192s-robust_clean/utilsx1.c pqclean_sphincs-shake-192s-robust_clean/wots.c pqclean_sphincs-shake-192s-robust_clean/wotsx1.c) - target_include_directories(sphincs_shake256_192s_robust_clean PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-shake-192s-robust_clean) - target_include_directories(sphincs_shake256_192s_robust_clean PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) - set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) -endif() - -if(OQS_ENABLE_SIG_sphincs_shake256_192s_robust_avx2) - add_library(sphincs_shake256_192s_robust_avx2 OBJECT pqclean_sphincs-shake-192s-robust_avx2/address.c pqclean_sphincs-shake-192s-robust_avx2/context_shake.c pqclean_sphincs-shake-192s-robust_avx2/fips202x4.c pqclean_sphincs-shake-192s-robust_avx2/fors.c pqclean_sphincs-shake-192s-robust_avx2/hash_shake.c pqclean_sphincs-shake-192s-robust_avx2/hash_shakex4.c pqclean_sphincs-shake-192s-robust_avx2/merkle.c pqclean_sphincs-shake-192s-robust_avx2/sign.c pqclean_sphincs-shake-192s-robust_avx2/thash_shake_robust.c pqclean_sphincs-shake-192s-robust_avx2/thash_shake_robustx4.c pqclean_sphincs-shake-192s-robust_avx2/utils.c pqclean_sphincs-shake-192s-robust_avx2/utilsx4.c pqclean_sphincs-shake-192s-robust_avx2/wots.c) - target_include_directories(sphincs_shake256_192s_robust_avx2 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-shake-192s-robust_avx2) - target_include_directories(sphincs_shake256_192s_robust_avx2 PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) - target_compile_options(sphincs_shake256_192s_robust_avx2 PRIVATE -mavx2) - set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) -endif() - -if(OQS_ENABLE_SIG_sphincs_shake256_192s_robust_aarch64) - add_library(sphincs_shake256_192s_robust_aarch64 OBJECT pqclean_sphincs-shake-192s-robust_aarch64/address.c pqclean_sphincs-shake-192s-robust_aarch64/context_shake.c pqclean_sphincs-shake-192s-robust_aarch64/f1600x2.s pqclean_sphincs-shake-192s-robust_aarch64/f1600x2_const.c pqclean_sphincs-shake-192s-robust_aarch64/fips202x2.c pqclean_sphincs-shake-192s-robust_aarch64/fors.c pqclean_sphincs-shake-192s-robust_aarch64/hash_shake.c pqclean_sphincs-shake-192s-robust_aarch64/hash_shakex2.c pqclean_sphincs-shake-192s-robust_aarch64/merkle.c pqclean_sphincs-shake-192s-robust_aarch64/sign.c pqclean_sphincs-shake-192s-robust_aarch64/thash_shake_robustx2.c pqclean_sphincs-shake-192s-robust_aarch64/utils.c pqclean_sphincs-shake-192s-robust_aarch64/utilsx2.c pqclean_sphincs-shake-192s-robust_aarch64/wots.c) - target_include_directories(sphincs_shake256_192s_robust_aarch64 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-shake-192s-robust_aarch64) - target_include_directories(sphincs_shake256_192s_robust_aarch64 PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) - target_compile_options(sphincs_shake256_192s_robust_aarch64 PRIVATE -march=armv8-a+crypto+sha3) - set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) -endif() - if(OQS_ENABLE_SIG_sphincs_shake256_192s_simple) add_library(sphincs_shake256_192s_simple_clean OBJECT sig_sphincs_shake256_192s_simple.c pqclean_sphincs-shake-192s-simple_clean/address.c pqclean_sphincs-shake-192s-simple_clean/context_shake.c pqclean_sphincs-shake-192s-simple_clean/fors.c pqclean_sphincs-shake-192s-simple_clean/hash_shake.c pqclean_sphincs-shake-192s-simple_clean/merkle.c pqclean_sphincs-shake-192s-simple_clean/sign.c pqclean_sphincs-shake-192s-simple_clean/thash_shake_simple.c pqclean_sphincs-shake-192s-simple_clean/utils.c pqclean_sphincs-shake-192s-simple_clean/utilsx1.c pqclean_sphincs-shake-192s-simple_clean/wots.c pqclean_sphincs-shake-192s-simple_clean/wotsx1.c) target_include_directories(sphincs_shake256_192s_simple_clean PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-shake-192s-simple_clean) @@ -549,29 +187,6 @@ if(OQS_ENABLE_SIG_sphincs_shake256_192s_simple_aarch64) set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) endif() -if(OQS_ENABLE_SIG_sphincs_shake256_256f_robust) - add_library(sphincs_shake256_256f_robust_clean OBJECT sig_sphincs_shake256_256f_robust.c pqclean_sphincs-shake-256f-robust_clean/address.c pqclean_sphincs-shake-256f-robust_clean/context_shake.c pqclean_sphincs-shake-256f-robust_clean/fors.c pqclean_sphincs-shake-256f-robust_clean/hash_shake.c pqclean_sphincs-shake-256f-robust_clean/merkle.c pqclean_sphincs-shake-256f-robust_clean/sign.c pqclean_sphincs-shake-256f-robust_clean/thash_shake_robust.c pqclean_sphincs-shake-256f-robust_clean/utils.c pqclean_sphincs-shake-256f-robust_clean/utilsx1.c pqclean_sphincs-shake-256f-robust_clean/wots.c pqclean_sphincs-shake-256f-robust_clean/wotsx1.c) - target_include_directories(sphincs_shake256_256f_robust_clean PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-shake-256f-robust_clean) - target_include_directories(sphincs_shake256_256f_robust_clean PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) - set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) -endif() - -if(OQS_ENABLE_SIG_sphincs_shake256_256f_robust_avx2) - add_library(sphincs_shake256_256f_robust_avx2 OBJECT pqclean_sphincs-shake-256f-robust_avx2/address.c pqclean_sphincs-shake-256f-robust_avx2/context_shake.c pqclean_sphincs-shake-256f-robust_avx2/fips202x4.c pqclean_sphincs-shake-256f-robust_avx2/fors.c pqclean_sphincs-shake-256f-robust_avx2/hash_shake.c pqclean_sphincs-shake-256f-robust_avx2/hash_shakex4.c pqclean_sphincs-shake-256f-robust_avx2/merkle.c pqclean_sphincs-shake-256f-robust_avx2/sign.c pqclean_sphincs-shake-256f-robust_avx2/thash_shake_robust.c pqclean_sphincs-shake-256f-robust_avx2/thash_shake_robustx4.c pqclean_sphincs-shake-256f-robust_avx2/utils.c pqclean_sphincs-shake-256f-robust_avx2/utilsx4.c pqclean_sphincs-shake-256f-robust_avx2/wots.c) - target_include_directories(sphincs_shake256_256f_robust_avx2 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-shake-256f-robust_avx2) - target_include_directories(sphincs_shake256_256f_robust_avx2 PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) - target_compile_options(sphincs_shake256_256f_robust_avx2 PRIVATE -mavx2) - set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) -endif() - -if(OQS_ENABLE_SIG_sphincs_shake256_256f_robust_aarch64) - add_library(sphincs_shake256_256f_robust_aarch64 OBJECT pqclean_sphincs-shake-256f-robust_aarch64/address.c pqclean_sphincs-shake-256f-robust_aarch64/context_shake.c pqclean_sphincs-shake-256f-robust_aarch64/f1600x2.s pqclean_sphincs-shake-256f-robust_aarch64/f1600x2_const.c pqclean_sphincs-shake-256f-robust_aarch64/fips202x2.c pqclean_sphincs-shake-256f-robust_aarch64/fors.c pqclean_sphincs-shake-256f-robust_aarch64/hash_shake.c pqclean_sphincs-shake-256f-robust_aarch64/hash_shakex2.c pqclean_sphincs-shake-256f-robust_aarch64/merkle.c pqclean_sphincs-shake-256f-robust_aarch64/sign.c pqclean_sphincs-shake-256f-robust_aarch64/thash_shake_robustx2.c pqclean_sphincs-shake-256f-robust_aarch64/utils.c pqclean_sphincs-shake-256f-robust_aarch64/utilsx2.c pqclean_sphincs-shake-256f-robust_aarch64/wots.c) - target_include_directories(sphincs_shake256_256f_robust_aarch64 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-shake-256f-robust_aarch64) - target_include_directories(sphincs_shake256_256f_robust_aarch64 PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) - target_compile_options(sphincs_shake256_256f_robust_aarch64 PRIVATE -march=armv8-a+crypto+sha3) - set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) -endif() - if(OQS_ENABLE_SIG_sphincs_shake256_256f_simple) add_library(sphincs_shake256_256f_simple_clean OBJECT sig_sphincs_shake256_256f_simple.c pqclean_sphincs-shake-256f-simple_clean/address.c pqclean_sphincs-shake-256f-simple_clean/context_shake.c pqclean_sphincs-shake-256f-simple_clean/fors.c pqclean_sphincs-shake-256f-simple_clean/hash_shake.c pqclean_sphincs-shake-256f-simple_clean/merkle.c pqclean_sphincs-shake-256f-simple_clean/sign.c pqclean_sphincs-shake-256f-simple_clean/thash_shake_simple.c pqclean_sphincs-shake-256f-simple_clean/utils.c pqclean_sphincs-shake-256f-simple_clean/utilsx1.c pqclean_sphincs-shake-256f-simple_clean/wots.c pqclean_sphincs-shake-256f-simple_clean/wotsx1.c) target_include_directories(sphincs_shake256_256f_simple_clean PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-shake-256f-simple_clean) @@ -595,29 +210,6 @@ if(OQS_ENABLE_SIG_sphincs_shake256_256f_simple_aarch64) set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) endif() -if(OQS_ENABLE_SIG_sphincs_shake256_256s_robust) - add_library(sphincs_shake256_256s_robust_clean OBJECT sig_sphincs_shake256_256s_robust.c pqclean_sphincs-shake-256s-robust_clean/address.c pqclean_sphincs-shake-256s-robust_clean/context_shake.c pqclean_sphincs-shake-256s-robust_clean/fors.c pqclean_sphincs-shake-256s-robust_clean/hash_shake.c pqclean_sphincs-shake-256s-robust_clean/merkle.c pqclean_sphincs-shake-256s-robust_clean/sign.c pqclean_sphincs-shake-256s-robust_clean/thash_shake_robust.c pqclean_sphincs-shake-256s-robust_clean/utils.c pqclean_sphincs-shake-256s-robust_clean/utilsx1.c pqclean_sphincs-shake-256s-robust_clean/wots.c pqclean_sphincs-shake-256s-robust_clean/wotsx1.c) - target_include_directories(sphincs_shake256_256s_robust_clean PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-shake-256s-robust_clean) - target_include_directories(sphincs_shake256_256s_robust_clean PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) - set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) -endif() - -if(OQS_ENABLE_SIG_sphincs_shake256_256s_robust_avx2) - add_library(sphincs_shake256_256s_robust_avx2 OBJECT pqclean_sphincs-shake-256s-robust_avx2/address.c pqclean_sphincs-shake-256s-robust_avx2/context_shake.c pqclean_sphincs-shake-256s-robust_avx2/fips202x4.c pqclean_sphincs-shake-256s-robust_avx2/fors.c pqclean_sphincs-shake-256s-robust_avx2/hash_shake.c pqclean_sphincs-shake-256s-robust_avx2/hash_shakex4.c pqclean_sphincs-shake-256s-robust_avx2/merkle.c pqclean_sphincs-shake-256s-robust_avx2/sign.c pqclean_sphincs-shake-256s-robust_avx2/thash_shake_robust.c pqclean_sphincs-shake-256s-robust_avx2/thash_shake_robustx4.c pqclean_sphincs-shake-256s-robust_avx2/utils.c pqclean_sphincs-shake-256s-robust_avx2/utilsx4.c pqclean_sphincs-shake-256s-robust_avx2/wots.c) - target_include_directories(sphincs_shake256_256s_robust_avx2 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-shake-256s-robust_avx2) - target_include_directories(sphincs_shake256_256s_robust_avx2 PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) - target_compile_options(sphincs_shake256_256s_robust_avx2 PRIVATE -mavx2) - set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) -endif() - -if(OQS_ENABLE_SIG_sphincs_shake256_256s_robust_aarch64) - add_library(sphincs_shake256_256s_robust_aarch64 OBJECT pqclean_sphincs-shake-256s-robust_aarch64/address.c pqclean_sphincs-shake-256s-robust_aarch64/context_shake.c pqclean_sphincs-shake-256s-robust_aarch64/f1600x2.s pqclean_sphincs-shake-256s-robust_aarch64/f1600x2_const.c pqclean_sphincs-shake-256s-robust_aarch64/fips202x2.c pqclean_sphincs-shake-256s-robust_aarch64/fors.c pqclean_sphincs-shake-256s-robust_aarch64/hash_shake.c pqclean_sphincs-shake-256s-robust_aarch64/hash_shakex2.c pqclean_sphincs-shake-256s-robust_aarch64/merkle.c pqclean_sphincs-shake-256s-robust_aarch64/sign.c pqclean_sphincs-shake-256s-robust_aarch64/thash_shake_robustx2.c pqclean_sphincs-shake-256s-robust_aarch64/utils.c pqclean_sphincs-shake-256s-robust_aarch64/utilsx2.c pqclean_sphincs-shake-256s-robust_aarch64/wots.c) - target_include_directories(sphincs_shake256_256s_robust_aarch64 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-shake-256s-robust_aarch64) - target_include_directories(sphincs_shake256_256s_robust_aarch64 PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) - target_compile_options(sphincs_shake256_256s_robust_aarch64 PRIVATE -march=armv8-a+crypto+sha3) - set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) -endif() - if(OQS_ENABLE_SIG_sphincs_shake256_256s_simple) add_library(sphincs_shake256_256s_simple_clean OBJECT sig_sphincs_shake256_256s_simple.c pqclean_sphincs-shake-256s-simple_clean/address.c pqclean_sphincs-shake-256s-simple_clean/context_shake.c pqclean_sphincs-shake-256s-simple_clean/fors.c pqclean_sphincs-shake-256s-simple_clean/hash_shake.c pqclean_sphincs-shake-256s-simple_clean/merkle.c pqclean_sphincs-shake-256s-simple_clean/sign.c pqclean_sphincs-shake-256s-simple_clean/thash_shake_simple.c pqclean_sphincs-shake-256s-simple_clean/utils.c pqclean_sphincs-shake-256s-simple_clean/utilsx1.c pqclean_sphincs-shake-256s-simple_clean/wots.c pqclean_sphincs-shake-256s-simple_clean/wotsx1.c) target_include_directories(sphincs_shake256_256s_simple_clean PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-shake-256s-simple_clean) diff --git a/src/sig/sphincs/sig_sphincs.h b/src/sig/sphincs/sig_sphincs.h index 15c0790305..e7c5c58a6b 100644 --- a/src/sig/sphincs/sig_sphincs.h +++ b/src/sig/sphincs/sig_sphincs.h @@ -5,149 +5,6 @@ #include -#ifdef OQS_ENABLE_SIG_sphincs_haraka_128f_robust -#define OQS_SIG_sphincs_haraka_128f_robust_length_public_key 32 -#define OQS_SIG_sphincs_haraka_128f_robust_length_secret_key 64 -#define OQS_SIG_sphincs_haraka_128f_robust_length_signature 17088 - -OQS_SIG *OQS_SIG_sphincs_haraka_128f_robust_new(void); -OQS_API OQS_STATUS OQS_SIG_sphincs_haraka_128f_robust_keypair(uint8_t *public_key, uint8_t *secret_key); -OQS_API OQS_STATUS OQS_SIG_sphincs_haraka_128f_robust_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, const uint8_t *secret_key); -OQS_API OQS_STATUS OQS_SIG_sphincs_haraka_128f_robust_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key); -#endif - -#ifdef OQS_ENABLE_SIG_sphincs_haraka_128f_simple -#define OQS_SIG_sphincs_haraka_128f_simple_length_public_key 32 -#define OQS_SIG_sphincs_haraka_128f_simple_length_secret_key 64 -#define OQS_SIG_sphincs_haraka_128f_simple_length_signature 17088 - -OQS_SIG *OQS_SIG_sphincs_haraka_128f_simple_new(void); -OQS_API OQS_STATUS OQS_SIG_sphincs_haraka_128f_simple_keypair(uint8_t *public_key, uint8_t *secret_key); -OQS_API OQS_STATUS OQS_SIG_sphincs_haraka_128f_simple_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, const uint8_t *secret_key); -OQS_API OQS_STATUS OQS_SIG_sphincs_haraka_128f_simple_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key); -#endif - -#ifdef OQS_ENABLE_SIG_sphincs_haraka_128s_robust -#define OQS_SIG_sphincs_haraka_128s_robust_length_public_key 32 -#define OQS_SIG_sphincs_haraka_128s_robust_length_secret_key 64 -#define OQS_SIG_sphincs_haraka_128s_robust_length_signature 7856 - -OQS_SIG *OQS_SIG_sphincs_haraka_128s_robust_new(void); -OQS_API OQS_STATUS OQS_SIG_sphincs_haraka_128s_robust_keypair(uint8_t *public_key, uint8_t *secret_key); -OQS_API OQS_STATUS OQS_SIG_sphincs_haraka_128s_robust_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, const uint8_t *secret_key); -OQS_API OQS_STATUS OQS_SIG_sphincs_haraka_128s_robust_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key); -#endif - -#ifdef OQS_ENABLE_SIG_sphincs_haraka_128s_simple -#define OQS_SIG_sphincs_haraka_128s_simple_length_public_key 32 -#define OQS_SIG_sphincs_haraka_128s_simple_length_secret_key 64 -#define OQS_SIG_sphincs_haraka_128s_simple_length_signature 7856 - -OQS_SIG *OQS_SIG_sphincs_haraka_128s_simple_new(void); -OQS_API OQS_STATUS OQS_SIG_sphincs_haraka_128s_simple_keypair(uint8_t *public_key, uint8_t *secret_key); -OQS_API OQS_STATUS OQS_SIG_sphincs_haraka_128s_simple_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, const uint8_t *secret_key); -OQS_API OQS_STATUS OQS_SIG_sphincs_haraka_128s_simple_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key); -#endif - -#ifdef OQS_ENABLE_SIG_sphincs_haraka_192f_robust -#define OQS_SIG_sphincs_haraka_192f_robust_length_public_key 48 -#define OQS_SIG_sphincs_haraka_192f_robust_length_secret_key 96 -#define OQS_SIG_sphincs_haraka_192f_robust_length_signature 35664 - -OQS_SIG *OQS_SIG_sphincs_haraka_192f_robust_new(void); -OQS_API OQS_STATUS OQS_SIG_sphincs_haraka_192f_robust_keypair(uint8_t *public_key, uint8_t *secret_key); -OQS_API OQS_STATUS OQS_SIG_sphincs_haraka_192f_robust_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, const uint8_t *secret_key); -OQS_API OQS_STATUS OQS_SIG_sphincs_haraka_192f_robust_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key); -#endif - -#ifdef OQS_ENABLE_SIG_sphincs_haraka_192f_simple -#define OQS_SIG_sphincs_haraka_192f_simple_length_public_key 48 -#define OQS_SIG_sphincs_haraka_192f_simple_length_secret_key 96 -#define OQS_SIG_sphincs_haraka_192f_simple_length_signature 35664 - -OQS_SIG *OQS_SIG_sphincs_haraka_192f_simple_new(void); -OQS_API OQS_STATUS OQS_SIG_sphincs_haraka_192f_simple_keypair(uint8_t *public_key, uint8_t *secret_key); -OQS_API OQS_STATUS OQS_SIG_sphincs_haraka_192f_simple_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, const uint8_t *secret_key); -OQS_API OQS_STATUS OQS_SIG_sphincs_haraka_192f_simple_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key); -#endif - -#ifdef OQS_ENABLE_SIG_sphincs_haraka_192s_robust -#define OQS_SIG_sphincs_haraka_192s_robust_length_public_key 48 -#define OQS_SIG_sphincs_haraka_192s_robust_length_secret_key 96 -#define OQS_SIG_sphincs_haraka_192s_robust_length_signature 16224 - -OQS_SIG *OQS_SIG_sphincs_haraka_192s_robust_new(void); -OQS_API OQS_STATUS OQS_SIG_sphincs_haraka_192s_robust_keypair(uint8_t *public_key, uint8_t *secret_key); -OQS_API OQS_STATUS OQS_SIG_sphincs_haraka_192s_robust_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, const uint8_t *secret_key); -OQS_API OQS_STATUS OQS_SIG_sphincs_haraka_192s_robust_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key); -#endif - -#ifdef OQS_ENABLE_SIG_sphincs_haraka_192s_simple -#define OQS_SIG_sphincs_haraka_192s_simple_length_public_key 48 -#define OQS_SIG_sphincs_haraka_192s_simple_length_secret_key 96 -#define OQS_SIG_sphincs_haraka_192s_simple_length_signature 16224 - -OQS_SIG *OQS_SIG_sphincs_haraka_192s_simple_new(void); -OQS_API OQS_STATUS OQS_SIG_sphincs_haraka_192s_simple_keypair(uint8_t *public_key, uint8_t *secret_key); -OQS_API OQS_STATUS OQS_SIG_sphincs_haraka_192s_simple_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, const uint8_t *secret_key); -OQS_API OQS_STATUS OQS_SIG_sphincs_haraka_192s_simple_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key); -#endif - -#ifdef OQS_ENABLE_SIG_sphincs_haraka_256f_robust -#define OQS_SIG_sphincs_haraka_256f_robust_length_public_key 64 -#define OQS_SIG_sphincs_haraka_256f_robust_length_secret_key 128 -#define OQS_SIG_sphincs_haraka_256f_robust_length_signature 49856 - -OQS_SIG *OQS_SIG_sphincs_haraka_256f_robust_new(void); -OQS_API OQS_STATUS OQS_SIG_sphincs_haraka_256f_robust_keypair(uint8_t *public_key, uint8_t *secret_key); -OQS_API OQS_STATUS OQS_SIG_sphincs_haraka_256f_robust_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, const uint8_t *secret_key); -OQS_API OQS_STATUS OQS_SIG_sphincs_haraka_256f_robust_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key); -#endif - -#ifdef OQS_ENABLE_SIG_sphincs_haraka_256f_simple -#define OQS_SIG_sphincs_haraka_256f_simple_length_public_key 64 -#define OQS_SIG_sphincs_haraka_256f_simple_length_secret_key 128 -#define OQS_SIG_sphincs_haraka_256f_simple_length_signature 49856 - -OQS_SIG *OQS_SIG_sphincs_haraka_256f_simple_new(void); -OQS_API OQS_STATUS OQS_SIG_sphincs_haraka_256f_simple_keypair(uint8_t *public_key, uint8_t *secret_key); -OQS_API OQS_STATUS OQS_SIG_sphincs_haraka_256f_simple_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, const uint8_t *secret_key); -OQS_API OQS_STATUS OQS_SIG_sphincs_haraka_256f_simple_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key); -#endif - -#ifdef OQS_ENABLE_SIG_sphincs_haraka_256s_robust -#define OQS_SIG_sphincs_haraka_256s_robust_length_public_key 64 -#define OQS_SIG_sphincs_haraka_256s_robust_length_secret_key 128 -#define OQS_SIG_sphincs_haraka_256s_robust_length_signature 29792 - -OQS_SIG *OQS_SIG_sphincs_haraka_256s_robust_new(void); -OQS_API OQS_STATUS OQS_SIG_sphincs_haraka_256s_robust_keypair(uint8_t *public_key, uint8_t *secret_key); -OQS_API OQS_STATUS OQS_SIG_sphincs_haraka_256s_robust_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, const uint8_t *secret_key); -OQS_API OQS_STATUS OQS_SIG_sphincs_haraka_256s_robust_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key); -#endif - -#ifdef OQS_ENABLE_SIG_sphincs_haraka_256s_simple -#define OQS_SIG_sphincs_haraka_256s_simple_length_public_key 64 -#define OQS_SIG_sphincs_haraka_256s_simple_length_secret_key 128 -#define OQS_SIG_sphincs_haraka_256s_simple_length_signature 29792 - -OQS_SIG *OQS_SIG_sphincs_haraka_256s_simple_new(void); -OQS_API OQS_STATUS OQS_SIG_sphincs_haraka_256s_simple_keypair(uint8_t *public_key, uint8_t *secret_key); -OQS_API OQS_STATUS OQS_SIG_sphincs_haraka_256s_simple_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, const uint8_t *secret_key); -OQS_API OQS_STATUS OQS_SIG_sphincs_haraka_256s_simple_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key); -#endif - -#ifdef OQS_ENABLE_SIG_sphincs_sha256_128f_robust -#define OQS_SIG_sphincs_sha256_128f_robust_length_public_key 32 -#define OQS_SIG_sphincs_sha256_128f_robust_length_secret_key 64 -#define OQS_SIG_sphincs_sha256_128f_robust_length_signature 17088 - -OQS_SIG *OQS_SIG_sphincs_sha256_128f_robust_new(void); -OQS_API OQS_STATUS OQS_SIG_sphincs_sha256_128f_robust_keypair(uint8_t *public_key, uint8_t *secret_key); -OQS_API OQS_STATUS OQS_SIG_sphincs_sha256_128f_robust_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, const uint8_t *secret_key); -OQS_API OQS_STATUS OQS_SIG_sphincs_sha256_128f_robust_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key); -#endif - #ifdef OQS_ENABLE_SIG_sphincs_sha256_128f_simple #define OQS_SIG_sphincs_sha256_128f_simple_length_public_key 32 #define OQS_SIG_sphincs_sha256_128f_simple_length_secret_key 64 @@ -159,17 +16,6 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_sha256_128f_simple_sign(uint8_t *signature, s OQS_API OQS_STATUS OQS_SIG_sphincs_sha256_128f_simple_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key); #endif -#ifdef OQS_ENABLE_SIG_sphincs_sha256_128s_robust -#define OQS_SIG_sphincs_sha256_128s_robust_length_public_key 32 -#define OQS_SIG_sphincs_sha256_128s_robust_length_secret_key 64 -#define OQS_SIG_sphincs_sha256_128s_robust_length_signature 7856 - -OQS_SIG *OQS_SIG_sphincs_sha256_128s_robust_new(void); -OQS_API OQS_STATUS OQS_SIG_sphincs_sha256_128s_robust_keypair(uint8_t *public_key, uint8_t *secret_key); -OQS_API OQS_STATUS OQS_SIG_sphincs_sha256_128s_robust_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, const uint8_t *secret_key); -OQS_API OQS_STATUS OQS_SIG_sphincs_sha256_128s_robust_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key); -#endif - #ifdef OQS_ENABLE_SIG_sphincs_sha256_128s_simple #define OQS_SIG_sphincs_sha256_128s_simple_length_public_key 32 #define OQS_SIG_sphincs_sha256_128s_simple_length_secret_key 64 @@ -181,17 +27,6 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_sha256_128s_simple_sign(uint8_t *signature, s OQS_API OQS_STATUS OQS_SIG_sphincs_sha256_128s_simple_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key); #endif -#ifdef OQS_ENABLE_SIG_sphincs_sha256_192f_robust -#define OQS_SIG_sphincs_sha256_192f_robust_length_public_key 48 -#define OQS_SIG_sphincs_sha256_192f_robust_length_secret_key 96 -#define OQS_SIG_sphincs_sha256_192f_robust_length_signature 35664 - -OQS_SIG *OQS_SIG_sphincs_sha256_192f_robust_new(void); -OQS_API OQS_STATUS OQS_SIG_sphincs_sha256_192f_robust_keypair(uint8_t *public_key, uint8_t *secret_key); -OQS_API OQS_STATUS OQS_SIG_sphincs_sha256_192f_robust_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, const uint8_t *secret_key); -OQS_API OQS_STATUS OQS_SIG_sphincs_sha256_192f_robust_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key); -#endif - #ifdef OQS_ENABLE_SIG_sphincs_sha256_192f_simple #define OQS_SIG_sphincs_sha256_192f_simple_length_public_key 48 #define OQS_SIG_sphincs_sha256_192f_simple_length_secret_key 96 @@ -203,17 +38,6 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_sha256_192f_simple_sign(uint8_t *signature, s OQS_API OQS_STATUS OQS_SIG_sphincs_sha256_192f_simple_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key); #endif -#ifdef OQS_ENABLE_SIG_sphincs_sha256_192s_robust -#define OQS_SIG_sphincs_sha256_192s_robust_length_public_key 48 -#define OQS_SIG_sphincs_sha256_192s_robust_length_secret_key 96 -#define OQS_SIG_sphincs_sha256_192s_robust_length_signature 16224 - -OQS_SIG *OQS_SIG_sphincs_sha256_192s_robust_new(void); -OQS_API OQS_STATUS OQS_SIG_sphincs_sha256_192s_robust_keypair(uint8_t *public_key, uint8_t *secret_key); -OQS_API OQS_STATUS OQS_SIG_sphincs_sha256_192s_robust_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, const uint8_t *secret_key); -OQS_API OQS_STATUS OQS_SIG_sphincs_sha256_192s_robust_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key); -#endif - #ifdef OQS_ENABLE_SIG_sphincs_sha256_192s_simple #define OQS_SIG_sphincs_sha256_192s_simple_length_public_key 48 #define OQS_SIG_sphincs_sha256_192s_simple_length_secret_key 96 @@ -225,17 +49,6 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_sha256_192s_simple_sign(uint8_t *signature, s OQS_API OQS_STATUS OQS_SIG_sphincs_sha256_192s_simple_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key); #endif -#ifdef OQS_ENABLE_SIG_sphincs_sha256_256f_robust -#define OQS_SIG_sphincs_sha256_256f_robust_length_public_key 64 -#define OQS_SIG_sphincs_sha256_256f_robust_length_secret_key 128 -#define OQS_SIG_sphincs_sha256_256f_robust_length_signature 49856 - -OQS_SIG *OQS_SIG_sphincs_sha256_256f_robust_new(void); -OQS_API OQS_STATUS OQS_SIG_sphincs_sha256_256f_robust_keypair(uint8_t *public_key, uint8_t *secret_key); -OQS_API OQS_STATUS OQS_SIG_sphincs_sha256_256f_robust_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, const uint8_t *secret_key); -OQS_API OQS_STATUS OQS_SIG_sphincs_sha256_256f_robust_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key); -#endif - #ifdef OQS_ENABLE_SIG_sphincs_sha256_256f_simple #define OQS_SIG_sphincs_sha256_256f_simple_length_public_key 64 #define OQS_SIG_sphincs_sha256_256f_simple_length_secret_key 128 @@ -247,17 +60,6 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_sha256_256f_simple_sign(uint8_t *signature, s OQS_API OQS_STATUS OQS_SIG_sphincs_sha256_256f_simple_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key); #endif -#ifdef OQS_ENABLE_SIG_sphincs_sha256_256s_robust -#define OQS_SIG_sphincs_sha256_256s_robust_length_public_key 64 -#define OQS_SIG_sphincs_sha256_256s_robust_length_secret_key 128 -#define OQS_SIG_sphincs_sha256_256s_robust_length_signature 29792 - -OQS_SIG *OQS_SIG_sphincs_sha256_256s_robust_new(void); -OQS_API OQS_STATUS OQS_SIG_sphincs_sha256_256s_robust_keypair(uint8_t *public_key, uint8_t *secret_key); -OQS_API OQS_STATUS OQS_SIG_sphincs_sha256_256s_robust_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, const uint8_t *secret_key); -OQS_API OQS_STATUS OQS_SIG_sphincs_sha256_256s_robust_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key); -#endif - #ifdef OQS_ENABLE_SIG_sphincs_sha256_256s_simple #define OQS_SIG_sphincs_sha256_256s_simple_length_public_key 64 #define OQS_SIG_sphincs_sha256_256s_simple_length_secret_key 128 @@ -269,17 +71,6 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_sha256_256s_simple_sign(uint8_t *signature, s OQS_API OQS_STATUS OQS_SIG_sphincs_sha256_256s_simple_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key); #endif -#ifdef OQS_ENABLE_SIG_sphincs_shake256_128f_robust -#define OQS_SIG_sphincs_shake256_128f_robust_length_public_key 32 -#define OQS_SIG_sphincs_shake256_128f_robust_length_secret_key 64 -#define OQS_SIG_sphincs_shake256_128f_robust_length_signature 17088 - -OQS_SIG *OQS_SIG_sphincs_shake256_128f_robust_new(void); -OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_128f_robust_keypair(uint8_t *public_key, uint8_t *secret_key); -OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_128f_robust_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, const uint8_t *secret_key); -OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_128f_robust_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key); -#endif - #ifdef OQS_ENABLE_SIG_sphincs_shake256_128f_simple #define OQS_SIG_sphincs_shake256_128f_simple_length_public_key 32 #define OQS_SIG_sphincs_shake256_128f_simple_length_secret_key 64 @@ -291,17 +82,6 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_128f_simple_sign(uint8_t *signature, OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_128f_simple_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key); #endif -#ifdef OQS_ENABLE_SIG_sphincs_shake256_128s_robust -#define OQS_SIG_sphincs_shake256_128s_robust_length_public_key 32 -#define OQS_SIG_sphincs_shake256_128s_robust_length_secret_key 64 -#define OQS_SIG_sphincs_shake256_128s_robust_length_signature 7856 - -OQS_SIG *OQS_SIG_sphincs_shake256_128s_robust_new(void); -OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_128s_robust_keypair(uint8_t *public_key, uint8_t *secret_key); -OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_128s_robust_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, const uint8_t *secret_key); -OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_128s_robust_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key); -#endif - #ifdef OQS_ENABLE_SIG_sphincs_shake256_128s_simple #define OQS_SIG_sphincs_shake256_128s_simple_length_public_key 32 #define OQS_SIG_sphincs_shake256_128s_simple_length_secret_key 64 @@ -313,17 +93,6 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_128s_simple_sign(uint8_t *signature, OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_128s_simple_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key); #endif -#ifdef OQS_ENABLE_SIG_sphincs_shake256_192f_robust -#define OQS_SIG_sphincs_shake256_192f_robust_length_public_key 48 -#define OQS_SIG_sphincs_shake256_192f_robust_length_secret_key 96 -#define OQS_SIG_sphincs_shake256_192f_robust_length_signature 35664 - -OQS_SIG *OQS_SIG_sphincs_shake256_192f_robust_new(void); -OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_192f_robust_keypair(uint8_t *public_key, uint8_t *secret_key); -OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_192f_robust_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, const uint8_t *secret_key); -OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_192f_robust_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key); -#endif - #ifdef OQS_ENABLE_SIG_sphincs_shake256_192f_simple #define OQS_SIG_sphincs_shake256_192f_simple_length_public_key 48 #define OQS_SIG_sphincs_shake256_192f_simple_length_secret_key 96 @@ -335,17 +104,6 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_192f_simple_sign(uint8_t *signature, OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_192f_simple_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key); #endif -#ifdef OQS_ENABLE_SIG_sphincs_shake256_192s_robust -#define OQS_SIG_sphincs_shake256_192s_robust_length_public_key 48 -#define OQS_SIG_sphincs_shake256_192s_robust_length_secret_key 96 -#define OQS_SIG_sphincs_shake256_192s_robust_length_signature 16224 - -OQS_SIG *OQS_SIG_sphincs_shake256_192s_robust_new(void); -OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_192s_robust_keypair(uint8_t *public_key, uint8_t *secret_key); -OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_192s_robust_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, const uint8_t *secret_key); -OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_192s_robust_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key); -#endif - #ifdef OQS_ENABLE_SIG_sphincs_shake256_192s_simple #define OQS_SIG_sphincs_shake256_192s_simple_length_public_key 48 #define OQS_SIG_sphincs_shake256_192s_simple_length_secret_key 96 @@ -357,17 +115,6 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_192s_simple_sign(uint8_t *signature, OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_192s_simple_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key); #endif -#ifdef OQS_ENABLE_SIG_sphincs_shake256_256f_robust -#define OQS_SIG_sphincs_shake256_256f_robust_length_public_key 64 -#define OQS_SIG_sphincs_shake256_256f_robust_length_secret_key 128 -#define OQS_SIG_sphincs_shake256_256f_robust_length_signature 49856 - -OQS_SIG *OQS_SIG_sphincs_shake256_256f_robust_new(void); -OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_256f_robust_keypair(uint8_t *public_key, uint8_t *secret_key); -OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_256f_robust_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, const uint8_t *secret_key); -OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_256f_robust_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key); -#endif - #ifdef OQS_ENABLE_SIG_sphincs_shake256_256f_simple #define OQS_SIG_sphincs_shake256_256f_simple_length_public_key 64 #define OQS_SIG_sphincs_shake256_256f_simple_length_secret_key 128 @@ -379,17 +126,6 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_256f_simple_sign(uint8_t *signature, OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_256f_simple_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key); #endif -#ifdef OQS_ENABLE_SIG_sphincs_shake256_256s_robust -#define OQS_SIG_sphincs_shake256_256s_robust_length_public_key 64 -#define OQS_SIG_sphincs_shake256_256s_robust_length_secret_key 128 -#define OQS_SIG_sphincs_shake256_256s_robust_length_signature 29792 - -OQS_SIG *OQS_SIG_sphincs_shake256_256s_robust_new(void); -OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_256s_robust_keypair(uint8_t *public_key, uint8_t *secret_key); -OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_256s_robust_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, const uint8_t *secret_key); -OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_256s_robust_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key); -#endif - #ifdef OQS_ENABLE_SIG_sphincs_shake256_256s_simple #define OQS_SIG_sphincs_shake256_256s_simple_length_public_key 64 #define OQS_SIG_sphincs_shake256_256s_simple_length_secret_key 128 diff --git a/tests/kat_sig.c b/tests/kat_sig.c index 27738a28c6..6ab9a15007 100644 --- a/tests/kat_sig.c +++ b/tests/kat_sig.c @@ -150,136 +150,6 @@ OQS_STATUS combine_message_signature(uint8_t **signed_msg, size_t *signed_msg_le (*signed_msg)[42 + msg_len] = 0x2A; memcpy(*signed_msg + 42 + msg_len + 1, falc_sig, signature_len - 41); return OQS_SUCCESS; - } else if (0 == strcmp(sig->method_name, "SPHINCS+-Haraka-128f-robust")) { - // signed_msg = signature || msg - *signed_msg_len = signature_len + msg_len; - *signed_msg = malloc(*signed_msg_len); - if (*signed_msg == NULL) { - return OQS_ERROR; - } - memcpy(*signed_msg, signature, signature_len); - memcpy(*signed_msg + signature_len, msg, msg_len); - return OQS_SUCCESS; - } else if (0 == strcmp(sig->method_name, "SPHINCS+-Haraka-128f-simple")) { - // signed_msg = signature || msg - *signed_msg_len = signature_len + msg_len; - *signed_msg = malloc(*signed_msg_len); - if (*signed_msg == NULL) { - return OQS_ERROR; - } - memcpy(*signed_msg, signature, signature_len); - memcpy(*signed_msg + signature_len, msg, msg_len); - return OQS_SUCCESS; - } else if (0 == strcmp(sig->method_name, "SPHINCS+-Haraka-128s-robust")) { - // signed_msg = signature || msg - *signed_msg_len = signature_len + msg_len; - *signed_msg = malloc(*signed_msg_len); - if (*signed_msg == NULL) { - return OQS_ERROR; - } - memcpy(*signed_msg, signature, signature_len); - memcpy(*signed_msg + signature_len, msg, msg_len); - return OQS_SUCCESS; - } else if (0 == strcmp(sig->method_name, "SPHINCS+-Haraka-128s-simple")) { - // signed_msg = signature || msg - *signed_msg_len = signature_len + msg_len; - *signed_msg = malloc(*signed_msg_len); - if (*signed_msg == NULL) { - return OQS_ERROR; - } - memcpy(*signed_msg, signature, signature_len); - memcpy(*signed_msg + signature_len, msg, msg_len); - return OQS_SUCCESS; - } else if (0 == strcmp(sig->method_name, "SPHINCS+-Haraka-192f-robust")) { - // signed_msg = signature || msg - *signed_msg_len = signature_len + msg_len; - *signed_msg = malloc(*signed_msg_len); - if (*signed_msg == NULL) { - return OQS_ERROR; - } - memcpy(*signed_msg, signature, signature_len); - memcpy(*signed_msg + signature_len, msg, msg_len); - return OQS_SUCCESS; - } else if (0 == strcmp(sig->method_name, "SPHINCS+-Haraka-192f-simple")) { - // signed_msg = signature || msg - *signed_msg_len = signature_len + msg_len; - *signed_msg = malloc(*signed_msg_len); - if (*signed_msg == NULL) { - return OQS_ERROR; - } - memcpy(*signed_msg, signature, signature_len); - memcpy(*signed_msg + signature_len, msg, msg_len); - return OQS_SUCCESS; - } else if (0 == strcmp(sig->method_name, "SPHINCS+-Haraka-192s-robust")) { - // signed_msg = signature || msg - *signed_msg_len = signature_len + msg_len; - *signed_msg = malloc(*signed_msg_len); - if (*signed_msg == NULL) { - return OQS_ERROR; - } - memcpy(*signed_msg, signature, signature_len); - memcpy(*signed_msg + signature_len, msg, msg_len); - return OQS_SUCCESS; - } else if (0 == strcmp(sig->method_name, "SPHINCS+-Haraka-192s-simple")) { - // signed_msg = signature || msg - *signed_msg_len = signature_len + msg_len; - *signed_msg = malloc(*signed_msg_len); - if (*signed_msg == NULL) { - return OQS_ERROR; - } - memcpy(*signed_msg, signature, signature_len); - memcpy(*signed_msg + signature_len, msg, msg_len); - return OQS_SUCCESS; - } else if (0 == strcmp(sig->method_name, "SPHINCS+-Haraka-256f-robust")) { - // signed_msg = signature || msg - *signed_msg_len = signature_len + msg_len; - *signed_msg = malloc(*signed_msg_len); - if (*signed_msg == NULL) { - return OQS_ERROR; - } - memcpy(*signed_msg, signature, signature_len); - memcpy(*signed_msg + signature_len, msg, msg_len); - return OQS_SUCCESS; - } else if (0 == strcmp(sig->method_name, "SPHINCS+-Haraka-256f-simple")) { - // signed_msg = signature || msg - *signed_msg_len = signature_len + msg_len; - *signed_msg = malloc(*signed_msg_len); - if (*signed_msg == NULL) { - return OQS_ERROR; - } - memcpy(*signed_msg, signature, signature_len); - memcpy(*signed_msg + signature_len, msg, msg_len); - return OQS_SUCCESS; - } else if (0 == strcmp(sig->method_name, "SPHINCS+-Haraka-256s-robust")) { - // signed_msg = signature || msg - *signed_msg_len = signature_len + msg_len; - *signed_msg = malloc(*signed_msg_len); - if (*signed_msg == NULL) { - return OQS_ERROR; - } - memcpy(*signed_msg, signature, signature_len); - memcpy(*signed_msg + signature_len, msg, msg_len); - return OQS_SUCCESS; - } else if (0 == strcmp(sig->method_name, "SPHINCS+-Haraka-256s-simple")) { - // signed_msg = signature || msg - *signed_msg_len = signature_len + msg_len; - *signed_msg = malloc(*signed_msg_len); - if (*signed_msg == NULL) { - return OQS_ERROR; - } - memcpy(*signed_msg, signature, signature_len); - memcpy(*signed_msg + signature_len, msg, msg_len); - return OQS_SUCCESS; - } else if (0 == strcmp(sig->method_name, "SPHINCS+-SHA256-128f-robust")) { - // signed_msg = signature || msg - *signed_msg_len = signature_len + msg_len; - *signed_msg = malloc(*signed_msg_len); - if (*signed_msg == NULL) { - return OQS_ERROR; - } - memcpy(*signed_msg, signature, signature_len); - memcpy(*signed_msg + signature_len, msg, msg_len); - return OQS_SUCCESS; } else if (0 == strcmp(sig->method_name, "SPHINCS+-SHA256-128f-simple")) { // signed_msg = signature || msg *signed_msg_len = signature_len + msg_len; @@ -290,16 +160,6 @@ OQS_STATUS combine_message_signature(uint8_t **signed_msg, size_t *signed_msg_le memcpy(*signed_msg, signature, signature_len); memcpy(*signed_msg + signature_len, msg, msg_len); return OQS_SUCCESS; - } else if (0 == strcmp(sig->method_name, "SPHINCS+-SHA256-128s-robust")) { - // signed_msg = signature || msg - *signed_msg_len = signature_len + msg_len; - *signed_msg = malloc(*signed_msg_len); - if (*signed_msg == NULL) { - return OQS_ERROR; - } - memcpy(*signed_msg, signature, signature_len); - memcpy(*signed_msg + signature_len, msg, msg_len); - return OQS_SUCCESS; } else if (0 == strcmp(sig->method_name, "SPHINCS+-SHA256-128s-simple")) { // signed_msg = signature || msg *signed_msg_len = signature_len + msg_len; @@ -310,16 +170,6 @@ OQS_STATUS combine_message_signature(uint8_t **signed_msg, size_t *signed_msg_le memcpy(*signed_msg, signature, signature_len); memcpy(*signed_msg + signature_len, msg, msg_len); return OQS_SUCCESS; - } else if (0 == strcmp(sig->method_name, "SPHINCS+-SHA256-192f-robust")) { - // signed_msg = signature || msg - *signed_msg_len = signature_len + msg_len; - *signed_msg = malloc(*signed_msg_len); - if (*signed_msg == NULL) { - return OQS_ERROR; - } - memcpy(*signed_msg, signature, signature_len); - memcpy(*signed_msg + signature_len, msg, msg_len); - return OQS_SUCCESS; } else if (0 == strcmp(sig->method_name, "SPHINCS+-SHA256-192f-simple")) { // signed_msg = signature || msg *signed_msg_len = signature_len + msg_len; @@ -330,16 +180,6 @@ OQS_STATUS combine_message_signature(uint8_t **signed_msg, size_t *signed_msg_le memcpy(*signed_msg, signature, signature_len); memcpy(*signed_msg + signature_len, msg, msg_len); return OQS_SUCCESS; - } else if (0 == strcmp(sig->method_name, "SPHINCS+-SHA256-192s-robust")) { - // signed_msg = signature || msg - *signed_msg_len = signature_len + msg_len; - *signed_msg = malloc(*signed_msg_len); - if (*signed_msg == NULL) { - return OQS_ERROR; - } - memcpy(*signed_msg, signature, signature_len); - memcpy(*signed_msg + signature_len, msg, msg_len); - return OQS_SUCCESS; } else if (0 == strcmp(sig->method_name, "SPHINCS+-SHA256-192s-simple")) { // signed_msg = signature || msg *signed_msg_len = signature_len + msg_len; @@ -350,16 +190,6 @@ OQS_STATUS combine_message_signature(uint8_t **signed_msg, size_t *signed_msg_le memcpy(*signed_msg, signature, signature_len); memcpy(*signed_msg + signature_len, msg, msg_len); return OQS_SUCCESS; - } else if (0 == strcmp(sig->method_name, "SPHINCS+-SHA256-256f-robust")) { - // signed_msg = signature || msg - *signed_msg_len = signature_len + msg_len; - *signed_msg = malloc(*signed_msg_len); - if (*signed_msg == NULL) { - return OQS_ERROR; - } - memcpy(*signed_msg, signature, signature_len); - memcpy(*signed_msg + signature_len, msg, msg_len); - return OQS_SUCCESS; } else if (0 == strcmp(sig->method_name, "SPHINCS+-SHA256-256f-simple")) { // signed_msg = signature || msg *signed_msg_len = signature_len + msg_len; @@ -370,16 +200,6 @@ OQS_STATUS combine_message_signature(uint8_t **signed_msg, size_t *signed_msg_le memcpy(*signed_msg, signature, signature_len); memcpy(*signed_msg + signature_len, msg, msg_len); return OQS_SUCCESS; - } else if (0 == strcmp(sig->method_name, "SPHINCS+-SHA256-256s-robust")) { - // signed_msg = signature || msg - *signed_msg_len = signature_len + msg_len; - *signed_msg = malloc(*signed_msg_len); - if (*signed_msg == NULL) { - return OQS_ERROR; - } - memcpy(*signed_msg, signature, signature_len); - memcpy(*signed_msg + signature_len, msg, msg_len); - return OQS_SUCCESS; } else if (0 == strcmp(sig->method_name, "SPHINCS+-SHA256-256s-simple")) { // signed_msg = signature || msg *signed_msg_len = signature_len + msg_len; @@ -390,16 +210,6 @@ OQS_STATUS combine_message_signature(uint8_t **signed_msg, size_t *signed_msg_le memcpy(*signed_msg, signature, signature_len); memcpy(*signed_msg + signature_len, msg, msg_len); return OQS_SUCCESS; - } else if (0 == strcmp(sig->method_name, "SPHINCS+-SHAKE256-128f-robust")) { - // signed_msg = signature || msg - *signed_msg_len = signature_len + msg_len; - *signed_msg = malloc(*signed_msg_len); - if (*signed_msg == NULL) { - return OQS_ERROR; - } - memcpy(*signed_msg, signature, signature_len); - memcpy(*signed_msg + signature_len, msg, msg_len); - return OQS_SUCCESS; } else if (0 == strcmp(sig->method_name, "SPHINCS+-SHAKE256-128f-simple")) { // signed_msg = signature || msg *signed_msg_len = signature_len + msg_len; @@ -410,16 +220,6 @@ OQS_STATUS combine_message_signature(uint8_t **signed_msg, size_t *signed_msg_le memcpy(*signed_msg, signature, signature_len); memcpy(*signed_msg + signature_len, msg, msg_len); return OQS_SUCCESS; - } else if (0 == strcmp(sig->method_name, "SPHINCS+-SHAKE256-128s-robust")) { - // signed_msg = signature || msg - *signed_msg_len = signature_len + msg_len; - *signed_msg = malloc(*signed_msg_len); - if (*signed_msg == NULL) { - return OQS_ERROR; - } - memcpy(*signed_msg, signature, signature_len); - memcpy(*signed_msg + signature_len, msg, msg_len); - return OQS_SUCCESS; } else if (0 == strcmp(sig->method_name, "SPHINCS+-SHAKE256-128s-simple")) { // signed_msg = signature || msg *signed_msg_len = signature_len + msg_len; @@ -430,16 +230,6 @@ OQS_STATUS combine_message_signature(uint8_t **signed_msg, size_t *signed_msg_le memcpy(*signed_msg, signature, signature_len); memcpy(*signed_msg + signature_len, msg, msg_len); return OQS_SUCCESS; - } else if (0 == strcmp(sig->method_name, "SPHINCS+-SHAKE256-192f-robust")) { - // signed_msg = signature || msg - *signed_msg_len = signature_len + msg_len; - *signed_msg = malloc(*signed_msg_len); - if (*signed_msg == NULL) { - return OQS_ERROR; - } - memcpy(*signed_msg, signature, signature_len); - memcpy(*signed_msg + signature_len, msg, msg_len); - return OQS_SUCCESS; } else if (0 == strcmp(sig->method_name, "SPHINCS+-SHAKE256-192f-simple")) { // signed_msg = signature || msg *signed_msg_len = signature_len + msg_len; @@ -450,16 +240,6 @@ OQS_STATUS combine_message_signature(uint8_t **signed_msg, size_t *signed_msg_le memcpy(*signed_msg, signature, signature_len); memcpy(*signed_msg + signature_len, msg, msg_len); return OQS_SUCCESS; - } else if (0 == strcmp(sig->method_name, "SPHINCS+-SHAKE256-192s-robust")) { - // signed_msg = signature || msg - *signed_msg_len = signature_len + msg_len; - *signed_msg = malloc(*signed_msg_len); - if (*signed_msg == NULL) { - return OQS_ERROR; - } - memcpy(*signed_msg, signature, signature_len); - memcpy(*signed_msg + signature_len, msg, msg_len); - return OQS_SUCCESS; } else if (0 == strcmp(sig->method_name, "SPHINCS+-SHAKE256-192s-simple")) { // signed_msg = signature || msg *signed_msg_len = signature_len + msg_len; @@ -470,16 +250,6 @@ OQS_STATUS combine_message_signature(uint8_t **signed_msg, size_t *signed_msg_le memcpy(*signed_msg, signature, signature_len); memcpy(*signed_msg + signature_len, msg, msg_len); return OQS_SUCCESS; - } else if (0 == strcmp(sig->method_name, "SPHINCS+-SHAKE256-256f-robust")) { - // signed_msg = signature || msg - *signed_msg_len = signature_len + msg_len; - *signed_msg = malloc(*signed_msg_len); - if (*signed_msg == NULL) { - return OQS_ERROR; - } - memcpy(*signed_msg, signature, signature_len); - memcpy(*signed_msg + signature_len, msg, msg_len); - return OQS_SUCCESS; } else if (0 == strcmp(sig->method_name, "SPHINCS+-SHAKE256-256f-simple")) { // signed_msg = signature || msg *signed_msg_len = signature_len + msg_len; @@ -490,16 +260,6 @@ OQS_STATUS combine_message_signature(uint8_t **signed_msg, size_t *signed_msg_le memcpy(*signed_msg, signature, signature_len); memcpy(*signed_msg + signature_len, msg, msg_len); return OQS_SUCCESS; - } else if (0 == strcmp(sig->method_name, "SPHINCS+-SHAKE256-256s-robust")) { - // signed_msg = signature || msg - *signed_msg_len = signature_len + msg_len; - *signed_msg = malloc(*signed_msg_len); - if (*signed_msg == NULL) { - return OQS_ERROR; - } - memcpy(*signed_msg, signature, signature_len); - memcpy(*signed_msg + signature_len, msg, msg_len); - return OQS_SUCCESS; } else if (0 == strcmp(sig->method_name, "SPHINCS+-SHAKE256-256s-simple")) { // signed_msg = signature || msg *signed_msg_len = signature_len + msg_len; From 26d8faa1de52c59c73dfc8628c631bfa84d6a3db Mon Sep 17 00:00:00 2001 From: Douglas Stebila Date: Sun, 19 Mar 2023 14:08:30 -0400 Subject: [PATCH 07/10] Delete obsolete files --- .../LICENSE | 116 --- .../address.c | 91 -- .../address.h | 52 - .../api.h | 77 -- .../context.h | 22 - .../context_haraka.c | 11 - .../fors.c | 202 ---- .../fors.h | 32 - .../haraka.c | 702 -------------- .../haraka.h | 42 - .../haraka_offsets.h | 21 - .../harakax4.h | 36 - .../hash.h | 28 - .../hash_haraka.c | 81 -- .../hash_harakax4.c | 35 - .../hashx4.h | 17 - .../merkle.c | 64 -- .../merkle.h | 21 - .../nistapi.h | 87 -- .../params.h | 56 -- .../sign.c | 286 ------ .../thash.h | 13 - .../thash_haraka_robust.c | 45 - .../thash_haraka_robustx4.c | 93 -- .../thashx4.h | 20 - .../utils.c | 148 --- .../utils.h | 58 -- .../utilsx4.c | 138 --- .../utilsx4.h | 30 - .../wots.c | 269 ------ .../wots.h | 25 - .../wotsx4.h | 41 - .../LICENSE | 116 --- .../address.c | 91 -- .../address.h | 52 - .../api.h | 77 -- .../context.h | 24 - .../context_haraka.c | 11 - .../fors.c | 156 --- .../fors.h | 32 - .../haraka.c | 913 ------------------ .../haraka.h | 42 - .../haraka_offsets.h | 21 - .../hash.h | 28 - .../hash_haraka.c | 81 -- .../merkle.c | 59 -- .../merkle.h | 21 - .../nistapi.h | 87 -- .../params.h | 56 -- .../sign.c | 286 ------ .../thash.h | 13 - .../thash_haraka_robust.c | 45 - .../utils.c | 148 --- .../utils.h | 58 -- .../utilsx1.c | 100 -- .../utilsx1.h | 27 - .../wots.c | 108 --- .../wots.h | 25 - .../wotsx1.c | 76 -- .../wotsx1.h | 39 - .../LICENSE | 116 --- .../address.c | 91 -- .../address.h | 52 - .../api.h | 77 -- .../context.h | 22 - .../context_haraka.c | 11 - .../fors.c | 202 ---- .../fors.h | 32 - .../haraka.c | 702 -------------- .../haraka.h | 42 - .../haraka_offsets.h | 21 - .../harakax4.h | 36 - .../hash.h | 28 - .../hash_haraka.c | 81 -- .../hash_harakax4.c | 35 - .../hashx4.h | 17 - .../merkle.c | 64 -- .../merkle.h | 21 - .../nistapi.h | 87 -- .../params.h | 56 -- .../sign.c | 286 ------ .../thash.h | 13 - .../thash_haraka_simple.c | 36 - .../thash_haraka_simplex4.c | 67 -- .../thashx4.h | 20 - .../utils.c | 148 --- .../utils.h | 58 -- .../utilsx4.c | 138 --- .../utilsx4.h | 30 - .../wots.c | 269 ------ .../wots.h | 25 - .../wotsx4.h | 41 - .../LICENSE | 116 --- .../address.c | 91 -- .../address.h | 52 - .../api.h | 77 -- .../context.h | 24 - .../context_haraka.c | 11 - .../fors.c | 156 --- .../fors.h | 32 - .../haraka.c | 913 ------------------ .../haraka.h | 42 - .../haraka_offsets.h | 21 - .../hash.h | 28 - .../hash_haraka.c | 81 -- .../merkle.c | 59 -- .../merkle.h | 21 - .../nistapi.h | 87 -- .../params.h | 56 -- .../sign.c | 286 ------ .../thash.h | 13 - .../thash_haraka_simple.c | 36 - .../utils.c | 148 --- .../utils.h | 58 -- .../utilsx1.c | 100 -- .../utilsx1.h | 27 - .../wots.c | 108 --- .../wots.h | 25 - .../wotsx1.c | 76 -- .../wotsx1.h | 39 - .../LICENSE | 116 --- .../address.c | 95 -- .../address.h | 52 - .../api.h | 77 -- .../context.h | 22 - .../context_haraka.c | 11 - .../fors.c | 202 ---- .../fors.h | 32 - .../haraka.c | 702 -------------- .../haraka.h | 42 - .../haraka_offsets.h | 21 - .../harakax4.h | 36 - .../hash.h | 28 - .../hash_haraka.c | 81 -- .../hash_harakax4.c | 35 - .../hashx4.h | 17 - .../merkle.c | 64 -- .../merkle.h | 21 - .../nistapi.h | 87 -- .../params.h | 56 -- .../sign.c | 286 ------ .../thash.h | 13 - .../thash_haraka_robust.c | 45 - .../thash_haraka_robustx4.c | 93 -- .../thashx4.h | 20 - .../utils.c | 148 --- .../utils.h | 58 -- .../utilsx4.c | 138 --- .../utilsx4.h | 30 - .../wots.c | 269 ------ .../wots.h | 25 - .../wotsx4.h | 41 - .../LICENSE | 116 --- .../address.c | 95 -- .../address.h | 52 - .../api.h | 77 -- .../context.h | 24 - .../context_haraka.c | 11 - .../fors.c | 156 --- .../fors.h | 32 - .../haraka.c | 913 ------------------ .../haraka.h | 42 - .../haraka_offsets.h | 21 - .../hash.h | 28 - .../hash_haraka.c | 81 -- .../merkle.c | 59 -- .../merkle.h | 21 - .../nistapi.h | 87 -- .../params.h | 56 -- .../sign.c | 286 ------ .../thash.h | 13 - .../thash_haraka_robust.c | 45 - .../utils.c | 148 --- .../utils.h | 58 -- .../utilsx1.c | 100 -- .../utilsx1.h | 27 - .../wots.c | 108 --- .../wots.h | 25 - .../wotsx1.c | 76 -- .../wotsx1.h | 39 - .../LICENSE | 116 --- .../address.c | 95 -- .../address.h | 52 - .../api.h | 77 -- .../context.h | 22 - .../context_haraka.c | 11 - .../fors.c | 202 ---- .../fors.h | 32 - .../haraka.c | 702 -------------- .../haraka.h | 42 - .../haraka_offsets.h | 21 - .../harakax4.h | 36 - .../hash.h | 28 - .../hash_haraka.c | 81 -- .../hash_harakax4.c | 35 - .../hashx4.h | 17 - .../merkle.c | 64 -- .../merkle.h | 21 - .../nistapi.h | 87 -- .../params.h | 56 -- .../sign.c | 286 ------ .../thash.h | 13 - .../thash_haraka_simple.c | 36 - .../thash_haraka_simplex4.c | 67 -- .../thashx4.h | 20 - .../utils.c | 148 --- .../utils.h | 58 -- .../utilsx4.c | 138 --- .../utilsx4.h | 30 - .../wots.c | 269 ------ .../wots.h | 25 - .../wotsx4.h | 41 - .../LICENSE | 116 --- .../address.c | 95 -- .../address.h | 52 - .../api.h | 77 -- .../context.h | 24 - .../context_haraka.c | 11 - .../fors.c | 156 --- .../fors.h | 32 - .../haraka.c | 913 ------------------ .../haraka.h | 42 - .../haraka_offsets.h | 21 - .../hash.h | 28 - .../hash_haraka.c | 81 -- .../merkle.c | 59 -- .../merkle.h | 21 - .../nistapi.h | 87 -- .../params.h | 56 -- .../sign.c | 286 ------ .../thash.h | 13 - .../thash_haraka_simple.c | 36 - .../utils.c | 148 --- .../utils.h | 58 -- .../utilsx1.c | 100 -- .../utilsx1.h | 27 - .../wots.c | 108 --- .../wots.h | 25 - .../wotsx1.c | 76 -- .../wotsx1.h | 39 - .../LICENSE | 116 --- .../address.c | 91 -- .../address.h | 52 - .../api.h | 77 -- .../context.h | 22 - .../context_haraka.c | 11 - .../fors.c | 202 ---- .../fors.h | 32 - .../haraka.c | 702 -------------- .../haraka.h | 42 - .../haraka_offsets.h | 21 - .../harakax4.h | 36 - .../hash.h | 28 - .../hash_haraka.c | 81 -- .../hash_harakax4.c | 35 - .../hashx4.h | 17 - .../merkle.c | 64 -- .../merkle.h | 21 - .../nistapi.h | 87 -- .../params.h | 56 -- .../sign.c | 286 ------ .../thash.h | 13 - .../thash_haraka_robust.c | 45 - .../thash_haraka_robustx4.c | 93 -- .../thashx4.h | 20 - .../utils.c | 148 --- .../utils.h | 58 -- .../utilsx4.c | 138 --- .../utilsx4.h | 30 - .../wots.c | 269 ------ .../wots.h | 25 - .../wotsx4.h | 41 - .../LICENSE | 116 --- .../address.c | 91 -- .../address.h | 52 - .../api.h | 77 -- .../context.h | 24 - .../context_haraka.c | 11 - .../fors.c | 156 --- .../fors.h | 32 - .../haraka.c | 913 ------------------ .../haraka.h | 42 - .../haraka_offsets.h | 21 - .../hash.h | 28 - .../hash_haraka.c | 81 -- .../merkle.c | 59 -- .../merkle.h | 21 - .../nistapi.h | 87 -- .../params.h | 56 -- .../sign.c | 286 ------ .../thash.h | 13 - .../thash_haraka_robust.c | 45 - .../utils.c | 148 --- .../utils.h | 58 -- .../utilsx1.c | 100 -- .../utilsx1.h | 27 - .../wots.c | 108 --- .../wots.h | 25 - .../wotsx1.c | 76 -- .../wotsx1.h | 39 - .../LICENSE | 116 --- .../address.c | 91 -- .../address.h | 52 - .../api.h | 77 -- .../context.h | 22 - .../context_haraka.c | 11 - .../fors.c | 202 ---- .../fors.h | 32 - .../haraka.c | 702 -------------- .../haraka.h | 42 - .../haraka_offsets.h | 21 - .../harakax4.h | 36 - .../hash.h | 28 - .../hash_haraka.c | 81 -- .../hash_harakax4.c | 35 - .../hashx4.h | 17 - .../merkle.c | 64 -- .../merkle.h | 21 - .../nistapi.h | 87 -- .../params.h | 56 -- .../sign.c | 286 ------ .../thash.h | 13 - .../thash_haraka_simple.c | 36 - .../thash_haraka_simplex4.c | 67 -- .../thashx4.h | 20 - .../utils.c | 148 --- .../utils.h | 58 -- .../utilsx4.c | 138 --- .../utilsx4.h | 30 - .../wots.c | 269 ------ .../wots.h | 25 - .../wotsx4.h | 41 - .../LICENSE | 116 --- .../address.c | 91 -- .../address.h | 52 - .../api.h | 77 -- .../context.h | 24 - .../context_haraka.c | 11 - .../fors.c | 156 --- .../fors.h | 32 - .../haraka.c | 913 ------------------ .../haraka.h | 42 - .../haraka_offsets.h | 21 - .../hash.h | 28 - .../hash_haraka.c | 81 -- .../merkle.c | 59 -- .../merkle.h | 21 - .../nistapi.h | 87 -- .../params.h | 56 -- .../sign.c | 286 ------ .../thash.h | 13 - .../thash_haraka_simple.c | 36 - .../utils.c | 148 --- .../utils.h | 58 -- .../utilsx1.c | 100 -- .../utilsx1.h | 27 - .../wots.c | 108 --- .../wots.h | 25 - .../wotsx1.c | 76 -- .../wotsx1.h | 39 - .../LICENSE | 116 --- .../address.c | 95 -- .../address.h | 52 - .../api.h | 77 -- .../context.h | 22 - .../context_haraka.c | 11 - .../fors.c | 202 ---- .../fors.h | 32 - .../haraka.c | 702 -------------- .../haraka.h | 42 - .../haraka_offsets.h | 21 - .../harakax4.h | 36 - .../hash.h | 28 - .../hash_haraka.c | 81 -- .../hash_harakax4.c | 35 - .../hashx4.h | 17 - .../merkle.c | 64 -- .../merkle.h | 21 - .../nistapi.h | 87 -- .../params.h | 56 -- .../sign.c | 286 ------ .../thash.h | 13 - .../thash_haraka_robust.c | 45 - .../thash_haraka_robustx4.c | 93 -- .../thashx4.h | 20 - .../utils.c | 148 --- .../utils.h | 58 -- .../utilsx4.c | 138 --- .../utilsx4.h | 30 - .../wots.c | 269 ------ .../wots.h | 25 - .../wotsx4.h | 41 - .../LICENSE | 116 --- .../address.c | 95 -- .../address.h | 52 - .../api.h | 77 -- .../context.h | 24 - .../context_haraka.c | 11 - .../fors.c | 156 --- .../fors.h | 32 - .../haraka.c | 913 ------------------ .../haraka.h | 42 - .../haraka_offsets.h | 21 - .../hash.h | 28 - .../hash_haraka.c | 81 -- .../merkle.c | 59 -- .../merkle.h | 21 - .../nistapi.h | 87 -- .../params.h | 56 -- .../sign.c | 286 ------ .../thash.h | 13 - .../thash_haraka_robust.c | 45 - .../utils.c | 148 --- .../utils.h | 58 -- .../utilsx1.c | 100 -- .../utilsx1.h | 27 - .../wots.c | 108 --- .../wots.h | 25 - .../wotsx1.c | 76 -- .../wotsx1.h | 39 - .../LICENSE | 116 --- .../address.c | 95 -- .../address.h | 52 - .../api.h | 77 -- .../context.h | 22 - .../context_haraka.c | 11 - .../fors.c | 202 ---- .../fors.h | 32 - .../haraka.c | 702 -------------- .../haraka.h | 42 - .../haraka_offsets.h | 21 - .../harakax4.h | 36 - .../hash.h | 28 - .../hash_haraka.c | 81 -- .../hash_harakax4.c | 35 - .../hashx4.h | 17 - .../merkle.c | 64 -- .../merkle.h | 21 - .../nistapi.h | 87 -- .../params.h | 56 -- .../sign.c | 286 ------ .../thash.h | 13 - .../thash_haraka_simple.c | 36 - .../thash_haraka_simplex4.c | 67 -- .../thashx4.h | 20 - .../utils.c | 148 --- .../utils.h | 58 -- .../utilsx4.c | 138 --- .../utilsx4.h | 30 - .../wots.c | 269 ------ .../wots.h | 25 - .../wotsx4.h | 41 - .../LICENSE | 116 --- .../address.c | 95 -- .../address.h | 52 - .../api.h | 77 -- .../context.h | 24 - .../context_haraka.c | 11 - .../fors.c | 156 --- .../fors.h | 32 - .../haraka.c | 913 ------------------ .../haraka.h | 42 - .../haraka_offsets.h | 21 - .../hash.h | 28 - .../hash_haraka.c | 81 -- .../merkle.c | 59 -- .../merkle.h | 21 - .../nistapi.h | 87 -- .../params.h | 56 -- .../sign.c | 286 ------ .../thash.h | 13 - .../thash_haraka_simple.c | 36 - .../utils.c | 148 --- .../utils.h | 58 -- .../utilsx1.c | 100 -- .../utilsx1.h | 27 - .../wots.c | 108 --- .../wots.h | 25 - .../wotsx1.c | 76 -- .../wotsx1.h | 39 - .../LICENSE | 116 --- .../address.c | 91 -- .../address.h | 52 - .../api.h | 77 -- .../context.h | 22 - .../context_haraka.c | 11 - .../fors.c | 202 ---- .../fors.h | 32 - .../haraka.c | 702 -------------- .../haraka.h | 42 - .../haraka_offsets.h | 21 - .../harakax4.h | 36 - .../hash.h | 28 - .../hash_haraka.c | 81 -- .../hash_harakax4.c | 35 - .../hashx4.h | 17 - .../merkle.c | 64 -- .../merkle.h | 21 - .../nistapi.h | 87 -- .../params.h | 56 -- .../sign.c | 286 ------ .../thash.h | 13 - .../thash_haraka_robust.c | 45 - .../thash_haraka_robustx4.c | 93 -- .../thashx4.h | 20 - .../utils.c | 148 --- .../utils.h | 58 -- .../utilsx4.c | 138 --- .../utilsx4.h | 30 - .../wots.c | 269 ------ .../wots.h | 25 - .../wotsx4.h | 41 - .../LICENSE | 116 --- .../address.c | 91 -- .../address.h | 52 - .../api.h | 77 -- .../context.h | 24 - .../context_haraka.c | 11 - .../fors.c | 156 --- .../fors.h | 32 - .../haraka.c | 913 ------------------ .../haraka.h | 42 - .../haraka_offsets.h | 21 - .../hash.h | 28 - .../hash_haraka.c | 81 -- .../merkle.c | 59 -- .../merkle.h | 21 - .../nistapi.h | 87 -- .../params.h | 56 -- .../sign.c | 286 ------ .../thash.h | 13 - .../thash_haraka_robust.c | 45 - .../utils.c | 148 --- .../utils.h | 58 -- .../utilsx1.c | 100 -- .../utilsx1.h | 27 - .../wots.c | 108 --- .../wots.h | 25 - .../wotsx1.c | 76 -- .../wotsx1.h | 39 - .../LICENSE | 116 --- .../address.c | 91 -- .../address.h | 52 - .../api.h | 77 -- .../context.h | 22 - .../context_haraka.c | 11 - .../fors.c | 202 ---- .../fors.h | 32 - .../haraka.c | 702 -------------- .../haraka.h | 42 - .../haraka_offsets.h | 21 - .../harakax4.h | 36 - .../hash.h | 28 - .../hash_haraka.c | 81 -- .../hash_harakax4.c | 35 - .../hashx4.h | 17 - .../merkle.c | 64 -- .../merkle.h | 21 - .../nistapi.h | 87 -- .../params.h | 56 -- .../sign.c | 286 ------ .../thash.h | 13 - .../thash_haraka_simple.c | 36 - .../thash_haraka_simplex4.c | 67 -- .../thashx4.h | 20 - .../utils.c | 148 --- .../utils.h | 58 -- .../utilsx4.c | 138 --- .../utilsx4.h | 30 - .../wots.c | 269 ------ .../wots.h | 25 - .../wotsx4.h | 41 - .../LICENSE | 116 --- .../address.c | 91 -- .../address.h | 52 - .../api.h | 77 -- .../context.h | 24 - .../context_haraka.c | 11 - .../fors.c | 156 --- .../fors.h | 32 - .../haraka.c | 913 ------------------ .../haraka.h | 42 - .../haraka_offsets.h | 21 - .../hash.h | 28 - .../hash_haraka.c | 81 -- .../merkle.c | 59 -- .../merkle.h | 21 - .../nistapi.h | 87 -- .../params.h | 56 -- .../sign.c | 286 ------ .../thash.h | 13 - .../thash_haraka_simple.c | 36 - .../utils.c | 148 --- .../utils.h | 58 -- .../utilsx1.c | 100 -- .../utilsx1.h | 27 - .../wots.c | 108 --- .../wots.h | 25 - .../wotsx1.c | 76 -- .../wotsx1.h | 39 - .../LICENSE | 116 --- .../address.c | 91 -- .../address.h | 52 - .../api.h | 77 -- .../context.h | 22 - .../context_haraka.c | 11 - .../fors.c | 202 ---- .../fors.h | 32 - .../haraka.c | 702 -------------- .../haraka.h | 42 - .../haraka_offsets.h | 21 - .../harakax4.h | 36 - .../hash.h | 28 - .../hash_haraka.c | 81 -- .../hash_harakax4.c | 35 - .../hashx4.h | 17 - .../merkle.c | 64 -- .../merkle.h | 21 - .../nistapi.h | 87 -- .../params.h | 56 -- .../sign.c | 286 ------ .../thash.h | 13 - .../thash_haraka_robust.c | 45 - .../thash_haraka_robustx4.c | 93 -- .../thashx4.h | 20 - .../utils.c | 148 --- .../utils.h | 58 -- .../utilsx4.c | 138 --- .../utilsx4.h | 30 - .../wots.c | 269 ------ .../wots.h | 25 - .../wotsx4.h | 41 - .../LICENSE | 116 --- .../address.c | 91 -- .../address.h | 52 - .../api.h | 77 -- .../context.h | 24 - .../context_haraka.c | 11 - .../fors.c | 156 --- .../fors.h | 32 - .../haraka.c | 913 ------------------ .../haraka.h | 42 - .../haraka_offsets.h | 21 - .../hash.h | 28 - .../hash_haraka.c | 81 -- .../merkle.c | 59 -- .../merkle.h | 21 - .../nistapi.h | 87 -- .../params.h | 56 -- .../sign.c | 286 ------ .../thash.h | 13 - .../thash_haraka_robust.c | 45 - .../utils.c | 148 --- .../utils.h | 58 -- .../utilsx1.c | 100 -- .../utilsx1.h | 27 - .../wots.c | 108 --- .../wots.h | 25 - .../wotsx1.c | 76 -- .../wotsx1.h | 39 - .../LICENSE | 116 --- .../address.c | 91 -- .../address.h | 52 - .../api.h | 77 -- .../context.h | 22 - .../context_haraka.c | 11 - .../fors.c | 202 ---- .../fors.h | 32 - .../haraka.c | 702 -------------- .../haraka.h | 42 - .../haraka_offsets.h | 21 - .../harakax4.h | 36 - .../hash.h | 28 - .../hash_haraka.c | 81 -- .../hash_harakax4.c | 35 - .../hashx4.h | 17 - .../merkle.c | 64 -- .../merkle.h | 21 - .../nistapi.h | 87 -- .../params.h | 56 -- .../sign.c | 286 ------ .../thash.h | 13 - .../thash_haraka_simple.c | 36 - .../thash_haraka_simplex4.c | 67 -- .../thashx4.h | 20 - .../utils.c | 148 --- .../utils.h | 58 -- .../utilsx4.c | 138 --- .../utilsx4.h | 30 - .../wots.c | 269 ------ .../wots.h | 25 - .../wotsx4.h | 41 - .../LICENSE | 116 --- .../address.c | 91 -- .../address.h | 52 - .../api.h | 77 -- .../context.h | 24 - .../context_haraka.c | 11 - .../fors.c | 156 --- .../fors.h | 32 - .../haraka.c | 913 ------------------ .../haraka.h | 42 - .../haraka_offsets.h | 21 - .../hash.h | 28 - .../hash_haraka.c | 81 -- .../merkle.c | 59 -- .../merkle.h | 21 - .../nistapi.h | 87 -- .../params.h | 56 -- .../sign.c | 286 ------ .../thash.h | 13 - .../thash_haraka_simple.c | 36 - .../utils.c | 148 --- .../utils.h | 58 -- .../utilsx1.c | 100 -- .../utilsx1.h | 27 - .../wots.c | 108 --- .../wots.h | 25 - .../wotsx1.c | 76 -- .../wotsx1.h | 39 - .../LICENSE | 116 --- .../address.c | 91 -- .../address.h | 52 - .../api.h | 77 -- .../context.h | 26 - .../context_sha2.c | 44 - .../fors.c | 226 ----- .../fors.h | 32 - .../hash.h | 37 - .../hash_sha2.c | 219 ----- .../hash_sha2x8.c | 75 -- .../hashx8.h | 20 - .../merkle.c | 65 -- .../merkle.h | 21 - .../nistapi.h | 87 -- .../params.h | 61 -- .../sha256avx.c | 357 ------- .../sha256avx.h | 44 - .../sha256x8.c | 185 ---- .../sha256x8.h | 64 -- .../sha2_offsets.h | 27 - .../sign.c | 286 ------ .../thash.h | 13 - .../thash_sha2_robust.c | 39 - .../thash_sha2_robustx8.c | 121 --- .../thashx8.h | 28 - .../utils.c | 148 --- .../utils.h | 58 -- .../utilsx8.c | 146 --- .../utilsx8.h | 29 - .../wots.c | 291 ------ .../wots.h | 25 - .../wotsx8.h | 42 - .../LICENSE | 116 --- .../address.c | 91 -- .../address.h | 52 - .../api.h | 77 -- .../context.h | 26 - .../context_sha2.c | 33 - .../fors.c | 156 --- .../fors.h | 32 - .../hash.h | 37 - .../hash_sha2.c | 219 ----- .../merkle.c | 59 -- .../merkle.h | 21 - .../nistapi.h | 87 -- .../params.h | 61 -- .../sha2_offsets.h | 27 - .../sign.c | 286 ------ .../thash.h | 13 - .../thash_sha2_robust.c | 39 - .../utils.c | 148 --- .../utils.h | 58 -- .../utilsx1.c | 100 -- .../utilsx1.h | 27 - .../wots.c | 108 --- .../wots.h | 25 - .../wotsx1.c | 76 -- .../wotsx1.h | 39 - .../LICENSE | 116 --- .../address.c | 95 -- .../address.h | 52 - .../api.h | 77 -- .../context.h | 26 - .../context_sha2.c | 44 - .../fors.c | 226 ----- .../fors.h | 32 - .../hash.h | 37 - .../hash_sha2.c | 219 ----- .../hash_sha2x8.c | 75 -- .../hashx8.h | 20 - .../merkle.c | 65 -- .../merkle.h | 21 - .../nistapi.h | 87 -- .../params.h | 61 -- .../sha256avx.c | 357 ------- .../sha256avx.h | 44 - .../sha256x8.c | 185 ---- .../sha256x8.h | 64 -- .../sha2_offsets.h | 27 - .../sign.c | 286 ------ .../thash.h | 13 - .../thash_sha2_robust.c | 39 - .../thash_sha2_robustx8.c | 121 --- .../thashx8.h | 28 - .../utils.c | 148 --- .../utils.h | 58 -- .../utilsx8.c | 146 --- .../utilsx8.h | 29 - .../wots.c | 291 ------ .../wots.h | 25 - .../wotsx8.h | 42 - .../LICENSE | 116 --- .../address.c | 95 -- .../address.h | 52 - .../api.h | 77 -- .../context.h | 26 - .../context_sha2.c | 33 - .../fors.c | 156 --- .../fors.h | 32 - .../hash.h | 37 - .../hash_sha2.c | 219 ----- .../merkle.c | 59 -- .../merkle.h | 21 - .../nistapi.h | 87 -- .../params.h | 61 -- .../sha2_offsets.h | 27 - .../sign.c | 286 ------ .../thash.h | 13 - .../thash_sha2_robust.c | 39 - .../utils.c | 148 --- .../utils.h | 58 -- .../utilsx1.c | 100 -- .../utilsx1.h | 27 - .../wots.c | 108 --- .../wots.h | 25 - .../wotsx1.c | 76 -- .../wotsx1.h | 39 - .../LICENSE | 116 --- .../address.c | 91 -- .../address.h | 52 - .../api.h | 77 -- .../context.h | 29 - .../context_sha2.c | 56 -- .../fors.c | 226 ----- .../fors.h | 32 - .../hash.h | 37 - .../hash_sha2.c | 219 ----- .../hash_sha2x8.c | 75 -- .../hashx8.h | 20 - .../merkle.c | 65 -- .../merkle.h | 21 - .../nistapi.h | 87 -- .../params.h | 61 -- .../sha256avx.c | 357 ------- .../sha256avx.h | 44 - .../sha256x8.c | 185 ---- .../sha256x8.h | 64 -- .../sha2_offsets.h | 27 - .../sha512x4.c | 446 --------- .../sha512x4.h | 58 -- .../sign.c | 286 ------ .../thash.h | 13 - .../thash_sha2_robust.c | 68 -- .../thash_sha2_robustx8.c | 268 ----- .../thashx8.h | 28 - .../utils.c | 148 --- .../utils.h | 58 -- .../utilsx8.c | 146 --- .../utilsx8.h | 29 - .../wots.c | 291 ------ .../wots.h | 25 - .../wotsx8.h | 42 - .../LICENSE | 116 --- .../address.c | 91 -- .../address.h | 52 - .../api.h | 77 -- .../context.h | 28 - .../context_sha2.c | 36 - .../fors.c | 156 --- .../fors.h | 32 - .../hash.h | 37 - .../hash_sha2.c | 219 ----- .../merkle.c | 59 -- .../merkle.h | 21 - .../nistapi.h | 87 -- .../params.h | 61 -- .../sha2_offsets.h | 27 - .../sign.c | 286 ------ .../thash.h | 13 - .../thash_sha2_robust.c | 68 -- .../utils.c | 148 --- .../utils.h | 58 -- .../utilsx1.c | 100 -- .../utilsx1.h | 27 - .../wots.c | 108 --- .../wots.h | 25 - .../wotsx1.c | 76 -- .../wotsx1.h | 39 - .../LICENSE | 116 --- .../address.c | 95 -- .../address.h | 52 - .../api.h | 77 -- .../context.h | 29 - .../context_sha2.c | 56 -- .../fors.c | 226 ----- .../fors.h | 32 - .../hash.h | 37 - .../hash_sha2.c | 219 ----- .../hash_sha2x8.c | 75 -- .../hashx8.h | 20 - .../merkle.c | 65 -- .../merkle.h | 21 - .../nistapi.h | 87 -- .../params.h | 61 -- .../sha256avx.c | 357 ------- .../sha256avx.h | 44 - .../sha256x8.c | 185 ---- .../sha256x8.h | 64 -- .../sha2_offsets.h | 27 - .../sha512x4.c | 446 --------- .../sha512x4.h | 58 -- .../sign.c | 286 ------ .../thash.h | 13 - .../thash_sha2_robust.c | 68 -- .../thash_sha2_robustx8.c | 268 ----- .../thashx8.h | 28 - .../utils.c | 148 --- .../utils.h | 58 -- .../utilsx8.c | 146 --- .../utilsx8.h | 29 - .../wots.c | 291 ------ .../wots.h | 25 - .../wotsx8.h | 42 - .../LICENSE | 116 --- .../address.c | 95 -- .../address.h | 52 - .../api.h | 77 -- .../context.h | 28 - .../context_sha2.c | 36 - .../fors.c | 156 --- .../fors.h | 32 - .../hash.h | 37 - .../hash_sha2.c | 219 ----- .../merkle.c | 59 -- .../merkle.h | 21 - .../nistapi.h | 87 -- .../params.h | 61 -- .../sha2_offsets.h | 27 - .../sign.c | 286 ------ .../thash.h | 13 - .../thash_sha2_robust.c | 68 -- .../utils.c | 148 --- .../utils.h | 58 -- .../utilsx1.c | 100 -- .../utilsx1.h | 27 - .../wots.c | 108 --- .../wots.h | 25 - .../wotsx1.c | 76 -- .../wotsx1.h | 39 - .../LICENSE | 116 --- .../address.c | 91 -- .../address.h | 52 - .../api.h | 77 -- .../context.h | 29 - .../context_sha2.c | 56 -- .../fors.c | 226 ----- .../fors.h | 32 - .../hash.h | 37 - .../hash_sha2.c | 219 ----- .../hash_sha2x8.c | 75 -- .../hashx8.h | 20 - .../merkle.c | 65 -- .../merkle.h | 21 - .../nistapi.h | 87 -- .../params.h | 61 -- .../sha256avx.c | 357 ------- .../sha256avx.h | 44 - .../sha256x8.c | 185 ---- .../sha256x8.h | 64 -- .../sha2_offsets.h | 27 - .../sha512x4.c | 446 --------- .../sha512x4.h | 58 -- .../sign.c | 286 ------ .../thash.h | 13 - .../thash_sha2_robust.c | 68 -- .../thash_sha2_robustx8.c | 268 ----- .../thashx8.h | 28 - .../utils.c | 148 --- .../utils.h | 58 -- .../utilsx8.c | 146 --- .../utilsx8.h | 29 - .../wots.c | 291 ------ .../wots.h | 25 - .../wotsx8.h | 42 - .../LICENSE | 116 --- .../address.c | 91 -- .../address.h | 52 - .../api.h | 77 -- .../context.h | 28 - .../context_sha2.c | 36 - .../fors.c | 156 --- .../fors.h | 32 - .../hash.h | 37 - .../hash_sha2.c | 219 ----- .../merkle.c | 59 -- .../merkle.h | 21 - .../nistapi.h | 87 -- .../params.h | 61 -- .../sha2_offsets.h | 27 - .../sign.c | 286 ------ .../thash.h | 13 - .../thash_sha2_robust.c | 68 -- .../utils.c | 148 --- .../utils.h | 58 -- .../utilsx1.c | 100 -- .../utilsx1.h | 27 - .../wots.c | 108 --- .../wots.h | 25 - .../wotsx1.c | 76 -- .../wotsx1.h | 39 - .../LICENSE | 116 --- .../address.c | 91 -- .../address.h | 52 - .../api.h | 77 -- .../context.h | 29 - .../context_sha2.c | 56 -- .../fors.c | 226 ----- .../fors.h | 32 - .../hash.h | 37 - .../hash_sha2.c | 219 ----- .../hash_sha2x8.c | 75 -- .../hashx8.h | 20 - .../merkle.c | 65 -- .../merkle.h | 21 - .../nistapi.h | 87 -- .../params.h | 61 -- .../sha256avx.c | 357 ------- .../sha256avx.h | 44 - .../sha256x8.c | 185 ---- .../sha256x8.h | 64 -- .../sha2_offsets.h | 27 - .../sha512x4.c | 446 --------- .../sha512x4.h | 58 -- .../sign.c | 286 ------ .../thash.h | 13 - .../thash_sha2_robust.c | 68 -- .../thash_sha2_robustx8.c | 268 ----- .../thashx8.h | 28 - .../utils.c | 148 --- .../utils.h | 58 -- .../utilsx8.c | 146 --- .../utilsx8.h | 29 - .../wots.c | 291 ------ .../wots.h | 25 - .../wotsx8.h | 42 - .../LICENSE | 116 --- .../address.c | 91 -- .../address.h | 52 - .../api.h | 77 -- .../context.h | 28 - .../context_sha2.c | 36 - .../fors.c | 156 --- .../fors.h | 32 - .../hash.h | 37 - .../hash_sha2.c | 219 ----- .../merkle.c | 59 -- .../merkle.h | 21 - .../nistapi.h | 87 -- .../params.h | 61 -- .../sha2_offsets.h | 27 - .../sign.c | 286 ------ .../thash.h | 13 - .../thash_sha2_robust.c | 68 -- .../utils.c | 148 --- .../utils.h | 58 -- .../utilsx1.c | 100 -- .../utilsx1.h | 27 - .../wots.c | 108 --- .../wots.h | 25 - .../wotsx1.c | 76 -- .../wotsx1.h | 39 - .../LICENSE | 116 --- .../address.c | 78 -- .../address.h | 50 - .../api.h | 81 -- .../fors.c | 240 ----- .../fors.h | 32 - .../hash.h | 31 - .../hash_sha256.c | 166 ---- .../hash_sha256x8.c | 61 -- .../hash_state.h | 33 - .../hashx8.h | 19 - .../params.h | 53 - .../sha256.c | 71 -- .../sha256.h | 21 - .../sha256avx.c | 296 ------ .../sha256avx.h | 103 -- .../sha256x8.c | 128 --- .../sha256x8.h | 44 - .../sign.c | 356 ------- .../thash.h | 28 - .../thash_sha256_robust.c | 78 -- .../thash_sha256_robustx8.c | 156 --- .../thashx8.h | 39 - .../utils.c | 199 ---- .../utils.h | 64 -- .../utilsx8.c | 172 ---- .../utilsx8.h | 46 - .../wots.c | 240 ----- .../wots.h | 41 - .../LICENSE | 116 --- .../address.c | 78 -- .../address.h | 50 - .../api.h | 81 -- .../fors.c | 161 --- .../fors.h | 32 - .../hash.h | 31 - .../hash_sha256.c | 162 ---- .../hash_state.h | 26 - .../params.h | 53 - .../sha256.c | 71 -- .../sha256.h | 21 - .../sign.c | 356 ------- .../thash.h | 28 - .../thash_sha256_robust.c | 82 -- .../utils.c | 199 ---- .../utils.h | 64 -- .../wots.c | 167 ---- .../wots.h | 41 - .../LICENSE | 116 --- .../address.c | 78 -- .../address.h | 50 - .../api.h | 81 -- .../fors.c | 240 ----- .../fors.h | 32 - .../hash.h | 31 - .../hash_sha256.c | 166 ---- .../hash_sha256x8.c | 61 -- .../hash_state.h | 33 - .../hashx8.h | 19 - .../params.h | 53 - .../sha256.c | 71 -- .../sha256.h | 21 - .../sha256avx.c | 296 ------ .../sha256avx.h | 103 -- .../sha256x8.c | 128 --- .../sha256x8.h | 44 - .../sign.c | 356 ------- .../thash.h | 28 - .../thash_sha256_simple.c | 75 -- .../thash_sha256_simplex8.c | 129 --- .../thashx8.h | 39 - .../utils.c | 199 ---- .../utils.h | 64 -- .../utilsx8.c | 172 ---- .../utilsx8.h | 46 - .../wots.c | 240 ----- .../wots.h | 41 - .../LICENSE | 116 --- .../address.c | 78 -- .../address.h | 50 - .../api.h | 81 -- .../fors.c | 161 --- .../fors.h | 32 - .../hash.h | 31 - .../hash_sha256.c | 162 ---- .../hash_state.h | 26 - .../params.h | 53 - .../sha256.c | 71 -- .../sha256.h | 21 - .../sign.c | 356 ------- .../thash.h | 28 - .../thash_sha256_simple.c | 75 -- .../utils.c | 199 ---- .../utils.h | 64 -- .../wots.c | 167 ---- .../wots.h | 41 - .../LICENSE | 116 --- .../address.c | 78 -- .../address.h | 50 - .../api.h | 81 -- .../fors.c | 240 ----- .../fors.h | 32 - .../hash.h | 31 - .../hash_sha256.c | 166 ---- .../hash_sha256x8.c | 61 -- .../hash_state.h | 33 - .../hashx8.h | 19 - .../params.h | 53 - .../sha256.c | 71 -- .../sha256.h | 21 - .../sha256avx.c | 296 ------ .../sha256avx.h | 103 -- .../sha256x8.c | 128 --- .../sha256x8.h | 44 - .../sign.c | 356 ------- .../thash.h | 28 - .../thash_sha256_robust.c | 78 -- .../thash_sha256_robustx8.c | 156 --- .../thashx8.h | 39 - .../utils.c | 199 ---- .../utils.h | 64 -- .../utilsx8.c | 172 ---- .../utilsx8.h | 46 - .../wots.c | 240 ----- .../wots.h | 41 - .../LICENSE | 116 --- .../address.c | 78 -- .../address.h | 50 - .../api.h | 81 -- .../fors.c | 161 --- .../fors.h | 32 - .../hash.h | 31 - .../hash_sha256.c | 162 ---- .../hash_state.h | 26 - .../params.h | 53 - .../sha256.c | 71 -- .../sha256.h | 21 - .../sign.c | 356 ------- .../thash.h | 28 - .../thash_sha256_robust.c | 82 -- .../utils.c | 199 ---- .../utils.h | 64 -- .../wots.c | 167 ---- .../wots.h | 41 - .../LICENSE | 116 --- .../address.c | 78 -- .../address.h | 50 - .../api.h | 81 -- .../fors.c | 240 ----- .../fors.h | 32 - .../hash.h | 31 - .../hash_sha256.c | 166 ---- .../hash_sha256x8.c | 61 -- .../hash_state.h | 33 - .../hashx8.h | 19 - .../params.h | 53 - .../sha256.c | 71 -- .../sha256.h | 21 - .../sha256avx.c | 296 ------ .../sha256avx.h | 103 -- .../sha256x8.c | 128 --- .../sha256x8.h | 44 - .../sign.c | 356 ------- .../thash.h | 28 - .../thash_sha256_simple.c | 75 -- .../thash_sha256_simplex8.c | 129 --- .../thashx8.h | 39 - .../utils.c | 199 ---- .../utils.h | 64 -- .../utilsx8.c | 172 ---- .../utilsx8.h | 46 - .../wots.c | 240 ----- .../wots.h | 41 - .../LICENSE | 116 --- .../address.c | 78 -- .../address.h | 50 - .../api.h | 81 -- .../fors.c | 161 --- .../fors.h | 32 - .../hash.h | 31 - .../hash_sha256.c | 162 ---- .../hash_state.h | 26 - .../params.h | 53 - .../sha256.c | 71 -- .../sha256.h | 21 - .../sign.c | 356 ------- .../thash.h | 28 - .../thash_sha256_simple.c | 75 -- .../utils.c | 199 ---- .../utils.h | 64 -- .../wots.c | 167 ---- .../wots.h | 41 - .../LICENSE | 116 --- .../address.c | 78 -- .../address.h | 50 - .../api.h | 81 -- .../fors.c | 240 ----- .../fors.h | 32 - .../hash.h | 31 - .../hash_sha256.c | 166 ---- .../hash_sha256x8.c | 61 -- .../hash_state.h | 33 - .../hashx8.h | 19 - .../params.h | 53 - .../sha256.c | 71 -- .../sha256.h | 21 - .../sha256avx.c | 296 ------ .../sha256avx.h | 103 -- .../sha256x8.c | 128 --- .../sha256x8.h | 44 - .../sign.c | 356 ------- .../thash.h | 28 - .../thash_sha256_robust.c | 78 -- .../thash_sha256_robustx8.c | 156 --- .../thashx8.h | 39 - .../utils.c | 199 ---- .../utils.h | 64 -- .../utilsx8.c | 172 ---- .../utilsx8.h | 46 - .../wots.c | 240 ----- .../wots.h | 41 - .../LICENSE | 116 --- .../address.c | 78 -- .../address.h | 50 - .../api.h | 81 -- .../fors.c | 161 --- .../fors.h | 32 - .../hash.h | 31 - .../hash_sha256.c | 162 ---- .../hash_state.h | 26 - .../params.h | 53 - .../sha256.c | 71 -- .../sha256.h | 21 - .../sign.c | 356 ------- .../thash.h | 28 - .../thash_sha256_robust.c | 82 -- .../utils.c | 199 ---- .../utils.h | 64 -- .../wots.c | 167 ---- .../wots.h | 41 - .../LICENSE | 116 --- .../address.c | 78 -- .../address.h | 50 - .../api.h | 81 -- .../fors.c | 240 ----- .../fors.h | 32 - .../hash.h | 31 - .../hash_sha256.c | 166 ---- .../hash_sha256x8.c | 61 -- .../hash_state.h | 33 - .../hashx8.h | 19 - .../params.h | 53 - .../sha256.c | 71 -- .../sha256.h | 21 - .../sha256avx.c | 296 ------ .../sha256avx.h | 103 -- .../sha256x8.c | 128 --- .../sha256x8.h | 44 - .../sign.c | 356 ------- .../thash.h | 28 - .../thash_sha256_simple.c | 75 -- .../thash_sha256_simplex8.c | 129 --- .../thashx8.h | 39 - .../utils.c | 199 ---- .../utils.h | 64 -- .../utilsx8.c | 172 ---- .../utilsx8.h | 46 - .../wots.c | 240 ----- .../wots.h | 41 - .../LICENSE | 116 --- .../address.c | 78 -- .../address.h | 50 - .../api.h | 81 -- .../fors.c | 161 --- .../fors.h | 32 - .../hash.h | 31 - .../hash_sha256.c | 162 ---- .../hash_state.h | 26 - .../params.h | 53 - .../sha256.c | 71 -- .../sha256.h | 21 - .../sign.c | 356 ------- .../thash.h | 28 - .../thash_sha256_simple.c | 75 -- .../utils.c | 199 ---- .../utils.h | 64 -- .../wots.c | 167 ---- .../wots.h | 41 - .../LICENSE | 116 --- .../address.c | 78 -- .../address.h | 50 - .../api.h | 81 -- .../fors.c | 240 ----- .../fors.h | 32 - .../hash.h | 31 - .../hash_sha256.c | 166 ---- .../hash_sha256x8.c | 61 -- .../hash_state.h | 33 - .../hashx8.h | 19 - .../params.h | 53 - .../sha256.c | 71 -- .../sha256.h | 21 - .../sha256avx.c | 296 ------ .../sha256avx.h | 103 -- .../sha256x8.c | 128 --- .../sha256x8.h | 44 - .../sign.c | 356 ------- .../thash.h | 28 - .../thash_sha256_robust.c | 78 -- .../thash_sha256_robustx8.c | 156 --- .../thashx8.h | 39 - .../utils.c | 199 ---- .../utils.h | 64 -- .../utilsx8.c | 172 ---- .../utilsx8.h | 46 - .../wots.c | 240 ----- .../wots.h | 41 - .../LICENSE | 116 --- .../address.c | 78 -- .../address.h | 50 - .../api.h | 81 -- .../fors.c | 161 --- .../fors.h | 32 - .../hash.h | 31 - .../hash_sha256.c | 162 ---- .../hash_state.h | 26 - .../params.h | 53 - .../sha256.c | 71 -- .../sha256.h | 21 - .../sign.c | 356 ------- .../thash.h | 28 - .../thash_sha256_robust.c | 82 -- .../utils.c | 199 ---- .../utils.h | 64 -- .../wots.c | 167 ---- .../wots.h | 41 - .../LICENSE | 116 --- .../address.c | 78 -- .../address.h | 50 - .../api.h | 81 -- .../fors.c | 240 ----- .../fors.h | 32 - .../hash.h | 31 - .../hash_sha256.c | 166 ---- .../hash_sha256x8.c | 61 -- .../hash_state.h | 33 - .../hashx8.h | 19 - .../params.h | 53 - .../sha256.c | 71 -- .../sha256.h | 21 - .../sha256avx.c | 296 ------ .../sha256avx.h | 103 -- .../sha256x8.c | 128 --- .../sha256x8.h | 44 - .../sign.c | 356 ------- .../thash.h | 28 - .../thash_sha256_simple.c | 75 -- .../thash_sha256_simplex8.c | 129 --- .../thashx8.h | 39 - .../utils.c | 199 ---- .../utils.h | 64 -- .../utilsx8.c | 172 ---- .../utilsx8.h | 46 - .../wots.c | 240 ----- .../wots.h | 41 - .../LICENSE | 116 --- .../address.c | 78 -- .../address.h | 50 - .../api.h | 81 -- .../fors.c | 161 --- .../fors.h | 32 - .../hash.h | 31 - .../hash_sha256.c | 162 ---- .../hash_state.h | 26 - .../params.h | 53 - .../sha256.c | 71 -- .../sha256.h | 21 - .../sign.c | 356 ------- .../thash.h | 28 - .../thash_sha256_simple.c | 75 -- .../utils.c | 199 ---- .../utils.h | 64 -- .../wots.c | 167 ---- .../wots.h | 41 - .../LICENSE | 116 --- .../address.c | 78 -- .../address.h | 50 - .../api.h | 81 -- .../fors.c | 240 ----- .../fors.h | 32 - .../hash.h | 31 - .../hash_sha256.c | 166 ---- .../hash_sha256x8.c | 61 -- .../hash_state.h | 33 - .../hashx8.h | 19 - .../params.h | 53 - .../sha256.c | 71 -- .../sha256.h | 21 - .../sha256avx.c | 296 ------ .../sha256avx.h | 103 -- .../sha256x8.c | 128 --- .../sha256x8.h | 44 - .../sign.c | 356 ------- .../thash.h | 28 - .../thash_sha256_robust.c | 78 -- .../thash_sha256_robustx8.c | 156 --- .../thashx8.h | 39 - .../utils.c | 199 ---- .../utils.h | 64 -- .../utilsx8.c | 172 ---- .../utilsx8.h | 46 - .../wots.c | 240 ----- .../wots.h | 41 - .../LICENSE | 116 --- .../address.c | 78 -- .../address.h | 50 - .../api.h | 81 -- .../fors.c | 161 --- .../fors.h | 32 - .../hash.h | 31 - .../hash_sha256.c | 162 ---- .../hash_state.h | 26 - .../params.h | 53 - .../sha256.c | 71 -- .../sha256.h | 21 - .../sign.c | 356 ------- .../thash.h | 28 - .../thash_sha256_robust.c | 82 -- .../utils.c | 199 ---- .../utils.h | 64 -- .../wots.c | 167 ---- .../wots.h | 41 - .../LICENSE | 116 --- .../address.c | 78 -- .../address.h | 50 - .../api.h | 81 -- .../fors.c | 240 ----- .../fors.h | 32 - .../hash.h | 31 - .../hash_sha256.c | 166 ---- .../hash_sha256x8.c | 61 -- .../hash_state.h | 33 - .../hashx8.h | 19 - .../params.h | 53 - .../sha256.c | 71 -- .../sha256.h | 21 - .../sha256avx.c | 296 ------ .../sha256avx.h | 103 -- .../sha256x8.c | 128 --- .../sha256x8.h | 44 - .../sign.c | 356 ------- .../thash.h | 28 - .../thash_sha256_simple.c | 75 -- .../thash_sha256_simplex8.c | 129 --- .../thashx8.h | 39 - .../utils.c | 199 ---- .../utils.h | 64 -- .../utilsx8.c | 172 ---- .../utilsx8.h | 46 - .../wots.c | 240 ----- .../wots.h | 41 - .../LICENSE | 116 --- .../address.c | 78 -- .../address.h | 50 - .../api.h | 81 -- .../fors.c | 161 --- .../fors.h | 32 - .../hash.h | 31 - .../hash_sha256.c | 162 ---- .../hash_state.h | 26 - .../params.h | 53 - .../sha256.c | 71 -- .../sha256.h | 21 - .../sign.c | 356 ------- .../thash.h | 28 - .../thash_sha256_simple.c | 75 -- .../utils.c | 199 ---- .../utils.h | 64 -- .../wots.c | 167 ---- .../wots.h | 41 - .../LICENSE | 116 --- .../address.c | 78 -- .../address.h | 50 - .../api.h | 81 -- .../fors.c | 240 ----- .../fors.h | 32 - .../hash.h | 31 - .../hash_sha256.c | 166 ---- .../hash_sha256x8.c | 61 -- .../hash_state.h | 33 - .../hashx8.h | 19 - .../params.h | 53 - .../sha256.c | 71 -- .../sha256.h | 21 - .../sha256avx.c | 296 ------ .../sha256avx.h | 103 -- .../sha256x8.c | 128 --- .../sha256x8.h | 44 - .../sign.c | 356 ------- .../thash.h | 28 - .../thash_sha256_robust.c | 78 -- .../thash_sha256_robustx8.c | 156 --- .../thashx8.h | 39 - .../utils.c | 199 ---- .../utils.h | 64 -- .../utilsx8.c | 172 ---- .../utilsx8.h | 46 - .../wots.c | 240 ----- .../wots.h | 41 - .../LICENSE | 116 --- .../address.c | 78 -- .../address.h | 50 - .../api.h | 81 -- .../fors.c | 161 --- .../fors.h | 32 - .../hash.h | 31 - .../hash_sha256.c | 162 ---- .../hash_state.h | 26 - .../params.h | 53 - .../sha256.c | 71 -- .../sha256.h | 21 - .../sign.c | 356 ------- .../thash.h | 28 - .../thash_sha256_robust.c | 82 -- .../utils.c | 199 ---- .../utils.h | 64 -- .../wots.c | 167 ---- .../wots.h | 41 - .../LICENSE | 116 --- .../address.c | 78 -- .../address.h | 50 - .../api.h | 81 -- .../fors.c | 240 ----- .../fors.h | 32 - .../hash.h | 31 - .../hash_sha256.c | 166 ---- .../hash_sha256x8.c | 61 -- .../hash_state.h | 33 - .../hashx8.h | 19 - .../params.h | 53 - .../sha256.c | 71 -- .../sha256.h | 21 - .../sha256avx.c | 296 ------ .../sha256avx.h | 103 -- .../sha256x8.c | 128 --- .../sha256x8.h | 44 - .../sign.c | 356 ------- .../thash.h | 28 - .../thash_sha256_simple.c | 75 -- .../thash_sha256_simplex8.c | 129 --- .../thashx8.h | 39 - .../utils.c | 199 ---- .../utils.h | 64 -- .../utilsx8.c | 172 ---- .../utilsx8.h | 46 - .../wots.c | 240 ----- .../wots.h | 41 - .../LICENSE | 116 --- .../address.c | 78 -- .../address.h | 50 - .../api.h | 81 -- .../fors.c | 161 --- .../fors.h | 32 - .../hash.h | 31 - .../hash_sha256.c | 162 ---- .../hash_state.h | 26 - .../params.h | 53 - .../sha256.c | 71 -- .../sha256.h | 21 - .../sign.c | 356 ------- .../thash.h | 28 - .../thash_sha256_simple.c | 75 -- .../utils.c | 199 ---- .../utils.h | 64 -- .../wots.c | 167 ---- .../wots.h | 41 - .../LICENSE | 116 --- .../address.c | 91 -- .../address.h | 52 - .../api.h | 77 -- .../context.h | 19 - .../context_shake.c | 12 - .../f1600x2.h | 11 - .../f1600x2.s | 143 --- .../f1600x2_const.c | 30 - .../fips202x2.c | 148 --- .../fips202x2.h | 24 - .../fors.c | 191 ---- .../fors.h | 32 - .../hash.h | 28 - .../hash_shake.c | 83 -- .../hash_shakex2.c | 52 - .../hashx2.h | 14 - .../merkle.c | 64 -- .../merkle.h | 21 - .../nistapi.h | 87 -- .../params.h | 56 -- .../shake_offsets.h | 21 - .../sign.c | 286 ------ .../thash.h | 13 - .../thash_shake_robustx2.c | 112 --- .../thashx2.h | 16 - .../utils.c | 148 --- .../utils.h | 58 -- .../utilsx2.c | 130 --- .../utilsx2.h | 30 - .../wots.c | 259 ----- .../wots.h | 25 - .../wotsx2.h | 40 - .../LICENSE | 116 --- .../address.c | 91 -- .../address.h | 52 - .../api.h | 77 -- .../context.h | 19 - .../context_shake.c | 12 - .../fips202x4.c | 210 ---- .../fips202x4.h | 28 - .../fors.c | 202 ---- .../fors.h | 32 - .../hash.h | 28 - .../hash_shake.c | 83 -- .../hash_shakex4.c | 64 -- .../hashx4.h | 17 - .../merkle.c | 64 -- .../merkle.h | 21 - .../nistapi.h | 87 -- .../params.h | 56 -- .../shake_offsets.h | 21 - .../sign.c | 286 ------ .../thash.h | 13 - .../thash_shake_robust.c | 31 - .../thash_shake_robustx4.c | 131 --- .../thashx4.h | 20 - .../utils.c | 148 --- .../utils.h | 58 -- .../utilsx4.c | 138 --- .../utilsx4.h | 30 - .../wots.c | 269 ------ .../wots.h | 25 - .../wotsx4.h | 41 - .../LICENSE | 116 --- .../address.c | 91 -- .../address.h | 52 - .../api.h | 77 -- .../context.h | 22 - .../context_shake.c | 12 - .../fors.c | 156 --- .../fors.h | 32 - .../hash.h | 28 - .../hash_shake.c | 83 -- .../merkle.c | 59 -- .../merkle.h | 21 - .../nistapi.h | 87 -- .../params.h | 56 -- .../shake_offsets.h | 21 - .../sign.c | 286 ------ .../thash.h | 13 - .../thash_shake_robust.c | 31 - .../utils.c | 148 --- .../utils.h | 58 -- .../utilsx1.c | 100 -- .../utilsx1.h | 27 - .../wots.c | 108 --- .../wots.h | 25 - .../wotsx1.c | 76 -- .../wotsx1.h | 39 - .../LICENSE | 116 --- .../address.c | 95 -- .../address.h | 52 - .../api.h | 77 -- .../context.h | 19 - .../context_shake.c | 12 - .../f1600x2.h | 11 - .../f1600x2.s | 143 --- .../f1600x2_const.c | 30 - .../fips202x2.c | 148 --- .../fips202x2.h | 24 - .../fors.c | 191 ---- .../fors.h | 32 - .../hash.h | 28 - .../hash_shake.c | 83 -- .../hash_shakex2.c | 52 - .../hashx2.h | 14 - .../merkle.c | 64 -- .../merkle.h | 21 - .../nistapi.h | 87 -- .../params.h | 56 -- .../shake_offsets.h | 21 - .../sign.c | 286 ------ .../thash.h | 13 - .../thash_shake_robustx2.c | 112 --- .../thashx2.h | 16 - .../utils.c | 148 --- .../utils.h | 58 -- .../utilsx2.c | 130 --- .../utilsx2.h | 30 - .../wots.c | 259 ----- .../wots.h | 25 - .../wotsx2.h | 40 - .../LICENSE | 116 --- .../address.c | 95 -- .../address.h | 52 - .../api.h | 77 -- .../context.h | 19 - .../context_shake.c | 12 - .../fips202x4.c | 210 ---- .../fips202x4.h | 28 - .../fors.c | 202 ---- .../fors.h | 32 - .../hash.h | 28 - .../hash_shake.c | 83 -- .../hash_shakex4.c | 64 -- .../hashx4.h | 17 - .../merkle.c | 64 -- .../merkle.h | 21 - .../nistapi.h | 87 -- .../params.h | 56 -- .../shake_offsets.h | 21 - .../sign.c | 286 ------ .../thash.h | 13 - .../thash_shake_robust.c | 31 - .../thash_shake_robustx4.c | 131 --- .../thashx4.h | 20 - .../utils.c | 148 --- .../utils.h | 58 -- .../utilsx4.c | 138 --- .../utilsx4.h | 30 - .../wots.c | 269 ------ .../wots.h | 25 - .../wotsx4.h | 41 - .../LICENSE | 116 --- .../address.c | 95 -- .../address.h | 52 - .../api.h | 77 -- .../context.h | 22 - .../context_shake.c | 12 - .../fors.c | 156 --- .../fors.h | 32 - .../hash.h | 28 - .../hash_shake.c | 83 -- .../merkle.c | 59 -- .../merkle.h | 21 - .../nistapi.h | 87 -- .../params.h | 56 -- .../shake_offsets.h | 21 - .../sign.c | 286 ------ .../thash.h | 13 - .../thash_shake_robust.c | 31 - .../utils.c | 148 --- .../utils.h | 58 -- .../utilsx1.c | 100 -- .../utilsx1.h | 27 - .../wots.c | 108 --- .../wots.h | 25 - .../wotsx1.c | 76 -- .../wotsx1.h | 39 - .../LICENSE | 116 --- .../address.c | 91 -- .../address.h | 52 - .../api.h | 77 -- .../context.h | 19 - .../context_shake.c | 12 - .../f1600x2.h | 11 - .../f1600x2.s | 143 --- .../f1600x2_const.c | 30 - .../fips202x2.c | 148 --- .../fips202x2.h | 24 - .../fors.c | 191 ---- .../fors.h | 32 - .../hash.h | 28 - .../hash_shake.c | 83 -- .../hash_shakex2.c | 52 - .../hashx2.h | 14 - .../merkle.c | 64 -- .../merkle.h | 21 - .../nistapi.h | 87 -- .../params.h | 56 -- .../shake_offsets.h | 21 - .../sign.c | 286 ------ .../thash.h | 13 - .../thash_shake_robustx2.c | 112 --- .../thashx2.h | 16 - .../utils.c | 148 --- .../utils.h | 58 -- .../utilsx2.c | 130 --- .../utilsx2.h | 30 - .../wots.c | 259 ----- .../wots.h | 25 - .../wotsx2.h | 40 - .../LICENSE | 116 --- .../address.c | 91 -- .../address.h | 52 - .../api.h | 77 -- .../context.h | 19 - .../context_shake.c | 12 - .../fips202x4.c | 210 ---- .../fips202x4.h | 28 - .../fors.c | 202 ---- .../fors.h | 32 - .../hash.h | 28 - .../hash_shake.c | 83 -- .../hash_shakex4.c | 64 -- .../hashx4.h | 17 - .../merkle.c | 64 -- .../merkle.h | 21 - .../nistapi.h | 87 -- .../params.h | 56 -- .../shake_offsets.h | 21 - .../sign.c | 286 ------ .../thash.h | 13 - .../thash_shake_robust.c | 31 - .../thash_shake_robustx4.c | 131 --- .../thashx4.h | 20 - .../utils.c | 148 --- .../utils.h | 58 -- .../utilsx4.c | 138 --- .../utilsx4.h | 30 - .../wots.c | 269 ------ .../wots.h | 25 - .../wotsx4.h | 41 - .../LICENSE | 116 --- .../address.c | 91 -- .../address.h | 52 - .../api.h | 77 -- .../context.h | 22 - .../context_shake.c | 12 - .../fors.c | 156 --- .../fors.h | 32 - .../hash.h | 28 - .../hash_shake.c | 83 -- .../merkle.c | 59 -- .../merkle.h | 21 - .../nistapi.h | 87 -- .../params.h | 56 -- .../shake_offsets.h | 21 - .../sign.c | 286 ------ .../thash.h | 13 - .../thash_shake_robust.c | 31 - .../utils.c | 148 --- .../utils.h | 58 -- .../utilsx1.c | 100 -- .../utilsx1.h | 27 - .../wots.c | 108 --- .../wots.h | 25 - .../wotsx1.c | 76 -- .../wotsx1.h | 39 - .../LICENSE | 116 --- .../address.c | 95 -- .../address.h | 52 - .../api.h | 77 -- .../context.h | 19 - .../context_shake.c | 12 - .../f1600x2.h | 11 - .../f1600x2.s | 143 --- .../f1600x2_const.c | 30 - .../fips202x2.c | 148 --- .../fips202x2.h | 24 - .../fors.c | 191 ---- .../fors.h | 32 - .../hash.h | 28 - .../hash_shake.c | 83 -- .../hash_shakex2.c | 52 - .../hashx2.h | 14 - .../merkle.c | 64 -- .../merkle.h | 21 - .../nistapi.h | 87 -- .../params.h | 56 -- .../shake_offsets.h | 21 - .../sign.c | 286 ------ .../thash.h | 13 - .../thash_shake_robustx2.c | 112 --- .../thashx2.h | 16 - .../utils.c | 148 --- .../utils.h | 58 -- .../utilsx2.c | 130 --- .../utilsx2.h | 30 - .../wots.c | 259 ----- .../wots.h | 25 - .../wotsx2.h | 40 - .../LICENSE | 116 --- .../address.c | 95 -- .../address.h | 52 - .../api.h | 77 -- .../context.h | 19 - .../context_shake.c | 12 - .../fips202x4.c | 210 ---- .../fips202x4.h | 28 - .../fors.c | 202 ---- .../fors.h | 32 - .../hash.h | 28 - .../hash_shake.c | 83 -- .../hash_shakex4.c | 64 -- .../hashx4.h | 17 - .../merkle.c | 64 -- .../merkle.h | 21 - .../nistapi.h | 87 -- .../params.h | 56 -- .../shake_offsets.h | 21 - .../sign.c | 286 ------ .../thash.h | 13 - .../thash_shake_robust.c | 31 - .../thash_shake_robustx4.c | 131 --- .../thashx4.h | 20 - .../utils.c | 148 --- .../utils.h | 58 -- .../utilsx4.c | 138 --- .../utilsx4.h | 30 - .../wots.c | 269 ------ .../wots.h | 25 - .../wotsx4.h | 41 - .../LICENSE | 116 --- .../address.c | 95 -- .../address.h | 52 - .../api.h | 77 -- .../context.h | 22 - .../context_shake.c | 12 - .../fors.c | 156 --- .../fors.h | 32 - .../hash.h | 28 - .../hash_shake.c | 83 -- .../merkle.c | 59 -- .../merkle.h | 21 - .../nistapi.h | 87 -- .../params.h | 56 -- .../shake_offsets.h | 21 - .../sign.c | 286 ------ .../thash.h | 13 - .../thash_shake_robust.c | 31 - .../utils.c | 148 --- .../utils.h | 58 -- .../utilsx1.c | 100 -- .../utilsx1.h | 27 - .../wots.c | 108 --- .../wots.h | 25 - .../wotsx1.c | 76 -- .../wotsx1.h | 39 - .../LICENSE | 116 --- .../address.c | 91 -- .../address.h | 52 - .../api.h | 77 -- .../context.h | 19 - .../context_shake.c | 12 - .../f1600x2.h | 11 - .../f1600x2.s | 143 --- .../f1600x2_const.c | 30 - .../fips202x2.c | 148 --- .../fips202x2.h | 24 - .../fors.c | 191 ---- .../fors.h | 32 - .../hash.h | 28 - .../hash_shake.c | 83 -- .../hash_shakex2.c | 52 - .../hashx2.h | 14 - .../merkle.c | 64 -- .../merkle.h | 21 - .../nistapi.h | 87 -- .../params.h | 56 -- .../shake_offsets.h | 21 - .../sign.c | 286 ------ .../thash.h | 13 - .../thash_shake_robustx2.c | 112 --- .../thashx2.h | 16 - .../utils.c | 148 --- .../utils.h | 58 -- .../utilsx2.c | 130 --- .../utilsx2.h | 30 - .../wots.c | 259 ----- .../wots.h | 25 - .../wotsx2.h | 40 - .../LICENSE | 116 --- .../address.c | 91 -- .../address.h | 52 - .../api.h | 77 -- .../context.h | 19 - .../context_shake.c | 12 - .../fips202x4.c | 210 ---- .../fips202x4.h | 28 - .../fors.c | 202 ---- .../fors.h | 32 - .../hash.h | 28 - .../hash_shake.c | 83 -- .../hash_shakex4.c | 64 -- .../hashx4.h | 17 - .../merkle.c | 64 -- .../merkle.h | 21 - .../nistapi.h | 87 -- .../params.h | 56 -- .../shake_offsets.h | 21 - .../sign.c | 286 ------ .../thash.h | 13 - .../thash_shake_robust.c | 31 - .../thash_shake_robustx4.c | 131 --- .../thashx4.h | 20 - .../utils.c | 148 --- .../utils.h | 58 -- .../utilsx4.c | 138 --- .../utilsx4.h | 30 - .../wots.c | 269 ------ .../wots.h | 25 - .../wotsx4.h | 41 - .../LICENSE | 116 --- .../address.c | 91 -- .../address.h | 52 - .../api.h | 77 -- .../context.h | 22 - .../context_shake.c | 12 - .../fors.c | 156 --- .../fors.h | 32 - .../hash.h | 28 - .../hash_shake.c | 83 -- .../merkle.c | 59 -- .../merkle.h | 21 - .../nistapi.h | 87 -- .../params.h | 56 -- .../shake_offsets.h | 21 - .../sign.c | 286 ------ .../thash.h | 13 - .../thash_shake_robust.c | 31 - .../utils.c | 148 --- .../utils.h | 58 -- .../utilsx1.c | 100 -- .../utilsx1.h | 27 - .../wots.c | 108 --- .../wots.h | 25 - .../wotsx1.c | 76 -- .../wotsx1.h | 39 - .../LICENSE | 116 --- .../address.c | 91 -- .../address.h | 52 - .../api.h | 77 -- .../context.h | 19 - .../context_shake.c | 12 - .../f1600x2.h | 11 - .../f1600x2.s | 143 --- .../f1600x2_const.c | 30 - .../fips202x2.c | 148 --- .../fips202x2.h | 24 - .../fors.c | 191 ---- .../fors.h | 32 - .../hash.h | 28 - .../hash_shake.c | 83 -- .../hash_shakex2.c | 52 - .../hashx2.h | 14 - .../merkle.c | 64 -- .../merkle.h | 21 - .../nistapi.h | 87 -- .../params.h | 56 -- .../shake_offsets.h | 21 - .../sign.c | 286 ------ .../thash.h | 13 - .../thash_shake_robustx2.c | 112 --- .../thashx2.h | 16 - .../utils.c | 148 --- .../utils.h | 58 -- .../utilsx2.c | 130 --- .../utilsx2.h | 30 - .../wots.c | 259 ----- .../wots.h | 25 - .../wotsx2.h | 40 - .../LICENSE | 116 --- .../address.c | 91 -- .../address.h | 52 - .../api.h | 77 -- .../context.h | 19 - .../context_shake.c | 12 - .../fips202x4.c | 210 ---- .../fips202x4.h | 28 - .../fors.c | 202 ---- .../fors.h | 32 - .../hash.h | 28 - .../hash_shake.c | 83 -- .../hash_shakex4.c | 64 -- .../hashx4.h | 17 - .../merkle.c | 64 -- .../merkle.h | 21 - .../nistapi.h | 87 -- .../params.h | 56 -- .../shake_offsets.h | 21 - .../sign.c | 286 ------ .../thash.h | 13 - .../thash_shake_robust.c | 31 - .../thash_shake_robustx4.c | 131 --- .../thashx4.h | 20 - .../utils.c | 148 --- .../utils.h | 58 -- .../utilsx4.c | 138 --- .../utilsx4.h | 30 - .../wots.c | 269 ------ .../wots.h | 25 - .../wotsx4.h | 41 - .../LICENSE | 116 --- .../address.c | 91 -- .../address.h | 52 - .../api.h | 77 -- .../context.h | 22 - .../context_shake.c | 12 - .../fors.c | 156 --- .../fors.h | 32 - .../hash.h | 28 - .../hash_shake.c | 83 -- .../merkle.c | 59 -- .../merkle.h | 21 - .../nistapi.h | 87 -- .../params.h | 56 -- .../shake_offsets.h | 21 - .../sign.c | 286 ------ .../thash.h | 13 - .../thash_shake_robust.c | 31 - .../utils.c | 148 --- .../utils.h | 58 -- .../utilsx1.c | 100 -- .../utilsx1.h | 27 - .../wots.c | 108 --- .../wots.h | 25 - .../wotsx1.c | 76 -- .../wotsx1.h | 39 - .../LICENSE | 116 --- .../address.c | 78 -- .../address.h | 50 - .../api.h | 81 -- .../fors.c | 206 ---- .../fors.h | 32 - .../hash.h | 31 - .../hash_shake256.c | 106 -- .../hash_shake256x4.c | 38 - .../hash_state.h | 30 - .../hashx4.h | 16 - .../params.h | 53 - .../sign.c | 409 -------- .../thash.h | 28 - .../thash_shake256_robust.c | 81 -- .../thash_shake256_robustx4.c | 66 -- .../thashx4.h | 25 - .../utils.c | 199 ---- .../utils.h | 64 -- .../utilsx4.c | 98 -- .../utilsx4.h | 38 - .../wots.c | 240 ----- .../wots.h | 41 - .../LICENSE | 116 --- .../address.c | 78 -- .../address.h | 50 - .../api.h | 81 -- .../fors.c | 161 --- .../fors.h | 32 - .../hash.h | 31 - .../hash_shake256.c | 106 -- .../hash_state.h | 30 - .../params.h | 53 - .../sign.c | 356 ------- .../thash.h | 28 - .../thash_shake256_robust.c | 81 -- .../utils.c | 199 ---- .../utils.h | 64 -- .../wots.c | 167 ---- .../wots.h | 41 - .../LICENSE | 116 --- .../address.c | 78 -- .../address.h | 50 - .../api.h | 81 -- .../fors.c | 206 ---- .../fors.h | 32 - .../hash.h | 31 - .../hash_shake256.c | 106 -- .../hash_shake256x4.c | 38 - .../hash_state.h | 30 - .../hashx4.h | 16 - .../params.h | 53 - .../sign.c | 409 -------- .../thash.h | 28 - .../thash_shake256_simple.c | 74 -- .../thash_shake256_simplex4.c | 47 - .../thashx4.h | 25 - .../utils.c | 199 ---- .../utils.h | 64 -- .../utilsx4.c | 98 -- .../utilsx4.h | 38 - .../wots.c | 240 ----- .../wots.h | 41 - .../LICENSE | 116 --- .../address.c | 78 -- .../address.h | 50 - .../api.h | 81 -- .../fors.c | 161 --- .../fors.h | 32 - .../hash.h | 31 - .../hash_shake256.c | 106 -- .../hash_state.h | 30 - .../params.h | 53 - .../sign.c | 356 ------- .../thash.h | 28 - .../thash_shake256_simple.c | 74 -- .../utils.c | 199 ---- .../utils.h | 64 -- .../wots.c | 167 ---- .../wots.h | 41 - .../LICENSE | 116 --- .../address.c | 78 -- .../address.h | 50 - .../api.h | 81 -- .../fors.c | 206 ---- .../fors.h | 32 - .../hash.h | 31 - .../hash_shake256.c | 106 -- .../hash_shake256x4.c | 38 - .../hash_state.h | 30 - .../hashx4.h | 16 - .../params.h | 53 - .../sign.c | 409 -------- .../thash.h | 28 - .../thash_shake256_robust.c | 81 -- .../thash_shake256_robustx4.c | 66 -- .../thashx4.h | 25 - .../utils.c | 199 ---- .../utils.h | 64 -- .../utilsx4.c | 98 -- .../utilsx4.h | 38 - .../wots.c | 240 ----- .../wots.h | 41 - .../LICENSE | 116 --- .../address.c | 78 -- .../address.h | 50 - .../api.h | 81 -- .../fors.c | 161 --- .../fors.h | 32 - .../hash.h | 31 - .../hash_shake256.c | 106 -- .../hash_state.h | 30 - .../params.h | 53 - .../sign.c | 356 ------- .../thash.h | 28 - .../thash_shake256_robust.c | 81 -- .../utils.c | 199 ---- .../utils.h | 64 -- .../wots.c | 167 ---- .../wots.h | 41 - .../LICENSE | 116 --- .../address.c | 78 -- .../address.h | 50 - .../api.h | 81 -- .../fors.c | 206 ---- .../fors.h | 32 - .../hash.h | 31 - .../hash_shake256.c | 106 -- .../hash_shake256x4.c | 38 - .../hash_state.h | 30 - .../hashx4.h | 16 - .../params.h | 53 - .../sign.c | 409 -------- .../thash.h | 28 - .../thash_shake256_simple.c | 74 -- .../thash_shake256_simplex4.c | 47 - .../thashx4.h | 25 - .../utils.c | 199 ---- .../utils.h | 64 -- .../utilsx4.c | 98 -- .../utilsx4.h | 38 - .../wots.c | 240 ----- .../wots.h | 41 - .../LICENSE | 116 --- .../address.c | 78 -- .../address.h | 50 - .../api.h | 81 -- .../fors.c | 161 --- .../fors.h | 32 - .../hash.h | 31 - .../hash_shake256.c | 106 -- .../hash_state.h | 30 - .../params.h | 53 - .../sign.c | 356 ------- .../thash.h | 28 - .../thash_shake256_simple.c | 74 -- .../utils.c | 199 ---- .../utils.h | 64 -- .../wots.c | 167 ---- .../wots.h | 41 - .../LICENSE | 116 --- .../address.c | 78 -- .../address.h | 50 - .../api.h | 81 -- .../fors.c | 206 ---- .../fors.h | 32 - .../hash.h | 31 - .../hash_shake256.c | 106 -- .../hash_shake256x4.c | 38 - .../hash_state.h | 30 - .../hashx4.h | 16 - .../params.h | 53 - .../sign.c | 409 -------- .../thash.h | 28 - .../thash_shake256_robust.c | 81 -- .../thash_shake256_robustx4.c | 66 -- .../thashx4.h | 25 - .../utils.c | 199 ---- .../utils.h | 64 -- .../utilsx4.c | 98 -- .../utilsx4.h | 38 - .../wots.c | 240 ----- .../wots.h | 41 - .../LICENSE | 116 --- .../address.c | 78 -- .../address.h | 50 - .../api.h | 81 -- .../fors.c | 161 --- .../fors.h | 32 - .../hash.h | 31 - .../hash_shake256.c | 106 -- .../hash_state.h | 30 - .../params.h | 53 - .../sign.c | 356 ------- .../thash.h | 28 - .../thash_shake256_robust.c | 81 -- .../utils.c | 199 ---- .../utils.h | 64 -- .../wots.c | 167 ---- .../wots.h | 41 - .../LICENSE | 116 --- .../address.c | 78 -- .../address.h | 50 - .../api.h | 81 -- .../fors.c | 206 ---- .../fors.h | 32 - .../hash.h | 31 - .../hash_shake256.c | 106 -- .../hash_shake256x4.c | 38 - .../hash_state.h | 30 - .../hashx4.h | 16 - .../params.h | 53 - .../sign.c | 409 -------- .../thash.h | 28 - .../thash_shake256_simple.c | 74 -- .../thash_shake256_simplex4.c | 47 - .../thashx4.h | 25 - .../utils.c | 199 ---- .../utils.h | 64 -- .../utilsx4.c | 98 -- .../utilsx4.h | 38 - .../wots.c | 240 ----- .../wots.h | 41 - .../LICENSE | 116 --- .../address.c | 78 -- .../address.h | 50 - .../api.h | 81 -- .../fors.c | 161 --- .../fors.h | 32 - .../hash.h | 31 - .../hash_shake256.c | 106 -- .../hash_state.h | 30 - .../params.h | 53 - .../sign.c | 356 ------- .../thash.h | 28 - .../thash_shake256_simple.c | 74 -- .../utils.c | 199 ---- .../utils.h | 64 -- .../wots.c | 167 ---- .../wots.h | 41 - .../LICENSE | 116 --- .../address.c | 78 -- .../address.h | 50 - .../api.h | 81 -- .../fors.c | 206 ---- .../fors.h | 32 - .../hash.h | 31 - .../hash_shake256.c | 106 -- .../hash_shake256x4.c | 38 - .../hash_state.h | 30 - .../hashx4.h | 16 - .../params.h | 53 - .../sign.c | 409 -------- .../thash.h | 28 - .../thash_shake256_robust.c | 81 -- .../thash_shake256_robustx4.c | 66 -- .../thashx4.h | 25 - .../utils.c | 199 ---- .../utils.h | 64 -- .../utilsx4.c | 98 -- .../utilsx4.h | 38 - .../wots.c | 240 ----- .../wots.h | 41 - .../LICENSE | 116 --- .../address.c | 78 -- .../address.h | 50 - .../api.h | 81 -- .../fors.c | 161 --- .../fors.h | 32 - .../hash.h | 31 - .../hash_shake256.c | 106 -- .../hash_state.h | 30 - .../params.h | 53 - .../sign.c | 356 ------- .../thash.h | 28 - .../thash_shake256_robust.c | 81 -- .../utils.c | 199 ---- .../utils.h | 64 -- .../wots.c | 167 ---- .../wots.h | 41 - .../LICENSE | 116 --- .../address.c | 78 -- .../address.h | 50 - .../api.h | 81 -- .../fors.c | 206 ---- .../fors.h | 32 - .../hash.h | 31 - .../hash_shake256.c | 106 -- .../hash_shake256x4.c | 38 - .../hash_state.h | 30 - .../hashx4.h | 16 - .../params.h | 53 - .../sign.c | 409 -------- .../thash.h | 28 - .../thash_shake256_simple.c | 74 -- .../thash_shake256_simplex4.c | 47 - .../thashx4.h | 25 - .../utils.c | 199 ---- .../utils.h | 64 -- .../utilsx4.c | 98 -- .../utilsx4.h | 38 - .../wots.c | 240 ----- .../wots.h | 41 - .../LICENSE | 116 --- .../address.c | 78 -- .../address.h | 50 - .../api.h | 81 -- .../fors.c | 161 --- .../fors.h | 32 - .../hash.h | 31 - .../hash_shake256.c | 106 -- .../hash_state.h | 30 - .../params.h | 53 - .../sign.c | 356 ------- .../thash.h | 28 - .../thash_shake256_simple.c | 74 -- .../utils.c | 199 ---- .../utils.h | 64 -- .../wots.c | 167 ---- .../wots.h | 41 - .../LICENSE | 116 --- .../address.c | 78 -- .../address.h | 50 - .../api.h | 81 -- .../fors.c | 206 ---- .../fors.h | 32 - .../hash.h | 31 - .../hash_shake256.c | 106 -- .../hash_shake256x4.c | 38 - .../hash_state.h | 30 - .../hashx4.h | 16 - .../params.h | 53 - .../sign.c | 409 -------- .../thash.h | 28 - .../thash_shake256_robust.c | 81 -- .../thash_shake256_robustx4.c | 66 -- .../thashx4.h | 25 - .../utils.c | 199 ---- .../utils.h | 64 -- .../utilsx4.c | 98 -- .../utilsx4.h | 38 - .../wots.c | 240 ----- .../wots.h | 41 - .../LICENSE | 116 --- .../address.c | 78 -- .../address.h | 50 - .../api.h | 81 -- .../fors.c | 161 --- .../fors.h | 32 - .../hash.h | 31 - .../hash_shake256.c | 106 -- .../hash_state.h | 30 - .../params.h | 53 - .../sign.c | 356 ------- .../thash.h | 28 - .../thash_shake256_robust.c | 81 -- .../utils.c | 199 ---- .../utils.h | 64 -- .../wots.c | 167 ---- .../wots.h | 41 - .../LICENSE | 116 --- .../address.c | 78 -- .../address.h | 50 - .../api.h | 81 -- .../fors.c | 206 ---- .../fors.h | 32 - .../hash.h | 31 - .../hash_shake256.c | 106 -- .../hash_shake256x4.c | 38 - .../hash_state.h | 30 - .../hashx4.h | 16 - .../params.h | 53 - .../sign.c | 409 -------- .../thash.h | 28 - .../thash_shake256_simple.c | 74 -- .../thash_shake256_simplex4.c | 47 - .../thashx4.h | 25 - .../utils.c | 199 ---- .../utils.h | 64 -- .../utilsx4.c | 98 -- .../utilsx4.h | 38 - .../wots.c | 240 ----- .../wots.h | 41 - .../LICENSE | 116 --- .../address.c | 78 -- .../address.h | 50 - .../api.h | 81 -- .../fors.c | 161 --- .../fors.h | 32 - .../hash.h | 31 - .../hash_shake256.c | 106 -- .../hash_state.h | 30 - .../params.h | 53 - .../sign.c | 356 ------- .../thash.h | 28 - .../thash_shake256_simple.c | 74 -- .../utils.c | 199 ---- .../utils.h | 64 -- .../wots.c | 167 ---- .../wots.h | 41 - .../LICENSE | 116 --- .../address.c | 78 -- .../address.h | 50 - .../api.h | 81 -- .../fors.c | 206 ---- .../fors.h | 32 - .../hash.h | 31 - .../hash_shake256.c | 106 -- .../hash_shake256x4.c | 38 - .../hash_state.h | 30 - .../hashx4.h | 16 - .../params.h | 53 - .../sign.c | 409 -------- .../thash.h | 28 - .../thash_shake256_robust.c | 81 -- .../thash_shake256_robustx4.c | 66 -- .../thashx4.h | 25 - .../utils.c | 199 ---- .../utils.h | 64 -- .../utilsx4.c | 98 -- .../utilsx4.h | 38 - .../wots.c | 240 ----- .../wots.h | 41 - .../LICENSE | 116 --- .../address.c | 78 -- .../address.h | 50 - .../api.h | 81 -- .../fors.c | 161 --- .../fors.h | 32 - .../hash.h | 31 - .../hash_shake256.c | 106 -- .../hash_state.h | 30 - .../params.h | 53 - .../sign.c | 356 ------- .../thash.h | 28 - .../thash_shake256_robust.c | 81 -- .../utils.c | 199 ---- .../utils.h | 64 -- .../wots.c | 167 ---- .../wots.h | 41 - .../LICENSE | 116 --- .../address.c | 78 -- .../address.h | 50 - .../api.h | 81 -- .../fors.c | 206 ---- .../fors.h | 32 - .../hash.h | 31 - .../hash_shake256.c | 106 -- .../hash_shake256x4.c | 38 - .../hash_state.h | 30 - .../hashx4.h | 16 - .../params.h | 53 - .../sign.c | 409 -------- .../thash.h | 28 - .../thash_shake256_simple.c | 74 -- .../thash_shake256_simplex4.c | 47 - .../thashx4.h | 25 - .../utils.c | 199 ---- .../utils.h | 64 -- .../utilsx4.c | 98 -- .../utilsx4.h | 38 - .../wots.c | 240 ----- .../wots.h | 41 - .../LICENSE | 116 --- .../address.c | 78 -- .../address.h | 50 - .../api.h | 81 -- .../fors.c | 161 --- .../fors.h | 32 - .../hash.h | 31 - .../hash_shake256.c | 106 -- .../hash_state.h | 30 - .../params.h | 53 - .../sign.c | 356 ------- .../thash.h | 28 - .../thash_shake256_simple.c | 74 -- .../utils.c | 199 ---- .../utils.h | 64 -- .../wots.c | 167 ---- .../wots.h | 41 - .../sphincs/sig_sphincs_haraka_128f_robust.c | 90 -- .../sphincs/sig_sphincs_haraka_128f_simple.c | 90 -- .../sphincs/sig_sphincs_haraka_128s_robust.c | 90 -- .../sphincs/sig_sphincs_haraka_128s_simple.c | 90 -- .../sphincs/sig_sphincs_haraka_192f_robust.c | 90 -- .../sphincs/sig_sphincs_haraka_192f_simple.c | 90 -- .../sphincs/sig_sphincs_haraka_192s_robust.c | 90 -- .../sphincs/sig_sphincs_haraka_192s_simple.c | 90 -- .../sphincs/sig_sphincs_haraka_256f_robust.c | 90 -- .../sphincs/sig_sphincs_haraka_256f_simple.c | 90 -- .../sphincs/sig_sphincs_haraka_256s_robust.c | 90 -- .../sphincs/sig_sphincs_haraka_256s_simple.c | 90 -- .../sphincs/sig_sphincs_sha256_128f_robust.c | 90 -- .../sphincs/sig_sphincs_sha256_128s_robust.c | 90 -- .../sphincs/sig_sphincs_sha256_192f_robust.c | 90 -- .../sphincs/sig_sphincs_sha256_192s_robust.c | 90 -- .../sphincs/sig_sphincs_sha256_256f_robust.c | 90 -- .../sphincs/sig_sphincs_sha256_256s_robust.c | 90 -- .../sig_sphincs_shake256_128f_robust.c | 126 --- .../sig_sphincs_shake256_128s_robust.c | 126 --- .../sig_sphincs_shake256_192f_robust.c | 126 --- .../sig_sphincs_shake256_192s_robust.c | 126 --- .../sig_sphincs_shake256_256f_robust.c | 126 --- .../sig_sphincs_shake256_256s_robust.c | 126 --- 2702 files changed, 249312 deletions(-) delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/LICENSE delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/address.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/address.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/api.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/context.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/context_haraka.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/fors.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/fors.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/haraka.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/haraka.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/haraka_offsets.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/harakax4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/hash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/hash_haraka.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/hash_harakax4.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/hashx4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/merkle.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/merkle.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/nistapi.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/params.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/sign.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/thash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/thash_haraka_robust.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/thash_haraka_robustx4.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/thashx4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/utils.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/utils.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/utilsx4.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/utilsx4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/wots.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/wots.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/wotsx4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/LICENSE delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/address.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/address.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/api.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/context.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/context_haraka.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/fors.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/fors.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/haraka.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/haraka.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/haraka_offsets.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/hash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/hash_haraka.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/merkle.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/merkle.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/nistapi.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/params.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/sign.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/thash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/thash_haraka_robust.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/utils.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/utils.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/utilsx1.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/utilsx1.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/wots.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/wots.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/wotsx1.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/wotsx1.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/LICENSE delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/address.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/address.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/api.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/context.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/context_haraka.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/fors.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/fors.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/haraka.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/haraka.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/haraka_offsets.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/harakax4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/hash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/hash_haraka.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/hash_harakax4.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/hashx4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/merkle.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/merkle.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/nistapi.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/params.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/sign.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/thash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/thash_haraka_simple.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/thash_haraka_simplex4.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/thashx4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/utils.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/utils.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/utilsx4.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/utilsx4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/wots.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/wots.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/wotsx4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/LICENSE delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/address.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/address.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/api.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/context.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/context_haraka.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/fors.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/fors.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/haraka.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/haraka.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/haraka_offsets.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/hash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/hash_haraka.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/merkle.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/merkle.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/nistapi.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/params.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/sign.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/thash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/thash_haraka_simple.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/utils.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/utils.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/utilsx1.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/utilsx1.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/wots.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/wots.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/wotsx1.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/wotsx1.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/LICENSE delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/address.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/address.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/api.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/context.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/context_haraka.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/fors.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/fors.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/haraka.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/haraka.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/haraka_offsets.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/harakax4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/hash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/hash_haraka.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/hash_harakax4.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/hashx4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/merkle.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/merkle.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/nistapi.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/params.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/sign.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/thash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/thash_haraka_robust.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/thash_haraka_robustx4.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/thashx4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/utils.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/utils.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/utilsx4.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/utilsx4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/wots.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/wots.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/wotsx4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/LICENSE delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/address.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/address.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/api.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/context.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/context_haraka.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/fors.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/fors.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/haraka.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/haraka.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/haraka_offsets.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/hash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/hash_haraka.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/merkle.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/merkle.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/nistapi.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/params.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/sign.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/thash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/thash_haraka_robust.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/utils.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/utils.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/utilsx1.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/utilsx1.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/wots.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/wots.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/wotsx1.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/wotsx1.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/LICENSE delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/address.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/address.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/api.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/context.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/context_haraka.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/fors.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/fors.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/haraka.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/haraka.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/haraka_offsets.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/harakax4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/hash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/hash_haraka.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/hash_harakax4.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/hashx4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/merkle.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/merkle.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/nistapi.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/params.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/sign.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/thash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/thash_haraka_simple.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/thash_haraka_simplex4.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/thashx4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/utils.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/utils.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/utilsx4.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/utilsx4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/wots.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/wots.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/wotsx4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/LICENSE delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/address.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/address.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/api.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/context.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/context_haraka.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/fors.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/fors.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/haraka.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/haraka.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/haraka_offsets.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/hash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/hash_haraka.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/merkle.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/merkle.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/nistapi.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/params.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/sign.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/thash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/thash_haraka_simple.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/utils.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/utils.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/utilsx1.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/utilsx1.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/wots.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/wots.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/wotsx1.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/wotsx1.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/LICENSE delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/address.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/address.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/api.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/context.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/context_haraka.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/fors.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/fors.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/haraka.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/haraka.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/haraka_offsets.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/harakax4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/hash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/hash_haraka.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/hash_harakax4.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/hashx4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/merkle.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/merkle.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/nistapi.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/params.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/sign.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/thash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/thash_haraka_robust.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/thash_haraka_robustx4.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/thashx4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/utils.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/utils.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/utilsx4.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/utilsx4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/wots.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/wots.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/wotsx4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/LICENSE delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/address.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/address.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/api.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/context.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/context_haraka.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/fors.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/fors.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/haraka.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/haraka.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/haraka_offsets.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/hash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/hash_haraka.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/merkle.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/merkle.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/nistapi.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/params.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/sign.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/thash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/thash_haraka_robust.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/utils.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/utils.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/utilsx1.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/utilsx1.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/wots.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/wots.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/wotsx1.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/wotsx1.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/LICENSE delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/address.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/address.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/api.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/context.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/context_haraka.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/fors.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/fors.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/haraka.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/haraka.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/haraka_offsets.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/harakax4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/hash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/hash_haraka.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/hash_harakax4.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/hashx4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/merkle.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/merkle.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/nistapi.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/params.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/sign.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/thash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/thash_haraka_simple.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/thash_haraka_simplex4.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/thashx4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/utils.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/utils.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/utilsx4.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/utilsx4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/wots.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/wots.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/wotsx4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/LICENSE delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/address.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/address.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/api.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/context.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/context_haraka.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/fors.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/fors.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/haraka.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/haraka.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/haraka_offsets.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/hash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/hash_haraka.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/merkle.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/merkle.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/nistapi.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/params.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/sign.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/thash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/thash_haraka_simple.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/utils.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/utils.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/utilsx1.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/utilsx1.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/wots.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/wots.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/wotsx1.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/wotsx1.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/LICENSE delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/address.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/address.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/api.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/context.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/context_haraka.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/fors.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/fors.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/haraka.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/haraka.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/haraka_offsets.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/harakax4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/hash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/hash_haraka.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/hash_harakax4.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/hashx4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/merkle.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/merkle.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/nistapi.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/params.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/sign.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/thash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/thash_haraka_robust.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/thash_haraka_robustx4.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/thashx4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/utils.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/utils.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/utilsx4.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/utilsx4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/wots.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/wots.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/wotsx4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/LICENSE delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/address.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/address.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/api.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/context.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/context_haraka.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/fors.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/fors.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/haraka.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/haraka.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/haraka_offsets.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/hash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/hash_haraka.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/merkle.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/merkle.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/nistapi.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/params.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/sign.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/thash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/thash_haraka_robust.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/utils.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/utils.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/utilsx1.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/utilsx1.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/wots.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/wots.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/wotsx1.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/wotsx1.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/LICENSE delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/address.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/address.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/api.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/context.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/context_haraka.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/fors.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/fors.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/haraka.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/haraka.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/haraka_offsets.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/harakax4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/hash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/hash_haraka.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/hash_harakax4.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/hashx4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/merkle.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/merkle.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/nistapi.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/params.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/sign.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/thash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/thash_haraka_simple.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/thash_haraka_simplex4.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/thashx4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/utils.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/utils.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/utilsx4.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/utilsx4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/wots.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/wots.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/wotsx4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/LICENSE delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/address.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/address.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/api.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/context.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/context_haraka.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/fors.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/fors.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/haraka.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/haraka.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/haraka_offsets.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/hash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/hash_haraka.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/merkle.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/merkle.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/nistapi.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/params.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/sign.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/thash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/thash_haraka_simple.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/utils.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/utils.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/utilsx1.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/utilsx1.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/wots.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/wots.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/wotsx1.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/wotsx1.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/LICENSE delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/address.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/address.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/api.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/context.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/context_haraka.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/fors.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/fors.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/haraka.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/haraka.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/haraka_offsets.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/harakax4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/hash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/hash_haraka.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/hash_harakax4.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/hashx4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/merkle.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/merkle.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/nistapi.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/params.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/sign.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/thash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/thash_haraka_robust.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/thash_haraka_robustx4.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/thashx4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/utils.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/utils.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/utilsx4.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/utilsx4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/wots.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/wots.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/wotsx4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/LICENSE delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/address.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/address.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/api.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/context.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/context_haraka.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/fors.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/fors.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/haraka.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/haraka.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/haraka_offsets.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/hash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/hash_haraka.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/merkle.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/merkle.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/nistapi.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/params.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/sign.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/thash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/thash_haraka_robust.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/utils.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/utils.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/utilsx1.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/utilsx1.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/wots.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/wots.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/wotsx1.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/wotsx1.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/LICENSE delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/address.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/address.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/api.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/context.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/context_haraka.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/fors.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/fors.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/haraka.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/haraka.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/haraka_offsets.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/harakax4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/hash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/hash_haraka.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/hash_harakax4.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/hashx4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/merkle.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/merkle.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/nistapi.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/params.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/sign.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/thash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/thash_haraka_simple.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/thash_haraka_simplex4.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/thashx4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/utils.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/utils.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/utilsx4.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/utilsx4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/wots.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/wots.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/wotsx4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/LICENSE delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/address.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/address.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/api.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/context.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/context_haraka.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/fors.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/fors.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/haraka.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/haraka.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/haraka_offsets.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/hash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/hash_haraka.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/merkle.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/merkle.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/nistapi.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/params.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/sign.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/thash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/thash_haraka_simple.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/utils.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/utils.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/utilsx1.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/utilsx1.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/wots.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/wots.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/wotsx1.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/wotsx1.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/LICENSE delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/address.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/address.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/api.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/context.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/context_haraka.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/fors.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/fors.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/haraka.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/haraka.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/haraka_offsets.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/harakax4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/hash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/hash_haraka.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/hash_harakax4.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/hashx4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/merkle.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/merkle.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/nistapi.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/params.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/sign.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/thash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/thash_haraka_robust.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/thash_haraka_robustx4.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/thashx4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/utils.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/utils.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/utilsx4.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/utilsx4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/wots.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/wots.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/wotsx4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/LICENSE delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/address.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/address.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/api.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/context.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/context_haraka.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/fors.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/fors.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/haraka.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/haraka.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/haraka_offsets.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/hash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/hash_haraka.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/merkle.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/merkle.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/nistapi.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/params.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/sign.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/thash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/thash_haraka_robust.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/utils.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/utils.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/utilsx1.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/utilsx1.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/wots.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/wots.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/wotsx1.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/wotsx1.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/LICENSE delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/address.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/address.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/api.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/context.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/context_haraka.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/fors.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/fors.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/haraka.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/haraka.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/haraka_offsets.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/harakax4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/hash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/hash_haraka.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/hash_harakax4.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/hashx4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/merkle.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/merkle.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/nistapi.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/params.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/sign.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/thash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/thash_haraka_simple.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/thash_haraka_simplex4.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/thashx4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/utils.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/utils.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/utilsx4.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/utilsx4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/wots.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/wots.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/wotsx4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/LICENSE delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/address.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/address.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/api.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/context.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/context_haraka.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/fors.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/fors.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/haraka.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/haraka.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/haraka_offsets.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/hash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/hash_haraka.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/merkle.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/merkle.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/nistapi.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/params.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/sign.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/thash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/thash_haraka_simple.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/utils.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/utils.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/utilsx1.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/utilsx1.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/wots.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/wots.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/wotsx1.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/wotsx1.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/LICENSE delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/address.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/address.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/api.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/context.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/context_sha2.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/fors.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/fors.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/hash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/hash_sha2.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/hash_sha2x8.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/hashx8.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/merkle.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/merkle.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/nistapi.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/params.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/sha256avx.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/sha256avx.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/sha256x8.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/sha256x8.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/sha2_offsets.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/sign.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/thash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/thash_sha2_robust.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/thash_sha2_robustx8.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/thashx8.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/utils.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/utils.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/utilsx8.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/utilsx8.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/wots.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/wots.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/wotsx8.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/LICENSE delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/address.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/address.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/api.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/context.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/context_sha2.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/fors.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/fors.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/hash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/hash_sha2.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/merkle.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/merkle.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/nistapi.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/params.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/sha2_offsets.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/sign.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/thash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/thash_sha2_robust.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/utils.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/utils.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/utilsx1.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/utilsx1.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/wots.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/wots.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/wotsx1.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/wotsx1.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/LICENSE delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/address.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/address.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/api.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/context.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/context_sha2.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/fors.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/fors.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/hash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/hash_sha2.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/hash_sha2x8.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/hashx8.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/merkle.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/merkle.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/nistapi.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/params.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/sha256avx.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/sha256avx.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/sha256x8.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/sha256x8.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/sha2_offsets.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/sign.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/thash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/thash_sha2_robust.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/thash_sha2_robustx8.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/thashx8.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/utils.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/utils.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/utilsx8.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/utilsx8.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/wots.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/wots.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/wotsx8.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/LICENSE delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/address.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/address.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/api.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/context.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/context_sha2.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/fors.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/fors.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/hash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/hash_sha2.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/merkle.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/merkle.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/nistapi.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/params.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/sha2_offsets.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/sign.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/thash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/thash_sha2_robust.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/utils.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/utils.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/utilsx1.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/utilsx1.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/wots.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/wots.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/wotsx1.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/wotsx1.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/LICENSE delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/address.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/address.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/api.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/context.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/context_sha2.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/fors.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/fors.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/hash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/hash_sha2.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/hash_sha2x8.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/hashx8.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/merkle.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/merkle.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/nistapi.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/params.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/sha256avx.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/sha256avx.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/sha256x8.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/sha256x8.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/sha2_offsets.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/sha512x4.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/sha512x4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/sign.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/thash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/thash_sha2_robust.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/thash_sha2_robustx8.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/thashx8.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/utils.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/utils.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/utilsx8.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/utilsx8.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/wots.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/wots.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/wotsx8.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/LICENSE delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/address.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/address.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/api.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/context.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/context_sha2.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/fors.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/fors.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/hash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/hash_sha2.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/merkle.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/merkle.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/nistapi.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/params.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/sha2_offsets.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/sign.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/thash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/thash_sha2_robust.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/utils.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/utils.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/utilsx1.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/utilsx1.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/wots.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/wots.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/wotsx1.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/wotsx1.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/LICENSE delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/address.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/address.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/api.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/context.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/context_sha2.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/fors.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/fors.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/hash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/hash_sha2.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/hash_sha2x8.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/hashx8.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/merkle.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/merkle.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/nistapi.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/params.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/sha256avx.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/sha256avx.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/sha256x8.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/sha256x8.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/sha2_offsets.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/sha512x4.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/sha512x4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/sign.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/thash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/thash_sha2_robust.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/thash_sha2_robustx8.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/thashx8.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/utils.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/utils.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/utilsx8.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/utilsx8.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/wots.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/wots.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/wotsx8.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/LICENSE delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/address.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/address.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/api.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/context.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/context_sha2.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/fors.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/fors.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/hash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/hash_sha2.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/merkle.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/merkle.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/nistapi.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/params.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/sha2_offsets.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/sign.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/thash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/thash_sha2_robust.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/utils.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/utils.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/utilsx1.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/utilsx1.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/wots.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/wots.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/wotsx1.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/wotsx1.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/LICENSE delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/address.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/address.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/api.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/context.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/context_sha2.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/fors.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/fors.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/hash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/hash_sha2.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/hash_sha2x8.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/hashx8.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/merkle.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/merkle.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/nistapi.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/params.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/sha256avx.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/sha256avx.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/sha256x8.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/sha256x8.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/sha2_offsets.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/sha512x4.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/sha512x4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/sign.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/thash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/thash_sha2_robust.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/thash_sha2_robustx8.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/thashx8.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/utils.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/utils.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/utilsx8.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/utilsx8.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/wots.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/wots.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/wotsx8.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/LICENSE delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/address.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/address.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/api.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/context.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/context_sha2.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/fors.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/fors.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/hash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/hash_sha2.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/merkle.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/merkle.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/nistapi.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/params.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/sha2_offsets.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/sign.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/thash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/thash_sha2_robust.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/utils.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/utils.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/utilsx1.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/utilsx1.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/wots.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/wots.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/wotsx1.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/wotsx1.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/LICENSE delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/address.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/address.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/api.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/context.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/context_sha2.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/fors.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/fors.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/hash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/hash_sha2.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/hash_sha2x8.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/hashx8.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/merkle.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/merkle.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/nistapi.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/params.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/sha256avx.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/sha256avx.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/sha256x8.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/sha256x8.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/sha2_offsets.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/sha512x4.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/sha512x4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/sign.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/thash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/thash_sha2_robust.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/thash_sha2_robustx8.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/thashx8.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/utils.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/utils.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/utilsx8.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/utilsx8.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/wots.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/wots.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/wotsx8.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/LICENSE delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/address.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/address.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/api.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/context.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/context_sha2.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/fors.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/fors.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/hash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/hash_sha2.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/merkle.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/merkle.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/nistapi.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/params.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/sha2_offsets.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/sign.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/thash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/thash_sha2_robust.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/utils.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/utils.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/utilsx1.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/utilsx1.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/wots.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/wots.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/wotsx1.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/wotsx1.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_avx2/LICENSE delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_avx2/address.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_avx2/address.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_avx2/api.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_avx2/fors.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_avx2/fors.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_avx2/hash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_avx2/hash_sha256.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_avx2/hash_sha256x8.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_avx2/hash_state.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_avx2/hashx8.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_avx2/params.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_avx2/sha256.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_avx2/sha256.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_avx2/sha256avx.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_avx2/sha256avx.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_avx2/sha256x8.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_avx2/sha256x8.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_avx2/sign.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_avx2/thash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_avx2/thash_sha256_robust.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_avx2/thash_sha256_robustx8.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_avx2/thashx8.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_avx2/utils.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_avx2/utils.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_avx2/utilsx8.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_avx2/utilsx8.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_avx2/wots.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_avx2/wots.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_clean/LICENSE delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_clean/address.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_clean/address.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_clean/api.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_clean/fors.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_clean/fors.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_clean/hash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_clean/hash_sha256.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_clean/hash_state.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_clean/params.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_clean/sha256.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_clean/sha256.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_clean/sign.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_clean/thash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_clean/thash_sha256_robust.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_clean/utils.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_clean/utils.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_clean/wots.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_clean/wots.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_avx2/LICENSE delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_avx2/address.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_avx2/address.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_avx2/api.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_avx2/fors.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_avx2/fors.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_avx2/hash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_avx2/hash_sha256.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_avx2/hash_sha256x8.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_avx2/hash_state.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_avx2/hashx8.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_avx2/params.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_avx2/sha256.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_avx2/sha256.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_avx2/sha256avx.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_avx2/sha256avx.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_avx2/sha256x8.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_avx2/sha256x8.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_avx2/sign.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_avx2/thash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_avx2/thash_sha256_simple.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_avx2/thash_sha256_simplex8.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_avx2/thashx8.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_avx2/utils.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_avx2/utils.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_avx2/utilsx8.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_avx2/utilsx8.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_avx2/wots.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_avx2/wots.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_clean/LICENSE delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_clean/address.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_clean/address.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_clean/api.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_clean/fors.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_clean/fors.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_clean/hash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_clean/hash_sha256.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_clean/hash_state.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_clean/params.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_clean/sha256.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_clean/sha256.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_clean/sign.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_clean/thash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_clean/thash_sha256_simple.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_clean/utils.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_clean/utils.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_clean/wots.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_clean/wots.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_avx2/LICENSE delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_avx2/address.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_avx2/address.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_avx2/api.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_avx2/fors.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_avx2/fors.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_avx2/hash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_avx2/hash_sha256.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_avx2/hash_sha256x8.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_avx2/hash_state.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_avx2/hashx8.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_avx2/params.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_avx2/sha256.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_avx2/sha256.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_avx2/sha256avx.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_avx2/sha256avx.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_avx2/sha256x8.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_avx2/sha256x8.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_avx2/sign.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_avx2/thash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_avx2/thash_sha256_robust.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_avx2/thash_sha256_robustx8.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_avx2/thashx8.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_avx2/utils.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_avx2/utils.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_avx2/utilsx8.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_avx2/utilsx8.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_avx2/wots.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_avx2/wots.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_clean/LICENSE delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_clean/address.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_clean/address.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_clean/api.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_clean/fors.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_clean/fors.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_clean/hash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_clean/hash_sha256.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_clean/hash_state.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_clean/params.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_clean/sha256.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_clean/sha256.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_clean/sign.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_clean/thash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_clean/thash_sha256_robust.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_clean/utils.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_clean/utils.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_clean/wots.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_clean/wots.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_avx2/LICENSE delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_avx2/address.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_avx2/address.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_avx2/api.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_avx2/fors.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_avx2/fors.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_avx2/hash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_avx2/hash_sha256.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_avx2/hash_sha256x8.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_avx2/hash_state.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_avx2/hashx8.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_avx2/params.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_avx2/sha256.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_avx2/sha256.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_avx2/sha256avx.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_avx2/sha256avx.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_avx2/sha256x8.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_avx2/sha256x8.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_avx2/sign.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_avx2/thash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_avx2/thash_sha256_simple.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_avx2/thash_sha256_simplex8.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_avx2/thashx8.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_avx2/utils.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_avx2/utils.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_avx2/utilsx8.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_avx2/utilsx8.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_avx2/wots.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_avx2/wots.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_clean/LICENSE delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_clean/address.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_clean/address.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_clean/api.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_clean/fors.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_clean/fors.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_clean/hash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_clean/hash_sha256.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_clean/hash_state.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_clean/params.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_clean/sha256.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_clean/sha256.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_clean/sign.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_clean/thash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_clean/thash_sha256_simple.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_clean/utils.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_clean/utils.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_clean/wots.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_clean/wots.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_avx2/LICENSE delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_avx2/address.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_avx2/address.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_avx2/api.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_avx2/fors.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_avx2/fors.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_avx2/hash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_avx2/hash_sha256.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_avx2/hash_sha256x8.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_avx2/hash_state.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_avx2/hashx8.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_avx2/params.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_avx2/sha256.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_avx2/sha256.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_avx2/sha256avx.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_avx2/sha256avx.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_avx2/sha256x8.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_avx2/sha256x8.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_avx2/sign.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_avx2/thash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_avx2/thash_sha256_robust.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_avx2/thash_sha256_robustx8.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_avx2/thashx8.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_avx2/utils.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_avx2/utils.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_avx2/utilsx8.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_avx2/utilsx8.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_avx2/wots.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_avx2/wots.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_clean/LICENSE delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_clean/address.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_clean/address.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_clean/api.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_clean/fors.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_clean/fors.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_clean/hash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_clean/hash_sha256.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_clean/hash_state.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_clean/params.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_clean/sha256.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_clean/sha256.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_clean/sign.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_clean/thash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_clean/thash_sha256_robust.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_clean/utils.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_clean/utils.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_clean/wots.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_clean/wots.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_avx2/LICENSE delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_avx2/address.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_avx2/address.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_avx2/api.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_avx2/fors.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_avx2/fors.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_avx2/hash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_avx2/hash_sha256.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_avx2/hash_sha256x8.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_avx2/hash_state.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_avx2/hashx8.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_avx2/params.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_avx2/sha256.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_avx2/sha256.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_avx2/sha256avx.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_avx2/sha256avx.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_avx2/sha256x8.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_avx2/sha256x8.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_avx2/sign.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_avx2/thash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_avx2/thash_sha256_simple.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_avx2/thash_sha256_simplex8.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_avx2/thashx8.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_avx2/utils.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_avx2/utils.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_avx2/utilsx8.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_avx2/utilsx8.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_avx2/wots.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_avx2/wots.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_clean/LICENSE delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_clean/address.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_clean/address.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_clean/api.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_clean/fors.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_clean/fors.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_clean/hash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_clean/hash_sha256.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_clean/hash_state.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_clean/params.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_clean/sha256.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_clean/sha256.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_clean/sign.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_clean/thash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_clean/thash_sha256_simple.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_clean/utils.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_clean/utils.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_clean/wots.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_clean/wots.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_avx2/LICENSE delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_avx2/address.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_avx2/address.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_avx2/api.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_avx2/fors.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_avx2/fors.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_avx2/hash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_avx2/hash_sha256.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_avx2/hash_sha256x8.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_avx2/hash_state.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_avx2/hashx8.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_avx2/params.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_avx2/sha256.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_avx2/sha256.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_avx2/sha256avx.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_avx2/sha256avx.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_avx2/sha256x8.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_avx2/sha256x8.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_avx2/sign.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_avx2/thash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_avx2/thash_sha256_robust.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_avx2/thash_sha256_robustx8.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_avx2/thashx8.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_avx2/utils.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_avx2/utils.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_avx2/utilsx8.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_avx2/utilsx8.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_avx2/wots.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_avx2/wots.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_clean/LICENSE delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_clean/address.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_clean/address.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_clean/api.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_clean/fors.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_clean/fors.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_clean/hash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_clean/hash_sha256.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_clean/hash_state.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_clean/params.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_clean/sha256.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_clean/sha256.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_clean/sign.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_clean/thash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_clean/thash_sha256_robust.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_clean/utils.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_clean/utils.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_clean/wots.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_clean/wots.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_avx2/LICENSE delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_avx2/address.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_avx2/address.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_avx2/api.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_avx2/fors.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_avx2/fors.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_avx2/hash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_avx2/hash_sha256.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_avx2/hash_sha256x8.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_avx2/hash_state.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_avx2/hashx8.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_avx2/params.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_avx2/sha256.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_avx2/sha256.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_avx2/sha256avx.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_avx2/sha256avx.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_avx2/sha256x8.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_avx2/sha256x8.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_avx2/sign.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_avx2/thash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_avx2/thash_sha256_simple.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_avx2/thash_sha256_simplex8.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_avx2/thashx8.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_avx2/utils.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_avx2/utils.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_avx2/utilsx8.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_avx2/utilsx8.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_avx2/wots.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_avx2/wots.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_clean/LICENSE delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_clean/address.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_clean/address.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_clean/api.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_clean/fors.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_clean/fors.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_clean/hash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_clean/hash_sha256.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_clean/hash_state.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_clean/params.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_clean/sha256.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_clean/sha256.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_clean/sign.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_clean/thash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_clean/thash_sha256_simple.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_clean/utils.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_clean/utils.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_clean/wots.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_clean/wots.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_avx2/LICENSE delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_avx2/address.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_avx2/address.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_avx2/api.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_avx2/fors.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_avx2/fors.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_avx2/hash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_avx2/hash_sha256.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_avx2/hash_sha256x8.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_avx2/hash_state.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_avx2/hashx8.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_avx2/params.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_avx2/sha256.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_avx2/sha256.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_avx2/sha256avx.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_avx2/sha256avx.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_avx2/sha256x8.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_avx2/sha256x8.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_avx2/sign.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_avx2/thash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_avx2/thash_sha256_robust.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_avx2/thash_sha256_robustx8.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_avx2/thashx8.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_avx2/utils.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_avx2/utils.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_avx2/utilsx8.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_avx2/utilsx8.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_avx2/wots.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_avx2/wots.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_clean/LICENSE delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_clean/address.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_clean/address.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_clean/api.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_clean/fors.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_clean/fors.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_clean/hash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_clean/hash_sha256.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_clean/hash_state.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_clean/params.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_clean/sha256.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_clean/sha256.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_clean/sign.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_clean/thash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_clean/thash_sha256_robust.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_clean/utils.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_clean/utils.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_clean/wots.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_clean/wots.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_avx2/LICENSE delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_avx2/address.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_avx2/address.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_avx2/api.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_avx2/fors.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_avx2/fors.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_avx2/hash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_avx2/hash_sha256.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_avx2/hash_sha256x8.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_avx2/hash_state.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_avx2/hashx8.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_avx2/params.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_avx2/sha256.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_avx2/sha256.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_avx2/sha256avx.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_avx2/sha256avx.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_avx2/sha256x8.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_avx2/sha256x8.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_avx2/sign.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_avx2/thash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_avx2/thash_sha256_simple.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_avx2/thash_sha256_simplex8.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_avx2/thashx8.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_avx2/utils.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_avx2/utils.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_avx2/utilsx8.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_avx2/utilsx8.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_avx2/wots.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_avx2/wots.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_clean/LICENSE delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_clean/address.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_clean/address.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_clean/api.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_clean/fors.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_clean/fors.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_clean/hash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_clean/hash_sha256.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_clean/hash_state.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_clean/params.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_clean/sha256.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_clean/sha256.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_clean/sign.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_clean/thash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_clean/thash_sha256_simple.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_clean/utils.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_clean/utils.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_clean/wots.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_clean/wots.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_avx2/LICENSE delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_avx2/address.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_avx2/address.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_avx2/api.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_avx2/fors.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_avx2/fors.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_avx2/hash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_avx2/hash_sha256.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_avx2/hash_sha256x8.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_avx2/hash_state.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_avx2/hashx8.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_avx2/params.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_avx2/sha256.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_avx2/sha256.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_avx2/sha256avx.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_avx2/sha256avx.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_avx2/sha256x8.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_avx2/sha256x8.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_avx2/sign.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_avx2/thash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_avx2/thash_sha256_robust.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_avx2/thash_sha256_robustx8.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_avx2/thashx8.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_avx2/utils.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_avx2/utils.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_avx2/utilsx8.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_avx2/utilsx8.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_avx2/wots.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_avx2/wots.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_clean/LICENSE delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_clean/address.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_clean/address.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_clean/api.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_clean/fors.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_clean/fors.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_clean/hash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_clean/hash_sha256.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_clean/hash_state.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_clean/params.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_clean/sha256.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_clean/sha256.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_clean/sign.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_clean/thash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_clean/thash_sha256_robust.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_clean/utils.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_clean/utils.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_clean/wots.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_clean/wots.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_avx2/LICENSE delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_avx2/address.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_avx2/address.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_avx2/api.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_avx2/fors.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_avx2/fors.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_avx2/hash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_avx2/hash_sha256.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_avx2/hash_sha256x8.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_avx2/hash_state.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_avx2/hashx8.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_avx2/params.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_avx2/sha256.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_avx2/sha256.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_avx2/sha256avx.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_avx2/sha256avx.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_avx2/sha256x8.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_avx2/sha256x8.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_avx2/sign.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_avx2/thash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_avx2/thash_sha256_simple.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_avx2/thash_sha256_simplex8.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_avx2/thashx8.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_avx2/utils.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_avx2/utils.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_avx2/utilsx8.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_avx2/utilsx8.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_avx2/wots.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_avx2/wots.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_clean/LICENSE delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_clean/address.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_clean/address.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_clean/api.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_clean/fors.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_clean/fors.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_clean/hash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_clean/hash_sha256.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_clean/hash_state.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_clean/params.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_clean/sha256.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_clean/sha256.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_clean/sign.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_clean/thash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_clean/thash_sha256_simple.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_clean/utils.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_clean/utils.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_clean/wots.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_clean/wots.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/LICENSE delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/address.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/address.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/api.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/context.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/context_shake.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/f1600x2.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/f1600x2.s delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/f1600x2_const.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/fips202x2.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/fips202x2.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/fors.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/fors.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/hash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/hash_shake.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/hash_shakex2.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/hashx2.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/merkle.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/merkle.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/nistapi.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/params.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/shake_offsets.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/sign.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/thash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/thash_shake_robustx2.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/thashx2.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/utils.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/utils.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/utilsx2.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/utilsx2.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/wots.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/wots.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/wotsx2.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/LICENSE delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/address.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/address.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/api.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/context.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/context_shake.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/fips202x4.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/fips202x4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/fors.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/fors.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/hash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/hash_shake.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/hash_shakex4.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/hashx4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/merkle.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/merkle.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/nistapi.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/params.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/shake_offsets.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/sign.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/thash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/thash_shake_robust.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/thash_shake_robustx4.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/thashx4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/utils.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/utils.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/utilsx4.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/utilsx4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/wots.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/wots.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/wotsx4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/LICENSE delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/address.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/address.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/api.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/context.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/context_shake.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/fors.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/fors.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/hash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/hash_shake.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/merkle.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/merkle.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/nistapi.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/params.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/shake_offsets.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/sign.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/thash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/thash_shake_robust.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/utils.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/utils.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/utilsx1.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/utilsx1.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/wots.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/wots.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/wotsx1.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/wotsx1.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/LICENSE delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/address.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/address.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/api.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/context.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/context_shake.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/f1600x2.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/f1600x2.s delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/f1600x2_const.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/fips202x2.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/fips202x2.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/fors.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/fors.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/hash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/hash_shake.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/hash_shakex2.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/hashx2.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/merkle.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/merkle.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/nistapi.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/params.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/shake_offsets.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/sign.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/thash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/thash_shake_robustx2.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/thashx2.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/utils.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/utils.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/utilsx2.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/utilsx2.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/wots.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/wots.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/wotsx2.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/LICENSE delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/address.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/address.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/api.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/context.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/context_shake.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/fips202x4.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/fips202x4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/fors.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/fors.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/hash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/hash_shake.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/hash_shakex4.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/hashx4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/merkle.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/merkle.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/nistapi.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/params.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/shake_offsets.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/sign.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/thash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/thash_shake_robust.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/thash_shake_robustx4.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/thashx4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/utils.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/utils.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/utilsx4.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/utilsx4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/wots.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/wots.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/wotsx4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/LICENSE delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/address.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/address.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/api.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/context.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/context_shake.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/fors.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/fors.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/hash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/hash_shake.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/merkle.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/merkle.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/nistapi.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/params.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/shake_offsets.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/sign.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/thash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/thash_shake_robust.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/utils.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/utils.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/utilsx1.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/utilsx1.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/wots.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/wots.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/wotsx1.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/wotsx1.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/LICENSE delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/address.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/address.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/api.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/context.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/context_shake.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/f1600x2.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/f1600x2.s delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/f1600x2_const.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/fips202x2.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/fips202x2.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/fors.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/fors.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/hash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/hash_shake.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/hash_shakex2.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/hashx2.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/merkle.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/merkle.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/nistapi.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/params.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/shake_offsets.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/sign.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/thash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/thash_shake_robustx2.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/thashx2.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/utils.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/utils.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/utilsx2.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/utilsx2.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/wots.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/wots.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/wotsx2.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/LICENSE delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/address.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/address.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/api.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/context.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/context_shake.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/fips202x4.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/fips202x4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/fors.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/fors.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/hash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/hash_shake.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/hash_shakex4.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/hashx4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/merkle.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/merkle.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/nistapi.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/params.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/shake_offsets.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/sign.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/thash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/thash_shake_robust.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/thash_shake_robustx4.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/thashx4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/utils.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/utils.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/utilsx4.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/utilsx4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/wots.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/wots.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/wotsx4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/LICENSE delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/address.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/address.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/api.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/context.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/context_shake.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/fors.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/fors.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/hash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/hash_shake.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/merkle.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/merkle.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/nistapi.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/params.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/shake_offsets.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/sign.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/thash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/thash_shake_robust.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/utils.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/utils.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/utilsx1.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/utilsx1.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/wots.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/wots.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/wotsx1.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/wotsx1.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/LICENSE delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/address.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/address.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/api.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/context.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/context_shake.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/f1600x2.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/f1600x2.s delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/f1600x2_const.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/fips202x2.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/fips202x2.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/fors.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/fors.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/hash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/hash_shake.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/hash_shakex2.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/hashx2.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/merkle.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/merkle.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/nistapi.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/params.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/shake_offsets.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/sign.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/thash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/thash_shake_robustx2.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/thashx2.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/utils.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/utils.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/utilsx2.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/utilsx2.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/wots.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/wots.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/wotsx2.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/LICENSE delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/address.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/address.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/api.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/context.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/context_shake.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/fips202x4.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/fips202x4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/fors.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/fors.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/hash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/hash_shake.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/hash_shakex4.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/hashx4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/merkle.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/merkle.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/nistapi.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/params.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/shake_offsets.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/sign.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/thash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/thash_shake_robust.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/thash_shake_robustx4.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/thashx4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/utils.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/utils.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/utilsx4.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/utilsx4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/wots.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/wots.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/wotsx4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/LICENSE delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/address.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/address.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/api.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/context.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/context_shake.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/fors.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/fors.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/hash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/hash_shake.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/merkle.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/merkle.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/nistapi.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/params.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/shake_offsets.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/sign.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/thash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/thash_shake_robust.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/utils.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/utils.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/utilsx1.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/utilsx1.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/wots.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/wots.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/wotsx1.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/wotsx1.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/LICENSE delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/address.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/address.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/api.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/context.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/context_shake.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/f1600x2.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/f1600x2.s delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/f1600x2_const.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/fips202x2.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/fips202x2.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/fors.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/fors.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/hash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/hash_shake.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/hash_shakex2.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/hashx2.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/merkle.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/merkle.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/nistapi.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/params.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/shake_offsets.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/sign.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/thash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/thash_shake_robustx2.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/thashx2.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/utils.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/utils.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/utilsx2.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/utilsx2.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/wots.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/wots.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/wotsx2.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/LICENSE delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/address.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/address.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/api.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/context.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/context_shake.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/fips202x4.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/fips202x4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/fors.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/fors.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/hash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/hash_shake.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/hash_shakex4.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/hashx4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/merkle.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/merkle.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/nistapi.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/params.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/shake_offsets.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/sign.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/thash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/thash_shake_robust.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/thash_shake_robustx4.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/thashx4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/utils.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/utils.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/utilsx4.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/utilsx4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/wots.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/wots.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/wotsx4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/LICENSE delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/address.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/address.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/api.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/context.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/context_shake.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/fors.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/fors.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/hash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/hash_shake.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/merkle.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/merkle.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/nistapi.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/params.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/shake_offsets.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/sign.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/thash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/thash_shake_robust.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/utils.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/utils.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/utilsx1.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/utilsx1.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/wots.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/wots.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/wotsx1.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/wotsx1.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/LICENSE delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/address.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/address.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/api.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/context.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/context_shake.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/f1600x2.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/f1600x2.s delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/f1600x2_const.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/fips202x2.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/fips202x2.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/fors.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/fors.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/hash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/hash_shake.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/hash_shakex2.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/hashx2.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/merkle.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/merkle.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/nistapi.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/params.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/shake_offsets.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/sign.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/thash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/thash_shake_robustx2.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/thashx2.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/utils.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/utils.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/utilsx2.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/utilsx2.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/wots.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/wots.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/wotsx2.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/LICENSE delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/address.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/address.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/api.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/context.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/context_shake.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/fips202x4.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/fips202x4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/fors.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/fors.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/hash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/hash_shake.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/hash_shakex4.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/hashx4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/merkle.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/merkle.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/nistapi.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/params.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/shake_offsets.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/sign.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/thash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/thash_shake_robust.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/thash_shake_robustx4.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/thashx4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/utils.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/utils.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/utilsx4.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/utilsx4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/wots.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/wots.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/wotsx4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/LICENSE delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/address.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/address.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/api.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/context.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/context_shake.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/fors.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/fors.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/hash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/hash_shake.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/merkle.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/merkle.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/nistapi.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/params.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/shake_offsets.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/sign.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/thash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/thash_shake_robust.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/utils.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/utils.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/utilsx1.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/utilsx1.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/wots.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/wots.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/wotsx1.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/wotsx1.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_avx2/LICENSE delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_avx2/address.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_avx2/address.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_avx2/api.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_avx2/fors.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_avx2/fors.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_avx2/hash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_avx2/hash_shake256.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_avx2/hash_shake256x4.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_avx2/hash_state.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_avx2/hashx4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_avx2/params.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_avx2/sign.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_avx2/thash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_avx2/thash_shake256_robust.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_avx2/thash_shake256_robustx4.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_avx2/thashx4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_avx2/utils.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_avx2/utils.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_avx2/utilsx4.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_avx2/utilsx4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_avx2/wots.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_avx2/wots.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_clean/LICENSE delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_clean/address.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_clean/address.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_clean/api.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_clean/fors.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_clean/fors.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_clean/hash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_clean/hash_shake256.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_clean/hash_state.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_clean/params.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_clean/sign.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_clean/thash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_clean/thash_shake256_robust.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_clean/utils.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_clean/utils.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_clean/wots.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_clean/wots.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_avx2/LICENSE delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_avx2/address.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_avx2/address.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_avx2/api.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_avx2/fors.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_avx2/fors.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_avx2/hash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_avx2/hash_shake256.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_avx2/hash_shake256x4.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_avx2/hash_state.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_avx2/hashx4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_avx2/params.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_avx2/sign.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_avx2/thash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_avx2/thash_shake256_simple.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_avx2/thash_shake256_simplex4.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_avx2/thashx4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_avx2/utils.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_avx2/utils.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_avx2/utilsx4.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_avx2/utilsx4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_avx2/wots.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_avx2/wots.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_clean/LICENSE delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_clean/address.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_clean/address.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_clean/api.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_clean/fors.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_clean/fors.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_clean/hash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_clean/hash_shake256.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_clean/hash_state.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_clean/params.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_clean/sign.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_clean/thash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_clean/thash_shake256_simple.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_clean/utils.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_clean/utils.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_clean/wots.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_clean/wots.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_avx2/LICENSE delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_avx2/address.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_avx2/address.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_avx2/api.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_avx2/fors.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_avx2/fors.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_avx2/hash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_avx2/hash_shake256.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_avx2/hash_shake256x4.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_avx2/hash_state.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_avx2/hashx4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_avx2/params.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_avx2/sign.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_avx2/thash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_avx2/thash_shake256_robust.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_avx2/thash_shake256_robustx4.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_avx2/thashx4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_avx2/utils.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_avx2/utils.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_avx2/utilsx4.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_avx2/utilsx4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_avx2/wots.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_avx2/wots.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_clean/LICENSE delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_clean/address.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_clean/address.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_clean/api.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_clean/fors.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_clean/fors.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_clean/hash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_clean/hash_shake256.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_clean/hash_state.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_clean/params.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_clean/sign.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_clean/thash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_clean/thash_shake256_robust.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_clean/utils.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_clean/utils.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_clean/wots.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_clean/wots.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_avx2/LICENSE delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_avx2/address.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_avx2/address.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_avx2/api.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_avx2/fors.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_avx2/fors.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_avx2/hash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_avx2/hash_shake256.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_avx2/hash_shake256x4.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_avx2/hash_state.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_avx2/hashx4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_avx2/params.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_avx2/sign.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_avx2/thash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_avx2/thash_shake256_simple.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_avx2/thash_shake256_simplex4.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_avx2/thashx4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_avx2/utils.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_avx2/utils.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_avx2/utilsx4.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_avx2/utilsx4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_avx2/wots.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_avx2/wots.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_clean/LICENSE delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_clean/address.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_clean/address.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_clean/api.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_clean/fors.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_clean/fors.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_clean/hash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_clean/hash_shake256.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_clean/hash_state.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_clean/params.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_clean/sign.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_clean/thash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_clean/thash_shake256_simple.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_clean/utils.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_clean/utils.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_clean/wots.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_clean/wots.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_avx2/LICENSE delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_avx2/address.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_avx2/address.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_avx2/api.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_avx2/fors.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_avx2/fors.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_avx2/hash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_avx2/hash_shake256.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_avx2/hash_shake256x4.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_avx2/hash_state.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_avx2/hashx4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_avx2/params.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_avx2/sign.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_avx2/thash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_avx2/thash_shake256_robust.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_avx2/thash_shake256_robustx4.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_avx2/thashx4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_avx2/utils.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_avx2/utils.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_avx2/utilsx4.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_avx2/utilsx4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_avx2/wots.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_avx2/wots.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_clean/LICENSE delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_clean/address.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_clean/address.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_clean/api.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_clean/fors.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_clean/fors.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_clean/hash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_clean/hash_shake256.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_clean/hash_state.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_clean/params.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_clean/sign.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_clean/thash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_clean/thash_shake256_robust.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_clean/utils.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_clean/utils.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_clean/wots.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_clean/wots.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_avx2/LICENSE delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_avx2/address.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_avx2/address.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_avx2/api.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_avx2/fors.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_avx2/fors.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_avx2/hash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_avx2/hash_shake256.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_avx2/hash_shake256x4.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_avx2/hash_state.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_avx2/hashx4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_avx2/params.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_avx2/sign.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_avx2/thash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_avx2/thash_shake256_simple.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_avx2/thash_shake256_simplex4.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_avx2/thashx4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_avx2/utils.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_avx2/utils.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_avx2/utilsx4.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_avx2/utilsx4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_avx2/wots.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_avx2/wots.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/LICENSE delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/address.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/address.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/api.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/fors.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/fors.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/hash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/hash_shake256.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/hash_state.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/params.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/sign.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/thash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/thash_shake256_simple.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/utils.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/utils.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/wots.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/wots.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_avx2/LICENSE delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_avx2/address.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_avx2/address.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_avx2/api.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_avx2/fors.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_avx2/fors.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_avx2/hash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_avx2/hash_shake256.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_avx2/hash_shake256x4.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_avx2/hash_state.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_avx2/hashx4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_avx2/params.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_avx2/sign.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_avx2/thash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_avx2/thash_shake256_robust.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_avx2/thash_shake256_robustx4.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_avx2/thashx4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_avx2/utils.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_avx2/utils.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_avx2/utilsx4.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_avx2/utilsx4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_avx2/wots.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_avx2/wots.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_clean/LICENSE delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_clean/address.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_clean/address.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_clean/api.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_clean/fors.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_clean/fors.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_clean/hash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_clean/hash_shake256.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_clean/hash_state.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_clean/params.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_clean/sign.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_clean/thash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_clean/thash_shake256_robust.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_clean/utils.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_clean/utils.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_clean/wots.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_clean/wots.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_avx2/LICENSE delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_avx2/address.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_avx2/address.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_avx2/api.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_avx2/fors.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_avx2/fors.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_avx2/hash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_avx2/hash_shake256.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_avx2/hash_shake256x4.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_avx2/hash_state.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_avx2/hashx4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_avx2/params.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_avx2/sign.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_avx2/thash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_avx2/thash_shake256_simple.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_avx2/thash_shake256_simplex4.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_avx2/thashx4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_avx2/utils.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_avx2/utils.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_avx2/utilsx4.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_avx2/utilsx4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_avx2/wots.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_avx2/wots.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_clean/LICENSE delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_clean/address.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_clean/address.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_clean/api.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_clean/fors.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_clean/fors.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_clean/hash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_clean/hash_shake256.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_clean/hash_state.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_clean/params.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_clean/sign.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_clean/thash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_clean/thash_shake256_simple.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_clean/utils.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_clean/utils.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_clean/wots.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_clean/wots.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_avx2/LICENSE delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_avx2/address.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_avx2/address.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_avx2/api.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_avx2/fors.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_avx2/fors.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_avx2/hash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_avx2/hash_shake256.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_avx2/hash_shake256x4.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_avx2/hash_state.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_avx2/hashx4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_avx2/params.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_avx2/sign.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_avx2/thash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_avx2/thash_shake256_robust.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_avx2/thash_shake256_robustx4.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_avx2/thashx4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_avx2/utils.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_avx2/utils.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_avx2/utilsx4.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_avx2/utilsx4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_avx2/wots.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_avx2/wots.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_clean/LICENSE delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_clean/address.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_clean/address.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_clean/api.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_clean/fors.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_clean/fors.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_clean/hash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_clean/hash_shake256.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_clean/hash_state.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_clean/params.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_clean/sign.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_clean/thash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_clean/thash_shake256_robust.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_clean/utils.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_clean/utils.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_clean/wots.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_clean/wots.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_avx2/LICENSE delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_avx2/address.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_avx2/address.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_avx2/api.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_avx2/fors.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_avx2/fors.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_avx2/hash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_avx2/hash_shake256.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_avx2/hash_shake256x4.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_avx2/hash_state.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_avx2/hashx4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_avx2/params.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_avx2/sign.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_avx2/thash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_avx2/thash_shake256_simple.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_avx2/thash_shake256_simplex4.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_avx2/thashx4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_avx2/utils.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_avx2/utils.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_avx2/utilsx4.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_avx2/utilsx4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_avx2/wots.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_avx2/wots.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_clean/LICENSE delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_clean/address.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_clean/address.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_clean/api.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_clean/fors.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_clean/fors.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_clean/hash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_clean/hash_shake256.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_clean/hash_state.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_clean/params.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_clean/sign.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_clean/thash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_clean/thash_shake256_simple.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_clean/utils.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_clean/utils.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_clean/wots.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_clean/wots.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_avx2/LICENSE delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_avx2/address.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_avx2/address.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_avx2/api.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_avx2/fors.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_avx2/fors.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_avx2/hash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_avx2/hash_shake256.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_avx2/hash_shake256x4.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_avx2/hash_state.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_avx2/hashx4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_avx2/params.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_avx2/sign.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_avx2/thash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_avx2/thash_shake256_robust.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_avx2/thash_shake256_robustx4.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_avx2/thashx4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_avx2/utils.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_avx2/utils.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_avx2/utilsx4.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_avx2/utilsx4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_avx2/wots.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_avx2/wots.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_clean/LICENSE delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_clean/address.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_clean/address.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_clean/api.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_clean/fors.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_clean/fors.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_clean/hash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_clean/hash_shake256.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_clean/hash_state.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_clean/params.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_clean/sign.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_clean/thash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_clean/thash_shake256_robust.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_clean/utils.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_clean/utils.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_clean/wots.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_clean/wots.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_avx2/LICENSE delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_avx2/address.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_avx2/address.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_avx2/api.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_avx2/fors.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_avx2/fors.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_avx2/hash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_avx2/hash_shake256.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_avx2/hash_shake256x4.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_avx2/hash_state.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_avx2/hashx4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_avx2/params.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_avx2/sign.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_avx2/thash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_avx2/thash_shake256_simple.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_avx2/thash_shake256_simplex4.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_avx2/thashx4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_avx2/utils.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_avx2/utils.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_avx2/utilsx4.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_avx2/utilsx4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_avx2/wots.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_avx2/wots.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_clean/LICENSE delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_clean/address.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_clean/address.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_clean/api.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_clean/fors.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_clean/fors.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_clean/hash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_clean/hash_shake256.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_clean/hash_state.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_clean/params.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_clean/sign.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_clean/thash.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_clean/thash_shake256_simple.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_clean/utils.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_clean/utils.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_clean/wots.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_clean/wots.h delete mode 100644 src/sig/sphincs/sig_sphincs_haraka_128f_robust.c delete mode 100644 src/sig/sphincs/sig_sphincs_haraka_128f_simple.c delete mode 100644 src/sig/sphincs/sig_sphincs_haraka_128s_robust.c delete mode 100644 src/sig/sphincs/sig_sphincs_haraka_128s_simple.c delete mode 100644 src/sig/sphincs/sig_sphincs_haraka_192f_robust.c delete mode 100644 src/sig/sphincs/sig_sphincs_haraka_192f_simple.c delete mode 100644 src/sig/sphincs/sig_sphincs_haraka_192s_robust.c delete mode 100644 src/sig/sphincs/sig_sphincs_haraka_192s_simple.c delete mode 100644 src/sig/sphincs/sig_sphincs_haraka_256f_robust.c delete mode 100644 src/sig/sphincs/sig_sphincs_haraka_256f_simple.c delete mode 100644 src/sig/sphincs/sig_sphincs_haraka_256s_robust.c delete mode 100644 src/sig/sphincs/sig_sphincs_haraka_256s_simple.c delete mode 100644 src/sig/sphincs/sig_sphincs_sha256_128f_robust.c delete mode 100644 src/sig/sphincs/sig_sphincs_sha256_128s_robust.c delete mode 100644 src/sig/sphincs/sig_sphincs_sha256_192f_robust.c delete mode 100644 src/sig/sphincs/sig_sphincs_sha256_192s_robust.c delete mode 100644 src/sig/sphincs/sig_sphincs_sha256_256f_robust.c delete mode 100644 src/sig/sphincs/sig_sphincs_sha256_256s_robust.c delete mode 100644 src/sig/sphincs/sig_sphincs_shake256_128f_robust.c delete mode 100644 src/sig/sphincs/sig_sphincs_shake256_128s_robust.c delete mode 100644 src/sig/sphincs/sig_sphincs_shake256_192f_robust.c delete mode 100644 src/sig/sphincs/sig_sphincs_shake256_192s_robust.c delete mode 100644 src/sig/sphincs/sig_sphincs_shake256_256f_robust.c delete mode 100644 src/sig/sphincs/sig_sphincs_shake256_256s_robust.c diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/LICENSE b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/LICENSE deleted file mode 100644 index 670154e353..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/LICENSE +++ /dev/null @@ -1,116 +0,0 @@ -CC0 1.0 Universal - -Statement of Purpose - -The laws of most jurisdictions throughout the world automatically confer -exclusive Copyright and Related Rights (defined below) upon the creator and -subsequent owner(s) (each and all, an "owner") of an original work of -authorship and/or a database (each, a "Work"). - -Certain owners wish to permanently relinquish those rights to a Work for the -purpose of contributing to a commons of creative, cultural and scientific -works ("Commons") that the public can reliably and without fear of later -claims of infringement build upon, modify, incorporate in other works, reuse -and redistribute as freely as possible in any form whatsoever and for any -purposes, including without limitation commercial purposes. These owners may -contribute to the Commons to promote the ideal of a free culture and the -further production of creative, cultural and scientific works, or to gain -reputation or greater distribution for their Work in part through the use and -efforts of others. - -For these and/or other purposes and motivations, and without any expectation -of additional consideration or compensation, the person associating CC0 with a -Work (the "Affirmer"), to the extent that he or she is an owner of Copyright -and Related Rights in the Work, voluntarily elects to apply CC0 to the Work -and publicly distribute the Work under its terms, with knowledge of his or her -Copyright and Related Rights in the Work and the meaning and intended legal -effect of CC0 on those rights. - -1. Copyright and Related Rights. A Work made available under CC0 may be -protected by copyright and related or neighboring rights ("Copyright and -Related Rights"). Copyright and Related Rights include, but are not limited -to, the following: - - i. the right to reproduce, adapt, distribute, perform, display, communicate, - and translate a Work; - - ii. moral rights retained by the original author(s) and/or performer(s); - - iii. publicity and privacy rights pertaining to a person's image or likeness - depicted in a Work; - - iv. rights protecting against unfair competition in regards to a Work, - subject to the limitations in paragraph 4(a), below; - - v. rights protecting the extraction, dissemination, use and reuse of data in - a Work; - - vi. database rights (such as those arising under Directive 96/9/EC of the - European Parliament and of the Council of 11 March 1996 on the legal - protection of databases, and under any national implementation thereof, - including any amended or successor version of such directive); and - - vii. other similar, equivalent or corresponding rights throughout the world - based on applicable law or treaty, and any national implementations thereof. - -2. Waiver. To the greatest extent permitted by, but not in contravention of, -applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and -unconditionally waives, abandons, and surrenders all of Affirmer's Copyright -and Related Rights and associated claims and causes of action, whether now -known or unknown (including existing as well as future claims and causes of -action), in the Work (i) in all territories worldwide, (ii) for the maximum -duration provided by applicable law or treaty (including future time -extensions), (iii) in any current or future medium and for any number of -copies, and (iv) for any purpose whatsoever, including without limitation -commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes -the Waiver for the benefit of each member of the public at large and to the -detriment of Affirmer's heirs and successors, fully intending that such Waiver -shall not be subject to revocation, rescission, cancellation, termination, or -any other legal or equitable action to disrupt the quiet enjoyment of the Work -by the public as contemplated by Affirmer's express Statement of Purpose. - -3. Public License Fallback. Should any part of the Waiver for any reason be -judged legally invalid or ineffective under applicable law, then the Waiver -shall be preserved to the maximum extent permitted taking into account -Affirmer's express Statement of Purpose. In addition, to the extent the Waiver -is so judged Affirmer hereby grants to each affected person a royalty-free, -non transferable, non sublicensable, non exclusive, irrevocable and -unconditional license to exercise Affirmer's Copyright and Related Rights in -the Work (i) in all territories worldwide, (ii) for the maximum duration -provided by applicable law or treaty (including future time extensions), (iii) -in any current or future medium and for any number of copies, and (iv) for any -purpose whatsoever, including without limitation commercial, advertising or -promotional purposes (the "License"). The License shall be deemed effective as -of the date CC0 was applied by Affirmer to the Work. Should any part of the -License for any reason be judged legally invalid or ineffective under -applicable law, such partial invalidity or ineffectiveness shall not -invalidate the remainder of the License, and in such case Affirmer hereby -affirms that he or she will not (i) exercise any of his or her remaining -Copyright and Related Rights in the Work or (ii) assert any associated claims -and causes of action with respect to the Work, in either case contrary to -Affirmer's express Statement of Purpose. - -4. Limitations and Disclaimers. - - a. No trademark or patent rights held by Affirmer are waived, abandoned, - surrendered, licensed or otherwise affected by this document. - - b. Affirmer offers the Work as-is and makes no representations or warranties - of any kind concerning the Work, express, implied, statutory or otherwise, - including without limitation warranties of title, merchantability, fitness - for a particular purpose, non infringement, or the absence of latent or - other defects, accuracy, or the present or absence of errors, whether or not - discoverable, all to the greatest extent permissible under applicable law. - - c. Affirmer disclaims responsibility for clearing rights of other persons - that may apply to the Work or any use thereof, including without limitation - any person's Copyright and Related Rights in the Work. Further, Affirmer - disclaims responsibility for obtaining any necessary consents, permissions - or other rights required for any use of the Work. - - d. Affirmer understands and acknowledges that Creative Commons is not a - party to this document and has no duty or obligation with respect to this - CC0 or use of the Work. - -For more information, please see - diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/address.c b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/address.c deleted file mode 100644 index b956e9cb29..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/address.c +++ /dev/null @@ -1,91 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "utils.h" - -/* - * Specify which level of Merkle tree (the "layer") we're working on - */ -void set_layer_addr(uint32_t addr[8], uint32_t layer) { - ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; -} - -/* - * Specify which Merkle tree within the level (the "tree address") we're working on - */ -void set_tree_addr(uint32_t addr[8], uint64_t tree) { - ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); -} - -/* - * Specify the reason we'll use this address structure for, that is, what - * hash will we compute with it. This is used so that unrelated types of - * hashes don't accidentally get the same address structure. The type will be - * one of the SPX_ADDR_TYPE constants - */ -void set_type(uint32_t addr[8], uint32_t type) { - ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; -} - -/* - * Copy the layer and tree fields of the address structure. This is used - * when we're doing multiple types of hashes within the same Merkle tree - */ -void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { - memcpy( out, in, SPX_OFFSET_TREE + 8 ); -} - -/* These functions are used for OTS addresses. */ - -/* - * Specify which Merkle leaf we're working on; that is, which OTS keypair - * we're talking about. - */ -void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { - ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; -} - -/* - * Copy the layer, tree and keypair fields of the address structure. This is - * used when we're doing multiple things within the same OTS keypair - */ -void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { - memcpy( out, in, SPX_OFFSET_TREE + 8 ); - ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; -} - -/* - * Specify which Merkle chain within the OTS we're working with - * (the chain address) - */ -void set_chain_addr(uint32_t addr[8], uint32_t chain) { - ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; -} - -/* - * Specify where in the Merkle chain we are -* (the hash address) - */ -void set_hash_addr(uint32_t addr[8], uint32_t hash) { - ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; -} - -/* These functions are used for all hash tree addresses (including FORS). */ - -/* - * Specify the height of the node in the Merkle/FORS tree we are in - * (the tree height) - */ -void set_tree_height(uint32_t addr[8], uint32_t tree_height) { - ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; -} - -/* - * Specify the distance from the left edge of the node in the Merkle/FORS tree - * (the tree index) - */ -void set_tree_index(uint32_t addr[8], uint32_t tree_index) { - u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/address.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/address.h deleted file mode 100644 index 24a84eb40c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/address.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef SPX_ADDRESS_H -#define SPX_ADDRESS_H - -#include - -#include "params.h" - -/* The hash types that are passed to set_type */ -#define SPX_ADDR_TYPE_WOTS 0 -#define SPX_ADDR_TYPE_WOTSPK 1 -#define SPX_ADDR_TYPE_HASHTREE 2 -#define SPX_ADDR_TYPE_FORSTREE 3 -#define SPX_ADDR_TYPE_FORSPK 4 -#define SPX_ADDR_TYPE_WOTSPRF 5 -#define SPX_ADDR_TYPE_FORSPRF 6 - -#define set_layer_addr SPX_NAMESPACE(set_layer_addr) -void set_layer_addr(uint32_t addr[8], uint32_t layer); - -#define set_tree_addr SPX_NAMESPACE(set_tree_addr) -void set_tree_addr(uint32_t addr[8], uint64_t tree); - -#define set_type SPX_NAMESPACE(set_type) -void set_type(uint32_t addr[8], uint32_t type); - -/* Copies the layer and tree part of one address into the other */ -#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) -void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for WOTS and FORS addresses. */ - -#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) -void set_keypair_addr(uint32_t addr[8], uint32_t keypair); - -#define set_chain_addr SPX_NAMESPACE(set_chain_addr) -void set_chain_addr(uint32_t addr[8], uint32_t chain); - -#define set_hash_addr SPX_NAMESPACE(set_hash_addr) -void set_hash_addr(uint32_t addr[8], uint32_t hash); - -#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) -void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for all hash tree addresses (including FORS). */ - -#define set_tree_height SPX_NAMESPACE(set_tree_height) -void set_tree_height(uint32_t addr[8], uint32_t tree_height); - -#define set_tree_index SPX_NAMESPACE(set_tree_index) -void set_tree_index(uint32_t addr[8], uint32_t tree_index); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/api.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/api.h deleted file mode 100644 index 5eabcbd2d7..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/api.h +++ /dev/null @@ -1,77 +0,0 @@ -#ifndef PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_API_H -#define PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_API_H - -#include -#include - -#define PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_CRYPTO_ALGNAME "SPHINCS+-haraka-128f-robust" - -#define PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_CRYPTO_SECRETKEYBYTES 64 -#define PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_CRYPTO_PUBLICKEYBYTES 32 -#define PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_CRYPTO_BYTES 17088 - -#define PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_CRYPTO_SEEDBYTES 48 - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, - const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk); -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/context.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/context.h deleted file mode 100644 index f03446b9cb..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/context.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef SPX_CONTEXT_H -#define SPX_CONTEXT_H - -#include - -#include "immintrin.h" -#include "params.h" - -typedef struct { - uint8_t pub_seed[SPX_N]; - uint8_t sk_seed[SPX_N]; - - __m128i rc[40]; -} spx_ctx; - -#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) -void initialize_hash_function(spx_ctx *ctx); - -#define free_hash_function SPX_NAMESPACE(free_hash_function) -void free_hash_function(spx_ctx *ctx); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/context_haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/context_haraka.c deleted file mode 100644 index f1cd7e3664..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/context_haraka.c +++ /dev/null @@ -1,11 +0,0 @@ -#include "context.h" -#include "haraka.h" - -void initialize_hash_function(spx_ctx *ctx) { - tweak_constants(ctx); -} - -// we don't support heap-based haraka right now -void free_hash_function(spx_ctx *ctx) { - (void)ctx; // suppress unused variable warnings -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/fors.c b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/fors.c deleted file mode 100644 index f1b0639cfc..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/fors.c +++ /dev/null @@ -1,202 +0,0 @@ -#include -#include -#include - -#include "fors.h" - -#include "address.h" -#include "hash.h" -#include "hashx4.h" -#include "thash.h" -#include "thashx4.h" -#include "utils.h" -#include "utilsx4.h" - -static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, - uint32_t fors_leaf_addr[8]) { - prf_addr(sk, ctx, fors_leaf_addr); -} - -static void fors_gen_skx4(unsigned char *sk0, - unsigned char *sk1, - unsigned char *sk2, - unsigned char *sk3, const spx_ctx *ctx, - uint32_t fors_leaf_addrx4[4 * 8]) { - prf_addrx4(sk0, sk1, sk2, sk3, - ctx, fors_leaf_addrx4); -} - -static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, - const spx_ctx *ctx, - uint32_t fors_leaf_addr[8]) { - thash(leaf, sk, 1, ctx, fors_leaf_addr); -} - -static void fors_sk_to_leafx4(unsigned char *leaf0, - unsigned char *leaf1, - unsigned char *leaf2, - unsigned char *leaf3, - const unsigned char *sk0, - const unsigned char *sk1, - const unsigned char *sk2, - const unsigned char *sk3, - const spx_ctx *ctx, - uint32_t fors_leaf_addrx4[4 * 8]) { - thashx4(leaf0, leaf1, leaf2, leaf3, - sk0, sk1, sk2, sk3, - 1, ctx, fors_leaf_addrx4); -} - -struct fors_gen_leaf_info { - uint32_t leaf_addrx[4 * 8]; -}; - -static void fors_gen_leafx4(unsigned char *leaf, - const spx_ctx *ctx, - uint32_t addr_idx, void *info) { - struct fors_gen_leaf_info *fors_info = info; - uint32_t *fors_leaf_addrx4 = fors_info->leaf_addrx; - unsigned int j; - - /* Only set the parts that the caller doesn't set */ - for (j = 0; j < 4; j++) { - set_tree_index(fors_leaf_addrx4 + j * 8, addr_idx + j); - set_type(fors_leaf_addrx4 + j * 8, SPX_ADDR_TYPE_FORSPRF); - } - - fors_gen_skx4(leaf + 0 * SPX_N, - leaf + 1 * SPX_N, - leaf + 2 * SPX_N, - leaf + 3 * SPX_N, - ctx, fors_leaf_addrx4); - - for (j = 0; j < 4; j++) { - set_type(fors_leaf_addrx4 + j * 8, SPX_ADDR_TYPE_FORSTREE); - } - - fors_sk_to_leafx4(leaf + 0 * SPX_N, - leaf + 1 * SPX_N, - leaf + 2 * SPX_N, - leaf + 3 * SPX_N, - leaf + 0 * SPX_N, - leaf + 1 * SPX_N, - leaf + 2 * SPX_N, - leaf + 3 * SPX_N, - ctx, fors_leaf_addrx4); -} - -/** - * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - * Assumes indices has space for SPX_FORS_TREES integers. - */ -static void message_to_indices(uint32_t *indices, const unsigned char *m) { - unsigned int i, j; - unsigned int offset = 0; - - for (i = 0; i < SPX_FORS_TREES; i++) { - indices[i] = 0; - for (j = 0; j < SPX_FORS_HEIGHT; j++) { - indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); - offset++; - } - } -} - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -void fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]) { - uint32_t indices[SPX_FORS_TREES]; - unsigned char roots[SPX_FORS_TREES * SPX_N]; - uint32_t fors_tree_addr[4 * 8] = {0}; - struct fors_gen_leaf_info fors_info = {0}; - uint32_t *fors_leaf_addr = fors_info.leaf_addrx; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - for (i = 0; i < 4; i++) { - copy_keypair_addr(fors_tree_addr + 8 * i, fors_addr); - set_type(fors_tree_addr + 8 * i, SPX_ADDR_TYPE_FORSTREE); - copy_keypair_addr(fors_leaf_addr + 8 * i, fors_addr); - } - copy_keypair_addr(fors_pk_addr, fors_addr); - set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < SPX_FORS_TREES; i++) { - idx_offset = i * (1 << SPX_FORS_HEIGHT); - - set_tree_height(fors_tree_addr, 0); - set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Include the secret key part that produces the selected leaf node. */ - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); - fors_gen_sk(sig, ctx, fors_tree_addr); - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); - sig += SPX_N; - - /* Compute the authentication path for this leaf node. */ - treehashx4(roots + i * SPX_N, sig, ctx, - indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx4, - fors_tree_addr, &fors_info); - - sig += SPX_N * SPX_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); -} - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -void fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]) { - uint32_t indices[SPX_FORS_TREES]; - unsigned char roots[SPX_FORS_TREES * SPX_N]; - unsigned char leaf[SPX_N]; - uint32_t fors_tree_addr[8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - copy_keypair_addr(fors_tree_addr, fors_addr); - copy_keypair_addr(fors_pk_addr, fors_addr); - - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); - set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < SPX_FORS_TREES; i++) { - idx_offset = i * (1 << SPX_FORS_HEIGHT); - - set_tree_height(fors_tree_addr, 0); - set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Derive the leaf from the included secret key part. */ - fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); - sig += SPX_N; - - /* Derive the corresponding root node of this tree. */ - compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, - sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); - sig += SPX_N * SPX_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/fors.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/fors.h deleted file mode 100644 index 509140a178..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/fors.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef SPX_FORS_H -#define SPX_FORS_H - -#include - -#include "context.h" -#include "params.h" - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -#define fors_sign SPX_NAMESPACE(fors_sign) -void fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]); - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) -void fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/haraka.c deleted file mode 100644 index b414b691d7..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/haraka.c +++ /dev/null @@ -1,702 +0,0 @@ -/* -Plain C implementation of the Haraka256 and Haraka512 permutations. -*/ -#include -#include -#include -#include -#include - -#include "haraka.h" -#include "harakax4.h" -#include "utils.h" - -#define HARAKAS_RATE 32 - -#define u64 unsigned long -#define u128 __m128i - -#define LOAD(src) _mm_loadu_si128((u128 *)(src)) -#define STORE(dest,src) _mm_storeu_si128((u128 *)(dest),src) - -#define XOR128(a, b) _mm_xor_si128(a, b) - -#define AES2(s0, s1, rci) \ - s0 = _mm_aesenc_si128(s0, *(rci)); \ - (s1) = _mm_aesenc_si128(s1, *((rci) + 1)); \ - (s0) = _mm_aesenc_si128(s0, *((rci) + 2)); \ - (s1) = _mm_aesenc_si128(s1, *((rci) + 3)); - -#define AES2_4x(s0, s1, s2, s3, rci) \ - AES2((s0)[0], (s0)[1], rci); \ - AES2((s1)[0], (s1)[1], rci); \ - AES2((s2)[0], (s2)[1], rci); \ - AES2((s3)[0], (s3)[1], rci); - -#define AES4(s0, s1, s2, s3, rci) \ - s0 = _mm_aesenc_si128(s0, *(rci)); \ - (s1) = _mm_aesenc_si128(s1, *((rci) + 1)); \ - (s2) = _mm_aesenc_si128(s2, *((rci) + 2)); \ - (s3) = _mm_aesenc_si128(s3, *((rci) + 3)); \ - (s0) = _mm_aesenc_si128(s0, *((rci) + 4)); \ - (s1) = _mm_aesenc_si128(s1, *((rci) + 5)); \ - (s2) = _mm_aesenc_si128(s2, *((rci) + 6)); \ - (s3) = _mm_aesenc_si128(s3, *((rci) + 7)); - -#define AES4_4x(s0, s1, s2, s3, rci) \ - AES4((s0)[0], (s0)[1], (s0)[2], (s0)[3], rci); \ - AES4((s1)[0], (s1)[1], (s1)[2], (s1)[3], rci); \ - AES4((s2)[0], (s2)[1], (s2)[2], (s2)[3], rci); \ - AES4((s3)[0], (s3)[1], (s3)[2], (s3)[3], rci); - -#define MIX2(s0, s1) \ - tmp = _mm_unpacklo_epi32(s0, s1); \ - (s1) = _mm_unpackhi_epi32(s0, s1); \ - (s0) = tmp; - -#define MIX4(s0, s1, s2, s3) \ - tmp = _mm_unpacklo_epi32(s0, s1); \ - (s0) = _mm_unpackhi_epi32(s0, s1); \ - (s1) = _mm_unpacklo_epi32(s2, s3); \ - (s2) = _mm_unpackhi_epi32(s2, s3); \ - (s3) = _mm_unpacklo_epi32(s0, s2); \ - (s0) = _mm_unpackhi_epi32(s0, s2); \ - (s2) = _mm_unpackhi_epi32(s1, tmp); \ - (s1) = _mm_unpacklo_epi32(s1, tmp); - -#define TRUNCSTORE(out, s0, s1, s2, s3) \ - _mm_storeu_si128((u128 *)(out), \ - _mm_castpd_si128(_mm_shuffle_pd(_mm_castsi128_pd(s0), _mm_castsi128_pd(s1), 3))); \ - _mm_storeu_si128((u128 *)((out) + 16), \ - _mm_castpd_si128(_mm_shuffle_pd(_mm_castsi128_pd(s2), _mm_castsi128_pd(s3), 0))); - -static void load_haraka_constants(u128 *rc) { - rc[0] = _mm_set_epi32((int)0x0684704c, (int)0xe620c00a, (int)0xb2c5fef0, (int)0x75817b9d); - rc[1] = _mm_set_epi32((int)0x8b66b4e1, (int)0x88f3a06b, (int)0x640f6ba4, (int)0x2f08f717); - rc[2] = _mm_set_epi32((int)0x3402de2d, (int)0x53f28498, (int)0xcf029d60, (int)0x9f029114); - rc[3] = _mm_set_epi32((int)0x0ed6eae6, (int)0x2e7b4f08, (int)0xbbf3bcaf, (int)0xfd5b4f79); - rc[4] = _mm_set_epi32((int)0xcbcfb0cb, (int)0x4872448b, (int)0x79eecd1c, (int)0xbe397044); - rc[5] = _mm_set_epi32((int)0x7eeacdee, (int)0x6e9032b7, (int)0x8d5335ed, (int)0x2b8a057b); - rc[6] = _mm_set_epi32((int)0x67c28f43, (int)0x5e2e7cd0, (int)0xe2412761, (int)0xda4fef1b); - rc[7] = _mm_set_epi32((int)0x2924d9b0, (int)0xafcacc07, (int)0x675ffde2, (int)0x1fc70b3b); - rc[8] = _mm_set_epi32((int)0xab4d63f1, (int)0xe6867fe9, (int)0xecdb8fca, (int)0xb9d465ee); - rc[9] = _mm_set_epi32((int)0x1c30bf84, (int)0xd4b7cd64, (int)0x5b2a404f, (int)0xad037e33); - rc[10] = _mm_set_epi32((int)0xb2cc0bb9, (int)0x941723bf, (int)0x69028b2e, (int)0x8df69800); - rc[11] = _mm_set_epi32((int)0xfa0478a6, (int)0xde6f5572, (int)0x4aaa9ec8, (int)0x5c9d2d8a); - rc[12] = _mm_set_epi32((int)0xdfb49f2b, (int)0x6b772a12, (int)0x0efa4f2e, (int)0x29129fd4); - rc[13] = _mm_set_epi32((int)0x1ea10344, (int)0xf449a236, (int)0x32d611ae, (int)0xbb6a12ee); - rc[14] = _mm_set_epi32((int)0xaf044988, (int)0x4b050084, (int)0x5f9600c9, (int)0x9ca8eca6); - rc[15] = _mm_set_epi32((int)0x21025ed8, (int)0x9d199c4f, (int)0x78a2c7e3, (int)0x27e593ec); - rc[16] = _mm_set_epi32((int)0xbf3aaaf8, (int)0xa759c9b7, (int)0xb9282ecd, (int)0x82d40173); - rc[17] = _mm_set_epi32((int)0x6260700d, (int)0x6186b017, (int)0x37f2efd9, (int)0x10307d6b); - rc[18] = _mm_set_epi32((int)0x5aca45c2, (int)0x21300443, (int)0x81c29153, (int)0xf6fc9ac6); - rc[19] = _mm_set_epi32((int)0x9223973c, (int)0x226b68bb, (int)0x2caf92e8, (int)0x36d1943a); - rc[20] = _mm_set_epi32((int)0xd3bf9238, (int)0x225886eb, (int)0x6cbab958, (int)0xe51071b4); - rc[21] = _mm_set_epi32((int)0xdb863ce5, (int)0xaef0c677, (int)0x933dfddd, (int)0x24e1128d); - rc[22] = _mm_set_epi32((int)0xbb606268, (int)0xffeba09c, (int)0x83e48de3, (int)0xcb2212b1); - rc[23] = _mm_set_epi32((int)0x734bd3dc, (int)0xe2e4d19c, (int)0x2db91a4e, (int)0xc72bf77d); - rc[24] = _mm_set_epi32((int)0x43bb47c3, (int)0x61301b43, (int)0x4b1415c4, (int)0x2cb3924e); - rc[25] = _mm_set_epi32((int)0xdba775a8, (int)0xe707eff6, (int)0x03b231dd, (int)0x16eb6899); - rc[26] = _mm_set_epi32((int)0x6df3614b, (int)0x3c755977, (int)0x8e5e2302, (int)0x7eca472c); - rc[27] = _mm_set_epi32((int)0xcda75a17, (int)0xd6de7d77, (int)0x6d1be5b9, (int)0xb88617f9); - rc[28] = _mm_set_epi32((int)0xec6b43f0, (int)0x6ba8e9aa, (int)0x9d6c069d, (int)0xa946ee5d); - rc[29] = _mm_set_epi32((int)0xcb1e6950, (int)0xf957332b, (int)0xa2531159, (int)0x3bf327c1); - rc[30] = _mm_set_epi32((int)0x2cee0c75, (int)0x00da619c, (int)0xe4ed0353, (int)0x600ed0d9); - rc[31] = _mm_set_epi32((int)0xf0b1a5a1, (int)0x96e90cab, (int)0x80bbbabc, (int)0x63a4a350); - rc[32] = _mm_set_epi32((int)0xae3db102, (int)0x5e962988, (int)0xab0dde30, (int)0x938dca39); - rc[33] = _mm_set_epi32((int)0x17bb8f38, (int)0xd554a40b, (int)0x8814f3a8, (int)0x2e75b442); - rc[34] = _mm_set_epi32((int)0x34bb8a5b, (int)0x5f427fd7, (int)0xaeb6b779, (int)0x360a16f6); - rc[35] = _mm_set_epi32((int)0x26f65241, (int)0xcbe55438, (int)0x43ce5918, (int)0xffbaafde); - rc[36] = _mm_set_epi32((int)0x4ce99a54, (int)0xb9f3026a, (int)0xa2ca9cf7, (int)0x839ec978); - rc[37] = _mm_set_epi32((int)0xae51a51a, (int)0x1bdff7be, (int)0x40c06e28, (int)0x22901235); - rc[38] = _mm_set_epi32((int)0xa0c1613c, (int)0xba7ed22b, (int)0xc173bc0f, (int)0x48a659cf); - rc[39] = _mm_set_epi32((int)0x756acc03, (int)0x02288288, (int)0x4ad6bdfd, (int)0xe9c59da1); -} - -void tweak_constants(spx_ctx *ctx) { - int i; - unsigned char buf[40 * 16]; - - /* Use the standard constants to generate tweaked ones. */ - load_haraka_constants(ctx->rc); - - /* Constants for pk.seed */ - haraka_S(buf, 40 * 16, ctx->pub_seed, SPX_N, ctx); - - /* Tweak constants with the pub_seed */ - for (i = 0; i < 40; i++) { - ctx->rc[i] = LOAD(buf + i * 16); - } -} - -static void haraka_S_absorb(unsigned char *s, unsigned int r, - const unsigned char *m, unsigned long long mlen, - unsigned char p, const spx_ctx *ctx) { - unsigned long long i; - PQCLEAN_VLA(unsigned char, t, r); - - while (mlen >= r) { - // XOR block to state - STORE(s, XOR128(LOAD(s), LOAD(m))); - STORE(s + 16, XOR128(LOAD(s + 16), LOAD(m + 16))); - haraka512_perm(s, s, ctx); - 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; - STORE(s, XOR128(LOAD(s), LOAD(t))); - STORE(s + 16, XOR128(LOAD(s + 16), LOAD(t + 16))); -} - -static void haraka_S_absorb4x(unsigned char *s, - unsigned int r, - const unsigned char *m0, - const unsigned char *m1, - const unsigned char *m2, - const unsigned char *m3, - unsigned long long int mlen, - unsigned char p, - const spx_ctx *ctx) { - unsigned long long i; - PQCLEAN_VLA(unsigned char, t0, r); - PQCLEAN_VLA(unsigned char, t1, r); - PQCLEAN_VLA(unsigned char, t2, r); - PQCLEAN_VLA(unsigned char, t3, r); - - while (mlen >= r) { - // XOR block to state - STORE(s, XOR128(LOAD(s), LOAD(m0))); - STORE(s + 16, XOR128(LOAD(s + 16), LOAD(m0 + 16))); - STORE(s + 64, XOR128(LOAD(s + 64), LOAD(m1))); - STORE(s + 80, XOR128(LOAD(s + 80), LOAD(m1 + 16))); - STORE(s + 128, XOR128(LOAD(s + 128), LOAD(m2))); - STORE(s + 144, XOR128(LOAD(s + 144), LOAD(m2 + 16))); - STORE(s + 192, XOR128(LOAD(s + 192), LOAD(m3))); - STORE(s + 208, XOR128(LOAD(s + 208), LOAD(m3 + 16))); - - haraka512_perm_x4(s, s, ctx); - mlen -= r; - m0 += r; - m1 += r; - m2 += r; - m3 += r; - } - - for (i = 0; i < r; ++i) { - t0[i] = 0; - t1[i] = 0; - t2[i] = 0; - t3[i] = 0; - } - for (i = 0; i < mlen; ++i) { - t0[i] = m0[i]; - t1[i] = m1[i]; - t2[i] = m2[i]; - t3[i] = m3[i]; - } - - t0[i] = p; - t1[i] = p; - t2[i] = p; - t3[i] = p; - - t0[r - 1] |= 128; - t1[r - 1] |= 128; - t2[r - 1] |= 128; - t3[r - 1] |= 128; - - STORE(s, XOR128(LOAD(s), LOAD(t0))); - STORE(s + 16, XOR128(LOAD(s + 16), LOAD(t0 + 16))); - STORE(s + 64, XOR128(LOAD(s + 64), LOAD(t1))); - STORE(s + 80, XOR128(LOAD(s + 80), LOAD(t1 + 16))); - STORE(s + 128, XOR128(LOAD(s + 128), LOAD(t2))); - STORE(s + 144, XOR128(LOAD(s + 144), LOAD(t2 + 16))); - STORE(s + 192, XOR128(LOAD(s + 192), LOAD(t3))); - STORE(s + 208, XOR128(LOAD(s + 208), LOAD(t3 + 16))); -} - -static void haraka_S_squeezeblocks(unsigned char *h, unsigned long long nblocks, - unsigned char *s, unsigned int r, - const spx_ctx *ctx) { - while (nblocks > 0) { - haraka512_perm(s, s, ctx); - STORE(h, LOAD(s)); - STORE(h + 16, LOAD(s + 16)); - h += r; - nblocks--; - } -} - -static void haraka_S_squeezeblocks4x(unsigned char *h0, - unsigned char *h1, - unsigned char *h2, - unsigned char *h3, - unsigned long long nblocks, - unsigned char *s, - unsigned int r, - const spx_ctx *ctx) { - while (nblocks > 0) { - haraka512_perm_x4(s, s, ctx); - STORE(h0, LOAD(s)); - STORE(h0 + 16, LOAD(s + 16)); - STORE(h1, LOAD(s + 64)); - STORE(h1 + 16, LOAD(s + 80)); - STORE(h2, LOAD(s + 128)); - STORE(h2 + 16, LOAD(s + 144)); - STORE(h3, LOAD(s + 192)); - STORE(h3 + 16, LOAD(s + 208)); - h0 += r; - h1 += r; - h2 += r; - h3 += r; - nblocks--; - } -} - -void haraka_S_inc_init(uint8_t *s_inc) { - size_t i; - - for (i = 0; i < 64; i++) { - s_inc[i] = 0; - } - s_inc[64] = 0; -} - -void haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, - const spx_ctx *ctx) { - size_t i; - - /* Recall that s_inc[64] is the non-absorbed bytes xored into the state */ - while (mlen + s_inc[64] >= HARAKAS_RATE) { - for (i = 0; i < (size_t)(HARAKAS_RATE - s_inc[64]); i++) { - /* Take the i'th byte from message - xor with the s_inc[64] + i'th byte of the state */ - s_inc[s_inc[64] + i] ^= m[i]; - } - mlen -= (size_t)(HARAKAS_RATE - s_inc[64]); - m += HARAKAS_RATE - s_inc[64]; - s_inc[64] = 0; - - haraka512_perm(s_inc, s_inc, ctx); - } - - for (i = 0; i < mlen; i++) { - s_inc[s_inc[64] + i] ^= m[i]; - } - s_inc[64] += (uint8_t)mlen; -} - -void haraka_S_inc_finalize(uint8_t *s_inc) { - /* After haraka_S_inc_absorb, we are guaranteed that s_inc[64] < HARAKAS_RATE, - so we can always use one more byte for p in the current state. */ - s_inc[s_inc[64]] ^= 0x1F; - s_inc[HARAKAS_RATE - 1] ^= 128; - s_inc[64] = 0; -} - -void haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, - const spx_ctx *ctx) { - size_t i; - - /* First consume any bytes we still have sitting around */ - for (i = 0; i < outlen && i < s_inc[64]; i++) { - /* There are s_inc[64] bytes left, so r - s_inc[64] is the first - available byte. We consume from there, i.e., up to r. */ - out[i] = (uint8_t)s_inc[(HARAKAS_RATE - s_inc[64] + i)]; - } - out += i; - outlen -= i; - s_inc[64] -= (uint8_t)i; - - /* Then squeeze the remaining necessary blocks */ - while (outlen > 0) { - haraka512_perm(s_inc, s_inc, ctx); - - for (i = 0; i < outlen && i < HARAKAS_RATE; i++) { - out[i] = s_inc[i]; - } - out += i; - outlen -= i; - s_inc[64] = (uint8_t)(HARAKAS_RATE - i); - } -} - -void haraka_S(unsigned char *out, unsigned long long outlen, - const unsigned char *in, unsigned long long inlen, - const spx_ctx *ctx) { - unsigned long long i; - unsigned char s[64]; - unsigned char d[32]; - - for (i = 0; i < 64; i++) { - s[i] = 0; - } - haraka_S_absorb(s, HARAKAS_RATE, in, inlen, 0x1F, ctx); - - haraka_S_squeezeblocks(out, outlen / HARAKAS_RATE, s, HARAKAS_RATE, ctx); - out += (outlen / HARAKAS_RATE) * HARAKAS_RATE; - - if (outlen % HARAKAS_RATE) { - haraka_S_squeezeblocks(d, 1, s, HARAKAS_RATE, ctx); - for (i = 0; i < outlen % HARAKAS_RATE; i++) { - out[i] = d[i]; - } - } -} - -void haraka_Sx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned long long outlen, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - unsigned long long inlen, - const spx_ctx *ctx) { - unsigned long long i; - unsigned char s[64 * 4]; - unsigned char d0[32]; - unsigned char d1[32]; - unsigned char d2[32]; - unsigned char d3[32]; - - for (i = 0; i < 64 * 4; i++) { - s[i] = 0; - } - haraka_S_absorb4x(s, HARAKAS_RATE, in0, in1, in2, in3, inlen, 0x1F, ctx); - - haraka_S_squeezeblocks4x(out0, out1, out2, out3, outlen / HARAKAS_RATE, s, - HARAKAS_RATE, ctx); - out0 += (outlen / HARAKAS_RATE) * HARAKAS_RATE; - out1 += (outlen / HARAKAS_RATE) * HARAKAS_RATE; - out2 += (outlen / HARAKAS_RATE) * HARAKAS_RATE; - out3 += (outlen / HARAKAS_RATE) * HARAKAS_RATE; - - if (outlen % HARAKAS_RATE) { - haraka_S_squeezeblocks4x(d0, d1, d2, d3, 1, s, HARAKAS_RATE, ctx); - for (i = 0; i < outlen % HARAKAS_RATE; i++) { - out0[i] = d0[i]; - out1[i] = d1[i]; - out2[i] = d2[i]; - out3[i] = d3[i]; - } - } -} - -void haraka512_perm(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx) { - u128 s[4], tmp; - - s[0] = LOAD(in); - s[1] = LOAD(in + 16); - s[2] = LOAD(in + 32); - s[3] = LOAD(in + 48); - - AES4(s[0], s[1], s[2], s[3], ctx->rc); - MIX4(s[0], s[1], s[2], s[3]); - - AES4(s[0], s[1], s[2], s[3], ctx->rc + 8); - MIX4(s[0], s[1], s[2], s[3]); - - AES4(s[0], s[1], s[2], s[3], ctx->rc + 16); - MIX4(s[0], s[1], s[2], s[3]); - - AES4(s[0], s[1], s[2], s[3], ctx->rc + 24); - MIX4(s[0], s[1], s[2], s[3]); - - AES4(s[0], s[1], s[2], s[3], ctx->rc + 32); - MIX4(s[0], s[1], s[2], s[3]); - - STORE(out, s[0]); - STORE(out + 16, s[1]); - STORE(out + 32, s[2]); - STORE(out + 48, s[3]); -} - -void haraka512_perm_x4(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx) { - u128 s[4][4], tmp; - - s[0][0] = LOAD(in); - s[0][1] = LOAD(in + 16); - s[0][2] = LOAD(in + 32); - s[0][3] = LOAD(in + 48); - s[1][0] = LOAD(in + 64); - s[1][1] = LOAD(in + 80); - s[1][2] = LOAD(in + 96); - s[1][3] = LOAD(in + 112); - s[2][0] = LOAD(in + 128); - s[2][1] = LOAD(in + 144); - s[2][2] = LOAD(in + 160); - s[2][3] = LOAD(in + 176); - s[3][0] = LOAD(in + 192); - s[3][1] = LOAD(in + 208); - s[3][2] = LOAD(in + 224); - s[3][3] = LOAD(in + 240); - - AES4_4x(s[0], s[1], s[2], s[3], ctx->rc); - MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); - MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); - MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); - MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - - AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 8); - MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); - MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); - MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); - MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - - AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 16); - MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); - MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); - MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); - MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - - AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 24); - MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); - MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); - MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); - MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - - AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 32); - MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); - MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); - MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); - MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - - STORE(out, s[0][0]); - STORE(out + 16, s[0][1]); - STORE(out + 32, s[0][2]); - STORE(out + 48, s[0][3]); - STORE(out + 64, s[1][0]); - STORE(out + 80, s[1][1]); - STORE(out + 96, s[1][2]); - STORE(out + 112, s[1][3]); - STORE(out + 128, s[2][0]); - STORE(out + 144, s[2][1]); - STORE(out + 160, s[2][2]); - STORE(out + 176, s[2][3]); - STORE(out + 192, s[3][0]); - STORE(out + 208, s[3][1]); - STORE(out + 224, s[3][2]); - STORE(out + 240, s[3][3]); -} - -void haraka512(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx) { - u128 s[4], tmp; - - s[0] = LOAD(in); - s[1] = LOAD(in + 16); - s[2] = LOAD(in + 32); - s[3] = LOAD(in + 48); - - AES4(s[0], s[1], s[2], s[3], ctx->rc); - MIX4(s[0], s[1], s[2], s[3]); - - AES4(s[0], s[1], s[2], s[3], ctx->rc + 8); - MIX4(s[0], s[1], s[2], s[3]); - - AES4(s[0], s[1], s[2], s[3], ctx->rc + 16); - MIX4(s[0], s[1], s[2], s[3]); - - AES4(s[0], s[1], s[2], s[3], ctx->rc + 24); - MIX4(s[0], s[1], s[2], s[3]); - - AES4(s[0], s[1], s[2], s[3], ctx->rc + 32); - MIX4(s[0], s[1], s[2], s[3]); - - s[0] = XOR128(s[0], LOAD(in)); - s[1] = XOR128(s[1], LOAD(in + 16)); - s[2] = XOR128(s[2], LOAD(in + 32)); - s[3] = XOR128(s[3], LOAD(in + 48)); - - // truncate and store result - TRUNCSTORE(out, s[0], s[1], s[2], s[3]); -} - -void haraka512x4(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx) { - u128 s[4][4], tmp; - - s[0][0] = LOAD(in); - s[0][1] = LOAD(in + 16); - s[0][2] = LOAD(in + 32); - s[0][3] = LOAD(in + 48); - s[1][0] = LOAD(in + 64); - s[1][1] = LOAD(in + 80); - s[1][2] = LOAD(in + 96); - s[1][3] = LOAD(in + 112); - s[2][0] = LOAD(in + 128); - s[2][1] = LOAD(in + 144); - s[2][2] = LOAD(in + 160); - s[2][3] = LOAD(in + 176); - s[3][0] = LOAD(in + 192); - s[3][1] = LOAD(in + 208); - s[3][2] = LOAD(in + 224); - s[3][3] = LOAD(in + 240); - - AES4_4x(s[0], s[1], s[2], s[3], ctx->rc); - MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); - MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); - MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); - MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - - AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 8); - MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); - MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); - MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); - MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - - AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 16); - MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); - MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); - MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); - MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - - AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 24); - MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); - MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); - MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); - MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - - AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 32); - MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); - MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); - MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); - MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - - s[0][0] = XOR128(s[0][0], LOAD(in)); - s[0][1] = XOR128(s[0][1], LOAD(in + 16)); - s[0][2] = XOR128(s[0][2], LOAD(in + 32)); - s[0][3] = XOR128(s[0][3], LOAD(in + 48)); - s[1][0] = XOR128(s[1][0], LOAD(in + 64)); - s[1][1] = XOR128(s[1][1], LOAD(in + 80)); - s[1][2] = XOR128(s[1][2], LOAD(in + 96)); - s[1][3] = XOR128(s[1][3], LOAD(in + 112)); - s[2][0] = XOR128(s[2][0], LOAD(in + 128)); - s[2][1] = XOR128(s[2][1], LOAD(in + 144)); - s[2][2] = XOR128(s[2][2], LOAD(in + 160)); - s[2][3] = XOR128(s[2][3], LOAD(in + 176)); - s[3][0] = XOR128(s[3][0], LOAD(in + 192)); - s[3][1] = XOR128(s[3][1], LOAD(in + 208)); - s[3][2] = XOR128(s[3][2], LOAD(in + 224)); - s[3][3] = XOR128(s[3][3], LOAD(in + 240)); - - TRUNCSTORE(out, s[0][0], s[0][1], s[0][2], s[0][3]); - TRUNCSTORE((out + 32), s[1][0], s[1][1], s[1][2], s[1][3]); - TRUNCSTORE((out + 64), s[2][0], s[2][1], s[2][2], s[2][3]); - TRUNCSTORE((out + 96), s[3][0], s[3][1], s[3][2], s[3][3]); -} - -void haraka256(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx) { - u128 s[2], tmp; - - s[0] = LOAD(in); - s[1] = LOAD(in + 16); - - AES2(s[0], s[1], ctx->rc); - MIX2(s[0], s[1]); - - AES2(s[0], s[1], ctx->rc + 4); - MIX2(s[0], s[1]); - - AES2(s[0], s[1], ctx->rc + 8); - MIX2(s[0], s[1]); - - AES2(s[0], s[1], ctx->rc + 12); - MIX2(s[0], s[1]); - - AES2(s[0], s[1], ctx->rc + 16); - MIX2(s[0], s[1]); - - s[0] = XOR128(s[0], LOAD(in)); - s[1] = XOR128(s[1], LOAD(in + 16)); - - STORE(out, s[0]); - STORE(out + 16, s[1]); -} - -void haraka256x4(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx) { - u128 s[4][2], tmp; - - s[0][0] = LOAD(in); - s[0][1] = LOAD(in + 16); - s[1][0] = LOAD(in + 32); - s[1][1] = LOAD(in + 48); - s[2][0] = LOAD(in + 64); - s[2][1] = LOAD(in + 80); - s[3][0] = LOAD(in + 96); - s[3][1] = LOAD(in + 112); - - // Round 1 - AES2_4x(s[0], s[1], s[2], s[3], ctx->rc); - - MIX2(s[0][0], s[0][1]); - MIX2(s[1][0], s[1][1]); - MIX2(s[2][0], s[2][1]); - MIX2(s[3][0], s[3][1]); - - // Round 2 - AES2_4x(s[0], s[1], s[2], s[3], ctx->rc + 4); - - MIX2(s[0][0], s[0][1]); - MIX2(s[1][0], s[1][1]); - MIX2(s[2][0], s[2][1]); - MIX2(s[3][0], s[3][1]); - - // Round 3 - AES2_4x(s[0], s[1], s[2], s[3], ctx->rc + 8); - - MIX2(s[0][0], s[0][1]); - MIX2(s[1][0], s[1][1]); - MIX2(s[2][0], s[2][1]); - MIX2(s[3][0], s[3][1]); - - // Round 4 - AES2_4x(s[0], s[1], s[2], s[3], ctx->rc + 12); - - MIX2(s[0][0], s[0][1]); - MIX2(s[1][0], s[1][1]); - MIX2(s[2][0], s[2][1]); - MIX2(s[3][0], s[3][1]); - - // Round 5 - AES2_4x(s[0], s[1], s[2], s[3], ctx->rc + 16); - - MIX2(s[0][0], s[0][1]); - MIX2(s[1][0], s[1][1]); - MIX2(s[2][0], s[2][1]); - MIX2(s[3][0], s[3][1]); - - // Feed Forward - s[0][0] = _mm_xor_si128(s[0][0], LOAD(in)); - s[0][1] = _mm_xor_si128(s[0][1], LOAD(in + 16)); - s[1][0] = _mm_xor_si128(s[1][0], LOAD(in + 32)); - s[1][1] = _mm_xor_si128(s[1][1], LOAD(in + 48)); - s[2][0] = _mm_xor_si128(s[2][0], LOAD(in + 64)); - s[2][1] = _mm_xor_si128(s[2][1], LOAD(in + 80)); - s[3][0] = _mm_xor_si128(s[3][0], LOAD(in + 96)); - s[3][1] = _mm_xor_si128(s[3][1], LOAD(in + 112)); - - STORE(out, s[0][0]); - STORE(out + 16, s[0][1]); - STORE(out + 32, s[1][0]); - STORE(out + 48, s[1][1]); - STORE(out + 64, s[2][0]); - STORE(out + 80, s[2][1]); - STORE(out + 96, s[3][0]); - STORE(out + 112, s[3][1]); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/haraka.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/haraka.h deleted file mode 100644 index 737cb6065f..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/haraka.h +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef SPX_HARAKA_H -#define SPX_HARAKA_H - -#include "context.h" -#include "params.h" - -/* Tweak constants with seed */ -#define tweak_constants SPX_NAMESPACE(tweak_constants) -void tweak_constants(spx_ctx *ctx); - -/* Haraka Sponge */ -#define haraka_S_inc_init SPX_NAMESPACE(haraka_S_inc_init) -void haraka_S_inc_init(uint8_t *s_inc); -#define haraka_S_inc_absorb SPX_NAMESPACE(haraka_S_inc_absorb) -void haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, - const spx_ctx *ctx); -#define haraka_S_inc_finalize SPX_NAMESPACE(haraka_S_inc_finalize) -void haraka_S_inc_finalize(uint8_t *s_inc); -#define haraka_S_inc_squeeze SPX_NAMESPACE(haraka_S_inc_squeeze) -void haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, - const spx_ctx *ctx); -#define haraka_S SPX_NAMESPACE(haraka_S) -void haraka_S(unsigned char *out, unsigned long long outlen, - const unsigned char *in, unsigned long long inlen, - const spx_ctx *ctx); - -/* Applies the 512-bit Haraka permutation to in. */ -#define haraka512_perm SPX_NAMESPACE(haraka512_perm) -void haraka512_perm(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx); - -/* Implementation of Haraka-512 */ -#define haraka512 SPX_NAMESPACE(haraka512) -void haraka512(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx); - -/* Implementation of Haraka-256 */ -#define haraka256 SPX_NAMESPACE(haraka256) -void haraka256(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/haraka_offsets.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/haraka_offsets.h deleted file mode 100644 index 7c062272a0..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/haraka_offsets.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef HARAKA_OFFSETS_H_ -#define HARAKA_OFFSETS_H_ - -/* - * Offsets of various fields in the address structure when we use Haraka as - * the Sphincs+ hash function - */ - -#define SPX_OFFSET_LAYER 3 /* The byte used to specify the Merkle tree layer */ -#define SPX_OFFSET_TREE 8 /* The start of the 8 byte field used to specify the tree */ -#define SPX_OFFSET_TYPE 19 /* The byte used to specify the hash type (reason) */ -#define SPX_OFFSET_KP_ADDR2 22 /* The high byte used to specify the key pair (which one-time signature) */ -#define SPX_OFFSET_KP_ADDR1 23 /* The low byte used to specify the key pair */ -#define SPX_OFFSET_CHAIN_ADDR 27 /* The byte used to specify the chain address (which Winternitz chain) */ -#define SPX_OFFSET_HASH_ADDR 31 /* The byte used to specify the hash address (where in the Winternitz chain) */ -#define SPX_OFFSET_TREE_HGT 27 /* The byte used to specify the height of this node in the FORS or Merkle tree */ -#define SPX_OFFSET_TREE_INDEX 28 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ - -#define SPX_HARAKA 1 - -#endif /* HARAKA_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/harakax4.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/harakax4.h deleted file mode 100644 index eadc69aa48..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/harakax4.h +++ /dev/null @@ -1,36 +0,0 @@ -#ifndef SPX_HARAKAX4_H -#define SPX_HARAKAX4_H - -#include "context.h" -#include "params.h" - -/* Haraka Sponge */ -#define haraka_Sx4 SPX_NAMESPACE(haraka_Sx4) -void haraka_Sx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned long long outlen, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - unsigned long long inlen, - const spx_ctx *ctx); - -/* Applies the 512-bit Haraka permutation x4 to in. */ -#define haraka512_perm_x4 SPX_NAMESPACE(haraka512_perm_x4) -void haraka512_perm_x4(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx); - -/* Implementation of Haraka-512 x4*/ -#define haraka512x4 SPX_NAMESPACE(haraka512x4) -void haraka512x4(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx); - -/* Implementation of Haraka-256 x4 */ -#define haraka256x4 SPX_NAMESPACE(haraka256x4) -void haraka256x4(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/hash.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/hash.h deleted file mode 100644 index f7c87d4c3c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/hash.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef SPX_HASH_H -#define SPX_HASH_H - -#include -#include - -#include "context.h" -#include "params.h" - -#define prf_addr SPX_NAMESPACE(prf_addr) -void prf_addr(unsigned char *out, const spx_ctx *ctx, - const uint32_t addr[8]); - -#define gen_message_random SPX_NAMESPACE(gen_message_random) -void gen_message_random(unsigned char *R, const unsigned char *sk_prf, - const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx); - -#define hash_message SPX_NAMESPACE(hash_message) -void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx); - - - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/hash_haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/hash_haraka.c deleted file mode 100644 index 750a67423b..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/hash_haraka.c +++ /dev/null @@ -1,81 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "utils.h" - -#include "haraka.h" -#include "hash.h" - -/* - * Computes PRF(key, addr), given a secret key of SPX_N bytes and an address - */ -void prf_addr(unsigned char *out, const spx_ctx *ctx, - const uint32_t addr[8]) { - /* Since SPX_N may be smaller than 32, we need temporary buffers. */ - unsigned char outbuf[32]; - unsigned char buf[64] = {0}; - - memcpy(buf, addr, SPX_ADDR_BYTES); - memcpy(buf + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); - - haraka512(outbuf, (const void *)buf, ctx); - memcpy(out, outbuf, SPX_N); -} - -/** - * Computes the message-dependent randomness R, using a secret seed and an - * optional randomization value as well as the message. - */ -void gen_message_random(unsigned char *R, const unsigned char *sk_prf, - const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx) { - uint8_t s_inc[65]; - - haraka_S_inc_init(s_inc); - haraka_S_inc_absorb(s_inc, sk_prf, SPX_N, ctx); - haraka_S_inc_absorb(s_inc, optrand, SPX_N, ctx); - haraka_S_inc_absorb(s_inc, m, mlen, ctx); - haraka_S_inc_finalize(s_inc); - haraka_S_inc_squeeze(R, SPX_N, s_inc, ctx); -} - -/** - * Computes the message hash using R, the public key, and the message. - * Outputs the message digest and the index of the leaf. The index is split in - * the tree index and the leaf index, for convenient copying to an address. - */ -void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx) { -#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) -#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) -#define SPX_LEAF_BITS SPX_TREE_HEIGHT -#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) -#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) - - unsigned char buf[SPX_DGST_BYTES]; - unsigned char *bufp = buf; - uint8_t s_inc[65]; - - haraka_S_inc_init(s_inc); - haraka_S_inc_absorb(s_inc, R, SPX_N, ctx); - haraka_S_inc_absorb(s_inc, pk + SPX_N, SPX_N, ctx); // Only absorb root part of pk - haraka_S_inc_absorb(s_inc, m, mlen, ctx); - haraka_S_inc_finalize(s_inc); - haraka_S_inc_squeeze(buf, SPX_DGST_BYTES, s_inc, ctx); - - memcpy(digest, bufp, SPX_FORS_MSG_BYTES); - bufp += SPX_FORS_MSG_BYTES; - - - *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); - *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); - bufp += SPX_TREE_BYTES; - - *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); - *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/hash_harakax4.c b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/hash_harakax4.c deleted file mode 100644 index cfa5162d79..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/hash_harakax4.c +++ /dev/null @@ -1,35 +0,0 @@ -#include -#include - -#include "address.h" -#include "harakax4.h" -#include "hashx4.h" -#include "params.h" - -/* - * 4-way parallel version of prf_addr; takes 4x as much input and output - */ -#define prf_addrx4 SPX_NAMESPACE(prf_addrx4) -void prf_addrx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const spx_ctx *ctx, - const uint32_t addrx4[4 * 8]) { - unsigned char bufx4[4 * 64] = {0}; - /* Since SPX_N may be smaller than 32, we need temporary buffers. */ - unsigned char outbuf[4 * 32]; - unsigned int i; - - for (i = 0; i < 4; i++) { - memcpy(bufx4 + i * 64, addrx4 + i * 8, SPX_ADDR_BYTES); - memcpy(bufx4 + i * 64 + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); - } - - haraka512x4(outbuf, bufx4, ctx); - - memcpy(out0, outbuf, SPX_N); - memcpy(out1, outbuf + 32, SPX_N); - memcpy(out2, outbuf + 64, SPX_N); - memcpy(out3, outbuf + 96, SPX_N); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/hashx4.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/hashx4.h deleted file mode 100644 index 3751a0ebd0..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/hashx4.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef SPX_HASHX4_H -#define SPX_HASHX4_H - -#include - -#include "context.h" -#include "params.h" - -#define prf_addrx4 SPX_NAMESPACE(prf_addrx4) -void prf_addrx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const spx_ctx *ctx, - const uint32_t addrx4[4 * 8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/merkle.c b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/merkle.c deleted file mode 100644 index f57811c1ac..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/merkle.c +++ /dev/null @@ -1,64 +0,0 @@ -#include -#include - -#include "merkle.h" - -#include "address.h" -#include "params.h" -#include "utils.h" -#include "utilsx4.h" -#include "wots.h" -#include "wotsx4.h" - -/* - * This generates a Merkle signature (WOTS signature followed by the Merkle - * authentication path). - */ -void merkle_sign(uint8_t *sig, unsigned char *root, - const spx_ctx *ctx, - uint32_t wots_addr[8], uint32_t tree_addr[8], - uint32_t idx_leaf) { - unsigned char *auth_path = sig + SPX_WOTS_BYTES; - uint32_t tree_addrx4[4 * 8] = { 0 }; - int j; - struct leaf_info_x4 info = { 0 }; - unsigned steps[ SPX_WOTS_LEN ]; - - info.wots_sig = sig; - chain_lengths(steps, root); - info.wots_steps = steps; - - for (j = 0; j < 4; j++) { - set_type(&tree_addrx4[8 * j], SPX_ADDR_TYPE_HASHTREE); - set_type(&info.leaf_addr[8 * j], SPX_ADDR_TYPE_WOTS); - set_type(&info.pk_addr[8 * j], SPX_ADDR_TYPE_WOTSPK); - copy_subtree_addr(&tree_addrx4[8 * j], tree_addr); - copy_subtree_addr(&info.leaf_addr[8 * j], wots_addr); - copy_subtree_addr(&info.pk_addr[8 * j], wots_addr); - } - - info.wots_sign_leaf = idx_leaf; - - treehashx4(root, auth_path, ctx, - idx_leaf, 0, - SPX_TREE_HEIGHT, - wots_gen_leafx4, - tree_addrx4, &info); -} - -/* Compute root node of the top-most subtree. */ -void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { - /* We do not need the auth path in key generation, but it simplifies the - code to have just one treehash routine that computes both root and path - in one function. */ - unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; - uint32_t top_tree_addr[8] = {0}; - uint32_t wots_addr[8] = {0}; - - set_layer_addr(top_tree_addr, SPX_D - 1); - set_layer_addr(wots_addr, SPX_D - 1); - - merkle_sign(auth_path, root, ctx, - wots_addr, top_tree_addr, - ~0U /* ~0 means "don't bother generating an auth path */ ); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/merkle.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/merkle.h deleted file mode 100644 index 769cf2e970..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/merkle.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef MERKLE_H_ -#define MERKLE_H_ - -#include - -#include "context.h" -#include "params.h" - -/* Generate a Merkle signature (WOTS signature followed by the Merkle */ -/* authentication path) */ -#define merkle_sign SPX_NAMESPACE(merkle_sign) -void merkle_sign(uint8_t *sig, unsigned char *root, - const spx_ctx *ctx, - uint32_t wots_addr[8], uint32_t tree_addr[8], - uint32_t idx_leaf); - -/* Compute the root node of the top-most subtree. */ -#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) -void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); - -#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/nistapi.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/nistapi.h deleted file mode 100644 index 3cb71afad4..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/nistapi.h +++ /dev/null @@ -1,87 +0,0 @@ -#ifndef SPX_API_H -#define SPX_API_H - -#include -#include - -#include "params.h" - -#define CRYPTO_ALGNAME "SPHINCS+" - -#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES -#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES -#define CRYPTO_BYTES SPX_BYTES -#define CRYPTO_SEEDBYTES (3*SPX_N) - -/* - * Returns the length of a secret key, in bytes - */ -#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) -size_t crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) -size_t crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) -size_t crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) -size_t crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) -int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) -int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) -int crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) -int crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -#define crypto_sign SPX_NAMESPACE(crypto_sign) -int crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) -int crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/params.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/params.h deleted file mode 100644 index 8cc6b09402..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/params.h +++ /dev/null @@ -1,56 +0,0 @@ -#ifndef SPX_PARAMS_H -#define SPX_PARAMS_H - -#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_##s - -/* Hash output length in bytes. */ -#define SPX_N 16 -/* Height of the hypertree. */ -#define SPX_FULL_HEIGHT 66 -/* Number of subtree layer. */ -#define SPX_D 22 -/* FORS tree dimensions. */ -#define SPX_FORS_HEIGHT 6 -#define SPX_FORS_TREES 33 -/* Winternitz parameter, */ -#define SPX_WOTS_W 16 - -/* The hash function is defined by linking a different hash.c file, as opposed - to setting a #define constant. */ - -/* For clarity */ -#define SPX_ADDR_BYTES 32 - -/* WOTS parameters. */ -#define SPX_WOTS_LOGW 4 - -#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) - -/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#define SPX_WOTS_LEN2 3 - -#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) -#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) -#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES - -/* Subtree size. */ -#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) - -//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT -// #error SPX_D should always divide SPX_FULL_HEIGHT -//#endif - -/* FORS parameters. */ -#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) -#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) -#define SPX_FORS_PK_BYTES SPX_N - -/* Resulting SPX sizes. */ -#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ - SPX_FULL_HEIGHT * SPX_N) -#define SPX_PK_BYTES (2 * SPX_N) -#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) - -#include "haraka_offsets.h" - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/sign.c b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/sign.c deleted file mode 100644 index 9d0c7d1b22..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/sign.c +++ /dev/null @@ -1,286 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "context.h" -#include "fors.h" -#include "hash.h" -#include "merkle.h" -#include "nistapi.h" -#include "params.h" -#include "randombytes.h" -#include "thash.h" -#include "utils.h" -#include "wots.h" - -/* - * Returns the length of a secret key, in bytes - */ -size_t crypto_sign_secretkeybytes(void) { - return CRYPTO_SECRETKEYBYTES; -} - -/* - * Returns the length of a public key, in bytes - */ -size_t crypto_sign_publickeybytes(void) { - return CRYPTO_PUBLICKEYBYTES; -} - -/* - * Returns the length of a signature, in bytes - */ -size_t crypto_sign_bytes(void) { - return CRYPTO_BYTES; -} - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t crypto_sign_seedbytes(void) { - return CRYPTO_SEEDBYTES; -} - -/* - * Generates an SPX key pair given a seed of length - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed) { - spx_ctx ctx; - - /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ - memcpy(sk, seed, CRYPTO_SEEDBYTES); - - memcpy(pk, sk + 2 * SPX_N, SPX_N); - - memcpy(ctx.pub_seed, pk, SPX_N); - memcpy(ctx.sk_seed, sk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - /* Compute root node of the top-most subtree. */ - merkle_gen_root(sk + 3 * SPX_N, &ctx); - - // cleanup - free_hash_function(&ctx); - - memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); - - return 0; -} - -/* - * Generates an SPX key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { - uint8_t seed[CRYPTO_SEEDBYTES]; - randombytes(seed, CRYPTO_SEEDBYTES); - crypto_sign_seed_keypair(pk, sk, seed); - - return 0; -} - -/** - * Returns an array containing a detached signature. - */ -int crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - spx_ctx ctx; - - const uint8_t *sk_prf = sk + SPX_N; - const uint8_t *pk = sk + 2 * SPX_N; - - uint8_t optrand[SPX_N]; - uint8_t mhash[SPX_FORS_MSG_BYTES]; - uint8_t root[SPX_N]; - uint32_t i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - - memcpy(ctx.sk_seed, sk, SPX_N); - memcpy(ctx.pub_seed, pk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - set_type(wots_addr, SPX_ADDR_TYPE_WOTS); - set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); - - /* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ - randombytes(optrand, SPX_N); - /* Compute the digest randomization value. */ - gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); - - /* Derive the message digest and leaf index from R, PK and M. */ - hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); - sig += SPX_N; - - set_tree_addr(wots_addr, tree); - set_keypair_addr(wots_addr, idx_leaf); - - /* Sign the message hash using FORS. */ - fors_sign(sig, root, mhash, &ctx, wots_addr); - sig += SPX_FORS_BYTES; - - for (i = 0; i < SPX_D; i++) { - set_layer_addr(tree_addr, i); - set_tree_addr(tree_addr, tree); - - copy_subtree_addr(wots_addr, tree_addr); - set_keypair_addr(wots_addr, idx_leaf); - - merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); - sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); - tree = tree >> SPX_TREE_HEIGHT; - } - - free_hash_function(&ctx); - - *siglen = SPX_BYTES; - - return 0; -} - -/** - * Verifies a detached signature and message under a given public key. - */ -int crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk) { - spx_ctx ctx; - const uint8_t *pub_root = pk + SPX_N; - uint8_t mhash[SPX_FORS_MSG_BYTES]; - uint8_t wots_pk[SPX_WOTS_BYTES]; - uint8_t root[SPX_N]; - uint8_t leaf[SPX_N]; - unsigned int i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - if (siglen != SPX_BYTES) { - return -1; - } - - memcpy(ctx.pub_seed, pk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - set_type(wots_addr, SPX_ADDR_TYPE_WOTS); - set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); - set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); - - /* Derive the message digest and leaf index from R || PK || M. */ - /* The additional SPX_N is a result of the hash domain separator. */ - hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); - sig += SPX_N; - - /* Layer correctly defaults to 0, so no need to set_layer_addr */ - set_tree_addr(wots_addr, tree); - set_keypair_addr(wots_addr, idx_leaf); - - fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); - sig += SPX_FORS_BYTES; - - /* For each subtree.. */ - for (i = 0; i < SPX_D; i++) { - set_layer_addr(tree_addr, i); - set_tree_addr(tree_addr, tree); - - copy_subtree_addr(wots_addr, tree_addr); - set_keypair_addr(wots_addr, idx_leaf); - - copy_keypair_addr(wots_pk_addr, wots_addr); - - /* The WOTS public key is only correct if the signature was correct. */ - /* Initially, root is the FORS pk, but on subsequent iterations it is - the root of the subtree below the currently processed subtree. */ - wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); - sig += SPX_WOTS_BYTES; - - /* Compute the leaf node using the WOTS public key. */ - thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); - - /* Compute the root node of this subtree. */ - compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, - &ctx, tree_addr); - sig += SPX_TREE_HEIGHT * SPX_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); - tree = tree >> SPX_TREE_HEIGHT; - } - - // cleanup - free_hash_function(&ctx); - - /* Check if the root node equals the root node in the public key. */ - if (memcmp(root, pub_root, SPX_N) != 0) { - return -1; - } - - return 0; -} - - -/** - * Returns an array containing the signature followed by the message. - */ -int crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk) { - size_t siglen; - - crypto_sign_signature(sm, &siglen, m, mlen, sk); - - memmove(sm + SPX_BYTES, m, mlen); - *smlen = siglen + mlen; - - return 0; -} - -/** - * Verifies a given signature-message pair under a given public key. - */ -int crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk) { - /* The API caller does not necessarily know what size a signature should be - but SPHINCS+ signatures are always exactly SPX_BYTES. */ - if (smlen < SPX_BYTES) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - *mlen = smlen - SPX_BYTES; - - if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - /* If verification was successful, move the message to the right place. */ - memmove(m, sm + SPX_BYTES, *mlen); - - return 0; -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/thash.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/thash.h deleted file mode 100644 index 8687ccfb4d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/thash.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef SPX_THASH_H -#define SPX_THASH_H - -#include "context.h" -#include "params.h" - -#include - -#define thash SPX_NAMESPACE(thash) -void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/thash_haraka_robust.c b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/thash_haraka_robust.c deleted file mode 100644 index 109502cbc2..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/thash_haraka_robust.c +++ /dev/null @@ -1,45 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "thash.h" -#include "utils.h" - -#include "haraka.h" - -/** - * Takes an array of inblocks concatenated arrays of SPX_N bytes. - */ -void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]) { - PQCLEAN_VLA(uint8_t, buf, SPX_ADDR_BYTES + inblocks * SPX_N); - PQCLEAN_VLA(uint8_t, bitmask, inblocks * SPX_N); - unsigned char outbuf[32]; - unsigned char buf_tmp[64]; - unsigned int i; - - if (inblocks == 1) { - /* F function */ - /* Since SPX_N may be smaller than 32, we need a temporary buffer. */ - memset(buf_tmp, 0, 64); - memcpy(buf_tmp, addr, 32); - - haraka256(outbuf, buf_tmp, ctx); - for (i = 0; i < inblocks * SPX_N; i++) { - buf_tmp[SPX_ADDR_BYTES + i] = in[i] ^ outbuf[i]; - } - haraka512(outbuf, buf_tmp, ctx); - memcpy(out, outbuf, SPX_N); - } else { - /* All other tweakable hashes*/ - memcpy(buf, addr, 32); - haraka_S(bitmask, inblocks * SPX_N, buf, SPX_ADDR_BYTES, ctx); - - for (i = 0; i < inblocks * SPX_N; i++) { - buf[SPX_ADDR_BYTES + i] = in[i] ^ bitmask[i]; - } - - haraka_S(out, SPX_N, buf, SPX_ADDR_BYTES + inblocks * SPX_N, ctx); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/thash_haraka_robustx4.c b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/thash_haraka_robustx4.c deleted file mode 100644 index 100808a3a5..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/thash_haraka_robustx4.c +++ /dev/null @@ -1,93 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "thashx4.h" - -#include "harakax4.h" - -#include "utils.h" - -/** - * 4-way parallel version of thash; takes 4x as much input and output - */ -#define thashx4 SPX_NAMESPACE(thashx4) -void thashx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addrx4[4 * 8]) { - PQCLEAN_VLA(unsigned char, buf0, SPX_ADDR_BYTES + inblocks * SPX_N); - PQCLEAN_VLA(unsigned char, buf1, SPX_ADDR_BYTES + inblocks * SPX_N); - PQCLEAN_VLA(unsigned char, buf2, SPX_ADDR_BYTES + inblocks * SPX_N); - PQCLEAN_VLA(unsigned char, buf3, SPX_ADDR_BYTES + inblocks * SPX_N); - PQCLEAN_VLA(unsigned char, bitmask0, inblocks * SPX_N); - PQCLEAN_VLA(unsigned char, bitmask1, inblocks * SPX_N); - PQCLEAN_VLA(unsigned char, bitmask2, inblocks * SPX_N); - PQCLEAN_VLA(unsigned char, bitmask3, inblocks * SPX_N); - unsigned char outbuf[32 * 4]; - unsigned char buf_tmp[64 * 4]; - unsigned int i; - - if (inblocks == 1) { - memset(buf_tmp, 0, 64 * 4); - - // Generate masks first in buffer - memcpy(buf_tmp, addrx4 + 0 * 8, 32); - memcpy(buf_tmp + 32, addrx4 + 1 * 8, 32); - memcpy(buf_tmp + 64, addrx4 + 2 * 8, 32); - memcpy(buf_tmp + 96, addrx4 + 3 * 8, 32); - - haraka256x4(outbuf, buf_tmp, ctx); - - /* move addresses to make room for inputs; zero old values */ - memcpy(buf_tmp + 192, buf_tmp + 96, SPX_ADDR_BYTES); - memcpy(buf_tmp + 128, buf_tmp + 64, SPX_ADDR_BYTES); - memcpy(buf_tmp + 64, buf_tmp + 32, SPX_ADDR_BYTES); - /* skip memcpy(buf_tmp, buf_tmp, SPX_ADDR_BYTES); already in place */ - - /* skip memset(buf_tmp, 0, SPX_ADDR_BYTES); remained untouched */ - memset(buf_tmp + 32, 0, SPX_ADDR_BYTES); - /* skip memset(buf_tmp + 64, 0, SPX_ADDR_BYTES); contains addr1 */ - memset(buf_tmp + 96, 0, SPX_ADDR_BYTES); - - for (i = 0; i < SPX_N; i++) { - buf_tmp[SPX_ADDR_BYTES + i] = in0[i] ^ outbuf[i]; - buf_tmp[SPX_ADDR_BYTES + i + 64] = in1[i] ^ outbuf[i + 32]; - buf_tmp[SPX_ADDR_BYTES + i + 128] = in2[i] ^ outbuf[i + 64]; - buf_tmp[SPX_ADDR_BYTES + i + 192] = in3[i] ^ outbuf[i + 96]; - } - - haraka512x4(outbuf, buf_tmp, ctx); - - memcpy(out0, outbuf, SPX_N); - memcpy(out1, outbuf + 32, SPX_N); - memcpy(out2, outbuf + 64, SPX_N); - memcpy(out3, outbuf + 96, SPX_N); - } else { - /* All other tweakable hashes*/ - memcpy(buf0, addrx4 + 0 * 8, 32); - memcpy(buf1, addrx4 + 1 * 8, 32); - memcpy(buf2, addrx4 + 2 * 8, 32); - memcpy(buf3, addrx4 + 3 * 8, 32); - - haraka_Sx4(bitmask0, bitmask1, bitmask2, bitmask3, inblocks * SPX_N, - buf0, buf1, buf2, buf3, SPX_ADDR_BYTES, ctx); - - for (i = 0; i < inblocks * SPX_N; i++) { - buf0[SPX_ADDR_BYTES + i] = in0[i] ^ bitmask0[i]; - buf1[SPX_ADDR_BYTES + i] = in1[i] ^ bitmask1[i]; - buf2[SPX_ADDR_BYTES + i] = in2[i] ^ bitmask2[i]; - buf3[SPX_ADDR_BYTES + i] = in3[i] ^ bitmask3[i]; - } - - haraka_Sx4(out0, out1, out2, out3, SPX_N, - buf0, buf1, buf2, buf3, SPX_ADDR_BYTES + inblocks * SPX_N, - ctx); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/thashx4.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/thashx4.h deleted file mode 100644 index 64798a3727..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/thashx4.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef SPX_THASHX4_H -#define SPX_THASHX4_H - -#include - -#include "context.h" -#include "params.h" - -#define thashx4 SPX_NAMESPACE(thashx4) -void thashx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addrx4[4 * 8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/utils.c b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/utils.c deleted file mode 100644 index 177b541fb9..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/utils.c +++ /dev/null @@ -1,148 +0,0 @@ -#include - -#include "utils.h" - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "thash.h" - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void ull_to_bytes(unsigned char *out, unsigned int outlen, - unsigned long long in) { - int i; - - /* Iterate over out in decreasing order, for big-endianness. */ - for (i = (signed int)outlen - 1; i >= 0; i--) { - out[i] = in & 0xff; - in = in >> 8; - } -} - -void u32_to_bytes(unsigned char *out, uint32_t in) { - out[0] = (unsigned char)(in >> 24); - out[1] = (unsigned char)(in >> 16); - out[2] = (unsigned char)(in >> 8); - out[3] = (unsigned char)in; -} - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { - unsigned long long retval = 0; - unsigned int i; - - for (i = 0; i < inlen; i++) { - retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); - } - return retval; -} - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void compute_root(unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const spx_ctx *ctx, uint32_t addr[8]) { - uint32_t i; - unsigned char buffer[2 * SPX_N]; - - /* If leaf_idx is odd (last bit = 1), current path element is a right child - and auth_path has to go left. Otherwise it is the other way around. */ - if (leaf_idx & 1) { - memcpy(buffer + SPX_N, leaf, SPX_N); - memcpy(buffer, auth_path, SPX_N); - } else { - memcpy(buffer, leaf, SPX_N); - memcpy(buffer + SPX_N, auth_path, SPX_N); - } - auth_path += SPX_N; - - for (i = 0; i < tree_height - 1; i++) { - leaf_idx >>= 1; - idx_offset >>= 1; - /* Set the address of the node we're creating. */ - set_tree_height(addr, i + 1); - set_tree_index(addr, leaf_idx + idx_offset); - - /* Pick the right or left neighbor, depending on parity of the node. */ - if (leaf_idx & 1) { - thash(buffer + SPX_N, buffer, 2, ctx, addr); - memcpy(buffer, auth_path, SPX_N); - } else { - thash(buffer, buffer, 2, ctx, addr); - memcpy(buffer + SPX_N, auth_path, SPX_N); - } - auth_path += SPX_N; - } - - /* The last iteration is exceptional; we do not copy an auth_path node. */ - leaf_idx >>= 1; - idx_offset >>= 1; - set_tree_height(addr, tree_height); - set_tree_index(addr, leaf_idx + idx_offset); - thash(root, buffer, 2, ctx, addr); -} - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const spx_ctx * /* ctx */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), - uint32_t tree_addr[8]) { - PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); - PQCLEAN_VLA(unsigned int, heights, tree_height + 1); - unsigned int offset = 0; - uint32_t idx; - uint32_t tree_idx; - - for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { - /* Add the next leaf node to the stack. */ - gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); - offset++; - heights[offset - 1] = 0; - - /* If this is a node we need for the auth path.. */ - if ((leaf_idx ^ 0x1) == idx) { - memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); - } - - /* While the top-most nodes are of equal height.. */ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { - /* Compute index of the new node, in the next layer. */ - tree_idx = (idx >> (heights[offset - 1] + 1)); - - /* Set the address of the node we're creating. */ - set_tree_height(tree_addr, heights[offset - 1] + 1); - set_tree_index(tree_addr, - tree_idx + (idx_offset >> (heights[offset - 1] + 1))); - /* Hash the top-most nodes from the stack together. */ - thash(stack + (offset - 2)*SPX_N, - stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); - offset--; - /* Note that the top-most node is now one layer higher. */ - heights[offset - 1]++; - - /* If this is a node we need for the auth path.. */ - if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_path + heights[offset - 1]*SPX_N, - stack + (offset - 1)*SPX_N, SPX_N); - } - } - } - memcpy(root, stack, SPX_N); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/utils.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/utils.h deleted file mode 100644 index 64f5d5a53a..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/utils.h +++ /dev/null @@ -1,58 +0,0 @@ -#ifndef SPX_UTILS_H -#define SPX_UTILS_H - -#include - -#include "compat.h" -#include "context.h" -#include "params.h" - - -/* To support MSVC use alloca() instead of VLAs. See #20. */ - - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) -void ull_to_bytes(unsigned char *out, unsigned int outlen, - unsigned long long in); -#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) -void u32_to_bytes(unsigned char *out, uint32_t in); - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) -unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -#define compute_root SPX_NAMESPACE(compute_root) -void compute_root(unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const spx_ctx *ctx, uint32_t addr[8]); - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -#define treehash SPX_NAMESPACE(treehash) -void treehash(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const spx_ctx *ctx /* ctx */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), - uint32_t tree_addr[8]); - - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/utilsx4.c b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/utilsx4.c deleted file mode 100644 index 1638677194..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/utilsx4.c +++ /dev/null @@ -1,138 +0,0 @@ -#include - -#include "utilsx4.h" - -#include "address.h" -#include "params.h" -#include "thashx4.h" -#include "utils.h" - -/* - * Generate the entire Merkle tree, computing the authentication path for leaf_idx, - * and the resulting root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) - * - * This expects tree_addrx4 to be initialized to 4 parallel addr structures for - * the Merkle tree nodes - * - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - * - * This works by using the standard Merkle tree building algorithm, except - * that each 'node' tracked is actually 4 consecutive nodes in the real tree. - * When we combine two logical nodes ABCD and WXYZ, we perform the H - * operation on adjacent real nodes, forming the parent logical node - * (AB)(CD)(WX)(YZ) - * - * When we get to the top two levels of the real tree (where there is only - * one logical node), we continue this operation two more times; the right - * most real node will by the actual root (and the other 3 nodes will be - * garbage). We follow the same thashx4 logic so that the 'extract - * authentication path components' part of the loop is still executed (and - * to simplify the code somewhat) - * - * This currently assumes tree_height >= 2; I suspect that doing an adjusting - * idx, addr_idx on the gen_leafx4 call if tree_height < 2 would fix it; since - * we don't actually use such short trees, I haven't bothered - */ -void treehashx4(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, - uint32_t tree_height, - void (*gen_leafx4)( - unsigned char * /* Where to write the leaves */, - const spx_ctx *, - uint32_t idx, void *info), - uint32_t tree_addrx4[4 * 8], - void *info) { - /* This is where we keep the intermediate nodes */ - PQCLEAN_VLA(unsigned char, stackx4, tree_height * 4 * SPX_N); - uint32_t left_adj = 0, prev_left_adj = 0; /* When we're doing the top 3 */ - /* levels, the left-most part of the tree isn't at the beginning */ - /* of current[]. These give the offset of the actual start */ - - uint32_t idx; - uint32_t max_idx = (1U << (tree_height - 2)) - 1; - for (idx = 0;; idx++) { - unsigned char current[4 * SPX_N]; /* Current logical node */ - gen_leafx4( current, ctx, 4 * idx + idx_offset, - info ); - - /* Now combine the freshly generated right node with previously */ - /* generated left ones */ - uint32_t internal_idx_offset = idx_offset; - uint32_t internal_idx = idx; - uint32_t internal_leaf = leaf_idx; - uint32_t h; /* The height we are in the Merkle tree */ - for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { - - /* Special processing if we're at the top of the tree */ - if (h >= tree_height - 2) { - if (h == tree_height) { - /* We hit the root; return it */ - memcpy( root, ¤t[3 * SPX_N], SPX_N ); - return; - } - /* The tree indexing logic is a bit off in this case */ - /* Adjust it so that the left-most node of the part of */ - /* the tree that we're processing has index 0 */ - prev_left_adj = left_adj; - left_adj = 4U - (1 << (tree_height - h - 1)); - } - - /* Check if we hit the top of the tree */ - if (h == tree_height) { - /* We hit the root; return it */ - memcpy( root, ¤t[3 * SPX_N], SPX_N ); - return; - } - - /* - * Check if one of the nodes we have is a part of the - * authentication path; if it is, write it out - */ - if ((((internal_idx << 2) ^ internal_leaf) & ~0x3U) == 0) { - memcpy( &auth_path[ h * SPX_N ], - ¤t[(((internal_leaf & 3) ^ 1) + prev_left_adj) * SPX_N], - SPX_N ); - } - - /* - * Check if we're at a left child; if so, stop going up the stack - * Exception: if we've reached the end of the tree, keep on going - * (so we combine the last 4 nodes into the one root node in two - * more iterations) - */ - if ((internal_idx & 1) == 0 && idx < max_idx) { - break; - } - - /* Ok, we're at a right node (or doing the top 3 levels) */ - /* Now combine the left and right logical nodes together */ - - /* Set the address of the node we're creating. */ - unsigned int j; - internal_idx_offset >>= 1; - for (j = 0; j < 4; j++) { - set_tree_height(tree_addrx4 + j * 8, h + 1); - set_tree_index(tree_addrx4 + j * 8, - (4 / 2) * (internal_idx & ~1U) + j - left_adj + internal_idx_offset ); - } - unsigned char *left = &stackx4[h * 4 * SPX_N]; - thashx4( ¤t[0 * SPX_N], - ¤t[1 * SPX_N], - ¤t[2 * SPX_N], - ¤t[3 * SPX_N], - &left [0 * SPX_N], - &left [2 * SPX_N], - ¤t[0 * SPX_N], - ¤t[2 * SPX_N], - 2, ctx, tree_addrx4); - } - - /* We've hit a left child; save the current for when we get the */ - /* corresponding right right */ - memcpy( &stackx4[h * 4 * SPX_N], current, 4 * SPX_N); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/utilsx4.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/utilsx4.h deleted file mode 100644 index facb874b18..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/utilsx4.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef SPX_UTILSX4_H -#define SPX_UTILSX4_H - -#include - -#include "context.h" -#include "params.h" - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - * - * This implementation uses AVX to compute internal nodes 4 at a time (in - * parallel) - */ -#define treehashx4 SPX_NAMESPACE(treehashx4) -void treehashx4(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leafx4)( - unsigned char * /* Where to write the leaves */, - const spx_ctx * /* ctx */, - uint32_t addr_idx, void *info), - uint32_t tree_addrx4[4 * 8], void *info); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/wots.c b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/wots.c deleted file mode 100644 index 4d5041ce05..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/wots.c +++ /dev/null @@ -1,269 +0,0 @@ -#include -#include - -#include "wots.h" - -#include "address.h" -#include "hash.h" -#include "hashx4.h" -#include "params.h" -#include "thash.h" -#include "thashx4.h" -#include "utils.h" -#include "utilsx4.h" -#include "wotsx4.h" - -// TODO clarify address expectations, and make them more uniform. -// TODO i.e. do we expect types to be set already? -// TODO and do we expect modifications or copies? - -/** - * Computes up the chains - */ -static void gen_chains( - unsigned char *out, - const unsigned char *in, - unsigned int start[SPX_WOTS_LEN], - const unsigned int steps[SPX_WOTS_LEN], - const spx_ctx *ctx, - uint32_t addr[8]) { - uint32_t i, j, k, idx, watching; - int done; - unsigned char empty[SPX_N]; - unsigned char *bufs[4]; - uint32_t addrs[8 * 4]; - - int l; - uint16_t counts[SPX_WOTS_W] = { 0 }; - uint16_t idxs[SPX_WOTS_LEN]; - uint16_t total, newTotal; - - /* set addrs = {addr, addr, addr, addr} */ - for (j = 0; j < 4; j++) { - memcpy(addrs + j * 8, addr, sizeof(uint32_t) * 8); - } - - /* Initialize out with the value at position 'start'. */ - memcpy(out, in, SPX_WOTS_LEN * SPX_N); - - /* Sort the chains in reverse order by steps using counting sort. */ - for (i = 0; i < SPX_WOTS_LEN; i++) { - counts[steps[i]]++; - } - total = 0; - for (l = SPX_WOTS_W - 1; l >= 0; l--) { - newTotal = counts[l] + total; - counts[l] = total; - total = newTotal; - } - for (i = 0; i < SPX_WOTS_LEN; i++) { - idxs[counts[steps[i]]] = (uint16_t)i; - counts[steps[i]]++; - } - - /* We got our work cut out for us: do it! */ - for (i = 0; i < SPX_WOTS_LEN; i += 4) { - for (j = 0; j < 4 && i + j < SPX_WOTS_LEN; j++) { - idx = idxs[i + j]; - set_chain_addr(addrs + j * 8, idx); - bufs[j] = out + SPX_N * idx; - } - - /* As the chains are sorted in reverse order, we know that the first - * chain is the longest and the last one is the shortest. We keep - * an eye on whether the last chain is done and then on the one before, - * et cetera. */ - watching = 3; - done = 0; - while (i + watching >= SPX_WOTS_LEN) { - bufs[watching] = &empty[0]; - watching--; - } - - for (k = 0;; k++) { - while (k == steps[idxs[i + watching]]) { - bufs[watching] = &empty[0]; - if (watching == 0) { - done = 1; - break; - } - watching--; - } - if (done) { - break; - } - for (j = 0; j < watching + 1; j++) { - set_hash_addr(addrs + j * 8, k + start[idxs[i + j]]); - } - - thashx4(bufs[0], bufs[1], bufs[2], bufs[3], - bufs[0], bufs[1], bufs[2], bufs[3], 1, ctx, addrs); - } - } -} - -/** - * base_w algorithm as described in draft. - * Interprets an array of bytes as integers in base w. - * This only works when log_w is a divisor of 8. - */ -static void base_w(unsigned int *output, const int out_len, - const unsigned char *input) { - int in = 0; - int out = 0; - unsigned char total = 0; - int bits = 0; - int consumed; - - for (consumed = 0; consumed < out_len; consumed++) { - if (bits == 0) { - total = input[in]; - in++; - bits += 8; - } - bits -= SPX_WOTS_LOGW; - output[out] = (total >> bits) & (SPX_WOTS_W - 1); - out++; - } -} - -/* Computes the WOTS+ checksum over a message (in base_w). */ -static void wots_checksum(unsigned int *csum_base_w, - const unsigned int *msg_base_w) { - unsigned int csum = 0; - unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; - unsigned int i; - - /* Compute checksum. */ - for (i = 0; i < SPX_WOTS_LEN1; i++) { - csum += SPX_WOTS_W - 1 - msg_base_w[i]; - } - - /* Convert checksum to base_w. */ - /* Make sure expected empty zero bits are the least significant bits. */ - csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); - ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); - base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); -} - -/* Takes a message and derives the matching chain lengths. */ -void chain_lengths(unsigned int *lengths, const unsigned char *msg) { - base_w(lengths, SPX_WOTS_LEN1, msg); - wots_checksum(lengths + SPX_WOTS_LEN1, lengths); -} - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const spx_ctx *ctx, uint32_t addr[8]) { - unsigned int steps[SPX_WOTS_LEN]; - unsigned int start[SPX_WOTS_LEN]; - uint32_t i; - - chain_lengths(start, msg); - - for (i = 0; i < SPX_WOTS_LEN; i++) { - steps[i] = SPX_WOTS_W - 1 - start[i]; - } - - gen_chains(pk, sig, start, steps, ctx, addr); -} - -/* - * This generates 4 sequential WOTS public keys - * It also generates the WOTS signature if leaf_info indicates - * that we're signing with one of these WOTS keys - */ -void wots_gen_leafx4(unsigned char *dest, - const spx_ctx *ctx, - uint32_t leaf_idx, void *v_info) { - struct leaf_info_x4 *info = v_info; - uint32_t *leaf_addr = info->leaf_addr; - uint32_t *pk_addr = info->pk_addr; - unsigned int i, j, k; - unsigned char pk_buffer[ 4 * SPX_WOTS_BYTES ]; - unsigned wots_offset = SPX_WOTS_BYTES; - unsigned char *buffer; - uint32_t wots_k_mask; - unsigned wots_sign_index; - - if (((leaf_idx ^ info->wots_sign_leaf) & ~3U) == 0) { - /* We're traversing the leaf that's signing; generate the WOTS */ - /* signature */ - wots_k_mask = 0; - wots_sign_index = info->wots_sign_leaf & 3; /* Which of of the 4 */ - /* 4 slots do the signatures come from */ - } else { - /* Nope, we're just generating pk's; turn off the signature logic */ - wots_k_mask = (uint32_t)~0; - wots_sign_index = 0; - } - - for (j = 0; j < 4; j++) { - set_keypair_addr( leaf_addr + j * 8, leaf_idx + j ); - set_keypair_addr( pk_addr + j * 8, leaf_idx + j ); - } - - for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { - uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k to */ - /* the step if we're generating a signature, ~0 if we're not */ - - /* Start with the secret seed */ - for (j = 0; j < 4; j++) { - set_chain_addr(leaf_addr + j * 8, i); - set_hash_addr(leaf_addr + j * 8, 0); - set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTSPRF); - } - prf_addrx4(buffer + 0 * wots_offset, - buffer + 1 * wots_offset, - buffer + 2 * wots_offset, - buffer + 3 * wots_offset, - ctx, leaf_addr); - - for (j = 0; j < 4; j++) { - set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTS); - } - - /* Iterate down the WOTS chain */ - for (k = 0;; k++) { - /* Check if one of the values we have needs to be saved as a */ - /* part of the WOTS signature */ - if (k == wots_k) { - memcpy( info->wots_sig + i * SPX_N, - buffer + wots_sign_index * wots_offset, SPX_N ); - } - - /* Check if we hit the top of the chain */ - if (k == SPX_WOTS_W - 1) { - break; - } - - /* Iterate one step on all 4 chains */ - for (j = 0; j < 4; j++) { - set_hash_addr(leaf_addr + j * 8, k); - } - thashx4(buffer + 0 * wots_offset, - buffer + 1 * wots_offset, - buffer + 2 * wots_offset, - buffer + 3 * wots_offset, - buffer + 0 * wots_offset, - buffer + 1 * wots_offset, - buffer + 2 * wots_offset, - buffer + 3 * wots_offset, 1, ctx, leaf_addr); - } - } - - /* Do the final thash to generate the public keys */ - thashx4(dest + 0 * SPX_N, - dest + 1 * SPX_N, - dest + 2 * SPX_N, - dest + 3 * SPX_N, - pk_buffer + 0 * wots_offset, - pk_buffer + 1 * wots_offset, - pk_buffer + 2 * wots_offset, - pk_buffer + 3 * wots_offset, SPX_WOTS_LEN, ctx, pk_addr); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/wots.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/wots.h deleted file mode 100644 index 4e7692eeef..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/wots.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef SPX_WOTS_H -#define SPX_WOTS_H - -#include - -#include "context.h" -#include "params.h" - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) -void wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const spx_ctx *ctx, uint32_t addr[8]); - -/* - * Compute the chain lengths needed for a given message hash - */ -#define chain_lengths SPX_NAMESPACE(chain_lengths) -void chain_lengths(unsigned int *lengths, const unsigned char *msg); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/wotsx4.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/wotsx4.h deleted file mode 100644 index cd634f1743..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_aesni/wotsx4.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef WOTSX4_H_ -#define WOTSX4_H_ - -#include - -#include "params.h" - -/* - * This is here to provide an interface to the internal wots_gen_leafx4 - * routine. While this routine is not referenced in the package outside of - * wots.c, it is called from the stand-alone benchmark code to characterize - * the performance - */ -struct leaf_info_x4 { - unsigned char *wots_sig; - uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ - uint32_t *wots_steps; - uint32_t leaf_addr[4 * 8]; - uint32_t pk_addr[4 * 8]; -}; - -/* Macro to set the leaf_info to something 'benign', that is, it would */ -/* run with the same time as it does during the real signing process */ -/* Used only by the benchmark code */ -#define INITIALIZE_LEAF_INFO_X4(info, addr, step_buffer) { \ - (info).wots_sig = 0; \ - (info).wots_sign_leaf = ~0; \ - (info).wots_steps = step_buffer; \ - int i; \ - for (i=0; i<4; i++) { \ - memcpy( &(info).leaf_addr[8*i], addr, 32 ); \ - memcpy( &(info).pk_addr[8*i], addr, 32 ); \ - } \ - } - -#define wots_gen_leafx4 SPX_NAMESPACE(wots_gen_leafx4) -void wots_gen_leafx4(unsigned char *dest, - const spx_ctx *ctx, - uint32_t leaf_idx, void *v_info); - -#endif /* WOTSX4_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/LICENSE b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/LICENSE deleted file mode 100644 index 670154e353..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/LICENSE +++ /dev/null @@ -1,116 +0,0 @@ -CC0 1.0 Universal - -Statement of Purpose - -The laws of most jurisdictions throughout the world automatically confer -exclusive Copyright and Related Rights (defined below) upon the creator and -subsequent owner(s) (each and all, an "owner") of an original work of -authorship and/or a database (each, a "Work"). - -Certain owners wish to permanently relinquish those rights to a Work for the -purpose of contributing to a commons of creative, cultural and scientific -works ("Commons") that the public can reliably and without fear of later -claims of infringement build upon, modify, incorporate in other works, reuse -and redistribute as freely as possible in any form whatsoever and for any -purposes, including without limitation commercial purposes. These owners may -contribute to the Commons to promote the ideal of a free culture and the -further production of creative, cultural and scientific works, or to gain -reputation or greater distribution for their Work in part through the use and -efforts of others. - -For these and/or other purposes and motivations, and without any expectation -of additional consideration or compensation, the person associating CC0 with a -Work (the "Affirmer"), to the extent that he or she is an owner of Copyright -and Related Rights in the Work, voluntarily elects to apply CC0 to the Work -and publicly distribute the Work under its terms, with knowledge of his or her -Copyright and Related Rights in the Work and the meaning and intended legal -effect of CC0 on those rights. - -1. Copyright and Related Rights. A Work made available under CC0 may be -protected by copyright and related or neighboring rights ("Copyright and -Related Rights"). Copyright and Related Rights include, but are not limited -to, the following: - - i. the right to reproduce, adapt, distribute, perform, display, communicate, - and translate a Work; - - ii. moral rights retained by the original author(s) and/or performer(s); - - iii. publicity and privacy rights pertaining to a person's image or likeness - depicted in a Work; - - iv. rights protecting against unfair competition in regards to a Work, - subject to the limitations in paragraph 4(a), below; - - v. rights protecting the extraction, dissemination, use and reuse of data in - a Work; - - vi. database rights (such as those arising under Directive 96/9/EC of the - European Parliament and of the Council of 11 March 1996 on the legal - protection of databases, and under any national implementation thereof, - including any amended or successor version of such directive); and - - vii. other similar, equivalent or corresponding rights throughout the world - based on applicable law or treaty, and any national implementations thereof. - -2. Waiver. To the greatest extent permitted by, but not in contravention of, -applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and -unconditionally waives, abandons, and surrenders all of Affirmer's Copyright -and Related Rights and associated claims and causes of action, whether now -known or unknown (including existing as well as future claims and causes of -action), in the Work (i) in all territories worldwide, (ii) for the maximum -duration provided by applicable law or treaty (including future time -extensions), (iii) in any current or future medium and for any number of -copies, and (iv) for any purpose whatsoever, including without limitation -commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes -the Waiver for the benefit of each member of the public at large and to the -detriment of Affirmer's heirs and successors, fully intending that such Waiver -shall not be subject to revocation, rescission, cancellation, termination, or -any other legal or equitable action to disrupt the quiet enjoyment of the Work -by the public as contemplated by Affirmer's express Statement of Purpose. - -3. Public License Fallback. Should any part of the Waiver for any reason be -judged legally invalid or ineffective under applicable law, then the Waiver -shall be preserved to the maximum extent permitted taking into account -Affirmer's express Statement of Purpose. In addition, to the extent the Waiver -is so judged Affirmer hereby grants to each affected person a royalty-free, -non transferable, non sublicensable, non exclusive, irrevocable and -unconditional license to exercise Affirmer's Copyright and Related Rights in -the Work (i) in all territories worldwide, (ii) for the maximum duration -provided by applicable law or treaty (including future time extensions), (iii) -in any current or future medium and for any number of copies, and (iv) for any -purpose whatsoever, including without limitation commercial, advertising or -promotional purposes (the "License"). The License shall be deemed effective as -of the date CC0 was applied by Affirmer to the Work. Should any part of the -License for any reason be judged legally invalid or ineffective under -applicable law, such partial invalidity or ineffectiveness shall not -invalidate the remainder of the License, and in such case Affirmer hereby -affirms that he or she will not (i) exercise any of his or her remaining -Copyright and Related Rights in the Work or (ii) assert any associated claims -and causes of action with respect to the Work, in either case contrary to -Affirmer's express Statement of Purpose. - -4. Limitations and Disclaimers. - - a. No trademark or patent rights held by Affirmer are waived, abandoned, - surrendered, licensed or otherwise affected by this document. - - b. Affirmer offers the Work as-is and makes no representations or warranties - of any kind concerning the Work, express, implied, statutory or otherwise, - including without limitation warranties of title, merchantability, fitness - for a particular purpose, non infringement, or the absence of latent or - other defects, accuracy, or the present or absence of errors, whether or not - discoverable, all to the greatest extent permissible under applicable law. - - c. Affirmer disclaims responsibility for clearing rights of other persons - that may apply to the Work or any use thereof, including without limitation - any person's Copyright and Related Rights in the Work. Further, Affirmer - disclaims responsibility for obtaining any necessary consents, permissions - or other rights required for any use of the Work. - - d. Affirmer understands and acknowledges that Creative Commons is not a - party to this document and has no duty or obligation with respect to this - CC0 or use of the Work. - -For more information, please see - diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/address.c b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/address.c deleted file mode 100644 index b956e9cb29..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/address.c +++ /dev/null @@ -1,91 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "utils.h" - -/* - * Specify which level of Merkle tree (the "layer") we're working on - */ -void set_layer_addr(uint32_t addr[8], uint32_t layer) { - ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; -} - -/* - * Specify which Merkle tree within the level (the "tree address") we're working on - */ -void set_tree_addr(uint32_t addr[8], uint64_t tree) { - ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); -} - -/* - * Specify the reason we'll use this address structure for, that is, what - * hash will we compute with it. This is used so that unrelated types of - * hashes don't accidentally get the same address structure. The type will be - * one of the SPX_ADDR_TYPE constants - */ -void set_type(uint32_t addr[8], uint32_t type) { - ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; -} - -/* - * Copy the layer and tree fields of the address structure. This is used - * when we're doing multiple types of hashes within the same Merkle tree - */ -void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { - memcpy( out, in, SPX_OFFSET_TREE + 8 ); -} - -/* These functions are used for OTS addresses. */ - -/* - * Specify which Merkle leaf we're working on; that is, which OTS keypair - * we're talking about. - */ -void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { - ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; -} - -/* - * Copy the layer, tree and keypair fields of the address structure. This is - * used when we're doing multiple things within the same OTS keypair - */ -void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { - memcpy( out, in, SPX_OFFSET_TREE + 8 ); - ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; -} - -/* - * Specify which Merkle chain within the OTS we're working with - * (the chain address) - */ -void set_chain_addr(uint32_t addr[8], uint32_t chain) { - ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; -} - -/* - * Specify where in the Merkle chain we are -* (the hash address) - */ -void set_hash_addr(uint32_t addr[8], uint32_t hash) { - ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; -} - -/* These functions are used for all hash tree addresses (including FORS). */ - -/* - * Specify the height of the node in the Merkle/FORS tree we are in - * (the tree height) - */ -void set_tree_height(uint32_t addr[8], uint32_t tree_height) { - ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; -} - -/* - * Specify the distance from the left edge of the node in the Merkle/FORS tree - * (the tree index) - */ -void set_tree_index(uint32_t addr[8], uint32_t tree_index) { - u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/address.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/address.h deleted file mode 100644 index 24a84eb40c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/address.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef SPX_ADDRESS_H -#define SPX_ADDRESS_H - -#include - -#include "params.h" - -/* The hash types that are passed to set_type */ -#define SPX_ADDR_TYPE_WOTS 0 -#define SPX_ADDR_TYPE_WOTSPK 1 -#define SPX_ADDR_TYPE_HASHTREE 2 -#define SPX_ADDR_TYPE_FORSTREE 3 -#define SPX_ADDR_TYPE_FORSPK 4 -#define SPX_ADDR_TYPE_WOTSPRF 5 -#define SPX_ADDR_TYPE_FORSPRF 6 - -#define set_layer_addr SPX_NAMESPACE(set_layer_addr) -void set_layer_addr(uint32_t addr[8], uint32_t layer); - -#define set_tree_addr SPX_NAMESPACE(set_tree_addr) -void set_tree_addr(uint32_t addr[8], uint64_t tree); - -#define set_type SPX_NAMESPACE(set_type) -void set_type(uint32_t addr[8], uint32_t type); - -/* Copies the layer and tree part of one address into the other */ -#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) -void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for WOTS and FORS addresses. */ - -#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) -void set_keypair_addr(uint32_t addr[8], uint32_t keypair); - -#define set_chain_addr SPX_NAMESPACE(set_chain_addr) -void set_chain_addr(uint32_t addr[8], uint32_t chain); - -#define set_hash_addr SPX_NAMESPACE(set_hash_addr) -void set_hash_addr(uint32_t addr[8], uint32_t hash); - -#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) -void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for all hash tree addresses (including FORS). */ - -#define set_tree_height SPX_NAMESPACE(set_tree_height) -void set_tree_height(uint32_t addr[8], uint32_t tree_height); - -#define set_tree_index SPX_NAMESPACE(set_tree_index) -void set_tree_index(uint32_t addr[8], uint32_t tree_index); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/api.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/api.h deleted file mode 100644 index b84a77dc3b..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/api.h +++ /dev/null @@ -1,77 +0,0 @@ -#ifndef PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_API_H -#define PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_API_H - -#include -#include - -#define PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_CRYPTO_ALGNAME "SPHINCS+-haraka-128f-robust" - -#define PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_CRYPTO_SECRETKEYBYTES 64 -#define PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_CRYPTO_PUBLICKEYBYTES 32 -#define PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_CRYPTO_BYTES 17088 - -#define PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_CRYPTO_SEEDBYTES 48 - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, - const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk); -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/context.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/context.h deleted file mode 100644 index 600dfb73c7..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/context.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef SPX_CONTEXT_H -#define SPX_CONTEXT_H - -#include -#include - -#include "params.h" - -typedef struct { - uint8_t pub_seed[SPX_N]; - uint8_t sk_seed[SPX_N]; - - - uint64_t tweaked512_rc64[10][8]; - uint32_t tweaked256_rc32[10][8]; -} spx_ctx; - -#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) -void initialize_hash_function(spx_ctx *ctx); - -#define free_hash_function SPX_NAMESPACE(free_hash_function) -void free_hash_function(spx_ctx *ctx); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/context_haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/context_haraka.c deleted file mode 100644 index f1cd7e3664..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/context_haraka.c +++ /dev/null @@ -1,11 +0,0 @@ -#include "context.h" -#include "haraka.h" - -void initialize_hash_function(spx_ctx *ctx) { - tweak_constants(ctx); -} - -// we don't support heap-based haraka right now -void free_hash_function(spx_ctx *ctx) { - (void)ctx; // suppress unused variable warnings -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/fors.c b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/fors.c deleted file mode 100644 index 96ca72e986..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/fors.c +++ /dev/null @@ -1,156 +0,0 @@ -#include -#include -#include - -#include "fors.h" - -#include "address.h" -#include "hash.h" -#include "thash.h" -#include "utils.h" -#include "utilsx1.h" - -static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, - uint32_t fors_leaf_addr[8]) { - prf_addr(sk, ctx, fors_leaf_addr); -} - -static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, - const spx_ctx *ctx, - uint32_t fors_leaf_addr[8]) { - thash(leaf, sk, 1, ctx, fors_leaf_addr); -} - -struct fors_gen_leaf_info { - uint32_t leaf_addrx[8]; -}; - -static void fors_gen_leafx1(unsigned char *leaf, - const spx_ctx *ctx, - uint32_t addr_idx, void *info) { - struct fors_gen_leaf_info *fors_info = info; - uint32_t *fors_leaf_addr = fors_info->leaf_addrx; - - /* Only set the parts that the caller doesn't set */ - set_tree_index(fors_leaf_addr, addr_idx); - set_type(fors_leaf_addr, SPX_ADDR_TYPE_FORSPRF); - fors_gen_sk(leaf, ctx, fors_leaf_addr); - - set_type(fors_leaf_addr, SPX_ADDR_TYPE_FORSTREE); - fors_sk_to_leaf(leaf, leaf, - ctx, fors_leaf_addr); -} - -/** - * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - * Assumes indices has space for SPX_FORS_TREES integers. - */ -static void message_to_indices(uint32_t *indices, const unsigned char *m) { - unsigned int i, j; - unsigned int offset = 0; - - for (i = 0; i < SPX_FORS_TREES; i++) { - indices[i] = 0; - for (j = 0; j < SPX_FORS_HEIGHT; j++) { - indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); - offset++; - } - } -} - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -void fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]) { - uint32_t indices[SPX_FORS_TREES]; - unsigned char roots[SPX_FORS_TREES * SPX_N]; - uint32_t fors_tree_addr[8] = {0}; - struct fors_gen_leaf_info fors_info = {0}; - uint32_t *fors_leaf_addr = fors_info.leaf_addrx; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - copy_keypair_addr(fors_tree_addr, fors_addr); - copy_keypair_addr(fors_leaf_addr, fors_addr); - - copy_keypair_addr(fors_pk_addr, fors_addr); - set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < SPX_FORS_TREES; i++) { - idx_offset = i * (1 << SPX_FORS_HEIGHT); - - set_tree_height(fors_tree_addr, 0); - set_tree_index(fors_tree_addr, indices[i] + idx_offset); - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); - - /* Include the secret key part that produces the selected leaf node. */ - fors_gen_sk(sig, ctx, fors_tree_addr); - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); - sig += SPX_N; - - /* Compute the authentication path for this leaf node. */ - treehashx1(roots + i * SPX_N, sig, ctx, - indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx1, - fors_tree_addr, &fors_info); - - sig += SPX_N * SPX_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); -} - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -void fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]) { - uint32_t indices[SPX_FORS_TREES]; - unsigned char roots[SPX_FORS_TREES * SPX_N]; - unsigned char leaf[SPX_N]; - uint32_t fors_tree_addr[8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - copy_keypair_addr(fors_tree_addr, fors_addr); - copy_keypair_addr(fors_pk_addr, fors_addr); - - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); - set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < SPX_FORS_TREES; i++) { - idx_offset = i * (1 << SPX_FORS_HEIGHT); - - set_tree_height(fors_tree_addr, 0); - set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Derive the leaf from the included secret key part. */ - fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); - sig += SPX_N; - - /* Derive the corresponding root node of this tree. */ - compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, - sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); - sig += SPX_N * SPX_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/fors.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/fors.h deleted file mode 100644 index 509140a178..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/fors.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef SPX_FORS_H -#define SPX_FORS_H - -#include - -#include "context.h" -#include "params.h" - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -#define fors_sign SPX_NAMESPACE(fors_sign) -void fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]); - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) -void fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/haraka.c deleted file mode 100644 index a4944913b5..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/haraka.c +++ /dev/null @@ -1,913 +0,0 @@ -/* - * Constant time implementation of the Haraka hash function. - * - * The bit-sliced implementation of the AES round functions are - * based on the AES implementation in BearSSL written - * by Thomas Pornin - */ - -#include -#include -#include -#include - -#include "haraka.h" -#include "utils.h" - -#define HARAKAS_RATE 32 - -static const uint64_t haraka512_rc64[10][8] = { - {0x24cf0ab9086f628b, 0xbdd6eeecc83b8382, 0xd96fb0306cdad0a7, 0xaace082ac8f95f89, 0x449d8e8870d7041f, 0x49bb2f80b2b3e2f8, 0x0569ae98d93bb258, 0x23dc9691e7d6a4b1}, - {0xd8ba10ede0fe5b6e, 0x7ecf7dbe424c7b8e, 0x6ea9949c6df62a31, 0xbf3f3c97ec9c313e, 0x241d03a196a1861e, 0xead3a51116e5a2ea, 0x77d479fcad9574e3, 0x18657a1af894b7a0}, - {0x10671e1a7f595522, 0xd9a00ff675d28c7b, 0x2f1edf0d2b9ba661, 0xb8ff58b8e3de45f9, 0xee29261da9865c02, 0xd1532aa4b50bdf43, 0x8bf858159b231bb1, 0xdf17439d22d4f599}, - {0xdd4b2f0870b918c0, 0x757a81f3b39b1bb6, 0x7a5c556898952e3f, 0x7dd70a16d915d87a, 0x3ae61971982b8301, 0xc3ab319e030412be, 0x17c0033ac094a8cb, 0x5a0630fc1a8dc4ef}, - {0x17708988c1632f73, 0xf92ddae090b44f4f, 0x11ac0285c43aa314, 0x509059941936b8ba, 0xd03e152fa2ce9b69, 0x3fbcbcb63a32998b, 0x6204696d692254f7, 0x915542ed93ec59b4}, - {0xf4ed94aa8879236e, 0xff6cb41cd38e03c0, 0x069b38602368aeab, 0x669495b820f0ddba, 0xf42013b1b8bf9e3d, 0xcf935efe6439734d, 0xbc1dcf42ca29e3f8, 0x7e6d3ed29f78ad67}, - {0xf3b0f6837ffcddaa, 0x3a76faef934ddf41, 0xcec7ae583a9c8e35, 0xe4dd18c68f0260af, 0x2c0e5df1ad398eaa, 0x478df5236ae22e8c, 0xfb944c46fe865f39, 0xaa48f82f028132ba}, - {0x231b9ae2b76aca77, 0x292a76a712db0b40, 0x5850625dc8134491, 0x73137dd469810fb5, 0x8a12a6a202a474fd, 0xd36fd9daa78bdb80, 0xb34c5e733505706f, 0xbaf1cdca818d9d96}, - {0x2e99781335e8c641, 0xbddfe5cce47d560e, 0xf74e9bf32e5e040c, 0x1d7a709d65996be9, 0x670df36a9cf66cdd, 0xd05ef84a176a2875, 0x0f888e828cb1c44e, 0x1a79e9c9727b052c}, - {0x83497348628d84de, 0x2e9387d51f22a754, 0xb000068da2f852d6, 0x378c9e1190fd6fe5, 0x870027c316de7293, 0xe51a9d4462e047bb, 0x90ecf7f8c6251195, 0x655953bfbed90a9c}, -}; - -static inline uint32_t br_dec32le(const unsigned char *src) { - return (uint32_t)src[0] - | ((uint32_t)src[1] << 8) - | ((uint32_t)src[2] << 16) - | ((uint32_t)src[3] << 24); -} - -static void br_range_dec32le(uint32_t *v, size_t num, const unsigned char *src) { - while (num-- > 0) { - *v ++ = br_dec32le(src); - src += 4; - } -} - -static inline void br_enc32le(unsigned char *dst, uint32_t x) { - dst[0] = (unsigned char)x; - dst[1] = (unsigned char)(x >> 8); - dst[2] = (unsigned char)(x >> 16); - dst[3] = (unsigned char)(x >> 24); -} - - -static void br_range_enc32le(unsigned char *dst, const uint32_t *v, size_t num) { - while (num-- > 0) { - br_enc32le(dst, *v ++); - dst += 4; - } -} - -static void br_aes_ct64_bitslice_Sbox(uint64_t *q) { - /* - * This S-box implementation is a straightforward translation of - * the circuit described by Boyar and Peralta in "A new - * combinational logic minimization technique with applications - * to cryptology" (https://eprint.iacr.org/2009/191.pdf). - * - * Note that variables x* (input) and s* (output) are numbered - * in "reverse" order (x0 is the high bit, x7 is the low bit). - */ - - uint64_t x0, x1, x2, x3, x4, x5, x6, x7; - uint64_t y1, y2, y3, y4, y5, y6, y7, y8, y9; - uint64_t y10, y11, y12, y13, y14, y15, y16, y17, y18, y19; - uint64_t y20, y21; - uint64_t z0, z1, z2, z3, z4, z5, z6, z7, z8, z9; - uint64_t z10, z11, z12, z13, z14, z15, z16, z17; - uint64_t t0, t1, t2, t3, t4, t5, t6, t7, t8, t9; - uint64_t t10, t11, t12, t13, t14, t15, t16, t17, t18, t19; - uint64_t t20, t21, t22, t23, t24, t25, t26, t27, t28, t29; - uint64_t t30, t31, t32, t33, t34, t35, t36, t37, t38, t39; - uint64_t t40, t41, t42, t43, t44, t45, t46, t47, t48, t49; - uint64_t t50, t51, t52, t53, t54, t55, t56, t57, t58, t59; - uint64_t t60, t61, t62, t63, t64, t65, t66, t67; - uint64_t s0, s1, s2, s3, s4, s5, s6, s7; - - x0 = q[7]; - x1 = q[6]; - x2 = q[5]; - x3 = q[4]; - x4 = q[3]; - x5 = q[2]; - x6 = q[1]; - x7 = q[0]; - - /* - * Top linear transformation. - */ - y14 = x3 ^ x5; - y13 = x0 ^ x6; - y9 = x0 ^ x3; - y8 = x0 ^ x5; - t0 = x1 ^ x2; - y1 = t0 ^ x7; - y4 = y1 ^ x3; - y12 = y13 ^ y14; - y2 = y1 ^ x0; - y5 = y1 ^ x6; - y3 = y5 ^ y8; - t1 = x4 ^ y12; - y15 = t1 ^ x5; - y20 = t1 ^ x1; - y6 = y15 ^ x7; - y10 = y15 ^ t0; - y11 = y20 ^ y9; - y7 = x7 ^ y11; - y17 = y10 ^ y11; - y19 = y10 ^ y8; - y16 = t0 ^ y11; - y21 = y13 ^ y16; - y18 = x0 ^ y16; - - /* - * Non-linear section. - */ - t2 = y12 & y15; - t3 = y3 & y6; - t4 = t3 ^ t2; - t5 = y4 & x7; - t6 = t5 ^ t2; - t7 = y13 & y16; - t8 = y5 & y1; - t9 = t8 ^ t7; - t10 = y2 & y7; - t11 = t10 ^ t7; - t12 = y9 & y11; - t13 = y14 & y17; - t14 = t13 ^ t12; - t15 = y8 & y10; - t16 = t15 ^ t12; - t17 = t4 ^ t14; - t18 = t6 ^ t16; - t19 = t9 ^ t14; - t20 = t11 ^ t16; - t21 = t17 ^ y20; - t22 = t18 ^ y19; - t23 = t19 ^ y21; - t24 = t20 ^ y18; - - t25 = t21 ^ t22; - t26 = t21 & t23; - t27 = t24 ^ t26; - t28 = t25 & t27; - t29 = t28 ^ t22; - t30 = t23 ^ t24; - t31 = t22 ^ t26; - t32 = t31 & t30; - t33 = t32 ^ t24; - t34 = t23 ^ t33; - t35 = t27 ^ t33; - t36 = t24 & t35; - t37 = t36 ^ t34; - t38 = t27 ^ t36; - t39 = t29 & t38; - t40 = t25 ^ t39; - - t41 = t40 ^ t37; - t42 = t29 ^ t33; - t43 = t29 ^ t40; - t44 = t33 ^ t37; - t45 = t42 ^ t41; - z0 = t44 & y15; - z1 = t37 & y6; - z2 = t33 & x7; - z3 = t43 & y16; - z4 = t40 & y1; - z5 = t29 & y7; - z6 = t42 & y11; - z7 = t45 & y17; - z8 = t41 & y10; - z9 = t44 & y12; - z10 = t37 & y3; - z11 = t33 & y4; - z12 = t43 & y13; - z13 = t40 & y5; - z14 = t29 & y2; - z15 = t42 & y9; - z16 = t45 & y14; - z17 = t41 & y8; - - /* - * Bottom linear transformation. - */ - t46 = z15 ^ z16; - t47 = z10 ^ z11; - t48 = z5 ^ z13; - t49 = z9 ^ z10; - t50 = z2 ^ z12; - t51 = z2 ^ z5; - t52 = z7 ^ z8; - t53 = z0 ^ z3; - t54 = z6 ^ z7; - t55 = z16 ^ z17; - t56 = z12 ^ t48; - t57 = t50 ^ t53; - t58 = z4 ^ t46; - t59 = z3 ^ t54; - t60 = t46 ^ t57; - t61 = z14 ^ t57; - t62 = t52 ^ t58; - t63 = t49 ^ t58; - t64 = z4 ^ t59; - t65 = t61 ^ t62; - t66 = z1 ^ t63; - s0 = t59 ^ t63; - s6 = t56 ^ ~t62; - s7 = t48 ^ ~t60; - t67 = t64 ^ t65; - s3 = t53 ^ t66; - s4 = t51 ^ t66; - s5 = t47 ^ t65; - s1 = t64 ^ ~s3; - s2 = t55 ^ ~t67; - - q[7] = s0; - q[6] = s1; - q[5] = s2; - q[4] = s3; - q[3] = s4; - q[2] = s5; - q[1] = s6; - q[0] = s7; -} - -static void br_aes_ct_bitslice_Sbox(uint32_t *q) { - /* - * This S-box implementation is a straightforward translation of - * the circuit described by Boyar and Peralta in "A new - * combinational logic minimization technique with applications - * to cryptology" (https://eprint.iacr.org/2009/191.pdf). - * - * Note that variables x* (input) and s* (output) are numbered - * in "reverse" order (x0 is the high bit, x7 is the low bit). - */ - - uint32_t x0, x1, x2, x3, x4, x5, x6, x7; - uint32_t y1, y2, y3, y4, y5, y6, y7, y8, y9; - uint32_t y10, y11, y12, y13, y14, y15, y16, y17, y18, y19; - uint32_t y20, y21; - uint32_t z0, z1, z2, z3, z4, z5, z6, z7, z8, z9; - uint32_t z10, z11, z12, z13, z14, z15, z16, z17; - uint32_t t0, t1, t2, t3, t4, t5, t6, t7, t8, t9; - uint32_t t10, t11, t12, t13, t14, t15, t16, t17, t18, t19; - uint32_t t20, t21, t22, t23, t24, t25, t26, t27, t28, t29; - uint32_t t30, t31, t32, t33, t34, t35, t36, t37, t38, t39; - uint32_t t40, t41, t42, t43, t44, t45, t46, t47, t48, t49; - uint32_t t50, t51, t52, t53, t54, t55, t56, t57, t58, t59; - uint32_t t60, t61, t62, t63, t64, t65, t66, t67; - uint32_t s0, s1, s2, s3, s4, s5, s6, s7; - - x0 = q[7]; - x1 = q[6]; - x2 = q[5]; - x3 = q[4]; - x4 = q[3]; - x5 = q[2]; - x6 = q[1]; - x7 = q[0]; - - /* - * Top linear transformation. - */ - y14 = x3 ^ x5; - y13 = x0 ^ x6; - y9 = x0 ^ x3; - y8 = x0 ^ x5; - t0 = x1 ^ x2; - y1 = t0 ^ x7; - y4 = y1 ^ x3; - y12 = y13 ^ y14; - y2 = y1 ^ x0; - y5 = y1 ^ x6; - y3 = y5 ^ y8; - t1 = x4 ^ y12; - y15 = t1 ^ x5; - y20 = t1 ^ x1; - y6 = y15 ^ x7; - y10 = y15 ^ t0; - y11 = y20 ^ y9; - y7 = x7 ^ y11; - y17 = y10 ^ y11; - y19 = y10 ^ y8; - y16 = t0 ^ y11; - y21 = y13 ^ y16; - y18 = x0 ^ y16; - - /* - * Non-linear section. - */ - t2 = y12 & y15; - t3 = y3 & y6; - t4 = t3 ^ t2; - t5 = y4 & x7; - t6 = t5 ^ t2; - t7 = y13 & y16; - t8 = y5 & y1; - t9 = t8 ^ t7; - t10 = y2 & y7; - t11 = t10 ^ t7; - t12 = y9 & y11; - t13 = y14 & y17; - t14 = t13 ^ t12; - t15 = y8 & y10; - t16 = t15 ^ t12; - t17 = t4 ^ t14; - t18 = t6 ^ t16; - t19 = t9 ^ t14; - t20 = t11 ^ t16; - t21 = t17 ^ y20; - t22 = t18 ^ y19; - t23 = t19 ^ y21; - t24 = t20 ^ y18; - - t25 = t21 ^ t22; - t26 = t21 & t23; - t27 = t24 ^ t26; - t28 = t25 & t27; - t29 = t28 ^ t22; - t30 = t23 ^ t24; - t31 = t22 ^ t26; - t32 = t31 & t30; - t33 = t32 ^ t24; - t34 = t23 ^ t33; - t35 = t27 ^ t33; - t36 = t24 & t35; - t37 = t36 ^ t34; - t38 = t27 ^ t36; - t39 = t29 & t38; - t40 = t25 ^ t39; - - t41 = t40 ^ t37; - t42 = t29 ^ t33; - t43 = t29 ^ t40; - t44 = t33 ^ t37; - t45 = t42 ^ t41; - z0 = t44 & y15; - z1 = t37 & y6; - z2 = t33 & x7; - z3 = t43 & y16; - z4 = t40 & y1; - z5 = t29 & y7; - z6 = t42 & y11; - z7 = t45 & y17; - z8 = t41 & y10; - z9 = t44 & y12; - z10 = t37 & y3; - z11 = t33 & y4; - z12 = t43 & y13; - z13 = t40 & y5; - z14 = t29 & y2; - z15 = t42 & y9; - z16 = t45 & y14; - z17 = t41 & y8; - - /* - * Bottom linear transformation. - */ - t46 = z15 ^ z16; - t47 = z10 ^ z11; - t48 = z5 ^ z13; - t49 = z9 ^ z10; - t50 = z2 ^ z12; - t51 = z2 ^ z5; - t52 = z7 ^ z8; - t53 = z0 ^ z3; - t54 = z6 ^ z7; - t55 = z16 ^ z17; - t56 = z12 ^ t48; - t57 = t50 ^ t53; - t58 = z4 ^ t46; - t59 = z3 ^ t54; - t60 = t46 ^ t57; - t61 = z14 ^ t57; - t62 = t52 ^ t58; - t63 = t49 ^ t58; - t64 = z4 ^ t59; - t65 = t61 ^ t62; - t66 = z1 ^ t63; - s0 = t59 ^ t63; - s6 = t56 ^ ~t62; - s7 = t48 ^ ~t60; - t67 = t64 ^ t65; - s3 = t53 ^ t66; - s4 = t51 ^ t66; - s5 = t47 ^ t65; - s1 = t64 ^ ~s3; - s2 = t55 ^ ~t67; - - q[7] = s0; - q[6] = s1; - q[5] = s2; - q[4] = s3; - q[3] = s4; - q[2] = s5; - q[1] = s6; - q[0] = s7; -} - -static void br_aes_ct_ortho(uint32_t *q) { -#define SWAPN_32(cl, ch, s, x, y) do { \ - uint32_t a, b; \ - a = (x); \ - b = (y); \ - (x) = (a & (uint32_t)(cl)) | ((b & (uint32_t)(cl)) << (s)); \ - (y) = ((a & (uint32_t)(ch)) >> (s)) | (b & (uint32_t)(ch)); \ - } while (0) - -#define SWAP2_32(x, y) SWAPN_32(0x55555555, 0xAAAAAAAA, 1, x, y) -#define SWAP4_32(x, y) SWAPN_32(0x33333333, 0xCCCCCCCC, 2, x, y) -#define SWAP8_32(x, y) SWAPN_32(0x0F0F0F0F, 0xF0F0F0F0, 4, x, y) - - SWAP2_32(q[0], q[1]); - SWAP2_32(q[2], q[3]); - SWAP2_32(q[4], q[5]); - SWAP2_32(q[6], q[7]); - - SWAP4_32(q[0], q[2]); - SWAP4_32(q[1], q[3]); - SWAP4_32(q[4], q[6]); - SWAP4_32(q[5], q[7]); - - SWAP8_32(q[0], q[4]); - SWAP8_32(q[1], q[5]); - SWAP8_32(q[2], q[6]); - SWAP8_32(q[3], q[7]); -} - -static inline void add_round_key32(uint32_t *q, const uint32_t *sk) { - q[0] ^= sk[0]; - q[1] ^= sk[1]; - q[2] ^= sk[2]; - q[3] ^= sk[3]; - q[4] ^= sk[4]; - q[5] ^= sk[5]; - q[6] ^= sk[6]; - q[7] ^= sk[7]; -} - -static inline void shift_rows32(uint32_t *q) { - int i; - - for (i = 0; i < 8; i++) { - uint32_t x; - - x = q[i]; - q[i] = (x & 0x000000FF) - | ((x & 0x0000FC00) >> 2) | ((x & 0x00000300) << 6) - | ((x & 0x00F00000) >> 4) | ((x & 0x000F0000) << 4) - | ((x & 0xC0000000) >> 6) | ((x & 0x3F000000) << 2); - } -} - -static inline uint32_t rotr16(uint32_t x) { - return (x << 16) | (x >> 16); -} - -static inline void mix_columns32(uint32_t *q) { - uint32_t q0, q1, q2, q3, q4, q5, q6, q7; - uint32_t r0, r1, r2, r3, r4, r5, r6, r7; - - q0 = q[0]; - q1 = q[1]; - q2 = q[2]; - q3 = q[3]; - q4 = q[4]; - q5 = q[5]; - q6 = q[6]; - q7 = q[7]; - r0 = (q0 >> 8) | (q0 << 24); - r1 = (q1 >> 8) | (q1 << 24); - r2 = (q2 >> 8) | (q2 << 24); - r3 = (q3 >> 8) | (q3 << 24); - r4 = (q4 >> 8) | (q4 << 24); - r5 = (q5 >> 8) | (q5 << 24); - r6 = (q6 >> 8) | (q6 << 24); - r7 = (q7 >> 8) | (q7 << 24); - - q[0] = q7 ^ r7 ^ r0 ^ rotr16(q0 ^ r0); - q[1] = q0 ^ r0 ^ q7 ^ r7 ^ r1 ^ rotr16(q1 ^ r1); - q[2] = q1 ^ r1 ^ r2 ^ rotr16(q2 ^ r2); - q[3] = q2 ^ r2 ^ q7 ^ r7 ^ r3 ^ rotr16(q3 ^ r3); - q[4] = q3 ^ r3 ^ q7 ^ r7 ^ r4 ^ rotr16(q4 ^ r4); - q[5] = q4 ^ r4 ^ r5 ^ rotr16(q5 ^ r5); - q[6] = q5 ^ r5 ^ r6 ^ rotr16(q6 ^ r6); - q[7] = q6 ^ r6 ^ r7 ^ rotr16(q7 ^ r7); -} - -static void br_aes_ct64_ortho(uint64_t *q) { -#define SWAPN(cl, ch, s, x, y) do { \ - uint64_t a, b; \ - a = (x); \ - b = (y); \ - (x) = (a & (uint64_t)(cl)) | ((b & (uint64_t)(cl)) << (s)); \ - (y) = ((a & (uint64_t)(ch)) >> (s)) | (b & (uint64_t)(ch)); \ - } while (0) - -#define SWAP2(x, y) SWAPN(0x5555555555555555, 0xAAAAAAAAAAAAAAAA, 1, x, y) -#define SWAP4(x, y) SWAPN(0x3333333333333333, 0xCCCCCCCCCCCCCCCC, 2, x, y) -#define SWAP8(x, y) SWAPN(0x0F0F0F0F0F0F0F0F, 0xF0F0F0F0F0F0F0F0, 4, x, y) - - SWAP2(q[0], q[1]); - SWAP2(q[2], q[3]); - SWAP2(q[4], q[5]); - SWAP2(q[6], q[7]); - - SWAP4(q[0], q[2]); - SWAP4(q[1], q[3]); - SWAP4(q[4], q[6]); - SWAP4(q[5], q[7]); - - SWAP8(q[0], q[4]); - SWAP8(q[1], q[5]); - SWAP8(q[2], q[6]); - SWAP8(q[3], q[7]); -} - - -static void br_aes_ct64_interleave_in(uint64_t *q0, uint64_t *q1, const uint32_t *w) { - uint64_t x0, x1, x2, x3; - - x0 = w[0]; - x1 = w[1]; - x2 = w[2]; - x3 = w[3]; - x0 |= (x0 << 16); - x1 |= (x1 << 16); - x2 |= (x2 << 16); - x3 |= (x3 << 16); - x0 &= (uint64_t)0x0000FFFF0000FFFF; - x1 &= (uint64_t)0x0000FFFF0000FFFF; - x2 &= (uint64_t)0x0000FFFF0000FFFF; - x3 &= (uint64_t)0x0000FFFF0000FFFF; - x0 |= (x0 << 8); - x1 |= (x1 << 8); - x2 |= (x2 << 8); - x3 |= (x3 << 8); - x0 &= (uint64_t)0x00FF00FF00FF00FF; - x1 &= (uint64_t)0x00FF00FF00FF00FF; - x2 &= (uint64_t)0x00FF00FF00FF00FF; - x3 &= (uint64_t)0x00FF00FF00FF00FF; - *q0 = x0 | (x2 << 8); - *q1 = x1 | (x3 << 8); -} - - -static void br_aes_ct64_interleave_out(uint32_t *w, uint64_t q0, uint64_t q1) { - uint64_t x0, x1, x2, x3; - - x0 = q0 & (uint64_t)0x00FF00FF00FF00FF; - x1 = q1 & (uint64_t)0x00FF00FF00FF00FF; - x2 = (q0 >> 8) & (uint64_t)0x00FF00FF00FF00FF; - x3 = (q1 >> 8) & (uint64_t)0x00FF00FF00FF00FF; - x0 |= (x0 >> 8); - x1 |= (x1 >> 8); - x2 |= (x2 >> 8); - x3 |= (x3 >> 8); - x0 &= (uint64_t)0x0000FFFF0000FFFF; - x1 &= (uint64_t)0x0000FFFF0000FFFF; - x2 &= (uint64_t)0x0000FFFF0000FFFF; - x3 &= (uint64_t)0x0000FFFF0000FFFF; - w[0] = (uint32_t)x0 | (uint32_t)(x0 >> 16); - w[1] = (uint32_t)x1 | (uint32_t)(x1 >> 16); - w[2] = (uint32_t)x2 | (uint32_t)(x2 >> 16); - w[3] = (uint32_t)x3 | (uint32_t)(x3 >> 16); -} - -static inline void add_round_key(uint64_t *q, const uint64_t *sk) { - q[0] ^= sk[0]; - q[1] ^= sk[1]; - q[2] ^= sk[2]; - q[3] ^= sk[3]; - q[4] ^= sk[4]; - q[5] ^= sk[5]; - q[6] ^= sk[6]; - q[7] ^= sk[7]; -} - -static inline void shift_rows(uint64_t *q) { - int i; - - for (i = 0; i < 8; i++) { - uint64_t x; - - x = q[i]; - q[i] = (x & (uint64_t)0x000000000000FFFF) - | ((x & (uint64_t)0x00000000FFF00000) >> 4) - | ((x & (uint64_t)0x00000000000F0000) << 12) - | ((x & (uint64_t)0x0000FF0000000000) >> 8) - | ((x & (uint64_t)0x000000FF00000000) << 8) - | ((x & (uint64_t)0xF000000000000000) >> 12) - | ((x & (uint64_t)0x0FFF000000000000) << 4); - } -} - -static inline uint64_t rotr32(uint64_t x) { - return (x << 32) | (x >> 32); -} - -static inline void mix_columns(uint64_t *q) { - uint64_t q0, q1, q2, q3, q4, q5, q6, q7; - uint64_t r0, r1, r2, r3, r4, r5, r6, r7; - - q0 = q[0]; - q1 = q[1]; - q2 = q[2]; - q3 = q[3]; - q4 = q[4]; - q5 = q[5]; - q6 = q[6]; - q7 = q[7]; - r0 = (q0 >> 16) | (q0 << 48); - r1 = (q1 >> 16) | (q1 << 48); - r2 = (q2 >> 16) | (q2 << 48); - r3 = (q3 >> 16) | (q3 << 48); - r4 = (q4 >> 16) | (q4 << 48); - r5 = (q5 >> 16) | (q5 << 48); - r6 = (q6 >> 16) | (q6 << 48); - r7 = (q7 >> 16) | (q7 << 48); - - q[0] = q7 ^ r7 ^ r0 ^ rotr32(q0 ^ r0); - q[1] = q0 ^ r0 ^ q7 ^ r7 ^ r1 ^ rotr32(q1 ^ r1); - q[2] = q1 ^ r1 ^ r2 ^ rotr32(q2 ^ r2); - q[3] = q2 ^ r2 ^ q7 ^ r7 ^ r3 ^ rotr32(q3 ^ r3); - q[4] = q3 ^ r3 ^ q7 ^ r7 ^ r4 ^ rotr32(q4 ^ r4); - q[5] = q4 ^ r4 ^ r5 ^ rotr32(q5 ^ r5); - q[6] = q5 ^ r5 ^ r6 ^ rotr32(q6 ^ r6); - q[7] = q6 ^ r6 ^ r7 ^ rotr32(q7 ^ r7); -} - -static void interleave_constant(uint64_t *out, const unsigned char *in) { - uint32_t tmp_32_constant[16]; - int i; - - br_range_dec32le(tmp_32_constant, 16, in); - for (i = 0; i < 4; i++) { - br_aes_ct64_interleave_in(&out[i], &out[i + 4], tmp_32_constant + (i << 2)); - } - br_aes_ct64_ortho(out); -} - -static void interleave_constant32(uint32_t *out, const unsigned char *in) { - int i; - for (i = 0; i < 4; i++) { - out[2 * i] = br_dec32le(in + 4 * i); - out[2 * i + 1] = br_dec32le(in + 4 * i + 16); - } - br_aes_ct_ortho(out); -} - -void tweak_constants(spx_ctx *ctx) { - unsigned char buf[40 * 16]; - int i; - - /* Use the standard constants to generate tweaked ones. */ - memcpy((uint8_t *)ctx->tweaked512_rc64, (uint8_t *)haraka512_rc64, 40 * 16); - - /* Constants for pk.seed */ - haraka_S(buf, 40 * 16, ctx->pub_seed, SPX_N, ctx); - for (i = 0; i < 10; i++) { - interleave_constant32(ctx->tweaked256_rc32[i], buf + 32 * i); - interleave_constant(ctx->tweaked512_rc64[i], buf + 64 * i); - } -} - -static void haraka_S_absorb(unsigned char *s, unsigned int r, - const unsigned char *m, unsigned long long mlen, - unsigned char p, const spx_ctx *ctx) { - unsigned long long i; - PQCLEAN_VLA(uint8_t, t, r); - - while (mlen >= r) { - /* XOR block to state */ - for (i = 0; i < r; ++i) { - s[i] ^= m[i]; - } - haraka512_perm(s, s, ctx); - 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; ++i) { - s[i] ^= t[i]; - } -} - -static void haraka_S_squeezeblocks(unsigned char *h, unsigned long long nblocks, - unsigned char *s, unsigned int r, - const spx_ctx *ctx) { - while (nblocks > 0) { - haraka512_perm(s, s, ctx); - memcpy(h, s, HARAKAS_RATE); - h += r; - nblocks--; - } -} - -void haraka_S_inc_init(uint8_t *s_inc) { - size_t i; - - for (i = 0; i < 64; i++) { - s_inc[i] = 0; - } - s_inc[64] = 0; -} - -void haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, - const spx_ctx *ctx) { - size_t i; - - /* Recall that s_inc[64] is the non-absorbed bytes xored into the state */ - while (mlen + s_inc[64] >= HARAKAS_RATE) { - for (i = 0; i < (size_t)(HARAKAS_RATE - s_inc[64]); i++) { - /* Take the i'th byte from message - xor with the s_inc[64] + i'th byte of the state */ - s_inc[s_inc[64] + i] ^= m[i]; - } - mlen -= (size_t)(HARAKAS_RATE - s_inc[64]); - m += HARAKAS_RATE - (uint8_t)s_inc[64]; - s_inc[64] = 0; - - haraka512_perm(s_inc, s_inc, ctx); - } - - for (i = 0; i < mlen; i++) { - s_inc[s_inc[64] + i] ^= m[i]; - } - s_inc[64] += (uint8_t)mlen; -} - -void haraka_S_inc_finalize(uint8_t *s_inc) { - /* After haraka_S_inc_absorb, we are guaranteed that s_inc[64] < HARAKAS_RATE, - so we can always use one more byte for p in the current state. */ - s_inc[s_inc[64]] ^= 0x1F; - s_inc[HARAKAS_RATE - 1] ^= 128; - s_inc[64] = 0; -} - -void haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, - const spx_ctx *ctx) { - size_t i; - - /* First consume any bytes we still have sitting around */ - for (i = 0; i < outlen && i < s_inc[64]; i++) { - /* There are s_inc[64] bytes left, so r - s_inc[64] is the first - available byte. We consume from there, i.e., up to r. */ - out[i] = (uint8_t)s_inc[(HARAKAS_RATE - s_inc[64] + i)]; - } - out += i; - outlen -= i; - s_inc[64] -= (uint8_t)i; - - /* Then squeeze the remaining necessary blocks */ - while (outlen > 0) { - haraka512_perm(s_inc, s_inc, ctx); - - for (i = 0; i < outlen && i < HARAKAS_RATE; i++) { - out[i] = s_inc[i]; - } - out += i; - outlen -= i; - s_inc[64] = (uint8_t)(HARAKAS_RATE - i); - } -} - -void haraka_S(unsigned char *out, unsigned long long outlen, - const unsigned char *in, unsigned long long inlen, - const spx_ctx *ctx) { - unsigned long long i; - unsigned char s[64]; - unsigned char d[32]; - - for (i = 0; i < 64; i++) { - s[i] = 0; - } - haraka_S_absorb(s, 32, in, inlen, 0x1F, ctx); - - haraka_S_squeezeblocks(out, outlen / 32, s, 32, ctx); - out += (outlen / 32) * 32; - - if (outlen % 32) { - haraka_S_squeezeblocks(d, 1, s, 32, ctx); - for (i = 0; i < outlen % 32; i++) { - out[i] = d[i]; - } - } -} - -void haraka512_perm(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx) { - uint32_t w[16]; - uint64_t q[8], tmp_q; - unsigned int i, j; - - br_range_dec32le(w, 16, in); - for (i = 0; i < 4; i++) { - br_aes_ct64_interleave_in(&q[i], &q[i + 4], w + (i << 2)); - } - br_aes_ct64_ortho(q); - - /* AES rounds */ - for (i = 0; i < 5; i++) { - for (j = 0; j < 2; j++) { - br_aes_ct64_bitslice_Sbox(q); - shift_rows(q); - mix_columns(q); - add_round_key(q, ctx->tweaked512_rc64[2 * i + j]); - } - /* Mix states */ - for (j = 0; j < 8; j++) { - tmp_q = q[j]; - q[j] = (tmp_q & 0x0001000100010001) << 5 | - (tmp_q & 0x0002000200020002) << 12 | - (tmp_q & 0x0004000400040004) >> 1 | - (tmp_q & 0x0008000800080008) << 6 | - (tmp_q & 0x0020002000200020) << 9 | - (tmp_q & 0x0040004000400040) >> 4 | - (tmp_q & 0x0080008000800080) << 3 | - (tmp_q & 0x2100210021002100) >> 5 | - (tmp_q & 0x0210021002100210) << 2 | - (tmp_q & 0x0800080008000800) << 4 | - (tmp_q & 0x1000100010001000) >> 12 | - (tmp_q & 0x4000400040004000) >> 10 | - (tmp_q & 0x8400840084008400) >> 3; - } - } - - br_aes_ct64_ortho(q); - for (i = 0; i < 4; i ++) { - br_aes_ct64_interleave_out(w + (i << 2), q[i], q[i + 4]); - } - br_range_enc32le(out, w, 16); -} - -void haraka512(unsigned char *out, const unsigned char *in, const spx_ctx *ctx) { - int i; - - unsigned char buf[64]; - - haraka512_perm(buf, in, ctx); - /* Feed-forward */ - for (i = 0; i < 64; i++) { - buf[i] = buf[i] ^ in[i]; - } - - /* Truncated */ - memcpy(out, buf + 8, 8); - memcpy(out + 8, buf + 24, 8); - memcpy(out + 16, buf + 32, 8); - memcpy(out + 24, buf + 48, 8); -} - - -void haraka256(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx) { - uint32_t q[8], tmp_q; - int i, j; - - for (i = 0; i < 4; i++) { - q[2 * i] = br_dec32le(in + 4 * i); - q[2 * i + 1] = br_dec32le(in + 4 * i + 16); - } - br_aes_ct_ortho(q); - - /* AES rounds */ - for (i = 0; i < 5; i++) { - for (j = 0; j < 2; j++) { - br_aes_ct_bitslice_Sbox(q); - shift_rows32(q); - mix_columns32(q); - add_round_key32(q, ctx->tweaked256_rc32[2 * i + j]); - } - - /* Mix states */ - for (j = 0; j < 8; j++) { - tmp_q = q[j]; - q[j] = (tmp_q & 0x81818181) | - (tmp_q & 0x02020202) << 1 | - (tmp_q & 0x04040404) << 2 | - (tmp_q & 0x08080808) << 3 | - (tmp_q & 0x10101010) >> 3 | - (tmp_q & 0x20202020) >> 2 | - (tmp_q & 0x40404040) >> 1; - } - } - - br_aes_ct_ortho(q); - for (i = 0; i < 4; i++) { - br_enc32le(out + 4 * i, q[2 * i]); - br_enc32le(out + 4 * i + 16, q[2 * i + 1]); - } - - for (i = 0; i < 32; i++) { - out[i] ^= in[i]; - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/haraka.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/haraka.h deleted file mode 100644 index 737cb6065f..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/haraka.h +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef SPX_HARAKA_H -#define SPX_HARAKA_H - -#include "context.h" -#include "params.h" - -/* Tweak constants with seed */ -#define tweak_constants SPX_NAMESPACE(tweak_constants) -void tweak_constants(spx_ctx *ctx); - -/* Haraka Sponge */ -#define haraka_S_inc_init SPX_NAMESPACE(haraka_S_inc_init) -void haraka_S_inc_init(uint8_t *s_inc); -#define haraka_S_inc_absorb SPX_NAMESPACE(haraka_S_inc_absorb) -void haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, - const spx_ctx *ctx); -#define haraka_S_inc_finalize SPX_NAMESPACE(haraka_S_inc_finalize) -void haraka_S_inc_finalize(uint8_t *s_inc); -#define haraka_S_inc_squeeze SPX_NAMESPACE(haraka_S_inc_squeeze) -void haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, - const spx_ctx *ctx); -#define haraka_S SPX_NAMESPACE(haraka_S) -void haraka_S(unsigned char *out, unsigned long long outlen, - const unsigned char *in, unsigned long long inlen, - const spx_ctx *ctx); - -/* Applies the 512-bit Haraka permutation to in. */ -#define haraka512_perm SPX_NAMESPACE(haraka512_perm) -void haraka512_perm(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx); - -/* Implementation of Haraka-512 */ -#define haraka512 SPX_NAMESPACE(haraka512) -void haraka512(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx); - -/* Implementation of Haraka-256 */ -#define haraka256 SPX_NAMESPACE(haraka256) -void haraka256(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/haraka_offsets.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/haraka_offsets.h deleted file mode 100644 index 7c062272a0..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/haraka_offsets.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef HARAKA_OFFSETS_H_ -#define HARAKA_OFFSETS_H_ - -/* - * Offsets of various fields in the address structure when we use Haraka as - * the Sphincs+ hash function - */ - -#define SPX_OFFSET_LAYER 3 /* The byte used to specify the Merkle tree layer */ -#define SPX_OFFSET_TREE 8 /* The start of the 8 byte field used to specify the tree */ -#define SPX_OFFSET_TYPE 19 /* The byte used to specify the hash type (reason) */ -#define SPX_OFFSET_KP_ADDR2 22 /* The high byte used to specify the key pair (which one-time signature) */ -#define SPX_OFFSET_KP_ADDR1 23 /* The low byte used to specify the key pair */ -#define SPX_OFFSET_CHAIN_ADDR 27 /* The byte used to specify the chain address (which Winternitz chain) */ -#define SPX_OFFSET_HASH_ADDR 31 /* The byte used to specify the hash address (where in the Winternitz chain) */ -#define SPX_OFFSET_TREE_HGT 27 /* The byte used to specify the height of this node in the FORS or Merkle tree */ -#define SPX_OFFSET_TREE_INDEX 28 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ - -#define SPX_HARAKA 1 - -#endif /* HARAKA_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/hash.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/hash.h deleted file mode 100644 index f7c87d4c3c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/hash.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef SPX_HASH_H -#define SPX_HASH_H - -#include -#include - -#include "context.h" -#include "params.h" - -#define prf_addr SPX_NAMESPACE(prf_addr) -void prf_addr(unsigned char *out, const spx_ctx *ctx, - const uint32_t addr[8]); - -#define gen_message_random SPX_NAMESPACE(gen_message_random) -void gen_message_random(unsigned char *R, const unsigned char *sk_prf, - const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx); - -#define hash_message SPX_NAMESPACE(hash_message) -void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx); - - - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/hash_haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/hash_haraka.c deleted file mode 100644 index 750a67423b..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/hash_haraka.c +++ /dev/null @@ -1,81 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "utils.h" - -#include "haraka.h" -#include "hash.h" - -/* - * Computes PRF(key, addr), given a secret key of SPX_N bytes and an address - */ -void prf_addr(unsigned char *out, const spx_ctx *ctx, - const uint32_t addr[8]) { - /* Since SPX_N may be smaller than 32, we need temporary buffers. */ - unsigned char outbuf[32]; - unsigned char buf[64] = {0}; - - memcpy(buf, addr, SPX_ADDR_BYTES); - memcpy(buf + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); - - haraka512(outbuf, (const void *)buf, ctx); - memcpy(out, outbuf, SPX_N); -} - -/** - * Computes the message-dependent randomness R, using a secret seed and an - * optional randomization value as well as the message. - */ -void gen_message_random(unsigned char *R, const unsigned char *sk_prf, - const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx) { - uint8_t s_inc[65]; - - haraka_S_inc_init(s_inc); - haraka_S_inc_absorb(s_inc, sk_prf, SPX_N, ctx); - haraka_S_inc_absorb(s_inc, optrand, SPX_N, ctx); - haraka_S_inc_absorb(s_inc, m, mlen, ctx); - haraka_S_inc_finalize(s_inc); - haraka_S_inc_squeeze(R, SPX_N, s_inc, ctx); -} - -/** - * Computes the message hash using R, the public key, and the message. - * Outputs the message digest and the index of the leaf. The index is split in - * the tree index and the leaf index, for convenient copying to an address. - */ -void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx) { -#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) -#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) -#define SPX_LEAF_BITS SPX_TREE_HEIGHT -#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) -#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) - - unsigned char buf[SPX_DGST_BYTES]; - unsigned char *bufp = buf; - uint8_t s_inc[65]; - - haraka_S_inc_init(s_inc); - haraka_S_inc_absorb(s_inc, R, SPX_N, ctx); - haraka_S_inc_absorb(s_inc, pk + SPX_N, SPX_N, ctx); // Only absorb root part of pk - haraka_S_inc_absorb(s_inc, m, mlen, ctx); - haraka_S_inc_finalize(s_inc); - haraka_S_inc_squeeze(buf, SPX_DGST_BYTES, s_inc, ctx); - - memcpy(digest, bufp, SPX_FORS_MSG_BYTES); - bufp += SPX_FORS_MSG_BYTES; - - - *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); - *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); - bufp += SPX_TREE_BYTES; - - *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); - *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/merkle.c b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/merkle.c deleted file mode 100644 index 0c1479fd93..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/merkle.c +++ /dev/null @@ -1,59 +0,0 @@ -#include -#include - -#include "address.h" -#include "merkle.h" -#include "params.h" -#include "utils.h" -#include "utilsx1.h" -#include "wots.h" -#include "wotsx1.h" - -/* - * This generates a Merkle signature (WOTS signature followed by the Merkle - * authentication path). This is in this file because most of the complexity - * is involved with the WOTS signature; the Merkle authentication path logic - * is mostly hidden in treehashx4 - */ -void merkle_sign(uint8_t *sig, unsigned char *root, - const spx_ctx *ctx, - uint32_t wots_addr[8], uint32_t tree_addr[8], - uint32_t idx_leaf) { - unsigned char *auth_path = sig + SPX_WOTS_BYTES; - struct leaf_info_x1 info = { 0 }; - unsigned steps[ SPX_WOTS_LEN ]; - - info.wots_sig = sig; - chain_lengths(steps, root); - info.wots_steps = steps; - - set_type(&tree_addr[0], SPX_ADDR_TYPE_HASHTREE); - set_type(&info.pk_addr[0], SPX_ADDR_TYPE_WOTSPK); - copy_subtree_addr(&info.leaf_addr[0], wots_addr); - copy_subtree_addr(&info.pk_addr[0], wots_addr); - - info.wots_sign_leaf = idx_leaf; - - treehashx1(root, auth_path, ctx, - idx_leaf, 0, - SPX_TREE_HEIGHT, - wots_gen_leafx1, - tree_addr, &info); -} - -/* Compute root node of the top-most subtree. */ -void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { - /* We do not need the auth path in key generation, but it simplifies the - code to have just one treehash routine that computes both root and path - in one function. */ - unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; - uint32_t top_tree_addr[8] = {0}; - uint32_t wots_addr[8] = {0}; - - set_layer_addr(top_tree_addr, SPX_D - 1); - set_layer_addr(wots_addr, SPX_D - 1); - - merkle_sign(auth_path, root, ctx, - wots_addr, top_tree_addr, - (uint32_t)~0 /* ~0 means "don't bother generating an auth path */ ); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/merkle.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/merkle.h deleted file mode 100644 index 769cf2e970..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/merkle.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef MERKLE_H_ -#define MERKLE_H_ - -#include - -#include "context.h" -#include "params.h" - -/* Generate a Merkle signature (WOTS signature followed by the Merkle */ -/* authentication path) */ -#define merkle_sign SPX_NAMESPACE(merkle_sign) -void merkle_sign(uint8_t *sig, unsigned char *root, - const spx_ctx *ctx, - uint32_t wots_addr[8], uint32_t tree_addr[8], - uint32_t idx_leaf); - -/* Compute the root node of the top-most subtree. */ -#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) -void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); - -#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/nistapi.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/nistapi.h deleted file mode 100644 index 3cb71afad4..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/nistapi.h +++ /dev/null @@ -1,87 +0,0 @@ -#ifndef SPX_API_H -#define SPX_API_H - -#include -#include - -#include "params.h" - -#define CRYPTO_ALGNAME "SPHINCS+" - -#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES -#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES -#define CRYPTO_BYTES SPX_BYTES -#define CRYPTO_SEEDBYTES (3*SPX_N) - -/* - * Returns the length of a secret key, in bytes - */ -#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) -size_t crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) -size_t crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) -size_t crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) -size_t crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) -int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) -int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) -int crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) -int crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -#define crypto_sign SPX_NAMESPACE(crypto_sign) -int crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) -int crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/params.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/params.h deleted file mode 100644 index 870e9ce136..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/params.h +++ /dev/null @@ -1,56 +0,0 @@ -#ifndef SPX_PARAMS_H -#define SPX_PARAMS_H - -#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_##s - -/* Hash output length in bytes. */ -#define SPX_N 16 -/* Height of the hypertree. */ -#define SPX_FULL_HEIGHT 66 -/* Number of subtree layer. */ -#define SPX_D 22 -/* FORS tree dimensions. */ -#define SPX_FORS_HEIGHT 6 -#define SPX_FORS_TREES 33 -/* Winternitz parameter, */ -#define SPX_WOTS_W 16 - -/* The hash function is defined by linking a different hash.c file, as opposed - to setting a #define constant. */ - -/* For clarity */ -#define SPX_ADDR_BYTES 32 - -/* WOTS parameters. */ -#define SPX_WOTS_LOGW 4 - -#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) - -/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#define SPX_WOTS_LEN2 3 - -#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) -#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) -#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES - -/* Subtree size. */ -#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) - -//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT -// #error SPX_D should always divide SPX_FULL_HEIGHT -//#endif - -/* FORS parameters. */ -#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) -#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) -#define SPX_FORS_PK_BYTES SPX_N - -/* Resulting SPX sizes. */ -#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ - SPX_FULL_HEIGHT * SPX_N) -#define SPX_PK_BYTES (2 * SPX_N) -#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) - -#include "haraka_offsets.h" - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/sign.c b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/sign.c deleted file mode 100644 index 9d0c7d1b22..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/sign.c +++ /dev/null @@ -1,286 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "context.h" -#include "fors.h" -#include "hash.h" -#include "merkle.h" -#include "nistapi.h" -#include "params.h" -#include "randombytes.h" -#include "thash.h" -#include "utils.h" -#include "wots.h" - -/* - * Returns the length of a secret key, in bytes - */ -size_t crypto_sign_secretkeybytes(void) { - return CRYPTO_SECRETKEYBYTES; -} - -/* - * Returns the length of a public key, in bytes - */ -size_t crypto_sign_publickeybytes(void) { - return CRYPTO_PUBLICKEYBYTES; -} - -/* - * Returns the length of a signature, in bytes - */ -size_t crypto_sign_bytes(void) { - return CRYPTO_BYTES; -} - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t crypto_sign_seedbytes(void) { - return CRYPTO_SEEDBYTES; -} - -/* - * Generates an SPX key pair given a seed of length - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed) { - spx_ctx ctx; - - /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ - memcpy(sk, seed, CRYPTO_SEEDBYTES); - - memcpy(pk, sk + 2 * SPX_N, SPX_N); - - memcpy(ctx.pub_seed, pk, SPX_N); - memcpy(ctx.sk_seed, sk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - /* Compute root node of the top-most subtree. */ - merkle_gen_root(sk + 3 * SPX_N, &ctx); - - // cleanup - free_hash_function(&ctx); - - memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); - - return 0; -} - -/* - * Generates an SPX key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { - uint8_t seed[CRYPTO_SEEDBYTES]; - randombytes(seed, CRYPTO_SEEDBYTES); - crypto_sign_seed_keypair(pk, sk, seed); - - return 0; -} - -/** - * Returns an array containing a detached signature. - */ -int crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - spx_ctx ctx; - - const uint8_t *sk_prf = sk + SPX_N; - const uint8_t *pk = sk + 2 * SPX_N; - - uint8_t optrand[SPX_N]; - uint8_t mhash[SPX_FORS_MSG_BYTES]; - uint8_t root[SPX_N]; - uint32_t i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - - memcpy(ctx.sk_seed, sk, SPX_N); - memcpy(ctx.pub_seed, pk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - set_type(wots_addr, SPX_ADDR_TYPE_WOTS); - set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); - - /* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ - randombytes(optrand, SPX_N); - /* Compute the digest randomization value. */ - gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); - - /* Derive the message digest and leaf index from R, PK and M. */ - hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); - sig += SPX_N; - - set_tree_addr(wots_addr, tree); - set_keypair_addr(wots_addr, idx_leaf); - - /* Sign the message hash using FORS. */ - fors_sign(sig, root, mhash, &ctx, wots_addr); - sig += SPX_FORS_BYTES; - - for (i = 0; i < SPX_D; i++) { - set_layer_addr(tree_addr, i); - set_tree_addr(tree_addr, tree); - - copy_subtree_addr(wots_addr, tree_addr); - set_keypair_addr(wots_addr, idx_leaf); - - merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); - sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); - tree = tree >> SPX_TREE_HEIGHT; - } - - free_hash_function(&ctx); - - *siglen = SPX_BYTES; - - return 0; -} - -/** - * Verifies a detached signature and message under a given public key. - */ -int crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk) { - spx_ctx ctx; - const uint8_t *pub_root = pk + SPX_N; - uint8_t mhash[SPX_FORS_MSG_BYTES]; - uint8_t wots_pk[SPX_WOTS_BYTES]; - uint8_t root[SPX_N]; - uint8_t leaf[SPX_N]; - unsigned int i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - if (siglen != SPX_BYTES) { - return -1; - } - - memcpy(ctx.pub_seed, pk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - set_type(wots_addr, SPX_ADDR_TYPE_WOTS); - set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); - set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); - - /* Derive the message digest and leaf index from R || PK || M. */ - /* The additional SPX_N is a result of the hash domain separator. */ - hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); - sig += SPX_N; - - /* Layer correctly defaults to 0, so no need to set_layer_addr */ - set_tree_addr(wots_addr, tree); - set_keypair_addr(wots_addr, idx_leaf); - - fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); - sig += SPX_FORS_BYTES; - - /* For each subtree.. */ - for (i = 0; i < SPX_D; i++) { - set_layer_addr(tree_addr, i); - set_tree_addr(tree_addr, tree); - - copy_subtree_addr(wots_addr, tree_addr); - set_keypair_addr(wots_addr, idx_leaf); - - copy_keypair_addr(wots_pk_addr, wots_addr); - - /* The WOTS public key is only correct if the signature was correct. */ - /* Initially, root is the FORS pk, but on subsequent iterations it is - the root of the subtree below the currently processed subtree. */ - wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); - sig += SPX_WOTS_BYTES; - - /* Compute the leaf node using the WOTS public key. */ - thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); - - /* Compute the root node of this subtree. */ - compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, - &ctx, tree_addr); - sig += SPX_TREE_HEIGHT * SPX_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); - tree = tree >> SPX_TREE_HEIGHT; - } - - // cleanup - free_hash_function(&ctx); - - /* Check if the root node equals the root node in the public key. */ - if (memcmp(root, pub_root, SPX_N) != 0) { - return -1; - } - - return 0; -} - - -/** - * Returns an array containing the signature followed by the message. - */ -int crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk) { - size_t siglen; - - crypto_sign_signature(sm, &siglen, m, mlen, sk); - - memmove(sm + SPX_BYTES, m, mlen); - *smlen = siglen + mlen; - - return 0; -} - -/** - * Verifies a given signature-message pair under a given public key. - */ -int crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk) { - /* The API caller does not necessarily know what size a signature should be - but SPHINCS+ signatures are always exactly SPX_BYTES. */ - if (smlen < SPX_BYTES) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - *mlen = smlen - SPX_BYTES; - - if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - /* If verification was successful, move the message to the right place. */ - memmove(m, sm + SPX_BYTES, *mlen); - - return 0; -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/thash.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/thash.h deleted file mode 100644 index 8687ccfb4d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/thash.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef SPX_THASH_H -#define SPX_THASH_H - -#include "context.h" -#include "params.h" - -#include - -#define thash SPX_NAMESPACE(thash) -void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/thash_haraka_robust.c b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/thash_haraka_robust.c deleted file mode 100644 index 109502cbc2..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/thash_haraka_robust.c +++ /dev/null @@ -1,45 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "thash.h" -#include "utils.h" - -#include "haraka.h" - -/** - * Takes an array of inblocks concatenated arrays of SPX_N bytes. - */ -void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]) { - PQCLEAN_VLA(uint8_t, buf, SPX_ADDR_BYTES + inblocks * SPX_N); - PQCLEAN_VLA(uint8_t, bitmask, inblocks * SPX_N); - unsigned char outbuf[32]; - unsigned char buf_tmp[64]; - unsigned int i; - - if (inblocks == 1) { - /* F function */ - /* Since SPX_N may be smaller than 32, we need a temporary buffer. */ - memset(buf_tmp, 0, 64); - memcpy(buf_tmp, addr, 32); - - haraka256(outbuf, buf_tmp, ctx); - for (i = 0; i < inblocks * SPX_N; i++) { - buf_tmp[SPX_ADDR_BYTES + i] = in[i] ^ outbuf[i]; - } - haraka512(outbuf, buf_tmp, ctx); - memcpy(out, outbuf, SPX_N); - } else { - /* All other tweakable hashes*/ - memcpy(buf, addr, 32); - haraka_S(bitmask, inblocks * SPX_N, buf, SPX_ADDR_BYTES, ctx); - - for (i = 0; i < inblocks * SPX_N; i++) { - buf[SPX_ADDR_BYTES + i] = in[i] ^ bitmask[i]; - } - - haraka_S(out, SPX_N, buf, SPX_ADDR_BYTES + inblocks * SPX_N, ctx); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/utils.c b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/utils.c deleted file mode 100644 index 177b541fb9..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/utils.c +++ /dev/null @@ -1,148 +0,0 @@ -#include - -#include "utils.h" - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "thash.h" - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void ull_to_bytes(unsigned char *out, unsigned int outlen, - unsigned long long in) { - int i; - - /* Iterate over out in decreasing order, for big-endianness. */ - for (i = (signed int)outlen - 1; i >= 0; i--) { - out[i] = in & 0xff; - in = in >> 8; - } -} - -void u32_to_bytes(unsigned char *out, uint32_t in) { - out[0] = (unsigned char)(in >> 24); - out[1] = (unsigned char)(in >> 16); - out[2] = (unsigned char)(in >> 8); - out[3] = (unsigned char)in; -} - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { - unsigned long long retval = 0; - unsigned int i; - - for (i = 0; i < inlen; i++) { - retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); - } - return retval; -} - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void compute_root(unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const spx_ctx *ctx, uint32_t addr[8]) { - uint32_t i; - unsigned char buffer[2 * SPX_N]; - - /* If leaf_idx is odd (last bit = 1), current path element is a right child - and auth_path has to go left. Otherwise it is the other way around. */ - if (leaf_idx & 1) { - memcpy(buffer + SPX_N, leaf, SPX_N); - memcpy(buffer, auth_path, SPX_N); - } else { - memcpy(buffer, leaf, SPX_N); - memcpy(buffer + SPX_N, auth_path, SPX_N); - } - auth_path += SPX_N; - - for (i = 0; i < tree_height - 1; i++) { - leaf_idx >>= 1; - idx_offset >>= 1; - /* Set the address of the node we're creating. */ - set_tree_height(addr, i + 1); - set_tree_index(addr, leaf_idx + idx_offset); - - /* Pick the right or left neighbor, depending on parity of the node. */ - if (leaf_idx & 1) { - thash(buffer + SPX_N, buffer, 2, ctx, addr); - memcpy(buffer, auth_path, SPX_N); - } else { - thash(buffer, buffer, 2, ctx, addr); - memcpy(buffer + SPX_N, auth_path, SPX_N); - } - auth_path += SPX_N; - } - - /* The last iteration is exceptional; we do not copy an auth_path node. */ - leaf_idx >>= 1; - idx_offset >>= 1; - set_tree_height(addr, tree_height); - set_tree_index(addr, leaf_idx + idx_offset); - thash(root, buffer, 2, ctx, addr); -} - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const spx_ctx * /* ctx */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), - uint32_t tree_addr[8]) { - PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); - PQCLEAN_VLA(unsigned int, heights, tree_height + 1); - unsigned int offset = 0; - uint32_t idx; - uint32_t tree_idx; - - for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { - /* Add the next leaf node to the stack. */ - gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); - offset++; - heights[offset - 1] = 0; - - /* If this is a node we need for the auth path.. */ - if ((leaf_idx ^ 0x1) == idx) { - memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); - } - - /* While the top-most nodes are of equal height.. */ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { - /* Compute index of the new node, in the next layer. */ - tree_idx = (idx >> (heights[offset - 1] + 1)); - - /* Set the address of the node we're creating. */ - set_tree_height(tree_addr, heights[offset - 1] + 1); - set_tree_index(tree_addr, - tree_idx + (idx_offset >> (heights[offset - 1] + 1))); - /* Hash the top-most nodes from the stack together. */ - thash(stack + (offset - 2)*SPX_N, - stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); - offset--; - /* Note that the top-most node is now one layer higher. */ - heights[offset - 1]++; - - /* If this is a node we need for the auth path.. */ - if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_path + heights[offset - 1]*SPX_N, - stack + (offset - 1)*SPX_N, SPX_N); - } - } - } - memcpy(root, stack, SPX_N); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/utils.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/utils.h deleted file mode 100644 index 64f5d5a53a..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/utils.h +++ /dev/null @@ -1,58 +0,0 @@ -#ifndef SPX_UTILS_H -#define SPX_UTILS_H - -#include - -#include "compat.h" -#include "context.h" -#include "params.h" - - -/* To support MSVC use alloca() instead of VLAs. See #20. */ - - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) -void ull_to_bytes(unsigned char *out, unsigned int outlen, - unsigned long long in); -#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) -void u32_to_bytes(unsigned char *out, uint32_t in); - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) -unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -#define compute_root SPX_NAMESPACE(compute_root) -void compute_root(unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const spx_ctx *ctx, uint32_t addr[8]); - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -#define treehash SPX_NAMESPACE(treehash) -void treehash(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const spx_ctx *ctx /* ctx */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), - uint32_t tree_addr[8]); - - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/utilsx1.c b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/utilsx1.c deleted file mode 100644 index fccb69b35d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/utilsx1.c +++ /dev/null @@ -1,100 +0,0 @@ -#include - -#include "utilsx1.h" - -#include "address.h" -#include "params.h" -#include "thash.h" -#include "utils.h" - -/* - * Generate the entire Merkle tree, computing the authentication path for - * leaf_idx, and the resulting root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) - * - * This expects tree_addr to be initialized to the addr structures for the - * Merkle tree nodes - * - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - * - * This works by using the standard Merkle tree building algorithm, - */ -void treehashx1(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, - uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* Where to write the leaves */, - const spx_ctx * /* ctx */, - uint32_t idx, void *info), - uint32_t tree_addr[8], - void *info) { - /* This is where we keep the intermediate nodes */ - PQCLEAN_VLA(uint8_t, stack, tree_height * SPX_N); - - uint32_t idx; - uint32_t max_idx = (uint32_t)((1 << tree_height) - 1); - for (idx = 0;; idx++) { - unsigned char current[2 * SPX_N]; /* Current logical node is at */ - /* index[SPX_N]. We do this to minimize the number of copies */ - /* needed during a thash */ - gen_leaf( ¤t[SPX_N], ctx, idx + idx_offset, - info ); - - /* Now combine the freshly generated right node with previously */ - /* generated left ones */ - uint32_t internal_idx_offset = idx_offset; - uint32_t internal_idx = idx; - uint32_t internal_leaf = leaf_idx; - uint32_t h; /* The height we are in the Merkle tree */ - for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { - - /* Check if we hit the top of the tree */ - if (h == tree_height) { - /* We hit the root; return it */ - memcpy( root, ¤t[SPX_N], SPX_N ); - return; - } - - /* - * Check if the node we have is a part of the - * authentication path; if it is, write it out - */ - if ((internal_idx ^ internal_leaf) == 0x01) { - memcpy( &auth_path[ h * SPX_N ], - ¤t[SPX_N], - SPX_N ); - } - - /* - * Check if we're at a left child; if so, stop going up the stack - * Exception: if we've reached the end of the tree, keep on going - * (so we combine the last 4 nodes into the one root node in two - * more iterations) - */ - if ((internal_idx & 1) == 0 && idx < max_idx) { - break; - } - - /* Ok, we're at a right node */ - /* Now combine the left and right logical nodes together */ - - /* Set the address of the node we're creating. */ - internal_idx_offset >>= 1; - set_tree_height(tree_addr, h + 1); - set_tree_index(tree_addr, internal_idx / 2 + internal_idx_offset ); - - unsigned char *left = &stack[h * SPX_N]; - memcpy( ¤t[0], left, SPX_N ); - thash( ¤t[1 * SPX_N], - ¤t[0 * SPX_N], - 2, ctx, tree_addr); - } - - /* We've hit a left child; save the current for when we get the */ - /* corresponding right right */ - memcpy( &stack[h * SPX_N], ¤t[SPX_N], SPX_N); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/utilsx1.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/utilsx1.h deleted file mode 100644 index e911d17d53..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/utilsx1.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef SPX_UTILSX4_H -#define SPX_UTILSX4_H - -#include - -#include "context.h" -#include "params.h" - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -#define treehashx1 SPX_NAMESPACE(treehashx1) -void treehashx1(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* Where to write the leaf */, - const spx_ctx * /* ctx */, - uint32_t addr_idx, void *info), - uint32_t tree_addrx4[8], void *info); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/wots.c b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/wots.c deleted file mode 100644 index 249717aaa8..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/wots.c +++ /dev/null @@ -1,108 +0,0 @@ -#include -#include - -#include "wots.h" -#include "wotsx1.h" - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "thash.h" -#include "utils.h" -#include "utilsx1.h" - -// TODO clarify address expectations, and make them more uniform. -// TODO i.e. do we expect types to be set already? -// TODO and do we expect modifications or copies? - -/** - * Computes the chaining function. - * out and in have to be n-byte arrays. - * - * Interprets in as start-th value of the chain. - * addr has to contain the address of the chain. - */ -static void gen_chain(unsigned char *out, const unsigned char *in, - unsigned int start, unsigned int steps, - const spx_ctx *ctx, uint32_t addr[8]) { - uint32_t i; - - /* Initialize out with the value at position 'start'. */ - memcpy(out, in, SPX_N); - - /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < SPX_WOTS_W; i++) { - set_hash_addr(addr, i); - thash(out, out, 1, ctx, addr); - } -} - -/** - * base_w algorithm as described in draft. - * Interprets an array of bytes as integers in base w. - * This only works when log_w is a divisor of 8. - */ -static void base_w(unsigned int *output, const int out_len, - const unsigned char *input) { - int in = 0; - int out = 0; - unsigned char total = 0; - int bits = 0; - int consumed; - - for (consumed = 0; consumed < out_len; consumed++) { - if (bits == 0) { - total = input[in]; - in++; - bits += 8; - } - bits -= SPX_WOTS_LOGW; - output[out] = (total >> bits) & (SPX_WOTS_W - 1); - out++; - } -} - -/* Computes the WOTS+ checksum over a message (in base_w). */ -static void wots_checksum(unsigned int *csum_base_w, - const unsigned int *msg_base_w) { - unsigned int csum = 0; - unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; - unsigned int i; - - /* Compute checksum. */ - for (i = 0; i < SPX_WOTS_LEN1; i++) { - csum += SPX_WOTS_W - 1 - msg_base_w[i]; - } - - /* Convert checksum to base_w. */ - /* Make sure expected empty zero bits are the least significant bits. */ - csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); - ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); - base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); -} - -/* Takes a message and derives the matching chain lengths. */ -void chain_lengths(unsigned int *lengths, const unsigned char *msg) { - base_w(lengths, SPX_WOTS_LEN1, msg); - wots_checksum(lengths + SPX_WOTS_LEN1, lengths); -} - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const spx_ctx *ctx, uint32_t addr[8]) { - unsigned int lengths[SPX_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < SPX_WOTS_LEN; i++) { - set_chain_addr(addr, i); - gen_chain(pk + i * SPX_N, sig + i * SPX_N, - lengths[i], SPX_WOTS_W - 1 - lengths[i], ctx, addr); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/wots.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/wots.h deleted file mode 100644 index 4e7692eeef..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/wots.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef SPX_WOTS_H -#define SPX_WOTS_H - -#include - -#include "context.h" -#include "params.h" - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) -void wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const spx_ctx *ctx, uint32_t addr[8]); - -/* - * Compute the chain lengths needed for a given message hash - */ -#define chain_lengths SPX_NAMESPACE(chain_lengths) -void chain_lengths(unsigned int *lengths, const unsigned char *msg); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/wotsx1.c b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/wotsx1.c deleted file mode 100644 index 3adec78dfb..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/wotsx1.c +++ /dev/null @@ -1,76 +0,0 @@ -#include -#include - -#include "wots.h" -#include "wotsx1.h" - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "thash.h" -#include "utils.h" - -/* - * This generates a WOTS public key - * It also generates the WOTS signature if leaf_info indicates - * that we're signing with this WOTS key - */ -void wots_gen_leafx1(unsigned char *dest, - const spx_ctx *ctx, - uint32_t leaf_idx, void *v_info) { - struct leaf_info_x1 *info = v_info; - uint32_t *leaf_addr = info->leaf_addr; - uint32_t *pk_addr = info->pk_addr; - unsigned int i, k; - unsigned char pk_buffer[ SPX_WOTS_BYTES ]; - unsigned char *buffer; - uint32_t wots_k_mask; - - if (leaf_idx == info->wots_sign_leaf) { - /* We're traversing the leaf that's signing; generate the WOTS */ - /* signature */ - wots_k_mask = 0; - } else { - /* Nope, we're just generating pk's; turn off the signature logic */ - wots_k_mask = (uint32_t)~0; - } - - set_keypair_addr( leaf_addr, leaf_idx ); - set_keypair_addr( pk_addr, leaf_idx ); - - for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { - uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k to */ - /* the step if we're generating a signature, ~0 if we're not */ - - /* Start with the secret seed */ - set_chain_addr(leaf_addr, i); - set_hash_addr(leaf_addr, 0); - set_type(leaf_addr, SPX_ADDR_TYPE_WOTSPRF); - - prf_addr(buffer, ctx, leaf_addr); - - set_type(leaf_addr, SPX_ADDR_TYPE_WOTS); - - /* Iterate down the WOTS chain */ - for (k = 0;; k++) { - /* Check if this is the value that needs to be saved as a */ - /* part of the WOTS signature */ - if (k == wots_k) { - memcpy( info->wots_sig + i * SPX_N, buffer, SPX_N ); - } - - /* Check if we hit the top of the chain */ - if (k == SPX_WOTS_W - 1) { - break; - } - - /* Iterate one step on the chain */ - set_hash_addr(leaf_addr, k); - - thash(buffer, buffer, 1, ctx, leaf_addr); - } - } - - /* Do the final thash to generate the public keys */ - thash(dest, pk_buffer, SPX_WOTS_LEN, ctx, pk_addr); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/wotsx1.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/wotsx1.h deleted file mode 100644 index e617929f96..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-robust_clean/wotsx1.h +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef WOTSX1_H_ -#define WOTSX1_H_ - -#include - -#include "context.h" -#include "params.h" - -/* - * This is here to provide an interface to the internal wots_gen_leafx1 - * routine. While this routine is not referenced in the package outside of - * wots.c, it is called from the stand-alone benchmark code to characterize - * the performance - */ -struct leaf_info_x1 { - unsigned char *wots_sig; - uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ - uint32_t *wots_steps; - uint32_t leaf_addr[8]; - uint32_t pk_addr[8]; -}; - -/* Macro to set the leaf_info to something 'benign', that is, it would */ -/* run with the same time as it does during the real signing process */ -/* Used only by the benchmark code */ -#define INITIALIZE_LEAF_INFO_X1(info, addr, step_buffer) { \ - (info).wots_sig = 0; \ - (info).wots_sign_leaf = ~0; \ - (info).wots_steps = step_buffer; \ - memcpy( &(info).leaf_addr[0], (addr), 32 ); \ - memcpy( &(info).pk_addr[0], (addr), 32 ); \ - } - -#define wots_gen_leafx1 SPX_NAMESPACE(wots_gen_leafx1) -void wots_gen_leafx1(unsigned char *dest, - const spx_ctx *ctx, - uint32_t leaf_idx, void *v_info); - -#endif /* WOTSX1_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/LICENSE b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/LICENSE deleted file mode 100644 index 670154e353..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/LICENSE +++ /dev/null @@ -1,116 +0,0 @@ -CC0 1.0 Universal - -Statement of Purpose - -The laws of most jurisdictions throughout the world automatically confer -exclusive Copyright and Related Rights (defined below) upon the creator and -subsequent owner(s) (each and all, an "owner") of an original work of -authorship and/or a database (each, a "Work"). - -Certain owners wish to permanently relinquish those rights to a Work for the -purpose of contributing to a commons of creative, cultural and scientific -works ("Commons") that the public can reliably and without fear of later -claims of infringement build upon, modify, incorporate in other works, reuse -and redistribute as freely as possible in any form whatsoever and for any -purposes, including without limitation commercial purposes. These owners may -contribute to the Commons to promote the ideal of a free culture and the -further production of creative, cultural and scientific works, or to gain -reputation or greater distribution for their Work in part through the use and -efforts of others. - -For these and/or other purposes and motivations, and without any expectation -of additional consideration or compensation, the person associating CC0 with a -Work (the "Affirmer"), to the extent that he or she is an owner of Copyright -and Related Rights in the Work, voluntarily elects to apply CC0 to the Work -and publicly distribute the Work under its terms, with knowledge of his or her -Copyright and Related Rights in the Work and the meaning and intended legal -effect of CC0 on those rights. - -1. Copyright and Related Rights. A Work made available under CC0 may be -protected by copyright and related or neighboring rights ("Copyright and -Related Rights"). Copyright and Related Rights include, but are not limited -to, the following: - - i. the right to reproduce, adapt, distribute, perform, display, communicate, - and translate a Work; - - ii. moral rights retained by the original author(s) and/or performer(s); - - iii. publicity and privacy rights pertaining to a person's image or likeness - depicted in a Work; - - iv. rights protecting against unfair competition in regards to a Work, - subject to the limitations in paragraph 4(a), below; - - v. rights protecting the extraction, dissemination, use and reuse of data in - a Work; - - vi. database rights (such as those arising under Directive 96/9/EC of the - European Parliament and of the Council of 11 March 1996 on the legal - protection of databases, and under any national implementation thereof, - including any amended or successor version of such directive); and - - vii. other similar, equivalent or corresponding rights throughout the world - based on applicable law or treaty, and any national implementations thereof. - -2. Waiver. To the greatest extent permitted by, but not in contravention of, -applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and -unconditionally waives, abandons, and surrenders all of Affirmer's Copyright -and Related Rights and associated claims and causes of action, whether now -known or unknown (including existing as well as future claims and causes of -action), in the Work (i) in all territories worldwide, (ii) for the maximum -duration provided by applicable law or treaty (including future time -extensions), (iii) in any current or future medium and for any number of -copies, and (iv) for any purpose whatsoever, including without limitation -commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes -the Waiver for the benefit of each member of the public at large and to the -detriment of Affirmer's heirs and successors, fully intending that such Waiver -shall not be subject to revocation, rescission, cancellation, termination, or -any other legal or equitable action to disrupt the quiet enjoyment of the Work -by the public as contemplated by Affirmer's express Statement of Purpose. - -3. Public License Fallback. Should any part of the Waiver for any reason be -judged legally invalid or ineffective under applicable law, then the Waiver -shall be preserved to the maximum extent permitted taking into account -Affirmer's express Statement of Purpose. In addition, to the extent the Waiver -is so judged Affirmer hereby grants to each affected person a royalty-free, -non transferable, non sublicensable, non exclusive, irrevocable and -unconditional license to exercise Affirmer's Copyright and Related Rights in -the Work (i) in all territories worldwide, (ii) for the maximum duration -provided by applicable law or treaty (including future time extensions), (iii) -in any current or future medium and for any number of copies, and (iv) for any -purpose whatsoever, including without limitation commercial, advertising or -promotional purposes (the "License"). The License shall be deemed effective as -of the date CC0 was applied by Affirmer to the Work. Should any part of the -License for any reason be judged legally invalid or ineffective under -applicable law, such partial invalidity or ineffectiveness shall not -invalidate the remainder of the License, and in such case Affirmer hereby -affirms that he or she will not (i) exercise any of his or her remaining -Copyright and Related Rights in the Work or (ii) assert any associated claims -and causes of action with respect to the Work, in either case contrary to -Affirmer's express Statement of Purpose. - -4. Limitations and Disclaimers. - - a. No trademark or patent rights held by Affirmer are waived, abandoned, - surrendered, licensed or otherwise affected by this document. - - b. Affirmer offers the Work as-is and makes no representations or warranties - of any kind concerning the Work, express, implied, statutory or otherwise, - including without limitation warranties of title, merchantability, fitness - for a particular purpose, non infringement, or the absence of latent or - other defects, accuracy, or the present or absence of errors, whether or not - discoverable, all to the greatest extent permissible under applicable law. - - c. Affirmer disclaims responsibility for clearing rights of other persons - that may apply to the Work or any use thereof, including without limitation - any person's Copyright and Related Rights in the Work. Further, Affirmer - disclaims responsibility for obtaining any necessary consents, permissions - or other rights required for any use of the Work. - - d. Affirmer understands and acknowledges that Creative Commons is not a - party to this document and has no duty or obligation with respect to this - CC0 or use of the Work. - -For more information, please see - diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/address.c b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/address.c deleted file mode 100644 index b956e9cb29..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/address.c +++ /dev/null @@ -1,91 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "utils.h" - -/* - * Specify which level of Merkle tree (the "layer") we're working on - */ -void set_layer_addr(uint32_t addr[8], uint32_t layer) { - ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; -} - -/* - * Specify which Merkle tree within the level (the "tree address") we're working on - */ -void set_tree_addr(uint32_t addr[8], uint64_t tree) { - ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); -} - -/* - * Specify the reason we'll use this address structure for, that is, what - * hash will we compute with it. This is used so that unrelated types of - * hashes don't accidentally get the same address structure. The type will be - * one of the SPX_ADDR_TYPE constants - */ -void set_type(uint32_t addr[8], uint32_t type) { - ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; -} - -/* - * Copy the layer and tree fields of the address structure. This is used - * when we're doing multiple types of hashes within the same Merkle tree - */ -void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { - memcpy( out, in, SPX_OFFSET_TREE + 8 ); -} - -/* These functions are used for OTS addresses. */ - -/* - * Specify which Merkle leaf we're working on; that is, which OTS keypair - * we're talking about. - */ -void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { - ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; -} - -/* - * Copy the layer, tree and keypair fields of the address structure. This is - * used when we're doing multiple things within the same OTS keypair - */ -void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { - memcpy( out, in, SPX_OFFSET_TREE + 8 ); - ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; -} - -/* - * Specify which Merkle chain within the OTS we're working with - * (the chain address) - */ -void set_chain_addr(uint32_t addr[8], uint32_t chain) { - ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; -} - -/* - * Specify where in the Merkle chain we are -* (the hash address) - */ -void set_hash_addr(uint32_t addr[8], uint32_t hash) { - ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; -} - -/* These functions are used for all hash tree addresses (including FORS). */ - -/* - * Specify the height of the node in the Merkle/FORS tree we are in - * (the tree height) - */ -void set_tree_height(uint32_t addr[8], uint32_t tree_height) { - ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; -} - -/* - * Specify the distance from the left edge of the node in the Merkle/FORS tree - * (the tree index) - */ -void set_tree_index(uint32_t addr[8], uint32_t tree_index) { - u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/address.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/address.h deleted file mode 100644 index 24a84eb40c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/address.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef SPX_ADDRESS_H -#define SPX_ADDRESS_H - -#include - -#include "params.h" - -/* The hash types that are passed to set_type */ -#define SPX_ADDR_TYPE_WOTS 0 -#define SPX_ADDR_TYPE_WOTSPK 1 -#define SPX_ADDR_TYPE_HASHTREE 2 -#define SPX_ADDR_TYPE_FORSTREE 3 -#define SPX_ADDR_TYPE_FORSPK 4 -#define SPX_ADDR_TYPE_WOTSPRF 5 -#define SPX_ADDR_TYPE_FORSPRF 6 - -#define set_layer_addr SPX_NAMESPACE(set_layer_addr) -void set_layer_addr(uint32_t addr[8], uint32_t layer); - -#define set_tree_addr SPX_NAMESPACE(set_tree_addr) -void set_tree_addr(uint32_t addr[8], uint64_t tree); - -#define set_type SPX_NAMESPACE(set_type) -void set_type(uint32_t addr[8], uint32_t type); - -/* Copies the layer and tree part of one address into the other */ -#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) -void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for WOTS and FORS addresses. */ - -#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) -void set_keypair_addr(uint32_t addr[8], uint32_t keypair); - -#define set_chain_addr SPX_NAMESPACE(set_chain_addr) -void set_chain_addr(uint32_t addr[8], uint32_t chain); - -#define set_hash_addr SPX_NAMESPACE(set_hash_addr) -void set_hash_addr(uint32_t addr[8], uint32_t hash); - -#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) -void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for all hash tree addresses (including FORS). */ - -#define set_tree_height SPX_NAMESPACE(set_tree_height) -void set_tree_height(uint32_t addr[8], uint32_t tree_height); - -#define set_tree_index SPX_NAMESPACE(set_tree_index) -void set_tree_index(uint32_t addr[8], uint32_t tree_index); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/api.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/api.h deleted file mode 100644 index fa22fa775b..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/api.h +++ /dev/null @@ -1,77 +0,0 @@ -#ifndef PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_API_H -#define PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_API_H - -#include -#include - -#define PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_CRYPTO_ALGNAME "SPHINCS+-haraka-128f-simple" - -#define PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_CRYPTO_SECRETKEYBYTES 64 -#define PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_CRYPTO_PUBLICKEYBYTES 32 -#define PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_CRYPTO_BYTES 17088 - -#define PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_CRYPTO_SEEDBYTES 48 - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, - const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk); -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/context.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/context.h deleted file mode 100644 index f03446b9cb..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/context.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef SPX_CONTEXT_H -#define SPX_CONTEXT_H - -#include - -#include "immintrin.h" -#include "params.h" - -typedef struct { - uint8_t pub_seed[SPX_N]; - uint8_t sk_seed[SPX_N]; - - __m128i rc[40]; -} spx_ctx; - -#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) -void initialize_hash_function(spx_ctx *ctx); - -#define free_hash_function SPX_NAMESPACE(free_hash_function) -void free_hash_function(spx_ctx *ctx); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/context_haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/context_haraka.c deleted file mode 100644 index f1cd7e3664..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/context_haraka.c +++ /dev/null @@ -1,11 +0,0 @@ -#include "context.h" -#include "haraka.h" - -void initialize_hash_function(spx_ctx *ctx) { - tweak_constants(ctx); -} - -// we don't support heap-based haraka right now -void free_hash_function(spx_ctx *ctx) { - (void)ctx; // suppress unused variable warnings -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/fors.c b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/fors.c deleted file mode 100644 index f1b0639cfc..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/fors.c +++ /dev/null @@ -1,202 +0,0 @@ -#include -#include -#include - -#include "fors.h" - -#include "address.h" -#include "hash.h" -#include "hashx4.h" -#include "thash.h" -#include "thashx4.h" -#include "utils.h" -#include "utilsx4.h" - -static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, - uint32_t fors_leaf_addr[8]) { - prf_addr(sk, ctx, fors_leaf_addr); -} - -static void fors_gen_skx4(unsigned char *sk0, - unsigned char *sk1, - unsigned char *sk2, - unsigned char *sk3, const spx_ctx *ctx, - uint32_t fors_leaf_addrx4[4 * 8]) { - prf_addrx4(sk0, sk1, sk2, sk3, - ctx, fors_leaf_addrx4); -} - -static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, - const spx_ctx *ctx, - uint32_t fors_leaf_addr[8]) { - thash(leaf, sk, 1, ctx, fors_leaf_addr); -} - -static void fors_sk_to_leafx4(unsigned char *leaf0, - unsigned char *leaf1, - unsigned char *leaf2, - unsigned char *leaf3, - const unsigned char *sk0, - const unsigned char *sk1, - const unsigned char *sk2, - const unsigned char *sk3, - const spx_ctx *ctx, - uint32_t fors_leaf_addrx4[4 * 8]) { - thashx4(leaf0, leaf1, leaf2, leaf3, - sk0, sk1, sk2, sk3, - 1, ctx, fors_leaf_addrx4); -} - -struct fors_gen_leaf_info { - uint32_t leaf_addrx[4 * 8]; -}; - -static void fors_gen_leafx4(unsigned char *leaf, - const spx_ctx *ctx, - uint32_t addr_idx, void *info) { - struct fors_gen_leaf_info *fors_info = info; - uint32_t *fors_leaf_addrx4 = fors_info->leaf_addrx; - unsigned int j; - - /* Only set the parts that the caller doesn't set */ - for (j = 0; j < 4; j++) { - set_tree_index(fors_leaf_addrx4 + j * 8, addr_idx + j); - set_type(fors_leaf_addrx4 + j * 8, SPX_ADDR_TYPE_FORSPRF); - } - - fors_gen_skx4(leaf + 0 * SPX_N, - leaf + 1 * SPX_N, - leaf + 2 * SPX_N, - leaf + 3 * SPX_N, - ctx, fors_leaf_addrx4); - - for (j = 0; j < 4; j++) { - set_type(fors_leaf_addrx4 + j * 8, SPX_ADDR_TYPE_FORSTREE); - } - - fors_sk_to_leafx4(leaf + 0 * SPX_N, - leaf + 1 * SPX_N, - leaf + 2 * SPX_N, - leaf + 3 * SPX_N, - leaf + 0 * SPX_N, - leaf + 1 * SPX_N, - leaf + 2 * SPX_N, - leaf + 3 * SPX_N, - ctx, fors_leaf_addrx4); -} - -/** - * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - * Assumes indices has space for SPX_FORS_TREES integers. - */ -static void message_to_indices(uint32_t *indices, const unsigned char *m) { - unsigned int i, j; - unsigned int offset = 0; - - for (i = 0; i < SPX_FORS_TREES; i++) { - indices[i] = 0; - for (j = 0; j < SPX_FORS_HEIGHT; j++) { - indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); - offset++; - } - } -} - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -void fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]) { - uint32_t indices[SPX_FORS_TREES]; - unsigned char roots[SPX_FORS_TREES * SPX_N]; - uint32_t fors_tree_addr[4 * 8] = {0}; - struct fors_gen_leaf_info fors_info = {0}; - uint32_t *fors_leaf_addr = fors_info.leaf_addrx; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - for (i = 0; i < 4; i++) { - copy_keypair_addr(fors_tree_addr + 8 * i, fors_addr); - set_type(fors_tree_addr + 8 * i, SPX_ADDR_TYPE_FORSTREE); - copy_keypair_addr(fors_leaf_addr + 8 * i, fors_addr); - } - copy_keypair_addr(fors_pk_addr, fors_addr); - set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < SPX_FORS_TREES; i++) { - idx_offset = i * (1 << SPX_FORS_HEIGHT); - - set_tree_height(fors_tree_addr, 0); - set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Include the secret key part that produces the selected leaf node. */ - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); - fors_gen_sk(sig, ctx, fors_tree_addr); - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); - sig += SPX_N; - - /* Compute the authentication path for this leaf node. */ - treehashx4(roots + i * SPX_N, sig, ctx, - indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx4, - fors_tree_addr, &fors_info); - - sig += SPX_N * SPX_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); -} - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -void fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]) { - uint32_t indices[SPX_FORS_TREES]; - unsigned char roots[SPX_FORS_TREES * SPX_N]; - unsigned char leaf[SPX_N]; - uint32_t fors_tree_addr[8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - copy_keypair_addr(fors_tree_addr, fors_addr); - copy_keypair_addr(fors_pk_addr, fors_addr); - - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); - set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < SPX_FORS_TREES; i++) { - idx_offset = i * (1 << SPX_FORS_HEIGHT); - - set_tree_height(fors_tree_addr, 0); - set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Derive the leaf from the included secret key part. */ - fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); - sig += SPX_N; - - /* Derive the corresponding root node of this tree. */ - compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, - sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); - sig += SPX_N * SPX_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/fors.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/fors.h deleted file mode 100644 index 509140a178..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/fors.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef SPX_FORS_H -#define SPX_FORS_H - -#include - -#include "context.h" -#include "params.h" - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -#define fors_sign SPX_NAMESPACE(fors_sign) -void fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]); - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) -void fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/haraka.c deleted file mode 100644 index b414b691d7..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/haraka.c +++ /dev/null @@ -1,702 +0,0 @@ -/* -Plain C implementation of the Haraka256 and Haraka512 permutations. -*/ -#include -#include -#include -#include -#include - -#include "haraka.h" -#include "harakax4.h" -#include "utils.h" - -#define HARAKAS_RATE 32 - -#define u64 unsigned long -#define u128 __m128i - -#define LOAD(src) _mm_loadu_si128((u128 *)(src)) -#define STORE(dest,src) _mm_storeu_si128((u128 *)(dest),src) - -#define XOR128(a, b) _mm_xor_si128(a, b) - -#define AES2(s0, s1, rci) \ - s0 = _mm_aesenc_si128(s0, *(rci)); \ - (s1) = _mm_aesenc_si128(s1, *((rci) + 1)); \ - (s0) = _mm_aesenc_si128(s0, *((rci) + 2)); \ - (s1) = _mm_aesenc_si128(s1, *((rci) + 3)); - -#define AES2_4x(s0, s1, s2, s3, rci) \ - AES2((s0)[0], (s0)[1], rci); \ - AES2((s1)[0], (s1)[1], rci); \ - AES2((s2)[0], (s2)[1], rci); \ - AES2((s3)[0], (s3)[1], rci); - -#define AES4(s0, s1, s2, s3, rci) \ - s0 = _mm_aesenc_si128(s0, *(rci)); \ - (s1) = _mm_aesenc_si128(s1, *((rci) + 1)); \ - (s2) = _mm_aesenc_si128(s2, *((rci) + 2)); \ - (s3) = _mm_aesenc_si128(s3, *((rci) + 3)); \ - (s0) = _mm_aesenc_si128(s0, *((rci) + 4)); \ - (s1) = _mm_aesenc_si128(s1, *((rci) + 5)); \ - (s2) = _mm_aesenc_si128(s2, *((rci) + 6)); \ - (s3) = _mm_aesenc_si128(s3, *((rci) + 7)); - -#define AES4_4x(s0, s1, s2, s3, rci) \ - AES4((s0)[0], (s0)[1], (s0)[2], (s0)[3], rci); \ - AES4((s1)[0], (s1)[1], (s1)[2], (s1)[3], rci); \ - AES4((s2)[0], (s2)[1], (s2)[2], (s2)[3], rci); \ - AES4((s3)[0], (s3)[1], (s3)[2], (s3)[3], rci); - -#define MIX2(s0, s1) \ - tmp = _mm_unpacklo_epi32(s0, s1); \ - (s1) = _mm_unpackhi_epi32(s0, s1); \ - (s0) = tmp; - -#define MIX4(s0, s1, s2, s3) \ - tmp = _mm_unpacklo_epi32(s0, s1); \ - (s0) = _mm_unpackhi_epi32(s0, s1); \ - (s1) = _mm_unpacklo_epi32(s2, s3); \ - (s2) = _mm_unpackhi_epi32(s2, s3); \ - (s3) = _mm_unpacklo_epi32(s0, s2); \ - (s0) = _mm_unpackhi_epi32(s0, s2); \ - (s2) = _mm_unpackhi_epi32(s1, tmp); \ - (s1) = _mm_unpacklo_epi32(s1, tmp); - -#define TRUNCSTORE(out, s0, s1, s2, s3) \ - _mm_storeu_si128((u128 *)(out), \ - _mm_castpd_si128(_mm_shuffle_pd(_mm_castsi128_pd(s0), _mm_castsi128_pd(s1), 3))); \ - _mm_storeu_si128((u128 *)((out) + 16), \ - _mm_castpd_si128(_mm_shuffle_pd(_mm_castsi128_pd(s2), _mm_castsi128_pd(s3), 0))); - -static void load_haraka_constants(u128 *rc) { - rc[0] = _mm_set_epi32((int)0x0684704c, (int)0xe620c00a, (int)0xb2c5fef0, (int)0x75817b9d); - rc[1] = _mm_set_epi32((int)0x8b66b4e1, (int)0x88f3a06b, (int)0x640f6ba4, (int)0x2f08f717); - rc[2] = _mm_set_epi32((int)0x3402de2d, (int)0x53f28498, (int)0xcf029d60, (int)0x9f029114); - rc[3] = _mm_set_epi32((int)0x0ed6eae6, (int)0x2e7b4f08, (int)0xbbf3bcaf, (int)0xfd5b4f79); - rc[4] = _mm_set_epi32((int)0xcbcfb0cb, (int)0x4872448b, (int)0x79eecd1c, (int)0xbe397044); - rc[5] = _mm_set_epi32((int)0x7eeacdee, (int)0x6e9032b7, (int)0x8d5335ed, (int)0x2b8a057b); - rc[6] = _mm_set_epi32((int)0x67c28f43, (int)0x5e2e7cd0, (int)0xe2412761, (int)0xda4fef1b); - rc[7] = _mm_set_epi32((int)0x2924d9b0, (int)0xafcacc07, (int)0x675ffde2, (int)0x1fc70b3b); - rc[8] = _mm_set_epi32((int)0xab4d63f1, (int)0xe6867fe9, (int)0xecdb8fca, (int)0xb9d465ee); - rc[9] = _mm_set_epi32((int)0x1c30bf84, (int)0xd4b7cd64, (int)0x5b2a404f, (int)0xad037e33); - rc[10] = _mm_set_epi32((int)0xb2cc0bb9, (int)0x941723bf, (int)0x69028b2e, (int)0x8df69800); - rc[11] = _mm_set_epi32((int)0xfa0478a6, (int)0xde6f5572, (int)0x4aaa9ec8, (int)0x5c9d2d8a); - rc[12] = _mm_set_epi32((int)0xdfb49f2b, (int)0x6b772a12, (int)0x0efa4f2e, (int)0x29129fd4); - rc[13] = _mm_set_epi32((int)0x1ea10344, (int)0xf449a236, (int)0x32d611ae, (int)0xbb6a12ee); - rc[14] = _mm_set_epi32((int)0xaf044988, (int)0x4b050084, (int)0x5f9600c9, (int)0x9ca8eca6); - rc[15] = _mm_set_epi32((int)0x21025ed8, (int)0x9d199c4f, (int)0x78a2c7e3, (int)0x27e593ec); - rc[16] = _mm_set_epi32((int)0xbf3aaaf8, (int)0xa759c9b7, (int)0xb9282ecd, (int)0x82d40173); - rc[17] = _mm_set_epi32((int)0x6260700d, (int)0x6186b017, (int)0x37f2efd9, (int)0x10307d6b); - rc[18] = _mm_set_epi32((int)0x5aca45c2, (int)0x21300443, (int)0x81c29153, (int)0xf6fc9ac6); - rc[19] = _mm_set_epi32((int)0x9223973c, (int)0x226b68bb, (int)0x2caf92e8, (int)0x36d1943a); - rc[20] = _mm_set_epi32((int)0xd3bf9238, (int)0x225886eb, (int)0x6cbab958, (int)0xe51071b4); - rc[21] = _mm_set_epi32((int)0xdb863ce5, (int)0xaef0c677, (int)0x933dfddd, (int)0x24e1128d); - rc[22] = _mm_set_epi32((int)0xbb606268, (int)0xffeba09c, (int)0x83e48de3, (int)0xcb2212b1); - rc[23] = _mm_set_epi32((int)0x734bd3dc, (int)0xe2e4d19c, (int)0x2db91a4e, (int)0xc72bf77d); - rc[24] = _mm_set_epi32((int)0x43bb47c3, (int)0x61301b43, (int)0x4b1415c4, (int)0x2cb3924e); - rc[25] = _mm_set_epi32((int)0xdba775a8, (int)0xe707eff6, (int)0x03b231dd, (int)0x16eb6899); - rc[26] = _mm_set_epi32((int)0x6df3614b, (int)0x3c755977, (int)0x8e5e2302, (int)0x7eca472c); - rc[27] = _mm_set_epi32((int)0xcda75a17, (int)0xd6de7d77, (int)0x6d1be5b9, (int)0xb88617f9); - rc[28] = _mm_set_epi32((int)0xec6b43f0, (int)0x6ba8e9aa, (int)0x9d6c069d, (int)0xa946ee5d); - rc[29] = _mm_set_epi32((int)0xcb1e6950, (int)0xf957332b, (int)0xa2531159, (int)0x3bf327c1); - rc[30] = _mm_set_epi32((int)0x2cee0c75, (int)0x00da619c, (int)0xe4ed0353, (int)0x600ed0d9); - rc[31] = _mm_set_epi32((int)0xf0b1a5a1, (int)0x96e90cab, (int)0x80bbbabc, (int)0x63a4a350); - rc[32] = _mm_set_epi32((int)0xae3db102, (int)0x5e962988, (int)0xab0dde30, (int)0x938dca39); - rc[33] = _mm_set_epi32((int)0x17bb8f38, (int)0xd554a40b, (int)0x8814f3a8, (int)0x2e75b442); - rc[34] = _mm_set_epi32((int)0x34bb8a5b, (int)0x5f427fd7, (int)0xaeb6b779, (int)0x360a16f6); - rc[35] = _mm_set_epi32((int)0x26f65241, (int)0xcbe55438, (int)0x43ce5918, (int)0xffbaafde); - rc[36] = _mm_set_epi32((int)0x4ce99a54, (int)0xb9f3026a, (int)0xa2ca9cf7, (int)0x839ec978); - rc[37] = _mm_set_epi32((int)0xae51a51a, (int)0x1bdff7be, (int)0x40c06e28, (int)0x22901235); - rc[38] = _mm_set_epi32((int)0xa0c1613c, (int)0xba7ed22b, (int)0xc173bc0f, (int)0x48a659cf); - rc[39] = _mm_set_epi32((int)0x756acc03, (int)0x02288288, (int)0x4ad6bdfd, (int)0xe9c59da1); -} - -void tweak_constants(spx_ctx *ctx) { - int i; - unsigned char buf[40 * 16]; - - /* Use the standard constants to generate tweaked ones. */ - load_haraka_constants(ctx->rc); - - /* Constants for pk.seed */ - haraka_S(buf, 40 * 16, ctx->pub_seed, SPX_N, ctx); - - /* Tweak constants with the pub_seed */ - for (i = 0; i < 40; i++) { - ctx->rc[i] = LOAD(buf + i * 16); - } -} - -static void haraka_S_absorb(unsigned char *s, unsigned int r, - const unsigned char *m, unsigned long long mlen, - unsigned char p, const spx_ctx *ctx) { - unsigned long long i; - PQCLEAN_VLA(unsigned char, t, r); - - while (mlen >= r) { - // XOR block to state - STORE(s, XOR128(LOAD(s), LOAD(m))); - STORE(s + 16, XOR128(LOAD(s + 16), LOAD(m + 16))); - haraka512_perm(s, s, ctx); - 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; - STORE(s, XOR128(LOAD(s), LOAD(t))); - STORE(s + 16, XOR128(LOAD(s + 16), LOAD(t + 16))); -} - -static void haraka_S_absorb4x(unsigned char *s, - unsigned int r, - const unsigned char *m0, - const unsigned char *m1, - const unsigned char *m2, - const unsigned char *m3, - unsigned long long int mlen, - unsigned char p, - const spx_ctx *ctx) { - unsigned long long i; - PQCLEAN_VLA(unsigned char, t0, r); - PQCLEAN_VLA(unsigned char, t1, r); - PQCLEAN_VLA(unsigned char, t2, r); - PQCLEAN_VLA(unsigned char, t3, r); - - while (mlen >= r) { - // XOR block to state - STORE(s, XOR128(LOAD(s), LOAD(m0))); - STORE(s + 16, XOR128(LOAD(s + 16), LOAD(m0 + 16))); - STORE(s + 64, XOR128(LOAD(s + 64), LOAD(m1))); - STORE(s + 80, XOR128(LOAD(s + 80), LOAD(m1 + 16))); - STORE(s + 128, XOR128(LOAD(s + 128), LOAD(m2))); - STORE(s + 144, XOR128(LOAD(s + 144), LOAD(m2 + 16))); - STORE(s + 192, XOR128(LOAD(s + 192), LOAD(m3))); - STORE(s + 208, XOR128(LOAD(s + 208), LOAD(m3 + 16))); - - haraka512_perm_x4(s, s, ctx); - mlen -= r; - m0 += r; - m1 += r; - m2 += r; - m3 += r; - } - - for (i = 0; i < r; ++i) { - t0[i] = 0; - t1[i] = 0; - t2[i] = 0; - t3[i] = 0; - } - for (i = 0; i < mlen; ++i) { - t0[i] = m0[i]; - t1[i] = m1[i]; - t2[i] = m2[i]; - t3[i] = m3[i]; - } - - t0[i] = p; - t1[i] = p; - t2[i] = p; - t3[i] = p; - - t0[r - 1] |= 128; - t1[r - 1] |= 128; - t2[r - 1] |= 128; - t3[r - 1] |= 128; - - STORE(s, XOR128(LOAD(s), LOAD(t0))); - STORE(s + 16, XOR128(LOAD(s + 16), LOAD(t0 + 16))); - STORE(s + 64, XOR128(LOAD(s + 64), LOAD(t1))); - STORE(s + 80, XOR128(LOAD(s + 80), LOAD(t1 + 16))); - STORE(s + 128, XOR128(LOAD(s + 128), LOAD(t2))); - STORE(s + 144, XOR128(LOAD(s + 144), LOAD(t2 + 16))); - STORE(s + 192, XOR128(LOAD(s + 192), LOAD(t3))); - STORE(s + 208, XOR128(LOAD(s + 208), LOAD(t3 + 16))); -} - -static void haraka_S_squeezeblocks(unsigned char *h, unsigned long long nblocks, - unsigned char *s, unsigned int r, - const spx_ctx *ctx) { - while (nblocks > 0) { - haraka512_perm(s, s, ctx); - STORE(h, LOAD(s)); - STORE(h + 16, LOAD(s + 16)); - h += r; - nblocks--; - } -} - -static void haraka_S_squeezeblocks4x(unsigned char *h0, - unsigned char *h1, - unsigned char *h2, - unsigned char *h3, - unsigned long long nblocks, - unsigned char *s, - unsigned int r, - const spx_ctx *ctx) { - while (nblocks > 0) { - haraka512_perm_x4(s, s, ctx); - STORE(h0, LOAD(s)); - STORE(h0 + 16, LOAD(s + 16)); - STORE(h1, LOAD(s + 64)); - STORE(h1 + 16, LOAD(s + 80)); - STORE(h2, LOAD(s + 128)); - STORE(h2 + 16, LOAD(s + 144)); - STORE(h3, LOAD(s + 192)); - STORE(h3 + 16, LOAD(s + 208)); - h0 += r; - h1 += r; - h2 += r; - h3 += r; - nblocks--; - } -} - -void haraka_S_inc_init(uint8_t *s_inc) { - size_t i; - - for (i = 0; i < 64; i++) { - s_inc[i] = 0; - } - s_inc[64] = 0; -} - -void haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, - const spx_ctx *ctx) { - size_t i; - - /* Recall that s_inc[64] is the non-absorbed bytes xored into the state */ - while (mlen + s_inc[64] >= HARAKAS_RATE) { - for (i = 0; i < (size_t)(HARAKAS_RATE - s_inc[64]); i++) { - /* Take the i'th byte from message - xor with the s_inc[64] + i'th byte of the state */ - s_inc[s_inc[64] + i] ^= m[i]; - } - mlen -= (size_t)(HARAKAS_RATE - s_inc[64]); - m += HARAKAS_RATE - s_inc[64]; - s_inc[64] = 0; - - haraka512_perm(s_inc, s_inc, ctx); - } - - for (i = 0; i < mlen; i++) { - s_inc[s_inc[64] + i] ^= m[i]; - } - s_inc[64] += (uint8_t)mlen; -} - -void haraka_S_inc_finalize(uint8_t *s_inc) { - /* After haraka_S_inc_absorb, we are guaranteed that s_inc[64] < HARAKAS_RATE, - so we can always use one more byte for p in the current state. */ - s_inc[s_inc[64]] ^= 0x1F; - s_inc[HARAKAS_RATE - 1] ^= 128; - s_inc[64] = 0; -} - -void haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, - const spx_ctx *ctx) { - size_t i; - - /* First consume any bytes we still have sitting around */ - for (i = 0; i < outlen && i < s_inc[64]; i++) { - /* There are s_inc[64] bytes left, so r - s_inc[64] is the first - available byte. We consume from there, i.e., up to r. */ - out[i] = (uint8_t)s_inc[(HARAKAS_RATE - s_inc[64] + i)]; - } - out += i; - outlen -= i; - s_inc[64] -= (uint8_t)i; - - /* Then squeeze the remaining necessary blocks */ - while (outlen > 0) { - haraka512_perm(s_inc, s_inc, ctx); - - for (i = 0; i < outlen && i < HARAKAS_RATE; i++) { - out[i] = s_inc[i]; - } - out += i; - outlen -= i; - s_inc[64] = (uint8_t)(HARAKAS_RATE - i); - } -} - -void haraka_S(unsigned char *out, unsigned long long outlen, - const unsigned char *in, unsigned long long inlen, - const spx_ctx *ctx) { - unsigned long long i; - unsigned char s[64]; - unsigned char d[32]; - - for (i = 0; i < 64; i++) { - s[i] = 0; - } - haraka_S_absorb(s, HARAKAS_RATE, in, inlen, 0x1F, ctx); - - haraka_S_squeezeblocks(out, outlen / HARAKAS_RATE, s, HARAKAS_RATE, ctx); - out += (outlen / HARAKAS_RATE) * HARAKAS_RATE; - - if (outlen % HARAKAS_RATE) { - haraka_S_squeezeblocks(d, 1, s, HARAKAS_RATE, ctx); - for (i = 0; i < outlen % HARAKAS_RATE; i++) { - out[i] = d[i]; - } - } -} - -void haraka_Sx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned long long outlen, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - unsigned long long inlen, - const spx_ctx *ctx) { - unsigned long long i; - unsigned char s[64 * 4]; - unsigned char d0[32]; - unsigned char d1[32]; - unsigned char d2[32]; - unsigned char d3[32]; - - for (i = 0; i < 64 * 4; i++) { - s[i] = 0; - } - haraka_S_absorb4x(s, HARAKAS_RATE, in0, in1, in2, in3, inlen, 0x1F, ctx); - - haraka_S_squeezeblocks4x(out0, out1, out2, out3, outlen / HARAKAS_RATE, s, - HARAKAS_RATE, ctx); - out0 += (outlen / HARAKAS_RATE) * HARAKAS_RATE; - out1 += (outlen / HARAKAS_RATE) * HARAKAS_RATE; - out2 += (outlen / HARAKAS_RATE) * HARAKAS_RATE; - out3 += (outlen / HARAKAS_RATE) * HARAKAS_RATE; - - if (outlen % HARAKAS_RATE) { - haraka_S_squeezeblocks4x(d0, d1, d2, d3, 1, s, HARAKAS_RATE, ctx); - for (i = 0; i < outlen % HARAKAS_RATE; i++) { - out0[i] = d0[i]; - out1[i] = d1[i]; - out2[i] = d2[i]; - out3[i] = d3[i]; - } - } -} - -void haraka512_perm(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx) { - u128 s[4], tmp; - - s[0] = LOAD(in); - s[1] = LOAD(in + 16); - s[2] = LOAD(in + 32); - s[3] = LOAD(in + 48); - - AES4(s[0], s[1], s[2], s[3], ctx->rc); - MIX4(s[0], s[1], s[2], s[3]); - - AES4(s[0], s[1], s[2], s[3], ctx->rc + 8); - MIX4(s[0], s[1], s[2], s[3]); - - AES4(s[0], s[1], s[2], s[3], ctx->rc + 16); - MIX4(s[0], s[1], s[2], s[3]); - - AES4(s[0], s[1], s[2], s[3], ctx->rc + 24); - MIX4(s[0], s[1], s[2], s[3]); - - AES4(s[0], s[1], s[2], s[3], ctx->rc + 32); - MIX4(s[0], s[1], s[2], s[3]); - - STORE(out, s[0]); - STORE(out + 16, s[1]); - STORE(out + 32, s[2]); - STORE(out + 48, s[3]); -} - -void haraka512_perm_x4(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx) { - u128 s[4][4], tmp; - - s[0][0] = LOAD(in); - s[0][1] = LOAD(in + 16); - s[0][2] = LOAD(in + 32); - s[0][3] = LOAD(in + 48); - s[1][0] = LOAD(in + 64); - s[1][1] = LOAD(in + 80); - s[1][2] = LOAD(in + 96); - s[1][3] = LOAD(in + 112); - s[2][0] = LOAD(in + 128); - s[2][1] = LOAD(in + 144); - s[2][2] = LOAD(in + 160); - s[2][3] = LOAD(in + 176); - s[3][0] = LOAD(in + 192); - s[3][1] = LOAD(in + 208); - s[3][2] = LOAD(in + 224); - s[3][3] = LOAD(in + 240); - - AES4_4x(s[0], s[1], s[2], s[3], ctx->rc); - MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); - MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); - MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); - MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - - AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 8); - MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); - MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); - MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); - MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - - AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 16); - MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); - MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); - MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); - MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - - AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 24); - MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); - MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); - MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); - MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - - AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 32); - MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); - MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); - MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); - MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - - STORE(out, s[0][0]); - STORE(out + 16, s[0][1]); - STORE(out + 32, s[0][2]); - STORE(out + 48, s[0][3]); - STORE(out + 64, s[1][0]); - STORE(out + 80, s[1][1]); - STORE(out + 96, s[1][2]); - STORE(out + 112, s[1][3]); - STORE(out + 128, s[2][0]); - STORE(out + 144, s[2][1]); - STORE(out + 160, s[2][2]); - STORE(out + 176, s[2][3]); - STORE(out + 192, s[3][0]); - STORE(out + 208, s[3][1]); - STORE(out + 224, s[3][2]); - STORE(out + 240, s[3][3]); -} - -void haraka512(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx) { - u128 s[4], tmp; - - s[0] = LOAD(in); - s[1] = LOAD(in + 16); - s[2] = LOAD(in + 32); - s[3] = LOAD(in + 48); - - AES4(s[0], s[1], s[2], s[3], ctx->rc); - MIX4(s[0], s[1], s[2], s[3]); - - AES4(s[0], s[1], s[2], s[3], ctx->rc + 8); - MIX4(s[0], s[1], s[2], s[3]); - - AES4(s[0], s[1], s[2], s[3], ctx->rc + 16); - MIX4(s[0], s[1], s[2], s[3]); - - AES4(s[0], s[1], s[2], s[3], ctx->rc + 24); - MIX4(s[0], s[1], s[2], s[3]); - - AES4(s[0], s[1], s[2], s[3], ctx->rc + 32); - MIX4(s[0], s[1], s[2], s[3]); - - s[0] = XOR128(s[0], LOAD(in)); - s[1] = XOR128(s[1], LOAD(in + 16)); - s[2] = XOR128(s[2], LOAD(in + 32)); - s[3] = XOR128(s[3], LOAD(in + 48)); - - // truncate and store result - TRUNCSTORE(out, s[0], s[1], s[2], s[3]); -} - -void haraka512x4(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx) { - u128 s[4][4], tmp; - - s[0][0] = LOAD(in); - s[0][1] = LOAD(in + 16); - s[0][2] = LOAD(in + 32); - s[0][3] = LOAD(in + 48); - s[1][0] = LOAD(in + 64); - s[1][1] = LOAD(in + 80); - s[1][2] = LOAD(in + 96); - s[1][3] = LOAD(in + 112); - s[2][0] = LOAD(in + 128); - s[2][1] = LOAD(in + 144); - s[2][2] = LOAD(in + 160); - s[2][3] = LOAD(in + 176); - s[3][0] = LOAD(in + 192); - s[3][1] = LOAD(in + 208); - s[3][2] = LOAD(in + 224); - s[3][3] = LOAD(in + 240); - - AES4_4x(s[0], s[1], s[2], s[3], ctx->rc); - MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); - MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); - MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); - MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - - AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 8); - MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); - MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); - MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); - MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - - AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 16); - MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); - MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); - MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); - MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - - AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 24); - MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); - MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); - MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); - MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - - AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 32); - MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); - MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); - MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); - MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - - s[0][0] = XOR128(s[0][0], LOAD(in)); - s[0][1] = XOR128(s[0][1], LOAD(in + 16)); - s[0][2] = XOR128(s[0][2], LOAD(in + 32)); - s[0][3] = XOR128(s[0][3], LOAD(in + 48)); - s[1][0] = XOR128(s[1][0], LOAD(in + 64)); - s[1][1] = XOR128(s[1][1], LOAD(in + 80)); - s[1][2] = XOR128(s[1][2], LOAD(in + 96)); - s[1][3] = XOR128(s[1][3], LOAD(in + 112)); - s[2][0] = XOR128(s[2][0], LOAD(in + 128)); - s[2][1] = XOR128(s[2][1], LOAD(in + 144)); - s[2][2] = XOR128(s[2][2], LOAD(in + 160)); - s[2][3] = XOR128(s[2][3], LOAD(in + 176)); - s[3][0] = XOR128(s[3][0], LOAD(in + 192)); - s[3][1] = XOR128(s[3][1], LOAD(in + 208)); - s[3][2] = XOR128(s[3][2], LOAD(in + 224)); - s[3][3] = XOR128(s[3][3], LOAD(in + 240)); - - TRUNCSTORE(out, s[0][0], s[0][1], s[0][2], s[0][3]); - TRUNCSTORE((out + 32), s[1][0], s[1][1], s[1][2], s[1][3]); - TRUNCSTORE((out + 64), s[2][0], s[2][1], s[2][2], s[2][3]); - TRUNCSTORE((out + 96), s[3][0], s[3][1], s[3][2], s[3][3]); -} - -void haraka256(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx) { - u128 s[2], tmp; - - s[0] = LOAD(in); - s[1] = LOAD(in + 16); - - AES2(s[0], s[1], ctx->rc); - MIX2(s[0], s[1]); - - AES2(s[0], s[1], ctx->rc + 4); - MIX2(s[0], s[1]); - - AES2(s[0], s[1], ctx->rc + 8); - MIX2(s[0], s[1]); - - AES2(s[0], s[1], ctx->rc + 12); - MIX2(s[0], s[1]); - - AES2(s[0], s[1], ctx->rc + 16); - MIX2(s[0], s[1]); - - s[0] = XOR128(s[0], LOAD(in)); - s[1] = XOR128(s[1], LOAD(in + 16)); - - STORE(out, s[0]); - STORE(out + 16, s[1]); -} - -void haraka256x4(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx) { - u128 s[4][2], tmp; - - s[0][0] = LOAD(in); - s[0][1] = LOAD(in + 16); - s[1][0] = LOAD(in + 32); - s[1][1] = LOAD(in + 48); - s[2][0] = LOAD(in + 64); - s[2][1] = LOAD(in + 80); - s[3][0] = LOAD(in + 96); - s[3][1] = LOAD(in + 112); - - // Round 1 - AES2_4x(s[0], s[1], s[2], s[3], ctx->rc); - - MIX2(s[0][0], s[0][1]); - MIX2(s[1][0], s[1][1]); - MIX2(s[2][0], s[2][1]); - MIX2(s[3][0], s[3][1]); - - // Round 2 - AES2_4x(s[0], s[1], s[2], s[3], ctx->rc + 4); - - MIX2(s[0][0], s[0][1]); - MIX2(s[1][0], s[1][1]); - MIX2(s[2][0], s[2][1]); - MIX2(s[3][0], s[3][1]); - - // Round 3 - AES2_4x(s[0], s[1], s[2], s[3], ctx->rc + 8); - - MIX2(s[0][0], s[0][1]); - MIX2(s[1][0], s[1][1]); - MIX2(s[2][0], s[2][1]); - MIX2(s[3][0], s[3][1]); - - // Round 4 - AES2_4x(s[0], s[1], s[2], s[3], ctx->rc + 12); - - MIX2(s[0][0], s[0][1]); - MIX2(s[1][0], s[1][1]); - MIX2(s[2][0], s[2][1]); - MIX2(s[3][0], s[3][1]); - - // Round 5 - AES2_4x(s[0], s[1], s[2], s[3], ctx->rc + 16); - - MIX2(s[0][0], s[0][1]); - MIX2(s[1][0], s[1][1]); - MIX2(s[2][0], s[2][1]); - MIX2(s[3][0], s[3][1]); - - // Feed Forward - s[0][0] = _mm_xor_si128(s[0][0], LOAD(in)); - s[0][1] = _mm_xor_si128(s[0][1], LOAD(in + 16)); - s[1][0] = _mm_xor_si128(s[1][0], LOAD(in + 32)); - s[1][1] = _mm_xor_si128(s[1][1], LOAD(in + 48)); - s[2][0] = _mm_xor_si128(s[2][0], LOAD(in + 64)); - s[2][1] = _mm_xor_si128(s[2][1], LOAD(in + 80)); - s[3][0] = _mm_xor_si128(s[3][0], LOAD(in + 96)); - s[3][1] = _mm_xor_si128(s[3][1], LOAD(in + 112)); - - STORE(out, s[0][0]); - STORE(out + 16, s[0][1]); - STORE(out + 32, s[1][0]); - STORE(out + 48, s[1][1]); - STORE(out + 64, s[2][0]); - STORE(out + 80, s[2][1]); - STORE(out + 96, s[3][0]); - STORE(out + 112, s[3][1]); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/haraka.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/haraka.h deleted file mode 100644 index 737cb6065f..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/haraka.h +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef SPX_HARAKA_H -#define SPX_HARAKA_H - -#include "context.h" -#include "params.h" - -/* Tweak constants with seed */ -#define tweak_constants SPX_NAMESPACE(tweak_constants) -void tweak_constants(spx_ctx *ctx); - -/* Haraka Sponge */ -#define haraka_S_inc_init SPX_NAMESPACE(haraka_S_inc_init) -void haraka_S_inc_init(uint8_t *s_inc); -#define haraka_S_inc_absorb SPX_NAMESPACE(haraka_S_inc_absorb) -void haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, - const spx_ctx *ctx); -#define haraka_S_inc_finalize SPX_NAMESPACE(haraka_S_inc_finalize) -void haraka_S_inc_finalize(uint8_t *s_inc); -#define haraka_S_inc_squeeze SPX_NAMESPACE(haraka_S_inc_squeeze) -void haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, - const spx_ctx *ctx); -#define haraka_S SPX_NAMESPACE(haraka_S) -void haraka_S(unsigned char *out, unsigned long long outlen, - const unsigned char *in, unsigned long long inlen, - const spx_ctx *ctx); - -/* Applies the 512-bit Haraka permutation to in. */ -#define haraka512_perm SPX_NAMESPACE(haraka512_perm) -void haraka512_perm(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx); - -/* Implementation of Haraka-512 */ -#define haraka512 SPX_NAMESPACE(haraka512) -void haraka512(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx); - -/* Implementation of Haraka-256 */ -#define haraka256 SPX_NAMESPACE(haraka256) -void haraka256(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/haraka_offsets.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/haraka_offsets.h deleted file mode 100644 index 7c062272a0..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/haraka_offsets.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef HARAKA_OFFSETS_H_ -#define HARAKA_OFFSETS_H_ - -/* - * Offsets of various fields in the address structure when we use Haraka as - * the Sphincs+ hash function - */ - -#define SPX_OFFSET_LAYER 3 /* The byte used to specify the Merkle tree layer */ -#define SPX_OFFSET_TREE 8 /* The start of the 8 byte field used to specify the tree */ -#define SPX_OFFSET_TYPE 19 /* The byte used to specify the hash type (reason) */ -#define SPX_OFFSET_KP_ADDR2 22 /* The high byte used to specify the key pair (which one-time signature) */ -#define SPX_OFFSET_KP_ADDR1 23 /* The low byte used to specify the key pair */ -#define SPX_OFFSET_CHAIN_ADDR 27 /* The byte used to specify the chain address (which Winternitz chain) */ -#define SPX_OFFSET_HASH_ADDR 31 /* The byte used to specify the hash address (where in the Winternitz chain) */ -#define SPX_OFFSET_TREE_HGT 27 /* The byte used to specify the height of this node in the FORS or Merkle tree */ -#define SPX_OFFSET_TREE_INDEX 28 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ - -#define SPX_HARAKA 1 - -#endif /* HARAKA_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/harakax4.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/harakax4.h deleted file mode 100644 index eadc69aa48..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/harakax4.h +++ /dev/null @@ -1,36 +0,0 @@ -#ifndef SPX_HARAKAX4_H -#define SPX_HARAKAX4_H - -#include "context.h" -#include "params.h" - -/* Haraka Sponge */ -#define haraka_Sx4 SPX_NAMESPACE(haraka_Sx4) -void haraka_Sx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned long long outlen, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - unsigned long long inlen, - const spx_ctx *ctx); - -/* Applies the 512-bit Haraka permutation x4 to in. */ -#define haraka512_perm_x4 SPX_NAMESPACE(haraka512_perm_x4) -void haraka512_perm_x4(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx); - -/* Implementation of Haraka-512 x4*/ -#define haraka512x4 SPX_NAMESPACE(haraka512x4) -void haraka512x4(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx); - -/* Implementation of Haraka-256 x4 */ -#define haraka256x4 SPX_NAMESPACE(haraka256x4) -void haraka256x4(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/hash.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/hash.h deleted file mode 100644 index f7c87d4c3c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/hash.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef SPX_HASH_H -#define SPX_HASH_H - -#include -#include - -#include "context.h" -#include "params.h" - -#define prf_addr SPX_NAMESPACE(prf_addr) -void prf_addr(unsigned char *out, const spx_ctx *ctx, - const uint32_t addr[8]); - -#define gen_message_random SPX_NAMESPACE(gen_message_random) -void gen_message_random(unsigned char *R, const unsigned char *sk_prf, - const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx); - -#define hash_message SPX_NAMESPACE(hash_message) -void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx); - - - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/hash_haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/hash_haraka.c deleted file mode 100644 index 750a67423b..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/hash_haraka.c +++ /dev/null @@ -1,81 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "utils.h" - -#include "haraka.h" -#include "hash.h" - -/* - * Computes PRF(key, addr), given a secret key of SPX_N bytes and an address - */ -void prf_addr(unsigned char *out, const spx_ctx *ctx, - const uint32_t addr[8]) { - /* Since SPX_N may be smaller than 32, we need temporary buffers. */ - unsigned char outbuf[32]; - unsigned char buf[64] = {0}; - - memcpy(buf, addr, SPX_ADDR_BYTES); - memcpy(buf + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); - - haraka512(outbuf, (const void *)buf, ctx); - memcpy(out, outbuf, SPX_N); -} - -/** - * Computes the message-dependent randomness R, using a secret seed and an - * optional randomization value as well as the message. - */ -void gen_message_random(unsigned char *R, const unsigned char *sk_prf, - const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx) { - uint8_t s_inc[65]; - - haraka_S_inc_init(s_inc); - haraka_S_inc_absorb(s_inc, sk_prf, SPX_N, ctx); - haraka_S_inc_absorb(s_inc, optrand, SPX_N, ctx); - haraka_S_inc_absorb(s_inc, m, mlen, ctx); - haraka_S_inc_finalize(s_inc); - haraka_S_inc_squeeze(R, SPX_N, s_inc, ctx); -} - -/** - * Computes the message hash using R, the public key, and the message. - * Outputs the message digest and the index of the leaf. The index is split in - * the tree index and the leaf index, for convenient copying to an address. - */ -void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx) { -#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) -#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) -#define SPX_LEAF_BITS SPX_TREE_HEIGHT -#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) -#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) - - unsigned char buf[SPX_DGST_BYTES]; - unsigned char *bufp = buf; - uint8_t s_inc[65]; - - haraka_S_inc_init(s_inc); - haraka_S_inc_absorb(s_inc, R, SPX_N, ctx); - haraka_S_inc_absorb(s_inc, pk + SPX_N, SPX_N, ctx); // Only absorb root part of pk - haraka_S_inc_absorb(s_inc, m, mlen, ctx); - haraka_S_inc_finalize(s_inc); - haraka_S_inc_squeeze(buf, SPX_DGST_BYTES, s_inc, ctx); - - memcpy(digest, bufp, SPX_FORS_MSG_BYTES); - bufp += SPX_FORS_MSG_BYTES; - - - *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); - *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); - bufp += SPX_TREE_BYTES; - - *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); - *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/hash_harakax4.c b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/hash_harakax4.c deleted file mode 100644 index cfa5162d79..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/hash_harakax4.c +++ /dev/null @@ -1,35 +0,0 @@ -#include -#include - -#include "address.h" -#include "harakax4.h" -#include "hashx4.h" -#include "params.h" - -/* - * 4-way parallel version of prf_addr; takes 4x as much input and output - */ -#define prf_addrx4 SPX_NAMESPACE(prf_addrx4) -void prf_addrx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const spx_ctx *ctx, - const uint32_t addrx4[4 * 8]) { - unsigned char bufx4[4 * 64] = {0}; - /* Since SPX_N may be smaller than 32, we need temporary buffers. */ - unsigned char outbuf[4 * 32]; - unsigned int i; - - for (i = 0; i < 4; i++) { - memcpy(bufx4 + i * 64, addrx4 + i * 8, SPX_ADDR_BYTES); - memcpy(bufx4 + i * 64 + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); - } - - haraka512x4(outbuf, bufx4, ctx); - - memcpy(out0, outbuf, SPX_N); - memcpy(out1, outbuf + 32, SPX_N); - memcpy(out2, outbuf + 64, SPX_N); - memcpy(out3, outbuf + 96, SPX_N); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/hashx4.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/hashx4.h deleted file mode 100644 index 3751a0ebd0..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/hashx4.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef SPX_HASHX4_H -#define SPX_HASHX4_H - -#include - -#include "context.h" -#include "params.h" - -#define prf_addrx4 SPX_NAMESPACE(prf_addrx4) -void prf_addrx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const spx_ctx *ctx, - const uint32_t addrx4[4 * 8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/merkle.c b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/merkle.c deleted file mode 100644 index f57811c1ac..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/merkle.c +++ /dev/null @@ -1,64 +0,0 @@ -#include -#include - -#include "merkle.h" - -#include "address.h" -#include "params.h" -#include "utils.h" -#include "utilsx4.h" -#include "wots.h" -#include "wotsx4.h" - -/* - * This generates a Merkle signature (WOTS signature followed by the Merkle - * authentication path). - */ -void merkle_sign(uint8_t *sig, unsigned char *root, - const spx_ctx *ctx, - uint32_t wots_addr[8], uint32_t tree_addr[8], - uint32_t idx_leaf) { - unsigned char *auth_path = sig + SPX_WOTS_BYTES; - uint32_t tree_addrx4[4 * 8] = { 0 }; - int j; - struct leaf_info_x4 info = { 0 }; - unsigned steps[ SPX_WOTS_LEN ]; - - info.wots_sig = sig; - chain_lengths(steps, root); - info.wots_steps = steps; - - for (j = 0; j < 4; j++) { - set_type(&tree_addrx4[8 * j], SPX_ADDR_TYPE_HASHTREE); - set_type(&info.leaf_addr[8 * j], SPX_ADDR_TYPE_WOTS); - set_type(&info.pk_addr[8 * j], SPX_ADDR_TYPE_WOTSPK); - copy_subtree_addr(&tree_addrx4[8 * j], tree_addr); - copy_subtree_addr(&info.leaf_addr[8 * j], wots_addr); - copy_subtree_addr(&info.pk_addr[8 * j], wots_addr); - } - - info.wots_sign_leaf = idx_leaf; - - treehashx4(root, auth_path, ctx, - idx_leaf, 0, - SPX_TREE_HEIGHT, - wots_gen_leafx4, - tree_addrx4, &info); -} - -/* Compute root node of the top-most subtree. */ -void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { - /* We do not need the auth path in key generation, but it simplifies the - code to have just one treehash routine that computes both root and path - in one function. */ - unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; - uint32_t top_tree_addr[8] = {0}; - uint32_t wots_addr[8] = {0}; - - set_layer_addr(top_tree_addr, SPX_D - 1); - set_layer_addr(wots_addr, SPX_D - 1); - - merkle_sign(auth_path, root, ctx, - wots_addr, top_tree_addr, - ~0U /* ~0 means "don't bother generating an auth path */ ); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/merkle.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/merkle.h deleted file mode 100644 index 769cf2e970..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/merkle.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef MERKLE_H_ -#define MERKLE_H_ - -#include - -#include "context.h" -#include "params.h" - -/* Generate a Merkle signature (WOTS signature followed by the Merkle */ -/* authentication path) */ -#define merkle_sign SPX_NAMESPACE(merkle_sign) -void merkle_sign(uint8_t *sig, unsigned char *root, - const spx_ctx *ctx, - uint32_t wots_addr[8], uint32_t tree_addr[8], - uint32_t idx_leaf); - -/* Compute the root node of the top-most subtree. */ -#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) -void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); - -#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/nistapi.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/nistapi.h deleted file mode 100644 index 3cb71afad4..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/nistapi.h +++ /dev/null @@ -1,87 +0,0 @@ -#ifndef SPX_API_H -#define SPX_API_H - -#include -#include - -#include "params.h" - -#define CRYPTO_ALGNAME "SPHINCS+" - -#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES -#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES -#define CRYPTO_BYTES SPX_BYTES -#define CRYPTO_SEEDBYTES (3*SPX_N) - -/* - * Returns the length of a secret key, in bytes - */ -#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) -size_t crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) -size_t crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) -size_t crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) -size_t crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) -int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) -int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) -int crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) -int crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -#define crypto_sign SPX_NAMESPACE(crypto_sign) -int crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) -int crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/params.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/params.h deleted file mode 100644 index c9502e4a8b..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/params.h +++ /dev/null @@ -1,56 +0,0 @@ -#ifndef SPX_PARAMS_H -#define SPX_PARAMS_H - -#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_##s - -/* Hash output length in bytes. */ -#define SPX_N 16 -/* Height of the hypertree. */ -#define SPX_FULL_HEIGHT 66 -/* Number of subtree layer. */ -#define SPX_D 22 -/* FORS tree dimensions. */ -#define SPX_FORS_HEIGHT 6 -#define SPX_FORS_TREES 33 -/* Winternitz parameter, */ -#define SPX_WOTS_W 16 - -/* The hash function is defined by linking a different hash.c file, as opposed - to setting a #define constant. */ - -/* For clarity */ -#define SPX_ADDR_BYTES 32 - -/* WOTS parameters. */ -#define SPX_WOTS_LOGW 4 - -#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) - -/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#define SPX_WOTS_LEN2 3 - -#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) -#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) -#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES - -/* Subtree size. */ -#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) - -//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT -// #error SPX_D should always divide SPX_FULL_HEIGHT -//#endif - -/* FORS parameters. */ -#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) -#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) -#define SPX_FORS_PK_BYTES SPX_N - -/* Resulting SPX sizes. */ -#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ - SPX_FULL_HEIGHT * SPX_N) -#define SPX_PK_BYTES (2 * SPX_N) -#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) - -#include "haraka_offsets.h" - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/sign.c b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/sign.c deleted file mode 100644 index 9d0c7d1b22..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/sign.c +++ /dev/null @@ -1,286 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "context.h" -#include "fors.h" -#include "hash.h" -#include "merkle.h" -#include "nistapi.h" -#include "params.h" -#include "randombytes.h" -#include "thash.h" -#include "utils.h" -#include "wots.h" - -/* - * Returns the length of a secret key, in bytes - */ -size_t crypto_sign_secretkeybytes(void) { - return CRYPTO_SECRETKEYBYTES; -} - -/* - * Returns the length of a public key, in bytes - */ -size_t crypto_sign_publickeybytes(void) { - return CRYPTO_PUBLICKEYBYTES; -} - -/* - * Returns the length of a signature, in bytes - */ -size_t crypto_sign_bytes(void) { - return CRYPTO_BYTES; -} - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t crypto_sign_seedbytes(void) { - return CRYPTO_SEEDBYTES; -} - -/* - * Generates an SPX key pair given a seed of length - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed) { - spx_ctx ctx; - - /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ - memcpy(sk, seed, CRYPTO_SEEDBYTES); - - memcpy(pk, sk + 2 * SPX_N, SPX_N); - - memcpy(ctx.pub_seed, pk, SPX_N); - memcpy(ctx.sk_seed, sk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - /* Compute root node of the top-most subtree. */ - merkle_gen_root(sk + 3 * SPX_N, &ctx); - - // cleanup - free_hash_function(&ctx); - - memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); - - return 0; -} - -/* - * Generates an SPX key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { - uint8_t seed[CRYPTO_SEEDBYTES]; - randombytes(seed, CRYPTO_SEEDBYTES); - crypto_sign_seed_keypair(pk, sk, seed); - - return 0; -} - -/** - * Returns an array containing a detached signature. - */ -int crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - spx_ctx ctx; - - const uint8_t *sk_prf = sk + SPX_N; - const uint8_t *pk = sk + 2 * SPX_N; - - uint8_t optrand[SPX_N]; - uint8_t mhash[SPX_FORS_MSG_BYTES]; - uint8_t root[SPX_N]; - uint32_t i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - - memcpy(ctx.sk_seed, sk, SPX_N); - memcpy(ctx.pub_seed, pk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - set_type(wots_addr, SPX_ADDR_TYPE_WOTS); - set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); - - /* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ - randombytes(optrand, SPX_N); - /* Compute the digest randomization value. */ - gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); - - /* Derive the message digest and leaf index from R, PK and M. */ - hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); - sig += SPX_N; - - set_tree_addr(wots_addr, tree); - set_keypair_addr(wots_addr, idx_leaf); - - /* Sign the message hash using FORS. */ - fors_sign(sig, root, mhash, &ctx, wots_addr); - sig += SPX_FORS_BYTES; - - for (i = 0; i < SPX_D; i++) { - set_layer_addr(tree_addr, i); - set_tree_addr(tree_addr, tree); - - copy_subtree_addr(wots_addr, tree_addr); - set_keypair_addr(wots_addr, idx_leaf); - - merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); - sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); - tree = tree >> SPX_TREE_HEIGHT; - } - - free_hash_function(&ctx); - - *siglen = SPX_BYTES; - - return 0; -} - -/** - * Verifies a detached signature and message under a given public key. - */ -int crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk) { - spx_ctx ctx; - const uint8_t *pub_root = pk + SPX_N; - uint8_t mhash[SPX_FORS_MSG_BYTES]; - uint8_t wots_pk[SPX_WOTS_BYTES]; - uint8_t root[SPX_N]; - uint8_t leaf[SPX_N]; - unsigned int i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - if (siglen != SPX_BYTES) { - return -1; - } - - memcpy(ctx.pub_seed, pk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - set_type(wots_addr, SPX_ADDR_TYPE_WOTS); - set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); - set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); - - /* Derive the message digest and leaf index from R || PK || M. */ - /* The additional SPX_N is a result of the hash domain separator. */ - hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); - sig += SPX_N; - - /* Layer correctly defaults to 0, so no need to set_layer_addr */ - set_tree_addr(wots_addr, tree); - set_keypair_addr(wots_addr, idx_leaf); - - fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); - sig += SPX_FORS_BYTES; - - /* For each subtree.. */ - for (i = 0; i < SPX_D; i++) { - set_layer_addr(tree_addr, i); - set_tree_addr(tree_addr, tree); - - copy_subtree_addr(wots_addr, tree_addr); - set_keypair_addr(wots_addr, idx_leaf); - - copy_keypair_addr(wots_pk_addr, wots_addr); - - /* The WOTS public key is only correct if the signature was correct. */ - /* Initially, root is the FORS pk, but on subsequent iterations it is - the root of the subtree below the currently processed subtree. */ - wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); - sig += SPX_WOTS_BYTES; - - /* Compute the leaf node using the WOTS public key. */ - thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); - - /* Compute the root node of this subtree. */ - compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, - &ctx, tree_addr); - sig += SPX_TREE_HEIGHT * SPX_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); - tree = tree >> SPX_TREE_HEIGHT; - } - - // cleanup - free_hash_function(&ctx); - - /* Check if the root node equals the root node in the public key. */ - if (memcmp(root, pub_root, SPX_N) != 0) { - return -1; - } - - return 0; -} - - -/** - * Returns an array containing the signature followed by the message. - */ -int crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk) { - size_t siglen; - - crypto_sign_signature(sm, &siglen, m, mlen, sk); - - memmove(sm + SPX_BYTES, m, mlen); - *smlen = siglen + mlen; - - return 0; -} - -/** - * Verifies a given signature-message pair under a given public key. - */ -int crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk) { - /* The API caller does not necessarily know what size a signature should be - but SPHINCS+ signatures are always exactly SPX_BYTES. */ - if (smlen < SPX_BYTES) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - *mlen = smlen - SPX_BYTES; - - if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - /* If verification was successful, move the message to the right place. */ - memmove(m, sm + SPX_BYTES, *mlen); - - return 0; -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/thash.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/thash.h deleted file mode 100644 index 8687ccfb4d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/thash.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef SPX_THASH_H -#define SPX_THASH_H - -#include "context.h" -#include "params.h" - -#include - -#define thash SPX_NAMESPACE(thash) -void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/thash_haraka_simple.c b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/thash_haraka_simple.c deleted file mode 100644 index 207777bf8d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/thash_haraka_simple.c +++ /dev/null @@ -1,36 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "thash.h" -#include "utils.h" - -#include "haraka.h" - -/** - * Takes an array of inblocks concatenated arrays of SPX_N bytes. - */ -void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]) { - PQCLEAN_VLA(uint8_t, buf, SPX_ADDR_BYTES + inblocks * SPX_N); - unsigned char outbuf[32]; - unsigned char buf_tmp[64]; - - if (inblocks == 1) { - /* F function */ - /* Since SPX_N may be smaller than 32, we need a temporary buffer. */ - memset(buf_tmp, 0, 64); - memcpy(buf_tmp, addr, 32); - memcpy(buf_tmp + SPX_ADDR_BYTES, in, SPX_N); - - haraka512(outbuf, buf_tmp, ctx); - memcpy(out, outbuf, SPX_N); - } else { - /* All other tweakable hashes*/ - memcpy(buf, addr, 32); - memcpy(buf + SPX_ADDR_BYTES, in, inblocks * SPX_N); - - haraka_S(out, SPX_N, buf, SPX_ADDR_BYTES + inblocks * SPX_N, ctx); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/thash_haraka_simplex4.c b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/thash_haraka_simplex4.c deleted file mode 100644 index 2ee763d7d9..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/thash_haraka_simplex4.c +++ /dev/null @@ -1,67 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "thashx4.h" - -#include "harakax4.h" - -#include "utils.h" - -/** - * 4-way parallel version of thash; takes 4x as much input and output - */ -#define thashx4 SPX_NAMESPACE(thashx4) -void thashx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addrx4[4 * 8]) { - PQCLEAN_VLA(unsigned char, buf0, SPX_ADDR_BYTES + inblocks * SPX_N); - PQCLEAN_VLA(unsigned char, buf1, SPX_ADDR_BYTES + inblocks * SPX_N); - PQCLEAN_VLA(unsigned char, buf2, SPX_ADDR_BYTES + inblocks * SPX_N); - PQCLEAN_VLA(unsigned char, buf3, SPX_ADDR_BYTES + inblocks * SPX_N); - unsigned char outbuf[32 * 4]; - unsigned char buf_tmp[64 * 4]; - - if (inblocks == 1) { - memset(buf_tmp, 0, 64 * 4); - - memcpy(buf_tmp, addrx4 + 0 * 8, 32); - memcpy(buf_tmp + 64, addrx4 + 1 * 8, 32); - memcpy(buf_tmp + 128, addrx4 + 2 * 8, 32); - memcpy(buf_tmp + 192, addrx4 + 3 * 8, 32); - - memcpy(buf_tmp + SPX_ADDR_BYTES, in0, SPX_N); - memcpy(buf_tmp + SPX_ADDR_BYTES + 64, in1, SPX_N); - memcpy(buf_tmp + SPX_ADDR_BYTES + 128, in2, SPX_N); - memcpy(buf_tmp + SPX_ADDR_BYTES + 192, in3, SPX_N); - - haraka512x4(outbuf, buf_tmp, ctx); - - memcpy(out0, outbuf, SPX_N); - memcpy(out1, outbuf + 32, SPX_N); - memcpy(out2, outbuf + 64, SPX_N); - memcpy(out3, outbuf + 96, SPX_N); - } else { - /* All other tweakable hashes*/ - memcpy(buf0, addrx4 + 0 * 8, 32); - memcpy(buf1, addrx4 + 1 * 8, 32); - memcpy(buf2, addrx4 + 2 * 8, 32); - memcpy(buf3, addrx4 + 3 * 8, 32); - - memcpy(buf0 + SPX_ADDR_BYTES, in0, inblocks * SPX_N); - memcpy(buf1 + SPX_ADDR_BYTES, in1, inblocks * SPX_N); - memcpy(buf2 + SPX_ADDR_BYTES, in2, inblocks * SPX_N); - memcpy(buf3 + SPX_ADDR_BYTES, in3, inblocks * SPX_N); - - haraka_Sx4(out0, out1, out2, out3, SPX_N, - buf0, buf1, buf2, buf3, SPX_ADDR_BYTES + inblocks * SPX_N, - ctx); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/thashx4.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/thashx4.h deleted file mode 100644 index 64798a3727..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/thashx4.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef SPX_THASHX4_H -#define SPX_THASHX4_H - -#include - -#include "context.h" -#include "params.h" - -#define thashx4 SPX_NAMESPACE(thashx4) -void thashx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addrx4[4 * 8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/utils.c b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/utils.c deleted file mode 100644 index 177b541fb9..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/utils.c +++ /dev/null @@ -1,148 +0,0 @@ -#include - -#include "utils.h" - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "thash.h" - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void ull_to_bytes(unsigned char *out, unsigned int outlen, - unsigned long long in) { - int i; - - /* Iterate over out in decreasing order, for big-endianness. */ - for (i = (signed int)outlen - 1; i >= 0; i--) { - out[i] = in & 0xff; - in = in >> 8; - } -} - -void u32_to_bytes(unsigned char *out, uint32_t in) { - out[0] = (unsigned char)(in >> 24); - out[1] = (unsigned char)(in >> 16); - out[2] = (unsigned char)(in >> 8); - out[3] = (unsigned char)in; -} - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { - unsigned long long retval = 0; - unsigned int i; - - for (i = 0; i < inlen; i++) { - retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); - } - return retval; -} - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void compute_root(unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const spx_ctx *ctx, uint32_t addr[8]) { - uint32_t i; - unsigned char buffer[2 * SPX_N]; - - /* If leaf_idx is odd (last bit = 1), current path element is a right child - and auth_path has to go left. Otherwise it is the other way around. */ - if (leaf_idx & 1) { - memcpy(buffer + SPX_N, leaf, SPX_N); - memcpy(buffer, auth_path, SPX_N); - } else { - memcpy(buffer, leaf, SPX_N); - memcpy(buffer + SPX_N, auth_path, SPX_N); - } - auth_path += SPX_N; - - for (i = 0; i < tree_height - 1; i++) { - leaf_idx >>= 1; - idx_offset >>= 1; - /* Set the address of the node we're creating. */ - set_tree_height(addr, i + 1); - set_tree_index(addr, leaf_idx + idx_offset); - - /* Pick the right or left neighbor, depending on parity of the node. */ - if (leaf_idx & 1) { - thash(buffer + SPX_N, buffer, 2, ctx, addr); - memcpy(buffer, auth_path, SPX_N); - } else { - thash(buffer, buffer, 2, ctx, addr); - memcpy(buffer + SPX_N, auth_path, SPX_N); - } - auth_path += SPX_N; - } - - /* The last iteration is exceptional; we do not copy an auth_path node. */ - leaf_idx >>= 1; - idx_offset >>= 1; - set_tree_height(addr, tree_height); - set_tree_index(addr, leaf_idx + idx_offset); - thash(root, buffer, 2, ctx, addr); -} - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const spx_ctx * /* ctx */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), - uint32_t tree_addr[8]) { - PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); - PQCLEAN_VLA(unsigned int, heights, tree_height + 1); - unsigned int offset = 0; - uint32_t idx; - uint32_t tree_idx; - - for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { - /* Add the next leaf node to the stack. */ - gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); - offset++; - heights[offset - 1] = 0; - - /* If this is a node we need for the auth path.. */ - if ((leaf_idx ^ 0x1) == idx) { - memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); - } - - /* While the top-most nodes are of equal height.. */ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { - /* Compute index of the new node, in the next layer. */ - tree_idx = (idx >> (heights[offset - 1] + 1)); - - /* Set the address of the node we're creating. */ - set_tree_height(tree_addr, heights[offset - 1] + 1); - set_tree_index(tree_addr, - tree_idx + (idx_offset >> (heights[offset - 1] + 1))); - /* Hash the top-most nodes from the stack together. */ - thash(stack + (offset - 2)*SPX_N, - stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); - offset--; - /* Note that the top-most node is now one layer higher. */ - heights[offset - 1]++; - - /* If this is a node we need for the auth path.. */ - if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_path + heights[offset - 1]*SPX_N, - stack + (offset - 1)*SPX_N, SPX_N); - } - } - } - memcpy(root, stack, SPX_N); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/utils.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/utils.h deleted file mode 100644 index 64f5d5a53a..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/utils.h +++ /dev/null @@ -1,58 +0,0 @@ -#ifndef SPX_UTILS_H -#define SPX_UTILS_H - -#include - -#include "compat.h" -#include "context.h" -#include "params.h" - - -/* To support MSVC use alloca() instead of VLAs. See #20. */ - - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) -void ull_to_bytes(unsigned char *out, unsigned int outlen, - unsigned long long in); -#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) -void u32_to_bytes(unsigned char *out, uint32_t in); - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) -unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -#define compute_root SPX_NAMESPACE(compute_root) -void compute_root(unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const spx_ctx *ctx, uint32_t addr[8]); - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -#define treehash SPX_NAMESPACE(treehash) -void treehash(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const spx_ctx *ctx /* ctx */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), - uint32_t tree_addr[8]); - - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/utilsx4.c b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/utilsx4.c deleted file mode 100644 index 1638677194..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/utilsx4.c +++ /dev/null @@ -1,138 +0,0 @@ -#include - -#include "utilsx4.h" - -#include "address.h" -#include "params.h" -#include "thashx4.h" -#include "utils.h" - -/* - * Generate the entire Merkle tree, computing the authentication path for leaf_idx, - * and the resulting root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) - * - * This expects tree_addrx4 to be initialized to 4 parallel addr structures for - * the Merkle tree nodes - * - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - * - * This works by using the standard Merkle tree building algorithm, except - * that each 'node' tracked is actually 4 consecutive nodes in the real tree. - * When we combine two logical nodes ABCD and WXYZ, we perform the H - * operation on adjacent real nodes, forming the parent logical node - * (AB)(CD)(WX)(YZ) - * - * When we get to the top two levels of the real tree (where there is only - * one logical node), we continue this operation two more times; the right - * most real node will by the actual root (and the other 3 nodes will be - * garbage). We follow the same thashx4 logic so that the 'extract - * authentication path components' part of the loop is still executed (and - * to simplify the code somewhat) - * - * This currently assumes tree_height >= 2; I suspect that doing an adjusting - * idx, addr_idx on the gen_leafx4 call if tree_height < 2 would fix it; since - * we don't actually use such short trees, I haven't bothered - */ -void treehashx4(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, - uint32_t tree_height, - void (*gen_leafx4)( - unsigned char * /* Where to write the leaves */, - const spx_ctx *, - uint32_t idx, void *info), - uint32_t tree_addrx4[4 * 8], - void *info) { - /* This is where we keep the intermediate nodes */ - PQCLEAN_VLA(unsigned char, stackx4, tree_height * 4 * SPX_N); - uint32_t left_adj = 0, prev_left_adj = 0; /* When we're doing the top 3 */ - /* levels, the left-most part of the tree isn't at the beginning */ - /* of current[]. These give the offset of the actual start */ - - uint32_t idx; - uint32_t max_idx = (1U << (tree_height - 2)) - 1; - for (idx = 0;; idx++) { - unsigned char current[4 * SPX_N]; /* Current logical node */ - gen_leafx4( current, ctx, 4 * idx + idx_offset, - info ); - - /* Now combine the freshly generated right node with previously */ - /* generated left ones */ - uint32_t internal_idx_offset = idx_offset; - uint32_t internal_idx = idx; - uint32_t internal_leaf = leaf_idx; - uint32_t h; /* The height we are in the Merkle tree */ - for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { - - /* Special processing if we're at the top of the tree */ - if (h >= tree_height - 2) { - if (h == tree_height) { - /* We hit the root; return it */ - memcpy( root, ¤t[3 * SPX_N], SPX_N ); - return; - } - /* The tree indexing logic is a bit off in this case */ - /* Adjust it so that the left-most node of the part of */ - /* the tree that we're processing has index 0 */ - prev_left_adj = left_adj; - left_adj = 4U - (1 << (tree_height - h - 1)); - } - - /* Check if we hit the top of the tree */ - if (h == tree_height) { - /* We hit the root; return it */ - memcpy( root, ¤t[3 * SPX_N], SPX_N ); - return; - } - - /* - * Check if one of the nodes we have is a part of the - * authentication path; if it is, write it out - */ - if ((((internal_idx << 2) ^ internal_leaf) & ~0x3U) == 0) { - memcpy( &auth_path[ h * SPX_N ], - ¤t[(((internal_leaf & 3) ^ 1) + prev_left_adj) * SPX_N], - SPX_N ); - } - - /* - * Check if we're at a left child; if so, stop going up the stack - * Exception: if we've reached the end of the tree, keep on going - * (so we combine the last 4 nodes into the one root node in two - * more iterations) - */ - if ((internal_idx & 1) == 0 && idx < max_idx) { - break; - } - - /* Ok, we're at a right node (or doing the top 3 levels) */ - /* Now combine the left and right logical nodes together */ - - /* Set the address of the node we're creating. */ - unsigned int j; - internal_idx_offset >>= 1; - for (j = 0; j < 4; j++) { - set_tree_height(tree_addrx4 + j * 8, h + 1); - set_tree_index(tree_addrx4 + j * 8, - (4 / 2) * (internal_idx & ~1U) + j - left_adj + internal_idx_offset ); - } - unsigned char *left = &stackx4[h * 4 * SPX_N]; - thashx4( ¤t[0 * SPX_N], - ¤t[1 * SPX_N], - ¤t[2 * SPX_N], - ¤t[3 * SPX_N], - &left [0 * SPX_N], - &left [2 * SPX_N], - ¤t[0 * SPX_N], - ¤t[2 * SPX_N], - 2, ctx, tree_addrx4); - } - - /* We've hit a left child; save the current for when we get the */ - /* corresponding right right */ - memcpy( &stackx4[h * 4 * SPX_N], current, 4 * SPX_N); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/utilsx4.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/utilsx4.h deleted file mode 100644 index facb874b18..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/utilsx4.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef SPX_UTILSX4_H -#define SPX_UTILSX4_H - -#include - -#include "context.h" -#include "params.h" - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - * - * This implementation uses AVX to compute internal nodes 4 at a time (in - * parallel) - */ -#define treehashx4 SPX_NAMESPACE(treehashx4) -void treehashx4(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leafx4)( - unsigned char * /* Where to write the leaves */, - const spx_ctx * /* ctx */, - uint32_t addr_idx, void *info), - uint32_t tree_addrx4[4 * 8], void *info); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/wots.c b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/wots.c deleted file mode 100644 index 4d5041ce05..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/wots.c +++ /dev/null @@ -1,269 +0,0 @@ -#include -#include - -#include "wots.h" - -#include "address.h" -#include "hash.h" -#include "hashx4.h" -#include "params.h" -#include "thash.h" -#include "thashx4.h" -#include "utils.h" -#include "utilsx4.h" -#include "wotsx4.h" - -// TODO clarify address expectations, and make them more uniform. -// TODO i.e. do we expect types to be set already? -// TODO and do we expect modifications or copies? - -/** - * Computes up the chains - */ -static void gen_chains( - unsigned char *out, - const unsigned char *in, - unsigned int start[SPX_WOTS_LEN], - const unsigned int steps[SPX_WOTS_LEN], - const spx_ctx *ctx, - uint32_t addr[8]) { - uint32_t i, j, k, idx, watching; - int done; - unsigned char empty[SPX_N]; - unsigned char *bufs[4]; - uint32_t addrs[8 * 4]; - - int l; - uint16_t counts[SPX_WOTS_W] = { 0 }; - uint16_t idxs[SPX_WOTS_LEN]; - uint16_t total, newTotal; - - /* set addrs = {addr, addr, addr, addr} */ - for (j = 0; j < 4; j++) { - memcpy(addrs + j * 8, addr, sizeof(uint32_t) * 8); - } - - /* Initialize out with the value at position 'start'. */ - memcpy(out, in, SPX_WOTS_LEN * SPX_N); - - /* Sort the chains in reverse order by steps using counting sort. */ - for (i = 0; i < SPX_WOTS_LEN; i++) { - counts[steps[i]]++; - } - total = 0; - for (l = SPX_WOTS_W - 1; l >= 0; l--) { - newTotal = counts[l] + total; - counts[l] = total; - total = newTotal; - } - for (i = 0; i < SPX_WOTS_LEN; i++) { - idxs[counts[steps[i]]] = (uint16_t)i; - counts[steps[i]]++; - } - - /* We got our work cut out for us: do it! */ - for (i = 0; i < SPX_WOTS_LEN; i += 4) { - for (j = 0; j < 4 && i + j < SPX_WOTS_LEN; j++) { - idx = idxs[i + j]; - set_chain_addr(addrs + j * 8, idx); - bufs[j] = out + SPX_N * idx; - } - - /* As the chains are sorted in reverse order, we know that the first - * chain is the longest and the last one is the shortest. We keep - * an eye on whether the last chain is done and then on the one before, - * et cetera. */ - watching = 3; - done = 0; - while (i + watching >= SPX_WOTS_LEN) { - bufs[watching] = &empty[0]; - watching--; - } - - for (k = 0;; k++) { - while (k == steps[idxs[i + watching]]) { - bufs[watching] = &empty[0]; - if (watching == 0) { - done = 1; - break; - } - watching--; - } - if (done) { - break; - } - for (j = 0; j < watching + 1; j++) { - set_hash_addr(addrs + j * 8, k + start[idxs[i + j]]); - } - - thashx4(bufs[0], bufs[1], bufs[2], bufs[3], - bufs[0], bufs[1], bufs[2], bufs[3], 1, ctx, addrs); - } - } -} - -/** - * base_w algorithm as described in draft. - * Interprets an array of bytes as integers in base w. - * This only works when log_w is a divisor of 8. - */ -static void base_w(unsigned int *output, const int out_len, - const unsigned char *input) { - int in = 0; - int out = 0; - unsigned char total = 0; - int bits = 0; - int consumed; - - for (consumed = 0; consumed < out_len; consumed++) { - if (bits == 0) { - total = input[in]; - in++; - bits += 8; - } - bits -= SPX_WOTS_LOGW; - output[out] = (total >> bits) & (SPX_WOTS_W - 1); - out++; - } -} - -/* Computes the WOTS+ checksum over a message (in base_w). */ -static void wots_checksum(unsigned int *csum_base_w, - const unsigned int *msg_base_w) { - unsigned int csum = 0; - unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; - unsigned int i; - - /* Compute checksum. */ - for (i = 0; i < SPX_WOTS_LEN1; i++) { - csum += SPX_WOTS_W - 1 - msg_base_w[i]; - } - - /* Convert checksum to base_w. */ - /* Make sure expected empty zero bits are the least significant bits. */ - csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); - ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); - base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); -} - -/* Takes a message and derives the matching chain lengths. */ -void chain_lengths(unsigned int *lengths, const unsigned char *msg) { - base_w(lengths, SPX_WOTS_LEN1, msg); - wots_checksum(lengths + SPX_WOTS_LEN1, lengths); -} - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const spx_ctx *ctx, uint32_t addr[8]) { - unsigned int steps[SPX_WOTS_LEN]; - unsigned int start[SPX_WOTS_LEN]; - uint32_t i; - - chain_lengths(start, msg); - - for (i = 0; i < SPX_WOTS_LEN; i++) { - steps[i] = SPX_WOTS_W - 1 - start[i]; - } - - gen_chains(pk, sig, start, steps, ctx, addr); -} - -/* - * This generates 4 sequential WOTS public keys - * It also generates the WOTS signature if leaf_info indicates - * that we're signing with one of these WOTS keys - */ -void wots_gen_leafx4(unsigned char *dest, - const spx_ctx *ctx, - uint32_t leaf_idx, void *v_info) { - struct leaf_info_x4 *info = v_info; - uint32_t *leaf_addr = info->leaf_addr; - uint32_t *pk_addr = info->pk_addr; - unsigned int i, j, k; - unsigned char pk_buffer[ 4 * SPX_WOTS_BYTES ]; - unsigned wots_offset = SPX_WOTS_BYTES; - unsigned char *buffer; - uint32_t wots_k_mask; - unsigned wots_sign_index; - - if (((leaf_idx ^ info->wots_sign_leaf) & ~3U) == 0) { - /* We're traversing the leaf that's signing; generate the WOTS */ - /* signature */ - wots_k_mask = 0; - wots_sign_index = info->wots_sign_leaf & 3; /* Which of of the 4 */ - /* 4 slots do the signatures come from */ - } else { - /* Nope, we're just generating pk's; turn off the signature logic */ - wots_k_mask = (uint32_t)~0; - wots_sign_index = 0; - } - - for (j = 0; j < 4; j++) { - set_keypair_addr( leaf_addr + j * 8, leaf_idx + j ); - set_keypair_addr( pk_addr + j * 8, leaf_idx + j ); - } - - for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { - uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k to */ - /* the step if we're generating a signature, ~0 if we're not */ - - /* Start with the secret seed */ - for (j = 0; j < 4; j++) { - set_chain_addr(leaf_addr + j * 8, i); - set_hash_addr(leaf_addr + j * 8, 0); - set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTSPRF); - } - prf_addrx4(buffer + 0 * wots_offset, - buffer + 1 * wots_offset, - buffer + 2 * wots_offset, - buffer + 3 * wots_offset, - ctx, leaf_addr); - - for (j = 0; j < 4; j++) { - set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTS); - } - - /* Iterate down the WOTS chain */ - for (k = 0;; k++) { - /* Check if one of the values we have needs to be saved as a */ - /* part of the WOTS signature */ - if (k == wots_k) { - memcpy( info->wots_sig + i * SPX_N, - buffer + wots_sign_index * wots_offset, SPX_N ); - } - - /* Check if we hit the top of the chain */ - if (k == SPX_WOTS_W - 1) { - break; - } - - /* Iterate one step on all 4 chains */ - for (j = 0; j < 4; j++) { - set_hash_addr(leaf_addr + j * 8, k); - } - thashx4(buffer + 0 * wots_offset, - buffer + 1 * wots_offset, - buffer + 2 * wots_offset, - buffer + 3 * wots_offset, - buffer + 0 * wots_offset, - buffer + 1 * wots_offset, - buffer + 2 * wots_offset, - buffer + 3 * wots_offset, 1, ctx, leaf_addr); - } - } - - /* Do the final thash to generate the public keys */ - thashx4(dest + 0 * SPX_N, - dest + 1 * SPX_N, - dest + 2 * SPX_N, - dest + 3 * SPX_N, - pk_buffer + 0 * wots_offset, - pk_buffer + 1 * wots_offset, - pk_buffer + 2 * wots_offset, - pk_buffer + 3 * wots_offset, SPX_WOTS_LEN, ctx, pk_addr); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/wots.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/wots.h deleted file mode 100644 index 4e7692eeef..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/wots.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef SPX_WOTS_H -#define SPX_WOTS_H - -#include - -#include "context.h" -#include "params.h" - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) -void wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const spx_ctx *ctx, uint32_t addr[8]); - -/* - * Compute the chain lengths needed for a given message hash - */ -#define chain_lengths SPX_NAMESPACE(chain_lengths) -void chain_lengths(unsigned int *lengths, const unsigned char *msg); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/wotsx4.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/wotsx4.h deleted file mode 100644 index cd634f1743..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_aesni/wotsx4.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef WOTSX4_H_ -#define WOTSX4_H_ - -#include - -#include "params.h" - -/* - * This is here to provide an interface to the internal wots_gen_leafx4 - * routine. While this routine is not referenced in the package outside of - * wots.c, it is called from the stand-alone benchmark code to characterize - * the performance - */ -struct leaf_info_x4 { - unsigned char *wots_sig; - uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ - uint32_t *wots_steps; - uint32_t leaf_addr[4 * 8]; - uint32_t pk_addr[4 * 8]; -}; - -/* Macro to set the leaf_info to something 'benign', that is, it would */ -/* run with the same time as it does during the real signing process */ -/* Used only by the benchmark code */ -#define INITIALIZE_LEAF_INFO_X4(info, addr, step_buffer) { \ - (info).wots_sig = 0; \ - (info).wots_sign_leaf = ~0; \ - (info).wots_steps = step_buffer; \ - int i; \ - for (i=0; i<4; i++) { \ - memcpy( &(info).leaf_addr[8*i], addr, 32 ); \ - memcpy( &(info).pk_addr[8*i], addr, 32 ); \ - } \ - } - -#define wots_gen_leafx4 SPX_NAMESPACE(wots_gen_leafx4) -void wots_gen_leafx4(unsigned char *dest, - const spx_ctx *ctx, - uint32_t leaf_idx, void *v_info); - -#endif /* WOTSX4_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/LICENSE b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/LICENSE deleted file mode 100644 index 670154e353..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/LICENSE +++ /dev/null @@ -1,116 +0,0 @@ -CC0 1.0 Universal - -Statement of Purpose - -The laws of most jurisdictions throughout the world automatically confer -exclusive Copyright and Related Rights (defined below) upon the creator and -subsequent owner(s) (each and all, an "owner") of an original work of -authorship and/or a database (each, a "Work"). - -Certain owners wish to permanently relinquish those rights to a Work for the -purpose of contributing to a commons of creative, cultural and scientific -works ("Commons") that the public can reliably and without fear of later -claims of infringement build upon, modify, incorporate in other works, reuse -and redistribute as freely as possible in any form whatsoever and for any -purposes, including without limitation commercial purposes. These owners may -contribute to the Commons to promote the ideal of a free culture and the -further production of creative, cultural and scientific works, or to gain -reputation or greater distribution for their Work in part through the use and -efforts of others. - -For these and/or other purposes and motivations, and without any expectation -of additional consideration or compensation, the person associating CC0 with a -Work (the "Affirmer"), to the extent that he or she is an owner of Copyright -and Related Rights in the Work, voluntarily elects to apply CC0 to the Work -and publicly distribute the Work under its terms, with knowledge of his or her -Copyright and Related Rights in the Work and the meaning and intended legal -effect of CC0 on those rights. - -1. Copyright and Related Rights. A Work made available under CC0 may be -protected by copyright and related or neighboring rights ("Copyright and -Related Rights"). Copyright and Related Rights include, but are not limited -to, the following: - - i. the right to reproduce, adapt, distribute, perform, display, communicate, - and translate a Work; - - ii. moral rights retained by the original author(s) and/or performer(s); - - iii. publicity and privacy rights pertaining to a person's image or likeness - depicted in a Work; - - iv. rights protecting against unfair competition in regards to a Work, - subject to the limitations in paragraph 4(a), below; - - v. rights protecting the extraction, dissemination, use and reuse of data in - a Work; - - vi. database rights (such as those arising under Directive 96/9/EC of the - European Parliament and of the Council of 11 March 1996 on the legal - protection of databases, and under any national implementation thereof, - including any amended or successor version of such directive); and - - vii. other similar, equivalent or corresponding rights throughout the world - based on applicable law or treaty, and any national implementations thereof. - -2. Waiver. To the greatest extent permitted by, but not in contravention of, -applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and -unconditionally waives, abandons, and surrenders all of Affirmer's Copyright -and Related Rights and associated claims and causes of action, whether now -known or unknown (including existing as well as future claims and causes of -action), in the Work (i) in all territories worldwide, (ii) for the maximum -duration provided by applicable law or treaty (including future time -extensions), (iii) in any current or future medium and for any number of -copies, and (iv) for any purpose whatsoever, including without limitation -commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes -the Waiver for the benefit of each member of the public at large and to the -detriment of Affirmer's heirs and successors, fully intending that such Waiver -shall not be subject to revocation, rescission, cancellation, termination, or -any other legal or equitable action to disrupt the quiet enjoyment of the Work -by the public as contemplated by Affirmer's express Statement of Purpose. - -3. Public License Fallback. Should any part of the Waiver for any reason be -judged legally invalid or ineffective under applicable law, then the Waiver -shall be preserved to the maximum extent permitted taking into account -Affirmer's express Statement of Purpose. In addition, to the extent the Waiver -is so judged Affirmer hereby grants to each affected person a royalty-free, -non transferable, non sublicensable, non exclusive, irrevocable and -unconditional license to exercise Affirmer's Copyright and Related Rights in -the Work (i) in all territories worldwide, (ii) for the maximum duration -provided by applicable law or treaty (including future time extensions), (iii) -in any current or future medium and for any number of copies, and (iv) for any -purpose whatsoever, including without limitation commercial, advertising or -promotional purposes (the "License"). The License shall be deemed effective as -of the date CC0 was applied by Affirmer to the Work. Should any part of the -License for any reason be judged legally invalid or ineffective under -applicable law, such partial invalidity or ineffectiveness shall not -invalidate the remainder of the License, and in such case Affirmer hereby -affirms that he or she will not (i) exercise any of his or her remaining -Copyright and Related Rights in the Work or (ii) assert any associated claims -and causes of action with respect to the Work, in either case contrary to -Affirmer's express Statement of Purpose. - -4. Limitations and Disclaimers. - - a. No trademark or patent rights held by Affirmer are waived, abandoned, - surrendered, licensed or otherwise affected by this document. - - b. Affirmer offers the Work as-is and makes no representations or warranties - of any kind concerning the Work, express, implied, statutory or otherwise, - including without limitation warranties of title, merchantability, fitness - for a particular purpose, non infringement, or the absence of latent or - other defects, accuracy, or the present or absence of errors, whether or not - discoverable, all to the greatest extent permissible under applicable law. - - c. Affirmer disclaims responsibility for clearing rights of other persons - that may apply to the Work or any use thereof, including without limitation - any person's Copyright and Related Rights in the Work. Further, Affirmer - disclaims responsibility for obtaining any necessary consents, permissions - or other rights required for any use of the Work. - - d. Affirmer understands and acknowledges that Creative Commons is not a - party to this document and has no duty or obligation with respect to this - CC0 or use of the Work. - -For more information, please see - diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/address.c b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/address.c deleted file mode 100644 index b956e9cb29..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/address.c +++ /dev/null @@ -1,91 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "utils.h" - -/* - * Specify which level of Merkle tree (the "layer") we're working on - */ -void set_layer_addr(uint32_t addr[8], uint32_t layer) { - ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; -} - -/* - * Specify which Merkle tree within the level (the "tree address") we're working on - */ -void set_tree_addr(uint32_t addr[8], uint64_t tree) { - ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); -} - -/* - * Specify the reason we'll use this address structure for, that is, what - * hash will we compute with it. This is used so that unrelated types of - * hashes don't accidentally get the same address structure. The type will be - * one of the SPX_ADDR_TYPE constants - */ -void set_type(uint32_t addr[8], uint32_t type) { - ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; -} - -/* - * Copy the layer and tree fields of the address structure. This is used - * when we're doing multiple types of hashes within the same Merkle tree - */ -void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { - memcpy( out, in, SPX_OFFSET_TREE + 8 ); -} - -/* These functions are used for OTS addresses. */ - -/* - * Specify which Merkle leaf we're working on; that is, which OTS keypair - * we're talking about. - */ -void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { - ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; -} - -/* - * Copy the layer, tree and keypair fields of the address structure. This is - * used when we're doing multiple things within the same OTS keypair - */ -void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { - memcpy( out, in, SPX_OFFSET_TREE + 8 ); - ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; -} - -/* - * Specify which Merkle chain within the OTS we're working with - * (the chain address) - */ -void set_chain_addr(uint32_t addr[8], uint32_t chain) { - ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; -} - -/* - * Specify where in the Merkle chain we are -* (the hash address) - */ -void set_hash_addr(uint32_t addr[8], uint32_t hash) { - ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; -} - -/* These functions are used for all hash tree addresses (including FORS). */ - -/* - * Specify the height of the node in the Merkle/FORS tree we are in - * (the tree height) - */ -void set_tree_height(uint32_t addr[8], uint32_t tree_height) { - ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; -} - -/* - * Specify the distance from the left edge of the node in the Merkle/FORS tree - * (the tree index) - */ -void set_tree_index(uint32_t addr[8], uint32_t tree_index) { - u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/address.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/address.h deleted file mode 100644 index 24a84eb40c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/address.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef SPX_ADDRESS_H -#define SPX_ADDRESS_H - -#include - -#include "params.h" - -/* The hash types that are passed to set_type */ -#define SPX_ADDR_TYPE_WOTS 0 -#define SPX_ADDR_TYPE_WOTSPK 1 -#define SPX_ADDR_TYPE_HASHTREE 2 -#define SPX_ADDR_TYPE_FORSTREE 3 -#define SPX_ADDR_TYPE_FORSPK 4 -#define SPX_ADDR_TYPE_WOTSPRF 5 -#define SPX_ADDR_TYPE_FORSPRF 6 - -#define set_layer_addr SPX_NAMESPACE(set_layer_addr) -void set_layer_addr(uint32_t addr[8], uint32_t layer); - -#define set_tree_addr SPX_NAMESPACE(set_tree_addr) -void set_tree_addr(uint32_t addr[8], uint64_t tree); - -#define set_type SPX_NAMESPACE(set_type) -void set_type(uint32_t addr[8], uint32_t type); - -/* Copies the layer and tree part of one address into the other */ -#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) -void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for WOTS and FORS addresses. */ - -#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) -void set_keypair_addr(uint32_t addr[8], uint32_t keypair); - -#define set_chain_addr SPX_NAMESPACE(set_chain_addr) -void set_chain_addr(uint32_t addr[8], uint32_t chain); - -#define set_hash_addr SPX_NAMESPACE(set_hash_addr) -void set_hash_addr(uint32_t addr[8], uint32_t hash); - -#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) -void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for all hash tree addresses (including FORS). */ - -#define set_tree_height SPX_NAMESPACE(set_tree_height) -void set_tree_height(uint32_t addr[8], uint32_t tree_height); - -#define set_tree_index SPX_NAMESPACE(set_tree_index) -void set_tree_index(uint32_t addr[8], uint32_t tree_index); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/api.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/api.h deleted file mode 100644 index 93bf33c9b3..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/api.h +++ /dev/null @@ -1,77 +0,0 @@ -#ifndef PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_API_H -#define PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_API_H - -#include -#include - -#define PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_CRYPTO_ALGNAME "SPHINCS+-haraka-128f-simple" - -#define PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_CRYPTO_SECRETKEYBYTES 64 -#define PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_CRYPTO_PUBLICKEYBYTES 32 -#define PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_CRYPTO_BYTES 17088 - -#define PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_CRYPTO_SEEDBYTES 48 - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, - const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk); -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/context.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/context.h deleted file mode 100644 index 600dfb73c7..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/context.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef SPX_CONTEXT_H -#define SPX_CONTEXT_H - -#include -#include - -#include "params.h" - -typedef struct { - uint8_t pub_seed[SPX_N]; - uint8_t sk_seed[SPX_N]; - - - uint64_t tweaked512_rc64[10][8]; - uint32_t tweaked256_rc32[10][8]; -} spx_ctx; - -#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) -void initialize_hash_function(spx_ctx *ctx); - -#define free_hash_function SPX_NAMESPACE(free_hash_function) -void free_hash_function(spx_ctx *ctx); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/context_haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/context_haraka.c deleted file mode 100644 index f1cd7e3664..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/context_haraka.c +++ /dev/null @@ -1,11 +0,0 @@ -#include "context.h" -#include "haraka.h" - -void initialize_hash_function(spx_ctx *ctx) { - tweak_constants(ctx); -} - -// we don't support heap-based haraka right now -void free_hash_function(spx_ctx *ctx) { - (void)ctx; // suppress unused variable warnings -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/fors.c b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/fors.c deleted file mode 100644 index 96ca72e986..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/fors.c +++ /dev/null @@ -1,156 +0,0 @@ -#include -#include -#include - -#include "fors.h" - -#include "address.h" -#include "hash.h" -#include "thash.h" -#include "utils.h" -#include "utilsx1.h" - -static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, - uint32_t fors_leaf_addr[8]) { - prf_addr(sk, ctx, fors_leaf_addr); -} - -static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, - const spx_ctx *ctx, - uint32_t fors_leaf_addr[8]) { - thash(leaf, sk, 1, ctx, fors_leaf_addr); -} - -struct fors_gen_leaf_info { - uint32_t leaf_addrx[8]; -}; - -static void fors_gen_leafx1(unsigned char *leaf, - const spx_ctx *ctx, - uint32_t addr_idx, void *info) { - struct fors_gen_leaf_info *fors_info = info; - uint32_t *fors_leaf_addr = fors_info->leaf_addrx; - - /* Only set the parts that the caller doesn't set */ - set_tree_index(fors_leaf_addr, addr_idx); - set_type(fors_leaf_addr, SPX_ADDR_TYPE_FORSPRF); - fors_gen_sk(leaf, ctx, fors_leaf_addr); - - set_type(fors_leaf_addr, SPX_ADDR_TYPE_FORSTREE); - fors_sk_to_leaf(leaf, leaf, - ctx, fors_leaf_addr); -} - -/** - * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - * Assumes indices has space for SPX_FORS_TREES integers. - */ -static void message_to_indices(uint32_t *indices, const unsigned char *m) { - unsigned int i, j; - unsigned int offset = 0; - - for (i = 0; i < SPX_FORS_TREES; i++) { - indices[i] = 0; - for (j = 0; j < SPX_FORS_HEIGHT; j++) { - indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); - offset++; - } - } -} - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -void fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]) { - uint32_t indices[SPX_FORS_TREES]; - unsigned char roots[SPX_FORS_TREES * SPX_N]; - uint32_t fors_tree_addr[8] = {0}; - struct fors_gen_leaf_info fors_info = {0}; - uint32_t *fors_leaf_addr = fors_info.leaf_addrx; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - copy_keypair_addr(fors_tree_addr, fors_addr); - copy_keypair_addr(fors_leaf_addr, fors_addr); - - copy_keypair_addr(fors_pk_addr, fors_addr); - set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < SPX_FORS_TREES; i++) { - idx_offset = i * (1 << SPX_FORS_HEIGHT); - - set_tree_height(fors_tree_addr, 0); - set_tree_index(fors_tree_addr, indices[i] + idx_offset); - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); - - /* Include the secret key part that produces the selected leaf node. */ - fors_gen_sk(sig, ctx, fors_tree_addr); - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); - sig += SPX_N; - - /* Compute the authentication path for this leaf node. */ - treehashx1(roots + i * SPX_N, sig, ctx, - indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx1, - fors_tree_addr, &fors_info); - - sig += SPX_N * SPX_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); -} - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -void fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]) { - uint32_t indices[SPX_FORS_TREES]; - unsigned char roots[SPX_FORS_TREES * SPX_N]; - unsigned char leaf[SPX_N]; - uint32_t fors_tree_addr[8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - copy_keypair_addr(fors_tree_addr, fors_addr); - copy_keypair_addr(fors_pk_addr, fors_addr); - - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); - set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < SPX_FORS_TREES; i++) { - idx_offset = i * (1 << SPX_FORS_HEIGHT); - - set_tree_height(fors_tree_addr, 0); - set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Derive the leaf from the included secret key part. */ - fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); - sig += SPX_N; - - /* Derive the corresponding root node of this tree. */ - compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, - sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); - sig += SPX_N * SPX_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/fors.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/fors.h deleted file mode 100644 index 509140a178..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/fors.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef SPX_FORS_H -#define SPX_FORS_H - -#include - -#include "context.h" -#include "params.h" - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -#define fors_sign SPX_NAMESPACE(fors_sign) -void fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]); - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) -void fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/haraka.c deleted file mode 100644 index a4944913b5..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/haraka.c +++ /dev/null @@ -1,913 +0,0 @@ -/* - * Constant time implementation of the Haraka hash function. - * - * The bit-sliced implementation of the AES round functions are - * based on the AES implementation in BearSSL written - * by Thomas Pornin - */ - -#include -#include -#include -#include - -#include "haraka.h" -#include "utils.h" - -#define HARAKAS_RATE 32 - -static const uint64_t haraka512_rc64[10][8] = { - {0x24cf0ab9086f628b, 0xbdd6eeecc83b8382, 0xd96fb0306cdad0a7, 0xaace082ac8f95f89, 0x449d8e8870d7041f, 0x49bb2f80b2b3e2f8, 0x0569ae98d93bb258, 0x23dc9691e7d6a4b1}, - {0xd8ba10ede0fe5b6e, 0x7ecf7dbe424c7b8e, 0x6ea9949c6df62a31, 0xbf3f3c97ec9c313e, 0x241d03a196a1861e, 0xead3a51116e5a2ea, 0x77d479fcad9574e3, 0x18657a1af894b7a0}, - {0x10671e1a7f595522, 0xd9a00ff675d28c7b, 0x2f1edf0d2b9ba661, 0xb8ff58b8e3de45f9, 0xee29261da9865c02, 0xd1532aa4b50bdf43, 0x8bf858159b231bb1, 0xdf17439d22d4f599}, - {0xdd4b2f0870b918c0, 0x757a81f3b39b1bb6, 0x7a5c556898952e3f, 0x7dd70a16d915d87a, 0x3ae61971982b8301, 0xc3ab319e030412be, 0x17c0033ac094a8cb, 0x5a0630fc1a8dc4ef}, - {0x17708988c1632f73, 0xf92ddae090b44f4f, 0x11ac0285c43aa314, 0x509059941936b8ba, 0xd03e152fa2ce9b69, 0x3fbcbcb63a32998b, 0x6204696d692254f7, 0x915542ed93ec59b4}, - {0xf4ed94aa8879236e, 0xff6cb41cd38e03c0, 0x069b38602368aeab, 0x669495b820f0ddba, 0xf42013b1b8bf9e3d, 0xcf935efe6439734d, 0xbc1dcf42ca29e3f8, 0x7e6d3ed29f78ad67}, - {0xf3b0f6837ffcddaa, 0x3a76faef934ddf41, 0xcec7ae583a9c8e35, 0xe4dd18c68f0260af, 0x2c0e5df1ad398eaa, 0x478df5236ae22e8c, 0xfb944c46fe865f39, 0xaa48f82f028132ba}, - {0x231b9ae2b76aca77, 0x292a76a712db0b40, 0x5850625dc8134491, 0x73137dd469810fb5, 0x8a12a6a202a474fd, 0xd36fd9daa78bdb80, 0xb34c5e733505706f, 0xbaf1cdca818d9d96}, - {0x2e99781335e8c641, 0xbddfe5cce47d560e, 0xf74e9bf32e5e040c, 0x1d7a709d65996be9, 0x670df36a9cf66cdd, 0xd05ef84a176a2875, 0x0f888e828cb1c44e, 0x1a79e9c9727b052c}, - {0x83497348628d84de, 0x2e9387d51f22a754, 0xb000068da2f852d6, 0x378c9e1190fd6fe5, 0x870027c316de7293, 0xe51a9d4462e047bb, 0x90ecf7f8c6251195, 0x655953bfbed90a9c}, -}; - -static inline uint32_t br_dec32le(const unsigned char *src) { - return (uint32_t)src[0] - | ((uint32_t)src[1] << 8) - | ((uint32_t)src[2] << 16) - | ((uint32_t)src[3] << 24); -} - -static void br_range_dec32le(uint32_t *v, size_t num, const unsigned char *src) { - while (num-- > 0) { - *v ++ = br_dec32le(src); - src += 4; - } -} - -static inline void br_enc32le(unsigned char *dst, uint32_t x) { - dst[0] = (unsigned char)x; - dst[1] = (unsigned char)(x >> 8); - dst[2] = (unsigned char)(x >> 16); - dst[3] = (unsigned char)(x >> 24); -} - - -static void br_range_enc32le(unsigned char *dst, const uint32_t *v, size_t num) { - while (num-- > 0) { - br_enc32le(dst, *v ++); - dst += 4; - } -} - -static void br_aes_ct64_bitslice_Sbox(uint64_t *q) { - /* - * This S-box implementation is a straightforward translation of - * the circuit described by Boyar and Peralta in "A new - * combinational logic minimization technique with applications - * to cryptology" (https://eprint.iacr.org/2009/191.pdf). - * - * Note that variables x* (input) and s* (output) are numbered - * in "reverse" order (x0 is the high bit, x7 is the low bit). - */ - - uint64_t x0, x1, x2, x3, x4, x5, x6, x7; - uint64_t y1, y2, y3, y4, y5, y6, y7, y8, y9; - uint64_t y10, y11, y12, y13, y14, y15, y16, y17, y18, y19; - uint64_t y20, y21; - uint64_t z0, z1, z2, z3, z4, z5, z6, z7, z8, z9; - uint64_t z10, z11, z12, z13, z14, z15, z16, z17; - uint64_t t0, t1, t2, t3, t4, t5, t6, t7, t8, t9; - uint64_t t10, t11, t12, t13, t14, t15, t16, t17, t18, t19; - uint64_t t20, t21, t22, t23, t24, t25, t26, t27, t28, t29; - uint64_t t30, t31, t32, t33, t34, t35, t36, t37, t38, t39; - uint64_t t40, t41, t42, t43, t44, t45, t46, t47, t48, t49; - uint64_t t50, t51, t52, t53, t54, t55, t56, t57, t58, t59; - uint64_t t60, t61, t62, t63, t64, t65, t66, t67; - uint64_t s0, s1, s2, s3, s4, s5, s6, s7; - - x0 = q[7]; - x1 = q[6]; - x2 = q[5]; - x3 = q[4]; - x4 = q[3]; - x5 = q[2]; - x6 = q[1]; - x7 = q[0]; - - /* - * Top linear transformation. - */ - y14 = x3 ^ x5; - y13 = x0 ^ x6; - y9 = x0 ^ x3; - y8 = x0 ^ x5; - t0 = x1 ^ x2; - y1 = t0 ^ x7; - y4 = y1 ^ x3; - y12 = y13 ^ y14; - y2 = y1 ^ x0; - y5 = y1 ^ x6; - y3 = y5 ^ y8; - t1 = x4 ^ y12; - y15 = t1 ^ x5; - y20 = t1 ^ x1; - y6 = y15 ^ x7; - y10 = y15 ^ t0; - y11 = y20 ^ y9; - y7 = x7 ^ y11; - y17 = y10 ^ y11; - y19 = y10 ^ y8; - y16 = t0 ^ y11; - y21 = y13 ^ y16; - y18 = x0 ^ y16; - - /* - * Non-linear section. - */ - t2 = y12 & y15; - t3 = y3 & y6; - t4 = t3 ^ t2; - t5 = y4 & x7; - t6 = t5 ^ t2; - t7 = y13 & y16; - t8 = y5 & y1; - t9 = t8 ^ t7; - t10 = y2 & y7; - t11 = t10 ^ t7; - t12 = y9 & y11; - t13 = y14 & y17; - t14 = t13 ^ t12; - t15 = y8 & y10; - t16 = t15 ^ t12; - t17 = t4 ^ t14; - t18 = t6 ^ t16; - t19 = t9 ^ t14; - t20 = t11 ^ t16; - t21 = t17 ^ y20; - t22 = t18 ^ y19; - t23 = t19 ^ y21; - t24 = t20 ^ y18; - - t25 = t21 ^ t22; - t26 = t21 & t23; - t27 = t24 ^ t26; - t28 = t25 & t27; - t29 = t28 ^ t22; - t30 = t23 ^ t24; - t31 = t22 ^ t26; - t32 = t31 & t30; - t33 = t32 ^ t24; - t34 = t23 ^ t33; - t35 = t27 ^ t33; - t36 = t24 & t35; - t37 = t36 ^ t34; - t38 = t27 ^ t36; - t39 = t29 & t38; - t40 = t25 ^ t39; - - t41 = t40 ^ t37; - t42 = t29 ^ t33; - t43 = t29 ^ t40; - t44 = t33 ^ t37; - t45 = t42 ^ t41; - z0 = t44 & y15; - z1 = t37 & y6; - z2 = t33 & x7; - z3 = t43 & y16; - z4 = t40 & y1; - z5 = t29 & y7; - z6 = t42 & y11; - z7 = t45 & y17; - z8 = t41 & y10; - z9 = t44 & y12; - z10 = t37 & y3; - z11 = t33 & y4; - z12 = t43 & y13; - z13 = t40 & y5; - z14 = t29 & y2; - z15 = t42 & y9; - z16 = t45 & y14; - z17 = t41 & y8; - - /* - * Bottom linear transformation. - */ - t46 = z15 ^ z16; - t47 = z10 ^ z11; - t48 = z5 ^ z13; - t49 = z9 ^ z10; - t50 = z2 ^ z12; - t51 = z2 ^ z5; - t52 = z7 ^ z8; - t53 = z0 ^ z3; - t54 = z6 ^ z7; - t55 = z16 ^ z17; - t56 = z12 ^ t48; - t57 = t50 ^ t53; - t58 = z4 ^ t46; - t59 = z3 ^ t54; - t60 = t46 ^ t57; - t61 = z14 ^ t57; - t62 = t52 ^ t58; - t63 = t49 ^ t58; - t64 = z4 ^ t59; - t65 = t61 ^ t62; - t66 = z1 ^ t63; - s0 = t59 ^ t63; - s6 = t56 ^ ~t62; - s7 = t48 ^ ~t60; - t67 = t64 ^ t65; - s3 = t53 ^ t66; - s4 = t51 ^ t66; - s5 = t47 ^ t65; - s1 = t64 ^ ~s3; - s2 = t55 ^ ~t67; - - q[7] = s0; - q[6] = s1; - q[5] = s2; - q[4] = s3; - q[3] = s4; - q[2] = s5; - q[1] = s6; - q[0] = s7; -} - -static void br_aes_ct_bitslice_Sbox(uint32_t *q) { - /* - * This S-box implementation is a straightforward translation of - * the circuit described by Boyar and Peralta in "A new - * combinational logic minimization technique with applications - * to cryptology" (https://eprint.iacr.org/2009/191.pdf). - * - * Note that variables x* (input) and s* (output) are numbered - * in "reverse" order (x0 is the high bit, x7 is the low bit). - */ - - uint32_t x0, x1, x2, x3, x4, x5, x6, x7; - uint32_t y1, y2, y3, y4, y5, y6, y7, y8, y9; - uint32_t y10, y11, y12, y13, y14, y15, y16, y17, y18, y19; - uint32_t y20, y21; - uint32_t z0, z1, z2, z3, z4, z5, z6, z7, z8, z9; - uint32_t z10, z11, z12, z13, z14, z15, z16, z17; - uint32_t t0, t1, t2, t3, t4, t5, t6, t7, t8, t9; - uint32_t t10, t11, t12, t13, t14, t15, t16, t17, t18, t19; - uint32_t t20, t21, t22, t23, t24, t25, t26, t27, t28, t29; - uint32_t t30, t31, t32, t33, t34, t35, t36, t37, t38, t39; - uint32_t t40, t41, t42, t43, t44, t45, t46, t47, t48, t49; - uint32_t t50, t51, t52, t53, t54, t55, t56, t57, t58, t59; - uint32_t t60, t61, t62, t63, t64, t65, t66, t67; - uint32_t s0, s1, s2, s3, s4, s5, s6, s7; - - x0 = q[7]; - x1 = q[6]; - x2 = q[5]; - x3 = q[4]; - x4 = q[3]; - x5 = q[2]; - x6 = q[1]; - x7 = q[0]; - - /* - * Top linear transformation. - */ - y14 = x3 ^ x5; - y13 = x0 ^ x6; - y9 = x0 ^ x3; - y8 = x0 ^ x5; - t0 = x1 ^ x2; - y1 = t0 ^ x7; - y4 = y1 ^ x3; - y12 = y13 ^ y14; - y2 = y1 ^ x0; - y5 = y1 ^ x6; - y3 = y5 ^ y8; - t1 = x4 ^ y12; - y15 = t1 ^ x5; - y20 = t1 ^ x1; - y6 = y15 ^ x7; - y10 = y15 ^ t0; - y11 = y20 ^ y9; - y7 = x7 ^ y11; - y17 = y10 ^ y11; - y19 = y10 ^ y8; - y16 = t0 ^ y11; - y21 = y13 ^ y16; - y18 = x0 ^ y16; - - /* - * Non-linear section. - */ - t2 = y12 & y15; - t3 = y3 & y6; - t4 = t3 ^ t2; - t5 = y4 & x7; - t6 = t5 ^ t2; - t7 = y13 & y16; - t8 = y5 & y1; - t9 = t8 ^ t7; - t10 = y2 & y7; - t11 = t10 ^ t7; - t12 = y9 & y11; - t13 = y14 & y17; - t14 = t13 ^ t12; - t15 = y8 & y10; - t16 = t15 ^ t12; - t17 = t4 ^ t14; - t18 = t6 ^ t16; - t19 = t9 ^ t14; - t20 = t11 ^ t16; - t21 = t17 ^ y20; - t22 = t18 ^ y19; - t23 = t19 ^ y21; - t24 = t20 ^ y18; - - t25 = t21 ^ t22; - t26 = t21 & t23; - t27 = t24 ^ t26; - t28 = t25 & t27; - t29 = t28 ^ t22; - t30 = t23 ^ t24; - t31 = t22 ^ t26; - t32 = t31 & t30; - t33 = t32 ^ t24; - t34 = t23 ^ t33; - t35 = t27 ^ t33; - t36 = t24 & t35; - t37 = t36 ^ t34; - t38 = t27 ^ t36; - t39 = t29 & t38; - t40 = t25 ^ t39; - - t41 = t40 ^ t37; - t42 = t29 ^ t33; - t43 = t29 ^ t40; - t44 = t33 ^ t37; - t45 = t42 ^ t41; - z0 = t44 & y15; - z1 = t37 & y6; - z2 = t33 & x7; - z3 = t43 & y16; - z4 = t40 & y1; - z5 = t29 & y7; - z6 = t42 & y11; - z7 = t45 & y17; - z8 = t41 & y10; - z9 = t44 & y12; - z10 = t37 & y3; - z11 = t33 & y4; - z12 = t43 & y13; - z13 = t40 & y5; - z14 = t29 & y2; - z15 = t42 & y9; - z16 = t45 & y14; - z17 = t41 & y8; - - /* - * Bottom linear transformation. - */ - t46 = z15 ^ z16; - t47 = z10 ^ z11; - t48 = z5 ^ z13; - t49 = z9 ^ z10; - t50 = z2 ^ z12; - t51 = z2 ^ z5; - t52 = z7 ^ z8; - t53 = z0 ^ z3; - t54 = z6 ^ z7; - t55 = z16 ^ z17; - t56 = z12 ^ t48; - t57 = t50 ^ t53; - t58 = z4 ^ t46; - t59 = z3 ^ t54; - t60 = t46 ^ t57; - t61 = z14 ^ t57; - t62 = t52 ^ t58; - t63 = t49 ^ t58; - t64 = z4 ^ t59; - t65 = t61 ^ t62; - t66 = z1 ^ t63; - s0 = t59 ^ t63; - s6 = t56 ^ ~t62; - s7 = t48 ^ ~t60; - t67 = t64 ^ t65; - s3 = t53 ^ t66; - s4 = t51 ^ t66; - s5 = t47 ^ t65; - s1 = t64 ^ ~s3; - s2 = t55 ^ ~t67; - - q[7] = s0; - q[6] = s1; - q[5] = s2; - q[4] = s3; - q[3] = s4; - q[2] = s5; - q[1] = s6; - q[0] = s7; -} - -static void br_aes_ct_ortho(uint32_t *q) { -#define SWAPN_32(cl, ch, s, x, y) do { \ - uint32_t a, b; \ - a = (x); \ - b = (y); \ - (x) = (a & (uint32_t)(cl)) | ((b & (uint32_t)(cl)) << (s)); \ - (y) = ((a & (uint32_t)(ch)) >> (s)) | (b & (uint32_t)(ch)); \ - } while (0) - -#define SWAP2_32(x, y) SWAPN_32(0x55555555, 0xAAAAAAAA, 1, x, y) -#define SWAP4_32(x, y) SWAPN_32(0x33333333, 0xCCCCCCCC, 2, x, y) -#define SWAP8_32(x, y) SWAPN_32(0x0F0F0F0F, 0xF0F0F0F0, 4, x, y) - - SWAP2_32(q[0], q[1]); - SWAP2_32(q[2], q[3]); - SWAP2_32(q[4], q[5]); - SWAP2_32(q[6], q[7]); - - SWAP4_32(q[0], q[2]); - SWAP4_32(q[1], q[3]); - SWAP4_32(q[4], q[6]); - SWAP4_32(q[5], q[7]); - - SWAP8_32(q[0], q[4]); - SWAP8_32(q[1], q[5]); - SWAP8_32(q[2], q[6]); - SWAP8_32(q[3], q[7]); -} - -static inline void add_round_key32(uint32_t *q, const uint32_t *sk) { - q[0] ^= sk[0]; - q[1] ^= sk[1]; - q[2] ^= sk[2]; - q[3] ^= sk[3]; - q[4] ^= sk[4]; - q[5] ^= sk[5]; - q[6] ^= sk[6]; - q[7] ^= sk[7]; -} - -static inline void shift_rows32(uint32_t *q) { - int i; - - for (i = 0; i < 8; i++) { - uint32_t x; - - x = q[i]; - q[i] = (x & 0x000000FF) - | ((x & 0x0000FC00) >> 2) | ((x & 0x00000300) << 6) - | ((x & 0x00F00000) >> 4) | ((x & 0x000F0000) << 4) - | ((x & 0xC0000000) >> 6) | ((x & 0x3F000000) << 2); - } -} - -static inline uint32_t rotr16(uint32_t x) { - return (x << 16) | (x >> 16); -} - -static inline void mix_columns32(uint32_t *q) { - uint32_t q0, q1, q2, q3, q4, q5, q6, q7; - uint32_t r0, r1, r2, r3, r4, r5, r6, r7; - - q0 = q[0]; - q1 = q[1]; - q2 = q[2]; - q3 = q[3]; - q4 = q[4]; - q5 = q[5]; - q6 = q[6]; - q7 = q[7]; - r0 = (q0 >> 8) | (q0 << 24); - r1 = (q1 >> 8) | (q1 << 24); - r2 = (q2 >> 8) | (q2 << 24); - r3 = (q3 >> 8) | (q3 << 24); - r4 = (q4 >> 8) | (q4 << 24); - r5 = (q5 >> 8) | (q5 << 24); - r6 = (q6 >> 8) | (q6 << 24); - r7 = (q7 >> 8) | (q7 << 24); - - q[0] = q7 ^ r7 ^ r0 ^ rotr16(q0 ^ r0); - q[1] = q0 ^ r0 ^ q7 ^ r7 ^ r1 ^ rotr16(q1 ^ r1); - q[2] = q1 ^ r1 ^ r2 ^ rotr16(q2 ^ r2); - q[3] = q2 ^ r2 ^ q7 ^ r7 ^ r3 ^ rotr16(q3 ^ r3); - q[4] = q3 ^ r3 ^ q7 ^ r7 ^ r4 ^ rotr16(q4 ^ r4); - q[5] = q4 ^ r4 ^ r5 ^ rotr16(q5 ^ r5); - q[6] = q5 ^ r5 ^ r6 ^ rotr16(q6 ^ r6); - q[7] = q6 ^ r6 ^ r7 ^ rotr16(q7 ^ r7); -} - -static void br_aes_ct64_ortho(uint64_t *q) { -#define SWAPN(cl, ch, s, x, y) do { \ - uint64_t a, b; \ - a = (x); \ - b = (y); \ - (x) = (a & (uint64_t)(cl)) | ((b & (uint64_t)(cl)) << (s)); \ - (y) = ((a & (uint64_t)(ch)) >> (s)) | (b & (uint64_t)(ch)); \ - } while (0) - -#define SWAP2(x, y) SWAPN(0x5555555555555555, 0xAAAAAAAAAAAAAAAA, 1, x, y) -#define SWAP4(x, y) SWAPN(0x3333333333333333, 0xCCCCCCCCCCCCCCCC, 2, x, y) -#define SWAP8(x, y) SWAPN(0x0F0F0F0F0F0F0F0F, 0xF0F0F0F0F0F0F0F0, 4, x, y) - - SWAP2(q[0], q[1]); - SWAP2(q[2], q[3]); - SWAP2(q[4], q[5]); - SWAP2(q[6], q[7]); - - SWAP4(q[0], q[2]); - SWAP4(q[1], q[3]); - SWAP4(q[4], q[6]); - SWAP4(q[5], q[7]); - - SWAP8(q[0], q[4]); - SWAP8(q[1], q[5]); - SWAP8(q[2], q[6]); - SWAP8(q[3], q[7]); -} - - -static void br_aes_ct64_interleave_in(uint64_t *q0, uint64_t *q1, const uint32_t *w) { - uint64_t x0, x1, x2, x3; - - x0 = w[0]; - x1 = w[1]; - x2 = w[2]; - x3 = w[3]; - x0 |= (x0 << 16); - x1 |= (x1 << 16); - x2 |= (x2 << 16); - x3 |= (x3 << 16); - x0 &= (uint64_t)0x0000FFFF0000FFFF; - x1 &= (uint64_t)0x0000FFFF0000FFFF; - x2 &= (uint64_t)0x0000FFFF0000FFFF; - x3 &= (uint64_t)0x0000FFFF0000FFFF; - x0 |= (x0 << 8); - x1 |= (x1 << 8); - x2 |= (x2 << 8); - x3 |= (x3 << 8); - x0 &= (uint64_t)0x00FF00FF00FF00FF; - x1 &= (uint64_t)0x00FF00FF00FF00FF; - x2 &= (uint64_t)0x00FF00FF00FF00FF; - x3 &= (uint64_t)0x00FF00FF00FF00FF; - *q0 = x0 | (x2 << 8); - *q1 = x1 | (x3 << 8); -} - - -static void br_aes_ct64_interleave_out(uint32_t *w, uint64_t q0, uint64_t q1) { - uint64_t x0, x1, x2, x3; - - x0 = q0 & (uint64_t)0x00FF00FF00FF00FF; - x1 = q1 & (uint64_t)0x00FF00FF00FF00FF; - x2 = (q0 >> 8) & (uint64_t)0x00FF00FF00FF00FF; - x3 = (q1 >> 8) & (uint64_t)0x00FF00FF00FF00FF; - x0 |= (x0 >> 8); - x1 |= (x1 >> 8); - x2 |= (x2 >> 8); - x3 |= (x3 >> 8); - x0 &= (uint64_t)0x0000FFFF0000FFFF; - x1 &= (uint64_t)0x0000FFFF0000FFFF; - x2 &= (uint64_t)0x0000FFFF0000FFFF; - x3 &= (uint64_t)0x0000FFFF0000FFFF; - w[0] = (uint32_t)x0 | (uint32_t)(x0 >> 16); - w[1] = (uint32_t)x1 | (uint32_t)(x1 >> 16); - w[2] = (uint32_t)x2 | (uint32_t)(x2 >> 16); - w[3] = (uint32_t)x3 | (uint32_t)(x3 >> 16); -} - -static inline void add_round_key(uint64_t *q, const uint64_t *sk) { - q[0] ^= sk[0]; - q[1] ^= sk[1]; - q[2] ^= sk[2]; - q[3] ^= sk[3]; - q[4] ^= sk[4]; - q[5] ^= sk[5]; - q[6] ^= sk[6]; - q[7] ^= sk[7]; -} - -static inline void shift_rows(uint64_t *q) { - int i; - - for (i = 0; i < 8; i++) { - uint64_t x; - - x = q[i]; - q[i] = (x & (uint64_t)0x000000000000FFFF) - | ((x & (uint64_t)0x00000000FFF00000) >> 4) - | ((x & (uint64_t)0x00000000000F0000) << 12) - | ((x & (uint64_t)0x0000FF0000000000) >> 8) - | ((x & (uint64_t)0x000000FF00000000) << 8) - | ((x & (uint64_t)0xF000000000000000) >> 12) - | ((x & (uint64_t)0x0FFF000000000000) << 4); - } -} - -static inline uint64_t rotr32(uint64_t x) { - return (x << 32) | (x >> 32); -} - -static inline void mix_columns(uint64_t *q) { - uint64_t q0, q1, q2, q3, q4, q5, q6, q7; - uint64_t r0, r1, r2, r3, r4, r5, r6, r7; - - q0 = q[0]; - q1 = q[1]; - q2 = q[2]; - q3 = q[3]; - q4 = q[4]; - q5 = q[5]; - q6 = q[6]; - q7 = q[7]; - r0 = (q0 >> 16) | (q0 << 48); - r1 = (q1 >> 16) | (q1 << 48); - r2 = (q2 >> 16) | (q2 << 48); - r3 = (q3 >> 16) | (q3 << 48); - r4 = (q4 >> 16) | (q4 << 48); - r5 = (q5 >> 16) | (q5 << 48); - r6 = (q6 >> 16) | (q6 << 48); - r7 = (q7 >> 16) | (q7 << 48); - - q[0] = q7 ^ r7 ^ r0 ^ rotr32(q0 ^ r0); - q[1] = q0 ^ r0 ^ q7 ^ r7 ^ r1 ^ rotr32(q1 ^ r1); - q[2] = q1 ^ r1 ^ r2 ^ rotr32(q2 ^ r2); - q[3] = q2 ^ r2 ^ q7 ^ r7 ^ r3 ^ rotr32(q3 ^ r3); - q[4] = q3 ^ r3 ^ q7 ^ r7 ^ r4 ^ rotr32(q4 ^ r4); - q[5] = q4 ^ r4 ^ r5 ^ rotr32(q5 ^ r5); - q[6] = q5 ^ r5 ^ r6 ^ rotr32(q6 ^ r6); - q[7] = q6 ^ r6 ^ r7 ^ rotr32(q7 ^ r7); -} - -static void interleave_constant(uint64_t *out, const unsigned char *in) { - uint32_t tmp_32_constant[16]; - int i; - - br_range_dec32le(tmp_32_constant, 16, in); - for (i = 0; i < 4; i++) { - br_aes_ct64_interleave_in(&out[i], &out[i + 4], tmp_32_constant + (i << 2)); - } - br_aes_ct64_ortho(out); -} - -static void interleave_constant32(uint32_t *out, const unsigned char *in) { - int i; - for (i = 0; i < 4; i++) { - out[2 * i] = br_dec32le(in + 4 * i); - out[2 * i + 1] = br_dec32le(in + 4 * i + 16); - } - br_aes_ct_ortho(out); -} - -void tweak_constants(spx_ctx *ctx) { - unsigned char buf[40 * 16]; - int i; - - /* Use the standard constants to generate tweaked ones. */ - memcpy((uint8_t *)ctx->tweaked512_rc64, (uint8_t *)haraka512_rc64, 40 * 16); - - /* Constants for pk.seed */ - haraka_S(buf, 40 * 16, ctx->pub_seed, SPX_N, ctx); - for (i = 0; i < 10; i++) { - interleave_constant32(ctx->tweaked256_rc32[i], buf + 32 * i); - interleave_constant(ctx->tweaked512_rc64[i], buf + 64 * i); - } -} - -static void haraka_S_absorb(unsigned char *s, unsigned int r, - const unsigned char *m, unsigned long long mlen, - unsigned char p, const spx_ctx *ctx) { - unsigned long long i; - PQCLEAN_VLA(uint8_t, t, r); - - while (mlen >= r) { - /* XOR block to state */ - for (i = 0; i < r; ++i) { - s[i] ^= m[i]; - } - haraka512_perm(s, s, ctx); - 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; ++i) { - s[i] ^= t[i]; - } -} - -static void haraka_S_squeezeblocks(unsigned char *h, unsigned long long nblocks, - unsigned char *s, unsigned int r, - const spx_ctx *ctx) { - while (nblocks > 0) { - haraka512_perm(s, s, ctx); - memcpy(h, s, HARAKAS_RATE); - h += r; - nblocks--; - } -} - -void haraka_S_inc_init(uint8_t *s_inc) { - size_t i; - - for (i = 0; i < 64; i++) { - s_inc[i] = 0; - } - s_inc[64] = 0; -} - -void haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, - const spx_ctx *ctx) { - size_t i; - - /* Recall that s_inc[64] is the non-absorbed bytes xored into the state */ - while (mlen + s_inc[64] >= HARAKAS_RATE) { - for (i = 0; i < (size_t)(HARAKAS_RATE - s_inc[64]); i++) { - /* Take the i'th byte from message - xor with the s_inc[64] + i'th byte of the state */ - s_inc[s_inc[64] + i] ^= m[i]; - } - mlen -= (size_t)(HARAKAS_RATE - s_inc[64]); - m += HARAKAS_RATE - (uint8_t)s_inc[64]; - s_inc[64] = 0; - - haraka512_perm(s_inc, s_inc, ctx); - } - - for (i = 0; i < mlen; i++) { - s_inc[s_inc[64] + i] ^= m[i]; - } - s_inc[64] += (uint8_t)mlen; -} - -void haraka_S_inc_finalize(uint8_t *s_inc) { - /* After haraka_S_inc_absorb, we are guaranteed that s_inc[64] < HARAKAS_RATE, - so we can always use one more byte for p in the current state. */ - s_inc[s_inc[64]] ^= 0x1F; - s_inc[HARAKAS_RATE - 1] ^= 128; - s_inc[64] = 0; -} - -void haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, - const spx_ctx *ctx) { - size_t i; - - /* First consume any bytes we still have sitting around */ - for (i = 0; i < outlen && i < s_inc[64]; i++) { - /* There are s_inc[64] bytes left, so r - s_inc[64] is the first - available byte. We consume from there, i.e., up to r. */ - out[i] = (uint8_t)s_inc[(HARAKAS_RATE - s_inc[64] + i)]; - } - out += i; - outlen -= i; - s_inc[64] -= (uint8_t)i; - - /* Then squeeze the remaining necessary blocks */ - while (outlen > 0) { - haraka512_perm(s_inc, s_inc, ctx); - - for (i = 0; i < outlen && i < HARAKAS_RATE; i++) { - out[i] = s_inc[i]; - } - out += i; - outlen -= i; - s_inc[64] = (uint8_t)(HARAKAS_RATE - i); - } -} - -void haraka_S(unsigned char *out, unsigned long long outlen, - const unsigned char *in, unsigned long long inlen, - const spx_ctx *ctx) { - unsigned long long i; - unsigned char s[64]; - unsigned char d[32]; - - for (i = 0; i < 64; i++) { - s[i] = 0; - } - haraka_S_absorb(s, 32, in, inlen, 0x1F, ctx); - - haraka_S_squeezeblocks(out, outlen / 32, s, 32, ctx); - out += (outlen / 32) * 32; - - if (outlen % 32) { - haraka_S_squeezeblocks(d, 1, s, 32, ctx); - for (i = 0; i < outlen % 32; i++) { - out[i] = d[i]; - } - } -} - -void haraka512_perm(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx) { - uint32_t w[16]; - uint64_t q[8], tmp_q; - unsigned int i, j; - - br_range_dec32le(w, 16, in); - for (i = 0; i < 4; i++) { - br_aes_ct64_interleave_in(&q[i], &q[i + 4], w + (i << 2)); - } - br_aes_ct64_ortho(q); - - /* AES rounds */ - for (i = 0; i < 5; i++) { - for (j = 0; j < 2; j++) { - br_aes_ct64_bitslice_Sbox(q); - shift_rows(q); - mix_columns(q); - add_round_key(q, ctx->tweaked512_rc64[2 * i + j]); - } - /* Mix states */ - for (j = 0; j < 8; j++) { - tmp_q = q[j]; - q[j] = (tmp_q & 0x0001000100010001) << 5 | - (tmp_q & 0x0002000200020002) << 12 | - (tmp_q & 0x0004000400040004) >> 1 | - (tmp_q & 0x0008000800080008) << 6 | - (tmp_q & 0x0020002000200020) << 9 | - (tmp_q & 0x0040004000400040) >> 4 | - (tmp_q & 0x0080008000800080) << 3 | - (tmp_q & 0x2100210021002100) >> 5 | - (tmp_q & 0x0210021002100210) << 2 | - (tmp_q & 0x0800080008000800) << 4 | - (tmp_q & 0x1000100010001000) >> 12 | - (tmp_q & 0x4000400040004000) >> 10 | - (tmp_q & 0x8400840084008400) >> 3; - } - } - - br_aes_ct64_ortho(q); - for (i = 0; i < 4; i ++) { - br_aes_ct64_interleave_out(w + (i << 2), q[i], q[i + 4]); - } - br_range_enc32le(out, w, 16); -} - -void haraka512(unsigned char *out, const unsigned char *in, const spx_ctx *ctx) { - int i; - - unsigned char buf[64]; - - haraka512_perm(buf, in, ctx); - /* Feed-forward */ - for (i = 0; i < 64; i++) { - buf[i] = buf[i] ^ in[i]; - } - - /* Truncated */ - memcpy(out, buf + 8, 8); - memcpy(out + 8, buf + 24, 8); - memcpy(out + 16, buf + 32, 8); - memcpy(out + 24, buf + 48, 8); -} - - -void haraka256(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx) { - uint32_t q[8], tmp_q; - int i, j; - - for (i = 0; i < 4; i++) { - q[2 * i] = br_dec32le(in + 4 * i); - q[2 * i + 1] = br_dec32le(in + 4 * i + 16); - } - br_aes_ct_ortho(q); - - /* AES rounds */ - for (i = 0; i < 5; i++) { - for (j = 0; j < 2; j++) { - br_aes_ct_bitslice_Sbox(q); - shift_rows32(q); - mix_columns32(q); - add_round_key32(q, ctx->tweaked256_rc32[2 * i + j]); - } - - /* Mix states */ - for (j = 0; j < 8; j++) { - tmp_q = q[j]; - q[j] = (tmp_q & 0x81818181) | - (tmp_q & 0x02020202) << 1 | - (tmp_q & 0x04040404) << 2 | - (tmp_q & 0x08080808) << 3 | - (tmp_q & 0x10101010) >> 3 | - (tmp_q & 0x20202020) >> 2 | - (tmp_q & 0x40404040) >> 1; - } - } - - br_aes_ct_ortho(q); - for (i = 0; i < 4; i++) { - br_enc32le(out + 4 * i, q[2 * i]); - br_enc32le(out + 4 * i + 16, q[2 * i + 1]); - } - - for (i = 0; i < 32; i++) { - out[i] ^= in[i]; - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/haraka.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/haraka.h deleted file mode 100644 index 737cb6065f..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/haraka.h +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef SPX_HARAKA_H -#define SPX_HARAKA_H - -#include "context.h" -#include "params.h" - -/* Tweak constants with seed */ -#define tweak_constants SPX_NAMESPACE(tweak_constants) -void tweak_constants(spx_ctx *ctx); - -/* Haraka Sponge */ -#define haraka_S_inc_init SPX_NAMESPACE(haraka_S_inc_init) -void haraka_S_inc_init(uint8_t *s_inc); -#define haraka_S_inc_absorb SPX_NAMESPACE(haraka_S_inc_absorb) -void haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, - const spx_ctx *ctx); -#define haraka_S_inc_finalize SPX_NAMESPACE(haraka_S_inc_finalize) -void haraka_S_inc_finalize(uint8_t *s_inc); -#define haraka_S_inc_squeeze SPX_NAMESPACE(haraka_S_inc_squeeze) -void haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, - const spx_ctx *ctx); -#define haraka_S SPX_NAMESPACE(haraka_S) -void haraka_S(unsigned char *out, unsigned long long outlen, - const unsigned char *in, unsigned long long inlen, - const spx_ctx *ctx); - -/* Applies the 512-bit Haraka permutation to in. */ -#define haraka512_perm SPX_NAMESPACE(haraka512_perm) -void haraka512_perm(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx); - -/* Implementation of Haraka-512 */ -#define haraka512 SPX_NAMESPACE(haraka512) -void haraka512(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx); - -/* Implementation of Haraka-256 */ -#define haraka256 SPX_NAMESPACE(haraka256) -void haraka256(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/haraka_offsets.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/haraka_offsets.h deleted file mode 100644 index 7c062272a0..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/haraka_offsets.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef HARAKA_OFFSETS_H_ -#define HARAKA_OFFSETS_H_ - -/* - * Offsets of various fields in the address structure when we use Haraka as - * the Sphincs+ hash function - */ - -#define SPX_OFFSET_LAYER 3 /* The byte used to specify the Merkle tree layer */ -#define SPX_OFFSET_TREE 8 /* The start of the 8 byte field used to specify the tree */ -#define SPX_OFFSET_TYPE 19 /* The byte used to specify the hash type (reason) */ -#define SPX_OFFSET_KP_ADDR2 22 /* The high byte used to specify the key pair (which one-time signature) */ -#define SPX_OFFSET_KP_ADDR1 23 /* The low byte used to specify the key pair */ -#define SPX_OFFSET_CHAIN_ADDR 27 /* The byte used to specify the chain address (which Winternitz chain) */ -#define SPX_OFFSET_HASH_ADDR 31 /* The byte used to specify the hash address (where in the Winternitz chain) */ -#define SPX_OFFSET_TREE_HGT 27 /* The byte used to specify the height of this node in the FORS or Merkle tree */ -#define SPX_OFFSET_TREE_INDEX 28 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ - -#define SPX_HARAKA 1 - -#endif /* HARAKA_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/hash.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/hash.h deleted file mode 100644 index f7c87d4c3c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/hash.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef SPX_HASH_H -#define SPX_HASH_H - -#include -#include - -#include "context.h" -#include "params.h" - -#define prf_addr SPX_NAMESPACE(prf_addr) -void prf_addr(unsigned char *out, const spx_ctx *ctx, - const uint32_t addr[8]); - -#define gen_message_random SPX_NAMESPACE(gen_message_random) -void gen_message_random(unsigned char *R, const unsigned char *sk_prf, - const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx); - -#define hash_message SPX_NAMESPACE(hash_message) -void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx); - - - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/hash_haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/hash_haraka.c deleted file mode 100644 index 750a67423b..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/hash_haraka.c +++ /dev/null @@ -1,81 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "utils.h" - -#include "haraka.h" -#include "hash.h" - -/* - * Computes PRF(key, addr), given a secret key of SPX_N bytes and an address - */ -void prf_addr(unsigned char *out, const spx_ctx *ctx, - const uint32_t addr[8]) { - /* Since SPX_N may be smaller than 32, we need temporary buffers. */ - unsigned char outbuf[32]; - unsigned char buf[64] = {0}; - - memcpy(buf, addr, SPX_ADDR_BYTES); - memcpy(buf + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); - - haraka512(outbuf, (const void *)buf, ctx); - memcpy(out, outbuf, SPX_N); -} - -/** - * Computes the message-dependent randomness R, using a secret seed and an - * optional randomization value as well as the message. - */ -void gen_message_random(unsigned char *R, const unsigned char *sk_prf, - const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx) { - uint8_t s_inc[65]; - - haraka_S_inc_init(s_inc); - haraka_S_inc_absorb(s_inc, sk_prf, SPX_N, ctx); - haraka_S_inc_absorb(s_inc, optrand, SPX_N, ctx); - haraka_S_inc_absorb(s_inc, m, mlen, ctx); - haraka_S_inc_finalize(s_inc); - haraka_S_inc_squeeze(R, SPX_N, s_inc, ctx); -} - -/** - * Computes the message hash using R, the public key, and the message. - * Outputs the message digest and the index of the leaf. The index is split in - * the tree index and the leaf index, for convenient copying to an address. - */ -void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx) { -#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) -#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) -#define SPX_LEAF_BITS SPX_TREE_HEIGHT -#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) -#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) - - unsigned char buf[SPX_DGST_BYTES]; - unsigned char *bufp = buf; - uint8_t s_inc[65]; - - haraka_S_inc_init(s_inc); - haraka_S_inc_absorb(s_inc, R, SPX_N, ctx); - haraka_S_inc_absorb(s_inc, pk + SPX_N, SPX_N, ctx); // Only absorb root part of pk - haraka_S_inc_absorb(s_inc, m, mlen, ctx); - haraka_S_inc_finalize(s_inc); - haraka_S_inc_squeeze(buf, SPX_DGST_BYTES, s_inc, ctx); - - memcpy(digest, bufp, SPX_FORS_MSG_BYTES); - bufp += SPX_FORS_MSG_BYTES; - - - *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); - *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); - bufp += SPX_TREE_BYTES; - - *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); - *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/merkle.c b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/merkle.c deleted file mode 100644 index 0c1479fd93..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/merkle.c +++ /dev/null @@ -1,59 +0,0 @@ -#include -#include - -#include "address.h" -#include "merkle.h" -#include "params.h" -#include "utils.h" -#include "utilsx1.h" -#include "wots.h" -#include "wotsx1.h" - -/* - * This generates a Merkle signature (WOTS signature followed by the Merkle - * authentication path). This is in this file because most of the complexity - * is involved with the WOTS signature; the Merkle authentication path logic - * is mostly hidden in treehashx4 - */ -void merkle_sign(uint8_t *sig, unsigned char *root, - const spx_ctx *ctx, - uint32_t wots_addr[8], uint32_t tree_addr[8], - uint32_t idx_leaf) { - unsigned char *auth_path = sig + SPX_WOTS_BYTES; - struct leaf_info_x1 info = { 0 }; - unsigned steps[ SPX_WOTS_LEN ]; - - info.wots_sig = sig; - chain_lengths(steps, root); - info.wots_steps = steps; - - set_type(&tree_addr[0], SPX_ADDR_TYPE_HASHTREE); - set_type(&info.pk_addr[0], SPX_ADDR_TYPE_WOTSPK); - copy_subtree_addr(&info.leaf_addr[0], wots_addr); - copy_subtree_addr(&info.pk_addr[0], wots_addr); - - info.wots_sign_leaf = idx_leaf; - - treehashx1(root, auth_path, ctx, - idx_leaf, 0, - SPX_TREE_HEIGHT, - wots_gen_leafx1, - tree_addr, &info); -} - -/* Compute root node of the top-most subtree. */ -void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { - /* We do not need the auth path in key generation, but it simplifies the - code to have just one treehash routine that computes both root and path - in one function. */ - unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; - uint32_t top_tree_addr[8] = {0}; - uint32_t wots_addr[8] = {0}; - - set_layer_addr(top_tree_addr, SPX_D - 1); - set_layer_addr(wots_addr, SPX_D - 1); - - merkle_sign(auth_path, root, ctx, - wots_addr, top_tree_addr, - (uint32_t)~0 /* ~0 means "don't bother generating an auth path */ ); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/merkle.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/merkle.h deleted file mode 100644 index 769cf2e970..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/merkle.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef MERKLE_H_ -#define MERKLE_H_ - -#include - -#include "context.h" -#include "params.h" - -/* Generate a Merkle signature (WOTS signature followed by the Merkle */ -/* authentication path) */ -#define merkle_sign SPX_NAMESPACE(merkle_sign) -void merkle_sign(uint8_t *sig, unsigned char *root, - const spx_ctx *ctx, - uint32_t wots_addr[8], uint32_t tree_addr[8], - uint32_t idx_leaf); - -/* Compute the root node of the top-most subtree. */ -#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) -void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); - -#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/nistapi.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/nistapi.h deleted file mode 100644 index 3cb71afad4..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/nistapi.h +++ /dev/null @@ -1,87 +0,0 @@ -#ifndef SPX_API_H -#define SPX_API_H - -#include -#include - -#include "params.h" - -#define CRYPTO_ALGNAME "SPHINCS+" - -#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES -#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES -#define CRYPTO_BYTES SPX_BYTES -#define CRYPTO_SEEDBYTES (3*SPX_N) - -/* - * Returns the length of a secret key, in bytes - */ -#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) -size_t crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) -size_t crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) -size_t crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) -size_t crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) -int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) -int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) -int crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) -int crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -#define crypto_sign SPX_NAMESPACE(crypto_sign) -int crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) -int crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/params.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/params.h deleted file mode 100644 index 2ca67d3cf2..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/params.h +++ /dev/null @@ -1,56 +0,0 @@ -#ifndef SPX_PARAMS_H -#define SPX_PARAMS_H - -#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_##s - -/* Hash output length in bytes. */ -#define SPX_N 16 -/* Height of the hypertree. */ -#define SPX_FULL_HEIGHT 66 -/* Number of subtree layer. */ -#define SPX_D 22 -/* FORS tree dimensions. */ -#define SPX_FORS_HEIGHT 6 -#define SPX_FORS_TREES 33 -/* Winternitz parameter, */ -#define SPX_WOTS_W 16 - -/* The hash function is defined by linking a different hash.c file, as opposed - to setting a #define constant. */ - -/* For clarity */ -#define SPX_ADDR_BYTES 32 - -/* WOTS parameters. */ -#define SPX_WOTS_LOGW 4 - -#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) - -/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#define SPX_WOTS_LEN2 3 - -#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) -#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) -#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES - -/* Subtree size. */ -#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) - -//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT -// #error SPX_D should always divide SPX_FULL_HEIGHT -//#endif - -/* FORS parameters. */ -#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) -#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) -#define SPX_FORS_PK_BYTES SPX_N - -/* Resulting SPX sizes. */ -#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ - SPX_FULL_HEIGHT * SPX_N) -#define SPX_PK_BYTES (2 * SPX_N) -#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) - -#include "haraka_offsets.h" - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/sign.c b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/sign.c deleted file mode 100644 index 9d0c7d1b22..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/sign.c +++ /dev/null @@ -1,286 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "context.h" -#include "fors.h" -#include "hash.h" -#include "merkle.h" -#include "nistapi.h" -#include "params.h" -#include "randombytes.h" -#include "thash.h" -#include "utils.h" -#include "wots.h" - -/* - * Returns the length of a secret key, in bytes - */ -size_t crypto_sign_secretkeybytes(void) { - return CRYPTO_SECRETKEYBYTES; -} - -/* - * Returns the length of a public key, in bytes - */ -size_t crypto_sign_publickeybytes(void) { - return CRYPTO_PUBLICKEYBYTES; -} - -/* - * Returns the length of a signature, in bytes - */ -size_t crypto_sign_bytes(void) { - return CRYPTO_BYTES; -} - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t crypto_sign_seedbytes(void) { - return CRYPTO_SEEDBYTES; -} - -/* - * Generates an SPX key pair given a seed of length - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed) { - spx_ctx ctx; - - /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ - memcpy(sk, seed, CRYPTO_SEEDBYTES); - - memcpy(pk, sk + 2 * SPX_N, SPX_N); - - memcpy(ctx.pub_seed, pk, SPX_N); - memcpy(ctx.sk_seed, sk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - /* Compute root node of the top-most subtree. */ - merkle_gen_root(sk + 3 * SPX_N, &ctx); - - // cleanup - free_hash_function(&ctx); - - memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); - - return 0; -} - -/* - * Generates an SPX key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { - uint8_t seed[CRYPTO_SEEDBYTES]; - randombytes(seed, CRYPTO_SEEDBYTES); - crypto_sign_seed_keypair(pk, sk, seed); - - return 0; -} - -/** - * Returns an array containing a detached signature. - */ -int crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - spx_ctx ctx; - - const uint8_t *sk_prf = sk + SPX_N; - const uint8_t *pk = sk + 2 * SPX_N; - - uint8_t optrand[SPX_N]; - uint8_t mhash[SPX_FORS_MSG_BYTES]; - uint8_t root[SPX_N]; - uint32_t i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - - memcpy(ctx.sk_seed, sk, SPX_N); - memcpy(ctx.pub_seed, pk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - set_type(wots_addr, SPX_ADDR_TYPE_WOTS); - set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); - - /* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ - randombytes(optrand, SPX_N); - /* Compute the digest randomization value. */ - gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); - - /* Derive the message digest and leaf index from R, PK and M. */ - hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); - sig += SPX_N; - - set_tree_addr(wots_addr, tree); - set_keypair_addr(wots_addr, idx_leaf); - - /* Sign the message hash using FORS. */ - fors_sign(sig, root, mhash, &ctx, wots_addr); - sig += SPX_FORS_BYTES; - - for (i = 0; i < SPX_D; i++) { - set_layer_addr(tree_addr, i); - set_tree_addr(tree_addr, tree); - - copy_subtree_addr(wots_addr, tree_addr); - set_keypair_addr(wots_addr, idx_leaf); - - merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); - sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); - tree = tree >> SPX_TREE_HEIGHT; - } - - free_hash_function(&ctx); - - *siglen = SPX_BYTES; - - return 0; -} - -/** - * Verifies a detached signature and message under a given public key. - */ -int crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk) { - spx_ctx ctx; - const uint8_t *pub_root = pk + SPX_N; - uint8_t mhash[SPX_FORS_MSG_BYTES]; - uint8_t wots_pk[SPX_WOTS_BYTES]; - uint8_t root[SPX_N]; - uint8_t leaf[SPX_N]; - unsigned int i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - if (siglen != SPX_BYTES) { - return -1; - } - - memcpy(ctx.pub_seed, pk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - set_type(wots_addr, SPX_ADDR_TYPE_WOTS); - set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); - set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); - - /* Derive the message digest and leaf index from R || PK || M. */ - /* The additional SPX_N is a result of the hash domain separator. */ - hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); - sig += SPX_N; - - /* Layer correctly defaults to 0, so no need to set_layer_addr */ - set_tree_addr(wots_addr, tree); - set_keypair_addr(wots_addr, idx_leaf); - - fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); - sig += SPX_FORS_BYTES; - - /* For each subtree.. */ - for (i = 0; i < SPX_D; i++) { - set_layer_addr(tree_addr, i); - set_tree_addr(tree_addr, tree); - - copy_subtree_addr(wots_addr, tree_addr); - set_keypair_addr(wots_addr, idx_leaf); - - copy_keypair_addr(wots_pk_addr, wots_addr); - - /* The WOTS public key is only correct if the signature was correct. */ - /* Initially, root is the FORS pk, but on subsequent iterations it is - the root of the subtree below the currently processed subtree. */ - wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); - sig += SPX_WOTS_BYTES; - - /* Compute the leaf node using the WOTS public key. */ - thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); - - /* Compute the root node of this subtree. */ - compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, - &ctx, tree_addr); - sig += SPX_TREE_HEIGHT * SPX_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); - tree = tree >> SPX_TREE_HEIGHT; - } - - // cleanup - free_hash_function(&ctx); - - /* Check if the root node equals the root node in the public key. */ - if (memcmp(root, pub_root, SPX_N) != 0) { - return -1; - } - - return 0; -} - - -/** - * Returns an array containing the signature followed by the message. - */ -int crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk) { - size_t siglen; - - crypto_sign_signature(sm, &siglen, m, mlen, sk); - - memmove(sm + SPX_BYTES, m, mlen); - *smlen = siglen + mlen; - - return 0; -} - -/** - * Verifies a given signature-message pair under a given public key. - */ -int crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk) { - /* The API caller does not necessarily know what size a signature should be - but SPHINCS+ signatures are always exactly SPX_BYTES. */ - if (smlen < SPX_BYTES) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - *mlen = smlen - SPX_BYTES; - - if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - /* If verification was successful, move the message to the right place. */ - memmove(m, sm + SPX_BYTES, *mlen); - - return 0; -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/thash.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/thash.h deleted file mode 100644 index 8687ccfb4d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/thash.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef SPX_THASH_H -#define SPX_THASH_H - -#include "context.h" -#include "params.h" - -#include - -#define thash SPX_NAMESPACE(thash) -void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/thash_haraka_simple.c b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/thash_haraka_simple.c deleted file mode 100644 index 207777bf8d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/thash_haraka_simple.c +++ /dev/null @@ -1,36 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "thash.h" -#include "utils.h" - -#include "haraka.h" - -/** - * Takes an array of inblocks concatenated arrays of SPX_N bytes. - */ -void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]) { - PQCLEAN_VLA(uint8_t, buf, SPX_ADDR_BYTES + inblocks * SPX_N); - unsigned char outbuf[32]; - unsigned char buf_tmp[64]; - - if (inblocks == 1) { - /* F function */ - /* Since SPX_N may be smaller than 32, we need a temporary buffer. */ - memset(buf_tmp, 0, 64); - memcpy(buf_tmp, addr, 32); - memcpy(buf_tmp + SPX_ADDR_BYTES, in, SPX_N); - - haraka512(outbuf, buf_tmp, ctx); - memcpy(out, outbuf, SPX_N); - } else { - /* All other tweakable hashes*/ - memcpy(buf, addr, 32); - memcpy(buf + SPX_ADDR_BYTES, in, inblocks * SPX_N); - - haraka_S(out, SPX_N, buf, SPX_ADDR_BYTES + inblocks * SPX_N, ctx); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/utils.c b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/utils.c deleted file mode 100644 index 177b541fb9..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/utils.c +++ /dev/null @@ -1,148 +0,0 @@ -#include - -#include "utils.h" - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "thash.h" - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void ull_to_bytes(unsigned char *out, unsigned int outlen, - unsigned long long in) { - int i; - - /* Iterate over out in decreasing order, for big-endianness. */ - for (i = (signed int)outlen - 1; i >= 0; i--) { - out[i] = in & 0xff; - in = in >> 8; - } -} - -void u32_to_bytes(unsigned char *out, uint32_t in) { - out[0] = (unsigned char)(in >> 24); - out[1] = (unsigned char)(in >> 16); - out[2] = (unsigned char)(in >> 8); - out[3] = (unsigned char)in; -} - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { - unsigned long long retval = 0; - unsigned int i; - - for (i = 0; i < inlen; i++) { - retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); - } - return retval; -} - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void compute_root(unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const spx_ctx *ctx, uint32_t addr[8]) { - uint32_t i; - unsigned char buffer[2 * SPX_N]; - - /* If leaf_idx is odd (last bit = 1), current path element is a right child - and auth_path has to go left. Otherwise it is the other way around. */ - if (leaf_idx & 1) { - memcpy(buffer + SPX_N, leaf, SPX_N); - memcpy(buffer, auth_path, SPX_N); - } else { - memcpy(buffer, leaf, SPX_N); - memcpy(buffer + SPX_N, auth_path, SPX_N); - } - auth_path += SPX_N; - - for (i = 0; i < tree_height - 1; i++) { - leaf_idx >>= 1; - idx_offset >>= 1; - /* Set the address of the node we're creating. */ - set_tree_height(addr, i + 1); - set_tree_index(addr, leaf_idx + idx_offset); - - /* Pick the right or left neighbor, depending on parity of the node. */ - if (leaf_idx & 1) { - thash(buffer + SPX_N, buffer, 2, ctx, addr); - memcpy(buffer, auth_path, SPX_N); - } else { - thash(buffer, buffer, 2, ctx, addr); - memcpy(buffer + SPX_N, auth_path, SPX_N); - } - auth_path += SPX_N; - } - - /* The last iteration is exceptional; we do not copy an auth_path node. */ - leaf_idx >>= 1; - idx_offset >>= 1; - set_tree_height(addr, tree_height); - set_tree_index(addr, leaf_idx + idx_offset); - thash(root, buffer, 2, ctx, addr); -} - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const spx_ctx * /* ctx */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), - uint32_t tree_addr[8]) { - PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); - PQCLEAN_VLA(unsigned int, heights, tree_height + 1); - unsigned int offset = 0; - uint32_t idx; - uint32_t tree_idx; - - for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { - /* Add the next leaf node to the stack. */ - gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); - offset++; - heights[offset - 1] = 0; - - /* If this is a node we need for the auth path.. */ - if ((leaf_idx ^ 0x1) == idx) { - memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); - } - - /* While the top-most nodes are of equal height.. */ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { - /* Compute index of the new node, in the next layer. */ - tree_idx = (idx >> (heights[offset - 1] + 1)); - - /* Set the address of the node we're creating. */ - set_tree_height(tree_addr, heights[offset - 1] + 1); - set_tree_index(tree_addr, - tree_idx + (idx_offset >> (heights[offset - 1] + 1))); - /* Hash the top-most nodes from the stack together. */ - thash(stack + (offset - 2)*SPX_N, - stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); - offset--; - /* Note that the top-most node is now one layer higher. */ - heights[offset - 1]++; - - /* If this is a node we need for the auth path.. */ - if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_path + heights[offset - 1]*SPX_N, - stack + (offset - 1)*SPX_N, SPX_N); - } - } - } - memcpy(root, stack, SPX_N); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/utils.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/utils.h deleted file mode 100644 index 64f5d5a53a..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/utils.h +++ /dev/null @@ -1,58 +0,0 @@ -#ifndef SPX_UTILS_H -#define SPX_UTILS_H - -#include - -#include "compat.h" -#include "context.h" -#include "params.h" - - -/* To support MSVC use alloca() instead of VLAs. See #20. */ - - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) -void ull_to_bytes(unsigned char *out, unsigned int outlen, - unsigned long long in); -#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) -void u32_to_bytes(unsigned char *out, uint32_t in); - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) -unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -#define compute_root SPX_NAMESPACE(compute_root) -void compute_root(unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const spx_ctx *ctx, uint32_t addr[8]); - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -#define treehash SPX_NAMESPACE(treehash) -void treehash(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const spx_ctx *ctx /* ctx */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), - uint32_t tree_addr[8]); - - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/utilsx1.c b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/utilsx1.c deleted file mode 100644 index fccb69b35d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/utilsx1.c +++ /dev/null @@ -1,100 +0,0 @@ -#include - -#include "utilsx1.h" - -#include "address.h" -#include "params.h" -#include "thash.h" -#include "utils.h" - -/* - * Generate the entire Merkle tree, computing the authentication path for - * leaf_idx, and the resulting root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) - * - * This expects tree_addr to be initialized to the addr structures for the - * Merkle tree nodes - * - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - * - * This works by using the standard Merkle tree building algorithm, - */ -void treehashx1(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, - uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* Where to write the leaves */, - const spx_ctx * /* ctx */, - uint32_t idx, void *info), - uint32_t tree_addr[8], - void *info) { - /* This is where we keep the intermediate nodes */ - PQCLEAN_VLA(uint8_t, stack, tree_height * SPX_N); - - uint32_t idx; - uint32_t max_idx = (uint32_t)((1 << tree_height) - 1); - for (idx = 0;; idx++) { - unsigned char current[2 * SPX_N]; /* Current logical node is at */ - /* index[SPX_N]. We do this to minimize the number of copies */ - /* needed during a thash */ - gen_leaf( ¤t[SPX_N], ctx, idx + idx_offset, - info ); - - /* Now combine the freshly generated right node with previously */ - /* generated left ones */ - uint32_t internal_idx_offset = idx_offset; - uint32_t internal_idx = idx; - uint32_t internal_leaf = leaf_idx; - uint32_t h; /* The height we are in the Merkle tree */ - for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { - - /* Check if we hit the top of the tree */ - if (h == tree_height) { - /* We hit the root; return it */ - memcpy( root, ¤t[SPX_N], SPX_N ); - return; - } - - /* - * Check if the node we have is a part of the - * authentication path; if it is, write it out - */ - if ((internal_idx ^ internal_leaf) == 0x01) { - memcpy( &auth_path[ h * SPX_N ], - ¤t[SPX_N], - SPX_N ); - } - - /* - * Check if we're at a left child; if so, stop going up the stack - * Exception: if we've reached the end of the tree, keep on going - * (so we combine the last 4 nodes into the one root node in two - * more iterations) - */ - if ((internal_idx & 1) == 0 && idx < max_idx) { - break; - } - - /* Ok, we're at a right node */ - /* Now combine the left and right logical nodes together */ - - /* Set the address of the node we're creating. */ - internal_idx_offset >>= 1; - set_tree_height(tree_addr, h + 1); - set_tree_index(tree_addr, internal_idx / 2 + internal_idx_offset ); - - unsigned char *left = &stack[h * SPX_N]; - memcpy( ¤t[0], left, SPX_N ); - thash( ¤t[1 * SPX_N], - ¤t[0 * SPX_N], - 2, ctx, tree_addr); - } - - /* We've hit a left child; save the current for when we get the */ - /* corresponding right right */ - memcpy( &stack[h * SPX_N], ¤t[SPX_N], SPX_N); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/utilsx1.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/utilsx1.h deleted file mode 100644 index e911d17d53..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/utilsx1.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef SPX_UTILSX4_H -#define SPX_UTILSX4_H - -#include - -#include "context.h" -#include "params.h" - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -#define treehashx1 SPX_NAMESPACE(treehashx1) -void treehashx1(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* Where to write the leaf */, - const spx_ctx * /* ctx */, - uint32_t addr_idx, void *info), - uint32_t tree_addrx4[8], void *info); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/wots.c b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/wots.c deleted file mode 100644 index 249717aaa8..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/wots.c +++ /dev/null @@ -1,108 +0,0 @@ -#include -#include - -#include "wots.h" -#include "wotsx1.h" - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "thash.h" -#include "utils.h" -#include "utilsx1.h" - -// TODO clarify address expectations, and make them more uniform. -// TODO i.e. do we expect types to be set already? -// TODO and do we expect modifications or copies? - -/** - * Computes the chaining function. - * out and in have to be n-byte arrays. - * - * Interprets in as start-th value of the chain. - * addr has to contain the address of the chain. - */ -static void gen_chain(unsigned char *out, const unsigned char *in, - unsigned int start, unsigned int steps, - const spx_ctx *ctx, uint32_t addr[8]) { - uint32_t i; - - /* Initialize out with the value at position 'start'. */ - memcpy(out, in, SPX_N); - - /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < SPX_WOTS_W; i++) { - set_hash_addr(addr, i); - thash(out, out, 1, ctx, addr); - } -} - -/** - * base_w algorithm as described in draft. - * Interprets an array of bytes as integers in base w. - * This only works when log_w is a divisor of 8. - */ -static void base_w(unsigned int *output, const int out_len, - const unsigned char *input) { - int in = 0; - int out = 0; - unsigned char total = 0; - int bits = 0; - int consumed; - - for (consumed = 0; consumed < out_len; consumed++) { - if (bits == 0) { - total = input[in]; - in++; - bits += 8; - } - bits -= SPX_WOTS_LOGW; - output[out] = (total >> bits) & (SPX_WOTS_W - 1); - out++; - } -} - -/* Computes the WOTS+ checksum over a message (in base_w). */ -static void wots_checksum(unsigned int *csum_base_w, - const unsigned int *msg_base_w) { - unsigned int csum = 0; - unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; - unsigned int i; - - /* Compute checksum. */ - for (i = 0; i < SPX_WOTS_LEN1; i++) { - csum += SPX_WOTS_W - 1 - msg_base_w[i]; - } - - /* Convert checksum to base_w. */ - /* Make sure expected empty zero bits are the least significant bits. */ - csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); - ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); - base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); -} - -/* Takes a message and derives the matching chain lengths. */ -void chain_lengths(unsigned int *lengths, const unsigned char *msg) { - base_w(lengths, SPX_WOTS_LEN1, msg); - wots_checksum(lengths + SPX_WOTS_LEN1, lengths); -} - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const spx_ctx *ctx, uint32_t addr[8]) { - unsigned int lengths[SPX_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < SPX_WOTS_LEN; i++) { - set_chain_addr(addr, i); - gen_chain(pk + i * SPX_N, sig + i * SPX_N, - lengths[i], SPX_WOTS_W - 1 - lengths[i], ctx, addr); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/wots.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/wots.h deleted file mode 100644 index 4e7692eeef..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/wots.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef SPX_WOTS_H -#define SPX_WOTS_H - -#include - -#include "context.h" -#include "params.h" - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) -void wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const spx_ctx *ctx, uint32_t addr[8]); - -/* - * Compute the chain lengths needed for a given message hash - */ -#define chain_lengths SPX_NAMESPACE(chain_lengths) -void chain_lengths(unsigned int *lengths, const unsigned char *msg); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/wotsx1.c b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/wotsx1.c deleted file mode 100644 index 3adec78dfb..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/wotsx1.c +++ /dev/null @@ -1,76 +0,0 @@ -#include -#include - -#include "wots.h" -#include "wotsx1.h" - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "thash.h" -#include "utils.h" - -/* - * This generates a WOTS public key - * It also generates the WOTS signature if leaf_info indicates - * that we're signing with this WOTS key - */ -void wots_gen_leafx1(unsigned char *dest, - const spx_ctx *ctx, - uint32_t leaf_idx, void *v_info) { - struct leaf_info_x1 *info = v_info; - uint32_t *leaf_addr = info->leaf_addr; - uint32_t *pk_addr = info->pk_addr; - unsigned int i, k; - unsigned char pk_buffer[ SPX_WOTS_BYTES ]; - unsigned char *buffer; - uint32_t wots_k_mask; - - if (leaf_idx == info->wots_sign_leaf) { - /* We're traversing the leaf that's signing; generate the WOTS */ - /* signature */ - wots_k_mask = 0; - } else { - /* Nope, we're just generating pk's; turn off the signature logic */ - wots_k_mask = (uint32_t)~0; - } - - set_keypair_addr( leaf_addr, leaf_idx ); - set_keypair_addr( pk_addr, leaf_idx ); - - for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { - uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k to */ - /* the step if we're generating a signature, ~0 if we're not */ - - /* Start with the secret seed */ - set_chain_addr(leaf_addr, i); - set_hash_addr(leaf_addr, 0); - set_type(leaf_addr, SPX_ADDR_TYPE_WOTSPRF); - - prf_addr(buffer, ctx, leaf_addr); - - set_type(leaf_addr, SPX_ADDR_TYPE_WOTS); - - /* Iterate down the WOTS chain */ - for (k = 0;; k++) { - /* Check if this is the value that needs to be saved as a */ - /* part of the WOTS signature */ - if (k == wots_k) { - memcpy( info->wots_sig + i * SPX_N, buffer, SPX_N ); - } - - /* Check if we hit the top of the chain */ - if (k == SPX_WOTS_W - 1) { - break; - } - - /* Iterate one step on the chain */ - set_hash_addr(leaf_addr, k); - - thash(buffer, buffer, 1, ctx, leaf_addr); - } - } - - /* Do the final thash to generate the public keys */ - thash(dest, pk_buffer, SPX_WOTS_LEN, ctx, pk_addr); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/wotsx1.h b/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/wotsx1.h deleted file mode 100644 index e617929f96..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128f-simple_clean/wotsx1.h +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef WOTSX1_H_ -#define WOTSX1_H_ - -#include - -#include "context.h" -#include "params.h" - -/* - * This is here to provide an interface to the internal wots_gen_leafx1 - * routine. While this routine is not referenced in the package outside of - * wots.c, it is called from the stand-alone benchmark code to characterize - * the performance - */ -struct leaf_info_x1 { - unsigned char *wots_sig; - uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ - uint32_t *wots_steps; - uint32_t leaf_addr[8]; - uint32_t pk_addr[8]; -}; - -/* Macro to set the leaf_info to something 'benign', that is, it would */ -/* run with the same time as it does during the real signing process */ -/* Used only by the benchmark code */ -#define INITIALIZE_LEAF_INFO_X1(info, addr, step_buffer) { \ - (info).wots_sig = 0; \ - (info).wots_sign_leaf = ~0; \ - (info).wots_steps = step_buffer; \ - memcpy( &(info).leaf_addr[0], (addr), 32 ); \ - memcpy( &(info).pk_addr[0], (addr), 32 ); \ - } - -#define wots_gen_leafx1 SPX_NAMESPACE(wots_gen_leafx1) -void wots_gen_leafx1(unsigned char *dest, - const spx_ctx *ctx, - uint32_t leaf_idx, void *v_info); - -#endif /* WOTSX1_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/LICENSE b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/LICENSE deleted file mode 100644 index 670154e353..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/LICENSE +++ /dev/null @@ -1,116 +0,0 @@ -CC0 1.0 Universal - -Statement of Purpose - -The laws of most jurisdictions throughout the world automatically confer -exclusive Copyright and Related Rights (defined below) upon the creator and -subsequent owner(s) (each and all, an "owner") of an original work of -authorship and/or a database (each, a "Work"). - -Certain owners wish to permanently relinquish those rights to a Work for the -purpose of contributing to a commons of creative, cultural and scientific -works ("Commons") that the public can reliably and without fear of later -claims of infringement build upon, modify, incorporate in other works, reuse -and redistribute as freely as possible in any form whatsoever and for any -purposes, including without limitation commercial purposes. These owners may -contribute to the Commons to promote the ideal of a free culture and the -further production of creative, cultural and scientific works, or to gain -reputation or greater distribution for their Work in part through the use and -efforts of others. - -For these and/or other purposes and motivations, and without any expectation -of additional consideration or compensation, the person associating CC0 with a -Work (the "Affirmer"), to the extent that he or she is an owner of Copyright -and Related Rights in the Work, voluntarily elects to apply CC0 to the Work -and publicly distribute the Work under its terms, with knowledge of his or her -Copyright and Related Rights in the Work and the meaning and intended legal -effect of CC0 on those rights. - -1. Copyright and Related Rights. A Work made available under CC0 may be -protected by copyright and related or neighboring rights ("Copyright and -Related Rights"). Copyright and Related Rights include, but are not limited -to, the following: - - i. the right to reproduce, adapt, distribute, perform, display, communicate, - and translate a Work; - - ii. moral rights retained by the original author(s) and/or performer(s); - - iii. publicity and privacy rights pertaining to a person's image or likeness - depicted in a Work; - - iv. rights protecting against unfair competition in regards to a Work, - subject to the limitations in paragraph 4(a), below; - - v. rights protecting the extraction, dissemination, use and reuse of data in - a Work; - - vi. database rights (such as those arising under Directive 96/9/EC of the - European Parliament and of the Council of 11 March 1996 on the legal - protection of databases, and under any national implementation thereof, - including any amended or successor version of such directive); and - - vii. other similar, equivalent or corresponding rights throughout the world - based on applicable law or treaty, and any national implementations thereof. - -2. Waiver. To the greatest extent permitted by, but not in contravention of, -applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and -unconditionally waives, abandons, and surrenders all of Affirmer's Copyright -and Related Rights and associated claims and causes of action, whether now -known or unknown (including existing as well as future claims and causes of -action), in the Work (i) in all territories worldwide, (ii) for the maximum -duration provided by applicable law or treaty (including future time -extensions), (iii) in any current or future medium and for any number of -copies, and (iv) for any purpose whatsoever, including without limitation -commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes -the Waiver for the benefit of each member of the public at large and to the -detriment of Affirmer's heirs and successors, fully intending that such Waiver -shall not be subject to revocation, rescission, cancellation, termination, or -any other legal or equitable action to disrupt the quiet enjoyment of the Work -by the public as contemplated by Affirmer's express Statement of Purpose. - -3. Public License Fallback. Should any part of the Waiver for any reason be -judged legally invalid or ineffective under applicable law, then the Waiver -shall be preserved to the maximum extent permitted taking into account -Affirmer's express Statement of Purpose. In addition, to the extent the Waiver -is so judged Affirmer hereby grants to each affected person a royalty-free, -non transferable, non sublicensable, non exclusive, irrevocable and -unconditional license to exercise Affirmer's Copyright and Related Rights in -the Work (i) in all territories worldwide, (ii) for the maximum duration -provided by applicable law or treaty (including future time extensions), (iii) -in any current or future medium and for any number of copies, and (iv) for any -purpose whatsoever, including without limitation commercial, advertising or -promotional purposes (the "License"). The License shall be deemed effective as -of the date CC0 was applied by Affirmer to the Work. Should any part of the -License for any reason be judged legally invalid or ineffective under -applicable law, such partial invalidity or ineffectiveness shall not -invalidate the remainder of the License, and in such case Affirmer hereby -affirms that he or she will not (i) exercise any of his or her remaining -Copyright and Related Rights in the Work or (ii) assert any associated claims -and causes of action with respect to the Work, in either case contrary to -Affirmer's express Statement of Purpose. - -4. Limitations and Disclaimers. - - a. No trademark or patent rights held by Affirmer are waived, abandoned, - surrendered, licensed or otherwise affected by this document. - - b. Affirmer offers the Work as-is and makes no representations or warranties - of any kind concerning the Work, express, implied, statutory or otherwise, - including without limitation warranties of title, merchantability, fitness - for a particular purpose, non infringement, or the absence of latent or - other defects, accuracy, or the present or absence of errors, whether or not - discoverable, all to the greatest extent permissible under applicable law. - - c. Affirmer disclaims responsibility for clearing rights of other persons - that may apply to the Work or any use thereof, including without limitation - any person's Copyright and Related Rights in the Work. Further, Affirmer - disclaims responsibility for obtaining any necessary consents, permissions - or other rights required for any use of the Work. - - d. Affirmer understands and acknowledges that Creative Commons is not a - party to this document and has no duty or obligation with respect to this - CC0 or use of the Work. - -For more information, please see - diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/address.c b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/address.c deleted file mode 100644 index d49d9f3b6b..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/address.c +++ /dev/null @@ -1,95 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "utils.h" - -/* - * Specify which level of Merkle tree (the "layer") we're working on - */ -void set_layer_addr(uint32_t addr[8], uint32_t layer) { - ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; -} - -/* - * Specify which Merkle tree within the level (the "tree address") we're working on - */ -void set_tree_addr(uint32_t addr[8], uint64_t tree) { - ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); -} - -/* - * Specify the reason we'll use this address structure for, that is, what - * hash will we compute with it. This is used so that unrelated types of - * hashes don't accidentally get the same address structure. The type will be - * one of the SPX_ADDR_TYPE constants - */ -void set_type(uint32_t addr[8], uint32_t type) { - ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; -} - -/* - * Copy the layer and tree fields of the address structure. This is used - * when we're doing multiple types of hashes within the same Merkle tree - */ -void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { - memcpy( out, in, SPX_OFFSET_TREE + 8 ); -} - -/* These functions are used for OTS addresses. */ - -/* - * Specify which Merkle leaf we're working on; that is, which OTS keypair - * we're talking about. - */ -void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { - /* We have > 256 OTS at the bottom of the Merkle tree; to specify */ - /* which one, we'd need to express it in two bytes */ - ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR2] = (unsigned char)(keypair >> 8); - ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; -} - -/* - * Copy the layer, tree and keypair fields of the address structure. This is - * used when we're doing multiple things within the same OTS keypair - */ -void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { - memcpy( out, in, SPX_OFFSET_TREE + 8 ); - ((unsigned char *)out)[SPX_OFFSET_KP_ADDR2] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR2]; - ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; -} - -/* - * Specify which Merkle chain within the OTS we're working with - * (the chain address) - */ -void set_chain_addr(uint32_t addr[8], uint32_t chain) { - ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; -} - -/* - * Specify where in the Merkle chain we are -* (the hash address) - */ -void set_hash_addr(uint32_t addr[8], uint32_t hash) { - ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; -} - -/* These functions are used for all hash tree addresses (including FORS). */ - -/* - * Specify the height of the node in the Merkle/FORS tree we are in - * (the tree height) - */ -void set_tree_height(uint32_t addr[8], uint32_t tree_height) { - ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; -} - -/* - * Specify the distance from the left edge of the node in the Merkle/FORS tree - * (the tree index) - */ -void set_tree_index(uint32_t addr[8], uint32_t tree_index) { - u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/address.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/address.h deleted file mode 100644 index 24a84eb40c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/address.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef SPX_ADDRESS_H -#define SPX_ADDRESS_H - -#include - -#include "params.h" - -/* The hash types that are passed to set_type */ -#define SPX_ADDR_TYPE_WOTS 0 -#define SPX_ADDR_TYPE_WOTSPK 1 -#define SPX_ADDR_TYPE_HASHTREE 2 -#define SPX_ADDR_TYPE_FORSTREE 3 -#define SPX_ADDR_TYPE_FORSPK 4 -#define SPX_ADDR_TYPE_WOTSPRF 5 -#define SPX_ADDR_TYPE_FORSPRF 6 - -#define set_layer_addr SPX_NAMESPACE(set_layer_addr) -void set_layer_addr(uint32_t addr[8], uint32_t layer); - -#define set_tree_addr SPX_NAMESPACE(set_tree_addr) -void set_tree_addr(uint32_t addr[8], uint64_t tree); - -#define set_type SPX_NAMESPACE(set_type) -void set_type(uint32_t addr[8], uint32_t type); - -/* Copies the layer and tree part of one address into the other */ -#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) -void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for WOTS and FORS addresses. */ - -#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) -void set_keypair_addr(uint32_t addr[8], uint32_t keypair); - -#define set_chain_addr SPX_NAMESPACE(set_chain_addr) -void set_chain_addr(uint32_t addr[8], uint32_t chain); - -#define set_hash_addr SPX_NAMESPACE(set_hash_addr) -void set_hash_addr(uint32_t addr[8], uint32_t hash); - -#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) -void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for all hash tree addresses (including FORS). */ - -#define set_tree_height SPX_NAMESPACE(set_tree_height) -void set_tree_height(uint32_t addr[8], uint32_t tree_height); - -#define set_tree_index SPX_NAMESPACE(set_tree_index) -void set_tree_index(uint32_t addr[8], uint32_t tree_index); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/api.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/api.h deleted file mode 100644 index 4c0ed0f9f3..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/api.h +++ /dev/null @@ -1,77 +0,0 @@ -#ifndef PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_API_H -#define PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_API_H - -#include -#include - -#define PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_CRYPTO_ALGNAME "SPHINCS+-haraka-128s-robust" - -#define PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_CRYPTO_SECRETKEYBYTES 64 -#define PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_CRYPTO_PUBLICKEYBYTES 32 -#define PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_CRYPTO_BYTES 7856 - -#define PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_CRYPTO_SEEDBYTES 48 - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, - const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk); -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/context.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/context.h deleted file mode 100644 index f03446b9cb..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/context.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef SPX_CONTEXT_H -#define SPX_CONTEXT_H - -#include - -#include "immintrin.h" -#include "params.h" - -typedef struct { - uint8_t pub_seed[SPX_N]; - uint8_t sk_seed[SPX_N]; - - __m128i rc[40]; -} spx_ctx; - -#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) -void initialize_hash_function(spx_ctx *ctx); - -#define free_hash_function SPX_NAMESPACE(free_hash_function) -void free_hash_function(spx_ctx *ctx); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/context_haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/context_haraka.c deleted file mode 100644 index f1cd7e3664..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/context_haraka.c +++ /dev/null @@ -1,11 +0,0 @@ -#include "context.h" -#include "haraka.h" - -void initialize_hash_function(spx_ctx *ctx) { - tweak_constants(ctx); -} - -// we don't support heap-based haraka right now -void free_hash_function(spx_ctx *ctx) { - (void)ctx; // suppress unused variable warnings -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/fors.c b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/fors.c deleted file mode 100644 index f1b0639cfc..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/fors.c +++ /dev/null @@ -1,202 +0,0 @@ -#include -#include -#include - -#include "fors.h" - -#include "address.h" -#include "hash.h" -#include "hashx4.h" -#include "thash.h" -#include "thashx4.h" -#include "utils.h" -#include "utilsx4.h" - -static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, - uint32_t fors_leaf_addr[8]) { - prf_addr(sk, ctx, fors_leaf_addr); -} - -static void fors_gen_skx4(unsigned char *sk0, - unsigned char *sk1, - unsigned char *sk2, - unsigned char *sk3, const spx_ctx *ctx, - uint32_t fors_leaf_addrx4[4 * 8]) { - prf_addrx4(sk0, sk1, sk2, sk3, - ctx, fors_leaf_addrx4); -} - -static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, - const spx_ctx *ctx, - uint32_t fors_leaf_addr[8]) { - thash(leaf, sk, 1, ctx, fors_leaf_addr); -} - -static void fors_sk_to_leafx4(unsigned char *leaf0, - unsigned char *leaf1, - unsigned char *leaf2, - unsigned char *leaf3, - const unsigned char *sk0, - const unsigned char *sk1, - const unsigned char *sk2, - const unsigned char *sk3, - const spx_ctx *ctx, - uint32_t fors_leaf_addrx4[4 * 8]) { - thashx4(leaf0, leaf1, leaf2, leaf3, - sk0, sk1, sk2, sk3, - 1, ctx, fors_leaf_addrx4); -} - -struct fors_gen_leaf_info { - uint32_t leaf_addrx[4 * 8]; -}; - -static void fors_gen_leafx4(unsigned char *leaf, - const spx_ctx *ctx, - uint32_t addr_idx, void *info) { - struct fors_gen_leaf_info *fors_info = info; - uint32_t *fors_leaf_addrx4 = fors_info->leaf_addrx; - unsigned int j; - - /* Only set the parts that the caller doesn't set */ - for (j = 0; j < 4; j++) { - set_tree_index(fors_leaf_addrx4 + j * 8, addr_idx + j); - set_type(fors_leaf_addrx4 + j * 8, SPX_ADDR_TYPE_FORSPRF); - } - - fors_gen_skx4(leaf + 0 * SPX_N, - leaf + 1 * SPX_N, - leaf + 2 * SPX_N, - leaf + 3 * SPX_N, - ctx, fors_leaf_addrx4); - - for (j = 0; j < 4; j++) { - set_type(fors_leaf_addrx4 + j * 8, SPX_ADDR_TYPE_FORSTREE); - } - - fors_sk_to_leafx4(leaf + 0 * SPX_N, - leaf + 1 * SPX_N, - leaf + 2 * SPX_N, - leaf + 3 * SPX_N, - leaf + 0 * SPX_N, - leaf + 1 * SPX_N, - leaf + 2 * SPX_N, - leaf + 3 * SPX_N, - ctx, fors_leaf_addrx4); -} - -/** - * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - * Assumes indices has space for SPX_FORS_TREES integers. - */ -static void message_to_indices(uint32_t *indices, const unsigned char *m) { - unsigned int i, j; - unsigned int offset = 0; - - for (i = 0; i < SPX_FORS_TREES; i++) { - indices[i] = 0; - for (j = 0; j < SPX_FORS_HEIGHT; j++) { - indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); - offset++; - } - } -} - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -void fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]) { - uint32_t indices[SPX_FORS_TREES]; - unsigned char roots[SPX_FORS_TREES * SPX_N]; - uint32_t fors_tree_addr[4 * 8] = {0}; - struct fors_gen_leaf_info fors_info = {0}; - uint32_t *fors_leaf_addr = fors_info.leaf_addrx; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - for (i = 0; i < 4; i++) { - copy_keypair_addr(fors_tree_addr + 8 * i, fors_addr); - set_type(fors_tree_addr + 8 * i, SPX_ADDR_TYPE_FORSTREE); - copy_keypair_addr(fors_leaf_addr + 8 * i, fors_addr); - } - copy_keypair_addr(fors_pk_addr, fors_addr); - set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < SPX_FORS_TREES; i++) { - idx_offset = i * (1 << SPX_FORS_HEIGHT); - - set_tree_height(fors_tree_addr, 0); - set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Include the secret key part that produces the selected leaf node. */ - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); - fors_gen_sk(sig, ctx, fors_tree_addr); - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); - sig += SPX_N; - - /* Compute the authentication path for this leaf node. */ - treehashx4(roots + i * SPX_N, sig, ctx, - indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx4, - fors_tree_addr, &fors_info); - - sig += SPX_N * SPX_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); -} - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -void fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]) { - uint32_t indices[SPX_FORS_TREES]; - unsigned char roots[SPX_FORS_TREES * SPX_N]; - unsigned char leaf[SPX_N]; - uint32_t fors_tree_addr[8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - copy_keypair_addr(fors_tree_addr, fors_addr); - copy_keypair_addr(fors_pk_addr, fors_addr); - - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); - set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < SPX_FORS_TREES; i++) { - idx_offset = i * (1 << SPX_FORS_HEIGHT); - - set_tree_height(fors_tree_addr, 0); - set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Derive the leaf from the included secret key part. */ - fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); - sig += SPX_N; - - /* Derive the corresponding root node of this tree. */ - compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, - sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); - sig += SPX_N * SPX_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/fors.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/fors.h deleted file mode 100644 index 509140a178..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/fors.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef SPX_FORS_H -#define SPX_FORS_H - -#include - -#include "context.h" -#include "params.h" - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -#define fors_sign SPX_NAMESPACE(fors_sign) -void fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]); - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) -void fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/haraka.c deleted file mode 100644 index b414b691d7..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/haraka.c +++ /dev/null @@ -1,702 +0,0 @@ -/* -Plain C implementation of the Haraka256 and Haraka512 permutations. -*/ -#include -#include -#include -#include -#include - -#include "haraka.h" -#include "harakax4.h" -#include "utils.h" - -#define HARAKAS_RATE 32 - -#define u64 unsigned long -#define u128 __m128i - -#define LOAD(src) _mm_loadu_si128((u128 *)(src)) -#define STORE(dest,src) _mm_storeu_si128((u128 *)(dest),src) - -#define XOR128(a, b) _mm_xor_si128(a, b) - -#define AES2(s0, s1, rci) \ - s0 = _mm_aesenc_si128(s0, *(rci)); \ - (s1) = _mm_aesenc_si128(s1, *((rci) + 1)); \ - (s0) = _mm_aesenc_si128(s0, *((rci) + 2)); \ - (s1) = _mm_aesenc_si128(s1, *((rci) + 3)); - -#define AES2_4x(s0, s1, s2, s3, rci) \ - AES2((s0)[0], (s0)[1], rci); \ - AES2((s1)[0], (s1)[1], rci); \ - AES2((s2)[0], (s2)[1], rci); \ - AES2((s3)[0], (s3)[1], rci); - -#define AES4(s0, s1, s2, s3, rci) \ - s0 = _mm_aesenc_si128(s0, *(rci)); \ - (s1) = _mm_aesenc_si128(s1, *((rci) + 1)); \ - (s2) = _mm_aesenc_si128(s2, *((rci) + 2)); \ - (s3) = _mm_aesenc_si128(s3, *((rci) + 3)); \ - (s0) = _mm_aesenc_si128(s0, *((rci) + 4)); \ - (s1) = _mm_aesenc_si128(s1, *((rci) + 5)); \ - (s2) = _mm_aesenc_si128(s2, *((rci) + 6)); \ - (s3) = _mm_aesenc_si128(s3, *((rci) + 7)); - -#define AES4_4x(s0, s1, s2, s3, rci) \ - AES4((s0)[0], (s0)[1], (s0)[2], (s0)[3], rci); \ - AES4((s1)[0], (s1)[1], (s1)[2], (s1)[3], rci); \ - AES4((s2)[0], (s2)[1], (s2)[2], (s2)[3], rci); \ - AES4((s3)[0], (s3)[1], (s3)[2], (s3)[3], rci); - -#define MIX2(s0, s1) \ - tmp = _mm_unpacklo_epi32(s0, s1); \ - (s1) = _mm_unpackhi_epi32(s0, s1); \ - (s0) = tmp; - -#define MIX4(s0, s1, s2, s3) \ - tmp = _mm_unpacklo_epi32(s0, s1); \ - (s0) = _mm_unpackhi_epi32(s0, s1); \ - (s1) = _mm_unpacklo_epi32(s2, s3); \ - (s2) = _mm_unpackhi_epi32(s2, s3); \ - (s3) = _mm_unpacklo_epi32(s0, s2); \ - (s0) = _mm_unpackhi_epi32(s0, s2); \ - (s2) = _mm_unpackhi_epi32(s1, tmp); \ - (s1) = _mm_unpacklo_epi32(s1, tmp); - -#define TRUNCSTORE(out, s0, s1, s2, s3) \ - _mm_storeu_si128((u128 *)(out), \ - _mm_castpd_si128(_mm_shuffle_pd(_mm_castsi128_pd(s0), _mm_castsi128_pd(s1), 3))); \ - _mm_storeu_si128((u128 *)((out) + 16), \ - _mm_castpd_si128(_mm_shuffle_pd(_mm_castsi128_pd(s2), _mm_castsi128_pd(s3), 0))); - -static void load_haraka_constants(u128 *rc) { - rc[0] = _mm_set_epi32((int)0x0684704c, (int)0xe620c00a, (int)0xb2c5fef0, (int)0x75817b9d); - rc[1] = _mm_set_epi32((int)0x8b66b4e1, (int)0x88f3a06b, (int)0x640f6ba4, (int)0x2f08f717); - rc[2] = _mm_set_epi32((int)0x3402de2d, (int)0x53f28498, (int)0xcf029d60, (int)0x9f029114); - rc[3] = _mm_set_epi32((int)0x0ed6eae6, (int)0x2e7b4f08, (int)0xbbf3bcaf, (int)0xfd5b4f79); - rc[4] = _mm_set_epi32((int)0xcbcfb0cb, (int)0x4872448b, (int)0x79eecd1c, (int)0xbe397044); - rc[5] = _mm_set_epi32((int)0x7eeacdee, (int)0x6e9032b7, (int)0x8d5335ed, (int)0x2b8a057b); - rc[6] = _mm_set_epi32((int)0x67c28f43, (int)0x5e2e7cd0, (int)0xe2412761, (int)0xda4fef1b); - rc[7] = _mm_set_epi32((int)0x2924d9b0, (int)0xafcacc07, (int)0x675ffde2, (int)0x1fc70b3b); - rc[8] = _mm_set_epi32((int)0xab4d63f1, (int)0xe6867fe9, (int)0xecdb8fca, (int)0xb9d465ee); - rc[9] = _mm_set_epi32((int)0x1c30bf84, (int)0xd4b7cd64, (int)0x5b2a404f, (int)0xad037e33); - rc[10] = _mm_set_epi32((int)0xb2cc0bb9, (int)0x941723bf, (int)0x69028b2e, (int)0x8df69800); - rc[11] = _mm_set_epi32((int)0xfa0478a6, (int)0xde6f5572, (int)0x4aaa9ec8, (int)0x5c9d2d8a); - rc[12] = _mm_set_epi32((int)0xdfb49f2b, (int)0x6b772a12, (int)0x0efa4f2e, (int)0x29129fd4); - rc[13] = _mm_set_epi32((int)0x1ea10344, (int)0xf449a236, (int)0x32d611ae, (int)0xbb6a12ee); - rc[14] = _mm_set_epi32((int)0xaf044988, (int)0x4b050084, (int)0x5f9600c9, (int)0x9ca8eca6); - rc[15] = _mm_set_epi32((int)0x21025ed8, (int)0x9d199c4f, (int)0x78a2c7e3, (int)0x27e593ec); - rc[16] = _mm_set_epi32((int)0xbf3aaaf8, (int)0xa759c9b7, (int)0xb9282ecd, (int)0x82d40173); - rc[17] = _mm_set_epi32((int)0x6260700d, (int)0x6186b017, (int)0x37f2efd9, (int)0x10307d6b); - rc[18] = _mm_set_epi32((int)0x5aca45c2, (int)0x21300443, (int)0x81c29153, (int)0xf6fc9ac6); - rc[19] = _mm_set_epi32((int)0x9223973c, (int)0x226b68bb, (int)0x2caf92e8, (int)0x36d1943a); - rc[20] = _mm_set_epi32((int)0xd3bf9238, (int)0x225886eb, (int)0x6cbab958, (int)0xe51071b4); - rc[21] = _mm_set_epi32((int)0xdb863ce5, (int)0xaef0c677, (int)0x933dfddd, (int)0x24e1128d); - rc[22] = _mm_set_epi32((int)0xbb606268, (int)0xffeba09c, (int)0x83e48de3, (int)0xcb2212b1); - rc[23] = _mm_set_epi32((int)0x734bd3dc, (int)0xe2e4d19c, (int)0x2db91a4e, (int)0xc72bf77d); - rc[24] = _mm_set_epi32((int)0x43bb47c3, (int)0x61301b43, (int)0x4b1415c4, (int)0x2cb3924e); - rc[25] = _mm_set_epi32((int)0xdba775a8, (int)0xe707eff6, (int)0x03b231dd, (int)0x16eb6899); - rc[26] = _mm_set_epi32((int)0x6df3614b, (int)0x3c755977, (int)0x8e5e2302, (int)0x7eca472c); - rc[27] = _mm_set_epi32((int)0xcda75a17, (int)0xd6de7d77, (int)0x6d1be5b9, (int)0xb88617f9); - rc[28] = _mm_set_epi32((int)0xec6b43f0, (int)0x6ba8e9aa, (int)0x9d6c069d, (int)0xa946ee5d); - rc[29] = _mm_set_epi32((int)0xcb1e6950, (int)0xf957332b, (int)0xa2531159, (int)0x3bf327c1); - rc[30] = _mm_set_epi32((int)0x2cee0c75, (int)0x00da619c, (int)0xe4ed0353, (int)0x600ed0d9); - rc[31] = _mm_set_epi32((int)0xf0b1a5a1, (int)0x96e90cab, (int)0x80bbbabc, (int)0x63a4a350); - rc[32] = _mm_set_epi32((int)0xae3db102, (int)0x5e962988, (int)0xab0dde30, (int)0x938dca39); - rc[33] = _mm_set_epi32((int)0x17bb8f38, (int)0xd554a40b, (int)0x8814f3a8, (int)0x2e75b442); - rc[34] = _mm_set_epi32((int)0x34bb8a5b, (int)0x5f427fd7, (int)0xaeb6b779, (int)0x360a16f6); - rc[35] = _mm_set_epi32((int)0x26f65241, (int)0xcbe55438, (int)0x43ce5918, (int)0xffbaafde); - rc[36] = _mm_set_epi32((int)0x4ce99a54, (int)0xb9f3026a, (int)0xa2ca9cf7, (int)0x839ec978); - rc[37] = _mm_set_epi32((int)0xae51a51a, (int)0x1bdff7be, (int)0x40c06e28, (int)0x22901235); - rc[38] = _mm_set_epi32((int)0xa0c1613c, (int)0xba7ed22b, (int)0xc173bc0f, (int)0x48a659cf); - rc[39] = _mm_set_epi32((int)0x756acc03, (int)0x02288288, (int)0x4ad6bdfd, (int)0xe9c59da1); -} - -void tweak_constants(spx_ctx *ctx) { - int i; - unsigned char buf[40 * 16]; - - /* Use the standard constants to generate tweaked ones. */ - load_haraka_constants(ctx->rc); - - /* Constants for pk.seed */ - haraka_S(buf, 40 * 16, ctx->pub_seed, SPX_N, ctx); - - /* Tweak constants with the pub_seed */ - for (i = 0; i < 40; i++) { - ctx->rc[i] = LOAD(buf + i * 16); - } -} - -static void haraka_S_absorb(unsigned char *s, unsigned int r, - const unsigned char *m, unsigned long long mlen, - unsigned char p, const spx_ctx *ctx) { - unsigned long long i; - PQCLEAN_VLA(unsigned char, t, r); - - while (mlen >= r) { - // XOR block to state - STORE(s, XOR128(LOAD(s), LOAD(m))); - STORE(s + 16, XOR128(LOAD(s + 16), LOAD(m + 16))); - haraka512_perm(s, s, ctx); - 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; - STORE(s, XOR128(LOAD(s), LOAD(t))); - STORE(s + 16, XOR128(LOAD(s + 16), LOAD(t + 16))); -} - -static void haraka_S_absorb4x(unsigned char *s, - unsigned int r, - const unsigned char *m0, - const unsigned char *m1, - const unsigned char *m2, - const unsigned char *m3, - unsigned long long int mlen, - unsigned char p, - const spx_ctx *ctx) { - unsigned long long i; - PQCLEAN_VLA(unsigned char, t0, r); - PQCLEAN_VLA(unsigned char, t1, r); - PQCLEAN_VLA(unsigned char, t2, r); - PQCLEAN_VLA(unsigned char, t3, r); - - while (mlen >= r) { - // XOR block to state - STORE(s, XOR128(LOAD(s), LOAD(m0))); - STORE(s + 16, XOR128(LOAD(s + 16), LOAD(m0 + 16))); - STORE(s + 64, XOR128(LOAD(s + 64), LOAD(m1))); - STORE(s + 80, XOR128(LOAD(s + 80), LOAD(m1 + 16))); - STORE(s + 128, XOR128(LOAD(s + 128), LOAD(m2))); - STORE(s + 144, XOR128(LOAD(s + 144), LOAD(m2 + 16))); - STORE(s + 192, XOR128(LOAD(s + 192), LOAD(m3))); - STORE(s + 208, XOR128(LOAD(s + 208), LOAD(m3 + 16))); - - haraka512_perm_x4(s, s, ctx); - mlen -= r; - m0 += r; - m1 += r; - m2 += r; - m3 += r; - } - - for (i = 0; i < r; ++i) { - t0[i] = 0; - t1[i] = 0; - t2[i] = 0; - t3[i] = 0; - } - for (i = 0; i < mlen; ++i) { - t0[i] = m0[i]; - t1[i] = m1[i]; - t2[i] = m2[i]; - t3[i] = m3[i]; - } - - t0[i] = p; - t1[i] = p; - t2[i] = p; - t3[i] = p; - - t0[r - 1] |= 128; - t1[r - 1] |= 128; - t2[r - 1] |= 128; - t3[r - 1] |= 128; - - STORE(s, XOR128(LOAD(s), LOAD(t0))); - STORE(s + 16, XOR128(LOAD(s + 16), LOAD(t0 + 16))); - STORE(s + 64, XOR128(LOAD(s + 64), LOAD(t1))); - STORE(s + 80, XOR128(LOAD(s + 80), LOAD(t1 + 16))); - STORE(s + 128, XOR128(LOAD(s + 128), LOAD(t2))); - STORE(s + 144, XOR128(LOAD(s + 144), LOAD(t2 + 16))); - STORE(s + 192, XOR128(LOAD(s + 192), LOAD(t3))); - STORE(s + 208, XOR128(LOAD(s + 208), LOAD(t3 + 16))); -} - -static void haraka_S_squeezeblocks(unsigned char *h, unsigned long long nblocks, - unsigned char *s, unsigned int r, - const spx_ctx *ctx) { - while (nblocks > 0) { - haraka512_perm(s, s, ctx); - STORE(h, LOAD(s)); - STORE(h + 16, LOAD(s + 16)); - h += r; - nblocks--; - } -} - -static void haraka_S_squeezeblocks4x(unsigned char *h0, - unsigned char *h1, - unsigned char *h2, - unsigned char *h3, - unsigned long long nblocks, - unsigned char *s, - unsigned int r, - const spx_ctx *ctx) { - while (nblocks > 0) { - haraka512_perm_x4(s, s, ctx); - STORE(h0, LOAD(s)); - STORE(h0 + 16, LOAD(s + 16)); - STORE(h1, LOAD(s + 64)); - STORE(h1 + 16, LOAD(s + 80)); - STORE(h2, LOAD(s + 128)); - STORE(h2 + 16, LOAD(s + 144)); - STORE(h3, LOAD(s + 192)); - STORE(h3 + 16, LOAD(s + 208)); - h0 += r; - h1 += r; - h2 += r; - h3 += r; - nblocks--; - } -} - -void haraka_S_inc_init(uint8_t *s_inc) { - size_t i; - - for (i = 0; i < 64; i++) { - s_inc[i] = 0; - } - s_inc[64] = 0; -} - -void haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, - const spx_ctx *ctx) { - size_t i; - - /* Recall that s_inc[64] is the non-absorbed bytes xored into the state */ - while (mlen + s_inc[64] >= HARAKAS_RATE) { - for (i = 0; i < (size_t)(HARAKAS_RATE - s_inc[64]); i++) { - /* Take the i'th byte from message - xor with the s_inc[64] + i'th byte of the state */ - s_inc[s_inc[64] + i] ^= m[i]; - } - mlen -= (size_t)(HARAKAS_RATE - s_inc[64]); - m += HARAKAS_RATE - s_inc[64]; - s_inc[64] = 0; - - haraka512_perm(s_inc, s_inc, ctx); - } - - for (i = 0; i < mlen; i++) { - s_inc[s_inc[64] + i] ^= m[i]; - } - s_inc[64] += (uint8_t)mlen; -} - -void haraka_S_inc_finalize(uint8_t *s_inc) { - /* After haraka_S_inc_absorb, we are guaranteed that s_inc[64] < HARAKAS_RATE, - so we can always use one more byte for p in the current state. */ - s_inc[s_inc[64]] ^= 0x1F; - s_inc[HARAKAS_RATE - 1] ^= 128; - s_inc[64] = 0; -} - -void haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, - const spx_ctx *ctx) { - size_t i; - - /* First consume any bytes we still have sitting around */ - for (i = 0; i < outlen && i < s_inc[64]; i++) { - /* There are s_inc[64] bytes left, so r - s_inc[64] is the first - available byte. We consume from there, i.e., up to r. */ - out[i] = (uint8_t)s_inc[(HARAKAS_RATE - s_inc[64] + i)]; - } - out += i; - outlen -= i; - s_inc[64] -= (uint8_t)i; - - /* Then squeeze the remaining necessary blocks */ - while (outlen > 0) { - haraka512_perm(s_inc, s_inc, ctx); - - for (i = 0; i < outlen && i < HARAKAS_RATE; i++) { - out[i] = s_inc[i]; - } - out += i; - outlen -= i; - s_inc[64] = (uint8_t)(HARAKAS_RATE - i); - } -} - -void haraka_S(unsigned char *out, unsigned long long outlen, - const unsigned char *in, unsigned long long inlen, - const spx_ctx *ctx) { - unsigned long long i; - unsigned char s[64]; - unsigned char d[32]; - - for (i = 0; i < 64; i++) { - s[i] = 0; - } - haraka_S_absorb(s, HARAKAS_RATE, in, inlen, 0x1F, ctx); - - haraka_S_squeezeblocks(out, outlen / HARAKAS_RATE, s, HARAKAS_RATE, ctx); - out += (outlen / HARAKAS_RATE) * HARAKAS_RATE; - - if (outlen % HARAKAS_RATE) { - haraka_S_squeezeblocks(d, 1, s, HARAKAS_RATE, ctx); - for (i = 0; i < outlen % HARAKAS_RATE; i++) { - out[i] = d[i]; - } - } -} - -void haraka_Sx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned long long outlen, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - unsigned long long inlen, - const spx_ctx *ctx) { - unsigned long long i; - unsigned char s[64 * 4]; - unsigned char d0[32]; - unsigned char d1[32]; - unsigned char d2[32]; - unsigned char d3[32]; - - for (i = 0; i < 64 * 4; i++) { - s[i] = 0; - } - haraka_S_absorb4x(s, HARAKAS_RATE, in0, in1, in2, in3, inlen, 0x1F, ctx); - - haraka_S_squeezeblocks4x(out0, out1, out2, out3, outlen / HARAKAS_RATE, s, - HARAKAS_RATE, ctx); - out0 += (outlen / HARAKAS_RATE) * HARAKAS_RATE; - out1 += (outlen / HARAKAS_RATE) * HARAKAS_RATE; - out2 += (outlen / HARAKAS_RATE) * HARAKAS_RATE; - out3 += (outlen / HARAKAS_RATE) * HARAKAS_RATE; - - if (outlen % HARAKAS_RATE) { - haraka_S_squeezeblocks4x(d0, d1, d2, d3, 1, s, HARAKAS_RATE, ctx); - for (i = 0; i < outlen % HARAKAS_RATE; i++) { - out0[i] = d0[i]; - out1[i] = d1[i]; - out2[i] = d2[i]; - out3[i] = d3[i]; - } - } -} - -void haraka512_perm(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx) { - u128 s[4], tmp; - - s[0] = LOAD(in); - s[1] = LOAD(in + 16); - s[2] = LOAD(in + 32); - s[3] = LOAD(in + 48); - - AES4(s[0], s[1], s[2], s[3], ctx->rc); - MIX4(s[0], s[1], s[2], s[3]); - - AES4(s[0], s[1], s[2], s[3], ctx->rc + 8); - MIX4(s[0], s[1], s[2], s[3]); - - AES4(s[0], s[1], s[2], s[3], ctx->rc + 16); - MIX4(s[0], s[1], s[2], s[3]); - - AES4(s[0], s[1], s[2], s[3], ctx->rc + 24); - MIX4(s[0], s[1], s[2], s[3]); - - AES4(s[0], s[1], s[2], s[3], ctx->rc + 32); - MIX4(s[0], s[1], s[2], s[3]); - - STORE(out, s[0]); - STORE(out + 16, s[1]); - STORE(out + 32, s[2]); - STORE(out + 48, s[3]); -} - -void haraka512_perm_x4(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx) { - u128 s[4][4], tmp; - - s[0][0] = LOAD(in); - s[0][1] = LOAD(in + 16); - s[0][2] = LOAD(in + 32); - s[0][3] = LOAD(in + 48); - s[1][0] = LOAD(in + 64); - s[1][1] = LOAD(in + 80); - s[1][2] = LOAD(in + 96); - s[1][3] = LOAD(in + 112); - s[2][0] = LOAD(in + 128); - s[2][1] = LOAD(in + 144); - s[2][2] = LOAD(in + 160); - s[2][3] = LOAD(in + 176); - s[3][0] = LOAD(in + 192); - s[3][1] = LOAD(in + 208); - s[3][2] = LOAD(in + 224); - s[3][3] = LOAD(in + 240); - - AES4_4x(s[0], s[1], s[2], s[3], ctx->rc); - MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); - MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); - MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); - MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - - AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 8); - MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); - MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); - MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); - MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - - AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 16); - MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); - MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); - MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); - MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - - AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 24); - MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); - MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); - MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); - MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - - AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 32); - MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); - MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); - MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); - MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - - STORE(out, s[0][0]); - STORE(out + 16, s[0][1]); - STORE(out + 32, s[0][2]); - STORE(out + 48, s[0][3]); - STORE(out + 64, s[1][0]); - STORE(out + 80, s[1][1]); - STORE(out + 96, s[1][2]); - STORE(out + 112, s[1][3]); - STORE(out + 128, s[2][0]); - STORE(out + 144, s[2][1]); - STORE(out + 160, s[2][2]); - STORE(out + 176, s[2][3]); - STORE(out + 192, s[3][0]); - STORE(out + 208, s[3][1]); - STORE(out + 224, s[3][2]); - STORE(out + 240, s[3][3]); -} - -void haraka512(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx) { - u128 s[4], tmp; - - s[0] = LOAD(in); - s[1] = LOAD(in + 16); - s[2] = LOAD(in + 32); - s[3] = LOAD(in + 48); - - AES4(s[0], s[1], s[2], s[3], ctx->rc); - MIX4(s[0], s[1], s[2], s[3]); - - AES4(s[0], s[1], s[2], s[3], ctx->rc + 8); - MIX4(s[0], s[1], s[2], s[3]); - - AES4(s[0], s[1], s[2], s[3], ctx->rc + 16); - MIX4(s[0], s[1], s[2], s[3]); - - AES4(s[0], s[1], s[2], s[3], ctx->rc + 24); - MIX4(s[0], s[1], s[2], s[3]); - - AES4(s[0], s[1], s[2], s[3], ctx->rc + 32); - MIX4(s[0], s[1], s[2], s[3]); - - s[0] = XOR128(s[0], LOAD(in)); - s[1] = XOR128(s[1], LOAD(in + 16)); - s[2] = XOR128(s[2], LOAD(in + 32)); - s[3] = XOR128(s[3], LOAD(in + 48)); - - // truncate and store result - TRUNCSTORE(out, s[0], s[1], s[2], s[3]); -} - -void haraka512x4(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx) { - u128 s[4][4], tmp; - - s[0][0] = LOAD(in); - s[0][1] = LOAD(in + 16); - s[0][2] = LOAD(in + 32); - s[0][3] = LOAD(in + 48); - s[1][0] = LOAD(in + 64); - s[1][1] = LOAD(in + 80); - s[1][2] = LOAD(in + 96); - s[1][3] = LOAD(in + 112); - s[2][0] = LOAD(in + 128); - s[2][1] = LOAD(in + 144); - s[2][2] = LOAD(in + 160); - s[2][3] = LOAD(in + 176); - s[3][0] = LOAD(in + 192); - s[3][1] = LOAD(in + 208); - s[3][2] = LOAD(in + 224); - s[3][3] = LOAD(in + 240); - - AES4_4x(s[0], s[1], s[2], s[3], ctx->rc); - MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); - MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); - MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); - MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - - AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 8); - MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); - MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); - MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); - MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - - AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 16); - MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); - MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); - MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); - MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - - AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 24); - MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); - MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); - MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); - MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - - AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 32); - MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); - MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); - MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); - MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - - s[0][0] = XOR128(s[0][0], LOAD(in)); - s[0][1] = XOR128(s[0][1], LOAD(in + 16)); - s[0][2] = XOR128(s[0][2], LOAD(in + 32)); - s[0][3] = XOR128(s[0][3], LOAD(in + 48)); - s[1][0] = XOR128(s[1][0], LOAD(in + 64)); - s[1][1] = XOR128(s[1][1], LOAD(in + 80)); - s[1][2] = XOR128(s[1][2], LOAD(in + 96)); - s[1][3] = XOR128(s[1][3], LOAD(in + 112)); - s[2][0] = XOR128(s[2][0], LOAD(in + 128)); - s[2][1] = XOR128(s[2][1], LOAD(in + 144)); - s[2][2] = XOR128(s[2][2], LOAD(in + 160)); - s[2][3] = XOR128(s[2][3], LOAD(in + 176)); - s[3][0] = XOR128(s[3][0], LOAD(in + 192)); - s[3][1] = XOR128(s[3][1], LOAD(in + 208)); - s[3][2] = XOR128(s[3][2], LOAD(in + 224)); - s[3][3] = XOR128(s[3][3], LOAD(in + 240)); - - TRUNCSTORE(out, s[0][0], s[0][1], s[0][2], s[0][3]); - TRUNCSTORE((out + 32), s[1][0], s[1][1], s[1][2], s[1][3]); - TRUNCSTORE((out + 64), s[2][0], s[2][1], s[2][2], s[2][3]); - TRUNCSTORE((out + 96), s[3][0], s[3][1], s[3][2], s[3][3]); -} - -void haraka256(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx) { - u128 s[2], tmp; - - s[0] = LOAD(in); - s[1] = LOAD(in + 16); - - AES2(s[0], s[1], ctx->rc); - MIX2(s[0], s[1]); - - AES2(s[0], s[1], ctx->rc + 4); - MIX2(s[0], s[1]); - - AES2(s[0], s[1], ctx->rc + 8); - MIX2(s[0], s[1]); - - AES2(s[0], s[1], ctx->rc + 12); - MIX2(s[0], s[1]); - - AES2(s[0], s[1], ctx->rc + 16); - MIX2(s[0], s[1]); - - s[0] = XOR128(s[0], LOAD(in)); - s[1] = XOR128(s[1], LOAD(in + 16)); - - STORE(out, s[0]); - STORE(out + 16, s[1]); -} - -void haraka256x4(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx) { - u128 s[4][2], tmp; - - s[0][0] = LOAD(in); - s[0][1] = LOAD(in + 16); - s[1][0] = LOAD(in + 32); - s[1][1] = LOAD(in + 48); - s[2][0] = LOAD(in + 64); - s[2][1] = LOAD(in + 80); - s[3][0] = LOAD(in + 96); - s[3][1] = LOAD(in + 112); - - // Round 1 - AES2_4x(s[0], s[1], s[2], s[3], ctx->rc); - - MIX2(s[0][0], s[0][1]); - MIX2(s[1][0], s[1][1]); - MIX2(s[2][0], s[2][1]); - MIX2(s[3][0], s[3][1]); - - // Round 2 - AES2_4x(s[0], s[1], s[2], s[3], ctx->rc + 4); - - MIX2(s[0][0], s[0][1]); - MIX2(s[1][0], s[1][1]); - MIX2(s[2][0], s[2][1]); - MIX2(s[3][0], s[3][1]); - - // Round 3 - AES2_4x(s[0], s[1], s[2], s[3], ctx->rc + 8); - - MIX2(s[0][0], s[0][1]); - MIX2(s[1][0], s[1][1]); - MIX2(s[2][0], s[2][1]); - MIX2(s[3][0], s[3][1]); - - // Round 4 - AES2_4x(s[0], s[1], s[2], s[3], ctx->rc + 12); - - MIX2(s[0][0], s[0][1]); - MIX2(s[1][0], s[1][1]); - MIX2(s[2][0], s[2][1]); - MIX2(s[3][0], s[3][1]); - - // Round 5 - AES2_4x(s[0], s[1], s[2], s[3], ctx->rc + 16); - - MIX2(s[0][0], s[0][1]); - MIX2(s[1][0], s[1][1]); - MIX2(s[2][0], s[2][1]); - MIX2(s[3][0], s[3][1]); - - // Feed Forward - s[0][0] = _mm_xor_si128(s[0][0], LOAD(in)); - s[0][1] = _mm_xor_si128(s[0][1], LOAD(in + 16)); - s[1][0] = _mm_xor_si128(s[1][0], LOAD(in + 32)); - s[1][1] = _mm_xor_si128(s[1][1], LOAD(in + 48)); - s[2][0] = _mm_xor_si128(s[2][0], LOAD(in + 64)); - s[2][1] = _mm_xor_si128(s[2][1], LOAD(in + 80)); - s[3][0] = _mm_xor_si128(s[3][0], LOAD(in + 96)); - s[3][1] = _mm_xor_si128(s[3][1], LOAD(in + 112)); - - STORE(out, s[0][0]); - STORE(out + 16, s[0][1]); - STORE(out + 32, s[1][0]); - STORE(out + 48, s[1][1]); - STORE(out + 64, s[2][0]); - STORE(out + 80, s[2][1]); - STORE(out + 96, s[3][0]); - STORE(out + 112, s[3][1]); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/haraka.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/haraka.h deleted file mode 100644 index 737cb6065f..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/haraka.h +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef SPX_HARAKA_H -#define SPX_HARAKA_H - -#include "context.h" -#include "params.h" - -/* Tweak constants with seed */ -#define tweak_constants SPX_NAMESPACE(tweak_constants) -void tweak_constants(spx_ctx *ctx); - -/* Haraka Sponge */ -#define haraka_S_inc_init SPX_NAMESPACE(haraka_S_inc_init) -void haraka_S_inc_init(uint8_t *s_inc); -#define haraka_S_inc_absorb SPX_NAMESPACE(haraka_S_inc_absorb) -void haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, - const spx_ctx *ctx); -#define haraka_S_inc_finalize SPX_NAMESPACE(haraka_S_inc_finalize) -void haraka_S_inc_finalize(uint8_t *s_inc); -#define haraka_S_inc_squeeze SPX_NAMESPACE(haraka_S_inc_squeeze) -void haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, - const spx_ctx *ctx); -#define haraka_S SPX_NAMESPACE(haraka_S) -void haraka_S(unsigned char *out, unsigned long long outlen, - const unsigned char *in, unsigned long long inlen, - const spx_ctx *ctx); - -/* Applies the 512-bit Haraka permutation to in. */ -#define haraka512_perm SPX_NAMESPACE(haraka512_perm) -void haraka512_perm(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx); - -/* Implementation of Haraka-512 */ -#define haraka512 SPX_NAMESPACE(haraka512) -void haraka512(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx); - -/* Implementation of Haraka-256 */ -#define haraka256 SPX_NAMESPACE(haraka256) -void haraka256(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/haraka_offsets.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/haraka_offsets.h deleted file mode 100644 index 7c062272a0..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/haraka_offsets.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef HARAKA_OFFSETS_H_ -#define HARAKA_OFFSETS_H_ - -/* - * Offsets of various fields in the address structure when we use Haraka as - * the Sphincs+ hash function - */ - -#define SPX_OFFSET_LAYER 3 /* The byte used to specify the Merkle tree layer */ -#define SPX_OFFSET_TREE 8 /* The start of the 8 byte field used to specify the tree */ -#define SPX_OFFSET_TYPE 19 /* The byte used to specify the hash type (reason) */ -#define SPX_OFFSET_KP_ADDR2 22 /* The high byte used to specify the key pair (which one-time signature) */ -#define SPX_OFFSET_KP_ADDR1 23 /* The low byte used to specify the key pair */ -#define SPX_OFFSET_CHAIN_ADDR 27 /* The byte used to specify the chain address (which Winternitz chain) */ -#define SPX_OFFSET_HASH_ADDR 31 /* The byte used to specify the hash address (where in the Winternitz chain) */ -#define SPX_OFFSET_TREE_HGT 27 /* The byte used to specify the height of this node in the FORS or Merkle tree */ -#define SPX_OFFSET_TREE_INDEX 28 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ - -#define SPX_HARAKA 1 - -#endif /* HARAKA_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/harakax4.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/harakax4.h deleted file mode 100644 index eadc69aa48..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/harakax4.h +++ /dev/null @@ -1,36 +0,0 @@ -#ifndef SPX_HARAKAX4_H -#define SPX_HARAKAX4_H - -#include "context.h" -#include "params.h" - -/* Haraka Sponge */ -#define haraka_Sx4 SPX_NAMESPACE(haraka_Sx4) -void haraka_Sx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned long long outlen, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - unsigned long long inlen, - const spx_ctx *ctx); - -/* Applies the 512-bit Haraka permutation x4 to in. */ -#define haraka512_perm_x4 SPX_NAMESPACE(haraka512_perm_x4) -void haraka512_perm_x4(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx); - -/* Implementation of Haraka-512 x4*/ -#define haraka512x4 SPX_NAMESPACE(haraka512x4) -void haraka512x4(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx); - -/* Implementation of Haraka-256 x4 */ -#define haraka256x4 SPX_NAMESPACE(haraka256x4) -void haraka256x4(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/hash.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/hash.h deleted file mode 100644 index f7c87d4c3c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/hash.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef SPX_HASH_H -#define SPX_HASH_H - -#include -#include - -#include "context.h" -#include "params.h" - -#define prf_addr SPX_NAMESPACE(prf_addr) -void prf_addr(unsigned char *out, const spx_ctx *ctx, - const uint32_t addr[8]); - -#define gen_message_random SPX_NAMESPACE(gen_message_random) -void gen_message_random(unsigned char *R, const unsigned char *sk_prf, - const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx); - -#define hash_message SPX_NAMESPACE(hash_message) -void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx); - - - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/hash_haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/hash_haraka.c deleted file mode 100644 index 750a67423b..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/hash_haraka.c +++ /dev/null @@ -1,81 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "utils.h" - -#include "haraka.h" -#include "hash.h" - -/* - * Computes PRF(key, addr), given a secret key of SPX_N bytes and an address - */ -void prf_addr(unsigned char *out, const spx_ctx *ctx, - const uint32_t addr[8]) { - /* Since SPX_N may be smaller than 32, we need temporary buffers. */ - unsigned char outbuf[32]; - unsigned char buf[64] = {0}; - - memcpy(buf, addr, SPX_ADDR_BYTES); - memcpy(buf + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); - - haraka512(outbuf, (const void *)buf, ctx); - memcpy(out, outbuf, SPX_N); -} - -/** - * Computes the message-dependent randomness R, using a secret seed and an - * optional randomization value as well as the message. - */ -void gen_message_random(unsigned char *R, const unsigned char *sk_prf, - const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx) { - uint8_t s_inc[65]; - - haraka_S_inc_init(s_inc); - haraka_S_inc_absorb(s_inc, sk_prf, SPX_N, ctx); - haraka_S_inc_absorb(s_inc, optrand, SPX_N, ctx); - haraka_S_inc_absorb(s_inc, m, mlen, ctx); - haraka_S_inc_finalize(s_inc); - haraka_S_inc_squeeze(R, SPX_N, s_inc, ctx); -} - -/** - * Computes the message hash using R, the public key, and the message. - * Outputs the message digest and the index of the leaf. The index is split in - * the tree index and the leaf index, for convenient copying to an address. - */ -void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx) { -#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) -#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) -#define SPX_LEAF_BITS SPX_TREE_HEIGHT -#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) -#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) - - unsigned char buf[SPX_DGST_BYTES]; - unsigned char *bufp = buf; - uint8_t s_inc[65]; - - haraka_S_inc_init(s_inc); - haraka_S_inc_absorb(s_inc, R, SPX_N, ctx); - haraka_S_inc_absorb(s_inc, pk + SPX_N, SPX_N, ctx); // Only absorb root part of pk - haraka_S_inc_absorb(s_inc, m, mlen, ctx); - haraka_S_inc_finalize(s_inc); - haraka_S_inc_squeeze(buf, SPX_DGST_BYTES, s_inc, ctx); - - memcpy(digest, bufp, SPX_FORS_MSG_BYTES); - bufp += SPX_FORS_MSG_BYTES; - - - *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); - *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); - bufp += SPX_TREE_BYTES; - - *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); - *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/hash_harakax4.c b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/hash_harakax4.c deleted file mode 100644 index cfa5162d79..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/hash_harakax4.c +++ /dev/null @@ -1,35 +0,0 @@ -#include -#include - -#include "address.h" -#include "harakax4.h" -#include "hashx4.h" -#include "params.h" - -/* - * 4-way parallel version of prf_addr; takes 4x as much input and output - */ -#define prf_addrx4 SPX_NAMESPACE(prf_addrx4) -void prf_addrx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const spx_ctx *ctx, - const uint32_t addrx4[4 * 8]) { - unsigned char bufx4[4 * 64] = {0}; - /* Since SPX_N may be smaller than 32, we need temporary buffers. */ - unsigned char outbuf[4 * 32]; - unsigned int i; - - for (i = 0; i < 4; i++) { - memcpy(bufx4 + i * 64, addrx4 + i * 8, SPX_ADDR_BYTES); - memcpy(bufx4 + i * 64 + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); - } - - haraka512x4(outbuf, bufx4, ctx); - - memcpy(out0, outbuf, SPX_N); - memcpy(out1, outbuf + 32, SPX_N); - memcpy(out2, outbuf + 64, SPX_N); - memcpy(out3, outbuf + 96, SPX_N); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/hashx4.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/hashx4.h deleted file mode 100644 index 3751a0ebd0..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/hashx4.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef SPX_HASHX4_H -#define SPX_HASHX4_H - -#include - -#include "context.h" -#include "params.h" - -#define prf_addrx4 SPX_NAMESPACE(prf_addrx4) -void prf_addrx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const spx_ctx *ctx, - const uint32_t addrx4[4 * 8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/merkle.c b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/merkle.c deleted file mode 100644 index f57811c1ac..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/merkle.c +++ /dev/null @@ -1,64 +0,0 @@ -#include -#include - -#include "merkle.h" - -#include "address.h" -#include "params.h" -#include "utils.h" -#include "utilsx4.h" -#include "wots.h" -#include "wotsx4.h" - -/* - * This generates a Merkle signature (WOTS signature followed by the Merkle - * authentication path). - */ -void merkle_sign(uint8_t *sig, unsigned char *root, - const spx_ctx *ctx, - uint32_t wots_addr[8], uint32_t tree_addr[8], - uint32_t idx_leaf) { - unsigned char *auth_path = sig + SPX_WOTS_BYTES; - uint32_t tree_addrx4[4 * 8] = { 0 }; - int j; - struct leaf_info_x4 info = { 0 }; - unsigned steps[ SPX_WOTS_LEN ]; - - info.wots_sig = sig; - chain_lengths(steps, root); - info.wots_steps = steps; - - for (j = 0; j < 4; j++) { - set_type(&tree_addrx4[8 * j], SPX_ADDR_TYPE_HASHTREE); - set_type(&info.leaf_addr[8 * j], SPX_ADDR_TYPE_WOTS); - set_type(&info.pk_addr[8 * j], SPX_ADDR_TYPE_WOTSPK); - copy_subtree_addr(&tree_addrx4[8 * j], tree_addr); - copy_subtree_addr(&info.leaf_addr[8 * j], wots_addr); - copy_subtree_addr(&info.pk_addr[8 * j], wots_addr); - } - - info.wots_sign_leaf = idx_leaf; - - treehashx4(root, auth_path, ctx, - idx_leaf, 0, - SPX_TREE_HEIGHT, - wots_gen_leafx4, - tree_addrx4, &info); -} - -/* Compute root node of the top-most subtree. */ -void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { - /* We do not need the auth path in key generation, but it simplifies the - code to have just one treehash routine that computes both root and path - in one function. */ - unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; - uint32_t top_tree_addr[8] = {0}; - uint32_t wots_addr[8] = {0}; - - set_layer_addr(top_tree_addr, SPX_D - 1); - set_layer_addr(wots_addr, SPX_D - 1); - - merkle_sign(auth_path, root, ctx, - wots_addr, top_tree_addr, - ~0U /* ~0 means "don't bother generating an auth path */ ); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/merkle.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/merkle.h deleted file mode 100644 index 769cf2e970..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/merkle.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef MERKLE_H_ -#define MERKLE_H_ - -#include - -#include "context.h" -#include "params.h" - -/* Generate a Merkle signature (WOTS signature followed by the Merkle */ -/* authentication path) */ -#define merkle_sign SPX_NAMESPACE(merkle_sign) -void merkle_sign(uint8_t *sig, unsigned char *root, - const spx_ctx *ctx, - uint32_t wots_addr[8], uint32_t tree_addr[8], - uint32_t idx_leaf); - -/* Compute the root node of the top-most subtree. */ -#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) -void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); - -#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/nistapi.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/nistapi.h deleted file mode 100644 index 3cb71afad4..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/nistapi.h +++ /dev/null @@ -1,87 +0,0 @@ -#ifndef SPX_API_H -#define SPX_API_H - -#include -#include - -#include "params.h" - -#define CRYPTO_ALGNAME "SPHINCS+" - -#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES -#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES -#define CRYPTO_BYTES SPX_BYTES -#define CRYPTO_SEEDBYTES (3*SPX_N) - -/* - * Returns the length of a secret key, in bytes - */ -#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) -size_t crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) -size_t crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) -size_t crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) -size_t crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) -int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) -int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) -int crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) -int crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -#define crypto_sign SPX_NAMESPACE(crypto_sign) -int crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) -int crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/params.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/params.h deleted file mode 100644 index 4e1e7f0bb6..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/params.h +++ /dev/null @@ -1,56 +0,0 @@ -#ifndef SPX_PARAMS_H -#define SPX_PARAMS_H - -#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_##s - -/* Hash output length in bytes. */ -#define SPX_N 16 -/* Height of the hypertree. */ -#define SPX_FULL_HEIGHT 63 -/* Number of subtree layer. */ -#define SPX_D 7 -/* FORS tree dimensions. */ -#define SPX_FORS_HEIGHT 12 -#define SPX_FORS_TREES 14 -/* Winternitz parameter, */ -#define SPX_WOTS_W 16 - -/* The hash function is defined by linking a different hash.c file, as opposed - to setting a #define constant. */ - -/* For clarity */ -#define SPX_ADDR_BYTES 32 - -/* WOTS parameters. */ -#define SPX_WOTS_LOGW 4 - -#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) - -/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#define SPX_WOTS_LEN2 3 - -#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) -#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) -#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES - -/* Subtree size. */ -#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) - -//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT -// #error SPX_D should always divide SPX_FULL_HEIGHT -//#endif - -/* FORS parameters. */ -#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) -#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) -#define SPX_FORS_PK_BYTES SPX_N - -/* Resulting SPX sizes. */ -#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ - SPX_FULL_HEIGHT * SPX_N) -#define SPX_PK_BYTES (2 * SPX_N) -#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) - -#include "haraka_offsets.h" - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/sign.c b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/sign.c deleted file mode 100644 index 9d0c7d1b22..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/sign.c +++ /dev/null @@ -1,286 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "context.h" -#include "fors.h" -#include "hash.h" -#include "merkle.h" -#include "nistapi.h" -#include "params.h" -#include "randombytes.h" -#include "thash.h" -#include "utils.h" -#include "wots.h" - -/* - * Returns the length of a secret key, in bytes - */ -size_t crypto_sign_secretkeybytes(void) { - return CRYPTO_SECRETKEYBYTES; -} - -/* - * Returns the length of a public key, in bytes - */ -size_t crypto_sign_publickeybytes(void) { - return CRYPTO_PUBLICKEYBYTES; -} - -/* - * Returns the length of a signature, in bytes - */ -size_t crypto_sign_bytes(void) { - return CRYPTO_BYTES; -} - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t crypto_sign_seedbytes(void) { - return CRYPTO_SEEDBYTES; -} - -/* - * Generates an SPX key pair given a seed of length - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed) { - spx_ctx ctx; - - /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ - memcpy(sk, seed, CRYPTO_SEEDBYTES); - - memcpy(pk, sk + 2 * SPX_N, SPX_N); - - memcpy(ctx.pub_seed, pk, SPX_N); - memcpy(ctx.sk_seed, sk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - /* Compute root node of the top-most subtree. */ - merkle_gen_root(sk + 3 * SPX_N, &ctx); - - // cleanup - free_hash_function(&ctx); - - memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); - - return 0; -} - -/* - * Generates an SPX key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { - uint8_t seed[CRYPTO_SEEDBYTES]; - randombytes(seed, CRYPTO_SEEDBYTES); - crypto_sign_seed_keypair(pk, sk, seed); - - return 0; -} - -/** - * Returns an array containing a detached signature. - */ -int crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - spx_ctx ctx; - - const uint8_t *sk_prf = sk + SPX_N; - const uint8_t *pk = sk + 2 * SPX_N; - - uint8_t optrand[SPX_N]; - uint8_t mhash[SPX_FORS_MSG_BYTES]; - uint8_t root[SPX_N]; - uint32_t i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - - memcpy(ctx.sk_seed, sk, SPX_N); - memcpy(ctx.pub_seed, pk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - set_type(wots_addr, SPX_ADDR_TYPE_WOTS); - set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); - - /* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ - randombytes(optrand, SPX_N); - /* Compute the digest randomization value. */ - gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); - - /* Derive the message digest and leaf index from R, PK and M. */ - hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); - sig += SPX_N; - - set_tree_addr(wots_addr, tree); - set_keypair_addr(wots_addr, idx_leaf); - - /* Sign the message hash using FORS. */ - fors_sign(sig, root, mhash, &ctx, wots_addr); - sig += SPX_FORS_BYTES; - - for (i = 0; i < SPX_D; i++) { - set_layer_addr(tree_addr, i); - set_tree_addr(tree_addr, tree); - - copy_subtree_addr(wots_addr, tree_addr); - set_keypair_addr(wots_addr, idx_leaf); - - merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); - sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); - tree = tree >> SPX_TREE_HEIGHT; - } - - free_hash_function(&ctx); - - *siglen = SPX_BYTES; - - return 0; -} - -/** - * Verifies a detached signature and message under a given public key. - */ -int crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk) { - spx_ctx ctx; - const uint8_t *pub_root = pk + SPX_N; - uint8_t mhash[SPX_FORS_MSG_BYTES]; - uint8_t wots_pk[SPX_WOTS_BYTES]; - uint8_t root[SPX_N]; - uint8_t leaf[SPX_N]; - unsigned int i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - if (siglen != SPX_BYTES) { - return -1; - } - - memcpy(ctx.pub_seed, pk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - set_type(wots_addr, SPX_ADDR_TYPE_WOTS); - set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); - set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); - - /* Derive the message digest and leaf index from R || PK || M. */ - /* The additional SPX_N is a result of the hash domain separator. */ - hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); - sig += SPX_N; - - /* Layer correctly defaults to 0, so no need to set_layer_addr */ - set_tree_addr(wots_addr, tree); - set_keypair_addr(wots_addr, idx_leaf); - - fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); - sig += SPX_FORS_BYTES; - - /* For each subtree.. */ - for (i = 0; i < SPX_D; i++) { - set_layer_addr(tree_addr, i); - set_tree_addr(tree_addr, tree); - - copy_subtree_addr(wots_addr, tree_addr); - set_keypair_addr(wots_addr, idx_leaf); - - copy_keypair_addr(wots_pk_addr, wots_addr); - - /* The WOTS public key is only correct if the signature was correct. */ - /* Initially, root is the FORS pk, but on subsequent iterations it is - the root of the subtree below the currently processed subtree. */ - wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); - sig += SPX_WOTS_BYTES; - - /* Compute the leaf node using the WOTS public key. */ - thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); - - /* Compute the root node of this subtree. */ - compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, - &ctx, tree_addr); - sig += SPX_TREE_HEIGHT * SPX_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); - tree = tree >> SPX_TREE_HEIGHT; - } - - // cleanup - free_hash_function(&ctx); - - /* Check if the root node equals the root node in the public key. */ - if (memcmp(root, pub_root, SPX_N) != 0) { - return -1; - } - - return 0; -} - - -/** - * Returns an array containing the signature followed by the message. - */ -int crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk) { - size_t siglen; - - crypto_sign_signature(sm, &siglen, m, mlen, sk); - - memmove(sm + SPX_BYTES, m, mlen); - *smlen = siglen + mlen; - - return 0; -} - -/** - * Verifies a given signature-message pair under a given public key. - */ -int crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk) { - /* The API caller does not necessarily know what size a signature should be - but SPHINCS+ signatures are always exactly SPX_BYTES. */ - if (smlen < SPX_BYTES) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - *mlen = smlen - SPX_BYTES; - - if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - /* If verification was successful, move the message to the right place. */ - memmove(m, sm + SPX_BYTES, *mlen); - - return 0; -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/thash.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/thash.h deleted file mode 100644 index 8687ccfb4d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/thash.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef SPX_THASH_H -#define SPX_THASH_H - -#include "context.h" -#include "params.h" - -#include - -#define thash SPX_NAMESPACE(thash) -void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/thash_haraka_robust.c b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/thash_haraka_robust.c deleted file mode 100644 index 109502cbc2..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/thash_haraka_robust.c +++ /dev/null @@ -1,45 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "thash.h" -#include "utils.h" - -#include "haraka.h" - -/** - * Takes an array of inblocks concatenated arrays of SPX_N bytes. - */ -void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]) { - PQCLEAN_VLA(uint8_t, buf, SPX_ADDR_BYTES + inblocks * SPX_N); - PQCLEAN_VLA(uint8_t, bitmask, inblocks * SPX_N); - unsigned char outbuf[32]; - unsigned char buf_tmp[64]; - unsigned int i; - - if (inblocks == 1) { - /* F function */ - /* Since SPX_N may be smaller than 32, we need a temporary buffer. */ - memset(buf_tmp, 0, 64); - memcpy(buf_tmp, addr, 32); - - haraka256(outbuf, buf_tmp, ctx); - for (i = 0; i < inblocks * SPX_N; i++) { - buf_tmp[SPX_ADDR_BYTES + i] = in[i] ^ outbuf[i]; - } - haraka512(outbuf, buf_tmp, ctx); - memcpy(out, outbuf, SPX_N); - } else { - /* All other tweakable hashes*/ - memcpy(buf, addr, 32); - haraka_S(bitmask, inblocks * SPX_N, buf, SPX_ADDR_BYTES, ctx); - - for (i = 0; i < inblocks * SPX_N; i++) { - buf[SPX_ADDR_BYTES + i] = in[i] ^ bitmask[i]; - } - - haraka_S(out, SPX_N, buf, SPX_ADDR_BYTES + inblocks * SPX_N, ctx); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/thash_haraka_robustx4.c b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/thash_haraka_robustx4.c deleted file mode 100644 index 100808a3a5..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/thash_haraka_robustx4.c +++ /dev/null @@ -1,93 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "thashx4.h" - -#include "harakax4.h" - -#include "utils.h" - -/** - * 4-way parallel version of thash; takes 4x as much input and output - */ -#define thashx4 SPX_NAMESPACE(thashx4) -void thashx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addrx4[4 * 8]) { - PQCLEAN_VLA(unsigned char, buf0, SPX_ADDR_BYTES + inblocks * SPX_N); - PQCLEAN_VLA(unsigned char, buf1, SPX_ADDR_BYTES + inblocks * SPX_N); - PQCLEAN_VLA(unsigned char, buf2, SPX_ADDR_BYTES + inblocks * SPX_N); - PQCLEAN_VLA(unsigned char, buf3, SPX_ADDR_BYTES + inblocks * SPX_N); - PQCLEAN_VLA(unsigned char, bitmask0, inblocks * SPX_N); - PQCLEAN_VLA(unsigned char, bitmask1, inblocks * SPX_N); - PQCLEAN_VLA(unsigned char, bitmask2, inblocks * SPX_N); - PQCLEAN_VLA(unsigned char, bitmask3, inblocks * SPX_N); - unsigned char outbuf[32 * 4]; - unsigned char buf_tmp[64 * 4]; - unsigned int i; - - if (inblocks == 1) { - memset(buf_tmp, 0, 64 * 4); - - // Generate masks first in buffer - memcpy(buf_tmp, addrx4 + 0 * 8, 32); - memcpy(buf_tmp + 32, addrx4 + 1 * 8, 32); - memcpy(buf_tmp + 64, addrx4 + 2 * 8, 32); - memcpy(buf_tmp + 96, addrx4 + 3 * 8, 32); - - haraka256x4(outbuf, buf_tmp, ctx); - - /* move addresses to make room for inputs; zero old values */ - memcpy(buf_tmp + 192, buf_tmp + 96, SPX_ADDR_BYTES); - memcpy(buf_tmp + 128, buf_tmp + 64, SPX_ADDR_BYTES); - memcpy(buf_tmp + 64, buf_tmp + 32, SPX_ADDR_BYTES); - /* skip memcpy(buf_tmp, buf_tmp, SPX_ADDR_BYTES); already in place */ - - /* skip memset(buf_tmp, 0, SPX_ADDR_BYTES); remained untouched */ - memset(buf_tmp + 32, 0, SPX_ADDR_BYTES); - /* skip memset(buf_tmp + 64, 0, SPX_ADDR_BYTES); contains addr1 */ - memset(buf_tmp + 96, 0, SPX_ADDR_BYTES); - - for (i = 0; i < SPX_N; i++) { - buf_tmp[SPX_ADDR_BYTES + i] = in0[i] ^ outbuf[i]; - buf_tmp[SPX_ADDR_BYTES + i + 64] = in1[i] ^ outbuf[i + 32]; - buf_tmp[SPX_ADDR_BYTES + i + 128] = in2[i] ^ outbuf[i + 64]; - buf_tmp[SPX_ADDR_BYTES + i + 192] = in3[i] ^ outbuf[i + 96]; - } - - haraka512x4(outbuf, buf_tmp, ctx); - - memcpy(out0, outbuf, SPX_N); - memcpy(out1, outbuf + 32, SPX_N); - memcpy(out2, outbuf + 64, SPX_N); - memcpy(out3, outbuf + 96, SPX_N); - } else { - /* All other tweakable hashes*/ - memcpy(buf0, addrx4 + 0 * 8, 32); - memcpy(buf1, addrx4 + 1 * 8, 32); - memcpy(buf2, addrx4 + 2 * 8, 32); - memcpy(buf3, addrx4 + 3 * 8, 32); - - haraka_Sx4(bitmask0, bitmask1, bitmask2, bitmask3, inblocks * SPX_N, - buf0, buf1, buf2, buf3, SPX_ADDR_BYTES, ctx); - - for (i = 0; i < inblocks * SPX_N; i++) { - buf0[SPX_ADDR_BYTES + i] = in0[i] ^ bitmask0[i]; - buf1[SPX_ADDR_BYTES + i] = in1[i] ^ bitmask1[i]; - buf2[SPX_ADDR_BYTES + i] = in2[i] ^ bitmask2[i]; - buf3[SPX_ADDR_BYTES + i] = in3[i] ^ bitmask3[i]; - } - - haraka_Sx4(out0, out1, out2, out3, SPX_N, - buf0, buf1, buf2, buf3, SPX_ADDR_BYTES + inblocks * SPX_N, - ctx); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/thashx4.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/thashx4.h deleted file mode 100644 index 64798a3727..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/thashx4.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef SPX_THASHX4_H -#define SPX_THASHX4_H - -#include - -#include "context.h" -#include "params.h" - -#define thashx4 SPX_NAMESPACE(thashx4) -void thashx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addrx4[4 * 8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/utils.c b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/utils.c deleted file mode 100644 index 177b541fb9..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/utils.c +++ /dev/null @@ -1,148 +0,0 @@ -#include - -#include "utils.h" - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "thash.h" - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void ull_to_bytes(unsigned char *out, unsigned int outlen, - unsigned long long in) { - int i; - - /* Iterate over out in decreasing order, for big-endianness. */ - for (i = (signed int)outlen - 1; i >= 0; i--) { - out[i] = in & 0xff; - in = in >> 8; - } -} - -void u32_to_bytes(unsigned char *out, uint32_t in) { - out[0] = (unsigned char)(in >> 24); - out[1] = (unsigned char)(in >> 16); - out[2] = (unsigned char)(in >> 8); - out[3] = (unsigned char)in; -} - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { - unsigned long long retval = 0; - unsigned int i; - - for (i = 0; i < inlen; i++) { - retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); - } - return retval; -} - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void compute_root(unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const spx_ctx *ctx, uint32_t addr[8]) { - uint32_t i; - unsigned char buffer[2 * SPX_N]; - - /* If leaf_idx is odd (last bit = 1), current path element is a right child - and auth_path has to go left. Otherwise it is the other way around. */ - if (leaf_idx & 1) { - memcpy(buffer + SPX_N, leaf, SPX_N); - memcpy(buffer, auth_path, SPX_N); - } else { - memcpy(buffer, leaf, SPX_N); - memcpy(buffer + SPX_N, auth_path, SPX_N); - } - auth_path += SPX_N; - - for (i = 0; i < tree_height - 1; i++) { - leaf_idx >>= 1; - idx_offset >>= 1; - /* Set the address of the node we're creating. */ - set_tree_height(addr, i + 1); - set_tree_index(addr, leaf_idx + idx_offset); - - /* Pick the right or left neighbor, depending on parity of the node. */ - if (leaf_idx & 1) { - thash(buffer + SPX_N, buffer, 2, ctx, addr); - memcpy(buffer, auth_path, SPX_N); - } else { - thash(buffer, buffer, 2, ctx, addr); - memcpy(buffer + SPX_N, auth_path, SPX_N); - } - auth_path += SPX_N; - } - - /* The last iteration is exceptional; we do not copy an auth_path node. */ - leaf_idx >>= 1; - idx_offset >>= 1; - set_tree_height(addr, tree_height); - set_tree_index(addr, leaf_idx + idx_offset); - thash(root, buffer, 2, ctx, addr); -} - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const spx_ctx * /* ctx */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), - uint32_t tree_addr[8]) { - PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); - PQCLEAN_VLA(unsigned int, heights, tree_height + 1); - unsigned int offset = 0; - uint32_t idx; - uint32_t tree_idx; - - for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { - /* Add the next leaf node to the stack. */ - gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); - offset++; - heights[offset - 1] = 0; - - /* If this is a node we need for the auth path.. */ - if ((leaf_idx ^ 0x1) == idx) { - memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); - } - - /* While the top-most nodes are of equal height.. */ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { - /* Compute index of the new node, in the next layer. */ - tree_idx = (idx >> (heights[offset - 1] + 1)); - - /* Set the address of the node we're creating. */ - set_tree_height(tree_addr, heights[offset - 1] + 1); - set_tree_index(tree_addr, - tree_idx + (idx_offset >> (heights[offset - 1] + 1))); - /* Hash the top-most nodes from the stack together. */ - thash(stack + (offset - 2)*SPX_N, - stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); - offset--; - /* Note that the top-most node is now one layer higher. */ - heights[offset - 1]++; - - /* If this is a node we need for the auth path.. */ - if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_path + heights[offset - 1]*SPX_N, - stack + (offset - 1)*SPX_N, SPX_N); - } - } - } - memcpy(root, stack, SPX_N); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/utils.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/utils.h deleted file mode 100644 index 64f5d5a53a..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/utils.h +++ /dev/null @@ -1,58 +0,0 @@ -#ifndef SPX_UTILS_H -#define SPX_UTILS_H - -#include - -#include "compat.h" -#include "context.h" -#include "params.h" - - -/* To support MSVC use alloca() instead of VLAs. See #20. */ - - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) -void ull_to_bytes(unsigned char *out, unsigned int outlen, - unsigned long long in); -#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) -void u32_to_bytes(unsigned char *out, uint32_t in); - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) -unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -#define compute_root SPX_NAMESPACE(compute_root) -void compute_root(unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const spx_ctx *ctx, uint32_t addr[8]); - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -#define treehash SPX_NAMESPACE(treehash) -void treehash(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const spx_ctx *ctx /* ctx */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), - uint32_t tree_addr[8]); - - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/utilsx4.c b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/utilsx4.c deleted file mode 100644 index 1638677194..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/utilsx4.c +++ /dev/null @@ -1,138 +0,0 @@ -#include - -#include "utilsx4.h" - -#include "address.h" -#include "params.h" -#include "thashx4.h" -#include "utils.h" - -/* - * Generate the entire Merkle tree, computing the authentication path for leaf_idx, - * and the resulting root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) - * - * This expects tree_addrx4 to be initialized to 4 parallel addr structures for - * the Merkle tree nodes - * - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - * - * This works by using the standard Merkle tree building algorithm, except - * that each 'node' tracked is actually 4 consecutive nodes in the real tree. - * When we combine two logical nodes ABCD and WXYZ, we perform the H - * operation on adjacent real nodes, forming the parent logical node - * (AB)(CD)(WX)(YZ) - * - * When we get to the top two levels of the real tree (where there is only - * one logical node), we continue this operation two more times; the right - * most real node will by the actual root (and the other 3 nodes will be - * garbage). We follow the same thashx4 logic so that the 'extract - * authentication path components' part of the loop is still executed (and - * to simplify the code somewhat) - * - * This currently assumes tree_height >= 2; I suspect that doing an adjusting - * idx, addr_idx on the gen_leafx4 call if tree_height < 2 would fix it; since - * we don't actually use such short trees, I haven't bothered - */ -void treehashx4(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, - uint32_t tree_height, - void (*gen_leafx4)( - unsigned char * /* Where to write the leaves */, - const spx_ctx *, - uint32_t idx, void *info), - uint32_t tree_addrx4[4 * 8], - void *info) { - /* This is where we keep the intermediate nodes */ - PQCLEAN_VLA(unsigned char, stackx4, tree_height * 4 * SPX_N); - uint32_t left_adj = 0, prev_left_adj = 0; /* When we're doing the top 3 */ - /* levels, the left-most part of the tree isn't at the beginning */ - /* of current[]. These give the offset of the actual start */ - - uint32_t idx; - uint32_t max_idx = (1U << (tree_height - 2)) - 1; - for (idx = 0;; idx++) { - unsigned char current[4 * SPX_N]; /* Current logical node */ - gen_leafx4( current, ctx, 4 * idx + idx_offset, - info ); - - /* Now combine the freshly generated right node with previously */ - /* generated left ones */ - uint32_t internal_idx_offset = idx_offset; - uint32_t internal_idx = idx; - uint32_t internal_leaf = leaf_idx; - uint32_t h; /* The height we are in the Merkle tree */ - for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { - - /* Special processing if we're at the top of the tree */ - if (h >= tree_height - 2) { - if (h == tree_height) { - /* We hit the root; return it */ - memcpy( root, ¤t[3 * SPX_N], SPX_N ); - return; - } - /* The tree indexing logic is a bit off in this case */ - /* Adjust it so that the left-most node of the part of */ - /* the tree that we're processing has index 0 */ - prev_left_adj = left_adj; - left_adj = 4U - (1 << (tree_height - h - 1)); - } - - /* Check if we hit the top of the tree */ - if (h == tree_height) { - /* We hit the root; return it */ - memcpy( root, ¤t[3 * SPX_N], SPX_N ); - return; - } - - /* - * Check if one of the nodes we have is a part of the - * authentication path; if it is, write it out - */ - if ((((internal_idx << 2) ^ internal_leaf) & ~0x3U) == 0) { - memcpy( &auth_path[ h * SPX_N ], - ¤t[(((internal_leaf & 3) ^ 1) + prev_left_adj) * SPX_N], - SPX_N ); - } - - /* - * Check if we're at a left child; if so, stop going up the stack - * Exception: if we've reached the end of the tree, keep on going - * (so we combine the last 4 nodes into the one root node in two - * more iterations) - */ - if ((internal_idx & 1) == 0 && idx < max_idx) { - break; - } - - /* Ok, we're at a right node (or doing the top 3 levels) */ - /* Now combine the left and right logical nodes together */ - - /* Set the address of the node we're creating. */ - unsigned int j; - internal_idx_offset >>= 1; - for (j = 0; j < 4; j++) { - set_tree_height(tree_addrx4 + j * 8, h + 1); - set_tree_index(tree_addrx4 + j * 8, - (4 / 2) * (internal_idx & ~1U) + j - left_adj + internal_idx_offset ); - } - unsigned char *left = &stackx4[h * 4 * SPX_N]; - thashx4( ¤t[0 * SPX_N], - ¤t[1 * SPX_N], - ¤t[2 * SPX_N], - ¤t[3 * SPX_N], - &left [0 * SPX_N], - &left [2 * SPX_N], - ¤t[0 * SPX_N], - ¤t[2 * SPX_N], - 2, ctx, tree_addrx4); - } - - /* We've hit a left child; save the current for when we get the */ - /* corresponding right right */ - memcpy( &stackx4[h * 4 * SPX_N], current, 4 * SPX_N); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/utilsx4.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/utilsx4.h deleted file mode 100644 index facb874b18..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/utilsx4.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef SPX_UTILSX4_H -#define SPX_UTILSX4_H - -#include - -#include "context.h" -#include "params.h" - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - * - * This implementation uses AVX to compute internal nodes 4 at a time (in - * parallel) - */ -#define treehashx4 SPX_NAMESPACE(treehashx4) -void treehashx4(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leafx4)( - unsigned char * /* Where to write the leaves */, - const spx_ctx * /* ctx */, - uint32_t addr_idx, void *info), - uint32_t tree_addrx4[4 * 8], void *info); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/wots.c b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/wots.c deleted file mode 100644 index 4d5041ce05..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/wots.c +++ /dev/null @@ -1,269 +0,0 @@ -#include -#include - -#include "wots.h" - -#include "address.h" -#include "hash.h" -#include "hashx4.h" -#include "params.h" -#include "thash.h" -#include "thashx4.h" -#include "utils.h" -#include "utilsx4.h" -#include "wotsx4.h" - -// TODO clarify address expectations, and make them more uniform. -// TODO i.e. do we expect types to be set already? -// TODO and do we expect modifications or copies? - -/** - * Computes up the chains - */ -static void gen_chains( - unsigned char *out, - const unsigned char *in, - unsigned int start[SPX_WOTS_LEN], - const unsigned int steps[SPX_WOTS_LEN], - const spx_ctx *ctx, - uint32_t addr[8]) { - uint32_t i, j, k, idx, watching; - int done; - unsigned char empty[SPX_N]; - unsigned char *bufs[4]; - uint32_t addrs[8 * 4]; - - int l; - uint16_t counts[SPX_WOTS_W] = { 0 }; - uint16_t idxs[SPX_WOTS_LEN]; - uint16_t total, newTotal; - - /* set addrs = {addr, addr, addr, addr} */ - for (j = 0; j < 4; j++) { - memcpy(addrs + j * 8, addr, sizeof(uint32_t) * 8); - } - - /* Initialize out with the value at position 'start'. */ - memcpy(out, in, SPX_WOTS_LEN * SPX_N); - - /* Sort the chains in reverse order by steps using counting sort. */ - for (i = 0; i < SPX_WOTS_LEN; i++) { - counts[steps[i]]++; - } - total = 0; - for (l = SPX_WOTS_W - 1; l >= 0; l--) { - newTotal = counts[l] + total; - counts[l] = total; - total = newTotal; - } - for (i = 0; i < SPX_WOTS_LEN; i++) { - idxs[counts[steps[i]]] = (uint16_t)i; - counts[steps[i]]++; - } - - /* We got our work cut out for us: do it! */ - for (i = 0; i < SPX_WOTS_LEN; i += 4) { - for (j = 0; j < 4 && i + j < SPX_WOTS_LEN; j++) { - idx = idxs[i + j]; - set_chain_addr(addrs + j * 8, idx); - bufs[j] = out + SPX_N * idx; - } - - /* As the chains are sorted in reverse order, we know that the first - * chain is the longest and the last one is the shortest. We keep - * an eye on whether the last chain is done and then on the one before, - * et cetera. */ - watching = 3; - done = 0; - while (i + watching >= SPX_WOTS_LEN) { - bufs[watching] = &empty[0]; - watching--; - } - - for (k = 0;; k++) { - while (k == steps[idxs[i + watching]]) { - bufs[watching] = &empty[0]; - if (watching == 0) { - done = 1; - break; - } - watching--; - } - if (done) { - break; - } - for (j = 0; j < watching + 1; j++) { - set_hash_addr(addrs + j * 8, k + start[idxs[i + j]]); - } - - thashx4(bufs[0], bufs[1], bufs[2], bufs[3], - bufs[0], bufs[1], bufs[2], bufs[3], 1, ctx, addrs); - } - } -} - -/** - * base_w algorithm as described in draft. - * Interprets an array of bytes as integers in base w. - * This only works when log_w is a divisor of 8. - */ -static void base_w(unsigned int *output, const int out_len, - const unsigned char *input) { - int in = 0; - int out = 0; - unsigned char total = 0; - int bits = 0; - int consumed; - - for (consumed = 0; consumed < out_len; consumed++) { - if (bits == 0) { - total = input[in]; - in++; - bits += 8; - } - bits -= SPX_WOTS_LOGW; - output[out] = (total >> bits) & (SPX_WOTS_W - 1); - out++; - } -} - -/* Computes the WOTS+ checksum over a message (in base_w). */ -static void wots_checksum(unsigned int *csum_base_w, - const unsigned int *msg_base_w) { - unsigned int csum = 0; - unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; - unsigned int i; - - /* Compute checksum. */ - for (i = 0; i < SPX_WOTS_LEN1; i++) { - csum += SPX_WOTS_W - 1 - msg_base_w[i]; - } - - /* Convert checksum to base_w. */ - /* Make sure expected empty zero bits are the least significant bits. */ - csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); - ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); - base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); -} - -/* Takes a message and derives the matching chain lengths. */ -void chain_lengths(unsigned int *lengths, const unsigned char *msg) { - base_w(lengths, SPX_WOTS_LEN1, msg); - wots_checksum(lengths + SPX_WOTS_LEN1, lengths); -} - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const spx_ctx *ctx, uint32_t addr[8]) { - unsigned int steps[SPX_WOTS_LEN]; - unsigned int start[SPX_WOTS_LEN]; - uint32_t i; - - chain_lengths(start, msg); - - for (i = 0; i < SPX_WOTS_LEN; i++) { - steps[i] = SPX_WOTS_W - 1 - start[i]; - } - - gen_chains(pk, sig, start, steps, ctx, addr); -} - -/* - * This generates 4 sequential WOTS public keys - * It also generates the WOTS signature if leaf_info indicates - * that we're signing with one of these WOTS keys - */ -void wots_gen_leafx4(unsigned char *dest, - const spx_ctx *ctx, - uint32_t leaf_idx, void *v_info) { - struct leaf_info_x4 *info = v_info; - uint32_t *leaf_addr = info->leaf_addr; - uint32_t *pk_addr = info->pk_addr; - unsigned int i, j, k; - unsigned char pk_buffer[ 4 * SPX_WOTS_BYTES ]; - unsigned wots_offset = SPX_WOTS_BYTES; - unsigned char *buffer; - uint32_t wots_k_mask; - unsigned wots_sign_index; - - if (((leaf_idx ^ info->wots_sign_leaf) & ~3U) == 0) { - /* We're traversing the leaf that's signing; generate the WOTS */ - /* signature */ - wots_k_mask = 0; - wots_sign_index = info->wots_sign_leaf & 3; /* Which of of the 4 */ - /* 4 slots do the signatures come from */ - } else { - /* Nope, we're just generating pk's; turn off the signature logic */ - wots_k_mask = (uint32_t)~0; - wots_sign_index = 0; - } - - for (j = 0; j < 4; j++) { - set_keypair_addr( leaf_addr + j * 8, leaf_idx + j ); - set_keypair_addr( pk_addr + j * 8, leaf_idx + j ); - } - - for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { - uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k to */ - /* the step if we're generating a signature, ~0 if we're not */ - - /* Start with the secret seed */ - for (j = 0; j < 4; j++) { - set_chain_addr(leaf_addr + j * 8, i); - set_hash_addr(leaf_addr + j * 8, 0); - set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTSPRF); - } - prf_addrx4(buffer + 0 * wots_offset, - buffer + 1 * wots_offset, - buffer + 2 * wots_offset, - buffer + 3 * wots_offset, - ctx, leaf_addr); - - for (j = 0; j < 4; j++) { - set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTS); - } - - /* Iterate down the WOTS chain */ - for (k = 0;; k++) { - /* Check if one of the values we have needs to be saved as a */ - /* part of the WOTS signature */ - if (k == wots_k) { - memcpy( info->wots_sig + i * SPX_N, - buffer + wots_sign_index * wots_offset, SPX_N ); - } - - /* Check if we hit the top of the chain */ - if (k == SPX_WOTS_W - 1) { - break; - } - - /* Iterate one step on all 4 chains */ - for (j = 0; j < 4; j++) { - set_hash_addr(leaf_addr + j * 8, k); - } - thashx4(buffer + 0 * wots_offset, - buffer + 1 * wots_offset, - buffer + 2 * wots_offset, - buffer + 3 * wots_offset, - buffer + 0 * wots_offset, - buffer + 1 * wots_offset, - buffer + 2 * wots_offset, - buffer + 3 * wots_offset, 1, ctx, leaf_addr); - } - } - - /* Do the final thash to generate the public keys */ - thashx4(dest + 0 * SPX_N, - dest + 1 * SPX_N, - dest + 2 * SPX_N, - dest + 3 * SPX_N, - pk_buffer + 0 * wots_offset, - pk_buffer + 1 * wots_offset, - pk_buffer + 2 * wots_offset, - pk_buffer + 3 * wots_offset, SPX_WOTS_LEN, ctx, pk_addr); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/wots.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/wots.h deleted file mode 100644 index 4e7692eeef..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/wots.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef SPX_WOTS_H -#define SPX_WOTS_H - -#include - -#include "context.h" -#include "params.h" - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) -void wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const spx_ctx *ctx, uint32_t addr[8]); - -/* - * Compute the chain lengths needed for a given message hash - */ -#define chain_lengths SPX_NAMESPACE(chain_lengths) -void chain_lengths(unsigned int *lengths, const unsigned char *msg); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/wotsx4.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/wotsx4.h deleted file mode 100644 index cd634f1743..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_aesni/wotsx4.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef WOTSX4_H_ -#define WOTSX4_H_ - -#include - -#include "params.h" - -/* - * This is here to provide an interface to the internal wots_gen_leafx4 - * routine. While this routine is not referenced in the package outside of - * wots.c, it is called from the stand-alone benchmark code to characterize - * the performance - */ -struct leaf_info_x4 { - unsigned char *wots_sig; - uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ - uint32_t *wots_steps; - uint32_t leaf_addr[4 * 8]; - uint32_t pk_addr[4 * 8]; -}; - -/* Macro to set the leaf_info to something 'benign', that is, it would */ -/* run with the same time as it does during the real signing process */ -/* Used only by the benchmark code */ -#define INITIALIZE_LEAF_INFO_X4(info, addr, step_buffer) { \ - (info).wots_sig = 0; \ - (info).wots_sign_leaf = ~0; \ - (info).wots_steps = step_buffer; \ - int i; \ - for (i=0; i<4; i++) { \ - memcpy( &(info).leaf_addr[8*i], addr, 32 ); \ - memcpy( &(info).pk_addr[8*i], addr, 32 ); \ - } \ - } - -#define wots_gen_leafx4 SPX_NAMESPACE(wots_gen_leafx4) -void wots_gen_leafx4(unsigned char *dest, - const spx_ctx *ctx, - uint32_t leaf_idx, void *v_info); - -#endif /* WOTSX4_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/LICENSE b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/LICENSE deleted file mode 100644 index 670154e353..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/LICENSE +++ /dev/null @@ -1,116 +0,0 @@ -CC0 1.0 Universal - -Statement of Purpose - -The laws of most jurisdictions throughout the world automatically confer -exclusive Copyright and Related Rights (defined below) upon the creator and -subsequent owner(s) (each and all, an "owner") of an original work of -authorship and/or a database (each, a "Work"). - -Certain owners wish to permanently relinquish those rights to a Work for the -purpose of contributing to a commons of creative, cultural and scientific -works ("Commons") that the public can reliably and without fear of later -claims of infringement build upon, modify, incorporate in other works, reuse -and redistribute as freely as possible in any form whatsoever and for any -purposes, including without limitation commercial purposes. These owners may -contribute to the Commons to promote the ideal of a free culture and the -further production of creative, cultural and scientific works, or to gain -reputation or greater distribution for their Work in part through the use and -efforts of others. - -For these and/or other purposes and motivations, and without any expectation -of additional consideration or compensation, the person associating CC0 with a -Work (the "Affirmer"), to the extent that he or she is an owner of Copyright -and Related Rights in the Work, voluntarily elects to apply CC0 to the Work -and publicly distribute the Work under its terms, with knowledge of his or her -Copyright and Related Rights in the Work and the meaning and intended legal -effect of CC0 on those rights. - -1. Copyright and Related Rights. A Work made available under CC0 may be -protected by copyright and related or neighboring rights ("Copyright and -Related Rights"). Copyright and Related Rights include, but are not limited -to, the following: - - i. the right to reproduce, adapt, distribute, perform, display, communicate, - and translate a Work; - - ii. moral rights retained by the original author(s) and/or performer(s); - - iii. publicity and privacy rights pertaining to a person's image or likeness - depicted in a Work; - - iv. rights protecting against unfair competition in regards to a Work, - subject to the limitations in paragraph 4(a), below; - - v. rights protecting the extraction, dissemination, use and reuse of data in - a Work; - - vi. database rights (such as those arising under Directive 96/9/EC of the - European Parliament and of the Council of 11 March 1996 on the legal - protection of databases, and under any national implementation thereof, - including any amended or successor version of such directive); and - - vii. other similar, equivalent or corresponding rights throughout the world - based on applicable law or treaty, and any national implementations thereof. - -2. Waiver. To the greatest extent permitted by, but not in contravention of, -applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and -unconditionally waives, abandons, and surrenders all of Affirmer's Copyright -and Related Rights and associated claims and causes of action, whether now -known or unknown (including existing as well as future claims and causes of -action), in the Work (i) in all territories worldwide, (ii) for the maximum -duration provided by applicable law or treaty (including future time -extensions), (iii) in any current or future medium and for any number of -copies, and (iv) for any purpose whatsoever, including without limitation -commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes -the Waiver for the benefit of each member of the public at large and to the -detriment of Affirmer's heirs and successors, fully intending that such Waiver -shall not be subject to revocation, rescission, cancellation, termination, or -any other legal or equitable action to disrupt the quiet enjoyment of the Work -by the public as contemplated by Affirmer's express Statement of Purpose. - -3. Public License Fallback. Should any part of the Waiver for any reason be -judged legally invalid or ineffective under applicable law, then the Waiver -shall be preserved to the maximum extent permitted taking into account -Affirmer's express Statement of Purpose. In addition, to the extent the Waiver -is so judged Affirmer hereby grants to each affected person a royalty-free, -non transferable, non sublicensable, non exclusive, irrevocable and -unconditional license to exercise Affirmer's Copyright and Related Rights in -the Work (i) in all territories worldwide, (ii) for the maximum duration -provided by applicable law or treaty (including future time extensions), (iii) -in any current or future medium and for any number of copies, and (iv) for any -purpose whatsoever, including without limitation commercial, advertising or -promotional purposes (the "License"). The License shall be deemed effective as -of the date CC0 was applied by Affirmer to the Work. Should any part of the -License for any reason be judged legally invalid or ineffective under -applicable law, such partial invalidity or ineffectiveness shall not -invalidate the remainder of the License, and in such case Affirmer hereby -affirms that he or she will not (i) exercise any of his or her remaining -Copyright and Related Rights in the Work or (ii) assert any associated claims -and causes of action with respect to the Work, in either case contrary to -Affirmer's express Statement of Purpose. - -4. Limitations and Disclaimers. - - a. No trademark or patent rights held by Affirmer are waived, abandoned, - surrendered, licensed or otherwise affected by this document. - - b. Affirmer offers the Work as-is and makes no representations or warranties - of any kind concerning the Work, express, implied, statutory or otherwise, - including without limitation warranties of title, merchantability, fitness - for a particular purpose, non infringement, or the absence of latent or - other defects, accuracy, or the present or absence of errors, whether or not - discoverable, all to the greatest extent permissible under applicable law. - - c. Affirmer disclaims responsibility for clearing rights of other persons - that may apply to the Work or any use thereof, including without limitation - any person's Copyright and Related Rights in the Work. Further, Affirmer - disclaims responsibility for obtaining any necessary consents, permissions - or other rights required for any use of the Work. - - d. Affirmer understands and acknowledges that Creative Commons is not a - party to this document and has no duty or obligation with respect to this - CC0 or use of the Work. - -For more information, please see - diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/address.c b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/address.c deleted file mode 100644 index d49d9f3b6b..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/address.c +++ /dev/null @@ -1,95 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "utils.h" - -/* - * Specify which level of Merkle tree (the "layer") we're working on - */ -void set_layer_addr(uint32_t addr[8], uint32_t layer) { - ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; -} - -/* - * Specify which Merkle tree within the level (the "tree address") we're working on - */ -void set_tree_addr(uint32_t addr[8], uint64_t tree) { - ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); -} - -/* - * Specify the reason we'll use this address structure for, that is, what - * hash will we compute with it. This is used so that unrelated types of - * hashes don't accidentally get the same address structure. The type will be - * one of the SPX_ADDR_TYPE constants - */ -void set_type(uint32_t addr[8], uint32_t type) { - ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; -} - -/* - * Copy the layer and tree fields of the address structure. This is used - * when we're doing multiple types of hashes within the same Merkle tree - */ -void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { - memcpy( out, in, SPX_OFFSET_TREE + 8 ); -} - -/* These functions are used for OTS addresses. */ - -/* - * Specify which Merkle leaf we're working on; that is, which OTS keypair - * we're talking about. - */ -void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { - /* We have > 256 OTS at the bottom of the Merkle tree; to specify */ - /* which one, we'd need to express it in two bytes */ - ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR2] = (unsigned char)(keypair >> 8); - ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; -} - -/* - * Copy the layer, tree and keypair fields of the address structure. This is - * used when we're doing multiple things within the same OTS keypair - */ -void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { - memcpy( out, in, SPX_OFFSET_TREE + 8 ); - ((unsigned char *)out)[SPX_OFFSET_KP_ADDR2] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR2]; - ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; -} - -/* - * Specify which Merkle chain within the OTS we're working with - * (the chain address) - */ -void set_chain_addr(uint32_t addr[8], uint32_t chain) { - ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; -} - -/* - * Specify where in the Merkle chain we are -* (the hash address) - */ -void set_hash_addr(uint32_t addr[8], uint32_t hash) { - ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; -} - -/* These functions are used for all hash tree addresses (including FORS). */ - -/* - * Specify the height of the node in the Merkle/FORS tree we are in - * (the tree height) - */ -void set_tree_height(uint32_t addr[8], uint32_t tree_height) { - ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; -} - -/* - * Specify the distance from the left edge of the node in the Merkle/FORS tree - * (the tree index) - */ -void set_tree_index(uint32_t addr[8], uint32_t tree_index) { - u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/address.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/address.h deleted file mode 100644 index 24a84eb40c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/address.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef SPX_ADDRESS_H -#define SPX_ADDRESS_H - -#include - -#include "params.h" - -/* The hash types that are passed to set_type */ -#define SPX_ADDR_TYPE_WOTS 0 -#define SPX_ADDR_TYPE_WOTSPK 1 -#define SPX_ADDR_TYPE_HASHTREE 2 -#define SPX_ADDR_TYPE_FORSTREE 3 -#define SPX_ADDR_TYPE_FORSPK 4 -#define SPX_ADDR_TYPE_WOTSPRF 5 -#define SPX_ADDR_TYPE_FORSPRF 6 - -#define set_layer_addr SPX_NAMESPACE(set_layer_addr) -void set_layer_addr(uint32_t addr[8], uint32_t layer); - -#define set_tree_addr SPX_NAMESPACE(set_tree_addr) -void set_tree_addr(uint32_t addr[8], uint64_t tree); - -#define set_type SPX_NAMESPACE(set_type) -void set_type(uint32_t addr[8], uint32_t type); - -/* Copies the layer and tree part of one address into the other */ -#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) -void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for WOTS and FORS addresses. */ - -#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) -void set_keypair_addr(uint32_t addr[8], uint32_t keypair); - -#define set_chain_addr SPX_NAMESPACE(set_chain_addr) -void set_chain_addr(uint32_t addr[8], uint32_t chain); - -#define set_hash_addr SPX_NAMESPACE(set_hash_addr) -void set_hash_addr(uint32_t addr[8], uint32_t hash); - -#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) -void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for all hash tree addresses (including FORS). */ - -#define set_tree_height SPX_NAMESPACE(set_tree_height) -void set_tree_height(uint32_t addr[8], uint32_t tree_height); - -#define set_tree_index SPX_NAMESPACE(set_tree_index) -void set_tree_index(uint32_t addr[8], uint32_t tree_index); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/api.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/api.h deleted file mode 100644 index 43aa4622f3..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/api.h +++ /dev/null @@ -1,77 +0,0 @@ -#ifndef PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_API_H -#define PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_API_H - -#include -#include - -#define PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_CRYPTO_ALGNAME "SPHINCS+-haraka-128s-robust" - -#define PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_CRYPTO_SECRETKEYBYTES 64 -#define PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_CRYPTO_PUBLICKEYBYTES 32 -#define PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_CRYPTO_BYTES 7856 - -#define PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_CRYPTO_SEEDBYTES 48 - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, - const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk); -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/context.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/context.h deleted file mode 100644 index 600dfb73c7..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/context.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef SPX_CONTEXT_H -#define SPX_CONTEXT_H - -#include -#include - -#include "params.h" - -typedef struct { - uint8_t pub_seed[SPX_N]; - uint8_t sk_seed[SPX_N]; - - - uint64_t tweaked512_rc64[10][8]; - uint32_t tweaked256_rc32[10][8]; -} spx_ctx; - -#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) -void initialize_hash_function(spx_ctx *ctx); - -#define free_hash_function SPX_NAMESPACE(free_hash_function) -void free_hash_function(spx_ctx *ctx); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/context_haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/context_haraka.c deleted file mode 100644 index f1cd7e3664..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/context_haraka.c +++ /dev/null @@ -1,11 +0,0 @@ -#include "context.h" -#include "haraka.h" - -void initialize_hash_function(spx_ctx *ctx) { - tweak_constants(ctx); -} - -// we don't support heap-based haraka right now -void free_hash_function(spx_ctx *ctx) { - (void)ctx; // suppress unused variable warnings -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/fors.c b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/fors.c deleted file mode 100644 index 96ca72e986..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/fors.c +++ /dev/null @@ -1,156 +0,0 @@ -#include -#include -#include - -#include "fors.h" - -#include "address.h" -#include "hash.h" -#include "thash.h" -#include "utils.h" -#include "utilsx1.h" - -static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, - uint32_t fors_leaf_addr[8]) { - prf_addr(sk, ctx, fors_leaf_addr); -} - -static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, - const spx_ctx *ctx, - uint32_t fors_leaf_addr[8]) { - thash(leaf, sk, 1, ctx, fors_leaf_addr); -} - -struct fors_gen_leaf_info { - uint32_t leaf_addrx[8]; -}; - -static void fors_gen_leafx1(unsigned char *leaf, - const spx_ctx *ctx, - uint32_t addr_idx, void *info) { - struct fors_gen_leaf_info *fors_info = info; - uint32_t *fors_leaf_addr = fors_info->leaf_addrx; - - /* Only set the parts that the caller doesn't set */ - set_tree_index(fors_leaf_addr, addr_idx); - set_type(fors_leaf_addr, SPX_ADDR_TYPE_FORSPRF); - fors_gen_sk(leaf, ctx, fors_leaf_addr); - - set_type(fors_leaf_addr, SPX_ADDR_TYPE_FORSTREE); - fors_sk_to_leaf(leaf, leaf, - ctx, fors_leaf_addr); -} - -/** - * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - * Assumes indices has space for SPX_FORS_TREES integers. - */ -static void message_to_indices(uint32_t *indices, const unsigned char *m) { - unsigned int i, j; - unsigned int offset = 0; - - for (i = 0; i < SPX_FORS_TREES; i++) { - indices[i] = 0; - for (j = 0; j < SPX_FORS_HEIGHT; j++) { - indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); - offset++; - } - } -} - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -void fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]) { - uint32_t indices[SPX_FORS_TREES]; - unsigned char roots[SPX_FORS_TREES * SPX_N]; - uint32_t fors_tree_addr[8] = {0}; - struct fors_gen_leaf_info fors_info = {0}; - uint32_t *fors_leaf_addr = fors_info.leaf_addrx; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - copy_keypair_addr(fors_tree_addr, fors_addr); - copy_keypair_addr(fors_leaf_addr, fors_addr); - - copy_keypair_addr(fors_pk_addr, fors_addr); - set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < SPX_FORS_TREES; i++) { - idx_offset = i * (1 << SPX_FORS_HEIGHT); - - set_tree_height(fors_tree_addr, 0); - set_tree_index(fors_tree_addr, indices[i] + idx_offset); - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); - - /* Include the secret key part that produces the selected leaf node. */ - fors_gen_sk(sig, ctx, fors_tree_addr); - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); - sig += SPX_N; - - /* Compute the authentication path for this leaf node. */ - treehashx1(roots + i * SPX_N, sig, ctx, - indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx1, - fors_tree_addr, &fors_info); - - sig += SPX_N * SPX_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); -} - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -void fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]) { - uint32_t indices[SPX_FORS_TREES]; - unsigned char roots[SPX_FORS_TREES * SPX_N]; - unsigned char leaf[SPX_N]; - uint32_t fors_tree_addr[8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - copy_keypair_addr(fors_tree_addr, fors_addr); - copy_keypair_addr(fors_pk_addr, fors_addr); - - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); - set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < SPX_FORS_TREES; i++) { - idx_offset = i * (1 << SPX_FORS_HEIGHT); - - set_tree_height(fors_tree_addr, 0); - set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Derive the leaf from the included secret key part. */ - fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); - sig += SPX_N; - - /* Derive the corresponding root node of this tree. */ - compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, - sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); - sig += SPX_N * SPX_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/fors.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/fors.h deleted file mode 100644 index 509140a178..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/fors.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef SPX_FORS_H -#define SPX_FORS_H - -#include - -#include "context.h" -#include "params.h" - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -#define fors_sign SPX_NAMESPACE(fors_sign) -void fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]); - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) -void fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/haraka.c deleted file mode 100644 index a4944913b5..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/haraka.c +++ /dev/null @@ -1,913 +0,0 @@ -/* - * Constant time implementation of the Haraka hash function. - * - * The bit-sliced implementation of the AES round functions are - * based on the AES implementation in BearSSL written - * by Thomas Pornin - */ - -#include -#include -#include -#include - -#include "haraka.h" -#include "utils.h" - -#define HARAKAS_RATE 32 - -static const uint64_t haraka512_rc64[10][8] = { - {0x24cf0ab9086f628b, 0xbdd6eeecc83b8382, 0xd96fb0306cdad0a7, 0xaace082ac8f95f89, 0x449d8e8870d7041f, 0x49bb2f80b2b3e2f8, 0x0569ae98d93bb258, 0x23dc9691e7d6a4b1}, - {0xd8ba10ede0fe5b6e, 0x7ecf7dbe424c7b8e, 0x6ea9949c6df62a31, 0xbf3f3c97ec9c313e, 0x241d03a196a1861e, 0xead3a51116e5a2ea, 0x77d479fcad9574e3, 0x18657a1af894b7a0}, - {0x10671e1a7f595522, 0xd9a00ff675d28c7b, 0x2f1edf0d2b9ba661, 0xb8ff58b8e3de45f9, 0xee29261da9865c02, 0xd1532aa4b50bdf43, 0x8bf858159b231bb1, 0xdf17439d22d4f599}, - {0xdd4b2f0870b918c0, 0x757a81f3b39b1bb6, 0x7a5c556898952e3f, 0x7dd70a16d915d87a, 0x3ae61971982b8301, 0xc3ab319e030412be, 0x17c0033ac094a8cb, 0x5a0630fc1a8dc4ef}, - {0x17708988c1632f73, 0xf92ddae090b44f4f, 0x11ac0285c43aa314, 0x509059941936b8ba, 0xd03e152fa2ce9b69, 0x3fbcbcb63a32998b, 0x6204696d692254f7, 0x915542ed93ec59b4}, - {0xf4ed94aa8879236e, 0xff6cb41cd38e03c0, 0x069b38602368aeab, 0x669495b820f0ddba, 0xf42013b1b8bf9e3d, 0xcf935efe6439734d, 0xbc1dcf42ca29e3f8, 0x7e6d3ed29f78ad67}, - {0xf3b0f6837ffcddaa, 0x3a76faef934ddf41, 0xcec7ae583a9c8e35, 0xe4dd18c68f0260af, 0x2c0e5df1ad398eaa, 0x478df5236ae22e8c, 0xfb944c46fe865f39, 0xaa48f82f028132ba}, - {0x231b9ae2b76aca77, 0x292a76a712db0b40, 0x5850625dc8134491, 0x73137dd469810fb5, 0x8a12a6a202a474fd, 0xd36fd9daa78bdb80, 0xb34c5e733505706f, 0xbaf1cdca818d9d96}, - {0x2e99781335e8c641, 0xbddfe5cce47d560e, 0xf74e9bf32e5e040c, 0x1d7a709d65996be9, 0x670df36a9cf66cdd, 0xd05ef84a176a2875, 0x0f888e828cb1c44e, 0x1a79e9c9727b052c}, - {0x83497348628d84de, 0x2e9387d51f22a754, 0xb000068da2f852d6, 0x378c9e1190fd6fe5, 0x870027c316de7293, 0xe51a9d4462e047bb, 0x90ecf7f8c6251195, 0x655953bfbed90a9c}, -}; - -static inline uint32_t br_dec32le(const unsigned char *src) { - return (uint32_t)src[0] - | ((uint32_t)src[1] << 8) - | ((uint32_t)src[2] << 16) - | ((uint32_t)src[3] << 24); -} - -static void br_range_dec32le(uint32_t *v, size_t num, const unsigned char *src) { - while (num-- > 0) { - *v ++ = br_dec32le(src); - src += 4; - } -} - -static inline void br_enc32le(unsigned char *dst, uint32_t x) { - dst[0] = (unsigned char)x; - dst[1] = (unsigned char)(x >> 8); - dst[2] = (unsigned char)(x >> 16); - dst[3] = (unsigned char)(x >> 24); -} - - -static void br_range_enc32le(unsigned char *dst, const uint32_t *v, size_t num) { - while (num-- > 0) { - br_enc32le(dst, *v ++); - dst += 4; - } -} - -static void br_aes_ct64_bitslice_Sbox(uint64_t *q) { - /* - * This S-box implementation is a straightforward translation of - * the circuit described by Boyar and Peralta in "A new - * combinational logic minimization technique with applications - * to cryptology" (https://eprint.iacr.org/2009/191.pdf). - * - * Note that variables x* (input) and s* (output) are numbered - * in "reverse" order (x0 is the high bit, x7 is the low bit). - */ - - uint64_t x0, x1, x2, x3, x4, x5, x6, x7; - uint64_t y1, y2, y3, y4, y5, y6, y7, y8, y9; - uint64_t y10, y11, y12, y13, y14, y15, y16, y17, y18, y19; - uint64_t y20, y21; - uint64_t z0, z1, z2, z3, z4, z5, z6, z7, z8, z9; - uint64_t z10, z11, z12, z13, z14, z15, z16, z17; - uint64_t t0, t1, t2, t3, t4, t5, t6, t7, t8, t9; - uint64_t t10, t11, t12, t13, t14, t15, t16, t17, t18, t19; - uint64_t t20, t21, t22, t23, t24, t25, t26, t27, t28, t29; - uint64_t t30, t31, t32, t33, t34, t35, t36, t37, t38, t39; - uint64_t t40, t41, t42, t43, t44, t45, t46, t47, t48, t49; - uint64_t t50, t51, t52, t53, t54, t55, t56, t57, t58, t59; - uint64_t t60, t61, t62, t63, t64, t65, t66, t67; - uint64_t s0, s1, s2, s3, s4, s5, s6, s7; - - x0 = q[7]; - x1 = q[6]; - x2 = q[5]; - x3 = q[4]; - x4 = q[3]; - x5 = q[2]; - x6 = q[1]; - x7 = q[0]; - - /* - * Top linear transformation. - */ - y14 = x3 ^ x5; - y13 = x0 ^ x6; - y9 = x0 ^ x3; - y8 = x0 ^ x5; - t0 = x1 ^ x2; - y1 = t0 ^ x7; - y4 = y1 ^ x3; - y12 = y13 ^ y14; - y2 = y1 ^ x0; - y5 = y1 ^ x6; - y3 = y5 ^ y8; - t1 = x4 ^ y12; - y15 = t1 ^ x5; - y20 = t1 ^ x1; - y6 = y15 ^ x7; - y10 = y15 ^ t0; - y11 = y20 ^ y9; - y7 = x7 ^ y11; - y17 = y10 ^ y11; - y19 = y10 ^ y8; - y16 = t0 ^ y11; - y21 = y13 ^ y16; - y18 = x0 ^ y16; - - /* - * Non-linear section. - */ - t2 = y12 & y15; - t3 = y3 & y6; - t4 = t3 ^ t2; - t5 = y4 & x7; - t6 = t5 ^ t2; - t7 = y13 & y16; - t8 = y5 & y1; - t9 = t8 ^ t7; - t10 = y2 & y7; - t11 = t10 ^ t7; - t12 = y9 & y11; - t13 = y14 & y17; - t14 = t13 ^ t12; - t15 = y8 & y10; - t16 = t15 ^ t12; - t17 = t4 ^ t14; - t18 = t6 ^ t16; - t19 = t9 ^ t14; - t20 = t11 ^ t16; - t21 = t17 ^ y20; - t22 = t18 ^ y19; - t23 = t19 ^ y21; - t24 = t20 ^ y18; - - t25 = t21 ^ t22; - t26 = t21 & t23; - t27 = t24 ^ t26; - t28 = t25 & t27; - t29 = t28 ^ t22; - t30 = t23 ^ t24; - t31 = t22 ^ t26; - t32 = t31 & t30; - t33 = t32 ^ t24; - t34 = t23 ^ t33; - t35 = t27 ^ t33; - t36 = t24 & t35; - t37 = t36 ^ t34; - t38 = t27 ^ t36; - t39 = t29 & t38; - t40 = t25 ^ t39; - - t41 = t40 ^ t37; - t42 = t29 ^ t33; - t43 = t29 ^ t40; - t44 = t33 ^ t37; - t45 = t42 ^ t41; - z0 = t44 & y15; - z1 = t37 & y6; - z2 = t33 & x7; - z3 = t43 & y16; - z4 = t40 & y1; - z5 = t29 & y7; - z6 = t42 & y11; - z7 = t45 & y17; - z8 = t41 & y10; - z9 = t44 & y12; - z10 = t37 & y3; - z11 = t33 & y4; - z12 = t43 & y13; - z13 = t40 & y5; - z14 = t29 & y2; - z15 = t42 & y9; - z16 = t45 & y14; - z17 = t41 & y8; - - /* - * Bottom linear transformation. - */ - t46 = z15 ^ z16; - t47 = z10 ^ z11; - t48 = z5 ^ z13; - t49 = z9 ^ z10; - t50 = z2 ^ z12; - t51 = z2 ^ z5; - t52 = z7 ^ z8; - t53 = z0 ^ z3; - t54 = z6 ^ z7; - t55 = z16 ^ z17; - t56 = z12 ^ t48; - t57 = t50 ^ t53; - t58 = z4 ^ t46; - t59 = z3 ^ t54; - t60 = t46 ^ t57; - t61 = z14 ^ t57; - t62 = t52 ^ t58; - t63 = t49 ^ t58; - t64 = z4 ^ t59; - t65 = t61 ^ t62; - t66 = z1 ^ t63; - s0 = t59 ^ t63; - s6 = t56 ^ ~t62; - s7 = t48 ^ ~t60; - t67 = t64 ^ t65; - s3 = t53 ^ t66; - s4 = t51 ^ t66; - s5 = t47 ^ t65; - s1 = t64 ^ ~s3; - s2 = t55 ^ ~t67; - - q[7] = s0; - q[6] = s1; - q[5] = s2; - q[4] = s3; - q[3] = s4; - q[2] = s5; - q[1] = s6; - q[0] = s7; -} - -static void br_aes_ct_bitslice_Sbox(uint32_t *q) { - /* - * This S-box implementation is a straightforward translation of - * the circuit described by Boyar and Peralta in "A new - * combinational logic minimization technique with applications - * to cryptology" (https://eprint.iacr.org/2009/191.pdf). - * - * Note that variables x* (input) and s* (output) are numbered - * in "reverse" order (x0 is the high bit, x7 is the low bit). - */ - - uint32_t x0, x1, x2, x3, x4, x5, x6, x7; - uint32_t y1, y2, y3, y4, y5, y6, y7, y8, y9; - uint32_t y10, y11, y12, y13, y14, y15, y16, y17, y18, y19; - uint32_t y20, y21; - uint32_t z0, z1, z2, z3, z4, z5, z6, z7, z8, z9; - uint32_t z10, z11, z12, z13, z14, z15, z16, z17; - uint32_t t0, t1, t2, t3, t4, t5, t6, t7, t8, t9; - uint32_t t10, t11, t12, t13, t14, t15, t16, t17, t18, t19; - uint32_t t20, t21, t22, t23, t24, t25, t26, t27, t28, t29; - uint32_t t30, t31, t32, t33, t34, t35, t36, t37, t38, t39; - uint32_t t40, t41, t42, t43, t44, t45, t46, t47, t48, t49; - uint32_t t50, t51, t52, t53, t54, t55, t56, t57, t58, t59; - uint32_t t60, t61, t62, t63, t64, t65, t66, t67; - uint32_t s0, s1, s2, s3, s4, s5, s6, s7; - - x0 = q[7]; - x1 = q[6]; - x2 = q[5]; - x3 = q[4]; - x4 = q[3]; - x5 = q[2]; - x6 = q[1]; - x7 = q[0]; - - /* - * Top linear transformation. - */ - y14 = x3 ^ x5; - y13 = x0 ^ x6; - y9 = x0 ^ x3; - y8 = x0 ^ x5; - t0 = x1 ^ x2; - y1 = t0 ^ x7; - y4 = y1 ^ x3; - y12 = y13 ^ y14; - y2 = y1 ^ x0; - y5 = y1 ^ x6; - y3 = y5 ^ y8; - t1 = x4 ^ y12; - y15 = t1 ^ x5; - y20 = t1 ^ x1; - y6 = y15 ^ x7; - y10 = y15 ^ t0; - y11 = y20 ^ y9; - y7 = x7 ^ y11; - y17 = y10 ^ y11; - y19 = y10 ^ y8; - y16 = t0 ^ y11; - y21 = y13 ^ y16; - y18 = x0 ^ y16; - - /* - * Non-linear section. - */ - t2 = y12 & y15; - t3 = y3 & y6; - t4 = t3 ^ t2; - t5 = y4 & x7; - t6 = t5 ^ t2; - t7 = y13 & y16; - t8 = y5 & y1; - t9 = t8 ^ t7; - t10 = y2 & y7; - t11 = t10 ^ t7; - t12 = y9 & y11; - t13 = y14 & y17; - t14 = t13 ^ t12; - t15 = y8 & y10; - t16 = t15 ^ t12; - t17 = t4 ^ t14; - t18 = t6 ^ t16; - t19 = t9 ^ t14; - t20 = t11 ^ t16; - t21 = t17 ^ y20; - t22 = t18 ^ y19; - t23 = t19 ^ y21; - t24 = t20 ^ y18; - - t25 = t21 ^ t22; - t26 = t21 & t23; - t27 = t24 ^ t26; - t28 = t25 & t27; - t29 = t28 ^ t22; - t30 = t23 ^ t24; - t31 = t22 ^ t26; - t32 = t31 & t30; - t33 = t32 ^ t24; - t34 = t23 ^ t33; - t35 = t27 ^ t33; - t36 = t24 & t35; - t37 = t36 ^ t34; - t38 = t27 ^ t36; - t39 = t29 & t38; - t40 = t25 ^ t39; - - t41 = t40 ^ t37; - t42 = t29 ^ t33; - t43 = t29 ^ t40; - t44 = t33 ^ t37; - t45 = t42 ^ t41; - z0 = t44 & y15; - z1 = t37 & y6; - z2 = t33 & x7; - z3 = t43 & y16; - z4 = t40 & y1; - z5 = t29 & y7; - z6 = t42 & y11; - z7 = t45 & y17; - z8 = t41 & y10; - z9 = t44 & y12; - z10 = t37 & y3; - z11 = t33 & y4; - z12 = t43 & y13; - z13 = t40 & y5; - z14 = t29 & y2; - z15 = t42 & y9; - z16 = t45 & y14; - z17 = t41 & y8; - - /* - * Bottom linear transformation. - */ - t46 = z15 ^ z16; - t47 = z10 ^ z11; - t48 = z5 ^ z13; - t49 = z9 ^ z10; - t50 = z2 ^ z12; - t51 = z2 ^ z5; - t52 = z7 ^ z8; - t53 = z0 ^ z3; - t54 = z6 ^ z7; - t55 = z16 ^ z17; - t56 = z12 ^ t48; - t57 = t50 ^ t53; - t58 = z4 ^ t46; - t59 = z3 ^ t54; - t60 = t46 ^ t57; - t61 = z14 ^ t57; - t62 = t52 ^ t58; - t63 = t49 ^ t58; - t64 = z4 ^ t59; - t65 = t61 ^ t62; - t66 = z1 ^ t63; - s0 = t59 ^ t63; - s6 = t56 ^ ~t62; - s7 = t48 ^ ~t60; - t67 = t64 ^ t65; - s3 = t53 ^ t66; - s4 = t51 ^ t66; - s5 = t47 ^ t65; - s1 = t64 ^ ~s3; - s2 = t55 ^ ~t67; - - q[7] = s0; - q[6] = s1; - q[5] = s2; - q[4] = s3; - q[3] = s4; - q[2] = s5; - q[1] = s6; - q[0] = s7; -} - -static void br_aes_ct_ortho(uint32_t *q) { -#define SWAPN_32(cl, ch, s, x, y) do { \ - uint32_t a, b; \ - a = (x); \ - b = (y); \ - (x) = (a & (uint32_t)(cl)) | ((b & (uint32_t)(cl)) << (s)); \ - (y) = ((a & (uint32_t)(ch)) >> (s)) | (b & (uint32_t)(ch)); \ - } while (0) - -#define SWAP2_32(x, y) SWAPN_32(0x55555555, 0xAAAAAAAA, 1, x, y) -#define SWAP4_32(x, y) SWAPN_32(0x33333333, 0xCCCCCCCC, 2, x, y) -#define SWAP8_32(x, y) SWAPN_32(0x0F0F0F0F, 0xF0F0F0F0, 4, x, y) - - SWAP2_32(q[0], q[1]); - SWAP2_32(q[2], q[3]); - SWAP2_32(q[4], q[5]); - SWAP2_32(q[6], q[7]); - - SWAP4_32(q[0], q[2]); - SWAP4_32(q[1], q[3]); - SWAP4_32(q[4], q[6]); - SWAP4_32(q[5], q[7]); - - SWAP8_32(q[0], q[4]); - SWAP8_32(q[1], q[5]); - SWAP8_32(q[2], q[6]); - SWAP8_32(q[3], q[7]); -} - -static inline void add_round_key32(uint32_t *q, const uint32_t *sk) { - q[0] ^= sk[0]; - q[1] ^= sk[1]; - q[2] ^= sk[2]; - q[3] ^= sk[3]; - q[4] ^= sk[4]; - q[5] ^= sk[5]; - q[6] ^= sk[6]; - q[7] ^= sk[7]; -} - -static inline void shift_rows32(uint32_t *q) { - int i; - - for (i = 0; i < 8; i++) { - uint32_t x; - - x = q[i]; - q[i] = (x & 0x000000FF) - | ((x & 0x0000FC00) >> 2) | ((x & 0x00000300) << 6) - | ((x & 0x00F00000) >> 4) | ((x & 0x000F0000) << 4) - | ((x & 0xC0000000) >> 6) | ((x & 0x3F000000) << 2); - } -} - -static inline uint32_t rotr16(uint32_t x) { - return (x << 16) | (x >> 16); -} - -static inline void mix_columns32(uint32_t *q) { - uint32_t q0, q1, q2, q3, q4, q5, q6, q7; - uint32_t r0, r1, r2, r3, r4, r5, r6, r7; - - q0 = q[0]; - q1 = q[1]; - q2 = q[2]; - q3 = q[3]; - q4 = q[4]; - q5 = q[5]; - q6 = q[6]; - q7 = q[7]; - r0 = (q0 >> 8) | (q0 << 24); - r1 = (q1 >> 8) | (q1 << 24); - r2 = (q2 >> 8) | (q2 << 24); - r3 = (q3 >> 8) | (q3 << 24); - r4 = (q4 >> 8) | (q4 << 24); - r5 = (q5 >> 8) | (q5 << 24); - r6 = (q6 >> 8) | (q6 << 24); - r7 = (q7 >> 8) | (q7 << 24); - - q[0] = q7 ^ r7 ^ r0 ^ rotr16(q0 ^ r0); - q[1] = q0 ^ r0 ^ q7 ^ r7 ^ r1 ^ rotr16(q1 ^ r1); - q[2] = q1 ^ r1 ^ r2 ^ rotr16(q2 ^ r2); - q[3] = q2 ^ r2 ^ q7 ^ r7 ^ r3 ^ rotr16(q3 ^ r3); - q[4] = q3 ^ r3 ^ q7 ^ r7 ^ r4 ^ rotr16(q4 ^ r4); - q[5] = q4 ^ r4 ^ r5 ^ rotr16(q5 ^ r5); - q[6] = q5 ^ r5 ^ r6 ^ rotr16(q6 ^ r6); - q[7] = q6 ^ r6 ^ r7 ^ rotr16(q7 ^ r7); -} - -static void br_aes_ct64_ortho(uint64_t *q) { -#define SWAPN(cl, ch, s, x, y) do { \ - uint64_t a, b; \ - a = (x); \ - b = (y); \ - (x) = (a & (uint64_t)(cl)) | ((b & (uint64_t)(cl)) << (s)); \ - (y) = ((a & (uint64_t)(ch)) >> (s)) | (b & (uint64_t)(ch)); \ - } while (0) - -#define SWAP2(x, y) SWAPN(0x5555555555555555, 0xAAAAAAAAAAAAAAAA, 1, x, y) -#define SWAP4(x, y) SWAPN(0x3333333333333333, 0xCCCCCCCCCCCCCCCC, 2, x, y) -#define SWAP8(x, y) SWAPN(0x0F0F0F0F0F0F0F0F, 0xF0F0F0F0F0F0F0F0, 4, x, y) - - SWAP2(q[0], q[1]); - SWAP2(q[2], q[3]); - SWAP2(q[4], q[5]); - SWAP2(q[6], q[7]); - - SWAP4(q[0], q[2]); - SWAP4(q[1], q[3]); - SWAP4(q[4], q[6]); - SWAP4(q[5], q[7]); - - SWAP8(q[0], q[4]); - SWAP8(q[1], q[5]); - SWAP8(q[2], q[6]); - SWAP8(q[3], q[7]); -} - - -static void br_aes_ct64_interleave_in(uint64_t *q0, uint64_t *q1, const uint32_t *w) { - uint64_t x0, x1, x2, x3; - - x0 = w[0]; - x1 = w[1]; - x2 = w[2]; - x3 = w[3]; - x0 |= (x0 << 16); - x1 |= (x1 << 16); - x2 |= (x2 << 16); - x3 |= (x3 << 16); - x0 &= (uint64_t)0x0000FFFF0000FFFF; - x1 &= (uint64_t)0x0000FFFF0000FFFF; - x2 &= (uint64_t)0x0000FFFF0000FFFF; - x3 &= (uint64_t)0x0000FFFF0000FFFF; - x0 |= (x0 << 8); - x1 |= (x1 << 8); - x2 |= (x2 << 8); - x3 |= (x3 << 8); - x0 &= (uint64_t)0x00FF00FF00FF00FF; - x1 &= (uint64_t)0x00FF00FF00FF00FF; - x2 &= (uint64_t)0x00FF00FF00FF00FF; - x3 &= (uint64_t)0x00FF00FF00FF00FF; - *q0 = x0 | (x2 << 8); - *q1 = x1 | (x3 << 8); -} - - -static void br_aes_ct64_interleave_out(uint32_t *w, uint64_t q0, uint64_t q1) { - uint64_t x0, x1, x2, x3; - - x0 = q0 & (uint64_t)0x00FF00FF00FF00FF; - x1 = q1 & (uint64_t)0x00FF00FF00FF00FF; - x2 = (q0 >> 8) & (uint64_t)0x00FF00FF00FF00FF; - x3 = (q1 >> 8) & (uint64_t)0x00FF00FF00FF00FF; - x0 |= (x0 >> 8); - x1 |= (x1 >> 8); - x2 |= (x2 >> 8); - x3 |= (x3 >> 8); - x0 &= (uint64_t)0x0000FFFF0000FFFF; - x1 &= (uint64_t)0x0000FFFF0000FFFF; - x2 &= (uint64_t)0x0000FFFF0000FFFF; - x3 &= (uint64_t)0x0000FFFF0000FFFF; - w[0] = (uint32_t)x0 | (uint32_t)(x0 >> 16); - w[1] = (uint32_t)x1 | (uint32_t)(x1 >> 16); - w[2] = (uint32_t)x2 | (uint32_t)(x2 >> 16); - w[3] = (uint32_t)x3 | (uint32_t)(x3 >> 16); -} - -static inline void add_round_key(uint64_t *q, const uint64_t *sk) { - q[0] ^= sk[0]; - q[1] ^= sk[1]; - q[2] ^= sk[2]; - q[3] ^= sk[3]; - q[4] ^= sk[4]; - q[5] ^= sk[5]; - q[6] ^= sk[6]; - q[7] ^= sk[7]; -} - -static inline void shift_rows(uint64_t *q) { - int i; - - for (i = 0; i < 8; i++) { - uint64_t x; - - x = q[i]; - q[i] = (x & (uint64_t)0x000000000000FFFF) - | ((x & (uint64_t)0x00000000FFF00000) >> 4) - | ((x & (uint64_t)0x00000000000F0000) << 12) - | ((x & (uint64_t)0x0000FF0000000000) >> 8) - | ((x & (uint64_t)0x000000FF00000000) << 8) - | ((x & (uint64_t)0xF000000000000000) >> 12) - | ((x & (uint64_t)0x0FFF000000000000) << 4); - } -} - -static inline uint64_t rotr32(uint64_t x) { - return (x << 32) | (x >> 32); -} - -static inline void mix_columns(uint64_t *q) { - uint64_t q0, q1, q2, q3, q4, q5, q6, q7; - uint64_t r0, r1, r2, r3, r4, r5, r6, r7; - - q0 = q[0]; - q1 = q[1]; - q2 = q[2]; - q3 = q[3]; - q4 = q[4]; - q5 = q[5]; - q6 = q[6]; - q7 = q[7]; - r0 = (q0 >> 16) | (q0 << 48); - r1 = (q1 >> 16) | (q1 << 48); - r2 = (q2 >> 16) | (q2 << 48); - r3 = (q3 >> 16) | (q3 << 48); - r4 = (q4 >> 16) | (q4 << 48); - r5 = (q5 >> 16) | (q5 << 48); - r6 = (q6 >> 16) | (q6 << 48); - r7 = (q7 >> 16) | (q7 << 48); - - q[0] = q7 ^ r7 ^ r0 ^ rotr32(q0 ^ r0); - q[1] = q0 ^ r0 ^ q7 ^ r7 ^ r1 ^ rotr32(q1 ^ r1); - q[2] = q1 ^ r1 ^ r2 ^ rotr32(q2 ^ r2); - q[3] = q2 ^ r2 ^ q7 ^ r7 ^ r3 ^ rotr32(q3 ^ r3); - q[4] = q3 ^ r3 ^ q7 ^ r7 ^ r4 ^ rotr32(q4 ^ r4); - q[5] = q4 ^ r4 ^ r5 ^ rotr32(q5 ^ r5); - q[6] = q5 ^ r5 ^ r6 ^ rotr32(q6 ^ r6); - q[7] = q6 ^ r6 ^ r7 ^ rotr32(q7 ^ r7); -} - -static void interleave_constant(uint64_t *out, const unsigned char *in) { - uint32_t tmp_32_constant[16]; - int i; - - br_range_dec32le(tmp_32_constant, 16, in); - for (i = 0; i < 4; i++) { - br_aes_ct64_interleave_in(&out[i], &out[i + 4], tmp_32_constant + (i << 2)); - } - br_aes_ct64_ortho(out); -} - -static void interleave_constant32(uint32_t *out, const unsigned char *in) { - int i; - for (i = 0; i < 4; i++) { - out[2 * i] = br_dec32le(in + 4 * i); - out[2 * i + 1] = br_dec32le(in + 4 * i + 16); - } - br_aes_ct_ortho(out); -} - -void tweak_constants(spx_ctx *ctx) { - unsigned char buf[40 * 16]; - int i; - - /* Use the standard constants to generate tweaked ones. */ - memcpy((uint8_t *)ctx->tweaked512_rc64, (uint8_t *)haraka512_rc64, 40 * 16); - - /* Constants for pk.seed */ - haraka_S(buf, 40 * 16, ctx->pub_seed, SPX_N, ctx); - for (i = 0; i < 10; i++) { - interleave_constant32(ctx->tweaked256_rc32[i], buf + 32 * i); - interleave_constant(ctx->tweaked512_rc64[i], buf + 64 * i); - } -} - -static void haraka_S_absorb(unsigned char *s, unsigned int r, - const unsigned char *m, unsigned long long mlen, - unsigned char p, const spx_ctx *ctx) { - unsigned long long i; - PQCLEAN_VLA(uint8_t, t, r); - - while (mlen >= r) { - /* XOR block to state */ - for (i = 0; i < r; ++i) { - s[i] ^= m[i]; - } - haraka512_perm(s, s, ctx); - 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; ++i) { - s[i] ^= t[i]; - } -} - -static void haraka_S_squeezeblocks(unsigned char *h, unsigned long long nblocks, - unsigned char *s, unsigned int r, - const spx_ctx *ctx) { - while (nblocks > 0) { - haraka512_perm(s, s, ctx); - memcpy(h, s, HARAKAS_RATE); - h += r; - nblocks--; - } -} - -void haraka_S_inc_init(uint8_t *s_inc) { - size_t i; - - for (i = 0; i < 64; i++) { - s_inc[i] = 0; - } - s_inc[64] = 0; -} - -void haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, - const spx_ctx *ctx) { - size_t i; - - /* Recall that s_inc[64] is the non-absorbed bytes xored into the state */ - while (mlen + s_inc[64] >= HARAKAS_RATE) { - for (i = 0; i < (size_t)(HARAKAS_RATE - s_inc[64]); i++) { - /* Take the i'th byte from message - xor with the s_inc[64] + i'th byte of the state */ - s_inc[s_inc[64] + i] ^= m[i]; - } - mlen -= (size_t)(HARAKAS_RATE - s_inc[64]); - m += HARAKAS_RATE - (uint8_t)s_inc[64]; - s_inc[64] = 0; - - haraka512_perm(s_inc, s_inc, ctx); - } - - for (i = 0; i < mlen; i++) { - s_inc[s_inc[64] + i] ^= m[i]; - } - s_inc[64] += (uint8_t)mlen; -} - -void haraka_S_inc_finalize(uint8_t *s_inc) { - /* After haraka_S_inc_absorb, we are guaranteed that s_inc[64] < HARAKAS_RATE, - so we can always use one more byte for p in the current state. */ - s_inc[s_inc[64]] ^= 0x1F; - s_inc[HARAKAS_RATE - 1] ^= 128; - s_inc[64] = 0; -} - -void haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, - const spx_ctx *ctx) { - size_t i; - - /* First consume any bytes we still have sitting around */ - for (i = 0; i < outlen && i < s_inc[64]; i++) { - /* There are s_inc[64] bytes left, so r - s_inc[64] is the first - available byte. We consume from there, i.e., up to r. */ - out[i] = (uint8_t)s_inc[(HARAKAS_RATE - s_inc[64] + i)]; - } - out += i; - outlen -= i; - s_inc[64] -= (uint8_t)i; - - /* Then squeeze the remaining necessary blocks */ - while (outlen > 0) { - haraka512_perm(s_inc, s_inc, ctx); - - for (i = 0; i < outlen && i < HARAKAS_RATE; i++) { - out[i] = s_inc[i]; - } - out += i; - outlen -= i; - s_inc[64] = (uint8_t)(HARAKAS_RATE - i); - } -} - -void haraka_S(unsigned char *out, unsigned long long outlen, - const unsigned char *in, unsigned long long inlen, - const spx_ctx *ctx) { - unsigned long long i; - unsigned char s[64]; - unsigned char d[32]; - - for (i = 0; i < 64; i++) { - s[i] = 0; - } - haraka_S_absorb(s, 32, in, inlen, 0x1F, ctx); - - haraka_S_squeezeblocks(out, outlen / 32, s, 32, ctx); - out += (outlen / 32) * 32; - - if (outlen % 32) { - haraka_S_squeezeblocks(d, 1, s, 32, ctx); - for (i = 0; i < outlen % 32; i++) { - out[i] = d[i]; - } - } -} - -void haraka512_perm(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx) { - uint32_t w[16]; - uint64_t q[8], tmp_q; - unsigned int i, j; - - br_range_dec32le(w, 16, in); - for (i = 0; i < 4; i++) { - br_aes_ct64_interleave_in(&q[i], &q[i + 4], w + (i << 2)); - } - br_aes_ct64_ortho(q); - - /* AES rounds */ - for (i = 0; i < 5; i++) { - for (j = 0; j < 2; j++) { - br_aes_ct64_bitslice_Sbox(q); - shift_rows(q); - mix_columns(q); - add_round_key(q, ctx->tweaked512_rc64[2 * i + j]); - } - /* Mix states */ - for (j = 0; j < 8; j++) { - tmp_q = q[j]; - q[j] = (tmp_q & 0x0001000100010001) << 5 | - (tmp_q & 0x0002000200020002) << 12 | - (tmp_q & 0x0004000400040004) >> 1 | - (tmp_q & 0x0008000800080008) << 6 | - (tmp_q & 0x0020002000200020) << 9 | - (tmp_q & 0x0040004000400040) >> 4 | - (tmp_q & 0x0080008000800080) << 3 | - (tmp_q & 0x2100210021002100) >> 5 | - (tmp_q & 0x0210021002100210) << 2 | - (tmp_q & 0x0800080008000800) << 4 | - (tmp_q & 0x1000100010001000) >> 12 | - (tmp_q & 0x4000400040004000) >> 10 | - (tmp_q & 0x8400840084008400) >> 3; - } - } - - br_aes_ct64_ortho(q); - for (i = 0; i < 4; i ++) { - br_aes_ct64_interleave_out(w + (i << 2), q[i], q[i + 4]); - } - br_range_enc32le(out, w, 16); -} - -void haraka512(unsigned char *out, const unsigned char *in, const spx_ctx *ctx) { - int i; - - unsigned char buf[64]; - - haraka512_perm(buf, in, ctx); - /* Feed-forward */ - for (i = 0; i < 64; i++) { - buf[i] = buf[i] ^ in[i]; - } - - /* Truncated */ - memcpy(out, buf + 8, 8); - memcpy(out + 8, buf + 24, 8); - memcpy(out + 16, buf + 32, 8); - memcpy(out + 24, buf + 48, 8); -} - - -void haraka256(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx) { - uint32_t q[8], tmp_q; - int i, j; - - for (i = 0; i < 4; i++) { - q[2 * i] = br_dec32le(in + 4 * i); - q[2 * i + 1] = br_dec32le(in + 4 * i + 16); - } - br_aes_ct_ortho(q); - - /* AES rounds */ - for (i = 0; i < 5; i++) { - for (j = 0; j < 2; j++) { - br_aes_ct_bitslice_Sbox(q); - shift_rows32(q); - mix_columns32(q); - add_round_key32(q, ctx->tweaked256_rc32[2 * i + j]); - } - - /* Mix states */ - for (j = 0; j < 8; j++) { - tmp_q = q[j]; - q[j] = (tmp_q & 0x81818181) | - (tmp_q & 0x02020202) << 1 | - (tmp_q & 0x04040404) << 2 | - (tmp_q & 0x08080808) << 3 | - (tmp_q & 0x10101010) >> 3 | - (tmp_q & 0x20202020) >> 2 | - (tmp_q & 0x40404040) >> 1; - } - } - - br_aes_ct_ortho(q); - for (i = 0; i < 4; i++) { - br_enc32le(out + 4 * i, q[2 * i]); - br_enc32le(out + 4 * i + 16, q[2 * i + 1]); - } - - for (i = 0; i < 32; i++) { - out[i] ^= in[i]; - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/haraka.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/haraka.h deleted file mode 100644 index 737cb6065f..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/haraka.h +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef SPX_HARAKA_H -#define SPX_HARAKA_H - -#include "context.h" -#include "params.h" - -/* Tweak constants with seed */ -#define tweak_constants SPX_NAMESPACE(tweak_constants) -void tweak_constants(spx_ctx *ctx); - -/* Haraka Sponge */ -#define haraka_S_inc_init SPX_NAMESPACE(haraka_S_inc_init) -void haraka_S_inc_init(uint8_t *s_inc); -#define haraka_S_inc_absorb SPX_NAMESPACE(haraka_S_inc_absorb) -void haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, - const spx_ctx *ctx); -#define haraka_S_inc_finalize SPX_NAMESPACE(haraka_S_inc_finalize) -void haraka_S_inc_finalize(uint8_t *s_inc); -#define haraka_S_inc_squeeze SPX_NAMESPACE(haraka_S_inc_squeeze) -void haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, - const spx_ctx *ctx); -#define haraka_S SPX_NAMESPACE(haraka_S) -void haraka_S(unsigned char *out, unsigned long long outlen, - const unsigned char *in, unsigned long long inlen, - const spx_ctx *ctx); - -/* Applies the 512-bit Haraka permutation to in. */ -#define haraka512_perm SPX_NAMESPACE(haraka512_perm) -void haraka512_perm(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx); - -/* Implementation of Haraka-512 */ -#define haraka512 SPX_NAMESPACE(haraka512) -void haraka512(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx); - -/* Implementation of Haraka-256 */ -#define haraka256 SPX_NAMESPACE(haraka256) -void haraka256(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/haraka_offsets.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/haraka_offsets.h deleted file mode 100644 index 7c062272a0..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/haraka_offsets.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef HARAKA_OFFSETS_H_ -#define HARAKA_OFFSETS_H_ - -/* - * Offsets of various fields in the address structure when we use Haraka as - * the Sphincs+ hash function - */ - -#define SPX_OFFSET_LAYER 3 /* The byte used to specify the Merkle tree layer */ -#define SPX_OFFSET_TREE 8 /* The start of the 8 byte field used to specify the tree */ -#define SPX_OFFSET_TYPE 19 /* The byte used to specify the hash type (reason) */ -#define SPX_OFFSET_KP_ADDR2 22 /* The high byte used to specify the key pair (which one-time signature) */ -#define SPX_OFFSET_KP_ADDR1 23 /* The low byte used to specify the key pair */ -#define SPX_OFFSET_CHAIN_ADDR 27 /* The byte used to specify the chain address (which Winternitz chain) */ -#define SPX_OFFSET_HASH_ADDR 31 /* The byte used to specify the hash address (where in the Winternitz chain) */ -#define SPX_OFFSET_TREE_HGT 27 /* The byte used to specify the height of this node in the FORS or Merkle tree */ -#define SPX_OFFSET_TREE_INDEX 28 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ - -#define SPX_HARAKA 1 - -#endif /* HARAKA_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/hash.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/hash.h deleted file mode 100644 index f7c87d4c3c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/hash.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef SPX_HASH_H -#define SPX_HASH_H - -#include -#include - -#include "context.h" -#include "params.h" - -#define prf_addr SPX_NAMESPACE(prf_addr) -void prf_addr(unsigned char *out, const spx_ctx *ctx, - const uint32_t addr[8]); - -#define gen_message_random SPX_NAMESPACE(gen_message_random) -void gen_message_random(unsigned char *R, const unsigned char *sk_prf, - const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx); - -#define hash_message SPX_NAMESPACE(hash_message) -void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx); - - - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/hash_haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/hash_haraka.c deleted file mode 100644 index 750a67423b..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/hash_haraka.c +++ /dev/null @@ -1,81 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "utils.h" - -#include "haraka.h" -#include "hash.h" - -/* - * Computes PRF(key, addr), given a secret key of SPX_N bytes and an address - */ -void prf_addr(unsigned char *out, const spx_ctx *ctx, - const uint32_t addr[8]) { - /* Since SPX_N may be smaller than 32, we need temporary buffers. */ - unsigned char outbuf[32]; - unsigned char buf[64] = {0}; - - memcpy(buf, addr, SPX_ADDR_BYTES); - memcpy(buf + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); - - haraka512(outbuf, (const void *)buf, ctx); - memcpy(out, outbuf, SPX_N); -} - -/** - * Computes the message-dependent randomness R, using a secret seed and an - * optional randomization value as well as the message. - */ -void gen_message_random(unsigned char *R, const unsigned char *sk_prf, - const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx) { - uint8_t s_inc[65]; - - haraka_S_inc_init(s_inc); - haraka_S_inc_absorb(s_inc, sk_prf, SPX_N, ctx); - haraka_S_inc_absorb(s_inc, optrand, SPX_N, ctx); - haraka_S_inc_absorb(s_inc, m, mlen, ctx); - haraka_S_inc_finalize(s_inc); - haraka_S_inc_squeeze(R, SPX_N, s_inc, ctx); -} - -/** - * Computes the message hash using R, the public key, and the message. - * Outputs the message digest and the index of the leaf. The index is split in - * the tree index and the leaf index, for convenient copying to an address. - */ -void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx) { -#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) -#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) -#define SPX_LEAF_BITS SPX_TREE_HEIGHT -#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) -#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) - - unsigned char buf[SPX_DGST_BYTES]; - unsigned char *bufp = buf; - uint8_t s_inc[65]; - - haraka_S_inc_init(s_inc); - haraka_S_inc_absorb(s_inc, R, SPX_N, ctx); - haraka_S_inc_absorb(s_inc, pk + SPX_N, SPX_N, ctx); // Only absorb root part of pk - haraka_S_inc_absorb(s_inc, m, mlen, ctx); - haraka_S_inc_finalize(s_inc); - haraka_S_inc_squeeze(buf, SPX_DGST_BYTES, s_inc, ctx); - - memcpy(digest, bufp, SPX_FORS_MSG_BYTES); - bufp += SPX_FORS_MSG_BYTES; - - - *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); - *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); - bufp += SPX_TREE_BYTES; - - *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); - *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/merkle.c b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/merkle.c deleted file mode 100644 index 0c1479fd93..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/merkle.c +++ /dev/null @@ -1,59 +0,0 @@ -#include -#include - -#include "address.h" -#include "merkle.h" -#include "params.h" -#include "utils.h" -#include "utilsx1.h" -#include "wots.h" -#include "wotsx1.h" - -/* - * This generates a Merkle signature (WOTS signature followed by the Merkle - * authentication path). This is in this file because most of the complexity - * is involved with the WOTS signature; the Merkle authentication path logic - * is mostly hidden in treehashx4 - */ -void merkle_sign(uint8_t *sig, unsigned char *root, - const spx_ctx *ctx, - uint32_t wots_addr[8], uint32_t tree_addr[8], - uint32_t idx_leaf) { - unsigned char *auth_path = sig + SPX_WOTS_BYTES; - struct leaf_info_x1 info = { 0 }; - unsigned steps[ SPX_WOTS_LEN ]; - - info.wots_sig = sig; - chain_lengths(steps, root); - info.wots_steps = steps; - - set_type(&tree_addr[0], SPX_ADDR_TYPE_HASHTREE); - set_type(&info.pk_addr[0], SPX_ADDR_TYPE_WOTSPK); - copy_subtree_addr(&info.leaf_addr[0], wots_addr); - copy_subtree_addr(&info.pk_addr[0], wots_addr); - - info.wots_sign_leaf = idx_leaf; - - treehashx1(root, auth_path, ctx, - idx_leaf, 0, - SPX_TREE_HEIGHT, - wots_gen_leafx1, - tree_addr, &info); -} - -/* Compute root node of the top-most subtree. */ -void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { - /* We do not need the auth path in key generation, but it simplifies the - code to have just one treehash routine that computes both root and path - in one function. */ - unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; - uint32_t top_tree_addr[8] = {0}; - uint32_t wots_addr[8] = {0}; - - set_layer_addr(top_tree_addr, SPX_D - 1); - set_layer_addr(wots_addr, SPX_D - 1); - - merkle_sign(auth_path, root, ctx, - wots_addr, top_tree_addr, - (uint32_t)~0 /* ~0 means "don't bother generating an auth path */ ); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/merkle.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/merkle.h deleted file mode 100644 index 769cf2e970..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/merkle.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef MERKLE_H_ -#define MERKLE_H_ - -#include - -#include "context.h" -#include "params.h" - -/* Generate a Merkle signature (WOTS signature followed by the Merkle */ -/* authentication path) */ -#define merkle_sign SPX_NAMESPACE(merkle_sign) -void merkle_sign(uint8_t *sig, unsigned char *root, - const spx_ctx *ctx, - uint32_t wots_addr[8], uint32_t tree_addr[8], - uint32_t idx_leaf); - -/* Compute the root node of the top-most subtree. */ -#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) -void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); - -#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/nistapi.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/nistapi.h deleted file mode 100644 index 3cb71afad4..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/nistapi.h +++ /dev/null @@ -1,87 +0,0 @@ -#ifndef SPX_API_H -#define SPX_API_H - -#include -#include - -#include "params.h" - -#define CRYPTO_ALGNAME "SPHINCS+" - -#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES -#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES -#define CRYPTO_BYTES SPX_BYTES -#define CRYPTO_SEEDBYTES (3*SPX_N) - -/* - * Returns the length of a secret key, in bytes - */ -#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) -size_t crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) -size_t crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) -size_t crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) -size_t crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) -int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) -int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) -int crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) -int crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -#define crypto_sign SPX_NAMESPACE(crypto_sign) -int crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) -int crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/params.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/params.h deleted file mode 100644 index 417aa923a8..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/params.h +++ /dev/null @@ -1,56 +0,0 @@ -#ifndef SPX_PARAMS_H -#define SPX_PARAMS_H - -#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_##s - -/* Hash output length in bytes. */ -#define SPX_N 16 -/* Height of the hypertree. */ -#define SPX_FULL_HEIGHT 63 -/* Number of subtree layer. */ -#define SPX_D 7 -/* FORS tree dimensions. */ -#define SPX_FORS_HEIGHT 12 -#define SPX_FORS_TREES 14 -/* Winternitz parameter, */ -#define SPX_WOTS_W 16 - -/* The hash function is defined by linking a different hash.c file, as opposed - to setting a #define constant. */ - -/* For clarity */ -#define SPX_ADDR_BYTES 32 - -/* WOTS parameters. */ -#define SPX_WOTS_LOGW 4 - -#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) - -/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#define SPX_WOTS_LEN2 3 - -#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) -#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) -#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES - -/* Subtree size. */ -#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) - -//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT -// #error SPX_D should always divide SPX_FULL_HEIGHT -//#endif - -/* FORS parameters. */ -#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) -#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) -#define SPX_FORS_PK_BYTES SPX_N - -/* Resulting SPX sizes. */ -#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ - SPX_FULL_HEIGHT * SPX_N) -#define SPX_PK_BYTES (2 * SPX_N) -#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) - -#include "haraka_offsets.h" - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/sign.c b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/sign.c deleted file mode 100644 index 9d0c7d1b22..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/sign.c +++ /dev/null @@ -1,286 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "context.h" -#include "fors.h" -#include "hash.h" -#include "merkle.h" -#include "nistapi.h" -#include "params.h" -#include "randombytes.h" -#include "thash.h" -#include "utils.h" -#include "wots.h" - -/* - * Returns the length of a secret key, in bytes - */ -size_t crypto_sign_secretkeybytes(void) { - return CRYPTO_SECRETKEYBYTES; -} - -/* - * Returns the length of a public key, in bytes - */ -size_t crypto_sign_publickeybytes(void) { - return CRYPTO_PUBLICKEYBYTES; -} - -/* - * Returns the length of a signature, in bytes - */ -size_t crypto_sign_bytes(void) { - return CRYPTO_BYTES; -} - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t crypto_sign_seedbytes(void) { - return CRYPTO_SEEDBYTES; -} - -/* - * Generates an SPX key pair given a seed of length - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed) { - spx_ctx ctx; - - /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ - memcpy(sk, seed, CRYPTO_SEEDBYTES); - - memcpy(pk, sk + 2 * SPX_N, SPX_N); - - memcpy(ctx.pub_seed, pk, SPX_N); - memcpy(ctx.sk_seed, sk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - /* Compute root node of the top-most subtree. */ - merkle_gen_root(sk + 3 * SPX_N, &ctx); - - // cleanup - free_hash_function(&ctx); - - memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); - - return 0; -} - -/* - * Generates an SPX key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { - uint8_t seed[CRYPTO_SEEDBYTES]; - randombytes(seed, CRYPTO_SEEDBYTES); - crypto_sign_seed_keypair(pk, sk, seed); - - return 0; -} - -/** - * Returns an array containing a detached signature. - */ -int crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - spx_ctx ctx; - - const uint8_t *sk_prf = sk + SPX_N; - const uint8_t *pk = sk + 2 * SPX_N; - - uint8_t optrand[SPX_N]; - uint8_t mhash[SPX_FORS_MSG_BYTES]; - uint8_t root[SPX_N]; - uint32_t i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - - memcpy(ctx.sk_seed, sk, SPX_N); - memcpy(ctx.pub_seed, pk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - set_type(wots_addr, SPX_ADDR_TYPE_WOTS); - set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); - - /* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ - randombytes(optrand, SPX_N); - /* Compute the digest randomization value. */ - gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); - - /* Derive the message digest and leaf index from R, PK and M. */ - hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); - sig += SPX_N; - - set_tree_addr(wots_addr, tree); - set_keypair_addr(wots_addr, idx_leaf); - - /* Sign the message hash using FORS. */ - fors_sign(sig, root, mhash, &ctx, wots_addr); - sig += SPX_FORS_BYTES; - - for (i = 0; i < SPX_D; i++) { - set_layer_addr(tree_addr, i); - set_tree_addr(tree_addr, tree); - - copy_subtree_addr(wots_addr, tree_addr); - set_keypair_addr(wots_addr, idx_leaf); - - merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); - sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); - tree = tree >> SPX_TREE_HEIGHT; - } - - free_hash_function(&ctx); - - *siglen = SPX_BYTES; - - return 0; -} - -/** - * Verifies a detached signature and message under a given public key. - */ -int crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk) { - spx_ctx ctx; - const uint8_t *pub_root = pk + SPX_N; - uint8_t mhash[SPX_FORS_MSG_BYTES]; - uint8_t wots_pk[SPX_WOTS_BYTES]; - uint8_t root[SPX_N]; - uint8_t leaf[SPX_N]; - unsigned int i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - if (siglen != SPX_BYTES) { - return -1; - } - - memcpy(ctx.pub_seed, pk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - set_type(wots_addr, SPX_ADDR_TYPE_WOTS); - set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); - set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); - - /* Derive the message digest and leaf index from R || PK || M. */ - /* The additional SPX_N is a result of the hash domain separator. */ - hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); - sig += SPX_N; - - /* Layer correctly defaults to 0, so no need to set_layer_addr */ - set_tree_addr(wots_addr, tree); - set_keypair_addr(wots_addr, idx_leaf); - - fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); - sig += SPX_FORS_BYTES; - - /* For each subtree.. */ - for (i = 0; i < SPX_D; i++) { - set_layer_addr(tree_addr, i); - set_tree_addr(tree_addr, tree); - - copy_subtree_addr(wots_addr, tree_addr); - set_keypair_addr(wots_addr, idx_leaf); - - copy_keypair_addr(wots_pk_addr, wots_addr); - - /* The WOTS public key is only correct if the signature was correct. */ - /* Initially, root is the FORS pk, but on subsequent iterations it is - the root of the subtree below the currently processed subtree. */ - wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); - sig += SPX_WOTS_BYTES; - - /* Compute the leaf node using the WOTS public key. */ - thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); - - /* Compute the root node of this subtree. */ - compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, - &ctx, tree_addr); - sig += SPX_TREE_HEIGHT * SPX_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); - tree = tree >> SPX_TREE_HEIGHT; - } - - // cleanup - free_hash_function(&ctx); - - /* Check if the root node equals the root node in the public key. */ - if (memcmp(root, pub_root, SPX_N) != 0) { - return -1; - } - - return 0; -} - - -/** - * Returns an array containing the signature followed by the message. - */ -int crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk) { - size_t siglen; - - crypto_sign_signature(sm, &siglen, m, mlen, sk); - - memmove(sm + SPX_BYTES, m, mlen); - *smlen = siglen + mlen; - - return 0; -} - -/** - * Verifies a given signature-message pair under a given public key. - */ -int crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk) { - /* The API caller does not necessarily know what size a signature should be - but SPHINCS+ signatures are always exactly SPX_BYTES. */ - if (smlen < SPX_BYTES) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - *mlen = smlen - SPX_BYTES; - - if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - /* If verification was successful, move the message to the right place. */ - memmove(m, sm + SPX_BYTES, *mlen); - - return 0; -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/thash.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/thash.h deleted file mode 100644 index 8687ccfb4d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/thash.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef SPX_THASH_H -#define SPX_THASH_H - -#include "context.h" -#include "params.h" - -#include - -#define thash SPX_NAMESPACE(thash) -void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/thash_haraka_robust.c b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/thash_haraka_robust.c deleted file mode 100644 index 109502cbc2..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/thash_haraka_robust.c +++ /dev/null @@ -1,45 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "thash.h" -#include "utils.h" - -#include "haraka.h" - -/** - * Takes an array of inblocks concatenated arrays of SPX_N bytes. - */ -void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]) { - PQCLEAN_VLA(uint8_t, buf, SPX_ADDR_BYTES + inblocks * SPX_N); - PQCLEAN_VLA(uint8_t, bitmask, inblocks * SPX_N); - unsigned char outbuf[32]; - unsigned char buf_tmp[64]; - unsigned int i; - - if (inblocks == 1) { - /* F function */ - /* Since SPX_N may be smaller than 32, we need a temporary buffer. */ - memset(buf_tmp, 0, 64); - memcpy(buf_tmp, addr, 32); - - haraka256(outbuf, buf_tmp, ctx); - for (i = 0; i < inblocks * SPX_N; i++) { - buf_tmp[SPX_ADDR_BYTES + i] = in[i] ^ outbuf[i]; - } - haraka512(outbuf, buf_tmp, ctx); - memcpy(out, outbuf, SPX_N); - } else { - /* All other tweakable hashes*/ - memcpy(buf, addr, 32); - haraka_S(bitmask, inblocks * SPX_N, buf, SPX_ADDR_BYTES, ctx); - - for (i = 0; i < inblocks * SPX_N; i++) { - buf[SPX_ADDR_BYTES + i] = in[i] ^ bitmask[i]; - } - - haraka_S(out, SPX_N, buf, SPX_ADDR_BYTES + inblocks * SPX_N, ctx); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/utils.c b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/utils.c deleted file mode 100644 index 177b541fb9..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/utils.c +++ /dev/null @@ -1,148 +0,0 @@ -#include - -#include "utils.h" - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "thash.h" - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void ull_to_bytes(unsigned char *out, unsigned int outlen, - unsigned long long in) { - int i; - - /* Iterate over out in decreasing order, for big-endianness. */ - for (i = (signed int)outlen - 1; i >= 0; i--) { - out[i] = in & 0xff; - in = in >> 8; - } -} - -void u32_to_bytes(unsigned char *out, uint32_t in) { - out[0] = (unsigned char)(in >> 24); - out[1] = (unsigned char)(in >> 16); - out[2] = (unsigned char)(in >> 8); - out[3] = (unsigned char)in; -} - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { - unsigned long long retval = 0; - unsigned int i; - - for (i = 0; i < inlen; i++) { - retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); - } - return retval; -} - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void compute_root(unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const spx_ctx *ctx, uint32_t addr[8]) { - uint32_t i; - unsigned char buffer[2 * SPX_N]; - - /* If leaf_idx is odd (last bit = 1), current path element is a right child - and auth_path has to go left. Otherwise it is the other way around. */ - if (leaf_idx & 1) { - memcpy(buffer + SPX_N, leaf, SPX_N); - memcpy(buffer, auth_path, SPX_N); - } else { - memcpy(buffer, leaf, SPX_N); - memcpy(buffer + SPX_N, auth_path, SPX_N); - } - auth_path += SPX_N; - - for (i = 0; i < tree_height - 1; i++) { - leaf_idx >>= 1; - idx_offset >>= 1; - /* Set the address of the node we're creating. */ - set_tree_height(addr, i + 1); - set_tree_index(addr, leaf_idx + idx_offset); - - /* Pick the right or left neighbor, depending on parity of the node. */ - if (leaf_idx & 1) { - thash(buffer + SPX_N, buffer, 2, ctx, addr); - memcpy(buffer, auth_path, SPX_N); - } else { - thash(buffer, buffer, 2, ctx, addr); - memcpy(buffer + SPX_N, auth_path, SPX_N); - } - auth_path += SPX_N; - } - - /* The last iteration is exceptional; we do not copy an auth_path node. */ - leaf_idx >>= 1; - idx_offset >>= 1; - set_tree_height(addr, tree_height); - set_tree_index(addr, leaf_idx + idx_offset); - thash(root, buffer, 2, ctx, addr); -} - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const spx_ctx * /* ctx */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), - uint32_t tree_addr[8]) { - PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); - PQCLEAN_VLA(unsigned int, heights, tree_height + 1); - unsigned int offset = 0; - uint32_t idx; - uint32_t tree_idx; - - for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { - /* Add the next leaf node to the stack. */ - gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); - offset++; - heights[offset - 1] = 0; - - /* If this is a node we need for the auth path.. */ - if ((leaf_idx ^ 0x1) == idx) { - memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); - } - - /* While the top-most nodes are of equal height.. */ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { - /* Compute index of the new node, in the next layer. */ - tree_idx = (idx >> (heights[offset - 1] + 1)); - - /* Set the address of the node we're creating. */ - set_tree_height(tree_addr, heights[offset - 1] + 1); - set_tree_index(tree_addr, - tree_idx + (idx_offset >> (heights[offset - 1] + 1))); - /* Hash the top-most nodes from the stack together. */ - thash(stack + (offset - 2)*SPX_N, - stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); - offset--; - /* Note that the top-most node is now one layer higher. */ - heights[offset - 1]++; - - /* If this is a node we need for the auth path.. */ - if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_path + heights[offset - 1]*SPX_N, - stack + (offset - 1)*SPX_N, SPX_N); - } - } - } - memcpy(root, stack, SPX_N); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/utils.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/utils.h deleted file mode 100644 index 64f5d5a53a..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/utils.h +++ /dev/null @@ -1,58 +0,0 @@ -#ifndef SPX_UTILS_H -#define SPX_UTILS_H - -#include - -#include "compat.h" -#include "context.h" -#include "params.h" - - -/* To support MSVC use alloca() instead of VLAs. See #20. */ - - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) -void ull_to_bytes(unsigned char *out, unsigned int outlen, - unsigned long long in); -#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) -void u32_to_bytes(unsigned char *out, uint32_t in); - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) -unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -#define compute_root SPX_NAMESPACE(compute_root) -void compute_root(unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const spx_ctx *ctx, uint32_t addr[8]); - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -#define treehash SPX_NAMESPACE(treehash) -void treehash(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const spx_ctx *ctx /* ctx */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), - uint32_t tree_addr[8]); - - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/utilsx1.c b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/utilsx1.c deleted file mode 100644 index fccb69b35d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/utilsx1.c +++ /dev/null @@ -1,100 +0,0 @@ -#include - -#include "utilsx1.h" - -#include "address.h" -#include "params.h" -#include "thash.h" -#include "utils.h" - -/* - * Generate the entire Merkle tree, computing the authentication path for - * leaf_idx, and the resulting root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) - * - * This expects tree_addr to be initialized to the addr structures for the - * Merkle tree nodes - * - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - * - * This works by using the standard Merkle tree building algorithm, - */ -void treehashx1(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, - uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* Where to write the leaves */, - const spx_ctx * /* ctx */, - uint32_t idx, void *info), - uint32_t tree_addr[8], - void *info) { - /* This is where we keep the intermediate nodes */ - PQCLEAN_VLA(uint8_t, stack, tree_height * SPX_N); - - uint32_t idx; - uint32_t max_idx = (uint32_t)((1 << tree_height) - 1); - for (idx = 0;; idx++) { - unsigned char current[2 * SPX_N]; /* Current logical node is at */ - /* index[SPX_N]. We do this to minimize the number of copies */ - /* needed during a thash */ - gen_leaf( ¤t[SPX_N], ctx, idx + idx_offset, - info ); - - /* Now combine the freshly generated right node with previously */ - /* generated left ones */ - uint32_t internal_idx_offset = idx_offset; - uint32_t internal_idx = idx; - uint32_t internal_leaf = leaf_idx; - uint32_t h; /* The height we are in the Merkle tree */ - for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { - - /* Check if we hit the top of the tree */ - if (h == tree_height) { - /* We hit the root; return it */ - memcpy( root, ¤t[SPX_N], SPX_N ); - return; - } - - /* - * Check if the node we have is a part of the - * authentication path; if it is, write it out - */ - if ((internal_idx ^ internal_leaf) == 0x01) { - memcpy( &auth_path[ h * SPX_N ], - ¤t[SPX_N], - SPX_N ); - } - - /* - * Check if we're at a left child; if so, stop going up the stack - * Exception: if we've reached the end of the tree, keep on going - * (so we combine the last 4 nodes into the one root node in two - * more iterations) - */ - if ((internal_idx & 1) == 0 && idx < max_idx) { - break; - } - - /* Ok, we're at a right node */ - /* Now combine the left and right logical nodes together */ - - /* Set the address of the node we're creating. */ - internal_idx_offset >>= 1; - set_tree_height(tree_addr, h + 1); - set_tree_index(tree_addr, internal_idx / 2 + internal_idx_offset ); - - unsigned char *left = &stack[h * SPX_N]; - memcpy( ¤t[0], left, SPX_N ); - thash( ¤t[1 * SPX_N], - ¤t[0 * SPX_N], - 2, ctx, tree_addr); - } - - /* We've hit a left child; save the current for when we get the */ - /* corresponding right right */ - memcpy( &stack[h * SPX_N], ¤t[SPX_N], SPX_N); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/utilsx1.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/utilsx1.h deleted file mode 100644 index e911d17d53..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/utilsx1.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef SPX_UTILSX4_H -#define SPX_UTILSX4_H - -#include - -#include "context.h" -#include "params.h" - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -#define treehashx1 SPX_NAMESPACE(treehashx1) -void treehashx1(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* Where to write the leaf */, - const spx_ctx * /* ctx */, - uint32_t addr_idx, void *info), - uint32_t tree_addrx4[8], void *info); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/wots.c b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/wots.c deleted file mode 100644 index 249717aaa8..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/wots.c +++ /dev/null @@ -1,108 +0,0 @@ -#include -#include - -#include "wots.h" -#include "wotsx1.h" - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "thash.h" -#include "utils.h" -#include "utilsx1.h" - -// TODO clarify address expectations, and make them more uniform. -// TODO i.e. do we expect types to be set already? -// TODO and do we expect modifications or copies? - -/** - * Computes the chaining function. - * out and in have to be n-byte arrays. - * - * Interprets in as start-th value of the chain. - * addr has to contain the address of the chain. - */ -static void gen_chain(unsigned char *out, const unsigned char *in, - unsigned int start, unsigned int steps, - const spx_ctx *ctx, uint32_t addr[8]) { - uint32_t i; - - /* Initialize out with the value at position 'start'. */ - memcpy(out, in, SPX_N); - - /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < SPX_WOTS_W; i++) { - set_hash_addr(addr, i); - thash(out, out, 1, ctx, addr); - } -} - -/** - * base_w algorithm as described in draft. - * Interprets an array of bytes as integers in base w. - * This only works when log_w is a divisor of 8. - */ -static void base_w(unsigned int *output, const int out_len, - const unsigned char *input) { - int in = 0; - int out = 0; - unsigned char total = 0; - int bits = 0; - int consumed; - - for (consumed = 0; consumed < out_len; consumed++) { - if (bits == 0) { - total = input[in]; - in++; - bits += 8; - } - bits -= SPX_WOTS_LOGW; - output[out] = (total >> bits) & (SPX_WOTS_W - 1); - out++; - } -} - -/* Computes the WOTS+ checksum over a message (in base_w). */ -static void wots_checksum(unsigned int *csum_base_w, - const unsigned int *msg_base_w) { - unsigned int csum = 0; - unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; - unsigned int i; - - /* Compute checksum. */ - for (i = 0; i < SPX_WOTS_LEN1; i++) { - csum += SPX_WOTS_W - 1 - msg_base_w[i]; - } - - /* Convert checksum to base_w. */ - /* Make sure expected empty zero bits are the least significant bits. */ - csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); - ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); - base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); -} - -/* Takes a message and derives the matching chain lengths. */ -void chain_lengths(unsigned int *lengths, const unsigned char *msg) { - base_w(lengths, SPX_WOTS_LEN1, msg); - wots_checksum(lengths + SPX_WOTS_LEN1, lengths); -} - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const spx_ctx *ctx, uint32_t addr[8]) { - unsigned int lengths[SPX_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < SPX_WOTS_LEN; i++) { - set_chain_addr(addr, i); - gen_chain(pk + i * SPX_N, sig + i * SPX_N, - lengths[i], SPX_WOTS_W - 1 - lengths[i], ctx, addr); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/wots.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/wots.h deleted file mode 100644 index 4e7692eeef..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/wots.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef SPX_WOTS_H -#define SPX_WOTS_H - -#include - -#include "context.h" -#include "params.h" - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) -void wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const spx_ctx *ctx, uint32_t addr[8]); - -/* - * Compute the chain lengths needed for a given message hash - */ -#define chain_lengths SPX_NAMESPACE(chain_lengths) -void chain_lengths(unsigned int *lengths, const unsigned char *msg); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/wotsx1.c b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/wotsx1.c deleted file mode 100644 index 3adec78dfb..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/wotsx1.c +++ /dev/null @@ -1,76 +0,0 @@ -#include -#include - -#include "wots.h" -#include "wotsx1.h" - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "thash.h" -#include "utils.h" - -/* - * This generates a WOTS public key - * It also generates the WOTS signature if leaf_info indicates - * that we're signing with this WOTS key - */ -void wots_gen_leafx1(unsigned char *dest, - const spx_ctx *ctx, - uint32_t leaf_idx, void *v_info) { - struct leaf_info_x1 *info = v_info; - uint32_t *leaf_addr = info->leaf_addr; - uint32_t *pk_addr = info->pk_addr; - unsigned int i, k; - unsigned char pk_buffer[ SPX_WOTS_BYTES ]; - unsigned char *buffer; - uint32_t wots_k_mask; - - if (leaf_idx == info->wots_sign_leaf) { - /* We're traversing the leaf that's signing; generate the WOTS */ - /* signature */ - wots_k_mask = 0; - } else { - /* Nope, we're just generating pk's; turn off the signature logic */ - wots_k_mask = (uint32_t)~0; - } - - set_keypair_addr( leaf_addr, leaf_idx ); - set_keypair_addr( pk_addr, leaf_idx ); - - for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { - uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k to */ - /* the step if we're generating a signature, ~0 if we're not */ - - /* Start with the secret seed */ - set_chain_addr(leaf_addr, i); - set_hash_addr(leaf_addr, 0); - set_type(leaf_addr, SPX_ADDR_TYPE_WOTSPRF); - - prf_addr(buffer, ctx, leaf_addr); - - set_type(leaf_addr, SPX_ADDR_TYPE_WOTS); - - /* Iterate down the WOTS chain */ - for (k = 0;; k++) { - /* Check if this is the value that needs to be saved as a */ - /* part of the WOTS signature */ - if (k == wots_k) { - memcpy( info->wots_sig + i * SPX_N, buffer, SPX_N ); - } - - /* Check if we hit the top of the chain */ - if (k == SPX_WOTS_W - 1) { - break; - } - - /* Iterate one step on the chain */ - set_hash_addr(leaf_addr, k); - - thash(buffer, buffer, 1, ctx, leaf_addr); - } - } - - /* Do the final thash to generate the public keys */ - thash(dest, pk_buffer, SPX_WOTS_LEN, ctx, pk_addr); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/wotsx1.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/wotsx1.h deleted file mode 100644 index e617929f96..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-robust_clean/wotsx1.h +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef WOTSX1_H_ -#define WOTSX1_H_ - -#include - -#include "context.h" -#include "params.h" - -/* - * This is here to provide an interface to the internal wots_gen_leafx1 - * routine. While this routine is not referenced in the package outside of - * wots.c, it is called from the stand-alone benchmark code to characterize - * the performance - */ -struct leaf_info_x1 { - unsigned char *wots_sig; - uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ - uint32_t *wots_steps; - uint32_t leaf_addr[8]; - uint32_t pk_addr[8]; -}; - -/* Macro to set the leaf_info to something 'benign', that is, it would */ -/* run with the same time as it does during the real signing process */ -/* Used only by the benchmark code */ -#define INITIALIZE_LEAF_INFO_X1(info, addr, step_buffer) { \ - (info).wots_sig = 0; \ - (info).wots_sign_leaf = ~0; \ - (info).wots_steps = step_buffer; \ - memcpy( &(info).leaf_addr[0], (addr), 32 ); \ - memcpy( &(info).pk_addr[0], (addr), 32 ); \ - } - -#define wots_gen_leafx1 SPX_NAMESPACE(wots_gen_leafx1) -void wots_gen_leafx1(unsigned char *dest, - const spx_ctx *ctx, - uint32_t leaf_idx, void *v_info); - -#endif /* WOTSX1_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/LICENSE b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/LICENSE deleted file mode 100644 index 670154e353..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/LICENSE +++ /dev/null @@ -1,116 +0,0 @@ -CC0 1.0 Universal - -Statement of Purpose - -The laws of most jurisdictions throughout the world automatically confer -exclusive Copyright and Related Rights (defined below) upon the creator and -subsequent owner(s) (each and all, an "owner") of an original work of -authorship and/or a database (each, a "Work"). - -Certain owners wish to permanently relinquish those rights to a Work for the -purpose of contributing to a commons of creative, cultural and scientific -works ("Commons") that the public can reliably and without fear of later -claims of infringement build upon, modify, incorporate in other works, reuse -and redistribute as freely as possible in any form whatsoever and for any -purposes, including without limitation commercial purposes. These owners may -contribute to the Commons to promote the ideal of a free culture and the -further production of creative, cultural and scientific works, or to gain -reputation or greater distribution for their Work in part through the use and -efforts of others. - -For these and/or other purposes and motivations, and without any expectation -of additional consideration or compensation, the person associating CC0 with a -Work (the "Affirmer"), to the extent that he or she is an owner of Copyright -and Related Rights in the Work, voluntarily elects to apply CC0 to the Work -and publicly distribute the Work under its terms, with knowledge of his or her -Copyright and Related Rights in the Work and the meaning and intended legal -effect of CC0 on those rights. - -1. Copyright and Related Rights. A Work made available under CC0 may be -protected by copyright and related or neighboring rights ("Copyright and -Related Rights"). Copyright and Related Rights include, but are not limited -to, the following: - - i. the right to reproduce, adapt, distribute, perform, display, communicate, - and translate a Work; - - ii. moral rights retained by the original author(s) and/or performer(s); - - iii. publicity and privacy rights pertaining to a person's image or likeness - depicted in a Work; - - iv. rights protecting against unfair competition in regards to a Work, - subject to the limitations in paragraph 4(a), below; - - v. rights protecting the extraction, dissemination, use and reuse of data in - a Work; - - vi. database rights (such as those arising under Directive 96/9/EC of the - European Parliament and of the Council of 11 March 1996 on the legal - protection of databases, and under any national implementation thereof, - including any amended or successor version of such directive); and - - vii. other similar, equivalent or corresponding rights throughout the world - based on applicable law or treaty, and any national implementations thereof. - -2. Waiver. To the greatest extent permitted by, but not in contravention of, -applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and -unconditionally waives, abandons, and surrenders all of Affirmer's Copyright -and Related Rights and associated claims and causes of action, whether now -known or unknown (including existing as well as future claims and causes of -action), in the Work (i) in all territories worldwide, (ii) for the maximum -duration provided by applicable law or treaty (including future time -extensions), (iii) in any current or future medium and for any number of -copies, and (iv) for any purpose whatsoever, including without limitation -commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes -the Waiver for the benefit of each member of the public at large and to the -detriment of Affirmer's heirs and successors, fully intending that such Waiver -shall not be subject to revocation, rescission, cancellation, termination, or -any other legal or equitable action to disrupt the quiet enjoyment of the Work -by the public as contemplated by Affirmer's express Statement of Purpose. - -3. Public License Fallback. Should any part of the Waiver for any reason be -judged legally invalid or ineffective under applicable law, then the Waiver -shall be preserved to the maximum extent permitted taking into account -Affirmer's express Statement of Purpose. In addition, to the extent the Waiver -is so judged Affirmer hereby grants to each affected person a royalty-free, -non transferable, non sublicensable, non exclusive, irrevocable and -unconditional license to exercise Affirmer's Copyright and Related Rights in -the Work (i) in all territories worldwide, (ii) for the maximum duration -provided by applicable law or treaty (including future time extensions), (iii) -in any current or future medium and for any number of copies, and (iv) for any -purpose whatsoever, including without limitation commercial, advertising or -promotional purposes (the "License"). The License shall be deemed effective as -of the date CC0 was applied by Affirmer to the Work. Should any part of the -License for any reason be judged legally invalid or ineffective under -applicable law, such partial invalidity or ineffectiveness shall not -invalidate the remainder of the License, and in such case Affirmer hereby -affirms that he or she will not (i) exercise any of his or her remaining -Copyright and Related Rights in the Work or (ii) assert any associated claims -and causes of action with respect to the Work, in either case contrary to -Affirmer's express Statement of Purpose. - -4. Limitations and Disclaimers. - - a. No trademark or patent rights held by Affirmer are waived, abandoned, - surrendered, licensed or otherwise affected by this document. - - b. Affirmer offers the Work as-is and makes no representations or warranties - of any kind concerning the Work, express, implied, statutory or otherwise, - including without limitation warranties of title, merchantability, fitness - for a particular purpose, non infringement, or the absence of latent or - other defects, accuracy, or the present or absence of errors, whether or not - discoverable, all to the greatest extent permissible under applicable law. - - c. Affirmer disclaims responsibility for clearing rights of other persons - that may apply to the Work or any use thereof, including without limitation - any person's Copyright and Related Rights in the Work. Further, Affirmer - disclaims responsibility for obtaining any necessary consents, permissions - or other rights required for any use of the Work. - - d. Affirmer understands and acknowledges that Creative Commons is not a - party to this document and has no duty or obligation with respect to this - CC0 or use of the Work. - -For more information, please see - diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/address.c b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/address.c deleted file mode 100644 index d49d9f3b6b..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/address.c +++ /dev/null @@ -1,95 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "utils.h" - -/* - * Specify which level of Merkle tree (the "layer") we're working on - */ -void set_layer_addr(uint32_t addr[8], uint32_t layer) { - ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; -} - -/* - * Specify which Merkle tree within the level (the "tree address") we're working on - */ -void set_tree_addr(uint32_t addr[8], uint64_t tree) { - ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); -} - -/* - * Specify the reason we'll use this address structure for, that is, what - * hash will we compute with it. This is used so that unrelated types of - * hashes don't accidentally get the same address structure. The type will be - * one of the SPX_ADDR_TYPE constants - */ -void set_type(uint32_t addr[8], uint32_t type) { - ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; -} - -/* - * Copy the layer and tree fields of the address structure. This is used - * when we're doing multiple types of hashes within the same Merkle tree - */ -void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { - memcpy( out, in, SPX_OFFSET_TREE + 8 ); -} - -/* These functions are used for OTS addresses. */ - -/* - * Specify which Merkle leaf we're working on; that is, which OTS keypair - * we're talking about. - */ -void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { - /* We have > 256 OTS at the bottom of the Merkle tree; to specify */ - /* which one, we'd need to express it in two bytes */ - ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR2] = (unsigned char)(keypair >> 8); - ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; -} - -/* - * Copy the layer, tree and keypair fields of the address structure. This is - * used when we're doing multiple things within the same OTS keypair - */ -void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { - memcpy( out, in, SPX_OFFSET_TREE + 8 ); - ((unsigned char *)out)[SPX_OFFSET_KP_ADDR2] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR2]; - ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; -} - -/* - * Specify which Merkle chain within the OTS we're working with - * (the chain address) - */ -void set_chain_addr(uint32_t addr[8], uint32_t chain) { - ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; -} - -/* - * Specify where in the Merkle chain we are -* (the hash address) - */ -void set_hash_addr(uint32_t addr[8], uint32_t hash) { - ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; -} - -/* These functions are used for all hash tree addresses (including FORS). */ - -/* - * Specify the height of the node in the Merkle/FORS tree we are in - * (the tree height) - */ -void set_tree_height(uint32_t addr[8], uint32_t tree_height) { - ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; -} - -/* - * Specify the distance from the left edge of the node in the Merkle/FORS tree - * (the tree index) - */ -void set_tree_index(uint32_t addr[8], uint32_t tree_index) { - u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/address.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/address.h deleted file mode 100644 index 24a84eb40c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/address.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef SPX_ADDRESS_H -#define SPX_ADDRESS_H - -#include - -#include "params.h" - -/* The hash types that are passed to set_type */ -#define SPX_ADDR_TYPE_WOTS 0 -#define SPX_ADDR_TYPE_WOTSPK 1 -#define SPX_ADDR_TYPE_HASHTREE 2 -#define SPX_ADDR_TYPE_FORSTREE 3 -#define SPX_ADDR_TYPE_FORSPK 4 -#define SPX_ADDR_TYPE_WOTSPRF 5 -#define SPX_ADDR_TYPE_FORSPRF 6 - -#define set_layer_addr SPX_NAMESPACE(set_layer_addr) -void set_layer_addr(uint32_t addr[8], uint32_t layer); - -#define set_tree_addr SPX_NAMESPACE(set_tree_addr) -void set_tree_addr(uint32_t addr[8], uint64_t tree); - -#define set_type SPX_NAMESPACE(set_type) -void set_type(uint32_t addr[8], uint32_t type); - -/* Copies the layer and tree part of one address into the other */ -#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) -void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for WOTS and FORS addresses. */ - -#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) -void set_keypair_addr(uint32_t addr[8], uint32_t keypair); - -#define set_chain_addr SPX_NAMESPACE(set_chain_addr) -void set_chain_addr(uint32_t addr[8], uint32_t chain); - -#define set_hash_addr SPX_NAMESPACE(set_hash_addr) -void set_hash_addr(uint32_t addr[8], uint32_t hash); - -#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) -void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for all hash tree addresses (including FORS). */ - -#define set_tree_height SPX_NAMESPACE(set_tree_height) -void set_tree_height(uint32_t addr[8], uint32_t tree_height); - -#define set_tree_index SPX_NAMESPACE(set_tree_index) -void set_tree_index(uint32_t addr[8], uint32_t tree_index); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/api.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/api.h deleted file mode 100644 index f292697e93..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/api.h +++ /dev/null @@ -1,77 +0,0 @@ -#ifndef PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_API_H -#define PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_API_H - -#include -#include - -#define PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_CRYPTO_ALGNAME "SPHINCS+-haraka-128s-simple" - -#define PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_CRYPTO_SECRETKEYBYTES 64 -#define PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_CRYPTO_PUBLICKEYBYTES 32 -#define PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_CRYPTO_BYTES 7856 - -#define PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_CRYPTO_SEEDBYTES 48 - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, - const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk); -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/context.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/context.h deleted file mode 100644 index f03446b9cb..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/context.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef SPX_CONTEXT_H -#define SPX_CONTEXT_H - -#include - -#include "immintrin.h" -#include "params.h" - -typedef struct { - uint8_t pub_seed[SPX_N]; - uint8_t sk_seed[SPX_N]; - - __m128i rc[40]; -} spx_ctx; - -#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) -void initialize_hash_function(spx_ctx *ctx); - -#define free_hash_function SPX_NAMESPACE(free_hash_function) -void free_hash_function(spx_ctx *ctx); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/context_haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/context_haraka.c deleted file mode 100644 index f1cd7e3664..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/context_haraka.c +++ /dev/null @@ -1,11 +0,0 @@ -#include "context.h" -#include "haraka.h" - -void initialize_hash_function(spx_ctx *ctx) { - tweak_constants(ctx); -} - -// we don't support heap-based haraka right now -void free_hash_function(spx_ctx *ctx) { - (void)ctx; // suppress unused variable warnings -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/fors.c b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/fors.c deleted file mode 100644 index f1b0639cfc..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/fors.c +++ /dev/null @@ -1,202 +0,0 @@ -#include -#include -#include - -#include "fors.h" - -#include "address.h" -#include "hash.h" -#include "hashx4.h" -#include "thash.h" -#include "thashx4.h" -#include "utils.h" -#include "utilsx4.h" - -static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, - uint32_t fors_leaf_addr[8]) { - prf_addr(sk, ctx, fors_leaf_addr); -} - -static void fors_gen_skx4(unsigned char *sk0, - unsigned char *sk1, - unsigned char *sk2, - unsigned char *sk3, const spx_ctx *ctx, - uint32_t fors_leaf_addrx4[4 * 8]) { - prf_addrx4(sk0, sk1, sk2, sk3, - ctx, fors_leaf_addrx4); -} - -static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, - const spx_ctx *ctx, - uint32_t fors_leaf_addr[8]) { - thash(leaf, sk, 1, ctx, fors_leaf_addr); -} - -static void fors_sk_to_leafx4(unsigned char *leaf0, - unsigned char *leaf1, - unsigned char *leaf2, - unsigned char *leaf3, - const unsigned char *sk0, - const unsigned char *sk1, - const unsigned char *sk2, - const unsigned char *sk3, - const spx_ctx *ctx, - uint32_t fors_leaf_addrx4[4 * 8]) { - thashx4(leaf0, leaf1, leaf2, leaf3, - sk0, sk1, sk2, sk3, - 1, ctx, fors_leaf_addrx4); -} - -struct fors_gen_leaf_info { - uint32_t leaf_addrx[4 * 8]; -}; - -static void fors_gen_leafx4(unsigned char *leaf, - const spx_ctx *ctx, - uint32_t addr_idx, void *info) { - struct fors_gen_leaf_info *fors_info = info; - uint32_t *fors_leaf_addrx4 = fors_info->leaf_addrx; - unsigned int j; - - /* Only set the parts that the caller doesn't set */ - for (j = 0; j < 4; j++) { - set_tree_index(fors_leaf_addrx4 + j * 8, addr_idx + j); - set_type(fors_leaf_addrx4 + j * 8, SPX_ADDR_TYPE_FORSPRF); - } - - fors_gen_skx4(leaf + 0 * SPX_N, - leaf + 1 * SPX_N, - leaf + 2 * SPX_N, - leaf + 3 * SPX_N, - ctx, fors_leaf_addrx4); - - for (j = 0; j < 4; j++) { - set_type(fors_leaf_addrx4 + j * 8, SPX_ADDR_TYPE_FORSTREE); - } - - fors_sk_to_leafx4(leaf + 0 * SPX_N, - leaf + 1 * SPX_N, - leaf + 2 * SPX_N, - leaf + 3 * SPX_N, - leaf + 0 * SPX_N, - leaf + 1 * SPX_N, - leaf + 2 * SPX_N, - leaf + 3 * SPX_N, - ctx, fors_leaf_addrx4); -} - -/** - * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - * Assumes indices has space for SPX_FORS_TREES integers. - */ -static void message_to_indices(uint32_t *indices, const unsigned char *m) { - unsigned int i, j; - unsigned int offset = 0; - - for (i = 0; i < SPX_FORS_TREES; i++) { - indices[i] = 0; - for (j = 0; j < SPX_FORS_HEIGHT; j++) { - indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); - offset++; - } - } -} - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -void fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]) { - uint32_t indices[SPX_FORS_TREES]; - unsigned char roots[SPX_FORS_TREES * SPX_N]; - uint32_t fors_tree_addr[4 * 8] = {0}; - struct fors_gen_leaf_info fors_info = {0}; - uint32_t *fors_leaf_addr = fors_info.leaf_addrx; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - for (i = 0; i < 4; i++) { - copy_keypair_addr(fors_tree_addr + 8 * i, fors_addr); - set_type(fors_tree_addr + 8 * i, SPX_ADDR_TYPE_FORSTREE); - copy_keypair_addr(fors_leaf_addr + 8 * i, fors_addr); - } - copy_keypair_addr(fors_pk_addr, fors_addr); - set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < SPX_FORS_TREES; i++) { - idx_offset = i * (1 << SPX_FORS_HEIGHT); - - set_tree_height(fors_tree_addr, 0); - set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Include the secret key part that produces the selected leaf node. */ - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); - fors_gen_sk(sig, ctx, fors_tree_addr); - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); - sig += SPX_N; - - /* Compute the authentication path for this leaf node. */ - treehashx4(roots + i * SPX_N, sig, ctx, - indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx4, - fors_tree_addr, &fors_info); - - sig += SPX_N * SPX_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); -} - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -void fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]) { - uint32_t indices[SPX_FORS_TREES]; - unsigned char roots[SPX_FORS_TREES * SPX_N]; - unsigned char leaf[SPX_N]; - uint32_t fors_tree_addr[8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - copy_keypair_addr(fors_tree_addr, fors_addr); - copy_keypair_addr(fors_pk_addr, fors_addr); - - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); - set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < SPX_FORS_TREES; i++) { - idx_offset = i * (1 << SPX_FORS_HEIGHT); - - set_tree_height(fors_tree_addr, 0); - set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Derive the leaf from the included secret key part. */ - fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); - sig += SPX_N; - - /* Derive the corresponding root node of this tree. */ - compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, - sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); - sig += SPX_N * SPX_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/fors.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/fors.h deleted file mode 100644 index 509140a178..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/fors.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef SPX_FORS_H -#define SPX_FORS_H - -#include - -#include "context.h" -#include "params.h" - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -#define fors_sign SPX_NAMESPACE(fors_sign) -void fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]); - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) -void fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/haraka.c deleted file mode 100644 index b414b691d7..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/haraka.c +++ /dev/null @@ -1,702 +0,0 @@ -/* -Plain C implementation of the Haraka256 and Haraka512 permutations. -*/ -#include -#include -#include -#include -#include - -#include "haraka.h" -#include "harakax4.h" -#include "utils.h" - -#define HARAKAS_RATE 32 - -#define u64 unsigned long -#define u128 __m128i - -#define LOAD(src) _mm_loadu_si128((u128 *)(src)) -#define STORE(dest,src) _mm_storeu_si128((u128 *)(dest),src) - -#define XOR128(a, b) _mm_xor_si128(a, b) - -#define AES2(s0, s1, rci) \ - s0 = _mm_aesenc_si128(s0, *(rci)); \ - (s1) = _mm_aesenc_si128(s1, *((rci) + 1)); \ - (s0) = _mm_aesenc_si128(s0, *((rci) + 2)); \ - (s1) = _mm_aesenc_si128(s1, *((rci) + 3)); - -#define AES2_4x(s0, s1, s2, s3, rci) \ - AES2((s0)[0], (s0)[1], rci); \ - AES2((s1)[0], (s1)[1], rci); \ - AES2((s2)[0], (s2)[1], rci); \ - AES2((s3)[0], (s3)[1], rci); - -#define AES4(s0, s1, s2, s3, rci) \ - s0 = _mm_aesenc_si128(s0, *(rci)); \ - (s1) = _mm_aesenc_si128(s1, *((rci) + 1)); \ - (s2) = _mm_aesenc_si128(s2, *((rci) + 2)); \ - (s3) = _mm_aesenc_si128(s3, *((rci) + 3)); \ - (s0) = _mm_aesenc_si128(s0, *((rci) + 4)); \ - (s1) = _mm_aesenc_si128(s1, *((rci) + 5)); \ - (s2) = _mm_aesenc_si128(s2, *((rci) + 6)); \ - (s3) = _mm_aesenc_si128(s3, *((rci) + 7)); - -#define AES4_4x(s0, s1, s2, s3, rci) \ - AES4((s0)[0], (s0)[1], (s0)[2], (s0)[3], rci); \ - AES4((s1)[0], (s1)[1], (s1)[2], (s1)[3], rci); \ - AES4((s2)[0], (s2)[1], (s2)[2], (s2)[3], rci); \ - AES4((s3)[0], (s3)[1], (s3)[2], (s3)[3], rci); - -#define MIX2(s0, s1) \ - tmp = _mm_unpacklo_epi32(s0, s1); \ - (s1) = _mm_unpackhi_epi32(s0, s1); \ - (s0) = tmp; - -#define MIX4(s0, s1, s2, s3) \ - tmp = _mm_unpacklo_epi32(s0, s1); \ - (s0) = _mm_unpackhi_epi32(s0, s1); \ - (s1) = _mm_unpacklo_epi32(s2, s3); \ - (s2) = _mm_unpackhi_epi32(s2, s3); \ - (s3) = _mm_unpacklo_epi32(s0, s2); \ - (s0) = _mm_unpackhi_epi32(s0, s2); \ - (s2) = _mm_unpackhi_epi32(s1, tmp); \ - (s1) = _mm_unpacklo_epi32(s1, tmp); - -#define TRUNCSTORE(out, s0, s1, s2, s3) \ - _mm_storeu_si128((u128 *)(out), \ - _mm_castpd_si128(_mm_shuffle_pd(_mm_castsi128_pd(s0), _mm_castsi128_pd(s1), 3))); \ - _mm_storeu_si128((u128 *)((out) + 16), \ - _mm_castpd_si128(_mm_shuffle_pd(_mm_castsi128_pd(s2), _mm_castsi128_pd(s3), 0))); - -static void load_haraka_constants(u128 *rc) { - rc[0] = _mm_set_epi32((int)0x0684704c, (int)0xe620c00a, (int)0xb2c5fef0, (int)0x75817b9d); - rc[1] = _mm_set_epi32((int)0x8b66b4e1, (int)0x88f3a06b, (int)0x640f6ba4, (int)0x2f08f717); - rc[2] = _mm_set_epi32((int)0x3402de2d, (int)0x53f28498, (int)0xcf029d60, (int)0x9f029114); - rc[3] = _mm_set_epi32((int)0x0ed6eae6, (int)0x2e7b4f08, (int)0xbbf3bcaf, (int)0xfd5b4f79); - rc[4] = _mm_set_epi32((int)0xcbcfb0cb, (int)0x4872448b, (int)0x79eecd1c, (int)0xbe397044); - rc[5] = _mm_set_epi32((int)0x7eeacdee, (int)0x6e9032b7, (int)0x8d5335ed, (int)0x2b8a057b); - rc[6] = _mm_set_epi32((int)0x67c28f43, (int)0x5e2e7cd0, (int)0xe2412761, (int)0xda4fef1b); - rc[7] = _mm_set_epi32((int)0x2924d9b0, (int)0xafcacc07, (int)0x675ffde2, (int)0x1fc70b3b); - rc[8] = _mm_set_epi32((int)0xab4d63f1, (int)0xe6867fe9, (int)0xecdb8fca, (int)0xb9d465ee); - rc[9] = _mm_set_epi32((int)0x1c30bf84, (int)0xd4b7cd64, (int)0x5b2a404f, (int)0xad037e33); - rc[10] = _mm_set_epi32((int)0xb2cc0bb9, (int)0x941723bf, (int)0x69028b2e, (int)0x8df69800); - rc[11] = _mm_set_epi32((int)0xfa0478a6, (int)0xde6f5572, (int)0x4aaa9ec8, (int)0x5c9d2d8a); - rc[12] = _mm_set_epi32((int)0xdfb49f2b, (int)0x6b772a12, (int)0x0efa4f2e, (int)0x29129fd4); - rc[13] = _mm_set_epi32((int)0x1ea10344, (int)0xf449a236, (int)0x32d611ae, (int)0xbb6a12ee); - rc[14] = _mm_set_epi32((int)0xaf044988, (int)0x4b050084, (int)0x5f9600c9, (int)0x9ca8eca6); - rc[15] = _mm_set_epi32((int)0x21025ed8, (int)0x9d199c4f, (int)0x78a2c7e3, (int)0x27e593ec); - rc[16] = _mm_set_epi32((int)0xbf3aaaf8, (int)0xa759c9b7, (int)0xb9282ecd, (int)0x82d40173); - rc[17] = _mm_set_epi32((int)0x6260700d, (int)0x6186b017, (int)0x37f2efd9, (int)0x10307d6b); - rc[18] = _mm_set_epi32((int)0x5aca45c2, (int)0x21300443, (int)0x81c29153, (int)0xf6fc9ac6); - rc[19] = _mm_set_epi32((int)0x9223973c, (int)0x226b68bb, (int)0x2caf92e8, (int)0x36d1943a); - rc[20] = _mm_set_epi32((int)0xd3bf9238, (int)0x225886eb, (int)0x6cbab958, (int)0xe51071b4); - rc[21] = _mm_set_epi32((int)0xdb863ce5, (int)0xaef0c677, (int)0x933dfddd, (int)0x24e1128d); - rc[22] = _mm_set_epi32((int)0xbb606268, (int)0xffeba09c, (int)0x83e48de3, (int)0xcb2212b1); - rc[23] = _mm_set_epi32((int)0x734bd3dc, (int)0xe2e4d19c, (int)0x2db91a4e, (int)0xc72bf77d); - rc[24] = _mm_set_epi32((int)0x43bb47c3, (int)0x61301b43, (int)0x4b1415c4, (int)0x2cb3924e); - rc[25] = _mm_set_epi32((int)0xdba775a8, (int)0xe707eff6, (int)0x03b231dd, (int)0x16eb6899); - rc[26] = _mm_set_epi32((int)0x6df3614b, (int)0x3c755977, (int)0x8e5e2302, (int)0x7eca472c); - rc[27] = _mm_set_epi32((int)0xcda75a17, (int)0xd6de7d77, (int)0x6d1be5b9, (int)0xb88617f9); - rc[28] = _mm_set_epi32((int)0xec6b43f0, (int)0x6ba8e9aa, (int)0x9d6c069d, (int)0xa946ee5d); - rc[29] = _mm_set_epi32((int)0xcb1e6950, (int)0xf957332b, (int)0xa2531159, (int)0x3bf327c1); - rc[30] = _mm_set_epi32((int)0x2cee0c75, (int)0x00da619c, (int)0xe4ed0353, (int)0x600ed0d9); - rc[31] = _mm_set_epi32((int)0xf0b1a5a1, (int)0x96e90cab, (int)0x80bbbabc, (int)0x63a4a350); - rc[32] = _mm_set_epi32((int)0xae3db102, (int)0x5e962988, (int)0xab0dde30, (int)0x938dca39); - rc[33] = _mm_set_epi32((int)0x17bb8f38, (int)0xd554a40b, (int)0x8814f3a8, (int)0x2e75b442); - rc[34] = _mm_set_epi32((int)0x34bb8a5b, (int)0x5f427fd7, (int)0xaeb6b779, (int)0x360a16f6); - rc[35] = _mm_set_epi32((int)0x26f65241, (int)0xcbe55438, (int)0x43ce5918, (int)0xffbaafde); - rc[36] = _mm_set_epi32((int)0x4ce99a54, (int)0xb9f3026a, (int)0xa2ca9cf7, (int)0x839ec978); - rc[37] = _mm_set_epi32((int)0xae51a51a, (int)0x1bdff7be, (int)0x40c06e28, (int)0x22901235); - rc[38] = _mm_set_epi32((int)0xa0c1613c, (int)0xba7ed22b, (int)0xc173bc0f, (int)0x48a659cf); - rc[39] = _mm_set_epi32((int)0x756acc03, (int)0x02288288, (int)0x4ad6bdfd, (int)0xe9c59da1); -} - -void tweak_constants(spx_ctx *ctx) { - int i; - unsigned char buf[40 * 16]; - - /* Use the standard constants to generate tweaked ones. */ - load_haraka_constants(ctx->rc); - - /* Constants for pk.seed */ - haraka_S(buf, 40 * 16, ctx->pub_seed, SPX_N, ctx); - - /* Tweak constants with the pub_seed */ - for (i = 0; i < 40; i++) { - ctx->rc[i] = LOAD(buf + i * 16); - } -} - -static void haraka_S_absorb(unsigned char *s, unsigned int r, - const unsigned char *m, unsigned long long mlen, - unsigned char p, const spx_ctx *ctx) { - unsigned long long i; - PQCLEAN_VLA(unsigned char, t, r); - - while (mlen >= r) { - // XOR block to state - STORE(s, XOR128(LOAD(s), LOAD(m))); - STORE(s + 16, XOR128(LOAD(s + 16), LOAD(m + 16))); - haraka512_perm(s, s, ctx); - 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; - STORE(s, XOR128(LOAD(s), LOAD(t))); - STORE(s + 16, XOR128(LOAD(s + 16), LOAD(t + 16))); -} - -static void haraka_S_absorb4x(unsigned char *s, - unsigned int r, - const unsigned char *m0, - const unsigned char *m1, - const unsigned char *m2, - const unsigned char *m3, - unsigned long long int mlen, - unsigned char p, - const spx_ctx *ctx) { - unsigned long long i; - PQCLEAN_VLA(unsigned char, t0, r); - PQCLEAN_VLA(unsigned char, t1, r); - PQCLEAN_VLA(unsigned char, t2, r); - PQCLEAN_VLA(unsigned char, t3, r); - - while (mlen >= r) { - // XOR block to state - STORE(s, XOR128(LOAD(s), LOAD(m0))); - STORE(s + 16, XOR128(LOAD(s + 16), LOAD(m0 + 16))); - STORE(s + 64, XOR128(LOAD(s + 64), LOAD(m1))); - STORE(s + 80, XOR128(LOAD(s + 80), LOAD(m1 + 16))); - STORE(s + 128, XOR128(LOAD(s + 128), LOAD(m2))); - STORE(s + 144, XOR128(LOAD(s + 144), LOAD(m2 + 16))); - STORE(s + 192, XOR128(LOAD(s + 192), LOAD(m3))); - STORE(s + 208, XOR128(LOAD(s + 208), LOAD(m3 + 16))); - - haraka512_perm_x4(s, s, ctx); - mlen -= r; - m0 += r; - m1 += r; - m2 += r; - m3 += r; - } - - for (i = 0; i < r; ++i) { - t0[i] = 0; - t1[i] = 0; - t2[i] = 0; - t3[i] = 0; - } - for (i = 0; i < mlen; ++i) { - t0[i] = m0[i]; - t1[i] = m1[i]; - t2[i] = m2[i]; - t3[i] = m3[i]; - } - - t0[i] = p; - t1[i] = p; - t2[i] = p; - t3[i] = p; - - t0[r - 1] |= 128; - t1[r - 1] |= 128; - t2[r - 1] |= 128; - t3[r - 1] |= 128; - - STORE(s, XOR128(LOAD(s), LOAD(t0))); - STORE(s + 16, XOR128(LOAD(s + 16), LOAD(t0 + 16))); - STORE(s + 64, XOR128(LOAD(s + 64), LOAD(t1))); - STORE(s + 80, XOR128(LOAD(s + 80), LOAD(t1 + 16))); - STORE(s + 128, XOR128(LOAD(s + 128), LOAD(t2))); - STORE(s + 144, XOR128(LOAD(s + 144), LOAD(t2 + 16))); - STORE(s + 192, XOR128(LOAD(s + 192), LOAD(t3))); - STORE(s + 208, XOR128(LOAD(s + 208), LOAD(t3 + 16))); -} - -static void haraka_S_squeezeblocks(unsigned char *h, unsigned long long nblocks, - unsigned char *s, unsigned int r, - const spx_ctx *ctx) { - while (nblocks > 0) { - haraka512_perm(s, s, ctx); - STORE(h, LOAD(s)); - STORE(h + 16, LOAD(s + 16)); - h += r; - nblocks--; - } -} - -static void haraka_S_squeezeblocks4x(unsigned char *h0, - unsigned char *h1, - unsigned char *h2, - unsigned char *h3, - unsigned long long nblocks, - unsigned char *s, - unsigned int r, - const spx_ctx *ctx) { - while (nblocks > 0) { - haraka512_perm_x4(s, s, ctx); - STORE(h0, LOAD(s)); - STORE(h0 + 16, LOAD(s + 16)); - STORE(h1, LOAD(s + 64)); - STORE(h1 + 16, LOAD(s + 80)); - STORE(h2, LOAD(s + 128)); - STORE(h2 + 16, LOAD(s + 144)); - STORE(h3, LOAD(s + 192)); - STORE(h3 + 16, LOAD(s + 208)); - h0 += r; - h1 += r; - h2 += r; - h3 += r; - nblocks--; - } -} - -void haraka_S_inc_init(uint8_t *s_inc) { - size_t i; - - for (i = 0; i < 64; i++) { - s_inc[i] = 0; - } - s_inc[64] = 0; -} - -void haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, - const spx_ctx *ctx) { - size_t i; - - /* Recall that s_inc[64] is the non-absorbed bytes xored into the state */ - while (mlen + s_inc[64] >= HARAKAS_RATE) { - for (i = 0; i < (size_t)(HARAKAS_RATE - s_inc[64]); i++) { - /* Take the i'th byte from message - xor with the s_inc[64] + i'th byte of the state */ - s_inc[s_inc[64] + i] ^= m[i]; - } - mlen -= (size_t)(HARAKAS_RATE - s_inc[64]); - m += HARAKAS_RATE - s_inc[64]; - s_inc[64] = 0; - - haraka512_perm(s_inc, s_inc, ctx); - } - - for (i = 0; i < mlen; i++) { - s_inc[s_inc[64] + i] ^= m[i]; - } - s_inc[64] += (uint8_t)mlen; -} - -void haraka_S_inc_finalize(uint8_t *s_inc) { - /* After haraka_S_inc_absorb, we are guaranteed that s_inc[64] < HARAKAS_RATE, - so we can always use one more byte for p in the current state. */ - s_inc[s_inc[64]] ^= 0x1F; - s_inc[HARAKAS_RATE - 1] ^= 128; - s_inc[64] = 0; -} - -void haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, - const spx_ctx *ctx) { - size_t i; - - /* First consume any bytes we still have sitting around */ - for (i = 0; i < outlen && i < s_inc[64]; i++) { - /* There are s_inc[64] bytes left, so r - s_inc[64] is the first - available byte. We consume from there, i.e., up to r. */ - out[i] = (uint8_t)s_inc[(HARAKAS_RATE - s_inc[64] + i)]; - } - out += i; - outlen -= i; - s_inc[64] -= (uint8_t)i; - - /* Then squeeze the remaining necessary blocks */ - while (outlen > 0) { - haraka512_perm(s_inc, s_inc, ctx); - - for (i = 0; i < outlen && i < HARAKAS_RATE; i++) { - out[i] = s_inc[i]; - } - out += i; - outlen -= i; - s_inc[64] = (uint8_t)(HARAKAS_RATE - i); - } -} - -void haraka_S(unsigned char *out, unsigned long long outlen, - const unsigned char *in, unsigned long long inlen, - const spx_ctx *ctx) { - unsigned long long i; - unsigned char s[64]; - unsigned char d[32]; - - for (i = 0; i < 64; i++) { - s[i] = 0; - } - haraka_S_absorb(s, HARAKAS_RATE, in, inlen, 0x1F, ctx); - - haraka_S_squeezeblocks(out, outlen / HARAKAS_RATE, s, HARAKAS_RATE, ctx); - out += (outlen / HARAKAS_RATE) * HARAKAS_RATE; - - if (outlen % HARAKAS_RATE) { - haraka_S_squeezeblocks(d, 1, s, HARAKAS_RATE, ctx); - for (i = 0; i < outlen % HARAKAS_RATE; i++) { - out[i] = d[i]; - } - } -} - -void haraka_Sx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned long long outlen, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - unsigned long long inlen, - const spx_ctx *ctx) { - unsigned long long i; - unsigned char s[64 * 4]; - unsigned char d0[32]; - unsigned char d1[32]; - unsigned char d2[32]; - unsigned char d3[32]; - - for (i = 0; i < 64 * 4; i++) { - s[i] = 0; - } - haraka_S_absorb4x(s, HARAKAS_RATE, in0, in1, in2, in3, inlen, 0x1F, ctx); - - haraka_S_squeezeblocks4x(out0, out1, out2, out3, outlen / HARAKAS_RATE, s, - HARAKAS_RATE, ctx); - out0 += (outlen / HARAKAS_RATE) * HARAKAS_RATE; - out1 += (outlen / HARAKAS_RATE) * HARAKAS_RATE; - out2 += (outlen / HARAKAS_RATE) * HARAKAS_RATE; - out3 += (outlen / HARAKAS_RATE) * HARAKAS_RATE; - - if (outlen % HARAKAS_RATE) { - haraka_S_squeezeblocks4x(d0, d1, d2, d3, 1, s, HARAKAS_RATE, ctx); - for (i = 0; i < outlen % HARAKAS_RATE; i++) { - out0[i] = d0[i]; - out1[i] = d1[i]; - out2[i] = d2[i]; - out3[i] = d3[i]; - } - } -} - -void haraka512_perm(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx) { - u128 s[4], tmp; - - s[0] = LOAD(in); - s[1] = LOAD(in + 16); - s[2] = LOAD(in + 32); - s[3] = LOAD(in + 48); - - AES4(s[0], s[1], s[2], s[3], ctx->rc); - MIX4(s[0], s[1], s[2], s[3]); - - AES4(s[0], s[1], s[2], s[3], ctx->rc + 8); - MIX4(s[0], s[1], s[2], s[3]); - - AES4(s[0], s[1], s[2], s[3], ctx->rc + 16); - MIX4(s[0], s[1], s[2], s[3]); - - AES4(s[0], s[1], s[2], s[3], ctx->rc + 24); - MIX4(s[0], s[1], s[2], s[3]); - - AES4(s[0], s[1], s[2], s[3], ctx->rc + 32); - MIX4(s[0], s[1], s[2], s[3]); - - STORE(out, s[0]); - STORE(out + 16, s[1]); - STORE(out + 32, s[2]); - STORE(out + 48, s[3]); -} - -void haraka512_perm_x4(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx) { - u128 s[4][4], tmp; - - s[0][0] = LOAD(in); - s[0][1] = LOAD(in + 16); - s[0][2] = LOAD(in + 32); - s[0][3] = LOAD(in + 48); - s[1][0] = LOAD(in + 64); - s[1][1] = LOAD(in + 80); - s[1][2] = LOAD(in + 96); - s[1][3] = LOAD(in + 112); - s[2][0] = LOAD(in + 128); - s[2][1] = LOAD(in + 144); - s[2][2] = LOAD(in + 160); - s[2][3] = LOAD(in + 176); - s[3][0] = LOAD(in + 192); - s[3][1] = LOAD(in + 208); - s[3][2] = LOAD(in + 224); - s[3][3] = LOAD(in + 240); - - AES4_4x(s[0], s[1], s[2], s[3], ctx->rc); - MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); - MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); - MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); - MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - - AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 8); - MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); - MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); - MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); - MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - - AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 16); - MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); - MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); - MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); - MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - - AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 24); - MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); - MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); - MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); - MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - - AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 32); - MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); - MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); - MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); - MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - - STORE(out, s[0][0]); - STORE(out + 16, s[0][1]); - STORE(out + 32, s[0][2]); - STORE(out + 48, s[0][3]); - STORE(out + 64, s[1][0]); - STORE(out + 80, s[1][1]); - STORE(out + 96, s[1][2]); - STORE(out + 112, s[1][3]); - STORE(out + 128, s[2][0]); - STORE(out + 144, s[2][1]); - STORE(out + 160, s[2][2]); - STORE(out + 176, s[2][3]); - STORE(out + 192, s[3][0]); - STORE(out + 208, s[3][1]); - STORE(out + 224, s[3][2]); - STORE(out + 240, s[3][3]); -} - -void haraka512(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx) { - u128 s[4], tmp; - - s[0] = LOAD(in); - s[1] = LOAD(in + 16); - s[2] = LOAD(in + 32); - s[3] = LOAD(in + 48); - - AES4(s[0], s[1], s[2], s[3], ctx->rc); - MIX4(s[0], s[1], s[2], s[3]); - - AES4(s[0], s[1], s[2], s[3], ctx->rc + 8); - MIX4(s[0], s[1], s[2], s[3]); - - AES4(s[0], s[1], s[2], s[3], ctx->rc + 16); - MIX4(s[0], s[1], s[2], s[3]); - - AES4(s[0], s[1], s[2], s[3], ctx->rc + 24); - MIX4(s[0], s[1], s[2], s[3]); - - AES4(s[0], s[1], s[2], s[3], ctx->rc + 32); - MIX4(s[0], s[1], s[2], s[3]); - - s[0] = XOR128(s[0], LOAD(in)); - s[1] = XOR128(s[1], LOAD(in + 16)); - s[2] = XOR128(s[2], LOAD(in + 32)); - s[3] = XOR128(s[3], LOAD(in + 48)); - - // truncate and store result - TRUNCSTORE(out, s[0], s[1], s[2], s[3]); -} - -void haraka512x4(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx) { - u128 s[4][4], tmp; - - s[0][0] = LOAD(in); - s[0][1] = LOAD(in + 16); - s[0][2] = LOAD(in + 32); - s[0][3] = LOAD(in + 48); - s[1][0] = LOAD(in + 64); - s[1][1] = LOAD(in + 80); - s[1][2] = LOAD(in + 96); - s[1][3] = LOAD(in + 112); - s[2][0] = LOAD(in + 128); - s[2][1] = LOAD(in + 144); - s[2][2] = LOAD(in + 160); - s[2][3] = LOAD(in + 176); - s[3][0] = LOAD(in + 192); - s[3][1] = LOAD(in + 208); - s[3][2] = LOAD(in + 224); - s[3][3] = LOAD(in + 240); - - AES4_4x(s[0], s[1], s[2], s[3], ctx->rc); - MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); - MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); - MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); - MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - - AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 8); - MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); - MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); - MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); - MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - - AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 16); - MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); - MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); - MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); - MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - - AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 24); - MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); - MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); - MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); - MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - - AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 32); - MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); - MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); - MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); - MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - - s[0][0] = XOR128(s[0][0], LOAD(in)); - s[0][1] = XOR128(s[0][1], LOAD(in + 16)); - s[0][2] = XOR128(s[0][2], LOAD(in + 32)); - s[0][3] = XOR128(s[0][3], LOAD(in + 48)); - s[1][0] = XOR128(s[1][0], LOAD(in + 64)); - s[1][1] = XOR128(s[1][1], LOAD(in + 80)); - s[1][2] = XOR128(s[1][2], LOAD(in + 96)); - s[1][3] = XOR128(s[1][3], LOAD(in + 112)); - s[2][0] = XOR128(s[2][0], LOAD(in + 128)); - s[2][1] = XOR128(s[2][1], LOAD(in + 144)); - s[2][2] = XOR128(s[2][2], LOAD(in + 160)); - s[2][3] = XOR128(s[2][3], LOAD(in + 176)); - s[3][0] = XOR128(s[3][0], LOAD(in + 192)); - s[3][1] = XOR128(s[3][1], LOAD(in + 208)); - s[3][2] = XOR128(s[3][2], LOAD(in + 224)); - s[3][3] = XOR128(s[3][3], LOAD(in + 240)); - - TRUNCSTORE(out, s[0][0], s[0][1], s[0][2], s[0][3]); - TRUNCSTORE((out + 32), s[1][0], s[1][1], s[1][2], s[1][3]); - TRUNCSTORE((out + 64), s[2][0], s[2][1], s[2][2], s[2][3]); - TRUNCSTORE((out + 96), s[3][0], s[3][1], s[3][2], s[3][3]); -} - -void haraka256(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx) { - u128 s[2], tmp; - - s[0] = LOAD(in); - s[1] = LOAD(in + 16); - - AES2(s[0], s[1], ctx->rc); - MIX2(s[0], s[1]); - - AES2(s[0], s[1], ctx->rc + 4); - MIX2(s[0], s[1]); - - AES2(s[0], s[1], ctx->rc + 8); - MIX2(s[0], s[1]); - - AES2(s[0], s[1], ctx->rc + 12); - MIX2(s[0], s[1]); - - AES2(s[0], s[1], ctx->rc + 16); - MIX2(s[0], s[1]); - - s[0] = XOR128(s[0], LOAD(in)); - s[1] = XOR128(s[1], LOAD(in + 16)); - - STORE(out, s[0]); - STORE(out + 16, s[1]); -} - -void haraka256x4(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx) { - u128 s[4][2], tmp; - - s[0][0] = LOAD(in); - s[0][1] = LOAD(in + 16); - s[1][0] = LOAD(in + 32); - s[1][1] = LOAD(in + 48); - s[2][0] = LOAD(in + 64); - s[2][1] = LOAD(in + 80); - s[3][0] = LOAD(in + 96); - s[3][1] = LOAD(in + 112); - - // Round 1 - AES2_4x(s[0], s[1], s[2], s[3], ctx->rc); - - MIX2(s[0][0], s[0][1]); - MIX2(s[1][0], s[1][1]); - MIX2(s[2][0], s[2][1]); - MIX2(s[3][0], s[3][1]); - - // Round 2 - AES2_4x(s[0], s[1], s[2], s[3], ctx->rc + 4); - - MIX2(s[0][0], s[0][1]); - MIX2(s[1][0], s[1][1]); - MIX2(s[2][0], s[2][1]); - MIX2(s[3][0], s[3][1]); - - // Round 3 - AES2_4x(s[0], s[1], s[2], s[3], ctx->rc + 8); - - MIX2(s[0][0], s[0][1]); - MIX2(s[1][0], s[1][1]); - MIX2(s[2][0], s[2][1]); - MIX2(s[3][0], s[3][1]); - - // Round 4 - AES2_4x(s[0], s[1], s[2], s[3], ctx->rc + 12); - - MIX2(s[0][0], s[0][1]); - MIX2(s[1][0], s[1][1]); - MIX2(s[2][0], s[2][1]); - MIX2(s[3][0], s[3][1]); - - // Round 5 - AES2_4x(s[0], s[1], s[2], s[3], ctx->rc + 16); - - MIX2(s[0][0], s[0][1]); - MIX2(s[1][0], s[1][1]); - MIX2(s[2][0], s[2][1]); - MIX2(s[3][0], s[3][1]); - - // Feed Forward - s[0][0] = _mm_xor_si128(s[0][0], LOAD(in)); - s[0][1] = _mm_xor_si128(s[0][1], LOAD(in + 16)); - s[1][0] = _mm_xor_si128(s[1][0], LOAD(in + 32)); - s[1][1] = _mm_xor_si128(s[1][1], LOAD(in + 48)); - s[2][0] = _mm_xor_si128(s[2][0], LOAD(in + 64)); - s[2][1] = _mm_xor_si128(s[2][1], LOAD(in + 80)); - s[3][0] = _mm_xor_si128(s[3][0], LOAD(in + 96)); - s[3][1] = _mm_xor_si128(s[3][1], LOAD(in + 112)); - - STORE(out, s[0][0]); - STORE(out + 16, s[0][1]); - STORE(out + 32, s[1][0]); - STORE(out + 48, s[1][1]); - STORE(out + 64, s[2][0]); - STORE(out + 80, s[2][1]); - STORE(out + 96, s[3][0]); - STORE(out + 112, s[3][1]); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/haraka.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/haraka.h deleted file mode 100644 index 737cb6065f..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/haraka.h +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef SPX_HARAKA_H -#define SPX_HARAKA_H - -#include "context.h" -#include "params.h" - -/* Tweak constants with seed */ -#define tweak_constants SPX_NAMESPACE(tweak_constants) -void tweak_constants(spx_ctx *ctx); - -/* Haraka Sponge */ -#define haraka_S_inc_init SPX_NAMESPACE(haraka_S_inc_init) -void haraka_S_inc_init(uint8_t *s_inc); -#define haraka_S_inc_absorb SPX_NAMESPACE(haraka_S_inc_absorb) -void haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, - const spx_ctx *ctx); -#define haraka_S_inc_finalize SPX_NAMESPACE(haraka_S_inc_finalize) -void haraka_S_inc_finalize(uint8_t *s_inc); -#define haraka_S_inc_squeeze SPX_NAMESPACE(haraka_S_inc_squeeze) -void haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, - const spx_ctx *ctx); -#define haraka_S SPX_NAMESPACE(haraka_S) -void haraka_S(unsigned char *out, unsigned long long outlen, - const unsigned char *in, unsigned long long inlen, - const spx_ctx *ctx); - -/* Applies the 512-bit Haraka permutation to in. */ -#define haraka512_perm SPX_NAMESPACE(haraka512_perm) -void haraka512_perm(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx); - -/* Implementation of Haraka-512 */ -#define haraka512 SPX_NAMESPACE(haraka512) -void haraka512(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx); - -/* Implementation of Haraka-256 */ -#define haraka256 SPX_NAMESPACE(haraka256) -void haraka256(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/haraka_offsets.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/haraka_offsets.h deleted file mode 100644 index 7c062272a0..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/haraka_offsets.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef HARAKA_OFFSETS_H_ -#define HARAKA_OFFSETS_H_ - -/* - * Offsets of various fields in the address structure when we use Haraka as - * the Sphincs+ hash function - */ - -#define SPX_OFFSET_LAYER 3 /* The byte used to specify the Merkle tree layer */ -#define SPX_OFFSET_TREE 8 /* The start of the 8 byte field used to specify the tree */ -#define SPX_OFFSET_TYPE 19 /* The byte used to specify the hash type (reason) */ -#define SPX_OFFSET_KP_ADDR2 22 /* The high byte used to specify the key pair (which one-time signature) */ -#define SPX_OFFSET_KP_ADDR1 23 /* The low byte used to specify the key pair */ -#define SPX_OFFSET_CHAIN_ADDR 27 /* The byte used to specify the chain address (which Winternitz chain) */ -#define SPX_OFFSET_HASH_ADDR 31 /* The byte used to specify the hash address (where in the Winternitz chain) */ -#define SPX_OFFSET_TREE_HGT 27 /* The byte used to specify the height of this node in the FORS or Merkle tree */ -#define SPX_OFFSET_TREE_INDEX 28 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ - -#define SPX_HARAKA 1 - -#endif /* HARAKA_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/harakax4.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/harakax4.h deleted file mode 100644 index eadc69aa48..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/harakax4.h +++ /dev/null @@ -1,36 +0,0 @@ -#ifndef SPX_HARAKAX4_H -#define SPX_HARAKAX4_H - -#include "context.h" -#include "params.h" - -/* Haraka Sponge */ -#define haraka_Sx4 SPX_NAMESPACE(haraka_Sx4) -void haraka_Sx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned long long outlen, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - unsigned long long inlen, - const spx_ctx *ctx); - -/* Applies the 512-bit Haraka permutation x4 to in. */ -#define haraka512_perm_x4 SPX_NAMESPACE(haraka512_perm_x4) -void haraka512_perm_x4(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx); - -/* Implementation of Haraka-512 x4*/ -#define haraka512x4 SPX_NAMESPACE(haraka512x4) -void haraka512x4(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx); - -/* Implementation of Haraka-256 x4 */ -#define haraka256x4 SPX_NAMESPACE(haraka256x4) -void haraka256x4(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/hash.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/hash.h deleted file mode 100644 index f7c87d4c3c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/hash.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef SPX_HASH_H -#define SPX_HASH_H - -#include -#include - -#include "context.h" -#include "params.h" - -#define prf_addr SPX_NAMESPACE(prf_addr) -void prf_addr(unsigned char *out, const spx_ctx *ctx, - const uint32_t addr[8]); - -#define gen_message_random SPX_NAMESPACE(gen_message_random) -void gen_message_random(unsigned char *R, const unsigned char *sk_prf, - const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx); - -#define hash_message SPX_NAMESPACE(hash_message) -void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx); - - - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/hash_haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/hash_haraka.c deleted file mode 100644 index 750a67423b..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/hash_haraka.c +++ /dev/null @@ -1,81 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "utils.h" - -#include "haraka.h" -#include "hash.h" - -/* - * Computes PRF(key, addr), given a secret key of SPX_N bytes and an address - */ -void prf_addr(unsigned char *out, const spx_ctx *ctx, - const uint32_t addr[8]) { - /* Since SPX_N may be smaller than 32, we need temporary buffers. */ - unsigned char outbuf[32]; - unsigned char buf[64] = {0}; - - memcpy(buf, addr, SPX_ADDR_BYTES); - memcpy(buf + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); - - haraka512(outbuf, (const void *)buf, ctx); - memcpy(out, outbuf, SPX_N); -} - -/** - * Computes the message-dependent randomness R, using a secret seed and an - * optional randomization value as well as the message. - */ -void gen_message_random(unsigned char *R, const unsigned char *sk_prf, - const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx) { - uint8_t s_inc[65]; - - haraka_S_inc_init(s_inc); - haraka_S_inc_absorb(s_inc, sk_prf, SPX_N, ctx); - haraka_S_inc_absorb(s_inc, optrand, SPX_N, ctx); - haraka_S_inc_absorb(s_inc, m, mlen, ctx); - haraka_S_inc_finalize(s_inc); - haraka_S_inc_squeeze(R, SPX_N, s_inc, ctx); -} - -/** - * Computes the message hash using R, the public key, and the message. - * Outputs the message digest and the index of the leaf. The index is split in - * the tree index and the leaf index, for convenient copying to an address. - */ -void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx) { -#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) -#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) -#define SPX_LEAF_BITS SPX_TREE_HEIGHT -#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) -#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) - - unsigned char buf[SPX_DGST_BYTES]; - unsigned char *bufp = buf; - uint8_t s_inc[65]; - - haraka_S_inc_init(s_inc); - haraka_S_inc_absorb(s_inc, R, SPX_N, ctx); - haraka_S_inc_absorb(s_inc, pk + SPX_N, SPX_N, ctx); // Only absorb root part of pk - haraka_S_inc_absorb(s_inc, m, mlen, ctx); - haraka_S_inc_finalize(s_inc); - haraka_S_inc_squeeze(buf, SPX_DGST_BYTES, s_inc, ctx); - - memcpy(digest, bufp, SPX_FORS_MSG_BYTES); - bufp += SPX_FORS_MSG_BYTES; - - - *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); - *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); - bufp += SPX_TREE_BYTES; - - *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); - *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/hash_harakax4.c b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/hash_harakax4.c deleted file mode 100644 index cfa5162d79..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/hash_harakax4.c +++ /dev/null @@ -1,35 +0,0 @@ -#include -#include - -#include "address.h" -#include "harakax4.h" -#include "hashx4.h" -#include "params.h" - -/* - * 4-way parallel version of prf_addr; takes 4x as much input and output - */ -#define prf_addrx4 SPX_NAMESPACE(prf_addrx4) -void prf_addrx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const spx_ctx *ctx, - const uint32_t addrx4[4 * 8]) { - unsigned char bufx4[4 * 64] = {0}; - /* Since SPX_N may be smaller than 32, we need temporary buffers. */ - unsigned char outbuf[4 * 32]; - unsigned int i; - - for (i = 0; i < 4; i++) { - memcpy(bufx4 + i * 64, addrx4 + i * 8, SPX_ADDR_BYTES); - memcpy(bufx4 + i * 64 + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); - } - - haraka512x4(outbuf, bufx4, ctx); - - memcpy(out0, outbuf, SPX_N); - memcpy(out1, outbuf + 32, SPX_N); - memcpy(out2, outbuf + 64, SPX_N); - memcpy(out3, outbuf + 96, SPX_N); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/hashx4.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/hashx4.h deleted file mode 100644 index 3751a0ebd0..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/hashx4.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef SPX_HASHX4_H -#define SPX_HASHX4_H - -#include - -#include "context.h" -#include "params.h" - -#define prf_addrx4 SPX_NAMESPACE(prf_addrx4) -void prf_addrx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const spx_ctx *ctx, - const uint32_t addrx4[4 * 8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/merkle.c b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/merkle.c deleted file mode 100644 index f57811c1ac..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/merkle.c +++ /dev/null @@ -1,64 +0,0 @@ -#include -#include - -#include "merkle.h" - -#include "address.h" -#include "params.h" -#include "utils.h" -#include "utilsx4.h" -#include "wots.h" -#include "wotsx4.h" - -/* - * This generates a Merkle signature (WOTS signature followed by the Merkle - * authentication path). - */ -void merkle_sign(uint8_t *sig, unsigned char *root, - const spx_ctx *ctx, - uint32_t wots_addr[8], uint32_t tree_addr[8], - uint32_t idx_leaf) { - unsigned char *auth_path = sig + SPX_WOTS_BYTES; - uint32_t tree_addrx4[4 * 8] = { 0 }; - int j; - struct leaf_info_x4 info = { 0 }; - unsigned steps[ SPX_WOTS_LEN ]; - - info.wots_sig = sig; - chain_lengths(steps, root); - info.wots_steps = steps; - - for (j = 0; j < 4; j++) { - set_type(&tree_addrx4[8 * j], SPX_ADDR_TYPE_HASHTREE); - set_type(&info.leaf_addr[8 * j], SPX_ADDR_TYPE_WOTS); - set_type(&info.pk_addr[8 * j], SPX_ADDR_TYPE_WOTSPK); - copy_subtree_addr(&tree_addrx4[8 * j], tree_addr); - copy_subtree_addr(&info.leaf_addr[8 * j], wots_addr); - copy_subtree_addr(&info.pk_addr[8 * j], wots_addr); - } - - info.wots_sign_leaf = idx_leaf; - - treehashx4(root, auth_path, ctx, - idx_leaf, 0, - SPX_TREE_HEIGHT, - wots_gen_leafx4, - tree_addrx4, &info); -} - -/* Compute root node of the top-most subtree. */ -void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { - /* We do not need the auth path in key generation, but it simplifies the - code to have just one treehash routine that computes both root and path - in one function. */ - unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; - uint32_t top_tree_addr[8] = {0}; - uint32_t wots_addr[8] = {0}; - - set_layer_addr(top_tree_addr, SPX_D - 1); - set_layer_addr(wots_addr, SPX_D - 1); - - merkle_sign(auth_path, root, ctx, - wots_addr, top_tree_addr, - ~0U /* ~0 means "don't bother generating an auth path */ ); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/merkle.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/merkle.h deleted file mode 100644 index 769cf2e970..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/merkle.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef MERKLE_H_ -#define MERKLE_H_ - -#include - -#include "context.h" -#include "params.h" - -/* Generate a Merkle signature (WOTS signature followed by the Merkle */ -/* authentication path) */ -#define merkle_sign SPX_NAMESPACE(merkle_sign) -void merkle_sign(uint8_t *sig, unsigned char *root, - const spx_ctx *ctx, - uint32_t wots_addr[8], uint32_t tree_addr[8], - uint32_t idx_leaf); - -/* Compute the root node of the top-most subtree. */ -#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) -void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); - -#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/nistapi.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/nistapi.h deleted file mode 100644 index 3cb71afad4..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/nistapi.h +++ /dev/null @@ -1,87 +0,0 @@ -#ifndef SPX_API_H -#define SPX_API_H - -#include -#include - -#include "params.h" - -#define CRYPTO_ALGNAME "SPHINCS+" - -#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES -#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES -#define CRYPTO_BYTES SPX_BYTES -#define CRYPTO_SEEDBYTES (3*SPX_N) - -/* - * Returns the length of a secret key, in bytes - */ -#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) -size_t crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) -size_t crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) -size_t crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) -size_t crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) -int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) -int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) -int crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) -int crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -#define crypto_sign SPX_NAMESPACE(crypto_sign) -int crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) -int crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/params.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/params.h deleted file mode 100644 index 1de64f01ac..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/params.h +++ /dev/null @@ -1,56 +0,0 @@ -#ifndef SPX_PARAMS_H -#define SPX_PARAMS_H - -#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_##s - -/* Hash output length in bytes. */ -#define SPX_N 16 -/* Height of the hypertree. */ -#define SPX_FULL_HEIGHT 63 -/* Number of subtree layer. */ -#define SPX_D 7 -/* FORS tree dimensions. */ -#define SPX_FORS_HEIGHT 12 -#define SPX_FORS_TREES 14 -/* Winternitz parameter, */ -#define SPX_WOTS_W 16 - -/* The hash function is defined by linking a different hash.c file, as opposed - to setting a #define constant. */ - -/* For clarity */ -#define SPX_ADDR_BYTES 32 - -/* WOTS parameters. */ -#define SPX_WOTS_LOGW 4 - -#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) - -/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#define SPX_WOTS_LEN2 3 - -#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) -#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) -#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES - -/* Subtree size. */ -#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) - -//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT -// #error SPX_D should always divide SPX_FULL_HEIGHT -//#endif - -/* FORS parameters. */ -#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) -#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) -#define SPX_FORS_PK_BYTES SPX_N - -/* Resulting SPX sizes. */ -#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ - SPX_FULL_HEIGHT * SPX_N) -#define SPX_PK_BYTES (2 * SPX_N) -#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) - -#include "haraka_offsets.h" - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/sign.c b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/sign.c deleted file mode 100644 index 9d0c7d1b22..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/sign.c +++ /dev/null @@ -1,286 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "context.h" -#include "fors.h" -#include "hash.h" -#include "merkle.h" -#include "nistapi.h" -#include "params.h" -#include "randombytes.h" -#include "thash.h" -#include "utils.h" -#include "wots.h" - -/* - * Returns the length of a secret key, in bytes - */ -size_t crypto_sign_secretkeybytes(void) { - return CRYPTO_SECRETKEYBYTES; -} - -/* - * Returns the length of a public key, in bytes - */ -size_t crypto_sign_publickeybytes(void) { - return CRYPTO_PUBLICKEYBYTES; -} - -/* - * Returns the length of a signature, in bytes - */ -size_t crypto_sign_bytes(void) { - return CRYPTO_BYTES; -} - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t crypto_sign_seedbytes(void) { - return CRYPTO_SEEDBYTES; -} - -/* - * Generates an SPX key pair given a seed of length - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed) { - spx_ctx ctx; - - /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ - memcpy(sk, seed, CRYPTO_SEEDBYTES); - - memcpy(pk, sk + 2 * SPX_N, SPX_N); - - memcpy(ctx.pub_seed, pk, SPX_N); - memcpy(ctx.sk_seed, sk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - /* Compute root node of the top-most subtree. */ - merkle_gen_root(sk + 3 * SPX_N, &ctx); - - // cleanup - free_hash_function(&ctx); - - memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); - - return 0; -} - -/* - * Generates an SPX key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { - uint8_t seed[CRYPTO_SEEDBYTES]; - randombytes(seed, CRYPTO_SEEDBYTES); - crypto_sign_seed_keypair(pk, sk, seed); - - return 0; -} - -/** - * Returns an array containing a detached signature. - */ -int crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - spx_ctx ctx; - - const uint8_t *sk_prf = sk + SPX_N; - const uint8_t *pk = sk + 2 * SPX_N; - - uint8_t optrand[SPX_N]; - uint8_t mhash[SPX_FORS_MSG_BYTES]; - uint8_t root[SPX_N]; - uint32_t i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - - memcpy(ctx.sk_seed, sk, SPX_N); - memcpy(ctx.pub_seed, pk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - set_type(wots_addr, SPX_ADDR_TYPE_WOTS); - set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); - - /* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ - randombytes(optrand, SPX_N); - /* Compute the digest randomization value. */ - gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); - - /* Derive the message digest and leaf index from R, PK and M. */ - hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); - sig += SPX_N; - - set_tree_addr(wots_addr, tree); - set_keypair_addr(wots_addr, idx_leaf); - - /* Sign the message hash using FORS. */ - fors_sign(sig, root, mhash, &ctx, wots_addr); - sig += SPX_FORS_BYTES; - - for (i = 0; i < SPX_D; i++) { - set_layer_addr(tree_addr, i); - set_tree_addr(tree_addr, tree); - - copy_subtree_addr(wots_addr, tree_addr); - set_keypair_addr(wots_addr, idx_leaf); - - merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); - sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); - tree = tree >> SPX_TREE_HEIGHT; - } - - free_hash_function(&ctx); - - *siglen = SPX_BYTES; - - return 0; -} - -/** - * Verifies a detached signature and message under a given public key. - */ -int crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk) { - spx_ctx ctx; - const uint8_t *pub_root = pk + SPX_N; - uint8_t mhash[SPX_FORS_MSG_BYTES]; - uint8_t wots_pk[SPX_WOTS_BYTES]; - uint8_t root[SPX_N]; - uint8_t leaf[SPX_N]; - unsigned int i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - if (siglen != SPX_BYTES) { - return -1; - } - - memcpy(ctx.pub_seed, pk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - set_type(wots_addr, SPX_ADDR_TYPE_WOTS); - set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); - set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); - - /* Derive the message digest and leaf index from R || PK || M. */ - /* The additional SPX_N is a result of the hash domain separator. */ - hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); - sig += SPX_N; - - /* Layer correctly defaults to 0, so no need to set_layer_addr */ - set_tree_addr(wots_addr, tree); - set_keypair_addr(wots_addr, idx_leaf); - - fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); - sig += SPX_FORS_BYTES; - - /* For each subtree.. */ - for (i = 0; i < SPX_D; i++) { - set_layer_addr(tree_addr, i); - set_tree_addr(tree_addr, tree); - - copy_subtree_addr(wots_addr, tree_addr); - set_keypair_addr(wots_addr, idx_leaf); - - copy_keypair_addr(wots_pk_addr, wots_addr); - - /* The WOTS public key is only correct if the signature was correct. */ - /* Initially, root is the FORS pk, but on subsequent iterations it is - the root of the subtree below the currently processed subtree. */ - wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); - sig += SPX_WOTS_BYTES; - - /* Compute the leaf node using the WOTS public key. */ - thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); - - /* Compute the root node of this subtree. */ - compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, - &ctx, tree_addr); - sig += SPX_TREE_HEIGHT * SPX_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); - tree = tree >> SPX_TREE_HEIGHT; - } - - // cleanup - free_hash_function(&ctx); - - /* Check if the root node equals the root node in the public key. */ - if (memcmp(root, pub_root, SPX_N) != 0) { - return -1; - } - - return 0; -} - - -/** - * Returns an array containing the signature followed by the message. - */ -int crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk) { - size_t siglen; - - crypto_sign_signature(sm, &siglen, m, mlen, sk); - - memmove(sm + SPX_BYTES, m, mlen); - *smlen = siglen + mlen; - - return 0; -} - -/** - * Verifies a given signature-message pair under a given public key. - */ -int crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk) { - /* The API caller does not necessarily know what size a signature should be - but SPHINCS+ signatures are always exactly SPX_BYTES. */ - if (smlen < SPX_BYTES) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - *mlen = smlen - SPX_BYTES; - - if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - /* If verification was successful, move the message to the right place. */ - memmove(m, sm + SPX_BYTES, *mlen); - - return 0; -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/thash.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/thash.h deleted file mode 100644 index 8687ccfb4d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/thash.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef SPX_THASH_H -#define SPX_THASH_H - -#include "context.h" -#include "params.h" - -#include - -#define thash SPX_NAMESPACE(thash) -void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/thash_haraka_simple.c b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/thash_haraka_simple.c deleted file mode 100644 index 207777bf8d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/thash_haraka_simple.c +++ /dev/null @@ -1,36 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "thash.h" -#include "utils.h" - -#include "haraka.h" - -/** - * Takes an array of inblocks concatenated arrays of SPX_N bytes. - */ -void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]) { - PQCLEAN_VLA(uint8_t, buf, SPX_ADDR_BYTES + inblocks * SPX_N); - unsigned char outbuf[32]; - unsigned char buf_tmp[64]; - - if (inblocks == 1) { - /* F function */ - /* Since SPX_N may be smaller than 32, we need a temporary buffer. */ - memset(buf_tmp, 0, 64); - memcpy(buf_tmp, addr, 32); - memcpy(buf_tmp + SPX_ADDR_BYTES, in, SPX_N); - - haraka512(outbuf, buf_tmp, ctx); - memcpy(out, outbuf, SPX_N); - } else { - /* All other tweakable hashes*/ - memcpy(buf, addr, 32); - memcpy(buf + SPX_ADDR_BYTES, in, inblocks * SPX_N); - - haraka_S(out, SPX_N, buf, SPX_ADDR_BYTES + inblocks * SPX_N, ctx); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/thash_haraka_simplex4.c b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/thash_haraka_simplex4.c deleted file mode 100644 index 2ee763d7d9..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/thash_haraka_simplex4.c +++ /dev/null @@ -1,67 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "thashx4.h" - -#include "harakax4.h" - -#include "utils.h" - -/** - * 4-way parallel version of thash; takes 4x as much input and output - */ -#define thashx4 SPX_NAMESPACE(thashx4) -void thashx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addrx4[4 * 8]) { - PQCLEAN_VLA(unsigned char, buf0, SPX_ADDR_BYTES + inblocks * SPX_N); - PQCLEAN_VLA(unsigned char, buf1, SPX_ADDR_BYTES + inblocks * SPX_N); - PQCLEAN_VLA(unsigned char, buf2, SPX_ADDR_BYTES + inblocks * SPX_N); - PQCLEAN_VLA(unsigned char, buf3, SPX_ADDR_BYTES + inblocks * SPX_N); - unsigned char outbuf[32 * 4]; - unsigned char buf_tmp[64 * 4]; - - if (inblocks == 1) { - memset(buf_tmp, 0, 64 * 4); - - memcpy(buf_tmp, addrx4 + 0 * 8, 32); - memcpy(buf_tmp + 64, addrx4 + 1 * 8, 32); - memcpy(buf_tmp + 128, addrx4 + 2 * 8, 32); - memcpy(buf_tmp + 192, addrx4 + 3 * 8, 32); - - memcpy(buf_tmp + SPX_ADDR_BYTES, in0, SPX_N); - memcpy(buf_tmp + SPX_ADDR_BYTES + 64, in1, SPX_N); - memcpy(buf_tmp + SPX_ADDR_BYTES + 128, in2, SPX_N); - memcpy(buf_tmp + SPX_ADDR_BYTES + 192, in3, SPX_N); - - haraka512x4(outbuf, buf_tmp, ctx); - - memcpy(out0, outbuf, SPX_N); - memcpy(out1, outbuf + 32, SPX_N); - memcpy(out2, outbuf + 64, SPX_N); - memcpy(out3, outbuf + 96, SPX_N); - } else { - /* All other tweakable hashes*/ - memcpy(buf0, addrx4 + 0 * 8, 32); - memcpy(buf1, addrx4 + 1 * 8, 32); - memcpy(buf2, addrx4 + 2 * 8, 32); - memcpy(buf3, addrx4 + 3 * 8, 32); - - memcpy(buf0 + SPX_ADDR_BYTES, in0, inblocks * SPX_N); - memcpy(buf1 + SPX_ADDR_BYTES, in1, inblocks * SPX_N); - memcpy(buf2 + SPX_ADDR_BYTES, in2, inblocks * SPX_N); - memcpy(buf3 + SPX_ADDR_BYTES, in3, inblocks * SPX_N); - - haraka_Sx4(out0, out1, out2, out3, SPX_N, - buf0, buf1, buf2, buf3, SPX_ADDR_BYTES + inblocks * SPX_N, - ctx); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/thashx4.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/thashx4.h deleted file mode 100644 index 64798a3727..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/thashx4.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef SPX_THASHX4_H -#define SPX_THASHX4_H - -#include - -#include "context.h" -#include "params.h" - -#define thashx4 SPX_NAMESPACE(thashx4) -void thashx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addrx4[4 * 8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/utils.c b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/utils.c deleted file mode 100644 index 177b541fb9..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/utils.c +++ /dev/null @@ -1,148 +0,0 @@ -#include - -#include "utils.h" - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "thash.h" - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void ull_to_bytes(unsigned char *out, unsigned int outlen, - unsigned long long in) { - int i; - - /* Iterate over out in decreasing order, for big-endianness. */ - for (i = (signed int)outlen - 1; i >= 0; i--) { - out[i] = in & 0xff; - in = in >> 8; - } -} - -void u32_to_bytes(unsigned char *out, uint32_t in) { - out[0] = (unsigned char)(in >> 24); - out[1] = (unsigned char)(in >> 16); - out[2] = (unsigned char)(in >> 8); - out[3] = (unsigned char)in; -} - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { - unsigned long long retval = 0; - unsigned int i; - - for (i = 0; i < inlen; i++) { - retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); - } - return retval; -} - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void compute_root(unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const spx_ctx *ctx, uint32_t addr[8]) { - uint32_t i; - unsigned char buffer[2 * SPX_N]; - - /* If leaf_idx is odd (last bit = 1), current path element is a right child - and auth_path has to go left. Otherwise it is the other way around. */ - if (leaf_idx & 1) { - memcpy(buffer + SPX_N, leaf, SPX_N); - memcpy(buffer, auth_path, SPX_N); - } else { - memcpy(buffer, leaf, SPX_N); - memcpy(buffer + SPX_N, auth_path, SPX_N); - } - auth_path += SPX_N; - - for (i = 0; i < tree_height - 1; i++) { - leaf_idx >>= 1; - idx_offset >>= 1; - /* Set the address of the node we're creating. */ - set_tree_height(addr, i + 1); - set_tree_index(addr, leaf_idx + idx_offset); - - /* Pick the right or left neighbor, depending on parity of the node. */ - if (leaf_idx & 1) { - thash(buffer + SPX_N, buffer, 2, ctx, addr); - memcpy(buffer, auth_path, SPX_N); - } else { - thash(buffer, buffer, 2, ctx, addr); - memcpy(buffer + SPX_N, auth_path, SPX_N); - } - auth_path += SPX_N; - } - - /* The last iteration is exceptional; we do not copy an auth_path node. */ - leaf_idx >>= 1; - idx_offset >>= 1; - set_tree_height(addr, tree_height); - set_tree_index(addr, leaf_idx + idx_offset); - thash(root, buffer, 2, ctx, addr); -} - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const spx_ctx * /* ctx */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), - uint32_t tree_addr[8]) { - PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); - PQCLEAN_VLA(unsigned int, heights, tree_height + 1); - unsigned int offset = 0; - uint32_t idx; - uint32_t tree_idx; - - for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { - /* Add the next leaf node to the stack. */ - gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); - offset++; - heights[offset - 1] = 0; - - /* If this is a node we need for the auth path.. */ - if ((leaf_idx ^ 0x1) == idx) { - memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); - } - - /* While the top-most nodes are of equal height.. */ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { - /* Compute index of the new node, in the next layer. */ - tree_idx = (idx >> (heights[offset - 1] + 1)); - - /* Set the address of the node we're creating. */ - set_tree_height(tree_addr, heights[offset - 1] + 1); - set_tree_index(tree_addr, - tree_idx + (idx_offset >> (heights[offset - 1] + 1))); - /* Hash the top-most nodes from the stack together. */ - thash(stack + (offset - 2)*SPX_N, - stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); - offset--; - /* Note that the top-most node is now one layer higher. */ - heights[offset - 1]++; - - /* If this is a node we need for the auth path.. */ - if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_path + heights[offset - 1]*SPX_N, - stack + (offset - 1)*SPX_N, SPX_N); - } - } - } - memcpy(root, stack, SPX_N); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/utils.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/utils.h deleted file mode 100644 index 64f5d5a53a..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/utils.h +++ /dev/null @@ -1,58 +0,0 @@ -#ifndef SPX_UTILS_H -#define SPX_UTILS_H - -#include - -#include "compat.h" -#include "context.h" -#include "params.h" - - -/* To support MSVC use alloca() instead of VLAs. See #20. */ - - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) -void ull_to_bytes(unsigned char *out, unsigned int outlen, - unsigned long long in); -#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) -void u32_to_bytes(unsigned char *out, uint32_t in); - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) -unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -#define compute_root SPX_NAMESPACE(compute_root) -void compute_root(unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const spx_ctx *ctx, uint32_t addr[8]); - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -#define treehash SPX_NAMESPACE(treehash) -void treehash(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const spx_ctx *ctx /* ctx */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), - uint32_t tree_addr[8]); - - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/utilsx4.c b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/utilsx4.c deleted file mode 100644 index 1638677194..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/utilsx4.c +++ /dev/null @@ -1,138 +0,0 @@ -#include - -#include "utilsx4.h" - -#include "address.h" -#include "params.h" -#include "thashx4.h" -#include "utils.h" - -/* - * Generate the entire Merkle tree, computing the authentication path for leaf_idx, - * and the resulting root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) - * - * This expects tree_addrx4 to be initialized to 4 parallel addr structures for - * the Merkle tree nodes - * - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - * - * This works by using the standard Merkle tree building algorithm, except - * that each 'node' tracked is actually 4 consecutive nodes in the real tree. - * When we combine two logical nodes ABCD and WXYZ, we perform the H - * operation on adjacent real nodes, forming the parent logical node - * (AB)(CD)(WX)(YZ) - * - * When we get to the top two levels of the real tree (where there is only - * one logical node), we continue this operation two more times; the right - * most real node will by the actual root (and the other 3 nodes will be - * garbage). We follow the same thashx4 logic so that the 'extract - * authentication path components' part of the loop is still executed (and - * to simplify the code somewhat) - * - * This currently assumes tree_height >= 2; I suspect that doing an adjusting - * idx, addr_idx on the gen_leafx4 call if tree_height < 2 would fix it; since - * we don't actually use such short trees, I haven't bothered - */ -void treehashx4(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, - uint32_t tree_height, - void (*gen_leafx4)( - unsigned char * /* Where to write the leaves */, - const spx_ctx *, - uint32_t idx, void *info), - uint32_t tree_addrx4[4 * 8], - void *info) { - /* This is where we keep the intermediate nodes */ - PQCLEAN_VLA(unsigned char, stackx4, tree_height * 4 * SPX_N); - uint32_t left_adj = 0, prev_left_adj = 0; /* When we're doing the top 3 */ - /* levels, the left-most part of the tree isn't at the beginning */ - /* of current[]. These give the offset of the actual start */ - - uint32_t idx; - uint32_t max_idx = (1U << (tree_height - 2)) - 1; - for (idx = 0;; idx++) { - unsigned char current[4 * SPX_N]; /* Current logical node */ - gen_leafx4( current, ctx, 4 * idx + idx_offset, - info ); - - /* Now combine the freshly generated right node with previously */ - /* generated left ones */ - uint32_t internal_idx_offset = idx_offset; - uint32_t internal_idx = idx; - uint32_t internal_leaf = leaf_idx; - uint32_t h; /* The height we are in the Merkle tree */ - for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { - - /* Special processing if we're at the top of the tree */ - if (h >= tree_height - 2) { - if (h == tree_height) { - /* We hit the root; return it */ - memcpy( root, ¤t[3 * SPX_N], SPX_N ); - return; - } - /* The tree indexing logic is a bit off in this case */ - /* Adjust it so that the left-most node of the part of */ - /* the tree that we're processing has index 0 */ - prev_left_adj = left_adj; - left_adj = 4U - (1 << (tree_height - h - 1)); - } - - /* Check if we hit the top of the tree */ - if (h == tree_height) { - /* We hit the root; return it */ - memcpy( root, ¤t[3 * SPX_N], SPX_N ); - return; - } - - /* - * Check if one of the nodes we have is a part of the - * authentication path; if it is, write it out - */ - if ((((internal_idx << 2) ^ internal_leaf) & ~0x3U) == 0) { - memcpy( &auth_path[ h * SPX_N ], - ¤t[(((internal_leaf & 3) ^ 1) + prev_left_adj) * SPX_N], - SPX_N ); - } - - /* - * Check if we're at a left child; if so, stop going up the stack - * Exception: if we've reached the end of the tree, keep on going - * (so we combine the last 4 nodes into the one root node in two - * more iterations) - */ - if ((internal_idx & 1) == 0 && idx < max_idx) { - break; - } - - /* Ok, we're at a right node (or doing the top 3 levels) */ - /* Now combine the left and right logical nodes together */ - - /* Set the address of the node we're creating. */ - unsigned int j; - internal_idx_offset >>= 1; - for (j = 0; j < 4; j++) { - set_tree_height(tree_addrx4 + j * 8, h + 1); - set_tree_index(tree_addrx4 + j * 8, - (4 / 2) * (internal_idx & ~1U) + j - left_adj + internal_idx_offset ); - } - unsigned char *left = &stackx4[h * 4 * SPX_N]; - thashx4( ¤t[0 * SPX_N], - ¤t[1 * SPX_N], - ¤t[2 * SPX_N], - ¤t[3 * SPX_N], - &left [0 * SPX_N], - &left [2 * SPX_N], - ¤t[0 * SPX_N], - ¤t[2 * SPX_N], - 2, ctx, tree_addrx4); - } - - /* We've hit a left child; save the current for when we get the */ - /* corresponding right right */ - memcpy( &stackx4[h * 4 * SPX_N], current, 4 * SPX_N); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/utilsx4.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/utilsx4.h deleted file mode 100644 index facb874b18..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/utilsx4.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef SPX_UTILSX4_H -#define SPX_UTILSX4_H - -#include - -#include "context.h" -#include "params.h" - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - * - * This implementation uses AVX to compute internal nodes 4 at a time (in - * parallel) - */ -#define treehashx4 SPX_NAMESPACE(treehashx4) -void treehashx4(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leafx4)( - unsigned char * /* Where to write the leaves */, - const spx_ctx * /* ctx */, - uint32_t addr_idx, void *info), - uint32_t tree_addrx4[4 * 8], void *info); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/wots.c b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/wots.c deleted file mode 100644 index 4d5041ce05..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/wots.c +++ /dev/null @@ -1,269 +0,0 @@ -#include -#include - -#include "wots.h" - -#include "address.h" -#include "hash.h" -#include "hashx4.h" -#include "params.h" -#include "thash.h" -#include "thashx4.h" -#include "utils.h" -#include "utilsx4.h" -#include "wotsx4.h" - -// TODO clarify address expectations, and make them more uniform. -// TODO i.e. do we expect types to be set already? -// TODO and do we expect modifications or copies? - -/** - * Computes up the chains - */ -static void gen_chains( - unsigned char *out, - const unsigned char *in, - unsigned int start[SPX_WOTS_LEN], - const unsigned int steps[SPX_WOTS_LEN], - const spx_ctx *ctx, - uint32_t addr[8]) { - uint32_t i, j, k, idx, watching; - int done; - unsigned char empty[SPX_N]; - unsigned char *bufs[4]; - uint32_t addrs[8 * 4]; - - int l; - uint16_t counts[SPX_WOTS_W] = { 0 }; - uint16_t idxs[SPX_WOTS_LEN]; - uint16_t total, newTotal; - - /* set addrs = {addr, addr, addr, addr} */ - for (j = 0; j < 4; j++) { - memcpy(addrs + j * 8, addr, sizeof(uint32_t) * 8); - } - - /* Initialize out with the value at position 'start'. */ - memcpy(out, in, SPX_WOTS_LEN * SPX_N); - - /* Sort the chains in reverse order by steps using counting sort. */ - for (i = 0; i < SPX_WOTS_LEN; i++) { - counts[steps[i]]++; - } - total = 0; - for (l = SPX_WOTS_W - 1; l >= 0; l--) { - newTotal = counts[l] + total; - counts[l] = total; - total = newTotal; - } - for (i = 0; i < SPX_WOTS_LEN; i++) { - idxs[counts[steps[i]]] = (uint16_t)i; - counts[steps[i]]++; - } - - /* We got our work cut out for us: do it! */ - for (i = 0; i < SPX_WOTS_LEN; i += 4) { - for (j = 0; j < 4 && i + j < SPX_WOTS_LEN; j++) { - idx = idxs[i + j]; - set_chain_addr(addrs + j * 8, idx); - bufs[j] = out + SPX_N * idx; - } - - /* As the chains are sorted in reverse order, we know that the first - * chain is the longest and the last one is the shortest. We keep - * an eye on whether the last chain is done and then on the one before, - * et cetera. */ - watching = 3; - done = 0; - while (i + watching >= SPX_WOTS_LEN) { - bufs[watching] = &empty[0]; - watching--; - } - - for (k = 0;; k++) { - while (k == steps[idxs[i + watching]]) { - bufs[watching] = &empty[0]; - if (watching == 0) { - done = 1; - break; - } - watching--; - } - if (done) { - break; - } - for (j = 0; j < watching + 1; j++) { - set_hash_addr(addrs + j * 8, k + start[idxs[i + j]]); - } - - thashx4(bufs[0], bufs[1], bufs[2], bufs[3], - bufs[0], bufs[1], bufs[2], bufs[3], 1, ctx, addrs); - } - } -} - -/** - * base_w algorithm as described in draft. - * Interprets an array of bytes as integers in base w. - * This only works when log_w is a divisor of 8. - */ -static void base_w(unsigned int *output, const int out_len, - const unsigned char *input) { - int in = 0; - int out = 0; - unsigned char total = 0; - int bits = 0; - int consumed; - - for (consumed = 0; consumed < out_len; consumed++) { - if (bits == 0) { - total = input[in]; - in++; - bits += 8; - } - bits -= SPX_WOTS_LOGW; - output[out] = (total >> bits) & (SPX_WOTS_W - 1); - out++; - } -} - -/* Computes the WOTS+ checksum over a message (in base_w). */ -static void wots_checksum(unsigned int *csum_base_w, - const unsigned int *msg_base_w) { - unsigned int csum = 0; - unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; - unsigned int i; - - /* Compute checksum. */ - for (i = 0; i < SPX_WOTS_LEN1; i++) { - csum += SPX_WOTS_W - 1 - msg_base_w[i]; - } - - /* Convert checksum to base_w. */ - /* Make sure expected empty zero bits are the least significant bits. */ - csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); - ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); - base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); -} - -/* Takes a message and derives the matching chain lengths. */ -void chain_lengths(unsigned int *lengths, const unsigned char *msg) { - base_w(lengths, SPX_WOTS_LEN1, msg); - wots_checksum(lengths + SPX_WOTS_LEN1, lengths); -} - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const spx_ctx *ctx, uint32_t addr[8]) { - unsigned int steps[SPX_WOTS_LEN]; - unsigned int start[SPX_WOTS_LEN]; - uint32_t i; - - chain_lengths(start, msg); - - for (i = 0; i < SPX_WOTS_LEN; i++) { - steps[i] = SPX_WOTS_W - 1 - start[i]; - } - - gen_chains(pk, sig, start, steps, ctx, addr); -} - -/* - * This generates 4 sequential WOTS public keys - * It also generates the WOTS signature if leaf_info indicates - * that we're signing with one of these WOTS keys - */ -void wots_gen_leafx4(unsigned char *dest, - const spx_ctx *ctx, - uint32_t leaf_idx, void *v_info) { - struct leaf_info_x4 *info = v_info; - uint32_t *leaf_addr = info->leaf_addr; - uint32_t *pk_addr = info->pk_addr; - unsigned int i, j, k; - unsigned char pk_buffer[ 4 * SPX_WOTS_BYTES ]; - unsigned wots_offset = SPX_WOTS_BYTES; - unsigned char *buffer; - uint32_t wots_k_mask; - unsigned wots_sign_index; - - if (((leaf_idx ^ info->wots_sign_leaf) & ~3U) == 0) { - /* We're traversing the leaf that's signing; generate the WOTS */ - /* signature */ - wots_k_mask = 0; - wots_sign_index = info->wots_sign_leaf & 3; /* Which of of the 4 */ - /* 4 slots do the signatures come from */ - } else { - /* Nope, we're just generating pk's; turn off the signature logic */ - wots_k_mask = (uint32_t)~0; - wots_sign_index = 0; - } - - for (j = 0; j < 4; j++) { - set_keypair_addr( leaf_addr + j * 8, leaf_idx + j ); - set_keypair_addr( pk_addr + j * 8, leaf_idx + j ); - } - - for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { - uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k to */ - /* the step if we're generating a signature, ~0 if we're not */ - - /* Start with the secret seed */ - for (j = 0; j < 4; j++) { - set_chain_addr(leaf_addr + j * 8, i); - set_hash_addr(leaf_addr + j * 8, 0); - set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTSPRF); - } - prf_addrx4(buffer + 0 * wots_offset, - buffer + 1 * wots_offset, - buffer + 2 * wots_offset, - buffer + 3 * wots_offset, - ctx, leaf_addr); - - for (j = 0; j < 4; j++) { - set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTS); - } - - /* Iterate down the WOTS chain */ - for (k = 0;; k++) { - /* Check if one of the values we have needs to be saved as a */ - /* part of the WOTS signature */ - if (k == wots_k) { - memcpy( info->wots_sig + i * SPX_N, - buffer + wots_sign_index * wots_offset, SPX_N ); - } - - /* Check if we hit the top of the chain */ - if (k == SPX_WOTS_W - 1) { - break; - } - - /* Iterate one step on all 4 chains */ - for (j = 0; j < 4; j++) { - set_hash_addr(leaf_addr + j * 8, k); - } - thashx4(buffer + 0 * wots_offset, - buffer + 1 * wots_offset, - buffer + 2 * wots_offset, - buffer + 3 * wots_offset, - buffer + 0 * wots_offset, - buffer + 1 * wots_offset, - buffer + 2 * wots_offset, - buffer + 3 * wots_offset, 1, ctx, leaf_addr); - } - } - - /* Do the final thash to generate the public keys */ - thashx4(dest + 0 * SPX_N, - dest + 1 * SPX_N, - dest + 2 * SPX_N, - dest + 3 * SPX_N, - pk_buffer + 0 * wots_offset, - pk_buffer + 1 * wots_offset, - pk_buffer + 2 * wots_offset, - pk_buffer + 3 * wots_offset, SPX_WOTS_LEN, ctx, pk_addr); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/wots.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/wots.h deleted file mode 100644 index 4e7692eeef..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/wots.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef SPX_WOTS_H -#define SPX_WOTS_H - -#include - -#include "context.h" -#include "params.h" - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) -void wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const spx_ctx *ctx, uint32_t addr[8]); - -/* - * Compute the chain lengths needed for a given message hash - */ -#define chain_lengths SPX_NAMESPACE(chain_lengths) -void chain_lengths(unsigned int *lengths, const unsigned char *msg); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/wotsx4.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/wotsx4.h deleted file mode 100644 index cd634f1743..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_aesni/wotsx4.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef WOTSX4_H_ -#define WOTSX4_H_ - -#include - -#include "params.h" - -/* - * This is here to provide an interface to the internal wots_gen_leafx4 - * routine. While this routine is not referenced in the package outside of - * wots.c, it is called from the stand-alone benchmark code to characterize - * the performance - */ -struct leaf_info_x4 { - unsigned char *wots_sig; - uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ - uint32_t *wots_steps; - uint32_t leaf_addr[4 * 8]; - uint32_t pk_addr[4 * 8]; -}; - -/* Macro to set the leaf_info to something 'benign', that is, it would */ -/* run with the same time as it does during the real signing process */ -/* Used only by the benchmark code */ -#define INITIALIZE_LEAF_INFO_X4(info, addr, step_buffer) { \ - (info).wots_sig = 0; \ - (info).wots_sign_leaf = ~0; \ - (info).wots_steps = step_buffer; \ - int i; \ - for (i=0; i<4; i++) { \ - memcpy( &(info).leaf_addr[8*i], addr, 32 ); \ - memcpy( &(info).pk_addr[8*i], addr, 32 ); \ - } \ - } - -#define wots_gen_leafx4 SPX_NAMESPACE(wots_gen_leafx4) -void wots_gen_leafx4(unsigned char *dest, - const spx_ctx *ctx, - uint32_t leaf_idx, void *v_info); - -#endif /* WOTSX4_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/LICENSE b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/LICENSE deleted file mode 100644 index 670154e353..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/LICENSE +++ /dev/null @@ -1,116 +0,0 @@ -CC0 1.0 Universal - -Statement of Purpose - -The laws of most jurisdictions throughout the world automatically confer -exclusive Copyright and Related Rights (defined below) upon the creator and -subsequent owner(s) (each and all, an "owner") of an original work of -authorship and/or a database (each, a "Work"). - -Certain owners wish to permanently relinquish those rights to a Work for the -purpose of contributing to a commons of creative, cultural and scientific -works ("Commons") that the public can reliably and without fear of later -claims of infringement build upon, modify, incorporate in other works, reuse -and redistribute as freely as possible in any form whatsoever and for any -purposes, including without limitation commercial purposes. These owners may -contribute to the Commons to promote the ideal of a free culture and the -further production of creative, cultural and scientific works, or to gain -reputation or greater distribution for their Work in part through the use and -efforts of others. - -For these and/or other purposes and motivations, and without any expectation -of additional consideration or compensation, the person associating CC0 with a -Work (the "Affirmer"), to the extent that he or she is an owner of Copyright -and Related Rights in the Work, voluntarily elects to apply CC0 to the Work -and publicly distribute the Work under its terms, with knowledge of his or her -Copyright and Related Rights in the Work and the meaning and intended legal -effect of CC0 on those rights. - -1. Copyright and Related Rights. A Work made available under CC0 may be -protected by copyright and related or neighboring rights ("Copyright and -Related Rights"). Copyright and Related Rights include, but are not limited -to, the following: - - i. the right to reproduce, adapt, distribute, perform, display, communicate, - and translate a Work; - - ii. moral rights retained by the original author(s) and/or performer(s); - - iii. publicity and privacy rights pertaining to a person's image or likeness - depicted in a Work; - - iv. rights protecting against unfair competition in regards to a Work, - subject to the limitations in paragraph 4(a), below; - - v. rights protecting the extraction, dissemination, use and reuse of data in - a Work; - - vi. database rights (such as those arising under Directive 96/9/EC of the - European Parliament and of the Council of 11 March 1996 on the legal - protection of databases, and under any national implementation thereof, - including any amended or successor version of such directive); and - - vii. other similar, equivalent or corresponding rights throughout the world - based on applicable law or treaty, and any national implementations thereof. - -2. Waiver. To the greatest extent permitted by, but not in contravention of, -applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and -unconditionally waives, abandons, and surrenders all of Affirmer's Copyright -and Related Rights and associated claims and causes of action, whether now -known or unknown (including existing as well as future claims and causes of -action), in the Work (i) in all territories worldwide, (ii) for the maximum -duration provided by applicable law or treaty (including future time -extensions), (iii) in any current or future medium and for any number of -copies, and (iv) for any purpose whatsoever, including without limitation -commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes -the Waiver for the benefit of each member of the public at large and to the -detriment of Affirmer's heirs and successors, fully intending that such Waiver -shall not be subject to revocation, rescission, cancellation, termination, or -any other legal or equitable action to disrupt the quiet enjoyment of the Work -by the public as contemplated by Affirmer's express Statement of Purpose. - -3. Public License Fallback. Should any part of the Waiver for any reason be -judged legally invalid or ineffective under applicable law, then the Waiver -shall be preserved to the maximum extent permitted taking into account -Affirmer's express Statement of Purpose. In addition, to the extent the Waiver -is so judged Affirmer hereby grants to each affected person a royalty-free, -non transferable, non sublicensable, non exclusive, irrevocable and -unconditional license to exercise Affirmer's Copyright and Related Rights in -the Work (i) in all territories worldwide, (ii) for the maximum duration -provided by applicable law or treaty (including future time extensions), (iii) -in any current or future medium and for any number of copies, and (iv) for any -purpose whatsoever, including without limitation commercial, advertising or -promotional purposes (the "License"). The License shall be deemed effective as -of the date CC0 was applied by Affirmer to the Work. Should any part of the -License for any reason be judged legally invalid or ineffective under -applicable law, such partial invalidity or ineffectiveness shall not -invalidate the remainder of the License, and in such case Affirmer hereby -affirms that he or she will not (i) exercise any of his or her remaining -Copyright and Related Rights in the Work or (ii) assert any associated claims -and causes of action with respect to the Work, in either case contrary to -Affirmer's express Statement of Purpose. - -4. Limitations and Disclaimers. - - a. No trademark or patent rights held by Affirmer are waived, abandoned, - surrendered, licensed or otherwise affected by this document. - - b. Affirmer offers the Work as-is and makes no representations or warranties - of any kind concerning the Work, express, implied, statutory or otherwise, - including without limitation warranties of title, merchantability, fitness - for a particular purpose, non infringement, or the absence of latent or - other defects, accuracy, or the present or absence of errors, whether or not - discoverable, all to the greatest extent permissible under applicable law. - - c. Affirmer disclaims responsibility for clearing rights of other persons - that may apply to the Work or any use thereof, including without limitation - any person's Copyright and Related Rights in the Work. Further, Affirmer - disclaims responsibility for obtaining any necessary consents, permissions - or other rights required for any use of the Work. - - d. Affirmer understands and acknowledges that Creative Commons is not a - party to this document and has no duty or obligation with respect to this - CC0 or use of the Work. - -For more information, please see - diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/address.c b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/address.c deleted file mode 100644 index d49d9f3b6b..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/address.c +++ /dev/null @@ -1,95 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "utils.h" - -/* - * Specify which level of Merkle tree (the "layer") we're working on - */ -void set_layer_addr(uint32_t addr[8], uint32_t layer) { - ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; -} - -/* - * Specify which Merkle tree within the level (the "tree address") we're working on - */ -void set_tree_addr(uint32_t addr[8], uint64_t tree) { - ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); -} - -/* - * Specify the reason we'll use this address structure for, that is, what - * hash will we compute with it. This is used so that unrelated types of - * hashes don't accidentally get the same address structure. The type will be - * one of the SPX_ADDR_TYPE constants - */ -void set_type(uint32_t addr[8], uint32_t type) { - ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; -} - -/* - * Copy the layer and tree fields of the address structure. This is used - * when we're doing multiple types of hashes within the same Merkle tree - */ -void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { - memcpy( out, in, SPX_OFFSET_TREE + 8 ); -} - -/* These functions are used for OTS addresses. */ - -/* - * Specify which Merkle leaf we're working on; that is, which OTS keypair - * we're talking about. - */ -void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { - /* We have > 256 OTS at the bottom of the Merkle tree; to specify */ - /* which one, we'd need to express it in two bytes */ - ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR2] = (unsigned char)(keypair >> 8); - ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; -} - -/* - * Copy the layer, tree and keypair fields of the address structure. This is - * used when we're doing multiple things within the same OTS keypair - */ -void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { - memcpy( out, in, SPX_OFFSET_TREE + 8 ); - ((unsigned char *)out)[SPX_OFFSET_KP_ADDR2] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR2]; - ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; -} - -/* - * Specify which Merkle chain within the OTS we're working with - * (the chain address) - */ -void set_chain_addr(uint32_t addr[8], uint32_t chain) { - ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; -} - -/* - * Specify where in the Merkle chain we are -* (the hash address) - */ -void set_hash_addr(uint32_t addr[8], uint32_t hash) { - ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; -} - -/* These functions are used for all hash tree addresses (including FORS). */ - -/* - * Specify the height of the node in the Merkle/FORS tree we are in - * (the tree height) - */ -void set_tree_height(uint32_t addr[8], uint32_t tree_height) { - ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; -} - -/* - * Specify the distance from the left edge of the node in the Merkle/FORS tree - * (the tree index) - */ -void set_tree_index(uint32_t addr[8], uint32_t tree_index) { - u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/address.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/address.h deleted file mode 100644 index 24a84eb40c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/address.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef SPX_ADDRESS_H -#define SPX_ADDRESS_H - -#include - -#include "params.h" - -/* The hash types that are passed to set_type */ -#define SPX_ADDR_TYPE_WOTS 0 -#define SPX_ADDR_TYPE_WOTSPK 1 -#define SPX_ADDR_TYPE_HASHTREE 2 -#define SPX_ADDR_TYPE_FORSTREE 3 -#define SPX_ADDR_TYPE_FORSPK 4 -#define SPX_ADDR_TYPE_WOTSPRF 5 -#define SPX_ADDR_TYPE_FORSPRF 6 - -#define set_layer_addr SPX_NAMESPACE(set_layer_addr) -void set_layer_addr(uint32_t addr[8], uint32_t layer); - -#define set_tree_addr SPX_NAMESPACE(set_tree_addr) -void set_tree_addr(uint32_t addr[8], uint64_t tree); - -#define set_type SPX_NAMESPACE(set_type) -void set_type(uint32_t addr[8], uint32_t type); - -/* Copies the layer and tree part of one address into the other */ -#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) -void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for WOTS and FORS addresses. */ - -#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) -void set_keypair_addr(uint32_t addr[8], uint32_t keypair); - -#define set_chain_addr SPX_NAMESPACE(set_chain_addr) -void set_chain_addr(uint32_t addr[8], uint32_t chain); - -#define set_hash_addr SPX_NAMESPACE(set_hash_addr) -void set_hash_addr(uint32_t addr[8], uint32_t hash); - -#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) -void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for all hash tree addresses (including FORS). */ - -#define set_tree_height SPX_NAMESPACE(set_tree_height) -void set_tree_height(uint32_t addr[8], uint32_t tree_height); - -#define set_tree_index SPX_NAMESPACE(set_tree_index) -void set_tree_index(uint32_t addr[8], uint32_t tree_index); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/api.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/api.h deleted file mode 100644 index 0942113fbd..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/api.h +++ /dev/null @@ -1,77 +0,0 @@ -#ifndef PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_API_H -#define PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_API_H - -#include -#include - -#define PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_CRYPTO_ALGNAME "SPHINCS+-haraka-128s-simple" - -#define PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_CRYPTO_SECRETKEYBYTES 64 -#define PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_CRYPTO_PUBLICKEYBYTES 32 -#define PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_CRYPTO_BYTES 7856 - -#define PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_CRYPTO_SEEDBYTES 48 - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, - const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk); -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/context.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/context.h deleted file mode 100644 index 600dfb73c7..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/context.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef SPX_CONTEXT_H -#define SPX_CONTEXT_H - -#include -#include - -#include "params.h" - -typedef struct { - uint8_t pub_seed[SPX_N]; - uint8_t sk_seed[SPX_N]; - - - uint64_t tweaked512_rc64[10][8]; - uint32_t tweaked256_rc32[10][8]; -} spx_ctx; - -#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) -void initialize_hash_function(spx_ctx *ctx); - -#define free_hash_function SPX_NAMESPACE(free_hash_function) -void free_hash_function(spx_ctx *ctx); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/context_haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/context_haraka.c deleted file mode 100644 index f1cd7e3664..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/context_haraka.c +++ /dev/null @@ -1,11 +0,0 @@ -#include "context.h" -#include "haraka.h" - -void initialize_hash_function(spx_ctx *ctx) { - tweak_constants(ctx); -} - -// we don't support heap-based haraka right now -void free_hash_function(spx_ctx *ctx) { - (void)ctx; // suppress unused variable warnings -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/fors.c b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/fors.c deleted file mode 100644 index 96ca72e986..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/fors.c +++ /dev/null @@ -1,156 +0,0 @@ -#include -#include -#include - -#include "fors.h" - -#include "address.h" -#include "hash.h" -#include "thash.h" -#include "utils.h" -#include "utilsx1.h" - -static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, - uint32_t fors_leaf_addr[8]) { - prf_addr(sk, ctx, fors_leaf_addr); -} - -static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, - const spx_ctx *ctx, - uint32_t fors_leaf_addr[8]) { - thash(leaf, sk, 1, ctx, fors_leaf_addr); -} - -struct fors_gen_leaf_info { - uint32_t leaf_addrx[8]; -}; - -static void fors_gen_leafx1(unsigned char *leaf, - const spx_ctx *ctx, - uint32_t addr_idx, void *info) { - struct fors_gen_leaf_info *fors_info = info; - uint32_t *fors_leaf_addr = fors_info->leaf_addrx; - - /* Only set the parts that the caller doesn't set */ - set_tree_index(fors_leaf_addr, addr_idx); - set_type(fors_leaf_addr, SPX_ADDR_TYPE_FORSPRF); - fors_gen_sk(leaf, ctx, fors_leaf_addr); - - set_type(fors_leaf_addr, SPX_ADDR_TYPE_FORSTREE); - fors_sk_to_leaf(leaf, leaf, - ctx, fors_leaf_addr); -} - -/** - * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - * Assumes indices has space for SPX_FORS_TREES integers. - */ -static void message_to_indices(uint32_t *indices, const unsigned char *m) { - unsigned int i, j; - unsigned int offset = 0; - - for (i = 0; i < SPX_FORS_TREES; i++) { - indices[i] = 0; - for (j = 0; j < SPX_FORS_HEIGHT; j++) { - indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); - offset++; - } - } -} - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -void fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]) { - uint32_t indices[SPX_FORS_TREES]; - unsigned char roots[SPX_FORS_TREES * SPX_N]; - uint32_t fors_tree_addr[8] = {0}; - struct fors_gen_leaf_info fors_info = {0}; - uint32_t *fors_leaf_addr = fors_info.leaf_addrx; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - copy_keypair_addr(fors_tree_addr, fors_addr); - copy_keypair_addr(fors_leaf_addr, fors_addr); - - copy_keypair_addr(fors_pk_addr, fors_addr); - set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < SPX_FORS_TREES; i++) { - idx_offset = i * (1 << SPX_FORS_HEIGHT); - - set_tree_height(fors_tree_addr, 0); - set_tree_index(fors_tree_addr, indices[i] + idx_offset); - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); - - /* Include the secret key part that produces the selected leaf node. */ - fors_gen_sk(sig, ctx, fors_tree_addr); - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); - sig += SPX_N; - - /* Compute the authentication path for this leaf node. */ - treehashx1(roots + i * SPX_N, sig, ctx, - indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx1, - fors_tree_addr, &fors_info); - - sig += SPX_N * SPX_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); -} - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -void fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]) { - uint32_t indices[SPX_FORS_TREES]; - unsigned char roots[SPX_FORS_TREES * SPX_N]; - unsigned char leaf[SPX_N]; - uint32_t fors_tree_addr[8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - copy_keypair_addr(fors_tree_addr, fors_addr); - copy_keypair_addr(fors_pk_addr, fors_addr); - - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); - set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < SPX_FORS_TREES; i++) { - idx_offset = i * (1 << SPX_FORS_HEIGHT); - - set_tree_height(fors_tree_addr, 0); - set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Derive the leaf from the included secret key part. */ - fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); - sig += SPX_N; - - /* Derive the corresponding root node of this tree. */ - compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, - sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); - sig += SPX_N * SPX_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/fors.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/fors.h deleted file mode 100644 index 509140a178..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/fors.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef SPX_FORS_H -#define SPX_FORS_H - -#include - -#include "context.h" -#include "params.h" - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -#define fors_sign SPX_NAMESPACE(fors_sign) -void fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]); - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) -void fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/haraka.c deleted file mode 100644 index a4944913b5..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/haraka.c +++ /dev/null @@ -1,913 +0,0 @@ -/* - * Constant time implementation of the Haraka hash function. - * - * The bit-sliced implementation of the AES round functions are - * based on the AES implementation in BearSSL written - * by Thomas Pornin - */ - -#include -#include -#include -#include - -#include "haraka.h" -#include "utils.h" - -#define HARAKAS_RATE 32 - -static const uint64_t haraka512_rc64[10][8] = { - {0x24cf0ab9086f628b, 0xbdd6eeecc83b8382, 0xd96fb0306cdad0a7, 0xaace082ac8f95f89, 0x449d8e8870d7041f, 0x49bb2f80b2b3e2f8, 0x0569ae98d93bb258, 0x23dc9691e7d6a4b1}, - {0xd8ba10ede0fe5b6e, 0x7ecf7dbe424c7b8e, 0x6ea9949c6df62a31, 0xbf3f3c97ec9c313e, 0x241d03a196a1861e, 0xead3a51116e5a2ea, 0x77d479fcad9574e3, 0x18657a1af894b7a0}, - {0x10671e1a7f595522, 0xd9a00ff675d28c7b, 0x2f1edf0d2b9ba661, 0xb8ff58b8e3de45f9, 0xee29261da9865c02, 0xd1532aa4b50bdf43, 0x8bf858159b231bb1, 0xdf17439d22d4f599}, - {0xdd4b2f0870b918c0, 0x757a81f3b39b1bb6, 0x7a5c556898952e3f, 0x7dd70a16d915d87a, 0x3ae61971982b8301, 0xc3ab319e030412be, 0x17c0033ac094a8cb, 0x5a0630fc1a8dc4ef}, - {0x17708988c1632f73, 0xf92ddae090b44f4f, 0x11ac0285c43aa314, 0x509059941936b8ba, 0xd03e152fa2ce9b69, 0x3fbcbcb63a32998b, 0x6204696d692254f7, 0x915542ed93ec59b4}, - {0xf4ed94aa8879236e, 0xff6cb41cd38e03c0, 0x069b38602368aeab, 0x669495b820f0ddba, 0xf42013b1b8bf9e3d, 0xcf935efe6439734d, 0xbc1dcf42ca29e3f8, 0x7e6d3ed29f78ad67}, - {0xf3b0f6837ffcddaa, 0x3a76faef934ddf41, 0xcec7ae583a9c8e35, 0xe4dd18c68f0260af, 0x2c0e5df1ad398eaa, 0x478df5236ae22e8c, 0xfb944c46fe865f39, 0xaa48f82f028132ba}, - {0x231b9ae2b76aca77, 0x292a76a712db0b40, 0x5850625dc8134491, 0x73137dd469810fb5, 0x8a12a6a202a474fd, 0xd36fd9daa78bdb80, 0xb34c5e733505706f, 0xbaf1cdca818d9d96}, - {0x2e99781335e8c641, 0xbddfe5cce47d560e, 0xf74e9bf32e5e040c, 0x1d7a709d65996be9, 0x670df36a9cf66cdd, 0xd05ef84a176a2875, 0x0f888e828cb1c44e, 0x1a79e9c9727b052c}, - {0x83497348628d84de, 0x2e9387d51f22a754, 0xb000068da2f852d6, 0x378c9e1190fd6fe5, 0x870027c316de7293, 0xe51a9d4462e047bb, 0x90ecf7f8c6251195, 0x655953bfbed90a9c}, -}; - -static inline uint32_t br_dec32le(const unsigned char *src) { - return (uint32_t)src[0] - | ((uint32_t)src[1] << 8) - | ((uint32_t)src[2] << 16) - | ((uint32_t)src[3] << 24); -} - -static void br_range_dec32le(uint32_t *v, size_t num, const unsigned char *src) { - while (num-- > 0) { - *v ++ = br_dec32le(src); - src += 4; - } -} - -static inline void br_enc32le(unsigned char *dst, uint32_t x) { - dst[0] = (unsigned char)x; - dst[1] = (unsigned char)(x >> 8); - dst[2] = (unsigned char)(x >> 16); - dst[3] = (unsigned char)(x >> 24); -} - - -static void br_range_enc32le(unsigned char *dst, const uint32_t *v, size_t num) { - while (num-- > 0) { - br_enc32le(dst, *v ++); - dst += 4; - } -} - -static void br_aes_ct64_bitslice_Sbox(uint64_t *q) { - /* - * This S-box implementation is a straightforward translation of - * the circuit described by Boyar and Peralta in "A new - * combinational logic minimization technique with applications - * to cryptology" (https://eprint.iacr.org/2009/191.pdf). - * - * Note that variables x* (input) and s* (output) are numbered - * in "reverse" order (x0 is the high bit, x7 is the low bit). - */ - - uint64_t x0, x1, x2, x3, x4, x5, x6, x7; - uint64_t y1, y2, y3, y4, y5, y6, y7, y8, y9; - uint64_t y10, y11, y12, y13, y14, y15, y16, y17, y18, y19; - uint64_t y20, y21; - uint64_t z0, z1, z2, z3, z4, z5, z6, z7, z8, z9; - uint64_t z10, z11, z12, z13, z14, z15, z16, z17; - uint64_t t0, t1, t2, t3, t4, t5, t6, t7, t8, t9; - uint64_t t10, t11, t12, t13, t14, t15, t16, t17, t18, t19; - uint64_t t20, t21, t22, t23, t24, t25, t26, t27, t28, t29; - uint64_t t30, t31, t32, t33, t34, t35, t36, t37, t38, t39; - uint64_t t40, t41, t42, t43, t44, t45, t46, t47, t48, t49; - uint64_t t50, t51, t52, t53, t54, t55, t56, t57, t58, t59; - uint64_t t60, t61, t62, t63, t64, t65, t66, t67; - uint64_t s0, s1, s2, s3, s4, s5, s6, s7; - - x0 = q[7]; - x1 = q[6]; - x2 = q[5]; - x3 = q[4]; - x4 = q[3]; - x5 = q[2]; - x6 = q[1]; - x7 = q[0]; - - /* - * Top linear transformation. - */ - y14 = x3 ^ x5; - y13 = x0 ^ x6; - y9 = x0 ^ x3; - y8 = x0 ^ x5; - t0 = x1 ^ x2; - y1 = t0 ^ x7; - y4 = y1 ^ x3; - y12 = y13 ^ y14; - y2 = y1 ^ x0; - y5 = y1 ^ x6; - y3 = y5 ^ y8; - t1 = x4 ^ y12; - y15 = t1 ^ x5; - y20 = t1 ^ x1; - y6 = y15 ^ x7; - y10 = y15 ^ t0; - y11 = y20 ^ y9; - y7 = x7 ^ y11; - y17 = y10 ^ y11; - y19 = y10 ^ y8; - y16 = t0 ^ y11; - y21 = y13 ^ y16; - y18 = x0 ^ y16; - - /* - * Non-linear section. - */ - t2 = y12 & y15; - t3 = y3 & y6; - t4 = t3 ^ t2; - t5 = y4 & x7; - t6 = t5 ^ t2; - t7 = y13 & y16; - t8 = y5 & y1; - t9 = t8 ^ t7; - t10 = y2 & y7; - t11 = t10 ^ t7; - t12 = y9 & y11; - t13 = y14 & y17; - t14 = t13 ^ t12; - t15 = y8 & y10; - t16 = t15 ^ t12; - t17 = t4 ^ t14; - t18 = t6 ^ t16; - t19 = t9 ^ t14; - t20 = t11 ^ t16; - t21 = t17 ^ y20; - t22 = t18 ^ y19; - t23 = t19 ^ y21; - t24 = t20 ^ y18; - - t25 = t21 ^ t22; - t26 = t21 & t23; - t27 = t24 ^ t26; - t28 = t25 & t27; - t29 = t28 ^ t22; - t30 = t23 ^ t24; - t31 = t22 ^ t26; - t32 = t31 & t30; - t33 = t32 ^ t24; - t34 = t23 ^ t33; - t35 = t27 ^ t33; - t36 = t24 & t35; - t37 = t36 ^ t34; - t38 = t27 ^ t36; - t39 = t29 & t38; - t40 = t25 ^ t39; - - t41 = t40 ^ t37; - t42 = t29 ^ t33; - t43 = t29 ^ t40; - t44 = t33 ^ t37; - t45 = t42 ^ t41; - z0 = t44 & y15; - z1 = t37 & y6; - z2 = t33 & x7; - z3 = t43 & y16; - z4 = t40 & y1; - z5 = t29 & y7; - z6 = t42 & y11; - z7 = t45 & y17; - z8 = t41 & y10; - z9 = t44 & y12; - z10 = t37 & y3; - z11 = t33 & y4; - z12 = t43 & y13; - z13 = t40 & y5; - z14 = t29 & y2; - z15 = t42 & y9; - z16 = t45 & y14; - z17 = t41 & y8; - - /* - * Bottom linear transformation. - */ - t46 = z15 ^ z16; - t47 = z10 ^ z11; - t48 = z5 ^ z13; - t49 = z9 ^ z10; - t50 = z2 ^ z12; - t51 = z2 ^ z5; - t52 = z7 ^ z8; - t53 = z0 ^ z3; - t54 = z6 ^ z7; - t55 = z16 ^ z17; - t56 = z12 ^ t48; - t57 = t50 ^ t53; - t58 = z4 ^ t46; - t59 = z3 ^ t54; - t60 = t46 ^ t57; - t61 = z14 ^ t57; - t62 = t52 ^ t58; - t63 = t49 ^ t58; - t64 = z4 ^ t59; - t65 = t61 ^ t62; - t66 = z1 ^ t63; - s0 = t59 ^ t63; - s6 = t56 ^ ~t62; - s7 = t48 ^ ~t60; - t67 = t64 ^ t65; - s3 = t53 ^ t66; - s4 = t51 ^ t66; - s5 = t47 ^ t65; - s1 = t64 ^ ~s3; - s2 = t55 ^ ~t67; - - q[7] = s0; - q[6] = s1; - q[5] = s2; - q[4] = s3; - q[3] = s4; - q[2] = s5; - q[1] = s6; - q[0] = s7; -} - -static void br_aes_ct_bitslice_Sbox(uint32_t *q) { - /* - * This S-box implementation is a straightforward translation of - * the circuit described by Boyar and Peralta in "A new - * combinational logic minimization technique with applications - * to cryptology" (https://eprint.iacr.org/2009/191.pdf). - * - * Note that variables x* (input) and s* (output) are numbered - * in "reverse" order (x0 is the high bit, x7 is the low bit). - */ - - uint32_t x0, x1, x2, x3, x4, x5, x6, x7; - uint32_t y1, y2, y3, y4, y5, y6, y7, y8, y9; - uint32_t y10, y11, y12, y13, y14, y15, y16, y17, y18, y19; - uint32_t y20, y21; - uint32_t z0, z1, z2, z3, z4, z5, z6, z7, z8, z9; - uint32_t z10, z11, z12, z13, z14, z15, z16, z17; - uint32_t t0, t1, t2, t3, t4, t5, t6, t7, t8, t9; - uint32_t t10, t11, t12, t13, t14, t15, t16, t17, t18, t19; - uint32_t t20, t21, t22, t23, t24, t25, t26, t27, t28, t29; - uint32_t t30, t31, t32, t33, t34, t35, t36, t37, t38, t39; - uint32_t t40, t41, t42, t43, t44, t45, t46, t47, t48, t49; - uint32_t t50, t51, t52, t53, t54, t55, t56, t57, t58, t59; - uint32_t t60, t61, t62, t63, t64, t65, t66, t67; - uint32_t s0, s1, s2, s3, s4, s5, s6, s7; - - x0 = q[7]; - x1 = q[6]; - x2 = q[5]; - x3 = q[4]; - x4 = q[3]; - x5 = q[2]; - x6 = q[1]; - x7 = q[0]; - - /* - * Top linear transformation. - */ - y14 = x3 ^ x5; - y13 = x0 ^ x6; - y9 = x0 ^ x3; - y8 = x0 ^ x5; - t0 = x1 ^ x2; - y1 = t0 ^ x7; - y4 = y1 ^ x3; - y12 = y13 ^ y14; - y2 = y1 ^ x0; - y5 = y1 ^ x6; - y3 = y5 ^ y8; - t1 = x4 ^ y12; - y15 = t1 ^ x5; - y20 = t1 ^ x1; - y6 = y15 ^ x7; - y10 = y15 ^ t0; - y11 = y20 ^ y9; - y7 = x7 ^ y11; - y17 = y10 ^ y11; - y19 = y10 ^ y8; - y16 = t0 ^ y11; - y21 = y13 ^ y16; - y18 = x0 ^ y16; - - /* - * Non-linear section. - */ - t2 = y12 & y15; - t3 = y3 & y6; - t4 = t3 ^ t2; - t5 = y4 & x7; - t6 = t5 ^ t2; - t7 = y13 & y16; - t8 = y5 & y1; - t9 = t8 ^ t7; - t10 = y2 & y7; - t11 = t10 ^ t7; - t12 = y9 & y11; - t13 = y14 & y17; - t14 = t13 ^ t12; - t15 = y8 & y10; - t16 = t15 ^ t12; - t17 = t4 ^ t14; - t18 = t6 ^ t16; - t19 = t9 ^ t14; - t20 = t11 ^ t16; - t21 = t17 ^ y20; - t22 = t18 ^ y19; - t23 = t19 ^ y21; - t24 = t20 ^ y18; - - t25 = t21 ^ t22; - t26 = t21 & t23; - t27 = t24 ^ t26; - t28 = t25 & t27; - t29 = t28 ^ t22; - t30 = t23 ^ t24; - t31 = t22 ^ t26; - t32 = t31 & t30; - t33 = t32 ^ t24; - t34 = t23 ^ t33; - t35 = t27 ^ t33; - t36 = t24 & t35; - t37 = t36 ^ t34; - t38 = t27 ^ t36; - t39 = t29 & t38; - t40 = t25 ^ t39; - - t41 = t40 ^ t37; - t42 = t29 ^ t33; - t43 = t29 ^ t40; - t44 = t33 ^ t37; - t45 = t42 ^ t41; - z0 = t44 & y15; - z1 = t37 & y6; - z2 = t33 & x7; - z3 = t43 & y16; - z4 = t40 & y1; - z5 = t29 & y7; - z6 = t42 & y11; - z7 = t45 & y17; - z8 = t41 & y10; - z9 = t44 & y12; - z10 = t37 & y3; - z11 = t33 & y4; - z12 = t43 & y13; - z13 = t40 & y5; - z14 = t29 & y2; - z15 = t42 & y9; - z16 = t45 & y14; - z17 = t41 & y8; - - /* - * Bottom linear transformation. - */ - t46 = z15 ^ z16; - t47 = z10 ^ z11; - t48 = z5 ^ z13; - t49 = z9 ^ z10; - t50 = z2 ^ z12; - t51 = z2 ^ z5; - t52 = z7 ^ z8; - t53 = z0 ^ z3; - t54 = z6 ^ z7; - t55 = z16 ^ z17; - t56 = z12 ^ t48; - t57 = t50 ^ t53; - t58 = z4 ^ t46; - t59 = z3 ^ t54; - t60 = t46 ^ t57; - t61 = z14 ^ t57; - t62 = t52 ^ t58; - t63 = t49 ^ t58; - t64 = z4 ^ t59; - t65 = t61 ^ t62; - t66 = z1 ^ t63; - s0 = t59 ^ t63; - s6 = t56 ^ ~t62; - s7 = t48 ^ ~t60; - t67 = t64 ^ t65; - s3 = t53 ^ t66; - s4 = t51 ^ t66; - s5 = t47 ^ t65; - s1 = t64 ^ ~s3; - s2 = t55 ^ ~t67; - - q[7] = s0; - q[6] = s1; - q[5] = s2; - q[4] = s3; - q[3] = s4; - q[2] = s5; - q[1] = s6; - q[0] = s7; -} - -static void br_aes_ct_ortho(uint32_t *q) { -#define SWAPN_32(cl, ch, s, x, y) do { \ - uint32_t a, b; \ - a = (x); \ - b = (y); \ - (x) = (a & (uint32_t)(cl)) | ((b & (uint32_t)(cl)) << (s)); \ - (y) = ((a & (uint32_t)(ch)) >> (s)) | (b & (uint32_t)(ch)); \ - } while (0) - -#define SWAP2_32(x, y) SWAPN_32(0x55555555, 0xAAAAAAAA, 1, x, y) -#define SWAP4_32(x, y) SWAPN_32(0x33333333, 0xCCCCCCCC, 2, x, y) -#define SWAP8_32(x, y) SWAPN_32(0x0F0F0F0F, 0xF0F0F0F0, 4, x, y) - - SWAP2_32(q[0], q[1]); - SWAP2_32(q[2], q[3]); - SWAP2_32(q[4], q[5]); - SWAP2_32(q[6], q[7]); - - SWAP4_32(q[0], q[2]); - SWAP4_32(q[1], q[3]); - SWAP4_32(q[4], q[6]); - SWAP4_32(q[5], q[7]); - - SWAP8_32(q[0], q[4]); - SWAP8_32(q[1], q[5]); - SWAP8_32(q[2], q[6]); - SWAP8_32(q[3], q[7]); -} - -static inline void add_round_key32(uint32_t *q, const uint32_t *sk) { - q[0] ^= sk[0]; - q[1] ^= sk[1]; - q[2] ^= sk[2]; - q[3] ^= sk[3]; - q[4] ^= sk[4]; - q[5] ^= sk[5]; - q[6] ^= sk[6]; - q[7] ^= sk[7]; -} - -static inline void shift_rows32(uint32_t *q) { - int i; - - for (i = 0; i < 8; i++) { - uint32_t x; - - x = q[i]; - q[i] = (x & 0x000000FF) - | ((x & 0x0000FC00) >> 2) | ((x & 0x00000300) << 6) - | ((x & 0x00F00000) >> 4) | ((x & 0x000F0000) << 4) - | ((x & 0xC0000000) >> 6) | ((x & 0x3F000000) << 2); - } -} - -static inline uint32_t rotr16(uint32_t x) { - return (x << 16) | (x >> 16); -} - -static inline void mix_columns32(uint32_t *q) { - uint32_t q0, q1, q2, q3, q4, q5, q6, q7; - uint32_t r0, r1, r2, r3, r4, r5, r6, r7; - - q0 = q[0]; - q1 = q[1]; - q2 = q[2]; - q3 = q[3]; - q4 = q[4]; - q5 = q[5]; - q6 = q[6]; - q7 = q[7]; - r0 = (q0 >> 8) | (q0 << 24); - r1 = (q1 >> 8) | (q1 << 24); - r2 = (q2 >> 8) | (q2 << 24); - r3 = (q3 >> 8) | (q3 << 24); - r4 = (q4 >> 8) | (q4 << 24); - r5 = (q5 >> 8) | (q5 << 24); - r6 = (q6 >> 8) | (q6 << 24); - r7 = (q7 >> 8) | (q7 << 24); - - q[0] = q7 ^ r7 ^ r0 ^ rotr16(q0 ^ r0); - q[1] = q0 ^ r0 ^ q7 ^ r7 ^ r1 ^ rotr16(q1 ^ r1); - q[2] = q1 ^ r1 ^ r2 ^ rotr16(q2 ^ r2); - q[3] = q2 ^ r2 ^ q7 ^ r7 ^ r3 ^ rotr16(q3 ^ r3); - q[4] = q3 ^ r3 ^ q7 ^ r7 ^ r4 ^ rotr16(q4 ^ r4); - q[5] = q4 ^ r4 ^ r5 ^ rotr16(q5 ^ r5); - q[6] = q5 ^ r5 ^ r6 ^ rotr16(q6 ^ r6); - q[7] = q6 ^ r6 ^ r7 ^ rotr16(q7 ^ r7); -} - -static void br_aes_ct64_ortho(uint64_t *q) { -#define SWAPN(cl, ch, s, x, y) do { \ - uint64_t a, b; \ - a = (x); \ - b = (y); \ - (x) = (a & (uint64_t)(cl)) | ((b & (uint64_t)(cl)) << (s)); \ - (y) = ((a & (uint64_t)(ch)) >> (s)) | (b & (uint64_t)(ch)); \ - } while (0) - -#define SWAP2(x, y) SWAPN(0x5555555555555555, 0xAAAAAAAAAAAAAAAA, 1, x, y) -#define SWAP4(x, y) SWAPN(0x3333333333333333, 0xCCCCCCCCCCCCCCCC, 2, x, y) -#define SWAP8(x, y) SWAPN(0x0F0F0F0F0F0F0F0F, 0xF0F0F0F0F0F0F0F0, 4, x, y) - - SWAP2(q[0], q[1]); - SWAP2(q[2], q[3]); - SWAP2(q[4], q[5]); - SWAP2(q[6], q[7]); - - SWAP4(q[0], q[2]); - SWAP4(q[1], q[3]); - SWAP4(q[4], q[6]); - SWAP4(q[5], q[7]); - - SWAP8(q[0], q[4]); - SWAP8(q[1], q[5]); - SWAP8(q[2], q[6]); - SWAP8(q[3], q[7]); -} - - -static void br_aes_ct64_interleave_in(uint64_t *q0, uint64_t *q1, const uint32_t *w) { - uint64_t x0, x1, x2, x3; - - x0 = w[0]; - x1 = w[1]; - x2 = w[2]; - x3 = w[3]; - x0 |= (x0 << 16); - x1 |= (x1 << 16); - x2 |= (x2 << 16); - x3 |= (x3 << 16); - x0 &= (uint64_t)0x0000FFFF0000FFFF; - x1 &= (uint64_t)0x0000FFFF0000FFFF; - x2 &= (uint64_t)0x0000FFFF0000FFFF; - x3 &= (uint64_t)0x0000FFFF0000FFFF; - x0 |= (x0 << 8); - x1 |= (x1 << 8); - x2 |= (x2 << 8); - x3 |= (x3 << 8); - x0 &= (uint64_t)0x00FF00FF00FF00FF; - x1 &= (uint64_t)0x00FF00FF00FF00FF; - x2 &= (uint64_t)0x00FF00FF00FF00FF; - x3 &= (uint64_t)0x00FF00FF00FF00FF; - *q0 = x0 | (x2 << 8); - *q1 = x1 | (x3 << 8); -} - - -static void br_aes_ct64_interleave_out(uint32_t *w, uint64_t q0, uint64_t q1) { - uint64_t x0, x1, x2, x3; - - x0 = q0 & (uint64_t)0x00FF00FF00FF00FF; - x1 = q1 & (uint64_t)0x00FF00FF00FF00FF; - x2 = (q0 >> 8) & (uint64_t)0x00FF00FF00FF00FF; - x3 = (q1 >> 8) & (uint64_t)0x00FF00FF00FF00FF; - x0 |= (x0 >> 8); - x1 |= (x1 >> 8); - x2 |= (x2 >> 8); - x3 |= (x3 >> 8); - x0 &= (uint64_t)0x0000FFFF0000FFFF; - x1 &= (uint64_t)0x0000FFFF0000FFFF; - x2 &= (uint64_t)0x0000FFFF0000FFFF; - x3 &= (uint64_t)0x0000FFFF0000FFFF; - w[0] = (uint32_t)x0 | (uint32_t)(x0 >> 16); - w[1] = (uint32_t)x1 | (uint32_t)(x1 >> 16); - w[2] = (uint32_t)x2 | (uint32_t)(x2 >> 16); - w[3] = (uint32_t)x3 | (uint32_t)(x3 >> 16); -} - -static inline void add_round_key(uint64_t *q, const uint64_t *sk) { - q[0] ^= sk[0]; - q[1] ^= sk[1]; - q[2] ^= sk[2]; - q[3] ^= sk[3]; - q[4] ^= sk[4]; - q[5] ^= sk[5]; - q[6] ^= sk[6]; - q[7] ^= sk[7]; -} - -static inline void shift_rows(uint64_t *q) { - int i; - - for (i = 0; i < 8; i++) { - uint64_t x; - - x = q[i]; - q[i] = (x & (uint64_t)0x000000000000FFFF) - | ((x & (uint64_t)0x00000000FFF00000) >> 4) - | ((x & (uint64_t)0x00000000000F0000) << 12) - | ((x & (uint64_t)0x0000FF0000000000) >> 8) - | ((x & (uint64_t)0x000000FF00000000) << 8) - | ((x & (uint64_t)0xF000000000000000) >> 12) - | ((x & (uint64_t)0x0FFF000000000000) << 4); - } -} - -static inline uint64_t rotr32(uint64_t x) { - return (x << 32) | (x >> 32); -} - -static inline void mix_columns(uint64_t *q) { - uint64_t q0, q1, q2, q3, q4, q5, q6, q7; - uint64_t r0, r1, r2, r3, r4, r5, r6, r7; - - q0 = q[0]; - q1 = q[1]; - q2 = q[2]; - q3 = q[3]; - q4 = q[4]; - q5 = q[5]; - q6 = q[6]; - q7 = q[7]; - r0 = (q0 >> 16) | (q0 << 48); - r1 = (q1 >> 16) | (q1 << 48); - r2 = (q2 >> 16) | (q2 << 48); - r3 = (q3 >> 16) | (q3 << 48); - r4 = (q4 >> 16) | (q4 << 48); - r5 = (q5 >> 16) | (q5 << 48); - r6 = (q6 >> 16) | (q6 << 48); - r7 = (q7 >> 16) | (q7 << 48); - - q[0] = q7 ^ r7 ^ r0 ^ rotr32(q0 ^ r0); - q[1] = q0 ^ r0 ^ q7 ^ r7 ^ r1 ^ rotr32(q1 ^ r1); - q[2] = q1 ^ r1 ^ r2 ^ rotr32(q2 ^ r2); - q[3] = q2 ^ r2 ^ q7 ^ r7 ^ r3 ^ rotr32(q3 ^ r3); - q[4] = q3 ^ r3 ^ q7 ^ r7 ^ r4 ^ rotr32(q4 ^ r4); - q[5] = q4 ^ r4 ^ r5 ^ rotr32(q5 ^ r5); - q[6] = q5 ^ r5 ^ r6 ^ rotr32(q6 ^ r6); - q[7] = q6 ^ r6 ^ r7 ^ rotr32(q7 ^ r7); -} - -static void interleave_constant(uint64_t *out, const unsigned char *in) { - uint32_t tmp_32_constant[16]; - int i; - - br_range_dec32le(tmp_32_constant, 16, in); - for (i = 0; i < 4; i++) { - br_aes_ct64_interleave_in(&out[i], &out[i + 4], tmp_32_constant + (i << 2)); - } - br_aes_ct64_ortho(out); -} - -static void interleave_constant32(uint32_t *out, const unsigned char *in) { - int i; - for (i = 0; i < 4; i++) { - out[2 * i] = br_dec32le(in + 4 * i); - out[2 * i + 1] = br_dec32le(in + 4 * i + 16); - } - br_aes_ct_ortho(out); -} - -void tweak_constants(spx_ctx *ctx) { - unsigned char buf[40 * 16]; - int i; - - /* Use the standard constants to generate tweaked ones. */ - memcpy((uint8_t *)ctx->tweaked512_rc64, (uint8_t *)haraka512_rc64, 40 * 16); - - /* Constants for pk.seed */ - haraka_S(buf, 40 * 16, ctx->pub_seed, SPX_N, ctx); - for (i = 0; i < 10; i++) { - interleave_constant32(ctx->tweaked256_rc32[i], buf + 32 * i); - interleave_constant(ctx->tweaked512_rc64[i], buf + 64 * i); - } -} - -static void haraka_S_absorb(unsigned char *s, unsigned int r, - const unsigned char *m, unsigned long long mlen, - unsigned char p, const spx_ctx *ctx) { - unsigned long long i; - PQCLEAN_VLA(uint8_t, t, r); - - while (mlen >= r) { - /* XOR block to state */ - for (i = 0; i < r; ++i) { - s[i] ^= m[i]; - } - haraka512_perm(s, s, ctx); - 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; ++i) { - s[i] ^= t[i]; - } -} - -static void haraka_S_squeezeblocks(unsigned char *h, unsigned long long nblocks, - unsigned char *s, unsigned int r, - const spx_ctx *ctx) { - while (nblocks > 0) { - haraka512_perm(s, s, ctx); - memcpy(h, s, HARAKAS_RATE); - h += r; - nblocks--; - } -} - -void haraka_S_inc_init(uint8_t *s_inc) { - size_t i; - - for (i = 0; i < 64; i++) { - s_inc[i] = 0; - } - s_inc[64] = 0; -} - -void haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, - const spx_ctx *ctx) { - size_t i; - - /* Recall that s_inc[64] is the non-absorbed bytes xored into the state */ - while (mlen + s_inc[64] >= HARAKAS_RATE) { - for (i = 0; i < (size_t)(HARAKAS_RATE - s_inc[64]); i++) { - /* Take the i'th byte from message - xor with the s_inc[64] + i'th byte of the state */ - s_inc[s_inc[64] + i] ^= m[i]; - } - mlen -= (size_t)(HARAKAS_RATE - s_inc[64]); - m += HARAKAS_RATE - (uint8_t)s_inc[64]; - s_inc[64] = 0; - - haraka512_perm(s_inc, s_inc, ctx); - } - - for (i = 0; i < mlen; i++) { - s_inc[s_inc[64] + i] ^= m[i]; - } - s_inc[64] += (uint8_t)mlen; -} - -void haraka_S_inc_finalize(uint8_t *s_inc) { - /* After haraka_S_inc_absorb, we are guaranteed that s_inc[64] < HARAKAS_RATE, - so we can always use one more byte for p in the current state. */ - s_inc[s_inc[64]] ^= 0x1F; - s_inc[HARAKAS_RATE - 1] ^= 128; - s_inc[64] = 0; -} - -void haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, - const spx_ctx *ctx) { - size_t i; - - /* First consume any bytes we still have sitting around */ - for (i = 0; i < outlen && i < s_inc[64]; i++) { - /* There are s_inc[64] bytes left, so r - s_inc[64] is the first - available byte. We consume from there, i.e., up to r. */ - out[i] = (uint8_t)s_inc[(HARAKAS_RATE - s_inc[64] + i)]; - } - out += i; - outlen -= i; - s_inc[64] -= (uint8_t)i; - - /* Then squeeze the remaining necessary blocks */ - while (outlen > 0) { - haraka512_perm(s_inc, s_inc, ctx); - - for (i = 0; i < outlen && i < HARAKAS_RATE; i++) { - out[i] = s_inc[i]; - } - out += i; - outlen -= i; - s_inc[64] = (uint8_t)(HARAKAS_RATE - i); - } -} - -void haraka_S(unsigned char *out, unsigned long long outlen, - const unsigned char *in, unsigned long long inlen, - const spx_ctx *ctx) { - unsigned long long i; - unsigned char s[64]; - unsigned char d[32]; - - for (i = 0; i < 64; i++) { - s[i] = 0; - } - haraka_S_absorb(s, 32, in, inlen, 0x1F, ctx); - - haraka_S_squeezeblocks(out, outlen / 32, s, 32, ctx); - out += (outlen / 32) * 32; - - if (outlen % 32) { - haraka_S_squeezeblocks(d, 1, s, 32, ctx); - for (i = 0; i < outlen % 32; i++) { - out[i] = d[i]; - } - } -} - -void haraka512_perm(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx) { - uint32_t w[16]; - uint64_t q[8], tmp_q; - unsigned int i, j; - - br_range_dec32le(w, 16, in); - for (i = 0; i < 4; i++) { - br_aes_ct64_interleave_in(&q[i], &q[i + 4], w + (i << 2)); - } - br_aes_ct64_ortho(q); - - /* AES rounds */ - for (i = 0; i < 5; i++) { - for (j = 0; j < 2; j++) { - br_aes_ct64_bitslice_Sbox(q); - shift_rows(q); - mix_columns(q); - add_round_key(q, ctx->tweaked512_rc64[2 * i + j]); - } - /* Mix states */ - for (j = 0; j < 8; j++) { - tmp_q = q[j]; - q[j] = (tmp_q & 0x0001000100010001) << 5 | - (tmp_q & 0x0002000200020002) << 12 | - (tmp_q & 0x0004000400040004) >> 1 | - (tmp_q & 0x0008000800080008) << 6 | - (tmp_q & 0x0020002000200020) << 9 | - (tmp_q & 0x0040004000400040) >> 4 | - (tmp_q & 0x0080008000800080) << 3 | - (tmp_q & 0x2100210021002100) >> 5 | - (tmp_q & 0x0210021002100210) << 2 | - (tmp_q & 0x0800080008000800) << 4 | - (tmp_q & 0x1000100010001000) >> 12 | - (tmp_q & 0x4000400040004000) >> 10 | - (tmp_q & 0x8400840084008400) >> 3; - } - } - - br_aes_ct64_ortho(q); - for (i = 0; i < 4; i ++) { - br_aes_ct64_interleave_out(w + (i << 2), q[i], q[i + 4]); - } - br_range_enc32le(out, w, 16); -} - -void haraka512(unsigned char *out, const unsigned char *in, const spx_ctx *ctx) { - int i; - - unsigned char buf[64]; - - haraka512_perm(buf, in, ctx); - /* Feed-forward */ - for (i = 0; i < 64; i++) { - buf[i] = buf[i] ^ in[i]; - } - - /* Truncated */ - memcpy(out, buf + 8, 8); - memcpy(out + 8, buf + 24, 8); - memcpy(out + 16, buf + 32, 8); - memcpy(out + 24, buf + 48, 8); -} - - -void haraka256(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx) { - uint32_t q[8], tmp_q; - int i, j; - - for (i = 0; i < 4; i++) { - q[2 * i] = br_dec32le(in + 4 * i); - q[2 * i + 1] = br_dec32le(in + 4 * i + 16); - } - br_aes_ct_ortho(q); - - /* AES rounds */ - for (i = 0; i < 5; i++) { - for (j = 0; j < 2; j++) { - br_aes_ct_bitslice_Sbox(q); - shift_rows32(q); - mix_columns32(q); - add_round_key32(q, ctx->tweaked256_rc32[2 * i + j]); - } - - /* Mix states */ - for (j = 0; j < 8; j++) { - tmp_q = q[j]; - q[j] = (tmp_q & 0x81818181) | - (tmp_q & 0x02020202) << 1 | - (tmp_q & 0x04040404) << 2 | - (tmp_q & 0x08080808) << 3 | - (tmp_q & 0x10101010) >> 3 | - (tmp_q & 0x20202020) >> 2 | - (tmp_q & 0x40404040) >> 1; - } - } - - br_aes_ct_ortho(q); - for (i = 0; i < 4; i++) { - br_enc32le(out + 4 * i, q[2 * i]); - br_enc32le(out + 4 * i + 16, q[2 * i + 1]); - } - - for (i = 0; i < 32; i++) { - out[i] ^= in[i]; - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/haraka.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/haraka.h deleted file mode 100644 index 737cb6065f..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/haraka.h +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef SPX_HARAKA_H -#define SPX_HARAKA_H - -#include "context.h" -#include "params.h" - -/* Tweak constants with seed */ -#define tweak_constants SPX_NAMESPACE(tweak_constants) -void tweak_constants(spx_ctx *ctx); - -/* Haraka Sponge */ -#define haraka_S_inc_init SPX_NAMESPACE(haraka_S_inc_init) -void haraka_S_inc_init(uint8_t *s_inc); -#define haraka_S_inc_absorb SPX_NAMESPACE(haraka_S_inc_absorb) -void haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, - const spx_ctx *ctx); -#define haraka_S_inc_finalize SPX_NAMESPACE(haraka_S_inc_finalize) -void haraka_S_inc_finalize(uint8_t *s_inc); -#define haraka_S_inc_squeeze SPX_NAMESPACE(haraka_S_inc_squeeze) -void haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, - const spx_ctx *ctx); -#define haraka_S SPX_NAMESPACE(haraka_S) -void haraka_S(unsigned char *out, unsigned long long outlen, - const unsigned char *in, unsigned long long inlen, - const spx_ctx *ctx); - -/* Applies the 512-bit Haraka permutation to in. */ -#define haraka512_perm SPX_NAMESPACE(haraka512_perm) -void haraka512_perm(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx); - -/* Implementation of Haraka-512 */ -#define haraka512 SPX_NAMESPACE(haraka512) -void haraka512(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx); - -/* Implementation of Haraka-256 */ -#define haraka256 SPX_NAMESPACE(haraka256) -void haraka256(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/haraka_offsets.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/haraka_offsets.h deleted file mode 100644 index 7c062272a0..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/haraka_offsets.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef HARAKA_OFFSETS_H_ -#define HARAKA_OFFSETS_H_ - -/* - * Offsets of various fields in the address structure when we use Haraka as - * the Sphincs+ hash function - */ - -#define SPX_OFFSET_LAYER 3 /* The byte used to specify the Merkle tree layer */ -#define SPX_OFFSET_TREE 8 /* The start of the 8 byte field used to specify the tree */ -#define SPX_OFFSET_TYPE 19 /* The byte used to specify the hash type (reason) */ -#define SPX_OFFSET_KP_ADDR2 22 /* The high byte used to specify the key pair (which one-time signature) */ -#define SPX_OFFSET_KP_ADDR1 23 /* The low byte used to specify the key pair */ -#define SPX_OFFSET_CHAIN_ADDR 27 /* The byte used to specify the chain address (which Winternitz chain) */ -#define SPX_OFFSET_HASH_ADDR 31 /* The byte used to specify the hash address (where in the Winternitz chain) */ -#define SPX_OFFSET_TREE_HGT 27 /* The byte used to specify the height of this node in the FORS or Merkle tree */ -#define SPX_OFFSET_TREE_INDEX 28 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ - -#define SPX_HARAKA 1 - -#endif /* HARAKA_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/hash.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/hash.h deleted file mode 100644 index f7c87d4c3c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/hash.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef SPX_HASH_H -#define SPX_HASH_H - -#include -#include - -#include "context.h" -#include "params.h" - -#define prf_addr SPX_NAMESPACE(prf_addr) -void prf_addr(unsigned char *out, const spx_ctx *ctx, - const uint32_t addr[8]); - -#define gen_message_random SPX_NAMESPACE(gen_message_random) -void gen_message_random(unsigned char *R, const unsigned char *sk_prf, - const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx); - -#define hash_message SPX_NAMESPACE(hash_message) -void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx); - - - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/hash_haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/hash_haraka.c deleted file mode 100644 index 750a67423b..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/hash_haraka.c +++ /dev/null @@ -1,81 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "utils.h" - -#include "haraka.h" -#include "hash.h" - -/* - * Computes PRF(key, addr), given a secret key of SPX_N bytes and an address - */ -void prf_addr(unsigned char *out, const spx_ctx *ctx, - const uint32_t addr[8]) { - /* Since SPX_N may be smaller than 32, we need temporary buffers. */ - unsigned char outbuf[32]; - unsigned char buf[64] = {0}; - - memcpy(buf, addr, SPX_ADDR_BYTES); - memcpy(buf + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); - - haraka512(outbuf, (const void *)buf, ctx); - memcpy(out, outbuf, SPX_N); -} - -/** - * Computes the message-dependent randomness R, using a secret seed and an - * optional randomization value as well as the message. - */ -void gen_message_random(unsigned char *R, const unsigned char *sk_prf, - const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx) { - uint8_t s_inc[65]; - - haraka_S_inc_init(s_inc); - haraka_S_inc_absorb(s_inc, sk_prf, SPX_N, ctx); - haraka_S_inc_absorb(s_inc, optrand, SPX_N, ctx); - haraka_S_inc_absorb(s_inc, m, mlen, ctx); - haraka_S_inc_finalize(s_inc); - haraka_S_inc_squeeze(R, SPX_N, s_inc, ctx); -} - -/** - * Computes the message hash using R, the public key, and the message. - * Outputs the message digest and the index of the leaf. The index is split in - * the tree index and the leaf index, for convenient copying to an address. - */ -void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx) { -#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) -#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) -#define SPX_LEAF_BITS SPX_TREE_HEIGHT -#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) -#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) - - unsigned char buf[SPX_DGST_BYTES]; - unsigned char *bufp = buf; - uint8_t s_inc[65]; - - haraka_S_inc_init(s_inc); - haraka_S_inc_absorb(s_inc, R, SPX_N, ctx); - haraka_S_inc_absorb(s_inc, pk + SPX_N, SPX_N, ctx); // Only absorb root part of pk - haraka_S_inc_absorb(s_inc, m, mlen, ctx); - haraka_S_inc_finalize(s_inc); - haraka_S_inc_squeeze(buf, SPX_DGST_BYTES, s_inc, ctx); - - memcpy(digest, bufp, SPX_FORS_MSG_BYTES); - bufp += SPX_FORS_MSG_BYTES; - - - *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); - *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); - bufp += SPX_TREE_BYTES; - - *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); - *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/merkle.c b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/merkle.c deleted file mode 100644 index 0c1479fd93..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/merkle.c +++ /dev/null @@ -1,59 +0,0 @@ -#include -#include - -#include "address.h" -#include "merkle.h" -#include "params.h" -#include "utils.h" -#include "utilsx1.h" -#include "wots.h" -#include "wotsx1.h" - -/* - * This generates a Merkle signature (WOTS signature followed by the Merkle - * authentication path). This is in this file because most of the complexity - * is involved with the WOTS signature; the Merkle authentication path logic - * is mostly hidden in treehashx4 - */ -void merkle_sign(uint8_t *sig, unsigned char *root, - const spx_ctx *ctx, - uint32_t wots_addr[8], uint32_t tree_addr[8], - uint32_t idx_leaf) { - unsigned char *auth_path = sig + SPX_WOTS_BYTES; - struct leaf_info_x1 info = { 0 }; - unsigned steps[ SPX_WOTS_LEN ]; - - info.wots_sig = sig; - chain_lengths(steps, root); - info.wots_steps = steps; - - set_type(&tree_addr[0], SPX_ADDR_TYPE_HASHTREE); - set_type(&info.pk_addr[0], SPX_ADDR_TYPE_WOTSPK); - copy_subtree_addr(&info.leaf_addr[0], wots_addr); - copy_subtree_addr(&info.pk_addr[0], wots_addr); - - info.wots_sign_leaf = idx_leaf; - - treehashx1(root, auth_path, ctx, - idx_leaf, 0, - SPX_TREE_HEIGHT, - wots_gen_leafx1, - tree_addr, &info); -} - -/* Compute root node of the top-most subtree. */ -void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { - /* We do not need the auth path in key generation, but it simplifies the - code to have just one treehash routine that computes both root and path - in one function. */ - unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; - uint32_t top_tree_addr[8] = {0}; - uint32_t wots_addr[8] = {0}; - - set_layer_addr(top_tree_addr, SPX_D - 1); - set_layer_addr(wots_addr, SPX_D - 1); - - merkle_sign(auth_path, root, ctx, - wots_addr, top_tree_addr, - (uint32_t)~0 /* ~0 means "don't bother generating an auth path */ ); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/merkle.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/merkle.h deleted file mode 100644 index 769cf2e970..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/merkle.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef MERKLE_H_ -#define MERKLE_H_ - -#include - -#include "context.h" -#include "params.h" - -/* Generate a Merkle signature (WOTS signature followed by the Merkle */ -/* authentication path) */ -#define merkle_sign SPX_NAMESPACE(merkle_sign) -void merkle_sign(uint8_t *sig, unsigned char *root, - const spx_ctx *ctx, - uint32_t wots_addr[8], uint32_t tree_addr[8], - uint32_t idx_leaf); - -/* Compute the root node of the top-most subtree. */ -#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) -void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); - -#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/nistapi.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/nistapi.h deleted file mode 100644 index 3cb71afad4..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/nistapi.h +++ /dev/null @@ -1,87 +0,0 @@ -#ifndef SPX_API_H -#define SPX_API_H - -#include -#include - -#include "params.h" - -#define CRYPTO_ALGNAME "SPHINCS+" - -#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES -#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES -#define CRYPTO_BYTES SPX_BYTES -#define CRYPTO_SEEDBYTES (3*SPX_N) - -/* - * Returns the length of a secret key, in bytes - */ -#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) -size_t crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) -size_t crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) -size_t crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) -size_t crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) -int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) -int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) -int crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) -int crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -#define crypto_sign SPX_NAMESPACE(crypto_sign) -int crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) -int crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/params.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/params.h deleted file mode 100644 index be1249e8af..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/params.h +++ /dev/null @@ -1,56 +0,0 @@ -#ifndef SPX_PARAMS_H -#define SPX_PARAMS_H - -#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_##s - -/* Hash output length in bytes. */ -#define SPX_N 16 -/* Height of the hypertree. */ -#define SPX_FULL_HEIGHT 63 -/* Number of subtree layer. */ -#define SPX_D 7 -/* FORS tree dimensions. */ -#define SPX_FORS_HEIGHT 12 -#define SPX_FORS_TREES 14 -/* Winternitz parameter, */ -#define SPX_WOTS_W 16 - -/* The hash function is defined by linking a different hash.c file, as opposed - to setting a #define constant. */ - -/* For clarity */ -#define SPX_ADDR_BYTES 32 - -/* WOTS parameters. */ -#define SPX_WOTS_LOGW 4 - -#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) - -/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#define SPX_WOTS_LEN2 3 - -#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) -#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) -#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES - -/* Subtree size. */ -#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) - -//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT -// #error SPX_D should always divide SPX_FULL_HEIGHT -//#endif - -/* FORS parameters. */ -#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) -#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) -#define SPX_FORS_PK_BYTES SPX_N - -/* Resulting SPX sizes. */ -#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ - SPX_FULL_HEIGHT * SPX_N) -#define SPX_PK_BYTES (2 * SPX_N) -#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) - -#include "haraka_offsets.h" - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/sign.c b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/sign.c deleted file mode 100644 index 9d0c7d1b22..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/sign.c +++ /dev/null @@ -1,286 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "context.h" -#include "fors.h" -#include "hash.h" -#include "merkle.h" -#include "nistapi.h" -#include "params.h" -#include "randombytes.h" -#include "thash.h" -#include "utils.h" -#include "wots.h" - -/* - * Returns the length of a secret key, in bytes - */ -size_t crypto_sign_secretkeybytes(void) { - return CRYPTO_SECRETKEYBYTES; -} - -/* - * Returns the length of a public key, in bytes - */ -size_t crypto_sign_publickeybytes(void) { - return CRYPTO_PUBLICKEYBYTES; -} - -/* - * Returns the length of a signature, in bytes - */ -size_t crypto_sign_bytes(void) { - return CRYPTO_BYTES; -} - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t crypto_sign_seedbytes(void) { - return CRYPTO_SEEDBYTES; -} - -/* - * Generates an SPX key pair given a seed of length - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed) { - spx_ctx ctx; - - /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ - memcpy(sk, seed, CRYPTO_SEEDBYTES); - - memcpy(pk, sk + 2 * SPX_N, SPX_N); - - memcpy(ctx.pub_seed, pk, SPX_N); - memcpy(ctx.sk_seed, sk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - /* Compute root node of the top-most subtree. */ - merkle_gen_root(sk + 3 * SPX_N, &ctx); - - // cleanup - free_hash_function(&ctx); - - memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); - - return 0; -} - -/* - * Generates an SPX key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { - uint8_t seed[CRYPTO_SEEDBYTES]; - randombytes(seed, CRYPTO_SEEDBYTES); - crypto_sign_seed_keypair(pk, sk, seed); - - return 0; -} - -/** - * Returns an array containing a detached signature. - */ -int crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - spx_ctx ctx; - - const uint8_t *sk_prf = sk + SPX_N; - const uint8_t *pk = sk + 2 * SPX_N; - - uint8_t optrand[SPX_N]; - uint8_t mhash[SPX_FORS_MSG_BYTES]; - uint8_t root[SPX_N]; - uint32_t i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - - memcpy(ctx.sk_seed, sk, SPX_N); - memcpy(ctx.pub_seed, pk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - set_type(wots_addr, SPX_ADDR_TYPE_WOTS); - set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); - - /* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ - randombytes(optrand, SPX_N); - /* Compute the digest randomization value. */ - gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); - - /* Derive the message digest and leaf index from R, PK and M. */ - hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); - sig += SPX_N; - - set_tree_addr(wots_addr, tree); - set_keypair_addr(wots_addr, idx_leaf); - - /* Sign the message hash using FORS. */ - fors_sign(sig, root, mhash, &ctx, wots_addr); - sig += SPX_FORS_BYTES; - - for (i = 0; i < SPX_D; i++) { - set_layer_addr(tree_addr, i); - set_tree_addr(tree_addr, tree); - - copy_subtree_addr(wots_addr, tree_addr); - set_keypair_addr(wots_addr, idx_leaf); - - merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); - sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); - tree = tree >> SPX_TREE_HEIGHT; - } - - free_hash_function(&ctx); - - *siglen = SPX_BYTES; - - return 0; -} - -/** - * Verifies a detached signature and message under a given public key. - */ -int crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk) { - spx_ctx ctx; - const uint8_t *pub_root = pk + SPX_N; - uint8_t mhash[SPX_FORS_MSG_BYTES]; - uint8_t wots_pk[SPX_WOTS_BYTES]; - uint8_t root[SPX_N]; - uint8_t leaf[SPX_N]; - unsigned int i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - if (siglen != SPX_BYTES) { - return -1; - } - - memcpy(ctx.pub_seed, pk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - set_type(wots_addr, SPX_ADDR_TYPE_WOTS); - set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); - set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); - - /* Derive the message digest and leaf index from R || PK || M. */ - /* The additional SPX_N is a result of the hash domain separator. */ - hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); - sig += SPX_N; - - /* Layer correctly defaults to 0, so no need to set_layer_addr */ - set_tree_addr(wots_addr, tree); - set_keypair_addr(wots_addr, idx_leaf); - - fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); - sig += SPX_FORS_BYTES; - - /* For each subtree.. */ - for (i = 0; i < SPX_D; i++) { - set_layer_addr(tree_addr, i); - set_tree_addr(tree_addr, tree); - - copy_subtree_addr(wots_addr, tree_addr); - set_keypair_addr(wots_addr, idx_leaf); - - copy_keypair_addr(wots_pk_addr, wots_addr); - - /* The WOTS public key is only correct if the signature was correct. */ - /* Initially, root is the FORS pk, but on subsequent iterations it is - the root of the subtree below the currently processed subtree. */ - wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); - sig += SPX_WOTS_BYTES; - - /* Compute the leaf node using the WOTS public key. */ - thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); - - /* Compute the root node of this subtree. */ - compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, - &ctx, tree_addr); - sig += SPX_TREE_HEIGHT * SPX_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); - tree = tree >> SPX_TREE_HEIGHT; - } - - // cleanup - free_hash_function(&ctx); - - /* Check if the root node equals the root node in the public key. */ - if (memcmp(root, pub_root, SPX_N) != 0) { - return -1; - } - - return 0; -} - - -/** - * Returns an array containing the signature followed by the message. - */ -int crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk) { - size_t siglen; - - crypto_sign_signature(sm, &siglen, m, mlen, sk); - - memmove(sm + SPX_BYTES, m, mlen); - *smlen = siglen + mlen; - - return 0; -} - -/** - * Verifies a given signature-message pair under a given public key. - */ -int crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk) { - /* The API caller does not necessarily know what size a signature should be - but SPHINCS+ signatures are always exactly SPX_BYTES. */ - if (smlen < SPX_BYTES) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - *mlen = smlen - SPX_BYTES; - - if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - /* If verification was successful, move the message to the right place. */ - memmove(m, sm + SPX_BYTES, *mlen); - - return 0; -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/thash.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/thash.h deleted file mode 100644 index 8687ccfb4d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/thash.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef SPX_THASH_H -#define SPX_THASH_H - -#include "context.h" -#include "params.h" - -#include - -#define thash SPX_NAMESPACE(thash) -void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/thash_haraka_simple.c b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/thash_haraka_simple.c deleted file mode 100644 index 207777bf8d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/thash_haraka_simple.c +++ /dev/null @@ -1,36 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "thash.h" -#include "utils.h" - -#include "haraka.h" - -/** - * Takes an array of inblocks concatenated arrays of SPX_N bytes. - */ -void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]) { - PQCLEAN_VLA(uint8_t, buf, SPX_ADDR_BYTES + inblocks * SPX_N); - unsigned char outbuf[32]; - unsigned char buf_tmp[64]; - - if (inblocks == 1) { - /* F function */ - /* Since SPX_N may be smaller than 32, we need a temporary buffer. */ - memset(buf_tmp, 0, 64); - memcpy(buf_tmp, addr, 32); - memcpy(buf_tmp + SPX_ADDR_BYTES, in, SPX_N); - - haraka512(outbuf, buf_tmp, ctx); - memcpy(out, outbuf, SPX_N); - } else { - /* All other tweakable hashes*/ - memcpy(buf, addr, 32); - memcpy(buf + SPX_ADDR_BYTES, in, inblocks * SPX_N); - - haraka_S(out, SPX_N, buf, SPX_ADDR_BYTES + inblocks * SPX_N, ctx); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/utils.c b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/utils.c deleted file mode 100644 index 177b541fb9..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/utils.c +++ /dev/null @@ -1,148 +0,0 @@ -#include - -#include "utils.h" - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "thash.h" - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void ull_to_bytes(unsigned char *out, unsigned int outlen, - unsigned long long in) { - int i; - - /* Iterate over out in decreasing order, for big-endianness. */ - for (i = (signed int)outlen - 1; i >= 0; i--) { - out[i] = in & 0xff; - in = in >> 8; - } -} - -void u32_to_bytes(unsigned char *out, uint32_t in) { - out[0] = (unsigned char)(in >> 24); - out[1] = (unsigned char)(in >> 16); - out[2] = (unsigned char)(in >> 8); - out[3] = (unsigned char)in; -} - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { - unsigned long long retval = 0; - unsigned int i; - - for (i = 0; i < inlen; i++) { - retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); - } - return retval; -} - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void compute_root(unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const spx_ctx *ctx, uint32_t addr[8]) { - uint32_t i; - unsigned char buffer[2 * SPX_N]; - - /* If leaf_idx is odd (last bit = 1), current path element is a right child - and auth_path has to go left. Otherwise it is the other way around. */ - if (leaf_idx & 1) { - memcpy(buffer + SPX_N, leaf, SPX_N); - memcpy(buffer, auth_path, SPX_N); - } else { - memcpy(buffer, leaf, SPX_N); - memcpy(buffer + SPX_N, auth_path, SPX_N); - } - auth_path += SPX_N; - - for (i = 0; i < tree_height - 1; i++) { - leaf_idx >>= 1; - idx_offset >>= 1; - /* Set the address of the node we're creating. */ - set_tree_height(addr, i + 1); - set_tree_index(addr, leaf_idx + idx_offset); - - /* Pick the right or left neighbor, depending on parity of the node. */ - if (leaf_idx & 1) { - thash(buffer + SPX_N, buffer, 2, ctx, addr); - memcpy(buffer, auth_path, SPX_N); - } else { - thash(buffer, buffer, 2, ctx, addr); - memcpy(buffer + SPX_N, auth_path, SPX_N); - } - auth_path += SPX_N; - } - - /* The last iteration is exceptional; we do not copy an auth_path node. */ - leaf_idx >>= 1; - idx_offset >>= 1; - set_tree_height(addr, tree_height); - set_tree_index(addr, leaf_idx + idx_offset); - thash(root, buffer, 2, ctx, addr); -} - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const spx_ctx * /* ctx */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), - uint32_t tree_addr[8]) { - PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); - PQCLEAN_VLA(unsigned int, heights, tree_height + 1); - unsigned int offset = 0; - uint32_t idx; - uint32_t tree_idx; - - for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { - /* Add the next leaf node to the stack. */ - gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); - offset++; - heights[offset - 1] = 0; - - /* If this is a node we need for the auth path.. */ - if ((leaf_idx ^ 0x1) == idx) { - memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); - } - - /* While the top-most nodes are of equal height.. */ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { - /* Compute index of the new node, in the next layer. */ - tree_idx = (idx >> (heights[offset - 1] + 1)); - - /* Set the address of the node we're creating. */ - set_tree_height(tree_addr, heights[offset - 1] + 1); - set_tree_index(tree_addr, - tree_idx + (idx_offset >> (heights[offset - 1] + 1))); - /* Hash the top-most nodes from the stack together. */ - thash(stack + (offset - 2)*SPX_N, - stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); - offset--; - /* Note that the top-most node is now one layer higher. */ - heights[offset - 1]++; - - /* If this is a node we need for the auth path.. */ - if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_path + heights[offset - 1]*SPX_N, - stack + (offset - 1)*SPX_N, SPX_N); - } - } - } - memcpy(root, stack, SPX_N); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/utils.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/utils.h deleted file mode 100644 index 64f5d5a53a..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/utils.h +++ /dev/null @@ -1,58 +0,0 @@ -#ifndef SPX_UTILS_H -#define SPX_UTILS_H - -#include - -#include "compat.h" -#include "context.h" -#include "params.h" - - -/* To support MSVC use alloca() instead of VLAs. See #20. */ - - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) -void ull_to_bytes(unsigned char *out, unsigned int outlen, - unsigned long long in); -#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) -void u32_to_bytes(unsigned char *out, uint32_t in); - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) -unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -#define compute_root SPX_NAMESPACE(compute_root) -void compute_root(unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const spx_ctx *ctx, uint32_t addr[8]); - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -#define treehash SPX_NAMESPACE(treehash) -void treehash(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const spx_ctx *ctx /* ctx */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), - uint32_t tree_addr[8]); - - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/utilsx1.c b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/utilsx1.c deleted file mode 100644 index fccb69b35d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/utilsx1.c +++ /dev/null @@ -1,100 +0,0 @@ -#include - -#include "utilsx1.h" - -#include "address.h" -#include "params.h" -#include "thash.h" -#include "utils.h" - -/* - * Generate the entire Merkle tree, computing the authentication path for - * leaf_idx, and the resulting root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) - * - * This expects tree_addr to be initialized to the addr structures for the - * Merkle tree nodes - * - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - * - * This works by using the standard Merkle tree building algorithm, - */ -void treehashx1(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, - uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* Where to write the leaves */, - const spx_ctx * /* ctx */, - uint32_t idx, void *info), - uint32_t tree_addr[8], - void *info) { - /* This is where we keep the intermediate nodes */ - PQCLEAN_VLA(uint8_t, stack, tree_height * SPX_N); - - uint32_t idx; - uint32_t max_idx = (uint32_t)((1 << tree_height) - 1); - for (idx = 0;; idx++) { - unsigned char current[2 * SPX_N]; /* Current logical node is at */ - /* index[SPX_N]. We do this to minimize the number of copies */ - /* needed during a thash */ - gen_leaf( ¤t[SPX_N], ctx, idx + idx_offset, - info ); - - /* Now combine the freshly generated right node with previously */ - /* generated left ones */ - uint32_t internal_idx_offset = idx_offset; - uint32_t internal_idx = idx; - uint32_t internal_leaf = leaf_idx; - uint32_t h; /* The height we are in the Merkle tree */ - for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { - - /* Check if we hit the top of the tree */ - if (h == tree_height) { - /* We hit the root; return it */ - memcpy( root, ¤t[SPX_N], SPX_N ); - return; - } - - /* - * Check if the node we have is a part of the - * authentication path; if it is, write it out - */ - if ((internal_idx ^ internal_leaf) == 0x01) { - memcpy( &auth_path[ h * SPX_N ], - ¤t[SPX_N], - SPX_N ); - } - - /* - * Check if we're at a left child; if so, stop going up the stack - * Exception: if we've reached the end of the tree, keep on going - * (so we combine the last 4 nodes into the one root node in two - * more iterations) - */ - if ((internal_idx & 1) == 0 && idx < max_idx) { - break; - } - - /* Ok, we're at a right node */ - /* Now combine the left and right logical nodes together */ - - /* Set the address of the node we're creating. */ - internal_idx_offset >>= 1; - set_tree_height(tree_addr, h + 1); - set_tree_index(tree_addr, internal_idx / 2 + internal_idx_offset ); - - unsigned char *left = &stack[h * SPX_N]; - memcpy( ¤t[0], left, SPX_N ); - thash( ¤t[1 * SPX_N], - ¤t[0 * SPX_N], - 2, ctx, tree_addr); - } - - /* We've hit a left child; save the current for when we get the */ - /* corresponding right right */ - memcpy( &stack[h * SPX_N], ¤t[SPX_N], SPX_N); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/utilsx1.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/utilsx1.h deleted file mode 100644 index e911d17d53..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/utilsx1.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef SPX_UTILSX4_H -#define SPX_UTILSX4_H - -#include - -#include "context.h" -#include "params.h" - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -#define treehashx1 SPX_NAMESPACE(treehashx1) -void treehashx1(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* Where to write the leaf */, - const spx_ctx * /* ctx */, - uint32_t addr_idx, void *info), - uint32_t tree_addrx4[8], void *info); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/wots.c b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/wots.c deleted file mode 100644 index 249717aaa8..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/wots.c +++ /dev/null @@ -1,108 +0,0 @@ -#include -#include - -#include "wots.h" -#include "wotsx1.h" - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "thash.h" -#include "utils.h" -#include "utilsx1.h" - -// TODO clarify address expectations, and make them more uniform. -// TODO i.e. do we expect types to be set already? -// TODO and do we expect modifications or copies? - -/** - * Computes the chaining function. - * out and in have to be n-byte arrays. - * - * Interprets in as start-th value of the chain. - * addr has to contain the address of the chain. - */ -static void gen_chain(unsigned char *out, const unsigned char *in, - unsigned int start, unsigned int steps, - const spx_ctx *ctx, uint32_t addr[8]) { - uint32_t i; - - /* Initialize out with the value at position 'start'. */ - memcpy(out, in, SPX_N); - - /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < SPX_WOTS_W; i++) { - set_hash_addr(addr, i); - thash(out, out, 1, ctx, addr); - } -} - -/** - * base_w algorithm as described in draft. - * Interprets an array of bytes as integers in base w. - * This only works when log_w is a divisor of 8. - */ -static void base_w(unsigned int *output, const int out_len, - const unsigned char *input) { - int in = 0; - int out = 0; - unsigned char total = 0; - int bits = 0; - int consumed; - - for (consumed = 0; consumed < out_len; consumed++) { - if (bits == 0) { - total = input[in]; - in++; - bits += 8; - } - bits -= SPX_WOTS_LOGW; - output[out] = (total >> bits) & (SPX_WOTS_W - 1); - out++; - } -} - -/* Computes the WOTS+ checksum over a message (in base_w). */ -static void wots_checksum(unsigned int *csum_base_w, - const unsigned int *msg_base_w) { - unsigned int csum = 0; - unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; - unsigned int i; - - /* Compute checksum. */ - for (i = 0; i < SPX_WOTS_LEN1; i++) { - csum += SPX_WOTS_W - 1 - msg_base_w[i]; - } - - /* Convert checksum to base_w. */ - /* Make sure expected empty zero bits are the least significant bits. */ - csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); - ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); - base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); -} - -/* Takes a message and derives the matching chain lengths. */ -void chain_lengths(unsigned int *lengths, const unsigned char *msg) { - base_w(lengths, SPX_WOTS_LEN1, msg); - wots_checksum(lengths + SPX_WOTS_LEN1, lengths); -} - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const spx_ctx *ctx, uint32_t addr[8]) { - unsigned int lengths[SPX_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < SPX_WOTS_LEN; i++) { - set_chain_addr(addr, i); - gen_chain(pk + i * SPX_N, sig + i * SPX_N, - lengths[i], SPX_WOTS_W - 1 - lengths[i], ctx, addr); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/wots.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/wots.h deleted file mode 100644 index 4e7692eeef..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/wots.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef SPX_WOTS_H -#define SPX_WOTS_H - -#include - -#include "context.h" -#include "params.h" - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) -void wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const spx_ctx *ctx, uint32_t addr[8]); - -/* - * Compute the chain lengths needed for a given message hash - */ -#define chain_lengths SPX_NAMESPACE(chain_lengths) -void chain_lengths(unsigned int *lengths, const unsigned char *msg); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/wotsx1.c b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/wotsx1.c deleted file mode 100644 index 3adec78dfb..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/wotsx1.c +++ /dev/null @@ -1,76 +0,0 @@ -#include -#include - -#include "wots.h" -#include "wotsx1.h" - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "thash.h" -#include "utils.h" - -/* - * This generates a WOTS public key - * It also generates the WOTS signature if leaf_info indicates - * that we're signing with this WOTS key - */ -void wots_gen_leafx1(unsigned char *dest, - const spx_ctx *ctx, - uint32_t leaf_idx, void *v_info) { - struct leaf_info_x1 *info = v_info; - uint32_t *leaf_addr = info->leaf_addr; - uint32_t *pk_addr = info->pk_addr; - unsigned int i, k; - unsigned char pk_buffer[ SPX_WOTS_BYTES ]; - unsigned char *buffer; - uint32_t wots_k_mask; - - if (leaf_idx == info->wots_sign_leaf) { - /* We're traversing the leaf that's signing; generate the WOTS */ - /* signature */ - wots_k_mask = 0; - } else { - /* Nope, we're just generating pk's; turn off the signature logic */ - wots_k_mask = (uint32_t)~0; - } - - set_keypair_addr( leaf_addr, leaf_idx ); - set_keypair_addr( pk_addr, leaf_idx ); - - for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { - uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k to */ - /* the step if we're generating a signature, ~0 if we're not */ - - /* Start with the secret seed */ - set_chain_addr(leaf_addr, i); - set_hash_addr(leaf_addr, 0); - set_type(leaf_addr, SPX_ADDR_TYPE_WOTSPRF); - - prf_addr(buffer, ctx, leaf_addr); - - set_type(leaf_addr, SPX_ADDR_TYPE_WOTS); - - /* Iterate down the WOTS chain */ - for (k = 0;; k++) { - /* Check if this is the value that needs to be saved as a */ - /* part of the WOTS signature */ - if (k == wots_k) { - memcpy( info->wots_sig + i * SPX_N, buffer, SPX_N ); - } - - /* Check if we hit the top of the chain */ - if (k == SPX_WOTS_W - 1) { - break; - } - - /* Iterate one step on the chain */ - set_hash_addr(leaf_addr, k); - - thash(buffer, buffer, 1, ctx, leaf_addr); - } - } - - /* Do the final thash to generate the public keys */ - thash(dest, pk_buffer, SPX_WOTS_LEN, ctx, pk_addr); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/wotsx1.h b/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/wotsx1.h deleted file mode 100644 index e617929f96..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-128s-simple_clean/wotsx1.h +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef WOTSX1_H_ -#define WOTSX1_H_ - -#include - -#include "context.h" -#include "params.h" - -/* - * This is here to provide an interface to the internal wots_gen_leafx1 - * routine. While this routine is not referenced in the package outside of - * wots.c, it is called from the stand-alone benchmark code to characterize - * the performance - */ -struct leaf_info_x1 { - unsigned char *wots_sig; - uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ - uint32_t *wots_steps; - uint32_t leaf_addr[8]; - uint32_t pk_addr[8]; -}; - -/* Macro to set the leaf_info to something 'benign', that is, it would */ -/* run with the same time as it does during the real signing process */ -/* Used only by the benchmark code */ -#define INITIALIZE_LEAF_INFO_X1(info, addr, step_buffer) { \ - (info).wots_sig = 0; \ - (info).wots_sign_leaf = ~0; \ - (info).wots_steps = step_buffer; \ - memcpy( &(info).leaf_addr[0], (addr), 32 ); \ - memcpy( &(info).pk_addr[0], (addr), 32 ); \ - } - -#define wots_gen_leafx1 SPX_NAMESPACE(wots_gen_leafx1) -void wots_gen_leafx1(unsigned char *dest, - const spx_ctx *ctx, - uint32_t leaf_idx, void *v_info); - -#endif /* WOTSX1_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/LICENSE b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/LICENSE deleted file mode 100644 index 670154e353..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/LICENSE +++ /dev/null @@ -1,116 +0,0 @@ -CC0 1.0 Universal - -Statement of Purpose - -The laws of most jurisdictions throughout the world automatically confer -exclusive Copyright and Related Rights (defined below) upon the creator and -subsequent owner(s) (each and all, an "owner") of an original work of -authorship and/or a database (each, a "Work"). - -Certain owners wish to permanently relinquish those rights to a Work for the -purpose of contributing to a commons of creative, cultural and scientific -works ("Commons") that the public can reliably and without fear of later -claims of infringement build upon, modify, incorporate in other works, reuse -and redistribute as freely as possible in any form whatsoever and for any -purposes, including without limitation commercial purposes. These owners may -contribute to the Commons to promote the ideal of a free culture and the -further production of creative, cultural and scientific works, or to gain -reputation or greater distribution for their Work in part through the use and -efforts of others. - -For these and/or other purposes and motivations, and without any expectation -of additional consideration or compensation, the person associating CC0 with a -Work (the "Affirmer"), to the extent that he or she is an owner of Copyright -and Related Rights in the Work, voluntarily elects to apply CC0 to the Work -and publicly distribute the Work under its terms, with knowledge of his or her -Copyright and Related Rights in the Work and the meaning and intended legal -effect of CC0 on those rights. - -1. Copyright and Related Rights. A Work made available under CC0 may be -protected by copyright and related or neighboring rights ("Copyright and -Related Rights"). Copyright and Related Rights include, but are not limited -to, the following: - - i. the right to reproduce, adapt, distribute, perform, display, communicate, - and translate a Work; - - ii. moral rights retained by the original author(s) and/or performer(s); - - iii. publicity and privacy rights pertaining to a person's image or likeness - depicted in a Work; - - iv. rights protecting against unfair competition in regards to a Work, - subject to the limitations in paragraph 4(a), below; - - v. rights protecting the extraction, dissemination, use and reuse of data in - a Work; - - vi. database rights (such as those arising under Directive 96/9/EC of the - European Parliament and of the Council of 11 March 1996 on the legal - protection of databases, and under any national implementation thereof, - including any amended or successor version of such directive); and - - vii. other similar, equivalent or corresponding rights throughout the world - based on applicable law or treaty, and any national implementations thereof. - -2. Waiver. To the greatest extent permitted by, but not in contravention of, -applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and -unconditionally waives, abandons, and surrenders all of Affirmer's Copyright -and Related Rights and associated claims and causes of action, whether now -known or unknown (including existing as well as future claims and causes of -action), in the Work (i) in all territories worldwide, (ii) for the maximum -duration provided by applicable law or treaty (including future time -extensions), (iii) in any current or future medium and for any number of -copies, and (iv) for any purpose whatsoever, including without limitation -commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes -the Waiver for the benefit of each member of the public at large and to the -detriment of Affirmer's heirs and successors, fully intending that such Waiver -shall not be subject to revocation, rescission, cancellation, termination, or -any other legal or equitable action to disrupt the quiet enjoyment of the Work -by the public as contemplated by Affirmer's express Statement of Purpose. - -3. Public License Fallback. Should any part of the Waiver for any reason be -judged legally invalid or ineffective under applicable law, then the Waiver -shall be preserved to the maximum extent permitted taking into account -Affirmer's express Statement of Purpose. In addition, to the extent the Waiver -is so judged Affirmer hereby grants to each affected person a royalty-free, -non transferable, non sublicensable, non exclusive, irrevocable and -unconditional license to exercise Affirmer's Copyright and Related Rights in -the Work (i) in all territories worldwide, (ii) for the maximum duration -provided by applicable law or treaty (including future time extensions), (iii) -in any current or future medium and for any number of copies, and (iv) for any -purpose whatsoever, including without limitation commercial, advertising or -promotional purposes (the "License"). The License shall be deemed effective as -of the date CC0 was applied by Affirmer to the Work. Should any part of the -License for any reason be judged legally invalid or ineffective under -applicable law, such partial invalidity or ineffectiveness shall not -invalidate the remainder of the License, and in such case Affirmer hereby -affirms that he or she will not (i) exercise any of his or her remaining -Copyright and Related Rights in the Work or (ii) assert any associated claims -and causes of action with respect to the Work, in either case contrary to -Affirmer's express Statement of Purpose. - -4. Limitations and Disclaimers. - - a. No trademark or patent rights held by Affirmer are waived, abandoned, - surrendered, licensed or otherwise affected by this document. - - b. Affirmer offers the Work as-is and makes no representations or warranties - of any kind concerning the Work, express, implied, statutory or otherwise, - including without limitation warranties of title, merchantability, fitness - for a particular purpose, non infringement, or the absence of latent or - other defects, accuracy, or the present or absence of errors, whether or not - discoverable, all to the greatest extent permissible under applicable law. - - c. Affirmer disclaims responsibility for clearing rights of other persons - that may apply to the Work or any use thereof, including without limitation - any person's Copyright and Related Rights in the Work. Further, Affirmer - disclaims responsibility for obtaining any necessary consents, permissions - or other rights required for any use of the Work. - - d. Affirmer understands and acknowledges that Creative Commons is not a - party to this document and has no duty or obligation with respect to this - CC0 or use of the Work. - -For more information, please see - diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/address.c b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/address.c deleted file mode 100644 index b956e9cb29..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/address.c +++ /dev/null @@ -1,91 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "utils.h" - -/* - * Specify which level of Merkle tree (the "layer") we're working on - */ -void set_layer_addr(uint32_t addr[8], uint32_t layer) { - ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; -} - -/* - * Specify which Merkle tree within the level (the "tree address") we're working on - */ -void set_tree_addr(uint32_t addr[8], uint64_t tree) { - ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); -} - -/* - * Specify the reason we'll use this address structure for, that is, what - * hash will we compute with it. This is used so that unrelated types of - * hashes don't accidentally get the same address structure. The type will be - * one of the SPX_ADDR_TYPE constants - */ -void set_type(uint32_t addr[8], uint32_t type) { - ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; -} - -/* - * Copy the layer and tree fields of the address structure. This is used - * when we're doing multiple types of hashes within the same Merkle tree - */ -void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { - memcpy( out, in, SPX_OFFSET_TREE + 8 ); -} - -/* These functions are used for OTS addresses. */ - -/* - * Specify which Merkle leaf we're working on; that is, which OTS keypair - * we're talking about. - */ -void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { - ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; -} - -/* - * Copy the layer, tree and keypair fields of the address structure. This is - * used when we're doing multiple things within the same OTS keypair - */ -void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { - memcpy( out, in, SPX_OFFSET_TREE + 8 ); - ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; -} - -/* - * Specify which Merkle chain within the OTS we're working with - * (the chain address) - */ -void set_chain_addr(uint32_t addr[8], uint32_t chain) { - ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; -} - -/* - * Specify where in the Merkle chain we are -* (the hash address) - */ -void set_hash_addr(uint32_t addr[8], uint32_t hash) { - ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; -} - -/* These functions are used for all hash tree addresses (including FORS). */ - -/* - * Specify the height of the node in the Merkle/FORS tree we are in - * (the tree height) - */ -void set_tree_height(uint32_t addr[8], uint32_t tree_height) { - ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; -} - -/* - * Specify the distance from the left edge of the node in the Merkle/FORS tree - * (the tree index) - */ -void set_tree_index(uint32_t addr[8], uint32_t tree_index) { - u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/address.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/address.h deleted file mode 100644 index 24a84eb40c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/address.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef SPX_ADDRESS_H -#define SPX_ADDRESS_H - -#include - -#include "params.h" - -/* The hash types that are passed to set_type */ -#define SPX_ADDR_TYPE_WOTS 0 -#define SPX_ADDR_TYPE_WOTSPK 1 -#define SPX_ADDR_TYPE_HASHTREE 2 -#define SPX_ADDR_TYPE_FORSTREE 3 -#define SPX_ADDR_TYPE_FORSPK 4 -#define SPX_ADDR_TYPE_WOTSPRF 5 -#define SPX_ADDR_TYPE_FORSPRF 6 - -#define set_layer_addr SPX_NAMESPACE(set_layer_addr) -void set_layer_addr(uint32_t addr[8], uint32_t layer); - -#define set_tree_addr SPX_NAMESPACE(set_tree_addr) -void set_tree_addr(uint32_t addr[8], uint64_t tree); - -#define set_type SPX_NAMESPACE(set_type) -void set_type(uint32_t addr[8], uint32_t type); - -/* Copies the layer and tree part of one address into the other */ -#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) -void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for WOTS and FORS addresses. */ - -#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) -void set_keypair_addr(uint32_t addr[8], uint32_t keypair); - -#define set_chain_addr SPX_NAMESPACE(set_chain_addr) -void set_chain_addr(uint32_t addr[8], uint32_t chain); - -#define set_hash_addr SPX_NAMESPACE(set_hash_addr) -void set_hash_addr(uint32_t addr[8], uint32_t hash); - -#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) -void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for all hash tree addresses (including FORS). */ - -#define set_tree_height SPX_NAMESPACE(set_tree_height) -void set_tree_height(uint32_t addr[8], uint32_t tree_height); - -#define set_tree_index SPX_NAMESPACE(set_tree_index) -void set_tree_index(uint32_t addr[8], uint32_t tree_index); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/api.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/api.h deleted file mode 100644 index 3c18614b37..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/api.h +++ /dev/null @@ -1,77 +0,0 @@ -#ifndef PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_API_H -#define PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_API_H - -#include -#include - -#define PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_CRYPTO_ALGNAME "SPHINCS+-haraka-192f-robust" - -#define PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_CRYPTO_SECRETKEYBYTES 96 -#define PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_CRYPTO_PUBLICKEYBYTES 48 -#define PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_CRYPTO_BYTES 35664 - -#define PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_CRYPTO_SEEDBYTES 72 - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, - const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk); -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/context.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/context.h deleted file mode 100644 index f03446b9cb..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/context.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef SPX_CONTEXT_H -#define SPX_CONTEXT_H - -#include - -#include "immintrin.h" -#include "params.h" - -typedef struct { - uint8_t pub_seed[SPX_N]; - uint8_t sk_seed[SPX_N]; - - __m128i rc[40]; -} spx_ctx; - -#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) -void initialize_hash_function(spx_ctx *ctx); - -#define free_hash_function SPX_NAMESPACE(free_hash_function) -void free_hash_function(spx_ctx *ctx); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/context_haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/context_haraka.c deleted file mode 100644 index f1cd7e3664..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/context_haraka.c +++ /dev/null @@ -1,11 +0,0 @@ -#include "context.h" -#include "haraka.h" - -void initialize_hash_function(spx_ctx *ctx) { - tweak_constants(ctx); -} - -// we don't support heap-based haraka right now -void free_hash_function(spx_ctx *ctx) { - (void)ctx; // suppress unused variable warnings -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/fors.c b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/fors.c deleted file mode 100644 index f1b0639cfc..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/fors.c +++ /dev/null @@ -1,202 +0,0 @@ -#include -#include -#include - -#include "fors.h" - -#include "address.h" -#include "hash.h" -#include "hashx4.h" -#include "thash.h" -#include "thashx4.h" -#include "utils.h" -#include "utilsx4.h" - -static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, - uint32_t fors_leaf_addr[8]) { - prf_addr(sk, ctx, fors_leaf_addr); -} - -static void fors_gen_skx4(unsigned char *sk0, - unsigned char *sk1, - unsigned char *sk2, - unsigned char *sk3, const spx_ctx *ctx, - uint32_t fors_leaf_addrx4[4 * 8]) { - prf_addrx4(sk0, sk1, sk2, sk3, - ctx, fors_leaf_addrx4); -} - -static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, - const spx_ctx *ctx, - uint32_t fors_leaf_addr[8]) { - thash(leaf, sk, 1, ctx, fors_leaf_addr); -} - -static void fors_sk_to_leafx4(unsigned char *leaf0, - unsigned char *leaf1, - unsigned char *leaf2, - unsigned char *leaf3, - const unsigned char *sk0, - const unsigned char *sk1, - const unsigned char *sk2, - const unsigned char *sk3, - const spx_ctx *ctx, - uint32_t fors_leaf_addrx4[4 * 8]) { - thashx4(leaf0, leaf1, leaf2, leaf3, - sk0, sk1, sk2, sk3, - 1, ctx, fors_leaf_addrx4); -} - -struct fors_gen_leaf_info { - uint32_t leaf_addrx[4 * 8]; -}; - -static void fors_gen_leafx4(unsigned char *leaf, - const spx_ctx *ctx, - uint32_t addr_idx, void *info) { - struct fors_gen_leaf_info *fors_info = info; - uint32_t *fors_leaf_addrx4 = fors_info->leaf_addrx; - unsigned int j; - - /* Only set the parts that the caller doesn't set */ - for (j = 0; j < 4; j++) { - set_tree_index(fors_leaf_addrx4 + j * 8, addr_idx + j); - set_type(fors_leaf_addrx4 + j * 8, SPX_ADDR_TYPE_FORSPRF); - } - - fors_gen_skx4(leaf + 0 * SPX_N, - leaf + 1 * SPX_N, - leaf + 2 * SPX_N, - leaf + 3 * SPX_N, - ctx, fors_leaf_addrx4); - - for (j = 0; j < 4; j++) { - set_type(fors_leaf_addrx4 + j * 8, SPX_ADDR_TYPE_FORSTREE); - } - - fors_sk_to_leafx4(leaf + 0 * SPX_N, - leaf + 1 * SPX_N, - leaf + 2 * SPX_N, - leaf + 3 * SPX_N, - leaf + 0 * SPX_N, - leaf + 1 * SPX_N, - leaf + 2 * SPX_N, - leaf + 3 * SPX_N, - ctx, fors_leaf_addrx4); -} - -/** - * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - * Assumes indices has space for SPX_FORS_TREES integers. - */ -static void message_to_indices(uint32_t *indices, const unsigned char *m) { - unsigned int i, j; - unsigned int offset = 0; - - for (i = 0; i < SPX_FORS_TREES; i++) { - indices[i] = 0; - for (j = 0; j < SPX_FORS_HEIGHT; j++) { - indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); - offset++; - } - } -} - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -void fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]) { - uint32_t indices[SPX_FORS_TREES]; - unsigned char roots[SPX_FORS_TREES * SPX_N]; - uint32_t fors_tree_addr[4 * 8] = {0}; - struct fors_gen_leaf_info fors_info = {0}; - uint32_t *fors_leaf_addr = fors_info.leaf_addrx; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - for (i = 0; i < 4; i++) { - copy_keypair_addr(fors_tree_addr + 8 * i, fors_addr); - set_type(fors_tree_addr + 8 * i, SPX_ADDR_TYPE_FORSTREE); - copy_keypair_addr(fors_leaf_addr + 8 * i, fors_addr); - } - copy_keypair_addr(fors_pk_addr, fors_addr); - set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < SPX_FORS_TREES; i++) { - idx_offset = i * (1 << SPX_FORS_HEIGHT); - - set_tree_height(fors_tree_addr, 0); - set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Include the secret key part that produces the selected leaf node. */ - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); - fors_gen_sk(sig, ctx, fors_tree_addr); - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); - sig += SPX_N; - - /* Compute the authentication path for this leaf node. */ - treehashx4(roots + i * SPX_N, sig, ctx, - indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx4, - fors_tree_addr, &fors_info); - - sig += SPX_N * SPX_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); -} - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -void fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]) { - uint32_t indices[SPX_FORS_TREES]; - unsigned char roots[SPX_FORS_TREES * SPX_N]; - unsigned char leaf[SPX_N]; - uint32_t fors_tree_addr[8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - copy_keypair_addr(fors_tree_addr, fors_addr); - copy_keypair_addr(fors_pk_addr, fors_addr); - - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); - set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < SPX_FORS_TREES; i++) { - idx_offset = i * (1 << SPX_FORS_HEIGHT); - - set_tree_height(fors_tree_addr, 0); - set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Derive the leaf from the included secret key part. */ - fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); - sig += SPX_N; - - /* Derive the corresponding root node of this tree. */ - compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, - sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); - sig += SPX_N * SPX_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/fors.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/fors.h deleted file mode 100644 index 509140a178..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/fors.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef SPX_FORS_H -#define SPX_FORS_H - -#include - -#include "context.h" -#include "params.h" - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -#define fors_sign SPX_NAMESPACE(fors_sign) -void fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]); - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) -void fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/haraka.c deleted file mode 100644 index b414b691d7..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/haraka.c +++ /dev/null @@ -1,702 +0,0 @@ -/* -Plain C implementation of the Haraka256 and Haraka512 permutations. -*/ -#include -#include -#include -#include -#include - -#include "haraka.h" -#include "harakax4.h" -#include "utils.h" - -#define HARAKAS_RATE 32 - -#define u64 unsigned long -#define u128 __m128i - -#define LOAD(src) _mm_loadu_si128((u128 *)(src)) -#define STORE(dest,src) _mm_storeu_si128((u128 *)(dest),src) - -#define XOR128(a, b) _mm_xor_si128(a, b) - -#define AES2(s0, s1, rci) \ - s0 = _mm_aesenc_si128(s0, *(rci)); \ - (s1) = _mm_aesenc_si128(s1, *((rci) + 1)); \ - (s0) = _mm_aesenc_si128(s0, *((rci) + 2)); \ - (s1) = _mm_aesenc_si128(s1, *((rci) + 3)); - -#define AES2_4x(s0, s1, s2, s3, rci) \ - AES2((s0)[0], (s0)[1], rci); \ - AES2((s1)[0], (s1)[1], rci); \ - AES2((s2)[0], (s2)[1], rci); \ - AES2((s3)[0], (s3)[1], rci); - -#define AES4(s0, s1, s2, s3, rci) \ - s0 = _mm_aesenc_si128(s0, *(rci)); \ - (s1) = _mm_aesenc_si128(s1, *((rci) + 1)); \ - (s2) = _mm_aesenc_si128(s2, *((rci) + 2)); \ - (s3) = _mm_aesenc_si128(s3, *((rci) + 3)); \ - (s0) = _mm_aesenc_si128(s0, *((rci) + 4)); \ - (s1) = _mm_aesenc_si128(s1, *((rci) + 5)); \ - (s2) = _mm_aesenc_si128(s2, *((rci) + 6)); \ - (s3) = _mm_aesenc_si128(s3, *((rci) + 7)); - -#define AES4_4x(s0, s1, s2, s3, rci) \ - AES4((s0)[0], (s0)[1], (s0)[2], (s0)[3], rci); \ - AES4((s1)[0], (s1)[1], (s1)[2], (s1)[3], rci); \ - AES4((s2)[0], (s2)[1], (s2)[2], (s2)[3], rci); \ - AES4((s3)[0], (s3)[1], (s3)[2], (s3)[3], rci); - -#define MIX2(s0, s1) \ - tmp = _mm_unpacklo_epi32(s0, s1); \ - (s1) = _mm_unpackhi_epi32(s0, s1); \ - (s0) = tmp; - -#define MIX4(s0, s1, s2, s3) \ - tmp = _mm_unpacklo_epi32(s0, s1); \ - (s0) = _mm_unpackhi_epi32(s0, s1); \ - (s1) = _mm_unpacklo_epi32(s2, s3); \ - (s2) = _mm_unpackhi_epi32(s2, s3); \ - (s3) = _mm_unpacklo_epi32(s0, s2); \ - (s0) = _mm_unpackhi_epi32(s0, s2); \ - (s2) = _mm_unpackhi_epi32(s1, tmp); \ - (s1) = _mm_unpacklo_epi32(s1, tmp); - -#define TRUNCSTORE(out, s0, s1, s2, s3) \ - _mm_storeu_si128((u128 *)(out), \ - _mm_castpd_si128(_mm_shuffle_pd(_mm_castsi128_pd(s0), _mm_castsi128_pd(s1), 3))); \ - _mm_storeu_si128((u128 *)((out) + 16), \ - _mm_castpd_si128(_mm_shuffle_pd(_mm_castsi128_pd(s2), _mm_castsi128_pd(s3), 0))); - -static void load_haraka_constants(u128 *rc) { - rc[0] = _mm_set_epi32((int)0x0684704c, (int)0xe620c00a, (int)0xb2c5fef0, (int)0x75817b9d); - rc[1] = _mm_set_epi32((int)0x8b66b4e1, (int)0x88f3a06b, (int)0x640f6ba4, (int)0x2f08f717); - rc[2] = _mm_set_epi32((int)0x3402de2d, (int)0x53f28498, (int)0xcf029d60, (int)0x9f029114); - rc[3] = _mm_set_epi32((int)0x0ed6eae6, (int)0x2e7b4f08, (int)0xbbf3bcaf, (int)0xfd5b4f79); - rc[4] = _mm_set_epi32((int)0xcbcfb0cb, (int)0x4872448b, (int)0x79eecd1c, (int)0xbe397044); - rc[5] = _mm_set_epi32((int)0x7eeacdee, (int)0x6e9032b7, (int)0x8d5335ed, (int)0x2b8a057b); - rc[6] = _mm_set_epi32((int)0x67c28f43, (int)0x5e2e7cd0, (int)0xe2412761, (int)0xda4fef1b); - rc[7] = _mm_set_epi32((int)0x2924d9b0, (int)0xafcacc07, (int)0x675ffde2, (int)0x1fc70b3b); - rc[8] = _mm_set_epi32((int)0xab4d63f1, (int)0xe6867fe9, (int)0xecdb8fca, (int)0xb9d465ee); - rc[9] = _mm_set_epi32((int)0x1c30bf84, (int)0xd4b7cd64, (int)0x5b2a404f, (int)0xad037e33); - rc[10] = _mm_set_epi32((int)0xb2cc0bb9, (int)0x941723bf, (int)0x69028b2e, (int)0x8df69800); - rc[11] = _mm_set_epi32((int)0xfa0478a6, (int)0xde6f5572, (int)0x4aaa9ec8, (int)0x5c9d2d8a); - rc[12] = _mm_set_epi32((int)0xdfb49f2b, (int)0x6b772a12, (int)0x0efa4f2e, (int)0x29129fd4); - rc[13] = _mm_set_epi32((int)0x1ea10344, (int)0xf449a236, (int)0x32d611ae, (int)0xbb6a12ee); - rc[14] = _mm_set_epi32((int)0xaf044988, (int)0x4b050084, (int)0x5f9600c9, (int)0x9ca8eca6); - rc[15] = _mm_set_epi32((int)0x21025ed8, (int)0x9d199c4f, (int)0x78a2c7e3, (int)0x27e593ec); - rc[16] = _mm_set_epi32((int)0xbf3aaaf8, (int)0xa759c9b7, (int)0xb9282ecd, (int)0x82d40173); - rc[17] = _mm_set_epi32((int)0x6260700d, (int)0x6186b017, (int)0x37f2efd9, (int)0x10307d6b); - rc[18] = _mm_set_epi32((int)0x5aca45c2, (int)0x21300443, (int)0x81c29153, (int)0xf6fc9ac6); - rc[19] = _mm_set_epi32((int)0x9223973c, (int)0x226b68bb, (int)0x2caf92e8, (int)0x36d1943a); - rc[20] = _mm_set_epi32((int)0xd3bf9238, (int)0x225886eb, (int)0x6cbab958, (int)0xe51071b4); - rc[21] = _mm_set_epi32((int)0xdb863ce5, (int)0xaef0c677, (int)0x933dfddd, (int)0x24e1128d); - rc[22] = _mm_set_epi32((int)0xbb606268, (int)0xffeba09c, (int)0x83e48de3, (int)0xcb2212b1); - rc[23] = _mm_set_epi32((int)0x734bd3dc, (int)0xe2e4d19c, (int)0x2db91a4e, (int)0xc72bf77d); - rc[24] = _mm_set_epi32((int)0x43bb47c3, (int)0x61301b43, (int)0x4b1415c4, (int)0x2cb3924e); - rc[25] = _mm_set_epi32((int)0xdba775a8, (int)0xe707eff6, (int)0x03b231dd, (int)0x16eb6899); - rc[26] = _mm_set_epi32((int)0x6df3614b, (int)0x3c755977, (int)0x8e5e2302, (int)0x7eca472c); - rc[27] = _mm_set_epi32((int)0xcda75a17, (int)0xd6de7d77, (int)0x6d1be5b9, (int)0xb88617f9); - rc[28] = _mm_set_epi32((int)0xec6b43f0, (int)0x6ba8e9aa, (int)0x9d6c069d, (int)0xa946ee5d); - rc[29] = _mm_set_epi32((int)0xcb1e6950, (int)0xf957332b, (int)0xa2531159, (int)0x3bf327c1); - rc[30] = _mm_set_epi32((int)0x2cee0c75, (int)0x00da619c, (int)0xe4ed0353, (int)0x600ed0d9); - rc[31] = _mm_set_epi32((int)0xf0b1a5a1, (int)0x96e90cab, (int)0x80bbbabc, (int)0x63a4a350); - rc[32] = _mm_set_epi32((int)0xae3db102, (int)0x5e962988, (int)0xab0dde30, (int)0x938dca39); - rc[33] = _mm_set_epi32((int)0x17bb8f38, (int)0xd554a40b, (int)0x8814f3a8, (int)0x2e75b442); - rc[34] = _mm_set_epi32((int)0x34bb8a5b, (int)0x5f427fd7, (int)0xaeb6b779, (int)0x360a16f6); - rc[35] = _mm_set_epi32((int)0x26f65241, (int)0xcbe55438, (int)0x43ce5918, (int)0xffbaafde); - rc[36] = _mm_set_epi32((int)0x4ce99a54, (int)0xb9f3026a, (int)0xa2ca9cf7, (int)0x839ec978); - rc[37] = _mm_set_epi32((int)0xae51a51a, (int)0x1bdff7be, (int)0x40c06e28, (int)0x22901235); - rc[38] = _mm_set_epi32((int)0xa0c1613c, (int)0xba7ed22b, (int)0xc173bc0f, (int)0x48a659cf); - rc[39] = _mm_set_epi32((int)0x756acc03, (int)0x02288288, (int)0x4ad6bdfd, (int)0xe9c59da1); -} - -void tweak_constants(spx_ctx *ctx) { - int i; - unsigned char buf[40 * 16]; - - /* Use the standard constants to generate tweaked ones. */ - load_haraka_constants(ctx->rc); - - /* Constants for pk.seed */ - haraka_S(buf, 40 * 16, ctx->pub_seed, SPX_N, ctx); - - /* Tweak constants with the pub_seed */ - for (i = 0; i < 40; i++) { - ctx->rc[i] = LOAD(buf + i * 16); - } -} - -static void haraka_S_absorb(unsigned char *s, unsigned int r, - const unsigned char *m, unsigned long long mlen, - unsigned char p, const spx_ctx *ctx) { - unsigned long long i; - PQCLEAN_VLA(unsigned char, t, r); - - while (mlen >= r) { - // XOR block to state - STORE(s, XOR128(LOAD(s), LOAD(m))); - STORE(s + 16, XOR128(LOAD(s + 16), LOAD(m + 16))); - haraka512_perm(s, s, ctx); - 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; - STORE(s, XOR128(LOAD(s), LOAD(t))); - STORE(s + 16, XOR128(LOAD(s + 16), LOAD(t + 16))); -} - -static void haraka_S_absorb4x(unsigned char *s, - unsigned int r, - const unsigned char *m0, - const unsigned char *m1, - const unsigned char *m2, - const unsigned char *m3, - unsigned long long int mlen, - unsigned char p, - const spx_ctx *ctx) { - unsigned long long i; - PQCLEAN_VLA(unsigned char, t0, r); - PQCLEAN_VLA(unsigned char, t1, r); - PQCLEAN_VLA(unsigned char, t2, r); - PQCLEAN_VLA(unsigned char, t3, r); - - while (mlen >= r) { - // XOR block to state - STORE(s, XOR128(LOAD(s), LOAD(m0))); - STORE(s + 16, XOR128(LOAD(s + 16), LOAD(m0 + 16))); - STORE(s + 64, XOR128(LOAD(s + 64), LOAD(m1))); - STORE(s + 80, XOR128(LOAD(s + 80), LOAD(m1 + 16))); - STORE(s + 128, XOR128(LOAD(s + 128), LOAD(m2))); - STORE(s + 144, XOR128(LOAD(s + 144), LOAD(m2 + 16))); - STORE(s + 192, XOR128(LOAD(s + 192), LOAD(m3))); - STORE(s + 208, XOR128(LOAD(s + 208), LOAD(m3 + 16))); - - haraka512_perm_x4(s, s, ctx); - mlen -= r; - m0 += r; - m1 += r; - m2 += r; - m3 += r; - } - - for (i = 0; i < r; ++i) { - t0[i] = 0; - t1[i] = 0; - t2[i] = 0; - t3[i] = 0; - } - for (i = 0; i < mlen; ++i) { - t0[i] = m0[i]; - t1[i] = m1[i]; - t2[i] = m2[i]; - t3[i] = m3[i]; - } - - t0[i] = p; - t1[i] = p; - t2[i] = p; - t3[i] = p; - - t0[r - 1] |= 128; - t1[r - 1] |= 128; - t2[r - 1] |= 128; - t3[r - 1] |= 128; - - STORE(s, XOR128(LOAD(s), LOAD(t0))); - STORE(s + 16, XOR128(LOAD(s + 16), LOAD(t0 + 16))); - STORE(s + 64, XOR128(LOAD(s + 64), LOAD(t1))); - STORE(s + 80, XOR128(LOAD(s + 80), LOAD(t1 + 16))); - STORE(s + 128, XOR128(LOAD(s + 128), LOAD(t2))); - STORE(s + 144, XOR128(LOAD(s + 144), LOAD(t2 + 16))); - STORE(s + 192, XOR128(LOAD(s + 192), LOAD(t3))); - STORE(s + 208, XOR128(LOAD(s + 208), LOAD(t3 + 16))); -} - -static void haraka_S_squeezeblocks(unsigned char *h, unsigned long long nblocks, - unsigned char *s, unsigned int r, - const spx_ctx *ctx) { - while (nblocks > 0) { - haraka512_perm(s, s, ctx); - STORE(h, LOAD(s)); - STORE(h + 16, LOAD(s + 16)); - h += r; - nblocks--; - } -} - -static void haraka_S_squeezeblocks4x(unsigned char *h0, - unsigned char *h1, - unsigned char *h2, - unsigned char *h3, - unsigned long long nblocks, - unsigned char *s, - unsigned int r, - const spx_ctx *ctx) { - while (nblocks > 0) { - haraka512_perm_x4(s, s, ctx); - STORE(h0, LOAD(s)); - STORE(h0 + 16, LOAD(s + 16)); - STORE(h1, LOAD(s + 64)); - STORE(h1 + 16, LOAD(s + 80)); - STORE(h2, LOAD(s + 128)); - STORE(h2 + 16, LOAD(s + 144)); - STORE(h3, LOAD(s + 192)); - STORE(h3 + 16, LOAD(s + 208)); - h0 += r; - h1 += r; - h2 += r; - h3 += r; - nblocks--; - } -} - -void haraka_S_inc_init(uint8_t *s_inc) { - size_t i; - - for (i = 0; i < 64; i++) { - s_inc[i] = 0; - } - s_inc[64] = 0; -} - -void haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, - const spx_ctx *ctx) { - size_t i; - - /* Recall that s_inc[64] is the non-absorbed bytes xored into the state */ - while (mlen + s_inc[64] >= HARAKAS_RATE) { - for (i = 0; i < (size_t)(HARAKAS_RATE - s_inc[64]); i++) { - /* Take the i'th byte from message - xor with the s_inc[64] + i'th byte of the state */ - s_inc[s_inc[64] + i] ^= m[i]; - } - mlen -= (size_t)(HARAKAS_RATE - s_inc[64]); - m += HARAKAS_RATE - s_inc[64]; - s_inc[64] = 0; - - haraka512_perm(s_inc, s_inc, ctx); - } - - for (i = 0; i < mlen; i++) { - s_inc[s_inc[64] + i] ^= m[i]; - } - s_inc[64] += (uint8_t)mlen; -} - -void haraka_S_inc_finalize(uint8_t *s_inc) { - /* After haraka_S_inc_absorb, we are guaranteed that s_inc[64] < HARAKAS_RATE, - so we can always use one more byte for p in the current state. */ - s_inc[s_inc[64]] ^= 0x1F; - s_inc[HARAKAS_RATE - 1] ^= 128; - s_inc[64] = 0; -} - -void haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, - const spx_ctx *ctx) { - size_t i; - - /* First consume any bytes we still have sitting around */ - for (i = 0; i < outlen && i < s_inc[64]; i++) { - /* There are s_inc[64] bytes left, so r - s_inc[64] is the first - available byte. We consume from there, i.e., up to r. */ - out[i] = (uint8_t)s_inc[(HARAKAS_RATE - s_inc[64] + i)]; - } - out += i; - outlen -= i; - s_inc[64] -= (uint8_t)i; - - /* Then squeeze the remaining necessary blocks */ - while (outlen > 0) { - haraka512_perm(s_inc, s_inc, ctx); - - for (i = 0; i < outlen && i < HARAKAS_RATE; i++) { - out[i] = s_inc[i]; - } - out += i; - outlen -= i; - s_inc[64] = (uint8_t)(HARAKAS_RATE - i); - } -} - -void haraka_S(unsigned char *out, unsigned long long outlen, - const unsigned char *in, unsigned long long inlen, - const spx_ctx *ctx) { - unsigned long long i; - unsigned char s[64]; - unsigned char d[32]; - - for (i = 0; i < 64; i++) { - s[i] = 0; - } - haraka_S_absorb(s, HARAKAS_RATE, in, inlen, 0x1F, ctx); - - haraka_S_squeezeblocks(out, outlen / HARAKAS_RATE, s, HARAKAS_RATE, ctx); - out += (outlen / HARAKAS_RATE) * HARAKAS_RATE; - - if (outlen % HARAKAS_RATE) { - haraka_S_squeezeblocks(d, 1, s, HARAKAS_RATE, ctx); - for (i = 0; i < outlen % HARAKAS_RATE; i++) { - out[i] = d[i]; - } - } -} - -void haraka_Sx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned long long outlen, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - unsigned long long inlen, - const spx_ctx *ctx) { - unsigned long long i; - unsigned char s[64 * 4]; - unsigned char d0[32]; - unsigned char d1[32]; - unsigned char d2[32]; - unsigned char d3[32]; - - for (i = 0; i < 64 * 4; i++) { - s[i] = 0; - } - haraka_S_absorb4x(s, HARAKAS_RATE, in0, in1, in2, in3, inlen, 0x1F, ctx); - - haraka_S_squeezeblocks4x(out0, out1, out2, out3, outlen / HARAKAS_RATE, s, - HARAKAS_RATE, ctx); - out0 += (outlen / HARAKAS_RATE) * HARAKAS_RATE; - out1 += (outlen / HARAKAS_RATE) * HARAKAS_RATE; - out2 += (outlen / HARAKAS_RATE) * HARAKAS_RATE; - out3 += (outlen / HARAKAS_RATE) * HARAKAS_RATE; - - if (outlen % HARAKAS_RATE) { - haraka_S_squeezeblocks4x(d0, d1, d2, d3, 1, s, HARAKAS_RATE, ctx); - for (i = 0; i < outlen % HARAKAS_RATE; i++) { - out0[i] = d0[i]; - out1[i] = d1[i]; - out2[i] = d2[i]; - out3[i] = d3[i]; - } - } -} - -void haraka512_perm(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx) { - u128 s[4], tmp; - - s[0] = LOAD(in); - s[1] = LOAD(in + 16); - s[2] = LOAD(in + 32); - s[3] = LOAD(in + 48); - - AES4(s[0], s[1], s[2], s[3], ctx->rc); - MIX4(s[0], s[1], s[2], s[3]); - - AES4(s[0], s[1], s[2], s[3], ctx->rc + 8); - MIX4(s[0], s[1], s[2], s[3]); - - AES4(s[0], s[1], s[2], s[3], ctx->rc + 16); - MIX4(s[0], s[1], s[2], s[3]); - - AES4(s[0], s[1], s[2], s[3], ctx->rc + 24); - MIX4(s[0], s[1], s[2], s[3]); - - AES4(s[0], s[1], s[2], s[3], ctx->rc + 32); - MIX4(s[0], s[1], s[2], s[3]); - - STORE(out, s[0]); - STORE(out + 16, s[1]); - STORE(out + 32, s[2]); - STORE(out + 48, s[3]); -} - -void haraka512_perm_x4(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx) { - u128 s[4][4], tmp; - - s[0][0] = LOAD(in); - s[0][1] = LOAD(in + 16); - s[0][2] = LOAD(in + 32); - s[0][3] = LOAD(in + 48); - s[1][0] = LOAD(in + 64); - s[1][1] = LOAD(in + 80); - s[1][2] = LOAD(in + 96); - s[1][3] = LOAD(in + 112); - s[2][0] = LOAD(in + 128); - s[2][1] = LOAD(in + 144); - s[2][2] = LOAD(in + 160); - s[2][3] = LOAD(in + 176); - s[3][0] = LOAD(in + 192); - s[3][1] = LOAD(in + 208); - s[3][2] = LOAD(in + 224); - s[3][3] = LOAD(in + 240); - - AES4_4x(s[0], s[1], s[2], s[3], ctx->rc); - MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); - MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); - MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); - MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - - AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 8); - MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); - MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); - MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); - MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - - AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 16); - MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); - MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); - MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); - MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - - AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 24); - MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); - MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); - MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); - MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - - AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 32); - MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); - MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); - MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); - MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - - STORE(out, s[0][0]); - STORE(out + 16, s[0][1]); - STORE(out + 32, s[0][2]); - STORE(out + 48, s[0][3]); - STORE(out + 64, s[1][0]); - STORE(out + 80, s[1][1]); - STORE(out + 96, s[1][2]); - STORE(out + 112, s[1][3]); - STORE(out + 128, s[2][0]); - STORE(out + 144, s[2][1]); - STORE(out + 160, s[2][2]); - STORE(out + 176, s[2][3]); - STORE(out + 192, s[3][0]); - STORE(out + 208, s[3][1]); - STORE(out + 224, s[3][2]); - STORE(out + 240, s[3][3]); -} - -void haraka512(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx) { - u128 s[4], tmp; - - s[0] = LOAD(in); - s[1] = LOAD(in + 16); - s[2] = LOAD(in + 32); - s[3] = LOAD(in + 48); - - AES4(s[0], s[1], s[2], s[3], ctx->rc); - MIX4(s[0], s[1], s[2], s[3]); - - AES4(s[0], s[1], s[2], s[3], ctx->rc + 8); - MIX4(s[0], s[1], s[2], s[3]); - - AES4(s[0], s[1], s[2], s[3], ctx->rc + 16); - MIX4(s[0], s[1], s[2], s[3]); - - AES4(s[0], s[1], s[2], s[3], ctx->rc + 24); - MIX4(s[0], s[1], s[2], s[3]); - - AES4(s[0], s[1], s[2], s[3], ctx->rc + 32); - MIX4(s[0], s[1], s[2], s[3]); - - s[0] = XOR128(s[0], LOAD(in)); - s[1] = XOR128(s[1], LOAD(in + 16)); - s[2] = XOR128(s[2], LOAD(in + 32)); - s[3] = XOR128(s[3], LOAD(in + 48)); - - // truncate and store result - TRUNCSTORE(out, s[0], s[1], s[2], s[3]); -} - -void haraka512x4(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx) { - u128 s[4][4], tmp; - - s[0][0] = LOAD(in); - s[0][1] = LOAD(in + 16); - s[0][2] = LOAD(in + 32); - s[0][3] = LOAD(in + 48); - s[1][0] = LOAD(in + 64); - s[1][1] = LOAD(in + 80); - s[1][2] = LOAD(in + 96); - s[1][3] = LOAD(in + 112); - s[2][0] = LOAD(in + 128); - s[2][1] = LOAD(in + 144); - s[2][2] = LOAD(in + 160); - s[2][3] = LOAD(in + 176); - s[3][0] = LOAD(in + 192); - s[3][1] = LOAD(in + 208); - s[3][2] = LOAD(in + 224); - s[3][3] = LOAD(in + 240); - - AES4_4x(s[0], s[1], s[2], s[3], ctx->rc); - MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); - MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); - MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); - MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - - AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 8); - MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); - MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); - MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); - MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - - AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 16); - MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); - MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); - MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); - MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - - AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 24); - MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); - MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); - MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); - MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - - AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 32); - MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); - MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); - MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); - MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - - s[0][0] = XOR128(s[0][0], LOAD(in)); - s[0][1] = XOR128(s[0][1], LOAD(in + 16)); - s[0][2] = XOR128(s[0][2], LOAD(in + 32)); - s[0][3] = XOR128(s[0][3], LOAD(in + 48)); - s[1][0] = XOR128(s[1][0], LOAD(in + 64)); - s[1][1] = XOR128(s[1][1], LOAD(in + 80)); - s[1][2] = XOR128(s[1][2], LOAD(in + 96)); - s[1][3] = XOR128(s[1][3], LOAD(in + 112)); - s[2][0] = XOR128(s[2][0], LOAD(in + 128)); - s[2][1] = XOR128(s[2][1], LOAD(in + 144)); - s[2][2] = XOR128(s[2][2], LOAD(in + 160)); - s[2][3] = XOR128(s[2][3], LOAD(in + 176)); - s[3][0] = XOR128(s[3][0], LOAD(in + 192)); - s[3][1] = XOR128(s[3][1], LOAD(in + 208)); - s[3][2] = XOR128(s[3][2], LOAD(in + 224)); - s[3][3] = XOR128(s[3][3], LOAD(in + 240)); - - TRUNCSTORE(out, s[0][0], s[0][1], s[0][2], s[0][3]); - TRUNCSTORE((out + 32), s[1][0], s[1][1], s[1][2], s[1][3]); - TRUNCSTORE((out + 64), s[2][0], s[2][1], s[2][2], s[2][3]); - TRUNCSTORE((out + 96), s[3][0], s[3][1], s[3][2], s[3][3]); -} - -void haraka256(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx) { - u128 s[2], tmp; - - s[0] = LOAD(in); - s[1] = LOAD(in + 16); - - AES2(s[0], s[1], ctx->rc); - MIX2(s[0], s[1]); - - AES2(s[0], s[1], ctx->rc + 4); - MIX2(s[0], s[1]); - - AES2(s[0], s[1], ctx->rc + 8); - MIX2(s[0], s[1]); - - AES2(s[0], s[1], ctx->rc + 12); - MIX2(s[0], s[1]); - - AES2(s[0], s[1], ctx->rc + 16); - MIX2(s[0], s[1]); - - s[0] = XOR128(s[0], LOAD(in)); - s[1] = XOR128(s[1], LOAD(in + 16)); - - STORE(out, s[0]); - STORE(out + 16, s[1]); -} - -void haraka256x4(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx) { - u128 s[4][2], tmp; - - s[0][0] = LOAD(in); - s[0][1] = LOAD(in + 16); - s[1][0] = LOAD(in + 32); - s[1][1] = LOAD(in + 48); - s[2][0] = LOAD(in + 64); - s[2][1] = LOAD(in + 80); - s[3][0] = LOAD(in + 96); - s[3][1] = LOAD(in + 112); - - // Round 1 - AES2_4x(s[0], s[1], s[2], s[3], ctx->rc); - - MIX2(s[0][0], s[0][1]); - MIX2(s[1][0], s[1][1]); - MIX2(s[2][0], s[2][1]); - MIX2(s[3][0], s[3][1]); - - // Round 2 - AES2_4x(s[0], s[1], s[2], s[3], ctx->rc + 4); - - MIX2(s[0][0], s[0][1]); - MIX2(s[1][0], s[1][1]); - MIX2(s[2][0], s[2][1]); - MIX2(s[3][0], s[3][1]); - - // Round 3 - AES2_4x(s[0], s[1], s[2], s[3], ctx->rc + 8); - - MIX2(s[0][0], s[0][1]); - MIX2(s[1][0], s[1][1]); - MIX2(s[2][0], s[2][1]); - MIX2(s[3][0], s[3][1]); - - // Round 4 - AES2_4x(s[0], s[1], s[2], s[3], ctx->rc + 12); - - MIX2(s[0][0], s[0][1]); - MIX2(s[1][0], s[1][1]); - MIX2(s[2][0], s[2][1]); - MIX2(s[3][0], s[3][1]); - - // Round 5 - AES2_4x(s[0], s[1], s[2], s[3], ctx->rc + 16); - - MIX2(s[0][0], s[0][1]); - MIX2(s[1][0], s[1][1]); - MIX2(s[2][0], s[2][1]); - MIX2(s[3][0], s[3][1]); - - // Feed Forward - s[0][0] = _mm_xor_si128(s[0][0], LOAD(in)); - s[0][1] = _mm_xor_si128(s[0][1], LOAD(in + 16)); - s[1][0] = _mm_xor_si128(s[1][0], LOAD(in + 32)); - s[1][1] = _mm_xor_si128(s[1][1], LOAD(in + 48)); - s[2][0] = _mm_xor_si128(s[2][0], LOAD(in + 64)); - s[2][1] = _mm_xor_si128(s[2][1], LOAD(in + 80)); - s[3][0] = _mm_xor_si128(s[3][0], LOAD(in + 96)); - s[3][1] = _mm_xor_si128(s[3][1], LOAD(in + 112)); - - STORE(out, s[0][0]); - STORE(out + 16, s[0][1]); - STORE(out + 32, s[1][0]); - STORE(out + 48, s[1][1]); - STORE(out + 64, s[2][0]); - STORE(out + 80, s[2][1]); - STORE(out + 96, s[3][0]); - STORE(out + 112, s[3][1]); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/haraka.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/haraka.h deleted file mode 100644 index 737cb6065f..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/haraka.h +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef SPX_HARAKA_H -#define SPX_HARAKA_H - -#include "context.h" -#include "params.h" - -/* Tweak constants with seed */ -#define tweak_constants SPX_NAMESPACE(tweak_constants) -void tweak_constants(spx_ctx *ctx); - -/* Haraka Sponge */ -#define haraka_S_inc_init SPX_NAMESPACE(haraka_S_inc_init) -void haraka_S_inc_init(uint8_t *s_inc); -#define haraka_S_inc_absorb SPX_NAMESPACE(haraka_S_inc_absorb) -void haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, - const spx_ctx *ctx); -#define haraka_S_inc_finalize SPX_NAMESPACE(haraka_S_inc_finalize) -void haraka_S_inc_finalize(uint8_t *s_inc); -#define haraka_S_inc_squeeze SPX_NAMESPACE(haraka_S_inc_squeeze) -void haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, - const spx_ctx *ctx); -#define haraka_S SPX_NAMESPACE(haraka_S) -void haraka_S(unsigned char *out, unsigned long long outlen, - const unsigned char *in, unsigned long long inlen, - const spx_ctx *ctx); - -/* Applies the 512-bit Haraka permutation to in. */ -#define haraka512_perm SPX_NAMESPACE(haraka512_perm) -void haraka512_perm(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx); - -/* Implementation of Haraka-512 */ -#define haraka512 SPX_NAMESPACE(haraka512) -void haraka512(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx); - -/* Implementation of Haraka-256 */ -#define haraka256 SPX_NAMESPACE(haraka256) -void haraka256(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/haraka_offsets.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/haraka_offsets.h deleted file mode 100644 index 7c062272a0..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/haraka_offsets.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef HARAKA_OFFSETS_H_ -#define HARAKA_OFFSETS_H_ - -/* - * Offsets of various fields in the address structure when we use Haraka as - * the Sphincs+ hash function - */ - -#define SPX_OFFSET_LAYER 3 /* The byte used to specify the Merkle tree layer */ -#define SPX_OFFSET_TREE 8 /* The start of the 8 byte field used to specify the tree */ -#define SPX_OFFSET_TYPE 19 /* The byte used to specify the hash type (reason) */ -#define SPX_OFFSET_KP_ADDR2 22 /* The high byte used to specify the key pair (which one-time signature) */ -#define SPX_OFFSET_KP_ADDR1 23 /* The low byte used to specify the key pair */ -#define SPX_OFFSET_CHAIN_ADDR 27 /* The byte used to specify the chain address (which Winternitz chain) */ -#define SPX_OFFSET_HASH_ADDR 31 /* The byte used to specify the hash address (where in the Winternitz chain) */ -#define SPX_OFFSET_TREE_HGT 27 /* The byte used to specify the height of this node in the FORS or Merkle tree */ -#define SPX_OFFSET_TREE_INDEX 28 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ - -#define SPX_HARAKA 1 - -#endif /* HARAKA_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/harakax4.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/harakax4.h deleted file mode 100644 index eadc69aa48..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/harakax4.h +++ /dev/null @@ -1,36 +0,0 @@ -#ifndef SPX_HARAKAX4_H -#define SPX_HARAKAX4_H - -#include "context.h" -#include "params.h" - -/* Haraka Sponge */ -#define haraka_Sx4 SPX_NAMESPACE(haraka_Sx4) -void haraka_Sx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned long long outlen, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - unsigned long long inlen, - const spx_ctx *ctx); - -/* Applies the 512-bit Haraka permutation x4 to in. */ -#define haraka512_perm_x4 SPX_NAMESPACE(haraka512_perm_x4) -void haraka512_perm_x4(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx); - -/* Implementation of Haraka-512 x4*/ -#define haraka512x4 SPX_NAMESPACE(haraka512x4) -void haraka512x4(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx); - -/* Implementation of Haraka-256 x4 */ -#define haraka256x4 SPX_NAMESPACE(haraka256x4) -void haraka256x4(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/hash.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/hash.h deleted file mode 100644 index f7c87d4c3c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/hash.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef SPX_HASH_H -#define SPX_HASH_H - -#include -#include - -#include "context.h" -#include "params.h" - -#define prf_addr SPX_NAMESPACE(prf_addr) -void prf_addr(unsigned char *out, const spx_ctx *ctx, - const uint32_t addr[8]); - -#define gen_message_random SPX_NAMESPACE(gen_message_random) -void gen_message_random(unsigned char *R, const unsigned char *sk_prf, - const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx); - -#define hash_message SPX_NAMESPACE(hash_message) -void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx); - - - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/hash_haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/hash_haraka.c deleted file mode 100644 index 750a67423b..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/hash_haraka.c +++ /dev/null @@ -1,81 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "utils.h" - -#include "haraka.h" -#include "hash.h" - -/* - * Computes PRF(key, addr), given a secret key of SPX_N bytes and an address - */ -void prf_addr(unsigned char *out, const spx_ctx *ctx, - const uint32_t addr[8]) { - /* Since SPX_N may be smaller than 32, we need temporary buffers. */ - unsigned char outbuf[32]; - unsigned char buf[64] = {0}; - - memcpy(buf, addr, SPX_ADDR_BYTES); - memcpy(buf + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); - - haraka512(outbuf, (const void *)buf, ctx); - memcpy(out, outbuf, SPX_N); -} - -/** - * Computes the message-dependent randomness R, using a secret seed and an - * optional randomization value as well as the message. - */ -void gen_message_random(unsigned char *R, const unsigned char *sk_prf, - const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx) { - uint8_t s_inc[65]; - - haraka_S_inc_init(s_inc); - haraka_S_inc_absorb(s_inc, sk_prf, SPX_N, ctx); - haraka_S_inc_absorb(s_inc, optrand, SPX_N, ctx); - haraka_S_inc_absorb(s_inc, m, mlen, ctx); - haraka_S_inc_finalize(s_inc); - haraka_S_inc_squeeze(R, SPX_N, s_inc, ctx); -} - -/** - * Computes the message hash using R, the public key, and the message. - * Outputs the message digest and the index of the leaf. The index is split in - * the tree index and the leaf index, for convenient copying to an address. - */ -void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx) { -#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) -#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) -#define SPX_LEAF_BITS SPX_TREE_HEIGHT -#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) -#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) - - unsigned char buf[SPX_DGST_BYTES]; - unsigned char *bufp = buf; - uint8_t s_inc[65]; - - haraka_S_inc_init(s_inc); - haraka_S_inc_absorb(s_inc, R, SPX_N, ctx); - haraka_S_inc_absorb(s_inc, pk + SPX_N, SPX_N, ctx); // Only absorb root part of pk - haraka_S_inc_absorb(s_inc, m, mlen, ctx); - haraka_S_inc_finalize(s_inc); - haraka_S_inc_squeeze(buf, SPX_DGST_BYTES, s_inc, ctx); - - memcpy(digest, bufp, SPX_FORS_MSG_BYTES); - bufp += SPX_FORS_MSG_BYTES; - - - *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); - *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); - bufp += SPX_TREE_BYTES; - - *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); - *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/hash_harakax4.c b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/hash_harakax4.c deleted file mode 100644 index cfa5162d79..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/hash_harakax4.c +++ /dev/null @@ -1,35 +0,0 @@ -#include -#include - -#include "address.h" -#include "harakax4.h" -#include "hashx4.h" -#include "params.h" - -/* - * 4-way parallel version of prf_addr; takes 4x as much input and output - */ -#define prf_addrx4 SPX_NAMESPACE(prf_addrx4) -void prf_addrx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const spx_ctx *ctx, - const uint32_t addrx4[4 * 8]) { - unsigned char bufx4[4 * 64] = {0}; - /* Since SPX_N may be smaller than 32, we need temporary buffers. */ - unsigned char outbuf[4 * 32]; - unsigned int i; - - for (i = 0; i < 4; i++) { - memcpy(bufx4 + i * 64, addrx4 + i * 8, SPX_ADDR_BYTES); - memcpy(bufx4 + i * 64 + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); - } - - haraka512x4(outbuf, bufx4, ctx); - - memcpy(out0, outbuf, SPX_N); - memcpy(out1, outbuf + 32, SPX_N); - memcpy(out2, outbuf + 64, SPX_N); - memcpy(out3, outbuf + 96, SPX_N); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/hashx4.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/hashx4.h deleted file mode 100644 index 3751a0ebd0..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/hashx4.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef SPX_HASHX4_H -#define SPX_HASHX4_H - -#include - -#include "context.h" -#include "params.h" - -#define prf_addrx4 SPX_NAMESPACE(prf_addrx4) -void prf_addrx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const spx_ctx *ctx, - const uint32_t addrx4[4 * 8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/merkle.c b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/merkle.c deleted file mode 100644 index f57811c1ac..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/merkle.c +++ /dev/null @@ -1,64 +0,0 @@ -#include -#include - -#include "merkle.h" - -#include "address.h" -#include "params.h" -#include "utils.h" -#include "utilsx4.h" -#include "wots.h" -#include "wotsx4.h" - -/* - * This generates a Merkle signature (WOTS signature followed by the Merkle - * authentication path). - */ -void merkle_sign(uint8_t *sig, unsigned char *root, - const spx_ctx *ctx, - uint32_t wots_addr[8], uint32_t tree_addr[8], - uint32_t idx_leaf) { - unsigned char *auth_path = sig + SPX_WOTS_BYTES; - uint32_t tree_addrx4[4 * 8] = { 0 }; - int j; - struct leaf_info_x4 info = { 0 }; - unsigned steps[ SPX_WOTS_LEN ]; - - info.wots_sig = sig; - chain_lengths(steps, root); - info.wots_steps = steps; - - for (j = 0; j < 4; j++) { - set_type(&tree_addrx4[8 * j], SPX_ADDR_TYPE_HASHTREE); - set_type(&info.leaf_addr[8 * j], SPX_ADDR_TYPE_WOTS); - set_type(&info.pk_addr[8 * j], SPX_ADDR_TYPE_WOTSPK); - copy_subtree_addr(&tree_addrx4[8 * j], tree_addr); - copy_subtree_addr(&info.leaf_addr[8 * j], wots_addr); - copy_subtree_addr(&info.pk_addr[8 * j], wots_addr); - } - - info.wots_sign_leaf = idx_leaf; - - treehashx4(root, auth_path, ctx, - idx_leaf, 0, - SPX_TREE_HEIGHT, - wots_gen_leafx4, - tree_addrx4, &info); -} - -/* Compute root node of the top-most subtree. */ -void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { - /* We do not need the auth path in key generation, but it simplifies the - code to have just one treehash routine that computes both root and path - in one function. */ - unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; - uint32_t top_tree_addr[8] = {0}; - uint32_t wots_addr[8] = {0}; - - set_layer_addr(top_tree_addr, SPX_D - 1); - set_layer_addr(wots_addr, SPX_D - 1); - - merkle_sign(auth_path, root, ctx, - wots_addr, top_tree_addr, - ~0U /* ~0 means "don't bother generating an auth path */ ); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/merkle.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/merkle.h deleted file mode 100644 index 769cf2e970..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/merkle.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef MERKLE_H_ -#define MERKLE_H_ - -#include - -#include "context.h" -#include "params.h" - -/* Generate a Merkle signature (WOTS signature followed by the Merkle */ -/* authentication path) */ -#define merkle_sign SPX_NAMESPACE(merkle_sign) -void merkle_sign(uint8_t *sig, unsigned char *root, - const spx_ctx *ctx, - uint32_t wots_addr[8], uint32_t tree_addr[8], - uint32_t idx_leaf); - -/* Compute the root node of the top-most subtree. */ -#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) -void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); - -#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/nistapi.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/nistapi.h deleted file mode 100644 index 3cb71afad4..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/nistapi.h +++ /dev/null @@ -1,87 +0,0 @@ -#ifndef SPX_API_H -#define SPX_API_H - -#include -#include - -#include "params.h" - -#define CRYPTO_ALGNAME "SPHINCS+" - -#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES -#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES -#define CRYPTO_BYTES SPX_BYTES -#define CRYPTO_SEEDBYTES (3*SPX_N) - -/* - * Returns the length of a secret key, in bytes - */ -#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) -size_t crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) -size_t crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) -size_t crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) -size_t crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) -int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) -int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) -int crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) -int crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -#define crypto_sign SPX_NAMESPACE(crypto_sign) -int crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) -int crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/params.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/params.h deleted file mode 100644 index 8188bbdd3b..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/params.h +++ /dev/null @@ -1,56 +0,0 @@ -#ifndef SPX_PARAMS_H -#define SPX_PARAMS_H - -#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_##s - -/* Hash output length in bytes. */ -#define SPX_N 24 -/* Height of the hypertree. */ -#define SPX_FULL_HEIGHT 66 -/* Number of subtree layer. */ -#define SPX_D 22 -/* FORS tree dimensions. */ -#define SPX_FORS_HEIGHT 8 -#define SPX_FORS_TREES 33 -/* Winternitz parameter, */ -#define SPX_WOTS_W 16 - -/* The hash function is defined by linking a different hash.c file, as opposed - to setting a #define constant. */ - -/* For clarity */ -#define SPX_ADDR_BYTES 32 - -/* WOTS parameters. */ -#define SPX_WOTS_LOGW 4 - -#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) - -/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#define SPX_WOTS_LEN2 3 - -#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) -#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) -#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES - -/* Subtree size. */ -#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) - -//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT -// #error SPX_D should always divide SPX_FULL_HEIGHT -//#endif - -/* FORS parameters. */ -#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) -#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) -#define SPX_FORS_PK_BYTES SPX_N - -/* Resulting SPX sizes. */ -#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ - SPX_FULL_HEIGHT * SPX_N) -#define SPX_PK_BYTES (2 * SPX_N) -#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) - -#include "haraka_offsets.h" - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/sign.c b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/sign.c deleted file mode 100644 index 9d0c7d1b22..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/sign.c +++ /dev/null @@ -1,286 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "context.h" -#include "fors.h" -#include "hash.h" -#include "merkle.h" -#include "nistapi.h" -#include "params.h" -#include "randombytes.h" -#include "thash.h" -#include "utils.h" -#include "wots.h" - -/* - * Returns the length of a secret key, in bytes - */ -size_t crypto_sign_secretkeybytes(void) { - return CRYPTO_SECRETKEYBYTES; -} - -/* - * Returns the length of a public key, in bytes - */ -size_t crypto_sign_publickeybytes(void) { - return CRYPTO_PUBLICKEYBYTES; -} - -/* - * Returns the length of a signature, in bytes - */ -size_t crypto_sign_bytes(void) { - return CRYPTO_BYTES; -} - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t crypto_sign_seedbytes(void) { - return CRYPTO_SEEDBYTES; -} - -/* - * Generates an SPX key pair given a seed of length - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed) { - spx_ctx ctx; - - /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ - memcpy(sk, seed, CRYPTO_SEEDBYTES); - - memcpy(pk, sk + 2 * SPX_N, SPX_N); - - memcpy(ctx.pub_seed, pk, SPX_N); - memcpy(ctx.sk_seed, sk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - /* Compute root node of the top-most subtree. */ - merkle_gen_root(sk + 3 * SPX_N, &ctx); - - // cleanup - free_hash_function(&ctx); - - memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); - - return 0; -} - -/* - * Generates an SPX key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { - uint8_t seed[CRYPTO_SEEDBYTES]; - randombytes(seed, CRYPTO_SEEDBYTES); - crypto_sign_seed_keypair(pk, sk, seed); - - return 0; -} - -/** - * Returns an array containing a detached signature. - */ -int crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - spx_ctx ctx; - - const uint8_t *sk_prf = sk + SPX_N; - const uint8_t *pk = sk + 2 * SPX_N; - - uint8_t optrand[SPX_N]; - uint8_t mhash[SPX_FORS_MSG_BYTES]; - uint8_t root[SPX_N]; - uint32_t i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - - memcpy(ctx.sk_seed, sk, SPX_N); - memcpy(ctx.pub_seed, pk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - set_type(wots_addr, SPX_ADDR_TYPE_WOTS); - set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); - - /* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ - randombytes(optrand, SPX_N); - /* Compute the digest randomization value. */ - gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); - - /* Derive the message digest and leaf index from R, PK and M. */ - hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); - sig += SPX_N; - - set_tree_addr(wots_addr, tree); - set_keypair_addr(wots_addr, idx_leaf); - - /* Sign the message hash using FORS. */ - fors_sign(sig, root, mhash, &ctx, wots_addr); - sig += SPX_FORS_BYTES; - - for (i = 0; i < SPX_D; i++) { - set_layer_addr(tree_addr, i); - set_tree_addr(tree_addr, tree); - - copy_subtree_addr(wots_addr, tree_addr); - set_keypair_addr(wots_addr, idx_leaf); - - merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); - sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); - tree = tree >> SPX_TREE_HEIGHT; - } - - free_hash_function(&ctx); - - *siglen = SPX_BYTES; - - return 0; -} - -/** - * Verifies a detached signature and message under a given public key. - */ -int crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk) { - spx_ctx ctx; - const uint8_t *pub_root = pk + SPX_N; - uint8_t mhash[SPX_FORS_MSG_BYTES]; - uint8_t wots_pk[SPX_WOTS_BYTES]; - uint8_t root[SPX_N]; - uint8_t leaf[SPX_N]; - unsigned int i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - if (siglen != SPX_BYTES) { - return -1; - } - - memcpy(ctx.pub_seed, pk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - set_type(wots_addr, SPX_ADDR_TYPE_WOTS); - set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); - set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); - - /* Derive the message digest and leaf index from R || PK || M. */ - /* The additional SPX_N is a result of the hash domain separator. */ - hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); - sig += SPX_N; - - /* Layer correctly defaults to 0, so no need to set_layer_addr */ - set_tree_addr(wots_addr, tree); - set_keypair_addr(wots_addr, idx_leaf); - - fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); - sig += SPX_FORS_BYTES; - - /* For each subtree.. */ - for (i = 0; i < SPX_D; i++) { - set_layer_addr(tree_addr, i); - set_tree_addr(tree_addr, tree); - - copy_subtree_addr(wots_addr, tree_addr); - set_keypair_addr(wots_addr, idx_leaf); - - copy_keypair_addr(wots_pk_addr, wots_addr); - - /* The WOTS public key is only correct if the signature was correct. */ - /* Initially, root is the FORS pk, but on subsequent iterations it is - the root of the subtree below the currently processed subtree. */ - wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); - sig += SPX_WOTS_BYTES; - - /* Compute the leaf node using the WOTS public key. */ - thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); - - /* Compute the root node of this subtree. */ - compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, - &ctx, tree_addr); - sig += SPX_TREE_HEIGHT * SPX_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); - tree = tree >> SPX_TREE_HEIGHT; - } - - // cleanup - free_hash_function(&ctx); - - /* Check if the root node equals the root node in the public key. */ - if (memcmp(root, pub_root, SPX_N) != 0) { - return -1; - } - - return 0; -} - - -/** - * Returns an array containing the signature followed by the message. - */ -int crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk) { - size_t siglen; - - crypto_sign_signature(sm, &siglen, m, mlen, sk); - - memmove(sm + SPX_BYTES, m, mlen); - *smlen = siglen + mlen; - - return 0; -} - -/** - * Verifies a given signature-message pair under a given public key. - */ -int crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk) { - /* The API caller does not necessarily know what size a signature should be - but SPHINCS+ signatures are always exactly SPX_BYTES. */ - if (smlen < SPX_BYTES) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - *mlen = smlen - SPX_BYTES; - - if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - /* If verification was successful, move the message to the right place. */ - memmove(m, sm + SPX_BYTES, *mlen); - - return 0; -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/thash.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/thash.h deleted file mode 100644 index 8687ccfb4d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/thash.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef SPX_THASH_H -#define SPX_THASH_H - -#include "context.h" -#include "params.h" - -#include - -#define thash SPX_NAMESPACE(thash) -void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/thash_haraka_robust.c b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/thash_haraka_robust.c deleted file mode 100644 index 109502cbc2..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/thash_haraka_robust.c +++ /dev/null @@ -1,45 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "thash.h" -#include "utils.h" - -#include "haraka.h" - -/** - * Takes an array of inblocks concatenated arrays of SPX_N bytes. - */ -void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]) { - PQCLEAN_VLA(uint8_t, buf, SPX_ADDR_BYTES + inblocks * SPX_N); - PQCLEAN_VLA(uint8_t, bitmask, inblocks * SPX_N); - unsigned char outbuf[32]; - unsigned char buf_tmp[64]; - unsigned int i; - - if (inblocks == 1) { - /* F function */ - /* Since SPX_N may be smaller than 32, we need a temporary buffer. */ - memset(buf_tmp, 0, 64); - memcpy(buf_tmp, addr, 32); - - haraka256(outbuf, buf_tmp, ctx); - for (i = 0; i < inblocks * SPX_N; i++) { - buf_tmp[SPX_ADDR_BYTES + i] = in[i] ^ outbuf[i]; - } - haraka512(outbuf, buf_tmp, ctx); - memcpy(out, outbuf, SPX_N); - } else { - /* All other tweakable hashes*/ - memcpy(buf, addr, 32); - haraka_S(bitmask, inblocks * SPX_N, buf, SPX_ADDR_BYTES, ctx); - - for (i = 0; i < inblocks * SPX_N; i++) { - buf[SPX_ADDR_BYTES + i] = in[i] ^ bitmask[i]; - } - - haraka_S(out, SPX_N, buf, SPX_ADDR_BYTES + inblocks * SPX_N, ctx); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/thash_haraka_robustx4.c b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/thash_haraka_robustx4.c deleted file mode 100644 index 100808a3a5..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/thash_haraka_robustx4.c +++ /dev/null @@ -1,93 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "thashx4.h" - -#include "harakax4.h" - -#include "utils.h" - -/** - * 4-way parallel version of thash; takes 4x as much input and output - */ -#define thashx4 SPX_NAMESPACE(thashx4) -void thashx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addrx4[4 * 8]) { - PQCLEAN_VLA(unsigned char, buf0, SPX_ADDR_BYTES + inblocks * SPX_N); - PQCLEAN_VLA(unsigned char, buf1, SPX_ADDR_BYTES + inblocks * SPX_N); - PQCLEAN_VLA(unsigned char, buf2, SPX_ADDR_BYTES + inblocks * SPX_N); - PQCLEAN_VLA(unsigned char, buf3, SPX_ADDR_BYTES + inblocks * SPX_N); - PQCLEAN_VLA(unsigned char, bitmask0, inblocks * SPX_N); - PQCLEAN_VLA(unsigned char, bitmask1, inblocks * SPX_N); - PQCLEAN_VLA(unsigned char, bitmask2, inblocks * SPX_N); - PQCLEAN_VLA(unsigned char, bitmask3, inblocks * SPX_N); - unsigned char outbuf[32 * 4]; - unsigned char buf_tmp[64 * 4]; - unsigned int i; - - if (inblocks == 1) { - memset(buf_tmp, 0, 64 * 4); - - // Generate masks first in buffer - memcpy(buf_tmp, addrx4 + 0 * 8, 32); - memcpy(buf_tmp + 32, addrx4 + 1 * 8, 32); - memcpy(buf_tmp + 64, addrx4 + 2 * 8, 32); - memcpy(buf_tmp + 96, addrx4 + 3 * 8, 32); - - haraka256x4(outbuf, buf_tmp, ctx); - - /* move addresses to make room for inputs; zero old values */ - memcpy(buf_tmp + 192, buf_tmp + 96, SPX_ADDR_BYTES); - memcpy(buf_tmp + 128, buf_tmp + 64, SPX_ADDR_BYTES); - memcpy(buf_tmp + 64, buf_tmp + 32, SPX_ADDR_BYTES); - /* skip memcpy(buf_tmp, buf_tmp, SPX_ADDR_BYTES); already in place */ - - /* skip memset(buf_tmp, 0, SPX_ADDR_BYTES); remained untouched */ - memset(buf_tmp + 32, 0, SPX_ADDR_BYTES); - /* skip memset(buf_tmp + 64, 0, SPX_ADDR_BYTES); contains addr1 */ - memset(buf_tmp + 96, 0, SPX_ADDR_BYTES); - - for (i = 0; i < SPX_N; i++) { - buf_tmp[SPX_ADDR_BYTES + i] = in0[i] ^ outbuf[i]; - buf_tmp[SPX_ADDR_BYTES + i + 64] = in1[i] ^ outbuf[i + 32]; - buf_tmp[SPX_ADDR_BYTES + i + 128] = in2[i] ^ outbuf[i + 64]; - buf_tmp[SPX_ADDR_BYTES + i + 192] = in3[i] ^ outbuf[i + 96]; - } - - haraka512x4(outbuf, buf_tmp, ctx); - - memcpy(out0, outbuf, SPX_N); - memcpy(out1, outbuf + 32, SPX_N); - memcpy(out2, outbuf + 64, SPX_N); - memcpy(out3, outbuf + 96, SPX_N); - } else { - /* All other tweakable hashes*/ - memcpy(buf0, addrx4 + 0 * 8, 32); - memcpy(buf1, addrx4 + 1 * 8, 32); - memcpy(buf2, addrx4 + 2 * 8, 32); - memcpy(buf3, addrx4 + 3 * 8, 32); - - haraka_Sx4(bitmask0, bitmask1, bitmask2, bitmask3, inblocks * SPX_N, - buf0, buf1, buf2, buf3, SPX_ADDR_BYTES, ctx); - - for (i = 0; i < inblocks * SPX_N; i++) { - buf0[SPX_ADDR_BYTES + i] = in0[i] ^ bitmask0[i]; - buf1[SPX_ADDR_BYTES + i] = in1[i] ^ bitmask1[i]; - buf2[SPX_ADDR_BYTES + i] = in2[i] ^ bitmask2[i]; - buf3[SPX_ADDR_BYTES + i] = in3[i] ^ bitmask3[i]; - } - - haraka_Sx4(out0, out1, out2, out3, SPX_N, - buf0, buf1, buf2, buf3, SPX_ADDR_BYTES + inblocks * SPX_N, - ctx); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/thashx4.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/thashx4.h deleted file mode 100644 index 64798a3727..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/thashx4.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef SPX_THASHX4_H -#define SPX_THASHX4_H - -#include - -#include "context.h" -#include "params.h" - -#define thashx4 SPX_NAMESPACE(thashx4) -void thashx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addrx4[4 * 8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/utils.c b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/utils.c deleted file mode 100644 index 177b541fb9..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/utils.c +++ /dev/null @@ -1,148 +0,0 @@ -#include - -#include "utils.h" - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "thash.h" - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void ull_to_bytes(unsigned char *out, unsigned int outlen, - unsigned long long in) { - int i; - - /* Iterate over out in decreasing order, for big-endianness. */ - for (i = (signed int)outlen - 1; i >= 0; i--) { - out[i] = in & 0xff; - in = in >> 8; - } -} - -void u32_to_bytes(unsigned char *out, uint32_t in) { - out[0] = (unsigned char)(in >> 24); - out[1] = (unsigned char)(in >> 16); - out[2] = (unsigned char)(in >> 8); - out[3] = (unsigned char)in; -} - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { - unsigned long long retval = 0; - unsigned int i; - - for (i = 0; i < inlen; i++) { - retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); - } - return retval; -} - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void compute_root(unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const spx_ctx *ctx, uint32_t addr[8]) { - uint32_t i; - unsigned char buffer[2 * SPX_N]; - - /* If leaf_idx is odd (last bit = 1), current path element is a right child - and auth_path has to go left. Otherwise it is the other way around. */ - if (leaf_idx & 1) { - memcpy(buffer + SPX_N, leaf, SPX_N); - memcpy(buffer, auth_path, SPX_N); - } else { - memcpy(buffer, leaf, SPX_N); - memcpy(buffer + SPX_N, auth_path, SPX_N); - } - auth_path += SPX_N; - - for (i = 0; i < tree_height - 1; i++) { - leaf_idx >>= 1; - idx_offset >>= 1; - /* Set the address of the node we're creating. */ - set_tree_height(addr, i + 1); - set_tree_index(addr, leaf_idx + idx_offset); - - /* Pick the right or left neighbor, depending on parity of the node. */ - if (leaf_idx & 1) { - thash(buffer + SPX_N, buffer, 2, ctx, addr); - memcpy(buffer, auth_path, SPX_N); - } else { - thash(buffer, buffer, 2, ctx, addr); - memcpy(buffer + SPX_N, auth_path, SPX_N); - } - auth_path += SPX_N; - } - - /* The last iteration is exceptional; we do not copy an auth_path node. */ - leaf_idx >>= 1; - idx_offset >>= 1; - set_tree_height(addr, tree_height); - set_tree_index(addr, leaf_idx + idx_offset); - thash(root, buffer, 2, ctx, addr); -} - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const spx_ctx * /* ctx */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), - uint32_t tree_addr[8]) { - PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); - PQCLEAN_VLA(unsigned int, heights, tree_height + 1); - unsigned int offset = 0; - uint32_t idx; - uint32_t tree_idx; - - for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { - /* Add the next leaf node to the stack. */ - gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); - offset++; - heights[offset - 1] = 0; - - /* If this is a node we need for the auth path.. */ - if ((leaf_idx ^ 0x1) == idx) { - memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); - } - - /* While the top-most nodes are of equal height.. */ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { - /* Compute index of the new node, in the next layer. */ - tree_idx = (idx >> (heights[offset - 1] + 1)); - - /* Set the address of the node we're creating. */ - set_tree_height(tree_addr, heights[offset - 1] + 1); - set_tree_index(tree_addr, - tree_idx + (idx_offset >> (heights[offset - 1] + 1))); - /* Hash the top-most nodes from the stack together. */ - thash(stack + (offset - 2)*SPX_N, - stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); - offset--; - /* Note that the top-most node is now one layer higher. */ - heights[offset - 1]++; - - /* If this is a node we need for the auth path.. */ - if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_path + heights[offset - 1]*SPX_N, - stack + (offset - 1)*SPX_N, SPX_N); - } - } - } - memcpy(root, stack, SPX_N); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/utils.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/utils.h deleted file mode 100644 index 64f5d5a53a..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/utils.h +++ /dev/null @@ -1,58 +0,0 @@ -#ifndef SPX_UTILS_H -#define SPX_UTILS_H - -#include - -#include "compat.h" -#include "context.h" -#include "params.h" - - -/* To support MSVC use alloca() instead of VLAs. See #20. */ - - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) -void ull_to_bytes(unsigned char *out, unsigned int outlen, - unsigned long long in); -#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) -void u32_to_bytes(unsigned char *out, uint32_t in); - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) -unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -#define compute_root SPX_NAMESPACE(compute_root) -void compute_root(unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const spx_ctx *ctx, uint32_t addr[8]); - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -#define treehash SPX_NAMESPACE(treehash) -void treehash(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const spx_ctx *ctx /* ctx */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), - uint32_t tree_addr[8]); - - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/utilsx4.c b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/utilsx4.c deleted file mode 100644 index 1638677194..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/utilsx4.c +++ /dev/null @@ -1,138 +0,0 @@ -#include - -#include "utilsx4.h" - -#include "address.h" -#include "params.h" -#include "thashx4.h" -#include "utils.h" - -/* - * Generate the entire Merkle tree, computing the authentication path for leaf_idx, - * and the resulting root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) - * - * This expects tree_addrx4 to be initialized to 4 parallel addr structures for - * the Merkle tree nodes - * - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - * - * This works by using the standard Merkle tree building algorithm, except - * that each 'node' tracked is actually 4 consecutive nodes in the real tree. - * When we combine two logical nodes ABCD and WXYZ, we perform the H - * operation on adjacent real nodes, forming the parent logical node - * (AB)(CD)(WX)(YZ) - * - * When we get to the top two levels of the real tree (where there is only - * one logical node), we continue this operation two more times; the right - * most real node will by the actual root (and the other 3 nodes will be - * garbage). We follow the same thashx4 logic so that the 'extract - * authentication path components' part of the loop is still executed (and - * to simplify the code somewhat) - * - * This currently assumes tree_height >= 2; I suspect that doing an adjusting - * idx, addr_idx on the gen_leafx4 call if tree_height < 2 would fix it; since - * we don't actually use such short trees, I haven't bothered - */ -void treehashx4(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, - uint32_t tree_height, - void (*gen_leafx4)( - unsigned char * /* Where to write the leaves */, - const spx_ctx *, - uint32_t idx, void *info), - uint32_t tree_addrx4[4 * 8], - void *info) { - /* This is where we keep the intermediate nodes */ - PQCLEAN_VLA(unsigned char, stackx4, tree_height * 4 * SPX_N); - uint32_t left_adj = 0, prev_left_adj = 0; /* When we're doing the top 3 */ - /* levels, the left-most part of the tree isn't at the beginning */ - /* of current[]. These give the offset of the actual start */ - - uint32_t idx; - uint32_t max_idx = (1U << (tree_height - 2)) - 1; - for (idx = 0;; idx++) { - unsigned char current[4 * SPX_N]; /* Current logical node */ - gen_leafx4( current, ctx, 4 * idx + idx_offset, - info ); - - /* Now combine the freshly generated right node with previously */ - /* generated left ones */ - uint32_t internal_idx_offset = idx_offset; - uint32_t internal_idx = idx; - uint32_t internal_leaf = leaf_idx; - uint32_t h; /* The height we are in the Merkle tree */ - for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { - - /* Special processing if we're at the top of the tree */ - if (h >= tree_height - 2) { - if (h == tree_height) { - /* We hit the root; return it */ - memcpy( root, ¤t[3 * SPX_N], SPX_N ); - return; - } - /* The tree indexing logic is a bit off in this case */ - /* Adjust it so that the left-most node of the part of */ - /* the tree that we're processing has index 0 */ - prev_left_adj = left_adj; - left_adj = 4U - (1 << (tree_height - h - 1)); - } - - /* Check if we hit the top of the tree */ - if (h == tree_height) { - /* We hit the root; return it */ - memcpy( root, ¤t[3 * SPX_N], SPX_N ); - return; - } - - /* - * Check if one of the nodes we have is a part of the - * authentication path; if it is, write it out - */ - if ((((internal_idx << 2) ^ internal_leaf) & ~0x3U) == 0) { - memcpy( &auth_path[ h * SPX_N ], - ¤t[(((internal_leaf & 3) ^ 1) + prev_left_adj) * SPX_N], - SPX_N ); - } - - /* - * Check if we're at a left child; if so, stop going up the stack - * Exception: if we've reached the end of the tree, keep on going - * (so we combine the last 4 nodes into the one root node in two - * more iterations) - */ - if ((internal_idx & 1) == 0 && idx < max_idx) { - break; - } - - /* Ok, we're at a right node (or doing the top 3 levels) */ - /* Now combine the left and right logical nodes together */ - - /* Set the address of the node we're creating. */ - unsigned int j; - internal_idx_offset >>= 1; - for (j = 0; j < 4; j++) { - set_tree_height(tree_addrx4 + j * 8, h + 1); - set_tree_index(tree_addrx4 + j * 8, - (4 / 2) * (internal_idx & ~1U) + j - left_adj + internal_idx_offset ); - } - unsigned char *left = &stackx4[h * 4 * SPX_N]; - thashx4( ¤t[0 * SPX_N], - ¤t[1 * SPX_N], - ¤t[2 * SPX_N], - ¤t[3 * SPX_N], - &left [0 * SPX_N], - &left [2 * SPX_N], - ¤t[0 * SPX_N], - ¤t[2 * SPX_N], - 2, ctx, tree_addrx4); - } - - /* We've hit a left child; save the current for when we get the */ - /* corresponding right right */ - memcpy( &stackx4[h * 4 * SPX_N], current, 4 * SPX_N); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/utilsx4.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/utilsx4.h deleted file mode 100644 index facb874b18..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/utilsx4.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef SPX_UTILSX4_H -#define SPX_UTILSX4_H - -#include - -#include "context.h" -#include "params.h" - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - * - * This implementation uses AVX to compute internal nodes 4 at a time (in - * parallel) - */ -#define treehashx4 SPX_NAMESPACE(treehashx4) -void treehashx4(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leafx4)( - unsigned char * /* Where to write the leaves */, - const spx_ctx * /* ctx */, - uint32_t addr_idx, void *info), - uint32_t tree_addrx4[4 * 8], void *info); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/wots.c b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/wots.c deleted file mode 100644 index 4d5041ce05..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/wots.c +++ /dev/null @@ -1,269 +0,0 @@ -#include -#include - -#include "wots.h" - -#include "address.h" -#include "hash.h" -#include "hashx4.h" -#include "params.h" -#include "thash.h" -#include "thashx4.h" -#include "utils.h" -#include "utilsx4.h" -#include "wotsx4.h" - -// TODO clarify address expectations, and make them more uniform. -// TODO i.e. do we expect types to be set already? -// TODO and do we expect modifications or copies? - -/** - * Computes up the chains - */ -static void gen_chains( - unsigned char *out, - const unsigned char *in, - unsigned int start[SPX_WOTS_LEN], - const unsigned int steps[SPX_WOTS_LEN], - const spx_ctx *ctx, - uint32_t addr[8]) { - uint32_t i, j, k, idx, watching; - int done; - unsigned char empty[SPX_N]; - unsigned char *bufs[4]; - uint32_t addrs[8 * 4]; - - int l; - uint16_t counts[SPX_WOTS_W] = { 0 }; - uint16_t idxs[SPX_WOTS_LEN]; - uint16_t total, newTotal; - - /* set addrs = {addr, addr, addr, addr} */ - for (j = 0; j < 4; j++) { - memcpy(addrs + j * 8, addr, sizeof(uint32_t) * 8); - } - - /* Initialize out with the value at position 'start'. */ - memcpy(out, in, SPX_WOTS_LEN * SPX_N); - - /* Sort the chains in reverse order by steps using counting sort. */ - for (i = 0; i < SPX_WOTS_LEN; i++) { - counts[steps[i]]++; - } - total = 0; - for (l = SPX_WOTS_W - 1; l >= 0; l--) { - newTotal = counts[l] + total; - counts[l] = total; - total = newTotal; - } - for (i = 0; i < SPX_WOTS_LEN; i++) { - idxs[counts[steps[i]]] = (uint16_t)i; - counts[steps[i]]++; - } - - /* We got our work cut out for us: do it! */ - for (i = 0; i < SPX_WOTS_LEN; i += 4) { - for (j = 0; j < 4 && i + j < SPX_WOTS_LEN; j++) { - idx = idxs[i + j]; - set_chain_addr(addrs + j * 8, idx); - bufs[j] = out + SPX_N * idx; - } - - /* As the chains are sorted in reverse order, we know that the first - * chain is the longest and the last one is the shortest. We keep - * an eye on whether the last chain is done and then on the one before, - * et cetera. */ - watching = 3; - done = 0; - while (i + watching >= SPX_WOTS_LEN) { - bufs[watching] = &empty[0]; - watching--; - } - - for (k = 0;; k++) { - while (k == steps[idxs[i + watching]]) { - bufs[watching] = &empty[0]; - if (watching == 0) { - done = 1; - break; - } - watching--; - } - if (done) { - break; - } - for (j = 0; j < watching + 1; j++) { - set_hash_addr(addrs + j * 8, k + start[idxs[i + j]]); - } - - thashx4(bufs[0], bufs[1], bufs[2], bufs[3], - bufs[0], bufs[1], bufs[2], bufs[3], 1, ctx, addrs); - } - } -} - -/** - * base_w algorithm as described in draft. - * Interprets an array of bytes as integers in base w. - * This only works when log_w is a divisor of 8. - */ -static void base_w(unsigned int *output, const int out_len, - const unsigned char *input) { - int in = 0; - int out = 0; - unsigned char total = 0; - int bits = 0; - int consumed; - - for (consumed = 0; consumed < out_len; consumed++) { - if (bits == 0) { - total = input[in]; - in++; - bits += 8; - } - bits -= SPX_WOTS_LOGW; - output[out] = (total >> bits) & (SPX_WOTS_W - 1); - out++; - } -} - -/* Computes the WOTS+ checksum over a message (in base_w). */ -static void wots_checksum(unsigned int *csum_base_w, - const unsigned int *msg_base_w) { - unsigned int csum = 0; - unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; - unsigned int i; - - /* Compute checksum. */ - for (i = 0; i < SPX_WOTS_LEN1; i++) { - csum += SPX_WOTS_W - 1 - msg_base_w[i]; - } - - /* Convert checksum to base_w. */ - /* Make sure expected empty zero bits are the least significant bits. */ - csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); - ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); - base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); -} - -/* Takes a message and derives the matching chain lengths. */ -void chain_lengths(unsigned int *lengths, const unsigned char *msg) { - base_w(lengths, SPX_WOTS_LEN1, msg); - wots_checksum(lengths + SPX_WOTS_LEN1, lengths); -} - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const spx_ctx *ctx, uint32_t addr[8]) { - unsigned int steps[SPX_WOTS_LEN]; - unsigned int start[SPX_WOTS_LEN]; - uint32_t i; - - chain_lengths(start, msg); - - for (i = 0; i < SPX_WOTS_LEN; i++) { - steps[i] = SPX_WOTS_W - 1 - start[i]; - } - - gen_chains(pk, sig, start, steps, ctx, addr); -} - -/* - * This generates 4 sequential WOTS public keys - * It also generates the WOTS signature if leaf_info indicates - * that we're signing with one of these WOTS keys - */ -void wots_gen_leafx4(unsigned char *dest, - const spx_ctx *ctx, - uint32_t leaf_idx, void *v_info) { - struct leaf_info_x4 *info = v_info; - uint32_t *leaf_addr = info->leaf_addr; - uint32_t *pk_addr = info->pk_addr; - unsigned int i, j, k; - unsigned char pk_buffer[ 4 * SPX_WOTS_BYTES ]; - unsigned wots_offset = SPX_WOTS_BYTES; - unsigned char *buffer; - uint32_t wots_k_mask; - unsigned wots_sign_index; - - if (((leaf_idx ^ info->wots_sign_leaf) & ~3U) == 0) { - /* We're traversing the leaf that's signing; generate the WOTS */ - /* signature */ - wots_k_mask = 0; - wots_sign_index = info->wots_sign_leaf & 3; /* Which of of the 4 */ - /* 4 slots do the signatures come from */ - } else { - /* Nope, we're just generating pk's; turn off the signature logic */ - wots_k_mask = (uint32_t)~0; - wots_sign_index = 0; - } - - for (j = 0; j < 4; j++) { - set_keypair_addr( leaf_addr + j * 8, leaf_idx + j ); - set_keypair_addr( pk_addr + j * 8, leaf_idx + j ); - } - - for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { - uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k to */ - /* the step if we're generating a signature, ~0 if we're not */ - - /* Start with the secret seed */ - for (j = 0; j < 4; j++) { - set_chain_addr(leaf_addr + j * 8, i); - set_hash_addr(leaf_addr + j * 8, 0); - set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTSPRF); - } - prf_addrx4(buffer + 0 * wots_offset, - buffer + 1 * wots_offset, - buffer + 2 * wots_offset, - buffer + 3 * wots_offset, - ctx, leaf_addr); - - for (j = 0; j < 4; j++) { - set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTS); - } - - /* Iterate down the WOTS chain */ - for (k = 0;; k++) { - /* Check if one of the values we have needs to be saved as a */ - /* part of the WOTS signature */ - if (k == wots_k) { - memcpy( info->wots_sig + i * SPX_N, - buffer + wots_sign_index * wots_offset, SPX_N ); - } - - /* Check if we hit the top of the chain */ - if (k == SPX_WOTS_W - 1) { - break; - } - - /* Iterate one step on all 4 chains */ - for (j = 0; j < 4; j++) { - set_hash_addr(leaf_addr + j * 8, k); - } - thashx4(buffer + 0 * wots_offset, - buffer + 1 * wots_offset, - buffer + 2 * wots_offset, - buffer + 3 * wots_offset, - buffer + 0 * wots_offset, - buffer + 1 * wots_offset, - buffer + 2 * wots_offset, - buffer + 3 * wots_offset, 1, ctx, leaf_addr); - } - } - - /* Do the final thash to generate the public keys */ - thashx4(dest + 0 * SPX_N, - dest + 1 * SPX_N, - dest + 2 * SPX_N, - dest + 3 * SPX_N, - pk_buffer + 0 * wots_offset, - pk_buffer + 1 * wots_offset, - pk_buffer + 2 * wots_offset, - pk_buffer + 3 * wots_offset, SPX_WOTS_LEN, ctx, pk_addr); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/wots.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/wots.h deleted file mode 100644 index 4e7692eeef..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/wots.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef SPX_WOTS_H -#define SPX_WOTS_H - -#include - -#include "context.h" -#include "params.h" - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) -void wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const spx_ctx *ctx, uint32_t addr[8]); - -/* - * Compute the chain lengths needed for a given message hash - */ -#define chain_lengths SPX_NAMESPACE(chain_lengths) -void chain_lengths(unsigned int *lengths, const unsigned char *msg); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/wotsx4.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/wotsx4.h deleted file mode 100644 index cd634f1743..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_aesni/wotsx4.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef WOTSX4_H_ -#define WOTSX4_H_ - -#include - -#include "params.h" - -/* - * This is here to provide an interface to the internal wots_gen_leafx4 - * routine. While this routine is not referenced in the package outside of - * wots.c, it is called from the stand-alone benchmark code to characterize - * the performance - */ -struct leaf_info_x4 { - unsigned char *wots_sig; - uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ - uint32_t *wots_steps; - uint32_t leaf_addr[4 * 8]; - uint32_t pk_addr[4 * 8]; -}; - -/* Macro to set the leaf_info to something 'benign', that is, it would */ -/* run with the same time as it does during the real signing process */ -/* Used only by the benchmark code */ -#define INITIALIZE_LEAF_INFO_X4(info, addr, step_buffer) { \ - (info).wots_sig = 0; \ - (info).wots_sign_leaf = ~0; \ - (info).wots_steps = step_buffer; \ - int i; \ - for (i=0; i<4; i++) { \ - memcpy( &(info).leaf_addr[8*i], addr, 32 ); \ - memcpy( &(info).pk_addr[8*i], addr, 32 ); \ - } \ - } - -#define wots_gen_leafx4 SPX_NAMESPACE(wots_gen_leafx4) -void wots_gen_leafx4(unsigned char *dest, - const spx_ctx *ctx, - uint32_t leaf_idx, void *v_info); - -#endif /* WOTSX4_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/LICENSE b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/LICENSE deleted file mode 100644 index 670154e353..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/LICENSE +++ /dev/null @@ -1,116 +0,0 @@ -CC0 1.0 Universal - -Statement of Purpose - -The laws of most jurisdictions throughout the world automatically confer -exclusive Copyright and Related Rights (defined below) upon the creator and -subsequent owner(s) (each and all, an "owner") of an original work of -authorship and/or a database (each, a "Work"). - -Certain owners wish to permanently relinquish those rights to a Work for the -purpose of contributing to a commons of creative, cultural and scientific -works ("Commons") that the public can reliably and without fear of later -claims of infringement build upon, modify, incorporate in other works, reuse -and redistribute as freely as possible in any form whatsoever and for any -purposes, including without limitation commercial purposes. These owners may -contribute to the Commons to promote the ideal of a free culture and the -further production of creative, cultural and scientific works, or to gain -reputation or greater distribution for their Work in part through the use and -efforts of others. - -For these and/or other purposes and motivations, and without any expectation -of additional consideration or compensation, the person associating CC0 with a -Work (the "Affirmer"), to the extent that he or she is an owner of Copyright -and Related Rights in the Work, voluntarily elects to apply CC0 to the Work -and publicly distribute the Work under its terms, with knowledge of his or her -Copyright and Related Rights in the Work and the meaning and intended legal -effect of CC0 on those rights. - -1. Copyright and Related Rights. A Work made available under CC0 may be -protected by copyright and related or neighboring rights ("Copyright and -Related Rights"). Copyright and Related Rights include, but are not limited -to, the following: - - i. the right to reproduce, adapt, distribute, perform, display, communicate, - and translate a Work; - - ii. moral rights retained by the original author(s) and/or performer(s); - - iii. publicity and privacy rights pertaining to a person's image or likeness - depicted in a Work; - - iv. rights protecting against unfair competition in regards to a Work, - subject to the limitations in paragraph 4(a), below; - - v. rights protecting the extraction, dissemination, use and reuse of data in - a Work; - - vi. database rights (such as those arising under Directive 96/9/EC of the - European Parliament and of the Council of 11 March 1996 on the legal - protection of databases, and under any national implementation thereof, - including any amended or successor version of such directive); and - - vii. other similar, equivalent or corresponding rights throughout the world - based on applicable law or treaty, and any national implementations thereof. - -2. Waiver. To the greatest extent permitted by, but not in contravention of, -applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and -unconditionally waives, abandons, and surrenders all of Affirmer's Copyright -and Related Rights and associated claims and causes of action, whether now -known or unknown (including existing as well as future claims and causes of -action), in the Work (i) in all territories worldwide, (ii) for the maximum -duration provided by applicable law or treaty (including future time -extensions), (iii) in any current or future medium and for any number of -copies, and (iv) for any purpose whatsoever, including without limitation -commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes -the Waiver for the benefit of each member of the public at large and to the -detriment of Affirmer's heirs and successors, fully intending that such Waiver -shall not be subject to revocation, rescission, cancellation, termination, or -any other legal or equitable action to disrupt the quiet enjoyment of the Work -by the public as contemplated by Affirmer's express Statement of Purpose. - -3. Public License Fallback. Should any part of the Waiver for any reason be -judged legally invalid or ineffective under applicable law, then the Waiver -shall be preserved to the maximum extent permitted taking into account -Affirmer's express Statement of Purpose. In addition, to the extent the Waiver -is so judged Affirmer hereby grants to each affected person a royalty-free, -non transferable, non sublicensable, non exclusive, irrevocable and -unconditional license to exercise Affirmer's Copyright and Related Rights in -the Work (i) in all territories worldwide, (ii) for the maximum duration -provided by applicable law or treaty (including future time extensions), (iii) -in any current or future medium and for any number of copies, and (iv) for any -purpose whatsoever, including without limitation commercial, advertising or -promotional purposes (the "License"). The License shall be deemed effective as -of the date CC0 was applied by Affirmer to the Work. Should any part of the -License for any reason be judged legally invalid or ineffective under -applicable law, such partial invalidity or ineffectiveness shall not -invalidate the remainder of the License, and in such case Affirmer hereby -affirms that he or she will not (i) exercise any of his or her remaining -Copyright and Related Rights in the Work or (ii) assert any associated claims -and causes of action with respect to the Work, in either case contrary to -Affirmer's express Statement of Purpose. - -4. Limitations and Disclaimers. - - a. No trademark or patent rights held by Affirmer are waived, abandoned, - surrendered, licensed or otherwise affected by this document. - - b. Affirmer offers the Work as-is and makes no representations or warranties - of any kind concerning the Work, express, implied, statutory or otherwise, - including without limitation warranties of title, merchantability, fitness - for a particular purpose, non infringement, or the absence of latent or - other defects, accuracy, or the present or absence of errors, whether or not - discoverable, all to the greatest extent permissible under applicable law. - - c. Affirmer disclaims responsibility for clearing rights of other persons - that may apply to the Work or any use thereof, including without limitation - any person's Copyright and Related Rights in the Work. Further, Affirmer - disclaims responsibility for obtaining any necessary consents, permissions - or other rights required for any use of the Work. - - d. Affirmer understands and acknowledges that Creative Commons is not a - party to this document and has no duty or obligation with respect to this - CC0 or use of the Work. - -For more information, please see - diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/address.c b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/address.c deleted file mode 100644 index b956e9cb29..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/address.c +++ /dev/null @@ -1,91 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "utils.h" - -/* - * Specify which level of Merkle tree (the "layer") we're working on - */ -void set_layer_addr(uint32_t addr[8], uint32_t layer) { - ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; -} - -/* - * Specify which Merkle tree within the level (the "tree address") we're working on - */ -void set_tree_addr(uint32_t addr[8], uint64_t tree) { - ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); -} - -/* - * Specify the reason we'll use this address structure for, that is, what - * hash will we compute with it. This is used so that unrelated types of - * hashes don't accidentally get the same address structure. The type will be - * one of the SPX_ADDR_TYPE constants - */ -void set_type(uint32_t addr[8], uint32_t type) { - ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; -} - -/* - * Copy the layer and tree fields of the address structure. This is used - * when we're doing multiple types of hashes within the same Merkle tree - */ -void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { - memcpy( out, in, SPX_OFFSET_TREE + 8 ); -} - -/* These functions are used for OTS addresses. */ - -/* - * Specify which Merkle leaf we're working on; that is, which OTS keypair - * we're talking about. - */ -void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { - ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; -} - -/* - * Copy the layer, tree and keypair fields of the address structure. This is - * used when we're doing multiple things within the same OTS keypair - */ -void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { - memcpy( out, in, SPX_OFFSET_TREE + 8 ); - ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; -} - -/* - * Specify which Merkle chain within the OTS we're working with - * (the chain address) - */ -void set_chain_addr(uint32_t addr[8], uint32_t chain) { - ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; -} - -/* - * Specify where in the Merkle chain we are -* (the hash address) - */ -void set_hash_addr(uint32_t addr[8], uint32_t hash) { - ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; -} - -/* These functions are used for all hash tree addresses (including FORS). */ - -/* - * Specify the height of the node in the Merkle/FORS tree we are in - * (the tree height) - */ -void set_tree_height(uint32_t addr[8], uint32_t tree_height) { - ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; -} - -/* - * Specify the distance from the left edge of the node in the Merkle/FORS tree - * (the tree index) - */ -void set_tree_index(uint32_t addr[8], uint32_t tree_index) { - u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/address.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/address.h deleted file mode 100644 index 24a84eb40c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/address.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef SPX_ADDRESS_H -#define SPX_ADDRESS_H - -#include - -#include "params.h" - -/* The hash types that are passed to set_type */ -#define SPX_ADDR_TYPE_WOTS 0 -#define SPX_ADDR_TYPE_WOTSPK 1 -#define SPX_ADDR_TYPE_HASHTREE 2 -#define SPX_ADDR_TYPE_FORSTREE 3 -#define SPX_ADDR_TYPE_FORSPK 4 -#define SPX_ADDR_TYPE_WOTSPRF 5 -#define SPX_ADDR_TYPE_FORSPRF 6 - -#define set_layer_addr SPX_NAMESPACE(set_layer_addr) -void set_layer_addr(uint32_t addr[8], uint32_t layer); - -#define set_tree_addr SPX_NAMESPACE(set_tree_addr) -void set_tree_addr(uint32_t addr[8], uint64_t tree); - -#define set_type SPX_NAMESPACE(set_type) -void set_type(uint32_t addr[8], uint32_t type); - -/* Copies the layer and tree part of one address into the other */ -#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) -void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for WOTS and FORS addresses. */ - -#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) -void set_keypair_addr(uint32_t addr[8], uint32_t keypair); - -#define set_chain_addr SPX_NAMESPACE(set_chain_addr) -void set_chain_addr(uint32_t addr[8], uint32_t chain); - -#define set_hash_addr SPX_NAMESPACE(set_hash_addr) -void set_hash_addr(uint32_t addr[8], uint32_t hash); - -#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) -void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for all hash tree addresses (including FORS). */ - -#define set_tree_height SPX_NAMESPACE(set_tree_height) -void set_tree_height(uint32_t addr[8], uint32_t tree_height); - -#define set_tree_index SPX_NAMESPACE(set_tree_index) -void set_tree_index(uint32_t addr[8], uint32_t tree_index); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/api.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/api.h deleted file mode 100644 index c41e8717a3..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/api.h +++ /dev/null @@ -1,77 +0,0 @@ -#ifndef PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_API_H -#define PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_API_H - -#include -#include - -#define PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_CRYPTO_ALGNAME "SPHINCS+-haraka-192f-robust" - -#define PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_CRYPTO_SECRETKEYBYTES 96 -#define PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_CRYPTO_PUBLICKEYBYTES 48 -#define PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_CRYPTO_BYTES 35664 - -#define PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_CRYPTO_SEEDBYTES 72 - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, - const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk); -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/context.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/context.h deleted file mode 100644 index 600dfb73c7..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/context.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef SPX_CONTEXT_H -#define SPX_CONTEXT_H - -#include -#include - -#include "params.h" - -typedef struct { - uint8_t pub_seed[SPX_N]; - uint8_t sk_seed[SPX_N]; - - - uint64_t tweaked512_rc64[10][8]; - uint32_t tweaked256_rc32[10][8]; -} spx_ctx; - -#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) -void initialize_hash_function(spx_ctx *ctx); - -#define free_hash_function SPX_NAMESPACE(free_hash_function) -void free_hash_function(spx_ctx *ctx); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/context_haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/context_haraka.c deleted file mode 100644 index f1cd7e3664..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/context_haraka.c +++ /dev/null @@ -1,11 +0,0 @@ -#include "context.h" -#include "haraka.h" - -void initialize_hash_function(spx_ctx *ctx) { - tweak_constants(ctx); -} - -// we don't support heap-based haraka right now -void free_hash_function(spx_ctx *ctx) { - (void)ctx; // suppress unused variable warnings -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/fors.c b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/fors.c deleted file mode 100644 index 96ca72e986..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/fors.c +++ /dev/null @@ -1,156 +0,0 @@ -#include -#include -#include - -#include "fors.h" - -#include "address.h" -#include "hash.h" -#include "thash.h" -#include "utils.h" -#include "utilsx1.h" - -static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, - uint32_t fors_leaf_addr[8]) { - prf_addr(sk, ctx, fors_leaf_addr); -} - -static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, - const spx_ctx *ctx, - uint32_t fors_leaf_addr[8]) { - thash(leaf, sk, 1, ctx, fors_leaf_addr); -} - -struct fors_gen_leaf_info { - uint32_t leaf_addrx[8]; -}; - -static void fors_gen_leafx1(unsigned char *leaf, - const spx_ctx *ctx, - uint32_t addr_idx, void *info) { - struct fors_gen_leaf_info *fors_info = info; - uint32_t *fors_leaf_addr = fors_info->leaf_addrx; - - /* Only set the parts that the caller doesn't set */ - set_tree_index(fors_leaf_addr, addr_idx); - set_type(fors_leaf_addr, SPX_ADDR_TYPE_FORSPRF); - fors_gen_sk(leaf, ctx, fors_leaf_addr); - - set_type(fors_leaf_addr, SPX_ADDR_TYPE_FORSTREE); - fors_sk_to_leaf(leaf, leaf, - ctx, fors_leaf_addr); -} - -/** - * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - * Assumes indices has space for SPX_FORS_TREES integers. - */ -static void message_to_indices(uint32_t *indices, const unsigned char *m) { - unsigned int i, j; - unsigned int offset = 0; - - for (i = 0; i < SPX_FORS_TREES; i++) { - indices[i] = 0; - for (j = 0; j < SPX_FORS_HEIGHT; j++) { - indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); - offset++; - } - } -} - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -void fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]) { - uint32_t indices[SPX_FORS_TREES]; - unsigned char roots[SPX_FORS_TREES * SPX_N]; - uint32_t fors_tree_addr[8] = {0}; - struct fors_gen_leaf_info fors_info = {0}; - uint32_t *fors_leaf_addr = fors_info.leaf_addrx; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - copy_keypair_addr(fors_tree_addr, fors_addr); - copy_keypair_addr(fors_leaf_addr, fors_addr); - - copy_keypair_addr(fors_pk_addr, fors_addr); - set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < SPX_FORS_TREES; i++) { - idx_offset = i * (1 << SPX_FORS_HEIGHT); - - set_tree_height(fors_tree_addr, 0); - set_tree_index(fors_tree_addr, indices[i] + idx_offset); - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); - - /* Include the secret key part that produces the selected leaf node. */ - fors_gen_sk(sig, ctx, fors_tree_addr); - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); - sig += SPX_N; - - /* Compute the authentication path for this leaf node. */ - treehashx1(roots + i * SPX_N, sig, ctx, - indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx1, - fors_tree_addr, &fors_info); - - sig += SPX_N * SPX_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); -} - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -void fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]) { - uint32_t indices[SPX_FORS_TREES]; - unsigned char roots[SPX_FORS_TREES * SPX_N]; - unsigned char leaf[SPX_N]; - uint32_t fors_tree_addr[8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - copy_keypair_addr(fors_tree_addr, fors_addr); - copy_keypair_addr(fors_pk_addr, fors_addr); - - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); - set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < SPX_FORS_TREES; i++) { - idx_offset = i * (1 << SPX_FORS_HEIGHT); - - set_tree_height(fors_tree_addr, 0); - set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Derive the leaf from the included secret key part. */ - fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); - sig += SPX_N; - - /* Derive the corresponding root node of this tree. */ - compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, - sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); - sig += SPX_N * SPX_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/fors.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/fors.h deleted file mode 100644 index 509140a178..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/fors.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef SPX_FORS_H -#define SPX_FORS_H - -#include - -#include "context.h" -#include "params.h" - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -#define fors_sign SPX_NAMESPACE(fors_sign) -void fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]); - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) -void fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/haraka.c deleted file mode 100644 index a4944913b5..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/haraka.c +++ /dev/null @@ -1,913 +0,0 @@ -/* - * Constant time implementation of the Haraka hash function. - * - * The bit-sliced implementation of the AES round functions are - * based on the AES implementation in BearSSL written - * by Thomas Pornin - */ - -#include -#include -#include -#include - -#include "haraka.h" -#include "utils.h" - -#define HARAKAS_RATE 32 - -static const uint64_t haraka512_rc64[10][8] = { - {0x24cf0ab9086f628b, 0xbdd6eeecc83b8382, 0xd96fb0306cdad0a7, 0xaace082ac8f95f89, 0x449d8e8870d7041f, 0x49bb2f80b2b3e2f8, 0x0569ae98d93bb258, 0x23dc9691e7d6a4b1}, - {0xd8ba10ede0fe5b6e, 0x7ecf7dbe424c7b8e, 0x6ea9949c6df62a31, 0xbf3f3c97ec9c313e, 0x241d03a196a1861e, 0xead3a51116e5a2ea, 0x77d479fcad9574e3, 0x18657a1af894b7a0}, - {0x10671e1a7f595522, 0xd9a00ff675d28c7b, 0x2f1edf0d2b9ba661, 0xb8ff58b8e3de45f9, 0xee29261da9865c02, 0xd1532aa4b50bdf43, 0x8bf858159b231bb1, 0xdf17439d22d4f599}, - {0xdd4b2f0870b918c0, 0x757a81f3b39b1bb6, 0x7a5c556898952e3f, 0x7dd70a16d915d87a, 0x3ae61971982b8301, 0xc3ab319e030412be, 0x17c0033ac094a8cb, 0x5a0630fc1a8dc4ef}, - {0x17708988c1632f73, 0xf92ddae090b44f4f, 0x11ac0285c43aa314, 0x509059941936b8ba, 0xd03e152fa2ce9b69, 0x3fbcbcb63a32998b, 0x6204696d692254f7, 0x915542ed93ec59b4}, - {0xf4ed94aa8879236e, 0xff6cb41cd38e03c0, 0x069b38602368aeab, 0x669495b820f0ddba, 0xf42013b1b8bf9e3d, 0xcf935efe6439734d, 0xbc1dcf42ca29e3f8, 0x7e6d3ed29f78ad67}, - {0xf3b0f6837ffcddaa, 0x3a76faef934ddf41, 0xcec7ae583a9c8e35, 0xe4dd18c68f0260af, 0x2c0e5df1ad398eaa, 0x478df5236ae22e8c, 0xfb944c46fe865f39, 0xaa48f82f028132ba}, - {0x231b9ae2b76aca77, 0x292a76a712db0b40, 0x5850625dc8134491, 0x73137dd469810fb5, 0x8a12a6a202a474fd, 0xd36fd9daa78bdb80, 0xb34c5e733505706f, 0xbaf1cdca818d9d96}, - {0x2e99781335e8c641, 0xbddfe5cce47d560e, 0xf74e9bf32e5e040c, 0x1d7a709d65996be9, 0x670df36a9cf66cdd, 0xd05ef84a176a2875, 0x0f888e828cb1c44e, 0x1a79e9c9727b052c}, - {0x83497348628d84de, 0x2e9387d51f22a754, 0xb000068da2f852d6, 0x378c9e1190fd6fe5, 0x870027c316de7293, 0xe51a9d4462e047bb, 0x90ecf7f8c6251195, 0x655953bfbed90a9c}, -}; - -static inline uint32_t br_dec32le(const unsigned char *src) { - return (uint32_t)src[0] - | ((uint32_t)src[1] << 8) - | ((uint32_t)src[2] << 16) - | ((uint32_t)src[3] << 24); -} - -static void br_range_dec32le(uint32_t *v, size_t num, const unsigned char *src) { - while (num-- > 0) { - *v ++ = br_dec32le(src); - src += 4; - } -} - -static inline void br_enc32le(unsigned char *dst, uint32_t x) { - dst[0] = (unsigned char)x; - dst[1] = (unsigned char)(x >> 8); - dst[2] = (unsigned char)(x >> 16); - dst[3] = (unsigned char)(x >> 24); -} - - -static void br_range_enc32le(unsigned char *dst, const uint32_t *v, size_t num) { - while (num-- > 0) { - br_enc32le(dst, *v ++); - dst += 4; - } -} - -static void br_aes_ct64_bitslice_Sbox(uint64_t *q) { - /* - * This S-box implementation is a straightforward translation of - * the circuit described by Boyar and Peralta in "A new - * combinational logic minimization technique with applications - * to cryptology" (https://eprint.iacr.org/2009/191.pdf). - * - * Note that variables x* (input) and s* (output) are numbered - * in "reverse" order (x0 is the high bit, x7 is the low bit). - */ - - uint64_t x0, x1, x2, x3, x4, x5, x6, x7; - uint64_t y1, y2, y3, y4, y5, y6, y7, y8, y9; - uint64_t y10, y11, y12, y13, y14, y15, y16, y17, y18, y19; - uint64_t y20, y21; - uint64_t z0, z1, z2, z3, z4, z5, z6, z7, z8, z9; - uint64_t z10, z11, z12, z13, z14, z15, z16, z17; - uint64_t t0, t1, t2, t3, t4, t5, t6, t7, t8, t9; - uint64_t t10, t11, t12, t13, t14, t15, t16, t17, t18, t19; - uint64_t t20, t21, t22, t23, t24, t25, t26, t27, t28, t29; - uint64_t t30, t31, t32, t33, t34, t35, t36, t37, t38, t39; - uint64_t t40, t41, t42, t43, t44, t45, t46, t47, t48, t49; - uint64_t t50, t51, t52, t53, t54, t55, t56, t57, t58, t59; - uint64_t t60, t61, t62, t63, t64, t65, t66, t67; - uint64_t s0, s1, s2, s3, s4, s5, s6, s7; - - x0 = q[7]; - x1 = q[6]; - x2 = q[5]; - x3 = q[4]; - x4 = q[3]; - x5 = q[2]; - x6 = q[1]; - x7 = q[0]; - - /* - * Top linear transformation. - */ - y14 = x3 ^ x5; - y13 = x0 ^ x6; - y9 = x0 ^ x3; - y8 = x0 ^ x5; - t0 = x1 ^ x2; - y1 = t0 ^ x7; - y4 = y1 ^ x3; - y12 = y13 ^ y14; - y2 = y1 ^ x0; - y5 = y1 ^ x6; - y3 = y5 ^ y8; - t1 = x4 ^ y12; - y15 = t1 ^ x5; - y20 = t1 ^ x1; - y6 = y15 ^ x7; - y10 = y15 ^ t0; - y11 = y20 ^ y9; - y7 = x7 ^ y11; - y17 = y10 ^ y11; - y19 = y10 ^ y8; - y16 = t0 ^ y11; - y21 = y13 ^ y16; - y18 = x0 ^ y16; - - /* - * Non-linear section. - */ - t2 = y12 & y15; - t3 = y3 & y6; - t4 = t3 ^ t2; - t5 = y4 & x7; - t6 = t5 ^ t2; - t7 = y13 & y16; - t8 = y5 & y1; - t9 = t8 ^ t7; - t10 = y2 & y7; - t11 = t10 ^ t7; - t12 = y9 & y11; - t13 = y14 & y17; - t14 = t13 ^ t12; - t15 = y8 & y10; - t16 = t15 ^ t12; - t17 = t4 ^ t14; - t18 = t6 ^ t16; - t19 = t9 ^ t14; - t20 = t11 ^ t16; - t21 = t17 ^ y20; - t22 = t18 ^ y19; - t23 = t19 ^ y21; - t24 = t20 ^ y18; - - t25 = t21 ^ t22; - t26 = t21 & t23; - t27 = t24 ^ t26; - t28 = t25 & t27; - t29 = t28 ^ t22; - t30 = t23 ^ t24; - t31 = t22 ^ t26; - t32 = t31 & t30; - t33 = t32 ^ t24; - t34 = t23 ^ t33; - t35 = t27 ^ t33; - t36 = t24 & t35; - t37 = t36 ^ t34; - t38 = t27 ^ t36; - t39 = t29 & t38; - t40 = t25 ^ t39; - - t41 = t40 ^ t37; - t42 = t29 ^ t33; - t43 = t29 ^ t40; - t44 = t33 ^ t37; - t45 = t42 ^ t41; - z0 = t44 & y15; - z1 = t37 & y6; - z2 = t33 & x7; - z3 = t43 & y16; - z4 = t40 & y1; - z5 = t29 & y7; - z6 = t42 & y11; - z7 = t45 & y17; - z8 = t41 & y10; - z9 = t44 & y12; - z10 = t37 & y3; - z11 = t33 & y4; - z12 = t43 & y13; - z13 = t40 & y5; - z14 = t29 & y2; - z15 = t42 & y9; - z16 = t45 & y14; - z17 = t41 & y8; - - /* - * Bottom linear transformation. - */ - t46 = z15 ^ z16; - t47 = z10 ^ z11; - t48 = z5 ^ z13; - t49 = z9 ^ z10; - t50 = z2 ^ z12; - t51 = z2 ^ z5; - t52 = z7 ^ z8; - t53 = z0 ^ z3; - t54 = z6 ^ z7; - t55 = z16 ^ z17; - t56 = z12 ^ t48; - t57 = t50 ^ t53; - t58 = z4 ^ t46; - t59 = z3 ^ t54; - t60 = t46 ^ t57; - t61 = z14 ^ t57; - t62 = t52 ^ t58; - t63 = t49 ^ t58; - t64 = z4 ^ t59; - t65 = t61 ^ t62; - t66 = z1 ^ t63; - s0 = t59 ^ t63; - s6 = t56 ^ ~t62; - s7 = t48 ^ ~t60; - t67 = t64 ^ t65; - s3 = t53 ^ t66; - s4 = t51 ^ t66; - s5 = t47 ^ t65; - s1 = t64 ^ ~s3; - s2 = t55 ^ ~t67; - - q[7] = s0; - q[6] = s1; - q[5] = s2; - q[4] = s3; - q[3] = s4; - q[2] = s5; - q[1] = s6; - q[0] = s7; -} - -static void br_aes_ct_bitslice_Sbox(uint32_t *q) { - /* - * This S-box implementation is a straightforward translation of - * the circuit described by Boyar and Peralta in "A new - * combinational logic minimization technique with applications - * to cryptology" (https://eprint.iacr.org/2009/191.pdf). - * - * Note that variables x* (input) and s* (output) are numbered - * in "reverse" order (x0 is the high bit, x7 is the low bit). - */ - - uint32_t x0, x1, x2, x3, x4, x5, x6, x7; - uint32_t y1, y2, y3, y4, y5, y6, y7, y8, y9; - uint32_t y10, y11, y12, y13, y14, y15, y16, y17, y18, y19; - uint32_t y20, y21; - uint32_t z0, z1, z2, z3, z4, z5, z6, z7, z8, z9; - uint32_t z10, z11, z12, z13, z14, z15, z16, z17; - uint32_t t0, t1, t2, t3, t4, t5, t6, t7, t8, t9; - uint32_t t10, t11, t12, t13, t14, t15, t16, t17, t18, t19; - uint32_t t20, t21, t22, t23, t24, t25, t26, t27, t28, t29; - uint32_t t30, t31, t32, t33, t34, t35, t36, t37, t38, t39; - uint32_t t40, t41, t42, t43, t44, t45, t46, t47, t48, t49; - uint32_t t50, t51, t52, t53, t54, t55, t56, t57, t58, t59; - uint32_t t60, t61, t62, t63, t64, t65, t66, t67; - uint32_t s0, s1, s2, s3, s4, s5, s6, s7; - - x0 = q[7]; - x1 = q[6]; - x2 = q[5]; - x3 = q[4]; - x4 = q[3]; - x5 = q[2]; - x6 = q[1]; - x7 = q[0]; - - /* - * Top linear transformation. - */ - y14 = x3 ^ x5; - y13 = x0 ^ x6; - y9 = x0 ^ x3; - y8 = x0 ^ x5; - t0 = x1 ^ x2; - y1 = t0 ^ x7; - y4 = y1 ^ x3; - y12 = y13 ^ y14; - y2 = y1 ^ x0; - y5 = y1 ^ x6; - y3 = y5 ^ y8; - t1 = x4 ^ y12; - y15 = t1 ^ x5; - y20 = t1 ^ x1; - y6 = y15 ^ x7; - y10 = y15 ^ t0; - y11 = y20 ^ y9; - y7 = x7 ^ y11; - y17 = y10 ^ y11; - y19 = y10 ^ y8; - y16 = t0 ^ y11; - y21 = y13 ^ y16; - y18 = x0 ^ y16; - - /* - * Non-linear section. - */ - t2 = y12 & y15; - t3 = y3 & y6; - t4 = t3 ^ t2; - t5 = y4 & x7; - t6 = t5 ^ t2; - t7 = y13 & y16; - t8 = y5 & y1; - t9 = t8 ^ t7; - t10 = y2 & y7; - t11 = t10 ^ t7; - t12 = y9 & y11; - t13 = y14 & y17; - t14 = t13 ^ t12; - t15 = y8 & y10; - t16 = t15 ^ t12; - t17 = t4 ^ t14; - t18 = t6 ^ t16; - t19 = t9 ^ t14; - t20 = t11 ^ t16; - t21 = t17 ^ y20; - t22 = t18 ^ y19; - t23 = t19 ^ y21; - t24 = t20 ^ y18; - - t25 = t21 ^ t22; - t26 = t21 & t23; - t27 = t24 ^ t26; - t28 = t25 & t27; - t29 = t28 ^ t22; - t30 = t23 ^ t24; - t31 = t22 ^ t26; - t32 = t31 & t30; - t33 = t32 ^ t24; - t34 = t23 ^ t33; - t35 = t27 ^ t33; - t36 = t24 & t35; - t37 = t36 ^ t34; - t38 = t27 ^ t36; - t39 = t29 & t38; - t40 = t25 ^ t39; - - t41 = t40 ^ t37; - t42 = t29 ^ t33; - t43 = t29 ^ t40; - t44 = t33 ^ t37; - t45 = t42 ^ t41; - z0 = t44 & y15; - z1 = t37 & y6; - z2 = t33 & x7; - z3 = t43 & y16; - z4 = t40 & y1; - z5 = t29 & y7; - z6 = t42 & y11; - z7 = t45 & y17; - z8 = t41 & y10; - z9 = t44 & y12; - z10 = t37 & y3; - z11 = t33 & y4; - z12 = t43 & y13; - z13 = t40 & y5; - z14 = t29 & y2; - z15 = t42 & y9; - z16 = t45 & y14; - z17 = t41 & y8; - - /* - * Bottom linear transformation. - */ - t46 = z15 ^ z16; - t47 = z10 ^ z11; - t48 = z5 ^ z13; - t49 = z9 ^ z10; - t50 = z2 ^ z12; - t51 = z2 ^ z5; - t52 = z7 ^ z8; - t53 = z0 ^ z3; - t54 = z6 ^ z7; - t55 = z16 ^ z17; - t56 = z12 ^ t48; - t57 = t50 ^ t53; - t58 = z4 ^ t46; - t59 = z3 ^ t54; - t60 = t46 ^ t57; - t61 = z14 ^ t57; - t62 = t52 ^ t58; - t63 = t49 ^ t58; - t64 = z4 ^ t59; - t65 = t61 ^ t62; - t66 = z1 ^ t63; - s0 = t59 ^ t63; - s6 = t56 ^ ~t62; - s7 = t48 ^ ~t60; - t67 = t64 ^ t65; - s3 = t53 ^ t66; - s4 = t51 ^ t66; - s5 = t47 ^ t65; - s1 = t64 ^ ~s3; - s2 = t55 ^ ~t67; - - q[7] = s0; - q[6] = s1; - q[5] = s2; - q[4] = s3; - q[3] = s4; - q[2] = s5; - q[1] = s6; - q[0] = s7; -} - -static void br_aes_ct_ortho(uint32_t *q) { -#define SWAPN_32(cl, ch, s, x, y) do { \ - uint32_t a, b; \ - a = (x); \ - b = (y); \ - (x) = (a & (uint32_t)(cl)) | ((b & (uint32_t)(cl)) << (s)); \ - (y) = ((a & (uint32_t)(ch)) >> (s)) | (b & (uint32_t)(ch)); \ - } while (0) - -#define SWAP2_32(x, y) SWAPN_32(0x55555555, 0xAAAAAAAA, 1, x, y) -#define SWAP4_32(x, y) SWAPN_32(0x33333333, 0xCCCCCCCC, 2, x, y) -#define SWAP8_32(x, y) SWAPN_32(0x0F0F0F0F, 0xF0F0F0F0, 4, x, y) - - SWAP2_32(q[0], q[1]); - SWAP2_32(q[2], q[3]); - SWAP2_32(q[4], q[5]); - SWAP2_32(q[6], q[7]); - - SWAP4_32(q[0], q[2]); - SWAP4_32(q[1], q[3]); - SWAP4_32(q[4], q[6]); - SWAP4_32(q[5], q[7]); - - SWAP8_32(q[0], q[4]); - SWAP8_32(q[1], q[5]); - SWAP8_32(q[2], q[6]); - SWAP8_32(q[3], q[7]); -} - -static inline void add_round_key32(uint32_t *q, const uint32_t *sk) { - q[0] ^= sk[0]; - q[1] ^= sk[1]; - q[2] ^= sk[2]; - q[3] ^= sk[3]; - q[4] ^= sk[4]; - q[5] ^= sk[5]; - q[6] ^= sk[6]; - q[7] ^= sk[7]; -} - -static inline void shift_rows32(uint32_t *q) { - int i; - - for (i = 0; i < 8; i++) { - uint32_t x; - - x = q[i]; - q[i] = (x & 0x000000FF) - | ((x & 0x0000FC00) >> 2) | ((x & 0x00000300) << 6) - | ((x & 0x00F00000) >> 4) | ((x & 0x000F0000) << 4) - | ((x & 0xC0000000) >> 6) | ((x & 0x3F000000) << 2); - } -} - -static inline uint32_t rotr16(uint32_t x) { - return (x << 16) | (x >> 16); -} - -static inline void mix_columns32(uint32_t *q) { - uint32_t q0, q1, q2, q3, q4, q5, q6, q7; - uint32_t r0, r1, r2, r3, r4, r5, r6, r7; - - q0 = q[0]; - q1 = q[1]; - q2 = q[2]; - q3 = q[3]; - q4 = q[4]; - q5 = q[5]; - q6 = q[6]; - q7 = q[7]; - r0 = (q0 >> 8) | (q0 << 24); - r1 = (q1 >> 8) | (q1 << 24); - r2 = (q2 >> 8) | (q2 << 24); - r3 = (q3 >> 8) | (q3 << 24); - r4 = (q4 >> 8) | (q4 << 24); - r5 = (q5 >> 8) | (q5 << 24); - r6 = (q6 >> 8) | (q6 << 24); - r7 = (q7 >> 8) | (q7 << 24); - - q[0] = q7 ^ r7 ^ r0 ^ rotr16(q0 ^ r0); - q[1] = q0 ^ r0 ^ q7 ^ r7 ^ r1 ^ rotr16(q1 ^ r1); - q[2] = q1 ^ r1 ^ r2 ^ rotr16(q2 ^ r2); - q[3] = q2 ^ r2 ^ q7 ^ r7 ^ r3 ^ rotr16(q3 ^ r3); - q[4] = q3 ^ r3 ^ q7 ^ r7 ^ r4 ^ rotr16(q4 ^ r4); - q[5] = q4 ^ r4 ^ r5 ^ rotr16(q5 ^ r5); - q[6] = q5 ^ r5 ^ r6 ^ rotr16(q6 ^ r6); - q[7] = q6 ^ r6 ^ r7 ^ rotr16(q7 ^ r7); -} - -static void br_aes_ct64_ortho(uint64_t *q) { -#define SWAPN(cl, ch, s, x, y) do { \ - uint64_t a, b; \ - a = (x); \ - b = (y); \ - (x) = (a & (uint64_t)(cl)) | ((b & (uint64_t)(cl)) << (s)); \ - (y) = ((a & (uint64_t)(ch)) >> (s)) | (b & (uint64_t)(ch)); \ - } while (0) - -#define SWAP2(x, y) SWAPN(0x5555555555555555, 0xAAAAAAAAAAAAAAAA, 1, x, y) -#define SWAP4(x, y) SWAPN(0x3333333333333333, 0xCCCCCCCCCCCCCCCC, 2, x, y) -#define SWAP8(x, y) SWAPN(0x0F0F0F0F0F0F0F0F, 0xF0F0F0F0F0F0F0F0, 4, x, y) - - SWAP2(q[0], q[1]); - SWAP2(q[2], q[3]); - SWAP2(q[4], q[5]); - SWAP2(q[6], q[7]); - - SWAP4(q[0], q[2]); - SWAP4(q[1], q[3]); - SWAP4(q[4], q[6]); - SWAP4(q[5], q[7]); - - SWAP8(q[0], q[4]); - SWAP8(q[1], q[5]); - SWAP8(q[2], q[6]); - SWAP8(q[3], q[7]); -} - - -static void br_aes_ct64_interleave_in(uint64_t *q0, uint64_t *q1, const uint32_t *w) { - uint64_t x0, x1, x2, x3; - - x0 = w[0]; - x1 = w[1]; - x2 = w[2]; - x3 = w[3]; - x0 |= (x0 << 16); - x1 |= (x1 << 16); - x2 |= (x2 << 16); - x3 |= (x3 << 16); - x0 &= (uint64_t)0x0000FFFF0000FFFF; - x1 &= (uint64_t)0x0000FFFF0000FFFF; - x2 &= (uint64_t)0x0000FFFF0000FFFF; - x3 &= (uint64_t)0x0000FFFF0000FFFF; - x0 |= (x0 << 8); - x1 |= (x1 << 8); - x2 |= (x2 << 8); - x3 |= (x3 << 8); - x0 &= (uint64_t)0x00FF00FF00FF00FF; - x1 &= (uint64_t)0x00FF00FF00FF00FF; - x2 &= (uint64_t)0x00FF00FF00FF00FF; - x3 &= (uint64_t)0x00FF00FF00FF00FF; - *q0 = x0 | (x2 << 8); - *q1 = x1 | (x3 << 8); -} - - -static void br_aes_ct64_interleave_out(uint32_t *w, uint64_t q0, uint64_t q1) { - uint64_t x0, x1, x2, x3; - - x0 = q0 & (uint64_t)0x00FF00FF00FF00FF; - x1 = q1 & (uint64_t)0x00FF00FF00FF00FF; - x2 = (q0 >> 8) & (uint64_t)0x00FF00FF00FF00FF; - x3 = (q1 >> 8) & (uint64_t)0x00FF00FF00FF00FF; - x0 |= (x0 >> 8); - x1 |= (x1 >> 8); - x2 |= (x2 >> 8); - x3 |= (x3 >> 8); - x0 &= (uint64_t)0x0000FFFF0000FFFF; - x1 &= (uint64_t)0x0000FFFF0000FFFF; - x2 &= (uint64_t)0x0000FFFF0000FFFF; - x3 &= (uint64_t)0x0000FFFF0000FFFF; - w[0] = (uint32_t)x0 | (uint32_t)(x0 >> 16); - w[1] = (uint32_t)x1 | (uint32_t)(x1 >> 16); - w[2] = (uint32_t)x2 | (uint32_t)(x2 >> 16); - w[3] = (uint32_t)x3 | (uint32_t)(x3 >> 16); -} - -static inline void add_round_key(uint64_t *q, const uint64_t *sk) { - q[0] ^= sk[0]; - q[1] ^= sk[1]; - q[2] ^= sk[2]; - q[3] ^= sk[3]; - q[4] ^= sk[4]; - q[5] ^= sk[5]; - q[6] ^= sk[6]; - q[7] ^= sk[7]; -} - -static inline void shift_rows(uint64_t *q) { - int i; - - for (i = 0; i < 8; i++) { - uint64_t x; - - x = q[i]; - q[i] = (x & (uint64_t)0x000000000000FFFF) - | ((x & (uint64_t)0x00000000FFF00000) >> 4) - | ((x & (uint64_t)0x00000000000F0000) << 12) - | ((x & (uint64_t)0x0000FF0000000000) >> 8) - | ((x & (uint64_t)0x000000FF00000000) << 8) - | ((x & (uint64_t)0xF000000000000000) >> 12) - | ((x & (uint64_t)0x0FFF000000000000) << 4); - } -} - -static inline uint64_t rotr32(uint64_t x) { - return (x << 32) | (x >> 32); -} - -static inline void mix_columns(uint64_t *q) { - uint64_t q0, q1, q2, q3, q4, q5, q6, q7; - uint64_t r0, r1, r2, r3, r4, r5, r6, r7; - - q0 = q[0]; - q1 = q[1]; - q2 = q[2]; - q3 = q[3]; - q4 = q[4]; - q5 = q[5]; - q6 = q[6]; - q7 = q[7]; - r0 = (q0 >> 16) | (q0 << 48); - r1 = (q1 >> 16) | (q1 << 48); - r2 = (q2 >> 16) | (q2 << 48); - r3 = (q3 >> 16) | (q3 << 48); - r4 = (q4 >> 16) | (q4 << 48); - r5 = (q5 >> 16) | (q5 << 48); - r6 = (q6 >> 16) | (q6 << 48); - r7 = (q7 >> 16) | (q7 << 48); - - q[0] = q7 ^ r7 ^ r0 ^ rotr32(q0 ^ r0); - q[1] = q0 ^ r0 ^ q7 ^ r7 ^ r1 ^ rotr32(q1 ^ r1); - q[2] = q1 ^ r1 ^ r2 ^ rotr32(q2 ^ r2); - q[3] = q2 ^ r2 ^ q7 ^ r7 ^ r3 ^ rotr32(q3 ^ r3); - q[4] = q3 ^ r3 ^ q7 ^ r7 ^ r4 ^ rotr32(q4 ^ r4); - q[5] = q4 ^ r4 ^ r5 ^ rotr32(q5 ^ r5); - q[6] = q5 ^ r5 ^ r6 ^ rotr32(q6 ^ r6); - q[7] = q6 ^ r6 ^ r7 ^ rotr32(q7 ^ r7); -} - -static void interleave_constant(uint64_t *out, const unsigned char *in) { - uint32_t tmp_32_constant[16]; - int i; - - br_range_dec32le(tmp_32_constant, 16, in); - for (i = 0; i < 4; i++) { - br_aes_ct64_interleave_in(&out[i], &out[i + 4], tmp_32_constant + (i << 2)); - } - br_aes_ct64_ortho(out); -} - -static void interleave_constant32(uint32_t *out, const unsigned char *in) { - int i; - for (i = 0; i < 4; i++) { - out[2 * i] = br_dec32le(in + 4 * i); - out[2 * i + 1] = br_dec32le(in + 4 * i + 16); - } - br_aes_ct_ortho(out); -} - -void tweak_constants(spx_ctx *ctx) { - unsigned char buf[40 * 16]; - int i; - - /* Use the standard constants to generate tweaked ones. */ - memcpy((uint8_t *)ctx->tweaked512_rc64, (uint8_t *)haraka512_rc64, 40 * 16); - - /* Constants for pk.seed */ - haraka_S(buf, 40 * 16, ctx->pub_seed, SPX_N, ctx); - for (i = 0; i < 10; i++) { - interleave_constant32(ctx->tweaked256_rc32[i], buf + 32 * i); - interleave_constant(ctx->tweaked512_rc64[i], buf + 64 * i); - } -} - -static void haraka_S_absorb(unsigned char *s, unsigned int r, - const unsigned char *m, unsigned long long mlen, - unsigned char p, const spx_ctx *ctx) { - unsigned long long i; - PQCLEAN_VLA(uint8_t, t, r); - - while (mlen >= r) { - /* XOR block to state */ - for (i = 0; i < r; ++i) { - s[i] ^= m[i]; - } - haraka512_perm(s, s, ctx); - 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; ++i) { - s[i] ^= t[i]; - } -} - -static void haraka_S_squeezeblocks(unsigned char *h, unsigned long long nblocks, - unsigned char *s, unsigned int r, - const spx_ctx *ctx) { - while (nblocks > 0) { - haraka512_perm(s, s, ctx); - memcpy(h, s, HARAKAS_RATE); - h += r; - nblocks--; - } -} - -void haraka_S_inc_init(uint8_t *s_inc) { - size_t i; - - for (i = 0; i < 64; i++) { - s_inc[i] = 0; - } - s_inc[64] = 0; -} - -void haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, - const spx_ctx *ctx) { - size_t i; - - /* Recall that s_inc[64] is the non-absorbed bytes xored into the state */ - while (mlen + s_inc[64] >= HARAKAS_RATE) { - for (i = 0; i < (size_t)(HARAKAS_RATE - s_inc[64]); i++) { - /* Take the i'th byte from message - xor with the s_inc[64] + i'th byte of the state */ - s_inc[s_inc[64] + i] ^= m[i]; - } - mlen -= (size_t)(HARAKAS_RATE - s_inc[64]); - m += HARAKAS_RATE - (uint8_t)s_inc[64]; - s_inc[64] = 0; - - haraka512_perm(s_inc, s_inc, ctx); - } - - for (i = 0; i < mlen; i++) { - s_inc[s_inc[64] + i] ^= m[i]; - } - s_inc[64] += (uint8_t)mlen; -} - -void haraka_S_inc_finalize(uint8_t *s_inc) { - /* After haraka_S_inc_absorb, we are guaranteed that s_inc[64] < HARAKAS_RATE, - so we can always use one more byte for p in the current state. */ - s_inc[s_inc[64]] ^= 0x1F; - s_inc[HARAKAS_RATE - 1] ^= 128; - s_inc[64] = 0; -} - -void haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, - const spx_ctx *ctx) { - size_t i; - - /* First consume any bytes we still have sitting around */ - for (i = 0; i < outlen && i < s_inc[64]; i++) { - /* There are s_inc[64] bytes left, so r - s_inc[64] is the first - available byte. We consume from there, i.e., up to r. */ - out[i] = (uint8_t)s_inc[(HARAKAS_RATE - s_inc[64] + i)]; - } - out += i; - outlen -= i; - s_inc[64] -= (uint8_t)i; - - /* Then squeeze the remaining necessary blocks */ - while (outlen > 0) { - haraka512_perm(s_inc, s_inc, ctx); - - for (i = 0; i < outlen && i < HARAKAS_RATE; i++) { - out[i] = s_inc[i]; - } - out += i; - outlen -= i; - s_inc[64] = (uint8_t)(HARAKAS_RATE - i); - } -} - -void haraka_S(unsigned char *out, unsigned long long outlen, - const unsigned char *in, unsigned long long inlen, - const spx_ctx *ctx) { - unsigned long long i; - unsigned char s[64]; - unsigned char d[32]; - - for (i = 0; i < 64; i++) { - s[i] = 0; - } - haraka_S_absorb(s, 32, in, inlen, 0x1F, ctx); - - haraka_S_squeezeblocks(out, outlen / 32, s, 32, ctx); - out += (outlen / 32) * 32; - - if (outlen % 32) { - haraka_S_squeezeblocks(d, 1, s, 32, ctx); - for (i = 0; i < outlen % 32; i++) { - out[i] = d[i]; - } - } -} - -void haraka512_perm(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx) { - uint32_t w[16]; - uint64_t q[8], tmp_q; - unsigned int i, j; - - br_range_dec32le(w, 16, in); - for (i = 0; i < 4; i++) { - br_aes_ct64_interleave_in(&q[i], &q[i + 4], w + (i << 2)); - } - br_aes_ct64_ortho(q); - - /* AES rounds */ - for (i = 0; i < 5; i++) { - for (j = 0; j < 2; j++) { - br_aes_ct64_bitslice_Sbox(q); - shift_rows(q); - mix_columns(q); - add_round_key(q, ctx->tweaked512_rc64[2 * i + j]); - } - /* Mix states */ - for (j = 0; j < 8; j++) { - tmp_q = q[j]; - q[j] = (tmp_q & 0x0001000100010001) << 5 | - (tmp_q & 0x0002000200020002) << 12 | - (tmp_q & 0x0004000400040004) >> 1 | - (tmp_q & 0x0008000800080008) << 6 | - (tmp_q & 0x0020002000200020) << 9 | - (tmp_q & 0x0040004000400040) >> 4 | - (tmp_q & 0x0080008000800080) << 3 | - (tmp_q & 0x2100210021002100) >> 5 | - (tmp_q & 0x0210021002100210) << 2 | - (tmp_q & 0x0800080008000800) << 4 | - (tmp_q & 0x1000100010001000) >> 12 | - (tmp_q & 0x4000400040004000) >> 10 | - (tmp_q & 0x8400840084008400) >> 3; - } - } - - br_aes_ct64_ortho(q); - for (i = 0; i < 4; i ++) { - br_aes_ct64_interleave_out(w + (i << 2), q[i], q[i + 4]); - } - br_range_enc32le(out, w, 16); -} - -void haraka512(unsigned char *out, const unsigned char *in, const spx_ctx *ctx) { - int i; - - unsigned char buf[64]; - - haraka512_perm(buf, in, ctx); - /* Feed-forward */ - for (i = 0; i < 64; i++) { - buf[i] = buf[i] ^ in[i]; - } - - /* Truncated */ - memcpy(out, buf + 8, 8); - memcpy(out + 8, buf + 24, 8); - memcpy(out + 16, buf + 32, 8); - memcpy(out + 24, buf + 48, 8); -} - - -void haraka256(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx) { - uint32_t q[8], tmp_q; - int i, j; - - for (i = 0; i < 4; i++) { - q[2 * i] = br_dec32le(in + 4 * i); - q[2 * i + 1] = br_dec32le(in + 4 * i + 16); - } - br_aes_ct_ortho(q); - - /* AES rounds */ - for (i = 0; i < 5; i++) { - for (j = 0; j < 2; j++) { - br_aes_ct_bitslice_Sbox(q); - shift_rows32(q); - mix_columns32(q); - add_round_key32(q, ctx->tweaked256_rc32[2 * i + j]); - } - - /* Mix states */ - for (j = 0; j < 8; j++) { - tmp_q = q[j]; - q[j] = (tmp_q & 0x81818181) | - (tmp_q & 0x02020202) << 1 | - (tmp_q & 0x04040404) << 2 | - (tmp_q & 0x08080808) << 3 | - (tmp_q & 0x10101010) >> 3 | - (tmp_q & 0x20202020) >> 2 | - (tmp_q & 0x40404040) >> 1; - } - } - - br_aes_ct_ortho(q); - for (i = 0; i < 4; i++) { - br_enc32le(out + 4 * i, q[2 * i]); - br_enc32le(out + 4 * i + 16, q[2 * i + 1]); - } - - for (i = 0; i < 32; i++) { - out[i] ^= in[i]; - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/haraka.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/haraka.h deleted file mode 100644 index 737cb6065f..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/haraka.h +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef SPX_HARAKA_H -#define SPX_HARAKA_H - -#include "context.h" -#include "params.h" - -/* Tweak constants with seed */ -#define tweak_constants SPX_NAMESPACE(tweak_constants) -void tweak_constants(spx_ctx *ctx); - -/* Haraka Sponge */ -#define haraka_S_inc_init SPX_NAMESPACE(haraka_S_inc_init) -void haraka_S_inc_init(uint8_t *s_inc); -#define haraka_S_inc_absorb SPX_NAMESPACE(haraka_S_inc_absorb) -void haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, - const spx_ctx *ctx); -#define haraka_S_inc_finalize SPX_NAMESPACE(haraka_S_inc_finalize) -void haraka_S_inc_finalize(uint8_t *s_inc); -#define haraka_S_inc_squeeze SPX_NAMESPACE(haraka_S_inc_squeeze) -void haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, - const spx_ctx *ctx); -#define haraka_S SPX_NAMESPACE(haraka_S) -void haraka_S(unsigned char *out, unsigned long long outlen, - const unsigned char *in, unsigned long long inlen, - const spx_ctx *ctx); - -/* Applies the 512-bit Haraka permutation to in. */ -#define haraka512_perm SPX_NAMESPACE(haraka512_perm) -void haraka512_perm(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx); - -/* Implementation of Haraka-512 */ -#define haraka512 SPX_NAMESPACE(haraka512) -void haraka512(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx); - -/* Implementation of Haraka-256 */ -#define haraka256 SPX_NAMESPACE(haraka256) -void haraka256(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/haraka_offsets.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/haraka_offsets.h deleted file mode 100644 index 7c062272a0..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/haraka_offsets.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef HARAKA_OFFSETS_H_ -#define HARAKA_OFFSETS_H_ - -/* - * Offsets of various fields in the address structure when we use Haraka as - * the Sphincs+ hash function - */ - -#define SPX_OFFSET_LAYER 3 /* The byte used to specify the Merkle tree layer */ -#define SPX_OFFSET_TREE 8 /* The start of the 8 byte field used to specify the tree */ -#define SPX_OFFSET_TYPE 19 /* The byte used to specify the hash type (reason) */ -#define SPX_OFFSET_KP_ADDR2 22 /* The high byte used to specify the key pair (which one-time signature) */ -#define SPX_OFFSET_KP_ADDR1 23 /* The low byte used to specify the key pair */ -#define SPX_OFFSET_CHAIN_ADDR 27 /* The byte used to specify the chain address (which Winternitz chain) */ -#define SPX_OFFSET_HASH_ADDR 31 /* The byte used to specify the hash address (where in the Winternitz chain) */ -#define SPX_OFFSET_TREE_HGT 27 /* The byte used to specify the height of this node in the FORS or Merkle tree */ -#define SPX_OFFSET_TREE_INDEX 28 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ - -#define SPX_HARAKA 1 - -#endif /* HARAKA_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/hash.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/hash.h deleted file mode 100644 index f7c87d4c3c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/hash.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef SPX_HASH_H -#define SPX_HASH_H - -#include -#include - -#include "context.h" -#include "params.h" - -#define prf_addr SPX_NAMESPACE(prf_addr) -void prf_addr(unsigned char *out, const spx_ctx *ctx, - const uint32_t addr[8]); - -#define gen_message_random SPX_NAMESPACE(gen_message_random) -void gen_message_random(unsigned char *R, const unsigned char *sk_prf, - const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx); - -#define hash_message SPX_NAMESPACE(hash_message) -void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx); - - - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/hash_haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/hash_haraka.c deleted file mode 100644 index 750a67423b..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/hash_haraka.c +++ /dev/null @@ -1,81 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "utils.h" - -#include "haraka.h" -#include "hash.h" - -/* - * Computes PRF(key, addr), given a secret key of SPX_N bytes and an address - */ -void prf_addr(unsigned char *out, const spx_ctx *ctx, - const uint32_t addr[8]) { - /* Since SPX_N may be smaller than 32, we need temporary buffers. */ - unsigned char outbuf[32]; - unsigned char buf[64] = {0}; - - memcpy(buf, addr, SPX_ADDR_BYTES); - memcpy(buf + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); - - haraka512(outbuf, (const void *)buf, ctx); - memcpy(out, outbuf, SPX_N); -} - -/** - * Computes the message-dependent randomness R, using a secret seed and an - * optional randomization value as well as the message. - */ -void gen_message_random(unsigned char *R, const unsigned char *sk_prf, - const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx) { - uint8_t s_inc[65]; - - haraka_S_inc_init(s_inc); - haraka_S_inc_absorb(s_inc, sk_prf, SPX_N, ctx); - haraka_S_inc_absorb(s_inc, optrand, SPX_N, ctx); - haraka_S_inc_absorb(s_inc, m, mlen, ctx); - haraka_S_inc_finalize(s_inc); - haraka_S_inc_squeeze(R, SPX_N, s_inc, ctx); -} - -/** - * Computes the message hash using R, the public key, and the message. - * Outputs the message digest and the index of the leaf. The index is split in - * the tree index and the leaf index, for convenient copying to an address. - */ -void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx) { -#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) -#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) -#define SPX_LEAF_BITS SPX_TREE_HEIGHT -#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) -#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) - - unsigned char buf[SPX_DGST_BYTES]; - unsigned char *bufp = buf; - uint8_t s_inc[65]; - - haraka_S_inc_init(s_inc); - haraka_S_inc_absorb(s_inc, R, SPX_N, ctx); - haraka_S_inc_absorb(s_inc, pk + SPX_N, SPX_N, ctx); // Only absorb root part of pk - haraka_S_inc_absorb(s_inc, m, mlen, ctx); - haraka_S_inc_finalize(s_inc); - haraka_S_inc_squeeze(buf, SPX_DGST_BYTES, s_inc, ctx); - - memcpy(digest, bufp, SPX_FORS_MSG_BYTES); - bufp += SPX_FORS_MSG_BYTES; - - - *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); - *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); - bufp += SPX_TREE_BYTES; - - *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); - *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/merkle.c b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/merkle.c deleted file mode 100644 index 0c1479fd93..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/merkle.c +++ /dev/null @@ -1,59 +0,0 @@ -#include -#include - -#include "address.h" -#include "merkle.h" -#include "params.h" -#include "utils.h" -#include "utilsx1.h" -#include "wots.h" -#include "wotsx1.h" - -/* - * This generates a Merkle signature (WOTS signature followed by the Merkle - * authentication path). This is in this file because most of the complexity - * is involved with the WOTS signature; the Merkle authentication path logic - * is mostly hidden in treehashx4 - */ -void merkle_sign(uint8_t *sig, unsigned char *root, - const spx_ctx *ctx, - uint32_t wots_addr[8], uint32_t tree_addr[8], - uint32_t idx_leaf) { - unsigned char *auth_path = sig + SPX_WOTS_BYTES; - struct leaf_info_x1 info = { 0 }; - unsigned steps[ SPX_WOTS_LEN ]; - - info.wots_sig = sig; - chain_lengths(steps, root); - info.wots_steps = steps; - - set_type(&tree_addr[0], SPX_ADDR_TYPE_HASHTREE); - set_type(&info.pk_addr[0], SPX_ADDR_TYPE_WOTSPK); - copy_subtree_addr(&info.leaf_addr[0], wots_addr); - copy_subtree_addr(&info.pk_addr[0], wots_addr); - - info.wots_sign_leaf = idx_leaf; - - treehashx1(root, auth_path, ctx, - idx_leaf, 0, - SPX_TREE_HEIGHT, - wots_gen_leafx1, - tree_addr, &info); -} - -/* Compute root node of the top-most subtree. */ -void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { - /* We do not need the auth path in key generation, but it simplifies the - code to have just one treehash routine that computes both root and path - in one function. */ - unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; - uint32_t top_tree_addr[8] = {0}; - uint32_t wots_addr[8] = {0}; - - set_layer_addr(top_tree_addr, SPX_D - 1); - set_layer_addr(wots_addr, SPX_D - 1); - - merkle_sign(auth_path, root, ctx, - wots_addr, top_tree_addr, - (uint32_t)~0 /* ~0 means "don't bother generating an auth path */ ); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/merkle.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/merkle.h deleted file mode 100644 index 769cf2e970..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/merkle.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef MERKLE_H_ -#define MERKLE_H_ - -#include - -#include "context.h" -#include "params.h" - -/* Generate a Merkle signature (WOTS signature followed by the Merkle */ -/* authentication path) */ -#define merkle_sign SPX_NAMESPACE(merkle_sign) -void merkle_sign(uint8_t *sig, unsigned char *root, - const spx_ctx *ctx, - uint32_t wots_addr[8], uint32_t tree_addr[8], - uint32_t idx_leaf); - -/* Compute the root node of the top-most subtree. */ -#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) -void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); - -#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/nistapi.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/nistapi.h deleted file mode 100644 index 3cb71afad4..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/nistapi.h +++ /dev/null @@ -1,87 +0,0 @@ -#ifndef SPX_API_H -#define SPX_API_H - -#include -#include - -#include "params.h" - -#define CRYPTO_ALGNAME "SPHINCS+" - -#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES -#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES -#define CRYPTO_BYTES SPX_BYTES -#define CRYPTO_SEEDBYTES (3*SPX_N) - -/* - * Returns the length of a secret key, in bytes - */ -#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) -size_t crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) -size_t crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) -size_t crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) -size_t crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) -int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) -int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) -int crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) -int crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -#define crypto_sign SPX_NAMESPACE(crypto_sign) -int crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) -int crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/params.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/params.h deleted file mode 100644 index b4f8c6e933..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/params.h +++ /dev/null @@ -1,56 +0,0 @@ -#ifndef SPX_PARAMS_H -#define SPX_PARAMS_H - -#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_##s - -/* Hash output length in bytes. */ -#define SPX_N 24 -/* Height of the hypertree. */ -#define SPX_FULL_HEIGHT 66 -/* Number of subtree layer. */ -#define SPX_D 22 -/* FORS tree dimensions. */ -#define SPX_FORS_HEIGHT 8 -#define SPX_FORS_TREES 33 -/* Winternitz parameter, */ -#define SPX_WOTS_W 16 - -/* The hash function is defined by linking a different hash.c file, as opposed - to setting a #define constant. */ - -/* For clarity */ -#define SPX_ADDR_BYTES 32 - -/* WOTS parameters. */ -#define SPX_WOTS_LOGW 4 - -#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) - -/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#define SPX_WOTS_LEN2 3 - -#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) -#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) -#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES - -/* Subtree size. */ -#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) - -//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT -// #error SPX_D should always divide SPX_FULL_HEIGHT -//#endif - -/* FORS parameters. */ -#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) -#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) -#define SPX_FORS_PK_BYTES SPX_N - -/* Resulting SPX sizes. */ -#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ - SPX_FULL_HEIGHT * SPX_N) -#define SPX_PK_BYTES (2 * SPX_N) -#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) - -#include "haraka_offsets.h" - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/sign.c b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/sign.c deleted file mode 100644 index 9d0c7d1b22..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/sign.c +++ /dev/null @@ -1,286 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "context.h" -#include "fors.h" -#include "hash.h" -#include "merkle.h" -#include "nistapi.h" -#include "params.h" -#include "randombytes.h" -#include "thash.h" -#include "utils.h" -#include "wots.h" - -/* - * Returns the length of a secret key, in bytes - */ -size_t crypto_sign_secretkeybytes(void) { - return CRYPTO_SECRETKEYBYTES; -} - -/* - * Returns the length of a public key, in bytes - */ -size_t crypto_sign_publickeybytes(void) { - return CRYPTO_PUBLICKEYBYTES; -} - -/* - * Returns the length of a signature, in bytes - */ -size_t crypto_sign_bytes(void) { - return CRYPTO_BYTES; -} - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t crypto_sign_seedbytes(void) { - return CRYPTO_SEEDBYTES; -} - -/* - * Generates an SPX key pair given a seed of length - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed) { - spx_ctx ctx; - - /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ - memcpy(sk, seed, CRYPTO_SEEDBYTES); - - memcpy(pk, sk + 2 * SPX_N, SPX_N); - - memcpy(ctx.pub_seed, pk, SPX_N); - memcpy(ctx.sk_seed, sk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - /* Compute root node of the top-most subtree. */ - merkle_gen_root(sk + 3 * SPX_N, &ctx); - - // cleanup - free_hash_function(&ctx); - - memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); - - return 0; -} - -/* - * Generates an SPX key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { - uint8_t seed[CRYPTO_SEEDBYTES]; - randombytes(seed, CRYPTO_SEEDBYTES); - crypto_sign_seed_keypair(pk, sk, seed); - - return 0; -} - -/** - * Returns an array containing a detached signature. - */ -int crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - spx_ctx ctx; - - const uint8_t *sk_prf = sk + SPX_N; - const uint8_t *pk = sk + 2 * SPX_N; - - uint8_t optrand[SPX_N]; - uint8_t mhash[SPX_FORS_MSG_BYTES]; - uint8_t root[SPX_N]; - uint32_t i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - - memcpy(ctx.sk_seed, sk, SPX_N); - memcpy(ctx.pub_seed, pk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - set_type(wots_addr, SPX_ADDR_TYPE_WOTS); - set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); - - /* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ - randombytes(optrand, SPX_N); - /* Compute the digest randomization value. */ - gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); - - /* Derive the message digest and leaf index from R, PK and M. */ - hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); - sig += SPX_N; - - set_tree_addr(wots_addr, tree); - set_keypair_addr(wots_addr, idx_leaf); - - /* Sign the message hash using FORS. */ - fors_sign(sig, root, mhash, &ctx, wots_addr); - sig += SPX_FORS_BYTES; - - for (i = 0; i < SPX_D; i++) { - set_layer_addr(tree_addr, i); - set_tree_addr(tree_addr, tree); - - copy_subtree_addr(wots_addr, tree_addr); - set_keypair_addr(wots_addr, idx_leaf); - - merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); - sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); - tree = tree >> SPX_TREE_HEIGHT; - } - - free_hash_function(&ctx); - - *siglen = SPX_BYTES; - - return 0; -} - -/** - * Verifies a detached signature and message under a given public key. - */ -int crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk) { - spx_ctx ctx; - const uint8_t *pub_root = pk + SPX_N; - uint8_t mhash[SPX_FORS_MSG_BYTES]; - uint8_t wots_pk[SPX_WOTS_BYTES]; - uint8_t root[SPX_N]; - uint8_t leaf[SPX_N]; - unsigned int i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - if (siglen != SPX_BYTES) { - return -1; - } - - memcpy(ctx.pub_seed, pk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - set_type(wots_addr, SPX_ADDR_TYPE_WOTS); - set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); - set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); - - /* Derive the message digest and leaf index from R || PK || M. */ - /* The additional SPX_N is a result of the hash domain separator. */ - hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); - sig += SPX_N; - - /* Layer correctly defaults to 0, so no need to set_layer_addr */ - set_tree_addr(wots_addr, tree); - set_keypair_addr(wots_addr, idx_leaf); - - fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); - sig += SPX_FORS_BYTES; - - /* For each subtree.. */ - for (i = 0; i < SPX_D; i++) { - set_layer_addr(tree_addr, i); - set_tree_addr(tree_addr, tree); - - copy_subtree_addr(wots_addr, tree_addr); - set_keypair_addr(wots_addr, idx_leaf); - - copy_keypair_addr(wots_pk_addr, wots_addr); - - /* The WOTS public key is only correct if the signature was correct. */ - /* Initially, root is the FORS pk, but on subsequent iterations it is - the root of the subtree below the currently processed subtree. */ - wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); - sig += SPX_WOTS_BYTES; - - /* Compute the leaf node using the WOTS public key. */ - thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); - - /* Compute the root node of this subtree. */ - compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, - &ctx, tree_addr); - sig += SPX_TREE_HEIGHT * SPX_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); - tree = tree >> SPX_TREE_HEIGHT; - } - - // cleanup - free_hash_function(&ctx); - - /* Check if the root node equals the root node in the public key. */ - if (memcmp(root, pub_root, SPX_N) != 0) { - return -1; - } - - return 0; -} - - -/** - * Returns an array containing the signature followed by the message. - */ -int crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk) { - size_t siglen; - - crypto_sign_signature(sm, &siglen, m, mlen, sk); - - memmove(sm + SPX_BYTES, m, mlen); - *smlen = siglen + mlen; - - return 0; -} - -/** - * Verifies a given signature-message pair under a given public key. - */ -int crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk) { - /* The API caller does not necessarily know what size a signature should be - but SPHINCS+ signatures are always exactly SPX_BYTES. */ - if (smlen < SPX_BYTES) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - *mlen = smlen - SPX_BYTES; - - if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - /* If verification was successful, move the message to the right place. */ - memmove(m, sm + SPX_BYTES, *mlen); - - return 0; -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/thash.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/thash.h deleted file mode 100644 index 8687ccfb4d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/thash.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef SPX_THASH_H -#define SPX_THASH_H - -#include "context.h" -#include "params.h" - -#include - -#define thash SPX_NAMESPACE(thash) -void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/thash_haraka_robust.c b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/thash_haraka_robust.c deleted file mode 100644 index 109502cbc2..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/thash_haraka_robust.c +++ /dev/null @@ -1,45 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "thash.h" -#include "utils.h" - -#include "haraka.h" - -/** - * Takes an array of inblocks concatenated arrays of SPX_N bytes. - */ -void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]) { - PQCLEAN_VLA(uint8_t, buf, SPX_ADDR_BYTES + inblocks * SPX_N); - PQCLEAN_VLA(uint8_t, bitmask, inblocks * SPX_N); - unsigned char outbuf[32]; - unsigned char buf_tmp[64]; - unsigned int i; - - if (inblocks == 1) { - /* F function */ - /* Since SPX_N may be smaller than 32, we need a temporary buffer. */ - memset(buf_tmp, 0, 64); - memcpy(buf_tmp, addr, 32); - - haraka256(outbuf, buf_tmp, ctx); - for (i = 0; i < inblocks * SPX_N; i++) { - buf_tmp[SPX_ADDR_BYTES + i] = in[i] ^ outbuf[i]; - } - haraka512(outbuf, buf_tmp, ctx); - memcpy(out, outbuf, SPX_N); - } else { - /* All other tweakable hashes*/ - memcpy(buf, addr, 32); - haraka_S(bitmask, inblocks * SPX_N, buf, SPX_ADDR_BYTES, ctx); - - for (i = 0; i < inblocks * SPX_N; i++) { - buf[SPX_ADDR_BYTES + i] = in[i] ^ bitmask[i]; - } - - haraka_S(out, SPX_N, buf, SPX_ADDR_BYTES + inblocks * SPX_N, ctx); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/utils.c b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/utils.c deleted file mode 100644 index 177b541fb9..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/utils.c +++ /dev/null @@ -1,148 +0,0 @@ -#include - -#include "utils.h" - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "thash.h" - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void ull_to_bytes(unsigned char *out, unsigned int outlen, - unsigned long long in) { - int i; - - /* Iterate over out in decreasing order, for big-endianness. */ - for (i = (signed int)outlen - 1; i >= 0; i--) { - out[i] = in & 0xff; - in = in >> 8; - } -} - -void u32_to_bytes(unsigned char *out, uint32_t in) { - out[0] = (unsigned char)(in >> 24); - out[1] = (unsigned char)(in >> 16); - out[2] = (unsigned char)(in >> 8); - out[3] = (unsigned char)in; -} - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { - unsigned long long retval = 0; - unsigned int i; - - for (i = 0; i < inlen; i++) { - retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); - } - return retval; -} - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void compute_root(unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const spx_ctx *ctx, uint32_t addr[8]) { - uint32_t i; - unsigned char buffer[2 * SPX_N]; - - /* If leaf_idx is odd (last bit = 1), current path element is a right child - and auth_path has to go left. Otherwise it is the other way around. */ - if (leaf_idx & 1) { - memcpy(buffer + SPX_N, leaf, SPX_N); - memcpy(buffer, auth_path, SPX_N); - } else { - memcpy(buffer, leaf, SPX_N); - memcpy(buffer + SPX_N, auth_path, SPX_N); - } - auth_path += SPX_N; - - for (i = 0; i < tree_height - 1; i++) { - leaf_idx >>= 1; - idx_offset >>= 1; - /* Set the address of the node we're creating. */ - set_tree_height(addr, i + 1); - set_tree_index(addr, leaf_idx + idx_offset); - - /* Pick the right or left neighbor, depending on parity of the node. */ - if (leaf_idx & 1) { - thash(buffer + SPX_N, buffer, 2, ctx, addr); - memcpy(buffer, auth_path, SPX_N); - } else { - thash(buffer, buffer, 2, ctx, addr); - memcpy(buffer + SPX_N, auth_path, SPX_N); - } - auth_path += SPX_N; - } - - /* The last iteration is exceptional; we do not copy an auth_path node. */ - leaf_idx >>= 1; - idx_offset >>= 1; - set_tree_height(addr, tree_height); - set_tree_index(addr, leaf_idx + idx_offset); - thash(root, buffer, 2, ctx, addr); -} - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const spx_ctx * /* ctx */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), - uint32_t tree_addr[8]) { - PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); - PQCLEAN_VLA(unsigned int, heights, tree_height + 1); - unsigned int offset = 0; - uint32_t idx; - uint32_t tree_idx; - - for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { - /* Add the next leaf node to the stack. */ - gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); - offset++; - heights[offset - 1] = 0; - - /* If this is a node we need for the auth path.. */ - if ((leaf_idx ^ 0x1) == idx) { - memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); - } - - /* While the top-most nodes are of equal height.. */ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { - /* Compute index of the new node, in the next layer. */ - tree_idx = (idx >> (heights[offset - 1] + 1)); - - /* Set the address of the node we're creating. */ - set_tree_height(tree_addr, heights[offset - 1] + 1); - set_tree_index(tree_addr, - tree_idx + (idx_offset >> (heights[offset - 1] + 1))); - /* Hash the top-most nodes from the stack together. */ - thash(stack + (offset - 2)*SPX_N, - stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); - offset--; - /* Note that the top-most node is now one layer higher. */ - heights[offset - 1]++; - - /* If this is a node we need for the auth path.. */ - if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_path + heights[offset - 1]*SPX_N, - stack + (offset - 1)*SPX_N, SPX_N); - } - } - } - memcpy(root, stack, SPX_N); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/utils.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/utils.h deleted file mode 100644 index 64f5d5a53a..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/utils.h +++ /dev/null @@ -1,58 +0,0 @@ -#ifndef SPX_UTILS_H -#define SPX_UTILS_H - -#include - -#include "compat.h" -#include "context.h" -#include "params.h" - - -/* To support MSVC use alloca() instead of VLAs. See #20. */ - - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) -void ull_to_bytes(unsigned char *out, unsigned int outlen, - unsigned long long in); -#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) -void u32_to_bytes(unsigned char *out, uint32_t in); - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) -unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -#define compute_root SPX_NAMESPACE(compute_root) -void compute_root(unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const spx_ctx *ctx, uint32_t addr[8]); - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -#define treehash SPX_NAMESPACE(treehash) -void treehash(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const spx_ctx *ctx /* ctx */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), - uint32_t tree_addr[8]); - - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/utilsx1.c b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/utilsx1.c deleted file mode 100644 index fccb69b35d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/utilsx1.c +++ /dev/null @@ -1,100 +0,0 @@ -#include - -#include "utilsx1.h" - -#include "address.h" -#include "params.h" -#include "thash.h" -#include "utils.h" - -/* - * Generate the entire Merkle tree, computing the authentication path for - * leaf_idx, and the resulting root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) - * - * This expects tree_addr to be initialized to the addr structures for the - * Merkle tree nodes - * - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - * - * This works by using the standard Merkle tree building algorithm, - */ -void treehashx1(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, - uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* Where to write the leaves */, - const spx_ctx * /* ctx */, - uint32_t idx, void *info), - uint32_t tree_addr[8], - void *info) { - /* This is where we keep the intermediate nodes */ - PQCLEAN_VLA(uint8_t, stack, tree_height * SPX_N); - - uint32_t idx; - uint32_t max_idx = (uint32_t)((1 << tree_height) - 1); - for (idx = 0;; idx++) { - unsigned char current[2 * SPX_N]; /* Current logical node is at */ - /* index[SPX_N]. We do this to minimize the number of copies */ - /* needed during a thash */ - gen_leaf( ¤t[SPX_N], ctx, idx + idx_offset, - info ); - - /* Now combine the freshly generated right node with previously */ - /* generated left ones */ - uint32_t internal_idx_offset = idx_offset; - uint32_t internal_idx = idx; - uint32_t internal_leaf = leaf_idx; - uint32_t h; /* The height we are in the Merkle tree */ - for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { - - /* Check if we hit the top of the tree */ - if (h == tree_height) { - /* We hit the root; return it */ - memcpy( root, ¤t[SPX_N], SPX_N ); - return; - } - - /* - * Check if the node we have is a part of the - * authentication path; if it is, write it out - */ - if ((internal_idx ^ internal_leaf) == 0x01) { - memcpy( &auth_path[ h * SPX_N ], - ¤t[SPX_N], - SPX_N ); - } - - /* - * Check if we're at a left child; if so, stop going up the stack - * Exception: if we've reached the end of the tree, keep on going - * (so we combine the last 4 nodes into the one root node in two - * more iterations) - */ - if ((internal_idx & 1) == 0 && idx < max_idx) { - break; - } - - /* Ok, we're at a right node */ - /* Now combine the left and right logical nodes together */ - - /* Set the address of the node we're creating. */ - internal_idx_offset >>= 1; - set_tree_height(tree_addr, h + 1); - set_tree_index(tree_addr, internal_idx / 2 + internal_idx_offset ); - - unsigned char *left = &stack[h * SPX_N]; - memcpy( ¤t[0], left, SPX_N ); - thash( ¤t[1 * SPX_N], - ¤t[0 * SPX_N], - 2, ctx, tree_addr); - } - - /* We've hit a left child; save the current for when we get the */ - /* corresponding right right */ - memcpy( &stack[h * SPX_N], ¤t[SPX_N], SPX_N); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/utilsx1.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/utilsx1.h deleted file mode 100644 index e911d17d53..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/utilsx1.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef SPX_UTILSX4_H -#define SPX_UTILSX4_H - -#include - -#include "context.h" -#include "params.h" - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -#define treehashx1 SPX_NAMESPACE(treehashx1) -void treehashx1(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* Where to write the leaf */, - const spx_ctx * /* ctx */, - uint32_t addr_idx, void *info), - uint32_t tree_addrx4[8], void *info); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/wots.c b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/wots.c deleted file mode 100644 index 249717aaa8..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/wots.c +++ /dev/null @@ -1,108 +0,0 @@ -#include -#include - -#include "wots.h" -#include "wotsx1.h" - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "thash.h" -#include "utils.h" -#include "utilsx1.h" - -// TODO clarify address expectations, and make them more uniform. -// TODO i.e. do we expect types to be set already? -// TODO and do we expect modifications or copies? - -/** - * Computes the chaining function. - * out and in have to be n-byte arrays. - * - * Interprets in as start-th value of the chain. - * addr has to contain the address of the chain. - */ -static void gen_chain(unsigned char *out, const unsigned char *in, - unsigned int start, unsigned int steps, - const spx_ctx *ctx, uint32_t addr[8]) { - uint32_t i; - - /* Initialize out with the value at position 'start'. */ - memcpy(out, in, SPX_N); - - /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < SPX_WOTS_W; i++) { - set_hash_addr(addr, i); - thash(out, out, 1, ctx, addr); - } -} - -/** - * base_w algorithm as described in draft. - * Interprets an array of bytes as integers in base w. - * This only works when log_w is a divisor of 8. - */ -static void base_w(unsigned int *output, const int out_len, - const unsigned char *input) { - int in = 0; - int out = 0; - unsigned char total = 0; - int bits = 0; - int consumed; - - for (consumed = 0; consumed < out_len; consumed++) { - if (bits == 0) { - total = input[in]; - in++; - bits += 8; - } - bits -= SPX_WOTS_LOGW; - output[out] = (total >> bits) & (SPX_WOTS_W - 1); - out++; - } -} - -/* Computes the WOTS+ checksum over a message (in base_w). */ -static void wots_checksum(unsigned int *csum_base_w, - const unsigned int *msg_base_w) { - unsigned int csum = 0; - unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; - unsigned int i; - - /* Compute checksum. */ - for (i = 0; i < SPX_WOTS_LEN1; i++) { - csum += SPX_WOTS_W - 1 - msg_base_w[i]; - } - - /* Convert checksum to base_w. */ - /* Make sure expected empty zero bits are the least significant bits. */ - csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); - ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); - base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); -} - -/* Takes a message and derives the matching chain lengths. */ -void chain_lengths(unsigned int *lengths, const unsigned char *msg) { - base_w(lengths, SPX_WOTS_LEN1, msg); - wots_checksum(lengths + SPX_WOTS_LEN1, lengths); -} - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const spx_ctx *ctx, uint32_t addr[8]) { - unsigned int lengths[SPX_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < SPX_WOTS_LEN; i++) { - set_chain_addr(addr, i); - gen_chain(pk + i * SPX_N, sig + i * SPX_N, - lengths[i], SPX_WOTS_W - 1 - lengths[i], ctx, addr); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/wots.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/wots.h deleted file mode 100644 index 4e7692eeef..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/wots.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef SPX_WOTS_H -#define SPX_WOTS_H - -#include - -#include "context.h" -#include "params.h" - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) -void wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const spx_ctx *ctx, uint32_t addr[8]); - -/* - * Compute the chain lengths needed for a given message hash - */ -#define chain_lengths SPX_NAMESPACE(chain_lengths) -void chain_lengths(unsigned int *lengths, const unsigned char *msg); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/wotsx1.c b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/wotsx1.c deleted file mode 100644 index 3adec78dfb..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/wotsx1.c +++ /dev/null @@ -1,76 +0,0 @@ -#include -#include - -#include "wots.h" -#include "wotsx1.h" - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "thash.h" -#include "utils.h" - -/* - * This generates a WOTS public key - * It also generates the WOTS signature if leaf_info indicates - * that we're signing with this WOTS key - */ -void wots_gen_leafx1(unsigned char *dest, - const spx_ctx *ctx, - uint32_t leaf_idx, void *v_info) { - struct leaf_info_x1 *info = v_info; - uint32_t *leaf_addr = info->leaf_addr; - uint32_t *pk_addr = info->pk_addr; - unsigned int i, k; - unsigned char pk_buffer[ SPX_WOTS_BYTES ]; - unsigned char *buffer; - uint32_t wots_k_mask; - - if (leaf_idx == info->wots_sign_leaf) { - /* We're traversing the leaf that's signing; generate the WOTS */ - /* signature */ - wots_k_mask = 0; - } else { - /* Nope, we're just generating pk's; turn off the signature logic */ - wots_k_mask = (uint32_t)~0; - } - - set_keypair_addr( leaf_addr, leaf_idx ); - set_keypair_addr( pk_addr, leaf_idx ); - - for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { - uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k to */ - /* the step if we're generating a signature, ~0 if we're not */ - - /* Start with the secret seed */ - set_chain_addr(leaf_addr, i); - set_hash_addr(leaf_addr, 0); - set_type(leaf_addr, SPX_ADDR_TYPE_WOTSPRF); - - prf_addr(buffer, ctx, leaf_addr); - - set_type(leaf_addr, SPX_ADDR_TYPE_WOTS); - - /* Iterate down the WOTS chain */ - for (k = 0;; k++) { - /* Check if this is the value that needs to be saved as a */ - /* part of the WOTS signature */ - if (k == wots_k) { - memcpy( info->wots_sig + i * SPX_N, buffer, SPX_N ); - } - - /* Check if we hit the top of the chain */ - if (k == SPX_WOTS_W - 1) { - break; - } - - /* Iterate one step on the chain */ - set_hash_addr(leaf_addr, k); - - thash(buffer, buffer, 1, ctx, leaf_addr); - } - } - - /* Do the final thash to generate the public keys */ - thash(dest, pk_buffer, SPX_WOTS_LEN, ctx, pk_addr); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/wotsx1.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/wotsx1.h deleted file mode 100644 index e617929f96..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-robust_clean/wotsx1.h +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef WOTSX1_H_ -#define WOTSX1_H_ - -#include - -#include "context.h" -#include "params.h" - -/* - * This is here to provide an interface to the internal wots_gen_leafx1 - * routine. While this routine is not referenced in the package outside of - * wots.c, it is called from the stand-alone benchmark code to characterize - * the performance - */ -struct leaf_info_x1 { - unsigned char *wots_sig; - uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ - uint32_t *wots_steps; - uint32_t leaf_addr[8]; - uint32_t pk_addr[8]; -}; - -/* Macro to set the leaf_info to something 'benign', that is, it would */ -/* run with the same time as it does during the real signing process */ -/* Used only by the benchmark code */ -#define INITIALIZE_LEAF_INFO_X1(info, addr, step_buffer) { \ - (info).wots_sig = 0; \ - (info).wots_sign_leaf = ~0; \ - (info).wots_steps = step_buffer; \ - memcpy( &(info).leaf_addr[0], (addr), 32 ); \ - memcpy( &(info).pk_addr[0], (addr), 32 ); \ - } - -#define wots_gen_leafx1 SPX_NAMESPACE(wots_gen_leafx1) -void wots_gen_leafx1(unsigned char *dest, - const spx_ctx *ctx, - uint32_t leaf_idx, void *v_info); - -#endif /* WOTSX1_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/LICENSE b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/LICENSE deleted file mode 100644 index 670154e353..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/LICENSE +++ /dev/null @@ -1,116 +0,0 @@ -CC0 1.0 Universal - -Statement of Purpose - -The laws of most jurisdictions throughout the world automatically confer -exclusive Copyright and Related Rights (defined below) upon the creator and -subsequent owner(s) (each and all, an "owner") of an original work of -authorship and/or a database (each, a "Work"). - -Certain owners wish to permanently relinquish those rights to a Work for the -purpose of contributing to a commons of creative, cultural and scientific -works ("Commons") that the public can reliably and without fear of later -claims of infringement build upon, modify, incorporate in other works, reuse -and redistribute as freely as possible in any form whatsoever and for any -purposes, including without limitation commercial purposes. These owners may -contribute to the Commons to promote the ideal of a free culture and the -further production of creative, cultural and scientific works, or to gain -reputation or greater distribution for their Work in part through the use and -efforts of others. - -For these and/or other purposes and motivations, and without any expectation -of additional consideration or compensation, the person associating CC0 with a -Work (the "Affirmer"), to the extent that he or she is an owner of Copyright -and Related Rights in the Work, voluntarily elects to apply CC0 to the Work -and publicly distribute the Work under its terms, with knowledge of his or her -Copyright and Related Rights in the Work and the meaning and intended legal -effect of CC0 on those rights. - -1. Copyright and Related Rights. A Work made available under CC0 may be -protected by copyright and related or neighboring rights ("Copyright and -Related Rights"). Copyright and Related Rights include, but are not limited -to, the following: - - i. the right to reproduce, adapt, distribute, perform, display, communicate, - and translate a Work; - - ii. moral rights retained by the original author(s) and/or performer(s); - - iii. publicity and privacy rights pertaining to a person's image or likeness - depicted in a Work; - - iv. rights protecting against unfair competition in regards to a Work, - subject to the limitations in paragraph 4(a), below; - - v. rights protecting the extraction, dissemination, use and reuse of data in - a Work; - - vi. database rights (such as those arising under Directive 96/9/EC of the - European Parliament and of the Council of 11 March 1996 on the legal - protection of databases, and under any national implementation thereof, - including any amended or successor version of such directive); and - - vii. other similar, equivalent or corresponding rights throughout the world - based on applicable law or treaty, and any national implementations thereof. - -2. Waiver. To the greatest extent permitted by, but not in contravention of, -applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and -unconditionally waives, abandons, and surrenders all of Affirmer's Copyright -and Related Rights and associated claims and causes of action, whether now -known or unknown (including existing as well as future claims and causes of -action), in the Work (i) in all territories worldwide, (ii) for the maximum -duration provided by applicable law or treaty (including future time -extensions), (iii) in any current or future medium and for any number of -copies, and (iv) for any purpose whatsoever, including without limitation -commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes -the Waiver for the benefit of each member of the public at large and to the -detriment of Affirmer's heirs and successors, fully intending that such Waiver -shall not be subject to revocation, rescission, cancellation, termination, or -any other legal or equitable action to disrupt the quiet enjoyment of the Work -by the public as contemplated by Affirmer's express Statement of Purpose. - -3. Public License Fallback. Should any part of the Waiver for any reason be -judged legally invalid or ineffective under applicable law, then the Waiver -shall be preserved to the maximum extent permitted taking into account -Affirmer's express Statement of Purpose. In addition, to the extent the Waiver -is so judged Affirmer hereby grants to each affected person a royalty-free, -non transferable, non sublicensable, non exclusive, irrevocable and -unconditional license to exercise Affirmer's Copyright and Related Rights in -the Work (i) in all territories worldwide, (ii) for the maximum duration -provided by applicable law or treaty (including future time extensions), (iii) -in any current or future medium and for any number of copies, and (iv) for any -purpose whatsoever, including without limitation commercial, advertising or -promotional purposes (the "License"). The License shall be deemed effective as -of the date CC0 was applied by Affirmer to the Work. Should any part of the -License for any reason be judged legally invalid or ineffective under -applicable law, such partial invalidity or ineffectiveness shall not -invalidate the remainder of the License, and in such case Affirmer hereby -affirms that he or she will not (i) exercise any of his or her remaining -Copyright and Related Rights in the Work or (ii) assert any associated claims -and causes of action with respect to the Work, in either case contrary to -Affirmer's express Statement of Purpose. - -4. Limitations and Disclaimers. - - a. No trademark or patent rights held by Affirmer are waived, abandoned, - surrendered, licensed or otherwise affected by this document. - - b. Affirmer offers the Work as-is and makes no representations or warranties - of any kind concerning the Work, express, implied, statutory or otherwise, - including without limitation warranties of title, merchantability, fitness - for a particular purpose, non infringement, or the absence of latent or - other defects, accuracy, or the present or absence of errors, whether or not - discoverable, all to the greatest extent permissible under applicable law. - - c. Affirmer disclaims responsibility for clearing rights of other persons - that may apply to the Work or any use thereof, including without limitation - any person's Copyright and Related Rights in the Work. Further, Affirmer - disclaims responsibility for obtaining any necessary consents, permissions - or other rights required for any use of the Work. - - d. Affirmer understands and acknowledges that Creative Commons is not a - party to this document and has no duty or obligation with respect to this - CC0 or use of the Work. - -For more information, please see - diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/address.c b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/address.c deleted file mode 100644 index b956e9cb29..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/address.c +++ /dev/null @@ -1,91 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "utils.h" - -/* - * Specify which level of Merkle tree (the "layer") we're working on - */ -void set_layer_addr(uint32_t addr[8], uint32_t layer) { - ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; -} - -/* - * Specify which Merkle tree within the level (the "tree address") we're working on - */ -void set_tree_addr(uint32_t addr[8], uint64_t tree) { - ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); -} - -/* - * Specify the reason we'll use this address structure for, that is, what - * hash will we compute with it. This is used so that unrelated types of - * hashes don't accidentally get the same address structure. The type will be - * one of the SPX_ADDR_TYPE constants - */ -void set_type(uint32_t addr[8], uint32_t type) { - ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; -} - -/* - * Copy the layer and tree fields of the address structure. This is used - * when we're doing multiple types of hashes within the same Merkle tree - */ -void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { - memcpy( out, in, SPX_OFFSET_TREE + 8 ); -} - -/* These functions are used for OTS addresses. */ - -/* - * Specify which Merkle leaf we're working on; that is, which OTS keypair - * we're talking about. - */ -void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { - ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; -} - -/* - * Copy the layer, tree and keypair fields of the address structure. This is - * used when we're doing multiple things within the same OTS keypair - */ -void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { - memcpy( out, in, SPX_OFFSET_TREE + 8 ); - ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; -} - -/* - * Specify which Merkle chain within the OTS we're working with - * (the chain address) - */ -void set_chain_addr(uint32_t addr[8], uint32_t chain) { - ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; -} - -/* - * Specify where in the Merkle chain we are -* (the hash address) - */ -void set_hash_addr(uint32_t addr[8], uint32_t hash) { - ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; -} - -/* These functions are used for all hash tree addresses (including FORS). */ - -/* - * Specify the height of the node in the Merkle/FORS tree we are in - * (the tree height) - */ -void set_tree_height(uint32_t addr[8], uint32_t tree_height) { - ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; -} - -/* - * Specify the distance from the left edge of the node in the Merkle/FORS tree - * (the tree index) - */ -void set_tree_index(uint32_t addr[8], uint32_t tree_index) { - u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/address.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/address.h deleted file mode 100644 index 24a84eb40c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/address.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef SPX_ADDRESS_H -#define SPX_ADDRESS_H - -#include - -#include "params.h" - -/* The hash types that are passed to set_type */ -#define SPX_ADDR_TYPE_WOTS 0 -#define SPX_ADDR_TYPE_WOTSPK 1 -#define SPX_ADDR_TYPE_HASHTREE 2 -#define SPX_ADDR_TYPE_FORSTREE 3 -#define SPX_ADDR_TYPE_FORSPK 4 -#define SPX_ADDR_TYPE_WOTSPRF 5 -#define SPX_ADDR_TYPE_FORSPRF 6 - -#define set_layer_addr SPX_NAMESPACE(set_layer_addr) -void set_layer_addr(uint32_t addr[8], uint32_t layer); - -#define set_tree_addr SPX_NAMESPACE(set_tree_addr) -void set_tree_addr(uint32_t addr[8], uint64_t tree); - -#define set_type SPX_NAMESPACE(set_type) -void set_type(uint32_t addr[8], uint32_t type); - -/* Copies the layer and tree part of one address into the other */ -#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) -void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for WOTS and FORS addresses. */ - -#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) -void set_keypair_addr(uint32_t addr[8], uint32_t keypair); - -#define set_chain_addr SPX_NAMESPACE(set_chain_addr) -void set_chain_addr(uint32_t addr[8], uint32_t chain); - -#define set_hash_addr SPX_NAMESPACE(set_hash_addr) -void set_hash_addr(uint32_t addr[8], uint32_t hash); - -#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) -void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for all hash tree addresses (including FORS). */ - -#define set_tree_height SPX_NAMESPACE(set_tree_height) -void set_tree_height(uint32_t addr[8], uint32_t tree_height); - -#define set_tree_index SPX_NAMESPACE(set_tree_index) -void set_tree_index(uint32_t addr[8], uint32_t tree_index); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/api.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/api.h deleted file mode 100644 index 1d3e324184..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/api.h +++ /dev/null @@ -1,77 +0,0 @@ -#ifndef PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_API_H -#define PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_API_H - -#include -#include - -#define PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_CRYPTO_ALGNAME "SPHINCS+-haraka-192f-simple" - -#define PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_CRYPTO_SECRETKEYBYTES 96 -#define PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_CRYPTO_PUBLICKEYBYTES 48 -#define PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_CRYPTO_BYTES 35664 - -#define PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_CRYPTO_SEEDBYTES 72 - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, - const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk); -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/context.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/context.h deleted file mode 100644 index f03446b9cb..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/context.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef SPX_CONTEXT_H -#define SPX_CONTEXT_H - -#include - -#include "immintrin.h" -#include "params.h" - -typedef struct { - uint8_t pub_seed[SPX_N]; - uint8_t sk_seed[SPX_N]; - - __m128i rc[40]; -} spx_ctx; - -#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) -void initialize_hash_function(spx_ctx *ctx); - -#define free_hash_function SPX_NAMESPACE(free_hash_function) -void free_hash_function(spx_ctx *ctx); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/context_haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/context_haraka.c deleted file mode 100644 index f1cd7e3664..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/context_haraka.c +++ /dev/null @@ -1,11 +0,0 @@ -#include "context.h" -#include "haraka.h" - -void initialize_hash_function(spx_ctx *ctx) { - tweak_constants(ctx); -} - -// we don't support heap-based haraka right now -void free_hash_function(spx_ctx *ctx) { - (void)ctx; // suppress unused variable warnings -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/fors.c b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/fors.c deleted file mode 100644 index f1b0639cfc..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/fors.c +++ /dev/null @@ -1,202 +0,0 @@ -#include -#include -#include - -#include "fors.h" - -#include "address.h" -#include "hash.h" -#include "hashx4.h" -#include "thash.h" -#include "thashx4.h" -#include "utils.h" -#include "utilsx4.h" - -static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, - uint32_t fors_leaf_addr[8]) { - prf_addr(sk, ctx, fors_leaf_addr); -} - -static void fors_gen_skx4(unsigned char *sk0, - unsigned char *sk1, - unsigned char *sk2, - unsigned char *sk3, const spx_ctx *ctx, - uint32_t fors_leaf_addrx4[4 * 8]) { - prf_addrx4(sk0, sk1, sk2, sk3, - ctx, fors_leaf_addrx4); -} - -static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, - const spx_ctx *ctx, - uint32_t fors_leaf_addr[8]) { - thash(leaf, sk, 1, ctx, fors_leaf_addr); -} - -static void fors_sk_to_leafx4(unsigned char *leaf0, - unsigned char *leaf1, - unsigned char *leaf2, - unsigned char *leaf3, - const unsigned char *sk0, - const unsigned char *sk1, - const unsigned char *sk2, - const unsigned char *sk3, - const spx_ctx *ctx, - uint32_t fors_leaf_addrx4[4 * 8]) { - thashx4(leaf0, leaf1, leaf2, leaf3, - sk0, sk1, sk2, sk3, - 1, ctx, fors_leaf_addrx4); -} - -struct fors_gen_leaf_info { - uint32_t leaf_addrx[4 * 8]; -}; - -static void fors_gen_leafx4(unsigned char *leaf, - const spx_ctx *ctx, - uint32_t addr_idx, void *info) { - struct fors_gen_leaf_info *fors_info = info; - uint32_t *fors_leaf_addrx4 = fors_info->leaf_addrx; - unsigned int j; - - /* Only set the parts that the caller doesn't set */ - for (j = 0; j < 4; j++) { - set_tree_index(fors_leaf_addrx4 + j * 8, addr_idx + j); - set_type(fors_leaf_addrx4 + j * 8, SPX_ADDR_TYPE_FORSPRF); - } - - fors_gen_skx4(leaf + 0 * SPX_N, - leaf + 1 * SPX_N, - leaf + 2 * SPX_N, - leaf + 3 * SPX_N, - ctx, fors_leaf_addrx4); - - for (j = 0; j < 4; j++) { - set_type(fors_leaf_addrx4 + j * 8, SPX_ADDR_TYPE_FORSTREE); - } - - fors_sk_to_leafx4(leaf + 0 * SPX_N, - leaf + 1 * SPX_N, - leaf + 2 * SPX_N, - leaf + 3 * SPX_N, - leaf + 0 * SPX_N, - leaf + 1 * SPX_N, - leaf + 2 * SPX_N, - leaf + 3 * SPX_N, - ctx, fors_leaf_addrx4); -} - -/** - * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - * Assumes indices has space for SPX_FORS_TREES integers. - */ -static void message_to_indices(uint32_t *indices, const unsigned char *m) { - unsigned int i, j; - unsigned int offset = 0; - - for (i = 0; i < SPX_FORS_TREES; i++) { - indices[i] = 0; - for (j = 0; j < SPX_FORS_HEIGHT; j++) { - indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); - offset++; - } - } -} - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -void fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]) { - uint32_t indices[SPX_FORS_TREES]; - unsigned char roots[SPX_FORS_TREES * SPX_N]; - uint32_t fors_tree_addr[4 * 8] = {0}; - struct fors_gen_leaf_info fors_info = {0}; - uint32_t *fors_leaf_addr = fors_info.leaf_addrx; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - for (i = 0; i < 4; i++) { - copy_keypair_addr(fors_tree_addr + 8 * i, fors_addr); - set_type(fors_tree_addr + 8 * i, SPX_ADDR_TYPE_FORSTREE); - copy_keypair_addr(fors_leaf_addr + 8 * i, fors_addr); - } - copy_keypair_addr(fors_pk_addr, fors_addr); - set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < SPX_FORS_TREES; i++) { - idx_offset = i * (1 << SPX_FORS_HEIGHT); - - set_tree_height(fors_tree_addr, 0); - set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Include the secret key part that produces the selected leaf node. */ - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); - fors_gen_sk(sig, ctx, fors_tree_addr); - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); - sig += SPX_N; - - /* Compute the authentication path for this leaf node. */ - treehashx4(roots + i * SPX_N, sig, ctx, - indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx4, - fors_tree_addr, &fors_info); - - sig += SPX_N * SPX_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); -} - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -void fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]) { - uint32_t indices[SPX_FORS_TREES]; - unsigned char roots[SPX_FORS_TREES * SPX_N]; - unsigned char leaf[SPX_N]; - uint32_t fors_tree_addr[8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - copy_keypair_addr(fors_tree_addr, fors_addr); - copy_keypair_addr(fors_pk_addr, fors_addr); - - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); - set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < SPX_FORS_TREES; i++) { - idx_offset = i * (1 << SPX_FORS_HEIGHT); - - set_tree_height(fors_tree_addr, 0); - set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Derive the leaf from the included secret key part. */ - fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); - sig += SPX_N; - - /* Derive the corresponding root node of this tree. */ - compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, - sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); - sig += SPX_N * SPX_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/fors.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/fors.h deleted file mode 100644 index 509140a178..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/fors.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef SPX_FORS_H -#define SPX_FORS_H - -#include - -#include "context.h" -#include "params.h" - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -#define fors_sign SPX_NAMESPACE(fors_sign) -void fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]); - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) -void fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/haraka.c deleted file mode 100644 index b414b691d7..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/haraka.c +++ /dev/null @@ -1,702 +0,0 @@ -/* -Plain C implementation of the Haraka256 and Haraka512 permutations. -*/ -#include -#include -#include -#include -#include - -#include "haraka.h" -#include "harakax4.h" -#include "utils.h" - -#define HARAKAS_RATE 32 - -#define u64 unsigned long -#define u128 __m128i - -#define LOAD(src) _mm_loadu_si128((u128 *)(src)) -#define STORE(dest,src) _mm_storeu_si128((u128 *)(dest),src) - -#define XOR128(a, b) _mm_xor_si128(a, b) - -#define AES2(s0, s1, rci) \ - s0 = _mm_aesenc_si128(s0, *(rci)); \ - (s1) = _mm_aesenc_si128(s1, *((rci) + 1)); \ - (s0) = _mm_aesenc_si128(s0, *((rci) + 2)); \ - (s1) = _mm_aesenc_si128(s1, *((rci) + 3)); - -#define AES2_4x(s0, s1, s2, s3, rci) \ - AES2((s0)[0], (s0)[1], rci); \ - AES2((s1)[0], (s1)[1], rci); \ - AES2((s2)[0], (s2)[1], rci); \ - AES2((s3)[0], (s3)[1], rci); - -#define AES4(s0, s1, s2, s3, rci) \ - s0 = _mm_aesenc_si128(s0, *(rci)); \ - (s1) = _mm_aesenc_si128(s1, *((rci) + 1)); \ - (s2) = _mm_aesenc_si128(s2, *((rci) + 2)); \ - (s3) = _mm_aesenc_si128(s3, *((rci) + 3)); \ - (s0) = _mm_aesenc_si128(s0, *((rci) + 4)); \ - (s1) = _mm_aesenc_si128(s1, *((rci) + 5)); \ - (s2) = _mm_aesenc_si128(s2, *((rci) + 6)); \ - (s3) = _mm_aesenc_si128(s3, *((rci) + 7)); - -#define AES4_4x(s0, s1, s2, s3, rci) \ - AES4((s0)[0], (s0)[1], (s0)[2], (s0)[3], rci); \ - AES4((s1)[0], (s1)[1], (s1)[2], (s1)[3], rci); \ - AES4((s2)[0], (s2)[1], (s2)[2], (s2)[3], rci); \ - AES4((s3)[0], (s3)[1], (s3)[2], (s3)[3], rci); - -#define MIX2(s0, s1) \ - tmp = _mm_unpacklo_epi32(s0, s1); \ - (s1) = _mm_unpackhi_epi32(s0, s1); \ - (s0) = tmp; - -#define MIX4(s0, s1, s2, s3) \ - tmp = _mm_unpacklo_epi32(s0, s1); \ - (s0) = _mm_unpackhi_epi32(s0, s1); \ - (s1) = _mm_unpacklo_epi32(s2, s3); \ - (s2) = _mm_unpackhi_epi32(s2, s3); \ - (s3) = _mm_unpacklo_epi32(s0, s2); \ - (s0) = _mm_unpackhi_epi32(s0, s2); \ - (s2) = _mm_unpackhi_epi32(s1, tmp); \ - (s1) = _mm_unpacklo_epi32(s1, tmp); - -#define TRUNCSTORE(out, s0, s1, s2, s3) \ - _mm_storeu_si128((u128 *)(out), \ - _mm_castpd_si128(_mm_shuffle_pd(_mm_castsi128_pd(s0), _mm_castsi128_pd(s1), 3))); \ - _mm_storeu_si128((u128 *)((out) + 16), \ - _mm_castpd_si128(_mm_shuffle_pd(_mm_castsi128_pd(s2), _mm_castsi128_pd(s3), 0))); - -static void load_haraka_constants(u128 *rc) { - rc[0] = _mm_set_epi32((int)0x0684704c, (int)0xe620c00a, (int)0xb2c5fef0, (int)0x75817b9d); - rc[1] = _mm_set_epi32((int)0x8b66b4e1, (int)0x88f3a06b, (int)0x640f6ba4, (int)0x2f08f717); - rc[2] = _mm_set_epi32((int)0x3402de2d, (int)0x53f28498, (int)0xcf029d60, (int)0x9f029114); - rc[3] = _mm_set_epi32((int)0x0ed6eae6, (int)0x2e7b4f08, (int)0xbbf3bcaf, (int)0xfd5b4f79); - rc[4] = _mm_set_epi32((int)0xcbcfb0cb, (int)0x4872448b, (int)0x79eecd1c, (int)0xbe397044); - rc[5] = _mm_set_epi32((int)0x7eeacdee, (int)0x6e9032b7, (int)0x8d5335ed, (int)0x2b8a057b); - rc[6] = _mm_set_epi32((int)0x67c28f43, (int)0x5e2e7cd0, (int)0xe2412761, (int)0xda4fef1b); - rc[7] = _mm_set_epi32((int)0x2924d9b0, (int)0xafcacc07, (int)0x675ffde2, (int)0x1fc70b3b); - rc[8] = _mm_set_epi32((int)0xab4d63f1, (int)0xe6867fe9, (int)0xecdb8fca, (int)0xb9d465ee); - rc[9] = _mm_set_epi32((int)0x1c30bf84, (int)0xd4b7cd64, (int)0x5b2a404f, (int)0xad037e33); - rc[10] = _mm_set_epi32((int)0xb2cc0bb9, (int)0x941723bf, (int)0x69028b2e, (int)0x8df69800); - rc[11] = _mm_set_epi32((int)0xfa0478a6, (int)0xde6f5572, (int)0x4aaa9ec8, (int)0x5c9d2d8a); - rc[12] = _mm_set_epi32((int)0xdfb49f2b, (int)0x6b772a12, (int)0x0efa4f2e, (int)0x29129fd4); - rc[13] = _mm_set_epi32((int)0x1ea10344, (int)0xf449a236, (int)0x32d611ae, (int)0xbb6a12ee); - rc[14] = _mm_set_epi32((int)0xaf044988, (int)0x4b050084, (int)0x5f9600c9, (int)0x9ca8eca6); - rc[15] = _mm_set_epi32((int)0x21025ed8, (int)0x9d199c4f, (int)0x78a2c7e3, (int)0x27e593ec); - rc[16] = _mm_set_epi32((int)0xbf3aaaf8, (int)0xa759c9b7, (int)0xb9282ecd, (int)0x82d40173); - rc[17] = _mm_set_epi32((int)0x6260700d, (int)0x6186b017, (int)0x37f2efd9, (int)0x10307d6b); - rc[18] = _mm_set_epi32((int)0x5aca45c2, (int)0x21300443, (int)0x81c29153, (int)0xf6fc9ac6); - rc[19] = _mm_set_epi32((int)0x9223973c, (int)0x226b68bb, (int)0x2caf92e8, (int)0x36d1943a); - rc[20] = _mm_set_epi32((int)0xd3bf9238, (int)0x225886eb, (int)0x6cbab958, (int)0xe51071b4); - rc[21] = _mm_set_epi32((int)0xdb863ce5, (int)0xaef0c677, (int)0x933dfddd, (int)0x24e1128d); - rc[22] = _mm_set_epi32((int)0xbb606268, (int)0xffeba09c, (int)0x83e48de3, (int)0xcb2212b1); - rc[23] = _mm_set_epi32((int)0x734bd3dc, (int)0xe2e4d19c, (int)0x2db91a4e, (int)0xc72bf77d); - rc[24] = _mm_set_epi32((int)0x43bb47c3, (int)0x61301b43, (int)0x4b1415c4, (int)0x2cb3924e); - rc[25] = _mm_set_epi32((int)0xdba775a8, (int)0xe707eff6, (int)0x03b231dd, (int)0x16eb6899); - rc[26] = _mm_set_epi32((int)0x6df3614b, (int)0x3c755977, (int)0x8e5e2302, (int)0x7eca472c); - rc[27] = _mm_set_epi32((int)0xcda75a17, (int)0xd6de7d77, (int)0x6d1be5b9, (int)0xb88617f9); - rc[28] = _mm_set_epi32((int)0xec6b43f0, (int)0x6ba8e9aa, (int)0x9d6c069d, (int)0xa946ee5d); - rc[29] = _mm_set_epi32((int)0xcb1e6950, (int)0xf957332b, (int)0xa2531159, (int)0x3bf327c1); - rc[30] = _mm_set_epi32((int)0x2cee0c75, (int)0x00da619c, (int)0xe4ed0353, (int)0x600ed0d9); - rc[31] = _mm_set_epi32((int)0xf0b1a5a1, (int)0x96e90cab, (int)0x80bbbabc, (int)0x63a4a350); - rc[32] = _mm_set_epi32((int)0xae3db102, (int)0x5e962988, (int)0xab0dde30, (int)0x938dca39); - rc[33] = _mm_set_epi32((int)0x17bb8f38, (int)0xd554a40b, (int)0x8814f3a8, (int)0x2e75b442); - rc[34] = _mm_set_epi32((int)0x34bb8a5b, (int)0x5f427fd7, (int)0xaeb6b779, (int)0x360a16f6); - rc[35] = _mm_set_epi32((int)0x26f65241, (int)0xcbe55438, (int)0x43ce5918, (int)0xffbaafde); - rc[36] = _mm_set_epi32((int)0x4ce99a54, (int)0xb9f3026a, (int)0xa2ca9cf7, (int)0x839ec978); - rc[37] = _mm_set_epi32((int)0xae51a51a, (int)0x1bdff7be, (int)0x40c06e28, (int)0x22901235); - rc[38] = _mm_set_epi32((int)0xa0c1613c, (int)0xba7ed22b, (int)0xc173bc0f, (int)0x48a659cf); - rc[39] = _mm_set_epi32((int)0x756acc03, (int)0x02288288, (int)0x4ad6bdfd, (int)0xe9c59da1); -} - -void tweak_constants(spx_ctx *ctx) { - int i; - unsigned char buf[40 * 16]; - - /* Use the standard constants to generate tweaked ones. */ - load_haraka_constants(ctx->rc); - - /* Constants for pk.seed */ - haraka_S(buf, 40 * 16, ctx->pub_seed, SPX_N, ctx); - - /* Tweak constants with the pub_seed */ - for (i = 0; i < 40; i++) { - ctx->rc[i] = LOAD(buf + i * 16); - } -} - -static void haraka_S_absorb(unsigned char *s, unsigned int r, - const unsigned char *m, unsigned long long mlen, - unsigned char p, const spx_ctx *ctx) { - unsigned long long i; - PQCLEAN_VLA(unsigned char, t, r); - - while (mlen >= r) { - // XOR block to state - STORE(s, XOR128(LOAD(s), LOAD(m))); - STORE(s + 16, XOR128(LOAD(s + 16), LOAD(m + 16))); - haraka512_perm(s, s, ctx); - 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; - STORE(s, XOR128(LOAD(s), LOAD(t))); - STORE(s + 16, XOR128(LOAD(s + 16), LOAD(t + 16))); -} - -static void haraka_S_absorb4x(unsigned char *s, - unsigned int r, - const unsigned char *m0, - const unsigned char *m1, - const unsigned char *m2, - const unsigned char *m3, - unsigned long long int mlen, - unsigned char p, - const spx_ctx *ctx) { - unsigned long long i; - PQCLEAN_VLA(unsigned char, t0, r); - PQCLEAN_VLA(unsigned char, t1, r); - PQCLEAN_VLA(unsigned char, t2, r); - PQCLEAN_VLA(unsigned char, t3, r); - - while (mlen >= r) { - // XOR block to state - STORE(s, XOR128(LOAD(s), LOAD(m0))); - STORE(s + 16, XOR128(LOAD(s + 16), LOAD(m0 + 16))); - STORE(s + 64, XOR128(LOAD(s + 64), LOAD(m1))); - STORE(s + 80, XOR128(LOAD(s + 80), LOAD(m1 + 16))); - STORE(s + 128, XOR128(LOAD(s + 128), LOAD(m2))); - STORE(s + 144, XOR128(LOAD(s + 144), LOAD(m2 + 16))); - STORE(s + 192, XOR128(LOAD(s + 192), LOAD(m3))); - STORE(s + 208, XOR128(LOAD(s + 208), LOAD(m3 + 16))); - - haraka512_perm_x4(s, s, ctx); - mlen -= r; - m0 += r; - m1 += r; - m2 += r; - m3 += r; - } - - for (i = 0; i < r; ++i) { - t0[i] = 0; - t1[i] = 0; - t2[i] = 0; - t3[i] = 0; - } - for (i = 0; i < mlen; ++i) { - t0[i] = m0[i]; - t1[i] = m1[i]; - t2[i] = m2[i]; - t3[i] = m3[i]; - } - - t0[i] = p; - t1[i] = p; - t2[i] = p; - t3[i] = p; - - t0[r - 1] |= 128; - t1[r - 1] |= 128; - t2[r - 1] |= 128; - t3[r - 1] |= 128; - - STORE(s, XOR128(LOAD(s), LOAD(t0))); - STORE(s + 16, XOR128(LOAD(s + 16), LOAD(t0 + 16))); - STORE(s + 64, XOR128(LOAD(s + 64), LOAD(t1))); - STORE(s + 80, XOR128(LOAD(s + 80), LOAD(t1 + 16))); - STORE(s + 128, XOR128(LOAD(s + 128), LOAD(t2))); - STORE(s + 144, XOR128(LOAD(s + 144), LOAD(t2 + 16))); - STORE(s + 192, XOR128(LOAD(s + 192), LOAD(t3))); - STORE(s + 208, XOR128(LOAD(s + 208), LOAD(t3 + 16))); -} - -static void haraka_S_squeezeblocks(unsigned char *h, unsigned long long nblocks, - unsigned char *s, unsigned int r, - const spx_ctx *ctx) { - while (nblocks > 0) { - haraka512_perm(s, s, ctx); - STORE(h, LOAD(s)); - STORE(h + 16, LOAD(s + 16)); - h += r; - nblocks--; - } -} - -static void haraka_S_squeezeblocks4x(unsigned char *h0, - unsigned char *h1, - unsigned char *h2, - unsigned char *h3, - unsigned long long nblocks, - unsigned char *s, - unsigned int r, - const spx_ctx *ctx) { - while (nblocks > 0) { - haraka512_perm_x4(s, s, ctx); - STORE(h0, LOAD(s)); - STORE(h0 + 16, LOAD(s + 16)); - STORE(h1, LOAD(s + 64)); - STORE(h1 + 16, LOAD(s + 80)); - STORE(h2, LOAD(s + 128)); - STORE(h2 + 16, LOAD(s + 144)); - STORE(h3, LOAD(s + 192)); - STORE(h3 + 16, LOAD(s + 208)); - h0 += r; - h1 += r; - h2 += r; - h3 += r; - nblocks--; - } -} - -void haraka_S_inc_init(uint8_t *s_inc) { - size_t i; - - for (i = 0; i < 64; i++) { - s_inc[i] = 0; - } - s_inc[64] = 0; -} - -void haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, - const spx_ctx *ctx) { - size_t i; - - /* Recall that s_inc[64] is the non-absorbed bytes xored into the state */ - while (mlen + s_inc[64] >= HARAKAS_RATE) { - for (i = 0; i < (size_t)(HARAKAS_RATE - s_inc[64]); i++) { - /* Take the i'th byte from message - xor with the s_inc[64] + i'th byte of the state */ - s_inc[s_inc[64] + i] ^= m[i]; - } - mlen -= (size_t)(HARAKAS_RATE - s_inc[64]); - m += HARAKAS_RATE - s_inc[64]; - s_inc[64] = 0; - - haraka512_perm(s_inc, s_inc, ctx); - } - - for (i = 0; i < mlen; i++) { - s_inc[s_inc[64] + i] ^= m[i]; - } - s_inc[64] += (uint8_t)mlen; -} - -void haraka_S_inc_finalize(uint8_t *s_inc) { - /* After haraka_S_inc_absorb, we are guaranteed that s_inc[64] < HARAKAS_RATE, - so we can always use one more byte for p in the current state. */ - s_inc[s_inc[64]] ^= 0x1F; - s_inc[HARAKAS_RATE - 1] ^= 128; - s_inc[64] = 0; -} - -void haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, - const spx_ctx *ctx) { - size_t i; - - /* First consume any bytes we still have sitting around */ - for (i = 0; i < outlen && i < s_inc[64]; i++) { - /* There are s_inc[64] bytes left, so r - s_inc[64] is the first - available byte. We consume from there, i.e., up to r. */ - out[i] = (uint8_t)s_inc[(HARAKAS_RATE - s_inc[64] + i)]; - } - out += i; - outlen -= i; - s_inc[64] -= (uint8_t)i; - - /* Then squeeze the remaining necessary blocks */ - while (outlen > 0) { - haraka512_perm(s_inc, s_inc, ctx); - - for (i = 0; i < outlen && i < HARAKAS_RATE; i++) { - out[i] = s_inc[i]; - } - out += i; - outlen -= i; - s_inc[64] = (uint8_t)(HARAKAS_RATE - i); - } -} - -void haraka_S(unsigned char *out, unsigned long long outlen, - const unsigned char *in, unsigned long long inlen, - const spx_ctx *ctx) { - unsigned long long i; - unsigned char s[64]; - unsigned char d[32]; - - for (i = 0; i < 64; i++) { - s[i] = 0; - } - haraka_S_absorb(s, HARAKAS_RATE, in, inlen, 0x1F, ctx); - - haraka_S_squeezeblocks(out, outlen / HARAKAS_RATE, s, HARAKAS_RATE, ctx); - out += (outlen / HARAKAS_RATE) * HARAKAS_RATE; - - if (outlen % HARAKAS_RATE) { - haraka_S_squeezeblocks(d, 1, s, HARAKAS_RATE, ctx); - for (i = 0; i < outlen % HARAKAS_RATE; i++) { - out[i] = d[i]; - } - } -} - -void haraka_Sx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned long long outlen, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - unsigned long long inlen, - const spx_ctx *ctx) { - unsigned long long i; - unsigned char s[64 * 4]; - unsigned char d0[32]; - unsigned char d1[32]; - unsigned char d2[32]; - unsigned char d3[32]; - - for (i = 0; i < 64 * 4; i++) { - s[i] = 0; - } - haraka_S_absorb4x(s, HARAKAS_RATE, in0, in1, in2, in3, inlen, 0x1F, ctx); - - haraka_S_squeezeblocks4x(out0, out1, out2, out3, outlen / HARAKAS_RATE, s, - HARAKAS_RATE, ctx); - out0 += (outlen / HARAKAS_RATE) * HARAKAS_RATE; - out1 += (outlen / HARAKAS_RATE) * HARAKAS_RATE; - out2 += (outlen / HARAKAS_RATE) * HARAKAS_RATE; - out3 += (outlen / HARAKAS_RATE) * HARAKAS_RATE; - - if (outlen % HARAKAS_RATE) { - haraka_S_squeezeblocks4x(d0, d1, d2, d3, 1, s, HARAKAS_RATE, ctx); - for (i = 0; i < outlen % HARAKAS_RATE; i++) { - out0[i] = d0[i]; - out1[i] = d1[i]; - out2[i] = d2[i]; - out3[i] = d3[i]; - } - } -} - -void haraka512_perm(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx) { - u128 s[4], tmp; - - s[0] = LOAD(in); - s[1] = LOAD(in + 16); - s[2] = LOAD(in + 32); - s[3] = LOAD(in + 48); - - AES4(s[0], s[1], s[2], s[3], ctx->rc); - MIX4(s[0], s[1], s[2], s[3]); - - AES4(s[0], s[1], s[2], s[3], ctx->rc + 8); - MIX4(s[0], s[1], s[2], s[3]); - - AES4(s[0], s[1], s[2], s[3], ctx->rc + 16); - MIX4(s[0], s[1], s[2], s[3]); - - AES4(s[0], s[1], s[2], s[3], ctx->rc + 24); - MIX4(s[0], s[1], s[2], s[3]); - - AES4(s[0], s[1], s[2], s[3], ctx->rc + 32); - MIX4(s[0], s[1], s[2], s[3]); - - STORE(out, s[0]); - STORE(out + 16, s[1]); - STORE(out + 32, s[2]); - STORE(out + 48, s[3]); -} - -void haraka512_perm_x4(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx) { - u128 s[4][4], tmp; - - s[0][0] = LOAD(in); - s[0][1] = LOAD(in + 16); - s[0][2] = LOAD(in + 32); - s[0][3] = LOAD(in + 48); - s[1][0] = LOAD(in + 64); - s[1][1] = LOAD(in + 80); - s[1][2] = LOAD(in + 96); - s[1][3] = LOAD(in + 112); - s[2][0] = LOAD(in + 128); - s[2][1] = LOAD(in + 144); - s[2][2] = LOAD(in + 160); - s[2][3] = LOAD(in + 176); - s[3][0] = LOAD(in + 192); - s[3][1] = LOAD(in + 208); - s[3][2] = LOAD(in + 224); - s[3][3] = LOAD(in + 240); - - AES4_4x(s[0], s[1], s[2], s[3], ctx->rc); - MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); - MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); - MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); - MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - - AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 8); - MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); - MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); - MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); - MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - - AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 16); - MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); - MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); - MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); - MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - - AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 24); - MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); - MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); - MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); - MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - - AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 32); - MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); - MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); - MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); - MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - - STORE(out, s[0][0]); - STORE(out + 16, s[0][1]); - STORE(out + 32, s[0][2]); - STORE(out + 48, s[0][3]); - STORE(out + 64, s[1][0]); - STORE(out + 80, s[1][1]); - STORE(out + 96, s[1][2]); - STORE(out + 112, s[1][3]); - STORE(out + 128, s[2][0]); - STORE(out + 144, s[2][1]); - STORE(out + 160, s[2][2]); - STORE(out + 176, s[2][3]); - STORE(out + 192, s[3][0]); - STORE(out + 208, s[3][1]); - STORE(out + 224, s[3][2]); - STORE(out + 240, s[3][3]); -} - -void haraka512(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx) { - u128 s[4], tmp; - - s[0] = LOAD(in); - s[1] = LOAD(in + 16); - s[2] = LOAD(in + 32); - s[3] = LOAD(in + 48); - - AES4(s[0], s[1], s[2], s[3], ctx->rc); - MIX4(s[0], s[1], s[2], s[3]); - - AES4(s[0], s[1], s[2], s[3], ctx->rc + 8); - MIX4(s[0], s[1], s[2], s[3]); - - AES4(s[0], s[1], s[2], s[3], ctx->rc + 16); - MIX4(s[0], s[1], s[2], s[3]); - - AES4(s[0], s[1], s[2], s[3], ctx->rc + 24); - MIX4(s[0], s[1], s[2], s[3]); - - AES4(s[0], s[1], s[2], s[3], ctx->rc + 32); - MIX4(s[0], s[1], s[2], s[3]); - - s[0] = XOR128(s[0], LOAD(in)); - s[1] = XOR128(s[1], LOAD(in + 16)); - s[2] = XOR128(s[2], LOAD(in + 32)); - s[3] = XOR128(s[3], LOAD(in + 48)); - - // truncate and store result - TRUNCSTORE(out, s[0], s[1], s[2], s[3]); -} - -void haraka512x4(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx) { - u128 s[4][4], tmp; - - s[0][0] = LOAD(in); - s[0][1] = LOAD(in + 16); - s[0][2] = LOAD(in + 32); - s[0][3] = LOAD(in + 48); - s[1][0] = LOAD(in + 64); - s[1][1] = LOAD(in + 80); - s[1][2] = LOAD(in + 96); - s[1][3] = LOAD(in + 112); - s[2][0] = LOAD(in + 128); - s[2][1] = LOAD(in + 144); - s[2][2] = LOAD(in + 160); - s[2][3] = LOAD(in + 176); - s[3][0] = LOAD(in + 192); - s[3][1] = LOAD(in + 208); - s[3][2] = LOAD(in + 224); - s[3][3] = LOAD(in + 240); - - AES4_4x(s[0], s[1], s[2], s[3], ctx->rc); - MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); - MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); - MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); - MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - - AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 8); - MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); - MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); - MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); - MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - - AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 16); - MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); - MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); - MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); - MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - - AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 24); - MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); - MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); - MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); - MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - - AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 32); - MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); - MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); - MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); - MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - - s[0][0] = XOR128(s[0][0], LOAD(in)); - s[0][1] = XOR128(s[0][1], LOAD(in + 16)); - s[0][2] = XOR128(s[0][2], LOAD(in + 32)); - s[0][3] = XOR128(s[0][3], LOAD(in + 48)); - s[1][0] = XOR128(s[1][0], LOAD(in + 64)); - s[1][1] = XOR128(s[1][1], LOAD(in + 80)); - s[1][2] = XOR128(s[1][2], LOAD(in + 96)); - s[1][3] = XOR128(s[1][3], LOAD(in + 112)); - s[2][0] = XOR128(s[2][0], LOAD(in + 128)); - s[2][1] = XOR128(s[2][1], LOAD(in + 144)); - s[2][2] = XOR128(s[2][2], LOAD(in + 160)); - s[2][3] = XOR128(s[2][3], LOAD(in + 176)); - s[3][0] = XOR128(s[3][0], LOAD(in + 192)); - s[3][1] = XOR128(s[3][1], LOAD(in + 208)); - s[3][2] = XOR128(s[3][2], LOAD(in + 224)); - s[3][3] = XOR128(s[3][3], LOAD(in + 240)); - - TRUNCSTORE(out, s[0][0], s[0][1], s[0][2], s[0][3]); - TRUNCSTORE((out + 32), s[1][0], s[1][1], s[1][2], s[1][3]); - TRUNCSTORE((out + 64), s[2][0], s[2][1], s[2][2], s[2][3]); - TRUNCSTORE((out + 96), s[3][0], s[3][1], s[3][2], s[3][3]); -} - -void haraka256(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx) { - u128 s[2], tmp; - - s[0] = LOAD(in); - s[1] = LOAD(in + 16); - - AES2(s[0], s[1], ctx->rc); - MIX2(s[0], s[1]); - - AES2(s[0], s[1], ctx->rc + 4); - MIX2(s[0], s[1]); - - AES2(s[0], s[1], ctx->rc + 8); - MIX2(s[0], s[1]); - - AES2(s[0], s[1], ctx->rc + 12); - MIX2(s[0], s[1]); - - AES2(s[0], s[1], ctx->rc + 16); - MIX2(s[0], s[1]); - - s[0] = XOR128(s[0], LOAD(in)); - s[1] = XOR128(s[1], LOAD(in + 16)); - - STORE(out, s[0]); - STORE(out + 16, s[1]); -} - -void haraka256x4(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx) { - u128 s[4][2], tmp; - - s[0][0] = LOAD(in); - s[0][1] = LOAD(in + 16); - s[1][0] = LOAD(in + 32); - s[1][1] = LOAD(in + 48); - s[2][0] = LOAD(in + 64); - s[2][1] = LOAD(in + 80); - s[3][0] = LOAD(in + 96); - s[3][1] = LOAD(in + 112); - - // Round 1 - AES2_4x(s[0], s[1], s[2], s[3], ctx->rc); - - MIX2(s[0][0], s[0][1]); - MIX2(s[1][0], s[1][1]); - MIX2(s[2][0], s[2][1]); - MIX2(s[3][0], s[3][1]); - - // Round 2 - AES2_4x(s[0], s[1], s[2], s[3], ctx->rc + 4); - - MIX2(s[0][0], s[0][1]); - MIX2(s[1][0], s[1][1]); - MIX2(s[2][0], s[2][1]); - MIX2(s[3][0], s[3][1]); - - // Round 3 - AES2_4x(s[0], s[1], s[2], s[3], ctx->rc + 8); - - MIX2(s[0][0], s[0][1]); - MIX2(s[1][0], s[1][1]); - MIX2(s[2][0], s[2][1]); - MIX2(s[3][0], s[3][1]); - - // Round 4 - AES2_4x(s[0], s[1], s[2], s[3], ctx->rc + 12); - - MIX2(s[0][0], s[0][1]); - MIX2(s[1][0], s[1][1]); - MIX2(s[2][0], s[2][1]); - MIX2(s[3][0], s[3][1]); - - // Round 5 - AES2_4x(s[0], s[1], s[2], s[3], ctx->rc + 16); - - MIX2(s[0][0], s[0][1]); - MIX2(s[1][0], s[1][1]); - MIX2(s[2][0], s[2][1]); - MIX2(s[3][0], s[3][1]); - - // Feed Forward - s[0][0] = _mm_xor_si128(s[0][0], LOAD(in)); - s[0][1] = _mm_xor_si128(s[0][1], LOAD(in + 16)); - s[1][0] = _mm_xor_si128(s[1][0], LOAD(in + 32)); - s[1][1] = _mm_xor_si128(s[1][1], LOAD(in + 48)); - s[2][0] = _mm_xor_si128(s[2][0], LOAD(in + 64)); - s[2][1] = _mm_xor_si128(s[2][1], LOAD(in + 80)); - s[3][0] = _mm_xor_si128(s[3][0], LOAD(in + 96)); - s[3][1] = _mm_xor_si128(s[3][1], LOAD(in + 112)); - - STORE(out, s[0][0]); - STORE(out + 16, s[0][1]); - STORE(out + 32, s[1][0]); - STORE(out + 48, s[1][1]); - STORE(out + 64, s[2][0]); - STORE(out + 80, s[2][1]); - STORE(out + 96, s[3][0]); - STORE(out + 112, s[3][1]); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/haraka.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/haraka.h deleted file mode 100644 index 737cb6065f..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/haraka.h +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef SPX_HARAKA_H -#define SPX_HARAKA_H - -#include "context.h" -#include "params.h" - -/* Tweak constants with seed */ -#define tweak_constants SPX_NAMESPACE(tweak_constants) -void tweak_constants(spx_ctx *ctx); - -/* Haraka Sponge */ -#define haraka_S_inc_init SPX_NAMESPACE(haraka_S_inc_init) -void haraka_S_inc_init(uint8_t *s_inc); -#define haraka_S_inc_absorb SPX_NAMESPACE(haraka_S_inc_absorb) -void haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, - const spx_ctx *ctx); -#define haraka_S_inc_finalize SPX_NAMESPACE(haraka_S_inc_finalize) -void haraka_S_inc_finalize(uint8_t *s_inc); -#define haraka_S_inc_squeeze SPX_NAMESPACE(haraka_S_inc_squeeze) -void haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, - const spx_ctx *ctx); -#define haraka_S SPX_NAMESPACE(haraka_S) -void haraka_S(unsigned char *out, unsigned long long outlen, - const unsigned char *in, unsigned long long inlen, - const spx_ctx *ctx); - -/* Applies the 512-bit Haraka permutation to in. */ -#define haraka512_perm SPX_NAMESPACE(haraka512_perm) -void haraka512_perm(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx); - -/* Implementation of Haraka-512 */ -#define haraka512 SPX_NAMESPACE(haraka512) -void haraka512(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx); - -/* Implementation of Haraka-256 */ -#define haraka256 SPX_NAMESPACE(haraka256) -void haraka256(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/haraka_offsets.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/haraka_offsets.h deleted file mode 100644 index 7c062272a0..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/haraka_offsets.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef HARAKA_OFFSETS_H_ -#define HARAKA_OFFSETS_H_ - -/* - * Offsets of various fields in the address structure when we use Haraka as - * the Sphincs+ hash function - */ - -#define SPX_OFFSET_LAYER 3 /* The byte used to specify the Merkle tree layer */ -#define SPX_OFFSET_TREE 8 /* The start of the 8 byte field used to specify the tree */ -#define SPX_OFFSET_TYPE 19 /* The byte used to specify the hash type (reason) */ -#define SPX_OFFSET_KP_ADDR2 22 /* The high byte used to specify the key pair (which one-time signature) */ -#define SPX_OFFSET_KP_ADDR1 23 /* The low byte used to specify the key pair */ -#define SPX_OFFSET_CHAIN_ADDR 27 /* The byte used to specify the chain address (which Winternitz chain) */ -#define SPX_OFFSET_HASH_ADDR 31 /* The byte used to specify the hash address (where in the Winternitz chain) */ -#define SPX_OFFSET_TREE_HGT 27 /* The byte used to specify the height of this node in the FORS or Merkle tree */ -#define SPX_OFFSET_TREE_INDEX 28 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ - -#define SPX_HARAKA 1 - -#endif /* HARAKA_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/harakax4.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/harakax4.h deleted file mode 100644 index eadc69aa48..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/harakax4.h +++ /dev/null @@ -1,36 +0,0 @@ -#ifndef SPX_HARAKAX4_H -#define SPX_HARAKAX4_H - -#include "context.h" -#include "params.h" - -/* Haraka Sponge */ -#define haraka_Sx4 SPX_NAMESPACE(haraka_Sx4) -void haraka_Sx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned long long outlen, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - unsigned long long inlen, - const spx_ctx *ctx); - -/* Applies the 512-bit Haraka permutation x4 to in. */ -#define haraka512_perm_x4 SPX_NAMESPACE(haraka512_perm_x4) -void haraka512_perm_x4(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx); - -/* Implementation of Haraka-512 x4*/ -#define haraka512x4 SPX_NAMESPACE(haraka512x4) -void haraka512x4(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx); - -/* Implementation of Haraka-256 x4 */ -#define haraka256x4 SPX_NAMESPACE(haraka256x4) -void haraka256x4(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/hash.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/hash.h deleted file mode 100644 index f7c87d4c3c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/hash.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef SPX_HASH_H -#define SPX_HASH_H - -#include -#include - -#include "context.h" -#include "params.h" - -#define prf_addr SPX_NAMESPACE(prf_addr) -void prf_addr(unsigned char *out, const spx_ctx *ctx, - const uint32_t addr[8]); - -#define gen_message_random SPX_NAMESPACE(gen_message_random) -void gen_message_random(unsigned char *R, const unsigned char *sk_prf, - const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx); - -#define hash_message SPX_NAMESPACE(hash_message) -void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx); - - - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/hash_haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/hash_haraka.c deleted file mode 100644 index 750a67423b..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/hash_haraka.c +++ /dev/null @@ -1,81 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "utils.h" - -#include "haraka.h" -#include "hash.h" - -/* - * Computes PRF(key, addr), given a secret key of SPX_N bytes and an address - */ -void prf_addr(unsigned char *out, const spx_ctx *ctx, - const uint32_t addr[8]) { - /* Since SPX_N may be smaller than 32, we need temporary buffers. */ - unsigned char outbuf[32]; - unsigned char buf[64] = {0}; - - memcpy(buf, addr, SPX_ADDR_BYTES); - memcpy(buf + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); - - haraka512(outbuf, (const void *)buf, ctx); - memcpy(out, outbuf, SPX_N); -} - -/** - * Computes the message-dependent randomness R, using a secret seed and an - * optional randomization value as well as the message. - */ -void gen_message_random(unsigned char *R, const unsigned char *sk_prf, - const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx) { - uint8_t s_inc[65]; - - haraka_S_inc_init(s_inc); - haraka_S_inc_absorb(s_inc, sk_prf, SPX_N, ctx); - haraka_S_inc_absorb(s_inc, optrand, SPX_N, ctx); - haraka_S_inc_absorb(s_inc, m, mlen, ctx); - haraka_S_inc_finalize(s_inc); - haraka_S_inc_squeeze(R, SPX_N, s_inc, ctx); -} - -/** - * Computes the message hash using R, the public key, and the message. - * Outputs the message digest and the index of the leaf. The index is split in - * the tree index and the leaf index, for convenient copying to an address. - */ -void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx) { -#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) -#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) -#define SPX_LEAF_BITS SPX_TREE_HEIGHT -#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) -#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) - - unsigned char buf[SPX_DGST_BYTES]; - unsigned char *bufp = buf; - uint8_t s_inc[65]; - - haraka_S_inc_init(s_inc); - haraka_S_inc_absorb(s_inc, R, SPX_N, ctx); - haraka_S_inc_absorb(s_inc, pk + SPX_N, SPX_N, ctx); // Only absorb root part of pk - haraka_S_inc_absorb(s_inc, m, mlen, ctx); - haraka_S_inc_finalize(s_inc); - haraka_S_inc_squeeze(buf, SPX_DGST_BYTES, s_inc, ctx); - - memcpy(digest, bufp, SPX_FORS_MSG_BYTES); - bufp += SPX_FORS_MSG_BYTES; - - - *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); - *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); - bufp += SPX_TREE_BYTES; - - *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); - *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/hash_harakax4.c b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/hash_harakax4.c deleted file mode 100644 index cfa5162d79..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/hash_harakax4.c +++ /dev/null @@ -1,35 +0,0 @@ -#include -#include - -#include "address.h" -#include "harakax4.h" -#include "hashx4.h" -#include "params.h" - -/* - * 4-way parallel version of prf_addr; takes 4x as much input and output - */ -#define prf_addrx4 SPX_NAMESPACE(prf_addrx4) -void prf_addrx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const spx_ctx *ctx, - const uint32_t addrx4[4 * 8]) { - unsigned char bufx4[4 * 64] = {0}; - /* Since SPX_N may be smaller than 32, we need temporary buffers. */ - unsigned char outbuf[4 * 32]; - unsigned int i; - - for (i = 0; i < 4; i++) { - memcpy(bufx4 + i * 64, addrx4 + i * 8, SPX_ADDR_BYTES); - memcpy(bufx4 + i * 64 + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); - } - - haraka512x4(outbuf, bufx4, ctx); - - memcpy(out0, outbuf, SPX_N); - memcpy(out1, outbuf + 32, SPX_N); - memcpy(out2, outbuf + 64, SPX_N); - memcpy(out3, outbuf + 96, SPX_N); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/hashx4.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/hashx4.h deleted file mode 100644 index 3751a0ebd0..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/hashx4.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef SPX_HASHX4_H -#define SPX_HASHX4_H - -#include - -#include "context.h" -#include "params.h" - -#define prf_addrx4 SPX_NAMESPACE(prf_addrx4) -void prf_addrx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const spx_ctx *ctx, - const uint32_t addrx4[4 * 8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/merkle.c b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/merkle.c deleted file mode 100644 index f57811c1ac..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/merkle.c +++ /dev/null @@ -1,64 +0,0 @@ -#include -#include - -#include "merkle.h" - -#include "address.h" -#include "params.h" -#include "utils.h" -#include "utilsx4.h" -#include "wots.h" -#include "wotsx4.h" - -/* - * This generates a Merkle signature (WOTS signature followed by the Merkle - * authentication path). - */ -void merkle_sign(uint8_t *sig, unsigned char *root, - const spx_ctx *ctx, - uint32_t wots_addr[8], uint32_t tree_addr[8], - uint32_t idx_leaf) { - unsigned char *auth_path = sig + SPX_WOTS_BYTES; - uint32_t tree_addrx4[4 * 8] = { 0 }; - int j; - struct leaf_info_x4 info = { 0 }; - unsigned steps[ SPX_WOTS_LEN ]; - - info.wots_sig = sig; - chain_lengths(steps, root); - info.wots_steps = steps; - - for (j = 0; j < 4; j++) { - set_type(&tree_addrx4[8 * j], SPX_ADDR_TYPE_HASHTREE); - set_type(&info.leaf_addr[8 * j], SPX_ADDR_TYPE_WOTS); - set_type(&info.pk_addr[8 * j], SPX_ADDR_TYPE_WOTSPK); - copy_subtree_addr(&tree_addrx4[8 * j], tree_addr); - copy_subtree_addr(&info.leaf_addr[8 * j], wots_addr); - copy_subtree_addr(&info.pk_addr[8 * j], wots_addr); - } - - info.wots_sign_leaf = idx_leaf; - - treehashx4(root, auth_path, ctx, - idx_leaf, 0, - SPX_TREE_HEIGHT, - wots_gen_leafx4, - tree_addrx4, &info); -} - -/* Compute root node of the top-most subtree. */ -void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { - /* We do not need the auth path in key generation, but it simplifies the - code to have just one treehash routine that computes both root and path - in one function. */ - unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; - uint32_t top_tree_addr[8] = {0}; - uint32_t wots_addr[8] = {0}; - - set_layer_addr(top_tree_addr, SPX_D - 1); - set_layer_addr(wots_addr, SPX_D - 1); - - merkle_sign(auth_path, root, ctx, - wots_addr, top_tree_addr, - ~0U /* ~0 means "don't bother generating an auth path */ ); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/merkle.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/merkle.h deleted file mode 100644 index 769cf2e970..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/merkle.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef MERKLE_H_ -#define MERKLE_H_ - -#include - -#include "context.h" -#include "params.h" - -/* Generate a Merkle signature (WOTS signature followed by the Merkle */ -/* authentication path) */ -#define merkle_sign SPX_NAMESPACE(merkle_sign) -void merkle_sign(uint8_t *sig, unsigned char *root, - const spx_ctx *ctx, - uint32_t wots_addr[8], uint32_t tree_addr[8], - uint32_t idx_leaf); - -/* Compute the root node of the top-most subtree. */ -#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) -void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); - -#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/nistapi.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/nistapi.h deleted file mode 100644 index 3cb71afad4..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/nistapi.h +++ /dev/null @@ -1,87 +0,0 @@ -#ifndef SPX_API_H -#define SPX_API_H - -#include -#include - -#include "params.h" - -#define CRYPTO_ALGNAME "SPHINCS+" - -#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES -#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES -#define CRYPTO_BYTES SPX_BYTES -#define CRYPTO_SEEDBYTES (3*SPX_N) - -/* - * Returns the length of a secret key, in bytes - */ -#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) -size_t crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) -size_t crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) -size_t crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) -size_t crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) -int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) -int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) -int crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) -int crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -#define crypto_sign SPX_NAMESPACE(crypto_sign) -int crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) -int crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/params.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/params.h deleted file mode 100644 index 916a7b09f6..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/params.h +++ /dev/null @@ -1,56 +0,0 @@ -#ifndef SPX_PARAMS_H -#define SPX_PARAMS_H - -#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_##s - -/* Hash output length in bytes. */ -#define SPX_N 24 -/* Height of the hypertree. */ -#define SPX_FULL_HEIGHT 66 -/* Number of subtree layer. */ -#define SPX_D 22 -/* FORS tree dimensions. */ -#define SPX_FORS_HEIGHT 8 -#define SPX_FORS_TREES 33 -/* Winternitz parameter, */ -#define SPX_WOTS_W 16 - -/* The hash function is defined by linking a different hash.c file, as opposed - to setting a #define constant. */ - -/* For clarity */ -#define SPX_ADDR_BYTES 32 - -/* WOTS parameters. */ -#define SPX_WOTS_LOGW 4 - -#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) - -/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#define SPX_WOTS_LEN2 3 - -#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) -#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) -#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES - -/* Subtree size. */ -#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) - -//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT -// #error SPX_D should always divide SPX_FULL_HEIGHT -//#endif - -/* FORS parameters. */ -#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) -#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) -#define SPX_FORS_PK_BYTES SPX_N - -/* Resulting SPX sizes. */ -#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ - SPX_FULL_HEIGHT * SPX_N) -#define SPX_PK_BYTES (2 * SPX_N) -#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) - -#include "haraka_offsets.h" - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/sign.c b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/sign.c deleted file mode 100644 index 9d0c7d1b22..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/sign.c +++ /dev/null @@ -1,286 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "context.h" -#include "fors.h" -#include "hash.h" -#include "merkle.h" -#include "nistapi.h" -#include "params.h" -#include "randombytes.h" -#include "thash.h" -#include "utils.h" -#include "wots.h" - -/* - * Returns the length of a secret key, in bytes - */ -size_t crypto_sign_secretkeybytes(void) { - return CRYPTO_SECRETKEYBYTES; -} - -/* - * Returns the length of a public key, in bytes - */ -size_t crypto_sign_publickeybytes(void) { - return CRYPTO_PUBLICKEYBYTES; -} - -/* - * Returns the length of a signature, in bytes - */ -size_t crypto_sign_bytes(void) { - return CRYPTO_BYTES; -} - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t crypto_sign_seedbytes(void) { - return CRYPTO_SEEDBYTES; -} - -/* - * Generates an SPX key pair given a seed of length - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed) { - spx_ctx ctx; - - /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ - memcpy(sk, seed, CRYPTO_SEEDBYTES); - - memcpy(pk, sk + 2 * SPX_N, SPX_N); - - memcpy(ctx.pub_seed, pk, SPX_N); - memcpy(ctx.sk_seed, sk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - /* Compute root node of the top-most subtree. */ - merkle_gen_root(sk + 3 * SPX_N, &ctx); - - // cleanup - free_hash_function(&ctx); - - memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); - - return 0; -} - -/* - * Generates an SPX key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { - uint8_t seed[CRYPTO_SEEDBYTES]; - randombytes(seed, CRYPTO_SEEDBYTES); - crypto_sign_seed_keypair(pk, sk, seed); - - return 0; -} - -/** - * Returns an array containing a detached signature. - */ -int crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - spx_ctx ctx; - - const uint8_t *sk_prf = sk + SPX_N; - const uint8_t *pk = sk + 2 * SPX_N; - - uint8_t optrand[SPX_N]; - uint8_t mhash[SPX_FORS_MSG_BYTES]; - uint8_t root[SPX_N]; - uint32_t i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - - memcpy(ctx.sk_seed, sk, SPX_N); - memcpy(ctx.pub_seed, pk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - set_type(wots_addr, SPX_ADDR_TYPE_WOTS); - set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); - - /* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ - randombytes(optrand, SPX_N); - /* Compute the digest randomization value. */ - gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); - - /* Derive the message digest and leaf index from R, PK and M. */ - hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); - sig += SPX_N; - - set_tree_addr(wots_addr, tree); - set_keypair_addr(wots_addr, idx_leaf); - - /* Sign the message hash using FORS. */ - fors_sign(sig, root, mhash, &ctx, wots_addr); - sig += SPX_FORS_BYTES; - - for (i = 0; i < SPX_D; i++) { - set_layer_addr(tree_addr, i); - set_tree_addr(tree_addr, tree); - - copy_subtree_addr(wots_addr, tree_addr); - set_keypair_addr(wots_addr, idx_leaf); - - merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); - sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); - tree = tree >> SPX_TREE_HEIGHT; - } - - free_hash_function(&ctx); - - *siglen = SPX_BYTES; - - return 0; -} - -/** - * Verifies a detached signature and message under a given public key. - */ -int crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk) { - spx_ctx ctx; - const uint8_t *pub_root = pk + SPX_N; - uint8_t mhash[SPX_FORS_MSG_BYTES]; - uint8_t wots_pk[SPX_WOTS_BYTES]; - uint8_t root[SPX_N]; - uint8_t leaf[SPX_N]; - unsigned int i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - if (siglen != SPX_BYTES) { - return -1; - } - - memcpy(ctx.pub_seed, pk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - set_type(wots_addr, SPX_ADDR_TYPE_WOTS); - set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); - set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); - - /* Derive the message digest and leaf index from R || PK || M. */ - /* The additional SPX_N is a result of the hash domain separator. */ - hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); - sig += SPX_N; - - /* Layer correctly defaults to 0, so no need to set_layer_addr */ - set_tree_addr(wots_addr, tree); - set_keypair_addr(wots_addr, idx_leaf); - - fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); - sig += SPX_FORS_BYTES; - - /* For each subtree.. */ - for (i = 0; i < SPX_D; i++) { - set_layer_addr(tree_addr, i); - set_tree_addr(tree_addr, tree); - - copy_subtree_addr(wots_addr, tree_addr); - set_keypair_addr(wots_addr, idx_leaf); - - copy_keypair_addr(wots_pk_addr, wots_addr); - - /* The WOTS public key is only correct if the signature was correct. */ - /* Initially, root is the FORS pk, but on subsequent iterations it is - the root of the subtree below the currently processed subtree. */ - wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); - sig += SPX_WOTS_BYTES; - - /* Compute the leaf node using the WOTS public key. */ - thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); - - /* Compute the root node of this subtree. */ - compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, - &ctx, tree_addr); - sig += SPX_TREE_HEIGHT * SPX_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); - tree = tree >> SPX_TREE_HEIGHT; - } - - // cleanup - free_hash_function(&ctx); - - /* Check if the root node equals the root node in the public key. */ - if (memcmp(root, pub_root, SPX_N) != 0) { - return -1; - } - - return 0; -} - - -/** - * Returns an array containing the signature followed by the message. - */ -int crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk) { - size_t siglen; - - crypto_sign_signature(sm, &siglen, m, mlen, sk); - - memmove(sm + SPX_BYTES, m, mlen); - *smlen = siglen + mlen; - - return 0; -} - -/** - * Verifies a given signature-message pair under a given public key. - */ -int crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk) { - /* The API caller does not necessarily know what size a signature should be - but SPHINCS+ signatures are always exactly SPX_BYTES. */ - if (smlen < SPX_BYTES) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - *mlen = smlen - SPX_BYTES; - - if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - /* If verification was successful, move the message to the right place. */ - memmove(m, sm + SPX_BYTES, *mlen); - - return 0; -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/thash.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/thash.h deleted file mode 100644 index 8687ccfb4d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/thash.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef SPX_THASH_H -#define SPX_THASH_H - -#include "context.h" -#include "params.h" - -#include - -#define thash SPX_NAMESPACE(thash) -void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/thash_haraka_simple.c b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/thash_haraka_simple.c deleted file mode 100644 index 207777bf8d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/thash_haraka_simple.c +++ /dev/null @@ -1,36 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "thash.h" -#include "utils.h" - -#include "haraka.h" - -/** - * Takes an array of inblocks concatenated arrays of SPX_N bytes. - */ -void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]) { - PQCLEAN_VLA(uint8_t, buf, SPX_ADDR_BYTES + inblocks * SPX_N); - unsigned char outbuf[32]; - unsigned char buf_tmp[64]; - - if (inblocks == 1) { - /* F function */ - /* Since SPX_N may be smaller than 32, we need a temporary buffer. */ - memset(buf_tmp, 0, 64); - memcpy(buf_tmp, addr, 32); - memcpy(buf_tmp + SPX_ADDR_BYTES, in, SPX_N); - - haraka512(outbuf, buf_tmp, ctx); - memcpy(out, outbuf, SPX_N); - } else { - /* All other tweakable hashes*/ - memcpy(buf, addr, 32); - memcpy(buf + SPX_ADDR_BYTES, in, inblocks * SPX_N); - - haraka_S(out, SPX_N, buf, SPX_ADDR_BYTES + inblocks * SPX_N, ctx); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/thash_haraka_simplex4.c b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/thash_haraka_simplex4.c deleted file mode 100644 index 2ee763d7d9..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/thash_haraka_simplex4.c +++ /dev/null @@ -1,67 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "thashx4.h" - -#include "harakax4.h" - -#include "utils.h" - -/** - * 4-way parallel version of thash; takes 4x as much input and output - */ -#define thashx4 SPX_NAMESPACE(thashx4) -void thashx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addrx4[4 * 8]) { - PQCLEAN_VLA(unsigned char, buf0, SPX_ADDR_BYTES + inblocks * SPX_N); - PQCLEAN_VLA(unsigned char, buf1, SPX_ADDR_BYTES + inblocks * SPX_N); - PQCLEAN_VLA(unsigned char, buf2, SPX_ADDR_BYTES + inblocks * SPX_N); - PQCLEAN_VLA(unsigned char, buf3, SPX_ADDR_BYTES + inblocks * SPX_N); - unsigned char outbuf[32 * 4]; - unsigned char buf_tmp[64 * 4]; - - if (inblocks == 1) { - memset(buf_tmp, 0, 64 * 4); - - memcpy(buf_tmp, addrx4 + 0 * 8, 32); - memcpy(buf_tmp + 64, addrx4 + 1 * 8, 32); - memcpy(buf_tmp + 128, addrx4 + 2 * 8, 32); - memcpy(buf_tmp + 192, addrx4 + 3 * 8, 32); - - memcpy(buf_tmp + SPX_ADDR_BYTES, in0, SPX_N); - memcpy(buf_tmp + SPX_ADDR_BYTES + 64, in1, SPX_N); - memcpy(buf_tmp + SPX_ADDR_BYTES + 128, in2, SPX_N); - memcpy(buf_tmp + SPX_ADDR_BYTES + 192, in3, SPX_N); - - haraka512x4(outbuf, buf_tmp, ctx); - - memcpy(out0, outbuf, SPX_N); - memcpy(out1, outbuf + 32, SPX_N); - memcpy(out2, outbuf + 64, SPX_N); - memcpy(out3, outbuf + 96, SPX_N); - } else { - /* All other tweakable hashes*/ - memcpy(buf0, addrx4 + 0 * 8, 32); - memcpy(buf1, addrx4 + 1 * 8, 32); - memcpy(buf2, addrx4 + 2 * 8, 32); - memcpy(buf3, addrx4 + 3 * 8, 32); - - memcpy(buf0 + SPX_ADDR_BYTES, in0, inblocks * SPX_N); - memcpy(buf1 + SPX_ADDR_BYTES, in1, inblocks * SPX_N); - memcpy(buf2 + SPX_ADDR_BYTES, in2, inblocks * SPX_N); - memcpy(buf3 + SPX_ADDR_BYTES, in3, inblocks * SPX_N); - - haraka_Sx4(out0, out1, out2, out3, SPX_N, - buf0, buf1, buf2, buf3, SPX_ADDR_BYTES + inblocks * SPX_N, - ctx); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/thashx4.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/thashx4.h deleted file mode 100644 index 64798a3727..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/thashx4.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef SPX_THASHX4_H -#define SPX_THASHX4_H - -#include - -#include "context.h" -#include "params.h" - -#define thashx4 SPX_NAMESPACE(thashx4) -void thashx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addrx4[4 * 8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/utils.c b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/utils.c deleted file mode 100644 index 177b541fb9..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/utils.c +++ /dev/null @@ -1,148 +0,0 @@ -#include - -#include "utils.h" - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "thash.h" - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void ull_to_bytes(unsigned char *out, unsigned int outlen, - unsigned long long in) { - int i; - - /* Iterate over out in decreasing order, for big-endianness. */ - for (i = (signed int)outlen - 1; i >= 0; i--) { - out[i] = in & 0xff; - in = in >> 8; - } -} - -void u32_to_bytes(unsigned char *out, uint32_t in) { - out[0] = (unsigned char)(in >> 24); - out[1] = (unsigned char)(in >> 16); - out[2] = (unsigned char)(in >> 8); - out[3] = (unsigned char)in; -} - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { - unsigned long long retval = 0; - unsigned int i; - - for (i = 0; i < inlen; i++) { - retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); - } - return retval; -} - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void compute_root(unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const spx_ctx *ctx, uint32_t addr[8]) { - uint32_t i; - unsigned char buffer[2 * SPX_N]; - - /* If leaf_idx is odd (last bit = 1), current path element is a right child - and auth_path has to go left. Otherwise it is the other way around. */ - if (leaf_idx & 1) { - memcpy(buffer + SPX_N, leaf, SPX_N); - memcpy(buffer, auth_path, SPX_N); - } else { - memcpy(buffer, leaf, SPX_N); - memcpy(buffer + SPX_N, auth_path, SPX_N); - } - auth_path += SPX_N; - - for (i = 0; i < tree_height - 1; i++) { - leaf_idx >>= 1; - idx_offset >>= 1; - /* Set the address of the node we're creating. */ - set_tree_height(addr, i + 1); - set_tree_index(addr, leaf_idx + idx_offset); - - /* Pick the right or left neighbor, depending on parity of the node. */ - if (leaf_idx & 1) { - thash(buffer + SPX_N, buffer, 2, ctx, addr); - memcpy(buffer, auth_path, SPX_N); - } else { - thash(buffer, buffer, 2, ctx, addr); - memcpy(buffer + SPX_N, auth_path, SPX_N); - } - auth_path += SPX_N; - } - - /* The last iteration is exceptional; we do not copy an auth_path node. */ - leaf_idx >>= 1; - idx_offset >>= 1; - set_tree_height(addr, tree_height); - set_tree_index(addr, leaf_idx + idx_offset); - thash(root, buffer, 2, ctx, addr); -} - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const spx_ctx * /* ctx */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), - uint32_t tree_addr[8]) { - PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); - PQCLEAN_VLA(unsigned int, heights, tree_height + 1); - unsigned int offset = 0; - uint32_t idx; - uint32_t tree_idx; - - for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { - /* Add the next leaf node to the stack. */ - gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); - offset++; - heights[offset - 1] = 0; - - /* If this is a node we need for the auth path.. */ - if ((leaf_idx ^ 0x1) == idx) { - memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); - } - - /* While the top-most nodes are of equal height.. */ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { - /* Compute index of the new node, in the next layer. */ - tree_idx = (idx >> (heights[offset - 1] + 1)); - - /* Set the address of the node we're creating. */ - set_tree_height(tree_addr, heights[offset - 1] + 1); - set_tree_index(tree_addr, - tree_idx + (idx_offset >> (heights[offset - 1] + 1))); - /* Hash the top-most nodes from the stack together. */ - thash(stack + (offset - 2)*SPX_N, - stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); - offset--; - /* Note that the top-most node is now one layer higher. */ - heights[offset - 1]++; - - /* If this is a node we need for the auth path.. */ - if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_path + heights[offset - 1]*SPX_N, - stack + (offset - 1)*SPX_N, SPX_N); - } - } - } - memcpy(root, stack, SPX_N); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/utils.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/utils.h deleted file mode 100644 index 64f5d5a53a..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/utils.h +++ /dev/null @@ -1,58 +0,0 @@ -#ifndef SPX_UTILS_H -#define SPX_UTILS_H - -#include - -#include "compat.h" -#include "context.h" -#include "params.h" - - -/* To support MSVC use alloca() instead of VLAs. See #20. */ - - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) -void ull_to_bytes(unsigned char *out, unsigned int outlen, - unsigned long long in); -#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) -void u32_to_bytes(unsigned char *out, uint32_t in); - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) -unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -#define compute_root SPX_NAMESPACE(compute_root) -void compute_root(unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const spx_ctx *ctx, uint32_t addr[8]); - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -#define treehash SPX_NAMESPACE(treehash) -void treehash(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const spx_ctx *ctx /* ctx */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), - uint32_t tree_addr[8]); - - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/utilsx4.c b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/utilsx4.c deleted file mode 100644 index 1638677194..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/utilsx4.c +++ /dev/null @@ -1,138 +0,0 @@ -#include - -#include "utilsx4.h" - -#include "address.h" -#include "params.h" -#include "thashx4.h" -#include "utils.h" - -/* - * Generate the entire Merkle tree, computing the authentication path for leaf_idx, - * and the resulting root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) - * - * This expects tree_addrx4 to be initialized to 4 parallel addr structures for - * the Merkle tree nodes - * - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - * - * This works by using the standard Merkle tree building algorithm, except - * that each 'node' tracked is actually 4 consecutive nodes in the real tree. - * When we combine two logical nodes ABCD and WXYZ, we perform the H - * operation on adjacent real nodes, forming the parent logical node - * (AB)(CD)(WX)(YZ) - * - * When we get to the top two levels of the real tree (where there is only - * one logical node), we continue this operation two more times; the right - * most real node will by the actual root (and the other 3 nodes will be - * garbage). We follow the same thashx4 logic so that the 'extract - * authentication path components' part of the loop is still executed (and - * to simplify the code somewhat) - * - * This currently assumes tree_height >= 2; I suspect that doing an adjusting - * idx, addr_idx on the gen_leafx4 call if tree_height < 2 would fix it; since - * we don't actually use such short trees, I haven't bothered - */ -void treehashx4(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, - uint32_t tree_height, - void (*gen_leafx4)( - unsigned char * /* Where to write the leaves */, - const spx_ctx *, - uint32_t idx, void *info), - uint32_t tree_addrx4[4 * 8], - void *info) { - /* This is where we keep the intermediate nodes */ - PQCLEAN_VLA(unsigned char, stackx4, tree_height * 4 * SPX_N); - uint32_t left_adj = 0, prev_left_adj = 0; /* When we're doing the top 3 */ - /* levels, the left-most part of the tree isn't at the beginning */ - /* of current[]. These give the offset of the actual start */ - - uint32_t idx; - uint32_t max_idx = (1U << (tree_height - 2)) - 1; - for (idx = 0;; idx++) { - unsigned char current[4 * SPX_N]; /* Current logical node */ - gen_leafx4( current, ctx, 4 * idx + idx_offset, - info ); - - /* Now combine the freshly generated right node with previously */ - /* generated left ones */ - uint32_t internal_idx_offset = idx_offset; - uint32_t internal_idx = idx; - uint32_t internal_leaf = leaf_idx; - uint32_t h; /* The height we are in the Merkle tree */ - for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { - - /* Special processing if we're at the top of the tree */ - if (h >= tree_height - 2) { - if (h == tree_height) { - /* We hit the root; return it */ - memcpy( root, ¤t[3 * SPX_N], SPX_N ); - return; - } - /* The tree indexing logic is a bit off in this case */ - /* Adjust it so that the left-most node of the part of */ - /* the tree that we're processing has index 0 */ - prev_left_adj = left_adj; - left_adj = 4U - (1 << (tree_height - h - 1)); - } - - /* Check if we hit the top of the tree */ - if (h == tree_height) { - /* We hit the root; return it */ - memcpy( root, ¤t[3 * SPX_N], SPX_N ); - return; - } - - /* - * Check if one of the nodes we have is a part of the - * authentication path; if it is, write it out - */ - if ((((internal_idx << 2) ^ internal_leaf) & ~0x3U) == 0) { - memcpy( &auth_path[ h * SPX_N ], - ¤t[(((internal_leaf & 3) ^ 1) + prev_left_adj) * SPX_N], - SPX_N ); - } - - /* - * Check if we're at a left child; if so, stop going up the stack - * Exception: if we've reached the end of the tree, keep on going - * (so we combine the last 4 nodes into the one root node in two - * more iterations) - */ - if ((internal_idx & 1) == 0 && idx < max_idx) { - break; - } - - /* Ok, we're at a right node (or doing the top 3 levels) */ - /* Now combine the left and right logical nodes together */ - - /* Set the address of the node we're creating. */ - unsigned int j; - internal_idx_offset >>= 1; - for (j = 0; j < 4; j++) { - set_tree_height(tree_addrx4 + j * 8, h + 1); - set_tree_index(tree_addrx4 + j * 8, - (4 / 2) * (internal_idx & ~1U) + j - left_adj + internal_idx_offset ); - } - unsigned char *left = &stackx4[h * 4 * SPX_N]; - thashx4( ¤t[0 * SPX_N], - ¤t[1 * SPX_N], - ¤t[2 * SPX_N], - ¤t[3 * SPX_N], - &left [0 * SPX_N], - &left [2 * SPX_N], - ¤t[0 * SPX_N], - ¤t[2 * SPX_N], - 2, ctx, tree_addrx4); - } - - /* We've hit a left child; save the current for when we get the */ - /* corresponding right right */ - memcpy( &stackx4[h * 4 * SPX_N], current, 4 * SPX_N); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/utilsx4.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/utilsx4.h deleted file mode 100644 index facb874b18..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/utilsx4.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef SPX_UTILSX4_H -#define SPX_UTILSX4_H - -#include - -#include "context.h" -#include "params.h" - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - * - * This implementation uses AVX to compute internal nodes 4 at a time (in - * parallel) - */ -#define treehashx4 SPX_NAMESPACE(treehashx4) -void treehashx4(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leafx4)( - unsigned char * /* Where to write the leaves */, - const spx_ctx * /* ctx */, - uint32_t addr_idx, void *info), - uint32_t tree_addrx4[4 * 8], void *info); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/wots.c b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/wots.c deleted file mode 100644 index 4d5041ce05..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/wots.c +++ /dev/null @@ -1,269 +0,0 @@ -#include -#include - -#include "wots.h" - -#include "address.h" -#include "hash.h" -#include "hashx4.h" -#include "params.h" -#include "thash.h" -#include "thashx4.h" -#include "utils.h" -#include "utilsx4.h" -#include "wotsx4.h" - -// TODO clarify address expectations, and make them more uniform. -// TODO i.e. do we expect types to be set already? -// TODO and do we expect modifications or copies? - -/** - * Computes up the chains - */ -static void gen_chains( - unsigned char *out, - const unsigned char *in, - unsigned int start[SPX_WOTS_LEN], - const unsigned int steps[SPX_WOTS_LEN], - const spx_ctx *ctx, - uint32_t addr[8]) { - uint32_t i, j, k, idx, watching; - int done; - unsigned char empty[SPX_N]; - unsigned char *bufs[4]; - uint32_t addrs[8 * 4]; - - int l; - uint16_t counts[SPX_WOTS_W] = { 0 }; - uint16_t idxs[SPX_WOTS_LEN]; - uint16_t total, newTotal; - - /* set addrs = {addr, addr, addr, addr} */ - for (j = 0; j < 4; j++) { - memcpy(addrs + j * 8, addr, sizeof(uint32_t) * 8); - } - - /* Initialize out with the value at position 'start'. */ - memcpy(out, in, SPX_WOTS_LEN * SPX_N); - - /* Sort the chains in reverse order by steps using counting sort. */ - for (i = 0; i < SPX_WOTS_LEN; i++) { - counts[steps[i]]++; - } - total = 0; - for (l = SPX_WOTS_W - 1; l >= 0; l--) { - newTotal = counts[l] + total; - counts[l] = total; - total = newTotal; - } - for (i = 0; i < SPX_WOTS_LEN; i++) { - idxs[counts[steps[i]]] = (uint16_t)i; - counts[steps[i]]++; - } - - /* We got our work cut out for us: do it! */ - for (i = 0; i < SPX_WOTS_LEN; i += 4) { - for (j = 0; j < 4 && i + j < SPX_WOTS_LEN; j++) { - idx = idxs[i + j]; - set_chain_addr(addrs + j * 8, idx); - bufs[j] = out + SPX_N * idx; - } - - /* As the chains are sorted in reverse order, we know that the first - * chain is the longest and the last one is the shortest. We keep - * an eye on whether the last chain is done and then on the one before, - * et cetera. */ - watching = 3; - done = 0; - while (i + watching >= SPX_WOTS_LEN) { - bufs[watching] = &empty[0]; - watching--; - } - - for (k = 0;; k++) { - while (k == steps[idxs[i + watching]]) { - bufs[watching] = &empty[0]; - if (watching == 0) { - done = 1; - break; - } - watching--; - } - if (done) { - break; - } - for (j = 0; j < watching + 1; j++) { - set_hash_addr(addrs + j * 8, k + start[idxs[i + j]]); - } - - thashx4(bufs[0], bufs[1], bufs[2], bufs[3], - bufs[0], bufs[1], bufs[2], bufs[3], 1, ctx, addrs); - } - } -} - -/** - * base_w algorithm as described in draft. - * Interprets an array of bytes as integers in base w. - * This only works when log_w is a divisor of 8. - */ -static void base_w(unsigned int *output, const int out_len, - const unsigned char *input) { - int in = 0; - int out = 0; - unsigned char total = 0; - int bits = 0; - int consumed; - - for (consumed = 0; consumed < out_len; consumed++) { - if (bits == 0) { - total = input[in]; - in++; - bits += 8; - } - bits -= SPX_WOTS_LOGW; - output[out] = (total >> bits) & (SPX_WOTS_W - 1); - out++; - } -} - -/* Computes the WOTS+ checksum over a message (in base_w). */ -static void wots_checksum(unsigned int *csum_base_w, - const unsigned int *msg_base_w) { - unsigned int csum = 0; - unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; - unsigned int i; - - /* Compute checksum. */ - for (i = 0; i < SPX_WOTS_LEN1; i++) { - csum += SPX_WOTS_W - 1 - msg_base_w[i]; - } - - /* Convert checksum to base_w. */ - /* Make sure expected empty zero bits are the least significant bits. */ - csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); - ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); - base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); -} - -/* Takes a message and derives the matching chain lengths. */ -void chain_lengths(unsigned int *lengths, const unsigned char *msg) { - base_w(lengths, SPX_WOTS_LEN1, msg); - wots_checksum(lengths + SPX_WOTS_LEN1, lengths); -} - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const spx_ctx *ctx, uint32_t addr[8]) { - unsigned int steps[SPX_WOTS_LEN]; - unsigned int start[SPX_WOTS_LEN]; - uint32_t i; - - chain_lengths(start, msg); - - for (i = 0; i < SPX_WOTS_LEN; i++) { - steps[i] = SPX_WOTS_W - 1 - start[i]; - } - - gen_chains(pk, sig, start, steps, ctx, addr); -} - -/* - * This generates 4 sequential WOTS public keys - * It also generates the WOTS signature if leaf_info indicates - * that we're signing with one of these WOTS keys - */ -void wots_gen_leafx4(unsigned char *dest, - const spx_ctx *ctx, - uint32_t leaf_idx, void *v_info) { - struct leaf_info_x4 *info = v_info; - uint32_t *leaf_addr = info->leaf_addr; - uint32_t *pk_addr = info->pk_addr; - unsigned int i, j, k; - unsigned char pk_buffer[ 4 * SPX_WOTS_BYTES ]; - unsigned wots_offset = SPX_WOTS_BYTES; - unsigned char *buffer; - uint32_t wots_k_mask; - unsigned wots_sign_index; - - if (((leaf_idx ^ info->wots_sign_leaf) & ~3U) == 0) { - /* We're traversing the leaf that's signing; generate the WOTS */ - /* signature */ - wots_k_mask = 0; - wots_sign_index = info->wots_sign_leaf & 3; /* Which of of the 4 */ - /* 4 slots do the signatures come from */ - } else { - /* Nope, we're just generating pk's; turn off the signature logic */ - wots_k_mask = (uint32_t)~0; - wots_sign_index = 0; - } - - for (j = 0; j < 4; j++) { - set_keypair_addr( leaf_addr + j * 8, leaf_idx + j ); - set_keypair_addr( pk_addr + j * 8, leaf_idx + j ); - } - - for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { - uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k to */ - /* the step if we're generating a signature, ~0 if we're not */ - - /* Start with the secret seed */ - for (j = 0; j < 4; j++) { - set_chain_addr(leaf_addr + j * 8, i); - set_hash_addr(leaf_addr + j * 8, 0); - set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTSPRF); - } - prf_addrx4(buffer + 0 * wots_offset, - buffer + 1 * wots_offset, - buffer + 2 * wots_offset, - buffer + 3 * wots_offset, - ctx, leaf_addr); - - for (j = 0; j < 4; j++) { - set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTS); - } - - /* Iterate down the WOTS chain */ - for (k = 0;; k++) { - /* Check if one of the values we have needs to be saved as a */ - /* part of the WOTS signature */ - if (k == wots_k) { - memcpy( info->wots_sig + i * SPX_N, - buffer + wots_sign_index * wots_offset, SPX_N ); - } - - /* Check if we hit the top of the chain */ - if (k == SPX_WOTS_W - 1) { - break; - } - - /* Iterate one step on all 4 chains */ - for (j = 0; j < 4; j++) { - set_hash_addr(leaf_addr + j * 8, k); - } - thashx4(buffer + 0 * wots_offset, - buffer + 1 * wots_offset, - buffer + 2 * wots_offset, - buffer + 3 * wots_offset, - buffer + 0 * wots_offset, - buffer + 1 * wots_offset, - buffer + 2 * wots_offset, - buffer + 3 * wots_offset, 1, ctx, leaf_addr); - } - } - - /* Do the final thash to generate the public keys */ - thashx4(dest + 0 * SPX_N, - dest + 1 * SPX_N, - dest + 2 * SPX_N, - dest + 3 * SPX_N, - pk_buffer + 0 * wots_offset, - pk_buffer + 1 * wots_offset, - pk_buffer + 2 * wots_offset, - pk_buffer + 3 * wots_offset, SPX_WOTS_LEN, ctx, pk_addr); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/wots.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/wots.h deleted file mode 100644 index 4e7692eeef..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/wots.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef SPX_WOTS_H -#define SPX_WOTS_H - -#include - -#include "context.h" -#include "params.h" - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) -void wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const spx_ctx *ctx, uint32_t addr[8]); - -/* - * Compute the chain lengths needed for a given message hash - */ -#define chain_lengths SPX_NAMESPACE(chain_lengths) -void chain_lengths(unsigned int *lengths, const unsigned char *msg); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/wotsx4.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/wotsx4.h deleted file mode 100644 index cd634f1743..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_aesni/wotsx4.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef WOTSX4_H_ -#define WOTSX4_H_ - -#include - -#include "params.h" - -/* - * This is here to provide an interface to the internal wots_gen_leafx4 - * routine. While this routine is not referenced in the package outside of - * wots.c, it is called from the stand-alone benchmark code to characterize - * the performance - */ -struct leaf_info_x4 { - unsigned char *wots_sig; - uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ - uint32_t *wots_steps; - uint32_t leaf_addr[4 * 8]; - uint32_t pk_addr[4 * 8]; -}; - -/* Macro to set the leaf_info to something 'benign', that is, it would */ -/* run with the same time as it does during the real signing process */ -/* Used only by the benchmark code */ -#define INITIALIZE_LEAF_INFO_X4(info, addr, step_buffer) { \ - (info).wots_sig = 0; \ - (info).wots_sign_leaf = ~0; \ - (info).wots_steps = step_buffer; \ - int i; \ - for (i=0; i<4; i++) { \ - memcpy( &(info).leaf_addr[8*i], addr, 32 ); \ - memcpy( &(info).pk_addr[8*i], addr, 32 ); \ - } \ - } - -#define wots_gen_leafx4 SPX_NAMESPACE(wots_gen_leafx4) -void wots_gen_leafx4(unsigned char *dest, - const spx_ctx *ctx, - uint32_t leaf_idx, void *v_info); - -#endif /* WOTSX4_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/LICENSE b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/LICENSE deleted file mode 100644 index 670154e353..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/LICENSE +++ /dev/null @@ -1,116 +0,0 @@ -CC0 1.0 Universal - -Statement of Purpose - -The laws of most jurisdictions throughout the world automatically confer -exclusive Copyright and Related Rights (defined below) upon the creator and -subsequent owner(s) (each and all, an "owner") of an original work of -authorship and/or a database (each, a "Work"). - -Certain owners wish to permanently relinquish those rights to a Work for the -purpose of contributing to a commons of creative, cultural and scientific -works ("Commons") that the public can reliably and without fear of later -claims of infringement build upon, modify, incorporate in other works, reuse -and redistribute as freely as possible in any form whatsoever and for any -purposes, including without limitation commercial purposes. These owners may -contribute to the Commons to promote the ideal of a free culture and the -further production of creative, cultural and scientific works, or to gain -reputation or greater distribution for their Work in part through the use and -efforts of others. - -For these and/or other purposes and motivations, and without any expectation -of additional consideration or compensation, the person associating CC0 with a -Work (the "Affirmer"), to the extent that he or she is an owner of Copyright -and Related Rights in the Work, voluntarily elects to apply CC0 to the Work -and publicly distribute the Work under its terms, with knowledge of his or her -Copyright and Related Rights in the Work and the meaning and intended legal -effect of CC0 on those rights. - -1. Copyright and Related Rights. A Work made available under CC0 may be -protected by copyright and related or neighboring rights ("Copyright and -Related Rights"). Copyright and Related Rights include, but are not limited -to, the following: - - i. the right to reproduce, adapt, distribute, perform, display, communicate, - and translate a Work; - - ii. moral rights retained by the original author(s) and/or performer(s); - - iii. publicity and privacy rights pertaining to a person's image or likeness - depicted in a Work; - - iv. rights protecting against unfair competition in regards to a Work, - subject to the limitations in paragraph 4(a), below; - - v. rights protecting the extraction, dissemination, use and reuse of data in - a Work; - - vi. database rights (such as those arising under Directive 96/9/EC of the - European Parliament and of the Council of 11 March 1996 on the legal - protection of databases, and under any national implementation thereof, - including any amended or successor version of such directive); and - - vii. other similar, equivalent or corresponding rights throughout the world - based on applicable law or treaty, and any national implementations thereof. - -2. Waiver. To the greatest extent permitted by, but not in contravention of, -applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and -unconditionally waives, abandons, and surrenders all of Affirmer's Copyright -and Related Rights and associated claims and causes of action, whether now -known or unknown (including existing as well as future claims and causes of -action), in the Work (i) in all territories worldwide, (ii) for the maximum -duration provided by applicable law or treaty (including future time -extensions), (iii) in any current or future medium and for any number of -copies, and (iv) for any purpose whatsoever, including without limitation -commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes -the Waiver for the benefit of each member of the public at large and to the -detriment of Affirmer's heirs and successors, fully intending that such Waiver -shall not be subject to revocation, rescission, cancellation, termination, or -any other legal or equitable action to disrupt the quiet enjoyment of the Work -by the public as contemplated by Affirmer's express Statement of Purpose. - -3. Public License Fallback. Should any part of the Waiver for any reason be -judged legally invalid or ineffective under applicable law, then the Waiver -shall be preserved to the maximum extent permitted taking into account -Affirmer's express Statement of Purpose. In addition, to the extent the Waiver -is so judged Affirmer hereby grants to each affected person a royalty-free, -non transferable, non sublicensable, non exclusive, irrevocable and -unconditional license to exercise Affirmer's Copyright and Related Rights in -the Work (i) in all territories worldwide, (ii) for the maximum duration -provided by applicable law or treaty (including future time extensions), (iii) -in any current or future medium and for any number of copies, and (iv) for any -purpose whatsoever, including without limitation commercial, advertising or -promotional purposes (the "License"). The License shall be deemed effective as -of the date CC0 was applied by Affirmer to the Work. Should any part of the -License for any reason be judged legally invalid or ineffective under -applicable law, such partial invalidity or ineffectiveness shall not -invalidate the remainder of the License, and in such case Affirmer hereby -affirms that he or she will not (i) exercise any of his or her remaining -Copyright and Related Rights in the Work or (ii) assert any associated claims -and causes of action with respect to the Work, in either case contrary to -Affirmer's express Statement of Purpose. - -4. Limitations and Disclaimers. - - a. No trademark or patent rights held by Affirmer are waived, abandoned, - surrendered, licensed or otherwise affected by this document. - - b. Affirmer offers the Work as-is and makes no representations or warranties - of any kind concerning the Work, express, implied, statutory or otherwise, - including without limitation warranties of title, merchantability, fitness - for a particular purpose, non infringement, or the absence of latent or - other defects, accuracy, or the present or absence of errors, whether or not - discoverable, all to the greatest extent permissible under applicable law. - - c. Affirmer disclaims responsibility for clearing rights of other persons - that may apply to the Work or any use thereof, including without limitation - any person's Copyright and Related Rights in the Work. Further, Affirmer - disclaims responsibility for obtaining any necessary consents, permissions - or other rights required for any use of the Work. - - d. Affirmer understands and acknowledges that Creative Commons is not a - party to this document and has no duty or obligation with respect to this - CC0 or use of the Work. - -For more information, please see - diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/address.c b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/address.c deleted file mode 100644 index b956e9cb29..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/address.c +++ /dev/null @@ -1,91 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "utils.h" - -/* - * Specify which level of Merkle tree (the "layer") we're working on - */ -void set_layer_addr(uint32_t addr[8], uint32_t layer) { - ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; -} - -/* - * Specify which Merkle tree within the level (the "tree address") we're working on - */ -void set_tree_addr(uint32_t addr[8], uint64_t tree) { - ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); -} - -/* - * Specify the reason we'll use this address structure for, that is, what - * hash will we compute with it. This is used so that unrelated types of - * hashes don't accidentally get the same address structure. The type will be - * one of the SPX_ADDR_TYPE constants - */ -void set_type(uint32_t addr[8], uint32_t type) { - ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; -} - -/* - * Copy the layer and tree fields of the address structure. This is used - * when we're doing multiple types of hashes within the same Merkle tree - */ -void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { - memcpy( out, in, SPX_OFFSET_TREE + 8 ); -} - -/* These functions are used for OTS addresses. */ - -/* - * Specify which Merkle leaf we're working on; that is, which OTS keypair - * we're talking about. - */ -void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { - ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; -} - -/* - * Copy the layer, tree and keypair fields of the address structure. This is - * used when we're doing multiple things within the same OTS keypair - */ -void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { - memcpy( out, in, SPX_OFFSET_TREE + 8 ); - ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; -} - -/* - * Specify which Merkle chain within the OTS we're working with - * (the chain address) - */ -void set_chain_addr(uint32_t addr[8], uint32_t chain) { - ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; -} - -/* - * Specify where in the Merkle chain we are -* (the hash address) - */ -void set_hash_addr(uint32_t addr[8], uint32_t hash) { - ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; -} - -/* These functions are used for all hash tree addresses (including FORS). */ - -/* - * Specify the height of the node in the Merkle/FORS tree we are in - * (the tree height) - */ -void set_tree_height(uint32_t addr[8], uint32_t tree_height) { - ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; -} - -/* - * Specify the distance from the left edge of the node in the Merkle/FORS tree - * (the tree index) - */ -void set_tree_index(uint32_t addr[8], uint32_t tree_index) { - u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/address.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/address.h deleted file mode 100644 index 24a84eb40c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/address.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef SPX_ADDRESS_H -#define SPX_ADDRESS_H - -#include - -#include "params.h" - -/* The hash types that are passed to set_type */ -#define SPX_ADDR_TYPE_WOTS 0 -#define SPX_ADDR_TYPE_WOTSPK 1 -#define SPX_ADDR_TYPE_HASHTREE 2 -#define SPX_ADDR_TYPE_FORSTREE 3 -#define SPX_ADDR_TYPE_FORSPK 4 -#define SPX_ADDR_TYPE_WOTSPRF 5 -#define SPX_ADDR_TYPE_FORSPRF 6 - -#define set_layer_addr SPX_NAMESPACE(set_layer_addr) -void set_layer_addr(uint32_t addr[8], uint32_t layer); - -#define set_tree_addr SPX_NAMESPACE(set_tree_addr) -void set_tree_addr(uint32_t addr[8], uint64_t tree); - -#define set_type SPX_NAMESPACE(set_type) -void set_type(uint32_t addr[8], uint32_t type); - -/* Copies the layer and tree part of one address into the other */ -#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) -void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for WOTS and FORS addresses. */ - -#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) -void set_keypair_addr(uint32_t addr[8], uint32_t keypair); - -#define set_chain_addr SPX_NAMESPACE(set_chain_addr) -void set_chain_addr(uint32_t addr[8], uint32_t chain); - -#define set_hash_addr SPX_NAMESPACE(set_hash_addr) -void set_hash_addr(uint32_t addr[8], uint32_t hash); - -#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) -void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for all hash tree addresses (including FORS). */ - -#define set_tree_height SPX_NAMESPACE(set_tree_height) -void set_tree_height(uint32_t addr[8], uint32_t tree_height); - -#define set_tree_index SPX_NAMESPACE(set_tree_index) -void set_tree_index(uint32_t addr[8], uint32_t tree_index); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/api.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/api.h deleted file mode 100644 index dae709471f..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/api.h +++ /dev/null @@ -1,77 +0,0 @@ -#ifndef PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_API_H -#define PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_API_H - -#include -#include - -#define PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_CRYPTO_ALGNAME "SPHINCS+-haraka-192f-simple" - -#define PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_CRYPTO_SECRETKEYBYTES 96 -#define PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_CRYPTO_PUBLICKEYBYTES 48 -#define PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_CRYPTO_BYTES 35664 - -#define PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_CRYPTO_SEEDBYTES 72 - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, - const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk); -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/context.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/context.h deleted file mode 100644 index 600dfb73c7..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/context.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef SPX_CONTEXT_H -#define SPX_CONTEXT_H - -#include -#include - -#include "params.h" - -typedef struct { - uint8_t pub_seed[SPX_N]; - uint8_t sk_seed[SPX_N]; - - - uint64_t tweaked512_rc64[10][8]; - uint32_t tweaked256_rc32[10][8]; -} spx_ctx; - -#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) -void initialize_hash_function(spx_ctx *ctx); - -#define free_hash_function SPX_NAMESPACE(free_hash_function) -void free_hash_function(spx_ctx *ctx); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/context_haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/context_haraka.c deleted file mode 100644 index f1cd7e3664..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/context_haraka.c +++ /dev/null @@ -1,11 +0,0 @@ -#include "context.h" -#include "haraka.h" - -void initialize_hash_function(spx_ctx *ctx) { - tweak_constants(ctx); -} - -// we don't support heap-based haraka right now -void free_hash_function(spx_ctx *ctx) { - (void)ctx; // suppress unused variable warnings -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/fors.c b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/fors.c deleted file mode 100644 index 96ca72e986..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/fors.c +++ /dev/null @@ -1,156 +0,0 @@ -#include -#include -#include - -#include "fors.h" - -#include "address.h" -#include "hash.h" -#include "thash.h" -#include "utils.h" -#include "utilsx1.h" - -static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, - uint32_t fors_leaf_addr[8]) { - prf_addr(sk, ctx, fors_leaf_addr); -} - -static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, - const spx_ctx *ctx, - uint32_t fors_leaf_addr[8]) { - thash(leaf, sk, 1, ctx, fors_leaf_addr); -} - -struct fors_gen_leaf_info { - uint32_t leaf_addrx[8]; -}; - -static void fors_gen_leafx1(unsigned char *leaf, - const spx_ctx *ctx, - uint32_t addr_idx, void *info) { - struct fors_gen_leaf_info *fors_info = info; - uint32_t *fors_leaf_addr = fors_info->leaf_addrx; - - /* Only set the parts that the caller doesn't set */ - set_tree_index(fors_leaf_addr, addr_idx); - set_type(fors_leaf_addr, SPX_ADDR_TYPE_FORSPRF); - fors_gen_sk(leaf, ctx, fors_leaf_addr); - - set_type(fors_leaf_addr, SPX_ADDR_TYPE_FORSTREE); - fors_sk_to_leaf(leaf, leaf, - ctx, fors_leaf_addr); -} - -/** - * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - * Assumes indices has space for SPX_FORS_TREES integers. - */ -static void message_to_indices(uint32_t *indices, const unsigned char *m) { - unsigned int i, j; - unsigned int offset = 0; - - for (i = 0; i < SPX_FORS_TREES; i++) { - indices[i] = 0; - for (j = 0; j < SPX_FORS_HEIGHT; j++) { - indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); - offset++; - } - } -} - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -void fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]) { - uint32_t indices[SPX_FORS_TREES]; - unsigned char roots[SPX_FORS_TREES * SPX_N]; - uint32_t fors_tree_addr[8] = {0}; - struct fors_gen_leaf_info fors_info = {0}; - uint32_t *fors_leaf_addr = fors_info.leaf_addrx; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - copy_keypair_addr(fors_tree_addr, fors_addr); - copy_keypair_addr(fors_leaf_addr, fors_addr); - - copy_keypair_addr(fors_pk_addr, fors_addr); - set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < SPX_FORS_TREES; i++) { - idx_offset = i * (1 << SPX_FORS_HEIGHT); - - set_tree_height(fors_tree_addr, 0); - set_tree_index(fors_tree_addr, indices[i] + idx_offset); - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); - - /* Include the secret key part that produces the selected leaf node. */ - fors_gen_sk(sig, ctx, fors_tree_addr); - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); - sig += SPX_N; - - /* Compute the authentication path for this leaf node. */ - treehashx1(roots + i * SPX_N, sig, ctx, - indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx1, - fors_tree_addr, &fors_info); - - sig += SPX_N * SPX_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); -} - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -void fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]) { - uint32_t indices[SPX_FORS_TREES]; - unsigned char roots[SPX_FORS_TREES * SPX_N]; - unsigned char leaf[SPX_N]; - uint32_t fors_tree_addr[8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - copy_keypair_addr(fors_tree_addr, fors_addr); - copy_keypair_addr(fors_pk_addr, fors_addr); - - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); - set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < SPX_FORS_TREES; i++) { - idx_offset = i * (1 << SPX_FORS_HEIGHT); - - set_tree_height(fors_tree_addr, 0); - set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Derive the leaf from the included secret key part. */ - fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); - sig += SPX_N; - - /* Derive the corresponding root node of this tree. */ - compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, - sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); - sig += SPX_N * SPX_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/fors.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/fors.h deleted file mode 100644 index 509140a178..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/fors.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef SPX_FORS_H -#define SPX_FORS_H - -#include - -#include "context.h" -#include "params.h" - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -#define fors_sign SPX_NAMESPACE(fors_sign) -void fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]); - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) -void fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/haraka.c deleted file mode 100644 index a4944913b5..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/haraka.c +++ /dev/null @@ -1,913 +0,0 @@ -/* - * Constant time implementation of the Haraka hash function. - * - * The bit-sliced implementation of the AES round functions are - * based on the AES implementation in BearSSL written - * by Thomas Pornin - */ - -#include -#include -#include -#include - -#include "haraka.h" -#include "utils.h" - -#define HARAKAS_RATE 32 - -static const uint64_t haraka512_rc64[10][8] = { - {0x24cf0ab9086f628b, 0xbdd6eeecc83b8382, 0xd96fb0306cdad0a7, 0xaace082ac8f95f89, 0x449d8e8870d7041f, 0x49bb2f80b2b3e2f8, 0x0569ae98d93bb258, 0x23dc9691e7d6a4b1}, - {0xd8ba10ede0fe5b6e, 0x7ecf7dbe424c7b8e, 0x6ea9949c6df62a31, 0xbf3f3c97ec9c313e, 0x241d03a196a1861e, 0xead3a51116e5a2ea, 0x77d479fcad9574e3, 0x18657a1af894b7a0}, - {0x10671e1a7f595522, 0xd9a00ff675d28c7b, 0x2f1edf0d2b9ba661, 0xb8ff58b8e3de45f9, 0xee29261da9865c02, 0xd1532aa4b50bdf43, 0x8bf858159b231bb1, 0xdf17439d22d4f599}, - {0xdd4b2f0870b918c0, 0x757a81f3b39b1bb6, 0x7a5c556898952e3f, 0x7dd70a16d915d87a, 0x3ae61971982b8301, 0xc3ab319e030412be, 0x17c0033ac094a8cb, 0x5a0630fc1a8dc4ef}, - {0x17708988c1632f73, 0xf92ddae090b44f4f, 0x11ac0285c43aa314, 0x509059941936b8ba, 0xd03e152fa2ce9b69, 0x3fbcbcb63a32998b, 0x6204696d692254f7, 0x915542ed93ec59b4}, - {0xf4ed94aa8879236e, 0xff6cb41cd38e03c0, 0x069b38602368aeab, 0x669495b820f0ddba, 0xf42013b1b8bf9e3d, 0xcf935efe6439734d, 0xbc1dcf42ca29e3f8, 0x7e6d3ed29f78ad67}, - {0xf3b0f6837ffcddaa, 0x3a76faef934ddf41, 0xcec7ae583a9c8e35, 0xe4dd18c68f0260af, 0x2c0e5df1ad398eaa, 0x478df5236ae22e8c, 0xfb944c46fe865f39, 0xaa48f82f028132ba}, - {0x231b9ae2b76aca77, 0x292a76a712db0b40, 0x5850625dc8134491, 0x73137dd469810fb5, 0x8a12a6a202a474fd, 0xd36fd9daa78bdb80, 0xb34c5e733505706f, 0xbaf1cdca818d9d96}, - {0x2e99781335e8c641, 0xbddfe5cce47d560e, 0xf74e9bf32e5e040c, 0x1d7a709d65996be9, 0x670df36a9cf66cdd, 0xd05ef84a176a2875, 0x0f888e828cb1c44e, 0x1a79e9c9727b052c}, - {0x83497348628d84de, 0x2e9387d51f22a754, 0xb000068da2f852d6, 0x378c9e1190fd6fe5, 0x870027c316de7293, 0xe51a9d4462e047bb, 0x90ecf7f8c6251195, 0x655953bfbed90a9c}, -}; - -static inline uint32_t br_dec32le(const unsigned char *src) { - return (uint32_t)src[0] - | ((uint32_t)src[1] << 8) - | ((uint32_t)src[2] << 16) - | ((uint32_t)src[3] << 24); -} - -static void br_range_dec32le(uint32_t *v, size_t num, const unsigned char *src) { - while (num-- > 0) { - *v ++ = br_dec32le(src); - src += 4; - } -} - -static inline void br_enc32le(unsigned char *dst, uint32_t x) { - dst[0] = (unsigned char)x; - dst[1] = (unsigned char)(x >> 8); - dst[2] = (unsigned char)(x >> 16); - dst[3] = (unsigned char)(x >> 24); -} - - -static void br_range_enc32le(unsigned char *dst, const uint32_t *v, size_t num) { - while (num-- > 0) { - br_enc32le(dst, *v ++); - dst += 4; - } -} - -static void br_aes_ct64_bitslice_Sbox(uint64_t *q) { - /* - * This S-box implementation is a straightforward translation of - * the circuit described by Boyar and Peralta in "A new - * combinational logic minimization technique with applications - * to cryptology" (https://eprint.iacr.org/2009/191.pdf). - * - * Note that variables x* (input) and s* (output) are numbered - * in "reverse" order (x0 is the high bit, x7 is the low bit). - */ - - uint64_t x0, x1, x2, x3, x4, x5, x6, x7; - uint64_t y1, y2, y3, y4, y5, y6, y7, y8, y9; - uint64_t y10, y11, y12, y13, y14, y15, y16, y17, y18, y19; - uint64_t y20, y21; - uint64_t z0, z1, z2, z3, z4, z5, z6, z7, z8, z9; - uint64_t z10, z11, z12, z13, z14, z15, z16, z17; - uint64_t t0, t1, t2, t3, t4, t5, t6, t7, t8, t9; - uint64_t t10, t11, t12, t13, t14, t15, t16, t17, t18, t19; - uint64_t t20, t21, t22, t23, t24, t25, t26, t27, t28, t29; - uint64_t t30, t31, t32, t33, t34, t35, t36, t37, t38, t39; - uint64_t t40, t41, t42, t43, t44, t45, t46, t47, t48, t49; - uint64_t t50, t51, t52, t53, t54, t55, t56, t57, t58, t59; - uint64_t t60, t61, t62, t63, t64, t65, t66, t67; - uint64_t s0, s1, s2, s3, s4, s5, s6, s7; - - x0 = q[7]; - x1 = q[6]; - x2 = q[5]; - x3 = q[4]; - x4 = q[3]; - x5 = q[2]; - x6 = q[1]; - x7 = q[0]; - - /* - * Top linear transformation. - */ - y14 = x3 ^ x5; - y13 = x0 ^ x6; - y9 = x0 ^ x3; - y8 = x0 ^ x5; - t0 = x1 ^ x2; - y1 = t0 ^ x7; - y4 = y1 ^ x3; - y12 = y13 ^ y14; - y2 = y1 ^ x0; - y5 = y1 ^ x6; - y3 = y5 ^ y8; - t1 = x4 ^ y12; - y15 = t1 ^ x5; - y20 = t1 ^ x1; - y6 = y15 ^ x7; - y10 = y15 ^ t0; - y11 = y20 ^ y9; - y7 = x7 ^ y11; - y17 = y10 ^ y11; - y19 = y10 ^ y8; - y16 = t0 ^ y11; - y21 = y13 ^ y16; - y18 = x0 ^ y16; - - /* - * Non-linear section. - */ - t2 = y12 & y15; - t3 = y3 & y6; - t4 = t3 ^ t2; - t5 = y4 & x7; - t6 = t5 ^ t2; - t7 = y13 & y16; - t8 = y5 & y1; - t9 = t8 ^ t7; - t10 = y2 & y7; - t11 = t10 ^ t7; - t12 = y9 & y11; - t13 = y14 & y17; - t14 = t13 ^ t12; - t15 = y8 & y10; - t16 = t15 ^ t12; - t17 = t4 ^ t14; - t18 = t6 ^ t16; - t19 = t9 ^ t14; - t20 = t11 ^ t16; - t21 = t17 ^ y20; - t22 = t18 ^ y19; - t23 = t19 ^ y21; - t24 = t20 ^ y18; - - t25 = t21 ^ t22; - t26 = t21 & t23; - t27 = t24 ^ t26; - t28 = t25 & t27; - t29 = t28 ^ t22; - t30 = t23 ^ t24; - t31 = t22 ^ t26; - t32 = t31 & t30; - t33 = t32 ^ t24; - t34 = t23 ^ t33; - t35 = t27 ^ t33; - t36 = t24 & t35; - t37 = t36 ^ t34; - t38 = t27 ^ t36; - t39 = t29 & t38; - t40 = t25 ^ t39; - - t41 = t40 ^ t37; - t42 = t29 ^ t33; - t43 = t29 ^ t40; - t44 = t33 ^ t37; - t45 = t42 ^ t41; - z0 = t44 & y15; - z1 = t37 & y6; - z2 = t33 & x7; - z3 = t43 & y16; - z4 = t40 & y1; - z5 = t29 & y7; - z6 = t42 & y11; - z7 = t45 & y17; - z8 = t41 & y10; - z9 = t44 & y12; - z10 = t37 & y3; - z11 = t33 & y4; - z12 = t43 & y13; - z13 = t40 & y5; - z14 = t29 & y2; - z15 = t42 & y9; - z16 = t45 & y14; - z17 = t41 & y8; - - /* - * Bottom linear transformation. - */ - t46 = z15 ^ z16; - t47 = z10 ^ z11; - t48 = z5 ^ z13; - t49 = z9 ^ z10; - t50 = z2 ^ z12; - t51 = z2 ^ z5; - t52 = z7 ^ z8; - t53 = z0 ^ z3; - t54 = z6 ^ z7; - t55 = z16 ^ z17; - t56 = z12 ^ t48; - t57 = t50 ^ t53; - t58 = z4 ^ t46; - t59 = z3 ^ t54; - t60 = t46 ^ t57; - t61 = z14 ^ t57; - t62 = t52 ^ t58; - t63 = t49 ^ t58; - t64 = z4 ^ t59; - t65 = t61 ^ t62; - t66 = z1 ^ t63; - s0 = t59 ^ t63; - s6 = t56 ^ ~t62; - s7 = t48 ^ ~t60; - t67 = t64 ^ t65; - s3 = t53 ^ t66; - s4 = t51 ^ t66; - s5 = t47 ^ t65; - s1 = t64 ^ ~s3; - s2 = t55 ^ ~t67; - - q[7] = s0; - q[6] = s1; - q[5] = s2; - q[4] = s3; - q[3] = s4; - q[2] = s5; - q[1] = s6; - q[0] = s7; -} - -static void br_aes_ct_bitslice_Sbox(uint32_t *q) { - /* - * This S-box implementation is a straightforward translation of - * the circuit described by Boyar and Peralta in "A new - * combinational logic minimization technique with applications - * to cryptology" (https://eprint.iacr.org/2009/191.pdf). - * - * Note that variables x* (input) and s* (output) are numbered - * in "reverse" order (x0 is the high bit, x7 is the low bit). - */ - - uint32_t x0, x1, x2, x3, x4, x5, x6, x7; - uint32_t y1, y2, y3, y4, y5, y6, y7, y8, y9; - uint32_t y10, y11, y12, y13, y14, y15, y16, y17, y18, y19; - uint32_t y20, y21; - uint32_t z0, z1, z2, z3, z4, z5, z6, z7, z8, z9; - uint32_t z10, z11, z12, z13, z14, z15, z16, z17; - uint32_t t0, t1, t2, t3, t4, t5, t6, t7, t8, t9; - uint32_t t10, t11, t12, t13, t14, t15, t16, t17, t18, t19; - uint32_t t20, t21, t22, t23, t24, t25, t26, t27, t28, t29; - uint32_t t30, t31, t32, t33, t34, t35, t36, t37, t38, t39; - uint32_t t40, t41, t42, t43, t44, t45, t46, t47, t48, t49; - uint32_t t50, t51, t52, t53, t54, t55, t56, t57, t58, t59; - uint32_t t60, t61, t62, t63, t64, t65, t66, t67; - uint32_t s0, s1, s2, s3, s4, s5, s6, s7; - - x0 = q[7]; - x1 = q[6]; - x2 = q[5]; - x3 = q[4]; - x4 = q[3]; - x5 = q[2]; - x6 = q[1]; - x7 = q[0]; - - /* - * Top linear transformation. - */ - y14 = x3 ^ x5; - y13 = x0 ^ x6; - y9 = x0 ^ x3; - y8 = x0 ^ x5; - t0 = x1 ^ x2; - y1 = t0 ^ x7; - y4 = y1 ^ x3; - y12 = y13 ^ y14; - y2 = y1 ^ x0; - y5 = y1 ^ x6; - y3 = y5 ^ y8; - t1 = x4 ^ y12; - y15 = t1 ^ x5; - y20 = t1 ^ x1; - y6 = y15 ^ x7; - y10 = y15 ^ t0; - y11 = y20 ^ y9; - y7 = x7 ^ y11; - y17 = y10 ^ y11; - y19 = y10 ^ y8; - y16 = t0 ^ y11; - y21 = y13 ^ y16; - y18 = x0 ^ y16; - - /* - * Non-linear section. - */ - t2 = y12 & y15; - t3 = y3 & y6; - t4 = t3 ^ t2; - t5 = y4 & x7; - t6 = t5 ^ t2; - t7 = y13 & y16; - t8 = y5 & y1; - t9 = t8 ^ t7; - t10 = y2 & y7; - t11 = t10 ^ t7; - t12 = y9 & y11; - t13 = y14 & y17; - t14 = t13 ^ t12; - t15 = y8 & y10; - t16 = t15 ^ t12; - t17 = t4 ^ t14; - t18 = t6 ^ t16; - t19 = t9 ^ t14; - t20 = t11 ^ t16; - t21 = t17 ^ y20; - t22 = t18 ^ y19; - t23 = t19 ^ y21; - t24 = t20 ^ y18; - - t25 = t21 ^ t22; - t26 = t21 & t23; - t27 = t24 ^ t26; - t28 = t25 & t27; - t29 = t28 ^ t22; - t30 = t23 ^ t24; - t31 = t22 ^ t26; - t32 = t31 & t30; - t33 = t32 ^ t24; - t34 = t23 ^ t33; - t35 = t27 ^ t33; - t36 = t24 & t35; - t37 = t36 ^ t34; - t38 = t27 ^ t36; - t39 = t29 & t38; - t40 = t25 ^ t39; - - t41 = t40 ^ t37; - t42 = t29 ^ t33; - t43 = t29 ^ t40; - t44 = t33 ^ t37; - t45 = t42 ^ t41; - z0 = t44 & y15; - z1 = t37 & y6; - z2 = t33 & x7; - z3 = t43 & y16; - z4 = t40 & y1; - z5 = t29 & y7; - z6 = t42 & y11; - z7 = t45 & y17; - z8 = t41 & y10; - z9 = t44 & y12; - z10 = t37 & y3; - z11 = t33 & y4; - z12 = t43 & y13; - z13 = t40 & y5; - z14 = t29 & y2; - z15 = t42 & y9; - z16 = t45 & y14; - z17 = t41 & y8; - - /* - * Bottom linear transformation. - */ - t46 = z15 ^ z16; - t47 = z10 ^ z11; - t48 = z5 ^ z13; - t49 = z9 ^ z10; - t50 = z2 ^ z12; - t51 = z2 ^ z5; - t52 = z7 ^ z8; - t53 = z0 ^ z3; - t54 = z6 ^ z7; - t55 = z16 ^ z17; - t56 = z12 ^ t48; - t57 = t50 ^ t53; - t58 = z4 ^ t46; - t59 = z3 ^ t54; - t60 = t46 ^ t57; - t61 = z14 ^ t57; - t62 = t52 ^ t58; - t63 = t49 ^ t58; - t64 = z4 ^ t59; - t65 = t61 ^ t62; - t66 = z1 ^ t63; - s0 = t59 ^ t63; - s6 = t56 ^ ~t62; - s7 = t48 ^ ~t60; - t67 = t64 ^ t65; - s3 = t53 ^ t66; - s4 = t51 ^ t66; - s5 = t47 ^ t65; - s1 = t64 ^ ~s3; - s2 = t55 ^ ~t67; - - q[7] = s0; - q[6] = s1; - q[5] = s2; - q[4] = s3; - q[3] = s4; - q[2] = s5; - q[1] = s6; - q[0] = s7; -} - -static void br_aes_ct_ortho(uint32_t *q) { -#define SWAPN_32(cl, ch, s, x, y) do { \ - uint32_t a, b; \ - a = (x); \ - b = (y); \ - (x) = (a & (uint32_t)(cl)) | ((b & (uint32_t)(cl)) << (s)); \ - (y) = ((a & (uint32_t)(ch)) >> (s)) | (b & (uint32_t)(ch)); \ - } while (0) - -#define SWAP2_32(x, y) SWAPN_32(0x55555555, 0xAAAAAAAA, 1, x, y) -#define SWAP4_32(x, y) SWAPN_32(0x33333333, 0xCCCCCCCC, 2, x, y) -#define SWAP8_32(x, y) SWAPN_32(0x0F0F0F0F, 0xF0F0F0F0, 4, x, y) - - SWAP2_32(q[0], q[1]); - SWAP2_32(q[2], q[3]); - SWAP2_32(q[4], q[5]); - SWAP2_32(q[6], q[7]); - - SWAP4_32(q[0], q[2]); - SWAP4_32(q[1], q[3]); - SWAP4_32(q[4], q[6]); - SWAP4_32(q[5], q[7]); - - SWAP8_32(q[0], q[4]); - SWAP8_32(q[1], q[5]); - SWAP8_32(q[2], q[6]); - SWAP8_32(q[3], q[7]); -} - -static inline void add_round_key32(uint32_t *q, const uint32_t *sk) { - q[0] ^= sk[0]; - q[1] ^= sk[1]; - q[2] ^= sk[2]; - q[3] ^= sk[3]; - q[4] ^= sk[4]; - q[5] ^= sk[5]; - q[6] ^= sk[6]; - q[7] ^= sk[7]; -} - -static inline void shift_rows32(uint32_t *q) { - int i; - - for (i = 0; i < 8; i++) { - uint32_t x; - - x = q[i]; - q[i] = (x & 0x000000FF) - | ((x & 0x0000FC00) >> 2) | ((x & 0x00000300) << 6) - | ((x & 0x00F00000) >> 4) | ((x & 0x000F0000) << 4) - | ((x & 0xC0000000) >> 6) | ((x & 0x3F000000) << 2); - } -} - -static inline uint32_t rotr16(uint32_t x) { - return (x << 16) | (x >> 16); -} - -static inline void mix_columns32(uint32_t *q) { - uint32_t q0, q1, q2, q3, q4, q5, q6, q7; - uint32_t r0, r1, r2, r3, r4, r5, r6, r7; - - q0 = q[0]; - q1 = q[1]; - q2 = q[2]; - q3 = q[3]; - q4 = q[4]; - q5 = q[5]; - q6 = q[6]; - q7 = q[7]; - r0 = (q0 >> 8) | (q0 << 24); - r1 = (q1 >> 8) | (q1 << 24); - r2 = (q2 >> 8) | (q2 << 24); - r3 = (q3 >> 8) | (q3 << 24); - r4 = (q4 >> 8) | (q4 << 24); - r5 = (q5 >> 8) | (q5 << 24); - r6 = (q6 >> 8) | (q6 << 24); - r7 = (q7 >> 8) | (q7 << 24); - - q[0] = q7 ^ r7 ^ r0 ^ rotr16(q0 ^ r0); - q[1] = q0 ^ r0 ^ q7 ^ r7 ^ r1 ^ rotr16(q1 ^ r1); - q[2] = q1 ^ r1 ^ r2 ^ rotr16(q2 ^ r2); - q[3] = q2 ^ r2 ^ q7 ^ r7 ^ r3 ^ rotr16(q3 ^ r3); - q[4] = q3 ^ r3 ^ q7 ^ r7 ^ r4 ^ rotr16(q4 ^ r4); - q[5] = q4 ^ r4 ^ r5 ^ rotr16(q5 ^ r5); - q[6] = q5 ^ r5 ^ r6 ^ rotr16(q6 ^ r6); - q[7] = q6 ^ r6 ^ r7 ^ rotr16(q7 ^ r7); -} - -static void br_aes_ct64_ortho(uint64_t *q) { -#define SWAPN(cl, ch, s, x, y) do { \ - uint64_t a, b; \ - a = (x); \ - b = (y); \ - (x) = (a & (uint64_t)(cl)) | ((b & (uint64_t)(cl)) << (s)); \ - (y) = ((a & (uint64_t)(ch)) >> (s)) | (b & (uint64_t)(ch)); \ - } while (0) - -#define SWAP2(x, y) SWAPN(0x5555555555555555, 0xAAAAAAAAAAAAAAAA, 1, x, y) -#define SWAP4(x, y) SWAPN(0x3333333333333333, 0xCCCCCCCCCCCCCCCC, 2, x, y) -#define SWAP8(x, y) SWAPN(0x0F0F0F0F0F0F0F0F, 0xF0F0F0F0F0F0F0F0, 4, x, y) - - SWAP2(q[0], q[1]); - SWAP2(q[2], q[3]); - SWAP2(q[4], q[5]); - SWAP2(q[6], q[7]); - - SWAP4(q[0], q[2]); - SWAP4(q[1], q[3]); - SWAP4(q[4], q[6]); - SWAP4(q[5], q[7]); - - SWAP8(q[0], q[4]); - SWAP8(q[1], q[5]); - SWAP8(q[2], q[6]); - SWAP8(q[3], q[7]); -} - - -static void br_aes_ct64_interleave_in(uint64_t *q0, uint64_t *q1, const uint32_t *w) { - uint64_t x0, x1, x2, x3; - - x0 = w[0]; - x1 = w[1]; - x2 = w[2]; - x3 = w[3]; - x0 |= (x0 << 16); - x1 |= (x1 << 16); - x2 |= (x2 << 16); - x3 |= (x3 << 16); - x0 &= (uint64_t)0x0000FFFF0000FFFF; - x1 &= (uint64_t)0x0000FFFF0000FFFF; - x2 &= (uint64_t)0x0000FFFF0000FFFF; - x3 &= (uint64_t)0x0000FFFF0000FFFF; - x0 |= (x0 << 8); - x1 |= (x1 << 8); - x2 |= (x2 << 8); - x3 |= (x3 << 8); - x0 &= (uint64_t)0x00FF00FF00FF00FF; - x1 &= (uint64_t)0x00FF00FF00FF00FF; - x2 &= (uint64_t)0x00FF00FF00FF00FF; - x3 &= (uint64_t)0x00FF00FF00FF00FF; - *q0 = x0 | (x2 << 8); - *q1 = x1 | (x3 << 8); -} - - -static void br_aes_ct64_interleave_out(uint32_t *w, uint64_t q0, uint64_t q1) { - uint64_t x0, x1, x2, x3; - - x0 = q0 & (uint64_t)0x00FF00FF00FF00FF; - x1 = q1 & (uint64_t)0x00FF00FF00FF00FF; - x2 = (q0 >> 8) & (uint64_t)0x00FF00FF00FF00FF; - x3 = (q1 >> 8) & (uint64_t)0x00FF00FF00FF00FF; - x0 |= (x0 >> 8); - x1 |= (x1 >> 8); - x2 |= (x2 >> 8); - x3 |= (x3 >> 8); - x0 &= (uint64_t)0x0000FFFF0000FFFF; - x1 &= (uint64_t)0x0000FFFF0000FFFF; - x2 &= (uint64_t)0x0000FFFF0000FFFF; - x3 &= (uint64_t)0x0000FFFF0000FFFF; - w[0] = (uint32_t)x0 | (uint32_t)(x0 >> 16); - w[1] = (uint32_t)x1 | (uint32_t)(x1 >> 16); - w[2] = (uint32_t)x2 | (uint32_t)(x2 >> 16); - w[3] = (uint32_t)x3 | (uint32_t)(x3 >> 16); -} - -static inline void add_round_key(uint64_t *q, const uint64_t *sk) { - q[0] ^= sk[0]; - q[1] ^= sk[1]; - q[2] ^= sk[2]; - q[3] ^= sk[3]; - q[4] ^= sk[4]; - q[5] ^= sk[5]; - q[6] ^= sk[6]; - q[7] ^= sk[7]; -} - -static inline void shift_rows(uint64_t *q) { - int i; - - for (i = 0; i < 8; i++) { - uint64_t x; - - x = q[i]; - q[i] = (x & (uint64_t)0x000000000000FFFF) - | ((x & (uint64_t)0x00000000FFF00000) >> 4) - | ((x & (uint64_t)0x00000000000F0000) << 12) - | ((x & (uint64_t)0x0000FF0000000000) >> 8) - | ((x & (uint64_t)0x000000FF00000000) << 8) - | ((x & (uint64_t)0xF000000000000000) >> 12) - | ((x & (uint64_t)0x0FFF000000000000) << 4); - } -} - -static inline uint64_t rotr32(uint64_t x) { - return (x << 32) | (x >> 32); -} - -static inline void mix_columns(uint64_t *q) { - uint64_t q0, q1, q2, q3, q4, q5, q6, q7; - uint64_t r0, r1, r2, r3, r4, r5, r6, r7; - - q0 = q[0]; - q1 = q[1]; - q2 = q[2]; - q3 = q[3]; - q4 = q[4]; - q5 = q[5]; - q6 = q[6]; - q7 = q[7]; - r0 = (q0 >> 16) | (q0 << 48); - r1 = (q1 >> 16) | (q1 << 48); - r2 = (q2 >> 16) | (q2 << 48); - r3 = (q3 >> 16) | (q3 << 48); - r4 = (q4 >> 16) | (q4 << 48); - r5 = (q5 >> 16) | (q5 << 48); - r6 = (q6 >> 16) | (q6 << 48); - r7 = (q7 >> 16) | (q7 << 48); - - q[0] = q7 ^ r7 ^ r0 ^ rotr32(q0 ^ r0); - q[1] = q0 ^ r0 ^ q7 ^ r7 ^ r1 ^ rotr32(q1 ^ r1); - q[2] = q1 ^ r1 ^ r2 ^ rotr32(q2 ^ r2); - q[3] = q2 ^ r2 ^ q7 ^ r7 ^ r3 ^ rotr32(q3 ^ r3); - q[4] = q3 ^ r3 ^ q7 ^ r7 ^ r4 ^ rotr32(q4 ^ r4); - q[5] = q4 ^ r4 ^ r5 ^ rotr32(q5 ^ r5); - q[6] = q5 ^ r5 ^ r6 ^ rotr32(q6 ^ r6); - q[7] = q6 ^ r6 ^ r7 ^ rotr32(q7 ^ r7); -} - -static void interleave_constant(uint64_t *out, const unsigned char *in) { - uint32_t tmp_32_constant[16]; - int i; - - br_range_dec32le(tmp_32_constant, 16, in); - for (i = 0; i < 4; i++) { - br_aes_ct64_interleave_in(&out[i], &out[i + 4], tmp_32_constant + (i << 2)); - } - br_aes_ct64_ortho(out); -} - -static void interleave_constant32(uint32_t *out, const unsigned char *in) { - int i; - for (i = 0; i < 4; i++) { - out[2 * i] = br_dec32le(in + 4 * i); - out[2 * i + 1] = br_dec32le(in + 4 * i + 16); - } - br_aes_ct_ortho(out); -} - -void tweak_constants(spx_ctx *ctx) { - unsigned char buf[40 * 16]; - int i; - - /* Use the standard constants to generate tweaked ones. */ - memcpy((uint8_t *)ctx->tweaked512_rc64, (uint8_t *)haraka512_rc64, 40 * 16); - - /* Constants for pk.seed */ - haraka_S(buf, 40 * 16, ctx->pub_seed, SPX_N, ctx); - for (i = 0; i < 10; i++) { - interleave_constant32(ctx->tweaked256_rc32[i], buf + 32 * i); - interleave_constant(ctx->tweaked512_rc64[i], buf + 64 * i); - } -} - -static void haraka_S_absorb(unsigned char *s, unsigned int r, - const unsigned char *m, unsigned long long mlen, - unsigned char p, const spx_ctx *ctx) { - unsigned long long i; - PQCLEAN_VLA(uint8_t, t, r); - - while (mlen >= r) { - /* XOR block to state */ - for (i = 0; i < r; ++i) { - s[i] ^= m[i]; - } - haraka512_perm(s, s, ctx); - 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; ++i) { - s[i] ^= t[i]; - } -} - -static void haraka_S_squeezeblocks(unsigned char *h, unsigned long long nblocks, - unsigned char *s, unsigned int r, - const spx_ctx *ctx) { - while (nblocks > 0) { - haraka512_perm(s, s, ctx); - memcpy(h, s, HARAKAS_RATE); - h += r; - nblocks--; - } -} - -void haraka_S_inc_init(uint8_t *s_inc) { - size_t i; - - for (i = 0; i < 64; i++) { - s_inc[i] = 0; - } - s_inc[64] = 0; -} - -void haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, - const spx_ctx *ctx) { - size_t i; - - /* Recall that s_inc[64] is the non-absorbed bytes xored into the state */ - while (mlen + s_inc[64] >= HARAKAS_RATE) { - for (i = 0; i < (size_t)(HARAKAS_RATE - s_inc[64]); i++) { - /* Take the i'th byte from message - xor with the s_inc[64] + i'th byte of the state */ - s_inc[s_inc[64] + i] ^= m[i]; - } - mlen -= (size_t)(HARAKAS_RATE - s_inc[64]); - m += HARAKAS_RATE - (uint8_t)s_inc[64]; - s_inc[64] = 0; - - haraka512_perm(s_inc, s_inc, ctx); - } - - for (i = 0; i < mlen; i++) { - s_inc[s_inc[64] + i] ^= m[i]; - } - s_inc[64] += (uint8_t)mlen; -} - -void haraka_S_inc_finalize(uint8_t *s_inc) { - /* After haraka_S_inc_absorb, we are guaranteed that s_inc[64] < HARAKAS_RATE, - so we can always use one more byte for p in the current state. */ - s_inc[s_inc[64]] ^= 0x1F; - s_inc[HARAKAS_RATE - 1] ^= 128; - s_inc[64] = 0; -} - -void haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, - const spx_ctx *ctx) { - size_t i; - - /* First consume any bytes we still have sitting around */ - for (i = 0; i < outlen && i < s_inc[64]; i++) { - /* There are s_inc[64] bytes left, so r - s_inc[64] is the first - available byte. We consume from there, i.e., up to r. */ - out[i] = (uint8_t)s_inc[(HARAKAS_RATE - s_inc[64] + i)]; - } - out += i; - outlen -= i; - s_inc[64] -= (uint8_t)i; - - /* Then squeeze the remaining necessary blocks */ - while (outlen > 0) { - haraka512_perm(s_inc, s_inc, ctx); - - for (i = 0; i < outlen && i < HARAKAS_RATE; i++) { - out[i] = s_inc[i]; - } - out += i; - outlen -= i; - s_inc[64] = (uint8_t)(HARAKAS_RATE - i); - } -} - -void haraka_S(unsigned char *out, unsigned long long outlen, - const unsigned char *in, unsigned long long inlen, - const spx_ctx *ctx) { - unsigned long long i; - unsigned char s[64]; - unsigned char d[32]; - - for (i = 0; i < 64; i++) { - s[i] = 0; - } - haraka_S_absorb(s, 32, in, inlen, 0x1F, ctx); - - haraka_S_squeezeblocks(out, outlen / 32, s, 32, ctx); - out += (outlen / 32) * 32; - - if (outlen % 32) { - haraka_S_squeezeblocks(d, 1, s, 32, ctx); - for (i = 0; i < outlen % 32; i++) { - out[i] = d[i]; - } - } -} - -void haraka512_perm(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx) { - uint32_t w[16]; - uint64_t q[8], tmp_q; - unsigned int i, j; - - br_range_dec32le(w, 16, in); - for (i = 0; i < 4; i++) { - br_aes_ct64_interleave_in(&q[i], &q[i + 4], w + (i << 2)); - } - br_aes_ct64_ortho(q); - - /* AES rounds */ - for (i = 0; i < 5; i++) { - for (j = 0; j < 2; j++) { - br_aes_ct64_bitslice_Sbox(q); - shift_rows(q); - mix_columns(q); - add_round_key(q, ctx->tweaked512_rc64[2 * i + j]); - } - /* Mix states */ - for (j = 0; j < 8; j++) { - tmp_q = q[j]; - q[j] = (tmp_q & 0x0001000100010001) << 5 | - (tmp_q & 0x0002000200020002) << 12 | - (tmp_q & 0x0004000400040004) >> 1 | - (tmp_q & 0x0008000800080008) << 6 | - (tmp_q & 0x0020002000200020) << 9 | - (tmp_q & 0x0040004000400040) >> 4 | - (tmp_q & 0x0080008000800080) << 3 | - (tmp_q & 0x2100210021002100) >> 5 | - (tmp_q & 0x0210021002100210) << 2 | - (tmp_q & 0x0800080008000800) << 4 | - (tmp_q & 0x1000100010001000) >> 12 | - (tmp_q & 0x4000400040004000) >> 10 | - (tmp_q & 0x8400840084008400) >> 3; - } - } - - br_aes_ct64_ortho(q); - for (i = 0; i < 4; i ++) { - br_aes_ct64_interleave_out(w + (i << 2), q[i], q[i + 4]); - } - br_range_enc32le(out, w, 16); -} - -void haraka512(unsigned char *out, const unsigned char *in, const spx_ctx *ctx) { - int i; - - unsigned char buf[64]; - - haraka512_perm(buf, in, ctx); - /* Feed-forward */ - for (i = 0; i < 64; i++) { - buf[i] = buf[i] ^ in[i]; - } - - /* Truncated */ - memcpy(out, buf + 8, 8); - memcpy(out + 8, buf + 24, 8); - memcpy(out + 16, buf + 32, 8); - memcpy(out + 24, buf + 48, 8); -} - - -void haraka256(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx) { - uint32_t q[8], tmp_q; - int i, j; - - for (i = 0; i < 4; i++) { - q[2 * i] = br_dec32le(in + 4 * i); - q[2 * i + 1] = br_dec32le(in + 4 * i + 16); - } - br_aes_ct_ortho(q); - - /* AES rounds */ - for (i = 0; i < 5; i++) { - for (j = 0; j < 2; j++) { - br_aes_ct_bitslice_Sbox(q); - shift_rows32(q); - mix_columns32(q); - add_round_key32(q, ctx->tweaked256_rc32[2 * i + j]); - } - - /* Mix states */ - for (j = 0; j < 8; j++) { - tmp_q = q[j]; - q[j] = (tmp_q & 0x81818181) | - (tmp_q & 0x02020202) << 1 | - (tmp_q & 0x04040404) << 2 | - (tmp_q & 0x08080808) << 3 | - (tmp_q & 0x10101010) >> 3 | - (tmp_q & 0x20202020) >> 2 | - (tmp_q & 0x40404040) >> 1; - } - } - - br_aes_ct_ortho(q); - for (i = 0; i < 4; i++) { - br_enc32le(out + 4 * i, q[2 * i]); - br_enc32le(out + 4 * i + 16, q[2 * i + 1]); - } - - for (i = 0; i < 32; i++) { - out[i] ^= in[i]; - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/haraka.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/haraka.h deleted file mode 100644 index 737cb6065f..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/haraka.h +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef SPX_HARAKA_H -#define SPX_HARAKA_H - -#include "context.h" -#include "params.h" - -/* Tweak constants with seed */ -#define tweak_constants SPX_NAMESPACE(tweak_constants) -void tweak_constants(spx_ctx *ctx); - -/* Haraka Sponge */ -#define haraka_S_inc_init SPX_NAMESPACE(haraka_S_inc_init) -void haraka_S_inc_init(uint8_t *s_inc); -#define haraka_S_inc_absorb SPX_NAMESPACE(haraka_S_inc_absorb) -void haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, - const spx_ctx *ctx); -#define haraka_S_inc_finalize SPX_NAMESPACE(haraka_S_inc_finalize) -void haraka_S_inc_finalize(uint8_t *s_inc); -#define haraka_S_inc_squeeze SPX_NAMESPACE(haraka_S_inc_squeeze) -void haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, - const spx_ctx *ctx); -#define haraka_S SPX_NAMESPACE(haraka_S) -void haraka_S(unsigned char *out, unsigned long long outlen, - const unsigned char *in, unsigned long long inlen, - const spx_ctx *ctx); - -/* Applies the 512-bit Haraka permutation to in. */ -#define haraka512_perm SPX_NAMESPACE(haraka512_perm) -void haraka512_perm(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx); - -/* Implementation of Haraka-512 */ -#define haraka512 SPX_NAMESPACE(haraka512) -void haraka512(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx); - -/* Implementation of Haraka-256 */ -#define haraka256 SPX_NAMESPACE(haraka256) -void haraka256(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/haraka_offsets.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/haraka_offsets.h deleted file mode 100644 index 7c062272a0..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/haraka_offsets.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef HARAKA_OFFSETS_H_ -#define HARAKA_OFFSETS_H_ - -/* - * Offsets of various fields in the address structure when we use Haraka as - * the Sphincs+ hash function - */ - -#define SPX_OFFSET_LAYER 3 /* The byte used to specify the Merkle tree layer */ -#define SPX_OFFSET_TREE 8 /* The start of the 8 byte field used to specify the tree */ -#define SPX_OFFSET_TYPE 19 /* The byte used to specify the hash type (reason) */ -#define SPX_OFFSET_KP_ADDR2 22 /* The high byte used to specify the key pair (which one-time signature) */ -#define SPX_OFFSET_KP_ADDR1 23 /* The low byte used to specify the key pair */ -#define SPX_OFFSET_CHAIN_ADDR 27 /* The byte used to specify the chain address (which Winternitz chain) */ -#define SPX_OFFSET_HASH_ADDR 31 /* The byte used to specify the hash address (where in the Winternitz chain) */ -#define SPX_OFFSET_TREE_HGT 27 /* The byte used to specify the height of this node in the FORS or Merkle tree */ -#define SPX_OFFSET_TREE_INDEX 28 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ - -#define SPX_HARAKA 1 - -#endif /* HARAKA_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/hash.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/hash.h deleted file mode 100644 index f7c87d4c3c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/hash.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef SPX_HASH_H -#define SPX_HASH_H - -#include -#include - -#include "context.h" -#include "params.h" - -#define prf_addr SPX_NAMESPACE(prf_addr) -void prf_addr(unsigned char *out, const spx_ctx *ctx, - const uint32_t addr[8]); - -#define gen_message_random SPX_NAMESPACE(gen_message_random) -void gen_message_random(unsigned char *R, const unsigned char *sk_prf, - const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx); - -#define hash_message SPX_NAMESPACE(hash_message) -void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx); - - - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/hash_haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/hash_haraka.c deleted file mode 100644 index 750a67423b..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/hash_haraka.c +++ /dev/null @@ -1,81 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "utils.h" - -#include "haraka.h" -#include "hash.h" - -/* - * Computes PRF(key, addr), given a secret key of SPX_N bytes and an address - */ -void prf_addr(unsigned char *out, const spx_ctx *ctx, - const uint32_t addr[8]) { - /* Since SPX_N may be smaller than 32, we need temporary buffers. */ - unsigned char outbuf[32]; - unsigned char buf[64] = {0}; - - memcpy(buf, addr, SPX_ADDR_BYTES); - memcpy(buf + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); - - haraka512(outbuf, (const void *)buf, ctx); - memcpy(out, outbuf, SPX_N); -} - -/** - * Computes the message-dependent randomness R, using a secret seed and an - * optional randomization value as well as the message. - */ -void gen_message_random(unsigned char *R, const unsigned char *sk_prf, - const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx) { - uint8_t s_inc[65]; - - haraka_S_inc_init(s_inc); - haraka_S_inc_absorb(s_inc, sk_prf, SPX_N, ctx); - haraka_S_inc_absorb(s_inc, optrand, SPX_N, ctx); - haraka_S_inc_absorb(s_inc, m, mlen, ctx); - haraka_S_inc_finalize(s_inc); - haraka_S_inc_squeeze(R, SPX_N, s_inc, ctx); -} - -/** - * Computes the message hash using R, the public key, and the message. - * Outputs the message digest and the index of the leaf. The index is split in - * the tree index and the leaf index, for convenient copying to an address. - */ -void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx) { -#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) -#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) -#define SPX_LEAF_BITS SPX_TREE_HEIGHT -#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) -#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) - - unsigned char buf[SPX_DGST_BYTES]; - unsigned char *bufp = buf; - uint8_t s_inc[65]; - - haraka_S_inc_init(s_inc); - haraka_S_inc_absorb(s_inc, R, SPX_N, ctx); - haraka_S_inc_absorb(s_inc, pk + SPX_N, SPX_N, ctx); // Only absorb root part of pk - haraka_S_inc_absorb(s_inc, m, mlen, ctx); - haraka_S_inc_finalize(s_inc); - haraka_S_inc_squeeze(buf, SPX_DGST_BYTES, s_inc, ctx); - - memcpy(digest, bufp, SPX_FORS_MSG_BYTES); - bufp += SPX_FORS_MSG_BYTES; - - - *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); - *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); - bufp += SPX_TREE_BYTES; - - *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); - *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/merkle.c b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/merkle.c deleted file mode 100644 index 0c1479fd93..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/merkle.c +++ /dev/null @@ -1,59 +0,0 @@ -#include -#include - -#include "address.h" -#include "merkle.h" -#include "params.h" -#include "utils.h" -#include "utilsx1.h" -#include "wots.h" -#include "wotsx1.h" - -/* - * This generates a Merkle signature (WOTS signature followed by the Merkle - * authentication path). This is in this file because most of the complexity - * is involved with the WOTS signature; the Merkle authentication path logic - * is mostly hidden in treehashx4 - */ -void merkle_sign(uint8_t *sig, unsigned char *root, - const spx_ctx *ctx, - uint32_t wots_addr[8], uint32_t tree_addr[8], - uint32_t idx_leaf) { - unsigned char *auth_path = sig + SPX_WOTS_BYTES; - struct leaf_info_x1 info = { 0 }; - unsigned steps[ SPX_WOTS_LEN ]; - - info.wots_sig = sig; - chain_lengths(steps, root); - info.wots_steps = steps; - - set_type(&tree_addr[0], SPX_ADDR_TYPE_HASHTREE); - set_type(&info.pk_addr[0], SPX_ADDR_TYPE_WOTSPK); - copy_subtree_addr(&info.leaf_addr[0], wots_addr); - copy_subtree_addr(&info.pk_addr[0], wots_addr); - - info.wots_sign_leaf = idx_leaf; - - treehashx1(root, auth_path, ctx, - idx_leaf, 0, - SPX_TREE_HEIGHT, - wots_gen_leafx1, - tree_addr, &info); -} - -/* Compute root node of the top-most subtree. */ -void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { - /* We do not need the auth path in key generation, but it simplifies the - code to have just one treehash routine that computes both root and path - in one function. */ - unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; - uint32_t top_tree_addr[8] = {0}; - uint32_t wots_addr[8] = {0}; - - set_layer_addr(top_tree_addr, SPX_D - 1); - set_layer_addr(wots_addr, SPX_D - 1); - - merkle_sign(auth_path, root, ctx, - wots_addr, top_tree_addr, - (uint32_t)~0 /* ~0 means "don't bother generating an auth path */ ); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/merkle.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/merkle.h deleted file mode 100644 index 769cf2e970..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/merkle.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef MERKLE_H_ -#define MERKLE_H_ - -#include - -#include "context.h" -#include "params.h" - -/* Generate a Merkle signature (WOTS signature followed by the Merkle */ -/* authentication path) */ -#define merkle_sign SPX_NAMESPACE(merkle_sign) -void merkle_sign(uint8_t *sig, unsigned char *root, - const spx_ctx *ctx, - uint32_t wots_addr[8], uint32_t tree_addr[8], - uint32_t idx_leaf); - -/* Compute the root node of the top-most subtree. */ -#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) -void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); - -#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/nistapi.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/nistapi.h deleted file mode 100644 index 3cb71afad4..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/nistapi.h +++ /dev/null @@ -1,87 +0,0 @@ -#ifndef SPX_API_H -#define SPX_API_H - -#include -#include - -#include "params.h" - -#define CRYPTO_ALGNAME "SPHINCS+" - -#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES -#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES -#define CRYPTO_BYTES SPX_BYTES -#define CRYPTO_SEEDBYTES (3*SPX_N) - -/* - * Returns the length of a secret key, in bytes - */ -#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) -size_t crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) -size_t crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) -size_t crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) -size_t crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) -int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) -int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) -int crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) -int crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -#define crypto_sign SPX_NAMESPACE(crypto_sign) -int crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) -int crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/params.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/params.h deleted file mode 100644 index ffaa5ef9ed..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/params.h +++ /dev/null @@ -1,56 +0,0 @@ -#ifndef SPX_PARAMS_H -#define SPX_PARAMS_H - -#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_##s - -/* Hash output length in bytes. */ -#define SPX_N 24 -/* Height of the hypertree. */ -#define SPX_FULL_HEIGHT 66 -/* Number of subtree layer. */ -#define SPX_D 22 -/* FORS tree dimensions. */ -#define SPX_FORS_HEIGHT 8 -#define SPX_FORS_TREES 33 -/* Winternitz parameter, */ -#define SPX_WOTS_W 16 - -/* The hash function is defined by linking a different hash.c file, as opposed - to setting a #define constant. */ - -/* For clarity */ -#define SPX_ADDR_BYTES 32 - -/* WOTS parameters. */ -#define SPX_WOTS_LOGW 4 - -#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) - -/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#define SPX_WOTS_LEN2 3 - -#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) -#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) -#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES - -/* Subtree size. */ -#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) - -//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT -// #error SPX_D should always divide SPX_FULL_HEIGHT -//#endif - -/* FORS parameters. */ -#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) -#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) -#define SPX_FORS_PK_BYTES SPX_N - -/* Resulting SPX sizes. */ -#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ - SPX_FULL_HEIGHT * SPX_N) -#define SPX_PK_BYTES (2 * SPX_N) -#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) - -#include "haraka_offsets.h" - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/sign.c b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/sign.c deleted file mode 100644 index 9d0c7d1b22..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/sign.c +++ /dev/null @@ -1,286 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "context.h" -#include "fors.h" -#include "hash.h" -#include "merkle.h" -#include "nistapi.h" -#include "params.h" -#include "randombytes.h" -#include "thash.h" -#include "utils.h" -#include "wots.h" - -/* - * Returns the length of a secret key, in bytes - */ -size_t crypto_sign_secretkeybytes(void) { - return CRYPTO_SECRETKEYBYTES; -} - -/* - * Returns the length of a public key, in bytes - */ -size_t crypto_sign_publickeybytes(void) { - return CRYPTO_PUBLICKEYBYTES; -} - -/* - * Returns the length of a signature, in bytes - */ -size_t crypto_sign_bytes(void) { - return CRYPTO_BYTES; -} - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t crypto_sign_seedbytes(void) { - return CRYPTO_SEEDBYTES; -} - -/* - * Generates an SPX key pair given a seed of length - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed) { - spx_ctx ctx; - - /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ - memcpy(sk, seed, CRYPTO_SEEDBYTES); - - memcpy(pk, sk + 2 * SPX_N, SPX_N); - - memcpy(ctx.pub_seed, pk, SPX_N); - memcpy(ctx.sk_seed, sk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - /* Compute root node of the top-most subtree. */ - merkle_gen_root(sk + 3 * SPX_N, &ctx); - - // cleanup - free_hash_function(&ctx); - - memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); - - return 0; -} - -/* - * Generates an SPX key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { - uint8_t seed[CRYPTO_SEEDBYTES]; - randombytes(seed, CRYPTO_SEEDBYTES); - crypto_sign_seed_keypair(pk, sk, seed); - - return 0; -} - -/** - * Returns an array containing a detached signature. - */ -int crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - spx_ctx ctx; - - const uint8_t *sk_prf = sk + SPX_N; - const uint8_t *pk = sk + 2 * SPX_N; - - uint8_t optrand[SPX_N]; - uint8_t mhash[SPX_FORS_MSG_BYTES]; - uint8_t root[SPX_N]; - uint32_t i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - - memcpy(ctx.sk_seed, sk, SPX_N); - memcpy(ctx.pub_seed, pk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - set_type(wots_addr, SPX_ADDR_TYPE_WOTS); - set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); - - /* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ - randombytes(optrand, SPX_N); - /* Compute the digest randomization value. */ - gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); - - /* Derive the message digest and leaf index from R, PK and M. */ - hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); - sig += SPX_N; - - set_tree_addr(wots_addr, tree); - set_keypair_addr(wots_addr, idx_leaf); - - /* Sign the message hash using FORS. */ - fors_sign(sig, root, mhash, &ctx, wots_addr); - sig += SPX_FORS_BYTES; - - for (i = 0; i < SPX_D; i++) { - set_layer_addr(tree_addr, i); - set_tree_addr(tree_addr, tree); - - copy_subtree_addr(wots_addr, tree_addr); - set_keypair_addr(wots_addr, idx_leaf); - - merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); - sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); - tree = tree >> SPX_TREE_HEIGHT; - } - - free_hash_function(&ctx); - - *siglen = SPX_BYTES; - - return 0; -} - -/** - * Verifies a detached signature and message under a given public key. - */ -int crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk) { - spx_ctx ctx; - const uint8_t *pub_root = pk + SPX_N; - uint8_t mhash[SPX_FORS_MSG_BYTES]; - uint8_t wots_pk[SPX_WOTS_BYTES]; - uint8_t root[SPX_N]; - uint8_t leaf[SPX_N]; - unsigned int i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - if (siglen != SPX_BYTES) { - return -1; - } - - memcpy(ctx.pub_seed, pk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - set_type(wots_addr, SPX_ADDR_TYPE_WOTS); - set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); - set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); - - /* Derive the message digest and leaf index from R || PK || M. */ - /* The additional SPX_N is a result of the hash domain separator. */ - hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); - sig += SPX_N; - - /* Layer correctly defaults to 0, so no need to set_layer_addr */ - set_tree_addr(wots_addr, tree); - set_keypair_addr(wots_addr, idx_leaf); - - fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); - sig += SPX_FORS_BYTES; - - /* For each subtree.. */ - for (i = 0; i < SPX_D; i++) { - set_layer_addr(tree_addr, i); - set_tree_addr(tree_addr, tree); - - copy_subtree_addr(wots_addr, tree_addr); - set_keypair_addr(wots_addr, idx_leaf); - - copy_keypair_addr(wots_pk_addr, wots_addr); - - /* The WOTS public key is only correct if the signature was correct. */ - /* Initially, root is the FORS pk, but on subsequent iterations it is - the root of the subtree below the currently processed subtree. */ - wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); - sig += SPX_WOTS_BYTES; - - /* Compute the leaf node using the WOTS public key. */ - thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); - - /* Compute the root node of this subtree. */ - compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, - &ctx, tree_addr); - sig += SPX_TREE_HEIGHT * SPX_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); - tree = tree >> SPX_TREE_HEIGHT; - } - - // cleanup - free_hash_function(&ctx); - - /* Check if the root node equals the root node in the public key. */ - if (memcmp(root, pub_root, SPX_N) != 0) { - return -1; - } - - return 0; -} - - -/** - * Returns an array containing the signature followed by the message. - */ -int crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk) { - size_t siglen; - - crypto_sign_signature(sm, &siglen, m, mlen, sk); - - memmove(sm + SPX_BYTES, m, mlen); - *smlen = siglen + mlen; - - return 0; -} - -/** - * Verifies a given signature-message pair under a given public key. - */ -int crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk) { - /* The API caller does not necessarily know what size a signature should be - but SPHINCS+ signatures are always exactly SPX_BYTES. */ - if (smlen < SPX_BYTES) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - *mlen = smlen - SPX_BYTES; - - if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - /* If verification was successful, move the message to the right place. */ - memmove(m, sm + SPX_BYTES, *mlen); - - return 0; -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/thash.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/thash.h deleted file mode 100644 index 8687ccfb4d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/thash.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef SPX_THASH_H -#define SPX_THASH_H - -#include "context.h" -#include "params.h" - -#include - -#define thash SPX_NAMESPACE(thash) -void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/thash_haraka_simple.c b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/thash_haraka_simple.c deleted file mode 100644 index 207777bf8d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/thash_haraka_simple.c +++ /dev/null @@ -1,36 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "thash.h" -#include "utils.h" - -#include "haraka.h" - -/** - * Takes an array of inblocks concatenated arrays of SPX_N bytes. - */ -void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]) { - PQCLEAN_VLA(uint8_t, buf, SPX_ADDR_BYTES + inblocks * SPX_N); - unsigned char outbuf[32]; - unsigned char buf_tmp[64]; - - if (inblocks == 1) { - /* F function */ - /* Since SPX_N may be smaller than 32, we need a temporary buffer. */ - memset(buf_tmp, 0, 64); - memcpy(buf_tmp, addr, 32); - memcpy(buf_tmp + SPX_ADDR_BYTES, in, SPX_N); - - haraka512(outbuf, buf_tmp, ctx); - memcpy(out, outbuf, SPX_N); - } else { - /* All other tweakable hashes*/ - memcpy(buf, addr, 32); - memcpy(buf + SPX_ADDR_BYTES, in, inblocks * SPX_N); - - haraka_S(out, SPX_N, buf, SPX_ADDR_BYTES + inblocks * SPX_N, ctx); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/utils.c b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/utils.c deleted file mode 100644 index 177b541fb9..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/utils.c +++ /dev/null @@ -1,148 +0,0 @@ -#include - -#include "utils.h" - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "thash.h" - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void ull_to_bytes(unsigned char *out, unsigned int outlen, - unsigned long long in) { - int i; - - /* Iterate over out in decreasing order, for big-endianness. */ - for (i = (signed int)outlen - 1; i >= 0; i--) { - out[i] = in & 0xff; - in = in >> 8; - } -} - -void u32_to_bytes(unsigned char *out, uint32_t in) { - out[0] = (unsigned char)(in >> 24); - out[1] = (unsigned char)(in >> 16); - out[2] = (unsigned char)(in >> 8); - out[3] = (unsigned char)in; -} - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { - unsigned long long retval = 0; - unsigned int i; - - for (i = 0; i < inlen; i++) { - retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); - } - return retval; -} - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void compute_root(unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const spx_ctx *ctx, uint32_t addr[8]) { - uint32_t i; - unsigned char buffer[2 * SPX_N]; - - /* If leaf_idx is odd (last bit = 1), current path element is a right child - and auth_path has to go left. Otherwise it is the other way around. */ - if (leaf_idx & 1) { - memcpy(buffer + SPX_N, leaf, SPX_N); - memcpy(buffer, auth_path, SPX_N); - } else { - memcpy(buffer, leaf, SPX_N); - memcpy(buffer + SPX_N, auth_path, SPX_N); - } - auth_path += SPX_N; - - for (i = 0; i < tree_height - 1; i++) { - leaf_idx >>= 1; - idx_offset >>= 1; - /* Set the address of the node we're creating. */ - set_tree_height(addr, i + 1); - set_tree_index(addr, leaf_idx + idx_offset); - - /* Pick the right or left neighbor, depending on parity of the node. */ - if (leaf_idx & 1) { - thash(buffer + SPX_N, buffer, 2, ctx, addr); - memcpy(buffer, auth_path, SPX_N); - } else { - thash(buffer, buffer, 2, ctx, addr); - memcpy(buffer + SPX_N, auth_path, SPX_N); - } - auth_path += SPX_N; - } - - /* The last iteration is exceptional; we do not copy an auth_path node. */ - leaf_idx >>= 1; - idx_offset >>= 1; - set_tree_height(addr, tree_height); - set_tree_index(addr, leaf_idx + idx_offset); - thash(root, buffer, 2, ctx, addr); -} - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const spx_ctx * /* ctx */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), - uint32_t tree_addr[8]) { - PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); - PQCLEAN_VLA(unsigned int, heights, tree_height + 1); - unsigned int offset = 0; - uint32_t idx; - uint32_t tree_idx; - - for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { - /* Add the next leaf node to the stack. */ - gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); - offset++; - heights[offset - 1] = 0; - - /* If this is a node we need for the auth path.. */ - if ((leaf_idx ^ 0x1) == idx) { - memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); - } - - /* While the top-most nodes are of equal height.. */ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { - /* Compute index of the new node, in the next layer. */ - tree_idx = (idx >> (heights[offset - 1] + 1)); - - /* Set the address of the node we're creating. */ - set_tree_height(tree_addr, heights[offset - 1] + 1); - set_tree_index(tree_addr, - tree_idx + (idx_offset >> (heights[offset - 1] + 1))); - /* Hash the top-most nodes from the stack together. */ - thash(stack + (offset - 2)*SPX_N, - stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); - offset--; - /* Note that the top-most node is now one layer higher. */ - heights[offset - 1]++; - - /* If this is a node we need for the auth path.. */ - if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_path + heights[offset - 1]*SPX_N, - stack + (offset - 1)*SPX_N, SPX_N); - } - } - } - memcpy(root, stack, SPX_N); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/utils.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/utils.h deleted file mode 100644 index 64f5d5a53a..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/utils.h +++ /dev/null @@ -1,58 +0,0 @@ -#ifndef SPX_UTILS_H -#define SPX_UTILS_H - -#include - -#include "compat.h" -#include "context.h" -#include "params.h" - - -/* To support MSVC use alloca() instead of VLAs. See #20. */ - - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) -void ull_to_bytes(unsigned char *out, unsigned int outlen, - unsigned long long in); -#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) -void u32_to_bytes(unsigned char *out, uint32_t in); - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) -unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -#define compute_root SPX_NAMESPACE(compute_root) -void compute_root(unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const spx_ctx *ctx, uint32_t addr[8]); - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -#define treehash SPX_NAMESPACE(treehash) -void treehash(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const spx_ctx *ctx /* ctx */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), - uint32_t tree_addr[8]); - - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/utilsx1.c b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/utilsx1.c deleted file mode 100644 index fccb69b35d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/utilsx1.c +++ /dev/null @@ -1,100 +0,0 @@ -#include - -#include "utilsx1.h" - -#include "address.h" -#include "params.h" -#include "thash.h" -#include "utils.h" - -/* - * Generate the entire Merkle tree, computing the authentication path for - * leaf_idx, and the resulting root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) - * - * This expects tree_addr to be initialized to the addr structures for the - * Merkle tree nodes - * - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - * - * This works by using the standard Merkle tree building algorithm, - */ -void treehashx1(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, - uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* Where to write the leaves */, - const spx_ctx * /* ctx */, - uint32_t idx, void *info), - uint32_t tree_addr[8], - void *info) { - /* This is where we keep the intermediate nodes */ - PQCLEAN_VLA(uint8_t, stack, tree_height * SPX_N); - - uint32_t idx; - uint32_t max_idx = (uint32_t)((1 << tree_height) - 1); - for (idx = 0;; idx++) { - unsigned char current[2 * SPX_N]; /* Current logical node is at */ - /* index[SPX_N]. We do this to minimize the number of copies */ - /* needed during a thash */ - gen_leaf( ¤t[SPX_N], ctx, idx + idx_offset, - info ); - - /* Now combine the freshly generated right node with previously */ - /* generated left ones */ - uint32_t internal_idx_offset = idx_offset; - uint32_t internal_idx = idx; - uint32_t internal_leaf = leaf_idx; - uint32_t h; /* The height we are in the Merkle tree */ - for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { - - /* Check if we hit the top of the tree */ - if (h == tree_height) { - /* We hit the root; return it */ - memcpy( root, ¤t[SPX_N], SPX_N ); - return; - } - - /* - * Check if the node we have is a part of the - * authentication path; if it is, write it out - */ - if ((internal_idx ^ internal_leaf) == 0x01) { - memcpy( &auth_path[ h * SPX_N ], - ¤t[SPX_N], - SPX_N ); - } - - /* - * Check if we're at a left child; if so, stop going up the stack - * Exception: if we've reached the end of the tree, keep on going - * (so we combine the last 4 nodes into the one root node in two - * more iterations) - */ - if ((internal_idx & 1) == 0 && idx < max_idx) { - break; - } - - /* Ok, we're at a right node */ - /* Now combine the left and right logical nodes together */ - - /* Set the address of the node we're creating. */ - internal_idx_offset >>= 1; - set_tree_height(tree_addr, h + 1); - set_tree_index(tree_addr, internal_idx / 2 + internal_idx_offset ); - - unsigned char *left = &stack[h * SPX_N]; - memcpy( ¤t[0], left, SPX_N ); - thash( ¤t[1 * SPX_N], - ¤t[0 * SPX_N], - 2, ctx, tree_addr); - } - - /* We've hit a left child; save the current for when we get the */ - /* corresponding right right */ - memcpy( &stack[h * SPX_N], ¤t[SPX_N], SPX_N); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/utilsx1.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/utilsx1.h deleted file mode 100644 index e911d17d53..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/utilsx1.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef SPX_UTILSX4_H -#define SPX_UTILSX4_H - -#include - -#include "context.h" -#include "params.h" - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -#define treehashx1 SPX_NAMESPACE(treehashx1) -void treehashx1(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* Where to write the leaf */, - const spx_ctx * /* ctx */, - uint32_t addr_idx, void *info), - uint32_t tree_addrx4[8], void *info); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/wots.c b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/wots.c deleted file mode 100644 index 249717aaa8..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/wots.c +++ /dev/null @@ -1,108 +0,0 @@ -#include -#include - -#include "wots.h" -#include "wotsx1.h" - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "thash.h" -#include "utils.h" -#include "utilsx1.h" - -// TODO clarify address expectations, and make them more uniform. -// TODO i.e. do we expect types to be set already? -// TODO and do we expect modifications or copies? - -/** - * Computes the chaining function. - * out and in have to be n-byte arrays. - * - * Interprets in as start-th value of the chain. - * addr has to contain the address of the chain. - */ -static void gen_chain(unsigned char *out, const unsigned char *in, - unsigned int start, unsigned int steps, - const spx_ctx *ctx, uint32_t addr[8]) { - uint32_t i; - - /* Initialize out with the value at position 'start'. */ - memcpy(out, in, SPX_N); - - /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < SPX_WOTS_W; i++) { - set_hash_addr(addr, i); - thash(out, out, 1, ctx, addr); - } -} - -/** - * base_w algorithm as described in draft. - * Interprets an array of bytes as integers in base w. - * This only works when log_w is a divisor of 8. - */ -static void base_w(unsigned int *output, const int out_len, - const unsigned char *input) { - int in = 0; - int out = 0; - unsigned char total = 0; - int bits = 0; - int consumed; - - for (consumed = 0; consumed < out_len; consumed++) { - if (bits == 0) { - total = input[in]; - in++; - bits += 8; - } - bits -= SPX_WOTS_LOGW; - output[out] = (total >> bits) & (SPX_WOTS_W - 1); - out++; - } -} - -/* Computes the WOTS+ checksum over a message (in base_w). */ -static void wots_checksum(unsigned int *csum_base_w, - const unsigned int *msg_base_w) { - unsigned int csum = 0; - unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; - unsigned int i; - - /* Compute checksum. */ - for (i = 0; i < SPX_WOTS_LEN1; i++) { - csum += SPX_WOTS_W - 1 - msg_base_w[i]; - } - - /* Convert checksum to base_w. */ - /* Make sure expected empty zero bits are the least significant bits. */ - csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); - ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); - base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); -} - -/* Takes a message and derives the matching chain lengths. */ -void chain_lengths(unsigned int *lengths, const unsigned char *msg) { - base_w(lengths, SPX_WOTS_LEN1, msg); - wots_checksum(lengths + SPX_WOTS_LEN1, lengths); -} - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const spx_ctx *ctx, uint32_t addr[8]) { - unsigned int lengths[SPX_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < SPX_WOTS_LEN; i++) { - set_chain_addr(addr, i); - gen_chain(pk + i * SPX_N, sig + i * SPX_N, - lengths[i], SPX_WOTS_W - 1 - lengths[i], ctx, addr); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/wots.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/wots.h deleted file mode 100644 index 4e7692eeef..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/wots.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef SPX_WOTS_H -#define SPX_WOTS_H - -#include - -#include "context.h" -#include "params.h" - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) -void wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const spx_ctx *ctx, uint32_t addr[8]); - -/* - * Compute the chain lengths needed for a given message hash - */ -#define chain_lengths SPX_NAMESPACE(chain_lengths) -void chain_lengths(unsigned int *lengths, const unsigned char *msg); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/wotsx1.c b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/wotsx1.c deleted file mode 100644 index 3adec78dfb..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/wotsx1.c +++ /dev/null @@ -1,76 +0,0 @@ -#include -#include - -#include "wots.h" -#include "wotsx1.h" - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "thash.h" -#include "utils.h" - -/* - * This generates a WOTS public key - * It also generates the WOTS signature if leaf_info indicates - * that we're signing with this WOTS key - */ -void wots_gen_leafx1(unsigned char *dest, - const spx_ctx *ctx, - uint32_t leaf_idx, void *v_info) { - struct leaf_info_x1 *info = v_info; - uint32_t *leaf_addr = info->leaf_addr; - uint32_t *pk_addr = info->pk_addr; - unsigned int i, k; - unsigned char pk_buffer[ SPX_WOTS_BYTES ]; - unsigned char *buffer; - uint32_t wots_k_mask; - - if (leaf_idx == info->wots_sign_leaf) { - /* We're traversing the leaf that's signing; generate the WOTS */ - /* signature */ - wots_k_mask = 0; - } else { - /* Nope, we're just generating pk's; turn off the signature logic */ - wots_k_mask = (uint32_t)~0; - } - - set_keypair_addr( leaf_addr, leaf_idx ); - set_keypair_addr( pk_addr, leaf_idx ); - - for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { - uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k to */ - /* the step if we're generating a signature, ~0 if we're not */ - - /* Start with the secret seed */ - set_chain_addr(leaf_addr, i); - set_hash_addr(leaf_addr, 0); - set_type(leaf_addr, SPX_ADDR_TYPE_WOTSPRF); - - prf_addr(buffer, ctx, leaf_addr); - - set_type(leaf_addr, SPX_ADDR_TYPE_WOTS); - - /* Iterate down the WOTS chain */ - for (k = 0;; k++) { - /* Check if this is the value that needs to be saved as a */ - /* part of the WOTS signature */ - if (k == wots_k) { - memcpy( info->wots_sig + i * SPX_N, buffer, SPX_N ); - } - - /* Check if we hit the top of the chain */ - if (k == SPX_WOTS_W - 1) { - break; - } - - /* Iterate one step on the chain */ - set_hash_addr(leaf_addr, k); - - thash(buffer, buffer, 1, ctx, leaf_addr); - } - } - - /* Do the final thash to generate the public keys */ - thash(dest, pk_buffer, SPX_WOTS_LEN, ctx, pk_addr); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/wotsx1.h b/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/wotsx1.h deleted file mode 100644 index e617929f96..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192f-simple_clean/wotsx1.h +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef WOTSX1_H_ -#define WOTSX1_H_ - -#include - -#include "context.h" -#include "params.h" - -/* - * This is here to provide an interface to the internal wots_gen_leafx1 - * routine. While this routine is not referenced in the package outside of - * wots.c, it is called from the stand-alone benchmark code to characterize - * the performance - */ -struct leaf_info_x1 { - unsigned char *wots_sig; - uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ - uint32_t *wots_steps; - uint32_t leaf_addr[8]; - uint32_t pk_addr[8]; -}; - -/* Macro to set the leaf_info to something 'benign', that is, it would */ -/* run with the same time as it does during the real signing process */ -/* Used only by the benchmark code */ -#define INITIALIZE_LEAF_INFO_X1(info, addr, step_buffer) { \ - (info).wots_sig = 0; \ - (info).wots_sign_leaf = ~0; \ - (info).wots_steps = step_buffer; \ - memcpy( &(info).leaf_addr[0], (addr), 32 ); \ - memcpy( &(info).pk_addr[0], (addr), 32 ); \ - } - -#define wots_gen_leafx1 SPX_NAMESPACE(wots_gen_leafx1) -void wots_gen_leafx1(unsigned char *dest, - const spx_ctx *ctx, - uint32_t leaf_idx, void *v_info); - -#endif /* WOTSX1_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/LICENSE b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/LICENSE deleted file mode 100644 index 670154e353..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/LICENSE +++ /dev/null @@ -1,116 +0,0 @@ -CC0 1.0 Universal - -Statement of Purpose - -The laws of most jurisdictions throughout the world automatically confer -exclusive Copyright and Related Rights (defined below) upon the creator and -subsequent owner(s) (each and all, an "owner") of an original work of -authorship and/or a database (each, a "Work"). - -Certain owners wish to permanently relinquish those rights to a Work for the -purpose of contributing to a commons of creative, cultural and scientific -works ("Commons") that the public can reliably and without fear of later -claims of infringement build upon, modify, incorporate in other works, reuse -and redistribute as freely as possible in any form whatsoever and for any -purposes, including without limitation commercial purposes. These owners may -contribute to the Commons to promote the ideal of a free culture and the -further production of creative, cultural and scientific works, or to gain -reputation or greater distribution for their Work in part through the use and -efforts of others. - -For these and/or other purposes and motivations, and without any expectation -of additional consideration or compensation, the person associating CC0 with a -Work (the "Affirmer"), to the extent that he or she is an owner of Copyright -and Related Rights in the Work, voluntarily elects to apply CC0 to the Work -and publicly distribute the Work under its terms, with knowledge of his or her -Copyright and Related Rights in the Work and the meaning and intended legal -effect of CC0 on those rights. - -1. Copyright and Related Rights. A Work made available under CC0 may be -protected by copyright and related or neighboring rights ("Copyright and -Related Rights"). Copyright and Related Rights include, but are not limited -to, the following: - - i. the right to reproduce, adapt, distribute, perform, display, communicate, - and translate a Work; - - ii. moral rights retained by the original author(s) and/or performer(s); - - iii. publicity and privacy rights pertaining to a person's image or likeness - depicted in a Work; - - iv. rights protecting against unfair competition in regards to a Work, - subject to the limitations in paragraph 4(a), below; - - v. rights protecting the extraction, dissemination, use and reuse of data in - a Work; - - vi. database rights (such as those arising under Directive 96/9/EC of the - European Parliament and of the Council of 11 March 1996 on the legal - protection of databases, and under any national implementation thereof, - including any amended or successor version of such directive); and - - vii. other similar, equivalent or corresponding rights throughout the world - based on applicable law or treaty, and any national implementations thereof. - -2. Waiver. To the greatest extent permitted by, but not in contravention of, -applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and -unconditionally waives, abandons, and surrenders all of Affirmer's Copyright -and Related Rights and associated claims and causes of action, whether now -known or unknown (including existing as well as future claims and causes of -action), in the Work (i) in all territories worldwide, (ii) for the maximum -duration provided by applicable law or treaty (including future time -extensions), (iii) in any current or future medium and for any number of -copies, and (iv) for any purpose whatsoever, including without limitation -commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes -the Waiver for the benefit of each member of the public at large and to the -detriment of Affirmer's heirs and successors, fully intending that such Waiver -shall not be subject to revocation, rescission, cancellation, termination, or -any other legal or equitable action to disrupt the quiet enjoyment of the Work -by the public as contemplated by Affirmer's express Statement of Purpose. - -3. Public License Fallback. Should any part of the Waiver for any reason be -judged legally invalid or ineffective under applicable law, then the Waiver -shall be preserved to the maximum extent permitted taking into account -Affirmer's express Statement of Purpose. In addition, to the extent the Waiver -is so judged Affirmer hereby grants to each affected person a royalty-free, -non transferable, non sublicensable, non exclusive, irrevocable and -unconditional license to exercise Affirmer's Copyright and Related Rights in -the Work (i) in all territories worldwide, (ii) for the maximum duration -provided by applicable law or treaty (including future time extensions), (iii) -in any current or future medium and for any number of copies, and (iv) for any -purpose whatsoever, including without limitation commercial, advertising or -promotional purposes (the "License"). The License shall be deemed effective as -of the date CC0 was applied by Affirmer to the Work. Should any part of the -License for any reason be judged legally invalid or ineffective under -applicable law, such partial invalidity or ineffectiveness shall not -invalidate the remainder of the License, and in such case Affirmer hereby -affirms that he or she will not (i) exercise any of his or her remaining -Copyright and Related Rights in the Work or (ii) assert any associated claims -and causes of action with respect to the Work, in either case contrary to -Affirmer's express Statement of Purpose. - -4. Limitations and Disclaimers. - - a. No trademark or patent rights held by Affirmer are waived, abandoned, - surrendered, licensed or otherwise affected by this document. - - b. Affirmer offers the Work as-is and makes no representations or warranties - of any kind concerning the Work, express, implied, statutory or otherwise, - including without limitation warranties of title, merchantability, fitness - for a particular purpose, non infringement, or the absence of latent or - other defects, accuracy, or the present or absence of errors, whether or not - discoverable, all to the greatest extent permissible under applicable law. - - c. Affirmer disclaims responsibility for clearing rights of other persons - that may apply to the Work or any use thereof, including without limitation - any person's Copyright and Related Rights in the Work. Further, Affirmer - disclaims responsibility for obtaining any necessary consents, permissions - or other rights required for any use of the Work. - - d. Affirmer understands and acknowledges that Creative Commons is not a - party to this document and has no duty or obligation with respect to this - CC0 or use of the Work. - -For more information, please see - diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/address.c b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/address.c deleted file mode 100644 index d49d9f3b6b..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/address.c +++ /dev/null @@ -1,95 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "utils.h" - -/* - * Specify which level of Merkle tree (the "layer") we're working on - */ -void set_layer_addr(uint32_t addr[8], uint32_t layer) { - ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; -} - -/* - * Specify which Merkle tree within the level (the "tree address") we're working on - */ -void set_tree_addr(uint32_t addr[8], uint64_t tree) { - ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); -} - -/* - * Specify the reason we'll use this address structure for, that is, what - * hash will we compute with it. This is used so that unrelated types of - * hashes don't accidentally get the same address structure. The type will be - * one of the SPX_ADDR_TYPE constants - */ -void set_type(uint32_t addr[8], uint32_t type) { - ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; -} - -/* - * Copy the layer and tree fields of the address structure. This is used - * when we're doing multiple types of hashes within the same Merkle tree - */ -void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { - memcpy( out, in, SPX_OFFSET_TREE + 8 ); -} - -/* These functions are used for OTS addresses. */ - -/* - * Specify which Merkle leaf we're working on; that is, which OTS keypair - * we're talking about. - */ -void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { - /* We have > 256 OTS at the bottom of the Merkle tree; to specify */ - /* which one, we'd need to express it in two bytes */ - ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR2] = (unsigned char)(keypair >> 8); - ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; -} - -/* - * Copy the layer, tree and keypair fields of the address structure. This is - * used when we're doing multiple things within the same OTS keypair - */ -void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { - memcpy( out, in, SPX_OFFSET_TREE + 8 ); - ((unsigned char *)out)[SPX_OFFSET_KP_ADDR2] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR2]; - ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; -} - -/* - * Specify which Merkle chain within the OTS we're working with - * (the chain address) - */ -void set_chain_addr(uint32_t addr[8], uint32_t chain) { - ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; -} - -/* - * Specify where in the Merkle chain we are -* (the hash address) - */ -void set_hash_addr(uint32_t addr[8], uint32_t hash) { - ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; -} - -/* These functions are used for all hash tree addresses (including FORS). */ - -/* - * Specify the height of the node in the Merkle/FORS tree we are in - * (the tree height) - */ -void set_tree_height(uint32_t addr[8], uint32_t tree_height) { - ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; -} - -/* - * Specify the distance from the left edge of the node in the Merkle/FORS tree - * (the tree index) - */ -void set_tree_index(uint32_t addr[8], uint32_t tree_index) { - u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/address.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/address.h deleted file mode 100644 index 24a84eb40c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/address.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef SPX_ADDRESS_H -#define SPX_ADDRESS_H - -#include - -#include "params.h" - -/* The hash types that are passed to set_type */ -#define SPX_ADDR_TYPE_WOTS 0 -#define SPX_ADDR_TYPE_WOTSPK 1 -#define SPX_ADDR_TYPE_HASHTREE 2 -#define SPX_ADDR_TYPE_FORSTREE 3 -#define SPX_ADDR_TYPE_FORSPK 4 -#define SPX_ADDR_TYPE_WOTSPRF 5 -#define SPX_ADDR_TYPE_FORSPRF 6 - -#define set_layer_addr SPX_NAMESPACE(set_layer_addr) -void set_layer_addr(uint32_t addr[8], uint32_t layer); - -#define set_tree_addr SPX_NAMESPACE(set_tree_addr) -void set_tree_addr(uint32_t addr[8], uint64_t tree); - -#define set_type SPX_NAMESPACE(set_type) -void set_type(uint32_t addr[8], uint32_t type); - -/* Copies the layer and tree part of one address into the other */ -#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) -void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for WOTS and FORS addresses. */ - -#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) -void set_keypair_addr(uint32_t addr[8], uint32_t keypair); - -#define set_chain_addr SPX_NAMESPACE(set_chain_addr) -void set_chain_addr(uint32_t addr[8], uint32_t chain); - -#define set_hash_addr SPX_NAMESPACE(set_hash_addr) -void set_hash_addr(uint32_t addr[8], uint32_t hash); - -#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) -void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for all hash tree addresses (including FORS). */ - -#define set_tree_height SPX_NAMESPACE(set_tree_height) -void set_tree_height(uint32_t addr[8], uint32_t tree_height); - -#define set_tree_index SPX_NAMESPACE(set_tree_index) -void set_tree_index(uint32_t addr[8], uint32_t tree_index); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/api.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/api.h deleted file mode 100644 index b435391496..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/api.h +++ /dev/null @@ -1,77 +0,0 @@ -#ifndef PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_API_H -#define PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_API_H - -#include -#include - -#define PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_CRYPTO_ALGNAME "SPHINCS+-haraka-192s-robust" - -#define PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_CRYPTO_SECRETKEYBYTES 96 -#define PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_CRYPTO_PUBLICKEYBYTES 48 -#define PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_CRYPTO_BYTES 16224 - -#define PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_CRYPTO_SEEDBYTES 72 - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, - const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk); -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/context.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/context.h deleted file mode 100644 index f03446b9cb..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/context.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef SPX_CONTEXT_H -#define SPX_CONTEXT_H - -#include - -#include "immintrin.h" -#include "params.h" - -typedef struct { - uint8_t pub_seed[SPX_N]; - uint8_t sk_seed[SPX_N]; - - __m128i rc[40]; -} spx_ctx; - -#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) -void initialize_hash_function(spx_ctx *ctx); - -#define free_hash_function SPX_NAMESPACE(free_hash_function) -void free_hash_function(spx_ctx *ctx); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/context_haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/context_haraka.c deleted file mode 100644 index f1cd7e3664..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/context_haraka.c +++ /dev/null @@ -1,11 +0,0 @@ -#include "context.h" -#include "haraka.h" - -void initialize_hash_function(spx_ctx *ctx) { - tweak_constants(ctx); -} - -// we don't support heap-based haraka right now -void free_hash_function(spx_ctx *ctx) { - (void)ctx; // suppress unused variable warnings -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/fors.c b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/fors.c deleted file mode 100644 index f1b0639cfc..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/fors.c +++ /dev/null @@ -1,202 +0,0 @@ -#include -#include -#include - -#include "fors.h" - -#include "address.h" -#include "hash.h" -#include "hashx4.h" -#include "thash.h" -#include "thashx4.h" -#include "utils.h" -#include "utilsx4.h" - -static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, - uint32_t fors_leaf_addr[8]) { - prf_addr(sk, ctx, fors_leaf_addr); -} - -static void fors_gen_skx4(unsigned char *sk0, - unsigned char *sk1, - unsigned char *sk2, - unsigned char *sk3, const spx_ctx *ctx, - uint32_t fors_leaf_addrx4[4 * 8]) { - prf_addrx4(sk0, sk1, sk2, sk3, - ctx, fors_leaf_addrx4); -} - -static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, - const spx_ctx *ctx, - uint32_t fors_leaf_addr[8]) { - thash(leaf, sk, 1, ctx, fors_leaf_addr); -} - -static void fors_sk_to_leafx4(unsigned char *leaf0, - unsigned char *leaf1, - unsigned char *leaf2, - unsigned char *leaf3, - const unsigned char *sk0, - const unsigned char *sk1, - const unsigned char *sk2, - const unsigned char *sk3, - const spx_ctx *ctx, - uint32_t fors_leaf_addrx4[4 * 8]) { - thashx4(leaf0, leaf1, leaf2, leaf3, - sk0, sk1, sk2, sk3, - 1, ctx, fors_leaf_addrx4); -} - -struct fors_gen_leaf_info { - uint32_t leaf_addrx[4 * 8]; -}; - -static void fors_gen_leafx4(unsigned char *leaf, - const spx_ctx *ctx, - uint32_t addr_idx, void *info) { - struct fors_gen_leaf_info *fors_info = info; - uint32_t *fors_leaf_addrx4 = fors_info->leaf_addrx; - unsigned int j; - - /* Only set the parts that the caller doesn't set */ - for (j = 0; j < 4; j++) { - set_tree_index(fors_leaf_addrx4 + j * 8, addr_idx + j); - set_type(fors_leaf_addrx4 + j * 8, SPX_ADDR_TYPE_FORSPRF); - } - - fors_gen_skx4(leaf + 0 * SPX_N, - leaf + 1 * SPX_N, - leaf + 2 * SPX_N, - leaf + 3 * SPX_N, - ctx, fors_leaf_addrx4); - - for (j = 0; j < 4; j++) { - set_type(fors_leaf_addrx4 + j * 8, SPX_ADDR_TYPE_FORSTREE); - } - - fors_sk_to_leafx4(leaf + 0 * SPX_N, - leaf + 1 * SPX_N, - leaf + 2 * SPX_N, - leaf + 3 * SPX_N, - leaf + 0 * SPX_N, - leaf + 1 * SPX_N, - leaf + 2 * SPX_N, - leaf + 3 * SPX_N, - ctx, fors_leaf_addrx4); -} - -/** - * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - * Assumes indices has space for SPX_FORS_TREES integers. - */ -static void message_to_indices(uint32_t *indices, const unsigned char *m) { - unsigned int i, j; - unsigned int offset = 0; - - for (i = 0; i < SPX_FORS_TREES; i++) { - indices[i] = 0; - for (j = 0; j < SPX_FORS_HEIGHT; j++) { - indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); - offset++; - } - } -} - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -void fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]) { - uint32_t indices[SPX_FORS_TREES]; - unsigned char roots[SPX_FORS_TREES * SPX_N]; - uint32_t fors_tree_addr[4 * 8] = {0}; - struct fors_gen_leaf_info fors_info = {0}; - uint32_t *fors_leaf_addr = fors_info.leaf_addrx; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - for (i = 0; i < 4; i++) { - copy_keypair_addr(fors_tree_addr + 8 * i, fors_addr); - set_type(fors_tree_addr + 8 * i, SPX_ADDR_TYPE_FORSTREE); - copy_keypair_addr(fors_leaf_addr + 8 * i, fors_addr); - } - copy_keypair_addr(fors_pk_addr, fors_addr); - set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < SPX_FORS_TREES; i++) { - idx_offset = i * (1 << SPX_FORS_HEIGHT); - - set_tree_height(fors_tree_addr, 0); - set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Include the secret key part that produces the selected leaf node. */ - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); - fors_gen_sk(sig, ctx, fors_tree_addr); - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); - sig += SPX_N; - - /* Compute the authentication path for this leaf node. */ - treehashx4(roots + i * SPX_N, sig, ctx, - indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx4, - fors_tree_addr, &fors_info); - - sig += SPX_N * SPX_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); -} - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -void fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]) { - uint32_t indices[SPX_FORS_TREES]; - unsigned char roots[SPX_FORS_TREES * SPX_N]; - unsigned char leaf[SPX_N]; - uint32_t fors_tree_addr[8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - copy_keypair_addr(fors_tree_addr, fors_addr); - copy_keypair_addr(fors_pk_addr, fors_addr); - - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); - set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < SPX_FORS_TREES; i++) { - idx_offset = i * (1 << SPX_FORS_HEIGHT); - - set_tree_height(fors_tree_addr, 0); - set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Derive the leaf from the included secret key part. */ - fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); - sig += SPX_N; - - /* Derive the corresponding root node of this tree. */ - compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, - sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); - sig += SPX_N * SPX_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/fors.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/fors.h deleted file mode 100644 index 509140a178..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/fors.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef SPX_FORS_H -#define SPX_FORS_H - -#include - -#include "context.h" -#include "params.h" - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -#define fors_sign SPX_NAMESPACE(fors_sign) -void fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]); - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) -void fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/haraka.c deleted file mode 100644 index b414b691d7..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/haraka.c +++ /dev/null @@ -1,702 +0,0 @@ -/* -Plain C implementation of the Haraka256 and Haraka512 permutations. -*/ -#include -#include -#include -#include -#include - -#include "haraka.h" -#include "harakax4.h" -#include "utils.h" - -#define HARAKAS_RATE 32 - -#define u64 unsigned long -#define u128 __m128i - -#define LOAD(src) _mm_loadu_si128((u128 *)(src)) -#define STORE(dest,src) _mm_storeu_si128((u128 *)(dest),src) - -#define XOR128(a, b) _mm_xor_si128(a, b) - -#define AES2(s0, s1, rci) \ - s0 = _mm_aesenc_si128(s0, *(rci)); \ - (s1) = _mm_aesenc_si128(s1, *((rci) + 1)); \ - (s0) = _mm_aesenc_si128(s0, *((rci) + 2)); \ - (s1) = _mm_aesenc_si128(s1, *((rci) + 3)); - -#define AES2_4x(s0, s1, s2, s3, rci) \ - AES2((s0)[0], (s0)[1], rci); \ - AES2((s1)[0], (s1)[1], rci); \ - AES2((s2)[0], (s2)[1], rci); \ - AES2((s3)[0], (s3)[1], rci); - -#define AES4(s0, s1, s2, s3, rci) \ - s0 = _mm_aesenc_si128(s0, *(rci)); \ - (s1) = _mm_aesenc_si128(s1, *((rci) + 1)); \ - (s2) = _mm_aesenc_si128(s2, *((rci) + 2)); \ - (s3) = _mm_aesenc_si128(s3, *((rci) + 3)); \ - (s0) = _mm_aesenc_si128(s0, *((rci) + 4)); \ - (s1) = _mm_aesenc_si128(s1, *((rci) + 5)); \ - (s2) = _mm_aesenc_si128(s2, *((rci) + 6)); \ - (s3) = _mm_aesenc_si128(s3, *((rci) + 7)); - -#define AES4_4x(s0, s1, s2, s3, rci) \ - AES4((s0)[0], (s0)[1], (s0)[2], (s0)[3], rci); \ - AES4((s1)[0], (s1)[1], (s1)[2], (s1)[3], rci); \ - AES4((s2)[0], (s2)[1], (s2)[2], (s2)[3], rci); \ - AES4((s3)[0], (s3)[1], (s3)[2], (s3)[3], rci); - -#define MIX2(s0, s1) \ - tmp = _mm_unpacklo_epi32(s0, s1); \ - (s1) = _mm_unpackhi_epi32(s0, s1); \ - (s0) = tmp; - -#define MIX4(s0, s1, s2, s3) \ - tmp = _mm_unpacklo_epi32(s0, s1); \ - (s0) = _mm_unpackhi_epi32(s0, s1); \ - (s1) = _mm_unpacklo_epi32(s2, s3); \ - (s2) = _mm_unpackhi_epi32(s2, s3); \ - (s3) = _mm_unpacklo_epi32(s0, s2); \ - (s0) = _mm_unpackhi_epi32(s0, s2); \ - (s2) = _mm_unpackhi_epi32(s1, tmp); \ - (s1) = _mm_unpacklo_epi32(s1, tmp); - -#define TRUNCSTORE(out, s0, s1, s2, s3) \ - _mm_storeu_si128((u128 *)(out), \ - _mm_castpd_si128(_mm_shuffle_pd(_mm_castsi128_pd(s0), _mm_castsi128_pd(s1), 3))); \ - _mm_storeu_si128((u128 *)((out) + 16), \ - _mm_castpd_si128(_mm_shuffle_pd(_mm_castsi128_pd(s2), _mm_castsi128_pd(s3), 0))); - -static void load_haraka_constants(u128 *rc) { - rc[0] = _mm_set_epi32((int)0x0684704c, (int)0xe620c00a, (int)0xb2c5fef0, (int)0x75817b9d); - rc[1] = _mm_set_epi32((int)0x8b66b4e1, (int)0x88f3a06b, (int)0x640f6ba4, (int)0x2f08f717); - rc[2] = _mm_set_epi32((int)0x3402de2d, (int)0x53f28498, (int)0xcf029d60, (int)0x9f029114); - rc[3] = _mm_set_epi32((int)0x0ed6eae6, (int)0x2e7b4f08, (int)0xbbf3bcaf, (int)0xfd5b4f79); - rc[4] = _mm_set_epi32((int)0xcbcfb0cb, (int)0x4872448b, (int)0x79eecd1c, (int)0xbe397044); - rc[5] = _mm_set_epi32((int)0x7eeacdee, (int)0x6e9032b7, (int)0x8d5335ed, (int)0x2b8a057b); - rc[6] = _mm_set_epi32((int)0x67c28f43, (int)0x5e2e7cd0, (int)0xe2412761, (int)0xda4fef1b); - rc[7] = _mm_set_epi32((int)0x2924d9b0, (int)0xafcacc07, (int)0x675ffde2, (int)0x1fc70b3b); - rc[8] = _mm_set_epi32((int)0xab4d63f1, (int)0xe6867fe9, (int)0xecdb8fca, (int)0xb9d465ee); - rc[9] = _mm_set_epi32((int)0x1c30bf84, (int)0xd4b7cd64, (int)0x5b2a404f, (int)0xad037e33); - rc[10] = _mm_set_epi32((int)0xb2cc0bb9, (int)0x941723bf, (int)0x69028b2e, (int)0x8df69800); - rc[11] = _mm_set_epi32((int)0xfa0478a6, (int)0xde6f5572, (int)0x4aaa9ec8, (int)0x5c9d2d8a); - rc[12] = _mm_set_epi32((int)0xdfb49f2b, (int)0x6b772a12, (int)0x0efa4f2e, (int)0x29129fd4); - rc[13] = _mm_set_epi32((int)0x1ea10344, (int)0xf449a236, (int)0x32d611ae, (int)0xbb6a12ee); - rc[14] = _mm_set_epi32((int)0xaf044988, (int)0x4b050084, (int)0x5f9600c9, (int)0x9ca8eca6); - rc[15] = _mm_set_epi32((int)0x21025ed8, (int)0x9d199c4f, (int)0x78a2c7e3, (int)0x27e593ec); - rc[16] = _mm_set_epi32((int)0xbf3aaaf8, (int)0xa759c9b7, (int)0xb9282ecd, (int)0x82d40173); - rc[17] = _mm_set_epi32((int)0x6260700d, (int)0x6186b017, (int)0x37f2efd9, (int)0x10307d6b); - rc[18] = _mm_set_epi32((int)0x5aca45c2, (int)0x21300443, (int)0x81c29153, (int)0xf6fc9ac6); - rc[19] = _mm_set_epi32((int)0x9223973c, (int)0x226b68bb, (int)0x2caf92e8, (int)0x36d1943a); - rc[20] = _mm_set_epi32((int)0xd3bf9238, (int)0x225886eb, (int)0x6cbab958, (int)0xe51071b4); - rc[21] = _mm_set_epi32((int)0xdb863ce5, (int)0xaef0c677, (int)0x933dfddd, (int)0x24e1128d); - rc[22] = _mm_set_epi32((int)0xbb606268, (int)0xffeba09c, (int)0x83e48de3, (int)0xcb2212b1); - rc[23] = _mm_set_epi32((int)0x734bd3dc, (int)0xe2e4d19c, (int)0x2db91a4e, (int)0xc72bf77d); - rc[24] = _mm_set_epi32((int)0x43bb47c3, (int)0x61301b43, (int)0x4b1415c4, (int)0x2cb3924e); - rc[25] = _mm_set_epi32((int)0xdba775a8, (int)0xe707eff6, (int)0x03b231dd, (int)0x16eb6899); - rc[26] = _mm_set_epi32((int)0x6df3614b, (int)0x3c755977, (int)0x8e5e2302, (int)0x7eca472c); - rc[27] = _mm_set_epi32((int)0xcda75a17, (int)0xd6de7d77, (int)0x6d1be5b9, (int)0xb88617f9); - rc[28] = _mm_set_epi32((int)0xec6b43f0, (int)0x6ba8e9aa, (int)0x9d6c069d, (int)0xa946ee5d); - rc[29] = _mm_set_epi32((int)0xcb1e6950, (int)0xf957332b, (int)0xa2531159, (int)0x3bf327c1); - rc[30] = _mm_set_epi32((int)0x2cee0c75, (int)0x00da619c, (int)0xe4ed0353, (int)0x600ed0d9); - rc[31] = _mm_set_epi32((int)0xf0b1a5a1, (int)0x96e90cab, (int)0x80bbbabc, (int)0x63a4a350); - rc[32] = _mm_set_epi32((int)0xae3db102, (int)0x5e962988, (int)0xab0dde30, (int)0x938dca39); - rc[33] = _mm_set_epi32((int)0x17bb8f38, (int)0xd554a40b, (int)0x8814f3a8, (int)0x2e75b442); - rc[34] = _mm_set_epi32((int)0x34bb8a5b, (int)0x5f427fd7, (int)0xaeb6b779, (int)0x360a16f6); - rc[35] = _mm_set_epi32((int)0x26f65241, (int)0xcbe55438, (int)0x43ce5918, (int)0xffbaafde); - rc[36] = _mm_set_epi32((int)0x4ce99a54, (int)0xb9f3026a, (int)0xa2ca9cf7, (int)0x839ec978); - rc[37] = _mm_set_epi32((int)0xae51a51a, (int)0x1bdff7be, (int)0x40c06e28, (int)0x22901235); - rc[38] = _mm_set_epi32((int)0xa0c1613c, (int)0xba7ed22b, (int)0xc173bc0f, (int)0x48a659cf); - rc[39] = _mm_set_epi32((int)0x756acc03, (int)0x02288288, (int)0x4ad6bdfd, (int)0xe9c59da1); -} - -void tweak_constants(spx_ctx *ctx) { - int i; - unsigned char buf[40 * 16]; - - /* Use the standard constants to generate tweaked ones. */ - load_haraka_constants(ctx->rc); - - /* Constants for pk.seed */ - haraka_S(buf, 40 * 16, ctx->pub_seed, SPX_N, ctx); - - /* Tweak constants with the pub_seed */ - for (i = 0; i < 40; i++) { - ctx->rc[i] = LOAD(buf + i * 16); - } -} - -static void haraka_S_absorb(unsigned char *s, unsigned int r, - const unsigned char *m, unsigned long long mlen, - unsigned char p, const spx_ctx *ctx) { - unsigned long long i; - PQCLEAN_VLA(unsigned char, t, r); - - while (mlen >= r) { - // XOR block to state - STORE(s, XOR128(LOAD(s), LOAD(m))); - STORE(s + 16, XOR128(LOAD(s + 16), LOAD(m + 16))); - haraka512_perm(s, s, ctx); - 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; - STORE(s, XOR128(LOAD(s), LOAD(t))); - STORE(s + 16, XOR128(LOAD(s + 16), LOAD(t + 16))); -} - -static void haraka_S_absorb4x(unsigned char *s, - unsigned int r, - const unsigned char *m0, - const unsigned char *m1, - const unsigned char *m2, - const unsigned char *m3, - unsigned long long int mlen, - unsigned char p, - const spx_ctx *ctx) { - unsigned long long i; - PQCLEAN_VLA(unsigned char, t0, r); - PQCLEAN_VLA(unsigned char, t1, r); - PQCLEAN_VLA(unsigned char, t2, r); - PQCLEAN_VLA(unsigned char, t3, r); - - while (mlen >= r) { - // XOR block to state - STORE(s, XOR128(LOAD(s), LOAD(m0))); - STORE(s + 16, XOR128(LOAD(s + 16), LOAD(m0 + 16))); - STORE(s + 64, XOR128(LOAD(s + 64), LOAD(m1))); - STORE(s + 80, XOR128(LOAD(s + 80), LOAD(m1 + 16))); - STORE(s + 128, XOR128(LOAD(s + 128), LOAD(m2))); - STORE(s + 144, XOR128(LOAD(s + 144), LOAD(m2 + 16))); - STORE(s + 192, XOR128(LOAD(s + 192), LOAD(m3))); - STORE(s + 208, XOR128(LOAD(s + 208), LOAD(m3 + 16))); - - haraka512_perm_x4(s, s, ctx); - mlen -= r; - m0 += r; - m1 += r; - m2 += r; - m3 += r; - } - - for (i = 0; i < r; ++i) { - t0[i] = 0; - t1[i] = 0; - t2[i] = 0; - t3[i] = 0; - } - for (i = 0; i < mlen; ++i) { - t0[i] = m0[i]; - t1[i] = m1[i]; - t2[i] = m2[i]; - t3[i] = m3[i]; - } - - t0[i] = p; - t1[i] = p; - t2[i] = p; - t3[i] = p; - - t0[r - 1] |= 128; - t1[r - 1] |= 128; - t2[r - 1] |= 128; - t3[r - 1] |= 128; - - STORE(s, XOR128(LOAD(s), LOAD(t0))); - STORE(s + 16, XOR128(LOAD(s + 16), LOAD(t0 + 16))); - STORE(s + 64, XOR128(LOAD(s + 64), LOAD(t1))); - STORE(s + 80, XOR128(LOAD(s + 80), LOAD(t1 + 16))); - STORE(s + 128, XOR128(LOAD(s + 128), LOAD(t2))); - STORE(s + 144, XOR128(LOAD(s + 144), LOAD(t2 + 16))); - STORE(s + 192, XOR128(LOAD(s + 192), LOAD(t3))); - STORE(s + 208, XOR128(LOAD(s + 208), LOAD(t3 + 16))); -} - -static void haraka_S_squeezeblocks(unsigned char *h, unsigned long long nblocks, - unsigned char *s, unsigned int r, - const spx_ctx *ctx) { - while (nblocks > 0) { - haraka512_perm(s, s, ctx); - STORE(h, LOAD(s)); - STORE(h + 16, LOAD(s + 16)); - h += r; - nblocks--; - } -} - -static void haraka_S_squeezeblocks4x(unsigned char *h0, - unsigned char *h1, - unsigned char *h2, - unsigned char *h3, - unsigned long long nblocks, - unsigned char *s, - unsigned int r, - const spx_ctx *ctx) { - while (nblocks > 0) { - haraka512_perm_x4(s, s, ctx); - STORE(h0, LOAD(s)); - STORE(h0 + 16, LOAD(s + 16)); - STORE(h1, LOAD(s + 64)); - STORE(h1 + 16, LOAD(s + 80)); - STORE(h2, LOAD(s + 128)); - STORE(h2 + 16, LOAD(s + 144)); - STORE(h3, LOAD(s + 192)); - STORE(h3 + 16, LOAD(s + 208)); - h0 += r; - h1 += r; - h2 += r; - h3 += r; - nblocks--; - } -} - -void haraka_S_inc_init(uint8_t *s_inc) { - size_t i; - - for (i = 0; i < 64; i++) { - s_inc[i] = 0; - } - s_inc[64] = 0; -} - -void haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, - const spx_ctx *ctx) { - size_t i; - - /* Recall that s_inc[64] is the non-absorbed bytes xored into the state */ - while (mlen + s_inc[64] >= HARAKAS_RATE) { - for (i = 0; i < (size_t)(HARAKAS_RATE - s_inc[64]); i++) { - /* Take the i'th byte from message - xor with the s_inc[64] + i'th byte of the state */ - s_inc[s_inc[64] + i] ^= m[i]; - } - mlen -= (size_t)(HARAKAS_RATE - s_inc[64]); - m += HARAKAS_RATE - s_inc[64]; - s_inc[64] = 0; - - haraka512_perm(s_inc, s_inc, ctx); - } - - for (i = 0; i < mlen; i++) { - s_inc[s_inc[64] + i] ^= m[i]; - } - s_inc[64] += (uint8_t)mlen; -} - -void haraka_S_inc_finalize(uint8_t *s_inc) { - /* After haraka_S_inc_absorb, we are guaranteed that s_inc[64] < HARAKAS_RATE, - so we can always use one more byte for p in the current state. */ - s_inc[s_inc[64]] ^= 0x1F; - s_inc[HARAKAS_RATE - 1] ^= 128; - s_inc[64] = 0; -} - -void haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, - const spx_ctx *ctx) { - size_t i; - - /* First consume any bytes we still have sitting around */ - for (i = 0; i < outlen && i < s_inc[64]; i++) { - /* There are s_inc[64] bytes left, so r - s_inc[64] is the first - available byte. We consume from there, i.e., up to r. */ - out[i] = (uint8_t)s_inc[(HARAKAS_RATE - s_inc[64] + i)]; - } - out += i; - outlen -= i; - s_inc[64] -= (uint8_t)i; - - /* Then squeeze the remaining necessary blocks */ - while (outlen > 0) { - haraka512_perm(s_inc, s_inc, ctx); - - for (i = 0; i < outlen && i < HARAKAS_RATE; i++) { - out[i] = s_inc[i]; - } - out += i; - outlen -= i; - s_inc[64] = (uint8_t)(HARAKAS_RATE - i); - } -} - -void haraka_S(unsigned char *out, unsigned long long outlen, - const unsigned char *in, unsigned long long inlen, - const spx_ctx *ctx) { - unsigned long long i; - unsigned char s[64]; - unsigned char d[32]; - - for (i = 0; i < 64; i++) { - s[i] = 0; - } - haraka_S_absorb(s, HARAKAS_RATE, in, inlen, 0x1F, ctx); - - haraka_S_squeezeblocks(out, outlen / HARAKAS_RATE, s, HARAKAS_RATE, ctx); - out += (outlen / HARAKAS_RATE) * HARAKAS_RATE; - - if (outlen % HARAKAS_RATE) { - haraka_S_squeezeblocks(d, 1, s, HARAKAS_RATE, ctx); - for (i = 0; i < outlen % HARAKAS_RATE; i++) { - out[i] = d[i]; - } - } -} - -void haraka_Sx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned long long outlen, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - unsigned long long inlen, - const spx_ctx *ctx) { - unsigned long long i; - unsigned char s[64 * 4]; - unsigned char d0[32]; - unsigned char d1[32]; - unsigned char d2[32]; - unsigned char d3[32]; - - for (i = 0; i < 64 * 4; i++) { - s[i] = 0; - } - haraka_S_absorb4x(s, HARAKAS_RATE, in0, in1, in2, in3, inlen, 0x1F, ctx); - - haraka_S_squeezeblocks4x(out0, out1, out2, out3, outlen / HARAKAS_RATE, s, - HARAKAS_RATE, ctx); - out0 += (outlen / HARAKAS_RATE) * HARAKAS_RATE; - out1 += (outlen / HARAKAS_RATE) * HARAKAS_RATE; - out2 += (outlen / HARAKAS_RATE) * HARAKAS_RATE; - out3 += (outlen / HARAKAS_RATE) * HARAKAS_RATE; - - if (outlen % HARAKAS_RATE) { - haraka_S_squeezeblocks4x(d0, d1, d2, d3, 1, s, HARAKAS_RATE, ctx); - for (i = 0; i < outlen % HARAKAS_RATE; i++) { - out0[i] = d0[i]; - out1[i] = d1[i]; - out2[i] = d2[i]; - out3[i] = d3[i]; - } - } -} - -void haraka512_perm(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx) { - u128 s[4], tmp; - - s[0] = LOAD(in); - s[1] = LOAD(in + 16); - s[2] = LOAD(in + 32); - s[3] = LOAD(in + 48); - - AES4(s[0], s[1], s[2], s[3], ctx->rc); - MIX4(s[0], s[1], s[2], s[3]); - - AES4(s[0], s[1], s[2], s[3], ctx->rc + 8); - MIX4(s[0], s[1], s[2], s[3]); - - AES4(s[0], s[1], s[2], s[3], ctx->rc + 16); - MIX4(s[0], s[1], s[2], s[3]); - - AES4(s[0], s[1], s[2], s[3], ctx->rc + 24); - MIX4(s[0], s[1], s[2], s[3]); - - AES4(s[0], s[1], s[2], s[3], ctx->rc + 32); - MIX4(s[0], s[1], s[2], s[3]); - - STORE(out, s[0]); - STORE(out + 16, s[1]); - STORE(out + 32, s[2]); - STORE(out + 48, s[3]); -} - -void haraka512_perm_x4(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx) { - u128 s[4][4], tmp; - - s[0][0] = LOAD(in); - s[0][1] = LOAD(in + 16); - s[0][2] = LOAD(in + 32); - s[0][3] = LOAD(in + 48); - s[1][0] = LOAD(in + 64); - s[1][1] = LOAD(in + 80); - s[1][2] = LOAD(in + 96); - s[1][3] = LOAD(in + 112); - s[2][0] = LOAD(in + 128); - s[2][1] = LOAD(in + 144); - s[2][2] = LOAD(in + 160); - s[2][3] = LOAD(in + 176); - s[3][0] = LOAD(in + 192); - s[3][1] = LOAD(in + 208); - s[3][2] = LOAD(in + 224); - s[3][3] = LOAD(in + 240); - - AES4_4x(s[0], s[1], s[2], s[3], ctx->rc); - MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); - MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); - MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); - MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - - AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 8); - MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); - MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); - MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); - MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - - AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 16); - MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); - MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); - MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); - MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - - AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 24); - MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); - MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); - MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); - MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - - AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 32); - MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); - MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); - MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); - MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - - STORE(out, s[0][0]); - STORE(out + 16, s[0][1]); - STORE(out + 32, s[0][2]); - STORE(out + 48, s[0][3]); - STORE(out + 64, s[1][0]); - STORE(out + 80, s[1][1]); - STORE(out + 96, s[1][2]); - STORE(out + 112, s[1][3]); - STORE(out + 128, s[2][0]); - STORE(out + 144, s[2][1]); - STORE(out + 160, s[2][2]); - STORE(out + 176, s[2][3]); - STORE(out + 192, s[3][0]); - STORE(out + 208, s[3][1]); - STORE(out + 224, s[3][2]); - STORE(out + 240, s[3][3]); -} - -void haraka512(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx) { - u128 s[4], tmp; - - s[0] = LOAD(in); - s[1] = LOAD(in + 16); - s[2] = LOAD(in + 32); - s[3] = LOAD(in + 48); - - AES4(s[0], s[1], s[2], s[3], ctx->rc); - MIX4(s[0], s[1], s[2], s[3]); - - AES4(s[0], s[1], s[2], s[3], ctx->rc + 8); - MIX4(s[0], s[1], s[2], s[3]); - - AES4(s[0], s[1], s[2], s[3], ctx->rc + 16); - MIX4(s[0], s[1], s[2], s[3]); - - AES4(s[0], s[1], s[2], s[3], ctx->rc + 24); - MIX4(s[0], s[1], s[2], s[3]); - - AES4(s[0], s[1], s[2], s[3], ctx->rc + 32); - MIX4(s[0], s[1], s[2], s[3]); - - s[0] = XOR128(s[0], LOAD(in)); - s[1] = XOR128(s[1], LOAD(in + 16)); - s[2] = XOR128(s[2], LOAD(in + 32)); - s[3] = XOR128(s[3], LOAD(in + 48)); - - // truncate and store result - TRUNCSTORE(out, s[0], s[1], s[2], s[3]); -} - -void haraka512x4(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx) { - u128 s[4][4], tmp; - - s[0][0] = LOAD(in); - s[0][1] = LOAD(in + 16); - s[0][2] = LOAD(in + 32); - s[0][3] = LOAD(in + 48); - s[1][0] = LOAD(in + 64); - s[1][1] = LOAD(in + 80); - s[1][2] = LOAD(in + 96); - s[1][3] = LOAD(in + 112); - s[2][0] = LOAD(in + 128); - s[2][1] = LOAD(in + 144); - s[2][2] = LOAD(in + 160); - s[2][3] = LOAD(in + 176); - s[3][0] = LOAD(in + 192); - s[3][1] = LOAD(in + 208); - s[3][2] = LOAD(in + 224); - s[3][3] = LOAD(in + 240); - - AES4_4x(s[0], s[1], s[2], s[3], ctx->rc); - MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); - MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); - MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); - MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - - AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 8); - MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); - MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); - MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); - MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - - AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 16); - MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); - MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); - MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); - MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - - AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 24); - MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); - MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); - MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); - MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - - AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 32); - MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); - MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); - MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); - MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - - s[0][0] = XOR128(s[0][0], LOAD(in)); - s[0][1] = XOR128(s[0][1], LOAD(in + 16)); - s[0][2] = XOR128(s[0][2], LOAD(in + 32)); - s[0][3] = XOR128(s[0][3], LOAD(in + 48)); - s[1][0] = XOR128(s[1][0], LOAD(in + 64)); - s[1][1] = XOR128(s[1][1], LOAD(in + 80)); - s[1][2] = XOR128(s[1][2], LOAD(in + 96)); - s[1][3] = XOR128(s[1][3], LOAD(in + 112)); - s[2][0] = XOR128(s[2][0], LOAD(in + 128)); - s[2][1] = XOR128(s[2][1], LOAD(in + 144)); - s[2][2] = XOR128(s[2][2], LOAD(in + 160)); - s[2][3] = XOR128(s[2][3], LOAD(in + 176)); - s[3][0] = XOR128(s[3][0], LOAD(in + 192)); - s[3][1] = XOR128(s[3][1], LOAD(in + 208)); - s[3][2] = XOR128(s[3][2], LOAD(in + 224)); - s[3][3] = XOR128(s[3][3], LOAD(in + 240)); - - TRUNCSTORE(out, s[0][0], s[0][1], s[0][2], s[0][3]); - TRUNCSTORE((out + 32), s[1][0], s[1][1], s[1][2], s[1][3]); - TRUNCSTORE((out + 64), s[2][0], s[2][1], s[2][2], s[2][3]); - TRUNCSTORE((out + 96), s[3][0], s[3][1], s[3][2], s[3][3]); -} - -void haraka256(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx) { - u128 s[2], tmp; - - s[0] = LOAD(in); - s[1] = LOAD(in + 16); - - AES2(s[0], s[1], ctx->rc); - MIX2(s[0], s[1]); - - AES2(s[0], s[1], ctx->rc + 4); - MIX2(s[0], s[1]); - - AES2(s[0], s[1], ctx->rc + 8); - MIX2(s[0], s[1]); - - AES2(s[0], s[1], ctx->rc + 12); - MIX2(s[0], s[1]); - - AES2(s[0], s[1], ctx->rc + 16); - MIX2(s[0], s[1]); - - s[0] = XOR128(s[0], LOAD(in)); - s[1] = XOR128(s[1], LOAD(in + 16)); - - STORE(out, s[0]); - STORE(out + 16, s[1]); -} - -void haraka256x4(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx) { - u128 s[4][2], tmp; - - s[0][0] = LOAD(in); - s[0][1] = LOAD(in + 16); - s[1][0] = LOAD(in + 32); - s[1][1] = LOAD(in + 48); - s[2][0] = LOAD(in + 64); - s[2][1] = LOAD(in + 80); - s[3][0] = LOAD(in + 96); - s[3][1] = LOAD(in + 112); - - // Round 1 - AES2_4x(s[0], s[1], s[2], s[3], ctx->rc); - - MIX2(s[0][0], s[0][1]); - MIX2(s[1][0], s[1][1]); - MIX2(s[2][0], s[2][1]); - MIX2(s[3][0], s[3][1]); - - // Round 2 - AES2_4x(s[0], s[1], s[2], s[3], ctx->rc + 4); - - MIX2(s[0][0], s[0][1]); - MIX2(s[1][0], s[1][1]); - MIX2(s[2][0], s[2][1]); - MIX2(s[3][0], s[3][1]); - - // Round 3 - AES2_4x(s[0], s[1], s[2], s[3], ctx->rc + 8); - - MIX2(s[0][0], s[0][1]); - MIX2(s[1][0], s[1][1]); - MIX2(s[2][0], s[2][1]); - MIX2(s[3][0], s[3][1]); - - // Round 4 - AES2_4x(s[0], s[1], s[2], s[3], ctx->rc + 12); - - MIX2(s[0][0], s[0][1]); - MIX2(s[1][0], s[1][1]); - MIX2(s[2][0], s[2][1]); - MIX2(s[3][0], s[3][1]); - - // Round 5 - AES2_4x(s[0], s[1], s[2], s[3], ctx->rc + 16); - - MIX2(s[0][0], s[0][1]); - MIX2(s[1][0], s[1][1]); - MIX2(s[2][0], s[2][1]); - MIX2(s[3][0], s[3][1]); - - // Feed Forward - s[0][0] = _mm_xor_si128(s[0][0], LOAD(in)); - s[0][1] = _mm_xor_si128(s[0][1], LOAD(in + 16)); - s[1][0] = _mm_xor_si128(s[1][0], LOAD(in + 32)); - s[1][1] = _mm_xor_si128(s[1][1], LOAD(in + 48)); - s[2][0] = _mm_xor_si128(s[2][0], LOAD(in + 64)); - s[2][1] = _mm_xor_si128(s[2][1], LOAD(in + 80)); - s[3][0] = _mm_xor_si128(s[3][0], LOAD(in + 96)); - s[3][1] = _mm_xor_si128(s[3][1], LOAD(in + 112)); - - STORE(out, s[0][0]); - STORE(out + 16, s[0][1]); - STORE(out + 32, s[1][0]); - STORE(out + 48, s[1][1]); - STORE(out + 64, s[2][0]); - STORE(out + 80, s[2][1]); - STORE(out + 96, s[3][0]); - STORE(out + 112, s[3][1]); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/haraka.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/haraka.h deleted file mode 100644 index 737cb6065f..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/haraka.h +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef SPX_HARAKA_H -#define SPX_HARAKA_H - -#include "context.h" -#include "params.h" - -/* Tweak constants with seed */ -#define tweak_constants SPX_NAMESPACE(tweak_constants) -void tweak_constants(spx_ctx *ctx); - -/* Haraka Sponge */ -#define haraka_S_inc_init SPX_NAMESPACE(haraka_S_inc_init) -void haraka_S_inc_init(uint8_t *s_inc); -#define haraka_S_inc_absorb SPX_NAMESPACE(haraka_S_inc_absorb) -void haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, - const spx_ctx *ctx); -#define haraka_S_inc_finalize SPX_NAMESPACE(haraka_S_inc_finalize) -void haraka_S_inc_finalize(uint8_t *s_inc); -#define haraka_S_inc_squeeze SPX_NAMESPACE(haraka_S_inc_squeeze) -void haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, - const spx_ctx *ctx); -#define haraka_S SPX_NAMESPACE(haraka_S) -void haraka_S(unsigned char *out, unsigned long long outlen, - const unsigned char *in, unsigned long long inlen, - const spx_ctx *ctx); - -/* Applies the 512-bit Haraka permutation to in. */ -#define haraka512_perm SPX_NAMESPACE(haraka512_perm) -void haraka512_perm(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx); - -/* Implementation of Haraka-512 */ -#define haraka512 SPX_NAMESPACE(haraka512) -void haraka512(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx); - -/* Implementation of Haraka-256 */ -#define haraka256 SPX_NAMESPACE(haraka256) -void haraka256(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/haraka_offsets.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/haraka_offsets.h deleted file mode 100644 index 7c062272a0..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/haraka_offsets.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef HARAKA_OFFSETS_H_ -#define HARAKA_OFFSETS_H_ - -/* - * Offsets of various fields in the address structure when we use Haraka as - * the Sphincs+ hash function - */ - -#define SPX_OFFSET_LAYER 3 /* The byte used to specify the Merkle tree layer */ -#define SPX_OFFSET_TREE 8 /* The start of the 8 byte field used to specify the tree */ -#define SPX_OFFSET_TYPE 19 /* The byte used to specify the hash type (reason) */ -#define SPX_OFFSET_KP_ADDR2 22 /* The high byte used to specify the key pair (which one-time signature) */ -#define SPX_OFFSET_KP_ADDR1 23 /* The low byte used to specify the key pair */ -#define SPX_OFFSET_CHAIN_ADDR 27 /* The byte used to specify the chain address (which Winternitz chain) */ -#define SPX_OFFSET_HASH_ADDR 31 /* The byte used to specify the hash address (where in the Winternitz chain) */ -#define SPX_OFFSET_TREE_HGT 27 /* The byte used to specify the height of this node in the FORS or Merkle tree */ -#define SPX_OFFSET_TREE_INDEX 28 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ - -#define SPX_HARAKA 1 - -#endif /* HARAKA_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/harakax4.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/harakax4.h deleted file mode 100644 index eadc69aa48..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/harakax4.h +++ /dev/null @@ -1,36 +0,0 @@ -#ifndef SPX_HARAKAX4_H -#define SPX_HARAKAX4_H - -#include "context.h" -#include "params.h" - -/* Haraka Sponge */ -#define haraka_Sx4 SPX_NAMESPACE(haraka_Sx4) -void haraka_Sx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned long long outlen, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - unsigned long long inlen, - const spx_ctx *ctx); - -/* Applies the 512-bit Haraka permutation x4 to in. */ -#define haraka512_perm_x4 SPX_NAMESPACE(haraka512_perm_x4) -void haraka512_perm_x4(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx); - -/* Implementation of Haraka-512 x4*/ -#define haraka512x4 SPX_NAMESPACE(haraka512x4) -void haraka512x4(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx); - -/* Implementation of Haraka-256 x4 */ -#define haraka256x4 SPX_NAMESPACE(haraka256x4) -void haraka256x4(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/hash.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/hash.h deleted file mode 100644 index f7c87d4c3c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/hash.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef SPX_HASH_H -#define SPX_HASH_H - -#include -#include - -#include "context.h" -#include "params.h" - -#define prf_addr SPX_NAMESPACE(prf_addr) -void prf_addr(unsigned char *out, const spx_ctx *ctx, - const uint32_t addr[8]); - -#define gen_message_random SPX_NAMESPACE(gen_message_random) -void gen_message_random(unsigned char *R, const unsigned char *sk_prf, - const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx); - -#define hash_message SPX_NAMESPACE(hash_message) -void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx); - - - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/hash_haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/hash_haraka.c deleted file mode 100644 index 750a67423b..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/hash_haraka.c +++ /dev/null @@ -1,81 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "utils.h" - -#include "haraka.h" -#include "hash.h" - -/* - * Computes PRF(key, addr), given a secret key of SPX_N bytes and an address - */ -void prf_addr(unsigned char *out, const spx_ctx *ctx, - const uint32_t addr[8]) { - /* Since SPX_N may be smaller than 32, we need temporary buffers. */ - unsigned char outbuf[32]; - unsigned char buf[64] = {0}; - - memcpy(buf, addr, SPX_ADDR_BYTES); - memcpy(buf + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); - - haraka512(outbuf, (const void *)buf, ctx); - memcpy(out, outbuf, SPX_N); -} - -/** - * Computes the message-dependent randomness R, using a secret seed and an - * optional randomization value as well as the message. - */ -void gen_message_random(unsigned char *R, const unsigned char *sk_prf, - const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx) { - uint8_t s_inc[65]; - - haraka_S_inc_init(s_inc); - haraka_S_inc_absorb(s_inc, sk_prf, SPX_N, ctx); - haraka_S_inc_absorb(s_inc, optrand, SPX_N, ctx); - haraka_S_inc_absorb(s_inc, m, mlen, ctx); - haraka_S_inc_finalize(s_inc); - haraka_S_inc_squeeze(R, SPX_N, s_inc, ctx); -} - -/** - * Computes the message hash using R, the public key, and the message. - * Outputs the message digest and the index of the leaf. The index is split in - * the tree index and the leaf index, for convenient copying to an address. - */ -void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx) { -#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) -#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) -#define SPX_LEAF_BITS SPX_TREE_HEIGHT -#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) -#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) - - unsigned char buf[SPX_DGST_BYTES]; - unsigned char *bufp = buf; - uint8_t s_inc[65]; - - haraka_S_inc_init(s_inc); - haraka_S_inc_absorb(s_inc, R, SPX_N, ctx); - haraka_S_inc_absorb(s_inc, pk + SPX_N, SPX_N, ctx); // Only absorb root part of pk - haraka_S_inc_absorb(s_inc, m, mlen, ctx); - haraka_S_inc_finalize(s_inc); - haraka_S_inc_squeeze(buf, SPX_DGST_BYTES, s_inc, ctx); - - memcpy(digest, bufp, SPX_FORS_MSG_BYTES); - bufp += SPX_FORS_MSG_BYTES; - - - *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); - *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); - bufp += SPX_TREE_BYTES; - - *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); - *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/hash_harakax4.c b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/hash_harakax4.c deleted file mode 100644 index cfa5162d79..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/hash_harakax4.c +++ /dev/null @@ -1,35 +0,0 @@ -#include -#include - -#include "address.h" -#include "harakax4.h" -#include "hashx4.h" -#include "params.h" - -/* - * 4-way parallel version of prf_addr; takes 4x as much input and output - */ -#define prf_addrx4 SPX_NAMESPACE(prf_addrx4) -void prf_addrx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const spx_ctx *ctx, - const uint32_t addrx4[4 * 8]) { - unsigned char bufx4[4 * 64] = {0}; - /* Since SPX_N may be smaller than 32, we need temporary buffers. */ - unsigned char outbuf[4 * 32]; - unsigned int i; - - for (i = 0; i < 4; i++) { - memcpy(bufx4 + i * 64, addrx4 + i * 8, SPX_ADDR_BYTES); - memcpy(bufx4 + i * 64 + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); - } - - haraka512x4(outbuf, bufx4, ctx); - - memcpy(out0, outbuf, SPX_N); - memcpy(out1, outbuf + 32, SPX_N); - memcpy(out2, outbuf + 64, SPX_N); - memcpy(out3, outbuf + 96, SPX_N); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/hashx4.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/hashx4.h deleted file mode 100644 index 3751a0ebd0..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/hashx4.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef SPX_HASHX4_H -#define SPX_HASHX4_H - -#include - -#include "context.h" -#include "params.h" - -#define prf_addrx4 SPX_NAMESPACE(prf_addrx4) -void prf_addrx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const spx_ctx *ctx, - const uint32_t addrx4[4 * 8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/merkle.c b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/merkle.c deleted file mode 100644 index f57811c1ac..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/merkle.c +++ /dev/null @@ -1,64 +0,0 @@ -#include -#include - -#include "merkle.h" - -#include "address.h" -#include "params.h" -#include "utils.h" -#include "utilsx4.h" -#include "wots.h" -#include "wotsx4.h" - -/* - * This generates a Merkle signature (WOTS signature followed by the Merkle - * authentication path). - */ -void merkle_sign(uint8_t *sig, unsigned char *root, - const spx_ctx *ctx, - uint32_t wots_addr[8], uint32_t tree_addr[8], - uint32_t idx_leaf) { - unsigned char *auth_path = sig + SPX_WOTS_BYTES; - uint32_t tree_addrx4[4 * 8] = { 0 }; - int j; - struct leaf_info_x4 info = { 0 }; - unsigned steps[ SPX_WOTS_LEN ]; - - info.wots_sig = sig; - chain_lengths(steps, root); - info.wots_steps = steps; - - for (j = 0; j < 4; j++) { - set_type(&tree_addrx4[8 * j], SPX_ADDR_TYPE_HASHTREE); - set_type(&info.leaf_addr[8 * j], SPX_ADDR_TYPE_WOTS); - set_type(&info.pk_addr[8 * j], SPX_ADDR_TYPE_WOTSPK); - copy_subtree_addr(&tree_addrx4[8 * j], tree_addr); - copy_subtree_addr(&info.leaf_addr[8 * j], wots_addr); - copy_subtree_addr(&info.pk_addr[8 * j], wots_addr); - } - - info.wots_sign_leaf = idx_leaf; - - treehashx4(root, auth_path, ctx, - idx_leaf, 0, - SPX_TREE_HEIGHT, - wots_gen_leafx4, - tree_addrx4, &info); -} - -/* Compute root node of the top-most subtree. */ -void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { - /* We do not need the auth path in key generation, but it simplifies the - code to have just one treehash routine that computes both root and path - in one function. */ - unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; - uint32_t top_tree_addr[8] = {0}; - uint32_t wots_addr[8] = {0}; - - set_layer_addr(top_tree_addr, SPX_D - 1); - set_layer_addr(wots_addr, SPX_D - 1); - - merkle_sign(auth_path, root, ctx, - wots_addr, top_tree_addr, - ~0U /* ~0 means "don't bother generating an auth path */ ); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/merkle.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/merkle.h deleted file mode 100644 index 769cf2e970..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/merkle.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef MERKLE_H_ -#define MERKLE_H_ - -#include - -#include "context.h" -#include "params.h" - -/* Generate a Merkle signature (WOTS signature followed by the Merkle */ -/* authentication path) */ -#define merkle_sign SPX_NAMESPACE(merkle_sign) -void merkle_sign(uint8_t *sig, unsigned char *root, - const spx_ctx *ctx, - uint32_t wots_addr[8], uint32_t tree_addr[8], - uint32_t idx_leaf); - -/* Compute the root node of the top-most subtree. */ -#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) -void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); - -#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/nistapi.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/nistapi.h deleted file mode 100644 index 3cb71afad4..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/nistapi.h +++ /dev/null @@ -1,87 +0,0 @@ -#ifndef SPX_API_H -#define SPX_API_H - -#include -#include - -#include "params.h" - -#define CRYPTO_ALGNAME "SPHINCS+" - -#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES -#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES -#define CRYPTO_BYTES SPX_BYTES -#define CRYPTO_SEEDBYTES (3*SPX_N) - -/* - * Returns the length of a secret key, in bytes - */ -#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) -size_t crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) -size_t crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) -size_t crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) -size_t crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) -int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) -int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) -int crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) -int crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -#define crypto_sign SPX_NAMESPACE(crypto_sign) -int crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) -int crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/params.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/params.h deleted file mode 100644 index b8ad803e37..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/params.h +++ /dev/null @@ -1,56 +0,0 @@ -#ifndef SPX_PARAMS_H -#define SPX_PARAMS_H - -#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_##s - -/* Hash output length in bytes. */ -#define SPX_N 24 -/* Height of the hypertree. */ -#define SPX_FULL_HEIGHT 63 -/* Number of subtree layer. */ -#define SPX_D 7 -/* FORS tree dimensions. */ -#define SPX_FORS_HEIGHT 14 -#define SPX_FORS_TREES 17 -/* Winternitz parameter, */ -#define SPX_WOTS_W 16 - -/* The hash function is defined by linking a different hash.c file, as opposed - to setting a #define constant. */ - -/* For clarity */ -#define SPX_ADDR_BYTES 32 - -/* WOTS parameters. */ -#define SPX_WOTS_LOGW 4 - -#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) - -/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#define SPX_WOTS_LEN2 3 - -#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) -#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) -#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES - -/* Subtree size. */ -#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) - -//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT -// #error SPX_D should always divide SPX_FULL_HEIGHT -//#endif - -/* FORS parameters. */ -#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) -#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) -#define SPX_FORS_PK_BYTES SPX_N - -/* Resulting SPX sizes. */ -#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ - SPX_FULL_HEIGHT * SPX_N) -#define SPX_PK_BYTES (2 * SPX_N) -#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) - -#include "haraka_offsets.h" - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/sign.c b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/sign.c deleted file mode 100644 index 9d0c7d1b22..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/sign.c +++ /dev/null @@ -1,286 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "context.h" -#include "fors.h" -#include "hash.h" -#include "merkle.h" -#include "nistapi.h" -#include "params.h" -#include "randombytes.h" -#include "thash.h" -#include "utils.h" -#include "wots.h" - -/* - * Returns the length of a secret key, in bytes - */ -size_t crypto_sign_secretkeybytes(void) { - return CRYPTO_SECRETKEYBYTES; -} - -/* - * Returns the length of a public key, in bytes - */ -size_t crypto_sign_publickeybytes(void) { - return CRYPTO_PUBLICKEYBYTES; -} - -/* - * Returns the length of a signature, in bytes - */ -size_t crypto_sign_bytes(void) { - return CRYPTO_BYTES; -} - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t crypto_sign_seedbytes(void) { - return CRYPTO_SEEDBYTES; -} - -/* - * Generates an SPX key pair given a seed of length - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed) { - spx_ctx ctx; - - /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ - memcpy(sk, seed, CRYPTO_SEEDBYTES); - - memcpy(pk, sk + 2 * SPX_N, SPX_N); - - memcpy(ctx.pub_seed, pk, SPX_N); - memcpy(ctx.sk_seed, sk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - /* Compute root node of the top-most subtree. */ - merkle_gen_root(sk + 3 * SPX_N, &ctx); - - // cleanup - free_hash_function(&ctx); - - memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); - - return 0; -} - -/* - * Generates an SPX key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { - uint8_t seed[CRYPTO_SEEDBYTES]; - randombytes(seed, CRYPTO_SEEDBYTES); - crypto_sign_seed_keypair(pk, sk, seed); - - return 0; -} - -/** - * Returns an array containing a detached signature. - */ -int crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - spx_ctx ctx; - - const uint8_t *sk_prf = sk + SPX_N; - const uint8_t *pk = sk + 2 * SPX_N; - - uint8_t optrand[SPX_N]; - uint8_t mhash[SPX_FORS_MSG_BYTES]; - uint8_t root[SPX_N]; - uint32_t i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - - memcpy(ctx.sk_seed, sk, SPX_N); - memcpy(ctx.pub_seed, pk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - set_type(wots_addr, SPX_ADDR_TYPE_WOTS); - set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); - - /* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ - randombytes(optrand, SPX_N); - /* Compute the digest randomization value. */ - gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); - - /* Derive the message digest and leaf index from R, PK and M. */ - hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); - sig += SPX_N; - - set_tree_addr(wots_addr, tree); - set_keypair_addr(wots_addr, idx_leaf); - - /* Sign the message hash using FORS. */ - fors_sign(sig, root, mhash, &ctx, wots_addr); - sig += SPX_FORS_BYTES; - - for (i = 0; i < SPX_D; i++) { - set_layer_addr(tree_addr, i); - set_tree_addr(tree_addr, tree); - - copy_subtree_addr(wots_addr, tree_addr); - set_keypair_addr(wots_addr, idx_leaf); - - merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); - sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); - tree = tree >> SPX_TREE_HEIGHT; - } - - free_hash_function(&ctx); - - *siglen = SPX_BYTES; - - return 0; -} - -/** - * Verifies a detached signature and message under a given public key. - */ -int crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk) { - spx_ctx ctx; - const uint8_t *pub_root = pk + SPX_N; - uint8_t mhash[SPX_FORS_MSG_BYTES]; - uint8_t wots_pk[SPX_WOTS_BYTES]; - uint8_t root[SPX_N]; - uint8_t leaf[SPX_N]; - unsigned int i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - if (siglen != SPX_BYTES) { - return -1; - } - - memcpy(ctx.pub_seed, pk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - set_type(wots_addr, SPX_ADDR_TYPE_WOTS); - set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); - set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); - - /* Derive the message digest and leaf index from R || PK || M. */ - /* The additional SPX_N is a result of the hash domain separator. */ - hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); - sig += SPX_N; - - /* Layer correctly defaults to 0, so no need to set_layer_addr */ - set_tree_addr(wots_addr, tree); - set_keypair_addr(wots_addr, idx_leaf); - - fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); - sig += SPX_FORS_BYTES; - - /* For each subtree.. */ - for (i = 0; i < SPX_D; i++) { - set_layer_addr(tree_addr, i); - set_tree_addr(tree_addr, tree); - - copy_subtree_addr(wots_addr, tree_addr); - set_keypair_addr(wots_addr, idx_leaf); - - copy_keypair_addr(wots_pk_addr, wots_addr); - - /* The WOTS public key is only correct if the signature was correct. */ - /* Initially, root is the FORS pk, but on subsequent iterations it is - the root of the subtree below the currently processed subtree. */ - wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); - sig += SPX_WOTS_BYTES; - - /* Compute the leaf node using the WOTS public key. */ - thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); - - /* Compute the root node of this subtree. */ - compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, - &ctx, tree_addr); - sig += SPX_TREE_HEIGHT * SPX_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); - tree = tree >> SPX_TREE_HEIGHT; - } - - // cleanup - free_hash_function(&ctx); - - /* Check if the root node equals the root node in the public key. */ - if (memcmp(root, pub_root, SPX_N) != 0) { - return -1; - } - - return 0; -} - - -/** - * Returns an array containing the signature followed by the message. - */ -int crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk) { - size_t siglen; - - crypto_sign_signature(sm, &siglen, m, mlen, sk); - - memmove(sm + SPX_BYTES, m, mlen); - *smlen = siglen + mlen; - - return 0; -} - -/** - * Verifies a given signature-message pair under a given public key. - */ -int crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk) { - /* The API caller does not necessarily know what size a signature should be - but SPHINCS+ signatures are always exactly SPX_BYTES. */ - if (smlen < SPX_BYTES) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - *mlen = smlen - SPX_BYTES; - - if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - /* If verification was successful, move the message to the right place. */ - memmove(m, sm + SPX_BYTES, *mlen); - - return 0; -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/thash.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/thash.h deleted file mode 100644 index 8687ccfb4d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/thash.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef SPX_THASH_H -#define SPX_THASH_H - -#include "context.h" -#include "params.h" - -#include - -#define thash SPX_NAMESPACE(thash) -void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/thash_haraka_robust.c b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/thash_haraka_robust.c deleted file mode 100644 index 109502cbc2..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/thash_haraka_robust.c +++ /dev/null @@ -1,45 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "thash.h" -#include "utils.h" - -#include "haraka.h" - -/** - * Takes an array of inblocks concatenated arrays of SPX_N bytes. - */ -void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]) { - PQCLEAN_VLA(uint8_t, buf, SPX_ADDR_BYTES + inblocks * SPX_N); - PQCLEAN_VLA(uint8_t, bitmask, inblocks * SPX_N); - unsigned char outbuf[32]; - unsigned char buf_tmp[64]; - unsigned int i; - - if (inblocks == 1) { - /* F function */ - /* Since SPX_N may be smaller than 32, we need a temporary buffer. */ - memset(buf_tmp, 0, 64); - memcpy(buf_tmp, addr, 32); - - haraka256(outbuf, buf_tmp, ctx); - for (i = 0; i < inblocks * SPX_N; i++) { - buf_tmp[SPX_ADDR_BYTES + i] = in[i] ^ outbuf[i]; - } - haraka512(outbuf, buf_tmp, ctx); - memcpy(out, outbuf, SPX_N); - } else { - /* All other tweakable hashes*/ - memcpy(buf, addr, 32); - haraka_S(bitmask, inblocks * SPX_N, buf, SPX_ADDR_BYTES, ctx); - - for (i = 0; i < inblocks * SPX_N; i++) { - buf[SPX_ADDR_BYTES + i] = in[i] ^ bitmask[i]; - } - - haraka_S(out, SPX_N, buf, SPX_ADDR_BYTES + inblocks * SPX_N, ctx); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/thash_haraka_robustx4.c b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/thash_haraka_robustx4.c deleted file mode 100644 index 100808a3a5..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/thash_haraka_robustx4.c +++ /dev/null @@ -1,93 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "thashx4.h" - -#include "harakax4.h" - -#include "utils.h" - -/** - * 4-way parallel version of thash; takes 4x as much input and output - */ -#define thashx4 SPX_NAMESPACE(thashx4) -void thashx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addrx4[4 * 8]) { - PQCLEAN_VLA(unsigned char, buf0, SPX_ADDR_BYTES + inblocks * SPX_N); - PQCLEAN_VLA(unsigned char, buf1, SPX_ADDR_BYTES + inblocks * SPX_N); - PQCLEAN_VLA(unsigned char, buf2, SPX_ADDR_BYTES + inblocks * SPX_N); - PQCLEAN_VLA(unsigned char, buf3, SPX_ADDR_BYTES + inblocks * SPX_N); - PQCLEAN_VLA(unsigned char, bitmask0, inblocks * SPX_N); - PQCLEAN_VLA(unsigned char, bitmask1, inblocks * SPX_N); - PQCLEAN_VLA(unsigned char, bitmask2, inblocks * SPX_N); - PQCLEAN_VLA(unsigned char, bitmask3, inblocks * SPX_N); - unsigned char outbuf[32 * 4]; - unsigned char buf_tmp[64 * 4]; - unsigned int i; - - if (inblocks == 1) { - memset(buf_tmp, 0, 64 * 4); - - // Generate masks first in buffer - memcpy(buf_tmp, addrx4 + 0 * 8, 32); - memcpy(buf_tmp + 32, addrx4 + 1 * 8, 32); - memcpy(buf_tmp + 64, addrx4 + 2 * 8, 32); - memcpy(buf_tmp + 96, addrx4 + 3 * 8, 32); - - haraka256x4(outbuf, buf_tmp, ctx); - - /* move addresses to make room for inputs; zero old values */ - memcpy(buf_tmp + 192, buf_tmp + 96, SPX_ADDR_BYTES); - memcpy(buf_tmp + 128, buf_tmp + 64, SPX_ADDR_BYTES); - memcpy(buf_tmp + 64, buf_tmp + 32, SPX_ADDR_BYTES); - /* skip memcpy(buf_tmp, buf_tmp, SPX_ADDR_BYTES); already in place */ - - /* skip memset(buf_tmp, 0, SPX_ADDR_BYTES); remained untouched */ - memset(buf_tmp + 32, 0, SPX_ADDR_BYTES); - /* skip memset(buf_tmp + 64, 0, SPX_ADDR_BYTES); contains addr1 */ - memset(buf_tmp + 96, 0, SPX_ADDR_BYTES); - - for (i = 0; i < SPX_N; i++) { - buf_tmp[SPX_ADDR_BYTES + i] = in0[i] ^ outbuf[i]; - buf_tmp[SPX_ADDR_BYTES + i + 64] = in1[i] ^ outbuf[i + 32]; - buf_tmp[SPX_ADDR_BYTES + i + 128] = in2[i] ^ outbuf[i + 64]; - buf_tmp[SPX_ADDR_BYTES + i + 192] = in3[i] ^ outbuf[i + 96]; - } - - haraka512x4(outbuf, buf_tmp, ctx); - - memcpy(out0, outbuf, SPX_N); - memcpy(out1, outbuf + 32, SPX_N); - memcpy(out2, outbuf + 64, SPX_N); - memcpy(out3, outbuf + 96, SPX_N); - } else { - /* All other tweakable hashes*/ - memcpy(buf0, addrx4 + 0 * 8, 32); - memcpy(buf1, addrx4 + 1 * 8, 32); - memcpy(buf2, addrx4 + 2 * 8, 32); - memcpy(buf3, addrx4 + 3 * 8, 32); - - haraka_Sx4(bitmask0, bitmask1, bitmask2, bitmask3, inblocks * SPX_N, - buf0, buf1, buf2, buf3, SPX_ADDR_BYTES, ctx); - - for (i = 0; i < inblocks * SPX_N; i++) { - buf0[SPX_ADDR_BYTES + i] = in0[i] ^ bitmask0[i]; - buf1[SPX_ADDR_BYTES + i] = in1[i] ^ bitmask1[i]; - buf2[SPX_ADDR_BYTES + i] = in2[i] ^ bitmask2[i]; - buf3[SPX_ADDR_BYTES + i] = in3[i] ^ bitmask3[i]; - } - - haraka_Sx4(out0, out1, out2, out3, SPX_N, - buf0, buf1, buf2, buf3, SPX_ADDR_BYTES + inblocks * SPX_N, - ctx); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/thashx4.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/thashx4.h deleted file mode 100644 index 64798a3727..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/thashx4.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef SPX_THASHX4_H -#define SPX_THASHX4_H - -#include - -#include "context.h" -#include "params.h" - -#define thashx4 SPX_NAMESPACE(thashx4) -void thashx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addrx4[4 * 8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/utils.c b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/utils.c deleted file mode 100644 index 177b541fb9..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/utils.c +++ /dev/null @@ -1,148 +0,0 @@ -#include - -#include "utils.h" - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "thash.h" - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void ull_to_bytes(unsigned char *out, unsigned int outlen, - unsigned long long in) { - int i; - - /* Iterate over out in decreasing order, for big-endianness. */ - for (i = (signed int)outlen - 1; i >= 0; i--) { - out[i] = in & 0xff; - in = in >> 8; - } -} - -void u32_to_bytes(unsigned char *out, uint32_t in) { - out[0] = (unsigned char)(in >> 24); - out[1] = (unsigned char)(in >> 16); - out[2] = (unsigned char)(in >> 8); - out[3] = (unsigned char)in; -} - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { - unsigned long long retval = 0; - unsigned int i; - - for (i = 0; i < inlen; i++) { - retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); - } - return retval; -} - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void compute_root(unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const spx_ctx *ctx, uint32_t addr[8]) { - uint32_t i; - unsigned char buffer[2 * SPX_N]; - - /* If leaf_idx is odd (last bit = 1), current path element is a right child - and auth_path has to go left. Otherwise it is the other way around. */ - if (leaf_idx & 1) { - memcpy(buffer + SPX_N, leaf, SPX_N); - memcpy(buffer, auth_path, SPX_N); - } else { - memcpy(buffer, leaf, SPX_N); - memcpy(buffer + SPX_N, auth_path, SPX_N); - } - auth_path += SPX_N; - - for (i = 0; i < tree_height - 1; i++) { - leaf_idx >>= 1; - idx_offset >>= 1; - /* Set the address of the node we're creating. */ - set_tree_height(addr, i + 1); - set_tree_index(addr, leaf_idx + idx_offset); - - /* Pick the right or left neighbor, depending on parity of the node. */ - if (leaf_idx & 1) { - thash(buffer + SPX_N, buffer, 2, ctx, addr); - memcpy(buffer, auth_path, SPX_N); - } else { - thash(buffer, buffer, 2, ctx, addr); - memcpy(buffer + SPX_N, auth_path, SPX_N); - } - auth_path += SPX_N; - } - - /* The last iteration is exceptional; we do not copy an auth_path node. */ - leaf_idx >>= 1; - idx_offset >>= 1; - set_tree_height(addr, tree_height); - set_tree_index(addr, leaf_idx + idx_offset); - thash(root, buffer, 2, ctx, addr); -} - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const spx_ctx * /* ctx */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), - uint32_t tree_addr[8]) { - PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); - PQCLEAN_VLA(unsigned int, heights, tree_height + 1); - unsigned int offset = 0; - uint32_t idx; - uint32_t tree_idx; - - for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { - /* Add the next leaf node to the stack. */ - gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); - offset++; - heights[offset - 1] = 0; - - /* If this is a node we need for the auth path.. */ - if ((leaf_idx ^ 0x1) == idx) { - memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); - } - - /* While the top-most nodes are of equal height.. */ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { - /* Compute index of the new node, in the next layer. */ - tree_idx = (idx >> (heights[offset - 1] + 1)); - - /* Set the address of the node we're creating. */ - set_tree_height(tree_addr, heights[offset - 1] + 1); - set_tree_index(tree_addr, - tree_idx + (idx_offset >> (heights[offset - 1] + 1))); - /* Hash the top-most nodes from the stack together. */ - thash(stack + (offset - 2)*SPX_N, - stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); - offset--; - /* Note that the top-most node is now one layer higher. */ - heights[offset - 1]++; - - /* If this is a node we need for the auth path.. */ - if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_path + heights[offset - 1]*SPX_N, - stack + (offset - 1)*SPX_N, SPX_N); - } - } - } - memcpy(root, stack, SPX_N); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/utils.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/utils.h deleted file mode 100644 index 64f5d5a53a..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/utils.h +++ /dev/null @@ -1,58 +0,0 @@ -#ifndef SPX_UTILS_H -#define SPX_UTILS_H - -#include - -#include "compat.h" -#include "context.h" -#include "params.h" - - -/* To support MSVC use alloca() instead of VLAs. See #20. */ - - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) -void ull_to_bytes(unsigned char *out, unsigned int outlen, - unsigned long long in); -#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) -void u32_to_bytes(unsigned char *out, uint32_t in); - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) -unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -#define compute_root SPX_NAMESPACE(compute_root) -void compute_root(unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const spx_ctx *ctx, uint32_t addr[8]); - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -#define treehash SPX_NAMESPACE(treehash) -void treehash(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const spx_ctx *ctx /* ctx */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), - uint32_t tree_addr[8]); - - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/utilsx4.c b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/utilsx4.c deleted file mode 100644 index 1638677194..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/utilsx4.c +++ /dev/null @@ -1,138 +0,0 @@ -#include - -#include "utilsx4.h" - -#include "address.h" -#include "params.h" -#include "thashx4.h" -#include "utils.h" - -/* - * Generate the entire Merkle tree, computing the authentication path for leaf_idx, - * and the resulting root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) - * - * This expects tree_addrx4 to be initialized to 4 parallel addr structures for - * the Merkle tree nodes - * - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - * - * This works by using the standard Merkle tree building algorithm, except - * that each 'node' tracked is actually 4 consecutive nodes in the real tree. - * When we combine two logical nodes ABCD and WXYZ, we perform the H - * operation on adjacent real nodes, forming the parent logical node - * (AB)(CD)(WX)(YZ) - * - * When we get to the top two levels of the real tree (where there is only - * one logical node), we continue this operation two more times; the right - * most real node will by the actual root (and the other 3 nodes will be - * garbage). We follow the same thashx4 logic so that the 'extract - * authentication path components' part of the loop is still executed (and - * to simplify the code somewhat) - * - * This currently assumes tree_height >= 2; I suspect that doing an adjusting - * idx, addr_idx on the gen_leafx4 call if tree_height < 2 would fix it; since - * we don't actually use such short trees, I haven't bothered - */ -void treehashx4(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, - uint32_t tree_height, - void (*gen_leafx4)( - unsigned char * /* Where to write the leaves */, - const spx_ctx *, - uint32_t idx, void *info), - uint32_t tree_addrx4[4 * 8], - void *info) { - /* This is where we keep the intermediate nodes */ - PQCLEAN_VLA(unsigned char, stackx4, tree_height * 4 * SPX_N); - uint32_t left_adj = 0, prev_left_adj = 0; /* When we're doing the top 3 */ - /* levels, the left-most part of the tree isn't at the beginning */ - /* of current[]. These give the offset of the actual start */ - - uint32_t idx; - uint32_t max_idx = (1U << (tree_height - 2)) - 1; - for (idx = 0;; idx++) { - unsigned char current[4 * SPX_N]; /* Current logical node */ - gen_leafx4( current, ctx, 4 * idx + idx_offset, - info ); - - /* Now combine the freshly generated right node with previously */ - /* generated left ones */ - uint32_t internal_idx_offset = idx_offset; - uint32_t internal_idx = idx; - uint32_t internal_leaf = leaf_idx; - uint32_t h; /* The height we are in the Merkle tree */ - for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { - - /* Special processing if we're at the top of the tree */ - if (h >= tree_height - 2) { - if (h == tree_height) { - /* We hit the root; return it */ - memcpy( root, ¤t[3 * SPX_N], SPX_N ); - return; - } - /* The tree indexing logic is a bit off in this case */ - /* Adjust it so that the left-most node of the part of */ - /* the tree that we're processing has index 0 */ - prev_left_adj = left_adj; - left_adj = 4U - (1 << (tree_height - h - 1)); - } - - /* Check if we hit the top of the tree */ - if (h == tree_height) { - /* We hit the root; return it */ - memcpy( root, ¤t[3 * SPX_N], SPX_N ); - return; - } - - /* - * Check if one of the nodes we have is a part of the - * authentication path; if it is, write it out - */ - if ((((internal_idx << 2) ^ internal_leaf) & ~0x3U) == 0) { - memcpy( &auth_path[ h * SPX_N ], - ¤t[(((internal_leaf & 3) ^ 1) + prev_left_adj) * SPX_N], - SPX_N ); - } - - /* - * Check if we're at a left child; if so, stop going up the stack - * Exception: if we've reached the end of the tree, keep on going - * (so we combine the last 4 nodes into the one root node in two - * more iterations) - */ - if ((internal_idx & 1) == 0 && idx < max_idx) { - break; - } - - /* Ok, we're at a right node (or doing the top 3 levels) */ - /* Now combine the left and right logical nodes together */ - - /* Set the address of the node we're creating. */ - unsigned int j; - internal_idx_offset >>= 1; - for (j = 0; j < 4; j++) { - set_tree_height(tree_addrx4 + j * 8, h + 1); - set_tree_index(tree_addrx4 + j * 8, - (4 / 2) * (internal_idx & ~1U) + j - left_adj + internal_idx_offset ); - } - unsigned char *left = &stackx4[h * 4 * SPX_N]; - thashx4( ¤t[0 * SPX_N], - ¤t[1 * SPX_N], - ¤t[2 * SPX_N], - ¤t[3 * SPX_N], - &left [0 * SPX_N], - &left [2 * SPX_N], - ¤t[0 * SPX_N], - ¤t[2 * SPX_N], - 2, ctx, tree_addrx4); - } - - /* We've hit a left child; save the current for when we get the */ - /* corresponding right right */ - memcpy( &stackx4[h * 4 * SPX_N], current, 4 * SPX_N); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/utilsx4.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/utilsx4.h deleted file mode 100644 index facb874b18..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/utilsx4.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef SPX_UTILSX4_H -#define SPX_UTILSX4_H - -#include - -#include "context.h" -#include "params.h" - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - * - * This implementation uses AVX to compute internal nodes 4 at a time (in - * parallel) - */ -#define treehashx4 SPX_NAMESPACE(treehashx4) -void treehashx4(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leafx4)( - unsigned char * /* Where to write the leaves */, - const spx_ctx * /* ctx */, - uint32_t addr_idx, void *info), - uint32_t tree_addrx4[4 * 8], void *info); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/wots.c b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/wots.c deleted file mode 100644 index 4d5041ce05..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/wots.c +++ /dev/null @@ -1,269 +0,0 @@ -#include -#include - -#include "wots.h" - -#include "address.h" -#include "hash.h" -#include "hashx4.h" -#include "params.h" -#include "thash.h" -#include "thashx4.h" -#include "utils.h" -#include "utilsx4.h" -#include "wotsx4.h" - -// TODO clarify address expectations, and make them more uniform. -// TODO i.e. do we expect types to be set already? -// TODO and do we expect modifications or copies? - -/** - * Computes up the chains - */ -static void gen_chains( - unsigned char *out, - const unsigned char *in, - unsigned int start[SPX_WOTS_LEN], - const unsigned int steps[SPX_WOTS_LEN], - const spx_ctx *ctx, - uint32_t addr[8]) { - uint32_t i, j, k, idx, watching; - int done; - unsigned char empty[SPX_N]; - unsigned char *bufs[4]; - uint32_t addrs[8 * 4]; - - int l; - uint16_t counts[SPX_WOTS_W] = { 0 }; - uint16_t idxs[SPX_WOTS_LEN]; - uint16_t total, newTotal; - - /* set addrs = {addr, addr, addr, addr} */ - for (j = 0; j < 4; j++) { - memcpy(addrs + j * 8, addr, sizeof(uint32_t) * 8); - } - - /* Initialize out with the value at position 'start'. */ - memcpy(out, in, SPX_WOTS_LEN * SPX_N); - - /* Sort the chains in reverse order by steps using counting sort. */ - for (i = 0; i < SPX_WOTS_LEN; i++) { - counts[steps[i]]++; - } - total = 0; - for (l = SPX_WOTS_W - 1; l >= 0; l--) { - newTotal = counts[l] + total; - counts[l] = total; - total = newTotal; - } - for (i = 0; i < SPX_WOTS_LEN; i++) { - idxs[counts[steps[i]]] = (uint16_t)i; - counts[steps[i]]++; - } - - /* We got our work cut out for us: do it! */ - for (i = 0; i < SPX_WOTS_LEN; i += 4) { - for (j = 0; j < 4 && i + j < SPX_WOTS_LEN; j++) { - idx = idxs[i + j]; - set_chain_addr(addrs + j * 8, idx); - bufs[j] = out + SPX_N * idx; - } - - /* As the chains are sorted in reverse order, we know that the first - * chain is the longest and the last one is the shortest. We keep - * an eye on whether the last chain is done and then on the one before, - * et cetera. */ - watching = 3; - done = 0; - while (i + watching >= SPX_WOTS_LEN) { - bufs[watching] = &empty[0]; - watching--; - } - - for (k = 0;; k++) { - while (k == steps[idxs[i + watching]]) { - bufs[watching] = &empty[0]; - if (watching == 0) { - done = 1; - break; - } - watching--; - } - if (done) { - break; - } - for (j = 0; j < watching + 1; j++) { - set_hash_addr(addrs + j * 8, k + start[idxs[i + j]]); - } - - thashx4(bufs[0], bufs[1], bufs[2], bufs[3], - bufs[0], bufs[1], bufs[2], bufs[3], 1, ctx, addrs); - } - } -} - -/** - * base_w algorithm as described in draft. - * Interprets an array of bytes as integers in base w. - * This only works when log_w is a divisor of 8. - */ -static void base_w(unsigned int *output, const int out_len, - const unsigned char *input) { - int in = 0; - int out = 0; - unsigned char total = 0; - int bits = 0; - int consumed; - - for (consumed = 0; consumed < out_len; consumed++) { - if (bits == 0) { - total = input[in]; - in++; - bits += 8; - } - bits -= SPX_WOTS_LOGW; - output[out] = (total >> bits) & (SPX_WOTS_W - 1); - out++; - } -} - -/* Computes the WOTS+ checksum over a message (in base_w). */ -static void wots_checksum(unsigned int *csum_base_w, - const unsigned int *msg_base_w) { - unsigned int csum = 0; - unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; - unsigned int i; - - /* Compute checksum. */ - for (i = 0; i < SPX_WOTS_LEN1; i++) { - csum += SPX_WOTS_W - 1 - msg_base_w[i]; - } - - /* Convert checksum to base_w. */ - /* Make sure expected empty zero bits are the least significant bits. */ - csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); - ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); - base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); -} - -/* Takes a message and derives the matching chain lengths. */ -void chain_lengths(unsigned int *lengths, const unsigned char *msg) { - base_w(lengths, SPX_WOTS_LEN1, msg); - wots_checksum(lengths + SPX_WOTS_LEN1, lengths); -} - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const spx_ctx *ctx, uint32_t addr[8]) { - unsigned int steps[SPX_WOTS_LEN]; - unsigned int start[SPX_WOTS_LEN]; - uint32_t i; - - chain_lengths(start, msg); - - for (i = 0; i < SPX_WOTS_LEN; i++) { - steps[i] = SPX_WOTS_W - 1 - start[i]; - } - - gen_chains(pk, sig, start, steps, ctx, addr); -} - -/* - * This generates 4 sequential WOTS public keys - * It also generates the WOTS signature if leaf_info indicates - * that we're signing with one of these WOTS keys - */ -void wots_gen_leafx4(unsigned char *dest, - const spx_ctx *ctx, - uint32_t leaf_idx, void *v_info) { - struct leaf_info_x4 *info = v_info; - uint32_t *leaf_addr = info->leaf_addr; - uint32_t *pk_addr = info->pk_addr; - unsigned int i, j, k; - unsigned char pk_buffer[ 4 * SPX_WOTS_BYTES ]; - unsigned wots_offset = SPX_WOTS_BYTES; - unsigned char *buffer; - uint32_t wots_k_mask; - unsigned wots_sign_index; - - if (((leaf_idx ^ info->wots_sign_leaf) & ~3U) == 0) { - /* We're traversing the leaf that's signing; generate the WOTS */ - /* signature */ - wots_k_mask = 0; - wots_sign_index = info->wots_sign_leaf & 3; /* Which of of the 4 */ - /* 4 slots do the signatures come from */ - } else { - /* Nope, we're just generating pk's; turn off the signature logic */ - wots_k_mask = (uint32_t)~0; - wots_sign_index = 0; - } - - for (j = 0; j < 4; j++) { - set_keypair_addr( leaf_addr + j * 8, leaf_idx + j ); - set_keypair_addr( pk_addr + j * 8, leaf_idx + j ); - } - - for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { - uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k to */ - /* the step if we're generating a signature, ~0 if we're not */ - - /* Start with the secret seed */ - for (j = 0; j < 4; j++) { - set_chain_addr(leaf_addr + j * 8, i); - set_hash_addr(leaf_addr + j * 8, 0); - set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTSPRF); - } - prf_addrx4(buffer + 0 * wots_offset, - buffer + 1 * wots_offset, - buffer + 2 * wots_offset, - buffer + 3 * wots_offset, - ctx, leaf_addr); - - for (j = 0; j < 4; j++) { - set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTS); - } - - /* Iterate down the WOTS chain */ - for (k = 0;; k++) { - /* Check if one of the values we have needs to be saved as a */ - /* part of the WOTS signature */ - if (k == wots_k) { - memcpy( info->wots_sig + i * SPX_N, - buffer + wots_sign_index * wots_offset, SPX_N ); - } - - /* Check if we hit the top of the chain */ - if (k == SPX_WOTS_W - 1) { - break; - } - - /* Iterate one step on all 4 chains */ - for (j = 0; j < 4; j++) { - set_hash_addr(leaf_addr + j * 8, k); - } - thashx4(buffer + 0 * wots_offset, - buffer + 1 * wots_offset, - buffer + 2 * wots_offset, - buffer + 3 * wots_offset, - buffer + 0 * wots_offset, - buffer + 1 * wots_offset, - buffer + 2 * wots_offset, - buffer + 3 * wots_offset, 1, ctx, leaf_addr); - } - } - - /* Do the final thash to generate the public keys */ - thashx4(dest + 0 * SPX_N, - dest + 1 * SPX_N, - dest + 2 * SPX_N, - dest + 3 * SPX_N, - pk_buffer + 0 * wots_offset, - pk_buffer + 1 * wots_offset, - pk_buffer + 2 * wots_offset, - pk_buffer + 3 * wots_offset, SPX_WOTS_LEN, ctx, pk_addr); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/wots.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/wots.h deleted file mode 100644 index 4e7692eeef..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/wots.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef SPX_WOTS_H -#define SPX_WOTS_H - -#include - -#include "context.h" -#include "params.h" - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) -void wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const spx_ctx *ctx, uint32_t addr[8]); - -/* - * Compute the chain lengths needed for a given message hash - */ -#define chain_lengths SPX_NAMESPACE(chain_lengths) -void chain_lengths(unsigned int *lengths, const unsigned char *msg); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/wotsx4.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/wotsx4.h deleted file mode 100644 index cd634f1743..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_aesni/wotsx4.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef WOTSX4_H_ -#define WOTSX4_H_ - -#include - -#include "params.h" - -/* - * This is here to provide an interface to the internal wots_gen_leafx4 - * routine. While this routine is not referenced in the package outside of - * wots.c, it is called from the stand-alone benchmark code to characterize - * the performance - */ -struct leaf_info_x4 { - unsigned char *wots_sig; - uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ - uint32_t *wots_steps; - uint32_t leaf_addr[4 * 8]; - uint32_t pk_addr[4 * 8]; -}; - -/* Macro to set the leaf_info to something 'benign', that is, it would */ -/* run with the same time as it does during the real signing process */ -/* Used only by the benchmark code */ -#define INITIALIZE_LEAF_INFO_X4(info, addr, step_buffer) { \ - (info).wots_sig = 0; \ - (info).wots_sign_leaf = ~0; \ - (info).wots_steps = step_buffer; \ - int i; \ - for (i=0; i<4; i++) { \ - memcpy( &(info).leaf_addr[8*i], addr, 32 ); \ - memcpy( &(info).pk_addr[8*i], addr, 32 ); \ - } \ - } - -#define wots_gen_leafx4 SPX_NAMESPACE(wots_gen_leafx4) -void wots_gen_leafx4(unsigned char *dest, - const spx_ctx *ctx, - uint32_t leaf_idx, void *v_info); - -#endif /* WOTSX4_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/LICENSE b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/LICENSE deleted file mode 100644 index 670154e353..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/LICENSE +++ /dev/null @@ -1,116 +0,0 @@ -CC0 1.0 Universal - -Statement of Purpose - -The laws of most jurisdictions throughout the world automatically confer -exclusive Copyright and Related Rights (defined below) upon the creator and -subsequent owner(s) (each and all, an "owner") of an original work of -authorship and/or a database (each, a "Work"). - -Certain owners wish to permanently relinquish those rights to a Work for the -purpose of contributing to a commons of creative, cultural and scientific -works ("Commons") that the public can reliably and without fear of later -claims of infringement build upon, modify, incorporate in other works, reuse -and redistribute as freely as possible in any form whatsoever and for any -purposes, including without limitation commercial purposes. These owners may -contribute to the Commons to promote the ideal of a free culture and the -further production of creative, cultural and scientific works, or to gain -reputation or greater distribution for their Work in part through the use and -efforts of others. - -For these and/or other purposes and motivations, and without any expectation -of additional consideration or compensation, the person associating CC0 with a -Work (the "Affirmer"), to the extent that he or she is an owner of Copyright -and Related Rights in the Work, voluntarily elects to apply CC0 to the Work -and publicly distribute the Work under its terms, with knowledge of his or her -Copyright and Related Rights in the Work and the meaning and intended legal -effect of CC0 on those rights. - -1. Copyright and Related Rights. A Work made available under CC0 may be -protected by copyright and related or neighboring rights ("Copyright and -Related Rights"). Copyright and Related Rights include, but are not limited -to, the following: - - i. the right to reproduce, adapt, distribute, perform, display, communicate, - and translate a Work; - - ii. moral rights retained by the original author(s) and/or performer(s); - - iii. publicity and privacy rights pertaining to a person's image or likeness - depicted in a Work; - - iv. rights protecting against unfair competition in regards to a Work, - subject to the limitations in paragraph 4(a), below; - - v. rights protecting the extraction, dissemination, use and reuse of data in - a Work; - - vi. database rights (such as those arising under Directive 96/9/EC of the - European Parliament and of the Council of 11 March 1996 on the legal - protection of databases, and under any national implementation thereof, - including any amended or successor version of such directive); and - - vii. other similar, equivalent or corresponding rights throughout the world - based on applicable law or treaty, and any national implementations thereof. - -2. Waiver. To the greatest extent permitted by, but not in contravention of, -applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and -unconditionally waives, abandons, and surrenders all of Affirmer's Copyright -and Related Rights and associated claims and causes of action, whether now -known or unknown (including existing as well as future claims and causes of -action), in the Work (i) in all territories worldwide, (ii) for the maximum -duration provided by applicable law or treaty (including future time -extensions), (iii) in any current or future medium and for any number of -copies, and (iv) for any purpose whatsoever, including without limitation -commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes -the Waiver for the benefit of each member of the public at large and to the -detriment of Affirmer's heirs and successors, fully intending that such Waiver -shall not be subject to revocation, rescission, cancellation, termination, or -any other legal or equitable action to disrupt the quiet enjoyment of the Work -by the public as contemplated by Affirmer's express Statement of Purpose. - -3. Public License Fallback. Should any part of the Waiver for any reason be -judged legally invalid or ineffective under applicable law, then the Waiver -shall be preserved to the maximum extent permitted taking into account -Affirmer's express Statement of Purpose. In addition, to the extent the Waiver -is so judged Affirmer hereby grants to each affected person a royalty-free, -non transferable, non sublicensable, non exclusive, irrevocable and -unconditional license to exercise Affirmer's Copyright and Related Rights in -the Work (i) in all territories worldwide, (ii) for the maximum duration -provided by applicable law or treaty (including future time extensions), (iii) -in any current or future medium and for any number of copies, and (iv) for any -purpose whatsoever, including without limitation commercial, advertising or -promotional purposes (the "License"). The License shall be deemed effective as -of the date CC0 was applied by Affirmer to the Work. Should any part of the -License for any reason be judged legally invalid or ineffective under -applicable law, such partial invalidity or ineffectiveness shall not -invalidate the remainder of the License, and in such case Affirmer hereby -affirms that he or she will not (i) exercise any of his or her remaining -Copyright and Related Rights in the Work or (ii) assert any associated claims -and causes of action with respect to the Work, in either case contrary to -Affirmer's express Statement of Purpose. - -4. Limitations and Disclaimers. - - a. No trademark or patent rights held by Affirmer are waived, abandoned, - surrendered, licensed or otherwise affected by this document. - - b. Affirmer offers the Work as-is and makes no representations or warranties - of any kind concerning the Work, express, implied, statutory or otherwise, - including without limitation warranties of title, merchantability, fitness - for a particular purpose, non infringement, or the absence of latent or - other defects, accuracy, or the present or absence of errors, whether or not - discoverable, all to the greatest extent permissible under applicable law. - - c. Affirmer disclaims responsibility for clearing rights of other persons - that may apply to the Work or any use thereof, including without limitation - any person's Copyright and Related Rights in the Work. Further, Affirmer - disclaims responsibility for obtaining any necessary consents, permissions - or other rights required for any use of the Work. - - d. Affirmer understands and acknowledges that Creative Commons is not a - party to this document and has no duty or obligation with respect to this - CC0 or use of the Work. - -For more information, please see - diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/address.c b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/address.c deleted file mode 100644 index d49d9f3b6b..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/address.c +++ /dev/null @@ -1,95 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "utils.h" - -/* - * Specify which level of Merkle tree (the "layer") we're working on - */ -void set_layer_addr(uint32_t addr[8], uint32_t layer) { - ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; -} - -/* - * Specify which Merkle tree within the level (the "tree address") we're working on - */ -void set_tree_addr(uint32_t addr[8], uint64_t tree) { - ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); -} - -/* - * Specify the reason we'll use this address structure for, that is, what - * hash will we compute with it. This is used so that unrelated types of - * hashes don't accidentally get the same address structure. The type will be - * one of the SPX_ADDR_TYPE constants - */ -void set_type(uint32_t addr[8], uint32_t type) { - ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; -} - -/* - * Copy the layer and tree fields of the address structure. This is used - * when we're doing multiple types of hashes within the same Merkle tree - */ -void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { - memcpy( out, in, SPX_OFFSET_TREE + 8 ); -} - -/* These functions are used for OTS addresses. */ - -/* - * Specify which Merkle leaf we're working on; that is, which OTS keypair - * we're talking about. - */ -void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { - /* We have > 256 OTS at the bottom of the Merkle tree; to specify */ - /* which one, we'd need to express it in two bytes */ - ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR2] = (unsigned char)(keypair >> 8); - ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; -} - -/* - * Copy the layer, tree and keypair fields of the address structure. This is - * used when we're doing multiple things within the same OTS keypair - */ -void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { - memcpy( out, in, SPX_OFFSET_TREE + 8 ); - ((unsigned char *)out)[SPX_OFFSET_KP_ADDR2] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR2]; - ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; -} - -/* - * Specify which Merkle chain within the OTS we're working with - * (the chain address) - */ -void set_chain_addr(uint32_t addr[8], uint32_t chain) { - ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; -} - -/* - * Specify where in the Merkle chain we are -* (the hash address) - */ -void set_hash_addr(uint32_t addr[8], uint32_t hash) { - ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; -} - -/* These functions are used for all hash tree addresses (including FORS). */ - -/* - * Specify the height of the node in the Merkle/FORS tree we are in - * (the tree height) - */ -void set_tree_height(uint32_t addr[8], uint32_t tree_height) { - ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; -} - -/* - * Specify the distance from the left edge of the node in the Merkle/FORS tree - * (the tree index) - */ -void set_tree_index(uint32_t addr[8], uint32_t tree_index) { - u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/address.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/address.h deleted file mode 100644 index 24a84eb40c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/address.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef SPX_ADDRESS_H -#define SPX_ADDRESS_H - -#include - -#include "params.h" - -/* The hash types that are passed to set_type */ -#define SPX_ADDR_TYPE_WOTS 0 -#define SPX_ADDR_TYPE_WOTSPK 1 -#define SPX_ADDR_TYPE_HASHTREE 2 -#define SPX_ADDR_TYPE_FORSTREE 3 -#define SPX_ADDR_TYPE_FORSPK 4 -#define SPX_ADDR_TYPE_WOTSPRF 5 -#define SPX_ADDR_TYPE_FORSPRF 6 - -#define set_layer_addr SPX_NAMESPACE(set_layer_addr) -void set_layer_addr(uint32_t addr[8], uint32_t layer); - -#define set_tree_addr SPX_NAMESPACE(set_tree_addr) -void set_tree_addr(uint32_t addr[8], uint64_t tree); - -#define set_type SPX_NAMESPACE(set_type) -void set_type(uint32_t addr[8], uint32_t type); - -/* Copies the layer and tree part of one address into the other */ -#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) -void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for WOTS and FORS addresses. */ - -#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) -void set_keypair_addr(uint32_t addr[8], uint32_t keypair); - -#define set_chain_addr SPX_NAMESPACE(set_chain_addr) -void set_chain_addr(uint32_t addr[8], uint32_t chain); - -#define set_hash_addr SPX_NAMESPACE(set_hash_addr) -void set_hash_addr(uint32_t addr[8], uint32_t hash); - -#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) -void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for all hash tree addresses (including FORS). */ - -#define set_tree_height SPX_NAMESPACE(set_tree_height) -void set_tree_height(uint32_t addr[8], uint32_t tree_height); - -#define set_tree_index SPX_NAMESPACE(set_tree_index) -void set_tree_index(uint32_t addr[8], uint32_t tree_index); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/api.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/api.h deleted file mode 100644 index feebb2d510..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/api.h +++ /dev/null @@ -1,77 +0,0 @@ -#ifndef PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_API_H -#define PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_API_H - -#include -#include - -#define PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_CRYPTO_ALGNAME "SPHINCS+-haraka-192s-robust" - -#define PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_CRYPTO_SECRETKEYBYTES 96 -#define PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_CRYPTO_PUBLICKEYBYTES 48 -#define PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_CRYPTO_BYTES 16224 - -#define PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_CRYPTO_SEEDBYTES 72 - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, - const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk); -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/context.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/context.h deleted file mode 100644 index 600dfb73c7..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/context.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef SPX_CONTEXT_H -#define SPX_CONTEXT_H - -#include -#include - -#include "params.h" - -typedef struct { - uint8_t pub_seed[SPX_N]; - uint8_t sk_seed[SPX_N]; - - - uint64_t tweaked512_rc64[10][8]; - uint32_t tweaked256_rc32[10][8]; -} spx_ctx; - -#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) -void initialize_hash_function(spx_ctx *ctx); - -#define free_hash_function SPX_NAMESPACE(free_hash_function) -void free_hash_function(spx_ctx *ctx); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/context_haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/context_haraka.c deleted file mode 100644 index f1cd7e3664..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/context_haraka.c +++ /dev/null @@ -1,11 +0,0 @@ -#include "context.h" -#include "haraka.h" - -void initialize_hash_function(spx_ctx *ctx) { - tweak_constants(ctx); -} - -// we don't support heap-based haraka right now -void free_hash_function(spx_ctx *ctx) { - (void)ctx; // suppress unused variable warnings -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/fors.c b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/fors.c deleted file mode 100644 index 96ca72e986..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/fors.c +++ /dev/null @@ -1,156 +0,0 @@ -#include -#include -#include - -#include "fors.h" - -#include "address.h" -#include "hash.h" -#include "thash.h" -#include "utils.h" -#include "utilsx1.h" - -static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, - uint32_t fors_leaf_addr[8]) { - prf_addr(sk, ctx, fors_leaf_addr); -} - -static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, - const spx_ctx *ctx, - uint32_t fors_leaf_addr[8]) { - thash(leaf, sk, 1, ctx, fors_leaf_addr); -} - -struct fors_gen_leaf_info { - uint32_t leaf_addrx[8]; -}; - -static void fors_gen_leafx1(unsigned char *leaf, - const spx_ctx *ctx, - uint32_t addr_idx, void *info) { - struct fors_gen_leaf_info *fors_info = info; - uint32_t *fors_leaf_addr = fors_info->leaf_addrx; - - /* Only set the parts that the caller doesn't set */ - set_tree_index(fors_leaf_addr, addr_idx); - set_type(fors_leaf_addr, SPX_ADDR_TYPE_FORSPRF); - fors_gen_sk(leaf, ctx, fors_leaf_addr); - - set_type(fors_leaf_addr, SPX_ADDR_TYPE_FORSTREE); - fors_sk_to_leaf(leaf, leaf, - ctx, fors_leaf_addr); -} - -/** - * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - * Assumes indices has space for SPX_FORS_TREES integers. - */ -static void message_to_indices(uint32_t *indices, const unsigned char *m) { - unsigned int i, j; - unsigned int offset = 0; - - for (i = 0; i < SPX_FORS_TREES; i++) { - indices[i] = 0; - for (j = 0; j < SPX_FORS_HEIGHT; j++) { - indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); - offset++; - } - } -} - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -void fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]) { - uint32_t indices[SPX_FORS_TREES]; - unsigned char roots[SPX_FORS_TREES * SPX_N]; - uint32_t fors_tree_addr[8] = {0}; - struct fors_gen_leaf_info fors_info = {0}; - uint32_t *fors_leaf_addr = fors_info.leaf_addrx; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - copy_keypair_addr(fors_tree_addr, fors_addr); - copy_keypair_addr(fors_leaf_addr, fors_addr); - - copy_keypair_addr(fors_pk_addr, fors_addr); - set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < SPX_FORS_TREES; i++) { - idx_offset = i * (1 << SPX_FORS_HEIGHT); - - set_tree_height(fors_tree_addr, 0); - set_tree_index(fors_tree_addr, indices[i] + idx_offset); - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); - - /* Include the secret key part that produces the selected leaf node. */ - fors_gen_sk(sig, ctx, fors_tree_addr); - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); - sig += SPX_N; - - /* Compute the authentication path for this leaf node. */ - treehashx1(roots + i * SPX_N, sig, ctx, - indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx1, - fors_tree_addr, &fors_info); - - sig += SPX_N * SPX_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); -} - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -void fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]) { - uint32_t indices[SPX_FORS_TREES]; - unsigned char roots[SPX_FORS_TREES * SPX_N]; - unsigned char leaf[SPX_N]; - uint32_t fors_tree_addr[8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - copy_keypair_addr(fors_tree_addr, fors_addr); - copy_keypair_addr(fors_pk_addr, fors_addr); - - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); - set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < SPX_FORS_TREES; i++) { - idx_offset = i * (1 << SPX_FORS_HEIGHT); - - set_tree_height(fors_tree_addr, 0); - set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Derive the leaf from the included secret key part. */ - fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); - sig += SPX_N; - - /* Derive the corresponding root node of this tree. */ - compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, - sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); - sig += SPX_N * SPX_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/fors.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/fors.h deleted file mode 100644 index 509140a178..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/fors.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef SPX_FORS_H -#define SPX_FORS_H - -#include - -#include "context.h" -#include "params.h" - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -#define fors_sign SPX_NAMESPACE(fors_sign) -void fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]); - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) -void fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/haraka.c deleted file mode 100644 index a4944913b5..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/haraka.c +++ /dev/null @@ -1,913 +0,0 @@ -/* - * Constant time implementation of the Haraka hash function. - * - * The bit-sliced implementation of the AES round functions are - * based on the AES implementation in BearSSL written - * by Thomas Pornin - */ - -#include -#include -#include -#include - -#include "haraka.h" -#include "utils.h" - -#define HARAKAS_RATE 32 - -static const uint64_t haraka512_rc64[10][8] = { - {0x24cf0ab9086f628b, 0xbdd6eeecc83b8382, 0xd96fb0306cdad0a7, 0xaace082ac8f95f89, 0x449d8e8870d7041f, 0x49bb2f80b2b3e2f8, 0x0569ae98d93bb258, 0x23dc9691e7d6a4b1}, - {0xd8ba10ede0fe5b6e, 0x7ecf7dbe424c7b8e, 0x6ea9949c6df62a31, 0xbf3f3c97ec9c313e, 0x241d03a196a1861e, 0xead3a51116e5a2ea, 0x77d479fcad9574e3, 0x18657a1af894b7a0}, - {0x10671e1a7f595522, 0xd9a00ff675d28c7b, 0x2f1edf0d2b9ba661, 0xb8ff58b8e3de45f9, 0xee29261da9865c02, 0xd1532aa4b50bdf43, 0x8bf858159b231bb1, 0xdf17439d22d4f599}, - {0xdd4b2f0870b918c0, 0x757a81f3b39b1bb6, 0x7a5c556898952e3f, 0x7dd70a16d915d87a, 0x3ae61971982b8301, 0xc3ab319e030412be, 0x17c0033ac094a8cb, 0x5a0630fc1a8dc4ef}, - {0x17708988c1632f73, 0xf92ddae090b44f4f, 0x11ac0285c43aa314, 0x509059941936b8ba, 0xd03e152fa2ce9b69, 0x3fbcbcb63a32998b, 0x6204696d692254f7, 0x915542ed93ec59b4}, - {0xf4ed94aa8879236e, 0xff6cb41cd38e03c0, 0x069b38602368aeab, 0x669495b820f0ddba, 0xf42013b1b8bf9e3d, 0xcf935efe6439734d, 0xbc1dcf42ca29e3f8, 0x7e6d3ed29f78ad67}, - {0xf3b0f6837ffcddaa, 0x3a76faef934ddf41, 0xcec7ae583a9c8e35, 0xe4dd18c68f0260af, 0x2c0e5df1ad398eaa, 0x478df5236ae22e8c, 0xfb944c46fe865f39, 0xaa48f82f028132ba}, - {0x231b9ae2b76aca77, 0x292a76a712db0b40, 0x5850625dc8134491, 0x73137dd469810fb5, 0x8a12a6a202a474fd, 0xd36fd9daa78bdb80, 0xb34c5e733505706f, 0xbaf1cdca818d9d96}, - {0x2e99781335e8c641, 0xbddfe5cce47d560e, 0xf74e9bf32e5e040c, 0x1d7a709d65996be9, 0x670df36a9cf66cdd, 0xd05ef84a176a2875, 0x0f888e828cb1c44e, 0x1a79e9c9727b052c}, - {0x83497348628d84de, 0x2e9387d51f22a754, 0xb000068da2f852d6, 0x378c9e1190fd6fe5, 0x870027c316de7293, 0xe51a9d4462e047bb, 0x90ecf7f8c6251195, 0x655953bfbed90a9c}, -}; - -static inline uint32_t br_dec32le(const unsigned char *src) { - return (uint32_t)src[0] - | ((uint32_t)src[1] << 8) - | ((uint32_t)src[2] << 16) - | ((uint32_t)src[3] << 24); -} - -static void br_range_dec32le(uint32_t *v, size_t num, const unsigned char *src) { - while (num-- > 0) { - *v ++ = br_dec32le(src); - src += 4; - } -} - -static inline void br_enc32le(unsigned char *dst, uint32_t x) { - dst[0] = (unsigned char)x; - dst[1] = (unsigned char)(x >> 8); - dst[2] = (unsigned char)(x >> 16); - dst[3] = (unsigned char)(x >> 24); -} - - -static void br_range_enc32le(unsigned char *dst, const uint32_t *v, size_t num) { - while (num-- > 0) { - br_enc32le(dst, *v ++); - dst += 4; - } -} - -static void br_aes_ct64_bitslice_Sbox(uint64_t *q) { - /* - * This S-box implementation is a straightforward translation of - * the circuit described by Boyar and Peralta in "A new - * combinational logic minimization technique with applications - * to cryptology" (https://eprint.iacr.org/2009/191.pdf). - * - * Note that variables x* (input) and s* (output) are numbered - * in "reverse" order (x0 is the high bit, x7 is the low bit). - */ - - uint64_t x0, x1, x2, x3, x4, x5, x6, x7; - uint64_t y1, y2, y3, y4, y5, y6, y7, y8, y9; - uint64_t y10, y11, y12, y13, y14, y15, y16, y17, y18, y19; - uint64_t y20, y21; - uint64_t z0, z1, z2, z3, z4, z5, z6, z7, z8, z9; - uint64_t z10, z11, z12, z13, z14, z15, z16, z17; - uint64_t t0, t1, t2, t3, t4, t5, t6, t7, t8, t9; - uint64_t t10, t11, t12, t13, t14, t15, t16, t17, t18, t19; - uint64_t t20, t21, t22, t23, t24, t25, t26, t27, t28, t29; - uint64_t t30, t31, t32, t33, t34, t35, t36, t37, t38, t39; - uint64_t t40, t41, t42, t43, t44, t45, t46, t47, t48, t49; - uint64_t t50, t51, t52, t53, t54, t55, t56, t57, t58, t59; - uint64_t t60, t61, t62, t63, t64, t65, t66, t67; - uint64_t s0, s1, s2, s3, s4, s5, s6, s7; - - x0 = q[7]; - x1 = q[6]; - x2 = q[5]; - x3 = q[4]; - x4 = q[3]; - x5 = q[2]; - x6 = q[1]; - x7 = q[0]; - - /* - * Top linear transformation. - */ - y14 = x3 ^ x5; - y13 = x0 ^ x6; - y9 = x0 ^ x3; - y8 = x0 ^ x5; - t0 = x1 ^ x2; - y1 = t0 ^ x7; - y4 = y1 ^ x3; - y12 = y13 ^ y14; - y2 = y1 ^ x0; - y5 = y1 ^ x6; - y3 = y5 ^ y8; - t1 = x4 ^ y12; - y15 = t1 ^ x5; - y20 = t1 ^ x1; - y6 = y15 ^ x7; - y10 = y15 ^ t0; - y11 = y20 ^ y9; - y7 = x7 ^ y11; - y17 = y10 ^ y11; - y19 = y10 ^ y8; - y16 = t0 ^ y11; - y21 = y13 ^ y16; - y18 = x0 ^ y16; - - /* - * Non-linear section. - */ - t2 = y12 & y15; - t3 = y3 & y6; - t4 = t3 ^ t2; - t5 = y4 & x7; - t6 = t5 ^ t2; - t7 = y13 & y16; - t8 = y5 & y1; - t9 = t8 ^ t7; - t10 = y2 & y7; - t11 = t10 ^ t7; - t12 = y9 & y11; - t13 = y14 & y17; - t14 = t13 ^ t12; - t15 = y8 & y10; - t16 = t15 ^ t12; - t17 = t4 ^ t14; - t18 = t6 ^ t16; - t19 = t9 ^ t14; - t20 = t11 ^ t16; - t21 = t17 ^ y20; - t22 = t18 ^ y19; - t23 = t19 ^ y21; - t24 = t20 ^ y18; - - t25 = t21 ^ t22; - t26 = t21 & t23; - t27 = t24 ^ t26; - t28 = t25 & t27; - t29 = t28 ^ t22; - t30 = t23 ^ t24; - t31 = t22 ^ t26; - t32 = t31 & t30; - t33 = t32 ^ t24; - t34 = t23 ^ t33; - t35 = t27 ^ t33; - t36 = t24 & t35; - t37 = t36 ^ t34; - t38 = t27 ^ t36; - t39 = t29 & t38; - t40 = t25 ^ t39; - - t41 = t40 ^ t37; - t42 = t29 ^ t33; - t43 = t29 ^ t40; - t44 = t33 ^ t37; - t45 = t42 ^ t41; - z0 = t44 & y15; - z1 = t37 & y6; - z2 = t33 & x7; - z3 = t43 & y16; - z4 = t40 & y1; - z5 = t29 & y7; - z6 = t42 & y11; - z7 = t45 & y17; - z8 = t41 & y10; - z9 = t44 & y12; - z10 = t37 & y3; - z11 = t33 & y4; - z12 = t43 & y13; - z13 = t40 & y5; - z14 = t29 & y2; - z15 = t42 & y9; - z16 = t45 & y14; - z17 = t41 & y8; - - /* - * Bottom linear transformation. - */ - t46 = z15 ^ z16; - t47 = z10 ^ z11; - t48 = z5 ^ z13; - t49 = z9 ^ z10; - t50 = z2 ^ z12; - t51 = z2 ^ z5; - t52 = z7 ^ z8; - t53 = z0 ^ z3; - t54 = z6 ^ z7; - t55 = z16 ^ z17; - t56 = z12 ^ t48; - t57 = t50 ^ t53; - t58 = z4 ^ t46; - t59 = z3 ^ t54; - t60 = t46 ^ t57; - t61 = z14 ^ t57; - t62 = t52 ^ t58; - t63 = t49 ^ t58; - t64 = z4 ^ t59; - t65 = t61 ^ t62; - t66 = z1 ^ t63; - s0 = t59 ^ t63; - s6 = t56 ^ ~t62; - s7 = t48 ^ ~t60; - t67 = t64 ^ t65; - s3 = t53 ^ t66; - s4 = t51 ^ t66; - s5 = t47 ^ t65; - s1 = t64 ^ ~s3; - s2 = t55 ^ ~t67; - - q[7] = s0; - q[6] = s1; - q[5] = s2; - q[4] = s3; - q[3] = s4; - q[2] = s5; - q[1] = s6; - q[0] = s7; -} - -static void br_aes_ct_bitslice_Sbox(uint32_t *q) { - /* - * This S-box implementation is a straightforward translation of - * the circuit described by Boyar and Peralta in "A new - * combinational logic minimization technique with applications - * to cryptology" (https://eprint.iacr.org/2009/191.pdf). - * - * Note that variables x* (input) and s* (output) are numbered - * in "reverse" order (x0 is the high bit, x7 is the low bit). - */ - - uint32_t x0, x1, x2, x3, x4, x5, x6, x7; - uint32_t y1, y2, y3, y4, y5, y6, y7, y8, y9; - uint32_t y10, y11, y12, y13, y14, y15, y16, y17, y18, y19; - uint32_t y20, y21; - uint32_t z0, z1, z2, z3, z4, z5, z6, z7, z8, z9; - uint32_t z10, z11, z12, z13, z14, z15, z16, z17; - uint32_t t0, t1, t2, t3, t4, t5, t6, t7, t8, t9; - uint32_t t10, t11, t12, t13, t14, t15, t16, t17, t18, t19; - uint32_t t20, t21, t22, t23, t24, t25, t26, t27, t28, t29; - uint32_t t30, t31, t32, t33, t34, t35, t36, t37, t38, t39; - uint32_t t40, t41, t42, t43, t44, t45, t46, t47, t48, t49; - uint32_t t50, t51, t52, t53, t54, t55, t56, t57, t58, t59; - uint32_t t60, t61, t62, t63, t64, t65, t66, t67; - uint32_t s0, s1, s2, s3, s4, s5, s6, s7; - - x0 = q[7]; - x1 = q[6]; - x2 = q[5]; - x3 = q[4]; - x4 = q[3]; - x5 = q[2]; - x6 = q[1]; - x7 = q[0]; - - /* - * Top linear transformation. - */ - y14 = x3 ^ x5; - y13 = x0 ^ x6; - y9 = x0 ^ x3; - y8 = x0 ^ x5; - t0 = x1 ^ x2; - y1 = t0 ^ x7; - y4 = y1 ^ x3; - y12 = y13 ^ y14; - y2 = y1 ^ x0; - y5 = y1 ^ x6; - y3 = y5 ^ y8; - t1 = x4 ^ y12; - y15 = t1 ^ x5; - y20 = t1 ^ x1; - y6 = y15 ^ x7; - y10 = y15 ^ t0; - y11 = y20 ^ y9; - y7 = x7 ^ y11; - y17 = y10 ^ y11; - y19 = y10 ^ y8; - y16 = t0 ^ y11; - y21 = y13 ^ y16; - y18 = x0 ^ y16; - - /* - * Non-linear section. - */ - t2 = y12 & y15; - t3 = y3 & y6; - t4 = t3 ^ t2; - t5 = y4 & x7; - t6 = t5 ^ t2; - t7 = y13 & y16; - t8 = y5 & y1; - t9 = t8 ^ t7; - t10 = y2 & y7; - t11 = t10 ^ t7; - t12 = y9 & y11; - t13 = y14 & y17; - t14 = t13 ^ t12; - t15 = y8 & y10; - t16 = t15 ^ t12; - t17 = t4 ^ t14; - t18 = t6 ^ t16; - t19 = t9 ^ t14; - t20 = t11 ^ t16; - t21 = t17 ^ y20; - t22 = t18 ^ y19; - t23 = t19 ^ y21; - t24 = t20 ^ y18; - - t25 = t21 ^ t22; - t26 = t21 & t23; - t27 = t24 ^ t26; - t28 = t25 & t27; - t29 = t28 ^ t22; - t30 = t23 ^ t24; - t31 = t22 ^ t26; - t32 = t31 & t30; - t33 = t32 ^ t24; - t34 = t23 ^ t33; - t35 = t27 ^ t33; - t36 = t24 & t35; - t37 = t36 ^ t34; - t38 = t27 ^ t36; - t39 = t29 & t38; - t40 = t25 ^ t39; - - t41 = t40 ^ t37; - t42 = t29 ^ t33; - t43 = t29 ^ t40; - t44 = t33 ^ t37; - t45 = t42 ^ t41; - z0 = t44 & y15; - z1 = t37 & y6; - z2 = t33 & x7; - z3 = t43 & y16; - z4 = t40 & y1; - z5 = t29 & y7; - z6 = t42 & y11; - z7 = t45 & y17; - z8 = t41 & y10; - z9 = t44 & y12; - z10 = t37 & y3; - z11 = t33 & y4; - z12 = t43 & y13; - z13 = t40 & y5; - z14 = t29 & y2; - z15 = t42 & y9; - z16 = t45 & y14; - z17 = t41 & y8; - - /* - * Bottom linear transformation. - */ - t46 = z15 ^ z16; - t47 = z10 ^ z11; - t48 = z5 ^ z13; - t49 = z9 ^ z10; - t50 = z2 ^ z12; - t51 = z2 ^ z5; - t52 = z7 ^ z8; - t53 = z0 ^ z3; - t54 = z6 ^ z7; - t55 = z16 ^ z17; - t56 = z12 ^ t48; - t57 = t50 ^ t53; - t58 = z4 ^ t46; - t59 = z3 ^ t54; - t60 = t46 ^ t57; - t61 = z14 ^ t57; - t62 = t52 ^ t58; - t63 = t49 ^ t58; - t64 = z4 ^ t59; - t65 = t61 ^ t62; - t66 = z1 ^ t63; - s0 = t59 ^ t63; - s6 = t56 ^ ~t62; - s7 = t48 ^ ~t60; - t67 = t64 ^ t65; - s3 = t53 ^ t66; - s4 = t51 ^ t66; - s5 = t47 ^ t65; - s1 = t64 ^ ~s3; - s2 = t55 ^ ~t67; - - q[7] = s0; - q[6] = s1; - q[5] = s2; - q[4] = s3; - q[3] = s4; - q[2] = s5; - q[1] = s6; - q[0] = s7; -} - -static void br_aes_ct_ortho(uint32_t *q) { -#define SWAPN_32(cl, ch, s, x, y) do { \ - uint32_t a, b; \ - a = (x); \ - b = (y); \ - (x) = (a & (uint32_t)(cl)) | ((b & (uint32_t)(cl)) << (s)); \ - (y) = ((a & (uint32_t)(ch)) >> (s)) | (b & (uint32_t)(ch)); \ - } while (0) - -#define SWAP2_32(x, y) SWAPN_32(0x55555555, 0xAAAAAAAA, 1, x, y) -#define SWAP4_32(x, y) SWAPN_32(0x33333333, 0xCCCCCCCC, 2, x, y) -#define SWAP8_32(x, y) SWAPN_32(0x0F0F0F0F, 0xF0F0F0F0, 4, x, y) - - SWAP2_32(q[0], q[1]); - SWAP2_32(q[2], q[3]); - SWAP2_32(q[4], q[5]); - SWAP2_32(q[6], q[7]); - - SWAP4_32(q[0], q[2]); - SWAP4_32(q[1], q[3]); - SWAP4_32(q[4], q[6]); - SWAP4_32(q[5], q[7]); - - SWAP8_32(q[0], q[4]); - SWAP8_32(q[1], q[5]); - SWAP8_32(q[2], q[6]); - SWAP8_32(q[3], q[7]); -} - -static inline void add_round_key32(uint32_t *q, const uint32_t *sk) { - q[0] ^= sk[0]; - q[1] ^= sk[1]; - q[2] ^= sk[2]; - q[3] ^= sk[3]; - q[4] ^= sk[4]; - q[5] ^= sk[5]; - q[6] ^= sk[6]; - q[7] ^= sk[7]; -} - -static inline void shift_rows32(uint32_t *q) { - int i; - - for (i = 0; i < 8; i++) { - uint32_t x; - - x = q[i]; - q[i] = (x & 0x000000FF) - | ((x & 0x0000FC00) >> 2) | ((x & 0x00000300) << 6) - | ((x & 0x00F00000) >> 4) | ((x & 0x000F0000) << 4) - | ((x & 0xC0000000) >> 6) | ((x & 0x3F000000) << 2); - } -} - -static inline uint32_t rotr16(uint32_t x) { - return (x << 16) | (x >> 16); -} - -static inline void mix_columns32(uint32_t *q) { - uint32_t q0, q1, q2, q3, q4, q5, q6, q7; - uint32_t r0, r1, r2, r3, r4, r5, r6, r7; - - q0 = q[0]; - q1 = q[1]; - q2 = q[2]; - q3 = q[3]; - q4 = q[4]; - q5 = q[5]; - q6 = q[6]; - q7 = q[7]; - r0 = (q0 >> 8) | (q0 << 24); - r1 = (q1 >> 8) | (q1 << 24); - r2 = (q2 >> 8) | (q2 << 24); - r3 = (q3 >> 8) | (q3 << 24); - r4 = (q4 >> 8) | (q4 << 24); - r5 = (q5 >> 8) | (q5 << 24); - r6 = (q6 >> 8) | (q6 << 24); - r7 = (q7 >> 8) | (q7 << 24); - - q[0] = q7 ^ r7 ^ r0 ^ rotr16(q0 ^ r0); - q[1] = q0 ^ r0 ^ q7 ^ r7 ^ r1 ^ rotr16(q1 ^ r1); - q[2] = q1 ^ r1 ^ r2 ^ rotr16(q2 ^ r2); - q[3] = q2 ^ r2 ^ q7 ^ r7 ^ r3 ^ rotr16(q3 ^ r3); - q[4] = q3 ^ r3 ^ q7 ^ r7 ^ r4 ^ rotr16(q4 ^ r4); - q[5] = q4 ^ r4 ^ r5 ^ rotr16(q5 ^ r5); - q[6] = q5 ^ r5 ^ r6 ^ rotr16(q6 ^ r6); - q[7] = q6 ^ r6 ^ r7 ^ rotr16(q7 ^ r7); -} - -static void br_aes_ct64_ortho(uint64_t *q) { -#define SWAPN(cl, ch, s, x, y) do { \ - uint64_t a, b; \ - a = (x); \ - b = (y); \ - (x) = (a & (uint64_t)(cl)) | ((b & (uint64_t)(cl)) << (s)); \ - (y) = ((a & (uint64_t)(ch)) >> (s)) | (b & (uint64_t)(ch)); \ - } while (0) - -#define SWAP2(x, y) SWAPN(0x5555555555555555, 0xAAAAAAAAAAAAAAAA, 1, x, y) -#define SWAP4(x, y) SWAPN(0x3333333333333333, 0xCCCCCCCCCCCCCCCC, 2, x, y) -#define SWAP8(x, y) SWAPN(0x0F0F0F0F0F0F0F0F, 0xF0F0F0F0F0F0F0F0, 4, x, y) - - SWAP2(q[0], q[1]); - SWAP2(q[2], q[3]); - SWAP2(q[4], q[5]); - SWAP2(q[6], q[7]); - - SWAP4(q[0], q[2]); - SWAP4(q[1], q[3]); - SWAP4(q[4], q[6]); - SWAP4(q[5], q[7]); - - SWAP8(q[0], q[4]); - SWAP8(q[1], q[5]); - SWAP8(q[2], q[6]); - SWAP8(q[3], q[7]); -} - - -static void br_aes_ct64_interleave_in(uint64_t *q0, uint64_t *q1, const uint32_t *w) { - uint64_t x0, x1, x2, x3; - - x0 = w[0]; - x1 = w[1]; - x2 = w[2]; - x3 = w[3]; - x0 |= (x0 << 16); - x1 |= (x1 << 16); - x2 |= (x2 << 16); - x3 |= (x3 << 16); - x0 &= (uint64_t)0x0000FFFF0000FFFF; - x1 &= (uint64_t)0x0000FFFF0000FFFF; - x2 &= (uint64_t)0x0000FFFF0000FFFF; - x3 &= (uint64_t)0x0000FFFF0000FFFF; - x0 |= (x0 << 8); - x1 |= (x1 << 8); - x2 |= (x2 << 8); - x3 |= (x3 << 8); - x0 &= (uint64_t)0x00FF00FF00FF00FF; - x1 &= (uint64_t)0x00FF00FF00FF00FF; - x2 &= (uint64_t)0x00FF00FF00FF00FF; - x3 &= (uint64_t)0x00FF00FF00FF00FF; - *q0 = x0 | (x2 << 8); - *q1 = x1 | (x3 << 8); -} - - -static void br_aes_ct64_interleave_out(uint32_t *w, uint64_t q0, uint64_t q1) { - uint64_t x0, x1, x2, x3; - - x0 = q0 & (uint64_t)0x00FF00FF00FF00FF; - x1 = q1 & (uint64_t)0x00FF00FF00FF00FF; - x2 = (q0 >> 8) & (uint64_t)0x00FF00FF00FF00FF; - x3 = (q1 >> 8) & (uint64_t)0x00FF00FF00FF00FF; - x0 |= (x0 >> 8); - x1 |= (x1 >> 8); - x2 |= (x2 >> 8); - x3 |= (x3 >> 8); - x0 &= (uint64_t)0x0000FFFF0000FFFF; - x1 &= (uint64_t)0x0000FFFF0000FFFF; - x2 &= (uint64_t)0x0000FFFF0000FFFF; - x3 &= (uint64_t)0x0000FFFF0000FFFF; - w[0] = (uint32_t)x0 | (uint32_t)(x0 >> 16); - w[1] = (uint32_t)x1 | (uint32_t)(x1 >> 16); - w[2] = (uint32_t)x2 | (uint32_t)(x2 >> 16); - w[3] = (uint32_t)x3 | (uint32_t)(x3 >> 16); -} - -static inline void add_round_key(uint64_t *q, const uint64_t *sk) { - q[0] ^= sk[0]; - q[1] ^= sk[1]; - q[2] ^= sk[2]; - q[3] ^= sk[3]; - q[4] ^= sk[4]; - q[5] ^= sk[5]; - q[6] ^= sk[6]; - q[7] ^= sk[7]; -} - -static inline void shift_rows(uint64_t *q) { - int i; - - for (i = 0; i < 8; i++) { - uint64_t x; - - x = q[i]; - q[i] = (x & (uint64_t)0x000000000000FFFF) - | ((x & (uint64_t)0x00000000FFF00000) >> 4) - | ((x & (uint64_t)0x00000000000F0000) << 12) - | ((x & (uint64_t)0x0000FF0000000000) >> 8) - | ((x & (uint64_t)0x000000FF00000000) << 8) - | ((x & (uint64_t)0xF000000000000000) >> 12) - | ((x & (uint64_t)0x0FFF000000000000) << 4); - } -} - -static inline uint64_t rotr32(uint64_t x) { - return (x << 32) | (x >> 32); -} - -static inline void mix_columns(uint64_t *q) { - uint64_t q0, q1, q2, q3, q4, q5, q6, q7; - uint64_t r0, r1, r2, r3, r4, r5, r6, r7; - - q0 = q[0]; - q1 = q[1]; - q2 = q[2]; - q3 = q[3]; - q4 = q[4]; - q5 = q[5]; - q6 = q[6]; - q7 = q[7]; - r0 = (q0 >> 16) | (q0 << 48); - r1 = (q1 >> 16) | (q1 << 48); - r2 = (q2 >> 16) | (q2 << 48); - r3 = (q3 >> 16) | (q3 << 48); - r4 = (q4 >> 16) | (q4 << 48); - r5 = (q5 >> 16) | (q5 << 48); - r6 = (q6 >> 16) | (q6 << 48); - r7 = (q7 >> 16) | (q7 << 48); - - q[0] = q7 ^ r7 ^ r0 ^ rotr32(q0 ^ r0); - q[1] = q0 ^ r0 ^ q7 ^ r7 ^ r1 ^ rotr32(q1 ^ r1); - q[2] = q1 ^ r1 ^ r2 ^ rotr32(q2 ^ r2); - q[3] = q2 ^ r2 ^ q7 ^ r7 ^ r3 ^ rotr32(q3 ^ r3); - q[4] = q3 ^ r3 ^ q7 ^ r7 ^ r4 ^ rotr32(q4 ^ r4); - q[5] = q4 ^ r4 ^ r5 ^ rotr32(q5 ^ r5); - q[6] = q5 ^ r5 ^ r6 ^ rotr32(q6 ^ r6); - q[7] = q6 ^ r6 ^ r7 ^ rotr32(q7 ^ r7); -} - -static void interleave_constant(uint64_t *out, const unsigned char *in) { - uint32_t tmp_32_constant[16]; - int i; - - br_range_dec32le(tmp_32_constant, 16, in); - for (i = 0; i < 4; i++) { - br_aes_ct64_interleave_in(&out[i], &out[i + 4], tmp_32_constant + (i << 2)); - } - br_aes_ct64_ortho(out); -} - -static void interleave_constant32(uint32_t *out, const unsigned char *in) { - int i; - for (i = 0; i < 4; i++) { - out[2 * i] = br_dec32le(in + 4 * i); - out[2 * i + 1] = br_dec32le(in + 4 * i + 16); - } - br_aes_ct_ortho(out); -} - -void tweak_constants(spx_ctx *ctx) { - unsigned char buf[40 * 16]; - int i; - - /* Use the standard constants to generate tweaked ones. */ - memcpy((uint8_t *)ctx->tweaked512_rc64, (uint8_t *)haraka512_rc64, 40 * 16); - - /* Constants for pk.seed */ - haraka_S(buf, 40 * 16, ctx->pub_seed, SPX_N, ctx); - for (i = 0; i < 10; i++) { - interleave_constant32(ctx->tweaked256_rc32[i], buf + 32 * i); - interleave_constant(ctx->tweaked512_rc64[i], buf + 64 * i); - } -} - -static void haraka_S_absorb(unsigned char *s, unsigned int r, - const unsigned char *m, unsigned long long mlen, - unsigned char p, const spx_ctx *ctx) { - unsigned long long i; - PQCLEAN_VLA(uint8_t, t, r); - - while (mlen >= r) { - /* XOR block to state */ - for (i = 0; i < r; ++i) { - s[i] ^= m[i]; - } - haraka512_perm(s, s, ctx); - 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; ++i) { - s[i] ^= t[i]; - } -} - -static void haraka_S_squeezeblocks(unsigned char *h, unsigned long long nblocks, - unsigned char *s, unsigned int r, - const spx_ctx *ctx) { - while (nblocks > 0) { - haraka512_perm(s, s, ctx); - memcpy(h, s, HARAKAS_RATE); - h += r; - nblocks--; - } -} - -void haraka_S_inc_init(uint8_t *s_inc) { - size_t i; - - for (i = 0; i < 64; i++) { - s_inc[i] = 0; - } - s_inc[64] = 0; -} - -void haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, - const spx_ctx *ctx) { - size_t i; - - /* Recall that s_inc[64] is the non-absorbed bytes xored into the state */ - while (mlen + s_inc[64] >= HARAKAS_RATE) { - for (i = 0; i < (size_t)(HARAKAS_RATE - s_inc[64]); i++) { - /* Take the i'th byte from message - xor with the s_inc[64] + i'th byte of the state */ - s_inc[s_inc[64] + i] ^= m[i]; - } - mlen -= (size_t)(HARAKAS_RATE - s_inc[64]); - m += HARAKAS_RATE - (uint8_t)s_inc[64]; - s_inc[64] = 0; - - haraka512_perm(s_inc, s_inc, ctx); - } - - for (i = 0; i < mlen; i++) { - s_inc[s_inc[64] + i] ^= m[i]; - } - s_inc[64] += (uint8_t)mlen; -} - -void haraka_S_inc_finalize(uint8_t *s_inc) { - /* After haraka_S_inc_absorb, we are guaranteed that s_inc[64] < HARAKAS_RATE, - so we can always use one more byte for p in the current state. */ - s_inc[s_inc[64]] ^= 0x1F; - s_inc[HARAKAS_RATE - 1] ^= 128; - s_inc[64] = 0; -} - -void haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, - const spx_ctx *ctx) { - size_t i; - - /* First consume any bytes we still have sitting around */ - for (i = 0; i < outlen && i < s_inc[64]; i++) { - /* There are s_inc[64] bytes left, so r - s_inc[64] is the first - available byte. We consume from there, i.e., up to r. */ - out[i] = (uint8_t)s_inc[(HARAKAS_RATE - s_inc[64] + i)]; - } - out += i; - outlen -= i; - s_inc[64] -= (uint8_t)i; - - /* Then squeeze the remaining necessary blocks */ - while (outlen > 0) { - haraka512_perm(s_inc, s_inc, ctx); - - for (i = 0; i < outlen && i < HARAKAS_RATE; i++) { - out[i] = s_inc[i]; - } - out += i; - outlen -= i; - s_inc[64] = (uint8_t)(HARAKAS_RATE - i); - } -} - -void haraka_S(unsigned char *out, unsigned long long outlen, - const unsigned char *in, unsigned long long inlen, - const spx_ctx *ctx) { - unsigned long long i; - unsigned char s[64]; - unsigned char d[32]; - - for (i = 0; i < 64; i++) { - s[i] = 0; - } - haraka_S_absorb(s, 32, in, inlen, 0x1F, ctx); - - haraka_S_squeezeblocks(out, outlen / 32, s, 32, ctx); - out += (outlen / 32) * 32; - - if (outlen % 32) { - haraka_S_squeezeblocks(d, 1, s, 32, ctx); - for (i = 0; i < outlen % 32; i++) { - out[i] = d[i]; - } - } -} - -void haraka512_perm(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx) { - uint32_t w[16]; - uint64_t q[8], tmp_q; - unsigned int i, j; - - br_range_dec32le(w, 16, in); - for (i = 0; i < 4; i++) { - br_aes_ct64_interleave_in(&q[i], &q[i + 4], w + (i << 2)); - } - br_aes_ct64_ortho(q); - - /* AES rounds */ - for (i = 0; i < 5; i++) { - for (j = 0; j < 2; j++) { - br_aes_ct64_bitslice_Sbox(q); - shift_rows(q); - mix_columns(q); - add_round_key(q, ctx->tweaked512_rc64[2 * i + j]); - } - /* Mix states */ - for (j = 0; j < 8; j++) { - tmp_q = q[j]; - q[j] = (tmp_q & 0x0001000100010001) << 5 | - (tmp_q & 0x0002000200020002) << 12 | - (tmp_q & 0x0004000400040004) >> 1 | - (tmp_q & 0x0008000800080008) << 6 | - (tmp_q & 0x0020002000200020) << 9 | - (tmp_q & 0x0040004000400040) >> 4 | - (tmp_q & 0x0080008000800080) << 3 | - (tmp_q & 0x2100210021002100) >> 5 | - (tmp_q & 0x0210021002100210) << 2 | - (tmp_q & 0x0800080008000800) << 4 | - (tmp_q & 0x1000100010001000) >> 12 | - (tmp_q & 0x4000400040004000) >> 10 | - (tmp_q & 0x8400840084008400) >> 3; - } - } - - br_aes_ct64_ortho(q); - for (i = 0; i < 4; i ++) { - br_aes_ct64_interleave_out(w + (i << 2), q[i], q[i + 4]); - } - br_range_enc32le(out, w, 16); -} - -void haraka512(unsigned char *out, const unsigned char *in, const spx_ctx *ctx) { - int i; - - unsigned char buf[64]; - - haraka512_perm(buf, in, ctx); - /* Feed-forward */ - for (i = 0; i < 64; i++) { - buf[i] = buf[i] ^ in[i]; - } - - /* Truncated */ - memcpy(out, buf + 8, 8); - memcpy(out + 8, buf + 24, 8); - memcpy(out + 16, buf + 32, 8); - memcpy(out + 24, buf + 48, 8); -} - - -void haraka256(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx) { - uint32_t q[8], tmp_q; - int i, j; - - for (i = 0; i < 4; i++) { - q[2 * i] = br_dec32le(in + 4 * i); - q[2 * i + 1] = br_dec32le(in + 4 * i + 16); - } - br_aes_ct_ortho(q); - - /* AES rounds */ - for (i = 0; i < 5; i++) { - for (j = 0; j < 2; j++) { - br_aes_ct_bitslice_Sbox(q); - shift_rows32(q); - mix_columns32(q); - add_round_key32(q, ctx->tweaked256_rc32[2 * i + j]); - } - - /* Mix states */ - for (j = 0; j < 8; j++) { - tmp_q = q[j]; - q[j] = (tmp_q & 0x81818181) | - (tmp_q & 0x02020202) << 1 | - (tmp_q & 0x04040404) << 2 | - (tmp_q & 0x08080808) << 3 | - (tmp_q & 0x10101010) >> 3 | - (tmp_q & 0x20202020) >> 2 | - (tmp_q & 0x40404040) >> 1; - } - } - - br_aes_ct_ortho(q); - for (i = 0; i < 4; i++) { - br_enc32le(out + 4 * i, q[2 * i]); - br_enc32le(out + 4 * i + 16, q[2 * i + 1]); - } - - for (i = 0; i < 32; i++) { - out[i] ^= in[i]; - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/haraka.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/haraka.h deleted file mode 100644 index 737cb6065f..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/haraka.h +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef SPX_HARAKA_H -#define SPX_HARAKA_H - -#include "context.h" -#include "params.h" - -/* Tweak constants with seed */ -#define tweak_constants SPX_NAMESPACE(tweak_constants) -void tweak_constants(spx_ctx *ctx); - -/* Haraka Sponge */ -#define haraka_S_inc_init SPX_NAMESPACE(haraka_S_inc_init) -void haraka_S_inc_init(uint8_t *s_inc); -#define haraka_S_inc_absorb SPX_NAMESPACE(haraka_S_inc_absorb) -void haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, - const spx_ctx *ctx); -#define haraka_S_inc_finalize SPX_NAMESPACE(haraka_S_inc_finalize) -void haraka_S_inc_finalize(uint8_t *s_inc); -#define haraka_S_inc_squeeze SPX_NAMESPACE(haraka_S_inc_squeeze) -void haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, - const spx_ctx *ctx); -#define haraka_S SPX_NAMESPACE(haraka_S) -void haraka_S(unsigned char *out, unsigned long long outlen, - const unsigned char *in, unsigned long long inlen, - const spx_ctx *ctx); - -/* Applies the 512-bit Haraka permutation to in. */ -#define haraka512_perm SPX_NAMESPACE(haraka512_perm) -void haraka512_perm(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx); - -/* Implementation of Haraka-512 */ -#define haraka512 SPX_NAMESPACE(haraka512) -void haraka512(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx); - -/* Implementation of Haraka-256 */ -#define haraka256 SPX_NAMESPACE(haraka256) -void haraka256(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/haraka_offsets.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/haraka_offsets.h deleted file mode 100644 index 7c062272a0..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/haraka_offsets.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef HARAKA_OFFSETS_H_ -#define HARAKA_OFFSETS_H_ - -/* - * Offsets of various fields in the address structure when we use Haraka as - * the Sphincs+ hash function - */ - -#define SPX_OFFSET_LAYER 3 /* The byte used to specify the Merkle tree layer */ -#define SPX_OFFSET_TREE 8 /* The start of the 8 byte field used to specify the tree */ -#define SPX_OFFSET_TYPE 19 /* The byte used to specify the hash type (reason) */ -#define SPX_OFFSET_KP_ADDR2 22 /* The high byte used to specify the key pair (which one-time signature) */ -#define SPX_OFFSET_KP_ADDR1 23 /* The low byte used to specify the key pair */ -#define SPX_OFFSET_CHAIN_ADDR 27 /* The byte used to specify the chain address (which Winternitz chain) */ -#define SPX_OFFSET_HASH_ADDR 31 /* The byte used to specify the hash address (where in the Winternitz chain) */ -#define SPX_OFFSET_TREE_HGT 27 /* The byte used to specify the height of this node in the FORS or Merkle tree */ -#define SPX_OFFSET_TREE_INDEX 28 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ - -#define SPX_HARAKA 1 - -#endif /* HARAKA_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/hash.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/hash.h deleted file mode 100644 index f7c87d4c3c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/hash.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef SPX_HASH_H -#define SPX_HASH_H - -#include -#include - -#include "context.h" -#include "params.h" - -#define prf_addr SPX_NAMESPACE(prf_addr) -void prf_addr(unsigned char *out, const spx_ctx *ctx, - const uint32_t addr[8]); - -#define gen_message_random SPX_NAMESPACE(gen_message_random) -void gen_message_random(unsigned char *R, const unsigned char *sk_prf, - const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx); - -#define hash_message SPX_NAMESPACE(hash_message) -void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx); - - - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/hash_haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/hash_haraka.c deleted file mode 100644 index 750a67423b..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/hash_haraka.c +++ /dev/null @@ -1,81 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "utils.h" - -#include "haraka.h" -#include "hash.h" - -/* - * Computes PRF(key, addr), given a secret key of SPX_N bytes and an address - */ -void prf_addr(unsigned char *out, const spx_ctx *ctx, - const uint32_t addr[8]) { - /* Since SPX_N may be smaller than 32, we need temporary buffers. */ - unsigned char outbuf[32]; - unsigned char buf[64] = {0}; - - memcpy(buf, addr, SPX_ADDR_BYTES); - memcpy(buf + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); - - haraka512(outbuf, (const void *)buf, ctx); - memcpy(out, outbuf, SPX_N); -} - -/** - * Computes the message-dependent randomness R, using a secret seed and an - * optional randomization value as well as the message. - */ -void gen_message_random(unsigned char *R, const unsigned char *sk_prf, - const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx) { - uint8_t s_inc[65]; - - haraka_S_inc_init(s_inc); - haraka_S_inc_absorb(s_inc, sk_prf, SPX_N, ctx); - haraka_S_inc_absorb(s_inc, optrand, SPX_N, ctx); - haraka_S_inc_absorb(s_inc, m, mlen, ctx); - haraka_S_inc_finalize(s_inc); - haraka_S_inc_squeeze(R, SPX_N, s_inc, ctx); -} - -/** - * Computes the message hash using R, the public key, and the message. - * Outputs the message digest and the index of the leaf. The index is split in - * the tree index and the leaf index, for convenient copying to an address. - */ -void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx) { -#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) -#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) -#define SPX_LEAF_BITS SPX_TREE_HEIGHT -#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) -#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) - - unsigned char buf[SPX_DGST_BYTES]; - unsigned char *bufp = buf; - uint8_t s_inc[65]; - - haraka_S_inc_init(s_inc); - haraka_S_inc_absorb(s_inc, R, SPX_N, ctx); - haraka_S_inc_absorb(s_inc, pk + SPX_N, SPX_N, ctx); // Only absorb root part of pk - haraka_S_inc_absorb(s_inc, m, mlen, ctx); - haraka_S_inc_finalize(s_inc); - haraka_S_inc_squeeze(buf, SPX_DGST_BYTES, s_inc, ctx); - - memcpy(digest, bufp, SPX_FORS_MSG_BYTES); - bufp += SPX_FORS_MSG_BYTES; - - - *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); - *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); - bufp += SPX_TREE_BYTES; - - *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); - *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/merkle.c b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/merkle.c deleted file mode 100644 index 0c1479fd93..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/merkle.c +++ /dev/null @@ -1,59 +0,0 @@ -#include -#include - -#include "address.h" -#include "merkle.h" -#include "params.h" -#include "utils.h" -#include "utilsx1.h" -#include "wots.h" -#include "wotsx1.h" - -/* - * This generates a Merkle signature (WOTS signature followed by the Merkle - * authentication path). This is in this file because most of the complexity - * is involved with the WOTS signature; the Merkle authentication path logic - * is mostly hidden in treehashx4 - */ -void merkle_sign(uint8_t *sig, unsigned char *root, - const spx_ctx *ctx, - uint32_t wots_addr[8], uint32_t tree_addr[8], - uint32_t idx_leaf) { - unsigned char *auth_path = sig + SPX_WOTS_BYTES; - struct leaf_info_x1 info = { 0 }; - unsigned steps[ SPX_WOTS_LEN ]; - - info.wots_sig = sig; - chain_lengths(steps, root); - info.wots_steps = steps; - - set_type(&tree_addr[0], SPX_ADDR_TYPE_HASHTREE); - set_type(&info.pk_addr[0], SPX_ADDR_TYPE_WOTSPK); - copy_subtree_addr(&info.leaf_addr[0], wots_addr); - copy_subtree_addr(&info.pk_addr[0], wots_addr); - - info.wots_sign_leaf = idx_leaf; - - treehashx1(root, auth_path, ctx, - idx_leaf, 0, - SPX_TREE_HEIGHT, - wots_gen_leafx1, - tree_addr, &info); -} - -/* Compute root node of the top-most subtree. */ -void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { - /* We do not need the auth path in key generation, but it simplifies the - code to have just one treehash routine that computes both root and path - in one function. */ - unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; - uint32_t top_tree_addr[8] = {0}; - uint32_t wots_addr[8] = {0}; - - set_layer_addr(top_tree_addr, SPX_D - 1); - set_layer_addr(wots_addr, SPX_D - 1); - - merkle_sign(auth_path, root, ctx, - wots_addr, top_tree_addr, - (uint32_t)~0 /* ~0 means "don't bother generating an auth path */ ); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/merkle.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/merkle.h deleted file mode 100644 index 769cf2e970..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/merkle.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef MERKLE_H_ -#define MERKLE_H_ - -#include - -#include "context.h" -#include "params.h" - -/* Generate a Merkle signature (WOTS signature followed by the Merkle */ -/* authentication path) */ -#define merkle_sign SPX_NAMESPACE(merkle_sign) -void merkle_sign(uint8_t *sig, unsigned char *root, - const spx_ctx *ctx, - uint32_t wots_addr[8], uint32_t tree_addr[8], - uint32_t idx_leaf); - -/* Compute the root node of the top-most subtree. */ -#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) -void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); - -#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/nistapi.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/nistapi.h deleted file mode 100644 index 3cb71afad4..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/nistapi.h +++ /dev/null @@ -1,87 +0,0 @@ -#ifndef SPX_API_H -#define SPX_API_H - -#include -#include - -#include "params.h" - -#define CRYPTO_ALGNAME "SPHINCS+" - -#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES -#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES -#define CRYPTO_BYTES SPX_BYTES -#define CRYPTO_SEEDBYTES (3*SPX_N) - -/* - * Returns the length of a secret key, in bytes - */ -#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) -size_t crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) -size_t crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) -size_t crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) -size_t crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) -int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) -int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) -int crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) -int crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -#define crypto_sign SPX_NAMESPACE(crypto_sign) -int crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) -int crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/params.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/params.h deleted file mode 100644 index b07e7b3c0d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/params.h +++ /dev/null @@ -1,56 +0,0 @@ -#ifndef SPX_PARAMS_H -#define SPX_PARAMS_H - -#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_##s - -/* Hash output length in bytes. */ -#define SPX_N 24 -/* Height of the hypertree. */ -#define SPX_FULL_HEIGHT 63 -/* Number of subtree layer. */ -#define SPX_D 7 -/* FORS tree dimensions. */ -#define SPX_FORS_HEIGHT 14 -#define SPX_FORS_TREES 17 -/* Winternitz parameter, */ -#define SPX_WOTS_W 16 - -/* The hash function is defined by linking a different hash.c file, as opposed - to setting a #define constant. */ - -/* For clarity */ -#define SPX_ADDR_BYTES 32 - -/* WOTS parameters. */ -#define SPX_WOTS_LOGW 4 - -#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) - -/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#define SPX_WOTS_LEN2 3 - -#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) -#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) -#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES - -/* Subtree size. */ -#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) - -//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT -// #error SPX_D should always divide SPX_FULL_HEIGHT -//#endif - -/* FORS parameters. */ -#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) -#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) -#define SPX_FORS_PK_BYTES SPX_N - -/* Resulting SPX sizes. */ -#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ - SPX_FULL_HEIGHT * SPX_N) -#define SPX_PK_BYTES (2 * SPX_N) -#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) - -#include "haraka_offsets.h" - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/sign.c b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/sign.c deleted file mode 100644 index 9d0c7d1b22..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/sign.c +++ /dev/null @@ -1,286 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "context.h" -#include "fors.h" -#include "hash.h" -#include "merkle.h" -#include "nistapi.h" -#include "params.h" -#include "randombytes.h" -#include "thash.h" -#include "utils.h" -#include "wots.h" - -/* - * Returns the length of a secret key, in bytes - */ -size_t crypto_sign_secretkeybytes(void) { - return CRYPTO_SECRETKEYBYTES; -} - -/* - * Returns the length of a public key, in bytes - */ -size_t crypto_sign_publickeybytes(void) { - return CRYPTO_PUBLICKEYBYTES; -} - -/* - * Returns the length of a signature, in bytes - */ -size_t crypto_sign_bytes(void) { - return CRYPTO_BYTES; -} - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t crypto_sign_seedbytes(void) { - return CRYPTO_SEEDBYTES; -} - -/* - * Generates an SPX key pair given a seed of length - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed) { - spx_ctx ctx; - - /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ - memcpy(sk, seed, CRYPTO_SEEDBYTES); - - memcpy(pk, sk + 2 * SPX_N, SPX_N); - - memcpy(ctx.pub_seed, pk, SPX_N); - memcpy(ctx.sk_seed, sk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - /* Compute root node of the top-most subtree. */ - merkle_gen_root(sk + 3 * SPX_N, &ctx); - - // cleanup - free_hash_function(&ctx); - - memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); - - return 0; -} - -/* - * Generates an SPX key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { - uint8_t seed[CRYPTO_SEEDBYTES]; - randombytes(seed, CRYPTO_SEEDBYTES); - crypto_sign_seed_keypair(pk, sk, seed); - - return 0; -} - -/** - * Returns an array containing a detached signature. - */ -int crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - spx_ctx ctx; - - const uint8_t *sk_prf = sk + SPX_N; - const uint8_t *pk = sk + 2 * SPX_N; - - uint8_t optrand[SPX_N]; - uint8_t mhash[SPX_FORS_MSG_BYTES]; - uint8_t root[SPX_N]; - uint32_t i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - - memcpy(ctx.sk_seed, sk, SPX_N); - memcpy(ctx.pub_seed, pk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - set_type(wots_addr, SPX_ADDR_TYPE_WOTS); - set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); - - /* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ - randombytes(optrand, SPX_N); - /* Compute the digest randomization value. */ - gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); - - /* Derive the message digest and leaf index from R, PK and M. */ - hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); - sig += SPX_N; - - set_tree_addr(wots_addr, tree); - set_keypair_addr(wots_addr, idx_leaf); - - /* Sign the message hash using FORS. */ - fors_sign(sig, root, mhash, &ctx, wots_addr); - sig += SPX_FORS_BYTES; - - for (i = 0; i < SPX_D; i++) { - set_layer_addr(tree_addr, i); - set_tree_addr(tree_addr, tree); - - copy_subtree_addr(wots_addr, tree_addr); - set_keypair_addr(wots_addr, idx_leaf); - - merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); - sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); - tree = tree >> SPX_TREE_HEIGHT; - } - - free_hash_function(&ctx); - - *siglen = SPX_BYTES; - - return 0; -} - -/** - * Verifies a detached signature and message under a given public key. - */ -int crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk) { - spx_ctx ctx; - const uint8_t *pub_root = pk + SPX_N; - uint8_t mhash[SPX_FORS_MSG_BYTES]; - uint8_t wots_pk[SPX_WOTS_BYTES]; - uint8_t root[SPX_N]; - uint8_t leaf[SPX_N]; - unsigned int i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - if (siglen != SPX_BYTES) { - return -1; - } - - memcpy(ctx.pub_seed, pk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - set_type(wots_addr, SPX_ADDR_TYPE_WOTS); - set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); - set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); - - /* Derive the message digest and leaf index from R || PK || M. */ - /* The additional SPX_N is a result of the hash domain separator. */ - hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); - sig += SPX_N; - - /* Layer correctly defaults to 0, so no need to set_layer_addr */ - set_tree_addr(wots_addr, tree); - set_keypair_addr(wots_addr, idx_leaf); - - fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); - sig += SPX_FORS_BYTES; - - /* For each subtree.. */ - for (i = 0; i < SPX_D; i++) { - set_layer_addr(tree_addr, i); - set_tree_addr(tree_addr, tree); - - copy_subtree_addr(wots_addr, tree_addr); - set_keypair_addr(wots_addr, idx_leaf); - - copy_keypair_addr(wots_pk_addr, wots_addr); - - /* The WOTS public key is only correct if the signature was correct. */ - /* Initially, root is the FORS pk, but on subsequent iterations it is - the root of the subtree below the currently processed subtree. */ - wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); - sig += SPX_WOTS_BYTES; - - /* Compute the leaf node using the WOTS public key. */ - thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); - - /* Compute the root node of this subtree. */ - compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, - &ctx, tree_addr); - sig += SPX_TREE_HEIGHT * SPX_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); - tree = tree >> SPX_TREE_HEIGHT; - } - - // cleanup - free_hash_function(&ctx); - - /* Check if the root node equals the root node in the public key. */ - if (memcmp(root, pub_root, SPX_N) != 0) { - return -1; - } - - return 0; -} - - -/** - * Returns an array containing the signature followed by the message. - */ -int crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk) { - size_t siglen; - - crypto_sign_signature(sm, &siglen, m, mlen, sk); - - memmove(sm + SPX_BYTES, m, mlen); - *smlen = siglen + mlen; - - return 0; -} - -/** - * Verifies a given signature-message pair under a given public key. - */ -int crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk) { - /* The API caller does not necessarily know what size a signature should be - but SPHINCS+ signatures are always exactly SPX_BYTES. */ - if (smlen < SPX_BYTES) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - *mlen = smlen - SPX_BYTES; - - if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - /* If verification was successful, move the message to the right place. */ - memmove(m, sm + SPX_BYTES, *mlen); - - return 0; -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/thash.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/thash.h deleted file mode 100644 index 8687ccfb4d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/thash.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef SPX_THASH_H -#define SPX_THASH_H - -#include "context.h" -#include "params.h" - -#include - -#define thash SPX_NAMESPACE(thash) -void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/thash_haraka_robust.c b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/thash_haraka_robust.c deleted file mode 100644 index 109502cbc2..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/thash_haraka_robust.c +++ /dev/null @@ -1,45 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "thash.h" -#include "utils.h" - -#include "haraka.h" - -/** - * Takes an array of inblocks concatenated arrays of SPX_N bytes. - */ -void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]) { - PQCLEAN_VLA(uint8_t, buf, SPX_ADDR_BYTES + inblocks * SPX_N); - PQCLEAN_VLA(uint8_t, bitmask, inblocks * SPX_N); - unsigned char outbuf[32]; - unsigned char buf_tmp[64]; - unsigned int i; - - if (inblocks == 1) { - /* F function */ - /* Since SPX_N may be smaller than 32, we need a temporary buffer. */ - memset(buf_tmp, 0, 64); - memcpy(buf_tmp, addr, 32); - - haraka256(outbuf, buf_tmp, ctx); - for (i = 0; i < inblocks * SPX_N; i++) { - buf_tmp[SPX_ADDR_BYTES + i] = in[i] ^ outbuf[i]; - } - haraka512(outbuf, buf_tmp, ctx); - memcpy(out, outbuf, SPX_N); - } else { - /* All other tweakable hashes*/ - memcpy(buf, addr, 32); - haraka_S(bitmask, inblocks * SPX_N, buf, SPX_ADDR_BYTES, ctx); - - for (i = 0; i < inblocks * SPX_N; i++) { - buf[SPX_ADDR_BYTES + i] = in[i] ^ bitmask[i]; - } - - haraka_S(out, SPX_N, buf, SPX_ADDR_BYTES + inblocks * SPX_N, ctx); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/utils.c b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/utils.c deleted file mode 100644 index 177b541fb9..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/utils.c +++ /dev/null @@ -1,148 +0,0 @@ -#include - -#include "utils.h" - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "thash.h" - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void ull_to_bytes(unsigned char *out, unsigned int outlen, - unsigned long long in) { - int i; - - /* Iterate over out in decreasing order, for big-endianness. */ - for (i = (signed int)outlen - 1; i >= 0; i--) { - out[i] = in & 0xff; - in = in >> 8; - } -} - -void u32_to_bytes(unsigned char *out, uint32_t in) { - out[0] = (unsigned char)(in >> 24); - out[1] = (unsigned char)(in >> 16); - out[2] = (unsigned char)(in >> 8); - out[3] = (unsigned char)in; -} - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { - unsigned long long retval = 0; - unsigned int i; - - for (i = 0; i < inlen; i++) { - retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); - } - return retval; -} - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void compute_root(unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const spx_ctx *ctx, uint32_t addr[8]) { - uint32_t i; - unsigned char buffer[2 * SPX_N]; - - /* If leaf_idx is odd (last bit = 1), current path element is a right child - and auth_path has to go left. Otherwise it is the other way around. */ - if (leaf_idx & 1) { - memcpy(buffer + SPX_N, leaf, SPX_N); - memcpy(buffer, auth_path, SPX_N); - } else { - memcpy(buffer, leaf, SPX_N); - memcpy(buffer + SPX_N, auth_path, SPX_N); - } - auth_path += SPX_N; - - for (i = 0; i < tree_height - 1; i++) { - leaf_idx >>= 1; - idx_offset >>= 1; - /* Set the address of the node we're creating. */ - set_tree_height(addr, i + 1); - set_tree_index(addr, leaf_idx + idx_offset); - - /* Pick the right or left neighbor, depending on parity of the node. */ - if (leaf_idx & 1) { - thash(buffer + SPX_N, buffer, 2, ctx, addr); - memcpy(buffer, auth_path, SPX_N); - } else { - thash(buffer, buffer, 2, ctx, addr); - memcpy(buffer + SPX_N, auth_path, SPX_N); - } - auth_path += SPX_N; - } - - /* The last iteration is exceptional; we do not copy an auth_path node. */ - leaf_idx >>= 1; - idx_offset >>= 1; - set_tree_height(addr, tree_height); - set_tree_index(addr, leaf_idx + idx_offset); - thash(root, buffer, 2, ctx, addr); -} - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const spx_ctx * /* ctx */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), - uint32_t tree_addr[8]) { - PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); - PQCLEAN_VLA(unsigned int, heights, tree_height + 1); - unsigned int offset = 0; - uint32_t idx; - uint32_t tree_idx; - - for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { - /* Add the next leaf node to the stack. */ - gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); - offset++; - heights[offset - 1] = 0; - - /* If this is a node we need for the auth path.. */ - if ((leaf_idx ^ 0x1) == idx) { - memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); - } - - /* While the top-most nodes are of equal height.. */ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { - /* Compute index of the new node, in the next layer. */ - tree_idx = (idx >> (heights[offset - 1] + 1)); - - /* Set the address of the node we're creating. */ - set_tree_height(tree_addr, heights[offset - 1] + 1); - set_tree_index(tree_addr, - tree_idx + (idx_offset >> (heights[offset - 1] + 1))); - /* Hash the top-most nodes from the stack together. */ - thash(stack + (offset - 2)*SPX_N, - stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); - offset--; - /* Note that the top-most node is now one layer higher. */ - heights[offset - 1]++; - - /* If this is a node we need for the auth path.. */ - if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_path + heights[offset - 1]*SPX_N, - stack + (offset - 1)*SPX_N, SPX_N); - } - } - } - memcpy(root, stack, SPX_N); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/utils.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/utils.h deleted file mode 100644 index 64f5d5a53a..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/utils.h +++ /dev/null @@ -1,58 +0,0 @@ -#ifndef SPX_UTILS_H -#define SPX_UTILS_H - -#include - -#include "compat.h" -#include "context.h" -#include "params.h" - - -/* To support MSVC use alloca() instead of VLAs. See #20. */ - - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) -void ull_to_bytes(unsigned char *out, unsigned int outlen, - unsigned long long in); -#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) -void u32_to_bytes(unsigned char *out, uint32_t in); - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) -unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -#define compute_root SPX_NAMESPACE(compute_root) -void compute_root(unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const spx_ctx *ctx, uint32_t addr[8]); - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -#define treehash SPX_NAMESPACE(treehash) -void treehash(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const spx_ctx *ctx /* ctx */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), - uint32_t tree_addr[8]); - - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/utilsx1.c b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/utilsx1.c deleted file mode 100644 index fccb69b35d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/utilsx1.c +++ /dev/null @@ -1,100 +0,0 @@ -#include - -#include "utilsx1.h" - -#include "address.h" -#include "params.h" -#include "thash.h" -#include "utils.h" - -/* - * Generate the entire Merkle tree, computing the authentication path for - * leaf_idx, and the resulting root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) - * - * This expects tree_addr to be initialized to the addr structures for the - * Merkle tree nodes - * - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - * - * This works by using the standard Merkle tree building algorithm, - */ -void treehashx1(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, - uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* Where to write the leaves */, - const spx_ctx * /* ctx */, - uint32_t idx, void *info), - uint32_t tree_addr[8], - void *info) { - /* This is where we keep the intermediate nodes */ - PQCLEAN_VLA(uint8_t, stack, tree_height * SPX_N); - - uint32_t idx; - uint32_t max_idx = (uint32_t)((1 << tree_height) - 1); - for (idx = 0;; idx++) { - unsigned char current[2 * SPX_N]; /* Current logical node is at */ - /* index[SPX_N]. We do this to minimize the number of copies */ - /* needed during a thash */ - gen_leaf( ¤t[SPX_N], ctx, idx + idx_offset, - info ); - - /* Now combine the freshly generated right node with previously */ - /* generated left ones */ - uint32_t internal_idx_offset = idx_offset; - uint32_t internal_idx = idx; - uint32_t internal_leaf = leaf_idx; - uint32_t h; /* The height we are in the Merkle tree */ - for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { - - /* Check if we hit the top of the tree */ - if (h == tree_height) { - /* We hit the root; return it */ - memcpy( root, ¤t[SPX_N], SPX_N ); - return; - } - - /* - * Check if the node we have is a part of the - * authentication path; if it is, write it out - */ - if ((internal_idx ^ internal_leaf) == 0x01) { - memcpy( &auth_path[ h * SPX_N ], - ¤t[SPX_N], - SPX_N ); - } - - /* - * Check if we're at a left child; if so, stop going up the stack - * Exception: if we've reached the end of the tree, keep on going - * (so we combine the last 4 nodes into the one root node in two - * more iterations) - */ - if ((internal_idx & 1) == 0 && idx < max_idx) { - break; - } - - /* Ok, we're at a right node */ - /* Now combine the left and right logical nodes together */ - - /* Set the address of the node we're creating. */ - internal_idx_offset >>= 1; - set_tree_height(tree_addr, h + 1); - set_tree_index(tree_addr, internal_idx / 2 + internal_idx_offset ); - - unsigned char *left = &stack[h * SPX_N]; - memcpy( ¤t[0], left, SPX_N ); - thash( ¤t[1 * SPX_N], - ¤t[0 * SPX_N], - 2, ctx, tree_addr); - } - - /* We've hit a left child; save the current for when we get the */ - /* corresponding right right */ - memcpy( &stack[h * SPX_N], ¤t[SPX_N], SPX_N); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/utilsx1.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/utilsx1.h deleted file mode 100644 index e911d17d53..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/utilsx1.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef SPX_UTILSX4_H -#define SPX_UTILSX4_H - -#include - -#include "context.h" -#include "params.h" - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -#define treehashx1 SPX_NAMESPACE(treehashx1) -void treehashx1(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* Where to write the leaf */, - const spx_ctx * /* ctx */, - uint32_t addr_idx, void *info), - uint32_t tree_addrx4[8], void *info); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/wots.c b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/wots.c deleted file mode 100644 index 249717aaa8..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/wots.c +++ /dev/null @@ -1,108 +0,0 @@ -#include -#include - -#include "wots.h" -#include "wotsx1.h" - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "thash.h" -#include "utils.h" -#include "utilsx1.h" - -// TODO clarify address expectations, and make them more uniform. -// TODO i.e. do we expect types to be set already? -// TODO and do we expect modifications or copies? - -/** - * Computes the chaining function. - * out and in have to be n-byte arrays. - * - * Interprets in as start-th value of the chain. - * addr has to contain the address of the chain. - */ -static void gen_chain(unsigned char *out, const unsigned char *in, - unsigned int start, unsigned int steps, - const spx_ctx *ctx, uint32_t addr[8]) { - uint32_t i; - - /* Initialize out with the value at position 'start'. */ - memcpy(out, in, SPX_N); - - /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < SPX_WOTS_W; i++) { - set_hash_addr(addr, i); - thash(out, out, 1, ctx, addr); - } -} - -/** - * base_w algorithm as described in draft. - * Interprets an array of bytes as integers in base w. - * This only works when log_w is a divisor of 8. - */ -static void base_w(unsigned int *output, const int out_len, - const unsigned char *input) { - int in = 0; - int out = 0; - unsigned char total = 0; - int bits = 0; - int consumed; - - for (consumed = 0; consumed < out_len; consumed++) { - if (bits == 0) { - total = input[in]; - in++; - bits += 8; - } - bits -= SPX_WOTS_LOGW; - output[out] = (total >> bits) & (SPX_WOTS_W - 1); - out++; - } -} - -/* Computes the WOTS+ checksum over a message (in base_w). */ -static void wots_checksum(unsigned int *csum_base_w, - const unsigned int *msg_base_w) { - unsigned int csum = 0; - unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; - unsigned int i; - - /* Compute checksum. */ - for (i = 0; i < SPX_WOTS_LEN1; i++) { - csum += SPX_WOTS_W - 1 - msg_base_w[i]; - } - - /* Convert checksum to base_w. */ - /* Make sure expected empty zero bits are the least significant bits. */ - csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); - ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); - base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); -} - -/* Takes a message and derives the matching chain lengths. */ -void chain_lengths(unsigned int *lengths, const unsigned char *msg) { - base_w(lengths, SPX_WOTS_LEN1, msg); - wots_checksum(lengths + SPX_WOTS_LEN1, lengths); -} - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const spx_ctx *ctx, uint32_t addr[8]) { - unsigned int lengths[SPX_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < SPX_WOTS_LEN; i++) { - set_chain_addr(addr, i); - gen_chain(pk + i * SPX_N, sig + i * SPX_N, - lengths[i], SPX_WOTS_W - 1 - lengths[i], ctx, addr); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/wots.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/wots.h deleted file mode 100644 index 4e7692eeef..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/wots.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef SPX_WOTS_H -#define SPX_WOTS_H - -#include - -#include "context.h" -#include "params.h" - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) -void wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const spx_ctx *ctx, uint32_t addr[8]); - -/* - * Compute the chain lengths needed for a given message hash - */ -#define chain_lengths SPX_NAMESPACE(chain_lengths) -void chain_lengths(unsigned int *lengths, const unsigned char *msg); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/wotsx1.c b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/wotsx1.c deleted file mode 100644 index 3adec78dfb..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/wotsx1.c +++ /dev/null @@ -1,76 +0,0 @@ -#include -#include - -#include "wots.h" -#include "wotsx1.h" - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "thash.h" -#include "utils.h" - -/* - * This generates a WOTS public key - * It also generates the WOTS signature if leaf_info indicates - * that we're signing with this WOTS key - */ -void wots_gen_leafx1(unsigned char *dest, - const spx_ctx *ctx, - uint32_t leaf_idx, void *v_info) { - struct leaf_info_x1 *info = v_info; - uint32_t *leaf_addr = info->leaf_addr; - uint32_t *pk_addr = info->pk_addr; - unsigned int i, k; - unsigned char pk_buffer[ SPX_WOTS_BYTES ]; - unsigned char *buffer; - uint32_t wots_k_mask; - - if (leaf_idx == info->wots_sign_leaf) { - /* We're traversing the leaf that's signing; generate the WOTS */ - /* signature */ - wots_k_mask = 0; - } else { - /* Nope, we're just generating pk's; turn off the signature logic */ - wots_k_mask = (uint32_t)~0; - } - - set_keypair_addr( leaf_addr, leaf_idx ); - set_keypair_addr( pk_addr, leaf_idx ); - - for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { - uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k to */ - /* the step if we're generating a signature, ~0 if we're not */ - - /* Start with the secret seed */ - set_chain_addr(leaf_addr, i); - set_hash_addr(leaf_addr, 0); - set_type(leaf_addr, SPX_ADDR_TYPE_WOTSPRF); - - prf_addr(buffer, ctx, leaf_addr); - - set_type(leaf_addr, SPX_ADDR_TYPE_WOTS); - - /* Iterate down the WOTS chain */ - for (k = 0;; k++) { - /* Check if this is the value that needs to be saved as a */ - /* part of the WOTS signature */ - if (k == wots_k) { - memcpy( info->wots_sig + i * SPX_N, buffer, SPX_N ); - } - - /* Check if we hit the top of the chain */ - if (k == SPX_WOTS_W - 1) { - break; - } - - /* Iterate one step on the chain */ - set_hash_addr(leaf_addr, k); - - thash(buffer, buffer, 1, ctx, leaf_addr); - } - } - - /* Do the final thash to generate the public keys */ - thash(dest, pk_buffer, SPX_WOTS_LEN, ctx, pk_addr); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/wotsx1.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/wotsx1.h deleted file mode 100644 index e617929f96..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-robust_clean/wotsx1.h +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef WOTSX1_H_ -#define WOTSX1_H_ - -#include - -#include "context.h" -#include "params.h" - -/* - * This is here to provide an interface to the internal wots_gen_leafx1 - * routine. While this routine is not referenced in the package outside of - * wots.c, it is called from the stand-alone benchmark code to characterize - * the performance - */ -struct leaf_info_x1 { - unsigned char *wots_sig; - uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ - uint32_t *wots_steps; - uint32_t leaf_addr[8]; - uint32_t pk_addr[8]; -}; - -/* Macro to set the leaf_info to something 'benign', that is, it would */ -/* run with the same time as it does during the real signing process */ -/* Used only by the benchmark code */ -#define INITIALIZE_LEAF_INFO_X1(info, addr, step_buffer) { \ - (info).wots_sig = 0; \ - (info).wots_sign_leaf = ~0; \ - (info).wots_steps = step_buffer; \ - memcpy( &(info).leaf_addr[0], (addr), 32 ); \ - memcpy( &(info).pk_addr[0], (addr), 32 ); \ - } - -#define wots_gen_leafx1 SPX_NAMESPACE(wots_gen_leafx1) -void wots_gen_leafx1(unsigned char *dest, - const spx_ctx *ctx, - uint32_t leaf_idx, void *v_info); - -#endif /* WOTSX1_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/LICENSE b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/LICENSE deleted file mode 100644 index 670154e353..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/LICENSE +++ /dev/null @@ -1,116 +0,0 @@ -CC0 1.0 Universal - -Statement of Purpose - -The laws of most jurisdictions throughout the world automatically confer -exclusive Copyright and Related Rights (defined below) upon the creator and -subsequent owner(s) (each and all, an "owner") of an original work of -authorship and/or a database (each, a "Work"). - -Certain owners wish to permanently relinquish those rights to a Work for the -purpose of contributing to a commons of creative, cultural and scientific -works ("Commons") that the public can reliably and without fear of later -claims of infringement build upon, modify, incorporate in other works, reuse -and redistribute as freely as possible in any form whatsoever and for any -purposes, including without limitation commercial purposes. These owners may -contribute to the Commons to promote the ideal of a free culture and the -further production of creative, cultural and scientific works, or to gain -reputation or greater distribution for their Work in part through the use and -efforts of others. - -For these and/or other purposes and motivations, and without any expectation -of additional consideration or compensation, the person associating CC0 with a -Work (the "Affirmer"), to the extent that he or she is an owner of Copyright -and Related Rights in the Work, voluntarily elects to apply CC0 to the Work -and publicly distribute the Work under its terms, with knowledge of his or her -Copyright and Related Rights in the Work and the meaning and intended legal -effect of CC0 on those rights. - -1. Copyright and Related Rights. A Work made available under CC0 may be -protected by copyright and related or neighboring rights ("Copyright and -Related Rights"). Copyright and Related Rights include, but are not limited -to, the following: - - i. the right to reproduce, adapt, distribute, perform, display, communicate, - and translate a Work; - - ii. moral rights retained by the original author(s) and/or performer(s); - - iii. publicity and privacy rights pertaining to a person's image or likeness - depicted in a Work; - - iv. rights protecting against unfair competition in regards to a Work, - subject to the limitations in paragraph 4(a), below; - - v. rights protecting the extraction, dissemination, use and reuse of data in - a Work; - - vi. database rights (such as those arising under Directive 96/9/EC of the - European Parliament and of the Council of 11 March 1996 on the legal - protection of databases, and under any national implementation thereof, - including any amended or successor version of such directive); and - - vii. other similar, equivalent or corresponding rights throughout the world - based on applicable law or treaty, and any national implementations thereof. - -2. Waiver. To the greatest extent permitted by, but not in contravention of, -applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and -unconditionally waives, abandons, and surrenders all of Affirmer's Copyright -and Related Rights and associated claims and causes of action, whether now -known or unknown (including existing as well as future claims and causes of -action), in the Work (i) in all territories worldwide, (ii) for the maximum -duration provided by applicable law or treaty (including future time -extensions), (iii) in any current or future medium and for any number of -copies, and (iv) for any purpose whatsoever, including without limitation -commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes -the Waiver for the benefit of each member of the public at large and to the -detriment of Affirmer's heirs and successors, fully intending that such Waiver -shall not be subject to revocation, rescission, cancellation, termination, or -any other legal or equitable action to disrupt the quiet enjoyment of the Work -by the public as contemplated by Affirmer's express Statement of Purpose. - -3. Public License Fallback. Should any part of the Waiver for any reason be -judged legally invalid or ineffective under applicable law, then the Waiver -shall be preserved to the maximum extent permitted taking into account -Affirmer's express Statement of Purpose. In addition, to the extent the Waiver -is so judged Affirmer hereby grants to each affected person a royalty-free, -non transferable, non sublicensable, non exclusive, irrevocable and -unconditional license to exercise Affirmer's Copyright and Related Rights in -the Work (i) in all territories worldwide, (ii) for the maximum duration -provided by applicable law or treaty (including future time extensions), (iii) -in any current or future medium and for any number of copies, and (iv) for any -purpose whatsoever, including without limitation commercial, advertising or -promotional purposes (the "License"). The License shall be deemed effective as -of the date CC0 was applied by Affirmer to the Work. Should any part of the -License for any reason be judged legally invalid or ineffective under -applicable law, such partial invalidity or ineffectiveness shall not -invalidate the remainder of the License, and in such case Affirmer hereby -affirms that he or she will not (i) exercise any of his or her remaining -Copyright and Related Rights in the Work or (ii) assert any associated claims -and causes of action with respect to the Work, in either case contrary to -Affirmer's express Statement of Purpose. - -4. Limitations and Disclaimers. - - a. No trademark or patent rights held by Affirmer are waived, abandoned, - surrendered, licensed or otherwise affected by this document. - - b. Affirmer offers the Work as-is and makes no representations or warranties - of any kind concerning the Work, express, implied, statutory or otherwise, - including without limitation warranties of title, merchantability, fitness - for a particular purpose, non infringement, or the absence of latent or - other defects, accuracy, or the present or absence of errors, whether or not - discoverable, all to the greatest extent permissible under applicable law. - - c. Affirmer disclaims responsibility for clearing rights of other persons - that may apply to the Work or any use thereof, including without limitation - any person's Copyright and Related Rights in the Work. Further, Affirmer - disclaims responsibility for obtaining any necessary consents, permissions - or other rights required for any use of the Work. - - d. Affirmer understands and acknowledges that Creative Commons is not a - party to this document and has no duty or obligation with respect to this - CC0 or use of the Work. - -For more information, please see - diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/address.c b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/address.c deleted file mode 100644 index d49d9f3b6b..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/address.c +++ /dev/null @@ -1,95 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "utils.h" - -/* - * Specify which level of Merkle tree (the "layer") we're working on - */ -void set_layer_addr(uint32_t addr[8], uint32_t layer) { - ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; -} - -/* - * Specify which Merkle tree within the level (the "tree address") we're working on - */ -void set_tree_addr(uint32_t addr[8], uint64_t tree) { - ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); -} - -/* - * Specify the reason we'll use this address structure for, that is, what - * hash will we compute with it. This is used so that unrelated types of - * hashes don't accidentally get the same address structure. The type will be - * one of the SPX_ADDR_TYPE constants - */ -void set_type(uint32_t addr[8], uint32_t type) { - ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; -} - -/* - * Copy the layer and tree fields of the address structure. This is used - * when we're doing multiple types of hashes within the same Merkle tree - */ -void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { - memcpy( out, in, SPX_OFFSET_TREE + 8 ); -} - -/* These functions are used for OTS addresses. */ - -/* - * Specify which Merkle leaf we're working on; that is, which OTS keypair - * we're talking about. - */ -void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { - /* We have > 256 OTS at the bottom of the Merkle tree; to specify */ - /* which one, we'd need to express it in two bytes */ - ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR2] = (unsigned char)(keypair >> 8); - ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; -} - -/* - * Copy the layer, tree and keypair fields of the address structure. This is - * used when we're doing multiple things within the same OTS keypair - */ -void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { - memcpy( out, in, SPX_OFFSET_TREE + 8 ); - ((unsigned char *)out)[SPX_OFFSET_KP_ADDR2] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR2]; - ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; -} - -/* - * Specify which Merkle chain within the OTS we're working with - * (the chain address) - */ -void set_chain_addr(uint32_t addr[8], uint32_t chain) { - ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; -} - -/* - * Specify where in the Merkle chain we are -* (the hash address) - */ -void set_hash_addr(uint32_t addr[8], uint32_t hash) { - ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; -} - -/* These functions are used for all hash tree addresses (including FORS). */ - -/* - * Specify the height of the node in the Merkle/FORS tree we are in - * (the tree height) - */ -void set_tree_height(uint32_t addr[8], uint32_t tree_height) { - ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; -} - -/* - * Specify the distance from the left edge of the node in the Merkle/FORS tree - * (the tree index) - */ -void set_tree_index(uint32_t addr[8], uint32_t tree_index) { - u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/address.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/address.h deleted file mode 100644 index 24a84eb40c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/address.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef SPX_ADDRESS_H -#define SPX_ADDRESS_H - -#include - -#include "params.h" - -/* The hash types that are passed to set_type */ -#define SPX_ADDR_TYPE_WOTS 0 -#define SPX_ADDR_TYPE_WOTSPK 1 -#define SPX_ADDR_TYPE_HASHTREE 2 -#define SPX_ADDR_TYPE_FORSTREE 3 -#define SPX_ADDR_TYPE_FORSPK 4 -#define SPX_ADDR_TYPE_WOTSPRF 5 -#define SPX_ADDR_TYPE_FORSPRF 6 - -#define set_layer_addr SPX_NAMESPACE(set_layer_addr) -void set_layer_addr(uint32_t addr[8], uint32_t layer); - -#define set_tree_addr SPX_NAMESPACE(set_tree_addr) -void set_tree_addr(uint32_t addr[8], uint64_t tree); - -#define set_type SPX_NAMESPACE(set_type) -void set_type(uint32_t addr[8], uint32_t type); - -/* Copies the layer and tree part of one address into the other */ -#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) -void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for WOTS and FORS addresses. */ - -#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) -void set_keypair_addr(uint32_t addr[8], uint32_t keypair); - -#define set_chain_addr SPX_NAMESPACE(set_chain_addr) -void set_chain_addr(uint32_t addr[8], uint32_t chain); - -#define set_hash_addr SPX_NAMESPACE(set_hash_addr) -void set_hash_addr(uint32_t addr[8], uint32_t hash); - -#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) -void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for all hash tree addresses (including FORS). */ - -#define set_tree_height SPX_NAMESPACE(set_tree_height) -void set_tree_height(uint32_t addr[8], uint32_t tree_height); - -#define set_tree_index SPX_NAMESPACE(set_tree_index) -void set_tree_index(uint32_t addr[8], uint32_t tree_index); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/api.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/api.h deleted file mode 100644 index c715a93959..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/api.h +++ /dev/null @@ -1,77 +0,0 @@ -#ifndef PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_API_H -#define PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_API_H - -#include -#include - -#define PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_CRYPTO_ALGNAME "SPHINCS+-haraka-192s-simple" - -#define PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_CRYPTO_SECRETKEYBYTES 96 -#define PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_CRYPTO_PUBLICKEYBYTES 48 -#define PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_CRYPTO_BYTES 16224 - -#define PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_CRYPTO_SEEDBYTES 72 - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, - const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk); -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/context.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/context.h deleted file mode 100644 index f03446b9cb..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/context.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef SPX_CONTEXT_H -#define SPX_CONTEXT_H - -#include - -#include "immintrin.h" -#include "params.h" - -typedef struct { - uint8_t pub_seed[SPX_N]; - uint8_t sk_seed[SPX_N]; - - __m128i rc[40]; -} spx_ctx; - -#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) -void initialize_hash_function(spx_ctx *ctx); - -#define free_hash_function SPX_NAMESPACE(free_hash_function) -void free_hash_function(spx_ctx *ctx); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/context_haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/context_haraka.c deleted file mode 100644 index f1cd7e3664..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/context_haraka.c +++ /dev/null @@ -1,11 +0,0 @@ -#include "context.h" -#include "haraka.h" - -void initialize_hash_function(spx_ctx *ctx) { - tweak_constants(ctx); -} - -// we don't support heap-based haraka right now -void free_hash_function(spx_ctx *ctx) { - (void)ctx; // suppress unused variable warnings -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/fors.c b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/fors.c deleted file mode 100644 index f1b0639cfc..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/fors.c +++ /dev/null @@ -1,202 +0,0 @@ -#include -#include -#include - -#include "fors.h" - -#include "address.h" -#include "hash.h" -#include "hashx4.h" -#include "thash.h" -#include "thashx4.h" -#include "utils.h" -#include "utilsx4.h" - -static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, - uint32_t fors_leaf_addr[8]) { - prf_addr(sk, ctx, fors_leaf_addr); -} - -static void fors_gen_skx4(unsigned char *sk0, - unsigned char *sk1, - unsigned char *sk2, - unsigned char *sk3, const spx_ctx *ctx, - uint32_t fors_leaf_addrx4[4 * 8]) { - prf_addrx4(sk0, sk1, sk2, sk3, - ctx, fors_leaf_addrx4); -} - -static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, - const spx_ctx *ctx, - uint32_t fors_leaf_addr[8]) { - thash(leaf, sk, 1, ctx, fors_leaf_addr); -} - -static void fors_sk_to_leafx4(unsigned char *leaf0, - unsigned char *leaf1, - unsigned char *leaf2, - unsigned char *leaf3, - const unsigned char *sk0, - const unsigned char *sk1, - const unsigned char *sk2, - const unsigned char *sk3, - const spx_ctx *ctx, - uint32_t fors_leaf_addrx4[4 * 8]) { - thashx4(leaf0, leaf1, leaf2, leaf3, - sk0, sk1, sk2, sk3, - 1, ctx, fors_leaf_addrx4); -} - -struct fors_gen_leaf_info { - uint32_t leaf_addrx[4 * 8]; -}; - -static void fors_gen_leafx4(unsigned char *leaf, - const spx_ctx *ctx, - uint32_t addr_idx, void *info) { - struct fors_gen_leaf_info *fors_info = info; - uint32_t *fors_leaf_addrx4 = fors_info->leaf_addrx; - unsigned int j; - - /* Only set the parts that the caller doesn't set */ - for (j = 0; j < 4; j++) { - set_tree_index(fors_leaf_addrx4 + j * 8, addr_idx + j); - set_type(fors_leaf_addrx4 + j * 8, SPX_ADDR_TYPE_FORSPRF); - } - - fors_gen_skx4(leaf + 0 * SPX_N, - leaf + 1 * SPX_N, - leaf + 2 * SPX_N, - leaf + 3 * SPX_N, - ctx, fors_leaf_addrx4); - - for (j = 0; j < 4; j++) { - set_type(fors_leaf_addrx4 + j * 8, SPX_ADDR_TYPE_FORSTREE); - } - - fors_sk_to_leafx4(leaf + 0 * SPX_N, - leaf + 1 * SPX_N, - leaf + 2 * SPX_N, - leaf + 3 * SPX_N, - leaf + 0 * SPX_N, - leaf + 1 * SPX_N, - leaf + 2 * SPX_N, - leaf + 3 * SPX_N, - ctx, fors_leaf_addrx4); -} - -/** - * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - * Assumes indices has space for SPX_FORS_TREES integers. - */ -static void message_to_indices(uint32_t *indices, const unsigned char *m) { - unsigned int i, j; - unsigned int offset = 0; - - for (i = 0; i < SPX_FORS_TREES; i++) { - indices[i] = 0; - for (j = 0; j < SPX_FORS_HEIGHT; j++) { - indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); - offset++; - } - } -} - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -void fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]) { - uint32_t indices[SPX_FORS_TREES]; - unsigned char roots[SPX_FORS_TREES * SPX_N]; - uint32_t fors_tree_addr[4 * 8] = {0}; - struct fors_gen_leaf_info fors_info = {0}; - uint32_t *fors_leaf_addr = fors_info.leaf_addrx; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - for (i = 0; i < 4; i++) { - copy_keypair_addr(fors_tree_addr + 8 * i, fors_addr); - set_type(fors_tree_addr + 8 * i, SPX_ADDR_TYPE_FORSTREE); - copy_keypair_addr(fors_leaf_addr + 8 * i, fors_addr); - } - copy_keypair_addr(fors_pk_addr, fors_addr); - set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < SPX_FORS_TREES; i++) { - idx_offset = i * (1 << SPX_FORS_HEIGHT); - - set_tree_height(fors_tree_addr, 0); - set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Include the secret key part that produces the selected leaf node. */ - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); - fors_gen_sk(sig, ctx, fors_tree_addr); - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); - sig += SPX_N; - - /* Compute the authentication path for this leaf node. */ - treehashx4(roots + i * SPX_N, sig, ctx, - indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx4, - fors_tree_addr, &fors_info); - - sig += SPX_N * SPX_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); -} - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -void fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]) { - uint32_t indices[SPX_FORS_TREES]; - unsigned char roots[SPX_FORS_TREES * SPX_N]; - unsigned char leaf[SPX_N]; - uint32_t fors_tree_addr[8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - copy_keypair_addr(fors_tree_addr, fors_addr); - copy_keypair_addr(fors_pk_addr, fors_addr); - - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); - set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < SPX_FORS_TREES; i++) { - idx_offset = i * (1 << SPX_FORS_HEIGHT); - - set_tree_height(fors_tree_addr, 0); - set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Derive the leaf from the included secret key part. */ - fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); - sig += SPX_N; - - /* Derive the corresponding root node of this tree. */ - compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, - sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); - sig += SPX_N * SPX_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/fors.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/fors.h deleted file mode 100644 index 509140a178..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/fors.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef SPX_FORS_H -#define SPX_FORS_H - -#include - -#include "context.h" -#include "params.h" - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -#define fors_sign SPX_NAMESPACE(fors_sign) -void fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]); - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) -void fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/haraka.c deleted file mode 100644 index b414b691d7..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/haraka.c +++ /dev/null @@ -1,702 +0,0 @@ -/* -Plain C implementation of the Haraka256 and Haraka512 permutations. -*/ -#include -#include -#include -#include -#include - -#include "haraka.h" -#include "harakax4.h" -#include "utils.h" - -#define HARAKAS_RATE 32 - -#define u64 unsigned long -#define u128 __m128i - -#define LOAD(src) _mm_loadu_si128((u128 *)(src)) -#define STORE(dest,src) _mm_storeu_si128((u128 *)(dest),src) - -#define XOR128(a, b) _mm_xor_si128(a, b) - -#define AES2(s0, s1, rci) \ - s0 = _mm_aesenc_si128(s0, *(rci)); \ - (s1) = _mm_aesenc_si128(s1, *((rci) + 1)); \ - (s0) = _mm_aesenc_si128(s0, *((rci) + 2)); \ - (s1) = _mm_aesenc_si128(s1, *((rci) + 3)); - -#define AES2_4x(s0, s1, s2, s3, rci) \ - AES2((s0)[0], (s0)[1], rci); \ - AES2((s1)[0], (s1)[1], rci); \ - AES2((s2)[0], (s2)[1], rci); \ - AES2((s3)[0], (s3)[1], rci); - -#define AES4(s0, s1, s2, s3, rci) \ - s0 = _mm_aesenc_si128(s0, *(rci)); \ - (s1) = _mm_aesenc_si128(s1, *((rci) + 1)); \ - (s2) = _mm_aesenc_si128(s2, *((rci) + 2)); \ - (s3) = _mm_aesenc_si128(s3, *((rci) + 3)); \ - (s0) = _mm_aesenc_si128(s0, *((rci) + 4)); \ - (s1) = _mm_aesenc_si128(s1, *((rci) + 5)); \ - (s2) = _mm_aesenc_si128(s2, *((rci) + 6)); \ - (s3) = _mm_aesenc_si128(s3, *((rci) + 7)); - -#define AES4_4x(s0, s1, s2, s3, rci) \ - AES4((s0)[0], (s0)[1], (s0)[2], (s0)[3], rci); \ - AES4((s1)[0], (s1)[1], (s1)[2], (s1)[3], rci); \ - AES4((s2)[0], (s2)[1], (s2)[2], (s2)[3], rci); \ - AES4((s3)[0], (s3)[1], (s3)[2], (s3)[3], rci); - -#define MIX2(s0, s1) \ - tmp = _mm_unpacklo_epi32(s0, s1); \ - (s1) = _mm_unpackhi_epi32(s0, s1); \ - (s0) = tmp; - -#define MIX4(s0, s1, s2, s3) \ - tmp = _mm_unpacklo_epi32(s0, s1); \ - (s0) = _mm_unpackhi_epi32(s0, s1); \ - (s1) = _mm_unpacklo_epi32(s2, s3); \ - (s2) = _mm_unpackhi_epi32(s2, s3); \ - (s3) = _mm_unpacklo_epi32(s0, s2); \ - (s0) = _mm_unpackhi_epi32(s0, s2); \ - (s2) = _mm_unpackhi_epi32(s1, tmp); \ - (s1) = _mm_unpacklo_epi32(s1, tmp); - -#define TRUNCSTORE(out, s0, s1, s2, s3) \ - _mm_storeu_si128((u128 *)(out), \ - _mm_castpd_si128(_mm_shuffle_pd(_mm_castsi128_pd(s0), _mm_castsi128_pd(s1), 3))); \ - _mm_storeu_si128((u128 *)((out) + 16), \ - _mm_castpd_si128(_mm_shuffle_pd(_mm_castsi128_pd(s2), _mm_castsi128_pd(s3), 0))); - -static void load_haraka_constants(u128 *rc) { - rc[0] = _mm_set_epi32((int)0x0684704c, (int)0xe620c00a, (int)0xb2c5fef0, (int)0x75817b9d); - rc[1] = _mm_set_epi32((int)0x8b66b4e1, (int)0x88f3a06b, (int)0x640f6ba4, (int)0x2f08f717); - rc[2] = _mm_set_epi32((int)0x3402de2d, (int)0x53f28498, (int)0xcf029d60, (int)0x9f029114); - rc[3] = _mm_set_epi32((int)0x0ed6eae6, (int)0x2e7b4f08, (int)0xbbf3bcaf, (int)0xfd5b4f79); - rc[4] = _mm_set_epi32((int)0xcbcfb0cb, (int)0x4872448b, (int)0x79eecd1c, (int)0xbe397044); - rc[5] = _mm_set_epi32((int)0x7eeacdee, (int)0x6e9032b7, (int)0x8d5335ed, (int)0x2b8a057b); - rc[6] = _mm_set_epi32((int)0x67c28f43, (int)0x5e2e7cd0, (int)0xe2412761, (int)0xda4fef1b); - rc[7] = _mm_set_epi32((int)0x2924d9b0, (int)0xafcacc07, (int)0x675ffde2, (int)0x1fc70b3b); - rc[8] = _mm_set_epi32((int)0xab4d63f1, (int)0xe6867fe9, (int)0xecdb8fca, (int)0xb9d465ee); - rc[9] = _mm_set_epi32((int)0x1c30bf84, (int)0xd4b7cd64, (int)0x5b2a404f, (int)0xad037e33); - rc[10] = _mm_set_epi32((int)0xb2cc0bb9, (int)0x941723bf, (int)0x69028b2e, (int)0x8df69800); - rc[11] = _mm_set_epi32((int)0xfa0478a6, (int)0xde6f5572, (int)0x4aaa9ec8, (int)0x5c9d2d8a); - rc[12] = _mm_set_epi32((int)0xdfb49f2b, (int)0x6b772a12, (int)0x0efa4f2e, (int)0x29129fd4); - rc[13] = _mm_set_epi32((int)0x1ea10344, (int)0xf449a236, (int)0x32d611ae, (int)0xbb6a12ee); - rc[14] = _mm_set_epi32((int)0xaf044988, (int)0x4b050084, (int)0x5f9600c9, (int)0x9ca8eca6); - rc[15] = _mm_set_epi32((int)0x21025ed8, (int)0x9d199c4f, (int)0x78a2c7e3, (int)0x27e593ec); - rc[16] = _mm_set_epi32((int)0xbf3aaaf8, (int)0xa759c9b7, (int)0xb9282ecd, (int)0x82d40173); - rc[17] = _mm_set_epi32((int)0x6260700d, (int)0x6186b017, (int)0x37f2efd9, (int)0x10307d6b); - rc[18] = _mm_set_epi32((int)0x5aca45c2, (int)0x21300443, (int)0x81c29153, (int)0xf6fc9ac6); - rc[19] = _mm_set_epi32((int)0x9223973c, (int)0x226b68bb, (int)0x2caf92e8, (int)0x36d1943a); - rc[20] = _mm_set_epi32((int)0xd3bf9238, (int)0x225886eb, (int)0x6cbab958, (int)0xe51071b4); - rc[21] = _mm_set_epi32((int)0xdb863ce5, (int)0xaef0c677, (int)0x933dfddd, (int)0x24e1128d); - rc[22] = _mm_set_epi32((int)0xbb606268, (int)0xffeba09c, (int)0x83e48de3, (int)0xcb2212b1); - rc[23] = _mm_set_epi32((int)0x734bd3dc, (int)0xe2e4d19c, (int)0x2db91a4e, (int)0xc72bf77d); - rc[24] = _mm_set_epi32((int)0x43bb47c3, (int)0x61301b43, (int)0x4b1415c4, (int)0x2cb3924e); - rc[25] = _mm_set_epi32((int)0xdba775a8, (int)0xe707eff6, (int)0x03b231dd, (int)0x16eb6899); - rc[26] = _mm_set_epi32((int)0x6df3614b, (int)0x3c755977, (int)0x8e5e2302, (int)0x7eca472c); - rc[27] = _mm_set_epi32((int)0xcda75a17, (int)0xd6de7d77, (int)0x6d1be5b9, (int)0xb88617f9); - rc[28] = _mm_set_epi32((int)0xec6b43f0, (int)0x6ba8e9aa, (int)0x9d6c069d, (int)0xa946ee5d); - rc[29] = _mm_set_epi32((int)0xcb1e6950, (int)0xf957332b, (int)0xa2531159, (int)0x3bf327c1); - rc[30] = _mm_set_epi32((int)0x2cee0c75, (int)0x00da619c, (int)0xe4ed0353, (int)0x600ed0d9); - rc[31] = _mm_set_epi32((int)0xf0b1a5a1, (int)0x96e90cab, (int)0x80bbbabc, (int)0x63a4a350); - rc[32] = _mm_set_epi32((int)0xae3db102, (int)0x5e962988, (int)0xab0dde30, (int)0x938dca39); - rc[33] = _mm_set_epi32((int)0x17bb8f38, (int)0xd554a40b, (int)0x8814f3a8, (int)0x2e75b442); - rc[34] = _mm_set_epi32((int)0x34bb8a5b, (int)0x5f427fd7, (int)0xaeb6b779, (int)0x360a16f6); - rc[35] = _mm_set_epi32((int)0x26f65241, (int)0xcbe55438, (int)0x43ce5918, (int)0xffbaafde); - rc[36] = _mm_set_epi32((int)0x4ce99a54, (int)0xb9f3026a, (int)0xa2ca9cf7, (int)0x839ec978); - rc[37] = _mm_set_epi32((int)0xae51a51a, (int)0x1bdff7be, (int)0x40c06e28, (int)0x22901235); - rc[38] = _mm_set_epi32((int)0xa0c1613c, (int)0xba7ed22b, (int)0xc173bc0f, (int)0x48a659cf); - rc[39] = _mm_set_epi32((int)0x756acc03, (int)0x02288288, (int)0x4ad6bdfd, (int)0xe9c59da1); -} - -void tweak_constants(spx_ctx *ctx) { - int i; - unsigned char buf[40 * 16]; - - /* Use the standard constants to generate tweaked ones. */ - load_haraka_constants(ctx->rc); - - /* Constants for pk.seed */ - haraka_S(buf, 40 * 16, ctx->pub_seed, SPX_N, ctx); - - /* Tweak constants with the pub_seed */ - for (i = 0; i < 40; i++) { - ctx->rc[i] = LOAD(buf + i * 16); - } -} - -static void haraka_S_absorb(unsigned char *s, unsigned int r, - const unsigned char *m, unsigned long long mlen, - unsigned char p, const spx_ctx *ctx) { - unsigned long long i; - PQCLEAN_VLA(unsigned char, t, r); - - while (mlen >= r) { - // XOR block to state - STORE(s, XOR128(LOAD(s), LOAD(m))); - STORE(s + 16, XOR128(LOAD(s + 16), LOAD(m + 16))); - haraka512_perm(s, s, ctx); - 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; - STORE(s, XOR128(LOAD(s), LOAD(t))); - STORE(s + 16, XOR128(LOAD(s + 16), LOAD(t + 16))); -} - -static void haraka_S_absorb4x(unsigned char *s, - unsigned int r, - const unsigned char *m0, - const unsigned char *m1, - const unsigned char *m2, - const unsigned char *m3, - unsigned long long int mlen, - unsigned char p, - const spx_ctx *ctx) { - unsigned long long i; - PQCLEAN_VLA(unsigned char, t0, r); - PQCLEAN_VLA(unsigned char, t1, r); - PQCLEAN_VLA(unsigned char, t2, r); - PQCLEAN_VLA(unsigned char, t3, r); - - while (mlen >= r) { - // XOR block to state - STORE(s, XOR128(LOAD(s), LOAD(m0))); - STORE(s + 16, XOR128(LOAD(s + 16), LOAD(m0 + 16))); - STORE(s + 64, XOR128(LOAD(s + 64), LOAD(m1))); - STORE(s + 80, XOR128(LOAD(s + 80), LOAD(m1 + 16))); - STORE(s + 128, XOR128(LOAD(s + 128), LOAD(m2))); - STORE(s + 144, XOR128(LOAD(s + 144), LOAD(m2 + 16))); - STORE(s + 192, XOR128(LOAD(s + 192), LOAD(m3))); - STORE(s + 208, XOR128(LOAD(s + 208), LOAD(m3 + 16))); - - haraka512_perm_x4(s, s, ctx); - mlen -= r; - m0 += r; - m1 += r; - m2 += r; - m3 += r; - } - - for (i = 0; i < r; ++i) { - t0[i] = 0; - t1[i] = 0; - t2[i] = 0; - t3[i] = 0; - } - for (i = 0; i < mlen; ++i) { - t0[i] = m0[i]; - t1[i] = m1[i]; - t2[i] = m2[i]; - t3[i] = m3[i]; - } - - t0[i] = p; - t1[i] = p; - t2[i] = p; - t3[i] = p; - - t0[r - 1] |= 128; - t1[r - 1] |= 128; - t2[r - 1] |= 128; - t3[r - 1] |= 128; - - STORE(s, XOR128(LOAD(s), LOAD(t0))); - STORE(s + 16, XOR128(LOAD(s + 16), LOAD(t0 + 16))); - STORE(s + 64, XOR128(LOAD(s + 64), LOAD(t1))); - STORE(s + 80, XOR128(LOAD(s + 80), LOAD(t1 + 16))); - STORE(s + 128, XOR128(LOAD(s + 128), LOAD(t2))); - STORE(s + 144, XOR128(LOAD(s + 144), LOAD(t2 + 16))); - STORE(s + 192, XOR128(LOAD(s + 192), LOAD(t3))); - STORE(s + 208, XOR128(LOAD(s + 208), LOAD(t3 + 16))); -} - -static void haraka_S_squeezeblocks(unsigned char *h, unsigned long long nblocks, - unsigned char *s, unsigned int r, - const spx_ctx *ctx) { - while (nblocks > 0) { - haraka512_perm(s, s, ctx); - STORE(h, LOAD(s)); - STORE(h + 16, LOAD(s + 16)); - h += r; - nblocks--; - } -} - -static void haraka_S_squeezeblocks4x(unsigned char *h0, - unsigned char *h1, - unsigned char *h2, - unsigned char *h3, - unsigned long long nblocks, - unsigned char *s, - unsigned int r, - const spx_ctx *ctx) { - while (nblocks > 0) { - haraka512_perm_x4(s, s, ctx); - STORE(h0, LOAD(s)); - STORE(h0 + 16, LOAD(s + 16)); - STORE(h1, LOAD(s + 64)); - STORE(h1 + 16, LOAD(s + 80)); - STORE(h2, LOAD(s + 128)); - STORE(h2 + 16, LOAD(s + 144)); - STORE(h3, LOAD(s + 192)); - STORE(h3 + 16, LOAD(s + 208)); - h0 += r; - h1 += r; - h2 += r; - h3 += r; - nblocks--; - } -} - -void haraka_S_inc_init(uint8_t *s_inc) { - size_t i; - - for (i = 0; i < 64; i++) { - s_inc[i] = 0; - } - s_inc[64] = 0; -} - -void haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, - const spx_ctx *ctx) { - size_t i; - - /* Recall that s_inc[64] is the non-absorbed bytes xored into the state */ - while (mlen + s_inc[64] >= HARAKAS_RATE) { - for (i = 0; i < (size_t)(HARAKAS_RATE - s_inc[64]); i++) { - /* Take the i'th byte from message - xor with the s_inc[64] + i'th byte of the state */ - s_inc[s_inc[64] + i] ^= m[i]; - } - mlen -= (size_t)(HARAKAS_RATE - s_inc[64]); - m += HARAKAS_RATE - s_inc[64]; - s_inc[64] = 0; - - haraka512_perm(s_inc, s_inc, ctx); - } - - for (i = 0; i < mlen; i++) { - s_inc[s_inc[64] + i] ^= m[i]; - } - s_inc[64] += (uint8_t)mlen; -} - -void haraka_S_inc_finalize(uint8_t *s_inc) { - /* After haraka_S_inc_absorb, we are guaranteed that s_inc[64] < HARAKAS_RATE, - so we can always use one more byte for p in the current state. */ - s_inc[s_inc[64]] ^= 0x1F; - s_inc[HARAKAS_RATE - 1] ^= 128; - s_inc[64] = 0; -} - -void haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, - const spx_ctx *ctx) { - size_t i; - - /* First consume any bytes we still have sitting around */ - for (i = 0; i < outlen && i < s_inc[64]; i++) { - /* There are s_inc[64] bytes left, so r - s_inc[64] is the first - available byte. We consume from there, i.e., up to r. */ - out[i] = (uint8_t)s_inc[(HARAKAS_RATE - s_inc[64] + i)]; - } - out += i; - outlen -= i; - s_inc[64] -= (uint8_t)i; - - /* Then squeeze the remaining necessary blocks */ - while (outlen > 0) { - haraka512_perm(s_inc, s_inc, ctx); - - for (i = 0; i < outlen && i < HARAKAS_RATE; i++) { - out[i] = s_inc[i]; - } - out += i; - outlen -= i; - s_inc[64] = (uint8_t)(HARAKAS_RATE - i); - } -} - -void haraka_S(unsigned char *out, unsigned long long outlen, - const unsigned char *in, unsigned long long inlen, - const spx_ctx *ctx) { - unsigned long long i; - unsigned char s[64]; - unsigned char d[32]; - - for (i = 0; i < 64; i++) { - s[i] = 0; - } - haraka_S_absorb(s, HARAKAS_RATE, in, inlen, 0x1F, ctx); - - haraka_S_squeezeblocks(out, outlen / HARAKAS_RATE, s, HARAKAS_RATE, ctx); - out += (outlen / HARAKAS_RATE) * HARAKAS_RATE; - - if (outlen % HARAKAS_RATE) { - haraka_S_squeezeblocks(d, 1, s, HARAKAS_RATE, ctx); - for (i = 0; i < outlen % HARAKAS_RATE; i++) { - out[i] = d[i]; - } - } -} - -void haraka_Sx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned long long outlen, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - unsigned long long inlen, - const spx_ctx *ctx) { - unsigned long long i; - unsigned char s[64 * 4]; - unsigned char d0[32]; - unsigned char d1[32]; - unsigned char d2[32]; - unsigned char d3[32]; - - for (i = 0; i < 64 * 4; i++) { - s[i] = 0; - } - haraka_S_absorb4x(s, HARAKAS_RATE, in0, in1, in2, in3, inlen, 0x1F, ctx); - - haraka_S_squeezeblocks4x(out0, out1, out2, out3, outlen / HARAKAS_RATE, s, - HARAKAS_RATE, ctx); - out0 += (outlen / HARAKAS_RATE) * HARAKAS_RATE; - out1 += (outlen / HARAKAS_RATE) * HARAKAS_RATE; - out2 += (outlen / HARAKAS_RATE) * HARAKAS_RATE; - out3 += (outlen / HARAKAS_RATE) * HARAKAS_RATE; - - if (outlen % HARAKAS_RATE) { - haraka_S_squeezeblocks4x(d0, d1, d2, d3, 1, s, HARAKAS_RATE, ctx); - for (i = 0; i < outlen % HARAKAS_RATE; i++) { - out0[i] = d0[i]; - out1[i] = d1[i]; - out2[i] = d2[i]; - out3[i] = d3[i]; - } - } -} - -void haraka512_perm(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx) { - u128 s[4], tmp; - - s[0] = LOAD(in); - s[1] = LOAD(in + 16); - s[2] = LOAD(in + 32); - s[3] = LOAD(in + 48); - - AES4(s[0], s[1], s[2], s[3], ctx->rc); - MIX4(s[0], s[1], s[2], s[3]); - - AES4(s[0], s[1], s[2], s[3], ctx->rc + 8); - MIX4(s[0], s[1], s[2], s[3]); - - AES4(s[0], s[1], s[2], s[3], ctx->rc + 16); - MIX4(s[0], s[1], s[2], s[3]); - - AES4(s[0], s[1], s[2], s[3], ctx->rc + 24); - MIX4(s[0], s[1], s[2], s[3]); - - AES4(s[0], s[1], s[2], s[3], ctx->rc + 32); - MIX4(s[0], s[1], s[2], s[3]); - - STORE(out, s[0]); - STORE(out + 16, s[1]); - STORE(out + 32, s[2]); - STORE(out + 48, s[3]); -} - -void haraka512_perm_x4(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx) { - u128 s[4][4], tmp; - - s[0][0] = LOAD(in); - s[0][1] = LOAD(in + 16); - s[0][2] = LOAD(in + 32); - s[0][3] = LOAD(in + 48); - s[1][0] = LOAD(in + 64); - s[1][1] = LOAD(in + 80); - s[1][2] = LOAD(in + 96); - s[1][3] = LOAD(in + 112); - s[2][0] = LOAD(in + 128); - s[2][1] = LOAD(in + 144); - s[2][2] = LOAD(in + 160); - s[2][3] = LOAD(in + 176); - s[3][0] = LOAD(in + 192); - s[3][1] = LOAD(in + 208); - s[3][2] = LOAD(in + 224); - s[3][3] = LOAD(in + 240); - - AES4_4x(s[0], s[1], s[2], s[3], ctx->rc); - MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); - MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); - MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); - MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - - AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 8); - MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); - MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); - MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); - MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - - AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 16); - MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); - MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); - MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); - MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - - AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 24); - MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); - MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); - MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); - MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - - AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 32); - MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); - MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); - MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); - MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - - STORE(out, s[0][0]); - STORE(out + 16, s[0][1]); - STORE(out + 32, s[0][2]); - STORE(out + 48, s[0][3]); - STORE(out + 64, s[1][0]); - STORE(out + 80, s[1][1]); - STORE(out + 96, s[1][2]); - STORE(out + 112, s[1][3]); - STORE(out + 128, s[2][0]); - STORE(out + 144, s[2][1]); - STORE(out + 160, s[2][2]); - STORE(out + 176, s[2][3]); - STORE(out + 192, s[3][0]); - STORE(out + 208, s[3][1]); - STORE(out + 224, s[3][2]); - STORE(out + 240, s[3][3]); -} - -void haraka512(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx) { - u128 s[4], tmp; - - s[0] = LOAD(in); - s[1] = LOAD(in + 16); - s[2] = LOAD(in + 32); - s[3] = LOAD(in + 48); - - AES4(s[0], s[1], s[2], s[3], ctx->rc); - MIX4(s[0], s[1], s[2], s[3]); - - AES4(s[0], s[1], s[2], s[3], ctx->rc + 8); - MIX4(s[0], s[1], s[2], s[3]); - - AES4(s[0], s[1], s[2], s[3], ctx->rc + 16); - MIX4(s[0], s[1], s[2], s[3]); - - AES4(s[0], s[1], s[2], s[3], ctx->rc + 24); - MIX4(s[0], s[1], s[2], s[3]); - - AES4(s[0], s[1], s[2], s[3], ctx->rc + 32); - MIX4(s[0], s[1], s[2], s[3]); - - s[0] = XOR128(s[0], LOAD(in)); - s[1] = XOR128(s[1], LOAD(in + 16)); - s[2] = XOR128(s[2], LOAD(in + 32)); - s[3] = XOR128(s[3], LOAD(in + 48)); - - // truncate and store result - TRUNCSTORE(out, s[0], s[1], s[2], s[3]); -} - -void haraka512x4(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx) { - u128 s[4][4], tmp; - - s[0][0] = LOAD(in); - s[0][1] = LOAD(in + 16); - s[0][2] = LOAD(in + 32); - s[0][3] = LOAD(in + 48); - s[1][0] = LOAD(in + 64); - s[1][1] = LOAD(in + 80); - s[1][2] = LOAD(in + 96); - s[1][3] = LOAD(in + 112); - s[2][0] = LOAD(in + 128); - s[2][1] = LOAD(in + 144); - s[2][2] = LOAD(in + 160); - s[2][3] = LOAD(in + 176); - s[3][0] = LOAD(in + 192); - s[3][1] = LOAD(in + 208); - s[3][2] = LOAD(in + 224); - s[3][3] = LOAD(in + 240); - - AES4_4x(s[0], s[1], s[2], s[3], ctx->rc); - MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); - MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); - MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); - MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - - AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 8); - MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); - MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); - MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); - MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - - AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 16); - MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); - MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); - MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); - MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - - AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 24); - MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); - MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); - MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); - MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - - AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 32); - MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); - MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); - MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); - MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - - s[0][0] = XOR128(s[0][0], LOAD(in)); - s[0][1] = XOR128(s[0][1], LOAD(in + 16)); - s[0][2] = XOR128(s[0][2], LOAD(in + 32)); - s[0][3] = XOR128(s[0][3], LOAD(in + 48)); - s[1][0] = XOR128(s[1][0], LOAD(in + 64)); - s[1][1] = XOR128(s[1][1], LOAD(in + 80)); - s[1][2] = XOR128(s[1][2], LOAD(in + 96)); - s[1][3] = XOR128(s[1][3], LOAD(in + 112)); - s[2][0] = XOR128(s[2][0], LOAD(in + 128)); - s[2][1] = XOR128(s[2][1], LOAD(in + 144)); - s[2][2] = XOR128(s[2][2], LOAD(in + 160)); - s[2][3] = XOR128(s[2][3], LOAD(in + 176)); - s[3][0] = XOR128(s[3][0], LOAD(in + 192)); - s[3][1] = XOR128(s[3][1], LOAD(in + 208)); - s[3][2] = XOR128(s[3][2], LOAD(in + 224)); - s[3][3] = XOR128(s[3][3], LOAD(in + 240)); - - TRUNCSTORE(out, s[0][0], s[0][1], s[0][2], s[0][3]); - TRUNCSTORE((out + 32), s[1][0], s[1][1], s[1][2], s[1][3]); - TRUNCSTORE((out + 64), s[2][0], s[2][1], s[2][2], s[2][3]); - TRUNCSTORE((out + 96), s[3][0], s[3][1], s[3][2], s[3][3]); -} - -void haraka256(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx) { - u128 s[2], tmp; - - s[0] = LOAD(in); - s[1] = LOAD(in + 16); - - AES2(s[0], s[1], ctx->rc); - MIX2(s[0], s[1]); - - AES2(s[0], s[1], ctx->rc + 4); - MIX2(s[0], s[1]); - - AES2(s[0], s[1], ctx->rc + 8); - MIX2(s[0], s[1]); - - AES2(s[0], s[1], ctx->rc + 12); - MIX2(s[0], s[1]); - - AES2(s[0], s[1], ctx->rc + 16); - MIX2(s[0], s[1]); - - s[0] = XOR128(s[0], LOAD(in)); - s[1] = XOR128(s[1], LOAD(in + 16)); - - STORE(out, s[0]); - STORE(out + 16, s[1]); -} - -void haraka256x4(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx) { - u128 s[4][2], tmp; - - s[0][0] = LOAD(in); - s[0][1] = LOAD(in + 16); - s[1][0] = LOAD(in + 32); - s[1][1] = LOAD(in + 48); - s[2][0] = LOAD(in + 64); - s[2][1] = LOAD(in + 80); - s[3][0] = LOAD(in + 96); - s[3][1] = LOAD(in + 112); - - // Round 1 - AES2_4x(s[0], s[1], s[2], s[3], ctx->rc); - - MIX2(s[0][0], s[0][1]); - MIX2(s[1][0], s[1][1]); - MIX2(s[2][0], s[2][1]); - MIX2(s[3][0], s[3][1]); - - // Round 2 - AES2_4x(s[0], s[1], s[2], s[3], ctx->rc + 4); - - MIX2(s[0][0], s[0][1]); - MIX2(s[1][0], s[1][1]); - MIX2(s[2][0], s[2][1]); - MIX2(s[3][0], s[3][1]); - - // Round 3 - AES2_4x(s[0], s[1], s[2], s[3], ctx->rc + 8); - - MIX2(s[0][0], s[0][1]); - MIX2(s[1][0], s[1][1]); - MIX2(s[2][0], s[2][1]); - MIX2(s[3][0], s[3][1]); - - // Round 4 - AES2_4x(s[0], s[1], s[2], s[3], ctx->rc + 12); - - MIX2(s[0][0], s[0][1]); - MIX2(s[1][0], s[1][1]); - MIX2(s[2][0], s[2][1]); - MIX2(s[3][0], s[3][1]); - - // Round 5 - AES2_4x(s[0], s[1], s[2], s[3], ctx->rc + 16); - - MIX2(s[0][0], s[0][1]); - MIX2(s[1][0], s[1][1]); - MIX2(s[2][0], s[2][1]); - MIX2(s[3][0], s[3][1]); - - // Feed Forward - s[0][0] = _mm_xor_si128(s[0][0], LOAD(in)); - s[0][1] = _mm_xor_si128(s[0][1], LOAD(in + 16)); - s[1][0] = _mm_xor_si128(s[1][0], LOAD(in + 32)); - s[1][1] = _mm_xor_si128(s[1][1], LOAD(in + 48)); - s[2][0] = _mm_xor_si128(s[2][0], LOAD(in + 64)); - s[2][1] = _mm_xor_si128(s[2][1], LOAD(in + 80)); - s[3][0] = _mm_xor_si128(s[3][0], LOAD(in + 96)); - s[3][1] = _mm_xor_si128(s[3][1], LOAD(in + 112)); - - STORE(out, s[0][0]); - STORE(out + 16, s[0][1]); - STORE(out + 32, s[1][0]); - STORE(out + 48, s[1][1]); - STORE(out + 64, s[2][0]); - STORE(out + 80, s[2][1]); - STORE(out + 96, s[3][0]); - STORE(out + 112, s[3][1]); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/haraka.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/haraka.h deleted file mode 100644 index 737cb6065f..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/haraka.h +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef SPX_HARAKA_H -#define SPX_HARAKA_H - -#include "context.h" -#include "params.h" - -/* Tweak constants with seed */ -#define tweak_constants SPX_NAMESPACE(tweak_constants) -void tweak_constants(spx_ctx *ctx); - -/* Haraka Sponge */ -#define haraka_S_inc_init SPX_NAMESPACE(haraka_S_inc_init) -void haraka_S_inc_init(uint8_t *s_inc); -#define haraka_S_inc_absorb SPX_NAMESPACE(haraka_S_inc_absorb) -void haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, - const spx_ctx *ctx); -#define haraka_S_inc_finalize SPX_NAMESPACE(haraka_S_inc_finalize) -void haraka_S_inc_finalize(uint8_t *s_inc); -#define haraka_S_inc_squeeze SPX_NAMESPACE(haraka_S_inc_squeeze) -void haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, - const spx_ctx *ctx); -#define haraka_S SPX_NAMESPACE(haraka_S) -void haraka_S(unsigned char *out, unsigned long long outlen, - const unsigned char *in, unsigned long long inlen, - const spx_ctx *ctx); - -/* Applies the 512-bit Haraka permutation to in. */ -#define haraka512_perm SPX_NAMESPACE(haraka512_perm) -void haraka512_perm(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx); - -/* Implementation of Haraka-512 */ -#define haraka512 SPX_NAMESPACE(haraka512) -void haraka512(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx); - -/* Implementation of Haraka-256 */ -#define haraka256 SPX_NAMESPACE(haraka256) -void haraka256(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/haraka_offsets.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/haraka_offsets.h deleted file mode 100644 index 7c062272a0..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/haraka_offsets.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef HARAKA_OFFSETS_H_ -#define HARAKA_OFFSETS_H_ - -/* - * Offsets of various fields in the address structure when we use Haraka as - * the Sphincs+ hash function - */ - -#define SPX_OFFSET_LAYER 3 /* The byte used to specify the Merkle tree layer */ -#define SPX_OFFSET_TREE 8 /* The start of the 8 byte field used to specify the tree */ -#define SPX_OFFSET_TYPE 19 /* The byte used to specify the hash type (reason) */ -#define SPX_OFFSET_KP_ADDR2 22 /* The high byte used to specify the key pair (which one-time signature) */ -#define SPX_OFFSET_KP_ADDR1 23 /* The low byte used to specify the key pair */ -#define SPX_OFFSET_CHAIN_ADDR 27 /* The byte used to specify the chain address (which Winternitz chain) */ -#define SPX_OFFSET_HASH_ADDR 31 /* The byte used to specify the hash address (where in the Winternitz chain) */ -#define SPX_OFFSET_TREE_HGT 27 /* The byte used to specify the height of this node in the FORS or Merkle tree */ -#define SPX_OFFSET_TREE_INDEX 28 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ - -#define SPX_HARAKA 1 - -#endif /* HARAKA_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/harakax4.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/harakax4.h deleted file mode 100644 index eadc69aa48..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/harakax4.h +++ /dev/null @@ -1,36 +0,0 @@ -#ifndef SPX_HARAKAX4_H -#define SPX_HARAKAX4_H - -#include "context.h" -#include "params.h" - -/* Haraka Sponge */ -#define haraka_Sx4 SPX_NAMESPACE(haraka_Sx4) -void haraka_Sx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned long long outlen, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - unsigned long long inlen, - const spx_ctx *ctx); - -/* Applies the 512-bit Haraka permutation x4 to in. */ -#define haraka512_perm_x4 SPX_NAMESPACE(haraka512_perm_x4) -void haraka512_perm_x4(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx); - -/* Implementation of Haraka-512 x4*/ -#define haraka512x4 SPX_NAMESPACE(haraka512x4) -void haraka512x4(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx); - -/* Implementation of Haraka-256 x4 */ -#define haraka256x4 SPX_NAMESPACE(haraka256x4) -void haraka256x4(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/hash.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/hash.h deleted file mode 100644 index f7c87d4c3c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/hash.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef SPX_HASH_H -#define SPX_HASH_H - -#include -#include - -#include "context.h" -#include "params.h" - -#define prf_addr SPX_NAMESPACE(prf_addr) -void prf_addr(unsigned char *out, const spx_ctx *ctx, - const uint32_t addr[8]); - -#define gen_message_random SPX_NAMESPACE(gen_message_random) -void gen_message_random(unsigned char *R, const unsigned char *sk_prf, - const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx); - -#define hash_message SPX_NAMESPACE(hash_message) -void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx); - - - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/hash_haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/hash_haraka.c deleted file mode 100644 index 750a67423b..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/hash_haraka.c +++ /dev/null @@ -1,81 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "utils.h" - -#include "haraka.h" -#include "hash.h" - -/* - * Computes PRF(key, addr), given a secret key of SPX_N bytes and an address - */ -void prf_addr(unsigned char *out, const spx_ctx *ctx, - const uint32_t addr[8]) { - /* Since SPX_N may be smaller than 32, we need temporary buffers. */ - unsigned char outbuf[32]; - unsigned char buf[64] = {0}; - - memcpy(buf, addr, SPX_ADDR_BYTES); - memcpy(buf + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); - - haraka512(outbuf, (const void *)buf, ctx); - memcpy(out, outbuf, SPX_N); -} - -/** - * Computes the message-dependent randomness R, using a secret seed and an - * optional randomization value as well as the message. - */ -void gen_message_random(unsigned char *R, const unsigned char *sk_prf, - const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx) { - uint8_t s_inc[65]; - - haraka_S_inc_init(s_inc); - haraka_S_inc_absorb(s_inc, sk_prf, SPX_N, ctx); - haraka_S_inc_absorb(s_inc, optrand, SPX_N, ctx); - haraka_S_inc_absorb(s_inc, m, mlen, ctx); - haraka_S_inc_finalize(s_inc); - haraka_S_inc_squeeze(R, SPX_N, s_inc, ctx); -} - -/** - * Computes the message hash using R, the public key, and the message. - * Outputs the message digest and the index of the leaf. The index is split in - * the tree index and the leaf index, for convenient copying to an address. - */ -void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx) { -#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) -#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) -#define SPX_LEAF_BITS SPX_TREE_HEIGHT -#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) -#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) - - unsigned char buf[SPX_DGST_BYTES]; - unsigned char *bufp = buf; - uint8_t s_inc[65]; - - haraka_S_inc_init(s_inc); - haraka_S_inc_absorb(s_inc, R, SPX_N, ctx); - haraka_S_inc_absorb(s_inc, pk + SPX_N, SPX_N, ctx); // Only absorb root part of pk - haraka_S_inc_absorb(s_inc, m, mlen, ctx); - haraka_S_inc_finalize(s_inc); - haraka_S_inc_squeeze(buf, SPX_DGST_BYTES, s_inc, ctx); - - memcpy(digest, bufp, SPX_FORS_MSG_BYTES); - bufp += SPX_FORS_MSG_BYTES; - - - *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); - *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); - bufp += SPX_TREE_BYTES; - - *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); - *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/hash_harakax4.c b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/hash_harakax4.c deleted file mode 100644 index cfa5162d79..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/hash_harakax4.c +++ /dev/null @@ -1,35 +0,0 @@ -#include -#include - -#include "address.h" -#include "harakax4.h" -#include "hashx4.h" -#include "params.h" - -/* - * 4-way parallel version of prf_addr; takes 4x as much input and output - */ -#define prf_addrx4 SPX_NAMESPACE(prf_addrx4) -void prf_addrx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const spx_ctx *ctx, - const uint32_t addrx4[4 * 8]) { - unsigned char bufx4[4 * 64] = {0}; - /* Since SPX_N may be smaller than 32, we need temporary buffers. */ - unsigned char outbuf[4 * 32]; - unsigned int i; - - for (i = 0; i < 4; i++) { - memcpy(bufx4 + i * 64, addrx4 + i * 8, SPX_ADDR_BYTES); - memcpy(bufx4 + i * 64 + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); - } - - haraka512x4(outbuf, bufx4, ctx); - - memcpy(out0, outbuf, SPX_N); - memcpy(out1, outbuf + 32, SPX_N); - memcpy(out2, outbuf + 64, SPX_N); - memcpy(out3, outbuf + 96, SPX_N); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/hashx4.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/hashx4.h deleted file mode 100644 index 3751a0ebd0..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/hashx4.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef SPX_HASHX4_H -#define SPX_HASHX4_H - -#include - -#include "context.h" -#include "params.h" - -#define prf_addrx4 SPX_NAMESPACE(prf_addrx4) -void prf_addrx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const spx_ctx *ctx, - const uint32_t addrx4[4 * 8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/merkle.c b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/merkle.c deleted file mode 100644 index f57811c1ac..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/merkle.c +++ /dev/null @@ -1,64 +0,0 @@ -#include -#include - -#include "merkle.h" - -#include "address.h" -#include "params.h" -#include "utils.h" -#include "utilsx4.h" -#include "wots.h" -#include "wotsx4.h" - -/* - * This generates a Merkle signature (WOTS signature followed by the Merkle - * authentication path). - */ -void merkle_sign(uint8_t *sig, unsigned char *root, - const spx_ctx *ctx, - uint32_t wots_addr[8], uint32_t tree_addr[8], - uint32_t idx_leaf) { - unsigned char *auth_path = sig + SPX_WOTS_BYTES; - uint32_t tree_addrx4[4 * 8] = { 0 }; - int j; - struct leaf_info_x4 info = { 0 }; - unsigned steps[ SPX_WOTS_LEN ]; - - info.wots_sig = sig; - chain_lengths(steps, root); - info.wots_steps = steps; - - for (j = 0; j < 4; j++) { - set_type(&tree_addrx4[8 * j], SPX_ADDR_TYPE_HASHTREE); - set_type(&info.leaf_addr[8 * j], SPX_ADDR_TYPE_WOTS); - set_type(&info.pk_addr[8 * j], SPX_ADDR_TYPE_WOTSPK); - copy_subtree_addr(&tree_addrx4[8 * j], tree_addr); - copy_subtree_addr(&info.leaf_addr[8 * j], wots_addr); - copy_subtree_addr(&info.pk_addr[8 * j], wots_addr); - } - - info.wots_sign_leaf = idx_leaf; - - treehashx4(root, auth_path, ctx, - idx_leaf, 0, - SPX_TREE_HEIGHT, - wots_gen_leafx4, - tree_addrx4, &info); -} - -/* Compute root node of the top-most subtree. */ -void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { - /* We do not need the auth path in key generation, but it simplifies the - code to have just one treehash routine that computes both root and path - in one function. */ - unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; - uint32_t top_tree_addr[8] = {0}; - uint32_t wots_addr[8] = {0}; - - set_layer_addr(top_tree_addr, SPX_D - 1); - set_layer_addr(wots_addr, SPX_D - 1); - - merkle_sign(auth_path, root, ctx, - wots_addr, top_tree_addr, - ~0U /* ~0 means "don't bother generating an auth path */ ); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/merkle.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/merkle.h deleted file mode 100644 index 769cf2e970..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/merkle.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef MERKLE_H_ -#define MERKLE_H_ - -#include - -#include "context.h" -#include "params.h" - -/* Generate a Merkle signature (WOTS signature followed by the Merkle */ -/* authentication path) */ -#define merkle_sign SPX_NAMESPACE(merkle_sign) -void merkle_sign(uint8_t *sig, unsigned char *root, - const spx_ctx *ctx, - uint32_t wots_addr[8], uint32_t tree_addr[8], - uint32_t idx_leaf); - -/* Compute the root node of the top-most subtree. */ -#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) -void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); - -#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/nistapi.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/nistapi.h deleted file mode 100644 index 3cb71afad4..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/nistapi.h +++ /dev/null @@ -1,87 +0,0 @@ -#ifndef SPX_API_H -#define SPX_API_H - -#include -#include - -#include "params.h" - -#define CRYPTO_ALGNAME "SPHINCS+" - -#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES -#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES -#define CRYPTO_BYTES SPX_BYTES -#define CRYPTO_SEEDBYTES (3*SPX_N) - -/* - * Returns the length of a secret key, in bytes - */ -#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) -size_t crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) -size_t crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) -size_t crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) -size_t crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) -int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) -int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) -int crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) -int crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -#define crypto_sign SPX_NAMESPACE(crypto_sign) -int crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) -int crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/params.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/params.h deleted file mode 100644 index f6cad0d391..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/params.h +++ /dev/null @@ -1,56 +0,0 @@ -#ifndef SPX_PARAMS_H -#define SPX_PARAMS_H - -#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_##s - -/* Hash output length in bytes. */ -#define SPX_N 24 -/* Height of the hypertree. */ -#define SPX_FULL_HEIGHT 63 -/* Number of subtree layer. */ -#define SPX_D 7 -/* FORS tree dimensions. */ -#define SPX_FORS_HEIGHT 14 -#define SPX_FORS_TREES 17 -/* Winternitz parameter, */ -#define SPX_WOTS_W 16 - -/* The hash function is defined by linking a different hash.c file, as opposed - to setting a #define constant. */ - -/* For clarity */ -#define SPX_ADDR_BYTES 32 - -/* WOTS parameters. */ -#define SPX_WOTS_LOGW 4 - -#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) - -/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#define SPX_WOTS_LEN2 3 - -#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) -#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) -#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES - -/* Subtree size. */ -#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) - -//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT -// #error SPX_D should always divide SPX_FULL_HEIGHT -//#endif - -/* FORS parameters. */ -#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) -#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) -#define SPX_FORS_PK_BYTES SPX_N - -/* Resulting SPX sizes. */ -#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ - SPX_FULL_HEIGHT * SPX_N) -#define SPX_PK_BYTES (2 * SPX_N) -#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) - -#include "haraka_offsets.h" - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/sign.c b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/sign.c deleted file mode 100644 index 9d0c7d1b22..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/sign.c +++ /dev/null @@ -1,286 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "context.h" -#include "fors.h" -#include "hash.h" -#include "merkle.h" -#include "nistapi.h" -#include "params.h" -#include "randombytes.h" -#include "thash.h" -#include "utils.h" -#include "wots.h" - -/* - * Returns the length of a secret key, in bytes - */ -size_t crypto_sign_secretkeybytes(void) { - return CRYPTO_SECRETKEYBYTES; -} - -/* - * Returns the length of a public key, in bytes - */ -size_t crypto_sign_publickeybytes(void) { - return CRYPTO_PUBLICKEYBYTES; -} - -/* - * Returns the length of a signature, in bytes - */ -size_t crypto_sign_bytes(void) { - return CRYPTO_BYTES; -} - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t crypto_sign_seedbytes(void) { - return CRYPTO_SEEDBYTES; -} - -/* - * Generates an SPX key pair given a seed of length - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed) { - spx_ctx ctx; - - /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ - memcpy(sk, seed, CRYPTO_SEEDBYTES); - - memcpy(pk, sk + 2 * SPX_N, SPX_N); - - memcpy(ctx.pub_seed, pk, SPX_N); - memcpy(ctx.sk_seed, sk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - /* Compute root node of the top-most subtree. */ - merkle_gen_root(sk + 3 * SPX_N, &ctx); - - // cleanup - free_hash_function(&ctx); - - memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); - - return 0; -} - -/* - * Generates an SPX key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { - uint8_t seed[CRYPTO_SEEDBYTES]; - randombytes(seed, CRYPTO_SEEDBYTES); - crypto_sign_seed_keypair(pk, sk, seed); - - return 0; -} - -/** - * Returns an array containing a detached signature. - */ -int crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - spx_ctx ctx; - - const uint8_t *sk_prf = sk + SPX_N; - const uint8_t *pk = sk + 2 * SPX_N; - - uint8_t optrand[SPX_N]; - uint8_t mhash[SPX_FORS_MSG_BYTES]; - uint8_t root[SPX_N]; - uint32_t i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - - memcpy(ctx.sk_seed, sk, SPX_N); - memcpy(ctx.pub_seed, pk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - set_type(wots_addr, SPX_ADDR_TYPE_WOTS); - set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); - - /* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ - randombytes(optrand, SPX_N); - /* Compute the digest randomization value. */ - gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); - - /* Derive the message digest and leaf index from R, PK and M. */ - hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); - sig += SPX_N; - - set_tree_addr(wots_addr, tree); - set_keypair_addr(wots_addr, idx_leaf); - - /* Sign the message hash using FORS. */ - fors_sign(sig, root, mhash, &ctx, wots_addr); - sig += SPX_FORS_BYTES; - - for (i = 0; i < SPX_D; i++) { - set_layer_addr(tree_addr, i); - set_tree_addr(tree_addr, tree); - - copy_subtree_addr(wots_addr, tree_addr); - set_keypair_addr(wots_addr, idx_leaf); - - merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); - sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); - tree = tree >> SPX_TREE_HEIGHT; - } - - free_hash_function(&ctx); - - *siglen = SPX_BYTES; - - return 0; -} - -/** - * Verifies a detached signature and message under a given public key. - */ -int crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk) { - spx_ctx ctx; - const uint8_t *pub_root = pk + SPX_N; - uint8_t mhash[SPX_FORS_MSG_BYTES]; - uint8_t wots_pk[SPX_WOTS_BYTES]; - uint8_t root[SPX_N]; - uint8_t leaf[SPX_N]; - unsigned int i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - if (siglen != SPX_BYTES) { - return -1; - } - - memcpy(ctx.pub_seed, pk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - set_type(wots_addr, SPX_ADDR_TYPE_WOTS); - set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); - set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); - - /* Derive the message digest and leaf index from R || PK || M. */ - /* The additional SPX_N is a result of the hash domain separator. */ - hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); - sig += SPX_N; - - /* Layer correctly defaults to 0, so no need to set_layer_addr */ - set_tree_addr(wots_addr, tree); - set_keypair_addr(wots_addr, idx_leaf); - - fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); - sig += SPX_FORS_BYTES; - - /* For each subtree.. */ - for (i = 0; i < SPX_D; i++) { - set_layer_addr(tree_addr, i); - set_tree_addr(tree_addr, tree); - - copy_subtree_addr(wots_addr, tree_addr); - set_keypair_addr(wots_addr, idx_leaf); - - copy_keypair_addr(wots_pk_addr, wots_addr); - - /* The WOTS public key is only correct if the signature was correct. */ - /* Initially, root is the FORS pk, but on subsequent iterations it is - the root of the subtree below the currently processed subtree. */ - wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); - sig += SPX_WOTS_BYTES; - - /* Compute the leaf node using the WOTS public key. */ - thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); - - /* Compute the root node of this subtree. */ - compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, - &ctx, tree_addr); - sig += SPX_TREE_HEIGHT * SPX_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); - tree = tree >> SPX_TREE_HEIGHT; - } - - // cleanup - free_hash_function(&ctx); - - /* Check if the root node equals the root node in the public key. */ - if (memcmp(root, pub_root, SPX_N) != 0) { - return -1; - } - - return 0; -} - - -/** - * Returns an array containing the signature followed by the message. - */ -int crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk) { - size_t siglen; - - crypto_sign_signature(sm, &siglen, m, mlen, sk); - - memmove(sm + SPX_BYTES, m, mlen); - *smlen = siglen + mlen; - - return 0; -} - -/** - * Verifies a given signature-message pair under a given public key. - */ -int crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk) { - /* The API caller does not necessarily know what size a signature should be - but SPHINCS+ signatures are always exactly SPX_BYTES. */ - if (smlen < SPX_BYTES) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - *mlen = smlen - SPX_BYTES; - - if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - /* If verification was successful, move the message to the right place. */ - memmove(m, sm + SPX_BYTES, *mlen); - - return 0; -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/thash.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/thash.h deleted file mode 100644 index 8687ccfb4d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/thash.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef SPX_THASH_H -#define SPX_THASH_H - -#include "context.h" -#include "params.h" - -#include - -#define thash SPX_NAMESPACE(thash) -void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/thash_haraka_simple.c b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/thash_haraka_simple.c deleted file mode 100644 index 207777bf8d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/thash_haraka_simple.c +++ /dev/null @@ -1,36 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "thash.h" -#include "utils.h" - -#include "haraka.h" - -/** - * Takes an array of inblocks concatenated arrays of SPX_N bytes. - */ -void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]) { - PQCLEAN_VLA(uint8_t, buf, SPX_ADDR_BYTES + inblocks * SPX_N); - unsigned char outbuf[32]; - unsigned char buf_tmp[64]; - - if (inblocks == 1) { - /* F function */ - /* Since SPX_N may be smaller than 32, we need a temporary buffer. */ - memset(buf_tmp, 0, 64); - memcpy(buf_tmp, addr, 32); - memcpy(buf_tmp + SPX_ADDR_BYTES, in, SPX_N); - - haraka512(outbuf, buf_tmp, ctx); - memcpy(out, outbuf, SPX_N); - } else { - /* All other tweakable hashes*/ - memcpy(buf, addr, 32); - memcpy(buf + SPX_ADDR_BYTES, in, inblocks * SPX_N); - - haraka_S(out, SPX_N, buf, SPX_ADDR_BYTES + inblocks * SPX_N, ctx); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/thash_haraka_simplex4.c b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/thash_haraka_simplex4.c deleted file mode 100644 index 2ee763d7d9..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/thash_haraka_simplex4.c +++ /dev/null @@ -1,67 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "thashx4.h" - -#include "harakax4.h" - -#include "utils.h" - -/** - * 4-way parallel version of thash; takes 4x as much input and output - */ -#define thashx4 SPX_NAMESPACE(thashx4) -void thashx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addrx4[4 * 8]) { - PQCLEAN_VLA(unsigned char, buf0, SPX_ADDR_BYTES + inblocks * SPX_N); - PQCLEAN_VLA(unsigned char, buf1, SPX_ADDR_BYTES + inblocks * SPX_N); - PQCLEAN_VLA(unsigned char, buf2, SPX_ADDR_BYTES + inblocks * SPX_N); - PQCLEAN_VLA(unsigned char, buf3, SPX_ADDR_BYTES + inblocks * SPX_N); - unsigned char outbuf[32 * 4]; - unsigned char buf_tmp[64 * 4]; - - if (inblocks == 1) { - memset(buf_tmp, 0, 64 * 4); - - memcpy(buf_tmp, addrx4 + 0 * 8, 32); - memcpy(buf_tmp + 64, addrx4 + 1 * 8, 32); - memcpy(buf_tmp + 128, addrx4 + 2 * 8, 32); - memcpy(buf_tmp + 192, addrx4 + 3 * 8, 32); - - memcpy(buf_tmp + SPX_ADDR_BYTES, in0, SPX_N); - memcpy(buf_tmp + SPX_ADDR_BYTES + 64, in1, SPX_N); - memcpy(buf_tmp + SPX_ADDR_BYTES + 128, in2, SPX_N); - memcpy(buf_tmp + SPX_ADDR_BYTES + 192, in3, SPX_N); - - haraka512x4(outbuf, buf_tmp, ctx); - - memcpy(out0, outbuf, SPX_N); - memcpy(out1, outbuf + 32, SPX_N); - memcpy(out2, outbuf + 64, SPX_N); - memcpy(out3, outbuf + 96, SPX_N); - } else { - /* All other tweakable hashes*/ - memcpy(buf0, addrx4 + 0 * 8, 32); - memcpy(buf1, addrx4 + 1 * 8, 32); - memcpy(buf2, addrx4 + 2 * 8, 32); - memcpy(buf3, addrx4 + 3 * 8, 32); - - memcpy(buf0 + SPX_ADDR_BYTES, in0, inblocks * SPX_N); - memcpy(buf1 + SPX_ADDR_BYTES, in1, inblocks * SPX_N); - memcpy(buf2 + SPX_ADDR_BYTES, in2, inblocks * SPX_N); - memcpy(buf3 + SPX_ADDR_BYTES, in3, inblocks * SPX_N); - - haraka_Sx4(out0, out1, out2, out3, SPX_N, - buf0, buf1, buf2, buf3, SPX_ADDR_BYTES + inblocks * SPX_N, - ctx); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/thashx4.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/thashx4.h deleted file mode 100644 index 64798a3727..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/thashx4.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef SPX_THASHX4_H -#define SPX_THASHX4_H - -#include - -#include "context.h" -#include "params.h" - -#define thashx4 SPX_NAMESPACE(thashx4) -void thashx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addrx4[4 * 8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/utils.c b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/utils.c deleted file mode 100644 index 177b541fb9..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/utils.c +++ /dev/null @@ -1,148 +0,0 @@ -#include - -#include "utils.h" - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "thash.h" - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void ull_to_bytes(unsigned char *out, unsigned int outlen, - unsigned long long in) { - int i; - - /* Iterate over out in decreasing order, for big-endianness. */ - for (i = (signed int)outlen - 1; i >= 0; i--) { - out[i] = in & 0xff; - in = in >> 8; - } -} - -void u32_to_bytes(unsigned char *out, uint32_t in) { - out[0] = (unsigned char)(in >> 24); - out[1] = (unsigned char)(in >> 16); - out[2] = (unsigned char)(in >> 8); - out[3] = (unsigned char)in; -} - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { - unsigned long long retval = 0; - unsigned int i; - - for (i = 0; i < inlen; i++) { - retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); - } - return retval; -} - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void compute_root(unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const spx_ctx *ctx, uint32_t addr[8]) { - uint32_t i; - unsigned char buffer[2 * SPX_N]; - - /* If leaf_idx is odd (last bit = 1), current path element is a right child - and auth_path has to go left. Otherwise it is the other way around. */ - if (leaf_idx & 1) { - memcpy(buffer + SPX_N, leaf, SPX_N); - memcpy(buffer, auth_path, SPX_N); - } else { - memcpy(buffer, leaf, SPX_N); - memcpy(buffer + SPX_N, auth_path, SPX_N); - } - auth_path += SPX_N; - - for (i = 0; i < tree_height - 1; i++) { - leaf_idx >>= 1; - idx_offset >>= 1; - /* Set the address of the node we're creating. */ - set_tree_height(addr, i + 1); - set_tree_index(addr, leaf_idx + idx_offset); - - /* Pick the right or left neighbor, depending on parity of the node. */ - if (leaf_idx & 1) { - thash(buffer + SPX_N, buffer, 2, ctx, addr); - memcpy(buffer, auth_path, SPX_N); - } else { - thash(buffer, buffer, 2, ctx, addr); - memcpy(buffer + SPX_N, auth_path, SPX_N); - } - auth_path += SPX_N; - } - - /* The last iteration is exceptional; we do not copy an auth_path node. */ - leaf_idx >>= 1; - idx_offset >>= 1; - set_tree_height(addr, tree_height); - set_tree_index(addr, leaf_idx + idx_offset); - thash(root, buffer, 2, ctx, addr); -} - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const spx_ctx * /* ctx */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), - uint32_t tree_addr[8]) { - PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); - PQCLEAN_VLA(unsigned int, heights, tree_height + 1); - unsigned int offset = 0; - uint32_t idx; - uint32_t tree_idx; - - for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { - /* Add the next leaf node to the stack. */ - gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); - offset++; - heights[offset - 1] = 0; - - /* If this is a node we need for the auth path.. */ - if ((leaf_idx ^ 0x1) == idx) { - memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); - } - - /* While the top-most nodes are of equal height.. */ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { - /* Compute index of the new node, in the next layer. */ - tree_idx = (idx >> (heights[offset - 1] + 1)); - - /* Set the address of the node we're creating. */ - set_tree_height(tree_addr, heights[offset - 1] + 1); - set_tree_index(tree_addr, - tree_idx + (idx_offset >> (heights[offset - 1] + 1))); - /* Hash the top-most nodes from the stack together. */ - thash(stack + (offset - 2)*SPX_N, - stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); - offset--; - /* Note that the top-most node is now one layer higher. */ - heights[offset - 1]++; - - /* If this is a node we need for the auth path.. */ - if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_path + heights[offset - 1]*SPX_N, - stack + (offset - 1)*SPX_N, SPX_N); - } - } - } - memcpy(root, stack, SPX_N); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/utils.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/utils.h deleted file mode 100644 index 64f5d5a53a..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/utils.h +++ /dev/null @@ -1,58 +0,0 @@ -#ifndef SPX_UTILS_H -#define SPX_UTILS_H - -#include - -#include "compat.h" -#include "context.h" -#include "params.h" - - -/* To support MSVC use alloca() instead of VLAs. See #20. */ - - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) -void ull_to_bytes(unsigned char *out, unsigned int outlen, - unsigned long long in); -#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) -void u32_to_bytes(unsigned char *out, uint32_t in); - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) -unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -#define compute_root SPX_NAMESPACE(compute_root) -void compute_root(unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const spx_ctx *ctx, uint32_t addr[8]); - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -#define treehash SPX_NAMESPACE(treehash) -void treehash(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const spx_ctx *ctx /* ctx */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), - uint32_t tree_addr[8]); - - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/utilsx4.c b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/utilsx4.c deleted file mode 100644 index 1638677194..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/utilsx4.c +++ /dev/null @@ -1,138 +0,0 @@ -#include - -#include "utilsx4.h" - -#include "address.h" -#include "params.h" -#include "thashx4.h" -#include "utils.h" - -/* - * Generate the entire Merkle tree, computing the authentication path for leaf_idx, - * and the resulting root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) - * - * This expects tree_addrx4 to be initialized to 4 parallel addr structures for - * the Merkle tree nodes - * - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - * - * This works by using the standard Merkle tree building algorithm, except - * that each 'node' tracked is actually 4 consecutive nodes in the real tree. - * When we combine two logical nodes ABCD and WXYZ, we perform the H - * operation on adjacent real nodes, forming the parent logical node - * (AB)(CD)(WX)(YZ) - * - * When we get to the top two levels of the real tree (where there is only - * one logical node), we continue this operation two more times; the right - * most real node will by the actual root (and the other 3 nodes will be - * garbage). We follow the same thashx4 logic so that the 'extract - * authentication path components' part of the loop is still executed (and - * to simplify the code somewhat) - * - * This currently assumes tree_height >= 2; I suspect that doing an adjusting - * idx, addr_idx on the gen_leafx4 call if tree_height < 2 would fix it; since - * we don't actually use such short trees, I haven't bothered - */ -void treehashx4(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, - uint32_t tree_height, - void (*gen_leafx4)( - unsigned char * /* Where to write the leaves */, - const spx_ctx *, - uint32_t idx, void *info), - uint32_t tree_addrx4[4 * 8], - void *info) { - /* This is where we keep the intermediate nodes */ - PQCLEAN_VLA(unsigned char, stackx4, tree_height * 4 * SPX_N); - uint32_t left_adj = 0, prev_left_adj = 0; /* When we're doing the top 3 */ - /* levels, the left-most part of the tree isn't at the beginning */ - /* of current[]. These give the offset of the actual start */ - - uint32_t idx; - uint32_t max_idx = (1U << (tree_height - 2)) - 1; - for (idx = 0;; idx++) { - unsigned char current[4 * SPX_N]; /* Current logical node */ - gen_leafx4( current, ctx, 4 * idx + idx_offset, - info ); - - /* Now combine the freshly generated right node with previously */ - /* generated left ones */ - uint32_t internal_idx_offset = idx_offset; - uint32_t internal_idx = idx; - uint32_t internal_leaf = leaf_idx; - uint32_t h; /* The height we are in the Merkle tree */ - for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { - - /* Special processing if we're at the top of the tree */ - if (h >= tree_height - 2) { - if (h == tree_height) { - /* We hit the root; return it */ - memcpy( root, ¤t[3 * SPX_N], SPX_N ); - return; - } - /* The tree indexing logic is a bit off in this case */ - /* Adjust it so that the left-most node of the part of */ - /* the tree that we're processing has index 0 */ - prev_left_adj = left_adj; - left_adj = 4U - (1 << (tree_height - h - 1)); - } - - /* Check if we hit the top of the tree */ - if (h == tree_height) { - /* We hit the root; return it */ - memcpy( root, ¤t[3 * SPX_N], SPX_N ); - return; - } - - /* - * Check if one of the nodes we have is a part of the - * authentication path; if it is, write it out - */ - if ((((internal_idx << 2) ^ internal_leaf) & ~0x3U) == 0) { - memcpy( &auth_path[ h * SPX_N ], - ¤t[(((internal_leaf & 3) ^ 1) + prev_left_adj) * SPX_N], - SPX_N ); - } - - /* - * Check if we're at a left child; if so, stop going up the stack - * Exception: if we've reached the end of the tree, keep on going - * (so we combine the last 4 nodes into the one root node in two - * more iterations) - */ - if ((internal_idx & 1) == 0 && idx < max_idx) { - break; - } - - /* Ok, we're at a right node (or doing the top 3 levels) */ - /* Now combine the left and right logical nodes together */ - - /* Set the address of the node we're creating. */ - unsigned int j; - internal_idx_offset >>= 1; - for (j = 0; j < 4; j++) { - set_tree_height(tree_addrx4 + j * 8, h + 1); - set_tree_index(tree_addrx4 + j * 8, - (4 / 2) * (internal_idx & ~1U) + j - left_adj + internal_idx_offset ); - } - unsigned char *left = &stackx4[h * 4 * SPX_N]; - thashx4( ¤t[0 * SPX_N], - ¤t[1 * SPX_N], - ¤t[2 * SPX_N], - ¤t[3 * SPX_N], - &left [0 * SPX_N], - &left [2 * SPX_N], - ¤t[0 * SPX_N], - ¤t[2 * SPX_N], - 2, ctx, tree_addrx4); - } - - /* We've hit a left child; save the current for when we get the */ - /* corresponding right right */ - memcpy( &stackx4[h * 4 * SPX_N], current, 4 * SPX_N); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/utilsx4.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/utilsx4.h deleted file mode 100644 index facb874b18..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/utilsx4.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef SPX_UTILSX4_H -#define SPX_UTILSX4_H - -#include - -#include "context.h" -#include "params.h" - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - * - * This implementation uses AVX to compute internal nodes 4 at a time (in - * parallel) - */ -#define treehashx4 SPX_NAMESPACE(treehashx4) -void treehashx4(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leafx4)( - unsigned char * /* Where to write the leaves */, - const spx_ctx * /* ctx */, - uint32_t addr_idx, void *info), - uint32_t tree_addrx4[4 * 8], void *info); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/wots.c b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/wots.c deleted file mode 100644 index 4d5041ce05..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/wots.c +++ /dev/null @@ -1,269 +0,0 @@ -#include -#include - -#include "wots.h" - -#include "address.h" -#include "hash.h" -#include "hashx4.h" -#include "params.h" -#include "thash.h" -#include "thashx4.h" -#include "utils.h" -#include "utilsx4.h" -#include "wotsx4.h" - -// TODO clarify address expectations, and make them more uniform. -// TODO i.e. do we expect types to be set already? -// TODO and do we expect modifications or copies? - -/** - * Computes up the chains - */ -static void gen_chains( - unsigned char *out, - const unsigned char *in, - unsigned int start[SPX_WOTS_LEN], - const unsigned int steps[SPX_WOTS_LEN], - const spx_ctx *ctx, - uint32_t addr[8]) { - uint32_t i, j, k, idx, watching; - int done; - unsigned char empty[SPX_N]; - unsigned char *bufs[4]; - uint32_t addrs[8 * 4]; - - int l; - uint16_t counts[SPX_WOTS_W] = { 0 }; - uint16_t idxs[SPX_WOTS_LEN]; - uint16_t total, newTotal; - - /* set addrs = {addr, addr, addr, addr} */ - for (j = 0; j < 4; j++) { - memcpy(addrs + j * 8, addr, sizeof(uint32_t) * 8); - } - - /* Initialize out with the value at position 'start'. */ - memcpy(out, in, SPX_WOTS_LEN * SPX_N); - - /* Sort the chains in reverse order by steps using counting sort. */ - for (i = 0; i < SPX_WOTS_LEN; i++) { - counts[steps[i]]++; - } - total = 0; - for (l = SPX_WOTS_W - 1; l >= 0; l--) { - newTotal = counts[l] + total; - counts[l] = total; - total = newTotal; - } - for (i = 0; i < SPX_WOTS_LEN; i++) { - idxs[counts[steps[i]]] = (uint16_t)i; - counts[steps[i]]++; - } - - /* We got our work cut out for us: do it! */ - for (i = 0; i < SPX_WOTS_LEN; i += 4) { - for (j = 0; j < 4 && i + j < SPX_WOTS_LEN; j++) { - idx = idxs[i + j]; - set_chain_addr(addrs + j * 8, idx); - bufs[j] = out + SPX_N * idx; - } - - /* As the chains are sorted in reverse order, we know that the first - * chain is the longest and the last one is the shortest. We keep - * an eye on whether the last chain is done and then on the one before, - * et cetera. */ - watching = 3; - done = 0; - while (i + watching >= SPX_WOTS_LEN) { - bufs[watching] = &empty[0]; - watching--; - } - - for (k = 0;; k++) { - while (k == steps[idxs[i + watching]]) { - bufs[watching] = &empty[0]; - if (watching == 0) { - done = 1; - break; - } - watching--; - } - if (done) { - break; - } - for (j = 0; j < watching + 1; j++) { - set_hash_addr(addrs + j * 8, k + start[idxs[i + j]]); - } - - thashx4(bufs[0], bufs[1], bufs[2], bufs[3], - bufs[0], bufs[1], bufs[2], bufs[3], 1, ctx, addrs); - } - } -} - -/** - * base_w algorithm as described in draft. - * Interprets an array of bytes as integers in base w. - * This only works when log_w is a divisor of 8. - */ -static void base_w(unsigned int *output, const int out_len, - const unsigned char *input) { - int in = 0; - int out = 0; - unsigned char total = 0; - int bits = 0; - int consumed; - - for (consumed = 0; consumed < out_len; consumed++) { - if (bits == 0) { - total = input[in]; - in++; - bits += 8; - } - bits -= SPX_WOTS_LOGW; - output[out] = (total >> bits) & (SPX_WOTS_W - 1); - out++; - } -} - -/* Computes the WOTS+ checksum over a message (in base_w). */ -static void wots_checksum(unsigned int *csum_base_w, - const unsigned int *msg_base_w) { - unsigned int csum = 0; - unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; - unsigned int i; - - /* Compute checksum. */ - for (i = 0; i < SPX_WOTS_LEN1; i++) { - csum += SPX_WOTS_W - 1 - msg_base_w[i]; - } - - /* Convert checksum to base_w. */ - /* Make sure expected empty zero bits are the least significant bits. */ - csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); - ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); - base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); -} - -/* Takes a message and derives the matching chain lengths. */ -void chain_lengths(unsigned int *lengths, const unsigned char *msg) { - base_w(lengths, SPX_WOTS_LEN1, msg); - wots_checksum(lengths + SPX_WOTS_LEN1, lengths); -} - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const spx_ctx *ctx, uint32_t addr[8]) { - unsigned int steps[SPX_WOTS_LEN]; - unsigned int start[SPX_WOTS_LEN]; - uint32_t i; - - chain_lengths(start, msg); - - for (i = 0; i < SPX_WOTS_LEN; i++) { - steps[i] = SPX_WOTS_W - 1 - start[i]; - } - - gen_chains(pk, sig, start, steps, ctx, addr); -} - -/* - * This generates 4 sequential WOTS public keys - * It also generates the WOTS signature if leaf_info indicates - * that we're signing with one of these WOTS keys - */ -void wots_gen_leafx4(unsigned char *dest, - const spx_ctx *ctx, - uint32_t leaf_idx, void *v_info) { - struct leaf_info_x4 *info = v_info; - uint32_t *leaf_addr = info->leaf_addr; - uint32_t *pk_addr = info->pk_addr; - unsigned int i, j, k; - unsigned char pk_buffer[ 4 * SPX_WOTS_BYTES ]; - unsigned wots_offset = SPX_WOTS_BYTES; - unsigned char *buffer; - uint32_t wots_k_mask; - unsigned wots_sign_index; - - if (((leaf_idx ^ info->wots_sign_leaf) & ~3U) == 0) { - /* We're traversing the leaf that's signing; generate the WOTS */ - /* signature */ - wots_k_mask = 0; - wots_sign_index = info->wots_sign_leaf & 3; /* Which of of the 4 */ - /* 4 slots do the signatures come from */ - } else { - /* Nope, we're just generating pk's; turn off the signature logic */ - wots_k_mask = (uint32_t)~0; - wots_sign_index = 0; - } - - for (j = 0; j < 4; j++) { - set_keypair_addr( leaf_addr + j * 8, leaf_idx + j ); - set_keypair_addr( pk_addr + j * 8, leaf_idx + j ); - } - - for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { - uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k to */ - /* the step if we're generating a signature, ~0 if we're not */ - - /* Start with the secret seed */ - for (j = 0; j < 4; j++) { - set_chain_addr(leaf_addr + j * 8, i); - set_hash_addr(leaf_addr + j * 8, 0); - set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTSPRF); - } - prf_addrx4(buffer + 0 * wots_offset, - buffer + 1 * wots_offset, - buffer + 2 * wots_offset, - buffer + 3 * wots_offset, - ctx, leaf_addr); - - for (j = 0; j < 4; j++) { - set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTS); - } - - /* Iterate down the WOTS chain */ - for (k = 0;; k++) { - /* Check if one of the values we have needs to be saved as a */ - /* part of the WOTS signature */ - if (k == wots_k) { - memcpy( info->wots_sig + i * SPX_N, - buffer + wots_sign_index * wots_offset, SPX_N ); - } - - /* Check if we hit the top of the chain */ - if (k == SPX_WOTS_W - 1) { - break; - } - - /* Iterate one step on all 4 chains */ - for (j = 0; j < 4; j++) { - set_hash_addr(leaf_addr + j * 8, k); - } - thashx4(buffer + 0 * wots_offset, - buffer + 1 * wots_offset, - buffer + 2 * wots_offset, - buffer + 3 * wots_offset, - buffer + 0 * wots_offset, - buffer + 1 * wots_offset, - buffer + 2 * wots_offset, - buffer + 3 * wots_offset, 1, ctx, leaf_addr); - } - } - - /* Do the final thash to generate the public keys */ - thashx4(dest + 0 * SPX_N, - dest + 1 * SPX_N, - dest + 2 * SPX_N, - dest + 3 * SPX_N, - pk_buffer + 0 * wots_offset, - pk_buffer + 1 * wots_offset, - pk_buffer + 2 * wots_offset, - pk_buffer + 3 * wots_offset, SPX_WOTS_LEN, ctx, pk_addr); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/wots.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/wots.h deleted file mode 100644 index 4e7692eeef..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/wots.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef SPX_WOTS_H -#define SPX_WOTS_H - -#include - -#include "context.h" -#include "params.h" - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) -void wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const spx_ctx *ctx, uint32_t addr[8]); - -/* - * Compute the chain lengths needed for a given message hash - */ -#define chain_lengths SPX_NAMESPACE(chain_lengths) -void chain_lengths(unsigned int *lengths, const unsigned char *msg); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/wotsx4.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/wotsx4.h deleted file mode 100644 index cd634f1743..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_aesni/wotsx4.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef WOTSX4_H_ -#define WOTSX4_H_ - -#include - -#include "params.h" - -/* - * This is here to provide an interface to the internal wots_gen_leafx4 - * routine. While this routine is not referenced in the package outside of - * wots.c, it is called from the stand-alone benchmark code to characterize - * the performance - */ -struct leaf_info_x4 { - unsigned char *wots_sig; - uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ - uint32_t *wots_steps; - uint32_t leaf_addr[4 * 8]; - uint32_t pk_addr[4 * 8]; -}; - -/* Macro to set the leaf_info to something 'benign', that is, it would */ -/* run with the same time as it does during the real signing process */ -/* Used only by the benchmark code */ -#define INITIALIZE_LEAF_INFO_X4(info, addr, step_buffer) { \ - (info).wots_sig = 0; \ - (info).wots_sign_leaf = ~0; \ - (info).wots_steps = step_buffer; \ - int i; \ - for (i=0; i<4; i++) { \ - memcpy( &(info).leaf_addr[8*i], addr, 32 ); \ - memcpy( &(info).pk_addr[8*i], addr, 32 ); \ - } \ - } - -#define wots_gen_leafx4 SPX_NAMESPACE(wots_gen_leafx4) -void wots_gen_leafx4(unsigned char *dest, - const spx_ctx *ctx, - uint32_t leaf_idx, void *v_info); - -#endif /* WOTSX4_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/LICENSE b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/LICENSE deleted file mode 100644 index 670154e353..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/LICENSE +++ /dev/null @@ -1,116 +0,0 @@ -CC0 1.0 Universal - -Statement of Purpose - -The laws of most jurisdictions throughout the world automatically confer -exclusive Copyright and Related Rights (defined below) upon the creator and -subsequent owner(s) (each and all, an "owner") of an original work of -authorship and/or a database (each, a "Work"). - -Certain owners wish to permanently relinquish those rights to a Work for the -purpose of contributing to a commons of creative, cultural and scientific -works ("Commons") that the public can reliably and without fear of later -claims of infringement build upon, modify, incorporate in other works, reuse -and redistribute as freely as possible in any form whatsoever and for any -purposes, including without limitation commercial purposes. These owners may -contribute to the Commons to promote the ideal of a free culture and the -further production of creative, cultural and scientific works, or to gain -reputation or greater distribution for their Work in part through the use and -efforts of others. - -For these and/or other purposes and motivations, and without any expectation -of additional consideration or compensation, the person associating CC0 with a -Work (the "Affirmer"), to the extent that he or she is an owner of Copyright -and Related Rights in the Work, voluntarily elects to apply CC0 to the Work -and publicly distribute the Work under its terms, with knowledge of his or her -Copyright and Related Rights in the Work and the meaning and intended legal -effect of CC0 on those rights. - -1. Copyright and Related Rights. A Work made available under CC0 may be -protected by copyright and related or neighboring rights ("Copyright and -Related Rights"). Copyright and Related Rights include, but are not limited -to, the following: - - i. the right to reproduce, adapt, distribute, perform, display, communicate, - and translate a Work; - - ii. moral rights retained by the original author(s) and/or performer(s); - - iii. publicity and privacy rights pertaining to a person's image or likeness - depicted in a Work; - - iv. rights protecting against unfair competition in regards to a Work, - subject to the limitations in paragraph 4(a), below; - - v. rights protecting the extraction, dissemination, use and reuse of data in - a Work; - - vi. database rights (such as those arising under Directive 96/9/EC of the - European Parliament and of the Council of 11 March 1996 on the legal - protection of databases, and under any national implementation thereof, - including any amended or successor version of such directive); and - - vii. other similar, equivalent or corresponding rights throughout the world - based on applicable law or treaty, and any national implementations thereof. - -2. Waiver. To the greatest extent permitted by, but not in contravention of, -applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and -unconditionally waives, abandons, and surrenders all of Affirmer's Copyright -and Related Rights and associated claims and causes of action, whether now -known or unknown (including existing as well as future claims and causes of -action), in the Work (i) in all territories worldwide, (ii) for the maximum -duration provided by applicable law or treaty (including future time -extensions), (iii) in any current or future medium and for any number of -copies, and (iv) for any purpose whatsoever, including without limitation -commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes -the Waiver for the benefit of each member of the public at large and to the -detriment of Affirmer's heirs and successors, fully intending that such Waiver -shall not be subject to revocation, rescission, cancellation, termination, or -any other legal or equitable action to disrupt the quiet enjoyment of the Work -by the public as contemplated by Affirmer's express Statement of Purpose. - -3. Public License Fallback. Should any part of the Waiver for any reason be -judged legally invalid or ineffective under applicable law, then the Waiver -shall be preserved to the maximum extent permitted taking into account -Affirmer's express Statement of Purpose. In addition, to the extent the Waiver -is so judged Affirmer hereby grants to each affected person a royalty-free, -non transferable, non sublicensable, non exclusive, irrevocable and -unconditional license to exercise Affirmer's Copyright and Related Rights in -the Work (i) in all territories worldwide, (ii) for the maximum duration -provided by applicable law or treaty (including future time extensions), (iii) -in any current or future medium and for any number of copies, and (iv) for any -purpose whatsoever, including without limitation commercial, advertising or -promotional purposes (the "License"). The License shall be deemed effective as -of the date CC0 was applied by Affirmer to the Work. Should any part of the -License for any reason be judged legally invalid or ineffective under -applicable law, such partial invalidity or ineffectiveness shall not -invalidate the remainder of the License, and in such case Affirmer hereby -affirms that he or she will not (i) exercise any of his or her remaining -Copyright and Related Rights in the Work or (ii) assert any associated claims -and causes of action with respect to the Work, in either case contrary to -Affirmer's express Statement of Purpose. - -4. Limitations and Disclaimers. - - a. No trademark or patent rights held by Affirmer are waived, abandoned, - surrendered, licensed or otherwise affected by this document. - - b. Affirmer offers the Work as-is and makes no representations or warranties - of any kind concerning the Work, express, implied, statutory or otherwise, - including without limitation warranties of title, merchantability, fitness - for a particular purpose, non infringement, or the absence of latent or - other defects, accuracy, or the present or absence of errors, whether or not - discoverable, all to the greatest extent permissible under applicable law. - - c. Affirmer disclaims responsibility for clearing rights of other persons - that may apply to the Work or any use thereof, including without limitation - any person's Copyright and Related Rights in the Work. Further, Affirmer - disclaims responsibility for obtaining any necessary consents, permissions - or other rights required for any use of the Work. - - d. Affirmer understands and acknowledges that Creative Commons is not a - party to this document and has no duty or obligation with respect to this - CC0 or use of the Work. - -For more information, please see - diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/address.c b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/address.c deleted file mode 100644 index d49d9f3b6b..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/address.c +++ /dev/null @@ -1,95 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "utils.h" - -/* - * Specify which level of Merkle tree (the "layer") we're working on - */ -void set_layer_addr(uint32_t addr[8], uint32_t layer) { - ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; -} - -/* - * Specify which Merkle tree within the level (the "tree address") we're working on - */ -void set_tree_addr(uint32_t addr[8], uint64_t tree) { - ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); -} - -/* - * Specify the reason we'll use this address structure for, that is, what - * hash will we compute with it. This is used so that unrelated types of - * hashes don't accidentally get the same address structure. The type will be - * one of the SPX_ADDR_TYPE constants - */ -void set_type(uint32_t addr[8], uint32_t type) { - ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; -} - -/* - * Copy the layer and tree fields of the address structure. This is used - * when we're doing multiple types of hashes within the same Merkle tree - */ -void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { - memcpy( out, in, SPX_OFFSET_TREE + 8 ); -} - -/* These functions are used for OTS addresses. */ - -/* - * Specify which Merkle leaf we're working on; that is, which OTS keypair - * we're talking about. - */ -void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { - /* We have > 256 OTS at the bottom of the Merkle tree; to specify */ - /* which one, we'd need to express it in two bytes */ - ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR2] = (unsigned char)(keypair >> 8); - ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; -} - -/* - * Copy the layer, tree and keypair fields of the address structure. This is - * used when we're doing multiple things within the same OTS keypair - */ -void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { - memcpy( out, in, SPX_OFFSET_TREE + 8 ); - ((unsigned char *)out)[SPX_OFFSET_KP_ADDR2] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR2]; - ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; -} - -/* - * Specify which Merkle chain within the OTS we're working with - * (the chain address) - */ -void set_chain_addr(uint32_t addr[8], uint32_t chain) { - ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; -} - -/* - * Specify where in the Merkle chain we are -* (the hash address) - */ -void set_hash_addr(uint32_t addr[8], uint32_t hash) { - ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; -} - -/* These functions are used for all hash tree addresses (including FORS). */ - -/* - * Specify the height of the node in the Merkle/FORS tree we are in - * (the tree height) - */ -void set_tree_height(uint32_t addr[8], uint32_t tree_height) { - ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; -} - -/* - * Specify the distance from the left edge of the node in the Merkle/FORS tree - * (the tree index) - */ -void set_tree_index(uint32_t addr[8], uint32_t tree_index) { - u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/address.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/address.h deleted file mode 100644 index 24a84eb40c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/address.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef SPX_ADDRESS_H -#define SPX_ADDRESS_H - -#include - -#include "params.h" - -/* The hash types that are passed to set_type */ -#define SPX_ADDR_TYPE_WOTS 0 -#define SPX_ADDR_TYPE_WOTSPK 1 -#define SPX_ADDR_TYPE_HASHTREE 2 -#define SPX_ADDR_TYPE_FORSTREE 3 -#define SPX_ADDR_TYPE_FORSPK 4 -#define SPX_ADDR_TYPE_WOTSPRF 5 -#define SPX_ADDR_TYPE_FORSPRF 6 - -#define set_layer_addr SPX_NAMESPACE(set_layer_addr) -void set_layer_addr(uint32_t addr[8], uint32_t layer); - -#define set_tree_addr SPX_NAMESPACE(set_tree_addr) -void set_tree_addr(uint32_t addr[8], uint64_t tree); - -#define set_type SPX_NAMESPACE(set_type) -void set_type(uint32_t addr[8], uint32_t type); - -/* Copies the layer and tree part of one address into the other */ -#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) -void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for WOTS and FORS addresses. */ - -#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) -void set_keypair_addr(uint32_t addr[8], uint32_t keypair); - -#define set_chain_addr SPX_NAMESPACE(set_chain_addr) -void set_chain_addr(uint32_t addr[8], uint32_t chain); - -#define set_hash_addr SPX_NAMESPACE(set_hash_addr) -void set_hash_addr(uint32_t addr[8], uint32_t hash); - -#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) -void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for all hash tree addresses (including FORS). */ - -#define set_tree_height SPX_NAMESPACE(set_tree_height) -void set_tree_height(uint32_t addr[8], uint32_t tree_height); - -#define set_tree_index SPX_NAMESPACE(set_tree_index) -void set_tree_index(uint32_t addr[8], uint32_t tree_index); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/api.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/api.h deleted file mode 100644 index ea16f2a221..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/api.h +++ /dev/null @@ -1,77 +0,0 @@ -#ifndef PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_API_H -#define PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_API_H - -#include -#include - -#define PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_CRYPTO_ALGNAME "SPHINCS+-haraka-192s-simple" - -#define PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_CRYPTO_SECRETKEYBYTES 96 -#define PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_CRYPTO_PUBLICKEYBYTES 48 -#define PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_CRYPTO_BYTES 16224 - -#define PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_CRYPTO_SEEDBYTES 72 - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, - const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk); -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/context.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/context.h deleted file mode 100644 index 600dfb73c7..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/context.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef SPX_CONTEXT_H -#define SPX_CONTEXT_H - -#include -#include - -#include "params.h" - -typedef struct { - uint8_t pub_seed[SPX_N]; - uint8_t sk_seed[SPX_N]; - - - uint64_t tweaked512_rc64[10][8]; - uint32_t tweaked256_rc32[10][8]; -} spx_ctx; - -#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) -void initialize_hash_function(spx_ctx *ctx); - -#define free_hash_function SPX_NAMESPACE(free_hash_function) -void free_hash_function(spx_ctx *ctx); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/context_haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/context_haraka.c deleted file mode 100644 index f1cd7e3664..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/context_haraka.c +++ /dev/null @@ -1,11 +0,0 @@ -#include "context.h" -#include "haraka.h" - -void initialize_hash_function(spx_ctx *ctx) { - tweak_constants(ctx); -} - -// we don't support heap-based haraka right now -void free_hash_function(spx_ctx *ctx) { - (void)ctx; // suppress unused variable warnings -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/fors.c b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/fors.c deleted file mode 100644 index 96ca72e986..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/fors.c +++ /dev/null @@ -1,156 +0,0 @@ -#include -#include -#include - -#include "fors.h" - -#include "address.h" -#include "hash.h" -#include "thash.h" -#include "utils.h" -#include "utilsx1.h" - -static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, - uint32_t fors_leaf_addr[8]) { - prf_addr(sk, ctx, fors_leaf_addr); -} - -static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, - const spx_ctx *ctx, - uint32_t fors_leaf_addr[8]) { - thash(leaf, sk, 1, ctx, fors_leaf_addr); -} - -struct fors_gen_leaf_info { - uint32_t leaf_addrx[8]; -}; - -static void fors_gen_leafx1(unsigned char *leaf, - const spx_ctx *ctx, - uint32_t addr_idx, void *info) { - struct fors_gen_leaf_info *fors_info = info; - uint32_t *fors_leaf_addr = fors_info->leaf_addrx; - - /* Only set the parts that the caller doesn't set */ - set_tree_index(fors_leaf_addr, addr_idx); - set_type(fors_leaf_addr, SPX_ADDR_TYPE_FORSPRF); - fors_gen_sk(leaf, ctx, fors_leaf_addr); - - set_type(fors_leaf_addr, SPX_ADDR_TYPE_FORSTREE); - fors_sk_to_leaf(leaf, leaf, - ctx, fors_leaf_addr); -} - -/** - * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - * Assumes indices has space for SPX_FORS_TREES integers. - */ -static void message_to_indices(uint32_t *indices, const unsigned char *m) { - unsigned int i, j; - unsigned int offset = 0; - - for (i = 0; i < SPX_FORS_TREES; i++) { - indices[i] = 0; - for (j = 0; j < SPX_FORS_HEIGHT; j++) { - indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); - offset++; - } - } -} - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -void fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]) { - uint32_t indices[SPX_FORS_TREES]; - unsigned char roots[SPX_FORS_TREES * SPX_N]; - uint32_t fors_tree_addr[8] = {0}; - struct fors_gen_leaf_info fors_info = {0}; - uint32_t *fors_leaf_addr = fors_info.leaf_addrx; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - copy_keypair_addr(fors_tree_addr, fors_addr); - copy_keypair_addr(fors_leaf_addr, fors_addr); - - copy_keypair_addr(fors_pk_addr, fors_addr); - set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < SPX_FORS_TREES; i++) { - idx_offset = i * (1 << SPX_FORS_HEIGHT); - - set_tree_height(fors_tree_addr, 0); - set_tree_index(fors_tree_addr, indices[i] + idx_offset); - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); - - /* Include the secret key part that produces the selected leaf node. */ - fors_gen_sk(sig, ctx, fors_tree_addr); - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); - sig += SPX_N; - - /* Compute the authentication path for this leaf node. */ - treehashx1(roots + i * SPX_N, sig, ctx, - indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx1, - fors_tree_addr, &fors_info); - - sig += SPX_N * SPX_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); -} - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -void fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]) { - uint32_t indices[SPX_FORS_TREES]; - unsigned char roots[SPX_FORS_TREES * SPX_N]; - unsigned char leaf[SPX_N]; - uint32_t fors_tree_addr[8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - copy_keypair_addr(fors_tree_addr, fors_addr); - copy_keypair_addr(fors_pk_addr, fors_addr); - - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); - set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < SPX_FORS_TREES; i++) { - idx_offset = i * (1 << SPX_FORS_HEIGHT); - - set_tree_height(fors_tree_addr, 0); - set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Derive the leaf from the included secret key part. */ - fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); - sig += SPX_N; - - /* Derive the corresponding root node of this tree. */ - compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, - sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); - sig += SPX_N * SPX_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/fors.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/fors.h deleted file mode 100644 index 509140a178..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/fors.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef SPX_FORS_H -#define SPX_FORS_H - -#include - -#include "context.h" -#include "params.h" - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -#define fors_sign SPX_NAMESPACE(fors_sign) -void fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]); - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) -void fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/haraka.c deleted file mode 100644 index a4944913b5..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/haraka.c +++ /dev/null @@ -1,913 +0,0 @@ -/* - * Constant time implementation of the Haraka hash function. - * - * The bit-sliced implementation of the AES round functions are - * based on the AES implementation in BearSSL written - * by Thomas Pornin - */ - -#include -#include -#include -#include - -#include "haraka.h" -#include "utils.h" - -#define HARAKAS_RATE 32 - -static const uint64_t haraka512_rc64[10][8] = { - {0x24cf0ab9086f628b, 0xbdd6eeecc83b8382, 0xd96fb0306cdad0a7, 0xaace082ac8f95f89, 0x449d8e8870d7041f, 0x49bb2f80b2b3e2f8, 0x0569ae98d93bb258, 0x23dc9691e7d6a4b1}, - {0xd8ba10ede0fe5b6e, 0x7ecf7dbe424c7b8e, 0x6ea9949c6df62a31, 0xbf3f3c97ec9c313e, 0x241d03a196a1861e, 0xead3a51116e5a2ea, 0x77d479fcad9574e3, 0x18657a1af894b7a0}, - {0x10671e1a7f595522, 0xd9a00ff675d28c7b, 0x2f1edf0d2b9ba661, 0xb8ff58b8e3de45f9, 0xee29261da9865c02, 0xd1532aa4b50bdf43, 0x8bf858159b231bb1, 0xdf17439d22d4f599}, - {0xdd4b2f0870b918c0, 0x757a81f3b39b1bb6, 0x7a5c556898952e3f, 0x7dd70a16d915d87a, 0x3ae61971982b8301, 0xc3ab319e030412be, 0x17c0033ac094a8cb, 0x5a0630fc1a8dc4ef}, - {0x17708988c1632f73, 0xf92ddae090b44f4f, 0x11ac0285c43aa314, 0x509059941936b8ba, 0xd03e152fa2ce9b69, 0x3fbcbcb63a32998b, 0x6204696d692254f7, 0x915542ed93ec59b4}, - {0xf4ed94aa8879236e, 0xff6cb41cd38e03c0, 0x069b38602368aeab, 0x669495b820f0ddba, 0xf42013b1b8bf9e3d, 0xcf935efe6439734d, 0xbc1dcf42ca29e3f8, 0x7e6d3ed29f78ad67}, - {0xf3b0f6837ffcddaa, 0x3a76faef934ddf41, 0xcec7ae583a9c8e35, 0xe4dd18c68f0260af, 0x2c0e5df1ad398eaa, 0x478df5236ae22e8c, 0xfb944c46fe865f39, 0xaa48f82f028132ba}, - {0x231b9ae2b76aca77, 0x292a76a712db0b40, 0x5850625dc8134491, 0x73137dd469810fb5, 0x8a12a6a202a474fd, 0xd36fd9daa78bdb80, 0xb34c5e733505706f, 0xbaf1cdca818d9d96}, - {0x2e99781335e8c641, 0xbddfe5cce47d560e, 0xf74e9bf32e5e040c, 0x1d7a709d65996be9, 0x670df36a9cf66cdd, 0xd05ef84a176a2875, 0x0f888e828cb1c44e, 0x1a79e9c9727b052c}, - {0x83497348628d84de, 0x2e9387d51f22a754, 0xb000068da2f852d6, 0x378c9e1190fd6fe5, 0x870027c316de7293, 0xe51a9d4462e047bb, 0x90ecf7f8c6251195, 0x655953bfbed90a9c}, -}; - -static inline uint32_t br_dec32le(const unsigned char *src) { - return (uint32_t)src[0] - | ((uint32_t)src[1] << 8) - | ((uint32_t)src[2] << 16) - | ((uint32_t)src[3] << 24); -} - -static void br_range_dec32le(uint32_t *v, size_t num, const unsigned char *src) { - while (num-- > 0) { - *v ++ = br_dec32le(src); - src += 4; - } -} - -static inline void br_enc32le(unsigned char *dst, uint32_t x) { - dst[0] = (unsigned char)x; - dst[1] = (unsigned char)(x >> 8); - dst[2] = (unsigned char)(x >> 16); - dst[3] = (unsigned char)(x >> 24); -} - - -static void br_range_enc32le(unsigned char *dst, const uint32_t *v, size_t num) { - while (num-- > 0) { - br_enc32le(dst, *v ++); - dst += 4; - } -} - -static void br_aes_ct64_bitslice_Sbox(uint64_t *q) { - /* - * This S-box implementation is a straightforward translation of - * the circuit described by Boyar and Peralta in "A new - * combinational logic minimization technique with applications - * to cryptology" (https://eprint.iacr.org/2009/191.pdf). - * - * Note that variables x* (input) and s* (output) are numbered - * in "reverse" order (x0 is the high bit, x7 is the low bit). - */ - - uint64_t x0, x1, x2, x3, x4, x5, x6, x7; - uint64_t y1, y2, y3, y4, y5, y6, y7, y8, y9; - uint64_t y10, y11, y12, y13, y14, y15, y16, y17, y18, y19; - uint64_t y20, y21; - uint64_t z0, z1, z2, z3, z4, z5, z6, z7, z8, z9; - uint64_t z10, z11, z12, z13, z14, z15, z16, z17; - uint64_t t0, t1, t2, t3, t4, t5, t6, t7, t8, t9; - uint64_t t10, t11, t12, t13, t14, t15, t16, t17, t18, t19; - uint64_t t20, t21, t22, t23, t24, t25, t26, t27, t28, t29; - uint64_t t30, t31, t32, t33, t34, t35, t36, t37, t38, t39; - uint64_t t40, t41, t42, t43, t44, t45, t46, t47, t48, t49; - uint64_t t50, t51, t52, t53, t54, t55, t56, t57, t58, t59; - uint64_t t60, t61, t62, t63, t64, t65, t66, t67; - uint64_t s0, s1, s2, s3, s4, s5, s6, s7; - - x0 = q[7]; - x1 = q[6]; - x2 = q[5]; - x3 = q[4]; - x4 = q[3]; - x5 = q[2]; - x6 = q[1]; - x7 = q[0]; - - /* - * Top linear transformation. - */ - y14 = x3 ^ x5; - y13 = x0 ^ x6; - y9 = x0 ^ x3; - y8 = x0 ^ x5; - t0 = x1 ^ x2; - y1 = t0 ^ x7; - y4 = y1 ^ x3; - y12 = y13 ^ y14; - y2 = y1 ^ x0; - y5 = y1 ^ x6; - y3 = y5 ^ y8; - t1 = x4 ^ y12; - y15 = t1 ^ x5; - y20 = t1 ^ x1; - y6 = y15 ^ x7; - y10 = y15 ^ t0; - y11 = y20 ^ y9; - y7 = x7 ^ y11; - y17 = y10 ^ y11; - y19 = y10 ^ y8; - y16 = t0 ^ y11; - y21 = y13 ^ y16; - y18 = x0 ^ y16; - - /* - * Non-linear section. - */ - t2 = y12 & y15; - t3 = y3 & y6; - t4 = t3 ^ t2; - t5 = y4 & x7; - t6 = t5 ^ t2; - t7 = y13 & y16; - t8 = y5 & y1; - t9 = t8 ^ t7; - t10 = y2 & y7; - t11 = t10 ^ t7; - t12 = y9 & y11; - t13 = y14 & y17; - t14 = t13 ^ t12; - t15 = y8 & y10; - t16 = t15 ^ t12; - t17 = t4 ^ t14; - t18 = t6 ^ t16; - t19 = t9 ^ t14; - t20 = t11 ^ t16; - t21 = t17 ^ y20; - t22 = t18 ^ y19; - t23 = t19 ^ y21; - t24 = t20 ^ y18; - - t25 = t21 ^ t22; - t26 = t21 & t23; - t27 = t24 ^ t26; - t28 = t25 & t27; - t29 = t28 ^ t22; - t30 = t23 ^ t24; - t31 = t22 ^ t26; - t32 = t31 & t30; - t33 = t32 ^ t24; - t34 = t23 ^ t33; - t35 = t27 ^ t33; - t36 = t24 & t35; - t37 = t36 ^ t34; - t38 = t27 ^ t36; - t39 = t29 & t38; - t40 = t25 ^ t39; - - t41 = t40 ^ t37; - t42 = t29 ^ t33; - t43 = t29 ^ t40; - t44 = t33 ^ t37; - t45 = t42 ^ t41; - z0 = t44 & y15; - z1 = t37 & y6; - z2 = t33 & x7; - z3 = t43 & y16; - z4 = t40 & y1; - z5 = t29 & y7; - z6 = t42 & y11; - z7 = t45 & y17; - z8 = t41 & y10; - z9 = t44 & y12; - z10 = t37 & y3; - z11 = t33 & y4; - z12 = t43 & y13; - z13 = t40 & y5; - z14 = t29 & y2; - z15 = t42 & y9; - z16 = t45 & y14; - z17 = t41 & y8; - - /* - * Bottom linear transformation. - */ - t46 = z15 ^ z16; - t47 = z10 ^ z11; - t48 = z5 ^ z13; - t49 = z9 ^ z10; - t50 = z2 ^ z12; - t51 = z2 ^ z5; - t52 = z7 ^ z8; - t53 = z0 ^ z3; - t54 = z6 ^ z7; - t55 = z16 ^ z17; - t56 = z12 ^ t48; - t57 = t50 ^ t53; - t58 = z4 ^ t46; - t59 = z3 ^ t54; - t60 = t46 ^ t57; - t61 = z14 ^ t57; - t62 = t52 ^ t58; - t63 = t49 ^ t58; - t64 = z4 ^ t59; - t65 = t61 ^ t62; - t66 = z1 ^ t63; - s0 = t59 ^ t63; - s6 = t56 ^ ~t62; - s7 = t48 ^ ~t60; - t67 = t64 ^ t65; - s3 = t53 ^ t66; - s4 = t51 ^ t66; - s5 = t47 ^ t65; - s1 = t64 ^ ~s3; - s2 = t55 ^ ~t67; - - q[7] = s0; - q[6] = s1; - q[5] = s2; - q[4] = s3; - q[3] = s4; - q[2] = s5; - q[1] = s6; - q[0] = s7; -} - -static void br_aes_ct_bitslice_Sbox(uint32_t *q) { - /* - * This S-box implementation is a straightforward translation of - * the circuit described by Boyar and Peralta in "A new - * combinational logic minimization technique with applications - * to cryptology" (https://eprint.iacr.org/2009/191.pdf). - * - * Note that variables x* (input) and s* (output) are numbered - * in "reverse" order (x0 is the high bit, x7 is the low bit). - */ - - uint32_t x0, x1, x2, x3, x4, x5, x6, x7; - uint32_t y1, y2, y3, y4, y5, y6, y7, y8, y9; - uint32_t y10, y11, y12, y13, y14, y15, y16, y17, y18, y19; - uint32_t y20, y21; - uint32_t z0, z1, z2, z3, z4, z5, z6, z7, z8, z9; - uint32_t z10, z11, z12, z13, z14, z15, z16, z17; - uint32_t t0, t1, t2, t3, t4, t5, t6, t7, t8, t9; - uint32_t t10, t11, t12, t13, t14, t15, t16, t17, t18, t19; - uint32_t t20, t21, t22, t23, t24, t25, t26, t27, t28, t29; - uint32_t t30, t31, t32, t33, t34, t35, t36, t37, t38, t39; - uint32_t t40, t41, t42, t43, t44, t45, t46, t47, t48, t49; - uint32_t t50, t51, t52, t53, t54, t55, t56, t57, t58, t59; - uint32_t t60, t61, t62, t63, t64, t65, t66, t67; - uint32_t s0, s1, s2, s3, s4, s5, s6, s7; - - x0 = q[7]; - x1 = q[6]; - x2 = q[5]; - x3 = q[4]; - x4 = q[3]; - x5 = q[2]; - x6 = q[1]; - x7 = q[0]; - - /* - * Top linear transformation. - */ - y14 = x3 ^ x5; - y13 = x0 ^ x6; - y9 = x0 ^ x3; - y8 = x0 ^ x5; - t0 = x1 ^ x2; - y1 = t0 ^ x7; - y4 = y1 ^ x3; - y12 = y13 ^ y14; - y2 = y1 ^ x0; - y5 = y1 ^ x6; - y3 = y5 ^ y8; - t1 = x4 ^ y12; - y15 = t1 ^ x5; - y20 = t1 ^ x1; - y6 = y15 ^ x7; - y10 = y15 ^ t0; - y11 = y20 ^ y9; - y7 = x7 ^ y11; - y17 = y10 ^ y11; - y19 = y10 ^ y8; - y16 = t0 ^ y11; - y21 = y13 ^ y16; - y18 = x0 ^ y16; - - /* - * Non-linear section. - */ - t2 = y12 & y15; - t3 = y3 & y6; - t4 = t3 ^ t2; - t5 = y4 & x7; - t6 = t5 ^ t2; - t7 = y13 & y16; - t8 = y5 & y1; - t9 = t8 ^ t7; - t10 = y2 & y7; - t11 = t10 ^ t7; - t12 = y9 & y11; - t13 = y14 & y17; - t14 = t13 ^ t12; - t15 = y8 & y10; - t16 = t15 ^ t12; - t17 = t4 ^ t14; - t18 = t6 ^ t16; - t19 = t9 ^ t14; - t20 = t11 ^ t16; - t21 = t17 ^ y20; - t22 = t18 ^ y19; - t23 = t19 ^ y21; - t24 = t20 ^ y18; - - t25 = t21 ^ t22; - t26 = t21 & t23; - t27 = t24 ^ t26; - t28 = t25 & t27; - t29 = t28 ^ t22; - t30 = t23 ^ t24; - t31 = t22 ^ t26; - t32 = t31 & t30; - t33 = t32 ^ t24; - t34 = t23 ^ t33; - t35 = t27 ^ t33; - t36 = t24 & t35; - t37 = t36 ^ t34; - t38 = t27 ^ t36; - t39 = t29 & t38; - t40 = t25 ^ t39; - - t41 = t40 ^ t37; - t42 = t29 ^ t33; - t43 = t29 ^ t40; - t44 = t33 ^ t37; - t45 = t42 ^ t41; - z0 = t44 & y15; - z1 = t37 & y6; - z2 = t33 & x7; - z3 = t43 & y16; - z4 = t40 & y1; - z5 = t29 & y7; - z6 = t42 & y11; - z7 = t45 & y17; - z8 = t41 & y10; - z9 = t44 & y12; - z10 = t37 & y3; - z11 = t33 & y4; - z12 = t43 & y13; - z13 = t40 & y5; - z14 = t29 & y2; - z15 = t42 & y9; - z16 = t45 & y14; - z17 = t41 & y8; - - /* - * Bottom linear transformation. - */ - t46 = z15 ^ z16; - t47 = z10 ^ z11; - t48 = z5 ^ z13; - t49 = z9 ^ z10; - t50 = z2 ^ z12; - t51 = z2 ^ z5; - t52 = z7 ^ z8; - t53 = z0 ^ z3; - t54 = z6 ^ z7; - t55 = z16 ^ z17; - t56 = z12 ^ t48; - t57 = t50 ^ t53; - t58 = z4 ^ t46; - t59 = z3 ^ t54; - t60 = t46 ^ t57; - t61 = z14 ^ t57; - t62 = t52 ^ t58; - t63 = t49 ^ t58; - t64 = z4 ^ t59; - t65 = t61 ^ t62; - t66 = z1 ^ t63; - s0 = t59 ^ t63; - s6 = t56 ^ ~t62; - s7 = t48 ^ ~t60; - t67 = t64 ^ t65; - s3 = t53 ^ t66; - s4 = t51 ^ t66; - s5 = t47 ^ t65; - s1 = t64 ^ ~s3; - s2 = t55 ^ ~t67; - - q[7] = s0; - q[6] = s1; - q[5] = s2; - q[4] = s3; - q[3] = s4; - q[2] = s5; - q[1] = s6; - q[0] = s7; -} - -static void br_aes_ct_ortho(uint32_t *q) { -#define SWAPN_32(cl, ch, s, x, y) do { \ - uint32_t a, b; \ - a = (x); \ - b = (y); \ - (x) = (a & (uint32_t)(cl)) | ((b & (uint32_t)(cl)) << (s)); \ - (y) = ((a & (uint32_t)(ch)) >> (s)) | (b & (uint32_t)(ch)); \ - } while (0) - -#define SWAP2_32(x, y) SWAPN_32(0x55555555, 0xAAAAAAAA, 1, x, y) -#define SWAP4_32(x, y) SWAPN_32(0x33333333, 0xCCCCCCCC, 2, x, y) -#define SWAP8_32(x, y) SWAPN_32(0x0F0F0F0F, 0xF0F0F0F0, 4, x, y) - - SWAP2_32(q[0], q[1]); - SWAP2_32(q[2], q[3]); - SWAP2_32(q[4], q[5]); - SWAP2_32(q[6], q[7]); - - SWAP4_32(q[0], q[2]); - SWAP4_32(q[1], q[3]); - SWAP4_32(q[4], q[6]); - SWAP4_32(q[5], q[7]); - - SWAP8_32(q[0], q[4]); - SWAP8_32(q[1], q[5]); - SWAP8_32(q[2], q[6]); - SWAP8_32(q[3], q[7]); -} - -static inline void add_round_key32(uint32_t *q, const uint32_t *sk) { - q[0] ^= sk[0]; - q[1] ^= sk[1]; - q[2] ^= sk[2]; - q[3] ^= sk[3]; - q[4] ^= sk[4]; - q[5] ^= sk[5]; - q[6] ^= sk[6]; - q[7] ^= sk[7]; -} - -static inline void shift_rows32(uint32_t *q) { - int i; - - for (i = 0; i < 8; i++) { - uint32_t x; - - x = q[i]; - q[i] = (x & 0x000000FF) - | ((x & 0x0000FC00) >> 2) | ((x & 0x00000300) << 6) - | ((x & 0x00F00000) >> 4) | ((x & 0x000F0000) << 4) - | ((x & 0xC0000000) >> 6) | ((x & 0x3F000000) << 2); - } -} - -static inline uint32_t rotr16(uint32_t x) { - return (x << 16) | (x >> 16); -} - -static inline void mix_columns32(uint32_t *q) { - uint32_t q0, q1, q2, q3, q4, q5, q6, q7; - uint32_t r0, r1, r2, r3, r4, r5, r6, r7; - - q0 = q[0]; - q1 = q[1]; - q2 = q[2]; - q3 = q[3]; - q4 = q[4]; - q5 = q[5]; - q6 = q[6]; - q7 = q[7]; - r0 = (q0 >> 8) | (q0 << 24); - r1 = (q1 >> 8) | (q1 << 24); - r2 = (q2 >> 8) | (q2 << 24); - r3 = (q3 >> 8) | (q3 << 24); - r4 = (q4 >> 8) | (q4 << 24); - r5 = (q5 >> 8) | (q5 << 24); - r6 = (q6 >> 8) | (q6 << 24); - r7 = (q7 >> 8) | (q7 << 24); - - q[0] = q7 ^ r7 ^ r0 ^ rotr16(q0 ^ r0); - q[1] = q0 ^ r0 ^ q7 ^ r7 ^ r1 ^ rotr16(q1 ^ r1); - q[2] = q1 ^ r1 ^ r2 ^ rotr16(q2 ^ r2); - q[3] = q2 ^ r2 ^ q7 ^ r7 ^ r3 ^ rotr16(q3 ^ r3); - q[4] = q3 ^ r3 ^ q7 ^ r7 ^ r4 ^ rotr16(q4 ^ r4); - q[5] = q4 ^ r4 ^ r5 ^ rotr16(q5 ^ r5); - q[6] = q5 ^ r5 ^ r6 ^ rotr16(q6 ^ r6); - q[7] = q6 ^ r6 ^ r7 ^ rotr16(q7 ^ r7); -} - -static void br_aes_ct64_ortho(uint64_t *q) { -#define SWAPN(cl, ch, s, x, y) do { \ - uint64_t a, b; \ - a = (x); \ - b = (y); \ - (x) = (a & (uint64_t)(cl)) | ((b & (uint64_t)(cl)) << (s)); \ - (y) = ((a & (uint64_t)(ch)) >> (s)) | (b & (uint64_t)(ch)); \ - } while (0) - -#define SWAP2(x, y) SWAPN(0x5555555555555555, 0xAAAAAAAAAAAAAAAA, 1, x, y) -#define SWAP4(x, y) SWAPN(0x3333333333333333, 0xCCCCCCCCCCCCCCCC, 2, x, y) -#define SWAP8(x, y) SWAPN(0x0F0F0F0F0F0F0F0F, 0xF0F0F0F0F0F0F0F0, 4, x, y) - - SWAP2(q[0], q[1]); - SWAP2(q[2], q[3]); - SWAP2(q[4], q[5]); - SWAP2(q[6], q[7]); - - SWAP4(q[0], q[2]); - SWAP4(q[1], q[3]); - SWAP4(q[4], q[6]); - SWAP4(q[5], q[7]); - - SWAP8(q[0], q[4]); - SWAP8(q[1], q[5]); - SWAP8(q[2], q[6]); - SWAP8(q[3], q[7]); -} - - -static void br_aes_ct64_interleave_in(uint64_t *q0, uint64_t *q1, const uint32_t *w) { - uint64_t x0, x1, x2, x3; - - x0 = w[0]; - x1 = w[1]; - x2 = w[2]; - x3 = w[3]; - x0 |= (x0 << 16); - x1 |= (x1 << 16); - x2 |= (x2 << 16); - x3 |= (x3 << 16); - x0 &= (uint64_t)0x0000FFFF0000FFFF; - x1 &= (uint64_t)0x0000FFFF0000FFFF; - x2 &= (uint64_t)0x0000FFFF0000FFFF; - x3 &= (uint64_t)0x0000FFFF0000FFFF; - x0 |= (x0 << 8); - x1 |= (x1 << 8); - x2 |= (x2 << 8); - x3 |= (x3 << 8); - x0 &= (uint64_t)0x00FF00FF00FF00FF; - x1 &= (uint64_t)0x00FF00FF00FF00FF; - x2 &= (uint64_t)0x00FF00FF00FF00FF; - x3 &= (uint64_t)0x00FF00FF00FF00FF; - *q0 = x0 | (x2 << 8); - *q1 = x1 | (x3 << 8); -} - - -static void br_aes_ct64_interleave_out(uint32_t *w, uint64_t q0, uint64_t q1) { - uint64_t x0, x1, x2, x3; - - x0 = q0 & (uint64_t)0x00FF00FF00FF00FF; - x1 = q1 & (uint64_t)0x00FF00FF00FF00FF; - x2 = (q0 >> 8) & (uint64_t)0x00FF00FF00FF00FF; - x3 = (q1 >> 8) & (uint64_t)0x00FF00FF00FF00FF; - x0 |= (x0 >> 8); - x1 |= (x1 >> 8); - x2 |= (x2 >> 8); - x3 |= (x3 >> 8); - x0 &= (uint64_t)0x0000FFFF0000FFFF; - x1 &= (uint64_t)0x0000FFFF0000FFFF; - x2 &= (uint64_t)0x0000FFFF0000FFFF; - x3 &= (uint64_t)0x0000FFFF0000FFFF; - w[0] = (uint32_t)x0 | (uint32_t)(x0 >> 16); - w[1] = (uint32_t)x1 | (uint32_t)(x1 >> 16); - w[2] = (uint32_t)x2 | (uint32_t)(x2 >> 16); - w[3] = (uint32_t)x3 | (uint32_t)(x3 >> 16); -} - -static inline void add_round_key(uint64_t *q, const uint64_t *sk) { - q[0] ^= sk[0]; - q[1] ^= sk[1]; - q[2] ^= sk[2]; - q[3] ^= sk[3]; - q[4] ^= sk[4]; - q[5] ^= sk[5]; - q[6] ^= sk[6]; - q[7] ^= sk[7]; -} - -static inline void shift_rows(uint64_t *q) { - int i; - - for (i = 0; i < 8; i++) { - uint64_t x; - - x = q[i]; - q[i] = (x & (uint64_t)0x000000000000FFFF) - | ((x & (uint64_t)0x00000000FFF00000) >> 4) - | ((x & (uint64_t)0x00000000000F0000) << 12) - | ((x & (uint64_t)0x0000FF0000000000) >> 8) - | ((x & (uint64_t)0x000000FF00000000) << 8) - | ((x & (uint64_t)0xF000000000000000) >> 12) - | ((x & (uint64_t)0x0FFF000000000000) << 4); - } -} - -static inline uint64_t rotr32(uint64_t x) { - return (x << 32) | (x >> 32); -} - -static inline void mix_columns(uint64_t *q) { - uint64_t q0, q1, q2, q3, q4, q5, q6, q7; - uint64_t r0, r1, r2, r3, r4, r5, r6, r7; - - q0 = q[0]; - q1 = q[1]; - q2 = q[2]; - q3 = q[3]; - q4 = q[4]; - q5 = q[5]; - q6 = q[6]; - q7 = q[7]; - r0 = (q0 >> 16) | (q0 << 48); - r1 = (q1 >> 16) | (q1 << 48); - r2 = (q2 >> 16) | (q2 << 48); - r3 = (q3 >> 16) | (q3 << 48); - r4 = (q4 >> 16) | (q4 << 48); - r5 = (q5 >> 16) | (q5 << 48); - r6 = (q6 >> 16) | (q6 << 48); - r7 = (q7 >> 16) | (q7 << 48); - - q[0] = q7 ^ r7 ^ r0 ^ rotr32(q0 ^ r0); - q[1] = q0 ^ r0 ^ q7 ^ r7 ^ r1 ^ rotr32(q1 ^ r1); - q[2] = q1 ^ r1 ^ r2 ^ rotr32(q2 ^ r2); - q[3] = q2 ^ r2 ^ q7 ^ r7 ^ r3 ^ rotr32(q3 ^ r3); - q[4] = q3 ^ r3 ^ q7 ^ r7 ^ r4 ^ rotr32(q4 ^ r4); - q[5] = q4 ^ r4 ^ r5 ^ rotr32(q5 ^ r5); - q[6] = q5 ^ r5 ^ r6 ^ rotr32(q6 ^ r6); - q[7] = q6 ^ r6 ^ r7 ^ rotr32(q7 ^ r7); -} - -static void interleave_constant(uint64_t *out, const unsigned char *in) { - uint32_t tmp_32_constant[16]; - int i; - - br_range_dec32le(tmp_32_constant, 16, in); - for (i = 0; i < 4; i++) { - br_aes_ct64_interleave_in(&out[i], &out[i + 4], tmp_32_constant + (i << 2)); - } - br_aes_ct64_ortho(out); -} - -static void interleave_constant32(uint32_t *out, const unsigned char *in) { - int i; - for (i = 0; i < 4; i++) { - out[2 * i] = br_dec32le(in + 4 * i); - out[2 * i + 1] = br_dec32le(in + 4 * i + 16); - } - br_aes_ct_ortho(out); -} - -void tweak_constants(spx_ctx *ctx) { - unsigned char buf[40 * 16]; - int i; - - /* Use the standard constants to generate tweaked ones. */ - memcpy((uint8_t *)ctx->tweaked512_rc64, (uint8_t *)haraka512_rc64, 40 * 16); - - /* Constants for pk.seed */ - haraka_S(buf, 40 * 16, ctx->pub_seed, SPX_N, ctx); - for (i = 0; i < 10; i++) { - interleave_constant32(ctx->tweaked256_rc32[i], buf + 32 * i); - interleave_constant(ctx->tweaked512_rc64[i], buf + 64 * i); - } -} - -static void haraka_S_absorb(unsigned char *s, unsigned int r, - const unsigned char *m, unsigned long long mlen, - unsigned char p, const spx_ctx *ctx) { - unsigned long long i; - PQCLEAN_VLA(uint8_t, t, r); - - while (mlen >= r) { - /* XOR block to state */ - for (i = 0; i < r; ++i) { - s[i] ^= m[i]; - } - haraka512_perm(s, s, ctx); - 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; ++i) { - s[i] ^= t[i]; - } -} - -static void haraka_S_squeezeblocks(unsigned char *h, unsigned long long nblocks, - unsigned char *s, unsigned int r, - const spx_ctx *ctx) { - while (nblocks > 0) { - haraka512_perm(s, s, ctx); - memcpy(h, s, HARAKAS_RATE); - h += r; - nblocks--; - } -} - -void haraka_S_inc_init(uint8_t *s_inc) { - size_t i; - - for (i = 0; i < 64; i++) { - s_inc[i] = 0; - } - s_inc[64] = 0; -} - -void haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, - const spx_ctx *ctx) { - size_t i; - - /* Recall that s_inc[64] is the non-absorbed bytes xored into the state */ - while (mlen + s_inc[64] >= HARAKAS_RATE) { - for (i = 0; i < (size_t)(HARAKAS_RATE - s_inc[64]); i++) { - /* Take the i'th byte from message - xor with the s_inc[64] + i'th byte of the state */ - s_inc[s_inc[64] + i] ^= m[i]; - } - mlen -= (size_t)(HARAKAS_RATE - s_inc[64]); - m += HARAKAS_RATE - (uint8_t)s_inc[64]; - s_inc[64] = 0; - - haraka512_perm(s_inc, s_inc, ctx); - } - - for (i = 0; i < mlen; i++) { - s_inc[s_inc[64] + i] ^= m[i]; - } - s_inc[64] += (uint8_t)mlen; -} - -void haraka_S_inc_finalize(uint8_t *s_inc) { - /* After haraka_S_inc_absorb, we are guaranteed that s_inc[64] < HARAKAS_RATE, - so we can always use one more byte for p in the current state. */ - s_inc[s_inc[64]] ^= 0x1F; - s_inc[HARAKAS_RATE - 1] ^= 128; - s_inc[64] = 0; -} - -void haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, - const spx_ctx *ctx) { - size_t i; - - /* First consume any bytes we still have sitting around */ - for (i = 0; i < outlen && i < s_inc[64]; i++) { - /* There are s_inc[64] bytes left, so r - s_inc[64] is the first - available byte. We consume from there, i.e., up to r. */ - out[i] = (uint8_t)s_inc[(HARAKAS_RATE - s_inc[64] + i)]; - } - out += i; - outlen -= i; - s_inc[64] -= (uint8_t)i; - - /* Then squeeze the remaining necessary blocks */ - while (outlen > 0) { - haraka512_perm(s_inc, s_inc, ctx); - - for (i = 0; i < outlen && i < HARAKAS_RATE; i++) { - out[i] = s_inc[i]; - } - out += i; - outlen -= i; - s_inc[64] = (uint8_t)(HARAKAS_RATE - i); - } -} - -void haraka_S(unsigned char *out, unsigned long long outlen, - const unsigned char *in, unsigned long long inlen, - const spx_ctx *ctx) { - unsigned long long i; - unsigned char s[64]; - unsigned char d[32]; - - for (i = 0; i < 64; i++) { - s[i] = 0; - } - haraka_S_absorb(s, 32, in, inlen, 0x1F, ctx); - - haraka_S_squeezeblocks(out, outlen / 32, s, 32, ctx); - out += (outlen / 32) * 32; - - if (outlen % 32) { - haraka_S_squeezeblocks(d, 1, s, 32, ctx); - for (i = 0; i < outlen % 32; i++) { - out[i] = d[i]; - } - } -} - -void haraka512_perm(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx) { - uint32_t w[16]; - uint64_t q[8], tmp_q; - unsigned int i, j; - - br_range_dec32le(w, 16, in); - for (i = 0; i < 4; i++) { - br_aes_ct64_interleave_in(&q[i], &q[i + 4], w + (i << 2)); - } - br_aes_ct64_ortho(q); - - /* AES rounds */ - for (i = 0; i < 5; i++) { - for (j = 0; j < 2; j++) { - br_aes_ct64_bitslice_Sbox(q); - shift_rows(q); - mix_columns(q); - add_round_key(q, ctx->tweaked512_rc64[2 * i + j]); - } - /* Mix states */ - for (j = 0; j < 8; j++) { - tmp_q = q[j]; - q[j] = (tmp_q & 0x0001000100010001) << 5 | - (tmp_q & 0x0002000200020002) << 12 | - (tmp_q & 0x0004000400040004) >> 1 | - (tmp_q & 0x0008000800080008) << 6 | - (tmp_q & 0x0020002000200020) << 9 | - (tmp_q & 0x0040004000400040) >> 4 | - (tmp_q & 0x0080008000800080) << 3 | - (tmp_q & 0x2100210021002100) >> 5 | - (tmp_q & 0x0210021002100210) << 2 | - (tmp_q & 0x0800080008000800) << 4 | - (tmp_q & 0x1000100010001000) >> 12 | - (tmp_q & 0x4000400040004000) >> 10 | - (tmp_q & 0x8400840084008400) >> 3; - } - } - - br_aes_ct64_ortho(q); - for (i = 0; i < 4; i ++) { - br_aes_ct64_interleave_out(w + (i << 2), q[i], q[i + 4]); - } - br_range_enc32le(out, w, 16); -} - -void haraka512(unsigned char *out, const unsigned char *in, const spx_ctx *ctx) { - int i; - - unsigned char buf[64]; - - haraka512_perm(buf, in, ctx); - /* Feed-forward */ - for (i = 0; i < 64; i++) { - buf[i] = buf[i] ^ in[i]; - } - - /* Truncated */ - memcpy(out, buf + 8, 8); - memcpy(out + 8, buf + 24, 8); - memcpy(out + 16, buf + 32, 8); - memcpy(out + 24, buf + 48, 8); -} - - -void haraka256(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx) { - uint32_t q[8], tmp_q; - int i, j; - - for (i = 0; i < 4; i++) { - q[2 * i] = br_dec32le(in + 4 * i); - q[2 * i + 1] = br_dec32le(in + 4 * i + 16); - } - br_aes_ct_ortho(q); - - /* AES rounds */ - for (i = 0; i < 5; i++) { - for (j = 0; j < 2; j++) { - br_aes_ct_bitslice_Sbox(q); - shift_rows32(q); - mix_columns32(q); - add_round_key32(q, ctx->tweaked256_rc32[2 * i + j]); - } - - /* Mix states */ - for (j = 0; j < 8; j++) { - tmp_q = q[j]; - q[j] = (tmp_q & 0x81818181) | - (tmp_q & 0x02020202) << 1 | - (tmp_q & 0x04040404) << 2 | - (tmp_q & 0x08080808) << 3 | - (tmp_q & 0x10101010) >> 3 | - (tmp_q & 0x20202020) >> 2 | - (tmp_q & 0x40404040) >> 1; - } - } - - br_aes_ct_ortho(q); - for (i = 0; i < 4; i++) { - br_enc32le(out + 4 * i, q[2 * i]); - br_enc32le(out + 4 * i + 16, q[2 * i + 1]); - } - - for (i = 0; i < 32; i++) { - out[i] ^= in[i]; - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/haraka.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/haraka.h deleted file mode 100644 index 737cb6065f..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/haraka.h +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef SPX_HARAKA_H -#define SPX_HARAKA_H - -#include "context.h" -#include "params.h" - -/* Tweak constants with seed */ -#define tweak_constants SPX_NAMESPACE(tweak_constants) -void tweak_constants(spx_ctx *ctx); - -/* Haraka Sponge */ -#define haraka_S_inc_init SPX_NAMESPACE(haraka_S_inc_init) -void haraka_S_inc_init(uint8_t *s_inc); -#define haraka_S_inc_absorb SPX_NAMESPACE(haraka_S_inc_absorb) -void haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, - const spx_ctx *ctx); -#define haraka_S_inc_finalize SPX_NAMESPACE(haraka_S_inc_finalize) -void haraka_S_inc_finalize(uint8_t *s_inc); -#define haraka_S_inc_squeeze SPX_NAMESPACE(haraka_S_inc_squeeze) -void haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, - const spx_ctx *ctx); -#define haraka_S SPX_NAMESPACE(haraka_S) -void haraka_S(unsigned char *out, unsigned long long outlen, - const unsigned char *in, unsigned long long inlen, - const spx_ctx *ctx); - -/* Applies the 512-bit Haraka permutation to in. */ -#define haraka512_perm SPX_NAMESPACE(haraka512_perm) -void haraka512_perm(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx); - -/* Implementation of Haraka-512 */ -#define haraka512 SPX_NAMESPACE(haraka512) -void haraka512(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx); - -/* Implementation of Haraka-256 */ -#define haraka256 SPX_NAMESPACE(haraka256) -void haraka256(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/haraka_offsets.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/haraka_offsets.h deleted file mode 100644 index 7c062272a0..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/haraka_offsets.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef HARAKA_OFFSETS_H_ -#define HARAKA_OFFSETS_H_ - -/* - * Offsets of various fields in the address structure when we use Haraka as - * the Sphincs+ hash function - */ - -#define SPX_OFFSET_LAYER 3 /* The byte used to specify the Merkle tree layer */ -#define SPX_OFFSET_TREE 8 /* The start of the 8 byte field used to specify the tree */ -#define SPX_OFFSET_TYPE 19 /* The byte used to specify the hash type (reason) */ -#define SPX_OFFSET_KP_ADDR2 22 /* The high byte used to specify the key pair (which one-time signature) */ -#define SPX_OFFSET_KP_ADDR1 23 /* The low byte used to specify the key pair */ -#define SPX_OFFSET_CHAIN_ADDR 27 /* The byte used to specify the chain address (which Winternitz chain) */ -#define SPX_OFFSET_HASH_ADDR 31 /* The byte used to specify the hash address (where in the Winternitz chain) */ -#define SPX_OFFSET_TREE_HGT 27 /* The byte used to specify the height of this node in the FORS or Merkle tree */ -#define SPX_OFFSET_TREE_INDEX 28 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ - -#define SPX_HARAKA 1 - -#endif /* HARAKA_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/hash.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/hash.h deleted file mode 100644 index f7c87d4c3c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/hash.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef SPX_HASH_H -#define SPX_HASH_H - -#include -#include - -#include "context.h" -#include "params.h" - -#define prf_addr SPX_NAMESPACE(prf_addr) -void prf_addr(unsigned char *out, const spx_ctx *ctx, - const uint32_t addr[8]); - -#define gen_message_random SPX_NAMESPACE(gen_message_random) -void gen_message_random(unsigned char *R, const unsigned char *sk_prf, - const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx); - -#define hash_message SPX_NAMESPACE(hash_message) -void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx); - - - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/hash_haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/hash_haraka.c deleted file mode 100644 index 750a67423b..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/hash_haraka.c +++ /dev/null @@ -1,81 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "utils.h" - -#include "haraka.h" -#include "hash.h" - -/* - * Computes PRF(key, addr), given a secret key of SPX_N bytes and an address - */ -void prf_addr(unsigned char *out, const spx_ctx *ctx, - const uint32_t addr[8]) { - /* Since SPX_N may be smaller than 32, we need temporary buffers. */ - unsigned char outbuf[32]; - unsigned char buf[64] = {0}; - - memcpy(buf, addr, SPX_ADDR_BYTES); - memcpy(buf + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); - - haraka512(outbuf, (const void *)buf, ctx); - memcpy(out, outbuf, SPX_N); -} - -/** - * Computes the message-dependent randomness R, using a secret seed and an - * optional randomization value as well as the message. - */ -void gen_message_random(unsigned char *R, const unsigned char *sk_prf, - const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx) { - uint8_t s_inc[65]; - - haraka_S_inc_init(s_inc); - haraka_S_inc_absorb(s_inc, sk_prf, SPX_N, ctx); - haraka_S_inc_absorb(s_inc, optrand, SPX_N, ctx); - haraka_S_inc_absorb(s_inc, m, mlen, ctx); - haraka_S_inc_finalize(s_inc); - haraka_S_inc_squeeze(R, SPX_N, s_inc, ctx); -} - -/** - * Computes the message hash using R, the public key, and the message. - * Outputs the message digest and the index of the leaf. The index is split in - * the tree index and the leaf index, for convenient copying to an address. - */ -void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx) { -#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) -#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) -#define SPX_LEAF_BITS SPX_TREE_HEIGHT -#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) -#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) - - unsigned char buf[SPX_DGST_BYTES]; - unsigned char *bufp = buf; - uint8_t s_inc[65]; - - haraka_S_inc_init(s_inc); - haraka_S_inc_absorb(s_inc, R, SPX_N, ctx); - haraka_S_inc_absorb(s_inc, pk + SPX_N, SPX_N, ctx); // Only absorb root part of pk - haraka_S_inc_absorb(s_inc, m, mlen, ctx); - haraka_S_inc_finalize(s_inc); - haraka_S_inc_squeeze(buf, SPX_DGST_BYTES, s_inc, ctx); - - memcpy(digest, bufp, SPX_FORS_MSG_BYTES); - bufp += SPX_FORS_MSG_BYTES; - - - *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); - *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); - bufp += SPX_TREE_BYTES; - - *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); - *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/merkle.c b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/merkle.c deleted file mode 100644 index 0c1479fd93..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/merkle.c +++ /dev/null @@ -1,59 +0,0 @@ -#include -#include - -#include "address.h" -#include "merkle.h" -#include "params.h" -#include "utils.h" -#include "utilsx1.h" -#include "wots.h" -#include "wotsx1.h" - -/* - * This generates a Merkle signature (WOTS signature followed by the Merkle - * authentication path). This is in this file because most of the complexity - * is involved with the WOTS signature; the Merkle authentication path logic - * is mostly hidden in treehashx4 - */ -void merkle_sign(uint8_t *sig, unsigned char *root, - const spx_ctx *ctx, - uint32_t wots_addr[8], uint32_t tree_addr[8], - uint32_t idx_leaf) { - unsigned char *auth_path = sig + SPX_WOTS_BYTES; - struct leaf_info_x1 info = { 0 }; - unsigned steps[ SPX_WOTS_LEN ]; - - info.wots_sig = sig; - chain_lengths(steps, root); - info.wots_steps = steps; - - set_type(&tree_addr[0], SPX_ADDR_TYPE_HASHTREE); - set_type(&info.pk_addr[0], SPX_ADDR_TYPE_WOTSPK); - copy_subtree_addr(&info.leaf_addr[0], wots_addr); - copy_subtree_addr(&info.pk_addr[0], wots_addr); - - info.wots_sign_leaf = idx_leaf; - - treehashx1(root, auth_path, ctx, - idx_leaf, 0, - SPX_TREE_HEIGHT, - wots_gen_leafx1, - tree_addr, &info); -} - -/* Compute root node of the top-most subtree. */ -void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { - /* We do not need the auth path in key generation, but it simplifies the - code to have just one treehash routine that computes both root and path - in one function. */ - unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; - uint32_t top_tree_addr[8] = {0}; - uint32_t wots_addr[8] = {0}; - - set_layer_addr(top_tree_addr, SPX_D - 1); - set_layer_addr(wots_addr, SPX_D - 1); - - merkle_sign(auth_path, root, ctx, - wots_addr, top_tree_addr, - (uint32_t)~0 /* ~0 means "don't bother generating an auth path */ ); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/merkle.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/merkle.h deleted file mode 100644 index 769cf2e970..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/merkle.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef MERKLE_H_ -#define MERKLE_H_ - -#include - -#include "context.h" -#include "params.h" - -/* Generate a Merkle signature (WOTS signature followed by the Merkle */ -/* authentication path) */ -#define merkle_sign SPX_NAMESPACE(merkle_sign) -void merkle_sign(uint8_t *sig, unsigned char *root, - const spx_ctx *ctx, - uint32_t wots_addr[8], uint32_t tree_addr[8], - uint32_t idx_leaf); - -/* Compute the root node of the top-most subtree. */ -#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) -void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); - -#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/nistapi.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/nistapi.h deleted file mode 100644 index 3cb71afad4..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/nistapi.h +++ /dev/null @@ -1,87 +0,0 @@ -#ifndef SPX_API_H -#define SPX_API_H - -#include -#include - -#include "params.h" - -#define CRYPTO_ALGNAME "SPHINCS+" - -#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES -#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES -#define CRYPTO_BYTES SPX_BYTES -#define CRYPTO_SEEDBYTES (3*SPX_N) - -/* - * Returns the length of a secret key, in bytes - */ -#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) -size_t crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) -size_t crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) -size_t crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) -size_t crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) -int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) -int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) -int crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) -int crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -#define crypto_sign SPX_NAMESPACE(crypto_sign) -int crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) -int crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/params.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/params.h deleted file mode 100644 index c17b802b00..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/params.h +++ /dev/null @@ -1,56 +0,0 @@ -#ifndef SPX_PARAMS_H -#define SPX_PARAMS_H - -#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_##s - -/* Hash output length in bytes. */ -#define SPX_N 24 -/* Height of the hypertree. */ -#define SPX_FULL_HEIGHT 63 -/* Number of subtree layer. */ -#define SPX_D 7 -/* FORS tree dimensions. */ -#define SPX_FORS_HEIGHT 14 -#define SPX_FORS_TREES 17 -/* Winternitz parameter, */ -#define SPX_WOTS_W 16 - -/* The hash function is defined by linking a different hash.c file, as opposed - to setting a #define constant. */ - -/* For clarity */ -#define SPX_ADDR_BYTES 32 - -/* WOTS parameters. */ -#define SPX_WOTS_LOGW 4 - -#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) - -/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#define SPX_WOTS_LEN2 3 - -#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) -#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) -#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES - -/* Subtree size. */ -#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) - -//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT -// #error SPX_D should always divide SPX_FULL_HEIGHT -//#endif - -/* FORS parameters. */ -#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) -#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) -#define SPX_FORS_PK_BYTES SPX_N - -/* Resulting SPX sizes. */ -#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ - SPX_FULL_HEIGHT * SPX_N) -#define SPX_PK_BYTES (2 * SPX_N) -#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) - -#include "haraka_offsets.h" - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/sign.c b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/sign.c deleted file mode 100644 index 9d0c7d1b22..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/sign.c +++ /dev/null @@ -1,286 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "context.h" -#include "fors.h" -#include "hash.h" -#include "merkle.h" -#include "nistapi.h" -#include "params.h" -#include "randombytes.h" -#include "thash.h" -#include "utils.h" -#include "wots.h" - -/* - * Returns the length of a secret key, in bytes - */ -size_t crypto_sign_secretkeybytes(void) { - return CRYPTO_SECRETKEYBYTES; -} - -/* - * Returns the length of a public key, in bytes - */ -size_t crypto_sign_publickeybytes(void) { - return CRYPTO_PUBLICKEYBYTES; -} - -/* - * Returns the length of a signature, in bytes - */ -size_t crypto_sign_bytes(void) { - return CRYPTO_BYTES; -} - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t crypto_sign_seedbytes(void) { - return CRYPTO_SEEDBYTES; -} - -/* - * Generates an SPX key pair given a seed of length - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed) { - spx_ctx ctx; - - /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ - memcpy(sk, seed, CRYPTO_SEEDBYTES); - - memcpy(pk, sk + 2 * SPX_N, SPX_N); - - memcpy(ctx.pub_seed, pk, SPX_N); - memcpy(ctx.sk_seed, sk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - /* Compute root node of the top-most subtree. */ - merkle_gen_root(sk + 3 * SPX_N, &ctx); - - // cleanup - free_hash_function(&ctx); - - memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); - - return 0; -} - -/* - * Generates an SPX key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { - uint8_t seed[CRYPTO_SEEDBYTES]; - randombytes(seed, CRYPTO_SEEDBYTES); - crypto_sign_seed_keypair(pk, sk, seed); - - return 0; -} - -/** - * Returns an array containing a detached signature. - */ -int crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - spx_ctx ctx; - - const uint8_t *sk_prf = sk + SPX_N; - const uint8_t *pk = sk + 2 * SPX_N; - - uint8_t optrand[SPX_N]; - uint8_t mhash[SPX_FORS_MSG_BYTES]; - uint8_t root[SPX_N]; - uint32_t i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - - memcpy(ctx.sk_seed, sk, SPX_N); - memcpy(ctx.pub_seed, pk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - set_type(wots_addr, SPX_ADDR_TYPE_WOTS); - set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); - - /* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ - randombytes(optrand, SPX_N); - /* Compute the digest randomization value. */ - gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); - - /* Derive the message digest and leaf index from R, PK and M. */ - hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); - sig += SPX_N; - - set_tree_addr(wots_addr, tree); - set_keypair_addr(wots_addr, idx_leaf); - - /* Sign the message hash using FORS. */ - fors_sign(sig, root, mhash, &ctx, wots_addr); - sig += SPX_FORS_BYTES; - - for (i = 0; i < SPX_D; i++) { - set_layer_addr(tree_addr, i); - set_tree_addr(tree_addr, tree); - - copy_subtree_addr(wots_addr, tree_addr); - set_keypair_addr(wots_addr, idx_leaf); - - merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); - sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); - tree = tree >> SPX_TREE_HEIGHT; - } - - free_hash_function(&ctx); - - *siglen = SPX_BYTES; - - return 0; -} - -/** - * Verifies a detached signature and message under a given public key. - */ -int crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk) { - spx_ctx ctx; - const uint8_t *pub_root = pk + SPX_N; - uint8_t mhash[SPX_FORS_MSG_BYTES]; - uint8_t wots_pk[SPX_WOTS_BYTES]; - uint8_t root[SPX_N]; - uint8_t leaf[SPX_N]; - unsigned int i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - if (siglen != SPX_BYTES) { - return -1; - } - - memcpy(ctx.pub_seed, pk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - set_type(wots_addr, SPX_ADDR_TYPE_WOTS); - set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); - set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); - - /* Derive the message digest and leaf index from R || PK || M. */ - /* The additional SPX_N is a result of the hash domain separator. */ - hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); - sig += SPX_N; - - /* Layer correctly defaults to 0, so no need to set_layer_addr */ - set_tree_addr(wots_addr, tree); - set_keypair_addr(wots_addr, idx_leaf); - - fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); - sig += SPX_FORS_BYTES; - - /* For each subtree.. */ - for (i = 0; i < SPX_D; i++) { - set_layer_addr(tree_addr, i); - set_tree_addr(tree_addr, tree); - - copy_subtree_addr(wots_addr, tree_addr); - set_keypair_addr(wots_addr, idx_leaf); - - copy_keypair_addr(wots_pk_addr, wots_addr); - - /* The WOTS public key is only correct if the signature was correct. */ - /* Initially, root is the FORS pk, but on subsequent iterations it is - the root of the subtree below the currently processed subtree. */ - wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); - sig += SPX_WOTS_BYTES; - - /* Compute the leaf node using the WOTS public key. */ - thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); - - /* Compute the root node of this subtree. */ - compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, - &ctx, tree_addr); - sig += SPX_TREE_HEIGHT * SPX_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); - tree = tree >> SPX_TREE_HEIGHT; - } - - // cleanup - free_hash_function(&ctx); - - /* Check if the root node equals the root node in the public key. */ - if (memcmp(root, pub_root, SPX_N) != 0) { - return -1; - } - - return 0; -} - - -/** - * Returns an array containing the signature followed by the message. - */ -int crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk) { - size_t siglen; - - crypto_sign_signature(sm, &siglen, m, mlen, sk); - - memmove(sm + SPX_BYTES, m, mlen); - *smlen = siglen + mlen; - - return 0; -} - -/** - * Verifies a given signature-message pair under a given public key. - */ -int crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk) { - /* The API caller does not necessarily know what size a signature should be - but SPHINCS+ signatures are always exactly SPX_BYTES. */ - if (smlen < SPX_BYTES) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - *mlen = smlen - SPX_BYTES; - - if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - /* If verification was successful, move the message to the right place. */ - memmove(m, sm + SPX_BYTES, *mlen); - - return 0; -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/thash.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/thash.h deleted file mode 100644 index 8687ccfb4d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/thash.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef SPX_THASH_H -#define SPX_THASH_H - -#include "context.h" -#include "params.h" - -#include - -#define thash SPX_NAMESPACE(thash) -void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/thash_haraka_simple.c b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/thash_haraka_simple.c deleted file mode 100644 index 207777bf8d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/thash_haraka_simple.c +++ /dev/null @@ -1,36 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "thash.h" -#include "utils.h" - -#include "haraka.h" - -/** - * Takes an array of inblocks concatenated arrays of SPX_N bytes. - */ -void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]) { - PQCLEAN_VLA(uint8_t, buf, SPX_ADDR_BYTES + inblocks * SPX_N); - unsigned char outbuf[32]; - unsigned char buf_tmp[64]; - - if (inblocks == 1) { - /* F function */ - /* Since SPX_N may be smaller than 32, we need a temporary buffer. */ - memset(buf_tmp, 0, 64); - memcpy(buf_tmp, addr, 32); - memcpy(buf_tmp + SPX_ADDR_BYTES, in, SPX_N); - - haraka512(outbuf, buf_tmp, ctx); - memcpy(out, outbuf, SPX_N); - } else { - /* All other tweakable hashes*/ - memcpy(buf, addr, 32); - memcpy(buf + SPX_ADDR_BYTES, in, inblocks * SPX_N); - - haraka_S(out, SPX_N, buf, SPX_ADDR_BYTES + inblocks * SPX_N, ctx); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/utils.c b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/utils.c deleted file mode 100644 index 177b541fb9..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/utils.c +++ /dev/null @@ -1,148 +0,0 @@ -#include - -#include "utils.h" - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "thash.h" - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void ull_to_bytes(unsigned char *out, unsigned int outlen, - unsigned long long in) { - int i; - - /* Iterate over out in decreasing order, for big-endianness. */ - for (i = (signed int)outlen - 1; i >= 0; i--) { - out[i] = in & 0xff; - in = in >> 8; - } -} - -void u32_to_bytes(unsigned char *out, uint32_t in) { - out[0] = (unsigned char)(in >> 24); - out[1] = (unsigned char)(in >> 16); - out[2] = (unsigned char)(in >> 8); - out[3] = (unsigned char)in; -} - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { - unsigned long long retval = 0; - unsigned int i; - - for (i = 0; i < inlen; i++) { - retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); - } - return retval; -} - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void compute_root(unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const spx_ctx *ctx, uint32_t addr[8]) { - uint32_t i; - unsigned char buffer[2 * SPX_N]; - - /* If leaf_idx is odd (last bit = 1), current path element is a right child - and auth_path has to go left. Otherwise it is the other way around. */ - if (leaf_idx & 1) { - memcpy(buffer + SPX_N, leaf, SPX_N); - memcpy(buffer, auth_path, SPX_N); - } else { - memcpy(buffer, leaf, SPX_N); - memcpy(buffer + SPX_N, auth_path, SPX_N); - } - auth_path += SPX_N; - - for (i = 0; i < tree_height - 1; i++) { - leaf_idx >>= 1; - idx_offset >>= 1; - /* Set the address of the node we're creating. */ - set_tree_height(addr, i + 1); - set_tree_index(addr, leaf_idx + idx_offset); - - /* Pick the right or left neighbor, depending on parity of the node. */ - if (leaf_idx & 1) { - thash(buffer + SPX_N, buffer, 2, ctx, addr); - memcpy(buffer, auth_path, SPX_N); - } else { - thash(buffer, buffer, 2, ctx, addr); - memcpy(buffer + SPX_N, auth_path, SPX_N); - } - auth_path += SPX_N; - } - - /* The last iteration is exceptional; we do not copy an auth_path node. */ - leaf_idx >>= 1; - idx_offset >>= 1; - set_tree_height(addr, tree_height); - set_tree_index(addr, leaf_idx + idx_offset); - thash(root, buffer, 2, ctx, addr); -} - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const spx_ctx * /* ctx */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), - uint32_t tree_addr[8]) { - PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); - PQCLEAN_VLA(unsigned int, heights, tree_height + 1); - unsigned int offset = 0; - uint32_t idx; - uint32_t tree_idx; - - for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { - /* Add the next leaf node to the stack. */ - gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); - offset++; - heights[offset - 1] = 0; - - /* If this is a node we need for the auth path.. */ - if ((leaf_idx ^ 0x1) == idx) { - memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); - } - - /* While the top-most nodes are of equal height.. */ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { - /* Compute index of the new node, in the next layer. */ - tree_idx = (idx >> (heights[offset - 1] + 1)); - - /* Set the address of the node we're creating. */ - set_tree_height(tree_addr, heights[offset - 1] + 1); - set_tree_index(tree_addr, - tree_idx + (idx_offset >> (heights[offset - 1] + 1))); - /* Hash the top-most nodes from the stack together. */ - thash(stack + (offset - 2)*SPX_N, - stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); - offset--; - /* Note that the top-most node is now one layer higher. */ - heights[offset - 1]++; - - /* If this is a node we need for the auth path.. */ - if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_path + heights[offset - 1]*SPX_N, - stack + (offset - 1)*SPX_N, SPX_N); - } - } - } - memcpy(root, stack, SPX_N); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/utils.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/utils.h deleted file mode 100644 index 64f5d5a53a..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/utils.h +++ /dev/null @@ -1,58 +0,0 @@ -#ifndef SPX_UTILS_H -#define SPX_UTILS_H - -#include - -#include "compat.h" -#include "context.h" -#include "params.h" - - -/* To support MSVC use alloca() instead of VLAs. See #20. */ - - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) -void ull_to_bytes(unsigned char *out, unsigned int outlen, - unsigned long long in); -#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) -void u32_to_bytes(unsigned char *out, uint32_t in); - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) -unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -#define compute_root SPX_NAMESPACE(compute_root) -void compute_root(unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const spx_ctx *ctx, uint32_t addr[8]); - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -#define treehash SPX_NAMESPACE(treehash) -void treehash(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const spx_ctx *ctx /* ctx */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), - uint32_t tree_addr[8]); - - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/utilsx1.c b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/utilsx1.c deleted file mode 100644 index fccb69b35d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/utilsx1.c +++ /dev/null @@ -1,100 +0,0 @@ -#include - -#include "utilsx1.h" - -#include "address.h" -#include "params.h" -#include "thash.h" -#include "utils.h" - -/* - * Generate the entire Merkle tree, computing the authentication path for - * leaf_idx, and the resulting root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) - * - * This expects tree_addr to be initialized to the addr structures for the - * Merkle tree nodes - * - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - * - * This works by using the standard Merkle tree building algorithm, - */ -void treehashx1(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, - uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* Where to write the leaves */, - const spx_ctx * /* ctx */, - uint32_t idx, void *info), - uint32_t tree_addr[8], - void *info) { - /* This is where we keep the intermediate nodes */ - PQCLEAN_VLA(uint8_t, stack, tree_height * SPX_N); - - uint32_t idx; - uint32_t max_idx = (uint32_t)((1 << tree_height) - 1); - for (idx = 0;; idx++) { - unsigned char current[2 * SPX_N]; /* Current logical node is at */ - /* index[SPX_N]. We do this to minimize the number of copies */ - /* needed during a thash */ - gen_leaf( ¤t[SPX_N], ctx, idx + idx_offset, - info ); - - /* Now combine the freshly generated right node with previously */ - /* generated left ones */ - uint32_t internal_idx_offset = idx_offset; - uint32_t internal_idx = idx; - uint32_t internal_leaf = leaf_idx; - uint32_t h; /* The height we are in the Merkle tree */ - for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { - - /* Check if we hit the top of the tree */ - if (h == tree_height) { - /* We hit the root; return it */ - memcpy( root, ¤t[SPX_N], SPX_N ); - return; - } - - /* - * Check if the node we have is a part of the - * authentication path; if it is, write it out - */ - if ((internal_idx ^ internal_leaf) == 0x01) { - memcpy( &auth_path[ h * SPX_N ], - ¤t[SPX_N], - SPX_N ); - } - - /* - * Check if we're at a left child; if so, stop going up the stack - * Exception: if we've reached the end of the tree, keep on going - * (so we combine the last 4 nodes into the one root node in two - * more iterations) - */ - if ((internal_idx & 1) == 0 && idx < max_idx) { - break; - } - - /* Ok, we're at a right node */ - /* Now combine the left and right logical nodes together */ - - /* Set the address of the node we're creating. */ - internal_idx_offset >>= 1; - set_tree_height(tree_addr, h + 1); - set_tree_index(tree_addr, internal_idx / 2 + internal_idx_offset ); - - unsigned char *left = &stack[h * SPX_N]; - memcpy( ¤t[0], left, SPX_N ); - thash( ¤t[1 * SPX_N], - ¤t[0 * SPX_N], - 2, ctx, tree_addr); - } - - /* We've hit a left child; save the current for when we get the */ - /* corresponding right right */ - memcpy( &stack[h * SPX_N], ¤t[SPX_N], SPX_N); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/utilsx1.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/utilsx1.h deleted file mode 100644 index e911d17d53..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/utilsx1.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef SPX_UTILSX4_H -#define SPX_UTILSX4_H - -#include - -#include "context.h" -#include "params.h" - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -#define treehashx1 SPX_NAMESPACE(treehashx1) -void treehashx1(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* Where to write the leaf */, - const spx_ctx * /* ctx */, - uint32_t addr_idx, void *info), - uint32_t tree_addrx4[8], void *info); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/wots.c b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/wots.c deleted file mode 100644 index 249717aaa8..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/wots.c +++ /dev/null @@ -1,108 +0,0 @@ -#include -#include - -#include "wots.h" -#include "wotsx1.h" - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "thash.h" -#include "utils.h" -#include "utilsx1.h" - -// TODO clarify address expectations, and make them more uniform. -// TODO i.e. do we expect types to be set already? -// TODO and do we expect modifications or copies? - -/** - * Computes the chaining function. - * out and in have to be n-byte arrays. - * - * Interprets in as start-th value of the chain. - * addr has to contain the address of the chain. - */ -static void gen_chain(unsigned char *out, const unsigned char *in, - unsigned int start, unsigned int steps, - const spx_ctx *ctx, uint32_t addr[8]) { - uint32_t i; - - /* Initialize out with the value at position 'start'. */ - memcpy(out, in, SPX_N); - - /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < SPX_WOTS_W; i++) { - set_hash_addr(addr, i); - thash(out, out, 1, ctx, addr); - } -} - -/** - * base_w algorithm as described in draft. - * Interprets an array of bytes as integers in base w. - * This only works when log_w is a divisor of 8. - */ -static void base_w(unsigned int *output, const int out_len, - const unsigned char *input) { - int in = 0; - int out = 0; - unsigned char total = 0; - int bits = 0; - int consumed; - - for (consumed = 0; consumed < out_len; consumed++) { - if (bits == 0) { - total = input[in]; - in++; - bits += 8; - } - bits -= SPX_WOTS_LOGW; - output[out] = (total >> bits) & (SPX_WOTS_W - 1); - out++; - } -} - -/* Computes the WOTS+ checksum over a message (in base_w). */ -static void wots_checksum(unsigned int *csum_base_w, - const unsigned int *msg_base_w) { - unsigned int csum = 0; - unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; - unsigned int i; - - /* Compute checksum. */ - for (i = 0; i < SPX_WOTS_LEN1; i++) { - csum += SPX_WOTS_W - 1 - msg_base_w[i]; - } - - /* Convert checksum to base_w. */ - /* Make sure expected empty zero bits are the least significant bits. */ - csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); - ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); - base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); -} - -/* Takes a message and derives the matching chain lengths. */ -void chain_lengths(unsigned int *lengths, const unsigned char *msg) { - base_w(lengths, SPX_WOTS_LEN1, msg); - wots_checksum(lengths + SPX_WOTS_LEN1, lengths); -} - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const spx_ctx *ctx, uint32_t addr[8]) { - unsigned int lengths[SPX_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < SPX_WOTS_LEN; i++) { - set_chain_addr(addr, i); - gen_chain(pk + i * SPX_N, sig + i * SPX_N, - lengths[i], SPX_WOTS_W - 1 - lengths[i], ctx, addr); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/wots.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/wots.h deleted file mode 100644 index 4e7692eeef..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/wots.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef SPX_WOTS_H -#define SPX_WOTS_H - -#include - -#include "context.h" -#include "params.h" - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) -void wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const spx_ctx *ctx, uint32_t addr[8]); - -/* - * Compute the chain lengths needed for a given message hash - */ -#define chain_lengths SPX_NAMESPACE(chain_lengths) -void chain_lengths(unsigned int *lengths, const unsigned char *msg); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/wotsx1.c b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/wotsx1.c deleted file mode 100644 index 3adec78dfb..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/wotsx1.c +++ /dev/null @@ -1,76 +0,0 @@ -#include -#include - -#include "wots.h" -#include "wotsx1.h" - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "thash.h" -#include "utils.h" - -/* - * This generates a WOTS public key - * It also generates the WOTS signature if leaf_info indicates - * that we're signing with this WOTS key - */ -void wots_gen_leafx1(unsigned char *dest, - const spx_ctx *ctx, - uint32_t leaf_idx, void *v_info) { - struct leaf_info_x1 *info = v_info; - uint32_t *leaf_addr = info->leaf_addr; - uint32_t *pk_addr = info->pk_addr; - unsigned int i, k; - unsigned char pk_buffer[ SPX_WOTS_BYTES ]; - unsigned char *buffer; - uint32_t wots_k_mask; - - if (leaf_idx == info->wots_sign_leaf) { - /* We're traversing the leaf that's signing; generate the WOTS */ - /* signature */ - wots_k_mask = 0; - } else { - /* Nope, we're just generating pk's; turn off the signature logic */ - wots_k_mask = (uint32_t)~0; - } - - set_keypair_addr( leaf_addr, leaf_idx ); - set_keypair_addr( pk_addr, leaf_idx ); - - for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { - uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k to */ - /* the step if we're generating a signature, ~0 if we're not */ - - /* Start with the secret seed */ - set_chain_addr(leaf_addr, i); - set_hash_addr(leaf_addr, 0); - set_type(leaf_addr, SPX_ADDR_TYPE_WOTSPRF); - - prf_addr(buffer, ctx, leaf_addr); - - set_type(leaf_addr, SPX_ADDR_TYPE_WOTS); - - /* Iterate down the WOTS chain */ - for (k = 0;; k++) { - /* Check if this is the value that needs to be saved as a */ - /* part of the WOTS signature */ - if (k == wots_k) { - memcpy( info->wots_sig + i * SPX_N, buffer, SPX_N ); - } - - /* Check if we hit the top of the chain */ - if (k == SPX_WOTS_W - 1) { - break; - } - - /* Iterate one step on the chain */ - set_hash_addr(leaf_addr, k); - - thash(buffer, buffer, 1, ctx, leaf_addr); - } - } - - /* Do the final thash to generate the public keys */ - thash(dest, pk_buffer, SPX_WOTS_LEN, ctx, pk_addr); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/wotsx1.h b/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/wotsx1.h deleted file mode 100644 index e617929f96..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-192s-simple_clean/wotsx1.h +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef WOTSX1_H_ -#define WOTSX1_H_ - -#include - -#include "context.h" -#include "params.h" - -/* - * This is here to provide an interface to the internal wots_gen_leafx1 - * routine. While this routine is not referenced in the package outside of - * wots.c, it is called from the stand-alone benchmark code to characterize - * the performance - */ -struct leaf_info_x1 { - unsigned char *wots_sig; - uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ - uint32_t *wots_steps; - uint32_t leaf_addr[8]; - uint32_t pk_addr[8]; -}; - -/* Macro to set the leaf_info to something 'benign', that is, it would */ -/* run with the same time as it does during the real signing process */ -/* Used only by the benchmark code */ -#define INITIALIZE_LEAF_INFO_X1(info, addr, step_buffer) { \ - (info).wots_sig = 0; \ - (info).wots_sign_leaf = ~0; \ - (info).wots_steps = step_buffer; \ - memcpy( &(info).leaf_addr[0], (addr), 32 ); \ - memcpy( &(info).pk_addr[0], (addr), 32 ); \ - } - -#define wots_gen_leafx1 SPX_NAMESPACE(wots_gen_leafx1) -void wots_gen_leafx1(unsigned char *dest, - const spx_ctx *ctx, - uint32_t leaf_idx, void *v_info); - -#endif /* WOTSX1_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/LICENSE b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/LICENSE deleted file mode 100644 index 670154e353..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/LICENSE +++ /dev/null @@ -1,116 +0,0 @@ -CC0 1.0 Universal - -Statement of Purpose - -The laws of most jurisdictions throughout the world automatically confer -exclusive Copyright and Related Rights (defined below) upon the creator and -subsequent owner(s) (each and all, an "owner") of an original work of -authorship and/or a database (each, a "Work"). - -Certain owners wish to permanently relinquish those rights to a Work for the -purpose of contributing to a commons of creative, cultural and scientific -works ("Commons") that the public can reliably and without fear of later -claims of infringement build upon, modify, incorporate in other works, reuse -and redistribute as freely as possible in any form whatsoever and for any -purposes, including without limitation commercial purposes. These owners may -contribute to the Commons to promote the ideal of a free culture and the -further production of creative, cultural and scientific works, or to gain -reputation or greater distribution for their Work in part through the use and -efforts of others. - -For these and/or other purposes and motivations, and without any expectation -of additional consideration or compensation, the person associating CC0 with a -Work (the "Affirmer"), to the extent that he or she is an owner of Copyright -and Related Rights in the Work, voluntarily elects to apply CC0 to the Work -and publicly distribute the Work under its terms, with knowledge of his or her -Copyright and Related Rights in the Work and the meaning and intended legal -effect of CC0 on those rights. - -1. Copyright and Related Rights. A Work made available under CC0 may be -protected by copyright and related or neighboring rights ("Copyright and -Related Rights"). Copyright and Related Rights include, but are not limited -to, the following: - - i. the right to reproduce, adapt, distribute, perform, display, communicate, - and translate a Work; - - ii. moral rights retained by the original author(s) and/or performer(s); - - iii. publicity and privacy rights pertaining to a person's image or likeness - depicted in a Work; - - iv. rights protecting against unfair competition in regards to a Work, - subject to the limitations in paragraph 4(a), below; - - v. rights protecting the extraction, dissemination, use and reuse of data in - a Work; - - vi. database rights (such as those arising under Directive 96/9/EC of the - European Parliament and of the Council of 11 March 1996 on the legal - protection of databases, and under any national implementation thereof, - including any amended or successor version of such directive); and - - vii. other similar, equivalent or corresponding rights throughout the world - based on applicable law or treaty, and any national implementations thereof. - -2. Waiver. To the greatest extent permitted by, but not in contravention of, -applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and -unconditionally waives, abandons, and surrenders all of Affirmer's Copyright -and Related Rights and associated claims and causes of action, whether now -known or unknown (including existing as well as future claims and causes of -action), in the Work (i) in all territories worldwide, (ii) for the maximum -duration provided by applicable law or treaty (including future time -extensions), (iii) in any current or future medium and for any number of -copies, and (iv) for any purpose whatsoever, including without limitation -commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes -the Waiver for the benefit of each member of the public at large and to the -detriment of Affirmer's heirs and successors, fully intending that such Waiver -shall not be subject to revocation, rescission, cancellation, termination, or -any other legal or equitable action to disrupt the quiet enjoyment of the Work -by the public as contemplated by Affirmer's express Statement of Purpose. - -3. Public License Fallback. Should any part of the Waiver for any reason be -judged legally invalid or ineffective under applicable law, then the Waiver -shall be preserved to the maximum extent permitted taking into account -Affirmer's express Statement of Purpose. In addition, to the extent the Waiver -is so judged Affirmer hereby grants to each affected person a royalty-free, -non transferable, non sublicensable, non exclusive, irrevocable and -unconditional license to exercise Affirmer's Copyright and Related Rights in -the Work (i) in all territories worldwide, (ii) for the maximum duration -provided by applicable law or treaty (including future time extensions), (iii) -in any current or future medium and for any number of copies, and (iv) for any -purpose whatsoever, including without limitation commercial, advertising or -promotional purposes (the "License"). The License shall be deemed effective as -of the date CC0 was applied by Affirmer to the Work. Should any part of the -License for any reason be judged legally invalid or ineffective under -applicable law, such partial invalidity or ineffectiveness shall not -invalidate the remainder of the License, and in such case Affirmer hereby -affirms that he or she will not (i) exercise any of his or her remaining -Copyright and Related Rights in the Work or (ii) assert any associated claims -and causes of action with respect to the Work, in either case contrary to -Affirmer's express Statement of Purpose. - -4. Limitations and Disclaimers. - - a. No trademark or patent rights held by Affirmer are waived, abandoned, - surrendered, licensed or otherwise affected by this document. - - b. Affirmer offers the Work as-is and makes no representations or warranties - of any kind concerning the Work, express, implied, statutory or otherwise, - including without limitation warranties of title, merchantability, fitness - for a particular purpose, non infringement, or the absence of latent or - other defects, accuracy, or the present or absence of errors, whether or not - discoverable, all to the greatest extent permissible under applicable law. - - c. Affirmer disclaims responsibility for clearing rights of other persons - that may apply to the Work or any use thereof, including without limitation - any person's Copyright and Related Rights in the Work. Further, Affirmer - disclaims responsibility for obtaining any necessary consents, permissions - or other rights required for any use of the Work. - - d. Affirmer understands and acknowledges that Creative Commons is not a - party to this document and has no duty or obligation with respect to this - CC0 or use of the Work. - -For more information, please see - diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/address.c b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/address.c deleted file mode 100644 index b956e9cb29..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/address.c +++ /dev/null @@ -1,91 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "utils.h" - -/* - * Specify which level of Merkle tree (the "layer") we're working on - */ -void set_layer_addr(uint32_t addr[8], uint32_t layer) { - ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; -} - -/* - * Specify which Merkle tree within the level (the "tree address") we're working on - */ -void set_tree_addr(uint32_t addr[8], uint64_t tree) { - ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); -} - -/* - * Specify the reason we'll use this address structure for, that is, what - * hash will we compute with it. This is used so that unrelated types of - * hashes don't accidentally get the same address structure. The type will be - * one of the SPX_ADDR_TYPE constants - */ -void set_type(uint32_t addr[8], uint32_t type) { - ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; -} - -/* - * Copy the layer and tree fields of the address structure. This is used - * when we're doing multiple types of hashes within the same Merkle tree - */ -void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { - memcpy( out, in, SPX_OFFSET_TREE + 8 ); -} - -/* These functions are used for OTS addresses. */ - -/* - * Specify which Merkle leaf we're working on; that is, which OTS keypair - * we're talking about. - */ -void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { - ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; -} - -/* - * Copy the layer, tree and keypair fields of the address structure. This is - * used when we're doing multiple things within the same OTS keypair - */ -void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { - memcpy( out, in, SPX_OFFSET_TREE + 8 ); - ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; -} - -/* - * Specify which Merkle chain within the OTS we're working with - * (the chain address) - */ -void set_chain_addr(uint32_t addr[8], uint32_t chain) { - ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; -} - -/* - * Specify where in the Merkle chain we are -* (the hash address) - */ -void set_hash_addr(uint32_t addr[8], uint32_t hash) { - ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; -} - -/* These functions are used for all hash tree addresses (including FORS). */ - -/* - * Specify the height of the node in the Merkle/FORS tree we are in - * (the tree height) - */ -void set_tree_height(uint32_t addr[8], uint32_t tree_height) { - ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; -} - -/* - * Specify the distance from the left edge of the node in the Merkle/FORS tree - * (the tree index) - */ -void set_tree_index(uint32_t addr[8], uint32_t tree_index) { - u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/address.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/address.h deleted file mode 100644 index 24a84eb40c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/address.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef SPX_ADDRESS_H -#define SPX_ADDRESS_H - -#include - -#include "params.h" - -/* The hash types that are passed to set_type */ -#define SPX_ADDR_TYPE_WOTS 0 -#define SPX_ADDR_TYPE_WOTSPK 1 -#define SPX_ADDR_TYPE_HASHTREE 2 -#define SPX_ADDR_TYPE_FORSTREE 3 -#define SPX_ADDR_TYPE_FORSPK 4 -#define SPX_ADDR_TYPE_WOTSPRF 5 -#define SPX_ADDR_TYPE_FORSPRF 6 - -#define set_layer_addr SPX_NAMESPACE(set_layer_addr) -void set_layer_addr(uint32_t addr[8], uint32_t layer); - -#define set_tree_addr SPX_NAMESPACE(set_tree_addr) -void set_tree_addr(uint32_t addr[8], uint64_t tree); - -#define set_type SPX_NAMESPACE(set_type) -void set_type(uint32_t addr[8], uint32_t type); - -/* Copies the layer and tree part of one address into the other */ -#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) -void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for WOTS and FORS addresses. */ - -#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) -void set_keypair_addr(uint32_t addr[8], uint32_t keypair); - -#define set_chain_addr SPX_NAMESPACE(set_chain_addr) -void set_chain_addr(uint32_t addr[8], uint32_t chain); - -#define set_hash_addr SPX_NAMESPACE(set_hash_addr) -void set_hash_addr(uint32_t addr[8], uint32_t hash); - -#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) -void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for all hash tree addresses (including FORS). */ - -#define set_tree_height SPX_NAMESPACE(set_tree_height) -void set_tree_height(uint32_t addr[8], uint32_t tree_height); - -#define set_tree_index SPX_NAMESPACE(set_tree_index) -void set_tree_index(uint32_t addr[8], uint32_t tree_index); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/api.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/api.h deleted file mode 100644 index 01aa8ffd25..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/api.h +++ /dev/null @@ -1,77 +0,0 @@ -#ifndef PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_API_H -#define PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_API_H - -#include -#include - -#define PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_CRYPTO_ALGNAME "SPHINCS+-haraka-256f-robust" - -#define PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_CRYPTO_SECRETKEYBYTES 128 -#define PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_CRYPTO_PUBLICKEYBYTES 64 -#define PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_CRYPTO_BYTES 49856 - -#define PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_CRYPTO_SEEDBYTES 96 - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, - const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk); -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/context.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/context.h deleted file mode 100644 index f03446b9cb..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/context.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef SPX_CONTEXT_H -#define SPX_CONTEXT_H - -#include - -#include "immintrin.h" -#include "params.h" - -typedef struct { - uint8_t pub_seed[SPX_N]; - uint8_t sk_seed[SPX_N]; - - __m128i rc[40]; -} spx_ctx; - -#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) -void initialize_hash_function(spx_ctx *ctx); - -#define free_hash_function SPX_NAMESPACE(free_hash_function) -void free_hash_function(spx_ctx *ctx); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/context_haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/context_haraka.c deleted file mode 100644 index f1cd7e3664..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/context_haraka.c +++ /dev/null @@ -1,11 +0,0 @@ -#include "context.h" -#include "haraka.h" - -void initialize_hash_function(spx_ctx *ctx) { - tweak_constants(ctx); -} - -// we don't support heap-based haraka right now -void free_hash_function(spx_ctx *ctx) { - (void)ctx; // suppress unused variable warnings -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/fors.c b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/fors.c deleted file mode 100644 index f1b0639cfc..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/fors.c +++ /dev/null @@ -1,202 +0,0 @@ -#include -#include -#include - -#include "fors.h" - -#include "address.h" -#include "hash.h" -#include "hashx4.h" -#include "thash.h" -#include "thashx4.h" -#include "utils.h" -#include "utilsx4.h" - -static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, - uint32_t fors_leaf_addr[8]) { - prf_addr(sk, ctx, fors_leaf_addr); -} - -static void fors_gen_skx4(unsigned char *sk0, - unsigned char *sk1, - unsigned char *sk2, - unsigned char *sk3, const spx_ctx *ctx, - uint32_t fors_leaf_addrx4[4 * 8]) { - prf_addrx4(sk0, sk1, sk2, sk3, - ctx, fors_leaf_addrx4); -} - -static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, - const spx_ctx *ctx, - uint32_t fors_leaf_addr[8]) { - thash(leaf, sk, 1, ctx, fors_leaf_addr); -} - -static void fors_sk_to_leafx4(unsigned char *leaf0, - unsigned char *leaf1, - unsigned char *leaf2, - unsigned char *leaf3, - const unsigned char *sk0, - const unsigned char *sk1, - const unsigned char *sk2, - const unsigned char *sk3, - const spx_ctx *ctx, - uint32_t fors_leaf_addrx4[4 * 8]) { - thashx4(leaf0, leaf1, leaf2, leaf3, - sk0, sk1, sk2, sk3, - 1, ctx, fors_leaf_addrx4); -} - -struct fors_gen_leaf_info { - uint32_t leaf_addrx[4 * 8]; -}; - -static void fors_gen_leafx4(unsigned char *leaf, - const spx_ctx *ctx, - uint32_t addr_idx, void *info) { - struct fors_gen_leaf_info *fors_info = info; - uint32_t *fors_leaf_addrx4 = fors_info->leaf_addrx; - unsigned int j; - - /* Only set the parts that the caller doesn't set */ - for (j = 0; j < 4; j++) { - set_tree_index(fors_leaf_addrx4 + j * 8, addr_idx + j); - set_type(fors_leaf_addrx4 + j * 8, SPX_ADDR_TYPE_FORSPRF); - } - - fors_gen_skx4(leaf + 0 * SPX_N, - leaf + 1 * SPX_N, - leaf + 2 * SPX_N, - leaf + 3 * SPX_N, - ctx, fors_leaf_addrx4); - - for (j = 0; j < 4; j++) { - set_type(fors_leaf_addrx4 + j * 8, SPX_ADDR_TYPE_FORSTREE); - } - - fors_sk_to_leafx4(leaf + 0 * SPX_N, - leaf + 1 * SPX_N, - leaf + 2 * SPX_N, - leaf + 3 * SPX_N, - leaf + 0 * SPX_N, - leaf + 1 * SPX_N, - leaf + 2 * SPX_N, - leaf + 3 * SPX_N, - ctx, fors_leaf_addrx4); -} - -/** - * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - * Assumes indices has space for SPX_FORS_TREES integers. - */ -static void message_to_indices(uint32_t *indices, const unsigned char *m) { - unsigned int i, j; - unsigned int offset = 0; - - for (i = 0; i < SPX_FORS_TREES; i++) { - indices[i] = 0; - for (j = 0; j < SPX_FORS_HEIGHT; j++) { - indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); - offset++; - } - } -} - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -void fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]) { - uint32_t indices[SPX_FORS_TREES]; - unsigned char roots[SPX_FORS_TREES * SPX_N]; - uint32_t fors_tree_addr[4 * 8] = {0}; - struct fors_gen_leaf_info fors_info = {0}; - uint32_t *fors_leaf_addr = fors_info.leaf_addrx; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - for (i = 0; i < 4; i++) { - copy_keypair_addr(fors_tree_addr + 8 * i, fors_addr); - set_type(fors_tree_addr + 8 * i, SPX_ADDR_TYPE_FORSTREE); - copy_keypair_addr(fors_leaf_addr + 8 * i, fors_addr); - } - copy_keypair_addr(fors_pk_addr, fors_addr); - set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < SPX_FORS_TREES; i++) { - idx_offset = i * (1 << SPX_FORS_HEIGHT); - - set_tree_height(fors_tree_addr, 0); - set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Include the secret key part that produces the selected leaf node. */ - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); - fors_gen_sk(sig, ctx, fors_tree_addr); - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); - sig += SPX_N; - - /* Compute the authentication path for this leaf node. */ - treehashx4(roots + i * SPX_N, sig, ctx, - indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx4, - fors_tree_addr, &fors_info); - - sig += SPX_N * SPX_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); -} - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -void fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]) { - uint32_t indices[SPX_FORS_TREES]; - unsigned char roots[SPX_FORS_TREES * SPX_N]; - unsigned char leaf[SPX_N]; - uint32_t fors_tree_addr[8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - copy_keypair_addr(fors_tree_addr, fors_addr); - copy_keypair_addr(fors_pk_addr, fors_addr); - - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); - set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < SPX_FORS_TREES; i++) { - idx_offset = i * (1 << SPX_FORS_HEIGHT); - - set_tree_height(fors_tree_addr, 0); - set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Derive the leaf from the included secret key part. */ - fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); - sig += SPX_N; - - /* Derive the corresponding root node of this tree. */ - compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, - sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); - sig += SPX_N * SPX_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/fors.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/fors.h deleted file mode 100644 index 509140a178..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/fors.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef SPX_FORS_H -#define SPX_FORS_H - -#include - -#include "context.h" -#include "params.h" - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -#define fors_sign SPX_NAMESPACE(fors_sign) -void fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]); - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) -void fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/haraka.c deleted file mode 100644 index b414b691d7..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/haraka.c +++ /dev/null @@ -1,702 +0,0 @@ -/* -Plain C implementation of the Haraka256 and Haraka512 permutations. -*/ -#include -#include -#include -#include -#include - -#include "haraka.h" -#include "harakax4.h" -#include "utils.h" - -#define HARAKAS_RATE 32 - -#define u64 unsigned long -#define u128 __m128i - -#define LOAD(src) _mm_loadu_si128((u128 *)(src)) -#define STORE(dest,src) _mm_storeu_si128((u128 *)(dest),src) - -#define XOR128(a, b) _mm_xor_si128(a, b) - -#define AES2(s0, s1, rci) \ - s0 = _mm_aesenc_si128(s0, *(rci)); \ - (s1) = _mm_aesenc_si128(s1, *((rci) + 1)); \ - (s0) = _mm_aesenc_si128(s0, *((rci) + 2)); \ - (s1) = _mm_aesenc_si128(s1, *((rci) + 3)); - -#define AES2_4x(s0, s1, s2, s3, rci) \ - AES2((s0)[0], (s0)[1], rci); \ - AES2((s1)[0], (s1)[1], rci); \ - AES2((s2)[0], (s2)[1], rci); \ - AES2((s3)[0], (s3)[1], rci); - -#define AES4(s0, s1, s2, s3, rci) \ - s0 = _mm_aesenc_si128(s0, *(rci)); \ - (s1) = _mm_aesenc_si128(s1, *((rci) + 1)); \ - (s2) = _mm_aesenc_si128(s2, *((rci) + 2)); \ - (s3) = _mm_aesenc_si128(s3, *((rci) + 3)); \ - (s0) = _mm_aesenc_si128(s0, *((rci) + 4)); \ - (s1) = _mm_aesenc_si128(s1, *((rci) + 5)); \ - (s2) = _mm_aesenc_si128(s2, *((rci) + 6)); \ - (s3) = _mm_aesenc_si128(s3, *((rci) + 7)); - -#define AES4_4x(s0, s1, s2, s3, rci) \ - AES4((s0)[0], (s0)[1], (s0)[2], (s0)[3], rci); \ - AES4((s1)[0], (s1)[1], (s1)[2], (s1)[3], rci); \ - AES4((s2)[0], (s2)[1], (s2)[2], (s2)[3], rci); \ - AES4((s3)[0], (s3)[1], (s3)[2], (s3)[3], rci); - -#define MIX2(s0, s1) \ - tmp = _mm_unpacklo_epi32(s0, s1); \ - (s1) = _mm_unpackhi_epi32(s0, s1); \ - (s0) = tmp; - -#define MIX4(s0, s1, s2, s3) \ - tmp = _mm_unpacklo_epi32(s0, s1); \ - (s0) = _mm_unpackhi_epi32(s0, s1); \ - (s1) = _mm_unpacklo_epi32(s2, s3); \ - (s2) = _mm_unpackhi_epi32(s2, s3); \ - (s3) = _mm_unpacklo_epi32(s0, s2); \ - (s0) = _mm_unpackhi_epi32(s0, s2); \ - (s2) = _mm_unpackhi_epi32(s1, tmp); \ - (s1) = _mm_unpacklo_epi32(s1, tmp); - -#define TRUNCSTORE(out, s0, s1, s2, s3) \ - _mm_storeu_si128((u128 *)(out), \ - _mm_castpd_si128(_mm_shuffle_pd(_mm_castsi128_pd(s0), _mm_castsi128_pd(s1), 3))); \ - _mm_storeu_si128((u128 *)((out) + 16), \ - _mm_castpd_si128(_mm_shuffle_pd(_mm_castsi128_pd(s2), _mm_castsi128_pd(s3), 0))); - -static void load_haraka_constants(u128 *rc) { - rc[0] = _mm_set_epi32((int)0x0684704c, (int)0xe620c00a, (int)0xb2c5fef0, (int)0x75817b9d); - rc[1] = _mm_set_epi32((int)0x8b66b4e1, (int)0x88f3a06b, (int)0x640f6ba4, (int)0x2f08f717); - rc[2] = _mm_set_epi32((int)0x3402de2d, (int)0x53f28498, (int)0xcf029d60, (int)0x9f029114); - rc[3] = _mm_set_epi32((int)0x0ed6eae6, (int)0x2e7b4f08, (int)0xbbf3bcaf, (int)0xfd5b4f79); - rc[4] = _mm_set_epi32((int)0xcbcfb0cb, (int)0x4872448b, (int)0x79eecd1c, (int)0xbe397044); - rc[5] = _mm_set_epi32((int)0x7eeacdee, (int)0x6e9032b7, (int)0x8d5335ed, (int)0x2b8a057b); - rc[6] = _mm_set_epi32((int)0x67c28f43, (int)0x5e2e7cd0, (int)0xe2412761, (int)0xda4fef1b); - rc[7] = _mm_set_epi32((int)0x2924d9b0, (int)0xafcacc07, (int)0x675ffde2, (int)0x1fc70b3b); - rc[8] = _mm_set_epi32((int)0xab4d63f1, (int)0xe6867fe9, (int)0xecdb8fca, (int)0xb9d465ee); - rc[9] = _mm_set_epi32((int)0x1c30bf84, (int)0xd4b7cd64, (int)0x5b2a404f, (int)0xad037e33); - rc[10] = _mm_set_epi32((int)0xb2cc0bb9, (int)0x941723bf, (int)0x69028b2e, (int)0x8df69800); - rc[11] = _mm_set_epi32((int)0xfa0478a6, (int)0xde6f5572, (int)0x4aaa9ec8, (int)0x5c9d2d8a); - rc[12] = _mm_set_epi32((int)0xdfb49f2b, (int)0x6b772a12, (int)0x0efa4f2e, (int)0x29129fd4); - rc[13] = _mm_set_epi32((int)0x1ea10344, (int)0xf449a236, (int)0x32d611ae, (int)0xbb6a12ee); - rc[14] = _mm_set_epi32((int)0xaf044988, (int)0x4b050084, (int)0x5f9600c9, (int)0x9ca8eca6); - rc[15] = _mm_set_epi32((int)0x21025ed8, (int)0x9d199c4f, (int)0x78a2c7e3, (int)0x27e593ec); - rc[16] = _mm_set_epi32((int)0xbf3aaaf8, (int)0xa759c9b7, (int)0xb9282ecd, (int)0x82d40173); - rc[17] = _mm_set_epi32((int)0x6260700d, (int)0x6186b017, (int)0x37f2efd9, (int)0x10307d6b); - rc[18] = _mm_set_epi32((int)0x5aca45c2, (int)0x21300443, (int)0x81c29153, (int)0xf6fc9ac6); - rc[19] = _mm_set_epi32((int)0x9223973c, (int)0x226b68bb, (int)0x2caf92e8, (int)0x36d1943a); - rc[20] = _mm_set_epi32((int)0xd3bf9238, (int)0x225886eb, (int)0x6cbab958, (int)0xe51071b4); - rc[21] = _mm_set_epi32((int)0xdb863ce5, (int)0xaef0c677, (int)0x933dfddd, (int)0x24e1128d); - rc[22] = _mm_set_epi32((int)0xbb606268, (int)0xffeba09c, (int)0x83e48de3, (int)0xcb2212b1); - rc[23] = _mm_set_epi32((int)0x734bd3dc, (int)0xe2e4d19c, (int)0x2db91a4e, (int)0xc72bf77d); - rc[24] = _mm_set_epi32((int)0x43bb47c3, (int)0x61301b43, (int)0x4b1415c4, (int)0x2cb3924e); - rc[25] = _mm_set_epi32((int)0xdba775a8, (int)0xe707eff6, (int)0x03b231dd, (int)0x16eb6899); - rc[26] = _mm_set_epi32((int)0x6df3614b, (int)0x3c755977, (int)0x8e5e2302, (int)0x7eca472c); - rc[27] = _mm_set_epi32((int)0xcda75a17, (int)0xd6de7d77, (int)0x6d1be5b9, (int)0xb88617f9); - rc[28] = _mm_set_epi32((int)0xec6b43f0, (int)0x6ba8e9aa, (int)0x9d6c069d, (int)0xa946ee5d); - rc[29] = _mm_set_epi32((int)0xcb1e6950, (int)0xf957332b, (int)0xa2531159, (int)0x3bf327c1); - rc[30] = _mm_set_epi32((int)0x2cee0c75, (int)0x00da619c, (int)0xe4ed0353, (int)0x600ed0d9); - rc[31] = _mm_set_epi32((int)0xf0b1a5a1, (int)0x96e90cab, (int)0x80bbbabc, (int)0x63a4a350); - rc[32] = _mm_set_epi32((int)0xae3db102, (int)0x5e962988, (int)0xab0dde30, (int)0x938dca39); - rc[33] = _mm_set_epi32((int)0x17bb8f38, (int)0xd554a40b, (int)0x8814f3a8, (int)0x2e75b442); - rc[34] = _mm_set_epi32((int)0x34bb8a5b, (int)0x5f427fd7, (int)0xaeb6b779, (int)0x360a16f6); - rc[35] = _mm_set_epi32((int)0x26f65241, (int)0xcbe55438, (int)0x43ce5918, (int)0xffbaafde); - rc[36] = _mm_set_epi32((int)0x4ce99a54, (int)0xb9f3026a, (int)0xa2ca9cf7, (int)0x839ec978); - rc[37] = _mm_set_epi32((int)0xae51a51a, (int)0x1bdff7be, (int)0x40c06e28, (int)0x22901235); - rc[38] = _mm_set_epi32((int)0xa0c1613c, (int)0xba7ed22b, (int)0xc173bc0f, (int)0x48a659cf); - rc[39] = _mm_set_epi32((int)0x756acc03, (int)0x02288288, (int)0x4ad6bdfd, (int)0xe9c59da1); -} - -void tweak_constants(spx_ctx *ctx) { - int i; - unsigned char buf[40 * 16]; - - /* Use the standard constants to generate tweaked ones. */ - load_haraka_constants(ctx->rc); - - /* Constants for pk.seed */ - haraka_S(buf, 40 * 16, ctx->pub_seed, SPX_N, ctx); - - /* Tweak constants with the pub_seed */ - for (i = 0; i < 40; i++) { - ctx->rc[i] = LOAD(buf + i * 16); - } -} - -static void haraka_S_absorb(unsigned char *s, unsigned int r, - const unsigned char *m, unsigned long long mlen, - unsigned char p, const spx_ctx *ctx) { - unsigned long long i; - PQCLEAN_VLA(unsigned char, t, r); - - while (mlen >= r) { - // XOR block to state - STORE(s, XOR128(LOAD(s), LOAD(m))); - STORE(s + 16, XOR128(LOAD(s + 16), LOAD(m + 16))); - haraka512_perm(s, s, ctx); - 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; - STORE(s, XOR128(LOAD(s), LOAD(t))); - STORE(s + 16, XOR128(LOAD(s + 16), LOAD(t + 16))); -} - -static void haraka_S_absorb4x(unsigned char *s, - unsigned int r, - const unsigned char *m0, - const unsigned char *m1, - const unsigned char *m2, - const unsigned char *m3, - unsigned long long int mlen, - unsigned char p, - const spx_ctx *ctx) { - unsigned long long i; - PQCLEAN_VLA(unsigned char, t0, r); - PQCLEAN_VLA(unsigned char, t1, r); - PQCLEAN_VLA(unsigned char, t2, r); - PQCLEAN_VLA(unsigned char, t3, r); - - while (mlen >= r) { - // XOR block to state - STORE(s, XOR128(LOAD(s), LOAD(m0))); - STORE(s + 16, XOR128(LOAD(s + 16), LOAD(m0 + 16))); - STORE(s + 64, XOR128(LOAD(s + 64), LOAD(m1))); - STORE(s + 80, XOR128(LOAD(s + 80), LOAD(m1 + 16))); - STORE(s + 128, XOR128(LOAD(s + 128), LOAD(m2))); - STORE(s + 144, XOR128(LOAD(s + 144), LOAD(m2 + 16))); - STORE(s + 192, XOR128(LOAD(s + 192), LOAD(m3))); - STORE(s + 208, XOR128(LOAD(s + 208), LOAD(m3 + 16))); - - haraka512_perm_x4(s, s, ctx); - mlen -= r; - m0 += r; - m1 += r; - m2 += r; - m3 += r; - } - - for (i = 0; i < r; ++i) { - t0[i] = 0; - t1[i] = 0; - t2[i] = 0; - t3[i] = 0; - } - for (i = 0; i < mlen; ++i) { - t0[i] = m0[i]; - t1[i] = m1[i]; - t2[i] = m2[i]; - t3[i] = m3[i]; - } - - t0[i] = p; - t1[i] = p; - t2[i] = p; - t3[i] = p; - - t0[r - 1] |= 128; - t1[r - 1] |= 128; - t2[r - 1] |= 128; - t3[r - 1] |= 128; - - STORE(s, XOR128(LOAD(s), LOAD(t0))); - STORE(s + 16, XOR128(LOAD(s + 16), LOAD(t0 + 16))); - STORE(s + 64, XOR128(LOAD(s + 64), LOAD(t1))); - STORE(s + 80, XOR128(LOAD(s + 80), LOAD(t1 + 16))); - STORE(s + 128, XOR128(LOAD(s + 128), LOAD(t2))); - STORE(s + 144, XOR128(LOAD(s + 144), LOAD(t2 + 16))); - STORE(s + 192, XOR128(LOAD(s + 192), LOAD(t3))); - STORE(s + 208, XOR128(LOAD(s + 208), LOAD(t3 + 16))); -} - -static void haraka_S_squeezeblocks(unsigned char *h, unsigned long long nblocks, - unsigned char *s, unsigned int r, - const spx_ctx *ctx) { - while (nblocks > 0) { - haraka512_perm(s, s, ctx); - STORE(h, LOAD(s)); - STORE(h + 16, LOAD(s + 16)); - h += r; - nblocks--; - } -} - -static void haraka_S_squeezeblocks4x(unsigned char *h0, - unsigned char *h1, - unsigned char *h2, - unsigned char *h3, - unsigned long long nblocks, - unsigned char *s, - unsigned int r, - const spx_ctx *ctx) { - while (nblocks > 0) { - haraka512_perm_x4(s, s, ctx); - STORE(h0, LOAD(s)); - STORE(h0 + 16, LOAD(s + 16)); - STORE(h1, LOAD(s + 64)); - STORE(h1 + 16, LOAD(s + 80)); - STORE(h2, LOAD(s + 128)); - STORE(h2 + 16, LOAD(s + 144)); - STORE(h3, LOAD(s + 192)); - STORE(h3 + 16, LOAD(s + 208)); - h0 += r; - h1 += r; - h2 += r; - h3 += r; - nblocks--; - } -} - -void haraka_S_inc_init(uint8_t *s_inc) { - size_t i; - - for (i = 0; i < 64; i++) { - s_inc[i] = 0; - } - s_inc[64] = 0; -} - -void haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, - const spx_ctx *ctx) { - size_t i; - - /* Recall that s_inc[64] is the non-absorbed bytes xored into the state */ - while (mlen + s_inc[64] >= HARAKAS_RATE) { - for (i = 0; i < (size_t)(HARAKAS_RATE - s_inc[64]); i++) { - /* Take the i'th byte from message - xor with the s_inc[64] + i'th byte of the state */ - s_inc[s_inc[64] + i] ^= m[i]; - } - mlen -= (size_t)(HARAKAS_RATE - s_inc[64]); - m += HARAKAS_RATE - s_inc[64]; - s_inc[64] = 0; - - haraka512_perm(s_inc, s_inc, ctx); - } - - for (i = 0; i < mlen; i++) { - s_inc[s_inc[64] + i] ^= m[i]; - } - s_inc[64] += (uint8_t)mlen; -} - -void haraka_S_inc_finalize(uint8_t *s_inc) { - /* After haraka_S_inc_absorb, we are guaranteed that s_inc[64] < HARAKAS_RATE, - so we can always use one more byte for p in the current state. */ - s_inc[s_inc[64]] ^= 0x1F; - s_inc[HARAKAS_RATE - 1] ^= 128; - s_inc[64] = 0; -} - -void haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, - const spx_ctx *ctx) { - size_t i; - - /* First consume any bytes we still have sitting around */ - for (i = 0; i < outlen && i < s_inc[64]; i++) { - /* There are s_inc[64] bytes left, so r - s_inc[64] is the first - available byte. We consume from there, i.e., up to r. */ - out[i] = (uint8_t)s_inc[(HARAKAS_RATE - s_inc[64] + i)]; - } - out += i; - outlen -= i; - s_inc[64] -= (uint8_t)i; - - /* Then squeeze the remaining necessary blocks */ - while (outlen > 0) { - haraka512_perm(s_inc, s_inc, ctx); - - for (i = 0; i < outlen && i < HARAKAS_RATE; i++) { - out[i] = s_inc[i]; - } - out += i; - outlen -= i; - s_inc[64] = (uint8_t)(HARAKAS_RATE - i); - } -} - -void haraka_S(unsigned char *out, unsigned long long outlen, - const unsigned char *in, unsigned long long inlen, - const spx_ctx *ctx) { - unsigned long long i; - unsigned char s[64]; - unsigned char d[32]; - - for (i = 0; i < 64; i++) { - s[i] = 0; - } - haraka_S_absorb(s, HARAKAS_RATE, in, inlen, 0x1F, ctx); - - haraka_S_squeezeblocks(out, outlen / HARAKAS_RATE, s, HARAKAS_RATE, ctx); - out += (outlen / HARAKAS_RATE) * HARAKAS_RATE; - - if (outlen % HARAKAS_RATE) { - haraka_S_squeezeblocks(d, 1, s, HARAKAS_RATE, ctx); - for (i = 0; i < outlen % HARAKAS_RATE; i++) { - out[i] = d[i]; - } - } -} - -void haraka_Sx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned long long outlen, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - unsigned long long inlen, - const spx_ctx *ctx) { - unsigned long long i; - unsigned char s[64 * 4]; - unsigned char d0[32]; - unsigned char d1[32]; - unsigned char d2[32]; - unsigned char d3[32]; - - for (i = 0; i < 64 * 4; i++) { - s[i] = 0; - } - haraka_S_absorb4x(s, HARAKAS_RATE, in0, in1, in2, in3, inlen, 0x1F, ctx); - - haraka_S_squeezeblocks4x(out0, out1, out2, out3, outlen / HARAKAS_RATE, s, - HARAKAS_RATE, ctx); - out0 += (outlen / HARAKAS_RATE) * HARAKAS_RATE; - out1 += (outlen / HARAKAS_RATE) * HARAKAS_RATE; - out2 += (outlen / HARAKAS_RATE) * HARAKAS_RATE; - out3 += (outlen / HARAKAS_RATE) * HARAKAS_RATE; - - if (outlen % HARAKAS_RATE) { - haraka_S_squeezeblocks4x(d0, d1, d2, d3, 1, s, HARAKAS_RATE, ctx); - for (i = 0; i < outlen % HARAKAS_RATE; i++) { - out0[i] = d0[i]; - out1[i] = d1[i]; - out2[i] = d2[i]; - out3[i] = d3[i]; - } - } -} - -void haraka512_perm(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx) { - u128 s[4], tmp; - - s[0] = LOAD(in); - s[1] = LOAD(in + 16); - s[2] = LOAD(in + 32); - s[3] = LOAD(in + 48); - - AES4(s[0], s[1], s[2], s[3], ctx->rc); - MIX4(s[0], s[1], s[2], s[3]); - - AES4(s[0], s[1], s[2], s[3], ctx->rc + 8); - MIX4(s[0], s[1], s[2], s[3]); - - AES4(s[0], s[1], s[2], s[3], ctx->rc + 16); - MIX4(s[0], s[1], s[2], s[3]); - - AES4(s[0], s[1], s[2], s[3], ctx->rc + 24); - MIX4(s[0], s[1], s[2], s[3]); - - AES4(s[0], s[1], s[2], s[3], ctx->rc + 32); - MIX4(s[0], s[1], s[2], s[3]); - - STORE(out, s[0]); - STORE(out + 16, s[1]); - STORE(out + 32, s[2]); - STORE(out + 48, s[3]); -} - -void haraka512_perm_x4(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx) { - u128 s[4][4], tmp; - - s[0][0] = LOAD(in); - s[0][1] = LOAD(in + 16); - s[0][2] = LOAD(in + 32); - s[0][3] = LOAD(in + 48); - s[1][0] = LOAD(in + 64); - s[1][1] = LOAD(in + 80); - s[1][2] = LOAD(in + 96); - s[1][3] = LOAD(in + 112); - s[2][0] = LOAD(in + 128); - s[2][1] = LOAD(in + 144); - s[2][2] = LOAD(in + 160); - s[2][3] = LOAD(in + 176); - s[3][0] = LOAD(in + 192); - s[3][1] = LOAD(in + 208); - s[3][2] = LOAD(in + 224); - s[3][3] = LOAD(in + 240); - - AES4_4x(s[0], s[1], s[2], s[3], ctx->rc); - MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); - MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); - MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); - MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - - AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 8); - MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); - MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); - MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); - MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - - AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 16); - MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); - MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); - MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); - MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - - AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 24); - MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); - MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); - MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); - MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - - AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 32); - MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); - MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); - MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); - MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - - STORE(out, s[0][0]); - STORE(out + 16, s[0][1]); - STORE(out + 32, s[0][2]); - STORE(out + 48, s[0][3]); - STORE(out + 64, s[1][0]); - STORE(out + 80, s[1][1]); - STORE(out + 96, s[1][2]); - STORE(out + 112, s[1][3]); - STORE(out + 128, s[2][0]); - STORE(out + 144, s[2][1]); - STORE(out + 160, s[2][2]); - STORE(out + 176, s[2][3]); - STORE(out + 192, s[3][0]); - STORE(out + 208, s[3][1]); - STORE(out + 224, s[3][2]); - STORE(out + 240, s[3][3]); -} - -void haraka512(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx) { - u128 s[4], tmp; - - s[0] = LOAD(in); - s[1] = LOAD(in + 16); - s[2] = LOAD(in + 32); - s[3] = LOAD(in + 48); - - AES4(s[0], s[1], s[2], s[3], ctx->rc); - MIX4(s[0], s[1], s[2], s[3]); - - AES4(s[0], s[1], s[2], s[3], ctx->rc + 8); - MIX4(s[0], s[1], s[2], s[3]); - - AES4(s[0], s[1], s[2], s[3], ctx->rc + 16); - MIX4(s[0], s[1], s[2], s[3]); - - AES4(s[0], s[1], s[2], s[3], ctx->rc + 24); - MIX4(s[0], s[1], s[2], s[3]); - - AES4(s[0], s[1], s[2], s[3], ctx->rc + 32); - MIX4(s[0], s[1], s[2], s[3]); - - s[0] = XOR128(s[0], LOAD(in)); - s[1] = XOR128(s[1], LOAD(in + 16)); - s[2] = XOR128(s[2], LOAD(in + 32)); - s[3] = XOR128(s[3], LOAD(in + 48)); - - // truncate and store result - TRUNCSTORE(out, s[0], s[1], s[2], s[3]); -} - -void haraka512x4(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx) { - u128 s[4][4], tmp; - - s[0][0] = LOAD(in); - s[0][1] = LOAD(in + 16); - s[0][2] = LOAD(in + 32); - s[0][3] = LOAD(in + 48); - s[1][0] = LOAD(in + 64); - s[1][1] = LOAD(in + 80); - s[1][2] = LOAD(in + 96); - s[1][3] = LOAD(in + 112); - s[2][0] = LOAD(in + 128); - s[2][1] = LOAD(in + 144); - s[2][2] = LOAD(in + 160); - s[2][3] = LOAD(in + 176); - s[3][0] = LOAD(in + 192); - s[3][1] = LOAD(in + 208); - s[3][2] = LOAD(in + 224); - s[3][3] = LOAD(in + 240); - - AES4_4x(s[0], s[1], s[2], s[3], ctx->rc); - MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); - MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); - MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); - MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - - AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 8); - MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); - MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); - MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); - MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - - AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 16); - MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); - MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); - MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); - MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - - AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 24); - MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); - MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); - MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); - MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - - AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 32); - MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); - MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); - MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); - MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - - s[0][0] = XOR128(s[0][0], LOAD(in)); - s[0][1] = XOR128(s[0][1], LOAD(in + 16)); - s[0][2] = XOR128(s[0][2], LOAD(in + 32)); - s[0][3] = XOR128(s[0][3], LOAD(in + 48)); - s[1][0] = XOR128(s[1][0], LOAD(in + 64)); - s[1][1] = XOR128(s[1][1], LOAD(in + 80)); - s[1][2] = XOR128(s[1][2], LOAD(in + 96)); - s[1][3] = XOR128(s[1][3], LOAD(in + 112)); - s[2][0] = XOR128(s[2][0], LOAD(in + 128)); - s[2][1] = XOR128(s[2][1], LOAD(in + 144)); - s[2][2] = XOR128(s[2][2], LOAD(in + 160)); - s[2][3] = XOR128(s[2][3], LOAD(in + 176)); - s[3][0] = XOR128(s[3][0], LOAD(in + 192)); - s[3][1] = XOR128(s[3][1], LOAD(in + 208)); - s[3][2] = XOR128(s[3][2], LOAD(in + 224)); - s[3][3] = XOR128(s[3][3], LOAD(in + 240)); - - TRUNCSTORE(out, s[0][0], s[0][1], s[0][2], s[0][3]); - TRUNCSTORE((out + 32), s[1][0], s[1][1], s[1][2], s[1][3]); - TRUNCSTORE((out + 64), s[2][0], s[2][1], s[2][2], s[2][3]); - TRUNCSTORE((out + 96), s[3][0], s[3][1], s[3][2], s[3][3]); -} - -void haraka256(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx) { - u128 s[2], tmp; - - s[0] = LOAD(in); - s[1] = LOAD(in + 16); - - AES2(s[0], s[1], ctx->rc); - MIX2(s[0], s[1]); - - AES2(s[0], s[1], ctx->rc + 4); - MIX2(s[0], s[1]); - - AES2(s[0], s[1], ctx->rc + 8); - MIX2(s[0], s[1]); - - AES2(s[0], s[1], ctx->rc + 12); - MIX2(s[0], s[1]); - - AES2(s[0], s[1], ctx->rc + 16); - MIX2(s[0], s[1]); - - s[0] = XOR128(s[0], LOAD(in)); - s[1] = XOR128(s[1], LOAD(in + 16)); - - STORE(out, s[0]); - STORE(out + 16, s[1]); -} - -void haraka256x4(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx) { - u128 s[4][2], tmp; - - s[0][0] = LOAD(in); - s[0][1] = LOAD(in + 16); - s[1][0] = LOAD(in + 32); - s[1][1] = LOAD(in + 48); - s[2][0] = LOAD(in + 64); - s[2][1] = LOAD(in + 80); - s[3][0] = LOAD(in + 96); - s[3][1] = LOAD(in + 112); - - // Round 1 - AES2_4x(s[0], s[1], s[2], s[3], ctx->rc); - - MIX2(s[0][0], s[0][1]); - MIX2(s[1][0], s[1][1]); - MIX2(s[2][0], s[2][1]); - MIX2(s[3][0], s[3][1]); - - // Round 2 - AES2_4x(s[0], s[1], s[2], s[3], ctx->rc + 4); - - MIX2(s[0][0], s[0][1]); - MIX2(s[1][0], s[1][1]); - MIX2(s[2][0], s[2][1]); - MIX2(s[3][0], s[3][1]); - - // Round 3 - AES2_4x(s[0], s[1], s[2], s[3], ctx->rc + 8); - - MIX2(s[0][0], s[0][1]); - MIX2(s[1][0], s[1][1]); - MIX2(s[2][0], s[2][1]); - MIX2(s[3][0], s[3][1]); - - // Round 4 - AES2_4x(s[0], s[1], s[2], s[3], ctx->rc + 12); - - MIX2(s[0][0], s[0][1]); - MIX2(s[1][0], s[1][1]); - MIX2(s[2][0], s[2][1]); - MIX2(s[3][0], s[3][1]); - - // Round 5 - AES2_4x(s[0], s[1], s[2], s[3], ctx->rc + 16); - - MIX2(s[0][0], s[0][1]); - MIX2(s[1][0], s[1][1]); - MIX2(s[2][0], s[2][1]); - MIX2(s[3][0], s[3][1]); - - // Feed Forward - s[0][0] = _mm_xor_si128(s[0][0], LOAD(in)); - s[0][1] = _mm_xor_si128(s[0][1], LOAD(in + 16)); - s[1][0] = _mm_xor_si128(s[1][0], LOAD(in + 32)); - s[1][1] = _mm_xor_si128(s[1][1], LOAD(in + 48)); - s[2][0] = _mm_xor_si128(s[2][0], LOAD(in + 64)); - s[2][1] = _mm_xor_si128(s[2][1], LOAD(in + 80)); - s[3][0] = _mm_xor_si128(s[3][0], LOAD(in + 96)); - s[3][1] = _mm_xor_si128(s[3][1], LOAD(in + 112)); - - STORE(out, s[0][0]); - STORE(out + 16, s[0][1]); - STORE(out + 32, s[1][0]); - STORE(out + 48, s[1][1]); - STORE(out + 64, s[2][0]); - STORE(out + 80, s[2][1]); - STORE(out + 96, s[3][0]); - STORE(out + 112, s[3][1]); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/haraka.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/haraka.h deleted file mode 100644 index 737cb6065f..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/haraka.h +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef SPX_HARAKA_H -#define SPX_HARAKA_H - -#include "context.h" -#include "params.h" - -/* Tweak constants with seed */ -#define tweak_constants SPX_NAMESPACE(tweak_constants) -void tweak_constants(spx_ctx *ctx); - -/* Haraka Sponge */ -#define haraka_S_inc_init SPX_NAMESPACE(haraka_S_inc_init) -void haraka_S_inc_init(uint8_t *s_inc); -#define haraka_S_inc_absorb SPX_NAMESPACE(haraka_S_inc_absorb) -void haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, - const spx_ctx *ctx); -#define haraka_S_inc_finalize SPX_NAMESPACE(haraka_S_inc_finalize) -void haraka_S_inc_finalize(uint8_t *s_inc); -#define haraka_S_inc_squeeze SPX_NAMESPACE(haraka_S_inc_squeeze) -void haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, - const spx_ctx *ctx); -#define haraka_S SPX_NAMESPACE(haraka_S) -void haraka_S(unsigned char *out, unsigned long long outlen, - const unsigned char *in, unsigned long long inlen, - const spx_ctx *ctx); - -/* Applies the 512-bit Haraka permutation to in. */ -#define haraka512_perm SPX_NAMESPACE(haraka512_perm) -void haraka512_perm(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx); - -/* Implementation of Haraka-512 */ -#define haraka512 SPX_NAMESPACE(haraka512) -void haraka512(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx); - -/* Implementation of Haraka-256 */ -#define haraka256 SPX_NAMESPACE(haraka256) -void haraka256(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/haraka_offsets.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/haraka_offsets.h deleted file mode 100644 index 7c062272a0..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/haraka_offsets.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef HARAKA_OFFSETS_H_ -#define HARAKA_OFFSETS_H_ - -/* - * Offsets of various fields in the address structure when we use Haraka as - * the Sphincs+ hash function - */ - -#define SPX_OFFSET_LAYER 3 /* The byte used to specify the Merkle tree layer */ -#define SPX_OFFSET_TREE 8 /* The start of the 8 byte field used to specify the tree */ -#define SPX_OFFSET_TYPE 19 /* The byte used to specify the hash type (reason) */ -#define SPX_OFFSET_KP_ADDR2 22 /* The high byte used to specify the key pair (which one-time signature) */ -#define SPX_OFFSET_KP_ADDR1 23 /* The low byte used to specify the key pair */ -#define SPX_OFFSET_CHAIN_ADDR 27 /* The byte used to specify the chain address (which Winternitz chain) */ -#define SPX_OFFSET_HASH_ADDR 31 /* The byte used to specify the hash address (where in the Winternitz chain) */ -#define SPX_OFFSET_TREE_HGT 27 /* The byte used to specify the height of this node in the FORS or Merkle tree */ -#define SPX_OFFSET_TREE_INDEX 28 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ - -#define SPX_HARAKA 1 - -#endif /* HARAKA_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/harakax4.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/harakax4.h deleted file mode 100644 index eadc69aa48..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/harakax4.h +++ /dev/null @@ -1,36 +0,0 @@ -#ifndef SPX_HARAKAX4_H -#define SPX_HARAKAX4_H - -#include "context.h" -#include "params.h" - -/* Haraka Sponge */ -#define haraka_Sx4 SPX_NAMESPACE(haraka_Sx4) -void haraka_Sx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned long long outlen, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - unsigned long long inlen, - const spx_ctx *ctx); - -/* Applies the 512-bit Haraka permutation x4 to in. */ -#define haraka512_perm_x4 SPX_NAMESPACE(haraka512_perm_x4) -void haraka512_perm_x4(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx); - -/* Implementation of Haraka-512 x4*/ -#define haraka512x4 SPX_NAMESPACE(haraka512x4) -void haraka512x4(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx); - -/* Implementation of Haraka-256 x4 */ -#define haraka256x4 SPX_NAMESPACE(haraka256x4) -void haraka256x4(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/hash.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/hash.h deleted file mode 100644 index f7c87d4c3c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/hash.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef SPX_HASH_H -#define SPX_HASH_H - -#include -#include - -#include "context.h" -#include "params.h" - -#define prf_addr SPX_NAMESPACE(prf_addr) -void prf_addr(unsigned char *out, const spx_ctx *ctx, - const uint32_t addr[8]); - -#define gen_message_random SPX_NAMESPACE(gen_message_random) -void gen_message_random(unsigned char *R, const unsigned char *sk_prf, - const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx); - -#define hash_message SPX_NAMESPACE(hash_message) -void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx); - - - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/hash_haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/hash_haraka.c deleted file mode 100644 index 750a67423b..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/hash_haraka.c +++ /dev/null @@ -1,81 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "utils.h" - -#include "haraka.h" -#include "hash.h" - -/* - * Computes PRF(key, addr), given a secret key of SPX_N bytes and an address - */ -void prf_addr(unsigned char *out, const spx_ctx *ctx, - const uint32_t addr[8]) { - /* Since SPX_N may be smaller than 32, we need temporary buffers. */ - unsigned char outbuf[32]; - unsigned char buf[64] = {0}; - - memcpy(buf, addr, SPX_ADDR_BYTES); - memcpy(buf + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); - - haraka512(outbuf, (const void *)buf, ctx); - memcpy(out, outbuf, SPX_N); -} - -/** - * Computes the message-dependent randomness R, using a secret seed and an - * optional randomization value as well as the message. - */ -void gen_message_random(unsigned char *R, const unsigned char *sk_prf, - const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx) { - uint8_t s_inc[65]; - - haraka_S_inc_init(s_inc); - haraka_S_inc_absorb(s_inc, sk_prf, SPX_N, ctx); - haraka_S_inc_absorb(s_inc, optrand, SPX_N, ctx); - haraka_S_inc_absorb(s_inc, m, mlen, ctx); - haraka_S_inc_finalize(s_inc); - haraka_S_inc_squeeze(R, SPX_N, s_inc, ctx); -} - -/** - * Computes the message hash using R, the public key, and the message. - * Outputs the message digest and the index of the leaf. The index is split in - * the tree index and the leaf index, for convenient copying to an address. - */ -void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx) { -#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) -#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) -#define SPX_LEAF_BITS SPX_TREE_HEIGHT -#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) -#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) - - unsigned char buf[SPX_DGST_BYTES]; - unsigned char *bufp = buf; - uint8_t s_inc[65]; - - haraka_S_inc_init(s_inc); - haraka_S_inc_absorb(s_inc, R, SPX_N, ctx); - haraka_S_inc_absorb(s_inc, pk + SPX_N, SPX_N, ctx); // Only absorb root part of pk - haraka_S_inc_absorb(s_inc, m, mlen, ctx); - haraka_S_inc_finalize(s_inc); - haraka_S_inc_squeeze(buf, SPX_DGST_BYTES, s_inc, ctx); - - memcpy(digest, bufp, SPX_FORS_MSG_BYTES); - bufp += SPX_FORS_MSG_BYTES; - - - *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); - *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); - bufp += SPX_TREE_BYTES; - - *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); - *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/hash_harakax4.c b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/hash_harakax4.c deleted file mode 100644 index cfa5162d79..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/hash_harakax4.c +++ /dev/null @@ -1,35 +0,0 @@ -#include -#include - -#include "address.h" -#include "harakax4.h" -#include "hashx4.h" -#include "params.h" - -/* - * 4-way parallel version of prf_addr; takes 4x as much input and output - */ -#define prf_addrx4 SPX_NAMESPACE(prf_addrx4) -void prf_addrx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const spx_ctx *ctx, - const uint32_t addrx4[4 * 8]) { - unsigned char bufx4[4 * 64] = {0}; - /* Since SPX_N may be smaller than 32, we need temporary buffers. */ - unsigned char outbuf[4 * 32]; - unsigned int i; - - for (i = 0; i < 4; i++) { - memcpy(bufx4 + i * 64, addrx4 + i * 8, SPX_ADDR_BYTES); - memcpy(bufx4 + i * 64 + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); - } - - haraka512x4(outbuf, bufx4, ctx); - - memcpy(out0, outbuf, SPX_N); - memcpy(out1, outbuf + 32, SPX_N); - memcpy(out2, outbuf + 64, SPX_N); - memcpy(out3, outbuf + 96, SPX_N); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/hashx4.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/hashx4.h deleted file mode 100644 index 3751a0ebd0..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/hashx4.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef SPX_HASHX4_H -#define SPX_HASHX4_H - -#include - -#include "context.h" -#include "params.h" - -#define prf_addrx4 SPX_NAMESPACE(prf_addrx4) -void prf_addrx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const spx_ctx *ctx, - const uint32_t addrx4[4 * 8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/merkle.c b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/merkle.c deleted file mode 100644 index f57811c1ac..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/merkle.c +++ /dev/null @@ -1,64 +0,0 @@ -#include -#include - -#include "merkle.h" - -#include "address.h" -#include "params.h" -#include "utils.h" -#include "utilsx4.h" -#include "wots.h" -#include "wotsx4.h" - -/* - * This generates a Merkle signature (WOTS signature followed by the Merkle - * authentication path). - */ -void merkle_sign(uint8_t *sig, unsigned char *root, - const spx_ctx *ctx, - uint32_t wots_addr[8], uint32_t tree_addr[8], - uint32_t idx_leaf) { - unsigned char *auth_path = sig + SPX_WOTS_BYTES; - uint32_t tree_addrx4[4 * 8] = { 0 }; - int j; - struct leaf_info_x4 info = { 0 }; - unsigned steps[ SPX_WOTS_LEN ]; - - info.wots_sig = sig; - chain_lengths(steps, root); - info.wots_steps = steps; - - for (j = 0; j < 4; j++) { - set_type(&tree_addrx4[8 * j], SPX_ADDR_TYPE_HASHTREE); - set_type(&info.leaf_addr[8 * j], SPX_ADDR_TYPE_WOTS); - set_type(&info.pk_addr[8 * j], SPX_ADDR_TYPE_WOTSPK); - copy_subtree_addr(&tree_addrx4[8 * j], tree_addr); - copy_subtree_addr(&info.leaf_addr[8 * j], wots_addr); - copy_subtree_addr(&info.pk_addr[8 * j], wots_addr); - } - - info.wots_sign_leaf = idx_leaf; - - treehashx4(root, auth_path, ctx, - idx_leaf, 0, - SPX_TREE_HEIGHT, - wots_gen_leafx4, - tree_addrx4, &info); -} - -/* Compute root node of the top-most subtree. */ -void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { - /* We do not need the auth path in key generation, but it simplifies the - code to have just one treehash routine that computes both root and path - in one function. */ - unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; - uint32_t top_tree_addr[8] = {0}; - uint32_t wots_addr[8] = {0}; - - set_layer_addr(top_tree_addr, SPX_D - 1); - set_layer_addr(wots_addr, SPX_D - 1); - - merkle_sign(auth_path, root, ctx, - wots_addr, top_tree_addr, - ~0U /* ~0 means "don't bother generating an auth path */ ); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/merkle.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/merkle.h deleted file mode 100644 index 769cf2e970..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/merkle.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef MERKLE_H_ -#define MERKLE_H_ - -#include - -#include "context.h" -#include "params.h" - -/* Generate a Merkle signature (WOTS signature followed by the Merkle */ -/* authentication path) */ -#define merkle_sign SPX_NAMESPACE(merkle_sign) -void merkle_sign(uint8_t *sig, unsigned char *root, - const spx_ctx *ctx, - uint32_t wots_addr[8], uint32_t tree_addr[8], - uint32_t idx_leaf); - -/* Compute the root node of the top-most subtree. */ -#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) -void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); - -#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/nistapi.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/nistapi.h deleted file mode 100644 index 3cb71afad4..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/nistapi.h +++ /dev/null @@ -1,87 +0,0 @@ -#ifndef SPX_API_H -#define SPX_API_H - -#include -#include - -#include "params.h" - -#define CRYPTO_ALGNAME "SPHINCS+" - -#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES -#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES -#define CRYPTO_BYTES SPX_BYTES -#define CRYPTO_SEEDBYTES (3*SPX_N) - -/* - * Returns the length of a secret key, in bytes - */ -#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) -size_t crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) -size_t crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) -size_t crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) -size_t crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) -int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) -int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) -int crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) -int crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -#define crypto_sign SPX_NAMESPACE(crypto_sign) -int crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) -int crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/params.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/params.h deleted file mode 100644 index a4e20d99ac..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/params.h +++ /dev/null @@ -1,56 +0,0 @@ -#ifndef SPX_PARAMS_H -#define SPX_PARAMS_H - -#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_##s - -/* Hash output length in bytes. */ -#define SPX_N 32 -/* Height of the hypertree. */ -#define SPX_FULL_HEIGHT 68 -/* Number of subtree layer. */ -#define SPX_D 17 -/* FORS tree dimensions. */ -#define SPX_FORS_HEIGHT 9 -#define SPX_FORS_TREES 35 -/* Winternitz parameter, */ -#define SPX_WOTS_W 16 - -/* The hash function is defined by linking a different hash.c file, as opposed - to setting a #define constant. */ - -/* For clarity */ -#define SPX_ADDR_BYTES 32 - -/* WOTS parameters. */ -#define SPX_WOTS_LOGW 4 - -#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) - -/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#define SPX_WOTS_LEN2 3 - -#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) -#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) -#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES - -/* Subtree size. */ -#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) - -//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT -// #error SPX_D should always divide SPX_FULL_HEIGHT -//#endif - -/* FORS parameters. */ -#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) -#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) -#define SPX_FORS_PK_BYTES SPX_N - -/* Resulting SPX sizes. */ -#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ - SPX_FULL_HEIGHT * SPX_N) -#define SPX_PK_BYTES (2 * SPX_N) -#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) - -#include "haraka_offsets.h" - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/sign.c b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/sign.c deleted file mode 100644 index 9d0c7d1b22..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/sign.c +++ /dev/null @@ -1,286 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "context.h" -#include "fors.h" -#include "hash.h" -#include "merkle.h" -#include "nistapi.h" -#include "params.h" -#include "randombytes.h" -#include "thash.h" -#include "utils.h" -#include "wots.h" - -/* - * Returns the length of a secret key, in bytes - */ -size_t crypto_sign_secretkeybytes(void) { - return CRYPTO_SECRETKEYBYTES; -} - -/* - * Returns the length of a public key, in bytes - */ -size_t crypto_sign_publickeybytes(void) { - return CRYPTO_PUBLICKEYBYTES; -} - -/* - * Returns the length of a signature, in bytes - */ -size_t crypto_sign_bytes(void) { - return CRYPTO_BYTES; -} - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t crypto_sign_seedbytes(void) { - return CRYPTO_SEEDBYTES; -} - -/* - * Generates an SPX key pair given a seed of length - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed) { - spx_ctx ctx; - - /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ - memcpy(sk, seed, CRYPTO_SEEDBYTES); - - memcpy(pk, sk + 2 * SPX_N, SPX_N); - - memcpy(ctx.pub_seed, pk, SPX_N); - memcpy(ctx.sk_seed, sk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - /* Compute root node of the top-most subtree. */ - merkle_gen_root(sk + 3 * SPX_N, &ctx); - - // cleanup - free_hash_function(&ctx); - - memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); - - return 0; -} - -/* - * Generates an SPX key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { - uint8_t seed[CRYPTO_SEEDBYTES]; - randombytes(seed, CRYPTO_SEEDBYTES); - crypto_sign_seed_keypair(pk, sk, seed); - - return 0; -} - -/** - * Returns an array containing a detached signature. - */ -int crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - spx_ctx ctx; - - const uint8_t *sk_prf = sk + SPX_N; - const uint8_t *pk = sk + 2 * SPX_N; - - uint8_t optrand[SPX_N]; - uint8_t mhash[SPX_FORS_MSG_BYTES]; - uint8_t root[SPX_N]; - uint32_t i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - - memcpy(ctx.sk_seed, sk, SPX_N); - memcpy(ctx.pub_seed, pk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - set_type(wots_addr, SPX_ADDR_TYPE_WOTS); - set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); - - /* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ - randombytes(optrand, SPX_N); - /* Compute the digest randomization value. */ - gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); - - /* Derive the message digest and leaf index from R, PK and M. */ - hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); - sig += SPX_N; - - set_tree_addr(wots_addr, tree); - set_keypair_addr(wots_addr, idx_leaf); - - /* Sign the message hash using FORS. */ - fors_sign(sig, root, mhash, &ctx, wots_addr); - sig += SPX_FORS_BYTES; - - for (i = 0; i < SPX_D; i++) { - set_layer_addr(tree_addr, i); - set_tree_addr(tree_addr, tree); - - copy_subtree_addr(wots_addr, tree_addr); - set_keypair_addr(wots_addr, idx_leaf); - - merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); - sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); - tree = tree >> SPX_TREE_HEIGHT; - } - - free_hash_function(&ctx); - - *siglen = SPX_BYTES; - - return 0; -} - -/** - * Verifies a detached signature and message under a given public key. - */ -int crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk) { - spx_ctx ctx; - const uint8_t *pub_root = pk + SPX_N; - uint8_t mhash[SPX_FORS_MSG_BYTES]; - uint8_t wots_pk[SPX_WOTS_BYTES]; - uint8_t root[SPX_N]; - uint8_t leaf[SPX_N]; - unsigned int i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - if (siglen != SPX_BYTES) { - return -1; - } - - memcpy(ctx.pub_seed, pk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - set_type(wots_addr, SPX_ADDR_TYPE_WOTS); - set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); - set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); - - /* Derive the message digest and leaf index from R || PK || M. */ - /* The additional SPX_N is a result of the hash domain separator. */ - hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); - sig += SPX_N; - - /* Layer correctly defaults to 0, so no need to set_layer_addr */ - set_tree_addr(wots_addr, tree); - set_keypair_addr(wots_addr, idx_leaf); - - fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); - sig += SPX_FORS_BYTES; - - /* For each subtree.. */ - for (i = 0; i < SPX_D; i++) { - set_layer_addr(tree_addr, i); - set_tree_addr(tree_addr, tree); - - copy_subtree_addr(wots_addr, tree_addr); - set_keypair_addr(wots_addr, idx_leaf); - - copy_keypair_addr(wots_pk_addr, wots_addr); - - /* The WOTS public key is only correct if the signature was correct. */ - /* Initially, root is the FORS pk, but on subsequent iterations it is - the root of the subtree below the currently processed subtree. */ - wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); - sig += SPX_WOTS_BYTES; - - /* Compute the leaf node using the WOTS public key. */ - thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); - - /* Compute the root node of this subtree. */ - compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, - &ctx, tree_addr); - sig += SPX_TREE_HEIGHT * SPX_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); - tree = tree >> SPX_TREE_HEIGHT; - } - - // cleanup - free_hash_function(&ctx); - - /* Check if the root node equals the root node in the public key. */ - if (memcmp(root, pub_root, SPX_N) != 0) { - return -1; - } - - return 0; -} - - -/** - * Returns an array containing the signature followed by the message. - */ -int crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk) { - size_t siglen; - - crypto_sign_signature(sm, &siglen, m, mlen, sk); - - memmove(sm + SPX_BYTES, m, mlen); - *smlen = siglen + mlen; - - return 0; -} - -/** - * Verifies a given signature-message pair under a given public key. - */ -int crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk) { - /* The API caller does not necessarily know what size a signature should be - but SPHINCS+ signatures are always exactly SPX_BYTES. */ - if (smlen < SPX_BYTES) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - *mlen = smlen - SPX_BYTES; - - if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - /* If verification was successful, move the message to the right place. */ - memmove(m, sm + SPX_BYTES, *mlen); - - return 0; -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/thash.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/thash.h deleted file mode 100644 index 8687ccfb4d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/thash.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef SPX_THASH_H -#define SPX_THASH_H - -#include "context.h" -#include "params.h" - -#include - -#define thash SPX_NAMESPACE(thash) -void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/thash_haraka_robust.c b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/thash_haraka_robust.c deleted file mode 100644 index 109502cbc2..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/thash_haraka_robust.c +++ /dev/null @@ -1,45 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "thash.h" -#include "utils.h" - -#include "haraka.h" - -/** - * Takes an array of inblocks concatenated arrays of SPX_N bytes. - */ -void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]) { - PQCLEAN_VLA(uint8_t, buf, SPX_ADDR_BYTES + inblocks * SPX_N); - PQCLEAN_VLA(uint8_t, bitmask, inblocks * SPX_N); - unsigned char outbuf[32]; - unsigned char buf_tmp[64]; - unsigned int i; - - if (inblocks == 1) { - /* F function */ - /* Since SPX_N may be smaller than 32, we need a temporary buffer. */ - memset(buf_tmp, 0, 64); - memcpy(buf_tmp, addr, 32); - - haraka256(outbuf, buf_tmp, ctx); - for (i = 0; i < inblocks * SPX_N; i++) { - buf_tmp[SPX_ADDR_BYTES + i] = in[i] ^ outbuf[i]; - } - haraka512(outbuf, buf_tmp, ctx); - memcpy(out, outbuf, SPX_N); - } else { - /* All other tweakable hashes*/ - memcpy(buf, addr, 32); - haraka_S(bitmask, inblocks * SPX_N, buf, SPX_ADDR_BYTES, ctx); - - for (i = 0; i < inblocks * SPX_N; i++) { - buf[SPX_ADDR_BYTES + i] = in[i] ^ bitmask[i]; - } - - haraka_S(out, SPX_N, buf, SPX_ADDR_BYTES + inblocks * SPX_N, ctx); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/thash_haraka_robustx4.c b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/thash_haraka_robustx4.c deleted file mode 100644 index 100808a3a5..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/thash_haraka_robustx4.c +++ /dev/null @@ -1,93 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "thashx4.h" - -#include "harakax4.h" - -#include "utils.h" - -/** - * 4-way parallel version of thash; takes 4x as much input and output - */ -#define thashx4 SPX_NAMESPACE(thashx4) -void thashx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addrx4[4 * 8]) { - PQCLEAN_VLA(unsigned char, buf0, SPX_ADDR_BYTES + inblocks * SPX_N); - PQCLEAN_VLA(unsigned char, buf1, SPX_ADDR_BYTES + inblocks * SPX_N); - PQCLEAN_VLA(unsigned char, buf2, SPX_ADDR_BYTES + inblocks * SPX_N); - PQCLEAN_VLA(unsigned char, buf3, SPX_ADDR_BYTES + inblocks * SPX_N); - PQCLEAN_VLA(unsigned char, bitmask0, inblocks * SPX_N); - PQCLEAN_VLA(unsigned char, bitmask1, inblocks * SPX_N); - PQCLEAN_VLA(unsigned char, bitmask2, inblocks * SPX_N); - PQCLEAN_VLA(unsigned char, bitmask3, inblocks * SPX_N); - unsigned char outbuf[32 * 4]; - unsigned char buf_tmp[64 * 4]; - unsigned int i; - - if (inblocks == 1) { - memset(buf_tmp, 0, 64 * 4); - - // Generate masks first in buffer - memcpy(buf_tmp, addrx4 + 0 * 8, 32); - memcpy(buf_tmp + 32, addrx4 + 1 * 8, 32); - memcpy(buf_tmp + 64, addrx4 + 2 * 8, 32); - memcpy(buf_tmp + 96, addrx4 + 3 * 8, 32); - - haraka256x4(outbuf, buf_tmp, ctx); - - /* move addresses to make room for inputs; zero old values */ - memcpy(buf_tmp + 192, buf_tmp + 96, SPX_ADDR_BYTES); - memcpy(buf_tmp + 128, buf_tmp + 64, SPX_ADDR_BYTES); - memcpy(buf_tmp + 64, buf_tmp + 32, SPX_ADDR_BYTES); - /* skip memcpy(buf_tmp, buf_tmp, SPX_ADDR_BYTES); already in place */ - - /* skip memset(buf_tmp, 0, SPX_ADDR_BYTES); remained untouched */ - memset(buf_tmp + 32, 0, SPX_ADDR_BYTES); - /* skip memset(buf_tmp + 64, 0, SPX_ADDR_BYTES); contains addr1 */ - memset(buf_tmp + 96, 0, SPX_ADDR_BYTES); - - for (i = 0; i < SPX_N; i++) { - buf_tmp[SPX_ADDR_BYTES + i] = in0[i] ^ outbuf[i]; - buf_tmp[SPX_ADDR_BYTES + i + 64] = in1[i] ^ outbuf[i + 32]; - buf_tmp[SPX_ADDR_BYTES + i + 128] = in2[i] ^ outbuf[i + 64]; - buf_tmp[SPX_ADDR_BYTES + i + 192] = in3[i] ^ outbuf[i + 96]; - } - - haraka512x4(outbuf, buf_tmp, ctx); - - memcpy(out0, outbuf, SPX_N); - memcpy(out1, outbuf + 32, SPX_N); - memcpy(out2, outbuf + 64, SPX_N); - memcpy(out3, outbuf + 96, SPX_N); - } else { - /* All other tweakable hashes*/ - memcpy(buf0, addrx4 + 0 * 8, 32); - memcpy(buf1, addrx4 + 1 * 8, 32); - memcpy(buf2, addrx4 + 2 * 8, 32); - memcpy(buf3, addrx4 + 3 * 8, 32); - - haraka_Sx4(bitmask0, bitmask1, bitmask2, bitmask3, inblocks * SPX_N, - buf0, buf1, buf2, buf3, SPX_ADDR_BYTES, ctx); - - for (i = 0; i < inblocks * SPX_N; i++) { - buf0[SPX_ADDR_BYTES + i] = in0[i] ^ bitmask0[i]; - buf1[SPX_ADDR_BYTES + i] = in1[i] ^ bitmask1[i]; - buf2[SPX_ADDR_BYTES + i] = in2[i] ^ bitmask2[i]; - buf3[SPX_ADDR_BYTES + i] = in3[i] ^ bitmask3[i]; - } - - haraka_Sx4(out0, out1, out2, out3, SPX_N, - buf0, buf1, buf2, buf3, SPX_ADDR_BYTES + inblocks * SPX_N, - ctx); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/thashx4.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/thashx4.h deleted file mode 100644 index 64798a3727..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/thashx4.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef SPX_THASHX4_H -#define SPX_THASHX4_H - -#include - -#include "context.h" -#include "params.h" - -#define thashx4 SPX_NAMESPACE(thashx4) -void thashx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addrx4[4 * 8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/utils.c b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/utils.c deleted file mode 100644 index 177b541fb9..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/utils.c +++ /dev/null @@ -1,148 +0,0 @@ -#include - -#include "utils.h" - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "thash.h" - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void ull_to_bytes(unsigned char *out, unsigned int outlen, - unsigned long long in) { - int i; - - /* Iterate over out in decreasing order, for big-endianness. */ - for (i = (signed int)outlen - 1; i >= 0; i--) { - out[i] = in & 0xff; - in = in >> 8; - } -} - -void u32_to_bytes(unsigned char *out, uint32_t in) { - out[0] = (unsigned char)(in >> 24); - out[1] = (unsigned char)(in >> 16); - out[2] = (unsigned char)(in >> 8); - out[3] = (unsigned char)in; -} - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { - unsigned long long retval = 0; - unsigned int i; - - for (i = 0; i < inlen; i++) { - retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); - } - return retval; -} - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void compute_root(unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const spx_ctx *ctx, uint32_t addr[8]) { - uint32_t i; - unsigned char buffer[2 * SPX_N]; - - /* If leaf_idx is odd (last bit = 1), current path element is a right child - and auth_path has to go left. Otherwise it is the other way around. */ - if (leaf_idx & 1) { - memcpy(buffer + SPX_N, leaf, SPX_N); - memcpy(buffer, auth_path, SPX_N); - } else { - memcpy(buffer, leaf, SPX_N); - memcpy(buffer + SPX_N, auth_path, SPX_N); - } - auth_path += SPX_N; - - for (i = 0; i < tree_height - 1; i++) { - leaf_idx >>= 1; - idx_offset >>= 1; - /* Set the address of the node we're creating. */ - set_tree_height(addr, i + 1); - set_tree_index(addr, leaf_idx + idx_offset); - - /* Pick the right or left neighbor, depending on parity of the node. */ - if (leaf_idx & 1) { - thash(buffer + SPX_N, buffer, 2, ctx, addr); - memcpy(buffer, auth_path, SPX_N); - } else { - thash(buffer, buffer, 2, ctx, addr); - memcpy(buffer + SPX_N, auth_path, SPX_N); - } - auth_path += SPX_N; - } - - /* The last iteration is exceptional; we do not copy an auth_path node. */ - leaf_idx >>= 1; - idx_offset >>= 1; - set_tree_height(addr, tree_height); - set_tree_index(addr, leaf_idx + idx_offset); - thash(root, buffer, 2, ctx, addr); -} - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const spx_ctx * /* ctx */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), - uint32_t tree_addr[8]) { - PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); - PQCLEAN_VLA(unsigned int, heights, tree_height + 1); - unsigned int offset = 0; - uint32_t idx; - uint32_t tree_idx; - - for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { - /* Add the next leaf node to the stack. */ - gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); - offset++; - heights[offset - 1] = 0; - - /* If this is a node we need for the auth path.. */ - if ((leaf_idx ^ 0x1) == idx) { - memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); - } - - /* While the top-most nodes are of equal height.. */ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { - /* Compute index of the new node, in the next layer. */ - tree_idx = (idx >> (heights[offset - 1] + 1)); - - /* Set the address of the node we're creating. */ - set_tree_height(tree_addr, heights[offset - 1] + 1); - set_tree_index(tree_addr, - tree_idx + (idx_offset >> (heights[offset - 1] + 1))); - /* Hash the top-most nodes from the stack together. */ - thash(stack + (offset - 2)*SPX_N, - stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); - offset--; - /* Note that the top-most node is now one layer higher. */ - heights[offset - 1]++; - - /* If this is a node we need for the auth path.. */ - if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_path + heights[offset - 1]*SPX_N, - stack + (offset - 1)*SPX_N, SPX_N); - } - } - } - memcpy(root, stack, SPX_N); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/utils.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/utils.h deleted file mode 100644 index 64f5d5a53a..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/utils.h +++ /dev/null @@ -1,58 +0,0 @@ -#ifndef SPX_UTILS_H -#define SPX_UTILS_H - -#include - -#include "compat.h" -#include "context.h" -#include "params.h" - - -/* To support MSVC use alloca() instead of VLAs. See #20. */ - - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) -void ull_to_bytes(unsigned char *out, unsigned int outlen, - unsigned long long in); -#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) -void u32_to_bytes(unsigned char *out, uint32_t in); - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) -unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -#define compute_root SPX_NAMESPACE(compute_root) -void compute_root(unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const spx_ctx *ctx, uint32_t addr[8]); - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -#define treehash SPX_NAMESPACE(treehash) -void treehash(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const spx_ctx *ctx /* ctx */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), - uint32_t tree_addr[8]); - - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/utilsx4.c b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/utilsx4.c deleted file mode 100644 index 1638677194..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/utilsx4.c +++ /dev/null @@ -1,138 +0,0 @@ -#include - -#include "utilsx4.h" - -#include "address.h" -#include "params.h" -#include "thashx4.h" -#include "utils.h" - -/* - * Generate the entire Merkle tree, computing the authentication path for leaf_idx, - * and the resulting root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) - * - * This expects tree_addrx4 to be initialized to 4 parallel addr structures for - * the Merkle tree nodes - * - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - * - * This works by using the standard Merkle tree building algorithm, except - * that each 'node' tracked is actually 4 consecutive nodes in the real tree. - * When we combine two logical nodes ABCD and WXYZ, we perform the H - * operation on adjacent real nodes, forming the parent logical node - * (AB)(CD)(WX)(YZ) - * - * When we get to the top two levels of the real tree (where there is only - * one logical node), we continue this operation two more times; the right - * most real node will by the actual root (and the other 3 nodes will be - * garbage). We follow the same thashx4 logic so that the 'extract - * authentication path components' part of the loop is still executed (and - * to simplify the code somewhat) - * - * This currently assumes tree_height >= 2; I suspect that doing an adjusting - * idx, addr_idx on the gen_leafx4 call if tree_height < 2 would fix it; since - * we don't actually use such short trees, I haven't bothered - */ -void treehashx4(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, - uint32_t tree_height, - void (*gen_leafx4)( - unsigned char * /* Where to write the leaves */, - const spx_ctx *, - uint32_t idx, void *info), - uint32_t tree_addrx4[4 * 8], - void *info) { - /* This is where we keep the intermediate nodes */ - PQCLEAN_VLA(unsigned char, stackx4, tree_height * 4 * SPX_N); - uint32_t left_adj = 0, prev_left_adj = 0; /* When we're doing the top 3 */ - /* levels, the left-most part of the tree isn't at the beginning */ - /* of current[]. These give the offset of the actual start */ - - uint32_t idx; - uint32_t max_idx = (1U << (tree_height - 2)) - 1; - for (idx = 0;; idx++) { - unsigned char current[4 * SPX_N]; /* Current logical node */ - gen_leafx4( current, ctx, 4 * idx + idx_offset, - info ); - - /* Now combine the freshly generated right node with previously */ - /* generated left ones */ - uint32_t internal_idx_offset = idx_offset; - uint32_t internal_idx = idx; - uint32_t internal_leaf = leaf_idx; - uint32_t h; /* The height we are in the Merkle tree */ - for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { - - /* Special processing if we're at the top of the tree */ - if (h >= tree_height - 2) { - if (h == tree_height) { - /* We hit the root; return it */ - memcpy( root, ¤t[3 * SPX_N], SPX_N ); - return; - } - /* The tree indexing logic is a bit off in this case */ - /* Adjust it so that the left-most node of the part of */ - /* the tree that we're processing has index 0 */ - prev_left_adj = left_adj; - left_adj = 4U - (1 << (tree_height - h - 1)); - } - - /* Check if we hit the top of the tree */ - if (h == tree_height) { - /* We hit the root; return it */ - memcpy( root, ¤t[3 * SPX_N], SPX_N ); - return; - } - - /* - * Check if one of the nodes we have is a part of the - * authentication path; if it is, write it out - */ - if ((((internal_idx << 2) ^ internal_leaf) & ~0x3U) == 0) { - memcpy( &auth_path[ h * SPX_N ], - ¤t[(((internal_leaf & 3) ^ 1) + prev_left_adj) * SPX_N], - SPX_N ); - } - - /* - * Check if we're at a left child; if so, stop going up the stack - * Exception: if we've reached the end of the tree, keep on going - * (so we combine the last 4 nodes into the one root node in two - * more iterations) - */ - if ((internal_idx & 1) == 0 && idx < max_idx) { - break; - } - - /* Ok, we're at a right node (or doing the top 3 levels) */ - /* Now combine the left and right logical nodes together */ - - /* Set the address of the node we're creating. */ - unsigned int j; - internal_idx_offset >>= 1; - for (j = 0; j < 4; j++) { - set_tree_height(tree_addrx4 + j * 8, h + 1); - set_tree_index(tree_addrx4 + j * 8, - (4 / 2) * (internal_idx & ~1U) + j - left_adj + internal_idx_offset ); - } - unsigned char *left = &stackx4[h * 4 * SPX_N]; - thashx4( ¤t[0 * SPX_N], - ¤t[1 * SPX_N], - ¤t[2 * SPX_N], - ¤t[3 * SPX_N], - &left [0 * SPX_N], - &left [2 * SPX_N], - ¤t[0 * SPX_N], - ¤t[2 * SPX_N], - 2, ctx, tree_addrx4); - } - - /* We've hit a left child; save the current for when we get the */ - /* corresponding right right */ - memcpy( &stackx4[h * 4 * SPX_N], current, 4 * SPX_N); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/utilsx4.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/utilsx4.h deleted file mode 100644 index facb874b18..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/utilsx4.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef SPX_UTILSX4_H -#define SPX_UTILSX4_H - -#include - -#include "context.h" -#include "params.h" - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - * - * This implementation uses AVX to compute internal nodes 4 at a time (in - * parallel) - */ -#define treehashx4 SPX_NAMESPACE(treehashx4) -void treehashx4(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leafx4)( - unsigned char * /* Where to write the leaves */, - const spx_ctx * /* ctx */, - uint32_t addr_idx, void *info), - uint32_t tree_addrx4[4 * 8], void *info); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/wots.c b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/wots.c deleted file mode 100644 index 4d5041ce05..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/wots.c +++ /dev/null @@ -1,269 +0,0 @@ -#include -#include - -#include "wots.h" - -#include "address.h" -#include "hash.h" -#include "hashx4.h" -#include "params.h" -#include "thash.h" -#include "thashx4.h" -#include "utils.h" -#include "utilsx4.h" -#include "wotsx4.h" - -// TODO clarify address expectations, and make them more uniform. -// TODO i.e. do we expect types to be set already? -// TODO and do we expect modifications or copies? - -/** - * Computes up the chains - */ -static void gen_chains( - unsigned char *out, - const unsigned char *in, - unsigned int start[SPX_WOTS_LEN], - const unsigned int steps[SPX_WOTS_LEN], - const spx_ctx *ctx, - uint32_t addr[8]) { - uint32_t i, j, k, idx, watching; - int done; - unsigned char empty[SPX_N]; - unsigned char *bufs[4]; - uint32_t addrs[8 * 4]; - - int l; - uint16_t counts[SPX_WOTS_W] = { 0 }; - uint16_t idxs[SPX_WOTS_LEN]; - uint16_t total, newTotal; - - /* set addrs = {addr, addr, addr, addr} */ - for (j = 0; j < 4; j++) { - memcpy(addrs + j * 8, addr, sizeof(uint32_t) * 8); - } - - /* Initialize out with the value at position 'start'. */ - memcpy(out, in, SPX_WOTS_LEN * SPX_N); - - /* Sort the chains in reverse order by steps using counting sort. */ - for (i = 0; i < SPX_WOTS_LEN; i++) { - counts[steps[i]]++; - } - total = 0; - for (l = SPX_WOTS_W - 1; l >= 0; l--) { - newTotal = counts[l] + total; - counts[l] = total; - total = newTotal; - } - for (i = 0; i < SPX_WOTS_LEN; i++) { - idxs[counts[steps[i]]] = (uint16_t)i; - counts[steps[i]]++; - } - - /* We got our work cut out for us: do it! */ - for (i = 0; i < SPX_WOTS_LEN; i += 4) { - for (j = 0; j < 4 && i + j < SPX_WOTS_LEN; j++) { - idx = idxs[i + j]; - set_chain_addr(addrs + j * 8, idx); - bufs[j] = out + SPX_N * idx; - } - - /* As the chains are sorted in reverse order, we know that the first - * chain is the longest and the last one is the shortest. We keep - * an eye on whether the last chain is done and then on the one before, - * et cetera. */ - watching = 3; - done = 0; - while (i + watching >= SPX_WOTS_LEN) { - bufs[watching] = &empty[0]; - watching--; - } - - for (k = 0;; k++) { - while (k == steps[idxs[i + watching]]) { - bufs[watching] = &empty[0]; - if (watching == 0) { - done = 1; - break; - } - watching--; - } - if (done) { - break; - } - for (j = 0; j < watching + 1; j++) { - set_hash_addr(addrs + j * 8, k + start[idxs[i + j]]); - } - - thashx4(bufs[0], bufs[1], bufs[2], bufs[3], - bufs[0], bufs[1], bufs[2], bufs[3], 1, ctx, addrs); - } - } -} - -/** - * base_w algorithm as described in draft. - * Interprets an array of bytes as integers in base w. - * This only works when log_w is a divisor of 8. - */ -static void base_w(unsigned int *output, const int out_len, - const unsigned char *input) { - int in = 0; - int out = 0; - unsigned char total = 0; - int bits = 0; - int consumed; - - for (consumed = 0; consumed < out_len; consumed++) { - if (bits == 0) { - total = input[in]; - in++; - bits += 8; - } - bits -= SPX_WOTS_LOGW; - output[out] = (total >> bits) & (SPX_WOTS_W - 1); - out++; - } -} - -/* Computes the WOTS+ checksum over a message (in base_w). */ -static void wots_checksum(unsigned int *csum_base_w, - const unsigned int *msg_base_w) { - unsigned int csum = 0; - unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; - unsigned int i; - - /* Compute checksum. */ - for (i = 0; i < SPX_WOTS_LEN1; i++) { - csum += SPX_WOTS_W - 1 - msg_base_w[i]; - } - - /* Convert checksum to base_w. */ - /* Make sure expected empty zero bits are the least significant bits. */ - csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); - ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); - base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); -} - -/* Takes a message and derives the matching chain lengths. */ -void chain_lengths(unsigned int *lengths, const unsigned char *msg) { - base_w(lengths, SPX_WOTS_LEN1, msg); - wots_checksum(lengths + SPX_WOTS_LEN1, lengths); -} - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const spx_ctx *ctx, uint32_t addr[8]) { - unsigned int steps[SPX_WOTS_LEN]; - unsigned int start[SPX_WOTS_LEN]; - uint32_t i; - - chain_lengths(start, msg); - - for (i = 0; i < SPX_WOTS_LEN; i++) { - steps[i] = SPX_WOTS_W - 1 - start[i]; - } - - gen_chains(pk, sig, start, steps, ctx, addr); -} - -/* - * This generates 4 sequential WOTS public keys - * It also generates the WOTS signature if leaf_info indicates - * that we're signing with one of these WOTS keys - */ -void wots_gen_leafx4(unsigned char *dest, - const spx_ctx *ctx, - uint32_t leaf_idx, void *v_info) { - struct leaf_info_x4 *info = v_info; - uint32_t *leaf_addr = info->leaf_addr; - uint32_t *pk_addr = info->pk_addr; - unsigned int i, j, k; - unsigned char pk_buffer[ 4 * SPX_WOTS_BYTES ]; - unsigned wots_offset = SPX_WOTS_BYTES; - unsigned char *buffer; - uint32_t wots_k_mask; - unsigned wots_sign_index; - - if (((leaf_idx ^ info->wots_sign_leaf) & ~3U) == 0) { - /* We're traversing the leaf that's signing; generate the WOTS */ - /* signature */ - wots_k_mask = 0; - wots_sign_index = info->wots_sign_leaf & 3; /* Which of of the 4 */ - /* 4 slots do the signatures come from */ - } else { - /* Nope, we're just generating pk's; turn off the signature logic */ - wots_k_mask = (uint32_t)~0; - wots_sign_index = 0; - } - - for (j = 0; j < 4; j++) { - set_keypair_addr( leaf_addr + j * 8, leaf_idx + j ); - set_keypair_addr( pk_addr + j * 8, leaf_idx + j ); - } - - for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { - uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k to */ - /* the step if we're generating a signature, ~0 if we're not */ - - /* Start with the secret seed */ - for (j = 0; j < 4; j++) { - set_chain_addr(leaf_addr + j * 8, i); - set_hash_addr(leaf_addr + j * 8, 0); - set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTSPRF); - } - prf_addrx4(buffer + 0 * wots_offset, - buffer + 1 * wots_offset, - buffer + 2 * wots_offset, - buffer + 3 * wots_offset, - ctx, leaf_addr); - - for (j = 0; j < 4; j++) { - set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTS); - } - - /* Iterate down the WOTS chain */ - for (k = 0;; k++) { - /* Check if one of the values we have needs to be saved as a */ - /* part of the WOTS signature */ - if (k == wots_k) { - memcpy( info->wots_sig + i * SPX_N, - buffer + wots_sign_index * wots_offset, SPX_N ); - } - - /* Check if we hit the top of the chain */ - if (k == SPX_WOTS_W - 1) { - break; - } - - /* Iterate one step on all 4 chains */ - for (j = 0; j < 4; j++) { - set_hash_addr(leaf_addr + j * 8, k); - } - thashx4(buffer + 0 * wots_offset, - buffer + 1 * wots_offset, - buffer + 2 * wots_offset, - buffer + 3 * wots_offset, - buffer + 0 * wots_offset, - buffer + 1 * wots_offset, - buffer + 2 * wots_offset, - buffer + 3 * wots_offset, 1, ctx, leaf_addr); - } - } - - /* Do the final thash to generate the public keys */ - thashx4(dest + 0 * SPX_N, - dest + 1 * SPX_N, - dest + 2 * SPX_N, - dest + 3 * SPX_N, - pk_buffer + 0 * wots_offset, - pk_buffer + 1 * wots_offset, - pk_buffer + 2 * wots_offset, - pk_buffer + 3 * wots_offset, SPX_WOTS_LEN, ctx, pk_addr); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/wots.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/wots.h deleted file mode 100644 index 4e7692eeef..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/wots.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef SPX_WOTS_H -#define SPX_WOTS_H - -#include - -#include "context.h" -#include "params.h" - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) -void wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const spx_ctx *ctx, uint32_t addr[8]); - -/* - * Compute the chain lengths needed for a given message hash - */ -#define chain_lengths SPX_NAMESPACE(chain_lengths) -void chain_lengths(unsigned int *lengths, const unsigned char *msg); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/wotsx4.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/wotsx4.h deleted file mode 100644 index cd634f1743..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_aesni/wotsx4.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef WOTSX4_H_ -#define WOTSX4_H_ - -#include - -#include "params.h" - -/* - * This is here to provide an interface to the internal wots_gen_leafx4 - * routine. While this routine is not referenced in the package outside of - * wots.c, it is called from the stand-alone benchmark code to characterize - * the performance - */ -struct leaf_info_x4 { - unsigned char *wots_sig; - uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ - uint32_t *wots_steps; - uint32_t leaf_addr[4 * 8]; - uint32_t pk_addr[4 * 8]; -}; - -/* Macro to set the leaf_info to something 'benign', that is, it would */ -/* run with the same time as it does during the real signing process */ -/* Used only by the benchmark code */ -#define INITIALIZE_LEAF_INFO_X4(info, addr, step_buffer) { \ - (info).wots_sig = 0; \ - (info).wots_sign_leaf = ~0; \ - (info).wots_steps = step_buffer; \ - int i; \ - for (i=0; i<4; i++) { \ - memcpy( &(info).leaf_addr[8*i], addr, 32 ); \ - memcpy( &(info).pk_addr[8*i], addr, 32 ); \ - } \ - } - -#define wots_gen_leafx4 SPX_NAMESPACE(wots_gen_leafx4) -void wots_gen_leafx4(unsigned char *dest, - const spx_ctx *ctx, - uint32_t leaf_idx, void *v_info); - -#endif /* WOTSX4_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/LICENSE b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/LICENSE deleted file mode 100644 index 670154e353..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/LICENSE +++ /dev/null @@ -1,116 +0,0 @@ -CC0 1.0 Universal - -Statement of Purpose - -The laws of most jurisdictions throughout the world automatically confer -exclusive Copyright and Related Rights (defined below) upon the creator and -subsequent owner(s) (each and all, an "owner") of an original work of -authorship and/or a database (each, a "Work"). - -Certain owners wish to permanently relinquish those rights to a Work for the -purpose of contributing to a commons of creative, cultural and scientific -works ("Commons") that the public can reliably and without fear of later -claims of infringement build upon, modify, incorporate in other works, reuse -and redistribute as freely as possible in any form whatsoever and for any -purposes, including without limitation commercial purposes. These owners may -contribute to the Commons to promote the ideal of a free culture and the -further production of creative, cultural and scientific works, or to gain -reputation or greater distribution for their Work in part through the use and -efforts of others. - -For these and/or other purposes and motivations, and without any expectation -of additional consideration or compensation, the person associating CC0 with a -Work (the "Affirmer"), to the extent that he or she is an owner of Copyright -and Related Rights in the Work, voluntarily elects to apply CC0 to the Work -and publicly distribute the Work under its terms, with knowledge of his or her -Copyright and Related Rights in the Work and the meaning and intended legal -effect of CC0 on those rights. - -1. Copyright and Related Rights. A Work made available under CC0 may be -protected by copyright and related or neighboring rights ("Copyright and -Related Rights"). Copyright and Related Rights include, but are not limited -to, the following: - - i. the right to reproduce, adapt, distribute, perform, display, communicate, - and translate a Work; - - ii. moral rights retained by the original author(s) and/or performer(s); - - iii. publicity and privacy rights pertaining to a person's image or likeness - depicted in a Work; - - iv. rights protecting against unfair competition in regards to a Work, - subject to the limitations in paragraph 4(a), below; - - v. rights protecting the extraction, dissemination, use and reuse of data in - a Work; - - vi. database rights (such as those arising under Directive 96/9/EC of the - European Parliament and of the Council of 11 March 1996 on the legal - protection of databases, and under any national implementation thereof, - including any amended or successor version of such directive); and - - vii. other similar, equivalent or corresponding rights throughout the world - based on applicable law or treaty, and any national implementations thereof. - -2. Waiver. To the greatest extent permitted by, but not in contravention of, -applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and -unconditionally waives, abandons, and surrenders all of Affirmer's Copyright -and Related Rights and associated claims and causes of action, whether now -known or unknown (including existing as well as future claims and causes of -action), in the Work (i) in all territories worldwide, (ii) for the maximum -duration provided by applicable law or treaty (including future time -extensions), (iii) in any current or future medium and for any number of -copies, and (iv) for any purpose whatsoever, including without limitation -commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes -the Waiver for the benefit of each member of the public at large and to the -detriment of Affirmer's heirs and successors, fully intending that such Waiver -shall not be subject to revocation, rescission, cancellation, termination, or -any other legal or equitable action to disrupt the quiet enjoyment of the Work -by the public as contemplated by Affirmer's express Statement of Purpose. - -3. Public License Fallback. Should any part of the Waiver for any reason be -judged legally invalid or ineffective under applicable law, then the Waiver -shall be preserved to the maximum extent permitted taking into account -Affirmer's express Statement of Purpose. In addition, to the extent the Waiver -is so judged Affirmer hereby grants to each affected person a royalty-free, -non transferable, non sublicensable, non exclusive, irrevocable and -unconditional license to exercise Affirmer's Copyright and Related Rights in -the Work (i) in all territories worldwide, (ii) for the maximum duration -provided by applicable law or treaty (including future time extensions), (iii) -in any current or future medium and for any number of copies, and (iv) for any -purpose whatsoever, including without limitation commercial, advertising or -promotional purposes (the "License"). The License shall be deemed effective as -of the date CC0 was applied by Affirmer to the Work. Should any part of the -License for any reason be judged legally invalid or ineffective under -applicable law, such partial invalidity or ineffectiveness shall not -invalidate the remainder of the License, and in such case Affirmer hereby -affirms that he or she will not (i) exercise any of his or her remaining -Copyright and Related Rights in the Work or (ii) assert any associated claims -and causes of action with respect to the Work, in either case contrary to -Affirmer's express Statement of Purpose. - -4. Limitations and Disclaimers. - - a. No trademark or patent rights held by Affirmer are waived, abandoned, - surrendered, licensed or otherwise affected by this document. - - b. Affirmer offers the Work as-is and makes no representations or warranties - of any kind concerning the Work, express, implied, statutory or otherwise, - including without limitation warranties of title, merchantability, fitness - for a particular purpose, non infringement, or the absence of latent or - other defects, accuracy, or the present or absence of errors, whether or not - discoverable, all to the greatest extent permissible under applicable law. - - c. Affirmer disclaims responsibility for clearing rights of other persons - that may apply to the Work or any use thereof, including without limitation - any person's Copyright and Related Rights in the Work. Further, Affirmer - disclaims responsibility for obtaining any necessary consents, permissions - or other rights required for any use of the Work. - - d. Affirmer understands and acknowledges that Creative Commons is not a - party to this document and has no duty or obligation with respect to this - CC0 or use of the Work. - -For more information, please see - diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/address.c b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/address.c deleted file mode 100644 index b956e9cb29..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/address.c +++ /dev/null @@ -1,91 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "utils.h" - -/* - * Specify which level of Merkle tree (the "layer") we're working on - */ -void set_layer_addr(uint32_t addr[8], uint32_t layer) { - ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; -} - -/* - * Specify which Merkle tree within the level (the "tree address") we're working on - */ -void set_tree_addr(uint32_t addr[8], uint64_t tree) { - ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); -} - -/* - * Specify the reason we'll use this address structure for, that is, what - * hash will we compute with it. This is used so that unrelated types of - * hashes don't accidentally get the same address structure. The type will be - * one of the SPX_ADDR_TYPE constants - */ -void set_type(uint32_t addr[8], uint32_t type) { - ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; -} - -/* - * Copy the layer and tree fields of the address structure. This is used - * when we're doing multiple types of hashes within the same Merkle tree - */ -void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { - memcpy( out, in, SPX_OFFSET_TREE + 8 ); -} - -/* These functions are used for OTS addresses. */ - -/* - * Specify which Merkle leaf we're working on; that is, which OTS keypair - * we're talking about. - */ -void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { - ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; -} - -/* - * Copy the layer, tree and keypair fields of the address structure. This is - * used when we're doing multiple things within the same OTS keypair - */ -void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { - memcpy( out, in, SPX_OFFSET_TREE + 8 ); - ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; -} - -/* - * Specify which Merkle chain within the OTS we're working with - * (the chain address) - */ -void set_chain_addr(uint32_t addr[8], uint32_t chain) { - ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; -} - -/* - * Specify where in the Merkle chain we are -* (the hash address) - */ -void set_hash_addr(uint32_t addr[8], uint32_t hash) { - ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; -} - -/* These functions are used for all hash tree addresses (including FORS). */ - -/* - * Specify the height of the node in the Merkle/FORS tree we are in - * (the tree height) - */ -void set_tree_height(uint32_t addr[8], uint32_t tree_height) { - ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; -} - -/* - * Specify the distance from the left edge of the node in the Merkle/FORS tree - * (the tree index) - */ -void set_tree_index(uint32_t addr[8], uint32_t tree_index) { - u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/address.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/address.h deleted file mode 100644 index 24a84eb40c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/address.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef SPX_ADDRESS_H -#define SPX_ADDRESS_H - -#include - -#include "params.h" - -/* The hash types that are passed to set_type */ -#define SPX_ADDR_TYPE_WOTS 0 -#define SPX_ADDR_TYPE_WOTSPK 1 -#define SPX_ADDR_TYPE_HASHTREE 2 -#define SPX_ADDR_TYPE_FORSTREE 3 -#define SPX_ADDR_TYPE_FORSPK 4 -#define SPX_ADDR_TYPE_WOTSPRF 5 -#define SPX_ADDR_TYPE_FORSPRF 6 - -#define set_layer_addr SPX_NAMESPACE(set_layer_addr) -void set_layer_addr(uint32_t addr[8], uint32_t layer); - -#define set_tree_addr SPX_NAMESPACE(set_tree_addr) -void set_tree_addr(uint32_t addr[8], uint64_t tree); - -#define set_type SPX_NAMESPACE(set_type) -void set_type(uint32_t addr[8], uint32_t type); - -/* Copies the layer and tree part of one address into the other */ -#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) -void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for WOTS and FORS addresses. */ - -#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) -void set_keypair_addr(uint32_t addr[8], uint32_t keypair); - -#define set_chain_addr SPX_NAMESPACE(set_chain_addr) -void set_chain_addr(uint32_t addr[8], uint32_t chain); - -#define set_hash_addr SPX_NAMESPACE(set_hash_addr) -void set_hash_addr(uint32_t addr[8], uint32_t hash); - -#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) -void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for all hash tree addresses (including FORS). */ - -#define set_tree_height SPX_NAMESPACE(set_tree_height) -void set_tree_height(uint32_t addr[8], uint32_t tree_height); - -#define set_tree_index SPX_NAMESPACE(set_tree_index) -void set_tree_index(uint32_t addr[8], uint32_t tree_index); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/api.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/api.h deleted file mode 100644 index 79754c0f43..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/api.h +++ /dev/null @@ -1,77 +0,0 @@ -#ifndef PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_API_H -#define PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_API_H - -#include -#include - -#define PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_CRYPTO_ALGNAME "SPHINCS+-haraka-256f-robust" - -#define PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_CRYPTO_SECRETKEYBYTES 128 -#define PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_CRYPTO_PUBLICKEYBYTES 64 -#define PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_CRYPTO_BYTES 49856 - -#define PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_CRYPTO_SEEDBYTES 96 - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, - const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk); -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/context.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/context.h deleted file mode 100644 index 600dfb73c7..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/context.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef SPX_CONTEXT_H -#define SPX_CONTEXT_H - -#include -#include - -#include "params.h" - -typedef struct { - uint8_t pub_seed[SPX_N]; - uint8_t sk_seed[SPX_N]; - - - uint64_t tweaked512_rc64[10][8]; - uint32_t tweaked256_rc32[10][8]; -} spx_ctx; - -#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) -void initialize_hash_function(spx_ctx *ctx); - -#define free_hash_function SPX_NAMESPACE(free_hash_function) -void free_hash_function(spx_ctx *ctx); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/context_haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/context_haraka.c deleted file mode 100644 index f1cd7e3664..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/context_haraka.c +++ /dev/null @@ -1,11 +0,0 @@ -#include "context.h" -#include "haraka.h" - -void initialize_hash_function(spx_ctx *ctx) { - tweak_constants(ctx); -} - -// we don't support heap-based haraka right now -void free_hash_function(spx_ctx *ctx) { - (void)ctx; // suppress unused variable warnings -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/fors.c b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/fors.c deleted file mode 100644 index 96ca72e986..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/fors.c +++ /dev/null @@ -1,156 +0,0 @@ -#include -#include -#include - -#include "fors.h" - -#include "address.h" -#include "hash.h" -#include "thash.h" -#include "utils.h" -#include "utilsx1.h" - -static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, - uint32_t fors_leaf_addr[8]) { - prf_addr(sk, ctx, fors_leaf_addr); -} - -static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, - const spx_ctx *ctx, - uint32_t fors_leaf_addr[8]) { - thash(leaf, sk, 1, ctx, fors_leaf_addr); -} - -struct fors_gen_leaf_info { - uint32_t leaf_addrx[8]; -}; - -static void fors_gen_leafx1(unsigned char *leaf, - const spx_ctx *ctx, - uint32_t addr_idx, void *info) { - struct fors_gen_leaf_info *fors_info = info; - uint32_t *fors_leaf_addr = fors_info->leaf_addrx; - - /* Only set the parts that the caller doesn't set */ - set_tree_index(fors_leaf_addr, addr_idx); - set_type(fors_leaf_addr, SPX_ADDR_TYPE_FORSPRF); - fors_gen_sk(leaf, ctx, fors_leaf_addr); - - set_type(fors_leaf_addr, SPX_ADDR_TYPE_FORSTREE); - fors_sk_to_leaf(leaf, leaf, - ctx, fors_leaf_addr); -} - -/** - * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - * Assumes indices has space for SPX_FORS_TREES integers. - */ -static void message_to_indices(uint32_t *indices, const unsigned char *m) { - unsigned int i, j; - unsigned int offset = 0; - - for (i = 0; i < SPX_FORS_TREES; i++) { - indices[i] = 0; - for (j = 0; j < SPX_FORS_HEIGHT; j++) { - indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); - offset++; - } - } -} - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -void fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]) { - uint32_t indices[SPX_FORS_TREES]; - unsigned char roots[SPX_FORS_TREES * SPX_N]; - uint32_t fors_tree_addr[8] = {0}; - struct fors_gen_leaf_info fors_info = {0}; - uint32_t *fors_leaf_addr = fors_info.leaf_addrx; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - copy_keypair_addr(fors_tree_addr, fors_addr); - copy_keypair_addr(fors_leaf_addr, fors_addr); - - copy_keypair_addr(fors_pk_addr, fors_addr); - set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < SPX_FORS_TREES; i++) { - idx_offset = i * (1 << SPX_FORS_HEIGHT); - - set_tree_height(fors_tree_addr, 0); - set_tree_index(fors_tree_addr, indices[i] + idx_offset); - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); - - /* Include the secret key part that produces the selected leaf node. */ - fors_gen_sk(sig, ctx, fors_tree_addr); - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); - sig += SPX_N; - - /* Compute the authentication path for this leaf node. */ - treehashx1(roots + i * SPX_N, sig, ctx, - indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx1, - fors_tree_addr, &fors_info); - - sig += SPX_N * SPX_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); -} - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -void fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]) { - uint32_t indices[SPX_FORS_TREES]; - unsigned char roots[SPX_FORS_TREES * SPX_N]; - unsigned char leaf[SPX_N]; - uint32_t fors_tree_addr[8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - copy_keypair_addr(fors_tree_addr, fors_addr); - copy_keypair_addr(fors_pk_addr, fors_addr); - - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); - set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < SPX_FORS_TREES; i++) { - idx_offset = i * (1 << SPX_FORS_HEIGHT); - - set_tree_height(fors_tree_addr, 0); - set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Derive the leaf from the included secret key part. */ - fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); - sig += SPX_N; - - /* Derive the corresponding root node of this tree. */ - compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, - sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); - sig += SPX_N * SPX_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/fors.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/fors.h deleted file mode 100644 index 509140a178..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/fors.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef SPX_FORS_H -#define SPX_FORS_H - -#include - -#include "context.h" -#include "params.h" - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -#define fors_sign SPX_NAMESPACE(fors_sign) -void fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]); - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) -void fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/haraka.c deleted file mode 100644 index a4944913b5..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/haraka.c +++ /dev/null @@ -1,913 +0,0 @@ -/* - * Constant time implementation of the Haraka hash function. - * - * The bit-sliced implementation of the AES round functions are - * based on the AES implementation in BearSSL written - * by Thomas Pornin - */ - -#include -#include -#include -#include - -#include "haraka.h" -#include "utils.h" - -#define HARAKAS_RATE 32 - -static const uint64_t haraka512_rc64[10][8] = { - {0x24cf0ab9086f628b, 0xbdd6eeecc83b8382, 0xd96fb0306cdad0a7, 0xaace082ac8f95f89, 0x449d8e8870d7041f, 0x49bb2f80b2b3e2f8, 0x0569ae98d93bb258, 0x23dc9691e7d6a4b1}, - {0xd8ba10ede0fe5b6e, 0x7ecf7dbe424c7b8e, 0x6ea9949c6df62a31, 0xbf3f3c97ec9c313e, 0x241d03a196a1861e, 0xead3a51116e5a2ea, 0x77d479fcad9574e3, 0x18657a1af894b7a0}, - {0x10671e1a7f595522, 0xd9a00ff675d28c7b, 0x2f1edf0d2b9ba661, 0xb8ff58b8e3de45f9, 0xee29261da9865c02, 0xd1532aa4b50bdf43, 0x8bf858159b231bb1, 0xdf17439d22d4f599}, - {0xdd4b2f0870b918c0, 0x757a81f3b39b1bb6, 0x7a5c556898952e3f, 0x7dd70a16d915d87a, 0x3ae61971982b8301, 0xc3ab319e030412be, 0x17c0033ac094a8cb, 0x5a0630fc1a8dc4ef}, - {0x17708988c1632f73, 0xf92ddae090b44f4f, 0x11ac0285c43aa314, 0x509059941936b8ba, 0xd03e152fa2ce9b69, 0x3fbcbcb63a32998b, 0x6204696d692254f7, 0x915542ed93ec59b4}, - {0xf4ed94aa8879236e, 0xff6cb41cd38e03c0, 0x069b38602368aeab, 0x669495b820f0ddba, 0xf42013b1b8bf9e3d, 0xcf935efe6439734d, 0xbc1dcf42ca29e3f8, 0x7e6d3ed29f78ad67}, - {0xf3b0f6837ffcddaa, 0x3a76faef934ddf41, 0xcec7ae583a9c8e35, 0xe4dd18c68f0260af, 0x2c0e5df1ad398eaa, 0x478df5236ae22e8c, 0xfb944c46fe865f39, 0xaa48f82f028132ba}, - {0x231b9ae2b76aca77, 0x292a76a712db0b40, 0x5850625dc8134491, 0x73137dd469810fb5, 0x8a12a6a202a474fd, 0xd36fd9daa78bdb80, 0xb34c5e733505706f, 0xbaf1cdca818d9d96}, - {0x2e99781335e8c641, 0xbddfe5cce47d560e, 0xf74e9bf32e5e040c, 0x1d7a709d65996be9, 0x670df36a9cf66cdd, 0xd05ef84a176a2875, 0x0f888e828cb1c44e, 0x1a79e9c9727b052c}, - {0x83497348628d84de, 0x2e9387d51f22a754, 0xb000068da2f852d6, 0x378c9e1190fd6fe5, 0x870027c316de7293, 0xe51a9d4462e047bb, 0x90ecf7f8c6251195, 0x655953bfbed90a9c}, -}; - -static inline uint32_t br_dec32le(const unsigned char *src) { - return (uint32_t)src[0] - | ((uint32_t)src[1] << 8) - | ((uint32_t)src[2] << 16) - | ((uint32_t)src[3] << 24); -} - -static void br_range_dec32le(uint32_t *v, size_t num, const unsigned char *src) { - while (num-- > 0) { - *v ++ = br_dec32le(src); - src += 4; - } -} - -static inline void br_enc32le(unsigned char *dst, uint32_t x) { - dst[0] = (unsigned char)x; - dst[1] = (unsigned char)(x >> 8); - dst[2] = (unsigned char)(x >> 16); - dst[3] = (unsigned char)(x >> 24); -} - - -static void br_range_enc32le(unsigned char *dst, const uint32_t *v, size_t num) { - while (num-- > 0) { - br_enc32le(dst, *v ++); - dst += 4; - } -} - -static void br_aes_ct64_bitslice_Sbox(uint64_t *q) { - /* - * This S-box implementation is a straightforward translation of - * the circuit described by Boyar and Peralta in "A new - * combinational logic minimization technique with applications - * to cryptology" (https://eprint.iacr.org/2009/191.pdf). - * - * Note that variables x* (input) and s* (output) are numbered - * in "reverse" order (x0 is the high bit, x7 is the low bit). - */ - - uint64_t x0, x1, x2, x3, x4, x5, x6, x7; - uint64_t y1, y2, y3, y4, y5, y6, y7, y8, y9; - uint64_t y10, y11, y12, y13, y14, y15, y16, y17, y18, y19; - uint64_t y20, y21; - uint64_t z0, z1, z2, z3, z4, z5, z6, z7, z8, z9; - uint64_t z10, z11, z12, z13, z14, z15, z16, z17; - uint64_t t0, t1, t2, t3, t4, t5, t6, t7, t8, t9; - uint64_t t10, t11, t12, t13, t14, t15, t16, t17, t18, t19; - uint64_t t20, t21, t22, t23, t24, t25, t26, t27, t28, t29; - uint64_t t30, t31, t32, t33, t34, t35, t36, t37, t38, t39; - uint64_t t40, t41, t42, t43, t44, t45, t46, t47, t48, t49; - uint64_t t50, t51, t52, t53, t54, t55, t56, t57, t58, t59; - uint64_t t60, t61, t62, t63, t64, t65, t66, t67; - uint64_t s0, s1, s2, s3, s4, s5, s6, s7; - - x0 = q[7]; - x1 = q[6]; - x2 = q[5]; - x3 = q[4]; - x4 = q[3]; - x5 = q[2]; - x6 = q[1]; - x7 = q[0]; - - /* - * Top linear transformation. - */ - y14 = x3 ^ x5; - y13 = x0 ^ x6; - y9 = x0 ^ x3; - y8 = x0 ^ x5; - t0 = x1 ^ x2; - y1 = t0 ^ x7; - y4 = y1 ^ x3; - y12 = y13 ^ y14; - y2 = y1 ^ x0; - y5 = y1 ^ x6; - y3 = y5 ^ y8; - t1 = x4 ^ y12; - y15 = t1 ^ x5; - y20 = t1 ^ x1; - y6 = y15 ^ x7; - y10 = y15 ^ t0; - y11 = y20 ^ y9; - y7 = x7 ^ y11; - y17 = y10 ^ y11; - y19 = y10 ^ y8; - y16 = t0 ^ y11; - y21 = y13 ^ y16; - y18 = x0 ^ y16; - - /* - * Non-linear section. - */ - t2 = y12 & y15; - t3 = y3 & y6; - t4 = t3 ^ t2; - t5 = y4 & x7; - t6 = t5 ^ t2; - t7 = y13 & y16; - t8 = y5 & y1; - t9 = t8 ^ t7; - t10 = y2 & y7; - t11 = t10 ^ t7; - t12 = y9 & y11; - t13 = y14 & y17; - t14 = t13 ^ t12; - t15 = y8 & y10; - t16 = t15 ^ t12; - t17 = t4 ^ t14; - t18 = t6 ^ t16; - t19 = t9 ^ t14; - t20 = t11 ^ t16; - t21 = t17 ^ y20; - t22 = t18 ^ y19; - t23 = t19 ^ y21; - t24 = t20 ^ y18; - - t25 = t21 ^ t22; - t26 = t21 & t23; - t27 = t24 ^ t26; - t28 = t25 & t27; - t29 = t28 ^ t22; - t30 = t23 ^ t24; - t31 = t22 ^ t26; - t32 = t31 & t30; - t33 = t32 ^ t24; - t34 = t23 ^ t33; - t35 = t27 ^ t33; - t36 = t24 & t35; - t37 = t36 ^ t34; - t38 = t27 ^ t36; - t39 = t29 & t38; - t40 = t25 ^ t39; - - t41 = t40 ^ t37; - t42 = t29 ^ t33; - t43 = t29 ^ t40; - t44 = t33 ^ t37; - t45 = t42 ^ t41; - z0 = t44 & y15; - z1 = t37 & y6; - z2 = t33 & x7; - z3 = t43 & y16; - z4 = t40 & y1; - z5 = t29 & y7; - z6 = t42 & y11; - z7 = t45 & y17; - z8 = t41 & y10; - z9 = t44 & y12; - z10 = t37 & y3; - z11 = t33 & y4; - z12 = t43 & y13; - z13 = t40 & y5; - z14 = t29 & y2; - z15 = t42 & y9; - z16 = t45 & y14; - z17 = t41 & y8; - - /* - * Bottom linear transformation. - */ - t46 = z15 ^ z16; - t47 = z10 ^ z11; - t48 = z5 ^ z13; - t49 = z9 ^ z10; - t50 = z2 ^ z12; - t51 = z2 ^ z5; - t52 = z7 ^ z8; - t53 = z0 ^ z3; - t54 = z6 ^ z7; - t55 = z16 ^ z17; - t56 = z12 ^ t48; - t57 = t50 ^ t53; - t58 = z4 ^ t46; - t59 = z3 ^ t54; - t60 = t46 ^ t57; - t61 = z14 ^ t57; - t62 = t52 ^ t58; - t63 = t49 ^ t58; - t64 = z4 ^ t59; - t65 = t61 ^ t62; - t66 = z1 ^ t63; - s0 = t59 ^ t63; - s6 = t56 ^ ~t62; - s7 = t48 ^ ~t60; - t67 = t64 ^ t65; - s3 = t53 ^ t66; - s4 = t51 ^ t66; - s5 = t47 ^ t65; - s1 = t64 ^ ~s3; - s2 = t55 ^ ~t67; - - q[7] = s0; - q[6] = s1; - q[5] = s2; - q[4] = s3; - q[3] = s4; - q[2] = s5; - q[1] = s6; - q[0] = s7; -} - -static void br_aes_ct_bitslice_Sbox(uint32_t *q) { - /* - * This S-box implementation is a straightforward translation of - * the circuit described by Boyar and Peralta in "A new - * combinational logic minimization technique with applications - * to cryptology" (https://eprint.iacr.org/2009/191.pdf). - * - * Note that variables x* (input) and s* (output) are numbered - * in "reverse" order (x0 is the high bit, x7 is the low bit). - */ - - uint32_t x0, x1, x2, x3, x4, x5, x6, x7; - uint32_t y1, y2, y3, y4, y5, y6, y7, y8, y9; - uint32_t y10, y11, y12, y13, y14, y15, y16, y17, y18, y19; - uint32_t y20, y21; - uint32_t z0, z1, z2, z3, z4, z5, z6, z7, z8, z9; - uint32_t z10, z11, z12, z13, z14, z15, z16, z17; - uint32_t t0, t1, t2, t3, t4, t5, t6, t7, t8, t9; - uint32_t t10, t11, t12, t13, t14, t15, t16, t17, t18, t19; - uint32_t t20, t21, t22, t23, t24, t25, t26, t27, t28, t29; - uint32_t t30, t31, t32, t33, t34, t35, t36, t37, t38, t39; - uint32_t t40, t41, t42, t43, t44, t45, t46, t47, t48, t49; - uint32_t t50, t51, t52, t53, t54, t55, t56, t57, t58, t59; - uint32_t t60, t61, t62, t63, t64, t65, t66, t67; - uint32_t s0, s1, s2, s3, s4, s5, s6, s7; - - x0 = q[7]; - x1 = q[6]; - x2 = q[5]; - x3 = q[4]; - x4 = q[3]; - x5 = q[2]; - x6 = q[1]; - x7 = q[0]; - - /* - * Top linear transformation. - */ - y14 = x3 ^ x5; - y13 = x0 ^ x6; - y9 = x0 ^ x3; - y8 = x0 ^ x5; - t0 = x1 ^ x2; - y1 = t0 ^ x7; - y4 = y1 ^ x3; - y12 = y13 ^ y14; - y2 = y1 ^ x0; - y5 = y1 ^ x6; - y3 = y5 ^ y8; - t1 = x4 ^ y12; - y15 = t1 ^ x5; - y20 = t1 ^ x1; - y6 = y15 ^ x7; - y10 = y15 ^ t0; - y11 = y20 ^ y9; - y7 = x7 ^ y11; - y17 = y10 ^ y11; - y19 = y10 ^ y8; - y16 = t0 ^ y11; - y21 = y13 ^ y16; - y18 = x0 ^ y16; - - /* - * Non-linear section. - */ - t2 = y12 & y15; - t3 = y3 & y6; - t4 = t3 ^ t2; - t5 = y4 & x7; - t6 = t5 ^ t2; - t7 = y13 & y16; - t8 = y5 & y1; - t9 = t8 ^ t7; - t10 = y2 & y7; - t11 = t10 ^ t7; - t12 = y9 & y11; - t13 = y14 & y17; - t14 = t13 ^ t12; - t15 = y8 & y10; - t16 = t15 ^ t12; - t17 = t4 ^ t14; - t18 = t6 ^ t16; - t19 = t9 ^ t14; - t20 = t11 ^ t16; - t21 = t17 ^ y20; - t22 = t18 ^ y19; - t23 = t19 ^ y21; - t24 = t20 ^ y18; - - t25 = t21 ^ t22; - t26 = t21 & t23; - t27 = t24 ^ t26; - t28 = t25 & t27; - t29 = t28 ^ t22; - t30 = t23 ^ t24; - t31 = t22 ^ t26; - t32 = t31 & t30; - t33 = t32 ^ t24; - t34 = t23 ^ t33; - t35 = t27 ^ t33; - t36 = t24 & t35; - t37 = t36 ^ t34; - t38 = t27 ^ t36; - t39 = t29 & t38; - t40 = t25 ^ t39; - - t41 = t40 ^ t37; - t42 = t29 ^ t33; - t43 = t29 ^ t40; - t44 = t33 ^ t37; - t45 = t42 ^ t41; - z0 = t44 & y15; - z1 = t37 & y6; - z2 = t33 & x7; - z3 = t43 & y16; - z4 = t40 & y1; - z5 = t29 & y7; - z6 = t42 & y11; - z7 = t45 & y17; - z8 = t41 & y10; - z9 = t44 & y12; - z10 = t37 & y3; - z11 = t33 & y4; - z12 = t43 & y13; - z13 = t40 & y5; - z14 = t29 & y2; - z15 = t42 & y9; - z16 = t45 & y14; - z17 = t41 & y8; - - /* - * Bottom linear transformation. - */ - t46 = z15 ^ z16; - t47 = z10 ^ z11; - t48 = z5 ^ z13; - t49 = z9 ^ z10; - t50 = z2 ^ z12; - t51 = z2 ^ z5; - t52 = z7 ^ z8; - t53 = z0 ^ z3; - t54 = z6 ^ z7; - t55 = z16 ^ z17; - t56 = z12 ^ t48; - t57 = t50 ^ t53; - t58 = z4 ^ t46; - t59 = z3 ^ t54; - t60 = t46 ^ t57; - t61 = z14 ^ t57; - t62 = t52 ^ t58; - t63 = t49 ^ t58; - t64 = z4 ^ t59; - t65 = t61 ^ t62; - t66 = z1 ^ t63; - s0 = t59 ^ t63; - s6 = t56 ^ ~t62; - s7 = t48 ^ ~t60; - t67 = t64 ^ t65; - s3 = t53 ^ t66; - s4 = t51 ^ t66; - s5 = t47 ^ t65; - s1 = t64 ^ ~s3; - s2 = t55 ^ ~t67; - - q[7] = s0; - q[6] = s1; - q[5] = s2; - q[4] = s3; - q[3] = s4; - q[2] = s5; - q[1] = s6; - q[0] = s7; -} - -static void br_aes_ct_ortho(uint32_t *q) { -#define SWAPN_32(cl, ch, s, x, y) do { \ - uint32_t a, b; \ - a = (x); \ - b = (y); \ - (x) = (a & (uint32_t)(cl)) | ((b & (uint32_t)(cl)) << (s)); \ - (y) = ((a & (uint32_t)(ch)) >> (s)) | (b & (uint32_t)(ch)); \ - } while (0) - -#define SWAP2_32(x, y) SWAPN_32(0x55555555, 0xAAAAAAAA, 1, x, y) -#define SWAP4_32(x, y) SWAPN_32(0x33333333, 0xCCCCCCCC, 2, x, y) -#define SWAP8_32(x, y) SWAPN_32(0x0F0F0F0F, 0xF0F0F0F0, 4, x, y) - - SWAP2_32(q[0], q[1]); - SWAP2_32(q[2], q[3]); - SWAP2_32(q[4], q[5]); - SWAP2_32(q[6], q[7]); - - SWAP4_32(q[0], q[2]); - SWAP4_32(q[1], q[3]); - SWAP4_32(q[4], q[6]); - SWAP4_32(q[5], q[7]); - - SWAP8_32(q[0], q[4]); - SWAP8_32(q[1], q[5]); - SWAP8_32(q[2], q[6]); - SWAP8_32(q[3], q[7]); -} - -static inline void add_round_key32(uint32_t *q, const uint32_t *sk) { - q[0] ^= sk[0]; - q[1] ^= sk[1]; - q[2] ^= sk[2]; - q[3] ^= sk[3]; - q[4] ^= sk[4]; - q[5] ^= sk[5]; - q[6] ^= sk[6]; - q[7] ^= sk[7]; -} - -static inline void shift_rows32(uint32_t *q) { - int i; - - for (i = 0; i < 8; i++) { - uint32_t x; - - x = q[i]; - q[i] = (x & 0x000000FF) - | ((x & 0x0000FC00) >> 2) | ((x & 0x00000300) << 6) - | ((x & 0x00F00000) >> 4) | ((x & 0x000F0000) << 4) - | ((x & 0xC0000000) >> 6) | ((x & 0x3F000000) << 2); - } -} - -static inline uint32_t rotr16(uint32_t x) { - return (x << 16) | (x >> 16); -} - -static inline void mix_columns32(uint32_t *q) { - uint32_t q0, q1, q2, q3, q4, q5, q6, q7; - uint32_t r0, r1, r2, r3, r4, r5, r6, r7; - - q0 = q[0]; - q1 = q[1]; - q2 = q[2]; - q3 = q[3]; - q4 = q[4]; - q5 = q[5]; - q6 = q[6]; - q7 = q[7]; - r0 = (q0 >> 8) | (q0 << 24); - r1 = (q1 >> 8) | (q1 << 24); - r2 = (q2 >> 8) | (q2 << 24); - r3 = (q3 >> 8) | (q3 << 24); - r4 = (q4 >> 8) | (q4 << 24); - r5 = (q5 >> 8) | (q5 << 24); - r6 = (q6 >> 8) | (q6 << 24); - r7 = (q7 >> 8) | (q7 << 24); - - q[0] = q7 ^ r7 ^ r0 ^ rotr16(q0 ^ r0); - q[1] = q0 ^ r0 ^ q7 ^ r7 ^ r1 ^ rotr16(q1 ^ r1); - q[2] = q1 ^ r1 ^ r2 ^ rotr16(q2 ^ r2); - q[3] = q2 ^ r2 ^ q7 ^ r7 ^ r3 ^ rotr16(q3 ^ r3); - q[4] = q3 ^ r3 ^ q7 ^ r7 ^ r4 ^ rotr16(q4 ^ r4); - q[5] = q4 ^ r4 ^ r5 ^ rotr16(q5 ^ r5); - q[6] = q5 ^ r5 ^ r6 ^ rotr16(q6 ^ r6); - q[7] = q6 ^ r6 ^ r7 ^ rotr16(q7 ^ r7); -} - -static void br_aes_ct64_ortho(uint64_t *q) { -#define SWAPN(cl, ch, s, x, y) do { \ - uint64_t a, b; \ - a = (x); \ - b = (y); \ - (x) = (a & (uint64_t)(cl)) | ((b & (uint64_t)(cl)) << (s)); \ - (y) = ((a & (uint64_t)(ch)) >> (s)) | (b & (uint64_t)(ch)); \ - } while (0) - -#define SWAP2(x, y) SWAPN(0x5555555555555555, 0xAAAAAAAAAAAAAAAA, 1, x, y) -#define SWAP4(x, y) SWAPN(0x3333333333333333, 0xCCCCCCCCCCCCCCCC, 2, x, y) -#define SWAP8(x, y) SWAPN(0x0F0F0F0F0F0F0F0F, 0xF0F0F0F0F0F0F0F0, 4, x, y) - - SWAP2(q[0], q[1]); - SWAP2(q[2], q[3]); - SWAP2(q[4], q[5]); - SWAP2(q[6], q[7]); - - SWAP4(q[0], q[2]); - SWAP4(q[1], q[3]); - SWAP4(q[4], q[6]); - SWAP4(q[5], q[7]); - - SWAP8(q[0], q[4]); - SWAP8(q[1], q[5]); - SWAP8(q[2], q[6]); - SWAP8(q[3], q[7]); -} - - -static void br_aes_ct64_interleave_in(uint64_t *q0, uint64_t *q1, const uint32_t *w) { - uint64_t x0, x1, x2, x3; - - x0 = w[0]; - x1 = w[1]; - x2 = w[2]; - x3 = w[3]; - x0 |= (x0 << 16); - x1 |= (x1 << 16); - x2 |= (x2 << 16); - x3 |= (x3 << 16); - x0 &= (uint64_t)0x0000FFFF0000FFFF; - x1 &= (uint64_t)0x0000FFFF0000FFFF; - x2 &= (uint64_t)0x0000FFFF0000FFFF; - x3 &= (uint64_t)0x0000FFFF0000FFFF; - x0 |= (x0 << 8); - x1 |= (x1 << 8); - x2 |= (x2 << 8); - x3 |= (x3 << 8); - x0 &= (uint64_t)0x00FF00FF00FF00FF; - x1 &= (uint64_t)0x00FF00FF00FF00FF; - x2 &= (uint64_t)0x00FF00FF00FF00FF; - x3 &= (uint64_t)0x00FF00FF00FF00FF; - *q0 = x0 | (x2 << 8); - *q1 = x1 | (x3 << 8); -} - - -static void br_aes_ct64_interleave_out(uint32_t *w, uint64_t q0, uint64_t q1) { - uint64_t x0, x1, x2, x3; - - x0 = q0 & (uint64_t)0x00FF00FF00FF00FF; - x1 = q1 & (uint64_t)0x00FF00FF00FF00FF; - x2 = (q0 >> 8) & (uint64_t)0x00FF00FF00FF00FF; - x3 = (q1 >> 8) & (uint64_t)0x00FF00FF00FF00FF; - x0 |= (x0 >> 8); - x1 |= (x1 >> 8); - x2 |= (x2 >> 8); - x3 |= (x3 >> 8); - x0 &= (uint64_t)0x0000FFFF0000FFFF; - x1 &= (uint64_t)0x0000FFFF0000FFFF; - x2 &= (uint64_t)0x0000FFFF0000FFFF; - x3 &= (uint64_t)0x0000FFFF0000FFFF; - w[0] = (uint32_t)x0 | (uint32_t)(x0 >> 16); - w[1] = (uint32_t)x1 | (uint32_t)(x1 >> 16); - w[2] = (uint32_t)x2 | (uint32_t)(x2 >> 16); - w[3] = (uint32_t)x3 | (uint32_t)(x3 >> 16); -} - -static inline void add_round_key(uint64_t *q, const uint64_t *sk) { - q[0] ^= sk[0]; - q[1] ^= sk[1]; - q[2] ^= sk[2]; - q[3] ^= sk[3]; - q[4] ^= sk[4]; - q[5] ^= sk[5]; - q[6] ^= sk[6]; - q[7] ^= sk[7]; -} - -static inline void shift_rows(uint64_t *q) { - int i; - - for (i = 0; i < 8; i++) { - uint64_t x; - - x = q[i]; - q[i] = (x & (uint64_t)0x000000000000FFFF) - | ((x & (uint64_t)0x00000000FFF00000) >> 4) - | ((x & (uint64_t)0x00000000000F0000) << 12) - | ((x & (uint64_t)0x0000FF0000000000) >> 8) - | ((x & (uint64_t)0x000000FF00000000) << 8) - | ((x & (uint64_t)0xF000000000000000) >> 12) - | ((x & (uint64_t)0x0FFF000000000000) << 4); - } -} - -static inline uint64_t rotr32(uint64_t x) { - return (x << 32) | (x >> 32); -} - -static inline void mix_columns(uint64_t *q) { - uint64_t q0, q1, q2, q3, q4, q5, q6, q7; - uint64_t r0, r1, r2, r3, r4, r5, r6, r7; - - q0 = q[0]; - q1 = q[1]; - q2 = q[2]; - q3 = q[3]; - q4 = q[4]; - q5 = q[5]; - q6 = q[6]; - q7 = q[7]; - r0 = (q0 >> 16) | (q0 << 48); - r1 = (q1 >> 16) | (q1 << 48); - r2 = (q2 >> 16) | (q2 << 48); - r3 = (q3 >> 16) | (q3 << 48); - r4 = (q4 >> 16) | (q4 << 48); - r5 = (q5 >> 16) | (q5 << 48); - r6 = (q6 >> 16) | (q6 << 48); - r7 = (q7 >> 16) | (q7 << 48); - - q[0] = q7 ^ r7 ^ r0 ^ rotr32(q0 ^ r0); - q[1] = q0 ^ r0 ^ q7 ^ r7 ^ r1 ^ rotr32(q1 ^ r1); - q[2] = q1 ^ r1 ^ r2 ^ rotr32(q2 ^ r2); - q[3] = q2 ^ r2 ^ q7 ^ r7 ^ r3 ^ rotr32(q3 ^ r3); - q[4] = q3 ^ r3 ^ q7 ^ r7 ^ r4 ^ rotr32(q4 ^ r4); - q[5] = q4 ^ r4 ^ r5 ^ rotr32(q5 ^ r5); - q[6] = q5 ^ r5 ^ r6 ^ rotr32(q6 ^ r6); - q[7] = q6 ^ r6 ^ r7 ^ rotr32(q7 ^ r7); -} - -static void interleave_constant(uint64_t *out, const unsigned char *in) { - uint32_t tmp_32_constant[16]; - int i; - - br_range_dec32le(tmp_32_constant, 16, in); - for (i = 0; i < 4; i++) { - br_aes_ct64_interleave_in(&out[i], &out[i + 4], tmp_32_constant + (i << 2)); - } - br_aes_ct64_ortho(out); -} - -static void interleave_constant32(uint32_t *out, const unsigned char *in) { - int i; - for (i = 0; i < 4; i++) { - out[2 * i] = br_dec32le(in + 4 * i); - out[2 * i + 1] = br_dec32le(in + 4 * i + 16); - } - br_aes_ct_ortho(out); -} - -void tweak_constants(spx_ctx *ctx) { - unsigned char buf[40 * 16]; - int i; - - /* Use the standard constants to generate tweaked ones. */ - memcpy((uint8_t *)ctx->tweaked512_rc64, (uint8_t *)haraka512_rc64, 40 * 16); - - /* Constants for pk.seed */ - haraka_S(buf, 40 * 16, ctx->pub_seed, SPX_N, ctx); - for (i = 0; i < 10; i++) { - interleave_constant32(ctx->tweaked256_rc32[i], buf + 32 * i); - interleave_constant(ctx->tweaked512_rc64[i], buf + 64 * i); - } -} - -static void haraka_S_absorb(unsigned char *s, unsigned int r, - const unsigned char *m, unsigned long long mlen, - unsigned char p, const spx_ctx *ctx) { - unsigned long long i; - PQCLEAN_VLA(uint8_t, t, r); - - while (mlen >= r) { - /* XOR block to state */ - for (i = 0; i < r; ++i) { - s[i] ^= m[i]; - } - haraka512_perm(s, s, ctx); - 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; ++i) { - s[i] ^= t[i]; - } -} - -static void haraka_S_squeezeblocks(unsigned char *h, unsigned long long nblocks, - unsigned char *s, unsigned int r, - const spx_ctx *ctx) { - while (nblocks > 0) { - haraka512_perm(s, s, ctx); - memcpy(h, s, HARAKAS_RATE); - h += r; - nblocks--; - } -} - -void haraka_S_inc_init(uint8_t *s_inc) { - size_t i; - - for (i = 0; i < 64; i++) { - s_inc[i] = 0; - } - s_inc[64] = 0; -} - -void haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, - const spx_ctx *ctx) { - size_t i; - - /* Recall that s_inc[64] is the non-absorbed bytes xored into the state */ - while (mlen + s_inc[64] >= HARAKAS_RATE) { - for (i = 0; i < (size_t)(HARAKAS_RATE - s_inc[64]); i++) { - /* Take the i'th byte from message - xor with the s_inc[64] + i'th byte of the state */ - s_inc[s_inc[64] + i] ^= m[i]; - } - mlen -= (size_t)(HARAKAS_RATE - s_inc[64]); - m += HARAKAS_RATE - (uint8_t)s_inc[64]; - s_inc[64] = 0; - - haraka512_perm(s_inc, s_inc, ctx); - } - - for (i = 0; i < mlen; i++) { - s_inc[s_inc[64] + i] ^= m[i]; - } - s_inc[64] += (uint8_t)mlen; -} - -void haraka_S_inc_finalize(uint8_t *s_inc) { - /* After haraka_S_inc_absorb, we are guaranteed that s_inc[64] < HARAKAS_RATE, - so we can always use one more byte for p in the current state. */ - s_inc[s_inc[64]] ^= 0x1F; - s_inc[HARAKAS_RATE - 1] ^= 128; - s_inc[64] = 0; -} - -void haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, - const spx_ctx *ctx) { - size_t i; - - /* First consume any bytes we still have sitting around */ - for (i = 0; i < outlen && i < s_inc[64]; i++) { - /* There are s_inc[64] bytes left, so r - s_inc[64] is the first - available byte. We consume from there, i.e., up to r. */ - out[i] = (uint8_t)s_inc[(HARAKAS_RATE - s_inc[64] + i)]; - } - out += i; - outlen -= i; - s_inc[64] -= (uint8_t)i; - - /* Then squeeze the remaining necessary blocks */ - while (outlen > 0) { - haraka512_perm(s_inc, s_inc, ctx); - - for (i = 0; i < outlen && i < HARAKAS_RATE; i++) { - out[i] = s_inc[i]; - } - out += i; - outlen -= i; - s_inc[64] = (uint8_t)(HARAKAS_RATE - i); - } -} - -void haraka_S(unsigned char *out, unsigned long long outlen, - const unsigned char *in, unsigned long long inlen, - const spx_ctx *ctx) { - unsigned long long i; - unsigned char s[64]; - unsigned char d[32]; - - for (i = 0; i < 64; i++) { - s[i] = 0; - } - haraka_S_absorb(s, 32, in, inlen, 0x1F, ctx); - - haraka_S_squeezeblocks(out, outlen / 32, s, 32, ctx); - out += (outlen / 32) * 32; - - if (outlen % 32) { - haraka_S_squeezeblocks(d, 1, s, 32, ctx); - for (i = 0; i < outlen % 32; i++) { - out[i] = d[i]; - } - } -} - -void haraka512_perm(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx) { - uint32_t w[16]; - uint64_t q[8], tmp_q; - unsigned int i, j; - - br_range_dec32le(w, 16, in); - for (i = 0; i < 4; i++) { - br_aes_ct64_interleave_in(&q[i], &q[i + 4], w + (i << 2)); - } - br_aes_ct64_ortho(q); - - /* AES rounds */ - for (i = 0; i < 5; i++) { - for (j = 0; j < 2; j++) { - br_aes_ct64_bitslice_Sbox(q); - shift_rows(q); - mix_columns(q); - add_round_key(q, ctx->tweaked512_rc64[2 * i + j]); - } - /* Mix states */ - for (j = 0; j < 8; j++) { - tmp_q = q[j]; - q[j] = (tmp_q & 0x0001000100010001) << 5 | - (tmp_q & 0x0002000200020002) << 12 | - (tmp_q & 0x0004000400040004) >> 1 | - (tmp_q & 0x0008000800080008) << 6 | - (tmp_q & 0x0020002000200020) << 9 | - (tmp_q & 0x0040004000400040) >> 4 | - (tmp_q & 0x0080008000800080) << 3 | - (tmp_q & 0x2100210021002100) >> 5 | - (tmp_q & 0x0210021002100210) << 2 | - (tmp_q & 0x0800080008000800) << 4 | - (tmp_q & 0x1000100010001000) >> 12 | - (tmp_q & 0x4000400040004000) >> 10 | - (tmp_q & 0x8400840084008400) >> 3; - } - } - - br_aes_ct64_ortho(q); - for (i = 0; i < 4; i ++) { - br_aes_ct64_interleave_out(w + (i << 2), q[i], q[i + 4]); - } - br_range_enc32le(out, w, 16); -} - -void haraka512(unsigned char *out, const unsigned char *in, const spx_ctx *ctx) { - int i; - - unsigned char buf[64]; - - haraka512_perm(buf, in, ctx); - /* Feed-forward */ - for (i = 0; i < 64; i++) { - buf[i] = buf[i] ^ in[i]; - } - - /* Truncated */ - memcpy(out, buf + 8, 8); - memcpy(out + 8, buf + 24, 8); - memcpy(out + 16, buf + 32, 8); - memcpy(out + 24, buf + 48, 8); -} - - -void haraka256(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx) { - uint32_t q[8], tmp_q; - int i, j; - - for (i = 0; i < 4; i++) { - q[2 * i] = br_dec32le(in + 4 * i); - q[2 * i + 1] = br_dec32le(in + 4 * i + 16); - } - br_aes_ct_ortho(q); - - /* AES rounds */ - for (i = 0; i < 5; i++) { - for (j = 0; j < 2; j++) { - br_aes_ct_bitslice_Sbox(q); - shift_rows32(q); - mix_columns32(q); - add_round_key32(q, ctx->tweaked256_rc32[2 * i + j]); - } - - /* Mix states */ - for (j = 0; j < 8; j++) { - tmp_q = q[j]; - q[j] = (tmp_q & 0x81818181) | - (tmp_q & 0x02020202) << 1 | - (tmp_q & 0x04040404) << 2 | - (tmp_q & 0x08080808) << 3 | - (tmp_q & 0x10101010) >> 3 | - (tmp_q & 0x20202020) >> 2 | - (tmp_q & 0x40404040) >> 1; - } - } - - br_aes_ct_ortho(q); - for (i = 0; i < 4; i++) { - br_enc32le(out + 4 * i, q[2 * i]); - br_enc32le(out + 4 * i + 16, q[2 * i + 1]); - } - - for (i = 0; i < 32; i++) { - out[i] ^= in[i]; - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/haraka.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/haraka.h deleted file mode 100644 index 737cb6065f..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/haraka.h +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef SPX_HARAKA_H -#define SPX_HARAKA_H - -#include "context.h" -#include "params.h" - -/* Tweak constants with seed */ -#define tweak_constants SPX_NAMESPACE(tweak_constants) -void tweak_constants(spx_ctx *ctx); - -/* Haraka Sponge */ -#define haraka_S_inc_init SPX_NAMESPACE(haraka_S_inc_init) -void haraka_S_inc_init(uint8_t *s_inc); -#define haraka_S_inc_absorb SPX_NAMESPACE(haraka_S_inc_absorb) -void haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, - const spx_ctx *ctx); -#define haraka_S_inc_finalize SPX_NAMESPACE(haraka_S_inc_finalize) -void haraka_S_inc_finalize(uint8_t *s_inc); -#define haraka_S_inc_squeeze SPX_NAMESPACE(haraka_S_inc_squeeze) -void haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, - const spx_ctx *ctx); -#define haraka_S SPX_NAMESPACE(haraka_S) -void haraka_S(unsigned char *out, unsigned long long outlen, - const unsigned char *in, unsigned long long inlen, - const spx_ctx *ctx); - -/* Applies the 512-bit Haraka permutation to in. */ -#define haraka512_perm SPX_NAMESPACE(haraka512_perm) -void haraka512_perm(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx); - -/* Implementation of Haraka-512 */ -#define haraka512 SPX_NAMESPACE(haraka512) -void haraka512(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx); - -/* Implementation of Haraka-256 */ -#define haraka256 SPX_NAMESPACE(haraka256) -void haraka256(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/haraka_offsets.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/haraka_offsets.h deleted file mode 100644 index 7c062272a0..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/haraka_offsets.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef HARAKA_OFFSETS_H_ -#define HARAKA_OFFSETS_H_ - -/* - * Offsets of various fields in the address structure when we use Haraka as - * the Sphincs+ hash function - */ - -#define SPX_OFFSET_LAYER 3 /* The byte used to specify the Merkle tree layer */ -#define SPX_OFFSET_TREE 8 /* The start of the 8 byte field used to specify the tree */ -#define SPX_OFFSET_TYPE 19 /* The byte used to specify the hash type (reason) */ -#define SPX_OFFSET_KP_ADDR2 22 /* The high byte used to specify the key pair (which one-time signature) */ -#define SPX_OFFSET_KP_ADDR1 23 /* The low byte used to specify the key pair */ -#define SPX_OFFSET_CHAIN_ADDR 27 /* The byte used to specify the chain address (which Winternitz chain) */ -#define SPX_OFFSET_HASH_ADDR 31 /* The byte used to specify the hash address (where in the Winternitz chain) */ -#define SPX_OFFSET_TREE_HGT 27 /* The byte used to specify the height of this node in the FORS or Merkle tree */ -#define SPX_OFFSET_TREE_INDEX 28 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ - -#define SPX_HARAKA 1 - -#endif /* HARAKA_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/hash.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/hash.h deleted file mode 100644 index f7c87d4c3c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/hash.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef SPX_HASH_H -#define SPX_HASH_H - -#include -#include - -#include "context.h" -#include "params.h" - -#define prf_addr SPX_NAMESPACE(prf_addr) -void prf_addr(unsigned char *out, const spx_ctx *ctx, - const uint32_t addr[8]); - -#define gen_message_random SPX_NAMESPACE(gen_message_random) -void gen_message_random(unsigned char *R, const unsigned char *sk_prf, - const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx); - -#define hash_message SPX_NAMESPACE(hash_message) -void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx); - - - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/hash_haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/hash_haraka.c deleted file mode 100644 index 750a67423b..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/hash_haraka.c +++ /dev/null @@ -1,81 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "utils.h" - -#include "haraka.h" -#include "hash.h" - -/* - * Computes PRF(key, addr), given a secret key of SPX_N bytes and an address - */ -void prf_addr(unsigned char *out, const spx_ctx *ctx, - const uint32_t addr[8]) { - /* Since SPX_N may be smaller than 32, we need temporary buffers. */ - unsigned char outbuf[32]; - unsigned char buf[64] = {0}; - - memcpy(buf, addr, SPX_ADDR_BYTES); - memcpy(buf + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); - - haraka512(outbuf, (const void *)buf, ctx); - memcpy(out, outbuf, SPX_N); -} - -/** - * Computes the message-dependent randomness R, using a secret seed and an - * optional randomization value as well as the message. - */ -void gen_message_random(unsigned char *R, const unsigned char *sk_prf, - const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx) { - uint8_t s_inc[65]; - - haraka_S_inc_init(s_inc); - haraka_S_inc_absorb(s_inc, sk_prf, SPX_N, ctx); - haraka_S_inc_absorb(s_inc, optrand, SPX_N, ctx); - haraka_S_inc_absorb(s_inc, m, mlen, ctx); - haraka_S_inc_finalize(s_inc); - haraka_S_inc_squeeze(R, SPX_N, s_inc, ctx); -} - -/** - * Computes the message hash using R, the public key, and the message. - * Outputs the message digest and the index of the leaf. The index is split in - * the tree index and the leaf index, for convenient copying to an address. - */ -void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx) { -#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) -#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) -#define SPX_LEAF_BITS SPX_TREE_HEIGHT -#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) -#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) - - unsigned char buf[SPX_DGST_BYTES]; - unsigned char *bufp = buf; - uint8_t s_inc[65]; - - haraka_S_inc_init(s_inc); - haraka_S_inc_absorb(s_inc, R, SPX_N, ctx); - haraka_S_inc_absorb(s_inc, pk + SPX_N, SPX_N, ctx); // Only absorb root part of pk - haraka_S_inc_absorb(s_inc, m, mlen, ctx); - haraka_S_inc_finalize(s_inc); - haraka_S_inc_squeeze(buf, SPX_DGST_BYTES, s_inc, ctx); - - memcpy(digest, bufp, SPX_FORS_MSG_BYTES); - bufp += SPX_FORS_MSG_BYTES; - - - *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); - *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); - bufp += SPX_TREE_BYTES; - - *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); - *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/merkle.c b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/merkle.c deleted file mode 100644 index 0c1479fd93..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/merkle.c +++ /dev/null @@ -1,59 +0,0 @@ -#include -#include - -#include "address.h" -#include "merkle.h" -#include "params.h" -#include "utils.h" -#include "utilsx1.h" -#include "wots.h" -#include "wotsx1.h" - -/* - * This generates a Merkle signature (WOTS signature followed by the Merkle - * authentication path). This is in this file because most of the complexity - * is involved with the WOTS signature; the Merkle authentication path logic - * is mostly hidden in treehashx4 - */ -void merkle_sign(uint8_t *sig, unsigned char *root, - const spx_ctx *ctx, - uint32_t wots_addr[8], uint32_t tree_addr[8], - uint32_t idx_leaf) { - unsigned char *auth_path = sig + SPX_WOTS_BYTES; - struct leaf_info_x1 info = { 0 }; - unsigned steps[ SPX_WOTS_LEN ]; - - info.wots_sig = sig; - chain_lengths(steps, root); - info.wots_steps = steps; - - set_type(&tree_addr[0], SPX_ADDR_TYPE_HASHTREE); - set_type(&info.pk_addr[0], SPX_ADDR_TYPE_WOTSPK); - copy_subtree_addr(&info.leaf_addr[0], wots_addr); - copy_subtree_addr(&info.pk_addr[0], wots_addr); - - info.wots_sign_leaf = idx_leaf; - - treehashx1(root, auth_path, ctx, - idx_leaf, 0, - SPX_TREE_HEIGHT, - wots_gen_leafx1, - tree_addr, &info); -} - -/* Compute root node of the top-most subtree. */ -void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { - /* We do not need the auth path in key generation, but it simplifies the - code to have just one treehash routine that computes both root and path - in one function. */ - unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; - uint32_t top_tree_addr[8] = {0}; - uint32_t wots_addr[8] = {0}; - - set_layer_addr(top_tree_addr, SPX_D - 1); - set_layer_addr(wots_addr, SPX_D - 1); - - merkle_sign(auth_path, root, ctx, - wots_addr, top_tree_addr, - (uint32_t)~0 /* ~0 means "don't bother generating an auth path */ ); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/merkle.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/merkle.h deleted file mode 100644 index 769cf2e970..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/merkle.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef MERKLE_H_ -#define MERKLE_H_ - -#include - -#include "context.h" -#include "params.h" - -/* Generate a Merkle signature (WOTS signature followed by the Merkle */ -/* authentication path) */ -#define merkle_sign SPX_NAMESPACE(merkle_sign) -void merkle_sign(uint8_t *sig, unsigned char *root, - const spx_ctx *ctx, - uint32_t wots_addr[8], uint32_t tree_addr[8], - uint32_t idx_leaf); - -/* Compute the root node of the top-most subtree. */ -#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) -void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); - -#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/nistapi.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/nistapi.h deleted file mode 100644 index 3cb71afad4..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/nistapi.h +++ /dev/null @@ -1,87 +0,0 @@ -#ifndef SPX_API_H -#define SPX_API_H - -#include -#include - -#include "params.h" - -#define CRYPTO_ALGNAME "SPHINCS+" - -#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES -#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES -#define CRYPTO_BYTES SPX_BYTES -#define CRYPTO_SEEDBYTES (3*SPX_N) - -/* - * Returns the length of a secret key, in bytes - */ -#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) -size_t crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) -size_t crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) -size_t crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) -size_t crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) -int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) -int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) -int crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) -int crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -#define crypto_sign SPX_NAMESPACE(crypto_sign) -int crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) -int crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/params.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/params.h deleted file mode 100644 index 41c7d2ff2b..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/params.h +++ /dev/null @@ -1,56 +0,0 @@ -#ifndef SPX_PARAMS_H -#define SPX_PARAMS_H - -#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_##s - -/* Hash output length in bytes. */ -#define SPX_N 32 -/* Height of the hypertree. */ -#define SPX_FULL_HEIGHT 68 -/* Number of subtree layer. */ -#define SPX_D 17 -/* FORS tree dimensions. */ -#define SPX_FORS_HEIGHT 9 -#define SPX_FORS_TREES 35 -/* Winternitz parameter, */ -#define SPX_WOTS_W 16 - -/* The hash function is defined by linking a different hash.c file, as opposed - to setting a #define constant. */ - -/* For clarity */ -#define SPX_ADDR_BYTES 32 - -/* WOTS parameters. */ -#define SPX_WOTS_LOGW 4 - -#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) - -/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#define SPX_WOTS_LEN2 3 - -#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) -#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) -#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES - -/* Subtree size. */ -#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) - -//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT -// #error SPX_D should always divide SPX_FULL_HEIGHT -//#endif - -/* FORS parameters. */ -#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) -#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) -#define SPX_FORS_PK_BYTES SPX_N - -/* Resulting SPX sizes. */ -#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ - SPX_FULL_HEIGHT * SPX_N) -#define SPX_PK_BYTES (2 * SPX_N) -#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) - -#include "haraka_offsets.h" - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/sign.c b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/sign.c deleted file mode 100644 index 9d0c7d1b22..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/sign.c +++ /dev/null @@ -1,286 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "context.h" -#include "fors.h" -#include "hash.h" -#include "merkle.h" -#include "nistapi.h" -#include "params.h" -#include "randombytes.h" -#include "thash.h" -#include "utils.h" -#include "wots.h" - -/* - * Returns the length of a secret key, in bytes - */ -size_t crypto_sign_secretkeybytes(void) { - return CRYPTO_SECRETKEYBYTES; -} - -/* - * Returns the length of a public key, in bytes - */ -size_t crypto_sign_publickeybytes(void) { - return CRYPTO_PUBLICKEYBYTES; -} - -/* - * Returns the length of a signature, in bytes - */ -size_t crypto_sign_bytes(void) { - return CRYPTO_BYTES; -} - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t crypto_sign_seedbytes(void) { - return CRYPTO_SEEDBYTES; -} - -/* - * Generates an SPX key pair given a seed of length - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed) { - spx_ctx ctx; - - /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ - memcpy(sk, seed, CRYPTO_SEEDBYTES); - - memcpy(pk, sk + 2 * SPX_N, SPX_N); - - memcpy(ctx.pub_seed, pk, SPX_N); - memcpy(ctx.sk_seed, sk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - /* Compute root node of the top-most subtree. */ - merkle_gen_root(sk + 3 * SPX_N, &ctx); - - // cleanup - free_hash_function(&ctx); - - memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); - - return 0; -} - -/* - * Generates an SPX key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { - uint8_t seed[CRYPTO_SEEDBYTES]; - randombytes(seed, CRYPTO_SEEDBYTES); - crypto_sign_seed_keypair(pk, sk, seed); - - return 0; -} - -/** - * Returns an array containing a detached signature. - */ -int crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - spx_ctx ctx; - - const uint8_t *sk_prf = sk + SPX_N; - const uint8_t *pk = sk + 2 * SPX_N; - - uint8_t optrand[SPX_N]; - uint8_t mhash[SPX_FORS_MSG_BYTES]; - uint8_t root[SPX_N]; - uint32_t i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - - memcpy(ctx.sk_seed, sk, SPX_N); - memcpy(ctx.pub_seed, pk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - set_type(wots_addr, SPX_ADDR_TYPE_WOTS); - set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); - - /* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ - randombytes(optrand, SPX_N); - /* Compute the digest randomization value. */ - gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); - - /* Derive the message digest and leaf index from R, PK and M. */ - hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); - sig += SPX_N; - - set_tree_addr(wots_addr, tree); - set_keypair_addr(wots_addr, idx_leaf); - - /* Sign the message hash using FORS. */ - fors_sign(sig, root, mhash, &ctx, wots_addr); - sig += SPX_FORS_BYTES; - - for (i = 0; i < SPX_D; i++) { - set_layer_addr(tree_addr, i); - set_tree_addr(tree_addr, tree); - - copy_subtree_addr(wots_addr, tree_addr); - set_keypair_addr(wots_addr, idx_leaf); - - merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); - sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); - tree = tree >> SPX_TREE_HEIGHT; - } - - free_hash_function(&ctx); - - *siglen = SPX_BYTES; - - return 0; -} - -/** - * Verifies a detached signature and message under a given public key. - */ -int crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk) { - spx_ctx ctx; - const uint8_t *pub_root = pk + SPX_N; - uint8_t mhash[SPX_FORS_MSG_BYTES]; - uint8_t wots_pk[SPX_WOTS_BYTES]; - uint8_t root[SPX_N]; - uint8_t leaf[SPX_N]; - unsigned int i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - if (siglen != SPX_BYTES) { - return -1; - } - - memcpy(ctx.pub_seed, pk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - set_type(wots_addr, SPX_ADDR_TYPE_WOTS); - set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); - set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); - - /* Derive the message digest and leaf index from R || PK || M. */ - /* The additional SPX_N is a result of the hash domain separator. */ - hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); - sig += SPX_N; - - /* Layer correctly defaults to 0, so no need to set_layer_addr */ - set_tree_addr(wots_addr, tree); - set_keypair_addr(wots_addr, idx_leaf); - - fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); - sig += SPX_FORS_BYTES; - - /* For each subtree.. */ - for (i = 0; i < SPX_D; i++) { - set_layer_addr(tree_addr, i); - set_tree_addr(tree_addr, tree); - - copy_subtree_addr(wots_addr, tree_addr); - set_keypair_addr(wots_addr, idx_leaf); - - copy_keypair_addr(wots_pk_addr, wots_addr); - - /* The WOTS public key is only correct if the signature was correct. */ - /* Initially, root is the FORS pk, but on subsequent iterations it is - the root of the subtree below the currently processed subtree. */ - wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); - sig += SPX_WOTS_BYTES; - - /* Compute the leaf node using the WOTS public key. */ - thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); - - /* Compute the root node of this subtree. */ - compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, - &ctx, tree_addr); - sig += SPX_TREE_HEIGHT * SPX_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); - tree = tree >> SPX_TREE_HEIGHT; - } - - // cleanup - free_hash_function(&ctx); - - /* Check if the root node equals the root node in the public key. */ - if (memcmp(root, pub_root, SPX_N) != 0) { - return -1; - } - - return 0; -} - - -/** - * Returns an array containing the signature followed by the message. - */ -int crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk) { - size_t siglen; - - crypto_sign_signature(sm, &siglen, m, mlen, sk); - - memmove(sm + SPX_BYTES, m, mlen); - *smlen = siglen + mlen; - - return 0; -} - -/** - * Verifies a given signature-message pair under a given public key. - */ -int crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk) { - /* The API caller does not necessarily know what size a signature should be - but SPHINCS+ signatures are always exactly SPX_BYTES. */ - if (smlen < SPX_BYTES) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - *mlen = smlen - SPX_BYTES; - - if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - /* If verification was successful, move the message to the right place. */ - memmove(m, sm + SPX_BYTES, *mlen); - - return 0; -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/thash.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/thash.h deleted file mode 100644 index 8687ccfb4d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/thash.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef SPX_THASH_H -#define SPX_THASH_H - -#include "context.h" -#include "params.h" - -#include - -#define thash SPX_NAMESPACE(thash) -void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/thash_haraka_robust.c b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/thash_haraka_robust.c deleted file mode 100644 index 109502cbc2..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/thash_haraka_robust.c +++ /dev/null @@ -1,45 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "thash.h" -#include "utils.h" - -#include "haraka.h" - -/** - * Takes an array of inblocks concatenated arrays of SPX_N bytes. - */ -void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]) { - PQCLEAN_VLA(uint8_t, buf, SPX_ADDR_BYTES + inblocks * SPX_N); - PQCLEAN_VLA(uint8_t, bitmask, inblocks * SPX_N); - unsigned char outbuf[32]; - unsigned char buf_tmp[64]; - unsigned int i; - - if (inblocks == 1) { - /* F function */ - /* Since SPX_N may be smaller than 32, we need a temporary buffer. */ - memset(buf_tmp, 0, 64); - memcpy(buf_tmp, addr, 32); - - haraka256(outbuf, buf_tmp, ctx); - for (i = 0; i < inblocks * SPX_N; i++) { - buf_tmp[SPX_ADDR_BYTES + i] = in[i] ^ outbuf[i]; - } - haraka512(outbuf, buf_tmp, ctx); - memcpy(out, outbuf, SPX_N); - } else { - /* All other tweakable hashes*/ - memcpy(buf, addr, 32); - haraka_S(bitmask, inblocks * SPX_N, buf, SPX_ADDR_BYTES, ctx); - - for (i = 0; i < inblocks * SPX_N; i++) { - buf[SPX_ADDR_BYTES + i] = in[i] ^ bitmask[i]; - } - - haraka_S(out, SPX_N, buf, SPX_ADDR_BYTES + inblocks * SPX_N, ctx); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/utils.c b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/utils.c deleted file mode 100644 index 177b541fb9..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/utils.c +++ /dev/null @@ -1,148 +0,0 @@ -#include - -#include "utils.h" - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "thash.h" - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void ull_to_bytes(unsigned char *out, unsigned int outlen, - unsigned long long in) { - int i; - - /* Iterate over out in decreasing order, for big-endianness. */ - for (i = (signed int)outlen - 1; i >= 0; i--) { - out[i] = in & 0xff; - in = in >> 8; - } -} - -void u32_to_bytes(unsigned char *out, uint32_t in) { - out[0] = (unsigned char)(in >> 24); - out[1] = (unsigned char)(in >> 16); - out[2] = (unsigned char)(in >> 8); - out[3] = (unsigned char)in; -} - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { - unsigned long long retval = 0; - unsigned int i; - - for (i = 0; i < inlen; i++) { - retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); - } - return retval; -} - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void compute_root(unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const spx_ctx *ctx, uint32_t addr[8]) { - uint32_t i; - unsigned char buffer[2 * SPX_N]; - - /* If leaf_idx is odd (last bit = 1), current path element is a right child - and auth_path has to go left. Otherwise it is the other way around. */ - if (leaf_idx & 1) { - memcpy(buffer + SPX_N, leaf, SPX_N); - memcpy(buffer, auth_path, SPX_N); - } else { - memcpy(buffer, leaf, SPX_N); - memcpy(buffer + SPX_N, auth_path, SPX_N); - } - auth_path += SPX_N; - - for (i = 0; i < tree_height - 1; i++) { - leaf_idx >>= 1; - idx_offset >>= 1; - /* Set the address of the node we're creating. */ - set_tree_height(addr, i + 1); - set_tree_index(addr, leaf_idx + idx_offset); - - /* Pick the right or left neighbor, depending on parity of the node. */ - if (leaf_idx & 1) { - thash(buffer + SPX_N, buffer, 2, ctx, addr); - memcpy(buffer, auth_path, SPX_N); - } else { - thash(buffer, buffer, 2, ctx, addr); - memcpy(buffer + SPX_N, auth_path, SPX_N); - } - auth_path += SPX_N; - } - - /* The last iteration is exceptional; we do not copy an auth_path node. */ - leaf_idx >>= 1; - idx_offset >>= 1; - set_tree_height(addr, tree_height); - set_tree_index(addr, leaf_idx + idx_offset); - thash(root, buffer, 2, ctx, addr); -} - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const spx_ctx * /* ctx */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), - uint32_t tree_addr[8]) { - PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); - PQCLEAN_VLA(unsigned int, heights, tree_height + 1); - unsigned int offset = 0; - uint32_t idx; - uint32_t tree_idx; - - for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { - /* Add the next leaf node to the stack. */ - gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); - offset++; - heights[offset - 1] = 0; - - /* If this is a node we need for the auth path.. */ - if ((leaf_idx ^ 0x1) == idx) { - memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); - } - - /* While the top-most nodes are of equal height.. */ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { - /* Compute index of the new node, in the next layer. */ - tree_idx = (idx >> (heights[offset - 1] + 1)); - - /* Set the address of the node we're creating. */ - set_tree_height(tree_addr, heights[offset - 1] + 1); - set_tree_index(tree_addr, - tree_idx + (idx_offset >> (heights[offset - 1] + 1))); - /* Hash the top-most nodes from the stack together. */ - thash(stack + (offset - 2)*SPX_N, - stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); - offset--; - /* Note that the top-most node is now one layer higher. */ - heights[offset - 1]++; - - /* If this is a node we need for the auth path.. */ - if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_path + heights[offset - 1]*SPX_N, - stack + (offset - 1)*SPX_N, SPX_N); - } - } - } - memcpy(root, stack, SPX_N); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/utils.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/utils.h deleted file mode 100644 index 64f5d5a53a..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/utils.h +++ /dev/null @@ -1,58 +0,0 @@ -#ifndef SPX_UTILS_H -#define SPX_UTILS_H - -#include - -#include "compat.h" -#include "context.h" -#include "params.h" - - -/* To support MSVC use alloca() instead of VLAs. See #20. */ - - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) -void ull_to_bytes(unsigned char *out, unsigned int outlen, - unsigned long long in); -#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) -void u32_to_bytes(unsigned char *out, uint32_t in); - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) -unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -#define compute_root SPX_NAMESPACE(compute_root) -void compute_root(unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const spx_ctx *ctx, uint32_t addr[8]); - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -#define treehash SPX_NAMESPACE(treehash) -void treehash(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const spx_ctx *ctx /* ctx */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), - uint32_t tree_addr[8]); - - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/utilsx1.c b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/utilsx1.c deleted file mode 100644 index fccb69b35d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/utilsx1.c +++ /dev/null @@ -1,100 +0,0 @@ -#include - -#include "utilsx1.h" - -#include "address.h" -#include "params.h" -#include "thash.h" -#include "utils.h" - -/* - * Generate the entire Merkle tree, computing the authentication path for - * leaf_idx, and the resulting root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) - * - * This expects tree_addr to be initialized to the addr structures for the - * Merkle tree nodes - * - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - * - * This works by using the standard Merkle tree building algorithm, - */ -void treehashx1(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, - uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* Where to write the leaves */, - const spx_ctx * /* ctx */, - uint32_t idx, void *info), - uint32_t tree_addr[8], - void *info) { - /* This is where we keep the intermediate nodes */ - PQCLEAN_VLA(uint8_t, stack, tree_height * SPX_N); - - uint32_t idx; - uint32_t max_idx = (uint32_t)((1 << tree_height) - 1); - for (idx = 0;; idx++) { - unsigned char current[2 * SPX_N]; /* Current logical node is at */ - /* index[SPX_N]. We do this to minimize the number of copies */ - /* needed during a thash */ - gen_leaf( ¤t[SPX_N], ctx, idx + idx_offset, - info ); - - /* Now combine the freshly generated right node with previously */ - /* generated left ones */ - uint32_t internal_idx_offset = idx_offset; - uint32_t internal_idx = idx; - uint32_t internal_leaf = leaf_idx; - uint32_t h; /* The height we are in the Merkle tree */ - for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { - - /* Check if we hit the top of the tree */ - if (h == tree_height) { - /* We hit the root; return it */ - memcpy( root, ¤t[SPX_N], SPX_N ); - return; - } - - /* - * Check if the node we have is a part of the - * authentication path; if it is, write it out - */ - if ((internal_idx ^ internal_leaf) == 0x01) { - memcpy( &auth_path[ h * SPX_N ], - ¤t[SPX_N], - SPX_N ); - } - - /* - * Check if we're at a left child; if so, stop going up the stack - * Exception: if we've reached the end of the tree, keep on going - * (so we combine the last 4 nodes into the one root node in two - * more iterations) - */ - if ((internal_idx & 1) == 0 && idx < max_idx) { - break; - } - - /* Ok, we're at a right node */ - /* Now combine the left and right logical nodes together */ - - /* Set the address of the node we're creating. */ - internal_idx_offset >>= 1; - set_tree_height(tree_addr, h + 1); - set_tree_index(tree_addr, internal_idx / 2 + internal_idx_offset ); - - unsigned char *left = &stack[h * SPX_N]; - memcpy( ¤t[0], left, SPX_N ); - thash( ¤t[1 * SPX_N], - ¤t[0 * SPX_N], - 2, ctx, tree_addr); - } - - /* We've hit a left child; save the current for when we get the */ - /* corresponding right right */ - memcpy( &stack[h * SPX_N], ¤t[SPX_N], SPX_N); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/utilsx1.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/utilsx1.h deleted file mode 100644 index e911d17d53..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/utilsx1.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef SPX_UTILSX4_H -#define SPX_UTILSX4_H - -#include - -#include "context.h" -#include "params.h" - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -#define treehashx1 SPX_NAMESPACE(treehashx1) -void treehashx1(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* Where to write the leaf */, - const spx_ctx * /* ctx */, - uint32_t addr_idx, void *info), - uint32_t tree_addrx4[8], void *info); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/wots.c b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/wots.c deleted file mode 100644 index 249717aaa8..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/wots.c +++ /dev/null @@ -1,108 +0,0 @@ -#include -#include - -#include "wots.h" -#include "wotsx1.h" - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "thash.h" -#include "utils.h" -#include "utilsx1.h" - -// TODO clarify address expectations, and make them more uniform. -// TODO i.e. do we expect types to be set already? -// TODO and do we expect modifications or copies? - -/** - * Computes the chaining function. - * out and in have to be n-byte arrays. - * - * Interprets in as start-th value of the chain. - * addr has to contain the address of the chain. - */ -static void gen_chain(unsigned char *out, const unsigned char *in, - unsigned int start, unsigned int steps, - const spx_ctx *ctx, uint32_t addr[8]) { - uint32_t i; - - /* Initialize out with the value at position 'start'. */ - memcpy(out, in, SPX_N); - - /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < SPX_WOTS_W; i++) { - set_hash_addr(addr, i); - thash(out, out, 1, ctx, addr); - } -} - -/** - * base_w algorithm as described in draft. - * Interprets an array of bytes as integers in base w. - * This only works when log_w is a divisor of 8. - */ -static void base_w(unsigned int *output, const int out_len, - const unsigned char *input) { - int in = 0; - int out = 0; - unsigned char total = 0; - int bits = 0; - int consumed; - - for (consumed = 0; consumed < out_len; consumed++) { - if (bits == 0) { - total = input[in]; - in++; - bits += 8; - } - bits -= SPX_WOTS_LOGW; - output[out] = (total >> bits) & (SPX_WOTS_W - 1); - out++; - } -} - -/* Computes the WOTS+ checksum over a message (in base_w). */ -static void wots_checksum(unsigned int *csum_base_w, - const unsigned int *msg_base_w) { - unsigned int csum = 0; - unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; - unsigned int i; - - /* Compute checksum. */ - for (i = 0; i < SPX_WOTS_LEN1; i++) { - csum += SPX_WOTS_W - 1 - msg_base_w[i]; - } - - /* Convert checksum to base_w. */ - /* Make sure expected empty zero bits are the least significant bits. */ - csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); - ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); - base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); -} - -/* Takes a message and derives the matching chain lengths. */ -void chain_lengths(unsigned int *lengths, const unsigned char *msg) { - base_w(lengths, SPX_WOTS_LEN1, msg); - wots_checksum(lengths + SPX_WOTS_LEN1, lengths); -} - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const spx_ctx *ctx, uint32_t addr[8]) { - unsigned int lengths[SPX_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < SPX_WOTS_LEN; i++) { - set_chain_addr(addr, i); - gen_chain(pk + i * SPX_N, sig + i * SPX_N, - lengths[i], SPX_WOTS_W - 1 - lengths[i], ctx, addr); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/wots.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/wots.h deleted file mode 100644 index 4e7692eeef..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/wots.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef SPX_WOTS_H -#define SPX_WOTS_H - -#include - -#include "context.h" -#include "params.h" - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) -void wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const spx_ctx *ctx, uint32_t addr[8]); - -/* - * Compute the chain lengths needed for a given message hash - */ -#define chain_lengths SPX_NAMESPACE(chain_lengths) -void chain_lengths(unsigned int *lengths, const unsigned char *msg); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/wotsx1.c b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/wotsx1.c deleted file mode 100644 index 3adec78dfb..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/wotsx1.c +++ /dev/null @@ -1,76 +0,0 @@ -#include -#include - -#include "wots.h" -#include "wotsx1.h" - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "thash.h" -#include "utils.h" - -/* - * This generates a WOTS public key - * It also generates the WOTS signature if leaf_info indicates - * that we're signing with this WOTS key - */ -void wots_gen_leafx1(unsigned char *dest, - const spx_ctx *ctx, - uint32_t leaf_idx, void *v_info) { - struct leaf_info_x1 *info = v_info; - uint32_t *leaf_addr = info->leaf_addr; - uint32_t *pk_addr = info->pk_addr; - unsigned int i, k; - unsigned char pk_buffer[ SPX_WOTS_BYTES ]; - unsigned char *buffer; - uint32_t wots_k_mask; - - if (leaf_idx == info->wots_sign_leaf) { - /* We're traversing the leaf that's signing; generate the WOTS */ - /* signature */ - wots_k_mask = 0; - } else { - /* Nope, we're just generating pk's; turn off the signature logic */ - wots_k_mask = (uint32_t)~0; - } - - set_keypair_addr( leaf_addr, leaf_idx ); - set_keypair_addr( pk_addr, leaf_idx ); - - for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { - uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k to */ - /* the step if we're generating a signature, ~0 if we're not */ - - /* Start with the secret seed */ - set_chain_addr(leaf_addr, i); - set_hash_addr(leaf_addr, 0); - set_type(leaf_addr, SPX_ADDR_TYPE_WOTSPRF); - - prf_addr(buffer, ctx, leaf_addr); - - set_type(leaf_addr, SPX_ADDR_TYPE_WOTS); - - /* Iterate down the WOTS chain */ - for (k = 0;; k++) { - /* Check if this is the value that needs to be saved as a */ - /* part of the WOTS signature */ - if (k == wots_k) { - memcpy( info->wots_sig + i * SPX_N, buffer, SPX_N ); - } - - /* Check if we hit the top of the chain */ - if (k == SPX_WOTS_W - 1) { - break; - } - - /* Iterate one step on the chain */ - set_hash_addr(leaf_addr, k); - - thash(buffer, buffer, 1, ctx, leaf_addr); - } - } - - /* Do the final thash to generate the public keys */ - thash(dest, pk_buffer, SPX_WOTS_LEN, ctx, pk_addr); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/wotsx1.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/wotsx1.h deleted file mode 100644 index e617929f96..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-robust_clean/wotsx1.h +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef WOTSX1_H_ -#define WOTSX1_H_ - -#include - -#include "context.h" -#include "params.h" - -/* - * This is here to provide an interface to the internal wots_gen_leafx1 - * routine. While this routine is not referenced in the package outside of - * wots.c, it is called from the stand-alone benchmark code to characterize - * the performance - */ -struct leaf_info_x1 { - unsigned char *wots_sig; - uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ - uint32_t *wots_steps; - uint32_t leaf_addr[8]; - uint32_t pk_addr[8]; -}; - -/* Macro to set the leaf_info to something 'benign', that is, it would */ -/* run with the same time as it does during the real signing process */ -/* Used only by the benchmark code */ -#define INITIALIZE_LEAF_INFO_X1(info, addr, step_buffer) { \ - (info).wots_sig = 0; \ - (info).wots_sign_leaf = ~0; \ - (info).wots_steps = step_buffer; \ - memcpy( &(info).leaf_addr[0], (addr), 32 ); \ - memcpy( &(info).pk_addr[0], (addr), 32 ); \ - } - -#define wots_gen_leafx1 SPX_NAMESPACE(wots_gen_leafx1) -void wots_gen_leafx1(unsigned char *dest, - const spx_ctx *ctx, - uint32_t leaf_idx, void *v_info); - -#endif /* WOTSX1_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/LICENSE b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/LICENSE deleted file mode 100644 index 670154e353..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/LICENSE +++ /dev/null @@ -1,116 +0,0 @@ -CC0 1.0 Universal - -Statement of Purpose - -The laws of most jurisdictions throughout the world automatically confer -exclusive Copyright and Related Rights (defined below) upon the creator and -subsequent owner(s) (each and all, an "owner") of an original work of -authorship and/or a database (each, a "Work"). - -Certain owners wish to permanently relinquish those rights to a Work for the -purpose of contributing to a commons of creative, cultural and scientific -works ("Commons") that the public can reliably and without fear of later -claims of infringement build upon, modify, incorporate in other works, reuse -and redistribute as freely as possible in any form whatsoever and for any -purposes, including without limitation commercial purposes. These owners may -contribute to the Commons to promote the ideal of a free culture and the -further production of creative, cultural and scientific works, or to gain -reputation or greater distribution for their Work in part through the use and -efforts of others. - -For these and/or other purposes and motivations, and without any expectation -of additional consideration or compensation, the person associating CC0 with a -Work (the "Affirmer"), to the extent that he or she is an owner of Copyright -and Related Rights in the Work, voluntarily elects to apply CC0 to the Work -and publicly distribute the Work under its terms, with knowledge of his or her -Copyright and Related Rights in the Work and the meaning and intended legal -effect of CC0 on those rights. - -1. Copyright and Related Rights. A Work made available under CC0 may be -protected by copyright and related or neighboring rights ("Copyright and -Related Rights"). Copyright and Related Rights include, but are not limited -to, the following: - - i. the right to reproduce, adapt, distribute, perform, display, communicate, - and translate a Work; - - ii. moral rights retained by the original author(s) and/or performer(s); - - iii. publicity and privacy rights pertaining to a person's image or likeness - depicted in a Work; - - iv. rights protecting against unfair competition in regards to a Work, - subject to the limitations in paragraph 4(a), below; - - v. rights protecting the extraction, dissemination, use and reuse of data in - a Work; - - vi. database rights (such as those arising under Directive 96/9/EC of the - European Parliament and of the Council of 11 March 1996 on the legal - protection of databases, and under any national implementation thereof, - including any amended or successor version of such directive); and - - vii. other similar, equivalent or corresponding rights throughout the world - based on applicable law or treaty, and any national implementations thereof. - -2. Waiver. To the greatest extent permitted by, but not in contravention of, -applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and -unconditionally waives, abandons, and surrenders all of Affirmer's Copyright -and Related Rights and associated claims and causes of action, whether now -known or unknown (including existing as well as future claims and causes of -action), in the Work (i) in all territories worldwide, (ii) for the maximum -duration provided by applicable law or treaty (including future time -extensions), (iii) in any current or future medium and for any number of -copies, and (iv) for any purpose whatsoever, including without limitation -commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes -the Waiver for the benefit of each member of the public at large and to the -detriment of Affirmer's heirs and successors, fully intending that such Waiver -shall not be subject to revocation, rescission, cancellation, termination, or -any other legal or equitable action to disrupt the quiet enjoyment of the Work -by the public as contemplated by Affirmer's express Statement of Purpose. - -3. Public License Fallback. Should any part of the Waiver for any reason be -judged legally invalid or ineffective under applicable law, then the Waiver -shall be preserved to the maximum extent permitted taking into account -Affirmer's express Statement of Purpose. In addition, to the extent the Waiver -is so judged Affirmer hereby grants to each affected person a royalty-free, -non transferable, non sublicensable, non exclusive, irrevocable and -unconditional license to exercise Affirmer's Copyright and Related Rights in -the Work (i) in all territories worldwide, (ii) for the maximum duration -provided by applicable law or treaty (including future time extensions), (iii) -in any current or future medium and for any number of copies, and (iv) for any -purpose whatsoever, including without limitation commercial, advertising or -promotional purposes (the "License"). The License shall be deemed effective as -of the date CC0 was applied by Affirmer to the Work. Should any part of the -License for any reason be judged legally invalid or ineffective under -applicable law, such partial invalidity or ineffectiveness shall not -invalidate the remainder of the License, and in such case Affirmer hereby -affirms that he or she will not (i) exercise any of his or her remaining -Copyright and Related Rights in the Work or (ii) assert any associated claims -and causes of action with respect to the Work, in either case contrary to -Affirmer's express Statement of Purpose. - -4. Limitations and Disclaimers. - - a. No trademark or patent rights held by Affirmer are waived, abandoned, - surrendered, licensed or otherwise affected by this document. - - b. Affirmer offers the Work as-is and makes no representations or warranties - of any kind concerning the Work, express, implied, statutory or otherwise, - including without limitation warranties of title, merchantability, fitness - for a particular purpose, non infringement, or the absence of latent or - other defects, accuracy, or the present or absence of errors, whether or not - discoverable, all to the greatest extent permissible under applicable law. - - c. Affirmer disclaims responsibility for clearing rights of other persons - that may apply to the Work or any use thereof, including without limitation - any person's Copyright and Related Rights in the Work. Further, Affirmer - disclaims responsibility for obtaining any necessary consents, permissions - or other rights required for any use of the Work. - - d. Affirmer understands and acknowledges that Creative Commons is not a - party to this document and has no duty or obligation with respect to this - CC0 or use of the Work. - -For more information, please see - diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/address.c b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/address.c deleted file mode 100644 index b956e9cb29..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/address.c +++ /dev/null @@ -1,91 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "utils.h" - -/* - * Specify which level of Merkle tree (the "layer") we're working on - */ -void set_layer_addr(uint32_t addr[8], uint32_t layer) { - ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; -} - -/* - * Specify which Merkle tree within the level (the "tree address") we're working on - */ -void set_tree_addr(uint32_t addr[8], uint64_t tree) { - ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); -} - -/* - * Specify the reason we'll use this address structure for, that is, what - * hash will we compute with it. This is used so that unrelated types of - * hashes don't accidentally get the same address structure. The type will be - * one of the SPX_ADDR_TYPE constants - */ -void set_type(uint32_t addr[8], uint32_t type) { - ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; -} - -/* - * Copy the layer and tree fields of the address structure. This is used - * when we're doing multiple types of hashes within the same Merkle tree - */ -void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { - memcpy( out, in, SPX_OFFSET_TREE + 8 ); -} - -/* These functions are used for OTS addresses. */ - -/* - * Specify which Merkle leaf we're working on; that is, which OTS keypair - * we're talking about. - */ -void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { - ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; -} - -/* - * Copy the layer, tree and keypair fields of the address structure. This is - * used when we're doing multiple things within the same OTS keypair - */ -void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { - memcpy( out, in, SPX_OFFSET_TREE + 8 ); - ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; -} - -/* - * Specify which Merkle chain within the OTS we're working with - * (the chain address) - */ -void set_chain_addr(uint32_t addr[8], uint32_t chain) { - ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; -} - -/* - * Specify where in the Merkle chain we are -* (the hash address) - */ -void set_hash_addr(uint32_t addr[8], uint32_t hash) { - ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; -} - -/* These functions are used for all hash tree addresses (including FORS). */ - -/* - * Specify the height of the node in the Merkle/FORS tree we are in - * (the tree height) - */ -void set_tree_height(uint32_t addr[8], uint32_t tree_height) { - ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; -} - -/* - * Specify the distance from the left edge of the node in the Merkle/FORS tree - * (the tree index) - */ -void set_tree_index(uint32_t addr[8], uint32_t tree_index) { - u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/address.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/address.h deleted file mode 100644 index 24a84eb40c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/address.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef SPX_ADDRESS_H -#define SPX_ADDRESS_H - -#include - -#include "params.h" - -/* The hash types that are passed to set_type */ -#define SPX_ADDR_TYPE_WOTS 0 -#define SPX_ADDR_TYPE_WOTSPK 1 -#define SPX_ADDR_TYPE_HASHTREE 2 -#define SPX_ADDR_TYPE_FORSTREE 3 -#define SPX_ADDR_TYPE_FORSPK 4 -#define SPX_ADDR_TYPE_WOTSPRF 5 -#define SPX_ADDR_TYPE_FORSPRF 6 - -#define set_layer_addr SPX_NAMESPACE(set_layer_addr) -void set_layer_addr(uint32_t addr[8], uint32_t layer); - -#define set_tree_addr SPX_NAMESPACE(set_tree_addr) -void set_tree_addr(uint32_t addr[8], uint64_t tree); - -#define set_type SPX_NAMESPACE(set_type) -void set_type(uint32_t addr[8], uint32_t type); - -/* Copies the layer and tree part of one address into the other */ -#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) -void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for WOTS and FORS addresses. */ - -#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) -void set_keypair_addr(uint32_t addr[8], uint32_t keypair); - -#define set_chain_addr SPX_NAMESPACE(set_chain_addr) -void set_chain_addr(uint32_t addr[8], uint32_t chain); - -#define set_hash_addr SPX_NAMESPACE(set_hash_addr) -void set_hash_addr(uint32_t addr[8], uint32_t hash); - -#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) -void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for all hash tree addresses (including FORS). */ - -#define set_tree_height SPX_NAMESPACE(set_tree_height) -void set_tree_height(uint32_t addr[8], uint32_t tree_height); - -#define set_tree_index SPX_NAMESPACE(set_tree_index) -void set_tree_index(uint32_t addr[8], uint32_t tree_index); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/api.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/api.h deleted file mode 100644 index 05d16a3ded..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/api.h +++ /dev/null @@ -1,77 +0,0 @@ -#ifndef PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_API_H -#define PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_API_H - -#include -#include - -#define PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_CRYPTO_ALGNAME "SPHINCS+-haraka-256f-simple" - -#define PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_CRYPTO_SECRETKEYBYTES 128 -#define PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_CRYPTO_PUBLICKEYBYTES 64 -#define PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_CRYPTO_BYTES 49856 - -#define PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_CRYPTO_SEEDBYTES 96 - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, - const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk); -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/context.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/context.h deleted file mode 100644 index f03446b9cb..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/context.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef SPX_CONTEXT_H -#define SPX_CONTEXT_H - -#include - -#include "immintrin.h" -#include "params.h" - -typedef struct { - uint8_t pub_seed[SPX_N]; - uint8_t sk_seed[SPX_N]; - - __m128i rc[40]; -} spx_ctx; - -#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) -void initialize_hash_function(spx_ctx *ctx); - -#define free_hash_function SPX_NAMESPACE(free_hash_function) -void free_hash_function(spx_ctx *ctx); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/context_haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/context_haraka.c deleted file mode 100644 index f1cd7e3664..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/context_haraka.c +++ /dev/null @@ -1,11 +0,0 @@ -#include "context.h" -#include "haraka.h" - -void initialize_hash_function(spx_ctx *ctx) { - tweak_constants(ctx); -} - -// we don't support heap-based haraka right now -void free_hash_function(spx_ctx *ctx) { - (void)ctx; // suppress unused variable warnings -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/fors.c b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/fors.c deleted file mode 100644 index f1b0639cfc..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/fors.c +++ /dev/null @@ -1,202 +0,0 @@ -#include -#include -#include - -#include "fors.h" - -#include "address.h" -#include "hash.h" -#include "hashx4.h" -#include "thash.h" -#include "thashx4.h" -#include "utils.h" -#include "utilsx4.h" - -static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, - uint32_t fors_leaf_addr[8]) { - prf_addr(sk, ctx, fors_leaf_addr); -} - -static void fors_gen_skx4(unsigned char *sk0, - unsigned char *sk1, - unsigned char *sk2, - unsigned char *sk3, const spx_ctx *ctx, - uint32_t fors_leaf_addrx4[4 * 8]) { - prf_addrx4(sk0, sk1, sk2, sk3, - ctx, fors_leaf_addrx4); -} - -static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, - const spx_ctx *ctx, - uint32_t fors_leaf_addr[8]) { - thash(leaf, sk, 1, ctx, fors_leaf_addr); -} - -static void fors_sk_to_leafx4(unsigned char *leaf0, - unsigned char *leaf1, - unsigned char *leaf2, - unsigned char *leaf3, - const unsigned char *sk0, - const unsigned char *sk1, - const unsigned char *sk2, - const unsigned char *sk3, - const spx_ctx *ctx, - uint32_t fors_leaf_addrx4[4 * 8]) { - thashx4(leaf0, leaf1, leaf2, leaf3, - sk0, sk1, sk2, sk3, - 1, ctx, fors_leaf_addrx4); -} - -struct fors_gen_leaf_info { - uint32_t leaf_addrx[4 * 8]; -}; - -static void fors_gen_leafx4(unsigned char *leaf, - const spx_ctx *ctx, - uint32_t addr_idx, void *info) { - struct fors_gen_leaf_info *fors_info = info; - uint32_t *fors_leaf_addrx4 = fors_info->leaf_addrx; - unsigned int j; - - /* Only set the parts that the caller doesn't set */ - for (j = 0; j < 4; j++) { - set_tree_index(fors_leaf_addrx4 + j * 8, addr_idx + j); - set_type(fors_leaf_addrx4 + j * 8, SPX_ADDR_TYPE_FORSPRF); - } - - fors_gen_skx4(leaf + 0 * SPX_N, - leaf + 1 * SPX_N, - leaf + 2 * SPX_N, - leaf + 3 * SPX_N, - ctx, fors_leaf_addrx4); - - for (j = 0; j < 4; j++) { - set_type(fors_leaf_addrx4 + j * 8, SPX_ADDR_TYPE_FORSTREE); - } - - fors_sk_to_leafx4(leaf + 0 * SPX_N, - leaf + 1 * SPX_N, - leaf + 2 * SPX_N, - leaf + 3 * SPX_N, - leaf + 0 * SPX_N, - leaf + 1 * SPX_N, - leaf + 2 * SPX_N, - leaf + 3 * SPX_N, - ctx, fors_leaf_addrx4); -} - -/** - * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - * Assumes indices has space for SPX_FORS_TREES integers. - */ -static void message_to_indices(uint32_t *indices, const unsigned char *m) { - unsigned int i, j; - unsigned int offset = 0; - - for (i = 0; i < SPX_FORS_TREES; i++) { - indices[i] = 0; - for (j = 0; j < SPX_FORS_HEIGHT; j++) { - indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); - offset++; - } - } -} - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -void fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]) { - uint32_t indices[SPX_FORS_TREES]; - unsigned char roots[SPX_FORS_TREES * SPX_N]; - uint32_t fors_tree_addr[4 * 8] = {0}; - struct fors_gen_leaf_info fors_info = {0}; - uint32_t *fors_leaf_addr = fors_info.leaf_addrx; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - for (i = 0; i < 4; i++) { - copy_keypair_addr(fors_tree_addr + 8 * i, fors_addr); - set_type(fors_tree_addr + 8 * i, SPX_ADDR_TYPE_FORSTREE); - copy_keypair_addr(fors_leaf_addr + 8 * i, fors_addr); - } - copy_keypair_addr(fors_pk_addr, fors_addr); - set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < SPX_FORS_TREES; i++) { - idx_offset = i * (1 << SPX_FORS_HEIGHT); - - set_tree_height(fors_tree_addr, 0); - set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Include the secret key part that produces the selected leaf node. */ - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); - fors_gen_sk(sig, ctx, fors_tree_addr); - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); - sig += SPX_N; - - /* Compute the authentication path for this leaf node. */ - treehashx4(roots + i * SPX_N, sig, ctx, - indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx4, - fors_tree_addr, &fors_info); - - sig += SPX_N * SPX_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); -} - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -void fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]) { - uint32_t indices[SPX_FORS_TREES]; - unsigned char roots[SPX_FORS_TREES * SPX_N]; - unsigned char leaf[SPX_N]; - uint32_t fors_tree_addr[8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - copy_keypair_addr(fors_tree_addr, fors_addr); - copy_keypair_addr(fors_pk_addr, fors_addr); - - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); - set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < SPX_FORS_TREES; i++) { - idx_offset = i * (1 << SPX_FORS_HEIGHT); - - set_tree_height(fors_tree_addr, 0); - set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Derive the leaf from the included secret key part. */ - fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); - sig += SPX_N; - - /* Derive the corresponding root node of this tree. */ - compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, - sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); - sig += SPX_N * SPX_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/fors.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/fors.h deleted file mode 100644 index 509140a178..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/fors.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef SPX_FORS_H -#define SPX_FORS_H - -#include - -#include "context.h" -#include "params.h" - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -#define fors_sign SPX_NAMESPACE(fors_sign) -void fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]); - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) -void fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/haraka.c deleted file mode 100644 index b414b691d7..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/haraka.c +++ /dev/null @@ -1,702 +0,0 @@ -/* -Plain C implementation of the Haraka256 and Haraka512 permutations. -*/ -#include -#include -#include -#include -#include - -#include "haraka.h" -#include "harakax4.h" -#include "utils.h" - -#define HARAKAS_RATE 32 - -#define u64 unsigned long -#define u128 __m128i - -#define LOAD(src) _mm_loadu_si128((u128 *)(src)) -#define STORE(dest,src) _mm_storeu_si128((u128 *)(dest),src) - -#define XOR128(a, b) _mm_xor_si128(a, b) - -#define AES2(s0, s1, rci) \ - s0 = _mm_aesenc_si128(s0, *(rci)); \ - (s1) = _mm_aesenc_si128(s1, *((rci) + 1)); \ - (s0) = _mm_aesenc_si128(s0, *((rci) + 2)); \ - (s1) = _mm_aesenc_si128(s1, *((rci) + 3)); - -#define AES2_4x(s0, s1, s2, s3, rci) \ - AES2((s0)[0], (s0)[1], rci); \ - AES2((s1)[0], (s1)[1], rci); \ - AES2((s2)[0], (s2)[1], rci); \ - AES2((s3)[0], (s3)[1], rci); - -#define AES4(s0, s1, s2, s3, rci) \ - s0 = _mm_aesenc_si128(s0, *(rci)); \ - (s1) = _mm_aesenc_si128(s1, *((rci) + 1)); \ - (s2) = _mm_aesenc_si128(s2, *((rci) + 2)); \ - (s3) = _mm_aesenc_si128(s3, *((rci) + 3)); \ - (s0) = _mm_aesenc_si128(s0, *((rci) + 4)); \ - (s1) = _mm_aesenc_si128(s1, *((rci) + 5)); \ - (s2) = _mm_aesenc_si128(s2, *((rci) + 6)); \ - (s3) = _mm_aesenc_si128(s3, *((rci) + 7)); - -#define AES4_4x(s0, s1, s2, s3, rci) \ - AES4((s0)[0], (s0)[1], (s0)[2], (s0)[3], rci); \ - AES4((s1)[0], (s1)[1], (s1)[2], (s1)[3], rci); \ - AES4((s2)[0], (s2)[1], (s2)[2], (s2)[3], rci); \ - AES4((s3)[0], (s3)[1], (s3)[2], (s3)[3], rci); - -#define MIX2(s0, s1) \ - tmp = _mm_unpacklo_epi32(s0, s1); \ - (s1) = _mm_unpackhi_epi32(s0, s1); \ - (s0) = tmp; - -#define MIX4(s0, s1, s2, s3) \ - tmp = _mm_unpacklo_epi32(s0, s1); \ - (s0) = _mm_unpackhi_epi32(s0, s1); \ - (s1) = _mm_unpacklo_epi32(s2, s3); \ - (s2) = _mm_unpackhi_epi32(s2, s3); \ - (s3) = _mm_unpacklo_epi32(s0, s2); \ - (s0) = _mm_unpackhi_epi32(s0, s2); \ - (s2) = _mm_unpackhi_epi32(s1, tmp); \ - (s1) = _mm_unpacklo_epi32(s1, tmp); - -#define TRUNCSTORE(out, s0, s1, s2, s3) \ - _mm_storeu_si128((u128 *)(out), \ - _mm_castpd_si128(_mm_shuffle_pd(_mm_castsi128_pd(s0), _mm_castsi128_pd(s1), 3))); \ - _mm_storeu_si128((u128 *)((out) + 16), \ - _mm_castpd_si128(_mm_shuffle_pd(_mm_castsi128_pd(s2), _mm_castsi128_pd(s3), 0))); - -static void load_haraka_constants(u128 *rc) { - rc[0] = _mm_set_epi32((int)0x0684704c, (int)0xe620c00a, (int)0xb2c5fef0, (int)0x75817b9d); - rc[1] = _mm_set_epi32((int)0x8b66b4e1, (int)0x88f3a06b, (int)0x640f6ba4, (int)0x2f08f717); - rc[2] = _mm_set_epi32((int)0x3402de2d, (int)0x53f28498, (int)0xcf029d60, (int)0x9f029114); - rc[3] = _mm_set_epi32((int)0x0ed6eae6, (int)0x2e7b4f08, (int)0xbbf3bcaf, (int)0xfd5b4f79); - rc[4] = _mm_set_epi32((int)0xcbcfb0cb, (int)0x4872448b, (int)0x79eecd1c, (int)0xbe397044); - rc[5] = _mm_set_epi32((int)0x7eeacdee, (int)0x6e9032b7, (int)0x8d5335ed, (int)0x2b8a057b); - rc[6] = _mm_set_epi32((int)0x67c28f43, (int)0x5e2e7cd0, (int)0xe2412761, (int)0xda4fef1b); - rc[7] = _mm_set_epi32((int)0x2924d9b0, (int)0xafcacc07, (int)0x675ffde2, (int)0x1fc70b3b); - rc[8] = _mm_set_epi32((int)0xab4d63f1, (int)0xe6867fe9, (int)0xecdb8fca, (int)0xb9d465ee); - rc[9] = _mm_set_epi32((int)0x1c30bf84, (int)0xd4b7cd64, (int)0x5b2a404f, (int)0xad037e33); - rc[10] = _mm_set_epi32((int)0xb2cc0bb9, (int)0x941723bf, (int)0x69028b2e, (int)0x8df69800); - rc[11] = _mm_set_epi32((int)0xfa0478a6, (int)0xde6f5572, (int)0x4aaa9ec8, (int)0x5c9d2d8a); - rc[12] = _mm_set_epi32((int)0xdfb49f2b, (int)0x6b772a12, (int)0x0efa4f2e, (int)0x29129fd4); - rc[13] = _mm_set_epi32((int)0x1ea10344, (int)0xf449a236, (int)0x32d611ae, (int)0xbb6a12ee); - rc[14] = _mm_set_epi32((int)0xaf044988, (int)0x4b050084, (int)0x5f9600c9, (int)0x9ca8eca6); - rc[15] = _mm_set_epi32((int)0x21025ed8, (int)0x9d199c4f, (int)0x78a2c7e3, (int)0x27e593ec); - rc[16] = _mm_set_epi32((int)0xbf3aaaf8, (int)0xa759c9b7, (int)0xb9282ecd, (int)0x82d40173); - rc[17] = _mm_set_epi32((int)0x6260700d, (int)0x6186b017, (int)0x37f2efd9, (int)0x10307d6b); - rc[18] = _mm_set_epi32((int)0x5aca45c2, (int)0x21300443, (int)0x81c29153, (int)0xf6fc9ac6); - rc[19] = _mm_set_epi32((int)0x9223973c, (int)0x226b68bb, (int)0x2caf92e8, (int)0x36d1943a); - rc[20] = _mm_set_epi32((int)0xd3bf9238, (int)0x225886eb, (int)0x6cbab958, (int)0xe51071b4); - rc[21] = _mm_set_epi32((int)0xdb863ce5, (int)0xaef0c677, (int)0x933dfddd, (int)0x24e1128d); - rc[22] = _mm_set_epi32((int)0xbb606268, (int)0xffeba09c, (int)0x83e48de3, (int)0xcb2212b1); - rc[23] = _mm_set_epi32((int)0x734bd3dc, (int)0xe2e4d19c, (int)0x2db91a4e, (int)0xc72bf77d); - rc[24] = _mm_set_epi32((int)0x43bb47c3, (int)0x61301b43, (int)0x4b1415c4, (int)0x2cb3924e); - rc[25] = _mm_set_epi32((int)0xdba775a8, (int)0xe707eff6, (int)0x03b231dd, (int)0x16eb6899); - rc[26] = _mm_set_epi32((int)0x6df3614b, (int)0x3c755977, (int)0x8e5e2302, (int)0x7eca472c); - rc[27] = _mm_set_epi32((int)0xcda75a17, (int)0xd6de7d77, (int)0x6d1be5b9, (int)0xb88617f9); - rc[28] = _mm_set_epi32((int)0xec6b43f0, (int)0x6ba8e9aa, (int)0x9d6c069d, (int)0xa946ee5d); - rc[29] = _mm_set_epi32((int)0xcb1e6950, (int)0xf957332b, (int)0xa2531159, (int)0x3bf327c1); - rc[30] = _mm_set_epi32((int)0x2cee0c75, (int)0x00da619c, (int)0xe4ed0353, (int)0x600ed0d9); - rc[31] = _mm_set_epi32((int)0xf0b1a5a1, (int)0x96e90cab, (int)0x80bbbabc, (int)0x63a4a350); - rc[32] = _mm_set_epi32((int)0xae3db102, (int)0x5e962988, (int)0xab0dde30, (int)0x938dca39); - rc[33] = _mm_set_epi32((int)0x17bb8f38, (int)0xd554a40b, (int)0x8814f3a8, (int)0x2e75b442); - rc[34] = _mm_set_epi32((int)0x34bb8a5b, (int)0x5f427fd7, (int)0xaeb6b779, (int)0x360a16f6); - rc[35] = _mm_set_epi32((int)0x26f65241, (int)0xcbe55438, (int)0x43ce5918, (int)0xffbaafde); - rc[36] = _mm_set_epi32((int)0x4ce99a54, (int)0xb9f3026a, (int)0xa2ca9cf7, (int)0x839ec978); - rc[37] = _mm_set_epi32((int)0xae51a51a, (int)0x1bdff7be, (int)0x40c06e28, (int)0x22901235); - rc[38] = _mm_set_epi32((int)0xa0c1613c, (int)0xba7ed22b, (int)0xc173bc0f, (int)0x48a659cf); - rc[39] = _mm_set_epi32((int)0x756acc03, (int)0x02288288, (int)0x4ad6bdfd, (int)0xe9c59da1); -} - -void tweak_constants(spx_ctx *ctx) { - int i; - unsigned char buf[40 * 16]; - - /* Use the standard constants to generate tweaked ones. */ - load_haraka_constants(ctx->rc); - - /* Constants for pk.seed */ - haraka_S(buf, 40 * 16, ctx->pub_seed, SPX_N, ctx); - - /* Tweak constants with the pub_seed */ - for (i = 0; i < 40; i++) { - ctx->rc[i] = LOAD(buf + i * 16); - } -} - -static void haraka_S_absorb(unsigned char *s, unsigned int r, - const unsigned char *m, unsigned long long mlen, - unsigned char p, const spx_ctx *ctx) { - unsigned long long i; - PQCLEAN_VLA(unsigned char, t, r); - - while (mlen >= r) { - // XOR block to state - STORE(s, XOR128(LOAD(s), LOAD(m))); - STORE(s + 16, XOR128(LOAD(s + 16), LOAD(m + 16))); - haraka512_perm(s, s, ctx); - 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; - STORE(s, XOR128(LOAD(s), LOAD(t))); - STORE(s + 16, XOR128(LOAD(s + 16), LOAD(t + 16))); -} - -static void haraka_S_absorb4x(unsigned char *s, - unsigned int r, - const unsigned char *m0, - const unsigned char *m1, - const unsigned char *m2, - const unsigned char *m3, - unsigned long long int mlen, - unsigned char p, - const spx_ctx *ctx) { - unsigned long long i; - PQCLEAN_VLA(unsigned char, t0, r); - PQCLEAN_VLA(unsigned char, t1, r); - PQCLEAN_VLA(unsigned char, t2, r); - PQCLEAN_VLA(unsigned char, t3, r); - - while (mlen >= r) { - // XOR block to state - STORE(s, XOR128(LOAD(s), LOAD(m0))); - STORE(s + 16, XOR128(LOAD(s + 16), LOAD(m0 + 16))); - STORE(s + 64, XOR128(LOAD(s + 64), LOAD(m1))); - STORE(s + 80, XOR128(LOAD(s + 80), LOAD(m1 + 16))); - STORE(s + 128, XOR128(LOAD(s + 128), LOAD(m2))); - STORE(s + 144, XOR128(LOAD(s + 144), LOAD(m2 + 16))); - STORE(s + 192, XOR128(LOAD(s + 192), LOAD(m3))); - STORE(s + 208, XOR128(LOAD(s + 208), LOAD(m3 + 16))); - - haraka512_perm_x4(s, s, ctx); - mlen -= r; - m0 += r; - m1 += r; - m2 += r; - m3 += r; - } - - for (i = 0; i < r; ++i) { - t0[i] = 0; - t1[i] = 0; - t2[i] = 0; - t3[i] = 0; - } - for (i = 0; i < mlen; ++i) { - t0[i] = m0[i]; - t1[i] = m1[i]; - t2[i] = m2[i]; - t3[i] = m3[i]; - } - - t0[i] = p; - t1[i] = p; - t2[i] = p; - t3[i] = p; - - t0[r - 1] |= 128; - t1[r - 1] |= 128; - t2[r - 1] |= 128; - t3[r - 1] |= 128; - - STORE(s, XOR128(LOAD(s), LOAD(t0))); - STORE(s + 16, XOR128(LOAD(s + 16), LOAD(t0 + 16))); - STORE(s + 64, XOR128(LOAD(s + 64), LOAD(t1))); - STORE(s + 80, XOR128(LOAD(s + 80), LOAD(t1 + 16))); - STORE(s + 128, XOR128(LOAD(s + 128), LOAD(t2))); - STORE(s + 144, XOR128(LOAD(s + 144), LOAD(t2 + 16))); - STORE(s + 192, XOR128(LOAD(s + 192), LOAD(t3))); - STORE(s + 208, XOR128(LOAD(s + 208), LOAD(t3 + 16))); -} - -static void haraka_S_squeezeblocks(unsigned char *h, unsigned long long nblocks, - unsigned char *s, unsigned int r, - const spx_ctx *ctx) { - while (nblocks > 0) { - haraka512_perm(s, s, ctx); - STORE(h, LOAD(s)); - STORE(h + 16, LOAD(s + 16)); - h += r; - nblocks--; - } -} - -static void haraka_S_squeezeblocks4x(unsigned char *h0, - unsigned char *h1, - unsigned char *h2, - unsigned char *h3, - unsigned long long nblocks, - unsigned char *s, - unsigned int r, - const spx_ctx *ctx) { - while (nblocks > 0) { - haraka512_perm_x4(s, s, ctx); - STORE(h0, LOAD(s)); - STORE(h0 + 16, LOAD(s + 16)); - STORE(h1, LOAD(s + 64)); - STORE(h1 + 16, LOAD(s + 80)); - STORE(h2, LOAD(s + 128)); - STORE(h2 + 16, LOAD(s + 144)); - STORE(h3, LOAD(s + 192)); - STORE(h3 + 16, LOAD(s + 208)); - h0 += r; - h1 += r; - h2 += r; - h3 += r; - nblocks--; - } -} - -void haraka_S_inc_init(uint8_t *s_inc) { - size_t i; - - for (i = 0; i < 64; i++) { - s_inc[i] = 0; - } - s_inc[64] = 0; -} - -void haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, - const spx_ctx *ctx) { - size_t i; - - /* Recall that s_inc[64] is the non-absorbed bytes xored into the state */ - while (mlen + s_inc[64] >= HARAKAS_RATE) { - for (i = 0; i < (size_t)(HARAKAS_RATE - s_inc[64]); i++) { - /* Take the i'th byte from message - xor with the s_inc[64] + i'th byte of the state */ - s_inc[s_inc[64] + i] ^= m[i]; - } - mlen -= (size_t)(HARAKAS_RATE - s_inc[64]); - m += HARAKAS_RATE - s_inc[64]; - s_inc[64] = 0; - - haraka512_perm(s_inc, s_inc, ctx); - } - - for (i = 0; i < mlen; i++) { - s_inc[s_inc[64] + i] ^= m[i]; - } - s_inc[64] += (uint8_t)mlen; -} - -void haraka_S_inc_finalize(uint8_t *s_inc) { - /* After haraka_S_inc_absorb, we are guaranteed that s_inc[64] < HARAKAS_RATE, - so we can always use one more byte for p in the current state. */ - s_inc[s_inc[64]] ^= 0x1F; - s_inc[HARAKAS_RATE - 1] ^= 128; - s_inc[64] = 0; -} - -void haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, - const spx_ctx *ctx) { - size_t i; - - /* First consume any bytes we still have sitting around */ - for (i = 0; i < outlen && i < s_inc[64]; i++) { - /* There are s_inc[64] bytes left, so r - s_inc[64] is the first - available byte. We consume from there, i.e., up to r. */ - out[i] = (uint8_t)s_inc[(HARAKAS_RATE - s_inc[64] + i)]; - } - out += i; - outlen -= i; - s_inc[64] -= (uint8_t)i; - - /* Then squeeze the remaining necessary blocks */ - while (outlen > 0) { - haraka512_perm(s_inc, s_inc, ctx); - - for (i = 0; i < outlen && i < HARAKAS_RATE; i++) { - out[i] = s_inc[i]; - } - out += i; - outlen -= i; - s_inc[64] = (uint8_t)(HARAKAS_RATE - i); - } -} - -void haraka_S(unsigned char *out, unsigned long long outlen, - const unsigned char *in, unsigned long long inlen, - const spx_ctx *ctx) { - unsigned long long i; - unsigned char s[64]; - unsigned char d[32]; - - for (i = 0; i < 64; i++) { - s[i] = 0; - } - haraka_S_absorb(s, HARAKAS_RATE, in, inlen, 0x1F, ctx); - - haraka_S_squeezeblocks(out, outlen / HARAKAS_RATE, s, HARAKAS_RATE, ctx); - out += (outlen / HARAKAS_RATE) * HARAKAS_RATE; - - if (outlen % HARAKAS_RATE) { - haraka_S_squeezeblocks(d, 1, s, HARAKAS_RATE, ctx); - for (i = 0; i < outlen % HARAKAS_RATE; i++) { - out[i] = d[i]; - } - } -} - -void haraka_Sx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned long long outlen, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - unsigned long long inlen, - const spx_ctx *ctx) { - unsigned long long i; - unsigned char s[64 * 4]; - unsigned char d0[32]; - unsigned char d1[32]; - unsigned char d2[32]; - unsigned char d3[32]; - - for (i = 0; i < 64 * 4; i++) { - s[i] = 0; - } - haraka_S_absorb4x(s, HARAKAS_RATE, in0, in1, in2, in3, inlen, 0x1F, ctx); - - haraka_S_squeezeblocks4x(out0, out1, out2, out3, outlen / HARAKAS_RATE, s, - HARAKAS_RATE, ctx); - out0 += (outlen / HARAKAS_RATE) * HARAKAS_RATE; - out1 += (outlen / HARAKAS_RATE) * HARAKAS_RATE; - out2 += (outlen / HARAKAS_RATE) * HARAKAS_RATE; - out3 += (outlen / HARAKAS_RATE) * HARAKAS_RATE; - - if (outlen % HARAKAS_RATE) { - haraka_S_squeezeblocks4x(d0, d1, d2, d3, 1, s, HARAKAS_RATE, ctx); - for (i = 0; i < outlen % HARAKAS_RATE; i++) { - out0[i] = d0[i]; - out1[i] = d1[i]; - out2[i] = d2[i]; - out3[i] = d3[i]; - } - } -} - -void haraka512_perm(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx) { - u128 s[4], tmp; - - s[0] = LOAD(in); - s[1] = LOAD(in + 16); - s[2] = LOAD(in + 32); - s[3] = LOAD(in + 48); - - AES4(s[0], s[1], s[2], s[3], ctx->rc); - MIX4(s[0], s[1], s[2], s[3]); - - AES4(s[0], s[1], s[2], s[3], ctx->rc + 8); - MIX4(s[0], s[1], s[2], s[3]); - - AES4(s[0], s[1], s[2], s[3], ctx->rc + 16); - MIX4(s[0], s[1], s[2], s[3]); - - AES4(s[0], s[1], s[2], s[3], ctx->rc + 24); - MIX4(s[0], s[1], s[2], s[3]); - - AES4(s[0], s[1], s[2], s[3], ctx->rc + 32); - MIX4(s[0], s[1], s[2], s[3]); - - STORE(out, s[0]); - STORE(out + 16, s[1]); - STORE(out + 32, s[2]); - STORE(out + 48, s[3]); -} - -void haraka512_perm_x4(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx) { - u128 s[4][4], tmp; - - s[0][0] = LOAD(in); - s[0][1] = LOAD(in + 16); - s[0][2] = LOAD(in + 32); - s[0][3] = LOAD(in + 48); - s[1][0] = LOAD(in + 64); - s[1][1] = LOAD(in + 80); - s[1][2] = LOAD(in + 96); - s[1][3] = LOAD(in + 112); - s[2][0] = LOAD(in + 128); - s[2][1] = LOAD(in + 144); - s[2][2] = LOAD(in + 160); - s[2][3] = LOAD(in + 176); - s[3][0] = LOAD(in + 192); - s[3][1] = LOAD(in + 208); - s[3][2] = LOAD(in + 224); - s[3][3] = LOAD(in + 240); - - AES4_4x(s[0], s[1], s[2], s[3], ctx->rc); - MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); - MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); - MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); - MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - - AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 8); - MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); - MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); - MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); - MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - - AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 16); - MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); - MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); - MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); - MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - - AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 24); - MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); - MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); - MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); - MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - - AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 32); - MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); - MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); - MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); - MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - - STORE(out, s[0][0]); - STORE(out + 16, s[0][1]); - STORE(out + 32, s[0][2]); - STORE(out + 48, s[0][3]); - STORE(out + 64, s[1][0]); - STORE(out + 80, s[1][1]); - STORE(out + 96, s[1][2]); - STORE(out + 112, s[1][3]); - STORE(out + 128, s[2][0]); - STORE(out + 144, s[2][1]); - STORE(out + 160, s[2][2]); - STORE(out + 176, s[2][3]); - STORE(out + 192, s[3][0]); - STORE(out + 208, s[3][1]); - STORE(out + 224, s[3][2]); - STORE(out + 240, s[3][3]); -} - -void haraka512(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx) { - u128 s[4], tmp; - - s[0] = LOAD(in); - s[1] = LOAD(in + 16); - s[2] = LOAD(in + 32); - s[3] = LOAD(in + 48); - - AES4(s[0], s[1], s[2], s[3], ctx->rc); - MIX4(s[0], s[1], s[2], s[3]); - - AES4(s[0], s[1], s[2], s[3], ctx->rc + 8); - MIX4(s[0], s[1], s[2], s[3]); - - AES4(s[0], s[1], s[2], s[3], ctx->rc + 16); - MIX4(s[0], s[1], s[2], s[3]); - - AES4(s[0], s[1], s[2], s[3], ctx->rc + 24); - MIX4(s[0], s[1], s[2], s[3]); - - AES4(s[0], s[1], s[2], s[3], ctx->rc + 32); - MIX4(s[0], s[1], s[2], s[3]); - - s[0] = XOR128(s[0], LOAD(in)); - s[1] = XOR128(s[1], LOAD(in + 16)); - s[2] = XOR128(s[2], LOAD(in + 32)); - s[3] = XOR128(s[3], LOAD(in + 48)); - - // truncate and store result - TRUNCSTORE(out, s[0], s[1], s[2], s[3]); -} - -void haraka512x4(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx) { - u128 s[4][4], tmp; - - s[0][0] = LOAD(in); - s[0][1] = LOAD(in + 16); - s[0][2] = LOAD(in + 32); - s[0][3] = LOAD(in + 48); - s[1][0] = LOAD(in + 64); - s[1][1] = LOAD(in + 80); - s[1][2] = LOAD(in + 96); - s[1][3] = LOAD(in + 112); - s[2][0] = LOAD(in + 128); - s[2][1] = LOAD(in + 144); - s[2][2] = LOAD(in + 160); - s[2][3] = LOAD(in + 176); - s[3][0] = LOAD(in + 192); - s[3][1] = LOAD(in + 208); - s[3][2] = LOAD(in + 224); - s[3][3] = LOAD(in + 240); - - AES4_4x(s[0], s[1], s[2], s[3], ctx->rc); - MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); - MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); - MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); - MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - - AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 8); - MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); - MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); - MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); - MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - - AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 16); - MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); - MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); - MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); - MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - - AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 24); - MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); - MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); - MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); - MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - - AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 32); - MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); - MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); - MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); - MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - - s[0][0] = XOR128(s[0][0], LOAD(in)); - s[0][1] = XOR128(s[0][1], LOAD(in + 16)); - s[0][2] = XOR128(s[0][2], LOAD(in + 32)); - s[0][3] = XOR128(s[0][3], LOAD(in + 48)); - s[1][0] = XOR128(s[1][0], LOAD(in + 64)); - s[1][1] = XOR128(s[1][1], LOAD(in + 80)); - s[1][2] = XOR128(s[1][2], LOAD(in + 96)); - s[1][3] = XOR128(s[1][3], LOAD(in + 112)); - s[2][0] = XOR128(s[2][0], LOAD(in + 128)); - s[2][1] = XOR128(s[2][1], LOAD(in + 144)); - s[2][2] = XOR128(s[2][2], LOAD(in + 160)); - s[2][3] = XOR128(s[2][3], LOAD(in + 176)); - s[3][0] = XOR128(s[3][0], LOAD(in + 192)); - s[3][1] = XOR128(s[3][1], LOAD(in + 208)); - s[3][2] = XOR128(s[3][2], LOAD(in + 224)); - s[3][3] = XOR128(s[3][3], LOAD(in + 240)); - - TRUNCSTORE(out, s[0][0], s[0][1], s[0][2], s[0][3]); - TRUNCSTORE((out + 32), s[1][0], s[1][1], s[1][2], s[1][3]); - TRUNCSTORE((out + 64), s[2][0], s[2][1], s[2][2], s[2][3]); - TRUNCSTORE((out + 96), s[3][0], s[3][1], s[3][2], s[3][3]); -} - -void haraka256(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx) { - u128 s[2], tmp; - - s[0] = LOAD(in); - s[1] = LOAD(in + 16); - - AES2(s[0], s[1], ctx->rc); - MIX2(s[0], s[1]); - - AES2(s[0], s[1], ctx->rc + 4); - MIX2(s[0], s[1]); - - AES2(s[0], s[1], ctx->rc + 8); - MIX2(s[0], s[1]); - - AES2(s[0], s[1], ctx->rc + 12); - MIX2(s[0], s[1]); - - AES2(s[0], s[1], ctx->rc + 16); - MIX2(s[0], s[1]); - - s[0] = XOR128(s[0], LOAD(in)); - s[1] = XOR128(s[1], LOAD(in + 16)); - - STORE(out, s[0]); - STORE(out + 16, s[1]); -} - -void haraka256x4(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx) { - u128 s[4][2], tmp; - - s[0][0] = LOAD(in); - s[0][1] = LOAD(in + 16); - s[1][0] = LOAD(in + 32); - s[1][1] = LOAD(in + 48); - s[2][0] = LOAD(in + 64); - s[2][1] = LOAD(in + 80); - s[3][0] = LOAD(in + 96); - s[3][1] = LOAD(in + 112); - - // Round 1 - AES2_4x(s[0], s[1], s[2], s[3], ctx->rc); - - MIX2(s[0][0], s[0][1]); - MIX2(s[1][0], s[1][1]); - MIX2(s[2][0], s[2][1]); - MIX2(s[3][0], s[3][1]); - - // Round 2 - AES2_4x(s[0], s[1], s[2], s[3], ctx->rc + 4); - - MIX2(s[0][0], s[0][1]); - MIX2(s[1][0], s[1][1]); - MIX2(s[2][0], s[2][1]); - MIX2(s[3][0], s[3][1]); - - // Round 3 - AES2_4x(s[0], s[1], s[2], s[3], ctx->rc + 8); - - MIX2(s[0][0], s[0][1]); - MIX2(s[1][0], s[1][1]); - MIX2(s[2][0], s[2][1]); - MIX2(s[3][0], s[3][1]); - - // Round 4 - AES2_4x(s[0], s[1], s[2], s[3], ctx->rc + 12); - - MIX2(s[0][0], s[0][1]); - MIX2(s[1][0], s[1][1]); - MIX2(s[2][0], s[2][1]); - MIX2(s[3][0], s[3][1]); - - // Round 5 - AES2_4x(s[0], s[1], s[2], s[3], ctx->rc + 16); - - MIX2(s[0][0], s[0][1]); - MIX2(s[1][0], s[1][1]); - MIX2(s[2][0], s[2][1]); - MIX2(s[3][0], s[3][1]); - - // Feed Forward - s[0][0] = _mm_xor_si128(s[0][0], LOAD(in)); - s[0][1] = _mm_xor_si128(s[0][1], LOAD(in + 16)); - s[1][0] = _mm_xor_si128(s[1][0], LOAD(in + 32)); - s[1][1] = _mm_xor_si128(s[1][1], LOAD(in + 48)); - s[2][0] = _mm_xor_si128(s[2][0], LOAD(in + 64)); - s[2][1] = _mm_xor_si128(s[2][1], LOAD(in + 80)); - s[3][0] = _mm_xor_si128(s[3][0], LOAD(in + 96)); - s[3][1] = _mm_xor_si128(s[3][1], LOAD(in + 112)); - - STORE(out, s[0][0]); - STORE(out + 16, s[0][1]); - STORE(out + 32, s[1][0]); - STORE(out + 48, s[1][1]); - STORE(out + 64, s[2][0]); - STORE(out + 80, s[2][1]); - STORE(out + 96, s[3][0]); - STORE(out + 112, s[3][1]); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/haraka.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/haraka.h deleted file mode 100644 index 737cb6065f..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/haraka.h +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef SPX_HARAKA_H -#define SPX_HARAKA_H - -#include "context.h" -#include "params.h" - -/* Tweak constants with seed */ -#define tweak_constants SPX_NAMESPACE(tweak_constants) -void tweak_constants(spx_ctx *ctx); - -/* Haraka Sponge */ -#define haraka_S_inc_init SPX_NAMESPACE(haraka_S_inc_init) -void haraka_S_inc_init(uint8_t *s_inc); -#define haraka_S_inc_absorb SPX_NAMESPACE(haraka_S_inc_absorb) -void haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, - const spx_ctx *ctx); -#define haraka_S_inc_finalize SPX_NAMESPACE(haraka_S_inc_finalize) -void haraka_S_inc_finalize(uint8_t *s_inc); -#define haraka_S_inc_squeeze SPX_NAMESPACE(haraka_S_inc_squeeze) -void haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, - const spx_ctx *ctx); -#define haraka_S SPX_NAMESPACE(haraka_S) -void haraka_S(unsigned char *out, unsigned long long outlen, - const unsigned char *in, unsigned long long inlen, - const spx_ctx *ctx); - -/* Applies the 512-bit Haraka permutation to in. */ -#define haraka512_perm SPX_NAMESPACE(haraka512_perm) -void haraka512_perm(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx); - -/* Implementation of Haraka-512 */ -#define haraka512 SPX_NAMESPACE(haraka512) -void haraka512(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx); - -/* Implementation of Haraka-256 */ -#define haraka256 SPX_NAMESPACE(haraka256) -void haraka256(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/haraka_offsets.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/haraka_offsets.h deleted file mode 100644 index 7c062272a0..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/haraka_offsets.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef HARAKA_OFFSETS_H_ -#define HARAKA_OFFSETS_H_ - -/* - * Offsets of various fields in the address structure when we use Haraka as - * the Sphincs+ hash function - */ - -#define SPX_OFFSET_LAYER 3 /* The byte used to specify the Merkle tree layer */ -#define SPX_OFFSET_TREE 8 /* The start of the 8 byte field used to specify the tree */ -#define SPX_OFFSET_TYPE 19 /* The byte used to specify the hash type (reason) */ -#define SPX_OFFSET_KP_ADDR2 22 /* The high byte used to specify the key pair (which one-time signature) */ -#define SPX_OFFSET_KP_ADDR1 23 /* The low byte used to specify the key pair */ -#define SPX_OFFSET_CHAIN_ADDR 27 /* The byte used to specify the chain address (which Winternitz chain) */ -#define SPX_OFFSET_HASH_ADDR 31 /* The byte used to specify the hash address (where in the Winternitz chain) */ -#define SPX_OFFSET_TREE_HGT 27 /* The byte used to specify the height of this node in the FORS or Merkle tree */ -#define SPX_OFFSET_TREE_INDEX 28 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ - -#define SPX_HARAKA 1 - -#endif /* HARAKA_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/harakax4.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/harakax4.h deleted file mode 100644 index eadc69aa48..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/harakax4.h +++ /dev/null @@ -1,36 +0,0 @@ -#ifndef SPX_HARAKAX4_H -#define SPX_HARAKAX4_H - -#include "context.h" -#include "params.h" - -/* Haraka Sponge */ -#define haraka_Sx4 SPX_NAMESPACE(haraka_Sx4) -void haraka_Sx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned long long outlen, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - unsigned long long inlen, - const spx_ctx *ctx); - -/* Applies the 512-bit Haraka permutation x4 to in. */ -#define haraka512_perm_x4 SPX_NAMESPACE(haraka512_perm_x4) -void haraka512_perm_x4(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx); - -/* Implementation of Haraka-512 x4*/ -#define haraka512x4 SPX_NAMESPACE(haraka512x4) -void haraka512x4(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx); - -/* Implementation of Haraka-256 x4 */ -#define haraka256x4 SPX_NAMESPACE(haraka256x4) -void haraka256x4(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/hash.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/hash.h deleted file mode 100644 index f7c87d4c3c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/hash.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef SPX_HASH_H -#define SPX_HASH_H - -#include -#include - -#include "context.h" -#include "params.h" - -#define prf_addr SPX_NAMESPACE(prf_addr) -void prf_addr(unsigned char *out, const spx_ctx *ctx, - const uint32_t addr[8]); - -#define gen_message_random SPX_NAMESPACE(gen_message_random) -void gen_message_random(unsigned char *R, const unsigned char *sk_prf, - const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx); - -#define hash_message SPX_NAMESPACE(hash_message) -void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx); - - - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/hash_haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/hash_haraka.c deleted file mode 100644 index 750a67423b..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/hash_haraka.c +++ /dev/null @@ -1,81 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "utils.h" - -#include "haraka.h" -#include "hash.h" - -/* - * Computes PRF(key, addr), given a secret key of SPX_N bytes and an address - */ -void prf_addr(unsigned char *out, const spx_ctx *ctx, - const uint32_t addr[8]) { - /* Since SPX_N may be smaller than 32, we need temporary buffers. */ - unsigned char outbuf[32]; - unsigned char buf[64] = {0}; - - memcpy(buf, addr, SPX_ADDR_BYTES); - memcpy(buf + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); - - haraka512(outbuf, (const void *)buf, ctx); - memcpy(out, outbuf, SPX_N); -} - -/** - * Computes the message-dependent randomness R, using a secret seed and an - * optional randomization value as well as the message. - */ -void gen_message_random(unsigned char *R, const unsigned char *sk_prf, - const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx) { - uint8_t s_inc[65]; - - haraka_S_inc_init(s_inc); - haraka_S_inc_absorb(s_inc, sk_prf, SPX_N, ctx); - haraka_S_inc_absorb(s_inc, optrand, SPX_N, ctx); - haraka_S_inc_absorb(s_inc, m, mlen, ctx); - haraka_S_inc_finalize(s_inc); - haraka_S_inc_squeeze(R, SPX_N, s_inc, ctx); -} - -/** - * Computes the message hash using R, the public key, and the message. - * Outputs the message digest and the index of the leaf. The index is split in - * the tree index and the leaf index, for convenient copying to an address. - */ -void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx) { -#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) -#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) -#define SPX_LEAF_BITS SPX_TREE_HEIGHT -#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) -#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) - - unsigned char buf[SPX_DGST_BYTES]; - unsigned char *bufp = buf; - uint8_t s_inc[65]; - - haraka_S_inc_init(s_inc); - haraka_S_inc_absorb(s_inc, R, SPX_N, ctx); - haraka_S_inc_absorb(s_inc, pk + SPX_N, SPX_N, ctx); // Only absorb root part of pk - haraka_S_inc_absorb(s_inc, m, mlen, ctx); - haraka_S_inc_finalize(s_inc); - haraka_S_inc_squeeze(buf, SPX_DGST_BYTES, s_inc, ctx); - - memcpy(digest, bufp, SPX_FORS_MSG_BYTES); - bufp += SPX_FORS_MSG_BYTES; - - - *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); - *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); - bufp += SPX_TREE_BYTES; - - *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); - *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/hash_harakax4.c b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/hash_harakax4.c deleted file mode 100644 index cfa5162d79..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/hash_harakax4.c +++ /dev/null @@ -1,35 +0,0 @@ -#include -#include - -#include "address.h" -#include "harakax4.h" -#include "hashx4.h" -#include "params.h" - -/* - * 4-way parallel version of prf_addr; takes 4x as much input and output - */ -#define prf_addrx4 SPX_NAMESPACE(prf_addrx4) -void prf_addrx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const spx_ctx *ctx, - const uint32_t addrx4[4 * 8]) { - unsigned char bufx4[4 * 64] = {0}; - /* Since SPX_N may be smaller than 32, we need temporary buffers. */ - unsigned char outbuf[4 * 32]; - unsigned int i; - - for (i = 0; i < 4; i++) { - memcpy(bufx4 + i * 64, addrx4 + i * 8, SPX_ADDR_BYTES); - memcpy(bufx4 + i * 64 + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); - } - - haraka512x4(outbuf, bufx4, ctx); - - memcpy(out0, outbuf, SPX_N); - memcpy(out1, outbuf + 32, SPX_N); - memcpy(out2, outbuf + 64, SPX_N); - memcpy(out3, outbuf + 96, SPX_N); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/hashx4.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/hashx4.h deleted file mode 100644 index 3751a0ebd0..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/hashx4.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef SPX_HASHX4_H -#define SPX_HASHX4_H - -#include - -#include "context.h" -#include "params.h" - -#define prf_addrx4 SPX_NAMESPACE(prf_addrx4) -void prf_addrx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const spx_ctx *ctx, - const uint32_t addrx4[4 * 8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/merkle.c b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/merkle.c deleted file mode 100644 index f57811c1ac..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/merkle.c +++ /dev/null @@ -1,64 +0,0 @@ -#include -#include - -#include "merkle.h" - -#include "address.h" -#include "params.h" -#include "utils.h" -#include "utilsx4.h" -#include "wots.h" -#include "wotsx4.h" - -/* - * This generates a Merkle signature (WOTS signature followed by the Merkle - * authentication path). - */ -void merkle_sign(uint8_t *sig, unsigned char *root, - const spx_ctx *ctx, - uint32_t wots_addr[8], uint32_t tree_addr[8], - uint32_t idx_leaf) { - unsigned char *auth_path = sig + SPX_WOTS_BYTES; - uint32_t tree_addrx4[4 * 8] = { 0 }; - int j; - struct leaf_info_x4 info = { 0 }; - unsigned steps[ SPX_WOTS_LEN ]; - - info.wots_sig = sig; - chain_lengths(steps, root); - info.wots_steps = steps; - - for (j = 0; j < 4; j++) { - set_type(&tree_addrx4[8 * j], SPX_ADDR_TYPE_HASHTREE); - set_type(&info.leaf_addr[8 * j], SPX_ADDR_TYPE_WOTS); - set_type(&info.pk_addr[8 * j], SPX_ADDR_TYPE_WOTSPK); - copy_subtree_addr(&tree_addrx4[8 * j], tree_addr); - copy_subtree_addr(&info.leaf_addr[8 * j], wots_addr); - copy_subtree_addr(&info.pk_addr[8 * j], wots_addr); - } - - info.wots_sign_leaf = idx_leaf; - - treehashx4(root, auth_path, ctx, - idx_leaf, 0, - SPX_TREE_HEIGHT, - wots_gen_leafx4, - tree_addrx4, &info); -} - -/* Compute root node of the top-most subtree. */ -void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { - /* We do not need the auth path in key generation, but it simplifies the - code to have just one treehash routine that computes both root and path - in one function. */ - unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; - uint32_t top_tree_addr[8] = {0}; - uint32_t wots_addr[8] = {0}; - - set_layer_addr(top_tree_addr, SPX_D - 1); - set_layer_addr(wots_addr, SPX_D - 1); - - merkle_sign(auth_path, root, ctx, - wots_addr, top_tree_addr, - ~0U /* ~0 means "don't bother generating an auth path */ ); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/merkle.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/merkle.h deleted file mode 100644 index 769cf2e970..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/merkle.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef MERKLE_H_ -#define MERKLE_H_ - -#include - -#include "context.h" -#include "params.h" - -/* Generate a Merkle signature (WOTS signature followed by the Merkle */ -/* authentication path) */ -#define merkle_sign SPX_NAMESPACE(merkle_sign) -void merkle_sign(uint8_t *sig, unsigned char *root, - const spx_ctx *ctx, - uint32_t wots_addr[8], uint32_t tree_addr[8], - uint32_t idx_leaf); - -/* Compute the root node of the top-most subtree. */ -#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) -void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); - -#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/nistapi.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/nistapi.h deleted file mode 100644 index 3cb71afad4..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/nistapi.h +++ /dev/null @@ -1,87 +0,0 @@ -#ifndef SPX_API_H -#define SPX_API_H - -#include -#include - -#include "params.h" - -#define CRYPTO_ALGNAME "SPHINCS+" - -#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES -#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES -#define CRYPTO_BYTES SPX_BYTES -#define CRYPTO_SEEDBYTES (3*SPX_N) - -/* - * Returns the length of a secret key, in bytes - */ -#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) -size_t crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) -size_t crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) -size_t crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) -size_t crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) -int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) -int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) -int crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) -int crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -#define crypto_sign SPX_NAMESPACE(crypto_sign) -int crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) -int crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/params.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/params.h deleted file mode 100644 index 21cd543162..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/params.h +++ /dev/null @@ -1,56 +0,0 @@ -#ifndef SPX_PARAMS_H -#define SPX_PARAMS_H - -#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_##s - -/* Hash output length in bytes. */ -#define SPX_N 32 -/* Height of the hypertree. */ -#define SPX_FULL_HEIGHT 68 -/* Number of subtree layer. */ -#define SPX_D 17 -/* FORS tree dimensions. */ -#define SPX_FORS_HEIGHT 9 -#define SPX_FORS_TREES 35 -/* Winternitz parameter, */ -#define SPX_WOTS_W 16 - -/* The hash function is defined by linking a different hash.c file, as opposed - to setting a #define constant. */ - -/* For clarity */ -#define SPX_ADDR_BYTES 32 - -/* WOTS parameters. */ -#define SPX_WOTS_LOGW 4 - -#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) - -/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#define SPX_WOTS_LEN2 3 - -#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) -#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) -#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES - -/* Subtree size. */ -#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) - -//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT -// #error SPX_D should always divide SPX_FULL_HEIGHT -//#endif - -/* FORS parameters. */ -#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) -#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) -#define SPX_FORS_PK_BYTES SPX_N - -/* Resulting SPX sizes. */ -#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ - SPX_FULL_HEIGHT * SPX_N) -#define SPX_PK_BYTES (2 * SPX_N) -#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) - -#include "haraka_offsets.h" - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/sign.c b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/sign.c deleted file mode 100644 index 9d0c7d1b22..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/sign.c +++ /dev/null @@ -1,286 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "context.h" -#include "fors.h" -#include "hash.h" -#include "merkle.h" -#include "nistapi.h" -#include "params.h" -#include "randombytes.h" -#include "thash.h" -#include "utils.h" -#include "wots.h" - -/* - * Returns the length of a secret key, in bytes - */ -size_t crypto_sign_secretkeybytes(void) { - return CRYPTO_SECRETKEYBYTES; -} - -/* - * Returns the length of a public key, in bytes - */ -size_t crypto_sign_publickeybytes(void) { - return CRYPTO_PUBLICKEYBYTES; -} - -/* - * Returns the length of a signature, in bytes - */ -size_t crypto_sign_bytes(void) { - return CRYPTO_BYTES; -} - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t crypto_sign_seedbytes(void) { - return CRYPTO_SEEDBYTES; -} - -/* - * Generates an SPX key pair given a seed of length - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed) { - spx_ctx ctx; - - /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ - memcpy(sk, seed, CRYPTO_SEEDBYTES); - - memcpy(pk, sk + 2 * SPX_N, SPX_N); - - memcpy(ctx.pub_seed, pk, SPX_N); - memcpy(ctx.sk_seed, sk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - /* Compute root node of the top-most subtree. */ - merkle_gen_root(sk + 3 * SPX_N, &ctx); - - // cleanup - free_hash_function(&ctx); - - memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); - - return 0; -} - -/* - * Generates an SPX key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { - uint8_t seed[CRYPTO_SEEDBYTES]; - randombytes(seed, CRYPTO_SEEDBYTES); - crypto_sign_seed_keypair(pk, sk, seed); - - return 0; -} - -/** - * Returns an array containing a detached signature. - */ -int crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - spx_ctx ctx; - - const uint8_t *sk_prf = sk + SPX_N; - const uint8_t *pk = sk + 2 * SPX_N; - - uint8_t optrand[SPX_N]; - uint8_t mhash[SPX_FORS_MSG_BYTES]; - uint8_t root[SPX_N]; - uint32_t i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - - memcpy(ctx.sk_seed, sk, SPX_N); - memcpy(ctx.pub_seed, pk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - set_type(wots_addr, SPX_ADDR_TYPE_WOTS); - set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); - - /* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ - randombytes(optrand, SPX_N); - /* Compute the digest randomization value. */ - gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); - - /* Derive the message digest and leaf index from R, PK and M. */ - hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); - sig += SPX_N; - - set_tree_addr(wots_addr, tree); - set_keypair_addr(wots_addr, idx_leaf); - - /* Sign the message hash using FORS. */ - fors_sign(sig, root, mhash, &ctx, wots_addr); - sig += SPX_FORS_BYTES; - - for (i = 0; i < SPX_D; i++) { - set_layer_addr(tree_addr, i); - set_tree_addr(tree_addr, tree); - - copy_subtree_addr(wots_addr, tree_addr); - set_keypair_addr(wots_addr, idx_leaf); - - merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); - sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); - tree = tree >> SPX_TREE_HEIGHT; - } - - free_hash_function(&ctx); - - *siglen = SPX_BYTES; - - return 0; -} - -/** - * Verifies a detached signature and message under a given public key. - */ -int crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk) { - spx_ctx ctx; - const uint8_t *pub_root = pk + SPX_N; - uint8_t mhash[SPX_FORS_MSG_BYTES]; - uint8_t wots_pk[SPX_WOTS_BYTES]; - uint8_t root[SPX_N]; - uint8_t leaf[SPX_N]; - unsigned int i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - if (siglen != SPX_BYTES) { - return -1; - } - - memcpy(ctx.pub_seed, pk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - set_type(wots_addr, SPX_ADDR_TYPE_WOTS); - set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); - set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); - - /* Derive the message digest and leaf index from R || PK || M. */ - /* The additional SPX_N is a result of the hash domain separator. */ - hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); - sig += SPX_N; - - /* Layer correctly defaults to 0, so no need to set_layer_addr */ - set_tree_addr(wots_addr, tree); - set_keypair_addr(wots_addr, idx_leaf); - - fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); - sig += SPX_FORS_BYTES; - - /* For each subtree.. */ - for (i = 0; i < SPX_D; i++) { - set_layer_addr(tree_addr, i); - set_tree_addr(tree_addr, tree); - - copy_subtree_addr(wots_addr, tree_addr); - set_keypair_addr(wots_addr, idx_leaf); - - copy_keypair_addr(wots_pk_addr, wots_addr); - - /* The WOTS public key is only correct if the signature was correct. */ - /* Initially, root is the FORS pk, but on subsequent iterations it is - the root of the subtree below the currently processed subtree. */ - wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); - sig += SPX_WOTS_BYTES; - - /* Compute the leaf node using the WOTS public key. */ - thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); - - /* Compute the root node of this subtree. */ - compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, - &ctx, tree_addr); - sig += SPX_TREE_HEIGHT * SPX_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); - tree = tree >> SPX_TREE_HEIGHT; - } - - // cleanup - free_hash_function(&ctx); - - /* Check if the root node equals the root node in the public key. */ - if (memcmp(root, pub_root, SPX_N) != 0) { - return -1; - } - - return 0; -} - - -/** - * Returns an array containing the signature followed by the message. - */ -int crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk) { - size_t siglen; - - crypto_sign_signature(sm, &siglen, m, mlen, sk); - - memmove(sm + SPX_BYTES, m, mlen); - *smlen = siglen + mlen; - - return 0; -} - -/** - * Verifies a given signature-message pair under a given public key. - */ -int crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk) { - /* The API caller does not necessarily know what size a signature should be - but SPHINCS+ signatures are always exactly SPX_BYTES. */ - if (smlen < SPX_BYTES) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - *mlen = smlen - SPX_BYTES; - - if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - /* If verification was successful, move the message to the right place. */ - memmove(m, sm + SPX_BYTES, *mlen); - - return 0; -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/thash.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/thash.h deleted file mode 100644 index 8687ccfb4d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/thash.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef SPX_THASH_H -#define SPX_THASH_H - -#include "context.h" -#include "params.h" - -#include - -#define thash SPX_NAMESPACE(thash) -void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/thash_haraka_simple.c b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/thash_haraka_simple.c deleted file mode 100644 index 207777bf8d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/thash_haraka_simple.c +++ /dev/null @@ -1,36 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "thash.h" -#include "utils.h" - -#include "haraka.h" - -/** - * Takes an array of inblocks concatenated arrays of SPX_N bytes. - */ -void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]) { - PQCLEAN_VLA(uint8_t, buf, SPX_ADDR_BYTES + inblocks * SPX_N); - unsigned char outbuf[32]; - unsigned char buf_tmp[64]; - - if (inblocks == 1) { - /* F function */ - /* Since SPX_N may be smaller than 32, we need a temporary buffer. */ - memset(buf_tmp, 0, 64); - memcpy(buf_tmp, addr, 32); - memcpy(buf_tmp + SPX_ADDR_BYTES, in, SPX_N); - - haraka512(outbuf, buf_tmp, ctx); - memcpy(out, outbuf, SPX_N); - } else { - /* All other tweakable hashes*/ - memcpy(buf, addr, 32); - memcpy(buf + SPX_ADDR_BYTES, in, inblocks * SPX_N); - - haraka_S(out, SPX_N, buf, SPX_ADDR_BYTES + inblocks * SPX_N, ctx); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/thash_haraka_simplex4.c b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/thash_haraka_simplex4.c deleted file mode 100644 index 2ee763d7d9..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/thash_haraka_simplex4.c +++ /dev/null @@ -1,67 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "thashx4.h" - -#include "harakax4.h" - -#include "utils.h" - -/** - * 4-way parallel version of thash; takes 4x as much input and output - */ -#define thashx4 SPX_NAMESPACE(thashx4) -void thashx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addrx4[4 * 8]) { - PQCLEAN_VLA(unsigned char, buf0, SPX_ADDR_BYTES + inblocks * SPX_N); - PQCLEAN_VLA(unsigned char, buf1, SPX_ADDR_BYTES + inblocks * SPX_N); - PQCLEAN_VLA(unsigned char, buf2, SPX_ADDR_BYTES + inblocks * SPX_N); - PQCLEAN_VLA(unsigned char, buf3, SPX_ADDR_BYTES + inblocks * SPX_N); - unsigned char outbuf[32 * 4]; - unsigned char buf_tmp[64 * 4]; - - if (inblocks == 1) { - memset(buf_tmp, 0, 64 * 4); - - memcpy(buf_tmp, addrx4 + 0 * 8, 32); - memcpy(buf_tmp + 64, addrx4 + 1 * 8, 32); - memcpy(buf_tmp + 128, addrx4 + 2 * 8, 32); - memcpy(buf_tmp + 192, addrx4 + 3 * 8, 32); - - memcpy(buf_tmp + SPX_ADDR_BYTES, in0, SPX_N); - memcpy(buf_tmp + SPX_ADDR_BYTES + 64, in1, SPX_N); - memcpy(buf_tmp + SPX_ADDR_BYTES + 128, in2, SPX_N); - memcpy(buf_tmp + SPX_ADDR_BYTES + 192, in3, SPX_N); - - haraka512x4(outbuf, buf_tmp, ctx); - - memcpy(out0, outbuf, SPX_N); - memcpy(out1, outbuf + 32, SPX_N); - memcpy(out2, outbuf + 64, SPX_N); - memcpy(out3, outbuf + 96, SPX_N); - } else { - /* All other tweakable hashes*/ - memcpy(buf0, addrx4 + 0 * 8, 32); - memcpy(buf1, addrx4 + 1 * 8, 32); - memcpy(buf2, addrx4 + 2 * 8, 32); - memcpy(buf3, addrx4 + 3 * 8, 32); - - memcpy(buf0 + SPX_ADDR_BYTES, in0, inblocks * SPX_N); - memcpy(buf1 + SPX_ADDR_BYTES, in1, inblocks * SPX_N); - memcpy(buf2 + SPX_ADDR_BYTES, in2, inblocks * SPX_N); - memcpy(buf3 + SPX_ADDR_BYTES, in3, inblocks * SPX_N); - - haraka_Sx4(out0, out1, out2, out3, SPX_N, - buf0, buf1, buf2, buf3, SPX_ADDR_BYTES + inblocks * SPX_N, - ctx); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/thashx4.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/thashx4.h deleted file mode 100644 index 64798a3727..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/thashx4.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef SPX_THASHX4_H -#define SPX_THASHX4_H - -#include - -#include "context.h" -#include "params.h" - -#define thashx4 SPX_NAMESPACE(thashx4) -void thashx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addrx4[4 * 8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/utils.c b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/utils.c deleted file mode 100644 index 177b541fb9..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/utils.c +++ /dev/null @@ -1,148 +0,0 @@ -#include - -#include "utils.h" - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "thash.h" - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void ull_to_bytes(unsigned char *out, unsigned int outlen, - unsigned long long in) { - int i; - - /* Iterate over out in decreasing order, for big-endianness. */ - for (i = (signed int)outlen - 1; i >= 0; i--) { - out[i] = in & 0xff; - in = in >> 8; - } -} - -void u32_to_bytes(unsigned char *out, uint32_t in) { - out[0] = (unsigned char)(in >> 24); - out[1] = (unsigned char)(in >> 16); - out[2] = (unsigned char)(in >> 8); - out[3] = (unsigned char)in; -} - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { - unsigned long long retval = 0; - unsigned int i; - - for (i = 0; i < inlen; i++) { - retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); - } - return retval; -} - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void compute_root(unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const spx_ctx *ctx, uint32_t addr[8]) { - uint32_t i; - unsigned char buffer[2 * SPX_N]; - - /* If leaf_idx is odd (last bit = 1), current path element is a right child - and auth_path has to go left. Otherwise it is the other way around. */ - if (leaf_idx & 1) { - memcpy(buffer + SPX_N, leaf, SPX_N); - memcpy(buffer, auth_path, SPX_N); - } else { - memcpy(buffer, leaf, SPX_N); - memcpy(buffer + SPX_N, auth_path, SPX_N); - } - auth_path += SPX_N; - - for (i = 0; i < tree_height - 1; i++) { - leaf_idx >>= 1; - idx_offset >>= 1; - /* Set the address of the node we're creating. */ - set_tree_height(addr, i + 1); - set_tree_index(addr, leaf_idx + idx_offset); - - /* Pick the right or left neighbor, depending on parity of the node. */ - if (leaf_idx & 1) { - thash(buffer + SPX_N, buffer, 2, ctx, addr); - memcpy(buffer, auth_path, SPX_N); - } else { - thash(buffer, buffer, 2, ctx, addr); - memcpy(buffer + SPX_N, auth_path, SPX_N); - } - auth_path += SPX_N; - } - - /* The last iteration is exceptional; we do not copy an auth_path node. */ - leaf_idx >>= 1; - idx_offset >>= 1; - set_tree_height(addr, tree_height); - set_tree_index(addr, leaf_idx + idx_offset); - thash(root, buffer, 2, ctx, addr); -} - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const spx_ctx * /* ctx */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), - uint32_t tree_addr[8]) { - PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); - PQCLEAN_VLA(unsigned int, heights, tree_height + 1); - unsigned int offset = 0; - uint32_t idx; - uint32_t tree_idx; - - for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { - /* Add the next leaf node to the stack. */ - gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); - offset++; - heights[offset - 1] = 0; - - /* If this is a node we need for the auth path.. */ - if ((leaf_idx ^ 0x1) == idx) { - memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); - } - - /* While the top-most nodes are of equal height.. */ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { - /* Compute index of the new node, in the next layer. */ - tree_idx = (idx >> (heights[offset - 1] + 1)); - - /* Set the address of the node we're creating. */ - set_tree_height(tree_addr, heights[offset - 1] + 1); - set_tree_index(tree_addr, - tree_idx + (idx_offset >> (heights[offset - 1] + 1))); - /* Hash the top-most nodes from the stack together. */ - thash(stack + (offset - 2)*SPX_N, - stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); - offset--; - /* Note that the top-most node is now one layer higher. */ - heights[offset - 1]++; - - /* If this is a node we need for the auth path.. */ - if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_path + heights[offset - 1]*SPX_N, - stack + (offset - 1)*SPX_N, SPX_N); - } - } - } - memcpy(root, stack, SPX_N); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/utils.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/utils.h deleted file mode 100644 index 64f5d5a53a..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/utils.h +++ /dev/null @@ -1,58 +0,0 @@ -#ifndef SPX_UTILS_H -#define SPX_UTILS_H - -#include - -#include "compat.h" -#include "context.h" -#include "params.h" - - -/* To support MSVC use alloca() instead of VLAs. See #20. */ - - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) -void ull_to_bytes(unsigned char *out, unsigned int outlen, - unsigned long long in); -#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) -void u32_to_bytes(unsigned char *out, uint32_t in); - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) -unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -#define compute_root SPX_NAMESPACE(compute_root) -void compute_root(unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const spx_ctx *ctx, uint32_t addr[8]); - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -#define treehash SPX_NAMESPACE(treehash) -void treehash(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const spx_ctx *ctx /* ctx */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), - uint32_t tree_addr[8]); - - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/utilsx4.c b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/utilsx4.c deleted file mode 100644 index 1638677194..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/utilsx4.c +++ /dev/null @@ -1,138 +0,0 @@ -#include - -#include "utilsx4.h" - -#include "address.h" -#include "params.h" -#include "thashx4.h" -#include "utils.h" - -/* - * Generate the entire Merkle tree, computing the authentication path for leaf_idx, - * and the resulting root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) - * - * This expects tree_addrx4 to be initialized to 4 parallel addr structures for - * the Merkle tree nodes - * - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - * - * This works by using the standard Merkle tree building algorithm, except - * that each 'node' tracked is actually 4 consecutive nodes in the real tree. - * When we combine two logical nodes ABCD and WXYZ, we perform the H - * operation on adjacent real nodes, forming the parent logical node - * (AB)(CD)(WX)(YZ) - * - * When we get to the top two levels of the real tree (where there is only - * one logical node), we continue this operation two more times; the right - * most real node will by the actual root (and the other 3 nodes will be - * garbage). We follow the same thashx4 logic so that the 'extract - * authentication path components' part of the loop is still executed (and - * to simplify the code somewhat) - * - * This currently assumes tree_height >= 2; I suspect that doing an adjusting - * idx, addr_idx on the gen_leafx4 call if tree_height < 2 would fix it; since - * we don't actually use such short trees, I haven't bothered - */ -void treehashx4(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, - uint32_t tree_height, - void (*gen_leafx4)( - unsigned char * /* Where to write the leaves */, - const spx_ctx *, - uint32_t idx, void *info), - uint32_t tree_addrx4[4 * 8], - void *info) { - /* This is where we keep the intermediate nodes */ - PQCLEAN_VLA(unsigned char, stackx4, tree_height * 4 * SPX_N); - uint32_t left_adj = 0, prev_left_adj = 0; /* When we're doing the top 3 */ - /* levels, the left-most part of the tree isn't at the beginning */ - /* of current[]. These give the offset of the actual start */ - - uint32_t idx; - uint32_t max_idx = (1U << (tree_height - 2)) - 1; - for (idx = 0;; idx++) { - unsigned char current[4 * SPX_N]; /* Current logical node */ - gen_leafx4( current, ctx, 4 * idx + idx_offset, - info ); - - /* Now combine the freshly generated right node with previously */ - /* generated left ones */ - uint32_t internal_idx_offset = idx_offset; - uint32_t internal_idx = idx; - uint32_t internal_leaf = leaf_idx; - uint32_t h; /* The height we are in the Merkle tree */ - for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { - - /* Special processing if we're at the top of the tree */ - if (h >= tree_height - 2) { - if (h == tree_height) { - /* We hit the root; return it */ - memcpy( root, ¤t[3 * SPX_N], SPX_N ); - return; - } - /* The tree indexing logic is a bit off in this case */ - /* Adjust it so that the left-most node of the part of */ - /* the tree that we're processing has index 0 */ - prev_left_adj = left_adj; - left_adj = 4U - (1 << (tree_height - h - 1)); - } - - /* Check if we hit the top of the tree */ - if (h == tree_height) { - /* We hit the root; return it */ - memcpy( root, ¤t[3 * SPX_N], SPX_N ); - return; - } - - /* - * Check if one of the nodes we have is a part of the - * authentication path; if it is, write it out - */ - if ((((internal_idx << 2) ^ internal_leaf) & ~0x3U) == 0) { - memcpy( &auth_path[ h * SPX_N ], - ¤t[(((internal_leaf & 3) ^ 1) + prev_left_adj) * SPX_N], - SPX_N ); - } - - /* - * Check if we're at a left child; if so, stop going up the stack - * Exception: if we've reached the end of the tree, keep on going - * (so we combine the last 4 nodes into the one root node in two - * more iterations) - */ - if ((internal_idx & 1) == 0 && idx < max_idx) { - break; - } - - /* Ok, we're at a right node (or doing the top 3 levels) */ - /* Now combine the left and right logical nodes together */ - - /* Set the address of the node we're creating. */ - unsigned int j; - internal_idx_offset >>= 1; - for (j = 0; j < 4; j++) { - set_tree_height(tree_addrx4 + j * 8, h + 1); - set_tree_index(tree_addrx4 + j * 8, - (4 / 2) * (internal_idx & ~1U) + j - left_adj + internal_idx_offset ); - } - unsigned char *left = &stackx4[h * 4 * SPX_N]; - thashx4( ¤t[0 * SPX_N], - ¤t[1 * SPX_N], - ¤t[2 * SPX_N], - ¤t[3 * SPX_N], - &left [0 * SPX_N], - &left [2 * SPX_N], - ¤t[0 * SPX_N], - ¤t[2 * SPX_N], - 2, ctx, tree_addrx4); - } - - /* We've hit a left child; save the current for when we get the */ - /* corresponding right right */ - memcpy( &stackx4[h * 4 * SPX_N], current, 4 * SPX_N); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/utilsx4.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/utilsx4.h deleted file mode 100644 index facb874b18..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/utilsx4.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef SPX_UTILSX4_H -#define SPX_UTILSX4_H - -#include - -#include "context.h" -#include "params.h" - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - * - * This implementation uses AVX to compute internal nodes 4 at a time (in - * parallel) - */ -#define treehashx4 SPX_NAMESPACE(treehashx4) -void treehashx4(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leafx4)( - unsigned char * /* Where to write the leaves */, - const spx_ctx * /* ctx */, - uint32_t addr_idx, void *info), - uint32_t tree_addrx4[4 * 8], void *info); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/wots.c b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/wots.c deleted file mode 100644 index 4d5041ce05..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/wots.c +++ /dev/null @@ -1,269 +0,0 @@ -#include -#include - -#include "wots.h" - -#include "address.h" -#include "hash.h" -#include "hashx4.h" -#include "params.h" -#include "thash.h" -#include "thashx4.h" -#include "utils.h" -#include "utilsx4.h" -#include "wotsx4.h" - -// TODO clarify address expectations, and make them more uniform. -// TODO i.e. do we expect types to be set already? -// TODO and do we expect modifications or copies? - -/** - * Computes up the chains - */ -static void gen_chains( - unsigned char *out, - const unsigned char *in, - unsigned int start[SPX_WOTS_LEN], - const unsigned int steps[SPX_WOTS_LEN], - const spx_ctx *ctx, - uint32_t addr[8]) { - uint32_t i, j, k, idx, watching; - int done; - unsigned char empty[SPX_N]; - unsigned char *bufs[4]; - uint32_t addrs[8 * 4]; - - int l; - uint16_t counts[SPX_WOTS_W] = { 0 }; - uint16_t idxs[SPX_WOTS_LEN]; - uint16_t total, newTotal; - - /* set addrs = {addr, addr, addr, addr} */ - for (j = 0; j < 4; j++) { - memcpy(addrs + j * 8, addr, sizeof(uint32_t) * 8); - } - - /* Initialize out with the value at position 'start'. */ - memcpy(out, in, SPX_WOTS_LEN * SPX_N); - - /* Sort the chains in reverse order by steps using counting sort. */ - for (i = 0; i < SPX_WOTS_LEN; i++) { - counts[steps[i]]++; - } - total = 0; - for (l = SPX_WOTS_W - 1; l >= 0; l--) { - newTotal = counts[l] + total; - counts[l] = total; - total = newTotal; - } - for (i = 0; i < SPX_WOTS_LEN; i++) { - idxs[counts[steps[i]]] = (uint16_t)i; - counts[steps[i]]++; - } - - /* We got our work cut out for us: do it! */ - for (i = 0; i < SPX_WOTS_LEN; i += 4) { - for (j = 0; j < 4 && i + j < SPX_WOTS_LEN; j++) { - idx = idxs[i + j]; - set_chain_addr(addrs + j * 8, idx); - bufs[j] = out + SPX_N * idx; - } - - /* As the chains are sorted in reverse order, we know that the first - * chain is the longest and the last one is the shortest. We keep - * an eye on whether the last chain is done and then on the one before, - * et cetera. */ - watching = 3; - done = 0; - while (i + watching >= SPX_WOTS_LEN) { - bufs[watching] = &empty[0]; - watching--; - } - - for (k = 0;; k++) { - while (k == steps[idxs[i + watching]]) { - bufs[watching] = &empty[0]; - if (watching == 0) { - done = 1; - break; - } - watching--; - } - if (done) { - break; - } - for (j = 0; j < watching + 1; j++) { - set_hash_addr(addrs + j * 8, k + start[idxs[i + j]]); - } - - thashx4(bufs[0], bufs[1], bufs[2], bufs[3], - bufs[0], bufs[1], bufs[2], bufs[3], 1, ctx, addrs); - } - } -} - -/** - * base_w algorithm as described in draft. - * Interprets an array of bytes as integers in base w. - * This only works when log_w is a divisor of 8. - */ -static void base_w(unsigned int *output, const int out_len, - const unsigned char *input) { - int in = 0; - int out = 0; - unsigned char total = 0; - int bits = 0; - int consumed; - - for (consumed = 0; consumed < out_len; consumed++) { - if (bits == 0) { - total = input[in]; - in++; - bits += 8; - } - bits -= SPX_WOTS_LOGW; - output[out] = (total >> bits) & (SPX_WOTS_W - 1); - out++; - } -} - -/* Computes the WOTS+ checksum over a message (in base_w). */ -static void wots_checksum(unsigned int *csum_base_w, - const unsigned int *msg_base_w) { - unsigned int csum = 0; - unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; - unsigned int i; - - /* Compute checksum. */ - for (i = 0; i < SPX_WOTS_LEN1; i++) { - csum += SPX_WOTS_W - 1 - msg_base_w[i]; - } - - /* Convert checksum to base_w. */ - /* Make sure expected empty zero bits are the least significant bits. */ - csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); - ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); - base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); -} - -/* Takes a message and derives the matching chain lengths. */ -void chain_lengths(unsigned int *lengths, const unsigned char *msg) { - base_w(lengths, SPX_WOTS_LEN1, msg); - wots_checksum(lengths + SPX_WOTS_LEN1, lengths); -} - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const spx_ctx *ctx, uint32_t addr[8]) { - unsigned int steps[SPX_WOTS_LEN]; - unsigned int start[SPX_WOTS_LEN]; - uint32_t i; - - chain_lengths(start, msg); - - for (i = 0; i < SPX_WOTS_LEN; i++) { - steps[i] = SPX_WOTS_W - 1 - start[i]; - } - - gen_chains(pk, sig, start, steps, ctx, addr); -} - -/* - * This generates 4 sequential WOTS public keys - * It also generates the WOTS signature if leaf_info indicates - * that we're signing with one of these WOTS keys - */ -void wots_gen_leafx4(unsigned char *dest, - const spx_ctx *ctx, - uint32_t leaf_idx, void *v_info) { - struct leaf_info_x4 *info = v_info; - uint32_t *leaf_addr = info->leaf_addr; - uint32_t *pk_addr = info->pk_addr; - unsigned int i, j, k; - unsigned char pk_buffer[ 4 * SPX_WOTS_BYTES ]; - unsigned wots_offset = SPX_WOTS_BYTES; - unsigned char *buffer; - uint32_t wots_k_mask; - unsigned wots_sign_index; - - if (((leaf_idx ^ info->wots_sign_leaf) & ~3U) == 0) { - /* We're traversing the leaf that's signing; generate the WOTS */ - /* signature */ - wots_k_mask = 0; - wots_sign_index = info->wots_sign_leaf & 3; /* Which of of the 4 */ - /* 4 slots do the signatures come from */ - } else { - /* Nope, we're just generating pk's; turn off the signature logic */ - wots_k_mask = (uint32_t)~0; - wots_sign_index = 0; - } - - for (j = 0; j < 4; j++) { - set_keypair_addr( leaf_addr + j * 8, leaf_idx + j ); - set_keypair_addr( pk_addr + j * 8, leaf_idx + j ); - } - - for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { - uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k to */ - /* the step if we're generating a signature, ~0 if we're not */ - - /* Start with the secret seed */ - for (j = 0; j < 4; j++) { - set_chain_addr(leaf_addr + j * 8, i); - set_hash_addr(leaf_addr + j * 8, 0); - set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTSPRF); - } - prf_addrx4(buffer + 0 * wots_offset, - buffer + 1 * wots_offset, - buffer + 2 * wots_offset, - buffer + 3 * wots_offset, - ctx, leaf_addr); - - for (j = 0; j < 4; j++) { - set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTS); - } - - /* Iterate down the WOTS chain */ - for (k = 0;; k++) { - /* Check if one of the values we have needs to be saved as a */ - /* part of the WOTS signature */ - if (k == wots_k) { - memcpy( info->wots_sig + i * SPX_N, - buffer + wots_sign_index * wots_offset, SPX_N ); - } - - /* Check if we hit the top of the chain */ - if (k == SPX_WOTS_W - 1) { - break; - } - - /* Iterate one step on all 4 chains */ - for (j = 0; j < 4; j++) { - set_hash_addr(leaf_addr + j * 8, k); - } - thashx4(buffer + 0 * wots_offset, - buffer + 1 * wots_offset, - buffer + 2 * wots_offset, - buffer + 3 * wots_offset, - buffer + 0 * wots_offset, - buffer + 1 * wots_offset, - buffer + 2 * wots_offset, - buffer + 3 * wots_offset, 1, ctx, leaf_addr); - } - } - - /* Do the final thash to generate the public keys */ - thashx4(dest + 0 * SPX_N, - dest + 1 * SPX_N, - dest + 2 * SPX_N, - dest + 3 * SPX_N, - pk_buffer + 0 * wots_offset, - pk_buffer + 1 * wots_offset, - pk_buffer + 2 * wots_offset, - pk_buffer + 3 * wots_offset, SPX_WOTS_LEN, ctx, pk_addr); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/wots.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/wots.h deleted file mode 100644 index 4e7692eeef..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/wots.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef SPX_WOTS_H -#define SPX_WOTS_H - -#include - -#include "context.h" -#include "params.h" - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) -void wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const spx_ctx *ctx, uint32_t addr[8]); - -/* - * Compute the chain lengths needed for a given message hash - */ -#define chain_lengths SPX_NAMESPACE(chain_lengths) -void chain_lengths(unsigned int *lengths, const unsigned char *msg); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/wotsx4.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/wotsx4.h deleted file mode 100644 index cd634f1743..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_aesni/wotsx4.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef WOTSX4_H_ -#define WOTSX4_H_ - -#include - -#include "params.h" - -/* - * This is here to provide an interface to the internal wots_gen_leafx4 - * routine. While this routine is not referenced in the package outside of - * wots.c, it is called from the stand-alone benchmark code to characterize - * the performance - */ -struct leaf_info_x4 { - unsigned char *wots_sig; - uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ - uint32_t *wots_steps; - uint32_t leaf_addr[4 * 8]; - uint32_t pk_addr[4 * 8]; -}; - -/* Macro to set the leaf_info to something 'benign', that is, it would */ -/* run with the same time as it does during the real signing process */ -/* Used only by the benchmark code */ -#define INITIALIZE_LEAF_INFO_X4(info, addr, step_buffer) { \ - (info).wots_sig = 0; \ - (info).wots_sign_leaf = ~0; \ - (info).wots_steps = step_buffer; \ - int i; \ - for (i=0; i<4; i++) { \ - memcpy( &(info).leaf_addr[8*i], addr, 32 ); \ - memcpy( &(info).pk_addr[8*i], addr, 32 ); \ - } \ - } - -#define wots_gen_leafx4 SPX_NAMESPACE(wots_gen_leafx4) -void wots_gen_leafx4(unsigned char *dest, - const spx_ctx *ctx, - uint32_t leaf_idx, void *v_info); - -#endif /* WOTSX4_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/LICENSE b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/LICENSE deleted file mode 100644 index 670154e353..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/LICENSE +++ /dev/null @@ -1,116 +0,0 @@ -CC0 1.0 Universal - -Statement of Purpose - -The laws of most jurisdictions throughout the world automatically confer -exclusive Copyright and Related Rights (defined below) upon the creator and -subsequent owner(s) (each and all, an "owner") of an original work of -authorship and/or a database (each, a "Work"). - -Certain owners wish to permanently relinquish those rights to a Work for the -purpose of contributing to a commons of creative, cultural and scientific -works ("Commons") that the public can reliably and without fear of later -claims of infringement build upon, modify, incorporate in other works, reuse -and redistribute as freely as possible in any form whatsoever and for any -purposes, including without limitation commercial purposes. These owners may -contribute to the Commons to promote the ideal of a free culture and the -further production of creative, cultural and scientific works, or to gain -reputation or greater distribution for their Work in part through the use and -efforts of others. - -For these and/or other purposes and motivations, and without any expectation -of additional consideration or compensation, the person associating CC0 with a -Work (the "Affirmer"), to the extent that he or she is an owner of Copyright -and Related Rights in the Work, voluntarily elects to apply CC0 to the Work -and publicly distribute the Work under its terms, with knowledge of his or her -Copyright and Related Rights in the Work and the meaning and intended legal -effect of CC0 on those rights. - -1. Copyright and Related Rights. A Work made available under CC0 may be -protected by copyright and related or neighboring rights ("Copyright and -Related Rights"). Copyright and Related Rights include, but are not limited -to, the following: - - i. the right to reproduce, adapt, distribute, perform, display, communicate, - and translate a Work; - - ii. moral rights retained by the original author(s) and/or performer(s); - - iii. publicity and privacy rights pertaining to a person's image or likeness - depicted in a Work; - - iv. rights protecting against unfair competition in regards to a Work, - subject to the limitations in paragraph 4(a), below; - - v. rights protecting the extraction, dissemination, use and reuse of data in - a Work; - - vi. database rights (such as those arising under Directive 96/9/EC of the - European Parliament and of the Council of 11 March 1996 on the legal - protection of databases, and under any national implementation thereof, - including any amended or successor version of such directive); and - - vii. other similar, equivalent or corresponding rights throughout the world - based on applicable law or treaty, and any national implementations thereof. - -2. Waiver. To the greatest extent permitted by, but not in contravention of, -applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and -unconditionally waives, abandons, and surrenders all of Affirmer's Copyright -and Related Rights and associated claims and causes of action, whether now -known or unknown (including existing as well as future claims and causes of -action), in the Work (i) in all territories worldwide, (ii) for the maximum -duration provided by applicable law or treaty (including future time -extensions), (iii) in any current or future medium and for any number of -copies, and (iv) for any purpose whatsoever, including without limitation -commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes -the Waiver for the benefit of each member of the public at large and to the -detriment of Affirmer's heirs and successors, fully intending that such Waiver -shall not be subject to revocation, rescission, cancellation, termination, or -any other legal or equitable action to disrupt the quiet enjoyment of the Work -by the public as contemplated by Affirmer's express Statement of Purpose. - -3. Public License Fallback. Should any part of the Waiver for any reason be -judged legally invalid or ineffective under applicable law, then the Waiver -shall be preserved to the maximum extent permitted taking into account -Affirmer's express Statement of Purpose. In addition, to the extent the Waiver -is so judged Affirmer hereby grants to each affected person a royalty-free, -non transferable, non sublicensable, non exclusive, irrevocable and -unconditional license to exercise Affirmer's Copyright and Related Rights in -the Work (i) in all territories worldwide, (ii) for the maximum duration -provided by applicable law or treaty (including future time extensions), (iii) -in any current or future medium and for any number of copies, and (iv) for any -purpose whatsoever, including without limitation commercial, advertising or -promotional purposes (the "License"). The License shall be deemed effective as -of the date CC0 was applied by Affirmer to the Work. Should any part of the -License for any reason be judged legally invalid or ineffective under -applicable law, such partial invalidity or ineffectiveness shall not -invalidate the remainder of the License, and in such case Affirmer hereby -affirms that he or she will not (i) exercise any of his or her remaining -Copyright and Related Rights in the Work or (ii) assert any associated claims -and causes of action with respect to the Work, in either case contrary to -Affirmer's express Statement of Purpose. - -4. Limitations and Disclaimers. - - a. No trademark or patent rights held by Affirmer are waived, abandoned, - surrendered, licensed or otherwise affected by this document. - - b. Affirmer offers the Work as-is and makes no representations or warranties - of any kind concerning the Work, express, implied, statutory or otherwise, - including without limitation warranties of title, merchantability, fitness - for a particular purpose, non infringement, or the absence of latent or - other defects, accuracy, or the present or absence of errors, whether or not - discoverable, all to the greatest extent permissible under applicable law. - - c. Affirmer disclaims responsibility for clearing rights of other persons - that may apply to the Work or any use thereof, including without limitation - any person's Copyright and Related Rights in the Work. Further, Affirmer - disclaims responsibility for obtaining any necessary consents, permissions - or other rights required for any use of the Work. - - d. Affirmer understands and acknowledges that Creative Commons is not a - party to this document and has no duty or obligation with respect to this - CC0 or use of the Work. - -For more information, please see - diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/address.c b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/address.c deleted file mode 100644 index b956e9cb29..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/address.c +++ /dev/null @@ -1,91 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "utils.h" - -/* - * Specify which level of Merkle tree (the "layer") we're working on - */ -void set_layer_addr(uint32_t addr[8], uint32_t layer) { - ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; -} - -/* - * Specify which Merkle tree within the level (the "tree address") we're working on - */ -void set_tree_addr(uint32_t addr[8], uint64_t tree) { - ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); -} - -/* - * Specify the reason we'll use this address structure for, that is, what - * hash will we compute with it. This is used so that unrelated types of - * hashes don't accidentally get the same address structure. The type will be - * one of the SPX_ADDR_TYPE constants - */ -void set_type(uint32_t addr[8], uint32_t type) { - ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; -} - -/* - * Copy the layer and tree fields of the address structure. This is used - * when we're doing multiple types of hashes within the same Merkle tree - */ -void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { - memcpy( out, in, SPX_OFFSET_TREE + 8 ); -} - -/* These functions are used for OTS addresses. */ - -/* - * Specify which Merkle leaf we're working on; that is, which OTS keypair - * we're talking about. - */ -void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { - ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; -} - -/* - * Copy the layer, tree and keypair fields of the address structure. This is - * used when we're doing multiple things within the same OTS keypair - */ -void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { - memcpy( out, in, SPX_OFFSET_TREE + 8 ); - ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; -} - -/* - * Specify which Merkle chain within the OTS we're working with - * (the chain address) - */ -void set_chain_addr(uint32_t addr[8], uint32_t chain) { - ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; -} - -/* - * Specify where in the Merkle chain we are -* (the hash address) - */ -void set_hash_addr(uint32_t addr[8], uint32_t hash) { - ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; -} - -/* These functions are used for all hash tree addresses (including FORS). */ - -/* - * Specify the height of the node in the Merkle/FORS tree we are in - * (the tree height) - */ -void set_tree_height(uint32_t addr[8], uint32_t tree_height) { - ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; -} - -/* - * Specify the distance from the left edge of the node in the Merkle/FORS tree - * (the tree index) - */ -void set_tree_index(uint32_t addr[8], uint32_t tree_index) { - u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/address.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/address.h deleted file mode 100644 index 24a84eb40c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/address.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef SPX_ADDRESS_H -#define SPX_ADDRESS_H - -#include - -#include "params.h" - -/* The hash types that are passed to set_type */ -#define SPX_ADDR_TYPE_WOTS 0 -#define SPX_ADDR_TYPE_WOTSPK 1 -#define SPX_ADDR_TYPE_HASHTREE 2 -#define SPX_ADDR_TYPE_FORSTREE 3 -#define SPX_ADDR_TYPE_FORSPK 4 -#define SPX_ADDR_TYPE_WOTSPRF 5 -#define SPX_ADDR_TYPE_FORSPRF 6 - -#define set_layer_addr SPX_NAMESPACE(set_layer_addr) -void set_layer_addr(uint32_t addr[8], uint32_t layer); - -#define set_tree_addr SPX_NAMESPACE(set_tree_addr) -void set_tree_addr(uint32_t addr[8], uint64_t tree); - -#define set_type SPX_NAMESPACE(set_type) -void set_type(uint32_t addr[8], uint32_t type); - -/* Copies the layer and tree part of one address into the other */ -#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) -void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for WOTS and FORS addresses. */ - -#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) -void set_keypair_addr(uint32_t addr[8], uint32_t keypair); - -#define set_chain_addr SPX_NAMESPACE(set_chain_addr) -void set_chain_addr(uint32_t addr[8], uint32_t chain); - -#define set_hash_addr SPX_NAMESPACE(set_hash_addr) -void set_hash_addr(uint32_t addr[8], uint32_t hash); - -#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) -void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for all hash tree addresses (including FORS). */ - -#define set_tree_height SPX_NAMESPACE(set_tree_height) -void set_tree_height(uint32_t addr[8], uint32_t tree_height); - -#define set_tree_index SPX_NAMESPACE(set_tree_index) -void set_tree_index(uint32_t addr[8], uint32_t tree_index); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/api.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/api.h deleted file mode 100644 index ee94b774bf..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/api.h +++ /dev/null @@ -1,77 +0,0 @@ -#ifndef PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_API_H -#define PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_API_H - -#include -#include - -#define PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_CRYPTO_ALGNAME "SPHINCS+-haraka-256f-simple" - -#define PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_CRYPTO_SECRETKEYBYTES 128 -#define PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_CRYPTO_PUBLICKEYBYTES 64 -#define PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_CRYPTO_BYTES 49856 - -#define PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_CRYPTO_SEEDBYTES 96 - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, - const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk); -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/context.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/context.h deleted file mode 100644 index 600dfb73c7..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/context.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef SPX_CONTEXT_H -#define SPX_CONTEXT_H - -#include -#include - -#include "params.h" - -typedef struct { - uint8_t pub_seed[SPX_N]; - uint8_t sk_seed[SPX_N]; - - - uint64_t tweaked512_rc64[10][8]; - uint32_t tweaked256_rc32[10][8]; -} spx_ctx; - -#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) -void initialize_hash_function(spx_ctx *ctx); - -#define free_hash_function SPX_NAMESPACE(free_hash_function) -void free_hash_function(spx_ctx *ctx); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/context_haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/context_haraka.c deleted file mode 100644 index f1cd7e3664..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/context_haraka.c +++ /dev/null @@ -1,11 +0,0 @@ -#include "context.h" -#include "haraka.h" - -void initialize_hash_function(spx_ctx *ctx) { - tweak_constants(ctx); -} - -// we don't support heap-based haraka right now -void free_hash_function(spx_ctx *ctx) { - (void)ctx; // suppress unused variable warnings -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/fors.c b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/fors.c deleted file mode 100644 index 96ca72e986..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/fors.c +++ /dev/null @@ -1,156 +0,0 @@ -#include -#include -#include - -#include "fors.h" - -#include "address.h" -#include "hash.h" -#include "thash.h" -#include "utils.h" -#include "utilsx1.h" - -static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, - uint32_t fors_leaf_addr[8]) { - prf_addr(sk, ctx, fors_leaf_addr); -} - -static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, - const spx_ctx *ctx, - uint32_t fors_leaf_addr[8]) { - thash(leaf, sk, 1, ctx, fors_leaf_addr); -} - -struct fors_gen_leaf_info { - uint32_t leaf_addrx[8]; -}; - -static void fors_gen_leafx1(unsigned char *leaf, - const spx_ctx *ctx, - uint32_t addr_idx, void *info) { - struct fors_gen_leaf_info *fors_info = info; - uint32_t *fors_leaf_addr = fors_info->leaf_addrx; - - /* Only set the parts that the caller doesn't set */ - set_tree_index(fors_leaf_addr, addr_idx); - set_type(fors_leaf_addr, SPX_ADDR_TYPE_FORSPRF); - fors_gen_sk(leaf, ctx, fors_leaf_addr); - - set_type(fors_leaf_addr, SPX_ADDR_TYPE_FORSTREE); - fors_sk_to_leaf(leaf, leaf, - ctx, fors_leaf_addr); -} - -/** - * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - * Assumes indices has space for SPX_FORS_TREES integers. - */ -static void message_to_indices(uint32_t *indices, const unsigned char *m) { - unsigned int i, j; - unsigned int offset = 0; - - for (i = 0; i < SPX_FORS_TREES; i++) { - indices[i] = 0; - for (j = 0; j < SPX_FORS_HEIGHT; j++) { - indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); - offset++; - } - } -} - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -void fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]) { - uint32_t indices[SPX_FORS_TREES]; - unsigned char roots[SPX_FORS_TREES * SPX_N]; - uint32_t fors_tree_addr[8] = {0}; - struct fors_gen_leaf_info fors_info = {0}; - uint32_t *fors_leaf_addr = fors_info.leaf_addrx; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - copy_keypair_addr(fors_tree_addr, fors_addr); - copy_keypair_addr(fors_leaf_addr, fors_addr); - - copy_keypair_addr(fors_pk_addr, fors_addr); - set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < SPX_FORS_TREES; i++) { - idx_offset = i * (1 << SPX_FORS_HEIGHT); - - set_tree_height(fors_tree_addr, 0); - set_tree_index(fors_tree_addr, indices[i] + idx_offset); - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); - - /* Include the secret key part that produces the selected leaf node. */ - fors_gen_sk(sig, ctx, fors_tree_addr); - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); - sig += SPX_N; - - /* Compute the authentication path for this leaf node. */ - treehashx1(roots + i * SPX_N, sig, ctx, - indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx1, - fors_tree_addr, &fors_info); - - sig += SPX_N * SPX_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); -} - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -void fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]) { - uint32_t indices[SPX_FORS_TREES]; - unsigned char roots[SPX_FORS_TREES * SPX_N]; - unsigned char leaf[SPX_N]; - uint32_t fors_tree_addr[8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - copy_keypair_addr(fors_tree_addr, fors_addr); - copy_keypair_addr(fors_pk_addr, fors_addr); - - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); - set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < SPX_FORS_TREES; i++) { - idx_offset = i * (1 << SPX_FORS_HEIGHT); - - set_tree_height(fors_tree_addr, 0); - set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Derive the leaf from the included secret key part. */ - fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); - sig += SPX_N; - - /* Derive the corresponding root node of this tree. */ - compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, - sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); - sig += SPX_N * SPX_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/fors.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/fors.h deleted file mode 100644 index 509140a178..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/fors.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef SPX_FORS_H -#define SPX_FORS_H - -#include - -#include "context.h" -#include "params.h" - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -#define fors_sign SPX_NAMESPACE(fors_sign) -void fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]); - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) -void fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/haraka.c deleted file mode 100644 index a4944913b5..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/haraka.c +++ /dev/null @@ -1,913 +0,0 @@ -/* - * Constant time implementation of the Haraka hash function. - * - * The bit-sliced implementation of the AES round functions are - * based on the AES implementation in BearSSL written - * by Thomas Pornin - */ - -#include -#include -#include -#include - -#include "haraka.h" -#include "utils.h" - -#define HARAKAS_RATE 32 - -static const uint64_t haraka512_rc64[10][8] = { - {0x24cf0ab9086f628b, 0xbdd6eeecc83b8382, 0xd96fb0306cdad0a7, 0xaace082ac8f95f89, 0x449d8e8870d7041f, 0x49bb2f80b2b3e2f8, 0x0569ae98d93bb258, 0x23dc9691e7d6a4b1}, - {0xd8ba10ede0fe5b6e, 0x7ecf7dbe424c7b8e, 0x6ea9949c6df62a31, 0xbf3f3c97ec9c313e, 0x241d03a196a1861e, 0xead3a51116e5a2ea, 0x77d479fcad9574e3, 0x18657a1af894b7a0}, - {0x10671e1a7f595522, 0xd9a00ff675d28c7b, 0x2f1edf0d2b9ba661, 0xb8ff58b8e3de45f9, 0xee29261da9865c02, 0xd1532aa4b50bdf43, 0x8bf858159b231bb1, 0xdf17439d22d4f599}, - {0xdd4b2f0870b918c0, 0x757a81f3b39b1bb6, 0x7a5c556898952e3f, 0x7dd70a16d915d87a, 0x3ae61971982b8301, 0xc3ab319e030412be, 0x17c0033ac094a8cb, 0x5a0630fc1a8dc4ef}, - {0x17708988c1632f73, 0xf92ddae090b44f4f, 0x11ac0285c43aa314, 0x509059941936b8ba, 0xd03e152fa2ce9b69, 0x3fbcbcb63a32998b, 0x6204696d692254f7, 0x915542ed93ec59b4}, - {0xf4ed94aa8879236e, 0xff6cb41cd38e03c0, 0x069b38602368aeab, 0x669495b820f0ddba, 0xf42013b1b8bf9e3d, 0xcf935efe6439734d, 0xbc1dcf42ca29e3f8, 0x7e6d3ed29f78ad67}, - {0xf3b0f6837ffcddaa, 0x3a76faef934ddf41, 0xcec7ae583a9c8e35, 0xe4dd18c68f0260af, 0x2c0e5df1ad398eaa, 0x478df5236ae22e8c, 0xfb944c46fe865f39, 0xaa48f82f028132ba}, - {0x231b9ae2b76aca77, 0x292a76a712db0b40, 0x5850625dc8134491, 0x73137dd469810fb5, 0x8a12a6a202a474fd, 0xd36fd9daa78bdb80, 0xb34c5e733505706f, 0xbaf1cdca818d9d96}, - {0x2e99781335e8c641, 0xbddfe5cce47d560e, 0xf74e9bf32e5e040c, 0x1d7a709d65996be9, 0x670df36a9cf66cdd, 0xd05ef84a176a2875, 0x0f888e828cb1c44e, 0x1a79e9c9727b052c}, - {0x83497348628d84de, 0x2e9387d51f22a754, 0xb000068da2f852d6, 0x378c9e1190fd6fe5, 0x870027c316de7293, 0xe51a9d4462e047bb, 0x90ecf7f8c6251195, 0x655953bfbed90a9c}, -}; - -static inline uint32_t br_dec32le(const unsigned char *src) { - return (uint32_t)src[0] - | ((uint32_t)src[1] << 8) - | ((uint32_t)src[2] << 16) - | ((uint32_t)src[3] << 24); -} - -static void br_range_dec32le(uint32_t *v, size_t num, const unsigned char *src) { - while (num-- > 0) { - *v ++ = br_dec32le(src); - src += 4; - } -} - -static inline void br_enc32le(unsigned char *dst, uint32_t x) { - dst[0] = (unsigned char)x; - dst[1] = (unsigned char)(x >> 8); - dst[2] = (unsigned char)(x >> 16); - dst[3] = (unsigned char)(x >> 24); -} - - -static void br_range_enc32le(unsigned char *dst, const uint32_t *v, size_t num) { - while (num-- > 0) { - br_enc32le(dst, *v ++); - dst += 4; - } -} - -static void br_aes_ct64_bitslice_Sbox(uint64_t *q) { - /* - * This S-box implementation is a straightforward translation of - * the circuit described by Boyar and Peralta in "A new - * combinational logic minimization technique with applications - * to cryptology" (https://eprint.iacr.org/2009/191.pdf). - * - * Note that variables x* (input) and s* (output) are numbered - * in "reverse" order (x0 is the high bit, x7 is the low bit). - */ - - uint64_t x0, x1, x2, x3, x4, x5, x6, x7; - uint64_t y1, y2, y3, y4, y5, y6, y7, y8, y9; - uint64_t y10, y11, y12, y13, y14, y15, y16, y17, y18, y19; - uint64_t y20, y21; - uint64_t z0, z1, z2, z3, z4, z5, z6, z7, z8, z9; - uint64_t z10, z11, z12, z13, z14, z15, z16, z17; - uint64_t t0, t1, t2, t3, t4, t5, t6, t7, t8, t9; - uint64_t t10, t11, t12, t13, t14, t15, t16, t17, t18, t19; - uint64_t t20, t21, t22, t23, t24, t25, t26, t27, t28, t29; - uint64_t t30, t31, t32, t33, t34, t35, t36, t37, t38, t39; - uint64_t t40, t41, t42, t43, t44, t45, t46, t47, t48, t49; - uint64_t t50, t51, t52, t53, t54, t55, t56, t57, t58, t59; - uint64_t t60, t61, t62, t63, t64, t65, t66, t67; - uint64_t s0, s1, s2, s3, s4, s5, s6, s7; - - x0 = q[7]; - x1 = q[6]; - x2 = q[5]; - x3 = q[4]; - x4 = q[3]; - x5 = q[2]; - x6 = q[1]; - x7 = q[0]; - - /* - * Top linear transformation. - */ - y14 = x3 ^ x5; - y13 = x0 ^ x6; - y9 = x0 ^ x3; - y8 = x0 ^ x5; - t0 = x1 ^ x2; - y1 = t0 ^ x7; - y4 = y1 ^ x3; - y12 = y13 ^ y14; - y2 = y1 ^ x0; - y5 = y1 ^ x6; - y3 = y5 ^ y8; - t1 = x4 ^ y12; - y15 = t1 ^ x5; - y20 = t1 ^ x1; - y6 = y15 ^ x7; - y10 = y15 ^ t0; - y11 = y20 ^ y9; - y7 = x7 ^ y11; - y17 = y10 ^ y11; - y19 = y10 ^ y8; - y16 = t0 ^ y11; - y21 = y13 ^ y16; - y18 = x0 ^ y16; - - /* - * Non-linear section. - */ - t2 = y12 & y15; - t3 = y3 & y6; - t4 = t3 ^ t2; - t5 = y4 & x7; - t6 = t5 ^ t2; - t7 = y13 & y16; - t8 = y5 & y1; - t9 = t8 ^ t7; - t10 = y2 & y7; - t11 = t10 ^ t7; - t12 = y9 & y11; - t13 = y14 & y17; - t14 = t13 ^ t12; - t15 = y8 & y10; - t16 = t15 ^ t12; - t17 = t4 ^ t14; - t18 = t6 ^ t16; - t19 = t9 ^ t14; - t20 = t11 ^ t16; - t21 = t17 ^ y20; - t22 = t18 ^ y19; - t23 = t19 ^ y21; - t24 = t20 ^ y18; - - t25 = t21 ^ t22; - t26 = t21 & t23; - t27 = t24 ^ t26; - t28 = t25 & t27; - t29 = t28 ^ t22; - t30 = t23 ^ t24; - t31 = t22 ^ t26; - t32 = t31 & t30; - t33 = t32 ^ t24; - t34 = t23 ^ t33; - t35 = t27 ^ t33; - t36 = t24 & t35; - t37 = t36 ^ t34; - t38 = t27 ^ t36; - t39 = t29 & t38; - t40 = t25 ^ t39; - - t41 = t40 ^ t37; - t42 = t29 ^ t33; - t43 = t29 ^ t40; - t44 = t33 ^ t37; - t45 = t42 ^ t41; - z0 = t44 & y15; - z1 = t37 & y6; - z2 = t33 & x7; - z3 = t43 & y16; - z4 = t40 & y1; - z5 = t29 & y7; - z6 = t42 & y11; - z7 = t45 & y17; - z8 = t41 & y10; - z9 = t44 & y12; - z10 = t37 & y3; - z11 = t33 & y4; - z12 = t43 & y13; - z13 = t40 & y5; - z14 = t29 & y2; - z15 = t42 & y9; - z16 = t45 & y14; - z17 = t41 & y8; - - /* - * Bottom linear transformation. - */ - t46 = z15 ^ z16; - t47 = z10 ^ z11; - t48 = z5 ^ z13; - t49 = z9 ^ z10; - t50 = z2 ^ z12; - t51 = z2 ^ z5; - t52 = z7 ^ z8; - t53 = z0 ^ z3; - t54 = z6 ^ z7; - t55 = z16 ^ z17; - t56 = z12 ^ t48; - t57 = t50 ^ t53; - t58 = z4 ^ t46; - t59 = z3 ^ t54; - t60 = t46 ^ t57; - t61 = z14 ^ t57; - t62 = t52 ^ t58; - t63 = t49 ^ t58; - t64 = z4 ^ t59; - t65 = t61 ^ t62; - t66 = z1 ^ t63; - s0 = t59 ^ t63; - s6 = t56 ^ ~t62; - s7 = t48 ^ ~t60; - t67 = t64 ^ t65; - s3 = t53 ^ t66; - s4 = t51 ^ t66; - s5 = t47 ^ t65; - s1 = t64 ^ ~s3; - s2 = t55 ^ ~t67; - - q[7] = s0; - q[6] = s1; - q[5] = s2; - q[4] = s3; - q[3] = s4; - q[2] = s5; - q[1] = s6; - q[0] = s7; -} - -static void br_aes_ct_bitslice_Sbox(uint32_t *q) { - /* - * This S-box implementation is a straightforward translation of - * the circuit described by Boyar and Peralta in "A new - * combinational logic minimization technique with applications - * to cryptology" (https://eprint.iacr.org/2009/191.pdf). - * - * Note that variables x* (input) and s* (output) are numbered - * in "reverse" order (x0 is the high bit, x7 is the low bit). - */ - - uint32_t x0, x1, x2, x3, x4, x5, x6, x7; - uint32_t y1, y2, y3, y4, y5, y6, y7, y8, y9; - uint32_t y10, y11, y12, y13, y14, y15, y16, y17, y18, y19; - uint32_t y20, y21; - uint32_t z0, z1, z2, z3, z4, z5, z6, z7, z8, z9; - uint32_t z10, z11, z12, z13, z14, z15, z16, z17; - uint32_t t0, t1, t2, t3, t4, t5, t6, t7, t8, t9; - uint32_t t10, t11, t12, t13, t14, t15, t16, t17, t18, t19; - uint32_t t20, t21, t22, t23, t24, t25, t26, t27, t28, t29; - uint32_t t30, t31, t32, t33, t34, t35, t36, t37, t38, t39; - uint32_t t40, t41, t42, t43, t44, t45, t46, t47, t48, t49; - uint32_t t50, t51, t52, t53, t54, t55, t56, t57, t58, t59; - uint32_t t60, t61, t62, t63, t64, t65, t66, t67; - uint32_t s0, s1, s2, s3, s4, s5, s6, s7; - - x0 = q[7]; - x1 = q[6]; - x2 = q[5]; - x3 = q[4]; - x4 = q[3]; - x5 = q[2]; - x6 = q[1]; - x7 = q[0]; - - /* - * Top linear transformation. - */ - y14 = x3 ^ x5; - y13 = x0 ^ x6; - y9 = x0 ^ x3; - y8 = x0 ^ x5; - t0 = x1 ^ x2; - y1 = t0 ^ x7; - y4 = y1 ^ x3; - y12 = y13 ^ y14; - y2 = y1 ^ x0; - y5 = y1 ^ x6; - y3 = y5 ^ y8; - t1 = x4 ^ y12; - y15 = t1 ^ x5; - y20 = t1 ^ x1; - y6 = y15 ^ x7; - y10 = y15 ^ t0; - y11 = y20 ^ y9; - y7 = x7 ^ y11; - y17 = y10 ^ y11; - y19 = y10 ^ y8; - y16 = t0 ^ y11; - y21 = y13 ^ y16; - y18 = x0 ^ y16; - - /* - * Non-linear section. - */ - t2 = y12 & y15; - t3 = y3 & y6; - t4 = t3 ^ t2; - t5 = y4 & x7; - t6 = t5 ^ t2; - t7 = y13 & y16; - t8 = y5 & y1; - t9 = t8 ^ t7; - t10 = y2 & y7; - t11 = t10 ^ t7; - t12 = y9 & y11; - t13 = y14 & y17; - t14 = t13 ^ t12; - t15 = y8 & y10; - t16 = t15 ^ t12; - t17 = t4 ^ t14; - t18 = t6 ^ t16; - t19 = t9 ^ t14; - t20 = t11 ^ t16; - t21 = t17 ^ y20; - t22 = t18 ^ y19; - t23 = t19 ^ y21; - t24 = t20 ^ y18; - - t25 = t21 ^ t22; - t26 = t21 & t23; - t27 = t24 ^ t26; - t28 = t25 & t27; - t29 = t28 ^ t22; - t30 = t23 ^ t24; - t31 = t22 ^ t26; - t32 = t31 & t30; - t33 = t32 ^ t24; - t34 = t23 ^ t33; - t35 = t27 ^ t33; - t36 = t24 & t35; - t37 = t36 ^ t34; - t38 = t27 ^ t36; - t39 = t29 & t38; - t40 = t25 ^ t39; - - t41 = t40 ^ t37; - t42 = t29 ^ t33; - t43 = t29 ^ t40; - t44 = t33 ^ t37; - t45 = t42 ^ t41; - z0 = t44 & y15; - z1 = t37 & y6; - z2 = t33 & x7; - z3 = t43 & y16; - z4 = t40 & y1; - z5 = t29 & y7; - z6 = t42 & y11; - z7 = t45 & y17; - z8 = t41 & y10; - z9 = t44 & y12; - z10 = t37 & y3; - z11 = t33 & y4; - z12 = t43 & y13; - z13 = t40 & y5; - z14 = t29 & y2; - z15 = t42 & y9; - z16 = t45 & y14; - z17 = t41 & y8; - - /* - * Bottom linear transformation. - */ - t46 = z15 ^ z16; - t47 = z10 ^ z11; - t48 = z5 ^ z13; - t49 = z9 ^ z10; - t50 = z2 ^ z12; - t51 = z2 ^ z5; - t52 = z7 ^ z8; - t53 = z0 ^ z3; - t54 = z6 ^ z7; - t55 = z16 ^ z17; - t56 = z12 ^ t48; - t57 = t50 ^ t53; - t58 = z4 ^ t46; - t59 = z3 ^ t54; - t60 = t46 ^ t57; - t61 = z14 ^ t57; - t62 = t52 ^ t58; - t63 = t49 ^ t58; - t64 = z4 ^ t59; - t65 = t61 ^ t62; - t66 = z1 ^ t63; - s0 = t59 ^ t63; - s6 = t56 ^ ~t62; - s7 = t48 ^ ~t60; - t67 = t64 ^ t65; - s3 = t53 ^ t66; - s4 = t51 ^ t66; - s5 = t47 ^ t65; - s1 = t64 ^ ~s3; - s2 = t55 ^ ~t67; - - q[7] = s0; - q[6] = s1; - q[5] = s2; - q[4] = s3; - q[3] = s4; - q[2] = s5; - q[1] = s6; - q[0] = s7; -} - -static void br_aes_ct_ortho(uint32_t *q) { -#define SWAPN_32(cl, ch, s, x, y) do { \ - uint32_t a, b; \ - a = (x); \ - b = (y); \ - (x) = (a & (uint32_t)(cl)) | ((b & (uint32_t)(cl)) << (s)); \ - (y) = ((a & (uint32_t)(ch)) >> (s)) | (b & (uint32_t)(ch)); \ - } while (0) - -#define SWAP2_32(x, y) SWAPN_32(0x55555555, 0xAAAAAAAA, 1, x, y) -#define SWAP4_32(x, y) SWAPN_32(0x33333333, 0xCCCCCCCC, 2, x, y) -#define SWAP8_32(x, y) SWAPN_32(0x0F0F0F0F, 0xF0F0F0F0, 4, x, y) - - SWAP2_32(q[0], q[1]); - SWAP2_32(q[2], q[3]); - SWAP2_32(q[4], q[5]); - SWAP2_32(q[6], q[7]); - - SWAP4_32(q[0], q[2]); - SWAP4_32(q[1], q[3]); - SWAP4_32(q[4], q[6]); - SWAP4_32(q[5], q[7]); - - SWAP8_32(q[0], q[4]); - SWAP8_32(q[1], q[5]); - SWAP8_32(q[2], q[6]); - SWAP8_32(q[3], q[7]); -} - -static inline void add_round_key32(uint32_t *q, const uint32_t *sk) { - q[0] ^= sk[0]; - q[1] ^= sk[1]; - q[2] ^= sk[2]; - q[3] ^= sk[3]; - q[4] ^= sk[4]; - q[5] ^= sk[5]; - q[6] ^= sk[6]; - q[7] ^= sk[7]; -} - -static inline void shift_rows32(uint32_t *q) { - int i; - - for (i = 0; i < 8; i++) { - uint32_t x; - - x = q[i]; - q[i] = (x & 0x000000FF) - | ((x & 0x0000FC00) >> 2) | ((x & 0x00000300) << 6) - | ((x & 0x00F00000) >> 4) | ((x & 0x000F0000) << 4) - | ((x & 0xC0000000) >> 6) | ((x & 0x3F000000) << 2); - } -} - -static inline uint32_t rotr16(uint32_t x) { - return (x << 16) | (x >> 16); -} - -static inline void mix_columns32(uint32_t *q) { - uint32_t q0, q1, q2, q3, q4, q5, q6, q7; - uint32_t r0, r1, r2, r3, r4, r5, r6, r7; - - q0 = q[0]; - q1 = q[1]; - q2 = q[2]; - q3 = q[3]; - q4 = q[4]; - q5 = q[5]; - q6 = q[6]; - q7 = q[7]; - r0 = (q0 >> 8) | (q0 << 24); - r1 = (q1 >> 8) | (q1 << 24); - r2 = (q2 >> 8) | (q2 << 24); - r3 = (q3 >> 8) | (q3 << 24); - r4 = (q4 >> 8) | (q4 << 24); - r5 = (q5 >> 8) | (q5 << 24); - r6 = (q6 >> 8) | (q6 << 24); - r7 = (q7 >> 8) | (q7 << 24); - - q[0] = q7 ^ r7 ^ r0 ^ rotr16(q0 ^ r0); - q[1] = q0 ^ r0 ^ q7 ^ r7 ^ r1 ^ rotr16(q1 ^ r1); - q[2] = q1 ^ r1 ^ r2 ^ rotr16(q2 ^ r2); - q[3] = q2 ^ r2 ^ q7 ^ r7 ^ r3 ^ rotr16(q3 ^ r3); - q[4] = q3 ^ r3 ^ q7 ^ r7 ^ r4 ^ rotr16(q4 ^ r4); - q[5] = q4 ^ r4 ^ r5 ^ rotr16(q5 ^ r5); - q[6] = q5 ^ r5 ^ r6 ^ rotr16(q6 ^ r6); - q[7] = q6 ^ r6 ^ r7 ^ rotr16(q7 ^ r7); -} - -static void br_aes_ct64_ortho(uint64_t *q) { -#define SWAPN(cl, ch, s, x, y) do { \ - uint64_t a, b; \ - a = (x); \ - b = (y); \ - (x) = (a & (uint64_t)(cl)) | ((b & (uint64_t)(cl)) << (s)); \ - (y) = ((a & (uint64_t)(ch)) >> (s)) | (b & (uint64_t)(ch)); \ - } while (0) - -#define SWAP2(x, y) SWAPN(0x5555555555555555, 0xAAAAAAAAAAAAAAAA, 1, x, y) -#define SWAP4(x, y) SWAPN(0x3333333333333333, 0xCCCCCCCCCCCCCCCC, 2, x, y) -#define SWAP8(x, y) SWAPN(0x0F0F0F0F0F0F0F0F, 0xF0F0F0F0F0F0F0F0, 4, x, y) - - SWAP2(q[0], q[1]); - SWAP2(q[2], q[3]); - SWAP2(q[4], q[5]); - SWAP2(q[6], q[7]); - - SWAP4(q[0], q[2]); - SWAP4(q[1], q[3]); - SWAP4(q[4], q[6]); - SWAP4(q[5], q[7]); - - SWAP8(q[0], q[4]); - SWAP8(q[1], q[5]); - SWAP8(q[2], q[6]); - SWAP8(q[3], q[7]); -} - - -static void br_aes_ct64_interleave_in(uint64_t *q0, uint64_t *q1, const uint32_t *w) { - uint64_t x0, x1, x2, x3; - - x0 = w[0]; - x1 = w[1]; - x2 = w[2]; - x3 = w[3]; - x0 |= (x0 << 16); - x1 |= (x1 << 16); - x2 |= (x2 << 16); - x3 |= (x3 << 16); - x0 &= (uint64_t)0x0000FFFF0000FFFF; - x1 &= (uint64_t)0x0000FFFF0000FFFF; - x2 &= (uint64_t)0x0000FFFF0000FFFF; - x3 &= (uint64_t)0x0000FFFF0000FFFF; - x0 |= (x0 << 8); - x1 |= (x1 << 8); - x2 |= (x2 << 8); - x3 |= (x3 << 8); - x0 &= (uint64_t)0x00FF00FF00FF00FF; - x1 &= (uint64_t)0x00FF00FF00FF00FF; - x2 &= (uint64_t)0x00FF00FF00FF00FF; - x3 &= (uint64_t)0x00FF00FF00FF00FF; - *q0 = x0 | (x2 << 8); - *q1 = x1 | (x3 << 8); -} - - -static void br_aes_ct64_interleave_out(uint32_t *w, uint64_t q0, uint64_t q1) { - uint64_t x0, x1, x2, x3; - - x0 = q0 & (uint64_t)0x00FF00FF00FF00FF; - x1 = q1 & (uint64_t)0x00FF00FF00FF00FF; - x2 = (q0 >> 8) & (uint64_t)0x00FF00FF00FF00FF; - x3 = (q1 >> 8) & (uint64_t)0x00FF00FF00FF00FF; - x0 |= (x0 >> 8); - x1 |= (x1 >> 8); - x2 |= (x2 >> 8); - x3 |= (x3 >> 8); - x0 &= (uint64_t)0x0000FFFF0000FFFF; - x1 &= (uint64_t)0x0000FFFF0000FFFF; - x2 &= (uint64_t)0x0000FFFF0000FFFF; - x3 &= (uint64_t)0x0000FFFF0000FFFF; - w[0] = (uint32_t)x0 | (uint32_t)(x0 >> 16); - w[1] = (uint32_t)x1 | (uint32_t)(x1 >> 16); - w[2] = (uint32_t)x2 | (uint32_t)(x2 >> 16); - w[3] = (uint32_t)x3 | (uint32_t)(x3 >> 16); -} - -static inline void add_round_key(uint64_t *q, const uint64_t *sk) { - q[0] ^= sk[0]; - q[1] ^= sk[1]; - q[2] ^= sk[2]; - q[3] ^= sk[3]; - q[4] ^= sk[4]; - q[5] ^= sk[5]; - q[6] ^= sk[6]; - q[7] ^= sk[7]; -} - -static inline void shift_rows(uint64_t *q) { - int i; - - for (i = 0; i < 8; i++) { - uint64_t x; - - x = q[i]; - q[i] = (x & (uint64_t)0x000000000000FFFF) - | ((x & (uint64_t)0x00000000FFF00000) >> 4) - | ((x & (uint64_t)0x00000000000F0000) << 12) - | ((x & (uint64_t)0x0000FF0000000000) >> 8) - | ((x & (uint64_t)0x000000FF00000000) << 8) - | ((x & (uint64_t)0xF000000000000000) >> 12) - | ((x & (uint64_t)0x0FFF000000000000) << 4); - } -} - -static inline uint64_t rotr32(uint64_t x) { - return (x << 32) | (x >> 32); -} - -static inline void mix_columns(uint64_t *q) { - uint64_t q0, q1, q2, q3, q4, q5, q6, q7; - uint64_t r0, r1, r2, r3, r4, r5, r6, r7; - - q0 = q[0]; - q1 = q[1]; - q2 = q[2]; - q3 = q[3]; - q4 = q[4]; - q5 = q[5]; - q6 = q[6]; - q7 = q[7]; - r0 = (q0 >> 16) | (q0 << 48); - r1 = (q1 >> 16) | (q1 << 48); - r2 = (q2 >> 16) | (q2 << 48); - r3 = (q3 >> 16) | (q3 << 48); - r4 = (q4 >> 16) | (q4 << 48); - r5 = (q5 >> 16) | (q5 << 48); - r6 = (q6 >> 16) | (q6 << 48); - r7 = (q7 >> 16) | (q7 << 48); - - q[0] = q7 ^ r7 ^ r0 ^ rotr32(q0 ^ r0); - q[1] = q0 ^ r0 ^ q7 ^ r7 ^ r1 ^ rotr32(q1 ^ r1); - q[2] = q1 ^ r1 ^ r2 ^ rotr32(q2 ^ r2); - q[3] = q2 ^ r2 ^ q7 ^ r7 ^ r3 ^ rotr32(q3 ^ r3); - q[4] = q3 ^ r3 ^ q7 ^ r7 ^ r4 ^ rotr32(q4 ^ r4); - q[5] = q4 ^ r4 ^ r5 ^ rotr32(q5 ^ r5); - q[6] = q5 ^ r5 ^ r6 ^ rotr32(q6 ^ r6); - q[7] = q6 ^ r6 ^ r7 ^ rotr32(q7 ^ r7); -} - -static void interleave_constant(uint64_t *out, const unsigned char *in) { - uint32_t tmp_32_constant[16]; - int i; - - br_range_dec32le(tmp_32_constant, 16, in); - for (i = 0; i < 4; i++) { - br_aes_ct64_interleave_in(&out[i], &out[i + 4], tmp_32_constant + (i << 2)); - } - br_aes_ct64_ortho(out); -} - -static void interleave_constant32(uint32_t *out, const unsigned char *in) { - int i; - for (i = 0; i < 4; i++) { - out[2 * i] = br_dec32le(in + 4 * i); - out[2 * i + 1] = br_dec32le(in + 4 * i + 16); - } - br_aes_ct_ortho(out); -} - -void tweak_constants(spx_ctx *ctx) { - unsigned char buf[40 * 16]; - int i; - - /* Use the standard constants to generate tweaked ones. */ - memcpy((uint8_t *)ctx->tweaked512_rc64, (uint8_t *)haraka512_rc64, 40 * 16); - - /* Constants for pk.seed */ - haraka_S(buf, 40 * 16, ctx->pub_seed, SPX_N, ctx); - for (i = 0; i < 10; i++) { - interleave_constant32(ctx->tweaked256_rc32[i], buf + 32 * i); - interleave_constant(ctx->tweaked512_rc64[i], buf + 64 * i); - } -} - -static void haraka_S_absorb(unsigned char *s, unsigned int r, - const unsigned char *m, unsigned long long mlen, - unsigned char p, const spx_ctx *ctx) { - unsigned long long i; - PQCLEAN_VLA(uint8_t, t, r); - - while (mlen >= r) { - /* XOR block to state */ - for (i = 0; i < r; ++i) { - s[i] ^= m[i]; - } - haraka512_perm(s, s, ctx); - 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; ++i) { - s[i] ^= t[i]; - } -} - -static void haraka_S_squeezeblocks(unsigned char *h, unsigned long long nblocks, - unsigned char *s, unsigned int r, - const spx_ctx *ctx) { - while (nblocks > 0) { - haraka512_perm(s, s, ctx); - memcpy(h, s, HARAKAS_RATE); - h += r; - nblocks--; - } -} - -void haraka_S_inc_init(uint8_t *s_inc) { - size_t i; - - for (i = 0; i < 64; i++) { - s_inc[i] = 0; - } - s_inc[64] = 0; -} - -void haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, - const spx_ctx *ctx) { - size_t i; - - /* Recall that s_inc[64] is the non-absorbed bytes xored into the state */ - while (mlen + s_inc[64] >= HARAKAS_RATE) { - for (i = 0; i < (size_t)(HARAKAS_RATE - s_inc[64]); i++) { - /* Take the i'th byte from message - xor with the s_inc[64] + i'th byte of the state */ - s_inc[s_inc[64] + i] ^= m[i]; - } - mlen -= (size_t)(HARAKAS_RATE - s_inc[64]); - m += HARAKAS_RATE - (uint8_t)s_inc[64]; - s_inc[64] = 0; - - haraka512_perm(s_inc, s_inc, ctx); - } - - for (i = 0; i < mlen; i++) { - s_inc[s_inc[64] + i] ^= m[i]; - } - s_inc[64] += (uint8_t)mlen; -} - -void haraka_S_inc_finalize(uint8_t *s_inc) { - /* After haraka_S_inc_absorb, we are guaranteed that s_inc[64] < HARAKAS_RATE, - so we can always use one more byte for p in the current state. */ - s_inc[s_inc[64]] ^= 0x1F; - s_inc[HARAKAS_RATE - 1] ^= 128; - s_inc[64] = 0; -} - -void haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, - const spx_ctx *ctx) { - size_t i; - - /* First consume any bytes we still have sitting around */ - for (i = 0; i < outlen && i < s_inc[64]; i++) { - /* There are s_inc[64] bytes left, so r - s_inc[64] is the first - available byte. We consume from there, i.e., up to r. */ - out[i] = (uint8_t)s_inc[(HARAKAS_RATE - s_inc[64] + i)]; - } - out += i; - outlen -= i; - s_inc[64] -= (uint8_t)i; - - /* Then squeeze the remaining necessary blocks */ - while (outlen > 0) { - haraka512_perm(s_inc, s_inc, ctx); - - for (i = 0; i < outlen && i < HARAKAS_RATE; i++) { - out[i] = s_inc[i]; - } - out += i; - outlen -= i; - s_inc[64] = (uint8_t)(HARAKAS_RATE - i); - } -} - -void haraka_S(unsigned char *out, unsigned long long outlen, - const unsigned char *in, unsigned long long inlen, - const spx_ctx *ctx) { - unsigned long long i; - unsigned char s[64]; - unsigned char d[32]; - - for (i = 0; i < 64; i++) { - s[i] = 0; - } - haraka_S_absorb(s, 32, in, inlen, 0x1F, ctx); - - haraka_S_squeezeblocks(out, outlen / 32, s, 32, ctx); - out += (outlen / 32) * 32; - - if (outlen % 32) { - haraka_S_squeezeblocks(d, 1, s, 32, ctx); - for (i = 0; i < outlen % 32; i++) { - out[i] = d[i]; - } - } -} - -void haraka512_perm(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx) { - uint32_t w[16]; - uint64_t q[8], tmp_q; - unsigned int i, j; - - br_range_dec32le(w, 16, in); - for (i = 0; i < 4; i++) { - br_aes_ct64_interleave_in(&q[i], &q[i + 4], w + (i << 2)); - } - br_aes_ct64_ortho(q); - - /* AES rounds */ - for (i = 0; i < 5; i++) { - for (j = 0; j < 2; j++) { - br_aes_ct64_bitslice_Sbox(q); - shift_rows(q); - mix_columns(q); - add_round_key(q, ctx->tweaked512_rc64[2 * i + j]); - } - /* Mix states */ - for (j = 0; j < 8; j++) { - tmp_q = q[j]; - q[j] = (tmp_q & 0x0001000100010001) << 5 | - (tmp_q & 0x0002000200020002) << 12 | - (tmp_q & 0x0004000400040004) >> 1 | - (tmp_q & 0x0008000800080008) << 6 | - (tmp_q & 0x0020002000200020) << 9 | - (tmp_q & 0x0040004000400040) >> 4 | - (tmp_q & 0x0080008000800080) << 3 | - (tmp_q & 0x2100210021002100) >> 5 | - (tmp_q & 0x0210021002100210) << 2 | - (tmp_q & 0x0800080008000800) << 4 | - (tmp_q & 0x1000100010001000) >> 12 | - (tmp_q & 0x4000400040004000) >> 10 | - (tmp_q & 0x8400840084008400) >> 3; - } - } - - br_aes_ct64_ortho(q); - for (i = 0; i < 4; i ++) { - br_aes_ct64_interleave_out(w + (i << 2), q[i], q[i + 4]); - } - br_range_enc32le(out, w, 16); -} - -void haraka512(unsigned char *out, const unsigned char *in, const spx_ctx *ctx) { - int i; - - unsigned char buf[64]; - - haraka512_perm(buf, in, ctx); - /* Feed-forward */ - for (i = 0; i < 64; i++) { - buf[i] = buf[i] ^ in[i]; - } - - /* Truncated */ - memcpy(out, buf + 8, 8); - memcpy(out + 8, buf + 24, 8); - memcpy(out + 16, buf + 32, 8); - memcpy(out + 24, buf + 48, 8); -} - - -void haraka256(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx) { - uint32_t q[8], tmp_q; - int i, j; - - for (i = 0; i < 4; i++) { - q[2 * i] = br_dec32le(in + 4 * i); - q[2 * i + 1] = br_dec32le(in + 4 * i + 16); - } - br_aes_ct_ortho(q); - - /* AES rounds */ - for (i = 0; i < 5; i++) { - for (j = 0; j < 2; j++) { - br_aes_ct_bitslice_Sbox(q); - shift_rows32(q); - mix_columns32(q); - add_round_key32(q, ctx->tweaked256_rc32[2 * i + j]); - } - - /* Mix states */ - for (j = 0; j < 8; j++) { - tmp_q = q[j]; - q[j] = (tmp_q & 0x81818181) | - (tmp_q & 0x02020202) << 1 | - (tmp_q & 0x04040404) << 2 | - (tmp_q & 0x08080808) << 3 | - (tmp_q & 0x10101010) >> 3 | - (tmp_q & 0x20202020) >> 2 | - (tmp_q & 0x40404040) >> 1; - } - } - - br_aes_ct_ortho(q); - for (i = 0; i < 4; i++) { - br_enc32le(out + 4 * i, q[2 * i]); - br_enc32le(out + 4 * i + 16, q[2 * i + 1]); - } - - for (i = 0; i < 32; i++) { - out[i] ^= in[i]; - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/haraka.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/haraka.h deleted file mode 100644 index 737cb6065f..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/haraka.h +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef SPX_HARAKA_H -#define SPX_HARAKA_H - -#include "context.h" -#include "params.h" - -/* Tweak constants with seed */ -#define tweak_constants SPX_NAMESPACE(tweak_constants) -void tweak_constants(spx_ctx *ctx); - -/* Haraka Sponge */ -#define haraka_S_inc_init SPX_NAMESPACE(haraka_S_inc_init) -void haraka_S_inc_init(uint8_t *s_inc); -#define haraka_S_inc_absorb SPX_NAMESPACE(haraka_S_inc_absorb) -void haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, - const spx_ctx *ctx); -#define haraka_S_inc_finalize SPX_NAMESPACE(haraka_S_inc_finalize) -void haraka_S_inc_finalize(uint8_t *s_inc); -#define haraka_S_inc_squeeze SPX_NAMESPACE(haraka_S_inc_squeeze) -void haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, - const spx_ctx *ctx); -#define haraka_S SPX_NAMESPACE(haraka_S) -void haraka_S(unsigned char *out, unsigned long long outlen, - const unsigned char *in, unsigned long long inlen, - const spx_ctx *ctx); - -/* Applies the 512-bit Haraka permutation to in. */ -#define haraka512_perm SPX_NAMESPACE(haraka512_perm) -void haraka512_perm(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx); - -/* Implementation of Haraka-512 */ -#define haraka512 SPX_NAMESPACE(haraka512) -void haraka512(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx); - -/* Implementation of Haraka-256 */ -#define haraka256 SPX_NAMESPACE(haraka256) -void haraka256(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/haraka_offsets.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/haraka_offsets.h deleted file mode 100644 index 7c062272a0..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/haraka_offsets.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef HARAKA_OFFSETS_H_ -#define HARAKA_OFFSETS_H_ - -/* - * Offsets of various fields in the address structure when we use Haraka as - * the Sphincs+ hash function - */ - -#define SPX_OFFSET_LAYER 3 /* The byte used to specify the Merkle tree layer */ -#define SPX_OFFSET_TREE 8 /* The start of the 8 byte field used to specify the tree */ -#define SPX_OFFSET_TYPE 19 /* The byte used to specify the hash type (reason) */ -#define SPX_OFFSET_KP_ADDR2 22 /* The high byte used to specify the key pair (which one-time signature) */ -#define SPX_OFFSET_KP_ADDR1 23 /* The low byte used to specify the key pair */ -#define SPX_OFFSET_CHAIN_ADDR 27 /* The byte used to specify the chain address (which Winternitz chain) */ -#define SPX_OFFSET_HASH_ADDR 31 /* The byte used to specify the hash address (where in the Winternitz chain) */ -#define SPX_OFFSET_TREE_HGT 27 /* The byte used to specify the height of this node in the FORS or Merkle tree */ -#define SPX_OFFSET_TREE_INDEX 28 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ - -#define SPX_HARAKA 1 - -#endif /* HARAKA_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/hash.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/hash.h deleted file mode 100644 index f7c87d4c3c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/hash.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef SPX_HASH_H -#define SPX_HASH_H - -#include -#include - -#include "context.h" -#include "params.h" - -#define prf_addr SPX_NAMESPACE(prf_addr) -void prf_addr(unsigned char *out, const spx_ctx *ctx, - const uint32_t addr[8]); - -#define gen_message_random SPX_NAMESPACE(gen_message_random) -void gen_message_random(unsigned char *R, const unsigned char *sk_prf, - const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx); - -#define hash_message SPX_NAMESPACE(hash_message) -void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx); - - - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/hash_haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/hash_haraka.c deleted file mode 100644 index 750a67423b..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/hash_haraka.c +++ /dev/null @@ -1,81 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "utils.h" - -#include "haraka.h" -#include "hash.h" - -/* - * Computes PRF(key, addr), given a secret key of SPX_N bytes and an address - */ -void prf_addr(unsigned char *out, const spx_ctx *ctx, - const uint32_t addr[8]) { - /* Since SPX_N may be smaller than 32, we need temporary buffers. */ - unsigned char outbuf[32]; - unsigned char buf[64] = {0}; - - memcpy(buf, addr, SPX_ADDR_BYTES); - memcpy(buf + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); - - haraka512(outbuf, (const void *)buf, ctx); - memcpy(out, outbuf, SPX_N); -} - -/** - * Computes the message-dependent randomness R, using a secret seed and an - * optional randomization value as well as the message. - */ -void gen_message_random(unsigned char *R, const unsigned char *sk_prf, - const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx) { - uint8_t s_inc[65]; - - haraka_S_inc_init(s_inc); - haraka_S_inc_absorb(s_inc, sk_prf, SPX_N, ctx); - haraka_S_inc_absorb(s_inc, optrand, SPX_N, ctx); - haraka_S_inc_absorb(s_inc, m, mlen, ctx); - haraka_S_inc_finalize(s_inc); - haraka_S_inc_squeeze(R, SPX_N, s_inc, ctx); -} - -/** - * Computes the message hash using R, the public key, and the message. - * Outputs the message digest and the index of the leaf. The index is split in - * the tree index and the leaf index, for convenient copying to an address. - */ -void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx) { -#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) -#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) -#define SPX_LEAF_BITS SPX_TREE_HEIGHT -#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) -#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) - - unsigned char buf[SPX_DGST_BYTES]; - unsigned char *bufp = buf; - uint8_t s_inc[65]; - - haraka_S_inc_init(s_inc); - haraka_S_inc_absorb(s_inc, R, SPX_N, ctx); - haraka_S_inc_absorb(s_inc, pk + SPX_N, SPX_N, ctx); // Only absorb root part of pk - haraka_S_inc_absorb(s_inc, m, mlen, ctx); - haraka_S_inc_finalize(s_inc); - haraka_S_inc_squeeze(buf, SPX_DGST_BYTES, s_inc, ctx); - - memcpy(digest, bufp, SPX_FORS_MSG_BYTES); - bufp += SPX_FORS_MSG_BYTES; - - - *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); - *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); - bufp += SPX_TREE_BYTES; - - *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); - *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/merkle.c b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/merkle.c deleted file mode 100644 index 0c1479fd93..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/merkle.c +++ /dev/null @@ -1,59 +0,0 @@ -#include -#include - -#include "address.h" -#include "merkle.h" -#include "params.h" -#include "utils.h" -#include "utilsx1.h" -#include "wots.h" -#include "wotsx1.h" - -/* - * This generates a Merkle signature (WOTS signature followed by the Merkle - * authentication path). This is in this file because most of the complexity - * is involved with the WOTS signature; the Merkle authentication path logic - * is mostly hidden in treehashx4 - */ -void merkle_sign(uint8_t *sig, unsigned char *root, - const spx_ctx *ctx, - uint32_t wots_addr[8], uint32_t tree_addr[8], - uint32_t idx_leaf) { - unsigned char *auth_path = sig + SPX_WOTS_BYTES; - struct leaf_info_x1 info = { 0 }; - unsigned steps[ SPX_WOTS_LEN ]; - - info.wots_sig = sig; - chain_lengths(steps, root); - info.wots_steps = steps; - - set_type(&tree_addr[0], SPX_ADDR_TYPE_HASHTREE); - set_type(&info.pk_addr[0], SPX_ADDR_TYPE_WOTSPK); - copy_subtree_addr(&info.leaf_addr[0], wots_addr); - copy_subtree_addr(&info.pk_addr[0], wots_addr); - - info.wots_sign_leaf = idx_leaf; - - treehashx1(root, auth_path, ctx, - idx_leaf, 0, - SPX_TREE_HEIGHT, - wots_gen_leafx1, - tree_addr, &info); -} - -/* Compute root node of the top-most subtree. */ -void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { - /* We do not need the auth path in key generation, but it simplifies the - code to have just one treehash routine that computes both root and path - in one function. */ - unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; - uint32_t top_tree_addr[8] = {0}; - uint32_t wots_addr[8] = {0}; - - set_layer_addr(top_tree_addr, SPX_D - 1); - set_layer_addr(wots_addr, SPX_D - 1); - - merkle_sign(auth_path, root, ctx, - wots_addr, top_tree_addr, - (uint32_t)~0 /* ~0 means "don't bother generating an auth path */ ); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/merkle.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/merkle.h deleted file mode 100644 index 769cf2e970..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/merkle.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef MERKLE_H_ -#define MERKLE_H_ - -#include - -#include "context.h" -#include "params.h" - -/* Generate a Merkle signature (WOTS signature followed by the Merkle */ -/* authentication path) */ -#define merkle_sign SPX_NAMESPACE(merkle_sign) -void merkle_sign(uint8_t *sig, unsigned char *root, - const spx_ctx *ctx, - uint32_t wots_addr[8], uint32_t tree_addr[8], - uint32_t idx_leaf); - -/* Compute the root node of the top-most subtree. */ -#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) -void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); - -#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/nistapi.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/nistapi.h deleted file mode 100644 index 3cb71afad4..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/nistapi.h +++ /dev/null @@ -1,87 +0,0 @@ -#ifndef SPX_API_H -#define SPX_API_H - -#include -#include - -#include "params.h" - -#define CRYPTO_ALGNAME "SPHINCS+" - -#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES -#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES -#define CRYPTO_BYTES SPX_BYTES -#define CRYPTO_SEEDBYTES (3*SPX_N) - -/* - * Returns the length of a secret key, in bytes - */ -#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) -size_t crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) -size_t crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) -size_t crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) -size_t crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) -int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) -int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) -int crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) -int crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -#define crypto_sign SPX_NAMESPACE(crypto_sign) -int crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) -int crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/params.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/params.h deleted file mode 100644 index ca96907eeb..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/params.h +++ /dev/null @@ -1,56 +0,0 @@ -#ifndef SPX_PARAMS_H -#define SPX_PARAMS_H - -#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_##s - -/* Hash output length in bytes. */ -#define SPX_N 32 -/* Height of the hypertree. */ -#define SPX_FULL_HEIGHT 68 -/* Number of subtree layer. */ -#define SPX_D 17 -/* FORS tree dimensions. */ -#define SPX_FORS_HEIGHT 9 -#define SPX_FORS_TREES 35 -/* Winternitz parameter, */ -#define SPX_WOTS_W 16 - -/* The hash function is defined by linking a different hash.c file, as opposed - to setting a #define constant. */ - -/* For clarity */ -#define SPX_ADDR_BYTES 32 - -/* WOTS parameters. */ -#define SPX_WOTS_LOGW 4 - -#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) - -/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#define SPX_WOTS_LEN2 3 - -#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) -#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) -#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES - -/* Subtree size. */ -#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) - -//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT -// #error SPX_D should always divide SPX_FULL_HEIGHT -//#endif - -/* FORS parameters. */ -#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) -#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) -#define SPX_FORS_PK_BYTES SPX_N - -/* Resulting SPX sizes. */ -#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ - SPX_FULL_HEIGHT * SPX_N) -#define SPX_PK_BYTES (2 * SPX_N) -#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) - -#include "haraka_offsets.h" - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/sign.c b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/sign.c deleted file mode 100644 index 9d0c7d1b22..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/sign.c +++ /dev/null @@ -1,286 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "context.h" -#include "fors.h" -#include "hash.h" -#include "merkle.h" -#include "nistapi.h" -#include "params.h" -#include "randombytes.h" -#include "thash.h" -#include "utils.h" -#include "wots.h" - -/* - * Returns the length of a secret key, in bytes - */ -size_t crypto_sign_secretkeybytes(void) { - return CRYPTO_SECRETKEYBYTES; -} - -/* - * Returns the length of a public key, in bytes - */ -size_t crypto_sign_publickeybytes(void) { - return CRYPTO_PUBLICKEYBYTES; -} - -/* - * Returns the length of a signature, in bytes - */ -size_t crypto_sign_bytes(void) { - return CRYPTO_BYTES; -} - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t crypto_sign_seedbytes(void) { - return CRYPTO_SEEDBYTES; -} - -/* - * Generates an SPX key pair given a seed of length - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed) { - spx_ctx ctx; - - /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ - memcpy(sk, seed, CRYPTO_SEEDBYTES); - - memcpy(pk, sk + 2 * SPX_N, SPX_N); - - memcpy(ctx.pub_seed, pk, SPX_N); - memcpy(ctx.sk_seed, sk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - /* Compute root node of the top-most subtree. */ - merkle_gen_root(sk + 3 * SPX_N, &ctx); - - // cleanup - free_hash_function(&ctx); - - memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); - - return 0; -} - -/* - * Generates an SPX key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { - uint8_t seed[CRYPTO_SEEDBYTES]; - randombytes(seed, CRYPTO_SEEDBYTES); - crypto_sign_seed_keypair(pk, sk, seed); - - return 0; -} - -/** - * Returns an array containing a detached signature. - */ -int crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - spx_ctx ctx; - - const uint8_t *sk_prf = sk + SPX_N; - const uint8_t *pk = sk + 2 * SPX_N; - - uint8_t optrand[SPX_N]; - uint8_t mhash[SPX_FORS_MSG_BYTES]; - uint8_t root[SPX_N]; - uint32_t i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - - memcpy(ctx.sk_seed, sk, SPX_N); - memcpy(ctx.pub_seed, pk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - set_type(wots_addr, SPX_ADDR_TYPE_WOTS); - set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); - - /* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ - randombytes(optrand, SPX_N); - /* Compute the digest randomization value. */ - gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); - - /* Derive the message digest and leaf index from R, PK and M. */ - hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); - sig += SPX_N; - - set_tree_addr(wots_addr, tree); - set_keypair_addr(wots_addr, idx_leaf); - - /* Sign the message hash using FORS. */ - fors_sign(sig, root, mhash, &ctx, wots_addr); - sig += SPX_FORS_BYTES; - - for (i = 0; i < SPX_D; i++) { - set_layer_addr(tree_addr, i); - set_tree_addr(tree_addr, tree); - - copy_subtree_addr(wots_addr, tree_addr); - set_keypair_addr(wots_addr, idx_leaf); - - merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); - sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); - tree = tree >> SPX_TREE_HEIGHT; - } - - free_hash_function(&ctx); - - *siglen = SPX_BYTES; - - return 0; -} - -/** - * Verifies a detached signature and message under a given public key. - */ -int crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk) { - spx_ctx ctx; - const uint8_t *pub_root = pk + SPX_N; - uint8_t mhash[SPX_FORS_MSG_BYTES]; - uint8_t wots_pk[SPX_WOTS_BYTES]; - uint8_t root[SPX_N]; - uint8_t leaf[SPX_N]; - unsigned int i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - if (siglen != SPX_BYTES) { - return -1; - } - - memcpy(ctx.pub_seed, pk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - set_type(wots_addr, SPX_ADDR_TYPE_WOTS); - set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); - set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); - - /* Derive the message digest and leaf index from R || PK || M. */ - /* The additional SPX_N is a result of the hash domain separator. */ - hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); - sig += SPX_N; - - /* Layer correctly defaults to 0, so no need to set_layer_addr */ - set_tree_addr(wots_addr, tree); - set_keypair_addr(wots_addr, idx_leaf); - - fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); - sig += SPX_FORS_BYTES; - - /* For each subtree.. */ - for (i = 0; i < SPX_D; i++) { - set_layer_addr(tree_addr, i); - set_tree_addr(tree_addr, tree); - - copy_subtree_addr(wots_addr, tree_addr); - set_keypair_addr(wots_addr, idx_leaf); - - copy_keypair_addr(wots_pk_addr, wots_addr); - - /* The WOTS public key is only correct if the signature was correct. */ - /* Initially, root is the FORS pk, but on subsequent iterations it is - the root of the subtree below the currently processed subtree. */ - wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); - sig += SPX_WOTS_BYTES; - - /* Compute the leaf node using the WOTS public key. */ - thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); - - /* Compute the root node of this subtree. */ - compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, - &ctx, tree_addr); - sig += SPX_TREE_HEIGHT * SPX_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); - tree = tree >> SPX_TREE_HEIGHT; - } - - // cleanup - free_hash_function(&ctx); - - /* Check if the root node equals the root node in the public key. */ - if (memcmp(root, pub_root, SPX_N) != 0) { - return -1; - } - - return 0; -} - - -/** - * Returns an array containing the signature followed by the message. - */ -int crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk) { - size_t siglen; - - crypto_sign_signature(sm, &siglen, m, mlen, sk); - - memmove(sm + SPX_BYTES, m, mlen); - *smlen = siglen + mlen; - - return 0; -} - -/** - * Verifies a given signature-message pair under a given public key. - */ -int crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk) { - /* The API caller does not necessarily know what size a signature should be - but SPHINCS+ signatures are always exactly SPX_BYTES. */ - if (smlen < SPX_BYTES) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - *mlen = smlen - SPX_BYTES; - - if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - /* If verification was successful, move the message to the right place. */ - memmove(m, sm + SPX_BYTES, *mlen); - - return 0; -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/thash.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/thash.h deleted file mode 100644 index 8687ccfb4d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/thash.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef SPX_THASH_H -#define SPX_THASH_H - -#include "context.h" -#include "params.h" - -#include - -#define thash SPX_NAMESPACE(thash) -void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/thash_haraka_simple.c b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/thash_haraka_simple.c deleted file mode 100644 index 207777bf8d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/thash_haraka_simple.c +++ /dev/null @@ -1,36 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "thash.h" -#include "utils.h" - -#include "haraka.h" - -/** - * Takes an array of inblocks concatenated arrays of SPX_N bytes. - */ -void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]) { - PQCLEAN_VLA(uint8_t, buf, SPX_ADDR_BYTES + inblocks * SPX_N); - unsigned char outbuf[32]; - unsigned char buf_tmp[64]; - - if (inblocks == 1) { - /* F function */ - /* Since SPX_N may be smaller than 32, we need a temporary buffer. */ - memset(buf_tmp, 0, 64); - memcpy(buf_tmp, addr, 32); - memcpy(buf_tmp + SPX_ADDR_BYTES, in, SPX_N); - - haraka512(outbuf, buf_tmp, ctx); - memcpy(out, outbuf, SPX_N); - } else { - /* All other tweakable hashes*/ - memcpy(buf, addr, 32); - memcpy(buf + SPX_ADDR_BYTES, in, inblocks * SPX_N); - - haraka_S(out, SPX_N, buf, SPX_ADDR_BYTES + inblocks * SPX_N, ctx); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/utils.c b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/utils.c deleted file mode 100644 index 177b541fb9..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/utils.c +++ /dev/null @@ -1,148 +0,0 @@ -#include - -#include "utils.h" - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "thash.h" - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void ull_to_bytes(unsigned char *out, unsigned int outlen, - unsigned long long in) { - int i; - - /* Iterate over out in decreasing order, for big-endianness. */ - for (i = (signed int)outlen - 1; i >= 0; i--) { - out[i] = in & 0xff; - in = in >> 8; - } -} - -void u32_to_bytes(unsigned char *out, uint32_t in) { - out[0] = (unsigned char)(in >> 24); - out[1] = (unsigned char)(in >> 16); - out[2] = (unsigned char)(in >> 8); - out[3] = (unsigned char)in; -} - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { - unsigned long long retval = 0; - unsigned int i; - - for (i = 0; i < inlen; i++) { - retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); - } - return retval; -} - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void compute_root(unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const spx_ctx *ctx, uint32_t addr[8]) { - uint32_t i; - unsigned char buffer[2 * SPX_N]; - - /* If leaf_idx is odd (last bit = 1), current path element is a right child - and auth_path has to go left. Otherwise it is the other way around. */ - if (leaf_idx & 1) { - memcpy(buffer + SPX_N, leaf, SPX_N); - memcpy(buffer, auth_path, SPX_N); - } else { - memcpy(buffer, leaf, SPX_N); - memcpy(buffer + SPX_N, auth_path, SPX_N); - } - auth_path += SPX_N; - - for (i = 0; i < tree_height - 1; i++) { - leaf_idx >>= 1; - idx_offset >>= 1; - /* Set the address of the node we're creating. */ - set_tree_height(addr, i + 1); - set_tree_index(addr, leaf_idx + idx_offset); - - /* Pick the right or left neighbor, depending on parity of the node. */ - if (leaf_idx & 1) { - thash(buffer + SPX_N, buffer, 2, ctx, addr); - memcpy(buffer, auth_path, SPX_N); - } else { - thash(buffer, buffer, 2, ctx, addr); - memcpy(buffer + SPX_N, auth_path, SPX_N); - } - auth_path += SPX_N; - } - - /* The last iteration is exceptional; we do not copy an auth_path node. */ - leaf_idx >>= 1; - idx_offset >>= 1; - set_tree_height(addr, tree_height); - set_tree_index(addr, leaf_idx + idx_offset); - thash(root, buffer, 2, ctx, addr); -} - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const spx_ctx * /* ctx */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), - uint32_t tree_addr[8]) { - PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); - PQCLEAN_VLA(unsigned int, heights, tree_height + 1); - unsigned int offset = 0; - uint32_t idx; - uint32_t tree_idx; - - for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { - /* Add the next leaf node to the stack. */ - gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); - offset++; - heights[offset - 1] = 0; - - /* If this is a node we need for the auth path.. */ - if ((leaf_idx ^ 0x1) == idx) { - memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); - } - - /* While the top-most nodes are of equal height.. */ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { - /* Compute index of the new node, in the next layer. */ - tree_idx = (idx >> (heights[offset - 1] + 1)); - - /* Set the address of the node we're creating. */ - set_tree_height(tree_addr, heights[offset - 1] + 1); - set_tree_index(tree_addr, - tree_idx + (idx_offset >> (heights[offset - 1] + 1))); - /* Hash the top-most nodes from the stack together. */ - thash(stack + (offset - 2)*SPX_N, - stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); - offset--; - /* Note that the top-most node is now one layer higher. */ - heights[offset - 1]++; - - /* If this is a node we need for the auth path.. */ - if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_path + heights[offset - 1]*SPX_N, - stack + (offset - 1)*SPX_N, SPX_N); - } - } - } - memcpy(root, stack, SPX_N); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/utils.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/utils.h deleted file mode 100644 index 64f5d5a53a..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/utils.h +++ /dev/null @@ -1,58 +0,0 @@ -#ifndef SPX_UTILS_H -#define SPX_UTILS_H - -#include - -#include "compat.h" -#include "context.h" -#include "params.h" - - -/* To support MSVC use alloca() instead of VLAs. See #20. */ - - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) -void ull_to_bytes(unsigned char *out, unsigned int outlen, - unsigned long long in); -#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) -void u32_to_bytes(unsigned char *out, uint32_t in); - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) -unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -#define compute_root SPX_NAMESPACE(compute_root) -void compute_root(unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const spx_ctx *ctx, uint32_t addr[8]); - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -#define treehash SPX_NAMESPACE(treehash) -void treehash(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const spx_ctx *ctx /* ctx */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), - uint32_t tree_addr[8]); - - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/utilsx1.c b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/utilsx1.c deleted file mode 100644 index fccb69b35d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/utilsx1.c +++ /dev/null @@ -1,100 +0,0 @@ -#include - -#include "utilsx1.h" - -#include "address.h" -#include "params.h" -#include "thash.h" -#include "utils.h" - -/* - * Generate the entire Merkle tree, computing the authentication path for - * leaf_idx, and the resulting root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) - * - * This expects tree_addr to be initialized to the addr structures for the - * Merkle tree nodes - * - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - * - * This works by using the standard Merkle tree building algorithm, - */ -void treehashx1(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, - uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* Where to write the leaves */, - const spx_ctx * /* ctx */, - uint32_t idx, void *info), - uint32_t tree_addr[8], - void *info) { - /* This is where we keep the intermediate nodes */ - PQCLEAN_VLA(uint8_t, stack, tree_height * SPX_N); - - uint32_t idx; - uint32_t max_idx = (uint32_t)((1 << tree_height) - 1); - for (idx = 0;; idx++) { - unsigned char current[2 * SPX_N]; /* Current logical node is at */ - /* index[SPX_N]. We do this to minimize the number of copies */ - /* needed during a thash */ - gen_leaf( ¤t[SPX_N], ctx, idx + idx_offset, - info ); - - /* Now combine the freshly generated right node with previously */ - /* generated left ones */ - uint32_t internal_idx_offset = idx_offset; - uint32_t internal_idx = idx; - uint32_t internal_leaf = leaf_idx; - uint32_t h; /* The height we are in the Merkle tree */ - for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { - - /* Check if we hit the top of the tree */ - if (h == tree_height) { - /* We hit the root; return it */ - memcpy( root, ¤t[SPX_N], SPX_N ); - return; - } - - /* - * Check if the node we have is a part of the - * authentication path; if it is, write it out - */ - if ((internal_idx ^ internal_leaf) == 0x01) { - memcpy( &auth_path[ h * SPX_N ], - ¤t[SPX_N], - SPX_N ); - } - - /* - * Check if we're at a left child; if so, stop going up the stack - * Exception: if we've reached the end of the tree, keep on going - * (so we combine the last 4 nodes into the one root node in two - * more iterations) - */ - if ((internal_idx & 1) == 0 && idx < max_idx) { - break; - } - - /* Ok, we're at a right node */ - /* Now combine the left and right logical nodes together */ - - /* Set the address of the node we're creating. */ - internal_idx_offset >>= 1; - set_tree_height(tree_addr, h + 1); - set_tree_index(tree_addr, internal_idx / 2 + internal_idx_offset ); - - unsigned char *left = &stack[h * SPX_N]; - memcpy( ¤t[0], left, SPX_N ); - thash( ¤t[1 * SPX_N], - ¤t[0 * SPX_N], - 2, ctx, tree_addr); - } - - /* We've hit a left child; save the current for when we get the */ - /* corresponding right right */ - memcpy( &stack[h * SPX_N], ¤t[SPX_N], SPX_N); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/utilsx1.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/utilsx1.h deleted file mode 100644 index e911d17d53..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/utilsx1.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef SPX_UTILSX4_H -#define SPX_UTILSX4_H - -#include - -#include "context.h" -#include "params.h" - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -#define treehashx1 SPX_NAMESPACE(treehashx1) -void treehashx1(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* Where to write the leaf */, - const spx_ctx * /* ctx */, - uint32_t addr_idx, void *info), - uint32_t tree_addrx4[8], void *info); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/wots.c b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/wots.c deleted file mode 100644 index 249717aaa8..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/wots.c +++ /dev/null @@ -1,108 +0,0 @@ -#include -#include - -#include "wots.h" -#include "wotsx1.h" - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "thash.h" -#include "utils.h" -#include "utilsx1.h" - -// TODO clarify address expectations, and make them more uniform. -// TODO i.e. do we expect types to be set already? -// TODO and do we expect modifications or copies? - -/** - * Computes the chaining function. - * out and in have to be n-byte arrays. - * - * Interprets in as start-th value of the chain. - * addr has to contain the address of the chain. - */ -static void gen_chain(unsigned char *out, const unsigned char *in, - unsigned int start, unsigned int steps, - const spx_ctx *ctx, uint32_t addr[8]) { - uint32_t i; - - /* Initialize out with the value at position 'start'. */ - memcpy(out, in, SPX_N); - - /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < SPX_WOTS_W; i++) { - set_hash_addr(addr, i); - thash(out, out, 1, ctx, addr); - } -} - -/** - * base_w algorithm as described in draft. - * Interprets an array of bytes as integers in base w. - * This only works when log_w is a divisor of 8. - */ -static void base_w(unsigned int *output, const int out_len, - const unsigned char *input) { - int in = 0; - int out = 0; - unsigned char total = 0; - int bits = 0; - int consumed; - - for (consumed = 0; consumed < out_len; consumed++) { - if (bits == 0) { - total = input[in]; - in++; - bits += 8; - } - bits -= SPX_WOTS_LOGW; - output[out] = (total >> bits) & (SPX_WOTS_W - 1); - out++; - } -} - -/* Computes the WOTS+ checksum over a message (in base_w). */ -static void wots_checksum(unsigned int *csum_base_w, - const unsigned int *msg_base_w) { - unsigned int csum = 0; - unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; - unsigned int i; - - /* Compute checksum. */ - for (i = 0; i < SPX_WOTS_LEN1; i++) { - csum += SPX_WOTS_W - 1 - msg_base_w[i]; - } - - /* Convert checksum to base_w. */ - /* Make sure expected empty zero bits are the least significant bits. */ - csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); - ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); - base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); -} - -/* Takes a message and derives the matching chain lengths. */ -void chain_lengths(unsigned int *lengths, const unsigned char *msg) { - base_w(lengths, SPX_WOTS_LEN1, msg); - wots_checksum(lengths + SPX_WOTS_LEN1, lengths); -} - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const spx_ctx *ctx, uint32_t addr[8]) { - unsigned int lengths[SPX_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < SPX_WOTS_LEN; i++) { - set_chain_addr(addr, i); - gen_chain(pk + i * SPX_N, sig + i * SPX_N, - lengths[i], SPX_WOTS_W - 1 - lengths[i], ctx, addr); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/wots.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/wots.h deleted file mode 100644 index 4e7692eeef..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/wots.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef SPX_WOTS_H -#define SPX_WOTS_H - -#include - -#include "context.h" -#include "params.h" - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) -void wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const spx_ctx *ctx, uint32_t addr[8]); - -/* - * Compute the chain lengths needed for a given message hash - */ -#define chain_lengths SPX_NAMESPACE(chain_lengths) -void chain_lengths(unsigned int *lengths, const unsigned char *msg); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/wotsx1.c b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/wotsx1.c deleted file mode 100644 index 3adec78dfb..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/wotsx1.c +++ /dev/null @@ -1,76 +0,0 @@ -#include -#include - -#include "wots.h" -#include "wotsx1.h" - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "thash.h" -#include "utils.h" - -/* - * This generates a WOTS public key - * It also generates the WOTS signature if leaf_info indicates - * that we're signing with this WOTS key - */ -void wots_gen_leafx1(unsigned char *dest, - const spx_ctx *ctx, - uint32_t leaf_idx, void *v_info) { - struct leaf_info_x1 *info = v_info; - uint32_t *leaf_addr = info->leaf_addr; - uint32_t *pk_addr = info->pk_addr; - unsigned int i, k; - unsigned char pk_buffer[ SPX_WOTS_BYTES ]; - unsigned char *buffer; - uint32_t wots_k_mask; - - if (leaf_idx == info->wots_sign_leaf) { - /* We're traversing the leaf that's signing; generate the WOTS */ - /* signature */ - wots_k_mask = 0; - } else { - /* Nope, we're just generating pk's; turn off the signature logic */ - wots_k_mask = (uint32_t)~0; - } - - set_keypair_addr( leaf_addr, leaf_idx ); - set_keypair_addr( pk_addr, leaf_idx ); - - for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { - uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k to */ - /* the step if we're generating a signature, ~0 if we're not */ - - /* Start with the secret seed */ - set_chain_addr(leaf_addr, i); - set_hash_addr(leaf_addr, 0); - set_type(leaf_addr, SPX_ADDR_TYPE_WOTSPRF); - - prf_addr(buffer, ctx, leaf_addr); - - set_type(leaf_addr, SPX_ADDR_TYPE_WOTS); - - /* Iterate down the WOTS chain */ - for (k = 0;; k++) { - /* Check if this is the value that needs to be saved as a */ - /* part of the WOTS signature */ - if (k == wots_k) { - memcpy( info->wots_sig + i * SPX_N, buffer, SPX_N ); - } - - /* Check if we hit the top of the chain */ - if (k == SPX_WOTS_W - 1) { - break; - } - - /* Iterate one step on the chain */ - set_hash_addr(leaf_addr, k); - - thash(buffer, buffer, 1, ctx, leaf_addr); - } - } - - /* Do the final thash to generate the public keys */ - thash(dest, pk_buffer, SPX_WOTS_LEN, ctx, pk_addr); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/wotsx1.h b/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/wotsx1.h deleted file mode 100644 index e617929f96..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256f-simple_clean/wotsx1.h +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef WOTSX1_H_ -#define WOTSX1_H_ - -#include - -#include "context.h" -#include "params.h" - -/* - * This is here to provide an interface to the internal wots_gen_leafx1 - * routine. While this routine is not referenced in the package outside of - * wots.c, it is called from the stand-alone benchmark code to characterize - * the performance - */ -struct leaf_info_x1 { - unsigned char *wots_sig; - uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ - uint32_t *wots_steps; - uint32_t leaf_addr[8]; - uint32_t pk_addr[8]; -}; - -/* Macro to set the leaf_info to something 'benign', that is, it would */ -/* run with the same time as it does during the real signing process */ -/* Used only by the benchmark code */ -#define INITIALIZE_LEAF_INFO_X1(info, addr, step_buffer) { \ - (info).wots_sig = 0; \ - (info).wots_sign_leaf = ~0; \ - (info).wots_steps = step_buffer; \ - memcpy( &(info).leaf_addr[0], (addr), 32 ); \ - memcpy( &(info).pk_addr[0], (addr), 32 ); \ - } - -#define wots_gen_leafx1 SPX_NAMESPACE(wots_gen_leafx1) -void wots_gen_leafx1(unsigned char *dest, - const spx_ctx *ctx, - uint32_t leaf_idx, void *v_info); - -#endif /* WOTSX1_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/LICENSE b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/LICENSE deleted file mode 100644 index 670154e353..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/LICENSE +++ /dev/null @@ -1,116 +0,0 @@ -CC0 1.0 Universal - -Statement of Purpose - -The laws of most jurisdictions throughout the world automatically confer -exclusive Copyright and Related Rights (defined below) upon the creator and -subsequent owner(s) (each and all, an "owner") of an original work of -authorship and/or a database (each, a "Work"). - -Certain owners wish to permanently relinquish those rights to a Work for the -purpose of contributing to a commons of creative, cultural and scientific -works ("Commons") that the public can reliably and without fear of later -claims of infringement build upon, modify, incorporate in other works, reuse -and redistribute as freely as possible in any form whatsoever and for any -purposes, including without limitation commercial purposes. These owners may -contribute to the Commons to promote the ideal of a free culture and the -further production of creative, cultural and scientific works, or to gain -reputation or greater distribution for their Work in part through the use and -efforts of others. - -For these and/or other purposes and motivations, and without any expectation -of additional consideration or compensation, the person associating CC0 with a -Work (the "Affirmer"), to the extent that he or she is an owner of Copyright -and Related Rights in the Work, voluntarily elects to apply CC0 to the Work -and publicly distribute the Work under its terms, with knowledge of his or her -Copyright and Related Rights in the Work and the meaning and intended legal -effect of CC0 on those rights. - -1. Copyright and Related Rights. A Work made available under CC0 may be -protected by copyright and related or neighboring rights ("Copyright and -Related Rights"). Copyright and Related Rights include, but are not limited -to, the following: - - i. the right to reproduce, adapt, distribute, perform, display, communicate, - and translate a Work; - - ii. moral rights retained by the original author(s) and/or performer(s); - - iii. publicity and privacy rights pertaining to a person's image or likeness - depicted in a Work; - - iv. rights protecting against unfair competition in regards to a Work, - subject to the limitations in paragraph 4(a), below; - - v. rights protecting the extraction, dissemination, use and reuse of data in - a Work; - - vi. database rights (such as those arising under Directive 96/9/EC of the - European Parliament and of the Council of 11 March 1996 on the legal - protection of databases, and under any national implementation thereof, - including any amended or successor version of such directive); and - - vii. other similar, equivalent or corresponding rights throughout the world - based on applicable law or treaty, and any national implementations thereof. - -2. Waiver. To the greatest extent permitted by, but not in contravention of, -applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and -unconditionally waives, abandons, and surrenders all of Affirmer's Copyright -and Related Rights and associated claims and causes of action, whether now -known or unknown (including existing as well as future claims and causes of -action), in the Work (i) in all territories worldwide, (ii) for the maximum -duration provided by applicable law or treaty (including future time -extensions), (iii) in any current or future medium and for any number of -copies, and (iv) for any purpose whatsoever, including without limitation -commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes -the Waiver for the benefit of each member of the public at large and to the -detriment of Affirmer's heirs and successors, fully intending that such Waiver -shall not be subject to revocation, rescission, cancellation, termination, or -any other legal or equitable action to disrupt the quiet enjoyment of the Work -by the public as contemplated by Affirmer's express Statement of Purpose. - -3. Public License Fallback. Should any part of the Waiver for any reason be -judged legally invalid or ineffective under applicable law, then the Waiver -shall be preserved to the maximum extent permitted taking into account -Affirmer's express Statement of Purpose. In addition, to the extent the Waiver -is so judged Affirmer hereby grants to each affected person a royalty-free, -non transferable, non sublicensable, non exclusive, irrevocable and -unconditional license to exercise Affirmer's Copyright and Related Rights in -the Work (i) in all territories worldwide, (ii) for the maximum duration -provided by applicable law or treaty (including future time extensions), (iii) -in any current or future medium and for any number of copies, and (iv) for any -purpose whatsoever, including without limitation commercial, advertising or -promotional purposes (the "License"). The License shall be deemed effective as -of the date CC0 was applied by Affirmer to the Work. Should any part of the -License for any reason be judged legally invalid or ineffective under -applicable law, such partial invalidity or ineffectiveness shall not -invalidate the remainder of the License, and in such case Affirmer hereby -affirms that he or she will not (i) exercise any of his or her remaining -Copyright and Related Rights in the Work or (ii) assert any associated claims -and causes of action with respect to the Work, in either case contrary to -Affirmer's express Statement of Purpose. - -4. Limitations and Disclaimers. - - a. No trademark or patent rights held by Affirmer are waived, abandoned, - surrendered, licensed or otherwise affected by this document. - - b. Affirmer offers the Work as-is and makes no representations or warranties - of any kind concerning the Work, express, implied, statutory or otherwise, - including without limitation warranties of title, merchantability, fitness - for a particular purpose, non infringement, or the absence of latent or - other defects, accuracy, or the present or absence of errors, whether or not - discoverable, all to the greatest extent permissible under applicable law. - - c. Affirmer disclaims responsibility for clearing rights of other persons - that may apply to the Work or any use thereof, including without limitation - any person's Copyright and Related Rights in the Work. Further, Affirmer - disclaims responsibility for obtaining any necessary consents, permissions - or other rights required for any use of the Work. - - d. Affirmer understands and acknowledges that Creative Commons is not a - party to this document and has no duty or obligation with respect to this - CC0 or use of the Work. - -For more information, please see - diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/address.c b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/address.c deleted file mode 100644 index b956e9cb29..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/address.c +++ /dev/null @@ -1,91 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "utils.h" - -/* - * Specify which level of Merkle tree (the "layer") we're working on - */ -void set_layer_addr(uint32_t addr[8], uint32_t layer) { - ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; -} - -/* - * Specify which Merkle tree within the level (the "tree address") we're working on - */ -void set_tree_addr(uint32_t addr[8], uint64_t tree) { - ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); -} - -/* - * Specify the reason we'll use this address structure for, that is, what - * hash will we compute with it. This is used so that unrelated types of - * hashes don't accidentally get the same address structure. The type will be - * one of the SPX_ADDR_TYPE constants - */ -void set_type(uint32_t addr[8], uint32_t type) { - ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; -} - -/* - * Copy the layer and tree fields of the address structure. This is used - * when we're doing multiple types of hashes within the same Merkle tree - */ -void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { - memcpy( out, in, SPX_OFFSET_TREE + 8 ); -} - -/* These functions are used for OTS addresses. */ - -/* - * Specify which Merkle leaf we're working on; that is, which OTS keypair - * we're talking about. - */ -void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { - ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; -} - -/* - * Copy the layer, tree and keypair fields of the address structure. This is - * used when we're doing multiple things within the same OTS keypair - */ -void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { - memcpy( out, in, SPX_OFFSET_TREE + 8 ); - ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; -} - -/* - * Specify which Merkle chain within the OTS we're working with - * (the chain address) - */ -void set_chain_addr(uint32_t addr[8], uint32_t chain) { - ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; -} - -/* - * Specify where in the Merkle chain we are -* (the hash address) - */ -void set_hash_addr(uint32_t addr[8], uint32_t hash) { - ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; -} - -/* These functions are used for all hash tree addresses (including FORS). */ - -/* - * Specify the height of the node in the Merkle/FORS tree we are in - * (the tree height) - */ -void set_tree_height(uint32_t addr[8], uint32_t tree_height) { - ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; -} - -/* - * Specify the distance from the left edge of the node in the Merkle/FORS tree - * (the tree index) - */ -void set_tree_index(uint32_t addr[8], uint32_t tree_index) { - u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/address.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/address.h deleted file mode 100644 index 24a84eb40c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/address.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef SPX_ADDRESS_H -#define SPX_ADDRESS_H - -#include - -#include "params.h" - -/* The hash types that are passed to set_type */ -#define SPX_ADDR_TYPE_WOTS 0 -#define SPX_ADDR_TYPE_WOTSPK 1 -#define SPX_ADDR_TYPE_HASHTREE 2 -#define SPX_ADDR_TYPE_FORSTREE 3 -#define SPX_ADDR_TYPE_FORSPK 4 -#define SPX_ADDR_TYPE_WOTSPRF 5 -#define SPX_ADDR_TYPE_FORSPRF 6 - -#define set_layer_addr SPX_NAMESPACE(set_layer_addr) -void set_layer_addr(uint32_t addr[8], uint32_t layer); - -#define set_tree_addr SPX_NAMESPACE(set_tree_addr) -void set_tree_addr(uint32_t addr[8], uint64_t tree); - -#define set_type SPX_NAMESPACE(set_type) -void set_type(uint32_t addr[8], uint32_t type); - -/* Copies the layer and tree part of one address into the other */ -#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) -void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for WOTS and FORS addresses. */ - -#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) -void set_keypair_addr(uint32_t addr[8], uint32_t keypair); - -#define set_chain_addr SPX_NAMESPACE(set_chain_addr) -void set_chain_addr(uint32_t addr[8], uint32_t chain); - -#define set_hash_addr SPX_NAMESPACE(set_hash_addr) -void set_hash_addr(uint32_t addr[8], uint32_t hash); - -#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) -void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for all hash tree addresses (including FORS). */ - -#define set_tree_height SPX_NAMESPACE(set_tree_height) -void set_tree_height(uint32_t addr[8], uint32_t tree_height); - -#define set_tree_index SPX_NAMESPACE(set_tree_index) -void set_tree_index(uint32_t addr[8], uint32_t tree_index); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/api.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/api.h deleted file mode 100644 index 839bde0588..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/api.h +++ /dev/null @@ -1,77 +0,0 @@ -#ifndef PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_API_H -#define PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_API_H - -#include -#include - -#define PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_CRYPTO_ALGNAME "SPHINCS+-haraka-256s-robust" - -#define PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_CRYPTO_SECRETKEYBYTES 128 -#define PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_CRYPTO_PUBLICKEYBYTES 64 -#define PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_CRYPTO_BYTES 29792 - -#define PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_CRYPTO_SEEDBYTES 96 - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, - const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk); -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/context.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/context.h deleted file mode 100644 index f03446b9cb..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/context.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef SPX_CONTEXT_H -#define SPX_CONTEXT_H - -#include - -#include "immintrin.h" -#include "params.h" - -typedef struct { - uint8_t pub_seed[SPX_N]; - uint8_t sk_seed[SPX_N]; - - __m128i rc[40]; -} spx_ctx; - -#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) -void initialize_hash_function(spx_ctx *ctx); - -#define free_hash_function SPX_NAMESPACE(free_hash_function) -void free_hash_function(spx_ctx *ctx); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/context_haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/context_haraka.c deleted file mode 100644 index f1cd7e3664..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/context_haraka.c +++ /dev/null @@ -1,11 +0,0 @@ -#include "context.h" -#include "haraka.h" - -void initialize_hash_function(spx_ctx *ctx) { - tweak_constants(ctx); -} - -// we don't support heap-based haraka right now -void free_hash_function(spx_ctx *ctx) { - (void)ctx; // suppress unused variable warnings -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/fors.c b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/fors.c deleted file mode 100644 index f1b0639cfc..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/fors.c +++ /dev/null @@ -1,202 +0,0 @@ -#include -#include -#include - -#include "fors.h" - -#include "address.h" -#include "hash.h" -#include "hashx4.h" -#include "thash.h" -#include "thashx4.h" -#include "utils.h" -#include "utilsx4.h" - -static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, - uint32_t fors_leaf_addr[8]) { - prf_addr(sk, ctx, fors_leaf_addr); -} - -static void fors_gen_skx4(unsigned char *sk0, - unsigned char *sk1, - unsigned char *sk2, - unsigned char *sk3, const spx_ctx *ctx, - uint32_t fors_leaf_addrx4[4 * 8]) { - prf_addrx4(sk0, sk1, sk2, sk3, - ctx, fors_leaf_addrx4); -} - -static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, - const spx_ctx *ctx, - uint32_t fors_leaf_addr[8]) { - thash(leaf, sk, 1, ctx, fors_leaf_addr); -} - -static void fors_sk_to_leafx4(unsigned char *leaf0, - unsigned char *leaf1, - unsigned char *leaf2, - unsigned char *leaf3, - const unsigned char *sk0, - const unsigned char *sk1, - const unsigned char *sk2, - const unsigned char *sk3, - const spx_ctx *ctx, - uint32_t fors_leaf_addrx4[4 * 8]) { - thashx4(leaf0, leaf1, leaf2, leaf3, - sk0, sk1, sk2, sk3, - 1, ctx, fors_leaf_addrx4); -} - -struct fors_gen_leaf_info { - uint32_t leaf_addrx[4 * 8]; -}; - -static void fors_gen_leafx4(unsigned char *leaf, - const spx_ctx *ctx, - uint32_t addr_idx, void *info) { - struct fors_gen_leaf_info *fors_info = info; - uint32_t *fors_leaf_addrx4 = fors_info->leaf_addrx; - unsigned int j; - - /* Only set the parts that the caller doesn't set */ - for (j = 0; j < 4; j++) { - set_tree_index(fors_leaf_addrx4 + j * 8, addr_idx + j); - set_type(fors_leaf_addrx4 + j * 8, SPX_ADDR_TYPE_FORSPRF); - } - - fors_gen_skx4(leaf + 0 * SPX_N, - leaf + 1 * SPX_N, - leaf + 2 * SPX_N, - leaf + 3 * SPX_N, - ctx, fors_leaf_addrx4); - - for (j = 0; j < 4; j++) { - set_type(fors_leaf_addrx4 + j * 8, SPX_ADDR_TYPE_FORSTREE); - } - - fors_sk_to_leafx4(leaf + 0 * SPX_N, - leaf + 1 * SPX_N, - leaf + 2 * SPX_N, - leaf + 3 * SPX_N, - leaf + 0 * SPX_N, - leaf + 1 * SPX_N, - leaf + 2 * SPX_N, - leaf + 3 * SPX_N, - ctx, fors_leaf_addrx4); -} - -/** - * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - * Assumes indices has space for SPX_FORS_TREES integers. - */ -static void message_to_indices(uint32_t *indices, const unsigned char *m) { - unsigned int i, j; - unsigned int offset = 0; - - for (i = 0; i < SPX_FORS_TREES; i++) { - indices[i] = 0; - for (j = 0; j < SPX_FORS_HEIGHT; j++) { - indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); - offset++; - } - } -} - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -void fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]) { - uint32_t indices[SPX_FORS_TREES]; - unsigned char roots[SPX_FORS_TREES * SPX_N]; - uint32_t fors_tree_addr[4 * 8] = {0}; - struct fors_gen_leaf_info fors_info = {0}; - uint32_t *fors_leaf_addr = fors_info.leaf_addrx; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - for (i = 0; i < 4; i++) { - copy_keypair_addr(fors_tree_addr + 8 * i, fors_addr); - set_type(fors_tree_addr + 8 * i, SPX_ADDR_TYPE_FORSTREE); - copy_keypair_addr(fors_leaf_addr + 8 * i, fors_addr); - } - copy_keypair_addr(fors_pk_addr, fors_addr); - set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < SPX_FORS_TREES; i++) { - idx_offset = i * (1 << SPX_FORS_HEIGHT); - - set_tree_height(fors_tree_addr, 0); - set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Include the secret key part that produces the selected leaf node. */ - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); - fors_gen_sk(sig, ctx, fors_tree_addr); - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); - sig += SPX_N; - - /* Compute the authentication path for this leaf node. */ - treehashx4(roots + i * SPX_N, sig, ctx, - indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx4, - fors_tree_addr, &fors_info); - - sig += SPX_N * SPX_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); -} - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -void fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]) { - uint32_t indices[SPX_FORS_TREES]; - unsigned char roots[SPX_FORS_TREES * SPX_N]; - unsigned char leaf[SPX_N]; - uint32_t fors_tree_addr[8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - copy_keypair_addr(fors_tree_addr, fors_addr); - copy_keypair_addr(fors_pk_addr, fors_addr); - - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); - set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < SPX_FORS_TREES; i++) { - idx_offset = i * (1 << SPX_FORS_HEIGHT); - - set_tree_height(fors_tree_addr, 0); - set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Derive the leaf from the included secret key part. */ - fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); - sig += SPX_N; - - /* Derive the corresponding root node of this tree. */ - compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, - sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); - sig += SPX_N * SPX_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/fors.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/fors.h deleted file mode 100644 index 509140a178..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/fors.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef SPX_FORS_H -#define SPX_FORS_H - -#include - -#include "context.h" -#include "params.h" - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -#define fors_sign SPX_NAMESPACE(fors_sign) -void fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]); - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) -void fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/haraka.c deleted file mode 100644 index b414b691d7..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/haraka.c +++ /dev/null @@ -1,702 +0,0 @@ -/* -Plain C implementation of the Haraka256 and Haraka512 permutations. -*/ -#include -#include -#include -#include -#include - -#include "haraka.h" -#include "harakax4.h" -#include "utils.h" - -#define HARAKAS_RATE 32 - -#define u64 unsigned long -#define u128 __m128i - -#define LOAD(src) _mm_loadu_si128((u128 *)(src)) -#define STORE(dest,src) _mm_storeu_si128((u128 *)(dest),src) - -#define XOR128(a, b) _mm_xor_si128(a, b) - -#define AES2(s0, s1, rci) \ - s0 = _mm_aesenc_si128(s0, *(rci)); \ - (s1) = _mm_aesenc_si128(s1, *((rci) + 1)); \ - (s0) = _mm_aesenc_si128(s0, *((rci) + 2)); \ - (s1) = _mm_aesenc_si128(s1, *((rci) + 3)); - -#define AES2_4x(s0, s1, s2, s3, rci) \ - AES2((s0)[0], (s0)[1], rci); \ - AES2((s1)[0], (s1)[1], rci); \ - AES2((s2)[0], (s2)[1], rci); \ - AES2((s3)[0], (s3)[1], rci); - -#define AES4(s0, s1, s2, s3, rci) \ - s0 = _mm_aesenc_si128(s0, *(rci)); \ - (s1) = _mm_aesenc_si128(s1, *((rci) + 1)); \ - (s2) = _mm_aesenc_si128(s2, *((rci) + 2)); \ - (s3) = _mm_aesenc_si128(s3, *((rci) + 3)); \ - (s0) = _mm_aesenc_si128(s0, *((rci) + 4)); \ - (s1) = _mm_aesenc_si128(s1, *((rci) + 5)); \ - (s2) = _mm_aesenc_si128(s2, *((rci) + 6)); \ - (s3) = _mm_aesenc_si128(s3, *((rci) + 7)); - -#define AES4_4x(s0, s1, s2, s3, rci) \ - AES4((s0)[0], (s0)[1], (s0)[2], (s0)[3], rci); \ - AES4((s1)[0], (s1)[1], (s1)[2], (s1)[3], rci); \ - AES4((s2)[0], (s2)[1], (s2)[2], (s2)[3], rci); \ - AES4((s3)[0], (s3)[1], (s3)[2], (s3)[3], rci); - -#define MIX2(s0, s1) \ - tmp = _mm_unpacklo_epi32(s0, s1); \ - (s1) = _mm_unpackhi_epi32(s0, s1); \ - (s0) = tmp; - -#define MIX4(s0, s1, s2, s3) \ - tmp = _mm_unpacklo_epi32(s0, s1); \ - (s0) = _mm_unpackhi_epi32(s0, s1); \ - (s1) = _mm_unpacklo_epi32(s2, s3); \ - (s2) = _mm_unpackhi_epi32(s2, s3); \ - (s3) = _mm_unpacklo_epi32(s0, s2); \ - (s0) = _mm_unpackhi_epi32(s0, s2); \ - (s2) = _mm_unpackhi_epi32(s1, tmp); \ - (s1) = _mm_unpacklo_epi32(s1, tmp); - -#define TRUNCSTORE(out, s0, s1, s2, s3) \ - _mm_storeu_si128((u128 *)(out), \ - _mm_castpd_si128(_mm_shuffle_pd(_mm_castsi128_pd(s0), _mm_castsi128_pd(s1), 3))); \ - _mm_storeu_si128((u128 *)((out) + 16), \ - _mm_castpd_si128(_mm_shuffle_pd(_mm_castsi128_pd(s2), _mm_castsi128_pd(s3), 0))); - -static void load_haraka_constants(u128 *rc) { - rc[0] = _mm_set_epi32((int)0x0684704c, (int)0xe620c00a, (int)0xb2c5fef0, (int)0x75817b9d); - rc[1] = _mm_set_epi32((int)0x8b66b4e1, (int)0x88f3a06b, (int)0x640f6ba4, (int)0x2f08f717); - rc[2] = _mm_set_epi32((int)0x3402de2d, (int)0x53f28498, (int)0xcf029d60, (int)0x9f029114); - rc[3] = _mm_set_epi32((int)0x0ed6eae6, (int)0x2e7b4f08, (int)0xbbf3bcaf, (int)0xfd5b4f79); - rc[4] = _mm_set_epi32((int)0xcbcfb0cb, (int)0x4872448b, (int)0x79eecd1c, (int)0xbe397044); - rc[5] = _mm_set_epi32((int)0x7eeacdee, (int)0x6e9032b7, (int)0x8d5335ed, (int)0x2b8a057b); - rc[6] = _mm_set_epi32((int)0x67c28f43, (int)0x5e2e7cd0, (int)0xe2412761, (int)0xda4fef1b); - rc[7] = _mm_set_epi32((int)0x2924d9b0, (int)0xafcacc07, (int)0x675ffde2, (int)0x1fc70b3b); - rc[8] = _mm_set_epi32((int)0xab4d63f1, (int)0xe6867fe9, (int)0xecdb8fca, (int)0xb9d465ee); - rc[9] = _mm_set_epi32((int)0x1c30bf84, (int)0xd4b7cd64, (int)0x5b2a404f, (int)0xad037e33); - rc[10] = _mm_set_epi32((int)0xb2cc0bb9, (int)0x941723bf, (int)0x69028b2e, (int)0x8df69800); - rc[11] = _mm_set_epi32((int)0xfa0478a6, (int)0xde6f5572, (int)0x4aaa9ec8, (int)0x5c9d2d8a); - rc[12] = _mm_set_epi32((int)0xdfb49f2b, (int)0x6b772a12, (int)0x0efa4f2e, (int)0x29129fd4); - rc[13] = _mm_set_epi32((int)0x1ea10344, (int)0xf449a236, (int)0x32d611ae, (int)0xbb6a12ee); - rc[14] = _mm_set_epi32((int)0xaf044988, (int)0x4b050084, (int)0x5f9600c9, (int)0x9ca8eca6); - rc[15] = _mm_set_epi32((int)0x21025ed8, (int)0x9d199c4f, (int)0x78a2c7e3, (int)0x27e593ec); - rc[16] = _mm_set_epi32((int)0xbf3aaaf8, (int)0xa759c9b7, (int)0xb9282ecd, (int)0x82d40173); - rc[17] = _mm_set_epi32((int)0x6260700d, (int)0x6186b017, (int)0x37f2efd9, (int)0x10307d6b); - rc[18] = _mm_set_epi32((int)0x5aca45c2, (int)0x21300443, (int)0x81c29153, (int)0xf6fc9ac6); - rc[19] = _mm_set_epi32((int)0x9223973c, (int)0x226b68bb, (int)0x2caf92e8, (int)0x36d1943a); - rc[20] = _mm_set_epi32((int)0xd3bf9238, (int)0x225886eb, (int)0x6cbab958, (int)0xe51071b4); - rc[21] = _mm_set_epi32((int)0xdb863ce5, (int)0xaef0c677, (int)0x933dfddd, (int)0x24e1128d); - rc[22] = _mm_set_epi32((int)0xbb606268, (int)0xffeba09c, (int)0x83e48de3, (int)0xcb2212b1); - rc[23] = _mm_set_epi32((int)0x734bd3dc, (int)0xe2e4d19c, (int)0x2db91a4e, (int)0xc72bf77d); - rc[24] = _mm_set_epi32((int)0x43bb47c3, (int)0x61301b43, (int)0x4b1415c4, (int)0x2cb3924e); - rc[25] = _mm_set_epi32((int)0xdba775a8, (int)0xe707eff6, (int)0x03b231dd, (int)0x16eb6899); - rc[26] = _mm_set_epi32((int)0x6df3614b, (int)0x3c755977, (int)0x8e5e2302, (int)0x7eca472c); - rc[27] = _mm_set_epi32((int)0xcda75a17, (int)0xd6de7d77, (int)0x6d1be5b9, (int)0xb88617f9); - rc[28] = _mm_set_epi32((int)0xec6b43f0, (int)0x6ba8e9aa, (int)0x9d6c069d, (int)0xa946ee5d); - rc[29] = _mm_set_epi32((int)0xcb1e6950, (int)0xf957332b, (int)0xa2531159, (int)0x3bf327c1); - rc[30] = _mm_set_epi32((int)0x2cee0c75, (int)0x00da619c, (int)0xe4ed0353, (int)0x600ed0d9); - rc[31] = _mm_set_epi32((int)0xf0b1a5a1, (int)0x96e90cab, (int)0x80bbbabc, (int)0x63a4a350); - rc[32] = _mm_set_epi32((int)0xae3db102, (int)0x5e962988, (int)0xab0dde30, (int)0x938dca39); - rc[33] = _mm_set_epi32((int)0x17bb8f38, (int)0xd554a40b, (int)0x8814f3a8, (int)0x2e75b442); - rc[34] = _mm_set_epi32((int)0x34bb8a5b, (int)0x5f427fd7, (int)0xaeb6b779, (int)0x360a16f6); - rc[35] = _mm_set_epi32((int)0x26f65241, (int)0xcbe55438, (int)0x43ce5918, (int)0xffbaafde); - rc[36] = _mm_set_epi32((int)0x4ce99a54, (int)0xb9f3026a, (int)0xa2ca9cf7, (int)0x839ec978); - rc[37] = _mm_set_epi32((int)0xae51a51a, (int)0x1bdff7be, (int)0x40c06e28, (int)0x22901235); - rc[38] = _mm_set_epi32((int)0xa0c1613c, (int)0xba7ed22b, (int)0xc173bc0f, (int)0x48a659cf); - rc[39] = _mm_set_epi32((int)0x756acc03, (int)0x02288288, (int)0x4ad6bdfd, (int)0xe9c59da1); -} - -void tweak_constants(spx_ctx *ctx) { - int i; - unsigned char buf[40 * 16]; - - /* Use the standard constants to generate tweaked ones. */ - load_haraka_constants(ctx->rc); - - /* Constants for pk.seed */ - haraka_S(buf, 40 * 16, ctx->pub_seed, SPX_N, ctx); - - /* Tweak constants with the pub_seed */ - for (i = 0; i < 40; i++) { - ctx->rc[i] = LOAD(buf + i * 16); - } -} - -static void haraka_S_absorb(unsigned char *s, unsigned int r, - const unsigned char *m, unsigned long long mlen, - unsigned char p, const spx_ctx *ctx) { - unsigned long long i; - PQCLEAN_VLA(unsigned char, t, r); - - while (mlen >= r) { - // XOR block to state - STORE(s, XOR128(LOAD(s), LOAD(m))); - STORE(s + 16, XOR128(LOAD(s + 16), LOAD(m + 16))); - haraka512_perm(s, s, ctx); - 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; - STORE(s, XOR128(LOAD(s), LOAD(t))); - STORE(s + 16, XOR128(LOAD(s + 16), LOAD(t + 16))); -} - -static void haraka_S_absorb4x(unsigned char *s, - unsigned int r, - const unsigned char *m0, - const unsigned char *m1, - const unsigned char *m2, - const unsigned char *m3, - unsigned long long int mlen, - unsigned char p, - const spx_ctx *ctx) { - unsigned long long i; - PQCLEAN_VLA(unsigned char, t0, r); - PQCLEAN_VLA(unsigned char, t1, r); - PQCLEAN_VLA(unsigned char, t2, r); - PQCLEAN_VLA(unsigned char, t3, r); - - while (mlen >= r) { - // XOR block to state - STORE(s, XOR128(LOAD(s), LOAD(m0))); - STORE(s + 16, XOR128(LOAD(s + 16), LOAD(m0 + 16))); - STORE(s + 64, XOR128(LOAD(s + 64), LOAD(m1))); - STORE(s + 80, XOR128(LOAD(s + 80), LOAD(m1 + 16))); - STORE(s + 128, XOR128(LOAD(s + 128), LOAD(m2))); - STORE(s + 144, XOR128(LOAD(s + 144), LOAD(m2 + 16))); - STORE(s + 192, XOR128(LOAD(s + 192), LOAD(m3))); - STORE(s + 208, XOR128(LOAD(s + 208), LOAD(m3 + 16))); - - haraka512_perm_x4(s, s, ctx); - mlen -= r; - m0 += r; - m1 += r; - m2 += r; - m3 += r; - } - - for (i = 0; i < r; ++i) { - t0[i] = 0; - t1[i] = 0; - t2[i] = 0; - t3[i] = 0; - } - for (i = 0; i < mlen; ++i) { - t0[i] = m0[i]; - t1[i] = m1[i]; - t2[i] = m2[i]; - t3[i] = m3[i]; - } - - t0[i] = p; - t1[i] = p; - t2[i] = p; - t3[i] = p; - - t0[r - 1] |= 128; - t1[r - 1] |= 128; - t2[r - 1] |= 128; - t3[r - 1] |= 128; - - STORE(s, XOR128(LOAD(s), LOAD(t0))); - STORE(s + 16, XOR128(LOAD(s + 16), LOAD(t0 + 16))); - STORE(s + 64, XOR128(LOAD(s + 64), LOAD(t1))); - STORE(s + 80, XOR128(LOAD(s + 80), LOAD(t1 + 16))); - STORE(s + 128, XOR128(LOAD(s + 128), LOAD(t2))); - STORE(s + 144, XOR128(LOAD(s + 144), LOAD(t2 + 16))); - STORE(s + 192, XOR128(LOAD(s + 192), LOAD(t3))); - STORE(s + 208, XOR128(LOAD(s + 208), LOAD(t3 + 16))); -} - -static void haraka_S_squeezeblocks(unsigned char *h, unsigned long long nblocks, - unsigned char *s, unsigned int r, - const spx_ctx *ctx) { - while (nblocks > 0) { - haraka512_perm(s, s, ctx); - STORE(h, LOAD(s)); - STORE(h + 16, LOAD(s + 16)); - h += r; - nblocks--; - } -} - -static void haraka_S_squeezeblocks4x(unsigned char *h0, - unsigned char *h1, - unsigned char *h2, - unsigned char *h3, - unsigned long long nblocks, - unsigned char *s, - unsigned int r, - const spx_ctx *ctx) { - while (nblocks > 0) { - haraka512_perm_x4(s, s, ctx); - STORE(h0, LOAD(s)); - STORE(h0 + 16, LOAD(s + 16)); - STORE(h1, LOAD(s + 64)); - STORE(h1 + 16, LOAD(s + 80)); - STORE(h2, LOAD(s + 128)); - STORE(h2 + 16, LOAD(s + 144)); - STORE(h3, LOAD(s + 192)); - STORE(h3 + 16, LOAD(s + 208)); - h0 += r; - h1 += r; - h2 += r; - h3 += r; - nblocks--; - } -} - -void haraka_S_inc_init(uint8_t *s_inc) { - size_t i; - - for (i = 0; i < 64; i++) { - s_inc[i] = 0; - } - s_inc[64] = 0; -} - -void haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, - const spx_ctx *ctx) { - size_t i; - - /* Recall that s_inc[64] is the non-absorbed bytes xored into the state */ - while (mlen + s_inc[64] >= HARAKAS_RATE) { - for (i = 0; i < (size_t)(HARAKAS_RATE - s_inc[64]); i++) { - /* Take the i'th byte from message - xor with the s_inc[64] + i'th byte of the state */ - s_inc[s_inc[64] + i] ^= m[i]; - } - mlen -= (size_t)(HARAKAS_RATE - s_inc[64]); - m += HARAKAS_RATE - s_inc[64]; - s_inc[64] = 0; - - haraka512_perm(s_inc, s_inc, ctx); - } - - for (i = 0; i < mlen; i++) { - s_inc[s_inc[64] + i] ^= m[i]; - } - s_inc[64] += (uint8_t)mlen; -} - -void haraka_S_inc_finalize(uint8_t *s_inc) { - /* After haraka_S_inc_absorb, we are guaranteed that s_inc[64] < HARAKAS_RATE, - so we can always use one more byte for p in the current state. */ - s_inc[s_inc[64]] ^= 0x1F; - s_inc[HARAKAS_RATE - 1] ^= 128; - s_inc[64] = 0; -} - -void haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, - const spx_ctx *ctx) { - size_t i; - - /* First consume any bytes we still have sitting around */ - for (i = 0; i < outlen && i < s_inc[64]; i++) { - /* There are s_inc[64] bytes left, so r - s_inc[64] is the first - available byte. We consume from there, i.e., up to r. */ - out[i] = (uint8_t)s_inc[(HARAKAS_RATE - s_inc[64] + i)]; - } - out += i; - outlen -= i; - s_inc[64] -= (uint8_t)i; - - /* Then squeeze the remaining necessary blocks */ - while (outlen > 0) { - haraka512_perm(s_inc, s_inc, ctx); - - for (i = 0; i < outlen && i < HARAKAS_RATE; i++) { - out[i] = s_inc[i]; - } - out += i; - outlen -= i; - s_inc[64] = (uint8_t)(HARAKAS_RATE - i); - } -} - -void haraka_S(unsigned char *out, unsigned long long outlen, - const unsigned char *in, unsigned long long inlen, - const spx_ctx *ctx) { - unsigned long long i; - unsigned char s[64]; - unsigned char d[32]; - - for (i = 0; i < 64; i++) { - s[i] = 0; - } - haraka_S_absorb(s, HARAKAS_RATE, in, inlen, 0x1F, ctx); - - haraka_S_squeezeblocks(out, outlen / HARAKAS_RATE, s, HARAKAS_RATE, ctx); - out += (outlen / HARAKAS_RATE) * HARAKAS_RATE; - - if (outlen % HARAKAS_RATE) { - haraka_S_squeezeblocks(d, 1, s, HARAKAS_RATE, ctx); - for (i = 0; i < outlen % HARAKAS_RATE; i++) { - out[i] = d[i]; - } - } -} - -void haraka_Sx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned long long outlen, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - unsigned long long inlen, - const spx_ctx *ctx) { - unsigned long long i; - unsigned char s[64 * 4]; - unsigned char d0[32]; - unsigned char d1[32]; - unsigned char d2[32]; - unsigned char d3[32]; - - for (i = 0; i < 64 * 4; i++) { - s[i] = 0; - } - haraka_S_absorb4x(s, HARAKAS_RATE, in0, in1, in2, in3, inlen, 0x1F, ctx); - - haraka_S_squeezeblocks4x(out0, out1, out2, out3, outlen / HARAKAS_RATE, s, - HARAKAS_RATE, ctx); - out0 += (outlen / HARAKAS_RATE) * HARAKAS_RATE; - out1 += (outlen / HARAKAS_RATE) * HARAKAS_RATE; - out2 += (outlen / HARAKAS_RATE) * HARAKAS_RATE; - out3 += (outlen / HARAKAS_RATE) * HARAKAS_RATE; - - if (outlen % HARAKAS_RATE) { - haraka_S_squeezeblocks4x(d0, d1, d2, d3, 1, s, HARAKAS_RATE, ctx); - for (i = 0; i < outlen % HARAKAS_RATE; i++) { - out0[i] = d0[i]; - out1[i] = d1[i]; - out2[i] = d2[i]; - out3[i] = d3[i]; - } - } -} - -void haraka512_perm(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx) { - u128 s[4], tmp; - - s[0] = LOAD(in); - s[1] = LOAD(in + 16); - s[2] = LOAD(in + 32); - s[3] = LOAD(in + 48); - - AES4(s[0], s[1], s[2], s[3], ctx->rc); - MIX4(s[0], s[1], s[2], s[3]); - - AES4(s[0], s[1], s[2], s[3], ctx->rc + 8); - MIX4(s[0], s[1], s[2], s[3]); - - AES4(s[0], s[1], s[2], s[3], ctx->rc + 16); - MIX4(s[0], s[1], s[2], s[3]); - - AES4(s[0], s[1], s[2], s[3], ctx->rc + 24); - MIX4(s[0], s[1], s[2], s[3]); - - AES4(s[0], s[1], s[2], s[3], ctx->rc + 32); - MIX4(s[0], s[1], s[2], s[3]); - - STORE(out, s[0]); - STORE(out + 16, s[1]); - STORE(out + 32, s[2]); - STORE(out + 48, s[3]); -} - -void haraka512_perm_x4(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx) { - u128 s[4][4], tmp; - - s[0][0] = LOAD(in); - s[0][1] = LOAD(in + 16); - s[0][2] = LOAD(in + 32); - s[0][3] = LOAD(in + 48); - s[1][0] = LOAD(in + 64); - s[1][1] = LOAD(in + 80); - s[1][2] = LOAD(in + 96); - s[1][3] = LOAD(in + 112); - s[2][0] = LOAD(in + 128); - s[2][1] = LOAD(in + 144); - s[2][2] = LOAD(in + 160); - s[2][3] = LOAD(in + 176); - s[3][0] = LOAD(in + 192); - s[3][1] = LOAD(in + 208); - s[3][2] = LOAD(in + 224); - s[3][3] = LOAD(in + 240); - - AES4_4x(s[0], s[1], s[2], s[3], ctx->rc); - MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); - MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); - MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); - MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - - AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 8); - MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); - MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); - MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); - MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - - AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 16); - MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); - MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); - MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); - MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - - AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 24); - MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); - MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); - MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); - MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - - AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 32); - MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); - MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); - MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); - MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - - STORE(out, s[0][0]); - STORE(out + 16, s[0][1]); - STORE(out + 32, s[0][2]); - STORE(out + 48, s[0][3]); - STORE(out + 64, s[1][0]); - STORE(out + 80, s[1][1]); - STORE(out + 96, s[1][2]); - STORE(out + 112, s[1][3]); - STORE(out + 128, s[2][0]); - STORE(out + 144, s[2][1]); - STORE(out + 160, s[2][2]); - STORE(out + 176, s[2][3]); - STORE(out + 192, s[3][0]); - STORE(out + 208, s[3][1]); - STORE(out + 224, s[3][2]); - STORE(out + 240, s[3][3]); -} - -void haraka512(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx) { - u128 s[4], tmp; - - s[0] = LOAD(in); - s[1] = LOAD(in + 16); - s[2] = LOAD(in + 32); - s[3] = LOAD(in + 48); - - AES4(s[0], s[1], s[2], s[3], ctx->rc); - MIX4(s[0], s[1], s[2], s[3]); - - AES4(s[0], s[1], s[2], s[3], ctx->rc + 8); - MIX4(s[0], s[1], s[2], s[3]); - - AES4(s[0], s[1], s[2], s[3], ctx->rc + 16); - MIX4(s[0], s[1], s[2], s[3]); - - AES4(s[0], s[1], s[2], s[3], ctx->rc + 24); - MIX4(s[0], s[1], s[2], s[3]); - - AES4(s[0], s[1], s[2], s[3], ctx->rc + 32); - MIX4(s[0], s[1], s[2], s[3]); - - s[0] = XOR128(s[0], LOAD(in)); - s[1] = XOR128(s[1], LOAD(in + 16)); - s[2] = XOR128(s[2], LOAD(in + 32)); - s[3] = XOR128(s[3], LOAD(in + 48)); - - // truncate and store result - TRUNCSTORE(out, s[0], s[1], s[2], s[3]); -} - -void haraka512x4(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx) { - u128 s[4][4], tmp; - - s[0][0] = LOAD(in); - s[0][1] = LOAD(in + 16); - s[0][2] = LOAD(in + 32); - s[0][3] = LOAD(in + 48); - s[1][0] = LOAD(in + 64); - s[1][1] = LOAD(in + 80); - s[1][2] = LOAD(in + 96); - s[1][3] = LOAD(in + 112); - s[2][0] = LOAD(in + 128); - s[2][1] = LOAD(in + 144); - s[2][2] = LOAD(in + 160); - s[2][3] = LOAD(in + 176); - s[3][0] = LOAD(in + 192); - s[3][1] = LOAD(in + 208); - s[3][2] = LOAD(in + 224); - s[3][3] = LOAD(in + 240); - - AES4_4x(s[0], s[1], s[2], s[3], ctx->rc); - MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); - MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); - MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); - MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - - AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 8); - MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); - MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); - MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); - MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - - AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 16); - MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); - MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); - MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); - MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - - AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 24); - MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); - MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); - MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); - MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - - AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 32); - MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); - MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); - MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); - MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - - s[0][0] = XOR128(s[0][0], LOAD(in)); - s[0][1] = XOR128(s[0][1], LOAD(in + 16)); - s[0][2] = XOR128(s[0][2], LOAD(in + 32)); - s[0][3] = XOR128(s[0][3], LOAD(in + 48)); - s[1][0] = XOR128(s[1][0], LOAD(in + 64)); - s[1][1] = XOR128(s[1][1], LOAD(in + 80)); - s[1][2] = XOR128(s[1][2], LOAD(in + 96)); - s[1][3] = XOR128(s[1][3], LOAD(in + 112)); - s[2][0] = XOR128(s[2][0], LOAD(in + 128)); - s[2][1] = XOR128(s[2][1], LOAD(in + 144)); - s[2][2] = XOR128(s[2][2], LOAD(in + 160)); - s[2][3] = XOR128(s[2][3], LOAD(in + 176)); - s[3][0] = XOR128(s[3][0], LOAD(in + 192)); - s[3][1] = XOR128(s[3][1], LOAD(in + 208)); - s[3][2] = XOR128(s[3][2], LOAD(in + 224)); - s[3][3] = XOR128(s[3][3], LOAD(in + 240)); - - TRUNCSTORE(out, s[0][0], s[0][1], s[0][2], s[0][3]); - TRUNCSTORE((out + 32), s[1][0], s[1][1], s[1][2], s[1][3]); - TRUNCSTORE((out + 64), s[2][0], s[2][1], s[2][2], s[2][3]); - TRUNCSTORE((out + 96), s[3][0], s[3][1], s[3][2], s[3][3]); -} - -void haraka256(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx) { - u128 s[2], tmp; - - s[0] = LOAD(in); - s[1] = LOAD(in + 16); - - AES2(s[0], s[1], ctx->rc); - MIX2(s[0], s[1]); - - AES2(s[0], s[1], ctx->rc + 4); - MIX2(s[0], s[1]); - - AES2(s[0], s[1], ctx->rc + 8); - MIX2(s[0], s[1]); - - AES2(s[0], s[1], ctx->rc + 12); - MIX2(s[0], s[1]); - - AES2(s[0], s[1], ctx->rc + 16); - MIX2(s[0], s[1]); - - s[0] = XOR128(s[0], LOAD(in)); - s[1] = XOR128(s[1], LOAD(in + 16)); - - STORE(out, s[0]); - STORE(out + 16, s[1]); -} - -void haraka256x4(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx) { - u128 s[4][2], tmp; - - s[0][0] = LOAD(in); - s[0][1] = LOAD(in + 16); - s[1][0] = LOAD(in + 32); - s[1][1] = LOAD(in + 48); - s[2][0] = LOAD(in + 64); - s[2][1] = LOAD(in + 80); - s[3][0] = LOAD(in + 96); - s[3][1] = LOAD(in + 112); - - // Round 1 - AES2_4x(s[0], s[1], s[2], s[3], ctx->rc); - - MIX2(s[0][0], s[0][1]); - MIX2(s[1][0], s[1][1]); - MIX2(s[2][0], s[2][1]); - MIX2(s[3][0], s[3][1]); - - // Round 2 - AES2_4x(s[0], s[1], s[2], s[3], ctx->rc + 4); - - MIX2(s[0][0], s[0][1]); - MIX2(s[1][0], s[1][1]); - MIX2(s[2][0], s[2][1]); - MIX2(s[3][0], s[3][1]); - - // Round 3 - AES2_4x(s[0], s[1], s[2], s[3], ctx->rc + 8); - - MIX2(s[0][0], s[0][1]); - MIX2(s[1][0], s[1][1]); - MIX2(s[2][0], s[2][1]); - MIX2(s[3][0], s[3][1]); - - // Round 4 - AES2_4x(s[0], s[1], s[2], s[3], ctx->rc + 12); - - MIX2(s[0][0], s[0][1]); - MIX2(s[1][0], s[1][1]); - MIX2(s[2][0], s[2][1]); - MIX2(s[3][0], s[3][1]); - - // Round 5 - AES2_4x(s[0], s[1], s[2], s[3], ctx->rc + 16); - - MIX2(s[0][0], s[0][1]); - MIX2(s[1][0], s[1][1]); - MIX2(s[2][0], s[2][1]); - MIX2(s[3][0], s[3][1]); - - // Feed Forward - s[0][0] = _mm_xor_si128(s[0][0], LOAD(in)); - s[0][1] = _mm_xor_si128(s[0][1], LOAD(in + 16)); - s[1][0] = _mm_xor_si128(s[1][0], LOAD(in + 32)); - s[1][1] = _mm_xor_si128(s[1][1], LOAD(in + 48)); - s[2][0] = _mm_xor_si128(s[2][0], LOAD(in + 64)); - s[2][1] = _mm_xor_si128(s[2][1], LOAD(in + 80)); - s[3][0] = _mm_xor_si128(s[3][0], LOAD(in + 96)); - s[3][1] = _mm_xor_si128(s[3][1], LOAD(in + 112)); - - STORE(out, s[0][0]); - STORE(out + 16, s[0][1]); - STORE(out + 32, s[1][0]); - STORE(out + 48, s[1][1]); - STORE(out + 64, s[2][0]); - STORE(out + 80, s[2][1]); - STORE(out + 96, s[3][0]); - STORE(out + 112, s[3][1]); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/haraka.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/haraka.h deleted file mode 100644 index 737cb6065f..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/haraka.h +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef SPX_HARAKA_H -#define SPX_HARAKA_H - -#include "context.h" -#include "params.h" - -/* Tweak constants with seed */ -#define tweak_constants SPX_NAMESPACE(tweak_constants) -void tweak_constants(spx_ctx *ctx); - -/* Haraka Sponge */ -#define haraka_S_inc_init SPX_NAMESPACE(haraka_S_inc_init) -void haraka_S_inc_init(uint8_t *s_inc); -#define haraka_S_inc_absorb SPX_NAMESPACE(haraka_S_inc_absorb) -void haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, - const spx_ctx *ctx); -#define haraka_S_inc_finalize SPX_NAMESPACE(haraka_S_inc_finalize) -void haraka_S_inc_finalize(uint8_t *s_inc); -#define haraka_S_inc_squeeze SPX_NAMESPACE(haraka_S_inc_squeeze) -void haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, - const spx_ctx *ctx); -#define haraka_S SPX_NAMESPACE(haraka_S) -void haraka_S(unsigned char *out, unsigned long long outlen, - const unsigned char *in, unsigned long long inlen, - const spx_ctx *ctx); - -/* Applies the 512-bit Haraka permutation to in. */ -#define haraka512_perm SPX_NAMESPACE(haraka512_perm) -void haraka512_perm(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx); - -/* Implementation of Haraka-512 */ -#define haraka512 SPX_NAMESPACE(haraka512) -void haraka512(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx); - -/* Implementation of Haraka-256 */ -#define haraka256 SPX_NAMESPACE(haraka256) -void haraka256(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/haraka_offsets.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/haraka_offsets.h deleted file mode 100644 index 7c062272a0..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/haraka_offsets.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef HARAKA_OFFSETS_H_ -#define HARAKA_OFFSETS_H_ - -/* - * Offsets of various fields in the address structure when we use Haraka as - * the Sphincs+ hash function - */ - -#define SPX_OFFSET_LAYER 3 /* The byte used to specify the Merkle tree layer */ -#define SPX_OFFSET_TREE 8 /* The start of the 8 byte field used to specify the tree */ -#define SPX_OFFSET_TYPE 19 /* The byte used to specify the hash type (reason) */ -#define SPX_OFFSET_KP_ADDR2 22 /* The high byte used to specify the key pair (which one-time signature) */ -#define SPX_OFFSET_KP_ADDR1 23 /* The low byte used to specify the key pair */ -#define SPX_OFFSET_CHAIN_ADDR 27 /* The byte used to specify the chain address (which Winternitz chain) */ -#define SPX_OFFSET_HASH_ADDR 31 /* The byte used to specify the hash address (where in the Winternitz chain) */ -#define SPX_OFFSET_TREE_HGT 27 /* The byte used to specify the height of this node in the FORS or Merkle tree */ -#define SPX_OFFSET_TREE_INDEX 28 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ - -#define SPX_HARAKA 1 - -#endif /* HARAKA_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/harakax4.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/harakax4.h deleted file mode 100644 index eadc69aa48..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/harakax4.h +++ /dev/null @@ -1,36 +0,0 @@ -#ifndef SPX_HARAKAX4_H -#define SPX_HARAKAX4_H - -#include "context.h" -#include "params.h" - -/* Haraka Sponge */ -#define haraka_Sx4 SPX_NAMESPACE(haraka_Sx4) -void haraka_Sx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned long long outlen, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - unsigned long long inlen, - const spx_ctx *ctx); - -/* Applies the 512-bit Haraka permutation x4 to in. */ -#define haraka512_perm_x4 SPX_NAMESPACE(haraka512_perm_x4) -void haraka512_perm_x4(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx); - -/* Implementation of Haraka-512 x4*/ -#define haraka512x4 SPX_NAMESPACE(haraka512x4) -void haraka512x4(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx); - -/* Implementation of Haraka-256 x4 */ -#define haraka256x4 SPX_NAMESPACE(haraka256x4) -void haraka256x4(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/hash.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/hash.h deleted file mode 100644 index f7c87d4c3c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/hash.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef SPX_HASH_H -#define SPX_HASH_H - -#include -#include - -#include "context.h" -#include "params.h" - -#define prf_addr SPX_NAMESPACE(prf_addr) -void prf_addr(unsigned char *out, const spx_ctx *ctx, - const uint32_t addr[8]); - -#define gen_message_random SPX_NAMESPACE(gen_message_random) -void gen_message_random(unsigned char *R, const unsigned char *sk_prf, - const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx); - -#define hash_message SPX_NAMESPACE(hash_message) -void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx); - - - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/hash_haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/hash_haraka.c deleted file mode 100644 index 750a67423b..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/hash_haraka.c +++ /dev/null @@ -1,81 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "utils.h" - -#include "haraka.h" -#include "hash.h" - -/* - * Computes PRF(key, addr), given a secret key of SPX_N bytes and an address - */ -void prf_addr(unsigned char *out, const spx_ctx *ctx, - const uint32_t addr[8]) { - /* Since SPX_N may be smaller than 32, we need temporary buffers. */ - unsigned char outbuf[32]; - unsigned char buf[64] = {0}; - - memcpy(buf, addr, SPX_ADDR_BYTES); - memcpy(buf + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); - - haraka512(outbuf, (const void *)buf, ctx); - memcpy(out, outbuf, SPX_N); -} - -/** - * Computes the message-dependent randomness R, using a secret seed and an - * optional randomization value as well as the message. - */ -void gen_message_random(unsigned char *R, const unsigned char *sk_prf, - const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx) { - uint8_t s_inc[65]; - - haraka_S_inc_init(s_inc); - haraka_S_inc_absorb(s_inc, sk_prf, SPX_N, ctx); - haraka_S_inc_absorb(s_inc, optrand, SPX_N, ctx); - haraka_S_inc_absorb(s_inc, m, mlen, ctx); - haraka_S_inc_finalize(s_inc); - haraka_S_inc_squeeze(R, SPX_N, s_inc, ctx); -} - -/** - * Computes the message hash using R, the public key, and the message. - * Outputs the message digest and the index of the leaf. The index is split in - * the tree index and the leaf index, for convenient copying to an address. - */ -void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx) { -#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) -#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) -#define SPX_LEAF_BITS SPX_TREE_HEIGHT -#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) -#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) - - unsigned char buf[SPX_DGST_BYTES]; - unsigned char *bufp = buf; - uint8_t s_inc[65]; - - haraka_S_inc_init(s_inc); - haraka_S_inc_absorb(s_inc, R, SPX_N, ctx); - haraka_S_inc_absorb(s_inc, pk + SPX_N, SPX_N, ctx); // Only absorb root part of pk - haraka_S_inc_absorb(s_inc, m, mlen, ctx); - haraka_S_inc_finalize(s_inc); - haraka_S_inc_squeeze(buf, SPX_DGST_BYTES, s_inc, ctx); - - memcpy(digest, bufp, SPX_FORS_MSG_BYTES); - bufp += SPX_FORS_MSG_BYTES; - - - *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); - *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); - bufp += SPX_TREE_BYTES; - - *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); - *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/hash_harakax4.c b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/hash_harakax4.c deleted file mode 100644 index cfa5162d79..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/hash_harakax4.c +++ /dev/null @@ -1,35 +0,0 @@ -#include -#include - -#include "address.h" -#include "harakax4.h" -#include "hashx4.h" -#include "params.h" - -/* - * 4-way parallel version of prf_addr; takes 4x as much input and output - */ -#define prf_addrx4 SPX_NAMESPACE(prf_addrx4) -void prf_addrx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const spx_ctx *ctx, - const uint32_t addrx4[4 * 8]) { - unsigned char bufx4[4 * 64] = {0}; - /* Since SPX_N may be smaller than 32, we need temporary buffers. */ - unsigned char outbuf[4 * 32]; - unsigned int i; - - for (i = 0; i < 4; i++) { - memcpy(bufx4 + i * 64, addrx4 + i * 8, SPX_ADDR_BYTES); - memcpy(bufx4 + i * 64 + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); - } - - haraka512x4(outbuf, bufx4, ctx); - - memcpy(out0, outbuf, SPX_N); - memcpy(out1, outbuf + 32, SPX_N); - memcpy(out2, outbuf + 64, SPX_N); - memcpy(out3, outbuf + 96, SPX_N); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/hashx4.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/hashx4.h deleted file mode 100644 index 3751a0ebd0..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/hashx4.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef SPX_HASHX4_H -#define SPX_HASHX4_H - -#include - -#include "context.h" -#include "params.h" - -#define prf_addrx4 SPX_NAMESPACE(prf_addrx4) -void prf_addrx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const spx_ctx *ctx, - const uint32_t addrx4[4 * 8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/merkle.c b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/merkle.c deleted file mode 100644 index f57811c1ac..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/merkle.c +++ /dev/null @@ -1,64 +0,0 @@ -#include -#include - -#include "merkle.h" - -#include "address.h" -#include "params.h" -#include "utils.h" -#include "utilsx4.h" -#include "wots.h" -#include "wotsx4.h" - -/* - * This generates a Merkle signature (WOTS signature followed by the Merkle - * authentication path). - */ -void merkle_sign(uint8_t *sig, unsigned char *root, - const spx_ctx *ctx, - uint32_t wots_addr[8], uint32_t tree_addr[8], - uint32_t idx_leaf) { - unsigned char *auth_path = sig + SPX_WOTS_BYTES; - uint32_t tree_addrx4[4 * 8] = { 0 }; - int j; - struct leaf_info_x4 info = { 0 }; - unsigned steps[ SPX_WOTS_LEN ]; - - info.wots_sig = sig; - chain_lengths(steps, root); - info.wots_steps = steps; - - for (j = 0; j < 4; j++) { - set_type(&tree_addrx4[8 * j], SPX_ADDR_TYPE_HASHTREE); - set_type(&info.leaf_addr[8 * j], SPX_ADDR_TYPE_WOTS); - set_type(&info.pk_addr[8 * j], SPX_ADDR_TYPE_WOTSPK); - copy_subtree_addr(&tree_addrx4[8 * j], tree_addr); - copy_subtree_addr(&info.leaf_addr[8 * j], wots_addr); - copy_subtree_addr(&info.pk_addr[8 * j], wots_addr); - } - - info.wots_sign_leaf = idx_leaf; - - treehashx4(root, auth_path, ctx, - idx_leaf, 0, - SPX_TREE_HEIGHT, - wots_gen_leafx4, - tree_addrx4, &info); -} - -/* Compute root node of the top-most subtree. */ -void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { - /* We do not need the auth path in key generation, but it simplifies the - code to have just one treehash routine that computes both root and path - in one function. */ - unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; - uint32_t top_tree_addr[8] = {0}; - uint32_t wots_addr[8] = {0}; - - set_layer_addr(top_tree_addr, SPX_D - 1); - set_layer_addr(wots_addr, SPX_D - 1); - - merkle_sign(auth_path, root, ctx, - wots_addr, top_tree_addr, - ~0U /* ~0 means "don't bother generating an auth path */ ); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/merkle.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/merkle.h deleted file mode 100644 index 769cf2e970..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/merkle.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef MERKLE_H_ -#define MERKLE_H_ - -#include - -#include "context.h" -#include "params.h" - -/* Generate a Merkle signature (WOTS signature followed by the Merkle */ -/* authentication path) */ -#define merkle_sign SPX_NAMESPACE(merkle_sign) -void merkle_sign(uint8_t *sig, unsigned char *root, - const spx_ctx *ctx, - uint32_t wots_addr[8], uint32_t tree_addr[8], - uint32_t idx_leaf); - -/* Compute the root node of the top-most subtree. */ -#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) -void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); - -#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/nistapi.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/nistapi.h deleted file mode 100644 index 3cb71afad4..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/nistapi.h +++ /dev/null @@ -1,87 +0,0 @@ -#ifndef SPX_API_H -#define SPX_API_H - -#include -#include - -#include "params.h" - -#define CRYPTO_ALGNAME "SPHINCS+" - -#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES -#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES -#define CRYPTO_BYTES SPX_BYTES -#define CRYPTO_SEEDBYTES (3*SPX_N) - -/* - * Returns the length of a secret key, in bytes - */ -#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) -size_t crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) -size_t crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) -size_t crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) -size_t crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) -int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) -int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) -int crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) -int crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -#define crypto_sign SPX_NAMESPACE(crypto_sign) -int crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) -int crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/params.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/params.h deleted file mode 100644 index e79b0d9fa5..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/params.h +++ /dev/null @@ -1,56 +0,0 @@ -#ifndef SPX_PARAMS_H -#define SPX_PARAMS_H - -#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_##s - -/* Hash output length in bytes. */ -#define SPX_N 32 -/* Height of the hypertree. */ -#define SPX_FULL_HEIGHT 64 -/* Number of subtree layer. */ -#define SPX_D 8 -/* FORS tree dimensions. */ -#define SPX_FORS_HEIGHT 14 -#define SPX_FORS_TREES 22 -/* Winternitz parameter, */ -#define SPX_WOTS_W 16 - -/* The hash function is defined by linking a different hash.c file, as opposed - to setting a #define constant. */ - -/* For clarity */ -#define SPX_ADDR_BYTES 32 - -/* WOTS parameters. */ -#define SPX_WOTS_LOGW 4 - -#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) - -/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#define SPX_WOTS_LEN2 3 - -#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) -#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) -#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES - -/* Subtree size. */ -#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) - -//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT -// #error SPX_D should always divide SPX_FULL_HEIGHT -//#endif - -/* FORS parameters. */ -#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) -#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) -#define SPX_FORS_PK_BYTES SPX_N - -/* Resulting SPX sizes. */ -#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ - SPX_FULL_HEIGHT * SPX_N) -#define SPX_PK_BYTES (2 * SPX_N) -#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) - -#include "haraka_offsets.h" - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/sign.c b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/sign.c deleted file mode 100644 index 9d0c7d1b22..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/sign.c +++ /dev/null @@ -1,286 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "context.h" -#include "fors.h" -#include "hash.h" -#include "merkle.h" -#include "nistapi.h" -#include "params.h" -#include "randombytes.h" -#include "thash.h" -#include "utils.h" -#include "wots.h" - -/* - * Returns the length of a secret key, in bytes - */ -size_t crypto_sign_secretkeybytes(void) { - return CRYPTO_SECRETKEYBYTES; -} - -/* - * Returns the length of a public key, in bytes - */ -size_t crypto_sign_publickeybytes(void) { - return CRYPTO_PUBLICKEYBYTES; -} - -/* - * Returns the length of a signature, in bytes - */ -size_t crypto_sign_bytes(void) { - return CRYPTO_BYTES; -} - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t crypto_sign_seedbytes(void) { - return CRYPTO_SEEDBYTES; -} - -/* - * Generates an SPX key pair given a seed of length - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed) { - spx_ctx ctx; - - /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ - memcpy(sk, seed, CRYPTO_SEEDBYTES); - - memcpy(pk, sk + 2 * SPX_N, SPX_N); - - memcpy(ctx.pub_seed, pk, SPX_N); - memcpy(ctx.sk_seed, sk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - /* Compute root node of the top-most subtree. */ - merkle_gen_root(sk + 3 * SPX_N, &ctx); - - // cleanup - free_hash_function(&ctx); - - memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); - - return 0; -} - -/* - * Generates an SPX key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { - uint8_t seed[CRYPTO_SEEDBYTES]; - randombytes(seed, CRYPTO_SEEDBYTES); - crypto_sign_seed_keypair(pk, sk, seed); - - return 0; -} - -/** - * Returns an array containing a detached signature. - */ -int crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - spx_ctx ctx; - - const uint8_t *sk_prf = sk + SPX_N; - const uint8_t *pk = sk + 2 * SPX_N; - - uint8_t optrand[SPX_N]; - uint8_t mhash[SPX_FORS_MSG_BYTES]; - uint8_t root[SPX_N]; - uint32_t i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - - memcpy(ctx.sk_seed, sk, SPX_N); - memcpy(ctx.pub_seed, pk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - set_type(wots_addr, SPX_ADDR_TYPE_WOTS); - set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); - - /* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ - randombytes(optrand, SPX_N); - /* Compute the digest randomization value. */ - gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); - - /* Derive the message digest and leaf index from R, PK and M. */ - hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); - sig += SPX_N; - - set_tree_addr(wots_addr, tree); - set_keypair_addr(wots_addr, idx_leaf); - - /* Sign the message hash using FORS. */ - fors_sign(sig, root, mhash, &ctx, wots_addr); - sig += SPX_FORS_BYTES; - - for (i = 0; i < SPX_D; i++) { - set_layer_addr(tree_addr, i); - set_tree_addr(tree_addr, tree); - - copy_subtree_addr(wots_addr, tree_addr); - set_keypair_addr(wots_addr, idx_leaf); - - merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); - sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); - tree = tree >> SPX_TREE_HEIGHT; - } - - free_hash_function(&ctx); - - *siglen = SPX_BYTES; - - return 0; -} - -/** - * Verifies a detached signature and message under a given public key. - */ -int crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk) { - spx_ctx ctx; - const uint8_t *pub_root = pk + SPX_N; - uint8_t mhash[SPX_FORS_MSG_BYTES]; - uint8_t wots_pk[SPX_WOTS_BYTES]; - uint8_t root[SPX_N]; - uint8_t leaf[SPX_N]; - unsigned int i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - if (siglen != SPX_BYTES) { - return -1; - } - - memcpy(ctx.pub_seed, pk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - set_type(wots_addr, SPX_ADDR_TYPE_WOTS); - set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); - set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); - - /* Derive the message digest and leaf index from R || PK || M. */ - /* The additional SPX_N is a result of the hash domain separator. */ - hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); - sig += SPX_N; - - /* Layer correctly defaults to 0, so no need to set_layer_addr */ - set_tree_addr(wots_addr, tree); - set_keypair_addr(wots_addr, idx_leaf); - - fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); - sig += SPX_FORS_BYTES; - - /* For each subtree.. */ - for (i = 0; i < SPX_D; i++) { - set_layer_addr(tree_addr, i); - set_tree_addr(tree_addr, tree); - - copy_subtree_addr(wots_addr, tree_addr); - set_keypair_addr(wots_addr, idx_leaf); - - copy_keypair_addr(wots_pk_addr, wots_addr); - - /* The WOTS public key is only correct if the signature was correct. */ - /* Initially, root is the FORS pk, but on subsequent iterations it is - the root of the subtree below the currently processed subtree. */ - wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); - sig += SPX_WOTS_BYTES; - - /* Compute the leaf node using the WOTS public key. */ - thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); - - /* Compute the root node of this subtree. */ - compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, - &ctx, tree_addr); - sig += SPX_TREE_HEIGHT * SPX_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); - tree = tree >> SPX_TREE_HEIGHT; - } - - // cleanup - free_hash_function(&ctx); - - /* Check if the root node equals the root node in the public key. */ - if (memcmp(root, pub_root, SPX_N) != 0) { - return -1; - } - - return 0; -} - - -/** - * Returns an array containing the signature followed by the message. - */ -int crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk) { - size_t siglen; - - crypto_sign_signature(sm, &siglen, m, mlen, sk); - - memmove(sm + SPX_BYTES, m, mlen); - *smlen = siglen + mlen; - - return 0; -} - -/** - * Verifies a given signature-message pair under a given public key. - */ -int crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk) { - /* The API caller does not necessarily know what size a signature should be - but SPHINCS+ signatures are always exactly SPX_BYTES. */ - if (smlen < SPX_BYTES) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - *mlen = smlen - SPX_BYTES; - - if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - /* If verification was successful, move the message to the right place. */ - memmove(m, sm + SPX_BYTES, *mlen); - - return 0; -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/thash.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/thash.h deleted file mode 100644 index 8687ccfb4d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/thash.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef SPX_THASH_H -#define SPX_THASH_H - -#include "context.h" -#include "params.h" - -#include - -#define thash SPX_NAMESPACE(thash) -void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/thash_haraka_robust.c b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/thash_haraka_robust.c deleted file mode 100644 index 109502cbc2..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/thash_haraka_robust.c +++ /dev/null @@ -1,45 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "thash.h" -#include "utils.h" - -#include "haraka.h" - -/** - * Takes an array of inblocks concatenated arrays of SPX_N bytes. - */ -void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]) { - PQCLEAN_VLA(uint8_t, buf, SPX_ADDR_BYTES + inblocks * SPX_N); - PQCLEAN_VLA(uint8_t, bitmask, inblocks * SPX_N); - unsigned char outbuf[32]; - unsigned char buf_tmp[64]; - unsigned int i; - - if (inblocks == 1) { - /* F function */ - /* Since SPX_N may be smaller than 32, we need a temporary buffer. */ - memset(buf_tmp, 0, 64); - memcpy(buf_tmp, addr, 32); - - haraka256(outbuf, buf_tmp, ctx); - for (i = 0; i < inblocks * SPX_N; i++) { - buf_tmp[SPX_ADDR_BYTES + i] = in[i] ^ outbuf[i]; - } - haraka512(outbuf, buf_tmp, ctx); - memcpy(out, outbuf, SPX_N); - } else { - /* All other tweakable hashes*/ - memcpy(buf, addr, 32); - haraka_S(bitmask, inblocks * SPX_N, buf, SPX_ADDR_BYTES, ctx); - - for (i = 0; i < inblocks * SPX_N; i++) { - buf[SPX_ADDR_BYTES + i] = in[i] ^ bitmask[i]; - } - - haraka_S(out, SPX_N, buf, SPX_ADDR_BYTES + inblocks * SPX_N, ctx); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/thash_haraka_robustx4.c b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/thash_haraka_robustx4.c deleted file mode 100644 index 100808a3a5..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/thash_haraka_robustx4.c +++ /dev/null @@ -1,93 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "thashx4.h" - -#include "harakax4.h" - -#include "utils.h" - -/** - * 4-way parallel version of thash; takes 4x as much input and output - */ -#define thashx4 SPX_NAMESPACE(thashx4) -void thashx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addrx4[4 * 8]) { - PQCLEAN_VLA(unsigned char, buf0, SPX_ADDR_BYTES + inblocks * SPX_N); - PQCLEAN_VLA(unsigned char, buf1, SPX_ADDR_BYTES + inblocks * SPX_N); - PQCLEAN_VLA(unsigned char, buf2, SPX_ADDR_BYTES + inblocks * SPX_N); - PQCLEAN_VLA(unsigned char, buf3, SPX_ADDR_BYTES + inblocks * SPX_N); - PQCLEAN_VLA(unsigned char, bitmask0, inblocks * SPX_N); - PQCLEAN_VLA(unsigned char, bitmask1, inblocks * SPX_N); - PQCLEAN_VLA(unsigned char, bitmask2, inblocks * SPX_N); - PQCLEAN_VLA(unsigned char, bitmask3, inblocks * SPX_N); - unsigned char outbuf[32 * 4]; - unsigned char buf_tmp[64 * 4]; - unsigned int i; - - if (inblocks == 1) { - memset(buf_tmp, 0, 64 * 4); - - // Generate masks first in buffer - memcpy(buf_tmp, addrx4 + 0 * 8, 32); - memcpy(buf_tmp + 32, addrx4 + 1 * 8, 32); - memcpy(buf_tmp + 64, addrx4 + 2 * 8, 32); - memcpy(buf_tmp + 96, addrx4 + 3 * 8, 32); - - haraka256x4(outbuf, buf_tmp, ctx); - - /* move addresses to make room for inputs; zero old values */ - memcpy(buf_tmp + 192, buf_tmp + 96, SPX_ADDR_BYTES); - memcpy(buf_tmp + 128, buf_tmp + 64, SPX_ADDR_BYTES); - memcpy(buf_tmp + 64, buf_tmp + 32, SPX_ADDR_BYTES); - /* skip memcpy(buf_tmp, buf_tmp, SPX_ADDR_BYTES); already in place */ - - /* skip memset(buf_tmp, 0, SPX_ADDR_BYTES); remained untouched */ - memset(buf_tmp + 32, 0, SPX_ADDR_BYTES); - /* skip memset(buf_tmp + 64, 0, SPX_ADDR_BYTES); contains addr1 */ - memset(buf_tmp + 96, 0, SPX_ADDR_BYTES); - - for (i = 0; i < SPX_N; i++) { - buf_tmp[SPX_ADDR_BYTES + i] = in0[i] ^ outbuf[i]; - buf_tmp[SPX_ADDR_BYTES + i + 64] = in1[i] ^ outbuf[i + 32]; - buf_tmp[SPX_ADDR_BYTES + i + 128] = in2[i] ^ outbuf[i + 64]; - buf_tmp[SPX_ADDR_BYTES + i + 192] = in3[i] ^ outbuf[i + 96]; - } - - haraka512x4(outbuf, buf_tmp, ctx); - - memcpy(out0, outbuf, SPX_N); - memcpy(out1, outbuf + 32, SPX_N); - memcpy(out2, outbuf + 64, SPX_N); - memcpy(out3, outbuf + 96, SPX_N); - } else { - /* All other tweakable hashes*/ - memcpy(buf0, addrx4 + 0 * 8, 32); - memcpy(buf1, addrx4 + 1 * 8, 32); - memcpy(buf2, addrx4 + 2 * 8, 32); - memcpy(buf3, addrx4 + 3 * 8, 32); - - haraka_Sx4(bitmask0, bitmask1, bitmask2, bitmask3, inblocks * SPX_N, - buf0, buf1, buf2, buf3, SPX_ADDR_BYTES, ctx); - - for (i = 0; i < inblocks * SPX_N; i++) { - buf0[SPX_ADDR_BYTES + i] = in0[i] ^ bitmask0[i]; - buf1[SPX_ADDR_BYTES + i] = in1[i] ^ bitmask1[i]; - buf2[SPX_ADDR_BYTES + i] = in2[i] ^ bitmask2[i]; - buf3[SPX_ADDR_BYTES + i] = in3[i] ^ bitmask3[i]; - } - - haraka_Sx4(out0, out1, out2, out3, SPX_N, - buf0, buf1, buf2, buf3, SPX_ADDR_BYTES + inblocks * SPX_N, - ctx); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/thashx4.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/thashx4.h deleted file mode 100644 index 64798a3727..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/thashx4.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef SPX_THASHX4_H -#define SPX_THASHX4_H - -#include - -#include "context.h" -#include "params.h" - -#define thashx4 SPX_NAMESPACE(thashx4) -void thashx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addrx4[4 * 8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/utils.c b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/utils.c deleted file mode 100644 index 177b541fb9..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/utils.c +++ /dev/null @@ -1,148 +0,0 @@ -#include - -#include "utils.h" - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "thash.h" - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void ull_to_bytes(unsigned char *out, unsigned int outlen, - unsigned long long in) { - int i; - - /* Iterate over out in decreasing order, for big-endianness. */ - for (i = (signed int)outlen - 1; i >= 0; i--) { - out[i] = in & 0xff; - in = in >> 8; - } -} - -void u32_to_bytes(unsigned char *out, uint32_t in) { - out[0] = (unsigned char)(in >> 24); - out[1] = (unsigned char)(in >> 16); - out[2] = (unsigned char)(in >> 8); - out[3] = (unsigned char)in; -} - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { - unsigned long long retval = 0; - unsigned int i; - - for (i = 0; i < inlen; i++) { - retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); - } - return retval; -} - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void compute_root(unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const spx_ctx *ctx, uint32_t addr[8]) { - uint32_t i; - unsigned char buffer[2 * SPX_N]; - - /* If leaf_idx is odd (last bit = 1), current path element is a right child - and auth_path has to go left. Otherwise it is the other way around. */ - if (leaf_idx & 1) { - memcpy(buffer + SPX_N, leaf, SPX_N); - memcpy(buffer, auth_path, SPX_N); - } else { - memcpy(buffer, leaf, SPX_N); - memcpy(buffer + SPX_N, auth_path, SPX_N); - } - auth_path += SPX_N; - - for (i = 0; i < tree_height - 1; i++) { - leaf_idx >>= 1; - idx_offset >>= 1; - /* Set the address of the node we're creating. */ - set_tree_height(addr, i + 1); - set_tree_index(addr, leaf_idx + idx_offset); - - /* Pick the right or left neighbor, depending on parity of the node. */ - if (leaf_idx & 1) { - thash(buffer + SPX_N, buffer, 2, ctx, addr); - memcpy(buffer, auth_path, SPX_N); - } else { - thash(buffer, buffer, 2, ctx, addr); - memcpy(buffer + SPX_N, auth_path, SPX_N); - } - auth_path += SPX_N; - } - - /* The last iteration is exceptional; we do not copy an auth_path node. */ - leaf_idx >>= 1; - idx_offset >>= 1; - set_tree_height(addr, tree_height); - set_tree_index(addr, leaf_idx + idx_offset); - thash(root, buffer, 2, ctx, addr); -} - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const spx_ctx * /* ctx */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), - uint32_t tree_addr[8]) { - PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); - PQCLEAN_VLA(unsigned int, heights, tree_height + 1); - unsigned int offset = 0; - uint32_t idx; - uint32_t tree_idx; - - for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { - /* Add the next leaf node to the stack. */ - gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); - offset++; - heights[offset - 1] = 0; - - /* If this is a node we need for the auth path.. */ - if ((leaf_idx ^ 0x1) == idx) { - memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); - } - - /* While the top-most nodes are of equal height.. */ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { - /* Compute index of the new node, in the next layer. */ - tree_idx = (idx >> (heights[offset - 1] + 1)); - - /* Set the address of the node we're creating. */ - set_tree_height(tree_addr, heights[offset - 1] + 1); - set_tree_index(tree_addr, - tree_idx + (idx_offset >> (heights[offset - 1] + 1))); - /* Hash the top-most nodes from the stack together. */ - thash(stack + (offset - 2)*SPX_N, - stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); - offset--; - /* Note that the top-most node is now one layer higher. */ - heights[offset - 1]++; - - /* If this is a node we need for the auth path.. */ - if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_path + heights[offset - 1]*SPX_N, - stack + (offset - 1)*SPX_N, SPX_N); - } - } - } - memcpy(root, stack, SPX_N); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/utils.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/utils.h deleted file mode 100644 index 64f5d5a53a..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/utils.h +++ /dev/null @@ -1,58 +0,0 @@ -#ifndef SPX_UTILS_H -#define SPX_UTILS_H - -#include - -#include "compat.h" -#include "context.h" -#include "params.h" - - -/* To support MSVC use alloca() instead of VLAs. See #20. */ - - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) -void ull_to_bytes(unsigned char *out, unsigned int outlen, - unsigned long long in); -#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) -void u32_to_bytes(unsigned char *out, uint32_t in); - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) -unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -#define compute_root SPX_NAMESPACE(compute_root) -void compute_root(unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const spx_ctx *ctx, uint32_t addr[8]); - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -#define treehash SPX_NAMESPACE(treehash) -void treehash(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const spx_ctx *ctx /* ctx */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), - uint32_t tree_addr[8]); - - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/utilsx4.c b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/utilsx4.c deleted file mode 100644 index 1638677194..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/utilsx4.c +++ /dev/null @@ -1,138 +0,0 @@ -#include - -#include "utilsx4.h" - -#include "address.h" -#include "params.h" -#include "thashx4.h" -#include "utils.h" - -/* - * Generate the entire Merkle tree, computing the authentication path for leaf_idx, - * and the resulting root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) - * - * This expects tree_addrx4 to be initialized to 4 parallel addr structures for - * the Merkle tree nodes - * - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - * - * This works by using the standard Merkle tree building algorithm, except - * that each 'node' tracked is actually 4 consecutive nodes in the real tree. - * When we combine two logical nodes ABCD and WXYZ, we perform the H - * operation on adjacent real nodes, forming the parent logical node - * (AB)(CD)(WX)(YZ) - * - * When we get to the top two levels of the real tree (where there is only - * one logical node), we continue this operation two more times; the right - * most real node will by the actual root (and the other 3 nodes will be - * garbage). We follow the same thashx4 logic so that the 'extract - * authentication path components' part of the loop is still executed (and - * to simplify the code somewhat) - * - * This currently assumes tree_height >= 2; I suspect that doing an adjusting - * idx, addr_idx on the gen_leafx4 call if tree_height < 2 would fix it; since - * we don't actually use such short trees, I haven't bothered - */ -void treehashx4(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, - uint32_t tree_height, - void (*gen_leafx4)( - unsigned char * /* Where to write the leaves */, - const spx_ctx *, - uint32_t idx, void *info), - uint32_t tree_addrx4[4 * 8], - void *info) { - /* This is where we keep the intermediate nodes */ - PQCLEAN_VLA(unsigned char, stackx4, tree_height * 4 * SPX_N); - uint32_t left_adj = 0, prev_left_adj = 0; /* When we're doing the top 3 */ - /* levels, the left-most part of the tree isn't at the beginning */ - /* of current[]. These give the offset of the actual start */ - - uint32_t idx; - uint32_t max_idx = (1U << (tree_height - 2)) - 1; - for (idx = 0;; idx++) { - unsigned char current[4 * SPX_N]; /* Current logical node */ - gen_leafx4( current, ctx, 4 * idx + idx_offset, - info ); - - /* Now combine the freshly generated right node with previously */ - /* generated left ones */ - uint32_t internal_idx_offset = idx_offset; - uint32_t internal_idx = idx; - uint32_t internal_leaf = leaf_idx; - uint32_t h; /* The height we are in the Merkle tree */ - for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { - - /* Special processing if we're at the top of the tree */ - if (h >= tree_height - 2) { - if (h == tree_height) { - /* We hit the root; return it */ - memcpy( root, ¤t[3 * SPX_N], SPX_N ); - return; - } - /* The tree indexing logic is a bit off in this case */ - /* Adjust it so that the left-most node of the part of */ - /* the tree that we're processing has index 0 */ - prev_left_adj = left_adj; - left_adj = 4U - (1 << (tree_height - h - 1)); - } - - /* Check if we hit the top of the tree */ - if (h == tree_height) { - /* We hit the root; return it */ - memcpy( root, ¤t[3 * SPX_N], SPX_N ); - return; - } - - /* - * Check if one of the nodes we have is a part of the - * authentication path; if it is, write it out - */ - if ((((internal_idx << 2) ^ internal_leaf) & ~0x3U) == 0) { - memcpy( &auth_path[ h * SPX_N ], - ¤t[(((internal_leaf & 3) ^ 1) + prev_left_adj) * SPX_N], - SPX_N ); - } - - /* - * Check if we're at a left child; if so, stop going up the stack - * Exception: if we've reached the end of the tree, keep on going - * (so we combine the last 4 nodes into the one root node in two - * more iterations) - */ - if ((internal_idx & 1) == 0 && idx < max_idx) { - break; - } - - /* Ok, we're at a right node (or doing the top 3 levels) */ - /* Now combine the left and right logical nodes together */ - - /* Set the address of the node we're creating. */ - unsigned int j; - internal_idx_offset >>= 1; - for (j = 0; j < 4; j++) { - set_tree_height(tree_addrx4 + j * 8, h + 1); - set_tree_index(tree_addrx4 + j * 8, - (4 / 2) * (internal_idx & ~1U) + j - left_adj + internal_idx_offset ); - } - unsigned char *left = &stackx4[h * 4 * SPX_N]; - thashx4( ¤t[0 * SPX_N], - ¤t[1 * SPX_N], - ¤t[2 * SPX_N], - ¤t[3 * SPX_N], - &left [0 * SPX_N], - &left [2 * SPX_N], - ¤t[0 * SPX_N], - ¤t[2 * SPX_N], - 2, ctx, tree_addrx4); - } - - /* We've hit a left child; save the current for when we get the */ - /* corresponding right right */ - memcpy( &stackx4[h * 4 * SPX_N], current, 4 * SPX_N); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/utilsx4.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/utilsx4.h deleted file mode 100644 index facb874b18..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/utilsx4.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef SPX_UTILSX4_H -#define SPX_UTILSX4_H - -#include - -#include "context.h" -#include "params.h" - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - * - * This implementation uses AVX to compute internal nodes 4 at a time (in - * parallel) - */ -#define treehashx4 SPX_NAMESPACE(treehashx4) -void treehashx4(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leafx4)( - unsigned char * /* Where to write the leaves */, - const spx_ctx * /* ctx */, - uint32_t addr_idx, void *info), - uint32_t tree_addrx4[4 * 8], void *info); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/wots.c b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/wots.c deleted file mode 100644 index 4d5041ce05..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/wots.c +++ /dev/null @@ -1,269 +0,0 @@ -#include -#include - -#include "wots.h" - -#include "address.h" -#include "hash.h" -#include "hashx4.h" -#include "params.h" -#include "thash.h" -#include "thashx4.h" -#include "utils.h" -#include "utilsx4.h" -#include "wotsx4.h" - -// TODO clarify address expectations, and make them more uniform. -// TODO i.e. do we expect types to be set already? -// TODO and do we expect modifications or copies? - -/** - * Computes up the chains - */ -static void gen_chains( - unsigned char *out, - const unsigned char *in, - unsigned int start[SPX_WOTS_LEN], - const unsigned int steps[SPX_WOTS_LEN], - const spx_ctx *ctx, - uint32_t addr[8]) { - uint32_t i, j, k, idx, watching; - int done; - unsigned char empty[SPX_N]; - unsigned char *bufs[4]; - uint32_t addrs[8 * 4]; - - int l; - uint16_t counts[SPX_WOTS_W] = { 0 }; - uint16_t idxs[SPX_WOTS_LEN]; - uint16_t total, newTotal; - - /* set addrs = {addr, addr, addr, addr} */ - for (j = 0; j < 4; j++) { - memcpy(addrs + j * 8, addr, sizeof(uint32_t) * 8); - } - - /* Initialize out with the value at position 'start'. */ - memcpy(out, in, SPX_WOTS_LEN * SPX_N); - - /* Sort the chains in reverse order by steps using counting sort. */ - for (i = 0; i < SPX_WOTS_LEN; i++) { - counts[steps[i]]++; - } - total = 0; - for (l = SPX_WOTS_W - 1; l >= 0; l--) { - newTotal = counts[l] + total; - counts[l] = total; - total = newTotal; - } - for (i = 0; i < SPX_WOTS_LEN; i++) { - idxs[counts[steps[i]]] = (uint16_t)i; - counts[steps[i]]++; - } - - /* We got our work cut out for us: do it! */ - for (i = 0; i < SPX_WOTS_LEN; i += 4) { - for (j = 0; j < 4 && i + j < SPX_WOTS_LEN; j++) { - idx = idxs[i + j]; - set_chain_addr(addrs + j * 8, idx); - bufs[j] = out + SPX_N * idx; - } - - /* As the chains are sorted in reverse order, we know that the first - * chain is the longest and the last one is the shortest. We keep - * an eye on whether the last chain is done and then on the one before, - * et cetera. */ - watching = 3; - done = 0; - while (i + watching >= SPX_WOTS_LEN) { - bufs[watching] = &empty[0]; - watching--; - } - - for (k = 0;; k++) { - while (k == steps[idxs[i + watching]]) { - bufs[watching] = &empty[0]; - if (watching == 0) { - done = 1; - break; - } - watching--; - } - if (done) { - break; - } - for (j = 0; j < watching + 1; j++) { - set_hash_addr(addrs + j * 8, k + start[idxs[i + j]]); - } - - thashx4(bufs[0], bufs[1], bufs[2], bufs[3], - bufs[0], bufs[1], bufs[2], bufs[3], 1, ctx, addrs); - } - } -} - -/** - * base_w algorithm as described in draft. - * Interprets an array of bytes as integers in base w. - * This only works when log_w is a divisor of 8. - */ -static void base_w(unsigned int *output, const int out_len, - const unsigned char *input) { - int in = 0; - int out = 0; - unsigned char total = 0; - int bits = 0; - int consumed; - - for (consumed = 0; consumed < out_len; consumed++) { - if (bits == 0) { - total = input[in]; - in++; - bits += 8; - } - bits -= SPX_WOTS_LOGW; - output[out] = (total >> bits) & (SPX_WOTS_W - 1); - out++; - } -} - -/* Computes the WOTS+ checksum over a message (in base_w). */ -static void wots_checksum(unsigned int *csum_base_w, - const unsigned int *msg_base_w) { - unsigned int csum = 0; - unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; - unsigned int i; - - /* Compute checksum. */ - for (i = 0; i < SPX_WOTS_LEN1; i++) { - csum += SPX_WOTS_W - 1 - msg_base_w[i]; - } - - /* Convert checksum to base_w. */ - /* Make sure expected empty zero bits are the least significant bits. */ - csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); - ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); - base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); -} - -/* Takes a message and derives the matching chain lengths. */ -void chain_lengths(unsigned int *lengths, const unsigned char *msg) { - base_w(lengths, SPX_WOTS_LEN1, msg); - wots_checksum(lengths + SPX_WOTS_LEN1, lengths); -} - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const spx_ctx *ctx, uint32_t addr[8]) { - unsigned int steps[SPX_WOTS_LEN]; - unsigned int start[SPX_WOTS_LEN]; - uint32_t i; - - chain_lengths(start, msg); - - for (i = 0; i < SPX_WOTS_LEN; i++) { - steps[i] = SPX_WOTS_W - 1 - start[i]; - } - - gen_chains(pk, sig, start, steps, ctx, addr); -} - -/* - * This generates 4 sequential WOTS public keys - * It also generates the WOTS signature if leaf_info indicates - * that we're signing with one of these WOTS keys - */ -void wots_gen_leafx4(unsigned char *dest, - const spx_ctx *ctx, - uint32_t leaf_idx, void *v_info) { - struct leaf_info_x4 *info = v_info; - uint32_t *leaf_addr = info->leaf_addr; - uint32_t *pk_addr = info->pk_addr; - unsigned int i, j, k; - unsigned char pk_buffer[ 4 * SPX_WOTS_BYTES ]; - unsigned wots_offset = SPX_WOTS_BYTES; - unsigned char *buffer; - uint32_t wots_k_mask; - unsigned wots_sign_index; - - if (((leaf_idx ^ info->wots_sign_leaf) & ~3U) == 0) { - /* We're traversing the leaf that's signing; generate the WOTS */ - /* signature */ - wots_k_mask = 0; - wots_sign_index = info->wots_sign_leaf & 3; /* Which of of the 4 */ - /* 4 slots do the signatures come from */ - } else { - /* Nope, we're just generating pk's; turn off the signature logic */ - wots_k_mask = (uint32_t)~0; - wots_sign_index = 0; - } - - for (j = 0; j < 4; j++) { - set_keypair_addr( leaf_addr + j * 8, leaf_idx + j ); - set_keypair_addr( pk_addr + j * 8, leaf_idx + j ); - } - - for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { - uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k to */ - /* the step if we're generating a signature, ~0 if we're not */ - - /* Start with the secret seed */ - for (j = 0; j < 4; j++) { - set_chain_addr(leaf_addr + j * 8, i); - set_hash_addr(leaf_addr + j * 8, 0); - set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTSPRF); - } - prf_addrx4(buffer + 0 * wots_offset, - buffer + 1 * wots_offset, - buffer + 2 * wots_offset, - buffer + 3 * wots_offset, - ctx, leaf_addr); - - for (j = 0; j < 4; j++) { - set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTS); - } - - /* Iterate down the WOTS chain */ - for (k = 0;; k++) { - /* Check if one of the values we have needs to be saved as a */ - /* part of the WOTS signature */ - if (k == wots_k) { - memcpy( info->wots_sig + i * SPX_N, - buffer + wots_sign_index * wots_offset, SPX_N ); - } - - /* Check if we hit the top of the chain */ - if (k == SPX_WOTS_W - 1) { - break; - } - - /* Iterate one step on all 4 chains */ - for (j = 0; j < 4; j++) { - set_hash_addr(leaf_addr + j * 8, k); - } - thashx4(buffer + 0 * wots_offset, - buffer + 1 * wots_offset, - buffer + 2 * wots_offset, - buffer + 3 * wots_offset, - buffer + 0 * wots_offset, - buffer + 1 * wots_offset, - buffer + 2 * wots_offset, - buffer + 3 * wots_offset, 1, ctx, leaf_addr); - } - } - - /* Do the final thash to generate the public keys */ - thashx4(dest + 0 * SPX_N, - dest + 1 * SPX_N, - dest + 2 * SPX_N, - dest + 3 * SPX_N, - pk_buffer + 0 * wots_offset, - pk_buffer + 1 * wots_offset, - pk_buffer + 2 * wots_offset, - pk_buffer + 3 * wots_offset, SPX_WOTS_LEN, ctx, pk_addr); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/wots.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/wots.h deleted file mode 100644 index 4e7692eeef..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/wots.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef SPX_WOTS_H -#define SPX_WOTS_H - -#include - -#include "context.h" -#include "params.h" - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) -void wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const spx_ctx *ctx, uint32_t addr[8]); - -/* - * Compute the chain lengths needed for a given message hash - */ -#define chain_lengths SPX_NAMESPACE(chain_lengths) -void chain_lengths(unsigned int *lengths, const unsigned char *msg); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/wotsx4.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/wotsx4.h deleted file mode 100644 index cd634f1743..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_aesni/wotsx4.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef WOTSX4_H_ -#define WOTSX4_H_ - -#include - -#include "params.h" - -/* - * This is here to provide an interface to the internal wots_gen_leafx4 - * routine. While this routine is not referenced in the package outside of - * wots.c, it is called from the stand-alone benchmark code to characterize - * the performance - */ -struct leaf_info_x4 { - unsigned char *wots_sig; - uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ - uint32_t *wots_steps; - uint32_t leaf_addr[4 * 8]; - uint32_t pk_addr[4 * 8]; -}; - -/* Macro to set the leaf_info to something 'benign', that is, it would */ -/* run with the same time as it does during the real signing process */ -/* Used only by the benchmark code */ -#define INITIALIZE_LEAF_INFO_X4(info, addr, step_buffer) { \ - (info).wots_sig = 0; \ - (info).wots_sign_leaf = ~0; \ - (info).wots_steps = step_buffer; \ - int i; \ - for (i=0; i<4; i++) { \ - memcpy( &(info).leaf_addr[8*i], addr, 32 ); \ - memcpy( &(info).pk_addr[8*i], addr, 32 ); \ - } \ - } - -#define wots_gen_leafx4 SPX_NAMESPACE(wots_gen_leafx4) -void wots_gen_leafx4(unsigned char *dest, - const spx_ctx *ctx, - uint32_t leaf_idx, void *v_info); - -#endif /* WOTSX4_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/LICENSE b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/LICENSE deleted file mode 100644 index 670154e353..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/LICENSE +++ /dev/null @@ -1,116 +0,0 @@ -CC0 1.0 Universal - -Statement of Purpose - -The laws of most jurisdictions throughout the world automatically confer -exclusive Copyright and Related Rights (defined below) upon the creator and -subsequent owner(s) (each and all, an "owner") of an original work of -authorship and/or a database (each, a "Work"). - -Certain owners wish to permanently relinquish those rights to a Work for the -purpose of contributing to a commons of creative, cultural and scientific -works ("Commons") that the public can reliably and without fear of later -claims of infringement build upon, modify, incorporate in other works, reuse -and redistribute as freely as possible in any form whatsoever and for any -purposes, including without limitation commercial purposes. These owners may -contribute to the Commons to promote the ideal of a free culture and the -further production of creative, cultural and scientific works, or to gain -reputation or greater distribution for their Work in part through the use and -efforts of others. - -For these and/or other purposes and motivations, and without any expectation -of additional consideration or compensation, the person associating CC0 with a -Work (the "Affirmer"), to the extent that he or she is an owner of Copyright -and Related Rights in the Work, voluntarily elects to apply CC0 to the Work -and publicly distribute the Work under its terms, with knowledge of his or her -Copyright and Related Rights in the Work and the meaning and intended legal -effect of CC0 on those rights. - -1. Copyright and Related Rights. A Work made available under CC0 may be -protected by copyright and related or neighboring rights ("Copyright and -Related Rights"). Copyright and Related Rights include, but are not limited -to, the following: - - i. the right to reproduce, adapt, distribute, perform, display, communicate, - and translate a Work; - - ii. moral rights retained by the original author(s) and/or performer(s); - - iii. publicity and privacy rights pertaining to a person's image or likeness - depicted in a Work; - - iv. rights protecting against unfair competition in regards to a Work, - subject to the limitations in paragraph 4(a), below; - - v. rights protecting the extraction, dissemination, use and reuse of data in - a Work; - - vi. database rights (such as those arising under Directive 96/9/EC of the - European Parliament and of the Council of 11 March 1996 on the legal - protection of databases, and under any national implementation thereof, - including any amended or successor version of such directive); and - - vii. other similar, equivalent or corresponding rights throughout the world - based on applicable law or treaty, and any national implementations thereof. - -2. Waiver. To the greatest extent permitted by, but not in contravention of, -applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and -unconditionally waives, abandons, and surrenders all of Affirmer's Copyright -and Related Rights and associated claims and causes of action, whether now -known or unknown (including existing as well as future claims and causes of -action), in the Work (i) in all territories worldwide, (ii) for the maximum -duration provided by applicable law or treaty (including future time -extensions), (iii) in any current or future medium and for any number of -copies, and (iv) for any purpose whatsoever, including without limitation -commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes -the Waiver for the benefit of each member of the public at large and to the -detriment of Affirmer's heirs and successors, fully intending that such Waiver -shall not be subject to revocation, rescission, cancellation, termination, or -any other legal or equitable action to disrupt the quiet enjoyment of the Work -by the public as contemplated by Affirmer's express Statement of Purpose. - -3. Public License Fallback. Should any part of the Waiver for any reason be -judged legally invalid or ineffective under applicable law, then the Waiver -shall be preserved to the maximum extent permitted taking into account -Affirmer's express Statement of Purpose. In addition, to the extent the Waiver -is so judged Affirmer hereby grants to each affected person a royalty-free, -non transferable, non sublicensable, non exclusive, irrevocable and -unconditional license to exercise Affirmer's Copyright and Related Rights in -the Work (i) in all territories worldwide, (ii) for the maximum duration -provided by applicable law or treaty (including future time extensions), (iii) -in any current or future medium and for any number of copies, and (iv) for any -purpose whatsoever, including without limitation commercial, advertising or -promotional purposes (the "License"). The License shall be deemed effective as -of the date CC0 was applied by Affirmer to the Work. Should any part of the -License for any reason be judged legally invalid or ineffective under -applicable law, such partial invalidity or ineffectiveness shall not -invalidate the remainder of the License, and in such case Affirmer hereby -affirms that he or she will not (i) exercise any of his or her remaining -Copyright and Related Rights in the Work or (ii) assert any associated claims -and causes of action with respect to the Work, in either case contrary to -Affirmer's express Statement of Purpose. - -4. Limitations and Disclaimers. - - a. No trademark or patent rights held by Affirmer are waived, abandoned, - surrendered, licensed or otherwise affected by this document. - - b. Affirmer offers the Work as-is and makes no representations or warranties - of any kind concerning the Work, express, implied, statutory or otherwise, - including without limitation warranties of title, merchantability, fitness - for a particular purpose, non infringement, or the absence of latent or - other defects, accuracy, or the present or absence of errors, whether or not - discoverable, all to the greatest extent permissible under applicable law. - - c. Affirmer disclaims responsibility for clearing rights of other persons - that may apply to the Work or any use thereof, including without limitation - any person's Copyright and Related Rights in the Work. Further, Affirmer - disclaims responsibility for obtaining any necessary consents, permissions - or other rights required for any use of the Work. - - d. Affirmer understands and acknowledges that Creative Commons is not a - party to this document and has no duty or obligation with respect to this - CC0 or use of the Work. - -For more information, please see - diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/address.c b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/address.c deleted file mode 100644 index b956e9cb29..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/address.c +++ /dev/null @@ -1,91 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "utils.h" - -/* - * Specify which level of Merkle tree (the "layer") we're working on - */ -void set_layer_addr(uint32_t addr[8], uint32_t layer) { - ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; -} - -/* - * Specify which Merkle tree within the level (the "tree address") we're working on - */ -void set_tree_addr(uint32_t addr[8], uint64_t tree) { - ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); -} - -/* - * Specify the reason we'll use this address structure for, that is, what - * hash will we compute with it. This is used so that unrelated types of - * hashes don't accidentally get the same address structure. The type will be - * one of the SPX_ADDR_TYPE constants - */ -void set_type(uint32_t addr[8], uint32_t type) { - ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; -} - -/* - * Copy the layer and tree fields of the address structure. This is used - * when we're doing multiple types of hashes within the same Merkle tree - */ -void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { - memcpy( out, in, SPX_OFFSET_TREE + 8 ); -} - -/* These functions are used for OTS addresses. */ - -/* - * Specify which Merkle leaf we're working on; that is, which OTS keypair - * we're talking about. - */ -void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { - ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; -} - -/* - * Copy the layer, tree and keypair fields of the address structure. This is - * used when we're doing multiple things within the same OTS keypair - */ -void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { - memcpy( out, in, SPX_OFFSET_TREE + 8 ); - ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; -} - -/* - * Specify which Merkle chain within the OTS we're working with - * (the chain address) - */ -void set_chain_addr(uint32_t addr[8], uint32_t chain) { - ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; -} - -/* - * Specify where in the Merkle chain we are -* (the hash address) - */ -void set_hash_addr(uint32_t addr[8], uint32_t hash) { - ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; -} - -/* These functions are used for all hash tree addresses (including FORS). */ - -/* - * Specify the height of the node in the Merkle/FORS tree we are in - * (the tree height) - */ -void set_tree_height(uint32_t addr[8], uint32_t tree_height) { - ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; -} - -/* - * Specify the distance from the left edge of the node in the Merkle/FORS tree - * (the tree index) - */ -void set_tree_index(uint32_t addr[8], uint32_t tree_index) { - u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/address.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/address.h deleted file mode 100644 index 24a84eb40c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/address.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef SPX_ADDRESS_H -#define SPX_ADDRESS_H - -#include - -#include "params.h" - -/* The hash types that are passed to set_type */ -#define SPX_ADDR_TYPE_WOTS 0 -#define SPX_ADDR_TYPE_WOTSPK 1 -#define SPX_ADDR_TYPE_HASHTREE 2 -#define SPX_ADDR_TYPE_FORSTREE 3 -#define SPX_ADDR_TYPE_FORSPK 4 -#define SPX_ADDR_TYPE_WOTSPRF 5 -#define SPX_ADDR_TYPE_FORSPRF 6 - -#define set_layer_addr SPX_NAMESPACE(set_layer_addr) -void set_layer_addr(uint32_t addr[8], uint32_t layer); - -#define set_tree_addr SPX_NAMESPACE(set_tree_addr) -void set_tree_addr(uint32_t addr[8], uint64_t tree); - -#define set_type SPX_NAMESPACE(set_type) -void set_type(uint32_t addr[8], uint32_t type); - -/* Copies the layer and tree part of one address into the other */ -#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) -void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for WOTS and FORS addresses. */ - -#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) -void set_keypair_addr(uint32_t addr[8], uint32_t keypair); - -#define set_chain_addr SPX_NAMESPACE(set_chain_addr) -void set_chain_addr(uint32_t addr[8], uint32_t chain); - -#define set_hash_addr SPX_NAMESPACE(set_hash_addr) -void set_hash_addr(uint32_t addr[8], uint32_t hash); - -#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) -void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for all hash tree addresses (including FORS). */ - -#define set_tree_height SPX_NAMESPACE(set_tree_height) -void set_tree_height(uint32_t addr[8], uint32_t tree_height); - -#define set_tree_index SPX_NAMESPACE(set_tree_index) -void set_tree_index(uint32_t addr[8], uint32_t tree_index); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/api.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/api.h deleted file mode 100644 index b9d6d35c70..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/api.h +++ /dev/null @@ -1,77 +0,0 @@ -#ifndef PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_API_H -#define PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_API_H - -#include -#include - -#define PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_CRYPTO_ALGNAME "SPHINCS+-haraka-256s-robust" - -#define PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_CRYPTO_SECRETKEYBYTES 128 -#define PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_CRYPTO_PUBLICKEYBYTES 64 -#define PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_CRYPTO_BYTES 29792 - -#define PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_CRYPTO_SEEDBYTES 96 - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, - const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk); -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/context.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/context.h deleted file mode 100644 index 600dfb73c7..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/context.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef SPX_CONTEXT_H -#define SPX_CONTEXT_H - -#include -#include - -#include "params.h" - -typedef struct { - uint8_t pub_seed[SPX_N]; - uint8_t sk_seed[SPX_N]; - - - uint64_t tweaked512_rc64[10][8]; - uint32_t tweaked256_rc32[10][8]; -} spx_ctx; - -#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) -void initialize_hash_function(spx_ctx *ctx); - -#define free_hash_function SPX_NAMESPACE(free_hash_function) -void free_hash_function(spx_ctx *ctx); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/context_haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/context_haraka.c deleted file mode 100644 index f1cd7e3664..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/context_haraka.c +++ /dev/null @@ -1,11 +0,0 @@ -#include "context.h" -#include "haraka.h" - -void initialize_hash_function(spx_ctx *ctx) { - tweak_constants(ctx); -} - -// we don't support heap-based haraka right now -void free_hash_function(spx_ctx *ctx) { - (void)ctx; // suppress unused variable warnings -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/fors.c b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/fors.c deleted file mode 100644 index 96ca72e986..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/fors.c +++ /dev/null @@ -1,156 +0,0 @@ -#include -#include -#include - -#include "fors.h" - -#include "address.h" -#include "hash.h" -#include "thash.h" -#include "utils.h" -#include "utilsx1.h" - -static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, - uint32_t fors_leaf_addr[8]) { - prf_addr(sk, ctx, fors_leaf_addr); -} - -static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, - const spx_ctx *ctx, - uint32_t fors_leaf_addr[8]) { - thash(leaf, sk, 1, ctx, fors_leaf_addr); -} - -struct fors_gen_leaf_info { - uint32_t leaf_addrx[8]; -}; - -static void fors_gen_leafx1(unsigned char *leaf, - const spx_ctx *ctx, - uint32_t addr_idx, void *info) { - struct fors_gen_leaf_info *fors_info = info; - uint32_t *fors_leaf_addr = fors_info->leaf_addrx; - - /* Only set the parts that the caller doesn't set */ - set_tree_index(fors_leaf_addr, addr_idx); - set_type(fors_leaf_addr, SPX_ADDR_TYPE_FORSPRF); - fors_gen_sk(leaf, ctx, fors_leaf_addr); - - set_type(fors_leaf_addr, SPX_ADDR_TYPE_FORSTREE); - fors_sk_to_leaf(leaf, leaf, - ctx, fors_leaf_addr); -} - -/** - * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - * Assumes indices has space for SPX_FORS_TREES integers. - */ -static void message_to_indices(uint32_t *indices, const unsigned char *m) { - unsigned int i, j; - unsigned int offset = 0; - - for (i = 0; i < SPX_FORS_TREES; i++) { - indices[i] = 0; - for (j = 0; j < SPX_FORS_HEIGHT; j++) { - indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); - offset++; - } - } -} - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -void fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]) { - uint32_t indices[SPX_FORS_TREES]; - unsigned char roots[SPX_FORS_TREES * SPX_N]; - uint32_t fors_tree_addr[8] = {0}; - struct fors_gen_leaf_info fors_info = {0}; - uint32_t *fors_leaf_addr = fors_info.leaf_addrx; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - copy_keypair_addr(fors_tree_addr, fors_addr); - copy_keypair_addr(fors_leaf_addr, fors_addr); - - copy_keypair_addr(fors_pk_addr, fors_addr); - set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < SPX_FORS_TREES; i++) { - idx_offset = i * (1 << SPX_FORS_HEIGHT); - - set_tree_height(fors_tree_addr, 0); - set_tree_index(fors_tree_addr, indices[i] + idx_offset); - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); - - /* Include the secret key part that produces the selected leaf node. */ - fors_gen_sk(sig, ctx, fors_tree_addr); - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); - sig += SPX_N; - - /* Compute the authentication path for this leaf node. */ - treehashx1(roots + i * SPX_N, sig, ctx, - indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx1, - fors_tree_addr, &fors_info); - - sig += SPX_N * SPX_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); -} - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -void fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]) { - uint32_t indices[SPX_FORS_TREES]; - unsigned char roots[SPX_FORS_TREES * SPX_N]; - unsigned char leaf[SPX_N]; - uint32_t fors_tree_addr[8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - copy_keypair_addr(fors_tree_addr, fors_addr); - copy_keypair_addr(fors_pk_addr, fors_addr); - - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); - set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < SPX_FORS_TREES; i++) { - idx_offset = i * (1 << SPX_FORS_HEIGHT); - - set_tree_height(fors_tree_addr, 0); - set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Derive the leaf from the included secret key part. */ - fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); - sig += SPX_N; - - /* Derive the corresponding root node of this tree. */ - compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, - sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); - sig += SPX_N * SPX_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/fors.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/fors.h deleted file mode 100644 index 509140a178..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/fors.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef SPX_FORS_H -#define SPX_FORS_H - -#include - -#include "context.h" -#include "params.h" - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -#define fors_sign SPX_NAMESPACE(fors_sign) -void fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]); - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) -void fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/haraka.c deleted file mode 100644 index a4944913b5..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/haraka.c +++ /dev/null @@ -1,913 +0,0 @@ -/* - * Constant time implementation of the Haraka hash function. - * - * The bit-sliced implementation of the AES round functions are - * based on the AES implementation in BearSSL written - * by Thomas Pornin - */ - -#include -#include -#include -#include - -#include "haraka.h" -#include "utils.h" - -#define HARAKAS_RATE 32 - -static const uint64_t haraka512_rc64[10][8] = { - {0x24cf0ab9086f628b, 0xbdd6eeecc83b8382, 0xd96fb0306cdad0a7, 0xaace082ac8f95f89, 0x449d8e8870d7041f, 0x49bb2f80b2b3e2f8, 0x0569ae98d93bb258, 0x23dc9691e7d6a4b1}, - {0xd8ba10ede0fe5b6e, 0x7ecf7dbe424c7b8e, 0x6ea9949c6df62a31, 0xbf3f3c97ec9c313e, 0x241d03a196a1861e, 0xead3a51116e5a2ea, 0x77d479fcad9574e3, 0x18657a1af894b7a0}, - {0x10671e1a7f595522, 0xd9a00ff675d28c7b, 0x2f1edf0d2b9ba661, 0xb8ff58b8e3de45f9, 0xee29261da9865c02, 0xd1532aa4b50bdf43, 0x8bf858159b231bb1, 0xdf17439d22d4f599}, - {0xdd4b2f0870b918c0, 0x757a81f3b39b1bb6, 0x7a5c556898952e3f, 0x7dd70a16d915d87a, 0x3ae61971982b8301, 0xc3ab319e030412be, 0x17c0033ac094a8cb, 0x5a0630fc1a8dc4ef}, - {0x17708988c1632f73, 0xf92ddae090b44f4f, 0x11ac0285c43aa314, 0x509059941936b8ba, 0xd03e152fa2ce9b69, 0x3fbcbcb63a32998b, 0x6204696d692254f7, 0x915542ed93ec59b4}, - {0xf4ed94aa8879236e, 0xff6cb41cd38e03c0, 0x069b38602368aeab, 0x669495b820f0ddba, 0xf42013b1b8bf9e3d, 0xcf935efe6439734d, 0xbc1dcf42ca29e3f8, 0x7e6d3ed29f78ad67}, - {0xf3b0f6837ffcddaa, 0x3a76faef934ddf41, 0xcec7ae583a9c8e35, 0xe4dd18c68f0260af, 0x2c0e5df1ad398eaa, 0x478df5236ae22e8c, 0xfb944c46fe865f39, 0xaa48f82f028132ba}, - {0x231b9ae2b76aca77, 0x292a76a712db0b40, 0x5850625dc8134491, 0x73137dd469810fb5, 0x8a12a6a202a474fd, 0xd36fd9daa78bdb80, 0xb34c5e733505706f, 0xbaf1cdca818d9d96}, - {0x2e99781335e8c641, 0xbddfe5cce47d560e, 0xf74e9bf32e5e040c, 0x1d7a709d65996be9, 0x670df36a9cf66cdd, 0xd05ef84a176a2875, 0x0f888e828cb1c44e, 0x1a79e9c9727b052c}, - {0x83497348628d84de, 0x2e9387d51f22a754, 0xb000068da2f852d6, 0x378c9e1190fd6fe5, 0x870027c316de7293, 0xe51a9d4462e047bb, 0x90ecf7f8c6251195, 0x655953bfbed90a9c}, -}; - -static inline uint32_t br_dec32le(const unsigned char *src) { - return (uint32_t)src[0] - | ((uint32_t)src[1] << 8) - | ((uint32_t)src[2] << 16) - | ((uint32_t)src[3] << 24); -} - -static void br_range_dec32le(uint32_t *v, size_t num, const unsigned char *src) { - while (num-- > 0) { - *v ++ = br_dec32le(src); - src += 4; - } -} - -static inline void br_enc32le(unsigned char *dst, uint32_t x) { - dst[0] = (unsigned char)x; - dst[1] = (unsigned char)(x >> 8); - dst[2] = (unsigned char)(x >> 16); - dst[3] = (unsigned char)(x >> 24); -} - - -static void br_range_enc32le(unsigned char *dst, const uint32_t *v, size_t num) { - while (num-- > 0) { - br_enc32le(dst, *v ++); - dst += 4; - } -} - -static void br_aes_ct64_bitslice_Sbox(uint64_t *q) { - /* - * This S-box implementation is a straightforward translation of - * the circuit described by Boyar and Peralta in "A new - * combinational logic minimization technique with applications - * to cryptology" (https://eprint.iacr.org/2009/191.pdf). - * - * Note that variables x* (input) and s* (output) are numbered - * in "reverse" order (x0 is the high bit, x7 is the low bit). - */ - - uint64_t x0, x1, x2, x3, x4, x5, x6, x7; - uint64_t y1, y2, y3, y4, y5, y6, y7, y8, y9; - uint64_t y10, y11, y12, y13, y14, y15, y16, y17, y18, y19; - uint64_t y20, y21; - uint64_t z0, z1, z2, z3, z4, z5, z6, z7, z8, z9; - uint64_t z10, z11, z12, z13, z14, z15, z16, z17; - uint64_t t0, t1, t2, t3, t4, t5, t6, t7, t8, t9; - uint64_t t10, t11, t12, t13, t14, t15, t16, t17, t18, t19; - uint64_t t20, t21, t22, t23, t24, t25, t26, t27, t28, t29; - uint64_t t30, t31, t32, t33, t34, t35, t36, t37, t38, t39; - uint64_t t40, t41, t42, t43, t44, t45, t46, t47, t48, t49; - uint64_t t50, t51, t52, t53, t54, t55, t56, t57, t58, t59; - uint64_t t60, t61, t62, t63, t64, t65, t66, t67; - uint64_t s0, s1, s2, s3, s4, s5, s6, s7; - - x0 = q[7]; - x1 = q[6]; - x2 = q[5]; - x3 = q[4]; - x4 = q[3]; - x5 = q[2]; - x6 = q[1]; - x7 = q[0]; - - /* - * Top linear transformation. - */ - y14 = x3 ^ x5; - y13 = x0 ^ x6; - y9 = x0 ^ x3; - y8 = x0 ^ x5; - t0 = x1 ^ x2; - y1 = t0 ^ x7; - y4 = y1 ^ x3; - y12 = y13 ^ y14; - y2 = y1 ^ x0; - y5 = y1 ^ x6; - y3 = y5 ^ y8; - t1 = x4 ^ y12; - y15 = t1 ^ x5; - y20 = t1 ^ x1; - y6 = y15 ^ x7; - y10 = y15 ^ t0; - y11 = y20 ^ y9; - y7 = x7 ^ y11; - y17 = y10 ^ y11; - y19 = y10 ^ y8; - y16 = t0 ^ y11; - y21 = y13 ^ y16; - y18 = x0 ^ y16; - - /* - * Non-linear section. - */ - t2 = y12 & y15; - t3 = y3 & y6; - t4 = t3 ^ t2; - t5 = y4 & x7; - t6 = t5 ^ t2; - t7 = y13 & y16; - t8 = y5 & y1; - t9 = t8 ^ t7; - t10 = y2 & y7; - t11 = t10 ^ t7; - t12 = y9 & y11; - t13 = y14 & y17; - t14 = t13 ^ t12; - t15 = y8 & y10; - t16 = t15 ^ t12; - t17 = t4 ^ t14; - t18 = t6 ^ t16; - t19 = t9 ^ t14; - t20 = t11 ^ t16; - t21 = t17 ^ y20; - t22 = t18 ^ y19; - t23 = t19 ^ y21; - t24 = t20 ^ y18; - - t25 = t21 ^ t22; - t26 = t21 & t23; - t27 = t24 ^ t26; - t28 = t25 & t27; - t29 = t28 ^ t22; - t30 = t23 ^ t24; - t31 = t22 ^ t26; - t32 = t31 & t30; - t33 = t32 ^ t24; - t34 = t23 ^ t33; - t35 = t27 ^ t33; - t36 = t24 & t35; - t37 = t36 ^ t34; - t38 = t27 ^ t36; - t39 = t29 & t38; - t40 = t25 ^ t39; - - t41 = t40 ^ t37; - t42 = t29 ^ t33; - t43 = t29 ^ t40; - t44 = t33 ^ t37; - t45 = t42 ^ t41; - z0 = t44 & y15; - z1 = t37 & y6; - z2 = t33 & x7; - z3 = t43 & y16; - z4 = t40 & y1; - z5 = t29 & y7; - z6 = t42 & y11; - z7 = t45 & y17; - z8 = t41 & y10; - z9 = t44 & y12; - z10 = t37 & y3; - z11 = t33 & y4; - z12 = t43 & y13; - z13 = t40 & y5; - z14 = t29 & y2; - z15 = t42 & y9; - z16 = t45 & y14; - z17 = t41 & y8; - - /* - * Bottom linear transformation. - */ - t46 = z15 ^ z16; - t47 = z10 ^ z11; - t48 = z5 ^ z13; - t49 = z9 ^ z10; - t50 = z2 ^ z12; - t51 = z2 ^ z5; - t52 = z7 ^ z8; - t53 = z0 ^ z3; - t54 = z6 ^ z7; - t55 = z16 ^ z17; - t56 = z12 ^ t48; - t57 = t50 ^ t53; - t58 = z4 ^ t46; - t59 = z3 ^ t54; - t60 = t46 ^ t57; - t61 = z14 ^ t57; - t62 = t52 ^ t58; - t63 = t49 ^ t58; - t64 = z4 ^ t59; - t65 = t61 ^ t62; - t66 = z1 ^ t63; - s0 = t59 ^ t63; - s6 = t56 ^ ~t62; - s7 = t48 ^ ~t60; - t67 = t64 ^ t65; - s3 = t53 ^ t66; - s4 = t51 ^ t66; - s5 = t47 ^ t65; - s1 = t64 ^ ~s3; - s2 = t55 ^ ~t67; - - q[7] = s0; - q[6] = s1; - q[5] = s2; - q[4] = s3; - q[3] = s4; - q[2] = s5; - q[1] = s6; - q[0] = s7; -} - -static void br_aes_ct_bitslice_Sbox(uint32_t *q) { - /* - * This S-box implementation is a straightforward translation of - * the circuit described by Boyar and Peralta in "A new - * combinational logic minimization technique with applications - * to cryptology" (https://eprint.iacr.org/2009/191.pdf). - * - * Note that variables x* (input) and s* (output) are numbered - * in "reverse" order (x0 is the high bit, x7 is the low bit). - */ - - uint32_t x0, x1, x2, x3, x4, x5, x6, x7; - uint32_t y1, y2, y3, y4, y5, y6, y7, y8, y9; - uint32_t y10, y11, y12, y13, y14, y15, y16, y17, y18, y19; - uint32_t y20, y21; - uint32_t z0, z1, z2, z3, z4, z5, z6, z7, z8, z9; - uint32_t z10, z11, z12, z13, z14, z15, z16, z17; - uint32_t t0, t1, t2, t3, t4, t5, t6, t7, t8, t9; - uint32_t t10, t11, t12, t13, t14, t15, t16, t17, t18, t19; - uint32_t t20, t21, t22, t23, t24, t25, t26, t27, t28, t29; - uint32_t t30, t31, t32, t33, t34, t35, t36, t37, t38, t39; - uint32_t t40, t41, t42, t43, t44, t45, t46, t47, t48, t49; - uint32_t t50, t51, t52, t53, t54, t55, t56, t57, t58, t59; - uint32_t t60, t61, t62, t63, t64, t65, t66, t67; - uint32_t s0, s1, s2, s3, s4, s5, s6, s7; - - x0 = q[7]; - x1 = q[6]; - x2 = q[5]; - x3 = q[4]; - x4 = q[3]; - x5 = q[2]; - x6 = q[1]; - x7 = q[0]; - - /* - * Top linear transformation. - */ - y14 = x3 ^ x5; - y13 = x0 ^ x6; - y9 = x0 ^ x3; - y8 = x0 ^ x5; - t0 = x1 ^ x2; - y1 = t0 ^ x7; - y4 = y1 ^ x3; - y12 = y13 ^ y14; - y2 = y1 ^ x0; - y5 = y1 ^ x6; - y3 = y5 ^ y8; - t1 = x4 ^ y12; - y15 = t1 ^ x5; - y20 = t1 ^ x1; - y6 = y15 ^ x7; - y10 = y15 ^ t0; - y11 = y20 ^ y9; - y7 = x7 ^ y11; - y17 = y10 ^ y11; - y19 = y10 ^ y8; - y16 = t0 ^ y11; - y21 = y13 ^ y16; - y18 = x0 ^ y16; - - /* - * Non-linear section. - */ - t2 = y12 & y15; - t3 = y3 & y6; - t4 = t3 ^ t2; - t5 = y4 & x7; - t6 = t5 ^ t2; - t7 = y13 & y16; - t8 = y5 & y1; - t9 = t8 ^ t7; - t10 = y2 & y7; - t11 = t10 ^ t7; - t12 = y9 & y11; - t13 = y14 & y17; - t14 = t13 ^ t12; - t15 = y8 & y10; - t16 = t15 ^ t12; - t17 = t4 ^ t14; - t18 = t6 ^ t16; - t19 = t9 ^ t14; - t20 = t11 ^ t16; - t21 = t17 ^ y20; - t22 = t18 ^ y19; - t23 = t19 ^ y21; - t24 = t20 ^ y18; - - t25 = t21 ^ t22; - t26 = t21 & t23; - t27 = t24 ^ t26; - t28 = t25 & t27; - t29 = t28 ^ t22; - t30 = t23 ^ t24; - t31 = t22 ^ t26; - t32 = t31 & t30; - t33 = t32 ^ t24; - t34 = t23 ^ t33; - t35 = t27 ^ t33; - t36 = t24 & t35; - t37 = t36 ^ t34; - t38 = t27 ^ t36; - t39 = t29 & t38; - t40 = t25 ^ t39; - - t41 = t40 ^ t37; - t42 = t29 ^ t33; - t43 = t29 ^ t40; - t44 = t33 ^ t37; - t45 = t42 ^ t41; - z0 = t44 & y15; - z1 = t37 & y6; - z2 = t33 & x7; - z3 = t43 & y16; - z4 = t40 & y1; - z5 = t29 & y7; - z6 = t42 & y11; - z7 = t45 & y17; - z8 = t41 & y10; - z9 = t44 & y12; - z10 = t37 & y3; - z11 = t33 & y4; - z12 = t43 & y13; - z13 = t40 & y5; - z14 = t29 & y2; - z15 = t42 & y9; - z16 = t45 & y14; - z17 = t41 & y8; - - /* - * Bottom linear transformation. - */ - t46 = z15 ^ z16; - t47 = z10 ^ z11; - t48 = z5 ^ z13; - t49 = z9 ^ z10; - t50 = z2 ^ z12; - t51 = z2 ^ z5; - t52 = z7 ^ z8; - t53 = z0 ^ z3; - t54 = z6 ^ z7; - t55 = z16 ^ z17; - t56 = z12 ^ t48; - t57 = t50 ^ t53; - t58 = z4 ^ t46; - t59 = z3 ^ t54; - t60 = t46 ^ t57; - t61 = z14 ^ t57; - t62 = t52 ^ t58; - t63 = t49 ^ t58; - t64 = z4 ^ t59; - t65 = t61 ^ t62; - t66 = z1 ^ t63; - s0 = t59 ^ t63; - s6 = t56 ^ ~t62; - s7 = t48 ^ ~t60; - t67 = t64 ^ t65; - s3 = t53 ^ t66; - s4 = t51 ^ t66; - s5 = t47 ^ t65; - s1 = t64 ^ ~s3; - s2 = t55 ^ ~t67; - - q[7] = s0; - q[6] = s1; - q[5] = s2; - q[4] = s3; - q[3] = s4; - q[2] = s5; - q[1] = s6; - q[0] = s7; -} - -static void br_aes_ct_ortho(uint32_t *q) { -#define SWAPN_32(cl, ch, s, x, y) do { \ - uint32_t a, b; \ - a = (x); \ - b = (y); \ - (x) = (a & (uint32_t)(cl)) | ((b & (uint32_t)(cl)) << (s)); \ - (y) = ((a & (uint32_t)(ch)) >> (s)) | (b & (uint32_t)(ch)); \ - } while (0) - -#define SWAP2_32(x, y) SWAPN_32(0x55555555, 0xAAAAAAAA, 1, x, y) -#define SWAP4_32(x, y) SWAPN_32(0x33333333, 0xCCCCCCCC, 2, x, y) -#define SWAP8_32(x, y) SWAPN_32(0x0F0F0F0F, 0xF0F0F0F0, 4, x, y) - - SWAP2_32(q[0], q[1]); - SWAP2_32(q[2], q[3]); - SWAP2_32(q[4], q[5]); - SWAP2_32(q[6], q[7]); - - SWAP4_32(q[0], q[2]); - SWAP4_32(q[1], q[3]); - SWAP4_32(q[4], q[6]); - SWAP4_32(q[5], q[7]); - - SWAP8_32(q[0], q[4]); - SWAP8_32(q[1], q[5]); - SWAP8_32(q[2], q[6]); - SWAP8_32(q[3], q[7]); -} - -static inline void add_round_key32(uint32_t *q, const uint32_t *sk) { - q[0] ^= sk[0]; - q[1] ^= sk[1]; - q[2] ^= sk[2]; - q[3] ^= sk[3]; - q[4] ^= sk[4]; - q[5] ^= sk[5]; - q[6] ^= sk[6]; - q[7] ^= sk[7]; -} - -static inline void shift_rows32(uint32_t *q) { - int i; - - for (i = 0; i < 8; i++) { - uint32_t x; - - x = q[i]; - q[i] = (x & 0x000000FF) - | ((x & 0x0000FC00) >> 2) | ((x & 0x00000300) << 6) - | ((x & 0x00F00000) >> 4) | ((x & 0x000F0000) << 4) - | ((x & 0xC0000000) >> 6) | ((x & 0x3F000000) << 2); - } -} - -static inline uint32_t rotr16(uint32_t x) { - return (x << 16) | (x >> 16); -} - -static inline void mix_columns32(uint32_t *q) { - uint32_t q0, q1, q2, q3, q4, q5, q6, q7; - uint32_t r0, r1, r2, r3, r4, r5, r6, r7; - - q0 = q[0]; - q1 = q[1]; - q2 = q[2]; - q3 = q[3]; - q4 = q[4]; - q5 = q[5]; - q6 = q[6]; - q7 = q[7]; - r0 = (q0 >> 8) | (q0 << 24); - r1 = (q1 >> 8) | (q1 << 24); - r2 = (q2 >> 8) | (q2 << 24); - r3 = (q3 >> 8) | (q3 << 24); - r4 = (q4 >> 8) | (q4 << 24); - r5 = (q5 >> 8) | (q5 << 24); - r6 = (q6 >> 8) | (q6 << 24); - r7 = (q7 >> 8) | (q7 << 24); - - q[0] = q7 ^ r7 ^ r0 ^ rotr16(q0 ^ r0); - q[1] = q0 ^ r0 ^ q7 ^ r7 ^ r1 ^ rotr16(q1 ^ r1); - q[2] = q1 ^ r1 ^ r2 ^ rotr16(q2 ^ r2); - q[3] = q2 ^ r2 ^ q7 ^ r7 ^ r3 ^ rotr16(q3 ^ r3); - q[4] = q3 ^ r3 ^ q7 ^ r7 ^ r4 ^ rotr16(q4 ^ r4); - q[5] = q4 ^ r4 ^ r5 ^ rotr16(q5 ^ r5); - q[6] = q5 ^ r5 ^ r6 ^ rotr16(q6 ^ r6); - q[7] = q6 ^ r6 ^ r7 ^ rotr16(q7 ^ r7); -} - -static void br_aes_ct64_ortho(uint64_t *q) { -#define SWAPN(cl, ch, s, x, y) do { \ - uint64_t a, b; \ - a = (x); \ - b = (y); \ - (x) = (a & (uint64_t)(cl)) | ((b & (uint64_t)(cl)) << (s)); \ - (y) = ((a & (uint64_t)(ch)) >> (s)) | (b & (uint64_t)(ch)); \ - } while (0) - -#define SWAP2(x, y) SWAPN(0x5555555555555555, 0xAAAAAAAAAAAAAAAA, 1, x, y) -#define SWAP4(x, y) SWAPN(0x3333333333333333, 0xCCCCCCCCCCCCCCCC, 2, x, y) -#define SWAP8(x, y) SWAPN(0x0F0F0F0F0F0F0F0F, 0xF0F0F0F0F0F0F0F0, 4, x, y) - - SWAP2(q[0], q[1]); - SWAP2(q[2], q[3]); - SWAP2(q[4], q[5]); - SWAP2(q[6], q[7]); - - SWAP4(q[0], q[2]); - SWAP4(q[1], q[3]); - SWAP4(q[4], q[6]); - SWAP4(q[5], q[7]); - - SWAP8(q[0], q[4]); - SWAP8(q[1], q[5]); - SWAP8(q[2], q[6]); - SWAP8(q[3], q[7]); -} - - -static void br_aes_ct64_interleave_in(uint64_t *q0, uint64_t *q1, const uint32_t *w) { - uint64_t x0, x1, x2, x3; - - x0 = w[0]; - x1 = w[1]; - x2 = w[2]; - x3 = w[3]; - x0 |= (x0 << 16); - x1 |= (x1 << 16); - x2 |= (x2 << 16); - x3 |= (x3 << 16); - x0 &= (uint64_t)0x0000FFFF0000FFFF; - x1 &= (uint64_t)0x0000FFFF0000FFFF; - x2 &= (uint64_t)0x0000FFFF0000FFFF; - x3 &= (uint64_t)0x0000FFFF0000FFFF; - x0 |= (x0 << 8); - x1 |= (x1 << 8); - x2 |= (x2 << 8); - x3 |= (x3 << 8); - x0 &= (uint64_t)0x00FF00FF00FF00FF; - x1 &= (uint64_t)0x00FF00FF00FF00FF; - x2 &= (uint64_t)0x00FF00FF00FF00FF; - x3 &= (uint64_t)0x00FF00FF00FF00FF; - *q0 = x0 | (x2 << 8); - *q1 = x1 | (x3 << 8); -} - - -static void br_aes_ct64_interleave_out(uint32_t *w, uint64_t q0, uint64_t q1) { - uint64_t x0, x1, x2, x3; - - x0 = q0 & (uint64_t)0x00FF00FF00FF00FF; - x1 = q1 & (uint64_t)0x00FF00FF00FF00FF; - x2 = (q0 >> 8) & (uint64_t)0x00FF00FF00FF00FF; - x3 = (q1 >> 8) & (uint64_t)0x00FF00FF00FF00FF; - x0 |= (x0 >> 8); - x1 |= (x1 >> 8); - x2 |= (x2 >> 8); - x3 |= (x3 >> 8); - x0 &= (uint64_t)0x0000FFFF0000FFFF; - x1 &= (uint64_t)0x0000FFFF0000FFFF; - x2 &= (uint64_t)0x0000FFFF0000FFFF; - x3 &= (uint64_t)0x0000FFFF0000FFFF; - w[0] = (uint32_t)x0 | (uint32_t)(x0 >> 16); - w[1] = (uint32_t)x1 | (uint32_t)(x1 >> 16); - w[2] = (uint32_t)x2 | (uint32_t)(x2 >> 16); - w[3] = (uint32_t)x3 | (uint32_t)(x3 >> 16); -} - -static inline void add_round_key(uint64_t *q, const uint64_t *sk) { - q[0] ^= sk[0]; - q[1] ^= sk[1]; - q[2] ^= sk[2]; - q[3] ^= sk[3]; - q[4] ^= sk[4]; - q[5] ^= sk[5]; - q[6] ^= sk[6]; - q[7] ^= sk[7]; -} - -static inline void shift_rows(uint64_t *q) { - int i; - - for (i = 0; i < 8; i++) { - uint64_t x; - - x = q[i]; - q[i] = (x & (uint64_t)0x000000000000FFFF) - | ((x & (uint64_t)0x00000000FFF00000) >> 4) - | ((x & (uint64_t)0x00000000000F0000) << 12) - | ((x & (uint64_t)0x0000FF0000000000) >> 8) - | ((x & (uint64_t)0x000000FF00000000) << 8) - | ((x & (uint64_t)0xF000000000000000) >> 12) - | ((x & (uint64_t)0x0FFF000000000000) << 4); - } -} - -static inline uint64_t rotr32(uint64_t x) { - return (x << 32) | (x >> 32); -} - -static inline void mix_columns(uint64_t *q) { - uint64_t q0, q1, q2, q3, q4, q5, q6, q7; - uint64_t r0, r1, r2, r3, r4, r5, r6, r7; - - q0 = q[0]; - q1 = q[1]; - q2 = q[2]; - q3 = q[3]; - q4 = q[4]; - q5 = q[5]; - q6 = q[6]; - q7 = q[7]; - r0 = (q0 >> 16) | (q0 << 48); - r1 = (q1 >> 16) | (q1 << 48); - r2 = (q2 >> 16) | (q2 << 48); - r3 = (q3 >> 16) | (q3 << 48); - r4 = (q4 >> 16) | (q4 << 48); - r5 = (q5 >> 16) | (q5 << 48); - r6 = (q6 >> 16) | (q6 << 48); - r7 = (q7 >> 16) | (q7 << 48); - - q[0] = q7 ^ r7 ^ r0 ^ rotr32(q0 ^ r0); - q[1] = q0 ^ r0 ^ q7 ^ r7 ^ r1 ^ rotr32(q1 ^ r1); - q[2] = q1 ^ r1 ^ r2 ^ rotr32(q2 ^ r2); - q[3] = q2 ^ r2 ^ q7 ^ r7 ^ r3 ^ rotr32(q3 ^ r3); - q[4] = q3 ^ r3 ^ q7 ^ r7 ^ r4 ^ rotr32(q4 ^ r4); - q[5] = q4 ^ r4 ^ r5 ^ rotr32(q5 ^ r5); - q[6] = q5 ^ r5 ^ r6 ^ rotr32(q6 ^ r6); - q[7] = q6 ^ r6 ^ r7 ^ rotr32(q7 ^ r7); -} - -static void interleave_constant(uint64_t *out, const unsigned char *in) { - uint32_t tmp_32_constant[16]; - int i; - - br_range_dec32le(tmp_32_constant, 16, in); - for (i = 0; i < 4; i++) { - br_aes_ct64_interleave_in(&out[i], &out[i + 4], tmp_32_constant + (i << 2)); - } - br_aes_ct64_ortho(out); -} - -static void interleave_constant32(uint32_t *out, const unsigned char *in) { - int i; - for (i = 0; i < 4; i++) { - out[2 * i] = br_dec32le(in + 4 * i); - out[2 * i + 1] = br_dec32le(in + 4 * i + 16); - } - br_aes_ct_ortho(out); -} - -void tweak_constants(spx_ctx *ctx) { - unsigned char buf[40 * 16]; - int i; - - /* Use the standard constants to generate tweaked ones. */ - memcpy((uint8_t *)ctx->tweaked512_rc64, (uint8_t *)haraka512_rc64, 40 * 16); - - /* Constants for pk.seed */ - haraka_S(buf, 40 * 16, ctx->pub_seed, SPX_N, ctx); - for (i = 0; i < 10; i++) { - interleave_constant32(ctx->tweaked256_rc32[i], buf + 32 * i); - interleave_constant(ctx->tweaked512_rc64[i], buf + 64 * i); - } -} - -static void haraka_S_absorb(unsigned char *s, unsigned int r, - const unsigned char *m, unsigned long long mlen, - unsigned char p, const spx_ctx *ctx) { - unsigned long long i; - PQCLEAN_VLA(uint8_t, t, r); - - while (mlen >= r) { - /* XOR block to state */ - for (i = 0; i < r; ++i) { - s[i] ^= m[i]; - } - haraka512_perm(s, s, ctx); - 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; ++i) { - s[i] ^= t[i]; - } -} - -static void haraka_S_squeezeblocks(unsigned char *h, unsigned long long nblocks, - unsigned char *s, unsigned int r, - const spx_ctx *ctx) { - while (nblocks > 0) { - haraka512_perm(s, s, ctx); - memcpy(h, s, HARAKAS_RATE); - h += r; - nblocks--; - } -} - -void haraka_S_inc_init(uint8_t *s_inc) { - size_t i; - - for (i = 0; i < 64; i++) { - s_inc[i] = 0; - } - s_inc[64] = 0; -} - -void haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, - const spx_ctx *ctx) { - size_t i; - - /* Recall that s_inc[64] is the non-absorbed bytes xored into the state */ - while (mlen + s_inc[64] >= HARAKAS_RATE) { - for (i = 0; i < (size_t)(HARAKAS_RATE - s_inc[64]); i++) { - /* Take the i'th byte from message - xor with the s_inc[64] + i'th byte of the state */ - s_inc[s_inc[64] + i] ^= m[i]; - } - mlen -= (size_t)(HARAKAS_RATE - s_inc[64]); - m += HARAKAS_RATE - (uint8_t)s_inc[64]; - s_inc[64] = 0; - - haraka512_perm(s_inc, s_inc, ctx); - } - - for (i = 0; i < mlen; i++) { - s_inc[s_inc[64] + i] ^= m[i]; - } - s_inc[64] += (uint8_t)mlen; -} - -void haraka_S_inc_finalize(uint8_t *s_inc) { - /* After haraka_S_inc_absorb, we are guaranteed that s_inc[64] < HARAKAS_RATE, - so we can always use one more byte for p in the current state. */ - s_inc[s_inc[64]] ^= 0x1F; - s_inc[HARAKAS_RATE - 1] ^= 128; - s_inc[64] = 0; -} - -void haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, - const spx_ctx *ctx) { - size_t i; - - /* First consume any bytes we still have sitting around */ - for (i = 0; i < outlen && i < s_inc[64]; i++) { - /* There are s_inc[64] bytes left, so r - s_inc[64] is the first - available byte. We consume from there, i.e., up to r. */ - out[i] = (uint8_t)s_inc[(HARAKAS_RATE - s_inc[64] + i)]; - } - out += i; - outlen -= i; - s_inc[64] -= (uint8_t)i; - - /* Then squeeze the remaining necessary blocks */ - while (outlen > 0) { - haraka512_perm(s_inc, s_inc, ctx); - - for (i = 0; i < outlen && i < HARAKAS_RATE; i++) { - out[i] = s_inc[i]; - } - out += i; - outlen -= i; - s_inc[64] = (uint8_t)(HARAKAS_RATE - i); - } -} - -void haraka_S(unsigned char *out, unsigned long long outlen, - const unsigned char *in, unsigned long long inlen, - const spx_ctx *ctx) { - unsigned long long i; - unsigned char s[64]; - unsigned char d[32]; - - for (i = 0; i < 64; i++) { - s[i] = 0; - } - haraka_S_absorb(s, 32, in, inlen, 0x1F, ctx); - - haraka_S_squeezeblocks(out, outlen / 32, s, 32, ctx); - out += (outlen / 32) * 32; - - if (outlen % 32) { - haraka_S_squeezeblocks(d, 1, s, 32, ctx); - for (i = 0; i < outlen % 32; i++) { - out[i] = d[i]; - } - } -} - -void haraka512_perm(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx) { - uint32_t w[16]; - uint64_t q[8], tmp_q; - unsigned int i, j; - - br_range_dec32le(w, 16, in); - for (i = 0; i < 4; i++) { - br_aes_ct64_interleave_in(&q[i], &q[i + 4], w + (i << 2)); - } - br_aes_ct64_ortho(q); - - /* AES rounds */ - for (i = 0; i < 5; i++) { - for (j = 0; j < 2; j++) { - br_aes_ct64_bitslice_Sbox(q); - shift_rows(q); - mix_columns(q); - add_round_key(q, ctx->tweaked512_rc64[2 * i + j]); - } - /* Mix states */ - for (j = 0; j < 8; j++) { - tmp_q = q[j]; - q[j] = (tmp_q & 0x0001000100010001) << 5 | - (tmp_q & 0x0002000200020002) << 12 | - (tmp_q & 0x0004000400040004) >> 1 | - (tmp_q & 0x0008000800080008) << 6 | - (tmp_q & 0x0020002000200020) << 9 | - (tmp_q & 0x0040004000400040) >> 4 | - (tmp_q & 0x0080008000800080) << 3 | - (tmp_q & 0x2100210021002100) >> 5 | - (tmp_q & 0x0210021002100210) << 2 | - (tmp_q & 0x0800080008000800) << 4 | - (tmp_q & 0x1000100010001000) >> 12 | - (tmp_q & 0x4000400040004000) >> 10 | - (tmp_q & 0x8400840084008400) >> 3; - } - } - - br_aes_ct64_ortho(q); - for (i = 0; i < 4; i ++) { - br_aes_ct64_interleave_out(w + (i << 2), q[i], q[i + 4]); - } - br_range_enc32le(out, w, 16); -} - -void haraka512(unsigned char *out, const unsigned char *in, const spx_ctx *ctx) { - int i; - - unsigned char buf[64]; - - haraka512_perm(buf, in, ctx); - /* Feed-forward */ - for (i = 0; i < 64; i++) { - buf[i] = buf[i] ^ in[i]; - } - - /* Truncated */ - memcpy(out, buf + 8, 8); - memcpy(out + 8, buf + 24, 8); - memcpy(out + 16, buf + 32, 8); - memcpy(out + 24, buf + 48, 8); -} - - -void haraka256(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx) { - uint32_t q[8], tmp_q; - int i, j; - - for (i = 0; i < 4; i++) { - q[2 * i] = br_dec32le(in + 4 * i); - q[2 * i + 1] = br_dec32le(in + 4 * i + 16); - } - br_aes_ct_ortho(q); - - /* AES rounds */ - for (i = 0; i < 5; i++) { - for (j = 0; j < 2; j++) { - br_aes_ct_bitslice_Sbox(q); - shift_rows32(q); - mix_columns32(q); - add_round_key32(q, ctx->tweaked256_rc32[2 * i + j]); - } - - /* Mix states */ - for (j = 0; j < 8; j++) { - tmp_q = q[j]; - q[j] = (tmp_q & 0x81818181) | - (tmp_q & 0x02020202) << 1 | - (tmp_q & 0x04040404) << 2 | - (tmp_q & 0x08080808) << 3 | - (tmp_q & 0x10101010) >> 3 | - (tmp_q & 0x20202020) >> 2 | - (tmp_q & 0x40404040) >> 1; - } - } - - br_aes_ct_ortho(q); - for (i = 0; i < 4; i++) { - br_enc32le(out + 4 * i, q[2 * i]); - br_enc32le(out + 4 * i + 16, q[2 * i + 1]); - } - - for (i = 0; i < 32; i++) { - out[i] ^= in[i]; - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/haraka.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/haraka.h deleted file mode 100644 index 737cb6065f..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/haraka.h +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef SPX_HARAKA_H -#define SPX_HARAKA_H - -#include "context.h" -#include "params.h" - -/* Tweak constants with seed */ -#define tweak_constants SPX_NAMESPACE(tweak_constants) -void tweak_constants(spx_ctx *ctx); - -/* Haraka Sponge */ -#define haraka_S_inc_init SPX_NAMESPACE(haraka_S_inc_init) -void haraka_S_inc_init(uint8_t *s_inc); -#define haraka_S_inc_absorb SPX_NAMESPACE(haraka_S_inc_absorb) -void haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, - const spx_ctx *ctx); -#define haraka_S_inc_finalize SPX_NAMESPACE(haraka_S_inc_finalize) -void haraka_S_inc_finalize(uint8_t *s_inc); -#define haraka_S_inc_squeeze SPX_NAMESPACE(haraka_S_inc_squeeze) -void haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, - const spx_ctx *ctx); -#define haraka_S SPX_NAMESPACE(haraka_S) -void haraka_S(unsigned char *out, unsigned long long outlen, - const unsigned char *in, unsigned long long inlen, - const spx_ctx *ctx); - -/* Applies the 512-bit Haraka permutation to in. */ -#define haraka512_perm SPX_NAMESPACE(haraka512_perm) -void haraka512_perm(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx); - -/* Implementation of Haraka-512 */ -#define haraka512 SPX_NAMESPACE(haraka512) -void haraka512(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx); - -/* Implementation of Haraka-256 */ -#define haraka256 SPX_NAMESPACE(haraka256) -void haraka256(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/haraka_offsets.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/haraka_offsets.h deleted file mode 100644 index 7c062272a0..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/haraka_offsets.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef HARAKA_OFFSETS_H_ -#define HARAKA_OFFSETS_H_ - -/* - * Offsets of various fields in the address structure when we use Haraka as - * the Sphincs+ hash function - */ - -#define SPX_OFFSET_LAYER 3 /* The byte used to specify the Merkle tree layer */ -#define SPX_OFFSET_TREE 8 /* The start of the 8 byte field used to specify the tree */ -#define SPX_OFFSET_TYPE 19 /* The byte used to specify the hash type (reason) */ -#define SPX_OFFSET_KP_ADDR2 22 /* The high byte used to specify the key pair (which one-time signature) */ -#define SPX_OFFSET_KP_ADDR1 23 /* The low byte used to specify the key pair */ -#define SPX_OFFSET_CHAIN_ADDR 27 /* The byte used to specify the chain address (which Winternitz chain) */ -#define SPX_OFFSET_HASH_ADDR 31 /* The byte used to specify the hash address (where in the Winternitz chain) */ -#define SPX_OFFSET_TREE_HGT 27 /* The byte used to specify the height of this node in the FORS or Merkle tree */ -#define SPX_OFFSET_TREE_INDEX 28 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ - -#define SPX_HARAKA 1 - -#endif /* HARAKA_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/hash.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/hash.h deleted file mode 100644 index f7c87d4c3c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/hash.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef SPX_HASH_H -#define SPX_HASH_H - -#include -#include - -#include "context.h" -#include "params.h" - -#define prf_addr SPX_NAMESPACE(prf_addr) -void prf_addr(unsigned char *out, const spx_ctx *ctx, - const uint32_t addr[8]); - -#define gen_message_random SPX_NAMESPACE(gen_message_random) -void gen_message_random(unsigned char *R, const unsigned char *sk_prf, - const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx); - -#define hash_message SPX_NAMESPACE(hash_message) -void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx); - - - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/hash_haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/hash_haraka.c deleted file mode 100644 index 750a67423b..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/hash_haraka.c +++ /dev/null @@ -1,81 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "utils.h" - -#include "haraka.h" -#include "hash.h" - -/* - * Computes PRF(key, addr), given a secret key of SPX_N bytes and an address - */ -void prf_addr(unsigned char *out, const spx_ctx *ctx, - const uint32_t addr[8]) { - /* Since SPX_N may be smaller than 32, we need temporary buffers. */ - unsigned char outbuf[32]; - unsigned char buf[64] = {0}; - - memcpy(buf, addr, SPX_ADDR_BYTES); - memcpy(buf + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); - - haraka512(outbuf, (const void *)buf, ctx); - memcpy(out, outbuf, SPX_N); -} - -/** - * Computes the message-dependent randomness R, using a secret seed and an - * optional randomization value as well as the message. - */ -void gen_message_random(unsigned char *R, const unsigned char *sk_prf, - const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx) { - uint8_t s_inc[65]; - - haraka_S_inc_init(s_inc); - haraka_S_inc_absorb(s_inc, sk_prf, SPX_N, ctx); - haraka_S_inc_absorb(s_inc, optrand, SPX_N, ctx); - haraka_S_inc_absorb(s_inc, m, mlen, ctx); - haraka_S_inc_finalize(s_inc); - haraka_S_inc_squeeze(R, SPX_N, s_inc, ctx); -} - -/** - * Computes the message hash using R, the public key, and the message. - * Outputs the message digest and the index of the leaf. The index is split in - * the tree index and the leaf index, for convenient copying to an address. - */ -void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx) { -#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) -#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) -#define SPX_LEAF_BITS SPX_TREE_HEIGHT -#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) -#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) - - unsigned char buf[SPX_DGST_BYTES]; - unsigned char *bufp = buf; - uint8_t s_inc[65]; - - haraka_S_inc_init(s_inc); - haraka_S_inc_absorb(s_inc, R, SPX_N, ctx); - haraka_S_inc_absorb(s_inc, pk + SPX_N, SPX_N, ctx); // Only absorb root part of pk - haraka_S_inc_absorb(s_inc, m, mlen, ctx); - haraka_S_inc_finalize(s_inc); - haraka_S_inc_squeeze(buf, SPX_DGST_BYTES, s_inc, ctx); - - memcpy(digest, bufp, SPX_FORS_MSG_BYTES); - bufp += SPX_FORS_MSG_BYTES; - - - *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); - *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); - bufp += SPX_TREE_BYTES; - - *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); - *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/merkle.c b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/merkle.c deleted file mode 100644 index 0c1479fd93..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/merkle.c +++ /dev/null @@ -1,59 +0,0 @@ -#include -#include - -#include "address.h" -#include "merkle.h" -#include "params.h" -#include "utils.h" -#include "utilsx1.h" -#include "wots.h" -#include "wotsx1.h" - -/* - * This generates a Merkle signature (WOTS signature followed by the Merkle - * authentication path). This is in this file because most of the complexity - * is involved with the WOTS signature; the Merkle authentication path logic - * is mostly hidden in treehashx4 - */ -void merkle_sign(uint8_t *sig, unsigned char *root, - const spx_ctx *ctx, - uint32_t wots_addr[8], uint32_t tree_addr[8], - uint32_t idx_leaf) { - unsigned char *auth_path = sig + SPX_WOTS_BYTES; - struct leaf_info_x1 info = { 0 }; - unsigned steps[ SPX_WOTS_LEN ]; - - info.wots_sig = sig; - chain_lengths(steps, root); - info.wots_steps = steps; - - set_type(&tree_addr[0], SPX_ADDR_TYPE_HASHTREE); - set_type(&info.pk_addr[0], SPX_ADDR_TYPE_WOTSPK); - copy_subtree_addr(&info.leaf_addr[0], wots_addr); - copy_subtree_addr(&info.pk_addr[0], wots_addr); - - info.wots_sign_leaf = idx_leaf; - - treehashx1(root, auth_path, ctx, - idx_leaf, 0, - SPX_TREE_HEIGHT, - wots_gen_leafx1, - tree_addr, &info); -} - -/* Compute root node of the top-most subtree. */ -void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { - /* We do not need the auth path in key generation, but it simplifies the - code to have just one treehash routine that computes both root and path - in one function. */ - unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; - uint32_t top_tree_addr[8] = {0}; - uint32_t wots_addr[8] = {0}; - - set_layer_addr(top_tree_addr, SPX_D - 1); - set_layer_addr(wots_addr, SPX_D - 1); - - merkle_sign(auth_path, root, ctx, - wots_addr, top_tree_addr, - (uint32_t)~0 /* ~0 means "don't bother generating an auth path */ ); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/merkle.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/merkle.h deleted file mode 100644 index 769cf2e970..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/merkle.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef MERKLE_H_ -#define MERKLE_H_ - -#include - -#include "context.h" -#include "params.h" - -/* Generate a Merkle signature (WOTS signature followed by the Merkle */ -/* authentication path) */ -#define merkle_sign SPX_NAMESPACE(merkle_sign) -void merkle_sign(uint8_t *sig, unsigned char *root, - const spx_ctx *ctx, - uint32_t wots_addr[8], uint32_t tree_addr[8], - uint32_t idx_leaf); - -/* Compute the root node of the top-most subtree. */ -#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) -void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); - -#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/nistapi.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/nistapi.h deleted file mode 100644 index 3cb71afad4..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/nistapi.h +++ /dev/null @@ -1,87 +0,0 @@ -#ifndef SPX_API_H -#define SPX_API_H - -#include -#include - -#include "params.h" - -#define CRYPTO_ALGNAME "SPHINCS+" - -#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES -#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES -#define CRYPTO_BYTES SPX_BYTES -#define CRYPTO_SEEDBYTES (3*SPX_N) - -/* - * Returns the length of a secret key, in bytes - */ -#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) -size_t crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) -size_t crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) -size_t crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) -size_t crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) -int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) -int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) -int crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) -int crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -#define crypto_sign SPX_NAMESPACE(crypto_sign) -int crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) -int crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/params.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/params.h deleted file mode 100644 index 97a78a6066..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/params.h +++ /dev/null @@ -1,56 +0,0 @@ -#ifndef SPX_PARAMS_H -#define SPX_PARAMS_H - -#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_##s - -/* Hash output length in bytes. */ -#define SPX_N 32 -/* Height of the hypertree. */ -#define SPX_FULL_HEIGHT 64 -/* Number of subtree layer. */ -#define SPX_D 8 -/* FORS tree dimensions. */ -#define SPX_FORS_HEIGHT 14 -#define SPX_FORS_TREES 22 -/* Winternitz parameter, */ -#define SPX_WOTS_W 16 - -/* The hash function is defined by linking a different hash.c file, as opposed - to setting a #define constant. */ - -/* For clarity */ -#define SPX_ADDR_BYTES 32 - -/* WOTS parameters. */ -#define SPX_WOTS_LOGW 4 - -#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) - -/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#define SPX_WOTS_LEN2 3 - -#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) -#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) -#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES - -/* Subtree size. */ -#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) - -//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT -// #error SPX_D should always divide SPX_FULL_HEIGHT -//#endif - -/* FORS parameters. */ -#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) -#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) -#define SPX_FORS_PK_BYTES SPX_N - -/* Resulting SPX sizes. */ -#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ - SPX_FULL_HEIGHT * SPX_N) -#define SPX_PK_BYTES (2 * SPX_N) -#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) - -#include "haraka_offsets.h" - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/sign.c b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/sign.c deleted file mode 100644 index 9d0c7d1b22..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/sign.c +++ /dev/null @@ -1,286 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "context.h" -#include "fors.h" -#include "hash.h" -#include "merkle.h" -#include "nistapi.h" -#include "params.h" -#include "randombytes.h" -#include "thash.h" -#include "utils.h" -#include "wots.h" - -/* - * Returns the length of a secret key, in bytes - */ -size_t crypto_sign_secretkeybytes(void) { - return CRYPTO_SECRETKEYBYTES; -} - -/* - * Returns the length of a public key, in bytes - */ -size_t crypto_sign_publickeybytes(void) { - return CRYPTO_PUBLICKEYBYTES; -} - -/* - * Returns the length of a signature, in bytes - */ -size_t crypto_sign_bytes(void) { - return CRYPTO_BYTES; -} - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t crypto_sign_seedbytes(void) { - return CRYPTO_SEEDBYTES; -} - -/* - * Generates an SPX key pair given a seed of length - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed) { - spx_ctx ctx; - - /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ - memcpy(sk, seed, CRYPTO_SEEDBYTES); - - memcpy(pk, sk + 2 * SPX_N, SPX_N); - - memcpy(ctx.pub_seed, pk, SPX_N); - memcpy(ctx.sk_seed, sk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - /* Compute root node of the top-most subtree. */ - merkle_gen_root(sk + 3 * SPX_N, &ctx); - - // cleanup - free_hash_function(&ctx); - - memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); - - return 0; -} - -/* - * Generates an SPX key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { - uint8_t seed[CRYPTO_SEEDBYTES]; - randombytes(seed, CRYPTO_SEEDBYTES); - crypto_sign_seed_keypair(pk, sk, seed); - - return 0; -} - -/** - * Returns an array containing a detached signature. - */ -int crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - spx_ctx ctx; - - const uint8_t *sk_prf = sk + SPX_N; - const uint8_t *pk = sk + 2 * SPX_N; - - uint8_t optrand[SPX_N]; - uint8_t mhash[SPX_FORS_MSG_BYTES]; - uint8_t root[SPX_N]; - uint32_t i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - - memcpy(ctx.sk_seed, sk, SPX_N); - memcpy(ctx.pub_seed, pk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - set_type(wots_addr, SPX_ADDR_TYPE_WOTS); - set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); - - /* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ - randombytes(optrand, SPX_N); - /* Compute the digest randomization value. */ - gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); - - /* Derive the message digest and leaf index from R, PK and M. */ - hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); - sig += SPX_N; - - set_tree_addr(wots_addr, tree); - set_keypair_addr(wots_addr, idx_leaf); - - /* Sign the message hash using FORS. */ - fors_sign(sig, root, mhash, &ctx, wots_addr); - sig += SPX_FORS_BYTES; - - for (i = 0; i < SPX_D; i++) { - set_layer_addr(tree_addr, i); - set_tree_addr(tree_addr, tree); - - copy_subtree_addr(wots_addr, tree_addr); - set_keypair_addr(wots_addr, idx_leaf); - - merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); - sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); - tree = tree >> SPX_TREE_HEIGHT; - } - - free_hash_function(&ctx); - - *siglen = SPX_BYTES; - - return 0; -} - -/** - * Verifies a detached signature and message under a given public key. - */ -int crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk) { - spx_ctx ctx; - const uint8_t *pub_root = pk + SPX_N; - uint8_t mhash[SPX_FORS_MSG_BYTES]; - uint8_t wots_pk[SPX_WOTS_BYTES]; - uint8_t root[SPX_N]; - uint8_t leaf[SPX_N]; - unsigned int i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - if (siglen != SPX_BYTES) { - return -1; - } - - memcpy(ctx.pub_seed, pk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - set_type(wots_addr, SPX_ADDR_TYPE_WOTS); - set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); - set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); - - /* Derive the message digest and leaf index from R || PK || M. */ - /* The additional SPX_N is a result of the hash domain separator. */ - hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); - sig += SPX_N; - - /* Layer correctly defaults to 0, so no need to set_layer_addr */ - set_tree_addr(wots_addr, tree); - set_keypair_addr(wots_addr, idx_leaf); - - fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); - sig += SPX_FORS_BYTES; - - /* For each subtree.. */ - for (i = 0; i < SPX_D; i++) { - set_layer_addr(tree_addr, i); - set_tree_addr(tree_addr, tree); - - copy_subtree_addr(wots_addr, tree_addr); - set_keypair_addr(wots_addr, idx_leaf); - - copy_keypair_addr(wots_pk_addr, wots_addr); - - /* The WOTS public key is only correct if the signature was correct. */ - /* Initially, root is the FORS pk, but on subsequent iterations it is - the root of the subtree below the currently processed subtree. */ - wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); - sig += SPX_WOTS_BYTES; - - /* Compute the leaf node using the WOTS public key. */ - thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); - - /* Compute the root node of this subtree. */ - compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, - &ctx, tree_addr); - sig += SPX_TREE_HEIGHT * SPX_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); - tree = tree >> SPX_TREE_HEIGHT; - } - - // cleanup - free_hash_function(&ctx); - - /* Check if the root node equals the root node in the public key. */ - if (memcmp(root, pub_root, SPX_N) != 0) { - return -1; - } - - return 0; -} - - -/** - * Returns an array containing the signature followed by the message. - */ -int crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk) { - size_t siglen; - - crypto_sign_signature(sm, &siglen, m, mlen, sk); - - memmove(sm + SPX_BYTES, m, mlen); - *smlen = siglen + mlen; - - return 0; -} - -/** - * Verifies a given signature-message pair under a given public key. - */ -int crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk) { - /* The API caller does not necessarily know what size a signature should be - but SPHINCS+ signatures are always exactly SPX_BYTES. */ - if (smlen < SPX_BYTES) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - *mlen = smlen - SPX_BYTES; - - if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - /* If verification was successful, move the message to the right place. */ - memmove(m, sm + SPX_BYTES, *mlen); - - return 0; -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/thash.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/thash.h deleted file mode 100644 index 8687ccfb4d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/thash.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef SPX_THASH_H -#define SPX_THASH_H - -#include "context.h" -#include "params.h" - -#include - -#define thash SPX_NAMESPACE(thash) -void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/thash_haraka_robust.c b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/thash_haraka_robust.c deleted file mode 100644 index 109502cbc2..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/thash_haraka_robust.c +++ /dev/null @@ -1,45 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "thash.h" -#include "utils.h" - -#include "haraka.h" - -/** - * Takes an array of inblocks concatenated arrays of SPX_N bytes. - */ -void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]) { - PQCLEAN_VLA(uint8_t, buf, SPX_ADDR_BYTES + inblocks * SPX_N); - PQCLEAN_VLA(uint8_t, bitmask, inblocks * SPX_N); - unsigned char outbuf[32]; - unsigned char buf_tmp[64]; - unsigned int i; - - if (inblocks == 1) { - /* F function */ - /* Since SPX_N may be smaller than 32, we need a temporary buffer. */ - memset(buf_tmp, 0, 64); - memcpy(buf_tmp, addr, 32); - - haraka256(outbuf, buf_tmp, ctx); - for (i = 0; i < inblocks * SPX_N; i++) { - buf_tmp[SPX_ADDR_BYTES + i] = in[i] ^ outbuf[i]; - } - haraka512(outbuf, buf_tmp, ctx); - memcpy(out, outbuf, SPX_N); - } else { - /* All other tweakable hashes*/ - memcpy(buf, addr, 32); - haraka_S(bitmask, inblocks * SPX_N, buf, SPX_ADDR_BYTES, ctx); - - for (i = 0; i < inblocks * SPX_N; i++) { - buf[SPX_ADDR_BYTES + i] = in[i] ^ bitmask[i]; - } - - haraka_S(out, SPX_N, buf, SPX_ADDR_BYTES + inblocks * SPX_N, ctx); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/utils.c b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/utils.c deleted file mode 100644 index 177b541fb9..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/utils.c +++ /dev/null @@ -1,148 +0,0 @@ -#include - -#include "utils.h" - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "thash.h" - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void ull_to_bytes(unsigned char *out, unsigned int outlen, - unsigned long long in) { - int i; - - /* Iterate over out in decreasing order, for big-endianness. */ - for (i = (signed int)outlen - 1; i >= 0; i--) { - out[i] = in & 0xff; - in = in >> 8; - } -} - -void u32_to_bytes(unsigned char *out, uint32_t in) { - out[0] = (unsigned char)(in >> 24); - out[1] = (unsigned char)(in >> 16); - out[2] = (unsigned char)(in >> 8); - out[3] = (unsigned char)in; -} - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { - unsigned long long retval = 0; - unsigned int i; - - for (i = 0; i < inlen; i++) { - retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); - } - return retval; -} - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void compute_root(unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const spx_ctx *ctx, uint32_t addr[8]) { - uint32_t i; - unsigned char buffer[2 * SPX_N]; - - /* If leaf_idx is odd (last bit = 1), current path element is a right child - and auth_path has to go left. Otherwise it is the other way around. */ - if (leaf_idx & 1) { - memcpy(buffer + SPX_N, leaf, SPX_N); - memcpy(buffer, auth_path, SPX_N); - } else { - memcpy(buffer, leaf, SPX_N); - memcpy(buffer + SPX_N, auth_path, SPX_N); - } - auth_path += SPX_N; - - for (i = 0; i < tree_height - 1; i++) { - leaf_idx >>= 1; - idx_offset >>= 1; - /* Set the address of the node we're creating. */ - set_tree_height(addr, i + 1); - set_tree_index(addr, leaf_idx + idx_offset); - - /* Pick the right or left neighbor, depending on parity of the node. */ - if (leaf_idx & 1) { - thash(buffer + SPX_N, buffer, 2, ctx, addr); - memcpy(buffer, auth_path, SPX_N); - } else { - thash(buffer, buffer, 2, ctx, addr); - memcpy(buffer + SPX_N, auth_path, SPX_N); - } - auth_path += SPX_N; - } - - /* The last iteration is exceptional; we do not copy an auth_path node. */ - leaf_idx >>= 1; - idx_offset >>= 1; - set_tree_height(addr, tree_height); - set_tree_index(addr, leaf_idx + idx_offset); - thash(root, buffer, 2, ctx, addr); -} - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const spx_ctx * /* ctx */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), - uint32_t tree_addr[8]) { - PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); - PQCLEAN_VLA(unsigned int, heights, tree_height + 1); - unsigned int offset = 0; - uint32_t idx; - uint32_t tree_idx; - - for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { - /* Add the next leaf node to the stack. */ - gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); - offset++; - heights[offset - 1] = 0; - - /* If this is a node we need for the auth path.. */ - if ((leaf_idx ^ 0x1) == idx) { - memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); - } - - /* While the top-most nodes are of equal height.. */ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { - /* Compute index of the new node, in the next layer. */ - tree_idx = (idx >> (heights[offset - 1] + 1)); - - /* Set the address of the node we're creating. */ - set_tree_height(tree_addr, heights[offset - 1] + 1); - set_tree_index(tree_addr, - tree_idx + (idx_offset >> (heights[offset - 1] + 1))); - /* Hash the top-most nodes from the stack together. */ - thash(stack + (offset - 2)*SPX_N, - stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); - offset--; - /* Note that the top-most node is now one layer higher. */ - heights[offset - 1]++; - - /* If this is a node we need for the auth path.. */ - if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_path + heights[offset - 1]*SPX_N, - stack + (offset - 1)*SPX_N, SPX_N); - } - } - } - memcpy(root, stack, SPX_N); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/utils.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/utils.h deleted file mode 100644 index 64f5d5a53a..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/utils.h +++ /dev/null @@ -1,58 +0,0 @@ -#ifndef SPX_UTILS_H -#define SPX_UTILS_H - -#include - -#include "compat.h" -#include "context.h" -#include "params.h" - - -/* To support MSVC use alloca() instead of VLAs. See #20. */ - - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) -void ull_to_bytes(unsigned char *out, unsigned int outlen, - unsigned long long in); -#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) -void u32_to_bytes(unsigned char *out, uint32_t in); - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) -unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -#define compute_root SPX_NAMESPACE(compute_root) -void compute_root(unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const spx_ctx *ctx, uint32_t addr[8]); - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -#define treehash SPX_NAMESPACE(treehash) -void treehash(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const spx_ctx *ctx /* ctx */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), - uint32_t tree_addr[8]); - - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/utilsx1.c b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/utilsx1.c deleted file mode 100644 index fccb69b35d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/utilsx1.c +++ /dev/null @@ -1,100 +0,0 @@ -#include - -#include "utilsx1.h" - -#include "address.h" -#include "params.h" -#include "thash.h" -#include "utils.h" - -/* - * Generate the entire Merkle tree, computing the authentication path for - * leaf_idx, and the resulting root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) - * - * This expects tree_addr to be initialized to the addr structures for the - * Merkle tree nodes - * - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - * - * This works by using the standard Merkle tree building algorithm, - */ -void treehashx1(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, - uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* Where to write the leaves */, - const spx_ctx * /* ctx */, - uint32_t idx, void *info), - uint32_t tree_addr[8], - void *info) { - /* This is where we keep the intermediate nodes */ - PQCLEAN_VLA(uint8_t, stack, tree_height * SPX_N); - - uint32_t idx; - uint32_t max_idx = (uint32_t)((1 << tree_height) - 1); - for (idx = 0;; idx++) { - unsigned char current[2 * SPX_N]; /* Current logical node is at */ - /* index[SPX_N]. We do this to minimize the number of copies */ - /* needed during a thash */ - gen_leaf( ¤t[SPX_N], ctx, idx + idx_offset, - info ); - - /* Now combine the freshly generated right node with previously */ - /* generated left ones */ - uint32_t internal_idx_offset = idx_offset; - uint32_t internal_idx = idx; - uint32_t internal_leaf = leaf_idx; - uint32_t h; /* The height we are in the Merkle tree */ - for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { - - /* Check if we hit the top of the tree */ - if (h == tree_height) { - /* We hit the root; return it */ - memcpy( root, ¤t[SPX_N], SPX_N ); - return; - } - - /* - * Check if the node we have is a part of the - * authentication path; if it is, write it out - */ - if ((internal_idx ^ internal_leaf) == 0x01) { - memcpy( &auth_path[ h * SPX_N ], - ¤t[SPX_N], - SPX_N ); - } - - /* - * Check if we're at a left child; if so, stop going up the stack - * Exception: if we've reached the end of the tree, keep on going - * (so we combine the last 4 nodes into the one root node in two - * more iterations) - */ - if ((internal_idx & 1) == 0 && idx < max_idx) { - break; - } - - /* Ok, we're at a right node */ - /* Now combine the left and right logical nodes together */ - - /* Set the address of the node we're creating. */ - internal_idx_offset >>= 1; - set_tree_height(tree_addr, h + 1); - set_tree_index(tree_addr, internal_idx / 2 + internal_idx_offset ); - - unsigned char *left = &stack[h * SPX_N]; - memcpy( ¤t[0], left, SPX_N ); - thash( ¤t[1 * SPX_N], - ¤t[0 * SPX_N], - 2, ctx, tree_addr); - } - - /* We've hit a left child; save the current for when we get the */ - /* corresponding right right */ - memcpy( &stack[h * SPX_N], ¤t[SPX_N], SPX_N); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/utilsx1.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/utilsx1.h deleted file mode 100644 index e911d17d53..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/utilsx1.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef SPX_UTILSX4_H -#define SPX_UTILSX4_H - -#include - -#include "context.h" -#include "params.h" - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -#define treehashx1 SPX_NAMESPACE(treehashx1) -void treehashx1(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* Where to write the leaf */, - const spx_ctx * /* ctx */, - uint32_t addr_idx, void *info), - uint32_t tree_addrx4[8], void *info); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/wots.c b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/wots.c deleted file mode 100644 index 249717aaa8..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/wots.c +++ /dev/null @@ -1,108 +0,0 @@ -#include -#include - -#include "wots.h" -#include "wotsx1.h" - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "thash.h" -#include "utils.h" -#include "utilsx1.h" - -// TODO clarify address expectations, and make them more uniform. -// TODO i.e. do we expect types to be set already? -// TODO and do we expect modifications or copies? - -/** - * Computes the chaining function. - * out and in have to be n-byte arrays. - * - * Interprets in as start-th value of the chain. - * addr has to contain the address of the chain. - */ -static void gen_chain(unsigned char *out, const unsigned char *in, - unsigned int start, unsigned int steps, - const spx_ctx *ctx, uint32_t addr[8]) { - uint32_t i; - - /* Initialize out with the value at position 'start'. */ - memcpy(out, in, SPX_N); - - /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < SPX_WOTS_W; i++) { - set_hash_addr(addr, i); - thash(out, out, 1, ctx, addr); - } -} - -/** - * base_w algorithm as described in draft. - * Interprets an array of bytes as integers in base w. - * This only works when log_w is a divisor of 8. - */ -static void base_w(unsigned int *output, const int out_len, - const unsigned char *input) { - int in = 0; - int out = 0; - unsigned char total = 0; - int bits = 0; - int consumed; - - for (consumed = 0; consumed < out_len; consumed++) { - if (bits == 0) { - total = input[in]; - in++; - bits += 8; - } - bits -= SPX_WOTS_LOGW; - output[out] = (total >> bits) & (SPX_WOTS_W - 1); - out++; - } -} - -/* Computes the WOTS+ checksum over a message (in base_w). */ -static void wots_checksum(unsigned int *csum_base_w, - const unsigned int *msg_base_w) { - unsigned int csum = 0; - unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; - unsigned int i; - - /* Compute checksum. */ - for (i = 0; i < SPX_WOTS_LEN1; i++) { - csum += SPX_WOTS_W - 1 - msg_base_w[i]; - } - - /* Convert checksum to base_w. */ - /* Make sure expected empty zero bits are the least significant bits. */ - csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); - ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); - base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); -} - -/* Takes a message and derives the matching chain lengths. */ -void chain_lengths(unsigned int *lengths, const unsigned char *msg) { - base_w(lengths, SPX_WOTS_LEN1, msg); - wots_checksum(lengths + SPX_WOTS_LEN1, lengths); -} - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const spx_ctx *ctx, uint32_t addr[8]) { - unsigned int lengths[SPX_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < SPX_WOTS_LEN; i++) { - set_chain_addr(addr, i); - gen_chain(pk + i * SPX_N, sig + i * SPX_N, - lengths[i], SPX_WOTS_W - 1 - lengths[i], ctx, addr); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/wots.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/wots.h deleted file mode 100644 index 4e7692eeef..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/wots.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef SPX_WOTS_H -#define SPX_WOTS_H - -#include - -#include "context.h" -#include "params.h" - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) -void wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const spx_ctx *ctx, uint32_t addr[8]); - -/* - * Compute the chain lengths needed for a given message hash - */ -#define chain_lengths SPX_NAMESPACE(chain_lengths) -void chain_lengths(unsigned int *lengths, const unsigned char *msg); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/wotsx1.c b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/wotsx1.c deleted file mode 100644 index 3adec78dfb..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/wotsx1.c +++ /dev/null @@ -1,76 +0,0 @@ -#include -#include - -#include "wots.h" -#include "wotsx1.h" - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "thash.h" -#include "utils.h" - -/* - * This generates a WOTS public key - * It also generates the WOTS signature if leaf_info indicates - * that we're signing with this WOTS key - */ -void wots_gen_leafx1(unsigned char *dest, - const spx_ctx *ctx, - uint32_t leaf_idx, void *v_info) { - struct leaf_info_x1 *info = v_info; - uint32_t *leaf_addr = info->leaf_addr; - uint32_t *pk_addr = info->pk_addr; - unsigned int i, k; - unsigned char pk_buffer[ SPX_WOTS_BYTES ]; - unsigned char *buffer; - uint32_t wots_k_mask; - - if (leaf_idx == info->wots_sign_leaf) { - /* We're traversing the leaf that's signing; generate the WOTS */ - /* signature */ - wots_k_mask = 0; - } else { - /* Nope, we're just generating pk's; turn off the signature logic */ - wots_k_mask = (uint32_t)~0; - } - - set_keypair_addr( leaf_addr, leaf_idx ); - set_keypair_addr( pk_addr, leaf_idx ); - - for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { - uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k to */ - /* the step if we're generating a signature, ~0 if we're not */ - - /* Start with the secret seed */ - set_chain_addr(leaf_addr, i); - set_hash_addr(leaf_addr, 0); - set_type(leaf_addr, SPX_ADDR_TYPE_WOTSPRF); - - prf_addr(buffer, ctx, leaf_addr); - - set_type(leaf_addr, SPX_ADDR_TYPE_WOTS); - - /* Iterate down the WOTS chain */ - for (k = 0;; k++) { - /* Check if this is the value that needs to be saved as a */ - /* part of the WOTS signature */ - if (k == wots_k) { - memcpy( info->wots_sig + i * SPX_N, buffer, SPX_N ); - } - - /* Check if we hit the top of the chain */ - if (k == SPX_WOTS_W - 1) { - break; - } - - /* Iterate one step on the chain */ - set_hash_addr(leaf_addr, k); - - thash(buffer, buffer, 1, ctx, leaf_addr); - } - } - - /* Do the final thash to generate the public keys */ - thash(dest, pk_buffer, SPX_WOTS_LEN, ctx, pk_addr); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/wotsx1.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/wotsx1.h deleted file mode 100644 index e617929f96..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-robust_clean/wotsx1.h +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef WOTSX1_H_ -#define WOTSX1_H_ - -#include - -#include "context.h" -#include "params.h" - -/* - * This is here to provide an interface to the internal wots_gen_leafx1 - * routine. While this routine is not referenced in the package outside of - * wots.c, it is called from the stand-alone benchmark code to characterize - * the performance - */ -struct leaf_info_x1 { - unsigned char *wots_sig; - uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ - uint32_t *wots_steps; - uint32_t leaf_addr[8]; - uint32_t pk_addr[8]; -}; - -/* Macro to set the leaf_info to something 'benign', that is, it would */ -/* run with the same time as it does during the real signing process */ -/* Used only by the benchmark code */ -#define INITIALIZE_LEAF_INFO_X1(info, addr, step_buffer) { \ - (info).wots_sig = 0; \ - (info).wots_sign_leaf = ~0; \ - (info).wots_steps = step_buffer; \ - memcpy( &(info).leaf_addr[0], (addr), 32 ); \ - memcpy( &(info).pk_addr[0], (addr), 32 ); \ - } - -#define wots_gen_leafx1 SPX_NAMESPACE(wots_gen_leafx1) -void wots_gen_leafx1(unsigned char *dest, - const spx_ctx *ctx, - uint32_t leaf_idx, void *v_info); - -#endif /* WOTSX1_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/LICENSE b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/LICENSE deleted file mode 100644 index 670154e353..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/LICENSE +++ /dev/null @@ -1,116 +0,0 @@ -CC0 1.0 Universal - -Statement of Purpose - -The laws of most jurisdictions throughout the world automatically confer -exclusive Copyright and Related Rights (defined below) upon the creator and -subsequent owner(s) (each and all, an "owner") of an original work of -authorship and/or a database (each, a "Work"). - -Certain owners wish to permanently relinquish those rights to a Work for the -purpose of contributing to a commons of creative, cultural and scientific -works ("Commons") that the public can reliably and without fear of later -claims of infringement build upon, modify, incorporate in other works, reuse -and redistribute as freely as possible in any form whatsoever and for any -purposes, including without limitation commercial purposes. These owners may -contribute to the Commons to promote the ideal of a free culture and the -further production of creative, cultural and scientific works, or to gain -reputation or greater distribution for their Work in part through the use and -efforts of others. - -For these and/or other purposes and motivations, and without any expectation -of additional consideration or compensation, the person associating CC0 with a -Work (the "Affirmer"), to the extent that he or she is an owner of Copyright -and Related Rights in the Work, voluntarily elects to apply CC0 to the Work -and publicly distribute the Work under its terms, with knowledge of his or her -Copyright and Related Rights in the Work and the meaning and intended legal -effect of CC0 on those rights. - -1. Copyright and Related Rights. A Work made available under CC0 may be -protected by copyright and related or neighboring rights ("Copyright and -Related Rights"). Copyright and Related Rights include, but are not limited -to, the following: - - i. the right to reproduce, adapt, distribute, perform, display, communicate, - and translate a Work; - - ii. moral rights retained by the original author(s) and/or performer(s); - - iii. publicity and privacy rights pertaining to a person's image or likeness - depicted in a Work; - - iv. rights protecting against unfair competition in regards to a Work, - subject to the limitations in paragraph 4(a), below; - - v. rights protecting the extraction, dissemination, use and reuse of data in - a Work; - - vi. database rights (such as those arising under Directive 96/9/EC of the - European Parliament and of the Council of 11 March 1996 on the legal - protection of databases, and under any national implementation thereof, - including any amended or successor version of such directive); and - - vii. other similar, equivalent or corresponding rights throughout the world - based on applicable law or treaty, and any national implementations thereof. - -2. Waiver. To the greatest extent permitted by, but not in contravention of, -applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and -unconditionally waives, abandons, and surrenders all of Affirmer's Copyright -and Related Rights and associated claims and causes of action, whether now -known or unknown (including existing as well as future claims and causes of -action), in the Work (i) in all territories worldwide, (ii) for the maximum -duration provided by applicable law or treaty (including future time -extensions), (iii) in any current or future medium and for any number of -copies, and (iv) for any purpose whatsoever, including without limitation -commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes -the Waiver for the benefit of each member of the public at large and to the -detriment of Affirmer's heirs and successors, fully intending that such Waiver -shall not be subject to revocation, rescission, cancellation, termination, or -any other legal or equitable action to disrupt the quiet enjoyment of the Work -by the public as contemplated by Affirmer's express Statement of Purpose. - -3. Public License Fallback. Should any part of the Waiver for any reason be -judged legally invalid or ineffective under applicable law, then the Waiver -shall be preserved to the maximum extent permitted taking into account -Affirmer's express Statement of Purpose. In addition, to the extent the Waiver -is so judged Affirmer hereby grants to each affected person a royalty-free, -non transferable, non sublicensable, non exclusive, irrevocable and -unconditional license to exercise Affirmer's Copyright and Related Rights in -the Work (i) in all territories worldwide, (ii) for the maximum duration -provided by applicable law or treaty (including future time extensions), (iii) -in any current or future medium and for any number of copies, and (iv) for any -purpose whatsoever, including without limitation commercial, advertising or -promotional purposes (the "License"). The License shall be deemed effective as -of the date CC0 was applied by Affirmer to the Work. Should any part of the -License for any reason be judged legally invalid or ineffective under -applicable law, such partial invalidity or ineffectiveness shall not -invalidate the remainder of the License, and in such case Affirmer hereby -affirms that he or she will not (i) exercise any of his or her remaining -Copyright and Related Rights in the Work or (ii) assert any associated claims -and causes of action with respect to the Work, in either case contrary to -Affirmer's express Statement of Purpose. - -4. Limitations and Disclaimers. - - a. No trademark or patent rights held by Affirmer are waived, abandoned, - surrendered, licensed or otherwise affected by this document. - - b. Affirmer offers the Work as-is and makes no representations or warranties - of any kind concerning the Work, express, implied, statutory or otherwise, - including without limitation warranties of title, merchantability, fitness - for a particular purpose, non infringement, or the absence of latent or - other defects, accuracy, or the present or absence of errors, whether or not - discoverable, all to the greatest extent permissible under applicable law. - - c. Affirmer disclaims responsibility for clearing rights of other persons - that may apply to the Work or any use thereof, including without limitation - any person's Copyright and Related Rights in the Work. Further, Affirmer - disclaims responsibility for obtaining any necessary consents, permissions - or other rights required for any use of the Work. - - d. Affirmer understands and acknowledges that Creative Commons is not a - party to this document and has no duty or obligation with respect to this - CC0 or use of the Work. - -For more information, please see - diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/address.c b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/address.c deleted file mode 100644 index b956e9cb29..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/address.c +++ /dev/null @@ -1,91 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "utils.h" - -/* - * Specify which level of Merkle tree (the "layer") we're working on - */ -void set_layer_addr(uint32_t addr[8], uint32_t layer) { - ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; -} - -/* - * Specify which Merkle tree within the level (the "tree address") we're working on - */ -void set_tree_addr(uint32_t addr[8], uint64_t tree) { - ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); -} - -/* - * Specify the reason we'll use this address structure for, that is, what - * hash will we compute with it. This is used so that unrelated types of - * hashes don't accidentally get the same address structure. The type will be - * one of the SPX_ADDR_TYPE constants - */ -void set_type(uint32_t addr[8], uint32_t type) { - ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; -} - -/* - * Copy the layer and tree fields of the address structure. This is used - * when we're doing multiple types of hashes within the same Merkle tree - */ -void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { - memcpy( out, in, SPX_OFFSET_TREE + 8 ); -} - -/* These functions are used for OTS addresses. */ - -/* - * Specify which Merkle leaf we're working on; that is, which OTS keypair - * we're talking about. - */ -void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { - ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; -} - -/* - * Copy the layer, tree and keypair fields of the address structure. This is - * used when we're doing multiple things within the same OTS keypair - */ -void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { - memcpy( out, in, SPX_OFFSET_TREE + 8 ); - ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; -} - -/* - * Specify which Merkle chain within the OTS we're working with - * (the chain address) - */ -void set_chain_addr(uint32_t addr[8], uint32_t chain) { - ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; -} - -/* - * Specify where in the Merkle chain we are -* (the hash address) - */ -void set_hash_addr(uint32_t addr[8], uint32_t hash) { - ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; -} - -/* These functions are used for all hash tree addresses (including FORS). */ - -/* - * Specify the height of the node in the Merkle/FORS tree we are in - * (the tree height) - */ -void set_tree_height(uint32_t addr[8], uint32_t tree_height) { - ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; -} - -/* - * Specify the distance from the left edge of the node in the Merkle/FORS tree - * (the tree index) - */ -void set_tree_index(uint32_t addr[8], uint32_t tree_index) { - u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/address.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/address.h deleted file mode 100644 index 24a84eb40c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/address.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef SPX_ADDRESS_H -#define SPX_ADDRESS_H - -#include - -#include "params.h" - -/* The hash types that are passed to set_type */ -#define SPX_ADDR_TYPE_WOTS 0 -#define SPX_ADDR_TYPE_WOTSPK 1 -#define SPX_ADDR_TYPE_HASHTREE 2 -#define SPX_ADDR_TYPE_FORSTREE 3 -#define SPX_ADDR_TYPE_FORSPK 4 -#define SPX_ADDR_TYPE_WOTSPRF 5 -#define SPX_ADDR_TYPE_FORSPRF 6 - -#define set_layer_addr SPX_NAMESPACE(set_layer_addr) -void set_layer_addr(uint32_t addr[8], uint32_t layer); - -#define set_tree_addr SPX_NAMESPACE(set_tree_addr) -void set_tree_addr(uint32_t addr[8], uint64_t tree); - -#define set_type SPX_NAMESPACE(set_type) -void set_type(uint32_t addr[8], uint32_t type); - -/* Copies the layer and tree part of one address into the other */ -#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) -void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for WOTS and FORS addresses. */ - -#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) -void set_keypair_addr(uint32_t addr[8], uint32_t keypair); - -#define set_chain_addr SPX_NAMESPACE(set_chain_addr) -void set_chain_addr(uint32_t addr[8], uint32_t chain); - -#define set_hash_addr SPX_NAMESPACE(set_hash_addr) -void set_hash_addr(uint32_t addr[8], uint32_t hash); - -#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) -void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for all hash tree addresses (including FORS). */ - -#define set_tree_height SPX_NAMESPACE(set_tree_height) -void set_tree_height(uint32_t addr[8], uint32_t tree_height); - -#define set_tree_index SPX_NAMESPACE(set_tree_index) -void set_tree_index(uint32_t addr[8], uint32_t tree_index); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/api.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/api.h deleted file mode 100644 index 099750a11c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/api.h +++ /dev/null @@ -1,77 +0,0 @@ -#ifndef PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_API_H -#define PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_API_H - -#include -#include - -#define PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_CRYPTO_ALGNAME "SPHINCS+-haraka-256s-simple" - -#define PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_CRYPTO_SECRETKEYBYTES 128 -#define PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_CRYPTO_PUBLICKEYBYTES 64 -#define PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_CRYPTO_BYTES 29792 - -#define PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_CRYPTO_SEEDBYTES 96 - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, - const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk); -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/context.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/context.h deleted file mode 100644 index f03446b9cb..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/context.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef SPX_CONTEXT_H -#define SPX_CONTEXT_H - -#include - -#include "immintrin.h" -#include "params.h" - -typedef struct { - uint8_t pub_seed[SPX_N]; - uint8_t sk_seed[SPX_N]; - - __m128i rc[40]; -} spx_ctx; - -#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) -void initialize_hash_function(spx_ctx *ctx); - -#define free_hash_function SPX_NAMESPACE(free_hash_function) -void free_hash_function(spx_ctx *ctx); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/context_haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/context_haraka.c deleted file mode 100644 index f1cd7e3664..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/context_haraka.c +++ /dev/null @@ -1,11 +0,0 @@ -#include "context.h" -#include "haraka.h" - -void initialize_hash_function(spx_ctx *ctx) { - tweak_constants(ctx); -} - -// we don't support heap-based haraka right now -void free_hash_function(spx_ctx *ctx) { - (void)ctx; // suppress unused variable warnings -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/fors.c b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/fors.c deleted file mode 100644 index f1b0639cfc..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/fors.c +++ /dev/null @@ -1,202 +0,0 @@ -#include -#include -#include - -#include "fors.h" - -#include "address.h" -#include "hash.h" -#include "hashx4.h" -#include "thash.h" -#include "thashx4.h" -#include "utils.h" -#include "utilsx4.h" - -static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, - uint32_t fors_leaf_addr[8]) { - prf_addr(sk, ctx, fors_leaf_addr); -} - -static void fors_gen_skx4(unsigned char *sk0, - unsigned char *sk1, - unsigned char *sk2, - unsigned char *sk3, const spx_ctx *ctx, - uint32_t fors_leaf_addrx4[4 * 8]) { - prf_addrx4(sk0, sk1, sk2, sk3, - ctx, fors_leaf_addrx4); -} - -static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, - const spx_ctx *ctx, - uint32_t fors_leaf_addr[8]) { - thash(leaf, sk, 1, ctx, fors_leaf_addr); -} - -static void fors_sk_to_leafx4(unsigned char *leaf0, - unsigned char *leaf1, - unsigned char *leaf2, - unsigned char *leaf3, - const unsigned char *sk0, - const unsigned char *sk1, - const unsigned char *sk2, - const unsigned char *sk3, - const spx_ctx *ctx, - uint32_t fors_leaf_addrx4[4 * 8]) { - thashx4(leaf0, leaf1, leaf2, leaf3, - sk0, sk1, sk2, sk3, - 1, ctx, fors_leaf_addrx4); -} - -struct fors_gen_leaf_info { - uint32_t leaf_addrx[4 * 8]; -}; - -static void fors_gen_leafx4(unsigned char *leaf, - const spx_ctx *ctx, - uint32_t addr_idx, void *info) { - struct fors_gen_leaf_info *fors_info = info; - uint32_t *fors_leaf_addrx4 = fors_info->leaf_addrx; - unsigned int j; - - /* Only set the parts that the caller doesn't set */ - for (j = 0; j < 4; j++) { - set_tree_index(fors_leaf_addrx4 + j * 8, addr_idx + j); - set_type(fors_leaf_addrx4 + j * 8, SPX_ADDR_TYPE_FORSPRF); - } - - fors_gen_skx4(leaf + 0 * SPX_N, - leaf + 1 * SPX_N, - leaf + 2 * SPX_N, - leaf + 3 * SPX_N, - ctx, fors_leaf_addrx4); - - for (j = 0; j < 4; j++) { - set_type(fors_leaf_addrx4 + j * 8, SPX_ADDR_TYPE_FORSTREE); - } - - fors_sk_to_leafx4(leaf + 0 * SPX_N, - leaf + 1 * SPX_N, - leaf + 2 * SPX_N, - leaf + 3 * SPX_N, - leaf + 0 * SPX_N, - leaf + 1 * SPX_N, - leaf + 2 * SPX_N, - leaf + 3 * SPX_N, - ctx, fors_leaf_addrx4); -} - -/** - * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - * Assumes indices has space for SPX_FORS_TREES integers. - */ -static void message_to_indices(uint32_t *indices, const unsigned char *m) { - unsigned int i, j; - unsigned int offset = 0; - - for (i = 0; i < SPX_FORS_TREES; i++) { - indices[i] = 0; - for (j = 0; j < SPX_FORS_HEIGHT; j++) { - indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); - offset++; - } - } -} - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -void fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]) { - uint32_t indices[SPX_FORS_TREES]; - unsigned char roots[SPX_FORS_TREES * SPX_N]; - uint32_t fors_tree_addr[4 * 8] = {0}; - struct fors_gen_leaf_info fors_info = {0}; - uint32_t *fors_leaf_addr = fors_info.leaf_addrx; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - for (i = 0; i < 4; i++) { - copy_keypair_addr(fors_tree_addr + 8 * i, fors_addr); - set_type(fors_tree_addr + 8 * i, SPX_ADDR_TYPE_FORSTREE); - copy_keypair_addr(fors_leaf_addr + 8 * i, fors_addr); - } - copy_keypair_addr(fors_pk_addr, fors_addr); - set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < SPX_FORS_TREES; i++) { - idx_offset = i * (1 << SPX_FORS_HEIGHT); - - set_tree_height(fors_tree_addr, 0); - set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Include the secret key part that produces the selected leaf node. */ - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); - fors_gen_sk(sig, ctx, fors_tree_addr); - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); - sig += SPX_N; - - /* Compute the authentication path for this leaf node. */ - treehashx4(roots + i * SPX_N, sig, ctx, - indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx4, - fors_tree_addr, &fors_info); - - sig += SPX_N * SPX_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); -} - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -void fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]) { - uint32_t indices[SPX_FORS_TREES]; - unsigned char roots[SPX_FORS_TREES * SPX_N]; - unsigned char leaf[SPX_N]; - uint32_t fors_tree_addr[8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - copy_keypair_addr(fors_tree_addr, fors_addr); - copy_keypair_addr(fors_pk_addr, fors_addr); - - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); - set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < SPX_FORS_TREES; i++) { - idx_offset = i * (1 << SPX_FORS_HEIGHT); - - set_tree_height(fors_tree_addr, 0); - set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Derive the leaf from the included secret key part. */ - fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); - sig += SPX_N; - - /* Derive the corresponding root node of this tree. */ - compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, - sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); - sig += SPX_N * SPX_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/fors.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/fors.h deleted file mode 100644 index 509140a178..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/fors.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef SPX_FORS_H -#define SPX_FORS_H - -#include - -#include "context.h" -#include "params.h" - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -#define fors_sign SPX_NAMESPACE(fors_sign) -void fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]); - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) -void fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/haraka.c deleted file mode 100644 index b414b691d7..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/haraka.c +++ /dev/null @@ -1,702 +0,0 @@ -/* -Plain C implementation of the Haraka256 and Haraka512 permutations. -*/ -#include -#include -#include -#include -#include - -#include "haraka.h" -#include "harakax4.h" -#include "utils.h" - -#define HARAKAS_RATE 32 - -#define u64 unsigned long -#define u128 __m128i - -#define LOAD(src) _mm_loadu_si128((u128 *)(src)) -#define STORE(dest,src) _mm_storeu_si128((u128 *)(dest),src) - -#define XOR128(a, b) _mm_xor_si128(a, b) - -#define AES2(s0, s1, rci) \ - s0 = _mm_aesenc_si128(s0, *(rci)); \ - (s1) = _mm_aesenc_si128(s1, *((rci) + 1)); \ - (s0) = _mm_aesenc_si128(s0, *((rci) + 2)); \ - (s1) = _mm_aesenc_si128(s1, *((rci) + 3)); - -#define AES2_4x(s0, s1, s2, s3, rci) \ - AES2((s0)[0], (s0)[1], rci); \ - AES2((s1)[0], (s1)[1], rci); \ - AES2((s2)[0], (s2)[1], rci); \ - AES2((s3)[0], (s3)[1], rci); - -#define AES4(s0, s1, s2, s3, rci) \ - s0 = _mm_aesenc_si128(s0, *(rci)); \ - (s1) = _mm_aesenc_si128(s1, *((rci) + 1)); \ - (s2) = _mm_aesenc_si128(s2, *((rci) + 2)); \ - (s3) = _mm_aesenc_si128(s3, *((rci) + 3)); \ - (s0) = _mm_aesenc_si128(s0, *((rci) + 4)); \ - (s1) = _mm_aesenc_si128(s1, *((rci) + 5)); \ - (s2) = _mm_aesenc_si128(s2, *((rci) + 6)); \ - (s3) = _mm_aesenc_si128(s3, *((rci) + 7)); - -#define AES4_4x(s0, s1, s2, s3, rci) \ - AES4((s0)[0], (s0)[1], (s0)[2], (s0)[3], rci); \ - AES4((s1)[0], (s1)[1], (s1)[2], (s1)[3], rci); \ - AES4((s2)[0], (s2)[1], (s2)[2], (s2)[3], rci); \ - AES4((s3)[0], (s3)[1], (s3)[2], (s3)[3], rci); - -#define MIX2(s0, s1) \ - tmp = _mm_unpacklo_epi32(s0, s1); \ - (s1) = _mm_unpackhi_epi32(s0, s1); \ - (s0) = tmp; - -#define MIX4(s0, s1, s2, s3) \ - tmp = _mm_unpacklo_epi32(s0, s1); \ - (s0) = _mm_unpackhi_epi32(s0, s1); \ - (s1) = _mm_unpacklo_epi32(s2, s3); \ - (s2) = _mm_unpackhi_epi32(s2, s3); \ - (s3) = _mm_unpacklo_epi32(s0, s2); \ - (s0) = _mm_unpackhi_epi32(s0, s2); \ - (s2) = _mm_unpackhi_epi32(s1, tmp); \ - (s1) = _mm_unpacklo_epi32(s1, tmp); - -#define TRUNCSTORE(out, s0, s1, s2, s3) \ - _mm_storeu_si128((u128 *)(out), \ - _mm_castpd_si128(_mm_shuffle_pd(_mm_castsi128_pd(s0), _mm_castsi128_pd(s1), 3))); \ - _mm_storeu_si128((u128 *)((out) + 16), \ - _mm_castpd_si128(_mm_shuffle_pd(_mm_castsi128_pd(s2), _mm_castsi128_pd(s3), 0))); - -static void load_haraka_constants(u128 *rc) { - rc[0] = _mm_set_epi32((int)0x0684704c, (int)0xe620c00a, (int)0xb2c5fef0, (int)0x75817b9d); - rc[1] = _mm_set_epi32((int)0x8b66b4e1, (int)0x88f3a06b, (int)0x640f6ba4, (int)0x2f08f717); - rc[2] = _mm_set_epi32((int)0x3402de2d, (int)0x53f28498, (int)0xcf029d60, (int)0x9f029114); - rc[3] = _mm_set_epi32((int)0x0ed6eae6, (int)0x2e7b4f08, (int)0xbbf3bcaf, (int)0xfd5b4f79); - rc[4] = _mm_set_epi32((int)0xcbcfb0cb, (int)0x4872448b, (int)0x79eecd1c, (int)0xbe397044); - rc[5] = _mm_set_epi32((int)0x7eeacdee, (int)0x6e9032b7, (int)0x8d5335ed, (int)0x2b8a057b); - rc[6] = _mm_set_epi32((int)0x67c28f43, (int)0x5e2e7cd0, (int)0xe2412761, (int)0xda4fef1b); - rc[7] = _mm_set_epi32((int)0x2924d9b0, (int)0xafcacc07, (int)0x675ffde2, (int)0x1fc70b3b); - rc[8] = _mm_set_epi32((int)0xab4d63f1, (int)0xe6867fe9, (int)0xecdb8fca, (int)0xb9d465ee); - rc[9] = _mm_set_epi32((int)0x1c30bf84, (int)0xd4b7cd64, (int)0x5b2a404f, (int)0xad037e33); - rc[10] = _mm_set_epi32((int)0xb2cc0bb9, (int)0x941723bf, (int)0x69028b2e, (int)0x8df69800); - rc[11] = _mm_set_epi32((int)0xfa0478a6, (int)0xde6f5572, (int)0x4aaa9ec8, (int)0x5c9d2d8a); - rc[12] = _mm_set_epi32((int)0xdfb49f2b, (int)0x6b772a12, (int)0x0efa4f2e, (int)0x29129fd4); - rc[13] = _mm_set_epi32((int)0x1ea10344, (int)0xf449a236, (int)0x32d611ae, (int)0xbb6a12ee); - rc[14] = _mm_set_epi32((int)0xaf044988, (int)0x4b050084, (int)0x5f9600c9, (int)0x9ca8eca6); - rc[15] = _mm_set_epi32((int)0x21025ed8, (int)0x9d199c4f, (int)0x78a2c7e3, (int)0x27e593ec); - rc[16] = _mm_set_epi32((int)0xbf3aaaf8, (int)0xa759c9b7, (int)0xb9282ecd, (int)0x82d40173); - rc[17] = _mm_set_epi32((int)0x6260700d, (int)0x6186b017, (int)0x37f2efd9, (int)0x10307d6b); - rc[18] = _mm_set_epi32((int)0x5aca45c2, (int)0x21300443, (int)0x81c29153, (int)0xf6fc9ac6); - rc[19] = _mm_set_epi32((int)0x9223973c, (int)0x226b68bb, (int)0x2caf92e8, (int)0x36d1943a); - rc[20] = _mm_set_epi32((int)0xd3bf9238, (int)0x225886eb, (int)0x6cbab958, (int)0xe51071b4); - rc[21] = _mm_set_epi32((int)0xdb863ce5, (int)0xaef0c677, (int)0x933dfddd, (int)0x24e1128d); - rc[22] = _mm_set_epi32((int)0xbb606268, (int)0xffeba09c, (int)0x83e48de3, (int)0xcb2212b1); - rc[23] = _mm_set_epi32((int)0x734bd3dc, (int)0xe2e4d19c, (int)0x2db91a4e, (int)0xc72bf77d); - rc[24] = _mm_set_epi32((int)0x43bb47c3, (int)0x61301b43, (int)0x4b1415c4, (int)0x2cb3924e); - rc[25] = _mm_set_epi32((int)0xdba775a8, (int)0xe707eff6, (int)0x03b231dd, (int)0x16eb6899); - rc[26] = _mm_set_epi32((int)0x6df3614b, (int)0x3c755977, (int)0x8e5e2302, (int)0x7eca472c); - rc[27] = _mm_set_epi32((int)0xcda75a17, (int)0xd6de7d77, (int)0x6d1be5b9, (int)0xb88617f9); - rc[28] = _mm_set_epi32((int)0xec6b43f0, (int)0x6ba8e9aa, (int)0x9d6c069d, (int)0xa946ee5d); - rc[29] = _mm_set_epi32((int)0xcb1e6950, (int)0xf957332b, (int)0xa2531159, (int)0x3bf327c1); - rc[30] = _mm_set_epi32((int)0x2cee0c75, (int)0x00da619c, (int)0xe4ed0353, (int)0x600ed0d9); - rc[31] = _mm_set_epi32((int)0xf0b1a5a1, (int)0x96e90cab, (int)0x80bbbabc, (int)0x63a4a350); - rc[32] = _mm_set_epi32((int)0xae3db102, (int)0x5e962988, (int)0xab0dde30, (int)0x938dca39); - rc[33] = _mm_set_epi32((int)0x17bb8f38, (int)0xd554a40b, (int)0x8814f3a8, (int)0x2e75b442); - rc[34] = _mm_set_epi32((int)0x34bb8a5b, (int)0x5f427fd7, (int)0xaeb6b779, (int)0x360a16f6); - rc[35] = _mm_set_epi32((int)0x26f65241, (int)0xcbe55438, (int)0x43ce5918, (int)0xffbaafde); - rc[36] = _mm_set_epi32((int)0x4ce99a54, (int)0xb9f3026a, (int)0xa2ca9cf7, (int)0x839ec978); - rc[37] = _mm_set_epi32((int)0xae51a51a, (int)0x1bdff7be, (int)0x40c06e28, (int)0x22901235); - rc[38] = _mm_set_epi32((int)0xa0c1613c, (int)0xba7ed22b, (int)0xc173bc0f, (int)0x48a659cf); - rc[39] = _mm_set_epi32((int)0x756acc03, (int)0x02288288, (int)0x4ad6bdfd, (int)0xe9c59da1); -} - -void tweak_constants(spx_ctx *ctx) { - int i; - unsigned char buf[40 * 16]; - - /* Use the standard constants to generate tweaked ones. */ - load_haraka_constants(ctx->rc); - - /* Constants for pk.seed */ - haraka_S(buf, 40 * 16, ctx->pub_seed, SPX_N, ctx); - - /* Tweak constants with the pub_seed */ - for (i = 0; i < 40; i++) { - ctx->rc[i] = LOAD(buf + i * 16); - } -} - -static void haraka_S_absorb(unsigned char *s, unsigned int r, - const unsigned char *m, unsigned long long mlen, - unsigned char p, const spx_ctx *ctx) { - unsigned long long i; - PQCLEAN_VLA(unsigned char, t, r); - - while (mlen >= r) { - // XOR block to state - STORE(s, XOR128(LOAD(s), LOAD(m))); - STORE(s + 16, XOR128(LOAD(s + 16), LOAD(m + 16))); - haraka512_perm(s, s, ctx); - 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; - STORE(s, XOR128(LOAD(s), LOAD(t))); - STORE(s + 16, XOR128(LOAD(s + 16), LOAD(t + 16))); -} - -static void haraka_S_absorb4x(unsigned char *s, - unsigned int r, - const unsigned char *m0, - const unsigned char *m1, - const unsigned char *m2, - const unsigned char *m3, - unsigned long long int mlen, - unsigned char p, - const spx_ctx *ctx) { - unsigned long long i; - PQCLEAN_VLA(unsigned char, t0, r); - PQCLEAN_VLA(unsigned char, t1, r); - PQCLEAN_VLA(unsigned char, t2, r); - PQCLEAN_VLA(unsigned char, t3, r); - - while (mlen >= r) { - // XOR block to state - STORE(s, XOR128(LOAD(s), LOAD(m0))); - STORE(s + 16, XOR128(LOAD(s + 16), LOAD(m0 + 16))); - STORE(s + 64, XOR128(LOAD(s + 64), LOAD(m1))); - STORE(s + 80, XOR128(LOAD(s + 80), LOAD(m1 + 16))); - STORE(s + 128, XOR128(LOAD(s + 128), LOAD(m2))); - STORE(s + 144, XOR128(LOAD(s + 144), LOAD(m2 + 16))); - STORE(s + 192, XOR128(LOAD(s + 192), LOAD(m3))); - STORE(s + 208, XOR128(LOAD(s + 208), LOAD(m3 + 16))); - - haraka512_perm_x4(s, s, ctx); - mlen -= r; - m0 += r; - m1 += r; - m2 += r; - m3 += r; - } - - for (i = 0; i < r; ++i) { - t0[i] = 0; - t1[i] = 0; - t2[i] = 0; - t3[i] = 0; - } - for (i = 0; i < mlen; ++i) { - t0[i] = m0[i]; - t1[i] = m1[i]; - t2[i] = m2[i]; - t3[i] = m3[i]; - } - - t0[i] = p; - t1[i] = p; - t2[i] = p; - t3[i] = p; - - t0[r - 1] |= 128; - t1[r - 1] |= 128; - t2[r - 1] |= 128; - t3[r - 1] |= 128; - - STORE(s, XOR128(LOAD(s), LOAD(t0))); - STORE(s + 16, XOR128(LOAD(s + 16), LOAD(t0 + 16))); - STORE(s + 64, XOR128(LOAD(s + 64), LOAD(t1))); - STORE(s + 80, XOR128(LOAD(s + 80), LOAD(t1 + 16))); - STORE(s + 128, XOR128(LOAD(s + 128), LOAD(t2))); - STORE(s + 144, XOR128(LOAD(s + 144), LOAD(t2 + 16))); - STORE(s + 192, XOR128(LOAD(s + 192), LOAD(t3))); - STORE(s + 208, XOR128(LOAD(s + 208), LOAD(t3 + 16))); -} - -static void haraka_S_squeezeblocks(unsigned char *h, unsigned long long nblocks, - unsigned char *s, unsigned int r, - const spx_ctx *ctx) { - while (nblocks > 0) { - haraka512_perm(s, s, ctx); - STORE(h, LOAD(s)); - STORE(h + 16, LOAD(s + 16)); - h += r; - nblocks--; - } -} - -static void haraka_S_squeezeblocks4x(unsigned char *h0, - unsigned char *h1, - unsigned char *h2, - unsigned char *h3, - unsigned long long nblocks, - unsigned char *s, - unsigned int r, - const spx_ctx *ctx) { - while (nblocks > 0) { - haraka512_perm_x4(s, s, ctx); - STORE(h0, LOAD(s)); - STORE(h0 + 16, LOAD(s + 16)); - STORE(h1, LOAD(s + 64)); - STORE(h1 + 16, LOAD(s + 80)); - STORE(h2, LOAD(s + 128)); - STORE(h2 + 16, LOAD(s + 144)); - STORE(h3, LOAD(s + 192)); - STORE(h3 + 16, LOAD(s + 208)); - h0 += r; - h1 += r; - h2 += r; - h3 += r; - nblocks--; - } -} - -void haraka_S_inc_init(uint8_t *s_inc) { - size_t i; - - for (i = 0; i < 64; i++) { - s_inc[i] = 0; - } - s_inc[64] = 0; -} - -void haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, - const spx_ctx *ctx) { - size_t i; - - /* Recall that s_inc[64] is the non-absorbed bytes xored into the state */ - while (mlen + s_inc[64] >= HARAKAS_RATE) { - for (i = 0; i < (size_t)(HARAKAS_RATE - s_inc[64]); i++) { - /* Take the i'th byte from message - xor with the s_inc[64] + i'th byte of the state */ - s_inc[s_inc[64] + i] ^= m[i]; - } - mlen -= (size_t)(HARAKAS_RATE - s_inc[64]); - m += HARAKAS_RATE - s_inc[64]; - s_inc[64] = 0; - - haraka512_perm(s_inc, s_inc, ctx); - } - - for (i = 0; i < mlen; i++) { - s_inc[s_inc[64] + i] ^= m[i]; - } - s_inc[64] += (uint8_t)mlen; -} - -void haraka_S_inc_finalize(uint8_t *s_inc) { - /* After haraka_S_inc_absorb, we are guaranteed that s_inc[64] < HARAKAS_RATE, - so we can always use one more byte for p in the current state. */ - s_inc[s_inc[64]] ^= 0x1F; - s_inc[HARAKAS_RATE - 1] ^= 128; - s_inc[64] = 0; -} - -void haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, - const spx_ctx *ctx) { - size_t i; - - /* First consume any bytes we still have sitting around */ - for (i = 0; i < outlen && i < s_inc[64]; i++) { - /* There are s_inc[64] bytes left, so r - s_inc[64] is the first - available byte. We consume from there, i.e., up to r. */ - out[i] = (uint8_t)s_inc[(HARAKAS_RATE - s_inc[64] + i)]; - } - out += i; - outlen -= i; - s_inc[64] -= (uint8_t)i; - - /* Then squeeze the remaining necessary blocks */ - while (outlen > 0) { - haraka512_perm(s_inc, s_inc, ctx); - - for (i = 0; i < outlen && i < HARAKAS_RATE; i++) { - out[i] = s_inc[i]; - } - out += i; - outlen -= i; - s_inc[64] = (uint8_t)(HARAKAS_RATE - i); - } -} - -void haraka_S(unsigned char *out, unsigned long long outlen, - const unsigned char *in, unsigned long long inlen, - const spx_ctx *ctx) { - unsigned long long i; - unsigned char s[64]; - unsigned char d[32]; - - for (i = 0; i < 64; i++) { - s[i] = 0; - } - haraka_S_absorb(s, HARAKAS_RATE, in, inlen, 0x1F, ctx); - - haraka_S_squeezeblocks(out, outlen / HARAKAS_RATE, s, HARAKAS_RATE, ctx); - out += (outlen / HARAKAS_RATE) * HARAKAS_RATE; - - if (outlen % HARAKAS_RATE) { - haraka_S_squeezeblocks(d, 1, s, HARAKAS_RATE, ctx); - for (i = 0; i < outlen % HARAKAS_RATE; i++) { - out[i] = d[i]; - } - } -} - -void haraka_Sx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned long long outlen, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - unsigned long long inlen, - const spx_ctx *ctx) { - unsigned long long i; - unsigned char s[64 * 4]; - unsigned char d0[32]; - unsigned char d1[32]; - unsigned char d2[32]; - unsigned char d3[32]; - - for (i = 0; i < 64 * 4; i++) { - s[i] = 0; - } - haraka_S_absorb4x(s, HARAKAS_RATE, in0, in1, in2, in3, inlen, 0x1F, ctx); - - haraka_S_squeezeblocks4x(out0, out1, out2, out3, outlen / HARAKAS_RATE, s, - HARAKAS_RATE, ctx); - out0 += (outlen / HARAKAS_RATE) * HARAKAS_RATE; - out1 += (outlen / HARAKAS_RATE) * HARAKAS_RATE; - out2 += (outlen / HARAKAS_RATE) * HARAKAS_RATE; - out3 += (outlen / HARAKAS_RATE) * HARAKAS_RATE; - - if (outlen % HARAKAS_RATE) { - haraka_S_squeezeblocks4x(d0, d1, d2, d3, 1, s, HARAKAS_RATE, ctx); - for (i = 0; i < outlen % HARAKAS_RATE; i++) { - out0[i] = d0[i]; - out1[i] = d1[i]; - out2[i] = d2[i]; - out3[i] = d3[i]; - } - } -} - -void haraka512_perm(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx) { - u128 s[4], tmp; - - s[0] = LOAD(in); - s[1] = LOAD(in + 16); - s[2] = LOAD(in + 32); - s[3] = LOAD(in + 48); - - AES4(s[0], s[1], s[2], s[3], ctx->rc); - MIX4(s[0], s[1], s[2], s[3]); - - AES4(s[0], s[1], s[2], s[3], ctx->rc + 8); - MIX4(s[0], s[1], s[2], s[3]); - - AES4(s[0], s[1], s[2], s[3], ctx->rc + 16); - MIX4(s[0], s[1], s[2], s[3]); - - AES4(s[0], s[1], s[2], s[3], ctx->rc + 24); - MIX4(s[0], s[1], s[2], s[3]); - - AES4(s[0], s[1], s[2], s[3], ctx->rc + 32); - MIX4(s[0], s[1], s[2], s[3]); - - STORE(out, s[0]); - STORE(out + 16, s[1]); - STORE(out + 32, s[2]); - STORE(out + 48, s[3]); -} - -void haraka512_perm_x4(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx) { - u128 s[4][4], tmp; - - s[0][0] = LOAD(in); - s[0][1] = LOAD(in + 16); - s[0][2] = LOAD(in + 32); - s[0][3] = LOAD(in + 48); - s[1][0] = LOAD(in + 64); - s[1][1] = LOAD(in + 80); - s[1][2] = LOAD(in + 96); - s[1][3] = LOAD(in + 112); - s[2][0] = LOAD(in + 128); - s[2][1] = LOAD(in + 144); - s[2][2] = LOAD(in + 160); - s[2][3] = LOAD(in + 176); - s[3][0] = LOAD(in + 192); - s[3][1] = LOAD(in + 208); - s[3][2] = LOAD(in + 224); - s[3][3] = LOAD(in + 240); - - AES4_4x(s[0], s[1], s[2], s[3], ctx->rc); - MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); - MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); - MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); - MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - - AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 8); - MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); - MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); - MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); - MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - - AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 16); - MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); - MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); - MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); - MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - - AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 24); - MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); - MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); - MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); - MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - - AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 32); - MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); - MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); - MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); - MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - - STORE(out, s[0][0]); - STORE(out + 16, s[0][1]); - STORE(out + 32, s[0][2]); - STORE(out + 48, s[0][3]); - STORE(out + 64, s[1][0]); - STORE(out + 80, s[1][1]); - STORE(out + 96, s[1][2]); - STORE(out + 112, s[1][3]); - STORE(out + 128, s[2][0]); - STORE(out + 144, s[2][1]); - STORE(out + 160, s[2][2]); - STORE(out + 176, s[2][3]); - STORE(out + 192, s[3][0]); - STORE(out + 208, s[3][1]); - STORE(out + 224, s[3][2]); - STORE(out + 240, s[3][3]); -} - -void haraka512(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx) { - u128 s[4], tmp; - - s[0] = LOAD(in); - s[1] = LOAD(in + 16); - s[2] = LOAD(in + 32); - s[3] = LOAD(in + 48); - - AES4(s[0], s[1], s[2], s[3], ctx->rc); - MIX4(s[0], s[1], s[2], s[3]); - - AES4(s[0], s[1], s[2], s[3], ctx->rc + 8); - MIX4(s[0], s[1], s[2], s[3]); - - AES4(s[0], s[1], s[2], s[3], ctx->rc + 16); - MIX4(s[0], s[1], s[2], s[3]); - - AES4(s[0], s[1], s[2], s[3], ctx->rc + 24); - MIX4(s[0], s[1], s[2], s[3]); - - AES4(s[0], s[1], s[2], s[3], ctx->rc + 32); - MIX4(s[0], s[1], s[2], s[3]); - - s[0] = XOR128(s[0], LOAD(in)); - s[1] = XOR128(s[1], LOAD(in + 16)); - s[2] = XOR128(s[2], LOAD(in + 32)); - s[3] = XOR128(s[3], LOAD(in + 48)); - - // truncate and store result - TRUNCSTORE(out, s[0], s[1], s[2], s[3]); -} - -void haraka512x4(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx) { - u128 s[4][4], tmp; - - s[0][0] = LOAD(in); - s[0][1] = LOAD(in + 16); - s[0][2] = LOAD(in + 32); - s[0][3] = LOAD(in + 48); - s[1][0] = LOAD(in + 64); - s[1][1] = LOAD(in + 80); - s[1][2] = LOAD(in + 96); - s[1][3] = LOAD(in + 112); - s[2][0] = LOAD(in + 128); - s[2][1] = LOAD(in + 144); - s[2][2] = LOAD(in + 160); - s[2][3] = LOAD(in + 176); - s[3][0] = LOAD(in + 192); - s[3][1] = LOAD(in + 208); - s[3][2] = LOAD(in + 224); - s[3][3] = LOAD(in + 240); - - AES4_4x(s[0], s[1], s[2], s[3], ctx->rc); - MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); - MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); - MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); - MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - - AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 8); - MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); - MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); - MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); - MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - - AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 16); - MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); - MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); - MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); - MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - - AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 24); - MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); - MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); - MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); - MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - - AES4_4x(s[0], s[1], s[2], s[3], ctx->rc + 32); - MIX4(s[0][0], s[0][1], s[0][2], s[0][3]); - MIX4(s[1][0], s[1][1], s[1][2], s[1][3]); - MIX4(s[2][0], s[2][1], s[2][2], s[2][3]); - MIX4(s[3][0], s[3][1], s[3][2], s[3][3]); - - s[0][0] = XOR128(s[0][0], LOAD(in)); - s[0][1] = XOR128(s[0][1], LOAD(in + 16)); - s[0][2] = XOR128(s[0][2], LOAD(in + 32)); - s[0][3] = XOR128(s[0][3], LOAD(in + 48)); - s[1][0] = XOR128(s[1][0], LOAD(in + 64)); - s[1][1] = XOR128(s[1][1], LOAD(in + 80)); - s[1][2] = XOR128(s[1][2], LOAD(in + 96)); - s[1][3] = XOR128(s[1][3], LOAD(in + 112)); - s[2][0] = XOR128(s[2][0], LOAD(in + 128)); - s[2][1] = XOR128(s[2][1], LOAD(in + 144)); - s[2][2] = XOR128(s[2][2], LOAD(in + 160)); - s[2][3] = XOR128(s[2][3], LOAD(in + 176)); - s[3][0] = XOR128(s[3][0], LOAD(in + 192)); - s[3][1] = XOR128(s[3][1], LOAD(in + 208)); - s[3][2] = XOR128(s[3][2], LOAD(in + 224)); - s[3][3] = XOR128(s[3][3], LOAD(in + 240)); - - TRUNCSTORE(out, s[0][0], s[0][1], s[0][2], s[0][3]); - TRUNCSTORE((out + 32), s[1][0], s[1][1], s[1][2], s[1][3]); - TRUNCSTORE((out + 64), s[2][0], s[2][1], s[2][2], s[2][3]); - TRUNCSTORE((out + 96), s[3][0], s[3][1], s[3][2], s[3][3]); -} - -void haraka256(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx) { - u128 s[2], tmp; - - s[0] = LOAD(in); - s[1] = LOAD(in + 16); - - AES2(s[0], s[1], ctx->rc); - MIX2(s[0], s[1]); - - AES2(s[0], s[1], ctx->rc + 4); - MIX2(s[0], s[1]); - - AES2(s[0], s[1], ctx->rc + 8); - MIX2(s[0], s[1]); - - AES2(s[0], s[1], ctx->rc + 12); - MIX2(s[0], s[1]); - - AES2(s[0], s[1], ctx->rc + 16); - MIX2(s[0], s[1]); - - s[0] = XOR128(s[0], LOAD(in)); - s[1] = XOR128(s[1], LOAD(in + 16)); - - STORE(out, s[0]); - STORE(out + 16, s[1]); -} - -void haraka256x4(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx) { - u128 s[4][2], tmp; - - s[0][0] = LOAD(in); - s[0][1] = LOAD(in + 16); - s[1][0] = LOAD(in + 32); - s[1][1] = LOAD(in + 48); - s[2][0] = LOAD(in + 64); - s[2][1] = LOAD(in + 80); - s[3][0] = LOAD(in + 96); - s[3][1] = LOAD(in + 112); - - // Round 1 - AES2_4x(s[0], s[1], s[2], s[3], ctx->rc); - - MIX2(s[0][0], s[0][1]); - MIX2(s[1][0], s[1][1]); - MIX2(s[2][0], s[2][1]); - MIX2(s[3][0], s[3][1]); - - // Round 2 - AES2_4x(s[0], s[1], s[2], s[3], ctx->rc + 4); - - MIX2(s[0][0], s[0][1]); - MIX2(s[1][0], s[1][1]); - MIX2(s[2][0], s[2][1]); - MIX2(s[3][0], s[3][1]); - - // Round 3 - AES2_4x(s[0], s[1], s[2], s[3], ctx->rc + 8); - - MIX2(s[0][0], s[0][1]); - MIX2(s[1][0], s[1][1]); - MIX2(s[2][0], s[2][1]); - MIX2(s[3][0], s[3][1]); - - // Round 4 - AES2_4x(s[0], s[1], s[2], s[3], ctx->rc + 12); - - MIX2(s[0][0], s[0][1]); - MIX2(s[1][0], s[1][1]); - MIX2(s[2][0], s[2][1]); - MIX2(s[3][0], s[3][1]); - - // Round 5 - AES2_4x(s[0], s[1], s[2], s[3], ctx->rc + 16); - - MIX2(s[0][0], s[0][1]); - MIX2(s[1][0], s[1][1]); - MIX2(s[2][0], s[2][1]); - MIX2(s[3][0], s[3][1]); - - // Feed Forward - s[0][0] = _mm_xor_si128(s[0][0], LOAD(in)); - s[0][1] = _mm_xor_si128(s[0][1], LOAD(in + 16)); - s[1][0] = _mm_xor_si128(s[1][0], LOAD(in + 32)); - s[1][1] = _mm_xor_si128(s[1][1], LOAD(in + 48)); - s[2][0] = _mm_xor_si128(s[2][0], LOAD(in + 64)); - s[2][1] = _mm_xor_si128(s[2][1], LOAD(in + 80)); - s[3][0] = _mm_xor_si128(s[3][0], LOAD(in + 96)); - s[3][1] = _mm_xor_si128(s[3][1], LOAD(in + 112)); - - STORE(out, s[0][0]); - STORE(out + 16, s[0][1]); - STORE(out + 32, s[1][0]); - STORE(out + 48, s[1][1]); - STORE(out + 64, s[2][0]); - STORE(out + 80, s[2][1]); - STORE(out + 96, s[3][0]); - STORE(out + 112, s[3][1]); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/haraka.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/haraka.h deleted file mode 100644 index 737cb6065f..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/haraka.h +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef SPX_HARAKA_H -#define SPX_HARAKA_H - -#include "context.h" -#include "params.h" - -/* Tweak constants with seed */ -#define tweak_constants SPX_NAMESPACE(tweak_constants) -void tweak_constants(spx_ctx *ctx); - -/* Haraka Sponge */ -#define haraka_S_inc_init SPX_NAMESPACE(haraka_S_inc_init) -void haraka_S_inc_init(uint8_t *s_inc); -#define haraka_S_inc_absorb SPX_NAMESPACE(haraka_S_inc_absorb) -void haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, - const spx_ctx *ctx); -#define haraka_S_inc_finalize SPX_NAMESPACE(haraka_S_inc_finalize) -void haraka_S_inc_finalize(uint8_t *s_inc); -#define haraka_S_inc_squeeze SPX_NAMESPACE(haraka_S_inc_squeeze) -void haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, - const spx_ctx *ctx); -#define haraka_S SPX_NAMESPACE(haraka_S) -void haraka_S(unsigned char *out, unsigned long long outlen, - const unsigned char *in, unsigned long long inlen, - const spx_ctx *ctx); - -/* Applies the 512-bit Haraka permutation to in. */ -#define haraka512_perm SPX_NAMESPACE(haraka512_perm) -void haraka512_perm(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx); - -/* Implementation of Haraka-512 */ -#define haraka512 SPX_NAMESPACE(haraka512) -void haraka512(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx); - -/* Implementation of Haraka-256 */ -#define haraka256 SPX_NAMESPACE(haraka256) -void haraka256(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/haraka_offsets.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/haraka_offsets.h deleted file mode 100644 index 7c062272a0..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/haraka_offsets.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef HARAKA_OFFSETS_H_ -#define HARAKA_OFFSETS_H_ - -/* - * Offsets of various fields in the address structure when we use Haraka as - * the Sphincs+ hash function - */ - -#define SPX_OFFSET_LAYER 3 /* The byte used to specify the Merkle tree layer */ -#define SPX_OFFSET_TREE 8 /* The start of the 8 byte field used to specify the tree */ -#define SPX_OFFSET_TYPE 19 /* The byte used to specify the hash type (reason) */ -#define SPX_OFFSET_KP_ADDR2 22 /* The high byte used to specify the key pair (which one-time signature) */ -#define SPX_OFFSET_KP_ADDR1 23 /* The low byte used to specify the key pair */ -#define SPX_OFFSET_CHAIN_ADDR 27 /* The byte used to specify the chain address (which Winternitz chain) */ -#define SPX_OFFSET_HASH_ADDR 31 /* The byte used to specify the hash address (where in the Winternitz chain) */ -#define SPX_OFFSET_TREE_HGT 27 /* The byte used to specify the height of this node in the FORS or Merkle tree */ -#define SPX_OFFSET_TREE_INDEX 28 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ - -#define SPX_HARAKA 1 - -#endif /* HARAKA_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/harakax4.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/harakax4.h deleted file mode 100644 index eadc69aa48..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/harakax4.h +++ /dev/null @@ -1,36 +0,0 @@ -#ifndef SPX_HARAKAX4_H -#define SPX_HARAKAX4_H - -#include "context.h" -#include "params.h" - -/* Haraka Sponge */ -#define haraka_Sx4 SPX_NAMESPACE(haraka_Sx4) -void haraka_Sx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned long long outlen, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - unsigned long long inlen, - const spx_ctx *ctx); - -/* Applies the 512-bit Haraka permutation x4 to in. */ -#define haraka512_perm_x4 SPX_NAMESPACE(haraka512_perm_x4) -void haraka512_perm_x4(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx); - -/* Implementation of Haraka-512 x4*/ -#define haraka512x4 SPX_NAMESPACE(haraka512x4) -void haraka512x4(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx); - -/* Implementation of Haraka-256 x4 */ -#define haraka256x4 SPX_NAMESPACE(haraka256x4) -void haraka256x4(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/hash.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/hash.h deleted file mode 100644 index f7c87d4c3c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/hash.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef SPX_HASH_H -#define SPX_HASH_H - -#include -#include - -#include "context.h" -#include "params.h" - -#define prf_addr SPX_NAMESPACE(prf_addr) -void prf_addr(unsigned char *out, const spx_ctx *ctx, - const uint32_t addr[8]); - -#define gen_message_random SPX_NAMESPACE(gen_message_random) -void gen_message_random(unsigned char *R, const unsigned char *sk_prf, - const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx); - -#define hash_message SPX_NAMESPACE(hash_message) -void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx); - - - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/hash_haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/hash_haraka.c deleted file mode 100644 index 750a67423b..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/hash_haraka.c +++ /dev/null @@ -1,81 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "utils.h" - -#include "haraka.h" -#include "hash.h" - -/* - * Computes PRF(key, addr), given a secret key of SPX_N bytes and an address - */ -void prf_addr(unsigned char *out, const spx_ctx *ctx, - const uint32_t addr[8]) { - /* Since SPX_N may be smaller than 32, we need temporary buffers. */ - unsigned char outbuf[32]; - unsigned char buf[64] = {0}; - - memcpy(buf, addr, SPX_ADDR_BYTES); - memcpy(buf + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); - - haraka512(outbuf, (const void *)buf, ctx); - memcpy(out, outbuf, SPX_N); -} - -/** - * Computes the message-dependent randomness R, using a secret seed and an - * optional randomization value as well as the message. - */ -void gen_message_random(unsigned char *R, const unsigned char *sk_prf, - const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx) { - uint8_t s_inc[65]; - - haraka_S_inc_init(s_inc); - haraka_S_inc_absorb(s_inc, sk_prf, SPX_N, ctx); - haraka_S_inc_absorb(s_inc, optrand, SPX_N, ctx); - haraka_S_inc_absorb(s_inc, m, mlen, ctx); - haraka_S_inc_finalize(s_inc); - haraka_S_inc_squeeze(R, SPX_N, s_inc, ctx); -} - -/** - * Computes the message hash using R, the public key, and the message. - * Outputs the message digest and the index of the leaf. The index is split in - * the tree index and the leaf index, for convenient copying to an address. - */ -void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx) { -#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) -#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) -#define SPX_LEAF_BITS SPX_TREE_HEIGHT -#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) -#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) - - unsigned char buf[SPX_DGST_BYTES]; - unsigned char *bufp = buf; - uint8_t s_inc[65]; - - haraka_S_inc_init(s_inc); - haraka_S_inc_absorb(s_inc, R, SPX_N, ctx); - haraka_S_inc_absorb(s_inc, pk + SPX_N, SPX_N, ctx); // Only absorb root part of pk - haraka_S_inc_absorb(s_inc, m, mlen, ctx); - haraka_S_inc_finalize(s_inc); - haraka_S_inc_squeeze(buf, SPX_DGST_BYTES, s_inc, ctx); - - memcpy(digest, bufp, SPX_FORS_MSG_BYTES); - bufp += SPX_FORS_MSG_BYTES; - - - *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); - *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); - bufp += SPX_TREE_BYTES; - - *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); - *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/hash_harakax4.c b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/hash_harakax4.c deleted file mode 100644 index cfa5162d79..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/hash_harakax4.c +++ /dev/null @@ -1,35 +0,0 @@ -#include -#include - -#include "address.h" -#include "harakax4.h" -#include "hashx4.h" -#include "params.h" - -/* - * 4-way parallel version of prf_addr; takes 4x as much input and output - */ -#define prf_addrx4 SPX_NAMESPACE(prf_addrx4) -void prf_addrx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const spx_ctx *ctx, - const uint32_t addrx4[4 * 8]) { - unsigned char bufx4[4 * 64] = {0}; - /* Since SPX_N may be smaller than 32, we need temporary buffers. */ - unsigned char outbuf[4 * 32]; - unsigned int i; - - for (i = 0; i < 4; i++) { - memcpy(bufx4 + i * 64, addrx4 + i * 8, SPX_ADDR_BYTES); - memcpy(bufx4 + i * 64 + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); - } - - haraka512x4(outbuf, bufx4, ctx); - - memcpy(out0, outbuf, SPX_N); - memcpy(out1, outbuf + 32, SPX_N); - memcpy(out2, outbuf + 64, SPX_N); - memcpy(out3, outbuf + 96, SPX_N); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/hashx4.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/hashx4.h deleted file mode 100644 index 3751a0ebd0..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/hashx4.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef SPX_HASHX4_H -#define SPX_HASHX4_H - -#include - -#include "context.h" -#include "params.h" - -#define prf_addrx4 SPX_NAMESPACE(prf_addrx4) -void prf_addrx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const spx_ctx *ctx, - const uint32_t addrx4[4 * 8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/merkle.c b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/merkle.c deleted file mode 100644 index f57811c1ac..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/merkle.c +++ /dev/null @@ -1,64 +0,0 @@ -#include -#include - -#include "merkle.h" - -#include "address.h" -#include "params.h" -#include "utils.h" -#include "utilsx4.h" -#include "wots.h" -#include "wotsx4.h" - -/* - * This generates a Merkle signature (WOTS signature followed by the Merkle - * authentication path). - */ -void merkle_sign(uint8_t *sig, unsigned char *root, - const spx_ctx *ctx, - uint32_t wots_addr[8], uint32_t tree_addr[8], - uint32_t idx_leaf) { - unsigned char *auth_path = sig + SPX_WOTS_BYTES; - uint32_t tree_addrx4[4 * 8] = { 0 }; - int j; - struct leaf_info_x4 info = { 0 }; - unsigned steps[ SPX_WOTS_LEN ]; - - info.wots_sig = sig; - chain_lengths(steps, root); - info.wots_steps = steps; - - for (j = 0; j < 4; j++) { - set_type(&tree_addrx4[8 * j], SPX_ADDR_TYPE_HASHTREE); - set_type(&info.leaf_addr[8 * j], SPX_ADDR_TYPE_WOTS); - set_type(&info.pk_addr[8 * j], SPX_ADDR_TYPE_WOTSPK); - copy_subtree_addr(&tree_addrx4[8 * j], tree_addr); - copy_subtree_addr(&info.leaf_addr[8 * j], wots_addr); - copy_subtree_addr(&info.pk_addr[8 * j], wots_addr); - } - - info.wots_sign_leaf = idx_leaf; - - treehashx4(root, auth_path, ctx, - idx_leaf, 0, - SPX_TREE_HEIGHT, - wots_gen_leafx4, - tree_addrx4, &info); -} - -/* Compute root node of the top-most subtree. */ -void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { - /* We do not need the auth path in key generation, but it simplifies the - code to have just one treehash routine that computes both root and path - in one function. */ - unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; - uint32_t top_tree_addr[8] = {0}; - uint32_t wots_addr[8] = {0}; - - set_layer_addr(top_tree_addr, SPX_D - 1); - set_layer_addr(wots_addr, SPX_D - 1); - - merkle_sign(auth_path, root, ctx, - wots_addr, top_tree_addr, - ~0U /* ~0 means "don't bother generating an auth path */ ); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/merkle.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/merkle.h deleted file mode 100644 index 769cf2e970..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/merkle.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef MERKLE_H_ -#define MERKLE_H_ - -#include - -#include "context.h" -#include "params.h" - -/* Generate a Merkle signature (WOTS signature followed by the Merkle */ -/* authentication path) */ -#define merkle_sign SPX_NAMESPACE(merkle_sign) -void merkle_sign(uint8_t *sig, unsigned char *root, - const spx_ctx *ctx, - uint32_t wots_addr[8], uint32_t tree_addr[8], - uint32_t idx_leaf); - -/* Compute the root node of the top-most subtree. */ -#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) -void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); - -#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/nistapi.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/nistapi.h deleted file mode 100644 index 3cb71afad4..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/nistapi.h +++ /dev/null @@ -1,87 +0,0 @@ -#ifndef SPX_API_H -#define SPX_API_H - -#include -#include - -#include "params.h" - -#define CRYPTO_ALGNAME "SPHINCS+" - -#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES -#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES -#define CRYPTO_BYTES SPX_BYTES -#define CRYPTO_SEEDBYTES (3*SPX_N) - -/* - * Returns the length of a secret key, in bytes - */ -#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) -size_t crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) -size_t crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) -size_t crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) -size_t crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) -int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) -int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) -int crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) -int crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -#define crypto_sign SPX_NAMESPACE(crypto_sign) -int crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) -int crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/params.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/params.h deleted file mode 100644 index 4390aba58b..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/params.h +++ /dev/null @@ -1,56 +0,0 @@ -#ifndef SPX_PARAMS_H -#define SPX_PARAMS_H - -#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_##s - -/* Hash output length in bytes. */ -#define SPX_N 32 -/* Height of the hypertree. */ -#define SPX_FULL_HEIGHT 64 -/* Number of subtree layer. */ -#define SPX_D 8 -/* FORS tree dimensions. */ -#define SPX_FORS_HEIGHT 14 -#define SPX_FORS_TREES 22 -/* Winternitz parameter, */ -#define SPX_WOTS_W 16 - -/* The hash function is defined by linking a different hash.c file, as opposed - to setting a #define constant. */ - -/* For clarity */ -#define SPX_ADDR_BYTES 32 - -/* WOTS parameters. */ -#define SPX_WOTS_LOGW 4 - -#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) - -/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#define SPX_WOTS_LEN2 3 - -#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) -#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) -#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES - -/* Subtree size. */ -#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) - -//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT -// #error SPX_D should always divide SPX_FULL_HEIGHT -//#endif - -/* FORS parameters. */ -#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) -#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) -#define SPX_FORS_PK_BYTES SPX_N - -/* Resulting SPX sizes. */ -#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ - SPX_FULL_HEIGHT * SPX_N) -#define SPX_PK_BYTES (2 * SPX_N) -#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) - -#include "haraka_offsets.h" - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/sign.c b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/sign.c deleted file mode 100644 index 9d0c7d1b22..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/sign.c +++ /dev/null @@ -1,286 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "context.h" -#include "fors.h" -#include "hash.h" -#include "merkle.h" -#include "nistapi.h" -#include "params.h" -#include "randombytes.h" -#include "thash.h" -#include "utils.h" -#include "wots.h" - -/* - * Returns the length of a secret key, in bytes - */ -size_t crypto_sign_secretkeybytes(void) { - return CRYPTO_SECRETKEYBYTES; -} - -/* - * Returns the length of a public key, in bytes - */ -size_t crypto_sign_publickeybytes(void) { - return CRYPTO_PUBLICKEYBYTES; -} - -/* - * Returns the length of a signature, in bytes - */ -size_t crypto_sign_bytes(void) { - return CRYPTO_BYTES; -} - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t crypto_sign_seedbytes(void) { - return CRYPTO_SEEDBYTES; -} - -/* - * Generates an SPX key pair given a seed of length - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed) { - spx_ctx ctx; - - /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ - memcpy(sk, seed, CRYPTO_SEEDBYTES); - - memcpy(pk, sk + 2 * SPX_N, SPX_N); - - memcpy(ctx.pub_seed, pk, SPX_N); - memcpy(ctx.sk_seed, sk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - /* Compute root node of the top-most subtree. */ - merkle_gen_root(sk + 3 * SPX_N, &ctx); - - // cleanup - free_hash_function(&ctx); - - memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); - - return 0; -} - -/* - * Generates an SPX key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { - uint8_t seed[CRYPTO_SEEDBYTES]; - randombytes(seed, CRYPTO_SEEDBYTES); - crypto_sign_seed_keypair(pk, sk, seed); - - return 0; -} - -/** - * Returns an array containing a detached signature. - */ -int crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - spx_ctx ctx; - - const uint8_t *sk_prf = sk + SPX_N; - const uint8_t *pk = sk + 2 * SPX_N; - - uint8_t optrand[SPX_N]; - uint8_t mhash[SPX_FORS_MSG_BYTES]; - uint8_t root[SPX_N]; - uint32_t i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - - memcpy(ctx.sk_seed, sk, SPX_N); - memcpy(ctx.pub_seed, pk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - set_type(wots_addr, SPX_ADDR_TYPE_WOTS); - set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); - - /* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ - randombytes(optrand, SPX_N); - /* Compute the digest randomization value. */ - gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); - - /* Derive the message digest and leaf index from R, PK and M. */ - hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); - sig += SPX_N; - - set_tree_addr(wots_addr, tree); - set_keypair_addr(wots_addr, idx_leaf); - - /* Sign the message hash using FORS. */ - fors_sign(sig, root, mhash, &ctx, wots_addr); - sig += SPX_FORS_BYTES; - - for (i = 0; i < SPX_D; i++) { - set_layer_addr(tree_addr, i); - set_tree_addr(tree_addr, tree); - - copy_subtree_addr(wots_addr, tree_addr); - set_keypair_addr(wots_addr, idx_leaf); - - merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); - sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); - tree = tree >> SPX_TREE_HEIGHT; - } - - free_hash_function(&ctx); - - *siglen = SPX_BYTES; - - return 0; -} - -/** - * Verifies a detached signature and message under a given public key. - */ -int crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk) { - spx_ctx ctx; - const uint8_t *pub_root = pk + SPX_N; - uint8_t mhash[SPX_FORS_MSG_BYTES]; - uint8_t wots_pk[SPX_WOTS_BYTES]; - uint8_t root[SPX_N]; - uint8_t leaf[SPX_N]; - unsigned int i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - if (siglen != SPX_BYTES) { - return -1; - } - - memcpy(ctx.pub_seed, pk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - set_type(wots_addr, SPX_ADDR_TYPE_WOTS); - set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); - set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); - - /* Derive the message digest and leaf index from R || PK || M. */ - /* The additional SPX_N is a result of the hash domain separator. */ - hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); - sig += SPX_N; - - /* Layer correctly defaults to 0, so no need to set_layer_addr */ - set_tree_addr(wots_addr, tree); - set_keypair_addr(wots_addr, idx_leaf); - - fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); - sig += SPX_FORS_BYTES; - - /* For each subtree.. */ - for (i = 0; i < SPX_D; i++) { - set_layer_addr(tree_addr, i); - set_tree_addr(tree_addr, tree); - - copy_subtree_addr(wots_addr, tree_addr); - set_keypair_addr(wots_addr, idx_leaf); - - copy_keypair_addr(wots_pk_addr, wots_addr); - - /* The WOTS public key is only correct if the signature was correct. */ - /* Initially, root is the FORS pk, but on subsequent iterations it is - the root of the subtree below the currently processed subtree. */ - wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); - sig += SPX_WOTS_BYTES; - - /* Compute the leaf node using the WOTS public key. */ - thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); - - /* Compute the root node of this subtree. */ - compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, - &ctx, tree_addr); - sig += SPX_TREE_HEIGHT * SPX_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); - tree = tree >> SPX_TREE_HEIGHT; - } - - // cleanup - free_hash_function(&ctx); - - /* Check if the root node equals the root node in the public key. */ - if (memcmp(root, pub_root, SPX_N) != 0) { - return -1; - } - - return 0; -} - - -/** - * Returns an array containing the signature followed by the message. - */ -int crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk) { - size_t siglen; - - crypto_sign_signature(sm, &siglen, m, mlen, sk); - - memmove(sm + SPX_BYTES, m, mlen); - *smlen = siglen + mlen; - - return 0; -} - -/** - * Verifies a given signature-message pair under a given public key. - */ -int crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk) { - /* The API caller does not necessarily know what size a signature should be - but SPHINCS+ signatures are always exactly SPX_BYTES. */ - if (smlen < SPX_BYTES) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - *mlen = smlen - SPX_BYTES; - - if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - /* If verification was successful, move the message to the right place. */ - memmove(m, sm + SPX_BYTES, *mlen); - - return 0; -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/thash.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/thash.h deleted file mode 100644 index 8687ccfb4d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/thash.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef SPX_THASH_H -#define SPX_THASH_H - -#include "context.h" -#include "params.h" - -#include - -#define thash SPX_NAMESPACE(thash) -void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/thash_haraka_simple.c b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/thash_haraka_simple.c deleted file mode 100644 index 207777bf8d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/thash_haraka_simple.c +++ /dev/null @@ -1,36 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "thash.h" -#include "utils.h" - -#include "haraka.h" - -/** - * Takes an array of inblocks concatenated arrays of SPX_N bytes. - */ -void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]) { - PQCLEAN_VLA(uint8_t, buf, SPX_ADDR_BYTES + inblocks * SPX_N); - unsigned char outbuf[32]; - unsigned char buf_tmp[64]; - - if (inblocks == 1) { - /* F function */ - /* Since SPX_N may be smaller than 32, we need a temporary buffer. */ - memset(buf_tmp, 0, 64); - memcpy(buf_tmp, addr, 32); - memcpy(buf_tmp + SPX_ADDR_BYTES, in, SPX_N); - - haraka512(outbuf, buf_tmp, ctx); - memcpy(out, outbuf, SPX_N); - } else { - /* All other tweakable hashes*/ - memcpy(buf, addr, 32); - memcpy(buf + SPX_ADDR_BYTES, in, inblocks * SPX_N); - - haraka_S(out, SPX_N, buf, SPX_ADDR_BYTES + inblocks * SPX_N, ctx); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/thash_haraka_simplex4.c b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/thash_haraka_simplex4.c deleted file mode 100644 index 2ee763d7d9..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/thash_haraka_simplex4.c +++ /dev/null @@ -1,67 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "thashx4.h" - -#include "harakax4.h" - -#include "utils.h" - -/** - * 4-way parallel version of thash; takes 4x as much input and output - */ -#define thashx4 SPX_NAMESPACE(thashx4) -void thashx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addrx4[4 * 8]) { - PQCLEAN_VLA(unsigned char, buf0, SPX_ADDR_BYTES + inblocks * SPX_N); - PQCLEAN_VLA(unsigned char, buf1, SPX_ADDR_BYTES + inblocks * SPX_N); - PQCLEAN_VLA(unsigned char, buf2, SPX_ADDR_BYTES + inblocks * SPX_N); - PQCLEAN_VLA(unsigned char, buf3, SPX_ADDR_BYTES + inblocks * SPX_N); - unsigned char outbuf[32 * 4]; - unsigned char buf_tmp[64 * 4]; - - if (inblocks == 1) { - memset(buf_tmp, 0, 64 * 4); - - memcpy(buf_tmp, addrx4 + 0 * 8, 32); - memcpy(buf_tmp + 64, addrx4 + 1 * 8, 32); - memcpy(buf_tmp + 128, addrx4 + 2 * 8, 32); - memcpy(buf_tmp + 192, addrx4 + 3 * 8, 32); - - memcpy(buf_tmp + SPX_ADDR_BYTES, in0, SPX_N); - memcpy(buf_tmp + SPX_ADDR_BYTES + 64, in1, SPX_N); - memcpy(buf_tmp + SPX_ADDR_BYTES + 128, in2, SPX_N); - memcpy(buf_tmp + SPX_ADDR_BYTES + 192, in3, SPX_N); - - haraka512x4(outbuf, buf_tmp, ctx); - - memcpy(out0, outbuf, SPX_N); - memcpy(out1, outbuf + 32, SPX_N); - memcpy(out2, outbuf + 64, SPX_N); - memcpy(out3, outbuf + 96, SPX_N); - } else { - /* All other tweakable hashes*/ - memcpy(buf0, addrx4 + 0 * 8, 32); - memcpy(buf1, addrx4 + 1 * 8, 32); - memcpy(buf2, addrx4 + 2 * 8, 32); - memcpy(buf3, addrx4 + 3 * 8, 32); - - memcpy(buf0 + SPX_ADDR_BYTES, in0, inblocks * SPX_N); - memcpy(buf1 + SPX_ADDR_BYTES, in1, inblocks * SPX_N); - memcpy(buf2 + SPX_ADDR_BYTES, in2, inblocks * SPX_N); - memcpy(buf3 + SPX_ADDR_BYTES, in3, inblocks * SPX_N); - - haraka_Sx4(out0, out1, out2, out3, SPX_N, - buf0, buf1, buf2, buf3, SPX_ADDR_BYTES + inblocks * SPX_N, - ctx); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/thashx4.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/thashx4.h deleted file mode 100644 index 64798a3727..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/thashx4.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef SPX_THASHX4_H -#define SPX_THASHX4_H - -#include - -#include "context.h" -#include "params.h" - -#define thashx4 SPX_NAMESPACE(thashx4) -void thashx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addrx4[4 * 8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/utils.c b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/utils.c deleted file mode 100644 index 177b541fb9..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/utils.c +++ /dev/null @@ -1,148 +0,0 @@ -#include - -#include "utils.h" - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "thash.h" - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void ull_to_bytes(unsigned char *out, unsigned int outlen, - unsigned long long in) { - int i; - - /* Iterate over out in decreasing order, for big-endianness. */ - for (i = (signed int)outlen - 1; i >= 0; i--) { - out[i] = in & 0xff; - in = in >> 8; - } -} - -void u32_to_bytes(unsigned char *out, uint32_t in) { - out[0] = (unsigned char)(in >> 24); - out[1] = (unsigned char)(in >> 16); - out[2] = (unsigned char)(in >> 8); - out[3] = (unsigned char)in; -} - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { - unsigned long long retval = 0; - unsigned int i; - - for (i = 0; i < inlen; i++) { - retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); - } - return retval; -} - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void compute_root(unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const spx_ctx *ctx, uint32_t addr[8]) { - uint32_t i; - unsigned char buffer[2 * SPX_N]; - - /* If leaf_idx is odd (last bit = 1), current path element is a right child - and auth_path has to go left. Otherwise it is the other way around. */ - if (leaf_idx & 1) { - memcpy(buffer + SPX_N, leaf, SPX_N); - memcpy(buffer, auth_path, SPX_N); - } else { - memcpy(buffer, leaf, SPX_N); - memcpy(buffer + SPX_N, auth_path, SPX_N); - } - auth_path += SPX_N; - - for (i = 0; i < tree_height - 1; i++) { - leaf_idx >>= 1; - idx_offset >>= 1; - /* Set the address of the node we're creating. */ - set_tree_height(addr, i + 1); - set_tree_index(addr, leaf_idx + idx_offset); - - /* Pick the right or left neighbor, depending on parity of the node. */ - if (leaf_idx & 1) { - thash(buffer + SPX_N, buffer, 2, ctx, addr); - memcpy(buffer, auth_path, SPX_N); - } else { - thash(buffer, buffer, 2, ctx, addr); - memcpy(buffer + SPX_N, auth_path, SPX_N); - } - auth_path += SPX_N; - } - - /* The last iteration is exceptional; we do not copy an auth_path node. */ - leaf_idx >>= 1; - idx_offset >>= 1; - set_tree_height(addr, tree_height); - set_tree_index(addr, leaf_idx + idx_offset); - thash(root, buffer, 2, ctx, addr); -} - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const spx_ctx * /* ctx */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), - uint32_t tree_addr[8]) { - PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); - PQCLEAN_VLA(unsigned int, heights, tree_height + 1); - unsigned int offset = 0; - uint32_t idx; - uint32_t tree_idx; - - for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { - /* Add the next leaf node to the stack. */ - gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); - offset++; - heights[offset - 1] = 0; - - /* If this is a node we need for the auth path.. */ - if ((leaf_idx ^ 0x1) == idx) { - memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); - } - - /* While the top-most nodes are of equal height.. */ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { - /* Compute index of the new node, in the next layer. */ - tree_idx = (idx >> (heights[offset - 1] + 1)); - - /* Set the address of the node we're creating. */ - set_tree_height(tree_addr, heights[offset - 1] + 1); - set_tree_index(tree_addr, - tree_idx + (idx_offset >> (heights[offset - 1] + 1))); - /* Hash the top-most nodes from the stack together. */ - thash(stack + (offset - 2)*SPX_N, - stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); - offset--; - /* Note that the top-most node is now one layer higher. */ - heights[offset - 1]++; - - /* If this is a node we need for the auth path.. */ - if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_path + heights[offset - 1]*SPX_N, - stack + (offset - 1)*SPX_N, SPX_N); - } - } - } - memcpy(root, stack, SPX_N); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/utils.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/utils.h deleted file mode 100644 index 64f5d5a53a..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/utils.h +++ /dev/null @@ -1,58 +0,0 @@ -#ifndef SPX_UTILS_H -#define SPX_UTILS_H - -#include - -#include "compat.h" -#include "context.h" -#include "params.h" - - -/* To support MSVC use alloca() instead of VLAs. See #20. */ - - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) -void ull_to_bytes(unsigned char *out, unsigned int outlen, - unsigned long long in); -#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) -void u32_to_bytes(unsigned char *out, uint32_t in); - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) -unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -#define compute_root SPX_NAMESPACE(compute_root) -void compute_root(unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const spx_ctx *ctx, uint32_t addr[8]); - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -#define treehash SPX_NAMESPACE(treehash) -void treehash(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const spx_ctx *ctx /* ctx */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), - uint32_t tree_addr[8]); - - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/utilsx4.c b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/utilsx4.c deleted file mode 100644 index 1638677194..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/utilsx4.c +++ /dev/null @@ -1,138 +0,0 @@ -#include - -#include "utilsx4.h" - -#include "address.h" -#include "params.h" -#include "thashx4.h" -#include "utils.h" - -/* - * Generate the entire Merkle tree, computing the authentication path for leaf_idx, - * and the resulting root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) - * - * This expects tree_addrx4 to be initialized to 4 parallel addr structures for - * the Merkle tree nodes - * - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - * - * This works by using the standard Merkle tree building algorithm, except - * that each 'node' tracked is actually 4 consecutive nodes in the real tree. - * When we combine two logical nodes ABCD and WXYZ, we perform the H - * operation on adjacent real nodes, forming the parent logical node - * (AB)(CD)(WX)(YZ) - * - * When we get to the top two levels of the real tree (where there is only - * one logical node), we continue this operation two more times; the right - * most real node will by the actual root (and the other 3 nodes will be - * garbage). We follow the same thashx4 logic so that the 'extract - * authentication path components' part of the loop is still executed (and - * to simplify the code somewhat) - * - * This currently assumes tree_height >= 2; I suspect that doing an adjusting - * idx, addr_idx on the gen_leafx4 call if tree_height < 2 would fix it; since - * we don't actually use such short trees, I haven't bothered - */ -void treehashx4(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, - uint32_t tree_height, - void (*gen_leafx4)( - unsigned char * /* Where to write the leaves */, - const spx_ctx *, - uint32_t idx, void *info), - uint32_t tree_addrx4[4 * 8], - void *info) { - /* This is where we keep the intermediate nodes */ - PQCLEAN_VLA(unsigned char, stackx4, tree_height * 4 * SPX_N); - uint32_t left_adj = 0, prev_left_adj = 0; /* When we're doing the top 3 */ - /* levels, the left-most part of the tree isn't at the beginning */ - /* of current[]. These give the offset of the actual start */ - - uint32_t idx; - uint32_t max_idx = (1U << (tree_height - 2)) - 1; - for (idx = 0;; idx++) { - unsigned char current[4 * SPX_N]; /* Current logical node */ - gen_leafx4( current, ctx, 4 * idx + idx_offset, - info ); - - /* Now combine the freshly generated right node with previously */ - /* generated left ones */ - uint32_t internal_idx_offset = idx_offset; - uint32_t internal_idx = idx; - uint32_t internal_leaf = leaf_idx; - uint32_t h; /* The height we are in the Merkle tree */ - for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { - - /* Special processing if we're at the top of the tree */ - if (h >= tree_height - 2) { - if (h == tree_height) { - /* We hit the root; return it */ - memcpy( root, ¤t[3 * SPX_N], SPX_N ); - return; - } - /* The tree indexing logic is a bit off in this case */ - /* Adjust it so that the left-most node of the part of */ - /* the tree that we're processing has index 0 */ - prev_left_adj = left_adj; - left_adj = 4U - (1 << (tree_height - h - 1)); - } - - /* Check if we hit the top of the tree */ - if (h == tree_height) { - /* We hit the root; return it */ - memcpy( root, ¤t[3 * SPX_N], SPX_N ); - return; - } - - /* - * Check if one of the nodes we have is a part of the - * authentication path; if it is, write it out - */ - if ((((internal_idx << 2) ^ internal_leaf) & ~0x3U) == 0) { - memcpy( &auth_path[ h * SPX_N ], - ¤t[(((internal_leaf & 3) ^ 1) + prev_left_adj) * SPX_N], - SPX_N ); - } - - /* - * Check if we're at a left child; if so, stop going up the stack - * Exception: if we've reached the end of the tree, keep on going - * (so we combine the last 4 nodes into the one root node in two - * more iterations) - */ - if ((internal_idx & 1) == 0 && idx < max_idx) { - break; - } - - /* Ok, we're at a right node (or doing the top 3 levels) */ - /* Now combine the left and right logical nodes together */ - - /* Set the address of the node we're creating. */ - unsigned int j; - internal_idx_offset >>= 1; - for (j = 0; j < 4; j++) { - set_tree_height(tree_addrx4 + j * 8, h + 1); - set_tree_index(tree_addrx4 + j * 8, - (4 / 2) * (internal_idx & ~1U) + j - left_adj + internal_idx_offset ); - } - unsigned char *left = &stackx4[h * 4 * SPX_N]; - thashx4( ¤t[0 * SPX_N], - ¤t[1 * SPX_N], - ¤t[2 * SPX_N], - ¤t[3 * SPX_N], - &left [0 * SPX_N], - &left [2 * SPX_N], - ¤t[0 * SPX_N], - ¤t[2 * SPX_N], - 2, ctx, tree_addrx4); - } - - /* We've hit a left child; save the current for when we get the */ - /* corresponding right right */ - memcpy( &stackx4[h * 4 * SPX_N], current, 4 * SPX_N); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/utilsx4.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/utilsx4.h deleted file mode 100644 index facb874b18..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/utilsx4.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef SPX_UTILSX4_H -#define SPX_UTILSX4_H - -#include - -#include "context.h" -#include "params.h" - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - * - * This implementation uses AVX to compute internal nodes 4 at a time (in - * parallel) - */ -#define treehashx4 SPX_NAMESPACE(treehashx4) -void treehashx4(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leafx4)( - unsigned char * /* Where to write the leaves */, - const spx_ctx * /* ctx */, - uint32_t addr_idx, void *info), - uint32_t tree_addrx4[4 * 8], void *info); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/wots.c b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/wots.c deleted file mode 100644 index 4d5041ce05..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/wots.c +++ /dev/null @@ -1,269 +0,0 @@ -#include -#include - -#include "wots.h" - -#include "address.h" -#include "hash.h" -#include "hashx4.h" -#include "params.h" -#include "thash.h" -#include "thashx4.h" -#include "utils.h" -#include "utilsx4.h" -#include "wotsx4.h" - -// TODO clarify address expectations, and make them more uniform. -// TODO i.e. do we expect types to be set already? -// TODO and do we expect modifications or copies? - -/** - * Computes up the chains - */ -static void gen_chains( - unsigned char *out, - const unsigned char *in, - unsigned int start[SPX_WOTS_LEN], - const unsigned int steps[SPX_WOTS_LEN], - const spx_ctx *ctx, - uint32_t addr[8]) { - uint32_t i, j, k, idx, watching; - int done; - unsigned char empty[SPX_N]; - unsigned char *bufs[4]; - uint32_t addrs[8 * 4]; - - int l; - uint16_t counts[SPX_WOTS_W] = { 0 }; - uint16_t idxs[SPX_WOTS_LEN]; - uint16_t total, newTotal; - - /* set addrs = {addr, addr, addr, addr} */ - for (j = 0; j < 4; j++) { - memcpy(addrs + j * 8, addr, sizeof(uint32_t) * 8); - } - - /* Initialize out with the value at position 'start'. */ - memcpy(out, in, SPX_WOTS_LEN * SPX_N); - - /* Sort the chains in reverse order by steps using counting sort. */ - for (i = 0; i < SPX_WOTS_LEN; i++) { - counts[steps[i]]++; - } - total = 0; - for (l = SPX_WOTS_W - 1; l >= 0; l--) { - newTotal = counts[l] + total; - counts[l] = total; - total = newTotal; - } - for (i = 0; i < SPX_WOTS_LEN; i++) { - idxs[counts[steps[i]]] = (uint16_t)i; - counts[steps[i]]++; - } - - /* We got our work cut out for us: do it! */ - for (i = 0; i < SPX_WOTS_LEN; i += 4) { - for (j = 0; j < 4 && i + j < SPX_WOTS_LEN; j++) { - idx = idxs[i + j]; - set_chain_addr(addrs + j * 8, idx); - bufs[j] = out + SPX_N * idx; - } - - /* As the chains are sorted in reverse order, we know that the first - * chain is the longest and the last one is the shortest. We keep - * an eye on whether the last chain is done and then on the one before, - * et cetera. */ - watching = 3; - done = 0; - while (i + watching >= SPX_WOTS_LEN) { - bufs[watching] = &empty[0]; - watching--; - } - - for (k = 0;; k++) { - while (k == steps[idxs[i + watching]]) { - bufs[watching] = &empty[0]; - if (watching == 0) { - done = 1; - break; - } - watching--; - } - if (done) { - break; - } - for (j = 0; j < watching + 1; j++) { - set_hash_addr(addrs + j * 8, k + start[idxs[i + j]]); - } - - thashx4(bufs[0], bufs[1], bufs[2], bufs[3], - bufs[0], bufs[1], bufs[2], bufs[3], 1, ctx, addrs); - } - } -} - -/** - * base_w algorithm as described in draft. - * Interprets an array of bytes as integers in base w. - * This only works when log_w is a divisor of 8. - */ -static void base_w(unsigned int *output, const int out_len, - const unsigned char *input) { - int in = 0; - int out = 0; - unsigned char total = 0; - int bits = 0; - int consumed; - - for (consumed = 0; consumed < out_len; consumed++) { - if (bits == 0) { - total = input[in]; - in++; - bits += 8; - } - bits -= SPX_WOTS_LOGW; - output[out] = (total >> bits) & (SPX_WOTS_W - 1); - out++; - } -} - -/* Computes the WOTS+ checksum over a message (in base_w). */ -static void wots_checksum(unsigned int *csum_base_w, - const unsigned int *msg_base_w) { - unsigned int csum = 0; - unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; - unsigned int i; - - /* Compute checksum. */ - for (i = 0; i < SPX_WOTS_LEN1; i++) { - csum += SPX_WOTS_W - 1 - msg_base_w[i]; - } - - /* Convert checksum to base_w. */ - /* Make sure expected empty zero bits are the least significant bits. */ - csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); - ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); - base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); -} - -/* Takes a message and derives the matching chain lengths. */ -void chain_lengths(unsigned int *lengths, const unsigned char *msg) { - base_w(lengths, SPX_WOTS_LEN1, msg); - wots_checksum(lengths + SPX_WOTS_LEN1, lengths); -} - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const spx_ctx *ctx, uint32_t addr[8]) { - unsigned int steps[SPX_WOTS_LEN]; - unsigned int start[SPX_WOTS_LEN]; - uint32_t i; - - chain_lengths(start, msg); - - for (i = 0; i < SPX_WOTS_LEN; i++) { - steps[i] = SPX_WOTS_W - 1 - start[i]; - } - - gen_chains(pk, sig, start, steps, ctx, addr); -} - -/* - * This generates 4 sequential WOTS public keys - * It also generates the WOTS signature if leaf_info indicates - * that we're signing with one of these WOTS keys - */ -void wots_gen_leafx4(unsigned char *dest, - const spx_ctx *ctx, - uint32_t leaf_idx, void *v_info) { - struct leaf_info_x4 *info = v_info; - uint32_t *leaf_addr = info->leaf_addr; - uint32_t *pk_addr = info->pk_addr; - unsigned int i, j, k; - unsigned char pk_buffer[ 4 * SPX_WOTS_BYTES ]; - unsigned wots_offset = SPX_WOTS_BYTES; - unsigned char *buffer; - uint32_t wots_k_mask; - unsigned wots_sign_index; - - if (((leaf_idx ^ info->wots_sign_leaf) & ~3U) == 0) { - /* We're traversing the leaf that's signing; generate the WOTS */ - /* signature */ - wots_k_mask = 0; - wots_sign_index = info->wots_sign_leaf & 3; /* Which of of the 4 */ - /* 4 slots do the signatures come from */ - } else { - /* Nope, we're just generating pk's; turn off the signature logic */ - wots_k_mask = (uint32_t)~0; - wots_sign_index = 0; - } - - for (j = 0; j < 4; j++) { - set_keypair_addr( leaf_addr + j * 8, leaf_idx + j ); - set_keypair_addr( pk_addr + j * 8, leaf_idx + j ); - } - - for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { - uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k to */ - /* the step if we're generating a signature, ~0 if we're not */ - - /* Start with the secret seed */ - for (j = 0; j < 4; j++) { - set_chain_addr(leaf_addr + j * 8, i); - set_hash_addr(leaf_addr + j * 8, 0); - set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTSPRF); - } - prf_addrx4(buffer + 0 * wots_offset, - buffer + 1 * wots_offset, - buffer + 2 * wots_offset, - buffer + 3 * wots_offset, - ctx, leaf_addr); - - for (j = 0; j < 4; j++) { - set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTS); - } - - /* Iterate down the WOTS chain */ - for (k = 0;; k++) { - /* Check if one of the values we have needs to be saved as a */ - /* part of the WOTS signature */ - if (k == wots_k) { - memcpy( info->wots_sig + i * SPX_N, - buffer + wots_sign_index * wots_offset, SPX_N ); - } - - /* Check if we hit the top of the chain */ - if (k == SPX_WOTS_W - 1) { - break; - } - - /* Iterate one step on all 4 chains */ - for (j = 0; j < 4; j++) { - set_hash_addr(leaf_addr + j * 8, k); - } - thashx4(buffer + 0 * wots_offset, - buffer + 1 * wots_offset, - buffer + 2 * wots_offset, - buffer + 3 * wots_offset, - buffer + 0 * wots_offset, - buffer + 1 * wots_offset, - buffer + 2 * wots_offset, - buffer + 3 * wots_offset, 1, ctx, leaf_addr); - } - } - - /* Do the final thash to generate the public keys */ - thashx4(dest + 0 * SPX_N, - dest + 1 * SPX_N, - dest + 2 * SPX_N, - dest + 3 * SPX_N, - pk_buffer + 0 * wots_offset, - pk_buffer + 1 * wots_offset, - pk_buffer + 2 * wots_offset, - pk_buffer + 3 * wots_offset, SPX_WOTS_LEN, ctx, pk_addr); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/wots.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/wots.h deleted file mode 100644 index 4e7692eeef..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/wots.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef SPX_WOTS_H -#define SPX_WOTS_H - -#include - -#include "context.h" -#include "params.h" - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) -void wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const spx_ctx *ctx, uint32_t addr[8]); - -/* - * Compute the chain lengths needed for a given message hash - */ -#define chain_lengths SPX_NAMESPACE(chain_lengths) -void chain_lengths(unsigned int *lengths, const unsigned char *msg); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/wotsx4.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/wotsx4.h deleted file mode 100644 index cd634f1743..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_aesni/wotsx4.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef WOTSX4_H_ -#define WOTSX4_H_ - -#include - -#include "params.h" - -/* - * This is here to provide an interface to the internal wots_gen_leafx4 - * routine. While this routine is not referenced in the package outside of - * wots.c, it is called from the stand-alone benchmark code to characterize - * the performance - */ -struct leaf_info_x4 { - unsigned char *wots_sig; - uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ - uint32_t *wots_steps; - uint32_t leaf_addr[4 * 8]; - uint32_t pk_addr[4 * 8]; -}; - -/* Macro to set the leaf_info to something 'benign', that is, it would */ -/* run with the same time as it does during the real signing process */ -/* Used only by the benchmark code */ -#define INITIALIZE_LEAF_INFO_X4(info, addr, step_buffer) { \ - (info).wots_sig = 0; \ - (info).wots_sign_leaf = ~0; \ - (info).wots_steps = step_buffer; \ - int i; \ - for (i=0; i<4; i++) { \ - memcpy( &(info).leaf_addr[8*i], addr, 32 ); \ - memcpy( &(info).pk_addr[8*i], addr, 32 ); \ - } \ - } - -#define wots_gen_leafx4 SPX_NAMESPACE(wots_gen_leafx4) -void wots_gen_leafx4(unsigned char *dest, - const spx_ctx *ctx, - uint32_t leaf_idx, void *v_info); - -#endif /* WOTSX4_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/LICENSE b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/LICENSE deleted file mode 100644 index 670154e353..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/LICENSE +++ /dev/null @@ -1,116 +0,0 @@ -CC0 1.0 Universal - -Statement of Purpose - -The laws of most jurisdictions throughout the world automatically confer -exclusive Copyright and Related Rights (defined below) upon the creator and -subsequent owner(s) (each and all, an "owner") of an original work of -authorship and/or a database (each, a "Work"). - -Certain owners wish to permanently relinquish those rights to a Work for the -purpose of contributing to a commons of creative, cultural and scientific -works ("Commons") that the public can reliably and without fear of later -claims of infringement build upon, modify, incorporate in other works, reuse -and redistribute as freely as possible in any form whatsoever and for any -purposes, including without limitation commercial purposes. These owners may -contribute to the Commons to promote the ideal of a free culture and the -further production of creative, cultural and scientific works, or to gain -reputation or greater distribution for their Work in part through the use and -efforts of others. - -For these and/or other purposes and motivations, and without any expectation -of additional consideration or compensation, the person associating CC0 with a -Work (the "Affirmer"), to the extent that he or she is an owner of Copyright -and Related Rights in the Work, voluntarily elects to apply CC0 to the Work -and publicly distribute the Work under its terms, with knowledge of his or her -Copyright and Related Rights in the Work and the meaning and intended legal -effect of CC0 on those rights. - -1. Copyright and Related Rights. A Work made available under CC0 may be -protected by copyright and related or neighboring rights ("Copyright and -Related Rights"). Copyright and Related Rights include, but are not limited -to, the following: - - i. the right to reproduce, adapt, distribute, perform, display, communicate, - and translate a Work; - - ii. moral rights retained by the original author(s) and/or performer(s); - - iii. publicity and privacy rights pertaining to a person's image or likeness - depicted in a Work; - - iv. rights protecting against unfair competition in regards to a Work, - subject to the limitations in paragraph 4(a), below; - - v. rights protecting the extraction, dissemination, use and reuse of data in - a Work; - - vi. database rights (such as those arising under Directive 96/9/EC of the - European Parliament and of the Council of 11 March 1996 on the legal - protection of databases, and under any national implementation thereof, - including any amended or successor version of such directive); and - - vii. other similar, equivalent or corresponding rights throughout the world - based on applicable law or treaty, and any national implementations thereof. - -2. Waiver. To the greatest extent permitted by, but not in contravention of, -applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and -unconditionally waives, abandons, and surrenders all of Affirmer's Copyright -and Related Rights and associated claims and causes of action, whether now -known or unknown (including existing as well as future claims and causes of -action), in the Work (i) in all territories worldwide, (ii) for the maximum -duration provided by applicable law or treaty (including future time -extensions), (iii) in any current or future medium and for any number of -copies, and (iv) for any purpose whatsoever, including without limitation -commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes -the Waiver for the benefit of each member of the public at large and to the -detriment of Affirmer's heirs and successors, fully intending that such Waiver -shall not be subject to revocation, rescission, cancellation, termination, or -any other legal or equitable action to disrupt the quiet enjoyment of the Work -by the public as contemplated by Affirmer's express Statement of Purpose. - -3. Public License Fallback. Should any part of the Waiver for any reason be -judged legally invalid or ineffective under applicable law, then the Waiver -shall be preserved to the maximum extent permitted taking into account -Affirmer's express Statement of Purpose. In addition, to the extent the Waiver -is so judged Affirmer hereby grants to each affected person a royalty-free, -non transferable, non sublicensable, non exclusive, irrevocable and -unconditional license to exercise Affirmer's Copyright and Related Rights in -the Work (i) in all territories worldwide, (ii) for the maximum duration -provided by applicable law or treaty (including future time extensions), (iii) -in any current or future medium and for any number of copies, and (iv) for any -purpose whatsoever, including without limitation commercial, advertising or -promotional purposes (the "License"). The License shall be deemed effective as -of the date CC0 was applied by Affirmer to the Work. Should any part of the -License for any reason be judged legally invalid or ineffective under -applicable law, such partial invalidity or ineffectiveness shall not -invalidate the remainder of the License, and in such case Affirmer hereby -affirms that he or she will not (i) exercise any of his or her remaining -Copyright and Related Rights in the Work or (ii) assert any associated claims -and causes of action with respect to the Work, in either case contrary to -Affirmer's express Statement of Purpose. - -4. Limitations and Disclaimers. - - a. No trademark or patent rights held by Affirmer are waived, abandoned, - surrendered, licensed or otherwise affected by this document. - - b. Affirmer offers the Work as-is and makes no representations or warranties - of any kind concerning the Work, express, implied, statutory or otherwise, - including without limitation warranties of title, merchantability, fitness - for a particular purpose, non infringement, or the absence of latent or - other defects, accuracy, or the present or absence of errors, whether or not - discoverable, all to the greatest extent permissible under applicable law. - - c. Affirmer disclaims responsibility for clearing rights of other persons - that may apply to the Work or any use thereof, including without limitation - any person's Copyright and Related Rights in the Work. Further, Affirmer - disclaims responsibility for obtaining any necessary consents, permissions - or other rights required for any use of the Work. - - d. Affirmer understands and acknowledges that Creative Commons is not a - party to this document and has no duty or obligation with respect to this - CC0 or use of the Work. - -For more information, please see - diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/address.c b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/address.c deleted file mode 100644 index b956e9cb29..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/address.c +++ /dev/null @@ -1,91 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "utils.h" - -/* - * Specify which level of Merkle tree (the "layer") we're working on - */ -void set_layer_addr(uint32_t addr[8], uint32_t layer) { - ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; -} - -/* - * Specify which Merkle tree within the level (the "tree address") we're working on - */ -void set_tree_addr(uint32_t addr[8], uint64_t tree) { - ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); -} - -/* - * Specify the reason we'll use this address structure for, that is, what - * hash will we compute with it. This is used so that unrelated types of - * hashes don't accidentally get the same address structure. The type will be - * one of the SPX_ADDR_TYPE constants - */ -void set_type(uint32_t addr[8], uint32_t type) { - ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; -} - -/* - * Copy the layer and tree fields of the address structure. This is used - * when we're doing multiple types of hashes within the same Merkle tree - */ -void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { - memcpy( out, in, SPX_OFFSET_TREE + 8 ); -} - -/* These functions are used for OTS addresses. */ - -/* - * Specify which Merkle leaf we're working on; that is, which OTS keypair - * we're talking about. - */ -void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { - ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; -} - -/* - * Copy the layer, tree and keypair fields of the address structure. This is - * used when we're doing multiple things within the same OTS keypair - */ -void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { - memcpy( out, in, SPX_OFFSET_TREE + 8 ); - ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; -} - -/* - * Specify which Merkle chain within the OTS we're working with - * (the chain address) - */ -void set_chain_addr(uint32_t addr[8], uint32_t chain) { - ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; -} - -/* - * Specify where in the Merkle chain we are -* (the hash address) - */ -void set_hash_addr(uint32_t addr[8], uint32_t hash) { - ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; -} - -/* These functions are used for all hash tree addresses (including FORS). */ - -/* - * Specify the height of the node in the Merkle/FORS tree we are in - * (the tree height) - */ -void set_tree_height(uint32_t addr[8], uint32_t tree_height) { - ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; -} - -/* - * Specify the distance from the left edge of the node in the Merkle/FORS tree - * (the tree index) - */ -void set_tree_index(uint32_t addr[8], uint32_t tree_index) { - u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/address.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/address.h deleted file mode 100644 index 24a84eb40c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/address.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef SPX_ADDRESS_H -#define SPX_ADDRESS_H - -#include - -#include "params.h" - -/* The hash types that are passed to set_type */ -#define SPX_ADDR_TYPE_WOTS 0 -#define SPX_ADDR_TYPE_WOTSPK 1 -#define SPX_ADDR_TYPE_HASHTREE 2 -#define SPX_ADDR_TYPE_FORSTREE 3 -#define SPX_ADDR_TYPE_FORSPK 4 -#define SPX_ADDR_TYPE_WOTSPRF 5 -#define SPX_ADDR_TYPE_FORSPRF 6 - -#define set_layer_addr SPX_NAMESPACE(set_layer_addr) -void set_layer_addr(uint32_t addr[8], uint32_t layer); - -#define set_tree_addr SPX_NAMESPACE(set_tree_addr) -void set_tree_addr(uint32_t addr[8], uint64_t tree); - -#define set_type SPX_NAMESPACE(set_type) -void set_type(uint32_t addr[8], uint32_t type); - -/* Copies the layer and tree part of one address into the other */ -#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) -void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for WOTS and FORS addresses. */ - -#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) -void set_keypair_addr(uint32_t addr[8], uint32_t keypair); - -#define set_chain_addr SPX_NAMESPACE(set_chain_addr) -void set_chain_addr(uint32_t addr[8], uint32_t chain); - -#define set_hash_addr SPX_NAMESPACE(set_hash_addr) -void set_hash_addr(uint32_t addr[8], uint32_t hash); - -#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) -void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for all hash tree addresses (including FORS). */ - -#define set_tree_height SPX_NAMESPACE(set_tree_height) -void set_tree_height(uint32_t addr[8], uint32_t tree_height); - -#define set_tree_index SPX_NAMESPACE(set_tree_index) -void set_tree_index(uint32_t addr[8], uint32_t tree_index); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/api.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/api.h deleted file mode 100644 index 50690ddb7c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/api.h +++ /dev/null @@ -1,77 +0,0 @@ -#ifndef PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_API_H -#define PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_API_H - -#include -#include - -#define PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_CRYPTO_ALGNAME "SPHINCS+-haraka-256s-simple" - -#define PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_CRYPTO_SECRETKEYBYTES 128 -#define PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_CRYPTO_PUBLICKEYBYTES 64 -#define PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_CRYPTO_BYTES 29792 - -#define PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_CRYPTO_SEEDBYTES 96 - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, - const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk); -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/context.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/context.h deleted file mode 100644 index 600dfb73c7..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/context.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef SPX_CONTEXT_H -#define SPX_CONTEXT_H - -#include -#include - -#include "params.h" - -typedef struct { - uint8_t pub_seed[SPX_N]; - uint8_t sk_seed[SPX_N]; - - - uint64_t tweaked512_rc64[10][8]; - uint32_t tweaked256_rc32[10][8]; -} spx_ctx; - -#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) -void initialize_hash_function(spx_ctx *ctx); - -#define free_hash_function SPX_NAMESPACE(free_hash_function) -void free_hash_function(spx_ctx *ctx); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/context_haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/context_haraka.c deleted file mode 100644 index f1cd7e3664..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/context_haraka.c +++ /dev/null @@ -1,11 +0,0 @@ -#include "context.h" -#include "haraka.h" - -void initialize_hash_function(spx_ctx *ctx) { - tweak_constants(ctx); -} - -// we don't support heap-based haraka right now -void free_hash_function(spx_ctx *ctx) { - (void)ctx; // suppress unused variable warnings -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/fors.c b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/fors.c deleted file mode 100644 index 96ca72e986..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/fors.c +++ /dev/null @@ -1,156 +0,0 @@ -#include -#include -#include - -#include "fors.h" - -#include "address.h" -#include "hash.h" -#include "thash.h" -#include "utils.h" -#include "utilsx1.h" - -static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, - uint32_t fors_leaf_addr[8]) { - prf_addr(sk, ctx, fors_leaf_addr); -} - -static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, - const spx_ctx *ctx, - uint32_t fors_leaf_addr[8]) { - thash(leaf, sk, 1, ctx, fors_leaf_addr); -} - -struct fors_gen_leaf_info { - uint32_t leaf_addrx[8]; -}; - -static void fors_gen_leafx1(unsigned char *leaf, - const spx_ctx *ctx, - uint32_t addr_idx, void *info) { - struct fors_gen_leaf_info *fors_info = info; - uint32_t *fors_leaf_addr = fors_info->leaf_addrx; - - /* Only set the parts that the caller doesn't set */ - set_tree_index(fors_leaf_addr, addr_idx); - set_type(fors_leaf_addr, SPX_ADDR_TYPE_FORSPRF); - fors_gen_sk(leaf, ctx, fors_leaf_addr); - - set_type(fors_leaf_addr, SPX_ADDR_TYPE_FORSTREE); - fors_sk_to_leaf(leaf, leaf, - ctx, fors_leaf_addr); -} - -/** - * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - * Assumes indices has space for SPX_FORS_TREES integers. - */ -static void message_to_indices(uint32_t *indices, const unsigned char *m) { - unsigned int i, j; - unsigned int offset = 0; - - for (i = 0; i < SPX_FORS_TREES; i++) { - indices[i] = 0; - for (j = 0; j < SPX_FORS_HEIGHT; j++) { - indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); - offset++; - } - } -} - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -void fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]) { - uint32_t indices[SPX_FORS_TREES]; - unsigned char roots[SPX_FORS_TREES * SPX_N]; - uint32_t fors_tree_addr[8] = {0}; - struct fors_gen_leaf_info fors_info = {0}; - uint32_t *fors_leaf_addr = fors_info.leaf_addrx; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - copy_keypair_addr(fors_tree_addr, fors_addr); - copy_keypair_addr(fors_leaf_addr, fors_addr); - - copy_keypair_addr(fors_pk_addr, fors_addr); - set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < SPX_FORS_TREES; i++) { - idx_offset = i * (1 << SPX_FORS_HEIGHT); - - set_tree_height(fors_tree_addr, 0); - set_tree_index(fors_tree_addr, indices[i] + idx_offset); - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); - - /* Include the secret key part that produces the selected leaf node. */ - fors_gen_sk(sig, ctx, fors_tree_addr); - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); - sig += SPX_N; - - /* Compute the authentication path for this leaf node. */ - treehashx1(roots + i * SPX_N, sig, ctx, - indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx1, - fors_tree_addr, &fors_info); - - sig += SPX_N * SPX_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); -} - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -void fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]) { - uint32_t indices[SPX_FORS_TREES]; - unsigned char roots[SPX_FORS_TREES * SPX_N]; - unsigned char leaf[SPX_N]; - uint32_t fors_tree_addr[8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - copy_keypair_addr(fors_tree_addr, fors_addr); - copy_keypair_addr(fors_pk_addr, fors_addr); - - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); - set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < SPX_FORS_TREES; i++) { - idx_offset = i * (1 << SPX_FORS_HEIGHT); - - set_tree_height(fors_tree_addr, 0); - set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Derive the leaf from the included secret key part. */ - fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); - sig += SPX_N; - - /* Derive the corresponding root node of this tree. */ - compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, - sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); - sig += SPX_N * SPX_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/fors.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/fors.h deleted file mode 100644 index 509140a178..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/fors.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef SPX_FORS_H -#define SPX_FORS_H - -#include - -#include "context.h" -#include "params.h" - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -#define fors_sign SPX_NAMESPACE(fors_sign) -void fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]); - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) -void fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/haraka.c deleted file mode 100644 index a4944913b5..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/haraka.c +++ /dev/null @@ -1,913 +0,0 @@ -/* - * Constant time implementation of the Haraka hash function. - * - * The bit-sliced implementation of the AES round functions are - * based on the AES implementation in BearSSL written - * by Thomas Pornin - */ - -#include -#include -#include -#include - -#include "haraka.h" -#include "utils.h" - -#define HARAKAS_RATE 32 - -static const uint64_t haraka512_rc64[10][8] = { - {0x24cf0ab9086f628b, 0xbdd6eeecc83b8382, 0xd96fb0306cdad0a7, 0xaace082ac8f95f89, 0x449d8e8870d7041f, 0x49bb2f80b2b3e2f8, 0x0569ae98d93bb258, 0x23dc9691e7d6a4b1}, - {0xd8ba10ede0fe5b6e, 0x7ecf7dbe424c7b8e, 0x6ea9949c6df62a31, 0xbf3f3c97ec9c313e, 0x241d03a196a1861e, 0xead3a51116e5a2ea, 0x77d479fcad9574e3, 0x18657a1af894b7a0}, - {0x10671e1a7f595522, 0xd9a00ff675d28c7b, 0x2f1edf0d2b9ba661, 0xb8ff58b8e3de45f9, 0xee29261da9865c02, 0xd1532aa4b50bdf43, 0x8bf858159b231bb1, 0xdf17439d22d4f599}, - {0xdd4b2f0870b918c0, 0x757a81f3b39b1bb6, 0x7a5c556898952e3f, 0x7dd70a16d915d87a, 0x3ae61971982b8301, 0xc3ab319e030412be, 0x17c0033ac094a8cb, 0x5a0630fc1a8dc4ef}, - {0x17708988c1632f73, 0xf92ddae090b44f4f, 0x11ac0285c43aa314, 0x509059941936b8ba, 0xd03e152fa2ce9b69, 0x3fbcbcb63a32998b, 0x6204696d692254f7, 0x915542ed93ec59b4}, - {0xf4ed94aa8879236e, 0xff6cb41cd38e03c0, 0x069b38602368aeab, 0x669495b820f0ddba, 0xf42013b1b8bf9e3d, 0xcf935efe6439734d, 0xbc1dcf42ca29e3f8, 0x7e6d3ed29f78ad67}, - {0xf3b0f6837ffcddaa, 0x3a76faef934ddf41, 0xcec7ae583a9c8e35, 0xe4dd18c68f0260af, 0x2c0e5df1ad398eaa, 0x478df5236ae22e8c, 0xfb944c46fe865f39, 0xaa48f82f028132ba}, - {0x231b9ae2b76aca77, 0x292a76a712db0b40, 0x5850625dc8134491, 0x73137dd469810fb5, 0x8a12a6a202a474fd, 0xd36fd9daa78bdb80, 0xb34c5e733505706f, 0xbaf1cdca818d9d96}, - {0x2e99781335e8c641, 0xbddfe5cce47d560e, 0xf74e9bf32e5e040c, 0x1d7a709d65996be9, 0x670df36a9cf66cdd, 0xd05ef84a176a2875, 0x0f888e828cb1c44e, 0x1a79e9c9727b052c}, - {0x83497348628d84de, 0x2e9387d51f22a754, 0xb000068da2f852d6, 0x378c9e1190fd6fe5, 0x870027c316de7293, 0xe51a9d4462e047bb, 0x90ecf7f8c6251195, 0x655953bfbed90a9c}, -}; - -static inline uint32_t br_dec32le(const unsigned char *src) { - return (uint32_t)src[0] - | ((uint32_t)src[1] << 8) - | ((uint32_t)src[2] << 16) - | ((uint32_t)src[3] << 24); -} - -static void br_range_dec32le(uint32_t *v, size_t num, const unsigned char *src) { - while (num-- > 0) { - *v ++ = br_dec32le(src); - src += 4; - } -} - -static inline void br_enc32le(unsigned char *dst, uint32_t x) { - dst[0] = (unsigned char)x; - dst[1] = (unsigned char)(x >> 8); - dst[2] = (unsigned char)(x >> 16); - dst[3] = (unsigned char)(x >> 24); -} - - -static void br_range_enc32le(unsigned char *dst, const uint32_t *v, size_t num) { - while (num-- > 0) { - br_enc32le(dst, *v ++); - dst += 4; - } -} - -static void br_aes_ct64_bitslice_Sbox(uint64_t *q) { - /* - * This S-box implementation is a straightforward translation of - * the circuit described by Boyar and Peralta in "A new - * combinational logic minimization technique with applications - * to cryptology" (https://eprint.iacr.org/2009/191.pdf). - * - * Note that variables x* (input) and s* (output) are numbered - * in "reverse" order (x0 is the high bit, x7 is the low bit). - */ - - uint64_t x0, x1, x2, x3, x4, x5, x6, x7; - uint64_t y1, y2, y3, y4, y5, y6, y7, y8, y9; - uint64_t y10, y11, y12, y13, y14, y15, y16, y17, y18, y19; - uint64_t y20, y21; - uint64_t z0, z1, z2, z3, z4, z5, z6, z7, z8, z9; - uint64_t z10, z11, z12, z13, z14, z15, z16, z17; - uint64_t t0, t1, t2, t3, t4, t5, t6, t7, t8, t9; - uint64_t t10, t11, t12, t13, t14, t15, t16, t17, t18, t19; - uint64_t t20, t21, t22, t23, t24, t25, t26, t27, t28, t29; - uint64_t t30, t31, t32, t33, t34, t35, t36, t37, t38, t39; - uint64_t t40, t41, t42, t43, t44, t45, t46, t47, t48, t49; - uint64_t t50, t51, t52, t53, t54, t55, t56, t57, t58, t59; - uint64_t t60, t61, t62, t63, t64, t65, t66, t67; - uint64_t s0, s1, s2, s3, s4, s5, s6, s7; - - x0 = q[7]; - x1 = q[6]; - x2 = q[5]; - x3 = q[4]; - x4 = q[3]; - x5 = q[2]; - x6 = q[1]; - x7 = q[0]; - - /* - * Top linear transformation. - */ - y14 = x3 ^ x5; - y13 = x0 ^ x6; - y9 = x0 ^ x3; - y8 = x0 ^ x5; - t0 = x1 ^ x2; - y1 = t0 ^ x7; - y4 = y1 ^ x3; - y12 = y13 ^ y14; - y2 = y1 ^ x0; - y5 = y1 ^ x6; - y3 = y5 ^ y8; - t1 = x4 ^ y12; - y15 = t1 ^ x5; - y20 = t1 ^ x1; - y6 = y15 ^ x7; - y10 = y15 ^ t0; - y11 = y20 ^ y9; - y7 = x7 ^ y11; - y17 = y10 ^ y11; - y19 = y10 ^ y8; - y16 = t0 ^ y11; - y21 = y13 ^ y16; - y18 = x0 ^ y16; - - /* - * Non-linear section. - */ - t2 = y12 & y15; - t3 = y3 & y6; - t4 = t3 ^ t2; - t5 = y4 & x7; - t6 = t5 ^ t2; - t7 = y13 & y16; - t8 = y5 & y1; - t9 = t8 ^ t7; - t10 = y2 & y7; - t11 = t10 ^ t7; - t12 = y9 & y11; - t13 = y14 & y17; - t14 = t13 ^ t12; - t15 = y8 & y10; - t16 = t15 ^ t12; - t17 = t4 ^ t14; - t18 = t6 ^ t16; - t19 = t9 ^ t14; - t20 = t11 ^ t16; - t21 = t17 ^ y20; - t22 = t18 ^ y19; - t23 = t19 ^ y21; - t24 = t20 ^ y18; - - t25 = t21 ^ t22; - t26 = t21 & t23; - t27 = t24 ^ t26; - t28 = t25 & t27; - t29 = t28 ^ t22; - t30 = t23 ^ t24; - t31 = t22 ^ t26; - t32 = t31 & t30; - t33 = t32 ^ t24; - t34 = t23 ^ t33; - t35 = t27 ^ t33; - t36 = t24 & t35; - t37 = t36 ^ t34; - t38 = t27 ^ t36; - t39 = t29 & t38; - t40 = t25 ^ t39; - - t41 = t40 ^ t37; - t42 = t29 ^ t33; - t43 = t29 ^ t40; - t44 = t33 ^ t37; - t45 = t42 ^ t41; - z0 = t44 & y15; - z1 = t37 & y6; - z2 = t33 & x7; - z3 = t43 & y16; - z4 = t40 & y1; - z5 = t29 & y7; - z6 = t42 & y11; - z7 = t45 & y17; - z8 = t41 & y10; - z9 = t44 & y12; - z10 = t37 & y3; - z11 = t33 & y4; - z12 = t43 & y13; - z13 = t40 & y5; - z14 = t29 & y2; - z15 = t42 & y9; - z16 = t45 & y14; - z17 = t41 & y8; - - /* - * Bottom linear transformation. - */ - t46 = z15 ^ z16; - t47 = z10 ^ z11; - t48 = z5 ^ z13; - t49 = z9 ^ z10; - t50 = z2 ^ z12; - t51 = z2 ^ z5; - t52 = z7 ^ z8; - t53 = z0 ^ z3; - t54 = z6 ^ z7; - t55 = z16 ^ z17; - t56 = z12 ^ t48; - t57 = t50 ^ t53; - t58 = z4 ^ t46; - t59 = z3 ^ t54; - t60 = t46 ^ t57; - t61 = z14 ^ t57; - t62 = t52 ^ t58; - t63 = t49 ^ t58; - t64 = z4 ^ t59; - t65 = t61 ^ t62; - t66 = z1 ^ t63; - s0 = t59 ^ t63; - s6 = t56 ^ ~t62; - s7 = t48 ^ ~t60; - t67 = t64 ^ t65; - s3 = t53 ^ t66; - s4 = t51 ^ t66; - s5 = t47 ^ t65; - s1 = t64 ^ ~s3; - s2 = t55 ^ ~t67; - - q[7] = s0; - q[6] = s1; - q[5] = s2; - q[4] = s3; - q[3] = s4; - q[2] = s5; - q[1] = s6; - q[0] = s7; -} - -static void br_aes_ct_bitslice_Sbox(uint32_t *q) { - /* - * This S-box implementation is a straightforward translation of - * the circuit described by Boyar and Peralta in "A new - * combinational logic minimization technique with applications - * to cryptology" (https://eprint.iacr.org/2009/191.pdf). - * - * Note that variables x* (input) and s* (output) are numbered - * in "reverse" order (x0 is the high bit, x7 is the low bit). - */ - - uint32_t x0, x1, x2, x3, x4, x5, x6, x7; - uint32_t y1, y2, y3, y4, y5, y6, y7, y8, y9; - uint32_t y10, y11, y12, y13, y14, y15, y16, y17, y18, y19; - uint32_t y20, y21; - uint32_t z0, z1, z2, z3, z4, z5, z6, z7, z8, z9; - uint32_t z10, z11, z12, z13, z14, z15, z16, z17; - uint32_t t0, t1, t2, t3, t4, t5, t6, t7, t8, t9; - uint32_t t10, t11, t12, t13, t14, t15, t16, t17, t18, t19; - uint32_t t20, t21, t22, t23, t24, t25, t26, t27, t28, t29; - uint32_t t30, t31, t32, t33, t34, t35, t36, t37, t38, t39; - uint32_t t40, t41, t42, t43, t44, t45, t46, t47, t48, t49; - uint32_t t50, t51, t52, t53, t54, t55, t56, t57, t58, t59; - uint32_t t60, t61, t62, t63, t64, t65, t66, t67; - uint32_t s0, s1, s2, s3, s4, s5, s6, s7; - - x0 = q[7]; - x1 = q[6]; - x2 = q[5]; - x3 = q[4]; - x4 = q[3]; - x5 = q[2]; - x6 = q[1]; - x7 = q[0]; - - /* - * Top linear transformation. - */ - y14 = x3 ^ x5; - y13 = x0 ^ x6; - y9 = x0 ^ x3; - y8 = x0 ^ x5; - t0 = x1 ^ x2; - y1 = t0 ^ x7; - y4 = y1 ^ x3; - y12 = y13 ^ y14; - y2 = y1 ^ x0; - y5 = y1 ^ x6; - y3 = y5 ^ y8; - t1 = x4 ^ y12; - y15 = t1 ^ x5; - y20 = t1 ^ x1; - y6 = y15 ^ x7; - y10 = y15 ^ t0; - y11 = y20 ^ y9; - y7 = x7 ^ y11; - y17 = y10 ^ y11; - y19 = y10 ^ y8; - y16 = t0 ^ y11; - y21 = y13 ^ y16; - y18 = x0 ^ y16; - - /* - * Non-linear section. - */ - t2 = y12 & y15; - t3 = y3 & y6; - t4 = t3 ^ t2; - t5 = y4 & x7; - t6 = t5 ^ t2; - t7 = y13 & y16; - t8 = y5 & y1; - t9 = t8 ^ t7; - t10 = y2 & y7; - t11 = t10 ^ t7; - t12 = y9 & y11; - t13 = y14 & y17; - t14 = t13 ^ t12; - t15 = y8 & y10; - t16 = t15 ^ t12; - t17 = t4 ^ t14; - t18 = t6 ^ t16; - t19 = t9 ^ t14; - t20 = t11 ^ t16; - t21 = t17 ^ y20; - t22 = t18 ^ y19; - t23 = t19 ^ y21; - t24 = t20 ^ y18; - - t25 = t21 ^ t22; - t26 = t21 & t23; - t27 = t24 ^ t26; - t28 = t25 & t27; - t29 = t28 ^ t22; - t30 = t23 ^ t24; - t31 = t22 ^ t26; - t32 = t31 & t30; - t33 = t32 ^ t24; - t34 = t23 ^ t33; - t35 = t27 ^ t33; - t36 = t24 & t35; - t37 = t36 ^ t34; - t38 = t27 ^ t36; - t39 = t29 & t38; - t40 = t25 ^ t39; - - t41 = t40 ^ t37; - t42 = t29 ^ t33; - t43 = t29 ^ t40; - t44 = t33 ^ t37; - t45 = t42 ^ t41; - z0 = t44 & y15; - z1 = t37 & y6; - z2 = t33 & x7; - z3 = t43 & y16; - z4 = t40 & y1; - z5 = t29 & y7; - z6 = t42 & y11; - z7 = t45 & y17; - z8 = t41 & y10; - z9 = t44 & y12; - z10 = t37 & y3; - z11 = t33 & y4; - z12 = t43 & y13; - z13 = t40 & y5; - z14 = t29 & y2; - z15 = t42 & y9; - z16 = t45 & y14; - z17 = t41 & y8; - - /* - * Bottom linear transformation. - */ - t46 = z15 ^ z16; - t47 = z10 ^ z11; - t48 = z5 ^ z13; - t49 = z9 ^ z10; - t50 = z2 ^ z12; - t51 = z2 ^ z5; - t52 = z7 ^ z8; - t53 = z0 ^ z3; - t54 = z6 ^ z7; - t55 = z16 ^ z17; - t56 = z12 ^ t48; - t57 = t50 ^ t53; - t58 = z4 ^ t46; - t59 = z3 ^ t54; - t60 = t46 ^ t57; - t61 = z14 ^ t57; - t62 = t52 ^ t58; - t63 = t49 ^ t58; - t64 = z4 ^ t59; - t65 = t61 ^ t62; - t66 = z1 ^ t63; - s0 = t59 ^ t63; - s6 = t56 ^ ~t62; - s7 = t48 ^ ~t60; - t67 = t64 ^ t65; - s3 = t53 ^ t66; - s4 = t51 ^ t66; - s5 = t47 ^ t65; - s1 = t64 ^ ~s3; - s2 = t55 ^ ~t67; - - q[7] = s0; - q[6] = s1; - q[5] = s2; - q[4] = s3; - q[3] = s4; - q[2] = s5; - q[1] = s6; - q[0] = s7; -} - -static void br_aes_ct_ortho(uint32_t *q) { -#define SWAPN_32(cl, ch, s, x, y) do { \ - uint32_t a, b; \ - a = (x); \ - b = (y); \ - (x) = (a & (uint32_t)(cl)) | ((b & (uint32_t)(cl)) << (s)); \ - (y) = ((a & (uint32_t)(ch)) >> (s)) | (b & (uint32_t)(ch)); \ - } while (0) - -#define SWAP2_32(x, y) SWAPN_32(0x55555555, 0xAAAAAAAA, 1, x, y) -#define SWAP4_32(x, y) SWAPN_32(0x33333333, 0xCCCCCCCC, 2, x, y) -#define SWAP8_32(x, y) SWAPN_32(0x0F0F0F0F, 0xF0F0F0F0, 4, x, y) - - SWAP2_32(q[0], q[1]); - SWAP2_32(q[2], q[3]); - SWAP2_32(q[4], q[5]); - SWAP2_32(q[6], q[7]); - - SWAP4_32(q[0], q[2]); - SWAP4_32(q[1], q[3]); - SWAP4_32(q[4], q[6]); - SWAP4_32(q[5], q[7]); - - SWAP8_32(q[0], q[4]); - SWAP8_32(q[1], q[5]); - SWAP8_32(q[2], q[6]); - SWAP8_32(q[3], q[7]); -} - -static inline void add_round_key32(uint32_t *q, const uint32_t *sk) { - q[0] ^= sk[0]; - q[1] ^= sk[1]; - q[2] ^= sk[2]; - q[3] ^= sk[3]; - q[4] ^= sk[4]; - q[5] ^= sk[5]; - q[6] ^= sk[6]; - q[7] ^= sk[7]; -} - -static inline void shift_rows32(uint32_t *q) { - int i; - - for (i = 0; i < 8; i++) { - uint32_t x; - - x = q[i]; - q[i] = (x & 0x000000FF) - | ((x & 0x0000FC00) >> 2) | ((x & 0x00000300) << 6) - | ((x & 0x00F00000) >> 4) | ((x & 0x000F0000) << 4) - | ((x & 0xC0000000) >> 6) | ((x & 0x3F000000) << 2); - } -} - -static inline uint32_t rotr16(uint32_t x) { - return (x << 16) | (x >> 16); -} - -static inline void mix_columns32(uint32_t *q) { - uint32_t q0, q1, q2, q3, q4, q5, q6, q7; - uint32_t r0, r1, r2, r3, r4, r5, r6, r7; - - q0 = q[0]; - q1 = q[1]; - q2 = q[2]; - q3 = q[3]; - q4 = q[4]; - q5 = q[5]; - q6 = q[6]; - q7 = q[7]; - r0 = (q0 >> 8) | (q0 << 24); - r1 = (q1 >> 8) | (q1 << 24); - r2 = (q2 >> 8) | (q2 << 24); - r3 = (q3 >> 8) | (q3 << 24); - r4 = (q4 >> 8) | (q4 << 24); - r5 = (q5 >> 8) | (q5 << 24); - r6 = (q6 >> 8) | (q6 << 24); - r7 = (q7 >> 8) | (q7 << 24); - - q[0] = q7 ^ r7 ^ r0 ^ rotr16(q0 ^ r0); - q[1] = q0 ^ r0 ^ q7 ^ r7 ^ r1 ^ rotr16(q1 ^ r1); - q[2] = q1 ^ r1 ^ r2 ^ rotr16(q2 ^ r2); - q[3] = q2 ^ r2 ^ q7 ^ r7 ^ r3 ^ rotr16(q3 ^ r3); - q[4] = q3 ^ r3 ^ q7 ^ r7 ^ r4 ^ rotr16(q4 ^ r4); - q[5] = q4 ^ r4 ^ r5 ^ rotr16(q5 ^ r5); - q[6] = q5 ^ r5 ^ r6 ^ rotr16(q6 ^ r6); - q[7] = q6 ^ r6 ^ r7 ^ rotr16(q7 ^ r7); -} - -static void br_aes_ct64_ortho(uint64_t *q) { -#define SWAPN(cl, ch, s, x, y) do { \ - uint64_t a, b; \ - a = (x); \ - b = (y); \ - (x) = (a & (uint64_t)(cl)) | ((b & (uint64_t)(cl)) << (s)); \ - (y) = ((a & (uint64_t)(ch)) >> (s)) | (b & (uint64_t)(ch)); \ - } while (0) - -#define SWAP2(x, y) SWAPN(0x5555555555555555, 0xAAAAAAAAAAAAAAAA, 1, x, y) -#define SWAP4(x, y) SWAPN(0x3333333333333333, 0xCCCCCCCCCCCCCCCC, 2, x, y) -#define SWAP8(x, y) SWAPN(0x0F0F0F0F0F0F0F0F, 0xF0F0F0F0F0F0F0F0, 4, x, y) - - SWAP2(q[0], q[1]); - SWAP2(q[2], q[3]); - SWAP2(q[4], q[5]); - SWAP2(q[6], q[7]); - - SWAP4(q[0], q[2]); - SWAP4(q[1], q[3]); - SWAP4(q[4], q[6]); - SWAP4(q[5], q[7]); - - SWAP8(q[0], q[4]); - SWAP8(q[1], q[5]); - SWAP8(q[2], q[6]); - SWAP8(q[3], q[7]); -} - - -static void br_aes_ct64_interleave_in(uint64_t *q0, uint64_t *q1, const uint32_t *w) { - uint64_t x0, x1, x2, x3; - - x0 = w[0]; - x1 = w[1]; - x2 = w[2]; - x3 = w[3]; - x0 |= (x0 << 16); - x1 |= (x1 << 16); - x2 |= (x2 << 16); - x3 |= (x3 << 16); - x0 &= (uint64_t)0x0000FFFF0000FFFF; - x1 &= (uint64_t)0x0000FFFF0000FFFF; - x2 &= (uint64_t)0x0000FFFF0000FFFF; - x3 &= (uint64_t)0x0000FFFF0000FFFF; - x0 |= (x0 << 8); - x1 |= (x1 << 8); - x2 |= (x2 << 8); - x3 |= (x3 << 8); - x0 &= (uint64_t)0x00FF00FF00FF00FF; - x1 &= (uint64_t)0x00FF00FF00FF00FF; - x2 &= (uint64_t)0x00FF00FF00FF00FF; - x3 &= (uint64_t)0x00FF00FF00FF00FF; - *q0 = x0 | (x2 << 8); - *q1 = x1 | (x3 << 8); -} - - -static void br_aes_ct64_interleave_out(uint32_t *w, uint64_t q0, uint64_t q1) { - uint64_t x0, x1, x2, x3; - - x0 = q0 & (uint64_t)0x00FF00FF00FF00FF; - x1 = q1 & (uint64_t)0x00FF00FF00FF00FF; - x2 = (q0 >> 8) & (uint64_t)0x00FF00FF00FF00FF; - x3 = (q1 >> 8) & (uint64_t)0x00FF00FF00FF00FF; - x0 |= (x0 >> 8); - x1 |= (x1 >> 8); - x2 |= (x2 >> 8); - x3 |= (x3 >> 8); - x0 &= (uint64_t)0x0000FFFF0000FFFF; - x1 &= (uint64_t)0x0000FFFF0000FFFF; - x2 &= (uint64_t)0x0000FFFF0000FFFF; - x3 &= (uint64_t)0x0000FFFF0000FFFF; - w[0] = (uint32_t)x0 | (uint32_t)(x0 >> 16); - w[1] = (uint32_t)x1 | (uint32_t)(x1 >> 16); - w[2] = (uint32_t)x2 | (uint32_t)(x2 >> 16); - w[3] = (uint32_t)x3 | (uint32_t)(x3 >> 16); -} - -static inline void add_round_key(uint64_t *q, const uint64_t *sk) { - q[0] ^= sk[0]; - q[1] ^= sk[1]; - q[2] ^= sk[2]; - q[3] ^= sk[3]; - q[4] ^= sk[4]; - q[5] ^= sk[5]; - q[6] ^= sk[6]; - q[7] ^= sk[7]; -} - -static inline void shift_rows(uint64_t *q) { - int i; - - for (i = 0; i < 8; i++) { - uint64_t x; - - x = q[i]; - q[i] = (x & (uint64_t)0x000000000000FFFF) - | ((x & (uint64_t)0x00000000FFF00000) >> 4) - | ((x & (uint64_t)0x00000000000F0000) << 12) - | ((x & (uint64_t)0x0000FF0000000000) >> 8) - | ((x & (uint64_t)0x000000FF00000000) << 8) - | ((x & (uint64_t)0xF000000000000000) >> 12) - | ((x & (uint64_t)0x0FFF000000000000) << 4); - } -} - -static inline uint64_t rotr32(uint64_t x) { - return (x << 32) | (x >> 32); -} - -static inline void mix_columns(uint64_t *q) { - uint64_t q0, q1, q2, q3, q4, q5, q6, q7; - uint64_t r0, r1, r2, r3, r4, r5, r6, r7; - - q0 = q[0]; - q1 = q[1]; - q2 = q[2]; - q3 = q[3]; - q4 = q[4]; - q5 = q[5]; - q6 = q[6]; - q7 = q[7]; - r0 = (q0 >> 16) | (q0 << 48); - r1 = (q1 >> 16) | (q1 << 48); - r2 = (q2 >> 16) | (q2 << 48); - r3 = (q3 >> 16) | (q3 << 48); - r4 = (q4 >> 16) | (q4 << 48); - r5 = (q5 >> 16) | (q5 << 48); - r6 = (q6 >> 16) | (q6 << 48); - r7 = (q7 >> 16) | (q7 << 48); - - q[0] = q7 ^ r7 ^ r0 ^ rotr32(q0 ^ r0); - q[1] = q0 ^ r0 ^ q7 ^ r7 ^ r1 ^ rotr32(q1 ^ r1); - q[2] = q1 ^ r1 ^ r2 ^ rotr32(q2 ^ r2); - q[3] = q2 ^ r2 ^ q7 ^ r7 ^ r3 ^ rotr32(q3 ^ r3); - q[4] = q3 ^ r3 ^ q7 ^ r7 ^ r4 ^ rotr32(q4 ^ r4); - q[5] = q4 ^ r4 ^ r5 ^ rotr32(q5 ^ r5); - q[6] = q5 ^ r5 ^ r6 ^ rotr32(q6 ^ r6); - q[7] = q6 ^ r6 ^ r7 ^ rotr32(q7 ^ r7); -} - -static void interleave_constant(uint64_t *out, const unsigned char *in) { - uint32_t tmp_32_constant[16]; - int i; - - br_range_dec32le(tmp_32_constant, 16, in); - for (i = 0; i < 4; i++) { - br_aes_ct64_interleave_in(&out[i], &out[i + 4], tmp_32_constant + (i << 2)); - } - br_aes_ct64_ortho(out); -} - -static void interleave_constant32(uint32_t *out, const unsigned char *in) { - int i; - for (i = 0; i < 4; i++) { - out[2 * i] = br_dec32le(in + 4 * i); - out[2 * i + 1] = br_dec32le(in + 4 * i + 16); - } - br_aes_ct_ortho(out); -} - -void tweak_constants(spx_ctx *ctx) { - unsigned char buf[40 * 16]; - int i; - - /* Use the standard constants to generate tweaked ones. */ - memcpy((uint8_t *)ctx->tweaked512_rc64, (uint8_t *)haraka512_rc64, 40 * 16); - - /* Constants for pk.seed */ - haraka_S(buf, 40 * 16, ctx->pub_seed, SPX_N, ctx); - for (i = 0; i < 10; i++) { - interleave_constant32(ctx->tweaked256_rc32[i], buf + 32 * i); - interleave_constant(ctx->tweaked512_rc64[i], buf + 64 * i); - } -} - -static void haraka_S_absorb(unsigned char *s, unsigned int r, - const unsigned char *m, unsigned long long mlen, - unsigned char p, const spx_ctx *ctx) { - unsigned long long i; - PQCLEAN_VLA(uint8_t, t, r); - - while (mlen >= r) { - /* XOR block to state */ - for (i = 0; i < r; ++i) { - s[i] ^= m[i]; - } - haraka512_perm(s, s, ctx); - 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; ++i) { - s[i] ^= t[i]; - } -} - -static void haraka_S_squeezeblocks(unsigned char *h, unsigned long long nblocks, - unsigned char *s, unsigned int r, - const spx_ctx *ctx) { - while (nblocks > 0) { - haraka512_perm(s, s, ctx); - memcpy(h, s, HARAKAS_RATE); - h += r; - nblocks--; - } -} - -void haraka_S_inc_init(uint8_t *s_inc) { - size_t i; - - for (i = 0; i < 64; i++) { - s_inc[i] = 0; - } - s_inc[64] = 0; -} - -void haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, - const spx_ctx *ctx) { - size_t i; - - /* Recall that s_inc[64] is the non-absorbed bytes xored into the state */ - while (mlen + s_inc[64] >= HARAKAS_RATE) { - for (i = 0; i < (size_t)(HARAKAS_RATE - s_inc[64]); i++) { - /* Take the i'th byte from message - xor with the s_inc[64] + i'th byte of the state */ - s_inc[s_inc[64] + i] ^= m[i]; - } - mlen -= (size_t)(HARAKAS_RATE - s_inc[64]); - m += HARAKAS_RATE - (uint8_t)s_inc[64]; - s_inc[64] = 0; - - haraka512_perm(s_inc, s_inc, ctx); - } - - for (i = 0; i < mlen; i++) { - s_inc[s_inc[64] + i] ^= m[i]; - } - s_inc[64] += (uint8_t)mlen; -} - -void haraka_S_inc_finalize(uint8_t *s_inc) { - /* After haraka_S_inc_absorb, we are guaranteed that s_inc[64] < HARAKAS_RATE, - so we can always use one more byte for p in the current state. */ - s_inc[s_inc[64]] ^= 0x1F; - s_inc[HARAKAS_RATE - 1] ^= 128; - s_inc[64] = 0; -} - -void haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, - const spx_ctx *ctx) { - size_t i; - - /* First consume any bytes we still have sitting around */ - for (i = 0; i < outlen && i < s_inc[64]; i++) { - /* There are s_inc[64] bytes left, so r - s_inc[64] is the first - available byte. We consume from there, i.e., up to r. */ - out[i] = (uint8_t)s_inc[(HARAKAS_RATE - s_inc[64] + i)]; - } - out += i; - outlen -= i; - s_inc[64] -= (uint8_t)i; - - /* Then squeeze the remaining necessary blocks */ - while (outlen > 0) { - haraka512_perm(s_inc, s_inc, ctx); - - for (i = 0; i < outlen && i < HARAKAS_RATE; i++) { - out[i] = s_inc[i]; - } - out += i; - outlen -= i; - s_inc[64] = (uint8_t)(HARAKAS_RATE - i); - } -} - -void haraka_S(unsigned char *out, unsigned long long outlen, - const unsigned char *in, unsigned long long inlen, - const spx_ctx *ctx) { - unsigned long long i; - unsigned char s[64]; - unsigned char d[32]; - - for (i = 0; i < 64; i++) { - s[i] = 0; - } - haraka_S_absorb(s, 32, in, inlen, 0x1F, ctx); - - haraka_S_squeezeblocks(out, outlen / 32, s, 32, ctx); - out += (outlen / 32) * 32; - - if (outlen % 32) { - haraka_S_squeezeblocks(d, 1, s, 32, ctx); - for (i = 0; i < outlen % 32; i++) { - out[i] = d[i]; - } - } -} - -void haraka512_perm(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx) { - uint32_t w[16]; - uint64_t q[8], tmp_q; - unsigned int i, j; - - br_range_dec32le(w, 16, in); - for (i = 0; i < 4; i++) { - br_aes_ct64_interleave_in(&q[i], &q[i + 4], w + (i << 2)); - } - br_aes_ct64_ortho(q); - - /* AES rounds */ - for (i = 0; i < 5; i++) { - for (j = 0; j < 2; j++) { - br_aes_ct64_bitslice_Sbox(q); - shift_rows(q); - mix_columns(q); - add_round_key(q, ctx->tweaked512_rc64[2 * i + j]); - } - /* Mix states */ - for (j = 0; j < 8; j++) { - tmp_q = q[j]; - q[j] = (tmp_q & 0x0001000100010001) << 5 | - (tmp_q & 0x0002000200020002) << 12 | - (tmp_q & 0x0004000400040004) >> 1 | - (tmp_q & 0x0008000800080008) << 6 | - (tmp_q & 0x0020002000200020) << 9 | - (tmp_q & 0x0040004000400040) >> 4 | - (tmp_q & 0x0080008000800080) << 3 | - (tmp_q & 0x2100210021002100) >> 5 | - (tmp_q & 0x0210021002100210) << 2 | - (tmp_q & 0x0800080008000800) << 4 | - (tmp_q & 0x1000100010001000) >> 12 | - (tmp_q & 0x4000400040004000) >> 10 | - (tmp_q & 0x8400840084008400) >> 3; - } - } - - br_aes_ct64_ortho(q); - for (i = 0; i < 4; i ++) { - br_aes_ct64_interleave_out(w + (i << 2), q[i], q[i + 4]); - } - br_range_enc32le(out, w, 16); -} - -void haraka512(unsigned char *out, const unsigned char *in, const spx_ctx *ctx) { - int i; - - unsigned char buf[64]; - - haraka512_perm(buf, in, ctx); - /* Feed-forward */ - for (i = 0; i < 64; i++) { - buf[i] = buf[i] ^ in[i]; - } - - /* Truncated */ - memcpy(out, buf + 8, 8); - memcpy(out + 8, buf + 24, 8); - memcpy(out + 16, buf + 32, 8); - memcpy(out + 24, buf + 48, 8); -} - - -void haraka256(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx) { - uint32_t q[8], tmp_q; - int i, j; - - for (i = 0; i < 4; i++) { - q[2 * i] = br_dec32le(in + 4 * i); - q[2 * i + 1] = br_dec32le(in + 4 * i + 16); - } - br_aes_ct_ortho(q); - - /* AES rounds */ - for (i = 0; i < 5; i++) { - for (j = 0; j < 2; j++) { - br_aes_ct_bitslice_Sbox(q); - shift_rows32(q); - mix_columns32(q); - add_round_key32(q, ctx->tweaked256_rc32[2 * i + j]); - } - - /* Mix states */ - for (j = 0; j < 8; j++) { - tmp_q = q[j]; - q[j] = (tmp_q & 0x81818181) | - (tmp_q & 0x02020202) << 1 | - (tmp_q & 0x04040404) << 2 | - (tmp_q & 0x08080808) << 3 | - (tmp_q & 0x10101010) >> 3 | - (tmp_q & 0x20202020) >> 2 | - (tmp_q & 0x40404040) >> 1; - } - } - - br_aes_ct_ortho(q); - for (i = 0; i < 4; i++) { - br_enc32le(out + 4 * i, q[2 * i]); - br_enc32le(out + 4 * i + 16, q[2 * i + 1]); - } - - for (i = 0; i < 32; i++) { - out[i] ^= in[i]; - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/haraka.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/haraka.h deleted file mode 100644 index 737cb6065f..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/haraka.h +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef SPX_HARAKA_H -#define SPX_HARAKA_H - -#include "context.h" -#include "params.h" - -/* Tweak constants with seed */ -#define tweak_constants SPX_NAMESPACE(tweak_constants) -void tweak_constants(spx_ctx *ctx); - -/* Haraka Sponge */ -#define haraka_S_inc_init SPX_NAMESPACE(haraka_S_inc_init) -void haraka_S_inc_init(uint8_t *s_inc); -#define haraka_S_inc_absorb SPX_NAMESPACE(haraka_S_inc_absorb) -void haraka_S_inc_absorb(uint8_t *s_inc, const uint8_t *m, size_t mlen, - const spx_ctx *ctx); -#define haraka_S_inc_finalize SPX_NAMESPACE(haraka_S_inc_finalize) -void haraka_S_inc_finalize(uint8_t *s_inc); -#define haraka_S_inc_squeeze SPX_NAMESPACE(haraka_S_inc_squeeze) -void haraka_S_inc_squeeze(uint8_t *out, size_t outlen, uint8_t *s_inc, - const spx_ctx *ctx); -#define haraka_S SPX_NAMESPACE(haraka_S) -void haraka_S(unsigned char *out, unsigned long long outlen, - const unsigned char *in, unsigned long long inlen, - const spx_ctx *ctx); - -/* Applies the 512-bit Haraka permutation to in. */ -#define haraka512_perm SPX_NAMESPACE(haraka512_perm) -void haraka512_perm(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx); - -/* Implementation of Haraka-512 */ -#define haraka512 SPX_NAMESPACE(haraka512) -void haraka512(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx); - -/* Implementation of Haraka-256 */ -#define haraka256 SPX_NAMESPACE(haraka256) -void haraka256(unsigned char *out, const unsigned char *in, - const spx_ctx *ctx); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/haraka_offsets.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/haraka_offsets.h deleted file mode 100644 index 7c062272a0..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/haraka_offsets.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef HARAKA_OFFSETS_H_ -#define HARAKA_OFFSETS_H_ - -/* - * Offsets of various fields in the address structure when we use Haraka as - * the Sphincs+ hash function - */ - -#define SPX_OFFSET_LAYER 3 /* The byte used to specify the Merkle tree layer */ -#define SPX_OFFSET_TREE 8 /* The start of the 8 byte field used to specify the tree */ -#define SPX_OFFSET_TYPE 19 /* The byte used to specify the hash type (reason) */ -#define SPX_OFFSET_KP_ADDR2 22 /* The high byte used to specify the key pair (which one-time signature) */ -#define SPX_OFFSET_KP_ADDR1 23 /* The low byte used to specify the key pair */ -#define SPX_OFFSET_CHAIN_ADDR 27 /* The byte used to specify the chain address (which Winternitz chain) */ -#define SPX_OFFSET_HASH_ADDR 31 /* The byte used to specify the hash address (where in the Winternitz chain) */ -#define SPX_OFFSET_TREE_HGT 27 /* The byte used to specify the height of this node in the FORS or Merkle tree */ -#define SPX_OFFSET_TREE_INDEX 28 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ - -#define SPX_HARAKA 1 - -#endif /* HARAKA_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/hash.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/hash.h deleted file mode 100644 index f7c87d4c3c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/hash.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef SPX_HASH_H -#define SPX_HASH_H - -#include -#include - -#include "context.h" -#include "params.h" - -#define prf_addr SPX_NAMESPACE(prf_addr) -void prf_addr(unsigned char *out, const spx_ctx *ctx, - const uint32_t addr[8]); - -#define gen_message_random SPX_NAMESPACE(gen_message_random) -void gen_message_random(unsigned char *R, const unsigned char *sk_prf, - const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx); - -#define hash_message SPX_NAMESPACE(hash_message) -void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx); - - - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/hash_haraka.c b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/hash_haraka.c deleted file mode 100644 index 750a67423b..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/hash_haraka.c +++ /dev/null @@ -1,81 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "utils.h" - -#include "haraka.h" -#include "hash.h" - -/* - * Computes PRF(key, addr), given a secret key of SPX_N bytes and an address - */ -void prf_addr(unsigned char *out, const spx_ctx *ctx, - const uint32_t addr[8]) { - /* Since SPX_N may be smaller than 32, we need temporary buffers. */ - unsigned char outbuf[32]; - unsigned char buf[64] = {0}; - - memcpy(buf, addr, SPX_ADDR_BYTES); - memcpy(buf + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); - - haraka512(outbuf, (const void *)buf, ctx); - memcpy(out, outbuf, SPX_N); -} - -/** - * Computes the message-dependent randomness R, using a secret seed and an - * optional randomization value as well as the message. - */ -void gen_message_random(unsigned char *R, const unsigned char *sk_prf, - const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx) { - uint8_t s_inc[65]; - - haraka_S_inc_init(s_inc); - haraka_S_inc_absorb(s_inc, sk_prf, SPX_N, ctx); - haraka_S_inc_absorb(s_inc, optrand, SPX_N, ctx); - haraka_S_inc_absorb(s_inc, m, mlen, ctx); - haraka_S_inc_finalize(s_inc); - haraka_S_inc_squeeze(R, SPX_N, s_inc, ctx); -} - -/** - * Computes the message hash using R, the public key, and the message. - * Outputs the message digest and the index of the leaf. The index is split in - * the tree index and the leaf index, for convenient copying to an address. - */ -void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx) { -#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) -#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) -#define SPX_LEAF_BITS SPX_TREE_HEIGHT -#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) -#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) - - unsigned char buf[SPX_DGST_BYTES]; - unsigned char *bufp = buf; - uint8_t s_inc[65]; - - haraka_S_inc_init(s_inc); - haraka_S_inc_absorb(s_inc, R, SPX_N, ctx); - haraka_S_inc_absorb(s_inc, pk + SPX_N, SPX_N, ctx); // Only absorb root part of pk - haraka_S_inc_absorb(s_inc, m, mlen, ctx); - haraka_S_inc_finalize(s_inc); - haraka_S_inc_squeeze(buf, SPX_DGST_BYTES, s_inc, ctx); - - memcpy(digest, bufp, SPX_FORS_MSG_BYTES); - bufp += SPX_FORS_MSG_BYTES; - - - *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); - *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); - bufp += SPX_TREE_BYTES; - - *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); - *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/merkle.c b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/merkle.c deleted file mode 100644 index 0c1479fd93..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/merkle.c +++ /dev/null @@ -1,59 +0,0 @@ -#include -#include - -#include "address.h" -#include "merkle.h" -#include "params.h" -#include "utils.h" -#include "utilsx1.h" -#include "wots.h" -#include "wotsx1.h" - -/* - * This generates a Merkle signature (WOTS signature followed by the Merkle - * authentication path). This is in this file because most of the complexity - * is involved with the WOTS signature; the Merkle authentication path logic - * is mostly hidden in treehashx4 - */ -void merkle_sign(uint8_t *sig, unsigned char *root, - const spx_ctx *ctx, - uint32_t wots_addr[8], uint32_t tree_addr[8], - uint32_t idx_leaf) { - unsigned char *auth_path = sig + SPX_WOTS_BYTES; - struct leaf_info_x1 info = { 0 }; - unsigned steps[ SPX_WOTS_LEN ]; - - info.wots_sig = sig; - chain_lengths(steps, root); - info.wots_steps = steps; - - set_type(&tree_addr[0], SPX_ADDR_TYPE_HASHTREE); - set_type(&info.pk_addr[0], SPX_ADDR_TYPE_WOTSPK); - copy_subtree_addr(&info.leaf_addr[0], wots_addr); - copy_subtree_addr(&info.pk_addr[0], wots_addr); - - info.wots_sign_leaf = idx_leaf; - - treehashx1(root, auth_path, ctx, - idx_leaf, 0, - SPX_TREE_HEIGHT, - wots_gen_leafx1, - tree_addr, &info); -} - -/* Compute root node of the top-most subtree. */ -void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { - /* We do not need the auth path in key generation, but it simplifies the - code to have just one treehash routine that computes both root and path - in one function. */ - unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; - uint32_t top_tree_addr[8] = {0}; - uint32_t wots_addr[8] = {0}; - - set_layer_addr(top_tree_addr, SPX_D - 1); - set_layer_addr(wots_addr, SPX_D - 1); - - merkle_sign(auth_path, root, ctx, - wots_addr, top_tree_addr, - (uint32_t)~0 /* ~0 means "don't bother generating an auth path */ ); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/merkle.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/merkle.h deleted file mode 100644 index 769cf2e970..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/merkle.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef MERKLE_H_ -#define MERKLE_H_ - -#include - -#include "context.h" -#include "params.h" - -/* Generate a Merkle signature (WOTS signature followed by the Merkle */ -/* authentication path) */ -#define merkle_sign SPX_NAMESPACE(merkle_sign) -void merkle_sign(uint8_t *sig, unsigned char *root, - const spx_ctx *ctx, - uint32_t wots_addr[8], uint32_t tree_addr[8], - uint32_t idx_leaf); - -/* Compute the root node of the top-most subtree. */ -#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) -void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); - -#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/nistapi.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/nistapi.h deleted file mode 100644 index 3cb71afad4..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/nistapi.h +++ /dev/null @@ -1,87 +0,0 @@ -#ifndef SPX_API_H -#define SPX_API_H - -#include -#include - -#include "params.h" - -#define CRYPTO_ALGNAME "SPHINCS+" - -#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES -#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES -#define CRYPTO_BYTES SPX_BYTES -#define CRYPTO_SEEDBYTES (3*SPX_N) - -/* - * Returns the length of a secret key, in bytes - */ -#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) -size_t crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) -size_t crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) -size_t crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) -size_t crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) -int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) -int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) -int crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) -int crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -#define crypto_sign SPX_NAMESPACE(crypto_sign) -int crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) -int crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/params.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/params.h deleted file mode 100644 index 89e496c816..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/params.h +++ /dev/null @@ -1,56 +0,0 @@ -#ifndef SPX_PARAMS_H -#define SPX_PARAMS_H - -#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_##s - -/* Hash output length in bytes. */ -#define SPX_N 32 -/* Height of the hypertree. */ -#define SPX_FULL_HEIGHT 64 -/* Number of subtree layer. */ -#define SPX_D 8 -/* FORS tree dimensions. */ -#define SPX_FORS_HEIGHT 14 -#define SPX_FORS_TREES 22 -/* Winternitz parameter, */ -#define SPX_WOTS_W 16 - -/* The hash function is defined by linking a different hash.c file, as opposed - to setting a #define constant. */ - -/* For clarity */ -#define SPX_ADDR_BYTES 32 - -/* WOTS parameters. */ -#define SPX_WOTS_LOGW 4 - -#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) - -/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#define SPX_WOTS_LEN2 3 - -#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) -#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) -#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES - -/* Subtree size. */ -#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) - -//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT -// #error SPX_D should always divide SPX_FULL_HEIGHT -//#endif - -/* FORS parameters. */ -#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) -#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) -#define SPX_FORS_PK_BYTES SPX_N - -/* Resulting SPX sizes. */ -#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ - SPX_FULL_HEIGHT * SPX_N) -#define SPX_PK_BYTES (2 * SPX_N) -#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) - -#include "haraka_offsets.h" - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/sign.c b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/sign.c deleted file mode 100644 index 9d0c7d1b22..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/sign.c +++ /dev/null @@ -1,286 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "context.h" -#include "fors.h" -#include "hash.h" -#include "merkle.h" -#include "nistapi.h" -#include "params.h" -#include "randombytes.h" -#include "thash.h" -#include "utils.h" -#include "wots.h" - -/* - * Returns the length of a secret key, in bytes - */ -size_t crypto_sign_secretkeybytes(void) { - return CRYPTO_SECRETKEYBYTES; -} - -/* - * Returns the length of a public key, in bytes - */ -size_t crypto_sign_publickeybytes(void) { - return CRYPTO_PUBLICKEYBYTES; -} - -/* - * Returns the length of a signature, in bytes - */ -size_t crypto_sign_bytes(void) { - return CRYPTO_BYTES; -} - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t crypto_sign_seedbytes(void) { - return CRYPTO_SEEDBYTES; -} - -/* - * Generates an SPX key pair given a seed of length - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed) { - spx_ctx ctx; - - /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ - memcpy(sk, seed, CRYPTO_SEEDBYTES); - - memcpy(pk, sk + 2 * SPX_N, SPX_N); - - memcpy(ctx.pub_seed, pk, SPX_N); - memcpy(ctx.sk_seed, sk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - /* Compute root node of the top-most subtree. */ - merkle_gen_root(sk + 3 * SPX_N, &ctx); - - // cleanup - free_hash_function(&ctx); - - memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); - - return 0; -} - -/* - * Generates an SPX key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { - uint8_t seed[CRYPTO_SEEDBYTES]; - randombytes(seed, CRYPTO_SEEDBYTES); - crypto_sign_seed_keypair(pk, sk, seed); - - return 0; -} - -/** - * Returns an array containing a detached signature. - */ -int crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - spx_ctx ctx; - - const uint8_t *sk_prf = sk + SPX_N; - const uint8_t *pk = sk + 2 * SPX_N; - - uint8_t optrand[SPX_N]; - uint8_t mhash[SPX_FORS_MSG_BYTES]; - uint8_t root[SPX_N]; - uint32_t i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - - memcpy(ctx.sk_seed, sk, SPX_N); - memcpy(ctx.pub_seed, pk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - set_type(wots_addr, SPX_ADDR_TYPE_WOTS); - set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); - - /* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ - randombytes(optrand, SPX_N); - /* Compute the digest randomization value. */ - gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); - - /* Derive the message digest and leaf index from R, PK and M. */ - hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); - sig += SPX_N; - - set_tree_addr(wots_addr, tree); - set_keypair_addr(wots_addr, idx_leaf); - - /* Sign the message hash using FORS. */ - fors_sign(sig, root, mhash, &ctx, wots_addr); - sig += SPX_FORS_BYTES; - - for (i = 0; i < SPX_D; i++) { - set_layer_addr(tree_addr, i); - set_tree_addr(tree_addr, tree); - - copy_subtree_addr(wots_addr, tree_addr); - set_keypair_addr(wots_addr, idx_leaf); - - merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); - sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); - tree = tree >> SPX_TREE_HEIGHT; - } - - free_hash_function(&ctx); - - *siglen = SPX_BYTES; - - return 0; -} - -/** - * Verifies a detached signature and message under a given public key. - */ -int crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk) { - spx_ctx ctx; - const uint8_t *pub_root = pk + SPX_N; - uint8_t mhash[SPX_FORS_MSG_BYTES]; - uint8_t wots_pk[SPX_WOTS_BYTES]; - uint8_t root[SPX_N]; - uint8_t leaf[SPX_N]; - unsigned int i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - if (siglen != SPX_BYTES) { - return -1; - } - - memcpy(ctx.pub_seed, pk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - set_type(wots_addr, SPX_ADDR_TYPE_WOTS); - set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); - set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); - - /* Derive the message digest and leaf index from R || PK || M. */ - /* The additional SPX_N is a result of the hash domain separator. */ - hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); - sig += SPX_N; - - /* Layer correctly defaults to 0, so no need to set_layer_addr */ - set_tree_addr(wots_addr, tree); - set_keypair_addr(wots_addr, idx_leaf); - - fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); - sig += SPX_FORS_BYTES; - - /* For each subtree.. */ - for (i = 0; i < SPX_D; i++) { - set_layer_addr(tree_addr, i); - set_tree_addr(tree_addr, tree); - - copy_subtree_addr(wots_addr, tree_addr); - set_keypair_addr(wots_addr, idx_leaf); - - copy_keypair_addr(wots_pk_addr, wots_addr); - - /* The WOTS public key is only correct if the signature was correct. */ - /* Initially, root is the FORS pk, but on subsequent iterations it is - the root of the subtree below the currently processed subtree. */ - wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); - sig += SPX_WOTS_BYTES; - - /* Compute the leaf node using the WOTS public key. */ - thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); - - /* Compute the root node of this subtree. */ - compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, - &ctx, tree_addr); - sig += SPX_TREE_HEIGHT * SPX_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); - tree = tree >> SPX_TREE_HEIGHT; - } - - // cleanup - free_hash_function(&ctx); - - /* Check if the root node equals the root node in the public key. */ - if (memcmp(root, pub_root, SPX_N) != 0) { - return -1; - } - - return 0; -} - - -/** - * Returns an array containing the signature followed by the message. - */ -int crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk) { - size_t siglen; - - crypto_sign_signature(sm, &siglen, m, mlen, sk); - - memmove(sm + SPX_BYTES, m, mlen); - *smlen = siglen + mlen; - - return 0; -} - -/** - * Verifies a given signature-message pair under a given public key. - */ -int crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk) { - /* The API caller does not necessarily know what size a signature should be - but SPHINCS+ signatures are always exactly SPX_BYTES. */ - if (smlen < SPX_BYTES) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - *mlen = smlen - SPX_BYTES; - - if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - /* If verification was successful, move the message to the right place. */ - memmove(m, sm + SPX_BYTES, *mlen); - - return 0; -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/thash.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/thash.h deleted file mode 100644 index 8687ccfb4d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/thash.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef SPX_THASH_H -#define SPX_THASH_H - -#include "context.h" -#include "params.h" - -#include - -#define thash SPX_NAMESPACE(thash) -void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/thash_haraka_simple.c b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/thash_haraka_simple.c deleted file mode 100644 index 207777bf8d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/thash_haraka_simple.c +++ /dev/null @@ -1,36 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "thash.h" -#include "utils.h" - -#include "haraka.h" - -/** - * Takes an array of inblocks concatenated arrays of SPX_N bytes. - */ -void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]) { - PQCLEAN_VLA(uint8_t, buf, SPX_ADDR_BYTES + inblocks * SPX_N); - unsigned char outbuf[32]; - unsigned char buf_tmp[64]; - - if (inblocks == 1) { - /* F function */ - /* Since SPX_N may be smaller than 32, we need a temporary buffer. */ - memset(buf_tmp, 0, 64); - memcpy(buf_tmp, addr, 32); - memcpy(buf_tmp + SPX_ADDR_BYTES, in, SPX_N); - - haraka512(outbuf, buf_tmp, ctx); - memcpy(out, outbuf, SPX_N); - } else { - /* All other tweakable hashes*/ - memcpy(buf, addr, 32); - memcpy(buf + SPX_ADDR_BYTES, in, inblocks * SPX_N); - - haraka_S(out, SPX_N, buf, SPX_ADDR_BYTES + inblocks * SPX_N, ctx); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/utils.c b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/utils.c deleted file mode 100644 index 177b541fb9..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/utils.c +++ /dev/null @@ -1,148 +0,0 @@ -#include - -#include "utils.h" - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "thash.h" - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void ull_to_bytes(unsigned char *out, unsigned int outlen, - unsigned long long in) { - int i; - - /* Iterate over out in decreasing order, for big-endianness. */ - for (i = (signed int)outlen - 1; i >= 0; i--) { - out[i] = in & 0xff; - in = in >> 8; - } -} - -void u32_to_bytes(unsigned char *out, uint32_t in) { - out[0] = (unsigned char)(in >> 24); - out[1] = (unsigned char)(in >> 16); - out[2] = (unsigned char)(in >> 8); - out[3] = (unsigned char)in; -} - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { - unsigned long long retval = 0; - unsigned int i; - - for (i = 0; i < inlen; i++) { - retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); - } - return retval; -} - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void compute_root(unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const spx_ctx *ctx, uint32_t addr[8]) { - uint32_t i; - unsigned char buffer[2 * SPX_N]; - - /* If leaf_idx is odd (last bit = 1), current path element is a right child - and auth_path has to go left. Otherwise it is the other way around. */ - if (leaf_idx & 1) { - memcpy(buffer + SPX_N, leaf, SPX_N); - memcpy(buffer, auth_path, SPX_N); - } else { - memcpy(buffer, leaf, SPX_N); - memcpy(buffer + SPX_N, auth_path, SPX_N); - } - auth_path += SPX_N; - - for (i = 0; i < tree_height - 1; i++) { - leaf_idx >>= 1; - idx_offset >>= 1; - /* Set the address of the node we're creating. */ - set_tree_height(addr, i + 1); - set_tree_index(addr, leaf_idx + idx_offset); - - /* Pick the right or left neighbor, depending on parity of the node. */ - if (leaf_idx & 1) { - thash(buffer + SPX_N, buffer, 2, ctx, addr); - memcpy(buffer, auth_path, SPX_N); - } else { - thash(buffer, buffer, 2, ctx, addr); - memcpy(buffer + SPX_N, auth_path, SPX_N); - } - auth_path += SPX_N; - } - - /* The last iteration is exceptional; we do not copy an auth_path node. */ - leaf_idx >>= 1; - idx_offset >>= 1; - set_tree_height(addr, tree_height); - set_tree_index(addr, leaf_idx + idx_offset); - thash(root, buffer, 2, ctx, addr); -} - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const spx_ctx * /* ctx */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), - uint32_t tree_addr[8]) { - PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); - PQCLEAN_VLA(unsigned int, heights, tree_height + 1); - unsigned int offset = 0; - uint32_t idx; - uint32_t tree_idx; - - for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { - /* Add the next leaf node to the stack. */ - gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); - offset++; - heights[offset - 1] = 0; - - /* If this is a node we need for the auth path.. */ - if ((leaf_idx ^ 0x1) == idx) { - memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); - } - - /* While the top-most nodes are of equal height.. */ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { - /* Compute index of the new node, in the next layer. */ - tree_idx = (idx >> (heights[offset - 1] + 1)); - - /* Set the address of the node we're creating. */ - set_tree_height(tree_addr, heights[offset - 1] + 1); - set_tree_index(tree_addr, - tree_idx + (idx_offset >> (heights[offset - 1] + 1))); - /* Hash the top-most nodes from the stack together. */ - thash(stack + (offset - 2)*SPX_N, - stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); - offset--; - /* Note that the top-most node is now one layer higher. */ - heights[offset - 1]++; - - /* If this is a node we need for the auth path.. */ - if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_path + heights[offset - 1]*SPX_N, - stack + (offset - 1)*SPX_N, SPX_N); - } - } - } - memcpy(root, stack, SPX_N); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/utils.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/utils.h deleted file mode 100644 index 64f5d5a53a..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/utils.h +++ /dev/null @@ -1,58 +0,0 @@ -#ifndef SPX_UTILS_H -#define SPX_UTILS_H - -#include - -#include "compat.h" -#include "context.h" -#include "params.h" - - -/* To support MSVC use alloca() instead of VLAs. See #20. */ - - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) -void ull_to_bytes(unsigned char *out, unsigned int outlen, - unsigned long long in); -#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) -void u32_to_bytes(unsigned char *out, uint32_t in); - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) -unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -#define compute_root SPX_NAMESPACE(compute_root) -void compute_root(unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const spx_ctx *ctx, uint32_t addr[8]); - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -#define treehash SPX_NAMESPACE(treehash) -void treehash(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const spx_ctx *ctx /* ctx */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), - uint32_t tree_addr[8]); - - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/utilsx1.c b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/utilsx1.c deleted file mode 100644 index fccb69b35d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/utilsx1.c +++ /dev/null @@ -1,100 +0,0 @@ -#include - -#include "utilsx1.h" - -#include "address.h" -#include "params.h" -#include "thash.h" -#include "utils.h" - -/* - * Generate the entire Merkle tree, computing the authentication path for - * leaf_idx, and the resulting root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) - * - * This expects tree_addr to be initialized to the addr structures for the - * Merkle tree nodes - * - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - * - * This works by using the standard Merkle tree building algorithm, - */ -void treehashx1(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, - uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* Where to write the leaves */, - const spx_ctx * /* ctx */, - uint32_t idx, void *info), - uint32_t tree_addr[8], - void *info) { - /* This is where we keep the intermediate nodes */ - PQCLEAN_VLA(uint8_t, stack, tree_height * SPX_N); - - uint32_t idx; - uint32_t max_idx = (uint32_t)((1 << tree_height) - 1); - for (idx = 0;; idx++) { - unsigned char current[2 * SPX_N]; /* Current logical node is at */ - /* index[SPX_N]. We do this to minimize the number of copies */ - /* needed during a thash */ - gen_leaf( ¤t[SPX_N], ctx, idx + idx_offset, - info ); - - /* Now combine the freshly generated right node with previously */ - /* generated left ones */ - uint32_t internal_idx_offset = idx_offset; - uint32_t internal_idx = idx; - uint32_t internal_leaf = leaf_idx; - uint32_t h; /* The height we are in the Merkle tree */ - for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { - - /* Check if we hit the top of the tree */ - if (h == tree_height) { - /* We hit the root; return it */ - memcpy( root, ¤t[SPX_N], SPX_N ); - return; - } - - /* - * Check if the node we have is a part of the - * authentication path; if it is, write it out - */ - if ((internal_idx ^ internal_leaf) == 0x01) { - memcpy( &auth_path[ h * SPX_N ], - ¤t[SPX_N], - SPX_N ); - } - - /* - * Check if we're at a left child; if so, stop going up the stack - * Exception: if we've reached the end of the tree, keep on going - * (so we combine the last 4 nodes into the one root node in two - * more iterations) - */ - if ((internal_idx & 1) == 0 && idx < max_idx) { - break; - } - - /* Ok, we're at a right node */ - /* Now combine the left and right logical nodes together */ - - /* Set the address of the node we're creating. */ - internal_idx_offset >>= 1; - set_tree_height(tree_addr, h + 1); - set_tree_index(tree_addr, internal_idx / 2 + internal_idx_offset ); - - unsigned char *left = &stack[h * SPX_N]; - memcpy( ¤t[0], left, SPX_N ); - thash( ¤t[1 * SPX_N], - ¤t[0 * SPX_N], - 2, ctx, tree_addr); - } - - /* We've hit a left child; save the current for when we get the */ - /* corresponding right right */ - memcpy( &stack[h * SPX_N], ¤t[SPX_N], SPX_N); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/utilsx1.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/utilsx1.h deleted file mode 100644 index e911d17d53..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/utilsx1.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef SPX_UTILSX4_H -#define SPX_UTILSX4_H - -#include - -#include "context.h" -#include "params.h" - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -#define treehashx1 SPX_NAMESPACE(treehashx1) -void treehashx1(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* Where to write the leaf */, - const spx_ctx * /* ctx */, - uint32_t addr_idx, void *info), - uint32_t tree_addrx4[8], void *info); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/wots.c b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/wots.c deleted file mode 100644 index 249717aaa8..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/wots.c +++ /dev/null @@ -1,108 +0,0 @@ -#include -#include - -#include "wots.h" -#include "wotsx1.h" - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "thash.h" -#include "utils.h" -#include "utilsx1.h" - -// TODO clarify address expectations, and make them more uniform. -// TODO i.e. do we expect types to be set already? -// TODO and do we expect modifications or copies? - -/** - * Computes the chaining function. - * out and in have to be n-byte arrays. - * - * Interprets in as start-th value of the chain. - * addr has to contain the address of the chain. - */ -static void gen_chain(unsigned char *out, const unsigned char *in, - unsigned int start, unsigned int steps, - const spx_ctx *ctx, uint32_t addr[8]) { - uint32_t i; - - /* Initialize out with the value at position 'start'. */ - memcpy(out, in, SPX_N); - - /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < SPX_WOTS_W; i++) { - set_hash_addr(addr, i); - thash(out, out, 1, ctx, addr); - } -} - -/** - * base_w algorithm as described in draft. - * Interprets an array of bytes as integers in base w. - * This only works when log_w is a divisor of 8. - */ -static void base_w(unsigned int *output, const int out_len, - const unsigned char *input) { - int in = 0; - int out = 0; - unsigned char total = 0; - int bits = 0; - int consumed; - - for (consumed = 0; consumed < out_len; consumed++) { - if (bits == 0) { - total = input[in]; - in++; - bits += 8; - } - bits -= SPX_WOTS_LOGW; - output[out] = (total >> bits) & (SPX_WOTS_W - 1); - out++; - } -} - -/* Computes the WOTS+ checksum over a message (in base_w). */ -static void wots_checksum(unsigned int *csum_base_w, - const unsigned int *msg_base_w) { - unsigned int csum = 0; - unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; - unsigned int i; - - /* Compute checksum. */ - for (i = 0; i < SPX_WOTS_LEN1; i++) { - csum += SPX_WOTS_W - 1 - msg_base_w[i]; - } - - /* Convert checksum to base_w. */ - /* Make sure expected empty zero bits are the least significant bits. */ - csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); - ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); - base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); -} - -/* Takes a message and derives the matching chain lengths. */ -void chain_lengths(unsigned int *lengths, const unsigned char *msg) { - base_w(lengths, SPX_WOTS_LEN1, msg); - wots_checksum(lengths + SPX_WOTS_LEN1, lengths); -} - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const spx_ctx *ctx, uint32_t addr[8]) { - unsigned int lengths[SPX_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < SPX_WOTS_LEN; i++) { - set_chain_addr(addr, i); - gen_chain(pk + i * SPX_N, sig + i * SPX_N, - lengths[i], SPX_WOTS_W - 1 - lengths[i], ctx, addr); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/wots.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/wots.h deleted file mode 100644 index 4e7692eeef..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/wots.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef SPX_WOTS_H -#define SPX_WOTS_H - -#include - -#include "context.h" -#include "params.h" - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) -void wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const spx_ctx *ctx, uint32_t addr[8]); - -/* - * Compute the chain lengths needed for a given message hash - */ -#define chain_lengths SPX_NAMESPACE(chain_lengths) -void chain_lengths(unsigned int *lengths, const unsigned char *msg); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/wotsx1.c b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/wotsx1.c deleted file mode 100644 index 3adec78dfb..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/wotsx1.c +++ /dev/null @@ -1,76 +0,0 @@ -#include -#include - -#include "wots.h" -#include "wotsx1.h" - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "thash.h" -#include "utils.h" - -/* - * This generates a WOTS public key - * It also generates the WOTS signature if leaf_info indicates - * that we're signing with this WOTS key - */ -void wots_gen_leafx1(unsigned char *dest, - const spx_ctx *ctx, - uint32_t leaf_idx, void *v_info) { - struct leaf_info_x1 *info = v_info; - uint32_t *leaf_addr = info->leaf_addr; - uint32_t *pk_addr = info->pk_addr; - unsigned int i, k; - unsigned char pk_buffer[ SPX_WOTS_BYTES ]; - unsigned char *buffer; - uint32_t wots_k_mask; - - if (leaf_idx == info->wots_sign_leaf) { - /* We're traversing the leaf that's signing; generate the WOTS */ - /* signature */ - wots_k_mask = 0; - } else { - /* Nope, we're just generating pk's; turn off the signature logic */ - wots_k_mask = (uint32_t)~0; - } - - set_keypair_addr( leaf_addr, leaf_idx ); - set_keypair_addr( pk_addr, leaf_idx ); - - for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { - uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k to */ - /* the step if we're generating a signature, ~0 if we're not */ - - /* Start with the secret seed */ - set_chain_addr(leaf_addr, i); - set_hash_addr(leaf_addr, 0); - set_type(leaf_addr, SPX_ADDR_TYPE_WOTSPRF); - - prf_addr(buffer, ctx, leaf_addr); - - set_type(leaf_addr, SPX_ADDR_TYPE_WOTS); - - /* Iterate down the WOTS chain */ - for (k = 0;; k++) { - /* Check if this is the value that needs to be saved as a */ - /* part of the WOTS signature */ - if (k == wots_k) { - memcpy( info->wots_sig + i * SPX_N, buffer, SPX_N ); - } - - /* Check if we hit the top of the chain */ - if (k == SPX_WOTS_W - 1) { - break; - } - - /* Iterate one step on the chain */ - set_hash_addr(leaf_addr, k); - - thash(buffer, buffer, 1, ctx, leaf_addr); - } - } - - /* Do the final thash to generate the public keys */ - thash(dest, pk_buffer, SPX_WOTS_LEN, ctx, pk_addr); -} diff --git a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/wotsx1.h b/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/wotsx1.h deleted file mode 100644 index e617929f96..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-haraka-256s-simple_clean/wotsx1.h +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef WOTSX1_H_ -#define WOTSX1_H_ - -#include - -#include "context.h" -#include "params.h" - -/* - * This is here to provide an interface to the internal wots_gen_leafx1 - * routine. While this routine is not referenced in the package outside of - * wots.c, it is called from the stand-alone benchmark code to characterize - * the performance - */ -struct leaf_info_x1 { - unsigned char *wots_sig; - uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ - uint32_t *wots_steps; - uint32_t leaf_addr[8]; - uint32_t pk_addr[8]; -}; - -/* Macro to set the leaf_info to something 'benign', that is, it would */ -/* run with the same time as it does during the real signing process */ -/* Used only by the benchmark code */ -#define INITIALIZE_LEAF_INFO_X1(info, addr, step_buffer) { \ - (info).wots_sig = 0; \ - (info).wots_sign_leaf = ~0; \ - (info).wots_steps = step_buffer; \ - memcpy( &(info).leaf_addr[0], (addr), 32 ); \ - memcpy( &(info).pk_addr[0], (addr), 32 ); \ - } - -#define wots_gen_leafx1 SPX_NAMESPACE(wots_gen_leafx1) -void wots_gen_leafx1(unsigned char *dest, - const spx_ctx *ctx, - uint32_t leaf_idx, void *v_info); - -#endif /* WOTSX1_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/LICENSE b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/LICENSE deleted file mode 100644 index 670154e353..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/LICENSE +++ /dev/null @@ -1,116 +0,0 @@ -CC0 1.0 Universal - -Statement of Purpose - -The laws of most jurisdictions throughout the world automatically confer -exclusive Copyright and Related Rights (defined below) upon the creator and -subsequent owner(s) (each and all, an "owner") of an original work of -authorship and/or a database (each, a "Work"). - -Certain owners wish to permanently relinquish those rights to a Work for the -purpose of contributing to a commons of creative, cultural and scientific -works ("Commons") that the public can reliably and without fear of later -claims of infringement build upon, modify, incorporate in other works, reuse -and redistribute as freely as possible in any form whatsoever and for any -purposes, including without limitation commercial purposes. These owners may -contribute to the Commons to promote the ideal of a free culture and the -further production of creative, cultural and scientific works, or to gain -reputation or greater distribution for their Work in part through the use and -efforts of others. - -For these and/or other purposes and motivations, and without any expectation -of additional consideration or compensation, the person associating CC0 with a -Work (the "Affirmer"), to the extent that he or she is an owner of Copyright -and Related Rights in the Work, voluntarily elects to apply CC0 to the Work -and publicly distribute the Work under its terms, with knowledge of his or her -Copyright and Related Rights in the Work and the meaning and intended legal -effect of CC0 on those rights. - -1. Copyright and Related Rights. A Work made available under CC0 may be -protected by copyright and related or neighboring rights ("Copyright and -Related Rights"). Copyright and Related Rights include, but are not limited -to, the following: - - i. the right to reproduce, adapt, distribute, perform, display, communicate, - and translate a Work; - - ii. moral rights retained by the original author(s) and/or performer(s); - - iii. publicity and privacy rights pertaining to a person's image or likeness - depicted in a Work; - - iv. rights protecting against unfair competition in regards to a Work, - subject to the limitations in paragraph 4(a), below; - - v. rights protecting the extraction, dissemination, use and reuse of data in - a Work; - - vi. database rights (such as those arising under Directive 96/9/EC of the - European Parliament and of the Council of 11 March 1996 on the legal - protection of databases, and under any national implementation thereof, - including any amended or successor version of such directive); and - - vii. other similar, equivalent or corresponding rights throughout the world - based on applicable law or treaty, and any national implementations thereof. - -2. Waiver. To the greatest extent permitted by, but not in contravention of, -applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and -unconditionally waives, abandons, and surrenders all of Affirmer's Copyright -and Related Rights and associated claims and causes of action, whether now -known or unknown (including existing as well as future claims and causes of -action), in the Work (i) in all territories worldwide, (ii) for the maximum -duration provided by applicable law or treaty (including future time -extensions), (iii) in any current or future medium and for any number of -copies, and (iv) for any purpose whatsoever, including without limitation -commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes -the Waiver for the benefit of each member of the public at large and to the -detriment of Affirmer's heirs and successors, fully intending that such Waiver -shall not be subject to revocation, rescission, cancellation, termination, or -any other legal or equitable action to disrupt the quiet enjoyment of the Work -by the public as contemplated by Affirmer's express Statement of Purpose. - -3. Public License Fallback. Should any part of the Waiver for any reason be -judged legally invalid or ineffective under applicable law, then the Waiver -shall be preserved to the maximum extent permitted taking into account -Affirmer's express Statement of Purpose. In addition, to the extent the Waiver -is so judged Affirmer hereby grants to each affected person a royalty-free, -non transferable, non sublicensable, non exclusive, irrevocable and -unconditional license to exercise Affirmer's Copyright and Related Rights in -the Work (i) in all territories worldwide, (ii) for the maximum duration -provided by applicable law or treaty (including future time extensions), (iii) -in any current or future medium and for any number of copies, and (iv) for any -purpose whatsoever, including without limitation commercial, advertising or -promotional purposes (the "License"). The License shall be deemed effective as -of the date CC0 was applied by Affirmer to the Work. Should any part of the -License for any reason be judged legally invalid or ineffective under -applicable law, such partial invalidity or ineffectiveness shall not -invalidate the remainder of the License, and in such case Affirmer hereby -affirms that he or she will not (i) exercise any of his or her remaining -Copyright and Related Rights in the Work or (ii) assert any associated claims -and causes of action with respect to the Work, in either case contrary to -Affirmer's express Statement of Purpose. - -4. Limitations and Disclaimers. - - a. No trademark or patent rights held by Affirmer are waived, abandoned, - surrendered, licensed or otherwise affected by this document. - - b. Affirmer offers the Work as-is and makes no representations or warranties - of any kind concerning the Work, express, implied, statutory or otherwise, - including without limitation warranties of title, merchantability, fitness - for a particular purpose, non infringement, or the absence of latent or - other defects, accuracy, or the present or absence of errors, whether or not - discoverable, all to the greatest extent permissible under applicable law. - - c. Affirmer disclaims responsibility for clearing rights of other persons - that may apply to the Work or any use thereof, including without limitation - any person's Copyright and Related Rights in the Work. Further, Affirmer - disclaims responsibility for obtaining any necessary consents, permissions - or other rights required for any use of the Work. - - d. Affirmer understands and acknowledges that Creative Commons is not a - party to this document and has no duty or obligation with respect to this - CC0 or use of the Work. - -For more information, please see - diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/address.c b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/address.c deleted file mode 100644 index b956e9cb29..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/address.c +++ /dev/null @@ -1,91 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "utils.h" - -/* - * Specify which level of Merkle tree (the "layer") we're working on - */ -void set_layer_addr(uint32_t addr[8], uint32_t layer) { - ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; -} - -/* - * Specify which Merkle tree within the level (the "tree address") we're working on - */ -void set_tree_addr(uint32_t addr[8], uint64_t tree) { - ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); -} - -/* - * Specify the reason we'll use this address structure for, that is, what - * hash will we compute with it. This is used so that unrelated types of - * hashes don't accidentally get the same address structure. The type will be - * one of the SPX_ADDR_TYPE constants - */ -void set_type(uint32_t addr[8], uint32_t type) { - ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; -} - -/* - * Copy the layer and tree fields of the address structure. This is used - * when we're doing multiple types of hashes within the same Merkle tree - */ -void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { - memcpy( out, in, SPX_OFFSET_TREE + 8 ); -} - -/* These functions are used for OTS addresses. */ - -/* - * Specify which Merkle leaf we're working on; that is, which OTS keypair - * we're talking about. - */ -void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { - ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; -} - -/* - * Copy the layer, tree and keypair fields of the address structure. This is - * used when we're doing multiple things within the same OTS keypair - */ -void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { - memcpy( out, in, SPX_OFFSET_TREE + 8 ); - ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; -} - -/* - * Specify which Merkle chain within the OTS we're working with - * (the chain address) - */ -void set_chain_addr(uint32_t addr[8], uint32_t chain) { - ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; -} - -/* - * Specify where in the Merkle chain we are -* (the hash address) - */ -void set_hash_addr(uint32_t addr[8], uint32_t hash) { - ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; -} - -/* These functions are used for all hash tree addresses (including FORS). */ - -/* - * Specify the height of the node in the Merkle/FORS tree we are in - * (the tree height) - */ -void set_tree_height(uint32_t addr[8], uint32_t tree_height) { - ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; -} - -/* - * Specify the distance from the left edge of the node in the Merkle/FORS tree - * (the tree index) - */ -void set_tree_index(uint32_t addr[8], uint32_t tree_index) { - u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/address.h b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/address.h deleted file mode 100644 index 24a84eb40c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/address.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef SPX_ADDRESS_H -#define SPX_ADDRESS_H - -#include - -#include "params.h" - -/* The hash types that are passed to set_type */ -#define SPX_ADDR_TYPE_WOTS 0 -#define SPX_ADDR_TYPE_WOTSPK 1 -#define SPX_ADDR_TYPE_HASHTREE 2 -#define SPX_ADDR_TYPE_FORSTREE 3 -#define SPX_ADDR_TYPE_FORSPK 4 -#define SPX_ADDR_TYPE_WOTSPRF 5 -#define SPX_ADDR_TYPE_FORSPRF 6 - -#define set_layer_addr SPX_NAMESPACE(set_layer_addr) -void set_layer_addr(uint32_t addr[8], uint32_t layer); - -#define set_tree_addr SPX_NAMESPACE(set_tree_addr) -void set_tree_addr(uint32_t addr[8], uint64_t tree); - -#define set_type SPX_NAMESPACE(set_type) -void set_type(uint32_t addr[8], uint32_t type); - -/* Copies the layer and tree part of one address into the other */ -#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) -void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for WOTS and FORS addresses. */ - -#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) -void set_keypair_addr(uint32_t addr[8], uint32_t keypair); - -#define set_chain_addr SPX_NAMESPACE(set_chain_addr) -void set_chain_addr(uint32_t addr[8], uint32_t chain); - -#define set_hash_addr SPX_NAMESPACE(set_hash_addr) -void set_hash_addr(uint32_t addr[8], uint32_t hash); - -#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) -void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for all hash tree addresses (including FORS). */ - -#define set_tree_height SPX_NAMESPACE(set_tree_height) -void set_tree_height(uint32_t addr[8], uint32_t tree_height); - -#define set_tree_index SPX_NAMESPACE(set_tree_index) -void set_tree_index(uint32_t addr[8], uint32_t tree_index); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/api.h b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/api.h deleted file mode 100644 index 2748190643..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/api.h +++ /dev/null @@ -1,77 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA2128FROBUST_AVX2_API_H -#define PQCLEAN_SPHINCSSHA2128FROBUST_AVX2_API_H - -#include -#include - -#define PQCLEAN_SPHINCSSHA2128FROBUST_AVX2_CRYPTO_ALGNAME "SPHINCS+-sha2-128f-robust" - -#define PQCLEAN_SPHINCSSHA2128FROBUST_AVX2_CRYPTO_SECRETKEYBYTES 64 -#define PQCLEAN_SPHINCSSHA2128FROBUST_AVX2_CRYPTO_PUBLICKEYBYTES 32 -#define PQCLEAN_SPHINCSSHA2128FROBUST_AVX2_CRYPTO_BYTES 17088 - -#define PQCLEAN_SPHINCSSHA2128FROBUST_AVX2_CRYPTO_SEEDBYTES 48 - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSSHA2128FROBUST_AVX2_crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSSHA2128FROBUST_AVX2_crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSSHA2128FROBUST_AVX2_crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSSHA2128FROBUST_AVX2_crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHA2128FROBUST_AVX2_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHA2128FROBUST_AVX2_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSSHA2128FROBUST_AVX2_crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSSHA2128FROBUST_AVX2_crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, - const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSSHA2128FROBUST_AVX2_crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSSHA2128FROBUST_AVX2_crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk); -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/context.h b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/context.h deleted file mode 100644 index 200d3c0fb1..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/context.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef SPX_CONTEXT_H -#define SPX_CONTEXT_H - -#include - -#include "params.h" -#include "sha2.h" -#include "sha256avx.h" - -// funky ordering due to optimal padding -typedef struct { - sha256x8ctx statex8_seeded; - sha256ctx state_seeded; - - uint8_t pub_seed[SPX_N]; - uint8_t sk_seed[SPX_N]; -} spx_ctx; - - -#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) -void initialize_hash_function(spx_ctx *ctx); - -#define free_hash_function SPX_NAMESPACE(free_hash_function) -void free_hash_function(spx_ctx *ctx); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/context_sha2.c b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/context_sha2.c deleted file mode 100644 index 073af8dd15..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/context_sha2.c +++ /dev/null @@ -1,44 +0,0 @@ -#include - -#include "context.h" - -/** - * Absorb the constant pub_seed using one round of the compression function - * This initializes state_seeded and state_seeded_512, which can then be - * reused in thash - **/ -static void seed_state(spx_ctx *ctx) { - uint8_t block[SPX_SHA512_BLOCK_BYTES]; - size_t i; - - for (i = 0; i < SPX_N; ++i) { - block[i] = ctx->pub_seed[i]; - } - for (i = SPX_N; i < SPX_SHA512_BLOCK_BYTES; ++i) { - block[i] = 0; - } - /* block has been properly initialized for both SHA-256 and SHA-512 */ - - sha256_inc_init(&ctx->state_seeded); - sha256_inc_blocks(&ctx->state_seeded, block, 1); - - // initialize x8 - sha256_init8x(&ctx->statex8_seeded); - sha256_transform8x(&ctx->statex8_seeded, - block, block, block, block, block, block, block, block); - - ctx->statex8_seeded.datalen = 0; - ctx->statex8_seeded.msglen = 512; - -} - - -/* For SHA, we initialize the hash function at the start */ -void initialize_hash_function(spx_ctx *ctx) { - seed_state(ctx); -} - -/* Free the incremental hashing context for heap-based SHA2 APIs */ -void free_hash_function(spx_ctx *ctx) { - sha256_inc_ctx_release(&ctx->state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/fors.c b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/fors.c deleted file mode 100644 index 4cab8e7415..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/fors.c +++ /dev/null @@ -1,226 +0,0 @@ -#include -#include -#include - -#include "fors.h" - - -#include "address.h" -#include "hash.h" -#include "hashx8.h" -#include "thash.h" -#include "thashx8.h" -#include "utils.h" -#include "utilsx8.h" -static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, - uint32_t fors_leaf_addr[8]) { - prf_addr(sk, ctx, fors_leaf_addr); -} - -static void fors_gen_skx8(unsigned char *sk0, - unsigned char *sk1, - unsigned char *sk2, - unsigned char *sk3, - unsigned char *sk4, - unsigned char *sk5, - unsigned char *sk6, - unsigned char *sk7, const spx_ctx *ctx, - uint32_t fors_leaf_addrx8[8 * 8]) { - prf_addrx8(sk0, sk1, sk2, sk3, sk4, sk5, sk6, sk7, - ctx, fors_leaf_addrx8); -} - -static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, - const spx_ctx *ctx, - uint32_t fors_leaf_addr[8]) { - thash(leaf, sk, 1, ctx, fors_leaf_addr); -} - -static void fors_sk_to_leafx8(unsigned char *leaf0, - unsigned char *leaf1, - unsigned char *leaf2, - unsigned char *leaf3, - unsigned char *leaf4, - unsigned char *leaf5, - unsigned char *leaf6, - unsigned char *leaf7, - const unsigned char *sk0, - const unsigned char *sk1, - const unsigned char *sk2, - const unsigned char *sk3, - const unsigned char *sk4, - const unsigned char *sk5, - const unsigned char *sk6, - const unsigned char *sk7, - const spx_ctx *ctx, - uint32_t fors_leaf_addrx8[8 * 8]) { - thashx8(leaf0, leaf1, leaf2, leaf3, leaf4, leaf5, leaf6, leaf7, - sk0, sk1, sk2, sk3, sk4, sk5, sk6, sk7, - 1, ctx, fors_leaf_addrx8); -} - -struct fors_gen_leaf_info { - uint32_t leaf_addrx[8 * 8]; -}; - -static void fors_gen_leafx8(unsigned char *leaf, - const spx_ctx *ctx, - uint32_t addr_idx, void *info) { - struct fors_gen_leaf_info *fors_info = info; - uint32_t *fors_leaf_addrx8 = fors_info->leaf_addrx; - unsigned int j; - - /* Only set the parts that the caller doesn't set */ - for (j = 0; j < 8; j++) { - set_tree_index(fors_leaf_addrx8 + j * 8, addr_idx + j); - set_type(fors_leaf_addrx8 + j * 8, SPX_ADDR_TYPE_FORSPRF); - } - - fors_gen_skx8(leaf + 0 * SPX_N, - leaf + 1 * SPX_N, - leaf + 2 * SPX_N, - leaf + 3 * SPX_N, - leaf + 4 * SPX_N, - leaf + 5 * SPX_N, - leaf + 6 * SPX_N, - leaf + 7 * SPX_N, - ctx, fors_leaf_addrx8); - - for (j = 0; j < 8; j++) { - set_type(fors_leaf_addrx8 + j * 8, SPX_ADDR_TYPE_FORSTREE); - } - - fors_sk_to_leafx8(leaf + 0 * SPX_N, - leaf + 1 * SPX_N, - leaf + 2 * SPX_N, - leaf + 3 * SPX_N, - leaf + 4 * SPX_N, - leaf + 5 * SPX_N, - leaf + 6 * SPX_N, - leaf + 7 * SPX_N, - leaf + 0 * SPX_N, - leaf + 1 * SPX_N, - leaf + 2 * SPX_N, - leaf + 3 * SPX_N, - leaf + 4 * SPX_N, - leaf + 5 * SPX_N, - leaf + 6 * SPX_N, - leaf + 7 * SPX_N, - ctx, fors_leaf_addrx8); -} - -/** - * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - * Assumes indices has space for SPX_FORS_TREES integers. - */ -static void message_to_indices(uint32_t *indices, const unsigned char *m) { - unsigned int i, j; - unsigned int offset = 0; - - for (i = 0; i < SPX_FORS_TREES; i++) { - indices[i] = 0; - for (j = 0; j < SPX_FORS_HEIGHT; j++) { - indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); - offset++; - } - } -} - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -void fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]) { - uint32_t indices[SPX_FORS_TREES]; - unsigned char roots[SPX_FORS_TREES * SPX_N]; - uint32_t fors_tree_addr[8 * 8] = {0}; - struct fors_gen_leaf_info fors_info = {0}; - uint32_t *fors_leaf_addr = fors_info.leaf_addrx; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - for (i = 0; i < 8; i++) { - copy_keypair_addr(fors_tree_addr + 8 * i, fors_addr); - set_type(fors_tree_addr + 8 * i, SPX_ADDR_TYPE_FORSTREE); - copy_keypair_addr(fors_leaf_addr + 8 * i, fors_addr); - } - copy_keypair_addr(fors_pk_addr, fors_addr); - set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < SPX_FORS_TREES; i++) { - idx_offset = i * (1 << SPX_FORS_HEIGHT); - - set_tree_height(fors_tree_addr, 0); - set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Include the secret key part that produces the selected leaf node. */ - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); - fors_gen_sk(sig, ctx, fors_tree_addr); - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); - sig += SPX_N; - - /* Compute the authentication path for this leaf node. */ - treehashx8(roots + i * SPX_N, sig, ctx, - indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx8, - fors_tree_addr, &fors_info); - - sig += SPX_N * SPX_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); -} - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -void fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]) { - uint32_t indices[SPX_FORS_TREES]; - unsigned char roots[SPX_FORS_TREES * SPX_N]; - unsigned char leaf[SPX_N]; - uint32_t fors_tree_addr[8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - copy_keypair_addr(fors_tree_addr, fors_addr); - copy_keypair_addr(fors_pk_addr, fors_addr); - - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); - set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < SPX_FORS_TREES; i++) { - idx_offset = i * (1 << SPX_FORS_HEIGHT); - - set_tree_height(fors_tree_addr, 0); - set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Derive the leaf from the included secret key part. */ - fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); - sig += SPX_N; - - /* Derive the corresponding root node of this tree. */ - compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, - sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); - sig += SPX_N * SPX_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/fors.h b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/fors.h deleted file mode 100644 index 509140a178..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/fors.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef SPX_FORS_H -#define SPX_FORS_H - -#include - -#include "context.h" -#include "params.h" - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -#define fors_sign SPX_NAMESPACE(fors_sign) -void fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]); - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) -void fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/hash.h b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/hash.h deleted file mode 100644 index ffe815f45d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/hash.h +++ /dev/null @@ -1,37 +0,0 @@ -#ifndef SPX_HASH_H -#define SPX_HASH_H - -#include -#include - -#include "context.h" -#include "params.h" - -#define prf_addr SPX_NAMESPACE(prf_addr) -void prf_addr(unsigned char *out, const spx_ctx *ctx, - const uint32_t addr[8]); - -#define gen_message_random SPX_NAMESPACE(gen_message_random) -void gen_message_random(unsigned char *R, const unsigned char *sk_prf, - const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx); - -#define hash_message SPX_NAMESPACE(hash_message) -void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx); - - -# define SPX_SHA256_ADDR_BYTES 22 - -# define mgf1_256 SPX_NAMESPACE(mgf1_256) -void mgf1_256(unsigned char *out, unsigned long outlen, - const unsigned char *in, unsigned long inlen); - -# define mgf1_512 SPX_NAMESPACE(mgf1_512) -void mgf1_512(unsigned char *out, unsigned long outlen, - const unsigned char *in, unsigned long inlen); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/hash_sha2.c b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/hash_sha2.c deleted file mode 100644 index 69f0dc0013..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/hash_sha2.c +++ /dev/null @@ -1,219 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "sha2.h" -#include "utils.h" - - - -#define SPX_SHAX_OUTPUT_BYTES SPX_SHA256_OUTPUT_BYTES -#define SPX_SHAX_BLOCK_BYTES SPX_SHA256_BLOCK_BYTES -#define shaX_inc_init sha256_inc_init -#define shaX_inc_blocks sha256_inc_blocks -#define shaX_inc_finalize sha256_inc_finalize -#define shaX sha256 -#define mgf1_X mgf1_256 -#define shaXstate sha256ctx - -/** - * mgf1 function based on the SHA-256 hash function - * Note that inlen should be sufficiently small that it still allows for - * an array to be allocated on the stack. Typically 'in' is merely a seed. - * Outputs outlen number of bytes - */ -void mgf1_256(unsigned char *out, unsigned long outlen, - const unsigned char *in, unsigned long inlen) { - PQCLEAN_VLA(uint8_t, inbuf, inlen + 4); - unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES]; - uint32_t i; - - memcpy(inbuf, in, inlen); - - /* While we can fit in at least another full block of SHA256 output.. */ - for (i = 0; (i + 1)*SPX_SHA256_OUTPUT_BYTES <= outlen; i++) { - u32_to_bytes(inbuf + inlen, i); - sha256(out, inbuf, inlen + 4); - out += SPX_SHA256_OUTPUT_BYTES; - } - /* Until we cannot anymore, and we fill the remainder. */ - if (outlen > i * SPX_SHA256_OUTPUT_BYTES) { - u32_to_bytes(inbuf + inlen, i); - sha256(outbuf, inbuf, inlen + 4); - memcpy(out, outbuf, outlen - i * SPX_SHA256_OUTPUT_BYTES); - } -} - -/* - * mgf1 function based on the SHA-512 hash function - */ -void mgf1_512(unsigned char *out, unsigned long outlen, - const unsigned char *in, unsigned long inlen) { - PQCLEAN_VLA(uint8_t, inbuf, inlen + 4); - unsigned char outbuf[SPX_SHA512_OUTPUT_BYTES]; - uint32_t i; - - memcpy(inbuf, in, inlen); - - /* While we can fit in at least another full block of SHA512 output.. */ - for (i = 0; (i + 1)*SPX_SHA512_OUTPUT_BYTES <= outlen; i++) { - u32_to_bytes(inbuf + inlen, i); - sha512(out, inbuf, inlen + 4); - out += SPX_SHA512_OUTPUT_BYTES; - } - /* Until we cannot anymore, and we fill the remainder. */ - if (outlen > i * SPX_SHA512_OUTPUT_BYTES) { - u32_to_bytes(inbuf + inlen, i); - sha512(outbuf, inbuf, inlen + 4); - memcpy(out, outbuf, outlen - i * SPX_SHA512_OUTPUT_BYTES); - } -} - -/* - * Computes PRF(pk_seed, sk_seed, addr). - */ -void prf_addr(unsigned char *out, const spx_ctx *ctx, - const uint32_t addr[8]) { - sha256ctx sha2_state; - unsigned char buf[SPX_SHA256_ADDR_BYTES + SPX_N]; - unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES]; - - /* Retrieve precomputed state containing pub_seed */ - sha256_inc_ctx_clone(&sha2_state, &ctx->state_seeded); - - /* Remainder: ADDR^c ‖ SK.seed */ - memcpy(buf, addr, SPX_SHA256_ADDR_BYTES); - memcpy(buf + SPX_SHA256_ADDR_BYTES, ctx->sk_seed, SPX_N); - - sha256_inc_finalize(outbuf, &sha2_state, buf, SPX_SHA256_ADDR_BYTES + SPX_N); - - memcpy(out, outbuf, SPX_N); -} - -/** - * Computes the message-dependent randomness R, using a secret seed as a key - * for HMAC, and an optional randomization value prefixed to the message. - * This requires m to have at least SPX_SHAX_BLOCK_BYTES + SPX_N space - * available in front of the pointer, i.e. before the message to use for the - * prefix. This is necessary to prevent having to move the message around (and - * allocate memory for it). - */ -void gen_message_random(unsigned char *R, const unsigned char *sk_prf, - const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx) { - (void)ctx; - - unsigned char buf[SPX_SHAX_BLOCK_BYTES + SPX_SHAX_OUTPUT_BYTES]; - shaXstate state; - int i; - - - /* This implements HMAC-SHA */ - for (i = 0; i < SPX_N; i++) { - buf[i] = 0x36 ^ sk_prf[i]; - } - memset(buf + SPX_N, 0x36, SPX_SHAX_BLOCK_BYTES - SPX_N); - - shaX_inc_init(&state); - shaX_inc_blocks(&state, buf, 1); - - memcpy(buf, optrand, SPX_N); - - /* If optrand + message cannot fill up an entire block */ - if (SPX_N + mlen < SPX_SHAX_BLOCK_BYTES) { - memcpy(buf + SPX_N, m, mlen); - shaX_inc_finalize(buf + SPX_SHAX_BLOCK_BYTES, &state, - buf, mlen + SPX_N); - } - /* Otherwise first fill a block, so that finalize only uses the message */ - else { - memcpy(buf + SPX_N, m, SPX_SHAX_BLOCK_BYTES - SPX_N); - shaX_inc_blocks(&state, buf, 1); - - m += SPX_SHAX_BLOCK_BYTES - SPX_N; - mlen -= SPX_SHAX_BLOCK_BYTES - SPX_N; - shaX_inc_finalize(buf + SPX_SHAX_BLOCK_BYTES, &state, m, mlen); - } - - for (i = 0; i < SPX_N; i++) { - buf[i] = 0x5c ^ sk_prf[i]; - } - memset(buf + SPX_N, 0x5c, SPX_SHAX_BLOCK_BYTES - SPX_N); - - shaX(buf, buf, SPX_SHAX_BLOCK_BYTES + SPX_SHAX_OUTPUT_BYTES); - memcpy(R, buf, SPX_N); -} - -/** - * Computes the message hash using R, the public key, and the message. - * Outputs the message digest and the index of the leaf. The index is split in - * the tree index and the leaf index, for convenient copying to an address. - */ -void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx) { - (void)ctx; -#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) -#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) -#define SPX_LEAF_BITS SPX_TREE_HEIGHT -#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) -#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) - - unsigned char seed[2 * SPX_N + SPX_SHAX_OUTPUT_BYTES]; - - /* Round to nearest multiple of SPX_SHAX_BLOCK_BYTES */ -#define SPX_INBLOCKS (((SPX_N + SPX_PK_BYTES + SPX_SHAX_BLOCK_BYTES - 1) & \ - -SPX_SHAX_BLOCK_BYTES) / SPX_SHAX_BLOCK_BYTES) - unsigned char inbuf[SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES]; - - unsigned char buf[SPX_DGST_BYTES]; - unsigned char *bufp = buf; - shaXstate state; - - shaX_inc_init(&state); - - // seed: SHA-X(R ‖ PK.seed ‖ PK.root ‖ M) - memcpy(inbuf, R, SPX_N); - memcpy(inbuf + SPX_N, pk, SPX_PK_BYTES); - - /* If R + pk + message cannot fill up an entire block */ - if (SPX_N + SPX_PK_BYTES + mlen < SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES) { - memcpy(inbuf + SPX_N + SPX_PK_BYTES, m, mlen); - shaX_inc_finalize(seed + 2 * SPX_N, &state, inbuf, SPX_N + SPX_PK_BYTES + mlen); - } - /* Otherwise first fill a block, so that finalize only uses the message */ - else { - memcpy(inbuf + SPX_N + SPX_PK_BYTES, m, - SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES - SPX_N - SPX_PK_BYTES); - shaX_inc_blocks(&state, inbuf, SPX_INBLOCKS); - - m += SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES - SPX_N - SPX_PK_BYTES; - mlen -= SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES - SPX_N - SPX_PK_BYTES; - shaX_inc_finalize(seed + 2 * SPX_N, &state, m, (size_t)mlen); - } - - // H_msg: MGF1-SHA-X(R ‖ PK.seed ‖ seed) - memcpy(seed, R, SPX_N); - memcpy(seed + SPX_N, pk, SPX_N); - - /* By doing this in two steps, we prevent hashing the message twice; - otherwise each iteration in MGF1 would hash the message again. */ - mgf1_X(bufp, SPX_DGST_BYTES, seed, 2 * SPX_N + SPX_SHAX_OUTPUT_BYTES); - - memcpy(digest, bufp, SPX_FORS_MSG_BYTES); - bufp += SPX_FORS_MSG_BYTES; - - - *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); - *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); - bufp += SPX_TREE_BYTES; - - *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); - *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); -} - - diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/hash_sha2x8.c b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/hash_sha2x8.c deleted file mode 100644 index e04af7a069..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/hash_sha2x8.c +++ /dev/null @@ -1,75 +0,0 @@ -#include -#include - -#include "hash.h" -#include "hashx8.h" - -#include "address.h" -#include "params.h" -#include "sha2.h" -#include "sha256avx.h" -#include "sha256x8.h" -#include "utils.h" - -/* - * 8-way parallel version of prf_addr; takes 8x as much input and output - */ -void prf_addrx8(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7, - const spx_ctx *ctx, - const uint32_t addrx8[8 * 8]) { - unsigned char bufx8[8 * (SPX_N + SPX_SHA256_ADDR_BYTES)]; - unsigned char outbufx8[8 * SPX_SHA256_OUTPUT_BYTES]; - unsigned int j; - - for (j = 0; j < 8; j++) { - memcpy(bufx8 + j * (SPX_N + SPX_SHA256_ADDR_BYTES), - addrx8 + j * 8, SPX_SHA256_ADDR_BYTES); - memcpy( - bufx8 + j * (SPX_N + SPX_SHA256_ADDR_BYTES) + SPX_SHA256_ADDR_BYTES, - ctx->sk_seed, - SPX_N - ); - } - - sha256x8_seeded( - /* out */ - outbufx8 + 0 * SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 1 * SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 2 * SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 3 * SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 4 * SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 5 * SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 6 * SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 7 * SPX_SHA256_OUTPUT_BYTES, - - /* seed */ - &ctx->statex8_seeded, - - /* in */ - bufx8 + 0 * (SPX_SHA256_ADDR_BYTES + SPX_N), - bufx8 + 1 * (SPX_SHA256_ADDR_BYTES + SPX_N), - bufx8 + 2 * (SPX_SHA256_ADDR_BYTES + SPX_N), - bufx8 + 3 * (SPX_SHA256_ADDR_BYTES + SPX_N), - bufx8 + 4 * (SPX_SHA256_ADDR_BYTES + SPX_N), - bufx8 + 5 * (SPX_SHA256_ADDR_BYTES + SPX_N), - bufx8 + 6 * (SPX_SHA256_ADDR_BYTES + SPX_N), - bufx8 + 7 * (SPX_SHA256_ADDR_BYTES + SPX_N), - SPX_SHA256_ADDR_BYTES + SPX_N /* len */ - ); - - memcpy(out0, outbufx8 + 0 * SPX_SHA256_OUTPUT_BYTES, SPX_N); - memcpy(out1, outbufx8 + 1 * SPX_SHA256_OUTPUT_BYTES, SPX_N); - memcpy(out2, outbufx8 + 2 * SPX_SHA256_OUTPUT_BYTES, SPX_N); - memcpy(out3, outbufx8 + 3 * SPX_SHA256_OUTPUT_BYTES, SPX_N); - memcpy(out4, outbufx8 + 4 * SPX_SHA256_OUTPUT_BYTES, SPX_N); - memcpy(out5, outbufx8 + 5 * SPX_SHA256_OUTPUT_BYTES, SPX_N); - memcpy(out6, outbufx8 + 6 * SPX_SHA256_OUTPUT_BYTES, SPX_N); - memcpy(out7, outbufx8 + 7 * SPX_SHA256_OUTPUT_BYTES, SPX_N); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/hashx8.h b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/hashx8.h deleted file mode 100644 index 46503f0a10..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/hashx8.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef SPX_HASHX8_H -#define SPX_HASHX8_H - -#include - -#include "params.h" - -#define prf_addrx8 SPX_NAMESPACE(prf_addrx8) -void prf_addrx8(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7, - const spx_ctx *ctx, - const uint32_t addrx8[8 * 8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/merkle.c b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/merkle.c deleted file mode 100644 index 1f353c8dd8..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/merkle.c +++ /dev/null @@ -1,65 +0,0 @@ -#include -#include - -#include "merkle.h" - -#include "address.h" -#include "params.h" -#include "utils.h" -#include "utilsx8.h" -#include "wots.h" -#include "wotsx8.h" - -/* - * This generates a Merkle signature (WOTS signature followed by the Merkle - * authentication path). - */ -void merkle_sign(uint8_t *sig, unsigned char *root, - const spx_ctx *ctx, - uint32_t wots_addr[8], uint32_t tree_addr[8], - uint32_t idx_leaf) { - unsigned char *auth_path = sig + SPX_WOTS_BYTES; - uint32_t tree_addrx8[8 * 8] = { 0 }; - int j; - struct leaf_info_x8 info = { 0 }; - unsigned steps[ SPX_WOTS_LEN ]; - - info.wots_sig = sig; - chain_lengths(steps, root); - info.wots_steps = steps; - - for (j = 0; j < 8; j++) { - set_type(&tree_addrx8[8 * j], SPX_ADDR_TYPE_HASHTREE); - set_type(&info.leaf_addr[8 * j], SPX_ADDR_TYPE_WOTS); - set_type(&info.pk_addr[8 * j], SPX_ADDR_TYPE_WOTSPK); - copy_subtree_addr(&tree_addrx8[8 * j], tree_addr); - copy_subtree_addr(&info.leaf_addr[8 * j], wots_addr); - copy_subtree_addr(&info.pk_addr[8 * j], wots_addr); - } - - info.wots_sign_leaf = idx_leaf; - - treehashx8(root, auth_path, ctx, - idx_leaf, 0, - SPX_TREE_HEIGHT, - wots_gen_leafx8, - tree_addrx8, &info); -} - -/* Compute root node of the top-most subtree. */ -/* Again, in this file because wots_gen_leaf is most of the work */ -void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { - /* We do not need the auth path in key generation, but it simplifies the - code to have just one treehash routine that computes both root and path - in one function. */ - unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; - uint32_t top_tree_addr[8] = {0}; - uint32_t wots_addr[8] = {0}; - - set_layer_addr(top_tree_addr, SPX_D - 1); - set_layer_addr(wots_addr, SPX_D - 1); - - merkle_sign(auth_path, root, ctx, - wots_addr, top_tree_addr, - ~0U /* ~0 means "don't bother generating an auth path */ ); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/merkle.h b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/merkle.h deleted file mode 100644 index 769cf2e970..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/merkle.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef MERKLE_H_ -#define MERKLE_H_ - -#include - -#include "context.h" -#include "params.h" - -/* Generate a Merkle signature (WOTS signature followed by the Merkle */ -/* authentication path) */ -#define merkle_sign SPX_NAMESPACE(merkle_sign) -void merkle_sign(uint8_t *sig, unsigned char *root, - const spx_ctx *ctx, - uint32_t wots_addr[8], uint32_t tree_addr[8], - uint32_t idx_leaf); - -/* Compute the root node of the top-most subtree. */ -#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) -void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); - -#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/nistapi.h b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/nistapi.h deleted file mode 100644 index 3cb71afad4..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/nistapi.h +++ /dev/null @@ -1,87 +0,0 @@ -#ifndef SPX_API_H -#define SPX_API_H - -#include -#include - -#include "params.h" - -#define CRYPTO_ALGNAME "SPHINCS+" - -#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES -#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES -#define CRYPTO_BYTES SPX_BYTES -#define CRYPTO_SEEDBYTES (3*SPX_N) - -/* - * Returns the length of a secret key, in bytes - */ -#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) -size_t crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) -size_t crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) -size_t crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) -size_t crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) -int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) -int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) -int crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) -int crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -#define crypto_sign SPX_NAMESPACE(crypto_sign) -int crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) -int crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/params.h b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/params.h deleted file mode 100644 index 73e2f8c913..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/params.h +++ /dev/null @@ -1,61 +0,0 @@ -#ifndef SPX_PARAMS_H -#define SPX_PARAMS_H - -#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSSHA2128FROBUST_AVX2_##s - -/* Hash output length in bytes. */ -#define SPX_N 16 -/* Height of the hypertree. */ -#define SPX_FULL_HEIGHT 66 -/* Number of subtree layer. */ -#define SPX_D 22 -/* FORS tree dimensions. */ -#define SPX_FORS_HEIGHT 6 -#define SPX_FORS_TREES 33 -/* Winternitz parameter, */ -#define SPX_WOTS_W 16 - -/* The hash function is defined by linking a different hash.c file, as opposed - to setting a #define constant. */ - -/* This is a SHA2-based parameter set, hence whether we use SHA-256 - * exclusively or we use both SHA-256 and SHA-512 is controlled by - * the following #define */ -#define SPX_SHA512 0 /* Use SHA-256 for all hashes */ - -/* For clarity */ -#define SPX_ADDR_BYTES 32 - -/* WOTS parameters. */ -#define SPX_WOTS_LOGW 4 - -#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) - -/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#define SPX_WOTS_LEN2 3 - -#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) -#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) -#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES - -/* Subtree size. */ -#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) - -//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT -// #error SPX_D should always divide SPX_FULL_HEIGHT -//#endif - -/* FORS parameters. */ -#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) -#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) -#define SPX_FORS_PK_BYTES SPX_N - -/* Resulting SPX sizes. */ -#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ - SPX_FULL_HEIGHT * SPX_N) -#define SPX_PK_BYTES (2 * SPX_N) -#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) - -#include "sha2_offsets.h" - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/sha256avx.c b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/sha256avx.c deleted file mode 100644 index 6bbe6ecc24..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/sha256avx.c +++ /dev/null @@ -1,357 +0,0 @@ -#include -#include -#include - -#include "sha256avx.h" - -static const unsigned int RC[] = { - 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, - 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, - 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, - 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, - 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, - 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, - 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, - 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, - 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, - 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, - 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, - 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, - 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, - 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, - 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, - 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 -}; - -#define u32 uint32_t -#define u256 __m256i - -#define XOR _mm256_xor_si256 -#define OR _mm256_or_si256 -#define AND _mm256_and_si256 -#define ADD32 _mm256_add_epi32 -#define NOT(x) _mm256_xor_si256(x, _mm256_set_epi32(-1, -1, -1, -1, -1, -1, -1, -1)) - -#define LOAD(src) _mm256_loadu_si256((__m256i *)(src)) -#define STORE(dest,src) _mm256_storeu_si256((__m256i *)(dest),src) - -#define BYTESWAP(x) _mm256_shuffle_epi8(x, _mm256_set_epi8(0xc,0xd,0xe,0xf,0x8,0x9,0xa,0xb,0x4,0x5,0x6,0x7,0x0,0x1,0x2,0x3,0xc,0xd,0xe,0xf,0x8,0x9,0xa,0xb,0x4,0x5,0x6,0x7,0x0,0x1,0x2,0x3)) - -#define SHIFTR32(x, y) _mm256_srli_epi32(x, y) -#define SHIFTL32(x, y) _mm256_slli_epi32(x, y) - -#define ROTR32(x, y) OR(SHIFTR32(x, y), SHIFTL32(x, 32 - (y))) -#define ROTL32(x, y) OR(SHIFTL32(x, y), SHIFTR32(x, 32 - (y))) - -#define XOR3(a, b, c) XOR(XOR(a, b), c) - -#define ADD3_32(a, b, c) ADD32(ADD32(a, b), c) -#define ADD4_32(a, b, c, d) ADD32(ADD32(ADD32(a, b), c), d) -#define ADD5_32(a, b, c, d, e) ADD32(ADD32(ADD32(ADD32(a, b), c), d), e) - -#define MAJ_AVX(a, b, c) XOR3(AND(a, b), AND(a, c), AND(b, c)) -#define CH_AVX(a, b, c) XOR(AND(a, b), AND(NOT(a), c)) - -#define SIGMA1_AVX(x) XOR3(ROTR32(x, 6), ROTR32(x, 11), ROTR32(x, 25)) -#define SIGMA0_AVX(x) XOR3(ROTR32(x, 2), ROTR32(x, 13), ROTR32(x, 22)) - -#define WSIGMA1_AVX(x) XOR3(ROTR32(x, 17), ROTR32(x, 19), SHIFTR32(x, 10)) -#define WSIGMA0_AVX(x) XOR3(ROTR32(x, 7), ROTR32(x, 18), SHIFTR32(x, 3)) - -#define SHA256ROUND_AVX(a, b, c, d, e, f, g, h, rc, w) \ - T0 = ADD5_32(h, SIGMA1_AVX(e), CH_AVX(e, f, g), _mm256_set1_epi32((int)RC[rc]), w); \ - (d) = ADD32(d, T0); \ - T1 = ADD32(SIGMA0_AVX(a), MAJ_AVX(a, b, c)); \ - (h) = ADD32(T0, T1); - -// Transpose 8 vectors containing 32-bit values -static void transpose(u256 s[8]) { - u256 tmp0[8]; - u256 tmp1[8]; - tmp0[0] = _mm256_unpacklo_epi32(s[0], s[1]); - tmp0[1] = _mm256_unpackhi_epi32(s[0], s[1]); - tmp0[2] = _mm256_unpacklo_epi32(s[2], s[3]); - tmp0[3] = _mm256_unpackhi_epi32(s[2], s[3]); - tmp0[4] = _mm256_unpacklo_epi32(s[4], s[5]); - tmp0[5] = _mm256_unpackhi_epi32(s[4], s[5]); - tmp0[6] = _mm256_unpacklo_epi32(s[6], s[7]); - tmp0[7] = _mm256_unpackhi_epi32(s[6], s[7]); - tmp1[0] = _mm256_unpacklo_epi64(tmp0[0], tmp0[2]); - tmp1[1] = _mm256_unpackhi_epi64(tmp0[0], tmp0[2]); - tmp1[2] = _mm256_unpacklo_epi64(tmp0[1], tmp0[3]); - tmp1[3] = _mm256_unpackhi_epi64(tmp0[1], tmp0[3]); - tmp1[4] = _mm256_unpacklo_epi64(tmp0[4], tmp0[6]); - tmp1[5] = _mm256_unpackhi_epi64(tmp0[4], tmp0[6]); - tmp1[6] = _mm256_unpacklo_epi64(tmp0[5], tmp0[7]); - tmp1[7] = _mm256_unpackhi_epi64(tmp0[5], tmp0[7]); - s[0] = _mm256_permute2x128_si256(tmp1[0], tmp1[4], 0x20); - s[1] = _mm256_permute2x128_si256(tmp1[1], tmp1[5], 0x20); - s[2] = _mm256_permute2x128_si256(tmp1[2], tmp1[6], 0x20); - s[3] = _mm256_permute2x128_si256(tmp1[3], tmp1[7], 0x20); - s[4] = _mm256_permute2x128_si256(tmp1[0], tmp1[4], 0x31); - s[5] = _mm256_permute2x128_si256(tmp1[1], tmp1[5], 0x31); - s[6] = _mm256_permute2x128_si256(tmp1[2], tmp1[6], 0x31); - s[7] = _mm256_permute2x128_si256(tmp1[3], tmp1[7], 0x31); -} - -void sha256_ctx_clone8x(sha256x8ctx *out, const sha256x8ctx *in) { - memcpy(out, in, sizeof(sha256x8ctx)); -} - -void sha256_init8x(sha256x8ctx *ctx) { - ctx->s[0] = _mm256_set_epi32((int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667); - ctx->s[1] = _mm256_set_epi32((int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85); - ctx->s[2] = _mm256_set_epi32((int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372); - ctx->s[3] = _mm256_set_epi32((int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a); - ctx->s[4] = _mm256_set_epi32((int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f); - ctx->s[5] = _mm256_set_epi32((int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c); - ctx->s[6] = _mm256_set_epi32((int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab); - ctx->s[7] = _mm256_set_epi32((int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19); - - ctx->datalen = 0; - ctx->msglen = 0; -} - -void sha256_final8x(sha256x8ctx *ctx, - unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7) { - unsigned int i, curlen; - - // Padding - if (ctx->datalen < 56) { - for (i = 0; i < 8; ++i) { - curlen = ctx->datalen; - ctx->msgblocks[64 * i + curlen++] = 0x80; - while (curlen < 64) { - ctx->msgblocks[64 * i + curlen++] = 0x00; - } - } - } else { - for (i = 0; i < 8; ++i) { - curlen = ctx->datalen; - ctx->msgblocks[64 * i + curlen++] = 0x80; - while (curlen < 64) { - ctx->msgblocks[64 * i + curlen++] = 0x00; - } - } - sha256_transform8x(ctx, - &ctx->msgblocks[64 * 0], - &ctx->msgblocks[64 * 1], - &ctx->msgblocks[64 * 2], - &ctx->msgblocks[64 * 3], - &ctx->msgblocks[64 * 4], - &ctx->msgblocks[64 * 5], - &ctx->msgblocks[64 * 6], - &ctx->msgblocks[64 * 7] - ); - memset(ctx->msgblocks, 0, 8 * 64); - } - - // Add length of the message to each block - ctx->msglen += ctx->datalen * 8; - for (i = 0; i < 8; i++) { - ctx->msgblocks[64 * i + 63] = (unsigned char)(ctx->msglen); - ctx->msgblocks[64 * i + 62] = (unsigned char)(ctx->msglen >> 8); - ctx->msgblocks[64 * i + 61] = (unsigned char)(ctx->msglen >> 16); - ctx->msgblocks[64 * i + 60] = (unsigned char)(ctx->msglen >> 24); - ctx->msgblocks[64 * i + 59] = (unsigned char)(ctx->msglen >> 32); - ctx->msgblocks[64 * i + 58] = (unsigned char)(ctx->msglen >> 40); - ctx->msgblocks[64 * i + 57] = (unsigned char)(ctx->msglen >> 48); - ctx->msgblocks[64 * i + 56] = (unsigned char)(ctx->msglen >> 56); - } - sha256_transform8x(ctx, - &ctx->msgblocks[64 * 0], - &ctx->msgblocks[64 * 1], - &ctx->msgblocks[64 * 2], - &ctx->msgblocks[64 * 3], - &ctx->msgblocks[64 * 4], - &ctx->msgblocks[64 * 5], - &ctx->msgblocks[64 * 6], - &ctx->msgblocks[64 * 7] - ); - - // Compute final hash output - transpose(ctx->s); - - // Store Hash value - STORE(out0, BYTESWAP(ctx->s[0])); - STORE(out1, BYTESWAP(ctx->s[1])); - STORE(out2, BYTESWAP(ctx->s[2])); - STORE(out3, BYTESWAP(ctx->s[3])); - STORE(out4, BYTESWAP(ctx->s[4])); - STORE(out5, BYTESWAP(ctx->s[5])); - STORE(out6, BYTESWAP(ctx->s[6])); - STORE(out7, BYTESWAP(ctx->s[7])); -} - -void sha256_transform8x(sha256x8ctx *ctx, - const unsigned char *data0, - const unsigned char *data1, - const unsigned char *data2, - const unsigned char *data3, - const unsigned char *data4, - const unsigned char *data5, - const unsigned char *data6, - const unsigned char *data7) { - u256 s[8], w[64], T0, T1; - - // Load words and transform data correctly - w[0] = BYTESWAP(LOAD(data0)); - w[0 + 8] = BYTESWAP(LOAD(data0 + 32)); - w[1] = BYTESWAP(LOAD(data1)); - w[1 + 8] = BYTESWAP(LOAD(data1 + 32)); - w[2] = BYTESWAP(LOAD(data2)); - w[2 + 8] = BYTESWAP(LOAD(data2 + 32)); - w[3] = BYTESWAP(LOAD(data3)); - w[3 + 8] = BYTESWAP(LOAD(data3 + 32)); - w[4] = BYTESWAP(LOAD(data4)); - w[4 + 8] = BYTESWAP(LOAD(data4 + 32)); - w[5] = BYTESWAP(LOAD(data5)); - w[5 + 8] = BYTESWAP(LOAD(data5 + 32)); - w[6] = BYTESWAP(LOAD(data6)); - w[6 + 8] = BYTESWAP(LOAD(data6 + 32)); - w[7] = BYTESWAP(LOAD(data7)); - w[7 + 8] = BYTESWAP(LOAD(data7 + 32)); - - transpose(w); - transpose(w + 8); - - // Initial State - s[0] = ctx->s[0]; - s[1] = ctx->s[1]; - s[2] = ctx->s[2]; - s[3] = ctx->s[3]; - s[4] = ctx->s[4]; - s[5] = ctx->s[5]; - s[6] = ctx->s[6]; - s[7] = ctx->s[7]; - - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 0, w[0]); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 1, w[1]); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 2, w[2]); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 3, w[3]); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 4, w[4]); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 5, w[5]); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 6, w[6]); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 7, w[7]); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 8, w[8]); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 9, w[9]); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 10, w[10]); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 11, w[11]); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 12, w[12]); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 13, w[13]); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 14, w[14]); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 15, w[15]); - w[16] = ADD4_32(WSIGMA1_AVX(w[14]), w[0], w[9], WSIGMA0_AVX(w[1])); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 16, w[16]); - w[17] = ADD4_32(WSIGMA1_AVX(w[15]), w[1], w[10], WSIGMA0_AVX(w[2])); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 17, w[17]); - w[18] = ADD4_32(WSIGMA1_AVX(w[16]), w[2], w[11], WSIGMA0_AVX(w[3])); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 18, w[18]); - w[19] = ADD4_32(WSIGMA1_AVX(w[17]), w[3], w[12], WSIGMA0_AVX(w[4])); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 19, w[19]); - w[20] = ADD4_32(WSIGMA1_AVX(w[18]), w[4], w[13], WSIGMA0_AVX(w[5])); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 20, w[20]); - w[21] = ADD4_32(WSIGMA1_AVX(w[19]), w[5], w[14], WSIGMA0_AVX(w[6])); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 21, w[21]); - w[22] = ADD4_32(WSIGMA1_AVX(w[20]), w[6], w[15], WSIGMA0_AVX(w[7])); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 22, w[22]); - w[23] = ADD4_32(WSIGMA1_AVX(w[21]), w[7], w[16], WSIGMA0_AVX(w[8])); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 23, w[23]); - w[24] = ADD4_32(WSIGMA1_AVX(w[22]), w[8], w[17], WSIGMA0_AVX(w[9])); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 24, w[24]); - w[25] = ADD4_32(WSIGMA1_AVX(w[23]), w[9], w[18], WSIGMA0_AVX(w[10])); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 25, w[25]); - w[26] = ADD4_32(WSIGMA1_AVX(w[24]), w[10], w[19], WSIGMA0_AVX(w[11])); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 26, w[26]); - w[27] = ADD4_32(WSIGMA1_AVX(w[25]), w[11], w[20], WSIGMA0_AVX(w[12])); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 27, w[27]); - w[28] = ADD4_32(WSIGMA1_AVX(w[26]), w[12], w[21], WSIGMA0_AVX(w[13])); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 28, w[28]); - w[29] = ADD4_32(WSIGMA1_AVX(w[27]), w[13], w[22], WSIGMA0_AVX(w[14])); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 29, w[29]); - w[30] = ADD4_32(WSIGMA1_AVX(w[28]), w[14], w[23], WSIGMA0_AVX(w[15])); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 30, w[30]); - w[31] = ADD4_32(WSIGMA1_AVX(w[29]), w[15], w[24], WSIGMA0_AVX(w[16])); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 31, w[31]); - w[32] = ADD4_32(WSIGMA1_AVX(w[30]), w[16], w[25], WSIGMA0_AVX(w[17])); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 32, w[32]); - w[33] = ADD4_32(WSIGMA1_AVX(w[31]), w[17], w[26], WSIGMA0_AVX(w[18])); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 33, w[33]); - w[34] = ADD4_32(WSIGMA1_AVX(w[32]), w[18], w[27], WSIGMA0_AVX(w[19])); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 34, w[34]); - w[35] = ADD4_32(WSIGMA1_AVX(w[33]), w[19], w[28], WSIGMA0_AVX(w[20])); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 35, w[35]); - w[36] = ADD4_32(WSIGMA1_AVX(w[34]), w[20], w[29], WSIGMA0_AVX(w[21])); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 36, w[36]); - w[37] = ADD4_32(WSIGMA1_AVX(w[35]), w[21], w[30], WSIGMA0_AVX(w[22])); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 37, w[37]); - w[38] = ADD4_32(WSIGMA1_AVX(w[36]), w[22], w[31], WSIGMA0_AVX(w[23])); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 38, w[38]); - w[39] = ADD4_32(WSIGMA1_AVX(w[37]), w[23], w[32], WSIGMA0_AVX(w[24])); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 39, w[39]); - w[40] = ADD4_32(WSIGMA1_AVX(w[38]), w[24], w[33], WSIGMA0_AVX(w[25])); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 40, w[40]); - w[41] = ADD4_32(WSIGMA1_AVX(w[39]), w[25], w[34], WSIGMA0_AVX(w[26])); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 41, w[41]); - w[42] = ADD4_32(WSIGMA1_AVX(w[40]), w[26], w[35], WSIGMA0_AVX(w[27])); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 42, w[42]); - w[43] = ADD4_32(WSIGMA1_AVX(w[41]), w[27], w[36], WSIGMA0_AVX(w[28])); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 43, w[43]); - w[44] = ADD4_32(WSIGMA1_AVX(w[42]), w[28], w[37], WSIGMA0_AVX(w[29])); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 44, w[44]); - w[45] = ADD4_32(WSIGMA1_AVX(w[43]), w[29], w[38], WSIGMA0_AVX(w[30])); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 45, w[45]); - w[46] = ADD4_32(WSIGMA1_AVX(w[44]), w[30], w[39], WSIGMA0_AVX(w[31])); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 46, w[46]); - w[47] = ADD4_32(WSIGMA1_AVX(w[45]), w[31], w[40], WSIGMA0_AVX(w[32])); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 47, w[47]); - w[48] = ADD4_32(WSIGMA1_AVX(w[46]), w[32], w[41], WSIGMA0_AVX(w[33])); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 48, w[48]); - w[49] = ADD4_32(WSIGMA1_AVX(w[47]), w[33], w[42], WSIGMA0_AVX(w[34])); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 49, w[49]); - w[50] = ADD4_32(WSIGMA1_AVX(w[48]), w[34], w[43], WSIGMA0_AVX(w[35])); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 50, w[50]); - w[51] = ADD4_32(WSIGMA1_AVX(w[49]), w[35], w[44], WSIGMA0_AVX(w[36])); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 51, w[51]); - w[52] = ADD4_32(WSIGMA1_AVX(w[50]), w[36], w[45], WSIGMA0_AVX(w[37])); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 52, w[52]); - w[53] = ADD4_32(WSIGMA1_AVX(w[51]), w[37], w[46], WSIGMA0_AVX(w[38])); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 53, w[53]); - w[54] = ADD4_32(WSIGMA1_AVX(w[52]), w[38], w[47], WSIGMA0_AVX(w[39])); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 54, w[54]); - w[55] = ADD4_32(WSIGMA1_AVX(w[53]), w[39], w[48], WSIGMA0_AVX(w[40])); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 55, w[55]); - w[56] = ADD4_32(WSIGMA1_AVX(w[54]), w[40], w[49], WSIGMA0_AVX(w[41])); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 56, w[56]); - w[57] = ADD4_32(WSIGMA1_AVX(w[55]), w[41], w[50], WSIGMA0_AVX(w[42])); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 57, w[57]); - w[58] = ADD4_32(WSIGMA1_AVX(w[56]), w[42], w[51], WSIGMA0_AVX(w[43])); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 58, w[58]); - w[59] = ADD4_32(WSIGMA1_AVX(w[57]), w[43], w[52], WSIGMA0_AVX(w[44])); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 59, w[59]); - w[60] = ADD4_32(WSIGMA1_AVX(w[58]), w[44], w[53], WSIGMA0_AVX(w[45])); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 60, w[60]); - w[61] = ADD4_32(WSIGMA1_AVX(w[59]), w[45], w[54], WSIGMA0_AVX(w[46])); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 61, w[61]); - w[62] = ADD4_32(WSIGMA1_AVX(w[60]), w[46], w[55], WSIGMA0_AVX(w[47])); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 62, w[62]); - w[63] = ADD4_32(WSIGMA1_AVX(w[61]), w[47], w[56], WSIGMA0_AVX(w[48])); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 63, w[63]); - - // Feed Forward - ctx->s[0] = ADD32(s[0], ctx->s[0]); - ctx->s[1] = ADD32(s[1], ctx->s[1]); - ctx->s[2] = ADD32(s[2], ctx->s[2]); - ctx->s[3] = ADD32(s[3], ctx->s[3]); - ctx->s[4] = ADD32(s[4], ctx->s[4]); - ctx->s[5] = ADD32(s[5], ctx->s[5]); - ctx->s[6] = ADD32(s[6], ctx->s[6]); - ctx->s[7] = ADD32(s[7], ctx->s[7]); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/sha256avx.h b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/sha256avx.h deleted file mode 100644 index 1e3bcf889b..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/sha256avx.h +++ /dev/null @@ -1,44 +0,0 @@ -#ifndef SHA256AVX_H -#define SHA256AVX_H - -#include -#include - -#include "params.h" - -typedef struct SHA256state { - __m256i s[8]; - unsigned char msgblocks[8 * 64]; - unsigned int datalen; - unsigned long long msglen; -} sha256x8ctx; - -#define sha256_ctx_clone8x SPX_NAMESPACE(sha256_ctx_clone8x) -void sha256_ctx_clone8x(sha256x8ctx *out, const sha256x8ctx *in); - -#define sha256_init8x SPX_NAMESPACE(sha256_init8x) -void sha256_init8x(sha256x8ctx *ctx); - -#define sha256_final8x SPX_NAMESPACE(sha256_final8x) -void sha256_final8x(sha256x8ctx *ctx, - unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7); - -#define sha256_transform8x SPX_NAMESPACE(sha256_transform8x) -void sha256_transform8x(sha256x8ctx *ctx, - const unsigned char *data0, - const unsigned char *data1, - const unsigned char *data2, - const unsigned char *data3, - const unsigned char *data4, - const unsigned char *data5, - const unsigned char *data6, - const unsigned char *data7); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/sha256x8.c b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/sha256x8.c deleted file mode 100644 index d97750c09b..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/sha256x8.c +++ /dev/null @@ -1,185 +0,0 @@ -#include - -#include "sha256avx.h" -#include "sha256x8.h" -#include "utils.h" - -// Performs sha256x8 on an initialized (and perhaps seeded) state. -static void _sha256x8( - sha256x8ctx *ctx, - unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - const unsigned char *in4, - const unsigned char *in5, - const unsigned char *in6, - const unsigned char *in7, unsigned long long inlen) { - unsigned long long i = 0; - while (inlen - i >= 64) { - sha256_transform8x(ctx, - in0 + i, - in1 + i, - in2 + i, - in3 + i, - in4 + i, - in5 + i, - in6 + i, - in7 + i - ); - i += 64; - ctx->msglen += 512; - } - - size_t bytes_to_copy = (size_t)(inlen - i); - memcpy(&ctx->msgblocks[64 * 0], in0 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64 * 1], in1 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64 * 2], in2 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64 * 3], in3 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64 * 4], in4 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64 * 5], in5 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64 * 6], in6 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64 * 7], in7 + i, bytes_to_copy); - ctx->datalen = (unsigned int)bytes_to_copy; - - sha256_final8x(ctx, out0, out1, out2, out3, out4, out5, out6, out7); -} - -void sha256x8_seeded( - unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7, - const sha256x8ctx *seed, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - const unsigned char *in4, - const unsigned char *in5, - const unsigned char *in6, - const unsigned char *in7, unsigned long long inlen) { - - sha256x8ctx ctx; - sha256_ctx_clone8x(&ctx, seed); - - _sha256x8(&ctx, out0, out1, out2, out3, out4, out5, out6, out7, - in0, in1, in2, in3, in4, in5, in6, in7, inlen); -} - -/* This provides a wrapper around the internals of 8x parallel SHA256 */ -void sha256x8(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - const unsigned char *in4, - const unsigned char *in5, - const unsigned char *in6, - const unsigned char *in7, unsigned long long inlen) { - sha256x8ctx ctx; - sha256_init8x(&ctx); - - _sha256x8(&ctx, out0, out1, out2, out3, out4, out5, out6, out7, - in0, in1, in2, in3, in4, in5, in6, in7, inlen); -} - -/** - * Note that inlen should be sufficiently small that it still allows for - * an array to be allocated on the stack. Typically 'in' is merely a seed. - * Outputs outlen number of bytes - */ -void mgf1x8(unsigned char *outx8, unsigned long outlen, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - const unsigned char *in4, - const unsigned char *in5, - const unsigned char *in6, - const unsigned char *in7, - unsigned long inlen) { - PQCLEAN_VLA(unsigned char, inbufx8, 8 * (inlen + 4)); - unsigned char outbufx8[8 * SPX_SHA256_OUTPUT_BYTES]; - uint32_t i; - unsigned int j; - - memcpy(inbufx8 + 0 * (inlen + 4), in0, inlen); - memcpy(inbufx8 + 1 * (inlen + 4), in1, inlen); - memcpy(inbufx8 + 2 * (inlen + 4), in2, inlen); - memcpy(inbufx8 + 3 * (inlen + 4), in3, inlen); - memcpy(inbufx8 + 4 * (inlen + 4), in4, inlen); - memcpy(inbufx8 + 5 * (inlen + 4), in5, inlen); - memcpy(inbufx8 + 6 * (inlen + 4), in6, inlen); - memcpy(inbufx8 + 7 * (inlen + 4), in7, inlen); - - /* While we can fit in at least another full block of SHA256 output.. */ - for (i = 0; (i + 1)*SPX_SHA256_OUTPUT_BYTES <= outlen; i++) { - for (j = 0; j < 8; j++) { - u32_to_bytes(inbufx8 + inlen + j * (inlen + 4), i); - } - - sha256x8(outx8 + 0 * outlen, - outx8 + 1 * outlen, - outx8 + 2 * outlen, - outx8 + 3 * outlen, - outx8 + 4 * outlen, - outx8 + 5 * outlen, - outx8 + 6 * outlen, - outx8 + 7 * outlen, - inbufx8 + 0 * (inlen + 4), - inbufx8 + 1 * (inlen + 4), - inbufx8 + 2 * (inlen + 4), - inbufx8 + 3 * (inlen + 4), - inbufx8 + 4 * (inlen + 4), - inbufx8 + 5 * (inlen + 4), - inbufx8 + 6 * (inlen + 4), - inbufx8 + 7 * (inlen + 4), inlen + 4); - outx8 += SPX_SHA256_OUTPUT_BYTES; - } - /* Until we cannot anymore, and we fill the remainder. */ - for (j = 0; j < 8; j++) { - u32_to_bytes(inbufx8 + inlen + j * (inlen + 4), i); - } - sha256x8(outbufx8 + 0 * SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 1 * SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 2 * SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 3 * SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 4 * SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 5 * SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 6 * SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 7 * SPX_SHA256_OUTPUT_BYTES, - inbufx8 + 0 * (inlen + 4), - inbufx8 + 1 * (inlen + 4), - inbufx8 + 2 * (inlen + 4), - inbufx8 + 3 * (inlen + 4), - inbufx8 + 4 * (inlen + 4), - inbufx8 + 5 * (inlen + 4), - inbufx8 + 6 * (inlen + 4), - inbufx8 + 7 * (inlen + 4), inlen + 4); - - for (j = 0; j < 8; j++) { - memcpy(outx8 + j * outlen, - outbufx8 + j * SPX_SHA256_OUTPUT_BYTES, - outlen - i * SPX_SHA256_OUTPUT_BYTES); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/sha256x8.h b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/sha256x8.h deleted file mode 100644 index 4f7330a6c1..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/sha256x8.h +++ /dev/null @@ -1,64 +0,0 @@ -#ifndef SPX_SHA256X8_H -#define SPX_SHA256X8_H - -#include "params.h" -#include "sha256avx.h" - - - -#define sha256x8_seeded SPX_NAMESPACE(sha256x8_seeded) -void sha256x8_seeded( - unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7, - const sha256x8ctx *seed, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - const unsigned char *in4, - const unsigned char *in5, - const unsigned char *in6, - const unsigned char *in7, unsigned long long inlen); - -/* This provides a wrapper around the internals of 8x parallel SHA256 */ -#define sha256x8 SPX_NAMESPACE(sha256x8) -void sha256x8(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - const unsigned char *in4, - const unsigned char *in5, - const unsigned char *in6, - const unsigned char *in7, unsigned long long inlen); - -/** - * Note that inlen should be sufficiently small that it still allows for - * an array to be allocated on the stack. Typically 'in' is merely a seed. - * Outputs outlen number of bytes - */ -#define mgf1x8 SPX_NAMESPACE(mgf1x8) -void mgf1x8(unsigned char *outx8, unsigned long outlen, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - const unsigned char *in4, - const unsigned char *in5, - const unsigned char *in6, - const unsigned char *in7, - unsigned long inlen); -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/sha2_offsets.h b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/sha2_offsets.h deleted file mode 100644 index 6e3584f7a4..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/sha2_offsets.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef SHA2_OFFSETS_H_ -#define SHA2_OFFSETS_H_ - -#define SPX_SHA256_BLOCK_BYTES 64 -#define SPX_SHA256_OUTPUT_BYTES 32 - -#define SPX_SHA512_BLOCK_BYTES 128 -#define SPX_SHA512_OUTPUT_BYTES 64 - -/* - * Offsets of various fields in the address structure when we use SHA2 as - * the Sphincs+ hash function - */ - -#define SPX_OFFSET_LAYER 0 /* The byte used to specify the Merkle tree layer */ -#define SPX_OFFSET_TREE 1 /* The start of the 8 byte field used to specify the tree */ -#define SPX_OFFSET_TYPE 9 /* The byte used to specify the hash type (reason) */ -#define SPX_OFFSET_KP_ADDR2 12 /* The high byte used to specify the key pair (which one-time signature) */ -#define SPX_OFFSET_KP_ADDR1 13 /* The low byte used to specify the key pair */ -#define SPX_OFFSET_CHAIN_ADDR 17 /* The byte used to specify the chain address (which Winternitz chain) */ -#define SPX_OFFSET_HASH_ADDR 21 /* The byte used to specify the hash address (where in the Winternitz chain) */ -#define SPX_OFFSET_TREE_HGT 17 /* The byte used to specify the height of this node in the FORS or Merkle tree */ -#define SPX_OFFSET_TREE_INDEX 18 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ - -#define SPX_SHA2 1 - -#endif /* SHA2_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/sign.c b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/sign.c deleted file mode 100644 index 9d0c7d1b22..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/sign.c +++ /dev/null @@ -1,286 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "context.h" -#include "fors.h" -#include "hash.h" -#include "merkle.h" -#include "nistapi.h" -#include "params.h" -#include "randombytes.h" -#include "thash.h" -#include "utils.h" -#include "wots.h" - -/* - * Returns the length of a secret key, in bytes - */ -size_t crypto_sign_secretkeybytes(void) { - return CRYPTO_SECRETKEYBYTES; -} - -/* - * Returns the length of a public key, in bytes - */ -size_t crypto_sign_publickeybytes(void) { - return CRYPTO_PUBLICKEYBYTES; -} - -/* - * Returns the length of a signature, in bytes - */ -size_t crypto_sign_bytes(void) { - return CRYPTO_BYTES; -} - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t crypto_sign_seedbytes(void) { - return CRYPTO_SEEDBYTES; -} - -/* - * Generates an SPX key pair given a seed of length - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed) { - spx_ctx ctx; - - /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ - memcpy(sk, seed, CRYPTO_SEEDBYTES); - - memcpy(pk, sk + 2 * SPX_N, SPX_N); - - memcpy(ctx.pub_seed, pk, SPX_N); - memcpy(ctx.sk_seed, sk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - /* Compute root node of the top-most subtree. */ - merkle_gen_root(sk + 3 * SPX_N, &ctx); - - // cleanup - free_hash_function(&ctx); - - memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); - - return 0; -} - -/* - * Generates an SPX key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { - uint8_t seed[CRYPTO_SEEDBYTES]; - randombytes(seed, CRYPTO_SEEDBYTES); - crypto_sign_seed_keypair(pk, sk, seed); - - return 0; -} - -/** - * Returns an array containing a detached signature. - */ -int crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - spx_ctx ctx; - - const uint8_t *sk_prf = sk + SPX_N; - const uint8_t *pk = sk + 2 * SPX_N; - - uint8_t optrand[SPX_N]; - uint8_t mhash[SPX_FORS_MSG_BYTES]; - uint8_t root[SPX_N]; - uint32_t i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - - memcpy(ctx.sk_seed, sk, SPX_N); - memcpy(ctx.pub_seed, pk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - set_type(wots_addr, SPX_ADDR_TYPE_WOTS); - set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); - - /* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ - randombytes(optrand, SPX_N); - /* Compute the digest randomization value. */ - gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); - - /* Derive the message digest and leaf index from R, PK and M. */ - hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); - sig += SPX_N; - - set_tree_addr(wots_addr, tree); - set_keypair_addr(wots_addr, idx_leaf); - - /* Sign the message hash using FORS. */ - fors_sign(sig, root, mhash, &ctx, wots_addr); - sig += SPX_FORS_BYTES; - - for (i = 0; i < SPX_D; i++) { - set_layer_addr(tree_addr, i); - set_tree_addr(tree_addr, tree); - - copy_subtree_addr(wots_addr, tree_addr); - set_keypair_addr(wots_addr, idx_leaf); - - merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); - sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); - tree = tree >> SPX_TREE_HEIGHT; - } - - free_hash_function(&ctx); - - *siglen = SPX_BYTES; - - return 0; -} - -/** - * Verifies a detached signature and message under a given public key. - */ -int crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk) { - spx_ctx ctx; - const uint8_t *pub_root = pk + SPX_N; - uint8_t mhash[SPX_FORS_MSG_BYTES]; - uint8_t wots_pk[SPX_WOTS_BYTES]; - uint8_t root[SPX_N]; - uint8_t leaf[SPX_N]; - unsigned int i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - if (siglen != SPX_BYTES) { - return -1; - } - - memcpy(ctx.pub_seed, pk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - set_type(wots_addr, SPX_ADDR_TYPE_WOTS); - set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); - set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); - - /* Derive the message digest and leaf index from R || PK || M. */ - /* The additional SPX_N is a result of the hash domain separator. */ - hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); - sig += SPX_N; - - /* Layer correctly defaults to 0, so no need to set_layer_addr */ - set_tree_addr(wots_addr, tree); - set_keypair_addr(wots_addr, idx_leaf); - - fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); - sig += SPX_FORS_BYTES; - - /* For each subtree.. */ - for (i = 0; i < SPX_D; i++) { - set_layer_addr(tree_addr, i); - set_tree_addr(tree_addr, tree); - - copy_subtree_addr(wots_addr, tree_addr); - set_keypair_addr(wots_addr, idx_leaf); - - copy_keypair_addr(wots_pk_addr, wots_addr); - - /* The WOTS public key is only correct if the signature was correct. */ - /* Initially, root is the FORS pk, but on subsequent iterations it is - the root of the subtree below the currently processed subtree. */ - wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); - sig += SPX_WOTS_BYTES; - - /* Compute the leaf node using the WOTS public key. */ - thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); - - /* Compute the root node of this subtree. */ - compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, - &ctx, tree_addr); - sig += SPX_TREE_HEIGHT * SPX_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); - tree = tree >> SPX_TREE_HEIGHT; - } - - // cleanup - free_hash_function(&ctx); - - /* Check if the root node equals the root node in the public key. */ - if (memcmp(root, pub_root, SPX_N) != 0) { - return -1; - } - - return 0; -} - - -/** - * Returns an array containing the signature followed by the message. - */ -int crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk) { - size_t siglen; - - crypto_sign_signature(sm, &siglen, m, mlen, sk); - - memmove(sm + SPX_BYTES, m, mlen); - *smlen = siglen + mlen; - - return 0; -} - -/** - * Verifies a given signature-message pair under a given public key. - */ -int crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk) { - /* The API caller does not necessarily know what size a signature should be - but SPHINCS+ signatures are always exactly SPX_BYTES. */ - if (smlen < SPX_BYTES) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - *mlen = smlen - SPX_BYTES; - - if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - /* If verification was successful, move the message to the right place. */ - memmove(m, sm + SPX_BYTES, *mlen); - - return 0; -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/thash.h b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/thash.h deleted file mode 100644 index 8687ccfb4d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/thash.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef SPX_THASH_H -#define SPX_THASH_H - -#include "context.h" -#include "params.h" - -#include - -#define thash SPX_NAMESPACE(thash) -void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/thash_sha2_robust.c b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/thash_sha2_robust.c deleted file mode 100644 index 18f65c2e42..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/thash_sha2_robust.c +++ /dev/null @@ -1,39 +0,0 @@ -#include -#include - -#include "address.h" -#include "context.h" -#include "hash.h" -#include "params.h" -#include "sha2.h" -#include "thash.h" -#include "utils.h" - - -/** - * Takes an array of inblocks concatenated arrays of SPX_N bytes. - */ -void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]) { - unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES]; - PQCLEAN_VLA(uint8_t, bitmask, inblocks * SPX_N); - PQCLEAN_VLA(uint8_t, buf, SPX_N + SPX_SHA256_OUTPUT_BYTES + inblocks * SPX_N); - sha256ctx sha2_state; - unsigned int i; - - memcpy(buf, ctx->pub_seed, SPX_N); - memcpy(buf + SPX_N, addr, SPX_SHA256_ADDR_BYTES); - mgf1_256(bitmask, inblocks * SPX_N, buf, SPX_N + SPX_SHA256_ADDR_BYTES); - - /* Retrieve precomputed state containing pub_seed */ - sha256_inc_ctx_clone(&sha2_state, &ctx->state_seeded); - - for (i = 0; i < inblocks * SPX_N; i++) { - buf[SPX_N + SPX_SHA256_ADDR_BYTES + i] = in[i] ^ bitmask[i]; - } - - sha256_inc_finalize(outbuf, &sha2_state, buf + SPX_N, - SPX_SHA256_ADDR_BYTES + inblocks * SPX_N); - memcpy(out, outbuf, SPX_N); -} - diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/thash_sha2_robustx8.c b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/thash_sha2_robustx8.c deleted file mode 100644 index 09ae4e1265..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/thash_sha2_robustx8.c +++ /dev/null @@ -1,121 +0,0 @@ -#include -#include - -#include "thashx8.h" - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "sha2.h" -#include "sha256avx.h" -#include "sha256x8.h" -#include "utils.h" - - -/** - * 8-way parallel version of thash; takes 8x as much input and output - */ -void thashx8(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - const unsigned char *in4, - const unsigned char *in5, - const unsigned char *in6, - const unsigned char *in7, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addrx8[8 * 8]) { - PQCLEAN_VLA(unsigned char, bufx8, 8 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)); - unsigned char outbufx8[8 * SPX_SHA256_OUTPUT_BYTES]; - PQCLEAN_VLA(unsigned char, bitmaskx8, 8 * (inblocks * SPX_N)); - unsigned int i; - - for (i = 0; i < 8; i++) { - memcpy(bufx8 + i * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - ctx->pub_seed, SPX_N); - memcpy(bufx8 + SPX_N + - i * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - addrx8 + i * 8, SPX_SHA256_ADDR_BYTES); - } - - mgf1x8(bitmaskx8, inblocks * SPX_N, - bufx8 + 0 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + 1 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + 2 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + 3 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + 4 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + 5 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + 6 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + 7 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - SPX_N + SPX_SHA256_ADDR_BYTES); - - for (i = 0; i < inblocks * SPX_N; i++) { - bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + - 0 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = - in0[i] ^ bitmaskx8[i + 0 * (inblocks * SPX_N)]; - bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + - 1 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = - in1[i] ^ bitmaskx8[i + 1 * (inblocks * SPX_N)]; - bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + - 2 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = - in2[i] ^ bitmaskx8[i + 2 * (inblocks * SPX_N)]; - bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + - 3 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = - in3[i] ^ bitmaskx8[i + 3 * (inblocks * SPX_N)]; - bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + - 4 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = - in4[i] ^ bitmaskx8[i + 4 * (inblocks * SPX_N)]; - bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + - 5 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = - in5[i] ^ bitmaskx8[i + 5 * (inblocks * SPX_N)]; - bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + - 6 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = - in6[i] ^ bitmaskx8[i + 6 * (inblocks * SPX_N)]; - bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + - 7 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = - in7[i] ^ bitmaskx8[i + 7 * (inblocks * SPX_N)]; - } - - sha256x8_seeded( - /* out */ - outbufx8 + 0 * SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 1 * SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 2 * SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 3 * SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 4 * SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 5 * SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 6 * SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 7 * SPX_SHA256_OUTPUT_BYTES, - - /* seed */ - &ctx->statex8_seeded, - - /* in */ - bufx8 + SPX_N + 0 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + SPX_N + 1 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + SPX_N + 2 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + SPX_N + 3 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + SPX_N + 4 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + SPX_N + 5 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + SPX_N + 6 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + SPX_N + 7 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - SPX_SHA256_ADDR_BYTES + inblocks * SPX_N /* len */ - ); - - memcpy(out0, outbufx8 + 0 * SPX_SHA256_OUTPUT_BYTES, SPX_N); - memcpy(out1, outbufx8 + 1 * SPX_SHA256_OUTPUT_BYTES, SPX_N); - memcpy(out2, outbufx8 + 2 * SPX_SHA256_OUTPUT_BYTES, SPX_N); - memcpy(out3, outbufx8 + 3 * SPX_SHA256_OUTPUT_BYTES, SPX_N); - memcpy(out4, outbufx8 + 4 * SPX_SHA256_OUTPUT_BYTES, SPX_N); - memcpy(out5, outbufx8 + 5 * SPX_SHA256_OUTPUT_BYTES, SPX_N); - memcpy(out6, outbufx8 + 6 * SPX_SHA256_OUTPUT_BYTES, SPX_N); - memcpy(out7, outbufx8 + 7 * SPX_SHA256_OUTPUT_BYTES, SPX_N); -} - diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/thashx8.h b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/thashx8.h deleted file mode 100644 index c02fe9cf3e..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/thashx8.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef SPX_THASHX8_H -#define SPX_THASHX8_H - -#include - -#include "context.h" -#include "params.h" - -#define thashx8 SPX_NAMESPACE(thashx8) -void thashx8(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - const unsigned char *in4, - const unsigned char *in5, - const unsigned char *in6, - const unsigned char *in7, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addrx8[8 * 8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/utils.c b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/utils.c deleted file mode 100644 index 177b541fb9..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/utils.c +++ /dev/null @@ -1,148 +0,0 @@ -#include - -#include "utils.h" - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "thash.h" - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void ull_to_bytes(unsigned char *out, unsigned int outlen, - unsigned long long in) { - int i; - - /* Iterate over out in decreasing order, for big-endianness. */ - for (i = (signed int)outlen - 1; i >= 0; i--) { - out[i] = in & 0xff; - in = in >> 8; - } -} - -void u32_to_bytes(unsigned char *out, uint32_t in) { - out[0] = (unsigned char)(in >> 24); - out[1] = (unsigned char)(in >> 16); - out[2] = (unsigned char)(in >> 8); - out[3] = (unsigned char)in; -} - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { - unsigned long long retval = 0; - unsigned int i; - - for (i = 0; i < inlen; i++) { - retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); - } - return retval; -} - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void compute_root(unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const spx_ctx *ctx, uint32_t addr[8]) { - uint32_t i; - unsigned char buffer[2 * SPX_N]; - - /* If leaf_idx is odd (last bit = 1), current path element is a right child - and auth_path has to go left. Otherwise it is the other way around. */ - if (leaf_idx & 1) { - memcpy(buffer + SPX_N, leaf, SPX_N); - memcpy(buffer, auth_path, SPX_N); - } else { - memcpy(buffer, leaf, SPX_N); - memcpy(buffer + SPX_N, auth_path, SPX_N); - } - auth_path += SPX_N; - - for (i = 0; i < tree_height - 1; i++) { - leaf_idx >>= 1; - idx_offset >>= 1; - /* Set the address of the node we're creating. */ - set_tree_height(addr, i + 1); - set_tree_index(addr, leaf_idx + idx_offset); - - /* Pick the right or left neighbor, depending on parity of the node. */ - if (leaf_idx & 1) { - thash(buffer + SPX_N, buffer, 2, ctx, addr); - memcpy(buffer, auth_path, SPX_N); - } else { - thash(buffer, buffer, 2, ctx, addr); - memcpy(buffer + SPX_N, auth_path, SPX_N); - } - auth_path += SPX_N; - } - - /* The last iteration is exceptional; we do not copy an auth_path node. */ - leaf_idx >>= 1; - idx_offset >>= 1; - set_tree_height(addr, tree_height); - set_tree_index(addr, leaf_idx + idx_offset); - thash(root, buffer, 2, ctx, addr); -} - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const spx_ctx * /* ctx */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), - uint32_t tree_addr[8]) { - PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); - PQCLEAN_VLA(unsigned int, heights, tree_height + 1); - unsigned int offset = 0; - uint32_t idx; - uint32_t tree_idx; - - for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { - /* Add the next leaf node to the stack. */ - gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); - offset++; - heights[offset - 1] = 0; - - /* If this is a node we need for the auth path.. */ - if ((leaf_idx ^ 0x1) == idx) { - memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); - } - - /* While the top-most nodes are of equal height.. */ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { - /* Compute index of the new node, in the next layer. */ - tree_idx = (idx >> (heights[offset - 1] + 1)); - - /* Set the address of the node we're creating. */ - set_tree_height(tree_addr, heights[offset - 1] + 1); - set_tree_index(tree_addr, - tree_idx + (idx_offset >> (heights[offset - 1] + 1))); - /* Hash the top-most nodes from the stack together. */ - thash(stack + (offset - 2)*SPX_N, - stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); - offset--; - /* Note that the top-most node is now one layer higher. */ - heights[offset - 1]++; - - /* If this is a node we need for the auth path.. */ - if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_path + heights[offset - 1]*SPX_N, - stack + (offset - 1)*SPX_N, SPX_N); - } - } - } - memcpy(root, stack, SPX_N); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/utils.h b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/utils.h deleted file mode 100644 index 64f5d5a53a..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/utils.h +++ /dev/null @@ -1,58 +0,0 @@ -#ifndef SPX_UTILS_H -#define SPX_UTILS_H - -#include - -#include "compat.h" -#include "context.h" -#include "params.h" - - -/* To support MSVC use alloca() instead of VLAs. See #20. */ - - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) -void ull_to_bytes(unsigned char *out, unsigned int outlen, - unsigned long long in); -#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) -void u32_to_bytes(unsigned char *out, uint32_t in); - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) -unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -#define compute_root SPX_NAMESPACE(compute_root) -void compute_root(unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const spx_ctx *ctx, uint32_t addr[8]); - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -#define treehash SPX_NAMESPACE(treehash) -void treehash(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const spx_ctx *ctx /* ctx */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), - uint32_t tree_addr[8]); - - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/utilsx8.c b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/utilsx8.c deleted file mode 100644 index f044b9595d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/utilsx8.c +++ /dev/null @@ -1,146 +0,0 @@ -#include - -#include "utils.h" -#include "utilsx8.h" - -#include "address.h" -#include "params.h" -#include "thashx8.h" - -/* - * Generate the entire Merkle tree, computing the authentication path for leaf_idx, - * and the resulting root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) - * - * This expects tree_addrx8 to be initialized to 8 parallel addr structures for - * the Merkle tree nodes - * - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - * - * This works by using the standard Merkle tree building algorithm, except - * that each 'node' tracked is actually 8 consecutive nodes in the real tree. - * When we combine two logical nodes ABCDEFGH and STUVWXYZ, we perform the H - * operation on adjacent real nodes, forming the parent logical node - * (AB)(CD)(EF)(GH)(ST)(UV)(WX)(YZ) - * - * When we get to the top three levels of the real tree (where there is only - * one logical node), we continue this operation three more times; the right - * most real node will by the actual root (and the other 7 nodes will be - * garbage). We follow the same thashx8 logic so that the 'extract - * authentication path components' part of the loop is still executed (and - * to simplify the code somewhat) - * - * This currently assumes tree_height >= 3; I suspect that doing an adjusting - * idx, addr_idx on the gen_leafx8 call if tree_height < 3 would fix it; since - * we don't actually use such short trees, I haven't bothered - */ -void treehashx8(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, - uint32_t tree_height, - void (*gen_leafx8)( - unsigned char * /* Where to write the leaves */, - const spx_ctx *, - uint32_t idx, void *info), - uint32_t tree_addrx8[8 * 8], - void *info) { - /* This is where we keep the intermediate nodes */ - PQCLEAN_VLA(unsigned char, stackx8, tree_height * 8 * SPX_N); - uint32_t left_adj = 0, prev_left_adj = 0; /* When we're doing the top 3 */ - /* levels, the left-most part of the tree isn't at the beginning */ - /* of current[]. These give the offset of the actual start */ - - uint32_t idx; - uint32_t max_idx = ((uint32_t)1 << (tree_height - 3)) - 1; - for (idx = 0;; idx++) { - unsigned char current[8 * SPX_N]; /* Current logical node */ - gen_leafx8( current, ctx, 8 * idx + idx_offset, - info ); - - /* Now combine the freshly generated right node with previously */ - /* generated left ones */ - uint32_t internal_idx_offset = idx_offset; - uint32_t internal_idx = idx; - uint32_t internal_leaf = leaf_idx; - uint32_t h; /* The height we are in the Merkle tree */ - for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { - - /* Special processing if we're at the top of the tree */ - if (h >= tree_height - 3) { - if (h == tree_height) { - /* We hit the root; return it */ - memcpy( root, ¤t[7 * SPX_N], SPX_N ); - return; - } - /* The tree indexing logic is a bit off in this case */ - /* Adjust it so that the left-most node of the part of */ - /* the tree that we're processing has index 0 */ - prev_left_adj = left_adj; - left_adj = (uint32_t)(8 - (1 << (tree_height - h - 1))); - } - - /* Check if we hit the top of the tree */ - if (h == tree_height) { - /* We hit the root; return it */ - memcpy( root, ¤t[7 * SPX_N], SPX_N ); - return; - } - - /* - * Check if one of the nodes we have is a part of the - * authentication path; if it is, write it out - */ - if ((((internal_idx << 3) ^ internal_leaf) & ~0x7U) == 0) { - memcpy( &auth_path[ h * SPX_N ], - ¤t[(((internal_leaf & 7) ^ 1) + prev_left_adj) * SPX_N], - SPX_N ); - } - - /* - * Check if we're at a left child; if so, stop going up the stack - * Exception: if we've reached the end of the tree, keep on going - * (so we combine the last 8 nodes into the one root node in three - * more iterations) - */ - if ((internal_idx & 1) == 0 && idx < max_idx) { - break; - } - - /* Ok, we're at a right node (or doing the top 3 levels) */ - /* Now combine the left and right logical nodes together */ - - /* Set the address of the node we're creating. */ - uint32_t j; - internal_idx_offset >>= 1; - for (j = 0; j < 8; j++) { - set_tree_height(tree_addrx8 + j * 8, h + 1); - set_tree_index(tree_addrx8 + j * 8, - (8 / 2) * (internal_idx & ~1U) + j - left_adj + internal_idx_offset ); - } - unsigned char *left = &stackx8[h * 8 * SPX_N]; - thashx8( ¤t[0 * SPX_N], - ¤t[1 * SPX_N], - ¤t[2 * SPX_N], - ¤t[3 * SPX_N], - ¤t[4 * SPX_N], - ¤t[5 * SPX_N], - ¤t[6 * SPX_N], - ¤t[7 * SPX_N], - &left [0 * SPX_N], - &left [2 * SPX_N], - &left [4 * SPX_N], - &left [6 * SPX_N], - ¤t[0 * SPX_N], - ¤t[2 * SPX_N], - ¤t[4 * SPX_N], - ¤t[6 * SPX_N], - 2, ctx, tree_addrx8); - } - - /* We've hit a left child; save the current for when we get the */ - /* corresponding right right */ - memcpy( &stackx8[h * 8 * SPX_N], current, 8 * SPX_N); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/utilsx8.h b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/utilsx8.h deleted file mode 100644 index 806d1e85be..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/utilsx8.h +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef SPX_UTILSX8_H -#define SPX_UTILSX8_H - -#include - -#include "params.h" - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - * - * This implementation uses AVX to compute internal nodes 8 at a time (in - * parallel) - */ -#define treehashx8 SPX_NAMESPACE(treehashx8) -void treehashx8(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leafx8)( - unsigned char * /* Where to write the leaves */, - const spx_ctx * /* ctx */, - uint32_t addr_idx, void *info), - uint32_t tree_addrx8[8 * 8], void *info); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/wots.c b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/wots.c deleted file mode 100644 index 689baf4db9..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/wots.c +++ /dev/null @@ -1,291 +0,0 @@ -#include -#include - -#include "wots.h" - -#include "address.h" -#include "hash.h" -#include "hashx8.h" -#include "params.h" -#include "thash.h" -#include "thashx8.h" -#include "utils.h" -#include "utilsx8.h" -#include "wotsx8.h" - -// TODO clarify address expectations, and make them more uniform. -// TODO i.e. do we expect types to be set already? -// TODO and do we expect modifications or copies? - -/** - * Computes up the chains - */ -static void gen_chains( - unsigned char *out, - const unsigned char *in, - unsigned int start[SPX_WOTS_LEN], - const unsigned int steps[SPX_WOTS_LEN], - const spx_ctx *ctx, - uint32_t addr[8]) { - uint32_t i, j, k, idx, watching; - int done; - unsigned char empty[SPX_N]; - unsigned char *bufs[8]; - uint32_t addrs[8 * 8]; - - int l; - uint16_t counts[SPX_WOTS_W] = { 0 }; - uint16_t idxs[SPX_WOTS_LEN]; - uint16_t total, newTotal; - - /* set addrs = {addr, addr, ..., addr} */ - for (j = 0; j < 8; j++) { - memcpy(addrs + j * 8, addr, sizeof(uint32_t) * 8); - } - - /* Initialize out with the value at position 'start'. */ - memcpy(out, in, SPX_WOTS_LEN * SPX_N); - - /* Sort the chains in reverse order by steps using counting sort. */ - for (i = 0; i < SPX_WOTS_LEN; i++) { - counts[steps[i]]++; - } - total = 0; - for (l = SPX_WOTS_W - 1; l >= 0; l--) { - newTotal = counts[l] + total; - counts[l] = total; - total = newTotal; - } - for (i = 0; i < SPX_WOTS_LEN; i++) { - idxs[counts[steps[i]]] = (uint16_t)i; - counts[steps[i]]++; - } - - /* We got our work cut out for us: do it! */ - for (i = 0; i < SPX_WOTS_LEN; i += 8) { - for (j = 0; j < 8 && i + j < SPX_WOTS_LEN; j++) { - idx = idxs[i + j]; - set_chain_addr(addrs + j * 8, idx); - bufs[j] = out + SPX_N * idx; - } - - /* As the chains are sorted in reverse order, we know that the first - * chain is the longest and the last one is the shortest. We keep - * an eye on whether the last chain is done and then on the one before, - * et cetera. */ - watching = 7; - done = 0; - while (i + watching >= SPX_WOTS_LEN) { - bufs[watching] = &empty[0]; - watching--; - } - - for (k = 0;; k++) { - while (k == steps[idxs[i + watching]]) { - bufs[watching] = &empty[0]; - if (watching == 0) { - done = 1; - break; - } - watching--; - } - if (done) { - break; - } - for (j = 0; j < watching + 1; j++) { - set_hash_addr(addrs + j * 8, k + start[idxs[i + j]]); - } - - thashx8(bufs[0], bufs[1], bufs[2], bufs[3], - bufs[4], bufs[5], bufs[6], bufs[7], - bufs[0], bufs[1], bufs[2], bufs[3], - bufs[4], bufs[5], bufs[6], bufs[7], 1, ctx, addrs); - } - } -} - -/** - * base_w algorithm as described in draft. - * Interprets an array of bytes as integers in base w. - * This only works when log_w is a divisor of 8. - */ -static void base_w(unsigned int *output, const int out_len, - const unsigned char *input) { - int in = 0; - int out = 0; - unsigned char total = 0; - int bits = 0; - int consumed; - - for (consumed = 0; consumed < out_len; consumed++) { - if (bits == 0) { - total = input[in]; - in++; - bits += 8; - } - bits -= SPX_WOTS_LOGW; - output[out] = (total >> bits) & (SPX_WOTS_W - 1); - out++; - } -} - -/* Computes the WOTS+ checksum over a message (in base_w). */ -static void wots_checksum(unsigned int *csum_base_w, - const unsigned int *msg_base_w) { - unsigned int csum = 0; - unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; - unsigned int i; - - /* Compute checksum. */ - for (i = 0; i < SPX_WOTS_LEN1; i++) { - csum += SPX_WOTS_W - 1 - msg_base_w[i]; - } - - /* Convert checksum to base_w. */ - /* Make sure expected empty zero bits are the least significant bits. */ - csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); - ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); - base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); -} - -/* Takes a message and derives the matching chain lengths. */ -void chain_lengths(unsigned int *lengths, const unsigned char *msg) { - base_w(lengths, SPX_WOTS_LEN1, msg); - wots_checksum(lengths + SPX_WOTS_LEN1, lengths); -} - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const spx_ctx *ctx, uint32_t addr[8]) { - unsigned int steps[SPX_WOTS_LEN]; - unsigned int start[SPX_WOTS_LEN]; - uint32_t i; - - chain_lengths(start, msg); - - for (i = 0; i < SPX_WOTS_LEN; i++) { - steps[i] = SPX_WOTS_W - 1 - start[i]; - } - - gen_chains(pk, sig, start, steps, ctx, addr); -} - -/* - * This generates 8 sequential WOTS public keys - * It also generates the WOTS signature if leaf_info indicates - * that we're signing with one of these WOTS keys - */ -void wots_gen_leafx8(unsigned char *dest, - const spx_ctx *ctx, - uint32_t leaf_idx, void *v_info) { - struct leaf_info_x8 *info = v_info; - uint32_t *leaf_addr = info->leaf_addr; - uint32_t *pk_addr = info->pk_addr; - unsigned int i, j, k; - unsigned char pk_buffer[ 8 * SPX_WOTS_BYTES ]; - unsigned wots_offset = SPX_WOTS_BYTES; - unsigned char *buffer; - uint32_t wots_k_mask; - unsigned wots_sign_index; - - if (((leaf_idx ^ info->wots_sign_leaf) & ~7U) == 0) { - /* We're traversing the leaf that's signing; generate the WOTS */ - /* signature */ - wots_k_mask = 0; - wots_sign_index = info->wots_sign_leaf & 7; /* Which of of the 8 */ - /* slots do the signatures come from */ - } else { - /* Nope, we're just generating pk's; turn off the signature logic */ - wots_k_mask = ~0U; - wots_sign_index = 0; - } - - for (j = 0; j < 8; j++) { - set_keypair_addr( leaf_addr + j * 8, leaf_idx + j ); - set_keypair_addr( pk_addr + j * 8, leaf_idx + j ); - } - - for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { - uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k */ - /* to the step if we're generating a signature, ~0 if we're not */ - - /* Start with the secret seed */ - for (j = 0; j < 8; j++) { - set_chain_addr(leaf_addr + j * 8, i); - set_hash_addr(leaf_addr + j * 8, 0); - set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTSPRF); - } - prf_addrx8(buffer + 0 * wots_offset, - buffer + 1 * wots_offset, - buffer + 2 * wots_offset, - buffer + 3 * wots_offset, - buffer + 4 * wots_offset, - buffer + 5 * wots_offset, - buffer + 6 * wots_offset, - buffer + 7 * wots_offset, - ctx, leaf_addr); - - for (j = 0; j < 8; j++) { - set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTS); - } - - /* Iterate down the WOTS chain */ - for (k = 0;; k++) { - /* Check if one of the values we have needs to be saved as a */ - /* part of the WOTS signature */ - if (k == wots_k) { - memcpy( info->wots_sig + i * SPX_N, - buffer + wots_sign_index * wots_offset, SPX_N ); - } - - /* Check if we hit the top of the chain */ - if (k == SPX_WOTS_W - 1) { - break; - } - - /* Iterate one step on all 8 chains */ - for (j = 0; j < 8; j++) { - set_hash_addr(leaf_addr + j * 8, k); - } - thashx8(buffer + 0 * wots_offset, - buffer + 1 * wots_offset, - buffer + 2 * wots_offset, - buffer + 3 * wots_offset, - buffer + 4 * wots_offset, - buffer + 5 * wots_offset, - buffer + 6 * wots_offset, - buffer + 7 * wots_offset, - buffer + 0 * wots_offset, - buffer + 1 * wots_offset, - buffer + 2 * wots_offset, - buffer + 3 * wots_offset, - buffer + 4 * wots_offset, - buffer + 5 * wots_offset, - buffer + 6 * wots_offset, - buffer + 7 * wots_offset, 1, ctx, leaf_addr); - } - } - - /* Do the final thash to generate the public keys */ - thashx8(dest + 0 * SPX_N, - dest + 1 * SPX_N, - dest + 2 * SPX_N, - dest + 3 * SPX_N, - dest + 4 * SPX_N, - dest + 5 * SPX_N, - dest + 6 * SPX_N, - dest + 7 * SPX_N, - pk_buffer + 0 * wots_offset, - pk_buffer + 1 * wots_offset, - pk_buffer + 2 * wots_offset, - pk_buffer + 3 * wots_offset, - pk_buffer + 4 * wots_offset, - pk_buffer + 5 * wots_offset, - pk_buffer + 6 * wots_offset, - pk_buffer + 7 * wots_offset, SPX_WOTS_LEN, ctx, pk_addr); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/wots.h b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/wots.h deleted file mode 100644 index 4e7692eeef..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/wots.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef SPX_WOTS_H -#define SPX_WOTS_H - -#include - -#include "context.h" -#include "params.h" - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) -void wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const spx_ctx *ctx, uint32_t addr[8]); - -/* - * Compute the chain lengths needed for a given message hash - */ -#define chain_lengths SPX_NAMESPACE(chain_lengths) -void chain_lengths(unsigned int *lengths, const unsigned char *msg); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/wotsx8.h b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/wotsx8.h deleted file mode 100644 index 10866efb35..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_avx2/wotsx8.h +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef WOTSX8_H_ -#define WOTSX8_H_ - -#include - -#include "context.h" -#include "params.h" - -/* - * This is here to provide an interface to the internal wots_gen_leafx8 - * routine. While this routine is not referenced in the package outside of - * wots.c, it is called from the stand-alone benchmark code to characterize - * the performance - */ -struct leaf_info_x8 { - unsigned char *wots_sig; - uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ - uint32_t *wots_steps; - uint32_t leaf_addr[8 * 8]; - uint32_t pk_addr[8 * 8]; -}; - -/* Macro to set the leaf_info to something 'benign', that is, it would */ -/* run with the same time as it does during the real signing process */ -/* Used only by the benchmark code */ -#define INITIALIZE_LEAF_INFO_X8(info, addr, step_buffer) { \ - (info).wots_sig = 0; \ - (info).wots_sign_leaf = ~0; \ - (info).wots_steps = step_buffer; \ - int i; \ - for (i=0; i<8; i++) { \ - memcpy( &(info).leaf_addr[8*i], addr, 32 ); \ - memcpy( &(info).pk_addr[8*i], addr, 32 ); \ - } \ - } - -#define wots_gen_leafx8 SPX_NAMESPACE(wots_gen_leafx8) -void wots_gen_leafx8(unsigned char *dest, - const spx_ctx *ctx, - uint32_t leaf_idx, void *v_info); - -#endif /* WOTSX8_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/LICENSE b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/LICENSE deleted file mode 100644 index 670154e353..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/LICENSE +++ /dev/null @@ -1,116 +0,0 @@ -CC0 1.0 Universal - -Statement of Purpose - -The laws of most jurisdictions throughout the world automatically confer -exclusive Copyright and Related Rights (defined below) upon the creator and -subsequent owner(s) (each and all, an "owner") of an original work of -authorship and/or a database (each, a "Work"). - -Certain owners wish to permanently relinquish those rights to a Work for the -purpose of contributing to a commons of creative, cultural and scientific -works ("Commons") that the public can reliably and without fear of later -claims of infringement build upon, modify, incorporate in other works, reuse -and redistribute as freely as possible in any form whatsoever and for any -purposes, including without limitation commercial purposes. These owners may -contribute to the Commons to promote the ideal of a free culture and the -further production of creative, cultural and scientific works, or to gain -reputation or greater distribution for their Work in part through the use and -efforts of others. - -For these and/or other purposes and motivations, and without any expectation -of additional consideration or compensation, the person associating CC0 with a -Work (the "Affirmer"), to the extent that he or she is an owner of Copyright -and Related Rights in the Work, voluntarily elects to apply CC0 to the Work -and publicly distribute the Work under its terms, with knowledge of his or her -Copyright and Related Rights in the Work and the meaning and intended legal -effect of CC0 on those rights. - -1. Copyright and Related Rights. A Work made available under CC0 may be -protected by copyright and related or neighboring rights ("Copyright and -Related Rights"). Copyright and Related Rights include, but are not limited -to, the following: - - i. the right to reproduce, adapt, distribute, perform, display, communicate, - and translate a Work; - - ii. moral rights retained by the original author(s) and/or performer(s); - - iii. publicity and privacy rights pertaining to a person's image or likeness - depicted in a Work; - - iv. rights protecting against unfair competition in regards to a Work, - subject to the limitations in paragraph 4(a), below; - - v. rights protecting the extraction, dissemination, use and reuse of data in - a Work; - - vi. database rights (such as those arising under Directive 96/9/EC of the - European Parliament and of the Council of 11 March 1996 on the legal - protection of databases, and under any national implementation thereof, - including any amended or successor version of such directive); and - - vii. other similar, equivalent or corresponding rights throughout the world - based on applicable law or treaty, and any national implementations thereof. - -2. Waiver. To the greatest extent permitted by, but not in contravention of, -applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and -unconditionally waives, abandons, and surrenders all of Affirmer's Copyright -and Related Rights and associated claims and causes of action, whether now -known or unknown (including existing as well as future claims and causes of -action), in the Work (i) in all territories worldwide, (ii) for the maximum -duration provided by applicable law or treaty (including future time -extensions), (iii) in any current or future medium and for any number of -copies, and (iv) for any purpose whatsoever, including without limitation -commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes -the Waiver for the benefit of each member of the public at large and to the -detriment of Affirmer's heirs and successors, fully intending that such Waiver -shall not be subject to revocation, rescission, cancellation, termination, or -any other legal or equitable action to disrupt the quiet enjoyment of the Work -by the public as contemplated by Affirmer's express Statement of Purpose. - -3. Public License Fallback. Should any part of the Waiver for any reason be -judged legally invalid or ineffective under applicable law, then the Waiver -shall be preserved to the maximum extent permitted taking into account -Affirmer's express Statement of Purpose. In addition, to the extent the Waiver -is so judged Affirmer hereby grants to each affected person a royalty-free, -non transferable, non sublicensable, non exclusive, irrevocable and -unconditional license to exercise Affirmer's Copyright and Related Rights in -the Work (i) in all territories worldwide, (ii) for the maximum duration -provided by applicable law or treaty (including future time extensions), (iii) -in any current or future medium and for any number of copies, and (iv) for any -purpose whatsoever, including without limitation commercial, advertising or -promotional purposes (the "License"). The License shall be deemed effective as -of the date CC0 was applied by Affirmer to the Work. Should any part of the -License for any reason be judged legally invalid or ineffective under -applicable law, such partial invalidity or ineffectiveness shall not -invalidate the remainder of the License, and in such case Affirmer hereby -affirms that he or she will not (i) exercise any of his or her remaining -Copyright and Related Rights in the Work or (ii) assert any associated claims -and causes of action with respect to the Work, in either case contrary to -Affirmer's express Statement of Purpose. - -4. Limitations and Disclaimers. - - a. No trademark or patent rights held by Affirmer are waived, abandoned, - surrendered, licensed or otherwise affected by this document. - - b. Affirmer offers the Work as-is and makes no representations or warranties - of any kind concerning the Work, express, implied, statutory or otherwise, - including without limitation warranties of title, merchantability, fitness - for a particular purpose, non infringement, or the absence of latent or - other defects, accuracy, or the present or absence of errors, whether or not - discoverable, all to the greatest extent permissible under applicable law. - - c. Affirmer disclaims responsibility for clearing rights of other persons - that may apply to the Work or any use thereof, including without limitation - any person's Copyright and Related Rights in the Work. Further, Affirmer - disclaims responsibility for obtaining any necessary consents, permissions - or other rights required for any use of the Work. - - d. Affirmer understands and acknowledges that Creative Commons is not a - party to this document and has no duty or obligation with respect to this - CC0 or use of the Work. - -For more information, please see - diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/address.c b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/address.c deleted file mode 100644 index b956e9cb29..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/address.c +++ /dev/null @@ -1,91 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "utils.h" - -/* - * Specify which level of Merkle tree (the "layer") we're working on - */ -void set_layer_addr(uint32_t addr[8], uint32_t layer) { - ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; -} - -/* - * Specify which Merkle tree within the level (the "tree address") we're working on - */ -void set_tree_addr(uint32_t addr[8], uint64_t tree) { - ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); -} - -/* - * Specify the reason we'll use this address structure for, that is, what - * hash will we compute with it. This is used so that unrelated types of - * hashes don't accidentally get the same address structure. The type will be - * one of the SPX_ADDR_TYPE constants - */ -void set_type(uint32_t addr[8], uint32_t type) { - ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; -} - -/* - * Copy the layer and tree fields of the address structure. This is used - * when we're doing multiple types of hashes within the same Merkle tree - */ -void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { - memcpy( out, in, SPX_OFFSET_TREE + 8 ); -} - -/* These functions are used for OTS addresses. */ - -/* - * Specify which Merkle leaf we're working on; that is, which OTS keypair - * we're talking about. - */ -void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { - ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; -} - -/* - * Copy the layer, tree and keypair fields of the address structure. This is - * used when we're doing multiple things within the same OTS keypair - */ -void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { - memcpy( out, in, SPX_OFFSET_TREE + 8 ); - ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; -} - -/* - * Specify which Merkle chain within the OTS we're working with - * (the chain address) - */ -void set_chain_addr(uint32_t addr[8], uint32_t chain) { - ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; -} - -/* - * Specify where in the Merkle chain we are -* (the hash address) - */ -void set_hash_addr(uint32_t addr[8], uint32_t hash) { - ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; -} - -/* These functions are used for all hash tree addresses (including FORS). */ - -/* - * Specify the height of the node in the Merkle/FORS tree we are in - * (the tree height) - */ -void set_tree_height(uint32_t addr[8], uint32_t tree_height) { - ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; -} - -/* - * Specify the distance from the left edge of the node in the Merkle/FORS tree - * (the tree index) - */ -void set_tree_index(uint32_t addr[8], uint32_t tree_index) { - u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/address.h b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/address.h deleted file mode 100644 index 24a84eb40c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/address.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef SPX_ADDRESS_H -#define SPX_ADDRESS_H - -#include - -#include "params.h" - -/* The hash types that are passed to set_type */ -#define SPX_ADDR_TYPE_WOTS 0 -#define SPX_ADDR_TYPE_WOTSPK 1 -#define SPX_ADDR_TYPE_HASHTREE 2 -#define SPX_ADDR_TYPE_FORSTREE 3 -#define SPX_ADDR_TYPE_FORSPK 4 -#define SPX_ADDR_TYPE_WOTSPRF 5 -#define SPX_ADDR_TYPE_FORSPRF 6 - -#define set_layer_addr SPX_NAMESPACE(set_layer_addr) -void set_layer_addr(uint32_t addr[8], uint32_t layer); - -#define set_tree_addr SPX_NAMESPACE(set_tree_addr) -void set_tree_addr(uint32_t addr[8], uint64_t tree); - -#define set_type SPX_NAMESPACE(set_type) -void set_type(uint32_t addr[8], uint32_t type); - -/* Copies the layer and tree part of one address into the other */ -#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) -void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for WOTS and FORS addresses. */ - -#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) -void set_keypair_addr(uint32_t addr[8], uint32_t keypair); - -#define set_chain_addr SPX_NAMESPACE(set_chain_addr) -void set_chain_addr(uint32_t addr[8], uint32_t chain); - -#define set_hash_addr SPX_NAMESPACE(set_hash_addr) -void set_hash_addr(uint32_t addr[8], uint32_t hash); - -#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) -void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for all hash tree addresses (including FORS). */ - -#define set_tree_height SPX_NAMESPACE(set_tree_height) -void set_tree_height(uint32_t addr[8], uint32_t tree_height); - -#define set_tree_index SPX_NAMESPACE(set_tree_index) -void set_tree_index(uint32_t addr[8], uint32_t tree_index); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/api.h b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/api.h deleted file mode 100644 index 6b4acf9b80..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/api.h +++ /dev/null @@ -1,77 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA2128FROBUST_CLEAN_API_H -#define PQCLEAN_SPHINCSSHA2128FROBUST_CLEAN_API_H - -#include -#include - -#define PQCLEAN_SPHINCSSHA2128FROBUST_CLEAN_CRYPTO_ALGNAME "SPHINCS+-sha2-128f-robust" - -#define PQCLEAN_SPHINCSSHA2128FROBUST_CLEAN_CRYPTO_SECRETKEYBYTES 64 -#define PQCLEAN_SPHINCSSHA2128FROBUST_CLEAN_CRYPTO_PUBLICKEYBYTES 32 -#define PQCLEAN_SPHINCSSHA2128FROBUST_CLEAN_CRYPTO_BYTES 17088 - -#define PQCLEAN_SPHINCSSHA2128FROBUST_CLEAN_CRYPTO_SEEDBYTES 48 - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSSHA2128FROBUST_CLEAN_crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSSHA2128FROBUST_CLEAN_crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSSHA2128FROBUST_CLEAN_crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSSHA2128FROBUST_CLEAN_crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHA2128FROBUST_CLEAN_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHA2128FROBUST_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSSHA2128FROBUST_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSSHA2128FROBUST_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, - const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSSHA2128FROBUST_CLEAN_crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSSHA2128FROBUST_CLEAN_crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk); -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/context.h b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/context.h deleted file mode 100644 index 27effb3e10..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/context.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef SPX_CONTEXT_H -#define SPX_CONTEXT_H - -#include -#include - -#include "params.h" -#include "sha2.h" - -typedef struct { - uint8_t pub_seed[SPX_N]; - uint8_t sk_seed[SPX_N]; - - // sha256 state that absorbed pub_seed - sha256ctx state_seeded; - - -} spx_ctx; - -#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) -void initialize_hash_function(spx_ctx *ctx); - -#define free_hash_function SPX_NAMESPACE(free_hash_function) -void free_hash_function(spx_ctx *ctx); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/context_sha2.c b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/context_sha2.c deleted file mode 100644 index 64f7e65465..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/context_sha2.c +++ /dev/null @@ -1,33 +0,0 @@ -#include "context.h" - -/** - * Absorb the constant pub_seed using one round of the compression function - * This initializes state_seeded and state_seeded_512, which can then be - * reused in thash - **/ -static void seed_state(spx_ctx *ctx) { - uint8_t block[SPX_SHA512_BLOCK_BYTES]; - size_t i; - - for (i = 0; i < SPX_N; ++i) { - block[i] = ctx->pub_seed[i]; - } - for (i = SPX_N; i < SPX_SHA512_BLOCK_BYTES; ++i) { - block[i] = 0; - } - /* block has been properly initialized for both SHA-256 and SHA-512 */ - - sha256_inc_init(&ctx->state_seeded); - sha256_inc_blocks(&ctx->state_seeded, block, 1); -} - - -/* We initialize the state for the hash functions */ -void initialize_hash_function(spx_ctx *ctx) { - seed_state(ctx); -} - -/* Free the incremental hashing context for heap-based SHA2 APIs */ -void free_hash_function(spx_ctx *ctx) { - sha256_inc_ctx_release(&ctx->state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/fors.c b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/fors.c deleted file mode 100644 index 96ca72e986..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/fors.c +++ /dev/null @@ -1,156 +0,0 @@ -#include -#include -#include - -#include "fors.h" - -#include "address.h" -#include "hash.h" -#include "thash.h" -#include "utils.h" -#include "utilsx1.h" - -static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, - uint32_t fors_leaf_addr[8]) { - prf_addr(sk, ctx, fors_leaf_addr); -} - -static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, - const spx_ctx *ctx, - uint32_t fors_leaf_addr[8]) { - thash(leaf, sk, 1, ctx, fors_leaf_addr); -} - -struct fors_gen_leaf_info { - uint32_t leaf_addrx[8]; -}; - -static void fors_gen_leafx1(unsigned char *leaf, - const spx_ctx *ctx, - uint32_t addr_idx, void *info) { - struct fors_gen_leaf_info *fors_info = info; - uint32_t *fors_leaf_addr = fors_info->leaf_addrx; - - /* Only set the parts that the caller doesn't set */ - set_tree_index(fors_leaf_addr, addr_idx); - set_type(fors_leaf_addr, SPX_ADDR_TYPE_FORSPRF); - fors_gen_sk(leaf, ctx, fors_leaf_addr); - - set_type(fors_leaf_addr, SPX_ADDR_TYPE_FORSTREE); - fors_sk_to_leaf(leaf, leaf, - ctx, fors_leaf_addr); -} - -/** - * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - * Assumes indices has space for SPX_FORS_TREES integers. - */ -static void message_to_indices(uint32_t *indices, const unsigned char *m) { - unsigned int i, j; - unsigned int offset = 0; - - for (i = 0; i < SPX_FORS_TREES; i++) { - indices[i] = 0; - for (j = 0; j < SPX_FORS_HEIGHT; j++) { - indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); - offset++; - } - } -} - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -void fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]) { - uint32_t indices[SPX_FORS_TREES]; - unsigned char roots[SPX_FORS_TREES * SPX_N]; - uint32_t fors_tree_addr[8] = {0}; - struct fors_gen_leaf_info fors_info = {0}; - uint32_t *fors_leaf_addr = fors_info.leaf_addrx; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - copy_keypair_addr(fors_tree_addr, fors_addr); - copy_keypair_addr(fors_leaf_addr, fors_addr); - - copy_keypair_addr(fors_pk_addr, fors_addr); - set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < SPX_FORS_TREES; i++) { - idx_offset = i * (1 << SPX_FORS_HEIGHT); - - set_tree_height(fors_tree_addr, 0); - set_tree_index(fors_tree_addr, indices[i] + idx_offset); - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); - - /* Include the secret key part that produces the selected leaf node. */ - fors_gen_sk(sig, ctx, fors_tree_addr); - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); - sig += SPX_N; - - /* Compute the authentication path for this leaf node. */ - treehashx1(roots + i * SPX_N, sig, ctx, - indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx1, - fors_tree_addr, &fors_info); - - sig += SPX_N * SPX_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); -} - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -void fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]) { - uint32_t indices[SPX_FORS_TREES]; - unsigned char roots[SPX_FORS_TREES * SPX_N]; - unsigned char leaf[SPX_N]; - uint32_t fors_tree_addr[8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - copy_keypair_addr(fors_tree_addr, fors_addr); - copy_keypair_addr(fors_pk_addr, fors_addr); - - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); - set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < SPX_FORS_TREES; i++) { - idx_offset = i * (1 << SPX_FORS_HEIGHT); - - set_tree_height(fors_tree_addr, 0); - set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Derive the leaf from the included secret key part. */ - fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); - sig += SPX_N; - - /* Derive the corresponding root node of this tree. */ - compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, - sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); - sig += SPX_N * SPX_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/fors.h b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/fors.h deleted file mode 100644 index 509140a178..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/fors.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef SPX_FORS_H -#define SPX_FORS_H - -#include - -#include "context.h" -#include "params.h" - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -#define fors_sign SPX_NAMESPACE(fors_sign) -void fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]); - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) -void fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/hash.h b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/hash.h deleted file mode 100644 index ffe815f45d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/hash.h +++ /dev/null @@ -1,37 +0,0 @@ -#ifndef SPX_HASH_H -#define SPX_HASH_H - -#include -#include - -#include "context.h" -#include "params.h" - -#define prf_addr SPX_NAMESPACE(prf_addr) -void prf_addr(unsigned char *out, const spx_ctx *ctx, - const uint32_t addr[8]); - -#define gen_message_random SPX_NAMESPACE(gen_message_random) -void gen_message_random(unsigned char *R, const unsigned char *sk_prf, - const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx); - -#define hash_message SPX_NAMESPACE(hash_message) -void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx); - - -# define SPX_SHA256_ADDR_BYTES 22 - -# define mgf1_256 SPX_NAMESPACE(mgf1_256) -void mgf1_256(unsigned char *out, unsigned long outlen, - const unsigned char *in, unsigned long inlen); - -# define mgf1_512 SPX_NAMESPACE(mgf1_512) -void mgf1_512(unsigned char *out, unsigned long outlen, - const unsigned char *in, unsigned long inlen); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/hash_sha2.c b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/hash_sha2.c deleted file mode 100644 index 69f0dc0013..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/hash_sha2.c +++ /dev/null @@ -1,219 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "sha2.h" -#include "utils.h" - - - -#define SPX_SHAX_OUTPUT_BYTES SPX_SHA256_OUTPUT_BYTES -#define SPX_SHAX_BLOCK_BYTES SPX_SHA256_BLOCK_BYTES -#define shaX_inc_init sha256_inc_init -#define shaX_inc_blocks sha256_inc_blocks -#define shaX_inc_finalize sha256_inc_finalize -#define shaX sha256 -#define mgf1_X mgf1_256 -#define shaXstate sha256ctx - -/** - * mgf1 function based on the SHA-256 hash function - * Note that inlen should be sufficiently small that it still allows for - * an array to be allocated on the stack. Typically 'in' is merely a seed. - * Outputs outlen number of bytes - */ -void mgf1_256(unsigned char *out, unsigned long outlen, - const unsigned char *in, unsigned long inlen) { - PQCLEAN_VLA(uint8_t, inbuf, inlen + 4); - unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES]; - uint32_t i; - - memcpy(inbuf, in, inlen); - - /* While we can fit in at least another full block of SHA256 output.. */ - for (i = 0; (i + 1)*SPX_SHA256_OUTPUT_BYTES <= outlen; i++) { - u32_to_bytes(inbuf + inlen, i); - sha256(out, inbuf, inlen + 4); - out += SPX_SHA256_OUTPUT_BYTES; - } - /* Until we cannot anymore, and we fill the remainder. */ - if (outlen > i * SPX_SHA256_OUTPUT_BYTES) { - u32_to_bytes(inbuf + inlen, i); - sha256(outbuf, inbuf, inlen + 4); - memcpy(out, outbuf, outlen - i * SPX_SHA256_OUTPUT_BYTES); - } -} - -/* - * mgf1 function based on the SHA-512 hash function - */ -void mgf1_512(unsigned char *out, unsigned long outlen, - const unsigned char *in, unsigned long inlen) { - PQCLEAN_VLA(uint8_t, inbuf, inlen + 4); - unsigned char outbuf[SPX_SHA512_OUTPUT_BYTES]; - uint32_t i; - - memcpy(inbuf, in, inlen); - - /* While we can fit in at least another full block of SHA512 output.. */ - for (i = 0; (i + 1)*SPX_SHA512_OUTPUT_BYTES <= outlen; i++) { - u32_to_bytes(inbuf + inlen, i); - sha512(out, inbuf, inlen + 4); - out += SPX_SHA512_OUTPUT_BYTES; - } - /* Until we cannot anymore, and we fill the remainder. */ - if (outlen > i * SPX_SHA512_OUTPUT_BYTES) { - u32_to_bytes(inbuf + inlen, i); - sha512(outbuf, inbuf, inlen + 4); - memcpy(out, outbuf, outlen - i * SPX_SHA512_OUTPUT_BYTES); - } -} - -/* - * Computes PRF(pk_seed, sk_seed, addr). - */ -void prf_addr(unsigned char *out, const spx_ctx *ctx, - const uint32_t addr[8]) { - sha256ctx sha2_state; - unsigned char buf[SPX_SHA256_ADDR_BYTES + SPX_N]; - unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES]; - - /* Retrieve precomputed state containing pub_seed */ - sha256_inc_ctx_clone(&sha2_state, &ctx->state_seeded); - - /* Remainder: ADDR^c ‖ SK.seed */ - memcpy(buf, addr, SPX_SHA256_ADDR_BYTES); - memcpy(buf + SPX_SHA256_ADDR_BYTES, ctx->sk_seed, SPX_N); - - sha256_inc_finalize(outbuf, &sha2_state, buf, SPX_SHA256_ADDR_BYTES + SPX_N); - - memcpy(out, outbuf, SPX_N); -} - -/** - * Computes the message-dependent randomness R, using a secret seed as a key - * for HMAC, and an optional randomization value prefixed to the message. - * This requires m to have at least SPX_SHAX_BLOCK_BYTES + SPX_N space - * available in front of the pointer, i.e. before the message to use for the - * prefix. This is necessary to prevent having to move the message around (and - * allocate memory for it). - */ -void gen_message_random(unsigned char *R, const unsigned char *sk_prf, - const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx) { - (void)ctx; - - unsigned char buf[SPX_SHAX_BLOCK_BYTES + SPX_SHAX_OUTPUT_BYTES]; - shaXstate state; - int i; - - - /* This implements HMAC-SHA */ - for (i = 0; i < SPX_N; i++) { - buf[i] = 0x36 ^ sk_prf[i]; - } - memset(buf + SPX_N, 0x36, SPX_SHAX_BLOCK_BYTES - SPX_N); - - shaX_inc_init(&state); - shaX_inc_blocks(&state, buf, 1); - - memcpy(buf, optrand, SPX_N); - - /* If optrand + message cannot fill up an entire block */ - if (SPX_N + mlen < SPX_SHAX_BLOCK_BYTES) { - memcpy(buf + SPX_N, m, mlen); - shaX_inc_finalize(buf + SPX_SHAX_BLOCK_BYTES, &state, - buf, mlen + SPX_N); - } - /* Otherwise first fill a block, so that finalize only uses the message */ - else { - memcpy(buf + SPX_N, m, SPX_SHAX_BLOCK_BYTES - SPX_N); - shaX_inc_blocks(&state, buf, 1); - - m += SPX_SHAX_BLOCK_BYTES - SPX_N; - mlen -= SPX_SHAX_BLOCK_BYTES - SPX_N; - shaX_inc_finalize(buf + SPX_SHAX_BLOCK_BYTES, &state, m, mlen); - } - - for (i = 0; i < SPX_N; i++) { - buf[i] = 0x5c ^ sk_prf[i]; - } - memset(buf + SPX_N, 0x5c, SPX_SHAX_BLOCK_BYTES - SPX_N); - - shaX(buf, buf, SPX_SHAX_BLOCK_BYTES + SPX_SHAX_OUTPUT_BYTES); - memcpy(R, buf, SPX_N); -} - -/** - * Computes the message hash using R, the public key, and the message. - * Outputs the message digest and the index of the leaf. The index is split in - * the tree index and the leaf index, for convenient copying to an address. - */ -void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx) { - (void)ctx; -#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) -#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) -#define SPX_LEAF_BITS SPX_TREE_HEIGHT -#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) -#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) - - unsigned char seed[2 * SPX_N + SPX_SHAX_OUTPUT_BYTES]; - - /* Round to nearest multiple of SPX_SHAX_BLOCK_BYTES */ -#define SPX_INBLOCKS (((SPX_N + SPX_PK_BYTES + SPX_SHAX_BLOCK_BYTES - 1) & \ - -SPX_SHAX_BLOCK_BYTES) / SPX_SHAX_BLOCK_BYTES) - unsigned char inbuf[SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES]; - - unsigned char buf[SPX_DGST_BYTES]; - unsigned char *bufp = buf; - shaXstate state; - - shaX_inc_init(&state); - - // seed: SHA-X(R ‖ PK.seed ‖ PK.root ‖ M) - memcpy(inbuf, R, SPX_N); - memcpy(inbuf + SPX_N, pk, SPX_PK_BYTES); - - /* If R + pk + message cannot fill up an entire block */ - if (SPX_N + SPX_PK_BYTES + mlen < SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES) { - memcpy(inbuf + SPX_N + SPX_PK_BYTES, m, mlen); - shaX_inc_finalize(seed + 2 * SPX_N, &state, inbuf, SPX_N + SPX_PK_BYTES + mlen); - } - /* Otherwise first fill a block, so that finalize only uses the message */ - else { - memcpy(inbuf + SPX_N + SPX_PK_BYTES, m, - SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES - SPX_N - SPX_PK_BYTES); - shaX_inc_blocks(&state, inbuf, SPX_INBLOCKS); - - m += SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES - SPX_N - SPX_PK_BYTES; - mlen -= SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES - SPX_N - SPX_PK_BYTES; - shaX_inc_finalize(seed + 2 * SPX_N, &state, m, (size_t)mlen); - } - - // H_msg: MGF1-SHA-X(R ‖ PK.seed ‖ seed) - memcpy(seed, R, SPX_N); - memcpy(seed + SPX_N, pk, SPX_N); - - /* By doing this in two steps, we prevent hashing the message twice; - otherwise each iteration in MGF1 would hash the message again. */ - mgf1_X(bufp, SPX_DGST_BYTES, seed, 2 * SPX_N + SPX_SHAX_OUTPUT_BYTES); - - memcpy(digest, bufp, SPX_FORS_MSG_BYTES); - bufp += SPX_FORS_MSG_BYTES; - - - *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); - *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); - bufp += SPX_TREE_BYTES; - - *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); - *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); -} - - diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/merkle.c b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/merkle.c deleted file mode 100644 index 0c1479fd93..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/merkle.c +++ /dev/null @@ -1,59 +0,0 @@ -#include -#include - -#include "address.h" -#include "merkle.h" -#include "params.h" -#include "utils.h" -#include "utilsx1.h" -#include "wots.h" -#include "wotsx1.h" - -/* - * This generates a Merkle signature (WOTS signature followed by the Merkle - * authentication path). This is in this file because most of the complexity - * is involved with the WOTS signature; the Merkle authentication path logic - * is mostly hidden in treehashx4 - */ -void merkle_sign(uint8_t *sig, unsigned char *root, - const spx_ctx *ctx, - uint32_t wots_addr[8], uint32_t tree_addr[8], - uint32_t idx_leaf) { - unsigned char *auth_path = sig + SPX_WOTS_BYTES; - struct leaf_info_x1 info = { 0 }; - unsigned steps[ SPX_WOTS_LEN ]; - - info.wots_sig = sig; - chain_lengths(steps, root); - info.wots_steps = steps; - - set_type(&tree_addr[0], SPX_ADDR_TYPE_HASHTREE); - set_type(&info.pk_addr[0], SPX_ADDR_TYPE_WOTSPK); - copy_subtree_addr(&info.leaf_addr[0], wots_addr); - copy_subtree_addr(&info.pk_addr[0], wots_addr); - - info.wots_sign_leaf = idx_leaf; - - treehashx1(root, auth_path, ctx, - idx_leaf, 0, - SPX_TREE_HEIGHT, - wots_gen_leafx1, - tree_addr, &info); -} - -/* Compute root node of the top-most subtree. */ -void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { - /* We do not need the auth path in key generation, but it simplifies the - code to have just one treehash routine that computes both root and path - in one function. */ - unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; - uint32_t top_tree_addr[8] = {0}; - uint32_t wots_addr[8] = {0}; - - set_layer_addr(top_tree_addr, SPX_D - 1); - set_layer_addr(wots_addr, SPX_D - 1); - - merkle_sign(auth_path, root, ctx, - wots_addr, top_tree_addr, - (uint32_t)~0 /* ~0 means "don't bother generating an auth path */ ); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/merkle.h b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/merkle.h deleted file mode 100644 index 769cf2e970..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/merkle.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef MERKLE_H_ -#define MERKLE_H_ - -#include - -#include "context.h" -#include "params.h" - -/* Generate a Merkle signature (WOTS signature followed by the Merkle */ -/* authentication path) */ -#define merkle_sign SPX_NAMESPACE(merkle_sign) -void merkle_sign(uint8_t *sig, unsigned char *root, - const spx_ctx *ctx, - uint32_t wots_addr[8], uint32_t tree_addr[8], - uint32_t idx_leaf); - -/* Compute the root node of the top-most subtree. */ -#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) -void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); - -#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/nistapi.h b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/nistapi.h deleted file mode 100644 index 3cb71afad4..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/nistapi.h +++ /dev/null @@ -1,87 +0,0 @@ -#ifndef SPX_API_H -#define SPX_API_H - -#include -#include - -#include "params.h" - -#define CRYPTO_ALGNAME "SPHINCS+" - -#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES -#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES -#define CRYPTO_BYTES SPX_BYTES -#define CRYPTO_SEEDBYTES (3*SPX_N) - -/* - * Returns the length of a secret key, in bytes - */ -#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) -size_t crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) -size_t crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) -size_t crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) -size_t crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) -int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) -int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) -int crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) -int crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -#define crypto_sign SPX_NAMESPACE(crypto_sign) -int crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) -int crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/params.h b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/params.h deleted file mode 100644 index 9b78d4d3bf..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/params.h +++ /dev/null @@ -1,61 +0,0 @@ -#ifndef SPX_PARAMS_H -#define SPX_PARAMS_H - -#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSSHA2128FROBUST_CLEAN_##s - -/* Hash output length in bytes. */ -#define SPX_N 16 -/* Height of the hypertree. */ -#define SPX_FULL_HEIGHT 66 -/* Number of subtree layer. */ -#define SPX_D 22 -/* FORS tree dimensions. */ -#define SPX_FORS_HEIGHT 6 -#define SPX_FORS_TREES 33 -/* Winternitz parameter, */ -#define SPX_WOTS_W 16 - -/* The hash function is defined by linking a different hash.c file, as opposed - to setting a #define constant. */ - -/* This is a SHA2-based parameter set, hence whether we use SHA-256 - * exclusively or we use both SHA-256 and SHA-512 is controlled by - * the following #define */ -#define SPX_SHA512 0 /* Use SHA-256 for all hashes */ - -/* For clarity */ -#define SPX_ADDR_BYTES 32 - -/* WOTS parameters. */ -#define SPX_WOTS_LOGW 4 - -#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) - -/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#define SPX_WOTS_LEN2 3 - -#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) -#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) -#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES - -/* Subtree size. */ -#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) - -//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT -// #error SPX_D should always divide SPX_FULL_HEIGHT -//#endif - -/* FORS parameters. */ -#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) -#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) -#define SPX_FORS_PK_BYTES SPX_N - -/* Resulting SPX sizes. */ -#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ - SPX_FULL_HEIGHT * SPX_N) -#define SPX_PK_BYTES (2 * SPX_N) -#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) - -#include "sha2_offsets.h" - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/sha2_offsets.h b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/sha2_offsets.h deleted file mode 100644 index 6e3584f7a4..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/sha2_offsets.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef SHA2_OFFSETS_H_ -#define SHA2_OFFSETS_H_ - -#define SPX_SHA256_BLOCK_BYTES 64 -#define SPX_SHA256_OUTPUT_BYTES 32 - -#define SPX_SHA512_BLOCK_BYTES 128 -#define SPX_SHA512_OUTPUT_BYTES 64 - -/* - * Offsets of various fields in the address structure when we use SHA2 as - * the Sphincs+ hash function - */ - -#define SPX_OFFSET_LAYER 0 /* The byte used to specify the Merkle tree layer */ -#define SPX_OFFSET_TREE 1 /* The start of the 8 byte field used to specify the tree */ -#define SPX_OFFSET_TYPE 9 /* The byte used to specify the hash type (reason) */ -#define SPX_OFFSET_KP_ADDR2 12 /* The high byte used to specify the key pair (which one-time signature) */ -#define SPX_OFFSET_KP_ADDR1 13 /* The low byte used to specify the key pair */ -#define SPX_OFFSET_CHAIN_ADDR 17 /* The byte used to specify the chain address (which Winternitz chain) */ -#define SPX_OFFSET_HASH_ADDR 21 /* The byte used to specify the hash address (where in the Winternitz chain) */ -#define SPX_OFFSET_TREE_HGT 17 /* The byte used to specify the height of this node in the FORS or Merkle tree */ -#define SPX_OFFSET_TREE_INDEX 18 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ - -#define SPX_SHA2 1 - -#endif /* SHA2_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/sign.c b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/sign.c deleted file mode 100644 index 9d0c7d1b22..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/sign.c +++ /dev/null @@ -1,286 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "context.h" -#include "fors.h" -#include "hash.h" -#include "merkle.h" -#include "nistapi.h" -#include "params.h" -#include "randombytes.h" -#include "thash.h" -#include "utils.h" -#include "wots.h" - -/* - * Returns the length of a secret key, in bytes - */ -size_t crypto_sign_secretkeybytes(void) { - return CRYPTO_SECRETKEYBYTES; -} - -/* - * Returns the length of a public key, in bytes - */ -size_t crypto_sign_publickeybytes(void) { - return CRYPTO_PUBLICKEYBYTES; -} - -/* - * Returns the length of a signature, in bytes - */ -size_t crypto_sign_bytes(void) { - return CRYPTO_BYTES; -} - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t crypto_sign_seedbytes(void) { - return CRYPTO_SEEDBYTES; -} - -/* - * Generates an SPX key pair given a seed of length - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed) { - spx_ctx ctx; - - /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ - memcpy(sk, seed, CRYPTO_SEEDBYTES); - - memcpy(pk, sk + 2 * SPX_N, SPX_N); - - memcpy(ctx.pub_seed, pk, SPX_N); - memcpy(ctx.sk_seed, sk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - /* Compute root node of the top-most subtree. */ - merkle_gen_root(sk + 3 * SPX_N, &ctx); - - // cleanup - free_hash_function(&ctx); - - memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); - - return 0; -} - -/* - * Generates an SPX key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { - uint8_t seed[CRYPTO_SEEDBYTES]; - randombytes(seed, CRYPTO_SEEDBYTES); - crypto_sign_seed_keypair(pk, sk, seed); - - return 0; -} - -/** - * Returns an array containing a detached signature. - */ -int crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - spx_ctx ctx; - - const uint8_t *sk_prf = sk + SPX_N; - const uint8_t *pk = sk + 2 * SPX_N; - - uint8_t optrand[SPX_N]; - uint8_t mhash[SPX_FORS_MSG_BYTES]; - uint8_t root[SPX_N]; - uint32_t i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - - memcpy(ctx.sk_seed, sk, SPX_N); - memcpy(ctx.pub_seed, pk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - set_type(wots_addr, SPX_ADDR_TYPE_WOTS); - set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); - - /* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ - randombytes(optrand, SPX_N); - /* Compute the digest randomization value. */ - gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); - - /* Derive the message digest and leaf index from R, PK and M. */ - hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); - sig += SPX_N; - - set_tree_addr(wots_addr, tree); - set_keypair_addr(wots_addr, idx_leaf); - - /* Sign the message hash using FORS. */ - fors_sign(sig, root, mhash, &ctx, wots_addr); - sig += SPX_FORS_BYTES; - - for (i = 0; i < SPX_D; i++) { - set_layer_addr(tree_addr, i); - set_tree_addr(tree_addr, tree); - - copy_subtree_addr(wots_addr, tree_addr); - set_keypair_addr(wots_addr, idx_leaf); - - merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); - sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); - tree = tree >> SPX_TREE_HEIGHT; - } - - free_hash_function(&ctx); - - *siglen = SPX_BYTES; - - return 0; -} - -/** - * Verifies a detached signature and message under a given public key. - */ -int crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk) { - spx_ctx ctx; - const uint8_t *pub_root = pk + SPX_N; - uint8_t mhash[SPX_FORS_MSG_BYTES]; - uint8_t wots_pk[SPX_WOTS_BYTES]; - uint8_t root[SPX_N]; - uint8_t leaf[SPX_N]; - unsigned int i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - if (siglen != SPX_BYTES) { - return -1; - } - - memcpy(ctx.pub_seed, pk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - set_type(wots_addr, SPX_ADDR_TYPE_WOTS); - set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); - set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); - - /* Derive the message digest and leaf index from R || PK || M. */ - /* The additional SPX_N is a result of the hash domain separator. */ - hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); - sig += SPX_N; - - /* Layer correctly defaults to 0, so no need to set_layer_addr */ - set_tree_addr(wots_addr, tree); - set_keypair_addr(wots_addr, idx_leaf); - - fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); - sig += SPX_FORS_BYTES; - - /* For each subtree.. */ - for (i = 0; i < SPX_D; i++) { - set_layer_addr(tree_addr, i); - set_tree_addr(tree_addr, tree); - - copy_subtree_addr(wots_addr, tree_addr); - set_keypair_addr(wots_addr, idx_leaf); - - copy_keypair_addr(wots_pk_addr, wots_addr); - - /* The WOTS public key is only correct if the signature was correct. */ - /* Initially, root is the FORS pk, but on subsequent iterations it is - the root of the subtree below the currently processed subtree. */ - wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); - sig += SPX_WOTS_BYTES; - - /* Compute the leaf node using the WOTS public key. */ - thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); - - /* Compute the root node of this subtree. */ - compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, - &ctx, tree_addr); - sig += SPX_TREE_HEIGHT * SPX_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); - tree = tree >> SPX_TREE_HEIGHT; - } - - // cleanup - free_hash_function(&ctx); - - /* Check if the root node equals the root node in the public key. */ - if (memcmp(root, pub_root, SPX_N) != 0) { - return -1; - } - - return 0; -} - - -/** - * Returns an array containing the signature followed by the message. - */ -int crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk) { - size_t siglen; - - crypto_sign_signature(sm, &siglen, m, mlen, sk); - - memmove(sm + SPX_BYTES, m, mlen); - *smlen = siglen + mlen; - - return 0; -} - -/** - * Verifies a given signature-message pair under a given public key. - */ -int crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk) { - /* The API caller does not necessarily know what size a signature should be - but SPHINCS+ signatures are always exactly SPX_BYTES. */ - if (smlen < SPX_BYTES) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - *mlen = smlen - SPX_BYTES; - - if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - /* If verification was successful, move the message to the right place. */ - memmove(m, sm + SPX_BYTES, *mlen); - - return 0; -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/thash.h b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/thash.h deleted file mode 100644 index 8687ccfb4d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/thash.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef SPX_THASH_H -#define SPX_THASH_H - -#include "context.h" -#include "params.h" - -#include - -#define thash SPX_NAMESPACE(thash) -void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/thash_sha2_robust.c b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/thash_sha2_robust.c deleted file mode 100644 index 18f65c2e42..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/thash_sha2_robust.c +++ /dev/null @@ -1,39 +0,0 @@ -#include -#include - -#include "address.h" -#include "context.h" -#include "hash.h" -#include "params.h" -#include "sha2.h" -#include "thash.h" -#include "utils.h" - - -/** - * Takes an array of inblocks concatenated arrays of SPX_N bytes. - */ -void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]) { - unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES]; - PQCLEAN_VLA(uint8_t, bitmask, inblocks * SPX_N); - PQCLEAN_VLA(uint8_t, buf, SPX_N + SPX_SHA256_OUTPUT_BYTES + inblocks * SPX_N); - sha256ctx sha2_state; - unsigned int i; - - memcpy(buf, ctx->pub_seed, SPX_N); - memcpy(buf + SPX_N, addr, SPX_SHA256_ADDR_BYTES); - mgf1_256(bitmask, inblocks * SPX_N, buf, SPX_N + SPX_SHA256_ADDR_BYTES); - - /* Retrieve precomputed state containing pub_seed */ - sha256_inc_ctx_clone(&sha2_state, &ctx->state_seeded); - - for (i = 0; i < inblocks * SPX_N; i++) { - buf[SPX_N + SPX_SHA256_ADDR_BYTES + i] = in[i] ^ bitmask[i]; - } - - sha256_inc_finalize(outbuf, &sha2_state, buf + SPX_N, - SPX_SHA256_ADDR_BYTES + inblocks * SPX_N); - memcpy(out, outbuf, SPX_N); -} - diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/utils.c b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/utils.c deleted file mode 100644 index 177b541fb9..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/utils.c +++ /dev/null @@ -1,148 +0,0 @@ -#include - -#include "utils.h" - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "thash.h" - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void ull_to_bytes(unsigned char *out, unsigned int outlen, - unsigned long long in) { - int i; - - /* Iterate over out in decreasing order, for big-endianness. */ - for (i = (signed int)outlen - 1; i >= 0; i--) { - out[i] = in & 0xff; - in = in >> 8; - } -} - -void u32_to_bytes(unsigned char *out, uint32_t in) { - out[0] = (unsigned char)(in >> 24); - out[1] = (unsigned char)(in >> 16); - out[2] = (unsigned char)(in >> 8); - out[3] = (unsigned char)in; -} - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { - unsigned long long retval = 0; - unsigned int i; - - for (i = 0; i < inlen; i++) { - retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); - } - return retval; -} - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void compute_root(unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const spx_ctx *ctx, uint32_t addr[8]) { - uint32_t i; - unsigned char buffer[2 * SPX_N]; - - /* If leaf_idx is odd (last bit = 1), current path element is a right child - and auth_path has to go left. Otherwise it is the other way around. */ - if (leaf_idx & 1) { - memcpy(buffer + SPX_N, leaf, SPX_N); - memcpy(buffer, auth_path, SPX_N); - } else { - memcpy(buffer, leaf, SPX_N); - memcpy(buffer + SPX_N, auth_path, SPX_N); - } - auth_path += SPX_N; - - for (i = 0; i < tree_height - 1; i++) { - leaf_idx >>= 1; - idx_offset >>= 1; - /* Set the address of the node we're creating. */ - set_tree_height(addr, i + 1); - set_tree_index(addr, leaf_idx + idx_offset); - - /* Pick the right or left neighbor, depending on parity of the node. */ - if (leaf_idx & 1) { - thash(buffer + SPX_N, buffer, 2, ctx, addr); - memcpy(buffer, auth_path, SPX_N); - } else { - thash(buffer, buffer, 2, ctx, addr); - memcpy(buffer + SPX_N, auth_path, SPX_N); - } - auth_path += SPX_N; - } - - /* The last iteration is exceptional; we do not copy an auth_path node. */ - leaf_idx >>= 1; - idx_offset >>= 1; - set_tree_height(addr, tree_height); - set_tree_index(addr, leaf_idx + idx_offset); - thash(root, buffer, 2, ctx, addr); -} - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const spx_ctx * /* ctx */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), - uint32_t tree_addr[8]) { - PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); - PQCLEAN_VLA(unsigned int, heights, tree_height + 1); - unsigned int offset = 0; - uint32_t idx; - uint32_t tree_idx; - - for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { - /* Add the next leaf node to the stack. */ - gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); - offset++; - heights[offset - 1] = 0; - - /* If this is a node we need for the auth path.. */ - if ((leaf_idx ^ 0x1) == idx) { - memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); - } - - /* While the top-most nodes are of equal height.. */ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { - /* Compute index of the new node, in the next layer. */ - tree_idx = (idx >> (heights[offset - 1] + 1)); - - /* Set the address of the node we're creating. */ - set_tree_height(tree_addr, heights[offset - 1] + 1); - set_tree_index(tree_addr, - tree_idx + (idx_offset >> (heights[offset - 1] + 1))); - /* Hash the top-most nodes from the stack together. */ - thash(stack + (offset - 2)*SPX_N, - stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); - offset--; - /* Note that the top-most node is now one layer higher. */ - heights[offset - 1]++; - - /* If this is a node we need for the auth path.. */ - if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_path + heights[offset - 1]*SPX_N, - stack + (offset - 1)*SPX_N, SPX_N); - } - } - } - memcpy(root, stack, SPX_N); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/utils.h b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/utils.h deleted file mode 100644 index 64f5d5a53a..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/utils.h +++ /dev/null @@ -1,58 +0,0 @@ -#ifndef SPX_UTILS_H -#define SPX_UTILS_H - -#include - -#include "compat.h" -#include "context.h" -#include "params.h" - - -/* To support MSVC use alloca() instead of VLAs. See #20. */ - - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) -void ull_to_bytes(unsigned char *out, unsigned int outlen, - unsigned long long in); -#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) -void u32_to_bytes(unsigned char *out, uint32_t in); - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) -unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -#define compute_root SPX_NAMESPACE(compute_root) -void compute_root(unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const spx_ctx *ctx, uint32_t addr[8]); - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -#define treehash SPX_NAMESPACE(treehash) -void treehash(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const spx_ctx *ctx /* ctx */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), - uint32_t tree_addr[8]); - - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/utilsx1.c b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/utilsx1.c deleted file mode 100644 index fccb69b35d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/utilsx1.c +++ /dev/null @@ -1,100 +0,0 @@ -#include - -#include "utilsx1.h" - -#include "address.h" -#include "params.h" -#include "thash.h" -#include "utils.h" - -/* - * Generate the entire Merkle tree, computing the authentication path for - * leaf_idx, and the resulting root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) - * - * This expects tree_addr to be initialized to the addr structures for the - * Merkle tree nodes - * - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - * - * This works by using the standard Merkle tree building algorithm, - */ -void treehashx1(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, - uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* Where to write the leaves */, - const spx_ctx * /* ctx */, - uint32_t idx, void *info), - uint32_t tree_addr[8], - void *info) { - /* This is where we keep the intermediate nodes */ - PQCLEAN_VLA(uint8_t, stack, tree_height * SPX_N); - - uint32_t idx; - uint32_t max_idx = (uint32_t)((1 << tree_height) - 1); - for (idx = 0;; idx++) { - unsigned char current[2 * SPX_N]; /* Current logical node is at */ - /* index[SPX_N]. We do this to minimize the number of copies */ - /* needed during a thash */ - gen_leaf( ¤t[SPX_N], ctx, idx + idx_offset, - info ); - - /* Now combine the freshly generated right node with previously */ - /* generated left ones */ - uint32_t internal_idx_offset = idx_offset; - uint32_t internal_idx = idx; - uint32_t internal_leaf = leaf_idx; - uint32_t h; /* The height we are in the Merkle tree */ - for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { - - /* Check if we hit the top of the tree */ - if (h == tree_height) { - /* We hit the root; return it */ - memcpy( root, ¤t[SPX_N], SPX_N ); - return; - } - - /* - * Check if the node we have is a part of the - * authentication path; if it is, write it out - */ - if ((internal_idx ^ internal_leaf) == 0x01) { - memcpy( &auth_path[ h * SPX_N ], - ¤t[SPX_N], - SPX_N ); - } - - /* - * Check if we're at a left child; if so, stop going up the stack - * Exception: if we've reached the end of the tree, keep on going - * (so we combine the last 4 nodes into the one root node in two - * more iterations) - */ - if ((internal_idx & 1) == 0 && idx < max_idx) { - break; - } - - /* Ok, we're at a right node */ - /* Now combine the left and right logical nodes together */ - - /* Set the address of the node we're creating. */ - internal_idx_offset >>= 1; - set_tree_height(tree_addr, h + 1); - set_tree_index(tree_addr, internal_idx / 2 + internal_idx_offset ); - - unsigned char *left = &stack[h * SPX_N]; - memcpy( ¤t[0], left, SPX_N ); - thash( ¤t[1 * SPX_N], - ¤t[0 * SPX_N], - 2, ctx, tree_addr); - } - - /* We've hit a left child; save the current for when we get the */ - /* corresponding right right */ - memcpy( &stack[h * SPX_N], ¤t[SPX_N], SPX_N); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/utilsx1.h b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/utilsx1.h deleted file mode 100644 index e911d17d53..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/utilsx1.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef SPX_UTILSX4_H -#define SPX_UTILSX4_H - -#include - -#include "context.h" -#include "params.h" - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -#define treehashx1 SPX_NAMESPACE(treehashx1) -void treehashx1(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* Where to write the leaf */, - const spx_ctx * /* ctx */, - uint32_t addr_idx, void *info), - uint32_t tree_addrx4[8], void *info); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/wots.c b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/wots.c deleted file mode 100644 index 249717aaa8..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/wots.c +++ /dev/null @@ -1,108 +0,0 @@ -#include -#include - -#include "wots.h" -#include "wotsx1.h" - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "thash.h" -#include "utils.h" -#include "utilsx1.h" - -// TODO clarify address expectations, and make them more uniform. -// TODO i.e. do we expect types to be set already? -// TODO and do we expect modifications or copies? - -/** - * Computes the chaining function. - * out and in have to be n-byte arrays. - * - * Interprets in as start-th value of the chain. - * addr has to contain the address of the chain. - */ -static void gen_chain(unsigned char *out, const unsigned char *in, - unsigned int start, unsigned int steps, - const spx_ctx *ctx, uint32_t addr[8]) { - uint32_t i; - - /* Initialize out with the value at position 'start'. */ - memcpy(out, in, SPX_N); - - /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < SPX_WOTS_W; i++) { - set_hash_addr(addr, i); - thash(out, out, 1, ctx, addr); - } -} - -/** - * base_w algorithm as described in draft. - * Interprets an array of bytes as integers in base w. - * This only works when log_w is a divisor of 8. - */ -static void base_w(unsigned int *output, const int out_len, - const unsigned char *input) { - int in = 0; - int out = 0; - unsigned char total = 0; - int bits = 0; - int consumed; - - for (consumed = 0; consumed < out_len; consumed++) { - if (bits == 0) { - total = input[in]; - in++; - bits += 8; - } - bits -= SPX_WOTS_LOGW; - output[out] = (total >> bits) & (SPX_WOTS_W - 1); - out++; - } -} - -/* Computes the WOTS+ checksum over a message (in base_w). */ -static void wots_checksum(unsigned int *csum_base_w, - const unsigned int *msg_base_w) { - unsigned int csum = 0; - unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; - unsigned int i; - - /* Compute checksum. */ - for (i = 0; i < SPX_WOTS_LEN1; i++) { - csum += SPX_WOTS_W - 1 - msg_base_w[i]; - } - - /* Convert checksum to base_w. */ - /* Make sure expected empty zero bits are the least significant bits. */ - csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); - ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); - base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); -} - -/* Takes a message and derives the matching chain lengths. */ -void chain_lengths(unsigned int *lengths, const unsigned char *msg) { - base_w(lengths, SPX_WOTS_LEN1, msg); - wots_checksum(lengths + SPX_WOTS_LEN1, lengths); -} - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const spx_ctx *ctx, uint32_t addr[8]) { - unsigned int lengths[SPX_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < SPX_WOTS_LEN; i++) { - set_chain_addr(addr, i); - gen_chain(pk + i * SPX_N, sig + i * SPX_N, - lengths[i], SPX_WOTS_W - 1 - lengths[i], ctx, addr); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/wots.h b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/wots.h deleted file mode 100644 index 4e7692eeef..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/wots.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef SPX_WOTS_H -#define SPX_WOTS_H - -#include - -#include "context.h" -#include "params.h" - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) -void wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const spx_ctx *ctx, uint32_t addr[8]); - -/* - * Compute the chain lengths needed for a given message hash - */ -#define chain_lengths SPX_NAMESPACE(chain_lengths) -void chain_lengths(unsigned int *lengths, const unsigned char *msg); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/wotsx1.c b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/wotsx1.c deleted file mode 100644 index 3adec78dfb..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/wotsx1.c +++ /dev/null @@ -1,76 +0,0 @@ -#include -#include - -#include "wots.h" -#include "wotsx1.h" - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "thash.h" -#include "utils.h" - -/* - * This generates a WOTS public key - * It also generates the WOTS signature if leaf_info indicates - * that we're signing with this WOTS key - */ -void wots_gen_leafx1(unsigned char *dest, - const spx_ctx *ctx, - uint32_t leaf_idx, void *v_info) { - struct leaf_info_x1 *info = v_info; - uint32_t *leaf_addr = info->leaf_addr; - uint32_t *pk_addr = info->pk_addr; - unsigned int i, k; - unsigned char pk_buffer[ SPX_WOTS_BYTES ]; - unsigned char *buffer; - uint32_t wots_k_mask; - - if (leaf_idx == info->wots_sign_leaf) { - /* We're traversing the leaf that's signing; generate the WOTS */ - /* signature */ - wots_k_mask = 0; - } else { - /* Nope, we're just generating pk's; turn off the signature logic */ - wots_k_mask = (uint32_t)~0; - } - - set_keypair_addr( leaf_addr, leaf_idx ); - set_keypair_addr( pk_addr, leaf_idx ); - - for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { - uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k to */ - /* the step if we're generating a signature, ~0 if we're not */ - - /* Start with the secret seed */ - set_chain_addr(leaf_addr, i); - set_hash_addr(leaf_addr, 0); - set_type(leaf_addr, SPX_ADDR_TYPE_WOTSPRF); - - prf_addr(buffer, ctx, leaf_addr); - - set_type(leaf_addr, SPX_ADDR_TYPE_WOTS); - - /* Iterate down the WOTS chain */ - for (k = 0;; k++) { - /* Check if this is the value that needs to be saved as a */ - /* part of the WOTS signature */ - if (k == wots_k) { - memcpy( info->wots_sig + i * SPX_N, buffer, SPX_N ); - } - - /* Check if we hit the top of the chain */ - if (k == SPX_WOTS_W - 1) { - break; - } - - /* Iterate one step on the chain */ - set_hash_addr(leaf_addr, k); - - thash(buffer, buffer, 1, ctx, leaf_addr); - } - } - - /* Do the final thash to generate the public keys */ - thash(dest, pk_buffer, SPX_WOTS_LEN, ctx, pk_addr); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/wotsx1.h b/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/wotsx1.h deleted file mode 100644 index e617929f96..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-128f-robust_clean/wotsx1.h +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef WOTSX1_H_ -#define WOTSX1_H_ - -#include - -#include "context.h" -#include "params.h" - -/* - * This is here to provide an interface to the internal wots_gen_leafx1 - * routine. While this routine is not referenced in the package outside of - * wots.c, it is called from the stand-alone benchmark code to characterize - * the performance - */ -struct leaf_info_x1 { - unsigned char *wots_sig; - uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ - uint32_t *wots_steps; - uint32_t leaf_addr[8]; - uint32_t pk_addr[8]; -}; - -/* Macro to set the leaf_info to something 'benign', that is, it would */ -/* run with the same time as it does during the real signing process */ -/* Used only by the benchmark code */ -#define INITIALIZE_LEAF_INFO_X1(info, addr, step_buffer) { \ - (info).wots_sig = 0; \ - (info).wots_sign_leaf = ~0; \ - (info).wots_steps = step_buffer; \ - memcpy( &(info).leaf_addr[0], (addr), 32 ); \ - memcpy( &(info).pk_addr[0], (addr), 32 ); \ - } - -#define wots_gen_leafx1 SPX_NAMESPACE(wots_gen_leafx1) -void wots_gen_leafx1(unsigned char *dest, - const spx_ctx *ctx, - uint32_t leaf_idx, void *v_info); - -#endif /* WOTSX1_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/LICENSE b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/LICENSE deleted file mode 100644 index 670154e353..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/LICENSE +++ /dev/null @@ -1,116 +0,0 @@ -CC0 1.0 Universal - -Statement of Purpose - -The laws of most jurisdictions throughout the world automatically confer -exclusive Copyright and Related Rights (defined below) upon the creator and -subsequent owner(s) (each and all, an "owner") of an original work of -authorship and/or a database (each, a "Work"). - -Certain owners wish to permanently relinquish those rights to a Work for the -purpose of contributing to a commons of creative, cultural and scientific -works ("Commons") that the public can reliably and without fear of later -claims of infringement build upon, modify, incorporate in other works, reuse -and redistribute as freely as possible in any form whatsoever and for any -purposes, including without limitation commercial purposes. These owners may -contribute to the Commons to promote the ideal of a free culture and the -further production of creative, cultural and scientific works, or to gain -reputation or greater distribution for their Work in part through the use and -efforts of others. - -For these and/or other purposes and motivations, and without any expectation -of additional consideration or compensation, the person associating CC0 with a -Work (the "Affirmer"), to the extent that he or she is an owner of Copyright -and Related Rights in the Work, voluntarily elects to apply CC0 to the Work -and publicly distribute the Work under its terms, with knowledge of his or her -Copyright and Related Rights in the Work and the meaning and intended legal -effect of CC0 on those rights. - -1. Copyright and Related Rights. A Work made available under CC0 may be -protected by copyright and related or neighboring rights ("Copyright and -Related Rights"). Copyright and Related Rights include, but are not limited -to, the following: - - i. the right to reproduce, adapt, distribute, perform, display, communicate, - and translate a Work; - - ii. moral rights retained by the original author(s) and/or performer(s); - - iii. publicity and privacy rights pertaining to a person's image or likeness - depicted in a Work; - - iv. rights protecting against unfair competition in regards to a Work, - subject to the limitations in paragraph 4(a), below; - - v. rights protecting the extraction, dissemination, use and reuse of data in - a Work; - - vi. database rights (such as those arising under Directive 96/9/EC of the - European Parliament and of the Council of 11 March 1996 on the legal - protection of databases, and under any national implementation thereof, - including any amended or successor version of such directive); and - - vii. other similar, equivalent or corresponding rights throughout the world - based on applicable law or treaty, and any national implementations thereof. - -2. Waiver. To the greatest extent permitted by, but not in contravention of, -applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and -unconditionally waives, abandons, and surrenders all of Affirmer's Copyright -and Related Rights and associated claims and causes of action, whether now -known or unknown (including existing as well as future claims and causes of -action), in the Work (i) in all territories worldwide, (ii) for the maximum -duration provided by applicable law or treaty (including future time -extensions), (iii) in any current or future medium and for any number of -copies, and (iv) for any purpose whatsoever, including without limitation -commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes -the Waiver for the benefit of each member of the public at large and to the -detriment of Affirmer's heirs and successors, fully intending that such Waiver -shall not be subject to revocation, rescission, cancellation, termination, or -any other legal or equitable action to disrupt the quiet enjoyment of the Work -by the public as contemplated by Affirmer's express Statement of Purpose. - -3. Public License Fallback. Should any part of the Waiver for any reason be -judged legally invalid or ineffective under applicable law, then the Waiver -shall be preserved to the maximum extent permitted taking into account -Affirmer's express Statement of Purpose. In addition, to the extent the Waiver -is so judged Affirmer hereby grants to each affected person a royalty-free, -non transferable, non sublicensable, non exclusive, irrevocable and -unconditional license to exercise Affirmer's Copyright and Related Rights in -the Work (i) in all territories worldwide, (ii) for the maximum duration -provided by applicable law or treaty (including future time extensions), (iii) -in any current or future medium and for any number of copies, and (iv) for any -purpose whatsoever, including without limitation commercial, advertising or -promotional purposes (the "License"). The License shall be deemed effective as -of the date CC0 was applied by Affirmer to the Work. Should any part of the -License for any reason be judged legally invalid or ineffective under -applicable law, such partial invalidity or ineffectiveness shall not -invalidate the remainder of the License, and in such case Affirmer hereby -affirms that he or she will not (i) exercise any of his or her remaining -Copyright and Related Rights in the Work or (ii) assert any associated claims -and causes of action with respect to the Work, in either case contrary to -Affirmer's express Statement of Purpose. - -4. Limitations and Disclaimers. - - a. No trademark or patent rights held by Affirmer are waived, abandoned, - surrendered, licensed or otherwise affected by this document. - - b. Affirmer offers the Work as-is and makes no representations or warranties - of any kind concerning the Work, express, implied, statutory or otherwise, - including without limitation warranties of title, merchantability, fitness - for a particular purpose, non infringement, or the absence of latent or - other defects, accuracy, or the present or absence of errors, whether or not - discoverable, all to the greatest extent permissible under applicable law. - - c. Affirmer disclaims responsibility for clearing rights of other persons - that may apply to the Work or any use thereof, including without limitation - any person's Copyright and Related Rights in the Work. Further, Affirmer - disclaims responsibility for obtaining any necessary consents, permissions - or other rights required for any use of the Work. - - d. Affirmer understands and acknowledges that Creative Commons is not a - party to this document and has no duty or obligation with respect to this - CC0 or use of the Work. - -For more information, please see - diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/address.c b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/address.c deleted file mode 100644 index d49d9f3b6b..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/address.c +++ /dev/null @@ -1,95 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "utils.h" - -/* - * Specify which level of Merkle tree (the "layer") we're working on - */ -void set_layer_addr(uint32_t addr[8], uint32_t layer) { - ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; -} - -/* - * Specify which Merkle tree within the level (the "tree address") we're working on - */ -void set_tree_addr(uint32_t addr[8], uint64_t tree) { - ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); -} - -/* - * Specify the reason we'll use this address structure for, that is, what - * hash will we compute with it. This is used so that unrelated types of - * hashes don't accidentally get the same address structure. The type will be - * one of the SPX_ADDR_TYPE constants - */ -void set_type(uint32_t addr[8], uint32_t type) { - ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; -} - -/* - * Copy the layer and tree fields of the address structure. This is used - * when we're doing multiple types of hashes within the same Merkle tree - */ -void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { - memcpy( out, in, SPX_OFFSET_TREE + 8 ); -} - -/* These functions are used for OTS addresses. */ - -/* - * Specify which Merkle leaf we're working on; that is, which OTS keypair - * we're talking about. - */ -void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { - /* We have > 256 OTS at the bottom of the Merkle tree; to specify */ - /* which one, we'd need to express it in two bytes */ - ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR2] = (unsigned char)(keypair >> 8); - ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; -} - -/* - * Copy the layer, tree and keypair fields of the address structure. This is - * used when we're doing multiple things within the same OTS keypair - */ -void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { - memcpy( out, in, SPX_OFFSET_TREE + 8 ); - ((unsigned char *)out)[SPX_OFFSET_KP_ADDR2] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR2]; - ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; -} - -/* - * Specify which Merkle chain within the OTS we're working with - * (the chain address) - */ -void set_chain_addr(uint32_t addr[8], uint32_t chain) { - ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; -} - -/* - * Specify where in the Merkle chain we are -* (the hash address) - */ -void set_hash_addr(uint32_t addr[8], uint32_t hash) { - ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; -} - -/* These functions are used for all hash tree addresses (including FORS). */ - -/* - * Specify the height of the node in the Merkle/FORS tree we are in - * (the tree height) - */ -void set_tree_height(uint32_t addr[8], uint32_t tree_height) { - ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; -} - -/* - * Specify the distance from the left edge of the node in the Merkle/FORS tree - * (the tree index) - */ -void set_tree_index(uint32_t addr[8], uint32_t tree_index) { - u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/address.h b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/address.h deleted file mode 100644 index 24a84eb40c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/address.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef SPX_ADDRESS_H -#define SPX_ADDRESS_H - -#include - -#include "params.h" - -/* The hash types that are passed to set_type */ -#define SPX_ADDR_TYPE_WOTS 0 -#define SPX_ADDR_TYPE_WOTSPK 1 -#define SPX_ADDR_TYPE_HASHTREE 2 -#define SPX_ADDR_TYPE_FORSTREE 3 -#define SPX_ADDR_TYPE_FORSPK 4 -#define SPX_ADDR_TYPE_WOTSPRF 5 -#define SPX_ADDR_TYPE_FORSPRF 6 - -#define set_layer_addr SPX_NAMESPACE(set_layer_addr) -void set_layer_addr(uint32_t addr[8], uint32_t layer); - -#define set_tree_addr SPX_NAMESPACE(set_tree_addr) -void set_tree_addr(uint32_t addr[8], uint64_t tree); - -#define set_type SPX_NAMESPACE(set_type) -void set_type(uint32_t addr[8], uint32_t type); - -/* Copies the layer and tree part of one address into the other */ -#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) -void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for WOTS and FORS addresses. */ - -#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) -void set_keypair_addr(uint32_t addr[8], uint32_t keypair); - -#define set_chain_addr SPX_NAMESPACE(set_chain_addr) -void set_chain_addr(uint32_t addr[8], uint32_t chain); - -#define set_hash_addr SPX_NAMESPACE(set_hash_addr) -void set_hash_addr(uint32_t addr[8], uint32_t hash); - -#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) -void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for all hash tree addresses (including FORS). */ - -#define set_tree_height SPX_NAMESPACE(set_tree_height) -void set_tree_height(uint32_t addr[8], uint32_t tree_height); - -#define set_tree_index SPX_NAMESPACE(set_tree_index) -void set_tree_index(uint32_t addr[8], uint32_t tree_index); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/api.h b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/api.h deleted file mode 100644 index a65994d064..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/api.h +++ /dev/null @@ -1,77 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA2128SROBUST_AVX2_API_H -#define PQCLEAN_SPHINCSSHA2128SROBUST_AVX2_API_H - -#include -#include - -#define PQCLEAN_SPHINCSSHA2128SROBUST_AVX2_CRYPTO_ALGNAME "SPHINCS+-sha2-128s-robust" - -#define PQCLEAN_SPHINCSSHA2128SROBUST_AVX2_CRYPTO_SECRETKEYBYTES 64 -#define PQCLEAN_SPHINCSSHA2128SROBUST_AVX2_CRYPTO_PUBLICKEYBYTES 32 -#define PQCLEAN_SPHINCSSHA2128SROBUST_AVX2_CRYPTO_BYTES 7856 - -#define PQCLEAN_SPHINCSSHA2128SROBUST_AVX2_CRYPTO_SEEDBYTES 48 - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSSHA2128SROBUST_AVX2_crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSSHA2128SROBUST_AVX2_crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSSHA2128SROBUST_AVX2_crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSSHA2128SROBUST_AVX2_crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHA2128SROBUST_AVX2_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHA2128SROBUST_AVX2_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSSHA2128SROBUST_AVX2_crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSSHA2128SROBUST_AVX2_crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, - const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSSHA2128SROBUST_AVX2_crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSSHA2128SROBUST_AVX2_crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk); -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/context.h b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/context.h deleted file mode 100644 index 200d3c0fb1..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/context.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef SPX_CONTEXT_H -#define SPX_CONTEXT_H - -#include - -#include "params.h" -#include "sha2.h" -#include "sha256avx.h" - -// funky ordering due to optimal padding -typedef struct { - sha256x8ctx statex8_seeded; - sha256ctx state_seeded; - - uint8_t pub_seed[SPX_N]; - uint8_t sk_seed[SPX_N]; -} spx_ctx; - - -#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) -void initialize_hash_function(spx_ctx *ctx); - -#define free_hash_function SPX_NAMESPACE(free_hash_function) -void free_hash_function(spx_ctx *ctx); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/context_sha2.c b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/context_sha2.c deleted file mode 100644 index 073af8dd15..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/context_sha2.c +++ /dev/null @@ -1,44 +0,0 @@ -#include - -#include "context.h" - -/** - * Absorb the constant pub_seed using one round of the compression function - * This initializes state_seeded and state_seeded_512, which can then be - * reused in thash - **/ -static void seed_state(spx_ctx *ctx) { - uint8_t block[SPX_SHA512_BLOCK_BYTES]; - size_t i; - - for (i = 0; i < SPX_N; ++i) { - block[i] = ctx->pub_seed[i]; - } - for (i = SPX_N; i < SPX_SHA512_BLOCK_BYTES; ++i) { - block[i] = 0; - } - /* block has been properly initialized for both SHA-256 and SHA-512 */ - - sha256_inc_init(&ctx->state_seeded); - sha256_inc_blocks(&ctx->state_seeded, block, 1); - - // initialize x8 - sha256_init8x(&ctx->statex8_seeded); - sha256_transform8x(&ctx->statex8_seeded, - block, block, block, block, block, block, block, block); - - ctx->statex8_seeded.datalen = 0; - ctx->statex8_seeded.msglen = 512; - -} - - -/* For SHA, we initialize the hash function at the start */ -void initialize_hash_function(spx_ctx *ctx) { - seed_state(ctx); -} - -/* Free the incremental hashing context for heap-based SHA2 APIs */ -void free_hash_function(spx_ctx *ctx) { - sha256_inc_ctx_release(&ctx->state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/fors.c b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/fors.c deleted file mode 100644 index 4cab8e7415..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/fors.c +++ /dev/null @@ -1,226 +0,0 @@ -#include -#include -#include - -#include "fors.h" - - -#include "address.h" -#include "hash.h" -#include "hashx8.h" -#include "thash.h" -#include "thashx8.h" -#include "utils.h" -#include "utilsx8.h" -static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, - uint32_t fors_leaf_addr[8]) { - prf_addr(sk, ctx, fors_leaf_addr); -} - -static void fors_gen_skx8(unsigned char *sk0, - unsigned char *sk1, - unsigned char *sk2, - unsigned char *sk3, - unsigned char *sk4, - unsigned char *sk5, - unsigned char *sk6, - unsigned char *sk7, const spx_ctx *ctx, - uint32_t fors_leaf_addrx8[8 * 8]) { - prf_addrx8(sk0, sk1, sk2, sk3, sk4, sk5, sk6, sk7, - ctx, fors_leaf_addrx8); -} - -static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, - const spx_ctx *ctx, - uint32_t fors_leaf_addr[8]) { - thash(leaf, sk, 1, ctx, fors_leaf_addr); -} - -static void fors_sk_to_leafx8(unsigned char *leaf0, - unsigned char *leaf1, - unsigned char *leaf2, - unsigned char *leaf3, - unsigned char *leaf4, - unsigned char *leaf5, - unsigned char *leaf6, - unsigned char *leaf7, - const unsigned char *sk0, - const unsigned char *sk1, - const unsigned char *sk2, - const unsigned char *sk3, - const unsigned char *sk4, - const unsigned char *sk5, - const unsigned char *sk6, - const unsigned char *sk7, - const spx_ctx *ctx, - uint32_t fors_leaf_addrx8[8 * 8]) { - thashx8(leaf0, leaf1, leaf2, leaf3, leaf4, leaf5, leaf6, leaf7, - sk0, sk1, sk2, sk3, sk4, sk5, sk6, sk7, - 1, ctx, fors_leaf_addrx8); -} - -struct fors_gen_leaf_info { - uint32_t leaf_addrx[8 * 8]; -}; - -static void fors_gen_leafx8(unsigned char *leaf, - const spx_ctx *ctx, - uint32_t addr_idx, void *info) { - struct fors_gen_leaf_info *fors_info = info; - uint32_t *fors_leaf_addrx8 = fors_info->leaf_addrx; - unsigned int j; - - /* Only set the parts that the caller doesn't set */ - for (j = 0; j < 8; j++) { - set_tree_index(fors_leaf_addrx8 + j * 8, addr_idx + j); - set_type(fors_leaf_addrx8 + j * 8, SPX_ADDR_TYPE_FORSPRF); - } - - fors_gen_skx8(leaf + 0 * SPX_N, - leaf + 1 * SPX_N, - leaf + 2 * SPX_N, - leaf + 3 * SPX_N, - leaf + 4 * SPX_N, - leaf + 5 * SPX_N, - leaf + 6 * SPX_N, - leaf + 7 * SPX_N, - ctx, fors_leaf_addrx8); - - for (j = 0; j < 8; j++) { - set_type(fors_leaf_addrx8 + j * 8, SPX_ADDR_TYPE_FORSTREE); - } - - fors_sk_to_leafx8(leaf + 0 * SPX_N, - leaf + 1 * SPX_N, - leaf + 2 * SPX_N, - leaf + 3 * SPX_N, - leaf + 4 * SPX_N, - leaf + 5 * SPX_N, - leaf + 6 * SPX_N, - leaf + 7 * SPX_N, - leaf + 0 * SPX_N, - leaf + 1 * SPX_N, - leaf + 2 * SPX_N, - leaf + 3 * SPX_N, - leaf + 4 * SPX_N, - leaf + 5 * SPX_N, - leaf + 6 * SPX_N, - leaf + 7 * SPX_N, - ctx, fors_leaf_addrx8); -} - -/** - * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - * Assumes indices has space for SPX_FORS_TREES integers. - */ -static void message_to_indices(uint32_t *indices, const unsigned char *m) { - unsigned int i, j; - unsigned int offset = 0; - - for (i = 0; i < SPX_FORS_TREES; i++) { - indices[i] = 0; - for (j = 0; j < SPX_FORS_HEIGHT; j++) { - indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); - offset++; - } - } -} - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -void fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]) { - uint32_t indices[SPX_FORS_TREES]; - unsigned char roots[SPX_FORS_TREES * SPX_N]; - uint32_t fors_tree_addr[8 * 8] = {0}; - struct fors_gen_leaf_info fors_info = {0}; - uint32_t *fors_leaf_addr = fors_info.leaf_addrx; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - for (i = 0; i < 8; i++) { - copy_keypair_addr(fors_tree_addr + 8 * i, fors_addr); - set_type(fors_tree_addr + 8 * i, SPX_ADDR_TYPE_FORSTREE); - copy_keypair_addr(fors_leaf_addr + 8 * i, fors_addr); - } - copy_keypair_addr(fors_pk_addr, fors_addr); - set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < SPX_FORS_TREES; i++) { - idx_offset = i * (1 << SPX_FORS_HEIGHT); - - set_tree_height(fors_tree_addr, 0); - set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Include the secret key part that produces the selected leaf node. */ - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); - fors_gen_sk(sig, ctx, fors_tree_addr); - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); - sig += SPX_N; - - /* Compute the authentication path for this leaf node. */ - treehashx8(roots + i * SPX_N, sig, ctx, - indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx8, - fors_tree_addr, &fors_info); - - sig += SPX_N * SPX_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); -} - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -void fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]) { - uint32_t indices[SPX_FORS_TREES]; - unsigned char roots[SPX_FORS_TREES * SPX_N]; - unsigned char leaf[SPX_N]; - uint32_t fors_tree_addr[8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - copy_keypair_addr(fors_tree_addr, fors_addr); - copy_keypair_addr(fors_pk_addr, fors_addr); - - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); - set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < SPX_FORS_TREES; i++) { - idx_offset = i * (1 << SPX_FORS_HEIGHT); - - set_tree_height(fors_tree_addr, 0); - set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Derive the leaf from the included secret key part. */ - fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); - sig += SPX_N; - - /* Derive the corresponding root node of this tree. */ - compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, - sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); - sig += SPX_N * SPX_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/fors.h b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/fors.h deleted file mode 100644 index 509140a178..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/fors.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef SPX_FORS_H -#define SPX_FORS_H - -#include - -#include "context.h" -#include "params.h" - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -#define fors_sign SPX_NAMESPACE(fors_sign) -void fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]); - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) -void fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/hash.h b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/hash.h deleted file mode 100644 index ffe815f45d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/hash.h +++ /dev/null @@ -1,37 +0,0 @@ -#ifndef SPX_HASH_H -#define SPX_HASH_H - -#include -#include - -#include "context.h" -#include "params.h" - -#define prf_addr SPX_NAMESPACE(prf_addr) -void prf_addr(unsigned char *out, const spx_ctx *ctx, - const uint32_t addr[8]); - -#define gen_message_random SPX_NAMESPACE(gen_message_random) -void gen_message_random(unsigned char *R, const unsigned char *sk_prf, - const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx); - -#define hash_message SPX_NAMESPACE(hash_message) -void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx); - - -# define SPX_SHA256_ADDR_BYTES 22 - -# define mgf1_256 SPX_NAMESPACE(mgf1_256) -void mgf1_256(unsigned char *out, unsigned long outlen, - const unsigned char *in, unsigned long inlen); - -# define mgf1_512 SPX_NAMESPACE(mgf1_512) -void mgf1_512(unsigned char *out, unsigned long outlen, - const unsigned char *in, unsigned long inlen); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/hash_sha2.c b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/hash_sha2.c deleted file mode 100644 index 69f0dc0013..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/hash_sha2.c +++ /dev/null @@ -1,219 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "sha2.h" -#include "utils.h" - - - -#define SPX_SHAX_OUTPUT_BYTES SPX_SHA256_OUTPUT_BYTES -#define SPX_SHAX_BLOCK_BYTES SPX_SHA256_BLOCK_BYTES -#define shaX_inc_init sha256_inc_init -#define shaX_inc_blocks sha256_inc_blocks -#define shaX_inc_finalize sha256_inc_finalize -#define shaX sha256 -#define mgf1_X mgf1_256 -#define shaXstate sha256ctx - -/** - * mgf1 function based on the SHA-256 hash function - * Note that inlen should be sufficiently small that it still allows for - * an array to be allocated on the stack. Typically 'in' is merely a seed. - * Outputs outlen number of bytes - */ -void mgf1_256(unsigned char *out, unsigned long outlen, - const unsigned char *in, unsigned long inlen) { - PQCLEAN_VLA(uint8_t, inbuf, inlen + 4); - unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES]; - uint32_t i; - - memcpy(inbuf, in, inlen); - - /* While we can fit in at least another full block of SHA256 output.. */ - for (i = 0; (i + 1)*SPX_SHA256_OUTPUT_BYTES <= outlen; i++) { - u32_to_bytes(inbuf + inlen, i); - sha256(out, inbuf, inlen + 4); - out += SPX_SHA256_OUTPUT_BYTES; - } - /* Until we cannot anymore, and we fill the remainder. */ - if (outlen > i * SPX_SHA256_OUTPUT_BYTES) { - u32_to_bytes(inbuf + inlen, i); - sha256(outbuf, inbuf, inlen + 4); - memcpy(out, outbuf, outlen - i * SPX_SHA256_OUTPUT_BYTES); - } -} - -/* - * mgf1 function based on the SHA-512 hash function - */ -void mgf1_512(unsigned char *out, unsigned long outlen, - const unsigned char *in, unsigned long inlen) { - PQCLEAN_VLA(uint8_t, inbuf, inlen + 4); - unsigned char outbuf[SPX_SHA512_OUTPUT_BYTES]; - uint32_t i; - - memcpy(inbuf, in, inlen); - - /* While we can fit in at least another full block of SHA512 output.. */ - for (i = 0; (i + 1)*SPX_SHA512_OUTPUT_BYTES <= outlen; i++) { - u32_to_bytes(inbuf + inlen, i); - sha512(out, inbuf, inlen + 4); - out += SPX_SHA512_OUTPUT_BYTES; - } - /* Until we cannot anymore, and we fill the remainder. */ - if (outlen > i * SPX_SHA512_OUTPUT_BYTES) { - u32_to_bytes(inbuf + inlen, i); - sha512(outbuf, inbuf, inlen + 4); - memcpy(out, outbuf, outlen - i * SPX_SHA512_OUTPUT_BYTES); - } -} - -/* - * Computes PRF(pk_seed, sk_seed, addr). - */ -void prf_addr(unsigned char *out, const spx_ctx *ctx, - const uint32_t addr[8]) { - sha256ctx sha2_state; - unsigned char buf[SPX_SHA256_ADDR_BYTES + SPX_N]; - unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES]; - - /* Retrieve precomputed state containing pub_seed */ - sha256_inc_ctx_clone(&sha2_state, &ctx->state_seeded); - - /* Remainder: ADDR^c ‖ SK.seed */ - memcpy(buf, addr, SPX_SHA256_ADDR_BYTES); - memcpy(buf + SPX_SHA256_ADDR_BYTES, ctx->sk_seed, SPX_N); - - sha256_inc_finalize(outbuf, &sha2_state, buf, SPX_SHA256_ADDR_BYTES + SPX_N); - - memcpy(out, outbuf, SPX_N); -} - -/** - * Computes the message-dependent randomness R, using a secret seed as a key - * for HMAC, and an optional randomization value prefixed to the message. - * This requires m to have at least SPX_SHAX_BLOCK_BYTES + SPX_N space - * available in front of the pointer, i.e. before the message to use for the - * prefix. This is necessary to prevent having to move the message around (and - * allocate memory for it). - */ -void gen_message_random(unsigned char *R, const unsigned char *sk_prf, - const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx) { - (void)ctx; - - unsigned char buf[SPX_SHAX_BLOCK_BYTES + SPX_SHAX_OUTPUT_BYTES]; - shaXstate state; - int i; - - - /* This implements HMAC-SHA */ - for (i = 0; i < SPX_N; i++) { - buf[i] = 0x36 ^ sk_prf[i]; - } - memset(buf + SPX_N, 0x36, SPX_SHAX_BLOCK_BYTES - SPX_N); - - shaX_inc_init(&state); - shaX_inc_blocks(&state, buf, 1); - - memcpy(buf, optrand, SPX_N); - - /* If optrand + message cannot fill up an entire block */ - if (SPX_N + mlen < SPX_SHAX_BLOCK_BYTES) { - memcpy(buf + SPX_N, m, mlen); - shaX_inc_finalize(buf + SPX_SHAX_BLOCK_BYTES, &state, - buf, mlen + SPX_N); - } - /* Otherwise first fill a block, so that finalize only uses the message */ - else { - memcpy(buf + SPX_N, m, SPX_SHAX_BLOCK_BYTES - SPX_N); - shaX_inc_blocks(&state, buf, 1); - - m += SPX_SHAX_BLOCK_BYTES - SPX_N; - mlen -= SPX_SHAX_BLOCK_BYTES - SPX_N; - shaX_inc_finalize(buf + SPX_SHAX_BLOCK_BYTES, &state, m, mlen); - } - - for (i = 0; i < SPX_N; i++) { - buf[i] = 0x5c ^ sk_prf[i]; - } - memset(buf + SPX_N, 0x5c, SPX_SHAX_BLOCK_BYTES - SPX_N); - - shaX(buf, buf, SPX_SHAX_BLOCK_BYTES + SPX_SHAX_OUTPUT_BYTES); - memcpy(R, buf, SPX_N); -} - -/** - * Computes the message hash using R, the public key, and the message. - * Outputs the message digest and the index of the leaf. The index is split in - * the tree index and the leaf index, for convenient copying to an address. - */ -void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx) { - (void)ctx; -#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) -#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) -#define SPX_LEAF_BITS SPX_TREE_HEIGHT -#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) -#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) - - unsigned char seed[2 * SPX_N + SPX_SHAX_OUTPUT_BYTES]; - - /* Round to nearest multiple of SPX_SHAX_BLOCK_BYTES */ -#define SPX_INBLOCKS (((SPX_N + SPX_PK_BYTES + SPX_SHAX_BLOCK_BYTES - 1) & \ - -SPX_SHAX_BLOCK_BYTES) / SPX_SHAX_BLOCK_BYTES) - unsigned char inbuf[SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES]; - - unsigned char buf[SPX_DGST_BYTES]; - unsigned char *bufp = buf; - shaXstate state; - - shaX_inc_init(&state); - - // seed: SHA-X(R ‖ PK.seed ‖ PK.root ‖ M) - memcpy(inbuf, R, SPX_N); - memcpy(inbuf + SPX_N, pk, SPX_PK_BYTES); - - /* If R + pk + message cannot fill up an entire block */ - if (SPX_N + SPX_PK_BYTES + mlen < SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES) { - memcpy(inbuf + SPX_N + SPX_PK_BYTES, m, mlen); - shaX_inc_finalize(seed + 2 * SPX_N, &state, inbuf, SPX_N + SPX_PK_BYTES + mlen); - } - /* Otherwise first fill a block, so that finalize only uses the message */ - else { - memcpy(inbuf + SPX_N + SPX_PK_BYTES, m, - SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES - SPX_N - SPX_PK_BYTES); - shaX_inc_blocks(&state, inbuf, SPX_INBLOCKS); - - m += SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES - SPX_N - SPX_PK_BYTES; - mlen -= SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES - SPX_N - SPX_PK_BYTES; - shaX_inc_finalize(seed + 2 * SPX_N, &state, m, (size_t)mlen); - } - - // H_msg: MGF1-SHA-X(R ‖ PK.seed ‖ seed) - memcpy(seed, R, SPX_N); - memcpy(seed + SPX_N, pk, SPX_N); - - /* By doing this in two steps, we prevent hashing the message twice; - otherwise each iteration in MGF1 would hash the message again. */ - mgf1_X(bufp, SPX_DGST_BYTES, seed, 2 * SPX_N + SPX_SHAX_OUTPUT_BYTES); - - memcpy(digest, bufp, SPX_FORS_MSG_BYTES); - bufp += SPX_FORS_MSG_BYTES; - - - *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); - *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); - bufp += SPX_TREE_BYTES; - - *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); - *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); -} - - diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/hash_sha2x8.c b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/hash_sha2x8.c deleted file mode 100644 index e04af7a069..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/hash_sha2x8.c +++ /dev/null @@ -1,75 +0,0 @@ -#include -#include - -#include "hash.h" -#include "hashx8.h" - -#include "address.h" -#include "params.h" -#include "sha2.h" -#include "sha256avx.h" -#include "sha256x8.h" -#include "utils.h" - -/* - * 8-way parallel version of prf_addr; takes 8x as much input and output - */ -void prf_addrx8(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7, - const spx_ctx *ctx, - const uint32_t addrx8[8 * 8]) { - unsigned char bufx8[8 * (SPX_N + SPX_SHA256_ADDR_BYTES)]; - unsigned char outbufx8[8 * SPX_SHA256_OUTPUT_BYTES]; - unsigned int j; - - for (j = 0; j < 8; j++) { - memcpy(bufx8 + j * (SPX_N + SPX_SHA256_ADDR_BYTES), - addrx8 + j * 8, SPX_SHA256_ADDR_BYTES); - memcpy( - bufx8 + j * (SPX_N + SPX_SHA256_ADDR_BYTES) + SPX_SHA256_ADDR_BYTES, - ctx->sk_seed, - SPX_N - ); - } - - sha256x8_seeded( - /* out */ - outbufx8 + 0 * SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 1 * SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 2 * SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 3 * SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 4 * SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 5 * SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 6 * SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 7 * SPX_SHA256_OUTPUT_BYTES, - - /* seed */ - &ctx->statex8_seeded, - - /* in */ - bufx8 + 0 * (SPX_SHA256_ADDR_BYTES + SPX_N), - bufx8 + 1 * (SPX_SHA256_ADDR_BYTES + SPX_N), - bufx8 + 2 * (SPX_SHA256_ADDR_BYTES + SPX_N), - bufx8 + 3 * (SPX_SHA256_ADDR_BYTES + SPX_N), - bufx8 + 4 * (SPX_SHA256_ADDR_BYTES + SPX_N), - bufx8 + 5 * (SPX_SHA256_ADDR_BYTES + SPX_N), - bufx8 + 6 * (SPX_SHA256_ADDR_BYTES + SPX_N), - bufx8 + 7 * (SPX_SHA256_ADDR_BYTES + SPX_N), - SPX_SHA256_ADDR_BYTES + SPX_N /* len */ - ); - - memcpy(out0, outbufx8 + 0 * SPX_SHA256_OUTPUT_BYTES, SPX_N); - memcpy(out1, outbufx8 + 1 * SPX_SHA256_OUTPUT_BYTES, SPX_N); - memcpy(out2, outbufx8 + 2 * SPX_SHA256_OUTPUT_BYTES, SPX_N); - memcpy(out3, outbufx8 + 3 * SPX_SHA256_OUTPUT_BYTES, SPX_N); - memcpy(out4, outbufx8 + 4 * SPX_SHA256_OUTPUT_BYTES, SPX_N); - memcpy(out5, outbufx8 + 5 * SPX_SHA256_OUTPUT_BYTES, SPX_N); - memcpy(out6, outbufx8 + 6 * SPX_SHA256_OUTPUT_BYTES, SPX_N); - memcpy(out7, outbufx8 + 7 * SPX_SHA256_OUTPUT_BYTES, SPX_N); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/hashx8.h b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/hashx8.h deleted file mode 100644 index 46503f0a10..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/hashx8.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef SPX_HASHX8_H -#define SPX_HASHX8_H - -#include - -#include "params.h" - -#define prf_addrx8 SPX_NAMESPACE(prf_addrx8) -void prf_addrx8(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7, - const spx_ctx *ctx, - const uint32_t addrx8[8 * 8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/merkle.c b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/merkle.c deleted file mode 100644 index 1f353c8dd8..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/merkle.c +++ /dev/null @@ -1,65 +0,0 @@ -#include -#include - -#include "merkle.h" - -#include "address.h" -#include "params.h" -#include "utils.h" -#include "utilsx8.h" -#include "wots.h" -#include "wotsx8.h" - -/* - * This generates a Merkle signature (WOTS signature followed by the Merkle - * authentication path). - */ -void merkle_sign(uint8_t *sig, unsigned char *root, - const spx_ctx *ctx, - uint32_t wots_addr[8], uint32_t tree_addr[8], - uint32_t idx_leaf) { - unsigned char *auth_path = sig + SPX_WOTS_BYTES; - uint32_t tree_addrx8[8 * 8] = { 0 }; - int j; - struct leaf_info_x8 info = { 0 }; - unsigned steps[ SPX_WOTS_LEN ]; - - info.wots_sig = sig; - chain_lengths(steps, root); - info.wots_steps = steps; - - for (j = 0; j < 8; j++) { - set_type(&tree_addrx8[8 * j], SPX_ADDR_TYPE_HASHTREE); - set_type(&info.leaf_addr[8 * j], SPX_ADDR_TYPE_WOTS); - set_type(&info.pk_addr[8 * j], SPX_ADDR_TYPE_WOTSPK); - copy_subtree_addr(&tree_addrx8[8 * j], tree_addr); - copy_subtree_addr(&info.leaf_addr[8 * j], wots_addr); - copy_subtree_addr(&info.pk_addr[8 * j], wots_addr); - } - - info.wots_sign_leaf = idx_leaf; - - treehashx8(root, auth_path, ctx, - idx_leaf, 0, - SPX_TREE_HEIGHT, - wots_gen_leafx8, - tree_addrx8, &info); -} - -/* Compute root node of the top-most subtree. */ -/* Again, in this file because wots_gen_leaf is most of the work */ -void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { - /* We do not need the auth path in key generation, but it simplifies the - code to have just one treehash routine that computes both root and path - in one function. */ - unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; - uint32_t top_tree_addr[8] = {0}; - uint32_t wots_addr[8] = {0}; - - set_layer_addr(top_tree_addr, SPX_D - 1); - set_layer_addr(wots_addr, SPX_D - 1); - - merkle_sign(auth_path, root, ctx, - wots_addr, top_tree_addr, - ~0U /* ~0 means "don't bother generating an auth path */ ); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/merkle.h b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/merkle.h deleted file mode 100644 index 769cf2e970..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/merkle.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef MERKLE_H_ -#define MERKLE_H_ - -#include - -#include "context.h" -#include "params.h" - -/* Generate a Merkle signature (WOTS signature followed by the Merkle */ -/* authentication path) */ -#define merkle_sign SPX_NAMESPACE(merkle_sign) -void merkle_sign(uint8_t *sig, unsigned char *root, - const spx_ctx *ctx, - uint32_t wots_addr[8], uint32_t tree_addr[8], - uint32_t idx_leaf); - -/* Compute the root node of the top-most subtree. */ -#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) -void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); - -#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/nistapi.h b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/nistapi.h deleted file mode 100644 index 3cb71afad4..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/nistapi.h +++ /dev/null @@ -1,87 +0,0 @@ -#ifndef SPX_API_H -#define SPX_API_H - -#include -#include - -#include "params.h" - -#define CRYPTO_ALGNAME "SPHINCS+" - -#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES -#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES -#define CRYPTO_BYTES SPX_BYTES -#define CRYPTO_SEEDBYTES (3*SPX_N) - -/* - * Returns the length of a secret key, in bytes - */ -#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) -size_t crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) -size_t crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) -size_t crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) -size_t crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) -int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) -int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) -int crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) -int crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -#define crypto_sign SPX_NAMESPACE(crypto_sign) -int crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) -int crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/params.h b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/params.h deleted file mode 100644 index ea5b76871e..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/params.h +++ /dev/null @@ -1,61 +0,0 @@ -#ifndef SPX_PARAMS_H -#define SPX_PARAMS_H - -#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSSHA2128SROBUST_AVX2_##s - -/* Hash output length in bytes. */ -#define SPX_N 16 -/* Height of the hypertree. */ -#define SPX_FULL_HEIGHT 63 -/* Number of subtree layer. */ -#define SPX_D 7 -/* FORS tree dimensions. */ -#define SPX_FORS_HEIGHT 12 -#define SPX_FORS_TREES 14 -/* Winternitz parameter, */ -#define SPX_WOTS_W 16 - -/* The hash function is defined by linking a different hash.c file, as opposed - to setting a #define constant. */ - -/* This is a SHA2-based parameter set, hence whether we use SHA-256 - * exclusively or we use both SHA-256 and SHA-512 is controlled by - * the following #define */ -#define SPX_SHA512 0 /* Use SHA-256 for all hashes */ - -/* For clarity */ -#define SPX_ADDR_BYTES 32 - -/* WOTS parameters. */ -#define SPX_WOTS_LOGW 4 - -#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) - -/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#define SPX_WOTS_LEN2 3 - -#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) -#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) -#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES - -/* Subtree size. */ -#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) - -//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT -// #error SPX_D should always divide SPX_FULL_HEIGHT -//#endif - -/* FORS parameters. */ -#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) -#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) -#define SPX_FORS_PK_BYTES SPX_N - -/* Resulting SPX sizes. */ -#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ - SPX_FULL_HEIGHT * SPX_N) -#define SPX_PK_BYTES (2 * SPX_N) -#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) - -#include "sha2_offsets.h" - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/sha256avx.c b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/sha256avx.c deleted file mode 100644 index 6bbe6ecc24..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/sha256avx.c +++ /dev/null @@ -1,357 +0,0 @@ -#include -#include -#include - -#include "sha256avx.h" - -static const unsigned int RC[] = { - 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, - 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, - 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, - 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, - 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, - 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, - 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, - 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, - 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, - 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, - 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, - 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, - 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, - 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, - 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, - 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 -}; - -#define u32 uint32_t -#define u256 __m256i - -#define XOR _mm256_xor_si256 -#define OR _mm256_or_si256 -#define AND _mm256_and_si256 -#define ADD32 _mm256_add_epi32 -#define NOT(x) _mm256_xor_si256(x, _mm256_set_epi32(-1, -1, -1, -1, -1, -1, -1, -1)) - -#define LOAD(src) _mm256_loadu_si256((__m256i *)(src)) -#define STORE(dest,src) _mm256_storeu_si256((__m256i *)(dest),src) - -#define BYTESWAP(x) _mm256_shuffle_epi8(x, _mm256_set_epi8(0xc,0xd,0xe,0xf,0x8,0x9,0xa,0xb,0x4,0x5,0x6,0x7,0x0,0x1,0x2,0x3,0xc,0xd,0xe,0xf,0x8,0x9,0xa,0xb,0x4,0x5,0x6,0x7,0x0,0x1,0x2,0x3)) - -#define SHIFTR32(x, y) _mm256_srli_epi32(x, y) -#define SHIFTL32(x, y) _mm256_slli_epi32(x, y) - -#define ROTR32(x, y) OR(SHIFTR32(x, y), SHIFTL32(x, 32 - (y))) -#define ROTL32(x, y) OR(SHIFTL32(x, y), SHIFTR32(x, 32 - (y))) - -#define XOR3(a, b, c) XOR(XOR(a, b), c) - -#define ADD3_32(a, b, c) ADD32(ADD32(a, b), c) -#define ADD4_32(a, b, c, d) ADD32(ADD32(ADD32(a, b), c), d) -#define ADD5_32(a, b, c, d, e) ADD32(ADD32(ADD32(ADD32(a, b), c), d), e) - -#define MAJ_AVX(a, b, c) XOR3(AND(a, b), AND(a, c), AND(b, c)) -#define CH_AVX(a, b, c) XOR(AND(a, b), AND(NOT(a), c)) - -#define SIGMA1_AVX(x) XOR3(ROTR32(x, 6), ROTR32(x, 11), ROTR32(x, 25)) -#define SIGMA0_AVX(x) XOR3(ROTR32(x, 2), ROTR32(x, 13), ROTR32(x, 22)) - -#define WSIGMA1_AVX(x) XOR3(ROTR32(x, 17), ROTR32(x, 19), SHIFTR32(x, 10)) -#define WSIGMA0_AVX(x) XOR3(ROTR32(x, 7), ROTR32(x, 18), SHIFTR32(x, 3)) - -#define SHA256ROUND_AVX(a, b, c, d, e, f, g, h, rc, w) \ - T0 = ADD5_32(h, SIGMA1_AVX(e), CH_AVX(e, f, g), _mm256_set1_epi32((int)RC[rc]), w); \ - (d) = ADD32(d, T0); \ - T1 = ADD32(SIGMA0_AVX(a), MAJ_AVX(a, b, c)); \ - (h) = ADD32(T0, T1); - -// Transpose 8 vectors containing 32-bit values -static void transpose(u256 s[8]) { - u256 tmp0[8]; - u256 tmp1[8]; - tmp0[0] = _mm256_unpacklo_epi32(s[0], s[1]); - tmp0[1] = _mm256_unpackhi_epi32(s[0], s[1]); - tmp0[2] = _mm256_unpacklo_epi32(s[2], s[3]); - tmp0[3] = _mm256_unpackhi_epi32(s[2], s[3]); - tmp0[4] = _mm256_unpacklo_epi32(s[4], s[5]); - tmp0[5] = _mm256_unpackhi_epi32(s[4], s[5]); - tmp0[6] = _mm256_unpacklo_epi32(s[6], s[7]); - tmp0[7] = _mm256_unpackhi_epi32(s[6], s[7]); - tmp1[0] = _mm256_unpacklo_epi64(tmp0[0], tmp0[2]); - tmp1[1] = _mm256_unpackhi_epi64(tmp0[0], tmp0[2]); - tmp1[2] = _mm256_unpacklo_epi64(tmp0[1], tmp0[3]); - tmp1[3] = _mm256_unpackhi_epi64(tmp0[1], tmp0[3]); - tmp1[4] = _mm256_unpacklo_epi64(tmp0[4], tmp0[6]); - tmp1[5] = _mm256_unpackhi_epi64(tmp0[4], tmp0[6]); - tmp1[6] = _mm256_unpacklo_epi64(tmp0[5], tmp0[7]); - tmp1[7] = _mm256_unpackhi_epi64(tmp0[5], tmp0[7]); - s[0] = _mm256_permute2x128_si256(tmp1[0], tmp1[4], 0x20); - s[1] = _mm256_permute2x128_si256(tmp1[1], tmp1[5], 0x20); - s[2] = _mm256_permute2x128_si256(tmp1[2], tmp1[6], 0x20); - s[3] = _mm256_permute2x128_si256(tmp1[3], tmp1[7], 0x20); - s[4] = _mm256_permute2x128_si256(tmp1[0], tmp1[4], 0x31); - s[5] = _mm256_permute2x128_si256(tmp1[1], tmp1[5], 0x31); - s[6] = _mm256_permute2x128_si256(tmp1[2], tmp1[6], 0x31); - s[7] = _mm256_permute2x128_si256(tmp1[3], tmp1[7], 0x31); -} - -void sha256_ctx_clone8x(sha256x8ctx *out, const sha256x8ctx *in) { - memcpy(out, in, sizeof(sha256x8ctx)); -} - -void sha256_init8x(sha256x8ctx *ctx) { - ctx->s[0] = _mm256_set_epi32((int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667); - ctx->s[1] = _mm256_set_epi32((int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85); - ctx->s[2] = _mm256_set_epi32((int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372); - ctx->s[3] = _mm256_set_epi32((int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a); - ctx->s[4] = _mm256_set_epi32((int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f); - ctx->s[5] = _mm256_set_epi32((int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c); - ctx->s[6] = _mm256_set_epi32((int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab); - ctx->s[7] = _mm256_set_epi32((int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19); - - ctx->datalen = 0; - ctx->msglen = 0; -} - -void sha256_final8x(sha256x8ctx *ctx, - unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7) { - unsigned int i, curlen; - - // Padding - if (ctx->datalen < 56) { - for (i = 0; i < 8; ++i) { - curlen = ctx->datalen; - ctx->msgblocks[64 * i + curlen++] = 0x80; - while (curlen < 64) { - ctx->msgblocks[64 * i + curlen++] = 0x00; - } - } - } else { - for (i = 0; i < 8; ++i) { - curlen = ctx->datalen; - ctx->msgblocks[64 * i + curlen++] = 0x80; - while (curlen < 64) { - ctx->msgblocks[64 * i + curlen++] = 0x00; - } - } - sha256_transform8x(ctx, - &ctx->msgblocks[64 * 0], - &ctx->msgblocks[64 * 1], - &ctx->msgblocks[64 * 2], - &ctx->msgblocks[64 * 3], - &ctx->msgblocks[64 * 4], - &ctx->msgblocks[64 * 5], - &ctx->msgblocks[64 * 6], - &ctx->msgblocks[64 * 7] - ); - memset(ctx->msgblocks, 0, 8 * 64); - } - - // Add length of the message to each block - ctx->msglen += ctx->datalen * 8; - for (i = 0; i < 8; i++) { - ctx->msgblocks[64 * i + 63] = (unsigned char)(ctx->msglen); - ctx->msgblocks[64 * i + 62] = (unsigned char)(ctx->msglen >> 8); - ctx->msgblocks[64 * i + 61] = (unsigned char)(ctx->msglen >> 16); - ctx->msgblocks[64 * i + 60] = (unsigned char)(ctx->msglen >> 24); - ctx->msgblocks[64 * i + 59] = (unsigned char)(ctx->msglen >> 32); - ctx->msgblocks[64 * i + 58] = (unsigned char)(ctx->msglen >> 40); - ctx->msgblocks[64 * i + 57] = (unsigned char)(ctx->msglen >> 48); - ctx->msgblocks[64 * i + 56] = (unsigned char)(ctx->msglen >> 56); - } - sha256_transform8x(ctx, - &ctx->msgblocks[64 * 0], - &ctx->msgblocks[64 * 1], - &ctx->msgblocks[64 * 2], - &ctx->msgblocks[64 * 3], - &ctx->msgblocks[64 * 4], - &ctx->msgblocks[64 * 5], - &ctx->msgblocks[64 * 6], - &ctx->msgblocks[64 * 7] - ); - - // Compute final hash output - transpose(ctx->s); - - // Store Hash value - STORE(out0, BYTESWAP(ctx->s[0])); - STORE(out1, BYTESWAP(ctx->s[1])); - STORE(out2, BYTESWAP(ctx->s[2])); - STORE(out3, BYTESWAP(ctx->s[3])); - STORE(out4, BYTESWAP(ctx->s[4])); - STORE(out5, BYTESWAP(ctx->s[5])); - STORE(out6, BYTESWAP(ctx->s[6])); - STORE(out7, BYTESWAP(ctx->s[7])); -} - -void sha256_transform8x(sha256x8ctx *ctx, - const unsigned char *data0, - const unsigned char *data1, - const unsigned char *data2, - const unsigned char *data3, - const unsigned char *data4, - const unsigned char *data5, - const unsigned char *data6, - const unsigned char *data7) { - u256 s[8], w[64], T0, T1; - - // Load words and transform data correctly - w[0] = BYTESWAP(LOAD(data0)); - w[0 + 8] = BYTESWAP(LOAD(data0 + 32)); - w[1] = BYTESWAP(LOAD(data1)); - w[1 + 8] = BYTESWAP(LOAD(data1 + 32)); - w[2] = BYTESWAP(LOAD(data2)); - w[2 + 8] = BYTESWAP(LOAD(data2 + 32)); - w[3] = BYTESWAP(LOAD(data3)); - w[3 + 8] = BYTESWAP(LOAD(data3 + 32)); - w[4] = BYTESWAP(LOAD(data4)); - w[4 + 8] = BYTESWAP(LOAD(data4 + 32)); - w[5] = BYTESWAP(LOAD(data5)); - w[5 + 8] = BYTESWAP(LOAD(data5 + 32)); - w[6] = BYTESWAP(LOAD(data6)); - w[6 + 8] = BYTESWAP(LOAD(data6 + 32)); - w[7] = BYTESWAP(LOAD(data7)); - w[7 + 8] = BYTESWAP(LOAD(data7 + 32)); - - transpose(w); - transpose(w + 8); - - // Initial State - s[0] = ctx->s[0]; - s[1] = ctx->s[1]; - s[2] = ctx->s[2]; - s[3] = ctx->s[3]; - s[4] = ctx->s[4]; - s[5] = ctx->s[5]; - s[6] = ctx->s[6]; - s[7] = ctx->s[7]; - - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 0, w[0]); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 1, w[1]); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 2, w[2]); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 3, w[3]); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 4, w[4]); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 5, w[5]); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 6, w[6]); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 7, w[7]); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 8, w[8]); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 9, w[9]); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 10, w[10]); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 11, w[11]); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 12, w[12]); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 13, w[13]); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 14, w[14]); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 15, w[15]); - w[16] = ADD4_32(WSIGMA1_AVX(w[14]), w[0], w[9], WSIGMA0_AVX(w[1])); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 16, w[16]); - w[17] = ADD4_32(WSIGMA1_AVX(w[15]), w[1], w[10], WSIGMA0_AVX(w[2])); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 17, w[17]); - w[18] = ADD4_32(WSIGMA1_AVX(w[16]), w[2], w[11], WSIGMA0_AVX(w[3])); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 18, w[18]); - w[19] = ADD4_32(WSIGMA1_AVX(w[17]), w[3], w[12], WSIGMA0_AVX(w[4])); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 19, w[19]); - w[20] = ADD4_32(WSIGMA1_AVX(w[18]), w[4], w[13], WSIGMA0_AVX(w[5])); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 20, w[20]); - w[21] = ADD4_32(WSIGMA1_AVX(w[19]), w[5], w[14], WSIGMA0_AVX(w[6])); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 21, w[21]); - w[22] = ADD4_32(WSIGMA1_AVX(w[20]), w[6], w[15], WSIGMA0_AVX(w[7])); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 22, w[22]); - w[23] = ADD4_32(WSIGMA1_AVX(w[21]), w[7], w[16], WSIGMA0_AVX(w[8])); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 23, w[23]); - w[24] = ADD4_32(WSIGMA1_AVX(w[22]), w[8], w[17], WSIGMA0_AVX(w[9])); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 24, w[24]); - w[25] = ADD4_32(WSIGMA1_AVX(w[23]), w[9], w[18], WSIGMA0_AVX(w[10])); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 25, w[25]); - w[26] = ADD4_32(WSIGMA1_AVX(w[24]), w[10], w[19], WSIGMA0_AVX(w[11])); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 26, w[26]); - w[27] = ADD4_32(WSIGMA1_AVX(w[25]), w[11], w[20], WSIGMA0_AVX(w[12])); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 27, w[27]); - w[28] = ADD4_32(WSIGMA1_AVX(w[26]), w[12], w[21], WSIGMA0_AVX(w[13])); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 28, w[28]); - w[29] = ADD4_32(WSIGMA1_AVX(w[27]), w[13], w[22], WSIGMA0_AVX(w[14])); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 29, w[29]); - w[30] = ADD4_32(WSIGMA1_AVX(w[28]), w[14], w[23], WSIGMA0_AVX(w[15])); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 30, w[30]); - w[31] = ADD4_32(WSIGMA1_AVX(w[29]), w[15], w[24], WSIGMA0_AVX(w[16])); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 31, w[31]); - w[32] = ADD4_32(WSIGMA1_AVX(w[30]), w[16], w[25], WSIGMA0_AVX(w[17])); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 32, w[32]); - w[33] = ADD4_32(WSIGMA1_AVX(w[31]), w[17], w[26], WSIGMA0_AVX(w[18])); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 33, w[33]); - w[34] = ADD4_32(WSIGMA1_AVX(w[32]), w[18], w[27], WSIGMA0_AVX(w[19])); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 34, w[34]); - w[35] = ADD4_32(WSIGMA1_AVX(w[33]), w[19], w[28], WSIGMA0_AVX(w[20])); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 35, w[35]); - w[36] = ADD4_32(WSIGMA1_AVX(w[34]), w[20], w[29], WSIGMA0_AVX(w[21])); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 36, w[36]); - w[37] = ADD4_32(WSIGMA1_AVX(w[35]), w[21], w[30], WSIGMA0_AVX(w[22])); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 37, w[37]); - w[38] = ADD4_32(WSIGMA1_AVX(w[36]), w[22], w[31], WSIGMA0_AVX(w[23])); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 38, w[38]); - w[39] = ADD4_32(WSIGMA1_AVX(w[37]), w[23], w[32], WSIGMA0_AVX(w[24])); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 39, w[39]); - w[40] = ADD4_32(WSIGMA1_AVX(w[38]), w[24], w[33], WSIGMA0_AVX(w[25])); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 40, w[40]); - w[41] = ADD4_32(WSIGMA1_AVX(w[39]), w[25], w[34], WSIGMA0_AVX(w[26])); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 41, w[41]); - w[42] = ADD4_32(WSIGMA1_AVX(w[40]), w[26], w[35], WSIGMA0_AVX(w[27])); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 42, w[42]); - w[43] = ADD4_32(WSIGMA1_AVX(w[41]), w[27], w[36], WSIGMA0_AVX(w[28])); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 43, w[43]); - w[44] = ADD4_32(WSIGMA1_AVX(w[42]), w[28], w[37], WSIGMA0_AVX(w[29])); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 44, w[44]); - w[45] = ADD4_32(WSIGMA1_AVX(w[43]), w[29], w[38], WSIGMA0_AVX(w[30])); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 45, w[45]); - w[46] = ADD4_32(WSIGMA1_AVX(w[44]), w[30], w[39], WSIGMA0_AVX(w[31])); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 46, w[46]); - w[47] = ADD4_32(WSIGMA1_AVX(w[45]), w[31], w[40], WSIGMA0_AVX(w[32])); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 47, w[47]); - w[48] = ADD4_32(WSIGMA1_AVX(w[46]), w[32], w[41], WSIGMA0_AVX(w[33])); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 48, w[48]); - w[49] = ADD4_32(WSIGMA1_AVX(w[47]), w[33], w[42], WSIGMA0_AVX(w[34])); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 49, w[49]); - w[50] = ADD4_32(WSIGMA1_AVX(w[48]), w[34], w[43], WSIGMA0_AVX(w[35])); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 50, w[50]); - w[51] = ADD4_32(WSIGMA1_AVX(w[49]), w[35], w[44], WSIGMA0_AVX(w[36])); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 51, w[51]); - w[52] = ADD4_32(WSIGMA1_AVX(w[50]), w[36], w[45], WSIGMA0_AVX(w[37])); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 52, w[52]); - w[53] = ADD4_32(WSIGMA1_AVX(w[51]), w[37], w[46], WSIGMA0_AVX(w[38])); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 53, w[53]); - w[54] = ADD4_32(WSIGMA1_AVX(w[52]), w[38], w[47], WSIGMA0_AVX(w[39])); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 54, w[54]); - w[55] = ADD4_32(WSIGMA1_AVX(w[53]), w[39], w[48], WSIGMA0_AVX(w[40])); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 55, w[55]); - w[56] = ADD4_32(WSIGMA1_AVX(w[54]), w[40], w[49], WSIGMA0_AVX(w[41])); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 56, w[56]); - w[57] = ADD4_32(WSIGMA1_AVX(w[55]), w[41], w[50], WSIGMA0_AVX(w[42])); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 57, w[57]); - w[58] = ADD4_32(WSIGMA1_AVX(w[56]), w[42], w[51], WSIGMA0_AVX(w[43])); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 58, w[58]); - w[59] = ADD4_32(WSIGMA1_AVX(w[57]), w[43], w[52], WSIGMA0_AVX(w[44])); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 59, w[59]); - w[60] = ADD4_32(WSIGMA1_AVX(w[58]), w[44], w[53], WSIGMA0_AVX(w[45])); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 60, w[60]); - w[61] = ADD4_32(WSIGMA1_AVX(w[59]), w[45], w[54], WSIGMA0_AVX(w[46])); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 61, w[61]); - w[62] = ADD4_32(WSIGMA1_AVX(w[60]), w[46], w[55], WSIGMA0_AVX(w[47])); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 62, w[62]); - w[63] = ADD4_32(WSIGMA1_AVX(w[61]), w[47], w[56], WSIGMA0_AVX(w[48])); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 63, w[63]); - - // Feed Forward - ctx->s[0] = ADD32(s[0], ctx->s[0]); - ctx->s[1] = ADD32(s[1], ctx->s[1]); - ctx->s[2] = ADD32(s[2], ctx->s[2]); - ctx->s[3] = ADD32(s[3], ctx->s[3]); - ctx->s[4] = ADD32(s[4], ctx->s[4]); - ctx->s[5] = ADD32(s[5], ctx->s[5]); - ctx->s[6] = ADD32(s[6], ctx->s[6]); - ctx->s[7] = ADD32(s[7], ctx->s[7]); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/sha256avx.h b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/sha256avx.h deleted file mode 100644 index 1e3bcf889b..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/sha256avx.h +++ /dev/null @@ -1,44 +0,0 @@ -#ifndef SHA256AVX_H -#define SHA256AVX_H - -#include -#include - -#include "params.h" - -typedef struct SHA256state { - __m256i s[8]; - unsigned char msgblocks[8 * 64]; - unsigned int datalen; - unsigned long long msglen; -} sha256x8ctx; - -#define sha256_ctx_clone8x SPX_NAMESPACE(sha256_ctx_clone8x) -void sha256_ctx_clone8x(sha256x8ctx *out, const sha256x8ctx *in); - -#define sha256_init8x SPX_NAMESPACE(sha256_init8x) -void sha256_init8x(sha256x8ctx *ctx); - -#define sha256_final8x SPX_NAMESPACE(sha256_final8x) -void sha256_final8x(sha256x8ctx *ctx, - unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7); - -#define sha256_transform8x SPX_NAMESPACE(sha256_transform8x) -void sha256_transform8x(sha256x8ctx *ctx, - const unsigned char *data0, - const unsigned char *data1, - const unsigned char *data2, - const unsigned char *data3, - const unsigned char *data4, - const unsigned char *data5, - const unsigned char *data6, - const unsigned char *data7); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/sha256x8.c b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/sha256x8.c deleted file mode 100644 index d97750c09b..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/sha256x8.c +++ /dev/null @@ -1,185 +0,0 @@ -#include - -#include "sha256avx.h" -#include "sha256x8.h" -#include "utils.h" - -// Performs sha256x8 on an initialized (and perhaps seeded) state. -static void _sha256x8( - sha256x8ctx *ctx, - unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - const unsigned char *in4, - const unsigned char *in5, - const unsigned char *in6, - const unsigned char *in7, unsigned long long inlen) { - unsigned long long i = 0; - while (inlen - i >= 64) { - sha256_transform8x(ctx, - in0 + i, - in1 + i, - in2 + i, - in3 + i, - in4 + i, - in5 + i, - in6 + i, - in7 + i - ); - i += 64; - ctx->msglen += 512; - } - - size_t bytes_to_copy = (size_t)(inlen - i); - memcpy(&ctx->msgblocks[64 * 0], in0 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64 * 1], in1 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64 * 2], in2 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64 * 3], in3 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64 * 4], in4 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64 * 5], in5 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64 * 6], in6 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64 * 7], in7 + i, bytes_to_copy); - ctx->datalen = (unsigned int)bytes_to_copy; - - sha256_final8x(ctx, out0, out1, out2, out3, out4, out5, out6, out7); -} - -void sha256x8_seeded( - unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7, - const sha256x8ctx *seed, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - const unsigned char *in4, - const unsigned char *in5, - const unsigned char *in6, - const unsigned char *in7, unsigned long long inlen) { - - sha256x8ctx ctx; - sha256_ctx_clone8x(&ctx, seed); - - _sha256x8(&ctx, out0, out1, out2, out3, out4, out5, out6, out7, - in0, in1, in2, in3, in4, in5, in6, in7, inlen); -} - -/* This provides a wrapper around the internals of 8x parallel SHA256 */ -void sha256x8(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - const unsigned char *in4, - const unsigned char *in5, - const unsigned char *in6, - const unsigned char *in7, unsigned long long inlen) { - sha256x8ctx ctx; - sha256_init8x(&ctx); - - _sha256x8(&ctx, out0, out1, out2, out3, out4, out5, out6, out7, - in0, in1, in2, in3, in4, in5, in6, in7, inlen); -} - -/** - * Note that inlen should be sufficiently small that it still allows for - * an array to be allocated on the stack. Typically 'in' is merely a seed. - * Outputs outlen number of bytes - */ -void mgf1x8(unsigned char *outx8, unsigned long outlen, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - const unsigned char *in4, - const unsigned char *in5, - const unsigned char *in6, - const unsigned char *in7, - unsigned long inlen) { - PQCLEAN_VLA(unsigned char, inbufx8, 8 * (inlen + 4)); - unsigned char outbufx8[8 * SPX_SHA256_OUTPUT_BYTES]; - uint32_t i; - unsigned int j; - - memcpy(inbufx8 + 0 * (inlen + 4), in0, inlen); - memcpy(inbufx8 + 1 * (inlen + 4), in1, inlen); - memcpy(inbufx8 + 2 * (inlen + 4), in2, inlen); - memcpy(inbufx8 + 3 * (inlen + 4), in3, inlen); - memcpy(inbufx8 + 4 * (inlen + 4), in4, inlen); - memcpy(inbufx8 + 5 * (inlen + 4), in5, inlen); - memcpy(inbufx8 + 6 * (inlen + 4), in6, inlen); - memcpy(inbufx8 + 7 * (inlen + 4), in7, inlen); - - /* While we can fit in at least another full block of SHA256 output.. */ - for (i = 0; (i + 1)*SPX_SHA256_OUTPUT_BYTES <= outlen; i++) { - for (j = 0; j < 8; j++) { - u32_to_bytes(inbufx8 + inlen + j * (inlen + 4), i); - } - - sha256x8(outx8 + 0 * outlen, - outx8 + 1 * outlen, - outx8 + 2 * outlen, - outx8 + 3 * outlen, - outx8 + 4 * outlen, - outx8 + 5 * outlen, - outx8 + 6 * outlen, - outx8 + 7 * outlen, - inbufx8 + 0 * (inlen + 4), - inbufx8 + 1 * (inlen + 4), - inbufx8 + 2 * (inlen + 4), - inbufx8 + 3 * (inlen + 4), - inbufx8 + 4 * (inlen + 4), - inbufx8 + 5 * (inlen + 4), - inbufx8 + 6 * (inlen + 4), - inbufx8 + 7 * (inlen + 4), inlen + 4); - outx8 += SPX_SHA256_OUTPUT_BYTES; - } - /* Until we cannot anymore, and we fill the remainder. */ - for (j = 0; j < 8; j++) { - u32_to_bytes(inbufx8 + inlen + j * (inlen + 4), i); - } - sha256x8(outbufx8 + 0 * SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 1 * SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 2 * SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 3 * SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 4 * SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 5 * SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 6 * SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 7 * SPX_SHA256_OUTPUT_BYTES, - inbufx8 + 0 * (inlen + 4), - inbufx8 + 1 * (inlen + 4), - inbufx8 + 2 * (inlen + 4), - inbufx8 + 3 * (inlen + 4), - inbufx8 + 4 * (inlen + 4), - inbufx8 + 5 * (inlen + 4), - inbufx8 + 6 * (inlen + 4), - inbufx8 + 7 * (inlen + 4), inlen + 4); - - for (j = 0; j < 8; j++) { - memcpy(outx8 + j * outlen, - outbufx8 + j * SPX_SHA256_OUTPUT_BYTES, - outlen - i * SPX_SHA256_OUTPUT_BYTES); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/sha256x8.h b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/sha256x8.h deleted file mode 100644 index 4f7330a6c1..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/sha256x8.h +++ /dev/null @@ -1,64 +0,0 @@ -#ifndef SPX_SHA256X8_H -#define SPX_SHA256X8_H - -#include "params.h" -#include "sha256avx.h" - - - -#define sha256x8_seeded SPX_NAMESPACE(sha256x8_seeded) -void sha256x8_seeded( - unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7, - const sha256x8ctx *seed, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - const unsigned char *in4, - const unsigned char *in5, - const unsigned char *in6, - const unsigned char *in7, unsigned long long inlen); - -/* This provides a wrapper around the internals of 8x parallel SHA256 */ -#define sha256x8 SPX_NAMESPACE(sha256x8) -void sha256x8(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - const unsigned char *in4, - const unsigned char *in5, - const unsigned char *in6, - const unsigned char *in7, unsigned long long inlen); - -/** - * Note that inlen should be sufficiently small that it still allows for - * an array to be allocated on the stack. Typically 'in' is merely a seed. - * Outputs outlen number of bytes - */ -#define mgf1x8 SPX_NAMESPACE(mgf1x8) -void mgf1x8(unsigned char *outx8, unsigned long outlen, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - const unsigned char *in4, - const unsigned char *in5, - const unsigned char *in6, - const unsigned char *in7, - unsigned long inlen); -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/sha2_offsets.h b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/sha2_offsets.h deleted file mode 100644 index 6e3584f7a4..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/sha2_offsets.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef SHA2_OFFSETS_H_ -#define SHA2_OFFSETS_H_ - -#define SPX_SHA256_BLOCK_BYTES 64 -#define SPX_SHA256_OUTPUT_BYTES 32 - -#define SPX_SHA512_BLOCK_BYTES 128 -#define SPX_SHA512_OUTPUT_BYTES 64 - -/* - * Offsets of various fields in the address structure when we use SHA2 as - * the Sphincs+ hash function - */ - -#define SPX_OFFSET_LAYER 0 /* The byte used to specify the Merkle tree layer */ -#define SPX_OFFSET_TREE 1 /* The start of the 8 byte field used to specify the tree */ -#define SPX_OFFSET_TYPE 9 /* The byte used to specify the hash type (reason) */ -#define SPX_OFFSET_KP_ADDR2 12 /* The high byte used to specify the key pair (which one-time signature) */ -#define SPX_OFFSET_KP_ADDR1 13 /* The low byte used to specify the key pair */ -#define SPX_OFFSET_CHAIN_ADDR 17 /* The byte used to specify the chain address (which Winternitz chain) */ -#define SPX_OFFSET_HASH_ADDR 21 /* The byte used to specify the hash address (where in the Winternitz chain) */ -#define SPX_OFFSET_TREE_HGT 17 /* The byte used to specify the height of this node in the FORS or Merkle tree */ -#define SPX_OFFSET_TREE_INDEX 18 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ - -#define SPX_SHA2 1 - -#endif /* SHA2_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/sign.c b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/sign.c deleted file mode 100644 index 9d0c7d1b22..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/sign.c +++ /dev/null @@ -1,286 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "context.h" -#include "fors.h" -#include "hash.h" -#include "merkle.h" -#include "nistapi.h" -#include "params.h" -#include "randombytes.h" -#include "thash.h" -#include "utils.h" -#include "wots.h" - -/* - * Returns the length of a secret key, in bytes - */ -size_t crypto_sign_secretkeybytes(void) { - return CRYPTO_SECRETKEYBYTES; -} - -/* - * Returns the length of a public key, in bytes - */ -size_t crypto_sign_publickeybytes(void) { - return CRYPTO_PUBLICKEYBYTES; -} - -/* - * Returns the length of a signature, in bytes - */ -size_t crypto_sign_bytes(void) { - return CRYPTO_BYTES; -} - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t crypto_sign_seedbytes(void) { - return CRYPTO_SEEDBYTES; -} - -/* - * Generates an SPX key pair given a seed of length - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed) { - spx_ctx ctx; - - /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ - memcpy(sk, seed, CRYPTO_SEEDBYTES); - - memcpy(pk, sk + 2 * SPX_N, SPX_N); - - memcpy(ctx.pub_seed, pk, SPX_N); - memcpy(ctx.sk_seed, sk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - /* Compute root node of the top-most subtree. */ - merkle_gen_root(sk + 3 * SPX_N, &ctx); - - // cleanup - free_hash_function(&ctx); - - memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); - - return 0; -} - -/* - * Generates an SPX key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { - uint8_t seed[CRYPTO_SEEDBYTES]; - randombytes(seed, CRYPTO_SEEDBYTES); - crypto_sign_seed_keypair(pk, sk, seed); - - return 0; -} - -/** - * Returns an array containing a detached signature. - */ -int crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - spx_ctx ctx; - - const uint8_t *sk_prf = sk + SPX_N; - const uint8_t *pk = sk + 2 * SPX_N; - - uint8_t optrand[SPX_N]; - uint8_t mhash[SPX_FORS_MSG_BYTES]; - uint8_t root[SPX_N]; - uint32_t i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - - memcpy(ctx.sk_seed, sk, SPX_N); - memcpy(ctx.pub_seed, pk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - set_type(wots_addr, SPX_ADDR_TYPE_WOTS); - set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); - - /* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ - randombytes(optrand, SPX_N); - /* Compute the digest randomization value. */ - gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); - - /* Derive the message digest and leaf index from R, PK and M. */ - hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); - sig += SPX_N; - - set_tree_addr(wots_addr, tree); - set_keypair_addr(wots_addr, idx_leaf); - - /* Sign the message hash using FORS. */ - fors_sign(sig, root, mhash, &ctx, wots_addr); - sig += SPX_FORS_BYTES; - - for (i = 0; i < SPX_D; i++) { - set_layer_addr(tree_addr, i); - set_tree_addr(tree_addr, tree); - - copy_subtree_addr(wots_addr, tree_addr); - set_keypair_addr(wots_addr, idx_leaf); - - merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); - sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); - tree = tree >> SPX_TREE_HEIGHT; - } - - free_hash_function(&ctx); - - *siglen = SPX_BYTES; - - return 0; -} - -/** - * Verifies a detached signature and message under a given public key. - */ -int crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk) { - spx_ctx ctx; - const uint8_t *pub_root = pk + SPX_N; - uint8_t mhash[SPX_FORS_MSG_BYTES]; - uint8_t wots_pk[SPX_WOTS_BYTES]; - uint8_t root[SPX_N]; - uint8_t leaf[SPX_N]; - unsigned int i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - if (siglen != SPX_BYTES) { - return -1; - } - - memcpy(ctx.pub_seed, pk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - set_type(wots_addr, SPX_ADDR_TYPE_WOTS); - set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); - set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); - - /* Derive the message digest and leaf index from R || PK || M. */ - /* The additional SPX_N is a result of the hash domain separator. */ - hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); - sig += SPX_N; - - /* Layer correctly defaults to 0, so no need to set_layer_addr */ - set_tree_addr(wots_addr, tree); - set_keypair_addr(wots_addr, idx_leaf); - - fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); - sig += SPX_FORS_BYTES; - - /* For each subtree.. */ - for (i = 0; i < SPX_D; i++) { - set_layer_addr(tree_addr, i); - set_tree_addr(tree_addr, tree); - - copy_subtree_addr(wots_addr, tree_addr); - set_keypair_addr(wots_addr, idx_leaf); - - copy_keypair_addr(wots_pk_addr, wots_addr); - - /* The WOTS public key is only correct if the signature was correct. */ - /* Initially, root is the FORS pk, but on subsequent iterations it is - the root of the subtree below the currently processed subtree. */ - wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); - sig += SPX_WOTS_BYTES; - - /* Compute the leaf node using the WOTS public key. */ - thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); - - /* Compute the root node of this subtree. */ - compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, - &ctx, tree_addr); - sig += SPX_TREE_HEIGHT * SPX_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); - tree = tree >> SPX_TREE_HEIGHT; - } - - // cleanup - free_hash_function(&ctx); - - /* Check if the root node equals the root node in the public key. */ - if (memcmp(root, pub_root, SPX_N) != 0) { - return -1; - } - - return 0; -} - - -/** - * Returns an array containing the signature followed by the message. - */ -int crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk) { - size_t siglen; - - crypto_sign_signature(sm, &siglen, m, mlen, sk); - - memmove(sm + SPX_BYTES, m, mlen); - *smlen = siglen + mlen; - - return 0; -} - -/** - * Verifies a given signature-message pair under a given public key. - */ -int crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk) { - /* The API caller does not necessarily know what size a signature should be - but SPHINCS+ signatures are always exactly SPX_BYTES. */ - if (smlen < SPX_BYTES) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - *mlen = smlen - SPX_BYTES; - - if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - /* If verification was successful, move the message to the right place. */ - memmove(m, sm + SPX_BYTES, *mlen); - - return 0; -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/thash.h b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/thash.h deleted file mode 100644 index 8687ccfb4d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/thash.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef SPX_THASH_H -#define SPX_THASH_H - -#include "context.h" -#include "params.h" - -#include - -#define thash SPX_NAMESPACE(thash) -void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/thash_sha2_robust.c b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/thash_sha2_robust.c deleted file mode 100644 index 18f65c2e42..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/thash_sha2_robust.c +++ /dev/null @@ -1,39 +0,0 @@ -#include -#include - -#include "address.h" -#include "context.h" -#include "hash.h" -#include "params.h" -#include "sha2.h" -#include "thash.h" -#include "utils.h" - - -/** - * Takes an array of inblocks concatenated arrays of SPX_N bytes. - */ -void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]) { - unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES]; - PQCLEAN_VLA(uint8_t, bitmask, inblocks * SPX_N); - PQCLEAN_VLA(uint8_t, buf, SPX_N + SPX_SHA256_OUTPUT_BYTES + inblocks * SPX_N); - sha256ctx sha2_state; - unsigned int i; - - memcpy(buf, ctx->pub_seed, SPX_N); - memcpy(buf + SPX_N, addr, SPX_SHA256_ADDR_BYTES); - mgf1_256(bitmask, inblocks * SPX_N, buf, SPX_N + SPX_SHA256_ADDR_BYTES); - - /* Retrieve precomputed state containing pub_seed */ - sha256_inc_ctx_clone(&sha2_state, &ctx->state_seeded); - - for (i = 0; i < inblocks * SPX_N; i++) { - buf[SPX_N + SPX_SHA256_ADDR_BYTES + i] = in[i] ^ bitmask[i]; - } - - sha256_inc_finalize(outbuf, &sha2_state, buf + SPX_N, - SPX_SHA256_ADDR_BYTES + inblocks * SPX_N); - memcpy(out, outbuf, SPX_N); -} - diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/thash_sha2_robustx8.c b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/thash_sha2_robustx8.c deleted file mode 100644 index 09ae4e1265..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/thash_sha2_robustx8.c +++ /dev/null @@ -1,121 +0,0 @@ -#include -#include - -#include "thashx8.h" - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "sha2.h" -#include "sha256avx.h" -#include "sha256x8.h" -#include "utils.h" - - -/** - * 8-way parallel version of thash; takes 8x as much input and output - */ -void thashx8(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - const unsigned char *in4, - const unsigned char *in5, - const unsigned char *in6, - const unsigned char *in7, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addrx8[8 * 8]) { - PQCLEAN_VLA(unsigned char, bufx8, 8 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)); - unsigned char outbufx8[8 * SPX_SHA256_OUTPUT_BYTES]; - PQCLEAN_VLA(unsigned char, bitmaskx8, 8 * (inblocks * SPX_N)); - unsigned int i; - - for (i = 0; i < 8; i++) { - memcpy(bufx8 + i * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - ctx->pub_seed, SPX_N); - memcpy(bufx8 + SPX_N + - i * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - addrx8 + i * 8, SPX_SHA256_ADDR_BYTES); - } - - mgf1x8(bitmaskx8, inblocks * SPX_N, - bufx8 + 0 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + 1 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + 2 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + 3 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + 4 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + 5 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + 6 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + 7 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - SPX_N + SPX_SHA256_ADDR_BYTES); - - for (i = 0; i < inblocks * SPX_N; i++) { - bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + - 0 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = - in0[i] ^ bitmaskx8[i + 0 * (inblocks * SPX_N)]; - bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + - 1 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = - in1[i] ^ bitmaskx8[i + 1 * (inblocks * SPX_N)]; - bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + - 2 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = - in2[i] ^ bitmaskx8[i + 2 * (inblocks * SPX_N)]; - bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + - 3 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = - in3[i] ^ bitmaskx8[i + 3 * (inblocks * SPX_N)]; - bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + - 4 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = - in4[i] ^ bitmaskx8[i + 4 * (inblocks * SPX_N)]; - bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + - 5 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = - in5[i] ^ bitmaskx8[i + 5 * (inblocks * SPX_N)]; - bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + - 6 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = - in6[i] ^ bitmaskx8[i + 6 * (inblocks * SPX_N)]; - bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + - 7 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = - in7[i] ^ bitmaskx8[i + 7 * (inblocks * SPX_N)]; - } - - sha256x8_seeded( - /* out */ - outbufx8 + 0 * SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 1 * SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 2 * SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 3 * SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 4 * SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 5 * SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 6 * SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 7 * SPX_SHA256_OUTPUT_BYTES, - - /* seed */ - &ctx->statex8_seeded, - - /* in */ - bufx8 + SPX_N + 0 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + SPX_N + 1 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + SPX_N + 2 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + SPX_N + 3 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + SPX_N + 4 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + SPX_N + 5 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + SPX_N + 6 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + SPX_N + 7 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - SPX_SHA256_ADDR_BYTES + inblocks * SPX_N /* len */ - ); - - memcpy(out0, outbufx8 + 0 * SPX_SHA256_OUTPUT_BYTES, SPX_N); - memcpy(out1, outbufx8 + 1 * SPX_SHA256_OUTPUT_BYTES, SPX_N); - memcpy(out2, outbufx8 + 2 * SPX_SHA256_OUTPUT_BYTES, SPX_N); - memcpy(out3, outbufx8 + 3 * SPX_SHA256_OUTPUT_BYTES, SPX_N); - memcpy(out4, outbufx8 + 4 * SPX_SHA256_OUTPUT_BYTES, SPX_N); - memcpy(out5, outbufx8 + 5 * SPX_SHA256_OUTPUT_BYTES, SPX_N); - memcpy(out6, outbufx8 + 6 * SPX_SHA256_OUTPUT_BYTES, SPX_N); - memcpy(out7, outbufx8 + 7 * SPX_SHA256_OUTPUT_BYTES, SPX_N); -} - diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/thashx8.h b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/thashx8.h deleted file mode 100644 index c02fe9cf3e..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/thashx8.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef SPX_THASHX8_H -#define SPX_THASHX8_H - -#include - -#include "context.h" -#include "params.h" - -#define thashx8 SPX_NAMESPACE(thashx8) -void thashx8(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - const unsigned char *in4, - const unsigned char *in5, - const unsigned char *in6, - const unsigned char *in7, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addrx8[8 * 8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/utils.c b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/utils.c deleted file mode 100644 index 177b541fb9..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/utils.c +++ /dev/null @@ -1,148 +0,0 @@ -#include - -#include "utils.h" - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "thash.h" - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void ull_to_bytes(unsigned char *out, unsigned int outlen, - unsigned long long in) { - int i; - - /* Iterate over out in decreasing order, for big-endianness. */ - for (i = (signed int)outlen - 1; i >= 0; i--) { - out[i] = in & 0xff; - in = in >> 8; - } -} - -void u32_to_bytes(unsigned char *out, uint32_t in) { - out[0] = (unsigned char)(in >> 24); - out[1] = (unsigned char)(in >> 16); - out[2] = (unsigned char)(in >> 8); - out[3] = (unsigned char)in; -} - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { - unsigned long long retval = 0; - unsigned int i; - - for (i = 0; i < inlen; i++) { - retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); - } - return retval; -} - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void compute_root(unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const spx_ctx *ctx, uint32_t addr[8]) { - uint32_t i; - unsigned char buffer[2 * SPX_N]; - - /* If leaf_idx is odd (last bit = 1), current path element is a right child - and auth_path has to go left. Otherwise it is the other way around. */ - if (leaf_idx & 1) { - memcpy(buffer + SPX_N, leaf, SPX_N); - memcpy(buffer, auth_path, SPX_N); - } else { - memcpy(buffer, leaf, SPX_N); - memcpy(buffer + SPX_N, auth_path, SPX_N); - } - auth_path += SPX_N; - - for (i = 0; i < tree_height - 1; i++) { - leaf_idx >>= 1; - idx_offset >>= 1; - /* Set the address of the node we're creating. */ - set_tree_height(addr, i + 1); - set_tree_index(addr, leaf_idx + idx_offset); - - /* Pick the right or left neighbor, depending on parity of the node. */ - if (leaf_idx & 1) { - thash(buffer + SPX_N, buffer, 2, ctx, addr); - memcpy(buffer, auth_path, SPX_N); - } else { - thash(buffer, buffer, 2, ctx, addr); - memcpy(buffer + SPX_N, auth_path, SPX_N); - } - auth_path += SPX_N; - } - - /* The last iteration is exceptional; we do not copy an auth_path node. */ - leaf_idx >>= 1; - idx_offset >>= 1; - set_tree_height(addr, tree_height); - set_tree_index(addr, leaf_idx + idx_offset); - thash(root, buffer, 2, ctx, addr); -} - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const spx_ctx * /* ctx */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), - uint32_t tree_addr[8]) { - PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); - PQCLEAN_VLA(unsigned int, heights, tree_height + 1); - unsigned int offset = 0; - uint32_t idx; - uint32_t tree_idx; - - for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { - /* Add the next leaf node to the stack. */ - gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); - offset++; - heights[offset - 1] = 0; - - /* If this is a node we need for the auth path.. */ - if ((leaf_idx ^ 0x1) == idx) { - memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); - } - - /* While the top-most nodes are of equal height.. */ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { - /* Compute index of the new node, in the next layer. */ - tree_idx = (idx >> (heights[offset - 1] + 1)); - - /* Set the address of the node we're creating. */ - set_tree_height(tree_addr, heights[offset - 1] + 1); - set_tree_index(tree_addr, - tree_idx + (idx_offset >> (heights[offset - 1] + 1))); - /* Hash the top-most nodes from the stack together. */ - thash(stack + (offset - 2)*SPX_N, - stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); - offset--; - /* Note that the top-most node is now one layer higher. */ - heights[offset - 1]++; - - /* If this is a node we need for the auth path.. */ - if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_path + heights[offset - 1]*SPX_N, - stack + (offset - 1)*SPX_N, SPX_N); - } - } - } - memcpy(root, stack, SPX_N); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/utils.h b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/utils.h deleted file mode 100644 index 64f5d5a53a..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/utils.h +++ /dev/null @@ -1,58 +0,0 @@ -#ifndef SPX_UTILS_H -#define SPX_UTILS_H - -#include - -#include "compat.h" -#include "context.h" -#include "params.h" - - -/* To support MSVC use alloca() instead of VLAs. See #20. */ - - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) -void ull_to_bytes(unsigned char *out, unsigned int outlen, - unsigned long long in); -#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) -void u32_to_bytes(unsigned char *out, uint32_t in); - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) -unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -#define compute_root SPX_NAMESPACE(compute_root) -void compute_root(unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const spx_ctx *ctx, uint32_t addr[8]); - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -#define treehash SPX_NAMESPACE(treehash) -void treehash(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const spx_ctx *ctx /* ctx */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), - uint32_t tree_addr[8]); - - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/utilsx8.c b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/utilsx8.c deleted file mode 100644 index f044b9595d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/utilsx8.c +++ /dev/null @@ -1,146 +0,0 @@ -#include - -#include "utils.h" -#include "utilsx8.h" - -#include "address.h" -#include "params.h" -#include "thashx8.h" - -/* - * Generate the entire Merkle tree, computing the authentication path for leaf_idx, - * and the resulting root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) - * - * This expects tree_addrx8 to be initialized to 8 parallel addr structures for - * the Merkle tree nodes - * - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - * - * This works by using the standard Merkle tree building algorithm, except - * that each 'node' tracked is actually 8 consecutive nodes in the real tree. - * When we combine two logical nodes ABCDEFGH and STUVWXYZ, we perform the H - * operation on adjacent real nodes, forming the parent logical node - * (AB)(CD)(EF)(GH)(ST)(UV)(WX)(YZ) - * - * When we get to the top three levels of the real tree (where there is only - * one logical node), we continue this operation three more times; the right - * most real node will by the actual root (and the other 7 nodes will be - * garbage). We follow the same thashx8 logic so that the 'extract - * authentication path components' part of the loop is still executed (and - * to simplify the code somewhat) - * - * This currently assumes tree_height >= 3; I suspect that doing an adjusting - * idx, addr_idx on the gen_leafx8 call if tree_height < 3 would fix it; since - * we don't actually use such short trees, I haven't bothered - */ -void treehashx8(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, - uint32_t tree_height, - void (*gen_leafx8)( - unsigned char * /* Where to write the leaves */, - const spx_ctx *, - uint32_t idx, void *info), - uint32_t tree_addrx8[8 * 8], - void *info) { - /* This is where we keep the intermediate nodes */ - PQCLEAN_VLA(unsigned char, stackx8, tree_height * 8 * SPX_N); - uint32_t left_adj = 0, prev_left_adj = 0; /* When we're doing the top 3 */ - /* levels, the left-most part of the tree isn't at the beginning */ - /* of current[]. These give the offset of the actual start */ - - uint32_t idx; - uint32_t max_idx = ((uint32_t)1 << (tree_height - 3)) - 1; - for (idx = 0;; idx++) { - unsigned char current[8 * SPX_N]; /* Current logical node */ - gen_leafx8( current, ctx, 8 * idx + idx_offset, - info ); - - /* Now combine the freshly generated right node with previously */ - /* generated left ones */ - uint32_t internal_idx_offset = idx_offset; - uint32_t internal_idx = idx; - uint32_t internal_leaf = leaf_idx; - uint32_t h; /* The height we are in the Merkle tree */ - for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { - - /* Special processing if we're at the top of the tree */ - if (h >= tree_height - 3) { - if (h == tree_height) { - /* We hit the root; return it */ - memcpy( root, ¤t[7 * SPX_N], SPX_N ); - return; - } - /* The tree indexing logic is a bit off in this case */ - /* Adjust it so that the left-most node of the part of */ - /* the tree that we're processing has index 0 */ - prev_left_adj = left_adj; - left_adj = (uint32_t)(8 - (1 << (tree_height - h - 1))); - } - - /* Check if we hit the top of the tree */ - if (h == tree_height) { - /* We hit the root; return it */ - memcpy( root, ¤t[7 * SPX_N], SPX_N ); - return; - } - - /* - * Check if one of the nodes we have is a part of the - * authentication path; if it is, write it out - */ - if ((((internal_idx << 3) ^ internal_leaf) & ~0x7U) == 0) { - memcpy( &auth_path[ h * SPX_N ], - ¤t[(((internal_leaf & 7) ^ 1) + prev_left_adj) * SPX_N], - SPX_N ); - } - - /* - * Check if we're at a left child; if so, stop going up the stack - * Exception: if we've reached the end of the tree, keep on going - * (so we combine the last 8 nodes into the one root node in three - * more iterations) - */ - if ((internal_idx & 1) == 0 && idx < max_idx) { - break; - } - - /* Ok, we're at a right node (or doing the top 3 levels) */ - /* Now combine the left and right logical nodes together */ - - /* Set the address of the node we're creating. */ - uint32_t j; - internal_idx_offset >>= 1; - for (j = 0; j < 8; j++) { - set_tree_height(tree_addrx8 + j * 8, h + 1); - set_tree_index(tree_addrx8 + j * 8, - (8 / 2) * (internal_idx & ~1U) + j - left_adj + internal_idx_offset ); - } - unsigned char *left = &stackx8[h * 8 * SPX_N]; - thashx8( ¤t[0 * SPX_N], - ¤t[1 * SPX_N], - ¤t[2 * SPX_N], - ¤t[3 * SPX_N], - ¤t[4 * SPX_N], - ¤t[5 * SPX_N], - ¤t[6 * SPX_N], - ¤t[7 * SPX_N], - &left [0 * SPX_N], - &left [2 * SPX_N], - &left [4 * SPX_N], - &left [6 * SPX_N], - ¤t[0 * SPX_N], - ¤t[2 * SPX_N], - ¤t[4 * SPX_N], - ¤t[6 * SPX_N], - 2, ctx, tree_addrx8); - } - - /* We've hit a left child; save the current for when we get the */ - /* corresponding right right */ - memcpy( &stackx8[h * 8 * SPX_N], current, 8 * SPX_N); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/utilsx8.h b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/utilsx8.h deleted file mode 100644 index 806d1e85be..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/utilsx8.h +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef SPX_UTILSX8_H -#define SPX_UTILSX8_H - -#include - -#include "params.h" - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - * - * This implementation uses AVX to compute internal nodes 8 at a time (in - * parallel) - */ -#define treehashx8 SPX_NAMESPACE(treehashx8) -void treehashx8(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leafx8)( - unsigned char * /* Where to write the leaves */, - const spx_ctx * /* ctx */, - uint32_t addr_idx, void *info), - uint32_t tree_addrx8[8 * 8], void *info); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/wots.c b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/wots.c deleted file mode 100644 index 689baf4db9..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/wots.c +++ /dev/null @@ -1,291 +0,0 @@ -#include -#include - -#include "wots.h" - -#include "address.h" -#include "hash.h" -#include "hashx8.h" -#include "params.h" -#include "thash.h" -#include "thashx8.h" -#include "utils.h" -#include "utilsx8.h" -#include "wotsx8.h" - -// TODO clarify address expectations, and make them more uniform. -// TODO i.e. do we expect types to be set already? -// TODO and do we expect modifications or copies? - -/** - * Computes up the chains - */ -static void gen_chains( - unsigned char *out, - const unsigned char *in, - unsigned int start[SPX_WOTS_LEN], - const unsigned int steps[SPX_WOTS_LEN], - const spx_ctx *ctx, - uint32_t addr[8]) { - uint32_t i, j, k, idx, watching; - int done; - unsigned char empty[SPX_N]; - unsigned char *bufs[8]; - uint32_t addrs[8 * 8]; - - int l; - uint16_t counts[SPX_WOTS_W] = { 0 }; - uint16_t idxs[SPX_WOTS_LEN]; - uint16_t total, newTotal; - - /* set addrs = {addr, addr, ..., addr} */ - for (j = 0; j < 8; j++) { - memcpy(addrs + j * 8, addr, sizeof(uint32_t) * 8); - } - - /* Initialize out with the value at position 'start'. */ - memcpy(out, in, SPX_WOTS_LEN * SPX_N); - - /* Sort the chains in reverse order by steps using counting sort. */ - for (i = 0; i < SPX_WOTS_LEN; i++) { - counts[steps[i]]++; - } - total = 0; - for (l = SPX_WOTS_W - 1; l >= 0; l--) { - newTotal = counts[l] + total; - counts[l] = total; - total = newTotal; - } - for (i = 0; i < SPX_WOTS_LEN; i++) { - idxs[counts[steps[i]]] = (uint16_t)i; - counts[steps[i]]++; - } - - /* We got our work cut out for us: do it! */ - for (i = 0; i < SPX_WOTS_LEN; i += 8) { - for (j = 0; j < 8 && i + j < SPX_WOTS_LEN; j++) { - idx = idxs[i + j]; - set_chain_addr(addrs + j * 8, idx); - bufs[j] = out + SPX_N * idx; - } - - /* As the chains are sorted in reverse order, we know that the first - * chain is the longest and the last one is the shortest. We keep - * an eye on whether the last chain is done and then on the one before, - * et cetera. */ - watching = 7; - done = 0; - while (i + watching >= SPX_WOTS_LEN) { - bufs[watching] = &empty[0]; - watching--; - } - - for (k = 0;; k++) { - while (k == steps[idxs[i + watching]]) { - bufs[watching] = &empty[0]; - if (watching == 0) { - done = 1; - break; - } - watching--; - } - if (done) { - break; - } - for (j = 0; j < watching + 1; j++) { - set_hash_addr(addrs + j * 8, k + start[idxs[i + j]]); - } - - thashx8(bufs[0], bufs[1], bufs[2], bufs[3], - bufs[4], bufs[5], bufs[6], bufs[7], - bufs[0], bufs[1], bufs[2], bufs[3], - bufs[4], bufs[5], bufs[6], bufs[7], 1, ctx, addrs); - } - } -} - -/** - * base_w algorithm as described in draft. - * Interprets an array of bytes as integers in base w. - * This only works when log_w is a divisor of 8. - */ -static void base_w(unsigned int *output, const int out_len, - const unsigned char *input) { - int in = 0; - int out = 0; - unsigned char total = 0; - int bits = 0; - int consumed; - - for (consumed = 0; consumed < out_len; consumed++) { - if (bits == 0) { - total = input[in]; - in++; - bits += 8; - } - bits -= SPX_WOTS_LOGW; - output[out] = (total >> bits) & (SPX_WOTS_W - 1); - out++; - } -} - -/* Computes the WOTS+ checksum over a message (in base_w). */ -static void wots_checksum(unsigned int *csum_base_w, - const unsigned int *msg_base_w) { - unsigned int csum = 0; - unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; - unsigned int i; - - /* Compute checksum. */ - for (i = 0; i < SPX_WOTS_LEN1; i++) { - csum += SPX_WOTS_W - 1 - msg_base_w[i]; - } - - /* Convert checksum to base_w. */ - /* Make sure expected empty zero bits are the least significant bits. */ - csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); - ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); - base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); -} - -/* Takes a message and derives the matching chain lengths. */ -void chain_lengths(unsigned int *lengths, const unsigned char *msg) { - base_w(lengths, SPX_WOTS_LEN1, msg); - wots_checksum(lengths + SPX_WOTS_LEN1, lengths); -} - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const spx_ctx *ctx, uint32_t addr[8]) { - unsigned int steps[SPX_WOTS_LEN]; - unsigned int start[SPX_WOTS_LEN]; - uint32_t i; - - chain_lengths(start, msg); - - for (i = 0; i < SPX_WOTS_LEN; i++) { - steps[i] = SPX_WOTS_W - 1 - start[i]; - } - - gen_chains(pk, sig, start, steps, ctx, addr); -} - -/* - * This generates 8 sequential WOTS public keys - * It also generates the WOTS signature if leaf_info indicates - * that we're signing with one of these WOTS keys - */ -void wots_gen_leafx8(unsigned char *dest, - const spx_ctx *ctx, - uint32_t leaf_idx, void *v_info) { - struct leaf_info_x8 *info = v_info; - uint32_t *leaf_addr = info->leaf_addr; - uint32_t *pk_addr = info->pk_addr; - unsigned int i, j, k; - unsigned char pk_buffer[ 8 * SPX_WOTS_BYTES ]; - unsigned wots_offset = SPX_WOTS_BYTES; - unsigned char *buffer; - uint32_t wots_k_mask; - unsigned wots_sign_index; - - if (((leaf_idx ^ info->wots_sign_leaf) & ~7U) == 0) { - /* We're traversing the leaf that's signing; generate the WOTS */ - /* signature */ - wots_k_mask = 0; - wots_sign_index = info->wots_sign_leaf & 7; /* Which of of the 8 */ - /* slots do the signatures come from */ - } else { - /* Nope, we're just generating pk's; turn off the signature logic */ - wots_k_mask = ~0U; - wots_sign_index = 0; - } - - for (j = 0; j < 8; j++) { - set_keypair_addr( leaf_addr + j * 8, leaf_idx + j ); - set_keypair_addr( pk_addr + j * 8, leaf_idx + j ); - } - - for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { - uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k */ - /* to the step if we're generating a signature, ~0 if we're not */ - - /* Start with the secret seed */ - for (j = 0; j < 8; j++) { - set_chain_addr(leaf_addr + j * 8, i); - set_hash_addr(leaf_addr + j * 8, 0); - set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTSPRF); - } - prf_addrx8(buffer + 0 * wots_offset, - buffer + 1 * wots_offset, - buffer + 2 * wots_offset, - buffer + 3 * wots_offset, - buffer + 4 * wots_offset, - buffer + 5 * wots_offset, - buffer + 6 * wots_offset, - buffer + 7 * wots_offset, - ctx, leaf_addr); - - for (j = 0; j < 8; j++) { - set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTS); - } - - /* Iterate down the WOTS chain */ - for (k = 0;; k++) { - /* Check if one of the values we have needs to be saved as a */ - /* part of the WOTS signature */ - if (k == wots_k) { - memcpy( info->wots_sig + i * SPX_N, - buffer + wots_sign_index * wots_offset, SPX_N ); - } - - /* Check if we hit the top of the chain */ - if (k == SPX_WOTS_W - 1) { - break; - } - - /* Iterate one step on all 8 chains */ - for (j = 0; j < 8; j++) { - set_hash_addr(leaf_addr + j * 8, k); - } - thashx8(buffer + 0 * wots_offset, - buffer + 1 * wots_offset, - buffer + 2 * wots_offset, - buffer + 3 * wots_offset, - buffer + 4 * wots_offset, - buffer + 5 * wots_offset, - buffer + 6 * wots_offset, - buffer + 7 * wots_offset, - buffer + 0 * wots_offset, - buffer + 1 * wots_offset, - buffer + 2 * wots_offset, - buffer + 3 * wots_offset, - buffer + 4 * wots_offset, - buffer + 5 * wots_offset, - buffer + 6 * wots_offset, - buffer + 7 * wots_offset, 1, ctx, leaf_addr); - } - } - - /* Do the final thash to generate the public keys */ - thashx8(dest + 0 * SPX_N, - dest + 1 * SPX_N, - dest + 2 * SPX_N, - dest + 3 * SPX_N, - dest + 4 * SPX_N, - dest + 5 * SPX_N, - dest + 6 * SPX_N, - dest + 7 * SPX_N, - pk_buffer + 0 * wots_offset, - pk_buffer + 1 * wots_offset, - pk_buffer + 2 * wots_offset, - pk_buffer + 3 * wots_offset, - pk_buffer + 4 * wots_offset, - pk_buffer + 5 * wots_offset, - pk_buffer + 6 * wots_offset, - pk_buffer + 7 * wots_offset, SPX_WOTS_LEN, ctx, pk_addr); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/wots.h b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/wots.h deleted file mode 100644 index 4e7692eeef..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/wots.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef SPX_WOTS_H -#define SPX_WOTS_H - -#include - -#include "context.h" -#include "params.h" - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) -void wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const spx_ctx *ctx, uint32_t addr[8]); - -/* - * Compute the chain lengths needed for a given message hash - */ -#define chain_lengths SPX_NAMESPACE(chain_lengths) -void chain_lengths(unsigned int *lengths, const unsigned char *msg); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/wotsx8.h b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/wotsx8.h deleted file mode 100644 index 10866efb35..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_avx2/wotsx8.h +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef WOTSX8_H_ -#define WOTSX8_H_ - -#include - -#include "context.h" -#include "params.h" - -/* - * This is here to provide an interface to the internal wots_gen_leafx8 - * routine. While this routine is not referenced in the package outside of - * wots.c, it is called from the stand-alone benchmark code to characterize - * the performance - */ -struct leaf_info_x8 { - unsigned char *wots_sig; - uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ - uint32_t *wots_steps; - uint32_t leaf_addr[8 * 8]; - uint32_t pk_addr[8 * 8]; -}; - -/* Macro to set the leaf_info to something 'benign', that is, it would */ -/* run with the same time as it does during the real signing process */ -/* Used only by the benchmark code */ -#define INITIALIZE_LEAF_INFO_X8(info, addr, step_buffer) { \ - (info).wots_sig = 0; \ - (info).wots_sign_leaf = ~0; \ - (info).wots_steps = step_buffer; \ - int i; \ - for (i=0; i<8; i++) { \ - memcpy( &(info).leaf_addr[8*i], addr, 32 ); \ - memcpy( &(info).pk_addr[8*i], addr, 32 ); \ - } \ - } - -#define wots_gen_leafx8 SPX_NAMESPACE(wots_gen_leafx8) -void wots_gen_leafx8(unsigned char *dest, - const spx_ctx *ctx, - uint32_t leaf_idx, void *v_info); - -#endif /* WOTSX8_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/LICENSE b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/LICENSE deleted file mode 100644 index 670154e353..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/LICENSE +++ /dev/null @@ -1,116 +0,0 @@ -CC0 1.0 Universal - -Statement of Purpose - -The laws of most jurisdictions throughout the world automatically confer -exclusive Copyright and Related Rights (defined below) upon the creator and -subsequent owner(s) (each and all, an "owner") of an original work of -authorship and/or a database (each, a "Work"). - -Certain owners wish to permanently relinquish those rights to a Work for the -purpose of contributing to a commons of creative, cultural and scientific -works ("Commons") that the public can reliably and without fear of later -claims of infringement build upon, modify, incorporate in other works, reuse -and redistribute as freely as possible in any form whatsoever and for any -purposes, including without limitation commercial purposes. These owners may -contribute to the Commons to promote the ideal of a free culture and the -further production of creative, cultural and scientific works, or to gain -reputation or greater distribution for their Work in part through the use and -efforts of others. - -For these and/or other purposes and motivations, and without any expectation -of additional consideration or compensation, the person associating CC0 with a -Work (the "Affirmer"), to the extent that he or she is an owner of Copyright -and Related Rights in the Work, voluntarily elects to apply CC0 to the Work -and publicly distribute the Work under its terms, with knowledge of his or her -Copyright and Related Rights in the Work and the meaning and intended legal -effect of CC0 on those rights. - -1. Copyright and Related Rights. A Work made available under CC0 may be -protected by copyright and related or neighboring rights ("Copyright and -Related Rights"). Copyright and Related Rights include, but are not limited -to, the following: - - i. the right to reproduce, adapt, distribute, perform, display, communicate, - and translate a Work; - - ii. moral rights retained by the original author(s) and/or performer(s); - - iii. publicity and privacy rights pertaining to a person's image or likeness - depicted in a Work; - - iv. rights protecting against unfair competition in regards to a Work, - subject to the limitations in paragraph 4(a), below; - - v. rights protecting the extraction, dissemination, use and reuse of data in - a Work; - - vi. database rights (such as those arising under Directive 96/9/EC of the - European Parliament and of the Council of 11 March 1996 on the legal - protection of databases, and under any national implementation thereof, - including any amended or successor version of such directive); and - - vii. other similar, equivalent or corresponding rights throughout the world - based on applicable law or treaty, and any national implementations thereof. - -2. Waiver. To the greatest extent permitted by, but not in contravention of, -applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and -unconditionally waives, abandons, and surrenders all of Affirmer's Copyright -and Related Rights and associated claims and causes of action, whether now -known or unknown (including existing as well as future claims and causes of -action), in the Work (i) in all territories worldwide, (ii) for the maximum -duration provided by applicable law or treaty (including future time -extensions), (iii) in any current or future medium and for any number of -copies, and (iv) for any purpose whatsoever, including without limitation -commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes -the Waiver for the benefit of each member of the public at large and to the -detriment of Affirmer's heirs and successors, fully intending that such Waiver -shall not be subject to revocation, rescission, cancellation, termination, or -any other legal or equitable action to disrupt the quiet enjoyment of the Work -by the public as contemplated by Affirmer's express Statement of Purpose. - -3. Public License Fallback. Should any part of the Waiver for any reason be -judged legally invalid or ineffective under applicable law, then the Waiver -shall be preserved to the maximum extent permitted taking into account -Affirmer's express Statement of Purpose. In addition, to the extent the Waiver -is so judged Affirmer hereby grants to each affected person a royalty-free, -non transferable, non sublicensable, non exclusive, irrevocable and -unconditional license to exercise Affirmer's Copyright and Related Rights in -the Work (i) in all territories worldwide, (ii) for the maximum duration -provided by applicable law or treaty (including future time extensions), (iii) -in any current or future medium and for any number of copies, and (iv) for any -purpose whatsoever, including without limitation commercial, advertising or -promotional purposes (the "License"). The License shall be deemed effective as -of the date CC0 was applied by Affirmer to the Work. Should any part of the -License for any reason be judged legally invalid or ineffective under -applicable law, such partial invalidity or ineffectiveness shall not -invalidate the remainder of the License, and in such case Affirmer hereby -affirms that he or she will not (i) exercise any of his or her remaining -Copyright and Related Rights in the Work or (ii) assert any associated claims -and causes of action with respect to the Work, in either case contrary to -Affirmer's express Statement of Purpose. - -4. Limitations and Disclaimers. - - a. No trademark or patent rights held by Affirmer are waived, abandoned, - surrendered, licensed or otherwise affected by this document. - - b. Affirmer offers the Work as-is and makes no representations or warranties - of any kind concerning the Work, express, implied, statutory or otherwise, - including without limitation warranties of title, merchantability, fitness - for a particular purpose, non infringement, or the absence of latent or - other defects, accuracy, or the present or absence of errors, whether or not - discoverable, all to the greatest extent permissible under applicable law. - - c. Affirmer disclaims responsibility for clearing rights of other persons - that may apply to the Work or any use thereof, including without limitation - any person's Copyright and Related Rights in the Work. Further, Affirmer - disclaims responsibility for obtaining any necessary consents, permissions - or other rights required for any use of the Work. - - d. Affirmer understands and acknowledges that Creative Commons is not a - party to this document and has no duty or obligation with respect to this - CC0 or use of the Work. - -For more information, please see - diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/address.c b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/address.c deleted file mode 100644 index d49d9f3b6b..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/address.c +++ /dev/null @@ -1,95 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "utils.h" - -/* - * Specify which level of Merkle tree (the "layer") we're working on - */ -void set_layer_addr(uint32_t addr[8], uint32_t layer) { - ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; -} - -/* - * Specify which Merkle tree within the level (the "tree address") we're working on - */ -void set_tree_addr(uint32_t addr[8], uint64_t tree) { - ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); -} - -/* - * Specify the reason we'll use this address structure for, that is, what - * hash will we compute with it. This is used so that unrelated types of - * hashes don't accidentally get the same address structure. The type will be - * one of the SPX_ADDR_TYPE constants - */ -void set_type(uint32_t addr[8], uint32_t type) { - ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; -} - -/* - * Copy the layer and tree fields of the address structure. This is used - * when we're doing multiple types of hashes within the same Merkle tree - */ -void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { - memcpy( out, in, SPX_OFFSET_TREE + 8 ); -} - -/* These functions are used for OTS addresses. */ - -/* - * Specify which Merkle leaf we're working on; that is, which OTS keypair - * we're talking about. - */ -void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { - /* We have > 256 OTS at the bottom of the Merkle tree; to specify */ - /* which one, we'd need to express it in two bytes */ - ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR2] = (unsigned char)(keypair >> 8); - ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; -} - -/* - * Copy the layer, tree and keypair fields of the address structure. This is - * used when we're doing multiple things within the same OTS keypair - */ -void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { - memcpy( out, in, SPX_OFFSET_TREE + 8 ); - ((unsigned char *)out)[SPX_OFFSET_KP_ADDR2] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR2]; - ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; -} - -/* - * Specify which Merkle chain within the OTS we're working with - * (the chain address) - */ -void set_chain_addr(uint32_t addr[8], uint32_t chain) { - ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; -} - -/* - * Specify where in the Merkle chain we are -* (the hash address) - */ -void set_hash_addr(uint32_t addr[8], uint32_t hash) { - ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; -} - -/* These functions are used for all hash tree addresses (including FORS). */ - -/* - * Specify the height of the node in the Merkle/FORS tree we are in - * (the tree height) - */ -void set_tree_height(uint32_t addr[8], uint32_t tree_height) { - ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; -} - -/* - * Specify the distance from the left edge of the node in the Merkle/FORS tree - * (the tree index) - */ -void set_tree_index(uint32_t addr[8], uint32_t tree_index) { - u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/address.h b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/address.h deleted file mode 100644 index 24a84eb40c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/address.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef SPX_ADDRESS_H -#define SPX_ADDRESS_H - -#include - -#include "params.h" - -/* The hash types that are passed to set_type */ -#define SPX_ADDR_TYPE_WOTS 0 -#define SPX_ADDR_TYPE_WOTSPK 1 -#define SPX_ADDR_TYPE_HASHTREE 2 -#define SPX_ADDR_TYPE_FORSTREE 3 -#define SPX_ADDR_TYPE_FORSPK 4 -#define SPX_ADDR_TYPE_WOTSPRF 5 -#define SPX_ADDR_TYPE_FORSPRF 6 - -#define set_layer_addr SPX_NAMESPACE(set_layer_addr) -void set_layer_addr(uint32_t addr[8], uint32_t layer); - -#define set_tree_addr SPX_NAMESPACE(set_tree_addr) -void set_tree_addr(uint32_t addr[8], uint64_t tree); - -#define set_type SPX_NAMESPACE(set_type) -void set_type(uint32_t addr[8], uint32_t type); - -/* Copies the layer and tree part of one address into the other */ -#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) -void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for WOTS and FORS addresses. */ - -#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) -void set_keypair_addr(uint32_t addr[8], uint32_t keypair); - -#define set_chain_addr SPX_NAMESPACE(set_chain_addr) -void set_chain_addr(uint32_t addr[8], uint32_t chain); - -#define set_hash_addr SPX_NAMESPACE(set_hash_addr) -void set_hash_addr(uint32_t addr[8], uint32_t hash); - -#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) -void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for all hash tree addresses (including FORS). */ - -#define set_tree_height SPX_NAMESPACE(set_tree_height) -void set_tree_height(uint32_t addr[8], uint32_t tree_height); - -#define set_tree_index SPX_NAMESPACE(set_tree_index) -void set_tree_index(uint32_t addr[8], uint32_t tree_index); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/api.h b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/api.h deleted file mode 100644 index 1c0a4f8659..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/api.h +++ /dev/null @@ -1,77 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA2128SROBUST_CLEAN_API_H -#define PQCLEAN_SPHINCSSHA2128SROBUST_CLEAN_API_H - -#include -#include - -#define PQCLEAN_SPHINCSSHA2128SROBUST_CLEAN_CRYPTO_ALGNAME "SPHINCS+-sha2-128s-robust" - -#define PQCLEAN_SPHINCSSHA2128SROBUST_CLEAN_CRYPTO_SECRETKEYBYTES 64 -#define PQCLEAN_SPHINCSSHA2128SROBUST_CLEAN_CRYPTO_PUBLICKEYBYTES 32 -#define PQCLEAN_SPHINCSSHA2128SROBUST_CLEAN_CRYPTO_BYTES 7856 - -#define PQCLEAN_SPHINCSSHA2128SROBUST_CLEAN_CRYPTO_SEEDBYTES 48 - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSSHA2128SROBUST_CLEAN_crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSSHA2128SROBUST_CLEAN_crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSSHA2128SROBUST_CLEAN_crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSSHA2128SROBUST_CLEAN_crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHA2128SROBUST_CLEAN_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHA2128SROBUST_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSSHA2128SROBUST_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSSHA2128SROBUST_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, - const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSSHA2128SROBUST_CLEAN_crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSSHA2128SROBUST_CLEAN_crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk); -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/context.h b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/context.h deleted file mode 100644 index 27effb3e10..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/context.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef SPX_CONTEXT_H -#define SPX_CONTEXT_H - -#include -#include - -#include "params.h" -#include "sha2.h" - -typedef struct { - uint8_t pub_seed[SPX_N]; - uint8_t sk_seed[SPX_N]; - - // sha256 state that absorbed pub_seed - sha256ctx state_seeded; - - -} spx_ctx; - -#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) -void initialize_hash_function(spx_ctx *ctx); - -#define free_hash_function SPX_NAMESPACE(free_hash_function) -void free_hash_function(spx_ctx *ctx); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/context_sha2.c b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/context_sha2.c deleted file mode 100644 index 64f7e65465..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/context_sha2.c +++ /dev/null @@ -1,33 +0,0 @@ -#include "context.h" - -/** - * Absorb the constant pub_seed using one round of the compression function - * This initializes state_seeded and state_seeded_512, which can then be - * reused in thash - **/ -static void seed_state(spx_ctx *ctx) { - uint8_t block[SPX_SHA512_BLOCK_BYTES]; - size_t i; - - for (i = 0; i < SPX_N; ++i) { - block[i] = ctx->pub_seed[i]; - } - for (i = SPX_N; i < SPX_SHA512_BLOCK_BYTES; ++i) { - block[i] = 0; - } - /* block has been properly initialized for both SHA-256 and SHA-512 */ - - sha256_inc_init(&ctx->state_seeded); - sha256_inc_blocks(&ctx->state_seeded, block, 1); -} - - -/* We initialize the state for the hash functions */ -void initialize_hash_function(spx_ctx *ctx) { - seed_state(ctx); -} - -/* Free the incremental hashing context for heap-based SHA2 APIs */ -void free_hash_function(spx_ctx *ctx) { - sha256_inc_ctx_release(&ctx->state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/fors.c b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/fors.c deleted file mode 100644 index 96ca72e986..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/fors.c +++ /dev/null @@ -1,156 +0,0 @@ -#include -#include -#include - -#include "fors.h" - -#include "address.h" -#include "hash.h" -#include "thash.h" -#include "utils.h" -#include "utilsx1.h" - -static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, - uint32_t fors_leaf_addr[8]) { - prf_addr(sk, ctx, fors_leaf_addr); -} - -static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, - const spx_ctx *ctx, - uint32_t fors_leaf_addr[8]) { - thash(leaf, sk, 1, ctx, fors_leaf_addr); -} - -struct fors_gen_leaf_info { - uint32_t leaf_addrx[8]; -}; - -static void fors_gen_leafx1(unsigned char *leaf, - const spx_ctx *ctx, - uint32_t addr_idx, void *info) { - struct fors_gen_leaf_info *fors_info = info; - uint32_t *fors_leaf_addr = fors_info->leaf_addrx; - - /* Only set the parts that the caller doesn't set */ - set_tree_index(fors_leaf_addr, addr_idx); - set_type(fors_leaf_addr, SPX_ADDR_TYPE_FORSPRF); - fors_gen_sk(leaf, ctx, fors_leaf_addr); - - set_type(fors_leaf_addr, SPX_ADDR_TYPE_FORSTREE); - fors_sk_to_leaf(leaf, leaf, - ctx, fors_leaf_addr); -} - -/** - * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - * Assumes indices has space for SPX_FORS_TREES integers. - */ -static void message_to_indices(uint32_t *indices, const unsigned char *m) { - unsigned int i, j; - unsigned int offset = 0; - - for (i = 0; i < SPX_FORS_TREES; i++) { - indices[i] = 0; - for (j = 0; j < SPX_FORS_HEIGHT; j++) { - indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); - offset++; - } - } -} - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -void fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]) { - uint32_t indices[SPX_FORS_TREES]; - unsigned char roots[SPX_FORS_TREES * SPX_N]; - uint32_t fors_tree_addr[8] = {0}; - struct fors_gen_leaf_info fors_info = {0}; - uint32_t *fors_leaf_addr = fors_info.leaf_addrx; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - copy_keypair_addr(fors_tree_addr, fors_addr); - copy_keypair_addr(fors_leaf_addr, fors_addr); - - copy_keypair_addr(fors_pk_addr, fors_addr); - set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < SPX_FORS_TREES; i++) { - idx_offset = i * (1 << SPX_FORS_HEIGHT); - - set_tree_height(fors_tree_addr, 0); - set_tree_index(fors_tree_addr, indices[i] + idx_offset); - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); - - /* Include the secret key part that produces the selected leaf node. */ - fors_gen_sk(sig, ctx, fors_tree_addr); - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); - sig += SPX_N; - - /* Compute the authentication path for this leaf node. */ - treehashx1(roots + i * SPX_N, sig, ctx, - indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx1, - fors_tree_addr, &fors_info); - - sig += SPX_N * SPX_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); -} - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -void fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]) { - uint32_t indices[SPX_FORS_TREES]; - unsigned char roots[SPX_FORS_TREES * SPX_N]; - unsigned char leaf[SPX_N]; - uint32_t fors_tree_addr[8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - copy_keypair_addr(fors_tree_addr, fors_addr); - copy_keypair_addr(fors_pk_addr, fors_addr); - - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); - set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < SPX_FORS_TREES; i++) { - idx_offset = i * (1 << SPX_FORS_HEIGHT); - - set_tree_height(fors_tree_addr, 0); - set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Derive the leaf from the included secret key part. */ - fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); - sig += SPX_N; - - /* Derive the corresponding root node of this tree. */ - compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, - sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); - sig += SPX_N * SPX_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/fors.h b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/fors.h deleted file mode 100644 index 509140a178..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/fors.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef SPX_FORS_H -#define SPX_FORS_H - -#include - -#include "context.h" -#include "params.h" - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -#define fors_sign SPX_NAMESPACE(fors_sign) -void fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]); - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) -void fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/hash.h b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/hash.h deleted file mode 100644 index ffe815f45d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/hash.h +++ /dev/null @@ -1,37 +0,0 @@ -#ifndef SPX_HASH_H -#define SPX_HASH_H - -#include -#include - -#include "context.h" -#include "params.h" - -#define prf_addr SPX_NAMESPACE(prf_addr) -void prf_addr(unsigned char *out, const spx_ctx *ctx, - const uint32_t addr[8]); - -#define gen_message_random SPX_NAMESPACE(gen_message_random) -void gen_message_random(unsigned char *R, const unsigned char *sk_prf, - const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx); - -#define hash_message SPX_NAMESPACE(hash_message) -void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx); - - -# define SPX_SHA256_ADDR_BYTES 22 - -# define mgf1_256 SPX_NAMESPACE(mgf1_256) -void mgf1_256(unsigned char *out, unsigned long outlen, - const unsigned char *in, unsigned long inlen); - -# define mgf1_512 SPX_NAMESPACE(mgf1_512) -void mgf1_512(unsigned char *out, unsigned long outlen, - const unsigned char *in, unsigned long inlen); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/hash_sha2.c b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/hash_sha2.c deleted file mode 100644 index 69f0dc0013..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/hash_sha2.c +++ /dev/null @@ -1,219 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "sha2.h" -#include "utils.h" - - - -#define SPX_SHAX_OUTPUT_BYTES SPX_SHA256_OUTPUT_BYTES -#define SPX_SHAX_BLOCK_BYTES SPX_SHA256_BLOCK_BYTES -#define shaX_inc_init sha256_inc_init -#define shaX_inc_blocks sha256_inc_blocks -#define shaX_inc_finalize sha256_inc_finalize -#define shaX sha256 -#define mgf1_X mgf1_256 -#define shaXstate sha256ctx - -/** - * mgf1 function based on the SHA-256 hash function - * Note that inlen should be sufficiently small that it still allows for - * an array to be allocated on the stack. Typically 'in' is merely a seed. - * Outputs outlen number of bytes - */ -void mgf1_256(unsigned char *out, unsigned long outlen, - const unsigned char *in, unsigned long inlen) { - PQCLEAN_VLA(uint8_t, inbuf, inlen + 4); - unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES]; - uint32_t i; - - memcpy(inbuf, in, inlen); - - /* While we can fit in at least another full block of SHA256 output.. */ - for (i = 0; (i + 1)*SPX_SHA256_OUTPUT_BYTES <= outlen; i++) { - u32_to_bytes(inbuf + inlen, i); - sha256(out, inbuf, inlen + 4); - out += SPX_SHA256_OUTPUT_BYTES; - } - /* Until we cannot anymore, and we fill the remainder. */ - if (outlen > i * SPX_SHA256_OUTPUT_BYTES) { - u32_to_bytes(inbuf + inlen, i); - sha256(outbuf, inbuf, inlen + 4); - memcpy(out, outbuf, outlen - i * SPX_SHA256_OUTPUT_BYTES); - } -} - -/* - * mgf1 function based on the SHA-512 hash function - */ -void mgf1_512(unsigned char *out, unsigned long outlen, - const unsigned char *in, unsigned long inlen) { - PQCLEAN_VLA(uint8_t, inbuf, inlen + 4); - unsigned char outbuf[SPX_SHA512_OUTPUT_BYTES]; - uint32_t i; - - memcpy(inbuf, in, inlen); - - /* While we can fit in at least another full block of SHA512 output.. */ - for (i = 0; (i + 1)*SPX_SHA512_OUTPUT_BYTES <= outlen; i++) { - u32_to_bytes(inbuf + inlen, i); - sha512(out, inbuf, inlen + 4); - out += SPX_SHA512_OUTPUT_BYTES; - } - /* Until we cannot anymore, and we fill the remainder. */ - if (outlen > i * SPX_SHA512_OUTPUT_BYTES) { - u32_to_bytes(inbuf + inlen, i); - sha512(outbuf, inbuf, inlen + 4); - memcpy(out, outbuf, outlen - i * SPX_SHA512_OUTPUT_BYTES); - } -} - -/* - * Computes PRF(pk_seed, sk_seed, addr). - */ -void prf_addr(unsigned char *out, const spx_ctx *ctx, - const uint32_t addr[8]) { - sha256ctx sha2_state; - unsigned char buf[SPX_SHA256_ADDR_BYTES + SPX_N]; - unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES]; - - /* Retrieve precomputed state containing pub_seed */ - sha256_inc_ctx_clone(&sha2_state, &ctx->state_seeded); - - /* Remainder: ADDR^c ‖ SK.seed */ - memcpy(buf, addr, SPX_SHA256_ADDR_BYTES); - memcpy(buf + SPX_SHA256_ADDR_BYTES, ctx->sk_seed, SPX_N); - - sha256_inc_finalize(outbuf, &sha2_state, buf, SPX_SHA256_ADDR_BYTES + SPX_N); - - memcpy(out, outbuf, SPX_N); -} - -/** - * Computes the message-dependent randomness R, using a secret seed as a key - * for HMAC, and an optional randomization value prefixed to the message. - * This requires m to have at least SPX_SHAX_BLOCK_BYTES + SPX_N space - * available in front of the pointer, i.e. before the message to use for the - * prefix. This is necessary to prevent having to move the message around (and - * allocate memory for it). - */ -void gen_message_random(unsigned char *R, const unsigned char *sk_prf, - const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx) { - (void)ctx; - - unsigned char buf[SPX_SHAX_BLOCK_BYTES + SPX_SHAX_OUTPUT_BYTES]; - shaXstate state; - int i; - - - /* This implements HMAC-SHA */ - for (i = 0; i < SPX_N; i++) { - buf[i] = 0x36 ^ sk_prf[i]; - } - memset(buf + SPX_N, 0x36, SPX_SHAX_BLOCK_BYTES - SPX_N); - - shaX_inc_init(&state); - shaX_inc_blocks(&state, buf, 1); - - memcpy(buf, optrand, SPX_N); - - /* If optrand + message cannot fill up an entire block */ - if (SPX_N + mlen < SPX_SHAX_BLOCK_BYTES) { - memcpy(buf + SPX_N, m, mlen); - shaX_inc_finalize(buf + SPX_SHAX_BLOCK_BYTES, &state, - buf, mlen + SPX_N); - } - /* Otherwise first fill a block, so that finalize only uses the message */ - else { - memcpy(buf + SPX_N, m, SPX_SHAX_BLOCK_BYTES - SPX_N); - shaX_inc_blocks(&state, buf, 1); - - m += SPX_SHAX_BLOCK_BYTES - SPX_N; - mlen -= SPX_SHAX_BLOCK_BYTES - SPX_N; - shaX_inc_finalize(buf + SPX_SHAX_BLOCK_BYTES, &state, m, mlen); - } - - for (i = 0; i < SPX_N; i++) { - buf[i] = 0x5c ^ sk_prf[i]; - } - memset(buf + SPX_N, 0x5c, SPX_SHAX_BLOCK_BYTES - SPX_N); - - shaX(buf, buf, SPX_SHAX_BLOCK_BYTES + SPX_SHAX_OUTPUT_BYTES); - memcpy(R, buf, SPX_N); -} - -/** - * Computes the message hash using R, the public key, and the message. - * Outputs the message digest and the index of the leaf. The index is split in - * the tree index and the leaf index, for convenient copying to an address. - */ -void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx) { - (void)ctx; -#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) -#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) -#define SPX_LEAF_BITS SPX_TREE_HEIGHT -#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) -#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) - - unsigned char seed[2 * SPX_N + SPX_SHAX_OUTPUT_BYTES]; - - /* Round to nearest multiple of SPX_SHAX_BLOCK_BYTES */ -#define SPX_INBLOCKS (((SPX_N + SPX_PK_BYTES + SPX_SHAX_BLOCK_BYTES - 1) & \ - -SPX_SHAX_BLOCK_BYTES) / SPX_SHAX_BLOCK_BYTES) - unsigned char inbuf[SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES]; - - unsigned char buf[SPX_DGST_BYTES]; - unsigned char *bufp = buf; - shaXstate state; - - shaX_inc_init(&state); - - // seed: SHA-X(R ‖ PK.seed ‖ PK.root ‖ M) - memcpy(inbuf, R, SPX_N); - memcpy(inbuf + SPX_N, pk, SPX_PK_BYTES); - - /* If R + pk + message cannot fill up an entire block */ - if (SPX_N + SPX_PK_BYTES + mlen < SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES) { - memcpy(inbuf + SPX_N + SPX_PK_BYTES, m, mlen); - shaX_inc_finalize(seed + 2 * SPX_N, &state, inbuf, SPX_N + SPX_PK_BYTES + mlen); - } - /* Otherwise first fill a block, so that finalize only uses the message */ - else { - memcpy(inbuf + SPX_N + SPX_PK_BYTES, m, - SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES - SPX_N - SPX_PK_BYTES); - shaX_inc_blocks(&state, inbuf, SPX_INBLOCKS); - - m += SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES - SPX_N - SPX_PK_BYTES; - mlen -= SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES - SPX_N - SPX_PK_BYTES; - shaX_inc_finalize(seed + 2 * SPX_N, &state, m, (size_t)mlen); - } - - // H_msg: MGF1-SHA-X(R ‖ PK.seed ‖ seed) - memcpy(seed, R, SPX_N); - memcpy(seed + SPX_N, pk, SPX_N); - - /* By doing this in two steps, we prevent hashing the message twice; - otherwise each iteration in MGF1 would hash the message again. */ - mgf1_X(bufp, SPX_DGST_BYTES, seed, 2 * SPX_N + SPX_SHAX_OUTPUT_BYTES); - - memcpy(digest, bufp, SPX_FORS_MSG_BYTES); - bufp += SPX_FORS_MSG_BYTES; - - - *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); - *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); - bufp += SPX_TREE_BYTES; - - *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); - *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); -} - - diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/merkle.c b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/merkle.c deleted file mode 100644 index 0c1479fd93..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/merkle.c +++ /dev/null @@ -1,59 +0,0 @@ -#include -#include - -#include "address.h" -#include "merkle.h" -#include "params.h" -#include "utils.h" -#include "utilsx1.h" -#include "wots.h" -#include "wotsx1.h" - -/* - * This generates a Merkle signature (WOTS signature followed by the Merkle - * authentication path). This is in this file because most of the complexity - * is involved with the WOTS signature; the Merkle authentication path logic - * is mostly hidden in treehashx4 - */ -void merkle_sign(uint8_t *sig, unsigned char *root, - const spx_ctx *ctx, - uint32_t wots_addr[8], uint32_t tree_addr[8], - uint32_t idx_leaf) { - unsigned char *auth_path = sig + SPX_WOTS_BYTES; - struct leaf_info_x1 info = { 0 }; - unsigned steps[ SPX_WOTS_LEN ]; - - info.wots_sig = sig; - chain_lengths(steps, root); - info.wots_steps = steps; - - set_type(&tree_addr[0], SPX_ADDR_TYPE_HASHTREE); - set_type(&info.pk_addr[0], SPX_ADDR_TYPE_WOTSPK); - copy_subtree_addr(&info.leaf_addr[0], wots_addr); - copy_subtree_addr(&info.pk_addr[0], wots_addr); - - info.wots_sign_leaf = idx_leaf; - - treehashx1(root, auth_path, ctx, - idx_leaf, 0, - SPX_TREE_HEIGHT, - wots_gen_leafx1, - tree_addr, &info); -} - -/* Compute root node of the top-most subtree. */ -void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { - /* We do not need the auth path in key generation, but it simplifies the - code to have just one treehash routine that computes both root and path - in one function. */ - unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; - uint32_t top_tree_addr[8] = {0}; - uint32_t wots_addr[8] = {0}; - - set_layer_addr(top_tree_addr, SPX_D - 1); - set_layer_addr(wots_addr, SPX_D - 1); - - merkle_sign(auth_path, root, ctx, - wots_addr, top_tree_addr, - (uint32_t)~0 /* ~0 means "don't bother generating an auth path */ ); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/merkle.h b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/merkle.h deleted file mode 100644 index 769cf2e970..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/merkle.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef MERKLE_H_ -#define MERKLE_H_ - -#include - -#include "context.h" -#include "params.h" - -/* Generate a Merkle signature (WOTS signature followed by the Merkle */ -/* authentication path) */ -#define merkle_sign SPX_NAMESPACE(merkle_sign) -void merkle_sign(uint8_t *sig, unsigned char *root, - const spx_ctx *ctx, - uint32_t wots_addr[8], uint32_t tree_addr[8], - uint32_t idx_leaf); - -/* Compute the root node of the top-most subtree. */ -#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) -void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); - -#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/nistapi.h b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/nistapi.h deleted file mode 100644 index 3cb71afad4..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/nistapi.h +++ /dev/null @@ -1,87 +0,0 @@ -#ifndef SPX_API_H -#define SPX_API_H - -#include -#include - -#include "params.h" - -#define CRYPTO_ALGNAME "SPHINCS+" - -#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES -#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES -#define CRYPTO_BYTES SPX_BYTES -#define CRYPTO_SEEDBYTES (3*SPX_N) - -/* - * Returns the length of a secret key, in bytes - */ -#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) -size_t crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) -size_t crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) -size_t crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) -size_t crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) -int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) -int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) -int crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) -int crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -#define crypto_sign SPX_NAMESPACE(crypto_sign) -int crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) -int crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/params.h b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/params.h deleted file mode 100644 index 14eb890bfb..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/params.h +++ /dev/null @@ -1,61 +0,0 @@ -#ifndef SPX_PARAMS_H -#define SPX_PARAMS_H - -#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSSHA2128SROBUST_CLEAN_##s - -/* Hash output length in bytes. */ -#define SPX_N 16 -/* Height of the hypertree. */ -#define SPX_FULL_HEIGHT 63 -/* Number of subtree layer. */ -#define SPX_D 7 -/* FORS tree dimensions. */ -#define SPX_FORS_HEIGHT 12 -#define SPX_FORS_TREES 14 -/* Winternitz parameter, */ -#define SPX_WOTS_W 16 - -/* The hash function is defined by linking a different hash.c file, as opposed - to setting a #define constant. */ - -/* This is a SHA2-based parameter set, hence whether we use SHA-256 - * exclusively or we use both SHA-256 and SHA-512 is controlled by - * the following #define */ -#define SPX_SHA512 0 /* Use SHA-256 for all hashes */ - -/* For clarity */ -#define SPX_ADDR_BYTES 32 - -/* WOTS parameters. */ -#define SPX_WOTS_LOGW 4 - -#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) - -/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#define SPX_WOTS_LEN2 3 - -#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) -#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) -#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES - -/* Subtree size. */ -#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) - -//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT -// #error SPX_D should always divide SPX_FULL_HEIGHT -//#endif - -/* FORS parameters. */ -#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) -#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) -#define SPX_FORS_PK_BYTES SPX_N - -/* Resulting SPX sizes. */ -#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ - SPX_FULL_HEIGHT * SPX_N) -#define SPX_PK_BYTES (2 * SPX_N) -#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) - -#include "sha2_offsets.h" - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/sha2_offsets.h b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/sha2_offsets.h deleted file mode 100644 index 6e3584f7a4..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/sha2_offsets.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef SHA2_OFFSETS_H_ -#define SHA2_OFFSETS_H_ - -#define SPX_SHA256_BLOCK_BYTES 64 -#define SPX_SHA256_OUTPUT_BYTES 32 - -#define SPX_SHA512_BLOCK_BYTES 128 -#define SPX_SHA512_OUTPUT_BYTES 64 - -/* - * Offsets of various fields in the address structure when we use SHA2 as - * the Sphincs+ hash function - */ - -#define SPX_OFFSET_LAYER 0 /* The byte used to specify the Merkle tree layer */ -#define SPX_OFFSET_TREE 1 /* The start of the 8 byte field used to specify the tree */ -#define SPX_OFFSET_TYPE 9 /* The byte used to specify the hash type (reason) */ -#define SPX_OFFSET_KP_ADDR2 12 /* The high byte used to specify the key pair (which one-time signature) */ -#define SPX_OFFSET_KP_ADDR1 13 /* The low byte used to specify the key pair */ -#define SPX_OFFSET_CHAIN_ADDR 17 /* The byte used to specify the chain address (which Winternitz chain) */ -#define SPX_OFFSET_HASH_ADDR 21 /* The byte used to specify the hash address (where in the Winternitz chain) */ -#define SPX_OFFSET_TREE_HGT 17 /* The byte used to specify the height of this node in the FORS or Merkle tree */ -#define SPX_OFFSET_TREE_INDEX 18 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ - -#define SPX_SHA2 1 - -#endif /* SHA2_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/sign.c b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/sign.c deleted file mode 100644 index 9d0c7d1b22..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/sign.c +++ /dev/null @@ -1,286 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "context.h" -#include "fors.h" -#include "hash.h" -#include "merkle.h" -#include "nistapi.h" -#include "params.h" -#include "randombytes.h" -#include "thash.h" -#include "utils.h" -#include "wots.h" - -/* - * Returns the length of a secret key, in bytes - */ -size_t crypto_sign_secretkeybytes(void) { - return CRYPTO_SECRETKEYBYTES; -} - -/* - * Returns the length of a public key, in bytes - */ -size_t crypto_sign_publickeybytes(void) { - return CRYPTO_PUBLICKEYBYTES; -} - -/* - * Returns the length of a signature, in bytes - */ -size_t crypto_sign_bytes(void) { - return CRYPTO_BYTES; -} - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t crypto_sign_seedbytes(void) { - return CRYPTO_SEEDBYTES; -} - -/* - * Generates an SPX key pair given a seed of length - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed) { - spx_ctx ctx; - - /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ - memcpy(sk, seed, CRYPTO_SEEDBYTES); - - memcpy(pk, sk + 2 * SPX_N, SPX_N); - - memcpy(ctx.pub_seed, pk, SPX_N); - memcpy(ctx.sk_seed, sk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - /* Compute root node of the top-most subtree. */ - merkle_gen_root(sk + 3 * SPX_N, &ctx); - - // cleanup - free_hash_function(&ctx); - - memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); - - return 0; -} - -/* - * Generates an SPX key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { - uint8_t seed[CRYPTO_SEEDBYTES]; - randombytes(seed, CRYPTO_SEEDBYTES); - crypto_sign_seed_keypair(pk, sk, seed); - - return 0; -} - -/** - * Returns an array containing a detached signature. - */ -int crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - spx_ctx ctx; - - const uint8_t *sk_prf = sk + SPX_N; - const uint8_t *pk = sk + 2 * SPX_N; - - uint8_t optrand[SPX_N]; - uint8_t mhash[SPX_FORS_MSG_BYTES]; - uint8_t root[SPX_N]; - uint32_t i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - - memcpy(ctx.sk_seed, sk, SPX_N); - memcpy(ctx.pub_seed, pk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - set_type(wots_addr, SPX_ADDR_TYPE_WOTS); - set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); - - /* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ - randombytes(optrand, SPX_N); - /* Compute the digest randomization value. */ - gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); - - /* Derive the message digest and leaf index from R, PK and M. */ - hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); - sig += SPX_N; - - set_tree_addr(wots_addr, tree); - set_keypair_addr(wots_addr, idx_leaf); - - /* Sign the message hash using FORS. */ - fors_sign(sig, root, mhash, &ctx, wots_addr); - sig += SPX_FORS_BYTES; - - for (i = 0; i < SPX_D; i++) { - set_layer_addr(tree_addr, i); - set_tree_addr(tree_addr, tree); - - copy_subtree_addr(wots_addr, tree_addr); - set_keypair_addr(wots_addr, idx_leaf); - - merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); - sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); - tree = tree >> SPX_TREE_HEIGHT; - } - - free_hash_function(&ctx); - - *siglen = SPX_BYTES; - - return 0; -} - -/** - * Verifies a detached signature and message under a given public key. - */ -int crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk) { - spx_ctx ctx; - const uint8_t *pub_root = pk + SPX_N; - uint8_t mhash[SPX_FORS_MSG_BYTES]; - uint8_t wots_pk[SPX_WOTS_BYTES]; - uint8_t root[SPX_N]; - uint8_t leaf[SPX_N]; - unsigned int i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - if (siglen != SPX_BYTES) { - return -1; - } - - memcpy(ctx.pub_seed, pk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - set_type(wots_addr, SPX_ADDR_TYPE_WOTS); - set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); - set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); - - /* Derive the message digest and leaf index from R || PK || M. */ - /* The additional SPX_N is a result of the hash domain separator. */ - hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); - sig += SPX_N; - - /* Layer correctly defaults to 0, so no need to set_layer_addr */ - set_tree_addr(wots_addr, tree); - set_keypair_addr(wots_addr, idx_leaf); - - fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); - sig += SPX_FORS_BYTES; - - /* For each subtree.. */ - for (i = 0; i < SPX_D; i++) { - set_layer_addr(tree_addr, i); - set_tree_addr(tree_addr, tree); - - copy_subtree_addr(wots_addr, tree_addr); - set_keypair_addr(wots_addr, idx_leaf); - - copy_keypair_addr(wots_pk_addr, wots_addr); - - /* The WOTS public key is only correct if the signature was correct. */ - /* Initially, root is the FORS pk, but on subsequent iterations it is - the root of the subtree below the currently processed subtree. */ - wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); - sig += SPX_WOTS_BYTES; - - /* Compute the leaf node using the WOTS public key. */ - thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); - - /* Compute the root node of this subtree. */ - compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, - &ctx, tree_addr); - sig += SPX_TREE_HEIGHT * SPX_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); - tree = tree >> SPX_TREE_HEIGHT; - } - - // cleanup - free_hash_function(&ctx); - - /* Check if the root node equals the root node in the public key. */ - if (memcmp(root, pub_root, SPX_N) != 0) { - return -1; - } - - return 0; -} - - -/** - * Returns an array containing the signature followed by the message. - */ -int crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk) { - size_t siglen; - - crypto_sign_signature(sm, &siglen, m, mlen, sk); - - memmove(sm + SPX_BYTES, m, mlen); - *smlen = siglen + mlen; - - return 0; -} - -/** - * Verifies a given signature-message pair under a given public key. - */ -int crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk) { - /* The API caller does not necessarily know what size a signature should be - but SPHINCS+ signatures are always exactly SPX_BYTES. */ - if (smlen < SPX_BYTES) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - *mlen = smlen - SPX_BYTES; - - if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - /* If verification was successful, move the message to the right place. */ - memmove(m, sm + SPX_BYTES, *mlen); - - return 0; -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/thash.h b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/thash.h deleted file mode 100644 index 8687ccfb4d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/thash.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef SPX_THASH_H -#define SPX_THASH_H - -#include "context.h" -#include "params.h" - -#include - -#define thash SPX_NAMESPACE(thash) -void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/thash_sha2_robust.c b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/thash_sha2_robust.c deleted file mode 100644 index 18f65c2e42..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/thash_sha2_robust.c +++ /dev/null @@ -1,39 +0,0 @@ -#include -#include - -#include "address.h" -#include "context.h" -#include "hash.h" -#include "params.h" -#include "sha2.h" -#include "thash.h" -#include "utils.h" - - -/** - * Takes an array of inblocks concatenated arrays of SPX_N bytes. - */ -void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]) { - unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES]; - PQCLEAN_VLA(uint8_t, bitmask, inblocks * SPX_N); - PQCLEAN_VLA(uint8_t, buf, SPX_N + SPX_SHA256_OUTPUT_BYTES + inblocks * SPX_N); - sha256ctx sha2_state; - unsigned int i; - - memcpy(buf, ctx->pub_seed, SPX_N); - memcpy(buf + SPX_N, addr, SPX_SHA256_ADDR_BYTES); - mgf1_256(bitmask, inblocks * SPX_N, buf, SPX_N + SPX_SHA256_ADDR_BYTES); - - /* Retrieve precomputed state containing pub_seed */ - sha256_inc_ctx_clone(&sha2_state, &ctx->state_seeded); - - for (i = 0; i < inblocks * SPX_N; i++) { - buf[SPX_N + SPX_SHA256_ADDR_BYTES + i] = in[i] ^ bitmask[i]; - } - - sha256_inc_finalize(outbuf, &sha2_state, buf + SPX_N, - SPX_SHA256_ADDR_BYTES + inblocks * SPX_N); - memcpy(out, outbuf, SPX_N); -} - diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/utils.c b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/utils.c deleted file mode 100644 index 177b541fb9..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/utils.c +++ /dev/null @@ -1,148 +0,0 @@ -#include - -#include "utils.h" - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "thash.h" - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void ull_to_bytes(unsigned char *out, unsigned int outlen, - unsigned long long in) { - int i; - - /* Iterate over out in decreasing order, for big-endianness. */ - for (i = (signed int)outlen - 1; i >= 0; i--) { - out[i] = in & 0xff; - in = in >> 8; - } -} - -void u32_to_bytes(unsigned char *out, uint32_t in) { - out[0] = (unsigned char)(in >> 24); - out[1] = (unsigned char)(in >> 16); - out[2] = (unsigned char)(in >> 8); - out[3] = (unsigned char)in; -} - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { - unsigned long long retval = 0; - unsigned int i; - - for (i = 0; i < inlen; i++) { - retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); - } - return retval; -} - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void compute_root(unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const spx_ctx *ctx, uint32_t addr[8]) { - uint32_t i; - unsigned char buffer[2 * SPX_N]; - - /* If leaf_idx is odd (last bit = 1), current path element is a right child - and auth_path has to go left. Otherwise it is the other way around. */ - if (leaf_idx & 1) { - memcpy(buffer + SPX_N, leaf, SPX_N); - memcpy(buffer, auth_path, SPX_N); - } else { - memcpy(buffer, leaf, SPX_N); - memcpy(buffer + SPX_N, auth_path, SPX_N); - } - auth_path += SPX_N; - - for (i = 0; i < tree_height - 1; i++) { - leaf_idx >>= 1; - idx_offset >>= 1; - /* Set the address of the node we're creating. */ - set_tree_height(addr, i + 1); - set_tree_index(addr, leaf_idx + idx_offset); - - /* Pick the right or left neighbor, depending on parity of the node. */ - if (leaf_idx & 1) { - thash(buffer + SPX_N, buffer, 2, ctx, addr); - memcpy(buffer, auth_path, SPX_N); - } else { - thash(buffer, buffer, 2, ctx, addr); - memcpy(buffer + SPX_N, auth_path, SPX_N); - } - auth_path += SPX_N; - } - - /* The last iteration is exceptional; we do not copy an auth_path node. */ - leaf_idx >>= 1; - idx_offset >>= 1; - set_tree_height(addr, tree_height); - set_tree_index(addr, leaf_idx + idx_offset); - thash(root, buffer, 2, ctx, addr); -} - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const spx_ctx * /* ctx */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), - uint32_t tree_addr[8]) { - PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); - PQCLEAN_VLA(unsigned int, heights, tree_height + 1); - unsigned int offset = 0; - uint32_t idx; - uint32_t tree_idx; - - for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { - /* Add the next leaf node to the stack. */ - gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); - offset++; - heights[offset - 1] = 0; - - /* If this is a node we need for the auth path.. */ - if ((leaf_idx ^ 0x1) == idx) { - memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); - } - - /* While the top-most nodes are of equal height.. */ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { - /* Compute index of the new node, in the next layer. */ - tree_idx = (idx >> (heights[offset - 1] + 1)); - - /* Set the address of the node we're creating. */ - set_tree_height(tree_addr, heights[offset - 1] + 1); - set_tree_index(tree_addr, - tree_idx + (idx_offset >> (heights[offset - 1] + 1))); - /* Hash the top-most nodes from the stack together. */ - thash(stack + (offset - 2)*SPX_N, - stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); - offset--; - /* Note that the top-most node is now one layer higher. */ - heights[offset - 1]++; - - /* If this is a node we need for the auth path.. */ - if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_path + heights[offset - 1]*SPX_N, - stack + (offset - 1)*SPX_N, SPX_N); - } - } - } - memcpy(root, stack, SPX_N); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/utils.h b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/utils.h deleted file mode 100644 index 64f5d5a53a..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/utils.h +++ /dev/null @@ -1,58 +0,0 @@ -#ifndef SPX_UTILS_H -#define SPX_UTILS_H - -#include - -#include "compat.h" -#include "context.h" -#include "params.h" - - -/* To support MSVC use alloca() instead of VLAs. See #20. */ - - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) -void ull_to_bytes(unsigned char *out, unsigned int outlen, - unsigned long long in); -#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) -void u32_to_bytes(unsigned char *out, uint32_t in); - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) -unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -#define compute_root SPX_NAMESPACE(compute_root) -void compute_root(unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const spx_ctx *ctx, uint32_t addr[8]); - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -#define treehash SPX_NAMESPACE(treehash) -void treehash(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const spx_ctx *ctx /* ctx */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), - uint32_t tree_addr[8]); - - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/utilsx1.c b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/utilsx1.c deleted file mode 100644 index fccb69b35d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/utilsx1.c +++ /dev/null @@ -1,100 +0,0 @@ -#include - -#include "utilsx1.h" - -#include "address.h" -#include "params.h" -#include "thash.h" -#include "utils.h" - -/* - * Generate the entire Merkle tree, computing the authentication path for - * leaf_idx, and the resulting root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) - * - * This expects tree_addr to be initialized to the addr structures for the - * Merkle tree nodes - * - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - * - * This works by using the standard Merkle tree building algorithm, - */ -void treehashx1(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, - uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* Where to write the leaves */, - const spx_ctx * /* ctx */, - uint32_t idx, void *info), - uint32_t tree_addr[8], - void *info) { - /* This is where we keep the intermediate nodes */ - PQCLEAN_VLA(uint8_t, stack, tree_height * SPX_N); - - uint32_t idx; - uint32_t max_idx = (uint32_t)((1 << tree_height) - 1); - for (idx = 0;; idx++) { - unsigned char current[2 * SPX_N]; /* Current logical node is at */ - /* index[SPX_N]. We do this to minimize the number of copies */ - /* needed during a thash */ - gen_leaf( ¤t[SPX_N], ctx, idx + idx_offset, - info ); - - /* Now combine the freshly generated right node with previously */ - /* generated left ones */ - uint32_t internal_idx_offset = idx_offset; - uint32_t internal_idx = idx; - uint32_t internal_leaf = leaf_idx; - uint32_t h; /* The height we are in the Merkle tree */ - for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { - - /* Check if we hit the top of the tree */ - if (h == tree_height) { - /* We hit the root; return it */ - memcpy( root, ¤t[SPX_N], SPX_N ); - return; - } - - /* - * Check if the node we have is a part of the - * authentication path; if it is, write it out - */ - if ((internal_idx ^ internal_leaf) == 0x01) { - memcpy( &auth_path[ h * SPX_N ], - ¤t[SPX_N], - SPX_N ); - } - - /* - * Check if we're at a left child; if so, stop going up the stack - * Exception: if we've reached the end of the tree, keep on going - * (so we combine the last 4 nodes into the one root node in two - * more iterations) - */ - if ((internal_idx & 1) == 0 && idx < max_idx) { - break; - } - - /* Ok, we're at a right node */ - /* Now combine the left and right logical nodes together */ - - /* Set the address of the node we're creating. */ - internal_idx_offset >>= 1; - set_tree_height(tree_addr, h + 1); - set_tree_index(tree_addr, internal_idx / 2 + internal_idx_offset ); - - unsigned char *left = &stack[h * SPX_N]; - memcpy( ¤t[0], left, SPX_N ); - thash( ¤t[1 * SPX_N], - ¤t[0 * SPX_N], - 2, ctx, tree_addr); - } - - /* We've hit a left child; save the current for when we get the */ - /* corresponding right right */ - memcpy( &stack[h * SPX_N], ¤t[SPX_N], SPX_N); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/utilsx1.h b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/utilsx1.h deleted file mode 100644 index e911d17d53..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/utilsx1.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef SPX_UTILSX4_H -#define SPX_UTILSX4_H - -#include - -#include "context.h" -#include "params.h" - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -#define treehashx1 SPX_NAMESPACE(treehashx1) -void treehashx1(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* Where to write the leaf */, - const spx_ctx * /* ctx */, - uint32_t addr_idx, void *info), - uint32_t tree_addrx4[8], void *info); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/wots.c b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/wots.c deleted file mode 100644 index 249717aaa8..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/wots.c +++ /dev/null @@ -1,108 +0,0 @@ -#include -#include - -#include "wots.h" -#include "wotsx1.h" - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "thash.h" -#include "utils.h" -#include "utilsx1.h" - -// TODO clarify address expectations, and make them more uniform. -// TODO i.e. do we expect types to be set already? -// TODO and do we expect modifications or copies? - -/** - * Computes the chaining function. - * out and in have to be n-byte arrays. - * - * Interprets in as start-th value of the chain. - * addr has to contain the address of the chain. - */ -static void gen_chain(unsigned char *out, const unsigned char *in, - unsigned int start, unsigned int steps, - const spx_ctx *ctx, uint32_t addr[8]) { - uint32_t i; - - /* Initialize out with the value at position 'start'. */ - memcpy(out, in, SPX_N); - - /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < SPX_WOTS_W; i++) { - set_hash_addr(addr, i); - thash(out, out, 1, ctx, addr); - } -} - -/** - * base_w algorithm as described in draft. - * Interprets an array of bytes as integers in base w. - * This only works when log_w is a divisor of 8. - */ -static void base_w(unsigned int *output, const int out_len, - const unsigned char *input) { - int in = 0; - int out = 0; - unsigned char total = 0; - int bits = 0; - int consumed; - - for (consumed = 0; consumed < out_len; consumed++) { - if (bits == 0) { - total = input[in]; - in++; - bits += 8; - } - bits -= SPX_WOTS_LOGW; - output[out] = (total >> bits) & (SPX_WOTS_W - 1); - out++; - } -} - -/* Computes the WOTS+ checksum over a message (in base_w). */ -static void wots_checksum(unsigned int *csum_base_w, - const unsigned int *msg_base_w) { - unsigned int csum = 0; - unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; - unsigned int i; - - /* Compute checksum. */ - for (i = 0; i < SPX_WOTS_LEN1; i++) { - csum += SPX_WOTS_W - 1 - msg_base_w[i]; - } - - /* Convert checksum to base_w. */ - /* Make sure expected empty zero bits are the least significant bits. */ - csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); - ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); - base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); -} - -/* Takes a message and derives the matching chain lengths. */ -void chain_lengths(unsigned int *lengths, const unsigned char *msg) { - base_w(lengths, SPX_WOTS_LEN1, msg); - wots_checksum(lengths + SPX_WOTS_LEN1, lengths); -} - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const spx_ctx *ctx, uint32_t addr[8]) { - unsigned int lengths[SPX_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < SPX_WOTS_LEN; i++) { - set_chain_addr(addr, i); - gen_chain(pk + i * SPX_N, sig + i * SPX_N, - lengths[i], SPX_WOTS_W - 1 - lengths[i], ctx, addr); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/wots.h b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/wots.h deleted file mode 100644 index 4e7692eeef..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/wots.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef SPX_WOTS_H -#define SPX_WOTS_H - -#include - -#include "context.h" -#include "params.h" - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) -void wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const spx_ctx *ctx, uint32_t addr[8]); - -/* - * Compute the chain lengths needed for a given message hash - */ -#define chain_lengths SPX_NAMESPACE(chain_lengths) -void chain_lengths(unsigned int *lengths, const unsigned char *msg); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/wotsx1.c b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/wotsx1.c deleted file mode 100644 index 3adec78dfb..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/wotsx1.c +++ /dev/null @@ -1,76 +0,0 @@ -#include -#include - -#include "wots.h" -#include "wotsx1.h" - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "thash.h" -#include "utils.h" - -/* - * This generates a WOTS public key - * It also generates the WOTS signature if leaf_info indicates - * that we're signing with this WOTS key - */ -void wots_gen_leafx1(unsigned char *dest, - const spx_ctx *ctx, - uint32_t leaf_idx, void *v_info) { - struct leaf_info_x1 *info = v_info; - uint32_t *leaf_addr = info->leaf_addr; - uint32_t *pk_addr = info->pk_addr; - unsigned int i, k; - unsigned char pk_buffer[ SPX_WOTS_BYTES ]; - unsigned char *buffer; - uint32_t wots_k_mask; - - if (leaf_idx == info->wots_sign_leaf) { - /* We're traversing the leaf that's signing; generate the WOTS */ - /* signature */ - wots_k_mask = 0; - } else { - /* Nope, we're just generating pk's; turn off the signature logic */ - wots_k_mask = (uint32_t)~0; - } - - set_keypair_addr( leaf_addr, leaf_idx ); - set_keypair_addr( pk_addr, leaf_idx ); - - for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { - uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k to */ - /* the step if we're generating a signature, ~0 if we're not */ - - /* Start with the secret seed */ - set_chain_addr(leaf_addr, i); - set_hash_addr(leaf_addr, 0); - set_type(leaf_addr, SPX_ADDR_TYPE_WOTSPRF); - - prf_addr(buffer, ctx, leaf_addr); - - set_type(leaf_addr, SPX_ADDR_TYPE_WOTS); - - /* Iterate down the WOTS chain */ - for (k = 0;; k++) { - /* Check if this is the value that needs to be saved as a */ - /* part of the WOTS signature */ - if (k == wots_k) { - memcpy( info->wots_sig + i * SPX_N, buffer, SPX_N ); - } - - /* Check if we hit the top of the chain */ - if (k == SPX_WOTS_W - 1) { - break; - } - - /* Iterate one step on the chain */ - set_hash_addr(leaf_addr, k); - - thash(buffer, buffer, 1, ctx, leaf_addr); - } - } - - /* Do the final thash to generate the public keys */ - thash(dest, pk_buffer, SPX_WOTS_LEN, ctx, pk_addr); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/wotsx1.h b/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/wotsx1.h deleted file mode 100644 index e617929f96..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-128s-robust_clean/wotsx1.h +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef WOTSX1_H_ -#define WOTSX1_H_ - -#include - -#include "context.h" -#include "params.h" - -/* - * This is here to provide an interface to the internal wots_gen_leafx1 - * routine. While this routine is not referenced in the package outside of - * wots.c, it is called from the stand-alone benchmark code to characterize - * the performance - */ -struct leaf_info_x1 { - unsigned char *wots_sig; - uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ - uint32_t *wots_steps; - uint32_t leaf_addr[8]; - uint32_t pk_addr[8]; -}; - -/* Macro to set the leaf_info to something 'benign', that is, it would */ -/* run with the same time as it does during the real signing process */ -/* Used only by the benchmark code */ -#define INITIALIZE_LEAF_INFO_X1(info, addr, step_buffer) { \ - (info).wots_sig = 0; \ - (info).wots_sign_leaf = ~0; \ - (info).wots_steps = step_buffer; \ - memcpy( &(info).leaf_addr[0], (addr), 32 ); \ - memcpy( &(info).pk_addr[0], (addr), 32 ); \ - } - -#define wots_gen_leafx1 SPX_NAMESPACE(wots_gen_leafx1) -void wots_gen_leafx1(unsigned char *dest, - const spx_ctx *ctx, - uint32_t leaf_idx, void *v_info); - -#endif /* WOTSX1_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/LICENSE b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/LICENSE deleted file mode 100644 index 670154e353..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/LICENSE +++ /dev/null @@ -1,116 +0,0 @@ -CC0 1.0 Universal - -Statement of Purpose - -The laws of most jurisdictions throughout the world automatically confer -exclusive Copyright and Related Rights (defined below) upon the creator and -subsequent owner(s) (each and all, an "owner") of an original work of -authorship and/or a database (each, a "Work"). - -Certain owners wish to permanently relinquish those rights to a Work for the -purpose of contributing to a commons of creative, cultural and scientific -works ("Commons") that the public can reliably and without fear of later -claims of infringement build upon, modify, incorporate in other works, reuse -and redistribute as freely as possible in any form whatsoever and for any -purposes, including without limitation commercial purposes. These owners may -contribute to the Commons to promote the ideal of a free culture and the -further production of creative, cultural and scientific works, or to gain -reputation or greater distribution for their Work in part through the use and -efforts of others. - -For these and/or other purposes and motivations, and without any expectation -of additional consideration or compensation, the person associating CC0 with a -Work (the "Affirmer"), to the extent that he or she is an owner of Copyright -and Related Rights in the Work, voluntarily elects to apply CC0 to the Work -and publicly distribute the Work under its terms, with knowledge of his or her -Copyright and Related Rights in the Work and the meaning and intended legal -effect of CC0 on those rights. - -1. Copyright and Related Rights. A Work made available under CC0 may be -protected by copyright and related or neighboring rights ("Copyright and -Related Rights"). Copyright and Related Rights include, but are not limited -to, the following: - - i. the right to reproduce, adapt, distribute, perform, display, communicate, - and translate a Work; - - ii. moral rights retained by the original author(s) and/or performer(s); - - iii. publicity and privacy rights pertaining to a person's image or likeness - depicted in a Work; - - iv. rights protecting against unfair competition in regards to a Work, - subject to the limitations in paragraph 4(a), below; - - v. rights protecting the extraction, dissemination, use and reuse of data in - a Work; - - vi. database rights (such as those arising under Directive 96/9/EC of the - European Parliament and of the Council of 11 March 1996 on the legal - protection of databases, and under any national implementation thereof, - including any amended or successor version of such directive); and - - vii. other similar, equivalent or corresponding rights throughout the world - based on applicable law or treaty, and any national implementations thereof. - -2. Waiver. To the greatest extent permitted by, but not in contravention of, -applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and -unconditionally waives, abandons, and surrenders all of Affirmer's Copyright -and Related Rights and associated claims and causes of action, whether now -known or unknown (including existing as well as future claims and causes of -action), in the Work (i) in all territories worldwide, (ii) for the maximum -duration provided by applicable law or treaty (including future time -extensions), (iii) in any current or future medium and for any number of -copies, and (iv) for any purpose whatsoever, including without limitation -commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes -the Waiver for the benefit of each member of the public at large and to the -detriment of Affirmer's heirs and successors, fully intending that such Waiver -shall not be subject to revocation, rescission, cancellation, termination, or -any other legal or equitable action to disrupt the quiet enjoyment of the Work -by the public as contemplated by Affirmer's express Statement of Purpose. - -3. Public License Fallback. Should any part of the Waiver for any reason be -judged legally invalid or ineffective under applicable law, then the Waiver -shall be preserved to the maximum extent permitted taking into account -Affirmer's express Statement of Purpose. In addition, to the extent the Waiver -is so judged Affirmer hereby grants to each affected person a royalty-free, -non transferable, non sublicensable, non exclusive, irrevocable and -unconditional license to exercise Affirmer's Copyright and Related Rights in -the Work (i) in all territories worldwide, (ii) for the maximum duration -provided by applicable law or treaty (including future time extensions), (iii) -in any current or future medium and for any number of copies, and (iv) for any -purpose whatsoever, including without limitation commercial, advertising or -promotional purposes (the "License"). The License shall be deemed effective as -of the date CC0 was applied by Affirmer to the Work. Should any part of the -License for any reason be judged legally invalid or ineffective under -applicable law, such partial invalidity or ineffectiveness shall not -invalidate the remainder of the License, and in such case Affirmer hereby -affirms that he or she will not (i) exercise any of his or her remaining -Copyright and Related Rights in the Work or (ii) assert any associated claims -and causes of action with respect to the Work, in either case contrary to -Affirmer's express Statement of Purpose. - -4. Limitations and Disclaimers. - - a. No trademark or patent rights held by Affirmer are waived, abandoned, - surrendered, licensed or otherwise affected by this document. - - b. Affirmer offers the Work as-is and makes no representations or warranties - of any kind concerning the Work, express, implied, statutory or otherwise, - including without limitation warranties of title, merchantability, fitness - for a particular purpose, non infringement, or the absence of latent or - other defects, accuracy, or the present or absence of errors, whether or not - discoverable, all to the greatest extent permissible under applicable law. - - c. Affirmer disclaims responsibility for clearing rights of other persons - that may apply to the Work or any use thereof, including without limitation - any person's Copyright and Related Rights in the Work. Further, Affirmer - disclaims responsibility for obtaining any necessary consents, permissions - or other rights required for any use of the Work. - - d. Affirmer understands and acknowledges that Creative Commons is not a - party to this document and has no duty or obligation with respect to this - CC0 or use of the Work. - -For more information, please see - diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/address.c b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/address.c deleted file mode 100644 index b956e9cb29..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/address.c +++ /dev/null @@ -1,91 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "utils.h" - -/* - * Specify which level of Merkle tree (the "layer") we're working on - */ -void set_layer_addr(uint32_t addr[8], uint32_t layer) { - ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; -} - -/* - * Specify which Merkle tree within the level (the "tree address") we're working on - */ -void set_tree_addr(uint32_t addr[8], uint64_t tree) { - ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); -} - -/* - * Specify the reason we'll use this address structure for, that is, what - * hash will we compute with it. This is used so that unrelated types of - * hashes don't accidentally get the same address structure. The type will be - * one of the SPX_ADDR_TYPE constants - */ -void set_type(uint32_t addr[8], uint32_t type) { - ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; -} - -/* - * Copy the layer and tree fields of the address structure. This is used - * when we're doing multiple types of hashes within the same Merkle tree - */ -void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { - memcpy( out, in, SPX_OFFSET_TREE + 8 ); -} - -/* These functions are used for OTS addresses. */ - -/* - * Specify which Merkle leaf we're working on; that is, which OTS keypair - * we're talking about. - */ -void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { - ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; -} - -/* - * Copy the layer, tree and keypair fields of the address structure. This is - * used when we're doing multiple things within the same OTS keypair - */ -void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { - memcpy( out, in, SPX_OFFSET_TREE + 8 ); - ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; -} - -/* - * Specify which Merkle chain within the OTS we're working with - * (the chain address) - */ -void set_chain_addr(uint32_t addr[8], uint32_t chain) { - ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; -} - -/* - * Specify where in the Merkle chain we are -* (the hash address) - */ -void set_hash_addr(uint32_t addr[8], uint32_t hash) { - ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; -} - -/* These functions are used for all hash tree addresses (including FORS). */ - -/* - * Specify the height of the node in the Merkle/FORS tree we are in - * (the tree height) - */ -void set_tree_height(uint32_t addr[8], uint32_t tree_height) { - ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; -} - -/* - * Specify the distance from the left edge of the node in the Merkle/FORS tree - * (the tree index) - */ -void set_tree_index(uint32_t addr[8], uint32_t tree_index) { - u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/address.h b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/address.h deleted file mode 100644 index 24a84eb40c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/address.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef SPX_ADDRESS_H -#define SPX_ADDRESS_H - -#include - -#include "params.h" - -/* The hash types that are passed to set_type */ -#define SPX_ADDR_TYPE_WOTS 0 -#define SPX_ADDR_TYPE_WOTSPK 1 -#define SPX_ADDR_TYPE_HASHTREE 2 -#define SPX_ADDR_TYPE_FORSTREE 3 -#define SPX_ADDR_TYPE_FORSPK 4 -#define SPX_ADDR_TYPE_WOTSPRF 5 -#define SPX_ADDR_TYPE_FORSPRF 6 - -#define set_layer_addr SPX_NAMESPACE(set_layer_addr) -void set_layer_addr(uint32_t addr[8], uint32_t layer); - -#define set_tree_addr SPX_NAMESPACE(set_tree_addr) -void set_tree_addr(uint32_t addr[8], uint64_t tree); - -#define set_type SPX_NAMESPACE(set_type) -void set_type(uint32_t addr[8], uint32_t type); - -/* Copies the layer and tree part of one address into the other */ -#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) -void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for WOTS and FORS addresses. */ - -#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) -void set_keypair_addr(uint32_t addr[8], uint32_t keypair); - -#define set_chain_addr SPX_NAMESPACE(set_chain_addr) -void set_chain_addr(uint32_t addr[8], uint32_t chain); - -#define set_hash_addr SPX_NAMESPACE(set_hash_addr) -void set_hash_addr(uint32_t addr[8], uint32_t hash); - -#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) -void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for all hash tree addresses (including FORS). */ - -#define set_tree_height SPX_NAMESPACE(set_tree_height) -void set_tree_height(uint32_t addr[8], uint32_t tree_height); - -#define set_tree_index SPX_NAMESPACE(set_tree_index) -void set_tree_index(uint32_t addr[8], uint32_t tree_index); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/api.h b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/api.h deleted file mode 100644 index 546545b0c1..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/api.h +++ /dev/null @@ -1,77 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA2192FROBUST_AVX2_API_H -#define PQCLEAN_SPHINCSSHA2192FROBUST_AVX2_API_H - -#include -#include - -#define PQCLEAN_SPHINCSSHA2192FROBUST_AVX2_CRYPTO_ALGNAME "SPHINCS+-sha2-192f-robust" - -#define PQCLEAN_SPHINCSSHA2192FROBUST_AVX2_CRYPTO_SECRETKEYBYTES 96 -#define PQCLEAN_SPHINCSSHA2192FROBUST_AVX2_CRYPTO_PUBLICKEYBYTES 48 -#define PQCLEAN_SPHINCSSHA2192FROBUST_AVX2_CRYPTO_BYTES 35664 - -#define PQCLEAN_SPHINCSSHA2192FROBUST_AVX2_CRYPTO_SEEDBYTES 72 - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSSHA2192FROBUST_AVX2_crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSSHA2192FROBUST_AVX2_crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSSHA2192FROBUST_AVX2_crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSSHA2192FROBUST_AVX2_crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHA2192FROBUST_AVX2_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHA2192FROBUST_AVX2_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSSHA2192FROBUST_AVX2_crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSSHA2192FROBUST_AVX2_crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, - const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSSHA2192FROBUST_AVX2_crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSSHA2192FROBUST_AVX2_crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk); -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/context.h b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/context.h deleted file mode 100644 index d3bf1c3aac..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/context.h +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef SPX_CONTEXT_H -#define SPX_CONTEXT_H - -#include - -#include "params.h" -#include "sha2.h" -#include "sha256avx.h" -#include "sha512x4.h" - -// funky ordering due to optimal padding -typedef struct { - sha256x8ctx statex8_seeded; - sha512x4ctx statex4_seeded_512; - sha256ctx state_seeded; - sha512ctx state_seeded_512; - - uint8_t pub_seed[SPX_N]; - uint8_t sk_seed[SPX_N]; -} spx_ctx; - - -#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) -void initialize_hash_function(spx_ctx *ctx); - -#define free_hash_function SPX_NAMESPACE(free_hash_function) -void free_hash_function(spx_ctx *ctx); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/context_sha2.c b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/context_sha2.c deleted file mode 100644 index 83c1b6585d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/context_sha2.c +++ /dev/null @@ -1,56 +0,0 @@ -#include - -#include "context.h" - -/** - * Absorb the constant pub_seed using one round of the compression function - * This initializes state_seeded and state_seeded_512, which can then be - * reused in thash - **/ -static void seed_state(spx_ctx *ctx) { - uint8_t block[SPX_SHA512_BLOCK_BYTES]; - size_t i; - - for (i = 0; i < SPX_N; ++i) { - block[i] = ctx->pub_seed[i]; - } - for (i = SPX_N; i < SPX_SHA512_BLOCK_BYTES; ++i) { - block[i] = 0; - } - /* block has been properly initialized for both SHA-256 and SHA-512 */ - - sha256_inc_init(&ctx->state_seeded); - sha256_inc_blocks(&ctx->state_seeded, block, 1); - - // initialize x8 - sha256_init8x(&ctx->statex8_seeded); - sha256_transform8x(&ctx->statex8_seeded, - block, block, block, block, block, block, block, block); - - ctx->statex8_seeded.datalen = 0; - ctx->statex8_seeded.msglen = 512; - - sha512_inc_init(&ctx->state_seeded_512); - sha512_inc_blocks(&ctx->state_seeded_512, block, 1); - - // initialize x4 - sha512_init4x(&ctx->statex4_seeded_512); - sha512_transform4x(&ctx->statex4_seeded_512, block, block, block, block); - - ctx->statex4_seeded_512.datalen = 0; - ctx->statex4_seeded_512.msglen = 1024; - - -} - - -/* For SHA, we initialize the hash function at the start */ -void initialize_hash_function(spx_ctx *ctx) { - seed_state(ctx); -} - -/* Free the incremental hashing context for heap-based SHA2 APIs */ -void free_hash_function(spx_ctx *ctx) { - sha256_inc_ctx_release(&ctx->state_seeded); - sha512_inc_ctx_release(&ctx->state_seeded_512); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/fors.c b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/fors.c deleted file mode 100644 index 4cab8e7415..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/fors.c +++ /dev/null @@ -1,226 +0,0 @@ -#include -#include -#include - -#include "fors.h" - - -#include "address.h" -#include "hash.h" -#include "hashx8.h" -#include "thash.h" -#include "thashx8.h" -#include "utils.h" -#include "utilsx8.h" -static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, - uint32_t fors_leaf_addr[8]) { - prf_addr(sk, ctx, fors_leaf_addr); -} - -static void fors_gen_skx8(unsigned char *sk0, - unsigned char *sk1, - unsigned char *sk2, - unsigned char *sk3, - unsigned char *sk4, - unsigned char *sk5, - unsigned char *sk6, - unsigned char *sk7, const spx_ctx *ctx, - uint32_t fors_leaf_addrx8[8 * 8]) { - prf_addrx8(sk0, sk1, sk2, sk3, sk4, sk5, sk6, sk7, - ctx, fors_leaf_addrx8); -} - -static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, - const spx_ctx *ctx, - uint32_t fors_leaf_addr[8]) { - thash(leaf, sk, 1, ctx, fors_leaf_addr); -} - -static void fors_sk_to_leafx8(unsigned char *leaf0, - unsigned char *leaf1, - unsigned char *leaf2, - unsigned char *leaf3, - unsigned char *leaf4, - unsigned char *leaf5, - unsigned char *leaf6, - unsigned char *leaf7, - const unsigned char *sk0, - const unsigned char *sk1, - const unsigned char *sk2, - const unsigned char *sk3, - const unsigned char *sk4, - const unsigned char *sk5, - const unsigned char *sk6, - const unsigned char *sk7, - const spx_ctx *ctx, - uint32_t fors_leaf_addrx8[8 * 8]) { - thashx8(leaf0, leaf1, leaf2, leaf3, leaf4, leaf5, leaf6, leaf7, - sk0, sk1, sk2, sk3, sk4, sk5, sk6, sk7, - 1, ctx, fors_leaf_addrx8); -} - -struct fors_gen_leaf_info { - uint32_t leaf_addrx[8 * 8]; -}; - -static void fors_gen_leafx8(unsigned char *leaf, - const spx_ctx *ctx, - uint32_t addr_idx, void *info) { - struct fors_gen_leaf_info *fors_info = info; - uint32_t *fors_leaf_addrx8 = fors_info->leaf_addrx; - unsigned int j; - - /* Only set the parts that the caller doesn't set */ - for (j = 0; j < 8; j++) { - set_tree_index(fors_leaf_addrx8 + j * 8, addr_idx + j); - set_type(fors_leaf_addrx8 + j * 8, SPX_ADDR_TYPE_FORSPRF); - } - - fors_gen_skx8(leaf + 0 * SPX_N, - leaf + 1 * SPX_N, - leaf + 2 * SPX_N, - leaf + 3 * SPX_N, - leaf + 4 * SPX_N, - leaf + 5 * SPX_N, - leaf + 6 * SPX_N, - leaf + 7 * SPX_N, - ctx, fors_leaf_addrx8); - - for (j = 0; j < 8; j++) { - set_type(fors_leaf_addrx8 + j * 8, SPX_ADDR_TYPE_FORSTREE); - } - - fors_sk_to_leafx8(leaf + 0 * SPX_N, - leaf + 1 * SPX_N, - leaf + 2 * SPX_N, - leaf + 3 * SPX_N, - leaf + 4 * SPX_N, - leaf + 5 * SPX_N, - leaf + 6 * SPX_N, - leaf + 7 * SPX_N, - leaf + 0 * SPX_N, - leaf + 1 * SPX_N, - leaf + 2 * SPX_N, - leaf + 3 * SPX_N, - leaf + 4 * SPX_N, - leaf + 5 * SPX_N, - leaf + 6 * SPX_N, - leaf + 7 * SPX_N, - ctx, fors_leaf_addrx8); -} - -/** - * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - * Assumes indices has space for SPX_FORS_TREES integers. - */ -static void message_to_indices(uint32_t *indices, const unsigned char *m) { - unsigned int i, j; - unsigned int offset = 0; - - for (i = 0; i < SPX_FORS_TREES; i++) { - indices[i] = 0; - for (j = 0; j < SPX_FORS_HEIGHT; j++) { - indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); - offset++; - } - } -} - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -void fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]) { - uint32_t indices[SPX_FORS_TREES]; - unsigned char roots[SPX_FORS_TREES * SPX_N]; - uint32_t fors_tree_addr[8 * 8] = {0}; - struct fors_gen_leaf_info fors_info = {0}; - uint32_t *fors_leaf_addr = fors_info.leaf_addrx; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - for (i = 0; i < 8; i++) { - copy_keypair_addr(fors_tree_addr + 8 * i, fors_addr); - set_type(fors_tree_addr + 8 * i, SPX_ADDR_TYPE_FORSTREE); - copy_keypair_addr(fors_leaf_addr + 8 * i, fors_addr); - } - copy_keypair_addr(fors_pk_addr, fors_addr); - set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < SPX_FORS_TREES; i++) { - idx_offset = i * (1 << SPX_FORS_HEIGHT); - - set_tree_height(fors_tree_addr, 0); - set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Include the secret key part that produces the selected leaf node. */ - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); - fors_gen_sk(sig, ctx, fors_tree_addr); - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); - sig += SPX_N; - - /* Compute the authentication path for this leaf node. */ - treehashx8(roots + i * SPX_N, sig, ctx, - indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx8, - fors_tree_addr, &fors_info); - - sig += SPX_N * SPX_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); -} - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -void fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]) { - uint32_t indices[SPX_FORS_TREES]; - unsigned char roots[SPX_FORS_TREES * SPX_N]; - unsigned char leaf[SPX_N]; - uint32_t fors_tree_addr[8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - copy_keypair_addr(fors_tree_addr, fors_addr); - copy_keypair_addr(fors_pk_addr, fors_addr); - - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); - set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < SPX_FORS_TREES; i++) { - idx_offset = i * (1 << SPX_FORS_HEIGHT); - - set_tree_height(fors_tree_addr, 0); - set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Derive the leaf from the included secret key part. */ - fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); - sig += SPX_N; - - /* Derive the corresponding root node of this tree. */ - compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, - sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); - sig += SPX_N * SPX_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/fors.h b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/fors.h deleted file mode 100644 index 509140a178..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/fors.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef SPX_FORS_H -#define SPX_FORS_H - -#include - -#include "context.h" -#include "params.h" - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -#define fors_sign SPX_NAMESPACE(fors_sign) -void fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]); - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) -void fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/hash.h b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/hash.h deleted file mode 100644 index ffe815f45d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/hash.h +++ /dev/null @@ -1,37 +0,0 @@ -#ifndef SPX_HASH_H -#define SPX_HASH_H - -#include -#include - -#include "context.h" -#include "params.h" - -#define prf_addr SPX_NAMESPACE(prf_addr) -void prf_addr(unsigned char *out, const spx_ctx *ctx, - const uint32_t addr[8]); - -#define gen_message_random SPX_NAMESPACE(gen_message_random) -void gen_message_random(unsigned char *R, const unsigned char *sk_prf, - const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx); - -#define hash_message SPX_NAMESPACE(hash_message) -void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx); - - -# define SPX_SHA256_ADDR_BYTES 22 - -# define mgf1_256 SPX_NAMESPACE(mgf1_256) -void mgf1_256(unsigned char *out, unsigned long outlen, - const unsigned char *in, unsigned long inlen); - -# define mgf1_512 SPX_NAMESPACE(mgf1_512) -void mgf1_512(unsigned char *out, unsigned long outlen, - const unsigned char *in, unsigned long inlen); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/hash_sha2.c b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/hash_sha2.c deleted file mode 100644 index 3d0085c8c1..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/hash_sha2.c +++ /dev/null @@ -1,219 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "sha2.h" -#include "utils.h" - - - -#define SPX_SHAX_OUTPUT_BYTES SPX_SHA512_OUTPUT_BYTES -#define SPX_SHAX_BLOCK_BYTES SPX_SHA512_BLOCK_BYTES -#define shaX_inc_init sha512_inc_init -#define shaX_inc_blocks sha512_inc_blocks -#define shaX_inc_finalize sha512_inc_finalize -#define shaX sha512 -#define mgf1_X mgf1_512 -#define shaXstate sha512ctx - -/** - * mgf1 function based on the SHA-256 hash function - * Note that inlen should be sufficiently small that it still allows for - * an array to be allocated on the stack. Typically 'in' is merely a seed. - * Outputs outlen number of bytes - */ -void mgf1_256(unsigned char *out, unsigned long outlen, - const unsigned char *in, unsigned long inlen) { - PQCLEAN_VLA(uint8_t, inbuf, inlen + 4); - unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES]; - uint32_t i; - - memcpy(inbuf, in, inlen); - - /* While we can fit in at least another full block of SHA256 output.. */ - for (i = 0; (i + 1)*SPX_SHA256_OUTPUT_BYTES <= outlen; i++) { - u32_to_bytes(inbuf + inlen, i); - sha256(out, inbuf, inlen + 4); - out += SPX_SHA256_OUTPUT_BYTES; - } - /* Until we cannot anymore, and we fill the remainder. */ - if (outlen > i * SPX_SHA256_OUTPUT_BYTES) { - u32_to_bytes(inbuf + inlen, i); - sha256(outbuf, inbuf, inlen + 4); - memcpy(out, outbuf, outlen - i * SPX_SHA256_OUTPUT_BYTES); - } -} - -/* - * mgf1 function based on the SHA-512 hash function - */ -void mgf1_512(unsigned char *out, unsigned long outlen, - const unsigned char *in, unsigned long inlen) { - PQCLEAN_VLA(uint8_t, inbuf, inlen + 4); - unsigned char outbuf[SPX_SHA512_OUTPUT_BYTES]; - uint32_t i; - - memcpy(inbuf, in, inlen); - - /* While we can fit in at least another full block of SHA512 output.. */ - for (i = 0; (i + 1)*SPX_SHA512_OUTPUT_BYTES <= outlen; i++) { - u32_to_bytes(inbuf + inlen, i); - sha512(out, inbuf, inlen + 4); - out += SPX_SHA512_OUTPUT_BYTES; - } - /* Until we cannot anymore, and we fill the remainder. */ - if (outlen > i * SPX_SHA512_OUTPUT_BYTES) { - u32_to_bytes(inbuf + inlen, i); - sha512(outbuf, inbuf, inlen + 4); - memcpy(out, outbuf, outlen - i * SPX_SHA512_OUTPUT_BYTES); - } -} - -/* - * Computes PRF(pk_seed, sk_seed, addr). - */ -void prf_addr(unsigned char *out, const spx_ctx *ctx, - const uint32_t addr[8]) { - sha256ctx sha2_state; - unsigned char buf[SPX_SHA256_ADDR_BYTES + SPX_N]; - unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES]; - - /* Retrieve precomputed state containing pub_seed */ - sha256_inc_ctx_clone(&sha2_state, &ctx->state_seeded); - - /* Remainder: ADDR^c ‖ SK.seed */ - memcpy(buf, addr, SPX_SHA256_ADDR_BYTES); - memcpy(buf + SPX_SHA256_ADDR_BYTES, ctx->sk_seed, SPX_N); - - sha256_inc_finalize(outbuf, &sha2_state, buf, SPX_SHA256_ADDR_BYTES + SPX_N); - - memcpy(out, outbuf, SPX_N); -} - -/** - * Computes the message-dependent randomness R, using a secret seed as a key - * for HMAC, and an optional randomization value prefixed to the message. - * This requires m to have at least SPX_SHAX_BLOCK_BYTES + SPX_N space - * available in front of the pointer, i.e. before the message to use for the - * prefix. This is necessary to prevent having to move the message around (and - * allocate memory for it). - */ -void gen_message_random(unsigned char *R, const unsigned char *sk_prf, - const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx) { - (void)ctx; - - unsigned char buf[SPX_SHAX_BLOCK_BYTES + SPX_SHAX_OUTPUT_BYTES]; - shaXstate state; - int i; - - - /* This implements HMAC-SHA */ - for (i = 0; i < SPX_N; i++) { - buf[i] = 0x36 ^ sk_prf[i]; - } - memset(buf + SPX_N, 0x36, SPX_SHAX_BLOCK_BYTES - SPX_N); - - shaX_inc_init(&state); - shaX_inc_blocks(&state, buf, 1); - - memcpy(buf, optrand, SPX_N); - - /* If optrand + message cannot fill up an entire block */ - if (SPX_N + mlen < SPX_SHAX_BLOCK_BYTES) { - memcpy(buf + SPX_N, m, mlen); - shaX_inc_finalize(buf + SPX_SHAX_BLOCK_BYTES, &state, - buf, mlen + SPX_N); - } - /* Otherwise first fill a block, so that finalize only uses the message */ - else { - memcpy(buf + SPX_N, m, SPX_SHAX_BLOCK_BYTES - SPX_N); - shaX_inc_blocks(&state, buf, 1); - - m += SPX_SHAX_BLOCK_BYTES - SPX_N; - mlen -= SPX_SHAX_BLOCK_BYTES - SPX_N; - shaX_inc_finalize(buf + SPX_SHAX_BLOCK_BYTES, &state, m, mlen); - } - - for (i = 0; i < SPX_N; i++) { - buf[i] = 0x5c ^ sk_prf[i]; - } - memset(buf + SPX_N, 0x5c, SPX_SHAX_BLOCK_BYTES - SPX_N); - - shaX(buf, buf, SPX_SHAX_BLOCK_BYTES + SPX_SHAX_OUTPUT_BYTES); - memcpy(R, buf, SPX_N); -} - -/** - * Computes the message hash using R, the public key, and the message. - * Outputs the message digest and the index of the leaf. The index is split in - * the tree index and the leaf index, for convenient copying to an address. - */ -void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx) { - (void)ctx; -#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) -#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) -#define SPX_LEAF_BITS SPX_TREE_HEIGHT -#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) -#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) - - unsigned char seed[2 * SPX_N + SPX_SHAX_OUTPUT_BYTES]; - - /* Round to nearest multiple of SPX_SHAX_BLOCK_BYTES */ -#define SPX_INBLOCKS (((SPX_N + SPX_PK_BYTES + SPX_SHAX_BLOCK_BYTES - 1) & \ - -SPX_SHAX_BLOCK_BYTES) / SPX_SHAX_BLOCK_BYTES) - unsigned char inbuf[SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES]; - - unsigned char buf[SPX_DGST_BYTES]; - unsigned char *bufp = buf; - shaXstate state; - - shaX_inc_init(&state); - - // seed: SHA-X(R ‖ PK.seed ‖ PK.root ‖ M) - memcpy(inbuf, R, SPX_N); - memcpy(inbuf + SPX_N, pk, SPX_PK_BYTES); - - /* If R + pk + message cannot fill up an entire block */ - if (SPX_N + SPX_PK_BYTES + mlen < SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES) { - memcpy(inbuf + SPX_N + SPX_PK_BYTES, m, mlen); - shaX_inc_finalize(seed + 2 * SPX_N, &state, inbuf, SPX_N + SPX_PK_BYTES + mlen); - } - /* Otherwise first fill a block, so that finalize only uses the message */ - else { - memcpy(inbuf + SPX_N + SPX_PK_BYTES, m, - SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES - SPX_N - SPX_PK_BYTES); - shaX_inc_blocks(&state, inbuf, SPX_INBLOCKS); - - m += SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES - SPX_N - SPX_PK_BYTES; - mlen -= SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES - SPX_N - SPX_PK_BYTES; - shaX_inc_finalize(seed + 2 * SPX_N, &state, m, (size_t)mlen); - } - - // H_msg: MGF1-SHA-X(R ‖ PK.seed ‖ seed) - memcpy(seed, R, SPX_N); - memcpy(seed + SPX_N, pk, SPX_N); - - /* By doing this in two steps, we prevent hashing the message twice; - otherwise each iteration in MGF1 would hash the message again. */ - mgf1_X(bufp, SPX_DGST_BYTES, seed, 2 * SPX_N + SPX_SHAX_OUTPUT_BYTES); - - memcpy(digest, bufp, SPX_FORS_MSG_BYTES); - bufp += SPX_FORS_MSG_BYTES; - - - *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); - *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); - bufp += SPX_TREE_BYTES; - - *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); - *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); -} - - diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/hash_sha2x8.c b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/hash_sha2x8.c deleted file mode 100644 index e04af7a069..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/hash_sha2x8.c +++ /dev/null @@ -1,75 +0,0 @@ -#include -#include - -#include "hash.h" -#include "hashx8.h" - -#include "address.h" -#include "params.h" -#include "sha2.h" -#include "sha256avx.h" -#include "sha256x8.h" -#include "utils.h" - -/* - * 8-way parallel version of prf_addr; takes 8x as much input and output - */ -void prf_addrx8(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7, - const spx_ctx *ctx, - const uint32_t addrx8[8 * 8]) { - unsigned char bufx8[8 * (SPX_N + SPX_SHA256_ADDR_BYTES)]; - unsigned char outbufx8[8 * SPX_SHA256_OUTPUT_BYTES]; - unsigned int j; - - for (j = 0; j < 8; j++) { - memcpy(bufx8 + j * (SPX_N + SPX_SHA256_ADDR_BYTES), - addrx8 + j * 8, SPX_SHA256_ADDR_BYTES); - memcpy( - bufx8 + j * (SPX_N + SPX_SHA256_ADDR_BYTES) + SPX_SHA256_ADDR_BYTES, - ctx->sk_seed, - SPX_N - ); - } - - sha256x8_seeded( - /* out */ - outbufx8 + 0 * SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 1 * SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 2 * SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 3 * SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 4 * SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 5 * SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 6 * SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 7 * SPX_SHA256_OUTPUT_BYTES, - - /* seed */ - &ctx->statex8_seeded, - - /* in */ - bufx8 + 0 * (SPX_SHA256_ADDR_BYTES + SPX_N), - bufx8 + 1 * (SPX_SHA256_ADDR_BYTES + SPX_N), - bufx8 + 2 * (SPX_SHA256_ADDR_BYTES + SPX_N), - bufx8 + 3 * (SPX_SHA256_ADDR_BYTES + SPX_N), - bufx8 + 4 * (SPX_SHA256_ADDR_BYTES + SPX_N), - bufx8 + 5 * (SPX_SHA256_ADDR_BYTES + SPX_N), - bufx8 + 6 * (SPX_SHA256_ADDR_BYTES + SPX_N), - bufx8 + 7 * (SPX_SHA256_ADDR_BYTES + SPX_N), - SPX_SHA256_ADDR_BYTES + SPX_N /* len */ - ); - - memcpy(out0, outbufx8 + 0 * SPX_SHA256_OUTPUT_BYTES, SPX_N); - memcpy(out1, outbufx8 + 1 * SPX_SHA256_OUTPUT_BYTES, SPX_N); - memcpy(out2, outbufx8 + 2 * SPX_SHA256_OUTPUT_BYTES, SPX_N); - memcpy(out3, outbufx8 + 3 * SPX_SHA256_OUTPUT_BYTES, SPX_N); - memcpy(out4, outbufx8 + 4 * SPX_SHA256_OUTPUT_BYTES, SPX_N); - memcpy(out5, outbufx8 + 5 * SPX_SHA256_OUTPUT_BYTES, SPX_N); - memcpy(out6, outbufx8 + 6 * SPX_SHA256_OUTPUT_BYTES, SPX_N); - memcpy(out7, outbufx8 + 7 * SPX_SHA256_OUTPUT_BYTES, SPX_N); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/hashx8.h b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/hashx8.h deleted file mode 100644 index 46503f0a10..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/hashx8.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef SPX_HASHX8_H -#define SPX_HASHX8_H - -#include - -#include "params.h" - -#define prf_addrx8 SPX_NAMESPACE(prf_addrx8) -void prf_addrx8(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7, - const spx_ctx *ctx, - const uint32_t addrx8[8 * 8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/merkle.c b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/merkle.c deleted file mode 100644 index 1f353c8dd8..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/merkle.c +++ /dev/null @@ -1,65 +0,0 @@ -#include -#include - -#include "merkle.h" - -#include "address.h" -#include "params.h" -#include "utils.h" -#include "utilsx8.h" -#include "wots.h" -#include "wotsx8.h" - -/* - * This generates a Merkle signature (WOTS signature followed by the Merkle - * authentication path). - */ -void merkle_sign(uint8_t *sig, unsigned char *root, - const spx_ctx *ctx, - uint32_t wots_addr[8], uint32_t tree_addr[8], - uint32_t idx_leaf) { - unsigned char *auth_path = sig + SPX_WOTS_BYTES; - uint32_t tree_addrx8[8 * 8] = { 0 }; - int j; - struct leaf_info_x8 info = { 0 }; - unsigned steps[ SPX_WOTS_LEN ]; - - info.wots_sig = sig; - chain_lengths(steps, root); - info.wots_steps = steps; - - for (j = 0; j < 8; j++) { - set_type(&tree_addrx8[8 * j], SPX_ADDR_TYPE_HASHTREE); - set_type(&info.leaf_addr[8 * j], SPX_ADDR_TYPE_WOTS); - set_type(&info.pk_addr[8 * j], SPX_ADDR_TYPE_WOTSPK); - copy_subtree_addr(&tree_addrx8[8 * j], tree_addr); - copy_subtree_addr(&info.leaf_addr[8 * j], wots_addr); - copy_subtree_addr(&info.pk_addr[8 * j], wots_addr); - } - - info.wots_sign_leaf = idx_leaf; - - treehashx8(root, auth_path, ctx, - idx_leaf, 0, - SPX_TREE_HEIGHT, - wots_gen_leafx8, - tree_addrx8, &info); -} - -/* Compute root node of the top-most subtree. */ -/* Again, in this file because wots_gen_leaf is most of the work */ -void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { - /* We do not need the auth path in key generation, but it simplifies the - code to have just one treehash routine that computes both root and path - in one function. */ - unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; - uint32_t top_tree_addr[8] = {0}; - uint32_t wots_addr[8] = {0}; - - set_layer_addr(top_tree_addr, SPX_D - 1); - set_layer_addr(wots_addr, SPX_D - 1); - - merkle_sign(auth_path, root, ctx, - wots_addr, top_tree_addr, - ~0U /* ~0 means "don't bother generating an auth path */ ); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/merkle.h b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/merkle.h deleted file mode 100644 index 769cf2e970..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/merkle.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef MERKLE_H_ -#define MERKLE_H_ - -#include - -#include "context.h" -#include "params.h" - -/* Generate a Merkle signature (WOTS signature followed by the Merkle */ -/* authentication path) */ -#define merkle_sign SPX_NAMESPACE(merkle_sign) -void merkle_sign(uint8_t *sig, unsigned char *root, - const spx_ctx *ctx, - uint32_t wots_addr[8], uint32_t tree_addr[8], - uint32_t idx_leaf); - -/* Compute the root node of the top-most subtree. */ -#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) -void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); - -#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/nistapi.h b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/nistapi.h deleted file mode 100644 index 3cb71afad4..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/nistapi.h +++ /dev/null @@ -1,87 +0,0 @@ -#ifndef SPX_API_H -#define SPX_API_H - -#include -#include - -#include "params.h" - -#define CRYPTO_ALGNAME "SPHINCS+" - -#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES -#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES -#define CRYPTO_BYTES SPX_BYTES -#define CRYPTO_SEEDBYTES (3*SPX_N) - -/* - * Returns the length of a secret key, in bytes - */ -#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) -size_t crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) -size_t crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) -size_t crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) -size_t crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) -int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) -int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) -int crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) -int crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -#define crypto_sign SPX_NAMESPACE(crypto_sign) -int crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) -int crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/params.h b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/params.h deleted file mode 100644 index c13415ac1c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/params.h +++ /dev/null @@ -1,61 +0,0 @@ -#ifndef SPX_PARAMS_H -#define SPX_PARAMS_H - -#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSSHA2192FROBUST_AVX2_##s - -/* Hash output length in bytes. */ -#define SPX_N 24 -/* Height of the hypertree. */ -#define SPX_FULL_HEIGHT 66 -/* Number of subtree layer. */ -#define SPX_D 22 -/* FORS tree dimensions. */ -#define SPX_FORS_HEIGHT 8 -#define SPX_FORS_TREES 33 -/* Winternitz parameter, */ -#define SPX_WOTS_W 16 - -/* The hash function is defined by linking a different hash.c file, as opposed - to setting a #define constant. */ - -/* This is a SHA2-based parameter set, hence whether we use SHA-256 - * exclusively or we use both SHA-256 and SHA-512 is controlled by - * the following #define */ -#define SPX_SHA512 1 /* Use SHA-512 for H and T_l, l >= 2 */ - -/* For clarity */ -#define SPX_ADDR_BYTES 32 - -/* WOTS parameters. */ -#define SPX_WOTS_LOGW 4 - -#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) - -/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#define SPX_WOTS_LEN2 3 - -#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) -#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) -#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES - -/* Subtree size. */ -#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) - -//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT -// #error SPX_D should always divide SPX_FULL_HEIGHT -//#endif - -/* FORS parameters. */ -#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) -#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) -#define SPX_FORS_PK_BYTES SPX_N - -/* Resulting SPX sizes. */ -#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ - SPX_FULL_HEIGHT * SPX_N) -#define SPX_PK_BYTES (2 * SPX_N) -#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) - -#include "sha2_offsets.h" - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/sha256avx.c b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/sha256avx.c deleted file mode 100644 index 6bbe6ecc24..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/sha256avx.c +++ /dev/null @@ -1,357 +0,0 @@ -#include -#include -#include - -#include "sha256avx.h" - -static const unsigned int RC[] = { - 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, - 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, - 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, - 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, - 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, - 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, - 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, - 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, - 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, - 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, - 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, - 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, - 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, - 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, - 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, - 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 -}; - -#define u32 uint32_t -#define u256 __m256i - -#define XOR _mm256_xor_si256 -#define OR _mm256_or_si256 -#define AND _mm256_and_si256 -#define ADD32 _mm256_add_epi32 -#define NOT(x) _mm256_xor_si256(x, _mm256_set_epi32(-1, -1, -1, -1, -1, -1, -1, -1)) - -#define LOAD(src) _mm256_loadu_si256((__m256i *)(src)) -#define STORE(dest,src) _mm256_storeu_si256((__m256i *)(dest),src) - -#define BYTESWAP(x) _mm256_shuffle_epi8(x, _mm256_set_epi8(0xc,0xd,0xe,0xf,0x8,0x9,0xa,0xb,0x4,0x5,0x6,0x7,0x0,0x1,0x2,0x3,0xc,0xd,0xe,0xf,0x8,0x9,0xa,0xb,0x4,0x5,0x6,0x7,0x0,0x1,0x2,0x3)) - -#define SHIFTR32(x, y) _mm256_srli_epi32(x, y) -#define SHIFTL32(x, y) _mm256_slli_epi32(x, y) - -#define ROTR32(x, y) OR(SHIFTR32(x, y), SHIFTL32(x, 32 - (y))) -#define ROTL32(x, y) OR(SHIFTL32(x, y), SHIFTR32(x, 32 - (y))) - -#define XOR3(a, b, c) XOR(XOR(a, b), c) - -#define ADD3_32(a, b, c) ADD32(ADD32(a, b), c) -#define ADD4_32(a, b, c, d) ADD32(ADD32(ADD32(a, b), c), d) -#define ADD5_32(a, b, c, d, e) ADD32(ADD32(ADD32(ADD32(a, b), c), d), e) - -#define MAJ_AVX(a, b, c) XOR3(AND(a, b), AND(a, c), AND(b, c)) -#define CH_AVX(a, b, c) XOR(AND(a, b), AND(NOT(a), c)) - -#define SIGMA1_AVX(x) XOR3(ROTR32(x, 6), ROTR32(x, 11), ROTR32(x, 25)) -#define SIGMA0_AVX(x) XOR3(ROTR32(x, 2), ROTR32(x, 13), ROTR32(x, 22)) - -#define WSIGMA1_AVX(x) XOR3(ROTR32(x, 17), ROTR32(x, 19), SHIFTR32(x, 10)) -#define WSIGMA0_AVX(x) XOR3(ROTR32(x, 7), ROTR32(x, 18), SHIFTR32(x, 3)) - -#define SHA256ROUND_AVX(a, b, c, d, e, f, g, h, rc, w) \ - T0 = ADD5_32(h, SIGMA1_AVX(e), CH_AVX(e, f, g), _mm256_set1_epi32((int)RC[rc]), w); \ - (d) = ADD32(d, T0); \ - T1 = ADD32(SIGMA0_AVX(a), MAJ_AVX(a, b, c)); \ - (h) = ADD32(T0, T1); - -// Transpose 8 vectors containing 32-bit values -static void transpose(u256 s[8]) { - u256 tmp0[8]; - u256 tmp1[8]; - tmp0[0] = _mm256_unpacklo_epi32(s[0], s[1]); - tmp0[1] = _mm256_unpackhi_epi32(s[0], s[1]); - tmp0[2] = _mm256_unpacklo_epi32(s[2], s[3]); - tmp0[3] = _mm256_unpackhi_epi32(s[2], s[3]); - tmp0[4] = _mm256_unpacklo_epi32(s[4], s[5]); - tmp0[5] = _mm256_unpackhi_epi32(s[4], s[5]); - tmp0[6] = _mm256_unpacklo_epi32(s[6], s[7]); - tmp0[7] = _mm256_unpackhi_epi32(s[6], s[7]); - tmp1[0] = _mm256_unpacklo_epi64(tmp0[0], tmp0[2]); - tmp1[1] = _mm256_unpackhi_epi64(tmp0[0], tmp0[2]); - tmp1[2] = _mm256_unpacklo_epi64(tmp0[1], tmp0[3]); - tmp1[3] = _mm256_unpackhi_epi64(tmp0[1], tmp0[3]); - tmp1[4] = _mm256_unpacklo_epi64(tmp0[4], tmp0[6]); - tmp1[5] = _mm256_unpackhi_epi64(tmp0[4], tmp0[6]); - tmp1[6] = _mm256_unpacklo_epi64(tmp0[5], tmp0[7]); - tmp1[7] = _mm256_unpackhi_epi64(tmp0[5], tmp0[7]); - s[0] = _mm256_permute2x128_si256(tmp1[0], tmp1[4], 0x20); - s[1] = _mm256_permute2x128_si256(tmp1[1], tmp1[5], 0x20); - s[2] = _mm256_permute2x128_si256(tmp1[2], tmp1[6], 0x20); - s[3] = _mm256_permute2x128_si256(tmp1[3], tmp1[7], 0x20); - s[4] = _mm256_permute2x128_si256(tmp1[0], tmp1[4], 0x31); - s[5] = _mm256_permute2x128_si256(tmp1[1], tmp1[5], 0x31); - s[6] = _mm256_permute2x128_si256(tmp1[2], tmp1[6], 0x31); - s[7] = _mm256_permute2x128_si256(tmp1[3], tmp1[7], 0x31); -} - -void sha256_ctx_clone8x(sha256x8ctx *out, const sha256x8ctx *in) { - memcpy(out, in, sizeof(sha256x8ctx)); -} - -void sha256_init8x(sha256x8ctx *ctx) { - ctx->s[0] = _mm256_set_epi32((int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667); - ctx->s[1] = _mm256_set_epi32((int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85); - ctx->s[2] = _mm256_set_epi32((int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372); - ctx->s[3] = _mm256_set_epi32((int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a); - ctx->s[4] = _mm256_set_epi32((int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f); - ctx->s[5] = _mm256_set_epi32((int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c); - ctx->s[6] = _mm256_set_epi32((int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab); - ctx->s[7] = _mm256_set_epi32((int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19); - - ctx->datalen = 0; - ctx->msglen = 0; -} - -void sha256_final8x(sha256x8ctx *ctx, - unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7) { - unsigned int i, curlen; - - // Padding - if (ctx->datalen < 56) { - for (i = 0; i < 8; ++i) { - curlen = ctx->datalen; - ctx->msgblocks[64 * i + curlen++] = 0x80; - while (curlen < 64) { - ctx->msgblocks[64 * i + curlen++] = 0x00; - } - } - } else { - for (i = 0; i < 8; ++i) { - curlen = ctx->datalen; - ctx->msgblocks[64 * i + curlen++] = 0x80; - while (curlen < 64) { - ctx->msgblocks[64 * i + curlen++] = 0x00; - } - } - sha256_transform8x(ctx, - &ctx->msgblocks[64 * 0], - &ctx->msgblocks[64 * 1], - &ctx->msgblocks[64 * 2], - &ctx->msgblocks[64 * 3], - &ctx->msgblocks[64 * 4], - &ctx->msgblocks[64 * 5], - &ctx->msgblocks[64 * 6], - &ctx->msgblocks[64 * 7] - ); - memset(ctx->msgblocks, 0, 8 * 64); - } - - // Add length of the message to each block - ctx->msglen += ctx->datalen * 8; - for (i = 0; i < 8; i++) { - ctx->msgblocks[64 * i + 63] = (unsigned char)(ctx->msglen); - ctx->msgblocks[64 * i + 62] = (unsigned char)(ctx->msglen >> 8); - ctx->msgblocks[64 * i + 61] = (unsigned char)(ctx->msglen >> 16); - ctx->msgblocks[64 * i + 60] = (unsigned char)(ctx->msglen >> 24); - ctx->msgblocks[64 * i + 59] = (unsigned char)(ctx->msglen >> 32); - ctx->msgblocks[64 * i + 58] = (unsigned char)(ctx->msglen >> 40); - ctx->msgblocks[64 * i + 57] = (unsigned char)(ctx->msglen >> 48); - ctx->msgblocks[64 * i + 56] = (unsigned char)(ctx->msglen >> 56); - } - sha256_transform8x(ctx, - &ctx->msgblocks[64 * 0], - &ctx->msgblocks[64 * 1], - &ctx->msgblocks[64 * 2], - &ctx->msgblocks[64 * 3], - &ctx->msgblocks[64 * 4], - &ctx->msgblocks[64 * 5], - &ctx->msgblocks[64 * 6], - &ctx->msgblocks[64 * 7] - ); - - // Compute final hash output - transpose(ctx->s); - - // Store Hash value - STORE(out0, BYTESWAP(ctx->s[0])); - STORE(out1, BYTESWAP(ctx->s[1])); - STORE(out2, BYTESWAP(ctx->s[2])); - STORE(out3, BYTESWAP(ctx->s[3])); - STORE(out4, BYTESWAP(ctx->s[4])); - STORE(out5, BYTESWAP(ctx->s[5])); - STORE(out6, BYTESWAP(ctx->s[6])); - STORE(out7, BYTESWAP(ctx->s[7])); -} - -void sha256_transform8x(sha256x8ctx *ctx, - const unsigned char *data0, - const unsigned char *data1, - const unsigned char *data2, - const unsigned char *data3, - const unsigned char *data4, - const unsigned char *data5, - const unsigned char *data6, - const unsigned char *data7) { - u256 s[8], w[64], T0, T1; - - // Load words and transform data correctly - w[0] = BYTESWAP(LOAD(data0)); - w[0 + 8] = BYTESWAP(LOAD(data0 + 32)); - w[1] = BYTESWAP(LOAD(data1)); - w[1 + 8] = BYTESWAP(LOAD(data1 + 32)); - w[2] = BYTESWAP(LOAD(data2)); - w[2 + 8] = BYTESWAP(LOAD(data2 + 32)); - w[3] = BYTESWAP(LOAD(data3)); - w[3 + 8] = BYTESWAP(LOAD(data3 + 32)); - w[4] = BYTESWAP(LOAD(data4)); - w[4 + 8] = BYTESWAP(LOAD(data4 + 32)); - w[5] = BYTESWAP(LOAD(data5)); - w[5 + 8] = BYTESWAP(LOAD(data5 + 32)); - w[6] = BYTESWAP(LOAD(data6)); - w[6 + 8] = BYTESWAP(LOAD(data6 + 32)); - w[7] = BYTESWAP(LOAD(data7)); - w[7 + 8] = BYTESWAP(LOAD(data7 + 32)); - - transpose(w); - transpose(w + 8); - - // Initial State - s[0] = ctx->s[0]; - s[1] = ctx->s[1]; - s[2] = ctx->s[2]; - s[3] = ctx->s[3]; - s[4] = ctx->s[4]; - s[5] = ctx->s[5]; - s[6] = ctx->s[6]; - s[7] = ctx->s[7]; - - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 0, w[0]); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 1, w[1]); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 2, w[2]); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 3, w[3]); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 4, w[4]); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 5, w[5]); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 6, w[6]); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 7, w[7]); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 8, w[8]); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 9, w[9]); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 10, w[10]); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 11, w[11]); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 12, w[12]); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 13, w[13]); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 14, w[14]); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 15, w[15]); - w[16] = ADD4_32(WSIGMA1_AVX(w[14]), w[0], w[9], WSIGMA0_AVX(w[1])); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 16, w[16]); - w[17] = ADD4_32(WSIGMA1_AVX(w[15]), w[1], w[10], WSIGMA0_AVX(w[2])); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 17, w[17]); - w[18] = ADD4_32(WSIGMA1_AVX(w[16]), w[2], w[11], WSIGMA0_AVX(w[3])); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 18, w[18]); - w[19] = ADD4_32(WSIGMA1_AVX(w[17]), w[3], w[12], WSIGMA0_AVX(w[4])); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 19, w[19]); - w[20] = ADD4_32(WSIGMA1_AVX(w[18]), w[4], w[13], WSIGMA0_AVX(w[5])); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 20, w[20]); - w[21] = ADD4_32(WSIGMA1_AVX(w[19]), w[5], w[14], WSIGMA0_AVX(w[6])); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 21, w[21]); - w[22] = ADD4_32(WSIGMA1_AVX(w[20]), w[6], w[15], WSIGMA0_AVX(w[7])); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 22, w[22]); - w[23] = ADD4_32(WSIGMA1_AVX(w[21]), w[7], w[16], WSIGMA0_AVX(w[8])); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 23, w[23]); - w[24] = ADD4_32(WSIGMA1_AVX(w[22]), w[8], w[17], WSIGMA0_AVX(w[9])); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 24, w[24]); - w[25] = ADD4_32(WSIGMA1_AVX(w[23]), w[9], w[18], WSIGMA0_AVX(w[10])); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 25, w[25]); - w[26] = ADD4_32(WSIGMA1_AVX(w[24]), w[10], w[19], WSIGMA0_AVX(w[11])); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 26, w[26]); - w[27] = ADD4_32(WSIGMA1_AVX(w[25]), w[11], w[20], WSIGMA0_AVX(w[12])); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 27, w[27]); - w[28] = ADD4_32(WSIGMA1_AVX(w[26]), w[12], w[21], WSIGMA0_AVX(w[13])); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 28, w[28]); - w[29] = ADD4_32(WSIGMA1_AVX(w[27]), w[13], w[22], WSIGMA0_AVX(w[14])); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 29, w[29]); - w[30] = ADD4_32(WSIGMA1_AVX(w[28]), w[14], w[23], WSIGMA0_AVX(w[15])); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 30, w[30]); - w[31] = ADD4_32(WSIGMA1_AVX(w[29]), w[15], w[24], WSIGMA0_AVX(w[16])); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 31, w[31]); - w[32] = ADD4_32(WSIGMA1_AVX(w[30]), w[16], w[25], WSIGMA0_AVX(w[17])); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 32, w[32]); - w[33] = ADD4_32(WSIGMA1_AVX(w[31]), w[17], w[26], WSIGMA0_AVX(w[18])); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 33, w[33]); - w[34] = ADD4_32(WSIGMA1_AVX(w[32]), w[18], w[27], WSIGMA0_AVX(w[19])); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 34, w[34]); - w[35] = ADD4_32(WSIGMA1_AVX(w[33]), w[19], w[28], WSIGMA0_AVX(w[20])); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 35, w[35]); - w[36] = ADD4_32(WSIGMA1_AVX(w[34]), w[20], w[29], WSIGMA0_AVX(w[21])); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 36, w[36]); - w[37] = ADD4_32(WSIGMA1_AVX(w[35]), w[21], w[30], WSIGMA0_AVX(w[22])); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 37, w[37]); - w[38] = ADD4_32(WSIGMA1_AVX(w[36]), w[22], w[31], WSIGMA0_AVX(w[23])); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 38, w[38]); - w[39] = ADD4_32(WSIGMA1_AVX(w[37]), w[23], w[32], WSIGMA0_AVX(w[24])); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 39, w[39]); - w[40] = ADD4_32(WSIGMA1_AVX(w[38]), w[24], w[33], WSIGMA0_AVX(w[25])); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 40, w[40]); - w[41] = ADD4_32(WSIGMA1_AVX(w[39]), w[25], w[34], WSIGMA0_AVX(w[26])); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 41, w[41]); - w[42] = ADD4_32(WSIGMA1_AVX(w[40]), w[26], w[35], WSIGMA0_AVX(w[27])); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 42, w[42]); - w[43] = ADD4_32(WSIGMA1_AVX(w[41]), w[27], w[36], WSIGMA0_AVX(w[28])); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 43, w[43]); - w[44] = ADD4_32(WSIGMA1_AVX(w[42]), w[28], w[37], WSIGMA0_AVX(w[29])); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 44, w[44]); - w[45] = ADD4_32(WSIGMA1_AVX(w[43]), w[29], w[38], WSIGMA0_AVX(w[30])); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 45, w[45]); - w[46] = ADD4_32(WSIGMA1_AVX(w[44]), w[30], w[39], WSIGMA0_AVX(w[31])); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 46, w[46]); - w[47] = ADD4_32(WSIGMA1_AVX(w[45]), w[31], w[40], WSIGMA0_AVX(w[32])); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 47, w[47]); - w[48] = ADD4_32(WSIGMA1_AVX(w[46]), w[32], w[41], WSIGMA0_AVX(w[33])); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 48, w[48]); - w[49] = ADD4_32(WSIGMA1_AVX(w[47]), w[33], w[42], WSIGMA0_AVX(w[34])); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 49, w[49]); - w[50] = ADD4_32(WSIGMA1_AVX(w[48]), w[34], w[43], WSIGMA0_AVX(w[35])); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 50, w[50]); - w[51] = ADD4_32(WSIGMA1_AVX(w[49]), w[35], w[44], WSIGMA0_AVX(w[36])); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 51, w[51]); - w[52] = ADD4_32(WSIGMA1_AVX(w[50]), w[36], w[45], WSIGMA0_AVX(w[37])); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 52, w[52]); - w[53] = ADD4_32(WSIGMA1_AVX(w[51]), w[37], w[46], WSIGMA0_AVX(w[38])); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 53, w[53]); - w[54] = ADD4_32(WSIGMA1_AVX(w[52]), w[38], w[47], WSIGMA0_AVX(w[39])); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 54, w[54]); - w[55] = ADD4_32(WSIGMA1_AVX(w[53]), w[39], w[48], WSIGMA0_AVX(w[40])); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 55, w[55]); - w[56] = ADD4_32(WSIGMA1_AVX(w[54]), w[40], w[49], WSIGMA0_AVX(w[41])); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 56, w[56]); - w[57] = ADD4_32(WSIGMA1_AVX(w[55]), w[41], w[50], WSIGMA0_AVX(w[42])); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 57, w[57]); - w[58] = ADD4_32(WSIGMA1_AVX(w[56]), w[42], w[51], WSIGMA0_AVX(w[43])); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 58, w[58]); - w[59] = ADD4_32(WSIGMA1_AVX(w[57]), w[43], w[52], WSIGMA0_AVX(w[44])); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 59, w[59]); - w[60] = ADD4_32(WSIGMA1_AVX(w[58]), w[44], w[53], WSIGMA0_AVX(w[45])); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 60, w[60]); - w[61] = ADD4_32(WSIGMA1_AVX(w[59]), w[45], w[54], WSIGMA0_AVX(w[46])); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 61, w[61]); - w[62] = ADD4_32(WSIGMA1_AVX(w[60]), w[46], w[55], WSIGMA0_AVX(w[47])); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 62, w[62]); - w[63] = ADD4_32(WSIGMA1_AVX(w[61]), w[47], w[56], WSIGMA0_AVX(w[48])); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 63, w[63]); - - // Feed Forward - ctx->s[0] = ADD32(s[0], ctx->s[0]); - ctx->s[1] = ADD32(s[1], ctx->s[1]); - ctx->s[2] = ADD32(s[2], ctx->s[2]); - ctx->s[3] = ADD32(s[3], ctx->s[3]); - ctx->s[4] = ADD32(s[4], ctx->s[4]); - ctx->s[5] = ADD32(s[5], ctx->s[5]); - ctx->s[6] = ADD32(s[6], ctx->s[6]); - ctx->s[7] = ADD32(s[7], ctx->s[7]); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/sha256avx.h b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/sha256avx.h deleted file mode 100644 index 1e3bcf889b..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/sha256avx.h +++ /dev/null @@ -1,44 +0,0 @@ -#ifndef SHA256AVX_H -#define SHA256AVX_H - -#include -#include - -#include "params.h" - -typedef struct SHA256state { - __m256i s[8]; - unsigned char msgblocks[8 * 64]; - unsigned int datalen; - unsigned long long msglen; -} sha256x8ctx; - -#define sha256_ctx_clone8x SPX_NAMESPACE(sha256_ctx_clone8x) -void sha256_ctx_clone8x(sha256x8ctx *out, const sha256x8ctx *in); - -#define sha256_init8x SPX_NAMESPACE(sha256_init8x) -void sha256_init8x(sha256x8ctx *ctx); - -#define sha256_final8x SPX_NAMESPACE(sha256_final8x) -void sha256_final8x(sha256x8ctx *ctx, - unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7); - -#define sha256_transform8x SPX_NAMESPACE(sha256_transform8x) -void sha256_transform8x(sha256x8ctx *ctx, - const unsigned char *data0, - const unsigned char *data1, - const unsigned char *data2, - const unsigned char *data3, - const unsigned char *data4, - const unsigned char *data5, - const unsigned char *data6, - const unsigned char *data7); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/sha256x8.c b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/sha256x8.c deleted file mode 100644 index d97750c09b..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/sha256x8.c +++ /dev/null @@ -1,185 +0,0 @@ -#include - -#include "sha256avx.h" -#include "sha256x8.h" -#include "utils.h" - -// Performs sha256x8 on an initialized (and perhaps seeded) state. -static void _sha256x8( - sha256x8ctx *ctx, - unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - const unsigned char *in4, - const unsigned char *in5, - const unsigned char *in6, - const unsigned char *in7, unsigned long long inlen) { - unsigned long long i = 0; - while (inlen - i >= 64) { - sha256_transform8x(ctx, - in0 + i, - in1 + i, - in2 + i, - in3 + i, - in4 + i, - in5 + i, - in6 + i, - in7 + i - ); - i += 64; - ctx->msglen += 512; - } - - size_t bytes_to_copy = (size_t)(inlen - i); - memcpy(&ctx->msgblocks[64 * 0], in0 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64 * 1], in1 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64 * 2], in2 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64 * 3], in3 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64 * 4], in4 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64 * 5], in5 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64 * 6], in6 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64 * 7], in7 + i, bytes_to_copy); - ctx->datalen = (unsigned int)bytes_to_copy; - - sha256_final8x(ctx, out0, out1, out2, out3, out4, out5, out6, out7); -} - -void sha256x8_seeded( - unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7, - const sha256x8ctx *seed, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - const unsigned char *in4, - const unsigned char *in5, - const unsigned char *in6, - const unsigned char *in7, unsigned long long inlen) { - - sha256x8ctx ctx; - sha256_ctx_clone8x(&ctx, seed); - - _sha256x8(&ctx, out0, out1, out2, out3, out4, out5, out6, out7, - in0, in1, in2, in3, in4, in5, in6, in7, inlen); -} - -/* This provides a wrapper around the internals of 8x parallel SHA256 */ -void sha256x8(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - const unsigned char *in4, - const unsigned char *in5, - const unsigned char *in6, - const unsigned char *in7, unsigned long long inlen) { - sha256x8ctx ctx; - sha256_init8x(&ctx); - - _sha256x8(&ctx, out0, out1, out2, out3, out4, out5, out6, out7, - in0, in1, in2, in3, in4, in5, in6, in7, inlen); -} - -/** - * Note that inlen should be sufficiently small that it still allows for - * an array to be allocated on the stack. Typically 'in' is merely a seed. - * Outputs outlen number of bytes - */ -void mgf1x8(unsigned char *outx8, unsigned long outlen, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - const unsigned char *in4, - const unsigned char *in5, - const unsigned char *in6, - const unsigned char *in7, - unsigned long inlen) { - PQCLEAN_VLA(unsigned char, inbufx8, 8 * (inlen + 4)); - unsigned char outbufx8[8 * SPX_SHA256_OUTPUT_BYTES]; - uint32_t i; - unsigned int j; - - memcpy(inbufx8 + 0 * (inlen + 4), in0, inlen); - memcpy(inbufx8 + 1 * (inlen + 4), in1, inlen); - memcpy(inbufx8 + 2 * (inlen + 4), in2, inlen); - memcpy(inbufx8 + 3 * (inlen + 4), in3, inlen); - memcpy(inbufx8 + 4 * (inlen + 4), in4, inlen); - memcpy(inbufx8 + 5 * (inlen + 4), in5, inlen); - memcpy(inbufx8 + 6 * (inlen + 4), in6, inlen); - memcpy(inbufx8 + 7 * (inlen + 4), in7, inlen); - - /* While we can fit in at least another full block of SHA256 output.. */ - for (i = 0; (i + 1)*SPX_SHA256_OUTPUT_BYTES <= outlen; i++) { - for (j = 0; j < 8; j++) { - u32_to_bytes(inbufx8 + inlen + j * (inlen + 4), i); - } - - sha256x8(outx8 + 0 * outlen, - outx8 + 1 * outlen, - outx8 + 2 * outlen, - outx8 + 3 * outlen, - outx8 + 4 * outlen, - outx8 + 5 * outlen, - outx8 + 6 * outlen, - outx8 + 7 * outlen, - inbufx8 + 0 * (inlen + 4), - inbufx8 + 1 * (inlen + 4), - inbufx8 + 2 * (inlen + 4), - inbufx8 + 3 * (inlen + 4), - inbufx8 + 4 * (inlen + 4), - inbufx8 + 5 * (inlen + 4), - inbufx8 + 6 * (inlen + 4), - inbufx8 + 7 * (inlen + 4), inlen + 4); - outx8 += SPX_SHA256_OUTPUT_BYTES; - } - /* Until we cannot anymore, and we fill the remainder. */ - for (j = 0; j < 8; j++) { - u32_to_bytes(inbufx8 + inlen + j * (inlen + 4), i); - } - sha256x8(outbufx8 + 0 * SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 1 * SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 2 * SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 3 * SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 4 * SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 5 * SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 6 * SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 7 * SPX_SHA256_OUTPUT_BYTES, - inbufx8 + 0 * (inlen + 4), - inbufx8 + 1 * (inlen + 4), - inbufx8 + 2 * (inlen + 4), - inbufx8 + 3 * (inlen + 4), - inbufx8 + 4 * (inlen + 4), - inbufx8 + 5 * (inlen + 4), - inbufx8 + 6 * (inlen + 4), - inbufx8 + 7 * (inlen + 4), inlen + 4); - - for (j = 0; j < 8; j++) { - memcpy(outx8 + j * outlen, - outbufx8 + j * SPX_SHA256_OUTPUT_BYTES, - outlen - i * SPX_SHA256_OUTPUT_BYTES); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/sha256x8.h b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/sha256x8.h deleted file mode 100644 index 4f7330a6c1..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/sha256x8.h +++ /dev/null @@ -1,64 +0,0 @@ -#ifndef SPX_SHA256X8_H -#define SPX_SHA256X8_H - -#include "params.h" -#include "sha256avx.h" - - - -#define sha256x8_seeded SPX_NAMESPACE(sha256x8_seeded) -void sha256x8_seeded( - unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7, - const sha256x8ctx *seed, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - const unsigned char *in4, - const unsigned char *in5, - const unsigned char *in6, - const unsigned char *in7, unsigned long long inlen); - -/* This provides a wrapper around the internals of 8x parallel SHA256 */ -#define sha256x8 SPX_NAMESPACE(sha256x8) -void sha256x8(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - const unsigned char *in4, - const unsigned char *in5, - const unsigned char *in6, - const unsigned char *in7, unsigned long long inlen); - -/** - * Note that inlen should be sufficiently small that it still allows for - * an array to be allocated on the stack. Typically 'in' is merely a seed. - * Outputs outlen number of bytes - */ -#define mgf1x8 SPX_NAMESPACE(mgf1x8) -void mgf1x8(unsigned char *outx8, unsigned long outlen, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - const unsigned char *in4, - const unsigned char *in5, - const unsigned char *in6, - const unsigned char *in7, - unsigned long inlen); -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/sha2_offsets.h b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/sha2_offsets.h deleted file mode 100644 index 6e3584f7a4..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/sha2_offsets.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef SHA2_OFFSETS_H_ -#define SHA2_OFFSETS_H_ - -#define SPX_SHA256_BLOCK_BYTES 64 -#define SPX_SHA256_OUTPUT_BYTES 32 - -#define SPX_SHA512_BLOCK_BYTES 128 -#define SPX_SHA512_OUTPUT_BYTES 64 - -/* - * Offsets of various fields in the address structure when we use SHA2 as - * the Sphincs+ hash function - */ - -#define SPX_OFFSET_LAYER 0 /* The byte used to specify the Merkle tree layer */ -#define SPX_OFFSET_TREE 1 /* The start of the 8 byte field used to specify the tree */ -#define SPX_OFFSET_TYPE 9 /* The byte used to specify the hash type (reason) */ -#define SPX_OFFSET_KP_ADDR2 12 /* The high byte used to specify the key pair (which one-time signature) */ -#define SPX_OFFSET_KP_ADDR1 13 /* The low byte used to specify the key pair */ -#define SPX_OFFSET_CHAIN_ADDR 17 /* The byte used to specify the chain address (which Winternitz chain) */ -#define SPX_OFFSET_HASH_ADDR 21 /* The byte used to specify the hash address (where in the Winternitz chain) */ -#define SPX_OFFSET_TREE_HGT 17 /* The byte used to specify the height of this node in the FORS or Merkle tree */ -#define SPX_OFFSET_TREE_INDEX 18 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ - -#define SPX_SHA2 1 - -#endif /* SHA2_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/sha512x4.c b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/sha512x4.c deleted file mode 100644 index 8d33deffdd..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/sha512x4.c +++ /dev/null @@ -1,446 +0,0 @@ -#include -#include -#include - -/* pull in the entire thing */ -#include "sha512x4.h" -#include "utils.h" - -typedef uint64_t u64; -typedef __m256i u256; - -#define BYTESWAP(x) _mm256_shuffle_epi8(x, _mm256_set_epi8(0x8,0x9,0xa,0xb,0xc,0xd,0xe,0xf,0x0,0x1,0x2,0x3,0x4,0x5,0x6,0x7,0x8,0x9,0xa,0xb,0xc,0xd,0xe,0xf,0x0,0x1,0x2,0x3,0x4,0x5,0x6,0x7)) -#define STORE(dest,src) _mm256_storeu_si256((__m256i *)(dest),src) - -// Transpose 4 vectors containing 64-bit values -// That is, it rearranges the array: -// A B C D -// E F G H -// I J K L -// M N O P -// into -// A E I M -// B F J N -// C G K O -// D H L P -// where each letter stands for 64 bits (and lsbits on the left) -static void transpose(u256 s[4]) { - u256 tmp[4]; - tmp[0] = _mm256_unpacklo_epi64(s[0], s[1]); - tmp[1] = _mm256_unpackhi_epi64(s[0], s[1]); - tmp[2] = _mm256_unpacklo_epi64(s[2], s[3]); - tmp[3] = _mm256_unpackhi_epi64(s[2], s[3]); - // tmp is in the order of - // A E C G - // B F D H - // I M K O - // J N L P - s[0] = _mm256_permute2x128_si256(tmp[0], tmp[2], 0x20); - s[1] = _mm256_permute2x128_si256(tmp[1], tmp[3], 0x20); - s[2] = _mm256_permute2x128_si256(tmp[0], tmp[2], 0x31); - s[3] = _mm256_permute2x128_si256(tmp[1], tmp[3], 0x31); -} - - -void sha512_init4x(sha512x4ctx *ctx) { -#define SET4(x) _mm256_set_epi64x((long long)(x), (long long)(x), (long long)(x), (long long)(x)) - ctx->s[0] = SET4(0x6a09e667f3bcc908ULL); - ctx->s[1] = SET4(0xbb67ae8584caa73bULL); - ctx->s[2] = SET4(0x3c6ef372fe94f82bULL); - ctx->s[3] = SET4(0xa54ff53a5f1d36f1ULL); - ctx->s[4] = SET4(0x510e527fade682d1ULL); - ctx->s[5] = SET4(0x9b05688c2b3e6c1fULL); - ctx->s[6] = SET4(0x1f83d9abfb41bd6bULL); - ctx->s[7] = SET4(0x5be0cd19137e2179ULL); -#undef SET4 - - ctx->datalen = 0; - ctx->msglen = 0; -} - -#define XOR _mm256_xor_si256 -#define OR _mm256_or_si256 -#define AND _mm256_and_si256 -#define ADD64 _mm256_add_epi64 - -#define LOAD(src) _mm256_loadu_si256((__m256i *)(src)) - -#define SHIFTR64(x, y) _mm256_srli_epi64(x, y) -#define SHIFTL64(x, y) _mm256_slli_epi64(x, y) - -#define ROTR64(x, y) OR(SHIFTR64(x, y), SHIFTL64(x, 64 - (y))) - -static u256 XOR3(u256 a, u256 b, u256 c) { - return XOR(XOR(a, b), c); -} - -#define ADD3_64(a, b, c) ADD64(ADD64(a, b), c) -#define ADD4_64(a, b, c, d) ADD64(ADD64(ADD64(a, b), c), d) -#define ADD5_64(a, b, c, d, e) ADD64(ADD64(ADD64(ADD64(a, b), c), d), e) - -static u256 MAJ_AVX(u256 a, u256 b, u256 c) { - return XOR(c, AND(XOR(a, c), XOR(b, c))); -} -static u256 CH_AVX(u256 a, u256 b, u256 c) { - return XOR(c, AND(a, XOR(b, c))); -} -static u256 SIGMA0_AVX(u256 x) { - return XOR3(ROTR64(x, 28), ROTR64(x, 34), ROTR64(x, 39)); -} -static u256 SIGMA1_AVX(u256 x) { - return XOR3(ROTR64(x, 14), ROTR64(x, 18), ROTR64(x, 41)); -} -static u256 GAMMA0_AVX(u256 x) { - return XOR3(ROTR64(x, 1), ROTR64(x, 8), SHIFTR64(x, 7)); -} -static u256 GAMMA1_AVX(u256 x) { - return XOR3(ROTR64(x, 19), ROTR64(x, 61), SHIFTR64(x, 6)); -} - -#define SHA512ROUND_AVX(a, b, c, d, e, f, g, h, rc, w) \ - T0 = ADD5_64(h, w, SIGMA1_AVX(e), CH_AVX(e, f, g), _mm256_set1_epi64x((long long)RC[rc])); \ - T1 = ADD64(SIGMA0_AVX(a), MAJ_AVX(a, b, c)); \ - (d) = ADD64(d, T0); \ - (h) = ADD64(T0, T1); - -static const unsigned long long RC[80] = { - 0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL, - 0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL, - 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL, - 0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL, - 0xd807aa98a3030242ULL, 0x12835b0145706fbeULL, - 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL, - 0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL, - 0x9bdc06a725c71235ULL, 0xc19bf174cf692694ULL, - 0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL, - 0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL, - 0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL, - 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL, - 0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL, - 0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL, - 0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL, - 0x06ca6351e003826fULL, 0x142929670a0e6e70ULL, - 0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL, - 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL, - 0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL, - 0x81c2c92e47edaee6ULL, 0x92722c851482353bULL, - 0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL, - 0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL, - 0xd192e819d6ef5218ULL, 0xd69906245565a910ULL, - 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL, - 0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL, - 0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL, - 0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL, - 0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL, - 0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL, - 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL, - 0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL, - 0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL, - 0xca273eceea26619cULL, 0xd186b8c721c0c207ULL, - 0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL, - 0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL, - 0x113f9804bef90daeULL, 0x1b710b35131c471bULL, - 0x28db77f523047d84ULL, 0x32caab7b40c72493ULL, - 0x3c9ebe0a15c9bebcULL, 0x431d67c49c100d4cULL, - 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL, - 0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL, -}; - -void sha512_transform4x( - sha512x4ctx *ctx, - const unsigned char *d0, - const unsigned char *d1, - const unsigned char *d2, - const unsigned char *d3) { - u256 s0, s1, s2, s3, s4, s5, s6, s7, w[16], T0, T1, nw; - - // Load words and transform data correctly - w[0 ] = BYTESWAP(LOAD(d0 )); - w[0 + 4] = BYTESWAP(LOAD(d0 + 32)); - w[0 + 8] = BYTESWAP(LOAD(d0 + 64)); - w[0 + 12] = BYTESWAP(LOAD(d0 + 96)); - - w[1 ] = BYTESWAP(LOAD(d1 )); - w[1 + 4] = BYTESWAP(LOAD(d1 + 32)); - w[1 + 8] = BYTESWAP(LOAD(d1 + 64)); - w[1 + 12] = BYTESWAP(LOAD(d1 + 96)); - - w[2 ] = BYTESWAP(LOAD(d2 )); - w[2 + 4] = BYTESWAP(LOAD(d2 + 32)); - w[2 + 8] = BYTESWAP(LOAD(d2 + 64)); - w[2 + 12] = BYTESWAP(LOAD(d2 + 96)); - - w[3 ] = BYTESWAP(LOAD(d3 )); - w[3 + 4] = BYTESWAP(LOAD(d3 + 32)); - w[3 + 8] = BYTESWAP(LOAD(d3 + 64)); - w[3 + 12] = BYTESWAP(LOAD(d3 + 96)); - - transpose(w); - transpose(w + 4); - transpose(w + 8); - transpose(w + 12); - - // Initial State - s0 = ctx->s[0]; - s1 = ctx->s[1]; - s2 = ctx->s[2]; - s3 = ctx->s[3]; - s4 = ctx->s[4]; - s5 = ctx->s[5]; - s6 = ctx->s[6]; - s7 = ctx->s[7]; - - // The first 16 rounds (where the w inputs are directly from the data) - SHA512ROUND_AVX(s0, s1, s2, s3, s4, s5, s6, s7, 0, w[0]); - SHA512ROUND_AVX(s7, s0, s1, s2, s3, s4, s5, s6, 1, w[1]); - SHA512ROUND_AVX(s6, s7, s0, s1, s2, s3, s4, s5, 2, w[2]); - SHA512ROUND_AVX(s5, s6, s7, s0, s1, s2, s3, s4, 3, w[3]); - SHA512ROUND_AVX(s4, s5, s6, s7, s0, s1, s2, s3, 4, w[4]); - SHA512ROUND_AVX(s3, s4, s5, s6, s7, s0, s1, s2, 5, w[5]); - SHA512ROUND_AVX(s2, s3, s4, s5, s6, s7, s0, s1, 6, w[6]); - SHA512ROUND_AVX(s1, s2, s3, s4, s5, s6, s7, s0, 7, w[7]); - SHA512ROUND_AVX(s0, s1, s2, s3, s4, s5, s6, s7, 8, w[8]); - SHA512ROUND_AVX(s7, s0, s1, s2, s3, s4, s5, s6, 9, w[9]); - SHA512ROUND_AVX(s6, s7, s0, s1, s2, s3, s4, s5, 10, w[10]); - SHA512ROUND_AVX(s5, s6, s7, s0, s1, s2, s3, s4, 11, w[11]); - SHA512ROUND_AVX(s4, s5, s6, s7, s0, s1, s2, s3, 12, w[12]); - SHA512ROUND_AVX(s3, s4, s5, s6, s7, s0, s1, s2, 13, w[13]); - SHA512ROUND_AVX(s2, s3, s4, s5, s6, s7, s0, s1, 14, w[14]); - SHA512ROUND_AVX(s1, s2, s3, s4, s5, s6, s7, s0, 15, w[15]); - -#define M(i) (((i)+16) & 0xf) -#define NextW(i) \ - w[M(i)] = ADD4_64(GAMMA1_AVX(w[M((i)-2)]), w[M((i)-7)], GAMMA0_AVX(w[M((i)-15)]), w[M((i)-16)]); - - // The remaining 64 rounds (where the w inputs are a linear fix of the data) - for (unsigned i = 16; i < 80; i += 16) { - nw = NextW(0); - SHA512ROUND_AVX(s0, s1, s2, s3, s4, s5, s6, s7, i + 0, nw); - nw = NextW(1); - SHA512ROUND_AVX(s7, s0, s1, s2, s3, s4, s5, s6, i + 1, nw); - nw = NextW(2); - SHA512ROUND_AVX(s6, s7, s0, s1, s2, s3, s4, s5, i + 2, nw); - nw = NextW(3); - SHA512ROUND_AVX(s5, s6, s7, s0, s1, s2, s3, s4, i + 3, nw); - nw = NextW(4); - SHA512ROUND_AVX(s4, s5, s6, s7, s0, s1, s2, s3, i + 4, nw); - nw = NextW(5); - SHA512ROUND_AVX(s3, s4, s5, s6, s7, s0, s1, s2, i + 5, nw); - nw = NextW(6); - SHA512ROUND_AVX(s2, s3, s4, s5, s6, s7, s0, s1, i + 6, nw); - nw = NextW(7); - SHA512ROUND_AVX(s1, s2, s3, s4, s5, s6, s7, s0, i + 7, nw); - nw = NextW(8); - SHA512ROUND_AVX(s0, s1, s2, s3, s4, s5, s6, s7, i + 8, nw); - nw = NextW(9); - SHA512ROUND_AVX(s7, s0, s1, s2, s3, s4, s5, s6, i + 9, nw); - nw = NextW(10); - SHA512ROUND_AVX(s6, s7, s0, s1, s2, s3, s4, s5, i + 10, nw); - nw = NextW(11); - SHA512ROUND_AVX(s5, s6, s7, s0, s1, s2, s3, s4, i + 11, nw); - nw = NextW(12); - SHA512ROUND_AVX(s4, s5, s6, s7, s0, s1, s2, s3, i + 12, nw); - nw = NextW(13); - SHA512ROUND_AVX(s3, s4, s5, s6, s7, s0, s1, s2, i + 13, nw); - nw = NextW(14); - SHA512ROUND_AVX(s2, s3, s4, s5, s6, s7, s0, s1, i + 14, nw); - nw = NextW(15); - SHA512ROUND_AVX(s1, s2, s3, s4, s5, s6, s7, s0, i + 15, nw); - } - - // Feed Forward - ctx->s[0] = ADD64(s0, ctx->s[0]); - ctx->s[1] = ADD64(s1, ctx->s[1]); - ctx->s[2] = ADD64(s2, ctx->s[2]); - ctx->s[3] = ADD64(s3, ctx->s[3]); - ctx->s[4] = ADD64(s4, ctx->s[4]); - ctx->s[5] = ADD64(s5, ctx->s[5]); - ctx->s[6] = ADD64(s6, ctx->s[6]); - ctx->s[7] = ADD64(s7, ctx->s[7]); -} - -static void _sha512x4( - sha512x4ctx *ctx, - unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - unsigned long long inlen) { - unsigned int i = 0; - - while (inlen - i >= 128) { - sha512_transform4x( - ctx, - in0 + i, - in1 + i, - in2 + i, - in3 + i - ); - ctx->msglen += 1024; - i += 128; - } - - ctx->datalen = (unsigned int)(inlen - i); - memcpy(&ctx->msgblocks[128 * 0], in0 + i, ctx->datalen); - memcpy(&ctx->msgblocks[128 * 1], in1 + i, ctx->datalen); - memcpy(&ctx->msgblocks[128 * 2], in2 + i, ctx->datalen); - memcpy(&ctx->msgblocks[128 * 3], in3 + i, ctx->datalen); - - // Padding - unsigned long curlen; - if (ctx->datalen < 112) { - for (i = 0; i < 4; ++i) { - curlen = ctx->datalen; - ctx->msgblocks[128 * i + curlen++] = 0x80; - while (curlen < 128) { - ctx->msgblocks[128 * i + curlen++] = 0x00; - } - } - } else { - for (i = 0; i < 4; ++i) { - curlen = ctx->datalen; - ctx->msgblocks[128 * i + curlen++] = 0x80; - while (curlen < 128) { - ctx->msgblocks[128 * i + curlen++] = 0x00; - } - } - sha512_transform4x( - ctx, - ctx->msgblocks, - ctx->msgblocks + 128, - ctx->msgblocks + 256, - ctx->msgblocks + 384 - ); - memset(ctx->msgblocks, 0, 4 * 128); - } - - // Add length of the message to each block - ctx->msglen += (unsigned long long)(ctx->datalen) * 8; - for (i = 0; i < 4; i++) { - ctx->msgblocks[128 * i + 127] = (unsigned char)(ctx->msglen); - ctx->msgblocks[128 * i + 126] = (unsigned char)(ctx->msglen >> 8); - ctx->msgblocks[128 * i + 125] = (unsigned char)(ctx->msglen >> 16); - ctx->msgblocks[128 * i + 124] = (unsigned char)(ctx->msglen >> 24); - ctx->msgblocks[128 * i + 123] = (unsigned char)(ctx->msglen >> 32); - ctx->msgblocks[128 * i + 122] = (unsigned char)(ctx->msglen >> 40); - ctx->msgblocks[128 * i + 121] = (unsigned char)(ctx->msglen >> 48); - ctx->msgblocks[128 * i + 120] = (unsigned char)(ctx->msglen >> 56); - memset( &ctx->msgblocks[128 * i + 112], 0, 8 ); - } - sha512_transform4x( - ctx, - ctx->msgblocks, - ctx->msgblocks + 128, - ctx->msgblocks + 256, - ctx->msgblocks + 384 - ); - - // Compute final hash output - transpose(ctx->s); - transpose(ctx->s + 4); - - // Store Hash value - __m256i out[2]; - STORE(out, BYTESWAP(ctx->s[0])); - STORE(out + 1, BYTESWAP(ctx->s[4])); - memcpy(out0, out, 64); - - STORE(out, BYTESWAP(ctx->s[1])); - STORE(out + 1, BYTESWAP(ctx->s[5])); - memcpy(out1, out, 64); - - STORE(out, BYTESWAP(ctx->s[2])); - STORE(out + 1, BYTESWAP(ctx->s[6])); - memcpy(out2, out, 64); - - STORE(out, BYTESWAP(ctx->s[3])); - STORE(out + 1, BYTESWAP(ctx->s[7])); - memcpy(out3, out, 64); -} - - -/** - * Note that inlen should be sufficiently small that it still allows for - * an array to be allocated on the stack. Typically 'in' is merely a seed. - * Outputs outlen number of bytes - */ -void mgf1x4_512(unsigned char *outx4, unsigned long outlen, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - unsigned long inlen) { - PQCLEAN_VLA(unsigned char, inbufx4, 4 * (inlen + 4)); - unsigned char outbuf[4 * 64]; - uint32_t i; - unsigned int j; - - memcpy(inbufx4 + 0 * (inlen + 4), in0, inlen); - memcpy(inbufx4 + 1 * (inlen + 4), in1, inlen); - memcpy(inbufx4 + 2 * (inlen + 4), in2, inlen); - memcpy(inbufx4 + 3 * (inlen + 4), in3, inlen); - - /* While we can fit in at least another full block of SHA512 output.. */ - unsigned long remaining = outlen; - for (i = 0; remaining > 0; i++) { - unsigned long this_step = SPX_SHA512_OUTPUT_BYTES; - if (this_step > remaining) { - this_step = remaining; - } - remaining -= this_step; - for (j = 0; j < 4; j++) { - u32_to_bytes(inbufx4 + inlen + j * (inlen + 4), i); - } - - sha512x4ctx ctx; - sha512_init4x(&ctx); - - _sha512x4( - &ctx, - outbuf + 0 * 64, - outbuf + 1 * 64, - outbuf + 2 * 64, - outbuf + 3 * 64, - inbufx4 + 0 * (inlen + 4), - inbufx4 + 1 * (inlen + 4), - inbufx4 + 2 * (inlen + 4), - inbufx4 + 3 * (inlen + 4), - inlen + 4 - ); - - memcpy(outx4 + 0 * outlen, outbuf + 0 * 64, this_step); - memcpy(outx4 + 1 * outlen, outbuf + 1 * 64, this_step); - memcpy(outx4 + 2 * outlen, outbuf + 2 * 64, this_step); - memcpy(outx4 + 3 * outlen, outbuf + 3 * 64, this_step); - outx4 += this_step; - } -} - -void sha512x4_seeded( - unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const sha512x4ctx *seed, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - unsigned long long inlen) { - sha512x4ctx ctx; - sha512_ctx_clone4x(&ctx, seed); - _sha512x4( - &ctx, - out0, out1, out2, out3, - in0, in1, in2, in3, - inlen - ); -} - -void sha512_ctx_clone4x(sha512x4ctx *out, const sha512x4ctx *in) { - memcpy(out, in, sizeof(sha512x4ctx)); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/sha512x4.h b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/sha512x4.h deleted file mode 100644 index 9bbe736514..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/sha512x4.h +++ /dev/null @@ -1,58 +0,0 @@ -#ifndef SHA512AVX_H -#define SHA512AVX_H - -#include -#include - - -#include "params.h" - -typedef struct SHA512state4x { - __m256i s[8]; - unsigned char msgblocks[4 * 128]; - unsigned int datalen; - unsigned long long msglen; -} sha512x4ctx; - -#define sha512_init4x SPX_NAMESPACE(sha512_init4x) -void sha512_init4x(sha512x4ctx *ctx); - -#define sha512_transform4x SPX_NAMESPACE(sha512_transform4x) -void sha512_transform4x( - sha512x4ctx *ctx, - const unsigned char *d0, - const unsigned char *d1, - const unsigned char *d2, - const unsigned char *d3); - - -#define sha512x4_seeded SPX_NAMESPACE(sha512x4_seeded) -void sha512x4_seeded( - unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const sha512x4ctx *seed, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - unsigned long long inlen); - -#define sha512_ctx_clone4x SPX_NAMESPACE(sha512_ctx_clone4x) -void sha512_ctx_clone4x(sha512x4ctx *out, const sha512x4ctx *in); - -/** - * Note that inlen should be sufficiently small that it still allows for - * an array to be allocated on the stack. Typically 'in' is merely a seed. - * Outputs outlen number of bytes - */ -#define mgf1x4_512 SPX_NAMESPACE(mgf1x4_512) -void mgf1x4_512(unsigned char *outx4, unsigned long outlen, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - unsigned long inlen); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/sign.c b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/sign.c deleted file mode 100644 index 9d0c7d1b22..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/sign.c +++ /dev/null @@ -1,286 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "context.h" -#include "fors.h" -#include "hash.h" -#include "merkle.h" -#include "nistapi.h" -#include "params.h" -#include "randombytes.h" -#include "thash.h" -#include "utils.h" -#include "wots.h" - -/* - * Returns the length of a secret key, in bytes - */ -size_t crypto_sign_secretkeybytes(void) { - return CRYPTO_SECRETKEYBYTES; -} - -/* - * Returns the length of a public key, in bytes - */ -size_t crypto_sign_publickeybytes(void) { - return CRYPTO_PUBLICKEYBYTES; -} - -/* - * Returns the length of a signature, in bytes - */ -size_t crypto_sign_bytes(void) { - return CRYPTO_BYTES; -} - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t crypto_sign_seedbytes(void) { - return CRYPTO_SEEDBYTES; -} - -/* - * Generates an SPX key pair given a seed of length - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed) { - spx_ctx ctx; - - /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ - memcpy(sk, seed, CRYPTO_SEEDBYTES); - - memcpy(pk, sk + 2 * SPX_N, SPX_N); - - memcpy(ctx.pub_seed, pk, SPX_N); - memcpy(ctx.sk_seed, sk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - /* Compute root node of the top-most subtree. */ - merkle_gen_root(sk + 3 * SPX_N, &ctx); - - // cleanup - free_hash_function(&ctx); - - memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); - - return 0; -} - -/* - * Generates an SPX key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { - uint8_t seed[CRYPTO_SEEDBYTES]; - randombytes(seed, CRYPTO_SEEDBYTES); - crypto_sign_seed_keypair(pk, sk, seed); - - return 0; -} - -/** - * Returns an array containing a detached signature. - */ -int crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - spx_ctx ctx; - - const uint8_t *sk_prf = sk + SPX_N; - const uint8_t *pk = sk + 2 * SPX_N; - - uint8_t optrand[SPX_N]; - uint8_t mhash[SPX_FORS_MSG_BYTES]; - uint8_t root[SPX_N]; - uint32_t i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - - memcpy(ctx.sk_seed, sk, SPX_N); - memcpy(ctx.pub_seed, pk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - set_type(wots_addr, SPX_ADDR_TYPE_WOTS); - set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); - - /* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ - randombytes(optrand, SPX_N); - /* Compute the digest randomization value. */ - gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); - - /* Derive the message digest and leaf index from R, PK and M. */ - hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); - sig += SPX_N; - - set_tree_addr(wots_addr, tree); - set_keypair_addr(wots_addr, idx_leaf); - - /* Sign the message hash using FORS. */ - fors_sign(sig, root, mhash, &ctx, wots_addr); - sig += SPX_FORS_BYTES; - - for (i = 0; i < SPX_D; i++) { - set_layer_addr(tree_addr, i); - set_tree_addr(tree_addr, tree); - - copy_subtree_addr(wots_addr, tree_addr); - set_keypair_addr(wots_addr, idx_leaf); - - merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); - sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); - tree = tree >> SPX_TREE_HEIGHT; - } - - free_hash_function(&ctx); - - *siglen = SPX_BYTES; - - return 0; -} - -/** - * Verifies a detached signature and message under a given public key. - */ -int crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk) { - spx_ctx ctx; - const uint8_t *pub_root = pk + SPX_N; - uint8_t mhash[SPX_FORS_MSG_BYTES]; - uint8_t wots_pk[SPX_WOTS_BYTES]; - uint8_t root[SPX_N]; - uint8_t leaf[SPX_N]; - unsigned int i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - if (siglen != SPX_BYTES) { - return -1; - } - - memcpy(ctx.pub_seed, pk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - set_type(wots_addr, SPX_ADDR_TYPE_WOTS); - set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); - set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); - - /* Derive the message digest and leaf index from R || PK || M. */ - /* The additional SPX_N is a result of the hash domain separator. */ - hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); - sig += SPX_N; - - /* Layer correctly defaults to 0, so no need to set_layer_addr */ - set_tree_addr(wots_addr, tree); - set_keypair_addr(wots_addr, idx_leaf); - - fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); - sig += SPX_FORS_BYTES; - - /* For each subtree.. */ - for (i = 0; i < SPX_D; i++) { - set_layer_addr(tree_addr, i); - set_tree_addr(tree_addr, tree); - - copy_subtree_addr(wots_addr, tree_addr); - set_keypair_addr(wots_addr, idx_leaf); - - copy_keypair_addr(wots_pk_addr, wots_addr); - - /* The WOTS public key is only correct if the signature was correct. */ - /* Initially, root is the FORS pk, but on subsequent iterations it is - the root of the subtree below the currently processed subtree. */ - wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); - sig += SPX_WOTS_BYTES; - - /* Compute the leaf node using the WOTS public key. */ - thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); - - /* Compute the root node of this subtree. */ - compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, - &ctx, tree_addr); - sig += SPX_TREE_HEIGHT * SPX_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); - tree = tree >> SPX_TREE_HEIGHT; - } - - // cleanup - free_hash_function(&ctx); - - /* Check if the root node equals the root node in the public key. */ - if (memcmp(root, pub_root, SPX_N) != 0) { - return -1; - } - - return 0; -} - - -/** - * Returns an array containing the signature followed by the message. - */ -int crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk) { - size_t siglen; - - crypto_sign_signature(sm, &siglen, m, mlen, sk); - - memmove(sm + SPX_BYTES, m, mlen); - *smlen = siglen + mlen; - - return 0; -} - -/** - * Verifies a given signature-message pair under a given public key. - */ -int crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk) { - /* The API caller does not necessarily know what size a signature should be - but SPHINCS+ signatures are always exactly SPX_BYTES. */ - if (smlen < SPX_BYTES) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - *mlen = smlen - SPX_BYTES; - - if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - /* If verification was successful, move the message to the right place. */ - memmove(m, sm + SPX_BYTES, *mlen); - - return 0; -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/thash.h b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/thash.h deleted file mode 100644 index 8687ccfb4d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/thash.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef SPX_THASH_H -#define SPX_THASH_H - -#include "context.h" -#include "params.h" - -#include - -#define thash SPX_NAMESPACE(thash) -void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/thash_sha2_robust.c b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/thash_sha2_robust.c deleted file mode 100644 index 3ab891175f..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/thash_sha2_robust.c +++ /dev/null @@ -1,68 +0,0 @@ -#include -#include - -#include "address.h" -#include "context.h" -#include "hash.h" -#include "params.h" -#include "sha2.h" -#include "thash.h" -#include "utils.h" - -static void thash_512(unsigned char *out, const unsigned char *in, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]); - -/** - * Takes an array of inblocks concatenated arrays of SPX_N bytes. - */ -void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]) { - if (inblocks > 1) { - thash_512(out, in, inblocks, ctx, addr); - return; - } - unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES]; - PQCLEAN_VLA(uint8_t, bitmask, inblocks * SPX_N); - PQCLEAN_VLA(uint8_t, buf, SPX_N + SPX_SHA256_OUTPUT_BYTES + inblocks * SPX_N); - sha256ctx sha2_state; - unsigned int i; - - memcpy(buf, ctx->pub_seed, SPX_N); - memcpy(buf + SPX_N, addr, SPX_SHA256_ADDR_BYTES); - mgf1_256(bitmask, inblocks * SPX_N, buf, SPX_N + SPX_SHA256_ADDR_BYTES); - - /* Retrieve precomputed state containing pub_seed */ - sha256_inc_ctx_clone(&sha2_state, &ctx->state_seeded); - - for (i = 0; i < inblocks * SPX_N; i++) { - buf[SPX_N + SPX_SHA256_ADDR_BYTES + i] = in[i] ^ bitmask[i]; - } - - sha256_inc_finalize(outbuf, &sha2_state, buf + SPX_N, - SPX_SHA256_ADDR_BYTES + inblocks * SPX_N); - memcpy(out, outbuf, SPX_N); -} - -static void thash_512(unsigned char *out, const unsigned char *in, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]) { - unsigned char outbuf[SPX_SHA512_OUTPUT_BYTES]; - PQCLEAN_VLA(uint8_t, bitmask, inblocks * SPX_N); - PQCLEAN_VLA(uint8_t, buf, SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N); - sha512ctx sha2_state; - unsigned int i; - - memcpy(buf, ctx->pub_seed, SPX_N); - memcpy(buf + SPX_N, addr, SPX_SHA256_ADDR_BYTES); - mgf1_512(bitmask, inblocks * SPX_N, buf, SPX_N + SPX_SHA256_ADDR_BYTES); - - /* Retrieve precomputed state containing pub_seed */ - sha512_inc_ctx_clone(&sha2_state, &ctx->state_seeded_512); - - for (i = 0; i < inblocks * SPX_N; i++) { - buf[SPX_N + SPX_SHA256_ADDR_BYTES + i] = in[i] ^ bitmask[i]; - } - - sha512_inc_finalize(outbuf, &sha2_state, buf + SPX_N, - SPX_SHA256_ADDR_BYTES + inblocks * SPX_N); - memcpy(out, outbuf, SPX_N); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/thash_sha2_robustx8.c b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/thash_sha2_robustx8.c deleted file mode 100644 index 991faa7eeb..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/thash_sha2_robustx8.c +++ /dev/null @@ -1,268 +0,0 @@ -#include -#include - -#include "thashx8.h" - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "sha2.h" -#include "sha256avx.h" -#include "sha256x8.h" -#include "utils.h" - -#include "sha512x4.h" - -static void thashx8_512( - unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - const unsigned char *in4, - const unsigned char *in5, - const unsigned char *in6, - const unsigned char *in7, - unsigned int inblocks, - const spx_ctx *ctx, - uint32_t addrx8[8 * 8] -); - -/** - * 8-way parallel version of thash; takes 8x as much input and output - */ -void thashx8(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - const unsigned char *in4, - const unsigned char *in5, - const unsigned char *in6, - const unsigned char *in7, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addrx8[8 * 8]) { - if (inblocks > 1) { - thashx8_512( - out0, out1, out2, out3, out4, out5, out6, out7, - in0, in1, in2, in3, in4, in5, in6, in7, - inblocks, ctx, addrx8); - return; - } - PQCLEAN_VLA(unsigned char, bufx8, 8 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)); - unsigned char outbufx8[8 * SPX_SHA256_OUTPUT_BYTES]; - PQCLEAN_VLA(unsigned char, bitmaskx8, 8 * (inblocks * SPX_N)); - unsigned int i; - - for (i = 0; i < 8; i++) { - memcpy(bufx8 + i * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - ctx->pub_seed, SPX_N); - memcpy(bufx8 + SPX_N + - i * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - addrx8 + i * 8, SPX_SHA256_ADDR_BYTES); - } - - mgf1x8(bitmaskx8, inblocks * SPX_N, - bufx8 + 0 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + 1 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + 2 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + 3 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + 4 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + 5 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + 6 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + 7 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - SPX_N + SPX_SHA256_ADDR_BYTES); - - for (i = 0; i < inblocks * SPX_N; i++) { - bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + - 0 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = - in0[i] ^ bitmaskx8[i + 0 * (inblocks * SPX_N)]; - bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + - 1 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = - in1[i] ^ bitmaskx8[i + 1 * (inblocks * SPX_N)]; - bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + - 2 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = - in2[i] ^ bitmaskx8[i + 2 * (inblocks * SPX_N)]; - bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + - 3 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = - in3[i] ^ bitmaskx8[i + 3 * (inblocks * SPX_N)]; - bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + - 4 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = - in4[i] ^ bitmaskx8[i + 4 * (inblocks * SPX_N)]; - bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + - 5 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = - in5[i] ^ bitmaskx8[i + 5 * (inblocks * SPX_N)]; - bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + - 6 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = - in6[i] ^ bitmaskx8[i + 6 * (inblocks * SPX_N)]; - bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + - 7 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = - in7[i] ^ bitmaskx8[i + 7 * (inblocks * SPX_N)]; - } - - sha256x8_seeded( - /* out */ - outbufx8 + 0 * SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 1 * SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 2 * SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 3 * SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 4 * SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 5 * SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 6 * SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 7 * SPX_SHA256_OUTPUT_BYTES, - - /* seed */ - &ctx->statex8_seeded, - - /* in */ - bufx8 + SPX_N + 0 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + SPX_N + 1 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + SPX_N + 2 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + SPX_N + 3 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + SPX_N + 4 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + SPX_N + 5 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + SPX_N + 6 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + SPX_N + 7 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - SPX_SHA256_ADDR_BYTES + inblocks * SPX_N /* len */ - ); - - memcpy(out0, outbufx8 + 0 * SPX_SHA256_OUTPUT_BYTES, SPX_N); - memcpy(out1, outbufx8 + 1 * SPX_SHA256_OUTPUT_BYTES, SPX_N); - memcpy(out2, outbufx8 + 2 * SPX_SHA256_OUTPUT_BYTES, SPX_N); - memcpy(out3, outbufx8 + 3 * SPX_SHA256_OUTPUT_BYTES, SPX_N); - memcpy(out4, outbufx8 + 4 * SPX_SHA256_OUTPUT_BYTES, SPX_N); - memcpy(out5, outbufx8 + 5 * SPX_SHA256_OUTPUT_BYTES, SPX_N); - memcpy(out6, outbufx8 + 6 * SPX_SHA256_OUTPUT_BYTES, SPX_N); - memcpy(out7, outbufx8 + 7 * SPX_SHA256_OUTPUT_BYTES, SPX_N); -} - -/** - * 2x4-way parallel version of thash; this is for the uses of thash that are - * based on SHA-512 - */ -static void thashx8_512( - unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - const unsigned char *in4, - const unsigned char *in5, - const unsigned char *in6, - const unsigned char *in7, - unsigned int inblocks, - const spx_ctx *ctx, - uint32_t addrx8[8 * 8]) { - PQCLEAN_VLA(unsigned char, bufx8, 8 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)); - unsigned char outbuf[4 * SPX_SHA512_OUTPUT_BYTES]; - PQCLEAN_VLA(unsigned char, bitmaskx4, 4 * (inblocks * SPX_N)); - unsigned int i; - - for (i = 0; i < 8; i++) { - memcpy(bufx8 + i * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - ctx->pub_seed, SPX_N); - memcpy(bufx8 + SPX_N + - i * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - addrx8 + i * 8, SPX_SHA256_ADDR_BYTES); - } - - mgf1x4_512(bitmaskx4, inblocks * SPX_N, - bufx8 + 0 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + 1 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + 2 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + 3 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - SPX_N + SPX_SHA256_ADDR_BYTES); - - for (i = 0; i < inblocks * SPX_N; i++) { - bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + - 0 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = - in0[i] ^ bitmaskx4[i + 0 * (inblocks * SPX_N)]; - bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + - 1 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = - in1[i] ^ bitmaskx4[i + 1 * (inblocks * SPX_N)]; - bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + - 2 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = - in2[i] ^ bitmaskx4[i + 2 * (inblocks * SPX_N)]; - bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + - 3 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = - in3[i] ^ bitmaskx4[i + 3 * (inblocks * SPX_N)]; - } - - mgf1x4_512(bitmaskx4, inblocks * SPX_N, - bufx8 + 4 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + 5 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + 6 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + 7 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - SPX_N + SPX_SHA256_ADDR_BYTES); - - for (i = 0; i < inblocks * SPX_N; i++) { - bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + - 4 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = - in4[i] ^ bitmaskx4[i + 0 * (inblocks * SPX_N)]; - bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + - 5 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = - in5[i] ^ bitmaskx4[i + 1 * (inblocks * SPX_N)]; - bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + - 6 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = - in6[i] ^ bitmaskx4[i + 2 * (inblocks * SPX_N)]; - bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + - 7 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = - in7[i] ^ bitmaskx4[i + 3 * (inblocks * SPX_N)]; - } - - sha512x4_seeded( - outbuf + 0 * SPX_SHA512_OUTPUT_BYTES, - outbuf + 1 * SPX_SHA512_OUTPUT_BYTES, - outbuf + 2 * SPX_SHA512_OUTPUT_BYTES, - outbuf + 3 * SPX_SHA512_OUTPUT_BYTES, - &ctx->statex4_seeded_512, /* seed */ - bufx8 + SPX_N + 0 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + SPX_N + 1 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + SPX_N + 2 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + SPX_N + 3 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - SPX_SHA256_ADDR_BYTES + inblocks * SPX_N /* len */ - ); - - memcpy(out0, outbuf + 0 * SPX_SHA512_OUTPUT_BYTES, SPX_N); - memcpy(out1, outbuf + 1 * SPX_SHA512_OUTPUT_BYTES, SPX_N); - memcpy(out2, outbuf + 2 * SPX_SHA512_OUTPUT_BYTES, SPX_N); - memcpy(out3, outbuf + 3 * SPX_SHA512_OUTPUT_BYTES, SPX_N); - - sha512x4_seeded( - outbuf + 0 * SPX_SHA512_OUTPUT_BYTES, - outbuf + 1 * SPX_SHA512_OUTPUT_BYTES, - outbuf + 2 * SPX_SHA512_OUTPUT_BYTES, - outbuf + 3 * SPX_SHA512_OUTPUT_BYTES, - &ctx->statex4_seeded_512, /* seed */ - bufx8 + SPX_N + 4 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + SPX_N + 5 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + SPX_N + 6 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + SPX_N + 7 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - SPX_SHA256_ADDR_BYTES + inblocks * SPX_N /* len */ - ); - - memcpy(out4, outbuf + 0 * SPX_SHA512_OUTPUT_BYTES, SPX_N); - memcpy(out5, outbuf + 1 * SPX_SHA512_OUTPUT_BYTES, SPX_N); - memcpy(out6, outbuf + 2 * SPX_SHA512_OUTPUT_BYTES, SPX_N); - memcpy(out7, outbuf + 3 * SPX_SHA512_OUTPUT_BYTES, SPX_N); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/thashx8.h b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/thashx8.h deleted file mode 100644 index c02fe9cf3e..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/thashx8.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef SPX_THASHX8_H -#define SPX_THASHX8_H - -#include - -#include "context.h" -#include "params.h" - -#define thashx8 SPX_NAMESPACE(thashx8) -void thashx8(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - const unsigned char *in4, - const unsigned char *in5, - const unsigned char *in6, - const unsigned char *in7, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addrx8[8 * 8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/utils.c b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/utils.c deleted file mode 100644 index 177b541fb9..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/utils.c +++ /dev/null @@ -1,148 +0,0 @@ -#include - -#include "utils.h" - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "thash.h" - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void ull_to_bytes(unsigned char *out, unsigned int outlen, - unsigned long long in) { - int i; - - /* Iterate over out in decreasing order, for big-endianness. */ - for (i = (signed int)outlen - 1; i >= 0; i--) { - out[i] = in & 0xff; - in = in >> 8; - } -} - -void u32_to_bytes(unsigned char *out, uint32_t in) { - out[0] = (unsigned char)(in >> 24); - out[1] = (unsigned char)(in >> 16); - out[2] = (unsigned char)(in >> 8); - out[3] = (unsigned char)in; -} - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { - unsigned long long retval = 0; - unsigned int i; - - for (i = 0; i < inlen; i++) { - retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); - } - return retval; -} - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void compute_root(unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const spx_ctx *ctx, uint32_t addr[8]) { - uint32_t i; - unsigned char buffer[2 * SPX_N]; - - /* If leaf_idx is odd (last bit = 1), current path element is a right child - and auth_path has to go left. Otherwise it is the other way around. */ - if (leaf_idx & 1) { - memcpy(buffer + SPX_N, leaf, SPX_N); - memcpy(buffer, auth_path, SPX_N); - } else { - memcpy(buffer, leaf, SPX_N); - memcpy(buffer + SPX_N, auth_path, SPX_N); - } - auth_path += SPX_N; - - for (i = 0; i < tree_height - 1; i++) { - leaf_idx >>= 1; - idx_offset >>= 1; - /* Set the address of the node we're creating. */ - set_tree_height(addr, i + 1); - set_tree_index(addr, leaf_idx + idx_offset); - - /* Pick the right or left neighbor, depending on parity of the node. */ - if (leaf_idx & 1) { - thash(buffer + SPX_N, buffer, 2, ctx, addr); - memcpy(buffer, auth_path, SPX_N); - } else { - thash(buffer, buffer, 2, ctx, addr); - memcpy(buffer + SPX_N, auth_path, SPX_N); - } - auth_path += SPX_N; - } - - /* The last iteration is exceptional; we do not copy an auth_path node. */ - leaf_idx >>= 1; - idx_offset >>= 1; - set_tree_height(addr, tree_height); - set_tree_index(addr, leaf_idx + idx_offset); - thash(root, buffer, 2, ctx, addr); -} - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const spx_ctx * /* ctx */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), - uint32_t tree_addr[8]) { - PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); - PQCLEAN_VLA(unsigned int, heights, tree_height + 1); - unsigned int offset = 0; - uint32_t idx; - uint32_t tree_idx; - - for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { - /* Add the next leaf node to the stack. */ - gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); - offset++; - heights[offset - 1] = 0; - - /* If this is a node we need for the auth path.. */ - if ((leaf_idx ^ 0x1) == idx) { - memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); - } - - /* While the top-most nodes are of equal height.. */ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { - /* Compute index of the new node, in the next layer. */ - tree_idx = (idx >> (heights[offset - 1] + 1)); - - /* Set the address of the node we're creating. */ - set_tree_height(tree_addr, heights[offset - 1] + 1); - set_tree_index(tree_addr, - tree_idx + (idx_offset >> (heights[offset - 1] + 1))); - /* Hash the top-most nodes from the stack together. */ - thash(stack + (offset - 2)*SPX_N, - stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); - offset--; - /* Note that the top-most node is now one layer higher. */ - heights[offset - 1]++; - - /* If this is a node we need for the auth path.. */ - if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_path + heights[offset - 1]*SPX_N, - stack + (offset - 1)*SPX_N, SPX_N); - } - } - } - memcpy(root, stack, SPX_N); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/utils.h b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/utils.h deleted file mode 100644 index 64f5d5a53a..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/utils.h +++ /dev/null @@ -1,58 +0,0 @@ -#ifndef SPX_UTILS_H -#define SPX_UTILS_H - -#include - -#include "compat.h" -#include "context.h" -#include "params.h" - - -/* To support MSVC use alloca() instead of VLAs. See #20. */ - - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) -void ull_to_bytes(unsigned char *out, unsigned int outlen, - unsigned long long in); -#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) -void u32_to_bytes(unsigned char *out, uint32_t in); - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) -unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -#define compute_root SPX_NAMESPACE(compute_root) -void compute_root(unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const spx_ctx *ctx, uint32_t addr[8]); - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -#define treehash SPX_NAMESPACE(treehash) -void treehash(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const spx_ctx *ctx /* ctx */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), - uint32_t tree_addr[8]); - - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/utilsx8.c b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/utilsx8.c deleted file mode 100644 index f044b9595d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/utilsx8.c +++ /dev/null @@ -1,146 +0,0 @@ -#include - -#include "utils.h" -#include "utilsx8.h" - -#include "address.h" -#include "params.h" -#include "thashx8.h" - -/* - * Generate the entire Merkle tree, computing the authentication path for leaf_idx, - * and the resulting root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) - * - * This expects tree_addrx8 to be initialized to 8 parallel addr structures for - * the Merkle tree nodes - * - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - * - * This works by using the standard Merkle tree building algorithm, except - * that each 'node' tracked is actually 8 consecutive nodes in the real tree. - * When we combine two logical nodes ABCDEFGH and STUVWXYZ, we perform the H - * operation on adjacent real nodes, forming the parent logical node - * (AB)(CD)(EF)(GH)(ST)(UV)(WX)(YZ) - * - * When we get to the top three levels of the real tree (where there is only - * one logical node), we continue this operation three more times; the right - * most real node will by the actual root (and the other 7 nodes will be - * garbage). We follow the same thashx8 logic so that the 'extract - * authentication path components' part of the loop is still executed (and - * to simplify the code somewhat) - * - * This currently assumes tree_height >= 3; I suspect that doing an adjusting - * idx, addr_idx on the gen_leafx8 call if tree_height < 3 would fix it; since - * we don't actually use such short trees, I haven't bothered - */ -void treehashx8(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, - uint32_t tree_height, - void (*gen_leafx8)( - unsigned char * /* Where to write the leaves */, - const spx_ctx *, - uint32_t idx, void *info), - uint32_t tree_addrx8[8 * 8], - void *info) { - /* This is where we keep the intermediate nodes */ - PQCLEAN_VLA(unsigned char, stackx8, tree_height * 8 * SPX_N); - uint32_t left_adj = 0, prev_left_adj = 0; /* When we're doing the top 3 */ - /* levels, the left-most part of the tree isn't at the beginning */ - /* of current[]. These give the offset of the actual start */ - - uint32_t idx; - uint32_t max_idx = ((uint32_t)1 << (tree_height - 3)) - 1; - for (idx = 0;; idx++) { - unsigned char current[8 * SPX_N]; /* Current logical node */ - gen_leafx8( current, ctx, 8 * idx + idx_offset, - info ); - - /* Now combine the freshly generated right node with previously */ - /* generated left ones */ - uint32_t internal_idx_offset = idx_offset; - uint32_t internal_idx = idx; - uint32_t internal_leaf = leaf_idx; - uint32_t h; /* The height we are in the Merkle tree */ - for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { - - /* Special processing if we're at the top of the tree */ - if (h >= tree_height - 3) { - if (h == tree_height) { - /* We hit the root; return it */ - memcpy( root, ¤t[7 * SPX_N], SPX_N ); - return; - } - /* The tree indexing logic is a bit off in this case */ - /* Adjust it so that the left-most node of the part of */ - /* the tree that we're processing has index 0 */ - prev_left_adj = left_adj; - left_adj = (uint32_t)(8 - (1 << (tree_height - h - 1))); - } - - /* Check if we hit the top of the tree */ - if (h == tree_height) { - /* We hit the root; return it */ - memcpy( root, ¤t[7 * SPX_N], SPX_N ); - return; - } - - /* - * Check if one of the nodes we have is a part of the - * authentication path; if it is, write it out - */ - if ((((internal_idx << 3) ^ internal_leaf) & ~0x7U) == 0) { - memcpy( &auth_path[ h * SPX_N ], - ¤t[(((internal_leaf & 7) ^ 1) + prev_left_adj) * SPX_N], - SPX_N ); - } - - /* - * Check if we're at a left child; if so, stop going up the stack - * Exception: if we've reached the end of the tree, keep on going - * (so we combine the last 8 nodes into the one root node in three - * more iterations) - */ - if ((internal_idx & 1) == 0 && idx < max_idx) { - break; - } - - /* Ok, we're at a right node (or doing the top 3 levels) */ - /* Now combine the left and right logical nodes together */ - - /* Set the address of the node we're creating. */ - uint32_t j; - internal_idx_offset >>= 1; - for (j = 0; j < 8; j++) { - set_tree_height(tree_addrx8 + j * 8, h + 1); - set_tree_index(tree_addrx8 + j * 8, - (8 / 2) * (internal_idx & ~1U) + j - left_adj + internal_idx_offset ); - } - unsigned char *left = &stackx8[h * 8 * SPX_N]; - thashx8( ¤t[0 * SPX_N], - ¤t[1 * SPX_N], - ¤t[2 * SPX_N], - ¤t[3 * SPX_N], - ¤t[4 * SPX_N], - ¤t[5 * SPX_N], - ¤t[6 * SPX_N], - ¤t[7 * SPX_N], - &left [0 * SPX_N], - &left [2 * SPX_N], - &left [4 * SPX_N], - &left [6 * SPX_N], - ¤t[0 * SPX_N], - ¤t[2 * SPX_N], - ¤t[4 * SPX_N], - ¤t[6 * SPX_N], - 2, ctx, tree_addrx8); - } - - /* We've hit a left child; save the current for when we get the */ - /* corresponding right right */ - memcpy( &stackx8[h * 8 * SPX_N], current, 8 * SPX_N); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/utilsx8.h b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/utilsx8.h deleted file mode 100644 index 806d1e85be..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/utilsx8.h +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef SPX_UTILSX8_H -#define SPX_UTILSX8_H - -#include - -#include "params.h" - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - * - * This implementation uses AVX to compute internal nodes 8 at a time (in - * parallel) - */ -#define treehashx8 SPX_NAMESPACE(treehashx8) -void treehashx8(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leafx8)( - unsigned char * /* Where to write the leaves */, - const spx_ctx * /* ctx */, - uint32_t addr_idx, void *info), - uint32_t tree_addrx8[8 * 8], void *info); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/wots.c b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/wots.c deleted file mode 100644 index 689baf4db9..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/wots.c +++ /dev/null @@ -1,291 +0,0 @@ -#include -#include - -#include "wots.h" - -#include "address.h" -#include "hash.h" -#include "hashx8.h" -#include "params.h" -#include "thash.h" -#include "thashx8.h" -#include "utils.h" -#include "utilsx8.h" -#include "wotsx8.h" - -// TODO clarify address expectations, and make them more uniform. -// TODO i.e. do we expect types to be set already? -// TODO and do we expect modifications or copies? - -/** - * Computes up the chains - */ -static void gen_chains( - unsigned char *out, - const unsigned char *in, - unsigned int start[SPX_WOTS_LEN], - const unsigned int steps[SPX_WOTS_LEN], - const spx_ctx *ctx, - uint32_t addr[8]) { - uint32_t i, j, k, idx, watching; - int done; - unsigned char empty[SPX_N]; - unsigned char *bufs[8]; - uint32_t addrs[8 * 8]; - - int l; - uint16_t counts[SPX_WOTS_W] = { 0 }; - uint16_t idxs[SPX_WOTS_LEN]; - uint16_t total, newTotal; - - /* set addrs = {addr, addr, ..., addr} */ - for (j = 0; j < 8; j++) { - memcpy(addrs + j * 8, addr, sizeof(uint32_t) * 8); - } - - /* Initialize out with the value at position 'start'. */ - memcpy(out, in, SPX_WOTS_LEN * SPX_N); - - /* Sort the chains in reverse order by steps using counting sort. */ - for (i = 0; i < SPX_WOTS_LEN; i++) { - counts[steps[i]]++; - } - total = 0; - for (l = SPX_WOTS_W - 1; l >= 0; l--) { - newTotal = counts[l] + total; - counts[l] = total; - total = newTotal; - } - for (i = 0; i < SPX_WOTS_LEN; i++) { - idxs[counts[steps[i]]] = (uint16_t)i; - counts[steps[i]]++; - } - - /* We got our work cut out for us: do it! */ - for (i = 0; i < SPX_WOTS_LEN; i += 8) { - for (j = 0; j < 8 && i + j < SPX_WOTS_LEN; j++) { - idx = idxs[i + j]; - set_chain_addr(addrs + j * 8, idx); - bufs[j] = out + SPX_N * idx; - } - - /* As the chains are sorted in reverse order, we know that the first - * chain is the longest and the last one is the shortest. We keep - * an eye on whether the last chain is done and then on the one before, - * et cetera. */ - watching = 7; - done = 0; - while (i + watching >= SPX_WOTS_LEN) { - bufs[watching] = &empty[0]; - watching--; - } - - for (k = 0;; k++) { - while (k == steps[idxs[i + watching]]) { - bufs[watching] = &empty[0]; - if (watching == 0) { - done = 1; - break; - } - watching--; - } - if (done) { - break; - } - for (j = 0; j < watching + 1; j++) { - set_hash_addr(addrs + j * 8, k + start[idxs[i + j]]); - } - - thashx8(bufs[0], bufs[1], bufs[2], bufs[3], - bufs[4], bufs[5], bufs[6], bufs[7], - bufs[0], bufs[1], bufs[2], bufs[3], - bufs[4], bufs[5], bufs[6], bufs[7], 1, ctx, addrs); - } - } -} - -/** - * base_w algorithm as described in draft. - * Interprets an array of bytes as integers in base w. - * This only works when log_w is a divisor of 8. - */ -static void base_w(unsigned int *output, const int out_len, - const unsigned char *input) { - int in = 0; - int out = 0; - unsigned char total = 0; - int bits = 0; - int consumed; - - for (consumed = 0; consumed < out_len; consumed++) { - if (bits == 0) { - total = input[in]; - in++; - bits += 8; - } - bits -= SPX_WOTS_LOGW; - output[out] = (total >> bits) & (SPX_WOTS_W - 1); - out++; - } -} - -/* Computes the WOTS+ checksum over a message (in base_w). */ -static void wots_checksum(unsigned int *csum_base_w, - const unsigned int *msg_base_w) { - unsigned int csum = 0; - unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; - unsigned int i; - - /* Compute checksum. */ - for (i = 0; i < SPX_WOTS_LEN1; i++) { - csum += SPX_WOTS_W - 1 - msg_base_w[i]; - } - - /* Convert checksum to base_w. */ - /* Make sure expected empty zero bits are the least significant bits. */ - csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); - ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); - base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); -} - -/* Takes a message and derives the matching chain lengths. */ -void chain_lengths(unsigned int *lengths, const unsigned char *msg) { - base_w(lengths, SPX_WOTS_LEN1, msg); - wots_checksum(lengths + SPX_WOTS_LEN1, lengths); -} - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const spx_ctx *ctx, uint32_t addr[8]) { - unsigned int steps[SPX_WOTS_LEN]; - unsigned int start[SPX_WOTS_LEN]; - uint32_t i; - - chain_lengths(start, msg); - - for (i = 0; i < SPX_WOTS_LEN; i++) { - steps[i] = SPX_WOTS_W - 1 - start[i]; - } - - gen_chains(pk, sig, start, steps, ctx, addr); -} - -/* - * This generates 8 sequential WOTS public keys - * It also generates the WOTS signature if leaf_info indicates - * that we're signing with one of these WOTS keys - */ -void wots_gen_leafx8(unsigned char *dest, - const spx_ctx *ctx, - uint32_t leaf_idx, void *v_info) { - struct leaf_info_x8 *info = v_info; - uint32_t *leaf_addr = info->leaf_addr; - uint32_t *pk_addr = info->pk_addr; - unsigned int i, j, k; - unsigned char pk_buffer[ 8 * SPX_WOTS_BYTES ]; - unsigned wots_offset = SPX_WOTS_BYTES; - unsigned char *buffer; - uint32_t wots_k_mask; - unsigned wots_sign_index; - - if (((leaf_idx ^ info->wots_sign_leaf) & ~7U) == 0) { - /* We're traversing the leaf that's signing; generate the WOTS */ - /* signature */ - wots_k_mask = 0; - wots_sign_index = info->wots_sign_leaf & 7; /* Which of of the 8 */ - /* slots do the signatures come from */ - } else { - /* Nope, we're just generating pk's; turn off the signature logic */ - wots_k_mask = ~0U; - wots_sign_index = 0; - } - - for (j = 0; j < 8; j++) { - set_keypair_addr( leaf_addr + j * 8, leaf_idx + j ); - set_keypair_addr( pk_addr + j * 8, leaf_idx + j ); - } - - for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { - uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k */ - /* to the step if we're generating a signature, ~0 if we're not */ - - /* Start with the secret seed */ - for (j = 0; j < 8; j++) { - set_chain_addr(leaf_addr + j * 8, i); - set_hash_addr(leaf_addr + j * 8, 0); - set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTSPRF); - } - prf_addrx8(buffer + 0 * wots_offset, - buffer + 1 * wots_offset, - buffer + 2 * wots_offset, - buffer + 3 * wots_offset, - buffer + 4 * wots_offset, - buffer + 5 * wots_offset, - buffer + 6 * wots_offset, - buffer + 7 * wots_offset, - ctx, leaf_addr); - - for (j = 0; j < 8; j++) { - set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTS); - } - - /* Iterate down the WOTS chain */ - for (k = 0;; k++) { - /* Check if one of the values we have needs to be saved as a */ - /* part of the WOTS signature */ - if (k == wots_k) { - memcpy( info->wots_sig + i * SPX_N, - buffer + wots_sign_index * wots_offset, SPX_N ); - } - - /* Check if we hit the top of the chain */ - if (k == SPX_WOTS_W - 1) { - break; - } - - /* Iterate one step on all 8 chains */ - for (j = 0; j < 8; j++) { - set_hash_addr(leaf_addr + j * 8, k); - } - thashx8(buffer + 0 * wots_offset, - buffer + 1 * wots_offset, - buffer + 2 * wots_offset, - buffer + 3 * wots_offset, - buffer + 4 * wots_offset, - buffer + 5 * wots_offset, - buffer + 6 * wots_offset, - buffer + 7 * wots_offset, - buffer + 0 * wots_offset, - buffer + 1 * wots_offset, - buffer + 2 * wots_offset, - buffer + 3 * wots_offset, - buffer + 4 * wots_offset, - buffer + 5 * wots_offset, - buffer + 6 * wots_offset, - buffer + 7 * wots_offset, 1, ctx, leaf_addr); - } - } - - /* Do the final thash to generate the public keys */ - thashx8(dest + 0 * SPX_N, - dest + 1 * SPX_N, - dest + 2 * SPX_N, - dest + 3 * SPX_N, - dest + 4 * SPX_N, - dest + 5 * SPX_N, - dest + 6 * SPX_N, - dest + 7 * SPX_N, - pk_buffer + 0 * wots_offset, - pk_buffer + 1 * wots_offset, - pk_buffer + 2 * wots_offset, - pk_buffer + 3 * wots_offset, - pk_buffer + 4 * wots_offset, - pk_buffer + 5 * wots_offset, - pk_buffer + 6 * wots_offset, - pk_buffer + 7 * wots_offset, SPX_WOTS_LEN, ctx, pk_addr); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/wots.h b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/wots.h deleted file mode 100644 index 4e7692eeef..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/wots.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef SPX_WOTS_H -#define SPX_WOTS_H - -#include - -#include "context.h" -#include "params.h" - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) -void wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const spx_ctx *ctx, uint32_t addr[8]); - -/* - * Compute the chain lengths needed for a given message hash - */ -#define chain_lengths SPX_NAMESPACE(chain_lengths) -void chain_lengths(unsigned int *lengths, const unsigned char *msg); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/wotsx8.h b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/wotsx8.h deleted file mode 100644 index 10866efb35..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_avx2/wotsx8.h +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef WOTSX8_H_ -#define WOTSX8_H_ - -#include - -#include "context.h" -#include "params.h" - -/* - * This is here to provide an interface to the internal wots_gen_leafx8 - * routine. While this routine is not referenced in the package outside of - * wots.c, it is called from the stand-alone benchmark code to characterize - * the performance - */ -struct leaf_info_x8 { - unsigned char *wots_sig; - uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ - uint32_t *wots_steps; - uint32_t leaf_addr[8 * 8]; - uint32_t pk_addr[8 * 8]; -}; - -/* Macro to set the leaf_info to something 'benign', that is, it would */ -/* run with the same time as it does during the real signing process */ -/* Used only by the benchmark code */ -#define INITIALIZE_LEAF_INFO_X8(info, addr, step_buffer) { \ - (info).wots_sig = 0; \ - (info).wots_sign_leaf = ~0; \ - (info).wots_steps = step_buffer; \ - int i; \ - for (i=0; i<8; i++) { \ - memcpy( &(info).leaf_addr[8*i], addr, 32 ); \ - memcpy( &(info).pk_addr[8*i], addr, 32 ); \ - } \ - } - -#define wots_gen_leafx8 SPX_NAMESPACE(wots_gen_leafx8) -void wots_gen_leafx8(unsigned char *dest, - const spx_ctx *ctx, - uint32_t leaf_idx, void *v_info); - -#endif /* WOTSX8_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/LICENSE b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/LICENSE deleted file mode 100644 index 670154e353..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/LICENSE +++ /dev/null @@ -1,116 +0,0 @@ -CC0 1.0 Universal - -Statement of Purpose - -The laws of most jurisdictions throughout the world automatically confer -exclusive Copyright and Related Rights (defined below) upon the creator and -subsequent owner(s) (each and all, an "owner") of an original work of -authorship and/or a database (each, a "Work"). - -Certain owners wish to permanently relinquish those rights to a Work for the -purpose of contributing to a commons of creative, cultural and scientific -works ("Commons") that the public can reliably and without fear of later -claims of infringement build upon, modify, incorporate in other works, reuse -and redistribute as freely as possible in any form whatsoever and for any -purposes, including without limitation commercial purposes. These owners may -contribute to the Commons to promote the ideal of a free culture and the -further production of creative, cultural and scientific works, or to gain -reputation or greater distribution for their Work in part through the use and -efforts of others. - -For these and/or other purposes and motivations, and without any expectation -of additional consideration or compensation, the person associating CC0 with a -Work (the "Affirmer"), to the extent that he or she is an owner of Copyright -and Related Rights in the Work, voluntarily elects to apply CC0 to the Work -and publicly distribute the Work under its terms, with knowledge of his or her -Copyright and Related Rights in the Work and the meaning and intended legal -effect of CC0 on those rights. - -1. Copyright and Related Rights. A Work made available under CC0 may be -protected by copyright and related or neighboring rights ("Copyright and -Related Rights"). Copyright and Related Rights include, but are not limited -to, the following: - - i. the right to reproduce, adapt, distribute, perform, display, communicate, - and translate a Work; - - ii. moral rights retained by the original author(s) and/or performer(s); - - iii. publicity and privacy rights pertaining to a person's image or likeness - depicted in a Work; - - iv. rights protecting against unfair competition in regards to a Work, - subject to the limitations in paragraph 4(a), below; - - v. rights protecting the extraction, dissemination, use and reuse of data in - a Work; - - vi. database rights (such as those arising under Directive 96/9/EC of the - European Parliament and of the Council of 11 March 1996 on the legal - protection of databases, and under any national implementation thereof, - including any amended or successor version of such directive); and - - vii. other similar, equivalent or corresponding rights throughout the world - based on applicable law or treaty, and any national implementations thereof. - -2. Waiver. To the greatest extent permitted by, but not in contravention of, -applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and -unconditionally waives, abandons, and surrenders all of Affirmer's Copyright -and Related Rights and associated claims and causes of action, whether now -known or unknown (including existing as well as future claims and causes of -action), in the Work (i) in all territories worldwide, (ii) for the maximum -duration provided by applicable law or treaty (including future time -extensions), (iii) in any current or future medium and for any number of -copies, and (iv) for any purpose whatsoever, including without limitation -commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes -the Waiver for the benefit of each member of the public at large and to the -detriment of Affirmer's heirs and successors, fully intending that such Waiver -shall not be subject to revocation, rescission, cancellation, termination, or -any other legal or equitable action to disrupt the quiet enjoyment of the Work -by the public as contemplated by Affirmer's express Statement of Purpose. - -3. Public License Fallback. Should any part of the Waiver for any reason be -judged legally invalid or ineffective under applicable law, then the Waiver -shall be preserved to the maximum extent permitted taking into account -Affirmer's express Statement of Purpose. In addition, to the extent the Waiver -is so judged Affirmer hereby grants to each affected person a royalty-free, -non transferable, non sublicensable, non exclusive, irrevocable and -unconditional license to exercise Affirmer's Copyright and Related Rights in -the Work (i) in all territories worldwide, (ii) for the maximum duration -provided by applicable law or treaty (including future time extensions), (iii) -in any current or future medium and for any number of copies, and (iv) for any -purpose whatsoever, including without limitation commercial, advertising or -promotional purposes (the "License"). The License shall be deemed effective as -of the date CC0 was applied by Affirmer to the Work. Should any part of the -License for any reason be judged legally invalid or ineffective under -applicable law, such partial invalidity or ineffectiveness shall not -invalidate the remainder of the License, and in such case Affirmer hereby -affirms that he or she will not (i) exercise any of his or her remaining -Copyright and Related Rights in the Work or (ii) assert any associated claims -and causes of action with respect to the Work, in either case contrary to -Affirmer's express Statement of Purpose. - -4. Limitations and Disclaimers. - - a. No trademark or patent rights held by Affirmer are waived, abandoned, - surrendered, licensed or otherwise affected by this document. - - b. Affirmer offers the Work as-is and makes no representations or warranties - of any kind concerning the Work, express, implied, statutory or otherwise, - including without limitation warranties of title, merchantability, fitness - for a particular purpose, non infringement, or the absence of latent or - other defects, accuracy, or the present or absence of errors, whether or not - discoverable, all to the greatest extent permissible under applicable law. - - c. Affirmer disclaims responsibility for clearing rights of other persons - that may apply to the Work or any use thereof, including without limitation - any person's Copyright and Related Rights in the Work. Further, Affirmer - disclaims responsibility for obtaining any necessary consents, permissions - or other rights required for any use of the Work. - - d. Affirmer understands and acknowledges that Creative Commons is not a - party to this document and has no duty or obligation with respect to this - CC0 or use of the Work. - -For more information, please see - diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/address.c b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/address.c deleted file mode 100644 index b956e9cb29..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/address.c +++ /dev/null @@ -1,91 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "utils.h" - -/* - * Specify which level of Merkle tree (the "layer") we're working on - */ -void set_layer_addr(uint32_t addr[8], uint32_t layer) { - ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; -} - -/* - * Specify which Merkle tree within the level (the "tree address") we're working on - */ -void set_tree_addr(uint32_t addr[8], uint64_t tree) { - ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); -} - -/* - * Specify the reason we'll use this address structure for, that is, what - * hash will we compute with it. This is used so that unrelated types of - * hashes don't accidentally get the same address structure. The type will be - * one of the SPX_ADDR_TYPE constants - */ -void set_type(uint32_t addr[8], uint32_t type) { - ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; -} - -/* - * Copy the layer and tree fields of the address structure. This is used - * when we're doing multiple types of hashes within the same Merkle tree - */ -void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { - memcpy( out, in, SPX_OFFSET_TREE + 8 ); -} - -/* These functions are used for OTS addresses. */ - -/* - * Specify which Merkle leaf we're working on; that is, which OTS keypair - * we're talking about. - */ -void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { - ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; -} - -/* - * Copy the layer, tree and keypair fields of the address structure. This is - * used when we're doing multiple things within the same OTS keypair - */ -void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { - memcpy( out, in, SPX_OFFSET_TREE + 8 ); - ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; -} - -/* - * Specify which Merkle chain within the OTS we're working with - * (the chain address) - */ -void set_chain_addr(uint32_t addr[8], uint32_t chain) { - ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; -} - -/* - * Specify where in the Merkle chain we are -* (the hash address) - */ -void set_hash_addr(uint32_t addr[8], uint32_t hash) { - ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; -} - -/* These functions are used for all hash tree addresses (including FORS). */ - -/* - * Specify the height of the node in the Merkle/FORS tree we are in - * (the tree height) - */ -void set_tree_height(uint32_t addr[8], uint32_t tree_height) { - ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; -} - -/* - * Specify the distance from the left edge of the node in the Merkle/FORS tree - * (the tree index) - */ -void set_tree_index(uint32_t addr[8], uint32_t tree_index) { - u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/address.h b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/address.h deleted file mode 100644 index 24a84eb40c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/address.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef SPX_ADDRESS_H -#define SPX_ADDRESS_H - -#include - -#include "params.h" - -/* The hash types that are passed to set_type */ -#define SPX_ADDR_TYPE_WOTS 0 -#define SPX_ADDR_TYPE_WOTSPK 1 -#define SPX_ADDR_TYPE_HASHTREE 2 -#define SPX_ADDR_TYPE_FORSTREE 3 -#define SPX_ADDR_TYPE_FORSPK 4 -#define SPX_ADDR_TYPE_WOTSPRF 5 -#define SPX_ADDR_TYPE_FORSPRF 6 - -#define set_layer_addr SPX_NAMESPACE(set_layer_addr) -void set_layer_addr(uint32_t addr[8], uint32_t layer); - -#define set_tree_addr SPX_NAMESPACE(set_tree_addr) -void set_tree_addr(uint32_t addr[8], uint64_t tree); - -#define set_type SPX_NAMESPACE(set_type) -void set_type(uint32_t addr[8], uint32_t type); - -/* Copies the layer and tree part of one address into the other */ -#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) -void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for WOTS and FORS addresses. */ - -#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) -void set_keypair_addr(uint32_t addr[8], uint32_t keypair); - -#define set_chain_addr SPX_NAMESPACE(set_chain_addr) -void set_chain_addr(uint32_t addr[8], uint32_t chain); - -#define set_hash_addr SPX_NAMESPACE(set_hash_addr) -void set_hash_addr(uint32_t addr[8], uint32_t hash); - -#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) -void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for all hash tree addresses (including FORS). */ - -#define set_tree_height SPX_NAMESPACE(set_tree_height) -void set_tree_height(uint32_t addr[8], uint32_t tree_height); - -#define set_tree_index SPX_NAMESPACE(set_tree_index) -void set_tree_index(uint32_t addr[8], uint32_t tree_index); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/api.h b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/api.h deleted file mode 100644 index 24875d652c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/api.h +++ /dev/null @@ -1,77 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA2192FROBUST_CLEAN_API_H -#define PQCLEAN_SPHINCSSHA2192FROBUST_CLEAN_API_H - -#include -#include - -#define PQCLEAN_SPHINCSSHA2192FROBUST_CLEAN_CRYPTO_ALGNAME "SPHINCS+-sha2-192f-robust" - -#define PQCLEAN_SPHINCSSHA2192FROBUST_CLEAN_CRYPTO_SECRETKEYBYTES 96 -#define PQCLEAN_SPHINCSSHA2192FROBUST_CLEAN_CRYPTO_PUBLICKEYBYTES 48 -#define PQCLEAN_SPHINCSSHA2192FROBUST_CLEAN_CRYPTO_BYTES 35664 - -#define PQCLEAN_SPHINCSSHA2192FROBUST_CLEAN_CRYPTO_SEEDBYTES 72 - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSSHA2192FROBUST_CLEAN_crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSSHA2192FROBUST_CLEAN_crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSSHA2192FROBUST_CLEAN_crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSSHA2192FROBUST_CLEAN_crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHA2192FROBUST_CLEAN_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHA2192FROBUST_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSSHA2192FROBUST_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSSHA2192FROBUST_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, - const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSSHA2192FROBUST_CLEAN_crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSSHA2192FROBUST_CLEAN_crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk); -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/context.h b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/context.h deleted file mode 100644 index 97e2e2469e..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/context.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef SPX_CONTEXT_H -#define SPX_CONTEXT_H - -#include -#include - -#include "params.h" -#include "sha2.h" - -typedef struct { - uint8_t pub_seed[SPX_N]; - uint8_t sk_seed[SPX_N]; - - // sha256 state that absorbed pub_seed - sha256ctx state_seeded; - - // sha512 state that absorbed pub_seed - sha512ctx state_seeded_512; - -} spx_ctx; - -#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) -void initialize_hash_function(spx_ctx *ctx); - -#define free_hash_function SPX_NAMESPACE(free_hash_function) -void free_hash_function(spx_ctx *ctx); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/context_sha2.c b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/context_sha2.c deleted file mode 100644 index 9ca9f4e7ac..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/context_sha2.c +++ /dev/null @@ -1,36 +0,0 @@ -#include "context.h" - -/** - * Absorb the constant pub_seed using one round of the compression function - * This initializes state_seeded and state_seeded_512, which can then be - * reused in thash - **/ -static void seed_state(spx_ctx *ctx) { - uint8_t block[SPX_SHA512_BLOCK_BYTES]; - size_t i; - - for (i = 0; i < SPX_N; ++i) { - block[i] = ctx->pub_seed[i]; - } - for (i = SPX_N; i < SPX_SHA512_BLOCK_BYTES; ++i) { - block[i] = 0; - } - /* block has been properly initialized for both SHA-256 and SHA-512 */ - - sha256_inc_init(&ctx->state_seeded); - sha256_inc_blocks(&ctx->state_seeded, block, 1); - sha512_inc_init(&ctx->state_seeded_512); - sha512_inc_blocks(&ctx->state_seeded_512, block, 1); -} - - -/* We initialize the state for the hash functions */ -void initialize_hash_function(spx_ctx *ctx) { - seed_state(ctx); -} - -/* Free the incremental hashing context for heap-based SHA2 APIs */ -void free_hash_function(spx_ctx *ctx) { - sha256_inc_ctx_release(&ctx->state_seeded); - sha512_inc_ctx_release(&ctx->state_seeded_512); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/fors.c b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/fors.c deleted file mode 100644 index 96ca72e986..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/fors.c +++ /dev/null @@ -1,156 +0,0 @@ -#include -#include -#include - -#include "fors.h" - -#include "address.h" -#include "hash.h" -#include "thash.h" -#include "utils.h" -#include "utilsx1.h" - -static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, - uint32_t fors_leaf_addr[8]) { - prf_addr(sk, ctx, fors_leaf_addr); -} - -static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, - const spx_ctx *ctx, - uint32_t fors_leaf_addr[8]) { - thash(leaf, sk, 1, ctx, fors_leaf_addr); -} - -struct fors_gen_leaf_info { - uint32_t leaf_addrx[8]; -}; - -static void fors_gen_leafx1(unsigned char *leaf, - const spx_ctx *ctx, - uint32_t addr_idx, void *info) { - struct fors_gen_leaf_info *fors_info = info; - uint32_t *fors_leaf_addr = fors_info->leaf_addrx; - - /* Only set the parts that the caller doesn't set */ - set_tree_index(fors_leaf_addr, addr_idx); - set_type(fors_leaf_addr, SPX_ADDR_TYPE_FORSPRF); - fors_gen_sk(leaf, ctx, fors_leaf_addr); - - set_type(fors_leaf_addr, SPX_ADDR_TYPE_FORSTREE); - fors_sk_to_leaf(leaf, leaf, - ctx, fors_leaf_addr); -} - -/** - * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - * Assumes indices has space for SPX_FORS_TREES integers. - */ -static void message_to_indices(uint32_t *indices, const unsigned char *m) { - unsigned int i, j; - unsigned int offset = 0; - - for (i = 0; i < SPX_FORS_TREES; i++) { - indices[i] = 0; - for (j = 0; j < SPX_FORS_HEIGHT; j++) { - indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); - offset++; - } - } -} - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -void fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]) { - uint32_t indices[SPX_FORS_TREES]; - unsigned char roots[SPX_FORS_TREES * SPX_N]; - uint32_t fors_tree_addr[8] = {0}; - struct fors_gen_leaf_info fors_info = {0}; - uint32_t *fors_leaf_addr = fors_info.leaf_addrx; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - copy_keypair_addr(fors_tree_addr, fors_addr); - copy_keypair_addr(fors_leaf_addr, fors_addr); - - copy_keypair_addr(fors_pk_addr, fors_addr); - set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < SPX_FORS_TREES; i++) { - idx_offset = i * (1 << SPX_FORS_HEIGHT); - - set_tree_height(fors_tree_addr, 0); - set_tree_index(fors_tree_addr, indices[i] + idx_offset); - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); - - /* Include the secret key part that produces the selected leaf node. */ - fors_gen_sk(sig, ctx, fors_tree_addr); - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); - sig += SPX_N; - - /* Compute the authentication path for this leaf node. */ - treehashx1(roots + i * SPX_N, sig, ctx, - indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx1, - fors_tree_addr, &fors_info); - - sig += SPX_N * SPX_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); -} - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -void fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]) { - uint32_t indices[SPX_FORS_TREES]; - unsigned char roots[SPX_FORS_TREES * SPX_N]; - unsigned char leaf[SPX_N]; - uint32_t fors_tree_addr[8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - copy_keypair_addr(fors_tree_addr, fors_addr); - copy_keypair_addr(fors_pk_addr, fors_addr); - - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); - set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < SPX_FORS_TREES; i++) { - idx_offset = i * (1 << SPX_FORS_HEIGHT); - - set_tree_height(fors_tree_addr, 0); - set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Derive the leaf from the included secret key part. */ - fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); - sig += SPX_N; - - /* Derive the corresponding root node of this tree. */ - compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, - sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); - sig += SPX_N * SPX_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/fors.h b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/fors.h deleted file mode 100644 index 509140a178..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/fors.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef SPX_FORS_H -#define SPX_FORS_H - -#include - -#include "context.h" -#include "params.h" - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -#define fors_sign SPX_NAMESPACE(fors_sign) -void fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]); - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) -void fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/hash.h b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/hash.h deleted file mode 100644 index ffe815f45d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/hash.h +++ /dev/null @@ -1,37 +0,0 @@ -#ifndef SPX_HASH_H -#define SPX_HASH_H - -#include -#include - -#include "context.h" -#include "params.h" - -#define prf_addr SPX_NAMESPACE(prf_addr) -void prf_addr(unsigned char *out, const spx_ctx *ctx, - const uint32_t addr[8]); - -#define gen_message_random SPX_NAMESPACE(gen_message_random) -void gen_message_random(unsigned char *R, const unsigned char *sk_prf, - const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx); - -#define hash_message SPX_NAMESPACE(hash_message) -void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx); - - -# define SPX_SHA256_ADDR_BYTES 22 - -# define mgf1_256 SPX_NAMESPACE(mgf1_256) -void mgf1_256(unsigned char *out, unsigned long outlen, - const unsigned char *in, unsigned long inlen); - -# define mgf1_512 SPX_NAMESPACE(mgf1_512) -void mgf1_512(unsigned char *out, unsigned long outlen, - const unsigned char *in, unsigned long inlen); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/hash_sha2.c b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/hash_sha2.c deleted file mode 100644 index 3d0085c8c1..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/hash_sha2.c +++ /dev/null @@ -1,219 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "sha2.h" -#include "utils.h" - - - -#define SPX_SHAX_OUTPUT_BYTES SPX_SHA512_OUTPUT_BYTES -#define SPX_SHAX_BLOCK_BYTES SPX_SHA512_BLOCK_BYTES -#define shaX_inc_init sha512_inc_init -#define shaX_inc_blocks sha512_inc_blocks -#define shaX_inc_finalize sha512_inc_finalize -#define shaX sha512 -#define mgf1_X mgf1_512 -#define shaXstate sha512ctx - -/** - * mgf1 function based on the SHA-256 hash function - * Note that inlen should be sufficiently small that it still allows for - * an array to be allocated on the stack. Typically 'in' is merely a seed. - * Outputs outlen number of bytes - */ -void mgf1_256(unsigned char *out, unsigned long outlen, - const unsigned char *in, unsigned long inlen) { - PQCLEAN_VLA(uint8_t, inbuf, inlen + 4); - unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES]; - uint32_t i; - - memcpy(inbuf, in, inlen); - - /* While we can fit in at least another full block of SHA256 output.. */ - for (i = 0; (i + 1)*SPX_SHA256_OUTPUT_BYTES <= outlen; i++) { - u32_to_bytes(inbuf + inlen, i); - sha256(out, inbuf, inlen + 4); - out += SPX_SHA256_OUTPUT_BYTES; - } - /* Until we cannot anymore, and we fill the remainder. */ - if (outlen > i * SPX_SHA256_OUTPUT_BYTES) { - u32_to_bytes(inbuf + inlen, i); - sha256(outbuf, inbuf, inlen + 4); - memcpy(out, outbuf, outlen - i * SPX_SHA256_OUTPUT_BYTES); - } -} - -/* - * mgf1 function based on the SHA-512 hash function - */ -void mgf1_512(unsigned char *out, unsigned long outlen, - const unsigned char *in, unsigned long inlen) { - PQCLEAN_VLA(uint8_t, inbuf, inlen + 4); - unsigned char outbuf[SPX_SHA512_OUTPUT_BYTES]; - uint32_t i; - - memcpy(inbuf, in, inlen); - - /* While we can fit in at least another full block of SHA512 output.. */ - for (i = 0; (i + 1)*SPX_SHA512_OUTPUT_BYTES <= outlen; i++) { - u32_to_bytes(inbuf + inlen, i); - sha512(out, inbuf, inlen + 4); - out += SPX_SHA512_OUTPUT_BYTES; - } - /* Until we cannot anymore, and we fill the remainder. */ - if (outlen > i * SPX_SHA512_OUTPUT_BYTES) { - u32_to_bytes(inbuf + inlen, i); - sha512(outbuf, inbuf, inlen + 4); - memcpy(out, outbuf, outlen - i * SPX_SHA512_OUTPUT_BYTES); - } -} - -/* - * Computes PRF(pk_seed, sk_seed, addr). - */ -void prf_addr(unsigned char *out, const spx_ctx *ctx, - const uint32_t addr[8]) { - sha256ctx sha2_state; - unsigned char buf[SPX_SHA256_ADDR_BYTES + SPX_N]; - unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES]; - - /* Retrieve precomputed state containing pub_seed */ - sha256_inc_ctx_clone(&sha2_state, &ctx->state_seeded); - - /* Remainder: ADDR^c ‖ SK.seed */ - memcpy(buf, addr, SPX_SHA256_ADDR_BYTES); - memcpy(buf + SPX_SHA256_ADDR_BYTES, ctx->sk_seed, SPX_N); - - sha256_inc_finalize(outbuf, &sha2_state, buf, SPX_SHA256_ADDR_BYTES + SPX_N); - - memcpy(out, outbuf, SPX_N); -} - -/** - * Computes the message-dependent randomness R, using a secret seed as a key - * for HMAC, and an optional randomization value prefixed to the message. - * This requires m to have at least SPX_SHAX_BLOCK_BYTES + SPX_N space - * available in front of the pointer, i.e. before the message to use for the - * prefix. This is necessary to prevent having to move the message around (and - * allocate memory for it). - */ -void gen_message_random(unsigned char *R, const unsigned char *sk_prf, - const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx) { - (void)ctx; - - unsigned char buf[SPX_SHAX_BLOCK_BYTES + SPX_SHAX_OUTPUT_BYTES]; - shaXstate state; - int i; - - - /* This implements HMAC-SHA */ - for (i = 0; i < SPX_N; i++) { - buf[i] = 0x36 ^ sk_prf[i]; - } - memset(buf + SPX_N, 0x36, SPX_SHAX_BLOCK_BYTES - SPX_N); - - shaX_inc_init(&state); - shaX_inc_blocks(&state, buf, 1); - - memcpy(buf, optrand, SPX_N); - - /* If optrand + message cannot fill up an entire block */ - if (SPX_N + mlen < SPX_SHAX_BLOCK_BYTES) { - memcpy(buf + SPX_N, m, mlen); - shaX_inc_finalize(buf + SPX_SHAX_BLOCK_BYTES, &state, - buf, mlen + SPX_N); - } - /* Otherwise first fill a block, so that finalize only uses the message */ - else { - memcpy(buf + SPX_N, m, SPX_SHAX_BLOCK_BYTES - SPX_N); - shaX_inc_blocks(&state, buf, 1); - - m += SPX_SHAX_BLOCK_BYTES - SPX_N; - mlen -= SPX_SHAX_BLOCK_BYTES - SPX_N; - shaX_inc_finalize(buf + SPX_SHAX_BLOCK_BYTES, &state, m, mlen); - } - - for (i = 0; i < SPX_N; i++) { - buf[i] = 0x5c ^ sk_prf[i]; - } - memset(buf + SPX_N, 0x5c, SPX_SHAX_BLOCK_BYTES - SPX_N); - - shaX(buf, buf, SPX_SHAX_BLOCK_BYTES + SPX_SHAX_OUTPUT_BYTES); - memcpy(R, buf, SPX_N); -} - -/** - * Computes the message hash using R, the public key, and the message. - * Outputs the message digest and the index of the leaf. The index is split in - * the tree index and the leaf index, for convenient copying to an address. - */ -void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx) { - (void)ctx; -#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) -#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) -#define SPX_LEAF_BITS SPX_TREE_HEIGHT -#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) -#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) - - unsigned char seed[2 * SPX_N + SPX_SHAX_OUTPUT_BYTES]; - - /* Round to nearest multiple of SPX_SHAX_BLOCK_BYTES */ -#define SPX_INBLOCKS (((SPX_N + SPX_PK_BYTES + SPX_SHAX_BLOCK_BYTES - 1) & \ - -SPX_SHAX_BLOCK_BYTES) / SPX_SHAX_BLOCK_BYTES) - unsigned char inbuf[SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES]; - - unsigned char buf[SPX_DGST_BYTES]; - unsigned char *bufp = buf; - shaXstate state; - - shaX_inc_init(&state); - - // seed: SHA-X(R ‖ PK.seed ‖ PK.root ‖ M) - memcpy(inbuf, R, SPX_N); - memcpy(inbuf + SPX_N, pk, SPX_PK_BYTES); - - /* If R + pk + message cannot fill up an entire block */ - if (SPX_N + SPX_PK_BYTES + mlen < SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES) { - memcpy(inbuf + SPX_N + SPX_PK_BYTES, m, mlen); - shaX_inc_finalize(seed + 2 * SPX_N, &state, inbuf, SPX_N + SPX_PK_BYTES + mlen); - } - /* Otherwise first fill a block, so that finalize only uses the message */ - else { - memcpy(inbuf + SPX_N + SPX_PK_BYTES, m, - SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES - SPX_N - SPX_PK_BYTES); - shaX_inc_blocks(&state, inbuf, SPX_INBLOCKS); - - m += SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES - SPX_N - SPX_PK_BYTES; - mlen -= SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES - SPX_N - SPX_PK_BYTES; - shaX_inc_finalize(seed + 2 * SPX_N, &state, m, (size_t)mlen); - } - - // H_msg: MGF1-SHA-X(R ‖ PK.seed ‖ seed) - memcpy(seed, R, SPX_N); - memcpy(seed + SPX_N, pk, SPX_N); - - /* By doing this in two steps, we prevent hashing the message twice; - otherwise each iteration in MGF1 would hash the message again. */ - mgf1_X(bufp, SPX_DGST_BYTES, seed, 2 * SPX_N + SPX_SHAX_OUTPUT_BYTES); - - memcpy(digest, bufp, SPX_FORS_MSG_BYTES); - bufp += SPX_FORS_MSG_BYTES; - - - *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); - *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); - bufp += SPX_TREE_BYTES; - - *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); - *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); -} - - diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/merkle.c b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/merkle.c deleted file mode 100644 index 0c1479fd93..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/merkle.c +++ /dev/null @@ -1,59 +0,0 @@ -#include -#include - -#include "address.h" -#include "merkle.h" -#include "params.h" -#include "utils.h" -#include "utilsx1.h" -#include "wots.h" -#include "wotsx1.h" - -/* - * This generates a Merkle signature (WOTS signature followed by the Merkle - * authentication path). This is in this file because most of the complexity - * is involved with the WOTS signature; the Merkle authentication path logic - * is mostly hidden in treehashx4 - */ -void merkle_sign(uint8_t *sig, unsigned char *root, - const spx_ctx *ctx, - uint32_t wots_addr[8], uint32_t tree_addr[8], - uint32_t idx_leaf) { - unsigned char *auth_path = sig + SPX_WOTS_BYTES; - struct leaf_info_x1 info = { 0 }; - unsigned steps[ SPX_WOTS_LEN ]; - - info.wots_sig = sig; - chain_lengths(steps, root); - info.wots_steps = steps; - - set_type(&tree_addr[0], SPX_ADDR_TYPE_HASHTREE); - set_type(&info.pk_addr[0], SPX_ADDR_TYPE_WOTSPK); - copy_subtree_addr(&info.leaf_addr[0], wots_addr); - copy_subtree_addr(&info.pk_addr[0], wots_addr); - - info.wots_sign_leaf = idx_leaf; - - treehashx1(root, auth_path, ctx, - idx_leaf, 0, - SPX_TREE_HEIGHT, - wots_gen_leafx1, - tree_addr, &info); -} - -/* Compute root node of the top-most subtree. */ -void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { - /* We do not need the auth path in key generation, but it simplifies the - code to have just one treehash routine that computes both root and path - in one function. */ - unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; - uint32_t top_tree_addr[8] = {0}; - uint32_t wots_addr[8] = {0}; - - set_layer_addr(top_tree_addr, SPX_D - 1); - set_layer_addr(wots_addr, SPX_D - 1); - - merkle_sign(auth_path, root, ctx, - wots_addr, top_tree_addr, - (uint32_t)~0 /* ~0 means "don't bother generating an auth path */ ); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/merkle.h b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/merkle.h deleted file mode 100644 index 769cf2e970..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/merkle.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef MERKLE_H_ -#define MERKLE_H_ - -#include - -#include "context.h" -#include "params.h" - -/* Generate a Merkle signature (WOTS signature followed by the Merkle */ -/* authentication path) */ -#define merkle_sign SPX_NAMESPACE(merkle_sign) -void merkle_sign(uint8_t *sig, unsigned char *root, - const spx_ctx *ctx, - uint32_t wots_addr[8], uint32_t tree_addr[8], - uint32_t idx_leaf); - -/* Compute the root node of the top-most subtree. */ -#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) -void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); - -#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/nistapi.h b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/nistapi.h deleted file mode 100644 index 3cb71afad4..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/nistapi.h +++ /dev/null @@ -1,87 +0,0 @@ -#ifndef SPX_API_H -#define SPX_API_H - -#include -#include - -#include "params.h" - -#define CRYPTO_ALGNAME "SPHINCS+" - -#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES -#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES -#define CRYPTO_BYTES SPX_BYTES -#define CRYPTO_SEEDBYTES (3*SPX_N) - -/* - * Returns the length of a secret key, in bytes - */ -#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) -size_t crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) -size_t crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) -size_t crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) -size_t crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) -int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) -int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) -int crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) -int crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -#define crypto_sign SPX_NAMESPACE(crypto_sign) -int crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) -int crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/params.h b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/params.h deleted file mode 100644 index 23704bcd52..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/params.h +++ /dev/null @@ -1,61 +0,0 @@ -#ifndef SPX_PARAMS_H -#define SPX_PARAMS_H - -#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSSHA2192FROBUST_CLEAN_##s - -/* Hash output length in bytes. */ -#define SPX_N 24 -/* Height of the hypertree. */ -#define SPX_FULL_HEIGHT 66 -/* Number of subtree layer. */ -#define SPX_D 22 -/* FORS tree dimensions. */ -#define SPX_FORS_HEIGHT 8 -#define SPX_FORS_TREES 33 -/* Winternitz parameter, */ -#define SPX_WOTS_W 16 - -/* The hash function is defined by linking a different hash.c file, as opposed - to setting a #define constant. */ - -/* This is a SHA2-based parameter set, hence whether we use SHA-256 - * exclusively or we use both SHA-256 and SHA-512 is controlled by - * the following #define */ -#define SPX_SHA512 1 /* Use SHA-512 for H and T_l, l >= 2 */ - -/* For clarity */ -#define SPX_ADDR_BYTES 32 - -/* WOTS parameters. */ -#define SPX_WOTS_LOGW 4 - -#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) - -/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#define SPX_WOTS_LEN2 3 - -#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) -#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) -#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES - -/* Subtree size. */ -#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) - -//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT -// #error SPX_D should always divide SPX_FULL_HEIGHT -//#endif - -/* FORS parameters. */ -#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) -#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) -#define SPX_FORS_PK_BYTES SPX_N - -/* Resulting SPX sizes. */ -#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ - SPX_FULL_HEIGHT * SPX_N) -#define SPX_PK_BYTES (2 * SPX_N) -#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) - -#include "sha2_offsets.h" - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/sha2_offsets.h b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/sha2_offsets.h deleted file mode 100644 index 6e3584f7a4..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/sha2_offsets.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef SHA2_OFFSETS_H_ -#define SHA2_OFFSETS_H_ - -#define SPX_SHA256_BLOCK_BYTES 64 -#define SPX_SHA256_OUTPUT_BYTES 32 - -#define SPX_SHA512_BLOCK_BYTES 128 -#define SPX_SHA512_OUTPUT_BYTES 64 - -/* - * Offsets of various fields in the address structure when we use SHA2 as - * the Sphincs+ hash function - */ - -#define SPX_OFFSET_LAYER 0 /* The byte used to specify the Merkle tree layer */ -#define SPX_OFFSET_TREE 1 /* The start of the 8 byte field used to specify the tree */ -#define SPX_OFFSET_TYPE 9 /* The byte used to specify the hash type (reason) */ -#define SPX_OFFSET_KP_ADDR2 12 /* The high byte used to specify the key pair (which one-time signature) */ -#define SPX_OFFSET_KP_ADDR1 13 /* The low byte used to specify the key pair */ -#define SPX_OFFSET_CHAIN_ADDR 17 /* The byte used to specify the chain address (which Winternitz chain) */ -#define SPX_OFFSET_HASH_ADDR 21 /* The byte used to specify the hash address (where in the Winternitz chain) */ -#define SPX_OFFSET_TREE_HGT 17 /* The byte used to specify the height of this node in the FORS or Merkle tree */ -#define SPX_OFFSET_TREE_INDEX 18 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ - -#define SPX_SHA2 1 - -#endif /* SHA2_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/sign.c b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/sign.c deleted file mode 100644 index 9d0c7d1b22..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/sign.c +++ /dev/null @@ -1,286 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "context.h" -#include "fors.h" -#include "hash.h" -#include "merkle.h" -#include "nistapi.h" -#include "params.h" -#include "randombytes.h" -#include "thash.h" -#include "utils.h" -#include "wots.h" - -/* - * Returns the length of a secret key, in bytes - */ -size_t crypto_sign_secretkeybytes(void) { - return CRYPTO_SECRETKEYBYTES; -} - -/* - * Returns the length of a public key, in bytes - */ -size_t crypto_sign_publickeybytes(void) { - return CRYPTO_PUBLICKEYBYTES; -} - -/* - * Returns the length of a signature, in bytes - */ -size_t crypto_sign_bytes(void) { - return CRYPTO_BYTES; -} - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t crypto_sign_seedbytes(void) { - return CRYPTO_SEEDBYTES; -} - -/* - * Generates an SPX key pair given a seed of length - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed) { - spx_ctx ctx; - - /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ - memcpy(sk, seed, CRYPTO_SEEDBYTES); - - memcpy(pk, sk + 2 * SPX_N, SPX_N); - - memcpy(ctx.pub_seed, pk, SPX_N); - memcpy(ctx.sk_seed, sk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - /* Compute root node of the top-most subtree. */ - merkle_gen_root(sk + 3 * SPX_N, &ctx); - - // cleanup - free_hash_function(&ctx); - - memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); - - return 0; -} - -/* - * Generates an SPX key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { - uint8_t seed[CRYPTO_SEEDBYTES]; - randombytes(seed, CRYPTO_SEEDBYTES); - crypto_sign_seed_keypair(pk, sk, seed); - - return 0; -} - -/** - * Returns an array containing a detached signature. - */ -int crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - spx_ctx ctx; - - const uint8_t *sk_prf = sk + SPX_N; - const uint8_t *pk = sk + 2 * SPX_N; - - uint8_t optrand[SPX_N]; - uint8_t mhash[SPX_FORS_MSG_BYTES]; - uint8_t root[SPX_N]; - uint32_t i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - - memcpy(ctx.sk_seed, sk, SPX_N); - memcpy(ctx.pub_seed, pk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - set_type(wots_addr, SPX_ADDR_TYPE_WOTS); - set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); - - /* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ - randombytes(optrand, SPX_N); - /* Compute the digest randomization value. */ - gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); - - /* Derive the message digest and leaf index from R, PK and M. */ - hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); - sig += SPX_N; - - set_tree_addr(wots_addr, tree); - set_keypair_addr(wots_addr, idx_leaf); - - /* Sign the message hash using FORS. */ - fors_sign(sig, root, mhash, &ctx, wots_addr); - sig += SPX_FORS_BYTES; - - for (i = 0; i < SPX_D; i++) { - set_layer_addr(tree_addr, i); - set_tree_addr(tree_addr, tree); - - copy_subtree_addr(wots_addr, tree_addr); - set_keypair_addr(wots_addr, idx_leaf); - - merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); - sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); - tree = tree >> SPX_TREE_HEIGHT; - } - - free_hash_function(&ctx); - - *siglen = SPX_BYTES; - - return 0; -} - -/** - * Verifies a detached signature and message under a given public key. - */ -int crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk) { - spx_ctx ctx; - const uint8_t *pub_root = pk + SPX_N; - uint8_t mhash[SPX_FORS_MSG_BYTES]; - uint8_t wots_pk[SPX_WOTS_BYTES]; - uint8_t root[SPX_N]; - uint8_t leaf[SPX_N]; - unsigned int i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - if (siglen != SPX_BYTES) { - return -1; - } - - memcpy(ctx.pub_seed, pk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - set_type(wots_addr, SPX_ADDR_TYPE_WOTS); - set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); - set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); - - /* Derive the message digest and leaf index from R || PK || M. */ - /* The additional SPX_N is a result of the hash domain separator. */ - hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); - sig += SPX_N; - - /* Layer correctly defaults to 0, so no need to set_layer_addr */ - set_tree_addr(wots_addr, tree); - set_keypair_addr(wots_addr, idx_leaf); - - fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); - sig += SPX_FORS_BYTES; - - /* For each subtree.. */ - for (i = 0; i < SPX_D; i++) { - set_layer_addr(tree_addr, i); - set_tree_addr(tree_addr, tree); - - copy_subtree_addr(wots_addr, tree_addr); - set_keypair_addr(wots_addr, idx_leaf); - - copy_keypair_addr(wots_pk_addr, wots_addr); - - /* The WOTS public key is only correct if the signature was correct. */ - /* Initially, root is the FORS pk, but on subsequent iterations it is - the root of the subtree below the currently processed subtree. */ - wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); - sig += SPX_WOTS_BYTES; - - /* Compute the leaf node using the WOTS public key. */ - thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); - - /* Compute the root node of this subtree. */ - compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, - &ctx, tree_addr); - sig += SPX_TREE_HEIGHT * SPX_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); - tree = tree >> SPX_TREE_HEIGHT; - } - - // cleanup - free_hash_function(&ctx); - - /* Check if the root node equals the root node in the public key. */ - if (memcmp(root, pub_root, SPX_N) != 0) { - return -1; - } - - return 0; -} - - -/** - * Returns an array containing the signature followed by the message. - */ -int crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk) { - size_t siglen; - - crypto_sign_signature(sm, &siglen, m, mlen, sk); - - memmove(sm + SPX_BYTES, m, mlen); - *smlen = siglen + mlen; - - return 0; -} - -/** - * Verifies a given signature-message pair under a given public key. - */ -int crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk) { - /* The API caller does not necessarily know what size a signature should be - but SPHINCS+ signatures are always exactly SPX_BYTES. */ - if (smlen < SPX_BYTES) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - *mlen = smlen - SPX_BYTES; - - if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - /* If verification was successful, move the message to the right place. */ - memmove(m, sm + SPX_BYTES, *mlen); - - return 0; -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/thash.h b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/thash.h deleted file mode 100644 index 8687ccfb4d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/thash.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef SPX_THASH_H -#define SPX_THASH_H - -#include "context.h" -#include "params.h" - -#include - -#define thash SPX_NAMESPACE(thash) -void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/thash_sha2_robust.c b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/thash_sha2_robust.c deleted file mode 100644 index 3ab891175f..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/thash_sha2_robust.c +++ /dev/null @@ -1,68 +0,0 @@ -#include -#include - -#include "address.h" -#include "context.h" -#include "hash.h" -#include "params.h" -#include "sha2.h" -#include "thash.h" -#include "utils.h" - -static void thash_512(unsigned char *out, const unsigned char *in, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]); - -/** - * Takes an array of inblocks concatenated arrays of SPX_N bytes. - */ -void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]) { - if (inblocks > 1) { - thash_512(out, in, inblocks, ctx, addr); - return; - } - unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES]; - PQCLEAN_VLA(uint8_t, bitmask, inblocks * SPX_N); - PQCLEAN_VLA(uint8_t, buf, SPX_N + SPX_SHA256_OUTPUT_BYTES + inblocks * SPX_N); - sha256ctx sha2_state; - unsigned int i; - - memcpy(buf, ctx->pub_seed, SPX_N); - memcpy(buf + SPX_N, addr, SPX_SHA256_ADDR_BYTES); - mgf1_256(bitmask, inblocks * SPX_N, buf, SPX_N + SPX_SHA256_ADDR_BYTES); - - /* Retrieve precomputed state containing pub_seed */ - sha256_inc_ctx_clone(&sha2_state, &ctx->state_seeded); - - for (i = 0; i < inblocks * SPX_N; i++) { - buf[SPX_N + SPX_SHA256_ADDR_BYTES + i] = in[i] ^ bitmask[i]; - } - - sha256_inc_finalize(outbuf, &sha2_state, buf + SPX_N, - SPX_SHA256_ADDR_BYTES + inblocks * SPX_N); - memcpy(out, outbuf, SPX_N); -} - -static void thash_512(unsigned char *out, const unsigned char *in, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]) { - unsigned char outbuf[SPX_SHA512_OUTPUT_BYTES]; - PQCLEAN_VLA(uint8_t, bitmask, inblocks * SPX_N); - PQCLEAN_VLA(uint8_t, buf, SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N); - sha512ctx sha2_state; - unsigned int i; - - memcpy(buf, ctx->pub_seed, SPX_N); - memcpy(buf + SPX_N, addr, SPX_SHA256_ADDR_BYTES); - mgf1_512(bitmask, inblocks * SPX_N, buf, SPX_N + SPX_SHA256_ADDR_BYTES); - - /* Retrieve precomputed state containing pub_seed */ - sha512_inc_ctx_clone(&sha2_state, &ctx->state_seeded_512); - - for (i = 0; i < inblocks * SPX_N; i++) { - buf[SPX_N + SPX_SHA256_ADDR_BYTES + i] = in[i] ^ bitmask[i]; - } - - sha512_inc_finalize(outbuf, &sha2_state, buf + SPX_N, - SPX_SHA256_ADDR_BYTES + inblocks * SPX_N); - memcpy(out, outbuf, SPX_N); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/utils.c b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/utils.c deleted file mode 100644 index 177b541fb9..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/utils.c +++ /dev/null @@ -1,148 +0,0 @@ -#include - -#include "utils.h" - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "thash.h" - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void ull_to_bytes(unsigned char *out, unsigned int outlen, - unsigned long long in) { - int i; - - /* Iterate over out in decreasing order, for big-endianness. */ - for (i = (signed int)outlen - 1; i >= 0; i--) { - out[i] = in & 0xff; - in = in >> 8; - } -} - -void u32_to_bytes(unsigned char *out, uint32_t in) { - out[0] = (unsigned char)(in >> 24); - out[1] = (unsigned char)(in >> 16); - out[2] = (unsigned char)(in >> 8); - out[3] = (unsigned char)in; -} - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { - unsigned long long retval = 0; - unsigned int i; - - for (i = 0; i < inlen; i++) { - retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); - } - return retval; -} - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void compute_root(unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const spx_ctx *ctx, uint32_t addr[8]) { - uint32_t i; - unsigned char buffer[2 * SPX_N]; - - /* If leaf_idx is odd (last bit = 1), current path element is a right child - and auth_path has to go left. Otherwise it is the other way around. */ - if (leaf_idx & 1) { - memcpy(buffer + SPX_N, leaf, SPX_N); - memcpy(buffer, auth_path, SPX_N); - } else { - memcpy(buffer, leaf, SPX_N); - memcpy(buffer + SPX_N, auth_path, SPX_N); - } - auth_path += SPX_N; - - for (i = 0; i < tree_height - 1; i++) { - leaf_idx >>= 1; - idx_offset >>= 1; - /* Set the address of the node we're creating. */ - set_tree_height(addr, i + 1); - set_tree_index(addr, leaf_idx + idx_offset); - - /* Pick the right or left neighbor, depending on parity of the node. */ - if (leaf_idx & 1) { - thash(buffer + SPX_N, buffer, 2, ctx, addr); - memcpy(buffer, auth_path, SPX_N); - } else { - thash(buffer, buffer, 2, ctx, addr); - memcpy(buffer + SPX_N, auth_path, SPX_N); - } - auth_path += SPX_N; - } - - /* The last iteration is exceptional; we do not copy an auth_path node. */ - leaf_idx >>= 1; - idx_offset >>= 1; - set_tree_height(addr, tree_height); - set_tree_index(addr, leaf_idx + idx_offset); - thash(root, buffer, 2, ctx, addr); -} - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const spx_ctx * /* ctx */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), - uint32_t tree_addr[8]) { - PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); - PQCLEAN_VLA(unsigned int, heights, tree_height + 1); - unsigned int offset = 0; - uint32_t idx; - uint32_t tree_idx; - - for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { - /* Add the next leaf node to the stack. */ - gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); - offset++; - heights[offset - 1] = 0; - - /* If this is a node we need for the auth path.. */ - if ((leaf_idx ^ 0x1) == idx) { - memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); - } - - /* While the top-most nodes are of equal height.. */ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { - /* Compute index of the new node, in the next layer. */ - tree_idx = (idx >> (heights[offset - 1] + 1)); - - /* Set the address of the node we're creating. */ - set_tree_height(tree_addr, heights[offset - 1] + 1); - set_tree_index(tree_addr, - tree_idx + (idx_offset >> (heights[offset - 1] + 1))); - /* Hash the top-most nodes from the stack together. */ - thash(stack + (offset - 2)*SPX_N, - stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); - offset--; - /* Note that the top-most node is now one layer higher. */ - heights[offset - 1]++; - - /* If this is a node we need for the auth path.. */ - if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_path + heights[offset - 1]*SPX_N, - stack + (offset - 1)*SPX_N, SPX_N); - } - } - } - memcpy(root, stack, SPX_N); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/utils.h b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/utils.h deleted file mode 100644 index 64f5d5a53a..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/utils.h +++ /dev/null @@ -1,58 +0,0 @@ -#ifndef SPX_UTILS_H -#define SPX_UTILS_H - -#include - -#include "compat.h" -#include "context.h" -#include "params.h" - - -/* To support MSVC use alloca() instead of VLAs. See #20. */ - - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) -void ull_to_bytes(unsigned char *out, unsigned int outlen, - unsigned long long in); -#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) -void u32_to_bytes(unsigned char *out, uint32_t in); - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) -unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -#define compute_root SPX_NAMESPACE(compute_root) -void compute_root(unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const spx_ctx *ctx, uint32_t addr[8]); - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -#define treehash SPX_NAMESPACE(treehash) -void treehash(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const spx_ctx *ctx /* ctx */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), - uint32_t tree_addr[8]); - - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/utilsx1.c b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/utilsx1.c deleted file mode 100644 index fccb69b35d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/utilsx1.c +++ /dev/null @@ -1,100 +0,0 @@ -#include - -#include "utilsx1.h" - -#include "address.h" -#include "params.h" -#include "thash.h" -#include "utils.h" - -/* - * Generate the entire Merkle tree, computing the authentication path for - * leaf_idx, and the resulting root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) - * - * This expects tree_addr to be initialized to the addr structures for the - * Merkle tree nodes - * - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - * - * This works by using the standard Merkle tree building algorithm, - */ -void treehashx1(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, - uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* Where to write the leaves */, - const spx_ctx * /* ctx */, - uint32_t idx, void *info), - uint32_t tree_addr[8], - void *info) { - /* This is where we keep the intermediate nodes */ - PQCLEAN_VLA(uint8_t, stack, tree_height * SPX_N); - - uint32_t idx; - uint32_t max_idx = (uint32_t)((1 << tree_height) - 1); - for (idx = 0;; idx++) { - unsigned char current[2 * SPX_N]; /* Current logical node is at */ - /* index[SPX_N]. We do this to minimize the number of copies */ - /* needed during a thash */ - gen_leaf( ¤t[SPX_N], ctx, idx + idx_offset, - info ); - - /* Now combine the freshly generated right node with previously */ - /* generated left ones */ - uint32_t internal_idx_offset = idx_offset; - uint32_t internal_idx = idx; - uint32_t internal_leaf = leaf_idx; - uint32_t h; /* The height we are in the Merkle tree */ - for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { - - /* Check if we hit the top of the tree */ - if (h == tree_height) { - /* We hit the root; return it */ - memcpy( root, ¤t[SPX_N], SPX_N ); - return; - } - - /* - * Check if the node we have is a part of the - * authentication path; if it is, write it out - */ - if ((internal_idx ^ internal_leaf) == 0x01) { - memcpy( &auth_path[ h * SPX_N ], - ¤t[SPX_N], - SPX_N ); - } - - /* - * Check if we're at a left child; if so, stop going up the stack - * Exception: if we've reached the end of the tree, keep on going - * (so we combine the last 4 nodes into the one root node in two - * more iterations) - */ - if ((internal_idx & 1) == 0 && idx < max_idx) { - break; - } - - /* Ok, we're at a right node */ - /* Now combine the left and right logical nodes together */ - - /* Set the address of the node we're creating. */ - internal_idx_offset >>= 1; - set_tree_height(tree_addr, h + 1); - set_tree_index(tree_addr, internal_idx / 2 + internal_idx_offset ); - - unsigned char *left = &stack[h * SPX_N]; - memcpy( ¤t[0], left, SPX_N ); - thash( ¤t[1 * SPX_N], - ¤t[0 * SPX_N], - 2, ctx, tree_addr); - } - - /* We've hit a left child; save the current for when we get the */ - /* corresponding right right */ - memcpy( &stack[h * SPX_N], ¤t[SPX_N], SPX_N); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/utilsx1.h b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/utilsx1.h deleted file mode 100644 index e911d17d53..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/utilsx1.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef SPX_UTILSX4_H -#define SPX_UTILSX4_H - -#include - -#include "context.h" -#include "params.h" - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -#define treehashx1 SPX_NAMESPACE(treehashx1) -void treehashx1(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* Where to write the leaf */, - const spx_ctx * /* ctx */, - uint32_t addr_idx, void *info), - uint32_t tree_addrx4[8], void *info); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/wots.c b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/wots.c deleted file mode 100644 index 249717aaa8..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/wots.c +++ /dev/null @@ -1,108 +0,0 @@ -#include -#include - -#include "wots.h" -#include "wotsx1.h" - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "thash.h" -#include "utils.h" -#include "utilsx1.h" - -// TODO clarify address expectations, and make them more uniform. -// TODO i.e. do we expect types to be set already? -// TODO and do we expect modifications or copies? - -/** - * Computes the chaining function. - * out and in have to be n-byte arrays. - * - * Interprets in as start-th value of the chain. - * addr has to contain the address of the chain. - */ -static void gen_chain(unsigned char *out, const unsigned char *in, - unsigned int start, unsigned int steps, - const spx_ctx *ctx, uint32_t addr[8]) { - uint32_t i; - - /* Initialize out with the value at position 'start'. */ - memcpy(out, in, SPX_N); - - /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < SPX_WOTS_W; i++) { - set_hash_addr(addr, i); - thash(out, out, 1, ctx, addr); - } -} - -/** - * base_w algorithm as described in draft. - * Interprets an array of bytes as integers in base w. - * This only works when log_w is a divisor of 8. - */ -static void base_w(unsigned int *output, const int out_len, - const unsigned char *input) { - int in = 0; - int out = 0; - unsigned char total = 0; - int bits = 0; - int consumed; - - for (consumed = 0; consumed < out_len; consumed++) { - if (bits == 0) { - total = input[in]; - in++; - bits += 8; - } - bits -= SPX_WOTS_LOGW; - output[out] = (total >> bits) & (SPX_WOTS_W - 1); - out++; - } -} - -/* Computes the WOTS+ checksum over a message (in base_w). */ -static void wots_checksum(unsigned int *csum_base_w, - const unsigned int *msg_base_w) { - unsigned int csum = 0; - unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; - unsigned int i; - - /* Compute checksum. */ - for (i = 0; i < SPX_WOTS_LEN1; i++) { - csum += SPX_WOTS_W - 1 - msg_base_w[i]; - } - - /* Convert checksum to base_w. */ - /* Make sure expected empty zero bits are the least significant bits. */ - csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); - ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); - base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); -} - -/* Takes a message and derives the matching chain lengths. */ -void chain_lengths(unsigned int *lengths, const unsigned char *msg) { - base_w(lengths, SPX_WOTS_LEN1, msg); - wots_checksum(lengths + SPX_WOTS_LEN1, lengths); -} - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const spx_ctx *ctx, uint32_t addr[8]) { - unsigned int lengths[SPX_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < SPX_WOTS_LEN; i++) { - set_chain_addr(addr, i); - gen_chain(pk + i * SPX_N, sig + i * SPX_N, - lengths[i], SPX_WOTS_W - 1 - lengths[i], ctx, addr); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/wots.h b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/wots.h deleted file mode 100644 index 4e7692eeef..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/wots.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef SPX_WOTS_H -#define SPX_WOTS_H - -#include - -#include "context.h" -#include "params.h" - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) -void wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const spx_ctx *ctx, uint32_t addr[8]); - -/* - * Compute the chain lengths needed for a given message hash - */ -#define chain_lengths SPX_NAMESPACE(chain_lengths) -void chain_lengths(unsigned int *lengths, const unsigned char *msg); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/wotsx1.c b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/wotsx1.c deleted file mode 100644 index 3adec78dfb..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/wotsx1.c +++ /dev/null @@ -1,76 +0,0 @@ -#include -#include - -#include "wots.h" -#include "wotsx1.h" - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "thash.h" -#include "utils.h" - -/* - * This generates a WOTS public key - * It also generates the WOTS signature if leaf_info indicates - * that we're signing with this WOTS key - */ -void wots_gen_leafx1(unsigned char *dest, - const spx_ctx *ctx, - uint32_t leaf_idx, void *v_info) { - struct leaf_info_x1 *info = v_info; - uint32_t *leaf_addr = info->leaf_addr; - uint32_t *pk_addr = info->pk_addr; - unsigned int i, k; - unsigned char pk_buffer[ SPX_WOTS_BYTES ]; - unsigned char *buffer; - uint32_t wots_k_mask; - - if (leaf_idx == info->wots_sign_leaf) { - /* We're traversing the leaf that's signing; generate the WOTS */ - /* signature */ - wots_k_mask = 0; - } else { - /* Nope, we're just generating pk's; turn off the signature logic */ - wots_k_mask = (uint32_t)~0; - } - - set_keypair_addr( leaf_addr, leaf_idx ); - set_keypair_addr( pk_addr, leaf_idx ); - - for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { - uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k to */ - /* the step if we're generating a signature, ~0 if we're not */ - - /* Start with the secret seed */ - set_chain_addr(leaf_addr, i); - set_hash_addr(leaf_addr, 0); - set_type(leaf_addr, SPX_ADDR_TYPE_WOTSPRF); - - prf_addr(buffer, ctx, leaf_addr); - - set_type(leaf_addr, SPX_ADDR_TYPE_WOTS); - - /* Iterate down the WOTS chain */ - for (k = 0;; k++) { - /* Check if this is the value that needs to be saved as a */ - /* part of the WOTS signature */ - if (k == wots_k) { - memcpy( info->wots_sig + i * SPX_N, buffer, SPX_N ); - } - - /* Check if we hit the top of the chain */ - if (k == SPX_WOTS_W - 1) { - break; - } - - /* Iterate one step on the chain */ - set_hash_addr(leaf_addr, k); - - thash(buffer, buffer, 1, ctx, leaf_addr); - } - } - - /* Do the final thash to generate the public keys */ - thash(dest, pk_buffer, SPX_WOTS_LEN, ctx, pk_addr); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/wotsx1.h b/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/wotsx1.h deleted file mode 100644 index e617929f96..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-192f-robust_clean/wotsx1.h +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef WOTSX1_H_ -#define WOTSX1_H_ - -#include - -#include "context.h" -#include "params.h" - -/* - * This is here to provide an interface to the internal wots_gen_leafx1 - * routine. While this routine is not referenced in the package outside of - * wots.c, it is called from the stand-alone benchmark code to characterize - * the performance - */ -struct leaf_info_x1 { - unsigned char *wots_sig; - uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ - uint32_t *wots_steps; - uint32_t leaf_addr[8]; - uint32_t pk_addr[8]; -}; - -/* Macro to set the leaf_info to something 'benign', that is, it would */ -/* run with the same time as it does during the real signing process */ -/* Used only by the benchmark code */ -#define INITIALIZE_LEAF_INFO_X1(info, addr, step_buffer) { \ - (info).wots_sig = 0; \ - (info).wots_sign_leaf = ~0; \ - (info).wots_steps = step_buffer; \ - memcpy( &(info).leaf_addr[0], (addr), 32 ); \ - memcpy( &(info).pk_addr[0], (addr), 32 ); \ - } - -#define wots_gen_leafx1 SPX_NAMESPACE(wots_gen_leafx1) -void wots_gen_leafx1(unsigned char *dest, - const spx_ctx *ctx, - uint32_t leaf_idx, void *v_info); - -#endif /* WOTSX1_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/LICENSE b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/LICENSE deleted file mode 100644 index 670154e353..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/LICENSE +++ /dev/null @@ -1,116 +0,0 @@ -CC0 1.0 Universal - -Statement of Purpose - -The laws of most jurisdictions throughout the world automatically confer -exclusive Copyright and Related Rights (defined below) upon the creator and -subsequent owner(s) (each and all, an "owner") of an original work of -authorship and/or a database (each, a "Work"). - -Certain owners wish to permanently relinquish those rights to a Work for the -purpose of contributing to a commons of creative, cultural and scientific -works ("Commons") that the public can reliably and without fear of later -claims of infringement build upon, modify, incorporate in other works, reuse -and redistribute as freely as possible in any form whatsoever and for any -purposes, including without limitation commercial purposes. These owners may -contribute to the Commons to promote the ideal of a free culture and the -further production of creative, cultural and scientific works, or to gain -reputation or greater distribution for their Work in part through the use and -efforts of others. - -For these and/or other purposes and motivations, and without any expectation -of additional consideration or compensation, the person associating CC0 with a -Work (the "Affirmer"), to the extent that he or she is an owner of Copyright -and Related Rights in the Work, voluntarily elects to apply CC0 to the Work -and publicly distribute the Work under its terms, with knowledge of his or her -Copyright and Related Rights in the Work and the meaning and intended legal -effect of CC0 on those rights. - -1. Copyright and Related Rights. A Work made available under CC0 may be -protected by copyright and related or neighboring rights ("Copyright and -Related Rights"). Copyright and Related Rights include, but are not limited -to, the following: - - i. the right to reproduce, adapt, distribute, perform, display, communicate, - and translate a Work; - - ii. moral rights retained by the original author(s) and/or performer(s); - - iii. publicity and privacy rights pertaining to a person's image or likeness - depicted in a Work; - - iv. rights protecting against unfair competition in regards to a Work, - subject to the limitations in paragraph 4(a), below; - - v. rights protecting the extraction, dissemination, use and reuse of data in - a Work; - - vi. database rights (such as those arising under Directive 96/9/EC of the - European Parliament and of the Council of 11 March 1996 on the legal - protection of databases, and under any national implementation thereof, - including any amended or successor version of such directive); and - - vii. other similar, equivalent or corresponding rights throughout the world - based on applicable law or treaty, and any national implementations thereof. - -2. Waiver. To the greatest extent permitted by, but not in contravention of, -applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and -unconditionally waives, abandons, and surrenders all of Affirmer's Copyright -and Related Rights and associated claims and causes of action, whether now -known or unknown (including existing as well as future claims and causes of -action), in the Work (i) in all territories worldwide, (ii) for the maximum -duration provided by applicable law or treaty (including future time -extensions), (iii) in any current or future medium and for any number of -copies, and (iv) for any purpose whatsoever, including without limitation -commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes -the Waiver for the benefit of each member of the public at large and to the -detriment of Affirmer's heirs and successors, fully intending that such Waiver -shall not be subject to revocation, rescission, cancellation, termination, or -any other legal or equitable action to disrupt the quiet enjoyment of the Work -by the public as contemplated by Affirmer's express Statement of Purpose. - -3. Public License Fallback. Should any part of the Waiver for any reason be -judged legally invalid or ineffective under applicable law, then the Waiver -shall be preserved to the maximum extent permitted taking into account -Affirmer's express Statement of Purpose. In addition, to the extent the Waiver -is so judged Affirmer hereby grants to each affected person a royalty-free, -non transferable, non sublicensable, non exclusive, irrevocable and -unconditional license to exercise Affirmer's Copyright and Related Rights in -the Work (i) in all territories worldwide, (ii) for the maximum duration -provided by applicable law or treaty (including future time extensions), (iii) -in any current or future medium and for any number of copies, and (iv) for any -purpose whatsoever, including without limitation commercial, advertising or -promotional purposes (the "License"). The License shall be deemed effective as -of the date CC0 was applied by Affirmer to the Work. Should any part of the -License for any reason be judged legally invalid or ineffective under -applicable law, such partial invalidity or ineffectiveness shall not -invalidate the remainder of the License, and in such case Affirmer hereby -affirms that he or she will not (i) exercise any of his or her remaining -Copyright and Related Rights in the Work or (ii) assert any associated claims -and causes of action with respect to the Work, in either case contrary to -Affirmer's express Statement of Purpose. - -4. Limitations and Disclaimers. - - a. No trademark or patent rights held by Affirmer are waived, abandoned, - surrendered, licensed or otherwise affected by this document. - - b. Affirmer offers the Work as-is and makes no representations or warranties - of any kind concerning the Work, express, implied, statutory or otherwise, - including without limitation warranties of title, merchantability, fitness - for a particular purpose, non infringement, or the absence of latent or - other defects, accuracy, or the present or absence of errors, whether or not - discoverable, all to the greatest extent permissible under applicable law. - - c. Affirmer disclaims responsibility for clearing rights of other persons - that may apply to the Work or any use thereof, including without limitation - any person's Copyright and Related Rights in the Work. Further, Affirmer - disclaims responsibility for obtaining any necessary consents, permissions - or other rights required for any use of the Work. - - d. Affirmer understands and acknowledges that Creative Commons is not a - party to this document and has no duty or obligation with respect to this - CC0 or use of the Work. - -For more information, please see - diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/address.c b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/address.c deleted file mode 100644 index d49d9f3b6b..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/address.c +++ /dev/null @@ -1,95 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "utils.h" - -/* - * Specify which level of Merkle tree (the "layer") we're working on - */ -void set_layer_addr(uint32_t addr[8], uint32_t layer) { - ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; -} - -/* - * Specify which Merkle tree within the level (the "tree address") we're working on - */ -void set_tree_addr(uint32_t addr[8], uint64_t tree) { - ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); -} - -/* - * Specify the reason we'll use this address structure for, that is, what - * hash will we compute with it. This is used so that unrelated types of - * hashes don't accidentally get the same address structure. The type will be - * one of the SPX_ADDR_TYPE constants - */ -void set_type(uint32_t addr[8], uint32_t type) { - ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; -} - -/* - * Copy the layer and tree fields of the address structure. This is used - * when we're doing multiple types of hashes within the same Merkle tree - */ -void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { - memcpy( out, in, SPX_OFFSET_TREE + 8 ); -} - -/* These functions are used for OTS addresses. */ - -/* - * Specify which Merkle leaf we're working on; that is, which OTS keypair - * we're talking about. - */ -void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { - /* We have > 256 OTS at the bottom of the Merkle tree; to specify */ - /* which one, we'd need to express it in two bytes */ - ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR2] = (unsigned char)(keypair >> 8); - ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; -} - -/* - * Copy the layer, tree and keypair fields of the address structure. This is - * used when we're doing multiple things within the same OTS keypair - */ -void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { - memcpy( out, in, SPX_OFFSET_TREE + 8 ); - ((unsigned char *)out)[SPX_OFFSET_KP_ADDR2] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR2]; - ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; -} - -/* - * Specify which Merkle chain within the OTS we're working with - * (the chain address) - */ -void set_chain_addr(uint32_t addr[8], uint32_t chain) { - ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; -} - -/* - * Specify where in the Merkle chain we are -* (the hash address) - */ -void set_hash_addr(uint32_t addr[8], uint32_t hash) { - ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; -} - -/* These functions are used for all hash tree addresses (including FORS). */ - -/* - * Specify the height of the node in the Merkle/FORS tree we are in - * (the tree height) - */ -void set_tree_height(uint32_t addr[8], uint32_t tree_height) { - ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; -} - -/* - * Specify the distance from the left edge of the node in the Merkle/FORS tree - * (the tree index) - */ -void set_tree_index(uint32_t addr[8], uint32_t tree_index) { - u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/address.h b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/address.h deleted file mode 100644 index 24a84eb40c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/address.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef SPX_ADDRESS_H -#define SPX_ADDRESS_H - -#include - -#include "params.h" - -/* The hash types that are passed to set_type */ -#define SPX_ADDR_TYPE_WOTS 0 -#define SPX_ADDR_TYPE_WOTSPK 1 -#define SPX_ADDR_TYPE_HASHTREE 2 -#define SPX_ADDR_TYPE_FORSTREE 3 -#define SPX_ADDR_TYPE_FORSPK 4 -#define SPX_ADDR_TYPE_WOTSPRF 5 -#define SPX_ADDR_TYPE_FORSPRF 6 - -#define set_layer_addr SPX_NAMESPACE(set_layer_addr) -void set_layer_addr(uint32_t addr[8], uint32_t layer); - -#define set_tree_addr SPX_NAMESPACE(set_tree_addr) -void set_tree_addr(uint32_t addr[8], uint64_t tree); - -#define set_type SPX_NAMESPACE(set_type) -void set_type(uint32_t addr[8], uint32_t type); - -/* Copies the layer and tree part of one address into the other */ -#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) -void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for WOTS and FORS addresses. */ - -#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) -void set_keypair_addr(uint32_t addr[8], uint32_t keypair); - -#define set_chain_addr SPX_NAMESPACE(set_chain_addr) -void set_chain_addr(uint32_t addr[8], uint32_t chain); - -#define set_hash_addr SPX_NAMESPACE(set_hash_addr) -void set_hash_addr(uint32_t addr[8], uint32_t hash); - -#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) -void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for all hash tree addresses (including FORS). */ - -#define set_tree_height SPX_NAMESPACE(set_tree_height) -void set_tree_height(uint32_t addr[8], uint32_t tree_height); - -#define set_tree_index SPX_NAMESPACE(set_tree_index) -void set_tree_index(uint32_t addr[8], uint32_t tree_index); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/api.h b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/api.h deleted file mode 100644 index 7c4b1b7987..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/api.h +++ /dev/null @@ -1,77 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA2192SROBUST_AVX2_API_H -#define PQCLEAN_SPHINCSSHA2192SROBUST_AVX2_API_H - -#include -#include - -#define PQCLEAN_SPHINCSSHA2192SROBUST_AVX2_CRYPTO_ALGNAME "SPHINCS+-sha2-192s-robust" - -#define PQCLEAN_SPHINCSSHA2192SROBUST_AVX2_CRYPTO_SECRETKEYBYTES 96 -#define PQCLEAN_SPHINCSSHA2192SROBUST_AVX2_CRYPTO_PUBLICKEYBYTES 48 -#define PQCLEAN_SPHINCSSHA2192SROBUST_AVX2_CRYPTO_BYTES 16224 - -#define PQCLEAN_SPHINCSSHA2192SROBUST_AVX2_CRYPTO_SEEDBYTES 72 - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSSHA2192SROBUST_AVX2_crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSSHA2192SROBUST_AVX2_crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSSHA2192SROBUST_AVX2_crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSSHA2192SROBUST_AVX2_crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHA2192SROBUST_AVX2_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHA2192SROBUST_AVX2_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSSHA2192SROBUST_AVX2_crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSSHA2192SROBUST_AVX2_crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, - const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSSHA2192SROBUST_AVX2_crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSSHA2192SROBUST_AVX2_crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk); -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/context.h b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/context.h deleted file mode 100644 index d3bf1c3aac..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/context.h +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef SPX_CONTEXT_H -#define SPX_CONTEXT_H - -#include - -#include "params.h" -#include "sha2.h" -#include "sha256avx.h" -#include "sha512x4.h" - -// funky ordering due to optimal padding -typedef struct { - sha256x8ctx statex8_seeded; - sha512x4ctx statex4_seeded_512; - sha256ctx state_seeded; - sha512ctx state_seeded_512; - - uint8_t pub_seed[SPX_N]; - uint8_t sk_seed[SPX_N]; -} spx_ctx; - - -#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) -void initialize_hash_function(spx_ctx *ctx); - -#define free_hash_function SPX_NAMESPACE(free_hash_function) -void free_hash_function(spx_ctx *ctx); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/context_sha2.c b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/context_sha2.c deleted file mode 100644 index 83c1b6585d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/context_sha2.c +++ /dev/null @@ -1,56 +0,0 @@ -#include - -#include "context.h" - -/** - * Absorb the constant pub_seed using one round of the compression function - * This initializes state_seeded and state_seeded_512, which can then be - * reused in thash - **/ -static void seed_state(spx_ctx *ctx) { - uint8_t block[SPX_SHA512_BLOCK_BYTES]; - size_t i; - - for (i = 0; i < SPX_N; ++i) { - block[i] = ctx->pub_seed[i]; - } - for (i = SPX_N; i < SPX_SHA512_BLOCK_BYTES; ++i) { - block[i] = 0; - } - /* block has been properly initialized for both SHA-256 and SHA-512 */ - - sha256_inc_init(&ctx->state_seeded); - sha256_inc_blocks(&ctx->state_seeded, block, 1); - - // initialize x8 - sha256_init8x(&ctx->statex8_seeded); - sha256_transform8x(&ctx->statex8_seeded, - block, block, block, block, block, block, block, block); - - ctx->statex8_seeded.datalen = 0; - ctx->statex8_seeded.msglen = 512; - - sha512_inc_init(&ctx->state_seeded_512); - sha512_inc_blocks(&ctx->state_seeded_512, block, 1); - - // initialize x4 - sha512_init4x(&ctx->statex4_seeded_512); - sha512_transform4x(&ctx->statex4_seeded_512, block, block, block, block); - - ctx->statex4_seeded_512.datalen = 0; - ctx->statex4_seeded_512.msglen = 1024; - - -} - - -/* For SHA, we initialize the hash function at the start */ -void initialize_hash_function(spx_ctx *ctx) { - seed_state(ctx); -} - -/* Free the incremental hashing context for heap-based SHA2 APIs */ -void free_hash_function(spx_ctx *ctx) { - sha256_inc_ctx_release(&ctx->state_seeded); - sha512_inc_ctx_release(&ctx->state_seeded_512); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/fors.c b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/fors.c deleted file mode 100644 index 4cab8e7415..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/fors.c +++ /dev/null @@ -1,226 +0,0 @@ -#include -#include -#include - -#include "fors.h" - - -#include "address.h" -#include "hash.h" -#include "hashx8.h" -#include "thash.h" -#include "thashx8.h" -#include "utils.h" -#include "utilsx8.h" -static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, - uint32_t fors_leaf_addr[8]) { - prf_addr(sk, ctx, fors_leaf_addr); -} - -static void fors_gen_skx8(unsigned char *sk0, - unsigned char *sk1, - unsigned char *sk2, - unsigned char *sk3, - unsigned char *sk4, - unsigned char *sk5, - unsigned char *sk6, - unsigned char *sk7, const spx_ctx *ctx, - uint32_t fors_leaf_addrx8[8 * 8]) { - prf_addrx8(sk0, sk1, sk2, sk3, sk4, sk5, sk6, sk7, - ctx, fors_leaf_addrx8); -} - -static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, - const spx_ctx *ctx, - uint32_t fors_leaf_addr[8]) { - thash(leaf, sk, 1, ctx, fors_leaf_addr); -} - -static void fors_sk_to_leafx8(unsigned char *leaf0, - unsigned char *leaf1, - unsigned char *leaf2, - unsigned char *leaf3, - unsigned char *leaf4, - unsigned char *leaf5, - unsigned char *leaf6, - unsigned char *leaf7, - const unsigned char *sk0, - const unsigned char *sk1, - const unsigned char *sk2, - const unsigned char *sk3, - const unsigned char *sk4, - const unsigned char *sk5, - const unsigned char *sk6, - const unsigned char *sk7, - const spx_ctx *ctx, - uint32_t fors_leaf_addrx8[8 * 8]) { - thashx8(leaf0, leaf1, leaf2, leaf3, leaf4, leaf5, leaf6, leaf7, - sk0, sk1, sk2, sk3, sk4, sk5, sk6, sk7, - 1, ctx, fors_leaf_addrx8); -} - -struct fors_gen_leaf_info { - uint32_t leaf_addrx[8 * 8]; -}; - -static void fors_gen_leafx8(unsigned char *leaf, - const spx_ctx *ctx, - uint32_t addr_idx, void *info) { - struct fors_gen_leaf_info *fors_info = info; - uint32_t *fors_leaf_addrx8 = fors_info->leaf_addrx; - unsigned int j; - - /* Only set the parts that the caller doesn't set */ - for (j = 0; j < 8; j++) { - set_tree_index(fors_leaf_addrx8 + j * 8, addr_idx + j); - set_type(fors_leaf_addrx8 + j * 8, SPX_ADDR_TYPE_FORSPRF); - } - - fors_gen_skx8(leaf + 0 * SPX_N, - leaf + 1 * SPX_N, - leaf + 2 * SPX_N, - leaf + 3 * SPX_N, - leaf + 4 * SPX_N, - leaf + 5 * SPX_N, - leaf + 6 * SPX_N, - leaf + 7 * SPX_N, - ctx, fors_leaf_addrx8); - - for (j = 0; j < 8; j++) { - set_type(fors_leaf_addrx8 + j * 8, SPX_ADDR_TYPE_FORSTREE); - } - - fors_sk_to_leafx8(leaf + 0 * SPX_N, - leaf + 1 * SPX_N, - leaf + 2 * SPX_N, - leaf + 3 * SPX_N, - leaf + 4 * SPX_N, - leaf + 5 * SPX_N, - leaf + 6 * SPX_N, - leaf + 7 * SPX_N, - leaf + 0 * SPX_N, - leaf + 1 * SPX_N, - leaf + 2 * SPX_N, - leaf + 3 * SPX_N, - leaf + 4 * SPX_N, - leaf + 5 * SPX_N, - leaf + 6 * SPX_N, - leaf + 7 * SPX_N, - ctx, fors_leaf_addrx8); -} - -/** - * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - * Assumes indices has space for SPX_FORS_TREES integers. - */ -static void message_to_indices(uint32_t *indices, const unsigned char *m) { - unsigned int i, j; - unsigned int offset = 0; - - for (i = 0; i < SPX_FORS_TREES; i++) { - indices[i] = 0; - for (j = 0; j < SPX_FORS_HEIGHT; j++) { - indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); - offset++; - } - } -} - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -void fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]) { - uint32_t indices[SPX_FORS_TREES]; - unsigned char roots[SPX_FORS_TREES * SPX_N]; - uint32_t fors_tree_addr[8 * 8] = {0}; - struct fors_gen_leaf_info fors_info = {0}; - uint32_t *fors_leaf_addr = fors_info.leaf_addrx; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - for (i = 0; i < 8; i++) { - copy_keypair_addr(fors_tree_addr + 8 * i, fors_addr); - set_type(fors_tree_addr + 8 * i, SPX_ADDR_TYPE_FORSTREE); - copy_keypair_addr(fors_leaf_addr + 8 * i, fors_addr); - } - copy_keypair_addr(fors_pk_addr, fors_addr); - set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < SPX_FORS_TREES; i++) { - idx_offset = i * (1 << SPX_FORS_HEIGHT); - - set_tree_height(fors_tree_addr, 0); - set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Include the secret key part that produces the selected leaf node. */ - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); - fors_gen_sk(sig, ctx, fors_tree_addr); - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); - sig += SPX_N; - - /* Compute the authentication path for this leaf node. */ - treehashx8(roots + i * SPX_N, sig, ctx, - indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx8, - fors_tree_addr, &fors_info); - - sig += SPX_N * SPX_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); -} - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -void fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]) { - uint32_t indices[SPX_FORS_TREES]; - unsigned char roots[SPX_FORS_TREES * SPX_N]; - unsigned char leaf[SPX_N]; - uint32_t fors_tree_addr[8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - copy_keypair_addr(fors_tree_addr, fors_addr); - copy_keypair_addr(fors_pk_addr, fors_addr); - - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); - set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < SPX_FORS_TREES; i++) { - idx_offset = i * (1 << SPX_FORS_HEIGHT); - - set_tree_height(fors_tree_addr, 0); - set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Derive the leaf from the included secret key part. */ - fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); - sig += SPX_N; - - /* Derive the corresponding root node of this tree. */ - compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, - sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); - sig += SPX_N * SPX_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/fors.h b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/fors.h deleted file mode 100644 index 509140a178..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/fors.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef SPX_FORS_H -#define SPX_FORS_H - -#include - -#include "context.h" -#include "params.h" - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -#define fors_sign SPX_NAMESPACE(fors_sign) -void fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]); - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) -void fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/hash.h b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/hash.h deleted file mode 100644 index ffe815f45d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/hash.h +++ /dev/null @@ -1,37 +0,0 @@ -#ifndef SPX_HASH_H -#define SPX_HASH_H - -#include -#include - -#include "context.h" -#include "params.h" - -#define prf_addr SPX_NAMESPACE(prf_addr) -void prf_addr(unsigned char *out, const spx_ctx *ctx, - const uint32_t addr[8]); - -#define gen_message_random SPX_NAMESPACE(gen_message_random) -void gen_message_random(unsigned char *R, const unsigned char *sk_prf, - const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx); - -#define hash_message SPX_NAMESPACE(hash_message) -void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx); - - -# define SPX_SHA256_ADDR_BYTES 22 - -# define mgf1_256 SPX_NAMESPACE(mgf1_256) -void mgf1_256(unsigned char *out, unsigned long outlen, - const unsigned char *in, unsigned long inlen); - -# define mgf1_512 SPX_NAMESPACE(mgf1_512) -void mgf1_512(unsigned char *out, unsigned long outlen, - const unsigned char *in, unsigned long inlen); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/hash_sha2.c b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/hash_sha2.c deleted file mode 100644 index 3d0085c8c1..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/hash_sha2.c +++ /dev/null @@ -1,219 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "sha2.h" -#include "utils.h" - - - -#define SPX_SHAX_OUTPUT_BYTES SPX_SHA512_OUTPUT_BYTES -#define SPX_SHAX_BLOCK_BYTES SPX_SHA512_BLOCK_BYTES -#define shaX_inc_init sha512_inc_init -#define shaX_inc_blocks sha512_inc_blocks -#define shaX_inc_finalize sha512_inc_finalize -#define shaX sha512 -#define mgf1_X mgf1_512 -#define shaXstate sha512ctx - -/** - * mgf1 function based on the SHA-256 hash function - * Note that inlen should be sufficiently small that it still allows for - * an array to be allocated on the stack. Typically 'in' is merely a seed. - * Outputs outlen number of bytes - */ -void mgf1_256(unsigned char *out, unsigned long outlen, - const unsigned char *in, unsigned long inlen) { - PQCLEAN_VLA(uint8_t, inbuf, inlen + 4); - unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES]; - uint32_t i; - - memcpy(inbuf, in, inlen); - - /* While we can fit in at least another full block of SHA256 output.. */ - for (i = 0; (i + 1)*SPX_SHA256_OUTPUT_BYTES <= outlen; i++) { - u32_to_bytes(inbuf + inlen, i); - sha256(out, inbuf, inlen + 4); - out += SPX_SHA256_OUTPUT_BYTES; - } - /* Until we cannot anymore, and we fill the remainder. */ - if (outlen > i * SPX_SHA256_OUTPUT_BYTES) { - u32_to_bytes(inbuf + inlen, i); - sha256(outbuf, inbuf, inlen + 4); - memcpy(out, outbuf, outlen - i * SPX_SHA256_OUTPUT_BYTES); - } -} - -/* - * mgf1 function based on the SHA-512 hash function - */ -void mgf1_512(unsigned char *out, unsigned long outlen, - const unsigned char *in, unsigned long inlen) { - PQCLEAN_VLA(uint8_t, inbuf, inlen + 4); - unsigned char outbuf[SPX_SHA512_OUTPUT_BYTES]; - uint32_t i; - - memcpy(inbuf, in, inlen); - - /* While we can fit in at least another full block of SHA512 output.. */ - for (i = 0; (i + 1)*SPX_SHA512_OUTPUT_BYTES <= outlen; i++) { - u32_to_bytes(inbuf + inlen, i); - sha512(out, inbuf, inlen + 4); - out += SPX_SHA512_OUTPUT_BYTES; - } - /* Until we cannot anymore, and we fill the remainder. */ - if (outlen > i * SPX_SHA512_OUTPUT_BYTES) { - u32_to_bytes(inbuf + inlen, i); - sha512(outbuf, inbuf, inlen + 4); - memcpy(out, outbuf, outlen - i * SPX_SHA512_OUTPUT_BYTES); - } -} - -/* - * Computes PRF(pk_seed, sk_seed, addr). - */ -void prf_addr(unsigned char *out, const spx_ctx *ctx, - const uint32_t addr[8]) { - sha256ctx sha2_state; - unsigned char buf[SPX_SHA256_ADDR_BYTES + SPX_N]; - unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES]; - - /* Retrieve precomputed state containing pub_seed */ - sha256_inc_ctx_clone(&sha2_state, &ctx->state_seeded); - - /* Remainder: ADDR^c ‖ SK.seed */ - memcpy(buf, addr, SPX_SHA256_ADDR_BYTES); - memcpy(buf + SPX_SHA256_ADDR_BYTES, ctx->sk_seed, SPX_N); - - sha256_inc_finalize(outbuf, &sha2_state, buf, SPX_SHA256_ADDR_BYTES + SPX_N); - - memcpy(out, outbuf, SPX_N); -} - -/** - * Computes the message-dependent randomness R, using a secret seed as a key - * for HMAC, and an optional randomization value prefixed to the message. - * This requires m to have at least SPX_SHAX_BLOCK_BYTES + SPX_N space - * available in front of the pointer, i.e. before the message to use for the - * prefix. This is necessary to prevent having to move the message around (and - * allocate memory for it). - */ -void gen_message_random(unsigned char *R, const unsigned char *sk_prf, - const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx) { - (void)ctx; - - unsigned char buf[SPX_SHAX_BLOCK_BYTES + SPX_SHAX_OUTPUT_BYTES]; - shaXstate state; - int i; - - - /* This implements HMAC-SHA */ - for (i = 0; i < SPX_N; i++) { - buf[i] = 0x36 ^ sk_prf[i]; - } - memset(buf + SPX_N, 0x36, SPX_SHAX_BLOCK_BYTES - SPX_N); - - shaX_inc_init(&state); - shaX_inc_blocks(&state, buf, 1); - - memcpy(buf, optrand, SPX_N); - - /* If optrand + message cannot fill up an entire block */ - if (SPX_N + mlen < SPX_SHAX_BLOCK_BYTES) { - memcpy(buf + SPX_N, m, mlen); - shaX_inc_finalize(buf + SPX_SHAX_BLOCK_BYTES, &state, - buf, mlen + SPX_N); - } - /* Otherwise first fill a block, so that finalize only uses the message */ - else { - memcpy(buf + SPX_N, m, SPX_SHAX_BLOCK_BYTES - SPX_N); - shaX_inc_blocks(&state, buf, 1); - - m += SPX_SHAX_BLOCK_BYTES - SPX_N; - mlen -= SPX_SHAX_BLOCK_BYTES - SPX_N; - shaX_inc_finalize(buf + SPX_SHAX_BLOCK_BYTES, &state, m, mlen); - } - - for (i = 0; i < SPX_N; i++) { - buf[i] = 0x5c ^ sk_prf[i]; - } - memset(buf + SPX_N, 0x5c, SPX_SHAX_BLOCK_BYTES - SPX_N); - - shaX(buf, buf, SPX_SHAX_BLOCK_BYTES + SPX_SHAX_OUTPUT_BYTES); - memcpy(R, buf, SPX_N); -} - -/** - * Computes the message hash using R, the public key, and the message. - * Outputs the message digest and the index of the leaf. The index is split in - * the tree index and the leaf index, for convenient copying to an address. - */ -void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx) { - (void)ctx; -#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) -#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) -#define SPX_LEAF_BITS SPX_TREE_HEIGHT -#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) -#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) - - unsigned char seed[2 * SPX_N + SPX_SHAX_OUTPUT_BYTES]; - - /* Round to nearest multiple of SPX_SHAX_BLOCK_BYTES */ -#define SPX_INBLOCKS (((SPX_N + SPX_PK_BYTES + SPX_SHAX_BLOCK_BYTES - 1) & \ - -SPX_SHAX_BLOCK_BYTES) / SPX_SHAX_BLOCK_BYTES) - unsigned char inbuf[SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES]; - - unsigned char buf[SPX_DGST_BYTES]; - unsigned char *bufp = buf; - shaXstate state; - - shaX_inc_init(&state); - - // seed: SHA-X(R ‖ PK.seed ‖ PK.root ‖ M) - memcpy(inbuf, R, SPX_N); - memcpy(inbuf + SPX_N, pk, SPX_PK_BYTES); - - /* If R + pk + message cannot fill up an entire block */ - if (SPX_N + SPX_PK_BYTES + mlen < SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES) { - memcpy(inbuf + SPX_N + SPX_PK_BYTES, m, mlen); - shaX_inc_finalize(seed + 2 * SPX_N, &state, inbuf, SPX_N + SPX_PK_BYTES + mlen); - } - /* Otherwise first fill a block, so that finalize only uses the message */ - else { - memcpy(inbuf + SPX_N + SPX_PK_BYTES, m, - SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES - SPX_N - SPX_PK_BYTES); - shaX_inc_blocks(&state, inbuf, SPX_INBLOCKS); - - m += SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES - SPX_N - SPX_PK_BYTES; - mlen -= SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES - SPX_N - SPX_PK_BYTES; - shaX_inc_finalize(seed + 2 * SPX_N, &state, m, (size_t)mlen); - } - - // H_msg: MGF1-SHA-X(R ‖ PK.seed ‖ seed) - memcpy(seed, R, SPX_N); - memcpy(seed + SPX_N, pk, SPX_N); - - /* By doing this in two steps, we prevent hashing the message twice; - otherwise each iteration in MGF1 would hash the message again. */ - mgf1_X(bufp, SPX_DGST_BYTES, seed, 2 * SPX_N + SPX_SHAX_OUTPUT_BYTES); - - memcpy(digest, bufp, SPX_FORS_MSG_BYTES); - bufp += SPX_FORS_MSG_BYTES; - - - *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); - *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); - bufp += SPX_TREE_BYTES; - - *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); - *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); -} - - diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/hash_sha2x8.c b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/hash_sha2x8.c deleted file mode 100644 index e04af7a069..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/hash_sha2x8.c +++ /dev/null @@ -1,75 +0,0 @@ -#include -#include - -#include "hash.h" -#include "hashx8.h" - -#include "address.h" -#include "params.h" -#include "sha2.h" -#include "sha256avx.h" -#include "sha256x8.h" -#include "utils.h" - -/* - * 8-way parallel version of prf_addr; takes 8x as much input and output - */ -void prf_addrx8(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7, - const spx_ctx *ctx, - const uint32_t addrx8[8 * 8]) { - unsigned char bufx8[8 * (SPX_N + SPX_SHA256_ADDR_BYTES)]; - unsigned char outbufx8[8 * SPX_SHA256_OUTPUT_BYTES]; - unsigned int j; - - for (j = 0; j < 8; j++) { - memcpy(bufx8 + j * (SPX_N + SPX_SHA256_ADDR_BYTES), - addrx8 + j * 8, SPX_SHA256_ADDR_BYTES); - memcpy( - bufx8 + j * (SPX_N + SPX_SHA256_ADDR_BYTES) + SPX_SHA256_ADDR_BYTES, - ctx->sk_seed, - SPX_N - ); - } - - sha256x8_seeded( - /* out */ - outbufx8 + 0 * SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 1 * SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 2 * SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 3 * SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 4 * SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 5 * SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 6 * SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 7 * SPX_SHA256_OUTPUT_BYTES, - - /* seed */ - &ctx->statex8_seeded, - - /* in */ - bufx8 + 0 * (SPX_SHA256_ADDR_BYTES + SPX_N), - bufx8 + 1 * (SPX_SHA256_ADDR_BYTES + SPX_N), - bufx8 + 2 * (SPX_SHA256_ADDR_BYTES + SPX_N), - bufx8 + 3 * (SPX_SHA256_ADDR_BYTES + SPX_N), - bufx8 + 4 * (SPX_SHA256_ADDR_BYTES + SPX_N), - bufx8 + 5 * (SPX_SHA256_ADDR_BYTES + SPX_N), - bufx8 + 6 * (SPX_SHA256_ADDR_BYTES + SPX_N), - bufx8 + 7 * (SPX_SHA256_ADDR_BYTES + SPX_N), - SPX_SHA256_ADDR_BYTES + SPX_N /* len */ - ); - - memcpy(out0, outbufx8 + 0 * SPX_SHA256_OUTPUT_BYTES, SPX_N); - memcpy(out1, outbufx8 + 1 * SPX_SHA256_OUTPUT_BYTES, SPX_N); - memcpy(out2, outbufx8 + 2 * SPX_SHA256_OUTPUT_BYTES, SPX_N); - memcpy(out3, outbufx8 + 3 * SPX_SHA256_OUTPUT_BYTES, SPX_N); - memcpy(out4, outbufx8 + 4 * SPX_SHA256_OUTPUT_BYTES, SPX_N); - memcpy(out5, outbufx8 + 5 * SPX_SHA256_OUTPUT_BYTES, SPX_N); - memcpy(out6, outbufx8 + 6 * SPX_SHA256_OUTPUT_BYTES, SPX_N); - memcpy(out7, outbufx8 + 7 * SPX_SHA256_OUTPUT_BYTES, SPX_N); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/hashx8.h b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/hashx8.h deleted file mode 100644 index 46503f0a10..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/hashx8.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef SPX_HASHX8_H -#define SPX_HASHX8_H - -#include - -#include "params.h" - -#define prf_addrx8 SPX_NAMESPACE(prf_addrx8) -void prf_addrx8(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7, - const spx_ctx *ctx, - const uint32_t addrx8[8 * 8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/merkle.c b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/merkle.c deleted file mode 100644 index 1f353c8dd8..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/merkle.c +++ /dev/null @@ -1,65 +0,0 @@ -#include -#include - -#include "merkle.h" - -#include "address.h" -#include "params.h" -#include "utils.h" -#include "utilsx8.h" -#include "wots.h" -#include "wotsx8.h" - -/* - * This generates a Merkle signature (WOTS signature followed by the Merkle - * authentication path). - */ -void merkle_sign(uint8_t *sig, unsigned char *root, - const spx_ctx *ctx, - uint32_t wots_addr[8], uint32_t tree_addr[8], - uint32_t idx_leaf) { - unsigned char *auth_path = sig + SPX_WOTS_BYTES; - uint32_t tree_addrx8[8 * 8] = { 0 }; - int j; - struct leaf_info_x8 info = { 0 }; - unsigned steps[ SPX_WOTS_LEN ]; - - info.wots_sig = sig; - chain_lengths(steps, root); - info.wots_steps = steps; - - for (j = 0; j < 8; j++) { - set_type(&tree_addrx8[8 * j], SPX_ADDR_TYPE_HASHTREE); - set_type(&info.leaf_addr[8 * j], SPX_ADDR_TYPE_WOTS); - set_type(&info.pk_addr[8 * j], SPX_ADDR_TYPE_WOTSPK); - copy_subtree_addr(&tree_addrx8[8 * j], tree_addr); - copy_subtree_addr(&info.leaf_addr[8 * j], wots_addr); - copy_subtree_addr(&info.pk_addr[8 * j], wots_addr); - } - - info.wots_sign_leaf = idx_leaf; - - treehashx8(root, auth_path, ctx, - idx_leaf, 0, - SPX_TREE_HEIGHT, - wots_gen_leafx8, - tree_addrx8, &info); -} - -/* Compute root node of the top-most subtree. */ -/* Again, in this file because wots_gen_leaf is most of the work */ -void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { - /* We do not need the auth path in key generation, but it simplifies the - code to have just one treehash routine that computes both root and path - in one function. */ - unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; - uint32_t top_tree_addr[8] = {0}; - uint32_t wots_addr[8] = {0}; - - set_layer_addr(top_tree_addr, SPX_D - 1); - set_layer_addr(wots_addr, SPX_D - 1); - - merkle_sign(auth_path, root, ctx, - wots_addr, top_tree_addr, - ~0U /* ~0 means "don't bother generating an auth path */ ); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/merkle.h b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/merkle.h deleted file mode 100644 index 769cf2e970..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/merkle.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef MERKLE_H_ -#define MERKLE_H_ - -#include - -#include "context.h" -#include "params.h" - -/* Generate a Merkle signature (WOTS signature followed by the Merkle */ -/* authentication path) */ -#define merkle_sign SPX_NAMESPACE(merkle_sign) -void merkle_sign(uint8_t *sig, unsigned char *root, - const spx_ctx *ctx, - uint32_t wots_addr[8], uint32_t tree_addr[8], - uint32_t idx_leaf); - -/* Compute the root node of the top-most subtree. */ -#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) -void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); - -#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/nistapi.h b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/nistapi.h deleted file mode 100644 index 3cb71afad4..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/nistapi.h +++ /dev/null @@ -1,87 +0,0 @@ -#ifndef SPX_API_H -#define SPX_API_H - -#include -#include - -#include "params.h" - -#define CRYPTO_ALGNAME "SPHINCS+" - -#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES -#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES -#define CRYPTO_BYTES SPX_BYTES -#define CRYPTO_SEEDBYTES (3*SPX_N) - -/* - * Returns the length of a secret key, in bytes - */ -#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) -size_t crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) -size_t crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) -size_t crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) -size_t crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) -int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) -int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) -int crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) -int crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -#define crypto_sign SPX_NAMESPACE(crypto_sign) -int crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) -int crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/params.h b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/params.h deleted file mode 100644 index c45bfd994c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/params.h +++ /dev/null @@ -1,61 +0,0 @@ -#ifndef SPX_PARAMS_H -#define SPX_PARAMS_H - -#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSSHA2192SROBUST_AVX2_##s - -/* Hash output length in bytes. */ -#define SPX_N 24 -/* Height of the hypertree. */ -#define SPX_FULL_HEIGHT 63 -/* Number of subtree layer. */ -#define SPX_D 7 -/* FORS tree dimensions. */ -#define SPX_FORS_HEIGHT 14 -#define SPX_FORS_TREES 17 -/* Winternitz parameter, */ -#define SPX_WOTS_W 16 - -/* The hash function is defined by linking a different hash.c file, as opposed - to setting a #define constant. */ - -/* This is a SHA2-based parameter set, hence whether we use SHA-256 - * exclusively or we use both SHA-256 and SHA-512 is controlled by - * the following #define */ -#define SPX_SHA512 1 /* Use SHA-512 for H and T_l, l >= 2 */ - -/* For clarity */ -#define SPX_ADDR_BYTES 32 - -/* WOTS parameters. */ -#define SPX_WOTS_LOGW 4 - -#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) - -/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#define SPX_WOTS_LEN2 3 - -#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) -#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) -#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES - -/* Subtree size. */ -#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) - -//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT -// #error SPX_D should always divide SPX_FULL_HEIGHT -//#endif - -/* FORS parameters. */ -#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) -#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) -#define SPX_FORS_PK_BYTES SPX_N - -/* Resulting SPX sizes. */ -#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ - SPX_FULL_HEIGHT * SPX_N) -#define SPX_PK_BYTES (2 * SPX_N) -#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) - -#include "sha2_offsets.h" - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/sha256avx.c b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/sha256avx.c deleted file mode 100644 index 6bbe6ecc24..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/sha256avx.c +++ /dev/null @@ -1,357 +0,0 @@ -#include -#include -#include - -#include "sha256avx.h" - -static const unsigned int RC[] = { - 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, - 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, - 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, - 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, - 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, - 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, - 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, - 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, - 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, - 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, - 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, - 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, - 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, - 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, - 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, - 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 -}; - -#define u32 uint32_t -#define u256 __m256i - -#define XOR _mm256_xor_si256 -#define OR _mm256_or_si256 -#define AND _mm256_and_si256 -#define ADD32 _mm256_add_epi32 -#define NOT(x) _mm256_xor_si256(x, _mm256_set_epi32(-1, -1, -1, -1, -1, -1, -1, -1)) - -#define LOAD(src) _mm256_loadu_si256((__m256i *)(src)) -#define STORE(dest,src) _mm256_storeu_si256((__m256i *)(dest),src) - -#define BYTESWAP(x) _mm256_shuffle_epi8(x, _mm256_set_epi8(0xc,0xd,0xe,0xf,0x8,0x9,0xa,0xb,0x4,0x5,0x6,0x7,0x0,0x1,0x2,0x3,0xc,0xd,0xe,0xf,0x8,0x9,0xa,0xb,0x4,0x5,0x6,0x7,0x0,0x1,0x2,0x3)) - -#define SHIFTR32(x, y) _mm256_srli_epi32(x, y) -#define SHIFTL32(x, y) _mm256_slli_epi32(x, y) - -#define ROTR32(x, y) OR(SHIFTR32(x, y), SHIFTL32(x, 32 - (y))) -#define ROTL32(x, y) OR(SHIFTL32(x, y), SHIFTR32(x, 32 - (y))) - -#define XOR3(a, b, c) XOR(XOR(a, b), c) - -#define ADD3_32(a, b, c) ADD32(ADD32(a, b), c) -#define ADD4_32(a, b, c, d) ADD32(ADD32(ADD32(a, b), c), d) -#define ADD5_32(a, b, c, d, e) ADD32(ADD32(ADD32(ADD32(a, b), c), d), e) - -#define MAJ_AVX(a, b, c) XOR3(AND(a, b), AND(a, c), AND(b, c)) -#define CH_AVX(a, b, c) XOR(AND(a, b), AND(NOT(a), c)) - -#define SIGMA1_AVX(x) XOR3(ROTR32(x, 6), ROTR32(x, 11), ROTR32(x, 25)) -#define SIGMA0_AVX(x) XOR3(ROTR32(x, 2), ROTR32(x, 13), ROTR32(x, 22)) - -#define WSIGMA1_AVX(x) XOR3(ROTR32(x, 17), ROTR32(x, 19), SHIFTR32(x, 10)) -#define WSIGMA0_AVX(x) XOR3(ROTR32(x, 7), ROTR32(x, 18), SHIFTR32(x, 3)) - -#define SHA256ROUND_AVX(a, b, c, d, e, f, g, h, rc, w) \ - T0 = ADD5_32(h, SIGMA1_AVX(e), CH_AVX(e, f, g), _mm256_set1_epi32((int)RC[rc]), w); \ - (d) = ADD32(d, T0); \ - T1 = ADD32(SIGMA0_AVX(a), MAJ_AVX(a, b, c)); \ - (h) = ADD32(T0, T1); - -// Transpose 8 vectors containing 32-bit values -static void transpose(u256 s[8]) { - u256 tmp0[8]; - u256 tmp1[8]; - tmp0[0] = _mm256_unpacklo_epi32(s[0], s[1]); - tmp0[1] = _mm256_unpackhi_epi32(s[0], s[1]); - tmp0[2] = _mm256_unpacklo_epi32(s[2], s[3]); - tmp0[3] = _mm256_unpackhi_epi32(s[2], s[3]); - tmp0[4] = _mm256_unpacklo_epi32(s[4], s[5]); - tmp0[5] = _mm256_unpackhi_epi32(s[4], s[5]); - tmp0[6] = _mm256_unpacklo_epi32(s[6], s[7]); - tmp0[7] = _mm256_unpackhi_epi32(s[6], s[7]); - tmp1[0] = _mm256_unpacklo_epi64(tmp0[0], tmp0[2]); - tmp1[1] = _mm256_unpackhi_epi64(tmp0[0], tmp0[2]); - tmp1[2] = _mm256_unpacklo_epi64(tmp0[1], tmp0[3]); - tmp1[3] = _mm256_unpackhi_epi64(tmp0[1], tmp0[3]); - tmp1[4] = _mm256_unpacklo_epi64(tmp0[4], tmp0[6]); - tmp1[5] = _mm256_unpackhi_epi64(tmp0[4], tmp0[6]); - tmp1[6] = _mm256_unpacklo_epi64(tmp0[5], tmp0[7]); - tmp1[7] = _mm256_unpackhi_epi64(tmp0[5], tmp0[7]); - s[0] = _mm256_permute2x128_si256(tmp1[0], tmp1[4], 0x20); - s[1] = _mm256_permute2x128_si256(tmp1[1], tmp1[5], 0x20); - s[2] = _mm256_permute2x128_si256(tmp1[2], tmp1[6], 0x20); - s[3] = _mm256_permute2x128_si256(tmp1[3], tmp1[7], 0x20); - s[4] = _mm256_permute2x128_si256(tmp1[0], tmp1[4], 0x31); - s[5] = _mm256_permute2x128_si256(tmp1[1], tmp1[5], 0x31); - s[6] = _mm256_permute2x128_si256(tmp1[2], tmp1[6], 0x31); - s[7] = _mm256_permute2x128_si256(tmp1[3], tmp1[7], 0x31); -} - -void sha256_ctx_clone8x(sha256x8ctx *out, const sha256x8ctx *in) { - memcpy(out, in, sizeof(sha256x8ctx)); -} - -void sha256_init8x(sha256x8ctx *ctx) { - ctx->s[0] = _mm256_set_epi32((int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667); - ctx->s[1] = _mm256_set_epi32((int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85); - ctx->s[2] = _mm256_set_epi32((int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372); - ctx->s[3] = _mm256_set_epi32((int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a); - ctx->s[4] = _mm256_set_epi32((int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f); - ctx->s[5] = _mm256_set_epi32((int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c); - ctx->s[6] = _mm256_set_epi32((int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab); - ctx->s[7] = _mm256_set_epi32((int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19); - - ctx->datalen = 0; - ctx->msglen = 0; -} - -void sha256_final8x(sha256x8ctx *ctx, - unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7) { - unsigned int i, curlen; - - // Padding - if (ctx->datalen < 56) { - for (i = 0; i < 8; ++i) { - curlen = ctx->datalen; - ctx->msgblocks[64 * i + curlen++] = 0x80; - while (curlen < 64) { - ctx->msgblocks[64 * i + curlen++] = 0x00; - } - } - } else { - for (i = 0; i < 8; ++i) { - curlen = ctx->datalen; - ctx->msgblocks[64 * i + curlen++] = 0x80; - while (curlen < 64) { - ctx->msgblocks[64 * i + curlen++] = 0x00; - } - } - sha256_transform8x(ctx, - &ctx->msgblocks[64 * 0], - &ctx->msgblocks[64 * 1], - &ctx->msgblocks[64 * 2], - &ctx->msgblocks[64 * 3], - &ctx->msgblocks[64 * 4], - &ctx->msgblocks[64 * 5], - &ctx->msgblocks[64 * 6], - &ctx->msgblocks[64 * 7] - ); - memset(ctx->msgblocks, 0, 8 * 64); - } - - // Add length of the message to each block - ctx->msglen += ctx->datalen * 8; - for (i = 0; i < 8; i++) { - ctx->msgblocks[64 * i + 63] = (unsigned char)(ctx->msglen); - ctx->msgblocks[64 * i + 62] = (unsigned char)(ctx->msglen >> 8); - ctx->msgblocks[64 * i + 61] = (unsigned char)(ctx->msglen >> 16); - ctx->msgblocks[64 * i + 60] = (unsigned char)(ctx->msglen >> 24); - ctx->msgblocks[64 * i + 59] = (unsigned char)(ctx->msglen >> 32); - ctx->msgblocks[64 * i + 58] = (unsigned char)(ctx->msglen >> 40); - ctx->msgblocks[64 * i + 57] = (unsigned char)(ctx->msglen >> 48); - ctx->msgblocks[64 * i + 56] = (unsigned char)(ctx->msglen >> 56); - } - sha256_transform8x(ctx, - &ctx->msgblocks[64 * 0], - &ctx->msgblocks[64 * 1], - &ctx->msgblocks[64 * 2], - &ctx->msgblocks[64 * 3], - &ctx->msgblocks[64 * 4], - &ctx->msgblocks[64 * 5], - &ctx->msgblocks[64 * 6], - &ctx->msgblocks[64 * 7] - ); - - // Compute final hash output - transpose(ctx->s); - - // Store Hash value - STORE(out0, BYTESWAP(ctx->s[0])); - STORE(out1, BYTESWAP(ctx->s[1])); - STORE(out2, BYTESWAP(ctx->s[2])); - STORE(out3, BYTESWAP(ctx->s[3])); - STORE(out4, BYTESWAP(ctx->s[4])); - STORE(out5, BYTESWAP(ctx->s[5])); - STORE(out6, BYTESWAP(ctx->s[6])); - STORE(out7, BYTESWAP(ctx->s[7])); -} - -void sha256_transform8x(sha256x8ctx *ctx, - const unsigned char *data0, - const unsigned char *data1, - const unsigned char *data2, - const unsigned char *data3, - const unsigned char *data4, - const unsigned char *data5, - const unsigned char *data6, - const unsigned char *data7) { - u256 s[8], w[64], T0, T1; - - // Load words and transform data correctly - w[0] = BYTESWAP(LOAD(data0)); - w[0 + 8] = BYTESWAP(LOAD(data0 + 32)); - w[1] = BYTESWAP(LOAD(data1)); - w[1 + 8] = BYTESWAP(LOAD(data1 + 32)); - w[2] = BYTESWAP(LOAD(data2)); - w[2 + 8] = BYTESWAP(LOAD(data2 + 32)); - w[3] = BYTESWAP(LOAD(data3)); - w[3 + 8] = BYTESWAP(LOAD(data3 + 32)); - w[4] = BYTESWAP(LOAD(data4)); - w[4 + 8] = BYTESWAP(LOAD(data4 + 32)); - w[5] = BYTESWAP(LOAD(data5)); - w[5 + 8] = BYTESWAP(LOAD(data5 + 32)); - w[6] = BYTESWAP(LOAD(data6)); - w[6 + 8] = BYTESWAP(LOAD(data6 + 32)); - w[7] = BYTESWAP(LOAD(data7)); - w[7 + 8] = BYTESWAP(LOAD(data7 + 32)); - - transpose(w); - transpose(w + 8); - - // Initial State - s[0] = ctx->s[0]; - s[1] = ctx->s[1]; - s[2] = ctx->s[2]; - s[3] = ctx->s[3]; - s[4] = ctx->s[4]; - s[5] = ctx->s[5]; - s[6] = ctx->s[6]; - s[7] = ctx->s[7]; - - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 0, w[0]); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 1, w[1]); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 2, w[2]); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 3, w[3]); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 4, w[4]); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 5, w[5]); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 6, w[6]); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 7, w[7]); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 8, w[8]); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 9, w[9]); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 10, w[10]); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 11, w[11]); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 12, w[12]); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 13, w[13]); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 14, w[14]); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 15, w[15]); - w[16] = ADD4_32(WSIGMA1_AVX(w[14]), w[0], w[9], WSIGMA0_AVX(w[1])); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 16, w[16]); - w[17] = ADD4_32(WSIGMA1_AVX(w[15]), w[1], w[10], WSIGMA0_AVX(w[2])); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 17, w[17]); - w[18] = ADD4_32(WSIGMA1_AVX(w[16]), w[2], w[11], WSIGMA0_AVX(w[3])); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 18, w[18]); - w[19] = ADD4_32(WSIGMA1_AVX(w[17]), w[3], w[12], WSIGMA0_AVX(w[4])); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 19, w[19]); - w[20] = ADD4_32(WSIGMA1_AVX(w[18]), w[4], w[13], WSIGMA0_AVX(w[5])); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 20, w[20]); - w[21] = ADD4_32(WSIGMA1_AVX(w[19]), w[5], w[14], WSIGMA0_AVX(w[6])); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 21, w[21]); - w[22] = ADD4_32(WSIGMA1_AVX(w[20]), w[6], w[15], WSIGMA0_AVX(w[7])); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 22, w[22]); - w[23] = ADD4_32(WSIGMA1_AVX(w[21]), w[7], w[16], WSIGMA0_AVX(w[8])); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 23, w[23]); - w[24] = ADD4_32(WSIGMA1_AVX(w[22]), w[8], w[17], WSIGMA0_AVX(w[9])); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 24, w[24]); - w[25] = ADD4_32(WSIGMA1_AVX(w[23]), w[9], w[18], WSIGMA0_AVX(w[10])); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 25, w[25]); - w[26] = ADD4_32(WSIGMA1_AVX(w[24]), w[10], w[19], WSIGMA0_AVX(w[11])); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 26, w[26]); - w[27] = ADD4_32(WSIGMA1_AVX(w[25]), w[11], w[20], WSIGMA0_AVX(w[12])); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 27, w[27]); - w[28] = ADD4_32(WSIGMA1_AVX(w[26]), w[12], w[21], WSIGMA0_AVX(w[13])); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 28, w[28]); - w[29] = ADD4_32(WSIGMA1_AVX(w[27]), w[13], w[22], WSIGMA0_AVX(w[14])); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 29, w[29]); - w[30] = ADD4_32(WSIGMA1_AVX(w[28]), w[14], w[23], WSIGMA0_AVX(w[15])); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 30, w[30]); - w[31] = ADD4_32(WSIGMA1_AVX(w[29]), w[15], w[24], WSIGMA0_AVX(w[16])); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 31, w[31]); - w[32] = ADD4_32(WSIGMA1_AVX(w[30]), w[16], w[25], WSIGMA0_AVX(w[17])); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 32, w[32]); - w[33] = ADD4_32(WSIGMA1_AVX(w[31]), w[17], w[26], WSIGMA0_AVX(w[18])); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 33, w[33]); - w[34] = ADD4_32(WSIGMA1_AVX(w[32]), w[18], w[27], WSIGMA0_AVX(w[19])); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 34, w[34]); - w[35] = ADD4_32(WSIGMA1_AVX(w[33]), w[19], w[28], WSIGMA0_AVX(w[20])); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 35, w[35]); - w[36] = ADD4_32(WSIGMA1_AVX(w[34]), w[20], w[29], WSIGMA0_AVX(w[21])); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 36, w[36]); - w[37] = ADD4_32(WSIGMA1_AVX(w[35]), w[21], w[30], WSIGMA0_AVX(w[22])); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 37, w[37]); - w[38] = ADD4_32(WSIGMA1_AVX(w[36]), w[22], w[31], WSIGMA0_AVX(w[23])); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 38, w[38]); - w[39] = ADD4_32(WSIGMA1_AVX(w[37]), w[23], w[32], WSIGMA0_AVX(w[24])); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 39, w[39]); - w[40] = ADD4_32(WSIGMA1_AVX(w[38]), w[24], w[33], WSIGMA0_AVX(w[25])); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 40, w[40]); - w[41] = ADD4_32(WSIGMA1_AVX(w[39]), w[25], w[34], WSIGMA0_AVX(w[26])); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 41, w[41]); - w[42] = ADD4_32(WSIGMA1_AVX(w[40]), w[26], w[35], WSIGMA0_AVX(w[27])); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 42, w[42]); - w[43] = ADD4_32(WSIGMA1_AVX(w[41]), w[27], w[36], WSIGMA0_AVX(w[28])); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 43, w[43]); - w[44] = ADD4_32(WSIGMA1_AVX(w[42]), w[28], w[37], WSIGMA0_AVX(w[29])); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 44, w[44]); - w[45] = ADD4_32(WSIGMA1_AVX(w[43]), w[29], w[38], WSIGMA0_AVX(w[30])); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 45, w[45]); - w[46] = ADD4_32(WSIGMA1_AVX(w[44]), w[30], w[39], WSIGMA0_AVX(w[31])); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 46, w[46]); - w[47] = ADD4_32(WSIGMA1_AVX(w[45]), w[31], w[40], WSIGMA0_AVX(w[32])); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 47, w[47]); - w[48] = ADD4_32(WSIGMA1_AVX(w[46]), w[32], w[41], WSIGMA0_AVX(w[33])); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 48, w[48]); - w[49] = ADD4_32(WSIGMA1_AVX(w[47]), w[33], w[42], WSIGMA0_AVX(w[34])); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 49, w[49]); - w[50] = ADD4_32(WSIGMA1_AVX(w[48]), w[34], w[43], WSIGMA0_AVX(w[35])); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 50, w[50]); - w[51] = ADD4_32(WSIGMA1_AVX(w[49]), w[35], w[44], WSIGMA0_AVX(w[36])); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 51, w[51]); - w[52] = ADD4_32(WSIGMA1_AVX(w[50]), w[36], w[45], WSIGMA0_AVX(w[37])); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 52, w[52]); - w[53] = ADD4_32(WSIGMA1_AVX(w[51]), w[37], w[46], WSIGMA0_AVX(w[38])); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 53, w[53]); - w[54] = ADD4_32(WSIGMA1_AVX(w[52]), w[38], w[47], WSIGMA0_AVX(w[39])); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 54, w[54]); - w[55] = ADD4_32(WSIGMA1_AVX(w[53]), w[39], w[48], WSIGMA0_AVX(w[40])); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 55, w[55]); - w[56] = ADD4_32(WSIGMA1_AVX(w[54]), w[40], w[49], WSIGMA0_AVX(w[41])); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 56, w[56]); - w[57] = ADD4_32(WSIGMA1_AVX(w[55]), w[41], w[50], WSIGMA0_AVX(w[42])); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 57, w[57]); - w[58] = ADD4_32(WSIGMA1_AVX(w[56]), w[42], w[51], WSIGMA0_AVX(w[43])); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 58, w[58]); - w[59] = ADD4_32(WSIGMA1_AVX(w[57]), w[43], w[52], WSIGMA0_AVX(w[44])); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 59, w[59]); - w[60] = ADD4_32(WSIGMA1_AVX(w[58]), w[44], w[53], WSIGMA0_AVX(w[45])); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 60, w[60]); - w[61] = ADD4_32(WSIGMA1_AVX(w[59]), w[45], w[54], WSIGMA0_AVX(w[46])); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 61, w[61]); - w[62] = ADD4_32(WSIGMA1_AVX(w[60]), w[46], w[55], WSIGMA0_AVX(w[47])); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 62, w[62]); - w[63] = ADD4_32(WSIGMA1_AVX(w[61]), w[47], w[56], WSIGMA0_AVX(w[48])); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 63, w[63]); - - // Feed Forward - ctx->s[0] = ADD32(s[0], ctx->s[0]); - ctx->s[1] = ADD32(s[1], ctx->s[1]); - ctx->s[2] = ADD32(s[2], ctx->s[2]); - ctx->s[3] = ADD32(s[3], ctx->s[3]); - ctx->s[4] = ADD32(s[4], ctx->s[4]); - ctx->s[5] = ADD32(s[5], ctx->s[5]); - ctx->s[6] = ADD32(s[6], ctx->s[6]); - ctx->s[7] = ADD32(s[7], ctx->s[7]); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/sha256avx.h b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/sha256avx.h deleted file mode 100644 index 1e3bcf889b..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/sha256avx.h +++ /dev/null @@ -1,44 +0,0 @@ -#ifndef SHA256AVX_H -#define SHA256AVX_H - -#include -#include - -#include "params.h" - -typedef struct SHA256state { - __m256i s[8]; - unsigned char msgblocks[8 * 64]; - unsigned int datalen; - unsigned long long msglen; -} sha256x8ctx; - -#define sha256_ctx_clone8x SPX_NAMESPACE(sha256_ctx_clone8x) -void sha256_ctx_clone8x(sha256x8ctx *out, const sha256x8ctx *in); - -#define sha256_init8x SPX_NAMESPACE(sha256_init8x) -void sha256_init8x(sha256x8ctx *ctx); - -#define sha256_final8x SPX_NAMESPACE(sha256_final8x) -void sha256_final8x(sha256x8ctx *ctx, - unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7); - -#define sha256_transform8x SPX_NAMESPACE(sha256_transform8x) -void sha256_transform8x(sha256x8ctx *ctx, - const unsigned char *data0, - const unsigned char *data1, - const unsigned char *data2, - const unsigned char *data3, - const unsigned char *data4, - const unsigned char *data5, - const unsigned char *data6, - const unsigned char *data7); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/sha256x8.c b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/sha256x8.c deleted file mode 100644 index d97750c09b..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/sha256x8.c +++ /dev/null @@ -1,185 +0,0 @@ -#include - -#include "sha256avx.h" -#include "sha256x8.h" -#include "utils.h" - -// Performs sha256x8 on an initialized (and perhaps seeded) state. -static void _sha256x8( - sha256x8ctx *ctx, - unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - const unsigned char *in4, - const unsigned char *in5, - const unsigned char *in6, - const unsigned char *in7, unsigned long long inlen) { - unsigned long long i = 0; - while (inlen - i >= 64) { - sha256_transform8x(ctx, - in0 + i, - in1 + i, - in2 + i, - in3 + i, - in4 + i, - in5 + i, - in6 + i, - in7 + i - ); - i += 64; - ctx->msglen += 512; - } - - size_t bytes_to_copy = (size_t)(inlen - i); - memcpy(&ctx->msgblocks[64 * 0], in0 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64 * 1], in1 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64 * 2], in2 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64 * 3], in3 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64 * 4], in4 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64 * 5], in5 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64 * 6], in6 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64 * 7], in7 + i, bytes_to_copy); - ctx->datalen = (unsigned int)bytes_to_copy; - - sha256_final8x(ctx, out0, out1, out2, out3, out4, out5, out6, out7); -} - -void sha256x8_seeded( - unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7, - const sha256x8ctx *seed, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - const unsigned char *in4, - const unsigned char *in5, - const unsigned char *in6, - const unsigned char *in7, unsigned long long inlen) { - - sha256x8ctx ctx; - sha256_ctx_clone8x(&ctx, seed); - - _sha256x8(&ctx, out0, out1, out2, out3, out4, out5, out6, out7, - in0, in1, in2, in3, in4, in5, in6, in7, inlen); -} - -/* This provides a wrapper around the internals of 8x parallel SHA256 */ -void sha256x8(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - const unsigned char *in4, - const unsigned char *in5, - const unsigned char *in6, - const unsigned char *in7, unsigned long long inlen) { - sha256x8ctx ctx; - sha256_init8x(&ctx); - - _sha256x8(&ctx, out0, out1, out2, out3, out4, out5, out6, out7, - in0, in1, in2, in3, in4, in5, in6, in7, inlen); -} - -/** - * Note that inlen should be sufficiently small that it still allows for - * an array to be allocated on the stack. Typically 'in' is merely a seed. - * Outputs outlen number of bytes - */ -void mgf1x8(unsigned char *outx8, unsigned long outlen, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - const unsigned char *in4, - const unsigned char *in5, - const unsigned char *in6, - const unsigned char *in7, - unsigned long inlen) { - PQCLEAN_VLA(unsigned char, inbufx8, 8 * (inlen + 4)); - unsigned char outbufx8[8 * SPX_SHA256_OUTPUT_BYTES]; - uint32_t i; - unsigned int j; - - memcpy(inbufx8 + 0 * (inlen + 4), in0, inlen); - memcpy(inbufx8 + 1 * (inlen + 4), in1, inlen); - memcpy(inbufx8 + 2 * (inlen + 4), in2, inlen); - memcpy(inbufx8 + 3 * (inlen + 4), in3, inlen); - memcpy(inbufx8 + 4 * (inlen + 4), in4, inlen); - memcpy(inbufx8 + 5 * (inlen + 4), in5, inlen); - memcpy(inbufx8 + 6 * (inlen + 4), in6, inlen); - memcpy(inbufx8 + 7 * (inlen + 4), in7, inlen); - - /* While we can fit in at least another full block of SHA256 output.. */ - for (i = 0; (i + 1)*SPX_SHA256_OUTPUT_BYTES <= outlen; i++) { - for (j = 0; j < 8; j++) { - u32_to_bytes(inbufx8 + inlen + j * (inlen + 4), i); - } - - sha256x8(outx8 + 0 * outlen, - outx8 + 1 * outlen, - outx8 + 2 * outlen, - outx8 + 3 * outlen, - outx8 + 4 * outlen, - outx8 + 5 * outlen, - outx8 + 6 * outlen, - outx8 + 7 * outlen, - inbufx8 + 0 * (inlen + 4), - inbufx8 + 1 * (inlen + 4), - inbufx8 + 2 * (inlen + 4), - inbufx8 + 3 * (inlen + 4), - inbufx8 + 4 * (inlen + 4), - inbufx8 + 5 * (inlen + 4), - inbufx8 + 6 * (inlen + 4), - inbufx8 + 7 * (inlen + 4), inlen + 4); - outx8 += SPX_SHA256_OUTPUT_BYTES; - } - /* Until we cannot anymore, and we fill the remainder. */ - for (j = 0; j < 8; j++) { - u32_to_bytes(inbufx8 + inlen + j * (inlen + 4), i); - } - sha256x8(outbufx8 + 0 * SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 1 * SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 2 * SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 3 * SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 4 * SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 5 * SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 6 * SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 7 * SPX_SHA256_OUTPUT_BYTES, - inbufx8 + 0 * (inlen + 4), - inbufx8 + 1 * (inlen + 4), - inbufx8 + 2 * (inlen + 4), - inbufx8 + 3 * (inlen + 4), - inbufx8 + 4 * (inlen + 4), - inbufx8 + 5 * (inlen + 4), - inbufx8 + 6 * (inlen + 4), - inbufx8 + 7 * (inlen + 4), inlen + 4); - - for (j = 0; j < 8; j++) { - memcpy(outx8 + j * outlen, - outbufx8 + j * SPX_SHA256_OUTPUT_BYTES, - outlen - i * SPX_SHA256_OUTPUT_BYTES); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/sha256x8.h b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/sha256x8.h deleted file mode 100644 index 4f7330a6c1..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/sha256x8.h +++ /dev/null @@ -1,64 +0,0 @@ -#ifndef SPX_SHA256X8_H -#define SPX_SHA256X8_H - -#include "params.h" -#include "sha256avx.h" - - - -#define sha256x8_seeded SPX_NAMESPACE(sha256x8_seeded) -void sha256x8_seeded( - unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7, - const sha256x8ctx *seed, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - const unsigned char *in4, - const unsigned char *in5, - const unsigned char *in6, - const unsigned char *in7, unsigned long long inlen); - -/* This provides a wrapper around the internals of 8x parallel SHA256 */ -#define sha256x8 SPX_NAMESPACE(sha256x8) -void sha256x8(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - const unsigned char *in4, - const unsigned char *in5, - const unsigned char *in6, - const unsigned char *in7, unsigned long long inlen); - -/** - * Note that inlen should be sufficiently small that it still allows for - * an array to be allocated on the stack. Typically 'in' is merely a seed. - * Outputs outlen number of bytes - */ -#define mgf1x8 SPX_NAMESPACE(mgf1x8) -void mgf1x8(unsigned char *outx8, unsigned long outlen, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - const unsigned char *in4, - const unsigned char *in5, - const unsigned char *in6, - const unsigned char *in7, - unsigned long inlen); -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/sha2_offsets.h b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/sha2_offsets.h deleted file mode 100644 index 6e3584f7a4..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/sha2_offsets.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef SHA2_OFFSETS_H_ -#define SHA2_OFFSETS_H_ - -#define SPX_SHA256_BLOCK_BYTES 64 -#define SPX_SHA256_OUTPUT_BYTES 32 - -#define SPX_SHA512_BLOCK_BYTES 128 -#define SPX_SHA512_OUTPUT_BYTES 64 - -/* - * Offsets of various fields in the address structure when we use SHA2 as - * the Sphincs+ hash function - */ - -#define SPX_OFFSET_LAYER 0 /* The byte used to specify the Merkle tree layer */ -#define SPX_OFFSET_TREE 1 /* The start of the 8 byte field used to specify the tree */ -#define SPX_OFFSET_TYPE 9 /* The byte used to specify the hash type (reason) */ -#define SPX_OFFSET_KP_ADDR2 12 /* The high byte used to specify the key pair (which one-time signature) */ -#define SPX_OFFSET_KP_ADDR1 13 /* The low byte used to specify the key pair */ -#define SPX_OFFSET_CHAIN_ADDR 17 /* The byte used to specify the chain address (which Winternitz chain) */ -#define SPX_OFFSET_HASH_ADDR 21 /* The byte used to specify the hash address (where in the Winternitz chain) */ -#define SPX_OFFSET_TREE_HGT 17 /* The byte used to specify the height of this node in the FORS or Merkle tree */ -#define SPX_OFFSET_TREE_INDEX 18 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ - -#define SPX_SHA2 1 - -#endif /* SHA2_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/sha512x4.c b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/sha512x4.c deleted file mode 100644 index 8d33deffdd..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/sha512x4.c +++ /dev/null @@ -1,446 +0,0 @@ -#include -#include -#include - -/* pull in the entire thing */ -#include "sha512x4.h" -#include "utils.h" - -typedef uint64_t u64; -typedef __m256i u256; - -#define BYTESWAP(x) _mm256_shuffle_epi8(x, _mm256_set_epi8(0x8,0x9,0xa,0xb,0xc,0xd,0xe,0xf,0x0,0x1,0x2,0x3,0x4,0x5,0x6,0x7,0x8,0x9,0xa,0xb,0xc,0xd,0xe,0xf,0x0,0x1,0x2,0x3,0x4,0x5,0x6,0x7)) -#define STORE(dest,src) _mm256_storeu_si256((__m256i *)(dest),src) - -// Transpose 4 vectors containing 64-bit values -// That is, it rearranges the array: -// A B C D -// E F G H -// I J K L -// M N O P -// into -// A E I M -// B F J N -// C G K O -// D H L P -// where each letter stands for 64 bits (and lsbits on the left) -static void transpose(u256 s[4]) { - u256 tmp[4]; - tmp[0] = _mm256_unpacklo_epi64(s[0], s[1]); - tmp[1] = _mm256_unpackhi_epi64(s[0], s[1]); - tmp[2] = _mm256_unpacklo_epi64(s[2], s[3]); - tmp[3] = _mm256_unpackhi_epi64(s[2], s[3]); - // tmp is in the order of - // A E C G - // B F D H - // I M K O - // J N L P - s[0] = _mm256_permute2x128_si256(tmp[0], tmp[2], 0x20); - s[1] = _mm256_permute2x128_si256(tmp[1], tmp[3], 0x20); - s[2] = _mm256_permute2x128_si256(tmp[0], tmp[2], 0x31); - s[3] = _mm256_permute2x128_si256(tmp[1], tmp[3], 0x31); -} - - -void sha512_init4x(sha512x4ctx *ctx) { -#define SET4(x) _mm256_set_epi64x((long long)(x), (long long)(x), (long long)(x), (long long)(x)) - ctx->s[0] = SET4(0x6a09e667f3bcc908ULL); - ctx->s[1] = SET4(0xbb67ae8584caa73bULL); - ctx->s[2] = SET4(0x3c6ef372fe94f82bULL); - ctx->s[3] = SET4(0xa54ff53a5f1d36f1ULL); - ctx->s[4] = SET4(0x510e527fade682d1ULL); - ctx->s[5] = SET4(0x9b05688c2b3e6c1fULL); - ctx->s[6] = SET4(0x1f83d9abfb41bd6bULL); - ctx->s[7] = SET4(0x5be0cd19137e2179ULL); -#undef SET4 - - ctx->datalen = 0; - ctx->msglen = 0; -} - -#define XOR _mm256_xor_si256 -#define OR _mm256_or_si256 -#define AND _mm256_and_si256 -#define ADD64 _mm256_add_epi64 - -#define LOAD(src) _mm256_loadu_si256((__m256i *)(src)) - -#define SHIFTR64(x, y) _mm256_srli_epi64(x, y) -#define SHIFTL64(x, y) _mm256_slli_epi64(x, y) - -#define ROTR64(x, y) OR(SHIFTR64(x, y), SHIFTL64(x, 64 - (y))) - -static u256 XOR3(u256 a, u256 b, u256 c) { - return XOR(XOR(a, b), c); -} - -#define ADD3_64(a, b, c) ADD64(ADD64(a, b), c) -#define ADD4_64(a, b, c, d) ADD64(ADD64(ADD64(a, b), c), d) -#define ADD5_64(a, b, c, d, e) ADD64(ADD64(ADD64(ADD64(a, b), c), d), e) - -static u256 MAJ_AVX(u256 a, u256 b, u256 c) { - return XOR(c, AND(XOR(a, c), XOR(b, c))); -} -static u256 CH_AVX(u256 a, u256 b, u256 c) { - return XOR(c, AND(a, XOR(b, c))); -} -static u256 SIGMA0_AVX(u256 x) { - return XOR3(ROTR64(x, 28), ROTR64(x, 34), ROTR64(x, 39)); -} -static u256 SIGMA1_AVX(u256 x) { - return XOR3(ROTR64(x, 14), ROTR64(x, 18), ROTR64(x, 41)); -} -static u256 GAMMA0_AVX(u256 x) { - return XOR3(ROTR64(x, 1), ROTR64(x, 8), SHIFTR64(x, 7)); -} -static u256 GAMMA1_AVX(u256 x) { - return XOR3(ROTR64(x, 19), ROTR64(x, 61), SHIFTR64(x, 6)); -} - -#define SHA512ROUND_AVX(a, b, c, d, e, f, g, h, rc, w) \ - T0 = ADD5_64(h, w, SIGMA1_AVX(e), CH_AVX(e, f, g), _mm256_set1_epi64x((long long)RC[rc])); \ - T1 = ADD64(SIGMA0_AVX(a), MAJ_AVX(a, b, c)); \ - (d) = ADD64(d, T0); \ - (h) = ADD64(T0, T1); - -static const unsigned long long RC[80] = { - 0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL, - 0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL, - 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL, - 0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL, - 0xd807aa98a3030242ULL, 0x12835b0145706fbeULL, - 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL, - 0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL, - 0x9bdc06a725c71235ULL, 0xc19bf174cf692694ULL, - 0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL, - 0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL, - 0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL, - 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL, - 0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL, - 0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL, - 0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL, - 0x06ca6351e003826fULL, 0x142929670a0e6e70ULL, - 0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL, - 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL, - 0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL, - 0x81c2c92e47edaee6ULL, 0x92722c851482353bULL, - 0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL, - 0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL, - 0xd192e819d6ef5218ULL, 0xd69906245565a910ULL, - 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL, - 0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL, - 0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL, - 0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL, - 0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL, - 0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL, - 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL, - 0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL, - 0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL, - 0xca273eceea26619cULL, 0xd186b8c721c0c207ULL, - 0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL, - 0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL, - 0x113f9804bef90daeULL, 0x1b710b35131c471bULL, - 0x28db77f523047d84ULL, 0x32caab7b40c72493ULL, - 0x3c9ebe0a15c9bebcULL, 0x431d67c49c100d4cULL, - 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL, - 0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL, -}; - -void sha512_transform4x( - sha512x4ctx *ctx, - const unsigned char *d0, - const unsigned char *d1, - const unsigned char *d2, - const unsigned char *d3) { - u256 s0, s1, s2, s3, s4, s5, s6, s7, w[16], T0, T1, nw; - - // Load words and transform data correctly - w[0 ] = BYTESWAP(LOAD(d0 )); - w[0 + 4] = BYTESWAP(LOAD(d0 + 32)); - w[0 + 8] = BYTESWAP(LOAD(d0 + 64)); - w[0 + 12] = BYTESWAP(LOAD(d0 + 96)); - - w[1 ] = BYTESWAP(LOAD(d1 )); - w[1 + 4] = BYTESWAP(LOAD(d1 + 32)); - w[1 + 8] = BYTESWAP(LOAD(d1 + 64)); - w[1 + 12] = BYTESWAP(LOAD(d1 + 96)); - - w[2 ] = BYTESWAP(LOAD(d2 )); - w[2 + 4] = BYTESWAP(LOAD(d2 + 32)); - w[2 + 8] = BYTESWAP(LOAD(d2 + 64)); - w[2 + 12] = BYTESWAP(LOAD(d2 + 96)); - - w[3 ] = BYTESWAP(LOAD(d3 )); - w[3 + 4] = BYTESWAP(LOAD(d3 + 32)); - w[3 + 8] = BYTESWAP(LOAD(d3 + 64)); - w[3 + 12] = BYTESWAP(LOAD(d3 + 96)); - - transpose(w); - transpose(w + 4); - transpose(w + 8); - transpose(w + 12); - - // Initial State - s0 = ctx->s[0]; - s1 = ctx->s[1]; - s2 = ctx->s[2]; - s3 = ctx->s[3]; - s4 = ctx->s[4]; - s5 = ctx->s[5]; - s6 = ctx->s[6]; - s7 = ctx->s[7]; - - // The first 16 rounds (where the w inputs are directly from the data) - SHA512ROUND_AVX(s0, s1, s2, s3, s4, s5, s6, s7, 0, w[0]); - SHA512ROUND_AVX(s7, s0, s1, s2, s3, s4, s5, s6, 1, w[1]); - SHA512ROUND_AVX(s6, s7, s0, s1, s2, s3, s4, s5, 2, w[2]); - SHA512ROUND_AVX(s5, s6, s7, s0, s1, s2, s3, s4, 3, w[3]); - SHA512ROUND_AVX(s4, s5, s6, s7, s0, s1, s2, s3, 4, w[4]); - SHA512ROUND_AVX(s3, s4, s5, s6, s7, s0, s1, s2, 5, w[5]); - SHA512ROUND_AVX(s2, s3, s4, s5, s6, s7, s0, s1, 6, w[6]); - SHA512ROUND_AVX(s1, s2, s3, s4, s5, s6, s7, s0, 7, w[7]); - SHA512ROUND_AVX(s0, s1, s2, s3, s4, s5, s6, s7, 8, w[8]); - SHA512ROUND_AVX(s7, s0, s1, s2, s3, s4, s5, s6, 9, w[9]); - SHA512ROUND_AVX(s6, s7, s0, s1, s2, s3, s4, s5, 10, w[10]); - SHA512ROUND_AVX(s5, s6, s7, s0, s1, s2, s3, s4, 11, w[11]); - SHA512ROUND_AVX(s4, s5, s6, s7, s0, s1, s2, s3, 12, w[12]); - SHA512ROUND_AVX(s3, s4, s5, s6, s7, s0, s1, s2, 13, w[13]); - SHA512ROUND_AVX(s2, s3, s4, s5, s6, s7, s0, s1, 14, w[14]); - SHA512ROUND_AVX(s1, s2, s3, s4, s5, s6, s7, s0, 15, w[15]); - -#define M(i) (((i)+16) & 0xf) -#define NextW(i) \ - w[M(i)] = ADD4_64(GAMMA1_AVX(w[M((i)-2)]), w[M((i)-7)], GAMMA0_AVX(w[M((i)-15)]), w[M((i)-16)]); - - // The remaining 64 rounds (where the w inputs are a linear fix of the data) - for (unsigned i = 16; i < 80; i += 16) { - nw = NextW(0); - SHA512ROUND_AVX(s0, s1, s2, s3, s4, s5, s6, s7, i + 0, nw); - nw = NextW(1); - SHA512ROUND_AVX(s7, s0, s1, s2, s3, s4, s5, s6, i + 1, nw); - nw = NextW(2); - SHA512ROUND_AVX(s6, s7, s0, s1, s2, s3, s4, s5, i + 2, nw); - nw = NextW(3); - SHA512ROUND_AVX(s5, s6, s7, s0, s1, s2, s3, s4, i + 3, nw); - nw = NextW(4); - SHA512ROUND_AVX(s4, s5, s6, s7, s0, s1, s2, s3, i + 4, nw); - nw = NextW(5); - SHA512ROUND_AVX(s3, s4, s5, s6, s7, s0, s1, s2, i + 5, nw); - nw = NextW(6); - SHA512ROUND_AVX(s2, s3, s4, s5, s6, s7, s0, s1, i + 6, nw); - nw = NextW(7); - SHA512ROUND_AVX(s1, s2, s3, s4, s5, s6, s7, s0, i + 7, nw); - nw = NextW(8); - SHA512ROUND_AVX(s0, s1, s2, s3, s4, s5, s6, s7, i + 8, nw); - nw = NextW(9); - SHA512ROUND_AVX(s7, s0, s1, s2, s3, s4, s5, s6, i + 9, nw); - nw = NextW(10); - SHA512ROUND_AVX(s6, s7, s0, s1, s2, s3, s4, s5, i + 10, nw); - nw = NextW(11); - SHA512ROUND_AVX(s5, s6, s7, s0, s1, s2, s3, s4, i + 11, nw); - nw = NextW(12); - SHA512ROUND_AVX(s4, s5, s6, s7, s0, s1, s2, s3, i + 12, nw); - nw = NextW(13); - SHA512ROUND_AVX(s3, s4, s5, s6, s7, s0, s1, s2, i + 13, nw); - nw = NextW(14); - SHA512ROUND_AVX(s2, s3, s4, s5, s6, s7, s0, s1, i + 14, nw); - nw = NextW(15); - SHA512ROUND_AVX(s1, s2, s3, s4, s5, s6, s7, s0, i + 15, nw); - } - - // Feed Forward - ctx->s[0] = ADD64(s0, ctx->s[0]); - ctx->s[1] = ADD64(s1, ctx->s[1]); - ctx->s[2] = ADD64(s2, ctx->s[2]); - ctx->s[3] = ADD64(s3, ctx->s[3]); - ctx->s[4] = ADD64(s4, ctx->s[4]); - ctx->s[5] = ADD64(s5, ctx->s[5]); - ctx->s[6] = ADD64(s6, ctx->s[6]); - ctx->s[7] = ADD64(s7, ctx->s[7]); -} - -static void _sha512x4( - sha512x4ctx *ctx, - unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - unsigned long long inlen) { - unsigned int i = 0; - - while (inlen - i >= 128) { - sha512_transform4x( - ctx, - in0 + i, - in1 + i, - in2 + i, - in3 + i - ); - ctx->msglen += 1024; - i += 128; - } - - ctx->datalen = (unsigned int)(inlen - i); - memcpy(&ctx->msgblocks[128 * 0], in0 + i, ctx->datalen); - memcpy(&ctx->msgblocks[128 * 1], in1 + i, ctx->datalen); - memcpy(&ctx->msgblocks[128 * 2], in2 + i, ctx->datalen); - memcpy(&ctx->msgblocks[128 * 3], in3 + i, ctx->datalen); - - // Padding - unsigned long curlen; - if (ctx->datalen < 112) { - for (i = 0; i < 4; ++i) { - curlen = ctx->datalen; - ctx->msgblocks[128 * i + curlen++] = 0x80; - while (curlen < 128) { - ctx->msgblocks[128 * i + curlen++] = 0x00; - } - } - } else { - for (i = 0; i < 4; ++i) { - curlen = ctx->datalen; - ctx->msgblocks[128 * i + curlen++] = 0x80; - while (curlen < 128) { - ctx->msgblocks[128 * i + curlen++] = 0x00; - } - } - sha512_transform4x( - ctx, - ctx->msgblocks, - ctx->msgblocks + 128, - ctx->msgblocks + 256, - ctx->msgblocks + 384 - ); - memset(ctx->msgblocks, 0, 4 * 128); - } - - // Add length of the message to each block - ctx->msglen += (unsigned long long)(ctx->datalen) * 8; - for (i = 0; i < 4; i++) { - ctx->msgblocks[128 * i + 127] = (unsigned char)(ctx->msglen); - ctx->msgblocks[128 * i + 126] = (unsigned char)(ctx->msglen >> 8); - ctx->msgblocks[128 * i + 125] = (unsigned char)(ctx->msglen >> 16); - ctx->msgblocks[128 * i + 124] = (unsigned char)(ctx->msglen >> 24); - ctx->msgblocks[128 * i + 123] = (unsigned char)(ctx->msglen >> 32); - ctx->msgblocks[128 * i + 122] = (unsigned char)(ctx->msglen >> 40); - ctx->msgblocks[128 * i + 121] = (unsigned char)(ctx->msglen >> 48); - ctx->msgblocks[128 * i + 120] = (unsigned char)(ctx->msglen >> 56); - memset( &ctx->msgblocks[128 * i + 112], 0, 8 ); - } - sha512_transform4x( - ctx, - ctx->msgblocks, - ctx->msgblocks + 128, - ctx->msgblocks + 256, - ctx->msgblocks + 384 - ); - - // Compute final hash output - transpose(ctx->s); - transpose(ctx->s + 4); - - // Store Hash value - __m256i out[2]; - STORE(out, BYTESWAP(ctx->s[0])); - STORE(out + 1, BYTESWAP(ctx->s[4])); - memcpy(out0, out, 64); - - STORE(out, BYTESWAP(ctx->s[1])); - STORE(out + 1, BYTESWAP(ctx->s[5])); - memcpy(out1, out, 64); - - STORE(out, BYTESWAP(ctx->s[2])); - STORE(out + 1, BYTESWAP(ctx->s[6])); - memcpy(out2, out, 64); - - STORE(out, BYTESWAP(ctx->s[3])); - STORE(out + 1, BYTESWAP(ctx->s[7])); - memcpy(out3, out, 64); -} - - -/** - * Note that inlen should be sufficiently small that it still allows for - * an array to be allocated on the stack. Typically 'in' is merely a seed. - * Outputs outlen number of bytes - */ -void mgf1x4_512(unsigned char *outx4, unsigned long outlen, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - unsigned long inlen) { - PQCLEAN_VLA(unsigned char, inbufx4, 4 * (inlen + 4)); - unsigned char outbuf[4 * 64]; - uint32_t i; - unsigned int j; - - memcpy(inbufx4 + 0 * (inlen + 4), in0, inlen); - memcpy(inbufx4 + 1 * (inlen + 4), in1, inlen); - memcpy(inbufx4 + 2 * (inlen + 4), in2, inlen); - memcpy(inbufx4 + 3 * (inlen + 4), in3, inlen); - - /* While we can fit in at least another full block of SHA512 output.. */ - unsigned long remaining = outlen; - for (i = 0; remaining > 0; i++) { - unsigned long this_step = SPX_SHA512_OUTPUT_BYTES; - if (this_step > remaining) { - this_step = remaining; - } - remaining -= this_step; - for (j = 0; j < 4; j++) { - u32_to_bytes(inbufx4 + inlen + j * (inlen + 4), i); - } - - sha512x4ctx ctx; - sha512_init4x(&ctx); - - _sha512x4( - &ctx, - outbuf + 0 * 64, - outbuf + 1 * 64, - outbuf + 2 * 64, - outbuf + 3 * 64, - inbufx4 + 0 * (inlen + 4), - inbufx4 + 1 * (inlen + 4), - inbufx4 + 2 * (inlen + 4), - inbufx4 + 3 * (inlen + 4), - inlen + 4 - ); - - memcpy(outx4 + 0 * outlen, outbuf + 0 * 64, this_step); - memcpy(outx4 + 1 * outlen, outbuf + 1 * 64, this_step); - memcpy(outx4 + 2 * outlen, outbuf + 2 * 64, this_step); - memcpy(outx4 + 3 * outlen, outbuf + 3 * 64, this_step); - outx4 += this_step; - } -} - -void sha512x4_seeded( - unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const sha512x4ctx *seed, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - unsigned long long inlen) { - sha512x4ctx ctx; - sha512_ctx_clone4x(&ctx, seed); - _sha512x4( - &ctx, - out0, out1, out2, out3, - in0, in1, in2, in3, - inlen - ); -} - -void sha512_ctx_clone4x(sha512x4ctx *out, const sha512x4ctx *in) { - memcpy(out, in, sizeof(sha512x4ctx)); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/sha512x4.h b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/sha512x4.h deleted file mode 100644 index 9bbe736514..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/sha512x4.h +++ /dev/null @@ -1,58 +0,0 @@ -#ifndef SHA512AVX_H -#define SHA512AVX_H - -#include -#include - - -#include "params.h" - -typedef struct SHA512state4x { - __m256i s[8]; - unsigned char msgblocks[4 * 128]; - unsigned int datalen; - unsigned long long msglen; -} sha512x4ctx; - -#define sha512_init4x SPX_NAMESPACE(sha512_init4x) -void sha512_init4x(sha512x4ctx *ctx); - -#define sha512_transform4x SPX_NAMESPACE(sha512_transform4x) -void sha512_transform4x( - sha512x4ctx *ctx, - const unsigned char *d0, - const unsigned char *d1, - const unsigned char *d2, - const unsigned char *d3); - - -#define sha512x4_seeded SPX_NAMESPACE(sha512x4_seeded) -void sha512x4_seeded( - unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const sha512x4ctx *seed, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - unsigned long long inlen); - -#define sha512_ctx_clone4x SPX_NAMESPACE(sha512_ctx_clone4x) -void sha512_ctx_clone4x(sha512x4ctx *out, const sha512x4ctx *in); - -/** - * Note that inlen should be sufficiently small that it still allows for - * an array to be allocated on the stack. Typically 'in' is merely a seed. - * Outputs outlen number of bytes - */ -#define mgf1x4_512 SPX_NAMESPACE(mgf1x4_512) -void mgf1x4_512(unsigned char *outx4, unsigned long outlen, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - unsigned long inlen); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/sign.c b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/sign.c deleted file mode 100644 index 9d0c7d1b22..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/sign.c +++ /dev/null @@ -1,286 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "context.h" -#include "fors.h" -#include "hash.h" -#include "merkle.h" -#include "nistapi.h" -#include "params.h" -#include "randombytes.h" -#include "thash.h" -#include "utils.h" -#include "wots.h" - -/* - * Returns the length of a secret key, in bytes - */ -size_t crypto_sign_secretkeybytes(void) { - return CRYPTO_SECRETKEYBYTES; -} - -/* - * Returns the length of a public key, in bytes - */ -size_t crypto_sign_publickeybytes(void) { - return CRYPTO_PUBLICKEYBYTES; -} - -/* - * Returns the length of a signature, in bytes - */ -size_t crypto_sign_bytes(void) { - return CRYPTO_BYTES; -} - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t crypto_sign_seedbytes(void) { - return CRYPTO_SEEDBYTES; -} - -/* - * Generates an SPX key pair given a seed of length - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed) { - spx_ctx ctx; - - /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ - memcpy(sk, seed, CRYPTO_SEEDBYTES); - - memcpy(pk, sk + 2 * SPX_N, SPX_N); - - memcpy(ctx.pub_seed, pk, SPX_N); - memcpy(ctx.sk_seed, sk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - /* Compute root node of the top-most subtree. */ - merkle_gen_root(sk + 3 * SPX_N, &ctx); - - // cleanup - free_hash_function(&ctx); - - memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); - - return 0; -} - -/* - * Generates an SPX key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { - uint8_t seed[CRYPTO_SEEDBYTES]; - randombytes(seed, CRYPTO_SEEDBYTES); - crypto_sign_seed_keypair(pk, sk, seed); - - return 0; -} - -/** - * Returns an array containing a detached signature. - */ -int crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - spx_ctx ctx; - - const uint8_t *sk_prf = sk + SPX_N; - const uint8_t *pk = sk + 2 * SPX_N; - - uint8_t optrand[SPX_N]; - uint8_t mhash[SPX_FORS_MSG_BYTES]; - uint8_t root[SPX_N]; - uint32_t i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - - memcpy(ctx.sk_seed, sk, SPX_N); - memcpy(ctx.pub_seed, pk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - set_type(wots_addr, SPX_ADDR_TYPE_WOTS); - set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); - - /* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ - randombytes(optrand, SPX_N); - /* Compute the digest randomization value. */ - gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); - - /* Derive the message digest and leaf index from R, PK and M. */ - hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); - sig += SPX_N; - - set_tree_addr(wots_addr, tree); - set_keypair_addr(wots_addr, idx_leaf); - - /* Sign the message hash using FORS. */ - fors_sign(sig, root, mhash, &ctx, wots_addr); - sig += SPX_FORS_BYTES; - - for (i = 0; i < SPX_D; i++) { - set_layer_addr(tree_addr, i); - set_tree_addr(tree_addr, tree); - - copy_subtree_addr(wots_addr, tree_addr); - set_keypair_addr(wots_addr, idx_leaf); - - merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); - sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); - tree = tree >> SPX_TREE_HEIGHT; - } - - free_hash_function(&ctx); - - *siglen = SPX_BYTES; - - return 0; -} - -/** - * Verifies a detached signature and message under a given public key. - */ -int crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk) { - spx_ctx ctx; - const uint8_t *pub_root = pk + SPX_N; - uint8_t mhash[SPX_FORS_MSG_BYTES]; - uint8_t wots_pk[SPX_WOTS_BYTES]; - uint8_t root[SPX_N]; - uint8_t leaf[SPX_N]; - unsigned int i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - if (siglen != SPX_BYTES) { - return -1; - } - - memcpy(ctx.pub_seed, pk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - set_type(wots_addr, SPX_ADDR_TYPE_WOTS); - set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); - set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); - - /* Derive the message digest and leaf index from R || PK || M. */ - /* The additional SPX_N is a result of the hash domain separator. */ - hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); - sig += SPX_N; - - /* Layer correctly defaults to 0, so no need to set_layer_addr */ - set_tree_addr(wots_addr, tree); - set_keypair_addr(wots_addr, idx_leaf); - - fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); - sig += SPX_FORS_BYTES; - - /* For each subtree.. */ - for (i = 0; i < SPX_D; i++) { - set_layer_addr(tree_addr, i); - set_tree_addr(tree_addr, tree); - - copy_subtree_addr(wots_addr, tree_addr); - set_keypair_addr(wots_addr, idx_leaf); - - copy_keypair_addr(wots_pk_addr, wots_addr); - - /* The WOTS public key is only correct if the signature was correct. */ - /* Initially, root is the FORS pk, but on subsequent iterations it is - the root of the subtree below the currently processed subtree. */ - wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); - sig += SPX_WOTS_BYTES; - - /* Compute the leaf node using the WOTS public key. */ - thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); - - /* Compute the root node of this subtree. */ - compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, - &ctx, tree_addr); - sig += SPX_TREE_HEIGHT * SPX_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); - tree = tree >> SPX_TREE_HEIGHT; - } - - // cleanup - free_hash_function(&ctx); - - /* Check if the root node equals the root node in the public key. */ - if (memcmp(root, pub_root, SPX_N) != 0) { - return -1; - } - - return 0; -} - - -/** - * Returns an array containing the signature followed by the message. - */ -int crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk) { - size_t siglen; - - crypto_sign_signature(sm, &siglen, m, mlen, sk); - - memmove(sm + SPX_BYTES, m, mlen); - *smlen = siglen + mlen; - - return 0; -} - -/** - * Verifies a given signature-message pair under a given public key. - */ -int crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk) { - /* The API caller does not necessarily know what size a signature should be - but SPHINCS+ signatures are always exactly SPX_BYTES. */ - if (smlen < SPX_BYTES) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - *mlen = smlen - SPX_BYTES; - - if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - /* If verification was successful, move the message to the right place. */ - memmove(m, sm + SPX_BYTES, *mlen); - - return 0; -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/thash.h b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/thash.h deleted file mode 100644 index 8687ccfb4d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/thash.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef SPX_THASH_H -#define SPX_THASH_H - -#include "context.h" -#include "params.h" - -#include - -#define thash SPX_NAMESPACE(thash) -void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/thash_sha2_robust.c b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/thash_sha2_robust.c deleted file mode 100644 index 3ab891175f..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/thash_sha2_robust.c +++ /dev/null @@ -1,68 +0,0 @@ -#include -#include - -#include "address.h" -#include "context.h" -#include "hash.h" -#include "params.h" -#include "sha2.h" -#include "thash.h" -#include "utils.h" - -static void thash_512(unsigned char *out, const unsigned char *in, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]); - -/** - * Takes an array of inblocks concatenated arrays of SPX_N bytes. - */ -void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]) { - if (inblocks > 1) { - thash_512(out, in, inblocks, ctx, addr); - return; - } - unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES]; - PQCLEAN_VLA(uint8_t, bitmask, inblocks * SPX_N); - PQCLEAN_VLA(uint8_t, buf, SPX_N + SPX_SHA256_OUTPUT_BYTES + inblocks * SPX_N); - sha256ctx sha2_state; - unsigned int i; - - memcpy(buf, ctx->pub_seed, SPX_N); - memcpy(buf + SPX_N, addr, SPX_SHA256_ADDR_BYTES); - mgf1_256(bitmask, inblocks * SPX_N, buf, SPX_N + SPX_SHA256_ADDR_BYTES); - - /* Retrieve precomputed state containing pub_seed */ - sha256_inc_ctx_clone(&sha2_state, &ctx->state_seeded); - - for (i = 0; i < inblocks * SPX_N; i++) { - buf[SPX_N + SPX_SHA256_ADDR_BYTES + i] = in[i] ^ bitmask[i]; - } - - sha256_inc_finalize(outbuf, &sha2_state, buf + SPX_N, - SPX_SHA256_ADDR_BYTES + inblocks * SPX_N); - memcpy(out, outbuf, SPX_N); -} - -static void thash_512(unsigned char *out, const unsigned char *in, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]) { - unsigned char outbuf[SPX_SHA512_OUTPUT_BYTES]; - PQCLEAN_VLA(uint8_t, bitmask, inblocks * SPX_N); - PQCLEAN_VLA(uint8_t, buf, SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N); - sha512ctx sha2_state; - unsigned int i; - - memcpy(buf, ctx->pub_seed, SPX_N); - memcpy(buf + SPX_N, addr, SPX_SHA256_ADDR_BYTES); - mgf1_512(bitmask, inblocks * SPX_N, buf, SPX_N + SPX_SHA256_ADDR_BYTES); - - /* Retrieve precomputed state containing pub_seed */ - sha512_inc_ctx_clone(&sha2_state, &ctx->state_seeded_512); - - for (i = 0; i < inblocks * SPX_N; i++) { - buf[SPX_N + SPX_SHA256_ADDR_BYTES + i] = in[i] ^ bitmask[i]; - } - - sha512_inc_finalize(outbuf, &sha2_state, buf + SPX_N, - SPX_SHA256_ADDR_BYTES + inblocks * SPX_N); - memcpy(out, outbuf, SPX_N); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/thash_sha2_robustx8.c b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/thash_sha2_robustx8.c deleted file mode 100644 index 991faa7eeb..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/thash_sha2_robustx8.c +++ /dev/null @@ -1,268 +0,0 @@ -#include -#include - -#include "thashx8.h" - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "sha2.h" -#include "sha256avx.h" -#include "sha256x8.h" -#include "utils.h" - -#include "sha512x4.h" - -static void thashx8_512( - unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - const unsigned char *in4, - const unsigned char *in5, - const unsigned char *in6, - const unsigned char *in7, - unsigned int inblocks, - const spx_ctx *ctx, - uint32_t addrx8[8 * 8] -); - -/** - * 8-way parallel version of thash; takes 8x as much input and output - */ -void thashx8(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - const unsigned char *in4, - const unsigned char *in5, - const unsigned char *in6, - const unsigned char *in7, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addrx8[8 * 8]) { - if (inblocks > 1) { - thashx8_512( - out0, out1, out2, out3, out4, out5, out6, out7, - in0, in1, in2, in3, in4, in5, in6, in7, - inblocks, ctx, addrx8); - return; - } - PQCLEAN_VLA(unsigned char, bufx8, 8 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)); - unsigned char outbufx8[8 * SPX_SHA256_OUTPUT_BYTES]; - PQCLEAN_VLA(unsigned char, bitmaskx8, 8 * (inblocks * SPX_N)); - unsigned int i; - - for (i = 0; i < 8; i++) { - memcpy(bufx8 + i * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - ctx->pub_seed, SPX_N); - memcpy(bufx8 + SPX_N + - i * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - addrx8 + i * 8, SPX_SHA256_ADDR_BYTES); - } - - mgf1x8(bitmaskx8, inblocks * SPX_N, - bufx8 + 0 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + 1 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + 2 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + 3 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + 4 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + 5 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + 6 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + 7 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - SPX_N + SPX_SHA256_ADDR_BYTES); - - for (i = 0; i < inblocks * SPX_N; i++) { - bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + - 0 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = - in0[i] ^ bitmaskx8[i + 0 * (inblocks * SPX_N)]; - bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + - 1 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = - in1[i] ^ bitmaskx8[i + 1 * (inblocks * SPX_N)]; - bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + - 2 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = - in2[i] ^ bitmaskx8[i + 2 * (inblocks * SPX_N)]; - bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + - 3 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = - in3[i] ^ bitmaskx8[i + 3 * (inblocks * SPX_N)]; - bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + - 4 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = - in4[i] ^ bitmaskx8[i + 4 * (inblocks * SPX_N)]; - bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + - 5 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = - in5[i] ^ bitmaskx8[i + 5 * (inblocks * SPX_N)]; - bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + - 6 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = - in6[i] ^ bitmaskx8[i + 6 * (inblocks * SPX_N)]; - bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + - 7 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = - in7[i] ^ bitmaskx8[i + 7 * (inblocks * SPX_N)]; - } - - sha256x8_seeded( - /* out */ - outbufx8 + 0 * SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 1 * SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 2 * SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 3 * SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 4 * SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 5 * SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 6 * SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 7 * SPX_SHA256_OUTPUT_BYTES, - - /* seed */ - &ctx->statex8_seeded, - - /* in */ - bufx8 + SPX_N + 0 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + SPX_N + 1 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + SPX_N + 2 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + SPX_N + 3 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + SPX_N + 4 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + SPX_N + 5 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + SPX_N + 6 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + SPX_N + 7 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - SPX_SHA256_ADDR_BYTES + inblocks * SPX_N /* len */ - ); - - memcpy(out0, outbufx8 + 0 * SPX_SHA256_OUTPUT_BYTES, SPX_N); - memcpy(out1, outbufx8 + 1 * SPX_SHA256_OUTPUT_BYTES, SPX_N); - memcpy(out2, outbufx8 + 2 * SPX_SHA256_OUTPUT_BYTES, SPX_N); - memcpy(out3, outbufx8 + 3 * SPX_SHA256_OUTPUT_BYTES, SPX_N); - memcpy(out4, outbufx8 + 4 * SPX_SHA256_OUTPUT_BYTES, SPX_N); - memcpy(out5, outbufx8 + 5 * SPX_SHA256_OUTPUT_BYTES, SPX_N); - memcpy(out6, outbufx8 + 6 * SPX_SHA256_OUTPUT_BYTES, SPX_N); - memcpy(out7, outbufx8 + 7 * SPX_SHA256_OUTPUT_BYTES, SPX_N); -} - -/** - * 2x4-way parallel version of thash; this is for the uses of thash that are - * based on SHA-512 - */ -static void thashx8_512( - unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - const unsigned char *in4, - const unsigned char *in5, - const unsigned char *in6, - const unsigned char *in7, - unsigned int inblocks, - const spx_ctx *ctx, - uint32_t addrx8[8 * 8]) { - PQCLEAN_VLA(unsigned char, bufx8, 8 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)); - unsigned char outbuf[4 * SPX_SHA512_OUTPUT_BYTES]; - PQCLEAN_VLA(unsigned char, bitmaskx4, 4 * (inblocks * SPX_N)); - unsigned int i; - - for (i = 0; i < 8; i++) { - memcpy(bufx8 + i * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - ctx->pub_seed, SPX_N); - memcpy(bufx8 + SPX_N + - i * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - addrx8 + i * 8, SPX_SHA256_ADDR_BYTES); - } - - mgf1x4_512(bitmaskx4, inblocks * SPX_N, - bufx8 + 0 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + 1 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + 2 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + 3 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - SPX_N + SPX_SHA256_ADDR_BYTES); - - for (i = 0; i < inblocks * SPX_N; i++) { - bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + - 0 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = - in0[i] ^ bitmaskx4[i + 0 * (inblocks * SPX_N)]; - bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + - 1 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = - in1[i] ^ bitmaskx4[i + 1 * (inblocks * SPX_N)]; - bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + - 2 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = - in2[i] ^ bitmaskx4[i + 2 * (inblocks * SPX_N)]; - bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + - 3 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = - in3[i] ^ bitmaskx4[i + 3 * (inblocks * SPX_N)]; - } - - mgf1x4_512(bitmaskx4, inblocks * SPX_N, - bufx8 + 4 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + 5 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + 6 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + 7 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - SPX_N + SPX_SHA256_ADDR_BYTES); - - for (i = 0; i < inblocks * SPX_N; i++) { - bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + - 4 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = - in4[i] ^ bitmaskx4[i + 0 * (inblocks * SPX_N)]; - bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + - 5 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = - in5[i] ^ bitmaskx4[i + 1 * (inblocks * SPX_N)]; - bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + - 6 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = - in6[i] ^ bitmaskx4[i + 2 * (inblocks * SPX_N)]; - bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + - 7 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = - in7[i] ^ bitmaskx4[i + 3 * (inblocks * SPX_N)]; - } - - sha512x4_seeded( - outbuf + 0 * SPX_SHA512_OUTPUT_BYTES, - outbuf + 1 * SPX_SHA512_OUTPUT_BYTES, - outbuf + 2 * SPX_SHA512_OUTPUT_BYTES, - outbuf + 3 * SPX_SHA512_OUTPUT_BYTES, - &ctx->statex4_seeded_512, /* seed */ - bufx8 + SPX_N + 0 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + SPX_N + 1 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + SPX_N + 2 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + SPX_N + 3 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - SPX_SHA256_ADDR_BYTES + inblocks * SPX_N /* len */ - ); - - memcpy(out0, outbuf + 0 * SPX_SHA512_OUTPUT_BYTES, SPX_N); - memcpy(out1, outbuf + 1 * SPX_SHA512_OUTPUT_BYTES, SPX_N); - memcpy(out2, outbuf + 2 * SPX_SHA512_OUTPUT_BYTES, SPX_N); - memcpy(out3, outbuf + 3 * SPX_SHA512_OUTPUT_BYTES, SPX_N); - - sha512x4_seeded( - outbuf + 0 * SPX_SHA512_OUTPUT_BYTES, - outbuf + 1 * SPX_SHA512_OUTPUT_BYTES, - outbuf + 2 * SPX_SHA512_OUTPUT_BYTES, - outbuf + 3 * SPX_SHA512_OUTPUT_BYTES, - &ctx->statex4_seeded_512, /* seed */ - bufx8 + SPX_N + 4 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + SPX_N + 5 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + SPX_N + 6 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + SPX_N + 7 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - SPX_SHA256_ADDR_BYTES + inblocks * SPX_N /* len */ - ); - - memcpy(out4, outbuf + 0 * SPX_SHA512_OUTPUT_BYTES, SPX_N); - memcpy(out5, outbuf + 1 * SPX_SHA512_OUTPUT_BYTES, SPX_N); - memcpy(out6, outbuf + 2 * SPX_SHA512_OUTPUT_BYTES, SPX_N); - memcpy(out7, outbuf + 3 * SPX_SHA512_OUTPUT_BYTES, SPX_N); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/thashx8.h b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/thashx8.h deleted file mode 100644 index c02fe9cf3e..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/thashx8.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef SPX_THASHX8_H -#define SPX_THASHX8_H - -#include - -#include "context.h" -#include "params.h" - -#define thashx8 SPX_NAMESPACE(thashx8) -void thashx8(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - const unsigned char *in4, - const unsigned char *in5, - const unsigned char *in6, - const unsigned char *in7, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addrx8[8 * 8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/utils.c b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/utils.c deleted file mode 100644 index 177b541fb9..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/utils.c +++ /dev/null @@ -1,148 +0,0 @@ -#include - -#include "utils.h" - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "thash.h" - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void ull_to_bytes(unsigned char *out, unsigned int outlen, - unsigned long long in) { - int i; - - /* Iterate over out in decreasing order, for big-endianness. */ - for (i = (signed int)outlen - 1; i >= 0; i--) { - out[i] = in & 0xff; - in = in >> 8; - } -} - -void u32_to_bytes(unsigned char *out, uint32_t in) { - out[0] = (unsigned char)(in >> 24); - out[1] = (unsigned char)(in >> 16); - out[2] = (unsigned char)(in >> 8); - out[3] = (unsigned char)in; -} - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { - unsigned long long retval = 0; - unsigned int i; - - for (i = 0; i < inlen; i++) { - retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); - } - return retval; -} - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void compute_root(unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const spx_ctx *ctx, uint32_t addr[8]) { - uint32_t i; - unsigned char buffer[2 * SPX_N]; - - /* If leaf_idx is odd (last bit = 1), current path element is a right child - and auth_path has to go left. Otherwise it is the other way around. */ - if (leaf_idx & 1) { - memcpy(buffer + SPX_N, leaf, SPX_N); - memcpy(buffer, auth_path, SPX_N); - } else { - memcpy(buffer, leaf, SPX_N); - memcpy(buffer + SPX_N, auth_path, SPX_N); - } - auth_path += SPX_N; - - for (i = 0; i < tree_height - 1; i++) { - leaf_idx >>= 1; - idx_offset >>= 1; - /* Set the address of the node we're creating. */ - set_tree_height(addr, i + 1); - set_tree_index(addr, leaf_idx + idx_offset); - - /* Pick the right or left neighbor, depending on parity of the node. */ - if (leaf_idx & 1) { - thash(buffer + SPX_N, buffer, 2, ctx, addr); - memcpy(buffer, auth_path, SPX_N); - } else { - thash(buffer, buffer, 2, ctx, addr); - memcpy(buffer + SPX_N, auth_path, SPX_N); - } - auth_path += SPX_N; - } - - /* The last iteration is exceptional; we do not copy an auth_path node. */ - leaf_idx >>= 1; - idx_offset >>= 1; - set_tree_height(addr, tree_height); - set_tree_index(addr, leaf_idx + idx_offset); - thash(root, buffer, 2, ctx, addr); -} - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const spx_ctx * /* ctx */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), - uint32_t tree_addr[8]) { - PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); - PQCLEAN_VLA(unsigned int, heights, tree_height + 1); - unsigned int offset = 0; - uint32_t idx; - uint32_t tree_idx; - - for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { - /* Add the next leaf node to the stack. */ - gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); - offset++; - heights[offset - 1] = 0; - - /* If this is a node we need for the auth path.. */ - if ((leaf_idx ^ 0x1) == idx) { - memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); - } - - /* While the top-most nodes are of equal height.. */ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { - /* Compute index of the new node, in the next layer. */ - tree_idx = (idx >> (heights[offset - 1] + 1)); - - /* Set the address of the node we're creating. */ - set_tree_height(tree_addr, heights[offset - 1] + 1); - set_tree_index(tree_addr, - tree_idx + (idx_offset >> (heights[offset - 1] + 1))); - /* Hash the top-most nodes from the stack together. */ - thash(stack + (offset - 2)*SPX_N, - stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); - offset--; - /* Note that the top-most node is now one layer higher. */ - heights[offset - 1]++; - - /* If this is a node we need for the auth path.. */ - if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_path + heights[offset - 1]*SPX_N, - stack + (offset - 1)*SPX_N, SPX_N); - } - } - } - memcpy(root, stack, SPX_N); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/utils.h b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/utils.h deleted file mode 100644 index 64f5d5a53a..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/utils.h +++ /dev/null @@ -1,58 +0,0 @@ -#ifndef SPX_UTILS_H -#define SPX_UTILS_H - -#include - -#include "compat.h" -#include "context.h" -#include "params.h" - - -/* To support MSVC use alloca() instead of VLAs. See #20. */ - - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) -void ull_to_bytes(unsigned char *out, unsigned int outlen, - unsigned long long in); -#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) -void u32_to_bytes(unsigned char *out, uint32_t in); - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) -unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -#define compute_root SPX_NAMESPACE(compute_root) -void compute_root(unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const spx_ctx *ctx, uint32_t addr[8]); - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -#define treehash SPX_NAMESPACE(treehash) -void treehash(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const spx_ctx *ctx /* ctx */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), - uint32_t tree_addr[8]); - - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/utilsx8.c b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/utilsx8.c deleted file mode 100644 index f044b9595d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/utilsx8.c +++ /dev/null @@ -1,146 +0,0 @@ -#include - -#include "utils.h" -#include "utilsx8.h" - -#include "address.h" -#include "params.h" -#include "thashx8.h" - -/* - * Generate the entire Merkle tree, computing the authentication path for leaf_idx, - * and the resulting root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) - * - * This expects tree_addrx8 to be initialized to 8 parallel addr structures for - * the Merkle tree nodes - * - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - * - * This works by using the standard Merkle tree building algorithm, except - * that each 'node' tracked is actually 8 consecutive nodes in the real tree. - * When we combine two logical nodes ABCDEFGH and STUVWXYZ, we perform the H - * operation on adjacent real nodes, forming the parent logical node - * (AB)(CD)(EF)(GH)(ST)(UV)(WX)(YZ) - * - * When we get to the top three levels of the real tree (where there is only - * one logical node), we continue this operation three more times; the right - * most real node will by the actual root (and the other 7 nodes will be - * garbage). We follow the same thashx8 logic so that the 'extract - * authentication path components' part of the loop is still executed (and - * to simplify the code somewhat) - * - * This currently assumes tree_height >= 3; I suspect that doing an adjusting - * idx, addr_idx on the gen_leafx8 call if tree_height < 3 would fix it; since - * we don't actually use such short trees, I haven't bothered - */ -void treehashx8(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, - uint32_t tree_height, - void (*gen_leafx8)( - unsigned char * /* Where to write the leaves */, - const spx_ctx *, - uint32_t idx, void *info), - uint32_t tree_addrx8[8 * 8], - void *info) { - /* This is where we keep the intermediate nodes */ - PQCLEAN_VLA(unsigned char, stackx8, tree_height * 8 * SPX_N); - uint32_t left_adj = 0, prev_left_adj = 0; /* When we're doing the top 3 */ - /* levels, the left-most part of the tree isn't at the beginning */ - /* of current[]. These give the offset of the actual start */ - - uint32_t idx; - uint32_t max_idx = ((uint32_t)1 << (tree_height - 3)) - 1; - for (idx = 0;; idx++) { - unsigned char current[8 * SPX_N]; /* Current logical node */ - gen_leafx8( current, ctx, 8 * idx + idx_offset, - info ); - - /* Now combine the freshly generated right node with previously */ - /* generated left ones */ - uint32_t internal_idx_offset = idx_offset; - uint32_t internal_idx = idx; - uint32_t internal_leaf = leaf_idx; - uint32_t h; /* The height we are in the Merkle tree */ - for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { - - /* Special processing if we're at the top of the tree */ - if (h >= tree_height - 3) { - if (h == tree_height) { - /* We hit the root; return it */ - memcpy( root, ¤t[7 * SPX_N], SPX_N ); - return; - } - /* The tree indexing logic is a bit off in this case */ - /* Adjust it so that the left-most node of the part of */ - /* the tree that we're processing has index 0 */ - prev_left_adj = left_adj; - left_adj = (uint32_t)(8 - (1 << (tree_height - h - 1))); - } - - /* Check if we hit the top of the tree */ - if (h == tree_height) { - /* We hit the root; return it */ - memcpy( root, ¤t[7 * SPX_N], SPX_N ); - return; - } - - /* - * Check if one of the nodes we have is a part of the - * authentication path; if it is, write it out - */ - if ((((internal_idx << 3) ^ internal_leaf) & ~0x7U) == 0) { - memcpy( &auth_path[ h * SPX_N ], - ¤t[(((internal_leaf & 7) ^ 1) + prev_left_adj) * SPX_N], - SPX_N ); - } - - /* - * Check if we're at a left child; if so, stop going up the stack - * Exception: if we've reached the end of the tree, keep on going - * (so we combine the last 8 nodes into the one root node in three - * more iterations) - */ - if ((internal_idx & 1) == 0 && idx < max_idx) { - break; - } - - /* Ok, we're at a right node (or doing the top 3 levels) */ - /* Now combine the left and right logical nodes together */ - - /* Set the address of the node we're creating. */ - uint32_t j; - internal_idx_offset >>= 1; - for (j = 0; j < 8; j++) { - set_tree_height(tree_addrx8 + j * 8, h + 1); - set_tree_index(tree_addrx8 + j * 8, - (8 / 2) * (internal_idx & ~1U) + j - left_adj + internal_idx_offset ); - } - unsigned char *left = &stackx8[h * 8 * SPX_N]; - thashx8( ¤t[0 * SPX_N], - ¤t[1 * SPX_N], - ¤t[2 * SPX_N], - ¤t[3 * SPX_N], - ¤t[4 * SPX_N], - ¤t[5 * SPX_N], - ¤t[6 * SPX_N], - ¤t[7 * SPX_N], - &left [0 * SPX_N], - &left [2 * SPX_N], - &left [4 * SPX_N], - &left [6 * SPX_N], - ¤t[0 * SPX_N], - ¤t[2 * SPX_N], - ¤t[4 * SPX_N], - ¤t[6 * SPX_N], - 2, ctx, tree_addrx8); - } - - /* We've hit a left child; save the current for when we get the */ - /* corresponding right right */ - memcpy( &stackx8[h * 8 * SPX_N], current, 8 * SPX_N); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/utilsx8.h b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/utilsx8.h deleted file mode 100644 index 806d1e85be..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/utilsx8.h +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef SPX_UTILSX8_H -#define SPX_UTILSX8_H - -#include - -#include "params.h" - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - * - * This implementation uses AVX to compute internal nodes 8 at a time (in - * parallel) - */ -#define treehashx8 SPX_NAMESPACE(treehashx8) -void treehashx8(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leafx8)( - unsigned char * /* Where to write the leaves */, - const spx_ctx * /* ctx */, - uint32_t addr_idx, void *info), - uint32_t tree_addrx8[8 * 8], void *info); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/wots.c b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/wots.c deleted file mode 100644 index 689baf4db9..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/wots.c +++ /dev/null @@ -1,291 +0,0 @@ -#include -#include - -#include "wots.h" - -#include "address.h" -#include "hash.h" -#include "hashx8.h" -#include "params.h" -#include "thash.h" -#include "thashx8.h" -#include "utils.h" -#include "utilsx8.h" -#include "wotsx8.h" - -// TODO clarify address expectations, and make them more uniform. -// TODO i.e. do we expect types to be set already? -// TODO and do we expect modifications or copies? - -/** - * Computes up the chains - */ -static void gen_chains( - unsigned char *out, - const unsigned char *in, - unsigned int start[SPX_WOTS_LEN], - const unsigned int steps[SPX_WOTS_LEN], - const spx_ctx *ctx, - uint32_t addr[8]) { - uint32_t i, j, k, idx, watching; - int done; - unsigned char empty[SPX_N]; - unsigned char *bufs[8]; - uint32_t addrs[8 * 8]; - - int l; - uint16_t counts[SPX_WOTS_W] = { 0 }; - uint16_t idxs[SPX_WOTS_LEN]; - uint16_t total, newTotal; - - /* set addrs = {addr, addr, ..., addr} */ - for (j = 0; j < 8; j++) { - memcpy(addrs + j * 8, addr, sizeof(uint32_t) * 8); - } - - /* Initialize out with the value at position 'start'. */ - memcpy(out, in, SPX_WOTS_LEN * SPX_N); - - /* Sort the chains in reverse order by steps using counting sort. */ - for (i = 0; i < SPX_WOTS_LEN; i++) { - counts[steps[i]]++; - } - total = 0; - for (l = SPX_WOTS_W - 1; l >= 0; l--) { - newTotal = counts[l] + total; - counts[l] = total; - total = newTotal; - } - for (i = 0; i < SPX_WOTS_LEN; i++) { - idxs[counts[steps[i]]] = (uint16_t)i; - counts[steps[i]]++; - } - - /* We got our work cut out for us: do it! */ - for (i = 0; i < SPX_WOTS_LEN; i += 8) { - for (j = 0; j < 8 && i + j < SPX_WOTS_LEN; j++) { - idx = idxs[i + j]; - set_chain_addr(addrs + j * 8, idx); - bufs[j] = out + SPX_N * idx; - } - - /* As the chains are sorted in reverse order, we know that the first - * chain is the longest and the last one is the shortest. We keep - * an eye on whether the last chain is done and then on the one before, - * et cetera. */ - watching = 7; - done = 0; - while (i + watching >= SPX_WOTS_LEN) { - bufs[watching] = &empty[0]; - watching--; - } - - for (k = 0;; k++) { - while (k == steps[idxs[i + watching]]) { - bufs[watching] = &empty[0]; - if (watching == 0) { - done = 1; - break; - } - watching--; - } - if (done) { - break; - } - for (j = 0; j < watching + 1; j++) { - set_hash_addr(addrs + j * 8, k + start[idxs[i + j]]); - } - - thashx8(bufs[0], bufs[1], bufs[2], bufs[3], - bufs[4], bufs[5], bufs[6], bufs[7], - bufs[0], bufs[1], bufs[2], bufs[3], - bufs[4], bufs[5], bufs[6], bufs[7], 1, ctx, addrs); - } - } -} - -/** - * base_w algorithm as described in draft. - * Interprets an array of bytes as integers in base w. - * This only works when log_w is a divisor of 8. - */ -static void base_w(unsigned int *output, const int out_len, - const unsigned char *input) { - int in = 0; - int out = 0; - unsigned char total = 0; - int bits = 0; - int consumed; - - for (consumed = 0; consumed < out_len; consumed++) { - if (bits == 0) { - total = input[in]; - in++; - bits += 8; - } - bits -= SPX_WOTS_LOGW; - output[out] = (total >> bits) & (SPX_WOTS_W - 1); - out++; - } -} - -/* Computes the WOTS+ checksum over a message (in base_w). */ -static void wots_checksum(unsigned int *csum_base_w, - const unsigned int *msg_base_w) { - unsigned int csum = 0; - unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; - unsigned int i; - - /* Compute checksum. */ - for (i = 0; i < SPX_WOTS_LEN1; i++) { - csum += SPX_WOTS_W - 1 - msg_base_w[i]; - } - - /* Convert checksum to base_w. */ - /* Make sure expected empty zero bits are the least significant bits. */ - csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); - ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); - base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); -} - -/* Takes a message and derives the matching chain lengths. */ -void chain_lengths(unsigned int *lengths, const unsigned char *msg) { - base_w(lengths, SPX_WOTS_LEN1, msg); - wots_checksum(lengths + SPX_WOTS_LEN1, lengths); -} - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const spx_ctx *ctx, uint32_t addr[8]) { - unsigned int steps[SPX_WOTS_LEN]; - unsigned int start[SPX_WOTS_LEN]; - uint32_t i; - - chain_lengths(start, msg); - - for (i = 0; i < SPX_WOTS_LEN; i++) { - steps[i] = SPX_WOTS_W - 1 - start[i]; - } - - gen_chains(pk, sig, start, steps, ctx, addr); -} - -/* - * This generates 8 sequential WOTS public keys - * It also generates the WOTS signature if leaf_info indicates - * that we're signing with one of these WOTS keys - */ -void wots_gen_leafx8(unsigned char *dest, - const spx_ctx *ctx, - uint32_t leaf_idx, void *v_info) { - struct leaf_info_x8 *info = v_info; - uint32_t *leaf_addr = info->leaf_addr; - uint32_t *pk_addr = info->pk_addr; - unsigned int i, j, k; - unsigned char pk_buffer[ 8 * SPX_WOTS_BYTES ]; - unsigned wots_offset = SPX_WOTS_BYTES; - unsigned char *buffer; - uint32_t wots_k_mask; - unsigned wots_sign_index; - - if (((leaf_idx ^ info->wots_sign_leaf) & ~7U) == 0) { - /* We're traversing the leaf that's signing; generate the WOTS */ - /* signature */ - wots_k_mask = 0; - wots_sign_index = info->wots_sign_leaf & 7; /* Which of of the 8 */ - /* slots do the signatures come from */ - } else { - /* Nope, we're just generating pk's; turn off the signature logic */ - wots_k_mask = ~0U; - wots_sign_index = 0; - } - - for (j = 0; j < 8; j++) { - set_keypair_addr( leaf_addr + j * 8, leaf_idx + j ); - set_keypair_addr( pk_addr + j * 8, leaf_idx + j ); - } - - for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { - uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k */ - /* to the step if we're generating a signature, ~0 if we're not */ - - /* Start with the secret seed */ - for (j = 0; j < 8; j++) { - set_chain_addr(leaf_addr + j * 8, i); - set_hash_addr(leaf_addr + j * 8, 0); - set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTSPRF); - } - prf_addrx8(buffer + 0 * wots_offset, - buffer + 1 * wots_offset, - buffer + 2 * wots_offset, - buffer + 3 * wots_offset, - buffer + 4 * wots_offset, - buffer + 5 * wots_offset, - buffer + 6 * wots_offset, - buffer + 7 * wots_offset, - ctx, leaf_addr); - - for (j = 0; j < 8; j++) { - set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTS); - } - - /* Iterate down the WOTS chain */ - for (k = 0;; k++) { - /* Check if one of the values we have needs to be saved as a */ - /* part of the WOTS signature */ - if (k == wots_k) { - memcpy( info->wots_sig + i * SPX_N, - buffer + wots_sign_index * wots_offset, SPX_N ); - } - - /* Check if we hit the top of the chain */ - if (k == SPX_WOTS_W - 1) { - break; - } - - /* Iterate one step on all 8 chains */ - for (j = 0; j < 8; j++) { - set_hash_addr(leaf_addr + j * 8, k); - } - thashx8(buffer + 0 * wots_offset, - buffer + 1 * wots_offset, - buffer + 2 * wots_offset, - buffer + 3 * wots_offset, - buffer + 4 * wots_offset, - buffer + 5 * wots_offset, - buffer + 6 * wots_offset, - buffer + 7 * wots_offset, - buffer + 0 * wots_offset, - buffer + 1 * wots_offset, - buffer + 2 * wots_offset, - buffer + 3 * wots_offset, - buffer + 4 * wots_offset, - buffer + 5 * wots_offset, - buffer + 6 * wots_offset, - buffer + 7 * wots_offset, 1, ctx, leaf_addr); - } - } - - /* Do the final thash to generate the public keys */ - thashx8(dest + 0 * SPX_N, - dest + 1 * SPX_N, - dest + 2 * SPX_N, - dest + 3 * SPX_N, - dest + 4 * SPX_N, - dest + 5 * SPX_N, - dest + 6 * SPX_N, - dest + 7 * SPX_N, - pk_buffer + 0 * wots_offset, - pk_buffer + 1 * wots_offset, - pk_buffer + 2 * wots_offset, - pk_buffer + 3 * wots_offset, - pk_buffer + 4 * wots_offset, - pk_buffer + 5 * wots_offset, - pk_buffer + 6 * wots_offset, - pk_buffer + 7 * wots_offset, SPX_WOTS_LEN, ctx, pk_addr); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/wots.h b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/wots.h deleted file mode 100644 index 4e7692eeef..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/wots.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef SPX_WOTS_H -#define SPX_WOTS_H - -#include - -#include "context.h" -#include "params.h" - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) -void wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const spx_ctx *ctx, uint32_t addr[8]); - -/* - * Compute the chain lengths needed for a given message hash - */ -#define chain_lengths SPX_NAMESPACE(chain_lengths) -void chain_lengths(unsigned int *lengths, const unsigned char *msg); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/wotsx8.h b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/wotsx8.h deleted file mode 100644 index 10866efb35..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_avx2/wotsx8.h +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef WOTSX8_H_ -#define WOTSX8_H_ - -#include - -#include "context.h" -#include "params.h" - -/* - * This is here to provide an interface to the internal wots_gen_leafx8 - * routine. While this routine is not referenced in the package outside of - * wots.c, it is called from the stand-alone benchmark code to characterize - * the performance - */ -struct leaf_info_x8 { - unsigned char *wots_sig; - uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ - uint32_t *wots_steps; - uint32_t leaf_addr[8 * 8]; - uint32_t pk_addr[8 * 8]; -}; - -/* Macro to set the leaf_info to something 'benign', that is, it would */ -/* run with the same time as it does during the real signing process */ -/* Used only by the benchmark code */ -#define INITIALIZE_LEAF_INFO_X8(info, addr, step_buffer) { \ - (info).wots_sig = 0; \ - (info).wots_sign_leaf = ~0; \ - (info).wots_steps = step_buffer; \ - int i; \ - for (i=0; i<8; i++) { \ - memcpy( &(info).leaf_addr[8*i], addr, 32 ); \ - memcpy( &(info).pk_addr[8*i], addr, 32 ); \ - } \ - } - -#define wots_gen_leafx8 SPX_NAMESPACE(wots_gen_leafx8) -void wots_gen_leafx8(unsigned char *dest, - const spx_ctx *ctx, - uint32_t leaf_idx, void *v_info); - -#endif /* WOTSX8_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/LICENSE b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/LICENSE deleted file mode 100644 index 670154e353..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/LICENSE +++ /dev/null @@ -1,116 +0,0 @@ -CC0 1.0 Universal - -Statement of Purpose - -The laws of most jurisdictions throughout the world automatically confer -exclusive Copyright and Related Rights (defined below) upon the creator and -subsequent owner(s) (each and all, an "owner") of an original work of -authorship and/or a database (each, a "Work"). - -Certain owners wish to permanently relinquish those rights to a Work for the -purpose of contributing to a commons of creative, cultural and scientific -works ("Commons") that the public can reliably and without fear of later -claims of infringement build upon, modify, incorporate in other works, reuse -and redistribute as freely as possible in any form whatsoever and for any -purposes, including without limitation commercial purposes. These owners may -contribute to the Commons to promote the ideal of a free culture and the -further production of creative, cultural and scientific works, or to gain -reputation or greater distribution for their Work in part through the use and -efforts of others. - -For these and/or other purposes and motivations, and without any expectation -of additional consideration or compensation, the person associating CC0 with a -Work (the "Affirmer"), to the extent that he or she is an owner of Copyright -and Related Rights in the Work, voluntarily elects to apply CC0 to the Work -and publicly distribute the Work under its terms, with knowledge of his or her -Copyright and Related Rights in the Work and the meaning and intended legal -effect of CC0 on those rights. - -1. Copyright and Related Rights. A Work made available under CC0 may be -protected by copyright and related or neighboring rights ("Copyright and -Related Rights"). Copyright and Related Rights include, but are not limited -to, the following: - - i. the right to reproduce, adapt, distribute, perform, display, communicate, - and translate a Work; - - ii. moral rights retained by the original author(s) and/or performer(s); - - iii. publicity and privacy rights pertaining to a person's image or likeness - depicted in a Work; - - iv. rights protecting against unfair competition in regards to a Work, - subject to the limitations in paragraph 4(a), below; - - v. rights protecting the extraction, dissemination, use and reuse of data in - a Work; - - vi. database rights (such as those arising under Directive 96/9/EC of the - European Parliament and of the Council of 11 March 1996 on the legal - protection of databases, and under any national implementation thereof, - including any amended or successor version of such directive); and - - vii. other similar, equivalent or corresponding rights throughout the world - based on applicable law or treaty, and any national implementations thereof. - -2. Waiver. To the greatest extent permitted by, but not in contravention of, -applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and -unconditionally waives, abandons, and surrenders all of Affirmer's Copyright -and Related Rights and associated claims and causes of action, whether now -known or unknown (including existing as well as future claims and causes of -action), in the Work (i) in all territories worldwide, (ii) for the maximum -duration provided by applicable law or treaty (including future time -extensions), (iii) in any current or future medium and for any number of -copies, and (iv) for any purpose whatsoever, including without limitation -commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes -the Waiver for the benefit of each member of the public at large and to the -detriment of Affirmer's heirs and successors, fully intending that such Waiver -shall not be subject to revocation, rescission, cancellation, termination, or -any other legal or equitable action to disrupt the quiet enjoyment of the Work -by the public as contemplated by Affirmer's express Statement of Purpose. - -3. Public License Fallback. Should any part of the Waiver for any reason be -judged legally invalid or ineffective under applicable law, then the Waiver -shall be preserved to the maximum extent permitted taking into account -Affirmer's express Statement of Purpose. In addition, to the extent the Waiver -is so judged Affirmer hereby grants to each affected person a royalty-free, -non transferable, non sublicensable, non exclusive, irrevocable and -unconditional license to exercise Affirmer's Copyright and Related Rights in -the Work (i) in all territories worldwide, (ii) for the maximum duration -provided by applicable law or treaty (including future time extensions), (iii) -in any current or future medium and for any number of copies, and (iv) for any -purpose whatsoever, including without limitation commercial, advertising or -promotional purposes (the "License"). The License shall be deemed effective as -of the date CC0 was applied by Affirmer to the Work. Should any part of the -License for any reason be judged legally invalid or ineffective under -applicable law, such partial invalidity or ineffectiveness shall not -invalidate the remainder of the License, and in such case Affirmer hereby -affirms that he or she will not (i) exercise any of his or her remaining -Copyright and Related Rights in the Work or (ii) assert any associated claims -and causes of action with respect to the Work, in either case contrary to -Affirmer's express Statement of Purpose. - -4. Limitations and Disclaimers. - - a. No trademark or patent rights held by Affirmer are waived, abandoned, - surrendered, licensed or otherwise affected by this document. - - b. Affirmer offers the Work as-is and makes no representations or warranties - of any kind concerning the Work, express, implied, statutory or otherwise, - including without limitation warranties of title, merchantability, fitness - for a particular purpose, non infringement, or the absence of latent or - other defects, accuracy, or the present or absence of errors, whether or not - discoverable, all to the greatest extent permissible under applicable law. - - c. Affirmer disclaims responsibility for clearing rights of other persons - that may apply to the Work or any use thereof, including without limitation - any person's Copyright and Related Rights in the Work. Further, Affirmer - disclaims responsibility for obtaining any necessary consents, permissions - or other rights required for any use of the Work. - - d. Affirmer understands and acknowledges that Creative Commons is not a - party to this document and has no duty or obligation with respect to this - CC0 or use of the Work. - -For more information, please see - diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/address.c b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/address.c deleted file mode 100644 index d49d9f3b6b..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/address.c +++ /dev/null @@ -1,95 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "utils.h" - -/* - * Specify which level of Merkle tree (the "layer") we're working on - */ -void set_layer_addr(uint32_t addr[8], uint32_t layer) { - ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; -} - -/* - * Specify which Merkle tree within the level (the "tree address") we're working on - */ -void set_tree_addr(uint32_t addr[8], uint64_t tree) { - ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); -} - -/* - * Specify the reason we'll use this address structure for, that is, what - * hash will we compute with it. This is used so that unrelated types of - * hashes don't accidentally get the same address structure. The type will be - * one of the SPX_ADDR_TYPE constants - */ -void set_type(uint32_t addr[8], uint32_t type) { - ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; -} - -/* - * Copy the layer and tree fields of the address structure. This is used - * when we're doing multiple types of hashes within the same Merkle tree - */ -void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { - memcpy( out, in, SPX_OFFSET_TREE + 8 ); -} - -/* These functions are used for OTS addresses. */ - -/* - * Specify which Merkle leaf we're working on; that is, which OTS keypair - * we're talking about. - */ -void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { - /* We have > 256 OTS at the bottom of the Merkle tree; to specify */ - /* which one, we'd need to express it in two bytes */ - ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR2] = (unsigned char)(keypair >> 8); - ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; -} - -/* - * Copy the layer, tree and keypair fields of the address structure. This is - * used when we're doing multiple things within the same OTS keypair - */ -void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { - memcpy( out, in, SPX_OFFSET_TREE + 8 ); - ((unsigned char *)out)[SPX_OFFSET_KP_ADDR2] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR2]; - ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; -} - -/* - * Specify which Merkle chain within the OTS we're working with - * (the chain address) - */ -void set_chain_addr(uint32_t addr[8], uint32_t chain) { - ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; -} - -/* - * Specify where in the Merkle chain we are -* (the hash address) - */ -void set_hash_addr(uint32_t addr[8], uint32_t hash) { - ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; -} - -/* These functions are used for all hash tree addresses (including FORS). */ - -/* - * Specify the height of the node in the Merkle/FORS tree we are in - * (the tree height) - */ -void set_tree_height(uint32_t addr[8], uint32_t tree_height) { - ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; -} - -/* - * Specify the distance from the left edge of the node in the Merkle/FORS tree - * (the tree index) - */ -void set_tree_index(uint32_t addr[8], uint32_t tree_index) { - u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/address.h b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/address.h deleted file mode 100644 index 24a84eb40c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/address.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef SPX_ADDRESS_H -#define SPX_ADDRESS_H - -#include - -#include "params.h" - -/* The hash types that are passed to set_type */ -#define SPX_ADDR_TYPE_WOTS 0 -#define SPX_ADDR_TYPE_WOTSPK 1 -#define SPX_ADDR_TYPE_HASHTREE 2 -#define SPX_ADDR_TYPE_FORSTREE 3 -#define SPX_ADDR_TYPE_FORSPK 4 -#define SPX_ADDR_TYPE_WOTSPRF 5 -#define SPX_ADDR_TYPE_FORSPRF 6 - -#define set_layer_addr SPX_NAMESPACE(set_layer_addr) -void set_layer_addr(uint32_t addr[8], uint32_t layer); - -#define set_tree_addr SPX_NAMESPACE(set_tree_addr) -void set_tree_addr(uint32_t addr[8], uint64_t tree); - -#define set_type SPX_NAMESPACE(set_type) -void set_type(uint32_t addr[8], uint32_t type); - -/* Copies the layer and tree part of one address into the other */ -#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) -void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for WOTS and FORS addresses. */ - -#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) -void set_keypair_addr(uint32_t addr[8], uint32_t keypair); - -#define set_chain_addr SPX_NAMESPACE(set_chain_addr) -void set_chain_addr(uint32_t addr[8], uint32_t chain); - -#define set_hash_addr SPX_NAMESPACE(set_hash_addr) -void set_hash_addr(uint32_t addr[8], uint32_t hash); - -#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) -void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for all hash tree addresses (including FORS). */ - -#define set_tree_height SPX_NAMESPACE(set_tree_height) -void set_tree_height(uint32_t addr[8], uint32_t tree_height); - -#define set_tree_index SPX_NAMESPACE(set_tree_index) -void set_tree_index(uint32_t addr[8], uint32_t tree_index); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/api.h b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/api.h deleted file mode 100644 index e1bfec0651..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/api.h +++ /dev/null @@ -1,77 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA2192SROBUST_CLEAN_API_H -#define PQCLEAN_SPHINCSSHA2192SROBUST_CLEAN_API_H - -#include -#include - -#define PQCLEAN_SPHINCSSHA2192SROBUST_CLEAN_CRYPTO_ALGNAME "SPHINCS+-sha2-192s-robust" - -#define PQCLEAN_SPHINCSSHA2192SROBUST_CLEAN_CRYPTO_SECRETKEYBYTES 96 -#define PQCLEAN_SPHINCSSHA2192SROBUST_CLEAN_CRYPTO_PUBLICKEYBYTES 48 -#define PQCLEAN_SPHINCSSHA2192SROBUST_CLEAN_CRYPTO_BYTES 16224 - -#define PQCLEAN_SPHINCSSHA2192SROBUST_CLEAN_CRYPTO_SEEDBYTES 72 - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSSHA2192SROBUST_CLEAN_crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSSHA2192SROBUST_CLEAN_crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSSHA2192SROBUST_CLEAN_crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSSHA2192SROBUST_CLEAN_crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHA2192SROBUST_CLEAN_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHA2192SROBUST_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSSHA2192SROBUST_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSSHA2192SROBUST_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, - const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSSHA2192SROBUST_CLEAN_crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSSHA2192SROBUST_CLEAN_crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk); -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/context.h b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/context.h deleted file mode 100644 index 97e2e2469e..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/context.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef SPX_CONTEXT_H -#define SPX_CONTEXT_H - -#include -#include - -#include "params.h" -#include "sha2.h" - -typedef struct { - uint8_t pub_seed[SPX_N]; - uint8_t sk_seed[SPX_N]; - - // sha256 state that absorbed pub_seed - sha256ctx state_seeded; - - // sha512 state that absorbed pub_seed - sha512ctx state_seeded_512; - -} spx_ctx; - -#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) -void initialize_hash_function(spx_ctx *ctx); - -#define free_hash_function SPX_NAMESPACE(free_hash_function) -void free_hash_function(spx_ctx *ctx); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/context_sha2.c b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/context_sha2.c deleted file mode 100644 index 9ca9f4e7ac..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/context_sha2.c +++ /dev/null @@ -1,36 +0,0 @@ -#include "context.h" - -/** - * Absorb the constant pub_seed using one round of the compression function - * This initializes state_seeded and state_seeded_512, which can then be - * reused in thash - **/ -static void seed_state(spx_ctx *ctx) { - uint8_t block[SPX_SHA512_BLOCK_BYTES]; - size_t i; - - for (i = 0; i < SPX_N; ++i) { - block[i] = ctx->pub_seed[i]; - } - for (i = SPX_N; i < SPX_SHA512_BLOCK_BYTES; ++i) { - block[i] = 0; - } - /* block has been properly initialized for both SHA-256 and SHA-512 */ - - sha256_inc_init(&ctx->state_seeded); - sha256_inc_blocks(&ctx->state_seeded, block, 1); - sha512_inc_init(&ctx->state_seeded_512); - sha512_inc_blocks(&ctx->state_seeded_512, block, 1); -} - - -/* We initialize the state for the hash functions */ -void initialize_hash_function(spx_ctx *ctx) { - seed_state(ctx); -} - -/* Free the incremental hashing context for heap-based SHA2 APIs */ -void free_hash_function(spx_ctx *ctx) { - sha256_inc_ctx_release(&ctx->state_seeded); - sha512_inc_ctx_release(&ctx->state_seeded_512); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/fors.c b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/fors.c deleted file mode 100644 index 96ca72e986..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/fors.c +++ /dev/null @@ -1,156 +0,0 @@ -#include -#include -#include - -#include "fors.h" - -#include "address.h" -#include "hash.h" -#include "thash.h" -#include "utils.h" -#include "utilsx1.h" - -static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, - uint32_t fors_leaf_addr[8]) { - prf_addr(sk, ctx, fors_leaf_addr); -} - -static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, - const spx_ctx *ctx, - uint32_t fors_leaf_addr[8]) { - thash(leaf, sk, 1, ctx, fors_leaf_addr); -} - -struct fors_gen_leaf_info { - uint32_t leaf_addrx[8]; -}; - -static void fors_gen_leafx1(unsigned char *leaf, - const spx_ctx *ctx, - uint32_t addr_idx, void *info) { - struct fors_gen_leaf_info *fors_info = info; - uint32_t *fors_leaf_addr = fors_info->leaf_addrx; - - /* Only set the parts that the caller doesn't set */ - set_tree_index(fors_leaf_addr, addr_idx); - set_type(fors_leaf_addr, SPX_ADDR_TYPE_FORSPRF); - fors_gen_sk(leaf, ctx, fors_leaf_addr); - - set_type(fors_leaf_addr, SPX_ADDR_TYPE_FORSTREE); - fors_sk_to_leaf(leaf, leaf, - ctx, fors_leaf_addr); -} - -/** - * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - * Assumes indices has space for SPX_FORS_TREES integers. - */ -static void message_to_indices(uint32_t *indices, const unsigned char *m) { - unsigned int i, j; - unsigned int offset = 0; - - for (i = 0; i < SPX_FORS_TREES; i++) { - indices[i] = 0; - for (j = 0; j < SPX_FORS_HEIGHT; j++) { - indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); - offset++; - } - } -} - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -void fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]) { - uint32_t indices[SPX_FORS_TREES]; - unsigned char roots[SPX_FORS_TREES * SPX_N]; - uint32_t fors_tree_addr[8] = {0}; - struct fors_gen_leaf_info fors_info = {0}; - uint32_t *fors_leaf_addr = fors_info.leaf_addrx; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - copy_keypair_addr(fors_tree_addr, fors_addr); - copy_keypair_addr(fors_leaf_addr, fors_addr); - - copy_keypair_addr(fors_pk_addr, fors_addr); - set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < SPX_FORS_TREES; i++) { - idx_offset = i * (1 << SPX_FORS_HEIGHT); - - set_tree_height(fors_tree_addr, 0); - set_tree_index(fors_tree_addr, indices[i] + idx_offset); - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); - - /* Include the secret key part that produces the selected leaf node. */ - fors_gen_sk(sig, ctx, fors_tree_addr); - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); - sig += SPX_N; - - /* Compute the authentication path for this leaf node. */ - treehashx1(roots + i * SPX_N, sig, ctx, - indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx1, - fors_tree_addr, &fors_info); - - sig += SPX_N * SPX_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); -} - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -void fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]) { - uint32_t indices[SPX_FORS_TREES]; - unsigned char roots[SPX_FORS_TREES * SPX_N]; - unsigned char leaf[SPX_N]; - uint32_t fors_tree_addr[8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - copy_keypair_addr(fors_tree_addr, fors_addr); - copy_keypair_addr(fors_pk_addr, fors_addr); - - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); - set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < SPX_FORS_TREES; i++) { - idx_offset = i * (1 << SPX_FORS_HEIGHT); - - set_tree_height(fors_tree_addr, 0); - set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Derive the leaf from the included secret key part. */ - fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); - sig += SPX_N; - - /* Derive the corresponding root node of this tree. */ - compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, - sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); - sig += SPX_N * SPX_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/fors.h b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/fors.h deleted file mode 100644 index 509140a178..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/fors.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef SPX_FORS_H -#define SPX_FORS_H - -#include - -#include "context.h" -#include "params.h" - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -#define fors_sign SPX_NAMESPACE(fors_sign) -void fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]); - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) -void fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/hash.h b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/hash.h deleted file mode 100644 index ffe815f45d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/hash.h +++ /dev/null @@ -1,37 +0,0 @@ -#ifndef SPX_HASH_H -#define SPX_HASH_H - -#include -#include - -#include "context.h" -#include "params.h" - -#define prf_addr SPX_NAMESPACE(prf_addr) -void prf_addr(unsigned char *out, const spx_ctx *ctx, - const uint32_t addr[8]); - -#define gen_message_random SPX_NAMESPACE(gen_message_random) -void gen_message_random(unsigned char *R, const unsigned char *sk_prf, - const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx); - -#define hash_message SPX_NAMESPACE(hash_message) -void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx); - - -# define SPX_SHA256_ADDR_BYTES 22 - -# define mgf1_256 SPX_NAMESPACE(mgf1_256) -void mgf1_256(unsigned char *out, unsigned long outlen, - const unsigned char *in, unsigned long inlen); - -# define mgf1_512 SPX_NAMESPACE(mgf1_512) -void mgf1_512(unsigned char *out, unsigned long outlen, - const unsigned char *in, unsigned long inlen); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/hash_sha2.c b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/hash_sha2.c deleted file mode 100644 index 3d0085c8c1..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/hash_sha2.c +++ /dev/null @@ -1,219 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "sha2.h" -#include "utils.h" - - - -#define SPX_SHAX_OUTPUT_BYTES SPX_SHA512_OUTPUT_BYTES -#define SPX_SHAX_BLOCK_BYTES SPX_SHA512_BLOCK_BYTES -#define shaX_inc_init sha512_inc_init -#define shaX_inc_blocks sha512_inc_blocks -#define shaX_inc_finalize sha512_inc_finalize -#define shaX sha512 -#define mgf1_X mgf1_512 -#define shaXstate sha512ctx - -/** - * mgf1 function based on the SHA-256 hash function - * Note that inlen should be sufficiently small that it still allows for - * an array to be allocated on the stack. Typically 'in' is merely a seed. - * Outputs outlen number of bytes - */ -void mgf1_256(unsigned char *out, unsigned long outlen, - const unsigned char *in, unsigned long inlen) { - PQCLEAN_VLA(uint8_t, inbuf, inlen + 4); - unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES]; - uint32_t i; - - memcpy(inbuf, in, inlen); - - /* While we can fit in at least another full block of SHA256 output.. */ - for (i = 0; (i + 1)*SPX_SHA256_OUTPUT_BYTES <= outlen; i++) { - u32_to_bytes(inbuf + inlen, i); - sha256(out, inbuf, inlen + 4); - out += SPX_SHA256_OUTPUT_BYTES; - } - /* Until we cannot anymore, and we fill the remainder. */ - if (outlen > i * SPX_SHA256_OUTPUT_BYTES) { - u32_to_bytes(inbuf + inlen, i); - sha256(outbuf, inbuf, inlen + 4); - memcpy(out, outbuf, outlen - i * SPX_SHA256_OUTPUT_BYTES); - } -} - -/* - * mgf1 function based on the SHA-512 hash function - */ -void mgf1_512(unsigned char *out, unsigned long outlen, - const unsigned char *in, unsigned long inlen) { - PQCLEAN_VLA(uint8_t, inbuf, inlen + 4); - unsigned char outbuf[SPX_SHA512_OUTPUT_BYTES]; - uint32_t i; - - memcpy(inbuf, in, inlen); - - /* While we can fit in at least another full block of SHA512 output.. */ - for (i = 0; (i + 1)*SPX_SHA512_OUTPUT_BYTES <= outlen; i++) { - u32_to_bytes(inbuf + inlen, i); - sha512(out, inbuf, inlen + 4); - out += SPX_SHA512_OUTPUT_BYTES; - } - /* Until we cannot anymore, and we fill the remainder. */ - if (outlen > i * SPX_SHA512_OUTPUT_BYTES) { - u32_to_bytes(inbuf + inlen, i); - sha512(outbuf, inbuf, inlen + 4); - memcpy(out, outbuf, outlen - i * SPX_SHA512_OUTPUT_BYTES); - } -} - -/* - * Computes PRF(pk_seed, sk_seed, addr). - */ -void prf_addr(unsigned char *out, const spx_ctx *ctx, - const uint32_t addr[8]) { - sha256ctx sha2_state; - unsigned char buf[SPX_SHA256_ADDR_BYTES + SPX_N]; - unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES]; - - /* Retrieve precomputed state containing pub_seed */ - sha256_inc_ctx_clone(&sha2_state, &ctx->state_seeded); - - /* Remainder: ADDR^c ‖ SK.seed */ - memcpy(buf, addr, SPX_SHA256_ADDR_BYTES); - memcpy(buf + SPX_SHA256_ADDR_BYTES, ctx->sk_seed, SPX_N); - - sha256_inc_finalize(outbuf, &sha2_state, buf, SPX_SHA256_ADDR_BYTES + SPX_N); - - memcpy(out, outbuf, SPX_N); -} - -/** - * Computes the message-dependent randomness R, using a secret seed as a key - * for HMAC, and an optional randomization value prefixed to the message. - * This requires m to have at least SPX_SHAX_BLOCK_BYTES + SPX_N space - * available in front of the pointer, i.e. before the message to use for the - * prefix. This is necessary to prevent having to move the message around (and - * allocate memory for it). - */ -void gen_message_random(unsigned char *R, const unsigned char *sk_prf, - const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx) { - (void)ctx; - - unsigned char buf[SPX_SHAX_BLOCK_BYTES + SPX_SHAX_OUTPUT_BYTES]; - shaXstate state; - int i; - - - /* This implements HMAC-SHA */ - for (i = 0; i < SPX_N; i++) { - buf[i] = 0x36 ^ sk_prf[i]; - } - memset(buf + SPX_N, 0x36, SPX_SHAX_BLOCK_BYTES - SPX_N); - - shaX_inc_init(&state); - shaX_inc_blocks(&state, buf, 1); - - memcpy(buf, optrand, SPX_N); - - /* If optrand + message cannot fill up an entire block */ - if (SPX_N + mlen < SPX_SHAX_BLOCK_BYTES) { - memcpy(buf + SPX_N, m, mlen); - shaX_inc_finalize(buf + SPX_SHAX_BLOCK_BYTES, &state, - buf, mlen + SPX_N); - } - /* Otherwise first fill a block, so that finalize only uses the message */ - else { - memcpy(buf + SPX_N, m, SPX_SHAX_BLOCK_BYTES - SPX_N); - shaX_inc_blocks(&state, buf, 1); - - m += SPX_SHAX_BLOCK_BYTES - SPX_N; - mlen -= SPX_SHAX_BLOCK_BYTES - SPX_N; - shaX_inc_finalize(buf + SPX_SHAX_BLOCK_BYTES, &state, m, mlen); - } - - for (i = 0; i < SPX_N; i++) { - buf[i] = 0x5c ^ sk_prf[i]; - } - memset(buf + SPX_N, 0x5c, SPX_SHAX_BLOCK_BYTES - SPX_N); - - shaX(buf, buf, SPX_SHAX_BLOCK_BYTES + SPX_SHAX_OUTPUT_BYTES); - memcpy(R, buf, SPX_N); -} - -/** - * Computes the message hash using R, the public key, and the message. - * Outputs the message digest and the index of the leaf. The index is split in - * the tree index and the leaf index, for convenient copying to an address. - */ -void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx) { - (void)ctx; -#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) -#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) -#define SPX_LEAF_BITS SPX_TREE_HEIGHT -#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) -#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) - - unsigned char seed[2 * SPX_N + SPX_SHAX_OUTPUT_BYTES]; - - /* Round to nearest multiple of SPX_SHAX_BLOCK_BYTES */ -#define SPX_INBLOCKS (((SPX_N + SPX_PK_BYTES + SPX_SHAX_BLOCK_BYTES - 1) & \ - -SPX_SHAX_BLOCK_BYTES) / SPX_SHAX_BLOCK_BYTES) - unsigned char inbuf[SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES]; - - unsigned char buf[SPX_DGST_BYTES]; - unsigned char *bufp = buf; - shaXstate state; - - shaX_inc_init(&state); - - // seed: SHA-X(R ‖ PK.seed ‖ PK.root ‖ M) - memcpy(inbuf, R, SPX_N); - memcpy(inbuf + SPX_N, pk, SPX_PK_BYTES); - - /* If R + pk + message cannot fill up an entire block */ - if (SPX_N + SPX_PK_BYTES + mlen < SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES) { - memcpy(inbuf + SPX_N + SPX_PK_BYTES, m, mlen); - shaX_inc_finalize(seed + 2 * SPX_N, &state, inbuf, SPX_N + SPX_PK_BYTES + mlen); - } - /* Otherwise first fill a block, so that finalize only uses the message */ - else { - memcpy(inbuf + SPX_N + SPX_PK_BYTES, m, - SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES - SPX_N - SPX_PK_BYTES); - shaX_inc_blocks(&state, inbuf, SPX_INBLOCKS); - - m += SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES - SPX_N - SPX_PK_BYTES; - mlen -= SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES - SPX_N - SPX_PK_BYTES; - shaX_inc_finalize(seed + 2 * SPX_N, &state, m, (size_t)mlen); - } - - // H_msg: MGF1-SHA-X(R ‖ PK.seed ‖ seed) - memcpy(seed, R, SPX_N); - memcpy(seed + SPX_N, pk, SPX_N); - - /* By doing this in two steps, we prevent hashing the message twice; - otherwise each iteration in MGF1 would hash the message again. */ - mgf1_X(bufp, SPX_DGST_BYTES, seed, 2 * SPX_N + SPX_SHAX_OUTPUT_BYTES); - - memcpy(digest, bufp, SPX_FORS_MSG_BYTES); - bufp += SPX_FORS_MSG_BYTES; - - - *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); - *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); - bufp += SPX_TREE_BYTES; - - *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); - *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); -} - - diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/merkle.c b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/merkle.c deleted file mode 100644 index 0c1479fd93..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/merkle.c +++ /dev/null @@ -1,59 +0,0 @@ -#include -#include - -#include "address.h" -#include "merkle.h" -#include "params.h" -#include "utils.h" -#include "utilsx1.h" -#include "wots.h" -#include "wotsx1.h" - -/* - * This generates a Merkle signature (WOTS signature followed by the Merkle - * authentication path). This is in this file because most of the complexity - * is involved with the WOTS signature; the Merkle authentication path logic - * is mostly hidden in treehashx4 - */ -void merkle_sign(uint8_t *sig, unsigned char *root, - const spx_ctx *ctx, - uint32_t wots_addr[8], uint32_t tree_addr[8], - uint32_t idx_leaf) { - unsigned char *auth_path = sig + SPX_WOTS_BYTES; - struct leaf_info_x1 info = { 0 }; - unsigned steps[ SPX_WOTS_LEN ]; - - info.wots_sig = sig; - chain_lengths(steps, root); - info.wots_steps = steps; - - set_type(&tree_addr[0], SPX_ADDR_TYPE_HASHTREE); - set_type(&info.pk_addr[0], SPX_ADDR_TYPE_WOTSPK); - copy_subtree_addr(&info.leaf_addr[0], wots_addr); - copy_subtree_addr(&info.pk_addr[0], wots_addr); - - info.wots_sign_leaf = idx_leaf; - - treehashx1(root, auth_path, ctx, - idx_leaf, 0, - SPX_TREE_HEIGHT, - wots_gen_leafx1, - tree_addr, &info); -} - -/* Compute root node of the top-most subtree. */ -void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { - /* We do not need the auth path in key generation, but it simplifies the - code to have just one treehash routine that computes both root and path - in one function. */ - unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; - uint32_t top_tree_addr[8] = {0}; - uint32_t wots_addr[8] = {0}; - - set_layer_addr(top_tree_addr, SPX_D - 1); - set_layer_addr(wots_addr, SPX_D - 1); - - merkle_sign(auth_path, root, ctx, - wots_addr, top_tree_addr, - (uint32_t)~0 /* ~0 means "don't bother generating an auth path */ ); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/merkle.h b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/merkle.h deleted file mode 100644 index 769cf2e970..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/merkle.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef MERKLE_H_ -#define MERKLE_H_ - -#include - -#include "context.h" -#include "params.h" - -/* Generate a Merkle signature (WOTS signature followed by the Merkle */ -/* authentication path) */ -#define merkle_sign SPX_NAMESPACE(merkle_sign) -void merkle_sign(uint8_t *sig, unsigned char *root, - const spx_ctx *ctx, - uint32_t wots_addr[8], uint32_t tree_addr[8], - uint32_t idx_leaf); - -/* Compute the root node of the top-most subtree. */ -#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) -void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); - -#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/nistapi.h b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/nistapi.h deleted file mode 100644 index 3cb71afad4..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/nistapi.h +++ /dev/null @@ -1,87 +0,0 @@ -#ifndef SPX_API_H -#define SPX_API_H - -#include -#include - -#include "params.h" - -#define CRYPTO_ALGNAME "SPHINCS+" - -#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES -#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES -#define CRYPTO_BYTES SPX_BYTES -#define CRYPTO_SEEDBYTES (3*SPX_N) - -/* - * Returns the length of a secret key, in bytes - */ -#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) -size_t crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) -size_t crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) -size_t crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) -size_t crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) -int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) -int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) -int crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) -int crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -#define crypto_sign SPX_NAMESPACE(crypto_sign) -int crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) -int crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/params.h b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/params.h deleted file mode 100644 index 398458b430..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/params.h +++ /dev/null @@ -1,61 +0,0 @@ -#ifndef SPX_PARAMS_H -#define SPX_PARAMS_H - -#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSSHA2192SROBUST_CLEAN_##s - -/* Hash output length in bytes. */ -#define SPX_N 24 -/* Height of the hypertree. */ -#define SPX_FULL_HEIGHT 63 -/* Number of subtree layer. */ -#define SPX_D 7 -/* FORS tree dimensions. */ -#define SPX_FORS_HEIGHT 14 -#define SPX_FORS_TREES 17 -/* Winternitz parameter, */ -#define SPX_WOTS_W 16 - -/* The hash function is defined by linking a different hash.c file, as opposed - to setting a #define constant. */ - -/* This is a SHA2-based parameter set, hence whether we use SHA-256 - * exclusively or we use both SHA-256 and SHA-512 is controlled by - * the following #define */ -#define SPX_SHA512 1 /* Use SHA-512 for H and T_l, l >= 2 */ - -/* For clarity */ -#define SPX_ADDR_BYTES 32 - -/* WOTS parameters. */ -#define SPX_WOTS_LOGW 4 - -#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) - -/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#define SPX_WOTS_LEN2 3 - -#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) -#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) -#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES - -/* Subtree size. */ -#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) - -//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT -// #error SPX_D should always divide SPX_FULL_HEIGHT -//#endif - -/* FORS parameters. */ -#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) -#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) -#define SPX_FORS_PK_BYTES SPX_N - -/* Resulting SPX sizes. */ -#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ - SPX_FULL_HEIGHT * SPX_N) -#define SPX_PK_BYTES (2 * SPX_N) -#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) - -#include "sha2_offsets.h" - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/sha2_offsets.h b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/sha2_offsets.h deleted file mode 100644 index 6e3584f7a4..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/sha2_offsets.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef SHA2_OFFSETS_H_ -#define SHA2_OFFSETS_H_ - -#define SPX_SHA256_BLOCK_BYTES 64 -#define SPX_SHA256_OUTPUT_BYTES 32 - -#define SPX_SHA512_BLOCK_BYTES 128 -#define SPX_SHA512_OUTPUT_BYTES 64 - -/* - * Offsets of various fields in the address structure when we use SHA2 as - * the Sphincs+ hash function - */ - -#define SPX_OFFSET_LAYER 0 /* The byte used to specify the Merkle tree layer */ -#define SPX_OFFSET_TREE 1 /* The start of the 8 byte field used to specify the tree */ -#define SPX_OFFSET_TYPE 9 /* The byte used to specify the hash type (reason) */ -#define SPX_OFFSET_KP_ADDR2 12 /* The high byte used to specify the key pair (which one-time signature) */ -#define SPX_OFFSET_KP_ADDR1 13 /* The low byte used to specify the key pair */ -#define SPX_OFFSET_CHAIN_ADDR 17 /* The byte used to specify the chain address (which Winternitz chain) */ -#define SPX_OFFSET_HASH_ADDR 21 /* The byte used to specify the hash address (where in the Winternitz chain) */ -#define SPX_OFFSET_TREE_HGT 17 /* The byte used to specify the height of this node in the FORS or Merkle tree */ -#define SPX_OFFSET_TREE_INDEX 18 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ - -#define SPX_SHA2 1 - -#endif /* SHA2_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/sign.c b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/sign.c deleted file mode 100644 index 9d0c7d1b22..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/sign.c +++ /dev/null @@ -1,286 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "context.h" -#include "fors.h" -#include "hash.h" -#include "merkle.h" -#include "nistapi.h" -#include "params.h" -#include "randombytes.h" -#include "thash.h" -#include "utils.h" -#include "wots.h" - -/* - * Returns the length of a secret key, in bytes - */ -size_t crypto_sign_secretkeybytes(void) { - return CRYPTO_SECRETKEYBYTES; -} - -/* - * Returns the length of a public key, in bytes - */ -size_t crypto_sign_publickeybytes(void) { - return CRYPTO_PUBLICKEYBYTES; -} - -/* - * Returns the length of a signature, in bytes - */ -size_t crypto_sign_bytes(void) { - return CRYPTO_BYTES; -} - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t crypto_sign_seedbytes(void) { - return CRYPTO_SEEDBYTES; -} - -/* - * Generates an SPX key pair given a seed of length - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed) { - spx_ctx ctx; - - /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ - memcpy(sk, seed, CRYPTO_SEEDBYTES); - - memcpy(pk, sk + 2 * SPX_N, SPX_N); - - memcpy(ctx.pub_seed, pk, SPX_N); - memcpy(ctx.sk_seed, sk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - /* Compute root node of the top-most subtree. */ - merkle_gen_root(sk + 3 * SPX_N, &ctx); - - // cleanup - free_hash_function(&ctx); - - memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); - - return 0; -} - -/* - * Generates an SPX key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { - uint8_t seed[CRYPTO_SEEDBYTES]; - randombytes(seed, CRYPTO_SEEDBYTES); - crypto_sign_seed_keypair(pk, sk, seed); - - return 0; -} - -/** - * Returns an array containing a detached signature. - */ -int crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - spx_ctx ctx; - - const uint8_t *sk_prf = sk + SPX_N; - const uint8_t *pk = sk + 2 * SPX_N; - - uint8_t optrand[SPX_N]; - uint8_t mhash[SPX_FORS_MSG_BYTES]; - uint8_t root[SPX_N]; - uint32_t i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - - memcpy(ctx.sk_seed, sk, SPX_N); - memcpy(ctx.pub_seed, pk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - set_type(wots_addr, SPX_ADDR_TYPE_WOTS); - set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); - - /* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ - randombytes(optrand, SPX_N); - /* Compute the digest randomization value. */ - gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); - - /* Derive the message digest and leaf index from R, PK and M. */ - hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); - sig += SPX_N; - - set_tree_addr(wots_addr, tree); - set_keypair_addr(wots_addr, idx_leaf); - - /* Sign the message hash using FORS. */ - fors_sign(sig, root, mhash, &ctx, wots_addr); - sig += SPX_FORS_BYTES; - - for (i = 0; i < SPX_D; i++) { - set_layer_addr(tree_addr, i); - set_tree_addr(tree_addr, tree); - - copy_subtree_addr(wots_addr, tree_addr); - set_keypair_addr(wots_addr, idx_leaf); - - merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); - sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); - tree = tree >> SPX_TREE_HEIGHT; - } - - free_hash_function(&ctx); - - *siglen = SPX_BYTES; - - return 0; -} - -/** - * Verifies a detached signature and message under a given public key. - */ -int crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk) { - spx_ctx ctx; - const uint8_t *pub_root = pk + SPX_N; - uint8_t mhash[SPX_FORS_MSG_BYTES]; - uint8_t wots_pk[SPX_WOTS_BYTES]; - uint8_t root[SPX_N]; - uint8_t leaf[SPX_N]; - unsigned int i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - if (siglen != SPX_BYTES) { - return -1; - } - - memcpy(ctx.pub_seed, pk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - set_type(wots_addr, SPX_ADDR_TYPE_WOTS); - set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); - set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); - - /* Derive the message digest and leaf index from R || PK || M. */ - /* The additional SPX_N is a result of the hash domain separator. */ - hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); - sig += SPX_N; - - /* Layer correctly defaults to 0, so no need to set_layer_addr */ - set_tree_addr(wots_addr, tree); - set_keypair_addr(wots_addr, idx_leaf); - - fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); - sig += SPX_FORS_BYTES; - - /* For each subtree.. */ - for (i = 0; i < SPX_D; i++) { - set_layer_addr(tree_addr, i); - set_tree_addr(tree_addr, tree); - - copy_subtree_addr(wots_addr, tree_addr); - set_keypair_addr(wots_addr, idx_leaf); - - copy_keypair_addr(wots_pk_addr, wots_addr); - - /* The WOTS public key is only correct if the signature was correct. */ - /* Initially, root is the FORS pk, but on subsequent iterations it is - the root of the subtree below the currently processed subtree. */ - wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); - sig += SPX_WOTS_BYTES; - - /* Compute the leaf node using the WOTS public key. */ - thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); - - /* Compute the root node of this subtree. */ - compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, - &ctx, tree_addr); - sig += SPX_TREE_HEIGHT * SPX_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); - tree = tree >> SPX_TREE_HEIGHT; - } - - // cleanup - free_hash_function(&ctx); - - /* Check if the root node equals the root node in the public key. */ - if (memcmp(root, pub_root, SPX_N) != 0) { - return -1; - } - - return 0; -} - - -/** - * Returns an array containing the signature followed by the message. - */ -int crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk) { - size_t siglen; - - crypto_sign_signature(sm, &siglen, m, mlen, sk); - - memmove(sm + SPX_BYTES, m, mlen); - *smlen = siglen + mlen; - - return 0; -} - -/** - * Verifies a given signature-message pair under a given public key. - */ -int crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk) { - /* The API caller does not necessarily know what size a signature should be - but SPHINCS+ signatures are always exactly SPX_BYTES. */ - if (smlen < SPX_BYTES) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - *mlen = smlen - SPX_BYTES; - - if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - /* If verification was successful, move the message to the right place. */ - memmove(m, sm + SPX_BYTES, *mlen); - - return 0; -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/thash.h b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/thash.h deleted file mode 100644 index 8687ccfb4d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/thash.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef SPX_THASH_H -#define SPX_THASH_H - -#include "context.h" -#include "params.h" - -#include - -#define thash SPX_NAMESPACE(thash) -void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/thash_sha2_robust.c b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/thash_sha2_robust.c deleted file mode 100644 index 3ab891175f..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/thash_sha2_robust.c +++ /dev/null @@ -1,68 +0,0 @@ -#include -#include - -#include "address.h" -#include "context.h" -#include "hash.h" -#include "params.h" -#include "sha2.h" -#include "thash.h" -#include "utils.h" - -static void thash_512(unsigned char *out, const unsigned char *in, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]); - -/** - * Takes an array of inblocks concatenated arrays of SPX_N bytes. - */ -void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]) { - if (inblocks > 1) { - thash_512(out, in, inblocks, ctx, addr); - return; - } - unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES]; - PQCLEAN_VLA(uint8_t, bitmask, inblocks * SPX_N); - PQCLEAN_VLA(uint8_t, buf, SPX_N + SPX_SHA256_OUTPUT_BYTES + inblocks * SPX_N); - sha256ctx sha2_state; - unsigned int i; - - memcpy(buf, ctx->pub_seed, SPX_N); - memcpy(buf + SPX_N, addr, SPX_SHA256_ADDR_BYTES); - mgf1_256(bitmask, inblocks * SPX_N, buf, SPX_N + SPX_SHA256_ADDR_BYTES); - - /* Retrieve precomputed state containing pub_seed */ - sha256_inc_ctx_clone(&sha2_state, &ctx->state_seeded); - - for (i = 0; i < inblocks * SPX_N; i++) { - buf[SPX_N + SPX_SHA256_ADDR_BYTES + i] = in[i] ^ bitmask[i]; - } - - sha256_inc_finalize(outbuf, &sha2_state, buf + SPX_N, - SPX_SHA256_ADDR_BYTES + inblocks * SPX_N); - memcpy(out, outbuf, SPX_N); -} - -static void thash_512(unsigned char *out, const unsigned char *in, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]) { - unsigned char outbuf[SPX_SHA512_OUTPUT_BYTES]; - PQCLEAN_VLA(uint8_t, bitmask, inblocks * SPX_N); - PQCLEAN_VLA(uint8_t, buf, SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N); - sha512ctx sha2_state; - unsigned int i; - - memcpy(buf, ctx->pub_seed, SPX_N); - memcpy(buf + SPX_N, addr, SPX_SHA256_ADDR_BYTES); - mgf1_512(bitmask, inblocks * SPX_N, buf, SPX_N + SPX_SHA256_ADDR_BYTES); - - /* Retrieve precomputed state containing pub_seed */ - sha512_inc_ctx_clone(&sha2_state, &ctx->state_seeded_512); - - for (i = 0; i < inblocks * SPX_N; i++) { - buf[SPX_N + SPX_SHA256_ADDR_BYTES + i] = in[i] ^ bitmask[i]; - } - - sha512_inc_finalize(outbuf, &sha2_state, buf + SPX_N, - SPX_SHA256_ADDR_BYTES + inblocks * SPX_N); - memcpy(out, outbuf, SPX_N); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/utils.c b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/utils.c deleted file mode 100644 index 177b541fb9..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/utils.c +++ /dev/null @@ -1,148 +0,0 @@ -#include - -#include "utils.h" - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "thash.h" - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void ull_to_bytes(unsigned char *out, unsigned int outlen, - unsigned long long in) { - int i; - - /* Iterate over out in decreasing order, for big-endianness. */ - for (i = (signed int)outlen - 1; i >= 0; i--) { - out[i] = in & 0xff; - in = in >> 8; - } -} - -void u32_to_bytes(unsigned char *out, uint32_t in) { - out[0] = (unsigned char)(in >> 24); - out[1] = (unsigned char)(in >> 16); - out[2] = (unsigned char)(in >> 8); - out[3] = (unsigned char)in; -} - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { - unsigned long long retval = 0; - unsigned int i; - - for (i = 0; i < inlen; i++) { - retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); - } - return retval; -} - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void compute_root(unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const spx_ctx *ctx, uint32_t addr[8]) { - uint32_t i; - unsigned char buffer[2 * SPX_N]; - - /* If leaf_idx is odd (last bit = 1), current path element is a right child - and auth_path has to go left. Otherwise it is the other way around. */ - if (leaf_idx & 1) { - memcpy(buffer + SPX_N, leaf, SPX_N); - memcpy(buffer, auth_path, SPX_N); - } else { - memcpy(buffer, leaf, SPX_N); - memcpy(buffer + SPX_N, auth_path, SPX_N); - } - auth_path += SPX_N; - - for (i = 0; i < tree_height - 1; i++) { - leaf_idx >>= 1; - idx_offset >>= 1; - /* Set the address of the node we're creating. */ - set_tree_height(addr, i + 1); - set_tree_index(addr, leaf_idx + idx_offset); - - /* Pick the right or left neighbor, depending on parity of the node. */ - if (leaf_idx & 1) { - thash(buffer + SPX_N, buffer, 2, ctx, addr); - memcpy(buffer, auth_path, SPX_N); - } else { - thash(buffer, buffer, 2, ctx, addr); - memcpy(buffer + SPX_N, auth_path, SPX_N); - } - auth_path += SPX_N; - } - - /* The last iteration is exceptional; we do not copy an auth_path node. */ - leaf_idx >>= 1; - idx_offset >>= 1; - set_tree_height(addr, tree_height); - set_tree_index(addr, leaf_idx + idx_offset); - thash(root, buffer, 2, ctx, addr); -} - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const spx_ctx * /* ctx */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), - uint32_t tree_addr[8]) { - PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); - PQCLEAN_VLA(unsigned int, heights, tree_height + 1); - unsigned int offset = 0; - uint32_t idx; - uint32_t tree_idx; - - for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { - /* Add the next leaf node to the stack. */ - gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); - offset++; - heights[offset - 1] = 0; - - /* If this is a node we need for the auth path.. */ - if ((leaf_idx ^ 0x1) == idx) { - memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); - } - - /* While the top-most nodes are of equal height.. */ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { - /* Compute index of the new node, in the next layer. */ - tree_idx = (idx >> (heights[offset - 1] + 1)); - - /* Set the address of the node we're creating. */ - set_tree_height(tree_addr, heights[offset - 1] + 1); - set_tree_index(tree_addr, - tree_idx + (idx_offset >> (heights[offset - 1] + 1))); - /* Hash the top-most nodes from the stack together. */ - thash(stack + (offset - 2)*SPX_N, - stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); - offset--; - /* Note that the top-most node is now one layer higher. */ - heights[offset - 1]++; - - /* If this is a node we need for the auth path.. */ - if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_path + heights[offset - 1]*SPX_N, - stack + (offset - 1)*SPX_N, SPX_N); - } - } - } - memcpy(root, stack, SPX_N); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/utils.h b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/utils.h deleted file mode 100644 index 64f5d5a53a..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/utils.h +++ /dev/null @@ -1,58 +0,0 @@ -#ifndef SPX_UTILS_H -#define SPX_UTILS_H - -#include - -#include "compat.h" -#include "context.h" -#include "params.h" - - -/* To support MSVC use alloca() instead of VLAs. See #20. */ - - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) -void ull_to_bytes(unsigned char *out, unsigned int outlen, - unsigned long long in); -#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) -void u32_to_bytes(unsigned char *out, uint32_t in); - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) -unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -#define compute_root SPX_NAMESPACE(compute_root) -void compute_root(unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const spx_ctx *ctx, uint32_t addr[8]); - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -#define treehash SPX_NAMESPACE(treehash) -void treehash(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const spx_ctx *ctx /* ctx */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), - uint32_t tree_addr[8]); - - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/utilsx1.c b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/utilsx1.c deleted file mode 100644 index fccb69b35d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/utilsx1.c +++ /dev/null @@ -1,100 +0,0 @@ -#include - -#include "utilsx1.h" - -#include "address.h" -#include "params.h" -#include "thash.h" -#include "utils.h" - -/* - * Generate the entire Merkle tree, computing the authentication path for - * leaf_idx, and the resulting root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) - * - * This expects tree_addr to be initialized to the addr structures for the - * Merkle tree nodes - * - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - * - * This works by using the standard Merkle tree building algorithm, - */ -void treehashx1(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, - uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* Where to write the leaves */, - const spx_ctx * /* ctx */, - uint32_t idx, void *info), - uint32_t tree_addr[8], - void *info) { - /* This is where we keep the intermediate nodes */ - PQCLEAN_VLA(uint8_t, stack, tree_height * SPX_N); - - uint32_t idx; - uint32_t max_idx = (uint32_t)((1 << tree_height) - 1); - for (idx = 0;; idx++) { - unsigned char current[2 * SPX_N]; /* Current logical node is at */ - /* index[SPX_N]. We do this to minimize the number of copies */ - /* needed during a thash */ - gen_leaf( ¤t[SPX_N], ctx, idx + idx_offset, - info ); - - /* Now combine the freshly generated right node with previously */ - /* generated left ones */ - uint32_t internal_idx_offset = idx_offset; - uint32_t internal_idx = idx; - uint32_t internal_leaf = leaf_idx; - uint32_t h; /* The height we are in the Merkle tree */ - for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { - - /* Check if we hit the top of the tree */ - if (h == tree_height) { - /* We hit the root; return it */ - memcpy( root, ¤t[SPX_N], SPX_N ); - return; - } - - /* - * Check if the node we have is a part of the - * authentication path; if it is, write it out - */ - if ((internal_idx ^ internal_leaf) == 0x01) { - memcpy( &auth_path[ h * SPX_N ], - ¤t[SPX_N], - SPX_N ); - } - - /* - * Check if we're at a left child; if so, stop going up the stack - * Exception: if we've reached the end of the tree, keep on going - * (so we combine the last 4 nodes into the one root node in two - * more iterations) - */ - if ((internal_idx & 1) == 0 && idx < max_idx) { - break; - } - - /* Ok, we're at a right node */ - /* Now combine the left and right logical nodes together */ - - /* Set the address of the node we're creating. */ - internal_idx_offset >>= 1; - set_tree_height(tree_addr, h + 1); - set_tree_index(tree_addr, internal_idx / 2 + internal_idx_offset ); - - unsigned char *left = &stack[h * SPX_N]; - memcpy( ¤t[0], left, SPX_N ); - thash( ¤t[1 * SPX_N], - ¤t[0 * SPX_N], - 2, ctx, tree_addr); - } - - /* We've hit a left child; save the current for when we get the */ - /* corresponding right right */ - memcpy( &stack[h * SPX_N], ¤t[SPX_N], SPX_N); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/utilsx1.h b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/utilsx1.h deleted file mode 100644 index e911d17d53..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/utilsx1.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef SPX_UTILSX4_H -#define SPX_UTILSX4_H - -#include - -#include "context.h" -#include "params.h" - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -#define treehashx1 SPX_NAMESPACE(treehashx1) -void treehashx1(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* Where to write the leaf */, - const spx_ctx * /* ctx */, - uint32_t addr_idx, void *info), - uint32_t tree_addrx4[8], void *info); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/wots.c b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/wots.c deleted file mode 100644 index 249717aaa8..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/wots.c +++ /dev/null @@ -1,108 +0,0 @@ -#include -#include - -#include "wots.h" -#include "wotsx1.h" - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "thash.h" -#include "utils.h" -#include "utilsx1.h" - -// TODO clarify address expectations, and make them more uniform. -// TODO i.e. do we expect types to be set already? -// TODO and do we expect modifications or copies? - -/** - * Computes the chaining function. - * out and in have to be n-byte arrays. - * - * Interprets in as start-th value of the chain. - * addr has to contain the address of the chain. - */ -static void gen_chain(unsigned char *out, const unsigned char *in, - unsigned int start, unsigned int steps, - const spx_ctx *ctx, uint32_t addr[8]) { - uint32_t i; - - /* Initialize out with the value at position 'start'. */ - memcpy(out, in, SPX_N); - - /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < SPX_WOTS_W; i++) { - set_hash_addr(addr, i); - thash(out, out, 1, ctx, addr); - } -} - -/** - * base_w algorithm as described in draft. - * Interprets an array of bytes as integers in base w. - * This only works when log_w is a divisor of 8. - */ -static void base_w(unsigned int *output, const int out_len, - const unsigned char *input) { - int in = 0; - int out = 0; - unsigned char total = 0; - int bits = 0; - int consumed; - - for (consumed = 0; consumed < out_len; consumed++) { - if (bits == 0) { - total = input[in]; - in++; - bits += 8; - } - bits -= SPX_WOTS_LOGW; - output[out] = (total >> bits) & (SPX_WOTS_W - 1); - out++; - } -} - -/* Computes the WOTS+ checksum over a message (in base_w). */ -static void wots_checksum(unsigned int *csum_base_w, - const unsigned int *msg_base_w) { - unsigned int csum = 0; - unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; - unsigned int i; - - /* Compute checksum. */ - for (i = 0; i < SPX_WOTS_LEN1; i++) { - csum += SPX_WOTS_W - 1 - msg_base_w[i]; - } - - /* Convert checksum to base_w. */ - /* Make sure expected empty zero bits are the least significant bits. */ - csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); - ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); - base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); -} - -/* Takes a message and derives the matching chain lengths. */ -void chain_lengths(unsigned int *lengths, const unsigned char *msg) { - base_w(lengths, SPX_WOTS_LEN1, msg); - wots_checksum(lengths + SPX_WOTS_LEN1, lengths); -} - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const spx_ctx *ctx, uint32_t addr[8]) { - unsigned int lengths[SPX_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < SPX_WOTS_LEN; i++) { - set_chain_addr(addr, i); - gen_chain(pk + i * SPX_N, sig + i * SPX_N, - lengths[i], SPX_WOTS_W - 1 - lengths[i], ctx, addr); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/wots.h b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/wots.h deleted file mode 100644 index 4e7692eeef..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/wots.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef SPX_WOTS_H -#define SPX_WOTS_H - -#include - -#include "context.h" -#include "params.h" - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) -void wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const spx_ctx *ctx, uint32_t addr[8]); - -/* - * Compute the chain lengths needed for a given message hash - */ -#define chain_lengths SPX_NAMESPACE(chain_lengths) -void chain_lengths(unsigned int *lengths, const unsigned char *msg); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/wotsx1.c b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/wotsx1.c deleted file mode 100644 index 3adec78dfb..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/wotsx1.c +++ /dev/null @@ -1,76 +0,0 @@ -#include -#include - -#include "wots.h" -#include "wotsx1.h" - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "thash.h" -#include "utils.h" - -/* - * This generates a WOTS public key - * It also generates the WOTS signature if leaf_info indicates - * that we're signing with this WOTS key - */ -void wots_gen_leafx1(unsigned char *dest, - const spx_ctx *ctx, - uint32_t leaf_idx, void *v_info) { - struct leaf_info_x1 *info = v_info; - uint32_t *leaf_addr = info->leaf_addr; - uint32_t *pk_addr = info->pk_addr; - unsigned int i, k; - unsigned char pk_buffer[ SPX_WOTS_BYTES ]; - unsigned char *buffer; - uint32_t wots_k_mask; - - if (leaf_idx == info->wots_sign_leaf) { - /* We're traversing the leaf that's signing; generate the WOTS */ - /* signature */ - wots_k_mask = 0; - } else { - /* Nope, we're just generating pk's; turn off the signature logic */ - wots_k_mask = (uint32_t)~0; - } - - set_keypair_addr( leaf_addr, leaf_idx ); - set_keypair_addr( pk_addr, leaf_idx ); - - for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { - uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k to */ - /* the step if we're generating a signature, ~0 if we're not */ - - /* Start with the secret seed */ - set_chain_addr(leaf_addr, i); - set_hash_addr(leaf_addr, 0); - set_type(leaf_addr, SPX_ADDR_TYPE_WOTSPRF); - - prf_addr(buffer, ctx, leaf_addr); - - set_type(leaf_addr, SPX_ADDR_TYPE_WOTS); - - /* Iterate down the WOTS chain */ - for (k = 0;; k++) { - /* Check if this is the value that needs to be saved as a */ - /* part of the WOTS signature */ - if (k == wots_k) { - memcpy( info->wots_sig + i * SPX_N, buffer, SPX_N ); - } - - /* Check if we hit the top of the chain */ - if (k == SPX_WOTS_W - 1) { - break; - } - - /* Iterate one step on the chain */ - set_hash_addr(leaf_addr, k); - - thash(buffer, buffer, 1, ctx, leaf_addr); - } - } - - /* Do the final thash to generate the public keys */ - thash(dest, pk_buffer, SPX_WOTS_LEN, ctx, pk_addr); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/wotsx1.h b/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/wotsx1.h deleted file mode 100644 index e617929f96..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-192s-robust_clean/wotsx1.h +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef WOTSX1_H_ -#define WOTSX1_H_ - -#include - -#include "context.h" -#include "params.h" - -/* - * This is here to provide an interface to the internal wots_gen_leafx1 - * routine. While this routine is not referenced in the package outside of - * wots.c, it is called from the stand-alone benchmark code to characterize - * the performance - */ -struct leaf_info_x1 { - unsigned char *wots_sig; - uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ - uint32_t *wots_steps; - uint32_t leaf_addr[8]; - uint32_t pk_addr[8]; -}; - -/* Macro to set the leaf_info to something 'benign', that is, it would */ -/* run with the same time as it does during the real signing process */ -/* Used only by the benchmark code */ -#define INITIALIZE_LEAF_INFO_X1(info, addr, step_buffer) { \ - (info).wots_sig = 0; \ - (info).wots_sign_leaf = ~0; \ - (info).wots_steps = step_buffer; \ - memcpy( &(info).leaf_addr[0], (addr), 32 ); \ - memcpy( &(info).pk_addr[0], (addr), 32 ); \ - } - -#define wots_gen_leafx1 SPX_NAMESPACE(wots_gen_leafx1) -void wots_gen_leafx1(unsigned char *dest, - const spx_ctx *ctx, - uint32_t leaf_idx, void *v_info); - -#endif /* WOTSX1_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/LICENSE b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/LICENSE deleted file mode 100644 index 670154e353..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/LICENSE +++ /dev/null @@ -1,116 +0,0 @@ -CC0 1.0 Universal - -Statement of Purpose - -The laws of most jurisdictions throughout the world automatically confer -exclusive Copyright and Related Rights (defined below) upon the creator and -subsequent owner(s) (each and all, an "owner") of an original work of -authorship and/or a database (each, a "Work"). - -Certain owners wish to permanently relinquish those rights to a Work for the -purpose of contributing to a commons of creative, cultural and scientific -works ("Commons") that the public can reliably and without fear of later -claims of infringement build upon, modify, incorporate in other works, reuse -and redistribute as freely as possible in any form whatsoever and for any -purposes, including without limitation commercial purposes. These owners may -contribute to the Commons to promote the ideal of a free culture and the -further production of creative, cultural and scientific works, or to gain -reputation or greater distribution for their Work in part through the use and -efforts of others. - -For these and/or other purposes and motivations, and without any expectation -of additional consideration or compensation, the person associating CC0 with a -Work (the "Affirmer"), to the extent that he or she is an owner of Copyright -and Related Rights in the Work, voluntarily elects to apply CC0 to the Work -and publicly distribute the Work under its terms, with knowledge of his or her -Copyright and Related Rights in the Work and the meaning and intended legal -effect of CC0 on those rights. - -1. Copyright and Related Rights. A Work made available under CC0 may be -protected by copyright and related or neighboring rights ("Copyright and -Related Rights"). Copyright and Related Rights include, but are not limited -to, the following: - - i. the right to reproduce, adapt, distribute, perform, display, communicate, - and translate a Work; - - ii. moral rights retained by the original author(s) and/or performer(s); - - iii. publicity and privacy rights pertaining to a person's image or likeness - depicted in a Work; - - iv. rights protecting against unfair competition in regards to a Work, - subject to the limitations in paragraph 4(a), below; - - v. rights protecting the extraction, dissemination, use and reuse of data in - a Work; - - vi. database rights (such as those arising under Directive 96/9/EC of the - European Parliament and of the Council of 11 March 1996 on the legal - protection of databases, and under any national implementation thereof, - including any amended or successor version of such directive); and - - vii. other similar, equivalent or corresponding rights throughout the world - based on applicable law or treaty, and any national implementations thereof. - -2. Waiver. To the greatest extent permitted by, but not in contravention of, -applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and -unconditionally waives, abandons, and surrenders all of Affirmer's Copyright -and Related Rights and associated claims and causes of action, whether now -known or unknown (including existing as well as future claims and causes of -action), in the Work (i) in all territories worldwide, (ii) for the maximum -duration provided by applicable law or treaty (including future time -extensions), (iii) in any current or future medium and for any number of -copies, and (iv) for any purpose whatsoever, including without limitation -commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes -the Waiver for the benefit of each member of the public at large and to the -detriment of Affirmer's heirs and successors, fully intending that such Waiver -shall not be subject to revocation, rescission, cancellation, termination, or -any other legal or equitable action to disrupt the quiet enjoyment of the Work -by the public as contemplated by Affirmer's express Statement of Purpose. - -3. Public License Fallback. Should any part of the Waiver for any reason be -judged legally invalid or ineffective under applicable law, then the Waiver -shall be preserved to the maximum extent permitted taking into account -Affirmer's express Statement of Purpose. In addition, to the extent the Waiver -is so judged Affirmer hereby grants to each affected person a royalty-free, -non transferable, non sublicensable, non exclusive, irrevocable and -unconditional license to exercise Affirmer's Copyright and Related Rights in -the Work (i) in all territories worldwide, (ii) for the maximum duration -provided by applicable law or treaty (including future time extensions), (iii) -in any current or future medium and for any number of copies, and (iv) for any -purpose whatsoever, including without limitation commercial, advertising or -promotional purposes (the "License"). The License shall be deemed effective as -of the date CC0 was applied by Affirmer to the Work. Should any part of the -License for any reason be judged legally invalid or ineffective under -applicable law, such partial invalidity or ineffectiveness shall not -invalidate the remainder of the License, and in such case Affirmer hereby -affirms that he or she will not (i) exercise any of his or her remaining -Copyright and Related Rights in the Work or (ii) assert any associated claims -and causes of action with respect to the Work, in either case contrary to -Affirmer's express Statement of Purpose. - -4. Limitations and Disclaimers. - - a. No trademark or patent rights held by Affirmer are waived, abandoned, - surrendered, licensed or otherwise affected by this document. - - b. Affirmer offers the Work as-is and makes no representations or warranties - of any kind concerning the Work, express, implied, statutory or otherwise, - including without limitation warranties of title, merchantability, fitness - for a particular purpose, non infringement, or the absence of latent or - other defects, accuracy, or the present or absence of errors, whether or not - discoverable, all to the greatest extent permissible under applicable law. - - c. Affirmer disclaims responsibility for clearing rights of other persons - that may apply to the Work or any use thereof, including without limitation - any person's Copyright and Related Rights in the Work. Further, Affirmer - disclaims responsibility for obtaining any necessary consents, permissions - or other rights required for any use of the Work. - - d. Affirmer understands and acknowledges that Creative Commons is not a - party to this document and has no duty or obligation with respect to this - CC0 or use of the Work. - -For more information, please see - diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/address.c b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/address.c deleted file mode 100644 index b956e9cb29..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/address.c +++ /dev/null @@ -1,91 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "utils.h" - -/* - * Specify which level of Merkle tree (the "layer") we're working on - */ -void set_layer_addr(uint32_t addr[8], uint32_t layer) { - ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; -} - -/* - * Specify which Merkle tree within the level (the "tree address") we're working on - */ -void set_tree_addr(uint32_t addr[8], uint64_t tree) { - ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); -} - -/* - * Specify the reason we'll use this address structure for, that is, what - * hash will we compute with it. This is used so that unrelated types of - * hashes don't accidentally get the same address structure. The type will be - * one of the SPX_ADDR_TYPE constants - */ -void set_type(uint32_t addr[8], uint32_t type) { - ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; -} - -/* - * Copy the layer and tree fields of the address structure. This is used - * when we're doing multiple types of hashes within the same Merkle tree - */ -void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { - memcpy( out, in, SPX_OFFSET_TREE + 8 ); -} - -/* These functions are used for OTS addresses. */ - -/* - * Specify which Merkle leaf we're working on; that is, which OTS keypair - * we're talking about. - */ -void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { - ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; -} - -/* - * Copy the layer, tree and keypair fields of the address structure. This is - * used when we're doing multiple things within the same OTS keypair - */ -void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { - memcpy( out, in, SPX_OFFSET_TREE + 8 ); - ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; -} - -/* - * Specify which Merkle chain within the OTS we're working with - * (the chain address) - */ -void set_chain_addr(uint32_t addr[8], uint32_t chain) { - ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; -} - -/* - * Specify where in the Merkle chain we are -* (the hash address) - */ -void set_hash_addr(uint32_t addr[8], uint32_t hash) { - ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; -} - -/* These functions are used for all hash tree addresses (including FORS). */ - -/* - * Specify the height of the node in the Merkle/FORS tree we are in - * (the tree height) - */ -void set_tree_height(uint32_t addr[8], uint32_t tree_height) { - ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; -} - -/* - * Specify the distance from the left edge of the node in the Merkle/FORS tree - * (the tree index) - */ -void set_tree_index(uint32_t addr[8], uint32_t tree_index) { - u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/address.h b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/address.h deleted file mode 100644 index 24a84eb40c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/address.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef SPX_ADDRESS_H -#define SPX_ADDRESS_H - -#include - -#include "params.h" - -/* The hash types that are passed to set_type */ -#define SPX_ADDR_TYPE_WOTS 0 -#define SPX_ADDR_TYPE_WOTSPK 1 -#define SPX_ADDR_TYPE_HASHTREE 2 -#define SPX_ADDR_TYPE_FORSTREE 3 -#define SPX_ADDR_TYPE_FORSPK 4 -#define SPX_ADDR_TYPE_WOTSPRF 5 -#define SPX_ADDR_TYPE_FORSPRF 6 - -#define set_layer_addr SPX_NAMESPACE(set_layer_addr) -void set_layer_addr(uint32_t addr[8], uint32_t layer); - -#define set_tree_addr SPX_NAMESPACE(set_tree_addr) -void set_tree_addr(uint32_t addr[8], uint64_t tree); - -#define set_type SPX_NAMESPACE(set_type) -void set_type(uint32_t addr[8], uint32_t type); - -/* Copies the layer and tree part of one address into the other */ -#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) -void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for WOTS and FORS addresses. */ - -#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) -void set_keypair_addr(uint32_t addr[8], uint32_t keypair); - -#define set_chain_addr SPX_NAMESPACE(set_chain_addr) -void set_chain_addr(uint32_t addr[8], uint32_t chain); - -#define set_hash_addr SPX_NAMESPACE(set_hash_addr) -void set_hash_addr(uint32_t addr[8], uint32_t hash); - -#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) -void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for all hash tree addresses (including FORS). */ - -#define set_tree_height SPX_NAMESPACE(set_tree_height) -void set_tree_height(uint32_t addr[8], uint32_t tree_height); - -#define set_tree_index SPX_NAMESPACE(set_tree_index) -void set_tree_index(uint32_t addr[8], uint32_t tree_index); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/api.h b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/api.h deleted file mode 100644 index e1deefba85..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/api.h +++ /dev/null @@ -1,77 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA2256FROBUST_AVX2_API_H -#define PQCLEAN_SPHINCSSHA2256FROBUST_AVX2_API_H - -#include -#include - -#define PQCLEAN_SPHINCSSHA2256FROBUST_AVX2_CRYPTO_ALGNAME "SPHINCS+-sha2-256f-robust" - -#define PQCLEAN_SPHINCSSHA2256FROBUST_AVX2_CRYPTO_SECRETKEYBYTES 128 -#define PQCLEAN_SPHINCSSHA2256FROBUST_AVX2_CRYPTO_PUBLICKEYBYTES 64 -#define PQCLEAN_SPHINCSSHA2256FROBUST_AVX2_CRYPTO_BYTES 49856 - -#define PQCLEAN_SPHINCSSHA2256FROBUST_AVX2_CRYPTO_SEEDBYTES 96 - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSSHA2256FROBUST_AVX2_crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSSHA2256FROBUST_AVX2_crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSSHA2256FROBUST_AVX2_crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSSHA2256FROBUST_AVX2_crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHA2256FROBUST_AVX2_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHA2256FROBUST_AVX2_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSSHA2256FROBUST_AVX2_crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSSHA2256FROBUST_AVX2_crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, - const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSSHA2256FROBUST_AVX2_crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSSHA2256FROBUST_AVX2_crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk); -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/context.h b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/context.h deleted file mode 100644 index d3bf1c3aac..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/context.h +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef SPX_CONTEXT_H -#define SPX_CONTEXT_H - -#include - -#include "params.h" -#include "sha2.h" -#include "sha256avx.h" -#include "sha512x4.h" - -// funky ordering due to optimal padding -typedef struct { - sha256x8ctx statex8_seeded; - sha512x4ctx statex4_seeded_512; - sha256ctx state_seeded; - sha512ctx state_seeded_512; - - uint8_t pub_seed[SPX_N]; - uint8_t sk_seed[SPX_N]; -} spx_ctx; - - -#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) -void initialize_hash_function(spx_ctx *ctx); - -#define free_hash_function SPX_NAMESPACE(free_hash_function) -void free_hash_function(spx_ctx *ctx); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/context_sha2.c b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/context_sha2.c deleted file mode 100644 index 83c1b6585d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/context_sha2.c +++ /dev/null @@ -1,56 +0,0 @@ -#include - -#include "context.h" - -/** - * Absorb the constant pub_seed using one round of the compression function - * This initializes state_seeded and state_seeded_512, which can then be - * reused in thash - **/ -static void seed_state(spx_ctx *ctx) { - uint8_t block[SPX_SHA512_BLOCK_BYTES]; - size_t i; - - for (i = 0; i < SPX_N; ++i) { - block[i] = ctx->pub_seed[i]; - } - for (i = SPX_N; i < SPX_SHA512_BLOCK_BYTES; ++i) { - block[i] = 0; - } - /* block has been properly initialized for both SHA-256 and SHA-512 */ - - sha256_inc_init(&ctx->state_seeded); - sha256_inc_blocks(&ctx->state_seeded, block, 1); - - // initialize x8 - sha256_init8x(&ctx->statex8_seeded); - sha256_transform8x(&ctx->statex8_seeded, - block, block, block, block, block, block, block, block); - - ctx->statex8_seeded.datalen = 0; - ctx->statex8_seeded.msglen = 512; - - sha512_inc_init(&ctx->state_seeded_512); - sha512_inc_blocks(&ctx->state_seeded_512, block, 1); - - // initialize x4 - sha512_init4x(&ctx->statex4_seeded_512); - sha512_transform4x(&ctx->statex4_seeded_512, block, block, block, block); - - ctx->statex4_seeded_512.datalen = 0; - ctx->statex4_seeded_512.msglen = 1024; - - -} - - -/* For SHA, we initialize the hash function at the start */ -void initialize_hash_function(spx_ctx *ctx) { - seed_state(ctx); -} - -/* Free the incremental hashing context for heap-based SHA2 APIs */ -void free_hash_function(spx_ctx *ctx) { - sha256_inc_ctx_release(&ctx->state_seeded); - sha512_inc_ctx_release(&ctx->state_seeded_512); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/fors.c b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/fors.c deleted file mode 100644 index 4cab8e7415..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/fors.c +++ /dev/null @@ -1,226 +0,0 @@ -#include -#include -#include - -#include "fors.h" - - -#include "address.h" -#include "hash.h" -#include "hashx8.h" -#include "thash.h" -#include "thashx8.h" -#include "utils.h" -#include "utilsx8.h" -static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, - uint32_t fors_leaf_addr[8]) { - prf_addr(sk, ctx, fors_leaf_addr); -} - -static void fors_gen_skx8(unsigned char *sk0, - unsigned char *sk1, - unsigned char *sk2, - unsigned char *sk3, - unsigned char *sk4, - unsigned char *sk5, - unsigned char *sk6, - unsigned char *sk7, const spx_ctx *ctx, - uint32_t fors_leaf_addrx8[8 * 8]) { - prf_addrx8(sk0, sk1, sk2, sk3, sk4, sk5, sk6, sk7, - ctx, fors_leaf_addrx8); -} - -static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, - const spx_ctx *ctx, - uint32_t fors_leaf_addr[8]) { - thash(leaf, sk, 1, ctx, fors_leaf_addr); -} - -static void fors_sk_to_leafx8(unsigned char *leaf0, - unsigned char *leaf1, - unsigned char *leaf2, - unsigned char *leaf3, - unsigned char *leaf4, - unsigned char *leaf5, - unsigned char *leaf6, - unsigned char *leaf7, - const unsigned char *sk0, - const unsigned char *sk1, - const unsigned char *sk2, - const unsigned char *sk3, - const unsigned char *sk4, - const unsigned char *sk5, - const unsigned char *sk6, - const unsigned char *sk7, - const spx_ctx *ctx, - uint32_t fors_leaf_addrx8[8 * 8]) { - thashx8(leaf0, leaf1, leaf2, leaf3, leaf4, leaf5, leaf6, leaf7, - sk0, sk1, sk2, sk3, sk4, sk5, sk6, sk7, - 1, ctx, fors_leaf_addrx8); -} - -struct fors_gen_leaf_info { - uint32_t leaf_addrx[8 * 8]; -}; - -static void fors_gen_leafx8(unsigned char *leaf, - const spx_ctx *ctx, - uint32_t addr_idx, void *info) { - struct fors_gen_leaf_info *fors_info = info; - uint32_t *fors_leaf_addrx8 = fors_info->leaf_addrx; - unsigned int j; - - /* Only set the parts that the caller doesn't set */ - for (j = 0; j < 8; j++) { - set_tree_index(fors_leaf_addrx8 + j * 8, addr_idx + j); - set_type(fors_leaf_addrx8 + j * 8, SPX_ADDR_TYPE_FORSPRF); - } - - fors_gen_skx8(leaf + 0 * SPX_N, - leaf + 1 * SPX_N, - leaf + 2 * SPX_N, - leaf + 3 * SPX_N, - leaf + 4 * SPX_N, - leaf + 5 * SPX_N, - leaf + 6 * SPX_N, - leaf + 7 * SPX_N, - ctx, fors_leaf_addrx8); - - for (j = 0; j < 8; j++) { - set_type(fors_leaf_addrx8 + j * 8, SPX_ADDR_TYPE_FORSTREE); - } - - fors_sk_to_leafx8(leaf + 0 * SPX_N, - leaf + 1 * SPX_N, - leaf + 2 * SPX_N, - leaf + 3 * SPX_N, - leaf + 4 * SPX_N, - leaf + 5 * SPX_N, - leaf + 6 * SPX_N, - leaf + 7 * SPX_N, - leaf + 0 * SPX_N, - leaf + 1 * SPX_N, - leaf + 2 * SPX_N, - leaf + 3 * SPX_N, - leaf + 4 * SPX_N, - leaf + 5 * SPX_N, - leaf + 6 * SPX_N, - leaf + 7 * SPX_N, - ctx, fors_leaf_addrx8); -} - -/** - * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - * Assumes indices has space for SPX_FORS_TREES integers. - */ -static void message_to_indices(uint32_t *indices, const unsigned char *m) { - unsigned int i, j; - unsigned int offset = 0; - - for (i = 0; i < SPX_FORS_TREES; i++) { - indices[i] = 0; - for (j = 0; j < SPX_FORS_HEIGHT; j++) { - indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); - offset++; - } - } -} - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -void fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]) { - uint32_t indices[SPX_FORS_TREES]; - unsigned char roots[SPX_FORS_TREES * SPX_N]; - uint32_t fors_tree_addr[8 * 8] = {0}; - struct fors_gen_leaf_info fors_info = {0}; - uint32_t *fors_leaf_addr = fors_info.leaf_addrx; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - for (i = 0; i < 8; i++) { - copy_keypair_addr(fors_tree_addr + 8 * i, fors_addr); - set_type(fors_tree_addr + 8 * i, SPX_ADDR_TYPE_FORSTREE); - copy_keypair_addr(fors_leaf_addr + 8 * i, fors_addr); - } - copy_keypair_addr(fors_pk_addr, fors_addr); - set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < SPX_FORS_TREES; i++) { - idx_offset = i * (1 << SPX_FORS_HEIGHT); - - set_tree_height(fors_tree_addr, 0); - set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Include the secret key part that produces the selected leaf node. */ - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); - fors_gen_sk(sig, ctx, fors_tree_addr); - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); - sig += SPX_N; - - /* Compute the authentication path for this leaf node. */ - treehashx8(roots + i * SPX_N, sig, ctx, - indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx8, - fors_tree_addr, &fors_info); - - sig += SPX_N * SPX_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); -} - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -void fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]) { - uint32_t indices[SPX_FORS_TREES]; - unsigned char roots[SPX_FORS_TREES * SPX_N]; - unsigned char leaf[SPX_N]; - uint32_t fors_tree_addr[8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - copy_keypair_addr(fors_tree_addr, fors_addr); - copy_keypair_addr(fors_pk_addr, fors_addr); - - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); - set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < SPX_FORS_TREES; i++) { - idx_offset = i * (1 << SPX_FORS_HEIGHT); - - set_tree_height(fors_tree_addr, 0); - set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Derive the leaf from the included secret key part. */ - fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); - sig += SPX_N; - - /* Derive the corresponding root node of this tree. */ - compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, - sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); - sig += SPX_N * SPX_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/fors.h b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/fors.h deleted file mode 100644 index 509140a178..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/fors.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef SPX_FORS_H -#define SPX_FORS_H - -#include - -#include "context.h" -#include "params.h" - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -#define fors_sign SPX_NAMESPACE(fors_sign) -void fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]); - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) -void fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/hash.h b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/hash.h deleted file mode 100644 index ffe815f45d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/hash.h +++ /dev/null @@ -1,37 +0,0 @@ -#ifndef SPX_HASH_H -#define SPX_HASH_H - -#include -#include - -#include "context.h" -#include "params.h" - -#define prf_addr SPX_NAMESPACE(prf_addr) -void prf_addr(unsigned char *out, const spx_ctx *ctx, - const uint32_t addr[8]); - -#define gen_message_random SPX_NAMESPACE(gen_message_random) -void gen_message_random(unsigned char *R, const unsigned char *sk_prf, - const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx); - -#define hash_message SPX_NAMESPACE(hash_message) -void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx); - - -# define SPX_SHA256_ADDR_BYTES 22 - -# define mgf1_256 SPX_NAMESPACE(mgf1_256) -void mgf1_256(unsigned char *out, unsigned long outlen, - const unsigned char *in, unsigned long inlen); - -# define mgf1_512 SPX_NAMESPACE(mgf1_512) -void mgf1_512(unsigned char *out, unsigned long outlen, - const unsigned char *in, unsigned long inlen); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/hash_sha2.c b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/hash_sha2.c deleted file mode 100644 index 3d0085c8c1..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/hash_sha2.c +++ /dev/null @@ -1,219 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "sha2.h" -#include "utils.h" - - - -#define SPX_SHAX_OUTPUT_BYTES SPX_SHA512_OUTPUT_BYTES -#define SPX_SHAX_BLOCK_BYTES SPX_SHA512_BLOCK_BYTES -#define shaX_inc_init sha512_inc_init -#define shaX_inc_blocks sha512_inc_blocks -#define shaX_inc_finalize sha512_inc_finalize -#define shaX sha512 -#define mgf1_X mgf1_512 -#define shaXstate sha512ctx - -/** - * mgf1 function based on the SHA-256 hash function - * Note that inlen should be sufficiently small that it still allows for - * an array to be allocated on the stack. Typically 'in' is merely a seed. - * Outputs outlen number of bytes - */ -void mgf1_256(unsigned char *out, unsigned long outlen, - const unsigned char *in, unsigned long inlen) { - PQCLEAN_VLA(uint8_t, inbuf, inlen + 4); - unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES]; - uint32_t i; - - memcpy(inbuf, in, inlen); - - /* While we can fit in at least another full block of SHA256 output.. */ - for (i = 0; (i + 1)*SPX_SHA256_OUTPUT_BYTES <= outlen; i++) { - u32_to_bytes(inbuf + inlen, i); - sha256(out, inbuf, inlen + 4); - out += SPX_SHA256_OUTPUT_BYTES; - } - /* Until we cannot anymore, and we fill the remainder. */ - if (outlen > i * SPX_SHA256_OUTPUT_BYTES) { - u32_to_bytes(inbuf + inlen, i); - sha256(outbuf, inbuf, inlen + 4); - memcpy(out, outbuf, outlen - i * SPX_SHA256_OUTPUT_BYTES); - } -} - -/* - * mgf1 function based on the SHA-512 hash function - */ -void mgf1_512(unsigned char *out, unsigned long outlen, - const unsigned char *in, unsigned long inlen) { - PQCLEAN_VLA(uint8_t, inbuf, inlen + 4); - unsigned char outbuf[SPX_SHA512_OUTPUT_BYTES]; - uint32_t i; - - memcpy(inbuf, in, inlen); - - /* While we can fit in at least another full block of SHA512 output.. */ - for (i = 0; (i + 1)*SPX_SHA512_OUTPUT_BYTES <= outlen; i++) { - u32_to_bytes(inbuf + inlen, i); - sha512(out, inbuf, inlen + 4); - out += SPX_SHA512_OUTPUT_BYTES; - } - /* Until we cannot anymore, and we fill the remainder. */ - if (outlen > i * SPX_SHA512_OUTPUT_BYTES) { - u32_to_bytes(inbuf + inlen, i); - sha512(outbuf, inbuf, inlen + 4); - memcpy(out, outbuf, outlen - i * SPX_SHA512_OUTPUT_BYTES); - } -} - -/* - * Computes PRF(pk_seed, sk_seed, addr). - */ -void prf_addr(unsigned char *out, const spx_ctx *ctx, - const uint32_t addr[8]) { - sha256ctx sha2_state; - unsigned char buf[SPX_SHA256_ADDR_BYTES + SPX_N]; - unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES]; - - /* Retrieve precomputed state containing pub_seed */ - sha256_inc_ctx_clone(&sha2_state, &ctx->state_seeded); - - /* Remainder: ADDR^c ‖ SK.seed */ - memcpy(buf, addr, SPX_SHA256_ADDR_BYTES); - memcpy(buf + SPX_SHA256_ADDR_BYTES, ctx->sk_seed, SPX_N); - - sha256_inc_finalize(outbuf, &sha2_state, buf, SPX_SHA256_ADDR_BYTES + SPX_N); - - memcpy(out, outbuf, SPX_N); -} - -/** - * Computes the message-dependent randomness R, using a secret seed as a key - * for HMAC, and an optional randomization value prefixed to the message. - * This requires m to have at least SPX_SHAX_BLOCK_BYTES + SPX_N space - * available in front of the pointer, i.e. before the message to use for the - * prefix. This is necessary to prevent having to move the message around (and - * allocate memory for it). - */ -void gen_message_random(unsigned char *R, const unsigned char *sk_prf, - const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx) { - (void)ctx; - - unsigned char buf[SPX_SHAX_BLOCK_BYTES + SPX_SHAX_OUTPUT_BYTES]; - shaXstate state; - int i; - - - /* This implements HMAC-SHA */ - for (i = 0; i < SPX_N; i++) { - buf[i] = 0x36 ^ sk_prf[i]; - } - memset(buf + SPX_N, 0x36, SPX_SHAX_BLOCK_BYTES - SPX_N); - - shaX_inc_init(&state); - shaX_inc_blocks(&state, buf, 1); - - memcpy(buf, optrand, SPX_N); - - /* If optrand + message cannot fill up an entire block */ - if (SPX_N + mlen < SPX_SHAX_BLOCK_BYTES) { - memcpy(buf + SPX_N, m, mlen); - shaX_inc_finalize(buf + SPX_SHAX_BLOCK_BYTES, &state, - buf, mlen + SPX_N); - } - /* Otherwise first fill a block, so that finalize only uses the message */ - else { - memcpy(buf + SPX_N, m, SPX_SHAX_BLOCK_BYTES - SPX_N); - shaX_inc_blocks(&state, buf, 1); - - m += SPX_SHAX_BLOCK_BYTES - SPX_N; - mlen -= SPX_SHAX_BLOCK_BYTES - SPX_N; - shaX_inc_finalize(buf + SPX_SHAX_BLOCK_BYTES, &state, m, mlen); - } - - for (i = 0; i < SPX_N; i++) { - buf[i] = 0x5c ^ sk_prf[i]; - } - memset(buf + SPX_N, 0x5c, SPX_SHAX_BLOCK_BYTES - SPX_N); - - shaX(buf, buf, SPX_SHAX_BLOCK_BYTES + SPX_SHAX_OUTPUT_BYTES); - memcpy(R, buf, SPX_N); -} - -/** - * Computes the message hash using R, the public key, and the message. - * Outputs the message digest and the index of the leaf. The index is split in - * the tree index and the leaf index, for convenient copying to an address. - */ -void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx) { - (void)ctx; -#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) -#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) -#define SPX_LEAF_BITS SPX_TREE_HEIGHT -#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) -#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) - - unsigned char seed[2 * SPX_N + SPX_SHAX_OUTPUT_BYTES]; - - /* Round to nearest multiple of SPX_SHAX_BLOCK_BYTES */ -#define SPX_INBLOCKS (((SPX_N + SPX_PK_BYTES + SPX_SHAX_BLOCK_BYTES - 1) & \ - -SPX_SHAX_BLOCK_BYTES) / SPX_SHAX_BLOCK_BYTES) - unsigned char inbuf[SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES]; - - unsigned char buf[SPX_DGST_BYTES]; - unsigned char *bufp = buf; - shaXstate state; - - shaX_inc_init(&state); - - // seed: SHA-X(R ‖ PK.seed ‖ PK.root ‖ M) - memcpy(inbuf, R, SPX_N); - memcpy(inbuf + SPX_N, pk, SPX_PK_BYTES); - - /* If R + pk + message cannot fill up an entire block */ - if (SPX_N + SPX_PK_BYTES + mlen < SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES) { - memcpy(inbuf + SPX_N + SPX_PK_BYTES, m, mlen); - shaX_inc_finalize(seed + 2 * SPX_N, &state, inbuf, SPX_N + SPX_PK_BYTES + mlen); - } - /* Otherwise first fill a block, so that finalize only uses the message */ - else { - memcpy(inbuf + SPX_N + SPX_PK_BYTES, m, - SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES - SPX_N - SPX_PK_BYTES); - shaX_inc_blocks(&state, inbuf, SPX_INBLOCKS); - - m += SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES - SPX_N - SPX_PK_BYTES; - mlen -= SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES - SPX_N - SPX_PK_BYTES; - shaX_inc_finalize(seed + 2 * SPX_N, &state, m, (size_t)mlen); - } - - // H_msg: MGF1-SHA-X(R ‖ PK.seed ‖ seed) - memcpy(seed, R, SPX_N); - memcpy(seed + SPX_N, pk, SPX_N); - - /* By doing this in two steps, we prevent hashing the message twice; - otherwise each iteration in MGF1 would hash the message again. */ - mgf1_X(bufp, SPX_DGST_BYTES, seed, 2 * SPX_N + SPX_SHAX_OUTPUT_BYTES); - - memcpy(digest, bufp, SPX_FORS_MSG_BYTES); - bufp += SPX_FORS_MSG_BYTES; - - - *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); - *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); - bufp += SPX_TREE_BYTES; - - *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); - *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); -} - - diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/hash_sha2x8.c b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/hash_sha2x8.c deleted file mode 100644 index e04af7a069..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/hash_sha2x8.c +++ /dev/null @@ -1,75 +0,0 @@ -#include -#include - -#include "hash.h" -#include "hashx8.h" - -#include "address.h" -#include "params.h" -#include "sha2.h" -#include "sha256avx.h" -#include "sha256x8.h" -#include "utils.h" - -/* - * 8-way parallel version of prf_addr; takes 8x as much input and output - */ -void prf_addrx8(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7, - const spx_ctx *ctx, - const uint32_t addrx8[8 * 8]) { - unsigned char bufx8[8 * (SPX_N + SPX_SHA256_ADDR_BYTES)]; - unsigned char outbufx8[8 * SPX_SHA256_OUTPUT_BYTES]; - unsigned int j; - - for (j = 0; j < 8; j++) { - memcpy(bufx8 + j * (SPX_N + SPX_SHA256_ADDR_BYTES), - addrx8 + j * 8, SPX_SHA256_ADDR_BYTES); - memcpy( - bufx8 + j * (SPX_N + SPX_SHA256_ADDR_BYTES) + SPX_SHA256_ADDR_BYTES, - ctx->sk_seed, - SPX_N - ); - } - - sha256x8_seeded( - /* out */ - outbufx8 + 0 * SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 1 * SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 2 * SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 3 * SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 4 * SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 5 * SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 6 * SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 7 * SPX_SHA256_OUTPUT_BYTES, - - /* seed */ - &ctx->statex8_seeded, - - /* in */ - bufx8 + 0 * (SPX_SHA256_ADDR_BYTES + SPX_N), - bufx8 + 1 * (SPX_SHA256_ADDR_BYTES + SPX_N), - bufx8 + 2 * (SPX_SHA256_ADDR_BYTES + SPX_N), - bufx8 + 3 * (SPX_SHA256_ADDR_BYTES + SPX_N), - bufx8 + 4 * (SPX_SHA256_ADDR_BYTES + SPX_N), - bufx8 + 5 * (SPX_SHA256_ADDR_BYTES + SPX_N), - bufx8 + 6 * (SPX_SHA256_ADDR_BYTES + SPX_N), - bufx8 + 7 * (SPX_SHA256_ADDR_BYTES + SPX_N), - SPX_SHA256_ADDR_BYTES + SPX_N /* len */ - ); - - memcpy(out0, outbufx8 + 0 * SPX_SHA256_OUTPUT_BYTES, SPX_N); - memcpy(out1, outbufx8 + 1 * SPX_SHA256_OUTPUT_BYTES, SPX_N); - memcpy(out2, outbufx8 + 2 * SPX_SHA256_OUTPUT_BYTES, SPX_N); - memcpy(out3, outbufx8 + 3 * SPX_SHA256_OUTPUT_BYTES, SPX_N); - memcpy(out4, outbufx8 + 4 * SPX_SHA256_OUTPUT_BYTES, SPX_N); - memcpy(out5, outbufx8 + 5 * SPX_SHA256_OUTPUT_BYTES, SPX_N); - memcpy(out6, outbufx8 + 6 * SPX_SHA256_OUTPUT_BYTES, SPX_N); - memcpy(out7, outbufx8 + 7 * SPX_SHA256_OUTPUT_BYTES, SPX_N); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/hashx8.h b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/hashx8.h deleted file mode 100644 index 46503f0a10..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/hashx8.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef SPX_HASHX8_H -#define SPX_HASHX8_H - -#include - -#include "params.h" - -#define prf_addrx8 SPX_NAMESPACE(prf_addrx8) -void prf_addrx8(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7, - const spx_ctx *ctx, - const uint32_t addrx8[8 * 8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/merkle.c b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/merkle.c deleted file mode 100644 index 1f353c8dd8..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/merkle.c +++ /dev/null @@ -1,65 +0,0 @@ -#include -#include - -#include "merkle.h" - -#include "address.h" -#include "params.h" -#include "utils.h" -#include "utilsx8.h" -#include "wots.h" -#include "wotsx8.h" - -/* - * This generates a Merkle signature (WOTS signature followed by the Merkle - * authentication path). - */ -void merkle_sign(uint8_t *sig, unsigned char *root, - const spx_ctx *ctx, - uint32_t wots_addr[8], uint32_t tree_addr[8], - uint32_t idx_leaf) { - unsigned char *auth_path = sig + SPX_WOTS_BYTES; - uint32_t tree_addrx8[8 * 8] = { 0 }; - int j; - struct leaf_info_x8 info = { 0 }; - unsigned steps[ SPX_WOTS_LEN ]; - - info.wots_sig = sig; - chain_lengths(steps, root); - info.wots_steps = steps; - - for (j = 0; j < 8; j++) { - set_type(&tree_addrx8[8 * j], SPX_ADDR_TYPE_HASHTREE); - set_type(&info.leaf_addr[8 * j], SPX_ADDR_TYPE_WOTS); - set_type(&info.pk_addr[8 * j], SPX_ADDR_TYPE_WOTSPK); - copy_subtree_addr(&tree_addrx8[8 * j], tree_addr); - copy_subtree_addr(&info.leaf_addr[8 * j], wots_addr); - copy_subtree_addr(&info.pk_addr[8 * j], wots_addr); - } - - info.wots_sign_leaf = idx_leaf; - - treehashx8(root, auth_path, ctx, - idx_leaf, 0, - SPX_TREE_HEIGHT, - wots_gen_leafx8, - tree_addrx8, &info); -} - -/* Compute root node of the top-most subtree. */ -/* Again, in this file because wots_gen_leaf is most of the work */ -void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { - /* We do not need the auth path in key generation, but it simplifies the - code to have just one treehash routine that computes both root and path - in one function. */ - unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; - uint32_t top_tree_addr[8] = {0}; - uint32_t wots_addr[8] = {0}; - - set_layer_addr(top_tree_addr, SPX_D - 1); - set_layer_addr(wots_addr, SPX_D - 1); - - merkle_sign(auth_path, root, ctx, - wots_addr, top_tree_addr, - ~0U /* ~0 means "don't bother generating an auth path */ ); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/merkle.h b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/merkle.h deleted file mode 100644 index 769cf2e970..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/merkle.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef MERKLE_H_ -#define MERKLE_H_ - -#include - -#include "context.h" -#include "params.h" - -/* Generate a Merkle signature (WOTS signature followed by the Merkle */ -/* authentication path) */ -#define merkle_sign SPX_NAMESPACE(merkle_sign) -void merkle_sign(uint8_t *sig, unsigned char *root, - const spx_ctx *ctx, - uint32_t wots_addr[8], uint32_t tree_addr[8], - uint32_t idx_leaf); - -/* Compute the root node of the top-most subtree. */ -#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) -void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); - -#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/nistapi.h b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/nistapi.h deleted file mode 100644 index 3cb71afad4..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/nistapi.h +++ /dev/null @@ -1,87 +0,0 @@ -#ifndef SPX_API_H -#define SPX_API_H - -#include -#include - -#include "params.h" - -#define CRYPTO_ALGNAME "SPHINCS+" - -#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES -#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES -#define CRYPTO_BYTES SPX_BYTES -#define CRYPTO_SEEDBYTES (3*SPX_N) - -/* - * Returns the length of a secret key, in bytes - */ -#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) -size_t crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) -size_t crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) -size_t crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) -size_t crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) -int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) -int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) -int crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) -int crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -#define crypto_sign SPX_NAMESPACE(crypto_sign) -int crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) -int crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/params.h b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/params.h deleted file mode 100644 index 4d40f55ed9..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/params.h +++ /dev/null @@ -1,61 +0,0 @@ -#ifndef SPX_PARAMS_H -#define SPX_PARAMS_H - -#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSSHA2256FROBUST_AVX2_##s - -/* Hash output length in bytes. */ -#define SPX_N 32 -/* Height of the hypertree. */ -#define SPX_FULL_HEIGHT 68 -/* Number of subtree layer. */ -#define SPX_D 17 -/* FORS tree dimensions. */ -#define SPX_FORS_HEIGHT 9 -#define SPX_FORS_TREES 35 -/* Winternitz parameter, */ -#define SPX_WOTS_W 16 - -/* The hash function is defined by linking a different hash.c file, as opposed - to setting a #define constant. */ - -/* This is a SHA2-based parameter set, hence whether we use SHA-256 - * exclusively or we use both SHA-256 and SHA-512 is controlled by - * the following #define */ -#define SPX_SHA512 1 /* Use SHA-512 for H and T_l, l >= 2 */ - -/* For clarity */ -#define SPX_ADDR_BYTES 32 - -/* WOTS parameters. */ -#define SPX_WOTS_LOGW 4 - -#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) - -/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#define SPX_WOTS_LEN2 3 - -#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) -#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) -#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES - -/* Subtree size. */ -#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) - -//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT -// #error SPX_D should always divide SPX_FULL_HEIGHT -//#endif - -/* FORS parameters. */ -#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) -#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) -#define SPX_FORS_PK_BYTES SPX_N - -/* Resulting SPX sizes. */ -#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ - SPX_FULL_HEIGHT * SPX_N) -#define SPX_PK_BYTES (2 * SPX_N) -#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) - -#include "sha2_offsets.h" - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/sha256avx.c b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/sha256avx.c deleted file mode 100644 index 6bbe6ecc24..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/sha256avx.c +++ /dev/null @@ -1,357 +0,0 @@ -#include -#include -#include - -#include "sha256avx.h" - -static const unsigned int RC[] = { - 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, - 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, - 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, - 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, - 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, - 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, - 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, - 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, - 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, - 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, - 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, - 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, - 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, - 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, - 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, - 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 -}; - -#define u32 uint32_t -#define u256 __m256i - -#define XOR _mm256_xor_si256 -#define OR _mm256_or_si256 -#define AND _mm256_and_si256 -#define ADD32 _mm256_add_epi32 -#define NOT(x) _mm256_xor_si256(x, _mm256_set_epi32(-1, -1, -1, -1, -1, -1, -1, -1)) - -#define LOAD(src) _mm256_loadu_si256((__m256i *)(src)) -#define STORE(dest,src) _mm256_storeu_si256((__m256i *)(dest),src) - -#define BYTESWAP(x) _mm256_shuffle_epi8(x, _mm256_set_epi8(0xc,0xd,0xe,0xf,0x8,0x9,0xa,0xb,0x4,0x5,0x6,0x7,0x0,0x1,0x2,0x3,0xc,0xd,0xe,0xf,0x8,0x9,0xa,0xb,0x4,0x5,0x6,0x7,0x0,0x1,0x2,0x3)) - -#define SHIFTR32(x, y) _mm256_srli_epi32(x, y) -#define SHIFTL32(x, y) _mm256_slli_epi32(x, y) - -#define ROTR32(x, y) OR(SHIFTR32(x, y), SHIFTL32(x, 32 - (y))) -#define ROTL32(x, y) OR(SHIFTL32(x, y), SHIFTR32(x, 32 - (y))) - -#define XOR3(a, b, c) XOR(XOR(a, b), c) - -#define ADD3_32(a, b, c) ADD32(ADD32(a, b), c) -#define ADD4_32(a, b, c, d) ADD32(ADD32(ADD32(a, b), c), d) -#define ADD5_32(a, b, c, d, e) ADD32(ADD32(ADD32(ADD32(a, b), c), d), e) - -#define MAJ_AVX(a, b, c) XOR3(AND(a, b), AND(a, c), AND(b, c)) -#define CH_AVX(a, b, c) XOR(AND(a, b), AND(NOT(a), c)) - -#define SIGMA1_AVX(x) XOR3(ROTR32(x, 6), ROTR32(x, 11), ROTR32(x, 25)) -#define SIGMA0_AVX(x) XOR3(ROTR32(x, 2), ROTR32(x, 13), ROTR32(x, 22)) - -#define WSIGMA1_AVX(x) XOR3(ROTR32(x, 17), ROTR32(x, 19), SHIFTR32(x, 10)) -#define WSIGMA0_AVX(x) XOR3(ROTR32(x, 7), ROTR32(x, 18), SHIFTR32(x, 3)) - -#define SHA256ROUND_AVX(a, b, c, d, e, f, g, h, rc, w) \ - T0 = ADD5_32(h, SIGMA1_AVX(e), CH_AVX(e, f, g), _mm256_set1_epi32((int)RC[rc]), w); \ - (d) = ADD32(d, T0); \ - T1 = ADD32(SIGMA0_AVX(a), MAJ_AVX(a, b, c)); \ - (h) = ADD32(T0, T1); - -// Transpose 8 vectors containing 32-bit values -static void transpose(u256 s[8]) { - u256 tmp0[8]; - u256 tmp1[8]; - tmp0[0] = _mm256_unpacklo_epi32(s[0], s[1]); - tmp0[1] = _mm256_unpackhi_epi32(s[0], s[1]); - tmp0[2] = _mm256_unpacklo_epi32(s[2], s[3]); - tmp0[3] = _mm256_unpackhi_epi32(s[2], s[3]); - tmp0[4] = _mm256_unpacklo_epi32(s[4], s[5]); - tmp0[5] = _mm256_unpackhi_epi32(s[4], s[5]); - tmp0[6] = _mm256_unpacklo_epi32(s[6], s[7]); - tmp0[7] = _mm256_unpackhi_epi32(s[6], s[7]); - tmp1[0] = _mm256_unpacklo_epi64(tmp0[0], tmp0[2]); - tmp1[1] = _mm256_unpackhi_epi64(tmp0[0], tmp0[2]); - tmp1[2] = _mm256_unpacklo_epi64(tmp0[1], tmp0[3]); - tmp1[3] = _mm256_unpackhi_epi64(tmp0[1], tmp0[3]); - tmp1[4] = _mm256_unpacklo_epi64(tmp0[4], tmp0[6]); - tmp1[5] = _mm256_unpackhi_epi64(tmp0[4], tmp0[6]); - tmp1[6] = _mm256_unpacklo_epi64(tmp0[5], tmp0[7]); - tmp1[7] = _mm256_unpackhi_epi64(tmp0[5], tmp0[7]); - s[0] = _mm256_permute2x128_si256(tmp1[0], tmp1[4], 0x20); - s[1] = _mm256_permute2x128_si256(tmp1[1], tmp1[5], 0x20); - s[2] = _mm256_permute2x128_si256(tmp1[2], tmp1[6], 0x20); - s[3] = _mm256_permute2x128_si256(tmp1[3], tmp1[7], 0x20); - s[4] = _mm256_permute2x128_si256(tmp1[0], tmp1[4], 0x31); - s[5] = _mm256_permute2x128_si256(tmp1[1], tmp1[5], 0x31); - s[6] = _mm256_permute2x128_si256(tmp1[2], tmp1[6], 0x31); - s[7] = _mm256_permute2x128_si256(tmp1[3], tmp1[7], 0x31); -} - -void sha256_ctx_clone8x(sha256x8ctx *out, const sha256x8ctx *in) { - memcpy(out, in, sizeof(sha256x8ctx)); -} - -void sha256_init8x(sha256x8ctx *ctx) { - ctx->s[0] = _mm256_set_epi32((int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667); - ctx->s[1] = _mm256_set_epi32((int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85); - ctx->s[2] = _mm256_set_epi32((int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372); - ctx->s[3] = _mm256_set_epi32((int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a); - ctx->s[4] = _mm256_set_epi32((int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f); - ctx->s[5] = _mm256_set_epi32((int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c); - ctx->s[6] = _mm256_set_epi32((int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab); - ctx->s[7] = _mm256_set_epi32((int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19); - - ctx->datalen = 0; - ctx->msglen = 0; -} - -void sha256_final8x(sha256x8ctx *ctx, - unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7) { - unsigned int i, curlen; - - // Padding - if (ctx->datalen < 56) { - for (i = 0; i < 8; ++i) { - curlen = ctx->datalen; - ctx->msgblocks[64 * i + curlen++] = 0x80; - while (curlen < 64) { - ctx->msgblocks[64 * i + curlen++] = 0x00; - } - } - } else { - for (i = 0; i < 8; ++i) { - curlen = ctx->datalen; - ctx->msgblocks[64 * i + curlen++] = 0x80; - while (curlen < 64) { - ctx->msgblocks[64 * i + curlen++] = 0x00; - } - } - sha256_transform8x(ctx, - &ctx->msgblocks[64 * 0], - &ctx->msgblocks[64 * 1], - &ctx->msgblocks[64 * 2], - &ctx->msgblocks[64 * 3], - &ctx->msgblocks[64 * 4], - &ctx->msgblocks[64 * 5], - &ctx->msgblocks[64 * 6], - &ctx->msgblocks[64 * 7] - ); - memset(ctx->msgblocks, 0, 8 * 64); - } - - // Add length of the message to each block - ctx->msglen += ctx->datalen * 8; - for (i = 0; i < 8; i++) { - ctx->msgblocks[64 * i + 63] = (unsigned char)(ctx->msglen); - ctx->msgblocks[64 * i + 62] = (unsigned char)(ctx->msglen >> 8); - ctx->msgblocks[64 * i + 61] = (unsigned char)(ctx->msglen >> 16); - ctx->msgblocks[64 * i + 60] = (unsigned char)(ctx->msglen >> 24); - ctx->msgblocks[64 * i + 59] = (unsigned char)(ctx->msglen >> 32); - ctx->msgblocks[64 * i + 58] = (unsigned char)(ctx->msglen >> 40); - ctx->msgblocks[64 * i + 57] = (unsigned char)(ctx->msglen >> 48); - ctx->msgblocks[64 * i + 56] = (unsigned char)(ctx->msglen >> 56); - } - sha256_transform8x(ctx, - &ctx->msgblocks[64 * 0], - &ctx->msgblocks[64 * 1], - &ctx->msgblocks[64 * 2], - &ctx->msgblocks[64 * 3], - &ctx->msgblocks[64 * 4], - &ctx->msgblocks[64 * 5], - &ctx->msgblocks[64 * 6], - &ctx->msgblocks[64 * 7] - ); - - // Compute final hash output - transpose(ctx->s); - - // Store Hash value - STORE(out0, BYTESWAP(ctx->s[0])); - STORE(out1, BYTESWAP(ctx->s[1])); - STORE(out2, BYTESWAP(ctx->s[2])); - STORE(out3, BYTESWAP(ctx->s[3])); - STORE(out4, BYTESWAP(ctx->s[4])); - STORE(out5, BYTESWAP(ctx->s[5])); - STORE(out6, BYTESWAP(ctx->s[6])); - STORE(out7, BYTESWAP(ctx->s[7])); -} - -void sha256_transform8x(sha256x8ctx *ctx, - const unsigned char *data0, - const unsigned char *data1, - const unsigned char *data2, - const unsigned char *data3, - const unsigned char *data4, - const unsigned char *data5, - const unsigned char *data6, - const unsigned char *data7) { - u256 s[8], w[64], T0, T1; - - // Load words and transform data correctly - w[0] = BYTESWAP(LOAD(data0)); - w[0 + 8] = BYTESWAP(LOAD(data0 + 32)); - w[1] = BYTESWAP(LOAD(data1)); - w[1 + 8] = BYTESWAP(LOAD(data1 + 32)); - w[2] = BYTESWAP(LOAD(data2)); - w[2 + 8] = BYTESWAP(LOAD(data2 + 32)); - w[3] = BYTESWAP(LOAD(data3)); - w[3 + 8] = BYTESWAP(LOAD(data3 + 32)); - w[4] = BYTESWAP(LOAD(data4)); - w[4 + 8] = BYTESWAP(LOAD(data4 + 32)); - w[5] = BYTESWAP(LOAD(data5)); - w[5 + 8] = BYTESWAP(LOAD(data5 + 32)); - w[6] = BYTESWAP(LOAD(data6)); - w[6 + 8] = BYTESWAP(LOAD(data6 + 32)); - w[7] = BYTESWAP(LOAD(data7)); - w[7 + 8] = BYTESWAP(LOAD(data7 + 32)); - - transpose(w); - transpose(w + 8); - - // Initial State - s[0] = ctx->s[0]; - s[1] = ctx->s[1]; - s[2] = ctx->s[2]; - s[3] = ctx->s[3]; - s[4] = ctx->s[4]; - s[5] = ctx->s[5]; - s[6] = ctx->s[6]; - s[7] = ctx->s[7]; - - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 0, w[0]); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 1, w[1]); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 2, w[2]); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 3, w[3]); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 4, w[4]); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 5, w[5]); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 6, w[6]); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 7, w[7]); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 8, w[8]); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 9, w[9]); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 10, w[10]); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 11, w[11]); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 12, w[12]); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 13, w[13]); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 14, w[14]); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 15, w[15]); - w[16] = ADD4_32(WSIGMA1_AVX(w[14]), w[0], w[9], WSIGMA0_AVX(w[1])); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 16, w[16]); - w[17] = ADD4_32(WSIGMA1_AVX(w[15]), w[1], w[10], WSIGMA0_AVX(w[2])); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 17, w[17]); - w[18] = ADD4_32(WSIGMA1_AVX(w[16]), w[2], w[11], WSIGMA0_AVX(w[3])); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 18, w[18]); - w[19] = ADD4_32(WSIGMA1_AVX(w[17]), w[3], w[12], WSIGMA0_AVX(w[4])); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 19, w[19]); - w[20] = ADD4_32(WSIGMA1_AVX(w[18]), w[4], w[13], WSIGMA0_AVX(w[5])); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 20, w[20]); - w[21] = ADD4_32(WSIGMA1_AVX(w[19]), w[5], w[14], WSIGMA0_AVX(w[6])); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 21, w[21]); - w[22] = ADD4_32(WSIGMA1_AVX(w[20]), w[6], w[15], WSIGMA0_AVX(w[7])); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 22, w[22]); - w[23] = ADD4_32(WSIGMA1_AVX(w[21]), w[7], w[16], WSIGMA0_AVX(w[8])); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 23, w[23]); - w[24] = ADD4_32(WSIGMA1_AVX(w[22]), w[8], w[17], WSIGMA0_AVX(w[9])); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 24, w[24]); - w[25] = ADD4_32(WSIGMA1_AVX(w[23]), w[9], w[18], WSIGMA0_AVX(w[10])); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 25, w[25]); - w[26] = ADD4_32(WSIGMA1_AVX(w[24]), w[10], w[19], WSIGMA0_AVX(w[11])); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 26, w[26]); - w[27] = ADD4_32(WSIGMA1_AVX(w[25]), w[11], w[20], WSIGMA0_AVX(w[12])); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 27, w[27]); - w[28] = ADD4_32(WSIGMA1_AVX(w[26]), w[12], w[21], WSIGMA0_AVX(w[13])); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 28, w[28]); - w[29] = ADD4_32(WSIGMA1_AVX(w[27]), w[13], w[22], WSIGMA0_AVX(w[14])); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 29, w[29]); - w[30] = ADD4_32(WSIGMA1_AVX(w[28]), w[14], w[23], WSIGMA0_AVX(w[15])); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 30, w[30]); - w[31] = ADD4_32(WSIGMA1_AVX(w[29]), w[15], w[24], WSIGMA0_AVX(w[16])); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 31, w[31]); - w[32] = ADD4_32(WSIGMA1_AVX(w[30]), w[16], w[25], WSIGMA0_AVX(w[17])); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 32, w[32]); - w[33] = ADD4_32(WSIGMA1_AVX(w[31]), w[17], w[26], WSIGMA0_AVX(w[18])); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 33, w[33]); - w[34] = ADD4_32(WSIGMA1_AVX(w[32]), w[18], w[27], WSIGMA0_AVX(w[19])); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 34, w[34]); - w[35] = ADD4_32(WSIGMA1_AVX(w[33]), w[19], w[28], WSIGMA0_AVX(w[20])); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 35, w[35]); - w[36] = ADD4_32(WSIGMA1_AVX(w[34]), w[20], w[29], WSIGMA0_AVX(w[21])); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 36, w[36]); - w[37] = ADD4_32(WSIGMA1_AVX(w[35]), w[21], w[30], WSIGMA0_AVX(w[22])); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 37, w[37]); - w[38] = ADD4_32(WSIGMA1_AVX(w[36]), w[22], w[31], WSIGMA0_AVX(w[23])); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 38, w[38]); - w[39] = ADD4_32(WSIGMA1_AVX(w[37]), w[23], w[32], WSIGMA0_AVX(w[24])); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 39, w[39]); - w[40] = ADD4_32(WSIGMA1_AVX(w[38]), w[24], w[33], WSIGMA0_AVX(w[25])); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 40, w[40]); - w[41] = ADD4_32(WSIGMA1_AVX(w[39]), w[25], w[34], WSIGMA0_AVX(w[26])); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 41, w[41]); - w[42] = ADD4_32(WSIGMA1_AVX(w[40]), w[26], w[35], WSIGMA0_AVX(w[27])); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 42, w[42]); - w[43] = ADD4_32(WSIGMA1_AVX(w[41]), w[27], w[36], WSIGMA0_AVX(w[28])); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 43, w[43]); - w[44] = ADD4_32(WSIGMA1_AVX(w[42]), w[28], w[37], WSIGMA0_AVX(w[29])); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 44, w[44]); - w[45] = ADD4_32(WSIGMA1_AVX(w[43]), w[29], w[38], WSIGMA0_AVX(w[30])); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 45, w[45]); - w[46] = ADD4_32(WSIGMA1_AVX(w[44]), w[30], w[39], WSIGMA0_AVX(w[31])); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 46, w[46]); - w[47] = ADD4_32(WSIGMA1_AVX(w[45]), w[31], w[40], WSIGMA0_AVX(w[32])); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 47, w[47]); - w[48] = ADD4_32(WSIGMA1_AVX(w[46]), w[32], w[41], WSIGMA0_AVX(w[33])); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 48, w[48]); - w[49] = ADD4_32(WSIGMA1_AVX(w[47]), w[33], w[42], WSIGMA0_AVX(w[34])); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 49, w[49]); - w[50] = ADD4_32(WSIGMA1_AVX(w[48]), w[34], w[43], WSIGMA0_AVX(w[35])); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 50, w[50]); - w[51] = ADD4_32(WSIGMA1_AVX(w[49]), w[35], w[44], WSIGMA0_AVX(w[36])); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 51, w[51]); - w[52] = ADD4_32(WSIGMA1_AVX(w[50]), w[36], w[45], WSIGMA0_AVX(w[37])); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 52, w[52]); - w[53] = ADD4_32(WSIGMA1_AVX(w[51]), w[37], w[46], WSIGMA0_AVX(w[38])); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 53, w[53]); - w[54] = ADD4_32(WSIGMA1_AVX(w[52]), w[38], w[47], WSIGMA0_AVX(w[39])); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 54, w[54]); - w[55] = ADD4_32(WSIGMA1_AVX(w[53]), w[39], w[48], WSIGMA0_AVX(w[40])); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 55, w[55]); - w[56] = ADD4_32(WSIGMA1_AVX(w[54]), w[40], w[49], WSIGMA0_AVX(w[41])); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 56, w[56]); - w[57] = ADD4_32(WSIGMA1_AVX(w[55]), w[41], w[50], WSIGMA0_AVX(w[42])); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 57, w[57]); - w[58] = ADD4_32(WSIGMA1_AVX(w[56]), w[42], w[51], WSIGMA0_AVX(w[43])); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 58, w[58]); - w[59] = ADD4_32(WSIGMA1_AVX(w[57]), w[43], w[52], WSIGMA0_AVX(w[44])); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 59, w[59]); - w[60] = ADD4_32(WSIGMA1_AVX(w[58]), w[44], w[53], WSIGMA0_AVX(w[45])); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 60, w[60]); - w[61] = ADD4_32(WSIGMA1_AVX(w[59]), w[45], w[54], WSIGMA0_AVX(w[46])); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 61, w[61]); - w[62] = ADD4_32(WSIGMA1_AVX(w[60]), w[46], w[55], WSIGMA0_AVX(w[47])); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 62, w[62]); - w[63] = ADD4_32(WSIGMA1_AVX(w[61]), w[47], w[56], WSIGMA0_AVX(w[48])); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 63, w[63]); - - // Feed Forward - ctx->s[0] = ADD32(s[0], ctx->s[0]); - ctx->s[1] = ADD32(s[1], ctx->s[1]); - ctx->s[2] = ADD32(s[2], ctx->s[2]); - ctx->s[3] = ADD32(s[3], ctx->s[3]); - ctx->s[4] = ADD32(s[4], ctx->s[4]); - ctx->s[5] = ADD32(s[5], ctx->s[5]); - ctx->s[6] = ADD32(s[6], ctx->s[6]); - ctx->s[7] = ADD32(s[7], ctx->s[7]); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/sha256avx.h b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/sha256avx.h deleted file mode 100644 index 1e3bcf889b..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/sha256avx.h +++ /dev/null @@ -1,44 +0,0 @@ -#ifndef SHA256AVX_H -#define SHA256AVX_H - -#include -#include - -#include "params.h" - -typedef struct SHA256state { - __m256i s[8]; - unsigned char msgblocks[8 * 64]; - unsigned int datalen; - unsigned long long msglen; -} sha256x8ctx; - -#define sha256_ctx_clone8x SPX_NAMESPACE(sha256_ctx_clone8x) -void sha256_ctx_clone8x(sha256x8ctx *out, const sha256x8ctx *in); - -#define sha256_init8x SPX_NAMESPACE(sha256_init8x) -void sha256_init8x(sha256x8ctx *ctx); - -#define sha256_final8x SPX_NAMESPACE(sha256_final8x) -void sha256_final8x(sha256x8ctx *ctx, - unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7); - -#define sha256_transform8x SPX_NAMESPACE(sha256_transform8x) -void sha256_transform8x(sha256x8ctx *ctx, - const unsigned char *data0, - const unsigned char *data1, - const unsigned char *data2, - const unsigned char *data3, - const unsigned char *data4, - const unsigned char *data5, - const unsigned char *data6, - const unsigned char *data7); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/sha256x8.c b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/sha256x8.c deleted file mode 100644 index d97750c09b..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/sha256x8.c +++ /dev/null @@ -1,185 +0,0 @@ -#include - -#include "sha256avx.h" -#include "sha256x8.h" -#include "utils.h" - -// Performs sha256x8 on an initialized (and perhaps seeded) state. -static void _sha256x8( - sha256x8ctx *ctx, - unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - const unsigned char *in4, - const unsigned char *in5, - const unsigned char *in6, - const unsigned char *in7, unsigned long long inlen) { - unsigned long long i = 0; - while (inlen - i >= 64) { - sha256_transform8x(ctx, - in0 + i, - in1 + i, - in2 + i, - in3 + i, - in4 + i, - in5 + i, - in6 + i, - in7 + i - ); - i += 64; - ctx->msglen += 512; - } - - size_t bytes_to_copy = (size_t)(inlen - i); - memcpy(&ctx->msgblocks[64 * 0], in0 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64 * 1], in1 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64 * 2], in2 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64 * 3], in3 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64 * 4], in4 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64 * 5], in5 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64 * 6], in6 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64 * 7], in7 + i, bytes_to_copy); - ctx->datalen = (unsigned int)bytes_to_copy; - - sha256_final8x(ctx, out0, out1, out2, out3, out4, out5, out6, out7); -} - -void sha256x8_seeded( - unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7, - const sha256x8ctx *seed, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - const unsigned char *in4, - const unsigned char *in5, - const unsigned char *in6, - const unsigned char *in7, unsigned long long inlen) { - - sha256x8ctx ctx; - sha256_ctx_clone8x(&ctx, seed); - - _sha256x8(&ctx, out0, out1, out2, out3, out4, out5, out6, out7, - in0, in1, in2, in3, in4, in5, in6, in7, inlen); -} - -/* This provides a wrapper around the internals of 8x parallel SHA256 */ -void sha256x8(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - const unsigned char *in4, - const unsigned char *in5, - const unsigned char *in6, - const unsigned char *in7, unsigned long long inlen) { - sha256x8ctx ctx; - sha256_init8x(&ctx); - - _sha256x8(&ctx, out0, out1, out2, out3, out4, out5, out6, out7, - in0, in1, in2, in3, in4, in5, in6, in7, inlen); -} - -/** - * Note that inlen should be sufficiently small that it still allows for - * an array to be allocated on the stack. Typically 'in' is merely a seed. - * Outputs outlen number of bytes - */ -void mgf1x8(unsigned char *outx8, unsigned long outlen, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - const unsigned char *in4, - const unsigned char *in5, - const unsigned char *in6, - const unsigned char *in7, - unsigned long inlen) { - PQCLEAN_VLA(unsigned char, inbufx8, 8 * (inlen + 4)); - unsigned char outbufx8[8 * SPX_SHA256_OUTPUT_BYTES]; - uint32_t i; - unsigned int j; - - memcpy(inbufx8 + 0 * (inlen + 4), in0, inlen); - memcpy(inbufx8 + 1 * (inlen + 4), in1, inlen); - memcpy(inbufx8 + 2 * (inlen + 4), in2, inlen); - memcpy(inbufx8 + 3 * (inlen + 4), in3, inlen); - memcpy(inbufx8 + 4 * (inlen + 4), in4, inlen); - memcpy(inbufx8 + 5 * (inlen + 4), in5, inlen); - memcpy(inbufx8 + 6 * (inlen + 4), in6, inlen); - memcpy(inbufx8 + 7 * (inlen + 4), in7, inlen); - - /* While we can fit in at least another full block of SHA256 output.. */ - for (i = 0; (i + 1)*SPX_SHA256_OUTPUT_BYTES <= outlen; i++) { - for (j = 0; j < 8; j++) { - u32_to_bytes(inbufx8 + inlen + j * (inlen + 4), i); - } - - sha256x8(outx8 + 0 * outlen, - outx8 + 1 * outlen, - outx8 + 2 * outlen, - outx8 + 3 * outlen, - outx8 + 4 * outlen, - outx8 + 5 * outlen, - outx8 + 6 * outlen, - outx8 + 7 * outlen, - inbufx8 + 0 * (inlen + 4), - inbufx8 + 1 * (inlen + 4), - inbufx8 + 2 * (inlen + 4), - inbufx8 + 3 * (inlen + 4), - inbufx8 + 4 * (inlen + 4), - inbufx8 + 5 * (inlen + 4), - inbufx8 + 6 * (inlen + 4), - inbufx8 + 7 * (inlen + 4), inlen + 4); - outx8 += SPX_SHA256_OUTPUT_BYTES; - } - /* Until we cannot anymore, and we fill the remainder. */ - for (j = 0; j < 8; j++) { - u32_to_bytes(inbufx8 + inlen + j * (inlen + 4), i); - } - sha256x8(outbufx8 + 0 * SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 1 * SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 2 * SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 3 * SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 4 * SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 5 * SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 6 * SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 7 * SPX_SHA256_OUTPUT_BYTES, - inbufx8 + 0 * (inlen + 4), - inbufx8 + 1 * (inlen + 4), - inbufx8 + 2 * (inlen + 4), - inbufx8 + 3 * (inlen + 4), - inbufx8 + 4 * (inlen + 4), - inbufx8 + 5 * (inlen + 4), - inbufx8 + 6 * (inlen + 4), - inbufx8 + 7 * (inlen + 4), inlen + 4); - - for (j = 0; j < 8; j++) { - memcpy(outx8 + j * outlen, - outbufx8 + j * SPX_SHA256_OUTPUT_BYTES, - outlen - i * SPX_SHA256_OUTPUT_BYTES); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/sha256x8.h b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/sha256x8.h deleted file mode 100644 index 4f7330a6c1..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/sha256x8.h +++ /dev/null @@ -1,64 +0,0 @@ -#ifndef SPX_SHA256X8_H -#define SPX_SHA256X8_H - -#include "params.h" -#include "sha256avx.h" - - - -#define sha256x8_seeded SPX_NAMESPACE(sha256x8_seeded) -void sha256x8_seeded( - unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7, - const sha256x8ctx *seed, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - const unsigned char *in4, - const unsigned char *in5, - const unsigned char *in6, - const unsigned char *in7, unsigned long long inlen); - -/* This provides a wrapper around the internals of 8x parallel SHA256 */ -#define sha256x8 SPX_NAMESPACE(sha256x8) -void sha256x8(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - const unsigned char *in4, - const unsigned char *in5, - const unsigned char *in6, - const unsigned char *in7, unsigned long long inlen); - -/** - * Note that inlen should be sufficiently small that it still allows for - * an array to be allocated on the stack. Typically 'in' is merely a seed. - * Outputs outlen number of bytes - */ -#define mgf1x8 SPX_NAMESPACE(mgf1x8) -void mgf1x8(unsigned char *outx8, unsigned long outlen, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - const unsigned char *in4, - const unsigned char *in5, - const unsigned char *in6, - const unsigned char *in7, - unsigned long inlen); -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/sha2_offsets.h b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/sha2_offsets.h deleted file mode 100644 index 6e3584f7a4..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/sha2_offsets.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef SHA2_OFFSETS_H_ -#define SHA2_OFFSETS_H_ - -#define SPX_SHA256_BLOCK_BYTES 64 -#define SPX_SHA256_OUTPUT_BYTES 32 - -#define SPX_SHA512_BLOCK_BYTES 128 -#define SPX_SHA512_OUTPUT_BYTES 64 - -/* - * Offsets of various fields in the address structure when we use SHA2 as - * the Sphincs+ hash function - */ - -#define SPX_OFFSET_LAYER 0 /* The byte used to specify the Merkle tree layer */ -#define SPX_OFFSET_TREE 1 /* The start of the 8 byte field used to specify the tree */ -#define SPX_OFFSET_TYPE 9 /* The byte used to specify the hash type (reason) */ -#define SPX_OFFSET_KP_ADDR2 12 /* The high byte used to specify the key pair (which one-time signature) */ -#define SPX_OFFSET_KP_ADDR1 13 /* The low byte used to specify the key pair */ -#define SPX_OFFSET_CHAIN_ADDR 17 /* The byte used to specify the chain address (which Winternitz chain) */ -#define SPX_OFFSET_HASH_ADDR 21 /* The byte used to specify the hash address (where in the Winternitz chain) */ -#define SPX_OFFSET_TREE_HGT 17 /* The byte used to specify the height of this node in the FORS or Merkle tree */ -#define SPX_OFFSET_TREE_INDEX 18 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ - -#define SPX_SHA2 1 - -#endif /* SHA2_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/sha512x4.c b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/sha512x4.c deleted file mode 100644 index 8d33deffdd..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/sha512x4.c +++ /dev/null @@ -1,446 +0,0 @@ -#include -#include -#include - -/* pull in the entire thing */ -#include "sha512x4.h" -#include "utils.h" - -typedef uint64_t u64; -typedef __m256i u256; - -#define BYTESWAP(x) _mm256_shuffle_epi8(x, _mm256_set_epi8(0x8,0x9,0xa,0xb,0xc,0xd,0xe,0xf,0x0,0x1,0x2,0x3,0x4,0x5,0x6,0x7,0x8,0x9,0xa,0xb,0xc,0xd,0xe,0xf,0x0,0x1,0x2,0x3,0x4,0x5,0x6,0x7)) -#define STORE(dest,src) _mm256_storeu_si256((__m256i *)(dest),src) - -// Transpose 4 vectors containing 64-bit values -// That is, it rearranges the array: -// A B C D -// E F G H -// I J K L -// M N O P -// into -// A E I M -// B F J N -// C G K O -// D H L P -// where each letter stands for 64 bits (and lsbits on the left) -static void transpose(u256 s[4]) { - u256 tmp[4]; - tmp[0] = _mm256_unpacklo_epi64(s[0], s[1]); - tmp[1] = _mm256_unpackhi_epi64(s[0], s[1]); - tmp[2] = _mm256_unpacklo_epi64(s[2], s[3]); - tmp[3] = _mm256_unpackhi_epi64(s[2], s[3]); - // tmp is in the order of - // A E C G - // B F D H - // I M K O - // J N L P - s[0] = _mm256_permute2x128_si256(tmp[0], tmp[2], 0x20); - s[1] = _mm256_permute2x128_si256(tmp[1], tmp[3], 0x20); - s[2] = _mm256_permute2x128_si256(tmp[0], tmp[2], 0x31); - s[3] = _mm256_permute2x128_si256(tmp[1], tmp[3], 0x31); -} - - -void sha512_init4x(sha512x4ctx *ctx) { -#define SET4(x) _mm256_set_epi64x((long long)(x), (long long)(x), (long long)(x), (long long)(x)) - ctx->s[0] = SET4(0x6a09e667f3bcc908ULL); - ctx->s[1] = SET4(0xbb67ae8584caa73bULL); - ctx->s[2] = SET4(0x3c6ef372fe94f82bULL); - ctx->s[3] = SET4(0xa54ff53a5f1d36f1ULL); - ctx->s[4] = SET4(0x510e527fade682d1ULL); - ctx->s[5] = SET4(0x9b05688c2b3e6c1fULL); - ctx->s[6] = SET4(0x1f83d9abfb41bd6bULL); - ctx->s[7] = SET4(0x5be0cd19137e2179ULL); -#undef SET4 - - ctx->datalen = 0; - ctx->msglen = 0; -} - -#define XOR _mm256_xor_si256 -#define OR _mm256_or_si256 -#define AND _mm256_and_si256 -#define ADD64 _mm256_add_epi64 - -#define LOAD(src) _mm256_loadu_si256((__m256i *)(src)) - -#define SHIFTR64(x, y) _mm256_srli_epi64(x, y) -#define SHIFTL64(x, y) _mm256_slli_epi64(x, y) - -#define ROTR64(x, y) OR(SHIFTR64(x, y), SHIFTL64(x, 64 - (y))) - -static u256 XOR3(u256 a, u256 b, u256 c) { - return XOR(XOR(a, b), c); -} - -#define ADD3_64(a, b, c) ADD64(ADD64(a, b), c) -#define ADD4_64(a, b, c, d) ADD64(ADD64(ADD64(a, b), c), d) -#define ADD5_64(a, b, c, d, e) ADD64(ADD64(ADD64(ADD64(a, b), c), d), e) - -static u256 MAJ_AVX(u256 a, u256 b, u256 c) { - return XOR(c, AND(XOR(a, c), XOR(b, c))); -} -static u256 CH_AVX(u256 a, u256 b, u256 c) { - return XOR(c, AND(a, XOR(b, c))); -} -static u256 SIGMA0_AVX(u256 x) { - return XOR3(ROTR64(x, 28), ROTR64(x, 34), ROTR64(x, 39)); -} -static u256 SIGMA1_AVX(u256 x) { - return XOR3(ROTR64(x, 14), ROTR64(x, 18), ROTR64(x, 41)); -} -static u256 GAMMA0_AVX(u256 x) { - return XOR3(ROTR64(x, 1), ROTR64(x, 8), SHIFTR64(x, 7)); -} -static u256 GAMMA1_AVX(u256 x) { - return XOR3(ROTR64(x, 19), ROTR64(x, 61), SHIFTR64(x, 6)); -} - -#define SHA512ROUND_AVX(a, b, c, d, e, f, g, h, rc, w) \ - T0 = ADD5_64(h, w, SIGMA1_AVX(e), CH_AVX(e, f, g), _mm256_set1_epi64x((long long)RC[rc])); \ - T1 = ADD64(SIGMA0_AVX(a), MAJ_AVX(a, b, c)); \ - (d) = ADD64(d, T0); \ - (h) = ADD64(T0, T1); - -static const unsigned long long RC[80] = { - 0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL, - 0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL, - 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL, - 0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL, - 0xd807aa98a3030242ULL, 0x12835b0145706fbeULL, - 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL, - 0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL, - 0x9bdc06a725c71235ULL, 0xc19bf174cf692694ULL, - 0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL, - 0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL, - 0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL, - 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL, - 0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL, - 0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL, - 0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL, - 0x06ca6351e003826fULL, 0x142929670a0e6e70ULL, - 0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL, - 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL, - 0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL, - 0x81c2c92e47edaee6ULL, 0x92722c851482353bULL, - 0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL, - 0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL, - 0xd192e819d6ef5218ULL, 0xd69906245565a910ULL, - 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL, - 0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL, - 0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL, - 0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL, - 0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL, - 0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL, - 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL, - 0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL, - 0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL, - 0xca273eceea26619cULL, 0xd186b8c721c0c207ULL, - 0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL, - 0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL, - 0x113f9804bef90daeULL, 0x1b710b35131c471bULL, - 0x28db77f523047d84ULL, 0x32caab7b40c72493ULL, - 0x3c9ebe0a15c9bebcULL, 0x431d67c49c100d4cULL, - 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL, - 0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL, -}; - -void sha512_transform4x( - sha512x4ctx *ctx, - const unsigned char *d0, - const unsigned char *d1, - const unsigned char *d2, - const unsigned char *d3) { - u256 s0, s1, s2, s3, s4, s5, s6, s7, w[16], T0, T1, nw; - - // Load words and transform data correctly - w[0 ] = BYTESWAP(LOAD(d0 )); - w[0 + 4] = BYTESWAP(LOAD(d0 + 32)); - w[0 + 8] = BYTESWAP(LOAD(d0 + 64)); - w[0 + 12] = BYTESWAP(LOAD(d0 + 96)); - - w[1 ] = BYTESWAP(LOAD(d1 )); - w[1 + 4] = BYTESWAP(LOAD(d1 + 32)); - w[1 + 8] = BYTESWAP(LOAD(d1 + 64)); - w[1 + 12] = BYTESWAP(LOAD(d1 + 96)); - - w[2 ] = BYTESWAP(LOAD(d2 )); - w[2 + 4] = BYTESWAP(LOAD(d2 + 32)); - w[2 + 8] = BYTESWAP(LOAD(d2 + 64)); - w[2 + 12] = BYTESWAP(LOAD(d2 + 96)); - - w[3 ] = BYTESWAP(LOAD(d3 )); - w[3 + 4] = BYTESWAP(LOAD(d3 + 32)); - w[3 + 8] = BYTESWAP(LOAD(d3 + 64)); - w[3 + 12] = BYTESWAP(LOAD(d3 + 96)); - - transpose(w); - transpose(w + 4); - transpose(w + 8); - transpose(w + 12); - - // Initial State - s0 = ctx->s[0]; - s1 = ctx->s[1]; - s2 = ctx->s[2]; - s3 = ctx->s[3]; - s4 = ctx->s[4]; - s5 = ctx->s[5]; - s6 = ctx->s[6]; - s7 = ctx->s[7]; - - // The first 16 rounds (where the w inputs are directly from the data) - SHA512ROUND_AVX(s0, s1, s2, s3, s4, s5, s6, s7, 0, w[0]); - SHA512ROUND_AVX(s7, s0, s1, s2, s3, s4, s5, s6, 1, w[1]); - SHA512ROUND_AVX(s6, s7, s0, s1, s2, s3, s4, s5, 2, w[2]); - SHA512ROUND_AVX(s5, s6, s7, s0, s1, s2, s3, s4, 3, w[3]); - SHA512ROUND_AVX(s4, s5, s6, s7, s0, s1, s2, s3, 4, w[4]); - SHA512ROUND_AVX(s3, s4, s5, s6, s7, s0, s1, s2, 5, w[5]); - SHA512ROUND_AVX(s2, s3, s4, s5, s6, s7, s0, s1, 6, w[6]); - SHA512ROUND_AVX(s1, s2, s3, s4, s5, s6, s7, s0, 7, w[7]); - SHA512ROUND_AVX(s0, s1, s2, s3, s4, s5, s6, s7, 8, w[8]); - SHA512ROUND_AVX(s7, s0, s1, s2, s3, s4, s5, s6, 9, w[9]); - SHA512ROUND_AVX(s6, s7, s0, s1, s2, s3, s4, s5, 10, w[10]); - SHA512ROUND_AVX(s5, s6, s7, s0, s1, s2, s3, s4, 11, w[11]); - SHA512ROUND_AVX(s4, s5, s6, s7, s0, s1, s2, s3, 12, w[12]); - SHA512ROUND_AVX(s3, s4, s5, s6, s7, s0, s1, s2, 13, w[13]); - SHA512ROUND_AVX(s2, s3, s4, s5, s6, s7, s0, s1, 14, w[14]); - SHA512ROUND_AVX(s1, s2, s3, s4, s5, s6, s7, s0, 15, w[15]); - -#define M(i) (((i)+16) & 0xf) -#define NextW(i) \ - w[M(i)] = ADD4_64(GAMMA1_AVX(w[M((i)-2)]), w[M((i)-7)], GAMMA0_AVX(w[M((i)-15)]), w[M((i)-16)]); - - // The remaining 64 rounds (where the w inputs are a linear fix of the data) - for (unsigned i = 16; i < 80; i += 16) { - nw = NextW(0); - SHA512ROUND_AVX(s0, s1, s2, s3, s4, s5, s6, s7, i + 0, nw); - nw = NextW(1); - SHA512ROUND_AVX(s7, s0, s1, s2, s3, s4, s5, s6, i + 1, nw); - nw = NextW(2); - SHA512ROUND_AVX(s6, s7, s0, s1, s2, s3, s4, s5, i + 2, nw); - nw = NextW(3); - SHA512ROUND_AVX(s5, s6, s7, s0, s1, s2, s3, s4, i + 3, nw); - nw = NextW(4); - SHA512ROUND_AVX(s4, s5, s6, s7, s0, s1, s2, s3, i + 4, nw); - nw = NextW(5); - SHA512ROUND_AVX(s3, s4, s5, s6, s7, s0, s1, s2, i + 5, nw); - nw = NextW(6); - SHA512ROUND_AVX(s2, s3, s4, s5, s6, s7, s0, s1, i + 6, nw); - nw = NextW(7); - SHA512ROUND_AVX(s1, s2, s3, s4, s5, s6, s7, s0, i + 7, nw); - nw = NextW(8); - SHA512ROUND_AVX(s0, s1, s2, s3, s4, s5, s6, s7, i + 8, nw); - nw = NextW(9); - SHA512ROUND_AVX(s7, s0, s1, s2, s3, s4, s5, s6, i + 9, nw); - nw = NextW(10); - SHA512ROUND_AVX(s6, s7, s0, s1, s2, s3, s4, s5, i + 10, nw); - nw = NextW(11); - SHA512ROUND_AVX(s5, s6, s7, s0, s1, s2, s3, s4, i + 11, nw); - nw = NextW(12); - SHA512ROUND_AVX(s4, s5, s6, s7, s0, s1, s2, s3, i + 12, nw); - nw = NextW(13); - SHA512ROUND_AVX(s3, s4, s5, s6, s7, s0, s1, s2, i + 13, nw); - nw = NextW(14); - SHA512ROUND_AVX(s2, s3, s4, s5, s6, s7, s0, s1, i + 14, nw); - nw = NextW(15); - SHA512ROUND_AVX(s1, s2, s3, s4, s5, s6, s7, s0, i + 15, nw); - } - - // Feed Forward - ctx->s[0] = ADD64(s0, ctx->s[0]); - ctx->s[1] = ADD64(s1, ctx->s[1]); - ctx->s[2] = ADD64(s2, ctx->s[2]); - ctx->s[3] = ADD64(s3, ctx->s[3]); - ctx->s[4] = ADD64(s4, ctx->s[4]); - ctx->s[5] = ADD64(s5, ctx->s[5]); - ctx->s[6] = ADD64(s6, ctx->s[6]); - ctx->s[7] = ADD64(s7, ctx->s[7]); -} - -static void _sha512x4( - sha512x4ctx *ctx, - unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - unsigned long long inlen) { - unsigned int i = 0; - - while (inlen - i >= 128) { - sha512_transform4x( - ctx, - in0 + i, - in1 + i, - in2 + i, - in3 + i - ); - ctx->msglen += 1024; - i += 128; - } - - ctx->datalen = (unsigned int)(inlen - i); - memcpy(&ctx->msgblocks[128 * 0], in0 + i, ctx->datalen); - memcpy(&ctx->msgblocks[128 * 1], in1 + i, ctx->datalen); - memcpy(&ctx->msgblocks[128 * 2], in2 + i, ctx->datalen); - memcpy(&ctx->msgblocks[128 * 3], in3 + i, ctx->datalen); - - // Padding - unsigned long curlen; - if (ctx->datalen < 112) { - for (i = 0; i < 4; ++i) { - curlen = ctx->datalen; - ctx->msgblocks[128 * i + curlen++] = 0x80; - while (curlen < 128) { - ctx->msgblocks[128 * i + curlen++] = 0x00; - } - } - } else { - for (i = 0; i < 4; ++i) { - curlen = ctx->datalen; - ctx->msgblocks[128 * i + curlen++] = 0x80; - while (curlen < 128) { - ctx->msgblocks[128 * i + curlen++] = 0x00; - } - } - sha512_transform4x( - ctx, - ctx->msgblocks, - ctx->msgblocks + 128, - ctx->msgblocks + 256, - ctx->msgblocks + 384 - ); - memset(ctx->msgblocks, 0, 4 * 128); - } - - // Add length of the message to each block - ctx->msglen += (unsigned long long)(ctx->datalen) * 8; - for (i = 0; i < 4; i++) { - ctx->msgblocks[128 * i + 127] = (unsigned char)(ctx->msglen); - ctx->msgblocks[128 * i + 126] = (unsigned char)(ctx->msglen >> 8); - ctx->msgblocks[128 * i + 125] = (unsigned char)(ctx->msglen >> 16); - ctx->msgblocks[128 * i + 124] = (unsigned char)(ctx->msglen >> 24); - ctx->msgblocks[128 * i + 123] = (unsigned char)(ctx->msglen >> 32); - ctx->msgblocks[128 * i + 122] = (unsigned char)(ctx->msglen >> 40); - ctx->msgblocks[128 * i + 121] = (unsigned char)(ctx->msglen >> 48); - ctx->msgblocks[128 * i + 120] = (unsigned char)(ctx->msglen >> 56); - memset( &ctx->msgblocks[128 * i + 112], 0, 8 ); - } - sha512_transform4x( - ctx, - ctx->msgblocks, - ctx->msgblocks + 128, - ctx->msgblocks + 256, - ctx->msgblocks + 384 - ); - - // Compute final hash output - transpose(ctx->s); - transpose(ctx->s + 4); - - // Store Hash value - __m256i out[2]; - STORE(out, BYTESWAP(ctx->s[0])); - STORE(out + 1, BYTESWAP(ctx->s[4])); - memcpy(out0, out, 64); - - STORE(out, BYTESWAP(ctx->s[1])); - STORE(out + 1, BYTESWAP(ctx->s[5])); - memcpy(out1, out, 64); - - STORE(out, BYTESWAP(ctx->s[2])); - STORE(out + 1, BYTESWAP(ctx->s[6])); - memcpy(out2, out, 64); - - STORE(out, BYTESWAP(ctx->s[3])); - STORE(out + 1, BYTESWAP(ctx->s[7])); - memcpy(out3, out, 64); -} - - -/** - * Note that inlen should be sufficiently small that it still allows for - * an array to be allocated on the stack. Typically 'in' is merely a seed. - * Outputs outlen number of bytes - */ -void mgf1x4_512(unsigned char *outx4, unsigned long outlen, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - unsigned long inlen) { - PQCLEAN_VLA(unsigned char, inbufx4, 4 * (inlen + 4)); - unsigned char outbuf[4 * 64]; - uint32_t i; - unsigned int j; - - memcpy(inbufx4 + 0 * (inlen + 4), in0, inlen); - memcpy(inbufx4 + 1 * (inlen + 4), in1, inlen); - memcpy(inbufx4 + 2 * (inlen + 4), in2, inlen); - memcpy(inbufx4 + 3 * (inlen + 4), in3, inlen); - - /* While we can fit in at least another full block of SHA512 output.. */ - unsigned long remaining = outlen; - for (i = 0; remaining > 0; i++) { - unsigned long this_step = SPX_SHA512_OUTPUT_BYTES; - if (this_step > remaining) { - this_step = remaining; - } - remaining -= this_step; - for (j = 0; j < 4; j++) { - u32_to_bytes(inbufx4 + inlen + j * (inlen + 4), i); - } - - sha512x4ctx ctx; - sha512_init4x(&ctx); - - _sha512x4( - &ctx, - outbuf + 0 * 64, - outbuf + 1 * 64, - outbuf + 2 * 64, - outbuf + 3 * 64, - inbufx4 + 0 * (inlen + 4), - inbufx4 + 1 * (inlen + 4), - inbufx4 + 2 * (inlen + 4), - inbufx4 + 3 * (inlen + 4), - inlen + 4 - ); - - memcpy(outx4 + 0 * outlen, outbuf + 0 * 64, this_step); - memcpy(outx4 + 1 * outlen, outbuf + 1 * 64, this_step); - memcpy(outx4 + 2 * outlen, outbuf + 2 * 64, this_step); - memcpy(outx4 + 3 * outlen, outbuf + 3 * 64, this_step); - outx4 += this_step; - } -} - -void sha512x4_seeded( - unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const sha512x4ctx *seed, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - unsigned long long inlen) { - sha512x4ctx ctx; - sha512_ctx_clone4x(&ctx, seed); - _sha512x4( - &ctx, - out0, out1, out2, out3, - in0, in1, in2, in3, - inlen - ); -} - -void sha512_ctx_clone4x(sha512x4ctx *out, const sha512x4ctx *in) { - memcpy(out, in, sizeof(sha512x4ctx)); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/sha512x4.h b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/sha512x4.h deleted file mode 100644 index 9bbe736514..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/sha512x4.h +++ /dev/null @@ -1,58 +0,0 @@ -#ifndef SHA512AVX_H -#define SHA512AVX_H - -#include -#include - - -#include "params.h" - -typedef struct SHA512state4x { - __m256i s[8]; - unsigned char msgblocks[4 * 128]; - unsigned int datalen; - unsigned long long msglen; -} sha512x4ctx; - -#define sha512_init4x SPX_NAMESPACE(sha512_init4x) -void sha512_init4x(sha512x4ctx *ctx); - -#define sha512_transform4x SPX_NAMESPACE(sha512_transform4x) -void sha512_transform4x( - sha512x4ctx *ctx, - const unsigned char *d0, - const unsigned char *d1, - const unsigned char *d2, - const unsigned char *d3); - - -#define sha512x4_seeded SPX_NAMESPACE(sha512x4_seeded) -void sha512x4_seeded( - unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const sha512x4ctx *seed, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - unsigned long long inlen); - -#define sha512_ctx_clone4x SPX_NAMESPACE(sha512_ctx_clone4x) -void sha512_ctx_clone4x(sha512x4ctx *out, const sha512x4ctx *in); - -/** - * Note that inlen should be sufficiently small that it still allows for - * an array to be allocated on the stack. Typically 'in' is merely a seed. - * Outputs outlen number of bytes - */ -#define mgf1x4_512 SPX_NAMESPACE(mgf1x4_512) -void mgf1x4_512(unsigned char *outx4, unsigned long outlen, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - unsigned long inlen); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/sign.c b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/sign.c deleted file mode 100644 index 9d0c7d1b22..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/sign.c +++ /dev/null @@ -1,286 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "context.h" -#include "fors.h" -#include "hash.h" -#include "merkle.h" -#include "nistapi.h" -#include "params.h" -#include "randombytes.h" -#include "thash.h" -#include "utils.h" -#include "wots.h" - -/* - * Returns the length of a secret key, in bytes - */ -size_t crypto_sign_secretkeybytes(void) { - return CRYPTO_SECRETKEYBYTES; -} - -/* - * Returns the length of a public key, in bytes - */ -size_t crypto_sign_publickeybytes(void) { - return CRYPTO_PUBLICKEYBYTES; -} - -/* - * Returns the length of a signature, in bytes - */ -size_t crypto_sign_bytes(void) { - return CRYPTO_BYTES; -} - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t crypto_sign_seedbytes(void) { - return CRYPTO_SEEDBYTES; -} - -/* - * Generates an SPX key pair given a seed of length - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed) { - spx_ctx ctx; - - /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ - memcpy(sk, seed, CRYPTO_SEEDBYTES); - - memcpy(pk, sk + 2 * SPX_N, SPX_N); - - memcpy(ctx.pub_seed, pk, SPX_N); - memcpy(ctx.sk_seed, sk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - /* Compute root node of the top-most subtree. */ - merkle_gen_root(sk + 3 * SPX_N, &ctx); - - // cleanup - free_hash_function(&ctx); - - memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); - - return 0; -} - -/* - * Generates an SPX key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { - uint8_t seed[CRYPTO_SEEDBYTES]; - randombytes(seed, CRYPTO_SEEDBYTES); - crypto_sign_seed_keypair(pk, sk, seed); - - return 0; -} - -/** - * Returns an array containing a detached signature. - */ -int crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - spx_ctx ctx; - - const uint8_t *sk_prf = sk + SPX_N; - const uint8_t *pk = sk + 2 * SPX_N; - - uint8_t optrand[SPX_N]; - uint8_t mhash[SPX_FORS_MSG_BYTES]; - uint8_t root[SPX_N]; - uint32_t i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - - memcpy(ctx.sk_seed, sk, SPX_N); - memcpy(ctx.pub_seed, pk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - set_type(wots_addr, SPX_ADDR_TYPE_WOTS); - set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); - - /* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ - randombytes(optrand, SPX_N); - /* Compute the digest randomization value. */ - gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); - - /* Derive the message digest and leaf index from R, PK and M. */ - hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); - sig += SPX_N; - - set_tree_addr(wots_addr, tree); - set_keypair_addr(wots_addr, idx_leaf); - - /* Sign the message hash using FORS. */ - fors_sign(sig, root, mhash, &ctx, wots_addr); - sig += SPX_FORS_BYTES; - - for (i = 0; i < SPX_D; i++) { - set_layer_addr(tree_addr, i); - set_tree_addr(tree_addr, tree); - - copy_subtree_addr(wots_addr, tree_addr); - set_keypair_addr(wots_addr, idx_leaf); - - merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); - sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); - tree = tree >> SPX_TREE_HEIGHT; - } - - free_hash_function(&ctx); - - *siglen = SPX_BYTES; - - return 0; -} - -/** - * Verifies a detached signature and message under a given public key. - */ -int crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk) { - spx_ctx ctx; - const uint8_t *pub_root = pk + SPX_N; - uint8_t mhash[SPX_FORS_MSG_BYTES]; - uint8_t wots_pk[SPX_WOTS_BYTES]; - uint8_t root[SPX_N]; - uint8_t leaf[SPX_N]; - unsigned int i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - if (siglen != SPX_BYTES) { - return -1; - } - - memcpy(ctx.pub_seed, pk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - set_type(wots_addr, SPX_ADDR_TYPE_WOTS); - set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); - set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); - - /* Derive the message digest and leaf index from R || PK || M. */ - /* The additional SPX_N is a result of the hash domain separator. */ - hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); - sig += SPX_N; - - /* Layer correctly defaults to 0, so no need to set_layer_addr */ - set_tree_addr(wots_addr, tree); - set_keypair_addr(wots_addr, idx_leaf); - - fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); - sig += SPX_FORS_BYTES; - - /* For each subtree.. */ - for (i = 0; i < SPX_D; i++) { - set_layer_addr(tree_addr, i); - set_tree_addr(tree_addr, tree); - - copy_subtree_addr(wots_addr, tree_addr); - set_keypair_addr(wots_addr, idx_leaf); - - copy_keypair_addr(wots_pk_addr, wots_addr); - - /* The WOTS public key is only correct if the signature was correct. */ - /* Initially, root is the FORS pk, but on subsequent iterations it is - the root of the subtree below the currently processed subtree. */ - wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); - sig += SPX_WOTS_BYTES; - - /* Compute the leaf node using the WOTS public key. */ - thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); - - /* Compute the root node of this subtree. */ - compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, - &ctx, tree_addr); - sig += SPX_TREE_HEIGHT * SPX_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); - tree = tree >> SPX_TREE_HEIGHT; - } - - // cleanup - free_hash_function(&ctx); - - /* Check if the root node equals the root node in the public key. */ - if (memcmp(root, pub_root, SPX_N) != 0) { - return -1; - } - - return 0; -} - - -/** - * Returns an array containing the signature followed by the message. - */ -int crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk) { - size_t siglen; - - crypto_sign_signature(sm, &siglen, m, mlen, sk); - - memmove(sm + SPX_BYTES, m, mlen); - *smlen = siglen + mlen; - - return 0; -} - -/** - * Verifies a given signature-message pair under a given public key. - */ -int crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk) { - /* The API caller does not necessarily know what size a signature should be - but SPHINCS+ signatures are always exactly SPX_BYTES. */ - if (smlen < SPX_BYTES) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - *mlen = smlen - SPX_BYTES; - - if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - /* If verification was successful, move the message to the right place. */ - memmove(m, sm + SPX_BYTES, *mlen); - - return 0; -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/thash.h b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/thash.h deleted file mode 100644 index 8687ccfb4d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/thash.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef SPX_THASH_H -#define SPX_THASH_H - -#include "context.h" -#include "params.h" - -#include - -#define thash SPX_NAMESPACE(thash) -void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/thash_sha2_robust.c b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/thash_sha2_robust.c deleted file mode 100644 index 3ab891175f..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/thash_sha2_robust.c +++ /dev/null @@ -1,68 +0,0 @@ -#include -#include - -#include "address.h" -#include "context.h" -#include "hash.h" -#include "params.h" -#include "sha2.h" -#include "thash.h" -#include "utils.h" - -static void thash_512(unsigned char *out, const unsigned char *in, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]); - -/** - * Takes an array of inblocks concatenated arrays of SPX_N bytes. - */ -void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]) { - if (inblocks > 1) { - thash_512(out, in, inblocks, ctx, addr); - return; - } - unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES]; - PQCLEAN_VLA(uint8_t, bitmask, inblocks * SPX_N); - PQCLEAN_VLA(uint8_t, buf, SPX_N + SPX_SHA256_OUTPUT_BYTES + inblocks * SPX_N); - sha256ctx sha2_state; - unsigned int i; - - memcpy(buf, ctx->pub_seed, SPX_N); - memcpy(buf + SPX_N, addr, SPX_SHA256_ADDR_BYTES); - mgf1_256(bitmask, inblocks * SPX_N, buf, SPX_N + SPX_SHA256_ADDR_BYTES); - - /* Retrieve precomputed state containing pub_seed */ - sha256_inc_ctx_clone(&sha2_state, &ctx->state_seeded); - - for (i = 0; i < inblocks * SPX_N; i++) { - buf[SPX_N + SPX_SHA256_ADDR_BYTES + i] = in[i] ^ bitmask[i]; - } - - sha256_inc_finalize(outbuf, &sha2_state, buf + SPX_N, - SPX_SHA256_ADDR_BYTES + inblocks * SPX_N); - memcpy(out, outbuf, SPX_N); -} - -static void thash_512(unsigned char *out, const unsigned char *in, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]) { - unsigned char outbuf[SPX_SHA512_OUTPUT_BYTES]; - PQCLEAN_VLA(uint8_t, bitmask, inblocks * SPX_N); - PQCLEAN_VLA(uint8_t, buf, SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N); - sha512ctx sha2_state; - unsigned int i; - - memcpy(buf, ctx->pub_seed, SPX_N); - memcpy(buf + SPX_N, addr, SPX_SHA256_ADDR_BYTES); - mgf1_512(bitmask, inblocks * SPX_N, buf, SPX_N + SPX_SHA256_ADDR_BYTES); - - /* Retrieve precomputed state containing pub_seed */ - sha512_inc_ctx_clone(&sha2_state, &ctx->state_seeded_512); - - for (i = 0; i < inblocks * SPX_N; i++) { - buf[SPX_N + SPX_SHA256_ADDR_BYTES + i] = in[i] ^ bitmask[i]; - } - - sha512_inc_finalize(outbuf, &sha2_state, buf + SPX_N, - SPX_SHA256_ADDR_BYTES + inblocks * SPX_N); - memcpy(out, outbuf, SPX_N); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/thash_sha2_robustx8.c b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/thash_sha2_robustx8.c deleted file mode 100644 index 991faa7eeb..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/thash_sha2_robustx8.c +++ /dev/null @@ -1,268 +0,0 @@ -#include -#include - -#include "thashx8.h" - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "sha2.h" -#include "sha256avx.h" -#include "sha256x8.h" -#include "utils.h" - -#include "sha512x4.h" - -static void thashx8_512( - unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - const unsigned char *in4, - const unsigned char *in5, - const unsigned char *in6, - const unsigned char *in7, - unsigned int inblocks, - const spx_ctx *ctx, - uint32_t addrx8[8 * 8] -); - -/** - * 8-way parallel version of thash; takes 8x as much input and output - */ -void thashx8(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - const unsigned char *in4, - const unsigned char *in5, - const unsigned char *in6, - const unsigned char *in7, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addrx8[8 * 8]) { - if (inblocks > 1) { - thashx8_512( - out0, out1, out2, out3, out4, out5, out6, out7, - in0, in1, in2, in3, in4, in5, in6, in7, - inblocks, ctx, addrx8); - return; - } - PQCLEAN_VLA(unsigned char, bufx8, 8 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)); - unsigned char outbufx8[8 * SPX_SHA256_OUTPUT_BYTES]; - PQCLEAN_VLA(unsigned char, bitmaskx8, 8 * (inblocks * SPX_N)); - unsigned int i; - - for (i = 0; i < 8; i++) { - memcpy(bufx8 + i * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - ctx->pub_seed, SPX_N); - memcpy(bufx8 + SPX_N + - i * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - addrx8 + i * 8, SPX_SHA256_ADDR_BYTES); - } - - mgf1x8(bitmaskx8, inblocks * SPX_N, - bufx8 + 0 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + 1 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + 2 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + 3 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + 4 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + 5 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + 6 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + 7 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - SPX_N + SPX_SHA256_ADDR_BYTES); - - for (i = 0; i < inblocks * SPX_N; i++) { - bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + - 0 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = - in0[i] ^ bitmaskx8[i + 0 * (inblocks * SPX_N)]; - bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + - 1 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = - in1[i] ^ bitmaskx8[i + 1 * (inblocks * SPX_N)]; - bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + - 2 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = - in2[i] ^ bitmaskx8[i + 2 * (inblocks * SPX_N)]; - bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + - 3 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = - in3[i] ^ bitmaskx8[i + 3 * (inblocks * SPX_N)]; - bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + - 4 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = - in4[i] ^ bitmaskx8[i + 4 * (inblocks * SPX_N)]; - bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + - 5 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = - in5[i] ^ bitmaskx8[i + 5 * (inblocks * SPX_N)]; - bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + - 6 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = - in6[i] ^ bitmaskx8[i + 6 * (inblocks * SPX_N)]; - bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + - 7 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = - in7[i] ^ bitmaskx8[i + 7 * (inblocks * SPX_N)]; - } - - sha256x8_seeded( - /* out */ - outbufx8 + 0 * SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 1 * SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 2 * SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 3 * SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 4 * SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 5 * SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 6 * SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 7 * SPX_SHA256_OUTPUT_BYTES, - - /* seed */ - &ctx->statex8_seeded, - - /* in */ - bufx8 + SPX_N + 0 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + SPX_N + 1 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + SPX_N + 2 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + SPX_N + 3 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + SPX_N + 4 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + SPX_N + 5 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + SPX_N + 6 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + SPX_N + 7 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - SPX_SHA256_ADDR_BYTES + inblocks * SPX_N /* len */ - ); - - memcpy(out0, outbufx8 + 0 * SPX_SHA256_OUTPUT_BYTES, SPX_N); - memcpy(out1, outbufx8 + 1 * SPX_SHA256_OUTPUT_BYTES, SPX_N); - memcpy(out2, outbufx8 + 2 * SPX_SHA256_OUTPUT_BYTES, SPX_N); - memcpy(out3, outbufx8 + 3 * SPX_SHA256_OUTPUT_BYTES, SPX_N); - memcpy(out4, outbufx8 + 4 * SPX_SHA256_OUTPUT_BYTES, SPX_N); - memcpy(out5, outbufx8 + 5 * SPX_SHA256_OUTPUT_BYTES, SPX_N); - memcpy(out6, outbufx8 + 6 * SPX_SHA256_OUTPUT_BYTES, SPX_N); - memcpy(out7, outbufx8 + 7 * SPX_SHA256_OUTPUT_BYTES, SPX_N); -} - -/** - * 2x4-way parallel version of thash; this is for the uses of thash that are - * based on SHA-512 - */ -static void thashx8_512( - unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - const unsigned char *in4, - const unsigned char *in5, - const unsigned char *in6, - const unsigned char *in7, - unsigned int inblocks, - const spx_ctx *ctx, - uint32_t addrx8[8 * 8]) { - PQCLEAN_VLA(unsigned char, bufx8, 8 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)); - unsigned char outbuf[4 * SPX_SHA512_OUTPUT_BYTES]; - PQCLEAN_VLA(unsigned char, bitmaskx4, 4 * (inblocks * SPX_N)); - unsigned int i; - - for (i = 0; i < 8; i++) { - memcpy(bufx8 + i * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - ctx->pub_seed, SPX_N); - memcpy(bufx8 + SPX_N + - i * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - addrx8 + i * 8, SPX_SHA256_ADDR_BYTES); - } - - mgf1x4_512(bitmaskx4, inblocks * SPX_N, - bufx8 + 0 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + 1 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + 2 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + 3 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - SPX_N + SPX_SHA256_ADDR_BYTES); - - for (i = 0; i < inblocks * SPX_N; i++) { - bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + - 0 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = - in0[i] ^ bitmaskx4[i + 0 * (inblocks * SPX_N)]; - bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + - 1 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = - in1[i] ^ bitmaskx4[i + 1 * (inblocks * SPX_N)]; - bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + - 2 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = - in2[i] ^ bitmaskx4[i + 2 * (inblocks * SPX_N)]; - bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + - 3 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = - in3[i] ^ bitmaskx4[i + 3 * (inblocks * SPX_N)]; - } - - mgf1x4_512(bitmaskx4, inblocks * SPX_N, - bufx8 + 4 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + 5 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + 6 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + 7 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - SPX_N + SPX_SHA256_ADDR_BYTES); - - for (i = 0; i < inblocks * SPX_N; i++) { - bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + - 4 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = - in4[i] ^ bitmaskx4[i + 0 * (inblocks * SPX_N)]; - bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + - 5 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = - in5[i] ^ bitmaskx4[i + 1 * (inblocks * SPX_N)]; - bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + - 6 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = - in6[i] ^ bitmaskx4[i + 2 * (inblocks * SPX_N)]; - bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + - 7 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = - in7[i] ^ bitmaskx4[i + 3 * (inblocks * SPX_N)]; - } - - sha512x4_seeded( - outbuf + 0 * SPX_SHA512_OUTPUT_BYTES, - outbuf + 1 * SPX_SHA512_OUTPUT_BYTES, - outbuf + 2 * SPX_SHA512_OUTPUT_BYTES, - outbuf + 3 * SPX_SHA512_OUTPUT_BYTES, - &ctx->statex4_seeded_512, /* seed */ - bufx8 + SPX_N + 0 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + SPX_N + 1 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + SPX_N + 2 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + SPX_N + 3 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - SPX_SHA256_ADDR_BYTES + inblocks * SPX_N /* len */ - ); - - memcpy(out0, outbuf + 0 * SPX_SHA512_OUTPUT_BYTES, SPX_N); - memcpy(out1, outbuf + 1 * SPX_SHA512_OUTPUT_BYTES, SPX_N); - memcpy(out2, outbuf + 2 * SPX_SHA512_OUTPUT_BYTES, SPX_N); - memcpy(out3, outbuf + 3 * SPX_SHA512_OUTPUT_BYTES, SPX_N); - - sha512x4_seeded( - outbuf + 0 * SPX_SHA512_OUTPUT_BYTES, - outbuf + 1 * SPX_SHA512_OUTPUT_BYTES, - outbuf + 2 * SPX_SHA512_OUTPUT_BYTES, - outbuf + 3 * SPX_SHA512_OUTPUT_BYTES, - &ctx->statex4_seeded_512, /* seed */ - bufx8 + SPX_N + 4 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + SPX_N + 5 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + SPX_N + 6 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + SPX_N + 7 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - SPX_SHA256_ADDR_BYTES + inblocks * SPX_N /* len */ - ); - - memcpy(out4, outbuf + 0 * SPX_SHA512_OUTPUT_BYTES, SPX_N); - memcpy(out5, outbuf + 1 * SPX_SHA512_OUTPUT_BYTES, SPX_N); - memcpy(out6, outbuf + 2 * SPX_SHA512_OUTPUT_BYTES, SPX_N); - memcpy(out7, outbuf + 3 * SPX_SHA512_OUTPUT_BYTES, SPX_N); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/thashx8.h b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/thashx8.h deleted file mode 100644 index c02fe9cf3e..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/thashx8.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef SPX_THASHX8_H -#define SPX_THASHX8_H - -#include - -#include "context.h" -#include "params.h" - -#define thashx8 SPX_NAMESPACE(thashx8) -void thashx8(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - const unsigned char *in4, - const unsigned char *in5, - const unsigned char *in6, - const unsigned char *in7, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addrx8[8 * 8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/utils.c b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/utils.c deleted file mode 100644 index 177b541fb9..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/utils.c +++ /dev/null @@ -1,148 +0,0 @@ -#include - -#include "utils.h" - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "thash.h" - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void ull_to_bytes(unsigned char *out, unsigned int outlen, - unsigned long long in) { - int i; - - /* Iterate over out in decreasing order, for big-endianness. */ - for (i = (signed int)outlen - 1; i >= 0; i--) { - out[i] = in & 0xff; - in = in >> 8; - } -} - -void u32_to_bytes(unsigned char *out, uint32_t in) { - out[0] = (unsigned char)(in >> 24); - out[1] = (unsigned char)(in >> 16); - out[2] = (unsigned char)(in >> 8); - out[3] = (unsigned char)in; -} - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { - unsigned long long retval = 0; - unsigned int i; - - for (i = 0; i < inlen; i++) { - retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); - } - return retval; -} - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void compute_root(unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const spx_ctx *ctx, uint32_t addr[8]) { - uint32_t i; - unsigned char buffer[2 * SPX_N]; - - /* If leaf_idx is odd (last bit = 1), current path element is a right child - and auth_path has to go left. Otherwise it is the other way around. */ - if (leaf_idx & 1) { - memcpy(buffer + SPX_N, leaf, SPX_N); - memcpy(buffer, auth_path, SPX_N); - } else { - memcpy(buffer, leaf, SPX_N); - memcpy(buffer + SPX_N, auth_path, SPX_N); - } - auth_path += SPX_N; - - for (i = 0; i < tree_height - 1; i++) { - leaf_idx >>= 1; - idx_offset >>= 1; - /* Set the address of the node we're creating. */ - set_tree_height(addr, i + 1); - set_tree_index(addr, leaf_idx + idx_offset); - - /* Pick the right or left neighbor, depending on parity of the node. */ - if (leaf_idx & 1) { - thash(buffer + SPX_N, buffer, 2, ctx, addr); - memcpy(buffer, auth_path, SPX_N); - } else { - thash(buffer, buffer, 2, ctx, addr); - memcpy(buffer + SPX_N, auth_path, SPX_N); - } - auth_path += SPX_N; - } - - /* The last iteration is exceptional; we do not copy an auth_path node. */ - leaf_idx >>= 1; - idx_offset >>= 1; - set_tree_height(addr, tree_height); - set_tree_index(addr, leaf_idx + idx_offset); - thash(root, buffer, 2, ctx, addr); -} - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const spx_ctx * /* ctx */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), - uint32_t tree_addr[8]) { - PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); - PQCLEAN_VLA(unsigned int, heights, tree_height + 1); - unsigned int offset = 0; - uint32_t idx; - uint32_t tree_idx; - - for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { - /* Add the next leaf node to the stack. */ - gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); - offset++; - heights[offset - 1] = 0; - - /* If this is a node we need for the auth path.. */ - if ((leaf_idx ^ 0x1) == idx) { - memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); - } - - /* While the top-most nodes are of equal height.. */ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { - /* Compute index of the new node, in the next layer. */ - tree_idx = (idx >> (heights[offset - 1] + 1)); - - /* Set the address of the node we're creating. */ - set_tree_height(tree_addr, heights[offset - 1] + 1); - set_tree_index(tree_addr, - tree_idx + (idx_offset >> (heights[offset - 1] + 1))); - /* Hash the top-most nodes from the stack together. */ - thash(stack + (offset - 2)*SPX_N, - stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); - offset--; - /* Note that the top-most node is now one layer higher. */ - heights[offset - 1]++; - - /* If this is a node we need for the auth path.. */ - if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_path + heights[offset - 1]*SPX_N, - stack + (offset - 1)*SPX_N, SPX_N); - } - } - } - memcpy(root, stack, SPX_N); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/utils.h b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/utils.h deleted file mode 100644 index 64f5d5a53a..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/utils.h +++ /dev/null @@ -1,58 +0,0 @@ -#ifndef SPX_UTILS_H -#define SPX_UTILS_H - -#include - -#include "compat.h" -#include "context.h" -#include "params.h" - - -/* To support MSVC use alloca() instead of VLAs. See #20. */ - - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) -void ull_to_bytes(unsigned char *out, unsigned int outlen, - unsigned long long in); -#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) -void u32_to_bytes(unsigned char *out, uint32_t in); - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) -unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -#define compute_root SPX_NAMESPACE(compute_root) -void compute_root(unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const spx_ctx *ctx, uint32_t addr[8]); - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -#define treehash SPX_NAMESPACE(treehash) -void treehash(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const spx_ctx *ctx /* ctx */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), - uint32_t tree_addr[8]); - - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/utilsx8.c b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/utilsx8.c deleted file mode 100644 index f044b9595d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/utilsx8.c +++ /dev/null @@ -1,146 +0,0 @@ -#include - -#include "utils.h" -#include "utilsx8.h" - -#include "address.h" -#include "params.h" -#include "thashx8.h" - -/* - * Generate the entire Merkle tree, computing the authentication path for leaf_idx, - * and the resulting root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) - * - * This expects tree_addrx8 to be initialized to 8 parallel addr structures for - * the Merkle tree nodes - * - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - * - * This works by using the standard Merkle tree building algorithm, except - * that each 'node' tracked is actually 8 consecutive nodes in the real tree. - * When we combine two logical nodes ABCDEFGH and STUVWXYZ, we perform the H - * operation on adjacent real nodes, forming the parent logical node - * (AB)(CD)(EF)(GH)(ST)(UV)(WX)(YZ) - * - * When we get to the top three levels of the real tree (where there is only - * one logical node), we continue this operation three more times; the right - * most real node will by the actual root (and the other 7 nodes will be - * garbage). We follow the same thashx8 logic so that the 'extract - * authentication path components' part of the loop is still executed (and - * to simplify the code somewhat) - * - * This currently assumes tree_height >= 3; I suspect that doing an adjusting - * idx, addr_idx on the gen_leafx8 call if tree_height < 3 would fix it; since - * we don't actually use such short trees, I haven't bothered - */ -void treehashx8(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, - uint32_t tree_height, - void (*gen_leafx8)( - unsigned char * /* Where to write the leaves */, - const spx_ctx *, - uint32_t idx, void *info), - uint32_t tree_addrx8[8 * 8], - void *info) { - /* This is where we keep the intermediate nodes */ - PQCLEAN_VLA(unsigned char, stackx8, tree_height * 8 * SPX_N); - uint32_t left_adj = 0, prev_left_adj = 0; /* When we're doing the top 3 */ - /* levels, the left-most part of the tree isn't at the beginning */ - /* of current[]. These give the offset of the actual start */ - - uint32_t idx; - uint32_t max_idx = ((uint32_t)1 << (tree_height - 3)) - 1; - for (idx = 0;; idx++) { - unsigned char current[8 * SPX_N]; /* Current logical node */ - gen_leafx8( current, ctx, 8 * idx + idx_offset, - info ); - - /* Now combine the freshly generated right node with previously */ - /* generated left ones */ - uint32_t internal_idx_offset = idx_offset; - uint32_t internal_idx = idx; - uint32_t internal_leaf = leaf_idx; - uint32_t h; /* The height we are in the Merkle tree */ - for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { - - /* Special processing if we're at the top of the tree */ - if (h >= tree_height - 3) { - if (h == tree_height) { - /* We hit the root; return it */ - memcpy( root, ¤t[7 * SPX_N], SPX_N ); - return; - } - /* The tree indexing logic is a bit off in this case */ - /* Adjust it so that the left-most node of the part of */ - /* the tree that we're processing has index 0 */ - prev_left_adj = left_adj; - left_adj = (uint32_t)(8 - (1 << (tree_height - h - 1))); - } - - /* Check if we hit the top of the tree */ - if (h == tree_height) { - /* We hit the root; return it */ - memcpy( root, ¤t[7 * SPX_N], SPX_N ); - return; - } - - /* - * Check if one of the nodes we have is a part of the - * authentication path; if it is, write it out - */ - if ((((internal_idx << 3) ^ internal_leaf) & ~0x7U) == 0) { - memcpy( &auth_path[ h * SPX_N ], - ¤t[(((internal_leaf & 7) ^ 1) + prev_left_adj) * SPX_N], - SPX_N ); - } - - /* - * Check if we're at a left child; if so, stop going up the stack - * Exception: if we've reached the end of the tree, keep on going - * (so we combine the last 8 nodes into the one root node in three - * more iterations) - */ - if ((internal_idx & 1) == 0 && idx < max_idx) { - break; - } - - /* Ok, we're at a right node (or doing the top 3 levels) */ - /* Now combine the left and right logical nodes together */ - - /* Set the address of the node we're creating. */ - uint32_t j; - internal_idx_offset >>= 1; - for (j = 0; j < 8; j++) { - set_tree_height(tree_addrx8 + j * 8, h + 1); - set_tree_index(tree_addrx8 + j * 8, - (8 / 2) * (internal_idx & ~1U) + j - left_adj + internal_idx_offset ); - } - unsigned char *left = &stackx8[h * 8 * SPX_N]; - thashx8( ¤t[0 * SPX_N], - ¤t[1 * SPX_N], - ¤t[2 * SPX_N], - ¤t[3 * SPX_N], - ¤t[4 * SPX_N], - ¤t[5 * SPX_N], - ¤t[6 * SPX_N], - ¤t[7 * SPX_N], - &left [0 * SPX_N], - &left [2 * SPX_N], - &left [4 * SPX_N], - &left [6 * SPX_N], - ¤t[0 * SPX_N], - ¤t[2 * SPX_N], - ¤t[4 * SPX_N], - ¤t[6 * SPX_N], - 2, ctx, tree_addrx8); - } - - /* We've hit a left child; save the current for when we get the */ - /* corresponding right right */ - memcpy( &stackx8[h * 8 * SPX_N], current, 8 * SPX_N); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/utilsx8.h b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/utilsx8.h deleted file mode 100644 index 806d1e85be..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/utilsx8.h +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef SPX_UTILSX8_H -#define SPX_UTILSX8_H - -#include - -#include "params.h" - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - * - * This implementation uses AVX to compute internal nodes 8 at a time (in - * parallel) - */ -#define treehashx8 SPX_NAMESPACE(treehashx8) -void treehashx8(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leafx8)( - unsigned char * /* Where to write the leaves */, - const spx_ctx * /* ctx */, - uint32_t addr_idx, void *info), - uint32_t tree_addrx8[8 * 8], void *info); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/wots.c b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/wots.c deleted file mode 100644 index 689baf4db9..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/wots.c +++ /dev/null @@ -1,291 +0,0 @@ -#include -#include - -#include "wots.h" - -#include "address.h" -#include "hash.h" -#include "hashx8.h" -#include "params.h" -#include "thash.h" -#include "thashx8.h" -#include "utils.h" -#include "utilsx8.h" -#include "wotsx8.h" - -// TODO clarify address expectations, and make them more uniform. -// TODO i.e. do we expect types to be set already? -// TODO and do we expect modifications or copies? - -/** - * Computes up the chains - */ -static void gen_chains( - unsigned char *out, - const unsigned char *in, - unsigned int start[SPX_WOTS_LEN], - const unsigned int steps[SPX_WOTS_LEN], - const spx_ctx *ctx, - uint32_t addr[8]) { - uint32_t i, j, k, idx, watching; - int done; - unsigned char empty[SPX_N]; - unsigned char *bufs[8]; - uint32_t addrs[8 * 8]; - - int l; - uint16_t counts[SPX_WOTS_W] = { 0 }; - uint16_t idxs[SPX_WOTS_LEN]; - uint16_t total, newTotal; - - /* set addrs = {addr, addr, ..., addr} */ - for (j = 0; j < 8; j++) { - memcpy(addrs + j * 8, addr, sizeof(uint32_t) * 8); - } - - /* Initialize out with the value at position 'start'. */ - memcpy(out, in, SPX_WOTS_LEN * SPX_N); - - /* Sort the chains in reverse order by steps using counting sort. */ - for (i = 0; i < SPX_WOTS_LEN; i++) { - counts[steps[i]]++; - } - total = 0; - for (l = SPX_WOTS_W - 1; l >= 0; l--) { - newTotal = counts[l] + total; - counts[l] = total; - total = newTotal; - } - for (i = 0; i < SPX_WOTS_LEN; i++) { - idxs[counts[steps[i]]] = (uint16_t)i; - counts[steps[i]]++; - } - - /* We got our work cut out for us: do it! */ - for (i = 0; i < SPX_WOTS_LEN; i += 8) { - for (j = 0; j < 8 && i + j < SPX_WOTS_LEN; j++) { - idx = idxs[i + j]; - set_chain_addr(addrs + j * 8, idx); - bufs[j] = out + SPX_N * idx; - } - - /* As the chains are sorted in reverse order, we know that the first - * chain is the longest and the last one is the shortest. We keep - * an eye on whether the last chain is done and then on the one before, - * et cetera. */ - watching = 7; - done = 0; - while (i + watching >= SPX_WOTS_LEN) { - bufs[watching] = &empty[0]; - watching--; - } - - for (k = 0;; k++) { - while (k == steps[idxs[i + watching]]) { - bufs[watching] = &empty[0]; - if (watching == 0) { - done = 1; - break; - } - watching--; - } - if (done) { - break; - } - for (j = 0; j < watching + 1; j++) { - set_hash_addr(addrs + j * 8, k + start[idxs[i + j]]); - } - - thashx8(bufs[0], bufs[1], bufs[2], bufs[3], - bufs[4], bufs[5], bufs[6], bufs[7], - bufs[0], bufs[1], bufs[2], bufs[3], - bufs[4], bufs[5], bufs[6], bufs[7], 1, ctx, addrs); - } - } -} - -/** - * base_w algorithm as described in draft. - * Interprets an array of bytes as integers in base w. - * This only works when log_w is a divisor of 8. - */ -static void base_w(unsigned int *output, const int out_len, - const unsigned char *input) { - int in = 0; - int out = 0; - unsigned char total = 0; - int bits = 0; - int consumed; - - for (consumed = 0; consumed < out_len; consumed++) { - if (bits == 0) { - total = input[in]; - in++; - bits += 8; - } - bits -= SPX_WOTS_LOGW; - output[out] = (total >> bits) & (SPX_WOTS_W - 1); - out++; - } -} - -/* Computes the WOTS+ checksum over a message (in base_w). */ -static void wots_checksum(unsigned int *csum_base_w, - const unsigned int *msg_base_w) { - unsigned int csum = 0; - unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; - unsigned int i; - - /* Compute checksum. */ - for (i = 0; i < SPX_WOTS_LEN1; i++) { - csum += SPX_WOTS_W - 1 - msg_base_w[i]; - } - - /* Convert checksum to base_w. */ - /* Make sure expected empty zero bits are the least significant bits. */ - csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); - ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); - base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); -} - -/* Takes a message and derives the matching chain lengths. */ -void chain_lengths(unsigned int *lengths, const unsigned char *msg) { - base_w(lengths, SPX_WOTS_LEN1, msg); - wots_checksum(lengths + SPX_WOTS_LEN1, lengths); -} - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const spx_ctx *ctx, uint32_t addr[8]) { - unsigned int steps[SPX_WOTS_LEN]; - unsigned int start[SPX_WOTS_LEN]; - uint32_t i; - - chain_lengths(start, msg); - - for (i = 0; i < SPX_WOTS_LEN; i++) { - steps[i] = SPX_WOTS_W - 1 - start[i]; - } - - gen_chains(pk, sig, start, steps, ctx, addr); -} - -/* - * This generates 8 sequential WOTS public keys - * It also generates the WOTS signature if leaf_info indicates - * that we're signing with one of these WOTS keys - */ -void wots_gen_leafx8(unsigned char *dest, - const spx_ctx *ctx, - uint32_t leaf_idx, void *v_info) { - struct leaf_info_x8 *info = v_info; - uint32_t *leaf_addr = info->leaf_addr; - uint32_t *pk_addr = info->pk_addr; - unsigned int i, j, k; - unsigned char pk_buffer[ 8 * SPX_WOTS_BYTES ]; - unsigned wots_offset = SPX_WOTS_BYTES; - unsigned char *buffer; - uint32_t wots_k_mask; - unsigned wots_sign_index; - - if (((leaf_idx ^ info->wots_sign_leaf) & ~7U) == 0) { - /* We're traversing the leaf that's signing; generate the WOTS */ - /* signature */ - wots_k_mask = 0; - wots_sign_index = info->wots_sign_leaf & 7; /* Which of of the 8 */ - /* slots do the signatures come from */ - } else { - /* Nope, we're just generating pk's; turn off the signature logic */ - wots_k_mask = ~0U; - wots_sign_index = 0; - } - - for (j = 0; j < 8; j++) { - set_keypair_addr( leaf_addr + j * 8, leaf_idx + j ); - set_keypair_addr( pk_addr + j * 8, leaf_idx + j ); - } - - for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { - uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k */ - /* to the step if we're generating a signature, ~0 if we're not */ - - /* Start with the secret seed */ - for (j = 0; j < 8; j++) { - set_chain_addr(leaf_addr + j * 8, i); - set_hash_addr(leaf_addr + j * 8, 0); - set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTSPRF); - } - prf_addrx8(buffer + 0 * wots_offset, - buffer + 1 * wots_offset, - buffer + 2 * wots_offset, - buffer + 3 * wots_offset, - buffer + 4 * wots_offset, - buffer + 5 * wots_offset, - buffer + 6 * wots_offset, - buffer + 7 * wots_offset, - ctx, leaf_addr); - - for (j = 0; j < 8; j++) { - set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTS); - } - - /* Iterate down the WOTS chain */ - for (k = 0;; k++) { - /* Check if one of the values we have needs to be saved as a */ - /* part of the WOTS signature */ - if (k == wots_k) { - memcpy( info->wots_sig + i * SPX_N, - buffer + wots_sign_index * wots_offset, SPX_N ); - } - - /* Check if we hit the top of the chain */ - if (k == SPX_WOTS_W - 1) { - break; - } - - /* Iterate one step on all 8 chains */ - for (j = 0; j < 8; j++) { - set_hash_addr(leaf_addr + j * 8, k); - } - thashx8(buffer + 0 * wots_offset, - buffer + 1 * wots_offset, - buffer + 2 * wots_offset, - buffer + 3 * wots_offset, - buffer + 4 * wots_offset, - buffer + 5 * wots_offset, - buffer + 6 * wots_offset, - buffer + 7 * wots_offset, - buffer + 0 * wots_offset, - buffer + 1 * wots_offset, - buffer + 2 * wots_offset, - buffer + 3 * wots_offset, - buffer + 4 * wots_offset, - buffer + 5 * wots_offset, - buffer + 6 * wots_offset, - buffer + 7 * wots_offset, 1, ctx, leaf_addr); - } - } - - /* Do the final thash to generate the public keys */ - thashx8(dest + 0 * SPX_N, - dest + 1 * SPX_N, - dest + 2 * SPX_N, - dest + 3 * SPX_N, - dest + 4 * SPX_N, - dest + 5 * SPX_N, - dest + 6 * SPX_N, - dest + 7 * SPX_N, - pk_buffer + 0 * wots_offset, - pk_buffer + 1 * wots_offset, - pk_buffer + 2 * wots_offset, - pk_buffer + 3 * wots_offset, - pk_buffer + 4 * wots_offset, - pk_buffer + 5 * wots_offset, - pk_buffer + 6 * wots_offset, - pk_buffer + 7 * wots_offset, SPX_WOTS_LEN, ctx, pk_addr); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/wots.h b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/wots.h deleted file mode 100644 index 4e7692eeef..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/wots.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef SPX_WOTS_H -#define SPX_WOTS_H - -#include - -#include "context.h" -#include "params.h" - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) -void wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const spx_ctx *ctx, uint32_t addr[8]); - -/* - * Compute the chain lengths needed for a given message hash - */ -#define chain_lengths SPX_NAMESPACE(chain_lengths) -void chain_lengths(unsigned int *lengths, const unsigned char *msg); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/wotsx8.h b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/wotsx8.h deleted file mode 100644 index 10866efb35..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_avx2/wotsx8.h +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef WOTSX8_H_ -#define WOTSX8_H_ - -#include - -#include "context.h" -#include "params.h" - -/* - * This is here to provide an interface to the internal wots_gen_leafx8 - * routine. While this routine is not referenced in the package outside of - * wots.c, it is called from the stand-alone benchmark code to characterize - * the performance - */ -struct leaf_info_x8 { - unsigned char *wots_sig; - uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ - uint32_t *wots_steps; - uint32_t leaf_addr[8 * 8]; - uint32_t pk_addr[8 * 8]; -}; - -/* Macro to set the leaf_info to something 'benign', that is, it would */ -/* run with the same time as it does during the real signing process */ -/* Used only by the benchmark code */ -#define INITIALIZE_LEAF_INFO_X8(info, addr, step_buffer) { \ - (info).wots_sig = 0; \ - (info).wots_sign_leaf = ~0; \ - (info).wots_steps = step_buffer; \ - int i; \ - for (i=0; i<8; i++) { \ - memcpy( &(info).leaf_addr[8*i], addr, 32 ); \ - memcpy( &(info).pk_addr[8*i], addr, 32 ); \ - } \ - } - -#define wots_gen_leafx8 SPX_NAMESPACE(wots_gen_leafx8) -void wots_gen_leafx8(unsigned char *dest, - const spx_ctx *ctx, - uint32_t leaf_idx, void *v_info); - -#endif /* WOTSX8_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/LICENSE b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/LICENSE deleted file mode 100644 index 670154e353..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/LICENSE +++ /dev/null @@ -1,116 +0,0 @@ -CC0 1.0 Universal - -Statement of Purpose - -The laws of most jurisdictions throughout the world automatically confer -exclusive Copyright and Related Rights (defined below) upon the creator and -subsequent owner(s) (each and all, an "owner") of an original work of -authorship and/or a database (each, a "Work"). - -Certain owners wish to permanently relinquish those rights to a Work for the -purpose of contributing to a commons of creative, cultural and scientific -works ("Commons") that the public can reliably and without fear of later -claims of infringement build upon, modify, incorporate in other works, reuse -and redistribute as freely as possible in any form whatsoever and for any -purposes, including without limitation commercial purposes. These owners may -contribute to the Commons to promote the ideal of a free culture and the -further production of creative, cultural and scientific works, or to gain -reputation or greater distribution for their Work in part through the use and -efforts of others. - -For these and/or other purposes and motivations, and without any expectation -of additional consideration or compensation, the person associating CC0 with a -Work (the "Affirmer"), to the extent that he or she is an owner of Copyright -and Related Rights in the Work, voluntarily elects to apply CC0 to the Work -and publicly distribute the Work under its terms, with knowledge of his or her -Copyright and Related Rights in the Work and the meaning and intended legal -effect of CC0 on those rights. - -1. Copyright and Related Rights. A Work made available under CC0 may be -protected by copyright and related or neighboring rights ("Copyright and -Related Rights"). Copyright and Related Rights include, but are not limited -to, the following: - - i. the right to reproduce, adapt, distribute, perform, display, communicate, - and translate a Work; - - ii. moral rights retained by the original author(s) and/or performer(s); - - iii. publicity and privacy rights pertaining to a person's image or likeness - depicted in a Work; - - iv. rights protecting against unfair competition in regards to a Work, - subject to the limitations in paragraph 4(a), below; - - v. rights protecting the extraction, dissemination, use and reuse of data in - a Work; - - vi. database rights (such as those arising under Directive 96/9/EC of the - European Parliament and of the Council of 11 March 1996 on the legal - protection of databases, and under any national implementation thereof, - including any amended or successor version of such directive); and - - vii. other similar, equivalent or corresponding rights throughout the world - based on applicable law or treaty, and any national implementations thereof. - -2. Waiver. To the greatest extent permitted by, but not in contravention of, -applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and -unconditionally waives, abandons, and surrenders all of Affirmer's Copyright -and Related Rights and associated claims and causes of action, whether now -known or unknown (including existing as well as future claims and causes of -action), in the Work (i) in all territories worldwide, (ii) for the maximum -duration provided by applicable law or treaty (including future time -extensions), (iii) in any current or future medium and for any number of -copies, and (iv) for any purpose whatsoever, including without limitation -commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes -the Waiver for the benefit of each member of the public at large and to the -detriment of Affirmer's heirs and successors, fully intending that such Waiver -shall not be subject to revocation, rescission, cancellation, termination, or -any other legal or equitable action to disrupt the quiet enjoyment of the Work -by the public as contemplated by Affirmer's express Statement of Purpose. - -3. Public License Fallback. Should any part of the Waiver for any reason be -judged legally invalid or ineffective under applicable law, then the Waiver -shall be preserved to the maximum extent permitted taking into account -Affirmer's express Statement of Purpose. In addition, to the extent the Waiver -is so judged Affirmer hereby grants to each affected person a royalty-free, -non transferable, non sublicensable, non exclusive, irrevocable and -unconditional license to exercise Affirmer's Copyright and Related Rights in -the Work (i) in all territories worldwide, (ii) for the maximum duration -provided by applicable law or treaty (including future time extensions), (iii) -in any current or future medium and for any number of copies, and (iv) for any -purpose whatsoever, including without limitation commercial, advertising or -promotional purposes (the "License"). The License shall be deemed effective as -of the date CC0 was applied by Affirmer to the Work. Should any part of the -License for any reason be judged legally invalid or ineffective under -applicable law, such partial invalidity or ineffectiveness shall not -invalidate the remainder of the License, and in such case Affirmer hereby -affirms that he or she will not (i) exercise any of his or her remaining -Copyright and Related Rights in the Work or (ii) assert any associated claims -and causes of action with respect to the Work, in either case contrary to -Affirmer's express Statement of Purpose. - -4. Limitations and Disclaimers. - - a. No trademark or patent rights held by Affirmer are waived, abandoned, - surrendered, licensed or otherwise affected by this document. - - b. Affirmer offers the Work as-is and makes no representations or warranties - of any kind concerning the Work, express, implied, statutory or otherwise, - including without limitation warranties of title, merchantability, fitness - for a particular purpose, non infringement, or the absence of latent or - other defects, accuracy, or the present or absence of errors, whether or not - discoverable, all to the greatest extent permissible under applicable law. - - c. Affirmer disclaims responsibility for clearing rights of other persons - that may apply to the Work or any use thereof, including without limitation - any person's Copyright and Related Rights in the Work. Further, Affirmer - disclaims responsibility for obtaining any necessary consents, permissions - or other rights required for any use of the Work. - - d. Affirmer understands and acknowledges that Creative Commons is not a - party to this document and has no duty or obligation with respect to this - CC0 or use of the Work. - -For more information, please see - diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/address.c b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/address.c deleted file mode 100644 index b956e9cb29..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/address.c +++ /dev/null @@ -1,91 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "utils.h" - -/* - * Specify which level of Merkle tree (the "layer") we're working on - */ -void set_layer_addr(uint32_t addr[8], uint32_t layer) { - ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; -} - -/* - * Specify which Merkle tree within the level (the "tree address") we're working on - */ -void set_tree_addr(uint32_t addr[8], uint64_t tree) { - ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); -} - -/* - * Specify the reason we'll use this address structure for, that is, what - * hash will we compute with it. This is used so that unrelated types of - * hashes don't accidentally get the same address structure. The type will be - * one of the SPX_ADDR_TYPE constants - */ -void set_type(uint32_t addr[8], uint32_t type) { - ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; -} - -/* - * Copy the layer and tree fields of the address structure. This is used - * when we're doing multiple types of hashes within the same Merkle tree - */ -void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { - memcpy( out, in, SPX_OFFSET_TREE + 8 ); -} - -/* These functions are used for OTS addresses. */ - -/* - * Specify which Merkle leaf we're working on; that is, which OTS keypair - * we're talking about. - */ -void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { - ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; -} - -/* - * Copy the layer, tree and keypair fields of the address structure. This is - * used when we're doing multiple things within the same OTS keypair - */ -void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { - memcpy( out, in, SPX_OFFSET_TREE + 8 ); - ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; -} - -/* - * Specify which Merkle chain within the OTS we're working with - * (the chain address) - */ -void set_chain_addr(uint32_t addr[8], uint32_t chain) { - ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; -} - -/* - * Specify where in the Merkle chain we are -* (the hash address) - */ -void set_hash_addr(uint32_t addr[8], uint32_t hash) { - ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; -} - -/* These functions are used for all hash tree addresses (including FORS). */ - -/* - * Specify the height of the node in the Merkle/FORS tree we are in - * (the tree height) - */ -void set_tree_height(uint32_t addr[8], uint32_t tree_height) { - ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; -} - -/* - * Specify the distance from the left edge of the node in the Merkle/FORS tree - * (the tree index) - */ -void set_tree_index(uint32_t addr[8], uint32_t tree_index) { - u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/address.h b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/address.h deleted file mode 100644 index 24a84eb40c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/address.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef SPX_ADDRESS_H -#define SPX_ADDRESS_H - -#include - -#include "params.h" - -/* The hash types that are passed to set_type */ -#define SPX_ADDR_TYPE_WOTS 0 -#define SPX_ADDR_TYPE_WOTSPK 1 -#define SPX_ADDR_TYPE_HASHTREE 2 -#define SPX_ADDR_TYPE_FORSTREE 3 -#define SPX_ADDR_TYPE_FORSPK 4 -#define SPX_ADDR_TYPE_WOTSPRF 5 -#define SPX_ADDR_TYPE_FORSPRF 6 - -#define set_layer_addr SPX_NAMESPACE(set_layer_addr) -void set_layer_addr(uint32_t addr[8], uint32_t layer); - -#define set_tree_addr SPX_NAMESPACE(set_tree_addr) -void set_tree_addr(uint32_t addr[8], uint64_t tree); - -#define set_type SPX_NAMESPACE(set_type) -void set_type(uint32_t addr[8], uint32_t type); - -/* Copies the layer and tree part of one address into the other */ -#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) -void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for WOTS and FORS addresses. */ - -#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) -void set_keypair_addr(uint32_t addr[8], uint32_t keypair); - -#define set_chain_addr SPX_NAMESPACE(set_chain_addr) -void set_chain_addr(uint32_t addr[8], uint32_t chain); - -#define set_hash_addr SPX_NAMESPACE(set_hash_addr) -void set_hash_addr(uint32_t addr[8], uint32_t hash); - -#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) -void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for all hash tree addresses (including FORS). */ - -#define set_tree_height SPX_NAMESPACE(set_tree_height) -void set_tree_height(uint32_t addr[8], uint32_t tree_height); - -#define set_tree_index SPX_NAMESPACE(set_tree_index) -void set_tree_index(uint32_t addr[8], uint32_t tree_index); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/api.h b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/api.h deleted file mode 100644 index a250a782ac..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/api.h +++ /dev/null @@ -1,77 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA2256FROBUST_CLEAN_API_H -#define PQCLEAN_SPHINCSSHA2256FROBUST_CLEAN_API_H - -#include -#include - -#define PQCLEAN_SPHINCSSHA2256FROBUST_CLEAN_CRYPTO_ALGNAME "SPHINCS+-sha2-256f-robust" - -#define PQCLEAN_SPHINCSSHA2256FROBUST_CLEAN_CRYPTO_SECRETKEYBYTES 128 -#define PQCLEAN_SPHINCSSHA2256FROBUST_CLEAN_CRYPTO_PUBLICKEYBYTES 64 -#define PQCLEAN_SPHINCSSHA2256FROBUST_CLEAN_CRYPTO_BYTES 49856 - -#define PQCLEAN_SPHINCSSHA2256FROBUST_CLEAN_CRYPTO_SEEDBYTES 96 - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSSHA2256FROBUST_CLEAN_crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSSHA2256FROBUST_CLEAN_crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSSHA2256FROBUST_CLEAN_crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSSHA2256FROBUST_CLEAN_crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHA2256FROBUST_CLEAN_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHA2256FROBUST_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSSHA2256FROBUST_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSSHA2256FROBUST_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, - const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSSHA2256FROBUST_CLEAN_crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSSHA2256FROBUST_CLEAN_crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk); -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/context.h b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/context.h deleted file mode 100644 index 97e2e2469e..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/context.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef SPX_CONTEXT_H -#define SPX_CONTEXT_H - -#include -#include - -#include "params.h" -#include "sha2.h" - -typedef struct { - uint8_t pub_seed[SPX_N]; - uint8_t sk_seed[SPX_N]; - - // sha256 state that absorbed pub_seed - sha256ctx state_seeded; - - // sha512 state that absorbed pub_seed - sha512ctx state_seeded_512; - -} spx_ctx; - -#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) -void initialize_hash_function(spx_ctx *ctx); - -#define free_hash_function SPX_NAMESPACE(free_hash_function) -void free_hash_function(spx_ctx *ctx); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/context_sha2.c b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/context_sha2.c deleted file mode 100644 index 9ca9f4e7ac..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/context_sha2.c +++ /dev/null @@ -1,36 +0,0 @@ -#include "context.h" - -/** - * Absorb the constant pub_seed using one round of the compression function - * This initializes state_seeded and state_seeded_512, which can then be - * reused in thash - **/ -static void seed_state(spx_ctx *ctx) { - uint8_t block[SPX_SHA512_BLOCK_BYTES]; - size_t i; - - for (i = 0; i < SPX_N; ++i) { - block[i] = ctx->pub_seed[i]; - } - for (i = SPX_N; i < SPX_SHA512_BLOCK_BYTES; ++i) { - block[i] = 0; - } - /* block has been properly initialized for both SHA-256 and SHA-512 */ - - sha256_inc_init(&ctx->state_seeded); - sha256_inc_blocks(&ctx->state_seeded, block, 1); - sha512_inc_init(&ctx->state_seeded_512); - sha512_inc_blocks(&ctx->state_seeded_512, block, 1); -} - - -/* We initialize the state for the hash functions */ -void initialize_hash_function(spx_ctx *ctx) { - seed_state(ctx); -} - -/* Free the incremental hashing context for heap-based SHA2 APIs */ -void free_hash_function(spx_ctx *ctx) { - sha256_inc_ctx_release(&ctx->state_seeded); - sha512_inc_ctx_release(&ctx->state_seeded_512); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/fors.c b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/fors.c deleted file mode 100644 index 96ca72e986..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/fors.c +++ /dev/null @@ -1,156 +0,0 @@ -#include -#include -#include - -#include "fors.h" - -#include "address.h" -#include "hash.h" -#include "thash.h" -#include "utils.h" -#include "utilsx1.h" - -static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, - uint32_t fors_leaf_addr[8]) { - prf_addr(sk, ctx, fors_leaf_addr); -} - -static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, - const spx_ctx *ctx, - uint32_t fors_leaf_addr[8]) { - thash(leaf, sk, 1, ctx, fors_leaf_addr); -} - -struct fors_gen_leaf_info { - uint32_t leaf_addrx[8]; -}; - -static void fors_gen_leafx1(unsigned char *leaf, - const spx_ctx *ctx, - uint32_t addr_idx, void *info) { - struct fors_gen_leaf_info *fors_info = info; - uint32_t *fors_leaf_addr = fors_info->leaf_addrx; - - /* Only set the parts that the caller doesn't set */ - set_tree_index(fors_leaf_addr, addr_idx); - set_type(fors_leaf_addr, SPX_ADDR_TYPE_FORSPRF); - fors_gen_sk(leaf, ctx, fors_leaf_addr); - - set_type(fors_leaf_addr, SPX_ADDR_TYPE_FORSTREE); - fors_sk_to_leaf(leaf, leaf, - ctx, fors_leaf_addr); -} - -/** - * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - * Assumes indices has space for SPX_FORS_TREES integers. - */ -static void message_to_indices(uint32_t *indices, const unsigned char *m) { - unsigned int i, j; - unsigned int offset = 0; - - for (i = 0; i < SPX_FORS_TREES; i++) { - indices[i] = 0; - for (j = 0; j < SPX_FORS_HEIGHT; j++) { - indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); - offset++; - } - } -} - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -void fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]) { - uint32_t indices[SPX_FORS_TREES]; - unsigned char roots[SPX_FORS_TREES * SPX_N]; - uint32_t fors_tree_addr[8] = {0}; - struct fors_gen_leaf_info fors_info = {0}; - uint32_t *fors_leaf_addr = fors_info.leaf_addrx; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - copy_keypair_addr(fors_tree_addr, fors_addr); - copy_keypair_addr(fors_leaf_addr, fors_addr); - - copy_keypair_addr(fors_pk_addr, fors_addr); - set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < SPX_FORS_TREES; i++) { - idx_offset = i * (1 << SPX_FORS_HEIGHT); - - set_tree_height(fors_tree_addr, 0); - set_tree_index(fors_tree_addr, indices[i] + idx_offset); - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); - - /* Include the secret key part that produces the selected leaf node. */ - fors_gen_sk(sig, ctx, fors_tree_addr); - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); - sig += SPX_N; - - /* Compute the authentication path for this leaf node. */ - treehashx1(roots + i * SPX_N, sig, ctx, - indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx1, - fors_tree_addr, &fors_info); - - sig += SPX_N * SPX_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); -} - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -void fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]) { - uint32_t indices[SPX_FORS_TREES]; - unsigned char roots[SPX_FORS_TREES * SPX_N]; - unsigned char leaf[SPX_N]; - uint32_t fors_tree_addr[8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - copy_keypair_addr(fors_tree_addr, fors_addr); - copy_keypair_addr(fors_pk_addr, fors_addr); - - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); - set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < SPX_FORS_TREES; i++) { - idx_offset = i * (1 << SPX_FORS_HEIGHT); - - set_tree_height(fors_tree_addr, 0); - set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Derive the leaf from the included secret key part. */ - fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); - sig += SPX_N; - - /* Derive the corresponding root node of this tree. */ - compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, - sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); - sig += SPX_N * SPX_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/fors.h b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/fors.h deleted file mode 100644 index 509140a178..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/fors.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef SPX_FORS_H -#define SPX_FORS_H - -#include - -#include "context.h" -#include "params.h" - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -#define fors_sign SPX_NAMESPACE(fors_sign) -void fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]); - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) -void fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/hash.h b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/hash.h deleted file mode 100644 index ffe815f45d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/hash.h +++ /dev/null @@ -1,37 +0,0 @@ -#ifndef SPX_HASH_H -#define SPX_HASH_H - -#include -#include - -#include "context.h" -#include "params.h" - -#define prf_addr SPX_NAMESPACE(prf_addr) -void prf_addr(unsigned char *out, const spx_ctx *ctx, - const uint32_t addr[8]); - -#define gen_message_random SPX_NAMESPACE(gen_message_random) -void gen_message_random(unsigned char *R, const unsigned char *sk_prf, - const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx); - -#define hash_message SPX_NAMESPACE(hash_message) -void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx); - - -# define SPX_SHA256_ADDR_BYTES 22 - -# define mgf1_256 SPX_NAMESPACE(mgf1_256) -void mgf1_256(unsigned char *out, unsigned long outlen, - const unsigned char *in, unsigned long inlen); - -# define mgf1_512 SPX_NAMESPACE(mgf1_512) -void mgf1_512(unsigned char *out, unsigned long outlen, - const unsigned char *in, unsigned long inlen); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/hash_sha2.c b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/hash_sha2.c deleted file mode 100644 index 3d0085c8c1..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/hash_sha2.c +++ /dev/null @@ -1,219 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "sha2.h" -#include "utils.h" - - - -#define SPX_SHAX_OUTPUT_BYTES SPX_SHA512_OUTPUT_BYTES -#define SPX_SHAX_BLOCK_BYTES SPX_SHA512_BLOCK_BYTES -#define shaX_inc_init sha512_inc_init -#define shaX_inc_blocks sha512_inc_blocks -#define shaX_inc_finalize sha512_inc_finalize -#define shaX sha512 -#define mgf1_X mgf1_512 -#define shaXstate sha512ctx - -/** - * mgf1 function based on the SHA-256 hash function - * Note that inlen should be sufficiently small that it still allows for - * an array to be allocated on the stack. Typically 'in' is merely a seed. - * Outputs outlen number of bytes - */ -void mgf1_256(unsigned char *out, unsigned long outlen, - const unsigned char *in, unsigned long inlen) { - PQCLEAN_VLA(uint8_t, inbuf, inlen + 4); - unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES]; - uint32_t i; - - memcpy(inbuf, in, inlen); - - /* While we can fit in at least another full block of SHA256 output.. */ - for (i = 0; (i + 1)*SPX_SHA256_OUTPUT_BYTES <= outlen; i++) { - u32_to_bytes(inbuf + inlen, i); - sha256(out, inbuf, inlen + 4); - out += SPX_SHA256_OUTPUT_BYTES; - } - /* Until we cannot anymore, and we fill the remainder. */ - if (outlen > i * SPX_SHA256_OUTPUT_BYTES) { - u32_to_bytes(inbuf + inlen, i); - sha256(outbuf, inbuf, inlen + 4); - memcpy(out, outbuf, outlen - i * SPX_SHA256_OUTPUT_BYTES); - } -} - -/* - * mgf1 function based on the SHA-512 hash function - */ -void mgf1_512(unsigned char *out, unsigned long outlen, - const unsigned char *in, unsigned long inlen) { - PQCLEAN_VLA(uint8_t, inbuf, inlen + 4); - unsigned char outbuf[SPX_SHA512_OUTPUT_BYTES]; - uint32_t i; - - memcpy(inbuf, in, inlen); - - /* While we can fit in at least another full block of SHA512 output.. */ - for (i = 0; (i + 1)*SPX_SHA512_OUTPUT_BYTES <= outlen; i++) { - u32_to_bytes(inbuf + inlen, i); - sha512(out, inbuf, inlen + 4); - out += SPX_SHA512_OUTPUT_BYTES; - } - /* Until we cannot anymore, and we fill the remainder. */ - if (outlen > i * SPX_SHA512_OUTPUT_BYTES) { - u32_to_bytes(inbuf + inlen, i); - sha512(outbuf, inbuf, inlen + 4); - memcpy(out, outbuf, outlen - i * SPX_SHA512_OUTPUT_BYTES); - } -} - -/* - * Computes PRF(pk_seed, sk_seed, addr). - */ -void prf_addr(unsigned char *out, const spx_ctx *ctx, - const uint32_t addr[8]) { - sha256ctx sha2_state; - unsigned char buf[SPX_SHA256_ADDR_BYTES + SPX_N]; - unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES]; - - /* Retrieve precomputed state containing pub_seed */ - sha256_inc_ctx_clone(&sha2_state, &ctx->state_seeded); - - /* Remainder: ADDR^c ‖ SK.seed */ - memcpy(buf, addr, SPX_SHA256_ADDR_BYTES); - memcpy(buf + SPX_SHA256_ADDR_BYTES, ctx->sk_seed, SPX_N); - - sha256_inc_finalize(outbuf, &sha2_state, buf, SPX_SHA256_ADDR_BYTES + SPX_N); - - memcpy(out, outbuf, SPX_N); -} - -/** - * Computes the message-dependent randomness R, using a secret seed as a key - * for HMAC, and an optional randomization value prefixed to the message. - * This requires m to have at least SPX_SHAX_BLOCK_BYTES + SPX_N space - * available in front of the pointer, i.e. before the message to use for the - * prefix. This is necessary to prevent having to move the message around (and - * allocate memory for it). - */ -void gen_message_random(unsigned char *R, const unsigned char *sk_prf, - const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx) { - (void)ctx; - - unsigned char buf[SPX_SHAX_BLOCK_BYTES + SPX_SHAX_OUTPUT_BYTES]; - shaXstate state; - int i; - - - /* This implements HMAC-SHA */ - for (i = 0; i < SPX_N; i++) { - buf[i] = 0x36 ^ sk_prf[i]; - } - memset(buf + SPX_N, 0x36, SPX_SHAX_BLOCK_BYTES - SPX_N); - - shaX_inc_init(&state); - shaX_inc_blocks(&state, buf, 1); - - memcpy(buf, optrand, SPX_N); - - /* If optrand + message cannot fill up an entire block */ - if (SPX_N + mlen < SPX_SHAX_BLOCK_BYTES) { - memcpy(buf + SPX_N, m, mlen); - shaX_inc_finalize(buf + SPX_SHAX_BLOCK_BYTES, &state, - buf, mlen + SPX_N); - } - /* Otherwise first fill a block, so that finalize only uses the message */ - else { - memcpy(buf + SPX_N, m, SPX_SHAX_BLOCK_BYTES - SPX_N); - shaX_inc_blocks(&state, buf, 1); - - m += SPX_SHAX_BLOCK_BYTES - SPX_N; - mlen -= SPX_SHAX_BLOCK_BYTES - SPX_N; - shaX_inc_finalize(buf + SPX_SHAX_BLOCK_BYTES, &state, m, mlen); - } - - for (i = 0; i < SPX_N; i++) { - buf[i] = 0x5c ^ sk_prf[i]; - } - memset(buf + SPX_N, 0x5c, SPX_SHAX_BLOCK_BYTES - SPX_N); - - shaX(buf, buf, SPX_SHAX_BLOCK_BYTES + SPX_SHAX_OUTPUT_BYTES); - memcpy(R, buf, SPX_N); -} - -/** - * Computes the message hash using R, the public key, and the message. - * Outputs the message digest and the index of the leaf. The index is split in - * the tree index and the leaf index, for convenient copying to an address. - */ -void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx) { - (void)ctx; -#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) -#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) -#define SPX_LEAF_BITS SPX_TREE_HEIGHT -#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) -#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) - - unsigned char seed[2 * SPX_N + SPX_SHAX_OUTPUT_BYTES]; - - /* Round to nearest multiple of SPX_SHAX_BLOCK_BYTES */ -#define SPX_INBLOCKS (((SPX_N + SPX_PK_BYTES + SPX_SHAX_BLOCK_BYTES - 1) & \ - -SPX_SHAX_BLOCK_BYTES) / SPX_SHAX_BLOCK_BYTES) - unsigned char inbuf[SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES]; - - unsigned char buf[SPX_DGST_BYTES]; - unsigned char *bufp = buf; - shaXstate state; - - shaX_inc_init(&state); - - // seed: SHA-X(R ‖ PK.seed ‖ PK.root ‖ M) - memcpy(inbuf, R, SPX_N); - memcpy(inbuf + SPX_N, pk, SPX_PK_BYTES); - - /* If R + pk + message cannot fill up an entire block */ - if (SPX_N + SPX_PK_BYTES + mlen < SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES) { - memcpy(inbuf + SPX_N + SPX_PK_BYTES, m, mlen); - shaX_inc_finalize(seed + 2 * SPX_N, &state, inbuf, SPX_N + SPX_PK_BYTES + mlen); - } - /* Otherwise first fill a block, so that finalize only uses the message */ - else { - memcpy(inbuf + SPX_N + SPX_PK_BYTES, m, - SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES - SPX_N - SPX_PK_BYTES); - shaX_inc_blocks(&state, inbuf, SPX_INBLOCKS); - - m += SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES - SPX_N - SPX_PK_BYTES; - mlen -= SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES - SPX_N - SPX_PK_BYTES; - shaX_inc_finalize(seed + 2 * SPX_N, &state, m, (size_t)mlen); - } - - // H_msg: MGF1-SHA-X(R ‖ PK.seed ‖ seed) - memcpy(seed, R, SPX_N); - memcpy(seed + SPX_N, pk, SPX_N); - - /* By doing this in two steps, we prevent hashing the message twice; - otherwise each iteration in MGF1 would hash the message again. */ - mgf1_X(bufp, SPX_DGST_BYTES, seed, 2 * SPX_N + SPX_SHAX_OUTPUT_BYTES); - - memcpy(digest, bufp, SPX_FORS_MSG_BYTES); - bufp += SPX_FORS_MSG_BYTES; - - - *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); - *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); - bufp += SPX_TREE_BYTES; - - *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); - *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); -} - - diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/merkle.c b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/merkle.c deleted file mode 100644 index 0c1479fd93..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/merkle.c +++ /dev/null @@ -1,59 +0,0 @@ -#include -#include - -#include "address.h" -#include "merkle.h" -#include "params.h" -#include "utils.h" -#include "utilsx1.h" -#include "wots.h" -#include "wotsx1.h" - -/* - * This generates a Merkle signature (WOTS signature followed by the Merkle - * authentication path). This is in this file because most of the complexity - * is involved with the WOTS signature; the Merkle authentication path logic - * is mostly hidden in treehashx4 - */ -void merkle_sign(uint8_t *sig, unsigned char *root, - const spx_ctx *ctx, - uint32_t wots_addr[8], uint32_t tree_addr[8], - uint32_t idx_leaf) { - unsigned char *auth_path = sig + SPX_WOTS_BYTES; - struct leaf_info_x1 info = { 0 }; - unsigned steps[ SPX_WOTS_LEN ]; - - info.wots_sig = sig; - chain_lengths(steps, root); - info.wots_steps = steps; - - set_type(&tree_addr[0], SPX_ADDR_TYPE_HASHTREE); - set_type(&info.pk_addr[0], SPX_ADDR_TYPE_WOTSPK); - copy_subtree_addr(&info.leaf_addr[0], wots_addr); - copy_subtree_addr(&info.pk_addr[0], wots_addr); - - info.wots_sign_leaf = idx_leaf; - - treehashx1(root, auth_path, ctx, - idx_leaf, 0, - SPX_TREE_HEIGHT, - wots_gen_leafx1, - tree_addr, &info); -} - -/* Compute root node of the top-most subtree. */ -void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { - /* We do not need the auth path in key generation, but it simplifies the - code to have just one treehash routine that computes both root and path - in one function. */ - unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; - uint32_t top_tree_addr[8] = {0}; - uint32_t wots_addr[8] = {0}; - - set_layer_addr(top_tree_addr, SPX_D - 1); - set_layer_addr(wots_addr, SPX_D - 1); - - merkle_sign(auth_path, root, ctx, - wots_addr, top_tree_addr, - (uint32_t)~0 /* ~0 means "don't bother generating an auth path */ ); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/merkle.h b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/merkle.h deleted file mode 100644 index 769cf2e970..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/merkle.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef MERKLE_H_ -#define MERKLE_H_ - -#include - -#include "context.h" -#include "params.h" - -/* Generate a Merkle signature (WOTS signature followed by the Merkle */ -/* authentication path) */ -#define merkle_sign SPX_NAMESPACE(merkle_sign) -void merkle_sign(uint8_t *sig, unsigned char *root, - const spx_ctx *ctx, - uint32_t wots_addr[8], uint32_t tree_addr[8], - uint32_t idx_leaf); - -/* Compute the root node of the top-most subtree. */ -#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) -void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); - -#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/nistapi.h b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/nistapi.h deleted file mode 100644 index 3cb71afad4..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/nistapi.h +++ /dev/null @@ -1,87 +0,0 @@ -#ifndef SPX_API_H -#define SPX_API_H - -#include -#include - -#include "params.h" - -#define CRYPTO_ALGNAME "SPHINCS+" - -#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES -#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES -#define CRYPTO_BYTES SPX_BYTES -#define CRYPTO_SEEDBYTES (3*SPX_N) - -/* - * Returns the length of a secret key, in bytes - */ -#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) -size_t crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) -size_t crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) -size_t crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) -size_t crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) -int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) -int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) -int crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) -int crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -#define crypto_sign SPX_NAMESPACE(crypto_sign) -int crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) -int crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/params.h b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/params.h deleted file mode 100644 index 0a47af7089..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/params.h +++ /dev/null @@ -1,61 +0,0 @@ -#ifndef SPX_PARAMS_H -#define SPX_PARAMS_H - -#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSSHA2256FROBUST_CLEAN_##s - -/* Hash output length in bytes. */ -#define SPX_N 32 -/* Height of the hypertree. */ -#define SPX_FULL_HEIGHT 68 -/* Number of subtree layer. */ -#define SPX_D 17 -/* FORS tree dimensions. */ -#define SPX_FORS_HEIGHT 9 -#define SPX_FORS_TREES 35 -/* Winternitz parameter, */ -#define SPX_WOTS_W 16 - -/* The hash function is defined by linking a different hash.c file, as opposed - to setting a #define constant. */ - -/* This is a SHA2-based parameter set, hence whether we use SHA-256 - * exclusively or we use both SHA-256 and SHA-512 is controlled by - * the following #define */ -#define SPX_SHA512 1 /* Use SHA-512 for H and T_l, l >= 2 */ - -/* For clarity */ -#define SPX_ADDR_BYTES 32 - -/* WOTS parameters. */ -#define SPX_WOTS_LOGW 4 - -#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) - -/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#define SPX_WOTS_LEN2 3 - -#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) -#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) -#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES - -/* Subtree size. */ -#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) - -//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT -// #error SPX_D should always divide SPX_FULL_HEIGHT -//#endif - -/* FORS parameters. */ -#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) -#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) -#define SPX_FORS_PK_BYTES SPX_N - -/* Resulting SPX sizes. */ -#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ - SPX_FULL_HEIGHT * SPX_N) -#define SPX_PK_BYTES (2 * SPX_N) -#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) - -#include "sha2_offsets.h" - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/sha2_offsets.h b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/sha2_offsets.h deleted file mode 100644 index 6e3584f7a4..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/sha2_offsets.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef SHA2_OFFSETS_H_ -#define SHA2_OFFSETS_H_ - -#define SPX_SHA256_BLOCK_BYTES 64 -#define SPX_SHA256_OUTPUT_BYTES 32 - -#define SPX_SHA512_BLOCK_BYTES 128 -#define SPX_SHA512_OUTPUT_BYTES 64 - -/* - * Offsets of various fields in the address structure when we use SHA2 as - * the Sphincs+ hash function - */ - -#define SPX_OFFSET_LAYER 0 /* The byte used to specify the Merkle tree layer */ -#define SPX_OFFSET_TREE 1 /* The start of the 8 byte field used to specify the tree */ -#define SPX_OFFSET_TYPE 9 /* The byte used to specify the hash type (reason) */ -#define SPX_OFFSET_KP_ADDR2 12 /* The high byte used to specify the key pair (which one-time signature) */ -#define SPX_OFFSET_KP_ADDR1 13 /* The low byte used to specify the key pair */ -#define SPX_OFFSET_CHAIN_ADDR 17 /* The byte used to specify the chain address (which Winternitz chain) */ -#define SPX_OFFSET_HASH_ADDR 21 /* The byte used to specify the hash address (where in the Winternitz chain) */ -#define SPX_OFFSET_TREE_HGT 17 /* The byte used to specify the height of this node in the FORS or Merkle tree */ -#define SPX_OFFSET_TREE_INDEX 18 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ - -#define SPX_SHA2 1 - -#endif /* SHA2_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/sign.c b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/sign.c deleted file mode 100644 index 9d0c7d1b22..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/sign.c +++ /dev/null @@ -1,286 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "context.h" -#include "fors.h" -#include "hash.h" -#include "merkle.h" -#include "nistapi.h" -#include "params.h" -#include "randombytes.h" -#include "thash.h" -#include "utils.h" -#include "wots.h" - -/* - * Returns the length of a secret key, in bytes - */ -size_t crypto_sign_secretkeybytes(void) { - return CRYPTO_SECRETKEYBYTES; -} - -/* - * Returns the length of a public key, in bytes - */ -size_t crypto_sign_publickeybytes(void) { - return CRYPTO_PUBLICKEYBYTES; -} - -/* - * Returns the length of a signature, in bytes - */ -size_t crypto_sign_bytes(void) { - return CRYPTO_BYTES; -} - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t crypto_sign_seedbytes(void) { - return CRYPTO_SEEDBYTES; -} - -/* - * Generates an SPX key pair given a seed of length - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed) { - spx_ctx ctx; - - /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ - memcpy(sk, seed, CRYPTO_SEEDBYTES); - - memcpy(pk, sk + 2 * SPX_N, SPX_N); - - memcpy(ctx.pub_seed, pk, SPX_N); - memcpy(ctx.sk_seed, sk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - /* Compute root node of the top-most subtree. */ - merkle_gen_root(sk + 3 * SPX_N, &ctx); - - // cleanup - free_hash_function(&ctx); - - memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); - - return 0; -} - -/* - * Generates an SPX key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { - uint8_t seed[CRYPTO_SEEDBYTES]; - randombytes(seed, CRYPTO_SEEDBYTES); - crypto_sign_seed_keypair(pk, sk, seed); - - return 0; -} - -/** - * Returns an array containing a detached signature. - */ -int crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - spx_ctx ctx; - - const uint8_t *sk_prf = sk + SPX_N; - const uint8_t *pk = sk + 2 * SPX_N; - - uint8_t optrand[SPX_N]; - uint8_t mhash[SPX_FORS_MSG_BYTES]; - uint8_t root[SPX_N]; - uint32_t i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - - memcpy(ctx.sk_seed, sk, SPX_N); - memcpy(ctx.pub_seed, pk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - set_type(wots_addr, SPX_ADDR_TYPE_WOTS); - set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); - - /* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ - randombytes(optrand, SPX_N); - /* Compute the digest randomization value. */ - gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); - - /* Derive the message digest and leaf index from R, PK and M. */ - hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); - sig += SPX_N; - - set_tree_addr(wots_addr, tree); - set_keypair_addr(wots_addr, idx_leaf); - - /* Sign the message hash using FORS. */ - fors_sign(sig, root, mhash, &ctx, wots_addr); - sig += SPX_FORS_BYTES; - - for (i = 0; i < SPX_D; i++) { - set_layer_addr(tree_addr, i); - set_tree_addr(tree_addr, tree); - - copy_subtree_addr(wots_addr, tree_addr); - set_keypair_addr(wots_addr, idx_leaf); - - merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); - sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); - tree = tree >> SPX_TREE_HEIGHT; - } - - free_hash_function(&ctx); - - *siglen = SPX_BYTES; - - return 0; -} - -/** - * Verifies a detached signature and message under a given public key. - */ -int crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk) { - spx_ctx ctx; - const uint8_t *pub_root = pk + SPX_N; - uint8_t mhash[SPX_FORS_MSG_BYTES]; - uint8_t wots_pk[SPX_WOTS_BYTES]; - uint8_t root[SPX_N]; - uint8_t leaf[SPX_N]; - unsigned int i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - if (siglen != SPX_BYTES) { - return -1; - } - - memcpy(ctx.pub_seed, pk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - set_type(wots_addr, SPX_ADDR_TYPE_WOTS); - set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); - set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); - - /* Derive the message digest and leaf index from R || PK || M. */ - /* The additional SPX_N is a result of the hash domain separator. */ - hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); - sig += SPX_N; - - /* Layer correctly defaults to 0, so no need to set_layer_addr */ - set_tree_addr(wots_addr, tree); - set_keypair_addr(wots_addr, idx_leaf); - - fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); - sig += SPX_FORS_BYTES; - - /* For each subtree.. */ - for (i = 0; i < SPX_D; i++) { - set_layer_addr(tree_addr, i); - set_tree_addr(tree_addr, tree); - - copy_subtree_addr(wots_addr, tree_addr); - set_keypair_addr(wots_addr, idx_leaf); - - copy_keypair_addr(wots_pk_addr, wots_addr); - - /* The WOTS public key is only correct if the signature was correct. */ - /* Initially, root is the FORS pk, but on subsequent iterations it is - the root of the subtree below the currently processed subtree. */ - wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); - sig += SPX_WOTS_BYTES; - - /* Compute the leaf node using the WOTS public key. */ - thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); - - /* Compute the root node of this subtree. */ - compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, - &ctx, tree_addr); - sig += SPX_TREE_HEIGHT * SPX_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); - tree = tree >> SPX_TREE_HEIGHT; - } - - // cleanup - free_hash_function(&ctx); - - /* Check if the root node equals the root node in the public key. */ - if (memcmp(root, pub_root, SPX_N) != 0) { - return -1; - } - - return 0; -} - - -/** - * Returns an array containing the signature followed by the message. - */ -int crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk) { - size_t siglen; - - crypto_sign_signature(sm, &siglen, m, mlen, sk); - - memmove(sm + SPX_BYTES, m, mlen); - *smlen = siglen + mlen; - - return 0; -} - -/** - * Verifies a given signature-message pair under a given public key. - */ -int crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk) { - /* The API caller does not necessarily know what size a signature should be - but SPHINCS+ signatures are always exactly SPX_BYTES. */ - if (smlen < SPX_BYTES) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - *mlen = smlen - SPX_BYTES; - - if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - /* If verification was successful, move the message to the right place. */ - memmove(m, sm + SPX_BYTES, *mlen); - - return 0; -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/thash.h b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/thash.h deleted file mode 100644 index 8687ccfb4d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/thash.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef SPX_THASH_H -#define SPX_THASH_H - -#include "context.h" -#include "params.h" - -#include - -#define thash SPX_NAMESPACE(thash) -void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/thash_sha2_robust.c b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/thash_sha2_robust.c deleted file mode 100644 index 3ab891175f..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/thash_sha2_robust.c +++ /dev/null @@ -1,68 +0,0 @@ -#include -#include - -#include "address.h" -#include "context.h" -#include "hash.h" -#include "params.h" -#include "sha2.h" -#include "thash.h" -#include "utils.h" - -static void thash_512(unsigned char *out, const unsigned char *in, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]); - -/** - * Takes an array of inblocks concatenated arrays of SPX_N bytes. - */ -void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]) { - if (inblocks > 1) { - thash_512(out, in, inblocks, ctx, addr); - return; - } - unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES]; - PQCLEAN_VLA(uint8_t, bitmask, inblocks * SPX_N); - PQCLEAN_VLA(uint8_t, buf, SPX_N + SPX_SHA256_OUTPUT_BYTES + inblocks * SPX_N); - sha256ctx sha2_state; - unsigned int i; - - memcpy(buf, ctx->pub_seed, SPX_N); - memcpy(buf + SPX_N, addr, SPX_SHA256_ADDR_BYTES); - mgf1_256(bitmask, inblocks * SPX_N, buf, SPX_N + SPX_SHA256_ADDR_BYTES); - - /* Retrieve precomputed state containing pub_seed */ - sha256_inc_ctx_clone(&sha2_state, &ctx->state_seeded); - - for (i = 0; i < inblocks * SPX_N; i++) { - buf[SPX_N + SPX_SHA256_ADDR_BYTES + i] = in[i] ^ bitmask[i]; - } - - sha256_inc_finalize(outbuf, &sha2_state, buf + SPX_N, - SPX_SHA256_ADDR_BYTES + inblocks * SPX_N); - memcpy(out, outbuf, SPX_N); -} - -static void thash_512(unsigned char *out, const unsigned char *in, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]) { - unsigned char outbuf[SPX_SHA512_OUTPUT_BYTES]; - PQCLEAN_VLA(uint8_t, bitmask, inblocks * SPX_N); - PQCLEAN_VLA(uint8_t, buf, SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N); - sha512ctx sha2_state; - unsigned int i; - - memcpy(buf, ctx->pub_seed, SPX_N); - memcpy(buf + SPX_N, addr, SPX_SHA256_ADDR_BYTES); - mgf1_512(bitmask, inblocks * SPX_N, buf, SPX_N + SPX_SHA256_ADDR_BYTES); - - /* Retrieve precomputed state containing pub_seed */ - sha512_inc_ctx_clone(&sha2_state, &ctx->state_seeded_512); - - for (i = 0; i < inblocks * SPX_N; i++) { - buf[SPX_N + SPX_SHA256_ADDR_BYTES + i] = in[i] ^ bitmask[i]; - } - - sha512_inc_finalize(outbuf, &sha2_state, buf + SPX_N, - SPX_SHA256_ADDR_BYTES + inblocks * SPX_N); - memcpy(out, outbuf, SPX_N); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/utils.c b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/utils.c deleted file mode 100644 index 177b541fb9..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/utils.c +++ /dev/null @@ -1,148 +0,0 @@ -#include - -#include "utils.h" - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "thash.h" - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void ull_to_bytes(unsigned char *out, unsigned int outlen, - unsigned long long in) { - int i; - - /* Iterate over out in decreasing order, for big-endianness. */ - for (i = (signed int)outlen - 1; i >= 0; i--) { - out[i] = in & 0xff; - in = in >> 8; - } -} - -void u32_to_bytes(unsigned char *out, uint32_t in) { - out[0] = (unsigned char)(in >> 24); - out[1] = (unsigned char)(in >> 16); - out[2] = (unsigned char)(in >> 8); - out[3] = (unsigned char)in; -} - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { - unsigned long long retval = 0; - unsigned int i; - - for (i = 0; i < inlen; i++) { - retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); - } - return retval; -} - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void compute_root(unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const spx_ctx *ctx, uint32_t addr[8]) { - uint32_t i; - unsigned char buffer[2 * SPX_N]; - - /* If leaf_idx is odd (last bit = 1), current path element is a right child - and auth_path has to go left. Otherwise it is the other way around. */ - if (leaf_idx & 1) { - memcpy(buffer + SPX_N, leaf, SPX_N); - memcpy(buffer, auth_path, SPX_N); - } else { - memcpy(buffer, leaf, SPX_N); - memcpy(buffer + SPX_N, auth_path, SPX_N); - } - auth_path += SPX_N; - - for (i = 0; i < tree_height - 1; i++) { - leaf_idx >>= 1; - idx_offset >>= 1; - /* Set the address of the node we're creating. */ - set_tree_height(addr, i + 1); - set_tree_index(addr, leaf_idx + idx_offset); - - /* Pick the right or left neighbor, depending on parity of the node. */ - if (leaf_idx & 1) { - thash(buffer + SPX_N, buffer, 2, ctx, addr); - memcpy(buffer, auth_path, SPX_N); - } else { - thash(buffer, buffer, 2, ctx, addr); - memcpy(buffer + SPX_N, auth_path, SPX_N); - } - auth_path += SPX_N; - } - - /* The last iteration is exceptional; we do not copy an auth_path node. */ - leaf_idx >>= 1; - idx_offset >>= 1; - set_tree_height(addr, tree_height); - set_tree_index(addr, leaf_idx + idx_offset); - thash(root, buffer, 2, ctx, addr); -} - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const spx_ctx * /* ctx */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), - uint32_t tree_addr[8]) { - PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); - PQCLEAN_VLA(unsigned int, heights, tree_height + 1); - unsigned int offset = 0; - uint32_t idx; - uint32_t tree_idx; - - for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { - /* Add the next leaf node to the stack. */ - gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); - offset++; - heights[offset - 1] = 0; - - /* If this is a node we need for the auth path.. */ - if ((leaf_idx ^ 0x1) == idx) { - memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); - } - - /* While the top-most nodes are of equal height.. */ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { - /* Compute index of the new node, in the next layer. */ - tree_idx = (idx >> (heights[offset - 1] + 1)); - - /* Set the address of the node we're creating. */ - set_tree_height(tree_addr, heights[offset - 1] + 1); - set_tree_index(tree_addr, - tree_idx + (idx_offset >> (heights[offset - 1] + 1))); - /* Hash the top-most nodes from the stack together. */ - thash(stack + (offset - 2)*SPX_N, - stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); - offset--; - /* Note that the top-most node is now one layer higher. */ - heights[offset - 1]++; - - /* If this is a node we need for the auth path.. */ - if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_path + heights[offset - 1]*SPX_N, - stack + (offset - 1)*SPX_N, SPX_N); - } - } - } - memcpy(root, stack, SPX_N); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/utils.h b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/utils.h deleted file mode 100644 index 64f5d5a53a..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/utils.h +++ /dev/null @@ -1,58 +0,0 @@ -#ifndef SPX_UTILS_H -#define SPX_UTILS_H - -#include - -#include "compat.h" -#include "context.h" -#include "params.h" - - -/* To support MSVC use alloca() instead of VLAs. See #20. */ - - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) -void ull_to_bytes(unsigned char *out, unsigned int outlen, - unsigned long long in); -#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) -void u32_to_bytes(unsigned char *out, uint32_t in); - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) -unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -#define compute_root SPX_NAMESPACE(compute_root) -void compute_root(unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const spx_ctx *ctx, uint32_t addr[8]); - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -#define treehash SPX_NAMESPACE(treehash) -void treehash(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const spx_ctx *ctx /* ctx */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), - uint32_t tree_addr[8]); - - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/utilsx1.c b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/utilsx1.c deleted file mode 100644 index fccb69b35d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/utilsx1.c +++ /dev/null @@ -1,100 +0,0 @@ -#include - -#include "utilsx1.h" - -#include "address.h" -#include "params.h" -#include "thash.h" -#include "utils.h" - -/* - * Generate the entire Merkle tree, computing the authentication path for - * leaf_idx, and the resulting root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) - * - * This expects tree_addr to be initialized to the addr structures for the - * Merkle tree nodes - * - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - * - * This works by using the standard Merkle tree building algorithm, - */ -void treehashx1(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, - uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* Where to write the leaves */, - const spx_ctx * /* ctx */, - uint32_t idx, void *info), - uint32_t tree_addr[8], - void *info) { - /* This is where we keep the intermediate nodes */ - PQCLEAN_VLA(uint8_t, stack, tree_height * SPX_N); - - uint32_t idx; - uint32_t max_idx = (uint32_t)((1 << tree_height) - 1); - for (idx = 0;; idx++) { - unsigned char current[2 * SPX_N]; /* Current logical node is at */ - /* index[SPX_N]. We do this to minimize the number of copies */ - /* needed during a thash */ - gen_leaf( ¤t[SPX_N], ctx, idx + idx_offset, - info ); - - /* Now combine the freshly generated right node with previously */ - /* generated left ones */ - uint32_t internal_idx_offset = idx_offset; - uint32_t internal_idx = idx; - uint32_t internal_leaf = leaf_idx; - uint32_t h; /* The height we are in the Merkle tree */ - for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { - - /* Check if we hit the top of the tree */ - if (h == tree_height) { - /* We hit the root; return it */ - memcpy( root, ¤t[SPX_N], SPX_N ); - return; - } - - /* - * Check if the node we have is a part of the - * authentication path; if it is, write it out - */ - if ((internal_idx ^ internal_leaf) == 0x01) { - memcpy( &auth_path[ h * SPX_N ], - ¤t[SPX_N], - SPX_N ); - } - - /* - * Check if we're at a left child; if so, stop going up the stack - * Exception: if we've reached the end of the tree, keep on going - * (so we combine the last 4 nodes into the one root node in two - * more iterations) - */ - if ((internal_idx & 1) == 0 && idx < max_idx) { - break; - } - - /* Ok, we're at a right node */ - /* Now combine the left and right logical nodes together */ - - /* Set the address of the node we're creating. */ - internal_idx_offset >>= 1; - set_tree_height(tree_addr, h + 1); - set_tree_index(tree_addr, internal_idx / 2 + internal_idx_offset ); - - unsigned char *left = &stack[h * SPX_N]; - memcpy( ¤t[0], left, SPX_N ); - thash( ¤t[1 * SPX_N], - ¤t[0 * SPX_N], - 2, ctx, tree_addr); - } - - /* We've hit a left child; save the current for when we get the */ - /* corresponding right right */ - memcpy( &stack[h * SPX_N], ¤t[SPX_N], SPX_N); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/utilsx1.h b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/utilsx1.h deleted file mode 100644 index e911d17d53..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/utilsx1.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef SPX_UTILSX4_H -#define SPX_UTILSX4_H - -#include - -#include "context.h" -#include "params.h" - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -#define treehashx1 SPX_NAMESPACE(treehashx1) -void treehashx1(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* Where to write the leaf */, - const spx_ctx * /* ctx */, - uint32_t addr_idx, void *info), - uint32_t tree_addrx4[8], void *info); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/wots.c b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/wots.c deleted file mode 100644 index 249717aaa8..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/wots.c +++ /dev/null @@ -1,108 +0,0 @@ -#include -#include - -#include "wots.h" -#include "wotsx1.h" - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "thash.h" -#include "utils.h" -#include "utilsx1.h" - -// TODO clarify address expectations, and make them more uniform. -// TODO i.e. do we expect types to be set already? -// TODO and do we expect modifications or copies? - -/** - * Computes the chaining function. - * out and in have to be n-byte arrays. - * - * Interprets in as start-th value of the chain. - * addr has to contain the address of the chain. - */ -static void gen_chain(unsigned char *out, const unsigned char *in, - unsigned int start, unsigned int steps, - const spx_ctx *ctx, uint32_t addr[8]) { - uint32_t i; - - /* Initialize out with the value at position 'start'. */ - memcpy(out, in, SPX_N); - - /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < SPX_WOTS_W; i++) { - set_hash_addr(addr, i); - thash(out, out, 1, ctx, addr); - } -} - -/** - * base_w algorithm as described in draft. - * Interprets an array of bytes as integers in base w. - * This only works when log_w is a divisor of 8. - */ -static void base_w(unsigned int *output, const int out_len, - const unsigned char *input) { - int in = 0; - int out = 0; - unsigned char total = 0; - int bits = 0; - int consumed; - - for (consumed = 0; consumed < out_len; consumed++) { - if (bits == 0) { - total = input[in]; - in++; - bits += 8; - } - bits -= SPX_WOTS_LOGW; - output[out] = (total >> bits) & (SPX_WOTS_W - 1); - out++; - } -} - -/* Computes the WOTS+ checksum over a message (in base_w). */ -static void wots_checksum(unsigned int *csum_base_w, - const unsigned int *msg_base_w) { - unsigned int csum = 0; - unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; - unsigned int i; - - /* Compute checksum. */ - for (i = 0; i < SPX_WOTS_LEN1; i++) { - csum += SPX_WOTS_W - 1 - msg_base_w[i]; - } - - /* Convert checksum to base_w. */ - /* Make sure expected empty zero bits are the least significant bits. */ - csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); - ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); - base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); -} - -/* Takes a message and derives the matching chain lengths. */ -void chain_lengths(unsigned int *lengths, const unsigned char *msg) { - base_w(lengths, SPX_WOTS_LEN1, msg); - wots_checksum(lengths + SPX_WOTS_LEN1, lengths); -} - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const spx_ctx *ctx, uint32_t addr[8]) { - unsigned int lengths[SPX_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < SPX_WOTS_LEN; i++) { - set_chain_addr(addr, i); - gen_chain(pk + i * SPX_N, sig + i * SPX_N, - lengths[i], SPX_WOTS_W - 1 - lengths[i], ctx, addr); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/wots.h b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/wots.h deleted file mode 100644 index 4e7692eeef..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/wots.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef SPX_WOTS_H -#define SPX_WOTS_H - -#include - -#include "context.h" -#include "params.h" - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) -void wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const spx_ctx *ctx, uint32_t addr[8]); - -/* - * Compute the chain lengths needed for a given message hash - */ -#define chain_lengths SPX_NAMESPACE(chain_lengths) -void chain_lengths(unsigned int *lengths, const unsigned char *msg); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/wotsx1.c b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/wotsx1.c deleted file mode 100644 index 3adec78dfb..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/wotsx1.c +++ /dev/null @@ -1,76 +0,0 @@ -#include -#include - -#include "wots.h" -#include "wotsx1.h" - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "thash.h" -#include "utils.h" - -/* - * This generates a WOTS public key - * It also generates the WOTS signature if leaf_info indicates - * that we're signing with this WOTS key - */ -void wots_gen_leafx1(unsigned char *dest, - const spx_ctx *ctx, - uint32_t leaf_idx, void *v_info) { - struct leaf_info_x1 *info = v_info; - uint32_t *leaf_addr = info->leaf_addr; - uint32_t *pk_addr = info->pk_addr; - unsigned int i, k; - unsigned char pk_buffer[ SPX_WOTS_BYTES ]; - unsigned char *buffer; - uint32_t wots_k_mask; - - if (leaf_idx == info->wots_sign_leaf) { - /* We're traversing the leaf that's signing; generate the WOTS */ - /* signature */ - wots_k_mask = 0; - } else { - /* Nope, we're just generating pk's; turn off the signature logic */ - wots_k_mask = (uint32_t)~0; - } - - set_keypair_addr( leaf_addr, leaf_idx ); - set_keypair_addr( pk_addr, leaf_idx ); - - for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { - uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k to */ - /* the step if we're generating a signature, ~0 if we're not */ - - /* Start with the secret seed */ - set_chain_addr(leaf_addr, i); - set_hash_addr(leaf_addr, 0); - set_type(leaf_addr, SPX_ADDR_TYPE_WOTSPRF); - - prf_addr(buffer, ctx, leaf_addr); - - set_type(leaf_addr, SPX_ADDR_TYPE_WOTS); - - /* Iterate down the WOTS chain */ - for (k = 0;; k++) { - /* Check if this is the value that needs to be saved as a */ - /* part of the WOTS signature */ - if (k == wots_k) { - memcpy( info->wots_sig + i * SPX_N, buffer, SPX_N ); - } - - /* Check if we hit the top of the chain */ - if (k == SPX_WOTS_W - 1) { - break; - } - - /* Iterate one step on the chain */ - set_hash_addr(leaf_addr, k); - - thash(buffer, buffer, 1, ctx, leaf_addr); - } - } - - /* Do the final thash to generate the public keys */ - thash(dest, pk_buffer, SPX_WOTS_LEN, ctx, pk_addr); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/wotsx1.h b/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/wotsx1.h deleted file mode 100644 index e617929f96..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-256f-robust_clean/wotsx1.h +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef WOTSX1_H_ -#define WOTSX1_H_ - -#include - -#include "context.h" -#include "params.h" - -/* - * This is here to provide an interface to the internal wots_gen_leafx1 - * routine. While this routine is not referenced in the package outside of - * wots.c, it is called from the stand-alone benchmark code to characterize - * the performance - */ -struct leaf_info_x1 { - unsigned char *wots_sig; - uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ - uint32_t *wots_steps; - uint32_t leaf_addr[8]; - uint32_t pk_addr[8]; -}; - -/* Macro to set the leaf_info to something 'benign', that is, it would */ -/* run with the same time as it does during the real signing process */ -/* Used only by the benchmark code */ -#define INITIALIZE_LEAF_INFO_X1(info, addr, step_buffer) { \ - (info).wots_sig = 0; \ - (info).wots_sign_leaf = ~0; \ - (info).wots_steps = step_buffer; \ - memcpy( &(info).leaf_addr[0], (addr), 32 ); \ - memcpy( &(info).pk_addr[0], (addr), 32 ); \ - } - -#define wots_gen_leafx1 SPX_NAMESPACE(wots_gen_leafx1) -void wots_gen_leafx1(unsigned char *dest, - const spx_ctx *ctx, - uint32_t leaf_idx, void *v_info); - -#endif /* WOTSX1_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/LICENSE b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/LICENSE deleted file mode 100644 index 670154e353..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/LICENSE +++ /dev/null @@ -1,116 +0,0 @@ -CC0 1.0 Universal - -Statement of Purpose - -The laws of most jurisdictions throughout the world automatically confer -exclusive Copyright and Related Rights (defined below) upon the creator and -subsequent owner(s) (each and all, an "owner") of an original work of -authorship and/or a database (each, a "Work"). - -Certain owners wish to permanently relinquish those rights to a Work for the -purpose of contributing to a commons of creative, cultural and scientific -works ("Commons") that the public can reliably and without fear of later -claims of infringement build upon, modify, incorporate in other works, reuse -and redistribute as freely as possible in any form whatsoever and for any -purposes, including without limitation commercial purposes. These owners may -contribute to the Commons to promote the ideal of a free culture and the -further production of creative, cultural and scientific works, or to gain -reputation or greater distribution for their Work in part through the use and -efforts of others. - -For these and/or other purposes and motivations, and without any expectation -of additional consideration or compensation, the person associating CC0 with a -Work (the "Affirmer"), to the extent that he or she is an owner of Copyright -and Related Rights in the Work, voluntarily elects to apply CC0 to the Work -and publicly distribute the Work under its terms, with knowledge of his or her -Copyright and Related Rights in the Work and the meaning and intended legal -effect of CC0 on those rights. - -1. Copyright and Related Rights. A Work made available under CC0 may be -protected by copyright and related or neighboring rights ("Copyright and -Related Rights"). Copyright and Related Rights include, but are not limited -to, the following: - - i. the right to reproduce, adapt, distribute, perform, display, communicate, - and translate a Work; - - ii. moral rights retained by the original author(s) and/or performer(s); - - iii. publicity and privacy rights pertaining to a person's image or likeness - depicted in a Work; - - iv. rights protecting against unfair competition in regards to a Work, - subject to the limitations in paragraph 4(a), below; - - v. rights protecting the extraction, dissemination, use and reuse of data in - a Work; - - vi. database rights (such as those arising under Directive 96/9/EC of the - European Parliament and of the Council of 11 March 1996 on the legal - protection of databases, and under any national implementation thereof, - including any amended or successor version of such directive); and - - vii. other similar, equivalent or corresponding rights throughout the world - based on applicable law or treaty, and any national implementations thereof. - -2. Waiver. To the greatest extent permitted by, but not in contravention of, -applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and -unconditionally waives, abandons, and surrenders all of Affirmer's Copyright -and Related Rights and associated claims and causes of action, whether now -known or unknown (including existing as well as future claims and causes of -action), in the Work (i) in all territories worldwide, (ii) for the maximum -duration provided by applicable law or treaty (including future time -extensions), (iii) in any current or future medium and for any number of -copies, and (iv) for any purpose whatsoever, including without limitation -commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes -the Waiver for the benefit of each member of the public at large and to the -detriment of Affirmer's heirs and successors, fully intending that such Waiver -shall not be subject to revocation, rescission, cancellation, termination, or -any other legal or equitable action to disrupt the quiet enjoyment of the Work -by the public as contemplated by Affirmer's express Statement of Purpose. - -3. Public License Fallback. Should any part of the Waiver for any reason be -judged legally invalid or ineffective under applicable law, then the Waiver -shall be preserved to the maximum extent permitted taking into account -Affirmer's express Statement of Purpose. In addition, to the extent the Waiver -is so judged Affirmer hereby grants to each affected person a royalty-free, -non transferable, non sublicensable, non exclusive, irrevocable and -unconditional license to exercise Affirmer's Copyright and Related Rights in -the Work (i) in all territories worldwide, (ii) for the maximum duration -provided by applicable law or treaty (including future time extensions), (iii) -in any current or future medium and for any number of copies, and (iv) for any -purpose whatsoever, including without limitation commercial, advertising or -promotional purposes (the "License"). The License shall be deemed effective as -of the date CC0 was applied by Affirmer to the Work. Should any part of the -License for any reason be judged legally invalid or ineffective under -applicable law, such partial invalidity or ineffectiveness shall not -invalidate the remainder of the License, and in such case Affirmer hereby -affirms that he or she will not (i) exercise any of his or her remaining -Copyright and Related Rights in the Work or (ii) assert any associated claims -and causes of action with respect to the Work, in either case contrary to -Affirmer's express Statement of Purpose. - -4. Limitations and Disclaimers. - - a. No trademark or patent rights held by Affirmer are waived, abandoned, - surrendered, licensed or otherwise affected by this document. - - b. Affirmer offers the Work as-is and makes no representations or warranties - of any kind concerning the Work, express, implied, statutory or otherwise, - including without limitation warranties of title, merchantability, fitness - for a particular purpose, non infringement, or the absence of latent or - other defects, accuracy, or the present or absence of errors, whether or not - discoverable, all to the greatest extent permissible under applicable law. - - c. Affirmer disclaims responsibility for clearing rights of other persons - that may apply to the Work or any use thereof, including without limitation - any person's Copyright and Related Rights in the Work. Further, Affirmer - disclaims responsibility for obtaining any necessary consents, permissions - or other rights required for any use of the Work. - - d. Affirmer understands and acknowledges that Creative Commons is not a - party to this document and has no duty or obligation with respect to this - CC0 or use of the Work. - -For more information, please see - diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/address.c b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/address.c deleted file mode 100644 index b956e9cb29..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/address.c +++ /dev/null @@ -1,91 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "utils.h" - -/* - * Specify which level of Merkle tree (the "layer") we're working on - */ -void set_layer_addr(uint32_t addr[8], uint32_t layer) { - ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; -} - -/* - * Specify which Merkle tree within the level (the "tree address") we're working on - */ -void set_tree_addr(uint32_t addr[8], uint64_t tree) { - ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); -} - -/* - * Specify the reason we'll use this address structure for, that is, what - * hash will we compute with it. This is used so that unrelated types of - * hashes don't accidentally get the same address structure. The type will be - * one of the SPX_ADDR_TYPE constants - */ -void set_type(uint32_t addr[8], uint32_t type) { - ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; -} - -/* - * Copy the layer and tree fields of the address structure. This is used - * when we're doing multiple types of hashes within the same Merkle tree - */ -void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { - memcpy( out, in, SPX_OFFSET_TREE + 8 ); -} - -/* These functions are used for OTS addresses. */ - -/* - * Specify which Merkle leaf we're working on; that is, which OTS keypair - * we're talking about. - */ -void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { - ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; -} - -/* - * Copy the layer, tree and keypair fields of the address structure. This is - * used when we're doing multiple things within the same OTS keypair - */ -void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { - memcpy( out, in, SPX_OFFSET_TREE + 8 ); - ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; -} - -/* - * Specify which Merkle chain within the OTS we're working with - * (the chain address) - */ -void set_chain_addr(uint32_t addr[8], uint32_t chain) { - ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; -} - -/* - * Specify where in the Merkle chain we are -* (the hash address) - */ -void set_hash_addr(uint32_t addr[8], uint32_t hash) { - ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; -} - -/* These functions are used for all hash tree addresses (including FORS). */ - -/* - * Specify the height of the node in the Merkle/FORS tree we are in - * (the tree height) - */ -void set_tree_height(uint32_t addr[8], uint32_t tree_height) { - ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; -} - -/* - * Specify the distance from the left edge of the node in the Merkle/FORS tree - * (the tree index) - */ -void set_tree_index(uint32_t addr[8], uint32_t tree_index) { - u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/address.h b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/address.h deleted file mode 100644 index 24a84eb40c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/address.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef SPX_ADDRESS_H -#define SPX_ADDRESS_H - -#include - -#include "params.h" - -/* The hash types that are passed to set_type */ -#define SPX_ADDR_TYPE_WOTS 0 -#define SPX_ADDR_TYPE_WOTSPK 1 -#define SPX_ADDR_TYPE_HASHTREE 2 -#define SPX_ADDR_TYPE_FORSTREE 3 -#define SPX_ADDR_TYPE_FORSPK 4 -#define SPX_ADDR_TYPE_WOTSPRF 5 -#define SPX_ADDR_TYPE_FORSPRF 6 - -#define set_layer_addr SPX_NAMESPACE(set_layer_addr) -void set_layer_addr(uint32_t addr[8], uint32_t layer); - -#define set_tree_addr SPX_NAMESPACE(set_tree_addr) -void set_tree_addr(uint32_t addr[8], uint64_t tree); - -#define set_type SPX_NAMESPACE(set_type) -void set_type(uint32_t addr[8], uint32_t type); - -/* Copies the layer and tree part of one address into the other */ -#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) -void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for WOTS and FORS addresses. */ - -#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) -void set_keypair_addr(uint32_t addr[8], uint32_t keypair); - -#define set_chain_addr SPX_NAMESPACE(set_chain_addr) -void set_chain_addr(uint32_t addr[8], uint32_t chain); - -#define set_hash_addr SPX_NAMESPACE(set_hash_addr) -void set_hash_addr(uint32_t addr[8], uint32_t hash); - -#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) -void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for all hash tree addresses (including FORS). */ - -#define set_tree_height SPX_NAMESPACE(set_tree_height) -void set_tree_height(uint32_t addr[8], uint32_t tree_height); - -#define set_tree_index SPX_NAMESPACE(set_tree_index) -void set_tree_index(uint32_t addr[8], uint32_t tree_index); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/api.h b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/api.h deleted file mode 100644 index 9427be0824..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/api.h +++ /dev/null @@ -1,77 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA2256SROBUST_AVX2_API_H -#define PQCLEAN_SPHINCSSHA2256SROBUST_AVX2_API_H - -#include -#include - -#define PQCLEAN_SPHINCSSHA2256SROBUST_AVX2_CRYPTO_ALGNAME "SPHINCS+-sha2-256s-robust" - -#define PQCLEAN_SPHINCSSHA2256SROBUST_AVX2_CRYPTO_SECRETKEYBYTES 128 -#define PQCLEAN_SPHINCSSHA2256SROBUST_AVX2_CRYPTO_PUBLICKEYBYTES 64 -#define PQCLEAN_SPHINCSSHA2256SROBUST_AVX2_CRYPTO_BYTES 29792 - -#define PQCLEAN_SPHINCSSHA2256SROBUST_AVX2_CRYPTO_SEEDBYTES 96 - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSSHA2256SROBUST_AVX2_crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSSHA2256SROBUST_AVX2_crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSSHA2256SROBUST_AVX2_crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSSHA2256SROBUST_AVX2_crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHA2256SROBUST_AVX2_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHA2256SROBUST_AVX2_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSSHA2256SROBUST_AVX2_crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSSHA2256SROBUST_AVX2_crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, - const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSSHA2256SROBUST_AVX2_crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSSHA2256SROBUST_AVX2_crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk); -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/context.h b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/context.h deleted file mode 100644 index d3bf1c3aac..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/context.h +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef SPX_CONTEXT_H -#define SPX_CONTEXT_H - -#include - -#include "params.h" -#include "sha2.h" -#include "sha256avx.h" -#include "sha512x4.h" - -// funky ordering due to optimal padding -typedef struct { - sha256x8ctx statex8_seeded; - sha512x4ctx statex4_seeded_512; - sha256ctx state_seeded; - sha512ctx state_seeded_512; - - uint8_t pub_seed[SPX_N]; - uint8_t sk_seed[SPX_N]; -} spx_ctx; - - -#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) -void initialize_hash_function(spx_ctx *ctx); - -#define free_hash_function SPX_NAMESPACE(free_hash_function) -void free_hash_function(spx_ctx *ctx); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/context_sha2.c b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/context_sha2.c deleted file mode 100644 index 83c1b6585d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/context_sha2.c +++ /dev/null @@ -1,56 +0,0 @@ -#include - -#include "context.h" - -/** - * Absorb the constant pub_seed using one round of the compression function - * This initializes state_seeded and state_seeded_512, which can then be - * reused in thash - **/ -static void seed_state(spx_ctx *ctx) { - uint8_t block[SPX_SHA512_BLOCK_BYTES]; - size_t i; - - for (i = 0; i < SPX_N; ++i) { - block[i] = ctx->pub_seed[i]; - } - for (i = SPX_N; i < SPX_SHA512_BLOCK_BYTES; ++i) { - block[i] = 0; - } - /* block has been properly initialized for both SHA-256 and SHA-512 */ - - sha256_inc_init(&ctx->state_seeded); - sha256_inc_blocks(&ctx->state_seeded, block, 1); - - // initialize x8 - sha256_init8x(&ctx->statex8_seeded); - sha256_transform8x(&ctx->statex8_seeded, - block, block, block, block, block, block, block, block); - - ctx->statex8_seeded.datalen = 0; - ctx->statex8_seeded.msglen = 512; - - sha512_inc_init(&ctx->state_seeded_512); - sha512_inc_blocks(&ctx->state_seeded_512, block, 1); - - // initialize x4 - sha512_init4x(&ctx->statex4_seeded_512); - sha512_transform4x(&ctx->statex4_seeded_512, block, block, block, block); - - ctx->statex4_seeded_512.datalen = 0; - ctx->statex4_seeded_512.msglen = 1024; - - -} - - -/* For SHA, we initialize the hash function at the start */ -void initialize_hash_function(spx_ctx *ctx) { - seed_state(ctx); -} - -/* Free the incremental hashing context for heap-based SHA2 APIs */ -void free_hash_function(spx_ctx *ctx) { - sha256_inc_ctx_release(&ctx->state_seeded); - sha512_inc_ctx_release(&ctx->state_seeded_512); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/fors.c b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/fors.c deleted file mode 100644 index 4cab8e7415..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/fors.c +++ /dev/null @@ -1,226 +0,0 @@ -#include -#include -#include - -#include "fors.h" - - -#include "address.h" -#include "hash.h" -#include "hashx8.h" -#include "thash.h" -#include "thashx8.h" -#include "utils.h" -#include "utilsx8.h" -static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, - uint32_t fors_leaf_addr[8]) { - prf_addr(sk, ctx, fors_leaf_addr); -} - -static void fors_gen_skx8(unsigned char *sk0, - unsigned char *sk1, - unsigned char *sk2, - unsigned char *sk3, - unsigned char *sk4, - unsigned char *sk5, - unsigned char *sk6, - unsigned char *sk7, const spx_ctx *ctx, - uint32_t fors_leaf_addrx8[8 * 8]) { - prf_addrx8(sk0, sk1, sk2, sk3, sk4, sk5, sk6, sk7, - ctx, fors_leaf_addrx8); -} - -static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, - const spx_ctx *ctx, - uint32_t fors_leaf_addr[8]) { - thash(leaf, sk, 1, ctx, fors_leaf_addr); -} - -static void fors_sk_to_leafx8(unsigned char *leaf0, - unsigned char *leaf1, - unsigned char *leaf2, - unsigned char *leaf3, - unsigned char *leaf4, - unsigned char *leaf5, - unsigned char *leaf6, - unsigned char *leaf7, - const unsigned char *sk0, - const unsigned char *sk1, - const unsigned char *sk2, - const unsigned char *sk3, - const unsigned char *sk4, - const unsigned char *sk5, - const unsigned char *sk6, - const unsigned char *sk7, - const spx_ctx *ctx, - uint32_t fors_leaf_addrx8[8 * 8]) { - thashx8(leaf0, leaf1, leaf2, leaf3, leaf4, leaf5, leaf6, leaf7, - sk0, sk1, sk2, sk3, sk4, sk5, sk6, sk7, - 1, ctx, fors_leaf_addrx8); -} - -struct fors_gen_leaf_info { - uint32_t leaf_addrx[8 * 8]; -}; - -static void fors_gen_leafx8(unsigned char *leaf, - const spx_ctx *ctx, - uint32_t addr_idx, void *info) { - struct fors_gen_leaf_info *fors_info = info; - uint32_t *fors_leaf_addrx8 = fors_info->leaf_addrx; - unsigned int j; - - /* Only set the parts that the caller doesn't set */ - for (j = 0; j < 8; j++) { - set_tree_index(fors_leaf_addrx8 + j * 8, addr_idx + j); - set_type(fors_leaf_addrx8 + j * 8, SPX_ADDR_TYPE_FORSPRF); - } - - fors_gen_skx8(leaf + 0 * SPX_N, - leaf + 1 * SPX_N, - leaf + 2 * SPX_N, - leaf + 3 * SPX_N, - leaf + 4 * SPX_N, - leaf + 5 * SPX_N, - leaf + 6 * SPX_N, - leaf + 7 * SPX_N, - ctx, fors_leaf_addrx8); - - for (j = 0; j < 8; j++) { - set_type(fors_leaf_addrx8 + j * 8, SPX_ADDR_TYPE_FORSTREE); - } - - fors_sk_to_leafx8(leaf + 0 * SPX_N, - leaf + 1 * SPX_N, - leaf + 2 * SPX_N, - leaf + 3 * SPX_N, - leaf + 4 * SPX_N, - leaf + 5 * SPX_N, - leaf + 6 * SPX_N, - leaf + 7 * SPX_N, - leaf + 0 * SPX_N, - leaf + 1 * SPX_N, - leaf + 2 * SPX_N, - leaf + 3 * SPX_N, - leaf + 4 * SPX_N, - leaf + 5 * SPX_N, - leaf + 6 * SPX_N, - leaf + 7 * SPX_N, - ctx, fors_leaf_addrx8); -} - -/** - * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - * Assumes indices has space for SPX_FORS_TREES integers. - */ -static void message_to_indices(uint32_t *indices, const unsigned char *m) { - unsigned int i, j; - unsigned int offset = 0; - - for (i = 0; i < SPX_FORS_TREES; i++) { - indices[i] = 0; - for (j = 0; j < SPX_FORS_HEIGHT; j++) { - indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); - offset++; - } - } -} - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -void fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]) { - uint32_t indices[SPX_FORS_TREES]; - unsigned char roots[SPX_FORS_TREES * SPX_N]; - uint32_t fors_tree_addr[8 * 8] = {0}; - struct fors_gen_leaf_info fors_info = {0}; - uint32_t *fors_leaf_addr = fors_info.leaf_addrx; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - for (i = 0; i < 8; i++) { - copy_keypair_addr(fors_tree_addr + 8 * i, fors_addr); - set_type(fors_tree_addr + 8 * i, SPX_ADDR_TYPE_FORSTREE); - copy_keypair_addr(fors_leaf_addr + 8 * i, fors_addr); - } - copy_keypair_addr(fors_pk_addr, fors_addr); - set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < SPX_FORS_TREES; i++) { - idx_offset = i * (1 << SPX_FORS_HEIGHT); - - set_tree_height(fors_tree_addr, 0); - set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Include the secret key part that produces the selected leaf node. */ - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); - fors_gen_sk(sig, ctx, fors_tree_addr); - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); - sig += SPX_N; - - /* Compute the authentication path for this leaf node. */ - treehashx8(roots + i * SPX_N, sig, ctx, - indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx8, - fors_tree_addr, &fors_info); - - sig += SPX_N * SPX_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); -} - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -void fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]) { - uint32_t indices[SPX_FORS_TREES]; - unsigned char roots[SPX_FORS_TREES * SPX_N]; - unsigned char leaf[SPX_N]; - uint32_t fors_tree_addr[8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - copy_keypair_addr(fors_tree_addr, fors_addr); - copy_keypair_addr(fors_pk_addr, fors_addr); - - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); - set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < SPX_FORS_TREES; i++) { - idx_offset = i * (1 << SPX_FORS_HEIGHT); - - set_tree_height(fors_tree_addr, 0); - set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Derive the leaf from the included secret key part. */ - fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); - sig += SPX_N; - - /* Derive the corresponding root node of this tree. */ - compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, - sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); - sig += SPX_N * SPX_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/fors.h b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/fors.h deleted file mode 100644 index 509140a178..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/fors.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef SPX_FORS_H -#define SPX_FORS_H - -#include - -#include "context.h" -#include "params.h" - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -#define fors_sign SPX_NAMESPACE(fors_sign) -void fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]); - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) -void fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/hash.h b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/hash.h deleted file mode 100644 index ffe815f45d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/hash.h +++ /dev/null @@ -1,37 +0,0 @@ -#ifndef SPX_HASH_H -#define SPX_HASH_H - -#include -#include - -#include "context.h" -#include "params.h" - -#define prf_addr SPX_NAMESPACE(prf_addr) -void prf_addr(unsigned char *out, const spx_ctx *ctx, - const uint32_t addr[8]); - -#define gen_message_random SPX_NAMESPACE(gen_message_random) -void gen_message_random(unsigned char *R, const unsigned char *sk_prf, - const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx); - -#define hash_message SPX_NAMESPACE(hash_message) -void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx); - - -# define SPX_SHA256_ADDR_BYTES 22 - -# define mgf1_256 SPX_NAMESPACE(mgf1_256) -void mgf1_256(unsigned char *out, unsigned long outlen, - const unsigned char *in, unsigned long inlen); - -# define mgf1_512 SPX_NAMESPACE(mgf1_512) -void mgf1_512(unsigned char *out, unsigned long outlen, - const unsigned char *in, unsigned long inlen); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/hash_sha2.c b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/hash_sha2.c deleted file mode 100644 index 3d0085c8c1..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/hash_sha2.c +++ /dev/null @@ -1,219 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "sha2.h" -#include "utils.h" - - - -#define SPX_SHAX_OUTPUT_BYTES SPX_SHA512_OUTPUT_BYTES -#define SPX_SHAX_BLOCK_BYTES SPX_SHA512_BLOCK_BYTES -#define shaX_inc_init sha512_inc_init -#define shaX_inc_blocks sha512_inc_blocks -#define shaX_inc_finalize sha512_inc_finalize -#define shaX sha512 -#define mgf1_X mgf1_512 -#define shaXstate sha512ctx - -/** - * mgf1 function based on the SHA-256 hash function - * Note that inlen should be sufficiently small that it still allows for - * an array to be allocated on the stack. Typically 'in' is merely a seed. - * Outputs outlen number of bytes - */ -void mgf1_256(unsigned char *out, unsigned long outlen, - const unsigned char *in, unsigned long inlen) { - PQCLEAN_VLA(uint8_t, inbuf, inlen + 4); - unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES]; - uint32_t i; - - memcpy(inbuf, in, inlen); - - /* While we can fit in at least another full block of SHA256 output.. */ - for (i = 0; (i + 1)*SPX_SHA256_OUTPUT_BYTES <= outlen; i++) { - u32_to_bytes(inbuf + inlen, i); - sha256(out, inbuf, inlen + 4); - out += SPX_SHA256_OUTPUT_BYTES; - } - /* Until we cannot anymore, and we fill the remainder. */ - if (outlen > i * SPX_SHA256_OUTPUT_BYTES) { - u32_to_bytes(inbuf + inlen, i); - sha256(outbuf, inbuf, inlen + 4); - memcpy(out, outbuf, outlen - i * SPX_SHA256_OUTPUT_BYTES); - } -} - -/* - * mgf1 function based on the SHA-512 hash function - */ -void mgf1_512(unsigned char *out, unsigned long outlen, - const unsigned char *in, unsigned long inlen) { - PQCLEAN_VLA(uint8_t, inbuf, inlen + 4); - unsigned char outbuf[SPX_SHA512_OUTPUT_BYTES]; - uint32_t i; - - memcpy(inbuf, in, inlen); - - /* While we can fit in at least another full block of SHA512 output.. */ - for (i = 0; (i + 1)*SPX_SHA512_OUTPUT_BYTES <= outlen; i++) { - u32_to_bytes(inbuf + inlen, i); - sha512(out, inbuf, inlen + 4); - out += SPX_SHA512_OUTPUT_BYTES; - } - /* Until we cannot anymore, and we fill the remainder. */ - if (outlen > i * SPX_SHA512_OUTPUT_BYTES) { - u32_to_bytes(inbuf + inlen, i); - sha512(outbuf, inbuf, inlen + 4); - memcpy(out, outbuf, outlen - i * SPX_SHA512_OUTPUT_BYTES); - } -} - -/* - * Computes PRF(pk_seed, sk_seed, addr). - */ -void prf_addr(unsigned char *out, const spx_ctx *ctx, - const uint32_t addr[8]) { - sha256ctx sha2_state; - unsigned char buf[SPX_SHA256_ADDR_BYTES + SPX_N]; - unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES]; - - /* Retrieve precomputed state containing pub_seed */ - sha256_inc_ctx_clone(&sha2_state, &ctx->state_seeded); - - /* Remainder: ADDR^c ‖ SK.seed */ - memcpy(buf, addr, SPX_SHA256_ADDR_BYTES); - memcpy(buf + SPX_SHA256_ADDR_BYTES, ctx->sk_seed, SPX_N); - - sha256_inc_finalize(outbuf, &sha2_state, buf, SPX_SHA256_ADDR_BYTES + SPX_N); - - memcpy(out, outbuf, SPX_N); -} - -/** - * Computes the message-dependent randomness R, using a secret seed as a key - * for HMAC, and an optional randomization value prefixed to the message. - * This requires m to have at least SPX_SHAX_BLOCK_BYTES + SPX_N space - * available in front of the pointer, i.e. before the message to use for the - * prefix. This is necessary to prevent having to move the message around (and - * allocate memory for it). - */ -void gen_message_random(unsigned char *R, const unsigned char *sk_prf, - const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx) { - (void)ctx; - - unsigned char buf[SPX_SHAX_BLOCK_BYTES + SPX_SHAX_OUTPUT_BYTES]; - shaXstate state; - int i; - - - /* This implements HMAC-SHA */ - for (i = 0; i < SPX_N; i++) { - buf[i] = 0x36 ^ sk_prf[i]; - } - memset(buf + SPX_N, 0x36, SPX_SHAX_BLOCK_BYTES - SPX_N); - - shaX_inc_init(&state); - shaX_inc_blocks(&state, buf, 1); - - memcpy(buf, optrand, SPX_N); - - /* If optrand + message cannot fill up an entire block */ - if (SPX_N + mlen < SPX_SHAX_BLOCK_BYTES) { - memcpy(buf + SPX_N, m, mlen); - shaX_inc_finalize(buf + SPX_SHAX_BLOCK_BYTES, &state, - buf, mlen + SPX_N); - } - /* Otherwise first fill a block, so that finalize only uses the message */ - else { - memcpy(buf + SPX_N, m, SPX_SHAX_BLOCK_BYTES - SPX_N); - shaX_inc_blocks(&state, buf, 1); - - m += SPX_SHAX_BLOCK_BYTES - SPX_N; - mlen -= SPX_SHAX_BLOCK_BYTES - SPX_N; - shaX_inc_finalize(buf + SPX_SHAX_BLOCK_BYTES, &state, m, mlen); - } - - for (i = 0; i < SPX_N; i++) { - buf[i] = 0x5c ^ sk_prf[i]; - } - memset(buf + SPX_N, 0x5c, SPX_SHAX_BLOCK_BYTES - SPX_N); - - shaX(buf, buf, SPX_SHAX_BLOCK_BYTES + SPX_SHAX_OUTPUT_BYTES); - memcpy(R, buf, SPX_N); -} - -/** - * Computes the message hash using R, the public key, and the message. - * Outputs the message digest and the index of the leaf. The index is split in - * the tree index and the leaf index, for convenient copying to an address. - */ -void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx) { - (void)ctx; -#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) -#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) -#define SPX_LEAF_BITS SPX_TREE_HEIGHT -#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) -#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) - - unsigned char seed[2 * SPX_N + SPX_SHAX_OUTPUT_BYTES]; - - /* Round to nearest multiple of SPX_SHAX_BLOCK_BYTES */ -#define SPX_INBLOCKS (((SPX_N + SPX_PK_BYTES + SPX_SHAX_BLOCK_BYTES - 1) & \ - -SPX_SHAX_BLOCK_BYTES) / SPX_SHAX_BLOCK_BYTES) - unsigned char inbuf[SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES]; - - unsigned char buf[SPX_DGST_BYTES]; - unsigned char *bufp = buf; - shaXstate state; - - shaX_inc_init(&state); - - // seed: SHA-X(R ‖ PK.seed ‖ PK.root ‖ M) - memcpy(inbuf, R, SPX_N); - memcpy(inbuf + SPX_N, pk, SPX_PK_BYTES); - - /* If R + pk + message cannot fill up an entire block */ - if (SPX_N + SPX_PK_BYTES + mlen < SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES) { - memcpy(inbuf + SPX_N + SPX_PK_BYTES, m, mlen); - shaX_inc_finalize(seed + 2 * SPX_N, &state, inbuf, SPX_N + SPX_PK_BYTES + mlen); - } - /* Otherwise first fill a block, so that finalize only uses the message */ - else { - memcpy(inbuf + SPX_N + SPX_PK_BYTES, m, - SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES - SPX_N - SPX_PK_BYTES); - shaX_inc_blocks(&state, inbuf, SPX_INBLOCKS); - - m += SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES - SPX_N - SPX_PK_BYTES; - mlen -= SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES - SPX_N - SPX_PK_BYTES; - shaX_inc_finalize(seed + 2 * SPX_N, &state, m, (size_t)mlen); - } - - // H_msg: MGF1-SHA-X(R ‖ PK.seed ‖ seed) - memcpy(seed, R, SPX_N); - memcpy(seed + SPX_N, pk, SPX_N); - - /* By doing this in two steps, we prevent hashing the message twice; - otherwise each iteration in MGF1 would hash the message again. */ - mgf1_X(bufp, SPX_DGST_BYTES, seed, 2 * SPX_N + SPX_SHAX_OUTPUT_BYTES); - - memcpy(digest, bufp, SPX_FORS_MSG_BYTES); - bufp += SPX_FORS_MSG_BYTES; - - - *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); - *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); - bufp += SPX_TREE_BYTES; - - *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); - *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); -} - - diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/hash_sha2x8.c b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/hash_sha2x8.c deleted file mode 100644 index e04af7a069..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/hash_sha2x8.c +++ /dev/null @@ -1,75 +0,0 @@ -#include -#include - -#include "hash.h" -#include "hashx8.h" - -#include "address.h" -#include "params.h" -#include "sha2.h" -#include "sha256avx.h" -#include "sha256x8.h" -#include "utils.h" - -/* - * 8-way parallel version of prf_addr; takes 8x as much input and output - */ -void prf_addrx8(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7, - const spx_ctx *ctx, - const uint32_t addrx8[8 * 8]) { - unsigned char bufx8[8 * (SPX_N + SPX_SHA256_ADDR_BYTES)]; - unsigned char outbufx8[8 * SPX_SHA256_OUTPUT_BYTES]; - unsigned int j; - - for (j = 0; j < 8; j++) { - memcpy(bufx8 + j * (SPX_N + SPX_SHA256_ADDR_BYTES), - addrx8 + j * 8, SPX_SHA256_ADDR_BYTES); - memcpy( - bufx8 + j * (SPX_N + SPX_SHA256_ADDR_BYTES) + SPX_SHA256_ADDR_BYTES, - ctx->sk_seed, - SPX_N - ); - } - - sha256x8_seeded( - /* out */ - outbufx8 + 0 * SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 1 * SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 2 * SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 3 * SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 4 * SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 5 * SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 6 * SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 7 * SPX_SHA256_OUTPUT_BYTES, - - /* seed */ - &ctx->statex8_seeded, - - /* in */ - bufx8 + 0 * (SPX_SHA256_ADDR_BYTES + SPX_N), - bufx8 + 1 * (SPX_SHA256_ADDR_BYTES + SPX_N), - bufx8 + 2 * (SPX_SHA256_ADDR_BYTES + SPX_N), - bufx8 + 3 * (SPX_SHA256_ADDR_BYTES + SPX_N), - bufx8 + 4 * (SPX_SHA256_ADDR_BYTES + SPX_N), - bufx8 + 5 * (SPX_SHA256_ADDR_BYTES + SPX_N), - bufx8 + 6 * (SPX_SHA256_ADDR_BYTES + SPX_N), - bufx8 + 7 * (SPX_SHA256_ADDR_BYTES + SPX_N), - SPX_SHA256_ADDR_BYTES + SPX_N /* len */ - ); - - memcpy(out0, outbufx8 + 0 * SPX_SHA256_OUTPUT_BYTES, SPX_N); - memcpy(out1, outbufx8 + 1 * SPX_SHA256_OUTPUT_BYTES, SPX_N); - memcpy(out2, outbufx8 + 2 * SPX_SHA256_OUTPUT_BYTES, SPX_N); - memcpy(out3, outbufx8 + 3 * SPX_SHA256_OUTPUT_BYTES, SPX_N); - memcpy(out4, outbufx8 + 4 * SPX_SHA256_OUTPUT_BYTES, SPX_N); - memcpy(out5, outbufx8 + 5 * SPX_SHA256_OUTPUT_BYTES, SPX_N); - memcpy(out6, outbufx8 + 6 * SPX_SHA256_OUTPUT_BYTES, SPX_N); - memcpy(out7, outbufx8 + 7 * SPX_SHA256_OUTPUT_BYTES, SPX_N); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/hashx8.h b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/hashx8.h deleted file mode 100644 index 46503f0a10..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/hashx8.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef SPX_HASHX8_H -#define SPX_HASHX8_H - -#include - -#include "params.h" - -#define prf_addrx8 SPX_NAMESPACE(prf_addrx8) -void prf_addrx8(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7, - const spx_ctx *ctx, - const uint32_t addrx8[8 * 8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/merkle.c b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/merkle.c deleted file mode 100644 index 1f353c8dd8..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/merkle.c +++ /dev/null @@ -1,65 +0,0 @@ -#include -#include - -#include "merkle.h" - -#include "address.h" -#include "params.h" -#include "utils.h" -#include "utilsx8.h" -#include "wots.h" -#include "wotsx8.h" - -/* - * This generates a Merkle signature (WOTS signature followed by the Merkle - * authentication path). - */ -void merkle_sign(uint8_t *sig, unsigned char *root, - const spx_ctx *ctx, - uint32_t wots_addr[8], uint32_t tree_addr[8], - uint32_t idx_leaf) { - unsigned char *auth_path = sig + SPX_WOTS_BYTES; - uint32_t tree_addrx8[8 * 8] = { 0 }; - int j; - struct leaf_info_x8 info = { 0 }; - unsigned steps[ SPX_WOTS_LEN ]; - - info.wots_sig = sig; - chain_lengths(steps, root); - info.wots_steps = steps; - - for (j = 0; j < 8; j++) { - set_type(&tree_addrx8[8 * j], SPX_ADDR_TYPE_HASHTREE); - set_type(&info.leaf_addr[8 * j], SPX_ADDR_TYPE_WOTS); - set_type(&info.pk_addr[8 * j], SPX_ADDR_TYPE_WOTSPK); - copy_subtree_addr(&tree_addrx8[8 * j], tree_addr); - copy_subtree_addr(&info.leaf_addr[8 * j], wots_addr); - copy_subtree_addr(&info.pk_addr[8 * j], wots_addr); - } - - info.wots_sign_leaf = idx_leaf; - - treehashx8(root, auth_path, ctx, - idx_leaf, 0, - SPX_TREE_HEIGHT, - wots_gen_leafx8, - tree_addrx8, &info); -} - -/* Compute root node of the top-most subtree. */ -/* Again, in this file because wots_gen_leaf is most of the work */ -void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { - /* We do not need the auth path in key generation, but it simplifies the - code to have just one treehash routine that computes both root and path - in one function. */ - unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; - uint32_t top_tree_addr[8] = {0}; - uint32_t wots_addr[8] = {0}; - - set_layer_addr(top_tree_addr, SPX_D - 1); - set_layer_addr(wots_addr, SPX_D - 1); - - merkle_sign(auth_path, root, ctx, - wots_addr, top_tree_addr, - ~0U /* ~0 means "don't bother generating an auth path */ ); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/merkle.h b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/merkle.h deleted file mode 100644 index 769cf2e970..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/merkle.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef MERKLE_H_ -#define MERKLE_H_ - -#include - -#include "context.h" -#include "params.h" - -/* Generate a Merkle signature (WOTS signature followed by the Merkle */ -/* authentication path) */ -#define merkle_sign SPX_NAMESPACE(merkle_sign) -void merkle_sign(uint8_t *sig, unsigned char *root, - const spx_ctx *ctx, - uint32_t wots_addr[8], uint32_t tree_addr[8], - uint32_t idx_leaf); - -/* Compute the root node of the top-most subtree. */ -#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) -void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); - -#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/nistapi.h b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/nistapi.h deleted file mode 100644 index 3cb71afad4..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/nistapi.h +++ /dev/null @@ -1,87 +0,0 @@ -#ifndef SPX_API_H -#define SPX_API_H - -#include -#include - -#include "params.h" - -#define CRYPTO_ALGNAME "SPHINCS+" - -#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES -#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES -#define CRYPTO_BYTES SPX_BYTES -#define CRYPTO_SEEDBYTES (3*SPX_N) - -/* - * Returns the length of a secret key, in bytes - */ -#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) -size_t crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) -size_t crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) -size_t crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) -size_t crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) -int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) -int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) -int crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) -int crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -#define crypto_sign SPX_NAMESPACE(crypto_sign) -int crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) -int crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/params.h b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/params.h deleted file mode 100644 index a81d22b014..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/params.h +++ /dev/null @@ -1,61 +0,0 @@ -#ifndef SPX_PARAMS_H -#define SPX_PARAMS_H - -#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSSHA2256SROBUST_AVX2_##s - -/* Hash output length in bytes. */ -#define SPX_N 32 -/* Height of the hypertree. */ -#define SPX_FULL_HEIGHT 64 -/* Number of subtree layer. */ -#define SPX_D 8 -/* FORS tree dimensions. */ -#define SPX_FORS_HEIGHT 14 -#define SPX_FORS_TREES 22 -/* Winternitz parameter, */ -#define SPX_WOTS_W 16 - -/* The hash function is defined by linking a different hash.c file, as opposed - to setting a #define constant. */ - -/* This is a SHA2-based parameter set, hence whether we use SHA-256 - * exclusively or we use both SHA-256 and SHA-512 is controlled by - * the following #define */ -#define SPX_SHA512 1 /* Use SHA-512 for H and T_l, l >= 2 */ - -/* For clarity */ -#define SPX_ADDR_BYTES 32 - -/* WOTS parameters. */ -#define SPX_WOTS_LOGW 4 - -#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) - -/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#define SPX_WOTS_LEN2 3 - -#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) -#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) -#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES - -/* Subtree size. */ -#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) - -//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT -// #error SPX_D should always divide SPX_FULL_HEIGHT -//#endif - -/* FORS parameters. */ -#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) -#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) -#define SPX_FORS_PK_BYTES SPX_N - -/* Resulting SPX sizes. */ -#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ - SPX_FULL_HEIGHT * SPX_N) -#define SPX_PK_BYTES (2 * SPX_N) -#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) - -#include "sha2_offsets.h" - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/sha256avx.c b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/sha256avx.c deleted file mode 100644 index 6bbe6ecc24..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/sha256avx.c +++ /dev/null @@ -1,357 +0,0 @@ -#include -#include -#include - -#include "sha256avx.h" - -static const unsigned int RC[] = { - 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, - 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, - 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, - 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, - 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, - 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, - 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, - 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, - 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, - 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, - 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, - 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, - 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, - 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, - 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, - 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 -}; - -#define u32 uint32_t -#define u256 __m256i - -#define XOR _mm256_xor_si256 -#define OR _mm256_or_si256 -#define AND _mm256_and_si256 -#define ADD32 _mm256_add_epi32 -#define NOT(x) _mm256_xor_si256(x, _mm256_set_epi32(-1, -1, -1, -1, -1, -1, -1, -1)) - -#define LOAD(src) _mm256_loadu_si256((__m256i *)(src)) -#define STORE(dest,src) _mm256_storeu_si256((__m256i *)(dest),src) - -#define BYTESWAP(x) _mm256_shuffle_epi8(x, _mm256_set_epi8(0xc,0xd,0xe,0xf,0x8,0x9,0xa,0xb,0x4,0x5,0x6,0x7,0x0,0x1,0x2,0x3,0xc,0xd,0xe,0xf,0x8,0x9,0xa,0xb,0x4,0x5,0x6,0x7,0x0,0x1,0x2,0x3)) - -#define SHIFTR32(x, y) _mm256_srli_epi32(x, y) -#define SHIFTL32(x, y) _mm256_slli_epi32(x, y) - -#define ROTR32(x, y) OR(SHIFTR32(x, y), SHIFTL32(x, 32 - (y))) -#define ROTL32(x, y) OR(SHIFTL32(x, y), SHIFTR32(x, 32 - (y))) - -#define XOR3(a, b, c) XOR(XOR(a, b), c) - -#define ADD3_32(a, b, c) ADD32(ADD32(a, b), c) -#define ADD4_32(a, b, c, d) ADD32(ADD32(ADD32(a, b), c), d) -#define ADD5_32(a, b, c, d, e) ADD32(ADD32(ADD32(ADD32(a, b), c), d), e) - -#define MAJ_AVX(a, b, c) XOR3(AND(a, b), AND(a, c), AND(b, c)) -#define CH_AVX(a, b, c) XOR(AND(a, b), AND(NOT(a), c)) - -#define SIGMA1_AVX(x) XOR3(ROTR32(x, 6), ROTR32(x, 11), ROTR32(x, 25)) -#define SIGMA0_AVX(x) XOR3(ROTR32(x, 2), ROTR32(x, 13), ROTR32(x, 22)) - -#define WSIGMA1_AVX(x) XOR3(ROTR32(x, 17), ROTR32(x, 19), SHIFTR32(x, 10)) -#define WSIGMA0_AVX(x) XOR3(ROTR32(x, 7), ROTR32(x, 18), SHIFTR32(x, 3)) - -#define SHA256ROUND_AVX(a, b, c, d, e, f, g, h, rc, w) \ - T0 = ADD5_32(h, SIGMA1_AVX(e), CH_AVX(e, f, g), _mm256_set1_epi32((int)RC[rc]), w); \ - (d) = ADD32(d, T0); \ - T1 = ADD32(SIGMA0_AVX(a), MAJ_AVX(a, b, c)); \ - (h) = ADD32(T0, T1); - -// Transpose 8 vectors containing 32-bit values -static void transpose(u256 s[8]) { - u256 tmp0[8]; - u256 tmp1[8]; - tmp0[0] = _mm256_unpacklo_epi32(s[0], s[1]); - tmp0[1] = _mm256_unpackhi_epi32(s[0], s[1]); - tmp0[2] = _mm256_unpacklo_epi32(s[2], s[3]); - tmp0[3] = _mm256_unpackhi_epi32(s[2], s[3]); - tmp0[4] = _mm256_unpacklo_epi32(s[4], s[5]); - tmp0[5] = _mm256_unpackhi_epi32(s[4], s[5]); - tmp0[6] = _mm256_unpacklo_epi32(s[6], s[7]); - tmp0[7] = _mm256_unpackhi_epi32(s[6], s[7]); - tmp1[0] = _mm256_unpacklo_epi64(tmp0[0], tmp0[2]); - tmp1[1] = _mm256_unpackhi_epi64(tmp0[0], tmp0[2]); - tmp1[2] = _mm256_unpacklo_epi64(tmp0[1], tmp0[3]); - tmp1[3] = _mm256_unpackhi_epi64(tmp0[1], tmp0[3]); - tmp1[4] = _mm256_unpacklo_epi64(tmp0[4], tmp0[6]); - tmp1[5] = _mm256_unpackhi_epi64(tmp0[4], tmp0[6]); - tmp1[6] = _mm256_unpacklo_epi64(tmp0[5], tmp0[7]); - tmp1[7] = _mm256_unpackhi_epi64(tmp0[5], tmp0[7]); - s[0] = _mm256_permute2x128_si256(tmp1[0], tmp1[4], 0x20); - s[1] = _mm256_permute2x128_si256(tmp1[1], tmp1[5], 0x20); - s[2] = _mm256_permute2x128_si256(tmp1[2], tmp1[6], 0x20); - s[3] = _mm256_permute2x128_si256(tmp1[3], tmp1[7], 0x20); - s[4] = _mm256_permute2x128_si256(tmp1[0], tmp1[4], 0x31); - s[5] = _mm256_permute2x128_si256(tmp1[1], tmp1[5], 0x31); - s[6] = _mm256_permute2x128_si256(tmp1[2], tmp1[6], 0x31); - s[7] = _mm256_permute2x128_si256(tmp1[3], tmp1[7], 0x31); -} - -void sha256_ctx_clone8x(sha256x8ctx *out, const sha256x8ctx *in) { - memcpy(out, in, sizeof(sha256x8ctx)); -} - -void sha256_init8x(sha256x8ctx *ctx) { - ctx->s[0] = _mm256_set_epi32((int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667); - ctx->s[1] = _mm256_set_epi32((int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85); - ctx->s[2] = _mm256_set_epi32((int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372); - ctx->s[3] = _mm256_set_epi32((int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a); - ctx->s[4] = _mm256_set_epi32((int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f); - ctx->s[5] = _mm256_set_epi32((int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c); - ctx->s[6] = _mm256_set_epi32((int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab); - ctx->s[7] = _mm256_set_epi32((int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19); - - ctx->datalen = 0; - ctx->msglen = 0; -} - -void sha256_final8x(sha256x8ctx *ctx, - unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7) { - unsigned int i, curlen; - - // Padding - if (ctx->datalen < 56) { - for (i = 0; i < 8; ++i) { - curlen = ctx->datalen; - ctx->msgblocks[64 * i + curlen++] = 0x80; - while (curlen < 64) { - ctx->msgblocks[64 * i + curlen++] = 0x00; - } - } - } else { - for (i = 0; i < 8; ++i) { - curlen = ctx->datalen; - ctx->msgblocks[64 * i + curlen++] = 0x80; - while (curlen < 64) { - ctx->msgblocks[64 * i + curlen++] = 0x00; - } - } - sha256_transform8x(ctx, - &ctx->msgblocks[64 * 0], - &ctx->msgblocks[64 * 1], - &ctx->msgblocks[64 * 2], - &ctx->msgblocks[64 * 3], - &ctx->msgblocks[64 * 4], - &ctx->msgblocks[64 * 5], - &ctx->msgblocks[64 * 6], - &ctx->msgblocks[64 * 7] - ); - memset(ctx->msgblocks, 0, 8 * 64); - } - - // Add length of the message to each block - ctx->msglen += ctx->datalen * 8; - for (i = 0; i < 8; i++) { - ctx->msgblocks[64 * i + 63] = (unsigned char)(ctx->msglen); - ctx->msgblocks[64 * i + 62] = (unsigned char)(ctx->msglen >> 8); - ctx->msgblocks[64 * i + 61] = (unsigned char)(ctx->msglen >> 16); - ctx->msgblocks[64 * i + 60] = (unsigned char)(ctx->msglen >> 24); - ctx->msgblocks[64 * i + 59] = (unsigned char)(ctx->msglen >> 32); - ctx->msgblocks[64 * i + 58] = (unsigned char)(ctx->msglen >> 40); - ctx->msgblocks[64 * i + 57] = (unsigned char)(ctx->msglen >> 48); - ctx->msgblocks[64 * i + 56] = (unsigned char)(ctx->msglen >> 56); - } - sha256_transform8x(ctx, - &ctx->msgblocks[64 * 0], - &ctx->msgblocks[64 * 1], - &ctx->msgblocks[64 * 2], - &ctx->msgblocks[64 * 3], - &ctx->msgblocks[64 * 4], - &ctx->msgblocks[64 * 5], - &ctx->msgblocks[64 * 6], - &ctx->msgblocks[64 * 7] - ); - - // Compute final hash output - transpose(ctx->s); - - // Store Hash value - STORE(out0, BYTESWAP(ctx->s[0])); - STORE(out1, BYTESWAP(ctx->s[1])); - STORE(out2, BYTESWAP(ctx->s[2])); - STORE(out3, BYTESWAP(ctx->s[3])); - STORE(out4, BYTESWAP(ctx->s[4])); - STORE(out5, BYTESWAP(ctx->s[5])); - STORE(out6, BYTESWAP(ctx->s[6])); - STORE(out7, BYTESWAP(ctx->s[7])); -} - -void sha256_transform8x(sha256x8ctx *ctx, - const unsigned char *data0, - const unsigned char *data1, - const unsigned char *data2, - const unsigned char *data3, - const unsigned char *data4, - const unsigned char *data5, - const unsigned char *data6, - const unsigned char *data7) { - u256 s[8], w[64], T0, T1; - - // Load words and transform data correctly - w[0] = BYTESWAP(LOAD(data0)); - w[0 + 8] = BYTESWAP(LOAD(data0 + 32)); - w[1] = BYTESWAP(LOAD(data1)); - w[1 + 8] = BYTESWAP(LOAD(data1 + 32)); - w[2] = BYTESWAP(LOAD(data2)); - w[2 + 8] = BYTESWAP(LOAD(data2 + 32)); - w[3] = BYTESWAP(LOAD(data3)); - w[3 + 8] = BYTESWAP(LOAD(data3 + 32)); - w[4] = BYTESWAP(LOAD(data4)); - w[4 + 8] = BYTESWAP(LOAD(data4 + 32)); - w[5] = BYTESWAP(LOAD(data5)); - w[5 + 8] = BYTESWAP(LOAD(data5 + 32)); - w[6] = BYTESWAP(LOAD(data6)); - w[6 + 8] = BYTESWAP(LOAD(data6 + 32)); - w[7] = BYTESWAP(LOAD(data7)); - w[7 + 8] = BYTESWAP(LOAD(data7 + 32)); - - transpose(w); - transpose(w + 8); - - // Initial State - s[0] = ctx->s[0]; - s[1] = ctx->s[1]; - s[2] = ctx->s[2]; - s[3] = ctx->s[3]; - s[4] = ctx->s[4]; - s[5] = ctx->s[5]; - s[6] = ctx->s[6]; - s[7] = ctx->s[7]; - - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 0, w[0]); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 1, w[1]); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 2, w[2]); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 3, w[3]); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 4, w[4]); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 5, w[5]); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 6, w[6]); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 7, w[7]); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 8, w[8]); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 9, w[9]); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 10, w[10]); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 11, w[11]); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 12, w[12]); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 13, w[13]); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 14, w[14]); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 15, w[15]); - w[16] = ADD4_32(WSIGMA1_AVX(w[14]), w[0], w[9], WSIGMA0_AVX(w[1])); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 16, w[16]); - w[17] = ADD4_32(WSIGMA1_AVX(w[15]), w[1], w[10], WSIGMA0_AVX(w[2])); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 17, w[17]); - w[18] = ADD4_32(WSIGMA1_AVX(w[16]), w[2], w[11], WSIGMA0_AVX(w[3])); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 18, w[18]); - w[19] = ADD4_32(WSIGMA1_AVX(w[17]), w[3], w[12], WSIGMA0_AVX(w[4])); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 19, w[19]); - w[20] = ADD4_32(WSIGMA1_AVX(w[18]), w[4], w[13], WSIGMA0_AVX(w[5])); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 20, w[20]); - w[21] = ADD4_32(WSIGMA1_AVX(w[19]), w[5], w[14], WSIGMA0_AVX(w[6])); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 21, w[21]); - w[22] = ADD4_32(WSIGMA1_AVX(w[20]), w[6], w[15], WSIGMA0_AVX(w[7])); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 22, w[22]); - w[23] = ADD4_32(WSIGMA1_AVX(w[21]), w[7], w[16], WSIGMA0_AVX(w[8])); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 23, w[23]); - w[24] = ADD4_32(WSIGMA1_AVX(w[22]), w[8], w[17], WSIGMA0_AVX(w[9])); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 24, w[24]); - w[25] = ADD4_32(WSIGMA1_AVX(w[23]), w[9], w[18], WSIGMA0_AVX(w[10])); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 25, w[25]); - w[26] = ADD4_32(WSIGMA1_AVX(w[24]), w[10], w[19], WSIGMA0_AVX(w[11])); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 26, w[26]); - w[27] = ADD4_32(WSIGMA1_AVX(w[25]), w[11], w[20], WSIGMA0_AVX(w[12])); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 27, w[27]); - w[28] = ADD4_32(WSIGMA1_AVX(w[26]), w[12], w[21], WSIGMA0_AVX(w[13])); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 28, w[28]); - w[29] = ADD4_32(WSIGMA1_AVX(w[27]), w[13], w[22], WSIGMA0_AVX(w[14])); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 29, w[29]); - w[30] = ADD4_32(WSIGMA1_AVX(w[28]), w[14], w[23], WSIGMA0_AVX(w[15])); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 30, w[30]); - w[31] = ADD4_32(WSIGMA1_AVX(w[29]), w[15], w[24], WSIGMA0_AVX(w[16])); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 31, w[31]); - w[32] = ADD4_32(WSIGMA1_AVX(w[30]), w[16], w[25], WSIGMA0_AVX(w[17])); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 32, w[32]); - w[33] = ADD4_32(WSIGMA1_AVX(w[31]), w[17], w[26], WSIGMA0_AVX(w[18])); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 33, w[33]); - w[34] = ADD4_32(WSIGMA1_AVX(w[32]), w[18], w[27], WSIGMA0_AVX(w[19])); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 34, w[34]); - w[35] = ADD4_32(WSIGMA1_AVX(w[33]), w[19], w[28], WSIGMA0_AVX(w[20])); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 35, w[35]); - w[36] = ADD4_32(WSIGMA1_AVX(w[34]), w[20], w[29], WSIGMA0_AVX(w[21])); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 36, w[36]); - w[37] = ADD4_32(WSIGMA1_AVX(w[35]), w[21], w[30], WSIGMA0_AVX(w[22])); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 37, w[37]); - w[38] = ADD4_32(WSIGMA1_AVX(w[36]), w[22], w[31], WSIGMA0_AVX(w[23])); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 38, w[38]); - w[39] = ADD4_32(WSIGMA1_AVX(w[37]), w[23], w[32], WSIGMA0_AVX(w[24])); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 39, w[39]); - w[40] = ADD4_32(WSIGMA1_AVX(w[38]), w[24], w[33], WSIGMA0_AVX(w[25])); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 40, w[40]); - w[41] = ADD4_32(WSIGMA1_AVX(w[39]), w[25], w[34], WSIGMA0_AVX(w[26])); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 41, w[41]); - w[42] = ADD4_32(WSIGMA1_AVX(w[40]), w[26], w[35], WSIGMA0_AVX(w[27])); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 42, w[42]); - w[43] = ADD4_32(WSIGMA1_AVX(w[41]), w[27], w[36], WSIGMA0_AVX(w[28])); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 43, w[43]); - w[44] = ADD4_32(WSIGMA1_AVX(w[42]), w[28], w[37], WSIGMA0_AVX(w[29])); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 44, w[44]); - w[45] = ADD4_32(WSIGMA1_AVX(w[43]), w[29], w[38], WSIGMA0_AVX(w[30])); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 45, w[45]); - w[46] = ADD4_32(WSIGMA1_AVX(w[44]), w[30], w[39], WSIGMA0_AVX(w[31])); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 46, w[46]); - w[47] = ADD4_32(WSIGMA1_AVX(w[45]), w[31], w[40], WSIGMA0_AVX(w[32])); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 47, w[47]); - w[48] = ADD4_32(WSIGMA1_AVX(w[46]), w[32], w[41], WSIGMA0_AVX(w[33])); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 48, w[48]); - w[49] = ADD4_32(WSIGMA1_AVX(w[47]), w[33], w[42], WSIGMA0_AVX(w[34])); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 49, w[49]); - w[50] = ADD4_32(WSIGMA1_AVX(w[48]), w[34], w[43], WSIGMA0_AVX(w[35])); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 50, w[50]); - w[51] = ADD4_32(WSIGMA1_AVX(w[49]), w[35], w[44], WSIGMA0_AVX(w[36])); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 51, w[51]); - w[52] = ADD4_32(WSIGMA1_AVX(w[50]), w[36], w[45], WSIGMA0_AVX(w[37])); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 52, w[52]); - w[53] = ADD4_32(WSIGMA1_AVX(w[51]), w[37], w[46], WSIGMA0_AVX(w[38])); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 53, w[53]); - w[54] = ADD4_32(WSIGMA1_AVX(w[52]), w[38], w[47], WSIGMA0_AVX(w[39])); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 54, w[54]); - w[55] = ADD4_32(WSIGMA1_AVX(w[53]), w[39], w[48], WSIGMA0_AVX(w[40])); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 55, w[55]); - w[56] = ADD4_32(WSIGMA1_AVX(w[54]), w[40], w[49], WSIGMA0_AVX(w[41])); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 56, w[56]); - w[57] = ADD4_32(WSIGMA1_AVX(w[55]), w[41], w[50], WSIGMA0_AVX(w[42])); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 57, w[57]); - w[58] = ADD4_32(WSIGMA1_AVX(w[56]), w[42], w[51], WSIGMA0_AVX(w[43])); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 58, w[58]); - w[59] = ADD4_32(WSIGMA1_AVX(w[57]), w[43], w[52], WSIGMA0_AVX(w[44])); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 59, w[59]); - w[60] = ADD4_32(WSIGMA1_AVX(w[58]), w[44], w[53], WSIGMA0_AVX(w[45])); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 60, w[60]); - w[61] = ADD4_32(WSIGMA1_AVX(w[59]), w[45], w[54], WSIGMA0_AVX(w[46])); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 61, w[61]); - w[62] = ADD4_32(WSIGMA1_AVX(w[60]), w[46], w[55], WSIGMA0_AVX(w[47])); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 62, w[62]); - w[63] = ADD4_32(WSIGMA1_AVX(w[61]), w[47], w[56], WSIGMA0_AVX(w[48])); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 63, w[63]); - - // Feed Forward - ctx->s[0] = ADD32(s[0], ctx->s[0]); - ctx->s[1] = ADD32(s[1], ctx->s[1]); - ctx->s[2] = ADD32(s[2], ctx->s[2]); - ctx->s[3] = ADD32(s[3], ctx->s[3]); - ctx->s[4] = ADD32(s[4], ctx->s[4]); - ctx->s[5] = ADD32(s[5], ctx->s[5]); - ctx->s[6] = ADD32(s[6], ctx->s[6]); - ctx->s[7] = ADD32(s[7], ctx->s[7]); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/sha256avx.h b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/sha256avx.h deleted file mode 100644 index 1e3bcf889b..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/sha256avx.h +++ /dev/null @@ -1,44 +0,0 @@ -#ifndef SHA256AVX_H -#define SHA256AVX_H - -#include -#include - -#include "params.h" - -typedef struct SHA256state { - __m256i s[8]; - unsigned char msgblocks[8 * 64]; - unsigned int datalen; - unsigned long long msglen; -} sha256x8ctx; - -#define sha256_ctx_clone8x SPX_NAMESPACE(sha256_ctx_clone8x) -void sha256_ctx_clone8x(sha256x8ctx *out, const sha256x8ctx *in); - -#define sha256_init8x SPX_NAMESPACE(sha256_init8x) -void sha256_init8x(sha256x8ctx *ctx); - -#define sha256_final8x SPX_NAMESPACE(sha256_final8x) -void sha256_final8x(sha256x8ctx *ctx, - unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7); - -#define sha256_transform8x SPX_NAMESPACE(sha256_transform8x) -void sha256_transform8x(sha256x8ctx *ctx, - const unsigned char *data0, - const unsigned char *data1, - const unsigned char *data2, - const unsigned char *data3, - const unsigned char *data4, - const unsigned char *data5, - const unsigned char *data6, - const unsigned char *data7); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/sha256x8.c b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/sha256x8.c deleted file mode 100644 index d97750c09b..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/sha256x8.c +++ /dev/null @@ -1,185 +0,0 @@ -#include - -#include "sha256avx.h" -#include "sha256x8.h" -#include "utils.h" - -// Performs sha256x8 on an initialized (and perhaps seeded) state. -static void _sha256x8( - sha256x8ctx *ctx, - unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - const unsigned char *in4, - const unsigned char *in5, - const unsigned char *in6, - const unsigned char *in7, unsigned long long inlen) { - unsigned long long i = 0; - while (inlen - i >= 64) { - sha256_transform8x(ctx, - in0 + i, - in1 + i, - in2 + i, - in3 + i, - in4 + i, - in5 + i, - in6 + i, - in7 + i - ); - i += 64; - ctx->msglen += 512; - } - - size_t bytes_to_copy = (size_t)(inlen - i); - memcpy(&ctx->msgblocks[64 * 0], in0 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64 * 1], in1 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64 * 2], in2 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64 * 3], in3 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64 * 4], in4 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64 * 5], in5 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64 * 6], in6 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64 * 7], in7 + i, bytes_to_copy); - ctx->datalen = (unsigned int)bytes_to_copy; - - sha256_final8x(ctx, out0, out1, out2, out3, out4, out5, out6, out7); -} - -void sha256x8_seeded( - unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7, - const sha256x8ctx *seed, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - const unsigned char *in4, - const unsigned char *in5, - const unsigned char *in6, - const unsigned char *in7, unsigned long long inlen) { - - sha256x8ctx ctx; - sha256_ctx_clone8x(&ctx, seed); - - _sha256x8(&ctx, out0, out1, out2, out3, out4, out5, out6, out7, - in0, in1, in2, in3, in4, in5, in6, in7, inlen); -} - -/* This provides a wrapper around the internals of 8x parallel SHA256 */ -void sha256x8(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - const unsigned char *in4, - const unsigned char *in5, - const unsigned char *in6, - const unsigned char *in7, unsigned long long inlen) { - sha256x8ctx ctx; - sha256_init8x(&ctx); - - _sha256x8(&ctx, out0, out1, out2, out3, out4, out5, out6, out7, - in0, in1, in2, in3, in4, in5, in6, in7, inlen); -} - -/** - * Note that inlen should be sufficiently small that it still allows for - * an array to be allocated on the stack. Typically 'in' is merely a seed. - * Outputs outlen number of bytes - */ -void mgf1x8(unsigned char *outx8, unsigned long outlen, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - const unsigned char *in4, - const unsigned char *in5, - const unsigned char *in6, - const unsigned char *in7, - unsigned long inlen) { - PQCLEAN_VLA(unsigned char, inbufx8, 8 * (inlen + 4)); - unsigned char outbufx8[8 * SPX_SHA256_OUTPUT_BYTES]; - uint32_t i; - unsigned int j; - - memcpy(inbufx8 + 0 * (inlen + 4), in0, inlen); - memcpy(inbufx8 + 1 * (inlen + 4), in1, inlen); - memcpy(inbufx8 + 2 * (inlen + 4), in2, inlen); - memcpy(inbufx8 + 3 * (inlen + 4), in3, inlen); - memcpy(inbufx8 + 4 * (inlen + 4), in4, inlen); - memcpy(inbufx8 + 5 * (inlen + 4), in5, inlen); - memcpy(inbufx8 + 6 * (inlen + 4), in6, inlen); - memcpy(inbufx8 + 7 * (inlen + 4), in7, inlen); - - /* While we can fit in at least another full block of SHA256 output.. */ - for (i = 0; (i + 1)*SPX_SHA256_OUTPUT_BYTES <= outlen; i++) { - for (j = 0; j < 8; j++) { - u32_to_bytes(inbufx8 + inlen + j * (inlen + 4), i); - } - - sha256x8(outx8 + 0 * outlen, - outx8 + 1 * outlen, - outx8 + 2 * outlen, - outx8 + 3 * outlen, - outx8 + 4 * outlen, - outx8 + 5 * outlen, - outx8 + 6 * outlen, - outx8 + 7 * outlen, - inbufx8 + 0 * (inlen + 4), - inbufx8 + 1 * (inlen + 4), - inbufx8 + 2 * (inlen + 4), - inbufx8 + 3 * (inlen + 4), - inbufx8 + 4 * (inlen + 4), - inbufx8 + 5 * (inlen + 4), - inbufx8 + 6 * (inlen + 4), - inbufx8 + 7 * (inlen + 4), inlen + 4); - outx8 += SPX_SHA256_OUTPUT_BYTES; - } - /* Until we cannot anymore, and we fill the remainder. */ - for (j = 0; j < 8; j++) { - u32_to_bytes(inbufx8 + inlen + j * (inlen + 4), i); - } - sha256x8(outbufx8 + 0 * SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 1 * SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 2 * SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 3 * SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 4 * SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 5 * SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 6 * SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 7 * SPX_SHA256_OUTPUT_BYTES, - inbufx8 + 0 * (inlen + 4), - inbufx8 + 1 * (inlen + 4), - inbufx8 + 2 * (inlen + 4), - inbufx8 + 3 * (inlen + 4), - inbufx8 + 4 * (inlen + 4), - inbufx8 + 5 * (inlen + 4), - inbufx8 + 6 * (inlen + 4), - inbufx8 + 7 * (inlen + 4), inlen + 4); - - for (j = 0; j < 8; j++) { - memcpy(outx8 + j * outlen, - outbufx8 + j * SPX_SHA256_OUTPUT_BYTES, - outlen - i * SPX_SHA256_OUTPUT_BYTES); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/sha256x8.h b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/sha256x8.h deleted file mode 100644 index 4f7330a6c1..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/sha256x8.h +++ /dev/null @@ -1,64 +0,0 @@ -#ifndef SPX_SHA256X8_H -#define SPX_SHA256X8_H - -#include "params.h" -#include "sha256avx.h" - - - -#define sha256x8_seeded SPX_NAMESPACE(sha256x8_seeded) -void sha256x8_seeded( - unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7, - const sha256x8ctx *seed, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - const unsigned char *in4, - const unsigned char *in5, - const unsigned char *in6, - const unsigned char *in7, unsigned long long inlen); - -/* This provides a wrapper around the internals of 8x parallel SHA256 */ -#define sha256x8 SPX_NAMESPACE(sha256x8) -void sha256x8(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - const unsigned char *in4, - const unsigned char *in5, - const unsigned char *in6, - const unsigned char *in7, unsigned long long inlen); - -/** - * Note that inlen should be sufficiently small that it still allows for - * an array to be allocated on the stack. Typically 'in' is merely a seed. - * Outputs outlen number of bytes - */ -#define mgf1x8 SPX_NAMESPACE(mgf1x8) -void mgf1x8(unsigned char *outx8, unsigned long outlen, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - const unsigned char *in4, - const unsigned char *in5, - const unsigned char *in6, - const unsigned char *in7, - unsigned long inlen); -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/sha2_offsets.h b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/sha2_offsets.h deleted file mode 100644 index 6e3584f7a4..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/sha2_offsets.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef SHA2_OFFSETS_H_ -#define SHA2_OFFSETS_H_ - -#define SPX_SHA256_BLOCK_BYTES 64 -#define SPX_SHA256_OUTPUT_BYTES 32 - -#define SPX_SHA512_BLOCK_BYTES 128 -#define SPX_SHA512_OUTPUT_BYTES 64 - -/* - * Offsets of various fields in the address structure when we use SHA2 as - * the Sphincs+ hash function - */ - -#define SPX_OFFSET_LAYER 0 /* The byte used to specify the Merkle tree layer */ -#define SPX_OFFSET_TREE 1 /* The start of the 8 byte field used to specify the tree */ -#define SPX_OFFSET_TYPE 9 /* The byte used to specify the hash type (reason) */ -#define SPX_OFFSET_KP_ADDR2 12 /* The high byte used to specify the key pair (which one-time signature) */ -#define SPX_OFFSET_KP_ADDR1 13 /* The low byte used to specify the key pair */ -#define SPX_OFFSET_CHAIN_ADDR 17 /* The byte used to specify the chain address (which Winternitz chain) */ -#define SPX_OFFSET_HASH_ADDR 21 /* The byte used to specify the hash address (where in the Winternitz chain) */ -#define SPX_OFFSET_TREE_HGT 17 /* The byte used to specify the height of this node in the FORS or Merkle tree */ -#define SPX_OFFSET_TREE_INDEX 18 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ - -#define SPX_SHA2 1 - -#endif /* SHA2_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/sha512x4.c b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/sha512x4.c deleted file mode 100644 index 8d33deffdd..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/sha512x4.c +++ /dev/null @@ -1,446 +0,0 @@ -#include -#include -#include - -/* pull in the entire thing */ -#include "sha512x4.h" -#include "utils.h" - -typedef uint64_t u64; -typedef __m256i u256; - -#define BYTESWAP(x) _mm256_shuffle_epi8(x, _mm256_set_epi8(0x8,0x9,0xa,0xb,0xc,0xd,0xe,0xf,0x0,0x1,0x2,0x3,0x4,0x5,0x6,0x7,0x8,0x9,0xa,0xb,0xc,0xd,0xe,0xf,0x0,0x1,0x2,0x3,0x4,0x5,0x6,0x7)) -#define STORE(dest,src) _mm256_storeu_si256((__m256i *)(dest),src) - -// Transpose 4 vectors containing 64-bit values -// That is, it rearranges the array: -// A B C D -// E F G H -// I J K L -// M N O P -// into -// A E I M -// B F J N -// C G K O -// D H L P -// where each letter stands for 64 bits (and lsbits on the left) -static void transpose(u256 s[4]) { - u256 tmp[4]; - tmp[0] = _mm256_unpacklo_epi64(s[0], s[1]); - tmp[1] = _mm256_unpackhi_epi64(s[0], s[1]); - tmp[2] = _mm256_unpacklo_epi64(s[2], s[3]); - tmp[3] = _mm256_unpackhi_epi64(s[2], s[3]); - // tmp is in the order of - // A E C G - // B F D H - // I M K O - // J N L P - s[0] = _mm256_permute2x128_si256(tmp[0], tmp[2], 0x20); - s[1] = _mm256_permute2x128_si256(tmp[1], tmp[3], 0x20); - s[2] = _mm256_permute2x128_si256(tmp[0], tmp[2], 0x31); - s[3] = _mm256_permute2x128_si256(tmp[1], tmp[3], 0x31); -} - - -void sha512_init4x(sha512x4ctx *ctx) { -#define SET4(x) _mm256_set_epi64x((long long)(x), (long long)(x), (long long)(x), (long long)(x)) - ctx->s[0] = SET4(0x6a09e667f3bcc908ULL); - ctx->s[1] = SET4(0xbb67ae8584caa73bULL); - ctx->s[2] = SET4(0x3c6ef372fe94f82bULL); - ctx->s[3] = SET4(0xa54ff53a5f1d36f1ULL); - ctx->s[4] = SET4(0x510e527fade682d1ULL); - ctx->s[5] = SET4(0x9b05688c2b3e6c1fULL); - ctx->s[6] = SET4(0x1f83d9abfb41bd6bULL); - ctx->s[7] = SET4(0x5be0cd19137e2179ULL); -#undef SET4 - - ctx->datalen = 0; - ctx->msglen = 0; -} - -#define XOR _mm256_xor_si256 -#define OR _mm256_or_si256 -#define AND _mm256_and_si256 -#define ADD64 _mm256_add_epi64 - -#define LOAD(src) _mm256_loadu_si256((__m256i *)(src)) - -#define SHIFTR64(x, y) _mm256_srli_epi64(x, y) -#define SHIFTL64(x, y) _mm256_slli_epi64(x, y) - -#define ROTR64(x, y) OR(SHIFTR64(x, y), SHIFTL64(x, 64 - (y))) - -static u256 XOR3(u256 a, u256 b, u256 c) { - return XOR(XOR(a, b), c); -} - -#define ADD3_64(a, b, c) ADD64(ADD64(a, b), c) -#define ADD4_64(a, b, c, d) ADD64(ADD64(ADD64(a, b), c), d) -#define ADD5_64(a, b, c, d, e) ADD64(ADD64(ADD64(ADD64(a, b), c), d), e) - -static u256 MAJ_AVX(u256 a, u256 b, u256 c) { - return XOR(c, AND(XOR(a, c), XOR(b, c))); -} -static u256 CH_AVX(u256 a, u256 b, u256 c) { - return XOR(c, AND(a, XOR(b, c))); -} -static u256 SIGMA0_AVX(u256 x) { - return XOR3(ROTR64(x, 28), ROTR64(x, 34), ROTR64(x, 39)); -} -static u256 SIGMA1_AVX(u256 x) { - return XOR3(ROTR64(x, 14), ROTR64(x, 18), ROTR64(x, 41)); -} -static u256 GAMMA0_AVX(u256 x) { - return XOR3(ROTR64(x, 1), ROTR64(x, 8), SHIFTR64(x, 7)); -} -static u256 GAMMA1_AVX(u256 x) { - return XOR3(ROTR64(x, 19), ROTR64(x, 61), SHIFTR64(x, 6)); -} - -#define SHA512ROUND_AVX(a, b, c, d, e, f, g, h, rc, w) \ - T0 = ADD5_64(h, w, SIGMA1_AVX(e), CH_AVX(e, f, g), _mm256_set1_epi64x((long long)RC[rc])); \ - T1 = ADD64(SIGMA0_AVX(a), MAJ_AVX(a, b, c)); \ - (d) = ADD64(d, T0); \ - (h) = ADD64(T0, T1); - -static const unsigned long long RC[80] = { - 0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL, - 0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL, - 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL, - 0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL, - 0xd807aa98a3030242ULL, 0x12835b0145706fbeULL, - 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL, - 0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL, - 0x9bdc06a725c71235ULL, 0xc19bf174cf692694ULL, - 0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL, - 0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL, - 0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL, - 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL, - 0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL, - 0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL, - 0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL, - 0x06ca6351e003826fULL, 0x142929670a0e6e70ULL, - 0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL, - 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL, - 0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL, - 0x81c2c92e47edaee6ULL, 0x92722c851482353bULL, - 0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL, - 0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL, - 0xd192e819d6ef5218ULL, 0xd69906245565a910ULL, - 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL, - 0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL, - 0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL, - 0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL, - 0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL, - 0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL, - 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL, - 0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL, - 0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL, - 0xca273eceea26619cULL, 0xd186b8c721c0c207ULL, - 0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL, - 0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL, - 0x113f9804bef90daeULL, 0x1b710b35131c471bULL, - 0x28db77f523047d84ULL, 0x32caab7b40c72493ULL, - 0x3c9ebe0a15c9bebcULL, 0x431d67c49c100d4cULL, - 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL, - 0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL, -}; - -void sha512_transform4x( - sha512x4ctx *ctx, - const unsigned char *d0, - const unsigned char *d1, - const unsigned char *d2, - const unsigned char *d3) { - u256 s0, s1, s2, s3, s4, s5, s6, s7, w[16], T0, T1, nw; - - // Load words and transform data correctly - w[0 ] = BYTESWAP(LOAD(d0 )); - w[0 + 4] = BYTESWAP(LOAD(d0 + 32)); - w[0 + 8] = BYTESWAP(LOAD(d0 + 64)); - w[0 + 12] = BYTESWAP(LOAD(d0 + 96)); - - w[1 ] = BYTESWAP(LOAD(d1 )); - w[1 + 4] = BYTESWAP(LOAD(d1 + 32)); - w[1 + 8] = BYTESWAP(LOAD(d1 + 64)); - w[1 + 12] = BYTESWAP(LOAD(d1 + 96)); - - w[2 ] = BYTESWAP(LOAD(d2 )); - w[2 + 4] = BYTESWAP(LOAD(d2 + 32)); - w[2 + 8] = BYTESWAP(LOAD(d2 + 64)); - w[2 + 12] = BYTESWAP(LOAD(d2 + 96)); - - w[3 ] = BYTESWAP(LOAD(d3 )); - w[3 + 4] = BYTESWAP(LOAD(d3 + 32)); - w[3 + 8] = BYTESWAP(LOAD(d3 + 64)); - w[3 + 12] = BYTESWAP(LOAD(d3 + 96)); - - transpose(w); - transpose(w + 4); - transpose(w + 8); - transpose(w + 12); - - // Initial State - s0 = ctx->s[0]; - s1 = ctx->s[1]; - s2 = ctx->s[2]; - s3 = ctx->s[3]; - s4 = ctx->s[4]; - s5 = ctx->s[5]; - s6 = ctx->s[6]; - s7 = ctx->s[7]; - - // The first 16 rounds (where the w inputs are directly from the data) - SHA512ROUND_AVX(s0, s1, s2, s3, s4, s5, s6, s7, 0, w[0]); - SHA512ROUND_AVX(s7, s0, s1, s2, s3, s4, s5, s6, 1, w[1]); - SHA512ROUND_AVX(s6, s7, s0, s1, s2, s3, s4, s5, 2, w[2]); - SHA512ROUND_AVX(s5, s6, s7, s0, s1, s2, s3, s4, 3, w[3]); - SHA512ROUND_AVX(s4, s5, s6, s7, s0, s1, s2, s3, 4, w[4]); - SHA512ROUND_AVX(s3, s4, s5, s6, s7, s0, s1, s2, 5, w[5]); - SHA512ROUND_AVX(s2, s3, s4, s5, s6, s7, s0, s1, 6, w[6]); - SHA512ROUND_AVX(s1, s2, s3, s4, s5, s6, s7, s0, 7, w[7]); - SHA512ROUND_AVX(s0, s1, s2, s3, s4, s5, s6, s7, 8, w[8]); - SHA512ROUND_AVX(s7, s0, s1, s2, s3, s4, s5, s6, 9, w[9]); - SHA512ROUND_AVX(s6, s7, s0, s1, s2, s3, s4, s5, 10, w[10]); - SHA512ROUND_AVX(s5, s6, s7, s0, s1, s2, s3, s4, 11, w[11]); - SHA512ROUND_AVX(s4, s5, s6, s7, s0, s1, s2, s3, 12, w[12]); - SHA512ROUND_AVX(s3, s4, s5, s6, s7, s0, s1, s2, 13, w[13]); - SHA512ROUND_AVX(s2, s3, s4, s5, s6, s7, s0, s1, 14, w[14]); - SHA512ROUND_AVX(s1, s2, s3, s4, s5, s6, s7, s0, 15, w[15]); - -#define M(i) (((i)+16) & 0xf) -#define NextW(i) \ - w[M(i)] = ADD4_64(GAMMA1_AVX(w[M((i)-2)]), w[M((i)-7)], GAMMA0_AVX(w[M((i)-15)]), w[M((i)-16)]); - - // The remaining 64 rounds (where the w inputs are a linear fix of the data) - for (unsigned i = 16; i < 80; i += 16) { - nw = NextW(0); - SHA512ROUND_AVX(s0, s1, s2, s3, s4, s5, s6, s7, i + 0, nw); - nw = NextW(1); - SHA512ROUND_AVX(s7, s0, s1, s2, s3, s4, s5, s6, i + 1, nw); - nw = NextW(2); - SHA512ROUND_AVX(s6, s7, s0, s1, s2, s3, s4, s5, i + 2, nw); - nw = NextW(3); - SHA512ROUND_AVX(s5, s6, s7, s0, s1, s2, s3, s4, i + 3, nw); - nw = NextW(4); - SHA512ROUND_AVX(s4, s5, s6, s7, s0, s1, s2, s3, i + 4, nw); - nw = NextW(5); - SHA512ROUND_AVX(s3, s4, s5, s6, s7, s0, s1, s2, i + 5, nw); - nw = NextW(6); - SHA512ROUND_AVX(s2, s3, s4, s5, s6, s7, s0, s1, i + 6, nw); - nw = NextW(7); - SHA512ROUND_AVX(s1, s2, s3, s4, s5, s6, s7, s0, i + 7, nw); - nw = NextW(8); - SHA512ROUND_AVX(s0, s1, s2, s3, s4, s5, s6, s7, i + 8, nw); - nw = NextW(9); - SHA512ROUND_AVX(s7, s0, s1, s2, s3, s4, s5, s6, i + 9, nw); - nw = NextW(10); - SHA512ROUND_AVX(s6, s7, s0, s1, s2, s3, s4, s5, i + 10, nw); - nw = NextW(11); - SHA512ROUND_AVX(s5, s6, s7, s0, s1, s2, s3, s4, i + 11, nw); - nw = NextW(12); - SHA512ROUND_AVX(s4, s5, s6, s7, s0, s1, s2, s3, i + 12, nw); - nw = NextW(13); - SHA512ROUND_AVX(s3, s4, s5, s6, s7, s0, s1, s2, i + 13, nw); - nw = NextW(14); - SHA512ROUND_AVX(s2, s3, s4, s5, s6, s7, s0, s1, i + 14, nw); - nw = NextW(15); - SHA512ROUND_AVX(s1, s2, s3, s4, s5, s6, s7, s0, i + 15, nw); - } - - // Feed Forward - ctx->s[0] = ADD64(s0, ctx->s[0]); - ctx->s[1] = ADD64(s1, ctx->s[1]); - ctx->s[2] = ADD64(s2, ctx->s[2]); - ctx->s[3] = ADD64(s3, ctx->s[3]); - ctx->s[4] = ADD64(s4, ctx->s[4]); - ctx->s[5] = ADD64(s5, ctx->s[5]); - ctx->s[6] = ADD64(s6, ctx->s[6]); - ctx->s[7] = ADD64(s7, ctx->s[7]); -} - -static void _sha512x4( - sha512x4ctx *ctx, - unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - unsigned long long inlen) { - unsigned int i = 0; - - while (inlen - i >= 128) { - sha512_transform4x( - ctx, - in0 + i, - in1 + i, - in2 + i, - in3 + i - ); - ctx->msglen += 1024; - i += 128; - } - - ctx->datalen = (unsigned int)(inlen - i); - memcpy(&ctx->msgblocks[128 * 0], in0 + i, ctx->datalen); - memcpy(&ctx->msgblocks[128 * 1], in1 + i, ctx->datalen); - memcpy(&ctx->msgblocks[128 * 2], in2 + i, ctx->datalen); - memcpy(&ctx->msgblocks[128 * 3], in3 + i, ctx->datalen); - - // Padding - unsigned long curlen; - if (ctx->datalen < 112) { - for (i = 0; i < 4; ++i) { - curlen = ctx->datalen; - ctx->msgblocks[128 * i + curlen++] = 0x80; - while (curlen < 128) { - ctx->msgblocks[128 * i + curlen++] = 0x00; - } - } - } else { - for (i = 0; i < 4; ++i) { - curlen = ctx->datalen; - ctx->msgblocks[128 * i + curlen++] = 0x80; - while (curlen < 128) { - ctx->msgblocks[128 * i + curlen++] = 0x00; - } - } - sha512_transform4x( - ctx, - ctx->msgblocks, - ctx->msgblocks + 128, - ctx->msgblocks + 256, - ctx->msgblocks + 384 - ); - memset(ctx->msgblocks, 0, 4 * 128); - } - - // Add length of the message to each block - ctx->msglen += (unsigned long long)(ctx->datalen) * 8; - for (i = 0; i < 4; i++) { - ctx->msgblocks[128 * i + 127] = (unsigned char)(ctx->msglen); - ctx->msgblocks[128 * i + 126] = (unsigned char)(ctx->msglen >> 8); - ctx->msgblocks[128 * i + 125] = (unsigned char)(ctx->msglen >> 16); - ctx->msgblocks[128 * i + 124] = (unsigned char)(ctx->msglen >> 24); - ctx->msgblocks[128 * i + 123] = (unsigned char)(ctx->msglen >> 32); - ctx->msgblocks[128 * i + 122] = (unsigned char)(ctx->msglen >> 40); - ctx->msgblocks[128 * i + 121] = (unsigned char)(ctx->msglen >> 48); - ctx->msgblocks[128 * i + 120] = (unsigned char)(ctx->msglen >> 56); - memset( &ctx->msgblocks[128 * i + 112], 0, 8 ); - } - sha512_transform4x( - ctx, - ctx->msgblocks, - ctx->msgblocks + 128, - ctx->msgblocks + 256, - ctx->msgblocks + 384 - ); - - // Compute final hash output - transpose(ctx->s); - transpose(ctx->s + 4); - - // Store Hash value - __m256i out[2]; - STORE(out, BYTESWAP(ctx->s[0])); - STORE(out + 1, BYTESWAP(ctx->s[4])); - memcpy(out0, out, 64); - - STORE(out, BYTESWAP(ctx->s[1])); - STORE(out + 1, BYTESWAP(ctx->s[5])); - memcpy(out1, out, 64); - - STORE(out, BYTESWAP(ctx->s[2])); - STORE(out + 1, BYTESWAP(ctx->s[6])); - memcpy(out2, out, 64); - - STORE(out, BYTESWAP(ctx->s[3])); - STORE(out + 1, BYTESWAP(ctx->s[7])); - memcpy(out3, out, 64); -} - - -/** - * Note that inlen should be sufficiently small that it still allows for - * an array to be allocated on the stack. Typically 'in' is merely a seed. - * Outputs outlen number of bytes - */ -void mgf1x4_512(unsigned char *outx4, unsigned long outlen, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - unsigned long inlen) { - PQCLEAN_VLA(unsigned char, inbufx4, 4 * (inlen + 4)); - unsigned char outbuf[4 * 64]; - uint32_t i; - unsigned int j; - - memcpy(inbufx4 + 0 * (inlen + 4), in0, inlen); - memcpy(inbufx4 + 1 * (inlen + 4), in1, inlen); - memcpy(inbufx4 + 2 * (inlen + 4), in2, inlen); - memcpy(inbufx4 + 3 * (inlen + 4), in3, inlen); - - /* While we can fit in at least another full block of SHA512 output.. */ - unsigned long remaining = outlen; - for (i = 0; remaining > 0; i++) { - unsigned long this_step = SPX_SHA512_OUTPUT_BYTES; - if (this_step > remaining) { - this_step = remaining; - } - remaining -= this_step; - for (j = 0; j < 4; j++) { - u32_to_bytes(inbufx4 + inlen + j * (inlen + 4), i); - } - - sha512x4ctx ctx; - sha512_init4x(&ctx); - - _sha512x4( - &ctx, - outbuf + 0 * 64, - outbuf + 1 * 64, - outbuf + 2 * 64, - outbuf + 3 * 64, - inbufx4 + 0 * (inlen + 4), - inbufx4 + 1 * (inlen + 4), - inbufx4 + 2 * (inlen + 4), - inbufx4 + 3 * (inlen + 4), - inlen + 4 - ); - - memcpy(outx4 + 0 * outlen, outbuf + 0 * 64, this_step); - memcpy(outx4 + 1 * outlen, outbuf + 1 * 64, this_step); - memcpy(outx4 + 2 * outlen, outbuf + 2 * 64, this_step); - memcpy(outx4 + 3 * outlen, outbuf + 3 * 64, this_step); - outx4 += this_step; - } -} - -void sha512x4_seeded( - unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const sha512x4ctx *seed, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - unsigned long long inlen) { - sha512x4ctx ctx; - sha512_ctx_clone4x(&ctx, seed); - _sha512x4( - &ctx, - out0, out1, out2, out3, - in0, in1, in2, in3, - inlen - ); -} - -void sha512_ctx_clone4x(sha512x4ctx *out, const sha512x4ctx *in) { - memcpy(out, in, sizeof(sha512x4ctx)); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/sha512x4.h b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/sha512x4.h deleted file mode 100644 index 9bbe736514..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/sha512x4.h +++ /dev/null @@ -1,58 +0,0 @@ -#ifndef SHA512AVX_H -#define SHA512AVX_H - -#include -#include - - -#include "params.h" - -typedef struct SHA512state4x { - __m256i s[8]; - unsigned char msgblocks[4 * 128]; - unsigned int datalen; - unsigned long long msglen; -} sha512x4ctx; - -#define sha512_init4x SPX_NAMESPACE(sha512_init4x) -void sha512_init4x(sha512x4ctx *ctx); - -#define sha512_transform4x SPX_NAMESPACE(sha512_transform4x) -void sha512_transform4x( - sha512x4ctx *ctx, - const unsigned char *d0, - const unsigned char *d1, - const unsigned char *d2, - const unsigned char *d3); - - -#define sha512x4_seeded SPX_NAMESPACE(sha512x4_seeded) -void sha512x4_seeded( - unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const sha512x4ctx *seed, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - unsigned long long inlen); - -#define sha512_ctx_clone4x SPX_NAMESPACE(sha512_ctx_clone4x) -void sha512_ctx_clone4x(sha512x4ctx *out, const sha512x4ctx *in); - -/** - * Note that inlen should be sufficiently small that it still allows for - * an array to be allocated on the stack. Typically 'in' is merely a seed. - * Outputs outlen number of bytes - */ -#define mgf1x4_512 SPX_NAMESPACE(mgf1x4_512) -void mgf1x4_512(unsigned char *outx4, unsigned long outlen, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - unsigned long inlen); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/sign.c b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/sign.c deleted file mode 100644 index 9d0c7d1b22..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/sign.c +++ /dev/null @@ -1,286 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "context.h" -#include "fors.h" -#include "hash.h" -#include "merkle.h" -#include "nistapi.h" -#include "params.h" -#include "randombytes.h" -#include "thash.h" -#include "utils.h" -#include "wots.h" - -/* - * Returns the length of a secret key, in bytes - */ -size_t crypto_sign_secretkeybytes(void) { - return CRYPTO_SECRETKEYBYTES; -} - -/* - * Returns the length of a public key, in bytes - */ -size_t crypto_sign_publickeybytes(void) { - return CRYPTO_PUBLICKEYBYTES; -} - -/* - * Returns the length of a signature, in bytes - */ -size_t crypto_sign_bytes(void) { - return CRYPTO_BYTES; -} - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t crypto_sign_seedbytes(void) { - return CRYPTO_SEEDBYTES; -} - -/* - * Generates an SPX key pair given a seed of length - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed) { - spx_ctx ctx; - - /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ - memcpy(sk, seed, CRYPTO_SEEDBYTES); - - memcpy(pk, sk + 2 * SPX_N, SPX_N); - - memcpy(ctx.pub_seed, pk, SPX_N); - memcpy(ctx.sk_seed, sk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - /* Compute root node of the top-most subtree. */ - merkle_gen_root(sk + 3 * SPX_N, &ctx); - - // cleanup - free_hash_function(&ctx); - - memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); - - return 0; -} - -/* - * Generates an SPX key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { - uint8_t seed[CRYPTO_SEEDBYTES]; - randombytes(seed, CRYPTO_SEEDBYTES); - crypto_sign_seed_keypair(pk, sk, seed); - - return 0; -} - -/** - * Returns an array containing a detached signature. - */ -int crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - spx_ctx ctx; - - const uint8_t *sk_prf = sk + SPX_N; - const uint8_t *pk = sk + 2 * SPX_N; - - uint8_t optrand[SPX_N]; - uint8_t mhash[SPX_FORS_MSG_BYTES]; - uint8_t root[SPX_N]; - uint32_t i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - - memcpy(ctx.sk_seed, sk, SPX_N); - memcpy(ctx.pub_seed, pk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - set_type(wots_addr, SPX_ADDR_TYPE_WOTS); - set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); - - /* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ - randombytes(optrand, SPX_N); - /* Compute the digest randomization value. */ - gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); - - /* Derive the message digest and leaf index from R, PK and M. */ - hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); - sig += SPX_N; - - set_tree_addr(wots_addr, tree); - set_keypair_addr(wots_addr, idx_leaf); - - /* Sign the message hash using FORS. */ - fors_sign(sig, root, mhash, &ctx, wots_addr); - sig += SPX_FORS_BYTES; - - for (i = 0; i < SPX_D; i++) { - set_layer_addr(tree_addr, i); - set_tree_addr(tree_addr, tree); - - copy_subtree_addr(wots_addr, tree_addr); - set_keypair_addr(wots_addr, idx_leaf); - - merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); - sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); - tree = tree >> SPX_TREE_HEIGHT; - } - - free_hash_function(&ctx); - - *siglen = SPX_BYTES; - - return 0; -} - -/** - * Verifies a detached signature and message under a given public key. - */ -int crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk) { - spx_ctx ctx; - const uint8_t *pub_root = pk + SPX_N; - uint8_t mhash[SPX_FORS_MSG_BYTES]; - uint8_t wots_pk[SPX_WOTS_BYTES]; - uint8_t root[SPX_N]; - uint8_t leaf[SPX_N]; - unsigned int i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - if (siglen != SPX_BYTES) { - return -1; - } - - memcpy(ctx.pub_seed, pk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - set_type(wots_addr, SPX_ADDR_TYPE_WOTS); - set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); - set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); - - /* Derive the message digest and leaf index from R || PK || M. */ - /* The additional SPX_N is a result of the hash domain separator. */ - hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); - sig += SPX_N; - - /* Layer correctly defaults to 0, so no need to set_layer_addr */ - set_tree_addr(wots_addr, tree); - set_keypair_addr(wots_addr, idx_leaf); - - fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); - sig += SPX_FORS_BYTES; - - /* For each subtree.. */ - for (i = 0; i < SPX_D; i++) { - set_layer_addr(tree_addr, i); - set_tree_addr(tree_addr, tree); - - copy_subtree_addr(wots_addr, tree_addr); - set_keypair_addr(wots_addr, idx_leaf); - - copy_keypair_addr(wots_pk_addr, wots_addr); - - /* The WOTS public key is only correct if the signature was correct. */ - /* Initially, root is the FORS pk, but on subsequent iterations it is - the root of the subtree below the currently processed subtree. */ - wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); - sig += SPX_WOTS_BYTES; - - /* Compute the leaf node using the WOTS public key. */ - thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); - - /* Compute the root node of this subtree. */ - compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, - &ctx, tree_addr); - sig += SPX_TREE_HEIGHT * SPX_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); - tree = tree >> SPX_TREE_HEIGHT; - } - - // cleanup - free_hash_function(&ctx); - - /* Check if the root node equals the root node in the public key. */ - if (memcmp(root, pub_root, SPX_N) != 0) { - return -1; - } - - return 0; -} - - -/** - * Returns an array containing the signature followed by the message. - */ -int crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk) { - size_t siglen; - - crypto_sign_signature(sm, &siglen, m, mlen, sk); - - memmove(sm + SPX_BYTES, m, mlen); - *smlen = siglen + mlen; - - return 0; -} - -/** - * Verifies a given signature-message pair under a given public key. - */ -int crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk) { - /* The API caller does not necessarily know what size a signature should be - but SPHINCS+ signatures are always exactly SPX_BYTES. */ - if (smlen < SPX_BYTES) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - *mlen = smlen - SPX_BYTES; - - if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - /* If verification was successful, move the message to the right place. */ - memmove(m, sm + SPX_BYTES, *mlen); - - return 0; -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/thash.h b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/thash.h deleted file mode 100644 index 8687ccfb4d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/thash.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef SPX_THASH_H -#define SPX_THASH_H - -#include "context.h" -#include "params.h" - -#include - -#define thash SPX_NAMESPACE(thash) -void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/thash_sha2_robust.c b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/thash_sha2_robust.c deleted file mode 100644 index 3ab891175f..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/thash_sha2_robust.c +++ /dev/null @@ -1,68 +0,0 @@ -#include -#include - -#include "address.h" -#include "context.h" -#include "hash.h" -#include "params.h" -#include "sha2.h" -#include "thash.h" -#include "utils.h" - -static void thash_512(unsigned char *out, const unsigned char *in, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]); - -/** - * Takes an array of inblocks concatenated arrays of SPX_N bytes. - */ -void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]) { - if (inblocks > 1) { - thash_512(out, in, inblocks, ctx, addr); - return; - } - unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES]; - PQCLEAN_VLA(uint8_t, bitmask, inblocks * SPX_N); - PQCLEAN_VLA(uint8_t, buf, SPX_N + SPX_SHA256_OUTPUT_BYTES + inblocks * SPX_N); - sha256ctx sha2_state; - unsigned int i; - - memcpy(buf, ctx->pub_seed, SPX_N); - memcpy(buf + SPX_N, addr, SPX_SHA256_ADDR_BYTES); - mgf1_256(bitmask, inblocks * SPX_N, buf, SPX_N + SPX_SHA256_ADDR_BYTES); - - /* Retrieve precomputed state containing pub_seed */ - sha256_inc_ctx_clone(&sha2_state, &ctx->state_seeded); - - for (i = 0; i < inblocks * SPX_N; i++) { - buf[SPX_N + SPX_SHA256_ADDR_BYTES + i] = in[i] ^ bitmask[i]; - } - - sha256_inc_finalize(outbuf, &sha2_state, buf + SPX_N, - SPX_SHA256_ADDR_BYTES + inblocks * SPX_N); - memcpy(out, outbuf, SPX_N); -} - -static void thash_512(unsigned char *out, const unsigned char *in, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]) { - unsigned char outbuf[SPX_SHA512_OUTPUT_BYTES]; - PQCLEAN_VLA(uint8_t, bitmask, inblocks * SPX_N); - PQCLEAN_VLA(uint8_t, buf, SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N); - sha512ctx sha2_state; - unsigned int i; - - memcpy(buf, ctx->pub_seed, SPX_N); - memcpy(buf + SPX_N, addr, SPX_SHA256_ADDR_BYTES); - mgf1_512(bitmask, inblocks * SPX_N, buf, SPX_N + SPX_SHA256_ADDR_BYTES); - - /* Retrieve precomputed state containing pub_seed */ - sha512_inc_ctx_clone(&sha2_state, &ctx->state_seeded_512); - - for (i = 0; i < inblocks * SPX_N; i++) { - buf[SPX_N + SPX_SHA256_ADDR_BYTES + i] = in[i] ^ bitmask[i]; - } - - sha512_inc_finalize(outbuf, &sha2_state, buf + SPX_N, - SPX_SHA256_ADDR_BYTES + inblocks * SPX_N); - memcpy(out, outbuf, SPX_N); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/thash_sha2_robustx8.c b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/thash_sha2_robustx8.c deleted file mode 100644 index 991faa7eeb..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/thash_sha2_robustx8.c +++ /dev/null @@ -1,268 +0,0 @@ -#include -#include - -#include "thashx8.h" - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "sha2.h" -#include "sha256avx.h" -#include "sha256x8.h" -#include "utils.h" - -#include "sha512x4.h" - -static void thashx8_512( - unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - const unsigned char *in4, - const unsigned char *in5, - const unsigned char *in6, - const unsigned char *in7, - unsigned int inblocks, - const spx_ctx *ctx, - uint32_t addrx8[8 * 8] -); - -/** - * 8-way parallel version of thash; takes 8x as much input and output - */ -void thashx8(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - const unsigned char *in4, - const unsigned char *in5, - const unsigned char *in6, - const unsigned char *in7, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addrx8[8 * 8]) { - if (inblocks > 1) { - thashx8_512( - out0, out1, out2, out3, out4, out5, out6, out7, - in0, in1, in2, in3, in4, in5, in6, in7, - inblocks, ctx, addrx8); - return; - } - PQCLEAN_VLA(unsigned char, bufx8, 8 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)); - unsigned char outbufx8[8 * SPX_SHA256_OUTPUT_BYTES]; - PQCLEAN_VLA(unsigned char, bitmaskx8, 8 * (inblocks * SPX_N)); - unsigned int i; - - for (i = 0; i < 8; i++) { - memcpy(bufx8 + i * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - ctx->pub_seed, SPX_N); - memcpy(bufx8 + SPX_N + - i * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - addrx8 + i * 8, SPX_SHA256_ADDR_BYTES); - } - - mgf1x8(bitmaskx8, inblocks * SPX_N, - bufx8 + 0 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + 1 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + 2 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + 3 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + 4 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + 5 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + 6 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + 7 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - SPX_N + SPX_SHA256_ADDR_BYTES); - - for (i = 0; i < inblocks * SPX_N; i++) { - bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + - 0 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = - in0[i] ^ bitmaskx8[i + 0 * (inblocks * SPX_N)]; - bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + - 1 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = - in1[i] ^ bitmaskx8[i + 1 * (inblocks * SPX_N)]; - bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + - 2 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = - in2[i] ^ bitmaskx8[i + 2 * (inblocks * SPX_N)]; - bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + - 3 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = - in3[i] ^ bitmaskx8[i + 3 * (inblocks * SPX_N)]; - bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + - 4 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = - in4[i] ^ bitmaskx8[i + 4 * (inblocks * SPX_N)]; - bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + - 5 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = - in5[i] ^ bitmaskx8[i + 5 * (inblocks * SPX_N)]; - bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + - 6 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = - in6[i] ^ bitmaskx8[i + 6 * (inblocks * SPX_N)]; - bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + - 7 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = - in7[i] ^ bitmaskx8[i + 7 * (inblocks * SPX_N)]; - } - - sha256x8_seeded( - /* out */ - outbufx8 + 0 * SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 1 * SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 2 * SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 3 * SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 4 * SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 5 * SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 6 * SPX_SHA256_OUTPUT_BYTES, - outbufx8 + 7 * SPX_SHA256_OUTPUT_BYTES, - - /* seed */ - &ctx->statex8_seeded, - - /* in */ - bufx8 + SPX_N + 0 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + SPX_N + 1 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + SPX_N + 2 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + SPX_N + 3 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + SPX_N + 4 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + SPX_N + 5 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + SPX_N + 6 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + SPX_N + 7 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - SPX_SHA256_ADDR_BYTES + inblocks * SPX_N /* len */ - ); - - memcpy(out0, outbufx8 + 0 * SPX_SHA256_OUTPUT_BYTES, SPX_N); - memcpy(out1, outbufx8 + 1 * SPX_SHA256_OUTPUT_BYTES, SPX_N); - memcpy(out2, outbufx8 + 2 * SPX_SHA256_OUTPUT_BYTES, SPX_N); - memcpy(out3, outbufx8 + 3 * SPX_SHA256_OUTPUT_BYTES, SPX_N); - memcpy(out4, outbufx8 + 4 * SPX_SHA256_OUTPUT_BYTES, SPX_N); - memcpy(out5, outbufx8 + 5 * SPX_SHA256_OUTPUT_BYTES, SPX_N); - memcpy(out6, outbufx8 + 6 * SPX_SHA256_OUTPUT_BYTES, SPX_N); - memcpy(out7, outbufx8 + 7 * SPX_SHA256_OUTPUT_BYTES, SPX_N); -} - -/** - * 2x4-way parallel version of thash; this is for the uses of thash that are - * based on SHA-512 - */ -static void thashx8_512( - unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - const unsigned char *in4, - const unsigned char *in5, - const unsigned char *in6, - const unsigned char *in7, - unsigned int inblocks, - const spx_ctx *ctx, - uint32_t addrx8[8 * 8]) { - PQCLEAN_VLA(unsigned char, bufx8, 8 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)); - unsigned char outbuf[4 * SPX_SHA512_OUTPUT_BYTES]; - PQCLEAN_VLA(unsigned char, bitmaskx4, 4 * (inblocks * SPX_N)); - unsigned int i; - - for (i = 0; i < 8; i++) { - memcpy(bufx8 + i * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - ctx->pub_seed, SPX_N); - memcpy(bufx8 + SPX_N + - i * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - addrx8 + i * 8, SPX_SHA256_ADDR_BYTES); - } - - mgf1x4_512(bitmaskx4, inblocks * SPX_N, - bufx8 + 0 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + 1 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + 2 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + 3 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - SPX_N + SPX_SHA256_ADDR_BYTES); - - for (i = 0; i < inblocks * SPX_N; i++) { - bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + - 0 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = - in0[i] ^ bitmaskx4[i + 0 * (inblocks * SPX_N)]; - bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + - 1 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = - in1[i] ^ bitmaskx4[i + 1 * (inblocks * SPX_N)]; - bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + - 2 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = - in2[i] ^ bitmaskx4[i + 2 * (inblocks * SPX_N)]; - bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + - 3 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = - in3[i] ^ bitmaskx4[i + 3 * (inblocks * SPX_N)]; - } - - mgf1x4_512(bitmaskx4, inblocks * SPX_N, - bufx8 + 4 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + 5 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + 6 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + 7 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - SPX_N + SPX_SHA256_ADDR_BYTES); - - for (i = 0; i < inblocks * SPX_N; i++) { - bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + - 4 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = - in4[i] ^ bitmaskx4[i + 0 * (inblocks * SPX_N)]; - bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + - 5 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = - in5[i] ^ bitmaskx4[i + 1 * (inblocks * SPX_N)]; - bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + - 6 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = - in6[i] ^ bitmaskx4[i + 2 * (inblocks * SPX_N)]; - bufx8[SPX_N + SPX_SHA256_ADDR_BYTES + i + - 7 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N)] = - in7[i] ^ bitmaskx4[i + 3 * (inblocks * SPX_N)]; - } - - sha512x4_seeded( - outbuf + 0 * SPX_SHA512_OUTPUT_BYTES, - outbuf + 1 * SPX_SHA512_OUTPUT_BYTES, - outbuf + 2 * SPX_SHA512_OUTPUT_BYTES, - outbuf + 3 * SPX_SHA512_OUTPUT_BYTES, - &ctx->statex4_seeded_512, /* seed */ - bufx8 + SPX_N + 0 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + SPX_N + 1 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + SPX_N + 2 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + SPX_N + 3 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - SPX_SHA256_ADDR_BYTES + inblocks * SPX_N /* len */ - ); - - memcpy(out0, outbuf + 0 * SPX_SHA512_OUTPUT_BYTES, SPX_N); - memcpy(out1, outbuf + 1 * SPX_SHA512_OUTPUT_BYTES, SPX_N); - memcpy(out2, outbuf + 2 * SPX_SHA512_OUTPUT_BYTES, SPX_N); - memcpy(out3, outbuf + 3 * SPX_SHA512_OUTPUT_BYTES, SPX_N); - - sha512x4_seeded( - outbuf + 0 * SPX_SHA512_OUTPUT_BYTES, - outbuf + 1 * SPX_SHA512_OUTPUT_BYTES, - outbuf + 2 * SPX_SHA512_OUTPUT_BYTES, - outbuf + 3 * SPX_SHA512_OUTPUT_BYTES, - &ctx->statex4_seeded_512, /* seed */ - bufx8 + SPX_N + 4 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + SPX_N + 5 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + SPX_N + 6 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - bufx8 + SPX_N + 7 * (SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N), - SPX_SHA256_ADDR_BYTES + inblocks * SPX_N /* len */ - ); - - memcpy(out4, outbuf + 0 * SPX_SHA512_OUTPUT_BYTES, SPX_N); - memcpy(out5, outbuf + 1 * SPX_SHA512_OUTPUT_BYTES, SPX_N); - memcpy(out6, outbuf + 2 * SPX_SHA512_OUTPUT_BYTES, SPX_N); - memcpy(out7, outbuf + 3 * SPX_SHA512_OUTPUT_BYTES, SPX_N); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/thashx8.h b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/thashx8.h deleted file mode 100644 index c02fe9cf3e..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/thashx8.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef SPX_THASHX8_H -#define SPX_THASHX8_H - -#include - -#include "context.h" -#include "params.h" - -#define thashx8 SPX_NAMESPACE(thashx8) -void thashx8(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - const unsigned char *in4, - const unsigned char *in5, - const unsigned char *in6, - const unsigned char *in7, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addrx8[8 * 8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/utils.c b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/utils.c deleted file mode 100644 index 177b541fb9..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/utils.c +++ /dev/null @@ -1,148 +0,0 @@ -#include - -#include "utils.h" - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "thash.h" - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void ull_to_bytes(unsigned char *out, unsigned int outlen, - unsigned long long in) { - int i; - - /* Iterate over out in decreasing order, for big-endianness. */ - for (i = (signed int)outlen - 1; i >= 0; i--) { - out[i] = in & 0xff; - in = in >> 8; - } -} - -void u32_to_bytes(unsigned char *out, uint32_t in) { - out[0] = (unsigned char)(in >> 24); - out[1] = (unsigned char)(in >> 16); - out[2] = (unsigned char)(in >> 8); - out[3] = (unsigned char)in; -} - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { - unsigned long long retval = 0; - unsigned int i; - - for (i = 0; i < inlen; i++) { - retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); - } - return retval; -} - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void compute_root(unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const spx_ctx *ctx, uint32_t addr[8]) { - uint32_t i; - unsigned char buffer[2 * SPX_N]; - - /* If leaf_idx is odd (last bit = 1), current path element is a right child - and auth_path has to go left. Otherwise it is the other way around. */ - if (leaf_idx & 1) { - memcpy(buffer + SPX_N, leaf, SPX_N); - memcpy(buffer, auth_path, SPX_N); - } else { - memcpy(buffer, leaf, SPX_N); - memcpy(buffer + SPX_N, auth_path, SPX_N); - } - auth_path += SPX_N; - - for (i = 0; i < tree_height - 1; i++) { - leaf_idx >>= 1; - idx_offset >>= 1; - /* Set the address of the node we're creating. */ - set_tree_height(addr, i + 1); - set_tree_index(addr, leaf_idx + idx_offset); - - /* Pick the right or left neighbor, depending on parity of the node. */ - if (leaf_idx & 1) { - thash(buffer + SPX_N, buffer, 2, ctx, addr); - memcpy(buffer, auth_path, SPX_N); - } else { - thash(buffer, buffer, 2, ctx, addr); - memcpy(buffer + SPX_N, auth_path, SPX_N); - } - auth_path += SPX_N; - } - - /* The last iteration is exceptional; we do not copy an auth_path node. */ - leaf_idx >>= 1; - idx_offset >>= 1; - set_tree_height(addr, tree_height); - set_tree_index(addr, leaf_idx + idx_offset); - thash(root, buffer, 2, ctx, addr); -} - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const spx_ctx * /* ctx */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), - uint32_t tree_addr[8]) { - PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); - PQCLEAN_VLA(unsigned int, heights, tree_height + 1); - unsigned int offset = 0; - uint32_t idx; - uint32_t tree_idx; - - for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { - /* Add the next leaf node to the stack. */ - gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); - offset++; - heights[offset - 1] = 0; - - /* If this is a node we need for the auth path.. */ - if ((leaf_idx ^ 0x1) == idx) { - memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); - } - - /* While the top-most nodes are of equal height.. */ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { - /* Compute index of the new node, in the next layer. */ - tree_idx = (idx >> (heights[offset - 1] + 1)); - - /* Set the address of the node we're creating. */ - set_tree_height(tree_addr, heights[offset - 1] + 1); - set_tree_index(tree_addr, - tree_idx + (idx_offset >> (heights[offset - 1] + 1))); - /* Hash the top-most nodes from the stack together. */ - thash(stack + (offset - 2)*SPX_N, - stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); - offset--; - /* Note that the top-most node is now one layer higher. */ - heights[offset - 1]++; - - /* If this is a node we need for the auth path.. */ - if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_path + heights[offset - 1]*SPX_N, - stack + (offset - 1)*SPX_N, SPX_N); - } - } - } - memcpy(root, stack, SPX_N); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/utils.h b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/utils.h deleted file mode 100644 index 64f5d5a53a..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/utils.h +++ /dev/null @@ -1,58 +0,0 @@ -#ifndef SPX_UTILS_H -#define SPX_UTILS_H - -#include - -#include "compat.h" -#include "context.h" -#include "params.h" - - -/* To support MSVC use alloca() instead of VLAs. See #20. */ - - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) -void ull_to_bytes(unsigned char *out, unsigned int outlen, - unsigned long long in); -#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) -void u32_to_bytes(unsigned char *out, uint32_t in); - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) -unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -#define compute_root SPX_NAMESPACE(compute_root) -void compute_root(unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const spx_ctx *ctx, uint32_t addr[8]); - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -#define treehash SPX_NAMESPACE(treehash) -void treehash(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const spx_ctx *ctx /* ctx */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), - uint32_t tree_addr[8]); - - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/utilsx8.c b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/utilsx8.c deleted file mode 100644 index f044b9595d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/utilsx8.c +++ /dev/null @@ -1,146 +0,0 @@ -#include - -#include "utils.h" -#include "utilsx8.h" - -#include "address.h" -#include "params.h" -#include "thashx8.h" - -/* - * Generate the entire Merkle tree, computing the authentication path for leaf_idx, - * and the resulting root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) - * - * This expects tree_addrx8 to be initialized to 8 parallel addr structures for - * the Merkle tree nodes - * - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - * - * This works by using the standard Merkle tree building algorithm, except - * that each 'node' tracked is actually 8 consecutive nodes in the real tree. - * When we combine two logical nodes ABCDEFGH and STUVWXYZ, we perform the H - * operation on adjacent real nodes, forming the parent logical node - * (AB)(CD)(EF)(GH)(ST)(UV)(WX)(YZ) - * - * When we get to the top three levels of the real tree (where there is only - * one logical node), we continue this operation three more times; the right - * most real node will by the actual root (and the other 7 nodes will be - * garbage). We follow the same thashx8 logic so that the 'extract - * authentication path components' part of the loop is still executed (and - * to simplify the code somewhat) - * - * This currently assumes tree_height >= 3; I suspect that doing an adjusting - * idx, addr_idx on the gen_leafx8 call if tree_height < 3 would fix it; since - * we don't actually use such short trees, I haven't bothered - */ -void treehashx8(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, - uint32_t tree_height, - void (*gen_leafx8)( - unsigned char * /* Where to write the leaves */, - const spx_ctx *, - uint32_t idx, void *info), - uint32_t tree_addrx8[8 * 8], - void *info) { - /* This is where we keep the intermediate nodes */ - PQCLEAN_VLA(unsigned char, stackx8, tree_height * 8 * SPX_N); - uint32_t left_adj = 0, prev_left_adj = 0; /* When we're doing the top 3 */ - /* levels, the left-most part of the tree isn't at the beginning */ - /* of current[]. These give the offset of the actual start */ - - uint32_t idx; - uint32_t max_idx = ((uint32_t)1 << (tree_height - 3)) - 1; - for (idx = 0;; idx++) { - unsigned char current[8 * SPX_N]; /* Current logical node */ - gen_leafx8( current, ctx, 8 * idx + idx_offset, - info ); - - /* Now combine the freshly generated right node with previously */ - /* generated left ones */ - uint32_t internal_idx_offset = idx_offset; - uint32_t internal_idx = idx; - uint32_t internal_leaf = leaf_idx; - uint32_t h; /* The height we are in the Merkle tree */ - for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { - - /* Special processing if we're at the top of the tree */ - if (h >= tree_height - 3) { - if (h == tree_height) { - /* We hit the root; return it */ - memcpy( root, ¤t[7 * SPX_N], SPX_N ); - return; - } - /* The tree indexing logic is a bit off in this case */ - /* Adjust it so that the left-most node of the part of */ - /* the tree that we're processing has index 0 */ - prev_left_adj = left_adj; - left_adj = (uint32_t)(8 - (1 << (tree_height - h - 1))); - } - - /* Check if we hit the top of the tree */ - if (h == tree_height) { - /* We hit the root; return it */ - memcpy( root, ¤t[7 * SPX_N], SPX_N ); - return; - } - - /* - * Check if one of the nodes we have is a part of the - * authentication path; if it is, write it out - */ - if ((((internal_idx << 3) ^ internal_leaf) & ~0x7U) == 0) { - memcpy( &auth_path[ h * SPX_N ], - ¤t[(((internal_leaf & 7) ^ 1) + prev_left_adj) * SPX_N], - SPX_N ); - } - - /* - * Check if we're at a left child; if so, stop going up the stack - * Exception: if we've reached the end of the tree, keep on going - * (so we combine the last 8 nodes into the one root node in three - * more iterations) - */ - if ((internal_idx & 1) == 0 && idx < max_idx) { - break; - } - - /* Ok, we're at a right node (or doing the top 3 levels) */ - /* Now combine the left and right logical nodes together */ - - /* Set the address of the node we're creating. */ - uint32_t j; - internal_idx_offset >>= 1; - for (j = 0; j < 8; j++) { - set_tree_height(tree_addrx8 + j * 8, h + 1); - set_tree_index(tree_addrx8 + j * 8, - (8 / 2) * (internal_idx & ~1U) + j - left_adj + internal_idx_offset ); - } - unsigned char *left = &stackx8[h * 8 * SPX_N]; - thashx8( ¤t[0 * SPX_N], - ¤t[1 * SPX_N], - ¤t[2 * SPX_N], - ¤t[3 * SPX_N], - ¤t[4 * SPX_N], - ¤t[5 * SPX_N], - ¤t[6 * SPX_N], - ¤t[7 * SPX_N], - &left [0 * SPX_N], - &left [2 * SPX_N], - &left [4 * SPX_N], - &left [6 * SPX_N], - ¤t[0 * SPX_N], - ¤t[2 * SPX_N], - ¤t[4 * SPX_N], - ¤t[6 * SPX_N], - 2, ctx, tree_addrx8); - } - - /* We've hit a left child; save the current for when we get the */ - /* corresponding right right */ - memcpy( &stackx8[h * 8 * SPX_N], current, 8 * SPX_N); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/utilsx8.h b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/utilsx8.h deleted file mode 100644 index 806d1e85be..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/utilsx8.h +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef SPX_UTILSX8_H -#define SPX_UTILSX8_H - -#include - -#include "params.h" - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - * - * This implementation uses AVX to compute internal nodes 8 at a time (in - * parallel) - */ -#define treehashx8 SPX_NAMESPACE(treehashx8) -void treehashx8(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leafx8)( - unsigned char * /* Where to write the leaves */, - const spx_ctx * /* ctx */, - uint32_t addr_idx, void *info), - uint32_t tree_addrx8[8 * 8], void *info); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/wots.c b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/wots.c deleted file mode 100644 index 689baf4db9..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/wots.c +++ /dev/null @@ -1,291 +0,0 @@ -#include -#include - -#include "wots.h" - -#include "address.h" -#include "hash.h" -#include "hashx8.h" -#include "params.h" -#include "thash.h" -#include "thashx8.h" -#include "utils.h" -#include "utilsx8.h" -#include "wotsx8.h" - -// TODO clarify address expectations, and make them more uniform. -// TODO i.e. do we expect types to be set already? -// TODO and do we expect modifications or copies? - -/** - * Computes up the chains - */ -static void gen_chains( - unsigned char *out, - const unsigned char *in, - unsigned int start[SPX_WOTS_LEN], - const unsigned int steps[SPX_WOTS_LEN], - const spx_ctx *ctx, - uint32_t addr[8]) { - uint32_t i, j, k, idx, watching; - int done; - unsigned char empty[SPX_N]; - unsigned char *bufs[8]; - uint32_t addrs[8 * 8]; - - int l; - uint16_t counts[SPX_WOTS_W] = { 0 }; - uint16_t idxs[SPX_WOTS_LEN]; - uint16_t total, newTotal; - - /* set addrs = {addr, addr, ..., addr} */ - for (j = 0; j < 8; j++) { - memcpy(addrs + j * 8, addr, sizeof(uint32_t) * 8); - } - - /* Initialize out with the value at position 'start'. */ - memcpy(out, in, SPX_WOTS_LEN * SPX_N); - - /* Sort the chains in reverse order by steps using counting sort. */ - for (i = 0; i < SPX_WOTS_LEN; i++) { - counts[steps[i]]++; - } - total = 0; - for (l = SPX_WOTS_W - 1; l >= 0; l--) { - newTotal = counts[l] + total; - counts[l] = total; - total = newTotal; - } - for (i = 0; i < SPX_WOTS_LEN; i++) { - idxs[counts[steps[i]]] = (uint16_t)i; - counts[steps[i]]++; - } - - /* We got our work cut out for us: do it! */ - for (i = 0; i < SPX_WOTS_LEN; i += 8) { - for (j = 0; j < 8 && i + j < SPX_WOTS_LEN; j++) { - idx = idxs[i + j]; - set_chain_addr(addrs + j * 8, idx); - bufs[j] = out + SPX_N * idx; - } - - /* As the chains are sorted in reverse order, we know that the first - * chain is the longest and the last one is the shortest. We keep - * an eye on whether the last chain is done and then on the one before, - * et cetera. */ - watching = 7; - done = 0; - while (i + watching >= SPX_WOTS_LEN) { - bufs[watching] = &empty[0]; - watching--; - } - - for (k = 0;; k++) { - while (k == steps[idxs[i + watching]]) { - bufs[watching] = &empty[0]; - if (watching == 0) { - done = 1; - break; - } - watching--; - } - if (done) { - break; - } - for (j = 0; j < watching + 1; j++) { - set_hash_addr(addrs + j * 8, k + start[idxs[i + j]]); - } - - thashx8(bufs[0], bufs[1], bufs[2], bufs[3], - bufs[4], bufs[5], bufs[6], bufs[7], - bufs[0], bufs[1], bufs[2], bufs[3], - bufs[4], bufs[5], bufs[6], bufs[7], 1, ctx, addrs); - } - } -} - -/** - * base_w algorithm as described in draft. - * Interprets an array of bytes as integers in base w. - * This only works when log_w is a divisor of 8. - */ -static void base_w(unsigned int *output, const int out_len, - const unsigned char *input) { - int in = 0; - int out = 0; - unsigned char total = 0; - int bits = 0; - int consumed; - - for (consumed = 0; consumed < out_len; consumed++) { - if (bits == 0) { - total = input[in]; - in++; - bits += 8; - } - bits -= SPX_WOTS_LOGW; - output[out] = (total >> bits) & (SPX_WOTS_W - 1); - out++; - } -} - -/* Computes the WOTS+ checksum over a message (in base_w). */ -static void wots_checksum(unsigned int *csum_base_w, - const unsigned int *msg_base_w) { - unsigned int csum = 0; - unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; - unsigned int i; - - /* Compute checksum. */ - for (i = 0; i < SPX_WOTS_LEN1; i++) { - csum += SPX_WOTS_W - 1 - msg_base_w[i]; - } - - /* Convert checksum to base_w. */ - /* Make sure expected empty zero bits are the least significant bits. */ - csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); - ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); - base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); -} - -/* Takes a message and derives the matching chain lengths. */ -void chain_lengths(unsigned int *lengths, const unsigned char *msg) { - base_w(lengths, SPX_WOTS_LEN1, msg); - wots_checksum(lengths + SPX_WOTS_LEN1, lengths); -} - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const spx_ctx *ctx, uint32_t addr[8]) { - unsigned int steps[SPX_WOTS_LEN]; - unsigned int start[SPX_WOTS_LEN]; - uint32_t i; - - chain_lengths(start, msg); - - for (i = 0; i < SPX_WOTS_LEN; i++) { - steps[i] = SPX_WOTS_W - 1 - start[i]; - } - - gen_chains(pk, sig, start, steps, ctx, addr); -} - -/* - * This generates 8 sequential WOTS public keys - * It also generates the WOTS signature if leaf_info indicates - * that we're signing with one of these WOTS keys - */ -void wots_gen_leafx8(unsigned char *dest, - const spx_ctx *ctx, - uint32_t leaf_idx, void *v_info) { - struct leaf_info_x8 *info = v_info; - uint32_t *leaf_addr = info->leaf_addr; - uint32_t *pk_addr = info->pk_addr; - unsigned int i, j, k; - unsigned char pk_buffer[ 8 * SPX_WOTS_BYTES ]; - unsigned wots_offset = SPX_WOTS_BYTES; - unsigned char *buffer; - uint32_t wots_k_mask; - unsigned wots_sign_index; - - if (((leaf_idx ^ info->wots_sign_leaf) & ~7U) == 0) { - /* We're traversing the leaf that's signing; generate the WOTS */ - /* signature */ - wots_k_mask = 0; - wots_sign_index = info->wots_sign_leaf & 7; /* Which of of the 8 */ - /* slots do the signatures come from */ - } else { - /* Nope, we're just generating pk's; turn off the signature logic */ - wots_k_mask = ~0U; - wots_sign_index = 0; - } - - for (j = 0; j < 8; j++) { - set_keypair_addr( leaf_addr + j * 8, leaf_idx + j ); - set_keypair_addr( pk_addr + j * 8, leaf_idx + j ); - } - - for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { - uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k */ - /* to the step if we're generating a signature, ~0 if we're not */ - - /* Start with the secret seed */ - for (j = 0; j < 8; j++) { - set_chain_addr(leaf_addr + j * 8, i); - set_hash_addr(leaf_addr + j * 8, 0); - set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTSPRF); - } - prf_addrx8(buffer + 0 * wots_offset, - buffer + 1 * wots_offset, - buffer + 2 * wots_offset, - buffer + 3 * wots_offset, - buffer + 4 * wots_offset, - buffer + 5 * wots_offset, - buffer + 6 * wots_offset, - buffer + 7 * wots_offset, - ctx, leaf_addr); - - for (j = 0; j < 8; j++) { - set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTS); - } - - /* Iterate down the WOTS chain */ - for (k = 0;; k++) { - /* Check if one of the values we have needs to be saved as a */ - /* part of the WOTS signature */ - if (k == wots_k) { - memcpy( info->wots_sig + i * SPX_N, - buffer + wots_sign_index * wots_offset, SPX_N ); - } - - /* Check if we hit the top of the chain */ - if (k == SPX_WOTS_W - 1) { - break; - } - - /* Iterate one step on all 8 chains */ - for (j = 0; j < 8; j++) { - set_hash_addr(leaf_addr + j * 8, k); - } - thashx8(buffer + 0 * wots_offset, - buffer + 1 * wots_offset, - buffer + 2 * wots_offset, - buffer + 3 * wots_offset, - buffer + 4 * wots_offset, - buffer + 5 * wots_offset, - buffer + 6 * wots_offset, - buffer + 7 * wots_offset, - buffer + 0 * wots_offset, - buffer + 1 * wots_offset, - buffer + 2 * wots_offset, - buffer + 3 * wots_offset, - buffer + 4 * wots_offset, - buffer + 5 * wots_offset, - buffer + 6 * wots_offset, - buffer + 7 * wots_offset, 1, ctx, leaf_addr); - } - } - - /* Do the final thash to generate the public keys */ - thashx8(dest + 0 * SPX_N, - dest + 1 * SPX_N, - dest + 2 * SPX_N, - dest + 3 * SPX_N, - dest + 4 * SPX_N, - dest + 5 * SPX_N, - dest + 6 * SPX_N, - dest + 7 * SPX_N, - pk_buffer + 0 * wots_offset, - pk_buffer + 1 * wots_offset, - pk_buffer + 2 * wots_offset, - pk_buffer + 3 * wots_offset, - pk_buffer + 4 * wots_offset, - pk_buffer + 5 * wots_offset, - pk_buffer + 6 * wots_offset, - pk_buffer + 7 * wots_offset, SPX_WOTS_LEN, ctx, pk_addr); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/wots.h b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/wots.h deleted file mode 100644 index 4e7692eeef..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/wots.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef SPX_WOTS_H -#define SPX_WOTS_H - -#include - -#include "context.h" -#include "params.h" - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) -void wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const spx_ctx *ctx, uint32_t addr[8]); - -/* - * Compute the chain lengths needed for a given message hash - */ -#define chain_lengths SPX_NAMESPACE(chain_lengths) -void chain_lengths(unsigned int *lengths, const unsigned char *msg); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/wotsx8.h b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/wotsx8.h deleted file mode 100644 index 10866efb35..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_avx2/wotsx8.h +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef WOTSX8_H_ -#define WOTSX8_H_ - -#include - -#include "context.h" -#include "params.h" - -/* - * This is here to provide an interface to the internal wots_gen_leafx8 - * routine. While this routine is not referenced in the package outside of - * wots.c, it is called from the stand-alone benchmark code to characterize - * the performance - */ -struct leaf_info_x8 { - unsigned char *wots_sig; - uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ - uint32_t *wots_steps; - uint32_t leaf_addr[8 * 8]; - uint32_t pk_addr[8 * 8]; -}; - -/* Macro to set the leaf_info to something 'benign', that is, it would */ -/* run with the same time as it does during the real signing process */ -/* Used only by the benchmark code */ -#define INITIALIZE_LEAF_INFO_X8(info, addr, step_buffer) { \ - (info).wots_sig = 0; \ - (info).wots_sign_leaf = ~0; \ - (info).wots_steps = step_buffer; \ - int i; \ - for (i=0; i<8; i++) { \ - memcpy( &(info).leaf_addr[8*i], addr, 32 ); \ - memcpy( &(info).pk_addr[8*i], addr, 32 ); \ - } \ - } - -#define wots_gen_leafx8 SPX_NAMESPACE(wots_gen_leafx8) -void wots_gen_leafx8(unsigned char *dest, - const spx_ctx *ctx, - uint32_t leaf_idx, void *v_info); - -#endif /* WOTSX8_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/LICENSE b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/LICENSE deleted file mode 100644 index 670154e353..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/LICENSE +++ /dev/null @@ -1,116 +0,0 @@ -CC0 1.0 Universal - -Statement of Purpose - -The laws of most jurisdictions throughout the world automatically confer -exclusive Copyright and Related Rights (defined below) upon the creator and -subsequent owner(s) (each and all, an "owner") of an original work of -authorship and/or a database (each, a "Work"). - -Certain owners wish to permanently relinquish those rights to a Work for the -purpose of contributing to a commons of creative, cultural and scientific -works ("Commons") that the public can reliably and without fear of later -claims of infringement build upon, modify, incorporate in other works, reuse -and redistribute as freely as possible in any form whatsoever and for any -purposes, including without limitation commercial purposes. These owners may -contribute to the Commons to promote the ideal of a free culture and the -further production of creative, cultural and scientific works, or to gain -reputation or greater distribution for their Work in part through the use and -efforts of others. - -For these and/or other purposes and motivations, and without any expectation -of additional consideration or compensation, the person associating CC0 with a -Work (the "Affirmer"), to the extent that he or she is an owner of Copyright -and Related Rights in the Work, voluntarily elects to apply CC0 to the Work -and publicly distribute the Work under its terms, with knowledge of his or her -Copyright and Related Rights in the Work and the meaning and intended legal -effect of CC0 on those rights. - -1. Copyright and Related Rights. A Work made available under CC0 may be -protected by copyright and related or neighboring rights ("Copyright and -Related Rights"). Copyright and Related Rights include, but are not limited -to, the following: - - i. the right to reproduce, adapt, distribute, perform, display, communicate, - and translate a Work; - - ii. moral rights retained by the original author(s) and/or performer(s); - - iii. publicity and privacy rights pertaining to a person's image or likeness - depicted in a Work; - - iv. rights protecting against unfair competition in regards to a Work, - subject to the limitations in paragraph 4(a), below; - - v. rights protecting the extraction, dissemination, use and reuse of data in - a Work; - - vi. database rights (such as those arising under Directive 96/9/EC of the - European Parliament and of the Council of 11 March 1996 on the legal - protection of databases, and under any national implementation thereof, - including any amended or successor version of such directive); and - - vii. other similar, equivalent or corresponding rights throughout the world - based on applicable law or treaty, and any national implementations thereof. - -2. Waiver. To the greatest extent permitted by, but not in contravention of, -applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and -unconditionally waives, abandons, and surrenders all of Affirmer's Copyright -and Related Rights and associated claims and causes of action, whether now -known or unknown (including existing as well as future claims and causes of -action), in the Work (i) in all territories worldwide, (ii) for the maximum -duration provided by applicable law or treaty (including future time -extensions), (iii) in any current or future medium and for any number of -copies, and (iv) for any purpose whatsoever, including without limitation -commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes -the Waiver for the benefit of each member of the public at large and to the -detriment of Affirmer's heirs and successors, fully intending that such Waiver -shall not be subject to revocation, rescission, cancellation, termination, or -any other legal or equitable action to disrupt the quiet enjoyment of the Work -by the public as contemplated by Affirmer's express Statement of Purpose. - -3. Public License Fallback. Should any part of the Waiver for any reason be -judged legally invalid or ineffective under applicable law, then the Waiver -shall be preserved to the maximum extent permitted taking into account -Affirmer's express Statement of Purpose. In addition, to the extent the Waiver -is so judged Affirmer hereby grants to each affected person a royalty-free, -non transferable, non sublicensable, non exclusive, irrevocable and -unconditional license to exercise Affirmer's Copyright and Related Rights in -the Work (i) in all territories worldwide, (ii) for the maximum duration -provided by applicable law or treaty (including future time extensions), (iii) -in any current or future medium and for any number of copies, and (iv) for any -purpose whatsoever, including without limitation commercial, advertising or -promotional purposes (the "License"). The License shall be deemed effective as -of the date CC0 was applied by Affirmer to the Work. Should any part of the -License for any reason be judged legally invalid or ineffective under -applicable law, such partial invalidity or ineffectiveness shall not -invalidate the remainder of the License, and in such case Affirmer hereby -affirms that he or she will not (i) exercise any of his or her remaining -Copyright and Related Rights in the Work or (ii) assert any associated claims -and causes of action with respect to the Work, in either case contrary to -Affirmer's express Statement of Purpose. - -4. Limitations and Disclaimers. - - a. No trademark or patent rights held by Affirmer are waived, abandoned, - surrendered, licensed or otherwise affected by this document. - - b. Affirmer offers the Work as-is and makes no representations or warranties - of any kind concerning the Work, express, implied, statutory or otherwise, - including without limitation warranties of title, merchantability, fitness - for a particular purpose, non infringement, or the absence of latent or - other defects, accuracy, or the present or absence of errors, whether or not - discoverable, all to the greatest extent permissible under applicable law. - - c. Affirmer disclaims responsibility for clearing rights of other persons - that may apply to the Work or any use thereof, including without limitation - any person's Copyright and Related Rights in the Work. Further, Affirmer - disclaims responsibility for obtaining any necessary consents, permissions - or other rights required for any use of the Work. - - d. Affirmer understands and acknowledges that Creative Commons is not a - party to this document and has no duty or obligation with respect to this - CC0 or use of the Work. - -For more information, please see - diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/address.c b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/address.c deleted file mode 100644 index b956e9cb29..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/address.c +++ /dev/null @@ -1,91 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "utils.h" - -/* - * Specify which level of Merkle tree (the "layer") we're working on - */ -void set_layer_addr(uint32_t addr[8], uint32_t layer) { - ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; -} - -/* - * Specify which Merkle tree within the level (the "tree address") we're working on - */ -void set_tree_addr(uint32_t addr[8], uint64_t tree) { - ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); -} - -/* - * Specify the reason we'll use this address structure for, that is, what - * hash will we compute with it. This is used so that unrelated types of - * hashes don't accidentally get the same address structure. The type will be - * one of the SPX_ADDR_TYPE constants - */ -void set_type(uint32_t addr[8], uint32_t type) { - ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; -} - -/* - * Copy the layer and tree fields of the address structure. This is used - * when we're doing multiple types of hashes within the same Merkle tree - */ -void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { - memcpy( out, in, SPX_OFFSET_TREE + 8 ); -} - -/* These functions are used for OTS addresses. */ - -/* - * Specify which Merkle leaf we're working on; that is, which OTS keypair - * we're talking about. - */ -void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { - ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; -} - -/* - * Copy the layer, tree and keypair fields of the address structure. This is - * used when we're doing multiple things within the same OTS keypair - */ -void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { - memcpy( out, in, SPX_OFFSET_TREE + 8 ); - ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; -} - -/* - * Specify which Merkle chain within the OTS we're working with - * (the chain address) - */ -void set_chain_addr(uint32_t addr[8], uint32_t chain) { - ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; -} - -/* - * Specify where in the Merkle chain we are -* (the hash address) - */ -void set_hash_addr(uint32_t addr[8], uint32_t hash) { - ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; -} - -/* These functions are used for all hash tree addresses (including FORS). */ - -/* - * Specify the height of the node in the Merkle/FORS tree we are in - * (the tree height) - */ -void set_tree_height(uint32_t addr[8], uint32_t tree_height) { - ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; -} - -/* - * Specify the distance from the left edge of the node in the Merkle/FORS tree - * (the tree index) - */ -void set_tree_index(uint32_t addr[8], uint32_t tree_index) { - u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/address.h b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/address.h deleted file mode 100644 index 24a84eb40c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/address.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef SPX_ADDRESS_H -#define SPX_ADDRESS_H - -#include - -#include "params.h" - -/* The hash types that are passed to set_type */ -#define SPX_ADDR_TYPE_WOTS 0 -#define SPX_ADDR_TYPE_WOTSPK 1 -#define SPX_ADDR_TYPE_HASHTREE 2 -#define SPX_ADDR_TYPE_FORSTREE 3 -#define SPX_ADDR_TYPE_FORSPK 4 -#define SPX_ADDR_TYPE_WOTSPRF 5 -#define SPX_ADDR_TYPE_FORSPRF 6 - -#define set_layer_addr SPX_NAMESPACE(set_layer_addr) -void set_layer_addr(uint32_t addr[8], uint32_t layer); - -#define set_tree_addr SPX_NAMESPACE(set_tree_addr) -void set_tree_addr(uint32_t addr[8], uint64_t tree); - -#define set_type SPX_NAMESPACE(set_type) -void set_type(uint32_t addr[8], uint32_t type); - -/* Copies the layer and tree part of one address into the other */ -#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) -void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for WOTS and FORS addresses. */ - -#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) -void set_keypair_addr(uint32_t addr[8], uint32_t keypair); - -#define set_chain_addr SPX_NAMESPACE(set_chain_addr) -void set_chain_addr(uint32_t addr[8], uint32_t chain); - -#define set_hash_addr SPX_NAMESPACE(set_hash_addr) -void set_hash_addr(uint32_t addr[8], uint32_t hash); - -#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) -void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for all hash tree addresses (including FORS). */ - -#define set_tree_height SPX_NAMESPACE(set_tree_height) -void set_tree_height(uint32_t addr[8], uint32_t tree_height); - -#define set_tree_index SPX_NAMESPACE(set_tree_index) -void set_tree_index(uint32_t addr[8], uint32_t tree_index); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/api.h b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/api.h deleted file mode 100644 index 068ef4812e..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/api.h +++ /dev/null @@ -1,77 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA2256SROBUST_CLEAN_API_H -#define PQCLEAN_SPHINCSSHA2256SROBUST_CLEAN_API_H - -#include -#include - -#define PQCLEAN_SPHINCSSHA2256SROBUST_CLEAN_CRYPTO_ALGNAME "SPHINCS+-sha2-256s-robust" - -#define PQCLEAN_SPHINCSSHA2256SROBUST_CLEAN_CRYPTO_SECRETKEYBYTES 128 -#define PQCLEAN_SPHINCSSHA2256SROBUST_CLEAN_CRYPTO_PUBLICKEYBYTES 64 -#define PQCLEAN_SPHINCSSHA2256SROBUST_CLEAN_CRYPTO_BYTES 29792 - -#define PQCLEAN_SPHINCSSHA2256SROBUST_CLEAN_CRYPTO_SEEDBYTES 96 - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSSHA2256SROBUST_CLEAN_crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSSHA2256SROBUST_CLEAN_crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSSHA2256SROBUST_CLEAN_crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSSHA2256SROBUST_CLEAN_crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHA2256SROBUST_CLEAN_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHA2256SROBUST_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSSHA2256SROBUST_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSSHA2256SROBUST_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, - const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSSHA2256SROBUST_CLEAN_crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSSHA2256SROBUST_CLEAN_crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk); -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/context.h b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/context.h deleted file mode 100644 index 97e2e2469e..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/context.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef SPX_CONTEXT_H -#define SPX_CONTEXT_H - -#include -#include - -#include "params.h" -#include "sha2.h" - -typedef struct { - uint8_t pub_seed[SPX_N]; - uint8_t sk_seed[SPX_N]; - - // sha256 state that absorbed pub_seed - sha256ctx state_seeded; - - // sha512 state that absorbed pub_seed - sha512ctx state_seeded_512; - -} spx_ctx; - -#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) -void initialize_hash_function(spx_ctx *ctx); - -#define free_hash_function SPX_NAMESPACE(free_hash_function) -void free_hash_function(spx_ctx *ctx); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/context_sha2.c b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/context_sha2.c deleted file mode 100644 index 9ca9f4e7ac..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/context_sha2.c +++ /dev/null @@ -1,36 +0,0 @@ -#include "context.h" - -/** - * Absorb the constant pub_seed using one round of the compression function - * This initializes state_seeded and state_seeded_512, which can then be - * reused in thash - **/ -static void seed_state(spx_ctx *ctx) { - uint8_t block[SPX_SHA512_BLOCK_BYTES]; - size_t i; - - for (i = 0; i < SPX_N; ++i) { - block[i] = ctx->pub_seed[i]; - } - for (i = SPX_N; i < SPX_SHA512_BLOCK_BYTES; ++i) { - block[i] = 0; - } - /* block has been properly initialized for both SHA-256 and SHA-512 */ - - sha256_inc_init(&ctx->state_seeded); - sha256_inc_blocks(&ctx->state_seeded, block, 1); - sha512_inc_init(&ctx->state_seeded_512); - sha512_inc_blocks(&ctx->state_seeded_512, block, 1); -} - - -/* We initialize the state for the hash functions */ -void initialize_hash_function(spx_ctx *ctx) { - seed_state(ctx); -} - -/* Free the incremental hashing context for heap-based SHA2 APIs */ -void free_hash_function(spx_ctx *ctx) { - sha256_inc_ctx_release(&ctx->state_seeded); - sha512_inc_ctx_release(&ctx->state_seeded_512); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/fors.c b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/fors.c deleted file mode 100644 index 96ca72e986..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/fors.c +++ /dev/null @@ -1,156 +0,0 @@ -#include -#include -#include - -#include "fors.h" - -#include "address.h" -#include "hash.h" -#include "thash.h" -#include "utils.h" -#include "utilsx1.h" - -static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, - uint32_t fors_leaf_addr[8]) { - prf_addr(sk, ctx, fors_leaf_addr); -} - -static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, - const spx_ctx *ctx, - uint32_t fors_leaf_addr[8]) { - thash(leaf, sk, 1, ctx, fors_leaf_addr); -} - -struct fors_gen_leaf_info { - uint32_t leaf_addrx[8]; -}; - -static void fors_gen_leafx1(unsigned char *leaf, - const spx_ctx *ctx, - uint32_t addr_idx, void *info) { - struct fors_gen_leaf_info *fors_info = info; - uint32_t *fors_leaf_addr = fors_info->leaf_addrx; - - /* Only set the parts that the caller doesn't set */ - set_tree_index(fors_leaf_addr, addr_idx); - set_type(fors_leaf_addr, SPX_ADDR_TYPE_FORSPRF); - fors_gen_sk(leaf, ctx, fors_leaf_addr); - - set_type(fors_leaf_addr, SPX_ADDR_TYPE_FORSTREE); - fors_sk_to_leaf(leaf, leaf, - ctx, fors_leaf_addr); -} - -/** - * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - * Assumes indices has space for SPX_FORS_TREES integers. - */ -static void message_to_indices(uint32_t *indices, const unsigned char *m) { - unsigned int i, j; - unsigned int offset = 0; - - for (i = 0; i < SPX_FORS_TREES; i++) { - indices[i] = 0; - for (j = 0; j < SPX_FORS_HEIGHT; j++) { - indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); - offset++; - } - } -} - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -void fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]) { - uint32_t indices[SPX_FORS_TREES]; - unsigned char roots[SPX_FORS_TREES * SPX_N]; - uint32_t fors_tree_addr[8] = {0}; - struct fors_gen_leaf_info fors_info = {0}; - uint32_t *fors_leaf_addr = fors_info.leaf_addrx; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - copy_keypair_addr(fors_tree_addr, fors_addr); - copy_keypair_addr(fors_leaf_addr, fors_addr); - - copy_keypair_addr(fors_pk_addr, fors_addr); - set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < SPX_FORS_TREES; i++) { - idx_offset = i * (1 << SPX_FORS_HEIGHT); - - set_tree_height(fors_tree_addr, 0); - set_tree_index(fors_tree_addr, indices[i] + idx_offset); - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); - - /* Include the secret key part that produces the selected leaf node. */ - fors_gen_sk(sig, ctx, fors_tree_addr); - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); - sig += SPX_N; - - /* Compute the authentication path for this leaf node. */ - treehashx1(roots + i * SPX_N, sig, ctx, - indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx1, - fors_tree_addr, &fors_info); - - sig += SPX_N * SPX_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); -} - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -void fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]) { - uint32_t indices[SPX_FORS_TREES]; - unsigned char roots[SPX_FORS_TREES * SPX_N]; - unsigned char leaf[SPX_N]; - uint32_t fors_tree_addr[8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - copy_keypair_addr(fors_tree_addr, fors_addr); - copy_keypair_addr(fors_pk_addr, fors_addr); - - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); - set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < SPX_FORS_TREES; i++) { - idx_offset = i * (1 << SPX_FORS_HEIGHT); - - set_tree_height(fors_tree_addr, 0); - set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Derive the leaf from the included secret key part. */ - fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); - sig += SPX_N; - - /* Derive the corresponding root node of this tree. */ - compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, - sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); - sig += SPX_N * SPX_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/fors.h b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/fors.h deleted file mode 100644 index 509140a178..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/fors.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef SPX_FORS_H -#define SPX_FORS_H - -#include - -#include "context.h" -#include "params.h" - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -#define fors_sign SPX_NAMESPACE(fors_sign) -void fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]); - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) -void fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/hash.h b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/hash.h deleted file mode 100644 index ffe815f45d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/hash.h +++ /dev/null @@ -1,37 +0,0 @@ -#ifndef SPX_HASH_H -#define SPX_HASH_H - -#include -#include - -#include "context.h" -#include "params.h" - -#define prf_addr SPX_NAMESPACE(prf_addr) -void prf_addr(unsigned char *out, const spx_ctx *ctx, - const uint32_t addr[8]); - -#define gen_message_random SPX_NAMESPACE(gen_message_random) -void gen_message_random(unsigned char *R, const unsigned char *sk_prf, - const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx); - -#define hash_message SPX_NAMESPACE(hash_message) -void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx); - - -# define SPX_SHA256_ADDR_BYTES 22 - -# define mgf1_256 SPX_NAMESPACE(mgf1_256) -void mgf1_256(unsigned char *out, unsigned long outlen, - const unsigned char *in, unsigned long inlen); - -# define mgf1_512 SPX_NAMESPACE(mgf1_512) -void mgf1_512(unsigned char *out, unsigned long outlen, - const unsigned char *in, unsigned long inlen); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/hash_sha2.c b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/hash_sha2.c deleted file mode 100644 index 3d0085c8c1..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/hash_sha2.c +++ /dev/null @@ -1,219 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "sha2.h" -#include "utils.h" - - - -#define SPX_SHAX_OUTPUT_BYTES SPX_SHA512_OUTPUT_BYTES -#define SPX_SHAX_BLOCK_BYTES SPX_SHA512_BLOCK_BYTES -#define shaX_inc_init sha512_inc_init -#define shaX_inc_blocks sha512_inc_blocks -#define shaX_inc_finalize sha512_inc_finalize -#define shaX sha512 -#define mgf1_X mgf1_512 -#define shaXstate sha512ctx - -/** - * mgf1 function based on the SHA-256 hash function - * Note that inlen should be sufficiently small that it still allows for - * an array to be allocated on the stack. Typically 'in' is merely a seed. - * Outputs outlen number of bytes - */ -void mgf1_256(unsigned char *out, unsigned long outlen, - const unsigned char *in, unsigned long inlen) { - PQCLEAN_VLA(uint8_t, inbuf, inlen + 4); - unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES]; - uint32_t i; - - memcpy(inbuf, in, inlen); - - /* While we can fit in at least another full block of SHA256 output.. */ - for (i = 0; (i + 1)*SPX_SHA256_OUTPUT_BYTES <= outlen; i++) { - u32_to_bytes(inbuf + inlen, i); - sha256(out, inbuf, inlen + 4); - out += SPX_SHA256_OUTPUT_BYTES; - } - /* Until we cannot anymore, and we fill the remainder. */ - if (outlen > i * SPX_SHA256_OUTPUT_BYTES) { - u32_to_bytes(inbuf + inlen, i); - sha256(outbuf, inbuf, inlen + 4); - memcpy(out, outbuf, outlen - i * SPX_SHA256_OUTPUT_BYTES); - } -} - -/* - * mgf1 function based on the SHA-512 hash function - */ -void mgf1_512(unsigned char *out, unsigned long outlen, - const unsigned char *in, unsigned long inlen) { - PQCLEAN_VLA(uint8_t, inbuf, inlen + 4); - unsigned char outbuf[SPX_SHA512_OUTPUT_BYTES]; - uint32_t i; - - memcpy(inbuf, in, inlen); - - /* While we can fit in at least another full block of SHA512 output.. */ - for (i = 0; (i + 1)*SPX_SHA512_OUTPUT_BYTES <= outlen; i++) { - u32_to_bytes(inbuf + inlen, i); - sha512(out, inbuf, inlen + 4); - out += SPX_SHA512_OUTPUT_BYTES; - } - /* Until we cannot anymore, and we fill the remainder. */ - if (outlen > i * SPX_SHA512_OUTPUT_BYTES) { - u32_to_bytes(inbuf + inlen, i); - sha512(outbuf, inbuf, inlen + 4); - memcpy(out, outbuf, outlen - i * SPX_SHA512_OUTPUT_BYTES); - } -} - -/* - * Computes PRF(pk_seed, sk_seed, addr). - */ -void prf_addr(unsigned char *out, const spx_ctx *ctx, - const uint32_t addr[8]) { - sha256ctx sha2_state; - unsigned char buf[SPX_SHA256_ADDR_BYTES + SPX_N]; - unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES]; - - /* Retrieve precomputed state containing pub_seed */ - sha256_inc_ctx_clone(&sha2_state, &ctx->state_seeded); - - /* Remainder: ADDR^c ‖ SK.seed */ - memcpy(buf, addr, SPX_SHA256_ADDR_BYTES); - memcpy(buf + SPX_SHA256_ADDR_BYTES, ctx->sk_seed, SPX_N); - - sha256_inc_finalize(outbuf, &sha2_state, buf, SPX_SHA256_ADDR_BYTES + SPX_N); - - memcpy(out, outbuf, SPX_N); -} - -/** - * Computes the message-dependent randomness R, using a secret seed as a key - * for HMAC, and an optional randomization value prefixed to the message. - * This requires m to have at least SPX_SHAX_BLOCK_BYTES + SPX_N space - * available in front of the pointer, i.e. before the message to use for the - * prefix. This is necessary to prevent having to move the message around (and - * allocate memory for it). - */ -void gen_message_random(unsigned char *R, const unsigned char *sk_prf, - const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx) { - (void)ctx; - - unsigned char buf[SPX_SHAX_BLOCK_BYTES + SPX_SHAX_OUTPUT_BYTES]; - shaXstate state; - int i; - - - /* This implements HMAC-SHA */ - for (i = 0; i < SPX_N; i++) { - buf[i] = 0x36 ^ sk_prf[i]; - } - memset(buf + SPX_N, 0x36, SPX_SHAX_BLOCK_BYTES - SPX_N); - - shaX_inc_init(&state); - shaX_inc_blocks(&state, buf, 1); - - memcpy(buf, optrand, SPX_N); - - /* If optrand + message cannot fill up an entire block */ - if (SPX_N + mlen < SPX_SHAX_BLOCK_BYTES) { - memcpy(buf + SPX_N, m, mlen); - shaX_inc_finalize(buf + SPX_SHAX_BLOCK_BYTES, &state, - buf, mlen + SPX_N); - } - /* Otherwise first fill a block, so that finalize only uses the message */ - else { - memcpy(buf + SPX_N, m, SPX_SHAX_BLOCK_BYTES - SPX_N); - shaX_inc_blocks(&state, buf, 1); - - m += SPX_SHAX_BLOCK_BYTES - SPX_N; - mlen -= SPX_SHAX_BLOCK_BYTES - SPX_N; - shaX_inc_finalize(buf + SPX_SHAX_BLOCK_BYTES, &state, m, mlen); - } - - for (i = 0; i < SPX_N; i++) { - buf[i] = 0x5c ^ sk_prf[i]; - } - memset(buf + SPX_N, 0x5c, SPX_SHAX_BLOCK_BYTES - SPX_N); - - shaX(buf, buf, SPX_SHAX_BLOCK_BYTES + SPX_SHAX_OUTPUT_BYTES); - memcpy(R, buf, SPX_N); -} - -/** - * Computes the message hash using R, the public key, and the message. - * Outputs the message digest and the index of the leaf. The index is split in - * the tree index and the leaf index, for convenient copying to an address. - */ -void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx) { - (void)ctx; -#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) -#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) -#define SPX_LEAF_BITS SPX_TREE_HEIGHT -#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) -#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) - - unsigned char seed[2 * SPX_N + SPX_SHAX_OUTPUT_BYTES]; - - /* Round to nearest multiple of SPX_SHAX_BLOCK_BYTES */ -#define SPX_INBLOCKS (((SPX_N + SPX_PK_BYTES + SPX_SHAX_BLOCK_BYTES - 1) & \ - -SPX_SHAX_BLOCK_BYTES) / SPX_SHAX_BLOCK_BYTES) - unsigned char inbuf[SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES]; - - unsigned char buf[SPX_DGST_BYTES]; - unsigned char *bufp = buf; - shaXstate state; - - shaX_inc_init(&state); - - // seed: SHA-X(R ‖ PK.seed ‖ PK.root ‖ M) - memcpy(inbuf, R, SPX_N); - memcpy(inbuf + SPX_N, pk, SPX_PK_BYTES); - - /* If R + pk + message cannot fill up an entire block */ - if (SPX_N + SPX_PK_BYTES + mlen < SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES) { - memcpy(inbuf + SPX_N + SPX_PK_BYTES, m, mlen); - shaX_inc_finalize(seed + 2 * SPX_N, &state, inbuf, SPX_N + SPX_PK_BYTES + mlen); - } - /* Otherwise first fill a block, so that finalize only uses the message */ - else { - memcpy(inbuf + SPX_N + SPX_PK_BYTES, m, - SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES - SPX_N - SPX_PK_BYTES); - shaX_inc_blocks(&state, inbuf, SPX_INBLOCKS); - - m += SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES - SPX_N - SPX_PK_BYTES; - mlen -= SPX_INBLOCKS * SPX_SHAX_BLOCK_BYTES - SPX_N - SPX_PK_BYTES; - shaX_inc_finalize(seed + 2 * SPX_N, &state, m, (size_t)mlen); - } - - // H_msg: MGF1-SHA-X(R ‖ PK.seed ‖ seed) - memcpy(seed, R, SPX_N); - memcpy(seed + SPX_N, pk, SPX_N); - - /* By doing this in two steps, we prevent hashing the message twice; - otherwise each iteration in MGF1 would hash the message again. */ - mgf1_X(bufp, SPX_DGST_BYTES, seed, 2 * SPX_N + SPX_SHAX_OUTPUT_BYTES); - - memcpy(digest, bufp, SPX_FORS_MSG_BYTES); - bufp += SPX_FORS_MSG_BYTES; - - - *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); - *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); - bufp += SPX_TREE_BYTES; - - *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); - *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); -} - - diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/merkle.c b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/merkle.c deleted file mode 100644 index 0c1479fd93..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/merkle.c +++ /dev/null @@ -1,59 +0,0 @@ -#include -#include - -#include "address.h" -#include "merkle.h" -#include "params.h" -#include "utils.h" -#include "utilsx1.h" -#include "wots.h" -#include "wotsx1.h" - -/* - * This generates a Merkle signature (WOTS signature followed by the Merkle - * authentication path). This is in this file because most of the complexity - * is involved with the WOTS signature; the Merkle authentication path logic - * is mostly hidden in treehashx4 - */ -void merkle_sign(uint8_t *sig, unsigned char *root, - const spx_ctx *ctx, - uint32_t wots_addr[8], uint32_t tree_addr[8], - uint32_t idx_leaf) { - unsigned char *auth_path = sig + SPX_WOTS_BYTES; - struct leaf_info_x1 info = { 0 }; - unsigned steps[ SPX_WOTS_LEN ]; - - info.wots_sig = sig; - chain_lengths(steps, root); - info.wots_steps = steps; - - set_type(&tree_addr[0], SPX_ADDR_TYPE_HASHTREE); - set_type(&info.pk_addr[0], SPX_ADDR_TYPE_WOTSPK); - copy_subtree_addr(&info.leaf_addr[0], wots_addr); - copy_subtree_addr(&info.pk_addr[0], wots_addr); - - info.wots_sign_leaf = idx_leaf; - - treehashx1(root, auth_path, ctx, - idx_leaf, 0, - SPX_TREE_HEIGHT, - wots_gen_leafx1, - tree_addr, &info); -} - -/* Compute root node of the top-most subtree. */ -void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { - /* We do not need the auth path in key generation, but it simplifies the - code to have just one treehash routine that computes both root and path - in one function. */ - unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; - uint32_t top_tree_addr[8] = {0}; - uint32_t wots_addr[8] = {0}; - - set_layer_addr(top_tree_addr, SPX_D - 1); - set_layer_addr(wots_addr, SPX_D - 1); - - merkle_sign(auth_path, root, ctx, - wots_addr, top_tree_addr, - (uint32_t)~0 /* ~0 means "don't bother generating an auth path */ ); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/merkle.h b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/merkle.h deleted file mode 100644 index 769cf2e970..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/merkle.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef MERKLE_H_ -#define MERKLE_H_ - -#include - -#include "context.h" -#include "params.h" - -/* Generate a Merkle signature (WOTS signature followed by the Merkle */ -/* authentication path) */ -#define merkle_sign SPX_NAMESPACE(merkle_sign) -void merkle_sign(uint8_t *sig, unsigned char *root, - const spx_ctx *ctx, - uint32_t wots_addr[8], uint32_t tree_addr[8], - uint32_t idx_leaf); - -/* Compute the root node of the top-most subtree. */ -#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) -void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); - -#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/nistapi.h b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/nistapi.h deleted file mode 100644 index 3cb71afad4..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/nistapi.h +++ /dev/null @@ -1,87 +0,0 @@ -#ifndef SPX_API_H -#define SPX_API_H - -#include -#include - -#include "params.h" - -#define CRYPTO_ALGNAME "SPHINCS+" - -#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES -#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES -#define CRYPTO_BYTES SPX_BYTES -#define CRYPTO_SEEDBYTES (3*SPX_N) - -/* - * Returns the length of a secret key, in bytes - */ -#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) -size_t crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) -size_t crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) -size_t crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) -size_t crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) -int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) -int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) -int crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) -int crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -#define crypto_sign SPX_NAMESPACE(crypto_sign) -int crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) -int crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/params.h b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/params.h deleted file mode 100644 index 0ded8edbc4..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/params.h +++ /dev/null @@ -1,61 +0,0 @@ -#ifndef SPX_PARAMS_H -#define SPX_PARAMS_H - -#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSSHA2256SROBUST_CLEAN_##s - -/* Hash output length in bytes. */ -#define SPX_N 32 -/* Height of the hypertree. */ -#define SPX_FULL_HEIGHT 64 -/* Number of subtree layer. */ -#define SPX_D 8 -/* FORS tree dimensions. */ -#define SPX_FORS_HEIGHT 14 -#define SPX_FORS_TREES 22 -/* Winternitz parameter, */ -#define SPX_WOTS_W 16 - -/* The hash function is defined by linking a different hash.c file, as opposed - to setting a #define constant. */ - -/* This is a SHA2-based parameter set, hence whether we use SHA-256 - * exclusively or we use both SHA-256 and SHA-512 is controlled by - * the following #define */ -#define SPX_SHA512 1 /* Use SHA-512 for H and T_l, l >= 2 */ - -/* For clarity */ -#define SPX_ADDR_BYTES 32 - -/* WOTS parameters. */ -#define SPX_WOTS_LOGW 4 - -#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) - -/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#define SPX_WOTS_LEN2 3 - -#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) -#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) -#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES - -/* Subtree size. */ -#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) - -//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT -// #error SPX_D should always divide SPX_FULL_HEIGHT -//#endif - -/* FORS parameters. */ -#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) -#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) -#define SPX_FORS_PK_BYTES SPX_N - -/* Resulting SPX sizes. */ -#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ - SPX_FULL_HEIGHT * SPX_N) -#define SPX_PK_BYTES (2 * SPX_N) -#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) - -#include "sha2_offsets.h" - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/sha2_offsets.h b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/sha2_offsets.h deleted file mode 100644 index 6e3584f7a4..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/sha2_offsets.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef SHA2_OFFSETS_H_ -#define SHA2_OFFSETS_H_ - -#define SPX_SHA256_BLOCK_BYTES 64 -#define SPX_SHA256_OUTPUT_BYTES 32 - -#define SPX_SHA512_BLOCK_BYTES 128 -#define SPX_SHA512_OUTPUT_BYTES 64 - -/* - * Offsets of various fields in the address structure when we use SHA2 as - * the Sphincs+ hash function - */ - -#define SPX_OFFSET_LAYER 0 /* The byte used to specify the Merkle tree layer */ -#define SPX_OFFSET_TREE 1 /* The start of the 8 byte field used to specify the tree */ -#define SPX_OFFSET_TYPE 9 /* The byte used to specify the hash type (reason) */ -#define SPX_OFFSET_KP_ADDR2 12 /* The high byte used to specify the key pair (which one-time signature) */ -#define SPX_OFFSET_KP_ADDR1 13 /* The low byte used to specify the key pair */ -#define SPX_OFFSET_CHAIN_ADDR 17 /* The byte used to specify the chain address (which Winternitz chain) */ -#define SPX_OFFSET_HASH_ADDR 21 /* The byte used to specify the hash address (where in the Winternitz chain) */ -#define SPX_OFFSET_TREE_HGT 17 /* The byte used to specify the height of this node in the FORS or Merkle tree */ -#define SPX_OFFSET_TREE_INDEX 18 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ - -#define SPX_SHA2 1 - -#endif /* SHA2_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/sign.c b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/sign.c deleted file mode 100644 index 9d0c7d1b22..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/sign.c +++ /dev/null @@ -1,286 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "context.h" -#include "fors.h" -#include "hash.h" -#include "merkle.h" -#include "nistapi.h" -#include "params.h" -#include "randombytes.h" -#include "thash.h" -#include "utils.h" -#include "wots.h" - -/* - * Returns the length of a secret key, in bytes - */ -size_t crypto_sign_secretkeybytes(void) { - return CRYPTO_SECRETKEYBYTES; -} - -/* - * Returns the length of a public key, in bytes - */ -size_t crypto_sign_publickeybytes(void) { - return CRYPTO_PUBLICKEYBYTES; -} - -/* - * Returns the length of a signature, in bytes - */ -size_t crypto_sign_bytes(void) { - return CRYPTO_BYTES; -} - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t crypto_sign_seedbytes(void) { - return CRYPTO_SEEDBYTES; -} - -/* - * Generates an SPX key pair given a seed of length - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed) { - spx_ctx ctx; - - /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ - memcpy(sk, seed, CRYPTO_SEEDBYTES); - - memcpy(pk, sk + 2 * SPX_N, SPX_N); - - memcpy(ctx.pub_seed, pk, SPX_N); - memcpy(ctx.sk_seed, sk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - /* Compute root node of the top-most subtree. */ - merkle_gen_root(sk + 3 * SPX_N, &ctx); - - // cleanup - free_hash_function(&ctx); - - memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); - - return 0; -} - -/* - * Generates an SPX key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { - uint8_t seed[CRYPTO_SEEDBYTES]; - randombytes(seed, CRYPTO_SEEDBYTES); - crypto_sign_seed_keypair(pk, sk, seed); - - return 0; -} - -/** - * Returns an array containing a detached signature. - */ -int crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - spx_ctx ctx; - - const uint8_t *sk_prf = sk + SPX_N; - const uint8_t *pk = sk + 2 * SPX_N; - - uint8_t optrand[SPX_N]; - uint8_t mhash[SPX_FORS_MSG_BYTES]; - uint8_t root[SPX_N]; - uint32_t i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - - memcpy(ctx.sk_seed, sk, SPX_N); - memcpy(ctx.pub_seed, pk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - set_type(wots_addr, SPX_ADDR_TYPE_WOTS); - set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); - - /* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ - randombytes(optrand, SPX_N); - /* Compute the digest randomization value. */ - gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); - - /* Derive the message digest and leaf index from R, PK and M. */ - hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); - sig += SPX_N; - - set_tree_addr(wots_addr, tree); - set_keypair_addr(wots_addr, idx_leaf); - - /* Sign the message hash using FORS. */ - fors_sign(sig, root, mhash, &ctx, wots_addr); - sig += SPX_FORS_BYTES; - - for (i = 0; i < SPX_D; i++) { - set_layer_addr(tree_addr, i); - set_tree_addr(tree_addr, tree); - - copy_subtree_addr(wots_addr, tree_addr); - set_keypair_addr(wots_addr, idx_leaf); - - merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); - sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); - tree = tree >> SPX_TREE_HEIGHT; - } - - free_hash_function(&ctx); - - *siglen = SPX_BYTES; - - return 0; -} - -/** - * Verifies a detached signature and message under a given public key. - */ -int crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk) { - spx_ctx ctx; - const uint8_t *pub_root = pk + SPX_N; - uint8_t mhash[SPX_FORS_MSG_BYTES]; - uint8_t wots_pk[SPX_WOTS_BYTES]; - uint8_t root[SPX_N]; - uint8_t leaf[SPX_N]; - unsigned int i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - if (siglen != SPX_BYTES) { - return -1; - } - - memcpy(ctx.pub_seed, pk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - set_type(wots_addr, SPX_ADDR_TYPE_WOTS); - set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); - set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); - - /* Derive the message digest and leaf index from R || PK || M. */ - /* The additional SPX_N is a result of the hash domain separator. */ - hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); - sig += SPX_N; - - /* Layer correctly defaults to 0, so no need to set_layer_addr */ - set_tree_addr(wots_addr, tree); - set_keypair_addr(wots_addr, idx_leaf); - - fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); - sig += SPX_FORS_BYTES; - - /* For each subtree.. */ - for (i = 0; i < SPX_D; i++) { - set_layer_addr(tree_addr, i); - set_tree_addr(tree_addr, tree); - - copy_subtree_addr(wots_addr, tree_addr); - set_keypair_addr(wots_addr, idx_leaf); - - copy_keypair_addr(wots_pk_addr, wots_addr); - - /* The WOTS public key is only correct if the signature was correct. */ - /* Initially, root is the FORS pk, but on subsequent iterations it is - the root of the subtree below the currently processed subtree. */ - wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); - sig += SPX_WOTS_BYTES; - - /* Compute the leaf node using the WOTS public key. */ - thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); - - /* Compute the root node of this subtree. */ - compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, - &ctx, tree_addr); - sig += SPX_TREE_HEIGHT * SPX_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); - tree = tree >> SPX_TREE_HEIGHT; - } - - // cleanup - free_hash_function(&ctx); - - /* Check if the root node equals the root node in the public key. */ - if (memcmp(root, pub_root, SPX_N) != 0) { - return -1; - } - - return 0; -} - - -/** - * Returns an array containing the signature followed by the message. - */ -int crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk) { - size_t siglen; - - crypto_sign_signature(sm, &siglen, m, mlen, sk); - - memmove(sm + SPX_BYTES, m, mlen); - *smlen = siglen + mlen; - - return 0; -} - -/** - * Verifies a given signature-message pair under a given public key. - */ -int crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk) { - /* The API caller does not necessarily know what size a signature should be - but SPHINCS+ signatures are always exactly SPX_BYTES. */ - if (smlen < SPX_BYTES) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - *mlen = smlen - SPX_BYTES; - - if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - /* If verification was successful, move the message to the right place. */ - memmove(m, sm + SPX_BYTES, *mlen); - - return 0; -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/thash.h b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/thash.h deleted file mode 100644 index 8687ccfb4d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/thash.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef SPX_THASH_H -#define SPX_THASH_H - -#include "context.h" -#include "params.h" - -#include - -#define thash SPX_NAMESPACE(thash) -void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/thash_sha2_robust.c b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/thash_sha2_robust.c deleted file mode 100644 index 3ab891175f..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/thash_sha2_robust.c +++ /dev/null @@ -1,68 +0,0 @@ -#include -#include - -#include "address.h" -#include "context.h" -#include "hash.h" -#include "params.h" -#include "sha2.h" -#include "thash.h" -#include "utils.h" - -static void thash_512(unsigned char *out, const unsigned char *in, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]); - -/** - * Takes an array of inblocks concatenated arrays of SPX_N bytes. - */ -void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]) { - if (inblocks > 1) { - thash_512(out, in, inblocks, ctx, addr); - return; - } - unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES]; - PQCLEAN_VLA(uint8_t, bitmask, inblocks * SPX_N); - PQCLEAN_VLA(uint8_t, buf, SPX_N + SPX_SHA256_OUTPUT_BYTES + inblocks * SPX_N); - sha256ctx sha2_state; - unsigned int i; - - memcpy(buf, ctx->pub_seed, SPX_N); - memcpy(buf + SPX_N, addr, SPX_SHA256_ADDR_BYTES); - mgf1_256(bitmask, inblocks * SPX_N, buf, SPX_N + SPX_SHA256_ADDR_BYTES); - - /* Retrieve precomputed state containing pub_seed */ - sha256_inc_ctx_clone(&sha2_state, &ctx->state_seeded); - - for (i = 0; i < inblocks * SPX_N; i++) { - buf[SPX_N + SPX_SHA256_ADDR_BYTES + i] = in[i] ^ bitmask[i]; - } - - sha256_inc_finalize(outbuf, &sha2_state, buf + SPX_N, - SPX_SHA256_ADDR_BYTES + inblocks * SPX_N); - memcpy(out, outbuf, SPX_N); -} - -static void thash_512(unsigned char *out, const unsigned char *in, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]) { - unsigned char outbuf[SPX_SHA512_OUTPUT_BYTES]; - PQCLEAN_VLA(uint8_t, bitmask, inblocks * SPX_N); - PQCLEAN_VLA(uint8_t, buf, SPX_N + SPX_SHA256_ADDR_BYTES + inblocks * SPX_N); - sha512ctx sha2_state; - unsigned int i; - - memcpy(buf, ctx->pub_seed, SPX_N); - memcpy(buf + SPX_N, addr, SPX_SHA256_ADDR_BYTES); - mgf1_512(bitmask, inblocks * SPX_N, buf, SPX_N + SPX_SHA256_ADDR_BYTES); - - /* Retrieve precomputed state containing pub_seed */ - sha512_inc_ctx_clone(&sha2_state, &ctx->state_seeded_512); - - for (i = 0; i < inblocks * SPX_N; i++) { - buf[SPX_N + SPX_SHA256_ADDR_BYTES + i] = in[i] ^ bitmask[i]; - } - - sha512_inc_finalize(outbuf, &sha2_state, buf + SPX_N, - SPX_SHA256_ADDR_BYTES + inblocks * SPX_N); - memcpy(out, outbuf, SPX_N); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/utils.c b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/utils.c deleted file mode 100644 index 177b541fb9..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/utils.c +++ /dev/null @@ -1,148 +0,0 @@ -#include - -#include "utils.h" - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "thash.h" - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void ull_to_bytes(unsigned char *out, unsigned int outlen, - unsigned long long in) { - int i; - - /* Iterate over out in decreasing order, for big-endianness. */ - for (i = (signed int)outlen - 1; i >= 0; i--) { - out[i] = in & 0xff; - in = in >> 8; - } -} - -void u32_to_bytes(unsigned char *out, uint32_t in) { - out[0] = (unsigned char)(in >> 24); - out[1] = (unsigned char)(in >> 16); - out[2] = (unsigned char)(in >> 8); - out[3] = (unsigned char)in; -} - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { - unsigned long long retval = 0; - unsigned int i; - - for (i = 0; i < inlen; i++) { - retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); - } - return retval; -} - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void compute_root(unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const spx_ctx *ctx, uint32_t addr[8]) { - uint32_t i; - unsigned char buffer[2 * SPX_N]; - - /* If leaf_idx is odd (last bit = 1), current path element is a right child - and auth_path has to go left. Otherwise it is the other way around. */ - if (leaf_idx & 1) { - memcpy(buffer + SPX_N, leaf, SPX_N); - memcpy(buffer, auth_path, SPX_N); - } else { - memcpy(buffer, leaf, SPX_N); - memcpy(buffer + SPX_N, auth_path, SPX_N); - } - auth_path += SPX_N; - - for (i = 0; i < tree_height - 1; i++) { - leaf_idx >>= 1; - idx_offset >>= 1; - /* Set the address of the node we're creating. */ - set_tree_height(addr, i + 1); - set_tree_index(addr, leaf_idx + idx_offset); - - /* Pick the right or left neighbor, depending on parity of the node. */ - if (leaf_idx & 1) { - thash(buffer + SPX_N, buffer, 2, ctx, addr); - memcpy(buffer, auth_path, SPX_N); - } else { - thash(buffer, buffer, 2, ctx, addr); - memcpy(buffer + SPX_N, auth_path, SPX_N); - } - auth_path += SPX_N; - } - - /* The last iteration is exceptional; we do not copy an auth_path node. */ - leaf_idx >>= 1; - idx_offset >>= 1; - set_tree_height(addr, tree_height); - set_tree_index(addr, leaf_idx + idx_offset); - thash(root, buffer, 2, ctx, addr); -} - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const spx_ctx * /* ctx */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), - uint32_t tree_addr[8]) { - PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); - PQCLEAN_VLA(unsigned int, heights, tree_height + 1); - unsigned int offset = 0; - uint32_t idx; - uint32_t tree_idx; - - for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { - /* Add the next leaf node to the stack. */ - gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); - offset++; - heights[offset - 1] = 0; - - /* If this is a node we need for the auth path.. */ - if ((leaf_idx ^ 0x1) == idx) { - memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); - } - - /* While the top-most nodes are of equal height.. */ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { - /* Compute index of the new node, in the next layer. */ - tree_idx = (idx >> (heights[offset - 1] + 1)); - - /* Set the address of the node we're creating. */ - set_tree_height(tree_addr, heights[offset - 1] + 1); - set_tree_index(tree_addr, - tree_idx + (idx_offset >> (heights[offset - 1] + 1))); - /* Hash the top-most nodes from the stack together. */ - thash(stack + (offset - 2)*SPX_N, - stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); - offset--; - /* Note that the top-most node is now one layer higher. */ - heights[offset - 1]++; - - /* If this is a node we need for the auth path.. */ - if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_path + heights[offset - 1]*SPX_N, - stack + (offset - 1)*SPX_N, SPX_N); - } - } - } - memcpy(root, stack, SPX_N); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/utils.h b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/utils.h deleted file mode 100644 index 64f5d5a53a..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/utils.h +++ /dev/null @@ -1,58 +0,0 @@ -#ifndef SPX_UTILS_H -#define SPX_UTILS_H - -#include - -#include "compat.h" -#include "context.h" -#include "params.h" - - -/* To support MSVC use alloca() instead of VLAs. See #20. */ - - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) -void ull_to_bytes(unsigned char *out, unsigned int outlen, - unsigned long long in); -#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) -void u32_to_bytes(unsigned char *out, uint32_t in); - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) -unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -#define compute_root SPX_NAMESPACE(compute_root) -void compute_root(unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const spx_ctx *ctx, uint32_t addr[8]); - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -#define treehash SPX_NAMESPACE(treehash) -void treehash(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const spx_ctx *ctx /* ctx */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), - uint32_t tree_addr[8]); - - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/utilsx1.c b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/utilsx1.c deleted file mode 100644 index fccb69b35d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/utilsx1.c +++ /dev/null @@ -1,100 +0,0 @@ -#include - -#include "utilsx1.h" - -#include "address.h" -#include "params.h" -#include "thash.h" -#include "utils.h" - -/* - * Generate the entire Merkle tree, computing the authentication path for - * leaf_idx, and the resulting root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) - * - * This expects tree_addr to be initialized to the addr structures for the - * Merkle tree nodes - * - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - * - * This works by using the standard Merkle tree building algorithm, - */ -void treehashx1(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, - uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* Where to write the leaves */, - const spx_ctx * /* ctx */, - uint32_t idx, void *info), - uint32_t tree_addr[8], - void *info) { - /* This is where we keep the intermediate nodes */ - PQCLEAN_VLA(uint8_t, stack, tree_height * SPX_N); - - uint32_t idx; - uint32_t max_idx = (uint32_t)((1 << tree_height) - 1); - for (idx = 0;; idx++) { - unsigned char current[2 * SPX_N]; /* Current logical node is at */ - /* index[SPX_N]. We do this to minimize the number of copies */ - /* needed during a thash */ - gen_leaf( ¤t[SPX_N], ctx, idx + idx_offset, - info ); - - /* Now combine the freshly generated right node with previously */ - /* generated left ones */ - uint32_t internal_idx_offset = idx_offset; - uint32_t internal_idx = idx; - uint32_t internal_leaf = leaf_idx; - uint32_t h; /* The height we are in the Merkle tree */ - for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { - - /* Check if we hit the top of the tree */ - if (h == tree_height) { - /* We hit the root; return it */ - memcpy( root, ¤t[SPX_N], SPX_N ); - return; - } - - /* - * Check if the node we have is a part of the - * authentication path; if it is, write it out - */ - if ((internal_idx ^ internal_leaf) == 0x01) { - memcpy( &auth_path[ h * SPX_N ], - ¤t[SPX_N], - SPX_N ); - } - - /* - * Check if we're at a left child; if so, stop going up the stack - * Exception: if we've reached the end of the tree, keep on going - * (so we combine the last 4 nodes into the one root node in two - * more iterations) - */ - if ((internal_idx & 1) == 0 && idx < max_idx) { - break; - } - - /* Ok, we're at a right node */ - /* Now combine the left and right logical nodes together */ - - /* Set the address of the node we're creating. */ - internal_idx_offset >>= 1; - set_tree_height(tree_addr, h + 1); - set_tree_index(tree_addr, internal_idx / 2 + internal_idx_offset ); - - unsigned char *left = &stack[h * SPX_N]; - memcpy( ¤t[0], left, SPX_N ); - thash( ¤t[1 * SPX_N], - ¤t[0 * SPX_N], - 2, ctx, tree_addr); - } - - /* We've hit a left child; save the current for when we get the */ - /* corresponding right right */ - memcpy( &stack[h * SPX_N], ¤t[SPX_N], SPX_N); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/utilsx1.h b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/utilsx1.h deleted file mode 100644 index e911d17d53..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/utilsx1.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef SPX_UTILSX4_H -#define SPX_UTILSX4_H - -#include - -#include "context.h" -#include "params.h" - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -#define treehashx1 SPX_NAMESPACE(treehashx1) -void treehashx1(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* Where to write the leaf */, - const spx_ctx * /* ctx */, - uint32_t addr_idx, void *info), - uint32_t tree_addrx4[8], void *info); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/wots.c b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/wots.c deleted file mode 100644 index 249717aaa8..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/wots.c +++ /dev/null @@ -1,108 +0,0 @@ -#include -#include - -#include "wots.h" -#include "wotsx1.h" - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "thash.h" -#include "utils.h" -#include "utilsx1.h" - -// TODO clarify address expectations, and make them more uniform. -// TODO i.e. do we expect types to be set already? -// TODO and do we expect modifications or copies? - -/** - * Computes the chaining function. - * out and in have to be n-byte arrays. - * - * Interprets in as start-th value of the chain. - * addr has to contain the address of the chain. - */ -static void gen_chain(unsigned char *out, const unsigned char *in, - unsigned int start, unsigned int steps, - const spx_ctx *ctx, uint32_t addr[8]) { - uint32_t i; - - /* Initialize out with the value at position 'start'. */ - memcpy(out, in, SPX_N); - - /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < SPX_WOTS_W; i++) { - set_hash_addr(addr, i); - thash(out, out, 1, ctx, addr); - } -} - -/** - * base_w algorithm as described in draft. - * Interprets an array of bytes as integers in base w. - * This only works when log_w is a divisor of 8. - */ -static void base_w(unsigned int *output, const int out_len, - const unsigned char *input) { - int in = 0; - int out = 0; - unsigned char total = 0; - int bits = 0; - int consumed; - - for (consumed = 0; consumed < out_len; consumed++) { - if (bits == 0) { - total = input[in]; - in++; - bits += 8; - } - bits -= SPX_WOTS_LOGW; - output[out] = (total >> bits) & (SPX_WOTS_W - 1); - out++; - } -} - -/* Computes the WOTS+ checksum over a message (in base_w). */ -static void wots_checksum(unsigned int *csum_base_w, - const unsigned int *msg_base_w) { - unsigned int csum = 0; - unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; - unsigned int i; - - /* Compute checksum. */ - for (i = 0; i < SPX_WOTS_LEN1; i++) { - csum += SPX_WOTS_W - 1 - msg_base_w[i]; - } - - /* Convert checksum to base_w. */ - /* Make sure expected empty zero bits are the least significant bits. */ - csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); - ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); - base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); -} - -/* Takes a message and derives the matching chain lengths. */ -void chain_lengths(unsigned int *lengths, const unsigned char *msg) { - base_w(lengths, SPX_WOTS_LEN1, msg); - wots_checksum(lengths + SPX_WOTS_LEN1, lengths); -} - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const spx_ctx *ctx, uint32_t addr[8]) { - unsigned int lengths[SPX_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < SPX_WOTS_LEN; i++) { - set_chain_addr(addr, i); - gen_chain(pk + i * SPX_N, sig + i * SPX_N, - lengths[i], SPX_WOTS_W - 1 - lengths[i], ctx, addr); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/wots.h b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/wots.h deleted file mode 100644 index 4e7692eeef..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/wots.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef SPX_WOTS_H -#define SPX_WOTS_H - -#include - -#include "context.h" -#include "params.h" - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) -void wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const spx_ctx *ctx, uint32_t addr[8]); - -/* - * Compute the chain lengths needed for a given message hash - */ -#define chain_lengths SPX_NAMESPACE(chain_lengths) -void chain_lengths(unsigned int *lengths, const unsigned char *msg); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/wotsx1.c b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/wotsx1.c deleted file mode 100644 index 3adec78dfb..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/wotsx1.c +++ /dev/null @@ -1,76 +0,0 @@ -#include -#include - -#include "wots.h" -#include "wotsx1.h" - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "thash.h" -#include "utils.h" - -/* - * This generates a WOTS public key - * It also generates the WOTS signature if leaf_info indicates - * that we're signing with this WOTS key - */ -void wots_gen_leafx1(unsigned char *dest, - const spx_ctx *ctx, - uint32_t leaf_idx, void *v_info) { - struct leaf_info_x1 *info = v_info; - uint32_t *leaf_addr = info->leaf_addr; - uint32_t *pk_addr = info->pk_addr; - unsigned int i, k; - unsigned char pk_buffer[ SPX_WOTS_BYTES ]; - unsigned char *buffer; - uint32_t wots_k_mask; - - if (leaf_idx == info->wots_sign_leaf) { - /* We're traversing the leaf that's signing; generate the WOTS */ - /* signature */ - wots_k_mask = 0; - } else { - /* Nope, we're just generating pk's; turn off the signature logic */ - wots_k_mask = (uint32_t)~0; - } - - set_keypair_addr( leaf_addr, leaf_idx ); - set_keypair_addr( pk_addr, leaf_idx ); - - for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { - uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k to */ - /* the step if we're generating a signature, ~0 if we're not */ - - /* Start with the secret seed */ - set_chain_addr(leaf_addr, i); - set_hash_addr(leaf_addr, 0); - set_type(leaf_addr, SPX_ADDR_TYPE_WOTSPRF); - - prf_addr(buffer, ctx, leaf_addr); - - set_type(leaf_addr, SPX_ADDR_TYPE_WOTS); - - /* Iterate down the WOTS chain */ - for (k = 0;; k++) { - /* Check if this is the value that needs to be saved as a */ - /* part of the WOTS signature */ - if (k == wots_k) { - memcpy( info->wots_sig + i * SPX_N, buffer, SPX_N ); - } - - /* Check if we hit the top of the chain */ - if (k == SPX_WOTS_W - 1) { - break; - } - - /* Iterate one step on the chain */ - set_hash_addr(leaf_addr, k); - - thash(buffer, buffer, 1, ctx, leaf_addr); - } - } - - /* Do the final thash to generate the public keys */ - thash(dest, pk_buffer, SPX_WOTS_LEN, ctx, pk_addr); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/wotsx1.h b/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/wotsx1.h deleted file mode 100644 index e617929f96..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha2-256s-robust_clean/wotsx1.h +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef WOTSX1_H_ -#define WOTSX1_H_ - -#include - -#include "context.h" -#include "params.h" - -/* - * This is here to provide an interface to the internal wots_gen_leafx1 - * routine. While this routine is not referenced in the package outside of - * wots.c, it is called from the stand-alone benchmark code to characterize - * the performance - */ -struct leaf_info_x1 { - unsigned char *wots_sig; - uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ - uint32_t *wots_steps; - uint32_t leaf_addr[8]; - uint32_t pk_addr[8]; -}; - -/* Macro to set the leaf_info to something 'benign', that is, it would */ -/* run with the same time as it does during the real signing process */ -/* Used only by the benchmark code */ -#define INITIALIZE_LEAF_INFO_X1(info, addr, step_buffer) { \ - (info).wots_sig = 0; \ - (info).wots_sign_leaf = ~0; \ - (info).wots_steps = step_buffer; \ - memcpy( &(info).leaf_addr[0], (addr), 32 ); \ - memcpy( &(info).pk_addr[0], (addr), 32 ); \ - } - -#define wots_gen_leafx1 SPX_NAMESPACE(wots_gen_leafx1) -void wots_gen_leafx1(unsigned char *dest, - const spx_ctx *ctx, - uint32_t leaf_idx, void *v_info); - -#endif /* WOTSX1_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_avx2/LICENSE b/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_avx2/LICENSE deleted file mode 100644 index 670154e353..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_avx2/LICENSE +++ /dev/null @@ -1,116 +0,0 @@ -CC0 1.0 Universal - -Statement of Purpose - -The laws of most jurisdictions throughout the world automatically confer -exclusive Copyright and Related Rights (defined below) upon the creator and -subsequent owner(s) (each and all, an "owner") of an original work of -authorship and/or a database (each, a "Work"). - -Certain owners wish to permanently relinquish those rights to a Work for the -purpose of contributing to a commons of creative, cultural and scientific -works ("Commons") that the public can reliably and without fear of later -claims of infringement build upon, modify, incorporate in other works, reuse -and redistribute as freely as possible in any form whatsoever and for any -purposes, including without limitation commercial purposes. These owners may -contribute to the Commons to promote the ideal of a free culture and the -further production of creative, cultural and scientific works, or to gain -reputation or greater distribution for their Work in part through the use and -efforts of others. - -For these and/or other purposes and motivations, and without any expectation -of additional consideration or compensation, the person associating CC0 with a -Work (the "Affirmer"), to the extent that he or she is an owner of Copyright -and Related Rights in the Work, voluntarily elects to apply CC0 to the Work -and publicly distribute the Work under its terms, with knowledge of his or her -Copyright and Related Rights in the Work and the meaning and intended legal -effect of CC0 on those rights. - -1. Copyright and Related Rights. A Work made available under CC0 may be -protected by copyright and related or neighboring rights ("Copyright and -Related Rights"). Copyright and Related Rights include, but are not limited -to, the following: - - i. the right to reproduce, adapt, distribute, perform, display, communicate, - and translate a Work; - - ii. moral rights retained by the original author(s) and/or performer(s); - - iii. publicity and privacy rights pertaining to a person's image or likeness - depicted in a Work; - - iv. rights protecting against unfair competition in regards to a Work, - subject to the limitations in paragraph 4(a), below; - - v. rights protecting the extraction, dissemination, use and reuse of data in - a Work; - - vi. database rights (such as those arising under Directive 96/9/EC of the - European Parliament and of the Council of 11 March 1996 on the legal - protection of databases, and under any national implementation thereof, - including any amended or successor version of such directive); and - - vii. other similar, equivalent or corresponding rights throughout the world - based on applicable law or treaty, and any national implementations thereof. - -2. Waiver. To the greatest extent permitted by, but not in contravention of, -applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and -unconditionally waives, abandons, and surrenders all of Affirmer's Copyright -and Related Rights and associated claims and causes of action, whether now -known or unknown (including existing as well as future claims and causes of -action), in the Work (i) in all territories worldwide, (ii) for the maximum -duration provided by applicable law or treaty (including future time -extensions), (iii) in any current or future medium and for any number of -copies, and (iv) for any purpose whatsoever, including without limitation -commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes -the Waiver for the benefit of each member of the public at large and to the -detriment of Affirmer's heirs and successors, fully intending that such Waiver -shall not be subject to revocation, rescission, cancellation, termination, or -any other legal or equitable action to disrupt the quiet enjoyment of the Work -by the public as contemplated by Affirmer's express Statement of Purpose. - -3. Public License Fallback. Should any part of the Waiver for any reason be -judged legally invalid or ineffective under applicable law, then the Waiver -shall be preserved to the maximum extent permitted taking into account -Affirmer's express Statement of Purpose. In addition, to the extent the Waiver -is so judged Affirmer hereby grants to each affected person a royalty-free, -non transferable, non sublicensable, non exclusive, irrevocable and -unconditional license to exercise Affirmer's Copyright and Related Rights in -the Work (i) in all territories worldwide, (ii) for the maximum duration -provided by applicable law or treaty (including future time extensions), (iii) -in any current or future medium and for any number of copies, and (iv) for any -purpose whatsoever, including without limitation commercial, advertising or -promotional purposes (the "License"). The License shall be deemed effective as -of the date CC0 was applied by Affirmer to the Work. Should any part of the -License for any reason be judged legally invalid or ineffective under -applicable law, such partial invalidity or ineffectiveness shall not -invalidate the remainder of the License, and in such case Affirmer hereby -affirms that he or she will not (i) exercise any of his or her remaining -Copyright and Related Rights in the Work or (ii) assert any associated claims -and causes of action with respect to the Work, in either case contrary to -Affirmer's express Statement of Purpose. - -4. Limitations and Disclaimers. - - a. No trademark or patent rights held by Affirmer are waived, abandoned, - surrendered, licensed or otherwise affected by this document. - - b. Affirmer offers the Work as-is and makes no representations or warranties - of any kind concerning the Work, express, implied, statutory or otherwise, - including without limitation warranties of title, merchantability, fitness - for a particular purpose, non infringement, or the absence of latent or - other defects, accuracy, or the present or absence of errors, whether or not - discoverable, all to the greatest extent permissible under applicable law. - - c. Affirmer disclaims responsibility for clearing rights of other persons - that may apply to the Work or any use thereof, including without limitation - any person's Copyright and Related Rights in the Work. Further, Affirmer - disclaims responsibility for obtaining any necessary consents, permissions - or other rights required for any use of the Work. - - d. Affirmer understands and acknowledges that Creative Commons is not a - party to this document and has no duty or obligation with respect to this - CC0 or use of the Work. - -For more information, please see - diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_avx2/address.c b/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_avx2/address.c deleted file mode 100644 index 2c49eb20f1..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_avx2/address.c +++ /dev/null @@ -1,78 +0,0 @@ -#include - -#include "address.h" -#include "params.h" -#include "utils.h" - -void PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]) { - int i; - - for (i = 0; i < 8; i++) { - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_ull_to_bytes( - bytes + i * 4, 4, addr[i]); - } -} - -void PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_set_layer_addr( - uint32_t addr[8], uint32_t layer) { - addr[0] = layer; -} - -void PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_set_tree_addr( - uint32_t addr[8], uint64_t tree) { - addr[1] = 0; - addr[2] = (uint32_t) (tree >> 32); - addr[3] = (uint32_t) tree; -} - -void PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_set_type( - uint32_t addr[8], uint32_t type) { - addr[4] = type; -} - -void PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; -} - -/* These functions are used for OTS addresses. */ - -void PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_set_keypair_addr( - uint32_t addr[8], uint32_t keypair) { - addr[5] = keypair; -} - -void PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; - out[5] = in[5]; -} - -void PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_set_chain_addr( - uint32_t addr[8], uint32_t chain) { - addr[6] = chain; -} - -void PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_set_hash_addr( - uint32_t addr[8], uint32_t hash) { - addr[7] = hash; -} - -/* These functions are used for all hash tree addresses (including FORS). */ - -void PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_set_tree_height( - uint32_t addr[8], uint32_t tree_height) { - addr[6] = tree_height; -} - -void PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_set_tree_index( - uint32_t addr[8], uint32_t tree_index) { - addr[7] = tree_index; -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_avx2/address.h b/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_avx2/address.h deleted file mode 100644 index e1d4e22c02..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_avx2/address.h +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_ADDRESS_H -#define PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_ADDRESS_H - -#include - -#define PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_ADDR_TYPE_WOTS 0 -#define PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_ADDR_TYPE_WOTSPK 1 -#define PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_ADDR_TYPE_HASHTREE 2 -#define PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_ADDR_TYPE_FORSTREE 3 -#define PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_ADDR_TYPE_FORSPK 4 - -void PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]); - -void PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_set_layer_addr( - uint32_t addr[8], uint32_t layer); - -void PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_set_tree_addr( - uint32_t addr[8], uint64_t tree); - -void PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_set_type( - uint32_t addr[8], uint32_t type); - -/* Copies the layer and tree part of one address into the other */ -void PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for WOTS and FORS addresses. */ - -void PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_set_keypair_addr( - uint32_t addr[8], uint32_t keypair); - -void PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_set_chain_addr( - uint32_t addr[8], uint32_t chain); - -void PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_set_hash_addr( - uint32_t addr[8], uint32_t hash); - -void PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for all hash tree addresses (including FORS). */ - -void PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_set_tree_height( - uint32_t addr[8], uint32_t tree_height); - -void PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_set_tree_index( - uint32_t addr[8], uint32_t tree_index); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_avx2/api.h b/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_avx2/api.h deleted file mode 100644 index 7eee4673da..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_avx2/api.h +++ /dev/null @@ -1,81 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_API_H -#define PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_API_H - -#include -#include - - - -#define PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_CRYPTO_ALGNAME "SPHINCS+" - -#define PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_CRYPTO_SECRETKEYBYTES 64 -#define PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_CRYPTO_PUBLICKEYBYTES 32 -#define PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_CRYPTO_BYTES 17088 -#define PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_CRYPTO_SEEDBYTES 48 - - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_avx2/fors.c b/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_avx2/fors.c deleted file mode 100644 index e2b80f6cdd..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_avx2/fors.c +++ /dev/null @@ -1,240 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "fors.h" -#include "hash.h" -#include "hashx8.h" -#include "thash.h" -#include "thashx8.h" -#include "utils.h" -#include "utilsx8.h" - -static void fors_gen_skx8(unsigned char *sk0, - unsigned char *sk1, - unsigned char *sk2, - unsigned char *sk3, - unsigned char *sk4, - unsigned char *sk5, - unsigned char *sk6, - unsigned char *sk7, const unsigned char *sk_seed, - uint32_t fors_leaf_addrx8[8 * 8]) { - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_prf_addrx8(sk0, sk1, sk2, sk3, sk4, sk5, sk6, sk7, - sk_seed, fors_leaf_addrx8); -} - -static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, - const unsigned char *pub_seed, - uint32_t fors_leaf_addr[8], - const hash_state *state_seeded) { - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_thash_1(leaf, sk, pub_seed, fors_leaf_addr, state_seeded); -} - -static void fors_sk_to_leafx8(unsigned char *leaf0, - unsigned char *leaf1, - unsigned char *leaf2, - unsigned char *leaf3, - unsigned char *leaf4, - unsigned char *leaf5, - unsigned char *leaf6, - unsigned char *leaf7, - const unsigned char *sk0, - const unsigned char *sk1, - const unsigned char *sk2, - const unsigned char *sk3, - const unsigned char *sk4, - const unsigned char *sk5, - const unsigned char *sk6, - const unsigned char *sk7, - const unsigned char *pub_seed, - uint32_t fors_leaf_addrx8[8 * 8], - const hash_state *state_seeded) { - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_thashx8_1(leaf0, leaf1, leaf2, leaf3, leaf4, leaf5, leaf6, leaf7, - sk0, sk1, sk2, sk3, sk4, sk5, sk6, sk7, - pub_seed, fors_leaf_addrx8, state_seeded); -} - -static void fors_gen_leafx8(unsigned char *leaf0, - unsigned char *leaf1, - unsigned char *leaf2, - unsigned char *leaf3, - unsigned char *leaf4, - unsigned char *leaf5, - unsigned char *leaf6, - unsigned char *leaf7, - const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx0, - uint32_t addr_idx1, - uint32_t addr_idx2, - uint32_t addr_idx3, - uint32_t addr_idx4, - uint32_t addr_idx5, - uint32_t addr_idx6, - uint32_t addr_idx7, - const uint32_t fors_tree_addr[8], - const hash_state *state_seeded) { - uint32_t fors_leaf_addrx8[8 * 8] = {0}; - unsigned int j; - - /* Only copy the parts that must be kept in fors_leaf_addrx8. */ - for (j = 0; j < 8; j++) { - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_copy_keypair_addr(fors_leaf_addrx8 + j * 8, fors_tree_addr); - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_set_type(fors_leaf_addrx8 + j * 8, PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_ADDR_TYPE_FORSTREE); - } - - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_set_tree_index(fors_leaf_addrx8 + 0 * 8, addr_idx0); - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_set_tree_index(fors_leaf_addrx8 + 1 * 8, addr_idx1); - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_set_tree_index(fors_leaf_addrx8 + 2 * 8, addr_idx2); - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_set_tree_index(fors_leaf_addrx8 + 3 * 8, addr_idx3); - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_set_tree_index(fors_leaf_addrx8 + 4 * 8, addr_idx4); - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_set_tree_index(fors_leaf_addrx8 + 5 * 8, addr_idx5); - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_set_tree_index(fors_leaf_addrx8 + 6 * 8, addr_idx6); - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_set_tree_index(fors_leaf_addrx8 + 7 * 8, addr_idx7); - - fors_gen_skx8(leaf0, leaf1, leaf2, leaf3, leaf4, leaf5, leaf6, leaf7, - sk_seed, fors_leaf_addrx8); - fors_sk_to_leafx8(leaf0, leaf1, leaf2, leaf3, leaf4, leaf5, leaf6, leaf7, - leaf0, leaf1, leaf2, leaf3, leaf4, leaf5, leaf6, leaf7, - pub_seed, fors_leaf_addrx8, state_seeded); -} - -/** - * Interprets m as PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_FORS_HEIGHT-bit unsigned integers. - * Assumes m contains at least PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_FORS_TREES bits. - * Assumes indices has space for PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_FORS_TREES integers. - */ -static void message_to_indices(uint32_t *indices, const unsigned char *m) { - unsigned int i, j; - unsigned int offset = 0; - - for (i = 0; i < PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_FORS_TREES; i++) { - indices[i] = 0; - for (j = 0; j < PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_FORS_HEIGHT; j++) { - indices[i] ^= (((uint32_t)m[offset >> 3] >> (offset & 0x7)) & 0x1) << j; - offset++; - } - } -} - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_fors_sign( - unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], - const hash_state *state_seeded) { - /* Round up to multiple of 8 to prevent out-of-bounds for x8 parallelism */ - uint32_t indices[(PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_FORS_TREES + 7) & ~7] = {0}; - unsigned char roots[((PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_FORS_TREES + 7) & ~7) * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N]; - /* Sign to a buffer, since we may not have a nice multiple of 8 and would - otherwise overrun the signature. */ - unsigned char sigbufx8[8 * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N * (1 + PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_FORS_HEIGHT)]; - uint32_t fors_tree_addrx8[8 * 8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset[8] = {0}; - unsigned int i, j; - - for (j = 0; j < 8; j++) { - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_copy_keypair_addr(fors_tree_addrx8 + j * 8, fors_addr); - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_set_type(fors_tree_addrx8 + j * 8, PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_ADDR_TYPE_FORSTREE); - } - - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_copy_keypair_addr(fors_pk_addr, fors_addr); - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_set_type(fors_pk_addr, PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < ((PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_FORS_TREES + 7) & ~0x7); i += 8) { - for (j = 0; j < 8; j++) { - if (i + j < PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_FORS_TREES) { - idx_offset[j] = (i + j) * (1 << PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_FORS_HEIGHT); - - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_set_tree_height(fors_tree_addrx8 + j * 8, 0); - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_set_tree_index(fors_tree_addrx8 + j * 8, - indices[i + j] + idx_offset[j]); - } - } - - /* Include the secret key part that produces the selected leaf nodes. */ - fors_gen_skx8(sigbufx8 + 0 * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N, - sigbufx8 + 1 * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N, - sigbufx8 + 2 * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N, - sigbufx8 + 3 * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N, - sigbufx8 + 4 * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N, - sigbufx8 + 5 * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N, - sigbufx8 + 6 * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N, - sigbufx8 + 7 * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N, - sk_seed, fors_tree_addrx8); - - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_treehashx8_FORS_HEIGHT( - roots + i * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N, sigbufx8 + 8 * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N, sk_seed, pub_seed, - &indices[i], idx_offset, fors_gen_leafx8, fors_tree_addrx8, - state_seeded); - - for (j = 0; j < 8; j++) { - if (i + j < PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_FORS_TREES) { - memcpy(sig, sigbufx8 + j * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N, PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N); - memcpy(sig + PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N, - sigbufx8 + 8 * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N + j * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_FORS_HEIGHT, - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_FORS_HEIGHT); - sig += PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N * (1 + PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_FORS_HEIGHT); - } - } - } - - /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_thash_FORS_TREES(pk, roots, pub_seed, fors_pk_addr, state_seeded); -} - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, - const uint32_t fors_addr[8], - const hash_state *state_seeded) { - uint32_t indices[PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_FORS_TREES]; - unsigned char roots[PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_FORS_TREES * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N]; - unsigned char leaf[PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N]; - uint32_t fors_tree_addr[8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_copy_keypair_addr(fors_tree_addr, fors_addr); - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_copy_keypair_addr(fors_pk_addr, fors_addr); - - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_set_type(fors_tree_addr, PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_set_type(fors_pk_addr, PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_FORS_TREES; i++) { - idx_offset = i * (1 << PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_FORS_HEIGHT); - - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_set_tree_height(fors_tree_addr, 0); - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Derive the leaf from the included secret key part. */ - fors_sk_to_leaf(leaf, sig, pub_seed, fors_tree_addr, state_seeded); - sig += PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N; - - /* Derive the corresponding root node of this tree. */ - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_compute_root(roots + i * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N, leaf, indices[i], idx_offset, - sig, PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_FORS_HEIGHT, pub_seed, fors_tree_addr, state_seeded); - sig += PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_thash_FORS_TREES(pk, roots, pub_seed, fors_pk_addr, state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_avx2/fors.h b/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_avx2/fors.h deleted file mode 100644 index 9f4aabb436..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_avx2/fors.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_FORS_H -#define PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_FORS_H - -#include - -#include "hash_state.h" -#include "params.h" - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_fors_sign( - unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *hash_state_seeded); - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_fors_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, const uint32_t fors_addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_avx2/hash.h b/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_avx2/hash.h deleted file mode 100644 index bf63b7def9..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_avx2/hash.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_HASH_H -#define PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_HASH_H - -#include "hash_state.h" - -#include -#include - -void PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_initialize_hash_function( - hash_state *hash_state_seeded, - const unsigned char *pub_seed, const unsigned char *sk_seed); - -void PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_destroy_hash_function(hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_avx2/hash_sha256.c b/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_avx2/hash_sha256.c deleted file mode 100644 index 8b0aa087f9..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_avx2/hash_sha256.c +++ /dev/null @@ -1,166 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "utils.h" - -#include "sha2.h" -#include "sha256.h" -#include "sha256x8.h" - -/** - * Initializes the hash function states - */ -void PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_initialize_hash_function( - hash_state *hash_state_seeded, - const unsigned char *pub_seed, const unsigned char *sk_seed) { - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_seed_state(&hash_state_seeded->x1, pub_seed); - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_seed_statex8(&hash_state_seeded->x8, pub_seed); - (void)sk_seed; /* Suppress an 'unused parameter' warning. */ -} - -/** - * Cleans up the hash function states - */ -void PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_destroy_hash_function(hash_state *hash_state_seeded) { - sha256_inc_ctx_release(&hash_state_seeded->x1); -} - -/* - * Computes PRF(key, addr), given a secret key of PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N bytes and an address - */ -void PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_prf_addr(unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded) { - unsigned char buf[PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_ADDR_BYTES]; - unsigned char outbuf[PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_OUTPUT_BYTES]; - - memcpy(buf, key, PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N); - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_compress_address(buf + PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N, addr); - - sha256(outbuf, buf, PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_ADDR_BYTES); - memcpy(out, outbuf, PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} - -/** - * Computes the message-dependent randomness R, using a secret seed as a key - * for HMAC, and an optional randomization value prefixed to the message. - * This requires m to have at least PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_BLOCK_BYTES + PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N space - * available in front of the pointer, i.e. before the message to use for the - * prefix. This is necessary to prevent having to move the message around (and - * allocate memory for it). - */ -void PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, const hash_state *hash_state_seeded) { - unsigned char buf[PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_BLOCK_BYTES + PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_OUTPUT_BYTES]; - sha256ctx state; - int i; - - /* This implements HMAC-SHA256 */ - for (i = 0; i < PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N; i++) { - buf[i] = 0x36 ^ sk_prf[i]; - } - memset(buf + PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N, 0x36, PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N); - - sha256_inc_init(&state); - sha256_inc_blocks(&state, buf, 1); - - memcpy(buf, optrand, PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N); - - /* If optrand + message cannot fill up an entire block */ - if (PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N + mlen < PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_BLOCK_BYTES) { - memcpy(buf + PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N, m, mlen); - sha256_inc_finalize(buf + PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_BLOCK_BYTES, &state, - buf, mlen + PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N); - } - /* Otherwise first fill a block, so that finalize only uses the message */ - else { - memcpy(buf + PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N, m, PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N); - sha256_inc_blocks(&state, buf, 1); - - m += PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N; - mlen -= PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N; - sha256_inc_finalize(buf + PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_BLOCK_BYTES, &state, m, mlen); - } - - for (i = 0; i < PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N; i++) { - buf[i] = 0x5c ^ sk_prf[i]; - } - memset(buf + PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N, 0x5c, PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N); - - sha256(buf, buf, PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_BLOCK_BYTES + PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_OUTPUT_BYTES); - memcpy(R, buf, PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} - -/** - * Computes the message hash using R, the public key, and the message. - * Outputs the message digest and the index of the leaf. The index is split in - * the tree index and the leaf index, for convenient copying to an address. - */ -void PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded) { -#define PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_TREE_BITS (PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_TREE_HEIGHT * (PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_D - 1)) -#define PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_TREE_BYTES ((PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_TREE_BITS + 7) / 8) -#define PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_LEAF_BITS PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_TREE_HEIGHT -#define PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_LEAF_BYTES ((PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_LEAF_BITS + 7) / 8) -#define PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_DGST_BYTES (PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_FORS_MSG_BYTES + PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_TREE_BYTES + PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_LEAF_BYTES) - - unsigned char seed[PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_OUTPUT_BYTES + 4]; - - /* Round to nearest multiple of PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_BLOCK_BYTES */ -#define PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_INBLOCKS (((PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_PK_BYTES + PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_BLOCK_BYTES - 1) & \ - -PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_BLOCK_BYTES) / PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_BLOCK_BYTES) - unsigned char inbuf[PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_INBLOCKS * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_BLOCK_BYTES]; - - unsigned char buf[PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_DGST_BYTES]; - unsigned char *bufp = buf; - sha256ctx state; - - sha256_inc_init(&state); - - memcpy(inbuf, R, PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N); - memcpy(inbuf + PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N, pk, PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_PK_BYTES); - - /* If R + pk + message cannot fill up an entire block */ - if (PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_PK_BYTES + mlen < PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_INBLOCKS * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_BLOCK_BYTES) { - memcpy(inbuf + PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_PK_BYTES, m, mlen); - sha256_inc_finalize(seed, &state, inbuf, PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_PK_BYTES + mlen); - } - /* Otherwise first fill a block, so that finalize only uses the message */ - else { - memcpy(inbuf + PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_PK_BYTES, m, - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_INBLOCKS * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_PK_BYTES); - sha256_inc_blocks(&state, inbuf, PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_INBLOCKS); - - m += PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_INBLOCKS * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_PK_BYTES; - mlen -= PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_INBLOCKS * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_PK_BYTES; - sha256_inc_finalize(seed, &state, m, mlen); - } - - /* By doing this in two steps, we prevent hashing the message twice; - otherwise each iteration in MGF1 would hash the message again. */ - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_mgf1(bufp, PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_DGST_BYTES, seed, PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_OUTPUT_BYTES); - - memcpy(digest, bufp, PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_FORS_MSG_BYTES); - bufp += PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_FORS_MSG_BYTES; - - *tree = PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_bytes_to_ull(bufp, PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_TREE_BYTES); - *tree &= (~(uint64_t)0) >> (64 - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_TREE_BITS); - bufp += PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_TREE_BYTES; - - *leaf_idx = (uint32_t)PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_bytes_to_ull( - bufp, PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_LEAF_BYTES); - *leaf_idx &= (~(uint32_t)0) >> (32 - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_LEAF_BITS); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_avx2/hash_sha256x8.c b/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_avx2/hash_sha256x8.c deleted file mode 100644 index d90bd977d3..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_avx2/hash_sha256x8.c +++ /dev/null @@ -1,61 +0,0 @@ -#include -#include - -#include "address.h" -#include "hashx8.h" -#include "params.h" -#include "sha256.h" -#include "sha256avx.h" -#include "sha256x8.h" -#include "utils.h" - -/* - * 8-way parallel version of prf_addr; takes 8x as much input and output - */ -void PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_prf_addrx8(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7, - const unsigned char *key, - const uint32_t addrx8[8 * 8]) { - unsigned char bufx8[8 * (PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_ADDR_BYTES)]; - unsigned char outbufx8[8 * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_OUTPUT_BYTES]; - unsigned int j; - - for (j = 0; j < 8; j++) { - memcpy(bufx8 + j * (PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_ADDR_BYTES), key, PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N); - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_compress_address(bufx8 + PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N + j * (PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_ADDR_BYTES), - addrx8 + j * 8); - } - - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_sha256x8(outbufx8 + 0 * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 1 * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 2 * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 3 * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 4 * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 5 * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 6 * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 7 * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_OUTPUT_BYTES, - bufx8 + 0 * (PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_ADDR_BYTES), - bufx8 + 1 * (PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_ADDR_BYTES), - bufx8 + 2 * (PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_ADDR_BYTES), - bufx8 + 3 * (PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_ADDR_BYTES), - bufx8 + 4 * (PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_ADDR_BYTES), - bufx8 + 5 * (PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_ADDR_BYTES), - bufx8 + 6 * (PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_ADDR_BYTES), - bufx8 + 7 * (PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_ADDR_BYTES), - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_ADDR_BYTES); - - memcpy(out0, outbufx8 + 0 * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N); - memcpy(out1, outbufx8 + 1 * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N); - memcpy(out2, outbufx8 + 2 * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N); - memcpy(out3, outbufx8 + 3 * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N); - memcpy(out4, outbufx8 + 4 * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N); - memcpy(out5, outbufx8 + 5 * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N); - memcpy(out6, outbufx8 + 6 * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N); - memcpy(out7, outbufx8 + 7 * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_avx2/hash_state.h b/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_avx2/hash_state.h deleted file mode 100644 index 3c11872e76..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_avx2/hash_state.h +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_HASH_STATE_H -#define PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_HASH_STATE_H - -/** - * Defines the type of the hash function state. - * - * Don't be fooled into thinking this instance of SPHINCS+ isn't stateless! - * - * From Section 7.2.2 from the SPHINCS+ round-2 specification: - * - * Each of the instances of the tweakable hash function take PK.seed as its - * first input, which is constant for a given key pair – and, thus, across - * a single signature. This leads to a lot of redundant computation. To remedy - * this, we pad PK.seed to the length of a full 64-byte SHA-256 input block. - * Because of the Merkle-DamgÃ¥rd construction that underlies SHA-256, this - * allows for reuse of the intermediate SHA-256 state after the initial call to - * the compression function which improves performance. - * - * We pass this hash state around in functions, because otherwise we need to - * have a global variable. - * - * We use a struct to differentiate between the x1 and x8 variants of SHA256. - */ - -#include "sha2.h" -#include "sha256avx.h" - -typedef struct { - sha256ctx x1; - sha256ctxx8 x8; -} hash_state; - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_avx2/hashx8.h b/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_avx2/hashx8.h deleted file mode 100644 index 502ebf9608..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_avx2/hashx8.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_HASHX8_H -#define PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_HASHX8_H - -#include - -#include "params.h" - -void PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_prf_addrx8(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7, - const unsigned char *key, - const uint32_t addrx8[8 * 8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_avx2/params.h b/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_avx2/params.h deleted file mode 100644 index 69ab9a2e42..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_avx2/params.h +++ /dev/null @@ -1,53 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_PARAMS_H -#define PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_PARAMS_H - -/* Hash output length in bytes. */ -#define PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N 16 -/* Height of the hypertree. */ -#define PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_FULL_HEIGHT 66 -/* Number of subtree layer. */ -#define PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_D 22 -/* FORS tree dimensions. */ -#define PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_FORS_HEIGHT 6 -#define PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_FORS_TREES 33 -/* Winternitz parameter, */ -#define PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_WOTS_W 16 - -/* The hash function is defined by linking a different hash.c file, as opposed - to setting a #define constant. */ - -/* For clarity */ -#define PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_ADDR_BYTES 32 - -/* WOTS parameters. */ -#define PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_WOTS_LOGW 4 - -#define PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_WOTS_LEN1 (8 * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N / PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_WOTS_LOGW) - -/* PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#define PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_WOTS_LEN2 3 - -#define PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_WOTS_LEN (PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_WOTS_LEN1 + PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_WOTS_LEN2) -#define PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_WOTS_BYTES (PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_WOTS_LEN * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N) -#define PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_WOTS_PK_BYTES PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_WOTS_BYTES - -/* Subtree size. */ -#define PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_TREE_HEIGHT (PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_FULL_HEIGHT / PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_D) - -/* FORS parameters. */ -#define PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_FORS_MSG_BYTES ((PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_FORS_TREES + 7) / 8) -#define PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_FORS_BYTES ((PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_FORS_HEIGHT + 1) * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_FORS_TREES * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N) -#define PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_FORS_PK_BYTES PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N - -/* Resulting SPX sizes. */ -#define PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_BYTES (PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_FORS_BYTES + PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_D * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_WOTS_BYTES +\ - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_FULL_HEIGHT * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N) -#define PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_PK_BYTES (2 * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N) -#define PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SK_BYTES (2 * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_PK_BYTES) - -/* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ -#define PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_OPTRAND_BYTES 32 - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_avx2/sha256.c b/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_avx2/sha256.c deleted file mode 100644 index dfb4280c36..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_avx2/sha256.c +++ /dev/null @@ -1,71 +0,0 @@ -/* Based on the public domain implementation in - * crypto_hash/sha512/ref/ from http://bench.cr.yp.to/supercop.html - * by D. J. Bernstein */ - -#include -#include -#include - -#include "sha2.h" -#include "sha256.h" -#include "utils.h" - -/* - * Compresses an address to a 22-byte sequence. - * This reduces the number of required SHA256 compression calls, as the last - * block of input is padded with at least 65 bits. - */ -void PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_compress_address(unsigned char *out, const uint32_t addr[8]) { - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_ull_to_bytes(out, 1, addr[0]); /* drop 3 bytes of the layer field */ - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_ull_to_bytes(out + 1, 4, addr[2]); /* drop the highest tree address word */ - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_ull_to_bytes(out + 5, 4, addr[3]); - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_ull_to_bytes(out + 9, 1, addr[4]); /* drop 3 bytes of the type field */ - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_ull_to_bytes(out + 10, 4, addr[5]); - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_ull_to_bytes(out + 14, 4, addr[6]); - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_ull_to_bytes(out + 18, 4, addr[7]); -} - -/** - * Requires 'input_plus_four_bytes' to have 'inlen' + 4 bytes, so that the last - * four bytes can be used for the counter. Typically 'input' is merely a seed. - * Outputs outlen number of bytes - */ -void PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_mgf1( - unsigned char *out, unsigned long outlen, - unsigned char *input_plus_four_bytes, unsigned long inlen) { - unsigned char outbuf[PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_OUTPUT_BYTES]; - unsigned long i; - - /* While we can fit in at least another full block of SHA256 output.. */ - for (i = 0; (i + 1)*PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_OUTPUT_BYTES <= outlen; i++) { - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_ull_to_bytes(input_plus_four_bytes + inlen, 4, i); - sha256(out, input_plus_four_bytes, inlen + 4); - out += PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_OUTPUT_BYTES; - } - /* Until we cannot anymore, and we fill the remainder. */ - if (outlen > i * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_OUTPUT_BYTES) { - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_ull_to_bytes(input_plus_four_bytes + inlen, 4, i); - sha256(outbuf, input_plus_four_bytes, inlen + 4); - memcpy(out, outbuf, outlen - i * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_OUTPUT_BYTES); - } -} - - -/** - * Absorb the constant pub_seed using one round of the compression function - * This initializes hash_state_seeded, which can then be reused in thash - **/ -void PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_seed_state(sha256ctx *hash_state_seeded, const unsigned char *pub_seed) { - uint8_t block[PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_BLOCK_BYTES]; - size_t i; - - for (i = 0; i < PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N; ++i) { - block[i] = pub_seed[i]; - } - for (i = PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N; i < PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_BLOCK_BYTES; ++i) { - block[i] = 0; - } - - sha256_inc_init(hash_state_seeded); - sha256_inc_blocks(hash_state_seeded, block, 1); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_avx2/sha256.h b/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_avx2/sha256.h deleted file mode 100644 index 6f40d278d3..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_avx2/sha256.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_H -#define PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_H - -#define PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_BLOCK_BYTES 64 -#define PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_OUTPUT_BYTES 32 /* This does not necessarily equal PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N */ -#define PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_ADDR_BYTES 22 - -#include -#include - -#include "sha2.h" - -void PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_compress_address(unsigned char *out, const uint32_t addr[8]); - -void PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_mgf1( - unsigned char *out, unsigned long outlen, - unsigned char *input_plus_four_bytes, unsigned long inlen); - -void PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_seed_state(sha256ctx *hash_state_seeded, const unsigned char *pub_seed); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_avx2/sha256avx.c b/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_avx2/sha256avx.c deleted file mode 100644 index 29669d9f20..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_avx2/sha256avx.c +++ /dev/null @@ -1,296 +0,0 @@ -#include -#include -#include - -#include "sha256avx.h" - -// Transpose 8 vectors containing 32-bit values -void PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_transpose(u256 s[8]) { - u256 tmp0[8]; - u256 tmp1[8]; - tmp0[0] = _mm256_unpacklo_epi32(s[0], s[1]); - tmp0[1] = _mm256_unpackhi_epi32(s[0], s[1]); - tmp0[2] = _mm256_unpacklo_epi32(s[2], s[3]); - tmp0[3] = _mm256_unpackhi_epi32(s[2], s[3]); - tmp0[4] = _mm256_unpacklo_epi32(s[4], s[5]); - tmp0[5] = _mm256_unpackhi_epi32(s[4], s[5]); - tmp0[6] = _mm256_unpacklo_epi32(s[6], s[7]); - tmp0[7] = _mm256_unpackhi_epi32(s[6], s[7]); - tmp1[0] = _mm256_unpacklo_epi64(tmp0[0], tmp0[2]); - tmp1[1] = _mm256_unpackhi_epi64(tmp0[0], tmp0[2]); - tmp1[2] = _mm256_unpacklo_epi64(tmp0[1], tmp0[3]); - tmp1[3] = _mm256_unpackhi_epi64(tmp0[1], tmp0[3]); - tmp1[4] = _mm256_unpacklo_epi64(tmp0[4], tmp0[6]); - tmp1[5] = _mm256_unpackhi_epi64(tmp0[4], tmp0[6]); - tmp1[6] = _mm256_unpacklo_epi64(tmp0[5], tmp0[7]); - tmp1[7] = _mm256_unpackhi_epi64(tmp0[5], tmp0[7]); - s[0] = _mm256_permute2x128_si256(tmp1[0], tmp1[4], 0x20); - s[1] = _mm256_permute2x128_si256(tmp1[1], tmp1[5], 0x20); - s[2] = _mm256_permute2x128_si256(tmp1[2], tmp1[6], 0x20); - s[3] = _mm256_permute2x128_si256(tmp1[3], tmp1[7], 0x20); - s[4] = _mm256_permute2x128_si256(tmp1[0], tmp1[4], 0x31); - s[5] = _mm256_permute2x128_si256(tmp1[1], tmp1[5], 0x31); - s[6] = _mm256_permute2x128_si256(tmp1[2], tmp1[6], 0x31); - s[7] = _mm256_permute2x128_si256(tmp1[3], tmp1[7], 0x31); -} - -void PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_sha256_clone_statex8(sha256ctxx8 *outctx, const sha256ctxx8 *inctx) { - memcpy(outctx, inctx, sizeof(sha256ctxx8)); -} - -void PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_sha256_init8x(sha256ctxx8 *ctx) { - ctx->s[0] = _mm256_set_epi32((int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667); - ctx->s[1] = _mm256_set_epi32((int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85); - ctx->s[2] = _mm256_set_epi32((int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372); - ctx->s[3] = _mm256_set_epi32((int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a); - ctx->s[4] = _mm256_set_epi32((int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f); - ctx->s[5] = _mm256_set_epi32((int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c); - ctx->s[6] = _mm256_set_epi32((int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab); - ctx->s[7] = _mm256_set_epi32((int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19); - - ctx->datalen = 0; - ctx->msglen = 0; -} - -void PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_sha256_update8x(sha256ctxx8 *ctx, - const unsigned char *d0, - const unsigned char *d1, - const unsigned char *d2, - const unsigned char *d3, - const unsigned char *d4, - const unsigned char *d5, - const unsigned char *d6, - const unsigned char *d7, - unsigned long long len) { - size_t i = 0; - size_t bytes_to_copy; - - while (i < len) { - bytes_to_copy = (size_t)len - i; - if (bytes_to_copy > 64) { - bytes_to_copy = 64; - } - memcpy(&ctx->msgblocks[64 * 0], d0 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64 * 1], d1 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64 * 2], d2 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64 * 3], d3 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64 * 4], d4 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64 * 5], d5 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64 * 6], d6 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64 * 7], d7 + i, bytes_to_copy); - ctx->datalen += (unsigned int)bytes_to_copy; - i += bytes_to_copy; - if (ctx->datalen == 64) { - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_sha256_transform8x(ctx, ctx->msgblocks); - ctx->msglen += 512; - ctx->datalen = 0; - } - } -} - -void PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_sha256_final8x(sha256ctxx8 *ctx, - unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7) { - unsigned int i, curlen; - - // Padding - if (ctx->datalen < 56) { - for (i = 0; i < 8; ++i) { - curlen = ctx->datalen; - ctx->msgblocks[64 * i + curlen++] = 0x80; - while (curlen < 64) { - ctx->msgblocks[64 * i + curlen++] = 0x00; - } - } - } else { - for (i = 0; i < 8; ++i) { - curlen = ctx->datalen; - ctx->msgblocks[64 * i + curlen++] = 0x80; - while (curlen < 64) { - ctx->msgblocks[64 * i + curlen++] = 0x00; - } - } - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_sha256_transform8x(ctx, ctx->msgblocks); - memset(ctx->msgblocks, 0, 8 * 64); - } - - // Add length of the message to each block - ctx->msglen += ctx->datalen * 8; - for (i = 0; i < 8; i++) { - ctx->msgblocks[64 * i + 63] = (unsigned char)ctx->msglen; - ctx->msgblocks[64 * i + 62] = (unsigned char)(ctx->msglen >> 8); - ctx->msgblocks[64 * i + 61] = (unsigned char)(ctx->msglen >> 16); - ctx->msgblocks[64 * i + 60] = (unsigned char)(ctx->msglen >> 24); - ctx->msgblocks[64 * i + 59] = (unsigned char)(ctx->msglen >> 32); - ctx->msgblocks[64 * i + 58] = (unsigned char)(ctx->msglen >> 40); - ctx->msgblocks[64 * i + 57] = (unsigned char)(ctx->msglen >> 48); - ctx->msgblocks[64 * i + 56] = (unsigned char)(ctx->msglen >> 56); - } - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_sha256_transform8x(ctx, ctx->msgblocks); - - // Compute final hash output - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_transpose(ctx->s); - - // Store Hash value - STORE(out0, BYTESWAP(ctx->s[0])); - STORE(out1, BYTESWAP(ctx->s[1])); - STORE(out2, BYTESWAP(ctx->s[2])); - STORE(out3, BYTESWAP(ctx->s[3])); - STORE(out4, BYTESWAP(ctx->s[4])); - STORE(out5, BYTESWAP(ctx->s[5])); - STORE(out6, BYTESWAP(ctx->s[6])); - STORE(out7, BYTESWAP(ctx->s[7])); -} - -void PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_sha256_transform8x(sha256ctxx8 *ctx, const unsigned char *data) { - u256 s[8], w[64], T0, T1; - int i; - - // Load words and transform data correctly - for (i = 0; i < 8; i++) { - w[i] = BYTESWAP(LOAD(data + 64 * i)); - w[i + 8] = BYTESWAP(LOAD(data + 32 + 64 * i)); - } - - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_transpose(w); - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_transpose(w + 8); - - // Initial State - s[0] = ctx->s[0]; - s[1] = ctx->s[1]; - s[2] = ctx->s[2]; - s[3] = ctx->s[3]; - s[4] = ctx->s[4]; - s[5] = ctx->s[5]; - s[6] = ctx->s[6]; - s[7] = ctx->s[7]; - - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 0, w[0]); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 1, w[1]); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 2, w[2]); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 3, w[3]); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 4, w[4]); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 5, w[5]); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 6, w[6]); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 7, w[7]); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 8, w[8]); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 9, w[9]); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 10, w[10]); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 11, w[11]); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 12, w[12]); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 13, w[13]); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 14, w[14]); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 15, w[15]); - w[16] = ADD4_32(WSIGMA1_AVX(w[14]), w[0], w[9], WSIGMA0_AVX(w[1])); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 16, w[16]); - w[17] = ADD4_32(WSIGMA1_AVX(w[15]), w[1], w[10], WSIGMA0_AVX(w[2])); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 17, w[17]); - w[18] = ADD4_32(WSIGMA1_AVX(w[16]), w[2], w[11], WSIGMA0_AVX(w[3])); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 18, w[18]); - w[19] = ADD4_32(WSIGMA1_AVX(w[17]), w[3], w[12], WSIGMA0_AVX(w[4])); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 19, w[19]); - w[20] = ADD4_32(WSIGMA1_AVX(w[18]), w[4], w[13], WSIGMA0_AVX(w[5])); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 20, w[20]); - w[21] = ADD4_32(WSIGMA1_AVX(w[19]), w[5], w[14], WSIGMA0_AVX(w[6])); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 21, w[21]); - w[22] = ADD4_32(WSIGMA1_AVX(w[20]), w[6], w[15], WSIGMA0_AVX(w[7])); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 22, w[22]); - w[23] = ADD4_32(WSIGMA1_AVX(w[21]), w[7], w[16], WSIGMA0_AVX(w[8])); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 23, w[23]); - w[24] = ADD4_32(WSIGMA1_AVX(w[22]), w[8], w[17], WSIGMA0_AVX(w[9])); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 24, w[24]); - w[25] = ADD4_32(WSIGMA1_AVX(w[23]), w[9], w[18], WSIGMA0_AVX(w[10])); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 25, w[25]); - w[26] = ADD4_32(WSIGMA1_AVX(w[24]), w[10], w[19], WSIGMA0_AVX(w[11])); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 26, w[26]); - w[27] = ADD4_32(WSIGMA1_AVX(w[25]), w[11], w[20], WSIGMA0_AVX(w[12])); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 27, w[27]); - w[28] = ADD4_32(WSIGMA1_AVX(w[26]), w[12], w[21], WSIGMA0_AVX(w[13])); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 28, w[28]); - w[29] = ADD4_32(WSIGMA1_AVX(w[27]), w[13], w[22], WSIGMA0_AVX(w[14])); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 29, w[29]); - w[30] = ADD4_32(WSIGMA1_AVX(w[28]), w[14], w[23], WSIGMA0_AVX(w[15])); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 30, w[30]); - w[31] = ADD4_32(WSIGMA1_AVX(w[29]), w[15], w[24], WSIGMA0_AVX(w[16])); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 31, w[31]); - w[32] = ADD4_32(WSIGMA1_AVX(w[30]), w[16], w[25], WSIGMA0_AVX(w[17])); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 32, w[32]); - w[33] = ADD4_32(WSIGMA1_AVX(w[31]), w[17], w[26], WSIGMA0_AVX(w[18])); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 33, w[33]); - w[34] = ADD4_32(WSIGMA1_AVX(w[32]), w[18], w[27], WSIGMA0_AVX(w[19])); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 34, w[34]); - w[35] = ADD4_32(WSIGMA1_AVX(w[33]), w[19], w[28], WSIGMA0_AVX(w[20])); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 35, w[35]); - w[36] = ADD4_32(WSIGMA1_AVX(w[34]), w[20], w[29], WSIGMA0_AVX(w[21])); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 36, w[36]); - w[37] = ADD4_32(WSIGMA1_AVX(w[35]), w[21], w[30], WSIGMA0_AVX(w[22])); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 37, w[37]); - w[38] = ADD4_32(WSIGMA1_AVX(w[36]), w[22], w[31], WSIGMA0_AVX(w[23])); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 38, w[38]); - w[39] = ADD4_32(WSIGMA1_AVX(w[37]), w[23], w[32], WSIGMA0_AVX(w[24])); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 39, w[39]); - w[40] = ADD4_32(WSIGMA1_AVX(w[38]), w[24], w[33], WSIGMA0_AVX(w[25])); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 40, w[40]); - w[41] = ADD4_32(WSIGMA1_AVX(w[39]), w[25], w[34], WSIGMA0_AVX(w[26])); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 41, w[41]); - w[42] = ADD4_32(WSIGMA1_AVX(w[40]), w[26], w[35], WSIGMA0_AVX(w[27])); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 42, w[42]); - w[43] = ADD4_32(WSIGMA1_AVX(w[41]), w[27], w[36], WSIGMA0_AVX(w[28])); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 43, w[43]); - w[44] = ADD4_32(WSIGMA1_AVX(w[42]), w[28], w[37], WSIGMA0_AVX(w[29])); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 44, w[44]); - w[45] = ADD4_32(WSIGMA1_AVX(w[43]), w[29], w[38], WSIGMA0_AVX(w[30])); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 45, w[45]); - w[46] = ADD4_32(WSIGMA1_AVX(w[44]), w[30], w[39], WSIGMA0_AVX(w[31])); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 46, w[46]); - w[47] = ADD4_32(WSIGMA1_AVX(w[45]), w[31], w[40], WSIGMA0_AVX(w[32])); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 47, w[47]); - w[48] = ADD4_32(WSIGMA1_AVX(w[46]), w[32], w[41], WSIGMA0_AVX(w[33])); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 48, w[48]); - w[49] = ADD4_32(WSIGMA1_AVX(w[47]), w[33], w[42], WSIGMA0_AVX(w[34])); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 49, w[49]); - w[50] = ADD4_32(WSIGMA1_AVX(w[48]), w[34], w[43], WSIGMA0_AVX(w[35])); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 50, w[50]); - w[51] = ADD4_32(WSIGMA1_AVX(w[49]), w[35], w[44], WSIGMA0_AVX(w[36])); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 51, w[51]); - w[52] = ADD4_32(WSIGMA1_AVX(w[50]), w[36], w[45], WSIGMA0_AVX(w[37])); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 52, w[52]); - w[53] = ADD4_32(WSIGMA1_AVX(w[51]), w[37], w[46], WSIGMA0_AVX(w[38])); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 53, w[53]); - w[54] = ADD4_32(WSIGMA1_AVX(w[52]), w[38], w[47], WSIGMA0_AVX(w[39])); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 54, w[54]); - w[55] = ADD4_32(WSIGMA1_AVX(w[53]), w[39], w[48], WSIGMA0_AVX(w[40])); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 55, w[55]); - w[56] = ADD4_32(WSIGMA1_AVX(w[54]), w[40], w[49], WSIGMA0_AVX(w[41])); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 56, w[56]); - w[57] = ADD4_32(WSIGMA1_AVX(w[55]), w[41], w[50], WSIGMA0_AVX(w[42])); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 57, w[57]); - w[58] = ADD4_32(WSIGMA1_AVX(w[56]), w[42], w[51], WSIGMA0_AVX(w[43])); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 58, w[58]); - w[59] = ADD4_32(WSIGMA1_AVX(w[57]), w[43], w[52], WSIGMA0_AVX(w[44])); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 59, w[59]); - w[60] = ADD4_32(WSIGMA1_AVX(w[58]), w[44], w[53], WSIGMA0_AVX(w[45])); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 60, w[60]); - w[61] = ADD4_32(WSIGMA1_AVX(w[59]), w[45], w[54], WSIGMA0_AVX(w[46])); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 61, w[61]); - w[62] = ADD4_32(WSIGMA1_AVX(w[60]), w[46], w[55], WSIGMA0_AVX(w[47])); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 62, w[62]); - w[63] = ADD4_32(WSIGMA1_AVX(w[61]), w[47], w[56], WSIGMA0_AVX(w[48])); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 63, w[63]); - - // Feed Forward - ctx->s[0] = ADD32(s[0], ctx->s[0]); - ctx->s[1] = ADD32(s[1], ctx->s[1]); - ctx->s[2] = ADD32(s[2], ctx->s[2]); - ctx->s[3] = ADD32(s[3], ctx->s[3]); - ctx->s[4] = ADD32(s[4], ctx->s[4]); - ctx->s[5] = ADD32(s[5], ctx->s[5]); - ctx->s[6] = ADD32(s[6], ctx->s[6]); - ctx->s[7] = ADD32(s[7], ctx->s[7]); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_avx2/sha256avx.h b/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_avx2/sha256avx.h deleted file mode 100644 index 6cbbcc7b31..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_avx2/sha256avx.h +++ /dev/null @@ -1,103 +0,0 @@ -#ifndef SHA256AVX_H -#define SHA256AVX_H - -#include -#include - -static const unsigned int RC[] = { - 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, - 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, - 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, - 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, - 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, - 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, - 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, - 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, - 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, - 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, - 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, - 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, - 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, - 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, - 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, - 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 -}; - -#define u32 uint32_t -#define u256 __m256i - -#define XOR _mm256_xor_si256 -#define OR _mm256_or_si256 -#define AND _mm256_and_si256 -#define ADD32 _mm256_add_epi32 -#define NOT(x) _mm256_xor_si256(x, _mm256_set_epi32(-1, -1, -1, -1, -1, -1, -1, -1)) - -#define LOAD(src) _mm256_loadu_si256((__m256i *)(src)) -#define STORE(dest,src) _mm256_storeu_si256((__m256i *)(dest),src) - -#define BYTESWAP(x) _mm256_shuffle_epi8(x, _mm256_set_epi8(0xc,0xd,0xe,0xf,0x8,0x9,0xa,0xb,0x4,0x5,0x6,0x7,0x0,0x1,0x2,0x3,0xc,0xd,0xe,0xf,0x8,0x9,0xa,0xb,0x4,0x5,0x6,0x7,0x0,0x1,0x2,0x3)) - -#define SHIFTR32(x, y) _mm256_srli_epi32(x, y) -#define SHIFTL32(x, y) _mm256_slli_epi32(x, y) - -#define ROTR32(x, y) OR(SHIFTR32(x, y), SHIFTL32(x, 32 - (y))) -#define ROTL32(x, y) OR(SHIFTL32(x, y), SHIFTR32(x, 32 - (y))) - -#define XOR3(a, b, c) XOR(XOR(a, b), c) - -#define ADD3_32(a, b, c) ADD32(ADD32(a, b), c) -#define ADD4_32(a, b, c, d) ADD32(ADD32(ADD32(a, b), c), d) -#define ADD5_32(a, b, c, d, e) ADD32(ADD32(ADD32(ADD32(a, b), c), d), e) - -#define MAJ_AVX(a, b, c) XOR3(AND(a, b), AND(a, c), AND(b, c)) -#define CH_AVX(a, b, c) XOR(AND(a, b), AND(NOT(a), c)) - -#define SIGMA1_AVX(x) XOR3(ROTR32(x, 6), ROTR32(x, 11), ROTR32(x, 25)) -#define SIGMA0_AVX(x) XOR3(ROTR32(x, 2), ROTR32(x, 13), ROTR32(x, 22)) - -#define WSIGMA1_AVX(x) XOR3(ROTR32(x, 17), ROTR32(x, 19), SHIFTR32(x, 10)) -#define WSIGMA0_AVX(x) XOR3(ROTR32(x, 7), ROTR32(x, 18), SHIFTR32(x, 3)) - -#define SHA256ROUND_AVX(a, b, c, d, e, f, g, h, rc, w) \ - T0 = ADD5_32(h, SIGMA1_AVX(e), CH_AVX(e, f, g), _mm256_set1_epi32((int)RC[rc]), w); \ - (d) = ADD32(d, T0); \ - T1 = ADD32(SIGMA0_AVX(a), MAJ_AVX(a, b, c)); \ - (h) = ADD32(T0, T1); - -typedef struct SHA256state { - u256 s[8]; - uint8_t msgblocks[8 * 64]; - unsigned int datalen; - uint64_t msglen; -} sha256ctxx8; - - -void PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_transpose(u256 s[8]); -void PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_sha256_init_frombytes_x8(sha256ctxx8 *ctx, const uint8_t *s, unsigned long long msglen); -void PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_sha256_init8x(sha256ctxx8 *ctx); -void PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_sha256_update8x(sha256ctxx8 *ctx, - const unsigned char *d0, - const unsigned char *d1, - const unsigned char *d2, - const unsigned char *d3, - const unsigned char *d4, - const unsigned char *d5, - const unsigned char *d6, - const unsigned char *d7, - unsigned long long len); -void PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_sha256_final8x(sha256ctxx8 *ctx, - unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7); - -void PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_sha256_transform8x(sha256ctxx8 *ctx, const unsigned char *data); - -void PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_sha256_clone_statex8(sha256ctxx8 *outctx, const sha256ctxx8 *inctx); - - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_avx2/sha256x8.c b/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_avx2/sha256x8.c deleted file mode 100644 index 74eac233a6..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_avx2/sha256x8.c +++ /dev/null @@ -1,128 +0,0 @@ -#include - -#include "sha256.h" -#include "sha256avx.h" -#include "sha256x8.h" -#include "utils.h" - -void PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_seed_statex8(sha256ctxx8 *ctx, const unsigned char *pub_seed) { - uint8_t block[PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_BLOCK_BYTES]; - size_t i; - - for (i = 0; i < PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N; ++i) { - block[i] = pub_seed[i]; - } - for (i = PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N; i < PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_BLOCK_BYTES; ++i) { - block[i] = 0; - } - - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_sha256_init8x(ctx); - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_sha256_update8x(ctx, block, block, block, block, block, block, block, block, PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_BLOCK_BYTES); - -} - -/* This provides a wrapper around the internals of 8x parallel SHA256 */ -void PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_sha256x8(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - const unsigned char *in4, - const unsigned char *in5, - const unsigned char *in6, - const unsigned char *in7, unsigned long long inlen) { - sha256ctxx8 ctx; - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_sha256_init8x(&ctx); - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_sha256_update8x(&ctx, in0, in1, in2, in3, in4, in5, in6, in7, inlen); - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_sha256_final8x(&ctx, out0, out1, out2, out3, out4, out5, out6, out7); -} - -/** - * Note that inlen should be sufficiently small that it still allows for - * an array to be allocated on the stack. Typically 'in' is merely a seed. - * Outputs outlen number of bytes - */ -void PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_mgf1x8( - unsigned char *outx8, - unsigned long outlen, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - const unsigned char *in4, - const unsigned char *in5, - const unsigned char *in6, - const unsigned char *in7, - unsigned long inlen) { - unsigned char inbufx8[8 * ((PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_ADDR_BYTES) + 4)]; - unsigned char outbufx8[8 * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_OUTPUT_BYTES]; - unsigned long i; - unsigned int j; - - memcpy(inbufx8 + 0 * (inlen + 4), in0, inlen); - memcpy(inbufx8 + 1 * (inlen + 4), in1, inlen); - memcpy(inbufx8 + 2 * (inlen + 4), in2, inlen); - memcpy(inbufx8 + 3 * (inlen + 4), in3, inlen); - memcpy(inbufx8 + 4 * (inlen + 4), in4, inlen); - memcpy(inbufx8 + 5 * (inlen + 4), in5, inlen); - memcpy(inbufx8 + 6 * (inlen + 4), in6, inlen); - memcpy(inbufx8 + 7 * (inlen + 4), in7, inlen); - - /* While we can fit in at least another full block of SHA256 output.. */ - for (i = 0; (i + 1)*PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_OUTPUT_BYTES <= outlen; i++) { - for (j = 0; j < 8; j++) { - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_ull_to_bytes(inbufx8 + inlen + j * (inlen + 4), 4, i); - } - - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_sha256x8(outx8 + 0 * outlen, - outx8 + 1 * outlen, - outx8 + 2 * outlen, - outx8 + 3 * outlen, - outx8 + 4 * outlen, - outx8 + 5 * outlen, - outx8 + 6 * outlen, - outx8 + 7 * outlen, - inbufx8 + 0 * (inlen + 4), - inbufx8 + 1 * (inlen + 4), - inbufx8 + 2 * (inlen + 4), - inbufx8 + 3 * (inlen + 4), - inbufx8 + 4 * (inlen + 4), - inbufx8 + 5 * (inlen + 4), - inbufx8 + 6 * (inlen + 4), - inbufx8 + 7 * (inlen + 4), inlen + 4); - outx8 += PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_OUTPUT_BYTES; - } - /* Until we cannot anymore, and we fill the remainder. */ - for (j = 0; j < 8; j++) { - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_ull_to_bytes(inbufx8 + inlen + j * (inlen + 4), 4, i); - } - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_sha256x8(outbufx8 + 0 * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 1 * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 2 * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 3 * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 4 * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 5 * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 6 * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 7 * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_OUTPUT_BYTES, - inbufx8 + 0 * (inlen + 4), - inbufx8 + 1 * (inlen + 4), - inbufx8 + 2 * (inlen + 4), - inbufx8 + 3 * (inlen + 4), - inbufx8 + 4 * (inlen + 4), - inbufx8 + 5 * (inlen + 4), - inbufx8 + 6 * (inlen + 4), - inbufx8 + 7 * (inlen + 4), inlen + 4); - - for (j = 0; j < 8; j++) { - memcpy(outx8 + j * outlen, - outbufx8 + j * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_OUTPUT_BYTES, - outlen - i * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_OUTPUT_BYTES); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_avx2/sha256x8.h b/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_avx2/sha256x8.h deleted file mode 100644 index e8b9954ef4..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_avx2/sha256x8.h +++ /dev/null @@ -1,44 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256X8_H -#define PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256X8_H - -#include "sha256avx.h" - -#define PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_BLOCK_BYTES 64 -#define PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_OUTPUT_BYTES 32 /* This does not necessarily equal PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N */ - -/* This provides a wrapper around the internals of 8x parallel SHA256 */ -void PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_sha256x8(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - const unsigned char *in4, - const unsigned char *in5, - const unsigned char *in6, - const unsigned char *in7, unsigned long long inlen); - -/** - * Note that inlen should be sufficiently small that it still allows for - * an array to be allocated on the stack. Typically 'in' is merely a seed. - * Outputs outlen number of bytes - */ -void PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_mgf1x8(unsigned char *outx8, unsigned long outlen, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - const unsigned char *in4, - const unsigned char *in5, - const unsigned char *in6, - const unsigned char *in7, - unsigned long inlen); - -void PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_seed_statex8(sha256ctxx8 *ctx, const unsigned char *pub_seed); -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_avx2/sign.c b/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_avx2/sign.c deleted file mode 100644 index 86eef28587..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_avx2/sign.c +++ /dev/null @@ -1,356 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "api.h" -#include "fors.h" -#include "hash.h" -#include "hash_state.h" -#include "params.h" -#include "randombytes.h" -#include "thash.h" -#include "utils.h" -#include "wots.h" - -/** - * Computes the leaf at a given address. First generates the WOTS key pair, - * then computes leaf by hashing horizontally. - */ -static void wots_gen_leaf(unsigned char *leaf, const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx, const uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - unsigned char pk[PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_WOTS_BYTES]; - uint32_t wots_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_set_type( - wots_addr, PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_set_type( - wots_pk_addr, PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_ADDR_TYPE_WOTSPK); - - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_set_keypair_addr( - wots_addr, addr_idx); - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_wots_gen_pk( - pk, sk_seed, pub_seed, wots_addr, hash_state_seeded); - - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_copy_keypair_addr( - wots_pk_addr, wots_addr); - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_thash_WOTS_LEN( - leaf, pk, pub_seed, wots_pk_addr, hash_state_seeded); -} - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_crypto_sign_secretkeybytes(void) { - return PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_CRYPTO_SECRETKEYBYTES; -} - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_crypto_sign_publickeybytes(void) { - return PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_CRYPTO_PUBLICKEYBYTES; -} - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_crypto_sign_bytes(void) { - return PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_CRYPTO_BYTES; -} - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_crypto_sign_seedbytes(void) { - return PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_CRYPTO_SEEDBYTES; -} - -/* - * Generates an SPX key pair given a seed of length - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed) { - /* We do not need the auth path in key generation, but it simplifies the - code to have just one treehash routine that computes both root and path - in one function. */ - unsigned char auth_path[PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_TREE_HEIGHT * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N]; - uint32_t top_tree_addr[8] = {0}; - hash_state hash_state_seeded; - - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_set_layer_addr( - top_tree_addr, PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_D - 1); - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_set_type( - top_tree_addr, PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_ADDR_TYPE_HASHTREE); - - /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ - memcpy(sk, seed, PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_CRYPTO_SEEDBYTES); - - memcpy(pk, sk + 2 * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N, PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_initialize_hash_function(&hash_state_seeded, pk, sk); - - /* Compute root node of the top-most subtree. */ - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_treehash_TREE_HEIGHT( - sk + 3 * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N, auth_path, sk, sk + 2 * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N, 0, 0, - wots_gen_leaf, top_tree_addr, &hash_state_seeded); - - memcpy(pk + PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N, sk + 3 * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N, PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N); - - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_destroy_hash_function(&hash_state_seeded); - return 0; -} - -/* - * Generates an SPX key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk) { - unsigned char seed[PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_CRYPTO_SEEDBYTES]; - randombytes(seed, PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_CRYPTO_SEEDBYTES); - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_crypto_sign_seed_keypair( - pk, sk, seed); - - return 0; -} - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - const unsigned char *sk_seed = sk; - const unsigned char *sk_prf = sk + PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N; - const unsigned char *pk = sk + 2 * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N; - const unsigned char *pub_seed = pk; - - unsigned char optrand[PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N]; - unsigned char mhash[PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_FORS_MSG_BYTES]; - unsigned char root[PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N]; - uint32_t i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - - hash_state hash_state_seeded; - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_initialize_hash_function( - &hash_state_seeded, - pub_seed, sk_seed); - - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_set_type( - wots_addr, PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_set_type( - tree_addr, PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_ADDR_TYPE_HASHTREE); - - /* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ - randombytes(optrand, PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N); - /* Compute the digest randomization value. */ - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_gen_message_random( - sig, sk_prf, optrand, m, mlen, &hash_state_seeded); - - /* Derive the message digest and leaf index from R, PK and M. */ - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N; - - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_set_keypair_addr( - wots_addr, idx_leaf); - - /* Sign the message hash using FORS. */ - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_fors_sign( - sig, root, mhash, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_FORS_BYTES; - - for (i = 0; i < PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_D; i++) { - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_set_tree_addr(tree_addr, tree); - - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_set_keypair_addr( - wots_addr, idx_leaf); - - /* Compute a WOTS signature. */ - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_wots_sign( - sig, root, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_WOTS_BYTES; - - /* Compute the authentication path for the used WOTS leaf. */ - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_treehash_TREE_HEIGHT( - root, sig, sk_seed, pub_seed, idx_leaf, 0, - wots_gen_leaf, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_TREE_HEIGHT * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_TREE_HEIGHT; - } - - *siglen = PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_BYTES; - - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_destroy_hash_function(&hash_state_seeded); - return 0; -} - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk) { - const unsigned char *pub_seed = pk; - const unsigned char *pub_root = pk + PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N; - unsigned char mhash[PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_FORS_MSG_BYTES]; - unsigned char wots_pk[PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_WOTS_BYTES]; - unsigned char root[PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N]; - unsigned char leaf[PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N]; - unsigned int i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - hash_state hash_state_seeded; - - if (siglen != PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_BYTES) { - return -1; - } - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_initialize_hash_function( - &hash_state_seeded, - pub_seed, NULL); - - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_set_type( - wots_addr, PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_set_type( - tree_addr, PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_ADDR_TYPE_HASHTREE); - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_set_type( - wots_pk_addr, PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_ADDR_TYPE_WOTSPK); - - /* Derive the message digest and leaf index from R || PK || M. */ - /* The additional PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N is a result of the hash domain separator. */ - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N; - - /* Layer correctly defaults to 0, so no need to set_layer_addr */ - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_set_keypair_addr( - wots_addr, idx_leaf); - - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_fors_pk_from_sig( - root, sig, mhash, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_FORS_BYTES; - - /* For each subtree.. */ - for (i = 0; i < PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_D; i++) { - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_set_tree_addr(tree_addr, tree); - - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_set_keypair_addr( - wots_addr, idx_leaf); - - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_copy_keypair_addr( - wots_pk_addr, wots_addr); - - /* The WOTS public key is only correct if the signature was correct. */ - /* Initially, root is the FORS pk, but on subsequent iterations it is - the root of the subtree below the currently processed subtree. */ - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_wots_pk_from_sig( - wots_pk, sig, root, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_WOTS_BYTES; - - /* Compute the leaf node using the WOTS public key. */ - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_thash_WOTS_LEN( - leaf, wots_pk, pub_seed, wots_pk_addr, &hash_state_seeded); - - /* Compute the root node of this subtree. */ - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_compute_root( - root, leaf, idx_leaf, 0, sig, PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_TREE_HEIGHT, - pub_seed, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_TREE_HEIGHT * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_TREE_HEIGHT; - } - - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_destroy_hash_function(&hash_state_seeded); - /* Check if the root node equals the root node in the public key. */ - if (memcmp(root, pub_root, PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N) != 0) { - return -1; - } - - return 0; -} - - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - size_t siglen; - - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_crypto_sign_signature( - sm, &siglen, m, mlen, sk); - - memmove(sm + PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_BYTES, m, mlen); - *smlen = siglen + mlen; - - return 0; -} - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk) { - /* The API caller does not necessarily know what size a signature should be - but SPHINCS+ signatures are always exactly PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_BYTES. */ - if (smlen < PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_BYTES) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - *mlen = smlen - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_BYTES; - - if (PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_crypto_sign_verify( - sm, PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_BYTES, sm + PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_BYTES, *mlen, pk)) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - /* If verification was successful, move the message to the right place. */ - memmove(m, sm + PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_BYTES, *mlen); - - return 0; -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_avx2/thash.h b/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_avx2/thash.h deleted file mode 100644 index 43ea918bdb..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_avx2/thash.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_THASH_H -#define PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_THASH_H - -#include "hash_state.h" - -#include - -void PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_avx2/thash_sha256_robust.c b/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_avx2/thash_sha256_robust.c deleted file mode 100644 index f2c72de0d0..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_avx2/thash_sha256_robust.c +++ /dev/null @@ -1,78 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "thash.h" - -#include "sha2.h" -#include "sha256.h" - -/** - * Takes an array of inblocks concatenated arrays of PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N bytes. - */ -static void thash( - unsigned char *out, unsigned char *buf, - const unsigned char *in, unsigned int inblocks, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char outbuf[PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_OUTPUT_BYTES]; - unsigned char *bitmask = buf + PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_ADDR_BYTES + 4; - sha256ctx sha2_state; - unsigned int i; - - memcpy(buf, pub_seed, PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N); - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_compress_address(buf + PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N, addr); - /* MGF1 requires us to have 4 extra bytes in 'buf' */ - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_mgf1(bitmask, inblocks * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N, buf, PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_ADDR_BYTES); - - /* Retrieve precomputed state containing pub_seed */ - sha256_inc_ctx_clone(&sha2_state, &hash_state_seeded->x1); - - for (i = 0; i < inblocks * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N; i++) { - buf[PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_ADDR_BYTES + i] = in[i] ^ bitmask[i]; - } - - sha256_inc_finalize(outbuf, &sha2_state, buf + PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N, - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N); - memcpy(out, outbuf, PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N); -} - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_ADDR_BYTES + 4 + 1 * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N]; - thash(out, buf, in, 1, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_ADDR_BYTES + 4 + 2 * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N]; - thash(out, buf, in, 2, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_ADDR_BYTES + 4 + PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_WOTS_LEN * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N]; - thash(out, buf, in, PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_WOTS_LEN, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_ADDR_BYTES + 4 + PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_FORS_TREES * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N]; - thash(out, buf, in, PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_FORS_TREES, pub_seed, addr, hash_state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_avx2/thash_sha256_robustx8.c b/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_avx2/thash_sha256_robustx8.c deleted file mode 100644 index e3be245aa8..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_avx2/thash_sha256_robustx8.c +++ /dev/null @@ -1,156 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "sha256.h" -#include "sha256avx.h" -#include "sha256x8.h" -#include "thashx8.h" -#include "utils.h" - -/** - * 8-way parallel version of thash; takes 8x as much input and output - */ -static void thashx8(uint8_t *out0, - uint8_t *out1, - uint8_t *out2, - uint8_t *out3, - uint8_t *out4, - uint8_t *out5, - uint8_t *out6, - uint8_t *out7, - const uint8_t *in0, - const uint8_t *in1, - const uint8_t *in2, - const uint8_t *in3, - const uint8_t *in4, - const uint8_t *in5, - const uint8_t *in6, - const uint8_t *in7, - unsigned int inblocks, - const uint8_t *pub_seed, - uint32_t addrx8[8 * 8], - uint8_t *bufx8, - uint8_t *bitmaskx8, - const hash_state *state_seeded) { - unsigned char outbufx8[8 * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_OUTPUT_BYTES]; - unsigned int i; - sha256ctxx8 ctx; - - (void)pub_seed; /* Suppress an 'unused parameter' warning. */ - - for (i = 0; i < 8; i++) { - memcpy(bufx8 + i * (PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N), - pub_seed, PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N); - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_compress_address(bufx8 + PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N + - i * (PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N), - addrx8 + i * 8); - } - - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_mgf1x8(bitmaskx8, inblocks * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N, - bufx8 + 0 * (PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N), - bufx8 + 1 * (PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N), - bufx8 + 2 * (PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N), - bufx8 + 3 * (PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N), - bufx8 + 4 * (PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N), - bufx8 + 5 * (PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N), - bufx8 + 6 * (PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N), - bufx8 + 7 * (PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N), - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_ADDR_BYTES - ); - - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_sha256_clone_statex8(&ctx, &state_seeded->x8); - - for (i = 0; i < inblocks * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N; i++) { - bufx8[PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_ADDR_BYTES + i + - 0 * (PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N)] = - in0[i] ^ bitmaskx8[i + 0 * (inblocks * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N)]; - bufx8[PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_ADDR_BYTES + i + - 1 * (PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N)] = - in1[i] ^ bitmaskx8[i + 1 * (inblocks * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N)]; - bufx8[PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_ADDR_BYTES + i + - 2 * (PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N)] = - in2[i] ^ bitmaskx8[i + 2 * (inblocks * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N)]; - bufx8[PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_ADDR_BYTES + i + - 3 * (PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N)] = - in3[i] ^ bitmaskx8[i + 3 * (inblocks * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N)]; - bufx8[PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_ADDR_BYTES + i + - 4 * (PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N)] = - in4[i] ^ bitmaskx8[i + 4 * (inblocks * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N)]; - bufx8[PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_ADDR_BYTES + i + - 5 * (PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N)] = - in5[i] ^ bitmaskx8[i + 5 * (inblocks * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N)]; - bufx8[PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_ADDR_BYTES + i + - 6 * (PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N)] = - in6[i] ^ bitmaskx8[i + 6 * (inblocks * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N)]; - bufx8[PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_ADDR_BYTES + i + - 7 * (PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N)] = - in7[i] ^ bitmaskx8[i + 7 * (inblocks * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N)]; - } - - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_sha256_update8x(&ctx, - bufx8 + PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N + 0 * (PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N), - bufx8 + PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N + 1 * (PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N), - bufx8 + PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N + 2 * (PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N), - bufx8 + PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N + 3 * (PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N), - bufx8 + PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N + 4 * (PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N), - bufx8 + PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N + 5 * (PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N), - bufx8 + PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N + 6 * (PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N), - bufx8 + PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N + 7 * (PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N), - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N); - - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_sha256_final8x(&ctx, - outbufx8 + 0 * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 1 * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 2 * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 3 * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 4 * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 5 * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 6 * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 7 * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_OUTPUT_BYTES); - - memcpy(out0, outbufx8 + 0 * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N); - memcpy(out1, outbufx8 + 1 * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N); - memcpy(out2, outbufx8 + 2 * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N); - memcpy(out3, outbufx8 + 3 * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N); - memcpy(out4, outbufx8 + 4 * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N); - memcpy(out5, outbufx8 + 5 * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N); - memcpy(out6, outbufx8 + 6 * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N); - memcpy(out7, outbufx8 + 7 * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N); -} - -#define thash_size_variant(name, size) \ - void PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_thashx8_##name(unsigned char *out0, \ - unsigned char *out1, \ - unsigned char *out2, \ - unsigned char *out3, \ - unsigned char *out4, \ - unsigned char *out5, \ - unsigned char *out6, \ - unsigned char *out7, \ - const unsigned char *in0, \ - const unsigned char *in1, \ - const unsigned char *in2, \ - const unsigned char *in3, \ - const unsigned char *in4, \ - const unsigned char *in5, \ - const unsigned char *in6, \ - const unsigned char *in7, \ - const unsigned char *pub_seed, \ - uint32_t addrx8[8*8], \ - const hash_state *state_seeded) { \ - const unsigned int inblocks = (size); \ - uint8_t bufx8[8*(PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_SHA256_ADDR_BYTES + (size)*PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N)]; \ - uint8_t bitmaskx8[8*((size) * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N)]; \ - thashx8(out0, out1, out2, out3, out4, out5, out6, out7, \ - in0, in1, in2, in3, in4, in5, in6, in7, inblocks, \ - pub_seed, addrx8, bufx8, bitmaskx8, state_seeded); \ - } - -thash_size_variant(1, 1) -thash_size_variant(2, 2) -thash_size_variant(WOTS_LEN, PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_WOTS_LEN) -thash_size_variant(FORS_TREES, PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_FORS_TREES) - -#undef thash_size_variant diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_avx2/thashx8.h b/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_avx2/thashx8.h deleted file mode 100644 index 10a5a1cb1d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_avx2/thashx8.h +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_THASHX8_H -#define PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_THASHX8_H - -#include - -#include "hash_state.h" -#include "sha256avx.h" - - -#define thashx8_variant(name) \ - void PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_thashx8_##name( \ - unsigned char *out0, \ - unsigned char *out1, \ - unsigned char *out2, \ - unsigned char *out3, \ - unsigned char *out4, \ - unsigned char *out5, \ - unsigned char *out6, \ - unsigned char *out7, \ - const unsigned char *in0, \ - const unsigned char *in1, \ - const unsigned char *in2, \ - const unsigned char *in3, \ - const unsigned char *in4, \ - const unsigned char *in5, \ - const unsigned char *in6, \ - const unsigned char *in7, \ - const unsigned char *pub_seed, \ - uint32_t addrx8[8*8], \ - const hash_state *state_seeded) - - -thashx8_variant(1); -thashx8_variant(2); -thashx8_variant(WOTS_LEN); -thashx8_variant(FORS_TREES); - -#undef thashx8_variant -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_avx2/utils.c b/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_avx2/utils.c deleted file mode 100644 index c3b52cc2b7..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_avx2/utils.c +++ /dev/null @@ -1,199 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "hash_state.h" -#include "params.h" -#include "thash.h" -#include "utils.h" - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in) { - - /* Iterate over out in decreasing order, for big-endianness. */ - for (size_t i = outlen; i > 0; i--) { - out[i - 1] = in & 0xff; - in = in >> 8; - } -} - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_bytes_to_ull( - const unsigned char *in, size_t inlen) { - unsigned long long retval = 0; - - for (size_t i = 0; i < inlen; i++) { - retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); - } - return retval; -} - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - uint32_t i; - unsigned char buffer[2 * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N]; - - /* If leaf_idx is odd (last bit = 1), current path element is a right child - and auth_path has to go left. Otherwise it is the other way around. */ - if (leaf_idx & 1) { - memcpy(buffer + PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N, leaf, PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N); - } else { - memcpy(buffer, leaf, PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N); - memcpy(buffer + PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N, auth_path, PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N); - } - auth_path += PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N; - - for (i = 0; i < tree_height - 1; i++) { - leaf_idx >>= 1; - idx_offset >>= 1; - /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_set_tree_height(addr, i + 1); - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_set_tree_index( - addr, leaf_idx + idx_offset); - - /* Pick the right or left neighbor, depending on parity of the node. */ - if (leaf_idx & 1) { - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_thash_2( - buffer + PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N); - } else { - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_thash_2( - buffer, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer + PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N, auth_path, PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N); - } - auth_path += PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N; - } - - /* The last iteration is exceptional; we do not copy an auth_path node. */ - leaf_idx >>= 1; - idx_offset >>= 1; - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_set_tree_height(addr, tree_height); - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_set_tree_index( - addr, leaf_idx + idx_offset); - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_thash_2( - root, buffer, pub_seed, addr, hash_state_seeded); -} - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -static void PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_treehash( - unsigned char *root, unsigned char *auth_path, - unsigned char *stack, unsigned int *heights, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - - unsigned int offset = 0; - uint32_t idx; - uint32_t tree_idx; - - for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { - /* Add the next leaf node to the stack. */ - gen_leaf(stack + offset * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N, - sk_seed, pub_seed, idx + idx_offset, tree_addr, - hash_state_seeded); - offset++; - heights[offset - 1] = 0; - - /* If this is a node we need for the auth path.. */ - if ((leaf_idx ^ 0x1) == idx) { - memcpy(auth_path, stack + (offset - 1)*PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N, PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N); - } - - /* While the top-most nodes are of equal height.. */ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { - /* Compute index of the new node, in the next layer. */ - tree_idx = (idx >> (heights[offset - 1] + 1)); - - /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_set_tree_height( - tree_addr, heights[offset - 1] + 1); - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_set_tree_index( - tree_addr, tree_idx + (idx_offset >> (heights[offset - 1] + 1))); - /* Hash the top-most nodes from the stack together. */ - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_thash_2( - stack + (offset - 2)*PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N, stack + (offset - 2)*PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N, - pub_seed, tree_addr, hash_state_seeded); - offset--; - /* Note that the top-most node is now one layer higher. */ - heights[offset - 1]++; - - /* If this is a node we need for the auth path.. */ - if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_path + heights[offset - 1]*PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N, - stack + (offset - 1)*PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N, PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N); - } - } - } - memcpy(root, stack, PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N); -} - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_FORS_HEIGHT + 1)*PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N]; - unsigned int heights[PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_FORS_HEIGHT + 1]; - - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_FORS_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_TREE_HEIGHT + 1)*PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N]; - unsigned int heights[PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_TREE_HEIGHT + 1]; - - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_TREE_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_avx2/utils.h b/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_avx2/utils.h deleted file mode 100644 index 18175fa0a9..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_avx2/utils.h +++ /dev/null @@ -1,64 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_UTILS_H -#define PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_UTILS_H - -#include "hash_state.h" -#include "params.h" -#include -#include - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in); - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_bytes_to_ull( - const unsigned char *in, size_t inlen); - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -void PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_avx2/utilsx8.c b/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_avx2/utilsx8.c deleted file mode 100644 index 470821ae96..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_avx2/utilsx8.c +++ /dev/null @@ -1,172 +0,0 @@ -#include - -#include "address.h" -#include "params.h" -#include "thashx8.h" -#include "utils.h" - -#include "utilsx8.h" - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -static void treehashx8(unsigned char *rootx8, unsigned char *auth_pathx8, - unsigned char *stackx8, unsigned int *heights, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t leaf_idx[8], uint32_t idx_offset[8], - uint32_t tree_height, - void (*gen_leafx8)( - unsigned char * /* leaf0 */, - unsigned char * /* leaf1 */, - unsigned char * /* leaf2 */, - unsigned char * /* leaf3 */, - unsigned char * /* leaf4 */, - unsigned char * /* leaf5 */, - unsigned char * /* leaf6 */, - unsigned char * /* leaf7 */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx0 */, - uint32_t /* addr_idx1 */, - uint32_t /* addr_idx2 */, - uint32_t /* addr_idx3 */, - uint32_t /* addr_idx4 */, - uint32_t /* addr_idx5 */, - uint32_t /* addr_idx6 */, - uint32_t /* addr_idx7 */, - const uint32_t[8] /* tree_addr */, - const hash_state * /* state_seeded */), - uint32_t tree_addrx8[8 * 8], - const hash_state *state_seeded) { - unsigned int offset = 0; - uint32_t idx; - uint32_t tree_idx; - unsigned int j; - - for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { - /* Add the next leaf node to the stack. */ - gen_leafx8(stackx8 + 0 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N + offset * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N, - stackx8 + 1 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N + offset * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N, - stackx8 + 2 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N + offset * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N, - stackx8 + 3 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N + offset * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N, - stackx8 + 4 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N + offset * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N, - stackx8 + 5 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N + offset * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N, - stackx8 + 6 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N + offset * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N, - stackx8 + 7 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N + offset * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N, - sk_seed, pub_seed, - idx + idx_offset[0], - idx + idx_offset[1], - idx + idx_offset[2], - idx + idx_offset[3], - idx + idx_offset[4], - idx + idx_offset[5], - idx + idx_offset[6], - idx + idx_offset[7], - tree_addrx8, - state_seeded); - offset++; - heights[offset - 1] = 0; - - /* If this is a node we need for the auth path.. */ - for (j = 0; j < 8; j++) { - if ((leaf_idx[j] ^ 0x1) == idx) { - memcpy(auth_pathx8 + j * tree_height * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N, - stackx8 + j * (tree_height + 1)*PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N + (offset - 1)*PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N, PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N); - } - } - - /* While the top-most nodes are of equal height.. */ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { - /* Compute index of the new node, in the next layer. */ - tree_idx = (idx >> (heights[offset - 1] + 1)); - - /* Set the address of the node we're creating. */ - for (j = 0; j < 8; j++) { - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_set_tree_height(tree_addrx8 + j * 8, heights[offset - 1] + 1); - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_set_tree_index(tree_addrx8 + j * 8, - tree_idx + (idx_offset[j] >> (heights[offset - 1] + 1))); - } - /* Hash the top-most nodes from the stack together. */ - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_thashx8_2(stackx8 + 0 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N, - stackx8 + 1 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N, - stackx8 + 2 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N, - stackx8 + 3 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N, - stackx8 + 4 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N, - stackx8 + 5 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N, - stackx8 + 6 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N, - stackx8 + 7 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N, - stackx8 + 0 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N, - stackx8 + 1 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N, - stackx8 + 2 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N, - stackx8 + 3 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N, - stackx8 + 4 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N, - stackx8 + 5 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N, - stackx8 + 6 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N, - stackx8 + 7 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N, - pub_seed, tree_addrx8, state_seeded); - offset--; - /* Note that the top-most node is now one layer higher. */ - heights[offset - 1]++; - - /* If this is a node we need for the auth path.. */ - for (j = 0; j < 8; j++) { - if (((leaf_idx[j] >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_pathx8 + j * tree_height * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N + heights[offset - 1]*PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N, - stackx8 + j * (tree_height + 1)*PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N + (offset - 1)*PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N, PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N); - } - } - } - } - - for (j = 0; j < 8; j++) { - memcpy(rootx8 + j * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N, stackx8 + j * (tree_height + 1)*PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N, PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N); - } -} - -/* The wrappers below ensure we used fixed-size buffers on the stack (no VLAs) */ - - -#define treehashx8_variant(name, size) \ - void PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_treehashx8_##name( \ - unsigned char *rootx8, unsigned char *auth_pathx8, \ - const unsigned char *sk_seed, const unsigned char *pub_seed, \ - const uint32_t leaf_idx[8], uint32_t idx_offset[8], \ - void (*gen_leafx8)( \ - unsigned char* /* leaf0 */, \ - unsigned char* /* leaf1 */, \ - unsigned char* /* leaf2 */, \ - unsigned char* /* leaf3 */, \ - unsigned char* /* leaf4 */, \ - unsigned char* /* leaf5 */, \ - unsigned char* /* leaf6 */, \ - unsigned char* /* leaf7 */, \ - const unsigned char* /* sk_seed */, \ - const unsigned char* /* pub_seed */, \ - uint32_t /* addr_idx0 */, \ - uint32_t /* addr_idx1 */, \ - uint32_t /* addr_idx2 */, \ - uint32_t /* addr_idx3 */, \ - uint32_t /* addr_idx4 */, \ - uint32_t /* addr_idx5 */, \ - uint32_t /* addr_idx6 */, \ - uint32_t /* addr_idx7 */, \ - const uint32_t[8] /* tree_addr */, \ - const hash_state* /* state_seeded */), \ - uint32_t tree_addrx8[8*8], \ - const hash_state *state_seeded) \ - { \ - const uint32_t tree_height = (size); \ - unsigned char stackx8[8*((size) + 1)*PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N]; \ - unsigned int heights[(size) + 1]; \ - treehashx8(rootx8, auth_pathx8, stackx8, heights, sk_seed, pub_seed, \ - leaf_idx, idx_offset, tree_height, gen_leafx8, tree_addrx8, state_seeded); \ - } - -treehashx8_variant(FORS_HEIGHT, PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_FORS_HEIGHT) - -#undef treehashx8_variant diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_avx2/utilsx8.h b/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_avx2/utilsx8.h deleted file mode 100644 index 69aa1efe45..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_avx2/utilsx8.h +++ /dev/null @@ -1,46 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_UTILSX8_H -#define PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_UTILSX8_H - -#include - -#include "hash_state.h" -#include "params.h" - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ - -void PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_treehashx8_FORS_HEIGHT( - unsigned char *rootx8, unsigned char *auth_pathx8, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t leaf_idx[8], uint32_t idx_offset[8], - void (*gen_leafx8)( - unsigned char * /* leaf0 */, - unsigned char * /* leaf1 */, - unsigned char * /* leaf2 */, - unsigned char * /* leaf3 */, - unsigned char * /* leaf4 */, - unsigned char * /* leaf5 */, - unsigned char * /* leaf6 */, - unsigned char * /* leaf7 */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx0 */, - uint32_t /* addr_idx1 */, - uint32_t /* addr_idx2 */, - uint32_t /* addr_idx3 */, - uint32_t /* addr_idx4 */, - uint32_t /* addr_idx5 */, - uint32_t /* addr_idx6 */, - uint32_t /* addr_idx7 */, - const uint32_t[8] /* tree_addr */, - const hash_state * /* state_seeded */), - uint32_t tree_addrx8[8 * 8], - const hash_state *state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_avx2/wots.c b/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_avx2/wots.c deleted file mode 100644 index 7ce8538cbc..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_avx2/wots.c +++ /dev/null @@ -1,240 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "hash_state.h" -#include "hashx8.h" -#include "params.h" -#include "thash.h" -#include "thashx8.h" -#include "utils.h" -#include "wots.h" - -// TODO clarify address expectations, and make them more uniform. -// TODO i.e. do we expect types to be set already? -// TODO and do we expect modifications or copies? - -/** - * Computes the starting value for a chain, i.e. the secret key. - * Expects the address to be complete up to the chain address. - */ -static void wots_gen_sk(unsigned char *sk, const unsigned char *sk_seed, - uint32_t wots_addr[8], const hash_state *state_seeded) { - /* Make sure that the hash address is actually zeroed. */ - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_set_hash_addr(wots_addr, 0); - - /* Generate sk element. */ - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_prf_addr(sk, sk_seed, wots_addr, state_seeded); -} - -/** - * 8-way parallel version of wots_gen_sk; expects 8x as much space in sk - */ -static void wots_gen_skx8(unsigned char *skx8, const unsigned char *sk_seed, - uint32_t wots_addrx8[8 * 8]) { - unsigned int j; - - /* Make sure that the hash address is actually zeroed. */ - for (j = 0; j < 8; j++) { - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_set_hash_addr(wots_addrx8 + j * 8, 0); - } - - /* Generate sk element. */ - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_prf_addrx8(skx8 + 0 * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N, - skx8 + 1 * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N, - skx8 + 2 * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N, - skx8 + 3 * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N, - skx8 + 4 * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N, - skx8 + 5 * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N, - skx8 + 6 * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N, - skx8 + 7 * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N, - sk_seed, wots_addrx8); -} - -/** - * Computes the chaining function. - * out and in have to be n-byte arrays. - * - * Interprets in as start-th value of the chain. - * addr has to contain the address of the chain. - */ -static void gen_chain(unsigned char *out, const unsigned char *in, - unsigned int start, unsigned int steps, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *state_seeded) { - uint32_t i; - - /* Initialize out with the value at position 'start'. */ - memcpy(out, in, PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N); - - /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_WOTS_W; i++) { - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_set_hash_addr(addr, i); - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_thash_1(out, out, pub_seed, addr, state_seeded); - } -} - -/** - * 8-way parallel version of gen_chain; expects 8x as much space in out, and - * 8x as much space in inx8. Assumes start and step identical across chains. - */ -static void gen_chainx8(unsigned char *outx8, const unsigned char *inx8, - unsigned int start, unsigned int steps, - const unsigned char *pub_seed, uint32_t addrx8[8 * 8], - const hash_state *state_seeded) { - uint32_t i; - unsigned int j; - - /* Initialize outx8 with the value at position 'start'. */ - memcpy(outx8, inx8, 8 * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N); - - /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_WOTS_W; i++) { - for (j = 0; j < 8; j++) { - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_set_hash_addr(addrx8 + j * 8, i); - } - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_thashx8_1(outx8 + 0 * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N, - outx8 + 1 * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N, - outx8 + 2 * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N, - outx8 + 3 * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N, - outx8 + 4 * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N, - outx8 + 5 * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N, - outx8 + 6 * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N, - outx8 + 7 * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N, - outx8 + 0 * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N, - outx8 + 1 * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N, - outx8 + 2 * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N, - outx8 + 3 * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N, - outx8 + 4 * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N, - outx8 + 5 * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N, - outx8 + 6 * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N, - outx8 + 7 * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N, - pub_seed, addrx8, state_seeded); - } -} - -/** - * base_w algorithm as described in draft. - * Interprets an array of bytes as integers in base w. - * This only works when log_w is a divisor of 8. - */ -static void base_w(unsigned int *output, const int out_len, const unsigned char *input) { - int in = 0; - int out = 0; - unsigned char total = 0; - int bits = 0; - int consumed; - - for (consumed = 0; consumed < out_len; consumed++) { - if (bits == 0) { - total = input[in]; - in++; - bits += 8; - } - bits -= PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_WOTS_LOGW; - output[out] = (unsigned int)(total >> bits) & (PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_WOTS_W - 1); - out++; - } -} - -/* Computes the WOTS+ checksum over a message (in base_w). */ -static void wots_checksum(unsigned int *csum_base_w, const unsigned int *msg_base_w) { - unsigned int csum = 0; - unsigned char csum_bytes[(PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_WOTS_LEN2 * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_WOTS_LOGW + 7) / 8]; - unsigned int i; - - /* Compute checksum. */ - for (i = 0; i < PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_WOTS_LEN1; i++) { - csum += PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_WOTS_W - 1 - msg_base_w[i]; - } - - /* Convert checksum to base_w. */ - /* Make sure expected empty zero bits are the least significant bits. */ - csum = csum << (8 - ((PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_WOTS_LEN2 * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_WOTS_LOGW) % 8)); - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); - base_w(csum_base_w, PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_WOTS_LEN2, csum_bytes); -} - -/* Takes a message and derives the matching chain lengths. */ -static void chain_lengths(unsigned int *lengths, const unsigned char *msg) { - base_w(lengths, PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_WOTS_LEN1, msg); - wots_checksum(lengths + PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_WOTS_LEN1, lengths); -} - -/** - * WOTS key generation. Takes a 32 byte sk_seed, expands it to WOTS private key - * elements and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_wots_gen_pk(unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *state_seeded) { - uint32_t i; - unsigned int j; - - uint32_t addrx8[8 * 8]; - unsigned char pkbuf[8 * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N]; - - for (j = 0; j < 8; j++) { - memcpy(addrx8 + j * 8, addr, sizeof(uint32_t) * 8); - } - - /* The last iteration typically does not have complete set of 4 chains, - but because we use pkbuf, this is not an issue -- we still do as many - in parallel as possible. */ - for (i = 0; i < ((PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_WOTS_LEN + 7) & ~0x7); i += 8) { - for (j = 0; j < 8; j++) { - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_set_chain_addr(addrx8 + j * 8, i + j); - } - wots_gen_skx8(pkbuf, sk_seed, addrx8); - gen_chainx8(pkbuf, pkbuf, 0, PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_WOTS_W - 1, pub_seed, addrx8, state_seeded); - for (j = 0; j < 8; j++) { - if (i + j < PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_WOTS_LEN) { - memcpy(pk + (i + j)*PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N, pkbuf + j * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N, PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N); - } - } - } -} - -/** - * Takes a n-byte message and the 32-byte sk_see to compute a signature 'sig'. - */ -void PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_wots_sign(unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_WOTS_LEN; i++) { - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_set_chain_addr(addr, i); - wots_gen_sk(sig + i * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N, sk_seed, addr, state_seeded); - gen_chain(sig + i * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N, sig + i * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N, 0, lengths[i], pub_seed, addr, state_seeded); - } -} - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_WOTS_LEN; i++) { - PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_set_chain_addr(addr, i); - gen_chain(pk + i * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N, sig + i * PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_N, - lengths[i], PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_WOTS_W - 1 - lengths[i], pub_seed, addr, state_seeded); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_avx2/wots.h b/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_avx2/wots.h deleted file mode 100644 index a0c7d52223..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_avx2/wots.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_WOTS_H -#define PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_WOTS_H - -#include "hash_state.h" -#include "params.h" -#include - -/** - * WOTS key generation. Takes a 32 byte seed for the private key, expands it to - * a full WOTS private key and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_wots_gen_pk( - unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -/** - * Takes a n-byte message and the 32-byte seed for the private key to compute a - * signature that is placed at 'sig'. - */ -void PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_wots_sign( - unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *hash_state_seeded); - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHA256128FROBUST_AVX2_wots_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_clean/LICENSE b/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_clean/LICENSE deleted file mode 100644 index 670154e353..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_clean/LICENSE +++ /dev/null @@ -1,116 +0,0 @@ -CC0 1.0 Universal - -Statement of Purpose - -The laws of most jurisdictions throughout the world automatically confer -exclusive Copyright and Related Rights (defined below) upon the creator and -subsequent owner(s) (each and all, an "owner") of an original work of -authorship and/or a database (each, a "Work"). - -Certain owners wish to permanently relinquish those rights to a Work for the -purpose of contributing to a commons of creative, cultural and scientific -works ("Commons") that the public can reliably and without fear of later -claims of infringement build upon, modify, incorporate in other works, reuse -and redistribute as freely as possible in any form whatsoever and for any -purposes, including without limitation commercial purposes. These owners may -contribute to the Commons to promote the ideal of a free culture and the -further production of creative, cultural and scientific works, or to gain -reputation or greater distribution for their Work in part through the use and -efforts of others. - -For these and/or other purposes and motivations, and without any expectation -of additional consideration or compensation, the person associating CC0 with a -Work (the "Affirmer"), to the extent that he or she is an owner of Copyright -and Related Rights in the Work, voluntarily elects to apply CC0 to the Work -and publicly distribute the Work under its terms, with knowledge of his or her -Copyright and Related Rights in the Work and the meaning and intended legal -effect of CC0 on those rights. - -1. Copyright and Related Rights. A Work made available under CC0 may be -protected by copyright and related or neighboring rights ("Copyright and -Related Rights"). Copyright and Related Rights include, but are not limited -to, the following: - - i. the right to reproduce, adapt, distribute, perform, display, communicate, - and translate a Work; - - ii. moral rights retained by the original author(s) and/or performer(s); - - iii. publicity and privacy rights pertaining to a person's image or likeness - depicted in a Work; - - iv. rights protecting against unfair competition in regards to a Work, - subject to the limitations in paragraph 4(a), below; - - v. rights protecting the extraction, dissemination, use and reuse of data in - a Work; - - vi. database rights (such as those arising under Directive 96/9/EC of the - European Parliament and of the Council of 11 March 1996 on the legal - protection of databases, and under any national implementation thereof, - including any amended or successor version of such directive); and - - vii. other similar, equivalent or corresponding rights throughout the world - based on applicable law or treaty, and any national implementations thereof. - -2. Waiver. To the greatest extent permitted by, but not in contravention of, -applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and -unconditionally waives, abandons, and surrenders all of Affirmer's Copyright -and Related Rights and associated claims and causes of action, whether now -known or unknown (including existing as well as future claims and causes of -action), in the Work (i) in all territories worldwide, (ii) for the maximum -duration provided by applicable law or treaty (including future time -extensions), (iii) in any current or future medium and for any number of -copies, and (iv) for any purpose whatsoever, including without limitation -commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes -the Waiver for the benefit of each member of the public at large and to the -detriment of Affirmer's heirs and successors, fully intending that such Waiver -shall not be subject to revocation, rescission, cancellation, termination, or -any other legal or equitable action to disrupt the quiet enjoyment of the Work -by the public as contemplated by Affirmer's express Statement of Purpose. - -3. Public License Fallback. Should any part of the Waiver for any reason be -judged legally invalid or ineffective under applicable law, then the Waiver -shall be preserved to the maximum extent permitted taking into account -Affirmer's express Statement of Purpose. In addition, to the extent the Waiver -is so judged Affirmer hereby grants to each affected person a royalty-free, -non transferable, non sublicensable, non exclusive, irrevocable and -unconditional license to exercise Affirmer's Copyright and Related Rights in -the Work (i) in all territories worldwide, (ii) for the maximum duration -provided by applicable law or treaty (including future time extensions), (iii) -in any current or future medium and for any number of copies, and (iv) for any -purpose whatsoever, including without limitation commercial, advertising or -promotional purposes (the "License"). The License shall be deemed effective as -of the date CC0 was applied by Affirmer to the Work. Should any part of the -License for any reason be judged legally invalid or ineffective under -applicable law, such partial invalidity or ineffectiveness shall not -invalidate the remainder of the License, and in such case Affirmer hereby -affirms that he or she will not (i) exercise any of his or her remaining -Copyright and Related Rights in the Work or (ii) assert any associated claims -and causes of action with respect to the Work, in either case contrary to -Affirmer's express Statement of Purpose. - -4. Limitations and Disclaimers. - - a. No trademark or patent rights held by Affirmer are waived, abandoned, - surrendered, licensed or otherwise affected by this document. - - b. Affirmer offers the Work as-is and makes no representations or warranties - of any kind concerning the Work, express, implied, statutory or otherwise, - including without limitation warranties of title, merchantability, fitness - for a particular purpose, non infringement, or the absence of latent or - other defects, accuracy, or the present or absence of errors, whether or not - discoverable, all to the greatest extent permissible under applicable law. - - c. Affirmer disclaims responsibility for clearing rights of other persons - that may apply to the Work or any use thereof, including without limitation - any person's Copyright and Related Rights in the Work. Further, Affirmer - disclaims responsibility for obtaining any necessary consents, permissions - or other rights required for any use of the Work. - - d. Affirmer understands and acknowledges that Creative Commons is not a - party to this document and has no duty or obligation with respect to this - CC0 or use of the Work. - -For more information, please see - diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_clean/address.c b/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_clean/address.c deleted file mode 100644 index eff46d7f4e..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_clean/address.c +++ /dev/null @@ -1,78 +0,0 @@ -#include - -#include "address.h" -#include "params.h" -#include "utils.h" - -void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]) { - int i; - - for (i = 0; i < 8; i++) { - PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_ull_to_bytes( - bytes + i * 4, 4, addr[i]); - } -} - -void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_set_layer_addr( - uint32_t addr[8], uint32_t layer) { - addr[0] = layer; -} - -void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_set_tree_addr( - uint32_t addr[8], uint64_t tree) { - addr[1] = 0; - addr[2] = (uint32_t) (tree >> 32); - addr[3] = (uint32_t) tree; -} - -void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_set_type( - uint32_t addr[8], uint32_t type) { - addr[4] = type; -} - -void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; -} - -/* These functions are used for OTS addresses. */ - -void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_set_keypair_addr( - uint32_t addr[8], uint32_t keypair) { - addr[5] = keypair; -} - -void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; - out[5] = in[5]; -} - -void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_set_chain_addr( - uint32_t addr[8], uint32_t chain) { - addr[6] = chain; -} - -void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_set_hash_addr( - uint32_t addr[8], uint32_t hash) { - addr[7] = hash; -} - -/* These functions are used for all hash tree addresses (including FORS). */ - -void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_set_tree_height( - uint32_t addr[8], uint32_t tree_height) { - addr[6] = tree_height; -} - -void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_set_tree_index( - uint32_t addr[8], uint32_t tree_index) { - addr[7] = tree_index; -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_clean/address.h b/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_clean/address.h deleted file mode 100644 index 33aae431d5..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_clean/address.h +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_ADDRESS_H -#define PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_ADDRESS_H - -#include - -#define PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_ADDR_TYPE_WOTS 0 -#define PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_ADDR_TYPE_WOTSPK 1 -#define PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_ADDR_TYPE_HASHTREE 2 -#define PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_ADDR_TYPE_FORSTREE 3 -#define PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_ADDR_TYPE_FORSPK 4 - -void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]); - -void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_set_layer_addr( - uint32_t addr[8], uint32_t layer); - -void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_set_tree_addr( - uint32_t addr[8], uint64_t tree); - -void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_set_type( - uint32_t addr[8], uint32_t type); - -/* Copies the layer and tree part of one address into the other */ -void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for WOTS and FORS addresses. */ - -void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_set_keypair_addr( - uint32_t addr[8], uint32_t keypair); - -void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_set_chain_addr( - uint32_t addr[8], uint32_t chain); - -void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_set_hash_addr( - uint32_t addr[8], uint32_t hash); - -void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for all hash tree addresses (including FORS). */ - -void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_set_tree_height( - uint32_t addr[8], uint32_t tree_height); - -void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_set_tree_index( - uint32_t addr[8], uint32_t tree_index); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_clean/api.h b/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_clean/api.h deleted file mode 100644 index b446d6d24e..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_clean/api.h +++ /dev/null @@ -1,81 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_API_H -#define PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_API_H - -#include -#include - - - -#define PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_CRYPTO_ALGNAME "SPHINCS+" - -#define PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_CRYPTO_SECRETKEYBYTES 64 -#define PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_CRYPTO_PUBLICKEYBYTES 32 -#define PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_CRYPTO_BYTES 17088 -#define PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_CRYPTO_SEEDBYTES 48 - - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_clean/fors.c b/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_clean/fors.c deleted file mode 100644 index 82d7d3db5b..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_clean/fors.c +++ /dev/null @@ -1,161 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "fors.h" -#include "hash.h" -#include "hash_state.h" -#include "thash.h" -#include "utils.h" - -static void fors_gen_sk(unsigned char *sk, const unsigned char *sk_seed, - uint32_t fors_leaf_addr[8], const hash_state *hash_state_seeded) { - PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_prf_addr( - sk, sk_seed, fors_leaf_addr, hash_state_seeded); -} - -static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, - const unsigned char *pub_seed, - uint32_t fors_leaf_addr[8], - const hash_state *hash_state_seeded) { - PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_thash_1( - leaf, sk, pub_seed, fors_leaf_addr, hash_state_seeded); -} - -static void fors_gen_leaf(unsigned char *leaf, const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx, const uint32_t fors_tree_addr[8], - const hash_state *hash_state_seeded) { - uint32_t fors_leaf_addr[8] = {0}; - - /* Only copy the parts that must be kept in fors_leaf_addr. */ - PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_copy_keypair_addr( - fors_leaf_addr, fors_tree_addr); - PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_set_type( - fors_leaf_addr, PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_set_tree_index( - fors_leaf_addr, addr_idx); - - fors_gen_sk(leaf, sk_seed, fors_leaf_addr, hash_state_seeded); - fors_sk_to_leaf(leaf, leaf, pub_seed, fors_leaf_addr, hash_state_seeded); -} - -/** - * Interprets m as PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_FORS_HEIGHT-bit unsigned integers. - * Assumes m contains at least PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_FORS_TREES bits. - * Assumes indices has space for PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_FORS_TREES integers. - */ -static void message_to_indices(uint32_t *indices, const unsigned char *m) { - unsigned int i, j; - unsigned int offset = 0; - - for (i = 0; i < PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_FORS_TREES; i++) { - indices[i] = 0; - for (j = 0; j < PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_FORS_HEIGHT; j++) { - indices[i] ^= (((uint32_t)m[offset >> 3] >> (offset & 0x7)) & 0x1) << j; - offset++; - } - } -} - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_fors_sign( - unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *hash_state_seeded) { - uint32_t indices[PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_FORS_TREES]; - unsigned char roots[PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_FORS_TREES * PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_N]; - uint32_t fors_tree_addr[8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_copy_keypair_addr( - fors_tree_addr, fors_addr); - PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_copy_keypair_addr( - fors_pk_addr, fors_addr); - - PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_set_type( - fors_tree_addr, PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_set_type( - fors_pk_addr, PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_FORS_TREES; i++) { - idx_offset = i * (1 << PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_FORS_HEIGHT); - - PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_set_tree_height( - fors_tree_addr, 0); - PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_set_tree_index( - fors_tree_addr, indices[i] + idx_offset); - - /* Include the secret key part that produces the selected leaf node. */ - fors_gen_sk(sig, sk_seed, fors_tree_addr, hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_N; - - /* Compute the authentication path for this leaf node. */ - PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_treehash_FORS_HEIGHT( - roots + i * PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_N, sig, sk_seed, pub_seed, - indices[i], idx_offset, fors_gen_leaf, fors_tree_addr, - hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_N * PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_thash_FORS_TREES( - pk, roots, pub_seed, fors_pk_addr, hash_state_seeded); -} - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_fors_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, const uint32_t fors_addr[8], - const hash_state *hash_state_seeded) { - uint32_t indices[PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_FORS_TREES]; - unsigned char roots[PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_FORS_TREES * PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_N]; - unsigned char leaf[PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_N]; - uint32_t fors_tree_addr[8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_copy_keypair_addr(fors_tree_addr, fors_addr); - PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_copy_keypair_addr(fors_pk_addr, fors_addr); - - PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_set_type(fors_tree_addr, PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_set_type(fors_pk_addr, PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_FORS_TREES; i++) { - idx_offset = i * (1 << PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_FORS_HEIGHT); - - PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_set_tree_height(fors_tree_addr, 0); - PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Derive the leaf from the included secret key part. */ - fors_sk_to_leaf(leaf, sig, pub_seed, fors_tree_addr, hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_N; - - /* Derive the corresponding root node of this tree. */ - PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_compute_root(roots + i * PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_N, leaf, indices[i], idx_offset, sig, - PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_FORS_HEIGHT, pub_seed, fors_tree_addr, hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_N * PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_thash_FORS_TREES(pk, roots, pub_seed, fors_pk_addr, hash_state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_clean/fors.h b/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_clean/fors.h deleted file mode 100644 index ee11d3ead6..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_clean/fors.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_FORS_H -#define PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_FORS_H - -#include - -#include "hash_state.h" -#include "params.h" - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_fors_sign( - unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *hash_state_seeded); - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_fors_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, const uint32_t fors_addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_clean/hash.h b/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_clean/hash.h deleted file mode 100644 index 8d2071f211..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_clean/hash.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_HASH_H -#define PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_HASH_H - -#include "hash_state.h" - -#include -#include - -void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_initialize_hash_function( - hash_state *hash_state_seeded, - const unsigned char *pub_seed, const unsigned char *sk_seed); - -void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_destroy_hash_function(hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_clean/hash_sha256.c b/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_clean/hash_sha256.c deleted file mode 100644 index 65e799073e..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_clean/hash_sha256.c +++ /dev/null @@ -1,162 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "utils.h" - -#include "sha2.h" -#include "sha256.h" - -/* For SHA256, there is no immediate reason to initialize at the start, - so this function is an empty operation. */ -void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_initialize_hash_function( - hash_state *hash_state_seeded, - const unsigned char *pub_seed, const unsigned char *sk_seed) { - PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_seed_state(hash_state_seeded, pub_seed); - (void)sk_seed; /* Suppress an 'unused parameter' warning. */ -} - -/* Clean up hash state */ -void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_destroy_hash_function(hash_state *hash_state_seeded) { - sha256_inc_ctx_release(hash_state_seeded); -} - -/* - * Computes PRF(key, addr), given a secret key of PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_N bytes and an address - */ -void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded) { - unsigned char buf[PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_N + PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_SHA256_ADDR_BYTES]; - unsigned char outbuf[PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_SHA256_OUTPUT_BYTES]; - - memcpy(buf, key, PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_N); - PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_compress_address(buf + PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_N, addr); - - sha256(outbuf, buf, PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_N + PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_SHA256_ADDR_BYTES); - memcpy(out, outbuf, PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_N); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} - -/** - * Computes the message-dependent randomness R, using a secret seed as a key - * for HMAC, and an optional randomization value prefixed to the message. - * This requires m to have at least PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_SHA256_BLOCK_BYTES + PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_N space - * available in front of the pointer, i.e. before the message to use for the - * prefix. This is necessary to prevent having to move the message around (and - * allocate memory for it). - */ -void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, const hash_state *hash_state_seeded) { - unsigned char buf[PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_SHA256_BLOCK_BYTES + PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_SHA256_OUTPUT_BYTES]; - sha256ctx state; - int i; - - /* This implements HMAC-SHA256 */ - for (i = 0; i < PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_N; i++) { - buf[i] = 0x36 ^ sk_prf[i]; - } - memset(buf + PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_N, 0x36, PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_N); - - sha256_inc_init(&state); - sha256_inc_blocks(&state, buf, 1); - - memcpy(buf, optrand, PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_N); - - /* If optrand + message cannot fill up an entire block */ - if (PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_N + mlen < PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_SHA256_BLOCK_BYTES) { - memcpy(buf + PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_N, m, mlen); - sha256_inc_finalize(buf + PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_SHA256_BLOCK_BYTES, &state, - buf, mlen + PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_N); - } - /* Otherwise first fill a block, so that finalize only uses the message */ - else { - memcpy(buf + PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_N, m, PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_N); - sha256_inc_blocks(&state, buf, 1); - - m += PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_N; - mlen -= PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_N; - sha256_inc_finalize(buf + PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_SHA256_BLOCK_BYTES, &state, m, mlen); - } - - for (i = 0; i < PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_N; i++) { - buf[i] = 0x5c ^ sk_prf[i]; - } - memset(buf + PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_N, 0x5c, PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_N); - - sha256(buf, buf, PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_SHA256_BLOCK_BYTES + PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_SHA256_OUTPUT_BYTES); - memcpy(R, buf, PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_N); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} - -/** - * Computes the message hash using R, the public key, and the message. - * Outputs the message digest and the index of the leaf. The index is split in - * the tree index and the leaf index, for convenient copying to an address. - */ -void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded) { -#define PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_TREE_BITS (PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_TREE_HEIGHT * (PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_D - 1)) -#define PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_TREE_BYTES ((PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_TREE_BITS + 7) / 8) -#define PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_LEAF_BITS PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_TREE_HEIGHT -#define PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_LEAF_BYTES ((PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_LEAF_BITS + 7) / 8) -#define PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_DGST_BYTES (PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_FORS_MSG_BYTES + PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_TREE_BYTES + PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_LEAF_BYTES) - - unsigned char seed[PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_SHA256_OUTPUT_BYTES + 4]; - - /* Round to nearest multiple of PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_SHA256_BLOCK_BYTES */ -#define PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_INBLOCKS (((PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_N + PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_PK_BYTES + PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_SHA256_BLOCK_BYTES - 1) & \ - -PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_SHA256_BLOCK_BYTES) / PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_SHA256_BLOCK_BYTES) - unsigned char inbuf[PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_INBLOCKS * PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_SHA256_BLOCK_BYTES]; - - unsigned char buf[PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_DGST_BYTES]; - unsigned char *bufp = buf; - sha256ctx state; - - sha256_inc_init(&state); - - memcpy(inbuf, R, PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_N); - memcpy(inbuf + PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_N, pk, PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_PK_BYTES); - - /* If R + pk + message cannot fill up an entire block */ - if (PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_N + PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_PK_BYTES + mlen < PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_INBLOCKS * PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_SHA256_BLOCK_BYTES) { - memcpy(inbuf + PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_N + PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_PK_BYTES, m, mlen); - sha256_inc_finalize(seed, &state, inbuf, PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_N + PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_PK_BYTES + mlen); - } - /* Otherwise first fill a block, so that finalize only uses the message */ - else { - memcpy(inbuf + PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_N + PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_PK_BYTES, m, - PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_INBLOCKS * PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_N - PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_PK_BYTES); - sha256_inc_blocks(&state, inbuf, PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_INBLOCKS); - - m += PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_INBLOCKS * PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_N - PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_PK_BYTES; - mlen -= PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_INBLOCKS * PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_N - PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_PK_BYTES; - sha256_inc_finalize(seed, &state, m, mlen); - } - - /* By doing this in two steps, we prevent hashing the message twice; - otherwise each iteration in MGF1 would hash the message again. */ - PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_mgf1(bufp, PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_DGST_BYTES, seed, PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_SHA256_OUTPUT_BYTES); - - memcpy(digest, bufp, PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_FORS_MSG_BYTES); - bufp += PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_FORS_MSG_BYTES; - - *tree = PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_bytes_to_ull(bufp, PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_TREE_BYTES); - *tree &= (~(uint64_t)0) >> (64 - PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_TREE_BITS); - bufp += PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_TREE_BYTES; - - *leaf_idx = (uint32_t)PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_bytes_to_ull( - bufp, PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_LEAF_BYTES); - *leaf_idx &= (~(uint32_t)0) >> (32 - PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_LEAF_BITS); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_clean/hash_state.h b/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_clean/hash_state.h deleted file mode 100644 index 19fc335e27..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_clean/hash_state.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef SPX_HASH_STATE_H -#define SPX_HASH_STATE_H - -/** - * Defines the type of the hash function state. - * - * Don't be fooled into thinking this instance of SPHINCS+ isn't stateless! - * - * From Section 7.2.2 from the SPHINCS+ round-2 specification: - * - * Each of the instances of the tweakable hash function take PK.seed as its - * first input, which is constant for a given key pair – and, thus, across - * a single signature. This leads to a lot of redundant computation. To remedy - * this, we pad PK.seed to the length of a full 64-byte SHA-256 input block. - * Because of the Merkle-DamgÃ¥rd construction that underlies SHA-256, this - * allows for reuse of the intermediate SHA-256 state after the initial call to - * the compression function which improves performance. - * - * We pass this hash state around in functions, because otherwise we need to - * have a global variable. - */ - -#include "sha2.h" -#define hash_state sha256ctx - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_clean/params.h b/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_clean/params.h deleted file mode 100644 index 4974288134..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_clean/params.h +++ /dev/null @@ -1,53 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_PARAMS_H -#define PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_PARAMS_H - -/* Hash output length in bytes. */ -#define PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_N 16 -/* Height of the hypertree. */ -#define PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_FULL_HEIGHT 66 -/* Number of subtree layer. */ -#define PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_D 22 -/* FORS tree dimensions. */ -#define PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_FORS_HEIGHT 6 -#define PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_FORS_TREES 33 -/* Winternitz parameter, */ -#define PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_WOTS_W 16 - -/* The hash function is defined by linking a different hash.c file, as opposed - to setting a #define constant. */ - -/* For clarity */ -#define PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_ADDR_BYTES 32 - -/* WOTS parameters. */ -#define PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_WOTS_LOGW 4 - -#define PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_WOTS_LEN1 (8 * PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_N / PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_WOTS_LOGW) - -/* PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#define PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_WOTS_LEN2 3 - -#define PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_WOTS_LEN (PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_WOTS_LEN1 + PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_WOTS_LEN2) -#define PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_WOTS_BYTES (PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_WOTS_LEN * PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_N) -#define PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_WOTS_PK_BYTES PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_WOTS_BYTES - -/* Subtree size. */ -#define PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_TREE_HEIGHT (PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_FULL_HEIGHT / PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_D) - -/* FORS parameters. */ -#define PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_FORS_MSG_BYTES ((PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_FORS_TREES + 7) / 8) -#define PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_FORS_BYTES ((PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_FORS_HEIGHT + 1) * PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_FORS_TREES * PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_N) -#define PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_FORS_PK_BYTES PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_N - -/* Resulting SPX sizes. */ -#define PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_BYTES (PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_N + PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_FORS_BYTES + PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_D * PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_WOTS_BYTES +\ - PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_FULL_HEIGHT * PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_N) -#define PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_PK_BYTES (2 * PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_N) -#define PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_SK_BYTES (2 * PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_N + PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_PK_BYTES) - -/* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ -#define PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_OPTRAND_BYTES 32 - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_clean/sha256.c b/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_clean/sha256.c deleted file mode 100644 index d1856e518d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_clean/sha256.c +++ /dev/null @@ -1,71 +0,0 @@ -/* Based on the public domain implementation in - * crypto_hash/sha512/ref/ from http://bench.cr.yp.to/supercop.html - * by D. J. Bernstein */ - -#include -#include -#include - -#include "sha2.h" -#include "sha256.h" -#include "utils.h" - -/* - * Compresses an address to a 22-byte sequence. - * This reduces the number of required SHA256 compression calls, as the last - * block of input is padded with at least 65 bits. - */ -void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_compress_address(unsigned char *out, const uint32_t addr[8]) { - PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_ull_to_bytes(out, 1, addr[0]); /* drop 3 bytes of the layer field */ - PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_ull_to_bytes(out + 1, 4, addr[2]); /* drop the highest tree address word */ - PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_ull_to_bytes(out + 5, 4, addr[3]); - PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_ull_to_bytes(out + 9, 1, addr[4]); /* drop 3 bytes of the type field */ - PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_ull_to_bytes(out + 10, 4, addr[5]); - PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_ull_to_bytes(out + 14, 4, addr[6]); - PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_ull_to_bytes(out + 18, 4, addr[7]); -} - -/** - * Requires 'input_plus_four_bytes' to have 'inlen' + 4 bytes, so that the last - * four bytes can be used for the counter. Typically 'input' is merely a seed. - * Outputs outlen number of bytes - */ -void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_mgf1( - unsigned char *out, unsigned long outlen, - unsigned char *input_plus_four_bytes, unsigned long inlen) { - unsigned char outbuf[PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_SHA256_OUTPUT_BYTES]; - unsigned long i; - - /* While we can fit in at least another full block of SHA256 output.. */ - for (i = 0; (i + 1)*PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_SHA256_OUTPUT_BYTES <= outlen; i++) { - PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_ull_to_bytes(input_plus_four_bytes + inlen, 4, i); - sha256(out, input_plus_four_bytes, inlen + 4); - out += PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_SHA256_OUTPUT_BYTES; - } - /* Until we cannot anymore, and we fill the remainder. */ - if (outlen > i * PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_SHA256_OUTPUT_BYTES) { - PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_ull_to_bytes(input_plus_four_bytes + inlen, 4, i); - sha256(outbuf, input_plus_four_bytes, inlen + 4); - memcpy(out, outbuf, outlen - i * PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_SHA256_OUTPUT_BYTES); - } -} - - -/** - * Absorb the constant pub_seed using one round of the compression function - * This initializes hash_state_seeded, which can then be reused in thash - **/ -void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_seed_state(sha256ctx *hash_state_seeded, const unsigned char *pub_seed) { - uint8_t block[PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_SHA256_BLOCK_BYTES]; - size_t i; - - for (i = 0; i < PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_N; ++i) { - block[i] = pub_seed[i]; - } - for (i = PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_N; i < PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_SHA256_BLOCK_BYTES; ++i) { - block[i] = 0; - } - - sha256_inc_init(hash_state_seeded); - sha256_inc_blocks(hash_state_seeded, block, 1); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_clean/sha256.h b/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_clean/sha256.h deleted file mode 100644 index 8a3b16bd3b..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_clean/sha256.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_SHA256_H -#define PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_SHA256_H - -#define PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_SHA256_BLOCK_BYTES 64 -#define PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_SHA256_OUTPUT_BYTES 32 /* This does not necessarily equal PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_N */ -#define PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_SHA256_ADDR_BYTES 22 - -#include -#include - -#include "sha2.h" - -void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_compress_address(unsigned char *out, const uint32_t addr[8]); - -void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_mgf1( - unsigned char *out, unsigned long outlen, - unsigned char *input_plus_four_bytes, unsigned long inlen); - -void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_seed_state(sha256ctx *hash_state_seeded, const unsigned char *pub_seed); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_clean/sign.c b/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_clean/sign.c deleted file mode 100644 index 22d82f40ac..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_clean/sign.c +++ /dev/null @@ -1,356 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "api.h" -#include "fors.h" -#include "hash.h" -#include "hash_state.h" -#include "params.h" -#include "randombytes.h" -#include "thash.h" -#include "utils.h" -#include "wots.h" - -/** - * Computes the leaf at a given address. First generates the WOTS key pair, - * then computes leaf by hashing horizontally. - */ -static void wots_gen_leaf(unsigned char *leaf, const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx, const uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - unsigned char pk[PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_WOTS_BYTES]; - uint32_t wots_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_set_type( - wots_addr, PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_set_type( - wots_pk_addr, PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_ADDR_TYPE_WOTSPK); - - PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_set_keypair_addr( - wots_addr, addr_idx); - PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_wots_gen_pk( - pk, sk_seed, pub_seed, wots_addr, hash_state_seeded); - - PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_copy_keypair_addr( - wots_pk_addr, wots_addr); - PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_thash_WOTS_LEN( - leaf, pk, pub_seed, wots_pk_addr, hash_state_seeded); -} - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_crypto_sign_secretkeybytes(void) { - return PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_CRYPTO_SECRETKEYBYTES; -} - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_crypto_sign_publickeybytes(void) { - return PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_CRYPTO_PUBLICKEYBYTES; -} - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_crypto_sign_bytes(void) { - return PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_CRYPTO_BYTES; -} - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_crypto_sign_seedbytes(void) { - return PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_CRYPTO_SEEDBYTES; -} - -/* - * Generates an SPX key pair given a seed of length - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed) { - /* We do not need the auth path in key generation, but it simplifies the - code to have just one treehash routine that computes both root and path - in one function. */ - unsigned char auth_path[PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_TREE_HEIGHT * PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_N]; - uint32_t top_tree_addr[8] = {0}; - hash_state hash_state_seeded; - - PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_set_layer_addr( - top_tree_addr, PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_D - 1); - PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_set_type( - top_tree_addr, PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_ADDR_TYPE_HASHTREE); - - /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ - memcpy(sk, seed, PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_CRYPTO_SEEDBYTES); - - memcpy(pk, sk + 2 * PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_N, PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_initialize_hash_function(&hash_state_seeded, pk, sk); - - /* Compute root node of the top-most subtree. */ - PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_treehash_TREE_HEIGHT( - sk + 3 * PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_N, auth_path, sk, sk + 2 * PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_N, 0, 0, - wots_gen_leaf, top_tree_addr, &hash_state_seeded); - - memcpy(pk + PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_N, sk + 3 * PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_N, PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_N); - - PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_destroy_hash_function(&hash_state_seeded); - return 0; -} - -/* - * Generates an SPX key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk) { - unsigned char seed[PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_CRYPTO_SEEDBYTES]; - randombytes(seed, PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_CRYPTO_SEEDBYTES); - PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_crypto_sign_seed_keypair( - pk, sk, seed); - - return 0; -} - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - const unsigned char *sk_seed = sk; - const unsigned char *sk_prf = sk + PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_N; - const unsigned char *pk = sk + 2 * PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_N; - const unsigned char *pub_seed = pk; - - unsigned char optrand[PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_N]; - unsigned char mhash[PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_FORS_MSG_BYTES]; - unsigned char root[PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_N]; - uint32_t i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - - hash_state hash_state_seeded; - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_initialize_hash_function( - &hash_state_seeded, - pub_seed, sk_seed); - - PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_set_type( - wots_addr, PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_set_type( - tree_addr, PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_ADDR_TYPE_HASHTREE); - - /* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ - randombytes(optrand, PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_N); - /* Compute the digest randomization value. */ - PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_gen_message_random( - sig, sk_prf, optrand, m, mlen, &hash_state_seeded); - - /* Derive the message digest and leaf index from R, PK and M. */ - PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_N; - - PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); - - /* Sign the message hash using FORS. */ - PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_fors_sign( - sig, root, mhash, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_FORS_BYTES; - - for (i = 0; i < PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_D; i++) { - PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_set_tree_addr(tree_addr, tree); - - PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); - - /* Compute a WOTS signature. */ - PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_wots_sign( - sig, root, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_WOTS_BYTES; - - /* Compute the authentication path for the used WOTS leaf. */ - PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_treehash_TREE_HEIGHT( - root, sig, sk_seed, pub_seed, idx_leaf, 0, - wots_gen_leaf, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_TREE_HEIGHT * PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_TREE_HEIGHT; - } - - *siglen = PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_BYTES; - - PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_destroy_hash_function(&hash_state_seeded); - return 0; -} - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk) { - const unsigned char *pub_seed = pk; - const unsigned char *pub_root = pk + PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_N; - unsigned char mhash[PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_FORS_MSG_BYTES]; - unsigned char wots_pk[PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_WOTS_BYTES]; - unsigned char root[PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_N]; - unsigned char leaf[PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_N]; - unsigned int i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - hash_state hash_state_seeded; - - if (siglen != PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_BYTES) { - return -1; - } - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_initialize_hash_function( - &hash_state_seeded, - pub_seed, NULL); - - PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_set_type( - wots_addr, PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_set_type( - tree_addr, PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_ADDR_TYPE_HASHTREE); - PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_set_type( - wots_pk_addr, PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_ADDR_TYPE_WOTSPK); - - /* Derive the message digest and leaf index from R || PK || M. */ - /* The additional PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_N is a result of the hash domain separator. */ - PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_N; - - /* Layer correctly defaults to 0, so no need to set_layer_addr */ - PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); - - PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_fors_pk_from_sig( - root, sig, mhash, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_FORS_BYTES; - - /* For each subtree.. */ - for (i = 0; i < PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_D; i++) { - PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_set_tree_addr(tree_addr, tree); - - PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); - - PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_copy_keypair_addr( - wots_pk_addr, wots_addr); - - /* The WOTS public key is only correct if the signature was correct. */ - /* Initially, root is the FORS pk, but on subsequent iterations it is - the root of the subtree below the currently processed subtree. */ - PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_wots_pk_from_sig( - wots_pk, sig, root, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_WOTS_BYTES; - - /* Compute the leaf node using the WOTS public key. */ - PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_thash_WOTS_LEN( - leaf, wots_pk, pub_seed, wots_pk_addr, &hash_state_seeded); - - /* Compute the root node of this subtree. */ - PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_compute_root( - root, leaf, idx_leaf, 0, sig, PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_TREE_HEIGHT, - pub_seed, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_TREE_HEIGHT * PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_TREE_HEIGHT; - } - - PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_destroy_hash_function(&hash_state_seeded); - /* Check if the root node equals the root node in the public key. */ - if (memcmp(root, pub_root, PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_N) != 0) { - return -1; - } - - return 0; -} - - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - size_t siglen; - - PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_crypto_sign_signature( - sm, &siglen, m, mlen, sk); - - memmove(sm + PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_BYTES, m, mlen); - *smlen = siglen + mlen; - - return 0; -} - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk) { - /* The API caller does not necessarily know what size a signature should be - but SPHINCS+ signatures are always exactly PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_BYTES. */ - if (smlen < PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_BYTES) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - *mlen = smlen - PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_BYTES; - - if (PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_crypto_sign_verify( - sm, PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_BYTES, sm + PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_BYTES, *mlen, pk)) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - /* If verification was successful, move the message to the right place. */ - memmove(m, sm + PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_BYTES, *mlen); - - return 0; -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_clean/thash.h b/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_clean/thash.h deleted file mode 100644 index 84383febe5..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_clean/thash.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_THASH_H -#define PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_THASH_H - -#include "hash_state.h" - -#include - -void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_clean/thash_sha256_robust.c b/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_clean/thash_sha256_robust.c deleted file mode 100644 index 27d59115bf..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_clean/thash_sha256_robust.c +++ /dev/null @@ -1,82 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "thash.h" - -#include "sha2.h" -#include "sha256.h" - -/** - * Takes an array of inblocks concatenated arrays of PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_N bytes. - */ -static void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_thash( - unsigned char *out, unsigned char *buf, - const unsigned char *in, unsigned int inblocks, - const unsigned char *pub_seed, uint32_t addr[8], - const sha256ctx *hash_state_seeded) { - - unsigned char outbuf[PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_SHA256_OUTPUT_BYTES]; - unsigned char *bitmask = buf + PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_N + PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_SHA256_ADDR_BYTES + 4; - sha256ctx sha2_state; - unsigned int i; - - memcpy(buf, pub_seed, PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_N); - PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_compress_address(buf + PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_N, addr); - /* MGF1 requires us to have 4 extra bytes in 'buf' */ - PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_mgf1(bitmask, inblocks * PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_N, buf, PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_N + PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_SHA256_ADDR_BYTES); - - /* Retrieve precomputed state containing pub_seed */ - sha256_inc_ctx_clone(&sha2_state, hash_state_seeded); - - for (i = 0; i < inblocks * PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_N; i++) { - buf[PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_N + PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_SHA256_ADDR_BYTES + i] = in[i] ^ bitmask[i]; - } - - sha256_inc_finalize(outbuf, &sha2_state, buf + PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_N, - PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_N); - memcpy(out, outbuf, PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_N); -} - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const sha256ctx *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_N + PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_SHA256_ADDR_BYTES + 4 + 1 * PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_N]; - PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_thash( - out, buf, in, 1, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const sha256ctx *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_N + PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_SHA256_ADDR_BYTES + 4 + 2 * PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_N]; - PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_thash( - out, buf, in, 2, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const sha256ctx *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_N + PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_SHA256_ADDR_BYTES + 4 + PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_WOTS_LEN * PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_N]; - PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_thash( - out, buf, in, PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_WOTS_LEN, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const sha256ctx *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_N + PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_SHA256_ADDR_BYTES + 4 + PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_FORS_TREES * PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_N]; - PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_thash( - out, buf, in, PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_FORS_TREES, pub_seed, addr, hash_state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_clean/utils.c b/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_clean/utils.c deleted file mode 100644 index 320e79432f..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_clean/utils.c +++ /dev/null @@ -1,199 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "hash_state.h" -#include "params.h" -#include "thash.h" -#include "utils.h" - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in) { - - /* Iterate over out in decreasing order, for big-endianness. */ - for (size_t i = outlen; i > 0; i--) { - out[i - 1] = in & 0xff; - in = in >> 8; - } -} - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_bytes_to_ull( - const unsigned char *in, size_t inlen) { - unsigned long long retval = 0; - - for (size_t i = 0; i < inlen; i++) { - retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); - } - return retval; -} - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - uint32_t i; - unsigned char buffer[2 * PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_N]; - - /* If leaf_idx is odd (last bit = 1), current path element is a right child - and auth_path has to go left. Otherwise it is the other way around. */ - if (leaf_idx & 1) { - memcpy(buffer + PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_N, leaf, PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_N); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_N); - } else { - memcpy(buffer, leaf, PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_N); - memcpy(buffer + PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_N, auth_path, PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_N); - } - auth_path += PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_N; - - for (i = 0; i < tree_height - 1; i++) { - leaf_idx >>= 1; - idx_offset >>= 1; - /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_set_tree_height(addr, i + 1); - PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_set_tree_index( - addr, leaf_idx + idx_offset); - - /* Pick the right or left neighbor, depending on parity of the node. */ - if (leaf_idx & 1) { - PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_thash_2( - buffer + PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_N, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_N); - } else { - PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_thash_2( - buffer, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer + PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_N, auth_path, PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_N); - } - auth_path += PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_N; - } - - /* The last iteration is exceptional; we do not copy an auth_path node. */ - leaf_idx >>= 1; - idx_offset >>= 1; - PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_set_tree_height(addr, tree_height); - PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_set_tree_index( - addr, leaf_idx + idx_offset); - PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_thash_2( - root, buffer, pub_seed, addr, hash_state_seeded); -} - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -static void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_treehash( - unsigned char *root, unsigned char *auth_path, - unsigned char *stack, unsigned int *heights, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - - unsigned int offset = 0; - uint32_t idx; - uint32_t tree_idx; - - for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { - /* Add the next leaf node to the stack. */ - gen_leaf(stack + offset * PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_N, - sk_seed, pub_seed, idx + idx_offset, tree_addr, - hash_state_seeded); - offset++; - heights[offset - 1] = 0; - - /* If this is a node we need for the auth path.. */ - if ((leaf_idx ^ 0x1) == idx) { - memcpy(auth_path, stack + (offset - 1)*PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_N, PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_N); - } - - /* While the top-most nodes are of equal height.. */ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { - /* Compute index of the new node, in the next layer. */ - tree_idx = (idx >> (heights[offset - 1] + 1)); - - /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_set_tree_height( - tree_addr, heights[offset - 1] + 1); - PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_set_tree_index( - tree_addr, tree_idx + (idx_offset >> (heights[offset - 1] + 1))); - /* Hash the top-most nodes from the stack together. */ - PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_thash_2( - stack + (offset - 2)*PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_N, stack + (offset - 2)*PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_N, - pub_seed, tree_addr, hash_state_seeded); - offset--; - /* Note that the top-most node is now one layer higher. */ - heights[offset - 1]++; - - /* If this is a node we need for the auth path.. */ - if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_path + heights[offset - 1]*PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_N, - stack + (offset - 1)*PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_N, PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_N); - } - } - } - memcpy(root, stack, PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_N); -} - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_FORS_HEIGHT + 1)*PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_N]; - unsigned int heights[PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_FORS_HEIGHT + 1]; - - PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_FORS_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_TREE_HEIGHT + 1)*PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_N]; - unsigned int heights[PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_TREE_HEIGHT + 1]; - - PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_TREE_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_clean/utils.h b/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_clean/utils.h deleted file mode 100644 index 7c950838d6..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_clean/utils.h +++ /dev/null @@ -1,64 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_UTILS_H -#define PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_UTILS_H - -#include "hash_state.h" -#include "params.h" -#include -#include - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in); - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_bytes_to_ull( - const unsigned char *in, size_t inlen); - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_clean/wots.c b/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_clean/wots.c deleted file mode 100644 index b46d746ac9..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_clean/wots.c +++ /dev/null @@ -1,167 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "hash_state.h" -#include "params.h" -#include "thash.h" -#include "utils.h" -#include "wots.h" - -// TODO clarify address expectations, and make them more uniform. -// TODO i.e. do we expect types to be set already? -// TODO and do we expect modifications or copies? - -/** - * Computes the starting value for a chain, i.e. the secret key. - * Expects the address to be complete up to the chain address. - */ -static void wots_gen_sk(unsigned char *sk, const unsigned char *sk_seed, - uint32_t wots_addr[8], - const hash_state *hash_state_seeded) { - /* Make sure that the hash address is actually zeroed. */ - PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_set_hash_addr(wots_addr, 0); - - /* Generate sk element. */ - PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_prf_addr(sk, sk_seed, wots_addr, hash_state_seeded); -} - -/** - * Computes the chaining function. - * out and in have to be n-byte arrays. - * - * Interprets in as start-th value of the chain. - * addr has to contain the address of the chain. - */ -static void gen_chain(unsigned char *out, const unsigned char *in, - unsigned int start, unsigned int steps, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - uint32_t i; - - /* Initialize out with the value at position 'start'. */ - memcpy(out, in, PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_N); - - /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_WOTS_W; i++) { - PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_set_hash_addr(addr, i); - PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_thash_1( - out, out, pub_seed, addr, hash_state_seeded); - } -} - -/** - * base_w algorithm as described in draft. - * Interprets an array of bytes as integers in base w. - * This only works when log_w is a divisor of 8. - */ -static void base_w(unsigned int *output, const size_t out_len, - const unsigned char *input) { - size_t in = 0; - size_t out = 0; - unsigned char total = 0; - unsigned int bits = 0; - size_t consumed; - - for (consumed = 0; consumed < out_len; consumed++) { - if (bits == 0) { - total = input[in]; - in++; - bits += 8; - } - bits -= PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_WOTS_LOGW; - output[out] = (unsigned int)((total >> bits) & (PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_WOTS_W - 1)); - out++; - } -} - -/* Computes the WOTS+ checksum over a message (in base_w). */ -static void wots_checksum(unsigned int *csum_base_w, - const unsigned int *msg_base_w) { - unsigned int csum = 0; - unsigned char csum_bytes[(PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_WOTS_LEN2 * PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_WOTS_LOGW + 7) / 8]; - unsigned int i; - - /* Compute checksum. */ - for (i = 0; i < PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_WOTS_LEN1; i++) { - csum += PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_WOTS_W - 1 - msg_base_w[i]; - } - - /* Convert checksum to base_w. */ - /* Make sure expected empty zero bits are the least significant bits. */ - csum = csum << (8 - ((PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_WOTS_LEN2 * PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_WOTS_LOGW) % 8)); - PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_ull_to_bytes( - csum_bytes, sizeof(csum_bytes), csum); - base_w(csum_base_w, PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_WOTS_LEN2, csum_bytes); -} - -/* Takes a message and derives the matching chain lengths. */ -static void chain_lengths(unsigned int *lengths, const unsigned char *msg) { - base_w(lengths, PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_WOTS_LEN1, msg); - wots_checksum(lengths + PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_WOTS_LEN1, lengths); -} - -/** - * WOTS key generation. Takes a 32 byte sk_seed, expands it to WOTS private key - * elements and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_wots_gen_pk( - unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - uint32_t i; - - for (i = 0; i < PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_WOTS_LEN; i++) { - PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_set_chain_addr(addr, i); - wots_gen_sk(pk + i * PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_N, sk_seed, addr, hash_state_seeded); - gen_chain(pk + i * PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_N, pk + i * PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_N, - 0, PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_WOTS_W - 1, pub_seed, addr, hash_state_seeded); - } -} - -/** - * Takes a n-byte message and the 32-byte sk_see to compute a signature 'sig'. - */ -void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_wots_sign( - unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *hash_state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_WOTS_LEN; i++) { - PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_set_chain_addr(addr, i); - wots_gen_sk(sig + i * PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_N, sk_seed, addr, hash_state_seeded); - gen_chain(sig + i * PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_N, sig + i * PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_N, 0, lengths[i], pub_seed, addr, hash_state_seeded); - } -} - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_wots_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_WOTS_LEN; i++) { - PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_set_chain_addr(addr, i); - gen_chain(pk + i * PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_N, sig + i * PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_N, - lengths[i], PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_WOTS_W - 1 - lengths[i], pub_seed, addr, - hash_state_seeded); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_clean/wots.h b/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_clean/wots.h deleted file mode 100644 index 499113e4c9..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_clean/wots.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_WOTS_H -#define PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_WOTS_H - -#include "hash_state.h" -#include "params.h" -#include - -/** - * WOTS key generation. Takes a 32 byte seed for the private key, expands it to - * a full WOTS private key and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_wots_gen_pk( - unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -/** - * Takes a n-byte message and the 32-byte seed for the private key to compute a - * signature that is placed at 'sig'. - */ -void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_wots_sign( - unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *hash_state_seeded); - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_wots_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_avx2/LICENSE b/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_avx2/LICENSE deleted file mode 100644 index 670154e353..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_avx2/LICENSE +++ /dev/null @@ -1,116 +0,0 @@ -CC0 1.0 Universal - -Statement of Purpose - -The laws of most jurisdictions throughout the world automatically confer -exclusive Copyright and Related Rights (defined below) upon the creator and -subsequent owner(s) (each and all, an "owner") of an original work of -authorship and/or a database (each, a "Work"). - -Certain owners wish to permanently relinquish those rights to a Work for the -purpose of contributing to a commons of creative, cultural and scientific -works ("Commons") that the public can reliably and without fear of later -claims of infringement build upon, modify, incorporate in other works, reuse -and redistribute as freely as possible in any form whatsoever and for any -purposes, including without limitation commercial purposes. These owners may -contribute to the Commons to promote the ideal of a free culture and the -further production of creative, cultural and scientific works, or to gain -reputation or greater distribution for their Work in part through the use and -efforts of others. - -For these and/or other purposes and motivations, and without any expectation -of additional consideration or compensation, the person associating CC0 with a -Work (the "Affirmer"), to the extent that he or she is an owner of Copyright -and Related Rights in the Work, voluntarily elects to apply CC0 to the Work -and publicly distribute the Work under its terms, with knowledge of his or her -Copyright and Related Rights in the Work and the meaning and intended legal -effect of CC0 on those rights. - -1. Copyright and Related Rights. A Work made available under CC0 may be -protected by copyright and related or neighboring rights ("Copyright and -Related Rights"). Copyright and Related Rights include, but are not limited -to, the following: - - i. the right to reproduce, adapt, distribute, perform, display, communicate, - and translate a Work; - - ii. moral rights retained by the original author(s) and/or performer(s); - - iii. publicity and privacy rights pertaining to a person's image or likeness - depicted in a Work; - - iv. rights protecting against unfair competition in regards to a Work, - subject to the limitations in paragraph 4(a), below; - - v. rights protecting the extraction, dissemination, use and reuse of data in - a Work; - - vi. database rights (such as those arising under Directive 96/9/EC of the - European Parliament and of the Council of 11 March 1996 on the legal - protection of databases, and under any national implementation thereof, - including any amended or successor version of such directive); and - - vii. other similar, equivalent or corresponding rights throughout the world - based on applicable law or treaty, and any national implementations thereof. - -2. Waiver. To the greatest extent permitted by, but not in contravention of, -applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and -unconditionally waives, abandons, and surrenders all of Affirmer's Copyright -and Related Rights and associated claims and causes of action, whether now -known or unknown (including existing as well as future claims and causes of -action), in the Work (i) in all territories worldwide, (ii) for the maximum -duration provided by applicable law or treaty (including future time -extensions), (iii) in any current or future medium and for any number of -copies, and (iv) for any purpose whatsoever, including without limitation -commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes -the Waiver for the benefit of each member of the public at large and to the -detriment of Affirmer's heirs and successors, fully intending that such Waiver -shall not be subject to revocation, rescission, cancellation, termination, or -any other legal or equitable action to disrupt the quiet enjoyment of the Work -by the public as contemplated by Affirmer's express Statement of Purpose. - -3. Public License Fallback. Should any part of the Waiver for any reason be -judged legally invalid or ineffective under applicable law, then the Waiver -shall be preserved to the maximum extent permitted taking into account -Affirmer's express Statement of Purpose. In addition, to the extent the Waiver -is so judged Affirmer hereby grants to each affected person a royalty-free, -non transferable, non sublicensable, non exclusive, irrevocable and -unconditional license to exercise Affirmer's Copyright and Related Rights in -the Work (i) in all territories worldwide, (ii) for the maximum duration -provided by applicable law or treaty (including future time extensions), (iii) -in any current or future medium and for any number of copies, and (iv) for any -purpose whatsoever, including without limitation commercial, advertising or -promotional purposes (the "License"). The License shall be deemed effective as -of the date CC0 was applied by Affirmer to the Work. Should any part of the -License for any reason be judged legally invalid or ineffective under -applicable law, such partial invalidity or ineffectiveness shall not -invalidate the remainder of the License, and in such case Affirmer hereby -affirms that he or she will not (i) exercise any of his or her remaining -Copyright and Related Rights in the Work or (ii) assert any associated claims -and causes of action with respect to the Work, in either case contrary to -Affirmer's express Statement of Purpose. - -4. Limitations and Disclaimers. - - a. No trademark or patent rights held by Affirmer are waived, abandoned, - surrendered, licensed or otherwise affected by this document. - - b. Affirmer offers the Work as-is and makes no representations or warranties - of any kind concerning the Work, express, implied, statutory or otherwise, - including without limitation warranties of title, merchantability, fitness - for a particular purpose, non infringement, or the absence of latent or - other defects, accuracy, or the present or absence of errors, whether or not - discoverable, all to the greatest extent permissible under applicable law. - - c. Affirmer disclaims responsibility for clearing rights of other persons - that may apply to the Work or any use thereof, including without limitation - any person's Copyright and Related Rights in the Work. Further, Affirmer - disclaims responsibility for obtaining any necessary consents, permissions - or other rights required for any use of the Work. - - d. Affirmer understands and acknowledges that Creative Commons is not a - party to this document and has no duty or obligation with respect to this - CC0 or use of the Work. - -For more information, please see - diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_avx2/address.c b/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_avx2/address.c deleted file mode 100644 index f467aeb509..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_avx2/address.c +++ /dev/null @@ -1,78 +0,0 @@ -#include - -#include "address.h" -#include "params.h" -#include "utils.h" - -void PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]) { - int i; - - for (i = 0; i < 8; i++) { - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_ull_to_bytes( - bytes + i * 4, 4, addr[i]); - } -} - -void PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_set_layer_addr( - uint32_t addr[8], uint32_t layer) { - addr[0] = layer; -} - -void PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_set_tree_addr( - uint32_t addr[8], uint64_t tree) { - addr[1] = 0; - addr[2] = (uint32_t) (tree >> 32); - addr[3] = (uint32_t) tree; -} - -void PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_set_type( - uint32_t addr[8], uint32_t type) { - addr[4] = type; -} - -void PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; -} - -/* These functions are used for OTS addresses. */ - -void PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_set_keypair_addr( - uint32_t addr[8], uint32_t keypair) { - addr[5] = keypair; -} - -void PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; - out[5] = in[5]; -} - -void PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_set_chain_addr( - uint32_t addr[8], uint32_t chain) { - addr[6] = chain; -} - -void PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_set_hash_addr( - uint32_t addr[8], uint32_t hash) { - addr[7] = hash; -} - -/* These functions are used for all hash tree addresses (including FORS). */ - -void PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_set_tree_height( - uint32_t addr[8], uint32_t tree_height) { - addr[6] = tree_height; -} - -void PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_set_tree_index( - uint32_t addr[8], uint32_t tree_index) { - addr[7] = tree_index; -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_avx2/address.h b/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_avx2/address.h deleted file mode 100644 index 44dbd21373..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_avx2/address.h +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_ADDRESS_H -#define PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_ADDRESS_H - -#include - -#define PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_ADDR_TYPE_WOTS 0 -#define PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_ADDR_TYPE_WOTSPK 1 -#define PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_ADDR_TYPE_HASHTREE 2 -#define PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_ADDR_TYPE_FORSTREE 3 -#define PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_ADDR_TYPE_FORSPK 4 - -void PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]); - -void PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_set_layer_addr( - uint32_t addr[8], uint32_t layer); - -void PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_set_tree_addr( - uint32_t addr[8], uint64_t tree); - -void PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_set_type( - uint32_t addr[8], uint32_t type); - -/* Copies the layer and tree part of one address into the other */ -void PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for WOTS and FORS addresses. */ - -void PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_set_keypair_addr( - uint32_t addr[8], uint32_t keypair); - -void PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_set_chain_addr( - uint32_t addr[8], uint32_t chain); - -void PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_set_hash_addr( - uint32_t addr[8], uint32_t hash); - -void PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for all hash tree addresses (including FORS). */ - -void PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_set_tree_height( - uint32_t addr[8], uint32_t tree_height); - -void PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_set_tree_index( - uint32_t addr[8], uint32_t tree_index); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_avx2/api.h b/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_avx2/api.h deleted file mode 100644 index 65a846372e..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_avx2/api.h +++ /dev/null @@ -1,81 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_API_H -#define PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_API_H - -#include -#include - - - -#define PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_CRYPTO_ALGNAME "SPHINCS+" - -#define PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_CRYPTO_SECRETKEYBYTES 64 -#define PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_CRYPTO_PUBLICKEYBYTES 32 -#define PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_CRYPTO_BYTES 17088 -#define PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_CRYPTO_SEEDBYTES 48 - - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_avx2/fors.c b/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_avx2/fors.c deleted file mode 100644 index b86ae83047..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_avx2/fors.c +++ /dev/null @@ -1,240 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "fors.h" -#include "hash.h" -#include "hashx8.h" -#include "thash.h" -#include "thashx8.h" -#include "utils.h" -#include "utilsx8.h" - -static void fors_gen_skx8(unsigned char *sk0, - unsigned char *sk1, - unsigned char *sk2, - unsigned char *sk3, - unsigned char *sk4, - unsigned char *sk5, - unsigned char *sk6, - unsigned char *sk7, const unsigned char *sk_seed, - uint32_t fors_leaf_addrx8[8 * 8]) { - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_prf_addrx8(sk0, sk1, sk2, sk3, sk4, sk5, sk6, sk7, - sk_seed, fors_leaf_addrx8); -} - -static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, - const unsigned char *pub_seed, - uint32_t fors_leaf_addr[8], - const hash_state *state_seeded) { - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_thash_1(leaf, sk, pub_seed, fors_leaf_addr, state_seeded); -} - -static void fors_sk_to_leafx8(unsigned char *leaf0, - unsigned char *leaf1, - unsigned char *leaf2, - unsigned char *leaf3, - unsigned char *leaf4, - unsigned char *leaf5, - unsigned char *leaf6, - unsigned char *leaf7, - const unsigned char *sk0, - const unsigned char *sk1, - const unsigned char *sk2, - const unsigned char *sk3, - const unsigned char *sk4, - const unsigned char *sk5, - const unsigned char *sk6, - const unsigned char *sk7, - const unsigned char *pub_seed, - uint32_t fors_leaf_addrx8[8 * 8], - const hash_state *state_seeded) { - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_thashx8_1(leaf0, leaf1, leaf2, leaf3, leaf4, leaf5, leaf6, leaf7, - sk0, sk1, sk2, sk3, sk4, sk5, sk6, sk7, - pub_seed, fors_leaf_addrx8, state_seeded); -} - -static void fors_gen_leafx8(unsigned char *leaf0, - unsigned char *leaf1, - unsigned char *leaf2, - unsigned char *leaf3, - unsigned char *leaf4, - unsigned char *leaf5, - unsigned char *leaf6, - unsigned char *leaf7, - const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx0, - uint32_t addr_idx1, - uint32_t addr_idx2, - uint32_t addr_idx3, - uint32_t addr_idx4, - uint32_t addr_idx5, - uint32_t addr_idx6, - uint32_t addr_idx7, - const uint32_t fors_tree_addr[8], - const hash_state *state_seeded) { - uint32_t fors_leaf_addrx8[8 * 8] = {0}; - unsigned int j; - - /* Only copy the parts that must be kept in fors_leaf_addrx8. */ - for (j = 0; j < 8; j++) { - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_copy_keypair_addr(fors_leaf_addrx8 + j * 8, fors_tree_addr); - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_set_type(fors_leaf_addrx8 + j * 8, PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_ADDR_TYPE_FORSTREE); - } - - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_set_tree_index(fors_leaf_addrx8 + 0 * 8, addr_idx0); - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_set_tree_index(fors_leaf_addrx8 + 1 * 8, addr_idx1); - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_set_tree_index(fors_leaf_addrx8 + 2 * 8, addr_idx2); - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_set_tree_index(fors_leaf_addrx8 + 3 * 8, addr_idx3); - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_set_tree_index(fors_leaf_addrx8 + 4 * 8, addr_idx4); - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_set_tree_index(fors_leaf_addrx8 + 5 * 8, addr_idx5); - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_set_tree_index(fors_leaf_addrx8 + 6 * 8, addr_idx6); - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_set_tree_index(fors_leaf_addrx8 + 7 * 8, addr_idx7); - - fors_gen_skx8(leaf0, leaf1, leaf2, leaf3, leaf4, leaf5, leaf6, leaf7, - sk_seed, fors_leaf_addrx8); - fors_sk_to_leafx8(leaf0, leaf1, leaf2, leaf3, leaf4, leaf5, leaf6, leaf7, - leaf0, leaf1, leaf2, leaf3, leaf4, leaf5, leaf6, leaf7, - pub_seed, fors_leaf_addrx8, state_seeded); -} - -/** - * Interprets m as PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_FORS_HEIGHT-bit unsigned integers. - * Assumes m contains at least PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_FORS_TREES bits. - * Assumes indices has space for PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_FORS_TREES integers. - */ -static void message_to_indices(uint32_t *indices, const unsigned char *m) { - unsigned int i, j; - unsigned int offset = 0; - - for (i = 0; i < PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_FORS_TREES; i++) { - indices[i] = 0; - for (j = 0; j < PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_FORS_HEIGHT; j++) { - indices[i] ^= (((uint32_t)m[offset >> 3] >> (offset & 0x7)) & 0x1) << j; - offset++; - } - } -} - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_fors_sign( - unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], - const hash_state *state_seeded) { - /* Round up to multiple of 8 to prevent out-of-bounds for x8 parallelism */ - uint32_t indices[(PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_FORS_TREES + 7) & ~7] = {0}; - unsigned char roots[((PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_FORS_TREES + 7) & ~7) * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N]; - /* Sign to a buffer, since we may not have a nice multiple of 8 and would - otherwise overrun the signature. */ - unsigned char sigbufx8[8 * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N * (1 + PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_FORS_HEIGHT)]; - uint32_t fors_tree_addrx8[8 * 8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset[8] = {0}; - unsigned int i, j; - - for (j = 0; j < 8; j++) { - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_copy_keypair_addr(fors_tree_addrx8 + j * 8, fors_addr); - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_set_type(fors_tree_addrx8 + j * 8, PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_ADDR_TYPE_FORSTREE); - } - - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_copy_keypair_addr(fors_pk_addr, fors_addr); - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_set_type(fors_pk_addr, PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < ((PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_FORS_TREES + 7) & ~0x7); i += 8) { - for (j = 0; j < 8; j++) { - if (i + j < PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_FORS_TREES) { - idx_offset[j] = (i + j) * (1 << PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_FORS_HEIGHT); - - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_set_tree_height(fors_tree_addrx8 + j * 8, 0); - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_set_tree_index(fors_tree_addrx8 + j * 8, - indices[i + j] + idx_offset[j]); - } - } - - /* Include the secret key part that produces the selected leaf nodes. */ - fors_gen_skx8(sigbufx8 + 0 * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N, - sigbufx8 + 1 * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N, - sigbufx8 + 2 * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N, - sigbufx8 + 3 * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N, - sigbufx8 + 4 * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N, - sigbufx8 + 5 * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N, - sigbufx8 + 6 * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N, - sigbufx8 + 7 * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N, - sk_seed, fors_tree_addrx8); - - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_treehashx8_FORS_HEIGHT( - roots + i * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N, sigbufx8 + 8 * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N, sk_seed, pub_seed, - &indices[i], idx_offset, fors_gen_leafx8, fors_tree_addrx8, - state_seeded); - - for (j = 0; j < 8; j++) { - if (i + j < PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_FORS_TREES) { - memcpy(sig, sigbufx8 + j * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N, PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N); - memcpy(sig + PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N, - sigbufx8 + 8 * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N + j * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_FORS_HEIGHT, - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_FORS_HEIGHT); - sig += PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N * (1 + PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_FORS_HEIGHT); - } - } - } - - /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_thash_FORS_TREES(pk, roots, pub_seed, fors_pk_addr, state_seeded); -} - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, - const uint32_t fors_addr[8], - const hash_state *state_seeded) { - uint32_t indices[PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_FORS_TREES]; - unsigned char roots[PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_FORS_TREES * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N]; - unsigned char leaf[PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N]; - uint32_t fors_tree_addr[8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_copy_keypair_addr(fors_tree_addr, fors_addr); - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_copy_keypair_addr(fors_pk_addr, fors_addr); - - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_set_type(fors_tree_addr, PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_set_type(fors_pk_addr, PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_FORS_TREES; i++) { - idx_offset = i * (1 << PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_FORS_HEIGHT); - - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_set_tree_height(fors_tree_addr, 0); - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Derive the leaf from the included secret key part. */ - fors_sk_to_leaf(leaf, sig, pub_seed, fors_tree_addr, state_seeded); - sig += PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N; - - /* Derive the corresponding root node of this tree. */ - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_compute_root(roots + i * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N, leaf, indices[i], idx_offset, - sig, PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_FORS_HEIGHT, pub_seed, fors_tree_addr, state_seeded); - sig += PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_thash_FORS_TREES(pk, roots, pub_seed, fors_pk_addr, state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_avx2/fors.h b/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_avx2/fors.h deleted file mode 100644 index ac6897acfe..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_avx2/fors.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_FORS_H -#define PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_FORS_H - -#include - -#include "hash_state.h" -#include "params.h" - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_fors_sign( - unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *hash_state_seeded); - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_fors_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, const uint32_t fors_addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_avx2/hash.h b/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_avx2/hash.h deleted file mode 100644 index 579f1949ad..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_avx2/hash.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_HASH_H -#define PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_HASH_H - -#include "hash_state.h" - -#include -#include - -void PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_initialize_hash_function( - hash_state *hash_state_seeded, - const unsigned char *pub_seed, const unsigned char *sk_seed); - -void PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_destroy_hash_function(hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_avx2/hash_sha256.c b/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_avx2/hash_sha256.c deleted file mode 100644 index 27ad6331d7..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_avx2/hash_sha256.c +++ /dev/null @@ -1,166 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "utils.h" - -#include "sha2.h" -#include "sha256.h" -#include "sha256x8.h" - -/** - * Initializes the hash function states - */ -void PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_initialize_hash_function( - hash_state *hash_state_seeded, - const unsigned char *pub_seed, const unsigned char *sk_seed) { - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_seed_state(&hash_state_seeded->x1, pub_seed); - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_seed_statex8(&hash_state_seeded->x8, pub_seed); - (void)sk_seed; /* Suppress an 'unused parameter' warning. */ -} - -/** - * Cleans up the hash function states - */ -void PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_destroy_hash_function(hash_state *hash_state_seeded) { - sha256_inc_ctx_release(&hash_state_seeded->x1); -} - -/* - * Computes PRF(key, addr), given a secret key of PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N bytes and an address - */ -void PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_prf_addr(unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded) { - unsigned char buf[PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_ADDR_BYTES]; - unsigned char outbuf[PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_OUTPUT_BYTES]; - - memcpy(buf, key, PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N); - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_compress_address(buf + PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N, addr); - - sha256(outbuf, buf, PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_ADDR_BYTES); - memcpy(out, outbuf, PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} - -/** - * Computes the message-dependent randomness R, using a secret seed as a key - * for HMAC, and an optional randomization value prefixed to the message. - * This requires m to have at least PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_BLOCK_BYTES + PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N space - * available in front of the pointer, i.e. before the message to use for the - * prefix. This is necessary to prevent having to move the message around (and - * allocate memory for it). - */ -void PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, const hash_state *hash_state_seeded) { - unsigned char buf[PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_BLOCK_BYTES + PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_OUTPUT_BYTES]; - sha256ctx state; - int i; - - /* This implements HMAC-SHA256 */ - for (i = 0; i < PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N; i++) { - buf[i] = 0x36 ^ sk_prf[i]; - } - memset(buf + PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N, 0x36, PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N); - - sha256_inc_init(&state); - sha256_inc_blocks(&state, buf, 1); - - memcpy(buf, optrand, PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N); - - /* If optrand + message cannot fill up an entire block */ - if (PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N + mlen < PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_BLOCK_BYTES) { - memcpy(buf + PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N, m, mlen); - sha256_inc_finalize(buf + PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_BLOCK_BYTES, &state, - buf, mlen + PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N); - } - /* Otherwise first fill a block, so that finalize only uses the message */ - else { - memcpy(buf + PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N, m, PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N); - sha256_inc_blocks(&state, buf, 1); - - m += PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N; - mlen -= PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N; - sha256_inc_finalize(buf + PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_BLOCK_BYTES, &state, m, mlen); - } - - for (i = 0; i < PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N; i++) { - buf[i] = 0x5c ^ sk_prf[i]; - } - memset(buf + PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N, 0x5c, PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N); - - sha256(buf, buf, PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_BLOCK_BYTES + PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_OUTPUT_BYTES); - memcpy(R, buf, PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} - -/** - * Computes the message hash using R, the public key, and the message. - * Outputs the message digest and the index of the leaf. The index is split in - * the tree index and the leaf index, for convenient copying to an address. - */ -void PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded) { -#define PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_TREE_BITS (PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_TREE_HEIGHT * (PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_D - 1)) -#define PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_TREE_BYTES ((PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_TREE_BITS + 7) / 8) -#define PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_LEAF_BITS PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_TREE_HEIGHT -#define PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_LEAF_BYTES ((PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_LEAF_BITS + 7) / 8) -#define PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_DGST_BYTES (PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_FORS_MSG_BYTES + PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_TREE_BYTES + PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_LEAF_BYTES) - - unsigned char seed[PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_OUTPUT_BYTES + 4]; - - /* Round to nearest multiple of PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_BLOCK_BYTES */ -#define PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_INBLOCKS (((PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_PK_BYTES + PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_BLOCK_BYTES - 1) & \ - -PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_BLOCK_BYTES) / PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_BLOCK_BYTES) - unsigned char inbuf[PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_INBLOCKS * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_BLOCK_BYTES]; - - unsigned char buf[PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_DGST_BYTES]; - unsigned char *bufp = buf; - sha256ctx state; - - sha256_inc_init(&state); - - memcpy(inbuf, R, PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N); - memcpy(inbuf + PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N, pk, PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_PK_BYTES); - - /* If R + pk + message cannot fill up an entire block */ - if (PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_PK_BYTES + mlen < PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_INBLOCKS * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_BLOCK_BYTES) { - memcpy(inbuf + PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_PK_BYTES, m, mlen); - sha256_inc_finalize(seed, &state, inbuf, PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_PK_BYTES + mlen); - } - /* Otherwise first fill a block, so that finalize only uses the message */ - else { - memcpy(inbuf + PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_PK_BYTES, m, - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_INBLOCKS * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_PK_BYTES); - sha256_inc_blocks(&state, inbuf, PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_INBLOCKS); - - m += PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_INBLOCKS * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_PK_BYTES; - mlen -= PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_INBLOCKS * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_PK_BYTES; - sha256_inc_finalize(seed, &state, m, mlen); - } - - /* By doing this in two steps, we prevent hashing the message twice; - otherwise each iteration in MGF1 would hash the message again. */ - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_mgf1(bufp, PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_DGST_BYTES, seed, PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_OUTPUT_BYTES); - - memcpy(digest, bufp, PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_FORS_MSG_BYTES); - bufp += PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_FORS_MSG_BYTES; - - *tree = PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_bytes_to_ull(bufp, PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_TREE_BYTES); - *tree &= (~(uint64_t)0) >> (64 - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_TREE_BITS); - bufp += PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_TREE_BYTES; - - *leaf_idx = (uint32_t)PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_bytes_to_ull( - bufp, PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_LEAF_BYTES); - *leaf_idx &= (~(uint32_t)0) >> (32 - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_LEAF_BITS); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_avx2/hash_sha256x8.c b/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_avx2/hash_sha256x8.c deleted file mode 100644 index 38c7375d6a..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_avx2/hash_sha256x8.c +++ /dev/null @@ -1,61 +0,0 @@ -#include -#include - -#include "address.h" -#include "hashx8.h" -#include "params.h" -#include "sha256.h" -#include "sha256avx.h" -#include "sha256x8.h" -#include "utils.h" - -/* - * 8-way parallel version of prf_addr; takes 8x as much input and output - */ -void PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_prf_addrx8(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7, - const unsigned char *key, - const uint32_t addrx8[8 * 8]) { - unsigned char bufx8[8 * (PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_ADDR_BYTES)]; - unsigned char outbufx8[8 * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_OUTPUT_BYTES]; - unsigned int j; - - for (j = 0; j < 8; j++) { - memcpy(bufx8 + j * (PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_ADDR_BYTES), key, PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N); - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_compress_address(bufx8 + PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N + j * (PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_ADDR_BYTES), - addrx8 + j * 8); - } - - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_sha256x8(outbufx8 + 0 * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 1 * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 2 * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 3 * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 4 * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 5 * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 6 * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 7 * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - bufx8 + 0 * (PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_ADDR_BYTES), - bufx8 + 1 * (PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_ADDR_BYTES), - bufx8 + 2 * (PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_ADDR_BYTES), - bufx8 + 3 * (PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_ADDR_BYTES), - bufx8 + 4 * (PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_ADDR_BYTES), - bufx8 + 5 * (PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_ADDR_BYTES), - bufx8 + 6 * (PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_ADDR_BYTES), - bufx8 + 7 * (PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_ADDR_BYTES), - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_ADDR_BYTES); - - memcpy(out0, outbufx8 + 0 * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N); - memcpy(out1, outbufx8 + 1 * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N); - memcpy(out2, outbufx8 + 2 * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N); - memcpy(out3, outbufx8 + 3 * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N); - memcpy(out4, outbufx8 + 4 * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N); - memcpy(out5, outbufx8 + 5 * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N); - memcpy(out6, outbufx8 + 6 * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N); - memcpy(out7, outbufx8 + 7 * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_avx2/hash_state.h b/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_avx2/hash_state.h deleted file mode 100644 index 94e632d80e..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_avx2/hash_state.h +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_HASH_STATE_H -#define PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_HASH_STATE_H - -/** - * Defines the type of the hash function state. - * - * Don't be fooled into thinking this instance of SPHINCS+ isn't stateless! - * - * From Section 7.2.2 from the SPHINCS+ round-2 specification: - * - * Each of the instances of the tweakable hash function take PK.seed as its - * first input, which is constant for a given key pair – and, thus, across - * a single signature. This leads to a lot of redundant computation. To remedy - * this, we pad PK.seed to the length of a full 64-byte SHA-256 input block. - * Because of the Merkle-DamgÃ¥rd construction that underlies SHA-256, this - * allows for reuse of the intermediate SHA-256 state after the initial call to - * the compression function which improves performance. - * - * We pass this hash state around in functions, because otherwise we need to - * have a global variable. - * - * We use a struct to differentiate between the x1 and x8 variants of SHA256. - */ - -#include "sha2.h" -#include "sha256avx.h" - -typedef struct { - sha256ctx x1; - sha256ctxx8 x8; -} hash_state; - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_avx2/hashx8.h b/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_avx2/hashx8.h deleted file mode 100644 index f1c3e37015..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_avx2/hashx8.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_HASHX8_H -#define PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_HASHX8_H - -#include - -#include "params.h" - -void PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_prf_addrx8(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7, - const unsigned char *key, - const uint32_t addrx8[8 * 8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_avx2/params.h b/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_avx2/params.h deleted file mode 100644 index 07087e08e4..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_avx2/params.h +++ /dev/null @@ -1,53 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_PARAMS_H -#define PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_PARAMS_H - -/* Hash output length in bytes. */ -#define PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N 16 -/* Height of the hypertree. */ -#define PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_FULL_HEIGHT 66 -/* Number of subtree layer. */ -#define PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_D 22 -/* FORS tree dimensions. */ -#define PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_FORS_HEIGHT 6 -#define PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_FORS_TREES 33 -/* Winternitz parameter, */ -#define PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_WOTS_W 16 - -/* The hash function is defined by linking a different hash.c file, as opposed - to setting a #define constant. */ - -/* For clarity */ -#define PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_ADDR_BYTES 32 - -/* WOTS parameters. */ -#define PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_WOTS_LOGW 4 - -#define PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_WOTS_LEN1 (8 * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N / PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_WOTS_LOGW) - -/* PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#define PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_WOTS_LEN2 3 - -#define PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_WOTS_LEN (PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_WOTS_LEN1 + PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_WOTS_LEN2) -#define PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_WOTS_BYTES (PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_WOTS_LEN * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N) -#define PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_WOTS_PK_BYTES PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_WOTS_BYTES - -/* Subtree size. */ -#define PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_TREE_HEIGHT (PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_FULL_HEIGHT / PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_D) - -/* FORS parameters. */ -#define PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_FORS_MSG_BYTES ((PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_FORS_TREES + 7) / 8) -#define PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_FORS_BYTES ((PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_FORS_HEIGHT + 1) * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_FORS_TREES * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N) -#define PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_FORS_PK_BYTES PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N - -/* Resulting SPX sizes. */ -#define PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_BYTES (PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_FORS_BYTES + PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_D * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_WOTS_BYTES +\ - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_FULL_HEIGHT * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N) -#define PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_PK_BYTES (2 * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N) -#define PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SK_BYTES (2 * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_PK_BYTES) - -/* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ -#define PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_OPTRAND_BYTES 32 - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_avx2/sha256.c b/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_avx2/sha256.c deleted file mode 100644 index 4489756c31..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_avx2/sha256.c +++ /dev/null @@ -1,71 +0,0 @@ -/* Based on the public domain implementation in - * crypto_hash/sha512/ref/ from http://bench.cr.yp.to/supercop.html - * by D. J. Bernstein */ - -#include -#include -#include - -#include "sha2.h" -#include "sha256.h" -#include "utils.h" - -/* - * Compresses an address to a 22-byte sequence. - * This reduces the number of required SHA256 compression calls, as the last - * block of input is padded with at least 65 bits. - */ -void PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_compress_address(unsigned char *out, const uint32_t addr[8]) { - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_ull_to_bytes(out, 1, addr[0]); /* drop 3 bytes of the layer field */ - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_ull_to_bytes(out + 1, 4, addr[2]); /* drop the highest tree address word */ - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_ull_to_bytes(out + 5, 4, addr[3]); - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_ull_to_bytes(out + 9, 1, addr[4]); /* drop 3 bytes of the type field */ - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_ull_to_bytes(out + 10, 4, addr[5]); - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_ull_to_bytes(out + 14, 4, addr[6]); - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_ull_to_bytes(out + 18, 4, addr[7]); -} - -/** - * Requires 'input_plus_four_bytes' to have 'inlen' + 4 bytes, so that the last - * four bytes can be used for the counter. Typically 'input' is merely a seed. - * Outputs outlen number of bytes - */ -void PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_mgf1( - unsigned char *out, unsigned long outlen, - unsigned char *input_plus_four_bytes, unsigned long inlen) { - unsigned char outbuf[PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_OUTPUT_BYTES]; - unsigned long i; - - /* While we can fit in at least another full block of SHA256 output.. */ - for (i = 0; (i + 1)*PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_OUTPUT_BYTES <= outlen; i++) { - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_ull_to_bytes(input_plus_four_bytes + inlen, 4, i); - sha256(out, input_plus_four_bytes, inlen + 4); - out += PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_OUTPUT_BYTES; - } - /* Until we cannot anymore, and we fill the remainder. */ - if (outlen > i * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_OUTPUT_BYTES) { - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_ull_to_bytes(input_plus_four_bytes + inlen, 4, i); - sha256(outbuf, input_plus_four_bytes, inlen + 4); - memcpy(out, outbuf, outlen - i * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_OUTPUT_BYTES); - } -} - - -/** - * Absorb the constant pub_seed using one round of the compression function - * This initializes hash_state_seeded, which can then be reused in thash - **/ -void PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_seed_state(sha256ctx *hash_state_seeded, const unsigned char *pub_seed) { - uint8_t block[PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_BLOCK_BYTES]; - size_t i; - - for (i = 0; i < PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N; ++i) { - block[i] = pub_seed[i]; - } - for (i = PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N; i < PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_BLOCK_BYTES; ++i) { - block[i] = 0; - } - - sha256_inc_init(hash_state_seeded); - sha256_inc_blocks(hash_state_seeded, block, 1); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_avx2/sha256.h b/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_avx2/sha256.h deleted file mode 100644 index 8790182b1c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_avx2/sha256.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_H -#define PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_H - -#define PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_BLOCK_BYTES 64 -#define PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_OUTPUT_BYTES 32 /* This does not necessarily equal PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N */ -#define PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_ADDR_BYTES 22 - -#include -#include - -#include "sha2.h" - -void PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_compress_address(unsigned char *out, const uint32_t addr[8]); - -void PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_mgf1( - unsigned char *out, unsigned long outlen, - unsigned char *input_plus_four_bytes, unsigned long inlen); - -void PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_seed_state(sha256ctx *hash_state_seeded, const unsigned char *pub_seed); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_avx2/sha256avx.c b/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_avx2/sha256avx.c deleted file mode 100644 index 0ee0c434dc..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_avx2/sha256avx.c +++ /dev/null @@ -1,296 +0,0 @@ -#include -#include -#include - -#include "sha256avx.h" - -// Transpose 8 vectors containing 32-bit values -void PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_transpose(u256 s[8]) { - u256 tmp0[8]; - u256 tmp1[8]; - tmp0[0] = _mm256_unpacklo_epi32(s[0], s[1]); - tmp0[1] = _mm256_unpackhi_epi32(s[0], s[1]); - tmp0[2] = _mm256_unpacklo_epi32(s[2], s[3]); - tmp0[3] = _mm256_unpackhi_epi32(s[2], s[3]); - tmp0[4] = _mm256_unpacklo_epi32(s[4], s[5]); - tmp0[5] = _mm256_unpackhi_epi32(s[4], s[5]); - tmp0[6] = _mm256_unpacklo_epi32(s[6], s[7]); - tmp0[7] = _mm256_unpackhi_epi32(s[6], s[7]); - tmp1[0] = _mm256_unpacklo_epi64(tmp0[0], tmp0[2]); - tmp1[1] = _mm256_unpackhi_epi64(tmp0[0], tmp0[2]); - tmp1[2] = _mm256_unpacklo_epi64(tmp0[1], tmp0[3]); - tmp1[3] = _mm256_unpackhi_epi64(tmp0[1], tmp0[3]); - tmp1[4] = _mm256_unpacklo_epi64(tmp0[4], tmp0[6]); - tmp1[5] = _mm256_unpackhi_epi64(tmp0[4], tmp0[6]); - tmp1[6] = _mm256_unpacklo_epi64(tmp0[5], tmp0[7]); - tmp1[7] = _mm256_unpackhi_epi64(tmp0[5], tmp0[7]); - s[0] = _mm256_permute2x128_si256(tmp1[0], tmp1[4], 0x20); - s[1] = _mm256_permute2x128_si256(tmp1[1], tmp1[5], 0x20); - s[2] = _mm256_permute2x128_si256(tmp1[2], tmp1[6], 0x20); - s[3] = _mm256_permute2x128_si256(tmp1[3], tmp1[7], 0x20); - s[4] = _mm256_permute2x128_si256(tmp1[0], tmp1[4], 0x31); - s[5] = _mm256_permute2x128_si256(tmp1[1], tmp1[5], 0x31); - s[6] = _mm256_permute2x128_si256(tmp1[2], tmp1[6], 0x31); - s[7] = _mm256_permute2x128_si256(tmp1[3], tmp1[7], 0x31); -} - -void PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_sha256_clone_statex8(sha256ctxx8 *outctx, const sha256ctxx8 *inctx) { - memcpy(outctx, inctx, sizeof(sha256ctxx8)); -} - -void PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_sha256_init8x(sha256ctxx8 *ctx) { - ctx->s[0] = _mm256_set_epi32((int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667); - ctx->s[1] = _mm256_set_epi32((int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85); - ctx->s[2] = _mm256_set_epi32((int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372); - ctx->s[3] = _mm256_set_epi32((int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a); - ctx->s[4] = _mm256_set_epi32((int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f); - ctx->s[5] = _mm256_set_epi32((int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c); - ctx->s[6] = _mm256_set_epi32((int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab); - ctx->s[7] = _mm256_set_epi32((int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19); - - ctx->datalen = 0; - ctx->msglen = 0; -} - -void PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_sha256_update8x(sha256ctxx8 *ctx, - const unsigned char *d0, - const unsigned char *d1, - const unsigned char *d2, - const unsigned char *d3, - const unsigned char *d4, - const unsigned char *d5, - const unsigned char *d6, - const unsigned char *d7, - unsigned long long len) { - size_t i = 0; - size_t bytes_to_copy; - - while (i < len) { - bytes_to_copy = (size_t)len - i; - if (bytes_to_copy > 64) { - bytes_to_copy = 64; - } - memcpy(&ctx->msgblocks[64 * 0], d0 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64 * 1], d1 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64 * 2], d2 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64 * 3], d3 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64 * 4], d4 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64 * 5], d5 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64 * 6], d6 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64 * 7], d7 + i, bytes_to_copy); - ctx->datalen += (unsigned int)bytes_to_copy; - i += bytes_to_copy; - if (ctx->datalen == 64) { - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_sha256_transform8x(ctx, ctx->msgblocks); - ctx->msglen += 512; - ctx->datalen = 0; - } - } -} - -void PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_sha256_final8x(sha256ctxx8 *ctx, - unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7) { - unsigned int i, curlen; - - // Padding - if (ctx->datalen < 56) { - for (i = 0; i < 8; ++i) { - curlen = ctx->datalen; - ctx->msgblocks[64 * i + curlen++] = 0x80; - while (curlen < 64) { - ctx->msgblocks[64 * i + curlen++] = 0x00; - } - } - } else { - for (i = 0; i < 8; ++i) { - curlen = ctx->datalen; - ctx->msgblocks[64 * i + curlen++] = 0x80; - while (curlen < 64) { - ctx->msgblocks[64 * i + curlen++] = 0x00; - } - } - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_sha256_transform8x(ctx, ctx->msgblocks); - memset(ctx->msgblocks, 0, 8 * 64); - } - - // Add length of the message to each block - ctx->msglen += ctx->datalen * 8; - for (i = 0; i < 8; i++) { - ctx->msgblocks[64 * i + 63] = (unsigned char)ctx->msglen; - ctx->msgblocks[64 * i + 62] = (unsigned char)(ctx->msglen >> 8); - ctx->msgblocks[64 * i + 61] = (unsigned char)(ctx->msglen >> 16); - ctx->msgblocks[64 * i + 60] = (unsigned char)(ctx->msglen >> 24); - ctx->msgblocks[64 * i + 59] = (unsigned char)(ctx->msglen >> 32); - ctx->msgblocks[64 * i + 58] = (unsigned char)(ctx->msglen >> 40); - ctx->msgblocks[64 * i + 57] = (unsigned char)(ctx->msglen >> 48); - ctx->msgblocks[64 * i + 56] = (unsigned char)(ctx->msglen >> 56); - } - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_sha256_transform8x(ctx, ctx->msgblocks); - - // Compute final hash output - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_transpose(ctx->s); - - // Store Hash value - STORE(out0, BYTESWAP(ctx->s[0])); - STORE(out1, BYTESWAP(ctx->s[1])); - STORE(out2, BYTESWAP(ctx->s[2])); - STORE(out3, BYTESWAP(ctx->s[3])); - STORE(out4, BYTESWAP(ctx->s[4])); - STORE(out5, BYTESWAP(ctx->s[5])); - STORE(out6, BYTESWAP(ctx->s[6])); - STORE(out7, BYTESWAP(ctx->s[7])); -} - -void PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_sha256_transform8x(sha256ctxx8 *ctx, const unsigned char *data) { - u256 s[8], w[64], T0, T1; - int i; - - // Load words and transform data correctly - for (i = 0; i < 8; i++) { - w[i] = BYTESWAP(LOAD(data + 64 * i)); - w[i + 8] = BYTESWAP(LOAD(data + 32 + 64 * i)); - } - - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_transpose(w); - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_transpose(w + 8); - - // Initial State - s[0] = ctx->s[0]; - s[1] = ctx->s[1]; - s[2] = ctx->s[2]; - s[3] = ctx->s[3]; - s[4] = ctx->s[4]; - s[5] = ctx->s[5]; - s[6] = ctx->s[6]; - s[7] = ctx->s[7]; - - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 0, w[0]); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 1, w[1]); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 2, w[2]); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 3, w[3]); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 4, w[4]); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 5, w[5]); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 6, w[6]); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 7, w[7]); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 8, w[8]); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 9, w[9]); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 10, w[10]); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 11, w[11]); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 12, w[12]); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 13, w[13]); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 14, w[14]); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 15, w[15]); - w[16] = ADD4_32(WSIGMA1_AVX(w[14]), w[0], w[9], WSIGMA0_AVX(w[1])); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 16, w[16]); - w[17] = ADD4_32(WSIGMA1_AVX(w[15]), w[1], w[10], WSIGMA0_AVX(w[2])); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 17, w[17]); - w[18] = ADD4_32(WSIGMA1_AVX(w[16]), w[2], w[11], WSIGMA0_AVX(w[3])); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 18, w[18]); - w[19] = ADD4_32(WSIGMA1_AVX(w[17]), w[3], w[12], WSIGMA0_AVX(w[4])); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 19, w[19]); - w[20] = ADD4_32(WSIGMA1_AVX(w[18]), w[4], w[13], WSIGMA0_AVX(w[5])); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 20, w[20]); - w[21] = ADD4_32(WSIGMA1_AVX(w[19]), w[5], w[14], WSIGMA0_AVX(w[6])); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 21, w[21]); - w[22] = ADD4_32(WSIGMA1_AVX(w[20]), w[6], w[15], WSIGMA0_AVX(w[7])); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 22, w[22]); - w[23] = ADD4_32(WSIGMA1_AVX(w[21]), w[7], w[16], WSIGMA0_AVX(w[8])); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 23, w[23]); - w[24] = ADD4_32(WSIGMA1_AVX(w[22]), w[8], w[17], WSIGMA0_AVX(w[9])); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 24, w[24]); - w[25] = ADD4_32(WSIGMA1_AVX(w[23]), w[9], w[18], WSIGMA0_AVX(w[10])); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 25, w[25]); - w[26] = ADD4_32(WSIGMA1_AVX(w[24]), w[10], w[19], WSIGMA0_AVX(w[11])); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 26, w[26]); - w[27] = ADD4_32(WSIGMA1_AVX(w[25]), w[11], w[20], WSIGMA0_AVX(w[12])); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 27, w[27]); - w[28] = ADD4_32(WSIGMA1_AVX(w[26]), w[12], w[21], WSIGMA0_AVX(w[13])); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 28, w[28]); - w[29] = ADD4_32(WSIGMA1_AVX(w[27]), w[13], w[22], WSIGMA0_AVX(w[14])); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 29, w[29]); - w[30] = ADD4_32(WSIGMA1_AVX(w[28]), w[14], w[23], WSIGMA0_AVX(w[15])); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 30, w[30]); - w[31] = ADD4_32(WSIGMA1_AVX(w[29]), w[15], w[24], WSIGMA0_AVX(w[16])); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 31, w[31]); - w[32] = ADD4_32(WSIGMA1_AVX(w[30]), w[16], w[25], WSIGMA0_AVX(w[17])); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 32, w[32]); - w[33] = ADD4_32(WSIGMA1_AVX(w[31]), w[17], w[26], WSIGMA0_AVX(w[18])); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 33, w[33]); - w[34] = ADD4_32(WSIGMA1_AVX(w[32]), w[18], w[27], WSIGMA0_AVX(w[19])); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 34, w[34]); - w[35] = ADD4_32(WSIGMA1_AVX(w[33]), w[19], w[28], WSIGMA0_AVX(w[20])); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 35, w[35]); - w[36] = ADD4_32(WSIGMA1_AVX(w[34]), w[20], w[29], WSIGMA0_AVX(w[21])); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 36, w[36]); - w[37] = ADD4_32(WSIGMA1_AVX(w[35]), w[21], w[30], WSIGMA0_AVX(w[22])); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 37, w[37]); - w[38] = ADD4_32(WSIGMA1_AVX(w[36]), w[22], w[31], WSIGMA0_AVX(w[23])); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 38, w[38]); - w[39] = ADD4_32(WSIGMA1_AVX(w[37]), w[23], w[32], WSIGMA0_AVX(w[24])); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 39, w[39]); - w[40] = ADD4_32(WSIGMA1_AVX(w[38]), w[24], w[33], WSIGMA0_AVX(w[25])); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 40, w[40]); - w[41] = ADD4_32(WSIGMA1_AVX(w[39]), w[25], w[34], WSIGMA0_AVX(w[26])); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 41, w[41]); - w[42] = ADD4_32(WSIGMA1_AVX(w[40]), w[26], w[35], WSIGMA0_AVX(w[27])); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 42, w[42]); - w[43] = ADD4_32(WSIGMA1_AVX(w[41]), w[27], w[36], WSIGMA0_AVX(w[28])); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 43, w[43]); - w[44] = ADD4_32(WSIGMA1_AVX(w[42]), w[28], w[37], WSIGMA0_AVX(w[29])); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 44, w[44]); - w[45] = ADD4_32(WSIGMA1_AVX(w[43]), w[29], w[38], WSIGMA0_AVX(w[30])); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 45, w[45]); - w[46] = ADD4_32(WSIGMA1_AVX(w[44]), w[30], w[39], WSIGMA0_AVX(w[31])); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 46, w[46]); - w[47] = ADD4_32(WSIGMA1_AVX(w[45]), w[31], w[40], WSIGMA0_AVX(w[32])); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 47, w[47]); - w[48] = ADD4_32(WSIGMA1_AVX(w[46]), w[32], w[41], WSIGMA0_AVX(w[33])); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 48, w[48]); - w[49] = ADD4_32(WSIGMA1_AVX(w[47]), w[33], w[42], WSIGMA0_AVX(w[34])); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 49, w[49]); - w[50] = ADD4_32(WSIGMA1_AVX(w[48]), w[34], w[43], WSIGMA0_AVX(w[35])); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 50, w[50]); - w[51] = ADD4_32(WSIGMA1_AVX(w[49]), w[35], w[44], WSIGMA0_AVX(w[36])); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 51, w[51]); - w[52] = ADD4_32(WSIGMA1_AVX(w[50]), w[36], w[45], WSIGMA0_AVX(w[37])); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 52, w[52]); - w[53] = ADD4_32(WSIGMA1_AVX(w[51]), w[37], w[46], WSIGMA0_AVX(w[38])); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 53, w[53]); - w[54] = ADD4_32(WSIGMA1_AVX(w[52]), w[38], w[47], WSIGMA0_AVX(w[39])); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 54, w[54]); - w[55] = ADD4_32(WSIGMA1_AVX(w[53]), w[39], w[48], WSIGMA0_AVX(w[40])); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 55, w[55]); - w[56] = ADD4_32(WSIGMA1_AVX(w[54]), w[40], w[49], WSIGMA0_AVX(w[41])); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 56, w[56]); - w[57] = ADD4_32(WSIGMA1_AVX(w[55]), w[41], w[50], WSIGMA0_AVX(w[42])); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 57, w[57]); - w[58] = ADD4_32(WSIGMA1_AVX(w[56]), w[42], w[51], WSIGMA0_AVX(w[43])); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 58, w[58]); - w[59] = ADD4_32(WSIGMA1_AVX(w[57]), w[43], w[52], WSIGMA0_AVX(w[44])); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 59, w[59]); - w[60] = ADD4_32(WSIGMA1_AVX(w[58]), w[44], w[53], WSIGMA0_AVX(w[45])); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 60, w[60]); - w[61] = ADD4_32(WSIGMA1_AVX(w[59]), w[45], w[54], WSIGMA0_AVX(w[46])); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 61, w[61]); - w[62] = ADD4_32(WSIGMA1_AVX(w[60]), w[46], w[55], WSIGMA0_AVX(w[47])); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 62, w[62]); - w[63] = ADD4_32(WSIGMA1_AVX(w[61]), w[47], w[56], WSIGMA0_AVX(w[48])); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 63, w[63]); - - // Feed Forward - ctx->s[0] = ADD32(s[0], ctx->s[0]); - ctx->s[1] = ADD32(s[1], ctx->s[1]); - ctx->s[2] = ADD32(s[2], ctx->s[2]); - ctx->s[3] = ADD32(s[3], ctx->s[3]); - ctx->s[4] = ADD32(s[4], ctx->s[4]); - ctx->s[5] = ADD32(s[5], ctx->s[5]); - ctx->s[6] = ADD32(s[6], ctx->s[6]); - ctx->s[7] = ADD32(s[7], ctx->s[7]); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_avx2/sha256avx.h b/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_avx2/sha256avx.h deleted file mode 100644 index f28a9e7c9b..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_avx2/sha256avx.h +++ /dev/null @@ -1,103 +0,0 @@ -#ifndef SHA256AVX_H -#define SHA256AVX_H - -#include -#include - -static const unsigned int RC[] = { - 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, - 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, - 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, - 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, - 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, - 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, - 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, - 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, - 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, - 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, - 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, - 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, - 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, - 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, - 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, - 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 -}; - -#define u32 uint32_t -#define u256 __m256i - -#define XOR _mm256_xor_si256 -#define OR _mm256_or_si256 -#define AND _mm256_and_si256 -#define ADD32 _mm256_add_epi32 -#define NOT(x) _mm256_xor_si256(x, _mm256_set_epi32(-1, -1, -1, -1, -1, -1, -1, -1)) - -#define LOAD(src) _mm256_loadu_si256((__m256i *)(src)) -#define STORE(dest,src) _mm256_storeu_si256((__m256i *)(dest),src) - -#define BYTESWAP(x) _mm256_shuffle_epi8(x, _mm256_set_epi8(0xc,0xd,0xe,0xf,0x8,0x9,0xa,0xb,0x4,0x5,0x6,0x7,0x0,0x1,0x2,0x3,0xc,0xd,0xe,0xf,0x8,0x9,0xa,0xb,0x4,0x5,0x6,0x7,0x0,0x1,0x2,0x3)) - -#define SHIFTR32(x, y) _mm256_srli_epi32(x, y) -#define SHIFTL32(x, y) _mm256_slli_epi32(x, y) - -#define ROTR32(x, y) OR(SHIFTR32(x, y), SHIFTL32(x, 32 - (y))) -#define ROTL32(x, y) OR(SHIFTL32(x, y), SHIFTR32(x, 32 - (y))) - -#define XOR3(a, b, c) XOR(XOR(a, b), c) - -#define ADD3_32(a, b, c) ADD32(ADD32(a, b), c) -#define ADD4_32(a, b, c, d) ADD32(ADD32(ADD32(a, b), c), d) -#define ADD5_32(a, b, c, d, e) ADD32(ADD32(ADD32(ADD32(a, b), c), d), e) - -#define MAJ_AVX(a, b, c) XOR3(AND(a, b), AND(a, c), AND(b, c)) -#define CH_AVX(a, b, c) XOR(AND(a, b), AND(NOT(a), c)) - -#define SIGMA1_AVX(x) XOR3(ROTR32(x, 6), ROTR32(x, 11), ROTR32(x, 25)) -#define SIGMA0_AVX(x) XOR3(ROTR32(x, 2), ROTR32(x, 13), ROTR32(x, 22)) - -#define WSIGMA1_AVX(x) XOR3(ROTR32(x, 17), ROTR32(x, 19), SHIFTR32(x, 10)) -#define WSIGMA0_AVX(x) XOR3(ROTR32(x, 7), ROTR32(x, 18), SHIFTR32(x, 3)) - -#define SHA256ROUND_AVX(a, b, c, d, e, f, g, h, rc, w) \ - T0 = ADD5_32(h, SIGMA1_AVX(e), CH_AVX(e, f, g), _mm256_set1_epi32((int)RC[rc]), w); \ - (d) = ADD32(d, T0); \ - T1 = ADD32(SIGMA0_AVX(a), MAJ_AVX(a, b, c)); \ - (h) = ADD32(T0, T1); - -typedef struct SHA256state { - u256 s[8]; - uint8_t msgblocks[8 * 64]; - unsigned int datalen; - uint64_t msglen; -} sha256ctxx8; - - -void PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_transpose(u256 s[8]); -void PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_sha256_init_frombytes_x8(sha256ctxx8 *ctx, const uint8_t *s, unsigned long long msglen); -void PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_sha256_init8x(sha256ctxx8 *ctx); -void PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_sha256_update8x(sha256ctxx8 *ctx, - const unsigned char *d0, - const unsigned char *d1, - const unsigned char *d2, - const unsigned char *d3, - const unsigned char *d4, - const unsigned char *d5, - const unsigned char *d6, - const unsigned char *d7, - unsigned long long len); -void PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_sha256_final8x(sha256ctxx8 *ctx, - unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7); - -void PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_sha256_transform8x(sha256ctxx8 *ctx, const unsigned char *data); - -void PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_sha256_clone_statex8(sha256ctxx8 *outctx, const sha256ctxx8 *inctx); - - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_avx2/sha256x8.c b/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_avx2/sha256x8.c deleted file mode 100644 index 36767bcaa0..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_avx2/sha256x8.c +++ /dev/null @@ -1,128 +0,0 @@ -#include - -#include "sha256.h" -#include "sha256avx.h" -#include "sha256x8.h" -#include "utils.h" - -void PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_seed_statex8(sha256ctxx8 *ctx, const unsigned char *pub_seed) { - uint8_t block[PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_BLOCK_BYTES]; - size_t i; - - for (i = 0; i < PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N; ++i) { - block[i] = pub_seed[i]; - } - for (i = PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N; i < PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_BLOCK_BYTES; ++i) { - block[i] = 0; - } - - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_sha256_init8x(ctx); - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_sha256_update8x(ctx, block, block, block, block, block, block, block, block, PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_BLOCK_BYTES); - -} - -/* This provides a wrapper around the internals of 8x parallel SHA256 */ -void PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_sha256x8(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - const unsigned char *in4, - const unsigned char *in5, - const unsigned char *in6, - const unsigned char *in7, unsigned long long inlen) { - sha256ctxx8 ctx; - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_sha256_init8x(&ctx); - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_sha256_update8x(&ctx, in0, in1, in2, in3, in4, in5, in6, in7, inlen); - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_sha256_final8x(&ctx, out0, out1, out2, out3, out4, out5, out6, out7); -} - -/** - * Note that inlen should be sufficiently small that it still allows for - * an array to be allocated on the stack. Typically 'in' is merely a seed. - * Outputs outlen number of bytes - */ -void PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_mgf1x8( - unsigned char *outx8, - unsigned long outlen, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - const unsigned char *in4, - const unsigned char *in5, - const unsigned char *in6, - const unsigned char *in7, - unsigned long inlen) { - unsigned char inbufx8[8 * ((PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_ADDR_BYTES) + 4)]; - unsigned char outbufx8[8 * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_OUTPUT_BYTES]; - unsigned long i; - unsigned int j; - - memcpy(inbufx8 + 0 * (inlen + 4), in0, inlen); - memcpy(inbufx8 + 1 * (inlen + 4), in1, inlen); - memcpy(inbufx8 + 2 * (inlen + 4), in2, inlen); - memcpy(inbufx8 + 3 * (inlen + 4), in3, inlen); - memcpy(inbufx8 + 4 * (inlen + 4), in4, inlen); - memcpy(inbufx8 + 5 * (inlen + 4), in5, inlen); - memcpy(inbufx8 + 6 * (inlen + 4), in6, inlen); - memcpy(inbufx8 + 7 * (inlen + 4), in7, inlen); - - /* While we can fit in at least another full block of SHA256 output.. */ - for (i = 0; (i + 1)*PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_OUTPUT_BYTES <= outlen; i++) { - for (j = 0; j < 8; j++) { - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_ull_to_bytes(inbufx8 + inlen + j * (inlen + 4), 4, i); - } - - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_sha256x8(outx8 + 0 * outlen, - outx8 + 1 * outlen, - outx8 + 2 * outlen, - outx8 + 3 * outlen, - outx8 + 4 * outlen, - outx8 + 5 * outlen, - outx8 + 6 * outlen, - outx8 + 7 * outlen, - inbufx8 + 0 * (inlen + 4), - inbufx8 + 1 * (inlen + 4), - inbufx8 + 2 * (inlen + 4), - inbufx8 + 3 * (inlen + 4), - inbufx8 + 4 * (inlen + 4), - inbufx8 + 5 * (inlen + 4), - inbufx8 + 6 * (inlen + 4), - inbufx8 + 7 * (inlen + 4), inlen + 4); - outx8 += PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_OUTPUT_BYTES; - } - /* Until we cannot anymore, and we fill the remainder. */ - for (j = 0; j < 8; j++) { - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_ull_to_bytes(inbufx8 + inlen + j * (inlen + 4), 4, i); - } - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_sha256x8(outbufx8 + 0 * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 1 * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 2 * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 3 * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 4 * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 5 * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 6 * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 7 * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - inbufx8 + 0 * (inlen + 4), - inbufx8 + 1 * (inlen + 4), - inbufx8 + 2 * (inlen + 4), - inbufx8 + 3 * (inlen + 4), - inbufx8 + 4 * (inlen + 4), - inbufx8 + 5 * (inlen + 4), - inbufx8 + 6 * (inlen + 4), - inbufx8 + 7 * (inlen + 4), inlen + 4); - - for (j = 0; j < 8; j++) { - memcpy(outx8 + j * outlen, - outbufx8 + j * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outlen - i * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_OUTPUT_BYTES); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_avx2/sha256x8.h b/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_avx2/sha256x8.h deleted file mode 100644 index d174694d0a..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_avx2/sha256x8.h +++ /dev/null @@ -1,44 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256X8_H -#define PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256X8_H - -#include "sha256avx.h" - -#define PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_BLOCK_BYTES 64 -#define PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_OUTPUT_BYTES 32 /* This does not necessarily equal PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N */ - -/* This provides a wrapper around the internals of 8x parallel SHA256 */ -void PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_sha256x8(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - const unsigned char *in4, - const unsigned char *in5, - const unsigned char *in6, - const unsigned char *in7, unsigned long long inlen); - -/** - * Note that inlen should be sufficiently small that it still allows for - * an array to be allocated on the stack. Typically 'in' is merely a seed. - * Outputs outlen number of bytes - */ -void PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_mgf1x8(unsigned char *outx8, unsigned long outlen, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - const unsigned char *in4, - const unsigned char *in5, - const unsigned char *in6, - const unsigned char *in7, - unsigned long inlen); - -void PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_seed_statex8(sha256ctxx8 *ctx, const unsigned char *pub_seed); -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_avx2/sign.c b/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_avx2/sign.c deleted file mode 100644 index 1240991706..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_avx2/sign.c +++ /dev/null @@ -1,356 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "api.h" -#include "fors.h" -#include "hash.h" -#include "hash_state.h" -#include "params.h" -#include "randombytes.h" -#include "thash.h" -#include "utils.h" -#include "wots.h" - -/** - * Computes the leaf at a given address. First generates the WOTS key pair, - * then computes leaf by hashing horizontally. - */ -static void wots_gen_leaf(unsigned char *leaf, const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx, const uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - unsigned char pk[PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_WOTS_BYTES]; - uint32_t wots_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_set_type( - wots_addr, PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_set_type( - wots_pk_addr, PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_ADDR_TYPE_WOTSPK); - - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_set_keypair_addr( - wots_addr, addr_idx); - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_wots_gen_pk( - pk, sk_seed, pub_seed, wots_addr, hash_state_seeded); - - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_copy_keypair_addr( - wots_pk_addr, wots_addr); - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_thash_WOTS_LEN( - leaf, pk, pub_seed, wots_pk_addr, hash_state_seeded); -} - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_crypto_sign_secretkeybytes(void) { - return PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_CRYPTO_SECRETKEYBYTES; -} - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_crypto_sign_publickeybytes(void) { - return PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_CRYPTO_PUBLICKEYBYTES; -} - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_crypto_sign_bytes(void) { - return PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_CRYPTO_BYTES; -} - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_crypto_sign_seedbytes(void) { - return PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_CRYPTO_SEEDBYTES; -} - -/* - * Generates an SPX key pair given a seed of length - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed) { - /* We do not need the auth path in key generation, but it simplifies the - code to have just one treehash routine that computes both root and path - in one function. */ - unsigned char auth_path[PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_TREE_HEIGHT * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N]; - uint32_t top_tree_addr[8] = {0}; - hash_state hash_state_seeded; - - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_set_layer_addr( - top_tree_addr, PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_D - 1); - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_set_type( - top_tree_addr, PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_ADDR_TYPE_HASHTREE); - - /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ - memcpy(sk, seed, PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_CRYPTO_SEEDBYTES); - - memcpy(pk, sk + 2 * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N, PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_initialize_hash_function(&hash_state_seeded, pk, sk); - - /* Compute root node of the top-most subtree. */ - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_treehash_TREE_HEIGHT( - sk + 3 * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N, auth_path, sk, sk + 2 * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N, 0, 0, - wots_gen_leaf, top_tree_addr, &hash_state_seeded); - - memcpy(pk + PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N, sk + 3 * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N, PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N); - - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_destroy_hash_function(&hash_state_seeded); - return 0; -} - -/* - * Generates an SPX key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk) { - unsigned char seed[PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_CRYPTO_SEEDBYTES]; - randombytes(seed, PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_CRYPTO_SEEDBYTES); - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_crypto_sign_seed_keypair( - pk, sk, seed); - - return 0; -} - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - const unsigned char *sk_seed = sk; - const unsigned char *sk_prf = sk + PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N; - const unsigned char *pk = sk + 2 * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N; - const unsigned char *pub_seed = pk; - - unsigned char optrand[PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N]; - unsigned char mhash[PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_FORS_MSG_BYTES]; - unsigned char root[PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N]; - uint32_t i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - - hash_state hash_state_seeded; - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_initialize_hash_function( - &hash_state_seeded, - pub_seed, sk_seed); - - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_set_type( - wots_addr, PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_set_type( - tree_addr, PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_ADDR_TYPE_HASHTREE); - - /* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ - randombytes(optrand, PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N); - /* Compute the digest randomization value. */ - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_gen_message_random( - sig, sk_prf, optrand, m, mlen, &hash_state_seeded); - - /* Derive the message digest and leaf index from R, PK and M. */ - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N; - - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_set_keypair_addr( - wots_addr, idx_leaf); - - /* Sign the message hash using FORS. */ - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_fors_sign( - sig, root, mhash, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_FORS_BYTES; - - for (i = 0; i < PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_D; i++) { - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_set_tree_addr(tree_addr, tree); - - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_set_keypair_addr( - wots_addr, idx_leaf); - - /* Compute a WOTS signature. */ - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_wots_sign( - sig, root, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_WOTS_BYTES; - - /* Compute the authentication path for the used WOTS leaf. */ - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_treehash_TREE_HEIGHT( - root, sig, sk_seed, pub_seed, idx_leaf, 0, - wots_gen_leaf, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_TREE_HEIGHT * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_TREE_HEIGHT; - } - - *siglen = PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_BYTES; - - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_destroy_hash_function(&hash_state_seeded); - return 0; -} - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk) { - const unsigned char *pub_seed = pk; - const unsigned char *pub_root = pk + PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N; - unsigned char mhash[PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_FORS_MSG_BYTES]; - unsigned char wots_pk[PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_WOTS_BYTES]; - unsigned char root[PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N]; - unsigned char leaf[PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N]; - unsigned int i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - hash_state hash_state_seeded; - - if (siglen != PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_BYTES) { - return -1; - } - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_initialize_hash_function( - &hash_state_seeded, - pub_seed, NULL); - - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_set_type( - wots_addr, PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_set_type( - tree_addr, PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_ADDR_TYPE_HASHTREE); - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_set_type( - wots_pk_addr, PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_ADDR_TYPE_WOTSPK); - - /* Derive the message digest and leaf index from R || PK || M. */ - /* The additional PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N is a result of the hash domain separator. */ - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N; - - /* Layer correctly defaults to 0, so no need to set_layer_addr */ - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_set_keypair_addr( - wots_addr, idx_leaf); - - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_fors_pk_from_sig( - root, sig, mhash, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_FORS_BYTES; - - /* For each subtree.. */ - for (i = 0; i < PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_D; i++) { - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_set_tree_addr(tree_addr, tree); - - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_set_keypair_addr( - wots_addr, idx_leaf); - - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_copy_keypair_addr( - wots_pk_addr, wots_addr); - - /* The WOTS public key is only correct if the signature was correct. */ - /* Initially, root is the FORS pk, but on subsequent iterations it is - the root of the subtree below the currently processed subtree. */ - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_wots_pk_from_sig( - wots_pk, sig, root, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_WOTS_BYTES; - - /* Compute the leaf node using the WOTS public key. */ - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_thash_WOTS_LEN( - leaf, wots_pk, pub_seed, wots_pk_addr, &hash_state_seeded); - - /* Compute the root node of this subtree. */ - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_compute_root( - root, leaf, idx_leaf, 0, sig, PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_TREE_HEIGHT, - pub_seed, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_TREE_HEIGHT * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_TREE_HEIGHT; - } - - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_destroy_hash_function(&hash_state_seeded); - /* Check if the root node equals the root node in the public key. */ - if (memcmp(root, pub_root, PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N) != 0) { - return -1; - } - - return 0; -} - - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - size_t siglen; - - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_crypto_sign_signature( - sm, &siglen, m, mlen, sk); - - memmove(sm + PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_BYTES, m, mlen); - *smlen = siglen + mlen; - - return 0; -} - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk) { - /* The API caller does not necessarily know what size a signature should be - but SPHINCS+ signatures are always exactly PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_BYTES. */ - if (smlen < PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_BYTES) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - *mlen = smlen - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_BYTES; - - if (PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_crypto_sign_verify( - sm, PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_BYTES, sm + PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_BYTES, *mlen, pk)) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - /* If verification was successful, move the message to the right place. */ - memmove(m, sm + PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_BYTES, *mlen); - - return 0; -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_avx2/thash.h b/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_avx2/thash.h deleted file mode 100644 index e12735eebc..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_avx2/thash.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_THASH_H -#define PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_THASH_H - -#include "hash_state.h" - -#include - -void PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_avx2/thash_sha256_simple.c b/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_avx2/thash_sha256_simple.c deleted file mode 100644 index 2f900c56ed..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_avx2/thash_sha256_simple.c +++ /dev/null @@ -1,75 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "thash.h" - -#include "sha2.h" -#include "sha256.h" - -/** - * Takes an array of inblocks concatenated arrays of PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N bytes. - */ -static void PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_thash( - unsigned char *out, unsigned char *buf, - const unsigned char *in, unsigned int inblocks, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char outbuf[PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_OUTPUT_BYTES]; - sha256ctx sha2_state; - - (void)pub_seed; /* Suppress an 'unused parameter' warning. */ - - /* Retrieve precomputed state containing pub_seed */ - sha256_inc_ctx_clone(&sha2_state, &hash_state_seeded->x1); - - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_compress_address(buf, addr); - memcpy(buf + PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_ADDR_BYTES, in, inblocks * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N); - - sha256_inc_finalize(outbuf, &sha2_state, buf, PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N); - memcpy(out, outbuf, PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N); -} - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_ADDR_BYTES + 1 * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N]; - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_thash( - out, buf, in, 1, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_ADDR_BYTES + 2 * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N]; - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_thash( - out, buf, in, 2, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_ADDR_BYTES + PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_WOTS_LEN * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N]; - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_thash( - out, buf, in, PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_WOTS_LEN, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_ADDR_BYTES + PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_FORS_TREES * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N]; - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_thash( - out, buf, in, PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_FORS_TREES, pub_seed, addr, hash_state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_avx2/thash_sha256_simplex8.c b/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_avx2/thash_sha256_simplex8.c deleted file mode 100644 index 127e312811..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_avx2/thash_sha256_simplex8.c +++ /dev/null @@ -1,129 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash_state.h" -#include "params.h" -#include "sha256.h" -#include "sha256avx.h" -#include "sha256x8.h" -#include "thashx8.h" -#include "utils.h" - -/** - * 8-way parallel version of thash; takes 8x as much input and output - */ -static void thashx8(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - const unsigned char *in4, - const unsigned char *in5, - const unsigned char *in6, - const unsigned char *in7, unsigned int inblocks, - const unsigned char *pub_seed, uint32_t addrx8[8 * 8], - uint8_t *bufx8, - const hash_state *state_seeded) { - unsigned char outbufx8[8 * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_OUTPUT_BYTES]; - unsigned int i; - sha256ctxx8 ctx; - - (void)pub_seed; /* Suppress an 'unused parameter' warning. */ - - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_sha256_clone_statex8(&ctx, &state_seeded->x8); - - for (i = 0; i < 8; i++) { - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_compress_address(bufx8 + i * (PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N), - addrx8 + i * 8); - } - - memcpy(bufx8 + PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_ADDR_BYTES + - 0 * (PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N), in0, inblocks * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N); - memcpy(bufx8 + PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_ADDR_BYTES + - 1 * (PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N), in1, inblocks * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N); - memcpy(bufx8 + PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_ADDR_BYTES + - 2 * (PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N), in2, inblocks * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N); - memcpy(bufx8 + PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_ADDR_BYTES + - 3 * (PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N), in3, inblocks * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N); - memcpy(bufx8 + PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_ADDR_BYTES + - 4 * (PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N), in4, inblocks * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N); - memcpy(bufx8 + PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_ADDR_BYTES + - 5 * (PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N), in5, inblocks * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N); - memcpy(bufx8 + PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_ADDR_BYTES + - 6 * (PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N), in6, inblocks * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N); - memcpy(bufx8 + PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_ADDR_BYTES + - 7 * (PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N), in7, inblocks * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N); - - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_sha256_update8x(&ctx, - bufx8 + 0 * (PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N), - bufx8 + 1 * (PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N), - bufx8 + 2 * (PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N), - bufx8 + 3 * (PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N), - bufx8 + 4 * (PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N), - bufx8 + 5 * (PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N), - bufx8 + 6 * (PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N), - bufx8 + 7 * (PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N), - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N); - - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_sha256_final8x(&ctx, - outbufx8 + 0 * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 1 * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 2 * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 3 * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 4 * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 5 * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 6 * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 7 * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_OUTPUT_BYTES); - - memcpy(out0, outbufx8 + 0 * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N); - memcpy(out1, outbufx8 + 1 * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N); - memcpy(out2, outbufx8 + 2 * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N); - memcpy(out3, outbufx8 + 3 * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N); - memcpy(out4, outbufx8 + 4 * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N); - memcpy(out5, outbufx8 + 5 * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N); - memcpy(out6, outbufx8 + 6 * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N); - memcpy(out7, outbufx8 + 7 * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N); -} - -#define thashx8_variant_impl(name, size) \ - void PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_thashx8_##name(unsigned char *out0, \ - unsigned char *out1, \ - unsigned char *out2, \ - unsigned char *out3, \ - unsigned char *out4, \ - unsigned char *out5, \ - unsigned char *out6, \ - unsigned char *out7, \ - const unsigned char *in0, \ - const unsigned char *in1, \ - const unsigned char *in2, \ - const unsigned char *in3, \ - const unsigned char *in4, \ - const unsigned char *in5, \ - const unsigned char *in6, \ - const unsigned char *in7, \ - const unsigned char *pub_seed, \ - uint32_t addrx8[8*8], \ - const hash_state *state_seeded) \ - { \ - const unsigned int inblocks = (size); \ - uint8_t bufx8[8*(PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_SHA256_ADDR_BYTES + (size)*PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N)]; \ - thashx8(out0, out1, out2, out3, out4, out5, out6, out7, \ - in0, in1, in2, in3, in4, in5, in6, in7, inblocks, \ - pub_seed, addrx8, bufx8, state_seeded); \ - } - -thashx8_variant_impl(1, 1) -thashx8_variant_impl(2, 2) -thashx8_variant_impl(WOTS_LEN, PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_WOTS_LEN) -thashx8_variant_impl(FORS_TREES, PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_FORS_TREES) - -#undef thashx8_variant_impl diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_avx2/thashx8.h b/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_avx2/thashx8.h deleted file mode 100644 index 6b91ada32a..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_avx2/thashx8.h +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_THASHX8_H -#define PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_THASHX8_H - -#include - -#include "hash_state.h" -#include "sha256avx.h" - - -#define thashx8_variant(name) \ - void PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_thashx8_##name( \ - unsigned char *out0, \ - unsigned char *out1, \ - unsigned char *out2, \ - unsigned char *out3, \ - unsigned char *out4, \ - unsigned char *out5, \ - unsigned char *out6, \ - unsigned char *out7, \ - const unsigned char *in0, \ - const unsigned char *in1, \ - const unsigned char *in2, \ - const unsigned char *in3, \ - const unsigned char *in4, \ - const unsigned char *in5, \ - const unsigned char *in6, \ - const unsigned char *in7, \ - const unsigned char *pub_seed, \ - uint32_t addrx8[8*8], \ - const hash_state *state_seeded) - - -thashx8_variant(1); -thashx8_variant(2); -thashx8_variant(WOTS_LEN); -thashx8_variant(FORS_TREES); - -#undef thashx8_variant -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_avx2/utils.c b/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_avx2/utils.c deleted file mode 100644 index 795c553f05..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_avx2/utils.c +++ /dev/null @@ -1,199 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "hash_state.h" -#include "params.h" -#include "thash.h" -#include "utils.h" - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in) { - - /* Iterate over out in decreasing order, for big-endianness. */ - for (size_t i = outlen; i > 0; i--) { - out[i - 1] = in & 0xff; - in = in >> 8; - } -} - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_bytes_to_ull( - const unsigned char *in, size_t inlen) { - unsigned long long retval = 0; - - for (size_t i = 0; i < inlen; i++) { - retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); - } - return retval; -} - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - uint32_t i; - unsigned char buffer[2 * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N]; - - /* If leaf_idx is odd (last bit = 1), current path element is a right child - and auth_path has to go left. Otherwise it is the other way around. */ - if (leaf_idx & 1) { - memcpy(buffer + PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N, leaf, PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N); - } else { - memcpy(buffer, leaf, PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N); - memcpy(buffer + PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N, auth_path, PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N); - } - auth_path += PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N; - - for (i = 0; i < tree_height - 1; i++) { - leaf_idx >>= 1; - idx_offset >>= 1; - /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_set_tree_height(addr, i + 1); - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_set_tree_index( - addr, leaf_idx + idx_offset); - - /* Pick the right or left neighbor, depending on parity of the node. */ - if (leaf_idx & 1) { - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_thash_2( - buffer + PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N); - } else { - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_thash_2( - buffer, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer + PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N, auth_path, PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N); - } - auth_path += PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N; - } - - /* The last iteration is exceptional; we do not copy an auth_path node. */ - leaf_idx >>= 1; - idx_offset >>= 1; - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_set_tree_height(addr, tree_height); - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_set_tree_index( - addr, leaf_idx + idx_offset); - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_thash_2( - root, buffer, pub_seed, addr, hash_state_seeded); -} - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -static void PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_treehash( - unsigned char *root, unsigned char *auth_path, - unsigned char *stack, unsigned int *heights, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - - unsigned int offset = 0; - uint32_t idx; - uint32_t tree_idx; - - for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { - /* Add the next leaf node to the stack. */ - gen_leaf(stack + offset * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N, - sk_seed, pub_seed, idx + idx_offset, tree_addr, - hash_state_seeded); - offset++; - heights[offset - 1] = 0; - - /* If this is a node we need for the auth path.. */ - if ((leaf_idx ^ 0x1) == idx) { - memcpy(auth_path, stack + (offset - 1)*PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N, PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N); - } - - /* While the top-most nodes are of equal height.. */ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { - /* Compute index of the new node, in the next layer. */ - tree_idx = (idx >> (heights[offset - 1] + 1)); - - /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_set_tree_height( - tree_addr, heights[offset - 1] + 1); - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_set_tree_index( - tree_addr, tree_idx + (idx_offset >> (heights[offset - 1] + 1))); - /* Hash the top-most nodes from the stack together. */ - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_thash_2( - stack + (offset - 2)*PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N, stack + (offset - 2)*PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N, - pub_seed, tree_addr, hash_state_seeded); - offset--; - /* Note that the top-most node is now one layer higher. */ - heights[offset - 1]++; - - /* If this is a node we need for the auth path.. */ - if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_path + heights[offset - 1]*PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N, - stack + (offset - 1)*PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N, PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N); - } - } - } - memcpy(root, stack, PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N); -} - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_FORS_HEIGHT + 1)*PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N]; - unsigned int heights[PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_FORS_HEIGHT + 1]; - - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_FORS_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_TREE_HEIGHT + 1)*PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N]; - unsigned int heights[PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_TREE_HEIGHT + 1]; - - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_TREE_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_avx2/utils.h b/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_avx2/utils.h deleted file mode 100644 index a3eba0d4da..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_avx2/utils.h +++ /dev/null @@ -1,64 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_UTILS_H -#define PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_UTILS_H - -#include "hash_state.h" -#include "params.h" -#include -#include - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in); - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_bytes_to_ull( - const unsigned char *in, size_t inlen); - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -void PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_avx2/utilsx8.c b/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_avx2/utilsx8.c deleted file mode 100644 index 996731176e..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_avx2/utilsx8.c +++ /dev/null @@ -1,172 +0,0 @@ -#include - -#include "address.h" -#include "params.h" -#include "thashx8.h" -#include "utils.h" - -#include "utilsx8.h" - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -static void treehashx8(unsigned char *rootx8, unsigned char *auth_pathx8, - unsigned char *stackx8, unsigned int *heights, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t leaf_idx[8], uint32_t idx_offset[8], - uint32_t tree_height, - void (*gen_leafx8)( - unsigned char * /* leaf0 */, - unsigned char * /* leaf1 */, - unsigned char * /* leaf2 */, - unsigned char * /* leaf3 */, - unsigned char * /* leaf4 */, - unsigned char * /* leaf5 */, - unsigned char * /* leaf6 */, - unsigned char * /* leaf7 */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx0 */, - uint32_t /* addr_idx1 */, - uint32_t /* addr_idx2 */, - uint32_t /* addr_idx3 */, - uint32_t /* addr_idx4 */, - uint32_t /* addr_idx5 */, - uint32_t /* addr_idx6 */, - uint32_t /* addr_idx7 */, - const uint32_t[8] /* tree_addr */, - const hash_state * /* state_seeded */), - uint32_t tree_addrx8[8 * 8], - const hash_state *state_seeded) { - unsigned int offset = 0; - uint32_t idx; - uint32_t tree_idx; - unsigned int j; - - for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { - /* Add the next leaf node to the stack. */ - gen_leafx8(stackx8 + 0 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N + offset * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N, - stackx8 + 1 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N + offset * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N, - stackx8 + 2 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N + offset * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N, - stackx8 + 3 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N + offset * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N, - stackx8 + 4 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N + offset * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N, - stackx8 + 5 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N + offset * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N, - stackx8 + 6 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N + offset * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N, - stackx8 + 7 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N + offset * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N, - sk_seed, pub_seed, - idx + idx_offset[0], - idx + idx_offset[1], - idx + idx_offset[2], - idx + idx_offset[3], - idx + idx_offset[4], - idx + idx_offset[5], - idx + idx_offset[6], - idx + idx_offset[7], - tree_addrx8, - state_seeded); - offset++; - heights[offset - 1] = 0; - - /* If this is a node we need for the auth path.. */ - for (j = 0; j < 8; j++) { - if ((leaf_idx[j] ^ 0x1) == idx) { - memcpy(auth_pathx8 + j * tree_height * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N, - stackx8 + j * (tree_height + 1)*PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N + (offset - 1)*PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N, PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N); - } - } - - /* While the top-most nodes are of equal height.. */ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { - /* Compute index of the new node, in the next layer. */ - tree_idx = (idx >> (heights[offset - 1] + 1)); - - /* Set the address of the node we're creating. */ - for (j = 0; j < 8; j++) { - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_set_tree_height(tree_addrx8 + j * 8, heights[offset - 1] + 1); - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_set_tree_index(tree_addrx8 + j * 8, - tree_idx + (idx_offset[j] >> (heights[offset - 1] + 1))); - } - /* Hash the top-most nodes from the stack together. */ - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_thashx8_2(stackx8 + 0 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N, - stackx8 + 1 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N, - stackx8 + 2 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N, - stackx8 + 3 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N, - stackx8 + 4 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N, - stackx8 + 5 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N, - stackx8 + 6 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N, - stackx8 + 7 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N, - stackx8 + 0 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N, - stackx8 + 1 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N, - stackx8 + 2 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N, - stackx8 + 3 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N, - stackx8 + 4 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N, - stackx8 + 5 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N, - stackx8 + 6 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N, - stackx8 + 7 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N, - pub_seed, tree_addrx8, state_seeded); - offset--; - /* Note that the top-most node is now one layer higher. */ - heights[offset - 1]++; - - /* If this is a node we need for the auth path.. */ - for (j = 0; j < 8; j++) { - if (((leaf_idx[j] >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_pathx8 + j * tree_height * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N + heights[offset - 1]*PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N, - stackx8 + j * (tree_height + 1)*PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N + (offset - 1)*PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N, PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N); - } - } - } - } - - for (j = 0; j < 8; j++) { - memcpy(rootx8 + j * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N, stackx8 + j * (tree_height + 1)*PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N, PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N); - } -} - -/* The wrappers below ensure we used fixed-size buffers on the stack (no VLAs) */ - - -#define treehashx8_variant(name, size) \ - void PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_treehashx8_##name( \ - unsigned char *rootx8, unsigned char *auth_pathx8, \ - const unsigned char *sk_seed, const unsigned char *pub_seed, \ - const uint32_t leaf_idx[8], uint32_t idx_offset[8], \ - void (*gen_leafx8)( \ - unsigned char* /* leaf0 */, \ - unsigned char* /* leaf1 */, \ - unsigned char* /* leaf2 */, \ - unsigned char* /* leaf3 */, \ - unsigned char* /* leaf4 */, \ - unsigned char* /* leaf5 */, \ - unsigned char* /* leaf6 */, \ - unsigned char* /* leaf7 */, \ - const unsigned char* /* sk_seed */, \ - const unsigned char* /* pub_seed */, \ - uint32_t /* addr_idx0 */, \ - uint32_t /* addr_idx1 */, \ - uint32_t /* addr_idx2 */, \ - uint32_t /* addr_idx3 */, \ - uint32_t /* addr_idx4 */, \ - uint32_t /* addr_idx5 */, \ - uint32_t /* addr_idx6 */, \ - uint32_t /* addr_idx7 */, \ - const uint32_t[8] /* tree_addr */, \ - const hash_state* /* state_seeded */), \ - uint32_t tree_addrx8[8*8], \ - const hash_state *state_seeded) \ - { \ - const uint32_t tree_height = (size); \ - unsigned char stackx8[8*((size) + 1)*PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N]; \ - unsigned int heights[(size) + 1]; \ - treehashx8(rootx8, auth_pathx8, stackx8, heights, sk_seed, pub_seed, \ - leaf_idx, idx_offset, tree_height, gen_leafx8, tree_addrx8, state_seeded); \ - } - -treehashx8_variant(FORS_HEIGHT, PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_FORS_HEIGHT) - -#undef treehashx8_variant diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_avx2/utilsx8.h b/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_avx2/utilsx8.h deleted file mode 100644 index d63de06901..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_avx2/utilsx8.h +++ /dev/null @@ -1,46 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_UTILSX8_H -#define PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_UTILSX8_H - -#include - -#include "hash_state.h" -#include "params.h" - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ - -void PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_treehashx8_FORS_HEIGHT( - unsigned char *rootx8, unsigned char *auth_pathx8, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t leaf_idx[8], uint32_t idx_offset[8], - void (*gen_leafx8)( - unsigned char * /* leaf0 */, - unsigned char * /* leaf1 */, - unsigned char * /* leaf2 */, - unsigned char * /* leaf3 */, - unsigned char * /* leaf4 */, - unsigned char * /* leaf5 */, - unsigned char * /* leaf6 */, - unsigned char * /* leaf7 */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx0 */, - uint32_t /* addr_idx1 */, - uint32_t /* addr_idx2 */, - uint32_t /* addr_idx3 */, - uint32_t /* addr_idx4 */, - uint32_t /* addr_idx5 */, - uint32_t /* addr_idx6 */, - uint32_t /* addr_idx7 */, - const uint32_t[8] /* tree_addr */, - const hash_state * /* state_seeded */), - uint32_t tree_addrx8[8 * 8], - const hash_state *state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_avx2/wots.c b/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_avx2/wots.c deleted file mode 100644 index ca4af0c50e..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_avx2/wots.c +++ /dev/null @@ -1,240 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "hash_state.h" -#include "hashx8.h" -#include "params.h" -#include "thash.h" -#include "thashx8.h" -#include "utils.h" -#include "wots.h" - -// TODO clarify address expectations, and make them more uniform. -// TODO i.e. do we expect types to be set already? -// TODO and do we expect modifications or copies? - -/** - * Computes the starting value for a chain, i.e. the secret key. - * Expects the address to be complete up to the chain address. - */ -static void wots_gen_sk(unsigned char *sk, const unsigned char *sk_seed, - uint32_t wots_addr[8], const hash_state *state_seeded) { - /* Make sure that the hash address is actually zeroed. */ - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_set_hash_addr(wots_addr, 0); - - /* Generate sk element. */ - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_prf_addr(sk, sk_seed, wots_addr, state_seeded); -} - -/** - * 8-way parallel version of wots_gen_sk; expects 8x as much space in sk - */ -static void wots_gen_skx8(unsigned char *skx8, const unsigned char *sk_seed, - uint32_t wots_addrx8[8 * 8]) { - unsigned int j; - - /* Make sure that the hash address is actually zeroed. */ - for (j = 0; j < 8; j++) { - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_set_hash_addr(wots_addrx8 + j * 8, 0); - } - - /* Generate sk element. */ - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_prf_addrx8(skx8 + 0 * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N, - skx8 + 1 * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N, - skx8 + 2 * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N, - skx8 + 3 * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N, - skx8 + 4 * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N, - skx8 + 5 * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N, - skx8 + 6 * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N, - skx8 + 7 * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N, - sk_seed, wots_addrx8); -} - -/** - * Computes the chaining function. - * out and in have to be n-byte arrays. - * - * Interprets in as start-th value of the chain. - * addr has to contain the address of the chain. - */ -static void gen_chain(unsigned char *out, const unsigned char *in, - unsigned int start, unsigned int steps, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *state_seeded) { - uint32_t i; - - /* Initialize out with the value at position 'start'. */ - memcpy(out, in, PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N); - - /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_WOTS_W; i++) { - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_set_hash_addr(addr, i); - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_thash_1(out, out, pub_seed, addr, state_seeded); - } -} - -/** - * 8-way parallel version of gen_chain; expects 8x as much space in out, and - * 8x as much space in inx8. Assumes start and step identical across chains. - */ -static void gen_chainx8(unsigned char *outx8, const unsigned char *inx8, - unsigned int start, unsigned int steps, - const unsigned char *pub_seed, uint32_t addrx8[8 * 8], - const hash_state *state_seeded) { - uint32_t i; - unsigned int j; - - /* Initialize outx8 with the value at position 'start'. */ - memcpy(outx8, inx8, 8 * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N); - - /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_WOTS_W; i++) { - for (j = 0; j < 8; j++) { - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_set_hash_addr(addrx8 + j * 8, i); - } - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_thashx8_1(outx8 + 0 * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N, - outx8 + 1 * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N, - outx8 + 2 * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N, - outx8 + 3 * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N, - outx8 + 4 * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N, - outx8 + 5 * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N, - outx8 + 6 * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N, - outx8 + 7 * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N, - outx8 + 0 * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N, - outx8 + 1 * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N, - outx8 + 2 * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N, - outx8 + 3 * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N, - outx8 + 4 * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N, - outx8 + 5 * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N, - outx8 + 6 * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N, - outx8 + 7 * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N, - pub_seed, addrx8, state_seeded); - } -} - -/** - * base_w algorithm as described in draft. - * Interprets an array of bytes as integers in base w. - * This only works when log_w is a divisor of 8. - */ -static void base_w(unsigned int *output, const int out_len, const unsigned char *input) { - int in = 0; - int out = 0; - unsigned char total = 0; - int bits = 0; - int consumed; - - for (consumed = 0; consumed < out_len; consumed++) { - if (bits == 0) { - total = input[in]; - in++; - bits += 8; - } - bits -= PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_WOTS_LOGW; - output[out] = (unsigned int)(total >> bits) & (PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_WOTS_W - 1); - out++; - } -} - -/* Computes the WOTS+ checksum over a message (in base_w). */ -static void wots_checksum(unsigned int *csum_base_w, const unsigned int *msg_base_w) { - unsigned int csum = 0; - unsigned char csum_bytes[(PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_WOTS_LEN2 * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_WOTS_LOGW + 7) / 8]; - unsigned int i; - - /* Compute checksum. */ - for (i = 0; i < PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_WOTS_LEN1; i++) { - csum += PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_WOTS_W - 1 - msg_base_w[i]; - } - - /* Convert checksum to base_w. */ - /* Make sure expected empty zero bits are the least significant bits. */ - csum = csum << (8 - ((PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_WOTS_LEN2 * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_WOTS_LOGW) % 8)); - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); - base_w(csum_base_w, PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_WOTS_LEN2, csum_bytes); -} - -/* Takes a message and derives the matching chain lengths. */ -static void chain_lengths(unsigned int *lengths, const unsigned char *msg) { - base_w(lengths, PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_WOTS_LEN1, msg); - wots_checksum(lengths + PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_WOTS_LEN1, lengths); -} - -/** - * WOTS key generation. Takes a 32 byte sk_seed, expands it to WOTS private key - * elements and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_wots_gen_pk(unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *state_seeded) { - uint32_t i; - unsigned int j; - - uint32_t addrx8[8 * 8]; - unsigned char pkbuf[8 * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N]; - - for (j = 0; j < 8; j++) { - memcpy(addrx8 + j * 8, addr, sizeof(uint32_t) * 8); - } - - /* The last iteration typically does not have complete set of 4 chains, - but because we use pkbuf, this is not an issue -- we still do as many - in parallel as possible. */ - for (i = 0; i < ((PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_WOTS_LEN + 7) & ~0x7); i += 8) { - for (j = 0; j < 8; j++) { - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_set_chain_addr(addrx8 + j * 8, i + j); - } - wots_gen_skx8(pkbuf, sk_seed, addrx8); - gen_chainx8(pkbuf, pkbuf, 0, PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_WOTS_W - 1, pub_seed, addrx8, state_seeded); - for (j = 0; j < 8; j++) { - if (i + j < PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_WOTS_LEN) { - memcpy(pk + (i + j)*PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N, pkbuf + j * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N, PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N); - } - } - } -} - -/** - * Takes a n-byte message and the 32-byte sk_see to compute a signature 'sig'. - */ -void PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_wots_sign(unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_WOTS_LEN; i++) { - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_set_chain_addr(addr, i); - wots_gen_sk(sig + i * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N, sk_seed, addr, state_seeded); - gen_chain(sig + i * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N, sig + i * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N, 0, lengths[i], pub_seed, addr, state_seeded); - } -} - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_WOTS_LEN; i++) { - PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_set_chain_addr(addr, i); - gen_chain(pk + i * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N, sig + i * PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_N, - lengths[i], PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_WOTS_W - 1 - lengths[i], pub_seed, addr, state_seeded); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_avx2/wots.h b/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_avx2/wots.h deleted file mode 100644 index dd8c2c5c3c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_avx2/wots.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_WOTS_H -#define PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_WOTS_H - -#include "hash_state.h" -#include "params.h" -#include - -/** - * WOTS key generation. Takes a 32 byte seed for the private key, expands it to - * a full WOTS private key and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_wots_gen_pk( - unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -/** - * Takes a n-byte message and the 32-byte seed for the private key to compute a - * signature that is placed at 'sig'. - */ -void PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_wots_sign( - unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *hash_state_seeded); - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHA256128FSIMPLE_AVX2_wots_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_clean/LICENSE b/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_clean/LICENSE deleted file mode 100644 index 670154e353..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_clean/LICENSE +++ /dev/null @@ -1,116 +0,0 @@ -CC0 1.0 Universal - -Statement of Purpose - -The laws of most jurisdictions throughout the world automatically confer -exclusive Copyright and Related Rights (defined below) upon the creator and -subsequent owner(s) (each and all, an "owner") of an original work of -authorship and/or a database (each, a "Work"). - -Certain owners wish to permanently relinquish those rights to a Work for the -purpose of contributing to a commons of creative, cultural and scientific -works ("Commons") that the public can reliably and without fear of later -claims of infringement build upon, modify, incorporate in other works, reuse -and redistribute as freely as possible in any form whatsoever and for any -purposes, including without limitation commercial purposes. These owners may -contribute to the Commons to promote the ideal of a free culture and the -further production of creative, cultural and scientific works, or to gain -reputation or greater distribution for their Work in part through the use and -efforts of others. - -For these and/or other purposes and motivations, and without any expectation -of additional consideration or compensation, the person associating CC0 with a -Work (the "Affirmer"), to the extent that he or she is an owner of Copyright -and Related Rights in the Work, voluntarily elects to apply CC0 to the Work -and publicly distribute the Work under its terms, with knowledge of his or her -Copyright and Related Rights in the Work and the meaning and intended legal -effect of CC0 on those rights. - -1. Copyright and Related Rights. A Work made available under CC0 may be -protected by copyright and related or neighboring rights ("Copyright and -Related Rights"). Copyright and Related Rights include, but are not limited -to, the following: - - i. the right to reproduce, adapt, distribute, perform, display, communicate, - and translate a Work; - - ii. moral rights retained by the original author(s) and/or performer(s); - - iii. publicity and privacy rights pertaining to a person's image or likeness - depicted in a Work; - - iv. rights protecting against unfair competition in regards to a Work, - subject to the limitations in paragraph 4(a), below; - - v. rights protecting the extraction, dissemination, use and reuse of data in - a Work; - - vi. database rights (such as those arising under Directive 96/9/EC of the - European Parliament and of the Council of 11 March 1996 on the legal - protection of databases, and under any national implementation thereof, - including any amended or successor version of such directive); and - - vii. other similar, equivalent or corresponding rights throughout the world - based on applicable law or treaty, and any national implementations thereof. - -2. Waiver. To the greatest extent permitted by, but not in contravention of, -applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and -unconditionally waives, abandons, and surrenders all of Affirmer's Copyright -and Related Rights and associated claims and causes of action, whether now -known or unknown (including existing as well as future claims and causes of -action), in the Work (i) in all territories worldwide, (ii) for the maximum -duration provided by applicable law or treaty (including future time -extensions), (iii) in any current or future medium and for any number of -copies, and (iv) for any purpose whatsoever, including without limitation -commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes -the Waiver for the benefit of each member of the public at large and to the -detriment of Affirmer's heirs and successors, fully intending that such Waiver -shall not be subject to revocation, rescission, cancellation, termination, or -any other legal or equitable action to disrupt the quiet enjoyment of the Work -by the public as contemplated by Affirmer's express Statement of Purpose. - -3. Public License Fallback. Should any part of the Waiver for any reason be -judged legally invalid or ineffective under applicable law, then the Waiver -shall be preserved to the maximum extent permitted taking into account -Affirmer's express Statement of Purpose. In addition, to the extent the Waiver -is so judged Affirmer hereby grants to each affected person a royalty-free, -non transferable, non sublicensable, non exclusive, irrevocable and -unconditional license to exercise Affirmer's Copyright and Related Rights in -the Work (i) in all territories worldwide, (ii) for the maximum duration -provided by applicable law or treaty (including future time extensions), (iii) -in any current or future medium and for any number of copies, and (iv) for any -purpose whatsoever, including without limitation commercial, advertising or -promotional purposes (the "License"). The License shall be deemed effective as -of the date CC0 was applied by Affirmer to the Work. Should any part of the -License for any reason be judged legally invalid or ineffective under -applicable law, such partial invalidity or ineffectiveness shall not -invalidate the remainder of the License, and in such case Affirmer hereby -affirms that he or she will not (i) exercise any of his or her remaining -Copyright and Related Rights in the Work or (ii) assert any associated claims -and causes of action with respect to the Work, in either case contrary to -Affirmer's express Statement of Purpose. - -4. Limitations and Disclaimers. - - a. No trademark or patent rights held by Affirmer are waived, abandoned, - surrendered, licensed or otherwise affected by this document. - - b. Affirmer offers the Work as-is and makes no representations or warranties - of any kind concerning the Work, express, implied, statutory or otherwise, - including without limitation warranties of title, merchantability, fitness - for a particular purpose, non infringement, or the absence of latent or - other defects, accuracy, or the present or absence of errors, whether or not - discoverable, all to the greatest extent permissible under applicable law. - - c. Affirmer disclaims responsibility for clearing rights of other persons - that may apply to the Work or any use thereof, including without limitation - any person's Copyright and Related Rights in the Work. Further, Affirmer - disclaims responsibility for obtaining any necessary consents, permissions - or other rights required for any use of the Work. - - d. Affirmer understands and acknowledges that Creative Commons is not a - party to this document and has no duty or obligation with respect to this - CC0 or use of the Work. - -For more information, please see - diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_clean/address.c b/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_clean/address.c deleted file mode 100644 index 6e5311ff8d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_clean/address.c +++ /dev/null @@ -1,78 +0,0 @@ -#include - -#include "address.h" -#include "params.h" -#include "utils.h" - -void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]) { - int i; - - for (i = 0; i < 8; i++) { - PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_ull_to_bytes( - bytes + i * 4, 4, addr[i]); - } -} - -void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_set_layer_addr( - uint32_t addr[8], uint32_t layer) { - addr[0] = layer; -} - -void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_set_tree_addr( - uint32_t addr[8], uint64_t tree) { - addr[1] = 0; - addr[2] = (uint32_t) (tree >> 32); - addr[3] = (uint32_t) tree; -} - -void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_set_type( - uint32_t addr[8], uint32_t type) { - addr[4] = type; -} - -void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; -} - -/* These functions are used for OTS addresses. */ - -void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_set_keypair_addr( - uint32_t addr[8], uint32_t keypair) { - addr[5] = keypair; -} - -void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; - out[5] = in[5]; -} - -void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_set_chain_addr( - uint32_t addr[8], uint32_t chain) { - addr[6] = chain; -} - -void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_set_hash_addr( - uint32_t addr[8], uint32_t hash) { - addr[7] = hash; -} - -/* These functions are used for all hash tree addresses (including FORS). */ - -void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_set_tree_height( - uint32_t addr[8], uint32_t tree_height) { - addr[6] = tree_height; -} - -void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_set_tree_index( - uint32_t addr[8], uint32_t tree_index) { - addr[7] = tree_index; -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_clean/address.h b/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_clean/address.h deleted file mode 100644 index 79a572be85..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_clean/address.h +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_ADDRESS_H -#define PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_ADDRESS_H - -#include - -#define PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_ADDR_TYPE_WOTS 0 -#define PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_ADDR_TYPE_WOTSPK 1 -#define PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_ADDR_TYPE_HASHTREE 2 -#define PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_ADDR_TYPE_FORSTREE 3 -#define PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_ADDR_TYPE_FORSPK 4 - -void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]); - -void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_set_layer_addr( - uint32_t addr[8], uint32_t layer); - -void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_set_tree_addr( - uint32_t addr[8], uint64_t tree); - -void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_set_type( - uint32_t addr[8], uint32_t type); - -/* Copies the layer and tree part of one address into the other */ -void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for WOTS and FORS addresses. */ - -void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_set_keypair_addr( - uint32_t addr[8], uint32_t keypair); - -void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_set_chain_addr( - uint32_t addr[8], uint32_t chain); - -void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_set_hash_addr( - uint32_t addr[8], uint32_t hash); - -void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for all hash tree addresses (including FORS). */ - -void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_set_tree_height( - uint32_t addr[8], uint32_t tree_height); - -void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_set_tree_index( - uint32_t addr[8], uint32_t tree_index); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_clean/api.h b/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_clean/api.h deleted file mode 100644 index c586aa23ef..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_clean/api.h +++ /dev/null @@ -1,81 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_API_H -#define PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_API_H - -#include -#include - - - -#define PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_CRYPTO_ALGNAME "SPHINCS+" - -#define PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_CRYPTO_SECRETKEYBYTES 64 -#define PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_CRYPTO_PUBLICKEYBYTES 32 -#define PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_CRYPTO_BYTES 17088 -#define PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_CRYPTO_SEEDBYTES 48 - - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_clean/fors.c b/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_clean/fors.c deleted file mode 100644 index 22c50b0c3b..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_clean/fors.c +++ /dev/null @@ -1,161 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "fors.h" -#include "hash.h" -#include "hash_state.h" -#include "thash.h" -#include "utils.h" - -static void fors_gen_sk(unsigned char *sk, const unsigned char *sk_seed, - uint32_t fors_leaf_addr[8], const hash_state *hash_state_seeded) { - PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_prf_addr( - sk, sk_seed, fors_leaf_addr, hash_state_seeded); -} - -static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, - const unsigned char *pub_seed, - uint32_t fors_leaf_addr[8], - const hash_state *hash_state_seeded) { - PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_thash_1( - leaf, sk, pub_seed, fors_leaf_addr, hash_state_seeded); -} - -static void fors_gen_leaf(unsigned char *leaf, const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx, const uint32_t fors_tree_addr[8], - const hash_state *hash_state_seeded) { - uint32_t fors_leaf_addr[8] = {0}; - - /* Only copy the parts that must be kept in fors_leaf_addr. */ - PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_copy_keypair_addr( - fors_leaf_addr, fors_tree_addr); - PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_set_type( - fors_leaf_addr, PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_set_tree_index( - fors_leaf_addr, addr_idx); - - fors_gen_sk(leaf, sk_seed, fors_leaf_addr, hash_state_seeded); - fors_sk_to_leaf(leaf, leaf, pub_seed, fors_leaf_addr, hash_state_seeded); -} - -/** - * Interprets m as PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_FORS_HEIGHT-bit unsigned integers. - * Assumes m contains at least PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_FORS_TREES bits. - * Assumes indices has space for PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_FORS_TREES integers. - */ -static void message_to_indices(uint32_t *indices, const unsigned char *m) { - unsigned int i, j; - unsigned int offset = 0; - - for (i = 0; i < PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_FORS_TREES; i++) { - indices[i] = 0; - for (j = 0; j < PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_FORS_HEIGHT; j++) { - indices[i] ^= (((uint32_t)m[offset >> 3] >> (offset & 0x7)) & 0x1) << j; - offset++; - } - } -} - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_fors_sign( - unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *hash_state_seeded) { - uint32_t indices[PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_FORS_TREES]; - unsigned char roots[PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_FORS_TREES * PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_N]; - uint32_t fors_tree_addr[8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_copy_keypair_addr( - fors_tree_addr, fors_addr); - PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_copy_keypair_addr( - fors_pk_addr, fors_addr); - - PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_set_type( - fors_tree_addr, PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_set_type( - fors_pk_addr, PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_FORS_TREES; i++) { - idx_offset = i * (1 << PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_FORS_HEIGHT); - - PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_set_tree_height( - fors_tree_addr, 0); - PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_set_tree_index( - fors_tree_addr, indices[i] + idx_offset); - - /* Include the secret key part that produces the selected leaf node. */ - fors_gen_sk(sig, sk_seed, fors_tree_addr, hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_N; - - /* Compute the authentication path for this leaf node. */ - PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_treehash_FORS_HEIGHT( - roots + i * PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_N, sig, sk_seed, pub_seed, - indices[i], idx_offset, fors_gen_leaf, fors_tree_addr, - hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_N * PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_thash_FORS_TREES( - pk, roots, pub_seed, fors_pk_addr, hash_state_seeded); -} - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_fors_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, const uint32_t fors_addr[8], - const hash_state *hash_state_seeded) { - uint32_t indices[PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_FORS_TREES]; - unsigned char roots[PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_FORS_TREES * PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_N]; - unsigned char leaf[PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_N]; - uint32_t fors_tree_addr[8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_copy_keypair_addr(fors_tree_addr, fors_addr); - PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_copy_keypair_addr(fors_pk_addr, fors_addr); - - PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_set_type(fors_tree_addr, PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_set_type(fors_pk_addr, PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_FORS_TREES; i++) { - idx_offset = i * (1 << PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_FORS_HEIGHT); - - PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_set_tree_height(fors_tree_addr, 0); - PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Derive the leaf from the included secret key part. */ - fors_sk_to_leaf(leaf, sig, pub_seed, fors_tree_addr, hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_N; - - /* Derive the corresponding root node of this tree. */ - PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_compute_root(roots + i * PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_N, leaf, indices[i], idx_offset, sig, - PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_FORS_HEIGHT, pub_seed, fors_tree_addr, hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_N * PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_thash_FORS_TREES(pk, roots, pub_seed, fors_pk_addr, hash_state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_clean/fors.h b/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_clean/fors.h deleted file mode 100644 index 4e2aba0158..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_clean/fors.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_FORS_H -#define PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_FORS_H - -#include - -#include "hash_state.h" -#include "params.h" - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_fors_sign( - unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *hash_state_seeded); - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_fors_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, const uint32_t fors_addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_clean/hash.h b/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_clean/hash.h deleted file mode 100644 index 1e6eef650e..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_clean/hash.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_HASH_H -#define PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_HASH_H - -#include "hash_state.h" - -#include -#include - -void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_initialize_hash_function( - hash_state *hash_state_seeded, - const unsigned char *pub_seed, const unsigned char *sk_seed); - -void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_destroy_hash_function(hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_clean/hash_sha256.c b/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_clean/hash_sha256.c deleted file mode 100644 index 0420a41cbe..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_clean/hash_sha256.c +++ /dev/null @@ -1,162 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "utils.h" - -#include "sha2.h" -#include "sha256.h" - -/* For SHA256, there is no immediate reason to initialize at the start, - so this function is an empty operation. */ -void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_initialize_hash_function( - hash_state *hash_state_seeded, - const unsigned char *pub_seed, const unsigned char *sk_seed) { - PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_seed_state(hash_state_seeded, pub_seed); - (void)sk_seed; /* Suppress an 'unused parameter' warning. */ -} - -/* Clean up hash state */ -void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_destroy_hash_function(hash_state *hash_state_seeded) { - sha256_inc_ctx_release(hash_state_seeded); -} - -/* - * Computes PRF(key, addr), given a secret key of PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_N bytes and an address - */ -void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded) { - unsigned char buf[PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_N + PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_SHA256_ADDR_BYTES]; - unsigned char outbuf[PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_SHA256_OUTPUT_BYTES]; - - memcpy(buf, key, PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_N); - PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_compress_address(buf + PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_N, addr); - - sha256(outbuf, buf, PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_N + PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_SHA256_ADDR_BYTES); - memcpy(out, outbuf, PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_N); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} - -/** - * Computes the message-dependent randomness R, using a secret seed as a key - * for HMAC, and an optional randomization value prefixed to the message. - * This requires m to have at least PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_SHA256_BLOCK_BYTES + PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_N space - * available in front of the pointer, i.e. before the message to use for the - * prefix. This is necessary to prevent having to move the message around (and - * allocate memory for it). - */ -void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, const hash_state *hash_state_seeded) { - unsigned char buf[PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_SHA256_BLOCK_BYTES + PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_SHA256_OUTPUT_BYTES]; - sha256ctx state; - int i; - - /* This implements HMAC-SHA256 */ - for (i = 0; i < PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_N; i++) { - buf[i] = 0x36 ^ sk_prf[i]; - } - memset(buf + PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_N, 0x36, PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_N); - - sha256_inc_init(&state); - sha256_inc_blocks(&state, buf, 1); - - memcpy(buf, optrand, PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_N); - - /* If optrand + message cannot fill up an entire block */ - if (PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_N + mlen < PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_SHA256_BLOCK_BYTES) { - memcpy(buf + PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_N, m, mlen); - sha256_inc_finalize(buf + PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_SHA256_BLOCK_BYTES, &state, - buf, mlen + PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_N); - } - /* Otherwise first fill a block, so that finalize only uses the message */ - else { - memcpy(buf + PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_N, m, PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_N); - sha256_inc_blocks(&state, buf, 1); - - m += PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_N; - mlen -= PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_N; - sha256_inc_finalize(buf + PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_SHA256_BLOCK_BYTES, &state, m, mlen); - } - - for (i = 0; i < PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_N; i++) { - buf[i] = 0x5c ^ sk_prf[i]; - } - memset(buf + PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_N, 0x5c, PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_N); - - sha256(buf, buf, PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_SHA256_BLOCK_BYTES + PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_SHA256_OUTPUT_BYTES); - memcpy(R, buf, PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_N); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} - -/** - * Computes the message hash using R, the public key, and the message. - * Outputs the message digest and the index of the leaf. The index is split in - * the tree index and the leaf index, for convenient copying to an address. - */ -void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded) { -#define PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_TREE_BITS (PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_TREE_HEIGHT * (PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_D - 1)) -#define PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_TREE_BYTES ((PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_TREE_BITS + 7) / 8) -#define PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_LEAF_BITS PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_TREE_HEIGHT -#define PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_LEAF_BYTES ((PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_LEAF_BITS + 7) / 8) -#define PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_DGST_BYTES (PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_FORS_MSG_BYTES + PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_TREE_BYTES + PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_LEAF_BYTES) - - unsigned char seed[PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_SHA256_OUTPUT_BYTES + 4]; - - /* Round to nearest multiple of PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_SHA256_BLOCK_BYTES */ -#define PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_INBLOCKS (((PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_N + PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_PK_BYTES + PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_SHA256_BLOCK_BYTES - 1) & \ - -PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_SHA256_BLOCK_BYTES) / PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_SHA256_BLOCK_BYTES) - unsigned char inbuf[PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_INBLOCKS * PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_SHA256_BLOCK_BYTES]; - - unsigned char buf[PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_DGST_BYTES]; - unsigned char *bufp = buf; - sha256ctx state; - - sha256_inc_init(&state); - - memcpy(inbuf, R, PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_N); - memcpy(inbuf + PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_N, pk, PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_PK_BYTES); - - /* If R + pk + message cannot fill up an entire block */ - if (PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_N + PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_PK_BYTES + mlen < PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_INBLOCKS * PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_SHA256_BLOCK_BYTES) { - memcpy(inbuf + PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_N + PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_PK_BYTES, m, mlen); - sha256_inc_finalize(seed, &state, inbuf, PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_N + PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_PK_BYTES + mlen); - } - /* Otherwise first fill a block, so that finalize only uses the message */ - else { - memcpy(inbuf + PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_N + PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_PK_BYTES, m, - PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_INBLOCKS * PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_N - PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_PK_BYTES); - sha256_inc_blocks(&state, inbuf, PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_INBLOCKS); - - m += PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_INBLOCKS * PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_N - PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_PK_BYTES; - mlen -= PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_INBLOCKS * PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_N - PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_PK_BYTES; - sha256_inc_finalize(seed, &state, m, mlen); - } - - /* By doing this in two steps, we prevent hashing the message twice; - otherwise each iteration in MGF1 would hash the message again. */ - PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_mgf1(bufp, PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_DGST_BYTES, seed, PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_SHA256_OUTPUT_BYTES); - - memcpy(digest, bufp, PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_FORS_MSG_BYTES); - bufp += PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_FORS_MSG_BYTES; - - *tree = PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_bytes_to_ull(bufp, PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_TREE_BYTES); - *tree &= (~(uint64_t)0) >> (64 - PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_TREE_BITS); - bufp += PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_TREE_BYTES; - - *leaf_idx = (uint32_t)PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_bytes_to_ull( - bufp, PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_LEAF_BYTES); - *leaf_idx &= (~(uint32_t)0) >> (32 - PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_LEAF_BITS); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_clean/hash_state.h b/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_clean/hash_state.h deleted file mode 100644 index 19fc335e27..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_clean/hash_state.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef SPX_HASH_STATE_H -#define SPX_HASH_STATE_H - -/** - * Defines the type of the hash function state. - * - * Don't be fooled into thinking this instance of SPHINCS+ isn't stateless! - * - * From Section 7.2.2 from the SPHINCS+ round-2 specification: - * - * Each of the instances of the tweakable hash function take PK.seed as its - * first input, which is constant for a given key pair – and, thus, across - * a single signature. This leads to a lot of redundant computation. To remedy - * this, we pad PK.seed to the length of a full 64-byte SHA-256 input block. - * Because of the Merkle-DamgÃ¥rd construction that underlies SHA-256, this - * allows for reuse of the intermediate SHA-256 state after the initial call to - * the compression function which improves performance. - * - * We pass this hash state around in functions, because otherwise we need to - * have a global variable. - */ - -#include "sha2.h" -#define hash_state sha256ctx - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_clean/params.h b/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_clean/params.h deleted file mode 100644 index 6e61d95214..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_clean/params.h +++ /dev/null @@ -1,53 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_PARAMS_H -#define PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_PARAMS_H - -/* Hash output length in bytes. */ -#define PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_N 16 -/* Height of the hypertree. */ -#define PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_FULL_HEIGHT 66 -/* Number of subtree layer. */ -#define PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_D 22 -/* FORS tree dimensions. */ -#define PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_FORS_HEIGHT 6 -#define PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_FORS_TREES 33 -/* Winternitz parameter, */ -#define PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_WOTS_W 16 - -/* The hash function is defined by linking a different hash.c file, as opposed - to setting a #define constant. */ - -/* For clarity */ -#define PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_ADDR_BYTES 32 - -/* WOTS parameters. */ -#define PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_WOTS_LOGW 4 - -#define PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_WOTS_LEN1 (8 * PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_N / PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_WOTS_LOGW) - -/* PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#define PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_WOTS_LEN2 3 - -#define PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_WOTS_LEN (PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_WOTS_LEN1 + PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_WOTS_LEN2) -#define PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_WOTS_BYTES (PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_WOTS_LEN * PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_N) -#define PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_WOTS_PK_BYTES PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_WOTS_BYTES - -/* Subtree size. */ -#define PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_TREE_HEIGHT (PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_FULL_HEIGHT / PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_D) - -/* FORS parameters. */ -#define PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_FORS_MSG_BYTES ((PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_FORS_TREES + 7) / 8) -#define PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_FORS_BYTES ((PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_FORS_HEIGHT + 1) * PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_FORS_TREES * PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_N) -#define PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_FORS_PK_BYTES PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_N - -/* Resulting SPX sizes. */ -#define PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_BYTES (PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_N + PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_FORS_BYTES + PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_D * PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_WOTS_BYTES +\ - PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_FULL_HEIGHT * PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_N) -#define PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_PK_BYTES (2 * PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_N) -#define PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_SK_BYTES (2 * PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_N + PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_PK_BYTES) - -/* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ -#define PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_OPTRAND_BYTES 32 - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_clean/sha256.c b/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_clean/sha256.c deleted file mode 100644 index 03d0eb990e..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_clean/sha256.c +++ /dev/null @@ -1,71 +0,0 @@ -/* Based on the public domain implementation in - * crypto_hash/sha512/ref/ from http://bench.cr.yp.to/supercop.html - * by D. J. Bernstein */ - -#include -#include -#include - -#include "sha2.h" -#include "sha256.h" -#include "utils.h" - -/* - * Compresses an address to a 22-byte sequence. - * This reduces the number of required SHA256 compression calls, as the last - * block of input is padded with at least 65 bits. - */ -void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_compress_address(unsigned char *out, const uint32_t addr[8]) { - PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_ull_to_bytes(out, 1, addr[0]); /* drop 3 bytes of the layer field */ - PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_ull_to_bytes(out + 1, 4, addr[2]); /* drop the highest tree address word */ - PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_ull_to_bytes(out + 5, 4, addr[3]); - PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_ull_to_bytes(out + 9, 1, addr[4]); /* drop 3 bytes of the type field */ - PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_ull_to_bytes(out + 10, 4, addr[5]); - PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_ull_to_bytes(out + 14, 4, addr[6]); - PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_ull_to_bytes(out + 18, 4, addr[7]); -} - -/** - * Requires 'input_plus_four_bytes' to have 'inlen' + 4 bytes, so that the last - * four bytes can be used for the counter. Typically 'input' is merely a seed. - * Outputs outlen number of bytes - */ -void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_mgf1( - unsigned char *out, unsigned long outlen, - unsigned char *input_plus_four_bytes, unsigned long inlen) { - unsigned char outbuf[PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_SHA256_OUTPUT_BYTES]; - unsigned long i; - - /* While we can fit in at least another full block of SHA256 output.. */ - for (i = 0; (i + 1)*PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_SHA256_OUTPUT_BYTES <= outlen; i++) { - PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_ull_to_bytes(input_plus_four_bytes + inlen, 4, i); - sha256(out, input_plus_four_bytes, inlen + 4); - out += PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_SHA256_OUTPUT_BYTES; - } - /* Until we cannot anymore, and we fill the remainder. */ - if (outlen > i * PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_SHA256_OUTPUT_BYTES) { - PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_ull_to_bytes(input_plus_four_bytes + inlen, 4, i); - sha256(outbuf, input_plus_four_bytes, inlen + 4); - memcpy(out, outbuf, outlen - i * PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_SHA256_OUTPUT_BYTES); - } -} - - -/** - * Absorb the constant pub_seed using one round of the compression function - * This initializes hash_state_seeded, which can then be reused in thash - **/ -void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_seed_state(sha256ctx *hash_state_seeded, const unsigned char *pub_seed) { - uint8_t block[PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_SHA256_BLOCK_BYTES]; - size_t i; - - for (i = 0; i < PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_N; ++i) { - block[i] = pub_seed[i]; - } - for (i = PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_N; i < PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_SHA256_BLOCK_BYTES; ++i) { - block[i] = 0; - } - - sha256_inc_init(hash_state_seeded); - sha256_inc_blocks(hash_state_seeded, block, 1); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_clean/sha256.h b/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_clean/sha256.h deleted file mode 100644 index 9536d88b8f..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_clean/sha256.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_SHA256_H -#define PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_SHA256_H - -#define PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_SHA256_BLOCK_BYTES 64 -#define PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_SHA256_OUTPUT_BYTES 32 /* This does not necessarily equal PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_N */ -#define PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_SHA256_ADDR_BYTES 22 - -#include -#include - -#include "sha2.h" - -void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_compress_address(unsigned char *out, const uint32_t addr[8]); - -void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_mgf1( - unsigned char *out, unsigned long outlen, - unsigned char *input_plus_four_bytes, unsigned long inlen); - -void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_seed_state(sha256ctx *hash_state_seeded, const unsigned char *pub_seed); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_clean/sign.c b/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_clean/sign.c deleted file mode 100644 index 49320f5071..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_clean/sign.c +++ /dev/null @@ -1,356 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "api.h" -#include "fors.h" -#include "hash.h" -#include "hash_state.h" -#include "params.h" -#include "randombytes.h" -#include "thash.h" -#include "utils.h" -#include "wots.h" - -/** - * Computes the leaf at a given address. First generates the WOTS key pair, - * then computes leaf by hashing horizontally. - */ -static void wots_gen_leaf(unsigned char *leaf, const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx, const uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - unsigned char pk[PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_WOTS_BYTES]; - uint32_t wots_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_set_type( - wots_addr, PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_set_type( - wots_pk_addr, PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_ADDR_TYPE_WOTSPK); - - PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_set_keypair_addr( - wots_addr, addr_idx); - PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_wots_gen_pk( - pk, sk_seed, pub_seed, wots_addr, hash_state_seeded); - - PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_copy_keypair_addr( - wots_pk_addr, wots_addr); - PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_thash_WOTS_LEN( - leaf, pk, pub_seed, wots_pk_addr, hash_state_seeded); -} - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_crypto_sign_secretkeybytes(void) { - return PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_CRYPTO_SECRETKEYBYTES; -} - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_crypto_sign_publickeybytes(void) { - return PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_CRYPTO_PUBLICKEYBYTES; -} - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_crypto_sign_bytes(void) { - return PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_CRYPTO_BYTES; -} - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_crypto_sign_seedbytes(void) { - return PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_CRYPTO_SEEDBYTES; -} - -/* - * Generates an SPX key pair given a seed of length - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed) { - /* We do not need the auth path in key generation, but it simplifies the - code to have just one treehash routine that computes both root and path - in one function. */ - unsigned char auth_path[PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_TREE_HEIGHT * PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_N]; - uint32_t top_tree_addr[8] = {0}; - hash_state hash_state_seeded; - - PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_set_layer_addr( - top_tree_addr, PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_D - 1); - PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_set_type( - top_tree_addr, PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_ADDR_TYPE_HASHTREE); - - /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ - memcpy(sk, seed, PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_CRYPTO_SEEDBYTES); - - memcpy(pk, sk + 2 * PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_N, PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_initialize_hash_function(&hash_state_seeded, pk, sk); - - /* Compute root node of the top-most subtree. */ - PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_treehash_TREE_HEIGHT( - sk + 3 * PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_N, auth_path, sk, sk + 2 * PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_N, 0, 0, - wots_gen_leaf, top_tree_addr, &hash_state_seeded); - - memcpy(pk + PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_N, sk + 3 * PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_N, PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_N); - - PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_destroy_hash_function(&hash_state_seeded); - return 0; -} - -/* - * Generates an SPX key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk) { - unsigned char seed[PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_CRYPTO_SEEDBYTES]; - randombytes(seed, PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_CRYPTO_SEEDBYTES); - PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_crypto_sign_seed_keypair( - pk, sk, seed); - - return 0; -} - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - const unsigned char *sk_seed = sk; - const unsigned char *sk_prf = sk + PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_N; - const unsigned char *pk = sk + 2 * PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_N; - const unsigned char *pub_seed = pk; - - unsigned char optrand[PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_N]; - unsigned char mhash[PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_FORS_MSG_BYTES]; - unsigned char root[PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_N]; - uint32_t i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - - hash_state hash_state_seeded; - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_initialize_hash_function( - &hash_state_seeded, - pub_seed, sk_seed); - - PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_set_type( - wots_addr, PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_set_type( - tree_addr, PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_ADDR_TYPE_HASHTREE); - - /* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ - randombytes(optrand, PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_N); - /* Compute the digest randomization value. */ - PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_gen_message_random( - sig, sk_prf, optrand, m, mlen, &hash_state_seeded); - - /* Derive the message digest and leaf index from R, PK and M. */ - PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_N; - - PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); - - /* Sign the message hash using FORS. */ - PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_fors_sign( - sig, root, mhash, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_FORS_BYTES; - - for (i = 0; i < PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_D; i++) { - PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_set_tree_addr(tree_addr, tree); - - PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); - - /* Compute a WOTS signature. */ - PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_wots_sign( - sig, root, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_WOTS_BYTES; - - /* Compute the authentication path for the used WOTS leaf. */ - PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_treehash_TREE_HEIGHT( - root, sig, sk_seed, pub_seed, idx_leaf, 0, - wots_gen_leaf, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_TREE_HEIGHT * PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_TREE_HEIGHT; - } - - *siglen = PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_BYTES; - - PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_destroy_hash_function(&hash_state_seeded); - return 0; -} - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk) { - const unsigned char *pub_seed = pk; - const unsigned char *pub_root = pk + PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_N; - unsigned char mhash[PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_FORS_MSG_BYTES]; - unsigned char wots_pk[PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_WOTS_BYTES]; - unsigned char root[PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_N]; - unsigned char leaf[PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_N]; - unsigned int i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - hash_state hash_state_seeded; - - if (siglen != PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_BYTES) { - return -1; - } - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_initialize_hash_function( - &hash_state_seeded, - pub_seed, NULL); - - PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_set_type( - wots_addr, PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_set_type( - tree_addr, PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_ADDR_TYPE_HASHTREE); - PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_set_type( - wots_pk_addr, PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_ADDR_TYPE_WOTSPK); - - /* Derive the message digest and leaf index from R || PK || M. */ - /* The additional PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_N is a result of the hash domain separator. */ - PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_N; - - /* Layer correctly defaults to 0, so no need to set_layer_addr */ - PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); - - PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_fors_pk_from_sig( - root, sig, mhash, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_FORS_BYTES; - - /* For each subtree.. */ - for (i = 0; i < PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_D; i++) { - PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_set_tree_addr(tree_addr, tree); - - PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); - - PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_copy_keypair_addr( - wots_pk_addr, wots_addr); - - /* The WOTS public key is only correct if the signature was correct. */ - /* Initially, root is the FORS pk, but on subsequent iterations it is - the root of the subtree below the currently processed subtree. */ - PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_wots_pk_from_sig( - wots_pk, sig, root, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_WOTS_BYTES; - - /* Compute the leaf node using the WOTS public key. */ - PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_thash_WOTS_LEN( - leaf, wots_pk, pub_seed, wots_pk_addr, &hash_state_seeded); - - /* Compute the root node of this subtree. */ - PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_compute_root( - root, leaf, idx_leaf, 0, sig, PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_TREE_HEIGHT, - pub_seed, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_TREE_HEIGHT * PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_TREE_HEIGHT; - } - - PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_destroy_hash_function(&hash_state_seeded); - /* Check if the root node equals the root node in the public key. */ - if (memcmp(root, pub_root, PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_N) != 0) { - return -1; - } - - return 0; -} - - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - size_t siglen; - - PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_crypto_sign_signature( - sm, &siglen, m, mlen, sk); - - memmove(sm + PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_BYTES, m, mlen); - *smlen = siglen + mlen; - - return 0; -} - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk) { - /* The API caller does not necessarily know what size a signature should be - but SPHINCS+ signatures are always exactly PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_BYTES. */ - if (smlen < PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_BYTES) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - *mlen = smlen - PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_BYTES; - - if (PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_crypto_sign_verify( - sm, PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_BYTES, sm + PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_BYTES, *mlen, pk)) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - /* If verification was successful, move the message to the right place. */ - memmove(m, sm + PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_BYTES, *mlen); - - return 0; -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_clean/thash.h b/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_clean/thash.h deleted file mode 100644 index 353f27d01a..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_clean/thash.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_THASH_H -#define PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_THASH_H - -#include "hash_state.h" - -#include - -void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_clean/thash_sha256_simple.c b/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_clean/thash_sha256_simple.c deleted file mode 100644 index ef0d3a93a8..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_clean/thash_sha256_simple.c +++ /dev/null @@ -1,75 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "thash.h" - -#include "sha2.h" -#include "sha256.h" - -/** - * Takes an array of inblocks concatenated arrays of PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_N bytes. - */ -static void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_thash( - unsigned char *out, unsigned char *buf, - const unsigned char *in, unsigned int inblocks, - const unsigned char *pub_seed, uint32_t addr[8], - const sha256ctx *hash_state_seeded) { - - unsigned char outbuf[PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_SHA256_OUTPUT_BYTES]; - sha256ctx sha2_state; - - (void)pub_seed; /* Suppress an 'unused parameter' warning. */ - - /* Retrieve precomputed state containing pub_seed */ - sha256_inc_ctx_clone(&sha2_state, hash_state_seeded); - - PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_compress_address(buf, addr); - memcpy(buf + PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_SHA256_ADDR_BYTES, in, inblocks * PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_N); - - sha256_inc_finalize(outbuf, &sha2_state, buf, PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_N); - memcpy(out, outbuf, PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_N); -} - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const sha256ctx *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_SHA256_ADDR_BYTES + 1 * PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_N]; - PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_thash( - out, buf, in, 1, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const sha256ctx *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_SHA256_ADDR_BYTES + 2 * PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_N]; - PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_thash( - out, buf, in, 2, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const sha256ctx *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_SHA256_ADDR_BYTES + PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_WOTS_LEN * PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_N]; - PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_thash( - out, buf, in, PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_WOTS_LEN, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const sha256ctx *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_SHA256_ADDR_BYTES + PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_FORS_TREES * PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_N]; - PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_thash( - out, buf, in, PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_FORS_TREES, pub_seed, addr, hash_state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_clean/utils.c b/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_clean/utils.c deleted file mode 100644 index e7e70b3513..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_clean/utils.c +++ /dev/null @@ -1,199 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "hash_state.h" -#include "params.h" -#include "thash.h" -#include "utils.h" - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in) { - - /* Iterate over out in decreasing order, for big-endianness. */ - for (size_t i = outlen; i > 0; i--) { - out[i - 1] = in & 0xff; - in = in >> 8; - } -} - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_bytes_to_ull( - const unsigned char *in, size_t inlen) { - unsigned long long retval = 0; - - for (size_t i = 0; i < inlen; i++) { - retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); - } - return retval; -} - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - uint32_t i; - unsigned char buffer[2 * PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_N]; - - /* If leaf_idx is odd (last bit = 1), current path element is a right child - and auth_path has to go left. Otherwise it is the other way around. */ - if (leaf_idx & 1) { - memcpy(buffer + PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_N, leaf, PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_N); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_N); - } else { - memcpy(buffer, leaf, PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_N); - memcpy(buffer + PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_N, auth_path, PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_N); - } - auth_path += PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_N; - - for (i = 0; i < tree_height - 1; i++) { - leaf_idx >>= 1; - idx_offset >>= 1; - /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_set_tree_height(addr, i + 1); - PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_set_tree_index( - addr, leaf_idx + idx_offset); - - /* Pick the right or left neighbor, depending on parity of the node. */ - if (leaf_idx & 1) { - PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_thash_2( - buffer + PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_N, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_N); - } else { - PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_thash_2( - buffer, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer + PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_N, auth_path, PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_N); - } - auth_path += PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_N; - } - - /* The last iteration is exceptional; we do not copy an auth_path node. */ - leaf_idx >>= 1; - idx_offset >>= 1; - PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_set_tree_height(addr, tree_height); - PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_set_tree_index( - addr, leaf_idx + idx_offset); - PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_thash_2( - root, buffer, pub_seed, addr, hash_state_seeded); -} - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -static void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_treehash( - unsigned char *root, unsigned char *auth_path, - unsigned char *stack, unsigned int *heights, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - - unsigned int offset = 0; - uint32_t idx; - uint32_t tree_idx; - - for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { - /* Add the next leaf node to the stack. */ - gen_leaf(stack + offset * PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_N, - sk_seed, pub_seed, idx + idx_offset, tree_addr, - hash_state_seeded); - offset++; - heights[offset - 1] = 0; - - /* If this is a node we need for the auth path.. */ - if ((leaf_idx ^ 0x1) == idx) { - memcpy(auth_path, stack + (offset - 1)*PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_N, PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_N); - } - - /* While the top-most nodes are of equal height.. */ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { - /* Compute index of the new node, in the next layer. */ - tree_idx = (idx >> (heights[offset - 1] + 1)); - - /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_set_tree_height( - tree_addr, heights[offset - 1] + 1); - PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_set_tree_index( - tree_addr, tree_idx + (idx_offset >> (heights[offset - 1] + 1))); - /* Hash the top-most nodes from the stack together. */ - PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_thash_2( - stack + (offset - 2)*PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_N, stack + (offset - 2)*PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_N, - pub_seed, tree_addr, hash_state_seeded); - offset--; - /* Note that the top-most node is now one layer higher. */ - heights[offset - 1]++; - - /* If this is a node we need for the auth path.. */ - if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_path + heights[offset - 1]*PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_N, - stack + (offset - 1)*PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_N, PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_N); - } - } - } - memcpy(root, stack, PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_N); -} - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_FORS_HEIGHT + 1)*PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_N]; - unsigned int heights[PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_FORS_HEIGHT + 1]; - - PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_FORS_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_TREE_HEIGHT + 1)*PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_N]; - unsigned int heights[PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_TREE_HEIGHT + 1]; - - PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_TREE_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_clean/utils.h b/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_clean/utils.h deleted file mode 100644 index 6d919a5f98..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_clean/utils.h +++ /dev/null @@ -1,64 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_UTILS_H -#define PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_UTILS_H - -#include "hash_state.h" -#include "params.h" -#include -#include - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in); - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_bytes_to_ull( - const unsigned char *in, size_t inlen); - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_clean/wots.c b/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_clean/wots.c deleted file mode 100644 index f67a4dbc90..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_clean/wots.c +++ /dev/null @@ -1,167 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "hash_state.h" -#include "params.h" -#include "thash.h" -#include "utils.h" -#include "wots.h" - -// TODO clarify address expectations, and make them more uniform. -// TODO i.e. do we expect types to be set already? -// TODO and do we expect modifications or copies? - -/** - * Computes the starting value for a chain, i.e. the secret key. - * Expects the address to be complete up to the chain address. - */ -static void wots_gen_sk(unsigned char *sk, const unsigned char *sk_seed, - uint32_t wots_addr[8], - const hash_state *hash_state_seeded) { - /* Make sure that the hash address is actually zeroed. */ - PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_set_hash_addr(wots_addr, 0); - - /* Generate sk element. */ - PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_prf_addr(sk, sk_seed, wots_addr, hash_state_seeded); -} - -/** - * Computes the chaining function. - * out and in have to be n-byte arrays. - * - * Interprets in as start-th value of the chain. - * addr has to contain the address of the chain. - */ -static void gen_chain(unsigned char *out, const unsigned char *in, - unsigned int start, unsigned int steps, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - uint32_t i; - - /* Initialize out with the value at position 'start'. */ - memcpy(out, in, PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_N); - - /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_WOTS_W; i++) { - PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_set_hash_addr(addr, i); - PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_thash_1( - out, out, pub_seed, addr, hash_state_seeded); - } -} - -/** - * base_w algorithm as described in draft. - * Interprets an array of bytes as integers in base w. - * This only works when log_w is a divisor of 8. - */ -static void base_w(unsigned int *output, const size_t out_len, - const unsigned char *input) { - size_t in = 0; - size_t out = 0; - unsigned char total = 0; - unsigned int bits = 0; - size_t consumed; - - for (consumed = 0; consumed < out_len; consumed++) { - if (bits == 0) { - total = input[in]; - in++; - bits += 8; - } - bits -= PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_WOTS_LOGW; - output[out] = (unsigned int)((total >> bits) & (PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_WOTS_W - 1)); - out++; - } -} - -/* Computes the WOTS+ checksum over a message (in base_w). */ -static void wots_checksum(unsigned int *csum_base_w, - const unsigned int *msg_base_w) { - unsigned int csum = 0; - unsigned char csum_bytes[(PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_WOTS_LEN2 * PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_WOTS_LOGW + 7) / 8]; - unsigned int i; - - /* Compute checksum. */ - for (i = 0; i < PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_WOTS_LEN1; i++) { - csum += PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_WOTS_W - 1 - msg_base_w[i]; - } - - /* Convert checksum to base_w. */ - /* Make sure expected empty zero bits are the least significant bits. */ - csum = csum << (8 - ((PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_WOTS_LEN2 * PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_WOTS_LOGW) % 8)); - PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_ull_to_bytes( - csum_bytes, sizeof(csum_bytes), csum); - base_w(csum_base_w, PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_WOTS_LEN2, csum_bytes); -} - -/* Takes a message and derives the matching chain lengths. */ -static void chain_lengths(unsigned int *lengths, const unsigned char *msg) { - base_w(lengths, PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_WOTS_LEN1, msg); - wots_checksum(lengths + PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_WOTS_LEN1, lengths); -} - -/** - * WOTS key generation. Takes a 32 byte sk_seed, expands it to WOTS private key - * elements and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_wots_gen_pk( - unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - uint32_t i; - - for (i = 0; i < PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_WOTS_LEN; i++) { - PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_set_chain_addr(addr, i); - wots_gen_sk(pk + i * PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_N, sk_seed, addr, hash_state_seeded); - gen_chain(pk + i * PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_N, pk + i * PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_N, - 0, PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_WOTS_W - 1, pub_seed, addr, hash_state_seeded); - } -} - -/** - * Takes a n-byte message and the 32-byte sk_see to compute a signature 'sig'. - */ -void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_wots_sign( - unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *hash_state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_WOTS_LEN; i++) { - PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_set_chain_addr(addr, i); - wots_gen_sk(sig + i * PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_N, sk_seed, addr, hash_state_seeded); - gen_chain(sig + i * PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_N, sig + i * PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_N, 0, lengths[i], pub_seed, addr, hash_state_seeded); - } -} - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_wots_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_WOTS_LEN; i++) { - PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_set_chain_addr(addr, i); - gen_chain(pk + i * PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_N, sig + i * PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_N, - lengths[i], PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_WOTS_W - 1 - lengths[i], pub_seed, addr, - hash_state_seeded); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_clean/wots.h b/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_clean/wots.h deleted file mode 100644 index e41546d568..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_clean/wots.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_WOTS_H -#define PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_WOTS_H - -#include "hash_state.h" -#include "params.h" -#include - -/** - * WOTS key generation. Takes a 32 byte seed for the private key, expands it to - * a full WOTS private key and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_wots_gen_pk( - unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -/** - * Takes a n-byte message and the 32-byte seed for the private key to compute a - * signature that is placed at 'sig'. - */ -void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_wots_sign( - unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *hash_state_seeded); - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_wots_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_avx2/LICENSE b/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_avx2/LICENSE deleted file mode 100644 index 670154e353..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_avx2/LICENSE +++ /dev/null @@ -1,116 +0,0 @@ -CC0 1.0 Universal - -Statement of Purpose - -The laws of most jurisdictions throughout the world automatically confer -exclusive Copyright and Related Rights (defined below) upon the creator and -subsequent owner(s) (each and all, an "owner") of an original work of -authorship and/or a database (each, a "Work"). - -Certain owners wish to permanently relinquish those rights to a Work for the -purpose of contributing to a commons of creative, cultural and scientific -works ("Commons") that the public can reliably and without fear of later -claims of infringement build upon, modify, incorporate in other works, reuse -and redistribute as freely as possible in any form whatsoever and for any -purposes, including without limitation commercial purposes. These owners may -contribute to the Commons to promote the ideal of a free culture and the -further production of creative, cultural and scientific works, or to gain -reputation or greater distribution for their Work in part through the use and -efforts of others. - -For these and/or other purposes and motivations, and without any expectation -of additional consideration or compensation, the person associating CC0 with a -Work (the "Affirmer"), to the extent that he or she is an owner of Copyright -and Related Rights in the Work, voluntarily elects to apply CC0 to the Work -and publicly distribute the Work under its terms, with knowledge of his or her -Copyright and Related Rights in the Work and the meaning and intended legal -effect of CC0 on those rights. - -1. Copyright and Related Rights. A Work made available under CC0 may be -protected by copyright and related or neighboring rights ("Copyright and -Related Rights"). Copyright and Related Rights include, but are not limited -to, the following: - - i. the right to reproduce, adapt, distribute, perform, display, communicate, - and translate a Work; - - ii. moral rights retained by the original author(s) and/or performer(s); - - iii. publicity and privacy rights pertaining to a person's image or likeness - depicted in a Work; - - iv. rights protecting against unfair competition in regards to a Work, - subject to the limitations in paragraph 4(a), below; - - v. rights protecting the extraction, dissemination, use and reuse of data in - a Work; - - vi. database rights (such as those arising under Directive 96/9/EC of the - European Parliament and of the Council of 11 March 1996 on the legal - protection of databases, and under any national implementation thereof, - including any amended or successor version of such directive); and - - vii. other similar, equivalent or corresponding rights throughout the world - based on applicable law or treaty, and any national implementations thereof. - -2. Waiver. To the greatest extent permitted by, but not in contravention of, -applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and -unconditionally waives, abandons, and surrenders all of Affirmer's Copyright -and Related Rights and associated claims and causes of action, whether now -known or unknown (including existing as well as future claims and causes of -action), in the Work (i) in all territories worldwide, (ii) for the maximum -duration provided by applicable law or treaty (including future time -extensions), (iii) in any current or future medium and for any number of -copies, and (iv) for any purpose whatsoever, including without limitation -commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes -the Waiver for the benefit of each member of the public at large and to the -detriment of Affirmer's heirs and successors, fully intending that such Waiver -shall not be subject to revocation, rescission, cancellation, termination, or -any other legal or equitable action to disrupt the quiet enjoyment of the Work -by the public as contemplated by Affirmer's express Statement of Purpose. - -3. Public License Fallback. Should any part of the Waiver for any reason be -judged legally invalid or ineffective under applicable law, then the Waiver -shall be preserved to the maximum extent permitted taking into account -Affirmer's express Statement of Purpose. In addition, to the extent the Waiver -is so judged Affirmer hereby grants to each affected person a royalty-free, -non transferable, non sublicensable, non exclusive, irrevocable and -unconditional license to exercise Affirmer's Copyright and Related Rights in -the Work (i) in all territories worldwide, (ii) for the maximum duration -provided by applicable law or treaty (including future time extensions), (iii) -in any current or future medium and for any number of copies, and (iv) for any -purpose whatsoever, including without limitation commercial, advertising or -promotional purposes (the "License"). The License shall be deemed effective as -of the date CC0 was applied by Affirmer to the Work. Should any part of the -License for any reason be judged legally invalid or ineffective under -applicable law, such partial invalidity or ineffectiveness shall not -invalidate the remainder of the License, and in such case Affirmer hereby -affirms that he or she will not (i) exercise any of his or her remaining -Copyright and Related Rights in the Work or (ii) assert any associated claims -and causes of action with respect to the Work, in either case contrary to -Affirmer's express Statement of Purpose. - -4. Limitations and Disclaimers. - - a. No trademark or patent rights held by Affirmer are waived, abandoned, - surrendered, licensed or otherwise affected by this document. - - b. Affirmer offers the Work as-is and makes no representations or warranties - of any kind concerning the Work, express, implied, statutory or otherwise, - including without limitation warranties of title, merchantability, fitness - for a particular purpose, non infringement, or the absence of latent or - other defects, accuracy, or the present or absence of errors, whether or not - discoverable, all to the greatest extent permissible under applicable law. - - c. Affirmer disclaims responsibility for clearing rights of other persons - that may apply to the Work or any use thereof, including without limitation - any person's Copyright and Related Rights in the Work. Further, Affirmer - disclaims responsibility for obtaining any necessary consents, permissions - or other rights required for any use of the Work. - - d. Affirmer understands and acknowledges that Creative Commons is not a - party to this document and has no duty or obligation with respect to this - CC0 or use of the Work. - -For more information, please see - diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_avx2/address.c b/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_avx2/address.c deleted file mode 100644 index 301c88f8c0..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_avx2/address.c +++ /dev/null @@ -1,78 +0,0 @@ -#include - -#include "address.h" -#include "params.h" -#include "utils.h" - -void PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]) { - int i; - - for (i = 0; i < 8; i++) { - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_ull_to_bytes( - bytes + i * 4, 4, addr[i]); - } -} - -void PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_set_layer_addr( - uint32_t addr[8], uint32_t layer) { - addr[0] = layer; -} - -void PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_set_tree_addr( - uint32_t addr[8], uint64_t tree) { - addr[1] = 0; - addr[2] = (uint32_t) (tree >> 32); - addr[3] = (uint32_t) tree; -} - -void PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_set_type( - uint32_t addr[8], uint32_t type) { - addr[4] = type; -} - -void PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; -} - -/* These functions are used for OTS addresses. */ - -void PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_set_keypair_addr( - uint32_t addr[8], uint32_t keypair) { - addr[5] = keypair; -} - -void PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; - out[5] = in[5]; -} - -void PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_set_chain_addr( - uint32_t addr[8], uint32_t chain) { - addr[6] = chain; -} - -void PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_set_hash_addr( - uint32_t addr[8], uint32_t hash) { - addr[7] = hash; -} - -/* These functions are used for all hash tree addresses (including FORS). */ - -void PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_set_tree_height( - uint32_t addr[8], uint32_t tree_height) { - addr[6] = tree_height; -} - -void PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_set_tree_index( - uint32_t addr[8], uint32_t tree_index) { - addr[7] = tree_index; -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_avx2/address.h b/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_avx2/address.h deleted file mode 100644 index b6d9b30d45..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_avx2/address.h +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_ADDRESS_H -#define PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_ADDRESS_H - -#include - -#define PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_ADDR_TYPE_WOTS 0 -#define PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_ADDR_TYPE_WOTSPK 1 -#define PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_ADDR_TYPE_HASHTREE 2 -#define PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_ADDR_TYPE_FORSTREE 3 -#define PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_ADDR_TYPE_FORSPK 4 - -void PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]); - -void PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_set_layer_addr( - uint32_t addr[8], uint32_t layer); - -void PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_set_tree_addr( - uint32_t addr[8], uint64_t tree); - -void PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_set_type( - uint32_t addr[8], uint32_t type); - -/* Copies the layer and tree part of one address into the other */ -void PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for WOTS and FORS addresses. */ - -void PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_set_keypair_addr( - uint32_t addr[8], uint32_t keypair); - -void PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_set_chain_addr( - uint32_t addr[8], uint32_t chain); - -void PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_set_hash_addr( - uint32_t addr[8], uint32_t hash); - -void PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for all hash tree addresses (including FORS). */ - -void PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_set_tree_height( - uint32_t addr[8], uint32_t tree_height); - -void PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_set_tree_index( - uint32_t addr[8], uint32_t tree_index); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_avx2/api.h b/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_avx2/api.h deleted file mode 100644 index ccb669d560..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_avx2/api.h +++ /dev/null @@ -1,81 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_API_H -#define PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_API_H - -#include -#include - - - -#define PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_CRYPTO_ALGNAME "SPHINCS+" - -#define PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_CRYPTO_SECRETKEYBYTES 64 -#define PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_CRYPTO_PUBLICKEYBYTES 32 -#define PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_CRYPTO_BYTES 7856 -#define PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_CRYPTO_SEEDBYTES 48 - - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_avx2/fors.c b/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_avx2/fors.c deleted file mode 100644 index fdcdcfc9ec..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_avx2/fors.c +++ /dev/null @@ -1,240 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "fors.h" -#include "hash.h" -#include "hashx8.h" -#include "thash.h" -#include "thashx8.h" -#include "utils.h" -#include "utilsx8.h" - -static void fors_gen_skx8(unsigned char *sk0, - unsigned char *sk1, - unsigned char *sk2, - unsigned char *sk3, - unsigned char *sk4, - unsigned char *sk5, - unsigned char *sk6, - unsigned char *sk7, const unsigned char *sk_seed, - uint32_t fors_leaf_addrx8[8 * 8]) { - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_prf_addrx8(sk0, sk1, sk2, sk3, sk4, sk5, sk6, sk7, - sk_seed, fors_leaf_addrx8); -} - -static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, - const unsigned char *pub_seed, - uint32_t fors_leaf_addr[8], - const hash_state *state_seeded) { - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_thash_1(leaf, sk, pub_seed, fors_leaf_addr, state_seeded); -} - -static void fors_sk_to_leafx8(unsigned char *leaf0, - unsigned char *leaf1, - unsigned char *leaf2, - unsigned char *leaf3, - unsigned char *leaf4, - unsigned char *leaf5, - unsigned char *leaf6, - unsigned char *leaf7, - const unsigned char *sk0, - const unsigned char *sk1, - const unsigned char *sk2, - const unsigned char *sk3, - const unsigned char *sk4, - const unsigned char *sk5, - const unsigned char *sk6, - const unsigned char *sk7, - const unsigned char *pub_seed, - uint32_t fors_leaf_addrx8[8 * 8], - const hash_state *state_seeded) { - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_thashx8_1(leaf0, leaf1, leaf2, leaf3, leaf4, leaf5, leaf6, leaf7, - sk0, sk1, sk2, sk3, sk4, sk5, sk6, sk7, - pub_seed, fors_leaf_addrx8, state_seeded); -} - -static void fors_gen_leafx8(unsigned char *leaf0, - unsigned char *leaf1, - unsigned char *leaf2, - unsigned char *leaf3, - unsigned char *leaf4, - unsigned char *leaf5, - unsigned char *leaf6, - unsigned char *leaf7, - const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx0, - uint32_t addr_idx1, - uint32_t addr_idx2, - uint32_t addr_idx3, - uint32_t addr_idx4, - uint32_t addr_idx5, - uint32_t addr_idx6, - uint32_t addr_idx7, - const uint32_t fors_tree_addr[8], - const hash_state *state_seeded) { - uint32_t fors_leaf_addrx8[8 * 8] = {0}; - unsigned int j; - - /* Only copy the parts that must be kept in fors_leaf_addrx8. */ - for (j = 0; j < 8; j++) { - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_copy_keypair_addr(fors_leaf_addrx8 + j * 8, fors_tree_addr); - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_set_type(fors_leaf_addrx8 + j * 8, PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_ADDR_TYPE_FORSTREE); - } - - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_set_tree_index(fors_leaf_addrx8 + 0 * 8, addr_idx0); - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_set_tree_index(fors_leaf_addrx8 + 1 * 8, addr_idx1); - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_set_tree_index(fors_leaf_addrx8 + 2 * 8, addr_idx2); - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_set_tree_index(fors_leaf_addrx8 + 3 * 8, addr_idx3); - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_set_tree_index(fors_leaf_addrx8 + 4 * 8, addr_idx4); - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_set_tree_index(fors_leaf_addrx8 + 5 * 8, addr_idx5); - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_set_tree_index(fors_leaf_addrx8 + 6 * 8, addr_idx6); - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_set_tree_index(fors_leaf_addrx8 + 7 * 8, addr_idx7); - - fors_gen_skx8(leaf0, leaf1, leaf2, leaf3, leaf4, leaf5, leaf6, leaf7, - sk_seed, fors_leaf_addrx8); - fors_sk_to_leafx8(leaf0, leaf1, leaf2, leaf3, leaf4, leaf5, leaf6, leaf7, - leaf0, leaf1, leaf2, leaf3, leaf4, leaf5, leaf6, leaf7, - pub_seed, fors_leaf_addrx8, state_seeded); -} - -/** - * Interprets m as PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_FORS_HEIGHT-bit unsigned integers. - * Assumes m contains at least PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_FORS_TREES bits. - * Assumes indices has space for PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_FORS_TREES integers. - */ -static void message_to_indices(uint32_t *indices, const unsigned char *m) { - unsigned int i, j; - unsigned int offset = 0; - - for (i = 0; i < PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_FORS_TREES; i++) { - indices[i] = 0; - for (j = 0; j < PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_FORS_HEIGHT; j++) { - indices[i] ^= (((uint32_t)m[offset >> 3] >> (offset & 0x7)) & 0x1) << j; - offset++; - } - } -} - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_fors_sign( - unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], - const hash_state *state_seeded) { - /* Round up to multiple of 8 to prevent out-of-bounds for x8 parallelism */ - uint32_t indices[(PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_FORS_TREES + 7) & ~7] = {0}; - unsigned char roots[((PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_FORS_TREES + 7) & ~7) * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N]; - /* Sign to a buffer, since we may not have a nice multiple of 8 and would - otherwise overrun the signature. */ - unsigned char sigbufx8[8 * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N * (1 + PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_FORS_HEIGHT)]; - uint32_t fors_tree_addrx8[8 * 8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset[8] = {0}; - unsigned int i, j; - - for (j = 0; j < 8; j++) { - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_copy_keypair_addr(fors_tree_addrx8 + j * 8, fors_addr); - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_set_type(fors_tree_addrx8 + j * 8, PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_ADDR_TYPE_FORSTREE); - } - - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_copy_keypair_addr(fors_pk_addr, fors_addr); - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_set_type(fors_pk_addr, PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < ((PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_FORS_TREES + 7) & ~0x7); i += 8) { - for (j = 0; j < 8; j++) { - if (i + j < PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_FORS_TREES) { - idx_offset[j] = (i + j) * (1 << PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_FORS_HEIGHT); - - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_set_tree_height(fors_tree_addrx8 + j * 8, 0); - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_set_tree_index(fors_tree_addrx8 + j * 8, - indices[i + j] + idx_offset[j]); - } - } - - /* Include the secret key part that produces the selected leaf nodes. */ - fors_gen_skx8(sigbufx8 + 0 * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N, - sigbufx8 + 1 * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N, - sigbufx8 + 2 * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N, - sigbufx8 + 3 * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N, - sigbufx8 + 4 * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N, - sigbufx8 + 5 * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N, - sigbufx8 + 6 * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N, - sigbufx8 + 7 * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N, - sk_seed, fors_tree_addrx8); - - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_treehashx8_FORS_HEIGHT( - roots + i * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N, sigbufx8 + 8 * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N, sk_seed, pub_seed, - &indices[i], idx_offset, fors_gen_leafx8, fors_tree_addrx8, - state_seeded); - - for (j = 0; j < 8; j++) { - if (i + j < PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_FORS_TREES) { - memcpy(sig, sigbufx8 + j * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N, PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N); - memcpy(sig + PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N, - sigbufx8 + 8 * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N + j * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_FORS_HEIGHT, - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_FORS_HEIGHT); - sig += PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N * (1 + PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_FORS_HEIGHT); - } - } - } - - /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_thash_FORS_TREES(pk, roots, pub_seed, fors_pk_addr, state_seeded); -} - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, - const uint32_t fors_addr[8], - const hash_state *state_seeded) { - uint32_t indices[PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_FORS_TREES]; - unsigned char roots[PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_FORS_TREES * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N]; - unsigned char leaf[PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N]; - uint32_t fors_tree_addr[8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_copy_keypair_addr(fors_tree_addr, fors_addr); - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_copy_keypair_addr(fors_pk_addr, fors_addr); - - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_set_type(fors_tree_addr, PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_set_type(fors_pk_addr, PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_FORS_TREES; i++) { - idx_offset = i * (1 << PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_FORS_HEIGHT); - - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_set_tree_height(fors_tree_addr, 0); - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Derive the leaf from the included secret key part. */ - fors_sk_to_leaf(leaf, sig, pub_seed, fors_tree_addr, state_seeded); - sig += PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N; - - /* Derive the corresponding root node of this tree. */ - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_compute_root(roots + i * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N, leaf, indices[i], idx_offset, - sig, PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_FORS_HEIGHT, pub_seed, fors_tree_addr, state_seeded); - sig += PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_thash_FORS_TREES(pk, roots, pub_seed, fors_pk_addr, state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_avx2/fors.h b/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_avx2/fors.h deleted file mode 100644 index 9e39b3e2f4..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_avx2/fors.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_FORS_H -#define PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_FORS_H - -#include - -#include "hash_state.h" -#include "params.h" - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_fors_sign( - unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *hash_state_seeded); - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_fors_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, const uint32_t fors_addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_avx2/hash.h b/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_avx2/hash.h deleted file mode 100644 index 602390baed..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_avx2/hash.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_HASH_H -#define PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_HASH_H - -#include "hash_state.h" - -#include -#include - -void PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_initialize_hash_function( - hash_state *hash_state_seeded, - const unsigned char *pub_seed, const unsigned char *sk_seed); - -void PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_destroy_hash_function(hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_avx2/hash_sha256.c b/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_avx2/hash_sha256.c deleted file mode 100644 index 3bb03320c0..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_avx2/hash_sha256.c +++ /dev/null @@ -1,166 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "utils.h" - -#include "sha2.h" -#include "sha256.h" -#include "sha256x8.h" - -/** - * Initializes the hash function states - */ -void PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_initialize_hash_function( - hash_state *hash_state_seeded, - const unsigned char *pub_seed, const unsigned char *sk_seed) { - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_seed_state(&hash_state_seeded->x1, pub_seed); - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_seed_statex8(&hash_state_seeded->x8, pub_seed); - (void)sk_seed; /* Suppress an 'unused parameter' warning. */ -} - -/** - * Cleans up the hash function states - */ -void PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_destroy_hash_function(hash_state *hash_state_seeded) { - sha256_inc_ctx_release(&hash_state_seeded->x1); -} - -/* - * Computes PRF(key, addr), given a secret key of PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N bytes and an address - */ -void PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_prf_addr(unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded) { - unsigned char buf[PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_ADDR_BYTES]; - unsigned char outbuf[PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_OUTPUT_BYTES]; - - memcpy(buf, key, PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N); - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_compress_address(buf + PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N, addr); - - sha256(outbuf, buf, PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_ADDR_BYTES); - memcpy(out, outbuf, PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} - -/** - * Computes the message-dependent randomness R, using a secret seed as a key - * for HMAC, and an optional randomization value prefixed to the message. - * This requires m to have at least PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_BLOCK_BYTES + PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N space - * available in front of the pointer, i.e. before the message to use for the - * prefix. This is necessary to prevent having to move the message around (and - * allocate memory for it). - */ -void PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, const hash_state *hash_state_seeded) { - unsigned char buf[PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_BLOCK_BYTES + PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_OUTPUT_BYTES]; - sha256ctx state; - int i; - - /* This implements HMAC-SHA256 */ - for (i = 0; i < PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N; i++) { - buf[i] = 0x36 ^ sk_prf[i]; - } - memset(buf + PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N, 0x36, PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N); - - sha256_inc_init(&state); - sha256_inc_blocks(&state, buf, 1); - - memcpy(buf, optrand, PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N); - - /* If optrand + message cannot fill up an entire block */ - if (PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N + mlen < PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_BLOCK_BYTES) { - memcpy(buf + PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N, m, mlen); - sha256_inc_finalize(buf + PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_BLOCK_BYTES, &state, - buf, mlen + PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N); - } - /* Otherwise first fill a block, so that finalize only uses the message */ - else { - memcpy(buf + PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N, m, PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N); - sha256_inc_blocks(&state, buf, 1); - - m += PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N; - mlen -= PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N; - sha256_inc_finalize(buf + PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_BLOCK_BYTES, &state, m, mlen); - } - - for (i = 0; i < PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N; i++) { - buf[i] = 0x5c ^ sk_prf[i]; - } - memset(buf + PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N, 0x5c, PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N); - - sha256(buf, buf, PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_BLOCK_BYTES + PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_OUTPUT_BYTES); - memcpy(R, buf, PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} - -/** - * Computes the message hash using R, the public key, and the message. - * Outputs the message digest and the index of the leaf. The index is split in - * the tree index and the leaf index, for convenient copying to an address. - */ -void PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded) { -#define PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_TREE_BITS (PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_TREE_HEIGHT * (PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_D - 1)) -#define PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_TREE_BYTES ((PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_TREE_BITS + 7) / 8) -#define PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_LEAF_BITS PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_TREE_HEIGHT -#define PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_LEAF_BYTES ((PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_LEAF_BITS + 7) / 8) -#define PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_DGST_BYTES (PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_FORS_MSG_BYTES + PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_TREE_BYTES + PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_LEAF_BYTES) - - unsigned char seed[PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_OUTPUT_BYTES + 4]; - - /* Round to nearest multiple of PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_BLOCK_BYTES */ -#define PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_INBLOCKS (((PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_PK_BYTES + PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_BLOCK_BYTES - 1) & \ - -PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_BLOCK_BYTES) / PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_BLOCK_BYTES) - unsigned char inbuf[PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_INBLOCKS * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_BLOCK_BYTES]; - - unsigned char buf[PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_DGST_BYTES]; - unsigned char *bufp = buf; - sha256ctx state; - - sha256_inc_init(&state); - - memcpy(inbuf, R, PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N); - memcpy(inbuf + PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N, pk, PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_PK_BYTES); - - /* If R + pk + message cannot fill up an entire block */ - if (PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_PK_BYTES + mlen < PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_INBLOCKS * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_BLOCK_BYTES) { - memcpy(inbuf + PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_PK_BYTES, m, mlen); - sha256_inc_finalize(seed, &state, inbuf, PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_PK_BYTES + mlen); - } - /* Otherwise first fill a block, so that finalize only uses the message */ - else { - memcpy(inbuf + PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_PK_BYTES, m, - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_INBLOCKS * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_PK_BYTES); - sha256_inc_blocks(&state, inbuf, PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_INBLOCKS); - - m += PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_INBLOCKS * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_PK_BYTES; - mlen -= PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_INBLOCKS * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_PK_BYTES; - sha256_inc_finalize(seed, &state, m, mlen); - } - - /* By doing this in two steps, we prevent hashing the message twice; - otherwise each iteration in MGF1 would hash the message again. */ - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_mgf1(bufp, PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_DGST_BYTES, seed, PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_OUTPUT_BYTES); - - memcpy(digest, bufp, PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_FORS_MSG_BYTES); - bufp += PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_FORS_MSG_BYTES; - - *tree = PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_bytes_to_ull(bufp, PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_TREE_BYTES); - *tree &= (~(uint64_t)0) >> (64 - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_TREE_BITS); - bufp += PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_TREE_BYTES; - - *leaf_idx = (uint32_t)PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_bytes_to_ull( - bufp, PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_LEAF_BYTES); - *leaf_idx &= (~(uint32_t)0) >> (32 - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_LEAF_BITS); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_avx2/hash_sha256x8.c b/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_avx2/hash_sha256x8.c deleted file mode 100644 index c71a605465..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_avx2/hash_sha256x8.c +++ /dev/null @@ -1,61 +0,0 @@ -#include -#include - -#include "address.h" -#include "hashx8.h" -#include "params.h" -#include "sha256.h" -#include "sha256avx.h" -#include "sha256x8.h" -#include "utils.h" - -/* - * 8-way parallel version of prf_addr; takes 8x as much input and output - */ -void PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_prf_addrx8(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7, - const unsigned char *key, - const uint32_t addrx8[8 * 8]) { - unsigned char bufx8[8 * (PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_ADDR_BYTES)]; - unsigned char outbufx8[8 * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_OUTPUT_BYTES]; - unsigned int j; - - for (j = 0; j < 8; j++) { - memcpy(bufx8 + j * (PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_ADDR_BYTES), key, PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N); - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_compress_address(bufx8 + PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N + j * (PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_ADDR_BYTES), - addrx8 + j * 8); - } - - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_sha256x8(outbufx8 + 0 * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 1 * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 2 * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 3 * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 4 * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 5 * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 6 * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 7 * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_OUTPUT_BYTES, - bufx8 + 0 * (PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_ADDR_BYTES), - bufx8 + 1 * (PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_ADDR_BYTES), - bufx8 + 2 * (PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_ADDR_BYTES), - bufx8 + 3 * (PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_ADDR_BYTES), - bufx8 + 4 * (PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_ADDR_BYTES), - bufx8 + 5 * (PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_ADDR_BYTES), - bufx8 + 6 * (PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_ADDR_BYTES), - bufx8 + 7 * (PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_ADDR_BYTES), - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_ADDR_BYTES); - - memcpy(out0, outbufx8 + 0 * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N); - memcpy(out1, outbufx8 + 1 * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N); - memcpy(out2, outbufx8 + 2 * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N); - memcpy(out3, outbufx8 + 3 * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N); - memcpy(out4, outbufx8 + 4 * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N); - memcpy(out5, outbufx8 + 5 * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N); - memcpy(out6, outbufx8 + 6 * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N); - memcpy(out7, outbufx8 + 7 * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_avx2/hash_state.h b/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_avx2/hash_state.h deleted file mode 100644 index 835b0ddda7..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_avx2/hash_state.h +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_HASH_STATE_H -#define PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_HASH_STATE_H - -/** - * Defines the type of the hash function state. - * - * Don't be fooled into thinking this instance of SPHINCS+ isn't stateless! - * - * From Section 7.2.2 from the SPHINCS+ round-2 specification: - * - * Each of the instances of the tweakable hash function take PK.seed as its - * first input, which is constant for a given key pair – and, thus, across - * a single signature. This leads to a lot of redundant computation. To remedy - * this, we pad PK.seed to the length of a full 64-byte SHA-256 input block. - * Because of the Merkle-DamgÃ¥rd construction that underlies SHA-256, this - * allows for reuse of the intermediate SHA-256 state after the initial call to - * the compression function which improves performance. - * - * We pass this hash state around in functions, because otherwise we need to - * have a global variable. - * - * We use a struct to differentiate between the x1 and x8 variants of SHA256. - */ - -#include "sha2.h" -#include "sha256avx.h" - -typedef struct { - sha256ctx x1; - sha256ctxx8 x8; -} hash_state; - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_avx2/hashx8.h b/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_avx2/hashx8.h deleted file mode 100644 index 68617c2166..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_avx2/hashx8.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_HASHX8_H -#define PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_HASHX8_H - -#include - -#include "params.h" - -void PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_prf_addrx8(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7, - const unsigned char *key, - const uint32_t addrx8[8 * 8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_avx2/params.h b/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_avx2/params.h deleted file mode 100644 index 2a9f013471..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_avx2/params.h +++ /dev/null @@ -1,53 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_PARAMS_H -#define PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_PARAMS_H - -/* Hash output length in bytes. */ -#define PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N 16 -/* Height of the hypertree. */ -#define PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_FULL_HEIGHT 63 -/* Number of subtree layer. */ -#define PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_D 7 -/* FORS tree dimensions. */ -#define PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_FORS_HEIGHT 12 -#define PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_FORS_TREES 14 -/* Winternitz parameter, */ -#define PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_WOTS_W 16 - -/* The hash function is defined by linking a different hash.c file, as opposed - to setting a #define constant. */ - -/* For clarity */ -#define PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_ADDR_BYTES 32 - -/* WOTS parameters. */ -#define PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_WOTS_LOGW 4 - -#define PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_WOTS_LEN1 (8 * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N / PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_WOTS_LOGW) - -/* PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#define PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_WOTS_LEN2 3 - -#define PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_WOTS_LEN (PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_WOTS_LEN1 + PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_WOTS_LEN2) -#define PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_WOTS_BYTES (PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_WOTS_LEN * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N) -#define PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_WOTS_PK_BYTES PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_WOTS_BYTES - -/* Subtree size. */ -#define PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_TREE_HEIGHT (PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_FULL_HEIGHT / PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_D) - -/* FORS parameters. */ -#define PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_FORS_MSG_BYTES ((PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_FORS_TREES + 7) / 8) -#define PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_FORS_BYTES ((PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_FORS_HEIGHT + 1) * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_FORS_TREES * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N) -#define PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_FORS_PK_BYTES PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N - -/* Resulting SPX sizes. */ -#define PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_BYTES (PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_FORS_BYTES + PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_D * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_WOTS_BYTES +\ - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_FULL_HEIGHT * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N) -#define PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_PK_BYTES (2 * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N) -#define PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SK_BYTES (2 * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_PK_BYTES) - -/* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ -#define PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_OPTRAND_BYTES 32 - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_avx2/sha256.c b/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_avx2/sha256.c deleted file mode 100644 index f722e3ec02..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_avx2/sha256.c +++ /dev/null @@ -1,71 +0,0 @@ -/* Based on the public domain implementation in - * crypto_hash/sha512/ref/ from http://bench.cr.yp.to/supercop.html - * by D. J. Bernstein */ - -#include -#include -#include - -#include "sha2.h" -#include "sha256.h" -#include "utils.h" - -/* - * Compresses an address to a 22-byte sequence. - * This reduces the number of required SHA256 compression calls, as the last - * block of input is padded with at least 65 bits. - */ -void PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_compress_address(unsigned char *out, const uint32_t addr[8]) { - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_ull_to_bytes(out, 1, addr[0]); /* drop 3 bytes of the layer field */ - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_ull_to_bytes(out + 1, 4, addr[2]); /* drop the highest tree address word */ - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_ull_to_bytes(out + 5, 4, addr[3]); - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_ull_to_bytes(out + 9, 1, addr[4]); /* drop 3 bytes of the type field */ - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_ull_to_bytes(out + 10, 4, addr[5]); - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_ull_to_bytes(out + 14, 4, addr[6]); - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_ull_to_bytes(out + 18, 4, addr[7]); -} - -/** - * Requires 'input_plus_four_bytes' to have 'inlen' + 4 bytes, so that the last - * four bytes can be used for the counter. Typically 'input' is merely a seed. - * Outputs outlen number of bytes - */ -void PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_mgf1( - unsigned char *out, unsigned long outlen, - unsigned char *input_plus_four_bytes, unsigned long inlen) { - unsigned char outbuf[PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_OUTPUT_BYTES]; - unsigned long i; - - /* While we can fit in at least another full block of SHA256 output.. */ - for (i = 0; (i + 1)*PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_OUTPUT_BYTES <= outlen; i++) { - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_ull_to_bytes(input_plus_four_bytes + inlen, 4, i); - sha256(out, input_plus_four_bytes, inlen + 4); - out += PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_OUTPUT_BYTES; - } - /* Until we cannot anymore, and we fill the remainder. */ - if (outlen > i * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_OUTPUT_BYTES) { - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_ull_to_bytes(input_plus_four_bytes + inlen, 4, i); - sha256(outbuf, input_plus_four_bytes, inlen + 4); - memcpy(out, outbuf, outlen - i * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_OUTPUT_BYTES); - } -} - - -/** - * Absorb the constant pub_seed using one round of the compression function - * This initializes hash_state_seeded, which can then be reused in thash - **/ -void PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_seed_state(sha256ctx *hash_state_seeded, const unsigned char *pub_seed) { - uint8_t block[PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_BLOCK_BYTES]; - size_t i; - - for (i = 0; i < PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N; ++i) { - block[i] = pub_seed[i]; - } - for (i = PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N; i < PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_BLOCK_BYTES; ++i) { - block[i] = 0; - } - - sha256_inc_init(hash_state_seeded); - sha256_inc_blocks(hash_state_seeded, block, 1); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_avx2/sha256.h b/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_avx2/sha256.h deleted file mode 100644 index 51bf8c8669..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_avx2/sha256.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_H -#define PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_H - -#define PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_BLOCK_BYTES 64 -#define PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_OUTPUT_BYTES 32 /* This does not necessarily equal PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N */ -#define PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_ADDR_BYTES 22 - -#include -#include - -#include "sha2.h" - -void PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_compress_address(unsigned char *out, const uint32_t addr[8]); - -void PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_mgf1( - unsigned char *out, unsigned long outlen, - unsigned char *input_plus_four_bytes, unsigned long inlen); - -void PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_seed_state(sha256ctx *hash_state_seeded, const unsigned char *pub_seed); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_avx2/sha256avx.c b/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_avx2/sha256avx.c deleted file mode 100644 index 28f4fda8a6..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_avx2/sha256avx.c +++ /dev/null @@ -1,296 +0,0 @@ -#include -#include -#include - -#include "sha256avx.h" - -// Transpose 8 vectors containing 32-bit values -void PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_transpose(u256 s[8]) { - u256 tmp0[8]; - u256 tmp1[8]; - tmp0[0] = _mm256_unpacklo_epi32(s[0], s[1]); - tmp0[1] = _mm256_unpackhi_epi32(s[0], s[1]); - tmp0[2] = _mm256_unpacklo_epi32(s[2], s[3]); - tmp0[3] = _mm256_unpackhi_epi32(s[2], s[3]); - tmp0[4] = _mm256_unpacklo_epi32(s[4], s[5]); - tmp0[5] = _mm256_unpackhi_epi32(s[4], s[5]); - tmp0[6] = _mm256_unpacklo_epi32(s[6], s[7]); - tmp0[7] = _mm256_unpackhi_epi32(s[6], s[7]); - tmp1[0] = _mm256_unpacklo_epi64(tmp0[0], tmp0[2]); - tmp1[1] = _mm256_unpackhi_epi64(tmp0[0], tmp0[2]); - tmp1[2] = _mm256_unpacklo_epi64(tmp0[1], tmp0[3]); - tmp1[3] = _mm256_unpackhi_epi64(tmp0[1], tmp0[3]); - tmp1[4] = _mm256_unpacklo_epi64(tmp0[4], tmp0[6]); - tmp1[5] = _mm256_unpackhi_epi64(tmp0[4], tmp0[6]); - tmp1[6] = _mm256_unpacklo_epi64(tmp0[5], tmp0[7]); - tmp1[7] = _mm256_unpackhi_epi64(tmp0[5], tmp0[7]); - s[0] = _mm256_permute2x128_si256(tmp1[0], tmp1[4], 0x20); - s[1] = _mm256_permute2x128_si256(tmp1[1], tmp1[5], 0x20); - s[2] = _mm256_permute2x128_si256(tmp1[2], tmp1[6], 0x20); - s[3] = _mm256_permute2x128_si256(tmp1[3], tmp1[7], 0x20); - s[4] = _mm256_permute2x128_si256(tmp1[0], tmp1[4], 0x31); - s[5] = _mm256_permute2x128_si256(tmp1[1], tmp1[5], 0x31); - s[6] = _mm256_permute2x128_si256(tmp1[2], tmp1[6], 0x31); - s[7] = _mm256_permute2x128_si256(tmp1[3], tmp1[7], 0x31); -} - -void PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_sha256_clone_statex8(sha256ctxx8 *outctx, const sha256ctxx8 *inctx) { - memcpy(outctx, inctx, sizeof(sha256ctxx8)); -} - -void PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_sha256_init8x(sha256ctxx8 *ctx) { - ctx->s[0] = _mm256_set_epi32((int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667); - ctx->s[1] = _mm256_set_epi32((int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85); - ctx->s[2] = _mm256_set_epi32((int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372); - ctx->s[3] = _mm256_set_epi32((int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a); - ctx->s[4] = _mm256_set_epi32((int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f); - ctx->s[5] = _mm256_set_epi32((int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c); - ctx->s[6] = _mm256_set_epi32((int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab); - ctx->s[7] = _mm256_set_epi32((int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19); - - ctx->datalen = 0; - ctx->msglen = 0; -} - -void PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_sha256_update8x(sha256ctxx8 *ctx, - const unsigned char *d0, - const unsigned char *d1, - const unsigned char *d2, - const unsigned char *d3, - const unsigned char *d4, - const unsigned char *d5, - const unsigned char *d6, - const unsigned char *d7, - unsigned long long len) { - size_t i = 0; - size_t bytes_to_copy; - - while (i < len) { - bytes_to_copy = (size_t)len - i; - if (bytes_to_copy > 64) { - bytes_to_copy = 64; - } - memcpy(&ctx->msgblocks[64 * 0], d0 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64 * 1], d1 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64 * 2], d2 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64 * 3], d3 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64 * 4], d4 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64 * 5], d5 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64 * 6], d6 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64 * 7], d7 + i, bytes_to_copy); - ctx->datalen += (unsigned int)bytes_to_copy; - i += bytes_to_copy; - if (ctx->datalen == 64) { - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_sha256_transform8x(ctx, ctx->msgblocks); - ctx->msglen += 512; - ctx->datalen = 0; - } - } -} - -void PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_sha256_final8x(sha256ctxx8 *ctx, - unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7) { - unsigned int i, curlen; - - // Padding - if (ctx->datalen < 56) { - for (i = 0; i < 8; ++i) { - curlen = ctx->datalen; - ctx->msgblocks[64 * i + curlen++] = 0x80; - while (curlen < 64) { - ctx->msgblocks[64 * i + curlen++] = 0x00; - } - } - } else { - for (i = 0; i < 8; ++i) { - curlen = ctx->datalen; - ctx->msgblocks[64 * i + curlen++] = 0x80; - while (curlen < 64) { - ctx->msgblocks[64 * i + curlen++] = 0x00; - } - } - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_sha256_transform8x(ctx, ctx->msgblocks); - memset(ctx->msgblocks, 0, 8 * 64); - } - - // Add length of the message to each block - ctx->msglen += ctx->datalen * 8; - for (i = 0; i < 8; i++) { - ctx->msgblocks[64 * i + 63] = (unsigned char)ctx->msglen; - ctx->msgblocks[64 * i + 62] = (unsigned char)(ctx->msglen >> 8); - ctx->msgblocks[64 * i + 61] = (unsigned char)(ctx->msglen >> 16); - ctx->msgblocks[64 * i + 60] = (unsigned char)(ctx->msglen >> 24); - ctx->msgblocks[64 * i + 59] = (unsigned char)(ctx->msglen >> 32); - ctx->msgblocks[64 * i + 58] = (unsigned char)(ctx->msglen >> 40); - ctx->msgblocks[64 * i + 57] = (unsigned char)(ctx->msglen >> 48); - ctx->msgblocks[64 * i + 56] = (unsigned char)(ctx->msglen >> 56); - } - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_sha256_transform8x(ctx, ctx->msgblocks); - - // Compute final hash output - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_transpose(ctx->s); - - // Store Hash value - STORE(out0, BYTESWAP(ctx->s[0])); - STORE(out1, BYTESWAP(ctx->s[1])); - STORE(out2, BYTESWAP(ctx->s[2])); - STORE(out3, BYTESWAP(ctx->s[3])); - STORE(out4, BYTESWAP(ctx->s[4])); - STORE(out5, BYTESWAP(ctx->s[5])); - STORE(out6, BYTESWAP(ctx->s[6])); - STORE(out7, BYTESWAP(ctx->s[7])); -} - -void PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_sha256_transform8x(sha256ctxx8 *ctx, const unsigned char *data) { - u256 s[8], w[64], T0, T1; - int i; - - // Load words and transform data correctly - for (i = 0; i < 8; i++) { - w[i] = BYTESWAP(LOAD(data + 64 * i)); - w[i + 8] = BYTESWAP(LOAD(data + 32 + 64 * i)); - } - - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_transpose(w); - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_transpose(w + 8); - - // Initial State - s[0] = ctx->s[0]; - s[1] = ctx->s[1]; - s[2] = ctx->s[2]; - s[3] = ctx->s[3]; - s[4] = ctx->s[4]; - s[5] = ctx->s[5]; - s[6] = ctx->s[6]; - s[7] = ctx->s[7]; - - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 0, w[0]); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 1, w[1]); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 2, w[2]); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 3, w[3]); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 4, w[4]); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 5, w[5]); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 6, w[6]); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 7, w[7]); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 8, w[8]); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 9, w[9]); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 10, w[10]); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 11, w[11]); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 12, w[12]); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 13, w[13]); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 14, w[14]); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 15, w[15]); - w[16] = ADD4_32(WSIGMA1_AVX(w[14]), w[0], w[9], WSIGMA0_AVX(w[1])); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 16, w[16]); - w[17] = ADD4_32(WSIGMA1_AVX(w[15]), w[1], w[10], WSIGMA0_AVX(w[2])); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 17, w[17]); - w[18] = ADD4_32(WSIGMA1_AVX(w[16]), w[2], w[11], WSIGMA0_AVX(w[3])); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 18, w[18]); - w[19] = ADD4_32(WSIGMA1_AVX(w[17]), w[3], w[12], WSIGMA0_AVX(w[4])); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 19, w[19]); - w[20] = ADD4_32(WSIGMA1_AVX(w[18]), w[4], w[13], WSIGMA0_AVX(w[5])); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 20, w[20]); - w[21] = ADD4_32(WSIGMA1_AVX(w[19]), w[5], w[14], WSIGMA0_AVX(w[6])); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 21, w[21]); - w[22] = ADD4_32(WSIGMA1_AVX(w[20]), w[6], w[15], WSIGMA0_AVX(w[7])); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 22, w[22]); - w[23] = ADD4_32(WSIGMA1_AVX(w[21]), w[7], w[16], WSIGMA0_AVX(w[8])); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 23, w[23]); - w[24] = ADD4_32(WSIGMA1_AVX(w[22]), w[8], w[17], WSIGMA0_AVX(w[9])); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 24, w[24]); - w[25] = ADD4_32(WSIGMA1_AVX(w[23]), w[9], w[18], WSIGMA0_AVX(w[10])); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 25, w[25]); - w[26] = ADD4_32(WSIGMA1_AVX(w[24]), w[10], w[19], WSIGMA0_AVX(w[11])); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 26, w[26]); - w[27] = ADD4_32(WSIGMA1_AVX(w[25]), w[11], w[20], WSIGMA0_AVX(w[12])); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 27, w[27]); - w[28] = ADD4_32(WSIGMA1_AVX(w[26]), w[12], w[21], WSIGMA0_AVX(w[13])); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 28, w[28]); - w[29] = ADD4_32(WSIGMA1_AVX(w[27]), w[13], w[22], WSIGMA0_AVX(w[14])); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 29, w[29]); - w[30] = ADD4_32(WSIGMA1_AVX(w[28]), w[14], w[23], WSIGMA0_AVX(w[15])); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 30, w[30]); - w[31] = ADD4_32(WSIGMA1_AVX(w[29]), w[15], w[24], WSIGMA0_AVX(w[16])); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 31, w[31]); - w[32] = ADD4_32(WSIGMA1_AVX(w[30]), w[16], w[25], WSIGMA0_AVX(w[17])); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 32, w[32]); - w[33] = ADD4_32(WSIGMA1_AVX(w[31]), w[17], w[26], WSIGMA0_AVX(w[18])); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 33, w[33]); - w[34] = ADD4_32(WSIGMA1_AVX(w[32]), w[18], w[27], WSIGMA0_AVX(w[19])); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 34, w[34]); - w[35] = ADD4_32(WSIGMA1_AVX(w[33]), w[19], w[28], WSIGMA0_AVX(w[20])); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 35, w[35]); - w[36] = ADD4_32(WSIGMA1_AVX(w[34]), w[20], w[29], WSIGMA0_AVX(w[21])); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 36, w[36]); - w[37] = ADD4_32(WSIGMA1_AVX(w[35]), w[21], w[30], WSIGMA0_AVX(w[22])); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 37, w[37]); - w[38] = ADD4_32(WSIGMA1_AVX(w[36]), w[22], w[31], WSIGMA0_AVX(w[23])); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 38, w[38]); - w[39] = ADD4_32(WSIGMA1_AVX(w[37]), w[23], w[32], WSIGMA0_AVX(w[24])); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 39, w[39]); - w[40] = ADD4_32(WSIGMA1_AVX(w[38]), w[24], w[33], WSIGMA0_AVX(w[25])); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 40, w[40]); - w[41] = ADD4_32(WSIGMA1_AVX(w[39]), w[25], w[34], WSIGMA0_AVX(w[26])); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 41, w[41]); - w[42] = ADD4_32(WSIGMA1_AVX(w[40]), w[26], w[35], WSIGMA0_AVX(w[27])); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 42, w[42]); - w[43] = ADD4_32(WSIGMA1_AVX(w[41]), w[27], w[36], WSIGMA0_AVX(w[28])); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 43, w[43]); - w[44] = ADD4_32(WSIGMA1_AVX(w[42]), w[28], w[37], WSIGMA0_AVX(w[29])); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 44, w[44]); - w[45] = ADD4_32(WSIGMA1_AVX(w[43]), w[29], w[38], WSIGMA0_AVX(w[30])); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 45, w[45]); - w[46] = ADD4_32(WSIGMA1_AVX(w[44]), w[30], w[39], WSIGMA0_AVX(w[31])); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 46, w[46]); - w[47] = ADD4_32(WSIGMA1_AVX(w[45]), w[31], w[40], WSIGMA0_AVX(w[32])); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 47, w[47]); - w[48] = ADD4_32(WSIGMA1_AVX(w[46]), w[32], w[41], WSIGMA0_AVX(w[33])); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 48, w[48]); - w[49] = ADD4_32(WSIGMA1_AVX(w[47]), w[33], w[42], WSIGMA0_AVX(w[34])); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 49, w[49]); - w[50] = ADD4_32(WSIGMA1_AVX(w[48]), w[34], w[43], WSIGMA0_AVX(w[35])); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 50, w[50]); - w[51] = ADD4_32(WSIGMA1_AVX(w[49]), w[35], w[44], WSIGMA0_AVX(w[36])); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 51, w[51]); - w[52] = ADD4_32(WSIGMA1_AVX(w[50]), w[36], w[45], WSIGMA0_AVX(w[37])); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 52, w[52]); - w[53] = ADD4_32(WSIGMA1_AVX(w[51]), w[37], w[46], WSIGMA0_AVX(w[38])); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 53, w[53]); - w[54] = ADD4_32(WSIGMA1_AVX(w[52]), w[38], w[47], WSIGMA0_AVX(w[39])); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 54, w[54]); - w[55] = ADD4_32(WSIGMA1_AVX(w[53]), w[39], w[48], WSIGMA0_AVX(w[40])); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 55, w[55]); - w[56] = ADD4_32(WSIGMA1_AVX(w[54]), w[40], w[49], WSIGMA0_AVX(w[41])); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 56, w[56]); - w[57] = ADD4_32(WSIGMA1_AVX(w[55]), w[41], w[50], WSIGMA0_AVX(w[42])); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 57, w[57]); - w[58] = ADD4_32(WSIGMA1_AVX(w[56]), w[42], w[51], WSIGMA0_AVX(w[43])); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 58, w[58]); - w[59] = ADD4_32(WSIGMA1_AVX(w[57]), w[43], w[52], WSIGMA0_AVX(w[44])); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 59, w[59]); - w[60] = ADD4_32(WSIGMA1_AVX(w[58]), w[44], w[53], WSIGMA0_AVX(w[45])); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 60, w[60]); - w[61] = ADD4_32(WSIGMA1_AVX(w[59]), w[45], w[54], WSIGMA0_AVX(w[46])); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 61, w[61]); - w[62] = ADD4_32(WSIGMA1_AVX(w[60]), w[46], w[55], WSIGMA0_AVX(w[47])); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 62, w[62]); - w[63] = ADD4_32(WSIGMA1_AVX(w[61]), w[47], w[56], WSIGMA0_AVX(w[48])); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 63, w[63]); - - // Feed Forward - ctx->s[0] = ADD32(s[0], ctx->s[0]); - ctx->s[1] = ADD32(s[1], ctx->s[1]); - ctx->s[2] = ADD32(s[2], ctx->s[2]); - ctx->s[3] = ADD32(s[3], ctx->s[3]); - ctx->s[4] = ADD32(s[4], ctx->s[4]); - ctx->s[5] = ADD32(s[5], ctx->s[5]); - ctx->s[6] = ADD32(s[6], ctx->s[6]); - ctx->s[7] = ADD32(s[7], ctx->s[7]); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_avx2/sha256avx.h b/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_avx2/sha256avx.h deleted file mode 100644 index 278f5c4d5b..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_avx2/sha256avx.h +++ /dev/null @@ -1,103 +0,0 @@ -#ifndef SHA256AVX_H -#define SHA256AVX_H - -#include -#include - -static const unsigned int RC[] = { - 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, - 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, - 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, - 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, - 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, - 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, - 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, - 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, - 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, - 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, - 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, - 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, - 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, - 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, - 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, - 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 -}; - -#define u32 uint32_t -#define u256 __m256i - -#define XOR _mm256_xor_si256 -#define OR _mm256_or_si256 -#define AND _mm256_and_si256 -#define ADD32 _mm256_add_epi32 -#define NOT(x) _mm256_xor_si256(x, _mm256_set_epi32(-1, -1, -1, -1, -1, -1, -1, -1)) - -#define LOAD(src) _mm256_loadu_si256((__m256i *)(src)) -#define STORE(dest,src) _mm256_storeu_si256((__m256i *)(dest),src) - -#define BYTESWAP(x) _mm256_shuffle_epi8(x, _mm256_set_epi8(0xc,0xd,0xe,0xf,0x8,0x9,0xa,0xb,0x4,0x5,0x6,0x7,0x0,0x1,0x2,0x3,0xc,0xd,0xe,0xf,0x8,0x9,0xa,0xb,0x4,0x5,0x6,0x7,0x0,0x1,0x2,0x3)) - -#define SHIFTR32(x, y) _mm256_srli_epi32(x, y) -#define SHIFTL32(x, y) _mm256_slli_epi32(x, y) - -#define ROTR32(x, y) OR(SHIFTR32(x, y), SHIFTL32(x, 32 - (y))) -#define ROTL32(x, y) OR(SHIFTL32(x, y), SHIFTR32(x, 32 - (y))) - -#define XOR3(a, b, c) XOR(XOR(a, b), c) - -#define ADD3_32(a, b, c) ADD32(ADD32(a, b), c) -#define ADD4_32(a, b, c, d) ADD32(ADD32(ADD32(a, b), c), d) -#define ADD5_32(a, b, c, d, e) ADD32(ADD32(ADD32(ADD32(a, b), c), d), e) - -#define MAJ_AVX(a, b, c) XOR3(AND(a, b), AND(a, c), AND(b, c)) -#define CH_AVX(a, b, c) XOR(AND(a, b), AND(NOT(a), c)) - -#define SIGMA1_AVX(x) XOR3(ROTR32(x, 6), ROTR32(x, 11), ROTR32(x, 25)) -#define SIGMA0_AVX(x) XOR3(ROTR32(x, 2), ROTR32(x, 13), ROTR32(x, 22)) - -#define WSIGMA1_AVX(x) XOR3(ROTR32(x, 17), ROTR32(x, 19), SHIFTR32(x, 10)) -#define WSIGMA0_AVX(x) XOR3(ROTR32(x, 7), ROTR32(x, 18), SHIFTR32(x, 3)) - -#define SHA256ROUND_AVX(a, b, c, d, e, f, g, h, rc, w) \ - T0 = ADD5_32(h, SIGMA1_AVX(e), CH_AVX(e, f, g), _mm256_set1_epi32((int)RC[rc]), w); \ - (d) = ADD32(d, T0); \ - T1 = ADD32(SIGMA0_AVX(a), MAJ_AVX(a, b, c)); \ - (h) = ADD32(T0, T1); - -typedef struct SHA256state { - u256 s[8]; - uint8_t msgblocks[8 * 64]; - unsigned int datalen; - uint64_t msglen; -} sha256ctxx8; - - -void PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_transpose(u256 s[8]); -void PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_sha256_init_frombytes_x8(sha256ctxx8 *ctx, const uint8_t *s, unsigned long long msglen); -void PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_sha256_init8x(sha256ctxx8 *ctx); -void PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_sha256_update8x(sha256ctxx8 *ctx, - const unsigned char *d0, - const unsigned char *d1, - const unsigned char *d2, - const unsigned char *d3, - const unsigned char *d4, - const unsigned char *d5, - const unsigned char *d6, - const unsigned char *d7, - unsigned long long len); -void PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_sha256_final8x(sha256ctxx8 *ctx, - unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7); - -void PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_sha256_transform8x(sha256ctxx8 *ctx, const unsigned char *data); - -void PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_sha256_clone_statex8(sha256ctxx8 *outctx, const sha256ctxx8 *inctx); - - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_avx2/sha256x8.c b/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_avx2/sha256x8.c deleted file mode 100644 index 257c93f0d4..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_avx2/sha256x8.c +++ /dev/null @@ -1,128 +0,0 @@ -#include - -#include "sha256.h" -#include "sha256avx.h" -#include "sha256x8.h" -#include "utils.h" - -void PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_seed_statex8(sha256ctxx8 *ctx, const unsigned char *pub_seed) { - uint8_t block[PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_BLOCK_BYTES]; - size_t i; - - for (i = 0; i < PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N; ++i) { - block[i] = pub_seed[i]; - } - for (i = PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N; i < PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_BLOCK_BYTES; ++i) { - block[i] = 0; - } - - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_sha256_init8x(ctx); - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_sha256_update8x(ctx, block, block, block, block, block, block, block, block, PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_BLOCK_BYTES); - -} - -/* This provides a wrapper around the internals of 8x parallel SHA256 */ -void PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_sha256x8(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - const unsigned char *in4, - const unsigned char *in5, - const unsigned char *in6, - const unsigned char *in7, unsigned long long inlen) { - sha256ctxx8 ctx; - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_sha256_init8x(&ctx); - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_sha256_update8x(&ctx, in0, in1, in2, in3, in4, in5, in6, in7, inlen); - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_sha256_final8x(&ctx, out0, out1, out2, out3, out4, out5, out6, out7); -} - -/** - * Note that inlen should be sufficiently small that it still allows for - * an array to be allocated on the stack. Typically 'in' is merely a seed. - * Outputs outlen number of bytes - */ -void PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_mgf1x8( - unsigned char *outx8, - unsigned long outlen, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - const unsigned char *in4, - const unsigned char *in5, - const unsigned char *in6, - const unsigned char *in7, - unsigned long inlen) { - unsigned char inbufx8[8 * ((PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_ADDR_BYTES) + 4)]; - unsigned char outbufx8[8 * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_OUTPUT_BYTES]; - unsigned long i; - unsigned int j; - - memcpy(inbufx8 + 0 * (inlen + 4), in0, inlen); - memcpy(inbufx8 + 1 * (inlen + 4), in1, inlen); - memcpy(inbufx8 + 2 * (inlen + 4), in2, inlen); - memcpy(inbufx8 + 3 * (inlen + 4), in3, inlen); - memcpy(inbufx8 + 4 * (inlen + 4), in4, inlen); - memcpy(inbufx8 + 5 * (inlen + 4), in5, inlen); - memcpy(inbufx8 + 6 * (inlen + 4), in6, inlen); - memcpy(inbufx8 + 7 * (inlen + 4), in7, inlen); - - /* While we can fit in at least another full block of SHA256 output.. */ - for (i = 0; (i + 1)*PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_OUTPUT_BYTES <= outlen; i++) { - for (j = 0; j < 8; j++) { - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_ull_to_bytes(inbufx8 + inlen + j * (inlen + 4), 4, i); - } - - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_sha256x8(outx8 + 0 * outlen, - outx8 + 1 * outlen, - outx8 + 2 * outlen, - outx8 + 3 * outlen, - outx8 + 4 * outlen, - outx8 + 5 * outlen, - outx8 + 6 * outlen, - outx8 + 7 * outlen, - inbufx8 + 0 * (inlen + 4), - inbufx8 + 1 * (inlen + 4), - inbufx8 + 2 * (inlen + 4), - inbufx8 + 3 * (inlen + 4), - inbufx8 + 4 * (inlen + 4), - inbufx8 + 5 * (inlen + 4), - inbufx8 + 6 * (inlen + 4), - inbufx8 + 7 * (inlen + 4), inlen + 4); - outx8 += PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_OUTPUT_BYTES; - } - /* Until we cannot anymore, and we fill the remainder. */ - for (j = 0; j < 8; j++) { - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_ull_to_bytes(inbufx8 + inlen + j * (inlen + 4), 4, i); - } - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_sha256x8(outbufx8 + 0 * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 1 * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 2 * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 3 * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 4 * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 5 * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 6 * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 7 * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_OUTPUT_BYTES, - inbufx8 + 0 * (inlen + 4), - inbufx8 + 1 * (inlen + 4), - inbufx8 + 2 * (inlen + 4), - inbufx8 + 3 * (inlen + 4), - inbufx8 + 4 * (inlen + 4), - inbufx8 + 5 * (inlen + 4), - inbufx8 + 6 * (inlen + 4), - inbufx8 + 7 * (inlen + 4), inlen + 4); - - for (j = 0; j < 8; j++) { - memcpy(outx8 + j * outlen, - outbufx8 + j * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_OUTPUT_BYTES, - outlen - i * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_OUTPUT_BYTES); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_avx2/sha256x8.h b/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_avx2/sha256x8.h deleted file mode 100644 index dd9e59094f..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_avx2/sha256x8.h +++ /dev/null @@ -1,44 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256X8_H -#define PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256X8_H - -#include "sha256avx.h" - -#define PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_BLOCK_BYTES 64 -#define PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_OUTPUT_BYTES 32 /* This does not necessarily equal PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N */ - -/* This provides a wrapper around the internals of 8x parallel SHA256 */ -void PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_sha256x8(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - const unsigned char *in4, - const unsigned char *in5, - const unsigned char *in6, - const unsigned char *in7, unsigned long long inlen); - -/** - * Note that inlen should be sufficiently small that it still allows for - * an array to be allocated on the stack. Typically 'in' is merely a seed. - * Outputs outlen number of bytes - */ -void PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_mgf1x8(unsigned char *outx8, unsigned long outlen, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - const unsigned char *in4, - const unsigned char *in5, - const unsigned char *in6, - const unsigned char *in7, - unsigned long inlen); - -void PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_seed_statex8(sha256ctxx8 *ctx, const unsigned char *pub_seed); -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_avx2/sign.c b/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_avx2/sign.c deleted file mode 100644 index e9472453a0..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_avx2/sign.c +++ /dev/null @@ -1,356 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "api.h" -#include "fors.h" -#include "hash.h" -#include "hash_state.h" -#include "params.h" -#include "randombytes.h" -#include "thash.h" -#include "utils.h" -#include "wots.h" - -/** - * Computes the leaf at a given address. First generates the WOTS key pair, - * then computes leaf by hashing horizontally. - */ -static void wots_gen_leaf(unsigned char *leaf, const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx, const uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - unsigned char pk[PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_WOTS_BYTES]; - uint32_t wots_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_set_type( - wots_addr, PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_set_type( - wots_pk_addr, PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_ADDR_TYPE_WOTSPK); - - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_set_keypair_addr( - wots_addr, addr_idx); - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_wots_gen_pk( - pk, sk_seed, pub_seed, wots_addr, hash_state_seeded); - - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_copy_keypair_addr( - wots_pk_addr, wots_addr); - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_thash_WOTS_LEN( - leaf, pk, pub_seed, wots_pk_addr, hash_state_seeded); -} - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_crypto_sign_secretkeybytes(void) { - return PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_CRYPTO_SECRETKEYBYTES; -} - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_crypto_sign_publickeybytes(void) { - return PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_CRYPTO_PUBLICKEYBYTES; -} - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_crypto_sign_bytes(void) { - return PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_CRYPTO_BYTES; -} - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_crypto_sign_seedbytes(void) { - return PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_CRYPTO_SEEDBYTES; -} - -/* - * Generates an SPX key pair given a seed of length - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed) { - /* We do not need the auth path in key generation, but it simplifies the - code to have just one treehash routine that computes both root and path - in one function. */ - unsigned char auth_path[PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_TREE_HEIGHT * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N]; - uint32_t top_tree_addr[8] = {0}; - hash_state hash_state_seeded; - - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_set_layer_addr( - top_tree_addr, PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_D - 1); - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_set_type( - top_tree_addr, PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_ADDR_TYPE_HASHTREE); - - /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ - memcpy(sk, seed, PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_CRYPTO_SEEDBYTES); - - memcpy(pk, sk + 2 * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N, PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_initialize_hash_function(&hash_state_seeded, pk, sk); - - /* Compute root node of the top-most subtree. */ - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_treehash_TREE_HEIGHT( - sk + 3 * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N, auth_path, sk, sk + 2 * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N, 0, 0, - wots_gen_leaf, top_tree_addr, &hash_state_seeded); - - memcpy(pk + PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N, sk + 3 * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N, PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N); - - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_destroy_hash_function(&hash_state_seeded); - return 0; -} - -/* - * Generates an SPX key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk) { - unsigned char seed[PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_CRYPTO_SEEDBYTES]; - randombytes(seed, PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_CRYPTO_SEEDBYTES); - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_crypto_sign_seed_keypair( - pk, sk, seed); - - return 0; -} - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - const unsigned char *sk_seed = sk; - const unsigned char *sk_prf = sk + PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N; - const unsigned char *pk = sk + 2 * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N; - const unsigned char *pub_seed = pk; - - unsigned char optrand[PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N]; - unsigned char mhash[PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_FORS_MSG_BYTES]; - unsigned char root[PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N]; - uint32_t i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - - hash_state hash_state_seeded; - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_initialize_hash_function( - &hash_state_seeded, - pub_seed, sk_seed); - - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_set_type( - wots_addr, PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_set_type( - tree_addr, PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_ADDR_TYPE_HASHTREE); - - /* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ - randombytes(optrand, PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N); - /* Compute the digest randomization value. */ - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_gen_message_random( - sig, sk_prf, optrand, m, mlen, &hash_state_seeded); - - /* Derive the message digest and leaf index from R, PK and M. */ - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N; - - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_set_keypair_addr( - wots_addr, idx_leaf); - - /* Sign the message hash using FORS. */ - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_fors_sign( - sig, root, mhash, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_FORS_BYTES; - - for (i = 0; i < PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_D; i++) { - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_set_tree_addr(tree_addr, tree); - - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_set_keypair_addr( - wots_addr, idx_leaf); - - /* Compute a WOTS signature. */ - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_wots_sign( - sig, root, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_WOTS_BYTES; - - /* Compute the authentication path for the used WOTS leaf. */ - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_treehash_TREE_HEIGHT( - root, sig, sk_seed, pub_seed, idx_leaf, 0, - wots_gen_leaf, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_TREE_HEIGHT * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_TREE_HEIGHT; - } - - *siglen = PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_BYTES; - - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_destroy_hash_function(&hash_state_seeded); - return 0; -} - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk) { - const unsigned char *pub_seed = pk; - const unsigned char *pub_root = pk + PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N; - unsigned char mhash[PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_FORS_MSG_BYTES]; - unsigned char wots_pk[PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_WOTS_BYTES]; - unsigned char root[PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N]; - unsigned char leaf[PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N]; - unsigned int i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - hash_state hash_state_seeded; - - if (siglen != PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_BYTES) { - return -1; - } - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_initialize_hash_function( - &hash_state_seeded, - pub_seed, NULL); - - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_set_type( - wots_addr, PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_set_type( - tree_addr, PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_ADDR_TYPE_HASHTREE); - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_set_type( - wots_pk_addr, PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_ADDR_TYPE_WOTSPK); - - /* Derive the message digest and leaf index from R || PK || M. */ - /* The additional PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N is a result of the hash domain separator. */ - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N; - - /* Layer correctly defaults to 0, so no need to set_layer_addr */ - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_set_keypair_addr( - wots_addr, idx_leaf); - - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_fors_pk_from_sig( - root, sig, mhash, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_FORS_BYTES; - - /* For each subtree.. */ - for (i = 0; i < PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_D; i++) { - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_set_tree_addr(tree_addr, tree); - - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_set_keypair_addr( - wots_addr, idx_leaf); - - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_copy_keypair_addr( - wots_pk_addr, wots_addr); - - /* The WOTS public key is only correct if the signature was correct. */ - /* Initially, root is the FORS pk, but on subsequent iterations it is - the root of the subtree below the currently processed subtree. */ - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_wots_pk_from_sig( - wots_pk, sig, root, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_WOTS_BYTES; - - /* Compute the leaf node using the WOTS public key. */ - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_thash_WOTS_LEN( - leaf, wots_pk, pub_seed, wots_pk_addr, &hash_state_seeded); - - /* Compute the root node of this subtree. */ - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_compute_root( - root, leaf, idx_leaf, 0, sig, PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_TREE_HEIGHT, - pub_seed, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_TREE_HEIGHT * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_TREE_HEIGHT; - } - - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_destroy_hash_function(&hash_state_seeded); - /* Check if the root node equals the root node in the public key. */ - if (memcmp(root, pub_root, PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N) != 0) { - return -1; - } - - return 0; -} - - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - size_t siglen; - - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_crypto_sign_signature( - sm, &siglen, m, mlen, sk); - - memmove(sm + PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_BYTES, m, mlen); - *smlen = siglen + mlen; - - return 0; -} - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk) { - /* The API caller does not necessarily know what size a signature should be - but SPHINCS+ signatures are always exactly PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_BYTES. */ - if (smlen < PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_BYTES) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - *mlen = smlen - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_BYTES; - - if (PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_crypto_sign_verify( - sm, PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_BYTES, sm + PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_BYTES, *mlen, pk)) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - /* If verification was successful, move the message to the right place. */ - memmove(m, sm + PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_BYTES, *mlen); - - return 0; -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_avx2/thash.h b/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_avx2/thash.h deleted file mode 100644 index 72406b66c2..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_avx2/thash.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_THASH_H -#define PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_THASH_H - -#include "hash_state.h" - -#include - -void PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_avx2/thash_sha256_robust.c b/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_avx2/thash_sha256_robust.c deleted file mode 100644 index b9af100eba..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_avx2/thash_sha256_robust.c +++ /dev/null @@ -1,78 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "thash.h" - -#include "sha2.h" -#include "sha256.h" - -/** - * Takes an array of inblocks concatenated arrays of PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N bytes. - */ -static void thash( - unsigned char *out, unsigned char *buf, - const unsigned char *in, unsigned int inblocks, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char outbuf[PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_OUTPUT_BYTES]; - unsigned char *bitmask = buf + PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_ADDR_BYTES + 4; - sha256ctx sha2_state; - unsigned int i; - - memcpy(buf, pub_seed, PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N); - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_compress_address(buf + PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N, addr); - /* MGF1 requires us to have 4 extra bytes in 'buf' */ - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_mgf1(bitmask, inblocks * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N, buf, PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_ADDR_BYTES); - - /* Retrieve precomputed state containing pub_seed */ - sha256_inc_ctx_clone(&sha2_state, &hash_state_seeded->x1); - - for (i = 0; i < inblocks * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N; i++) { - buf[PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_ADDR_BYTES + i] = in[i] ^ bitmask[i]; - } - - sha256_inc_finalize(outbuf, &sha2_state, buf + PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N, - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N); - memcpy(out, outbuf, PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N); -} - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_ADDR_BYTES + 4 + 1 * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N]; - thash(out, buf, in, 1, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_ADDR_BYTES + 4 + 2 * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N]; - thash(out, buf, in, 2, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_ADDR_BYTES + 4 + PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_WOTS_LEN * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N]; - thash(out, buf, in, PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_WOTS_LEN, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_ADDR_BYTES + 4 + PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_FORS_TREES * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N]; - thash(out, buf, in, PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_FORS_TREES, pub_seed, addr, hash_state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_avx2/thash_sha256_robustx8.c b/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_avx2/thash_sha256_robustx8.c deleted file mode 100644 index d3f45a50e9..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_avx2/thash_sha256_robustx8.c +++ /dev/null @@ -1,156 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "sha256.h" -#include "sha256avx.h" -#include "sha256x8.h" -#include "thashx8.h" -#include "utils.h" - -/** - * 8-way parallel version of thash; takes 8x as much input and output - */ -static void thashx8(uint8_t *out0, - uint8_t *out1, - uint8_t *out2, - uint8_t *out3, - uint8_t *out4, - uint8_t *out5, - uint8_t *out6, - uint8_t *out7, - const uint8_t *in0, - const uint8_t *in1, - const uint8_t *in2, - const uint8_t *in3, - const uint8_t *in4, - const uint8_t *in5, - const uint8_t *in6, - const uint8_t *in7, - unsigned int inblocks, - const uint8_t *pub_seed, - uint32_t addrx8[8 * 8], - uint8_t *bufx8, - uint8_t *bitmaskx8, - const hash_state *state_seeded) { - unsigned char outbufx8[8 * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_OUTPUT_BYTES]; - unsigned int i; - sha256ctxx8 ctx; - - (void)pub_seed; /* Suppress an 'unused parameter' warning. */ - - for (i = 0; i < 8; i++) { - memcpy(bufx8 + i * (PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N), - pub_seed, PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N); - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_compress_address(bufx8 + PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N + - i * (PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N), - addrx8 + i * 8); - } - - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_mgf1x8(bitmaskx8, inblocks * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N, - bufx8 + 0 * (PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N), - bufx8 + 1 * (PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N), - bufx8 + 2 * (PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N), - bufx8 + 3 * (PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N), - bufx8 + 4 * (PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N), - bufx8 + 5 * (PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N), - bufx8 + 6 * (PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N), - bufx8 + 7 * (PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N), - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_ADDR_BYTES - ); - - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_sha256_clone_statex8(&ctx, &state_seeded->x8); - - for (i = 0; i < inblocks * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N; i++) { - bufx8[PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_ADDR_BYTES + i + - 0 * (PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N)] = - in0[i] ^ bitmaskx8[i + 0 * (inblocks * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N)]; - bufx8[PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_ADDR_BYTES + i + - 1 * (PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N)] = - in1[i] ^ bitmaskx8[i + 1 * (inblocks * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N)]; - bufx8[PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_ADDR_BYTES + i + - 2 * (PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N)] = - in2[i] ^ bitmaskx8[i + 2 * (inblocks * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N)]; - bufx8[PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_ADDR_BYTES + i + - 3 * (PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N)] = - in3[i] ^ bitmaskx8[i + 3 * (inblocks * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N)]; - bufx8[PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_ADDR_BYTES + i + - 4 * (PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N)] = - in4[i] ^ bitmaskx8[i + 4 * (inblocks * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N)]; - bufx8[PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_ADDR_BYTES + i + - 5 * (PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N)] = - in5[i] ^ bitmaskx8[i + 5 * (inblocks * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N)]; - bufx8[PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_ADDR_BYTES + i + - 6 * (PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N)] = - in6[i] ^ bitmaskx8[i + 6 * (inblocks * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N)]; - bufx8[PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_ADDR_BYTES + i + - 7 * (PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N)] = - in7[i] ^ bitmaskx8[i + 7 * (inblocks * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N)]; - } - - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_sha256_update8x(&ctx, - bufx8 + PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N + 0 * (PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N), - bufx8 + PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N + 1 * (PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N), - bufx8 + PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N + 2 * (PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N), - bufx8 + PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N + 3 * (PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N), - bufx8 + PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N + 4 * (PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N), - bufx8 + PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N + 5 * (PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N), - bufx8 + PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N + 6 * (PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N), - bufx8 + PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N + 7 * (PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N), - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N); - - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_sha256_final8x(&ctx, - outbufx8 + 0 * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 1 * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 2 * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 3 * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 4 * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 5 * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 6 * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 7 * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_OUTPUT_BYTES); - - memcpy(out0, outbufx8 + 0 * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N); - memcpy(out1, outbufx8 + 1 * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N); - memcpy(out2, outbufx8 + 2 * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N); - memcpy(out3, outbufx8 + 3 * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N); - memcpy(out4, outbufx8 + 4 * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N); - memcpy(out5, outbufx8 + 5 * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N); - memcpy(out6, outbufx8 + 6 * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N); - memcpy(out7, outbufx8 + 7 * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N); -} - -#define thash_size_variant(name, size) \ - void PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_thashx8_##name(unsigned char *out0, \ - unsigned char *out1, \ - unsigned char *out2, \ - unsigned char *out3, \ - unsigned char *out4, \ - unsigned char *out5, \ - unsigned char *out6, \ - unsigned char *out7, \ - const unsigned char *in0, \ - const unsigned char *in1, \ - const unsigned char *in2, \ - const unsigned char *in3, \ - const unsigned char *in4, \ - const unsigned char *in5, \ - const unsigned char *in6, \ - const unsigned char *in7, \ - const unsigned char *pub_seed, \ - uint32_t addrx8[8*8], \ - const hash_state *state_seeded) { \ - const unsigned int inblocks = (size); \ - uint8_t bufx8[8*(PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_SHA256_ADDR_BYTES + (size)*PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N)]; \ - uint8_t bitmaskx8[8*((size) * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N)]; \ - thashx8(out0, out1, out2, out3, out4, out5, out6, out7, \ - in0, in1, in2, in3, in4, in5, in6, in7, inblocks, \ - pub_seed, addrx8, bufx8, bitmaskx8, state_seeded); \ - } - -thash_size_variant(1, 1) -thash_size_variant(2, 2) -thash_size_variant(WOTS_LEN, PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_WOTS_LEN) -thash_size_variant(FORS_TREES, PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_FORS_TREES) - -#undef thash_size_variant diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_avx2/thashx8.h b/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_avx2/thashx8.h deleted file mode 100644 index 4c4a1bc0a8..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_avx2/thashx8.h +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_THASHX8_H -#define PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_THASHX8_H - -#include - -#include "hash_state.h" -#include "sha256avx.h" - - -#define thashx8_variant(name) \ - void PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_thashx8_##name( \ - unsigned char *out0, \ - unsigned char *out1, \ - unsigned char *out2, \ - unsigned char *out3, \ - unsigned char *out4, \ - unsigned char *out5, \ - unsigned char *out6, \ - unsigned char *out7, \ - const unsigned char *in0, \ - const unsigned char *in1, \ - const unsigned char *in2, \ - const unsigned char *in3, \ - const unsigned char *in4, \ - const unsigned char *in5, \ - const unsigned char *in6, \ - const unsigned char *in7, \ - const unsigned char *pub_seed, \ - uint32_t addrx8[8*8], \ - const hash_state *state_seeded) - - -thashx8_variant(1); -thashx8_variant(2); -thashx8_variant(WOTS_LEN); -thashx8_variant(FORS_TREES); - -#undef thashx8_variant -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_avx2/utils.c b/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_avx2/utils.c deleted file mode 100644 index d2dd13b3ed..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_avx2/utils.c +++ /dev/null @@ -1,199 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "hash_state.h" -#include "params.h" -#include "thash.h" -#include "utils.h" - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in) { - - /* Iterate over out in decreasing order, for big-endianness. */ - for (size_t i = outlen; i > 0; i--) { - out[i - 1] = in & 0xff; - in = in >> 8; - } -} - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_bytes_to_ull( - const unsigned char *in, size_t inlen) { - unsigned long long retval = 0; - - for (size_t i = 0; i < inlen; i++) { - retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); - } - return retval; -} - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - uint32_t i; - unsigned char buffer[2 * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N]; - - /* If leaf_idx is odd (last bit = 1), current path element is a right child - and auth_path has to go left. Otherwise it is the other way around. */ - if (leaf_idx & 1) { - memcpy(buffer + PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N, leaf, PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N); - } else { - memcpy(buffer, leaf, PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N); - memcpy(buffer + PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N, auth_path, PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N); - } - auth_path += PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N; - - for (i = 0; i < tree_height - 1; i++) { - leaf_idx >>= 1; - idx_offset >>= 1; - /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_set_tree_height(addr, i + 1); - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_set_tree_index( - addr, leaf_idx + idx_offset); - - /* Pick the right or left neighbor, depending on parity of the node. */ - if (leaf_idx & 1) { - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_thash_2( - buffer + PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N); - } else { - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_thash_2( - buffer, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer + PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N, auth_path, PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N); - } - auth_path += PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N; - } - - /* The last iteration is exceptional; we do not copy an auth_path node. */ - leaf_idx >>= 1; - idx_offset >>= 1; - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_set_tree_height(addr, tree_height); - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_set_tree_index( - addr, leaf_idx + idx_offset); - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_thash_2( - root, buffer, pub_seed, addr, hash_state_seeded); -} - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -static void PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_treehash( - unsigned char *root, unsigned char *auth_path, - unsigned char *stack, unsigned int *heights, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - - unsigned int offset = 0; - uint32_t idx; - uint32_t tree_idx; - - for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { - /* Add the next leaf node to the stack. */ - gen_leaf(stack + offset * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N, - sk_seed, pub_seed, idx + idx_offset, tree_addr, - hash_state_seeded); - offset++; - heights[offset - 1] = 0; - - /* If this is a node we need for the auth path.. */ - if ((leaf_idx ^ 0x1) == idx) { - memcpy(auth_path, stack + (offset - 1)*PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N, PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N); - } - - /* While the top-most nodes are of equal height.. */ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { - /* Compute index of the new node, in the next layer. */ - tree_idx = (idx >> (heights[offset - 1] + 1)); - - /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_set_tree_height( - tree_addr, heights[offset - 1] + 1); - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_set_tree_index( - tree_addr, tree_idx + (idx_offset >> (heights[offset - 1] + 1))); - /* Hash the top-most nodes from the stack together. */ - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_thash_2( - stack + (offset - 2)*PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N, stack + (offset - 2)*PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N, - pub_seed, tree_addr, hash_state_seeded); - offset--; - /* Note that the top-most node is now one layer higher. */ - heights[offset - 1]++; - - /* If this is a node we need for the auth path.. */ - if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_path + heights[offset - 1]*PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N, - stack + (offset - 1)*PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N, PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N); - } - } - } - memcpy(root, stack, PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N); -} - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_FORS_HEIGHT + 1)*PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N]; - unsigned int heights[PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_FORS_HEIGHT + 1]; - - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_FORS_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_TREE_HEIGHT + 1)*PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N]; - unsigned int heights[PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_TREE_HEIGHT + 1]; - - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_TREE_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_avx2/utils.h b/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_avx2/utils.h deleted file mode 100644 index 367900dc4f..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_avx2/utils.h +++ /dev/null @@ -1,64 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_UTILS_H -#define PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_UTILS_H - -#include "hash_state.h" -#include "params.h" -#include -#include - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in); - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_bytes_to_ull( - const unsigned char *in, size_t inlen); - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -void PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_avx2/utilsx8.c b/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_avx2/utilsx8.c deleted file mode 100644 index 64bca5eb43..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_avx2/utilsx8.c +++ /dev/null @@ -1,172 +0,0 @@ -#include - -#include "address.h" -#include "params.h" -#include "thashx8.h" -#include "utils.h" - -#include "utilsx8.h" - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -static void treehashx8(unsigned char *rootx8, unsigned char *auth_pathx8, - unsigned char *stackx8, unsigned int *heights, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t leaf_idx[8], uint32_t idx_offset[8], - uint32_t tree_height, - void (*gen_leafx8)( - unsigned char * /* leaf0 */, - unsigned char * /* leaf1 */, - unsigned char * /* leaf2 */, - unsigned char * /* leaf3 */, - unsigned char * /* leaf4 */, - unsigned char * /* leaf5 */, - unsigned char * /* leaf6 */, - unsigned char * /* leaf7 */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx0 */, - uint32_t /* addr_idx1 */, - uint32_t /* addr_idx2 */, - uint32_t /* addr_idx3 */, - uint32_t /* addr_idx4 */, - uint32_t /* addr_idx5 */, - uint32_t /* addr_idx6 */, - uint32_t /* addr_idx7 */, - const uint32_t[8] /* tree_addr */, - const hash_state * /* state_seeded */), - uint32_t tree_addrx8[8 * 8], - const hash_state *state_seeded) { - unsigned int offset = 0; - uint32_t idx; - uint32_t tree_idx; - unsigned int j; - - for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { - /* Add the next leaf node to the stack. */ - gen_leafx8(stackx8 + 0 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N + offset * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N, - stackx8 + 1 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N + offset * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N, - stackx8 + 2 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N + offset * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N, - stackx8 + 3 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N + offset * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N, - stackx8 + 4 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N + offset * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N, - stackx8 + 5 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N + offset * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N, - stackx8 + 6 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N + offset * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N, - stackx8 + 7 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N + offset * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N, - sk_seed, pub_seed, - idx + idx_offset[0], - idx + idx_offset[1], - idx + idx_offset[2], - idx + idx_offset[3], - idx + idx_offset[4], - idx + idx_offset[5], - idx + idx_offset[6], - idx + idx_offset[7], - tree_addrx8, - state_seeded); - offset++; - heights[offset - 1] = 0; - - /* If this is a node we need for the auth path.. */ - for (j = 0; j < 8; j++) { - if ((leaf_idx[j] ^ 0x1) == idx) { - memcpy(auth_pathx8 + j * tree_height * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N, - stackx8 + j * (tree_height + 1)*PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N + (offset - 1)*PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N, PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N); - } - } - - /* While the top-most nodes are of equal height.. */ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { - /* Compute index of the new node, in the next layer. */ - tree_idx = (idx >> (heights[offset - 1] + 1)); - - /* Set the address of the node we're creating. */ - for (j = 0; j < 8; j++) { - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_set_tree_height(tree_addrx8 + j * 8, heights[offset - 1] + 1); - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_set_tree_index(tree_addrx8 + j * 8, - tree_idx + (idx_offset[j] >> (heights[offset - 1] + 1))); - } - /* Hash the top-most nodes from the stack together. */ - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_thashx8_2(stackx8 + 0 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N, - stackx8 + 1 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N, - stackx8 + 2 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N, - stackx8 + 3 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N, - stackx8 + 4 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N, - stackx8 + 5 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N, - stackx8 + 6 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N, - stackx8 + 7 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N, - stackx8 + 0 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N, - stackx8 + 1 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N, - stackx8 + 2 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N, - stackx8 + 3 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N, - stackx8 + 4 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N, - stackx8 + 5 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N, - stackx8 + 6 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N, - stackx8 + 7 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N, - pub_seed, tree_addrx8, state_seeded); - offset--; - /* Note that the top-most node is now one layer higher. */ - heights[offset - 1]++; - - /* If this is a node we need for the auth path.. */ - for (j = 0; j < 8; j++) { - if (((leaf_idx[j] >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_pathx8 + j * tree_height * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N + heights[offset - 1]*PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N, - stackx8 + j * (tree_height + 1)*PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N + (offset - 1)*PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N, PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N); - } - } - } - } - - for (j = 0; j < 8; j++) { - memcpy(rootx8 + j * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N, stackx8 + j * (tree_height + 1)*PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N, PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N); - } -} - -/* The wrappers below ensure we used fixed-size buffers on the stack (no VLAs) */ - - -#define treehashx8_variant(name, size) \ - void PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_treehashx8_##name( \ - unsigned char *rootx8, unsigned char *auth_pathx8, \ - const unsigned char *sk_seed, const unsigned char *pub_seed, \ - const uint32_t leaf_idx[8], uint32_t idx_offset[8], \ - void (*gen_leafx8)( \ - unsigned char* /* leaf0 */, \ - unsigned char* /* leaf1 */, \ - unsigned char* /* leaf2 */, \ - unsigned char* /* leaf3 */, \ - unsigned char* /* leaf4 */, \ - unsigned char* /* leaf5 */, \ - unsigned char* /* leaf6 */, \ - unsigned char* /* leaf7 */, \ - const unsigned char* /* sk_seed */, \ - const unsigned char* /* pub_seed */, \ - uint32_t /* addr_idx0 */, \ - uint32_t /* addr_idx1 */, \ - uint32_t /* addr_idx2 */, \ - uint32_t /* addr_idx3 */, \ - uint32_t /* addr_idx4 */, \ - uint32_t /* addr_idx5 */, \ - uint32_t /* addr_idx6 */, \ - uint32_t /* addr_idx7 */, \ - const uint32_t[8] /* tree_addr */, \ - const hash_state* /* state_seeded */), \ - uint32_t tree_addrx8[8*8], \ - const hash_state *state_seeded) \ - { \ - const uint32_t tree_height = (size); \ - unsigned char stackx8[8*((size) + 1)*PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N]; \ - unsigned int heights[(size) + 1]; \ - treehashx8(rootx8, auth_pathx8, stackx8, heights, sk_seed, pub_seed, \ - leaf_idx, idx_offset, tree_height, gen_leafx8, tree_addrx8, state_seeded); \ - } - -treehashx8_variant(FORS_HEIGHT, PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_FORS_HEIGHT) - -#undef treehashx8_variant diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_avx2/utilsx8.h b/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_avx2/utilsx8.h deleted file mode 100644 index a472def1f3..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_avx2/utilsx8.h +++ /dev/null @@ -1,46 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_UTILSX8_H -#define PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_UTILSX8_H - -#include - -#include "hash_state.h" -#include "params.h" - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ - -void PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_treehashx8_FORS_HEIGHT( - unsigned char *rootx8, unsigned char *auth_pathx8, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t leaf_idx[8], uint32_t idx_offset[8], - void (*gen_leafx8)( - unsigned char * /* leaf0 */, - unsigned char * /* leaf1 */, - unsigned char * /* leaf2 */, - unsigned char * /* leaf3 */, - unsigned char * /* leaf4 */, - unsigned char * /* leaf5 */, - unsigned char * /* leaf6 */, - unsigned char * /* leaf7 */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx0 */, - uint32_t /* addr_idx1 */, - uint32_t /* addr_idx2 */, - uint32_t /* addr_idx3 */, - uint32_t /* addr_idx4 */, - uint32_t /* addr_idx5 */, - uint32_t /* addr_idx6 */, - uint32_t /* addr_idx7 */, - const uint32_t[8] /* tree_addr */, - const hash_state * /* state_seeded */), - uint32_t tree_addrx8[8 * 8], - const hash_state *state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_avx2/wots.c b/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_avx2/wots.c deleted file mode 100644 index 6f21fca86b..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_avx2/wots.c +++ /dev/null @@ -1,240 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "hash_state.h" -#include "hashx8.h" -#include "params.h" -#include "thash.h" -#include "thashx8.h" -#include "utils.h" -#include "wots.h" - -// TODO clarify address expectations, and make them more uniform. -// TODO i.e. do we expect types to be set already? -// TODO and do we expect modifications or copies? - -/** - * Computes the starting value for a chain, i.e. the secret key. - * Expects the address to be complete up to the chain address. - */ -static void wots_gen_sk(unsigned char *sk, const unsigned char *sk_seed, - uint32_t wots_addr[8], const hash_state *state_seeded) { - /* Make sure that the hash address is actually zeroed. */ - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_set_hash_addr(wots_addr, 0); - - /* Generate sk element. */ - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_prf_addr(sk, sk_seed, wots_addr, state_seeded); -} - -/** - * 8-way parallel version of wots_gen_sk; expects 8x as much space in sk - */ -static void wots_gen_skx8(unsigned char *skx8, const unsigned char *sk_seed, - uint32_t wots_addrx8[8 * 8]) { - unsigned int j; - - /* Make sure that the hash address is actually zeroed. */ - for (j = 0; j < 8; j++) { - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_set_hash_addr(wots_addrx8 + j * 8, 0); - } - - /* Generate sk element. */ - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_prf_addrx8(skx8 + 0 * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N, - skx8 + 1 * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N, - skx8 + 2 * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N, - skx8 + 3 * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N, - skx8 + 4 * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N, - skx8 + 5 * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N, - skx8 + 6 * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N, - skx8 + 7 * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N, - sk_seed, wots_addrx8); -} - -/** - * Computes the chaining function. - * out and in have to be n-byte arrays. - * - * Interprets in as start-th value of the chain. - * addr has to contain the address of the chain. - */ -static void gen_chain(unsigned char *out, const unsigned char *in, - unsigned int start, unsigned int steps, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *state_seeded) { - uint32_t i; - - /* Initialize out with the value at position 'start'. */ - memcpy(out, in, PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N); - - /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_WOTS_W; i++) { - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_set_hash_addr(addr, i); - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_thash_1(out, out, pub_seed, addr, state_seeded); - } -} - -/** - * 8-way parallel version of gen_chain; expects 8x as much space in out, and - * 8x as much space in inx8. Assumes start and step identical across chains. - */ -static void gen_chainx8(unsigned char *outx8, const unsigned char *inx8, - unsigned int start, unsigned int steps, - const unsigned char *pub_seed, uint32_t addrx8[8 * 8], - const hash_state *state_seeded) { - uint32_t i; - unsigned int j; - - /* Initialize outx8 with the value at position 'start'. */ - memcpy(outx8, inx8, 8 * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N); - - /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_WOTS_W; i++) { - for (j = 0; j < 8; j++) { - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_set_hash_addr(addrx8 + j * 8, i); - } - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_thashx8_1(outx8 + 0 * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N, - outx8 + 1 * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N, - outx8 + 2 * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N, - outx8 + 3 * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N, - outx8 + 4 * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N, - outx8 + 5 * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N, - outx8 + 6 * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N, - outx8 + 7 * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N, - outx8 + 0 * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N, - outx8 + 1 * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N, - outx8 + 2 * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N, - outx8 + 3 * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N, - outx8 + 4 * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N, - outx8 + 5 * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N, - outx8 + 6 * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N, - outx8 + 7 * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N, - pub_seed, addrx8, state_seeded); - } -} - -/** - * base_w algorithm as described in draft. - * Interprets an array of bytes as integers in base w. - * This only works when log_w is a divisor of 8. - */ -static void base_w(unsigned int *output, const int out_len, const unsigned char *input) { - int in = 0; - int out = 0; - unsigned char total = 0; - int bits = 0; - int consumed; - - for (consumed = 0; consumed < out_len; consumed++) { - if (bits == 0) { - total = input[in]; - in++; - bits += 8; - } - bits -= PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_WOTS_LOGW; - output[out] = (unsigned int)(total >> bits) & (PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_WOTS_W - 1); - out++; - } -} - -/* Computes the WOTS+ checksum over a message (in base_w). */ -static void wots_checksum(unsigned int *csum_base_w, const unsigned int *msg_base_w) { - unsigned int csum = 0; - unsigned char csum_bytes[(PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_WOTS_LEN2 * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_WOTS_LOGW + 7) / 8]; - unsigned int i; - - /* Compute checksum. */ - for (i = 0; i < PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_WOTS_LEN1; i++) { - csum += PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_WOTS_W - 1 - msg_base_w[i]; - } - - /* Convert checksum to base_w. */ - /* Make sure expected empty zero bits are the least significant bits. */ - csum = csum << (8 - ((PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_WOTS_LEN2 * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_WOTS_LOGW) % 8)); - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); - base_w(csum_base_w, PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_WOTS_LEN2, csum_bytes); -} - -/* Takes a message and derives the matching chain lengths. */ -static void chain_lengths(unsigned int *lengths, const unsigned char *msg) { - base_w(lengths, PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_WOTS_LEN1, msg); - wots_checksum(lengths + PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_WOTS_LEN1, lengths); -} - -/** - * WOTS key generation. Takes a 32 byte sk_seed, expands it to WOTS private key - * elements and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_wots_gen_pk(unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *state_seeded) { - uint32_t i; - unsigned int j; - - uint32_t addrx8[8 * 8]; - unsigned char pkbuf[8 * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N]; - - for (j = 0; j < 8; j++) { - memcpy(addrx8 + j * 8, addr, sizeof(uint32_t) * 8); - } - - /* The last iteration typically does not have complete set of 4 chains, - but because we use pkbuf, this is not an issue -- we still do as many - in parallel as possible. */ - for (i = 0; i < ((PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_WOTS_LEN + 7) & ~0x7); i += 8) { - for (j = 0; j < 8; j++) { - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_set_chain_addr(addrx8 + j * 8, i + j); - } - wots_gen_skx8(pkbuf, sk_seed, addrx8); - gen_chainx8(pkbuf, pkbuf, 0, PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_WOTS_W - 1, pub_seed, addrx8, state_seeded); - for (j = 0; j < 8; j++) { - if (i + j < PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_WOTS_LEN) { - memcpy(pk + (i + j)*PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N, pkbuf + j * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N, PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N); - } - } - } -} - -/** - * Takes a n-byte message and the 32-byte sk_see to compute a signature 'sig'. - */ -void PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_wots_sign(unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_WOTS_LEN; i++) { - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_set_chain_addr(addr, i); - wots_gen_sk(sig + i * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N, sk_seed, addr, state_seeded); - gen_chain(sig + i * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N, sig + i * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N, 0, lengths[i], pub_seed, addr, state_seeded); - } -} - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_WOTS_LEN; i++) { - PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_set_chain_addr(addr, i); - gen_chain(pk + i * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N, sig + i * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N, - lengths[i], PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_WOTS_W - 1 - lengths[i], pub_seed, addr, state_seeded); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_avx2/wots.h b/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_avx2/wots.h deleted file mode 100644 index ddc0b90a51..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_avx2/wots.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_WOTS_H -#define PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_WOTS_H - -#include "hash_state.h" -#include "params.h" -#include - -/** - * WOTS key generation. Takes a 32 byte seed for the private key, expands it to - * a full WOTS private key and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_wots_gen_pk( - unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -/** - * Takes a n-byte message and the 32-byte seed for the private key to compute a - * signature that is placed at 'sig'. - */ -void PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_wots_sign( - unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *hash_state_seeded); - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_wots_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_clean/LICENSE b/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_clean/LICENSE deleted file mode 100644 index 670154e353..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_clean/LICENSE +++ /dev/null @@ -1,116 +0,0 @@ -CC0 1.0 Universal - -Statement of Purpose - -The laws of most jurisdictions throughout the world automatically confer -exclusive Copyright and Related Rights (defined below) upon the creator and -subsequent owner(s) (each and all, an "owner") of an original work of -authorship and/or a database (each, a "Work"). - -Certain owners wish to permanently relinquish those rights to a Work for the -purpose of contributing to a commons of creative, cultural and scientific -works ("Commons") that the public can reliably and without fear of later -claims of infringement build upon, modify, incorporate in other works, reuse -and redistribute as freely as possible in any form whatsoever and for any -purposes, including without limitation commercial purposes. These owners may -contribute to the Commons to promote the ideal of a free culture and the -further production of creative, cultural and scientific works, or to gain -reputation or greater distribution for their Work in part through the use and -efforts of others. - -For these and/or other purposes and motivations, and without any expectation -of additional consideration or compensation, the person associating CC0 with a -Work (the "Affirmer"), to the extent that he or she is an owner of Copyright -and Related Rights in the Work, voluntarily elects to apply CC0 to the Work -and publicly distribute the Work under its terms, with knowledge of his or her -Copyright and Related Rights in the Work and the meaning and intended legal -effect of CC0 on those rights. - -1. Copyright and Related Rights. A Work made available under CC0 may be -protected by copyright and related or neighboring rights ("Copyright and -Related Rights"). Copyright and Related Rights include, but are not limited -to, the following: - - i. the right to reproduce, adapt, distribute, perform, display, communicate, - and translate a Work; - - ii. moral rights retained by the original author(s) and/or performer(s); - - iii. publicity and privacy rights pertaining to a person's image or likeness - depicted in a Work; - - iv. rights protecting against unfair competition in regards to a Work, - subject to the limitations in paragraph 4(a), below; - - v. rights protecting the extraction, dissemination, use and reuse of data in - a Work; - - vi. database rights (such as those arising under Directive 96/9/EC of the - European Parliament and of the Council of 11 March 1996 on the legal - protection of databases, and under any national implementation thereof, - including any amended or successor version of such directive); and - - vii. other similar, equivalent or corresponding rights throughout the world - based on applicable law or treaty, and any national implementations thereof. - -2. Waiver. To the greatest extent permitted by, but not in contravention of, -applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and -unconditionally waives, abandons, and surrenders all of Affirmer's Copyright -and Related Rights and associated claims and causes of action, whether now -known or unknown (including existing as well as future claims and causes of -action), in the Work (i) in all territories worldwide, (ii) for the maximum -duration provided by applicable law or treaty (including future time -extensions), (iii) in any current or future medium and for any number of -copies, and (iv) for any purpose whatsoever, including without limitation -commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes -the Waiver for the benefit of each member of the public at large and to the -detriment of Affirmer's heirs and successors, fully intending that such Waiver -shall not be subject to revocation, rescission, cancellation, termination, or -any other legal or equitable action to disrupt the quiet enjoyment of the Work -by the public as contemplated by Affirmer's express Statement of Purpose. - -3. Public License Fallback. Should any part of the Waiver for any reason be -judged legally invalid or ineffective under applicable law, then the Waiver -shall be preserved to the maximum extent permitted taking into account -Affirmer's express Statement of Purpose. In addition, to the extent the Waiver -is so judged Affirmer hereby grants to each affected person a royalty-free, -non transferable, non sublicensable, non exclusive, irrevocable and -unconditional license to exercise Affirmer's Copyright and Related Rights in -the Work (i) in all territories worldwide, (ii) for the maximum duration -provided by applicable law or treaty (including future time extensions), (iii) -in any current or future medium and for any number of copies, and (iv) for any -purpose whatsoever, including without limitation commercial, advertising or -promotional purposes (the "License"). The License shall be deemed effective as -of the date CC0 was applied by Affirmer to the Work. Should any part of the -License for any reason be judged legally invalid or ineffective under -applicable law, such partial invalidity or ineffectiveness shall not -invalidate the remainder of the License, and in such case Affirmer hereby -affirms that he or she will not (i) exercise any of his or her remaining -Copyright and Related Rights in the Work or (ii) assert any associated claims -and causes of action with respect to the Work, in either case contrary to -Affirmer's express Statement of Purpose. - -4. Limitations and Disclaimers. - - a. No trademark or patent rights held by Affirmer are waived, abandoned, - surrendered, licensed or otherwise affected by this document. - - b. Affirmer offers the Work as-is and makes no representations or warranties - of any kind concerning the Work, express, implied, statutory or otherwise, - including without limitation warranties of title, merchantability, fitness - for a particular purpose, non infringement, or the absence of latent or - other defects, accuracy, or the present or absence of errors, whether or not - discoverable, all to the greatest extent permissible under applicable law. - - c. Affirmer disclaims responsibility for clearing rights of other persons - that may apply to the Work or any use thereof, including without limitation - any person's Copyright and Related Rights in the Work. Further, Affirmer - disclaims responsibility for obtaining any necessary consents, permissions - or other rights required for any use of the Work. - - d. Affirmer understands and acknowledges that Creative Commons is not a - party to this document and has no duty or obligation with respect to this - CC0 or use of the Work. - -For more information, please see - diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_clean/address.c b/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_clean/address.c deleted file mode 100644 index 5b946b7566..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_clean/address.c +++ /dev/null @@ -1,78 +0,0 @@ -#include - -#include "address.h" -#include "params.h" -#include "utils.h" - -void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]) { - int i; - - for (i = 0; i < 8; i++) { - PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_ull_to_bytes( - bytes + i * 4, 4, addr[i]); - } -} - -void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_set_layer_addr( - uint32_t addr[8], uint32_t layer) { - addr[0] = layer; -} - -void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_set_tree_addr( - uint32_t addr[8], uint64_t tree) { - addr[1] = 0; - addr[2] = (uint32_t) (tree >> 32); - addr[3] = (uint32_t) tree; -} - -void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_set_type( - uint32_t addr[8], uint32_t type) { - addr[4] = type; -} - -void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; -} - -/* These functions are used for OTS addresses. */ - -void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_set_keypair_addr( - uint32_t addr[8], uint32_t keypair) { - addr[5] = keypair; -} - -void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; - out[5] = in[5]; -} - -void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_set_chain_addr( - uint32_t addr[8], uint32_t chain) { - addr[6] = chain; -} - -void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_set_hash_addr( - uint32_t addr[8], uint32_t hash) { - addr[7] = hash; -} - -/* These functions are used for all hash tree addresses (including FORS). */ - -void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_set_tree_height( - uint32_t addr[8], uint32_t tree_height) { - addr[6] = tree_height; -} - -void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_set_tree_index( - uint32_t addr[8], uint32_t tree_index) { - addr[7] = tree_index; -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_clean/address.h b/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_clean/address.h deleted file mode 100644 index ae9a7ea8aa..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_clean/address.h +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_ADDRESS_H -#define PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_ADDRESS_H - -#include - -#define PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_ADDR_TYPE_WOTS 0 -#define PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_ADDR_TYPE_WOTSPK 1 -#define PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_ADDR_TYPE_HASHTREE 2 -#define PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_ADDR_TYPE_FORSTREE 3 -#define PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_ADDR_TYPE_FORSPK 4 - -void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]); - -void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_set_layer_addr( - uint32_t addr[8], uint32_t layer); - -void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_set_tree_addr( - uint32_t addr[8], uint64_t tree); - -void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_set_type( - uint32_t addr[8], uint32_t type); - -/* Copies the layer and tree part of one address into the other */ -void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for WOTS and FORS addresses. */ - -void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_set_keypair_addr( - uint32_t addr[8], uint32_t keypair); - -void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_set_chain_addr( - uint32_t addr[8], uint32_t chain); - -void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_set_hash_addr( - uint32_t addr[8], uint32_t hash); - -void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for all hash tree addresses (including FORS). */ - -void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_set_tree_height( - uint32_t addr[8], uint32_t tree_height); - -void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_set_tree_index( - uint32_t addr[8], uint32_t tree_index); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_clean/api.h b/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_clean/api.h deleted file mode 100644 index 129c42b73f..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_clean/api.h +++ /dev/null @@ -1,81 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_API_H -#define PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_API_H - -#include -#include - - - -#define PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_CRYPTO_ALGNAME "SPHINCS+" - -#define PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_CRYPTO_SECRETKEYBYTES 64 -#define PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_CRYPTO_PUBLICKEYBYTES 32 -#define PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_CRYPTO_BYTES 7856 -#define PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_CRYPTO_SEEDBYTES 48 - - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_clean/fors.c b/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_clean/fors.c deleted file mode 100644 index b6490e2e58..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_clean/fors.c +++ /dev/null @@ -1,161 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "fors.h" -#include "hash.h" -#include "hash_state.h" -#include "thash.h" -#include "utils.h" - -static void fors_gen_sk(unsigned char *sk, const unsigned char *sk_seed, - uint32_t fors_leaf_addr[8], const hash_state *hash_state_seeded) { - PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_prf_addr( - sk, sk_seed, fors_leaf_addr, hash_state_seeded); -} - -static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, - const unsigned char *pub_seed, - uint32_t fors_leaf_addr[8], - const hash_state *hash_state_seeded) { - PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_thash_1( - leaf, sk, pub_seed, fors_leaf_addr, hash_state_seeded); -} - -static void fors_gen_leaf(unsigned char *leaf, const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx, const uint32_t fors_tree_addr[8], - const hash_state *hash_state_seeded) { - uint32_t fors_leaf_addr[8] = {0}; - - /* Only copy the parts that must be kept in fors_leaf_addr. */ - PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_copy_keypair_addr( - fors_leaf_addr, fors_tree_addr); - PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_set_type( - fors_leaf_addr, PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_set_tree_index( - fors_leaf_addr, addr_idx); - - fors_gen_sk(leaf, sk_seed, fors_leaf_addr, hash_state_seeded); - fors_sk_to_leaf(leaf, leaf, pub_seed, fors_leaf_addr, hash_state_seeded); -} - -/** - * Interprets m as PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_FORS_HEIGHT-bit unsigned integers. - * Assumes m contains at least PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_FORS_TREES bits. - * Assumes indices has space for PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_FORS_TREES integers. - */ -static void message_to_indices(uint32_t *indices, const unsigned char *m) { - unsigned int i, j; - unsigned int offset = 0; - - for (i = 0; i < PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_FORS_TREES; i++) { - indices[i] = 0; - for (j = 0; j < PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_FORS_HEIGHT; j++) { - indices[i] ^= (((uint32_t)m[offset >> 3] >> (offset & 0x7)) & 0x1) << j; - offset++; - } - } -} - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_fors_sign( - unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *hash_state_seeded) { - uint32_t indices[PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_FORS_TREES]; - unsigned char roots[PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_FORS_TREES * PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_N]; - uint32_t fors_tree_addr[8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_copy_keypair_addr( - fors_tree_addr, fors_addr); - PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_copy_keypair_addr( - fors_pk_addr, fors_addr); - - PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_set_type( - fors_tree_addr, PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_set_type( - fors_pk_addr, PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_FORS_TREES; i++) { - idx_offset = i * (1 << PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_FORS_HEIGHT); - - PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_set_tree_height( - fors_tree_addr, 0); - PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_set_tree_index( - fors_tree_addr, indices[i] + idx_offset); - - /* Include the secret key part that produces the selected leaf node. */ - fors_gen_sk(sig, sk_seed, fors_tree_addr, hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_N; - - /* Compute the authentication path for this leaf node. */ - PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_treehash_FORS_HEIGHT( - roots + i * PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_N, sig, sk_seed, pub_seed, - indices[i], idx_offset, fors_gen_leaf, fors_tree_addr, - hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_N * PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_thash_FORS_TREES( - pk, roots, pub_seed, fors_pk_addr, hash_state_seeded); -} - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_fors_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, const uint32_t fors_addr[8], - const hash_state *hash_state_seeded) { - uint32_t indices[PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_FORS_TREES]; - unsigned char roots[PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_FORS_TREES * PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_N]; - unsigned char leaf[PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_N]; - uint32_t fors_tree_addr[8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_copy_keypair_addr(fors_tree_addr, fors_addr); - PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_copy_keypair_addr(fors_pk_addr, fors_addr); - - PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_set_type(fors_tree_addr, PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_set_type(fors_pk_addr, PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_FORS_TREES; i++) { - idx_offset = i * (1 << PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_FORS_HEIGHT); - - PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_set_tree_height(fors_tree_addr, 0); - PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Derive the leaf from the included secret key part. */ - fors_sk_to_leaf(leaf, sig, pub_seed, fors_tree_addr, hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_N; - - /* Derive the corresponding root node of this tree. */ - PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_compute_root(roots + i * PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_N, leaf, indices[i], idx_offset, sig, - PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_FORS_HEIGHT, pub_seed, fors_tree_addr, hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_N * PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_thash_FORS_TREES(pk, roots, pub_seed, fors_pk_addr, hash_state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_clean/fors.h b/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_clean/fors.h deleted file mode 100644 index c726541b53..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_clean/fors.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_FORS_H -#define PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_FORS_H - -#include - -#include "hash_state.h" -#include "params.h" - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_fors_sign( - unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *hash_state_seeded); - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_fors_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, const uint32_t fors_addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_clean/hash.h b/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_clean/hash.h deleted file mode 100644 index 5aefd667c8..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_clean/hash.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_HASH_H -#define PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_HASH_H - -#include "hash_state.h" - -#include -#include - -void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_initialize_hash_function( - hash_state *hash_state_seeded, - const unsigned char *pub_seed, const unsigned char *sk_seed); - -void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_destroy_hash_function(hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_clean/hash_sha256.c b/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_clean/hash_sha256.c deleted file mode 100644 index 744670a878..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_clean/hash_sha256.c +++ /dev/null @@ -1,162 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "utils.h" - -#include "sha2.h" -#include "sha256.h" - -/* For SHA256, there is no immediate reason to initialize at the start, - so this function is an empty operation. */ -void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_initialize_hash_function( - hash_state *hash_state_seeded, - const unsigned char *pub_seed, const unsigned char *sk_seed) { - PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_seed_state(hash_state_seeded, pub_seed); - (void)sk_seed; /* Suppress an 'unused parameter' warning. */ -} - -/* Clean up hash state */ -void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_destroy_hash_function(hash_state *hash_state_seeded) { - sha256_inc_ctx_release(hash_state_seeded); -} - -/* - * Computes PRF(key, addr), given a secret key of PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_N bytes and an address - */ -void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded) { - unsigned char buf[PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_N + PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_SHA256_ADDR_BYTES]; - unsigned char outbuf[PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_SHA256_OUTPUT_BYTES]; - - memcpy(buf, key, PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_N); - PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_compress_address(buf + PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_N, addr); - - sha256(outbuf, buf, PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_N + PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_SHA256_ADDR_BYTES); - memcpy(out, outbuf, PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_N); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} - -/** - * Computes the message-dependent randomness R, using a secret seed as a key - * for HMAC, and an optional randomization value prefixed to the message. - * This requires m to have at least PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_SHA256_BLOCK_BYTES + PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_N space - * available in front of the pointer, i.e. before the message to use for the - * prefix. This is necessary to prevent having to move the message around (and - * allocate memory for it). - */ -void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, const hash_state *hash_state_seeded) { - unsigned char buf[PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_SHA256_BLOCK_BYTES + PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_SHA256_OUTPUT_BYTES]; - sha256ctx state; - int i; - - /* This implements HMAC-SHA256 */ - for (i = 0; i < PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_N; i++) { - buf[i] = 0x36 ^ sk_prf[i]; - } - memset(buf + PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_N, 0x36, PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_N); - - sha256_inc_init(&state); - sha256_inc_blocks(&state, buf, 1); - - memcpy(buf, optrand, PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_N); - - /* If optrand + message cannot fill up an entire block */ - if (PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_N + mlen < PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_SHA256_BLOCK_BYTES) { - memcpy(buf + PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_N, m, mlen); - sha256_inc_finalize(buf + PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_SHA256_BLOCK_BYTES, &state, - buf, mlen + PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_N); - } - /* Otherwise first fill a block, so that finalize only uses the message */ - else { - memcpy(buf + PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_N, m, PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_N); - sha256_inc_blocks(&state, buf, 1); - - m += PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_N; - mlen -= PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_N; - sha256_inc_finalize(buf + PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_SHA256_BLOCK_BYTES, &state, m, mlen); - } - - for (i = 0; i < PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_N; i++) { - buf[i] = 0x5c ^ sk_prf[i]; - } - memset(buf + PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_N, 0x5c, PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_N); - - sha256(buf, buf, PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_SHA256_BLOCK_BYTES + PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_SHA256_OUTPUT_BYTES); - memcpy(R, buf, PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_N); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} - -/** - * Computes the message hash using R, the public key, and the message. - * Outputs the message digest and the index of the leaf. The index is split in - * the tree index and the leaf index, for convenient copying to an address. - */ -void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded) { -#define PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_TREE_BITS (PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_TREE_HEIGHT * (PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_D - 1)) -#define PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_TREE_BYTES ((PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_TREE_BITS + 7) / 8) -#define PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_LEAF_BITS PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_TREE_HEIGHT -#define PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_LEAF_BYTES ((PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_LEAF_BITS + 7) / 8) -#define PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_DGST_BYTES (PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_FORS_MSG_BYTES + PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_TREE_BYTES + PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_LEAF_BYTES) - - unsigned char seed[PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_SHA256_OUTPUT_BYTES + 4]; - - /* Round to nearest multiple of PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_SHA256_BLOCK_BYTES */ -#define PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_INBLOCKS (((PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_N + PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_PK_BYTES + PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_SHA256_BLOCK_BYTES - 1) & \ - -PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_SHA256_BLOCK_BYTES) / PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_SHA256_BLOCK_BYTES) - unsigned char inbuf[PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_INBLOCKS * PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_SHA256_BLOCK_BYTES]; - - unsigned char buf[PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_DGST_BYTES]; - unsigned char *bufp = buf; - sha256ctx state; - - sha256_inc_init(&state); - - memcpy(inbuf, R, PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_N); - memcpy(inbuf + PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_N, pk, PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_PK_BYTES); - - /* If R + pk + message cannot fill up an entire block */ - if (PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_N + PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_PK_BYTES + mlen < PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_INBLOCKS * PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_SHA256_BLOCK_BYTES) { - memcpy(inbuf + PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_N + PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_PK_BYTES, m, mlen); - sha256_inc_finalize(seed, &state, inbuf, PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_N + PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_PK_BYTES + mlen); - } - /* Otherwise first fill a block, so that finalize only uses the message */ - else { - memcpy(inbuf + PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_N + PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_PK_BYTES, m, - PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_INBLOCKS * PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_N - PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_PK_BYTES); - sha256_inc_blocks(&state, inbuf, PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_INBLOCKS); - - m += PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_INBLOCKS * PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_N - PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_PK_BYTES; - mlen -= PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_INBLOCKS * PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_N - PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_PK_BYTES; - sha256_inc_finalize(seed, &state, m, mlen); - } - - /* By doing this in two steps, we prevent hashing the message twice; - otherwise each iteration in MGF1 would hash the message again. */ - PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_mgf1(bufp, PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_DGST_BYTES, seed, PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_SHA256_OUTPUT_BYTES); - - memcpy(digest, bufp, PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_FORS_MSG_BYTES); - bufp += PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_FORS_MSG_BYTES; - - *tree = PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_bytes_to_ull(bufp, PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_TREE_BYTES); - *tree &= (~(uint64_t)0) >> (64 - PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_TREE_BITS); - bufp += PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_TREE_BYTES; - - *leaf_idx = (uint32_t)PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_bytes_to_ull( - bufp, PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_LEAF_BYTES); - *leaf_idx &= (~(uint32_t)0) >> (32 - PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_LEAF_BITS); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_clean/hash_state.h b/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_clean/hash_state.h deleted file mode 100644 index 19fc335e27..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_clean/hash_state.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef SPX_HASH_STATE_H -#define SPX_HASH_STATE_H - -/** - * Defines the type of the hash function state. - * - * Don't be fooled into thinking this instance of SPHINCS+ isn't stateless! - * - * From Section 7.2.2 from the SPHINCS+ round-2 specification: - * - * Each of the instances of the tweakable hash function take PK.seed as its - * first input, which is constant for a given key pair – and, thus, across - * a single signature. This leads to a lot of redundant computation. To remedy - * this, we pad PK.seed to the length of a full 64-byte SHA-256 input block. - * Because of the Merkle-DamgÃ¥rd construction that underlies SHA-256, this - * allows for reuse of the intermediate SHA-256 state after the initial call to - * the compression function which improves performance. - * - * We pass this hash state around in functions, because otherwise we need to - * have a global variable. - */ - -#include "sha2.h" -#define hash_state sha256ctx - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_clean/params.h b/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_clean/params.h deleted file mode 100644 index 27c7c8f352..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_clean/params.h +++ /dev/null @@ -1,53 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_PARAMS_H -#define PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_PARAMS_H - -/* Hash output length in bytes. */ -#define PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_N 16 -/* Height of the hypertree. */ -#define PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_FULL_HEIGHT 63 -/* Number of subtree layer. */ -#define PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_D 7 -/* FORS tree dimensions. */ -#define PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_FORS_HEIGHT 12 -#define PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_FORS_TREES 14 -/* Winternitz parameter, */ -#define PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_WOTS_W 16 - -/* The hash function is defined by linking a different hash.c file, as opposed - to setting a #define constant. */ - -/* For clarity */ -#define PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_ADDR_BYTES 32 - -/* WOTS parameters. */ -#define PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_WOTS_LOGW 4 - -#define PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_WOTS_LEN1 (8 * PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_N / PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_WOTS_LOGW) - -/* PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#define PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_WOTS_LEN2 3 - -#define PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_WOTS_LEN (PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_WOTS_LEN1 + PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_WOTS_LEN2) -#define PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_WOTS_BYTES (PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_WOTS_LEN * PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_N) -#define PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_WOTS_PK_BYTES PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_WOTS_BYTES - -/* Subtree size. */ -#define PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_TREE_HEIGHT (PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_FULL_HEIGHT / PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_D) - -/* FORS parameters. */ -#define PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_FORS_MSG_BYTES ((PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_FORS_TREES + 7) / 8) -#define PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_FORS_BYTES ((PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_FORS_HEIGHT + 1) * PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_FORS_TREES * PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_N) -#define PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_FORS_PK_BYTES PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_N - -/* Resulting SPX sizes. */ -#define PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_BYTES (PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_N + PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_FORS_BYTES + PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_D * PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_WOTS_BYTES +\ - PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_FULL_HEIGHT * PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_N) -#define PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_PK_BYTES (2 * PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_N) -#define PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_SK_BYTES (2 * PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_N + PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_PK_BYTES) - -/* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ -#define PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_OPTRAND_BYTES 32 - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_clean/sha256.c b/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_clean/sha256.c deleted file mode 100644 index 5e49d372f8..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_clean/sha256.c +++ /dev/null @@ -1,71 +0,0 @@ -/* Based on the public domain implementation in - * crypto_hash/sha512/ref/ from http://bench.cr.yp.to/supercop.html - * by D. J. Bernstein */ - -#include -#include -#include - -#include "sha2.h" -#include "sha256.h" -#include "utils.h" - -/* - * Compresses an address to a 22-byte sequence. - * This reduces the number of required SHA256 compression calls, as the last - * block of input is padded with at least 65 bits. - */ -void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_compress_address(unsigned char *out, const uint32_t addr[8]) { - PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_ull_to_bytes(out, 1, addr[0]); /* drop 3 bytes of the layer field */ - PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_ull_to_bytes(out + 1, 4, addr[2]); /* drop the highest tree address word */ - PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_ull_to_bytes(out + 5, 4, addr[3]); - PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_ull_to_bytes(out + 9, 1, addr[4]); /* drop 3 bytes of the type field */ - PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_ull_to_bytes(out + 10, 4, addr[5]); - PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_ull_to_bytes(out + 14, 4, addr[6]); - PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_ull_to_bytes(out + 18, 4, addr[7]); -} - -/** - * Requires 'input_plus_four_bytes' to have 'inlen' + 4 bytes, so that the last - * four bytes can be used for the counter. Typically 'input' is merely a seed. - * Outputs outlen number of bytes - */ -void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_mgf1( - unsigned char *out, unsigned long outlen, - unsigned char *input_plus_four_bytes, unsigned long inlen) { - unsigned char outbuf[PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_SHA256_OUTPUT_BYTES]; - unsigned long i; - - /* While we can fit in at least another full block of SHA256 output.. */ - for (i = 0; (i + 1)*PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_SHA256_OUTPUT_BYTES <= outlen; i++) { - PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_ull_to_bytes(input_plus_four_bytes + inlen, 4, i); - sha256(out, input_plus_four_bytes, inlen + 4); - out += PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_SHA256_OUTPUT_BYTES; - } - /* Until we cannot anymore, and we fill the remainder. */ - if (outlen > i * PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_SHA256_OUTPUT_BYTES) { - PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_ull_to_bytes(input_plus_four_bytes + inlen, 4, i); - sha256(outbuf, input_plus_four_bytes, inlen + 4); - memcpy(out, outbuf, outlen - i * PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_SHA256_OUTPUT_BYTES); - } -} - - -/** - * Absorb the constant pub_seed using one round of the compression function - * This initializes hash_state_seeded, which can then be reused in thash - **/ -void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_seed_state(sha256ctx *hash_state_seeded, const unsigned char *pub_seed) { - uint8_t block[PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_SHA256_BLOCK_BYTES]; - size_t i; - - for (i = 0; i < PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_N; ++i) { - block[i] = pub_seed[i]; - } - for (i = PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_N; i < PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_SHA256_BLOCK_BYTES; ++i) { - block[i] = 0; - } - - sha256_inc_init(hash_state_seeded); - sha256_inc_blocks(hash_state_seeded, block, 1); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_clean/sha256.h b/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_clean/sha256.h deleted file mode 100644 index 9bbf592f11..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_clean/sha256.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_SHA256_H -#define PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_SHA256_H - -#define PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_SHA256_BLOCK_BYTES 64 -#define PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_SHA256_OUTPUT_BYTES 32 /* This does not necessarily equal PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_N */ -#define PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_SHA256_ADDR_BYTES 22 - -#include -#include - -#include "sha2.h" - -void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_compress_address(unsigned char *out, const uint32_t addr[8]); - -void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_mgf1( - unsigned char *out, unsigned long outlen, - unsigned char *input_plus_four_bytes, unsigned long inlen); - -void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_seed_state(sha256ctx *hash_state_seeded, const unsigned char *pub_seed); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_clean/sign.c b/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_clean/sign.c deleted file mode 100644 index d5a31191f2..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_clean/sign.c +++ /dev/null @@ -1,356 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "api.h" -#include "fors.h" -#include "hash.h" -#include "hash_state.h" -#include "params.h" -#include "randombytes.h" -#include "thash.h" -#include "utils.h" -#include "wots.h" - -/** - * Computes the leaf at a given address. First generates the WOTS key pair, - * then computes leaf by hashing horizontally. - */ -static void wots_gen_leaf(unsigned char *leaf, const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx, const uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - unsigned char pk[PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_WOTS_BYTES]; - uint32_t wots_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_set_type( - wots_addr, PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_set_type( - wots_pk_addr, PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_ADDR_TYPE_WOTSPK); - - PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_set_keypair_addr( - wots_addr, addr_idx); - PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_wots_gen_pk( - pk, sk_seed, pub_seed, wots_addr, hash_state_seeded); - - PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_copy_keypair_addr( - wots_pk_addr, wots_addr); - PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_thash_WOTS_LEN( - leaf, pk, pub_seed, wots_pk_addr, hash_state_seeded); -} - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_crypto_sign_secretkeybytes(void) { - return PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_CRYPTO_SECRETKEYBYTES; -} - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_crypto_sign_publickeybytes(void) { - return PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_CRYPTO_PUBLICKEYBYTES; -} - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_crypto_sign_bytes(void) { - return PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_CRYPTO_BYTES; -} - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_crypto_sign_seedbytes(void) { - return PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_CRYPTO_SEEDBYTES; -} - -/* - * Generates an SPX key pair given a seed of length - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed) { - /* We do not need the auth path in key generation, but it simplifies the - code to have just one treehash routine that computes both root and path - in one function. */ - unsigned char auth_path[PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_TREE_HEIGHT * PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_N]; - uint32_t top_tree_addr[8] = {0}; - hash_state hash_state_seeded; - - PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_set_layer_addr( - top_tree_addr, PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_D - 1); - PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_set_type( - top_tree_addr, PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_ADDR_TYPE_HASHTREE); - - /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ - memcpy(sk, seed, PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_CRYPTO_SEEDBYTES); - - memcpy(pk, sk + 2 * PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_N, PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_initialize_hash_function(&hash_state_seeded, pk, sk); - - /* Compute root node of the top-most subtree. */ - PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_treehash_TREE_HEIGHT( - sk + 3 * PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_N, auth_path, sk, sk + 2 * PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_N, 0, 0, - wots_gen_leaf, top_tree_addr, &hash_state_seeded); - - memcpy(pk + PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_N, sk + 3 * PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_N, PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_N); - - PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_destroy_hash_function(&hash_state_seeded); - return 0; -} - -/* - * Generates an SPX key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk) { - unsigned char seed[PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_CRYPTO_SEEDBYTES]; - randombytes(seed, PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_CRYPTO_SEEDBYTES); - PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_crypto_sign_seed_keypair( - pk, sk, seed); - - return 0; -} - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - const unsigned char *sk_seed = sk; - const unsigned char *sk_prf = sk + PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_N; - const unsigned char *pk = sk + 2 * PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_N; - const unsigned char *pub_seed = pk; - - unsigned char optrand[PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_N]; - unsigned char mhash[PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_FORS_MSG_BYTES]; - unsigned char root[PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_N]; - uint32_t i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - - hash_state hash_state_seeded; - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_initialize_hash_function( - &hash_state_seeded, - pub_seed, sk_seed); - - PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_set_type( - wots_addr, PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_set_type( - tree_addr, PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_ADDR_TYPE_HASHTREE); - - /* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ - randombytes(optrand, PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_N); - /* Compute the digest randomization value. */ - PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_gen_message_random( - sig, sk_prf, optrand, m, mlen, &hash_state_seeded); - - /* Derive the message digest and leaf index from R, PK and M. */ - PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_N; - - PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); - - /* Sign the message hash using FORS. */ - PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_fors_sign( - sig, root, mhash, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_FORS_BYTES; - - for (i = 0; i < PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_D; i++) { - PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_set_tree_addr(tree_addr, tree); - - PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); - - /* Compute a WOTS signature. */ - PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_wots_sign( - sig, root, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_WOTS_BYTES; - - /* Compute the authentication path for the used WOTS leaf. */ - PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_treehash_TREE_HEIGHT( - root, sig, sk_seed, pub_seed, idx_leaf, 0, - wots_gen_leaf, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_TREE_HEIGHT * PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_TREE_HEIGHT; - } - - *siglen = PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_BYTES; - - PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_destroy_hash_function(&hash_state_seeded); - return 0; -} - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk) { - const unsigned char *pub_seed = pk; - const unsigned char *pub_root = pk + PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_N; - unsigned char mhash[PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_FORS_MSG_BYTES]; - unsigned char wots_pk[PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_WOTS_BYTES]; - unsigned char root[PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_N]; - unsigned char leaf[PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_N]; - unsigned int i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - hash_state hash_state_seeded; - - if (siglen != PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_BYTES) { - return -1; - } - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_initialize_hash_function( - &hash_state_seeded, - pub_seed, NULL); - - PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_set_type( - wots_addr, PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_set_type( - tree_addr, PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_ADDR_TYPE_HASHTREE); - PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_set_type( - wots_pk_addr, PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_ADDR_TYPE_WOTSPK); - - /* Derive the message digest and leaf index from R || PK || M. */ - /* The additional PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_N is a result of the hash domain separator. */ - PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_N; - - /* Layer correctly defaults to 0, so no need to set_layer_addr */ - PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); - - PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_fors_pk_from_sig( - root, sig, mhash, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_FORS_BYTES; - - /* For each subtree.. */ - for (i = 0; i < PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_D; i++) { - PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_set_tree_addr(tree_addr, tree); - - PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); - - PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_copy_keypair_addr( - wots_pk_addr, wots_addr); - - /* The WOTS public key is only correct if the signature was correct. */ - /* Initially, root is the FORS pk, but on subsequent iterations it is - the root of the subtree below the currently processed subtree. */ - PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_wots_pk_from_sig( - wots_pk, sig, root, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_WOTS_BYTES; - - /* Compute the leaf node using the WOTS public key. */ - PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_thash_WOTS_LEN( - leaf, wots_pk, pub_seed, wots_pk_addr, &hash_state_seeded); - - /* Compute the root node of this subtree. */ - PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_compute_root( - root, leaf, idx_leaf, 0, sig, PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_TREE_HEIGHT, - pub_seed, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_TREE_HEIGHT * PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_TREE_HEIGHT; - } - - PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_destroy_hash_function(&hash_state_seeded); - /* Check if the root node equals the root node in the public key. */ - if (memcmp(root, pub_root, PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_N) != 0) { - return -1; - } - - return 0; -} - - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - size_t siglen; - - PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_crypto_sign_signature( - sm, &siglen, m, mlen, sk); - - memmove(sm + PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_BYTES, m, mlen); - *smlen = siglen + mlen; - - return 0; -} - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk) { - /* The API caller does not necessarily know what size a signature should be - but SPHINCS+ signatures are always exactly PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_BYTES. */ - if (smlen < PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_BYTES) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - *mlen = smlen - PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_BYTES; - - if (PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_crypto_sign_verify( - sm, PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_BYTES, sm + PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_BYTES, *mlen, pk)) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - /* If verification was successful, move the message to the right place. */ - memmove(m, sm + PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_BYTES, *mlen); - - return 0; -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_clean/thash.h b/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_clean/thash.h deleted file mode 100644 index e44c2884b3..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_clean/thash.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_THASH_H -#define PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_THASH_H - -#include "hash_state.h" - -#include - -void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_clean/thash_sha256_robust.c b/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_clean/thash_sha256_robust.c deleted file mode 100644 index a10b1a82e5..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_clean/thash_sha256_robust.c +++ /dev/null @@ -1,82 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "thash.h" - -#include "sha2.h" -#include "sha256.h" - -/** - * Takes an array of inblocks concatenated arrays of PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_N bytes. - */ -static void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_thash( - unsigned char *out, unsigned char *buf, - const unsigned char *in, unsigned int inblocks, - const unsigned char *pub_seed, uint32_t addr[8], - const sha256ctx *hash_state_seeded) { - - unsigned char outbuf[PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_SHA256_OUTPUT_BYTES]; - unsigned char *bitmask = buf + PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_N + PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_SHA256_ADDR_BYTES + 4; - sha256ctx sha2_state; - unsigned int i; - - memcpy(buf, pub_seed, PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_N); - PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_compress_address(buf + PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_N, addr); - /* MGF1 requires us to have 4 extra bytes in 'buf' */ - PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_mgf1(bitmask, inblocks * PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_N, buf, PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_N + PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_SHA256_ADDR_BYTES); - - /* Retrieve precomputed state containing pub_seed */ - sha256_inc_ctx_clone(&sha2_state, hash_state_seeded); - - for (i = 0; i < inblocks * PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_N; i++) { - buf[PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_N + PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_SHA256_ADDR_BYTES + i] = in[i] ^ bitmask[i]; - } - - sha256_inc_finalize(outbuf, &sha2_state, buf + PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_N, - PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_N); - memcpy(out, outbuf, PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_N); -} - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const sha256ctx *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_N + PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_SHA256_ADDR_BYTES + 4 + 1 * PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_N]; - PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_thash( - out, buf, in, 1, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const sha256ctx *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_N + PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_SHA256_ADDR_BYTES + 4 + 2 * PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_N]; - PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_thash( - out, buf, in, 2, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const sha256ctx *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_N + PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_SHA256_ADDR_BYTES + 4 + PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_WOTS_LEN * PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_N]; - PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_thash( - out, buf, in, PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_WOTS_LEN, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const sha256ctx *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_N + PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_SHA256_ADDR_BYTES + 4 + PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_FORS_TREES * PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_N]; - PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_thash( - out, buf, in, PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_FORS_TREES, pub_seed, addr, hash_state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_clean/utils.c b/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_clean/utils.c deleted file mode 100644 index 61c3a669a1..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_clean/utils.c +++ /dev/null @@ -1,199 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "hash_state.h" -#include "params.h" -#include "thash.h" -#include "utils.h" - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in) { - - /* Iterate over out in decreasing order, for big-endianness. */ - for (size_t i = outlen; i > 0; i--) { - out[i - 1] = in & 0xff; - in = in >> 8; - } -} - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_bytes_to_ull( - const unsigned char *in, size_t inlen) { - unsigned long long retval = 0; - - for (size_t i = 0; i < inlen; i++) { - retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); - } - return retval; -} - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - uint32_t i; - unsigned char buffer[2 * PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_N]; - - /* If leaf_idx is odd (last bit = 1), current path element is a right child - and auth_path has to go left. Otherwise it is the other way around. */ - if (leaf_idx & 1) { - memcpy(buffer + PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_N, leaf, PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_N); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_N); - } else { - memcpy(buffer, leaf, PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_N); - memcpy(buffer + PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_N, auth_path, PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_N); - } - auth_path += PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_N; - - for (i = 0; i < tree_height - 1; i++) { - leaf_idx >>= 1; - idx_offset >>= 1; - /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_set_tree_height(addr, i + 1); - PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_set_tree_index( - addr, leaf_idx + idx_offset); - - /* Pick the right or left neighbor, depending on parity of the node. */ - if (leaf_idx & 1) { - PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_thash_2( - buffer + PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_N, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_N); - } else { - PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_thash_2( - buffer, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer + PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_N, auth_path, PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_N); - } - auth_path += PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_N; - } - - /* The last iteration is exceptional; we do not copy an auth_path node. */ - leaf_idx >>= 1; - idx_offset >>= 1; - PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_set_tree_height(addr, tree_height); - PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_set_tree_index( - addr, leaf_idx + idx_offset); - PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_thash_2( - root, buffer, pub_seed, addr, hash_state_seeded); -} - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -static void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_treehash( - unsigned char *root, unsigned char *auth_path, - unsigned char *stack, unsigned int *heights, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - - unsigned int offset = 0; - uint32_t idx; - uint32_t tree_idx; - - for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { - /* Add the next leaf node to the stack. */ - gen_leaf(stack + offset * PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_N, - sk_seed, pub_seed, idx + idx_offset, tree_addr, - hash_state_seeded); - offset++; - heights[offset - 1] = 0; - - /* If this is a node we need for the auth path.. */ - if ((leaf_idx ^ 0x1) == idx) { - memcpy(auth_path, stack + (offset - 1)*PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_N, PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_N); - } - - /* While the top-most nodes are of equal height.. */ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { - /* Compute index of the new node, in the next layer. */ - tree_idx = (idx >> (heights[offset - 1] + 1)); - - /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_set_tree_height( - tree_addr, heights[offset - 1] + 1); - PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_set_tree_index( - tree_addr, tree_idx + (idx_offset >> (heights[offset - 1] + 1))); - /* Hash the top-most nodes from the stack together. */ - PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_thash_2( - stack + (offset - 2)*PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_N, stack + (offset - 2)*PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_N, - pub_seed, tree_addr, hash_state_seeded); - offset--; - /* Note that the top-most node is now one layer higher. */ - heights[offset - 1]++; - - /* If this is a node we need for the auth path.. */ - if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_path + heights[offset - 1]*PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_N, - stack + (offset - 1)*PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_N, PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_N); - } - } - } - memcpy(root, stack, PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_N); -} - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_FORS_HEIGHT + 1)*PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_N]; - unsigned int heights[PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_FORS_HEIGHT + 1]; - - PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_FORS_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_TREE_HEIGHT + 1)*PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_N]; - unsigned int heights[PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_TREE_HEIGHT + 1]; - - PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_TREE_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_clean/utils.h b/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_clean/utils.h deleted file mode 100644 index 693eecae38..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_clean/utils.h +++ /dev/null @@ -1,64 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_UTILS_H -#define PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_UTILS_H - -#include "hash_state.h" -#include "params.h" -#include -#include - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in); - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_bytes_to_ull( - const unsigned char *in, size_t inlen); - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_clean/wots.c b/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_clean/wots.c deleted file mode 100644 index 7eca64ccc0..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_clean/wots.c +++ /dev/null @@ -1,167 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "hash_state.h" -#include "params.h" -#include "thash.h" -#include "utils.h" -#include "wots.h" - -// TODO clarify address expectations, and make them more uniform. -// TODO i.e. do we expect types to be set already? -// TODO and do we expect modifications or copies? - -/** - * Computes the starting value for a chain, i.e. the secret key. - * Expects the address to be complete up to the chain address. - */ -static void wots_gen_sk(unsigned char *sk, const unsigned char *sk_seed, - uint32_t wots_addr[8], - const hash_state *hash_state_seeded) { - /* Make sure that the hash address is actually zeroed. */ - PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_set_hash_addr(wots_addr, 0); - - /* Generate sk element. */ - PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_prf_addr(sk, sk_seed, wots_addr, hash_state_seeded); -} - -/** - * Computes the chaining function. - * out and in have to be n-byte arrays. - * - * Interprets in as start-th value of the chain. - * addr has to contain the address of the chain. - */ -static void gen_chain(unsigned char *out, const unsigned char *in, - unsigned int start, unsigned int steps, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - uint32_t i; - - /* Initialize out with the value at position 'start'. */ - memcpy(out, in, PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_N); - - /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_WOTS_W; i++) { - PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_set_hash_addr(addr, i); - PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_thash_1( - out, out, pub_seed, addr, hash_state_seeded); - } -} - -/** - * base_w algorithm as described in draft. - * Interprets an array of bytes as integers in base w. - * This only works when log_w is a divisor of 8. - */ -static void base_w(unsigned int *output, const size_t out_len, - const unsigned char *input) { - size_t in = 0; - size_t out = 0; - unsigned char total = 0; - unsigned int bits = 0; - size_t consumed; - - for (consumed = 0; consumed < out_len; consumed++) { - if (bits == 0) { - total = input[in]; - in++; - bits += 8; - } - bits -= PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_WOTS_LOGW; - output[out] = (unsigned int)((total >> bits) & (PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_WOTS_W - 1)); - out++; - } -} - -/* Computes the WOTS+ checksum over a message (in base_w). */ -static void wots_checksum(unsigned int *csum_base_w, - const unsigned int *msg_base_w) { - unsigned int csum = 0; - unsigned char csum_bytes[(PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_WOTS_LEN2 * PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_WOTS_LOGW + 7) / 8]; - unsigned int i; - - /* Compute checksum. */ - for (i = 0; i < PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_WOTS_LEN1; i++) { - csum += PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_WOTS_W - 1 - msg_base_w[i]; - } - - /* Convert checksum to base_w. */ - /* Make sure expected empty zero bits are the least significant bits. */ - csum = csum << (8 - ((PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_WOTS_LEN2 * PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_WOTS_LOGW) % 8)); - PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_ull_to_bytes( - csum_bytes, sizeof(csum_bytes), csum); - base_w(csum_base_w, PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_WOTS_LEN2, csum_bytes); -} - -/* Takes a message and derives the matching chain lengths. */ -static void chain_lengths(unsigned int *lengths, const unsigned char *msg) { - base_w(lengths, PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_WOTS_LEN1, msg); - wots_checksum(lengths + PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_WOTS_LEN1, lengths); -} - -/** - * WOTS key generation. Takes a 32 byte sk_seed, expands it to WOTS private key - * elements and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_wots_gen_pk( - unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - uint32_t i; - - for (i = 0; i < PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_WOTS_LEN; i++) { - PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_set_chain_addr(addr, i); - wots_gen_sk(pk + i * PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_N, sk_seed, addr, hash_state_seeded); - gen_chain(pk + i * PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_N, pk + i * PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_N, - 0, PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_WOTS_W - 1, pub_seed, addr, hash_state_seeded); - } -} - -/** - * Takes a n-byte message and the 32-byte sk_see to compute a signature 'sig'. - */ -void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_wots_sign( - unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *hash_state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_WOTS_LEN; i++) { - PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_set_chain_addr(addr, i); - wots_gen_sk(sig + i * PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_N, sk_seed, addr, hash_state_seeded); - gen_chain(sig + i * PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_N, sig + i * PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_N, 0, lengths[i], pub_seed, addr, hash_state_seeded); - } -} - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_wots_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_WOTS_LEN; i++) { - PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_set_chain_addr(addr, i); - gen_chain(pk + i * PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_N, sig + i * PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_N, - lengths[i], PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_WOTS_W - 1 - lengths[i], pub_seed, addr, - hash_state_seeded); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_clean/wots.h b/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_clean/wots.h deleted file mode 100644 index d45383db85..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_clean/wots.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_WOTS_H -#define PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_WOTS_H - -#include "hash_state.h" -#include "params.h" -#include - -/** - * WOTS key generation. Takes a 32 byte seed for the private key, expands it to - * a full WOTS private key and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_wots_gen_pk( - unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -/** - * Takes a n-byte message and the 32-byte seed for the private key to compute a - * signature that is placed at 'sig'. - */ -void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_wots_sign( - unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *hash_state_seeded); - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_wots_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_avx2/LICENSE b/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_avx2/LICENSE deleted file mode 100644 index 670154e353..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_avx2/LICENSE +++ /dev/null @@ -1,116 +0,0 @@ -CC0 1.0 Universal - -Statement of Purpose - -The laws of most jurisdictions throughout the world automatically confer -exclusive Copyright and Related Rights (defined below) upon the creator and -subsequent owner(s) (each and all, an "owner") of an original work of -authorship and/or a database (each, a "Work"). - -Certain owners wish to permanently relinquish those rights to a Work for the -purpose of contributing to a commons of creative, cultural and scientific -works ("Commons") that the public can reliably and without fear of later -claims of infringement build upon, modify, incorporate in other works, reuse -and redistribute as freely as possible in any form whatsoever and for any -purposes, including without limitation commercial purposes. These owners may -contribute to the Commons to promote the ideal of a free culture and the -further production of creative, cultural and scientific works, or to gain -reputation or greater distribution for their Work in part through the use and -efforts of others. - -For these and/or other purposes and motivations, and without any expectation -of additional consideration or compensation, the person associating CC0 with a -Work (the "Affirmer"), to the extent that he or she is an owner of Copyright -and Related Rights in the Work, voluntarily elects to apply CC0 to the Work -and publicly distribute the Work under its terms, with knowledge of his or her -Copyright and Related Rights in the Work and the meaning and intended legal -effect of CC0 on those rights. - -1. Copyright and Related Rights. A Work made available under CC0 may be -protected by copyright and related or neighboring rights ("Copyright and -Related Rights"). Copyright and Related Rights include, but are not limited -to, the following: - - i. the right to reproduce, adapt, distribute, perform, display, communicate, - and translate a Work; - - ii. moral rights retained by the original author(s) and/or performer(s); - - iii. publicity and privacy rights pertaining to a person's image or likeness - depicted in a Work; - - iv. rights protecting against unfair competition in regards to a Work, - subject to the limitations in paragraph 4(a), below; - - v. rights protecting the extraction, dissemination, use and reuse of data in - a Work; - - vi. database rights (such as those arising under Directive 96/9/EC of the - European Parliament and of the Council of 11 March 1996 on the legal - protection of databases, and under any national implementation thereof, - including any amended or successor version of such directive); and - - vii. other similar, equivalent or corresponding rights throughout the world - based on applicable law or treaty, and any national implementations thereof. - -2. Waiver. To the greatest extent permitted by, but not in contravention of, -applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and -unconditionally waives, abandons, and surrenders all of Affirmer's Copyright -and Related Rights and associated claims and causes of action, whether now -known or unknown (including existing as well as future claims and causes of -action), in the Work (i) in all territories worldwide, (ii) for the maximum -duration provided by applicable law or treaty (including future time -extensions), (iii) in any current or future medium and for any number of -copies, and (iv) for any purpose whatsoever, including without limitation -commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes -the Waiver for the benefit of each member of the public at large and to the -detriment of Affirmer's heirs and successors, fully intending that such Waiver -shall not be subject to revocation, rescission, cancellation, termination, or -any other legal or equitable action to disrupt the quiet enjoyment of the Work -by the public as contemplated by Affirmer's express Statement of Purpose. - -3. Public License Fallback. Should any part of the Waiver for any reason be -judged legally invalid or ineffective under applicable law, then the Waiver -shall be preserved to the maximum extent permitted taking into account -Affirmer's express Statement of Purpose. In addition, to the extent the Waiver -is so judged Affirmer hereby grants to each affected person a royalty-free, -non transferable, non sublicensable, non exclusive, irrevocable and -unconditional license to exercise Affirmer's Copyright and Related Rights in -the Work (i) in all territories worldwide, (ii) for the maximum duration -provided by applicable law or treaty (including future time extensions), (iii) -in any current or future medium and for any number of copies, and (iv) for any -purpose whatsoever, including without limitation commercial, advertising or -promotional purposes (the "License"). The License shall be deemed effective as -of the date CC0 was applied by Affirmer to the Work. Should any part of the -License for any reason be judged legally invalid or ineffective under -applicable law, such partial invalidity or ineffectiveness shall not -invalidate the remainder of the License, and in such case Affirmer hereby -affirms that he or she will not (i) exercise any of his or her remaining -Copyright and Related Rights in the Work or (ii) assert any associated claims -and causes of action with respect to the Work, in either case contrary to -Affirmer's express Statement of Purpose. - -4. Limitations and Disclaimers. - - a. No trademark or patent rights held by Affirmer are waived, abandoned, - surrendered, licensed or otherwise affected by this document. - - b. Affirmer offers the Work as-is and makes no representations or warranties - of any kind concerning the Work, express, implied, statutory or otherwise, - including without limitation warranties of title, merchantability, fitness - for a particular purpose, non infringement, or the absence of latent or - other defects, accuracy, or the present or absence of errors, whether or not - discoverable, all to the greatest extent permissible under applicable law. - - c. Affirmer disclaims responsibility for clearing rights of other persons - that may apply to the Work or any use thereof, including without limitation - any person's Copyright and Related Rights in the Work. Further, Affirmer - disclaims responsibility for obtaining any necessary consents, permissions - or other rights required for any use of the Work. - - d. Affirmer understands and acknowledges that Creative Commons is not a - party to this document and has no duty or obligation with respect to this - CC0 or use of the Work. - -For more information, please see - diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_avx2/address.c b/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_avx2/address.c deleted file mode 100644 index 5e9437ea36..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_avx2/address.c +++ /dev/null @@ -1,78 +0,0 @@ -#include - -#include "address.h" -#include "params.h" -#include "utils.h" - -void PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]) { - int i; - - for (i = 0; i < 8; i++) { - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_ull_to_bytes( - bytes + i * 4, 4, addr[i]); - } -} - -void PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_set_layer_addr( - uint32_t addr[8], uint32_t layer) { - addr[0] = layer; -} - -void PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_set_tree_addr( - uint32_t addr[8], uint64_t tree) { - addr[1] = 0; - addr[2] = (uint32_t) (tree >> 32); - addr[3] = (uint32_t) tree; -} - -void PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_set_type( - uint32_t addr[8], uint32_t type) { - addr[4] = type; -} - -void PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; -} - -/* These functions are used for OTS addresses. */ - -void PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_set_keypair_addr( - uint32_t addr[8], uint32_t keypair) { - addr[5] = keypair; -} - -void PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; - out[5] = in[5]; -} - -void PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_set_chain_addr( - uint32_t addr[8], uint32_t chain) { - addr[6] = chain; -} - -void PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_set_hash_addr( - uint32_t addr[8], uint32_t hash) { - addr[7] = hash; -} - -/* These functions are used for all hash tree addresses (including FORS). */ - -void PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_set_tree_height( - uint32_t addr[8], uint32_t tree_height) { - addr[6] = tree_height; -} - -void PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_set_tree_index( - uint32_t addr[8], uint32_t tree_index) { - addr[7] = tree_index; -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_avx2/address.h b/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_avx2/address.h deleted file mode 100644 index afc84c24c8..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_avx2/address.h +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_ADDRESS_H -#define PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_ADDRESS_H - -#include - -#define PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_ADDR_TYPE_WOTS 0 -#define PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_ADDR_TYPE_WOTSPK 1 -#define PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_ADDR_TYPE_HASHTREE 2 -#define PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_ADDR_TYPE_FORSTREE 3 -#define PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_ADDR_TYPE_FORSPK 4 - -void PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]); - -void PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_set_layer_addr( - uint32_t addr[8], uint32_t layer); - -void PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_set_tree_addr( - uint32_t addr[8], uint64_t tree); - -void PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_set_type( - uint32_t addr[8], uint32_t type); - -/* Copies the layer and tree part of one address into the other */ -void PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for WOTS and FORS addresses. */ - -void PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_set_keypair_addr( - uint32_t addr[8], uint32_t keypair); - -void PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_set_chain_addr( - uint32_t addr[8], uint32_t chain); - -void PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_set_hash_addr( - uint32_t addr[8], uint32_t hash); - -void PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for all hash tree addresses (including FORS). */ - -void PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_set_tree_height( - uint32_t addr[8], uint32_t tree_height); - -void PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_set_tree_index( - uint32_t addr[8], uint32_t tree_index); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_avx2/api.h b/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_avx2/api.h deleted file mode 100644 index a0e22a4a74..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_avx2/api.h +++ /dev/null @@ -1,81 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_API_H -#define PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_API_H - -#include -#include - - - -#define PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_CRYPTO_ALGNAME "SPHINCS+" - -#define PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_CRYPTO_SECRETKEYBYTES 64 -#define PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_CRYPTO_PUBLICKEYBYTES 32 -#define PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_CRYPTO_BYTES 7856 -#define PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_CRYPTO_SEEDBYTES 48 - - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_avx2/fors.c b/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_avx2/fors.c deleted file mode 100644 index b99bd67909..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_avx2/fors.c +++ /dev/null @@ -1,240 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "fors.h" -#include "hash.h" -#include "hashx8.h" -#include "thash.h" -#include "thashx8.h" -#include "utils.h" -#include "utilsx8.h" - -static void fors_gen_skx8(unsigned char *sk0, - unsigned char *sk1, - unsigned char *sk2, - unsigned char *sk3, - unsigned char *sk4, - unsigned char *sk5, - unsigned char *sk6, - unsigned char *sk7, const unsigned char *sk_seed, - uint32_t fors_leaf_addrx8[8 * 8]) { - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_prf_addrx8(sk0, sk1, sk2, sk3, sk4, sk5, sk6, sk7, - sk_seed, fors_leaf_addrx8); -} - -static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, - const unsigned char *pub_seed, - uint32_t fors_leaf_addr[8], - const hash_state *state_seeded) { - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_thash_1(leaf, sk, pub_seed, fors_leaf_addr, state_seeded); -} - -static void fors_sk_to_leafx8(unsigned char *leaf0, - unsigned char *leaf1, - unsigned char *leaf2, - unsigned char *leaf3, - unsigned char *leaf4, - unsigned char *leaf5, - unsigned char *leaf6, - unsigned char *leaf7, - const unsigned char *sk0, - const unsigned char *sk1, - const unsigned char *sk2, - const unsigned char *sk3, - const unsigned char *sk4, - const unsigned char *sk5, - const unsigned char *sk6, - const unsigned char *sk7, - const unsigned char *pub_seed, - uint32_t fors_leaf_addrx8[8 * 8], - const hash_state *state_seeded) { - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_thashx8_1(leaf0, leaf1, leaf2, leaf3, leaf4, leaf5, leaf6, leaf7, - sk0, sk1, sk2, sk3, sk4, sk5, sk6, sk7, - pub_seed, fors_leaf_addrx8, state_seeded); -} - -static void fors_gen_leafx8(unsigned char *leaf0, - unsigned char *leaf1, - unsigned char *leaf2, - unsigned char *leaf3, - unsigned char *leaf4, - unsigned char *leaf5, - unsigned char *leaf6, - unsigned char *leaf7, - const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx0, - uint32_t addr_idx1, - uint32_t addr_idx2, - uint32_t addr_idx3, - uint32_t addr_idx4, - uint32_t addr_idx5, - uint32_t addr_idx6, - uint32_t addr_idx7, - const uint32_t fors_tree_addr[8], - const hash_state *state_seeded) { - uint32_t fors_leaf_addrx8[8 * 8] = {0}; - unsigned int j; - - /* Only copy the parts that must be kept in fors_leaf_addrx8. */ - for (j = 0; j < 8; j++) { - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_copy_keypair_addr(fors_leaf_addrx8 + j * 8, fors_tree_addr); - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_set_type(fors_leaf_addrx8 + j * 8, PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_ADDR_TYPE_FORSTREE); - } - - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_set_tree_index(fors_leaf_addrx8 + 0 * 8, addr_idx0); - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_set_tree_index(fors_leaf_addrx8 + 1 * 8, addr_idx1); - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_set_tree_index(fors_leaf_addrx8 + 2 * 8, addr_idx2); - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_set_tree_index(fors_leaf_addrx8 + 3 * 8, addr_idx3); - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_set_tree_index(fors_leaf_addrx8 + 4 * 8, addr_idx4); - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_set_tree_index(fors_leaf_addrx8 + 5 * 8, addr_idx5); - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_set_tree_index(fors_leaf_addrx8 + 6 * 8, addr_idx6); - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_set_tree_index(fors_leaf_addrx8 + 7 * 8, addr_idx7); - - fors_gen_skx8(leaf0, leaf1, leaf2, leaf3, leaf4, leaf5, leaf6, leaf7, - sk_seed, fors_leaf_addrx8); - fors_sk_to_leafx8(leaf0, leaf1, leaf2, leaf3, leaf4, leaf5, leaf6, leaf7, - leaf0, leaf1, leaf2, leaf3, leaf4, leaf5, leaf6, leaf7, - pub_seed, fors_leaf_addrx8, state_seeded); -} - -/** - * Interprets m as PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_FORS_HEIGHT-bit unsigned integers. - * Assumes m contains at least PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_FORS_TREES bits. - * Assumes indices has space for PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_FORS_TREES integers. - */ -static void message_to_indices(uint32_t *indices, const unsigned char *m) { - unsigned int i, j; - unsigned int offset = 0; - - for (i = 0; i < PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_FORS_TREES; i++) { - indices[i] = 0; - for (j = 0; j < PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_FORS_HEIGHT; j++) { - indices[i] ^= (((uint32_t)m[offset >> 3] >> (offset & 0x7)) & 0x1) << j; - offset++; - } - } -} - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_fors_sign( - unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], - const hash_state *state_seeded) { - /* Round up to multiple of 8 to prevent out-of-bounds for x8 parallelism */ - uint32_t indices[(PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_FORS_TREES + 7) & ~7] = {0}; - unsigned char roots[((PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_FORS_TREES + 7) & ~7) * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N]; - /* Sign to a buffer, since we may not have a nice multiple of 8 and would - otherwise overrun the signature. */ - unsigned char sigbufx8[8 * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N * (1 + PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_FORS_HEIGHT)]; - uint32_t fors_tree_addrx8[8 * 8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset[8] = {0}; - unsigned int i, j; - - for (j = 0; j < 8; j++) { - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_copy_keypair_addr(fors_tree_addrx8 + j * 8, fors_addr); - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_set_type(fors_tree_addrx8 + j * 8, PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_ADDR_TYPE_FORSTREE); - } - - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_copy_keypair_addr(fors_pk_addr, fors_addr); - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_set_type(fors_pk_addr, PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < ((PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_FORS_TREES + 7) & ~0x7); i += 8) { - for (j = 0; j < 8; j++) { - if (i + j < PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_FORS_TREES) { - idx_offset[j] = (i + j) * (1 << PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_FORS_HEIGHT); - - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_set_tree_height(fors_tree_addrx8 + j * 8, 0); - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_set_tree_index(fors_tree_addrx8 + j * 8, - indices[i + j] + idx_offset[j]); - } - } - - /* Include the secret key part that produces the selected leaf nodes. */ - fors_gen_skx8(sigbufx8 + 0 * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N, - sigbufx8 + 1 * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N, - sigbufx8 + 2 * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N, - sigbufx8 + 3 * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N, - sigbufx8 + 4 * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N, - sigbufx8 + 5 * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N, - sigbufx8 + 6 * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N, - sigbufx8 + 7 * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N, - sk_seed, fors_tree_addrx8); - - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_treehashx8_FORS_HEIGHT( - roots + i * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N, sigbufx8 + 8 * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N, sk_seed, pub_seed, - &indices[i], idx_offset, fors_gen_leafx8, fors_tree_addrx8, - state_seeded); - - for (j = 0; j < 8; j++) { - if (i + j < PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_FORS_TREES) { - memcpy(sig, sigbufx8 + j * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N, PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N); - memcpy(sig + PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N, - sigbufx8 + 8 * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N + j * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_FORS_HEIGHT, - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_FORS_HEIGHT); - sig += PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N * (1 + PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_FORS_HEIGHT); - } - } - } - - /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_thash_FORS_TREES(pk, roots, pub_seed, fors_pk_addr, state_seeded); -} - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, - const uint32_t fors_addr[8], - const hash_state *state_seeded) { - uint32_t indices[PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_FORS_TREES]; - unsigned char roots[PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_FORS_TREES * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N]; - unsigned char leaf[PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N]; - uint32_t fors_tree_addr[8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_copy_keypair_addr(fors_tree_addr, fors_addr); - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_copy_keypair_addr(fors_pk_addr, fors_addr); - - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_set_type(fors_tree_addr, PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_set_type(fors_pk_addr, PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_FORS_TREES; i++) { - idx_offset = i * (1 << PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_FORS_HEIGHT); - - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_set_tree_height(fors_tree_addr, 0); - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Derive the leaf from the included secret key part. */ - fors_sk_to_leaf(leaf, sig, pub_seed, fors_tree_addr, state_seeded); - sig += PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N; - - /* Derive the corresponding root node of this tree. */ - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_compute_root(roots + i * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N, leaf, indices[i], idx_offset, - sig, PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_FORS_HEIGHT, pub_seed, fors_tree_addr, state_seeded); - sig += PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_thash_FORS_TREES(pk, roots, pub_seed, fors_pk_addr, state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_avx2/fors.h b/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_avx2/fors.h deleted file mode 100644 index f0bdc3b4ea..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_avx2/fors.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_FORS_H -#define PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_FORS_H - -#include - -#include "hash_state.h" -#include "params.h" - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_fors_sign( - unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *hash_state_seeded); - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_fors_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, const uint32_t fors_addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_avx2/hash.h b/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_avx2/hash.h deleted file mode 100644 index 36d143bd0f..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_avx2/hash.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_HASH_H -#define PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_HASH_H - -#include "hash_state.h" - -#include -#include - -void PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_initialize_hash_function( - hash_state *hash_state_seeded, - const unsigned char *pub_seed, const unsigned char *sk_seed); - -void PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_destroy_hash_function(hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_avx2/hash_sha256.c b/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_avx2/hash_sha256.c deleted file mode 100644 index 62625cd2f6..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_avx2/hash_sha256.c +++ /dev/null @@ -1,166 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "utils.h" - -#include "sha2.h" -#include "sha256.h" -#include "sha256x8.h" - -/** - * Initializes the hash function states - */ -void PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_initialize_hash_function( - hash_state *hash_state_seeded, - const unsigned char *pub_seed, const unsigned char *sk_seed) { - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_seed_state(&hash_state_seeded->x1, pub_seed); - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_seed_statex8(&hash_state_seeded->x8, pub_seed); - (void)sk_seed; /* Suppress an 'unused parameter' warning. */ -} - -/** - * Cleans up the hash function states - */ -void PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_destroy_hash_function(hash_state *hash_state_seeded) { - sha256_inc_ctx_release(&hash_state_seeded->x1); -} - -/* - * Computes PRF(key, addr), given a secret key of PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N bytes and an address - */ -void PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_prf_addr(unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded) { - unsigned char buf[PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_ADDR_BYTES]; - unsigned char outbuf[PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_OUTPUT_BYTES]; - - memcpy(buf, key, PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N); - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_compress_address(buf + PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N, addr); - - sha256(outbuf, buf, PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_ADDR_BYTES); - memcpy(out, outbuf, PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} - -/** - * Computes the message-dependent randomness R, using a secret seed as a key - * for HMAC, and an optional randomization value prefixed to the message. - * This requires m to have at least PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_BLOCK_BYTES + PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N space - * available in front of the pointer, i.e. before the message to use for the - * prefix. This is necessary to prevent having to move the message around (and - * allocate memory for it). - */ -void PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, const hash_state *hash_state_seeded) { - unsigned char buf[PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_BLOCK_BYTES + PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_OUTPUT_BYTES]; - sha256ctx state; - int i; - - /* This implements HMAC-SHA256 */ - for (i = 0; i < PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N; i++) { - buf[i] = 0x36 ^ sk_prf[i]; - } - memset(buf + PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N, 0x36, PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N); - - sha256_inc_init(&state); - sha256_inc_blocks(&state, buf, 1); - - memcpy(buf, optrand, PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N); - - /* If optrand + message cannot fill up an entire block */ - if (PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N + mlen < PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_BLOCK_BYTES) { - memcpy(buf + PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N, m, mlen); - sha256_inc_finalize(buf + PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_BLOCK_BYTES, &state, - buf, mlen + PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N); - } - /* Otherwise first fill a block, so that finalize only uses the message */ - else { - memcpy(buf + PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N, m, PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N); - sha256_inc_blocks(&state, buf, 1); - - m += PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N; - mlen -= PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N; - sha256_inc_finalize(buf + PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_BLOCK_BYTES, &state, m, mlen); - } - - for (i = 0; i < PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N; i++) { - buf[i] = 0x5c ^ sk_prf[i]; - } - memset(buf + PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N, 0x5c, PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N); - - sha256(buf, buf, PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_BLOCK_BYTES + PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_OUTPUT_BYTES); - memcpy(R, buf, PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} - -/** - * Computes the message hash using R, the public key, and the message. - * Outputs the message digest and the index of the leaf. The index is split in - * the tree index and the leaf index, for convenient copying to an address. - */ -void PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded) { -#define PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_TREE_BITS (PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_TREE_HEIGHT * (PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_D - 1)) -#define PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_TREE_BYTES ((PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_TREE_BITS + 7) / 8) -#define PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_LEAF_BITS PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_TREE_HEIGHT -#define PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_LEAF_BYTES ((PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_LEAF_BITS + 7) / 8) -#define PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_DGST_BYTES (PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_FORS_MSG_BYTES + PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_TREE_BYTES + PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_LEAF_BYTES) - - unsigned char seed[PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_OUTPUT_BYTES + 4]; - - /* Round to nearest multiple of PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_BLOCK_BYTES */ -#define PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_INBLOCKS (((PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_PK_BYTES + PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_BLOCK_BYTES - 1) & \ - -PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_BLOCK_BYTES) / PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_BLOCK_BYTES) - unsigned char inbuf[PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_INBLOCKS * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_BLOCK_BYTES]; - - unsigned char buf[PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_DGST_BYTES]; - unsigned char *bufp = buf; - sha256ctx state; - - sha256_inc_init(&state); - - memcpy(inbuf, R, PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N); - memcpy(inbuf + PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N, pk, PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_PK_BYTES); - - /* If R + pk + message cannot fill up an entire block */ - if (PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_PK_BYTES + mlen < PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_INBLOCKS * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_BLOCK_BYTES) { - memcpy(inbuf + PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_PK_BYTES, m, mlen); - sha256_inc_finalize(seed, &state, inbuf, PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_PK_BYTES + mlen); - } - /* Otherwise first fill a block, so that finalize only uses the message */ - else { - memcpy(inbuf + PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_PK_BYTES, m, - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_INBLOCKS * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_PK_BYTES); - sha256_inc_blocks(&state, inbuf, PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_INBLOCKS); - - m += PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_INBLOCKS * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_PK_BYTES; - mlen -= PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_INBLOCKS * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_PK_BYTES; - sha256_inc_finalize(seed, &state, m, mlen); - } - - /* By doing this in two steps, we prevent hashing the message twice; - otherwise each iteration in MGF1 would hash the message again. */ - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_mgf1(bufp, PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_DGST_BYTES, seed, PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_OUTPUT_BYTES); - - memcpy(digest, bufp, PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_FORS_MSG_BYTES); - bufp += PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_FORS_MSG_BYTES; - - *tree = PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_bytes_to_ull(bufp, PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_TREE_BYTES); - *tree &= (~(uint64_t)0) >> (64 - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_TREE_BITS); - bufp += PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_TREE_BYTES; - - *leaf_idx = (uint32_t)PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_bytes_to_ull( - bufp, PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_LEAF_BYTES); - *leaf_idx &= (~(uint32_t)0) >> (32 - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_LEAF_BITS); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_avx2/hash_sha256x8.c b/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_avx2/hash_sha256x8.c deleted file mode 100644 index 06a5c1e63a..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_avx2/hash_sha256x8.c +++ /dev/null @@ -1,61 +0,0 @@ -#include -#include - -#include "address.h" -#include "hashx8.h" -#include "params.h" -#include "sha256.h" -#include "sha256avx.h" -#include "sha256x8.h" -#include "utils.h" - -/* - * 8-way parallel version of prf_addr; takes 8x as much input and output - */ -void PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_prf_addrx8(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7, - const unsigned char *key, - const uint32_t addrx8[8 * 8]) { - unsigned char bufx8[8 * (PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_ADDR_BYTES)]; - unsigned char outbufx8[8 * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_OUTPUT_BYTES]; - unsigned int j; - - for (j = 0; j < 8; j++) { - memcpy(bufx8 + j * (PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_ADDR_BYTES), key, PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N); - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_compress_address(bufx8 + PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N + j * (PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_ADDR_BYTES), - addrx8 + j * 8); - } - - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_sha256x8(outbufx8 + 0 * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 1 * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 2 * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 3 * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 4 * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 5 * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 6 * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 7 * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - bufx8 + 0 * (PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_ADDR_BYTES), - bufx8 + 1 * (PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_ADDR_BYTES), - bufx8 + 2 * (PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_ADDR_BYTES), - bufx8 + 3 * (PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_ADDR_BYTES), - bufx8 + 4 * (PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_ADDR_BYTES), - bufx8 + 5 * (PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_ADDR_BYTES), - bufx8 + 6 * (PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_ADDR_BYTES), - bufx8 + 7 * (PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_ADDR_BYTES), - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_ADDR_BYTES); - - memcpy(out0, outbufx8 + 0 * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N); - memcpy(out1, outbufx8 + 1 * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N); - memcpy(out2, outbufx8 + 2 * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N); - memcpy(out3, outbufx8 + 3 * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N); - memcpy(out4, outbufx8 + 4 * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N); - memcpy(out5, outbufx8 + 5 * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N); - memcpy(out6, outbufx8 + 6 * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N); - memcpy(out7, outbufx8 + 7 * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_avx2/hash_state.h b/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_avx2/hash_state.h deleted file mode 100644 index 17e1e96b79..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_avx2/hash_state.h +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_HASH_STATE_H -#define PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_HASH_STATE_H - -/** - * Defines the type of the hash function state. - * - * Don't be fooled into thinking this instance of SPHINCS+ isn't stateless! - * - * From Section 7.2.2 from the SPHINCS+ round-2 specification: - * - * Each of the instances of the tweakable hash function take PK.seed as its - * first input, which is constant for a given key pair – and, thus, across - * a single signature. This leads to a lot of redundant computation. To remedy - * this, we pad PK.seed to the length of a full 64-byte SHA-256 input block. - * Because of the Merkle-Damgård construction that underlies SHA-256, this - * allows for reuse of the intermediate SHA-256 state after the initial call to - * the compression function which improves performance. - * - * We pass this hash state around in functions, because otherwise we need to - * have a global variable. - * - * We use a struct to differentiate between the x1 and x8 variants of SHA256. - */ - -#include "sha2.h" -#include "sha256avx.h" - -typedef struct { - sha256ctx x1; - sha256ctxx8 x8; -} hash_state; - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_avx2/hashx8.h b/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_avx2/hashx8.h deleted file mode 100644 index b35e898d24..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_avx2/hashx8.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_HASHX8_H -#define PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_HASHX8_H - -#include - -#include "params.h" - -void PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_prf_addrx8(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7, - const unsigned char *key, - const uint32_t addrx8[8 * 8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_avx2/params.h b/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_avx2/params.h deleted file mode 100644 index a9b2caf961..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_avx2/params.h +++ /dev/null @@ -1,53 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_PARAMS_H -#define PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_PARAMS_H - -/* Hash output length in bytes. */ -#define PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N 16 -/* Height of the hypertree. */ -#define PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_FULL_HEIGHT 63 -/* Number of subtree layer. */ -#define PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_D 7 -/* FORS tree dimensions. */ -#define PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_FORS_HEIGHT 12 -#define PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_FORS_TREES 14 -/* Winternitz parameter, */ -#define PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_WOTS_W 16 - -/* The hash function is defined by linking a different hash.c file, as opposed - to setting a #define constant. */ - -/* For clarity */ -#define PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_ADDR_BYTES 32 - -/* WOTS parameters. */ -#define PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_WOTS_LOGW 4 - -#define PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_WOTS_LEN1 (8 * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N / PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_WOTS_LOGW) - -/* PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#define PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_WOTS_LEN2 3 - -#define PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_WOTS_LEN (PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_WOTS_LEN1 + PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_WOTS_LEN2) -#define PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_WOTS_BYTES (PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_WOTS_LEN * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N) -#define PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_WOTS_PK_BYTES PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_WOTS_BYTES - -/* Subtree size. */ -#define PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_TREE_HEIGHT (PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_FULL_HEIGHT / PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_D) - -/* FORS parameters. */ -#define PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_FORS_MSG_BYTES ((PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_FORS_TREES + 7) / 8) -#define PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_FORS_BYTES ((PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_FORS_HEIGHT + 1) * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_FORS_TREES * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N) -#define PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_FORS_PK_BYTES PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N - -/* Resulting SPX sizes. */ -#define PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_BYTES (PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_FORS_BYTES + PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_D * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_WOTS_BYTES +\ - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_FULL_HEIGHT * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N) -#define PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_PK_BYTES (2 * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N) -#define PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SK_BYTES (2 * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_PK_BYTES) - -/* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ -#define PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_OPTRAND_BYTES 32 - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_avx2/sha256.c b/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_avx2/sha256.c deleted file mode 100644 index b91a2eeee5..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_avx2/sha256.c +++ /dev/null @@ -1,71 +0,0 @@ -/* Based on the public domain implementation in - * crypto_hash/sha512/ref/ from http://bench.cr.yp.to/supercop.html - * by D. J. Bernstein */ - -#include -#include -#include - -#include "sha2.h" -#include "sha256.h" -#include "utils.h" - -/* - * Compresses an address to a 22-byte sequence. - * This reduces the number of required SHA256 compression calls, as the last - * block of input is padded with at least 65 bits. - */ -void PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_compress_address(unsigned char *out, const uint32_t addr[8]) { - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_ull_to_bytes(out, 1, addr[0]); /* drop 3 bytes of the layer field */ - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_ull_to_bytes(out + 1, 4, addr[2]); /* drop the highest tree address word */ - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_ull_to_bytes(out + 5, 4, addr[3]); - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_ull_to_bytes(out + 9, 1, addr[4]); /* drop 3 bytes of the type field */ - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_ull_to_bytes(out + 10, 4, addr[5]); - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_ull_to_bytes(out + 14, 4, addr[6]); - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_ull_to_bytes(out + 18, 4, addr[7]); -} - -/** - * Requires 'input_plus_four_bytes' to have 'inlen' + 4 bytes, so that the last - * four bytes can be used for the counter. Typically 'input' is merely a seed. - * Outputs outlen number of bytes - */ -void PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_mgf1( - unsigned char *out, unsigned long outlen, - unsigned char *input_plus_four_bytes, unsigned long inlen) { - unsigned char outbuf[PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_OUTPUT_BYTES]; - unsigned long i; - - /* While we can fit in at least another full block of SHA256 output.. */ - for (i = 0; (i + 1)*PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_OUTPUT_BYTES <= outlen; i++) { - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_ull_to_bytes(input_plus_four_bytes + inlen, 4, i); - sha256(out, input_plus_four_bytes, inlen + 4); - out += PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_OUTPUT_BYTES; - } - /* Until we cannot anymore, and we fill the remainder. */ - if (outlen > i * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_OUTPUT_BYTES) { - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_ull_to_bytes(input_plus_four_bytes + inlen, 4, i); - sha256(outbuf, input_plus_four_bytes, inlen + 4); - memcpy(out, outbuf, outlen - i * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_OUTPUT_BYTES); - } -} - - -/** - * Absorb the constant pub_seed using one round of the compression function - * This initializes hash_state_seeded, which can then be reused in thash - **/ -void PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_seed_state(sha256ctx *hash_state_seeded, const unsigned char *pub_seed) { - uint8_t block[PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_BLOCK_BYTES]; - size_t i; - - for (i = 0; i < PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N; ++i) { - block[i] = pub_seed[i]; - } - for (i = PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N; i < PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_BLOCK_BYTES; ++i) { - block[i] = 0; - } - - sha256_inc_init(hash_state_seeded); - sha256_inc_blocks(hash_state_seeded, block, 1); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_avx2/sha256.h b/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_avx2/sha256.h deleted file mode 100644 index 8d130b0e46..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_avx2/sha256.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_H -#define PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_H - -#define PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_BLOCK_BYTES 64 -#define PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_OUTPUT_BYTES 32 /* This does not necessarily equal PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N */ -#define PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_ADDR_BYTES 22 - -#include -#include - -#include "sha2.h" - -void PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_compress_address(unsigned char *out, const uint32_t addr[8]); - -void PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_mgf1( - unsigned char *out, unsigned long outlen, - unsigned char *input_plus_four_bytes, unsigned long inlen); - -void PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_seed_state(sha256ctx *hash_state_seeded, const unsigned char *pub_seed); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_avx2/sha256avx.c b/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_avx2/sha256avx.c deleted file mode 100644 index 485a7d7e4a..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_avx2/sha256avx.c +++ /dev/null @@ -1,296 +0,0 @@ -#include -#include -#include - -#include "sha256avx.h" - -// Transpose 8 vectors containing 32-bit values -void PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_transpose(u256 s[8]) { - u256 tmp0[8]; - u256 tmp1[8]; - tmp0[0] = _mm256_unpacklo_epi32(s[0], s[1]); - tmp0[1] = _mm256_unpackhi_epi32(s[0], s[1]); - tmp0[2] = _mm256_unpacklo_epi32(s[2], s[3]); - tmp0[3] = _mm256_unpackhi_epi32(s[2], s[3]); - tmp0[4] = _mm256_unpacklo_epi32(s[4], s[5]); - tmp0[5] = _mm256_unpackhi_epi32(s[4], s[5]); - tmp0[6] = _mm256_unpacklo_epi32(s[6], s[7]); - tmp0[7] = _mm256_unpackhi_epi32(s[6], s[7]); - tmp1[0] = _mm256_unpacklo_epi64(tmp0[0], tmp0[2]); - tmp1[1] = _mm256_unpackhi_epi64(tmp0[0], tmp0[2]); - tmp1[2] = _mm256_unpacklo_epi64(tmp0[1], tmp0[3]); - tmp1[3] = _mm256_unpackhi_epi64(tmp0[1], tmp0[3]); - tmp1[4] = _mm256_unpacklo_epi64(tmp0[4], tmp0[6]); - tmp1[5] = _mm256_unpackhi_epi64(tmp0[4], tmp0[6]); - tmp1[6] = _mm256_unpacklo_epi64(tmp0[5], tmp0[7]); - tmp1[7] = _mm256_unpackhi_epi64(tmp0[5], tmp0[7]); - s[0] = _mm256_permute2x128_si256(tmp1[0], tmp1[4], 0x20); - s[1] = _mm256_permute2x128_si256(tmp1[1], tmp1[5], 0x20); - s[2] = _mm256_permute2x128_si256(tmp1[2], tmp1[6], 0x20); - s[3] = _mm256_permute2x128_si256(tmp1[3], tmp1[7], 0x20); - s[4] = _mm256_permute2x128_si256(tmp1[0], tmp1[4], 0x31); - s[5] = _mm256_permute2x128_si256(tmp1[1], tmp1[5], 0x31); - s[6] = _mm256_permute2x128_si256(tmp1[2], tmp1[6], 0x31); - s[7] = _mm256_permute2x128_si256(tmp1[3], tmp1[7], 0x31); -} - -void PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_sha256_clone_statex8(sha256ctxx8 *outctx, const sha256ctxx8 *inctx) { - memcpy(outctx, inctx, sizeof(sha256ctxx8)); -} - -void PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_sha256_init8x(sha256ctxx8 *ctx) { - ctx->s[0] = _mm256_set_epi32((int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667); - ctx->s[1] = _mm256_set_epi32((int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85); - ctx->s[2] = _mm256_set_epi32((int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372); - ctx->s[3] = _mm256_set_epi32((int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a); - ctx->s[4] = _mm256_set_epi32((int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f); - ctx->s[5] = _mm256_set_epi32((int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c); - ctx->s[6] = _mm256_set_epi32((int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab); - ctx->s[7] = _mm256_set_epi32((int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19); - - ctx->datalen = 0; - ctx->msglen = 0; -} - -void PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_sha256_update8x(sha256ctxx8 *ctx, - const unsigned char *d0, - const unsigned char *d1, - const unsigned char *d2, - const unsigned char *d3, - const unsigned char *d4, - const unsigned char *d5, - const unsigned char *d6, - const unsigned char *d7, - unsigned long long len) { - size_t i = 0; - size_t bytes_to_copy; - - while (i < len) { - bytes_to_copy = (size_t)len - i; - if (bytes_to_copy > 64) { - bytes_to_copy = 64; - } - memcpy(&ctx->msgblocks[64 * 0], d0 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64 * 1], d1 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64 * 2], d2 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64 * 3], d3 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64 * 4], d4 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64 * 5], d5 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64 * 6], d6 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64 * 7], d7 + i, bytes_to_copy); - ctx->datalen += (unsigned int)bytes_to_copy; - i += bytes_to_copy; - if (ctx->datalen == 64) { - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_sha256_transform8x(ctx, ctx->msgblocks); - ctx->msglen += 512; - ctx->datalen = 0; - } - } -} - -void PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_sha256_final8x(sha256ctxx8 *ctx, - unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7) { - unsigned int i, curlen; - - // Padding - if (ctx->datalen < 56) { - for (i = 0; i < 8; ++i) { - curlen = ctx->datalen; - ctx->msgblocks[64 * i + curlen++] = 0x80; - while (curlen < 64) { - ctx->msgblocks[64 * i + curlen++] = 0x00; - } - } - } else { - for (i = 0; i < 8; ++i) { - curlen = ctx->datalen; - ctx->msgblocks[64 * i + curlen++] = 0x80; - while (curlen < 64) { - ctx->msgblocks[64 * i + curlen++] = 0x00; - } - } - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_sha256_transform8x(ctx, ctx->msgblocks); - memset(ctx->msgblocks, 0, 8 * 64); - } - - // Add length of the message to each block - ctx->msglen += ctx->datalen * 8; - for (i = 0; i < 8; i++) { - ctx->msgblocks[64 * i + 63] = (unsigned char)ctx->msglen; - ctx->msgblocks[64 * i + 62] = (unsigned char)(ctx->msglen >> 8); - ctx->msgblocks[64 * i + 61] = (unsigned char)(ctx->msglen >> 16); - ctx->msgblocks[64 * i + 60] = (unsigned char)(ctx->msglen >> 24); - ctx->msgblocks[64 * i + 59] = (unsigned char)(ctx->msglen >> 32); - ctx->msgblocks[64 * i + 58] = (unsigned char)(ctx->msglen >> 40); - ctx->msgblocks[64 * i + 57] = (unsigned char)(ctx->msglen >> 48); - ctx->msgblocks[64 * i + 56] = (unsigned char)(ctx->msglen >> 56); - } - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_sha256_transform8x(ctx, ctx->msgblocks); - - // Compute final hash output - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_transpose(ctx->s); - - // Store Hash value - STORE(out0, BYTESWAP(ctx->s[0])); - STORE(out1, BYTESWAP(ctx->s[1])); - STORE(out2, BYTESWAP(ctx->s[2])); - STORE(out3, BYTESWAP(ctx->s[3])); - STORE(out4, BYTESWAP(ctx->s[4])); - STORE(out5, BYTESWAP(ctx->s[5])); - STORE(out6, BYTESWAP(ctx->s[6])); - STORE(out7, BYTESWAP(ctx->s[7])); -} - -void PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_sha256_transform8x(sha256ctxx8 *ctx, const unsigned char *data) { - u256 s[8], w[64], T0, T1; - int i; - - // Load words and transform data correctly - for (i = 0; i < 8; i++) { - w[i] = BYTESWAP(LOAD(data + 64 * i)); - w[i + 8] = BYTESWAP(LOAD(data + 32 + 64 * i)); - } - - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_transpose(w); - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_transpose(w + 8); - - // Initial State - s[0] = ctx->s[0]; - s[1] = ctx->s[1]; - s[2] = ctx->s[2]; - s[3] = ctx->s[3]; - s[4] = ctx->s[4]; - s[5] = ctx->s[5]; - s[6] = ctx->s[6]; - s[7] = ctx->s[7]; - - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 0, w[0]); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 1, w[1]); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 2, w[2]); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 3, w[3]); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 4, w[4]); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 5, w[5]); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 6, w[6]); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 7, w[7]); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 8, w[8]); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 9, w[9]); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 10, w[10]); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 11, w[11]); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 12, w[12]); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 13, w[13]); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 14, w[14]); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 15, w[15]); - w[16] = ADD4_32(WSIGMA1_AVX(w[14]), w[0], w[9], WSIGMA0_AVX(w[1])); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 16, w[16]); - w[17] = ADD4_32(WSIGMA1_AVX(w[15]), w[1], w[10], WSIGMA0_AVX(w[2])); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 17, w[17]); - w[18] = ADD4_32(WSIGMA1_AVX(w[16]), w[2], w[11], WSIGMA0_AVX(w[3])); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 18, w[18]); - w[19] = ADD4_32(WSIGMA1_AVX(w[17]), w[3], w[12], WSIGMA0_AVX(w[4])); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 19, w[19]); - w[20] = ADD4_32(WSIGMA1_AVX(w[18]), w[4], w[13], WSIGMA0_AVX(w[5])); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 20, w[20]); - w[21] = ADD4_32(WSIGMA1_AVX(w[19]), w[5], w[14], WSIGMA0_AVX(w[6])); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 21, w[21]); - w[22] = ADD4_32(WSIGMA1_AVX(w[20]), w[6], w[15], WSIGMA0_AVX(w[7])); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 22, w[22]); - w[23] = ADD4_32(WSIGMA1_AVX(w[21]), w[7], w[16], WSIGMA0_AVX(w[8])); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 23, w[23]); - w[24] = ADD4_32(WSIGMA1_AVX(w[22]), w[8], w[17], WSIGMA0_AVX(w[9])); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 24, w[24]); - w[25] = ADD4_32(WSIGMA1_AVX(w[23]), w[9], w[18], WSIGMA0_AVX(w[10])); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 25, w[25]); - w[26] = ADD4_32(WSIGMA1_AVX(w[24]), w[10], w[19], WSIGMA0_AVX(w[11])); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 26, w[26]); - w[27] = ADD4_32(WSIGMA1_AVX(w[25]), w[11], w[20], WSIGMA0_AVX(w[12])); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 27, w[27]); - w[28] = ADD4_32(WSIGMA1_AVX(w[26]), w[12], w[21], WSIGMA0_AVX(w[13])); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 28, w[28]); - w[29] = ADD4_32(WSIGMA1_AVX(w[27]), w[13], w[22], WSIGMA0_AVX(w[14])); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 29, w[29]); - w[30] = ADD4_32(WSIGMA1_AVX(w[28]), w[14], w[23], WSIGMA0_AVX(w[15])); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 30, w[30]); - w[31] = ADD4_32(WSIGMA1_AVX(w[29]), w[15], w[24], WSIGMA0_AVX(w[16])); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 31, w[31]); - w[32] = ADD4_32(WSIGMA1_AVX(w[30]), w[16], w[25], WSIGMA0_AVX(w[17])); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 32, w[32]); - w[33] = ADD4_32(WSIGMA1_AVX(w[31]), w[17], w[26], WSIGMA0_AVX(w[18])); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 33, w[33]); - w[34] = ADD4_32(WSIGMA1_AVX(w[32]), w[18], w[27], WSIGMA0_AVX(w[19])); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 34, w[34]); - w[35] = ADD4_32(WSIGMA1_AVX(w[33]), w[19], w[28], WSIGMA0_AVX(w[20])); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 35, w[35]); - w[36] = ADD4_32(WSIGMA1_AVX(w[34]), w[20], w[29], WSIGMA0_AVX(w[21])); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 36, w[36]); - w[37] = ADD4_32(WSIGMA1_AVX(w[35]), w[21], w[30], WSIGMA0_AVX(w[22])); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 37, w[37]); - w[38] = ADD4_32(WSIGMA1_AVX(w[36]), w[22], w[31], WSIGMA0_AVX(w[23])); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 38, w[38]); - w[39] = ADD4_32(WSIGMA1_AVX(w[37]), w[23], w[32], WSIGMA0_AVX(w[24])); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 39, w[39]); - w[40] = ADD4_32(WSIGMA1_AVX(w[38]), w[24], w[33], WSIGMA0_AVX(w[25])); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 40, w[40]); - w[41] = ADD4_32(WSIGMA1_AVX(w[39]), w[25], w[34], WSIGMA0_AVX(w[26])); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 41, w[41]); - w[42] = ADD4_32(WSIGMA1_AVX(w[40]), w[26], w[35], WSIGMA0_AVX(w[27])); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 42, w[42]); - w[43] = ADD4_32(WSIGMA1_AVX(w[41]), w[27], w[36], WSIGMA0_AVX(w[28])); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 43, w[43]); - w[44] = ADD4_32(WSIGMA1_AVX(w[42]), w[28], w[37], WSIGMA0_AVX(w[29])); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 44, w[44]); - w[45] = ADD4_32(WSIGMA1_AVX(w[43]), w[29], w[38], WSIGMA0_AVX(w[30])); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 45, w[45]); - w[46] = ADD4_32(WSIGMA1_AVX(w[44]), w[30], w[39], WSIGMA0_AVX(w[31])); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 46, w[46]); - w[47] = ADD4_32(WSIGMA1_AVX(w[45]), w[31], w[40], WSIGMA0_AVX(w[32])); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 47, w[47]); - w[48] = ADD4_32(WSIGMA1_AVX(w[46]), w[32], w[41], WSIGMA0_AVX(w[33])); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 48, w[48]); - w[49] = ADD4_32(WSIGMA1_AVX(w[47]), w[33], w[42], WSIGMA0_AVX(w[34])); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 49, w[49]); - w[50] = ADD4_32(WSIGMA1_AVX(w[48]), w[34], w[43], WSIGMA0_AVX(w[35])); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 50, w[50]); - w[51] = ADD4_32(WSIGMA1_AVX(w[49]), w[35], w[44], WSIGMA0_AVX(w[36])); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 51, w[51]); - w[52] = ADD4_32(WSIGMA1_AVX(w[50]), w[36], w[45], WSIGMA0_AVX(w[37])); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 52, w[52]); - w[53] = ADD4_32(WSIGMA1_AVX(w[51]), w[37], w[46], WSIGMA0_AVX(w[38])); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 53, w[53]); - w[54] = ADD4_32(WSIGMA1_AVX(w[52]), w[38], w[47], WSIGMA0_AVX(w[39])); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 54, w[54]); - w[55] = ADD4_32(WSIGMA1_AVX(w[53]), w[39], w[48], WSIGMA0_AVX(w[40])); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 55, w[55]); - w[56] = ADD4_32(WSIGMA1_AVX(w[54]), w[40], w[49], WSIGMA0_AVX(w[41])); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 56, w[56]); - w[57] = ADD4_32(WSIGMA1_AVX(w[55]), w[41], w[50], WSIGMA0_AVX(w[42])); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 57, w[57]); - w[58] = ADD4_32(WSIGMA1_AVX(w[56]), w[42], w[51], WSIGMA0_AVX(w[43])); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 58, w[58]); - w[59] = ADD4_32(WSIGMA1_AVX(w[57]), w[43], w[52], WSIGMA0_AVX(w[44])); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 59, w[59]); - w[60] = ADD4_32(WSIGMA1_AVX(w[58]), w[44], w[53], WSIGMA0_AVX(w[45])); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 60, w[60]); - w[61] = ADD4_32(WSIGMA1_AVX(w[59]), w[45], w[54], WSIGMA0_AVX(w[46])); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 61, w[61]); - w[62] = ADD4_32(WSIGMA1_AVX(w[60]), w[46], w[55], WSIGMA0_AVX(w[47])); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 62, w[62]); - w[63] = ADD4_32(WSIGMA1_AVX(w[61]), w[47], w[56], WSIGMA0_AVX(w[48])); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 63, w[63]); - - // Feed Forward - ctx->s[0] = ADD32(s[0], ctx->s[0]); - ctx->s[1] = ADD32(s[1], ctx->s[1]); - ctx->s[2] = ADD32(s[2], ctx->s[2]); - ctx->s[3] = ADD32(s[3], ctx->s[3]); - ctx->s[4] = ADD32(s[4], ctx->s[4]); - ctx->s[5] = ADD32(s[5], ctx->s[5]); - ctx->s[6] = ADD32(s[6], ctx->s[6]); - ctx->s[7] = ADD32(s[7], ctx->s[7]); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_avx2/sha256avx.h b/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_avx2/sha256avx.h deleted file mode 100644 index e3acbfc282..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_avx2/sha256avx.h +++ /dev/null @@ -1,103 +0,0 @@ -#ifndef SHA256AVX_H -#define SHA256AVX_H - -#include -#include - -static const unsigned int RC[] = { - 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, - 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, - 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, - 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, - 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, - 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, - 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, - 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, - 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, - 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, - 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, - 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, - 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, - 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, - 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, - 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 -}; - -#define u32 uint32_t -#define u256 __m256i - -#define XOR _mm256_xor_si256 -#define OR _mm256_or_si256 -#define AND _mm256_and_si256 -#define ADD32 _mm256_add_epi32 -#define NOT(x) _mm256_xor_si256(x, _mm256_set_epi32(-1, -1, -1, -1, -1, -1, -1, -1)) - -#define LOAD(src) _mm256_loadu_si256((__m256i *)(src)) -#define STORE(dest,src) _mm256_storeu_si256((__m256i *)(dest),src) - -#define BYTESWAP(x) _mm256_shuffle_epi8(x, _mm256_set_epi8(0xc,0xd,0xe,0xf,0x8,0x9,0xa,0xb,0x4,0x5,0x6,0x7,0x0,0x1,0x2,0x3,0xc,0xd,0xe,0xf,0x8,0x9,0xa,0xb,0x4,0x5,0x6,0x7,0x0,0x1,0x2,0x3)) - -#define SHIFTR32(x, y) _mm256_srli_epi32(x, y) -#define SHIFTL32(x, y) _mm256_slli_epi32(x, y) - -#define ROTR32(x, y) OR(SHIFTR32(x, y), SHIFTL32(x, 32 - (y))) -#define ROTL32(x, y) OR(SHIFTL32(x, y), SHIFTR32(x, 32 - (y))) - -#define XOR3(a, b, c) XOR(XOR(a, b), c) - -#define ADD3_32(a, b, c) ADD32(ADD32(a, b), c) -#define ADD4_32(a, b, c, d) ADD32(ADD32(ADD32(a, b), c), d) -#define ADD5_32(a, b, c, d, e) ADD32(ADD32(ADD32(ADD32(a, b), c), d), e) - -#define MAJ_AVX(a, b, c) XOR3(AND(a, b), AND(a, c), AND(b, c)) -#define CH_AVX(a, b, c) XOR(AND(a, b), AND(NOT(a), c)) - -#define SIGMA1_AVX(x) XOR3(ROTR32(x, 6), ROTR32(x, 11), ROTR32(x, 25)) -#define SIGMA0_AVX(x) XOR3(ROTR32(x, 2), ROTR32(x, 13), ROTR32(x, 22)) - -#define WSIGMA1_AVX(x) XOR3(ROTR32(x, 17), ROTR32(x, 19), SHIFTR32(x, 10)) -#define WSIGMA0_AVX(x) XOR3(ROTR32(x, 7), ROTR32(x, 18), SHIFTR32(x, 3)) - -#define SHA256ROUND_AVX(a, b, c, d, e, f, g, h, rc, w) \ - T0 = ADD5_32(h, SIGMA1_AVX(e), CH_AVX(e, f, g), _mm256_set1_epi32((int)RC[rc]), w); \ - (d) = ADD32(d, T0); \ - T1 = ADD32(SIGMA0_AVX(a), MAJ_AVX(a, b, c)); \ - (h) = ADD32(T0, T1); - -typedef struct SHA256state { - u256 s[8]; - uint8_t msgblocks[8 * 64]; - unsigned int datalen; - uint64_t msglen; -} sha256ctxx8; - - -void PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_transpose(u256 s[8]); -void PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_sha256_init_frombytes_x8(sha256ctxx8 *ctx, const uint8_t *s, unsigned long long msglen); -void PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_sha256_init8x(sha256ctxx8 *ctx); -void PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_sha256_update8x(sha256ctxx8 *ctx, - const unsigned char *d0, - const unsigned char *d1, - const unsigned char *d2, - const unsigned char *d3, - const unsigned char *d4, - const unsigned char *d5, - const unsigned char *d6, - const unsigned char *d7, - unsigned long long len); -void PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_sha256_final8x(sha256ctxx8 *ctx, - unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7); - -void PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_sha256_transform8x(sha256ctxx8 *ctx, const unsigned char *data); - -void PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_sha256_clone_statex8(sha256ctxx8 *outctx, const sha256ctxx8 *inctx); - - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_avx2/sha256x8.c b/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_avx2/sha256x8.c deleted file mode 100644 index 23fc7e52ae..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_avx2/sha256x8.c +++ /dev/null @@ -1,128 +0,0 @@ -#include - -#include "sha256.h" -#include "sha256avx.h" -#include "sha256x8.h" -#include "utils.h" - -void PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_seed_statex8(sha256ctxx8 *ctx, const unsigned char *pub_seed) { - uint8_t block[PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_BLOCK_BYTES]; - size_t i; - - for (i = 0; i < PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N; ++i) { - block[i] = pub_seed[i]; - } - for (i = PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N; i < PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_BLOCK_BYTES; ++i) { - block[i] = 0; - } - - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_sha256_init8x(ctx); - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_sha256_update8x(ctx, block, block, block, block, block, block, block, block, PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_BLOCK_BYTES); - -} - -/* This provides a wrapper around the internals of 8x parallel SHA256 */ -void PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_sha256x8(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - const unsigned char *in4, - const unsigned char *in5, - const unsigned char *in6, - const unsigned char *in7, unsigned long long inlen) { - sha256ctxx8 ctx; - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_sha256_init8x(&ctx); - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_sha256_update8x(&ctx, in0, in1, in2, in3, in4, in5, in6, in7, inlen); - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_sha256_final8x(&ctx, out0, out1, out2, out3, out4, out5, out6, out7); -} - -/** - * Note that inlen should be sufficiently small that it still allows for - * an array to be allocated on the stack. Typically 'in' is merely a seed. - * Outputs outlen number of bytes - */ -void PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_mgf1x8( - unsigned char *outx8, - unsigned long outlen, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - const unsigned char *in4, - const unsigned char *in5, - const unsigned char *in6, - const unsigned char *in7, - unsigned long inlen) { - unsigned char inbufx8[8 * ((PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_ADDR_BYTES) + 4)]; - unsigned char outbufx8[8 * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_OUTPUT_BYTES]; - unsigned long i; - unsigned int j; - - memcpy(inbufx8 + 0 * (inlen + 4), in0, inlen); - memcpy(inbufx8 + 1 * (inlen + 4), in1, inlen); - memcpy(inbufx8 + 2 * (inlen + 4), in2, inlen); - memcpy(inbufx8 + 3 * (inlen + 4), in3, inlen); - memcpy(inbufx8 + 4 * (inlen + 4), in4, inlen); - memcpy(inbufx8 + 5 * (inlen + 4), in5, inlen); - memcpy(inbufx8 + 6 * (inlen + 4), in6, inlen); - memcpy(inbufx8 + 7 * (inlen + 4), in7, inlen); - - /* While we can fit in at least another full block of SHA256 output.. */ - for (i = 0; (i + 1)*PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_OUTPUT_BYTES <= outlen; i++) { - for (j = 0; j < 8; j++) { - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_ull_to_bytes(inbufx8 + inlen + j * (inlen + 4), 4, i); - } - - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_sha256x8(outx8 + 0 * outlen, - outx8 + 1 * outlen, - outx8 + 2 * outlen, - outx8 + 3 * outlen, - outx8 + 4 * outlen, - outx8 + 5 * outlen, - outx8 + 6 * outlen, - outx8 + 7 * outlen, - inbufx8 + 0 * (inlen + 4), - inbufx8 + 1 * (inlen + 4), - inbufx8 + 2 * (inlen + 4), - inbufx8 + 3 * (inlen + 4), - inbufx8 + 4 * (inlen + 4), - inbufx8 + 5 * (inlen + 4), - inbufx8 + 6 * (inlen + 4), - inbufx8 + 7 * (inlen + 4), inlen + 4); - outx8 += PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_OUTPUT_BYTES; - } - /* Until we cannot anymore, and we fill the remainder. */ - for (j = 0; j < 8; j++) { - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_ull_to_bytes(inbufx8 + inlen + j * (inlen + 4), 4, i); - } - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_sha256x8(outbufx8 + 0 * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 1 * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 2 * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 3 * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 4 * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 5 * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 6 * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 7 * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - inbufx8 + 0 * (inlen + 4), - inbufx8 + 1 * (inlen + 4), - inbufx8 + 2 * (inlen + 4), - inbufx8 + 3 * (inlen + 4), - inbufx8 + 4 * (inlen + 4), - inbufx8 + 5 * (inlen + 4), - inbufx8 + 6 * (inlen + 4), - inbufx8 + 7 * (inlen + 4), inlen + 4); - - for (j = 0; j < 8; j++) { - memcpy(outx8 + j * outlen, - outbufx8 + j * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outlen - i * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_OUTPUT_BYTES); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_avx2/sha256x8.h b/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_avx2/sha256x8.h deleted file mode 100644 index 057635814f..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_avx2/sha256x8.h +++ /dev/null @@ -1,44 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256X8_H -#define PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256X8_H - -#include "sha256avx.h" - -#define PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_BLOCK_BYTES 64 -#define PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_OUTPUT_BYTES 32 /* This does not necessarily equal PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N */ - -/* This provides a wrapper around the internals of 8x parallel SHA256 */ -void PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_sha256x8(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - const unsigned char *in4, - const unsigned char *in5, - const unsigned char *in6, - const unsigned char *in7, unsigned long long inlen); - -/** - * Note that inlen should be sufficiently small that it still allows for - * an array to be allocated on the stack. Typically 'in' is merely a seed. - * Outputs outlen number of bytes - */ -void PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_mgf1x8(unsigned char *outx8, unsigned long outlen, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - const unsigned char *in4, - const unsigned char *in5, - const unsigned char *in6, - const unsigned char *in7, - unsigned long inlen); - -void PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_seed_statex8(sha256ctxx8 *ctx, const unsigned char *pub_seed); -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_avx2/sign.c b/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_avx2/sign.c deleted file mode 100644 index d0bf4e3a9a..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_avx2/sign.c +++ /dev/null @@ -1,356 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "api.h" -#include "fors.h" -#include "hash.h" -#include "hash_state.h" -#include "params.h" -#include "randombytes.h" -#include "thash.h" -#include "utils.h" -#include "wots.h" - -/** - * Computes the leaf at a given address. First generates the WOTS key pair, - * then computes leaf by hashing horizontally. - */ -static void wots_gen_leaf(unsigned char *leaf, const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx, const uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - unsigned char pk[PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_WOTS_BYTES]; - uint32_t wots_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_set_type( - wots_addr, PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_set_type( - wots_pk_addr, PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_ADDR_TYPE_WOTSPK); - - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_set_keypair_addr( - wots_addr, addr_idx); - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_wots_gen_pk( - pk, sk_seed, pub_seed, wots_addr, hash_state_seeded); - - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_copy_keypair_addr( - wots_pk_addr, wots_addr); - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_thash_WOTS_LEN( - leaf, pk, pub_seed, wots_pk_addr, hash_state_seeded); -} - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_crypto_sign_secretkeybytes(void) { - return PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_CRYPTO_SECRETKEYBYTES; -} - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_crypto_sign_publickeybytes(void) { - return PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_CRYPTO_PUBLICKEYBYTES; -} - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_crypto_sign_bytes(void) { - return PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_CRYPTO_BYTES; -} - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_crypto_sign_seedbytes(void) { - return PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_CRYPTO_SEEDBYTES; -} - -/* - * Generates an SPX key pair given a seed of length - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed) { - /* We do not need the auth path in key generation, but it simplifies the - code to have just one treehash routine that computes both root and path - in one function. */ - unsigned char auth_path[PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_TREE_HEIGHT * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N]; - uint32_t top_tree_addr[8] = {0}; - hash_state hash_state_seeded; - - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_set_layer_addr( - top_tree_addr, PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_D - 1); - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_set_type( - top_tree_addr, PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_ADDR_TYPE_HASHTREE); - - /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ - memcpy(sk, seed, PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_CRYPTO_SEEDBYTES); - - memcpy(pk, sk + 2 * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N, PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_initialize_hash_function(&hash_state_seeded, pk, sk); - - /* Compute root node of the top-most subtree. */ - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_treehash_TREE_HEIGHT( - sk + 3 * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N, auth_path, sk, sk + 2 * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N, 0, 0, - wots_gen_leaf, top_tree_addr, &hash_state_seeded); - - memcpy(pk + PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N, sk + 3 * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N, PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N); - - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_destroy_hash_function(&hash_state_seeded); - return 0; -} - -/* - * Generates an SPX key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk) { - unsigned char seed[PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_CRYPTO_SEEDBYTES]; - randombytes(seed, PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_CRYPTO_SEEDBYTES); - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_crypto_sign_seed_keypair( - pk, sk, seed); - - return 0; -} - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - const unsigned char *sk_seed = sk; - const unsigned char *sk_prf = sk + PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N; - const unsigned char *pk = sk + 2 * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N; - const unsigned char *pub_seed = pk; - - unsigned char optrand[PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N]; - unsigned char mhash[PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_FORS_MSG_BYTES]; - unsigned char root[PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N]; - uint32_t i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - - hash_state hash_state_seeded; - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_initialize_hash_function( - &hash_state_seeded, - pub_seed, sk_seed); - - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_set_type( - wots_addr, PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_set_type( - tree_addr, PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_ADDR_TYPE_HASHTREE); - - /* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ - randombytes(optrand, PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N); - /* Compute the digest randomization value. */ - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_gen_message_random( - sig, sk_prf, optrand, m, mlen, &hash_state_seeded); - - /* Derive the message digest and leaf index from R, PK and M. */ - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N; - - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_set_keypair_addr( - wots_addr, idx_leaf); - - /* Sign the message hash using FORS. */ - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_fors_sign( - sig, root, mhash, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_FORS_BYTES; - - for (i = 0; i < PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_D; i++) { - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_set_tree_addr(tree_addr, tree); - - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_set_keypair_addr( - wots_addr, idx_leaf); - - /* Compute a WOTS signature. */ - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_wots_sign( - sig, root, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_WOTS_BYTES; - - /* Compute the authentication path for the used WOTS leaf. */ - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_treehash_TREE_HEIGHT( - root, sig, sk_seed, pub_seed, idx_leaf, 0, - wots_gen_leaf, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_TREE_HEIGHT * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_TREE_HEIGHT; - } - - *siglen = PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_BYTES; - - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_destroy_hash_function(&hash_state_seeded); - return 0; -} - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk) { - const unsigned char *pub_seed = pk; - const unsigned char *pub_root = pk + PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N; - unsigned char mhash[PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_FORS_MSG_BYTES]; - unsigned char wots_pk[PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_WOTS_BYTES]; - unsigned char root[PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N]; - unsigned char leaf[PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N]; - unsigned int i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - hash_state hash_state_seeded; - - if (siglen != PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_BYTES) { - return -1; - } - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_initialize_hash_function( - &hash_state_seeded, - pub_seed, NULL); - - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_set_type( - wots_addr, PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_set_type( - tree_addr, PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_ADDR_TYPE_HASHTREE); - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_set_type( - wots_pk_addr, PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_ADDR_TYPE_WOTSPK); - - /* Derive the message digest and leaf index from R || PK || M. */ - /* The additional PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N is a result of the hash domain separator. */ - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N; - - /* Layer correctly defaults to 0, so no need to set_layer_addr */ - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_set_keypair_addr( - wots_addr, idx_leaf); - - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_fors_pk_from_sig( - root, sig, mhash, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_FORS_BYTES; - - /* For each subtree.. */ - for (i = 0; i < PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_D; i++) { - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_set_tree_addr(tree_addr, tree); - - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_set_keypair_addr( - wots_addr, idx_leaf); - - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_copy_keypair_addr( - wots_pk_addr, wots_addr); - - /* The WOTS public key is only correct if the signature was correct. */ - /* Initially, root is the FORS pk, but on subsequent iterations it is - the root of the subtree below the currently processed subtree. */ - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_wots_pk_from_sig( - wots_pk, sig, root, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_WOTS_BYTES; - - /* Compute the leaf node using the WOTS public key. */ - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_thash_WOTS_LEN( - leaf, wots_pk, pub_seed, wots_pk_addr, &hash_state_seeded); - - /* Compute the root node of this subtree. */ - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_compute_root( - root, leaf, idx_leaf, 0, sig, PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_TREE_HEIGHT, - pub_seed, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_TREE_HEIGHT * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_TREE_HEIGHT; - } - - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_destroy_hash_function(&hash_state_seeded); - /* Check if the root node equals the root node in the public key. */ - if (memcmp(root, pub_root, PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N) != 0) { - return -1; - } - - return 0; -} - - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - size_t siglen; - - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_crypto_sign_signature( - sm, &siglen, m, mlen, sk); - - memmove(sm + PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_BYTES, m, mlen); - *smlen = siglen + mlen; - - return 0; -} - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk) { - /* The API caller does not necessarily know what size a signature should be - but SPHINCS+ signatures are always exactly PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_BYTES. */ - if (smlen < PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_BYTES) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - *mlen = smlen - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_BYTES; - - if (PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_crypto_sign_verify( - sm, PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_BYTES, sm + PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_BYTES, *mlen, pk)) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - /* If verification was successful, move the message to the right place. */ - memmove(m, sm + PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_BYTES, *mlen); - - return 0; -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_avx2/thash.h b/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_avx2/thash.h deleted file mode 100644 index 0b9eb1c14a..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_avx2/thash.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_THASH_H -#define PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_THASH_H - -#include "hash_state.h" - -#include - -void PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_avx2/thash_sha256_simple.c b/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_avx2/thash_sha256_simple.c deleted file mode 100644 index df280608fb..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_avx2/thash_sha256_simple.c +++ /dev/null @@ -1,75 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "thash.h" - -#include "sha2.h" -#include "sha256.h" - -/** - * Takes an array of inblocks concatenated arrays of PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N bytes. - */ -static void PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_thash( - unsigned char *out, unsigned char *buf, - const unsigned char *in, unsigned int inblocks, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char outbuf[PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_OUTPUT_BYTES]; - sha256ctx sha2_state; - - (void)pub_seed; /* Suppress an 'unused parameter' warning. */ - - /* Retrieve precomputed state containing pub_seed */ - sha256_inc_ctx_clone(&sha2_state, &hash_state_seeded->x1); - - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_compress_address(buf, addr); - memcpy(buf + PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_ADDR_BYTES, in, inblocks * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N); - - sha256_inc_finalize(outbuf, &sha2_state, buf, PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N); - memcpy(out, outbuf, PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N); -} - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_ADDR_BYTES + 1 * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N]; - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_thash( - out, buf, in, 1, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_ADDR_BYTES + 2 * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N]; - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_thash( - out, buf, in, 2, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_ADDR_BYTES + PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_WOTS_LEN * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N]; - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_thash( - out, buf, in, PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_WOTS_LEN, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_ADDR_BYTES + PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_FORS_TREES * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N]; - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_thash( - out, buf, in, PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_FORS_TREES, pub_seed, addr, hash_state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_avx2/thash_sha256_simplex8.c b/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_avx2/thash_sha256_simplex8.c deleted file mode 100644 index 4bdb920997..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_avx2/thash_sha256_simplex8.c +++ /dev/null @@ -1,129 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash_state.h" -#include "params.h" -#include "sha256.h" -#include "sha256avx.h" -#include "sha256x8.h" -#include "thashx8.h" -#include "utils.h" - -/** - * 8-way parallel version of thash; takes 8x as much input and output - */ -static void thashx8(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - const unsigned char *in4, - const unsigned char *in5, - const unsigned char *in6, - const unsigned char *in7, unsigned int inblocks, - const unsigned char *pub_seed, uint32_t addrx8[8 * 8], - uint8_t *bufx8, - const hash_state *state_seeded) { - unsigned char outbufx8[8 * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_OUTPUT_BYTES]; - unsigned int i; - sha256ctxx8 ctx; - - (void)pub_seed; /* Suppress an 'unused parameter' warning. */ - - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_sha256_clone_statex8(&ctx, &state_seeded->x8); - - for (i = 0; i < 8; i++) { - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_compress_address(bufx8 + i * (PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N), - addrx8 + i * 8); - } - - memcpy(bufx8 + PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_ADDR_BYTES + - 0 * (PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N), in0, inblocks * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N); - memcpy(bufx8 + PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_ADDR_BYTES + - 1 * (PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N), in1, inblocks * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N); - memcpy(bufx8 + PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_ADDR_BYTES + - 2 * (PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N), in2, inblocks * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N); - memcpy(bufx8 + PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_ADDR_BYTES + - 3 * (PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N), in3, inblocks * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N); - memcpy(bufx8 + PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_ADDR_BYTES + - 4 * (PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N), in4, inblocks * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N); - memcpy(bufx8 + PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_ADDR_BYTES + - 5 * (PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N), in5, inblocks * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N); - memcpy(bufx8 + PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_ADDR_BYTES + - 6 * (PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N), in6, inblocks * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N); - memcpy(bufx8 + PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_ADDR_BYTES + - 7 * (PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N), in7, inblocks * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N); - - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_sha256_update8x(&ctx, - bufx8 + 0 * (PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N), - bufx8 + 1 * (PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N), - bufx8 + 2 * (PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N), - bufx8 + 3 * (PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N), - bufx8 + 4 * (PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N), - bufx8 + 5 * (PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N), - bufx8 + 6 * (PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N), - bufx8 + 7 * (PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N), - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N); - - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_sha256_final8x(&ctx, - outbufx8 + 0 * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 1 * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 2 * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 3 * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 4 * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 5 * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 6 * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 7 * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_OUTPUT_BYTES); - - memcpy(out0, outbufx8 + 0 * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N); - memcpy(out1, outbufx8 + 1 * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N); - memcpy(out2, outbufx8 + 2 * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N); - memcpy(out3, outbufx8 + 3 * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N); - memcpy(out4, outbufx8 + 4 * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N); - memcpy(out5, outbufx8 + 5 * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N); - memcpy(out6, outbufx8 + 6 * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N); - memcpy(out7, outbufx8 + 7 * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N); -} - -#define thashx8_variant_impl(name, size) \ - void PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_thashx8_##name(unsigned char *out0, \ - unsigned char *out1, \ - unsigned char *out2, \ - unsigned char *out3, \ - unsigned char *out4, \ - unsigned char *out5, \ - unsigned char *out6, \ - unsigned char *out7, \ - const unsigned char *in0, \ - const unsigned char *in1, \ - const unsigned char *in2, \ - const unsigned char *in3, \ - const unsigned char *in4, \ - const unsigned char *in5, \ - const unsigned char *in6, \ - const unsigned char *in7, \ - const unsigned char *pub_seed, \ - uint32_t addrx8[8*8], \ - const hash_state *state_seeded) \ - { \ - const unsigned int inblocks = (size); \ - uint8_t bufx8[8*(PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_SHA256_ADDR_BYTES + (size)*PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N)]; \ - thashx8(out0, out1, out2, out3, out4, out5, out6, out7, \ - in0, in1, in2, in3, in4, in5, in6, in7, inblocks, \ - pub_seed, addrx8, bufx8, state_seeded); \ - } - -thashx8_variant_impl(1, 1) -thashx8_variant_impl(2, 2) -thashx8_variant_impl(WOTS_LEN, PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_WOTS_LEN) -thashx8_variant_impl(FORS_TREES, PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_FORS_TREES) - -#undef thashx8_variant_impl diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_avx2/thashx8.h b/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_avx2/thashx8.h deleted file mode 100644 index 3fa8f7bd99..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_avx2/thashx8.h +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_THASHX8_H -#define PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_THASHX8_H - -#include - -#include "hash_state.h" -#include "sha256avx.h" - - -#define thashx8_variant(name) \ - void PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_thashx8_##name( \ - unsigned char *out0, \ - unsigned char *out1, \ - unsigned char *out2, \ - unsigned char *out3, \ - unsigned char *out4, \ - unsigned char *out5, \ - unsigned char *out6, \ - unsigned char *out7, \ - const unsigned char *in0, \ - const unsigned char *in1, \ - const unsigned char *in2, \ - const unsigned char *in3, \ - const unsigned char *in4, \ - const unsigned char *in5, \ - const unsigned char *in6, \ - const unsigned char *in7, \ - const unsigned char *pub_seed, \ - uint32_t addrx8[8*8], \ - const hash_state *state_seeded) - - -thashx8_variant(1); -thashx8_variant(2); -thashx8_variant(WOTS_LEN); -thashx8_variant(FORS_TREES); - -#undef thashx8_variant -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_avx2/utils.c b/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_avx2/utils.c deleted file mode 100644 index 0e299f4390..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_avx2/utils.c +++ /dev/null @@ -1,199 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "hash_state.h" -#include "params.h" -#include "thash.h" -#include "utils.h" - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in) { - - /* Iterate over out in decreasing order, for big-endianness. */ - for (size_t i = outlen; i > 0; i--) { - out[i - 1] = in & 0xff; - in = in >> 8; - } -} - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_bytes_to_ull( - const unsigned char *in, size_t inlen) { - unsigned long long retval = 0; - - for (size_t i = 0; i < inlen; i++) { - retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); - } - return retval; -} - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - uint32_t i; - unsigned char buffer[2 * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N]; - - /* If leaf_idx is odd (last bit = 1), current path element is a right child - and auth_path has to go left. Otherwise it is the other way around. */ - if (leaf_idx & 1) { - memcpy(buffer + PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N, leaf, PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N); - } else { - memcpy(buffer, leaf, PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N); - memcpy(buffer + PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N, auth_path, PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N); - } - auth_path += PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N; - - for (i = 0; i < tree_height - 1; i++) { - leaf_idx >>= 1; - idx_offset >>= 1; - /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_set_tree_height(addr, i + 1); - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_set_tree_index( - addr, leaf_idx + idx_offset); - - /* Pick the right or left neighbor, depending on parity of the node. */ - if (leaf_idx & 1) { - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_thash_2( - buffer + PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N); - } else { - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_thash_2( - buffer, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer + PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N, auth_path, PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N); - } - auth_path += PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N; - } - - /* The last iteration is exceptional; we do not copy an auth_path node. */ - leaf_idx >>= 1; - idx_offset >>= 1; - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_set_tree_height(addr, tree_height); - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_set_tree_index( - addr, leaf_idx + idx_offset); - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_thash_2( - root, buffer, pub_seed, addr, hash_state_seeded); -} - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -static void PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_treehash( - unsigned char *root, unsigned char *auth_path, - unsigned char *stack, unsigned int *heights, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - - unsigned int offset = 0; - uint32_t idx; - uint32_t tree_idx; - - for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { - /* Add the next leaf node to the stack. */ - gen_leaf(stack + offset * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N, - sk_seed, pub_seed, idx + idx_offset, tree_addr, - hash_state_seeded); - offset++; - heights[offset - 1] = 0; - - /* If this is a node we need for the auth path.. */ - if ((leaf_idx ^ 0x1) == idx) { - memcpy(auth_path, stack + (offset - 1)*PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N, PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N); - } - - /* While the top-most nodes are of equal height.. */ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { - /* Compute index of the new node, in the next layer. */ - tree_idx = (idx >> (heights[offset - 1] + 1)); - - /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_set_tree_height( - tree_addr, heights[offset - 1] + 1); - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_set_tree_index( - tree_addr, tree_idx + (idx_offset >> (heights[offset - 1] + 1))); - /* Hash the top-most nodes from the stack together. */ - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_thash_2( - stack + (offset - 2)*PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N, stack + (offset - 2)*PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N, - pub_seed, tree_addr, hash_state_seeded); - offset--; - /* Note that the top-most node is now one layer higher. */ - heights[offset - 1]++; - - /* If this is a node we need for the auth path.. */ - if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_path + heights[offset - 1]*PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N, - stack + (offset - 1)*PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N, PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N); - } - } - } - memcpy(root, stack, PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N); -} - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_FORS_HEIGHT + 1)*PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N]; - unsigned int heights[PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_FORS_HEIGHT + 1]; - - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_FORS_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_TREE_HEIGHT + 1)*PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N]; - unsigned int heights[PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_TREE_HEIGHT + 1]; - - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_TREE_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_avx2/utils.h b/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_avx2/utils.h deleted file mode 100644 index b6eac4e217..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_avx2/utils.h +++ /dev/null @@ -1,64 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_UTILS_H -#define PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_UTILS_H - -#include "hash_state.h" -#include "params.h" -#include -#include - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in); - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_bytes_to_ull( - const unsigned char *in, size_t inlen); - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -void PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_avx2/utilsx8.c b/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_avx2/utilsx8.c deleted file mode 100644 index 94ffe293e8..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_avx2/utilsx8.c +++ /dev/null @@ -1,172 +0,0 @@ -#include - -#include "address.h" -#include "params.h" -#include "thashx8.h" -#include "utils.h" - -#include "utilsx8.h" - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -static void treehashx8(unsigned char *rootx8, unsigned char *auth_pathx8, - unsigned char *stackx8, unsigned int *heights, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t leaf_idx[8], uint32_t idx_offset[8], - uint32_t tree_height, - void (*gen_leafx8)( - unsigned char * /* leaf0 */, - unsigned char * /* leaf1 */, - unsigned char * /* leaf2 */, - unsigned char * /* leaf3 */, - unsigned char * /* leaf4 */, - unsigned char * /* leaf5 */, - unsigned char * /* leaf6 */, - unsigned char * /* leaf7 */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx0 */, - uint32_t /* addr_idx1 */, - uint32_t /* addr_idx2 */, - uint32_t /* addr_idx3 */, - uint32_t /* addr_idx4 */, - uint32_t /* addr_idx5 */, - uint32_t /* addr_idx6 */, - uint32_t /* addr_idx7 */, - const uint32_t[8] /* tree_addr */, - const hash_state * /* state_seeded */), - uint32_t tree_addrx8[8 * 8], - const hash_state *state_seeded) { - unsigned int offset = 0; - uint32_t idx; - uint32_t tree_idx; - unsigned int j; - - for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { - /* Add the next leaf node to the stack. */ - gen_leafx8(stackx8 + 0 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N + offset * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N, - stackx8 + 1 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N + offset * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N, - stackx8 + 2 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N + offset * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N, - stackx8 + 3 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N + offset * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N, - stackx8 + 4 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N + offset * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N, - stackx8 + 5 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N + offset * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N, - stackx8 + 6 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N + offset * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N, - stackx8 + 7 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N + offset * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N, - sk_seed, pub_seed, - idx + idx_offset[0], - idx + idx_offset[1], - idx + idx_offset[2], - idx + idx_offset[3], - idx + idx_offset[4], - idx + idx_offset[5], - idx + idx_offset[6], - idx + idx_offset[7], - tree_addrx8, - state_seeded); - offset++; - heights[offset - 1] = 0; - - /* If this is a node we need for the auth path.. */ - for (j = 0; j < 8; j++) { - if ((leaf_idx[j] ^ 0x1) == idx) { - memcpy(auth_pathx8 + j * tree_height * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N, - stackx8 + j * (tree_height + 1)*PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N + (offset - 1)*PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N, PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N); - } - } - - /* While the top-most nodes are of equal height.. */ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { - /* Compute index of the new node, in the next layer. */ - tree_idx = (idx >> (heights[offset - 1] + 1)); - - /* Set the address of the node we're creating. */ - for (j = 0; j < 8; j++) { - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_set_tree_height(tree_addrx8 + j * 8, heights[offset - 1] + 1); - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_set_tree_index(tree_addrx8 + j * 8, - tree_idx + (idx_offset[j] >> (heights[offset - 1] + 1))); - } - /* Hash the top-most nodes from the stack together. */ - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_thashx8_2(stackx8 + 0 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N, - stackx8 + 1 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N, - stackx8 + 2 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N, - stackx8 + 3 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N, - stackx8 + 4 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N, - stackx8 + 5 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N, - stackx8 + 6 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N, - stackx8 + 7 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N, - stackx8 + 0 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N, - stackx8 + 1 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N, - stackx8 + 2 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N, - stackx8 + 3 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N, - stackx8 + 4 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N, - stackx8 + 5 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N, - stackx8 + 6 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N, - stackx8 + 7 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N, - pub_seed, tree_addrx8, state_seeded); - offset--; - /* Note that the top-most node is now one layer higher. */ - heights[offset - 1]++; - - /* If this is a node we need for the auth path.. */ - for (j = 0; j < 8; j++) { - if (((leaf_idx[j] >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_pathx8 + j * tree_height * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N + heights[offset - 1]*PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N, - stackx8 + j * (tree_height + 1)*PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N + (offset - 1)*PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N, PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N); - } - } - } - } - - for (j = 0; j < 8; j++) { - memcpy(rootx8 + j * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N, stackx8 + j * (tree_height + 1)*PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N, PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N); - } -} - -/* The wrappers below ensure we used fixed-size buffers on the stack (no VLAs) */ - - -#define treehashx8_variant(name, size) \ - void PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_treehashx8_##name( \ - unsigned char *rootx8, unsigned char *auth_pathx8, \ - const unsigned char *sk_seed, const unsigned char *pub_seed, \ - const uint32_t leaf_idx[8], uint32_t idx_offset[8], \ - void (*gen_leafx8)( \ - unsigned char* /* leaf0 */, \ - unsigned char* /* leaf1 */, \ - unsigned char* /* leaf2 */, \ - unsigned char* /* leaf3 */, \ - unsigned char* /* leaf4 */, \ - unsigned char* /* leaf5 */, \ - unsigned char* /* leaf6 */, \ - unsigned char* /* leaf7 */, \ - const unsigned char* /* sk_seed */, \ - const unsigned char* /* pub_seed */, \ - uint32_t /* addr_idx0 */, \ - uint32_t /* addr_idx1 */, \ - uint32_t /* addr_idx2 */, \ - uint32_t /* addr_idx3 */, \ - uint32_t /* addr_idx4 */, \ - uint32_t /* addr_idx5 */, \ - uint32_t /* addr_idx6 */, \ - uint32_t /* addr_idx7 */, \ - const uint32_t[8] /* tree_addr */, \ - const hash_state* /* state_seeded */), \ - uint32_t tree_addrx8[8*8], \ - const hash_state *state_seeded) \ - { \ - const uint32_t tree_height = (size); \ - unsigned char stackx8[8*((size) + 1)*PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N]; \ - unsigned int heights[(size) + 1]; \ - treehashx8(rootx8, auth_pathx8, stackx8, heights, sk_seed, pub_seed, \ - leaf_idx, idx_offset, tree_height, gen_leafx8, tree_addrx8, state_seeded); \ - } - -treehashx8_variant(FORS_HEIGHT, PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_FORS_HEIGHT) - -#undef treehashx8_variant diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_avx2/utilsx8.h b/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_avx2/utilsx8.h deleted file mode 100644 index 6f8a421275..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_avx2/utilsx8.h +++ /dev/null @@ -1,46 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_UTILSX8_H -#define PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_UTILSX8_H - -#include - -#include "hash_state.h" -#include "params.h" - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ - -void PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_treehashx8_FORS_HEIGHT( - unsigned char *rootx8, unsigned char *auth_pathx8, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t leaf_idx[8], uint32_t idx_offset[8], - void (*gen_leafx8)( - unsigned char * /* leaf0 */, - unsigned char * /* leaf1 */, - unsigned char * /* leaf2 */, - unsigned char * /* leaf3 */, - unsigned char * /* leaf4 */, - unsigned char * /* leaf5 */, - unsigned char * /* leaf6 */, - unsigned char * /* leaf7 */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx0 */, - uint32_t /* addr_idx1 */, - uint32_t /* addr_idx2 */, - uint32_t /* addr_idx3 */, - uint32_t /* addr_idx4 */, - uint32_t /* addr_idx5 */, - uint32_t /* addr_idx6 */, - uint32_t /* addr_idx7 */, - const uint32_t[8] /* tree_addr */, - const hash_state * /* state_seeded */), - uint32_t tree_addrx8[8 * 8], - const hash_state *state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_avx2/wots.c b/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_avx2/wots.c deleted file mode 100644 index 40ad012805..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_avx2/wots.c +++ /dev/null @@ -1,240 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "hash_state.h" -#include "hashx8.h" -#include "params.h" -#include "thash.h" -#include "thashx8.h" -#include "utils.h" -#include "wots.h" - -// TODO clarify address expectations, and make them more uniform. -// TODO i.e. do we expect types to be set already? -// TODO and do we expect modifications or copies? - -/** - * Computes the starting value for a chain, i.e. the secret key. - * Expects the address to be complete up to the chain address. - */ -static void wots_gen_sk(unsigned char *sk, const unsigned char *sk_seed, - uint32_t wots_addr[8], const hash_state *state_seeded) { - /* Make sure that the hash address is actually zeroed. */ - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_set_hash_addr(wots_addr, 0); - - /* Generate sk element. */ - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_prf_addr(sk, sk_seed, wots_addr, state_seeded); -} - -/** - * 8-way parallel version of wots_gen_sk; expects 8x as much space in sk - */ -static void wots_gen_skx8(unsigned char *skx8, const unsigned char *sk_seed, - uint32_t wots_addrx8[8 * 8]) { - unsigned int j; - - /* Make sure that the hash address is actually zeroed. */ - for (j = 0; j < 8; j++) { - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_set_hash_addr(wots_addrx8 + j * 8, 0); - } - - /* Generate sk element. */ - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_prf_addrx8(skx8 + 0 * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N, - skx8 + 1 * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N, - skx8 + 2 * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N, - skx8 + 3 * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N, - skx8 + 4 * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N, - skx8 + 5 * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N, - skx8 + 6 * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N, - skx8 + 7 * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N, - sk_seed, wots_addrx8); -} - -/** - * Computes the chaining function. - * out and in have to be n-byte arrays. - * - * Interprets in as start-th value of the chain. - * addr has to contain the address of the chain. - */ -static void gen_chain(unsigned char *out, const unsigned char *in, - unsigned int start, unsigned int steps, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *state_seeded) { - uint32_t i; - - /* Initialize out with the value at position 'start'. */ - memcpy(out, in, PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N); - - /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_WOTS_W; i++) { - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_set_hash_addr(addr, i); - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_thash_1(out, out, pub_seed, addr, state_seeded); - } -} - -/** - * 8-way parallel version of gen_chain; expects 8x as much space in out, and - * 8x as much space in inx8. Assumes start and step identical across chains. - */ -static void gen_chainx8(unsigned char *outx8, const unsigned char *inx8, - unsigned int start, unsigned int steps, - const unsigned char *pub_seed, uint32_t addrx8[8 * 8], - const hash_state *state_seeded) { - uint32_t i; - unsigned int j; - - /* Initialize outx8 with the value at position 'start'. */ - memcpy(outx8, inx8, 8 * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N); - - /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_WOTS_W; i++) { - for (j = 0; j < 8; j++) { - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_set_hash_addr(addrx8 + j * 8, i); - } - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_thashx8_1(outx8 + 0 * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N, - outx8 + 1 * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N, - outx8 + 2 * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N, - outx8 + 3 * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N, - outx8 + 4 * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N, - outx8 + 5 * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N, - outx8 + 6 * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N, - outx8 + 7 * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N, - outx8 + 0 * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N, - outx8 + 1 * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N, - outx8 + 2 * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N, - outx8 + 3 * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N, - outx8 + 4 * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N, - outx8 + 5 * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N, - outx8 + 6 * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N, - outx8 + 7 * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N, - pub_seed, addrx8, state_seeded); - } -} - -/** - * base_w algorithm as described in draft. - * Interprets an array of bytes as integers in base w. - * This only works when log_w is a divisor of 8. - */ -static void base_w(unsigned int *output, const int out_len, const unsigned char *input) { - int in = 0; - int out = 0; - unsigned char total = 0; - int bits = 0; - int consumed; - - for (consumed = 0; consumed < out_len; consumed++) { - if (bits == 0) { - total = input[in]; - in++; - bits += 8; - } - bits -= PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_WOTS_LOGW; - output[out] = (unsigned int)(total >> bits) & (PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_WOTS_W - 1); - out++; - } -} - -/* Computes the WOTS+ checksum over a message (in base_w). */ -static void wots_checksum(unsigned int *csum_base_w, const unsigned int *msg_base_w) { - unsigned int csum = 0; - unsigned char csum_bytes[(PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_WOTS_LEN2 * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_WOTS_LOGW + 7) / 8]; - unsigned int i; - - /* Compute checksum. */ - for (i = 0; i < PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_WOTS_LEN1; i++) { - csum += PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_WOTS_W - 1 - msg_base_w[i]; - } - - /* Convert checksum to base_w. */ - /* Make sure expected empty zero bits are the least significant bits. */ - csum = csum << (8 - ((PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_WOTS_LEN2 * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_WOTS_LOGW) % 8)); - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); - base_w(csum_base_w, PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_WOTS_LEN2, csum_bytes); -} - -/* Takes a message and derives the matching chain lengths. */ -static void chain_lengths(unsigned int *lengths, const unsigned char *msg) { - base_w(lengths, PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_WOTS_LEN1, msg); - wots_checksum(lengths + PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_WOTS_LEN1, lengths); -} - -/** - * WOTS key generation. Takes a 32 byte sk_seed, expands it to WOTS private key - * elements and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_wots_gen_pk(unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *state_seeded) { - uint32_t i; - unsigned int j; - - uint32_t addrx8[8 * 8]; - unsigned char pkbuf[8 * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N]; - - for (j = 0; j < 8; j++) { - memcpy(addrx8 + j * 8, addr, sizeof(uint32_t) * 8); - } - - /* The last iteration typically does not have complete set of 4 chains, - but because we use pkbuf, this is not an issue -- we still do as many - in parallel as possible. */ - for (i = 0; i < ((PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_WOTS_LEN + 7) & ~0x7); i += 8) { - for (j = 0; j < 8; j++) { - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_set_chain_addr(addrx8 + j * 8, i + j); - } - wots_gen_skx8(pkbuf, sk_seed, addrx8); - gen_chainx8(pkbuf, pkbuf, 0, PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_WOTS_W - 1, pub_seed, addrx8, state_seeded); - for (j = 0; j < 8; j++) { - if (i + j < PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_WOTS_LEN) { - memcpy(pk + (i + j)*PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N, pkbuf + j * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N, PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N); - } - } - } -} - -/** - * Takes a n-byte message and the 32-byte sk_see to compute a signature 'sig'. - */ -void PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_wots_sign(unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_WOTS_LEN; i++) { - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_set_chain_addr(addr, i); - wots_gen_sk(sig + i * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N, sk_seed, addr, state_seeded); - gen_chain(sig + i * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N, sig + i * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N, 0, lengths[i], pub_seed, addr, state_seeded); - } -} - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_WOTS_LEN; i++) { - PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_set_chain_addr(addr, i); - gen_chain(pk + i * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N, sig + i * PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_N, - lengths[i], PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_WOTS_W - 1 - lengths[i], pub_seed, addr, state_seeded); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_avx2/wots.h b/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_avx2/wots.h deleted file mode 100644 index 8946e815b2..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_avx2/wots.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_WOTS_H -#define PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_WOTS_H - -#include "hash_state.h" -#include "params.h" -#include - -/** - * WOTS key generation. Takes a 32 byte seed for the private key, expands it to - * a full WOTS private key and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_wots_gen_pk( - unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -/** - * Takes a n-byte message and the 32-byte seed for the private key to compute a - * signature that is placed at 'sig'. - */ -void PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_wots_sign( - unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *hash_state_seeded); - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHA256128SSIMPLE_AVX2_wots_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_clean/LICENSE b/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_clean/LICENSE deleted file mode 100644 index 670154e353..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_clean/LICENSE +++ /dev/null @@ -1,116 +0,0 @@ -CC0 1.0 Universal - -Statement of Purpose - -The laws of most jurisdictions throughout the world automatically confer -exclusive Copyright and Related Rights (defined below) upon the creator and -subsequent owner(s) (each and all, an "owner") of an original work of -authorship and/or a database (each, a "Work"). - -Certain owners wish to permanently relinquish those rights to a Work for the -purpose of contributing to a commons of creative, cultural and scientific -works ("Commons") that the public can reliably and without fear of later -claims of infringement build upon, modify, incorporate in other works, reuse -and redistribute as freely as possible in any form whatsoever and for any -purposes, including without limitation commercial purposes. These owners may -contribute to the Commons to promote the ideal of a free culture and the -further production of creative, cultural and scientific works, or to gain -reputation or greater distribution for their Work in part through the use and -efforts of others. - -For these and/or other purposes and motivations, and without any expectation -of additional consideration or compensation, the person associating CC0 with a -Work (the "Affirmer"), to the extent that he or she is an owner of Copyright -and Related Rights in the Work, voluntarily elects to apply CC0 to the Work -and publicly distribute the Work under its terms, with knowledge of his or her -Copyright and Related Rights in the Work and the meaning and intended legal -effect of CC0 on those rights. - -1. Copyright and Related Rights. A Work made available under CC0 may be -protected by copyright and related or neighboring rights ("Copyright and -Related Rights"). Copyright and Related Rights include, but are not limited -to, the following: - - i. the right to reproduce, adapt, distribute, perform, display, communicate, - and translate a Work; - - ii. moral rights retained by the original author(s) and/or performer(s); - - iii. publicity and privacy rights pertaining to a person's image or likeness - depicted in a Work; - - iv. rights protecting against unfair competition in regards to a Work, - subject to the limitations in paragraph 4(a), below; - - v. rights protecting the extraction, dissemination, use and reuse of data in - a Work; - - vi. database rights (such as those arising under Directive 96/9/EC of the - European Parliament and of the Council of 11 March 1996 on the legal - protection of databases, and under any national implementation thereof, - including any amended or successor version of such directive); and - - vii. other similar, equivalent or corresponding rights throughout the world - based on applicable law or treaty, and any national implementations thereof. - -2. Waiver. To the greatest extent permitted by, but not in contravention of, -applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and -unconditionally waives, abandons, and surrenders all of Affirmer's Copyright -and Related Rights and associated claims and causes of action, whether now -known or unknown (including existing as well as future claims and causes of -action), in the Work (i) in all territories worldwide, (ii) for the maximum -duration provided by applicable law or treaty (including future time -extensions), (iii) in any current or future medium and for any number of -copies, and (iv) for any purpose whatsoever, including without limitation -commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes -the Waiver for the benefit of each member of the public at large and to the -detriment of Affirmer's heirs and successors, fully intending that such Waiver -shall not be subject to revocation, rescission, cancellation, termination, or -any other legal or equitable action to disrupt the quiet enjoyment of the Work -by the public as contemplated by Affirmer's express Statement of Purpose. - -3. Public License Fallback. Should any part of the Waiver for any reason be -judged legally invalid or ineffective under applicable law, then the Waiver -shall be preserved to the maximum extent permitted taking into account -Affirmer's express Statement of Purpose. In addition, to the extent the Waiver -is so judged Affirmer hereby grants to each affected person a royalty-free, -non transferable, non sublicensable, non exclusive, irrevocable and -unconditional license to exercise Affirmer's Copyright and Related Rights in -the Work (i) in all territories worldwide, (ii) for the maximum duration -provided by applicable law or treaty (including future time extensions), (iii) -in any current or future medium and for any number of copies, and (iv) for any -purpose whatsoever, including without limitation commercial, advertising or -promotional purposes (the "License"). The License shall be deemed effective as -of the date CC0 was applied by Affirmer to the Work. Should any part of the -License for any reason be judged legally invalid or ineffective under -applicable law, such partial invalidity or ineffectiveness shall not -invalidate the remainder of the License, and in such case Affirmer hereby -affirms that he or she will not (i) exercise any of his or her remaining -Copyright and Related Rights in the Work or (ii) assert any associated claims -and causes of action with respect to the Work, in either case contrary to -Affirmer's express Statement of Purpose. - -4. Limitations and Disclaimers. - - a. No trademark or patent rights held by Affirmer are waived, abandoned, - surrendered, licensed or otherwise affected by this document. - - b. Affirmer offers the Work as-is and makes no representations or warranties - of any kind concerning the Work, express, implied, statutory or otherwise, - including without limitation warranties of title, merchantability, fitness - for a particular purpose, non infringement, or the absence of latent or - other defects, accuracy, or the present or absence of errors, whether or not - discoverable, all to the greatest extent permissible under applicable law. - - c. Affirmer disclaims responsibility for clearing rights of other persons - that may apply to the Work or any use thereof, including without limitation - any person's Copyright and Related Rights in the Work. Further, Affirmer - disclaims responsibility for obtaining any necessary consents, permissions - or other rights required for any use of the Work. - - d. Affirmer understands and acknowledges that Creative Commons is not a - party to this document and has no duty or obligation with respect to this - CC0 or use of the Work. - -For more information, please see - diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_clean/address.c b/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_clean/address.c deleted file mode 100644 index f58ec0ca03..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_clean/address.c +++ /dev/null @@ -1,78 +0,0 @@ -#include - -#include "address.h" -#include "params.h" -#include "utils.h" - -void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]) { - int i; - - for (i = 0; i < 8; i++) { - PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_ull_to_bytes( - bytes + i * 4, 4, addr[i]); - } -} - -void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_set_layer_addr( - uint32_t addr[8], uint32_t layer) { - addr[0] = layer; -} - -void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_set_tree_addr( - uint32_t addr[8], uint64_t tree) { - addr[1] = 0; - addr[2] = (uint32_t) (tree >> 32); - addr[3] = (uint32_t) tree; -} - -void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_set_type( - uint32_t addr[8], uint32_t type) { - addr[4] = type; -} - -void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; -} - -/* These functions are used for OTS addresses. */ - -void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_set_keypair_addr( - uint32_t addr[8], uint32_t keypair) { - addr[5] = keypair; -} - -void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; - out[5] = in[5]; -} - -void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_set_chain_addr( - uint32_t addr[8], uint32_t chain) { - addr[6] = chain; -} - -void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_set_hash_addr( - uint32_t addr[8], uint32_t hash) { - addr[7] = hash; -} - -/* These functions are used for all hash tree addresses (including FORS). */ - -void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_set_tree_height( - uint32_t addr[8], uint32_t tree_height) { - addr[6] = tree_height; -} - -void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_set_tree_index( - uint32_t addr[8], uint32_t tree_index) { - addr[7] = tree_index; -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_clean/address.h b/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_clean/address.h deleted file mode 100644 index 265cb76fa7..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_clean/address.h +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_ADDRESS_H -#define PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_ADDRESS_H - -#include - -#define PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_ADDR_TYPE_WOTS 0 -#define PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_ADDR_TYPE_WOTSPK 1 -#define PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_ADDR_TYPE_HASHTREE 2 -#define PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_ADDR_TYPE_FORSTREE 3 -#define PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_ADDR_TYPE_FORSPK 4 - -void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]); - -void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_set_layer_addr( - uint32_t addr[8], uint32_t layer); - -void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_set_tree_addr( - uint32_t addr[8], uint64_t tree); - -void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_set_type( - uint32_t addr[8], uint32_t type); - -/* Copies the layer and tree part of one address into the other */ -void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for WOTS and FORS addresses. */ - -void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_set_keypair_addr( - uint32_t addr[8], uint32_t keypair); - -void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_set_chain_addr( - uint32_t addr[8], uint32_t chain); - -void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_set_hash_addr( - uint32_t addr[8], uint32_t hash); - -void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for all hash tree addresses (including FORS). */ - -void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_set_tree_height( - uint32_t addr[8], uint32_t tree_height); - -void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_set_tree_index( - uint32_t addr[8], uint32_t tree_index); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_clean/api.h b/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_clean/api.h deleted file mode 100644 index 126e4fc146..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_clean/api.h +++ /dev/null @@ -1,81 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_API_H -#define PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_API_H - -#include -#include - - - -#define PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_CRYPTO_ALGNAME "SPHINCS+" - -#define PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_CRYPTO_SECRETKEYBYTES 64 -#define PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_CRYPTO_PUBLICKEYBYTES 32 -#define PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_CRYPTO_BYTES 7856 -#define PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_CRYPTO_SEEDBYTES 48 - - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_clean/fors.c b/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_clean/fors.c deleted file mode 100644 index 35a50fb3ad..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_clean/fors.c +++ /dev/null @@ -1,161 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "fors.h" -#include "hash.h" -#include "hash_state.h" -#include "thash.h" -#include "utils.h" - -static void fors_gen_sk(unsigned char *sk, const unsigned char *sk_seed, - uint32_t fors_leaf_addr[8], const hash_state *hash_state_seeded) { - PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_prf_addr( - sk, sk_seed, fors_leaf_addr, hash_state_seeded); -} - -static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, - const unsigned char *pub_seed, - uint32_t fors_leaf_addr[8], - const hash_state *hash_state_seeded) { - PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_thash_1( - leaf, sk, pub_seed, fors_leaf_addr, hash_state_seeded); -} - -static void fors_gen_leaf(unsigned char *leaf, const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx, const uint32_t fors_tree_addr[8], - const hash_state *hash_state_seeded) { - uint32_t fors_leaf_addr[8] = {0}; - - /* Only copy the parts that must be kept in fors_leaf_addr. */ - PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_copy_keypair_addr( - fors_leaf_addr, fors_tree_addr); - PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_set_type( - fors_leaf_addr, PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_set_tree_index( - fors_leaf_addr, addr_idx); - - fors_gen_sk(leaf, sk_seed, fors_leaf_addr, hash_state_seeded); - fors_sk_to_leaf(leaf, leaf, pub_seed, fors_leaf_addr, hash_state_seeded); -} - -/** - * Interprets m as PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_FORS_HEIGHT-bit unsigned integers. - * Assumes m contains at least PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_FORS_TREES bits. - * Assumes indices has space for PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_FORS_TREES integers. - */ -static void message_to_indices(uint32_t *indices, const unsigned char *m) { - unsigned int i, j; - unsigned int offset = 0; - - for (i = 0; i < PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_FORS_TREES; i++) { - indices[i] = 0; - for (j = 0; j < PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_FORS_HEIGHT; j++) { - indices[i] ^= (((uint32_t)m[offset >> 3] >> (offset & 0x7)) & 0x1) << j; - offset++; - } - } -} - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_fors_sign( - unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *hash_state_seeded) { - uint32_t indices[PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_FORS_TREES]; - unsigned char roots[PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_FORS_TREES * PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_N]; - uint32_t fors_tree_addr[8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_copy_keypair_addr( - fors_tree_addr, fors_addr); - PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_copy_keypair_addr( - fors_pk_addr, fors_addr); - - PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_set_type( - fors_tree_addr, PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_set_type( - fors_pk_addr, PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_FORS_TREES; i++) { - idx_offset = i * (1 << PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_FORS_HEIGHT); - - PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_set_tree_height( - fors_tree_addr, 0); - PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_set_tree_index( - fors_tree_addr, indices[i] + idx_offset); - - /* Include the secret key part that produces the selected leaf node. */ - fors_gen_sk(sig, sk_seed, fors_tree_addr, hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_N; - - /* Compute the authentication path for this leaf node. */ - PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_treehash_FORS_HEIGHT( - roots + i * PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_N, sig, sk_seed, pub_seed, - indices[i], idx_offset, fors_gen_leaf, fors_tree_addr, - hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_N * PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_thash_FORS_TREES( - pk, roots, pub_seed, fors_pk_addr, hash_state_seeded); -} - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_fors_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, const uint32_t fors_addr[8], - const hash_state *hash_state_seeded) { - uint32_t indices[PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_FORS_TREES]; - unsigned char roots[PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_FORS_TREES * PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_N]; - unsigned char leaf[PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_N]; - uint32_t fors_tree_addr[8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_copy_keypair_addr(fors_tree_addr, fors_addr); - PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_copy_keypair_addr(fors_pk_addr, fors_addr); - - PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_set_type(fors_tree_addr, PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_set_type(fors_pk_addr, PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_FORS_TREES; i++) { - idx_offset = i * (1 << PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_FORS_HEIGHT); - - PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_set_tree_height(fors_tree_addr, 0); - PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Derive the leaf from the included secret key part. */ - fors_sk_to_leaf(leaf, sig, pub_seed, fors_tree_addr, hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_N; - - /* Derive the corresponding root node of this tree. */ - PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_compute_root(roots + i * PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_N, leaf, indices[i], idx_offset, sig, - PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_FORS_HEIGHT, pub_seed, fors_tree_addr, hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_N * PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_thash_FORS_TREES(pk, roots, pub_seed, fors_pk_addr, hash_state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_clean/fors.h b/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_clean/fors.h deleted file mode 100644 index a9ebebf956..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_clean/fors.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_FORS_H -#define PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_FORS_H - -#include - -#include "hash_state.h" -#include "params.h" - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_fors_sign( - unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *hash_state_seeded); - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_fors_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, const uint32_t fors_addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_clean/hash.h b/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_clean/hash.h deleted file mode 100644 index 5bd73b349a..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_clean/hash.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_HASH_H -#define PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_HASH_H - -#include "hash_state.h" - -#include -#include - -void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_initialize_hash_function( - hash_state *hash_state_seeded, - const unsigned char *pub_seed, const unsigned char *sk_seed); - -void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_destroy_hash_function(hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_clean/hash_sha256.c b/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_clean/hash_sha256.c deleted file mode 100644 index b2334d1917..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_clean/hash_sha256.c +++ /dev/null @@ -1,162 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "utils.h" - -#include "sha2.h" -#include "sha256.h" - -/* For SHA256, there is no immediate reason to initialize at the start, - so this function is an empty operation. */ -void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_initialize_hash_function( - hash_state *hash_state_seeded, - const unsigned char *pub_seed, const unsigned char *sk_seed) { - PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_seed_state(hash_state_seeded, pub_seed); - (void)sk_seed; /* Suppress an 'unused parameter' warning. */ -} - -/* Clean up hash state */ -void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_destroy_hash_function(hash_state *hash_state_seeded) { - sha256_inc_ctx_release(hash_state_seeded); -} - -/* - * Computes PRF(key, addr), given a secret key of PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_N bytes and an address - */ -void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded) { - unsigned char buf[PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_N + PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_SHA256_ADDR_BYTES]; - unsigned char outbuf[PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_SHA256_OUTPUT_BYTES]; - - memcpy(buf, key, PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_N); - PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_compress_address(buf + PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_N, addr); - - sha256(outbuf, buf, PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_N + PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_SHA256_ADDR_BYTES); - memcpy(out, outbuf, PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_N); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} - -/** - * Computes the message-dependent randomness R, using a secret seed as a key - * for HMAC, and an optional randomization value prefixed to the message. - * This requires m to have at least PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_SHA256_BLOCK_BYTES + PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_N space - * available in front of the pointer, i.e. before the message to use for the - * prefix. This is necessary to prevent having to move the message around (and - * allocate memory for it). - */ -void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, const hash_state *hash_state_seeded) { - unsigned char buf[PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_SHA256_BLOCK_BYTES + PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_SHA256_OUTPUT_BYTES]; - sha256ctx state; - int i; - - /* This implements HMAC-SHA256 */ - for (i = 0; i < PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_N; i++) { - buf[i] = 0x36 ^ sk_prf[i]; - } - memset(buf + PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_N, 0x36, PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_N); - - sha256_inc_init(&state); - sha256_inc_blocks(&state, buf, 1); - - memcpy(buf, optrand, PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_N); - - /* If optrand + message cannot fill up an entire block */ - if (PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_N + mlen < PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_SHA256_BLOCK_BYTES) { - memcpy(buf + PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_N, m, mlen); - sha256_inc_finalize(buf + PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_SHA256_BLOCK_BYTES, &state, - buf, mlen + PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_N); - } - /* Otherwise first fill a block, so that finalize only uses the message */ - else { - memcpy(buf + PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_N, m, PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_N); - sha256_inc_blocks(&state, buf, 1); - - m += PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_N; - mlen -= PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_N; - sha256_inc_finalize(buf + PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_SHA256_BLOCK_BYTES, &state, m, mlen); - } - - for (i = 0; i < PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_N; i++) { - buf[i] = 0x5c ^ sk_prf[i]; - } - memset(buf + PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_N, 0x5c, PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_N); - - sha256(buf, buf, PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_SHA256_BLOCK_BYTES + PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_SHA256_OUTPUT_BYTES); - memcpy(R, buf, PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_N); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} - -/** - * Computes the message hash using R, the public key, and the message. - * Outputs the message digest and the index of the leaf. The index is split in - * the tree index and the leaf index, for convenient copying to an address. - */ -void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded) { -#define PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_TREE_BITS (PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_TREE_HEIGHT * (PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_D - 1)) -#define PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_TREE_BYTES ((PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_TREE_BITS + 7) / 8) -#define PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_LEAF_BITS PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_TREE_HEIGHT -#define PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_LEAF_BYTES ((PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_LEAF_BITS + 7) / 8) -#define PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_DGST_BYTES (PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_FORS_MSG_BYTES + PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_TREE_BYTES + PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_LEAF_BYTES) - - unsigned char seed[PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_SHA256_OUTPUT_BYTES + 4]; - - /* Round to nearest multiple of PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_SHA256_BLOCK_BYTES */ -#define PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_INBLOCKS (((PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_N + PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_PK_BYTES + PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_SHA256_BLOCK_BYTES - 1) & \ - -PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_SHA256_BLOCK_BYTES) / PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_SHA256_BLOCK_BYTES) - unsigned char inbuf[PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_INBLOCKS * PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_SHA256_BLOCK_BYTES]; - - unsigned char buf[PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_DGST_BYTES]; - unsigned char *bufp = buf; - sha256ctx state; - - sha256_inc_init(&state); - - memcpy(inbuf, R, PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_N); - memcpy(inbuf + PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_N, pk, PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_PK_BYTES); - - /* If R + pk + message cannot fill up an entire block */ - if (PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_N + PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_PK_BYTES + mlen < PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_INBLOCKS * PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_SHA256_BLOCK_BYTES) { - memcpy(inbuf + PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_N + PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_PK_BYTES, m, mlen); - sha256_inc_finalize(seed, &state, inbuf, PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_N + PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_PK_BYTES + mlen); - } - /* Otherwise first fill a block, so that finalize only uses the message */ - else { - memcpy(inbuf + PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_N + PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_PK_BYTES, m, - PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_INBLOCKS * PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_N - PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_PK_BYTES); - sha256_inc_blocks(&state, inbuf, PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_INBLOCKS); - - m += PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_INBLOCKS * PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_N - PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_PK_BYTES; - mlen -= PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_INBLOCKS * PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_N - PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_PK_BYTES; - sha256_inc_finalize(seed, &state, m, mlen); - } - - /* By doing this in two steps, we prevent hashing the message twice; - otherwise each iteration in MGF1 would hash the message again. */ - PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_mgf1(bufp, PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_DGST_BYTES, seed, PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_SHA256_OUTPUT_BYTES); - - memcpy(digest, bufp, PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_FORS_MSG_BYTES); - bufp += PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_FORS_MSG_BYTES; - - *tree = PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_bytes_to_ull(bufp, PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_TREE_BYTES); - *tree &= (~(uint64_t)0) >> (64 - PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_TREE_BITS); - bufp += PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_TREE_BYTES; - - *leaf_idx = (uint32_t)PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_bytes_to_ull( - bufp, PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_LEAF_BYTES); - *leaf_idx &= (~(uint32_t)0) >> (32 - PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_LEAF_BITS); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_clean/hash_state.h b/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_clean/hash_state.h deleted file mode 100644 index 19fc335e27..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_clean/hash_state.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef SPX_HASH_STATE_H -#define SPX_HASH_STATE_H - -/** - * Defines the type of the hash function state. - * - * Don't be fooled into thinking this instance of SPHINCS+ isn't stateless! - * - * From Section 7.2.2 from the SPHINCS+ round-2 specification: - * - * Each of the instances of the tweakable hash function take PK.seed as its - * first input, which is constant for a given key pair – and, thus, across - * a single signature. This leads to a lot of redundant computation. To remedy - * this, we pad PK.seed to the length of a full 64-byte SHA-256 input block. - * Because of the Merkle-Damgård construction that underlies SHA-256, this - * allows for reuse of the intermediate SHA-256 state after the initial call to - * the compression function which improves performance. - * - * We pass this hash state around in functions, because otherwise we need to - * have a global variable. - */ - -#include "sha2.h" -#define hash_state sha256ctx - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_clean/params.h b/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_clean/params.h deleted file mode 100644 index 1c922f492b..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_clean/params.h +++ /dev/null @@ -1,53 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_PARAMS_H -#define PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_PARAMS_H - -/* Hash output length in bytes. */ -#define PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_N 16 -/* Height of the hypertree. */ -#define PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_FULL_HEIGHT 63 -/* Number of subtree layer. */ -#define PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_D 7 -/* FORS tree dimensions. */ -#define PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_FORS_HEIGHT 12 -#define PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_FORS_TREES 14 -/* Winternitz parameter, */ -#define PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_WOTS_W 16 - -/* The hash function is defined by linking a different hash.c file, as opposed - to setting a #define constant. */ - -/* For clarity */ -#define PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_ADDR_BYTES 32 - -/* WOTS parameters. */ -#define PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_WOTS_LOGW 4 - -#define PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_WOTS_LEN1 (8 * PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_N / PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_WOTS_LOGW) - -/* PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#define PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_WOTS_LEN2 3 - -#define PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_WOTS_LEN (PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_WOTS_LEN1 + PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_WOTS_LEN2) -#define PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_WOTS_BYTES (PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_WOTS_LEN * PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_N) -#define PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_WOTS_PK_BYTES PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_WOTS_BYTES - -/* Subtree size. */ -#define PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_TREE_HEIGHT (PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_FULL_HEIGHT / PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_D) - -/* FORS parameters. */ -#define PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_FORS_MSG_BYTES ((PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_FORS_TREES + 7) / 8) -#define PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_FORS_BYTES ((PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_FORS_HEIGHT + 1) * PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_FORS_TREES * PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_N) -#define PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_FORS_PK_BYTES PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_N - -/* Resulting SPX sizes. */ -#define PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_BYTES (PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_N + PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_FORS_BYTES + PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_D * PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_WOTS_BYTES +\ - PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_FULL_HEIGHT * PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_N) -#define PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_PK_BYTES (2 * PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_N) -#define PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_SK_BYTES (2 * PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_N + PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_PK_BYTES) - -/* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ -#define PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_OPTRAND_BYTES 32 - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_clean/sha256.c b/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_clean/sha256.c deleted file mode 100644 index f801acac92..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_clean/sha256.c +++ /dev/null @@ -1,71 +0,0 @@ -/* Based on the public domain implementation in - * crypto_hash/sha512/ref/ from http://bench.cr.yp.to/supercop.html - * by D. J. Bernstein */ - -#include -#include -#include - -#include "sha2.h" -#include "sha256.h" -#include "utils.h" - -/* - * Compresses an address to a 22-byte sequence. - * This reduces the number of required SHA256 compression calls, as the last - * block of input is padded with at least 65 bits. - */ -void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_compress_address(unsigned char *out, const uint32_t addr[8]) { - PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_ull_to_bytes(out, 1, addr[0]); /* drop 3 bytes of the layer field */ - PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_ull_to_bytes(out + 1, 4, addr[2]); /* drop the highest tree address word */ - PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_ull_to_bytes(out + 5, 4, addr[3]); - PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_ull_to_bytes(out + 9, 1, addr[4]); /* drop 3 bytes of the type field */ - PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_ull_to_bytes(out + 10, 4, addr[5]); - PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_ull_to_bytes(out + 14, 4, addr[6]); - PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_ull_to_bytes(out + 18, 4, addr[7]); -} - -/** - * Requires 'input_plus_four_bytes' to have 'inlen' + 4 bytes, so that the last - * four bytes can be used for the counter. Typically 'input' is merely a seed. - * Outputs outlen number of bytes - */ -void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_mgf1( - unsigned char *out, unsigned long outlen, - unsigned char *input_plus_four_bytes, unsigned long inlen) { - unsigned char outbuf[PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_SHA256_OUTPUT_BYTES]; - unsigned long i; - - /* While we can fit in at least another full block of SHA256 output.. */ - for (i = 0; (i + 1)*PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_SHA256_OUTPUT_BYTES <= outlen; i++) { - PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_ull_to_bytes(input_plus_four_bytes + inlen, 4, i); - sha256(out, input_plus_four_bytes, inlen + 4); - out += PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_SHA256_OUTPUT_BYTES; - } - /* Until we cannot anymore, and we fill the remainder. */ - if (outlen > i * PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_SHA256_OUTPUT_BYTES) { - PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_ull_to_bytes(input_plus_four_bytes + inlen, 4, i); - sha256(outbuf, input_plus_four_bytes, inlen + 4); - memcpy(out, outbuf, outlen - i * PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_SHA256_OUTPUT_BYTES); - } -} - - -/** - * Absorb the constant pub_seed using one round of the compression function - * This initializes hash_state_seeded, which can then be reused in thash - **/ -void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_seed_state(sha256ctx *hash_state_seeded, const unsigned char *pub_seed) { - uint8_t block[PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_SHA256_BLOCK_BYTES]; - size_t i; - - for (i = 0; i < PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_N; ++i) { - block[i] = pub_seed[i]; - } - for (i = PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_N; i < PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_SHA256_BLOCK_BYTES; ++i) { - block[i] = 0; - } - - sha256_inc_init(hash_state_seeded); - sha256_inc_blocks(hash_state_seeded, block, 1); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_clean/sha256.h b/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_clean/sha256.h deleted file mode 100644 index fa9bc9ba7e..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_clean/sha256.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_SHA256_H -#define PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_SHA256_H - -#define PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_SHA256_BLOCK_BYTES 64 -#define PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_SHA256_OUTPUT_BYTES 32 /* This does not necessarily equal PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_N */ -#define PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_SHA256_ADDR_BYTES 22 - -#include -#include - -#include "sha2.h" - -void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_compress_address(unsigned char *out, const uint32_t addr[8]); - -void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_mgf1( - unsigned char *out, unsigned long outlen, - unsigned char *input_plus_four_bytes, unsigned long inlen); - -void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_seed_state(sha256ctx *hash_state_seeded, const unsigned char *pub_seed); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_clean/sign.c b/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_clean/sign.c deleted file mode 100644 index 276ef8f7e8..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_clean/sign.c +++ /dev/null @@ -1,356 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "api.h" -#include "fors.h" -#include "hash.h" -#include "hash_state.h" -#include "params.h" -#include "randombytes.h" -#include "thash.h" -#include "utils.h" -#include "wots.h" - -/** - * Computes the leaf at a given address. First generates the WOTS key pair, - * then computes leaf by hashing horizontally. - */ -static void wots_gen_leaf(unsigned char *leaf, const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx, const uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - unsigned char pk[PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_WOTS_BYTES]; - uint32_t wots_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_set_type( - wots_addr, PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_set_type( - wots_pk_addr, PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_ADDR_TYPE_WOTSPK); - - PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_set_keypair_addr( - wots_addr, addr_idx); - PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_wots_gen_pk( - pk, sk_seed, pub_seed, wots_addr, hash_state_seeded); - - PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_copy_keypair_addr( - wots_pk_addr, wots_addr); - PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_thash_WOTS_LEN( - leaf, pk, pub_seed, wots_pk_addr, hash_state_seeded); -} - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_crypto_sign_secretkeybytes(void) { - return PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_CRYPTO_SECRETKEYBYTES; -} - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_crypto_sign_publickeybytes(void) { - return PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_CRYPTO_PUBLICKEYBYTES; -} - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_crypto_sign_bytes(void) { - return PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_CRYPTO_BYTES; -} - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_crypto_sign_seedbytes(void) { - return PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_CRYPTO_SEEDBYTES; -} - -/* - * Generates an SPX key pair given a seed of length - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed) { - /* We do not need the auth path in key generation, but it simplifies the - code to have just one treehash routine that computes both root and path - in one function. */ - unsigned char auth_path[PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_TREE_HEIGHT * PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_N]; - uint32_t top_tree_addr[8] = {0}; - hash_state hash_state_seeded; - - PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_set_layer_addr( - top_tree_addr, PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_D - 1); - PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_set_type( - top_tree_addr, PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_ADDR_TYPE_HASHTREE); - - /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ - memcpy(sk, seed, PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_CRYPTO_SEEDBYTES); - - memcpy(pk, sk + 2 * PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_N, PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_initialize_hash_function(&hash_state_seeded, pk, sk); - - /* Compute root node of the top-most subtree. */ - PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_treehash_TREE_HEIGHT( - sk + 3 * PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_N, auth_path, sk, sk + 2 * PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_N, 0, 0, - wots_gen_leaf, top_tree_addr, &hash_state_seeded); - - memcpy(pk + PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_N, sk + 3 * PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_N, PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_N); - - PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_destroy_hash_function(&hash_state_seeded); - return 0; -} - -/* - * Generates an SPX key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk) { - unsigned char seed[PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_CRYPTO_SEEDBYTES]; - randombytes(seed, PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_CRYPTO_SEEDBYTES); - PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_crypto_sign_seed_keypair( - pk, sk, seed); - - return 0; -} - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - const unsigned char *sk_seed = sk; - const unsigned char *sk_prf = sk + PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_N; - const unsigned char *pk = sk + 2 * PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_N; - const unsigned char *pub_seed = pk; - - unsigned char optrand[PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_N]; - unsigned char mhash[PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_FORS_MSG_BYTES]; - unsigned char root[PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_N]; - uint32_t i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - - hash_state hash_state_seeded; - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_initialize_hash_function( - &hash_state_seeded, - pub_seed, sk_seed); - - PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_set_type( - wots_addr, PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_set_type( - tree_addr, PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_ADDR_TYPE_HASHTREE); - - /* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ - randombytes(optrand, PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_N); - /* Compute the digest randomization value. */ - PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_gen_message_random( - sig, sk_prf, optrand, m, mlen, &hash_state_seeded); - - /* Derive the message digest and leaf index from R, PK and M. */ - PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_N; - - PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); - - /* Sign the message hash using FORS. */ - PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_fors_sign( - sig, root, mhash, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_FORS_BYTES; - - for (i = 0; i < PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_D; i++) { - PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_set_tree_addr(tree_addr, tree); - - PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); - - /* Compute a WOTS signature. */ - PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_wots_sign( - sig, root, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_WOTS_BYTES; - - /* Compute the authentication path for the used WOTS leaf. */ - PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_treehash_TREE_HEIGHT( - root, sig, sk_seed, pub_seed, idx_leaf, 0, - wots_gen_leaf, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_TREE_HEIGHT * PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_TREE_HEIGHT; - } - - *siglen = PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_BYTES; - - PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_destroy_hash_function(&hash_state_seeded); - return 0; -} - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk) { - const unsigned char *pub_seed = pk; - const unsigned char *pub_root = pk + PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_N; - unsigned char mhash[PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_FORS_MSG_BYTES]; - unsigned char wots_pk[PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_WOTS_BYTES]; - unsigned char root[PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_N]; - unsigned char leaf[PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_N]; - unsigned int i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - hash_state hash_state_seeded; - - if (siglen != PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_BYTES) { - return -1; - } - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_initialize_hash_function( - &hash_state_seeded, - pub_seed, NULL); - - PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_set_type( - wots_addr, PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_set_type( - tree_addr, PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_ADDR_TYPE_HASHTREE); - PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_set_type( - wots_pk_addr, PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_ADDR_TYPE_WOTSPK); - - /* Derive the message digest and leaf index from R || PK || M. */ - /* The additional PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_N is a result of the hash domain separator. */ - PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_N; - - /* Layer correctly defaults to 0, so no need to set_layer_addr */ - PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); - - PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_fors_pk_from_sig( - root, sig, mhash, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_FORS_BYTES; - - /* For each subtree.. */ - for (i = 0; i < PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_D; i++) { - PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_set_tree_addr(tree_addr, tree); - - PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); - - PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_copy_keypair_addr( - wots_pk_addr, wots_addr); - - /* The WOTS public key is only correct if the signature was correct. */ - /* Initially, root is the FORS pk, but on subsequent iterations it is - the root of the subtree below the currently processed subtree. */ - PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_wots_pk_from_sig( - wots_pk, sig, root, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_WOTS_BYTES; - - /* Compute the leaf node using the WOTS public key. */ - PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_thash_WOTS_LEN( - leaf, wots_pk, pub_seed, wots_pk_addr, &hash_state_seeded); - - /* Compute the root node of this subtree. */ - PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_compute_root( - root, leaf, idx_leaf, 0, sig, PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_TREE_HEIGHT, - pub_seed, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_TREE_HEIGHT * PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_TREE_HEIGHT; - } - - PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_destroy_hash_function(&hash_state_seeded); - /* Check if the root node equals the root node in the public key. */ - if (memcmp(root, pub_root, PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_N) != 0) { - return -1; - } - - return 0; -} - - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - size_t siglen; - - PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_crypto_sign_signature( - sm, &siglen, m, mlen, sk); - - memmove(sm + PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_BYTES, m, mlen); - *smlen = siglen + mlen; - - return 0; -} - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk) { - /* The API caller does not necessarily know what size a signature should be - but SPHINCS+ signatures are always exactly PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_BYTES. */ - if (smlen < PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_BYTES) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - *mlen = smlen - PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_BYTES; - - if (PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_crypto_sign_verify( - sm, PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_BYTES, sm + PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_BYTES, *mlen, pk)) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - /* If verification was successful, move the message to the right place. */ - memmove(m, sm + PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_BYTES, *mlen); - - return 0; -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_clean/thash.h b/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_clean/thash.h deleted file mode 100644 index d17f8591fd..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_clean/thash.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_THASH_H -#define PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_THASH_H - -#include "hash_state.h" - -#include - -void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_clean/thash_sha256_simple.c b/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_clean/thash_sha256_simple.c deleted file mode 100644 index 4695df9818..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_clean/thash_sha256_simple.c +++ /dev/null @@ -1,75 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "thash.h" - -#include "sha2.h" -#include "sha256.h" - -/** - * Takes an array of inblocks concatenated arrays of PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_N bytes. - */ -static void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_thash( - unsigned char *out, unsigned char *buf, - const unsigned char *in, unsigned int inblocks, - const unsigned char *pub_seed, uint32_t addr[8], - const sha256ctx *hash_state_seeded) { - - unsigned char outbuf[PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_SHA256_OUTPUT_BYTES]; - sha256ctx sha2_state; - - (void)pub_seed; /* Suppress an 'unused parameter' warning. */ - - /* Retrieve precomputed state containing pub_seed */ - sha256_inc_ctx_clone(&sha2_state, hash_state_seeded); - - PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_compress_address(buf, addr); - memcpy(buf + PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_SHA256_ADDR_BYTES, in, inblocks * PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_N); - - sha256_inc_finalize(outbuf, &sha2_state, buf, PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_N); - memcpy(out, outbuf, PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_N); -} - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const sha256ctx *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_SHA256_ADDR_BYTES + 1 * PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_N]; - PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_thash( - out, buf, in, 1, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const sha256ctx *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_SHA256_ADDR_BYTES + 2 * PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_N]; - PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_thash( - out, buf, in, 2, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const sha256ctx *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_SHA256_ADDR_BYTES + PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_WOTS_LEN * PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_N]; - PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_thash( - out, buf, in, PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_WOTS_LEN, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const sha256ctx *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_SHA256_ADDR_BYTES + PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_FORS_TREES * PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_N]; - PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_thash( - out, buf, in, PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_FORS_TREES, pub_seed, addr, hash_state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_clean/utils.c b/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_clean/utils.c deleted file mode 100644 index ef0ab916e8..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_clean/utils.c +++ /dev/null @@ -1,199 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "hash_state.h" -#include "params.h" -#include "thash.h" -#include "utils.h" - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in) { - - /* Iterate over out in decreasing order, for big-endianness. */ - for (size_t i = outlen; i > 0; i--) { - out[i - 1] = in & 0xff; - in = in >> 8; - } -} - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_bytes_to_ull( - const unsigned char *in, size_t inlen) { - unsigned long long retval = 0; - - for (size_t i = 0; i < inlen; i++) { - retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); - } - return retval; -} - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - uint32_t i; - unsigned char buffer[2 * PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_N]; - - /* If leaf_idx is odd (last bit = 1), current path element is a right child - and auth_path has to go left. Otherwise it is the other way around. */ - if (leaf_idx & 1) { - memcpy(buffer + PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_N, leaf, PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_N); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_N); - } else { - memcpy(buffer, leaf, PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_N); - memcpy(buffer + PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_N, auth_path, PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_N); - } - auth_path += PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_N; - - for (i = 0; i < tree_height - 1; i++) { - leaf_idx >>= 1; - idx_offset >>= 1; - /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_set_tree_height(addr, i + 1); - PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_set_tree_index( - addr, leaf_idx + idx_offset); - - /* Pick the right or left neighbor, depending on parity of the node. */ - if (leaf_idx & 1) { - PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_thash_2( - buffer + PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_N, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_N); - } else { - PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_thash_2( - buffer, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer + PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_N, auth_path, PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_N); - } - auth_path += PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_N; - } - - /* The last iteration is exceptional; we do not copy an auth_path node. */ - leaf_idx >>= 1; - idx_offset >>= 1; - PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_set_tree_height(addr, tree_height); - PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_set_tree_index( - addr, leaf_idx + idx_offset); - PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_thash_2( - root, buffer, pub_seed, addr, hash_state_seeded); -} - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -static void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_treehash( - unsigned char *root, unsigned char *auth_path, - unsigned char *stack, unsigned int *heights, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - - unsigned int offset = 0; - uint32_t idx; - uint32_t tree_idx; - - for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { - /* Add the next leaf node to the stack. */ - gen_leaf(stack + offset * PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_N, - sk_seed, pub_seed, idx + idx_offset, tree_addr, - hash_state_seeded); - offset++; - heights[offset - 1] = 0; - - /* If this is a node we need for the auth path.. */ - if ((leaf_idx ^ 0x1) == idx) { - memcpy(auth_path, stack + (offset - 1)*PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_N, PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_N); - } - - /* While the top-most nodes are of equal height.. */ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { - /* Compute index of the new node, in the next layer. */ - tree_idx = (idx >> (heights[offset - 1] + 1)); - - /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_set_tree_height( - tree_addr, heights[offset - 1] + 1); - PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_set_tree_index( - tree_addr, tree_idx + (idx_offset >> (heights[offset - 1] + 1))); - /* Hash the top-most nodes from the stack together. */ - PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_thash_2( - stack + (offset - 2)*PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_N, stack + (offset - 2)*PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_N, - pub_seed, tree_addr, hash_state_seeded); - offset--; - /* Note that the top-most node is now one layer higher. */ - heights[offset - 1]++; - - /* If this is a node we need for the auth path.. */ - if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_path + heights[offset - 1]*PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_N, - stack + (offset - 1)*PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_N, PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_N); - } - } - } - memcpy(root, stack, PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_N); -} - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_FORS_HEIGHT + 1)*PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_N]; - unsigned int heights[PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_FORS_HEIGHT + 1]; - - PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_FORS_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_TREE_HEIGHT + 1)*PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_N]; - unsigned int heights[PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_TREE_HEIGHT + 1]; - - PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_TREE_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_clean/utils.h b/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_clean/utils.h deleted file mode 100644 index 2ae62c52fd..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_clean/utils.h +++ /dev/null @@ -1,64 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_UTILS_H -#define PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_UTILS_H - -#include "hash_state.h" -#include "params.h" -#include -#include - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in); - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_bytes_to_ull( - const unsigned char *in, size_t inlen); - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_clean/wots.c b/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_clean/wots.c deleted file mode 100644 index 0f74f47a03..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_clean/wots.c +++ /dev/null @@ -1,167 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "hash_state.h" -#include "params.h" -#include "thash.h" -#include "utils.h" -#include "wots.h" - -// TODO clarify address expectations, and make them more uniform. -// TODO i.e. do we expect types to be set already? -// TODO and do we expect modifications or copies? - -/** - * Computes the starting value for a chain, i.e. the secret key. - * Expects the address to be complete up to the chain address. - */ -static void wots_gen_sk(unsigned char *sk, const unsigned char *sk_seed, - uint32_t wots_addr[8], - const hash_state *hash_state_seeded) { - /* Make sure that the hash address is actually zeroed. */ - PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_set_hash_addr(wots_addr, 0); - - /* Generate sk element. */ - PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_prf_addr(sk, sk_seed, wots_addr, hash_state_seeded); -} - -/** - * Computes the chaining function. - * out and in have to be n-byte arrays. - * - * Interprets in as start-th value of the chain. - * addr has to contain the address of the chain. - */ -static void gen_chain(unsigned char *out, const unsigned char *in, - unsigned int start, unsigned int steps, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - uint32_t i; - - /* Initialize out with the value at position 'start'. */ - memcpy(out, in, PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_N); - - /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_WOTS_W; i++) { - PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_set_hash_addr(addr, i); - PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_thash_1( - out, out, pub_seed, addr, hash_state_seeded); - } -} - -/** - * base_w algorithm as described in draft. - * Interprets an array of bytes as integers in base w. - * This only works when log_w is a divisor of 8. - */ -static void base_w(unsigned int *output, const size_t out_len, - const unsigned char *input) { - size_t in = 0; - size_t out = 0; - unsigned char total = 0; - unsigned int bits = 0; - size_t consumed; - - for (consumed = 0; consumed < out_len; consumed++) { - if (bits == 0) { - total = input[in]; - in++; - bits += 8; - } - bits -= PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_WOTS_LOGW; - output[out] = (unsigned int)((total >> bits) & (PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_WOTS_W - 1)); - out++; - } -} - -/* Computes the WOTS+ checksum over a message (in base_w). */ -static void wots_checksum(unsigned int *csum_base_w, - const unsigned int *msg_base_w) { - unsigned int csum = 0; - unsigned char csum_bytes[(PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_WOTS_LEN2 * PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_WOTS_LOGW + 7) / 8]; - unsigned int i; - - /* Compute checksum. */ - for (i = 0; i < PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_WOTS_LEN1; i++) { - csum += PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_WOTS_W - 1 - msg_base_w[i]; - } - - /* Convert checksum to base_w. */ - /* Make sure expected empty zero bits are the least significant bits. */ - csum = csum << (8 - ((PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_WOTS_LEN2 * PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_WOTS_LOGW) % 8)); - PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_ull_to_bytes( - csum_bytes, sizeof(csum_bytes), csum); - base_w(csum_base_w, PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_WOTS_LEN2, csum_bytes); -} - -/* Takes a message and derives the matching chain lengths. */ -static void chain_lengths(unsigned int *lengths, const unsigned char *msg) { - base_w(lengths, PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_WOTS_LEN1, msg); - wots_checksum(lengths + PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_WOTS_LEN1, lengths); -} - -/** - * WOTS key generation. Takes a 32 byte sk_seed, expands it to WOTS private key - * elements and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_wots_gen_pk( - unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - uint32_t i; - - for (i = 0; i < PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_WOTS_LEN; i++) { - PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_set_chain_addr(addr, i); - wots_gen_sk(pk + i * PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_N, sk_seed, addr, hash_state_seeded); - gen_chain(pk + i * PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_N, pk + i * PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_N, - 0, PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_WOTS_W - 1, pub_seed, addr, hash_state_seeded); - } -} - -/** - * Takes a n-byte message and the 32-byte sk_see to compute a signature 'sig'. - */ -void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_wots_sign( - unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *hash_state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_WOTS_LEN; i++) { - PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_set_chain_addr(addr, i); - wots_gen_sk(sig + i * PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_N, sk_seed, addr, hash_state_seeded); - gen_chain(sig + i * PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_N, sig + i * PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_N, 0, lengths[i], pub_seed, addr, hash_state_seeded); - } -} - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_wots_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_WOTS_LEN; i++) { - PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_set_chain_addr(addr, i); - gen_chain(pk + i * PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_N, sig + i * PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_N, - lengths[i], PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_WOTS_W - 1 - lengths[i], pub_seed, addr, - hash_state_seeded); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_clean/wots.h b/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_clean/wots.h deleted file mode 100644 index 56be39f186..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_clean/wots.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_WOTS_H -#define PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_WOTS_H - -#include "hash_state.h" -#include "params.h" -#include - -/** - * WOTS key generation. Takes a 32 byte seed for the private key, expands it to - * a full WOTS private key and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_wots_gen_pk( - unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -/** - * Takes a n-byte message and the 32-byte seed for the private key to compute a - * signature that is placed at 'sig'. - */ -void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_wots_sign( - unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *hash_state_seeded); - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_wots_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_avx2/LICENSE b/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_avx2/LICENSE deleted file mode 100644 index 670154e353..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_avx2/LICENSE +++ /dev/null @@ -1,116 +0,0 @@ -CC0 1.0 Universal - -Statement of Purpose - -The laws of most jurisdictions throughout the world automatically confer -exclusive Copyright and Related Rights (defined below) upon the creator and -subsequent owner(s) (each and all, an "owner") of an original work of -authorship and/or a database (each, a "Work"). - -Certain owners wish to permanently relinquish those rights to a Work for the -purpose of contributing to a commons of creative, cultural and scientific -works ("Commons") that the public can reliably and without fear of later -claims of infringement build upon, modify, incorporate in other works, reuse -and redistribute as freely as possible in any form whatsoever and for any -purposes, including without limitation commercial purposes. These owners may -contribute to the Commons to promote the ideal of a free culture and the -further production of creative, cultural and scientific works, or to gain -reputation or greater distribution for their Work in part through the use and -efforts of others. - -For these and/or other purposes and motivations, and without any expectation -of additional consideration or compensation, the person associating CC0 with a -Work (the "Affirmer"), to the extent that he or she is an owner of Copyright -and Related Rights in the Work, voluntarily elects to apply CC0 to the Work -and publicly distribute the Work under its terms, with knowledge of his or her -Copyright and Related Rights in the Work and the meaning and intended legal -effect of CC0 on those rights. - -1. Copyright and Related Rights. A Work made available under CC0 may be -protected by copyright and related or neighboring rights ("Copyright and -Related Rights"). Copyright and Related Rights include, but are not limited -to, the following: - - i. the right to reproduce, adapt, distribute, perform, display, communicate, - and translate a Work; - - ii. moral rights retained by the original author(s) and/or performer(s); - - iii. publicity and privacy rights pertaining to a person's image or likeness - depicted in a Work; - - iv. rights protecting against unfair competition in regards to a Work, - subject to the limitations in paragraph 4(a), below; - - v. rights protecting the extraction, dissemination, use and reuse of data in - a Work; - - vi. database rights (such as those arising under Directive 96/9/EC of the - European Parliament and of the Council of 11 March 1996 on the legal - protection of databases, and under any national implementation thereof, - including any amended or successor version of such directive); and - - vii. other similar, equivalent or corresponding rights throughout the world - based on applicable law or treaty, and any national implementations thereof. - -2. Waiver. To the greatest extent permitted by, but not in contravention of, -applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and -unconditionally waives, abandons, and surrenders all of Affirmer's Copyright -and Related Rights and associated claims and causes of action, whether now -known or unknown (including existing as well as future claims and causes of -action), in the Work (i) in all territories worldwide, (ii) for the maximum -duration provided by applicable law or treaty (including future time -extensions), (iii) in any current or future medium and for any number of -copies, and (iv) for any purpose whatsoever, including without limitation -commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes -the Waiver for the benefit of each member of the public at large and to the -detriment of Affirmer's heirs and successors, fully intending that such Waiver -shall not be subject to revocation, rescission, cancellation, termination, or -any other legal or equitable action to disrupt the quiet enjoyment of the Work -by the public as contemplated by Affirmer's express Statement of Purpose. - -3. Public License Fallback. Should any part of the Waiver for any reason be -judged legally invalid or ineffective under applicable law, then the Waiver -shall be preserved to the maximum extent permitted taking into account -Affirmer's express Statement of Purpose. In addition, to the extent the Waiver -is so judged Affirmer hereby grants to each affected person a royalty-free, -non transferable, non sublicensable, non exclusive, irrevocable and -unconditional license to exercise Affirmer's Copyright and Related Rights in -the Work (i) in all territories worldwide, (ii) for the maximum duration -provided by applicable law or treaty (including future time extensions), (iii) -in any current or future medium and for any number of copies, and (iv) for any -purpose whatsoever, including without limitation commercial, advertising or -promotional purposes (the "License"). The License shall be deemed effective as -of the date CC0 was applied by Affirmer to the Work. Should any part of the -License for any reason be judged legally invalid or ineffective under -applicable law, such partial invalidity or ineffectiveness shall not -invalidate the remainder of the License, and in such case Affirmer hereby -affirms that he or she will not (i) exercise any of his or her remaining -Copyright and Related Rights in the Work or (ii) assert any associated claims -and causes of action with respect to the Work, in either case contrary to -Affirmer's express Statement of Purpose. - -4. Limitations and Disclaimers. - - a. No trademark or patent rights held by Affirmer are waived, abandoned, - surrendered, licensed or otherwise affected by this document. - - b. Affirmer offers the Work as-is and makes no representations or warranties - of any kind concerning the Work, express, implied, statutory or otherwise, - including without limitation warranties of title, merchantability, fitness - for a particular purpose, non infringement, or the absence of latent or - other defects, accuracy, or the present or absence of errors, whether or not - discoverable, all to the greatest extent permissible under applicable law. - - c. Affirmer disclaims responsibility for clearing rights of other persons - that may apply to the Work or any use thereof, including without limitation - any person's Copyright and Related Rights in the Work. Further, Affirmer - disclaims responsibility for obtaining any necessary consents, permissions - or other rights required for any use of the Work. - - d. Affirmer understands and acknowledges that Creative Commons is not a - party to this document and has no duty or obligation with respect to this - CC0 or use of the Work. - -For more information, please see - diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_avx2/address.c b/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_avx2/address.c deleted file mode 100644 index e67fe54635..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_avx2/address.c +++ /dev/null @@ -1,78 +0,0 @@ -#include - -#include "address.h" -#include "params.h" -#include "utils.h" - -void PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]) { - int i; - - for (i = 0; i < 8; i++) { - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_ull_to_bytes( - bytes + i * 4, 4, addr[i]); - } -} - -void PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_set_layer_addr( - uint32_t addr[8], uint32_t layer) { - addr[0] = layer; -} - -void PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_set_tree_addr( - uint32_t addr[8], uint64_t tree) { - addr[1] = 0; - addr[2] = (uint32_t) (tree >> 32); - addr[3] = (uint32_t) tree; -} - -void PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_set_type( - uint32_t addr[8], uint32_t type) { - addr[4] = type; -} - -void PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; -} - -/* These functions are used for OTS addresses. */ - -void PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_set_keypair_addr( - uint32_t addr[8], uint32_t keypair) { - addr[5] = keypair; -} - -void PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; - out[5] = in[5]; -} - -void PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_set_chain_addr( - uint32_t addr[8], uint32_t chain) { - addr[6] = chain; -} - -void PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_set_hash_addr( - uint32_t addr[8], uint32_t hash) { - addr[7] = hash; -} - -/* These functions are used for all hash tree addresses (including FORS). */ - -void PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_set_tree_height( - uint32_t addr[8], uint32_t tree_height) { - addr[6] = tree_height; -} - -void PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_set_tree_index( - uint32_t addr[8], uint32_t tree_index) { - addr[7] = tree_index; -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_avx2/address.h b/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_avx2/address.h deleted file mode 100644 index cca15aca0d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_avx2/address.h +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_ADDRESS_H -#define PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_ADDRESS_H - -#include - -#define PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_ADDR_TYPE_WOTS 0 -#define PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_ADDR_TYPE_WOTSPK 1 -#define PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_ADDR_TYPE_HASHTREE 2 -#define PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_ADDR_TYPE_FORSTREE 3 -#define PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_ADDR_TYPE_FORSPK 4 - -void PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]); - -void PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_set_layer_addr( - uint32_t addr[8], uint32_t layer); - -void PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_set_tree_addr( - uint32_t addr[8], uint64_t tree); - -void PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_set_type( - uint32_t addr[8], uint32_t type); - -/* Copies the layer and tree part of one address into the other */ -void PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for WOTS and FORS addresses. */ - -void PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_set_keypair_addr( - uint32_t addr[8], uint32_t keypair); - -void PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_set_chain_addr( - uint32_t addr[8], uint32_t chain); - -void PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_set_hash_addr( - uint32_t addr[8], uint32_t hash); - -void PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for all hash tree addresses (including FORS). */ - -void PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_set_tree_height( - uint32_t addr[8], uint32_t tree_height); - -void PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_set_tree_index( - uint32_t addr[8], uint32_t tree_index); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_avx2/api.h b/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_avx2/api.h deleted file mode 100644 index 4a6ba6f089..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_avx2/api.h +++ /dev/null @@ -1,81 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_API_H -#define PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_API_H - -#include -#include - - - -#define PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_CRYPTO_ALGNAME "SPHINCS+" - -#define PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_CRYPTO_SECRETKEYBYTES 96 -#define PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_CRYPTO_PUBLICKEYBYTES 48 -#define PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_CRYPTO_BYTES 35664 -#define PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_CRYPTO_SEEDBYTES 72 - - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_avx2/fors.c b/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_avx2/fors.c deleted file mode 100644 index c828925bed..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_avx2/fors.c +++ /dev/null @@ -1,240 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "fors.h" -#include "hash.h" -#include "hashx8.h" -#include "thash.h" -#include "thashx8.h" -#include "utils.h" -#include "utilsx8.h" - -static void fors_gen_skx8(unsigned char *sk0, - unsigned char *sk1, - unsigned char *sk2, - unsigned char *sk3, - unsigned char *sk4, - unsigned char *sk5, - unsigned char *sk6, - unsigned char *sk7, const unsigned char *sk_seed, - uint32_t fors_leaf_addrx8[8 * 8]) { - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_prf_addrx8(sk0, sk1, sk2, sk3, sk4, sk5, sk6, sk7, - sk_seed, fors_leaf_addrx8); -} - -static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, - const unsigned char *pub_seed, - uint32_t fors_leaf_addr[8], - const hash_state *state_seeded) { - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_thash_1(leaf, sk, pub_seed, fors_leaf_addr, state_seeded); -} - -static void fors_sk_to_leafx8(unsigned char *leaf0, - unsigned char *leaf1, - unsigned char *leaf2, - unsigned char *leaf3, - unsigned char *leaf4, - unsigned char *leaf5, - unsigned char *leaf6, - unsigned char *leaf7, - const unsigned char *sk0, - const unsigned char *sk1, - const unsigned char *sk2, - const unsigned char *sk3, - const unsigned char *sk4, - const unsigned char *sk5, - const unsigned char *sk6, - const unsigned char *sk7, - const unsigned char *pub_seed, - uint32_t fors_leaf_addrx8[8 * 8], - const hash_state *state_seeded) { - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_thashx8_1(leaf0, leaf1, leaf2, leaf3, leaf4, leaf5, leaf6, leaf7, - sk0, sk1, sk2, sk3, sk4, sk5, sk6, sk7, - pub_seed, fors_leaf_addrx8, state_seeded); -} - -static void fors_gen_leafx8(unsigned char *leaf0, - unsigned char *leaf1, - unsigned char *leaf2, - unsigned char *leaf3, - unsigned char *leaf4, - unsigned char *leaf5, - unsigned char *leaf6, - unsigned char *leaf7, - const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx0, - uint32_t addr_idx1, - uint32_t addr_idx2, - uint32_t addr_idx3, - uint32_t addr_idx4, - uint32_t addr_idx5, - uint32_t addr_idx6, - uint32_t addr_idx7, - const uint32_t fors_tree_addr[8], - const hash_state *state_seeded) { - uint32_t fors_leaf_addrx8[8 * 8] = {0}; - unsigned int j; - - /* Only copy the parts that must be kept in fors_leaf_addrx8. */ - for (j = 0; j < 8; j++) { - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_copy_keypair_addr(fors_leaf_addrx8 + j * 8, fors_tree_addr); - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_set_type(fors_leaf_addrx8 + j * 8, PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_ADDR_TYPE_FORSTREE); - } - - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_set_tree_index(fors_leaf_addrx8 + 0 * 8, addr_idx0); - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_set_tree_index(fors_leaf_addrx8 + 1 * 8, addr_idx1); - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_set_tree_index(fors_leaf_addrx8 + 2 * 8, addr_idx2); - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_set_tree_index(fors_leaf_addrx8 + 3 * 8, addr_idx3); - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_set_tree_index(fors_leaf_addrx8 + 4 * 8, addr_idx4); - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_set_tree_index(fors_leaf_addrx8 + 5 * 8, addr_idx5); - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_set_tree_index(fors_leaf_addrx8 + 6 * 8, addr_idx6); - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_set_tree_index(fors_leaf_addrx8 + 7 * 8, addr_idx7); - - fors_gen_skx8(leaf0, leaf1, leaf2, leaf3, leaf4, leaf5, leaf6, leaf7, - sk_seed, fors_leaf_addrx8); - fors_sk_to_leafx8(leaf0, leaf1, leaf2, leaf3, leaf4, leaf5, leaf6, leaf7, - leaf0, leaf1, leaf2, leaf3, leaf4, leaf5, leaf6, leaf7, - pub_seed, fors_leaf_addrx8, state_seeded); -} - -/** - * Interprets m as PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_FORS_HEIGHT-bit unsigned integers. - * Assumes m contains at least PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_FORS_TREES bits. - * Assumes indices has space for PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_FORS_TREES integers. - */ -static void message_to_indices(uint32_t *indices, const unsigned char *m) { - unsigned int i, j; - unsigned int offset = 0; - - for (i = 0; i < PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_FORS_TREES; i++) { - indices[i] = 0; - for (j = 0; j < PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_FORS_HEIGHT; j++) { - indices[i] ^= (((uint32_t)m[offset >> 3] >> (offset & 0x7)) & 0x1) << j; - offset++; - } - } -} - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_fors_sign( - unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], - const hash_state *state_seeded) { - /* Round up to multiple of 8 to prevent out-of-bounds for x8 parallelism */ - uint32_t indices[(PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_FORS_TREES + 7) & ~7] = {0}; - unsigned char roots[((PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_FORS_TREES + 7) & ~7) * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N]; - /* Sign to a buffer, since we may not have a nice multiple of 8 and would - otherwise overrun the signature. */ - unsigned char sigbufx8[8 * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N * (1 + PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_FORS_HEIGHT)]; - uint32_t fors_tree_addrx8[8 * 8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset[8] = {0}; - unsigned int i, j; - - for (j = 0; j < 8; j++) { - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_copy_keypair_addr(fors_tree_addrx8 + j * 8, fors_addr); - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_set_type(fors_tree_addrx8 + j * 8, PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_ADDR_TYPE_FORSTREE); - } - - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_copy_keypair_addr(fors_pk_addr, fors_addr); - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_set_type(fors_pk_addr, PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < ((PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_FORS_TREES + 7) & ~0x7); i += 8) { - for (j = 0; j < 8; j++) { - if (i + j < PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_FORS_TREES) { - idx_offset[j] = (i + j) * (1 << PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_FORS_HEIGHT); - - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_set_tree_height(fors_tree_addrx8 + j * 8, 0); - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_set_tree_index(fors_tree_addrx8 + j * 8, - indices[i + j] + idx_offset[j]); - } - } - - /* Include the secret key part that produces the selected leaf nodes. */ - fors_gen_skx8(sigbufx8 + 0 * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N, - sigbufx8 + 1 * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N, - sigbufx8 + 2 * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N, - sigbufx8 + 3 * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N, - sigbufx8 + 4 * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N, - sigbufx8 + 5 * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N, - sigbufx8 + 6 * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N, - sigbufx8 + 7 * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N, - sk_seed, fors_tree_addrx8); - - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_treehashx8_FORS_HEIGHT( - roots + i * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N, sigbufx8 + 8 * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N, sk_seed, pub_seed, - &indices[i], idx_offset, fors_gen_leafx8, fors_tree_addrx8, - state_seeded); - - for (j = 0; j < 8; j++) { - if (i + j < PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_FORS_TREES) { - memcpy(sig, sigbufx8 + j * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N, PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N); - memcpy(sig + PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N, - sigbufx8 + 8 * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N + j * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_FORS_HEIGHT, - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_FORS_HEIGHT); - sig += PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N * (1 + PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_FORS_HEIGHT); - } - } - } - - /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_thash_FORS_TREES(pk, roots, pub_seed, fors_pk_addr, state_seeded); -} - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, - const uint32_t fors_addr[8], - const hash_state *state_seeded) { - uint32_t indices[PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_FORS_TREES]; - unsigned char roots[PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_FORS_TREES * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N]; - unsigned char leaf[PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N]; - uint32_t fors_tree_addr[8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_copy_keypair_addr(fors_tree_addr, fors_addr); - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_copy_keypair_addr(fors_pk_addr, fors_addr); - - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_set_type(fors_tree_addr, PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_set_type(fors_pk_addr, PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_FORS_TREES; i++) { - idx_offset = i * (1 << PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_FORS_HEIGHT); - - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_set_tree_height(fors_tree_addr, 0); - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Derive the leaf from the included secret key part. */ - fors_sk_to_leaf(leaf, sig, pub_seed, fors_tree_addr, state_seeded); - sig += PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N; - - /* Derive the corresponding root node of this tree. */ - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_compute_root(roots + i * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N, leaf, indices[i], idx_offset, - sig, PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_FORS_HEIGHT, pub_seed, fors_tree_addr, state_seeded); - sig += PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_thash_FORS_TREES(pk, roots, pub_seed, fors_pk_addr, state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_avx2/fors.h b/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_avx2/fors.h deleted file mode 100644 index be1df581a5..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_avx2/fors.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_FORS_H -#define PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_FORS_H - -#include - -#include "hash_state.h" -#include "params.h" - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_fors_sign( - unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *hash_state_seeded); - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_fors_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, const uint32_t fors_addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_avx2/hash.h b/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_avx2/hash.h deleted file mode 100644 index bf26d724e5..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_avx2/hash.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_HASH_H -#define PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_HASH_H - -#include "hash_state.h" - -#include -#include - -void PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_initialize_hash_function( - hash_state *hash_state_seeded, - const unsigned char *pub_seed, const unsigned char *sk_seed); - -void PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_destroy_hash_function(hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_avx2/hash_sha256.c b/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_avx2/hash_sha256.c deleted file mode 100644 index fad52a5ff9..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_avx2/hash_sha256.c +++ /dev/null @@ -1,166 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "utils.h" - -#include "sha2.h" -#include "sha256.h" -#include "sha256x8.h" - -/** - * Initializes the hash function states - */ -void PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_initialize_hash_function( - hash_state *hash_state_seeded, - const unsigned char *pub_seed, const unsigned char *sk_seed) { - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_seed_state(&hash_state_seeded->x1, pub_seed); - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_seed_statex8(&hash_state_seeded->x8, pub_seed); - (void)sk_seed; /* Suppress an 'unused parameter' warning. */ -} - -/** - * Cleans up the hash function states - */ -void PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_destroy_hash_function(hash_state *hash_state_seeded) { - sha256_inc_ctx_release(&hash_state_seeded->x1); -} - -/* - * Computes PRF(key, addr), given a secret key of PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N bytes and an address - */ -void PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_prf_addr(unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded) { - unsigned char buf[PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_ADDR_BYTES]; - unsigned char outbuf[PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_OUTPUT_BYTES]; - - memcpy(buf, key, PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N); - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_compress_address(buf + PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N, addr); - - sha256(outbuf, buf, PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_ADDR_BYTES); - memcpy(out, outbuf, PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} - -/** - * Computes the message-dependent randomness R, using a secret seed as a key - * for HMAC, and an optional randomization value prefixed to the message. - * This requires m to have at least PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_BLOCK_BYTES + PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N space - * available in front of the pointer, i.e. before the message to use for the - * prefix. This is necessary to prevent having to move the message around (and - * allocate memory for it). - */ -void PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, const hash_state *hash_state_seeded) { - unsigned char buf[PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_BLOCK_BYTES + PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_OUTPUT_BYTES]; - sha256ctx state; - int i; - - /* This implements HMAC-SHA256 */ - for (i = 0; i < PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N; i++) { - buf[i] = 0x36 ^ sk_prf[i]; - } - memset(buf + PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N, 0x36, PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N); - - sha256_inc_init(&state); - sha256_inc_blocks(&state, buf, 1); - - memcpy(buf, optrand, PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N); - - /* If optrand + message cannot fill up an entire block */ - if (PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N + mlen < PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_BLOCK_BYTES) { - memcpy(buf + PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N, m, mlen); - sha256_inc_finalize(buf + PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_BLOCK_BYTES, &state, - buf, mlen + PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N); - } - /* Otherwise first fill a block, so that finalize only uses the message */ - else { - memcpy(buf + PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N, m, PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N); - sha256_inc_blocks(&state, buf, 1); - - m += PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N; - mlen -= PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N; - sha256_inc_finalize(buf + PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_BLOCK_BYTES, &state, m, mlen); - } - - for (i = 0; i < PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N; i++) { - buf[i] = 0x5c ^ sk_prf[i]; - } - memset(buf + PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N, 0x5c, PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N); - - sha256(buf, buf, PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_BLOCK_BYTES + PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_OUTPUT_BYTES); - memcpy(R, buf, PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} - -/** - * Computes the message hash using R, the public key, and the message. - * Outputs the message digest and the index of the leaf. The index is split in - * the tree index and the leaf index, for convenient copying to an address. - */ -void PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded) { -#define PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_TREE_BITS (PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_TREE_HEIGHT * (PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_D - 1)) -#define PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_TREE_BYTES ((PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_TREE_BITS + 7) / 8) -#define PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_LEAF_BITS PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_TREE_HEIGHT -#define PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_LEAF_BYTES ((PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_LEAF_BITS + 7) / 8) -#define PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_DGST_BYTES (PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_FORS_MSG_BYTES + PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_TREE_BYTES + PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_LEAF_BYTES) - - unsigned char seed[PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_OUTPUT_BYTES + 4]; - - /* Round to nearest multiple of PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_BLOCK_BYTES */ -#define PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_INBLOCKS (((PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_PK_BYTES + PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_BLOCK_BYTES - 1) & \ - -PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_BLOCK_BYTES) / PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_BLOCK_BYTES) - unsigned char inbuf[PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_INBLOCKS * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_BLOCK_BYTES]; - - unsigned char buf[PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_DGST_BYTES]; - unsigned char *bufp = buf; - sha256ctx state; - - sha256_inc_init(&state); - - memcpy(inbuf, R, PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N); - memcpy(inbuf + PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N, pk, PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_PK_BYTES); - - /* If R + pk + message cannot fill up an entire block */ - if (PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_PK_BYTES + mlen < PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_INBLOCKS * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_BLOCK_BYTES) { - memcpy(inbuf + PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_PK_BYTES, m, mlen); - sha256_inc_finalize(seed, &state, inbuf, PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_PK_BYTES + mlen); - } - /* Otherwise first fill a block, so that finalize only uses the message */ - else { - memcpy(inbuf + PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_PK_BYTES, m, - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_INBLOCKS * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_PK_BYTES); - sha256_inc_blocks(&state, inbuf, PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_INBLOCKS); - - m += PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_INBLOCKS * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_PK_BYTES; - mlen -= PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_INBLOCKS * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_PK_BYTES; - sha256_inc_finalize(seed, &state, m, mlen); - } - - /* By doing this in two steps, we prevent hashing the message twice; - otherwise each iteration in MGF1 would hash the message again. */ - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_mgf1(bufp, PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_DGST_BYTES, seed, PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_OUTPUT_BYTES); - - memcpy(digest, bufp, PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_FORS_MSG_BYTES); - bufp += PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_FORS_MSG_BYTES; - - *tree = PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_bytes_to_ull(bufp, PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_TREE_BYTES); - *tree &= (~(uint64_t)0) >> (64 - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_TREE_BITS); - bufp += PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_TREE_BYTES; - - *leaf_idx = (uint32_t)PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_bytes_to_ull( - bufp, PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_LEAF_BYTES); - *leaf_idx &= (~(uint32_t)0) >> (32 - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_LEAF_BITS); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_avx2/hash_sha256x8.c b/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_avx2/hash_sha256x8.c deleted file mode 100644 index 57992dc320..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_avx2/hash_sha256x8.c +++ /dev/null @@ -1,61 +0,0 @@ -#include -#include - -#include "address.h" -#include "hashx8.h" -#include "params.h" -#include "sha256.h" -#include "sha256avx.h" -#include "sha256x8.h" -#include "utils.h" - -/* - * 8-way parallel version of prf_addr; takes 8x as much input and output - */ -void PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_prf_addrx8(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7, - const unsigned char *key, - const uint32_t addrx8[8 * 8]) { - unsigned char bufx8[8 * (PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_ADDR_BYTES)]; - unsigned char outbufx8[8 * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_OUTPUT_BYTES]; - unsigned int j; - - for (j = 0; j < 8; j++) { - memcpy(bufx8 + j * (PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_ADDR_BYTES), key, PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N); - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_compress_address(bufx8 + PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N + j * (PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_ADDR_BYTES), - addrx8 + j * 8); - } - - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_sha256x8(outbufx8 + 0 * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 1 * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 2 * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 3 * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 4 * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 5 * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 6 * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 7 * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_OUTPUT_BYTES, - bufx8 + 0 * (PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_ADDR_BYTES), - bufx8 + 1 * (PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_ADDR_BYTES), - bufx8 + 2 * (PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_ADDR_BYTES), - bufx8 + 3 * (PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_ADDR_BYTES), - bufx8 + 4 * (PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_ADDR_BYTES), - bufx8 + 5 * (PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_ADDR_BYTES), - bufx8 + 6 * (PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_ADDR_BYTES), - bufx8 + 7 * (PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_ADDR_BYTES), - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_ADDR_BYTES); - - memcpy(out0, outbufx8 + 0 * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N); - memcpy(out1, outbufx8 + 1 * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N); - memcpy(out2, outbufx8 + 2 * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N); - memcpy(out3, outbufx8 + 3 * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N); - memcpy(out4, outbufx8 + 4 * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N); - memcpy(out5, outbufx8 + 5 * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N); - memcpy(out6, outbufx8 + 6 * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N); - memcpy(out7, outbufx8 + 7 * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_avx2/hash_state.h b/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_avx2/hash_state.h deleted file mode 100644 index 5d65df8b3c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_avx2/hash_state.h +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_HASH_STATE_H -#define PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_HASH_STATE_H - -/** - * Defines the type of the hash function state. - * - * Don't be fooled into thinking this instance of SPHINCS+ isn't stateless! - * - * From Section 7.2.2 from the SPHINCS+ round-2 specification: - * - * Each of the instances of the tweakable hash function take PK.seed as its - * first input, which is constant for a given key pair – and, thus, across - * a single signature. This leads to a lot of redundant computation. To remedy - * this, we pad PK.seed to the length of a full 64-byte SHA-256 input block. - * Because of the Merkle-Damgård construction that underlies SHA-256, this - * allows for reuse of the intermediate SHA-256 state after the initial call to - * the compression function which improves performance. - * - * We pass this hash state around in functions, because otherwise we need to - * have a global variable. - * - * We use a struct to differentiate between the x1 and x8 variants of SHA256. - */ - -#include "sha2.h" -#include "sha256avx.h" - -typedef struct { - sha256ctx x1; - sha256ctxx8 x8; -} hash_state; - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_avx2/hashx8.h b/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_avx2/hashx8.h deleted file mode 100644 index 064211f45d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_avx2/hashx8.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_HASHX8_H -#define PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_HASHX8_H - -#include - -#include "params.h" - -void PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_prf_addrx8(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7, - const unsigned char *key, - const uint32_t addrx8[8 * 8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_avx2/params.h b/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_avx2/params.h deleted file mode 100644 index 650a703a72..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_avx2/params.h +++ /dev/null @@ -1,53 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_PARAMS_H -#define PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_PARAMS_H - -/* Hash output length in bytes. */ -#define PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N 24 -/* Height of the hypertree. */ -#define PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_FULL_HEIGHT 66 -/* Number of subtree layer. */ -#define PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_D 22 -/* FORS tree dimensions. */ -#define PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_FORS_HEIGHT 8 -#define PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_FORS_TREES 33 -/* Winternitz parameter, */ -#define PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_WOTS_W 16 - -/* The hash function is defined by linking a different hash.c file, as opposed - to setting a #define constant. */ - -/* For clarity */ -#define PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_ADDR_BYTES 32 - -/* WOTS parameters. */ -#define PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_WOTS_LOGW 4 - -#define PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_WOTS_LEN1 (8 * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N / PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_WOTS_LOGW) - -/* PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#define PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_WOTS_LEN2 3 - -#define PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_WOTS_LEN (PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_WOTS_LEN1 + PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_WOTS_LEN2) -#define PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_WOTS_BYTES (PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_WOTS_LEN * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N) -#define PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_WOTS_PK_BYTES PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_WOTS_BYTES - -/* Subtree size. */ -#define PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_TREE_HEIGHT (PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_FULL_HEIGHT / PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_D) - -/* FORS parameters. */ -#define PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_FORS_MSG_BYTES ((PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_FORS_TREES + 7) / 8) -#define PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_FORS_BYTES ((PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_FORS_HEIGHT + 1) * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_FORS_TREES * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N) -#define PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_FORS_PK_BYTES PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N - -/* Resulting SPX sizes. */ -#define PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_BYTES (PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_FORS_BYTES + PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_D * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_WOTS_BYTES +\ - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_FULL_HEIGHT * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N) -#define PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_PK_BYTES (2 * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N) -#define PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SK_BYTES (2 * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_PK_BYTES) - -/* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ -#define PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_OPTRAND_BYTES 32 - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_avx2/sha256.c b/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_avx2/sha256.c deleted file mode 100644 index 92ee47ef87..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_avx2/sha256.c +++ /dev/null @@ -1,71 +0,0 @@ -/* Based on the public domain implementation in - * crypto_hash/sha512/ref/ from http://bench.cr.yp.to/supercop.html - * by D. J. Bernstein */ - -#include -#include -#include - -#include "sha2.h" -#include "sha256.h" -#include "utils.h" - -/* - * Compresses an address to a 22-byte sequence. - * This reduces the number of required SHA256 compression calls, as the last - * block of input is padded with at least 65 bits. - */ -void PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_compress_address(unsigned char *out, const uint32_t addr[8]) { - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_ull_to_bytes(out, 1, addr[0]); /* drop 3 bytes of the layer field */ - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_ull_to_bytes(out + 1, 4, addr[2]); /* drop the highest tree address word */ - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_ull_to_bytes(out + 5, 4, addr[3]); - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_ull_to_bytes(out + 9, 1, addr[4]); /* drop 3 bytes of the type field */ - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_ull_to_bytes(out + 10, 4, addr[5]); - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_ull_to_bytes(out + 14, 4, addr[6]); - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_ull_to_bytes(out + 18, 4, addr[7]); -} - -/** - * Requires 'input_plus_four_bytes' to have 'inlen' + 4 bytes, so that the last - * four bytes can be used for the counter. Typically 'input' is merely a seed. - * Outputs outlen number of bytes - */ -void PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_mgf1( - unsigned char *out, unsigned long outlen, - unsigned char *input_plus_four_bytes, unsigned long inlen) { - unsigned char outbuf[PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_OUTPUT_BYTES]; - unsigned long i; - - /* While we can fit in at least another full block of SHA256 output.. */ - for (i = 0; (i + 1)*PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_OUTPUT_BYTES <= outlen; i++) { - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_ull_to_bytes(input_plus_four_bytes + inlen, 4, i); - sha256(out, input_plus_four_bytes, inlen + 4); - out += PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_OUTPUT_BYTES; - } - /* Until we cannot anymore, and we fill the remainder. */ - if (outlen > i * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_OUTPUT_BYTES) { - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_ull_to_bytes(input_plus_four_bytes + inlen, 4, i); - sha256(outbuf, input_plus_four_bytes, inlen + 4); - memcpy(out, outbuf, outlen - i * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_OUTPUT_BYTES); - } -} - - -/** - * Absorb the constant pub_seed using one round of the compression function - * This initializes hash_state_seeded, which can then be reused in thash - **/ -void PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_seed_state(sha256ctx *hash_state_seeded, const unsigned char *pub_seed) { - uint8_t block[PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_BLOCK_BYTES]; - size_t i; - - for (i = 0; i < PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N; ++i) { - block[i] = pub_seed[i]; - } - for (i = PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N; i < PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_BLOCK_BYTES; ++i) { - block[i] = 0; - } - - sha256_inc_init(hash_state_seeded); - sha256_inc_blocks(hash_state_seeded, block, 1); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_avx2/sha256.h b/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_avx2/sha256.h deleted file mode 100644 index e3ff91dee8..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_avx2/sha256.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_H -#define PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_H - -#define PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_BLOCK_BYTES 64 -#define PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_OUTPUT_BYTES 32 /* This does not necessarily equal PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N */ -#define PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_ADDR_BYTES 22 - -#include -#include - -#include "sha2.h" - -void PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_compress_address(unsigned char *out, const uint32_t addr[8]); - -void PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_mgf1( - unsigned char *out, unsigned long outlen, - unsigned char *input_plus_four_bytes, unsigned long inlen); - -void PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_seed_state(sha256ctx *hash_state_seeded, const unsigned char *pub_seed); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_avx2/sha256avx.c b/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_avx2/sha256avx.c deleted file mode 100644 index ab2e7329aa..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_avx2/sha256avx.c +++ /dev/null @@ -1,296 +0,0 @@ -#include -#include -#include - -#include "sha256avx.h" - -// Transpose 8 vectors containing 32-bit values -void PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_transpose(u256 s[8]) { - u256 tmp0[8]; - u256 tmp1[8]; - tmp0[0] = _mm256_unpacklo_epi32(s[0], s[1]); - tmp0[1] = _mm256_unpackhi_epi32(s[0], s[1]); - tmp0[2] = _mm256_unpacklo_epi32(s[2], s[3]); - tmp0[3] = _mm256_unpackhi_epi32(s[2], s[3]); - tmp0[4] = _mm256_unpacklo_epi32(s[4], s[5]); - tmp0[5] = _mm256_unpackhi_epi32(s[4], s[5]); - tmp0[6] = _mm256_unpacklo_epi32(s[6], s[7]); - tmp0[7] = _mm256_unpackhi_epi32(s[6], s[7]); - tmp1[0] = _mm256_unpacklo_epi64(tmp0[0], tmp0[2]); - tmp1[1] = _mm256_unpackhi_epi64(tmp0[0], tmp0[2]); - tmp1[2] = _mm256_unpacklo_epi64(tmp0[1], tmp0[3]); - tmp1[3] = _mm256_unpackhi_epi64(tmp0[1], tmp0[3]); - tmp1[4] = _mm256_unpacklo_epi64(tmp0[4], tmp0[6]); - tmp1[5] = _mm256_unpackhi_epi64(tmp0[4], tmp0[6]); - tmp1[6] = _mm256_unpacklo_epi64(tmp0[5], tmp0[7]); - tmp1[7] = _mm256_unpackhi_epi64(tmp0[5], tmp0[7]); - s[0] = _mm256_permute2x128_si256(tmp1[0], tmp1[4], 0x20); - s[1] = _mm256_permute2x128_si256(tmp1[1], tmp1[5], 0x20); - s[2] = _mm256_permute2x128_si256(tmp1[2], tmp1[6], 0x20); - s[3] = _mm256_permute2x128_si256(tmp1[3], tmp1[7], 0x20); - s[4] = _mm256_permute2x128_si256(tmp1[0], tmp1[4], 0x31); - s[5] = _mm256_permute2x128_si256(tmp1[1], tmp1[5], 0x31); - s[6] = _mm256_permute2x128_si256(tmp1[2], tmp1[6], 0x31); - s[7] = _mm256_permute2x128_si256(tmp1[3], tmp1[7], 0x31); -} - -void PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_sha256_clone_statex8(sha256ctxx8 *outctx, const sha256ctxx8 *inctx) { - memcpy(outctx, inctx, sizeof(sha256ctxx8)); -} - -void PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_sha256_init8x(sha256ctxx8 *ctx) { - ctx->s[0] = _mm256_set_epi32((int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667); - ctx->s[1] = _mm256_set_epi32((int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85); - ctx->s[2] = _mm256_set_epi32((int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372); - ctx->s[3] = _mm256_set_epi32((int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a); - ctx->s[4] = _mm256_set_epi32((int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f); - ctx->s[5] = _mm256_set_epi32((int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c); - ctx->s[6] = _mm256_set_epi32((int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab); - ctx->s[7] = _mm256_set_epi32((int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19); - - ctx->datalen = 0; - ctx->msglen = 0; -} - -void PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_sha256_update8x(sha256ctxx8 *ctx, - const unsigned char *d0, - const unsigned char *d1, - const unsigned char *d2, - const unsigned char *d3, - const unsigned char *d4, - const unsigned char *d5, - const unsigned char *d6, - const unsigned char *d7, - unsigned long long len) { - size_t i = 0; - size_t bytes_to_copy; - - while (i < len) { - bytes_to_copy = (size_t)len - i; - if (bytes_to_copy > 64) { - bytes_to_copy = 64; - } - memcpy(&ctx->msgblocks[64 * 0], d0 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64 * 1], d1 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64 * 2], d2 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64 * 3], d3 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64 * 4], d4 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64 * 5], d5 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64 * 6], d6 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64 * 7], d7 + i, bytes_to_copy); - ctx->datalen += (unsigned int)bytes_to_copy; - i += bytes_to_copy; - if (ctx->datalen == 64) { - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_sha256_transform8x(ctx, ctx->msgblocks); - ctx->msglen += 512; - ctx->datalen = 0; - } - } -} - -void PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_sha256_final8x(sha256ctxx8 *ctx, - unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7) { - unsigned int i, curlen; - - // Padding - if (ctx->datalen < 56) { - for (i = 0; i < 8; ++i) { - curlen = ctx->datalen; - ctx->msgblocks[64 * i + curlen++] = 0x80; - while (curlen < 64) { - ctx->msgblocks[64 * i + curlen++] = 0x00; - } - } - } else { - for (i = 0; i < 8; ++i) { - curlen = ctx->datalen; - ctx->msgblocks[64 * i + curlen++] = 0x80; - while (curlen < 64) { - ctx->msgblocks[64 * i + curlen++] = 0x00; - } - } - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_sha256_transform8x(ctx, ctx->msgblocks); - memset(ctx->msgblocks, 0, 8 * 64); - } - - // Add length of the message to each block - ctx->msglen += ctx->datalen * 8; - for (i = 0; i < 8; i++) { - ctx->msgblocks[64 * i + 63] = (unsigned char)ctx->msglen; - ctx->msgblocks[64 * i + 62] = (unsigned char)(ctx->msglen >> 8); - ctx->msgblocks[64 * i + 61] = (unsigned char)(ctx->msglen >> 16); - ctx->msgblocks[64 * i + 60] = (unsigned char)(ctx->msglen >> 24); - ctx->msgblocks[64 * i + 59] = (unsigned char)(ctx->msglen >> 32); - ctx->msgblocks[64 * i + 58] = (unsigned char)(ctx->msglen >> 40); - ctx->msgblocks[64 * i + 57] = (unsigned char)(ctx->msglen >> 48); - ctx->msgblocks[64 * i + 56] = (unsigned char)(ctx->msglen >> 56); - } - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_sha256_transform8x(ctx, ctx->msgblocks); - - // Compute final hash output - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_transpose(ctx->s); - - // Store Hash value - STORE(out0, BYTESWAP(ctx->s[0])); - STORE(out1, BYTESWAP(ctx->s[1])); - STORE(out2, BYTESWAP(ctx->s[2])); - STORE(out3, BYTESWAP(ctx->s[3])); - STORE(out4, BYTESWAP(ctx->s[4])); - STORE(out5, BYTESWAP(ctx->s[5])); - STORE(out6, BYTESWAP(ctx->s[6])); - STORE(out7, BYTESWAP(ctx->s[7])); -} - -void PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_sha256_transform8x(sha256ctxx8 *ctx, const unsigned char *data) { - u256 s[8], w[64], T0, T1; - int i; - - // Load words and transform data correctly - for (i = 0; i < 8; i++) { - w[i] = BYTESWAP(LOAD(data + 64 * i)); - w[i + 8] = BYTESWAP(LOAD(data + 32 + 64 * i)); - } - - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_transpose(w); - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_transpose(w + 8); - - // Initial State - s[0] = ctx->s[0]; - s[1] = ctx->s[1]; - s[2] = ctx->s[2]; - s[3] = ctx->s[3]; - s[4] = ctx->s[4]; - s[5] = ctx->s[5]; - s[6] = ctx->s[6]; - s[7] = ctx->s[7]; - - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 0, w[0]); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 1, w[1]); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 2, w[2]); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 3, w[3]); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 4, w[4]); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 5, w[5]); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 6, w[6]); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 7, w[7]); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 8, w[8]); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 9, w[9]); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 10, w[10]); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 11, w[11]); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 12, w[12]); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 13, w[13]); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 14, w[14]); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 15, w[15]); - w[16] = ADD4_32(WSIGMA1_AVX(w[14]), w[0], w[9], WSIGMA0_AVX(w[1])); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 16, w[16]); - w[17] = ADD4_32(WSIGMA1_AVX(w[15]), w[1], w[10], WSIGMA0_AVX(w[2])); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 17, w[17]); - w[18] = ADD4_32(WSIGMA1_AVX(w[16]), w[2], w[11], WSIGMA0_AVX(w[3])); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 18, w[18]); - w[19] = ADD4_32(WSIGMA1_AVX(w[17]), w[3], w[12], WSIGMA0_AVX(w[4])); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 19, w[19]); - w[20] = ADD4_32(WSIGMA1_AVX(w[18]), w[4], w[13], WSIGMA0_AVX(w[5])); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 20, w[20]); - w[21] = ADD4_32(WSIGMA1_AVX(w[19]), w[5], w[14], WSIGMA0_AVX(w[6])); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 21, w[21]); - w[22] = ADD4_32(WSIGMA1_AVX(w[20]), w[6], w[15], WSIGMA0_AVX(w[7])); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 22, w[22]); - w[23] = ADD4_32(WSIGMA1_AVX(w[21]), w[7], w[16], WSIGMA0_AVX(w[8])); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 23, w[23]); - w[24] = ADD4_32(WSIGMA1_AVX(w[22]), w[8], w[17], WSIGMA0_AVX(w[9])); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 24, w[24]); - w[25] = ADD4_32(WSIGMA1_AVX(w[23]), w[9], w[18], WSIGMA0_AVX(w[10])); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 25, w[25]); - w[26] = ADD4_32(WSIGMA1_AVX(w[24]), w[10], w[19], WSIGMA0_AVX(w[11])); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 26, w[26]); - w[27] = ADD4_32(WSIGMA1_AVX(w[25]), w[11], w[20], WSIGMA0_AVX(w[12])); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 27, w[27]); - w[28] = ADD4_32(WSIGMA1_AVX(w[26]), w[12], w[21], WSIGMA0_AVX(w[13])); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 28, w[28]); - w[29] = ADD4_32(WSIGMA1_AVX(w[27]), w[13], w[22], WSIGMA0_AVX(w[14])); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 29, w[29]); - w[30] = ADD4_32(WSIGMA1_AVX(w[28]), w[14], w[23], WSIGMA0_AVX(w[15])); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 30, w[30]); - w[31] = ADD4_32(WSIGMA1_AVX(w[29]), w[15], w[24], WSIGMA0_AVX(w[16])); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 31, w[31]); - w[32] = ADD4_32(WSIGMA1_AVX(w[30]), w[16], w[25], WSIGMA0_AVX(w[17])); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 32, w[32]); - w[33] = ADD4_32(WSIGMA1_AVX(w[31]), w[17], w[26], WSIGMA0_AVX(w[18])); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 33, w[33]); - w[34] = ADD4_32(WSIGMA1_AVX(w[32]), w[18], w[27], WSIGMA0_AVX(w[19])); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 34, w[34]); - w[35] = ADD4_32(WSIGMA1_AVX(w[33]), w[19], w[28], WSIGMA0_AVX(w[20])); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 35, w[35]); - w[36] = ADD4_32(WSIGMA1_AVX(w[34]), w[20], w[29], WSIGMA0_AVX(w[21])); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 36, w[36]); - w[37] = ADD4_32(WSIGMA1_AVX(w[35]), w[21], w[30], WSIGMA0_AVX(w[22])); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 37, w[37]); - w[38] = ADD4_32(WSIGMA1_AVX(w[36]), w[22], w[31], WSIGMA0_AVX(w[23])); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 38, w[38]); - w[39] = ADD4_32(WSIGMA1_AVX(w[37]), w[23], w[32], WSIGMA0_AVX(w[24])); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 39, w[39]); - w[40] = ADD4_32(WSIGMA1_AVX(w[38]), w[24], w[33], WSIGMA0_AVX(w[25])); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 40, w[40]); - w[41] = ADD4_32(WSIGMA1_AVX(w[39]), w[25], w[34], WSIGMA0_AVX(w[26])); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 41, w[41]); - w[42] = ADD4_32(WSIGMA1_AVX(w[40]), w[26], w[35], WSIGMA0_AVX(w[27])); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 42, w[42]); - w[43] = ADD4_32(WSIGMA1_AVX(w[41]), w[27], w[36], WSIGMA0_AVX(w[28])); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 43, w[43]); - w[44] = ADD4_32(WSIGMA1_AVX(w[42]), w[28], w[37], WSIGMA0_AVX(w[29])); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 44, w[44]); - w[45] = ADD4_32(WSIGMA1_AVX(w[43]), w[29], w[38], WSIGMA0_AVX(w[30])); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 45, w[45]); - w[46] = ADD4_32(WSIGMA1_AVX(w[44]), w[30], w[39], WSIGMA0_AVX(w[31])); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 46, w[46]); - w[47] = ADD4_32(WSIGMA1_AVX(w[45]), w[31], w[40], WSIGMA0_AVX(w[32])); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 47, w[47]); - w[48] = ADD4_32(WSIGMA1_AVX(w[46]), w[32], w[41], WSIGMA0_AVX(w[33])); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 48, w[48]); - w[49] = ADD4_32(WSIGMA1_AVX(w[47]), w[33], w[42], WSIGMA0_AVX(w[34])); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 49, w[49]); - w[50] = ADD4_32(WSIGMA1_AVX(w[48]), w[34], w[43], WSIGMA0_AVX(w[35])); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 50, w[50]); - w[51] = ADD4_32(WSIGMA1_AVX(w[49]), w[35], w[44], WSIGMA0_AVX(w[36])); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 51, w[51]); - w[52] = ADD4_32(WSIGMA1_AVX(w[50]), w[36], w[45], WSIGMA0_AVX(w[37])); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 52, w[52]); - w[53] = ADD4_32(WSIGMA1_AVX(w[51]), w[37], w[46], WSIGMA0_AVX(w[38])); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 53, w[53]); - w[54] = ADD4_32(WSIGMA1_AVX(w[52]), w[38], w[47], WSIGMA0_AVX(w[39])); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 54, w[54]); - w[55] = ADD4_32(WSIGMA1_AVX(w[53]), w[39], w[48], WSIGMA0_AVX(w[40])); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 55, w[55]); - w[56] = ADD4_32(WSIGMA1_AVX(w[54]), w[40], w[49], WSIGMA0_AVX(w[41])); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 56, w[56]); - w[57] = ADD4_32(WSIGMA1_AVX(w[55]), w[41], w[50], WSIGMA0_AVX(w[42])); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 57, w[57]); - w[58] = ADD4_32(WSIGMA1_AVX(w[56]), w[42], w[51], WSIGMA0_AVX(w[43])); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 58, w[58]); - w[59] = ADD4_32(WSIGMA1_AVX(w[57]), w[43], w[52], WSIGMA0_AVX(w[44])); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 59, w[59]); - w[60] = ADD4_32(WSIGMA1_AVX(w[58]), w[44], w[53], WSIGMA0_AVX(w[45])); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 60, w[60]); - w[61] = ADD4_32(WSIGMA1_AVX(w[59]), w[45], w[54], WSIGMA0_AVX(w[46])); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 61, w[61]); - w[62] = ADD4_32(WSIGMA1_AVX(w[60]), w[46], w[55], WSIGMA0_AVX(w[47])); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 62, w[62]); - w[63] = ADD4_32(WSIGMA1_AVX(w[61]), w[47], w[56], WSIGMA0_AVX(w[48])); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 63, w[63]); - - // Feed Forward - ctx->s[0] = ADD32(s[0], ctx->s[0]); - ctx->s[1] = ADD32(s[1], ctx->s[1]); - ctx->s[2] = ADD32(s[2], ctx->s[2]); - ctx->s[3] = ADD32(s[3], ctx->s[3]); - ctx->s[4] = ADD32(s[4], ctx->s[4]); - ctx->s[5] = ADD32(s[5], ctx->s[5]); - ctx->s[6] = ADD32(s[6], ctx->s[6]); - ctx->s[7] = ADD32(s[7], ctx->s[7]); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_avx2/sha256avx.h b/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_avx2/sha256avx.h deleted file mode 100644 index dda7c53144..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_avx2/sha256avx.h +++ /dev/null @@ -1,103 +0,0 @@ -#ifndef SHA256AVX_H -#define SHA256AVX_H - -#include -#include - -static const unsigned int RC[] = { - 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, - 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, - 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, - 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, - 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, - 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, - 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, - 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, - 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, - 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, - 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, - 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, - 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, - 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, - 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, - 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 -}; - -#define u32 uint32_t -#define u256 __m256i - -#define XOR _mm256_xor_si256 -#define OR _mm256_or_si256 -#define AND _mm256_and_si256 -#define ADD32 _mm256_add_epi32 -#define NOT(x) _mm256_xor_si256(x, _mm256_set_epi32(-1, -1, -1, -1, -1, -1, -1, -1)) - -#define LOAD(src) _mm256_loadu_si256((__m256i *)(src)) -#define STORE(dest,src) _mm256_storeu_si256((__m256i *)(dest),src) - -#define BYTESWAP(x) _mm256_shuffle_epi8(x, _mm256_set_epi8(0xc,0xd,0xe,0xf,0x8,0x9,0xa,0xb,0x4,0x5,0x6,0x7,0x0,0x1,0x2,0x3,0xc,0xd,0xe,0xf,0x8,0x9,0xa,0xb,0x4,0x5,0x6,0x7,0x0,0x1,0x2,0x3)) - -#define SHIFTR32(x, y) _mm256_srli_epi32(x, y) -#define SHIFTL32(x, y) _mm256_slli_epi32(x, y) - -#define ROTR32(x, y) OR(SHIFTR32(x, y), SHIFTL32(x, 32 - (y))) -#define ROTL32(x, y) OR(SHIFTL32(x, y), SHIFTR32(x, 32 - (y))) - -#define XOR3(a, b, c) XOR(XOR(a, b), c) - -#define ADD3_32(a, b, c) ADD32(ADD32(a, b), c) -#define ADD4_32(a, b, c, d) ADD32(ADD32(ADD32(a, b), c), d) -#define ADD5_32(a, b, c, d, e) ADD32(ADD32(ADD32(ADD32(a, b), c), d), e) - -#define MAJ_AVX(a, b, c) XOR3(AND(a, b), AND(a, c), AND(b, c)) -#define CH_AVX(a, b, c) XOR(AND(a, b), AND(NOT(a), c)) - -#define SIGMA1_AVX(x) XOR3(ROTR32(x, 6), ROTR32(x, 11), ROTR32(x, 25)) -#define SIGMA0_AVX(x) XOR3(ROTR32(x, 2), ROTR32(x, 13), ROTR32(x, 22)) - -#define WSIGMA1_AVX(x) XOR3(ROTR32(x, 17), ROTR32(x, 19), SHIFTR32(x, 10)) -#define WSIGMA0_AVX(x) XOR3(ROTR32(x, 7), ROTR32(x, 18), SHIFTR32(x, 3)) - -#define SHA256ROUND_AVX(a, b, c, d, e, f, g, h, rc, w) \ - T0 = ADD5_32(h, SIGMA1_AVX(e), CH_AVX(e, f, g), _mm256_set1_epi32((int)RC[rc]), w); \ - (d) = ADD32(d, T0); \ - T1 = ADD32(SIGMA0_AVX(a), MAJ_AVX(a, b, c)); \ - (h) = ADD32(T0, T1); - -typedef struct SHA256state { - u256 s[8]; - uint8_t msgblocks[8 * 64]; - unsigned int datalen; - uint64_t msglen; -} sha256ctxx8; - - -void PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_transpose(u256 s[8]); -void PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_sha256_init_frombytes_x8(sha256ctxx8 *ctx, const uint8_t *s, unsigned long long msglen); -void PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_sha256_init8x(sha256ctxx8 *ctx); -void PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_sha256_update8x(sha256ctxx8 *ctx, - const unsigned char *d0, - const unsigned char *d1, - const unsigned char *d2, - const unsigned char *d3, - const unsigned char *d4, - const unsigned char *d5, - const unsigned char *d6, - const unsigned char *d7, - unsigned long long len); -void PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_sha256_final8x(sha256ctxx8 *ctx, - unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7); - -void PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_sha256_transform8x(sha256ctxx8 *ctx, const unsigned char *data); - -void PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_sha256_clone_statex8(sha256ctxx8 *outctx, const sha256ctxx8 *inctx); - - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_avx2/sha256x8.c b/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_avx2/sha256x8.c deleted file mode 100644 index ce20013aab..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_avx2/sha256x8.c +++ /dev/null @@ -1,128 +0,0 @@ -#include - -#include "sha256.h" -#include "sha256avx.h" -#include "sha256x8.h" -#include "utils.h" - -void PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_seed_statex8(sha256ctxx8 *ctx, const unsigned char *pub_seed) { - uint8_t block[PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_BLOCK_BYTES]; - size_t i; - - for (i = 0; i < PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N; ++i) { - block[i] = pub_seed[i]; - } - for (i = PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N; i < PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_BLOCK_BYTES; ++i) { - block[i] = 0; - } - - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_sha256_init8x(ctx); - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_sha256_update8x(ctx, block, block, block, block, block, block, block, block, PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_BLOCK_BYTES); - -} - -/* This provides a wrapper around the internals of 8x parallel SHA256 */ -void PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_sha256x8(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - const unsigned char *in4, - const unsigned char *in5, - const unsigned char *in6, - const unsigned char *in7, unsigned long long inlen) { - sha256ctxx8 ctx; - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_sha256_init8x(&ctx); - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_sha256_update8x(&ctx, in0, in1, in2, in3, in4, in5, in6, in7, inlen); - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_sha256_final8x(&ctx, out0, out1, out2, out3, out4, out5, out6, out7); -} - -/** - * Note that inlen should be sufficiently small that it still allows for - * an array to be allocated on the stack. Typically 'in' is merely a seed. - * Outputs outlen number of bytes - */ -void PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_mgf1x8( - unsigned char *outx8, - unsigned long outlen, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - const unsigned char *in4, - const unsigned char *in5, - const unsigned char *in6, - const unsigned char *in7, - unsigned long inlen) { - unsigned char inbufx8[8 * ((PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_ADDR_BYTES) + 4)]; - unsigned char outbufx8[8 * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_OUTPUT_BYTES]; - unsigned long i; - unsigned int j; - - memcpy(inbufx8 + 0 * (inlen + 4), in0, inlen); - memcpy(inbufx8 + 1 * (inlen + 4), in1, inlen); - memcpy(inbufx8 + 2 * (inlen + 4), in2, inlen); - memcpy(inbufx8 + 3 * (inlen + 4), in3, inlen); - memcpy(inbufx8 + 4 * (inlen + 4), in4, inlen); - memcpy(inbufx8 + 5 * (inlen + 4), in5, inlen); - memcpy(inbufx8 + 6 * (inlen + 4), in6, inlen); - memcpy(inbufx8 + 7 * (inlen + 4), in7, inlen); - - /* While we can fit in at least another full block of SHA256 output.. */ - for (i = 0; (i + 1)*PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_OUTPUT_BYTES <= outlen; i++) { - for (j = 0; j < 8; j++) { - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_ull_to_bytes(inbufx8 + inlen + j * (inlen + 4), 4, i); - } - - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_sha256x8(outx8 + 0 * outlen, - outx8 + 1 * outlen, - outx8 + 2 * outlen, - outx8 + 3 * outlen, - outx8 + 4 * outlen, - outx8 + 5 * outlen, - outx8 + 6 * outlen, - outx8 + 7 * outlen, - inbufx8 + 0 * (inlen + 4), - inbufx8 + 1 * (inlen + 4), - inbufx8 + 2 * (inlen + 4), - inbufx8 + 3 * (inlen + 4), - inbufx8 + 4 * (inlen + 4), - inbufx8 + 5 * (inlen + 4), - inbufx8 + 6 * (inlen + 4), - inbufx8 + 7 * (inlen + 4), inlen + 4); - outx8 += PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_OUTPUT_BYTES; - } - /* Until we cannot anymore, and we fill the remainder. */ - for (j = 0; j < 8; j++) { - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_ull_to_bytes(inbufx8 + inlen + j * (inlen + 4), 4, i); - } - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_sha256x8(outbufx8 + 0 * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 1 * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 2 * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 3 * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 4 * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 5 * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 6 * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 7 * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_OUTPUT_BYTES, - inbufx8 + 0 * (inlen + 4), - inbufx8 + 1 * (inlen + 4), - inbufx8 + 2 * (inlen + 4), - inbufx8 + 3 * (inlen + 4), - inbufx8 + 4 * (inlen + 4), - inbufx8 + 5 * (inlen + 4), - inbufx8 + 6 * (inlen + 4), - inbufx8 + 7 * (inlen + 4), inlen + 4); - - for (j = 0; j < 8; j++) { - memcpy(outx8 + j * outlen, - outbufx8 + j * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_OUTPUT_BYTES, - outlen - i * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_OUTPUT_BYTES); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_avx2/sha256x8.h b/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_avx2/sha256x8.h deleted file mode 100644 index 05c191d494..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_avx2/sha256x8.h +++ /dev/null @@ -1,44 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256X8_H -#define PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256X8_H - -#include "sha256avx.h" - -#define PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_BLOCK_BYTES 64 -#define PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_OUTPUT_BYTES 32 /* This does not necessarily equal PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N */ - -/* This provides a wrapper around the internals of 8x parallel SHA256 */ -void PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_sha256x8(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - const unsigned char *in4, - const unsigned char *in5, - const unsigned char *in6, - const unsigned char *in7, unsigned long long inlen); - -/** - * Note that inlen should be sufficiently small that it still allows for - * an array to be allocated on the stack. Typically 'in' is merely a seed. - * Outputs outlen number of bytes - */ -void PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_mgf1x8(unsigned char *outx8, unsigned long outlen, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - const unsigned char *in4, - const unsigned char *in5, - const unsigned char *in6, - const unsigned char *in7, - unsigned long inlen); - -void PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_seed_statex8(sha256ctxx8 *ctx, const unsigned char *pub_seed); -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_avx2/sign.c b/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_avx2/sign.c deleted file mode 100644 index 6cde92c277..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_avx2/sign.c +++ /dev/null @@ -1,356 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "api.h" -#include "fors.h" -#include "hash.h" -#include "hash_state.h" -#include "params.h" -#include "randombytes.h" -#include "thash.h" -#include "utils.h" -#include "wots.h" - -/** - * Computes the leaf at a given address. First generates the WOTS key pair, - * then computes leaf by hashing horizontally. - */ -static void wots_gen_leaf(unsigned char *leaf, const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx, const uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - unsigned char pk[PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_WOTS_BYTES]; - uint32_t wots_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_set_type( - wots_addr, PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_set_type( - wots_pk_addr, PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_ADDR_TYPE_WOTSPK); - - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_set_keypair_addr( - wots_addr, addr_idx); - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_wots_gen_pk( - pk, sk_seed, pub_seed, wots_addr, hash_state_seeded); - - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_copy_keypair_addr( - wots_pk_addr, wots_addr); - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_thash_WOTS_LEN( - leaf, pk, pub_seed, wots_pk_addr, hash_state_seeded); -} - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_crypto_sign_secretkeybytes(void) { - return PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_CRYPTO_SECRETKEYBYTES; -} - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_crypto_sign_publickeybytes(void) { - return PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_CRYPTO_PUBLICKEYBYTES; -} - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_crypto_sign_bytes(void) { - return PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_CRYPTO_BYTES; -} - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_crypto_sign_seedbytes(void) { - return PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_CRYPTO_SEEDBYTES; -} - -/* - * Generates an SPX key pair given a seed of length - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed) { - /* We do not need the auth path in key generation, but it simplifies the - code to have just one treehash routine that computes both root and path - in one function. */ - unsigned char auth_path[PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_TREE_HEIGHT * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N]; - uint32_t top_tree_addr[8] = {0}; - hash_state hash_state_seeded; - - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_set_layer_addr( - top_tree_addr, PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_D - 1); - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_set_type( - top_tree_addr, PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_ADDR_TYPE_HASHTREE); - - /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ - memcpy(sk, seed, PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_CRYPTO_SEEDBYTES); - - memcpy(pk, sk + 2 * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N, PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_initialize_hash_function(&hash_state_seeded, pk, sk); - - /* Compute root node of the top-most subtree. */ - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_treehash_TREE_HEIGHT( - sk + 3 * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N, auth_path, sk, sk + 2 * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N, 0, 0, - wots_gen_leaf, top_tree_addr, &hash_state_seeded); - - memcpy(pk + PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N, sk + 3 * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N, PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N); - - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_destroy_hash_function(&hash_state_seeded); - return 0; -} - -/* - * Generates an SPX key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk) { - unsigned char seed[PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_CRYPTO_SEEDBYTES]; - randombytes(seed, PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_CRYPTO_SEEDBYTES); - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_crypto_sign_seed_keypair( - pk, sk, seed); - - return 0; -} - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - const unsigned char *sk_seed = sk; - const unsigned char *sk_prf = sk + PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N; - const unsigned char *pk = sk + 2 * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N; - const unsigned char *pub_seed = pk; - - unsigned char optrand[PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N]; - unsigned char mhash[PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_FORS_MSG_BYTES]; - unsigned char root[PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N]; - uint32_t i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - - hash_state hash_state_seeded; - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_initialize_hash_function( - &hash_state_seeded, - pub_seed, sk_seed); - - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_set_type( - wots_addr, PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_set_type( - tree_addr, PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_ADDR_TYPE_HASHTREE); - - /* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ - randombytes(optrand, PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N); - /* Compute the digest randomization value. */ - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_gen_message_random( - sig, sk_prf, optrand, m, mlen, &hash_state_seeded); - - /* Derive the message digest and leaf index from R, PK and M. */ - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N; - - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_set_keypair_addr( - wots_addr, idx_leaf); - - /* Sign the message hash using FORS. */ - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_fors_sign( - sig, root, mhash, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_FORS_BYTES; - - for (i = 0; i < PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_D; i++) { - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_set_tree_addr(tree_addr, tree); - - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_set_keypair_addr( - wots_addr, idx_leaf); - - /* Compute a WOTS signature. */ - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_wots_sign( - sig, root, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_WOTS_BYTES; - - /* Compute the authentication path for the used WOTS leaf. */ - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_treehash_TREE_HEIGHT( - root, sig, sk_seed, pub_seed, idx_leaf, 0, - wots_gen_leaf, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_TREE_HEIGHT * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_TREE_HEIGHT; - } - - *siglen = PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_BYTES; - - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_destroy_hash_function(&hash_state_seeded); - return 0; -} - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk) { - const unsigned char *pub_seed = pk; - const unsigned char *pub_root = pk + PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N; - unsigned char mhash[PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_FORS_MSG_BYTES]; - unsigned char wots_pk[PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_WOTS_BYTES]; - unsigned char root[PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N]; - unsigned char leaf[PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N]; - unsigned int i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - hash_state hash_state_seeded; - - if (siglen != PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_BYTES) { - return -1; - } - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_initialize_hash_function( - &hash_state_seeded, - pub_seed, NULL); - - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_set_type( - wots_addr, PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_set_type( - tree_addr, PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_ADDR_TYPE_HASHTREE); - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_set_type( - wots_pk_addr, PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_ADDR_TYPE_WOTSPK); - - /* Derive the message digest and leaf index from R || PK || M. */ - /* The additional PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N is a result of the hash domain separator. */ - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N; - - /* Layer correctly defaults to 0, so no need to set_layer_addr */ - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_set_keypair_addr( - wots_addr, idx_leaf); - - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_fors_pk_from_sig( - root, sig, mhash, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_FORS_BYTES; - - /* For each subtree.. */ - for (i = 0; i < PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_D; i++) { - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_set_tree_addr(tree_addr, tree); - - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_set_keypair_addr( - wots_addr, idx_leaf); - - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_copy_keypair_addr( - wots_pk_addr, wots_addr); - - /* The WOTS public key is only correct if the signature was correct. */ - /* Initially, root is the FORS pk, but on subsequent iterations it is - the root of the subtree below the currently processed subtree. */ - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_wots_pk_from_sig( - wots_pk, sig, root, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_WOTS_BYTES; - - /* Compute the leaf node using the WOTS public key. */ - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_thash_WOTS_LEN( - leaf, wots_pk, pub_seed, wots_pk_addr, &hash_state_seeded); - - /* Compute the root node of this subtree. */ - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_compute_root( - root, leaf, idx_leaf, 0, sig, PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_TREE_HEIGHT, - pub_seed, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_TREE_HEIGHT * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_TREE_HEIGHT; - } - - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_destroy_hash_function(&hash_state_seeded); - /* Check if the root node equals the root node in the public key. */ - if (memcmp(root, pub_root, PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N) != 0) { - return -1; - } - - return 0; -} - - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - size_t siglen; - - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_crypto_sign_signature( - sm, &siglen, m, mlen, sk); - - memmove(sm + PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_BYTES, m, mlen); - *smlen = siglen + mlen; - - return 0; -} - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk) { - /* The API caller does not necessarily know what size a signature should be - but SPHINCS+ signatures are always exactly PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_BYTES. */ - if (smlen < PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_BYTES) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - *mlen = smlen - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_BYTES; - - if (PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_crypto_sign_verify( - sm, PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_BYTES, sm + PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_BYTES, *mlen, pk)) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - /* If verification was successful, move the message to the right place. */ - memmove(m, sm + PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_BYTES, *mlen); - - return 0; -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_avx2/thash.h b/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_avx2/thash.h deleted file mode 100644 index 52ce115bcd..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_avx2/thash.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_THASH_H -#define PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_THASH_H - -#include "hash_state.h" - -#include - -void PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_avx2/thash_sha256_robust.c b/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_avx2/thash_sha256_robust.c deleted file mode 100644 index 157e8ff545..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_avx2/thash_sha256_robust.c +++ /dev/null @@ -1,78 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "thash.h" - -#include "sha2.h" -#include "sha256.h" - -/** - * Takes an array of inblocks concatenated arrays of PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N bytes. - */ -static void thash( - unsigned char *out, unsigned char *buf, - const unsigned char *in, unsigned int inblocks, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char outbuf[PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_OUTPUT_BYTES]; - unsigned char *bitmask = buf + PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_ADDR_BYTES + 4; - sha256ctx sha2_state; - unsigned int i; - - memcpy(buf, pub_seed, PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N); - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_compress_address(buf + PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N, addr); - /* MGF1 requires us to have 4 extra bytes in 'buf' */ - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_mgf1(bitmask, inblocks * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N, buf, PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_ADDR_BYTES); - - /* Retrieve precomputed state containing pub_seed */ - sha256_inc_ctx_clone(&sha2_state, &hash_state_seeded->x1); - - for (i = 0; i < inblocks * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N; i++) { - buf[PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_ADDR_BYTES + i] = in[i] ^ bitmask[i]; - } - - sha256_inc_finalize(outbuf, &sha2_state, buf + PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N, - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N); - memcpy(out, outbuf, PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N); -} - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_ADDR_BYTES + 4 + 1 * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N]; - thash(out, buf, in, 1, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_ADDR_BYTES + 4 + 2 * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N]; - thash(out, buf, in, 2, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_ADDR_BYTES + 4 + PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_WOTS_LEN * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N]; - thash(out, buf, in, PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_WOTS_LEN, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_ADDR_BYTES + 4 + PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_FORS_TREES * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N]; - thash(out, buf, in, PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_FORS_TREES, pub_seed, addr, hash_state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_avx2/thash_sha256_robustx8.c b/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_avx2/thash_sha256_robustx8.c deleted file mode 100644 index 032df5d08d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_avx2/thash_sha256_robustx8.c +++ /dev/null @@ -1,156 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "sha256.h" -#include "sha256avx.h" -#include "sha256x8.h" -#include "thashx8.h" -#include "utils.h" - -/** - * 8-way parallel version of thash; takes 8x as much input and output - */ -static void thashx8(uint8_t *out0, - uint8_t *out1, - uint8_t *out2, - uint8_t *out3, - uint8_t *out4, - uint8_t *out5, - uint8_t *out6, - uint8_t *out7, - const uint8_t *in0, - const uint8_t *in1, - const uint8_t *in2, - const uint8_t *in3, - const uint8_t *in4, - const uint8_t *in5, - const uint8_t *in6, - const uint8_t *in7, - unsigned int inblocks, - const uint8_t *pub_seed, - uint32_t addrx8[8 * 8], - uint8_t *bufx8, - uint8_t *bitmaskx8, - const hash_state *state_seeded) { - unsigned char outbufx8[8 * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_OUTPUT_BYTES]; - unsigned int i; - sha256ctxx8 ctx; - - (void)pub_seed; /* Suppress an 'unused parameter' warning. */ - - for (i = 0; i < 8; i++) { - memcpy(bufx8 + i * (PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N), - pub_seed, PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N); - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_compress_address(bufx8 + PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N + - i * (PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N), - addrx8 + i * 8); - } - - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_mgf1x8(bitmaskx8, inblocks * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N, - bufx8 + 0 * (PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N), - bufx8 + 1 * (PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N), - bufx8 + 2 * (PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N), - bufx8 + 3 * (PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N), - bufx8 + 4 * (PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N), - bufx8 + 5 * (PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N), - bufx8 + 6 * (PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N), - bufx8 + 7 * (PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N), - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_ADDR_BYTES - ); - - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_sha256_clone_statex8(&ctx, &state_seeded->x8); - - for (i = 0; i < inblocks * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N; i++) { - bufx8[PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_ADDR_BYTES + i + - 0 * (PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N)] = - in0[i] ^ bitmaskx8[i + 0 * (inblocks * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N)]; - bufx8[PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_ADDR_BYTES + i + - 1 * (PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N)] = - in1[i] ^ bitmaskx8[i + 1 * (inblocks * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N)]; - bufx8[PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_ADDR_BYTES + i + - 2 * (PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N)] = - in2[i] ^ bitmaskx8[i + 2 * (inblocks * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N)]; - bufx8[PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_ADDR_BYTES + i + - 3 * (PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N)] = - in3[i] ^ bitmaskx8[i + 3 * (inblocks * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N)]; - bufx8[PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_ADDR_BYTES + i + - 4 * (PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N)] = - in4[i] ^ bitmaskx8[i + 4 * (inblocks * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N)]; - bufx8[PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_ADDR_BYTES + i + - 5 * (PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N)] = - in5[i] ^ bitmaskx8[i + 5 * (inblocks * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N)]; - bufx8[PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_ADDR_BYTES + i + - 6 * (PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N)] = - in6[i] ^ bitmaskx8[i + 6 * (inblocks * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N)]; - bufx8[PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_ADDR_BYTES + i + - 7 * (PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N)] = - in7[i] ^ bitmaskx8[i + 7 * (inblocks * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N)]; - } - - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_sha256_update8x(&ctx, - bufx8 + PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N + 0 * (PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N), - bufx8 + PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N + 1 * (PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N), - bufx8 + PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N + 2 * (PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N), - bufx8 + PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N + 3 * (PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N), - bufx8 + PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N + 4 * (PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N), - bufx8 + PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N + 5 * (PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N), - bufx8 + PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N + 6 * (PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N), - bufx8 + PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N + 7 * (PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N), - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N); - - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_sha256_final8x(&ctx, - outbufx8 + 0 * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 1 * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 2 * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 3 * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 4 * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 5 * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 6 * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 7 * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_OUTPUT_BYTES); - - memcpy(out0, outbufx8 + 0 * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N); - memcpy(out1, outbufx8 + 1 * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N); - memcpy(out2, outbufx8 + 2 * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N); - memcpy(out3, outbufx8 + 3 * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N); - memcpy(out4, outbufx8 + 4 * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N); - memcpy(out5, outbufx8 + 5 * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N); - memcpy(out6, outbufx8 + 6 * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N); - memcpy(out7, outbufx8 + 7 * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N); -} - -#define thash_size_variant(name, size) \ - void PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_thashx8_##name(unsigned char *out0, \ - unsigned char *out1, \ - unsigned char *out2, \ - unsigned char *out3, \ - unsigned char *out4, \ - unsigned char *out5, \ - unsigned char *out6, \ - unsigned char *out7, \ - const unsigned char *in0, \ - const unsigned char *in1, \ - const unsigned char *in2, \ - const unsigned char *in3, \ - const unsigned char *in4, \ - const unsigned char *in5, \ - const unsigned char *in6, \ - const unsigned char *in7, \ - const unsigned char *pub_seed, \ - uint32_t addrx8[8*8], \ - const hash_state *state_seeded) { \ - const unsigned int inblocks = (size); \ - uint8_t bufx8[8*(PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_SHA256_ADDR_BYTES + (size)*PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N)]; \ - uint8_t bitmaskx8[8*((size) * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N)]; \ - thashx8(out0, out1, out2, out3, out4, out5, out6, out7, \ - in0, in1, in2, in3, in4, in5, in6, in7, inblocks, \ - pub_seed, addrx8, bufx8, bitmaskx8, state_seeded); \ - } - -thash_size_variant(1, 1) -thash_size_variant(2, 2) -thash_size_variant(WOTS_LEN, PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_WOTS_LEN) -thash_size_variant(FORS_TREES, PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_FORS_TREES) - -#undef thash_size_variant diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_avx2/thashx8.h b/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_avx2/thashx8.h deleted file mode 100644 index 3f08c7d3d7..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_avx2/thashx8.h +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_THASHX8_H -#define PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_THASHX8_H - -#include - -#include "hash_state.h" -#include "sha256avx.h" - - -#define thashx8_variant(name) \ - void PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_thashx8_##name( \ - unsigned char *out0, \ - unsigned char *out1, \ - unsigned char *out2, \ - unsigned char *out3, \ - unsigned char *out4, \ - unsigned char *out5, \ - unsigned char *out6, \ - unsigned char *out7, \ - const unsigned char *in0, \ - const unsigned char *in1, \ - const unsigned char *in2, \ - const unsigned char *in3, \ - const unsigned char *in4, \ - const unsigned char *in5, \ - const unsigned char *in6, \ - const unsigned char *in7, \ - const unsigned char *pub_seed, \ - uint32_t addrx8[8*8], \ - const hash_state *state_seeded) - - -thashx8_variant(1); -thashx8_variant(2); -thashx8_variant(WOTS_LEN); -thashx8_variant(FORS_TREES); - -#undef thashx8_variant -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_avx2/utils.c b/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_avx2/utils.c deleted file mode 100644 index 45cc5764f0..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_avx2/utils.c +++ /dev/null @@ -1,199 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "hash_state.h" -#include "params.h" -#include "thash.h" -#include "utils.h" - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in) { - - /* Iterate over out in decreasing order, for big-endianness. */ - for (size_t i = outlen; i > 0; i--) { - out[i - 1] = in & 0xff; - in = in >> 8; - } -} - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_bytes_to_ull( - const unsigned char *in, size_t inlen) { - unsigned long long retval = 0; - - for (size_t i = 0; i < inlen; i++) { - retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); - } - return retval; -} - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - uint32_t i; - unsigned char buffer[2 * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N]; - - /* If leaf_idx is odd (last bit = 1), current path element is a right child - and auth_path has to go left. Otherwise it is the other way around. */ - if (leaf_idx & 1) { - memcpy(buffer + PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N, leaf, PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N); - } else { - memcpy(buffer, leaf, PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N); - memcpy(buffer + PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N, auth_path, PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N); - } - auth_path += PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N; - - for (i = 0; i < tree_height - 1; i++) { - leaf_idx >>= 1; - idx_offset >>= 1; - /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_set_tree_height(addr, i + 1); - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_set_tree_index( - addr, leaf_idx + idx_offset); - - /* Pick the right or left neighbor, depending on parity of the node. */ - if (leaf_idx & 1) { - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_thash_2( - buffer + PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N); - } else { - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_thash_2( - buffer, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer + PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N, auth_path, PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N); - } - auth_path += PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N; - } - - /* The last iteration is exceptional; we do not copy an auth_path node. */ - leaf_idx >>= 1; - idx_offset >>= 1; - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_set_tree_height(addr, tree_height); - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_set_tree_index( - addr, leaf_idx + idx_offset); - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_thash_2( - root, buffer, pub_seed, addr, hash_state_seeded); -} - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -static void PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_treehash( - unsigned char *root, unsigned char *auth_path, - unsigned char *stack, unsigned int *heights, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - - unsigned int offset = 0; - uint32_t idx; - uint32_t tree_idx; - - for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { - /* Add the next leaf node to the stack. */ - gen_leaf(stack + offset * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N, - sk_seed, pub_seed, idx + idx_offset, tree_addr, - hash_state_seeded); - offset++; - heights[offset - 1] = 0; - - /* If this is a node we need for the auth path.. */ - if ((leaf_idx ^ 0x1) == idx) { - memcpy(auth_path, stack + (offset - 1)*PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N, PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N); - } - - /* While the top-most nodes are of equal height.. */ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { - /* Compute index of the new node, in the next layer. */ - tree_idx = (idx >> (heights[offset - 1] + 1)); - - /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_set_tree_height( - tree_addr, heights[offset - 1] + 1); - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_set_tree_index( - tree_addr, tree_idx + (idx_offset >> (heights[offset - 1] + 1))); - /* Hash the top-most nodes from the stack together. */ - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_thash_2( - stack + (offset - 2)*PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N, stack + (offset - 2)*PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N, - pub_seed, tree_addr, hash_state_seeded); - offset--; - /* Note that the top-most node is now one layer higher. */ - heights[offset - 1]++; - - /* If this is a node we need for the auth path.. */ - if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_path + heights[offset - 1]*PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N, - stack + (offset - 1)*PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N, PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N); - } - } - } - memcpy(root, stack, PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N); -} - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_FORS_HEIGHT + 1)*PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N]; - unsigned int heights[PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_FORS_HEIGHT + 1]; - - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_FORS_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_TREE_HEIGHT + 1)*PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N]; - unsigned int heights[PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_TREE_HEIGHT + 1]; - - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_TREE_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_avx2/utils.h b/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_avx2/utils.h deleted file mode 100644 index c2f1b6fbab..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_avx2/utils.h +++ /dev/null @@ -1,64 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_UTILS_H -#define PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_UTILS_H - -#include "hash_state.h" -#include "params.h" -#include -#include - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in); - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_bytes_to_ull( - const unsigned char *in, size_t inlen); - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -void PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_avx2/utilsx8.c b/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_avx2/utilsx8.c deleted file mode 100644 index a46d16de97..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_avx2/utilsx8.c +++ /dev/null @@ -1,172 +0,0 @@ -#include - -#include "address.h" -#include "params.h" -#include "thashx8.h" -#include "utils.h" - -#include "utilsx8.h" - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -static void treehashx8(unsigned char *rootx8, unsigned char *auth_pathx8, - unsigned char *stackx8, unsigned int *heights, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t leaf_idx[8], uint32_t idx_offset[8], - uint32_t tree_height, - void (*gen_leafx8)( - unsigned char * /* leaf0 */, - unsigned char * /* leaf1 */, - unsigned char * /* leaf2 */, - unsigned char * /* leaf3 */, - unsigned char * /* leaf4 */, - unsigned char * /* leaf5 */, - unsigned char * /* leaf6 */, - unsigned char * /* leaf7 */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx0 */, - uint32_t /* addr_idx1 */, - uint32_t /* addr_idx2 */, - uint32_t /* addr_idx3 */, - uint32_t /* addr_idx4 */, - uint32_t /* addr_idx5 */, - uint32_t /* addr_idx6 */, - uint32_t /* addr_idx7 */, - const uint32_t[8] /* tree_addr */, - const hash_state * /* state_seeded */), - uint32_t tree_addrx8[8 * 8], - const hash_state *state_seeded) { - unsigned int offset = 0; - uint32_t idx; - uint32_t tree_idx; - unsigned int j; - - for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { - /* Add the next leaf node to the stack. */ - gen_leafx8(stackx8 + 0 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N + offset * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N, - stackx8 + 1 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N + offset * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N, - stackx8 + 2 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N + offset * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N, - stackx8 + 3 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N + offset * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N, - stackx8 + 4 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N + offset * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N, - stackx8 + 5 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N + offset * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N, - stackx8 + 6 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N + offset * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N, - stackx8 + 7 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N + offset * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N, - sk_seed, pub_seed, - idx + idx_offset[0], - idx + idx_offset[1], - idx + idx_offset[2], - idx + idx_offset[3], - idx + idx_offset[4], - idx + idx_offset[5], - idx + idx_offset[6], - idx + idx_offset[7], - tree_addrx8, - state_seeded); - offset++; - heights[offset - 1] = 0; - - /* If this is a node we need for the auth path.. */ - for (j = 0; j < 8; j++) { - if ((leaf_idx[j] ^ 0x1) == idx) { - memcpy(auth_pathx8 + j * tree_height * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N, - stackx8 + j * (tree_height + 1)*PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N + (offset - 1)*PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N, PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N); - } - } - - /* While the top-most nodes are of equal height.. */ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { - /* Compute index of the new node, in the next layer. */ - tree_idx = (idx >> (heights[offset - 1] + 1)); - - /* Set the address of the node we're creating. */ - for (j = 0; j < 8; j++) { - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_set_tree_height(tree_addrx8 + j * 8, heights[offset - 1] + 1); - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_set_tree_index(tree_addrx8 + j * 8, - tree_idx + (idx_offset[j] >> (heights[offset - 1] + 1))); - } - /* Hash the top-most nodes from the stack together. */ - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_thashx8_2(stackx8 + 0 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N, - stackx8 + 1 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N, - stackx8 + 2 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N, - stackx8 + 3 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N, - stackx8 + 4 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N, - stackx8 + 5 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N, - stackx8 + 6 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N, - stackx8 + 7 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N, - stackx8 + 0 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N, - stackx8 + 1 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N, - stackx8 + 2 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N, - stackx8 + 3 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N, - stackx8 + 4 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N, - stackx8 + 5 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N, - stackx8 + 6 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N, - stackx8 + 7 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N, - pub_seed, tree_addrx8, state_seeded); - offset--; - /* Note that the top-most node is now one layer higher. */ - heights[offset - 1]++; - - /* If this is a node we need for the auth path.. */ - for (j = 0; j < 8; j++) { - if (((leaf_idx[j] >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_pathx8 + j * tree_height * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N + heights[offset - 1]*PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N, - stackx8 + j * (tree_height + 1)*PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N + (offset - 1)*PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N, PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N); - } - } - } - } - - for (j = 0; j < 8; j++) { - memcpy(rootx8 + j * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N, stackx8 + j * (tree_height + 1)*PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N, PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N); - } -} - -/* The wrappers below ensure we used fixed-size buffers on the stack (no VLAs) */ - - -#define treehashx8_variant(name, size) \ - void PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_treehashx8_##name( \ - unsigned char *rootx8, unsigned char *auth_pathx8, \ - const unsigned char *sk_seed, const unsigned char *pub_seed, \ - const uint32_t leaf_idx[8], uint32_t idx_offset[8], \ - void (*gen_leafx8)( \ - unsigned char* /* leaf0 */, \ - unsigned char* /* leaf1 */, \ - unsigned char* /* leaf2 */, \ - unsigned char* /* leaf3 */, \ - unsigned char* /* leaf4 */, \ - unsigned char* /* leaf5 */, \ - unsigned char* /* leaf6 */, \ - unsigned char* /* leaf7 */, \ - const unsigned char* /* sk_seed */, \ - const unsigned char* /* pub_seed */, \ - uint32_t /* addr_idx0 */, \ - uint32_t /* addr_idx1 */, \ - uint32_t /* addr_idx2 */, \ - uint32_t /* addr_idx3 */, \ - uint32_t /* addr_idx4 */, \ - uint32_t /* addr_idx5 */, \ - uint32_t /* addr_idx6 */, \ - uint32_t /* addr_idx7 */, \ - const uint32_t[8] /* tree_addr */, \ - const hash_state* /* state_seeded */), \ - uint32_t tree_addrx8[8*8], \ - const hash_state *state_seeded) \ - { \ - const uint32_t tree_height = (size); \ - unsigned char stackx8[8*((size) + 1)*PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N]; \ - unsigned int heights[(size) + 1]; \ - treehashx8(rootx8, auth_pathx8, stackx8, heights, sk_seed, pub_seed, \ - leaf_idx, idx_offset, tree_height, gen_leafx8, tree_addrx8, state_seeded); \ - } - -treehashx8_variant(FORS_HEIGHT, PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_FORS_HEIGHT) - -#undef treehashx8_variant diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_avx2/utilsx8.h b/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_avx2/utilsx8.h deleted file mode 100644 index b039cb5ec8..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_avx2/utilsx8.h +++ /dev/null @@ -1,46 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_UTILSX8_H -#define PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_UTILSX8_H - -#include - -#include "hash_state.h" -#include "params.h" - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ - -void PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_treehashx8_FORS_HEIGHT( - unsigned char *rootx8, unsigned char *auth_pathx8, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t leaf_idx[8], uint32_t idx_offset[8], - void (*gen_leafx8)( - unsigned char * /* leaf0 */, - unsigned char * /* leaf1 */, - unsigned char * /* leaf2 */, - unsigned char * /* leaf3 */, - unsigned char * /* leaf4 */, - unsigned char * /* leaf5 */, - unsigned char * /* leaf6 */, - unsigned char * /* leaf7 */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx0 */, - uint32_t /* addr_idx1 */, - uint32_t /* addr_idx2 */, - uint32_t /* addr_idx3 */, - uint32_t /* addr_idx4 */, - uint32_t /* addr_idx5 */, - uint32_t /* addr_idx6 */, - uint32_t /* addr_idx7 */, - const uint32_t[8] /* tree_addr */, - const hash_state * /* state_seeded */), - uint32_t tree_addrx8[8 * 8], - const hash_state *state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_avx2/wots.c b/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_avx2/wots.c deleted file mode 100644 index 7f416c3bb9..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_avx2/wots.c +++ /dev/null @@ -1,240 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "hash_state.h" -#include "hashx8.h" -#include "params.h" -#include "thash.h" -#include "thashx8.h" -#include "utils.h" -#include "wots.h" - -// TODO clarify address expectations, and make them more uniform. -// TODO i.e. do we expect types to be set already? -// TODO and do we expect modifications or copies? - -/** - * Computes the starting value for a chain, i.e. the secret key. - * Expects the address to be complete up to the chain address. - */ -static void wots_gen_sk(unsigned char *sk, const unsigned char *sk_seed, - uint32_t wots_addr[8], const hash_state *state_seeded) { - /* Make sure that the hash address is actually zeroed. */ - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_set_hash_addr(wots_addr, 0); - - /* Generate sk element. */ - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_prf_addr(sk, sk_seed, wots_addr, state_seeded); -} - -/** - * 8-way parallel version of wots_gen_sk; expects 8x as much space in sk - */ -static void wots_gen_skx8(unsigned char *skx8, const unsigned char *sk_seed, - uint32_t wots_addrx8[8 * 8]) { - unsigned int j; - - /* Make sure that the hash address is actually zeroed. */ - for (j = 0; j < 8; j++) { - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_set_hash_addr(wots_addrx8 + j * 8, 0); - } - - /* Generate sk element. */ - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_prf_addrx8(skx8 + 0 * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N, - skx8 + 1 * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N, - skx8 + 2 * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N, - skx8 + 3 * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N, - skx8 + 4 * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N, - skx8 + 5 * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N, - skx8 + 6 * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N, - skx8 + 7 * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N, - sk_seed, wots_addrx8); -} - -/** - * Computes the chaining function. - * out and in have to be n-byte arrays. - * - * Interprets in as start-th value of the chain. - * addr has to contain the address of the chain. - */ -static void gen_chain(unsigned char *out, const unsigned char *in, - unsigned int start, unsigned int steps, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *state_seeded) { - uint32_t i; - - /* Initialize out with the value at position 'start'. */ - memcpy(out, in, PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N); - - /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_WOTS_W; i++) { - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_set_hash_addr(addr, i); - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_thash_1(out, out, pub_seed, addr, state_seeded); - } -} - -/** - * 8-way parallel version of gen_chain; expects 8x as much space in out, and - * 8x as much space in inx8. Assumes start and step identical across chains. - */ -static void gen_chainx8(unsigned char *outx8, const unsigned char *inx8, - unsigned int start, unsigned int steps, - const unsigned char *pub_seed, uint32_t addrx8[8 * 8], - const hash_state *state_seeded) { - uint32_t i; - unsigned int j; - - /* Initialize outx8 with the value at position 'start'. */ - memcpy(outx8, inx8, 8 * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N); - - /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_WOTS_W; i++) { - for (j = 0; j < 8; j++) { - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_set_hash_addr(addrx8 + j * 8, i); - } - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_thashx8_1(outx8 + 0 * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N, - outx8 + 1 * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N, - outx8 + 2 * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N, - outx8 + 3 * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N, - outx8 + 4 * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N, - outx8 + 5 * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N, - outx8 + 6 * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N, - outx8 + 7 * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N, - outx8 + 0 * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N, - outx8 + 1 * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N, - outx8 + 2 * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N, - outx8 + 3 * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N, - outx8 + 4 * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N, - outx8 + 5 * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N, - outx8 + 6 * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N, - outx8 + 7 * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N, - pub_seed, addrx8, state_seeded); - } -} - -/** - * base_w algorithm as described in draft. - * Interprets an array of bytes as integers in base w. - * This only works when log_w is a divisor of 8. - */ -static void base_w(unsigned int *output, const int out_len, const unsigned char *input) { - int in = 0; - int out = 0; - unsigned char total = 0; - int bits = 0; - int consumed; - - for (consumed = 0; consumed < out_len; consumed++) { - if (bits == 0) { - total = input[in]; - in++; - bits += 8; - } - bits -= PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_WOTS_LOGW; - output[out] = (unsigned int)(total >> bits) & (PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_WOTS_W - 1); - out++; - } -} - -/* Computes the WOTS+ checksum over a message (in base_w). */ -static void wots_checksum(unsigned int *csum_base_w, const unsigned int *msg_base_w) { - unsigned int csum = 0; - unsigned char csum_bytes[(PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_WOTS_LEN2 * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_WOTS_LOGW + 7) / 8]; - unsigned int i; - - /* Compute checksum. */ - for (i = 0; i < PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_WOTS_LEN1; i++) { - csum += PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_WOTS_W - 1 - msg_base_w[i]; - } - - /* Convert checksum to base_w. */ - /* Make sure expected empty zero bits are the least significant bits. */ - csum = csum << (8 - ((PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_WOTS_LEN2 * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_WOTS_LOGW) % 8)); - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); - base_w(csum_base_w, PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_WOTS_LEN2, csum_bytes); -} - -/* Takes a message and derives the matching chain lengths. */ -static void chain_lengths(unsigned int *lengths, const unsigned char *msg) { - base_w(lengths, PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_WOTS_LEN1, msg); - wots_checksum(lengths + PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_WOTS_LEN1, lengths); -} - -/** - * WOTS key generation. Takes a 32 byte sk_seed, expands it to WOTS private key - * elements and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_wots_gen_pk(unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *state_seeded) { - uint32_t i; - unsigned int j; - - uint32_t addrx8[8 * 8]; - unsigned char pkbuf[8 * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N]; - - for (j = 0; j < 8; j++) { - memcpy(addrx8 + j * 8, addr, sizeof(uint32_t) * 8); - } - - /* The last iteration typically does not have complete set of 4 chains, - but because we use pkbuf, this is not an issue -- we still do as many - in parallel as possible. */ - for (i = 0; i < ((PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_WOTS_LEN + 7) & ~0x7); i += 8) { - for (j = 0; j < 8; j++) { - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_set_chain_addr(addrx8 + j * 8, i + j); - } - wots_gen_skx8(pkbuf, sk_seed, addrx8); - gen_chainx8(pkbuf, pkbuf, 0, PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_WOTS_W - 1, pub_seed, addrx8, state_seeded); - for (j = 0; j < 8; j++) { - if (i + j < PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_WOTS_LEN) { - memcpy(pk + (i + j)*PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N, pkbuf + j * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N, PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N); - } - } - } -} - -/** - * Takes a n-byte message and the 32-byte sk_see to compute a signature 'sig'. - */ -void PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_wots_sign(unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_WOTS_LEN; i++) { - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_set_chain_addr(addr, i); - wots_gen_sk(sig + i * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N, sk_seed, addr, state_seeded); - gen_chain(sig + i * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N, sig + i * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N, 0, lengths[i], pub_seed, addr, state_seeded); - } -} - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_WOTS_LEN; i++) { - PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_set_chain_addr(addr, i); - gen_chain(pk + i * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N, sig + i * PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_N, - lengths[i], PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_WOTS_W - 1 - lengths[i], pub_seed, addr, state_seeded); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_avx2/wots.h b/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_avx2/wots.h deleted file mode 100644 index dcd92bd2c4..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_avx2/wots.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_WOTS_H -#define PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_WOTS_H - -#include "hash_state.h" -#include "params.h" -#include - -/** - * WOTS key generation. Takes a 32 byte seed for the private key, expands it to - * a full WOTS private key and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_wots_gen_pk( - unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -/** - * Takes a n-byte message and the 32-byte seed for the private key to compute a - * signature that is placed at 'sig'. - */ -void PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_wots_sign( - unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *hash_state_seeded); - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHA256192FROBUST_AVX2_wots_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_clean/LICENSE b/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_clean/LICENSE deleted file mode 100644 index 670154e353..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_clean/LICENSE +++ /dev/null @@ -1,116 +0,0 @@ -CC0 1.0 Universal - -Statement of Purpose - -The laws of most jurisdictions throughout the world automatically confer -exclusive Copyright and Related Rights (defined below) upon the creator and -subsequent owner(s) (each and all, an "owner") of an original work of -authorship and/or a database (each, a "Work"). - -Certain owners wish to permanently relinquish those rights to a Work for the -purpose of contributing to a commons of creative, cultural and scientific -works ("Commons") that the public can reliably and without fear of later -claims of infringement build upon, modify, incorporate in other works, reuse -and redistribute as freely as possible in any form whatsoever and for any -purposes, including without limitation commercial purposes. These owners may -contribute to the Commons to promote the ideal of a free culture and the -further production of creative, cultural and scientific works, or to gain -reputation or greater distribution for their Work in part through the use and -efforts of others. - -For these and/or other purposes and motivations, and without any expectation -of additional consideration or compensation, the person associating CC0 with a -Work (the "Affirmer"), to the extent that he or she is an owner of Copyright -and Related Rights in the Work, voluntarily elects to apply CC0 to the Work -and publicly distribute the Work under its terms, with knowledge of his or her -Copyright and Related Rights in the Work and the meaning and intended legal -effect of CC0 on those rights. - -1. Copyright and Related Rights. A Work made available under CC0 may be -protected by copyright and related or neighboring rights ("Copyright and -Related Rights"). Copyright and Related Rights include, but are not limited -to, the following: - - i. the right to reproduce, adapt, distribute, perform, display, communicate, - and translate a Work; - - ii. moral rights retained by the original author(s) and/or performer(s); - - iii. publicity and privacy rights pertaining to a person's image or likeness - depicted in a Work; - - iv. rights protecting against unfair competition in regards to a Work, - subject to the limitations in paragraph 4(a), below; - - v. rights protecting the extraction, dissemination, use and reuse of data in - a Work; - - vi. database rights (such as those arising under Directive 96/9/EC of the - European Parliament and of the Council of 11 March 1996 on the legal - protection of databases, and under any national implementation thereof, - including any amended or successor version of such directive); and - - vii. other similar, equivalent or corresponding rights throughout the world - based on applicable law or treaty, and any national implementations thereof. - -2. Waiver. To the greatest extent permitted by, but not in contravention of, -applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and -unconditionally waives, abandons, and surrenders all of Affirmer's Copyright -and Related Rights and associated claims and causes of action, whether now -known or unknown (including existing as well as future claims and causes of -action), in the Work (i) in all territories worldwide, (ii) for the maximum -duration provided by applicable law or treaty (including future time -extensions), (iii) in any current or future medium and for any number of -copies, and (iv) for any purpose whatsoever, including without limitation -commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes -the Waiver for the benefit of each member of the public at large and to the -detriment of Affirmer's heirs and successors, fully intending that such Waiver -shall not be subject to revocation, rescission, cancellation, termination, or -any other legal or equitable action to disrupt the quiet enjoyment of the Work -by the public as contemplated by Affirmer's express Statement of Purpose. - -3. Public License Fallback. Should any part of the Waiver for any reason be -judged legally invalid or ineffective under applicable law, then the Waiver -shall be preserved to the maximum extent permitted taking into account -Affirmer's express Statement of Purpose. In addition, to the extent the Waiver -is so judged Affirmer hereby grants to each affected person a royalty-free, -non transferable, non sublicensable, non exclusive, irrevocable and -unconditional license to exercise Affirmer's Copyright and Related Rights in -the Work (i) in all territories worldwide, (ii) for the maximum duration -provided by applicable law or treaty (including future time extensions), (iii) -in any current or future medium and for any number of copies, and (iv) for any -purpose whatsoever, including without limitation commercial, advertising or -promotional purposes (the "License"). The License shall be deemed effective as -of the date CC0 was applied by Affirmer to the Work. Should any part of the -License for any reason be judged legally invalid or ineffective under -applicable law, such partial invalidity or ineffectiveness shall not -invalidate the remainder of the License, and in such case Affirmer hereby -affirms that he or she will not (i) exercise any of his or her remaining -Copyright and Related Rights in the Work or (ii) assert any associated claims -and causes of action with respect to the Work, in either case contrary to -Affirmer's express Statement of Purpose. - -4. Limitations and Disclaimers. - - a. No trademark or patent rights held by Affirmer are waived, abandoned, - surrendered, licensed or otherwise affected by this document. - - b. Affirmer offers the Work as-is and makes no representations or warranties - of any kind concerning the Work, express, implied, statutory or otherwise, - including without limitation warranties of title, merchantability, fitness - for a particular purpose, non infringement, or the absence of latent or - other defects, accuracy, or the present or absence of errors, whether or not - discoverable, all to the greatest extent permissible under applicable law. - - c. Affirmer disclaims responsibility for clearing rights of other persons - that may apply to the Work or any use thereof, including without limitation - any person's Copyright and Related Rights in the Work. Further, Affirmer - disclaims responsibility for obtaining any necessary consents, permissions - or other rights required for any use of the Work. - - d. Affirmer understands and acknowledges that Creative Commons is not a - party to this document and has no duty or obligation with respect to this - CC0 or use of the Work. - -For more information, please see - diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_clean/address.c b/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_clean/address.c deleted file mode 100644 index 220bf4a3dc..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_clean/address.c +++ /dev/null @@ -1,78 +0,0 @@ -#include - -#include "address.h" -#include "params.h" -#include "utils.h" - -void PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]) { - int i; - - for (i = 0; i < 8; i++) { - PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_ull_to_bytes( - bytes + i * 4, 4, addr[i]); - } -} - -void PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_set_layer_addr( - uint32_t addr[8], uint32_t layer) { - addr[0] = layer; -} - -void PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_set_tree_addr( - uint32_t addr[8], uint64_t tree) { - addr[1] = 0; - addr[2] = (uint32_t) (tree >> 32); - addr[3] = (uint32_t) tree; -} - -void PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_set_type( - uint32_t addr[8], uint32_t type) { - addr[4] = type; -} - -void PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; -} - -/* These functions are used for OTS addresses. */ - -void PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_set_keypair_addr( - uint32_t addr[8], uint32_t keypair) { - addr[5] = keypair; -} - -void PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; - out[5] = in[5]; -} - -void PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_set_chain_addr( - uint32_t addr[8], uint32_t chain) { - addr[6] = chain; -} - -void PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_set_hash_addr( - uint32_t addr[8], uint32_t hash) { - addr[7] = hash; -} - -/* These functions are used for all hash tree addresses (including FORS). */ - -void PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_set_tree_height( - uint32_t addr[8], uint32_t tree_height) { - addr[6] = tree_height; -} - -void PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_set_tree_index( - uint32_t addr[8], uint32_t tree_index) { - addr[7] = tree_index; -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_clean/address.h b/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_clean/address.h deleted file mode 100644 index 21fc43e90a..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_clean/address.h +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_ADDRESS_H -#define PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_ADDRESS_H - -#include - -#define PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_ADDR_TYPE_WOTS 0 -#define PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_ADDR_TYPE_WOTSPK 1 -#define PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_ADDR_TYPE_HASHTREE 2 -#define PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_ADDR_TYPE_FORSTREE 3 -#define PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_ADDR_TYPE_FORSPK 4 - -void PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]); - -void PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_set_layer_addr( - uint32_t addr[8], uint32_t layer); - -void PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_set_tree_addr( - uint32_t addr[8], uint64_t tree); - -void PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_set_type( - uint32_t addr[8], uint32_t type); - -/* Copies the layer and tree part of one address into the other */ -void PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for WOTS and FORS addresses. */ - -void PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_set_keypair_addr( - uint32_t addr[8], uint32_t keypair); - -void PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_set_chain_addr( - uint32_t addr[8], uint32_t chain); - -void PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_set_hash_addr( - uint32_t addr[8], uint32_t hash); - -void PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for all hash tree addresses (including FORS). */ - -void PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_set_tree_height( - uint32_t addr[8], uint32_t tree_height); - -void PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_set_tree_index( - uint32_t addr[8], uint32_t tree_index); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_clean/api.h b/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_clean/api.h deleted file mode 100644 index 1d8a0885f0..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_clean/api.h +++ /dev/null @@ -1,81 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_API_H -#define PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_API_H - -#include -#include - - - -#define PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_CRYPTO_ALGNAME "SPHINCS+" - -#define PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_CRYPTO_SECRETKEYBYTES 96 -#define PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_CRYPTO_PUBLICKEYBYTES 48 -#define PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_CRYPTO_BYTES 35664 -#define PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_CRYPTO_SEEDBYTES 72 - - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_clean/fors.c b/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_clean/fors.c deleted file mode 100644 index a6bea27cbb..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_clean/fors.c +++ /dev/null @@ -1,161 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "fors.h" -#include "hash.h" -#include "hash_state.h" -#include "thash.h" -#include "utils.h" - -static void fors_gen_sk(unsigned char *sk, const unsigned char *sk_seed, - uint32_t fors_leaf_addr[8], const hash_state *hash_state_seeded) { - PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_prf_addr( - sk, sk_seed, fors_leaf_addr, hash_state_seeded); -} - -static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, - const unsigned char *pub_seed, - uint32_t fors_leaf_addr[8], - const hash_state *hash_state_seeded) { - PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_thash_1( - leaf, sk, pub_seed, fors_leaf_addr, hash_state_seeded); -} - -static void fors_gen_leaf(unsigned char *leaf, const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx, const uint32_t fors_tree_addr[8], - const hash_state *hash_state_seeded) { - uint32_t fors_leaf_addr[8] = {0}; - - /* Only copy the parts that must be kept in fors_leaf_addr. */ - PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_copy_keypair_addr( - fors_leaf_addr, fors_tree_addr); - PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_set_type( - fors_leaf_addr, PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_set_tree_index( - fors_leaf_addr, addr_idx); - - fors_gen_sk(leaf, sk_seed, fors_leaf_addr, hash_state_seeded); - fors_sk_to_leaf(leaf, leaf, pub_seed, fors_leaf_addr, hash_state_seeded); -} - -/** - * Interprets m as PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_FORS_HEIGHT-bit unsigned integers. - * Assumes m contains at least PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_FORS_TREES bits. - * Assumes indices has space for PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_FORS_TREES integers. - */ -static void message_to_indices(uint32_t *indices, const unsigned char *m) { - unsigned int i, j; - unsigned int offset = 0; - - for (i = 0; i < PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_FORS_TREES; i++) { - indices[i] = 0; - for (j = 0; j < PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_FORS_HEIGHT; j++) { - indices[i] ^= (((uint32_t)m[offset >> 3] >> (offset & 0x7)) & 0x1) << j; - offset++; - } - } -} - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_fors_sign( - unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *hash_state_seeded) { - uint32_t indices[PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_FORS_TREES]; - unsigned char roots[PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_FORS_TREES * PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_N]; - uint32_t fors_tree_addr[8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_copy_keypair_addr( - fors_tree_addr, fors_addr); - PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_copy_keypair_addr( - fors_pk_addr, fors_addr); - - PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_set_type( - fors_tree_addr, PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_set_type( - fors_pk_addr, PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_FORS_TREES; i++) { - idx_offset = i * (1 << PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_FORS_HEIGHT); - - PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_set_tree_height( - fors_tree_addr, 0); - PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_set_tree_index( - fors_tree_addr, indices[i] + idx_offset); - - /* Include the secret key part that produces the selected leaf node. */ - fors_gen_sk(sig, sk_seed, fors_tree_addr, hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_N; - - /* Compute the authentication path for this leaf node. */ - PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_treehash_FORS_HEIGHT( - roots + i * PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_N, sig, sk_seed, pub_seed, - indices[i], idx_offset, fors_gen_leaf, fors_tree_addr, - hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_N * PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_thash_FORS_TREES( - pk, roots, pub_seed, fors_pk_addr, hash_state_seeded); -} - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_fors_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, const uint32_t fors_addr[8], - const hash_state *hash_state_seeded) { - uint32_t indices[PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_FORS_TREES]; - unsigned char roots[PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_FORS_TREES * PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_N]; - unsigned char leaf[PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_N]; - uint32_t fors_tree_addr[8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_copy_keypair_addr(fors_tree_addr, fors_addr); - PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_copy_keypair_addr(fors_pk_addr, fors_addr); - - PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_set_type(fors_tree_addr, PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_set_type(fors_pk_addr, PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_FORS_TREES; i++) { - idx_offset = i * (1 << PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_FORS_HEIGHT); - - PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_set_tree_height(fors_tree_addr, 0); - PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Derive the leaf from the included secret key part. */ - fors_sk_to_leaf(leaf, sig, pub_seed, fors_tree_addr, hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_N; - - /* Derive the corresponding root node of this tree. */ - PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_compute_root(roots + i * PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_N, leaf, indices[i], idx_offset, sig, - PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_FORS_HEIGHT, pub_seed, fors_tree_addr, hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_N * PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_thash_FORS_TREES(pk, roots, pub_seed, fors_pk_addr, hash_state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_clean/fors.h b/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_clean/fors.h deleted file mode 100644 index b3047774a0..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_clean/fors.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_FORS_H -#define PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_FORS_H - -#include - -#include "hash_state.h" -#include "params.h" - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_fors_sign( - unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *hash_state_seeded); - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_fors_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, const uint32_t fors_addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_clean/hash.h b/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_clean/hash.h deleted file mode 100644 index 282883ea16..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_clean/hash.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_HASH_H -#define PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_HASH_H - -#include "hash_state.h" - -#include -#include - -void PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_initialize_hash_function( - hash_state *hash_state_seeded, - const unsigned char *pub_seed, const unsigned char *sk_seed); - -void PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_destroy_hash_function(hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_clean/hash_sha256.c b/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_clean/hash_sha256.c deleted file mode 100644 index 490b60b901..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_clean/hash_sha256.c +++ /dev/null @@ -1,162 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "utils.h" - -#include "sha2.h" -#include "sha256.h" - -/* For SHA256, there is no immediate reason to initialize at the start, - so this function is an empty operation. */ -void PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_initialize_hash_function( - hash_state *hash_state_seeded, - const unsigned char *pub_seed, const unsigned char *sk_seed) { - PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_seed_state(hash_state_seeded, pub_seed); - (void)sk_seed; /* Suppress an 'unused parameter' warning. */ -} - -/* Clean up hash state */ -void PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_destroy_hash_function(hash_state *hash_state_seeded) { - sha256_inc_ctx_release(hash_state_seeded); -} - -/* - * Computes PRF(key, addr), given a secret key of PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_N bytes and an address - */ -void PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded) { - unsigned char buf[PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_N + PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_SHA256_ADDR_BYTES]; - unsigned char outbuf[PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_SHA256_OUTPUT_BYTES]; - - memcpy(buf, key, PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_N); - PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_compress_address(buf + PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_N, addr); - - sha256(outbuf, buf, PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_N + PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_SHA256_ADDR_BYTES); - memcpy(out, outbuf, PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_N); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} - -/** - * Computes the message-dependent randomness R, using a secret seed as a key - * for HMAC, and an optional randomization value prefixed to the message. - * This requires m to have at least PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_SHA256_BLOCK_BYTES + PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_N space - * available in front of the pointer, i.e. before the message to use for the - * prefix. This is necessary to prevent having to move the message around (and - * allocate memory for it). - */ -void PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, const hash_state *hash_state_seeded) { - unsigned char buf[PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_SHA256_BLOCK_BYTES + PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_SHA256_OUTPUT_BYTES]; - sha256ctx state; - int i; - - /* This implements HMAC-SHA256 */ - for (i = 0; i < PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_N; i++) { - buf[i] = 0x36 ^ sk_prf[i]; - } - memset(buf + PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_N, 0x36, PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_N); - - sha256_inc_init(&state); - sha256_inc_blocks(&state, buf, 1); - - memcpy(buf, optrand, PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_N); - - /* If optrand + message cannot fill up an entire block */ - if (PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_N + mlen < PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_SHA256_BLOCK_BYTES) { - memcpy(buf + PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_N, m, mlen); - sha256_inc_finalize(buf + PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_SHA256_BLOCK_BYTES, &state, - buf, mlen + PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_N); - } - /* Otherwise first fill a block, so that finalize only uses the message */ - else { - memcpy(buf + PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_N, m, PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_N); - sha256_inc_blocks(&state, buf, 1); - - m += PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_N; - mlen -= PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_N; - sha256_inc_finalize(buf + PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_SHA256_BLOCK_BYTES, &state, m, mlen); - } - - for (i = 0; i < PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_N; i++) { - buf[i] = 0x5c ^ sk_prf[i]; - } - memset(buf + PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_N, 0x5c, PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_N); - - sha256(buf, buf, PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_SHA256_BLOCK_BYTES + PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_SHA256_OUTPUT_BYTES); - memcpy(R, buf, PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_N); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} - -/** - * Computes the message hash using R, the public key, and the message. - * Outputs the message digest and the index of the leaf. The index is split in - * the tree index and the leaf index, for convenient copying to an address. - */ -void PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded) { -#define PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_TREE_BITS (PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_TREE_HEIGHT * (PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_D - 1)) -#define PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_TREE_BYTES ((PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_TREE_BITS + 7) / 8) -#define PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_LEAF_BITS PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_TREE_HEIGHT -#define PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_LEAF_BYTES ((PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_LEAF_BITS + 7) / 8) -#define PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_DGST_BYTES (PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_FORS_MSG_BYTES + PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_TREE_BYTES + PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_LEAF_BYTES) - - unsigned char seed[PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_SHA256_OUTPUT_BYTES + 4]; - - /* Round to nearest multiple of PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_SHA256_BLOCK_BYTES */ -#define PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_INBLOCKS (((PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_N + PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_PK_BYTES + PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_SHA256_BLOCK_BYTES - 1) & \ - -PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_SHA256_BLOCK_BYTES) / PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_SHA256_BLOCK_BYTES) - unsigned char inbuf[PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_INBLOCKS * PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_SHA256_BLOCK_BYTES]; - - unsigned char buf[PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_DGST_BYTES]; - unsigned char *bufp = buf; - sha256ctx state; - - sha256_inc_init(&state); - - memcpy(inbuf, R, PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_N); - memcpy(inbuf + PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_N, pk, PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_PK_BYTES); - - /* If R + pk + message cannot fill up an entire block */ - if (PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_N + PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_PK_BYTES + mlen < PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_INBLOCKS * PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_SHA256_BLOCK_BYTES) { - memcpy(inbuf + PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_N + PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_PK_BYTES, m, mlen); - sha256_inc_finalize(seed, &state, inbuf, PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_N + PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_PK_BYTES + mlen); - } - /* Otherwise first fill a block, so that finalize only uses the message */ - else { - memcpy(inbuf + PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_N + PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_PK_BYTES, m, - PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_INBLOCKS * PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_N - PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_PK_BYTES); - sha256_inc_blocks(&state, inbuf, PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_INBLOCKS); - - m += PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_INBLOCKS * PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_N - PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_PK_BYTES; - mlen -= PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_INBLOCKS * PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_N - PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_PK_BYTES; - sha256_inc_finalize(seed, &state, m, mlen); - } - - /* By doing this in two steps, we prevent hashing the message twice; - otherwise each iteration in MGF1 would hash the message again. */ - PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_mgf1(bufp, PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_DGST_BYTES, seed, PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_SHA256_OUTPUT_BYTES); - - memcpy(digest, bufp, PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_FORS_MSG_BYTES); - bufp += PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_FORS_MSG_BYTES; - - *tree = PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_bytes_to_ull(bufp, PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_TREE_BYTES); - *tree &= (~(uint64_t)0) >> (64 - PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_TREE_BITS); - bufp += PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_TREE_BYTES; - - *leaf_idx = (uint32_t)PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_bytes_to_ull( - bufp, PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_LEAF_BYTES); - *leaf_idx &= (~(uint32_t)0) >> (32 - PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_LEAF_BITS); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_clean/hash_state.h b/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_clean/hash_state.h deleted file mode 100644 index 19fc335e27..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_clean/hash_state.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef SPX_HASH_STATE_H -#define SPX_HASH_STATE_H - -/** - * Defines the type of the hash function state. - * - * Don't be fooled into thinking this instance of SPHINCS+ isn't stateless! - * - * From Section 7.2.2 from the SPHINCS+ round-2 specification: - * - * Each of the instances of the tweakable hash function take PK.seed as its - * first input, which is constant for a given key pair – and, thus, across - * a single signature. This leads to a lot of redundant computation. To remedy - * this, we pad PK.seed to the length of a full 64-byte SHA-256 input block. - * Because of the Merkle-Damgård construction that underlies SHA-256, this - * allows for reuse of the intermediate SHA-256 state after the initial call to - * the compression function which improves performance. - * - * We pass this hash state around in functions, because otherwise we need to - * have a global variable. - */ - -#include "sha2.h" -#define hash_state sha256ctx - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_clean/params.h b/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_clean/params.h deleted file mode 100644 index 394b355088..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_clean/params.h +++ /dev/null @@ -1,53 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_PARAMS_H -#define PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_PARAMS_H - -/* Hash output length in bytes. */ -#define PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_N 24 -/* Height of the hypertree. */ -#define PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_FULL_HEIGHT 66 -/* Number of subtree layer. */ -#define PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_D 22 -/* FORS tree dimensions. */ -#define PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_FORS_HEIGHT 8 -#define PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_FORS_TREES 33 -/* Winternitz parameter, */ -#define PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_WOTS_W 16 - -/* The hash function is defined by linking a different hash.c file, as opposed - to setting a #define constant. */ - -/* For clarity */ -#define PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_ADDR_BYTES 32 - -/* WOTS parameters. */ -#define PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_WOTS_LOGW 4 - -#define PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_WOTS_LEN1 (8 * PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_N / PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_WOTS_LOGW) - -/* PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#define PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_WOTS_LEN2 3 - -#define PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_WOTS_LEN (PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_WOTS_LEN1 + PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_WOTS_LEN2) -#define PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_WOTS_BYTES (PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_WOTS_LEN * PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_N) -#define PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_WOTS_PK_BYTES PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_WOTS_BYTES - -/* Subtree size. */ -#define PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_TREE_HEIGHT (PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_FULL_HEIGHT / PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_D) - -/* FORS parameters. */ -#define PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_FORS_MSG_BYTES ((PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_FORS_TREES + 7) / 8) -#define PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_FORS_BYTES ((PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_FORS_HEIGHT + 1) * PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_FORS_TREES * PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_N) -#define PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_FORS_PK_BYTES PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_N - -/* Resulting SPX sizes. */ -#define PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_BYTES (PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_N + PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_FORS_BYTES + PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_D * PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_WOTS_BYTES +\ - PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_FULL_HEIGHT * PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_N) -#define PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_PK_BYTES (2 * PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_N) -#define PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_SK_BYTES (2 * PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_N + PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_PK_BYTES) - -/* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ -#define PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_OPTRAND_BYTES 32 - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_clean/sha256.c b/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_clean/sha256.c deleted file mode 100644 index c5d71b51b1..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_clean/sha256.c +++ /dev/null @@ -1,71 +0,0 @@ -/* Based on the public domain implementation in - * crypto_hash/sha512/ref/ from http://bench.cr.yp.to/supercop.html - * by D. J. Bernstein */ - -#include -#include -#include - -#include "sha2.h" -#include "sha256.h" -#include "utils.h" - -/* - * Compresses an address to a 22-byte sequence. - * This reduces the number of required SHA256 compression calls, as the last - * block of input is padded with at least 65 bits. - */ -void PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_compress_address(unsigned char *out, const uint32_t addr[8]) { - PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_ull_to_bytes(out, 1, addr[0]); /* drop 3 bytes of the layer field */ - PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_ull_to_bytes(out + 1, 4, addr[2]); /* drop the highest tree address word */ - PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_ull_to_bytes(out + 5, 4, addr[3]); - PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_ull_to_bytes(out + 9, 1, addr[4]); /* drop 3 bytes of the type field */ - PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_ull_to_bytes(out + 10, 4, addr[5]); - PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_ull_to_bytes(out + 14, 4, addr[6]); - PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_ull_to_bytes(out + 18, 4, addr[7]); -} - -/** - * Requires 'input_plus_four_bytes' to have 'inlen' + 4 bytes, so that the last - * four bytes can be used for the counter. Typically 'input' is merely a seed. - * Outputs outlen number of bytes - */ -void PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_mgf1( - unsigned char *out, unsigned long outlen, - unsigned char *input_plus_four_bytes, unsigned long inlen) { - unsigned char outbuf[PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_SHA256_OUTPUT_BYTES]; - unsigned long i; - - /* While we can fit in at least another full block of SHA256 output.. */ - for (i = 0; (i + 1)*PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_SHA256_OUTPUT_BYTES <= outlen; i++) { - PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_ull_to_bytes(input_plus_four_bytes + inlen, 4, i); - sha256(out, input_plus_four_bytes, inlen + 4); - out += PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_SHA256_OUTPUT_BYTES; - } - /* Until we cannot anymore, and we fill the remainder. */ - if (outlen > i * PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_SHA256_OUTPUT_BYTES) { - PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_ull_to_bytes(input_plus_four_bytes + inlen, 4, i); - sha256(outbuf, input_plus_four_bytes, inlen + 4); - memcpy(out, outbuf, outlen - i * PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_SHA256_OUTPUT_BYTES); - } -} - - -/** - * Absorb the constant pub_seed using one round of the compression function - * This initializes hash_state_seeded, which can then be reused in thash - **/ -void PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_seed_state(sha256ctx *hash_state_seeded, const unsigned char *pub_seed) { - uint8_t block[PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_SHA256_BLOCK_BYTES]; - size_t i; - - for (i = 0; i < PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_N; ++i) { - block[i] = pub_seed[i]; - } - for (i = PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_N; i < PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_SHA256_BLOCK_BYTES; ++i) { - block[i] = 0; - } - - sha256_inc_init(hash_state_seeded); - sha256_inc_blocks(hash_state_seeded, block, 1); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_clean/sha256.h b/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_clean/sha256.h deleted file mode 100644 index ee97619d0a..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_clean/sha256.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_SHA256_H -#define PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_SHA256_H - -#define PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_SHA256_BLOCK_BYTES 64 -#define PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_SHA256_OUTPUT_BYTES 32 /* This does not necessarily equal PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_N */ -#define PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_SHA256_ADDR_BYTES 22 - -#include -#include - -#include "sha2.h" - -void PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_compress_address(unsigned char *out, const uint32_t addr[8]); - -void PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_mgf1( - unsigned char *out, unsigned long outlen, - unsigned char *input_plus_four_bytes, unsigned long inlen); - -void PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_seed_state(sha256ctx *hash_state_seeded, const unsigned char *pub_seed); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_clean/sign.c b/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_clean/sign.c deleted file mode 100644 index 1e75cb0758..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_clean/sign.c +++ /dev/null @@ -1,356 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "api.h" -#include "fors.h" -#include "hash.h" -#include "hash_state.h" -#include "params.h" -#include "randombytes.h" -#include "thash.h" -#include "utils.h" -#include "wots.h" - -/** - * Computes the leaf at a given address. First generates the WOTS key pair, - * then computes leaf by hashing horizontally. - */ -static void wots_gen_leaf(unsigned char *leaf, const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx, const uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - unsigned char pk[PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_WOTS_BYTES]; - uint32_t wots_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_set_type( - wots_addr, PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_set_type( - wots_pk_addr, PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_ADDR_TYPE_WOTSPK); - - PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_set_keypair_addr( - wots_addr, addr_idx); - PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_wots_gen_pk( - pk, sk_seed, pub_seed, wots_addr, hash_state_seeded); - - PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_copy_keypair_addr( - wots_pk_addr, wots_addr); - PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_thash_WOTS_LEN( - leaf, pk, pub_seed, wots_pk_addr, hash_state_seeded); -} - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_crypto_sign_secretkeybytes(void) { - return PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_CRYPTO_SECRETKEYBYTES; -} - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_crypto_sign_publickeybytes(void) { - return PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_CRYPTO_PUBLICKEYBYTES; -} - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_crypto_sign_bytes(void) { - return PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_CRYPTO_BYTES; -} - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_crypto_sign_seedbytes(void) { - return PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_CRYPTO_SEEDBYTES; -} - -/* - * Generates an SPX key pair given a seed of length - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed) { - /* We do not need the auth path in key generation, but it simplifies the - code to have just one treehash routine that computes both root and path - in one function. */ - unsigned char auth_path[PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_TREE_HEIGHT * PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_N]; - uint32_t top_tree_addr[8] = {0}; - hash_state hash_state_seeded; - - PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_set_layer_addr( - top_tree_addr, PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_D - 1); - PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_set_type( - top_tree_addr, PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_ADDR_TYPE_HASHTREE); - - /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ - memcpy(sk, seed, PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_CRYPTO_SEEDBYTES); - - memcpy(pk, sk + 2 * PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_N, PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_initialize_hash_function(&hash_state_seeded, pk, sk); - - /* Compute root node of the top-most subtree. */ - PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_treehash_TREE_HEIGHT( - sk + 3 * PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_N, auth_path, sk, sk + 2 * PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_N, 0, 0, - wots_gen_leaf, top_tree_addr, &hash_state_seeded); - - memcpy(pk + PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_N, sk + 3 * PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_N, PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_N); - - PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_destroy_hash_function(&hash_state_seeded); - return 0; -} - -/* - * Generates an SPX key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk) { - unsigned char seed[PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_CRYPTO_SEEDBYTES]; - randombytes(seed, PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_CRYPTO_SEEDBYTES); - PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_crypto_sign_seed_keypair( - pk, sk, seed); - - return 0; -} - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - const unsigned char *sk_seed = sk; - const unsigned char *sk_prf = sk + PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_N; - const unsigned char *pk = sk + 2 * PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_N; - const unsigned char *pub_seed = pk; - - unsigned char optrand[PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_N]; - unsigned char mhash[PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_FORS_MSG_BYTES]; - unsigned char root[PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_N]; - uint32_t i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - - hash_state hash_state_seeded; - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_initialize_hash_function( - &hash_state_seeded, - pub_seed, sk_seed); - - PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_set_type( - wots_addr, PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_set_type( - tree_addr, PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_ADDR_TYPE_HASHTREE); - - /* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ - randombytes(optrand, PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_N); - /* Compute the digest randomization value. */ - PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_gen_message_random( - sig, sk_prf, optrand, m, mlen, &hash_state_seeded); - - /* Derive the message digest and leaf index from R, PK and M. */ - PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_N; - - PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); - - /* Sign the message hash using FORS. */ - PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_fors_sign( - sig, root, mhash, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_FORS_BYTES; - - for (i = 0; i < PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_D; i++) { - PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_set_tree_addr(tree_addr, tree); - - PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); - - /* Compute a WOTS signature. */ - PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_wots_sign( - sig, root, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_WOTS_BYTES; - - /* Compute the authentication path for the used WOTS leaf. */ - PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_treehash_TREE_HEIGHT( - root, sig, sk_seed, pub_seed, idx_leaf, 0, - wots_gen_leaf, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_TREE_HEIGHT * PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_TREE_HEIGHT; - } - - *siglen = PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_BYTES; - - PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_destroy_hash_function(&hash_state_seeded); - return 0; -} - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk) { - const unsigned char *pub_seed = pk; - const unsigned char *pub_root = pk + PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_N; - unsigned char mhash[PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_FORS_MSG_BYTES]; - unsigned char wots_pk[PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_WOTS_BYTES]; - unsigned char root[PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_N]; - unsigned char leaf[PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_N]; - unsigned int i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - hash_state hash_state_seeded; - - if (siglen != PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_BYTES) { - return -1; - } - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_initialize_hash_function( - &hash_state_seeded, - pub_seed, NULL); - - PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_set_type( - wots_addr, PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_set_type( - tree_addr, PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_ADDR_TYPE_HASHTREE); - PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_set_type( - wots_pk_addr, PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_ADDR_TYPE_WOTSPK); - - /* Derive the message digest and leaf index from R || PK || M. */ - /* The additional PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_N is a result of the hash domain separator. */ - PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_N; - - /* Layer correctly defaults to 0, so no need to set_layer_addr */ - PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); - - PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_fors_pk_from_sig( - root, sig, mhash, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_FORS_BYTES; - - /* For each subtree.. */ - for (i = 0; i < PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_D; i++) { - PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_set_tree_addr(tree_addr, tree); - - PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); - - PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_copy_keypair_addr( - wots_pk_addr, wots_addr); - - /* The WOTS public key is only correct if the signature was correct. */ - /* Initially, root is the FORS pk, but on subsequent iterations it is - the root of the subtree below the currently processed subtree. */ - PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_wots_pk_from_sig( - wots_pk, sig, root, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_WOTS_BYTES; - - /* Compute the leaf node using the WOTS public key. */ - PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_thash_WOTS_LEN( - leaf, wots_pk, pub_seed, wots_pk_addr, &hash_state_seeded); - - /* Compute the root node of this subtree. */ - PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_compute_root( - root, leaf, idx_leaf, 0, sig, PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_TREE_HEIGHT, - pub_seed, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_TREE_HEIGHT * PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_TREE_HEIGHT; - } - - PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_destroy_hash_function(&hash_state_seeded); - /* Check if the root node equals the root node in the public key. */ - if (memcmp(root, pub_root, PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_N) != 0) { - return -1; - } - - return 0; -} - - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - size_t siglen; - - PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_crypto_sign_signature( - sm, &siglen, m, mlen, sk); - - memmove(sm + PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_BYTES, m, mlen); - *smlen = siglen + mlen; - - return 0; -} - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk) { - /* The API caller does not necessarily know what size a signature should be - but SPHINCS+ signatures are always exactly PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_BYTES. */ - if (smlen < PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_BYTES) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - *mlen = smlen - PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_BYTES; - - if (PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_crypto_sign_verify( - sm, PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_BYTES, sm + PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_BYTES, *mlen, pk)) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - /* If verification was successful, move the message to the right place. */ - memmove(m, sm + PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_BYTES, *mlen); - - return 0; -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_clean/thash.h b/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_clean/thash.h deleted file mode 100644 index 8e9aa2eec4..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_clean/thash.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_THASH_H -#define PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_THASH_H - -#include "hash_state.h" - -#include - -void PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_clean/thash_sha256_robust.c b/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_clean/thash_sha256_robust.c deleted file mode 100644 index 8a289d072f..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_clean/thash_sha256_robust.c +++ /dev/null @@ -1,82 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "thash.h" - -#include "sha2.h" -#include "sha256.h" - -/** - * Takes an array of inblocks concatenated arrays of PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_N bytes. - */ -static void PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_thash( - unsigned char *out, unsigned char *buf, - const unsigned char *in, unsigned int inblocks, - const unsigned char *pub_seed, uint32_t addr[8], - const sha256ctx *hash_state_seeded) { - - unsigned char outbuf[PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_SHA256_OUTPUT_BYTES]; - unsigned char *bitmask = buf + PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_N + PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_SHA256_ADDR_BYTES + 4; - sha256ctx sha2_state; - unsigned int i; - - memcpy(buf, pub_seed, PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_N); - PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_compress_address(buf + PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_N, addr); - /* MGF1 requires us to have 4 extra bytes in 'buf' */ - PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_mgf1(bitmask, inblocks * PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_N, buf, PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_N + PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_SHA256_ADDR_BYTES); - - /* Retrieve precomputed state containing pub_seed */ - sha256_inc_ctx_clone(&sha2_state, hash_state_seeded); - - for (i = 0; i < inblocks * PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_N; i++) { - buf[PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_N + PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_SHA256_ADDR_BYTES + i] = in[i] ^ bitmask[i]; - } - - sha256_inc_finalize(outbuf, &sha2_state, buf + PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_N, - PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_N); - memcpy(out, outbuf, PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_N); -} - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const sha256ctx *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_N + PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_SHA256_ADDR_BYTES + 4 + 1 * PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_N]; - PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_thash( - out, buf, in, 1, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const sha256ctx *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_N + PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_SHA256_ADDR_BYTES + 4 + 2 * PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_N]; - PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_thash( - out, buf, in, 2, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const sha256ctx *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_N + PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_SHA256_ADDR_BYTES + 4 + PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_WOTS_LEN * PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_N]; - PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_thash( - out, buf, in, PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_WOTS_LEN, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const sha256ctx *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_N + PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_SHA256_ADDR_BYTES + 4 + PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_FORS_TREES * PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_N]; - PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_thash( - out, buf, in, PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_FORS_TREES, pub_seed, addr, hash_state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_clean/utils.c b/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_clean/utils.c deleted file mode 100644 index aa12f30dc3..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_clean/utils.c +++ /dev/null @@ -1,199 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "hash_state.h" -#include "params.h" -#include "thash.h" -#include "utils.h" - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in) { - - /* Iterate over out in decreasing order, for big-endianness. */ - for (size_t i = outlen; i > 0; i--) { - out[i - 1] = in & 0xff; - in = in >> 8; - } -} - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_bytes_to_ull( - const unsigned char *in, size_t inlen) { - unsigned long long retval = 0; - - for (size_t i = 0; i < inlen; i++) { - retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); - } - return retval; -} - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - uint32_t i; - unsigned char buffer[2 * PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_N]; - - /* If leaf_idx is odd (last bit = 1), current path element is a right child - and auth_path has to go left. Otherwise it is the other way around. */ - if (leaf_idx & 1) { - memcpy(buffer + PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_N, leaf, PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_N); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_N); - } else { - memcpy(buffer, leaf, PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_N); - memcpy(buffer + PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_N, auth_path, PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_N); - } - auth_path += PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_N; - - for (i = 0; i < tree_height - 1; i++) { - leaf_idx >>= 1; - idx_offset >>= 1; - /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_set_tree_height(addr, i + 1); - PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_set_tree_index( - addr, leaf_idx + idx_offset); - - /* Pick the right or left neighbor, depending on parity of the node. */ - if (leaf_idx & 1) { - PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_thash_2( - buffer + PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_N, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_N); - } else { - PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_thash_2( - buffer, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer + PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_N, auth_path, PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_N); - } - auth_path += PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_N; - } - - /* The last iteration is exceptional; we do not copy an auth_path node. */ - leaf_idx >>= 1; - idx_offset >>= 1; - PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_set_tree_height(addr, tree_height); - PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_set_tree_index( - addr, leaf_idx + idx_offset); - PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_thash_2( - root, buffer, pub_seed, addr, hash_state_seeded); -} - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -static void PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_treehash( - unsigned char *root, unsigned char *auth_path, - unsigned char *stack, unsigned int *heights, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - - unsigned int offset = 0; - uint32_t idx; - uint32_t tree_idx; - - for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { - /* Add the next leaf node to the stack. */ - gen_leaf(stack + offset * PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_N, - sk_seed, pub_seed, idx + idx_offset, tree_addr, - hash_state_seeded); - offset++; - heights[offset - 1] = 0; - - /* If this is a node we need for the auth path.. */ - if ((leaf_idx ^ 0x1) == idx) { - memcpy(auth_path, stack + (offset - 1)*PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_N, PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_N); - } - - /* While the top-most nodes are of equal height.. */ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { - /* Compute index of the new node, in the next layer. */ - tree_idx = (idx >> (heights[offset - 1] + 1)); - - /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_set_tree_height( - tree_addr, heights[offset - 1] + 1); - PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_set_tree_index( - tree_addr, tree_idx + (idx_offset >> (heights[offset - 1] + 1))); - /* Hash the top-most nodes from the stack together. */ - PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_thash_2( - stack + (offset - 2)*PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_N, stack + (offset - 2)*PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_N, - pub_seed, tree_addr, hash_state_seeded); - offset--; - /* Note that the top-most node is now one layer higher. */ - heights[offset - 1]++; - - /* If this is a node we need for the auth path.. */ - if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_path + heights[offset - 1]*PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_N, - stack + (offset - 1)*PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_N, PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_N); - } - } - } - memcpy(root, stack, PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_N); -} - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_FORS_HEIGHT + 1)*PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_N]; - unsigned int heights[PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_FORS_HEIGHT + 1]; - - PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_FORS_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_TREE_HEIGHT + 1)*PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_N]; - unsigned int heights[PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_TREE_HEIGHT + 1]; - - PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_TREE_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_clean/utils.h b/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_clean/utils.h deleted file mode 100644 index 22b428a6c7..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_clean/utils.h +++ /dev/null @@ -1,64 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_UTILS_H -#define PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_UTILS_H - -#include "hash_state.h" -#include "params.h" -#include -#include - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in); - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_bytes_to_ull( - const unsigned char *in, size_t inlen); - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -void PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_clean/wots.c b/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_clean/wots.c deleted file mode 100644 index 8cf20b7d3b..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_clean/wots.c +++ /dev/null @@ -1,167 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "hash_state.h" -#include "params.h" -#include "thash.h" -#include "utils.h" -#include "wots.h" - -// TODO clarify address expectations, and make them more uniform. -// TODO i.e. do we expect types to be set already? -// TODO and do we expect modifications or copies? - -/** - * Computes the starting value for a chain, i.e. the secret key. - * Expects the address to be complete up to the chain address. - */ -static void wots_gen_sk(unsigned char *sk, const unsigned char *sk_seed, - uint32_t wots_addr[8], - const hash_state *hash_state_seeded) { - /* Make sure that the hash address is actually zeroed. */ - PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_set_hash_addr(wots_addr, 0); - - /* Generate sk element. */ - PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_prf_addr(sk, sk_seed, wots_addr, hash_state_seeded); -} - -/** - * Computes the chaining function. - * out and in have to be n-byte arrays. - * - * Interprets in as start-th value of the chain. - * addr has to contain the address of the chain. - */ -static void gen_chain(unsigned char *out, const unsigned char *in, - unsigned int start, unsigned int steps, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - uint32_t i; - - /* Initialize out with the value at position 'start'. */ - memcpy(out, in, PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_N); - - /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_WOTS_W; i++) { - PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_set_hash_addr(addr, i); - PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_thash_1( - out, out, pub_seed, addr, hash_state_seeded); - } -} - -/** - * base_w algorithm as described in draft. - * Interprets an array of bytes as integers in base w. - * This only works when log_w is a divisor of 8. - */ -static void base_w(unsigned int *output, const size_t out_len, - const unsigned char *input) { - size_t in = 0; - size_t out = 0; - unsigned char total = 0; - unsigned int bits = 0; - size_t consumed; - - for (consumed = 0; consumed < out_len; consumed++) { - if (bits == 0) { - total = input[in]; - in++; - bits += 8; - } - bits -= PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_WOTS_LOGW; - output[out] = (unsigned int)((total >> bits) & (PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_WOTS_W - 1)); - out++; - } -} - -/* Computes the WOTS+ checksum over a message (in base_w). */ -static void wots_checksum(unsigned int *csum_base_w, - const unsigned int *msg_base_w) { - unsigned int csum = 0; - unsigned char csum_bytes[(PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_WOTS_LEN2 * PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_WOTS_LOGW + 7) / 8]; - unsigned int i; - - /* Compute checksum. */ - for (i = 0; i < PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_WOTS_LEN1; i++) { - csum += PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_WOTS_W - 1 - msg_base_w[i]; - } - - /* Convert checksum to base_w. */ - /* Make sure expected empty zero bits are the least significant bits. */ - csum = csum << (8 - ((PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_WOTS_LEN2 * PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_WOTS_LOGW) % 8)); - PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_ull_to_bytes( - csum_bytes, sizeof(csum_bytes), csum); - base_w(csum_base_w, PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_WOTS_LEN2, csum_bytes); -} - -/* Takes a message and derives the matching chain lengths. */ -static void chain_lengths(unsigned int *lengths, const unsigned char *msg) { - base_w(lengths, PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_WOTS_LEN1, msg); - wots_checksum(lengths + PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_WOTS_LEN1, lengths); -} - -/** - * WOTS key generation. Takes a 32 byte sk_seed, expands it to WOTS private key - * elements and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_wots_gen_pk( - unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - uint32_t i; - - for (i = 0; i < PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_WOTS_LEN; i++) { - PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_set_chain_addr(addr, i); - wots_gen_sk(pk + i * PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_N, sk_seed, addr, hash_state_seeded); - gen_chain(pk + i * PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_N, pk + i * PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_N, - 0, PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_WOTS_W - 1, pub_seed, addr, hash_state_seeded); - } -} - -/** - * Takes a n-byte message and the 32-byte sk_see to compute a signature 'sig'. - */ -void PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_wots_sign( - unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *hash_state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_WOTS_LEN; i++) { - PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_set_chain_addr(addr, i); - wots_gen_sk(sig + i * PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_N, sk_seed, addr, hash_state_seeded); - gen_chain(sig + i * PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_N, sig + i * PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_N, 0, lengths[i], pub_seed, addr, hash_state_seeded); - } -} - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_wots_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_WOTS_LEN; i++) { - PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_set_chain_addr(addr, i); - gen_chain(pk + i * PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_N, sig + i * PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_N, - lengths[i], PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_WOTS_W - 1 - lengths[i], pub_seed, addr, - hash_state_seeded); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_clean/wots.h b/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_clean/wots.h deleted file mode 100644 index 1d26d8165f..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_clean/wots.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_WOTS_H -#define PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_WOTS_H - -#include "hash_state.h" -#include "params.h" -#include - -/** - * WOTS key generation. Takes a 32 byte seed for the private key, expands it to - * a full WOTS private key and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_wots_gen_pk( - unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -/** - * Takes a n-byte message and the 32-byte seed for the private key to compute a - * signature that is placed at 'sig'. - */ -void PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_wots_sign( - unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *hash_state_seeded); - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_wots_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_avx2/LICENSE b/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_avx2/LICENSE deleted file mode 100644 index 670154e353..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_avx2/LICENSE +++ /dev/null @@ -1,116 +0,0 @@ -CC0 1.0 Universal - -Statement of Purpose - -The laws of most jurisdictions throughout the world automatically confer -exclusive Copyright and Related Rights (defined below) upon the creator and -subsequent owner(s) (each and all, an "owner") of an original work of -authorship and/or a database (each, a "Work"). - -Certain owners wish to permanently relinquish those rights to a Work for the -purpose of contributing to a commons of creative, cultural and scientific -works ("Commons") that the public can reliably and without fear of later -claims of infringement build upon, modify, incorporate in other works, reuse -and redistribute as freely as possible in any form whatsoever and for any -purposes, including without limitation commercial purposes. These owners may -contribute to the Commons to promote the ideal of a free culture and the -further production of creative, cultural and scientific works, or to gain -reputation or greater distribution for their Work in part through the use and -efforts of others. - -For these and/or other purposes and motivations, and without any expectation -of additional consideration or compensation, the person associating CC0 with a -Work (the "Affirmer"), to the extent that he or she is an owner of Copyright -and Related Rights in the Work, voluntarily elects to apply CC0 to the Work -and publicly distribute the Work under its terms, with knowledge of his or her -Copyright and Related Rights in the Work and the meaning and intended legal -effect of CC0 on those rights. - -1. Copyright and Related Rights. A Work made available under CC0 may be -protected by copyright and related or neighboring rights ("Copyright and -Related Rights"). Copyright and Related Rights include, but are not limited -to, the following: - - i. the right to reproduce, adapt, distribute, perform, display, communicate, - and translate a Work; - - ii. moral rights retained by the original author(s) and/or performer(s); - - iii. publicity and privacy rights pertaining to a person's image or likeness - depicted in a Work; - - iv. rights protecting against unfair competition in regards to a Work, - subject to the limitations in paragraph 4(a), below; - - v. rights protecting the extraction, dissemination, use and reuse of data in - a Work; - - vi. database rights (such as those arising under Directive 96/9/EC of the - European Parliament and of the Council of 11 March 1996 on the legal - protection of databases, and under any national implementation thereof, - including any amended or successor version of such directive); and - - vii. other similar, equivalent or corresponding rights throughout the world - based on applicable law or treaty, and any national implementations thereof. - -2. Waiver. To the greatest extent permitted by, but not in contravention of, -applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and -unconditionally waives, abandons, and surrenders all of Affirmer's Copyright -and Related Rights and associated claims and causes of action, whether now -known or unknown (including existing as well as future claims and causes of -action), in the Work (i) in all territories worldwide, (ii) for the maximum -duration provided by applicable law or treaty (including future time -extensions), (iii) in any current or future medium and for any number of -copies, and (iv) for any purpose whatsoever, including without limitation -commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes -the Waiver for the benefit of each member of the public at large and to the -detriment of Affirmer's heirs and successors, fully intending that such Waiver -shall not be subject to revocation, rescission, cancellation, termination, or -any other legal or equitable action to disrupt the quiet enjoyment of the Work -by the public as contemplated by Affirmer's express Statement of Purpose. - -3. Public License Fallback. Should any part of the Waiver for any reason be -judged legally invalid or ineffective under applicable law, then the Waiver -shall be preserved to the maximum extent permitted taking into account -Affirmer's express Statement of Purpose. In addition, to the extent the Waiver -is so judged Affirmer hereby grants to each affected person a royalty-free, -non transferable, non sublicensable, non exclusive, irrevocable and -unconditional license to exercise Affirmer's Copyright and Related Rights in -the Work (i) in all territories worldwide, (ii) for the maximum duration -provided by applicable law or treaty (including future time extensions), (iii) -in any current or future medium and for any number of copies, and (iv) for any -purpose whatsoever, including without limitation commercial, advertising or -promotional purposes (the "License"). The License shall be deemed effective as -of the date CC0 was applied by Affirmer to the Work. Should any part of the -License for any reason be judged legally invalid or ineffective under -applicable law, such partial invalidity or ineffectiveness shall not -invalidate the remainder of the License, and in such case Affirmer hereby -affirms that he or she will not (i) exercise any of his or her remaining -Copyright and Related Rights in the Work or (ii) assert any associated claims -and causes of action with respect to the Work, in either case contrary to -Affirmer's express Statement of Purpose. - -4. Limitations and Disclaimers. - - a. No trademark or patent rights held by Affirmer are waived, abandoned, - surrendered, licensed or otherwise affected by this document. - - b. Affirmer offers the Work as-is and makes no representations or warranties - of any kind concerning the Work, express, implied, statutory or otherwise, - including without limitation warranties of title, merchantability, fitness - for a particular purpose, non infringement, or the absence of latent or - other defects, accuracy, or the present or absence of errors, whether or not - discoverable, all to the greatest extent permissible under applicable law. - - c. Affirmer disclaims responsibility for clearing rights of other persons - that may apply to the Work or any use thereof, including without limitation - any person's Copyright and Related Rights in the Work. Further, Affirmer - disclaims responsibility for obtaining any necessary consents, permissions - or other rights required for any use of the Work. - - d. Affirmer understands and acknowledges that Creative Commons is not a - party to this document and has no duty or obligation with respect to this - CC0 or use of the Work. - -For more information, please see - diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_avx2/address.c b/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_avx2/address.c deleted file mode 100644 index bd2e11f397..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_avx2/address.c +++ /dev/null @@ -1,78 +0,0 @@ -#include - -#include "address.h" -#include "params.h" -#include "utils.h" - -void PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]) { - int i; - - for (i = 0; i < 8; i++) { - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_ull_to_bytes( - bytes + i * 4, 4, addr[i]); - } -} - -void PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_set_layer_addr( - uint32_t addr[8], uint32_t layer) { - addr[0] = layer; -} - -void PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_set_tree_addr( - uint32_t addr[8], uint64_t tree) { - addr[1] = 0; - addr[2] = (uint32_t) (tree >> 32); - addr[3] = (uint32_t) tree; -} - -void PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_set_type( - uint32_t addr[8], uint32_t type) { - addr[4] = type; -} - -void PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; -} - -/* These functions are used for OTS addresses. */ - -void PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_set_keypair_addr( - uint32_t addr[8], uint32_t keypair) { - addr[5] = keypair; -} - -void PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; - out[5] = in[5]; -} - -void PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_set_chain_addr( - uint32_t addr[8], uint32_t chain) { - addr[6] = chain; -} - -void PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_set_hash_addr( - uint32_t addr[8], uint32_t hash) { - addr[7] = hash; -} - -/* These functions are used for all hash tree addresses (including FORS). */ - -void PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_set_tree_height( - uint32_t addr[8], uint32_t tree_height) { - addr[6] = tree_height; -} - -void PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_set_tree_index( - uint32_t addr[8], uint32_t tree_index) { - addr[7] = tree_index; -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_avx2/address.h b/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_avx2/address.h deleted file mode 100644 index 5187d3aa7e..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_avx2/address.h +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_ADDRESS_H -#define PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_ADDRESS_H - -#include - -#define PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_ADDR_TYPE_WOTS 0 -#define PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_ADDR_TYPE_WOTSPK 1 -#define PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_ADDR_TYPE_HASHTREE 2 -#define PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_ADDR_TYPE_FORSTREE 3 -#define PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_ADDR_TYPE_FORSPK 4 - -void PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]); - -void PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_set_layer_addr( - uint32_t addr[8], uint32_t layer); - -void PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_set_tree_addr( - uint32_t addr[8], uint64_t tree); - -void PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_set_type( - uint32_t addr[8], uint32_t type); - -/* Copies the layer and tree part of one address into the other */ -void PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for WOTS and FORS addresses. */ - -void PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_set_keypair_addr( - uint32_t addr[8], uint32_t keypair); - -void PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_set_chain_addr( - uint32_t addr[8], uint32_t chain); - -void PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_set_hash_addr( - uint32_t addr[8], uint32_t hash); - -void PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for all hash tree addresses (including FORS). */ - -void PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_set_tree_height( - uint32_t addr[8], uint32_t tree_height); - -void PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_set_tree_index( - uint32_t addr[8], uint32_t tree_index); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_avx2/api.h b/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_avx2/api.h deleted file mode 100644 index add60c93d1..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_avx2/api.h +++ /dev/null @@ -1,81 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_API_H -#define PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_API_H - -#include -#include - - - -#define PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_CRYPTO_ALGNAME "SPHINCS+" - -#define PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_CRYPTO_SECRETKEYBYTES 96 -#define PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_CRYPTO_PUBLICKEYBYTES 48 -#define PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_CRYPTO_BYTES 35664 -#define PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_CRYPTO_SEEDBYTES 72 - - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_avx2/fors.c b/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_avx2/fors.c deleted file mode 100644 index 3ab2621c40..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_avx2/fors.c +++ /dev/null @@ -1,240 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "fors.h" -#include "hash.h" -#include "hashx8.h" -#include "thash.h" -#include "thashx8.h" -#include "utils.h" -#include "utilsx8.h" - -static void fors_gen_skx8(unsigned char *sk0, - unsigned char *sk1, - unsigned char *sk2, - unsigned char *sk3, - unsigned char *sk4, - unsigned char *sk5, - unsigned char *sk6, - unsigned char *sk7, const unsigned char *sk_seed, - uint32_t fors_leaf_addrx8[8 * 8]) { - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_prf_addrx8(sk0, sk1, sk2, sk3, sk4, sk5, sk6, sk7, - sk_seed, fors_leaf_addrx8); -} - -static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, - const unsigned char *pub_seed, - uint32_t fors_leaf_addr[8], - const hash_state *state_seeded) { - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_thash_1(leaf, sk, pub_seed, fors_leaf_addr, state_seeded); -} - -static void fors_sk_to_leafx8(unsigned char *leaf0, - unsigned char *leaf1, - unsigned char *leaf2, - unsigned char *leaf3, - unsigned char *leaf4, - unsigned char *leaf5, - unsigned char *leaf6, - unsigned char *leaf7, - const unsigned char *sk0, - const unsigned char *sk1, - const unsigned char *sk2, - const unsigned char *sk3, - const unsigned char *sk4, - const unsigned char *sk5, - const unsigned char *sk6, - const unsigned char *sk7, - const unsigned char *pub_seed, - uint32_t fors_leaf_addrx8[8 * 8], - const hash_state *state_seeded) { - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_thashx8_1(leaf0, leaf1, leaf2, leaf3, leaf4, leaf5, leaf6, leaf7, - sk0, sk1, sk2, sk3, sk4, sk5, sk6, sk7, - pub_seed, fors_leaf_addrx8, state_seeded); -} - -static void fors_gen_leafx8(unsigned char *leaf0, - unsigned char *leaf1, - unsigned char *leaf2, - unsigned char *leaf3, - unsigned char *leaf4, - unsigned char *leaf5, - unsigned char *leaf6, - unsigned char *leaf7, - const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx0, - uint32_t addr_idx1, - uint32_t addr_idx2, - uint32_t addr_idx3, - uint32_t addr_idx4, - uint32_t addr_idx5, - uint32_t addr_idx6, - uint32_t addr_idx7, - const uint32_t fors_tree_addr[8], - const hash_state *state_seeded) { - uint32_t fors_leaf_addrx8[8 * 8] = {0}; - unsigned int j; - - /* Only copy the parts that must be kept in fors_leaf_addrx8. */ - for (j = 0; j < 8; j++) { - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_copy_keypair_addr(fors_leaf_addrx8 + j * 8, fors_tree_addr); - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_set_type(fors_leaf_addrx8 + j * 8, PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_ADDR_TYPE_FORSTREE); - } - - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_set_tree_index(fors_leaf_addrx8 + 0 * 8, addr_idx0); - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_set_tree_index(fors_leaf_addrx8 + 1 * 8, addr_idx1); - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_set_tree_index(fors_leaf_addrx8 + 2 * 8, addr_idx2); - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_set_tree_index(fors_leaf_addrx8 + 3 * 8, addr_idx3); - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_set_tree_index(fors_leaf_addrx8 + 4 * 8, addr_idx4); - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_set_tree_index(fors_leaf_addrx8 + 5 * 8, addr_idx5); - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_set_tree_index(fors_leaf_addrx8 + 6 * 8, addr_idx6); - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_set_tree_index(fors_leaf_addrx8 + 7 * 8, addr_idx7); - - fors_gen_skx8(leaf0, leaf1, leaf2, leaf3, leaf4, leaf5, leaf6, leaf7, - sk_seed, fors_leaf_addrx8); - fors_sk_to_leafx8(leaf0, leaf1, leaf2, leaf3, leaf4, leaf5, leaf6, leaf7, - leaf0, leaf1, leaf2, leaf3, leaf4, leaf5, leaf6, leaf7, - pub_seed, fors_leaf_addrx8, state_seeded); -} - -/** - * Interprets m as PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_FORS_HEIGHT-bit unsigned integers. - * Assumes m contains at least PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_FORS_TREES bits. - * Assumes indices has space for PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_FORS_TREES integers. - */ -static void message_to_indices(uint32_t *indices, const unsigned char *m) { - unsigned int i, j; - unsigned int offset = 0; - - for (i = 0; i < PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_FORS_TREES; i++) { - indices[i] = 0; - for (j = 0; j < PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_FORS_HEIGHT; j++) { - indices[i] ^= (((uint32_t)m[offset >> 3] >> (offset & 0x7)) & 0x1) << j; - offset++; - } - } -} - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_fors_sign( - unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], - const hash_state *state_seeded) { - /* Round up to multiple of 8 to prevent out-of-bounds for x8 parallelism */ - uint32_t indices[(PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_FORS_TREES + 7) & ~7] = {0}; - unsigned char roots[((PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_FORS_TREES + 7) & ~7) * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N]; - /* Sign to a buffer, since we may not have a nice multiple of 8 and would - otherwise overrun the signature. */ - unsigned char sigbufx8[8 * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N * (1 + PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_FORS_HEIGHT)]; - uint32_t fors_tree_addrx8[8 * 8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset[8] = {0}; - unsigned int i, j; - - for (j = 0; j < 8; j++) { - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_copy_keypair_addr(fors_tree_addrx8 + j * 8, fors_addr); - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_set_type(fors_tree_addrx8 + j * 8, PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_ADDR_TYPE_FORSTREE); - } - - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_copy_keypair_addr(fors_pk_addr, fors_addr); - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_set_type(fors_pk_addr, PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < ((PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_FORS_TREES + 7) & ~0x7); i += 8) { - for (j = 0; j < 8; j++) { - if (i + j < PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_FORS_TREES) { - idx_offset[j] = (i + j) * (1 << PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_FORS_HEIGHT); - - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_set_tree_height(fors_tree_addrx8 + j * 8, 0); - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_set_tree_index(fors_tree_addrx8 + j * 8, - indices[i + j] + idx_offset[j]); - } - } - - /* Include the secret key part that produces the selected leaf nodes. */ - fors_gen_skx8(sigbufx8 + 0 * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N, - sigbufx8 + 1 * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N, - sigbufx8 + 2 * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N, - sigbufx8 + 3 * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N, - sigbufx8 + 4 * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N, - sigbufx8 + 5 * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N, - sigbufx8 + 6 * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N, - sigbufx8 + 7 * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N, - sk_seed, fors_tree_addrx8); - - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_treehashx8_FORS_HEIGHT( - roots + i * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N, sigbufx8 + 8 * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N, sk_seed, pub_seed, - &indices[i], idx_offset, fors_gen_leafx8, fors_tree_addrx8, - state_seeded); - - for (j = 0; j < 8; j++) { - if (i + j < PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_FORS_TREES) { - memcpy(sig, sigbufx8 + j * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N, PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N); - memcpy(sig + PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N, - sigbufx8 + 8 * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N + j * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_FORS_HEIGHT, - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_FORS_HEIGHT); - sig += PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N * (1 + PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_FORS_HEIGHT); - } - } - } - - /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_thash_FORS_TREES(pk, roots, pub_seed, fors_pk_addr, state_seeded); -} - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, - const uint32_t fors_addr[8], - const hash_state *state_seeded) { - uint32_t indices[PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_FORS_TREES]; - unsigned char roots[PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_FORS_TREES * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N]; - unsigned char leaf[PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N]; - uint32_t fors_tree_addr[8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_copy_keypair_addr(fors_tree_addr, fors_addr); - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_copy_keypair_addr(fors_pk_addr, fors_addr); - - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_set_type(fors_tree_addr, PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_set_type(fors_pk_addr, PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_FORS_TREES; i++) { - idx_offset = i * (1 << PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_FORS_HEIGHT); - - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_set_tree_height(fors_tree_addr, 0); - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Derive the leaf from the included secret key part. */ - fors_sk_to_leaf(leaf, sig, pub_seed, fors_tree_addr, state_seeded); - sig += PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N; - - /* Derive the corresponding root node of this tree. */ - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_compute_root(roots + i * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N, leaf, indices[i], idx_offset, - sig, PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_FORS_HEIGHT, pub_seed, fors_tree_addr, state_seeded); - sig += PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_thash_FORS_TREES(pk, roots, pub_seed, fors_pk_addr, state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_avx2/fors.h b/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_avx2/fors.h deleted file mode 100644 index a66780c8ef..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_avx2/fors.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_FORS_H -#define PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_FORS_H - -#include - -#include "hash_state.h" -#include "params.h" - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_fors_sign( - unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *hash_state_seeded); - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_fors_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, const uint32_t fors_addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_avx2/hash.h b/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_avx2/hash.h deleted file mode 100644 index fe95601bef..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_avx2/hash.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_HASH_H -#define PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_HASH_H - -#include "hash_state.h" - -#include -#include - -void PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_initialize_hash_function( - hash_state *hash_state_seeded, - const unsigned char *pub_seed, const unsigned char *sk_seed); - -void PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_destroy_hash_function(hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_avx2/hash_sha256.c b/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_avx2/hash_sha256.c deleted file mode 100644 index 88e9f529b2..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_avx2/hash_sha256.c +++ /dev/null @@ -1,166 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "utils.h" - -#include "sha2.h" -#include "sha256.h" -#include "sha256x8.h" - -/** - * Initializes the hash function states - */ -void PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_initialize_hash_function( - hash_state *hash_state_seeded, - const unsigned char *pub_seed, const unsigned char *sk_seed) { - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_seed_state(&hash_state_seeded->x1, pub_seed); - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_seed_statex8(&hash_state_seeded->x8, pub_seed); - (void)sk_seed; /* Suppress an 'unused parameter' warning. */ -} - -/** - * Cleans up the hash function states - */ -void PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_destroy_hash_function(hash_state *hash_state_seeded) { - sha256_inc_ctx_release(&hash_state_seeded->x1); -} - -/* - * Computes PRF(key, addr), given a secret key of PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N bytes and an address - */ -void PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_prf_addr(unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded) { - unsigned char buf[PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_ADDR_BYTES]; - unsigned char outbuf[PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_OUTPUT_BYTES]; - - memcpy(buf, key, PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N); - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_compress_address(buf + PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N, addr); - - sha256(outbuf, buf, PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_ADDR_BYTES); - memcpy(out, outbuf, PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} - -/** - * Computes the message-dependent randomness R, using a secret seed as a key - * for HMAC, and an optional randomization value prefixed to the message. - * This requires m to have at least PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_BLOCK_BYTES + PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N space - * available in front of the pointer, i.e. before the message to use for the - * prefix. This is necessary to prevent having to move the message around (and - * allocate memory for it). - */ -void PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, const hash_state *hash_state_seeded) { - unsigned char buf[PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_BLOCK_BYTES + PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_OUTPUT_BYTES]; - sha256ctx state; - int i; - - /* This implements HMAC-SHA256 */ - for (i = 0; i < PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N; i++) { - buf[i] = 0x36 ^ sk_prf[i]; - } - memset(buf + PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N, 0x36, PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N); - - sha256_inc_init(&state); - sha256_inc_blocks(&state, buf, 1); - - memcpy(buf, optrand, PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N); - - /* If optrand + message cannot fill up an entire block */ - if (PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N + mlen < PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_BLOCK_BYTES) { - memcpy(buf + PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N, m, mlen); - sha256_inc_finalize(buf + PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_BLOCK_BYTES, &state, - buf, mlen + PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N); - } - /* Otherwise first fill a block, so that finalize only uses the message */ - else { - memcpy(buf + PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N, m, PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N); - sha256_inc_blocks(&state, buf, 1); - - m += PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N; - mlen -= PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N; - sha256_inc_finalize(buf + PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_BLOCK_BYTES, &state, m, mlen); - } - - for (i = 0; i < PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N; i++) { - buf[i] = 0x5c ^ sk_prf[i]; - } - memset(buf + PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N, 0x5c, PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N); - - sha256(buf, buf, PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_BLOCK_BYTES + PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_OUTPUT_BYTES); - memcpy(R, buf, PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} - -/** - * Computes the message hash using R, the public key, and the message. - * Outputs the message digest and the index of the leaf. The index is split in - * the tree index and the leaf index, for convenient copying to an address. - */ -void PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded) { -#define PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_TREE_BITS (PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_TREE_HEIGHT * (PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_D - 1)) -#define PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_TREE_BYTES ((PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_TREE_BITS + 7) / 8) -#define PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_LEAF_BITS PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_TREE_HEIGHT -#define PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_LEAF_BYTES ((PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_LEAF_BITS + 7) / 8) -#define PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_DGST_BYTES (PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_FORS_MSG_BYTES + PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_TREE_BYTES + PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_LEAF_BYTES) - - unsigned char seed[PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_OUTPUT_BYTES + 4]; - - /* Round to nearest multiple of PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_BLOCK_BYTES */ -#define PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_INBLOCKS (((PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_PK_BYTES + PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_BLOCK_BYTES - 1) & \ - -PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_BLOCK_BYTES) / PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_BLOCK_BYTES) - unsigned char inbuf[PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_INBLOCKS * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_BLOCK_BYTES]; - - unsigned char buf[PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_DGST_BYTES]; - unsigned char *bufp = buf; - sha256ctx state; - - sha256_inc_init(&state); - - memcpy(inbuf, R, PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N); - memcpy(inbuf + PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N, pk, PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_PK_BYTES); - - /* If R + pk + message cannot fill up an entire block */ - if (PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_PK_BYTES + mlen < PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_INBLOCKS * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_BLOCK_BYTES) { - memcpy(inbuf + PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_PK_BYTES, m, mlen); - sha256_inc_finalize(seed, &state, inbuf, PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_PK_BYTES + mlen); - } - /* Otherwise first fill a block, so that finalize only uses the message */ - else { - memcpy(inbuf + PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_PK_BYTES, m, - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_INBLOCKS * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_PK_BYTES); - sha256_inc_blocks(&state, inbuf, PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_INBLOCKS); - - m += PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_INBLOCKS * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_PK_BYTES; - mlen -= PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_INBLOCKS * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_PK_BYTES; - sha256_inc_finalize(seed, &state, m, mlen); - } - - /* By doing this in two steps, we prevent hashing the message twice; - otherwise each iteration in MGF1 would hash the message again. */ - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_mgf1(bufp, PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_DGST_BYTES, seed, PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_OUTPUT_BYTES); - - memcpy(digest, bufp, PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_FORS_MSG_BYTES); - bufp += PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_FORS_MSG_BYTES; - - *tree = PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_bytes_to_ull(bufp, PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_TREE_BYTES); - *tree &= (~(uint64_t)0) >> (64 - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_TREE_BITS); - bufp += PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_TREE_BYTES; - - *leaf_idx = (uint32_t)PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_bytes_to_ull( - bufp, PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_LEAF_BYTES); - *leaf_idx &= (~(uint32_t)0) >> (32 - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_LEAF_BITS); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_avx2/hash_sha256x8.c b/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_avx2/hash_sha256x8.c deleted file mode 100644 index 9f55df838a..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_avx2/hash_sha256x8.c +++ /dev/null @@ -1,61 +0,0 @@ -#include -#include - -#include "address.h" -#include "hashx8.h" -#include "params.h" -#include "sha256.h" -#include "sha256avx.h" -#include "sha256x8.h" -#include "utils.h" - -/* - * 8-way parallel version of prf_addr; takes 8x as much input and output - */ -void PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_prf_addrx8(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7, - const unsigned char *key, - const uint32_t addrx8[8 * 8]) { - unsigned char bufx8[8 * (PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_ADDR_BYTES)]; - unsigned char outbufx8[8 * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_OUTPUT_BYTES]; - unsigned int j; - - for (j = 0; j < 8; j++) { - memcpy(bufx8 + j * (PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_ADDR_BYTES), key, PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N); - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_compress_address(bufx8 + PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N + j * (PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_ADDR_BYTES), - addrx8 + j * 8); - } - - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_sha256x8(outbufx8 + 0 * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 1 * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 2 * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 3 * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 4 * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 5 * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 6 * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 7 * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - bufx8 + 0 * (PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_ADDR_BYTES), - bufx8 + 1 * (PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_ADDR_BYTES), - bufx8 + 2 * (PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_ADDR_BYTES), - bufx8 + 3 * (PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_ADDR_BYTES), - bufx8 + 4 * (PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_ADDR_BYTES), - bufx8 + 5 * (PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_ADDR_BYTES), - bufx8 + 6 * (PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_ADDR_BYTES), - bufx8 + 7 * (PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_ADDR_BYTES), - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_ADDR_BYTES); - - memcpy(out0, outbufx8 + 0 * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N); - memcpy(out1, outbufx8 + 1 * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N); - memcpy(out2, outbufx8 + 2 * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N); - memcpy(out3, outbufx8 + 3 * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N); - memcpy(out4, outbufx8 + 4 * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N); - memcpy(out5, outbufx8 + 5 * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N); - memcpy(out6, outbufx8 + 6 * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N); - memcpy(out7, outbufx8 + 7 * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_avx2/hash_state.h b/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_avx2/hash_state.h deleted file mode 100644 index d2e112a533..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_avx2/hash_state.h +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_HASH_STATE_H -#define PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_HASH_STATE_H - -/** - * Defines the type of the hash function state. - * - * Don't be fooled into thinking this instance of SPHINCS+ isn't stateless! - * - * From Section 7.2.2 from the SPHINCS+ round-2 specification: - * - * Each of the instances of the tweakable hash function take PK.seed as its - * first input, which is constant for a given key pair – and, thus, across - * a single signature. This leads to a lot of redundant computation. To remedy - * this, we pad PK.seed to the length of a full 64-byte SHA-256 input block. - * Because of the Merkle-Damgård construction that underlies SHA-256, this - * allows for reuse of the intermediate SHA-256 state after the initial call to - * the compression function which improves performance. - * - * We pass this hash state around in functions, because otherwise we need to - * have a global variable. - * - * We use a struct to differentiate between the x1 and x8 variants of SHA256. - */ - -#include "sha2.h" -#include "sha256avx.h" - -typedef struct { - sha256ctx x1; - sha256ctxx8 x8; -} hash_state; - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_avx2/hashx8.h b/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_avx2/hashx8.h deleted file mode 100644 index 3ec3f02441..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_avx2/hashx8.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_HASHX8_H -#define PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_HASHX8_H - -#include - -#include "params.h" - -void PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_prf_addrx8(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7, - const unsigned char *key, - const uint32_t addrx8[8 * 8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_avx2/params.h b/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_avx2/params.h deleted file mode 100644 index 602cc68f34..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_avx2/params.h +++ /dev/null @@ -1,53 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_PARAMS_H -#define PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_PARAMS_H - -/* Hash output length in bytes. */ -#define PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N 24 -/* Height of the hypertree. */ -#define PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_FULL_HEIGHT 66 -/* Number of subtree layer. */ -#define PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_D 22 -/* FORS tree dimensions. */ -#define PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_FORS_HEIGHT 8 -#define PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_FORS_TREES 33 -/* Winternitz parameter, */ -#define PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_WOTS_W 16 - -/* The hash function is defined by linking a different hash.c file, as opposed - to setting a #define constant. */ - -/* For clarity */ -#define PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_ADDR_BYTES 32 - -/* WOTS parameters. */ -#define PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_WOTS_LOGW 4 - -#define PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_WOTS_LEN1 (8 * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N / PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_WOTS_LOGW) - -/* PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#define PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_WOTS_LEN2 3 - -#define PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_WOTS_LEN (PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_WOTS_LEN1 + PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_WOTS_LEN2) -#define PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_WOTS_BYTES (PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_WOTS_LEN * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N) -#define PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_WOTS_PK_BYTES PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_WOTS_BYTES - -/* Subtree size. */ -#define PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_TREE_HEIGHT (PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_FULL_HEIGHT / PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_D) - -/* FORS parameters. */ -#define PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_FORS_MSG_BYTES ((PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_FORS_TREES + 7) / 8) -#define PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_FORS_BYTES ((PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_FORS_HEIGHT + 1) * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_FORS_TREES * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N) -#define PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_FORS_PK_BYTES PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N - -/* Resulting SPX sizes. */ -#define PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_BYTES (PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_FORS_BYTES + PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_D * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_WOTS_BYTES +\ - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_FULL_HEIGHT * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N) -#define PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_PK_BYTES (2 * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N) -#define PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SK_BYTES (2 * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_PK_BYTES) - -/* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ -#define PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_OPTRAND_BYTES 32 - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_avx2/sha256.c b/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_avx2/sha256.c deleted file mode 100644 index 648e5d0e7d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_avx2/sha256.c +++ /dev/null @@ -1,71 +0,0 @@ -/* Based on the public domain implementation in - * crypto_hash/sha512/ref/ from http://bench.cr.yp.to/supercop.html - * by D. J. Bernstein */ - -#include -#include -#include - -#include "sha2.h" -#include "sha256.h" -#include "utils.h" - -/* - * Compresses an address to a 22-byte sequence. - * This reduces the number of required SHA256 compression calls, as the last - * block of input is padded with at least 65 bits. - */ -void PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_compress_address(unsigned char *out, const uint32_t addr[8]) { - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_ull_to_bytes(out, 1, addr[0]); /* drop 3 bytes of the layer field */ - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_ull_to_bytes(out + 1, 4, addr[2]); /* drop the highest tree address word */ - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_ull_to_bytes(out + 5, 4, addr[3]); - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_ull_to_bytes(out + 9, 1, addr[4]); /* drop 3 bytes of the type field */ - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_ull_to_bytes(out + 10, 4, addr[5]); - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_ull_to_bytes(out + 14, 4, addr[6]); - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_ull_to_bytes(out + 18, 4, addr[7]); -} - -/** - * Requires 'input_plus_four_bytes' to have 'inlen' + 4 bytes, so that the last - * four bytes can be used for the counter. Typically 'input' is merely a seed. - * Outputs outlen number of bytes - */ -void PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_mgf1( - unsigned char *out, unsigned long outlen, - unsigned char *input_plus_four_bytes, unsigned long inlen) { - unsigned char outbuf[PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_OUTPUT_BYTES]; - unsigned long i; - - /* While we can fit in at least another full block of SHA256 output.. */ - for (i = 0; (i + 1)*PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_OUTPUT_BYTES <= outlen; i++) { - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_ull_to_bytes(input_plus_four_bytes + inlen, 4, i); - sha256(out, input_plus_four_bytes, inlen + 4); - out += PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_OUTPUT_BYTES; - } - /* Until we cannot anymore, and we fill the remainder. */ - if (outlen > i * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_OUTPUT_BYTES) { - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_ull_to_bytes(input_plus_four_bytes + inlen, 4, i); - sha256(outbuf, input_plus_four_bytes, inlen + 4); - memcpy(out, outbuf, outlen - i * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_OUTPUT_BYTES); - } -} - - -/** - * Absorb the constant pub_seed using one round of the compression function - * This initializes hash_state_seeded, which can then be reused in thash - **/ -void PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_seed_state(sha256ctx *hash_state_seeded, const unsigned char *pub_seed) { - uint8_t block[PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_BLOCK_BYTES]; - size_t i; - - for (i = 0; i < PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N; ++i) { - block[i] = pub_seed[i]; - } - for (i = PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N; i < PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_BLOCK_BYTES; ++i) { - block[i] = 0; - } - - sha256_inc_init(hash_state_seeded); - sha256_inc_blocks(hash_state_seeded, block, 1); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_avx2/sha256.h b/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_avx2/sha256.h deleted file mode 100644 index 1540ae97fb..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_avx2/sha256.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_H -#define PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_H - -#define PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_BLOCK_BYTES 64 -#define PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_OUTPUT_BYTES 32 /* This does not necessarily equal PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N */ -#define PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_ADDR_BYTES 22 - -#include -#include - -#include "sha2.h" - -void PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_compress_address(unsigned char *out, const uint32_t addr[8]); - -void PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_mgf1( - unsigned char *out, unsigned long outlen, - unsigned char *input_plus_four_bytes, unsigned long inlen); - -void PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_seed_state(sha256ctx *hash_state_seeded, const unsigned char *pub_seed); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_avx2/sha256avx.c b/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_avx2/sha256avx.c deleted file mode 100644 index 5a0e5c5969..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_avx2/sha256avx.c +++ /dev/null @@ -1,296 +0,0 @@ -#include -#include -#include - -#include "sha256avx.h" - -// Transpose 8 vectors containing 32-bit values -void PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_transpose(u256 s[8]) { - u256 tmp0[8]; - u256 tmp1[8]; - tmp0[0] = _mm256_unpacklo_epi32(s[0], s[1]); - tmp0[1] = _mm256_unpackhi_epi32(s[0], s[1]); - tmp0[2] = _mm256_unpacklo_epi32(s[2], s[3]); - tmp0[3] = _mm256_unpackhi_epi32(s[2], s[3]); - tmp0[4] = _mm256_unpacklo_epi32(s[4], s[5]); - tmp0[5] = _mm256_unpackhi_epi32(s[4], s[5]); - tmp0[6] = _mm256_unpacklo_epi32(s[6], s[7]); - tmp0[7] = _mm256_unpackhi_epi32(s[6], s[7]); - tmp1[0] = _mm256_unpacklo_epi64(tmp0[0], tmp0[2]); - tmp1[1] = _mm256_unpackhi_epi64(tmp0[0], tmp0[2]); - tmp1[2] = _mm256_unpacklo_epi64(tmp0[1], tmp0[3]); - tmp1[3] = _mm256_unpackhi_epi64(tmp0[1], tmp0[3]); - tmp1[4] = _mm256_unpacklo_epi64(tmp0[4], tmp0[6]); - tmp1[5] = _mm256_unpackhi_epi64(tmp0[4], tmp0[6]); - tmp1[6] = _mm256_unpacklo_epi64(tmp0[5], tmp0[7]); - tmp1[7] = _mm256_unpackhi_epi64(tmp0[5], tmp0[7]); - s[0] = _mm256_permute2x128_si256(tmp1[0], tmp1[4], 0x20); - s[1] = _mm256_permute2x128_si256(tmp1[1], tmp1[5], 0x20); - s[2] = _mm256_permute2x128_si256(tmp1[2], tmp1[6], 0x20); - s[3] = _mm256_permute2x128_si256(tmp1[3], tmp1[7], 0x20); - s[4] = _mm256_permute2x128_si256(tmp1[0], tmp1[4], 0x31); - s[5] = _mm256_permute2x128_si256(tmp1[1], tmp1[5], 0x31); - s[6] = _mm256_permute2x128_si256(tmp1[2], tmp1[6], 0x31); - s[7] = _mm256_permute2x128_si256(tmp1[3], tmp1[7], 0x31); -} - -void PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_sha256_clone_statex8(sha256ctxx8 *outctx, const sha256ctxx8 *inctx) { - memcpy(outctx, inctx, sizeof(sha256ctxx8)); -} - -void PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_sha256_init8x(sha256ctxx8 *ctx) { - ctx->s[0] = _mm256_set_epi32((int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667); - ctx->s[1] = _mm256_set_epi32((int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85); - ctx->s[2] = _mm256_set_epi32((int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372); - ctx->s[3] = _mm256_set_epi32((int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a); - ctx->s[4] = _mm256_set_epi32((int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f); - ctx->s[5] = _mm256_set_epi32((int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c); - ctx->s[6] = _mm256_set_epi32((int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab); - ctx->s[7] = _mm256_set_epi32((int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19); - - ctx->datalen = 0; - ctx->msglen = 0; -} - -void PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_sha256_update8x(sha256ctxx8 *ctx, - const unsigned char *d0, - const unsigned char *d1, - const unsigned char *d2, - const unsigned char *d3, - const unsigned char *d4, - const unsigned char *d5, - const unsigned char *d6, - const unsigned char *d7, - unsigned long long len) { - size_t i = 0; - size_t bytes_to_copy; - - while (i < len) { - bytes_to_copy = (size_t)len - i; - if (bytes_to_copy > 64) { - bytes_to_copy = 64; - } - memcpy(&ctx->msgblocks[64 * 0], d0 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64 * 1], d1 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64 * 2], d2 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64 * 3], d3 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64 * 4], d4 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64 * 5], d5 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64 * 6], d6 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64 * 7], d7 + i, bytes_to_copy); - ctx->datalen += (unsigned int)bytes_to_copy; - i += bytes_to_copy; - if (ctx->datalen == 64) { - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_sha256_transform8x(ctx, ctx->msgblocks); - ctx->msglen += 512; - ctx->datalen = 0; - } - } -} - -void PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_sha256_final8x(sha256ctxx8 *ctx, - unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7) { - unsigned int i, curlen; - - // Padding - if (ctx->datalen < 56) { - for (i = 0; i < 8; ++i) { - curlen = ctx->datalen; - ctx->msgblocks[64 * i + curlen++] = 0x80; - while (curlen < 64) { - ctx->msgblocks[64 * i + curlen++] = 0x00; - } - } - } else { - for (i = 0; i < 8; ++i) { - curlen = ctx->datalen; - ctx->msgblocks[64 * i + curlen++] = 0x80; - while (curlen < 64) { - ctx->msgblocks[64 * i + curlen++] = 0x00; - } - } - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_sha256_transform8x(ctx, ctx->msgblocks); - memset(ctx->msgblocks, 0, 8 * 64); - } - - // Add length of the message to each block - ctx->msglen += ctx->datalen * 8; - for (i = 0; i < 8; i++) { - ctx->msgblocks[64 * i + 63] = (unsigned char)ctx->msglen; - ctx->msgblocks[64 * i + 62] = (unsigned char)(ctx->msglen >> 8); - ctx->msgblocks[64 * i + 61] = (unsigned char)(ctx->msglen >> 16); - ctx->msgblocks[64 * i + 60] = (unsigned char)(ctx->msglen >> 24); - ctx->msgblocks[64 * i + 59] = (unsigned char)(ctx->msglen >> 32); - ctx->msgblocks[64 * i + 58] = (unsigned char)(ctx->msglen >> 40); - ctx->msgblocks[64 * i + 57] = (unsigned char)(ctx->msglen >> 48); - ctx->msgblocks[64 * i + 56] = (unsigned char)(ctx->msglen >> 56); - } - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_sha256_transform8x(ctx, ctx->msgblocks); - - // Compute final hash output - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_transpose(ctx->s); - - // Store Hash value - STORE(out0, BYTESWAP(ctx->s[0])); - STORE(out1, BYTESWAP(ctx->s[1])); - STORE(out2, BYTESWAP(ctx->s[2])); - STORE(out3, BYTESWAP(ctx->s[3])); - STORE(out4, BYTESWAP(ctx->s[4])); - STORE(out5, BYTESWAP(ctx->s[5])); - STORE(out6, BYTESWAP(ctx->s[6])); - STORE(out7, BYTESWAP(ctx->s[7])); -} - -void PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_sha256_transform8x(sha256ctxx8 *ctx, const unsigned char *data) { - u256 s[8], w[64], T0, T1; - int i; - - // Load words and transform data correctly - for (i = 0; i < 8; i++) { - w[i] = BYTESWAP(LOAD(data + 64 * i)); - w[i + 8] = BYTESWAP(LOAD(data + 32 + 64 * i)); - } - - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_transpose(w); - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_transpose(w + 8); - - // Initial State - s[0] = ctx->s[0]; - s[1] = ctx->s[1]; - s[2] = ctx->s[2]; - s[3] = ctx->s[3]; - s[4] = ctx->s[4]; - s[5] = ctx->s[5]; - s[6] = ctx->s[6]; - s[7] = ctx->s[7]; - - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 0, w[0]); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 1, w[1]); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 2, w[2]); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 3, w[3]); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 4, w[4]); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 5, w[5]); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 6, w[6]); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 7, w[7]); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 8, w[8]); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 9, w[9]); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 10, w[10]); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 11, w[11]); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 12, w[12]); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 13, w[13]); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 14, w[14]); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 15, w[15]); - w[16] = ADD4_32(WSIGMA1_AVX(w[14]), w[0], w[9], WSIGMA0_AVX(w[1])); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 16, w[16]); - w[17] = ADD4_32(WSIGMA1_AVX(w[15]), w[1], w[10], WSIGMA0_AVX(w[2])); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 17, w[17]); - w[18] = ADD4_32(WSIGMA1_AVX(w[16]), w[2], w[11], WSIGMA0_AVX(w[3])); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 18, w[18]); - w[19] = ADD4_32(WSIGMA1_AVX(w[17]), w[3], w[12], WSIGMA0_AVX(w[4])); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 19, w[19]); - w[20] = ADD4_32(WSIGMA1_AVX(w[18]), w[4], w[13], WSIGMA0_AVX(w[5])); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 20, w[20]); - w[21] = ADD4_32(WSIGMA1_AVX(w[19]), w[5], w[14], WSIGMA0_AVX(w[6])); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 21, w[21]); - w[22] = ADD4_32(WSIGMA1_AVX(w[20]), w[6], w[15], WSIGMA0_AVX(w[7])); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 22, w[22]); - w[23] = ADD4_32(WSIGMA1_AVX(w[21]), w[7], w[16], WSIGMA0_AVX(w[8])); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 23, w[23]); - w[24] = ADD4_32(WSIGMA1_AVX(w[22]), w[8], w[17], WSIGMA0_AVX(w[9])); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 24, w[24]); - w[25] = ADD4_32(WSIGMA1_AVX(w[23]), w[9], w[18], WSIGMA0_AVX(w[10])); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 25, w[25]); - w[26] = ADD4_32(WSIGMA1_AVX(w[24]), w[10], w[19], WSIGMA0_AVX(w[11])); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 26, w[26]); - w[27] = ADD4_32(WSIGMA1_AVX(w[25]), w[11], w[20], WSIGMA0_AVX(w[12])); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 27, w[27]); - w[28] = ADD4_32(WSIGMA1_AVX(w[26]), w[12], w[21], WSIGMA0_AVX(w[13])); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 28, w[28]); - w[29] = ADD4_32(WSIGMA1_AVX(w[27]), w[13], w[22], WSIGMA0_AVX(w[14])); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 29, w[29]); - w[30] = ADD4_32(WSIGMA1_AVX(w[28]), w[14], w[23], WSIGMA0_AVX(w[15])); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 30, w[30]); - w[31] = ADD4_32(WSIGMA1_AVX(w[29]), w[15], w[24], WSIGMA0_AVX(w[16])); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 31, w[31]); - w[32] = ADD4_32(WSIGMA1_AVX(w[30]), w[16], w[25], WSIGMA0_AVX(w[17])); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 32, w[32]); - w[33] = ADD4_32(WSIGMA1_AVX(w[31]), w[17], w[26], WSIGMA0_AVX(w[18])); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 33, w[33]); - w[34] = ADD4_32(WSIGMA1_AVX(w[32]), w[18], w[27], WSIGMA0_AVX(w[19])); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 34, w[34]); - w[35] = ADD4_32(WSIGMA1_AVX(w[33]), w[19], w[28], WSIGMA0_AVX(w[20])); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 35, w[35]); - w[36] = ADD4_32(WSIGMA1_AVX(w[34]), w[20], w[29], WSIGMA0_AVX(w[21])); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 36, w[36]); - w[37] = ADD4_32(WSIGMA1_AVX(w[35]), w[21], w[30], WSIGMA0_AVX(w[22])); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 37, w[37]); - w[38] = ADD4_32(WSIGMA1_AVX(w[36]), w[22], w[31], WSIGMA0_AVX(w[23])); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 38, w[38]); - w[39] = ADD4_32(WSIGMA1_AVX(w[37]), w[23], w[32], WSIGMA0_AVX(w[24])); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 39, w[39]); - w[40] = ADD4_32(WSIGMA1_AVX(w[38]), w[24], w[33], WSIGMA0_AVX(w[25])); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 40, w[40]); - w[41] = ADD4_32(WSIGMA1_AVX(w[39]), w[25], w[34], WSIGMA0_AVX(w[26])); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 41, w[41]); - w[42] = ADD4_32(WSIGMA1_AVX(w[40]), w[26], w[35], WSIGMA0_AVX(w[27])); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 42, w[42]); - w[43] = ADD4_32(WSIGMA1_AVX(w[41]), w[27], w[36], WSIGMA0_AVX(w[28])); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 43, w[43]); - w[44] = ADD4_32(WSIGMA1_AVX(w[42]), w[28], w[37], WSIGMA0_AVX(w[29])); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 44, w[44]); - w[45] = ADD4_32(WSIGMA1_AVX(w[43]), w[29], w[38], WSIGMA0_AVX(w[30])); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 45, w[45]); - w[46] = ADD4_32(WSIGMA1_AVX(w[44]), w[30], w[39], WSIGMA0_AVX(w[31])); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 46, w[46]); - w[47] = ADD4_32(WSIGMA1_AVX(w[45]), w[31], w[40], WSIGMA0_AVX(w[32])); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 47, w[47]); - w[48] = ADD4_32(WSIGMA1_AVX(w[46]), w[32], w[41], WSIGMA0_AVX(w[33])); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 48, w[48]); - w[49] = ADD4_32(WSIGMA1_AVX(w[47]), w[33], w[42], WSIGMA0_AVX(w[34])); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 49, w[49]); - w[50] = ADD4_32(WSIGMA1_AVX(w[48]), w[34], w[43], WSIGMA0_AVX(w[35])); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 50, w[50]); - w[51] = ADD4_32(WSIGMA1_AVX(w[49]), w[35], w[44], WSIGMA0_AVX(w[36])); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 51, w[51]); - w[52] = ADD4_32(WSIGMA1_AVX(w[50]), w[36], w[45], WSIGMA0_AVX(w[37])); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 52, w[52]); - w[53] = ADD4_32(WSIGMA1_AVX(w[51]), w[37], w[46], WSIGMA0_AVX(w[38])); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 53, w[53]); - w[54] = ADD4_32(WSIGMA1_AVX(w[52]), w[38], w[47], WSIGMA0_AVX(w[39])); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 54, w[54]); - w[55] = ADD4_32(WSIGMA1_AVX(w[53]), w[39], w[48], WSIGMA0_AVX(w[40])); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 55, w[55]); - w[56] = ADD4_32(WSIGMA1_AVX(w[54]), w[40], w[49], WSIGMA0_AVX(w[41])); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 56, w[56]); - w[57] = ADD4_32(WSIGMA1_AVX(w[55]), w[41], w[50], WSIGMA0_AVX(w[42])); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 57, w[57]); - w[58] = ADD4_32(WSIGMA1_AVX(w[56]), w[42], w[51], WSIGMA0_AVX(w[43])); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 58, w[58]); - w[59] = ADD4_32(WSIGMA1_AVX(w[57]), w[43], w[52], WSIGMA0_AVX(w[44])); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 59, w[59]); - w[60] = ADD4_32(WSIGMA1_AVX(w[58]), w[44], w[53], WSIGMA0_AVX(w[45])); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 60, w[60]); - w[61] = ADD4_32(WSIGMA1_AVX(w[59]), w[45], w[54], WSIGMA0_AVX(w[46])); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 61, w[61]); - w[62] = ADD4_32(WSIGMA1_AVX(w[60]), w[46], w[55], WSIGMA0_AVX(w[47])); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 62, w[62]); - w[63] = ADD4_32(WSIGMA1_AVX(w[61]), w[47], w[56], WSIGMA0_AVX(w[48])); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 63, w[63]); - - // Feed Forward - ctx->s[0] = ADD32(s[0], ctx->s[0]); - ctx->s[1] = ADD32(s[1], ctx->s[1]); - ctx->s[2] = ADD32(s[2], ctx->s[2]); - ctx->s[3] = ADD32(s[3], ctx->s[3]); - ctx->s[4] = ADD32(s[4], ctx->s[4]); - ctx->s[5] = ADD32(s[5], ctx->s[5]); - ctx->s[6] = ADD32(s[6], ctx->s[6]); - ctx->s[7] = ADD32(s[7], ctx->s[7]); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_avx2/sha256avx.h b/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_avx2/sha256avx.h deleted file mode 100644 index 682d557c0a..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_avx2/sha256avx.h +++ /dev/null @@ -1,103 +0,0 @@ -#ifndef SHA256AVX_H -#define SHA256AVX_H - -#include -#include - -static const unsigned int RC[] = { - 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, - 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, - 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, - 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, - 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, - 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, - 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, - 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, - 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, - 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, - 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, - 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, - 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, - 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, - 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, - 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 -}; - -#define u32 uint32_t -#define u256 __m256i - -#define XOR _mm256_xor_si256 -#define OR _mm256_or_si256 -#define AND _mm256_and_si256 -#define ADD32 _mm256_add_epi32 -#define NOT(x) _mm256_xor_si256(x, _mm256_set_epi32(-1, -1, -1, -1, -1, -1, -1, -1)) - -#define LOAD(src) _mm256_loadu_si256((__m256i *)(src)) -#define STORE(dest,src) _mm256_storeu_si256((__m256i *)(dest),src) - -#define BYTESWAP(x) _mm256_shuffle_epi8(x, _mm256_set_epi8(0xc,0xd,0xe,0xf,0x8,0x9,0xa,0xb,0x4,0x5,0x6,0x7,0x0,0x1,0x2,0x3,0xc,0xd,0xe,0xf,0x8,0x9,0xa,0xb,0x4,0x5,0x6,0x7,0x0,0x1,0x2,0x3)) - -#define SHIFTR32(x, y) _mm256_srli_epi32(x, y) -#define SHIFTL32(x, y) _mm256_slli_epi32(x, y) - -#define ROTR32(x, y) OR(SHIFTR32(x, y), SHIFTL32(x, 32 - (y))) -#define ROTL32(x, y) OR(SHIFTL32(x, y), SHIFTR32(x, 32 - (y))) - -#define XOR3(a, b, c) XOR(XOR(a, b), c) - -#define ADD3_32(a, b, c) ADD32(ADD32(a, b), c) -#define ADD4_32(a, b, c, d) ADD32(ADD32(ADD32(a, b), c), d) -#define ADD5_32(a, b, c, d, e) ADD32(ADD32(ADD32(ADD32(a, b), c), d), e) - -#define MAJ_AVX(a, b, c) XOR3(AND(a, b), AND(a, c), AND(b, c)) -#define CH_AVX(a, b, c) XOR(AND(a, b), AND(NOT(a), c)) - -#define SIGMA1_AVX(x) XOR3(ROTR32(x, 6), ROTR32(x, 11), ROTR32(x, 25)) -#define SIGMA0_AVX(x) XOR3(ROTR32(x, 2), ROTR32(x, 13), ROTR32(x, 22)) - -#define WSIGMA1_AVX(x) XOR3(ROTR32(x, 17), ROTR32(x, 19), SHIFTR32(x, 10)) -#define WSIGMA0_AVX(x) XOR3(ROTR32(x, 7), ROTR32(x, 18), SHIFTR32(x, 3)) - -#define SHA256ROUND_AVX(a, b, c, d, e, f, g, h, rc, w) \ - T0 = ADD5_32(h, SIGMA1_AVX(e), CH_AVX(e, f, g), _mm256_set1_epi32((int)RC[rc]), w); \ - (d) = ADD32(d, T0); \ - T1 = ADD32(SIGMA0_AVX(a), MAJ_AVX(a, b, c)); \ - (h) = ADD32(T0, T1); - -typedef struct SHA256state { - u256 s[8]; - uint8_t msgblocks[8 * 64]; - unsigned int datalen; - uint64_t msglen; -} sha256ctxx8; - - -void PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_transpose(u256 s[8]); -void PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_sha256_init_frombytes_x8(sha256ctxx8 *ctx, const uint8_t *s, unsigned long long msglen); -void PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_sha256_init8x(sha256ctxx8 *ctx); -void PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_sha256_update8x(sha256ctxx8 *ctx, - const unsigned char *d0, - const unsigned char *d1, - const unsigned char *d2, - const unsigned char *d3, - const unsigned char *d4, - const unsigned char *d5, - const unsigned char *d6, - const unsigned char *d7, - unsigned long long len); -void PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_sha256_final8x(sha256ctxx8 *ctx, - unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7); - -void PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_sha256_transform8x(sha256ctxx8 *ctx, const unsigned char *data); - -void PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_sha256_clone_statex8(sha256ctxx8 *outctx, const sha256ctxx8 *inctx); - - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_avx2/sha256x8.c b/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_avx2/sha256x8.c deleted file mode 100644 index 24d32834d2..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_avx2/sha256x8.c +++ /dev/null @@ -1,128 +0,0 @@ -#include - -#include "sha256.h" -#include "sha256avx.h" -#include "sha256x8.h" -#include "utils.h" - -void PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_seed_statex8(sha256ctxx8 *ctx, const unsigned char *pub_seed) { - uint8_t block[PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_BLOCK_BYTES]; - size_t i; - - for (i = 0; i < PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N; ++i) { - block[i] = pub_seed[i]; - } - for (i = PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N; i < PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_BLOCK_BYTES; ++i) { - block[i] = 0; - } - - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_sha256_init8x(ctx); - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_sha256_update8x(ctx, block, block, block, block, block, block, block, block, PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_BLOCK_BYTES); - -} - -/* This provides a wrapper around the internals of 8x parallel SHA256 */ -void PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_sha256x8(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - const unsigned char *in4, - const unsigned char *in5, - const unsigned char *in6, - const unsigned char *in7, unsigned long long inlen) { - sha256ctxx8 ctx; - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_sha256_init8x(&ctx); - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_sha256_update8x(&ctx, in0, in1, in2, in3, in4, in5, in6, in7, inlen); - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_sha256_final8x(&ctx, out0, out1, out2, out3, out4, out5, out6, out7); -} - -/** - * Note that inlen should be sufficiently small that it still allows for - * an array to be allocated on the stack. Typically 'in' is merely a seed. - * Outputs outlen number of bytes - */ -void PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_mgf1x8( - unsigned char *outx8, - unsigned long outlen, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - const unsigned char *in4, - const unsigned char *in5, - const unsigned char *in6, - const unsigned char *in7, - unsigned long inlen) { - unsigned char inbufx8[8 * ((PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_ADDR_BYTES) + 4)]; - unsigned char outbufx8[8 * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_OUTPUT_BYTES]; - unsigned long i; - unsigned int j; - - memcpy(inbufx8 + 0 * (inlen + 4), in0, inlen); - memcpy(inbufx8 + 1 * (inlen + 4), in1, inlen); - memcpy(inbufx8 + 2 * (inlen + 4), in2, inlen); - memcpy(inbufx8 + 3 * (inlen + 4), in3, inlen); - memcpy(inbufx8 + 4 * (inlen + 4), in4, inlen); - memcpy(inbufx8 + 5 * (inlen + 4), in5, inlen); - memcpy(inbufx8 + 6 * (inlen + 4), in6, inlen); - memcpy(inbufx8 + 7 * (inlen + 4), in7, inlen); - - /* While we can fit in at least another full block of SHA256 output.. */ - for (i = 0; (i + 1)*PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_OUTPUT_BYTES <= outlen; i++) { - for (j = 0; j < 8; j++) { - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_ull_to_bytes(inbufx8 + inlen + j * (inlen + 4), 4, i); - } - - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_sha256x8(outx8 + 0 * outlen, - outx8 + 1 * outlen, - outx8 + 2 * outlen, - outx8 + 3 * outlen, - outx8 + 4 * outlen, - outx8 + 5 * outlen, - outx8 + 6 * outlen, - outx8 + 7 * outlen, - inbufx8 + 0 * (inlen + 4), - inbufx8 + 1 * (inlen + 4), - inbufx8 + 2 * (inlen + 4), - inbufx8 + 3 * (inlen + 4), - inbufx8 + 4 * (inlen + 4), - inbufx8 + 5 * (inlen + 4), - inbufx8 + 6 * (inlen + 4), - inbufx8 + 7 * (inlen + 4), inlen + 4); - outx8 += PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_OUTPUT_BYTES; - } - /* Until we cannot anymore, and we fill the remainder. */ - for (j = 0; j < 8; j++) { - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_ull_to_bytes(inbufx8 + inlen + j * (inlen + 4), 4, i); - } - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_sha256x8(outbufx8 + 0 * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 1 * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 2 * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 3 * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 4 * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 5 * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 6 * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 7 * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - inbufx8 + 0 * (inlen + 4), - inbufx8 + 1 * (inlen + 4), - inbufx8 + 2 * (inlen + 4), - inbufx8 + 3 * (inlen + 4), - inbufx8 + 4 * (inlen + 4), - inbufx8 + 5 * (inlen + 4), - inbufx8 + 6 * (inlen + 4), - inbufx8 + 7 * (inlen + 4), inlen + 4); - - for (j = 0; j < 8; j++) { - memcpy(outx8 + j * outlen, - outbufx8 + j * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outlen - i * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_OUTPUT_BYTES); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_avx2/sha256x8.h b/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_avx2/sha256x8.h deleted file mode 100644 index ac40133b66..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_avx2/sha256x8.h +++ /dev/null @@ -1,44 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256X8_H -#define PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256X8_H - -#include "sha256avx.h" - -#define PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_BLOCK_BYTES 64 -#define PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_OUTPUT_BYTES 32 /* This does not necessarily equal PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N */ - -/* This provides a wrapper around the internals of 8x parallel SHA256 */ -void PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_sha256x8(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - const unsigned char *in4, - const unsigned char *in5, - const unsigned char *in6, - const unsigned char *in7, unsigned long long inlen); - -/** - * Note that inlen should be sufficiently small that it still allows for - * an array to be allocated on the stack. Typically 'in' is merely a seed. - * Outputs outlen number of bytes - */ -void PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_mgf1x8(unsigned char *outx8, unsigned long outlen, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - const unsigned char *in4, - const unsigned char *in5, - const unsigned char *in6, - const unsigned char *in7, - unsigned long inlen); - -void PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_seed_statex8(sha256ctxx8 *ctx, const unsigned char *pub_seed); -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_avx2/sign.c b/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_avx2/sign.c deleted file mode 100644 index c8c9439512..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_avx2/sign.c +++ /dev/null @@ -1,356 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "api.h" -#include "fors.h" -#include "hash.h" -#include "hash_state.h" -#include "params.h" -#include "randombytes.h" -#include "thash.h" -#include "utils.h" -#include "wots.h" - -/** - * Computes the leaf at a given address. First generates the WOTS key pair, - * then computes leaf by hashing horizontally. - */ -static void wots_gen_leaf(unsigned char *leaf, const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx, const uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - unsigned char pk[PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_WOTS_BYTES]; - uint32_t wots_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_set_type( - wots_addr, PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_set_type( - wots_pk_addr, PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_ADDR_TYPE_WOTSPK); - - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_set_keypair_addr( - wots_addr, addr_idx); - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_wots_gen_pk( - pk, sk_seed, pub_seed, wots_addr, hash_state_seeded); - - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_copy_keypair_addr( - wots_pk_addr, wots_addr); - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_thash_WOTS_LEN( - leaf, pk, pub_seed, wots_pk_addr, hash_state_seeded); -} - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_crypto_sign_secretkeybytes(void) { - return PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_CRYPTO_SECRETKEYBYTES; -} - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_crypto_sign_publickeybytes(void) { - return PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_CRYPTO_PUBLICKEYBYTES; -} - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_crypto_sign_bytes(void) { - return PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_CRYPTO_BYTES; -} - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_crypto_sign_seedbytes(void) { - return PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_CRYPTO_SEEDBYTES; -} - -/* - * Generates an SPX key pair given a seed of length - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed) { - /* We do not need the auth path in key generation, but it simplifies the - code to have just one treehash routine that computes both root and path - in one function. */ - unsigned char auth_path[PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_TREE_HEIGHT * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N]; - uint32_t top_tree_addr[8] = {0}; - hash_state hash_state_seeded; - - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_set_layer_addr( - top_tree_addr, PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_D - 1); - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_set_type( - top_tree_addr, PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_ADDR_TYPE_HASHTREE); - - /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ - memcpy(sk, seed, PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_CRYPTO_SEEDBYTES); - - memcpy(pk, sk + 2 * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N, PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_initialize_hash_function(&hash_state_seeded, pk, sk); - - /* Compute root node of the top-most subtree. */ - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_treehash_TREE_HEIGHT( - sk + 3 * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N, auth_path, sk, sk + 2 * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N, 0, 0, - wots_gen_leaf, top_tree_addr, &hash_state_seeded); - - memcpy(pk + PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N, sk + 3 * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N, PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N); - - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_destroy_hash_function(&hash_state_seeded); - return 0; -} - -/* - * Generates an SPX key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk) { - unsigned char seed[PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_CRYPTO_SEEDBYTES]; - randombytes(seed, PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_CRYPTO_SEEDBYTES); - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_crypto_sign_seed_keypair( - pk, sk, seed); - - return 0; -} - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - const unsigned char *sk_seed = sk; - const unsigned char *sk_prf = sk + PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N; - const unsigned char *pk = sk + 2 * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N; - const unsigned char *pub_seed = pk; - - unsigned char optrand[PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N]; - unsigned char mhash[PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_FORS_MSG_BYTES]; - unsigned char root[PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N]; - uint32_t i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - - hash_state hash_state_seeded; - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_initialize_hash_function( - &hash_state_seeded, - pub_seed, sk_seed); - - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_set_type( - wots_addr, PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_set_type( - tree_addr, PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_ADDR_TYPE_HASHTREE); - - /* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ - randombytes(optrand, PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N); - /* Compute the digest randomization value. */ - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_gen_message_random( - sig, sk_prf, optrand, m, mlen, &hash_state_seeded); - - /* Derive the message digest and leaf index from R, PK and M. */ - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N; - - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_set_keypair_addr( - wots_addr, idx_leaf); - - /* Sign the message hash using FORS. */ - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_fors_sign( - sig, root, mhash, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_FORS_BYTES; - - for (i = 0; i < PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_D; i++) { - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_set_tree_addr(tree_addr, tree); - - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_set_keypair_addr( - wots_addr, idx_leaf); - - /* Compute a WOTS signature. */ - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_wots_sign( - sig, root, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_WOTS_BYTES; - - /* Compute the authentication path for the used WOTS leaf. */ - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_treehash_TREE_HEIGHT( - root, sig, sk_seed, pub_seed, idx_leaf, 0, - wots_gen_leaf, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_TREE_HEIGHT * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_TREE_HEIGHT; - } - - *siglen = PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_BYTES; - - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_destroy_hash_function(&hash_state_seeded); - return 0; -} - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk) { - const unsigned char *pub_seed = pk; - const unsigned char *pub_root = pk + PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N; - unsigned char mhash[PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_FORS_MSG_BYTES]; - unsigned char wots_pk[PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_WOTS_BYTES]; - unsigned char root[PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N]; - unsigned char leaf[PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N]; - unsigned int i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - hash_state hash_state_seeded; - - if (siglen != PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_BYTES) { - return -1; - } - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_initialize_hash_function( - &hash_state_seeded, - pub_seed, NULL); - - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_set_type( - wots_addr, PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_set_type( - tree_addr, PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_ADDR_TYPE_HASHTREE); - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_set_type( - wots_pk_addr, PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_ADDR_TYPE_WOTSPK); - - /* Derive the message digest and leaf index from R || PK || M. */ - /* The additional PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N is a result of the hash domain separator. */ - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N; - - /* Layer correctly defaults to 0, so no need to set_layer_addr */ - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_set_keypair_addr( - wots_addr, idx_leaf); - - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_fors_pk_from_sig( - root, sig, mhash, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_FORS_BYTES; - - /* For each subtree.. */ - for (i = 0; i < PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_D; i++) { - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_set_tree_addr(tree_addr, tree); - - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_set_keypair_addr( - wots_addr, idx_leaf); - - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_copy_keypair_addr( - wots_pk_addr, wots_addr); - - /* The WOTS public key is only correct if the signature was correct. */ - /* Initially, root is the FORS pk, but on subsequent iterations it is - the root of the subtree below the currently processed subtree. */ - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_wots_pk_from_sig( - wots_pk, sig, root, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_WOTS_BYTES; - - /* Compute the leaf node using the WOTS public key. */ - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_thash_WOTS_LEN( - leaf, wots_pk, pub_seed, wots_pk_addr, &hash_state_seeded); - - /* Compute the root node of this subtree. */ - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_compute_root( - root, leaf, idx_leaf, 0, sig, PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_TREE_HEIGHT, - pub_seed, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_TREE_HEIGHT * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_TREE_HEIGHT; - } - - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_destroy_hash_function(&hash_state_seeded); - /* Check if the root node equals the root node in the public key. */ - if (memcmp(root, pub_root, PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N) != 0) { - return -1; - } - - return 0; -} - - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - size_t siglen; - - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_crypto_sign_signature( - sm, &siglen, m, mlen, sk); - - memmove(sm + PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_BYTES, m, mlen); - *smlen = siglen + mlen; - - return 0; -} - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk) { - /* The API caller does not necessarily know what size a signature should be - but SPHINCS+ signatures are always exactly PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_BYTES. */ - if (smlen < PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_BYTES) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - *mlen = smlen - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_BYTES; - - if (PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_crypto_sign_verify( - sm, PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_BYTES, sm + PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_BYTES, *mlen, pk)) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - /* If verification was successful, move the message to the right place. */ - memmove(m, sm + PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_BYTES, *mlen); - - return 0; -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_avx2/thash.h b/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_avx2/thash.h deleted file mode 100644 index 841382bd17..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_avx2/thash.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_THASH_H -#define PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_THASH_H - -#include "hash_state.h" - -#include - -void PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_avx2/thash_sha256_simple.c b/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_avx2/thash_sha256_simple.c deleted file mode 100644 index 57f57eadd9..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_avx2/thash_sha256_simple.c +++ /dev/null @@ -1,75 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "thash.h" - -#include "sha2.h" -#include "sha256.h" - -/** - * Takes an array of inblocks concatenated arrays of PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N bytes. - */ -static void PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_thash( - unsigned char *out, unsigned char *buf, - const unsigned char *in, unsigned int inblocks, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char outbuf[PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_OUTPUT_BYTES]; - sha256ctx sha2_state; - - (void)pub_seed; /* Suppress an 'unused parameter' warning. */ - - /* Retrieve precomputed state containing pub_seed */ - sha256_inc_ctx_clone(&sha2_state, &hash_state_seeded->x1); - - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_compress_address(buf, addr); - memcpy(buf + PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_ADDR_BYTES, in, inblocks * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N); - - sha256_inc_finalize(outbuf, &sha2_state, buf, PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N); - memcpy(out, outbuf, PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N); -} - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_ADDR_BYTES + 1 * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N]; - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_thash( - out, buf, in, 1, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_ADDR_BYTES + 2 * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N]; - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_thash( - out, buf, in, 2, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_ADDR_BYTES + PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_WOTS_LEN * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N]; - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_thash( - out, buf, in, PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_WOTS_LEN, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_ADDR_BYTES + PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_FORS_TREES * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N]; - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_thash( - out, buf, in, PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_FORS_TREES, pub_seed, addr, hash_state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_avx2/thash_sha256_simplex8.c b/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_avx2/thash_sha256_simplex8.c deleted file mode 100644 index ee301b2811..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_avx2/thash_sha256_simplex8.c +++ /dev/null @@ -1,129 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash_state.h" -#include "params.h" -#include "sha256.h" -#include "sha256avx.h" -#include "sha256x8.h" -#include "thashx8.h" -#include "utils.h" - -/** - * 8-way parallel version of thash; takes 8x as much input and output - */ -static void thashx8(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - const unsigned char *in4, - const unsigned char *in5, - const unsigned char *in6, - const unsigned char *in7, unsigned int inblocks, - const unsigned char *pub_seed, uint32_t addrx8[8 * 8], - uint8_t *bufx8, - const hash_state *state_seeded) { - unsigned char outbufx8[8 * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_OUTPUT_BYTES]; - unsigned int i; - sha256ctxx8 ctx; - - (void)pub_seed; /* Suppress an 'unused parameter' warning. */ - - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_sha256_clone_statex8(&ctx, &state_seeded->x8); - - for (i = 0; i < 8; i++) { - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_compress_address(bufx8 + i * (PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N), - addrx8 + i * 8); - } - - memcpy(bufx8 + PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_ADDR_BYTES + - 0 * (PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N), in0, inblocks * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N); - memcpy(bufx8 + PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_ADDR_BYTES + - 1 * (PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N), in1, inblocks * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N); - memcpy(bufx8 + PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_ADDR_BYTES + - 2 * (PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N), in2, inblocks * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N); - memcpy(bufx8 + PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_ADDR_BYTES + - 3 * (PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N), in3, inblocks * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N); - memcpy(bufx8 + PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_ADDR_BYTES + - 4 * (PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N), in4, inblocks * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N); - memcpy(bufx8 + PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_ADDR_BYTES + - 5 * (PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N), in5, inblocks * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N); - memcpy(bufx8 + PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_ADDR_BYTES + - 6 * (PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N), in6, inblocks * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N); - memcpy(bufx8 + PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_ADDR_BYTES + - 7 * (PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N), in7, inblocks * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N); - - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_sha256_update8x(&ctx, - bufx8 + 0 * (PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N), - bufx8 + 1 * (PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N), - bufx8 + 2 * (PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N), - bufx8 + 3 * (PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N), - bufx8 + 4 * (PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N), - bufx8 + 5 * (PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N), - bufx8 + 6 * (PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N), - bufx8 + 7 * (PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N), - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N); - - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_sha256_final8x(&ctx, - outbufx8 + 0 * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 1 * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 2 * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 3 * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 4 * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 5 * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 6 * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 7 * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_OUTPUT_BYTES); - - memcpy(out0, outbufx8 + 0 * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N); - memcpy(out1, outbufx8 + 1 * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N); - memcpy(out2, outbufx8 + 2 * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N); - memcpy(out3, outbufx8 + 3 * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N); - memcpy(out4, outbufx8 + 4 * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N); - memcpy(out5, outbufx8 + 5 * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N); - memcpy(out6, outbufx8 + 6 * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N); - memcpy(out7, outbufx8 + 7 * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N); -} - -#define thashx8_variant_impl(name, size) \ - void PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_thashx8_##name(unsigned char *out0, \ - unsigned char *out1, \ - unsigned char *out2, \ - unsigned char *out3, \ - unsigned char *out4, \ - unsigned char *out5, \ - unsigned char *out6, \ - unsigned char *out7, \ - const unsigned char *in0, \ - const unsigned char *in1, \ - const unsigned char *in2, \ - const unsigned char *in3, \ - const unsigned char *in4, \ - const unsigned char *in5, \ - const unsigned char *in6, \ - const unsigned char *in7, \ - const unsigned char *pub_seed, \ - uint32_t addrx8[8*8], \ - const hash_state *state_seeded) \ - { \ - const unsigned int inblocks = (size); \ - uint8_t bufx8[8*(PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_SHA256_ADDR_BYTES + (size)*PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N)]; \ - thashx8(out0, out1, out2, out3, out4, out5, out6, out7, \ - in0, in1, in2, in3, in4, in5, in6, in7, inblocks, \ - pub_seed, addrx8, bufx8, state_seeded); \ - } - -thashx8_variant_impl(1, 1) -thashx8_variant_impl(2, 2) -thashx8_variant_impl(WOTS_LEN, PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_WOTS_LEN) -thashx8_variant_impl(FORS_TREES, PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_FORS_TREES) - -#undef thashx8_variant_impl diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_avx2/thashx8.h b/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_avx2/thashx8.h deleted file mode 100644 index 17d1ecc046..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_avx2/thashx8.h +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_THASHX8_H -#define PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_THASHX8_H - -#include - -#include "hash_state.h" -#include "sha256avx.h" - - -#define thashx8_variant(name) \ - void PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_thashx8_##name( \ - unsigned char *out0, \ - unsigned char *out1, \ - unsigned char *out2, \ - unsigned char *out3, \ - unsigned char *out4, \ - unsigned char *out5, \ - unsigned char *out6, \ - unsigned char *out7, \ - const unsigned char *in0, \ - const unsigned char *in1, \ - const unsigned char *in2, \ - const unsigned char *in3, \ - const unsigned char *in4, \ - const unsigned char *in5, \ - const unsigned char *in6, \ - const unsigned char *in7, \ - const unsigned char *pub_seed, \ - uint32_t addrx8[8*8], \ - const hash_state *state_seeded) - - -thashx8_variant(1); -thashx8_variant(2); -thashx8_variant(WOTS_LEN); -thashx8_variant(FORS_TREES); - -#undef thashx8_variant -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_avx2/utils.c b/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_avx2/utils.c deleted file mode 100644 index 91c17256a9..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_avx2/utils.c +++ /dev/null @@ -1,199 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "hash_state.h" -#include "params.h" -#include "thash.h" -#include "utils.h" - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in) { - - /* Iterate over out in decreasing order, for big-endianness. */ - for (size_t i = outlen; i > 0; i--) { - out[i - 1] = in & 0xff; - in = in >> 8; - } -} - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_bytes_to_ull( - const unsigned char *in, size_t inlen) { - unsigned long long retval = 0; - - for (size_t i = 0; i < inlen; i++) { - retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); - } - return retval; -} - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - uint32_t i; - unsigned char buffer[2 * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N]; - - /* If leaf_idx is odd (last bit = 1), current path element is a right child - and auth_path has to go left. Otherwise it is the other way around. */ - if (leaf_idx & 1) { - memcpy(buffer + PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N, leaf, PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N); - } else { - memcpy(buffer, leaf, PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N); - memcpy(buffer + PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N, auth_path, PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N); - } - auth_path += PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N; - - for (i = 0; i < tree_height - 1; i++) { - leaf_idx >>= 1; - idx_offset >>= 1; - /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_set_tree_height(addr, i + 1); - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_set_tree_index( - addr, leaf_idx + idx_offset); - - /* Pick the right or left neighbor, depending on parity of the node. */ - if (leaf_idx & 1) { - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_thash_2( - buffer + PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N); - } else { - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_thash_2( - buffer, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer + PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N, auth_path, PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N); - } - auth_path += PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N; - } - - /* The last iteration is exceptional; we do not copy an auth_path node. */ - leaf_idx >>= 1; - idx_offset >>= 1; - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_set_tree_height(addr, tree_height); - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_set_tree_index( - addr, leaf_idx + idx_offset); - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_thash_2( - root, buffer, pub_seed, addr, hash_state_seeded); -} - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -static void PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_treehash( - unsigned char *root, unsigned char *auth_path, - unsigned char *stack, unsigned int *heights, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - - unsigned int offset = 0; - uint32_t idx; - uint32_t tree_idx; - - for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { - /* Add the next leaf node to the stack. */ - gen_leaf(stack + offset * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N, - sk_seed, pub_seed, idx + idx_offset, tree_addr, - hash_state_seeded); - offset++; - heights[offset - 1] = 0; - - /* If this is a node we need for the auth path.. */ - if ((leaf_idx ^ 0x1) == idx) { - memcpy(auth_path, stack + (offset - 1)*PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N, PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N); - } - - /* While the top-most nodes are of equal height.. */ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { - /* Compute index of the new node, in the next layer. */ - tree_idx = (idx >> (heights[offset - 1] + 1)); - - /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_set_tree_height( - tree_addr, heights[offset - 1] + 1); - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_set_tree_index( - tree_addr, tree_idx + (idx_offset >> (heights[offset - 1] + 1))); - /* Hash the top-most nodes from the stack together. */ - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_thash_2( - stack + (offset - 2)*PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N, stack + (offset - 2)*PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N, - pub_seed, tree_addr, hash_state_seeded); - offset--; - /* Note that the top-most node is now one layer higher. */ - heights[offset - 1]++; - - /* If this is a node we need for the auth path.. */ - if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_path + heights[offset - 1]*PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N, - stack + (offset - 1)*PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N, PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N); - } - } - } - memcpy(root, stack, PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N); -} - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_FORS_HEIGHT + 1)*PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N]; - unsigned int heights[PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_FORS_HEIGHT + 1]; - - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_FORS_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_TREE_HEIGHT + 1)*PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N]; - unsigned int heights[PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_TREE_HEIGHT + 1]; - - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_TREE_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_avx2/utils.h b/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_avx2/utils.h deleted file mode 100644 index 825bcca7e6..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_avx2/utils.h +++ /dev/null @@ -1,64 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_UTILS_H -#define PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_UTILS_H - -#include "hash_state.h" -#include "params.h" -#include -#include - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in); - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_bytes_to_ull( - const unsigned char *in, size_t inlen); - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -void PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_avx2/utilsx8.c b/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_avx2/utilsx8.c deleted file mode 100644 index 2d133369e9..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_avx2/utilsx8.c +++ /dev/null @@ -1,172 +0,0 @@ -#include - -#include "address.h" -#include "params.h" -#include "thashx8.h" -#include "utils.h" - -#include "utilsx8.h" - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -static void treehashx8(unsigned char *rootx8, unsigned char *auth_pathx8, - unsigned char *stackx8, unsigned int *heights, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t leaf_idx[8], uint32_t idx_offset[8], - uint32_t tree_height, - void (*gen_leafx8)( - unsigned char * /* leaf0 */, - unsigned char * /* leaf1 */, - unsigned char * /* leaf2 */, - unsigned char * /* leaf3 */, - unsigned char * /* leaf4 */, - unsigned char * /* leaf5 */, - unsigned char * /* leaf6 */, - unsigned char * /* leaf7 */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx0 */, - uint32_t /* addr_idx1 */, - uint32_t /* addr_idx2 */, - uint32_t /* addr_idx3 */, - uint32_t /* addr_idx4 */, - uint32_t /* addr_idx5 */, - uint32_t /* addr_idx6 */, - uint32_t /* addr_idx7 */, - const uint32_t[8] /* tree_addr */, - const hash_state * /* state_seeded */), - uint32_t tree_addrx8[8 * 8], - const hash_state *state_seeded) { - unsigned int offset = 0; - uint32_t idx; - uint32_t tree_idx; - unsigned int j; - - for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { - /* Add the next leaf node to the stack. */ - gen_leafx8(stackx8 + 0 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N + offset * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N, - stackx8 + 1 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N + offset * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N, - stackx8 + 2 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N + offset * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N, - stackx8 + 3 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N + offset * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N, - stackx8 + 4 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N + offset * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N, - stackx8 + 5 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N + offset * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N, - stackx8 + 6 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N + offset * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N, - stackx8 + 7 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N + offset * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N, - sk_seed, pub_seed, - idx + idx_offset[0], - idx + idx_offset[1], - idx + idx_offset[2], - idx + idx_offset[3], - idx + idx_offset[4], - idx + idx_offset[5], - idx + idx_offset[6], - idx + idx_offset[7], - tree_addrx8, - state_seeded); - offset++; - heights[offset - 1] = 0; - - /* If this is a node we need for the auth path.. */ - for (j = 0; j < 8; j++) { - if ((leaf_idx[j] ^ 0x1) == idx) { - memcpy(auth_pathx8 + j * tree_height * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N, - stackx8 + j * (tree_height + 1)*PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N + (offset - 1)*PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N, PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N); - } - } - - /* While the top-most nodes are of equal height.. */ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { - /* Compute index of the new node, in the next layer. */ - tree_idx = (idx >> (heights[offset - 1] + 1)); - - /* Set the address of the node we're creating. */ - for (j = 0; j < 8; j++) { - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_set_tree_height(tree_addrx8 + j * 8, heights[offset - 1] + 1); - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_set_tree_index(tree_addrx8 + j * 8, - tree_idx + (idx_offset[j] >> (heights[offset - 1] + 1))); - } - /* Hash the top-most nodes from the stack together. */ - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_thashx8_2(stackx8 + 0 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N, - stackx8 + 1 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N, - stackx8 + 2 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N, - stackx8 + 3 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N, - stackx8 + 4 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N, - stackx8 + 5 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N, - stackx8 + 6 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N, - stackx8 + 7 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N, - stackx8 + 0 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N, - stackx8 + 1 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N, - stackx8 + 2 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N, - stackx8 + 3 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N, - stackx8 + 4 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N, - stackx8 + 5 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N, - stackx8 + 6 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N, - stackx8 + 7 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N, - pub_seed, tree_addrx8, state_seeded); - offset--; - /* Note that the top-most node is now one layer higher. */ - heights[offset - 1]++; - - /* If this is a node we need for the auth path.. */ - for (j = 0; j < 8; j++) { - if (((leaf_idx[j] >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_pathx8 + j * tree_height * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N + heights[offset - 1]*PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N, - stackx8 + j * (tree_height + 1)*PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N + (offset - 1)*PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N, PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N); - } - } - } - } - - for (j = 0; j < 8; j++) { - memcpy(rootx8 + j * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N, stackx8 + j * (tree_height + 1)*PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N, PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N); - } -} - -/* The wrappers below ensure we used fixed-size buffers on the stack (no VLAs) */ - - -#define treehashx8_variant(name, size) \ - void PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_treehashx8_##name( \ - unsigned char *rootx8, unsigned char *auth_pathx8, \ - const unsigned char *sk_seed, const unsigned char *pub_seed, \ - const uint32_t leaf_idx[8], uint32_t idx_offset[8], \ - void (*gen_leafx8)( \ - unsigned char* /* leaf0 */, \ - unsigned char* /* leaf1 */, \ - unsigned char* /* leaf2 */, \ - unsigned char* /* leaf3 */, \ - unsigned char* /* leaf4 */, \ - unsigned char* /* leaf5 */, \ - unsigned char* /* leaf6 */, \ - unsigned char* /* leaf7 */, \ - const unsigned char* /* sk_seed */, \ - const unsigned char* /* pub_seed */, \ - uint32_t /* addr_idx0 */, \ - uint32_t /* addr_idx1 */, \ - uint32_t /* addr_idx2 */, \ - uint32_t /* addr_idx3 */, \ - uint32_t /* addr_idx4 */, \ - uint32_t /* addr_idx5 */, \ - uint32_t /* addr_idx6 */, \ - uint32_t /* addr_idx7 */, \ - const uint32_t[8] /* tree_addr */, \ - const hash_state* /* state_seeded */), \ - uint32_t tree_addrx8[8*8], \ - const hash_state *state_seeded) \ - { \ - const uint32_t tree_height = (size); \ - unsigned char stackx8[8*((size) + 1)*PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N]; \ - unsigned int heights[(size) + 1]; \ - treehashx8(rootx8, auth_pathx8, stackx8, heights, sk_seed, pub_seed, \ - leaf_idx, idx_offset, tree_height, gen_leafx8, tree_addrx8, state_seeded); \ - } - -treehashx8_variant(FORS_HEIGHT, PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_FORS_HEIGHT) - -#undef treehashx8_variant diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_avx2/utilsx8.h b/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_avx2/utilsx8.h deleted file mode 100644 index e6df8cdc02..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_avx2/utilsx8.h +++ /dev/null @@ -1,46 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_UTILSX8_H -#define PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_UTILSX8_H - -#include - -#include "hash_state.h" -#include "params.h" - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ - -void PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_treehashx8_FORS_HEIGHT( - unsigned char *rootx8, unsigned char *auth_pathx8, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t leaf_idx[8], uint32_t idx_offset[8], - void (*gen_leafx8)( - unsigned char * /* leaf0 */, - unsigned char * /* leaf1 */, - unsigned char * /* leaf2 */, - unsigned char * /* leaf3 */, - unsigned char * /* leaf4 */, - unsigned char * /* leaf5 */, - unsigned char * /* leaf6 */, - unsigned char * /* leaf7 */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx0 */, - uint32_t /* addr_idx1 */, - uint32_t /* addr_idx2 */, - uint32_t /* addr_idx3 */, - uint32_t /* addr_idx4 */, - uint32_t /* addr_idx5 */, - uint32_t /* addr_idx6 */, - uint32_t /* addr_idx7 */, - const uint32_t[8] /* tree_addr */, - const hash_state * /* state_seeded */), - uint32_t tree_addrx8[8 * 8], - const hash_state *state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_avx2/wots.c b/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_avx2/wots.c deleted file mode 100644 index 463ce74b93..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_avx2/wots.c +++ /dev/null @@ -1,240 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "hash_state.h" -#include "hashx8.h" -#include "params.h" -#include "thash.h" -#include "thashx8.h" -#include "utils.h" -#include "wots.h" - -// TODO clarify address expectations, and make them more uniform. -// TODO i.e. do we expect types to be set already? -// TODO and do we expect modifications or copies? - -/** - * Computes the starting value for a chain, i.e. the secret key. - * Expects the address to be complete up to the chain address. - */ -static void wots_gen_sk(unsigned char *sk, const unsigned char *sk_seed, - uint32_t wots_addr[8], const hash_state *state_seeded) { - /* Make sure that the hash address is actually zeroed. */ - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_set_hash_addr(wots_addr, 0); - - /* Generate sk element. */ - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_prf_addr(sk, sk_seed, wots_addr, state_seeded); -} - -/** - * 8-way parallel version of wots_gen_sk; expects 8x as much space in sk - */ -static void wots_gen_skx8(unsigned char *skx8, const unsigned char *sk_seed, - uint32_t wots_addrx8[8 * 8]) { - unsigned int j; - - /* Make sure that the hash address is actually zeroed. */ - for (j = 0; j < 8; j++) { - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_set_hash_addr(wots_addrx8 + j * 8, 0); - } - - /* Generate sk element. */ - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_prf_addrx8(skx8 + 0 * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N, - skx8 + 1 * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N, - skx8 + 2 * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N, - skx8 + 3 * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N, - skx8 + 4 * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N, - skx8 + 5 * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N, - skx8 + 6 * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N, - skx8 + 7 * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N, - sk_seed, wots_addrx8); -} - -/** - * Computes the chaining function. - * out and in have to be n-byte arrays. - * - * Interprets in as start-th value of the chain. - * addr has to contain the address of the chain. - */ -static void gen_chain(unsigned char *out, const unsigned char *in, - unsigned int start, unsigned int steps, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *state_seeded) { - uint32_t i; - - /* Initialize out with the value at position 'start'. */ - memcpy(out, in, PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N); - - /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_WOTS_W; i++) { - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_set_hash_addr(addr, i); - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_thash_1(out, out, pub_seed, addr, state_seeded); - } -} - -/** - * 8-way parallel version of gen_chain; expects 8x as much space in out, and - * 8x as much space in inx8. Assumes start and step identical across chains. - */ -static void gen_chainx8(unsigned char *outx8, const unsigned char *inx8, - unsigned int start, unsigned int steps, - const unsigned char *pub_seed, uint32_t addrx8[8 * 8], - const hash_state *state_seeded) { - uint32_t i; - unsigned int j; - - /* Initialize outx8 with the value at position 'start'. */ - memcpy(outx8, inx8, 8 * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N); - - /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_WOTS_W; i++) { - for (j = 0; j < 8; j++) { - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_set_hash_addr(addrx8 + j * 8, i); - } - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_thashx8_1(outx8 + 0 * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N, - outx8 + 1 * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N, - outx8 + 2 * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N, - outx8 + 3 * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N, - outx8 + 4 * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N, - outx8 + 5 * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N, - outx8 + 6 * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N, - outx8 + 7 * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N, - outx8 + 0 * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N, - outx8 + 1 * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N, - outx8 + 2 * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N, - outx8 + 3 * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N, - outx8 + 4 * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N, - outx8 + 5 * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N, - outx8 + 6 * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N, - outx8 + 7 * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N, - pub_seed, addrx8, state_seeded); - } -} - -/** - * base_w algorithm as described in draft. - * Interprets an array of bytes as integers in base w. - * This only works when log_w is a divisor of 8. - */ -static void base_w(unsigned int *output, const int out_len, const unsigned char *input) { - int in = 0; - int out = 0; - unsigned char total = 0; - int bits = 0; - int consumed; - - for (consumed = 0; consumed < out_len; consumed++) { - if (bits == 0) { - total = input[in]; - in++; - bits += 8; - } - bits -= PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_WOTS_LOGW; - output[out] = (unsigned int)(total >> bits) & (PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_WOTS_W - 1); - out++; - } -} - -/* Computes the WOTS+ checksum over a message (in base_w). */ -static void wots_checksum(unsigned int *csum_base_w, const unsigned int *msg_base_w) { - unsigned int csum = 0; - unsigned char csum_bytes[(PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_WOTS_LEN2 * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_WOTS_LOGW + 7) / 8]; - unsigned int i; - - /* Compute checksum. */ - for (i = 0; i < PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_WOTS_LEN1; i++) { - csum += PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_WOTS_W - 1 - msg_base_w[i]; - } - - /* Convert checksum to base_w. */ - /* Make sure expected empty zero bits are the least significant bits. */ - csum = csum << (8 - ((PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_WOTS_LEN2 * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_WOTS_LOGW) % 8)); - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); - base_w(csum_base_w, PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_WOTS_LEN2, csum_bytes); -} - -/* Takes a message and derives the matching chain lengths. */ -static void chain_lengths(unsigned int *lengths, const unsigned char *msg) { - base_w(lengths, PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_WOTS_LEN1, msg); - wots_checksum(lengths + PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_WOTS_LEN1, lengths); -} - -/** - * WOTS key generation. Takes a 32 byte sk_seed, expands it to WOTS private key - * elements and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_wots_gen_pk(unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *state_seeded) { - uint32_t i; - unsigned int j; - - uint32_t addrx8[8 * 8]; - unsigned char pkbuf[8 * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N]; - - for (j = 0; j < 8; j++) { - memcpy(addrx8 + j * 8, addr, sizeof(uint32_t) * 8); - } - - /* The last iteration typically does not have complete set of 4 chains, - but because we use pkbuf, this is not an issue -- we still do as many - in parallel as possible. */ - for (i = 0; i < ((PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_WOTS_LEN + 7) & ~0x7); i += 8) { - for (j = 0; j < 8; j++) { - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_set_chain_addr(addrx8 + j * 8, i + j); - } - wots_gen_skx8(pkbuf, sk_seed, addrx8); - gen_chainx8(pkbuf, pkbuf, 0, PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_WOTS_W - 1, pub_seed, addrx8, state_seeded); - for (j = 0; j < 8; j++) { - if (i + j < PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_WOTS_LEN) { - memcpy(pk + (i + j)*PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N, pkbuf + j * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N, PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N); - } - } - } -} - -/** - * Takes a n-byte message and the 32-byte sk_see to compute a signature 'sig'. - */ -void PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_wots_sign(unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_WOTS_LEN; i++) { - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_set_chain_addr(addr, i); - wots_gen_sk(sig + i * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N, sk_seed, addr, state_seeded); - gen_chain(sig + i * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N, sig + i * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N, 0, lengths[i], pub_seed, addr, state_seeded); - } -} - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_WOTS_LEN; i++) { - PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_set_chain_addr(addr, i); - gen_chain(pk + i * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N, sig + i * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N, - lengths[i], PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_WOTS_W - 1 - lengths[i], pub_seed, addr, state_seeded); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_avx2/wots.h b/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_avx2/wots.h deleted file mode 100644 index 1adea3c6f2..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_avx2/wots.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_WOTS_H -#define PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_WOTS_H - -#include "hash_state.h" -#include "params.h" -#include - -/** - * WOTS key generation. Takes a 32 byte seed for the private key, expands it to - * a full WOTS private key and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_wots_gen_pk( - unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -/** - * Takes a n-byte message and the 32-byte seed for the private key to compute a - * signature that is placed at 'sig'. - */ -void PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_wots_sign( - unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *hash_state_seeded); - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_wots_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_clean/LICENSE b/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_clean/LICENSE deleted file mode 100644 index 670154e353..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_clean/LICENSE +++ /dev/null @@ -1,116 +0,0 @@ -CC0 1.0 Universal - -Statement of Purpose - -The laws of most jurisdictions throughout the world automatically confer -exclusive Copyright and Related Rights (defined below) upon the creator and -subsequent owner(s) (each and all, an "owner") of an original work of -authorship and/or a database (each, a "Work"). - -Certain owners wish to permanently relinquish those rights to a Work for the -purpose of contributing to a commons of creative, cultural and scientific -works ("Commons") that the public can reliably and without fear of later -claims of infringement build upon, modify, incorporate in other works, reuse -and redistribute as freely as possible in any form whatsoever and for any -purposes, including without limitation commercial purposes. These owners may -contribute to the Commons to promote the ideal of a free culture and the -further production of creative, cultural and scientific works, or to gain -reputation or greater distribution for their Work in part through the use and -efforts of others. - -For these and/or other purposes and motivations, and without any expectation -of additional consideration or compensation, the person associating CC0 with a -Work (the "Affirmer"), to the extent that he or she is an owner of Copyright -and Related Rights in the Work, voluntarily elects to apply CC0 to the Work -and publicly distribute the Work under its terms, with knowledge of his or her -Copyright and Related Rights in the Work and the meaning and intended legal -effect of CC0 on those rights. - -1. Copyright and Related Rights. A Work made available under CC0 may be -protected by copyright and related or neighboring rights ("Copyright and -Related Rights"). Copyright and Related Rights include, but are not limited -to, the following: - - i. the right to reproduce, adapt, distribute, perform, display, communicate, - and translate a Work; - - ii. moral rights retained by the original author(s) and/or performer(s); - - iii. publicity and privacy rights pertaining to a person's image or likeness - depicted in a Work; - - iv. rights protecting against unfair competition in regards to a Work, - subject to the limitations in paragraph 4(a), below; - - v. rights protecting the extraction, dissemination, use and reuse of data in - a Work; - - vi. database rights (such as those arising under Directive 96/9/EC of the - European Parliament and of the Council of 11 March 1996 on the legal - protection of databases, and under any national implementation thereof, - including any amended or successor version of such directive); and - - vii. other similar, equivalent or corresponding rights throughout the world - based on applicable law or treaty, and any national implementations thereof. - -2. Waiver. To the greatest extent permitted by, but not in contravention of, -applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and -unconditionally waives, abandons, and surrenders all of Affirmer's Copyright -and Related Rights and associated claims and causes of action, whether now -known or unknown (including existing as well as future claims and causes of -action), in the Work (i) in all territories worldwide, (ii) for the maximum -duration provided by applicable law or treaty (including future time -extensions), (iii) in any current or future medium and for any number of -copies, and (iv) for any purpose whatsoever, including without limitation -commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes -the Waiver for the benefit of each member of the public at large and to the -detriment of Affirmer's heirs and successors, fully intending that such Waiver -shall not be subject to revocation, rescission, cancellation, termination, or -any other legal or equitable action to disrupt the quiet enjoyment of the Work -by the public as contemplated by Affirmer's express Statement of Purpose. - -3. Public License Fallback. Should any part of the Waiver for any reason be -judged legally invalid or ineffective under applicable law, then the Waiver -shall be preserved to the maximum extent permitted taking into account -Affirmer's express Statement of Purpose. In addition, to the extent the Waiver -is so judged Affirmer hereby grants to each affected person a royalty-free, -non transferable, non sublicensable, non exclusive, irrevocable and -unconditional license to exercise Affirmer's Copyright and Related Rights in -the Work (i) in all territories worldwide, (ii) for the maximum duration -provided by applicable law or treaty (including future time extensions), (iii) -in any current or future medium and for any number of copies, and (iv) for any -purpose whatsoever, including without limitation commercial, advertising or -promotional purposes (the "License"). The License shall be deemed effective as -of the date CC0 was applied by Affirmer to the Work. Should any part of the -License for any reason be judged legally invalid or ineffective under -applicable law, such partial invalidity or ineffectiveness shall not -invalidate the remainder of the License, and in such case Affirmer hereby -affirms that he or she will not (i) exercise any of his or her remaining -Copyright and Related Rights in the Work or (ii) assert any associated claims -and causes of action with respect to the Work, in either case contrary to -Affirmer's express Statement of Purpose. - -4. Limitations and Disclaimers. - - a. No trademark or patent rights held by Affirmer are waived, abandoned, - surrendered, licensed or otherwise affected by this document. - - b. Affirmer offers the Work as-is and makes no representations or warranties - of any kind concerning the Work, express, implied, statutory or otherwise, - including without limitation warranties of title, merchantability, fitness - for a particular purpose, non infringement, or the absence of latent or - other defects, accuracy, or the present or absence of errors, whether or not - discoverable, all to the greatest extent permissible under applicable law. - - c. Affirmer disclaims responsibility for clearing rights of other persons - that may apply to the Work or any use thereof, including without limitation - any person's Copyright and Related Rights in the Work. Further, Affirmer - disclaims responsibility for obtaining any necessary consents, permissions - or other rights required for any use of the Work. - - d. Affirmer understands and acknowledges that Creative Commons is not a - party to this document and has no duty or obligation with respect to this - CC0 or use of the Work. - -For more information, please see - diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_clean/address.c b/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_clean/address.c deleted file mode 100644 index d268f11f0c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_clean/address.c +++ /dev/null @@ -1,78 +0,0 @@ -#include - -#include "address.h" -#include "params.h" -#include "utils.h" - -void PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]) { - int i; - - for (i = 0; i < 8; i++) { - PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_ull_to_bytes( - bytes + i * 4, 4, addr[i]); - } -} - -void PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_set_layer_addr( - uint32_t addr[8], uint32_t layer) { - addr[0] = layer; -} - -void PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_set_tree_addr( - uint32_t addr[8], uint64_t tree) { - addr[1] = 0; - addr[2] = (uint32_t) (tree >> 32); - addr[3] = (uint32_t) tree; -} - -void PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_set_type( - uint32_t addr[8], uint32_t type) { - addr[4] = type; -} - -void PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; -} - -/* These functions are used for OTS addresses. */ - -void PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_set_keypair_addr( - uint32_t addr[8], uint32_t keypair) { - addr[5] = keypair; -} - -void PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; - out[5] = in[5]; -} - -void PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_set_chain_addr( - uint32_t addr[8], uint32_t chain) { - addr[6] = chain; -} - -void PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_set_hash_addr( - uint32_t addr[8], uint32_t hash) { - addr[7] = hash; -} - -/* These functions are used for all hash tree addresses (including FORS). */ - -void PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_set_tree_height( - uint32_t addr[8], uint32_t tree_height) { - addr[6] = tree_height; -} - -void PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_set_tree_index( - uint32_t addr[8], uint32_t tree_index) { - addr[7] = tree_index; -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_clean/address.h b/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_clean/address.h deleted file mode 100644 index c4489f99f9..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_clean/address.h +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_ADDRESS_H -#define PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_ADDRESS_H - -#include - -#define PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_ADDR_TYPE_WOTS 0 -#define PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_ADDR_TYPE_WOTSPK 1 -#define PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_ADDR_TYPE_HASHTREE 2 -#define PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_ADDR_TYPE_FORSTREE 3 -#define PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_ADDR_TYPE_FORSPK 4 - -void PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]); - -void PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_set_layer_addr( - uint32_t addr[8], uint32_t layer); - -void PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_set_tree_addr( - uint32_t addr[8], uint64_t tree); - -void PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_set_type( - uint32_t addr[8], uint32_t type); - -/* Copies the layer and tree part of one address into the other */ -void PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for WOTS and FORS addresses. */ - -void PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_set_keypair_addr( - uint32_t addr[8], uint32_t keypair); - -void PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_set_chain_addr( - uint32_t addr[8], uint32_t chain); - -void PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_set_hash_addr( - uint32_t addr[8], uint32_t hash); - -void PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for all hash tree addresses (including FORS). */ - -void PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_set_tree_height( - uint32_t addr[8], uint32_t tree_height); - -void PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_set_tree_index( - uint32_t addr[8], uint32_t tree_index); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_clean/api.h b/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_clean/api.h deleted file mode 100644 index 03c7f73f08..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_clean/api.h +++ /dev/null @@ -1,81 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_API_H -#define PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_API_H - -#include -#include - - - -#define PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_CRYPTO_ALGNAME "SPHINCS+" - -#define PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_CRYPTO_SECRETKEYBYTES 96 -#define PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_CRYPTO_PUBLICKEYBYTES 48 -#define PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_CRYPTO_BYTES 35664 -#define PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_CRYPTO_SEEDBYTES 72 - - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_clean/fors.c b/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_clean/fors.c deleted file mode 100644 index 78d4a7ecfd..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_clean/fors.c +++ /dev/null @@ -1,161 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "fors.h" -#include "hash.h" -#include "hash_state.h" -#include "thash.h" -#include "utils.h" - -static void fors_gen_sk(unsigned char *sk, const unsigned char *sk_seed, - uint32_t fors_leaf_addr[8], const hash_state *hash_state_seeded) { - PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_prf_addr( - sk, sk_seed, fors_leaf_addr, hash_state_seeded); -} - -static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, - const unsigned char *pub_seed, - uint32_t fors_leaf_addr[8], - const hash_state *hash_state_seeded) { - PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_thash_1( - leaf, sk, pub_seed, fors_leaf_addr, hash_state_seeded); -} - -static void fors_gen_leaf(unsigned char *leaf, const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx, const uint32_t fors_tree_addr[8], - const hash_state *hash_state_seeded) { - uint32_t fors_leaf_addr[8] = {0}; - - /* Only copy the parts that must be kept in fors_leaf_addr. */ - PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_copy_keypair_addr( - fors_leaf_addr, fors_tree_addr); - PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_set_type( - fors_leaf_addr, PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_set_tree_index( - fors_leaf_addr, addr_idx); - - fors_gen_sk(leaf, sk_seed, fors_leaf_addr, hash_state_seeded); - fors_sk_to_leaf(leaf, leaf, pub_seed, fors_leaf_addr, hash_state_seeded); -} - -/** - * Interprets m as PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_FORS_HEIGHT-bit unsigned integers. - * Assumes m contains at least PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_FORS_TREES bits. - * Assumes indices has space for PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_FORS_TREES integers. - */ -static void message_to_indices(uint32_t *indices, const unsigned char *m) { - unsigned int i, j; - unsigned int offset = 0; - - for (i = 0; i < PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_FORS_TREES; i++) { - indices[i] = 0; - for (j = 0; j < PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_FORS_HEIGHT; j++) { - indices[i] ^= (((uint32_t)m[offset >> 3] >> (offset & 0x7)) & 0x1) << j; - offset++; - } - } -} - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_fors_sign( - unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *hash_state_seeded) { - uint32_t indices[PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_FORS_TREES]; - unsigned char roots[PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_FORS_TREES * PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_N]; - uint32_t fors_tree_addr[8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_copy_keypair_addr( - fors_tree_addr, fors_addr); - PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_copy_keypair_addr( - fors_pk_addr, fors_addr); - - PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_set_type( - fors_tree_addr, PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_set_type( - fors_pk_addr, PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_FORS_TREES; i++) { - idx_offset = i * (1 << PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_FORS_HEIGHT); - - PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_set_tree_height( - fors_tree_addr, 0); - PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_set_tree_index( - fors_tree_addr, indices[i] + idx_offset); - - /* Include the secret key part that produces the selected leaf node. */ - fors_gen_sk(sig, sk_seed, fors_tree_addr, hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_N; - - /* Compute the authentication path for this leaf node. */ - PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_treehash_FORS_HEIGHT( - roots + i * PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_N, sig, sk_seed, pub_seed, - indices[i], idx_offset, fors_gen_leaf, fors_tree_addr, - hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_N * PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_thash_FORS_TREES( - pk, roots, pub_seed, fors_pk_addr, hash_state_seeded); -} - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_fors_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, const uint32_t fors_addr[8], - const hash_state *hash_state_seeded) { - uint32_t indices[PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_FORS_TREES]; - unsigned char roots[PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_FORS_TREES * PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_N]; - unsigned char leaf[PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_N]; - uint32_t fors_tree_addr[8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_copy_keypair_addr(fors_tree_addr, fors_addr); - PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_copy_keypair_addr(fors_pk_addr, fors_addr); - - PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_set_type(fors_tree_addr, PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_set_type(fors_pk_addr, PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_FORS_TREES; i++) { - idx_offset = i * (1 << PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_FORS_HEIGHT); - - PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_set_tree_height(fors_tree_addr, 0); - PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Derive the leaf from the included secret key part. */ - fors_sk_to_leaf(leaf, sig, pub_seed, fors_tree_addr, hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_N; - - /* Derive the corresponding root node of this tree. */ - PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_compute_root(roots + i * PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_N, leaf, indices[i], idx_offset, sig, - PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_FORS_HEIGHT, pub_seed, fors_tree_addr, hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_N * PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_thash_FORS_TREES(pk, roots, pub_seed, fors_pk_addr, hash_state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_clean/fors.h b/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_clean/fors.h deleted file mode 100644 index 17ae61350f..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_clean/fors.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_FORS_H -#define PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_FORS_H - -#include - -#include "hash_state.h" -#include "params.h" - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_fors_sign( - unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *hash_state_seeded); - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_fors_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, const uint32_t fors_addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_clean/hash.h b/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_clean/hash.h deleted file mode 100644 index 1f14cad7ca..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_clean/hash.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_HASH_H -#define PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_HASH_H - -#include "hash_state.h" - -#include -#include - -void PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_initialize_hash_function( - hash_state *hash_state_seeded, - const unsigned char *pub_seed, const unsigned char *sk_seed); - -void PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_destroy_hash_function(hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_clean/hash_sha256.c b/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_clean/hash_sha256.c deleted file mode 100644 index 5a5e5c3a90..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_clean/hash_sha256.c +++ /dev/null @@ -1,162 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "utils.h" - -#include "sha2.h" -#include "sha256.h" - -/* For SHA256, there is no immediate reason to initialize at the start, - so this function is an empty operation. */ -void PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_initialize_hash_function( - hash_state *hash_state_seeded, - const unsigned char *pub_seed, const unsigned char *sk_seed) { - PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_seed_state(hash_state_seeded, pub_seed); - (void)sk_seed; /* Suppress an 'unused parameter' warning. */ -} - -/* Clean up hash state */ -void PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_destroy_hash_function(hash_state *hash_state_seeded) { - sha256_inc_ctx_release(hash_state_seeded); -} - -/* - * Computes PRF(key, addr), given a secret key of PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_N bytes and an address - */ -void PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded) { - unsigned char buf[PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_N + PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_SHA256_ADDR_BYTES]; - unsigned char outbuf[PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_SHA256_OUTPUT_BYTES]; - - memcpy(buf, key, PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_N); - PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_compress_address(buf + PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_N, addr); - - sha256(outbuf, buf, PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_N + PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_SHA256_ADDR_BYTES); - memcpy(out, outbuf, PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_N); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} - -/** - * Computes the message-dependent randomness R, using a secret seed as a key - * for HMAC, and an optional randomization value prefixed to the message. - * This requires m to have at least PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_SHA256_BLOCK_BYTES + PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_N space - * available in front of the pointer, i.e. before the message to use for the - * prefix. This is necessary to prevent having to move the message around (and - * allocate memory for it). - */ -void PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, const hash_state *hash_state_seeded) { - unsigned char buf[PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_SHA256_BLOCK_BYTES + PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_SHA256_OUTPUT_BYTES]; - sha256ctx state; - int i; - - /* This implements HMAC-SHA256 */ - for (i = 0; i < PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_N; i++) { - buf[i] = 0x36 ^ sk_prf[i]; - } - memset(buf + PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_N, 0x36, PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_N); - - sha256_inc_init(&state); - sha256_inc_blocks(&state, buf, 1); - - memcpy(buf, optrand, PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_N); - - /* If optrand + message cannot fill up an entire block */ - if (PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_N + mlen < PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_SHA256_BLOCK_BYTES) { - memcpy(buf + PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_N, m, mlen); - sha256_inc_finalize(buf + PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_SHA256_BLOCK_BYTES, &state, - buf, mlen + PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_N); - } - /* Otherwise first fill a block, so that finalize only uses the message */ - else { - memcpy(buf + PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_N, m, PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_N); - sha256_inc_blocks(&state, buf, 1); - - m += PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_N; - mlen -= PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_N; - sha256_inc_finalize(buf + PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_SHA256_BLOCK_BYTES, &state, m, mlen); - } - - for (i = 0; i < PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_N; i++) { - buf[i] = 0x5c ^ sk_prf[i]; - } - memset(buf + PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_N, 0x5c, PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_N); - - sha256(buf, buf, PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_SHA256_BLOCK_BYTES + PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_SHA256_OUTPUT_BYTES); - memcpy(R, buf, PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_N); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} - -/** - * Computes the message hash using R, the public key, and the message. - * Outputs the message digest and the index of the leaf. The index is split in - * the tree index and the leaf index, for convenient copying to an address. - */ -void PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded) { -#define PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_TREE_BITS (PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_TREE_HEIGHT * (PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_D - 1)) -#define PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_TREE_BYTES ((PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_TREE_BITS + 7) / 8) -#define PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_LEAF_BITS PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_TREE_HEIGHT -#define PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_LEAF_BYTES ((PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_LEAF_BITS + 7) / 8) -#define PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_DGST_BYTES (PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_FORS_MSG_BYTES + PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_TREE_BYTES + PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_LEAF_BYTES) - - unsigned char seed[PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_SHA256_OUTPUT_BYTES + 4]; - - /* Round to nearest multiple of PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_SHA256_BLOCK_BYTES */ -#define PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_INBLOCKS (((PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_N + PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_PK_BYTES + PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_SHA256_BLOCK_BYTES - 1) & \ - -PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_SHA256_BLOCK_BYTES) / PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_SHA256_BLOCK_BYTES) - unsigned char inbuf[PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_INBLOCKS * PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_SHA256_BLOCK_BYTES]; - - unsigned char buf[PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_DGST_BYTES]; - unsigned char *bufp = buf; - sha256ctx state; - - sha256_inc_init(&state); - - memcpy(inbuf, R, PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_N); - memcpy(inbuf + PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_N, pk, PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_PK_BYTES); - - /* If R + pk + message cannot fill up an entire block */ - if (PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_N + PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_PK_BYTES + mlen < PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_INBLOCKS * PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_SHA256_BLOCK_BYTES) { - memcpy(inbuf + PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_N + PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_PK_BYTES, m, mlen); - sha256_inc_finalize(seed, &state, inbuf, PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_N + PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_PK_BYTES + mlen); - } - /* Otherwise first fill a block, so that finalize only uses the message */ - else { - memcpy(inbuf + PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_N + PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_PK_BYTES, m, - PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_INBLOCKS * PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_N - PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_PK_BYTES); - sha256_inc_blocks(&state, inbuf, PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_INBLOCKS); - - m += PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_INBLOCKS * PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_N - PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_PK_BYTES; - mlen -= PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_INBLOCKS * PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_N - PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_PK_BYTES; - sha256_inc_finalize(seed, &state, m, mlen); - } - - /* By doing this in two steps, we prevent hashing the message twice; - otherwise each iteration in MGF1 would hash the message again. */ - PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_mgf1(bufp, PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_DGST_BYTES, seed, PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_SHA256_OUTPUT_BYTES); - - memcpy(digest, bufp, PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_FORS_MSG_BYTES); - bufp += PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_FORS_MSG_BYTES; - - *tree = PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_bytes_to_ull(bufp, PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_TREE_BYTES); - *tree &= (~(uint64_t)0) >> (64 - PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_TREE_BITS); - bufp += PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_TREE_BYTES; - - *leaf_idx = (uint32_t)PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_bytes_to_ull( - bufp, PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_LEAF_BYTES); - *leaf_idx &= (~(uint32_t)0) >> (32 - PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_LEAF_BITS); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_clean/hash_state.h b/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_clean/hash_state.h deleted file mode 100644 index 19fc335e27..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_clean/hash_state.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef SPX_HASH_STATE_H -#define SPX_HASH_STATE_H - -/** - * Defines the type of the hash function state. - * - * Don't be fooled into thinking this instance of SPHINCS+ isn't stateless! - * - * From Section 7.2.2 from the SPHINCS+ round-2 specification: - * - * Each of the instances of the tweakable hash function take PK.seed as its - * first input, which is constant for a given key pair – and, thus, across - * a single signature. This leads to a lot of redundant computation. To remedy - * this, we pad PK.seed to the length of a full 64-byte SHA-256 input block. - * Because of the Merkle-Damgård construction that underlies SHA-256, this - * allows for reuse of the intermediate SHA-256 state after the initial call to - * the compression function which improves performance. - * - * We pass this hash state around in functions, because otherwise we need to - * have a global variable. - */ - -#include "sha2.h" -#define hash_state sha256ctx - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_clean/params.h b/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_clean/params.h deleted file mode 100644 index 86ea975310..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_clean/params.h +++ /dev/null @@ -1,53 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_PARAMS_H -#define PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_PARAMS_H - -/* Hash output length in bytes. */ -#define PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_N 24 -/* Height of the hypertree. */ -#define PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_FULL_HEIGHT 66 -/* Number of subtree layer. */ -#define PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_D 22 -/* FORS tree dimensions. */ -#define PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_FORS_HEIGHT 8 -#define PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_FORS_TREES 33 -/* Winternitz parameter, */ -#define PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_WOTS_W 16 - -/* The hash function is defined by linking a different hash.c file, as opposed - to setting a #define constant. */ - -/* For clarity */ -#define PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_ADDR_BYTES 32 - -/* WOTS parameters. */ -#define PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_WOTS_LOGW 4 - -#define PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_WOTS_LEN1 (8 * PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_N / PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_WOTS_LOGW) - -/* PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#define PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_WOTS_LEN2 3 - -#define PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_WOTS_LEN (PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_WOTS_LEN1 + PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_WOTS_LEN2) -#define PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_WOTS_BYTES (PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_WOTS_LEN * PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_N) -#define PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_WOTS_PK_BYTES PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_WOTS_BYTES - -/* Subtree size. */ -#define PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_TREE_HEIGHT (PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_FULL_HEIGHT / PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_D) - -/* FORS parameters. */ -#define PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_FORS_MSG_BYTES ((PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_FORS_TREES + 7) / 8) -#define PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_FORS_BYTES ((PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_FORS_HEIGHT + 1) * PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_FORS_TREES * PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_N) -#define PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_FORS_PK_BYTES PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_N - -/* Resulting SPX sizes. */ -#define PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_BYTES (PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_N + PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_FORS_BYTES + PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_D * PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_WOTS_BYTES +\ - PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_FULL_HEIGHT * PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_N) -#define PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_PK_BYTES (2 * PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_N) -#define PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_SK_BYTES (2 * PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_N + PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_PK_BYTES) - -/* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ -#define PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_OPTRAND_BYTES 32 - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_clean/sha256.c b/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_clean/sha256.c deleted file mode 100644 index 0c36b70510..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_clean/sha256.c +++ /dev/null @@ -1,71 +0,0 @@ -/* Based on the public domain implementation in - * crypto_hash/sha512/ref/ from http://bench.cr.yp.to/supercop.html - * by D. J. Bernstein */ - -#include -#include -#include - -#include "sha2.h" -#include "sha256.h" -#include "utils.h" - -/* - * Compresses an address to a 22-byte sequence. - * This reduces the number of required SHA256 compression calls, as the last - * block of input is padded with at least 65 bits. - */ -void PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_compress_address(unsigned char *out, const uint32_t addr[8]) { - PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_ull_to_bytes(out, 1, addr[0]); /* drop 3 bytes of the layer field */ - PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_ull_to_bytes(out + 1, 4, addr[2]); /* drop the highest tree address word */ - PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_ull_to_bytes(out + 5, 4, addr[3]); - PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_ull_to_bytes(out + 9, 1, addr[4]); /* drop 3 bytes of the type field */ - PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_ull_to_bytes(out + 10, 4, addr[5]); - PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_ull_to_bytes(out + 14, 4, addr[6]); - PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_ull_to_bytes(out + 18, 4, addr[7]); -} - -/** - * Requires 'input_plus_four_bytes' to have 'inlen' + 4 bytes, so that the last - * four bytes can be used for the counter. Typically 'input' is merely a seed. - * Outputs outlen number of bytes - */ -void PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_mgf1( - unsigned char *out, unsigned long outlen, - unsigned char *input_plus_four_bytes, unsigned long inlen) { - unsigned char outbuf[PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_SHA256_OUTPUT_BYTES]; - unsigned long i; - - /* While we can fit in at least another full block of SHA256 output.. */ - for (i = 0; (i + 1)*PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_SHA256_OUTPUT_BYTES <= outlen; i++) { - PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_ull_to_bytes(input_plus_four_bytes + inlen, 4, i); - sha256(out, input_plus_four_bytes, inlen + 4); - out += PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_SHA256_OUTPUT_BYTES; - } - /* Until we cannot anymore, and we fill the remainder. */ - if (outlen > i * PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_SHA256_OUTPUT_BYTES) { - PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_ull_to_bytes(input_plus_four_bytes + inlen, 4, i); - sha256(outbuf, input_plus_four_bytes, inlen + 4); - memcpy(out, outbuf, outlen - i * PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_SHA256_OUTPUT_BYTES); - } -} - - -/** - * Absorb the constant pub_seed using one round of the compression function - * This initializes hash_state_seeded, which can then be reused in thash - **/ -void PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_seed_state(sha256ctx *hash_state_seeded, const unsigned char *pub_seed) { - uint8_t block[PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_SHA256_BLOCK_BYTES]; - size_t i; - - for (i = 0; i < PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_N; ++i) { - block[i] = pub_seed[i]; - } - for (i = PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_N; i < PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_SHA256_BLOCK_BYTES; ++i) { - block[i] = 0; - } - - sha256_inc_init(hash_state_seeded); - sha256_inc_blocks(hash_state_seeded, block, 1); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_clean/sha256.h b/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_clean/sha256.h deleted file mode 100644 index a1166df6a2..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_clean/sha256.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_SHA256_H -#define PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_SHA256_H - -#define PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_SHA256_BLOCK_BYTES 64 -#define PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_SHA256_OUTPUT_BYTES 32 /* This does not necessarily equal PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_N */ -#define PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_SHA256_ADDR_BYTES 22 - -#include -#include - -#include "sha2.h" - -void PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_compress_address(unsigned char *out, const uint32_t addr[8]); - -void PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_mgf1( - unsigned char *out, unsigned long outlen, - unsigned char *input_plus_four_bytes, unsigned long inlen); - -void PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_seed_state(sha256ctx *hash_state_seeded, const unsigned char *pub_seed); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_clean/sign.c b/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_clean/sign.c deleted file mode 100644 index 00ab08f06d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_clean/sign.c +++ /dev/null @@ -1,356 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "api.h" -#include "fors.h" -#include "hash.h" -#include "hash_state.h" -#include "params.h" -#include "randombytes.h" -#include "thash.h" -#include "utils.h" -#include "wots.h" - -/** - * Computes the leaf at a given address. First generates the WOTS key pair, - * then computes leaf by hashing horizontally. - */ -static void wots_gen_leaf(unsigned char *leaf, const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx, const uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - unsigned char pk[PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_WOTS_BYTES]; - uint32_t wots_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_set_type( - wots_addr, PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_set_type( - wots_pk_addr, PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_ADDR_TYPE_WOTSPK); - - PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_set_keypair_addr( - wots_addr, addr_idx); - PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_wots_gen_pk( - pk, sk_seed, pub_seed, wots_addr, hash_state_seeded); - - PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_copy_keypair_addr( - wots_pk_addr, wots_addr); - PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_thash_WOTS_LEN( - leaf, pk, pub_seed, wots_pk_addr, hash_state_seeded); -} - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_crypto_sign_secretkeybytes(void) { - return PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_CRYPTO_SECRETKEYBYTES; -} - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_crypto_sign_publickeybytes(void) { - return PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_CRYPTO_PUBLICKEYBYTES; -} - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_crypto_sign_bytes(void) { - return PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_CRYPTO_BYTES; -} - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_crypto_sign_seedbytes(void) { - return PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_CRYPTO_SEEDBYTES; -} - -/* - * Generates an SPX key pair given a seed of length - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed) { - /* We do not need the auth path in key generation, but it simplifies the - code to have just one treehash routine that computes both root and path - in one function. */ - unsigned char auth_path[PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_TREE_HEIGHT * PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_N]; - uint32_t top_tree_addr[8] = {0}; - hash_state hash_state_seeded; - - PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_set_layer_addr( - top_tree_addr, PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_D - 1); - PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_set_type( - top_tree_addr, PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_ADDR_TYPE_HASHTREE); - - /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ - memcpy(sk, seed, PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_CRYPTO_SEEDBYTES); - - memcpy(pk, sk + 2 * PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_N, PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_initialize_hash_function(&hash_state_seeded, pk, sk); - - /* Compute root node of the top-most subtree. */ - PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_treehash_TREE_HEIGHT( - sk + 3 * PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_N, auth_path, sk, sk + 2 * PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_N, 0, 0, - wots_gen_leaf, top_tree_addr, &hash_state_seeded); - - memcpy(pk + PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_N, sk + 3 * PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_N, PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_N); - - PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_destroy_hash_function(&hash_state_seeded); - return 0; -} - -/* - * Generates an SPX key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk) { - unsigned char seed[PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_CRYPTO_SEEDBYTES]; - randombytes(seed, PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_CRYPTO_SEEDBYTES); - PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_crypto_sign_seed_keypair( - pk, sk, seed); - - return 0; -} - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - const unsigned char *sk_seed = sk; - const unsigned char *sk_prf = sk + PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_N; - const unsigned char *pk = sk + 2 * PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_N; - const unsigned char *pub_seed = pk; - - unsigned char optrand[PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_N]; - unsigned char mhash[PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_FORS_MSG_BYTES]; - unsigned char root[PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_N]; - uint32_t i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - - hash_state hash_state_seeded; - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_initialize_hash_function( - &hash_state_seeded, - pub_seed, sk_seed); - - PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_set_type( - wots_addr, PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_set_type( - tree_addr, PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_ADDR_TYPE_HASHTREE); - - /* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ - randombytes(optrand, PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_N); - /* Compute the digest randomization value. */ - PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_gen_message_random( - sig, sk_prf, optrand, m, mlen, &hash_state_seeded); - - /* Derive the message digest and leaf index from R, PK and M. */ - PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_N; - - PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); - - /* Sign the message hash using FORS. */ - PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_fors_sign( - sig, root, mhash, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_FORS_BYTES; - - for (i = 0; i < PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_D; i++) { - PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_set_tree_addr(tree_addr, tree); - - PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); - - /* Compute a WOTS signature. */ - PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_wots_sign( - sig, root, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_WOTS_BYTES; - - /* Compute the authentication path for the used WOTS leaf. */ - PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_treehash_TREE_HEIGHT( - root, sig, sk_seed, pub_seed, idx_leaf, 0, - wots_gen_leaf, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_TREE_HEIGHT * PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_TREE_HEIGHT; - } - - *siglen = PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_BYTES; - - PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_destroy_hash_function(&hash_state_seeded); - return 0; -} - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk) { - const unsigned char *pub_seed = pk; - const unsigned char *pub_root = pk + PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_N; - unsigned char mhash[PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_FORS_MSG_BYTES]; - unsigned char wots_pk[PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_WOTS_BYTES]; - unsigned char root[PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_N]; - unsigned char leaf[PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_N]; - unsigned int i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - hash_state hash_state_seeded; - - if (siglen != PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_BYTES) { - return -1; - } - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_initialize_hash_function( - &hash_state_seeded, - pub_seed, NULL); - - PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_set_type( - wots_addr, PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_set_type( - tree_addr, PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_ADDR_TYPE_HASHTREE); - PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_set_type( - wots_pk_addr, PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_ADDR_TYPE_WOTSPK); - - /* Derive the message digest and leaf index from R || PK || M. */ - /* The additional PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_N is a result of the hash domain separator. */ - PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_N; - - /* Layer correctly defaults to 0, so no need to set_layer_addr */ - PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); - - PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_fors_pk_from_sig( - root, sig, mhash, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_FORS_BYTES; - - /* For each subtree.. */ - for (i = 0; i < PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_D; i++) { - PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_set_tree_addr(tree_addr, tree); - - PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); - - PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_copy_keypair_addr( - wots_pk_addr, wots_addr); - - /* The WOTS public key is only correct if the signature was correct. */ - /* Initially, root is the FORS pk, but on subsequent iterations it is - the root of the subtree below the currently processed subtree. */ - PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_wots_pk_from_sig( - wots_pk, sig, root, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_WOTS_BYTES; - - /* Compute the leaf node using the WOTS public key. */ - PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_thash_WOTS_LEN( - leaf, wots_pk, pub_seed, wots_pk_addr, &hash_state_seeded); - - /* Compute the root node of this subtree. */ - PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_compute_root( - root, leaf, idx_leaf, 0, sig, PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_TREE_HEIGHT, - pub_seed, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_TREE_HEIGHT * PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_TREE_HEIGHT; - } - - PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_destroy_hash_function(&hash_state_seeded); - /* Check if the root node equals the root node in the public key. */ - if (memcmp(root, pub_root, PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_N) != 0) { - return -1; - } - - return 0; -} - - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - size_t siglen; - - PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_crypto_sign_signature( - sm, &siglen, m, mlen, sk); - - memmove(sm + PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_BYTES, m, mlen); - *smlen = siglen + mlen; - - return 0; -} - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk) { - /* The API caller does not necessarily know what size a signature should be - but SPHINCS+ signatures are always exactly PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_BYTES. */ - if (smlen < PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_BYTES) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - *mlen = smlen - PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_BYTES; - - if (PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_crypto_sign_verify( - sm, PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_BYTES, sm + PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_BYTES, *mlen, pk)) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - /* If verification was successful, move the message to the right place. */ - memmove(m, sm + PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_BYTES, *mlen); - - return 0; -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_clean/thash.h b/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_clean/thash.h deleted file mode 100644 index 353f7f92bc..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_clean/thash.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_THASH_H -#define PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_THASH_H - -#include "hash_state.h" - -#include - -void PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_clean/thash_sha256_simple.c b/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_clean/thash_sha256_simple.c deleted file mode 100644 index 445aab667e..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_clean/thash_sha256_simple.c +++ /dev/null @@ -1,75 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "thash.h" - -#include "sha2.h" -#include "sha256.h" - -/** - * Takes an array of inblocks concatenated arrays of PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_N bytes. - */ -static void PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_thash( - unsigned char *out, unsigned char *buf, - const unsigned char *in, unsigned int inblocks, - const unsigned char *pub_seed, uint32_t addr[8], - const sha256ctx *hash_state_seeded) { - - unsigned char outbuf[PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_SHA256_OUTPUT_BYTES]; - sha256ctx sha2_state; - - (void)pub_seed; /* Suppress an 'unused parameter' warning. */ - - /* Retrieve precomputed state containing pub_seed */ - sha256_inc_ctx_clone(&sha2_state, hash_state_seeded); - - PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_compress_address(buf, addr); - memcpy(buf + PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_SHA256_ADDR_BYTES, in, inblocks * PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_N); - - sha256_inc_finalize(outbuf, &sha2_state, buf, PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_N); - memcpy(out, outbuf, PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_N); -} - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const sha256ctx *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_SHA256_ADDR_BYTES + 1 * PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_N]; - PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_thash( - out, buf, in, 1, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const sha256ctx *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_SHA256_ADDR_BYTES + 2 * PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_N]; - PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_thash( - out, buf, in, 2, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const sha256ctx *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_SHA256_ADDR_BYTES + PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_WOTS_LEN * PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_N]; - PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_thash( - out, buf, in, PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_WOTS_LEN, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const sha256ctx *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_SHA256_ADDR_BYTES + PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_FORS_TREES * PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_N]; - PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_thash( - out, buf, in, PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_FORS_TREES, pub_seed, addr, hash_state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_clean/utils.c b/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_clean/utils.c deleted file mode 100644 index 34c1702583..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_clean/utils.c +++ /dev/null @@ -1,199 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "hash_state.h" -#include "params.h" -#include "thash.h" -#include "utils.h" - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in) { - - /* Iterate over out in decreasing order, for big-endianness. */ - for (size_t i = outlen; i > 0; i--) { - out[i - 1] = in & 0xff; - in = in >> 8; - } -} - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_bytes_to_ull( - const unsigned char *in, size_t inlen) { - unsigned long long retval = 0; - - for (size_t i = 0; i < inlen; i++) { - retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); - } - return retval; -} - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - uint32_t i; - unsigned char buffer[2 * PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_N]; - - /* If leaf_idx is odd (last bit = 1), current path element is a right child - and auth_path has to go left. Otherwise it is the other way around. */ - if (leaf_idx & 1) { - memcpy(buffer + PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_N, leaf, PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_N); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_N); - } else { - memcpy(buffer, leaf, PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_N); - memcpy(buffer + PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_N, auth_path, PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_N); - } - auth_path += PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_N; - - for (i = 0; i < tree_height - 1; i++) { - leaf_idx >>= 1; - idx_offset >>= 1; - /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_set_tree_height(addr, i + 1); - PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_set_tree_index( - addr, leaf_idx + idx_offset); - - /* Pick the right or left neighbor, depending on parity of the node. */ - if (leaf_idx & 1) { - PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_thash_2( - buffer + PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_N, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_N); - } else { - PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_thash_2( - buffer, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer + PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_N, auth_path, PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_N); - } - auth_path += PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_N; - } - - /* The last iteration is exceptional; we do not copy an auth_path node. */ - leaf_idx >>= 1; - idx_offset >>= 1; - PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_set_tree_height(addr, tree_height); - PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_set_tree_index( - addr, leaf_idx + idx_offset); - PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_thash_2( - root, buffer, pub_seed, addr, hash_state_seeded); -} - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -static void PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_treehash( - unsigned char *root, unsigned char *auth_path, - unsigned char *stack, unsigned int *heights, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - - unsigned int offset = 0; - uint32_t idx; - uint32_t tree_idx; - - for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { - /* Add the next leaf node to the stack. */ - gen_leaf(stack + offset * PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_N, - sk_seed, pub_seed, idx + idx_offset, tree_addr, - hash_state_seeded); - offset++; - heights[offset - 1] = 0; - - /* If this is a node we need for the auth path.. */ - if ((leaf_idx ^ 0x1) == idx) { - memcpy(auth_path, stack + (offset - 1)*PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_N, PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_N); - } - - /* While the top-most nodes are of equal height.. */ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { - /* Compute index of the new node, in the next layer. */ - tree_idx = (idx >> (heights[offset - 1] + 1)); - - /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_set_tree_height( - tree_addr, heights[offset - 1] + 1); - PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_set_tree_index( - tree_addr, tree_idx + (idx_offset >> (heights[offset - 1] + 1))); - /* Hash the top-most nodes from the stack together. */ - PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_thash_2( - stack + (offset - 2)*PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_N, stack + (offset - 2)*PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_N, - pub_seed, tree_addr, hash_state_seeded); - offset--; - /* Note that the top-most node is now one layer higher. */ - heights[offset - 1]++; - - /* If this is a node we need for the auth path.. */ - if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_path + heights[offset - 1]*PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_N, - stack + (offset - 1)*PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_N, PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_N); - } - } - } - memcpy(root, stack, PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_N); -} - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_FORS_HEIGHT + 1)*PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_N]; - unsigned int heights[PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_FORS_HEIGHT + 1]; - - PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_FORS_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_TREE_HEIGHT + 1)*PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_N]; - unsigned int heights[PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_TREE_HEIGHT + 1]; - - PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_TREE_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_clean/utils.h b/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_clean/utils.h deleted file mode 100644 index e0b9926c49..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_clean/utils.h +++ /dev/null @@ -1,64 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_UTILS_H -#define PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_UTILS_H - -#include "hash_state.h" -#include "params.h" -#include -#include - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in); - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_bytes_to_ull( - const unsigned char *in, size_t inlen); - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -void PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_clean/wots.c b/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_clean/wots.c deleted file mode 100644 index ff04afab5e..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_clean/wots.c +++ /dev/null @@ -1,167 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "hash_state.h" -#include "params.h" -#include "thash.h" -#include "utils.h" -#include "wots.h" - -// TODO clarify address expectations, and make them more uniform. -// TODO i.e. do we expect types to be set already? -// TODO and do we expect modifications or copies? - -/** - * Computes the starting value for a chain, i.e. the secret key. - * Expects the address to be complete up to the chain address. - */ -static void wots_gen_sk(unsigned char *sk, const unsigned char *sk_seed, - uint32_t wots_addr[8], - const hash_state *hash_state_seeded) { - /* Make sure that the hash address is actually zeroed. */ - PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_set_hash_addr(wots_addr, 0); - - /* Generate sk element. */ - PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_prf_addr(sk, sk_seed, wots_addr, hash_state_seeded); -} - -/** - * Computes the chaining function. - * out and in have to be n-byte arrays. - * - * Interprets in as start-th value of the chain. - * addr has to contain the address of the chain. - */ -static void gen_chain(unsigned char *out, const unsigned char *in, - unsigned int start, unsigned int steps, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - uint32_t i; - - /* Initialize out with the value at position 'start'. */ - memcpy(out, in, PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_N); - - /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_WOTS_W; i++) { - PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_set_hash_addr(addr, i); - PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_thash_1( - out, out, pub_seed, addr, hash_state_seeded); - } -} - -/** - * base_w algorithm as described in draft. - * Interprets an array of bytes as integers in base w. - * This only works when log_w is a divisor of 8. - */ -static void base_w(unsigned int *output, const size_t out_len, - const unsigned char *input) { - size_t in = 0; - size_t out = 0; - unsigned char total = 0; - unsigned int bits = 0; - size_t consumed; - - for (consumed = 0; consumed < out_len; consumed++) { - if (bits == 0) { - total = input[in]; - in++; - bits += 8; - } - bits -= PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_WOTS_LOGW; - output[out] = (unsigned int)((total >> bits) & (PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_WOTS_W - 1)); - out++; - } -} - -/* Computes the WOTS+ checksum over a message (in base_w). */ -static void wots_checksum(unsigned int *csum_base_w, - const unsigned int *msg_base_w) { - unsigned int csum = 0; - unsigned char csum_bytes[(PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_WOTS_LEN2 * PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_WOTS_LOGW + 7) / 8]; - unsigned int i; - - /* Compute checksum. */ - for (i = 0; i < PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_WOTS_LEN1; i++) { - csum += PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_WOTS_W - 1 - msg_base_w[i]; - } - - /* Convert checksum to base_w. */ - /* Make sure expected empty zero bits are the least significant bits. */ - csum = csum << (8 - ((PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_WOTS_LEN2 * PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_WOTS_LOGW) % 8)); - PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_ull_to_bytes( - csum_bytes, sizeof(csum_bytes), csum); - base_w(csum_base_w, PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_WOTS_LEN2, csum_bytes); -} - -/* Takes a message and derives the matching chain lengths. */ -static void chain_lengths(unsigned int *lengths, const unsigned char *msg) { - base_w(lengths, PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_WOTS_LEN1, msg); - wots_checksum(lengths + PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_WOTS_LEN1, lengths); -} - -/** - * WOTS key generation. Takes a 32 byte sk_seed, expands it to WOTS private key - * elements and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_wots_gen_pk( - unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - uint32_t i; - - for (i = 0; i < PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_WOTS_LEN; i++) { - PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_set_chain_addr(addr, i); - wots_gen_sk(pk + i * PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_N, sk_seed, addr, hash_state_seeded); - gen_chain(pk + i * PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_N, pk + i * PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_N, - 0, PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_WOTS_W - 1, pub_seed, addr, hash_state_seeded); - } -} - -/** - * Takes a n-byte message and the 32-byte sk_see to compute a signature 'sig'. - */ -void PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_wots_sign( - unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *hash_state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_WOTS_LEN; i++) { - PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_set_chain_addr(addr, i); - wots_gen_sk(sig + i * PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_N, sk_seed, addr, hash_state_seeded); - gen_chain(sig + i * PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_N, sig + i * PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_N, 0, lengths[i], pub_seed, addr, hash_state_seeded); - } -} - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_wots_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_WOTS_LEN; i++) { - PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_set_chain_addr(addr, i); - gen_chain(pk + i * PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_N, sig + i * PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_N, - lengths[i], PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_WOTS_W - 1 - lengths[i], pub_seed, addr, - hash_state_seeded); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_clean/wots.h b/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_clean/wots.h deleted file mode 100644 index 8497fe62e0..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192f-simple_clean/wots.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_WOTS_H -#define PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_WOTS_H - -#include "hash_state.h" -#include "params.h" -#include - -/** - * WOTS key generation. Takes a 32 byte seed for the private key, expands it to - * a full WOTS private key and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_wots_gen_pk( - unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -/** - * Takes a n-byte message and the 32-byte seed for the private key to compute a - * signature that is placed at 'sig'. - */ -void PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_wots_sign( - unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *hash_state_seeded); - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_wots_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_avx2/LICENSE b/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_avx2/LICENSE deleted file mode 100644 index 670154e353..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_avx2/LICENSE +++ /dev/null @@ -1,116 +0,0 @@ -CC0 1.0 Universal - -Statement of Purpose - -The laws of most jurisdictions throughout the world automatically confer -exclusive Copyright and Related Rights (defined below) upon the creator and -subsequent owner(s) (each and all, an "owner") of an original work of -authorship and/or a database (each, a "Work"). - -Certain owners wish to permanently relinquish those rights to a Work for the -purpose of contributing to a commons of creative, cultural and scientific -works ("Commons") that the public can reliably and without fear of later -claims of infringement build upon, modify, incorporate in other works, reuse -and redistribute as freely as possible in any form whatsoever and for any -purposes, including without limitation commercial purposes. These owners may -contribute to the Commons to promote the ideal of a free culture and the -further production of creative, cultural and scientific works, or to gain -reputation or greater distribution for their Work in part through the use and -efforts of others. - -For these and/or other purposes and motivations, and without any expectation -of additional consideration or compensation, the person associating CC0 with a -Work (the "Affirmer"), to the extent that he or she is an owner of Copyright -and Related Rights in the Work, voluntarily elects to apply CC0 to the Work -and publicly distribute the Work under its terms, with knowledge of his or her -Copyright and Related Rights in the Work and the meaning and intended legal -effect of CC0 on those rights. - -1. Copyright and Related Rights. A Work made available under CC0 may be -protected by copyright and related or neighboring rights ("Copyright and -Related Rights"). Copyright and Related Rights include, but are not limited -to, the following: - - i. the right to reproduce, adapt, distribute, perform, display, communicate, - and translate a Work; - - ii. moral rights retained by the original author(s) and/or performer(s); - - iii. publicity and privacy rights pertaining to a person's image or likeness - depicted in a Work; - - iv. rights protecting against unfair competition in regards to a Work, - subject to the limitations in paragraph 4(a), below; - - v. rights protecting the extraction, dissemination, use and reuse of data in - a Work; - - vi. database rights (such as those arising under Directive 96/9/EC of the - European Parliament and of the Council of 11 March 1996 on the legal - protection of databases, and under any national implementation thereof, - including any amended or successor version of such directive); and - - vii. other similar, equivalent or corresponding rights throughout the world - based on applicable law or treaty, and any national implementations thereof. - -2. Waiver. To the greatest extent permitted by, but not in contravention of, -applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and -unconditionally waives, abandons, and surrenders all of Affirmer's Copyright -and Related Rights and associated claims and causes of action, whether now -known or unknown (including existing as well as future claims and causes of -action), in the Work (i) in all territories worldwide, (ii) for the maximum -duration provided by applicable law or treaty (including future time -extensions), (iii) in any current or future medium and for any number of -copies, and (iv) for any purpose whatsoever, including without limitation -commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes -the Waiver for the benefit of each member of the public at large and to the -detriment of Affirmer's heirs and successors, fully intending that such Waiver -shall not be subject to revocation, rescission, cancellation, termination, or -any other legal or equitable action to disrupt the quiet enjoyment of the Work -by the public as contemplated by Affirmer's express Statement of Purpose. - -3. Public License Fallback. Should any part of the Waiver for any reason be -judged legally invalid or ineffective under applicable law, then the Waiver -shall be preserved to the maximum extent permitted taking into account -Affirmer's express Statement of Purpose. In addition, to the extent the Waiver -is so judged Affirmer hereby grants to each affected person a royalty-free, -non transferable, non sublicensable, non exclusive, irrevocable and -unconditional license to exercise Affirmer's Copyright and Related Rights in -the Work (i) in all territories worldwide, (ii) for the maximum duration -provided by applicable law or treaty (including future time extensions), (iii) -in any current or future medium and for any number of copies, and (iv) for any -purpose whatsoever, including without limitation commercial, advertising or -promotional purposes (the "License"). The License shall be deemed effective as -of the date CC0 was applied by Affirmer to the Work. Should any part of the -License for any reason be judged legally invalid or ineffective under -applicable law, such partial invalidity or ineffectiveness shall not -invalidate the remainder of the License, and in such case Affirmer hereby -affirms that he or she will not (i) exercise any of his or her remaining -Copyright and Related Rights in the Work or (ii) assert any associated claims -and causes of action with respect to the Work, in either case contrary to -Affirmer's express Statement of Purpose. - -4. Limitations and Disclaimers. - - a. No trademark or patent rights held by Affirmer are waived, abandoned, - surrendered, licensed or otherwise affected by this document. - - b. Affirmer offers the Work as-is and makes no representations or warranties - of any kind concerning the Work, express, implied, statutory or otherwise, - including without limitation warranties of title, merchantability, fitness - for a particular purpose, non infringement, or the absence of latent or - other defects, accuracy, or the present or absence of errors, whether or not - discoverable, all to the greatest extent permissible under applicable law. - - c. Affirmer disclaims responsibility for clearing rights of other persons - that may apply to the Work or any use thereof, including without limitation - any person's Copyright and Related Rights in the Work. Further, Affirmer - disclaims responsibility for obtaining any necessary consents, permissions - or other rights required for any use of the Work. - - d. Affirmer understands and acknowledges that Creative Commons is not a - party to this document and has no duty or obligation with respect to this - CC0 or use of the Work. - -For more information, please see - diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_avx2/address.c b/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_avx2/address.c deleted file mode 100644 index 1de7cc0d48..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_avx2/address.c +++ /dev/null @@ -1,78 +0,0 @@ -#include - -#include "address.h" -#include "params.h" -#include "utils.h" - -void PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]) { - int i; - - for (i = 0; i < 8; i++) { - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_ull_to_bytes( - bytes + i * 4, 4, addr[i]); - } -} - -void PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_set_layer_addr( - uint32_t addr[8], uint32_t layer) { - addr[0] = layer; -} - -void PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_set_tree_addr( - uint32_t addr[8], uint64_t tree) { - addr[1] = 0; - addr[2] = (uint32_t) (tree >> 32); - addr[3] = (uint32_t) tree; -} - -void PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_set_type( - uint32_t addr[8], uint32_t type) { - addr[4] = type; -} - -void PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; -} - -/* These functions are used for OTS addresses. */ - -void PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_set_keypair_addr( - uint32_t addr[8], uint32_t keypair) { - addr[5] = keypair; -} - -void PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; - out[5] = in[5]; -} - -void PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_set_chain_addr( - uint32_t addr[8], uint32_t chain) { - addr[6] = chain; -} - -void PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_set_hash_addr( - uint32_t addr[8], uint32_t hash) { - addr[7] = hash; -} - -/* These functions are used for all hash tree addresses (including FORS). */ - -void PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_set_tree_height( - uint32_t addr[8], uint32_t tree_height) { - addr[6] = tree_height; -} - -void PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_set_tree_index( - uint32_t addr[8], uint32_t tree_index) { - addr[7] = tree_index; -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_avx2/address.h b/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_avx2/address.h deleted file mode 100644 index 5a005db15c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_avx2/address.h +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_ADDRESS_H -#define PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_ADDRESS_H - -#include - -#define PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_ADDR_TYPE_WOTS 0 -#define PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_ADDR_TYPE_WOTSPK 1 -#define PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_ADDR_TYPE_HASHTREE 2 -#define PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_ADDR_TYPE_FORSTREE 3 -#define PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_ADDR_TYPE_FORSPK 4 - -void PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]); - -void PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_set_layer_addr( - uint32_t addr[8], uint32_t layer); - -void PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_set_tree_addr( - uint32_t addr[8], uint64_t tree); - -void PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_set_type( - uint32_t addr[8], uint32_t type); - -/* Copies the layer and tree part of one address into the other */ -void PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for WOTS and FORS addresses. */ - -void PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_set_keypair_addr( - uint32_t addr[8], uint32_t keypair); - -void PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_set_chain_addr( - uint32_t addr[8], uint32_t chain); - -void PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_set_hash_addr( - uint32_t addr[8], uint32_t hash); - -void PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for all hash tree addresses (including FORS). */ - -void PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_set_tree_height( - uint32_t addr[8], uint32_t tree_height); - -void PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_set_tree_index( - uint32_t addr[8], uint32_t tree_index); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_avx2/api.h b/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_avx2/api.h deleted file mode 100644 index 6d3e8e6714..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_avx2/api.h +++ /dev/null @@ -1,81 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_API_H -#define PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_API_H - -#include -#include - - - -#define PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_CRYPTO_ALGNAME "SPHINCS+" - -#define PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_CRYPTO_SECRETKEYBYTES 96 -#define PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_CRYPTO_PUBLICKEYBYTES 48 -#define PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_CRYPTO_BYTES 16224 -#define PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_CRYPTO_SEEDBYTES 72 - - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_avx2/fors.c b/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_avx2/fors.c deleted file mode 100644 index 75fa34573a..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_avx2/fors.c +++ /dev/null @@ -1,240 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "fors.h" -#include "hash.h" -#include "hashx8.h" -#include "thash.h" -#include "thashx8.h" -#include "utils.h" -#include "utilsx8.h" - -static void fors_gen_skx8(unsigned char *sk0, - unsigned char *sk1, - unsigned char *sk2, - unsigned char *sk3, - unsigned char *sk4, - unsigned char *sk5, - unsigned char *sk6, - unsigned char *sk7, const unsigned char *sk_seed, - uint32_t fors_leaf_addrx8[8 * 8]) { - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_prf_addrx8(sk0, sk1, sk2, sk3, sk4, sk5, sk6, sk7, - sk_seed, fors_leaf_addrx8); -} - -static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, - const unsigned char *pub_seed, - uint32_t fors_leaf_addr[8], - const hash_state *state_seeded) { - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_thash_1(leaf, sk, pub_seed, fors_leaf_addr, state_seeded); -} - -static void fors_sk_to_leafx8(unsigned char *leaf0, - unsigned char *leaf1, - unsigned char *leaf2, - unsigned char *leaf3, - unsigned char *leaf4, - unsigned char *leaf5, - unsigned char *leaf6, - unsigned char *leaf7, - const unsigned char *sk0, - const unsigned char *sk1, - const unsigned char *sk2, - const unsigned char *sk3, - const unsigned char *sk4, - const unsigned char *sk5, - const unsigned char *sk6, - const unsigned char *sk7, - const unsigned char *pub_seed, - uint32_t fors_leaf_addrx8[8 * 8], - const hash_state *state_seeded) { - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_thashx8_1(leaf0, leaf1, leaf2, leaf3, leaf4, leaf5, leaf6, leaf7, - sk0, sk1, sk2, sk3, sk4, sk5, sk6, sk7, - pub_seed, fors_leaf_addrx8, state_seeded); -} - -static void fors_gen_leafx8(unsigned char *leaf0, - unsigned char *leaf1, - unsigned char *leaf2, - unsigned char *leaf3, - unsigned char *leaf4, - unsigned char *leaf5, - unsigned char *leaf6, - unsigned char *leaf7, - const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx0, - uint32_t addr_idx1, - uint32_t addr_idx2, - uint32_t addr_idx3, - uint32_t addr_idx4, - uint32_t addr_idx5, - uint32_t addr_idx6, - uint32_t addr_idx7, - const uint32_t fors_tree_addr[8], - const hash_state *state_seeded) { - uint32_t fors_leaf_addrx8[8 * 8] = {0}; - unsigned int j; - - /* Only copy the parts that must be kept in fors_leaf_addrx8. */ - for (j = 0; j < 8; j++) { - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_copy_keypair_addr(fors_leaf_addrx8 + j * 8, fors_tree_addr); - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_set_type(fors_leaf_addrx8 + j * 8, PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_ADDR_TYPE_FORSTREE); - } - - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_set_tree_index(fors_leaf_addrx8 + 0 * 8, addr_idx0); - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_set_tree_index(fors_leaf_addrx8 + 1 * 8, addr_idx1); - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_set_tree_index(fors_leaf_addrx8 + 2 * 8, addr_idx2); - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_set_tree_index(fors_leaf_addrx8 + 3 * 8, addr_idx3); - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_set_tree_index(fors_leaf_addrx8 + 4 * 8, addr_idx4); - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_set_tree_index(fors_leaf_addrx8 + 5 * 8, addr_idx5); - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_set_tree_index(fors_leaf_addrx8 + 6 * 8, addr_idx6); - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_set_tree_index(fors_leaf_addrx8 + 7 * 8, addr_idx7); - - fors_gen_skx8(leaf0, leaf1, leaf2, leaf3, leaf4, leaf5, leaf6, leaf7, - sk_seed, fors_leaf_addrx8); - fors_sk_to_leafx8(leaf0, leaf1, leaf2, leaf3, leaf4, leaf5, leaf6, leaf7, - leaf0, leaf1, leaf2, leaf3, leaf4, leaf5, leaf6, leaf7, - pub_seed, fors_leaf_addrx8, state_seeded); -} - -/** - * Interprets m as PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_FORS_HEIGHT-bit unsigned integers. - * Assumes m contains at least PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_FORS_TREES bits. - * Assumes indices has space for PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_FORS_TREES integers. - */ -static void message_to_indices(uint32_t *indices, const unsigned char *m) { - unsigned int i, j; - unsigned int offset = 0; - - for (i = 0; i < PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_FORS_TREES; i++) { - indices[i] = 0; - for (j = 0; j < PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_FORS_HEIGHT; j++) { - indices[i] ^= (((uint32_t)m[offset >> 3] >> (offset & 0x7)) & 0x1) << j; - offset++; - } - } -} - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_fors_sign( - unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], - const hash_state *state_seeded) { - /* Round up to multiple of 8 to prevent out-of-bounds for x8 parallelism */ - uint32_t indices[(PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_FORS_TREES + 7) & ~7] = {0}; - unsigned char roots[((PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_FORS_TREES + 7) & ~7) * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N]; - /* Sign to a buffer, since we may not have a nice multiple of 8 and would - otherwise overrun the signature. */ - unsigned char sigbufx8[8 * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N * (1 + PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_FORS_HEIGHT)]; - uint32_t fors_tree_addrx8[8 * 8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset[8] = {0}; - unsigned int i, j; - - for (j = 0; j < 8; j++) { - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_copy_keypair_addr(fors_tree_addrx8 + j * 8, fors_addr); - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_set_type(fors_tree_addrx8 + j * 8, PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_ADDR_TYPE_FORSTREE); - } - - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_copy_keypair_addr(fors_pk_addr, fors_addr); - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_set_type(fors_pk_addr, PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < ((PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_FORS_TREES + 7) & ~0x7); i += 8) { - for (j = 0; j < 8; j++) { - if (i + j < PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_FORS_TREES) { - idx_offset[j] = (i + j) * (1 << PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_FORS_HEIGHT); - - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_set_tree_height(fors_tree_addrx8 + j * 8, 0); - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_set_tree_index(fors_tree_addrx8 + j * 8, - indices[i + j] + idx_offset[j]); - } - } - - /* Include the secret key part that produces the selected leaf nodes. */ - fors_gen_skx8(sigbufx8 + 0 * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N, - sigbufx8 + 1 * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N, - sigbufx8 + 2 * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N, - sigbufx8 + 3 * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N, - sigbufx8 + 4 * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N, - sigbufx8 + 5 * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N, - sigbufx8 + 6 * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N, - sigbufx8 + 7 * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N, - sk_seed, fors_tree_addrx8); - - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_treehashx8_FORS_HEIGHT( - roots + i * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N, sigbufx8 + 8 * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N, sk_seed, pub_seed, - &indices[i], idx_offset, fors_gen_leafx8, fors_tree_addrx8, - state_seeded); - - for (j = 0; j < 8; j++) { - if (i + j < PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_FORS_TREES) { - memcpy(sig, sigbufx8 + j * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N, PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N); - memcpy(sig + PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N, - sigbufx8 + 8 * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N + j * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_FORS_HEIGHT, - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_FORS_HEIGHT); - sig += PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N * (1 + PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_FORS_HEIGHT); - } - } - } - - /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_thash_FORS_TREES(pk, roots, pub_seed, fors_pk_addr, state_seeded); -} - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, - const uint32_t fors_addr[8], - const hash_state *state_seeded) { - uint32_t indices[PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_FORS_TREES]; - unsigned char roots[PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_FORS_TREES * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N]; - unsigned char leaf[PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N]; - uint32_t fors_tree_addr[8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_copy_keypair_addr(fors_tree_addr, fors_addr); - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_copy_keypair_addr(fors_pk_addr, fors_addr); - - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_set_type(fors_tree_addr, PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_set_type(fors_pk_addr, PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_FORS_TREES; i++) { - idx_offset = i * (1 << PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_FORS_HEIGHT); - - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_set_tree_height(fors_tree_addr, 0); - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Derive the leaf from the included secret key part. */ - fors_sk_to_leaf(leaf, sig, pub_seed, fors_tree_addr, state_seeded); - sig += PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N; - - /* Derive the corresponding root node of this tree. */ - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_compute_root(roots + i * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N, leaf, indices[i], idx_offset, - sig, PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_FORS_HEIGHT, pub_seed, fors_tree_addr, state_seeded); - sig += PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_thash_FORS_TREES(pk, roots, pub_seed, fors_pk_addr, state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_avx2/fors.h b/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_avx2/fors.h deleted file mode 100644 index a6b35a3df8..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_avx2/fors.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_FORS_H -#define PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_FORS_H - -#include - -#include "hash_state.h" -#include "params.h" - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_fors_sign( - unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *hash_state_seeded); - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_fors_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, const uint32_t fors_addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_avx2/hash.h b/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_avx2/hash.h deleted file mode 100644 index 85fa0c57a3..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_avx2/hash.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_HASH_H -#define PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_HASH_H - -#include "hash_state.h" - -#include -#include - -void PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_initialize_hash_function( - hash_state *hash_state_seeded, - const unsigned char *pub_seed, const unsigned char *sk_seed); - -void PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_destroy_hash_function(hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_avx2/hash_sha256.c b/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_avx2/hash_sha256.c deleted file mode 100644 index aef4714c46..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_avx2/hash_sha256.c +++ /dev/null @@ -1,166 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "utils.h" - -#include "sha2.h" -#include "sha256.h" -#include "sha256x8.h" - -/** - * Initializes the hash function states - */ -void PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_initialize_hash_function( - hash_state *hash_state_seeded, - const unsigned char *pub_seed, const unsigned char *sk_seed) { - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_seed_state(&hash_state_seeded->x1, pub_seed); - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_seed_statex8(&hash_state_seeded->x8, pub_seed); - (void)sk_seed; /* Suppress an 'unused parameter' warning. */ -} - -/** - * Cleans up the hash function states - */ -void PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_destroy_hash_function(hash_state *hash_state_seeded) { - sha256_inc_ctx_release(&hash_state_seeded->x1); -} - -/* - * Computes PRF(key, addr), given a secret key of PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N bytes and an address - */ -void PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_prf_addr(unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded) { - unsigned char buf[PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_ADDR_BYTES]; - unsigned char outbuf[PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_OUTPUT_BYTES]; - - memcpy(buf, key, PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N); - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_compress_address(buf + PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N, addr); - - sha256(outbuf, buf, PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_ADDR_BYTES); - memcpy(out, outbuf, PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} - -/** - * Computes the message-dependent randomness R, using a secret seed as a key - * for HMAC, and an optional randomization value prefixed to the message. - * This requires m to have at least PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_BLOCK_BYTES + PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N space - * available in front of the pointer, i.e. before the message to use for the - * prefix. This is necessary to prevent having to move the message around (and - * allocate memory for it). - */ -void PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, const hash_state *hash_state_seeded) { - unsigned char buf[PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_BLOCK_BYTES + PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_OUTPUT_BYTES]; - sha256ctx state; - int i; - - /* This implements HMAC-SHA256 */ - for (i = 0; i < PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N; i++) { - buf[i] = 0x36 ^ sk_prf[i]; - } - memset(buf + PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N, 0x36, PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N); - - sha256_inc_init(&state); - sha256_inc_blocks(&state, buf, 1); - - memcpy(buf, optrand, PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N); - - /* If optrand + message cannot fill up an entire block */ - if (PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N + mlen < PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_BLOCK_BYTES) { - memcpy(buf + PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N, m, mlen); - sha256_inc_finalize(buf + PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_BLOCK_BYTES, &state, - buf, mlen + PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N); - } - /* Otherwise first fill a block, so that finalize only uses the message */ - else { - memcpy(buf + PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N, m, PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N); - sha256_inc_blocks(&state, buf, 1); - - m += PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N; - mlen -= PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N; - sha256_inc_finalize(buf + PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_BLOCK_BYTES, &state, m, mlen); - } - - for (i = 0; i < PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N; i++) { - buf[i] = 0x5c ^ sk_prf[i]; - } - memset(buf + PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N, 0x5c, PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N); - - sha256(buf, buf, PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_BLOCK_BYTES + PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_OUTPUT_BYTES); - memcpy(R, buf, PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} - -/** - * Computes the message hash using R, the public key, and the message. - * Outputs the message digest and the index of the leaf. The index is split in - * the tree index and the leaf index, for convenient copying to an address. - */ -void PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded) { -#define PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_TREE_BITS (PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_TREE_HEIGHT * (PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_D - 1)) -#define PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_TREE_BYTES ((PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_TREE_BITS + 7) / 8) -#define PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_LEAF_BITS PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_TREE_HEIGHT -#define PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_LEAF_BYTES ((PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_LEAF_BITS + 7) / 8) -#define PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_DGST_BYTES (PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_FORS_MSG_BYTES + PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_TREE_BYTES + PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_LEAF_BYTES) - - unsigned char seed[PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_OUTPUT_BYTES + 4]; - - /* Round to nearest multiple of PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_BLOCK_BYTES */ -#define PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_INBLOCKS (((PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_PK_BYTES + PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_BLOCK_BYTES - 1) & \ - -PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_BLOCK_BYTES) / PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_BLOCK_BYTES) - unsigned char inbuf[PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_INBLOCKS * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_BLOCK_BYTES]; - - unsigned char buf[PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_DGST_BYTES]; - unsigned char *bufp = buf; - sha256ctx state; - - sha256_inc_init(&state); - - memcpy(inbuf, R, PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N); - memcpy(inbuf + PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N, pk, PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_PK_BYTES); - - /* If R + pk + message cannot fill up an entire block */ - if (PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_PK_BYTES + mlen < PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_INBLOCKS * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_BLOCK_BYTES) { - memcpy(inbuf + PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_PK_BYTES, m, mlen); - sha256_inc_finalize(seed, &state, inbuf, PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_PK_BYTES + mlen); - } - /* Otherwise first fill a block, so that finalize only uses the message */ - else { - memcpy(inbuf + PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_PK_BYTES, m, - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_INBLOCKS * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_PK_BYTES); - sha256_inc_blocks(&state, inbuf, PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_INBLOCKS); - - m += PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_INBLOCKS * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_PK_BYTES; - mlen -= PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_INBLOCKS * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_PK_BYTES; - sha256_inc_finalize(seed, &state, m, mlen); - } - - /* By doing this in two steps, we prevent hashing the message twice; - otherwise each iteration in MGF1 would hash the message again. */ - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_mgf1(bufp, PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_DGST_BYTES, seed, PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_OUTPUT_BYTES); - - memcpy(digest, bufp, PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_FORS_MSG_BYTES); - bufp += PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_FORS_MSG_BYTES; - - *tree = PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_bytes_to_ull(bufp, PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_TREE_BYTES); - *tree &= (~(uint64_t)0) >> (64 - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_TREE_BITS); - bufp += PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_TREE_BYTES; - - *leaf_idx = (uint32_t)PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_bytes_to_ull( - bufp, PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_LEAF_BYTES); - *leaf_idx &= (~(uint32_t)0) >> (32 - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_LEAF_BITS); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_avx2/hash_sha256x8.c b/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_avx2/hash_sha256x8.c deleted file mode 100644 index 6132282b8b..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_avx2/hash_sha256x8.c +++ /dev/null @@ -1,61 +0,0 @@ -#include -#include - -#include "address.h" -#include "hashx8.h" -#include "params.h" -#include "sha256.h" -#include "sha256avx.h" -#include "sha256x8.h" -#include "utils.h" - -/* - * 8-way parallel version of prf_addr; takes 8x as much input and output - */ -void PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_prf_addrx8(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7, - const unsigned char *key, - const uint32_t addrx8[8 * 8]) { - unsigned char bufx8[8 * (PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_ADDR_BYTES)]; - unsigned char outbufx8[8 * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_OUTPUT_BYTES]; - unsigned int j; - - for (j = 0; j < 8; j++) { - memcpy(bufx8 + j * (PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_ADDR_BYTES), key, PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N); - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_compress_address(bufx8 + PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N + j * (PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_ADDR_BYTES), - addrx8 + j * 8); - } - - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_sha256x8(outbufx8 + 0 * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 1 * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 2 * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 3 * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 4 * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 5 * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 6 * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 7 * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_OUTPUT_BYTES, - bufx8 + 0 * (PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_ADDR_BYTES), - bufx8 + 1 * (PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_ADDR_BYTES), - bufx8 + 2 * (PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_ADDR_BYTES), - bufx8 + 3 * (PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_ADDR_BYTES), - bufx8 + 4 * (PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_ADDR_BYTES), - bufx8 + 5 * (PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_ADDR_BYTES), - bufx8 + 6 * (PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_ADDR_BYTES), - bufx8 + 7 * (PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_ADDR_BYTES), - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_ADDR_BYTES); - - memcpy(out0, outbufx8 + 0 * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N); - memcpy(out1, outbufx8 + 1 * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N); - memcpy(out2, outbufx8 + 2 * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N); - memcpy(out3, outbufx8 + 3 * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N); - memcpy(out4, outbufx8 + 4 * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N); - memcpy(out5, outbufx8 + 5 * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N); - memcpy(out6, outbufx8 + 6 * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N); - memcpy(out7, outbufx8 + 7 * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_avx2/hash_state.h b/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_avx2/hash_state.h deleted file mode 100644 index 40ed5e544a..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_avx2/hash_state.h +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_HASH_STATE_H -#define PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_HASH_STATE_H - -/** - * Defines the type of the hash function state. - * - * Don't be fooled into thinking this instance of SPHINCS+ isn't stateless! - * - * From Section 7.2.2 from the SPHINCS+ round-2 specification: - * - * Each of the instances of the tweakable hash function take PK.seed as its - * first input, which is constant for a given key pair – and, thus, across - * a single signature. This leads to a lot of redundant computation. To remedy - * this, we pad PK.seed to the length of a full 64-byte SHA-256 input block. - * Because of the Merkle-Damgård construction that underlies SHA-256, this - * allows for reuse of the intermediate SHA-256 state after the initial call to - * the compression function which improves performance. - * - * We pass this hash state around in functions, because otherwise we need to - * have a global variable. - * - * We use a struct to differentiate between the x1 and x8 variants of SHA256. - */ - -#include "sha2.h" -#include "sha256avx.h" - -typedef struct { - sha256ctx x1; - sha256ctxx8 x8; -} hash_state; - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_avx2/hashx8.h b/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_avx2/hashx8.h deleted file mode 100644 index 0cc8380c65..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_avx2/hashx8.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_HASHX8_H -#define PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_HASHX8_H - -#include - -#include "params.h" - -void PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_prf_addrx8(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7, - const unsigned char *key, - const uint32_t addrx8[8 * 8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_avx2/params.h b/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_avx2/params.h deleted file mode 100644 index 0be7e4d855..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_avx2/params.h +++ /dev/null @@ -1,53 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_PARAMS_H -#define PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_PARAMS_H - -/* Hash output length in bytes. */ -#define PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N 24 -/* Height of the hypertree. */ -#define PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_FULL_HEIGHT 63 -/* Number of subtree layer. */ -#define PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_D 7 -/* FORS tree dimensions. */ -#define PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_FORS_HEIGHT 14 -#define PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_FORS_TREES 17 -/* Winternitz parameter, */ -#define PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_WOTS_W 16 - -/* The hash function is defined by linking a different hash.c file, as opposed - to setting a #define constant. */ - -/* For clarity */ -#define PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_ADDR_BYTES 32 - -/* WOTS parameters. */ -#define PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_WOTS_LOGW 4 - -#define PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_WOTS_LEN1 (8 * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N / PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_WOTS_LOGW) - -/* PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#define PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_WOTS_LEN2 3 - -#define PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_WOTS_LEN (PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_WOTS_LEN1 + PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_WOTS_LEN2) -#define PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_WOTS_BYTES (PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_WOTS_LEN * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N) -#define PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_WOTS_PK_BYTES PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_WOTS_BYTES - -/* Subtree size. */ -#define PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_TREE_HEIGHT (PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_FULL_HEIGHT / PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_D) - -/* FORS parameters. */ -#define PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_FORS_MSG_BYTES ((PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_FORS_TREES + 7) / 8) -#define PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_FORS_BYTES ((PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_FORS_HEIGHT + 1) * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_FORS_TREES * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N) -#define PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_FORS_PK_BYTES PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N - -/* Resulting SPX sizes. */ -#define PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_BYTES (PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_FORS_BYTES + PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_D * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_WOTS_BYTES +\ - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_FULL_HEIGHT * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N) -#define PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_PK_BYTES (2 * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N) -#define PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SK_BYTES (2 * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_PK_BYTES) - -/* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ -#define PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_OPTRAND_BYTES 32 - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_avx2/sha256.c b/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_avx2/sha256.c deleted file mode 100644 index e108296f65..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_avx2/sha256.c +++ /dev/null @@ -1,71 +0,0 @@ -/* Based on the public domain implementation in - * crypto_hash/sha512/ref/ from http://bench.cr.yp.to/supercop.html - * by D. J. Bernstein */ - -#include -#include -#include - -#include "sha2.h" -#include "sha256.h" -#include "utils.h" - -/* - * Compresses an address to a 22-byte sequence. - * This reduces the number of required SHA256 compression calls, as the last - * block of input is padded with at least 65 bits. - */ -void PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_compress_address(unsigned char *out, const uint32_t addr[8]) { - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_ull_to_bytes(out, 1, addr[0]); /* drop 3 bytes of the layer field */ - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_ull_to_bytes(out + 1, 4, addr[2]); /* drop the highest tree address word */ - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_ull_to_bytes(out + 5, 4, addr[3]); - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_ull_to_bytes(out + 9, 1, addr[4]); /* drop 3 bytes of the type field */ - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_ull_to_bytes(out + 10, 4, addr[5]); - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_ull_to_bytes(out + 14, 4, addr[6]); - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_ull_to_bytes(out + 18, 4, addr[7]); -} - -/** - * Requires 'input_plus_four_bytes' to have 'inlen' + 4 bytes, so that the last - * four bytes can be used for the counter. Typically 'input' is merely a seed. - * Outputs outlen number of bytes - */ -void PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_mgf1( - unsigned char *out, unsigned long outlen, - unsigned char *input_plus_four_bytes, unsigned long inlen) { - unsigned char outbuf[PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_OUTPUT_BYTES]; - unsigned long i; - - /* While we can fit in at least another full block of SHA256 output.. */ - for (i = 0; (i + 1)*PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_OUTPUT_BYTES <= outlen; i++) { - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_ull_to_bytes(input_plus_four_bytes + inlen, 4, i); - sha256(out, input_plus_four_bytes, inlen + 4); - out += PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_OUTPUT_BYTES; - } - /* Until we cannot anymore, and we fill the remainder. */ - if (outlen > i * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_OUTPUT_BYTES) { - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_ull_to_bytes(input_plus_four_bytes + inlen, 4, i); - sha256(outbuf, input_plus_four_bytes, inlen + 4); - memcpy(out, outbuf, outlen - i * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_OUTPUT_BYTES); - } -} - - -/** - * Absorb the constant pub_seed using one round of the compression function - * This initializes hash_state_seeded, which can then be reused in thash - **/ -void PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_seed_state(sha256ctx *hash_state_seeded, const unsigned char *pub_seed) { - uint8_t block[PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_BLOCK_BYTES]; - size_t i; - - for (i = 0; i < PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N; ++i) { - block[i] = pub_seed[i]; - } - for (i = PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N; i < PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_BLOCK_BYTES; ++i) { - block[i] = 0; - } - - sha256_inc_init(hash_state_seeded); - sha256_inc_blocks(hash_state_seeded, block, 1); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_avx2/sha256.h b/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_avx2/sha256.h deleted file mode 100644 index a22d3d94cc..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_avx2/sha256.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_H -#define PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_H - -#define PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_BLOCK_BYTES 64 -#define PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_OUTPUT_BYTES 32 /* This does not necessarily equal PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N */ -#define PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_ADDR_BYTES 22 - -#include -#include - -#include "sha2.h" - -void PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_compress_address(unsigned char *out, const uint32_t addr[8]); - -void PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_mgf1( - unsigned char *out, unsigned long outlen, - unsigned char *input_plus_four_bytes, unsigned long inlen); - -void PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_seed_state(sha256ctx *hash_state_seeded, const unsigned char *pub_seed); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_avx2/sha256avx.c b/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_avx2/sha256avx.c deleted file mode 100644 index dd33b6fbf8..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_avx2/sha256avx.c +++ /dev/null @@ -1,296 +0,0 @@ -#include -#include -#include - -#include "sha256avx.h" - -// Transpose 8 vectors containing 32-bit values -void PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_transpose(u256 s[8]) { - u256 tmp0[8]; - u256 tmp1[8]; - tmp0[0] = _mm256_unpacklo_epi32(s[0], s[1]); - tmp0[1] = _mm256_unpackhi_epi32(s[0], s[1]); - tmp0[2] = _mm256_unpacklo_epi32(s[2], s[3]); - tmp0[3] = _mm256_unpackhi_epi32(s[2], s[3]); - tmp0[4] = _mm256_unpacklo_epi32(s[4], s[5]); - tmp0[5] = _mm256_unpackhi_epi32(s[4], s[5]); - tmp0[6] = _mm256_unpacklo_epi32(s[6], s[7]); - tmp0[7] = _mm256_unpackhi_epi32(s[6], s[7]); - tmp1[0] = _mm256_unpacklo_epi64(tmp0[0], tmp0[2]); - tmp1[1] = _mm256_unpackhi_epi64(tmp0[0], tmp0[2]); - tmp1[2] = _mm256_unpacklo_epi64(tmp0[1], tmp0[3]); - tmp1[3] = _mm256_unpackhi_epi64(tmp0[1], tmp0[3]); - tmp1[4] = _mm256_unpacklo_epi64(tmp0[4], tmp0[6]); - tmp1[5] = _mm256_unpackhi_epi64(tmp0[4], tmp0[6]); - tmp1[6] = _mm256_unpacklo_epi64(tmp0[5], tmp0[7]); - tmp1[7] = _mm256_unpackhi_epi64(tmp0[5], tmp0[7]); - s[0] = _mm256_permute2x128_si256(tmp1[0], tmp1[4], 0x20); - s[1] = _mm256_permute2x128_si256(tmp1[1], tmp1[5], 0x20); - s[2] = _mm256_permute2x128_si256(tmp1[2], tmp1[6], 0x20); - s[3] = _mm256_permute2x128_si256(tmp1[3], tmp1[7], 0x20); - s[4] = _mm256_permute2x128_si256(tmp1[0], tmp1[4], 0x31); - s[5] = _mm256_permute2x128_si256(tmp1[1], tmp1[5], 0x31); - s[6] = _mm256_permute2x128_si256(tmp1[2], tmp1[6], 0x31); - s[7] = _mm256_permute2x128_si256(tmp1[3], tmp1[7], 0x31); -} - -void PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_sha256_clone_statex8(sha256ctxx8 *outctx, const sha256ctxx8 *inctx) { - memcpy(outctx, inctx, sizeof(sha256ctxx8)); -} - -void PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_sha256_init8x(sha256ctxx8 *ctx) { - ctx->s[0] = _mm256_set_epi32((int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667); - ctx->s[1] = _mm256_set_epi32((int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85); - ctx->s[2] = _mm256_set_epi32((int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372); - ctx->s[3] = _mm256_set_epi32((int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a); - ctx->s[4] = _mm256_set_epi32((int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f); - ctx->s[5] = _mm256_set_epi32((int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c); - ctx->s[6] = _mm256_set_epi32((int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab); - ctx->s[7] = _mm256_set_epi32((int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19); - - ctx->datalen = 0; - ctx->msglen = 0; -} - -void PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_sha256_update8x(sha256ctxx8 *ctx, - const unsigned char *d0, - const unsigned char *d1, - const unsigned char *d2, - const unsigned char *d3, - const unsigned char *d4, - const unsigned char *d5, - const unsigned char *d6, - const unsigned char *d7, - unsigned long long len) { - size_t i = 0; - size_t bytes_to_copy; - - while (i < len) { - bytes_to_copy = (size_t)len - i; - if (bytes_to_copy > 64) { - bytes_to_copy = 64; - } - memcpy(&ctx->msgblocks[64 * 0], d0 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64 * 1], d1 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64 * 2], d2 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64 * 3], d3 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64 * 4], d4 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64 * 5], d5 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64 * 6], d6 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64 * 7], d7 + i, bytes_to_copy); - ctx->datalen += (unsigned int)bytes_to_copy; - i += bytes_to_copy; - if (ctx->datalen == 64) { - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_sha256_transform8x(ctx, ctx->msgblocks); - ctx->msglen += 512; - ctx->datalen = 0; - } - } -} - -void PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_sha256_final8x(sha256ctxx8 *ctx, - unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7) { - unsigned int i, curlen; - - // Padding - if (ctx->datalen < 56) { - for (i = 0; i < 8; ++i) { - curlen = ctx->datalen; - ctx->msgblocks[64 * i + curlen++] = 0x80; - while (curlen < 64) { - ctx->msgblocks[64 * i + curlen++] = 0x00; - } - } - } else { - for (i = 0; i < 8; ++i) { - curlen = ctx->datalen; - ctx->msgblocks[64 * i + curlen++] = 0x80; - while (curlen < 64) { - ctx->msgblocks[64 * i + curlen++] = 0x00; - } - } - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_sha256_transform8x(ctx, ctx->msgblocks); - memset(ctx->msgblocks, 0, 8 * 64); - } - - // Add length of the message to each block - ctx->msglen += ctx->datalen * 8; - for (i = 0; i < 8; i++) { - ctx->msgblocks[64 * i + 63] = (unsigned char)ctx->msglen; - ctx->msgblocks[64 * i + 62] = (unsigned char)(ctx->msglen >> 8); - ctx->msgblocks[64 * i + 61] = (unsigned char)(ctx->msglen >> 16); - ctx->msgblocks[64 * i + 60] = (unsigned char)(ctx->msglen >> 24); - ctx->msgblocks[64 * i + 59] = (unsigned char)(ctx->msglen >> 32); - ctx->msgblocks[64 * i + 58] = (unsigned char)(ctx->msglen >> 40); - ctx->msgblocks[64 * i + 57] = (unsigned char)(ctx->msglen >> 48); - ctx->msgblocks[64 * i + 56] = (unsigned char)(ctx->msglen >> 56); - } - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_sha256_transform8x(ctx, ctx->msgblocks); - - // Compute final hash output - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_transpose(ctx->s); - - // Store Hash value - STORE(out0, BYTESWAP(ctx->s[0])); - STORE(out1, BYTESWAP(ctx->s[1])); - STORE(out2, BYTESWAP(ctx->s[2])); - STORE(out3, BYTESWAP(ctx->s[3])); - STORE(out4, BYTESWAP(ctx->s[4])); - STORE(out5, BYTESWAP(ctx->s[5])); - STORE(out6, BYTESWAP(ctx->s[6])); - STORE(out7, BYTESWAP(ctx->s[7])); -} - -void PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_sha256_transform8x(sha256ctxx8 *ctx, const unsigned char *data) { - u256 s[8], w[64], T0, T1; - int i; - - // Load words and transform data correctly - for (i = 0; i < 8; i++) { - w[i] = BYTESWAP(LOAD(data + 64 * i)); - w[i + 8] = BYTESWAP(LOAD(data + 32 + 64 * i)); - } - - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_transpose(w); - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_transpose(w + 8); - - // Initial State - s[0] = ctx->s[0]; - s[1] = ctx->s[1]; - s[2] = ctx->s[2]; - s[3] = ctx->s[3]; - s[4] = ctx->s[4]; - s[5] = ctx->s[5]; - s[6] = ctx->s[6]; - s[7] = ctx->s[7]; - - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 0, w[0]); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 1, w[1]); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 2, w[2]); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 3, w[3]); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 4, w[4]); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 5, w[5]); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 6, w[6]); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 7, w[7]); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 8, w[8]); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 9, w[9]); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 10, w[10]); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 11, w[11]); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 12, w[12]); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 13, w[13]); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 14, w[14]); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 15, w[15]); - w[16] = ADD4_32(WSIGMA1_AVX(w[14]), w[0], w[9], WSIGMA0_AVX(w[1])); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 16, w[16]); - w[17] = ADD4_32(WSIGMA1_AVX(w[15]), w[1], w[10], WSIGMA0_AVX(w[2])); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 17, w[17]); - w[18] = ADD4_32(WSIGMA1_AVX(w[16]), w[2], w[11], WSIGMA0_AVX(w[3])); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 18, w[18]); - w[19] = ADD4_32(WSIGMA1_AVX(w[17]), w[3], w[12], WSIGMA0_AVX(w[4])); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 19, w[19]); - w[20] = ADD4_32(WSIGMA1_AVX(w[18]), w[4], w[13], WSIGMA0_AVX(w[5])); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 20, w[20]); - w[21] = ADD4_32(WSIGMA1_AVX(w[19]), w[5], w[14], WSIGMA0_AVX(w[6])); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 21, w[21]); - w[22] = ADD4_32(WSIGMA1_AVX(w[20]), w[6], w[15], WSIGMA0_AVX(w[7])); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 22, w[22]); - w[23] = ADD4_32(WSIGMA1_AVX(w[21]), w[7], w[16], WSIGMA0_AVX(w[8])); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 23, w[23]); - w[24] = ADD4_32(WSIGMA1_AVX(w[22]), w[8], w[17], WSIGMA0_AVX(w[9])); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 24, w[24]); - w[25] = ADD4_32(WSIGMA1_AVX(w[23]), w[9], w[18], WSIGMA0_AVX(w[10])); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 25, w[25]); - w[26] = ADD4_32(WSIGMA1_AVX(w[24]), w[10], w[19], WSIGMA0_AVX(w[11])); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 26, w[26]); - w[27] = ADD4_32(WSIGMA1_AVX(w[25]), w[11], w[20], WSIGMA0_AVX(w[12])); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 27, w[27]); - w[28] = ADD4_32(WSIGMA1_AVX(w[26]), w[12], w[21], WSIGMA0_AVX(w[13])); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 28, w[28]); - w[29] = ADD4_32(WSIGMA1_AVX(w[27]), w[13], w[22], WSIGMA0_AVX(w[14])); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 29, w[29]); - w[30] = ADD4_32(WSIGMA1_AVX(w[28]), w[14], w[23], WSIGMA0_AVX(w[15])); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 30, w[30]); - w[31] = ADD4_32(WSIGMA1_AVX(w[29]), w[15], w[24], WSIGMA0_AVX(w[16])); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 31, w[31]); - w[32] = ADD4_32(WSIGMA1_AVX(w[30]), w[16], w[25], WSIGMA0_AVX(w[17])); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 32, w[32]); - w[33] = ADD4_32(WSIGMA1_AVX(w[31]), w[17], w[26], WSIGMA0_AVX(w[18])); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 33, w[33]); - w[34] = ADD4_32(WSIGMA1_AVX(w[32]), w[18], w[27], WSIGMA0_AVX(w[19])); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 34, w[34]); - w[35] = ADD4_32(WSIGMA1_AVX(w[33]), w[19], w[28], WSIGMA0_AVX(w[20])); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 35, w[35]); - w[36] = ADD4_32(WSIGMA1_AVX(w[34]), w[20], w[29], WSIGMA0_AVX(w[21])); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 36, w[36]); - w[37] = ADD4_32(WSIGMA1_AVX(w[35]), w[21], w[30], WSIGMA0_AVX(w[22])); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 37, w[37]); - w[38] = ADD4_32(WSIGMA1_AVX(w[36]), w[22], w[31], WSIGMA0_AVX(w[23])); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 38, w[38]); - w[39] = ADD4_32(WSIGMA1_AVX(w[37]), w[23], w[32], WSIGMA0_AVX(w[24])); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 39, w[39]); - w[40] = ADD4_32(WSIGMA1_AVX(w[38]), w[24], w[33], WSIGMA0_AVX(w[25])); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 40, w[40]); - w[41] = ADD4_32(WSIGMA1_AVX(w[39]), w[25], w[34], WSIGMA0_AVX(w[26])); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 41, w[41]); - w[42] = ADD4_32(WSIGMA1_AVX(w[40]), w[26], w[35], WSIGMA0_AVX(w[27])); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 42, w[42]); - w[43] = ADD4_32(WSIGMA1_AVX(w[41]), w[27], w[36], WSIGMA0_AVX(w[28])); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 43, w[43]); - w[44] = ADD4_32(WSIGMA1_AVX(w[42]), w[28], w[37], WSIGMA0_AVX(w[29])); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 44, w[44]); - w[45] = ADD4_32(WSIGMA1_AVX(w[43]), w[29], w[38], WSIGMA0_AVX(w[30])); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 45, w[45]); - w[46] = ADD4_32(WSIGMA1_AVX(w[44]), w[30], w[39], WSIGMA0_AVX(w[31])); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 46, w[46]); - w[47] = ADD4_32(WSIGMA1_AVX(w[45]), w[31], w[40], WSIGMA0_AVX(w[32])); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 47, w[47]); - w[48] = ADD4_32(WSIGMA1_AVX(w[46]), w[32], w[41], WSIGMA0_AVX(w[33])); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 48, w[48]); - w[49] = ADD4_32(WSIGMA1_AVX(w[47]), w[33], w[42], WSIGMA0_AVX(w[34])); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 49, w[49]); - w[50] = ADD4_32(WSIGMA1_AVX(w[48]), w[34], w[43], WSIGMA0_AVX(w[35])); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 50, w[50]); - w[51] = ADD4_32(WSIGMA1_AVX(w[49]), w[35], w[44], WSIGMA0_AVX(w[36])); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 51, w[51]); - w[52] = ADD4_32(WSIGMA1_AVX(w[50]), w[36], w[45], WSIGMA0_AVX(w[37])); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 52, w[52]); - w[53] = ADD4_32(WSIGMA1_AVX(w[51]), w[37], w[46], WSIGMA0_AVX(w[38])); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 53, w[53]); - w[54] = ADD4_32(WSIGMA1_AVX(w[52]), w[38], w[47], WSIGMA0_AVX(w[39])); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 54, w[54]); - w[55] = ADD4_32(WSIGMA1_AVX(w[53]), w[39], w[48], WSIGMA0_AVX(w[40])); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 55, w[55]); - w[56] = ADD4_32(WSIGMA1_AVX(w[54]), w[40], w[49], WSIGMA0_AVX(w[41])); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 56, w[56]); - w[57] = ADD4_32(WSIGMA1_AVX(w[55]), w[41], w[50], WSIGMA0_AVX(w[42])); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 57, w[57]); - w[58] = ADD4_32(WSIGMA1_AVX(w[56]), w[42], w[51], WSIGMA0_AVX(w[43])); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 58, w[58]); - w[59] = ADD4_32(WSIGMA1_AVX(w[57]), w[43], w[52], WSIGMA0_AVX(w[44])); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 59, w[59]); - w[60] = ADD4_32(WSIGMA1_AVX(w[58]), w[44], w[53], WSIGMA0_AVX(w[45])); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 60, w[60]); - w[61] = ADD4_32(WSIGMA1_AVX(w[59]), w[45], w[54], WSIGMA0_AVX(w[46])); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 61, w[61]); - w[62] = ADD4_32(WSIGMA1_AVX(w[60]), w[46], w[55], WSIGMA0_AVX(w[47])); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 62, w[62]); - w[63] = ADD4_32(WSIGMA1_AVX(w[61]), w[47], w[56], WSIGMA0_AVX(w[48])); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 63, w[63]); - - // Feed Forward - ctx->s[0] = ADD32(s[0], ctx->s[0]); - ctx->s[1] = ADD32(s[1], ctx->s[1]); - ctx->s[2] = ADD32(s[2], ctx->s[2]); - ctx->s[3] = ADD32(s[3], ctx->s[3]); - ctx->s[4] = ADD32(s[4], ctx->s[4]); - ctx->s[5] = ADD32(s[5], ctx->s[5]); - ctx->s[6] = ADD32(s[6], ctx->s[6]); - ctx->s[7] = ADD32(s[7], ctx->s[7]); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_avx2/sha256avx.h b/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_avx2/sha256avx.h deleted file mode 100644 index 8560336cf8..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_avx2/sha256avx.h +++ /dev/null @@ -1,103 +0,0 @@ -#ifndef SHA256AVX_H -#define SHA256AVX_H - -#include -#include - -static const unsigned int RC[] = { - 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, - 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, - 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, - 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, - 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, - 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, - 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, - 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, - 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, - 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, - 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, - 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, - 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, - 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, - 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, - 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 -}; - -#define u32 uint32_t -#define u256 __m256i - -#define XOR _mm256_xor_si256 -#define OR _mm256_or_si256 -#define AND _mm256_and_si256 -#define ADD32 _mm256_add_epi32 -#define NOT(x) _mm256_xor_si256(x, _mm256_set_epi32(-1, -1, -1, -1, -1, -1, -1, -1)) - -#define LOAD(src) _mm256_loadu_si256((__m256i *)(src)) -#define STORE(dest,src) _mm256_storeu_si256((__m256i *)(dest),src) - -#define BYTESWAP(x) _mm256_shuffle_epi8(x, _mm256_set_epi8(0xc,0xd,0xe,0xf,0x8,0x9,0xa,0xb,0x4,0x5,0x6,0x7,0x0,0x1,0x2,0x3,0xc,0xd,0xe,0xf,0x8,0x9,0xa,0xb,0x4,0x5,0x6,0x7,0x0,0x1,0x2,0x3)) - -#define SHIFTR32(x, y) _mm256_srli_epi32(x, y) -#define SHIFTL32(x, y) _mm256_slli_epi32(x, y) - -#define ROTR32(x, y) OR(SHIFTR32(x, y), SHIFTL32(x, 32 - (y))) -#define ROTL32(x, y) OR(SHIFTL32(x, y), SHIFTR32(x, 32 - (y))) - -#define XOR3(a, b, c) XOR(XOR(a, b), c) - -#define ADD3_32(a, b, c) ADD32(ADD32(a, b), c) -#define ADD4_32(a, b, c, d) ADD32(ADD32(ADD32(a, b), c), d) -#define ADD5_32(a, b, c, d, e) ADD32(ADD32(ADD32(ADD32(a, b), c), d), e) - -#define MAJ_AVX(a, b, c) XOR3(AND(a, b), AND(a, c), AND(b, c)) -#define CH_AVX(a, b, c) XOR(AND(a, b), AND(NOT(a), c)) - -#define SIGMA1_AVX(x) XOR3(ROTR32(x, 6), ROTR32(x, 11), ROTR32(x, 25)) -#define SIGMA0_AVX(x) XOR3(ROTR32(x, 2), ROTR32(x, 13), ROTR32(x, 22)) - -#define WSIGMA1_AVX(x) XOR3(ROTR32(x, 17), ROTR32(x, 19), SHIFTR32(x, 10)) -#define WSIGMA0_AVX(x) XOR3(ROTR32(x, 7), ROTR32(x, 18), SHIFTR32(x, 3)) - -#define SHA256ROUND_AVX(a, b, c, d, e, f, g, h, rc, w) \ - T0 = ADD5_32(h, SIGMA1_AVX(e), CH_AVX(e, f, g), _mm256_set1_epi32((int)RC[rc]), w); \ - (d) = ADD32(d, T0); \ - T1 = ADD32(SIGMA0_AVX(a), MAJ_AVX(a, b, c)); \ - (h) = ADD32(T0, T1); - -typedef struct SHA256state { - u256 s[8]; - uint8_t msgblocks[8 * 64]; - unsigned int datalen; - uint64_t msglen; -} sha256ctxx8; - - -void PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_transpose(u256 s[8]); -void PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_sha256_init_frombytes_x8(sha256ctxx8 *ctx, const uint8_t *s, unsigned long long msglen); -void PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_sha256_init8x(sha256ctxx8 *ctx); -void PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_sha256_update8x(sha256ctxx8 *ctx, - const unsigned char *d0, - const unsigned char *d1, - const unsigned char *d2, - const unsigned char *d3, - const unsigned char *d4, - const unsigned char *d5, - const unsigned char *d6, - const unsigned char *d7, - unsigned long long len); -void PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_sha256_final8x(sha256ctxx8 *ctx, - unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7); - -void PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_sha256_transform8x(sha256ctxx8 *ctx, const unsigned char *data); - -void PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_sha256_clone_statex8(sha256ctxx8 *outctx, const sha256ctxx8 *inctx); - - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_avx2/sha256x8.c b/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_avx2/sha256x8.c deleted file mode 100644 index 45cebb470a..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_avx2/sha256x8.c +++ /dev/null @@ -1,128 +0,0 @@ -#include - -#include "sha256.h" -#include "sha256avx.h" -#include "sha256x8.h" -#include "utils.h" - -void PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_seed_statex8(sha256ctxx8 *ctx, const unsigned char *pub_seed) { - uint8_t block[PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_BLOCK_BYTES]; - size_t i; - - for (i = 0; i < PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N; ++i) { - block[i] = pub_seed[i]; - } - for (i = PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N; i < PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_BLOCK_BYTES; ++i) { - block[i] = 0; - } - - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_sha256_init8x(ctx); - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_sha256_update8x(ctx, block, block, block, block, block, block, block, block, PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_BLOCK_BYTES); - -} - -/* This provides a wrapper around the internals of 8x parallel SHA256 */ -void PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_sha256x8(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - const unsigned char *in4, - const unsigned char *in5, - const unsigned char *in6, - const unsigned char *in7, unsigned long long inlen) { - sha256ctxx8 ctx; - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_sha256_init8x(&ctx); - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_sha256_update8x(&ctx, in0, in1, in2, in3, in4, in5, in6, in7, inlen); - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_sha256_final8x(&ctx, out0, out1, out2, out3, out4, out5, out6, out7); -} - -/** - * Note that inlen should be sufficiently small that it still allows for - * an array to be allocated on the stack. Typically 'in' is merely a seed. - * Outputs outlen number of bytes - */ -void PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_mgf1x8( - unsigned char *outx8, - unsigned long outlen, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - const unsigned char *in4, - const unsigned char *in5, - const unsigned char *in6, - const unsigned char *in7, - unsigned long inlen) { - unsigned char inbufx8[8 * ((PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_ADDR_BYTES) + 4)]; - unsigned char outbufx8[8 * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_OUTPUT_BYTES]; - unsigned long i; - unsigned int j; - - memcpy(inbufx8 + 0 * (inlen + 4), in0, inlen); - memcpy(inbufx8 + 1 * (inlen + 4), in1, inlen); - memcpy(inbufx8 + 2 * (inlen + 4), in2, inlen); - memcpy(inbufx8 + 3 * (inlen + 4), in3, inlen); - memcpy(inbufx8 + 4 * (inlen + 4), in4, inlen); - memcpy(inbufx8 + 5 * (inlen + 4), in5, inlen); - memcpy(inbufx8 + 6 * (inlen + 4), in6, inlen); - memcpy(inbufx8 + 7 * (inlen + 4), in7, inlen); - - /* While we can fit in at least another full block of SHA256 output.. */ - for (i = 0; (i + 1)*PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_OUTPUT_BYTES <= outlen; i++) { - for (j = 0; j < 8; j++) { - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_ull_to_bytes(inbufx8 + inlen + j * (inlen + 4), 4, i); - } - - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_sha256x8(outx8 + 0 * outlen, - outx8 + 1 * outlen, - outx8 + 2 * outlen, - outx8 + 3 * outlen, - outx8 + 4 * outlen, - outx8 + 5 * outlen, - outx8 + 6 * outlen, - outx8 + 7 * outlen, - inbufx8 + 0 * (inlen + 4), - inbufx8 + 1 * (inlen + 4), - inbufx8 + 2 * (inlen + 4), - inbufx8 + 3 * (inlen + 4), - inbufx8 + 4 * (inlen + 4), - inbufx8 + 5 * (inlen + 4), - inbufx8 + 6 * (inlen + 4), - inbufx8 + 7 * (inlen + 4), inlen + 4); - outx8 += PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_OUTPUT_BYTES; - } - /* Until we cannot anymore, and we fill the remainder. */ - for (j = 0; j < 8; j++) { - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_ull_to_bytes(inbufx8 + inlen + j * (inlen + 4), 4, i); - } - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_sha256x8(outbufx8 + 0 * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 1 * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 2 * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 3 * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 4 * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 5 * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 6 * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 7 * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_OUTPUT_BYTES, - inbufx8 + 0 * (inlen + 4), - inbufx8 + 1 * (inlen + 4), - inbufx8 + 2 * (inlen + 4), - inbufx8 + 3 * (inlen + 4), - inbufx8 + 4 * (inlen + 4), - inbufx8 + 5 * (inlen + 4), - inbufx8 + 6 * (inlen + 4), - inbufx8 + 7 * (inlen + 4), inlen + 4); - - for (j = 0; j < 8; j++) { - memcpy(outx8 + j * outlen, - outbufx8 + j * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_OUTPUT_BYTES, - outlen - i * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_OUTPUT_BYTES); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_avx2/sha256x8.h b/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_avx2/sha256x8.h deleted file mode 100644 index 4d52cfa381..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_avx2/sha256x8.h +++ /dev/null @@ -1,44 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256X8_H -#define PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256X8_H - -#include "sha256avx.h" - -#define PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_BLOCK_BYTES 64 -#define PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_OUTPUT_BYTES 32 /* This does not necessarily equal PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N */ - -/* This provides a wrapper around the internals of 8x parallel SHA256 */ -void PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_sha256x8(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - const unsigned char *in4, - const unsigned char *in5, - const unsigned char *in6, - const unsigned char *in7, unsigned long long inlen); - -/** - * Note that inlen should be sufficiently small that it still allows for - * an array to be allocated on the stack. Typically 'in' is merely a seed. - * Outputs outlen number of bytes - */ -void PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_mgf1x8(unsigned char *outx8, unsigned long outlen, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - const unsigned char *in4, - const unsigned char *in5, - const unsigned char *in6, - const unsigned char *in7, - unsigned long inlen); - -void PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_seed_statex8(sha256ctxx8 *ctx, const unsigned char *pub_seed); -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_avx2/sign.c b/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_avx2/sign.c deleted file mode 100644 index 9ed7a22811..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_avx2/sign.c +++ /dev/null @@ -1,356 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "api.h" -#include "fors.h" -#include "hash.h" -#include "hash_state.h" -#include "params.h" -#include "randombytes.h" -#include "thash.h" -#include "utils.h" -#include "wots.h" - -/** - * Computes the leaf at a given address. First generates the WOTS key pair, - * then computes leaf by hashing horizontally. - */ -static void wots_gen_leaf(unsigned char *leaf, const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx, const uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - unsigned char pk[PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_WOTS_BYTES]; - uint32_t wots_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_set_type( - wots_addr, PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_set_type( - wots_pk_addr, PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_ADDR_TYPE_WOTSPK); - - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_set_keypair_addr( - wots_addr, addr_idx); - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_wots_gen_pk( - pk, sk_seed, pub_seed, wots_addr, hash_state_seeded); - - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_copy_keypair_addr( - wots_pk_addr, wots_addr); - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_thash_WOTS_LEN( - leaf, pk, pub_seed, wots_pk_addr, hash_state_seeded); -} - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_crypto_sign_secretkeybytes(void) { - return PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_CRYPTO_SECRETKEYBYTES; -} - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_crypto_sign_publickeybytes(void) { - return PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_CRYPTO_PUBLICKEYBYTES; -} - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_crypto_sign_bytes(void) { - return PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_CRYPTO_BYTES; -} - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_crypto_sign_seedbytes(void) { - return PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_CRYPTO_SEEDBYTES; -} - -/* - * Generates an SPX key pair given a seed of length - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed) { - /* We do not need the auth path in key generation, but it simplifies the - code to have just one treehash routine that computes both root and path - in one function. */ - unsigned char auth_path[PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_TREE_HEIGHT * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N]; - uint32_t top_tree_addr[8] = {0}; - hash_state hash_state_seeded; - - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_set_layer_addr( - top_tree_addr, PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_D - 1); - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_set_type( - top_tree_addr, PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_ADDR_TYPE_HASHTREE); - - /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ - memcpy(sk, seed, PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_CRYPTO_SEEDBYTES); - - memcpy(pk, sk + 2 * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N, PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_initialize_hash_function(&hash_state_seeded, pk, sk); - - /* Compute root node of the top-most subtree. */ - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_treehash_TREE_HEIGHT( - sk + 3 * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N, auth_path, sk, sk + 2 * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N, 0, 0, - wots_gen_leaf, top_tree_addr, &hash_state_seeded); - - memcpy(pk + PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N, sk + 3 * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N, PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N); - - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_destroy_hash_function(&hash_state_seeded); - return 0; -} - -/* - * Generates an SPX key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk) { - unsigned char seed[PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_CRYPTO_SEEDBYTES]; - randombytes(seed, PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_CRYPTO_SEEDBYTES); - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_crypto_sign_seed_keypair( - pk, sk, seed); - - return 0; -} - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - const unsigned char *sk_seed = sk; - const unsigned char *sk_prf = sk + PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N; - const unsigned char *pk = sk + 2 * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N; - const unsigned char *pub_seed = pk; - - unsigned char optrand[PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N]; - unsigned char mhash[PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_FORS_MSG_BYTES]; - unsigned char root[PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N]; - uint32_t i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - - hash_state hash_state_seeded; - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_initialize_hash_function( - &hash_state_seeded, - pub_seed, sk_seed); - - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_set_type( - wots_addr, PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_set_type( - tree_addr, PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_ADDR_TYPE_HASHTREE); - - /* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ - randombytes(optrand, PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N); - /* Compute the digest randomization value. */ - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_gen_message_random( - sig, sk_prf, optrand, m, mlen, &hash_state_seeded); - - /* Derive the message digest and leaf index from R, PK and M. */ - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N; - - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_set_keypair_addr( - wots_addr, idx_leaf); - - /* Sign the message hash using FORS. */ - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_fors_sign( - sig, root, mhash, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_FORS_BYTES; - - for (i = 0; i < PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_D; i++) { - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_set_tree_addr(tree_addr, tree); - - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_set_keypair_addr( - wots_addr, idx_leaf); - - /* Compute a WOTS signature. */ - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_wots_sign( - sig, root, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_WOTS_BYTES; - - /* Compute the authentication path for the used WOTS leaf. */ - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_treehash_TREE_HEIGHT( - root, sig, sk_seed, pub_seed, idx_leaf, 0, - wots_gen_leaf, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_TREE_HEIGHT * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_TREE_HEIGHT; - } - - *siglen = PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_BYTES; - - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_destroy_hash_function(&hash_state_seeded); - return 0; -} - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk) { - const unsigned char *pub_seed = pk; - const unsigned char *pub_root = pk + PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N; - unsigned char mhash[PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_FORS_MSG_BYTES]; - unsigned char wots_pk[PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_WOTS_BYTES]; - unsigned char root[PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N]; - unsigned char leaf[PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N]; - unsigned int i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - hash_state hash_state_seeded; - - if (siglen != PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_BYTES) { - return -1; - } - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_initialize_hash_function( - &hash_state_seeded, - pub_seed, NULL); - - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_set_type( - wots_addr, PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_set_type( - tree_addr, PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_ADDR_TYPE_HASHTREE); - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_set_type( - wots_pk_addr, PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_ADDR_TYPE_WOTSPK); - - /* Derive the message digest and leaf index from R || PK || M. */ - /* The additional PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N is a result of the hash domain separator. */ - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N; - - /* Layer correctly defaults to 0, so no need to set_layer_addr */ - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_set_keypair_addr( - wots_addr, idx_leaf); - - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_fors_pk_from_sig( - root, sig, mhash, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_FORS_BYTES; - - /* For each subtree.. */ - for (i = 0; i < PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_D; i++) { - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_set_tree_addr(tree_addr, tree); - - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_set_keypair_addr( - wots_addr, idx_leaf); - - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_copy_keypair_addr( - wots_pk_addr, wots_addr); - - /* The WOTS public key is only correct if the signature was correct. */ - /* Initially, root is the FORS pk, but on subsequent iterations it is - the root of the subtree below the currently processed subtree. */ - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_wots_pk_from_sig( - wots_pk, sig, root, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_WOTS_BYTES; - - /* Compute the leaf node using the WOTS public key. */ - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_thash_WOTS_LEN( - leaf, wots_pk, pub_seed, wots_pk_addr, &hash_state_seeded); - - /* Compute the root node of this subtree. */ - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_compute_root( - root, leaf, idx_leaf, 0, sig, PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_TREE_HEIGHT, - pub_seed, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_TREE_HEIGHT * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_TREE_HEIGHT; - } - - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_destroy_hash_function(&hash_state_seeded); - /* Check if the root node equals the root node in the public key. */ - if (memcmp(root, pub_root, PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N) != 0) { - return -1; - } - - return 0; -} - - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - size_t siglen; - - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_crypto_sign_signature( - sm, &siglen, m, mlen, sk); - - memmove(sm + PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_BYTES, m, mlen); - *smlen = siglen + mlen; - - return 0; -} - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk) { - /* The API caller does not necessarily know what size a signature should be - but SPHINCS+ signatures are always exactly PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_BYTES. */ - if (smlen < PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_BYTES) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - *mlen = smlen - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_BYTES; - - if (PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_crypto_sign_verify( - sm, PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_BYTES, sm + PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_BYTES, *mlen, pk)) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - /* If verification was successful, move the message to the right place. */ - memmove(m, sm + PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_BYTES, *mlen); - - return 0; -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_avx2/thash.h b/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_avx2/thash.h deleted file mode 100644 index 0a8a7ea7f4..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_avx2/thash.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_THASH_H -#define PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_THASH_H - -#include "hash_state.h" - -#include - -void PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_avx2/thash_sha256_robust.c b/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_avx2/thash_sha256_robust.c deleted file mode 100644 index 5c56e52443..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_avx2/thash_sha256_robust.c +++ /dev/null @@ -1,78 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "thash.h" - -#include "sha2.h" -#include "sha256.h" - -/** - * Takes an array of inblocks concatenated arrays of PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N bytes. - */ -static void thash( - unsigned char *out, unsigned char *buf, - const unsigned char *in, unsigned int inblocks, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char outbuf[PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_OUTPUT_BYTES]; - unsigned char *bitmask = buf + PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_ADDR_BYTES + 4; - sha256ctx sha2_state; - unsigned int i; - - memcpy(buf, pub_seed, PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N); - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_compress_address(buf + PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N, addr); - /* MGF1 requires us to have 4 extra bytes in 'buf' */ - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_mgf1(bitmask, inblocks * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N, buf, PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_ADDR_BYTES); - - /* Retrieve precomputed state containing pub_seed */ - sha256_inc_ctx_clone(&sha2_state, &hash_state_seeded->x1); - - for (i = 0; i < inblocks * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N; i++) { - buf[PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_ADDR_BYTES + i] = in[i] ^ bitmask[i]; - } - - sha256_inc_finalize(outbuf, &sha2_state, buf + PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N, - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N); - memcpy(out, outbuf, PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N); -} - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_ADDR_BYTES + 4 + 1 * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N]; - thash(out, buf, in, 1, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_ADDR_BYTES + 4 + 2 * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N]; - thash(out, buf, in, 2, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_ADDR_BYTES + 4 + PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_WOTS_LEN * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N]; - thash(out, buf, in, PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_WOTS_LEN, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_ADDR_BYTES + 4 + PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_FORS_TREES * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N]; - thash(out, buf, in, PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_FORS_TREES, pub_seed, addr, hash_state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_avx2/thash_sha256_robustx8.c b/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_avx2/thash_sha256_robustx8.c deleted file mode 100644 index 41264eeaf9..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_avx2/thash_sha256_robustx8.c +++ /dev/null @@ -1,156 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "sha256.h" -#include "sha256avx.h" -#include "sha256x8.h" -#include "thashx8.h" -#include "utils.h" - -/** - * 8-way parallel version of thash; takes 8x as much input and output - */ -static void thashx8(uint8_t *out0, - uint8_t *out1, - uint8_t *out2, - uint8_t *out3, - uint8_t *out4, - uint8_t *out5, - uint8_t *out6, - uint8_t *out7, - const uint8_t *in0, - const uint8_t *in1, - const uint8_t *in2, - const uint8_t *in3, - const uint8_t *in4, - const uint8_t *in5, - const uint8_t *in6, - const uint8_t *in7, - unsigned int inblocks, - const uint8_t *pub_seed, - uint32_t addrx8[8 * 8], - uint8_t *bufx8, - uint8_t *bitmaskx8, - const hash_state *state_seeded) { - unsigned char outbufx8[8 * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_OUTPUT_BYTES]; - unsigned int i; - sha256ctxx8 ctx; - - (void)pub_seed; /* Suppress an 'unused parameter' warning. */ - - for (i = 0; i < 8; i++) { - memcpy(bufx8 + i * (PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N), - pub_seed, PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N); - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_compress_address(bufx8 + PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N + - i * (PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N), - addrx8 + i * 8); - } - - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_mgf1x8(bitmaskx8, inblocks * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N, - bufx8 + 0 * (PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N), - bufx8 + 1 * (PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N), - bufx8 + 2 * (PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N), - bufx8 + 3 * (PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N), - bufx8 + 4 * (PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N), - bufx8 + 5 * (PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N), - bufx8 + 6 * (PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N), - bufx8 + 7 * (PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N), - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_ADDR_BYTES - ); - - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_sha256_clone_statex8(&ctx, &state_seeded->x8); - - for (i = 0; i < inblocks * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N; i++) { - bufx8[PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_ADDR_BYTES + i + - 0 * (PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N)] = - in0[i] ^ bitmaskx8[i + 0 * (inblocks * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N)]; - bufx8[PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_ADDR_BYTES + i + - 1 * (PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N)] = - in1[i] ^ bitmaskx8[i + 1 * (inblocks * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N)]; - bufx8[PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_ADDR_BYTES + i + - 2 * (PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N)] = - in2[i] ^ bitmaskx8[i + 2 * (inblocks * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N)]; - bufx8[PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_ADDR_BYTES + i + - 3 * (PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N)] = - in3[i] ^ bitmaskx8[i + 3 * (inblocks * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N)]; - bufx8[PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_ADDR_BYTES + i + - 4 * (PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N)] = - in4[i] ^ bitmaskx8[i + 4 * (inblocks * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N)]; - bufx8[PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_ADDR_BYTES + i + - 5 * (PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N)] = - in5[i] ^ bitmaskx8[i + 5 * (inblocks * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N)]; - bufx8[PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_ADDR_BYTES + i + - 6 * (PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N)] = - in6[i] ^ bitmaskx8[i + 6 * (inblocks * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N)]; - bufx8[PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_ADDR_BYTES + i + - 7 * (PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N)] = - in7[i] ^ bitmaskx8[i + 7 * (inblocks * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N)]; - } - - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_sha256_update8x(&ctx, - bufx8 + PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N + 0 * (PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N), - bufx8 + PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N + 1 * (PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N), - bufx8 + PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N + 2 * (PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N), - bufx8 + PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N + 3 * (PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N), - bufx8 + PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N + 4 * (PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N), - bufx8 + PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N + 5 * (PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N), - bufx8 + PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N + 6 * (PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N), - bufx8 + PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N + 7 * (PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N), - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N); - - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_sha256_final8x(&ctx, - outbufx8 + 0 * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 1 * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 2 * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 3 * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 4 * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 5 * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 6 * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 7 * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_OUTPUT_BYTES); - - memcpy(out0, outbufx8 + 0 * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N); - memcpy(out1, outbufx8 + 1 * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N); - memcpy(out2, outbufx8 + 2 * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N); - memcpy(out3, outbufx8 + 3 * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N); - memcpy(out4, outbufx8 + 4 * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N); - memcpy(out5, outbufx8 + 5 * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N); - memcpy(out6, outbufx8 + 6 * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N); - memcpy(out7, outbufx8 + 7 * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N); -} - -#define thash_size_variant(name, size) \ - void PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_thashx8_##name(unsigned char *out0, \ - unsigned char *out1, \ - unsigned char *out2, \ - unsigned char *out3, \ - unsigned char *out4, \ - unsigned char *out5, \ - unsigned char *out6, \ - unsigned char *out7, \ - const unsigned char *in0, \ - const unsigned char *in1, \ - const unsigned char *in2, \ - const unsigned char *in3, \ - const unsigned char *in4, \ - const unsigned char *in5, \ - const unsigned char *in6, \ - const unsigned char *in7, \ - const unsigned char *pub_seed, \ - uint32_t addrx8[8*8], \ - const hash_state *state_seeded) { \ - const unsigned int inblocks = (size); \ - uint8_t bufx8[8*(PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_SHA256_ADDR_BYTES + (size)*PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N)]; \ - uint8_t bitmaskx8[8*((size) * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N)]; \ - thashx8(out0, out1, out2, out3, out4, out5, out6, out7, \ - in0, in1, in2, in3, in4, in5, in6, in7, inblocks, \ - pub_seed, addrx8, bufx8, bitmaskx8, state_seeded); \ - } - -thash_size_variant(1, 1) -thash_size_variant(2, 2) -thash_size_variant(WOTS_LEN, PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_WOTS_LEN) -thash_size_variant(FORS_TREES, PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_FORS_TREES) - -#undef thash_size_variant diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_avx2/thashx8.h b/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_avx2/thashx8.h deleted file mode 100644 index fc1817afb6..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_avx2/thashx8.h +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_THASHX8_H -#define PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_THASHX8_H - -#include - -#include "hash_state.h" -#include "sha256avx.h" - - -#define thashx8_variant(name) \ - void PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_thashx8_##name( \ - unsigned char *out0, \ - unsigned char *out1, \ - unsigned char *out2, \ - unsigned char *out3, \ - unsigned char *out4, \ - unsigned char *out5, \ - unsigned char *out6, \ - unsigned char *out7, \ - const unsigned char *in0, \ - const unsigned char *in1, \ - const unsigned char *in2, \ - const unsigned char *in3, \ - const unsigned char *in4, \ - const unsigned char *in5, \ - const unsigned char *in6, \ - const unsigned char *in7, \ - const unsigned char *pub_seed, \ - uint32_t addrx8[8*8], \ - const hash_state *state_seeded) - - -thashx8_variant(1); -thashx8_variant(2); -thashx8_variant(WOTS_LEN); -thashx8_variant(FORS_TREES); - -#undef thashx8_variant -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_avx2/utils.c b/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_avx2/utils.c deleted file mode 100644 index a63094287e..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_avx2/utils.c +++ /dev/null @@ -1,199 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "hash_state.h" -#include "params.h" -#include "thash.h" -#include "utils.h" - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in) { - - /* Iterate over out in decreasing order, for big-endianness. */ - for (size_t i = outlen; i > 0; i--) { - out[i - 1] = in & 0xff; - in = in >> 8; - } -} - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_bytes_to_ull( - const unsigned char *in, size_t inlen) { - unsigned long long retval = 0; - - for (size_t i = 0; i < inlen; i++) { - retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); - } - return retval; -} - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - uint32_t i; - unsigned char buffer[2 * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N]; - - /* If leaf_idx is odd (last bit = 1), current path element is a right child - and auth_path has to go left. Otherwise it is the other way around. */ - if (leaf_idx & 1) { - memcpy(buffer + PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N, leaf, PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N); - } else { - memcpy(buffer, leaf, PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N); - memcpy(buffer + PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N, auth_path, PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N); - } - auth_path += PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N; - - for (i = 0; i < tree_height - 1; i++) { - leaf_idx >>= 1; - idx_offset >>= 1; - /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_set_tree_height(addr, i + 1); - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_set_tree_index( - addr, leaf_idx + idx_offset); - - /* Pick the right or left neighbor, depending on parity of the node. */ - if (leaf_idx & 1) { - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_thash_2( - buffer + PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N); - } else { - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_thash_2( - buffer, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer + PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N, auth_path, PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N); - } - auth_path += PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N; - } - - /* The last iteration is exceptional; we do not copy an auth_path node. */ - leaf_idx >>= 1; - idx_offset >>= 1; - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_set_tree_height(addr, tree_height); - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_set_tree_index( - addr, leaf_idx + idx_offset); - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_thash_2( - root, buffer, pub_seed, addr, hash_state_seeded); -} - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -static void PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_treehash( - unsigned char *root, unsigned char *auth_path, - unsigned char *stack, unsigned int *heights, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - - unsigned int offset = 0; - uint32_t idx; - uint32_t tree_idx; - - for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { - /* Add the next leaf node to the stack. */ - gen_leaf(stack + offset * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N, - sk_seed, pub_seed, idx + idx_offset, tree_addr, - hash_state_seeded); - offset++; - heights[offset - 1] = 0; - - /* If this is a node we need for the auth path.. */ - if ((leaf_idx ^ 0x1) == idx) { - memcpy(auth_path, stack + (offset - 1)*PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N, PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N); - } - - /* While the top-most nodes are of equal height.. */ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { - /* Compute index of the new node, in the next layer. */ - tree_idx = (idx >> (heights[offset - 1] + 1)); - - /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_set_tree_height( - tree_addr, heights[offset - 1] + 1); - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_set_tree_index( - tree_addr, tree_idx + (idx_offset >> (heights[offset - 1] + 1))); - /* Hash the top-most nodes from the stack together. */ - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_thash_2( - stack + (offset - 2)*PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N, stack + (offset - 2)*PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N, - pub_seed, tree_addr, hash_state_seeded); - offset--; - /* Note that the top-most node is now one layer higher. */ - heights[offset - 1]++; - - /* If this is a node we need for the auth path.. */ - if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_path + heights[offset - 1]*PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N, - stack + (offset - 1)*PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N, PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N); - } - } - } - memcpy(root, stack, PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N); -} - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_FORS_HEIGHT + 1)*PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N]; - unsigned int heights[PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_FORS_HEIGHT + 1]; - - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_FORS_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_TREE_HEIGHT + 1)*PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N]; - unsigned int heights[PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_TREE_HEIGHT + 1]; - - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_TREE_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_avx2/utils.h b/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_avx2/utils.h deleted file mode 100644 index 4cc7cba398..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_avx2/utils.h +++ /dev/null @@ -1,64 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_UTILS_H -#define PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_UTILS_H - -#include "hash_state.h" -#include "params.h" -#include -#include - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in); - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_bytes_to_ull( - const unsigned char *in, size_t inlen); - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -void PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_avx2/utilsx8.c b/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_avx2/utilsx8.c deleted file mode 100644 index 05c39b7d05..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_avx2/utilsx8.c +++ /dev/null @@ -1,172 +0,0 @@ -#include - -#include "address.h" -#include "params.h" -#include "thashx8.h" -#include "utils.h" - -#include "utilsx8.h" - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -static void treehashx8(unsigned char *rootx8, unsigned char *auth_pathx8, - unsigned char *stackx8, unsigned int *heights, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t leaf_idx[8], uint32_t idx_offset[8], - uint32_t tree_height, - void (*gen_leafx8)( - unsigned char * /* leaf0 */, - unsigned char * /* leaf1 */, - unsigned char * /* leaf2 */, - unsigned char * /* leaf3 */, - unsigned char * /* leaf4 */, - unsigned char * /* leaf5 */, - unsigned char * /* leaf6 */, - unsigned char * /* leaf7 */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx0 */, - uint32_t /* addr_idx1 */, - uint32_t /* addr_idx2 */, - uint32_t /* addr_idx3 */, - uint32_t /* addr_idx4 */, - uint32_t /* addr_idx5 */, - uint32_t /* addr_idx6 */, - uint32_t /* addr_idx7 */, - const uint32_t[8] /* tree_addr */, - const hash_state * /* state_seeded */), - uint32_t tree_addrx8[8 * 8], - const hash_state *state_seeded) { - unsigned int offset = 0; - uint32_t idx; - uint32_t tree_idx; - unsigned int j; - - for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { - /* Add the next leaf node to the stack. */ - gen_leafx8(stackx8 + 0 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N + offset * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N, - stackx8 + 1 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N + offset * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N, - stackx8 + 2 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N + offset * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N, - stackx8 + 3 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N + offset * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N, - stackx8 + 4 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N + offset * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N, - stackx8 + 5 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N + offset * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N, - stackx8 + 6 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N + offset * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N, - stackx8 + 7 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N + offset * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N, - sk_seed, pub_seed, - idx + idx_offset[0], - idx + idx_offset[1], - idx + idx_offset[2], - idx + idx_offset[3], - idx + idx_offset[4], - idx + idx_offset[5], - idx + idx_offset[6], - idx + idx_offset[7], - tree_addrx8, - state_seeded); - offset++; - heights[offset - 1] = 0; - - /* If this is a node we need for the auth path.. */ - for (j = 0; j < 8; j++) { - if ((leaf_idx[j] ^ 0x1) == idx) { - memcpy(auth_pathx8 + j * tree_height * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N, - stackx8 + j * (tree_height + 1)*PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N + (offset - 1)*PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N, PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N); - } - } - - /* While the top-most nodes are of equal height.. */ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { - /* Compute index of the new node, in the next layer. */ - tree_idx = (idx >> (heights[offset - 1] + 1)); - - /* Set the address of the node we're creating. */ - for (j = 0; j < 8; j++) { - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_set_tree_height(tree_addrx8 + j * 8, heights[offset - 1] + 1); - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_set_tree_index(tree_addrx8 + j * 8, - tree_idx + (idx_offset[j] >> (heights[offset - 1] + 1))); - } - /* Hash the top-most nodes from the stack together. */ - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_thashx8_2(stackx8 + 0 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N, - stackx8 + 1 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N, - stackx8 + 2 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N, - stackx8 + 3 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N, - stackx8 + 4 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N, - stackx8 + 5 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N, - stackx8 + 6 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N, - stackx8 + 7 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N, - stackx8 + 0 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N, - stackx8 + 1 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N, - stackx8 + 2 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N, - stackx8 + 3 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N, - stackx8 + 4 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N, - stackx8 + 5 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N, - stackx8 + 6 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N, - stackx8 + 7 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N, - pub_seed, tree_addrx8, state_seeded); - offset--; - /* Note that the top-most node is now one layer higher. */ - heights[offset - 1]++; - - /* If this is a node we need for the auth path.. */ - for (j = 0; j < 8; j++) { - if (((leaf_idx[j] >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_pathx8 + j * tree_height * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N + heights[offset - 1]*PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N, - stackx8 + j * (tree_height + 1)*PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N + (offset - 1)*PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N, PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N); - } - } - } - } - - for (j = 0; j < 8; j++) { - memcpy(rootx8 + j * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N, stackx8 + j * (tree_height + 1)*PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N, PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N); - } -} - -/* The wrappers below ensure we used fixed-size buffers on the stack (no VLAs) */ - - -#define treehashx8_variant(name, size) \ - void PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_treehashx8_##name( \ - unsigned char *rootx8, unsigned char *auth_pathx8, \ - const unsigned char *sk_seed, const unsigned char *pub_seed, \ - const uint32_t leaf_idx[8], uint32_t idx_offset[8], \ - void (*gen_leafx8)( \ - unsigned char* /* leaf0 */, \ - unsigned char* /* leaf1 */, \ - unsigned char* /* leaf2 */, \ - unsigned char* /* leaf3 */, \ - unsigned char* /* leaf4 */, \ - unsigned char* /* leaf5 */, \ - unsigned char* /* leaf6 */, \ - unsigned char* /* leaf7 */, \ - const unsigned char* /* sk_seed */, \ - const unsigned char* /* pub_seed */, \ - uint32_t /* addr_idx0 */, \ - uint32_t /* addr_idx1 */, \ - uint32_t /* addr_idx2 */, \ - uint32_t /* addr_idx3 */, \ - uint32_t /* addr_idx4 */, \ - uint32_t /* addr_idx5 */, \ - uint32_t /* addr_idx6 */, \ - uint32_t /* addr_idx7 */, \ - const uint32_t[8] /* tree_addr */, \ - const hash_state* /* state_seeded */), \ - uint32_t tree_addrx8[8*8], \ - const hash_state *state_seeded) \ - { \ - const uint32_t tree_height = (size); \ - unsigned char stackx8[8*((size) + 1)*PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N]; \ - unsigned int heights[(size) + 1]; \ - treehashx8(rootx8, auth_pathx8, stackx8, heights, sk_seed, pub_seed, \ - leaf_idx, idx_offset, tree_height, gen_leafx8, tree_addrx8, state_seeded); \ - } - -treehashx8_variant(FORS_HEIGHT, PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_FORS_HEIGHT) - -#undef treehashx8_variant diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_avx2/utilsx8.h b/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_avx2/utilsx8.h deleted file mode 100644 index 5ce6d63081..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_avx2/utilsx8.h +++ /dev/null @@ -1,46 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_UTILSX8_H -#define PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_UTILSX8_H - -#include - -#include "hash_state.h" -#include "params.h" - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ - -void PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_treehashx8_FORS_HEIGHT( - unsigned char *rootx8, unsigned char *auth_pathx8, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t leaf_idx[8], uint32_t idx_offset[8], - void (*gen_leafx8)( - unsigned char * /* leaf0 */, - unsigned char * /* leaf1 */, - unsigned char * /* leaf2 */, - unsigned char * /* leaf3 */, - unsigned char * /* leaf4 */, - unsigned char * /* leaf5 */, - unsigned char * /* leaf6 */, - unsigned char * /* leaf7 */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx0 */, - uint32_t /* addr_idx1 */, - uint32_t /* addr_idx2 */, - uint32_t /* addr_idx3 */, - uint32_t /* addr_idx4 */, - uint32_t /* addr_idx5 */, - uint32_t /* addr_idx6 */, - uint32_t /* addr_idx7 */, - const uint32_t[8] /* tree_addr */, - const hash_state * /* state_seeded */), - uint32_t tree_addrx8[8 * 8], - const hash_state *state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_avx2/wots.c b/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_avx2/wots.c deleted file mode 100644 index 61f5d54aec..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_avx2/wots.c +++ /dev/null @@ -1,240 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "hash_state.h" -#include "hashx8.h" -#include "params.h" -#include "thash.h" -#include "thashx8.h" -#include "utils.h" -#include "wots.h" - -// TODO clarify address expectations, and make them more uniform. -// TODO i.e. do we expect types to be set already? -// TODO and do we expect modifications or copies? - -/** - * Computes the starting value for a chain, i.e. the secret key. - * Expects the address to be complete up to the chain address. - */ -static void wots_gen_sk(unsigned char *sk, const unsigned char *sk_seed, - uint32_t wots_addr[8], const hash_state *state_seeded) { - /* Make sure that the hash address is actually zeroed. */ - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_set_hash_addr(wots_addr, 0); - - /* Generate sk element. */ - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_prf_addr(sk, sk_seed, wots_addr, state_seeded); -} - -/** - * 8-way parallel version of wots_gen_sk; expects 8x as much space in sk - */ -static void wots_gen_skx8(unsigned char *skx8, const unsigned char *sk_seed, - uint32_t wots_addrx8[8 * 8]) { - unsigned int j; - - /* Make sure that the hash address is actually zeroed. */ - for (j = 0; j < 8; j++) { - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_set_hash_addr(wots_addrx8 + j * 8, 0); - } - - /* Generate sk element. */ - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_prf_addrx8(skx8 + 0 * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N, - skx8 + 1 * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N, - skx8 + 2 * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N, - skx8 + 3 * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N, - skx8 + 4 * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N, - skx8 + 5 * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N, - skx8 + 6 * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N, - skx8 + 7 * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N, - sk_seed, wots_addrx8); -} - -/** - * Computes the chaining function. - * out and in have to be n-byte arrays. - * - * Interprets in as start-th value of the chain. - * addr has to contain the address of the chain. - */ -static void gen_chain(unsigned char *out, const unsigned char *in, - unsigned int start, unsigned int steps, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *state_seeded) { - uint32_t i; - - /* Initialize out with the value at position 'start'. */ - memcpy(out, in, PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N); - - /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_WOTS_W; i++) { - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_set_hash_addr(addr, i); - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_thash_1(out, out, pub_seed, addr, state_seeded); - } -} - -/** - * 8-way parallel version of gen_chain; expects 8x as much space in out, and - * 8x as much space in inx8. Assumes start and step identical across chains. - */ -static void gen_chainx8(unsigned char *outx8, const unsigned char *inx8, - unsigned int start, unsigned int steps, - const unsigned char *pub_seed, uint32_t addrx8[8 * 8], - const hash_state *state_seeded) { - uint32_t i; - unsigned int j; - - /* Initialize outx8 with the value at position 'start'. */ - memcpy(outx8, inx8, 8 * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N); - - /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_WOTS_W; i++) { - for (j = 0; j < 8; j++) { - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_set_hash_addr(addrx8 + j * 8, i); - } - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_thashx8_1(outx8 + 0 * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N, - outx8 + 1 * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N, - outx8 + 2 * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N, - outx8 + 3 * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N, - outx8 + 4 * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N, - outx8 + 5 * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N, - outx8 + 6 * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N, - outx8 + 7 * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N, - outx8 + 0 * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N, - outx8 + 1 * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N, - outx8 + 2 * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N, - outx8 + 3 * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N, - outx8 + 4 * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N, - outx8 + 5 * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N, - outx8 + 6 * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N, - outx8 + 7 * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N, - pub_seed, addrx8, state_seeded); - } -} - -/** - * base_w algorithm as described in draft. - * Interprets an array of bytes as integers in base w. - * This only works when log_w is a divisor of 8. - */ -static void base_w(unsigned int *output, const int out_len, const unsigned char *input) { - int in = 0; - int out = 0; - unsigned char total = 0; - int bits = 0; - int consumed; - - for (consumed = 0; consumed < out_len; consumed++) { - if (bits == 0) { - total = input[in]; - in++; - bits += 8; - } - bits -= PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_WOTS_LOGW; - output[out] = (unsigned int)(total >> bits) & (PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_WOTS_W - 1); - out++; - } -} - -/* Computes the WOTS+ checksum over a message (in base_w). */ -static void wots_checksum(unsigned int *csum_base_w, const unsigned int *msg_base_w) { - unsigned int csum = 0; - unsigned char csum_bytes[(PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_WOTS_LEN2 * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_WOTS_LOGW + 7) / 8]; - unsigned int i; - - /* Compute checksum. */ - for (i = 0; i < PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_WOTS_LEN1; i++) { - csum += PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_WOTS_W - 1 - msg_base_w[i]; - } - - /* Convert checksum to base_w. */ - /* Make sure expected empty zero bits are the least significant bits. */ - csum = csum << (8 - ((PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_WOTS_LEN2 * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_WOTS_LOGW) % 8)); - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); - base_w(csum_base_w, PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_WOTS_LEN2, csum_bytes); -} - -/* Takes a message and derives the matching chain lengths. */ -static void chain_lengths(unsigned int *lengths, const unsigned char *msg) { - base_w(lengths, PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_WOTS_LEN1, msg); - wots_checksum(lengths + PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_WOTS_LEN1, lengths); -} - -/** - * WOTS key generation. Takes a 32 byte sk_seed, expands it to WOTS private key - * elements and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_wots_gen_pk(unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *state_seeded) { - uint32_t i; - unsigned int j; - - uint32_t addrx8[8 * 8]; - unsigned char pkbuf[8 * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N]; - - for (j = 0; j < 8; j++) { - memcpy(addrx8 + j * 8, addr, sizeof(uint32_t) * 8); - } - - /* The last iteration typically does not have complete set of 4 chains, - but because we use pkbuf, this is not an issue -- we still do as many - in parallel as possible. */ - for (i = 0; i < ((PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_WOTS_LEN + 7) & ~0x7); i += 8) { - for (j = 0; j < 8; j++) { - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_set_chain_addr(addrx8 + j * 8, i + j); - } - wots_gen_skx8(pkbuf, sk_seed, addrx8); - gen_chainx8(pkbuf, pkbuf, 0, PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_WOTS_W - 1, pub_seed, addrx8, state_seeded); - for (j = 0; j < 8; j++) { - if (i + j < PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_WOTS_LEN) { - memcpy(pk + (i + j)*PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N, pkbuf + j * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N, PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N); - } - } - } -} - -/** - * Takes a n-byte message and the 32-byte sk_see to compute a signature 'sig'. - */ -void PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_wots_sign(unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_WOTS_LEN; i++) { - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_set_chain_addr(addr, i); - wots_gen_sk(sig + i * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N, sk_seed, addr, state_seeded); - gen_chain(sig + i * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N, sig + i * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N, 0, lengths[i], pub_seed, addr, state_seeded); - } -} - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_WOTS_LEN; i++) { - PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_set_chain_addr(addr, i); - gen_chain(pk + i * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N, sig + i * PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_N, - lengths[i], PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_WOTS_W - 1 - lengths[i], pub_seed, addr, state_seeded); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_avx2/wots.h b/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_avx2/wots.h deleted file mode 100644 index cbd26fea54..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_avx2/wots.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_WOTS_H -#define PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_WOTS_H - -#include "hash_state.h" -#include "params.h" -#include - -/** - * WOTS key generation. Takes a 32 byte seed for the private key, expands it to - * a full WOTS private key and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_wots_gen_pk( - unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -/** - * Takes a n-byte message and the 32-byte seed for the private key to compute a - * signature that is placed at 'sig'. - */ -void PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_wots_sign( - unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *hash_state_seeded); - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHA256192SROBUST_AVX2_wots_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_clean/LICENSE b/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_clean/LICENSE deleted file mode 100644 index 670154e353..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_clean/LICENSE +++ /dev/null @@ -1,116 +0,0 @@ -CC0 1.0 Universal - -Statement of Purpose - -The laws of most jurisdictions throughout the world automatically confer -exclusive Copyright and Related Rights (defined below) upon the creator and -subsequent owner(s) (each and all, an "owner") of an original work of -authorship and/or a database (each, a "Work"). - -Certain owners wish to permanently relinquish those rights to a Work for the -purpose of contributing to a commons of creative, cultural and scientific -works ("Commons") that the public can reliably and without fear of later -claims of infringement build upon, modify, incorporate in other works, reuse -and redistribute as freely as possible in any form whatsoever and for any -purposes, including without limitation commercial purposes. These owners may -contribute to the Commons to promote the ideal of a free culture and the -further production of creative, cultural and scientific works, or to gain -reputation or greater distribution for their Work in part through the use and -efforts of others. - -For these and/or other purposes and motivations, and without any expectation -of additional consideration or compensation, the person associating CC0 with a -Work (the "Affirmer"), to the extent that he or she is an owner of Copyright -and Related Rights in the Work, voluntarily elects to apply CC0 to the Work -and publicly distribute the Work under its terms, with knowledge of his or her -Copyright and Related Rights in the Work and the meaning and intended legal -effect of CC0 on those rights. - -1. Copyright and Related Rights. A Work made available under CC0 may be -protected by copyright and related or neighboring rights ("Copyright and -Related Rights"). Copyright and Related Rights include, but are not limited -to, the following: - - i. the right to reproduce, adapt, distribute, perform, display, communicate, - and translate a Work; - - ii. moral rights retained by the original author(s) and/or performer(s); - - iii. publicity and privacy rights pertaining to a person's image or likeness - depicted in a Work; - - iv. rights protecting against unfair competition in regards to a Work, - subject to the limitations in paragraph 4(a), below; - - v. rights protecting the extraction, dissemination, use and reuse of data in - a Work; - - vi. database rights (such as those arising under Directive 96/9/EC of the - European Parliament and of the Council of 11 March 1996 on the legal - protection of databases, and under any national implementation thereof, - including any amended or successor version of such directive); and - - vii. other similar, equivalent or corresponding rights throughout the world - based on applicable law or treaty, and any national implementations thereof. - -2. Waiver. To the greatest extent permitted by, but not in contravention of, -applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and -unconditionally waives, abandons, and surrenders all of Affirmer's Copyright -and Related Rights and associated claims and causes of action, whether now -known or unknown (including existing as well as future claims and causes of -action), in the Work (i) in all territories worldwide, (ii) for the maximum -duration provided by applicable law or treaty (including future time -extensions), (iii) in any current or future medium and for any number of -copies, and (iv) for any purpose whatsoever, including without limitation -commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes -the Waiver for the benefit of each member of the public at large and to the -detriment of Affirmer's heirs and successors, fully intending that such Waiver -shall not be subject to revocation, rescission, cancellation, termination, or -any other legal or equitable action to disrupt the quiet enjoyment of the Work -by the public as contemplated by Affirmer's express Statement of Purpose. - -3. Public License Fallback. Should any part of the Waiver for any reason be -judged legally invalid or ineffective under applicable law, then the Waiver -shall be preserved to the maximum extent permitted taking into account -Affirmer's express Statement of Purpose. In addition, to the extent the Waiver -is so judged Affirmer hereby grants to each affected person a royalty-free, -non transferable, non sublicensable, non exclusive, irrevocable and -unconditional license to exercise Affirmer's Copyright and Related Rights in -the Work (i) in all territories worldwide, (ii) for the maximum duration -provided by applicable law or treaty (including future time extensions), (iii) -in any current or future medium and for any number of copies, and (iv) for any -purpose whatsoever, including without limitation commercial, advertising or -promotional purposes (the "License"). The License shall be deemed effective as -of the date CC0 was applied by Affirmer to the Work. Should any part of the -License for any reason be judged legally invalid or ineffective under -applicable law, such partial invalidity or ineffectiveness shall not -invalidate the remainder of the License, and in such case Affirmer hereby -affirms that he or she will not (i) exercise any of his or her remaining -Copyright and Related Rights in the Work or (ii) assert any associated claims -and causes of action with respect to the Work, in either case contrary to -Affirmer's express Statement of Purpose. - -4. Limitations and Disclaimers. - - a. No trademark or patent rights held by Affirmer are waived, abandoned, - surrendered, licensed or otherwise affected by this document. - - b. Affirmer offers the Work as-is and makes no representations or warranties - of any kind concerning the Work, express, implied, statutory or otherwise, - including without limitation warranties of title, merchantability, fitness - for a particular purpose, non infringement, or the absence of latent or - other defects, accuracy, or the present or absence of errors, whether or not - discoverable, all to the greatest extent permissible under applicable law. - - c. Affirmer disclaims responsibility for clearing rights of other persons - that may apply to the Work or any use thereof, including without limitation - any person's Copyright and Related Rights in the Work. Further, Affirmer - disclaims responsibility for obtaining any necessary consents, permissions - or other rights required for any use of the Work. - - d. Affirmer understands and acknowledges that Creative Commons is not a - party to this document and has no duty or obligation with respect to this - CC0 or use of the Work. - -For more information, please see - diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_clean/address.c b/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_clean/address.c deleted file mode 100644 index 0da3ca4bcf..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_clean/address.c +++ /dev/null @@ -1,78 +0,0 @@ -#include - -#include "address.h" -#include "params.h" -#include "utils.h" - -void PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]) { - int i; - - for (i = 0; i < 8; i++) { - PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_ull_to_bytes( - bytes + i * 4, 4, addr[i]); - } -} - -void PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_set_layer_addr( - uint32_t addr[8], uint32_t layer) { - addr[0] = layer; -} - -void PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_set_tree_addr( - uint32_t addr[8], uint64_t tree) { - addr[1] = 0; - addr[2] = (uint32_t) (tree >> 32); - addr[3] = (uint32_t) tree; -} - -void PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_set_type( - uint32_t addr[8], uint32_t type) { - addr[4] = type; -} - -void PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; -} - -/* These functions are used for OTS addresses. */ - -void PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_set_keypair_addr( - uint32_t addr[8], uint32_t keypair) { - addr[5] = keypair; -} - -void PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; - out[5] = in[5]; -} - -void PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_set_chain_addr( - uint32_t addr[8], uint32_t chain) { - addr[6] = chain; -} - -void PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_set_hash_addr( - uint32_t addr[8], uint32_t hash) { - addr[7] = hash; -} - -/* These functions are used for all hash tree addresses (including FORS). */ - -void PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_set_tree_height( - uint32_t addr[8], uint32_t tree_height) { - addr[6] = tree_height; -} - -void PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_set_tree_index( - uint32_t addr[8], uint32_t tree_index) { - addr[7] = tree_index; -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_clean/address.h b/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_clean/address.h deleted file mode 100644 index f354877cad..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_clean/address.h +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_ADDRESS_H -#define PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_ADDRESS_H - -#include - -#define PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_ADDR_TYPE_WOTS 0 -#define PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_ADDR_TYPE_WOTSPK 1 -#define PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_ADDR_TYPE_HASHTREE 2 -#define PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_ADDR_TYPE_FORSTREE 3 -#define PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_ADDR_TYPE_FORSPK 4 - -void PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]); - -void PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_set_layer_addr( - uint32_t addr[8], uint32_t layer); - -void PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_set_tree_addr( - uint32_t addr[8], uint64_t tree); - -void PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_set_type( - uint32_t addr[8], uint32_t type); - -/* Copies the layer and tree part of one address into the other */ -void PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for WOTS and FORS addresses. */ - -void PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_set_keypair_addr( - uint32_t addr[8], uint32_t keypair); - -void PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_set_chain_addr( - uint32_t addr[8], uint32_t chain); - -void PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_set_hash_addr( - uint32_t addr[8], uint32_t hash); - -void PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for all hash tree addresses (including FORS). */ - -void PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_set_tree_height( - uint32_t addr[8], uint32_t tree_height); - -void PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_set_tree_index( - uint32_t addr[8], uint32_t tree_index); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_clean/api.h b/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_clean/api.h deleted file mode 100644 index 676cf6dedc..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_clean/api.h +++ /dev/null @@ -1,81 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_API_H -#define PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_API_H - -#include -#include - - - -#define PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_CRYPTO_ALGNAME "SPHINCS+" - -#define PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_CRYPTO_SECRETKEYBYTES 96 -#define PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_CRYPTO_PUBLICKEYBYTES 48 -#define PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_CRYPTO_BYTES 16224 -#define PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_CRYPTO_SEEDBYTES 72 - - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_clean/fors.c b/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_clean/fors.c deleted file mode 100644 index 8ff15d59d5..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_clean/fors.c +++ /dev/null @@ -1,161 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "fors.h" -#include "hash.h" -#include "hash_state.h" -#include "thash.h" -#include "utils.h" - -static void fors_gen_sk(unsigned char *sk, const unsigned char *sk_seed, - uint32_t fors_leaf_addr[8], const hash_state *hash_state_seeded) { - PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_prf_addr( - sk, sk_seed, fors_leaf_addr, hash_state_seeded); -} - -static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, - const unsigned char *pub_seed, - uint32_t fors_leaf_addr[8], - const hash_state *hash_state_seeded) { - PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_thash_1( - leaf, sk, pub_seed, fors_leaf_addr, hash_state_seeded); -} - -static void fors_gen_leaf(unsigned char *leaf, const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx, const uint32_t fors_tree_addr[8], - const hash_state *hash_state_seeded) { - uint32_t fors_leaf_addr[8] = {0}; - - /* Only copy the parts that must be kept in fors_leaf_addr. */ - PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_copy_keypair_addr( - fors_leaf_addr, fors_tree_addr); - PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_set_type( - fors_leaf_addr, PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_set_tree_index( - fors_leaf_addr, addr_idx); - - fors_gen_sk(leaf, sk_seed, fors_leaf_addr, hash_state_seeded); - fors_sk_to_leaf(leaf, leaf, pub_seed, fors_leaf_addr, hash_state_seeded); -} - -/** - * Interprets m as PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_FORS_HEIGHT-bit unsigned integers. - * Assumes m contains at least PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_FORS_TREES bits. - * Assumes indices has space for PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_FORS_TREES integers. - */ -static void message_to_indices(uint32_t *indices, const unsigned char *m) { - unsigned int i, j; - unsigned int offset = 0; - - for (i = 0; i < PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_FORS_TREES; i++) { - indices[i] = 0; - for (j = 0; j < PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_FORS_HEIGHT; j++) { - indices[i] ^= (((uint32_t)m[offset >> 3] >> (offset & 0x7)) & 0x1) << j; - offset++; - } - } -} - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_fors_sign( - unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *hash_state_seeded) { - uint32_t indices[PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_FORS_TREES]; - unsigned char roots[PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_FORS_TREES * PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_N]; - uint32_t fors_tree_addr[8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_copy_keypair_addr( - fors_tree_addr, fors_addr); - PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_copy_keypair_addr( - fors_pk_addr, fors_addr); - - PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_set_type( - fors_tree_addr, PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_set_type( - fors_pk_addr, PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_FORS_TREES; i++) { - idx_offset = i * (1 << PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_FORS_HEIGHT); - - PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_set_tree_height( - fors_tree_addr, 0); - PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_set_tree_index( - fors_tree_addr, indices[i] + idx_offset); - - /* Include the secret key part that produces the selected leaf node. */ - fors_gen_sk(sig, sk_seed, fors_tree_addr, hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_N; - - /* Compute the authentication path for this leaf node. */ - PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_treehash_FORS_HEIGHT( - roots + i * PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_N, sig, sk_seed, pub_seed, - indices[i], idx_offset, fors_gen_leaf, fors_tree_addr, - hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_N * PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_thash_FORS_TREES( - pk, roots, pub_seed, fors_pk_addr, hash_state_seeded); -} - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_fors_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, const uint32_t fors_addr[8], - const hash_state *hash_state_seeded) { - uint32_t indices[PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_FORS_TREES]; - unsigned char roots[PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_FORS_TREES * PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_N]; - unsigned char leaf[PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_N]; - uint32_t fors_tree_addr[8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_copy_keypair_addr(fors_tree_addr, fors_addr); - PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_copy_keypair_addr(fors_pk_addr, fors_addr); - - PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_set_type(fors_tree_addr, PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_set_type(fors_pk_addr, PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_FORS_TREES; i++) { - idx_offset = i * (1 << PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_FORS_HEIGHT); - - PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_set_tree_height(fors_tree_addr, 0); - PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Derive the leaf from the included secret key part. */ - fors_sk_to_leaf(leaf, sig, pub_seed, fors_tree_addr, hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_N; - - /* Derive the corresponding root node of this tree. */ - PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_compute_root(roots + i * PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_N, leaf, indices[i], idx_offset, sig, - PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_FORS_HEIGHT, pub_seed, fors_tree_addr, hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_N * PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_thash_FORS_TREES(pk, roots, pub_seed, fors_pk_addr, hash_state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_clean/fors.h b/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_clean/fors.h deleted file mode 100644 index b4036312ab..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_clean/fors.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_FORS_H -#define PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_FORS_H - -#include - -#include "hash_state.h" -#include "params.h" - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_fors_sign( - unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *hash_state_seeded); - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_fors_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, const uint32_t fors_addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_clean/hash.h b/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_clean/hash.h deleted file mode 100644 index 379c336261..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_clean/hash.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_HASH_H -#define PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_HASH_H - -#include "hash_state.h" - -#include -#include - -void PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_initialize_hash_function( - hash_state *hash_state_seeded, - const unsigned char *pub_seed, const unsigned char *sk_seed); - -void PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_destroy_hash_function(hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_clean/hash_sha256.c b/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_clean/hash_sha256.c deleted file mode 100644 index 88f7c47ebd..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_clean/hash_sha256.c +++ /dev/null @@ -1,162 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "utils.h" - -#include "sha2.h" -#include "sha256.h" - -/* For SHA256, there is no immediate reason to initialize at the start, - so this function is an empty operation. */ -void PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_initialize_hash_function( - hash_state *hash_state_seeded, - const unsigned char *pub_seed, const unsigned char *sk_seed) { - PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_seed_state(hash_state_seeded, pub_seed); - (void)sk_seed; /* Suppress an 'unused parameter' warning. */ -} - -/* Clean up hash state */ -void PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_destroy_hash_function(hash_state *hash_state_seeded) { - sha256_inc_ctx_release(hash_state_seeded); -} - -/* - * Computes PRF(key, addr), given a secret key of PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_N bytes and an address - */ -void PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded) { - unsigned char buf[PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_N + PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_SHA256_ADDR_BYTES]; - unsigned char outbuf[PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_SHA256_OUTPUT_BYTES]; - - memcpy(buf, key, PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_N); - PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_compress_address(buf + PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_N, addr); - - sha256(outbuf, buf, PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_N + PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_SHA256_ADDR_BYTES); - memcpy(out, outbuf, PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_N); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} - -/** - * Computes the message-dependent randomness R, using a secret seed as a key - * for HMAC, and an optional randomization value prefixed to the message. - * This requires m to have at least PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_SHA256_BLOCK_BYTES + PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_N space - * available in front of the pointer, i.e. before the message to use for the - * prefix. This is necessary to prevent having to move the message around (and - * allocate memory for it). - */ -void PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, const hash_state *hash_state_seeded) { - unsigned char buf[PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_SHA256_BLOCK_BYTES + PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_SHA256_OUTPUT_BYTES]; - sha256ctx state; - int i; - - /* This implements HMAC-SHA256 */ - for (i = 0; i < PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_N; i++) { - buf[i] = 0x36 ^ sk_prf[i]; - } - memset(buf + PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_N, 0x36, PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_N); - - sha256_inc_init(&state); - sha256_inc_blocks(&state, buf, 1); - - memcpy(buf, optrand, PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_N); - - /* If optrand + message cannot fill up an entire block */ - if (PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_N + mlen < PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_SHA256_BLOCK_BYTES) { - memcpy(buf + PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_N, m, mlen); - sha256_inc_finalize(buf + PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_SHA256_BLOCK_BYTES, &state, - buf, mlen + PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_N); - } - /* Otherwise first fill a block, so that finalize only uses the message */ - else { - memcpy(buf + PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_N, m, PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_N); - sha256_inc_blocks(&state, buf, 1); - - m += PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_N; - mlen -= PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_N; - sha256_inc_finalize(buf + PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_SHA256_BLOCK_BYTES, &state, m, mlen); - } - - for (i = 0; i < PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_N; i++) { - buf[i] = 0x5c ^ sk_prf[i]; - } - memset(buf + PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_N, 0x5c, PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_N); - - sha256(buf, buf, PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_SHA256_BLOCK_BYTES + PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_SHA256_OUTPUT_BYTES); - memcpy(R, buf, PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_N); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} - -/** - * Computes the message hash using R, the public key, and the message. - * Outputs the message digest and the index of the leaf. The index is split in - * the tree index and the leaf index, for convenient copying to an address. - */ -void PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded) { -#define PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_TREE_BITS (PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_TREE_HEIGHT * (PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_D - 1)) -#define PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_TREE_BYTES ((PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_TREE_BITS + 7) / 8) -#define PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_LEAF_BITS PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_TREE_HEIGHT -#define PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_LEAF_BYTES ((PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_LEAF_BITS + 7) / 8) -#define PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_DGST_BYTES (PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_FORS_MSG_BYTES + PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_TREE_BYTES + PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_LEAF_BYTES) - - unsigned char seed[PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_SHA256_OUTPUT_BYTES + 4]; - - /* Round to nearest multiple of PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_SHA256_BLOCK_BYTES */ -#define PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_INBLOCKS (((PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_N + PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_PK_BYTES + PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_SHA256_BLOCK_BYTES - 1) & \ - -PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_SHA256_BLOCK_BYTES) / PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_SHA256_BLOCK_BYTES) - unsigned char inbuf[PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_INBLOCKS * PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_SHA256_BLOCK_BYTES]; - - unsigned char buf[PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_DGST_BYTES]; - unsigned char *bufp = buf; - sha256ctx state; - - sha256_inc_init(&state); - - memcpy(inbuf, R, PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_N); - memcpy(inbuf + PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_N, pk, PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_PK_BYTES); - - /* If R + pk + message cannot fill up an entire block */ - if (PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_N + PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_PK_BYTES + mlen < PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_INBLOCKS * PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_SHA256_BLOCK_BYTES) { - memcpy(inbuf + PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_N + PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_PK_BYTES, m, mlen); - sha256_inc_finalize(seed, &state, inbuf, PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_N + PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_PK_BYTES + mlen); - } - /* Otherwise first fill a block, so that finalize only uses the message */ - else { - memcpy(inbuf + PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_N + PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_PK_BYTES, m, - PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_INBLOCKS * PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_N - PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_PK_BYTES); - sha256_inc_blocks(&state, inbuf, PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_INBLOCKS); - - m += PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_INBLOCKS * PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_N - PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_PK_BYTES; - mlen -= PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_INBLOCKS * PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_N - PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_PK_BYTES; - sha256_inc_finalize(seed, &state, m, mlen); - } - - /* By doing this in two steps, we prevent hashing the message twice; - otherwise each iteration in MGF1 would hash the message again. */ - PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_mgf1(bufp, PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_DGST_BYTES, seed, PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_SHA256_OUTPUT_BYTES); - - memcpy(digest, bufp, PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_FORS_MSG_BYTES); - bufp += PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_FORS_MSG_BYTES; - - *tree = PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_bytes_to_ull(bufp, PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_TREE_BYTES); - *tree &= (~(uint64_t)0) >> (64 - PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_TREE_BITS); - bufp += PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_TREE_BYTES; - - *leaf_idx = (uint32_t)PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_bytes_to_ull( - bufp, PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_LEAF_BYTES); - *leaf_idx &= (~(uint32_t)0) >> (32 - PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_LEAF_BITS); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_clean/hash_state.h b/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_clean/hash_state.h deleted file mode 100644 index 19fc335e27..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_clean/hash_state.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef SPX_HASH_STATE_H -#define SPX_HASH_STATE_H - -/** - * Defines the type of the hash function state. - * - * Don't be fooled into thinking this instance of SPHINCS+ isn't stateless! - * - * From Section 7.2.2 from the SPHINCS+ round-2 specification: - * - * Each of the instances of the tweakable hash function take PK.seed as its - * first input, which is constant for a given key pair – and, thus, across - * a single signature. This leads to a lot of redundant computation. To remedy - * this, we pad PK.seed to the length of a full 64-byte SHA-256 input block. - * Because of the Merkle-Damgård construction that underlies SHA-256, this - * allows for reuse of the intermediate SHA-256 state after the initial call to - * the compression function which improves performance. - * - * We pass this hash state around in functions, because otherwise we need to - * have a global variable. - */ - -#include "sha2.h" -#define hash_state sha256ctx - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_clean/params.h b/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_clean/params.h deleted file mode 100644 index 39da769454..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_clean/params.h +++ /dev/null @@ -1,53 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_PARAMS_H -#define PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_PARAMS_H - -/* Hash output length in bytes. */ -#define PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_N 24 -/* Height of the hypertree. */ -#define PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_FULL_HEIGHT 63 -/* Number of subtree layer. */ -#define PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_D 7 -/* FORS tree dimensions. */ -#define PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_FORS_HEIGHT 14 -#define PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_FORS_TREES 17 -/* Winternitz parameter, */ -#define PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_WOTS_W 16 - -/* The hash function is defined by linking a different hash.c file, as opposed - to setting a #define constant. */ - -/* For clarity */ -#define PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_ADDR_BYTES 32 - -/* WOTS parameters. */ -#define PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_WOTS_LOGW 4 - -#define PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_WOTS_LEN1 (8 * PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_N / PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_WOTS_LOGW) - -/* PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#define PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_WOTS_LEN2 3 - -#define PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_WOTS_LEN (PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_WOTS_LEN1 + PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_WOTS_LEN2) -#define PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_WOTS_BYTES (PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_WOTS_LEN * PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_N) -#define PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_WOTS_PK_BYTES PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_WOTS_BYTES - -/* Subtree size. */ -#define PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_TREE_HEIGHT (PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_FULL_HEIGHT / PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_D) - -/* FORS parameters. */ -#define PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_FORS_MSG_BYTES ((PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_FORS_TREES + 7) / 8) -#define PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_FORS_BYTES ((PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_FORS_HEIGHT + 1) * PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_FORS_TREES * PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_N) -#define PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_FORS_PK_BYTES PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_N - -/* Resulting SPX sizes. */ -#define PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_BYTES (PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_N + PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_FORS_BYTES + PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_D * PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_WOTS_BYTES +\ - PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_FULL_HEIGHT * PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_N) -#define PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_PK_BYTES (2 * PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_N) -#define PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_SK_BYTES (2 * PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_N + PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_PK_BYTES) - -/* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ -#define PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_OPTRAND_BYTES 32 - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_clean/sha256.c b/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_clean/sha256.c deleted file mode 100644 index ca42a31e86..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_clean/sha256.c +++ /dev/null @@ -1,71 +0,0 @@ -/* Based on the public domain implementation in - * crypto_hash/sha512/ref/ from http://bench.cr.yp.to/supercop.html - * by D. J. Bernstein */ - -#include -#include -#include - -#include "sha2.h" -#include "sha256.h" -#include "utils.h" - -/* - * Compresses an address to a 22-byte sequence. - * This reduces the number of required SHA256 compression calls, as the last - * block of input is padded with at least 65 bits. - */ -void PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_compress_address(unsigned char *out, const uint32_t addr[8]) { - PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_ull_to_bytes(out, 1, addr[0]); /* drop 3 bytes of the layer field */ - PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_ull_to_bytes(out + 1, 4, addr[2]); /* drop the highest tree address word */ - PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_ull_to_bytes(out + 5, 4, addr[3]); - PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_ull_to_bytes(out + 9, 1, addr[4]); /* drop 3 bytes of the type field */ - PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_ull_to_bytes(out + 10, 4, addr[5]); - PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_ull_to_bytes(out + 14, 4, addr[6]); - PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_ull_to_bytes(out + 18, 4, addr[7]); -} - -/** - * Requires 'input_plus_four_bytes' to have 'inlen' + 4 bytes, so that the last - * four bytes can be used for the counter. Typically 'input' is merely a seed. - * Outputs outlen number of bytes - */ -void PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_mgf1( - unsigned char *out, unsigned long outlen, - unsigned char *input_plus_four_bytes, unsigned long inlen) { - unsigned char outbuf[PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_SHA256_OUTPUT_BYTES]; - unsigned long i; - - /* While we can fit in at least another full block of SHA256 output.. */ - for (i = 0; (i + 1)*PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_SHA256_OUTPUT_BYTES <= outlen; i++) { - PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_ull_to_bytes(input_plus_four_bytes + inlen, 4, i); - sha256(out, input_plus_four_bytes, inlen + 4); - out += PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_SHA256_OUTPUT_BYTES; - } - /* Until we cannot anymore, and we fill the remainder. */ - if (outlen > i * PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_SHA256_OUTPUT_BYTES) { - PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_ull_to_bytes(input_plus_four_bytes + inlen, 4, i); - sha256(outbuf, input_plus_four_bytes, inlen + 4); - memcpy(out, outbuf, outlen - i * PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_SHA256_OUTPUT_BYTES); - } -} - - -/** - * Absorb the constant pub_seed using one round of the compression function - * This initializes hash_state_seeded, which can then be reused in thash - **/ -void PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_seed_state(sha256ctx *hash_state_seeded, const unsigned char *pub_seed) { - uint8_t block[PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_SHA256_BLOCK_BYTES]; - size_t i; - - for (i = 0; i < PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_N; ++i) { - block[i] = pub_seed[i]; - } - for (i = PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_N; i < PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_SHA256_BLOCK_BYTES; ++i) { - block[i] = 0; - } - - sha256_inc_init(hash_state_seeded); - sha256_inc_blocks(hash_state_seeded, block, 1); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_clean/sha256.h b/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_clean/sha256.h deleted file mode 100644 index 011c2dca83..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_clean/sha256.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_SHA256_H -#define PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_SHA256_H - -#define PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_SHA256_BLOCK_BYTES 64 -#define PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_SHA256_OUTPUT_BYTES 32 /* This does not necessarily equal PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_N */ -#define PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_SHA256_ADDR_BYTES 22 - -#include -#include - -#include "sha2.h" - -void PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_compress_address(unsigned char *out, const uint32_t addr[8]); - -void PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_mgf1( - unsigned char *out, unsigned long outlen, - unsigned char *input_plus_four_bytes, unsigned long inlen); - -void PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_seed_state(sha256ctx *hash_state_seeded, const unsigned char *pub_seed); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_clean/sign.c b/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_clean/sign.c deleted file mode 100644 index 7216f9c6d0..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_clean/sign.c +++ /dev/null @@ -1,356 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "api.h" -#include "fors.h" -#include "hash.h" -#include "hash_state.h" -#include "params.h" -#include "randombytes.h" -#include "thash.h" -#include "utils.h" -#include "wots.h" - -/** - * Computes the leaf at a given address. First generates the WOTS key pair, - * then computes leaf by hashing horizontally. - */ -static void wots_gen_leaf(unsigned char *leaf, const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx, const uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - unsigned char pk[PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_WOTS_BYTES]; - uint32_t wots_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_set_type( - wots_addr, PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_set_type( - wots_pk_addr, PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_ADDR_TYPE_WOTSPK); - - PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_set_keypair_addr( - wots_addr, addr_idx); - PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_wots_gen_pk( - pk, sk_seed, pub_seed, wots_addr, hash_state_seeded); - - PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_copy_keypair_addr( - wots_pk_addr, wots_addr); - PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_thash_WOTS_LEN( - leaf, pk, pub_seed, wots_pk_addr, hash_state_seeded); -} - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_crypto_sign_secretkeybytes(void) { - return PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_CRYPTO_SECRETKEYBYTES; -} - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_crypto_sign_publickeybytes(void) { - return PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_CRYPTO_PUBLICKEYBYTES; -} - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_crypto_sign_bytes(void) { - return PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_CRYPTO_BYTES; -} - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_crypto_sign_seedbytes(void) { - return PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_CRYPTO_SEEDBYTES; -} - -/* - * Generates an SPX key pair given a seed of length - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed) { - /* We do not need the auth path in key generation, but it simplifies the - code to have just one treehash routine that computes both root and path - in one function. */ - unsigned char auth_path[PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_TREE_HEIGHT * PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_N]; - uint32_t top_tree_addr[8] = {0}; - hash_state hash_state_seeded; - - PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_set_layer_addr( - top_tree_addr, PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_D - 1); - PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_set_type( - top_tree_addr, PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_ADDR_TYPE_HASHTREE); - - /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ - memcpy(sk, seed, PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_CRYPTO_SEEDBYTES); - - memcpy(pk, sk + 2 * PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_N, PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_initialize_hash_function(&hash_state_seeded, pk, sk); - - /* Compute root node of the top-most subtree. */ - PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_treehash_TREE_HEIGHT( - sk + 3 * PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_N, auth_path, sk, sk + 2 * PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_N, 0, 0, - wots_gen_leaf, top_tree_addr, &hash_state_seeded); - - memcpy(pk + PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_N, sk + 3 * PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_N, PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_N); - - PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_destroy_hash_function(&hash_state_seeded); - return 0; -} - -/* - * Generates an SPX key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk) { - unsigned char seed[PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_CRYPTO_SEEDBYTES]; - randombytes(seed, PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_CRYPTO_SEEDBYTES); - PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_crypto_sign_seed_keypair( - pk, sk, seed); - - return 0; -} - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - const unsigned char *sk_seed = sk; - const unsigned char *sk_prf = sk + PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_N; - const unsigned char *pk = sk + 2 * PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_N; - const unsigned char *pub_seed = pk; - - unsigned char optrand[PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_N]; - unsigned char mhash[PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_FORS_MSG_BYTES]; - unsigned char root[PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_N]; - uint32_t i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - - hash_state hash_state_seeded; - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_initialize_hash_function( - &hash_state_seeded, - pub_seed, sk_seed); - - PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_set_type( - wots_addr, PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_set_type( - tree_addr, PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_ADDR_TYPE_HASHTREE); - - /* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ - randombytes(optrand, PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_N); - /* Compute the digest randomization value. */ - PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_gen_message_random( - sig, sk_prf, optrand, m, mlen, &hash_state_seeded); - - /* Derive the message digest and leaf index from R, PK and M. */ - PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_N; - - PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); - - /* Sign the message hash using FORS. */ - PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_fors_sign( - sig, root, mhash, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_FORS_BYTES; - - for (i = 0; i < PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_D; i++) { - PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_set_tree_addr(tree_addr, tree); - - PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); - - /* Compute a WOTS signature. */ - PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_wots_sign( - sig, root, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_WOTS_BYTES; - - /* Compute the authentication path for the used WOTS leaf. */ - PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_treehash_TREE_HEIGHT( - root, sig, sk_seed, pub_seed, idx_leaf, 0, - wots_gen_leaf, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_TREE_HEIGHT * PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_TREE_HEIGHT; - } - - *siglen = PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_BYTES; - - PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_destroy_hash_function(&hash_state_seeded); - return 0; -} - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk) { - const unsigned char *pub_seed = pk; - const unsigned char *pub_root = pk + PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_N; - unsigned char mhash[PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_FORS_MSG_BYTES]; - unsigned char wots_pk[PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_WOTS_BYTES]; - unsigned char root[PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_N]; - unsigned char leaf[PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_N]; - unsigned int i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - hash_state hash_state_seeded; - - if (siglen != PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_BYTES) { - return -1; - } - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_initialize_hash_function( - &hash_state_seeded, - pub_seed, NULL); - - PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_set_type( - wots_addr, PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_set_type( - tree_addr, PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_ADDR_TYPE_HASHTREE); - PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_set_type( - wots_pk_addr, PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_ADDR_TYPE_WOTSPK); - - /* Derive the message digest and leaf index from R || PK || M. */ - /* The additional PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_N is a result of the hash domain separator. */ - PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_N; - - /* Layer correctly defaults to 0, so no need to set_layer_addr */ - PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); - - PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_fors_pk_from_sig( - root, sig, mhash, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_FORS_BYTES; - - /* For each subtree.. */ - for (i = 0; i < PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_D; i++) { - PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_set_tree_addr(tree_addr, tree); - - PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); - - PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_copy_keypair_addr( - wots_pk_addr, wots_addr); - - /* The WOTS public key is only correct if the signature was correct. */ - /* Initially, root is the FORS pk, but on subsequent iterations it is - the root of the subtree below the currently processed subtree. */ - PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_wots_pk_from_sig( - wots_pk, sig, root, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_WOTS_BYTES; - - /* Compute the leaf node using the WOTS public key. */ - PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_thash_WOTS_LEN( - leaf, wots_pk, pub_seed, wots_pk_addr, &hash_state_seeded); - - /* Compute the root node of this subtree. */ - PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_compute_root( - root, leaf, idx_leaf, 0, sig, PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_TREE_HEIGHT, - pub_seed, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_TREE_HEIGHT * PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_TREE_HEIGHT; - } - - PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_destroy_hash_function(&hash_state_seeded); - /* Check if the root node equals the root node in the public key. */ - if (memcmp(root, pub_root, PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_N) != 0) { - return -1; - } - - return 0; -} - - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - size_t siglen; - - PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_crypto_sign_signature( - sm, &siglen, m, mlen, sk); - - memmove(sm + PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_BYTES, m, mlen); - *smlen = siglen + mlen; - - return 0; -} - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk) { - /* The API caller does not necessarily know what size a signature should be - but SPHINCS+ signatures are always exactly PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_BYTES. */ - if (smlen < PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_BYTES) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - *mlen = smlen - PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_BYTES; - - if (PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_crypto_sign_verify( - sm, PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_BYTES, sm + PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_BYTES, *mlen, pk)) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - /* If verification was successful, move the message to the right place. */ - memmove(m, sm + PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_BYTES, *mlen); - - return 0; -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_clean/thash.h b/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_clean/thash.h deleted file mode 100644 index 1b6f5f8282..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_clean/thash.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_THASH_H -#define PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_THASH_H - -#include "hash_state.h" - -#include - -void PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_clean/thash_sha256_robust.c b/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_clean/thash_sha256_robust.c deleted file mode 100644 index 996c7b3223..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_clean/thash_sha256_robust.c +++ /dev/null @@ -1,82 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "thash.h" - -#include "sha2.h" -#include "sha256.h" - -/** - * Takes an array of inblocks concatenated arrays of PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_N bytes. - */ -static void PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_thash( - unsigned char *out, unsigned char *buf, - const unsigned char *in, unsigned int inblocks, - const unsigned char *pub_seed, uint32_t addr[8], - const sha256ctx *hash_state_seeded) { - - unsigned char outbuf[PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_SHA256_OUTPUT_BYTES]; - unsigned char *bitmask = buf + PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_N + PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_SHA256_ADDR_BYTES + 4; - sha256ctx sha2_state; - unsigned int i; - - memcpy(buf, pub_seed, PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_N); - PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_compress_address(buf + PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_N, addr); - /* MGF1 requires us to have 4 extra bytes in 'buf' */ - PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_mgf1(bitmask, inblocks * PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_N, buf, PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_N + PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_SHA256_ADDR_BYTES); - - /* Retrieve precomputed state containing pub_seed */ - sha256_inc_ctx_clone(&sha2_state, hash_state_seeded); - - for (i = 0; i < inblocks * PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_N; i++) { - buf[PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_N + PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_SHA256_ADDR_BYTES + i] = in[i] ^ bitmask[i]; - } - - sha256_inc_finalize(outbuf, &sha2_state, buf + PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_N, - PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_N); - memcpy(out, outbuf, PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_N); -} - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const sha256ctx *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_N + PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_SHA256_ADDR_BYTES + 4 + 1 * PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_N]; - PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_thash( - out, buf, in, 1, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const sha256ctx *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_N + PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_SHA256_ADDR_BYTES + 4 + 2 * PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_N]; - PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_thash( - out, buf, in, 2, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const sha256ctx *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_N + PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_SHA256_ADDR_BYTES + 4 + PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_WOTS_LEN * PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_N]; - PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_thash( - out, buf, in, PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_WOTS_LEN, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const sha256ctx *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_N + PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_SHA256_ADDR_BYTES + 4 + PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_FORS_TREES * PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_N]; - PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_thash( - out, buf, in, PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_FORS_TREES, pub_seed, addr, hash_state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_clean/utils.c b/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_clean/utils.c deleted file mode 100644 index eb0125e8af..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_clean/utils.c +++ /dev/null @@ -1,199 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "hash_state.h" -#include "params.h" -#include "thash.h" -#include "utils.h" - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in) { - - /* Iterate over out in decreasing order, for big-endianness. */ - for (size_t i = outlen; i > 0; i--) { - out[i - 1] = in & 0xff; - in = in >> 8; - } -} - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_bytes_to_ull( - const unsigned char *in, size_t inlen) { - unsigned long long retval = 0; - - for (size_t i = 0; i < inlen; i++) { - retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); - } - return retval; -} - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - uint32_t i; - unsigned char buffer[2 * PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_N]; - - /* If leaf_idx is odd (last bit = 1), current path element is a right child - and auth_path has to go left. Otherwise it is the other way around. */ - if (leaf_idx & 1) { - memcpy(buffer + PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_N, leaf, PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_N); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_N); - } else { - memcpy(buffer, leaf, PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_N); - memcpy(buffer + PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_N, auth_path, PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_N); - } - auth_path += PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_N; - - for (i = 0; i < tree_height - 1; i++) { - leaf_idx >>= 1; - idx_offset >>= 1; - /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_set_tree_height(addr, i + 1); - PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_set_tree_index( - addr, leaf_idx + idx_offset); - - /* Pick the right or left neighbor, depending on parity of the node. */ - if (leaf_idx & 1) { - PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_thash_2( - buffer + PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_N, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_N); - } else { - PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_thash_2( - buffer, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer + PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_N, auth_path, PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_N); - } - auth_path += PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_N; - } - - /* The last iteration is exceptional; we do not copy an auth_path node. */ - leaf_idx >>= 1; - idx_offset >>= 1; - PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_set_tree_height(addr, tree_height); - PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_set_tree_index( - addr, leaf_idx + idx_offset); - PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_thash_2( - root, buffer, pub_seed, addr, hash_state_seeded); -} - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -static void PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_treehash( - unsigned char *root, unsigned char *auth_path, - unsigned char *stack, unsigned int *heights, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - - unsigned int offset = 0; - uint32_t idx; - uint32_t tree_idx; - - for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { - /* Add the next leaf node to the stack. */ - gen_leaf(stack + offset * PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_N, - sk_seed, pub_seed, idx + idx_offset, tree_addr, - hash_state_seeded); - offset++; - heights[offset - 1] = 0; - - /* If this is a node we need for the auth path.. */ - if ((leaf_idx ^ 0x1) == idx) { - memcpy(auth_path, stack + (offset - 1)*PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_N, PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_N); - } - - /* While the top-most nodes are of equal height.. */ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { - /* Compute index of the new node, in the next layer. */ - tree_idx = (idx >> (heights[offset - 1] + 1)); - - /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_set_tree_height( - tree_addr, heights[offset - 1] + 1); - PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_set_tree_index( - tree_addr, tree_idx + (idx_offset >> (heights[offset - 1] + 1))); - /* Hash the top-most nodes from the stack together. */ - PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_thash_2( - stack + (offset - 2)*PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_N, stack + (offset - 2)*PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_N, - pub_seed, tree_addr, hash_state_seeded); - offset--; - /* Note that the top-most node is now one layer higher. */ - heights[offset - 1]++; - - /* If this is a node we need for the auth path.. */ - if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_path + heights[offset - 1]*PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_N, - stack + (offset - 1)*PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_N, PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_N); - } - } - } - memcpy(root, stack, PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_N); -} - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_FORS_HEIGHT + 1)*PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_N]; - unsigned int heights[PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_FORS_HEIGHT + 1]; - - PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_FORS_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_TREE_HEIGHT + 1)*PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_N]; - unsigned int heights[PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_TREE_HEIGHT + 1]; - - PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_TREE_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_clean/utils.h b/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_clean/utils.h deleted file mode 100644 index 4c4868d6b7..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_clean/utils.h +++ /dev/null @@ -1,64 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_UTILS_H -#define PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_UTILS_H - -#include "hash_state.h" -#include "params.h" -#include -#include - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in); - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_bytes_to_ull( - const unsigned char *in, size_t inlen); - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -void PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_clean/wots.c b/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_clean/wots.c deleted file mode 100644 index 097716d4de..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_clean/wots.c +++ /dev/null @@ -1,167 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "hash_state.h" -#include "params.h" -#include "thash.h" -#include "utils.h" -#include "wots.h" - -// TODO clarify address expectations, and make them more uniform. -// TODO i.e. do we expect types to be set already? -// TODO and do we expect modifications or copies? - -/** - * Computes the starting value for a chain, i.e. the secret key. - * Expects the address to be complete up to the chain address. - */ -static void wots_gen_sk(unsigned char *sk, const unsigned char *sk_seed, - uint32_t wots_addr[8], - const hash_state *hash_state_seeded) { - /* Make sure that the hash address is actually zeroed. */ - PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_set_hash_addr(wots_addr, 0); - - /* Generate sk element. */ - PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_prf_addr(sk, sk_seed, wots_addr, hash_state_seeded); -} - -/** - * Computes the chaining function. - * out and in have to be n-byte arrays. - * - * Interprets in as start-th value of the chain. - * addr has to contain the address of the chain. - */ -static void gen_chain(unsigned char *out, const unsigned char *in, - unsigned int start, unsigned int steps, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - uint32_t i; - - /* Initialize out with the value at position 'start'. */ - memcpy(out, in, PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_N); - - /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_WOTS_W; i++) { - PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_set_hash_addr(addr, i); - PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_thash_1( - out, out, pub_seed, addr, hash_state_seeded); - } -} - -/** - * base_w algorithm as described in draft. - * Interprets an array of bytes as integers in base w. - * This only works when log_w is a divisor of 8. - */ -static void base_w(unsigned int *output, const size_t out_len, - const unsigned char *input) { - size_t in = 0; - size_t out = 0; - unsigned char total = 0; - unsigned int bits = 0; - size_t consumed; - - for (consumed = 0; consumed < out_len; consumed++) { - if (bits == 0) { - total = input[in]; - in++; - bits += 8; - } - bits -= PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_WOTS_LOGW; - output[out] = (unsigned int)((total >> bits) & (PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_WOTS_W - 1)); - out++; - } -} - -/* Computes the WOTS+ checksum over a message (in base_w). */ -static void wots_checksum(unsigned int *csum_base_w, - const unsigned int *msg_base_w) { - unsigned int csum = 0; - unsigned char csum_bytes[(PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_WOTS_LEN2 * PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_WOTS_LOGW + 7) / 8]; - unsigned int i; - - /* Compute checksum. */ - for (i = 0; i < PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_WOTS_LEN1; i++) { - csum += PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_WOTS_W - 1 - msg_base_w[i]; - } - - /* Convert checksum to base_w. */ - /* Make sure expected empty zero bits are the least significant bits. */ - csum = csum << (8 - ((PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_WOTS_LEN2 * PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_WOTS_LOGW) % 8)); - PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_ull_to_bytes( - csum_bytes, sizeof(csum_bytes), csum); - base_w(csum_base_w, PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_WOTS_LEN2, csum_bytes); -} - -/* Takes a message and derives the matching chain lengths. */ -static void chain_lengths(unsigned int *lengths, const unsigned char *msg) { - base_w(lengths, PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_WOTS_LEN1, msg); - wots_checksum(lengths + PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_WOTS_LEN1, lengths); -} - -/** - * WOTS key generation. Takes a 32 byte sk_seed, expands it to WOTS private key - * elements and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_wots_gen_pk( - unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - uint32_t i; - - for (i = 0; i < PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_WOTS_LEN; i++) { - PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_set_chain_addr(addr, i); - wots_gen_sk(pk + i * PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_N, sk_seed, addr, hash_state_seeded); - gen_chain(pk + i * PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_N, pk + i * PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_N, - 0, PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_WOTS_W - 1, pub_seed, addr, hash_state_seeded); - } -} - -/** - * Takes a n-byte message and the 32-byte sk_see to compute a signature 'sig'. - */ -void PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_wots_sign( - unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *hash_state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_WOTS_LEN; i++) { - PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_set_chain_addr(addr, i); - wots_gen_sk(sig + i * PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_N, sk_seed, addr, hash_state_seeded); - gen_chain(sig + i * PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_N, sig + i * PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_N, 0, lengths[i], pub_seed, addr, hash_state_seeded); - } -} - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_wots_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_WOTS_LEN; i++) { - PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_set_chain_addr(addr, i); - gen_chain(pk + i * PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_N, sig + i * PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_N, - lengths[i], PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_WOTS_W - 1 - lengths[i], pub_seed, addr, - hash_state_seeded); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_clean/wots.h b/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_clean/wots.h deleted file mode 100644 index 7178ae1b01..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192s-robust_clean/wots.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_WOTS_H -#define PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_WOTS_H - -#include "hash_state.h" -#include "params.h" -#include - -/** - * WOTS key generation. Takes a 32 byte seed for the private key, expands it to - * a full WOTS private key and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_wots_gen_pk( - unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -/** - * Takes a n-byte message and the 32-byte seed for the private key to compute a - * signature that is placed at 'sig'. - */ -void PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_wots_sign( - unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *hash_state_seeded); - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_wots_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_avx2/LICENSE b/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_avx2/LICENSE deleted file mode 100644 index 670154e353..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_avx2/LICENSE +++ /dev/null @@ -1,116 +0,0 @@ -CC0 1.0 Universal - -Statement of Purpose - -The laws of most jurisdictions throughout the world automatically confer -exclusive Copyright and Related Rights (defined below) upon the creator and -subsequent owner(s) (each and all, an "owner") of an original work of -authorship and/or a database (each, a "Work"). - -Certain owners wish to permanently relinquish those rights to a Work for the -purpose of contributing to a commons of creative, cultural and scientific -works ("Commons") that the public can reliably and without fear of later -claims of infringement build upon, modify, incorporate in other works, reuse -and redistribute as freely as possible in any form whatsoever and for any -purposes, including without limitation commercial purposes. These owners may -contribute to the Commons to promote the ideal of a free culture and the -further production of creative, cultural and scientific works, or to gain -reputation or greater distribution for their Work in part through the use and -efforts of others. - -For these and/or other purposes and motivations, and without any expectation -of additional consideration or compensation, the person associating CC0 with a -Work (the "Affirmer"), to the extent that he or she is an owner of Copyright -and Related Rights in the Work, voluntarily elects to apply CC0 to the Work -and publicly distribute the Work under its terms, with knowledge of his or her -Copyright and Related Rights in the Work and the meaning and intended legal -effect of CC0 on those rights. - -1. Copyright and Related Rights. A Work made available under CC0 may be -protected by copyright and related or neighboring rights ("Copyright and -Related Rights"). Copyright and Related Rights include, but are not limited -to, the following: - - i. the right to reproduce, adapt, distribute, perform, display, communicate, - and translate a Work; - - ii. moral rights retained by the original author(s) and/or performer(s); - - iii. publicity and privacy rights pertaining to a person's image or likeness - depicted in a Work; - - iv. rights protecting against unfair competition in regards to a Work, - subject to the limitations in paragraph 4(a), below; - - v. rights protecting the extraction, dissemination, use and reuse of data in - a Work; - - vi. database rights (such as those arising under Directive 96/9/EC of the - European Parliament and of the Council of 11 March 1996 on the legal - protection of databases, and under any national implementation thereof, - including any amended or successor version of such directive); and - - vii. other similar, equivalent or corresponding rights throughout the world - based on applicable law or treaty, and any national implementations thereof. - -2. Waiver. To the greatest extent permitted by, but not in contravention of, -applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and -unconditionally waives, abandons, and surrenders all of Affirmer's Copyright -and Related Rights and associated claims and causes of action, whether now -known or unknown (including existing as well as future claims and causes of -action), in the Work (i) in all territories worldwide, (ii) for the maximum -duration provided by applicable law or treaty (including future time -extensions), (iii) in any current or future medium and for any number of -copies, and (iv) for any purpose whatsoever, including without limitation -commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes -the Waiver for the benefit of each member of the public at large and to the -detriment of Affirmer's heirs and successors, fully intending that such Waiver -shall not be subject to revocation, rescission, cancellation, termination, or -any other legal or equitable action to disrupt the quiet enjoyment of the Work -by the public as contemplated by Affirmer's express Statement of Purpose. - -3. Public License Fallback. Should any part of the Waiver for any reason be -judged legally invalid or ineffective under applicable law, then the Waiver -shall be preserved to the maximum extent permitted taking into account -Affirmer's express Statement of Purpose. In addition, to the extent the Waiver -is so judged Affirmer hereby grants to each affected person a royalty-free, -non transferable, non sublicensable, non exclusive, irrevocable and -unconditional license to exercise Affirmer's Copyright and Related Rights in -the Work (i) in all territories worldwide, (ii) for the maximum duration -provided by applicable law or treaty (including future time extensions), (iii) -in any current or future medium and for any number of copies, and (iv) for any -purpose whatsoever, including without limitation commercial, advertising or -promotional purposes (the "License"). The License shall be deemed effective as -of the date CC0 was applied by Affirmer to the Work. Should any part of the -License for any reason be judged legally invalid or ineffective under -applicable law, such partial invalidity or ineffectiveness shall not -invalidate the remainder of the License, and in such case Affirmer hereby -affirms that he or she will not (i) exercise any of his or her remaining -Copyright and Related Rights in the Work or (ii) assert any associated claims -and causes of action with respect to the Work, in either case contrary to -Affirmer's express Statement of Purpose. - -4. Limitations and Disclaimers. - - a. No trademark or patent rights held by Affirmer are waived, abandoned, - surrendered, licensed or otherwise affected by this document. - - b. Affirmer offers the Work as-is and makes no representations or warranties - of any kind concerning the Work, express, implied, statutory or otherwise, - including without limitation warranties of title, merchantability, fitness - for a particular purpose, non infringement, or the absence of latent or - other defects, accuracy, or the present or absence of errors, whether or not - discoverable, all to the greatest extent permissible under applicable law. - - c. Affirmer disclaims responsibility for clearing rights of other persons - that may apply to the Work or any use thereof, including without limitation - any person's Copyright and Related Rights in the Work. Further, Affirmer - disclaims responsibility for obtaining any necessary consents, permissions - or other rights required for any use of the Work. - - d. Affirmer understands and acknowledges that Creative Commons is not a - party to this document and has no duty or obligation with respect to this - CC0 or use of the Work. - -For more information, please see - diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_avx2/address.c b/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_avx2/address.c deleted file mode 100644 index 9731a7540e..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_avx2/address.c +++ /dev/null @@ -1,78 +0,0 @@ -#include - -#include "address.h" -#include "params.h" -#include "utils.h" - -void PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]) { - int i; - - for (i = 0; i < 8; i++) { - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_ull_to_bytes( - bytes + i * 4, 4, addr[i]); - } -} - -void PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_set_layer_addr( - uint32_t addr[8], uint32_t layer) { - addr[0] = layer; -} - -void PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_set_tree_addr( - uint32_t addr[8], uint64_t tree) { - addr[1] = 0; - addr[2] = (uint32_t) (tree >> 32); - addr[3] = (uint32_t) tree; -} - -void PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_set_type( - uint32_t addr[8], uint32_t type) { - addr[4] = type; -} - -void PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; -} - -/* These functions are used for OTS addresses. */ - -void PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_set_keypair_addr( - uint32_t addr[8], uint32_t keypair) { - addr[5] = keypair; -} - -void PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; - out[5] = in[5]; -} - -void PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_set_chain_addr( - uint32_t addr[8], uint32_t chain) { - addr[6] = chain; -} - -void PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_set_hash_addr( - uint32_t addr[8], uint32_t hash) { - addr[7] = hash; -} - -/* These functions are used for all hash tree addresses (including FORS). */ - -void PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_set_tree_height( - uint32_t addr[8], uint32_t tree_height) { - addr[6] = tree_height; -} - -void PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_set_tree_index( - uint32_t addr[8], uint32_t tree_index) { - addr[7] = tree_index; -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_avx2/address.h b/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_avx2/address.h deleted file mode 100644 index 2963af316e..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_avx2/address.h +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_ADDRESS_H -#define PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_ADDRESS_H - -#include - -#define PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_ADDR_TYPE_WOTS 0 -#define PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_ADDR_TYPE_WOTSPK 1 -#define PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_ADDR_TYPE_HASHTREE 2 -#define PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_ADDR_TYPE_FORSTREE 3 -#define PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_ADDR_TYPE_FORSPK 4 - -void PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]); - -void PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_set_layer_addr( - uint32_t addr[8], uint32_t layer); - -void PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_set_tree_addr( - uint32_t addr[8], uint64_t tree); - -void PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_set_type( - uint32_t addr[8], uint32_t type); - -/* Copies the layer and tree part of one address into the other */ -void PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for WOTS and FORS addresses. */ - -void PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_set_keypair_addr( - uint32_t addr[8], uint32_t keypair); - -void PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_set_chain_addr( - uint32_t addr[8], uint32_t chain); - -void PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_set_hash_addr( - uint32_t addr[8], uint32_t hash); - -void PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for all hash tree addresses (including FORS). */ - -void PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_set_tree_height( - uint32_t addr[8], uint32_t tree_height); - -void PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_set_tree_index( - uint32_t addr[8], uint32_t tree_index); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_avx2/api.h b/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_avx2/api.h deleted file mode 100644 index 9a553735b4..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_avx2/api.h +++ /dev/null @@ -1,81 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_API_H -#define PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_API_H - -#include -#include - - - -#define PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_CRYPTO_ALGNAME "SPHINCS+" - -#define PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_CRYPTO_SECRETKEYBYTES 96 -#define PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_CRYPTO_PUBLICKEYBYTES 48 -#define PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_CRYPTO_BYTES 16224 -#define PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_CRYPTO_SEEDBYTES 72 - - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_avx2/fors.c b/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_avx2/fors.c deleted file mode 100644 index 1afc681b10..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_avx2/fors.c +++ /dev/null @@ -1,240 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "fors.h" -#include "hash.h" -#include "hashx8.h" -#include "thash.h" -#include "thashx8.h" -#include "utils.h" -#include "utilsx8.h" - -static void fors_gen_skx8(unsigned char *sk0, - unsigned char *sk1, - unsigned char *sk2, - unsigned char *sk3, - unsigned char *sk4, - unsigned char *sk5, - unsigned char *sk6, - unsigned char *sk7, const unsigned char *sk_seed, - uint32_t fors_leaf_addrx8[8 * 8]) { - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_prf_addrx8(sk0, sk1, sk2, sk3, sk4, sk5, sk6, sk7, - sk_seed, fors_leaf_addrx8); -} - -static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, - const unsigned char *pub_seed, - uint32_t fors_leaf_addr[8], - const hash_state *state_seeded) { - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_thash_1(leaf, sk, pub_seed, fors_leaf_addr, state_seeded); -} - -static void fors_sk_to_leafx8(unsigned char *leaf0, - unsigned char *leaf1, - unsigned char *leaf2, - unsigned char *leaf3, - unsigned char *leaf4, - unsigned char *leaf5, - unsigned char *leaf6, - unsigned char *leaf7, - const unsigned char *sk0, - const unsigned char *sk1, - const unsigned char *sk2, - const unsigned char *sk3, - const unsigned char *sk4, - const unsigned char *sk5, - const unsigned char *sk6, - const unsigned char *sk7, - const unsigned char *pub_seed, - uint32_t fors_leaf_addrx8[8 * 8], - const hash_state *state_seeded) { - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_thashx8_1(leaf0, leaf1, leaf2, leaf3, leaf4, leaf5, leaf6, leaf7, - sk0, sk1, sk2, sk3, sk4, sk5, sk6, sk7, - pub_seed, fors_leaf_addrx8, state_seeded); -} - -static void fors_gen_leafx8(unsigned char *leaf0, - unsigned char *leaf1, - unsigned char *leaf2, - unsigned char *leaf3, - unsigned char *leaf4, - unsigned char *leaf5, - unsigned char *leaf6, - unsigned char *leaf7, - const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx0, - uint32_t addr_idx1, - uint32_t addr_idx2, - uint32_t addr_idx3, - uint32_t addr_idx4, - uint32_t addr_idx5, - uint32_t addr_idx6, - uint32_t addr_idx7, - const uint32_t fors_tree_addr[8], - const hash_state *state_seeded) { - uint32_t fors_leaf_addrx8[8 * 8] = {0}; - unsigned int j; - - /* Only copy the parts that must be kept in fors_leaf_addrx8. */ - for (j = 0; j < 8; j++) { - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_copy_keypair_addr(fors_leaf_addrx8 + j * 8, fors_tree_addr); - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_set_type(fors_leaf_addrx8 + j * 8, PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_ADDR_TYPE_FORSTREE); - } - - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_set_tree_index(fors_leaf_addrx8 + 0 * 8, addr_idx0); - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_set_tree_index(fors_leaf_addrx8 + 1 * 8, addr_idx1); - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_set_tree_index(fors_leaf_addrx8 + 2 * 8, addr_idx2); - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_set_tree_index(fors_leaf_addrx8 + 3 * 8, addr_idx3); - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_set_tree_index(fors_leaf_addrx8 + 4 * 8, addr_idx4); - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_set_tree_index(fors_leaf_addrx8 + 5 * 8, addr_idx5); - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_set_tree_index(fors_leaf_addrx8 + 6 * 8, addr_idx6); - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_set_tree_index(fors_leaf_addrx8 + 7 * 8, addr_idx7); - - fors_gen_skx8(leaf0, leaf1, leaf2, leaf3, leaf4, leaf5, leaf6, leaf7, - sk_seed, fors_leaf_addrx8); - fors_sk_to_leafx8(leaf0, leaf1, leaf2, leaf3, leaf4, leaf5, leaf6, leaf7, - leaf0, leaf1, leaf2, leaf3, leaf4, leaf5, leaf6, leaf7, - pub_seed, fors_leaf_addrx8, state_seeded); -} - -/** - * Interprets m as PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_FORS_HEIGHT-bit unsigned integers. - * Assumes m contains at least PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_FORS_TREES bits. - * Assumes indices has space for PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_FORS_TREES integers. - */ -static void message_to_indices(uint32_t *indices, const unsigned char *m) { - unsigned int i, j; - unsigned int offset = 0; - - for (i = 0; i < PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_FORS_TREES; i++) { - indices[i] = 0; - for (j = 0; j < PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_FORS_HEIGHT; j++) { - indices[i] ^= (((uint32_t)m[offset >> 3] >> (offset & 0x7)) & 0x1) << j; - offset++; - } - } -} - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_fors_sign( - unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], - const hash_state *state_seeded) { - /* Round up to multiple of 8 to prevent out-of-bounds for x8 parallelism */ - uint32_t indices[(PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_FORS_TREES + 7) & ~7] = {0}; - unsigned char roots[((PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_FORS_TREES + 7) & ~7) * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N]; - /* Sign to a buffer, since we may not have a nice multiple of 8 and would - otherwise overrun the signature. */ - unsigned char sigbufx8[8 * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N * (1 + PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_FORS_HEIGHT)]; - uint32_t fors_tree_addrx8[8 * 8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset[8] = {0}; - unsigned int i, j; - - for (j = 0; j < 8; j++) { - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_copy_keypair_addr(fors_tree_addrx8 + j * 8, fors_addr); - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_set_type(fors_tree_addrx8 + j * 8, PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_ADDR_TYPE_FORSTREE); - } - - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_copy_keypair_addr(fors_pk_addr, fors_addr); - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_set_type(fors_pk_addr, PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < ((PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_FORS_TREES + 7) & ~0x7); i += 8) { - for (j = 0; j < 8; j++) { - if (i + j < PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_FORS_TREES) { - idx_offset[j] = (i + j) * (1 << PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_FORS_HEIGHT); - - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_set_tree_height(fors_tree_addrx8 + j * 8, 0); - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_set_tree_index(fors_tree_addrx8 + j * 8, - indices[i + j] + idx_offset[j]); - } - } - - /* Include the secret key part that produces the selected leaf nodes. */ - fors_gen_skx8(sigbufx8 + 0 * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N, - sigbufx8 + 1 * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N, - sigbufx8 + 2 * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N, - sigbufx8 + 3 * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N, - sigbufx8 + 4 * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N, - sigbufx8 + 5 * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N, - sigbufx8 + 6 * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N, - sigbufx8 + 7 * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N, - sk_seed, fors_tree_addrx8); - - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_treehashx8_FORS_HEIGHT( - roots + i * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N, sigbufx8 + 8 * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N, sk_seed, pub_seed, - &indices[i], idx_offset, fors_gen_leafx8, fors_tree_addrx8, - state_seeded); - - for (j = 0; j < 8; j++) { - if (i + j < PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_FORS_TREES) { - memcpy(sig, sigbufx8 + j * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N, PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N); - memcpy(sig + PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N, - sigbufx8 + 8 * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N + j * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_FORS_HEIGHT, - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_FORS_HEIGHT); - sig += PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N * (1 + PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_FORS_HEIGHT); - } - } - } - - /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_thash_FORS_TREES(pk, roots, pub_seed, fors_pk_addr, state_seeded); -} - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, - const uint32_t fors_addr[8], - const hash_state *state_seeded) { - uint32_t indices[PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_FORS_TREES]; - unsigned char roots[PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_FORS_TREES * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N]; - unsigned char leaf[PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N]; - uint32_t fors_tree_addr[8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_copy_keypair_addr(fors_tree_addr, fors_addr); - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_copy_keypair_addr(fors_pk_addr, fors_addr); - - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_set_type(fors_tree_addr, PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_set_type(fors_pk_addr, PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_FORS_TREES; i++) { - idx_offset = i * (1 << PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_FORS_HEIGHT); - - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_set_tree_height(fors_tree_addr, 0); - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Derive the leaf from the included secret key part. */ - fors_sk_to_leaf(leaf, sig, pub_seed, fors_tree_addr, state_seeded); - sig += PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N; - - /* Derive the corresponding root node of this tree. */ - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_compute_root(roots + i * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N, leaf, indices[i], idx_offset, - sig, PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_FORS_HEIGHT, pub_seed, fors_tree_addr, state_seeded); - sig += PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_thash_FORS_TREES(pk, roots, pub_seed, fors_pk_addr, state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_avx2/fors.h b/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_avx2/fors.h deleted file mode 100644 index 833e79839b..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_avx2/fors.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_FORS_H -#define PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_FORS_H - -#include - -#include "hash_state.h" -#include "params.h" - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_fors_sign( - unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *hash_state_seeded); - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_fors_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, const uint32_t fors_addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_avx2/hash.h b/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_avx2/hash.h deleted file mode 100644 index dd1da3821c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_avx2/hash.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_HASH_H -#define PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_HASH_H - -#include "hash_state.h" - -#include -#include - -void PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_initialize_hash_function( - hash_state *hash_state_seeded, - const unsigned char *pub_seed, const unsigned char *sk_seed); - -void PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_destroy_hash_function(hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_avx2/hash_sha256.c b/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_avx2/hash_sha256.c deleted file mode 100644 index 40301ba13f..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_avx2/hash_sha256.c +++ /dev/null @@ -1,166 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "utils.h" - -#include "sha2.h" -#include "sha256.h" -#include "sha256x8.h" - -/** - * Initializes the hash function states - */ -void PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_initialize_hash_function( - hash_state *hash_state_seeded, - const unsigned char *pub_seed, const unsigned char *sk_seed) { - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_seed_state(&hash_state_seeded->x1, pub_seed); - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_seed_statex8(&hash_state_seeded->x8, pub_seed); - (void)sk_seed; /* Suppress an 'unused parameter' warning. */ -} - -/** - * Cleans up the hash function states - */ -void PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_destroy_hash_function(hash_state *hash_state_seeded) { - sha256_inc_ctx_release(&hash_state_seeded->x1); -} - -/* - * Computes PRF(key, addr), given a secret key of PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N bytes and an address - */ -void PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_prf_addr(unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded) { - unsigned char buf[PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_ADDR_BYTES]; - unsigned char outbuf[PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_OUTPUT_BYTES]; - - memcpy(buf, key, PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N); - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_compress_address(buf + PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N, addr); - - sha256(outbuf, buf, PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_ADDR_BYTES); - memcpy(out, outbuf, PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} - -/** - * Computes the message-dependent randomness R, using a secret seed as a key - * for HMAC, and an optional randomization value prefixed to the message. - * This requires m to have at least PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_BLOCK_BYTES + PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N space - * available in front of the pointer, i.e. before the message to use for the - * prefix. This is necessary to prevent having to move the message around (and - * allocate memory for it). - */ -void PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, const hash_state *hash_state_seeded) { - unsigned char buf[PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_BLOCK_BYTES + PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_OUTPUT_BYTES]; - sha256ctx state; - int i; - - /* This implements HMAC-SHA256 */ - for (i = 0; i < PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N; i++) { - buf[i] = 0x36 ^ sk_prf[i]; - } - memset(buf + PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N, 0x36, PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N); - - sha256_inc_init(&state); - sha256_inc_blocks(&state, buf, 1); - - memcpy(buf, optrand, PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N); - - /* If optrand + message cannot fill up an entire block */ - if (PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N + mlen < PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_BLOCK_BYTES) { - memcpy(buf + PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N, m, mlen); - sha256_inc_finalize(buf + PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_BLOCK_BYTES, &state, - buf, mlen + PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N); - } - /* Otherwise first fill a block, so that finalize only uses the message */ - else { - memcpy(buf + PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N, m, PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N); - sha256_inc_blocks(&state, buf, 1); - - m += PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N; - mlen -= PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N; - sha256_inc_finalize(buf + PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_BLOCK_BYTES, &state, m, mlen); - } - - for (i = 0; i < PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N; i++) { - buf[i] = 0x5c ^ sk_prf[i]; - } - memset(buf + PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N, 0x5c, PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N); - - sha256(buf, buf, PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_BLOCK_BYTES + PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_OUTPUT_BYTES); - memcpy(R, buf, PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} - -/** - * Computes the message hash using R, the public key, and the message. - * Outputs the message digest and the index of the leaf. The index is split in - * the tree index and the leaf index, for convenient copying to an address. - */ -void PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded) { -#define PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_TREE_BITS (PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_TREE_HEIGHT * (PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_D - 1)) -#define PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_TREE_BYTES ((PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_TREE_BITS + 7) / 8) -#define PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_LEAF_BITS PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_TREE_HEIGHT -#define PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_LEAF_BYTES ((PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_LEAF_BITS + 7) / 8) -#define PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_DGST_BYTES (PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_FORS_MSG_BYTES + PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_TREE_BYTES + PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_LEAF_BYTES) - - unsigned char seed[PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_OUTPUT_BYTES + 4]; - - /* Round to nearest multiple of PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_BLOCK_BYTES */ -#define PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_INBLOCKS (((PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_PK_BYTES + PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_BLOCK_BYTES - 1) & \ - -PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_BLOCK_BYTES) / PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_BLOCK_BYTES) - unsigned char inbuf[PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_INBLOCKS * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_BLOCK_BYTES]; - - unsigned char buf[PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_DGST_BYTES]; - unsigned char *bufp = buf; - sha256ctx state; - - sha256_inc_init(&state); - - memcpy(inbuf, R, PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N); - memcpy(inbuf + PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N, pk, PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_PK_BYTES); - - /* If R + pk + message cannot fill up an entire block */ - if (PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_PK_BYTES + mlen < PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_INBLOCKS * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_BLOCK_BYTES) { - memcpy(inbuf + PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_PK_BYTES, m, mlen); - sha256_inc_finalize(seed, &state, inbuf, PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_PK_BYTES + mlen); - } - /* Otherwise first fill a block, so that finalize only uses the message */ - else { - memcpy(inbuf + PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_PK_BYTES, m, - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_INBLOCKS * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_PK_BYTES); - sha256_inc_blocks(&state, inbuf, PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_INBLOCKS); - - m += PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_INBLOCKS * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_PK_BYTES; - mlen -= PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_INBLOCKS * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_PK_BYTES; - sha256_inc_finalize(seed, &state, m, mlen); - } - - /* By doing this in two steps, we prevent hashing the message twice; - otherwise each iteration in MGF1 would hash the message again. */ - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_mgf1(bufp, PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_DGST_BYTES, seed, PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_OUTPUT_BYTES); - - memcpy(digest, bufp, PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_FORS_MSG_BYTES); - bufp += PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_FORS_MSG_BYTES; - - *tree = PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_bytes_to_ull(bufp, PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_TREE_BYTES); - *tree &= (~(uint64_t)0) >> (64 - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_TREE_BITS); - bufp += PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_TREE_BYTES; - - *leaf_idx = (uint32_t)PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_bytes_to_ull( - bufp, PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_LEAF_BYTES); - *leaf_idx &= (~(uint32_t)0) >> (32 - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_LEAF_BITS); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_avx2/hash_sha256x8.c b/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_avx2/hash_sha256x8.c deleted file mode 100644 index 835ff826a2..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_avx2/hash_sha256x8.c +++ /dev/null @@ -1,61 +0,0 @@ -#include -#include - -#include "address.h" -#include "hashx8.h" -#include "params.h" -#include "sha256.h" -#include "sha256avx.h" -#include "sha256x8.h" -#include "utils.h" - -/* - * 8-way parallel version of prf_addr; takes 8x as much input and output - */ -void PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_prf_addrx8(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7, - const unsigned char *key, - const uint32_t addrx8[8 * 8]) { - unsigned char bufx8[8 * (PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_ADDR_BYTES)]; - unsigned char outbufx8[8 * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_OUTPUT_BYTES]; - unsigned int j; - - for (j = 0; j < 8; j++) { - memcpy(bufx8 + j * (PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_ADDR_BYTES), key, PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N); - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_compress_address(bufx8 + PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N + j * (PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_ADDR_BYTES), - addrx8 + j * 8); - } - - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_sha256x8(outbufx8 + 0 * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 1 * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 2 * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 3 * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 4 * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 5 * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 6 * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 7 * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - bufx8 + 0 * (PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_ADDR_BYTES), - bufx8 + 1 * (PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_ADDR_BYTES), - bufx8 + 2 * (PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_ADDR_BYTES), - bufx8 + 3 * (PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_ADDR_BYTES), - bufx8 + 4 * (PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_ADDR_BYTES), - bufx8 + 5 * (PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_ADDR_BYTES), - bufx8 + 6 * (PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_ADDR_BYTES), - bufx8 + 7 * (PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_ADDR_BYTES), - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_ADDR_BYTES); - - memcpy(out0, outbufx8 + 0 * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N); - memcpy(out1, outbufx8 + 1 * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N); - memcpy(out2, outbufx8 + 2 * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N); - memcpy(out3, outbufx8 + 3 * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N); - memcpy(out4, outbufx8 + 4 * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N); - memcpy(out5, outbufx8 + 5 * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N); - memcpy(out6, outbufx8 + 6 * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N); - memcpy(out7, outbufx8 + 7 * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_avx2/hash_state.h b/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_avx2/hash_state.h deleted file mode 100644 index aebebdb8ed..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_avx2/hash_state.h +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_HASH_STATE_H -#define PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_HASH_STATE_H - -/** - * Defines the type of the hash function state. - * - * Don't be fooled into thinking this instance of SPHINCS+ isn't stateless! - * - * From Section 7.2.2 from the SPHINCS+ round-2 specification: - * - * Each of the instances of the tweakable hash function take PK.seed as its - * first input, which is constant for a given key pair – and, thus, across - * a single signature. This leads to a lot of redundant computation. To remedy - * this, we pad PK.seed to the length of a full 64-byte SHA-256 input block. - * Because of the Merkle-Damgård construction that underlies SHA-256, this - * allows for reuse of the intermediate SHA-256 state after the initial call to - * the compression function which improves performance. - * - * We pass this hash state around in functions, because otherwise we need to - * have a global variable. - * - * We use a struct to differentiate between the x1 and x8 variants of SHA256. - */ - -#include "sha2.h" -#include "sha256avx.h" - -typedef struct { - sha256ctx x1; - sha256ctxx8 x8; -} hash_state; - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_avx2/hashx8.h b/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_avx2/hashx8.h deleted file mode 100644 index d079b5c3ce..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_avx2/hashx8.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_HASHX8_H -#define PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_HASHX8_H - -#include - -#include "params.h" - -void PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_prf_addrx8(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7, - const unsigned char *key, - const uint32_t addrx8[8 * 8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_avx2/params.h b/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_avx2/params.h deleted file mode 100644 index 9de35fc022..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_avx2/params.h +++ /dev/null @@ -1,53 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_PARAMS_H -#define PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_PARAMS_H - -/* Hash output length in bytes. */ -#define PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N 24 -/* Height of the hypertree. */ -#define PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_FULL_HEIGHT 63 -/* Number of subtree layer. */ -#define PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_D 7 -/* FORS tree dimensions. */ -#define PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_FORS_HEIGHT 14 -#define PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_FORS_TREES 17 -/* Winternitz parameter, */ -#define PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_WOTS_W 16 - -/* The hash function is defined by linking a different hash.c file, as opposed - to setting a #define constant. */ - -/* For clarity */ -#define PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_ADDR_BYTES 32 - -/* WOTS parameters. */ -#define PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_WOTS_LOGW 4 - -#define PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_WOTS_LEN1 (8 * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N / PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_WOTS_LOGW) - -/* PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#define PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_WOTS_LEN2 3 - -#define PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_WOTS_LEN (PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_WOTS_LEN1 + PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_WOTS_LEN2) -#define PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_WOTS_BYTES (PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_WOTS_LEN * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N) -#define PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_WOTS_PK_BYTES PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_WOTS_BYTES - -/* Subtree size. */ -#define PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_TREE_HEIGHT (PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_FULL_HEIGHT / PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_D) - -/* FORS parameters. */ -#define PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_FORS_MSG_BYTES ((PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_FORS_TREES + 7) / 8) -#define PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_FORS_BYTES ((PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_FORS_HEIGHT + 1) * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_FORS_TREES * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N) -#define PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_FORS_PK_BYTES PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N - -/* Resulting SPX sizes. */ -#define PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_BYTES (PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_FORS_BYTES + PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_D * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_WOTS_BYTES +\ - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_FULL_HEIGHT * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N) -#define PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_PK_BYTES (2 * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N) -#define PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SK_BYTES (2 * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_PK_BYTES) - -/* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ -#define PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_OPTRAND_BYTES 32 - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_avx2/sha256.c b/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_avx2/sha256.c deleted file mode 100644 index 96e520e55b..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_avx2/sha256.c +++ /dev/null @@ -1,71 +0,0 @@ -/* Based on the public domain implementation in - * crypto_hash/sha512/ref/ from http://bench.cr.yp.to/supercop.html - * by D. J. Bernstein */ - -#include -#include -#include - -#include "sha2.h" -#include "sha256.h" -#include "utils.h" - -/* - * Compresses an address to a 22-byte sequence. - * This reduces the number of required SHA256 compression calls, as the last - * block of input is padded with at least 65 bits. - */ -void PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_compress_address(unsigned char *out, const uint32_t addr[8]) { - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_ull_to_bytes(out, 1, addr[0]); /* drop 3 bytes of the layer field */ - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_ull_to_bytes(out + 1, 4, addr[2]); /* drop the highest tree address word */ - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_ull_to_bytes(out + 5, 4, addr[3]); - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_ull_to_bytes(out + 9, 1, addr[4]); /* drop 3 bytes of the type field */ - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_ull_to_bytes(out + 10, 4, addr[5]); - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_ull_to_bytes(out + 14, 4, addr[6]); - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_ull_to_bytes(out + 18, 4, addr[7]); -} - -/** - * Requires 'input_plus_four_bytes' to have 'inlen' + 4 bytes, so that the last - * four bytes can be used for the counter. Typically 'input' is merely a seed. - * Outputs outlen number of bytes - */ -void PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_mgf1( - unsigned char *out, unsigned long outlen, - unsigned char *input_plus_four_bytes, unsigned long inlen) { - unsigned char outbuf[PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_OUTPUT_BYTES]; - unsigned long i; - - /* While we can fit in at least another full block of SHA256 output.. */ - for (i = 0; (i + 1)*PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_OUTPUT_BYTES <= outlen; i++) { - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_ull_to_bytes(input_plus_four_bytes + inlen, 4, i); - sha256(out, input_plus_four_bytes, inlen + 4); - out += PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_OUTPUT_BYTES; - } - /* Until we cannot anymore, and we fill the remainder. */ - if (outlen > i * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_OUTPUT_BYTES) { - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_ull_to_bytes(input_plus_four_bytes + inlen, 4, i); - sha256(outbuf, input_plus_four_bytes, inlen + 4); - memcpy(out, outbuf, outlen - i * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_OUTPUT_BYTES); - } -} - - -/** - * Absorb the constant pub_seed using one round of the compression function - * This initializes hash_state_seeded, which can then be reused in thash - **/ -void PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_seed_state(sha256ctx *hash_state_seeded, const unsigned char *pub_seed) { - uint8_t block[PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_BLOCK_BYTES]; - size_t i; - - for (i = 0; i < PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N; ++i) { - block[i] = pub_seed[i]; - } - for (i = PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N; i < PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_BLOCK_BYTES; ++i) { - block[i] = 0; - } - - sha256_inc_init(hash_state_seeded); - sha256_inc_blocks(hash_state_seeded, block, 1); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_avx2/sha256.h b/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_avx2/sha256.h deleted file mode 100644 index 273f94288b..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_avx2/sha256.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_H -#define PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_H - -#define PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_BLOCK_BYTES 64 -#define PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_OUTPUT_BYTES 32 /* This does not necessarily equal PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N */ -#define PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_ADDR_BYTES 22 - -#include -#include - -#include "sha2.h" - -void PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_compress_address(unsigned char *out, const uint32_t addr[8]); - -void PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_mgf1( - unsigned char *out, unsigned long outlen, - unsigned char *input_plus_four_bytes, unsigned long inlen); - -void PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_seed_state(sha256ctx *hash_state_seeded, const unsigned char *pub_seed); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_avx2/sha256avx.c b/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_avx2/sha256avx.c deleted file mode 100644 index 904296444f..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_avx2/sha256avx.c +++ /dev/null @@ -1,296 +0,0 @@ -#include -#include -#include - -#include "sha256avx.h" - -// Transpose 8 vectors containing 32-bit values -void PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_transpose(u256 s[8]) { - u256 tmp0[8]; - u256 tmp1[8]; - tmp0[0] = _mm256_unpacklo_epi32(s[0], s[1]); - tmp0[1] = _mm256_unpackhi_epi32(s[0], s[1]); - tmp0[2] = _mm256_unpacklo_epi32(s[2], s[3]); - tmp0[3] = _mm256_unpackhi_epi32(s[2], s[3]); - tmp0[4] = _mm256_unpacklo_epi32(s[4], s[5]); - tmp0[5] = _mm256_unpackhi_epi32(s[4], s[5]); - tmp0[6] = _mm256_unpacklo_epi32(s[6], s[7]); - tmp0[7] = _mm256_unpackhi_epi32(s[6], s[7]); - tmp1[0] = _mm256_unpacklo_epi64(tmp0[0], tmp0[2]); - tmp1[1] = _mm256_unpackhi_epi64(tmp0[0], tmp0[2]); - tmp1[2] = _mm256_unpacklo_epi64(tmp0[1], tmp0[3]); - tmp1[3] = _mm256_unpackhi_epi64(tmp0[1], tmp0[3]); - tmp1[4] = _mm256_unpacklo_epi64(tmp0[4], tmp0[6]); - tmp1[5] = _mm256_unpackhi_epi64(tmp0[4], tmp0[6]); - tmp1[6] = _mm256_unpacklo_epi64(tmp0[5], tmp0[7]); - tmp1[7] = _mm256_unpackhi_epi64(tmp0[5], tmp0[7]); - s[0] = _mm256_permute2x128_si256(tmp1[0], tmp1[4], 0x20); - s[1] = _mm256_permute2x128_si256(tmp1[1], tmp1[5], 0x20); - s[2] = _mm256_permute2x128_si256(tmp1[2], tmp1[6], 0x20); - s[3] = _mm256_permute2x128_si256(tmp1[3], tmp1[7], 0x20); - s[4] = _mm256_permute2x128_si256(tmp1[0], tmp1[4], 0x31); - s[5] = _mm256_permute2x128_si256(tmp1[1], tmp1[5], 0x31); - s[6] = _mm256_permute2x128_si256(tmp1[2], tmp1[6], 0x31); - s[7] = _mm256_permute2x128_si256(tmp1[3], tmp1[7], 0x31); -} - -void PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_sha256_clone_statex8(sha256ctxx8 *outctx, const sha256ctxx8 *inctx) { - memcpy(outctx, inctx, sizeof(sha256ctxx8)); -} - -void PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_sha256_init8x(sha256ctxx8 *ctx) { - ctx->s[0] = _mm256_set_epi32((int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667); - ctx->s[1] = _mm256_set_epi32((int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85); - ctx->s[2] = _mm256_set_epi32((int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372); - ctx->s[3] = _mm256_set_epi32((int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a); - ctx->s[4] = _mm256_set_epi32((int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f); - ctx->s[5] = _mm256_set_epi32((int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c); - ctx->s[6] = _mm256_set_epi32((int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab); - ctx->s[7] = _mm256_set_epi32((int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19); - - ctx->datalen = 0; - ctx->msglen = 0; -} - -void PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_sha256_update8x(sha256ctxx8 *ctx, - const unsigned char *d0, - const unsigned char *d1, - const unsigned char *d2, - const unsigned char *d3, - const unsigned char *d4, - const unsigned char *d5, - const unsigned char *d6, - const unsigned char *d7, - unsigned long long len) { - size_t i = 0; - size_t bytes_to_copy; - - while (i < len) { - bytes_to_copy = (size_t)len - i; - if (bytes_to_copy > 64) { - bytes_to_copy = 64; - } - memcpy(&ctx->msgblocks[64 * 0], d0 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64 * 1], d1 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64 * 2], d2 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64 * 3], d3 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64 * 4], d4 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64 * 5], d5 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64 * 6], d6 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64 * 7], d7 + i, bytes_to_copy); - ctx->datalen += (unsigned int)bytes_to_copy; - i += bytes_to_copy; - if (ctx->datalen == 64) { - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_sha256_transform8x(ctx, ctx->msgblocks); - ctx->msglen += 512; - ctx->datalen = 0; - } - } -} - -void PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_sha256_final8x(sha256ctxx8 *ctx, - unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7) { - unsigned int i, curlen; - - // Padding - if (ctx->datalen < 56) { - for (i = 0; i < 8; ++i) { - curlen = ctx->datalen; - ctx->msgblocks[64 * i + curlen++] = 0x80; - while (curlen < 64) { - ctx->msgblocks[64 * i + curlen++] = 0x00; - } - } - } else { - for (i = 0; i < 8; ++i) { - curlen = ctx->datalen; - ctx->msgblocks[64 * i + curlen++] = 0x80; - while (curlen < 64) { - ctx->msgblocks[64 * i + curlen++] = 0x00; - } - } - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_sha256_transform8x(ctx, ctx->msgblocks); - memset(ctx->msgblocks, 0, 8 * 64); - } - - // Add length of the message to each block - ctx->msglen += ctx->datalen * 8; - for (i = 0; i < 8; i++) { - ctx->msgblocks[64 * i + 63] = (unsigned char)ctx->msglen; - ctx->msgblocks[64 * i + 62] = (unsigned char)(ctx->msglen >> 8); - ctx->msgblocks[64 * i + 61] = (unsigned char)(ctx->msglen >> 16); - ctx->msgblocks[64 * i + 60] = (unsigned char)(ctx->msglen >> 24); - ctx->msgblocks[64 * i + 59] = (unsigned char)(ctx->msglen >> 32); - ctx->msgblocks[64 * i + 58] = (unsigned char)(ctx->msglen >> 40); - ctx->msgblocks[64 * i + 57] = (unsigned char)(ctx->msglen >> 48); - ctx->msgblocks[64 * i + 56] = (unsigned char)(ctx->msglen >> 56); - } - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_sha256_transform8x(ctx, ctx->msgblocks); - - // Compute final hash output - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_transpose(ctx->s); - - // Store Hash value - STORE(out0, BYTESWAP(ctx->s[0])); - STORE(out1, BYTESWAP(ctx->s[1])); - STORE(out2, BYTESWAP(ctx->s[2])); - STORE(out3, BYTESWAP(ctx->s[3])); - STORE(out4, BYTESWAP(ctx->s[4])); - STORE(out5, BYTESWAP(ctx->s[5])); - STORE(out6, BYTESWAP(ctx->s[6])); - STORE(out7, BYTESWAP(ctx->s[7])); -} - -void PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_sha256_transform8x(sha256ctxx8 *ctx, const unsigned char *data) { - u256 s[8], w[64], T0, T1; - int i; - - // Load words and transform data correctly - for (i = 0; i < 8; i++) { - w[i] = BYTESWAP(LOAD(data + 64 * i)); - w[i + 8] = BYTESWAP(LOAD(data + 32 + 64 * i)); - } - - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_transpose(w); - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_transpose(w + 8); - - // Initial State - s[0] = ctx->s[0]; - s[1] = ctx->s[1]; - s[2] = ctx->s[2]; - s[3] = ctx->s[3]; - s[4] = ctx->s[4]; - s[5] = ctx->s[5]; - s[6] = ctx->s[6]; - s[7] = ctx->s[7]; - - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 0, w[0]); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 1, w[1]); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 2, w[2]); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 3, w[3]); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 4, w[4]); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 5, w[5]); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 6, w[6]); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 7, w[7]); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 8, w[8]); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 9, w[9]); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 10, w[10]); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 11, w[11]); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 12, w[12]); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 13, w[13]); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 14, w[14]); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 15, w[15]); - w[16] = ADD4_32(WSIGMA1_AVX(w[14]), w[0], w[9], WSIGMA0_AVX(w[1])); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 16, w[16]); - w[17] = ADD4_32(WSIGMA1_AVX(w[15]), w[1], w[10], WSIGMA0_AVX(w[2])); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 17, w[17]); - w[18] = ADD4_32(WSIGMA1_AVX(w[16]), w[2], w[11], WSIGMA0_AVX(w[3])); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 18, w[18]); - w[19] = ADD4_32(WSIGMA1_AVX(w[17]), w[3], w[12], WSIGMA0_AVX(w[4])); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 19, w[19]); - w[20] = ADD4_32(WSIGMA1_AVX(w[18]), w[4], w[13], WSIGMA0_AVX(w[5])); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 20, w[20]); - w[21] = ADD4_32(WSIGMA1_AVX(w[19]), w[5], w[14], WSIGMA0_AVX(w[6])); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 21, w[21]); - w[22] = ADD4_32(WSIGMA1_AVX(w[20]), w[6], w[15], WSIGMA0_AVX(w[7])); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 22, w[22]); - w[23] = ADD4_32(WSIGMA1_AVX(w[21]), w[7], w[16], WSIGMA0_AVX(w[8])); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 23, w[23]); - w[24] = ADD4_32(WSIGMA1_AVX(w[22]), w[8], w[17], WSIGMA0_AVX(w[9])); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 24, w[24]); - w[25] = ADD4_32(WSIGMA1_AVX(w[23]), w[9], w[18], WSIGMA0_AVX(w[10])); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 25, w[25]); - w[26] = ADD4_32(WSIGMA1_AVX(w[24]), w[10], w[19], WSIGMA0_AVX(w[11])); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 26, w[26]); - w[27] = ADD4_32(WSIGMA1_AVX(w[25]), w[11], w[20], WSIGMA0_AVX(w[12])); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 27, w[27]); - w[28] = ADD4_32(WSIGMA1_AVX(w[26]), w[12], w[21], WSIGMA0_AVX(w[13])); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 28, w[28]); - w[29] = ADD4_32(WSIGMA1_AVX(w[27]), w[13], w[22], WSIGMA0_AVX(w[14])); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 29, w[29]); - w[30] = ADD4_32(WSIGMA1_AVX(w[28]), w[14], w[23], WSIGMA0_AVX(w[15])); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 30, w[30]); - w[31] = ADD4_32(WSIGMA1_AVX(w[29]), w[15], w[24], WSIGMA0_AVX(w[16])); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 31, w[31]); - w[32] = ADD4_32(WSIGMA1_AVX(w[30]), w[16], w[25], WSIGMA0_AVX(w[17])); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 32, w[32]); - w[33] = ADD4_32(WSIGMA1_AVX(w[31]), w[17], w[26], WSIGMA0_AVX(w[18])); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 33, w[33]); - w[34] = ADD4_32(WSIGMA1_AVX(w[32]), w[18], w[27], WSIGMA0_AVX(w[19])); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 34, w[34]); - w[35] = ADD4_32(WSIGMA1_AVX(w[33]), w[19], w[28], WSIGMA0_AVX(w[20])); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 35, w[35]); - w[36] = ADD4_32(WSIGMA1_AVX(w[34]), w[20], w[29], WSIGMA0_AVX(w[21])); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 36, w[36]); - w[37] = ADD4_32(WSIGMA1_AVX(w[35]), w[21], w[30], WSIGMA0_AVX(w[22])); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 37, w[37]); - w[38] = ADD4_32(WSIGMA1_AVX(w[36]), w[22], w[31], WSIGMA0_AVX(w[23])); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 38, w[38]); - w[39] = ADD4_32(WSIGMA1_AVX(w[37]), w[23], w[32], WSIGMA0_AVX(w[24])); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 39, w[39]); - w[40] = ADD4_32(WSIGMA1_AVX(w[38]), w[24], w[33], WSIGMA0_AVX(w[25])); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 40, w[40]); - w[41] = ADD4_32(WSIGMA1_AVX(w[39]), w[25], w[34], WSIGMA0_AVX(w[26])); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 41, w[41]); - w[42] = ADD4_32(WSIGMA1_AVX(w[40]), w[26], w[35], WSIGMA0_AVX(w[27])); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 42, w[42]); - w[43] = ADD4_32(WSIGMA1_AVX(w[41]), w[27], w[36], WSIGMA0_AVX(w[28])); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 43, w[43]); - w[44] = ADD4_32(WSIGMA1_AVX(w[42]), w[28], w[37], WSIGMA0_AVX(w[29])); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 44, w[44]); - w[45] = ADD4_32(WSIGMA1_AVX(w[43]), w[29], w[38], WSIGMA0_AVX(w[30])); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 45, w[45]); - w[46] = ADD4_32(WSIGMA1_AVX(w[44]), w[30], w[39], WSIGMA0_AVX(w[31])); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 46, w[46]); - w[47] = ADD4_32(WSIGMA1_AVX(w[45]), w[31], w[40], WSIGMA0_AVX(w[32])); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 47, w[47]); - w[48] = ADD4_32(WSIGMA1_AVX(w[46]), w[32], w[41], WSIGMA0_AVX(w[33])); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 48, w[48]); - w[49] = ADD4_32(WSIGMA1_AVX(w[47]), w[33], w[42], WSIGMA0_AVX(w[34])); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 49, w[49]); - w[50] = ADD4_32(WSIGMA1_AVX(w[48]), w[34], w[43], WSIGMA0_AVX(w[35])); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 50, w[50]); - w[51] = ADD4_32(WSIGMA1_AVX(w[49]), w[35], w[44], WSIGMA0_AVX(w[36])); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 51, w[51]); - w[52] = ADD4_32(WSIGMA1_AVX(w[50]), w[36], w[45], WSIGMA0_AVX(w[37])); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 52, w[52]); - w[53] = ADD4_32(WSIGMA1_AVX(w[51]), w[37], w[46], WSIGMA0_AVX(w[38])); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 53, w[53]); - w[54] = ADD4_32(WSIGMA1_AVX(w[52]), w[38], w[47], WSIGMA0_AVX(w[39])); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 54, w[54]); - w[55] = ADD4_32(WSIGMA1_AVX(w[53]), w[39], w[48], WSIGMA0_AVX(w[40])); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 55, w[55]); - w[56] = ADD4_32(WSIGMA1_AVX(w[54]), w[40], w[49], WSIGMA0_AVX(w[41])); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 56, w[56]); - w[57] = ADD4_32(WSIGMA1_AVX(w[55]), w[41], w[50], WSIGMA0_AVX(w[42])); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 57, w[57]); - w[58] = ADD4_32(WSIGMA1_AVX(w[56]), w[42], w[51], WSIGMA0_AVX(w[43])); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 58, w[58]); - w[59] = ADD4_32(WSIGMA1_AVX(w[57]), w[43], w[52], WSIGMA0_AVX(w[44])); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 59, w[59]); - w[60] = ADD4_32(WSIGMA1_AVX(w[58]), w[44], w[53], WSIGMA0_AVX(w[45])); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 60, w[60]); - w[61] = ADD4_32(WSIGMA1_AVX(w[59]), w[45], w[54], WSIGMA0_AVX(w[46])); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 61, w[61]); - w[62] = ADD4_32(WSIGMA1_AVX(w[60]), w[46], w[55], WSIGMA0_AVX(w[47])); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 62, w[62]); - w[63] = ADD4_32(WSIGMA1_AVX(w[61]), w[47], w[56], WSIGMA0_AVX(w[48])); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 63, w[63]); - - // Feed Forward - ctx->s[0] = ADD32(s[0], ctx->s[0]); - ctx->s[1] = ADD32(s[1], ctx->s[1]); - ctx->s[2] = ADD32(s[2], ctx->s[2]); - ctx->s[3] = ADD32(s[3], ctx->s[3]); - ctx->s[4] = ADD32(s[4], ctx->s[4]); - ctx->s[5] = ADD32(s[5], ctx->s[5]); - ctx->s[6] = ADD32(s[6], ctx->s[6]); - ctx->s[7] = ADD32(s[7], ctx->s[7]); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_avx2/sha256avx.h b/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_avx2/sha256avx.h deleted file mode 100644 index 608b38ae16..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_avx2/sha256avx.h +++ /dev/null @@ -1,103 +0,0 @@ -#ifndef SHA256AVX_H -#define SHA256AVX_H - -#include -#include - -static const unsigned int RC[] = { - 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, - 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, - 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, - 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, - 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, - 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, - 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, - 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, - 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, - 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, - 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, - 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, - 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, - 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, - 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, - 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 -}; - -#define u32 uint32_t -#define u256 __m256i - -#define XOR _mm256_xor_si256 -#define OR _mm256_or_si256 -#define AND _mm256_and_si256 -#define ADD32 _mm256_add_epi32 -#define NOT(x) _mm256_xor_si256(x, _mm256_set_epi32(-1, -1, -1, -1, -1, -1, -1, -1)) - -#define LOAD(src) _mm256_loadu_si256((__m256i *)(src)) -#define STORE(dest,src) _mm256_storeu_si256((__m256i *)(dest),src) - -#define BYTESWAP(x) _mm256_shuffle_epi8(x, _mm256_set_epi8(0xc,0xd,0xe,0xf,0x8,0x9,0xa,0xb,0x4,0x5,0x6,0x7,0x0,0x1,0x2,0x3,0xc,0xd,0xe,0xf,0x8,0x9,0xa,0xb,0x4,0x5,0x6,0x7,0x0,0x1,0x2,0x3)) - -#define SHIFTR32(x, y) _mm256_srli_epi32(x, y) -#define SHIFTL32(x, y) _mm256_slli_epi32(x, y) - -#define ROTR32(x, y) OR(SHIFTR32(x, y), SHIFTL32(x, 32 - (y))) -#define ROTL32(x, y) OR(SHIFTL32(x, y), SHIFTR32(x, 32 - (y))) - -#define XOR3(a, b, c) XOR(XOR(a, b), c) - -#define ADD3_32(a, b, c) ADD32(ADD32(a, b), c) -#define ADD4_32(a, b, c, d) ADD32(ADD32(ADD32(a, b), c), d) -#define ADD5_32(a, b, c, d, e) ADD32(ADD32(ADD32(ADD32(a, b), c), d), e) - -#define MAJ_AVX(a, b, c) XOR3(AND(a, b), AND(a, c), AND(b, c)) -#define CH_AVX(a, b, c) XOR(AND(a, b), AND(NOT(a), c)) - -#define SIGMA1_AVX(x) XOR3(ROTR32(x, 6), ROTR32(x, 11), ROTR32(x, 25)) -#define SIGMA0_AVX(x) XOR3(ROTR32(x, 2), ROTR32(x, 13), ROTR32(x, 22)) - -#define WSIGMA1_AVX(x) XOR3(ROTR32(x, 17), ROTR32(x, 19), SHIFTR32(x, 10)) -#define WSIGMA0_AVX(x) XOR3(ROTR32(x, 7), ROTR32(x, 18), SHIFTR32(x, 3)) - -#define SHA256ROUND_AVX(a, b, c, d, e, f, g, h, rc, w) \ - T0 = ADD5_32(h, SIGMA1_AVX(e), CH_AVX(e, f, g), _mm256_set1_epi32((int)RC[rc]), w); \ - (d) = ADD32(d, T0); \ - T1 = ADD32(SIGMA0_AVX(a), MAJ_AVX(a, b, c)); \ - (h) = ADD32(T0, T1); - -typedef struct SHA256state { - u256 s[8]; - uint8_t msgblocks[8 * 64]; - unsigned int datalen; - uint64_t msglen; -} sha256ctxx8; - - -void PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_transpose(u256 s[8]); -void PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_sha256_init_frombytes_x8(sha256ctxx8 *ctx, const uint8_t *s, unsigned long long msglen); -void PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_sha256_init8x(sha256ctxx8 *ctx); -void PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_sha256_update8x(sha256ctxx8 *ctx, - const unsigned char *d0, - const unsigned char *d1, - const unsigned char *d2, - const unsigned char *d3, - const unsigned char *d4, - const unsigned char *d5, - const unsigned char *d6, - const unsigned char *d7, - unsigned long long len); -void PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_sha256_final8x(sha256ctxx8 *ctx, - unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7); - -void PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_sha256_transform8x(sha256ctxx8 *ctx, const unsigned char *data); - -void PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_sha256_clone_statex8(sha256ctxx8 *outctx, const sha256ctxx8 *inctx); - - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_avx2/sha256x8.c b/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_avx2/sha256x8.c deleted file mode 100644 index 9ea319ecc1..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_avx2/sha256x8.c +++ /dev/null @@ -1,128 +0,0 @@ -#include - -#include "sha256.h" -#include "sha256avx.h" -#include "sha256x8.h" -#include "utils.h" - -void PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_seed_statex8(sha256ctxx8 *ctx, const unsigned char *pub_seed) { - uint8_t block[PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_BLOCK_BYTES]; - size_t i; - - for (i = 0; i < PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N; ++i) { - block[i] = pub_seed[i]; - } - for (i = PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N; i < PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_BLOCK_BYTES; ++i) { - block[i] = 0; - } - - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_sha256_init8x(ctx); - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_sha256_update8x(ctx, block, block, block, block, block, block, block, block, PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_BLOCK_BYTES); - -} - -/* This provides a wrapper around the internals of 8x parallel SHA256 */ -void PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_sha256x8(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - const unsigned char *in4, - const unsigned char *in5, - const unsigned char *in6, - const unsigned char *in7, unsigned long long inlen) { - sha256ctxx8 ctx; - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_sha256_init8x(&ctx); - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_sha256_update8x(&ctx, in0, in1, in2, in3, in4, in5, in6, in7, inlen); - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_sha256_final8x(&ctx, out0, out1, out2, out3, out4, out5, out6, out7); -} - -/** - * Note that inlen should be sufficiently small that it still allows for - * an array to be allocated on the stack. Typically 'in' is merely a seed. - * Outputs outlen number of bytes - */ -void PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_mgf1x8( - unsigned char *outx8, - unsigned long outlen, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - const unsigned char *in4, - const unsigned char *in5, - const unsigned char *in6, - const unsigned char *in7, - unsigned long inlen) { - unsigned char inbufx8[8 * ((PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_ADDR_BYTES) + 4)]; - unsigned char outbufx8[8 * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_OUTPUT_BYTES]; - unsigned long i; - unsigned int j; - - memcpy(inbufx8 + 0 * (inlen + 4), in0, inlen); - memcpy(inbufx8 + 1 * (inlen + 4), in1, inlen); - memcpy(inbufx8 + 2 * (inlen + 4), in2, inlen); - memcpy(inbufx8 + 3 * (inlen + 4), in3, inlen); - memcpy(inbufx8 + 4 * (inlen + 4), in4, inlen); - memcpy(inbufx8 + 5 * (inlen + 4), in5, inlen); - memcpy(inbufx8 + 6 * (inlen + 4), in6, inlen); - memcpy(inbufx8 + 7 * (inlen + 4), in7, inlen); - - /* While we can fit in at least another full block of SHA256 output.. */ - for (i = 0; (i + 1)*PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_OUTPUT_BYTES <= outlen; i++) { - for (j = 0; j < 8; j++) { - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_ull_to_bytes(inbufx8 + inlen + j * (inlen + 4), 4, i); - } - - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_sha256x8(outx8 + 0 * outlen, - outx8 + 1 * outlen, - outx8 + 2 * outlen, - outx8 + 3 * outlen, - outx8 + 4 * outlen, - outx8 + 5 * outlen, - outx8 + 6 * outlen, - outx8 + 7 * outlen, - inbufx8 + 0 * (inlen + 4), - inbufx8 + 1 * (inlen + 4), - inbufx8 + 2 * (inlen + 4), - inbufx8 + 3 * (inlen + 4), - inbufx8 + 4 * (inlen + 4), - inbufx8 + 5 * (inlen + 4), - inbufx8 + 6 * (inlen + 4), - inbufx8 + 7 * (inlen + 4), inlen + 4); - outx8 += PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_OUTPUT_BYTES; - } - /* Until we cannot anymore, and we fill the remainder. */ - for (j = 0; j < 8; j++) { - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_ull_to_bytes(inbufx8 + inlen + j * (inlen + 4), 4, i); - } - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_sha256x8(outbufx8 + 0 * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 1 * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 2 * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 3 * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 4 * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 5 * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 6 * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 7 * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - inbufx8 + 0 * (inlen + 4), - inbufx8 + 1 * (inlen + 4), - inbufx8 + 2 * (inlen + 4), - inbufx8 + 3 * (inlen + 4), - inbufx8 + 4 * (inlen + 4), - inbufx8 + 5 * (inlen + 4), - inbufx8 + 6 * (inlen + 4), - inbufx8 + 7 * (inlen + 4), inlen + 4); - - for (j = 0; j < 8; j++) { - memcpy(outx8 + j * outlen, - outbufx8 + j * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outlen - i * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_OUTPUT_BYTES); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_avx2/sha256x8.h b/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_avx2/sha256x8.h deleted file mode 100644 index a6a1d8671d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_avx2/sha256x8.h +++ /dev/null @@ -1,44 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256X8_H -#define PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256X8_H - -#include "sha256avx.h" - -#define PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_BLOCK_BYTES 64 -#define PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_OUTPUT_BYTES 32 /* This does not necessarily equal PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N */ - -/* This provides a wrapper around the internals of 8x parallel SHA256 */ -void PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_sha256x8(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - const unsigned char *in4, - const unsigned char *in5, - const unsigned char *in6, - const unsigned char *in7, unsigned long long inlen); - -/** - * Note that inlen should be sufficiently small that it still allows for - * an array to be allocated on the stack. Typically 'in' is merely a seed. - * Outputs outlen number of bytes - */ -void PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_mgf1x8(unsigned char *outx8, unsigned long outlen, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - const unsigned char *in4, - const unsigned char *in5, - const unsigned char *in6, - const unsigned char *in7, - unsigned long inlen); - -void PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_seed_statex8(sha256ctxx8 *ctx, const unsigned char *pub_seed); -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_avx2/sign.c b/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_avx2/sign.c deleted file mode 100644 index c3702bf693..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_avx2/sign.c +++ /dev/null @@ -1,356 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "api.h" -#include "fors.h" -#include "hash.h" -#include "hash_state.h" -#include "params.h" -#include "randombytes.h" -#include "thash.h" -#include "utils.h" -#include "wots.h" - -/** - * Computes the leaf at a given address. First generates the WOTS key pair, - * then computes leaf by hashing horizontally. - */ -static void wots_gen_leaf(unsigned char *leaf, const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx, const uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - unsigned char pk[PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_WOTS_BYTES]; - uint32_t wots_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_set_type( - wots_addr, PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_set_type( - wots_pk_addr, PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_ADDR_TYPE_WOTSPK); - - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_set_keypair_addr( - wots_addr, addr_idx); - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_wots_gen_pk( - pk, sk_seed, pub_seed, wots_addr, hash_state_seeded); - - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_copy_keypair_addr( - wots_pk_addr, wots_addr); - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_thash_WOTS_LEN( - leaf, pk, pub_seed, wots_pk_addr, hash_state_seeded); -} - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_crypto_sign_secretkeybytes(void) { - return PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_CRYPTO_SECRETKEYBYTES; -} - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_crypto_sign_publickeybytes(void) { - return PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_CRYPTO_PUBLICKEYBYTES; -} - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_crypto_sign_bytes(void) { - return PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_CRYPTO_BYTES; -} - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_crypto_sign_seedbytes(void) { - return PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_CRYPTO_SEEDBYTES; -} - -/* - * Generates an SPX key pair given a seed of length - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed) { - /* We do not need the auth path in key generation, but it simplifies the - code to have just one treehash routine that computes both root and path - in one function. */ - unsigned char auth_path[PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_TREE_HEIGHT * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N]; - uint32_t top_tree_addr[8] = {0}; - hash_state hash_state_seeded; - - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_set_layer_addr( - top_tree_addr, PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_D - 1); - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_set_type( - top_tree_addr, PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_ADDR_TYPE_HASHTREE); - - /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ - memcpy(sk, seed, PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_CRYPTO_SEEDBYTES); - - memcpy(pk, sk + 2 * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N, PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_initialize_hash_function(&hash_state_seeded, pk, sk); - - /* Compute root node of the top-most subtree. */ - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_treehash_TREE_HEIGHT( - sk + 3 * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N, auth_path, sk, sk + 2 * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N, 0, 0, - wots_gen_leaf, top_tree_addr, &hash_state_seeded); - - memcpy(pk + PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N, sk + 3 * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N, PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N); - - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_destroy_hash_function(&hash_state_seeded); - return 0; -} - -/* - * Generates an SPX key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk) { - unsigned char seed[PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_CRYPTO_SEEDBYTES]; - randombytes(seed, PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_CRYPTO_SEEDBYTES); - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_crypto_sign_seed_keypair( - pk, sk, seed); - - return 0; -} - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - const unsigned char *sk_seed = sk; - const unsigned char *sk_prf = sk + PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N; - const unsigned char *pk = sk + 2 * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N; - const unsigned char *pub_seed = pk; - - unsigned char optrand[PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N]; - unsigned char mhash[PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_FORS_MSG_BYTES]; - unsigned char root[PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N]; - uint32_t i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - - hash_state hash_state_seeded; - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_initialize_hash_function( - &hash_state_seeded, - pub_seed, sk_seed); - - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_set_type( - wots_addr, PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_set_type( - tree_addr, PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_ADDR_TYPE_HASHTREE); - - /* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ - randombytes(optrand, PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N); - /* Compute the digest randomization value. */ - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_gen_message_random( - sig, sk_prf, optrand, m, mlen, &hash_state_seeded); - - /* Derive the message digest and leaf index from R, PK and M. */ - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N; - - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_set_keypair_addr( - wots_addr, idx_leaf); - - /* Sign the message hash using FORS. */ - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_fors_sign( - sig, root, mhash, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_FORS_BYTES; - - for (i = 0; i < PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_D; i++) { - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_set_tree_addr(tree_addr, tree); - - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_set_keypair_addr( - wots_addr, idx_leaf); - - /* Compute a WOTS signature. */ - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_wots_sign( - sig, root, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_WOTS_BYTES; - - /* Compute the authentication path for the used WOTS leaf. */ - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_treehash_TREE_HEIGHT( - root, sig, sk_seed, pub_seed, idx_leaf, 0, - wots_gen_leaf, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_TREE_HEIGHT * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_TREE_HEIGHT; - } - - *siglen = PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_BYTES; - - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_destroy_hash_function(&hash_state_seeded); - return 0; -} - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk) { - const unsigned char *pub_seed = pk; - const unsigned char *pub_root = pk + PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N; - unsigned char mhash[PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_FORS_MSG_BYTES]; - unsigned char wots_pk[PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_WOTS_BYTES]; - unsigned char root[PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N]; - unsigned char leaf[PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N]; - unsigned int i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - hash_state hash_state_seeded; - - if (siglen != PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_BYTES) { - return -1; - } - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_initialize_hash_function( - &hash_state_seeded, - pub_seed, NULL); - - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_set_type( - wots_addr, PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_set_type( - tree_addr, PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_ADDR_TYPE_HASHTREE); - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_set_type( - wots_pk_addr, PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_ADDR_TYPE_WOTSPK); - - /* Derive the message digest and leaf index from R || PK || M. */ - /* The additional PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N is a result of the hash domain separator. */ - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N; - - /* Layer correctly defaults to 0, so no need to set_layer_addr */ - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_set_keypair_addr( - wots_addr, idx_leaf); - - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_fors_pk_from_sig( - root, sig, mhash, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_FORS_BYTES; - - /* For each subtree.. */ - for (i = 0; i < PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_D; i++) { - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_set_tree_addr(tree_addr, tree); - - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_set_keypair_addr( - wots_addr, idx_leaf); - - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_copy_keypair_addr( - wots_pk_addr, wots_addr); - - /* The WOTS public key is only correct if the signature was correct. */ - /* Initially, root is the FORS pk, but on subsequent iterations it is - the root of the subtree below the currently processed subtree. */ - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_wots_pk_from_sig( - wots_pk, sig, root, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_WOTS_BYTES; - - /* Compute the leaf node using the WOTS public key. */ - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_thash_WOTS_LEN( - leaf, wots_pk, pub_seed, wots_pk_addr, &hash_state_seeded); - - /* Compute the root node of this subtree. */ - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_compute_root( - root, leaf, idx_leaf, 0, sig, PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_TREE_HEIGHT, - pub_seed, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_TREE_HEIGHT * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_TREE_HEIGHT; - } - - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_destroy_hash_function(&hash_state_seeded); - /* Check if the root node equals the root node in the public key. */ - if (memcmp(root, pub_root, PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N) != 0) { - return -1; - } - - return 0; -} - - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - size_t siglen; - - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_crypto_sign_signature( - sm, &siglen, m, mlen, sk); - - memmove(sm + PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_BYTES, m, mlen); - *smlen = siglen + mlen; - - return 0; -} - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk) { - /* The API caller does not necessarily know what size a signature should be - but SPHINCS+ signatures are always exactly PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_BYTES. */ - if (smlen < PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_BYTES) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - *mlen = smlen - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_BYTES; - - if (PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_crypto_sign_verify( - sm, PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_BYTES, sm + PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_BYTES, *mlen, pk)) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - /* If verification was successful, move the message to the right place. */ - memmove(m, sm + PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_BYTES, *mlen); - - return 0; -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_avx2/thash.h b/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_avx2/thash.h deleted file mode 100644 index 25572bb9b0..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_avx2/thash.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_THASH_H -#define PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_THASH_H - -#include "hash_state.h" - -#include - -void PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_avx2/thash_sha256_simple.c b/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_avx2/thash_sha256_simple.c deleted file mode 100644 index 4f6c8c0145..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_avx2/thash_sha256_simple.c +++ /dev/null @@ -1,75 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "thash.h" - -#include "sha2.h" -#include "sha256.h" - -/** - * Takes an array of inblocks concatenated arrays of PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N bytes. - */ -static void PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_thash( - unsigned char *out, unsigned char *buf, - const unsigned char *in, unsigned int inblocks, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char outbuf[PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_OUTPUT_BYTES]; - sha256ctx sha2_state; - - (void)pub_seed; /* Suppress an 'unused parameter' warning. */ - - /* Retrieve precomputed state containing pub_seed */ - sha256_inc_ctx_clone(&sha2_state, &hash_state_seeded->x1); - - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_compress_address(buf, addr); - memcpy(buf + PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_ADDR_BYTES, in, inblocks * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N); - - sha256_inc_finalize(outbuf, &sha2_state, buf, PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N); - memcpy(out, outbuf, PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N); -} - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_ADDR_BYTES + 1 * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N]; - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_thash( - out, buf, in, 1, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_ADDR_BYTES + 2 * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N]; - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_thash( - out, buf, in, 2, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_ADDR_BYTES + PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_WOTS_LEN * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N]; - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_thash( - out, buf, in, PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_WOTS_LEN, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_ADDR_BYTES + PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_FORS_TREES * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N]; - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_thash( - out, buf, in, PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_FORS_TREES, pub_seed, addr, hash_state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_avx2/thash_sha256_simplex8.c b/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_avx2/thash_sha256_simplex8.c deleted file mode 100644 index 1a1835d500..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_avx2/thash_sha256_simplex8.c +++ /dev/null @@ -1,129 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash_state.h" -#include "params.h" -#include "sha256.h" -#include "sha256avx.h" -#include "sha256x8.h" -#include "thashx8.h" -#include "utils.h" - -/** - * 8-way parallel version of thash; takes 8x as much input and output - */ -static void thashx8(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - const unsigned char *in4, - const unsigned char *in5, - const unsigned char *in6, - const unsigned char *in7, unsigned int inblocks, - const unsigned char *pub_seed, uint32_t addrx8[8 * 8], - uint8_t *bufx8, - const hash_state *state_seeded) { - unsigned char outbufx8[8 * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_OUTPUT_BYTES]; - unsigned int i; - sha256ctxx8 ctx; - - (void)pub_seed; /* Suppress an 'unused parameter' warning. */ - - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_sha256_clone_statex8(&ctx, &state_seeded->x8); - - for (i = 0; i < 8; i++) { - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_compress_address(bufx8 + i * (PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N), - addrx8 + i * 8); - } - - memcpy(bufx8 + PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_ADDR_BYTES + - 0 * (PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N), in0, inblocks * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N); - memcpy(bufx8 + PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_ADDR_BYTES + - 1 * (PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N), in1, inblocks * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N); - memcpy(bufx8 + PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_ADDR_BYTES + - 2 * (PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N), in2, inblocks * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N); - memcpy(bufx8 + PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_ADDR_BYTES + - 3 * (PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N), in3, inblocks * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N); - memcpy(bufx8 + PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_ADDR_BYTES + - 4 * (PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N), in4, inblocks * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N); - memcpy(bufx8 + PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_ADDR_BYTES + - 5 * (PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N), in5, inblocks * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N); - memcpy(bufx8 + PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_ADDR_BYTES + - 6 * (PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N), in6, inblocks * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N); - memcpy(bufx8 + PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_ADDR_BYTES + - 7 * (PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N), in7, inblocks * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N); - - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_sha256_update8x(&ctx, - bufx8 + 0 * (PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N), - bufx8 + 1 * (PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N), - bufx8 + 2 * (PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N), - bufx8 + 3 * (PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N), - bufx8 + 4 * (PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N), - bufx8 + 5 * (PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N), - bufx8 + 6 * (PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N), - bufx8 + 7 * (PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N), - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N); - - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_sha256_final8x(&ctx, - outbufx8 + 0 * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 1 * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 2 * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 3 * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 4 * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 5 * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 6 * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 7 * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_OUTPUT_BYTES); - - memcpy(out0, outbufx8 + 0 * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N); - memcpy(out1, outbufx8 + 1 * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N); - memcpy(out2, outbufx8 + 2 * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N); - memcpy(out3, outbufx8 + 3 * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N); - memcpy(out4, outbufx8 + 4 * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N); - memcpy(out5, outbufx8 + 5 * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N); - memcpy(out6, outbufx8 + 6 * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N); - memcpy(out7, outbufx8 + 7 * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N); -} - -#define thashx8_variant_impl(name, size) \ - void PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_thashx8_##name(unsigned char *out0, \ - unsigned char *out1, \ - unsigned char *out2, \ - unsigned char *out3, \ - unsigned char *out4, \ - unsigned char *out5, \ - unsigned char *out6, \ - unsigned char *out7, \ - const unsigned char *in0, \ - const unsigned char *in1, \ - const unsigned char *in2, \ - const unsigned char *in3, \ - const unsigned char *in4, \ - const unsigned char *in5, \ - const unsigned char *in6, \ - const unsigned char *in7, \ - const unsigned char *pub_seed, \ - uint32_t addrx8[8*8], \ - const hash_state *state_seeded) \ - { \ - const unsigned int inblocks = (size); \ - uint8_t bufx8[8*(PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_SHA256_ADDR_BYTES + (size)*PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N)]; \ - thashx8(out0, out1, out2, out3, out4, out5, out6, out7, \ - in0, in1, in2, in3, in4, in5, in6, in7, inblocks, \ - pub_seed, addrx8, bufx8, state_seeded); \ - } - -thashx8_variant_impl(1, 1) -thashx8_variant_impl(2, 2) -thashx8_variant_impl(WOTS_LEN, PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_WOTS_LEN) -thashx8_variant_impl(FORS_TREES, PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_FORS_TREES) - -#undef thashx8_variant_impl diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_avx2/thashx8.h b/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_avx2/thashx8.h deleted file mode 100644 index a2dfebf415..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_avx2/thashx8.h +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_THASHX8_H -#define PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_THASHX8_H - -#include - -#include "hash_state.h" -#include "sha256avx.h" - - -#define thashx8_variant(name) \ - void PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_thashx8_##name( \ - unsigned char *out0, \ - unsigned char *out1, \ - unsigned char *out2, \ - unsigned char *out3, \ - unsigned char *out4, \ - unsigned char *out5, \ - unsigned char *out6, \ - unsigned char *out7, \ - const unsigned char *in0, \ - const unsigned char *in1, \ - const unsigned char *in2, \ - const unsigned char *in3, \ - const unsigned char *in4, \ - const unsigned char *in5, \ - const unsigned char *in6, \ - const unsigned char *in7, \ - const unsigned char *pub_seed, \ - uint32_t addrx8[8*8], \ - const hash_state *state_seeded) - - -thashx8_variant(1); -thashx8_variant(2); -thashx8_variant(WOTS_LEN); -thashx8_variant(FORS_TREES); - -#undef thashx8_variant -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_avx2/utils.c b/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_avx2/utils.c deleted file mode 100644 index d9bee51e12..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_avx2/utils.c +++ /dev/null @@ -1,199 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "hash_state.h" -#include "params.h" -#include "thash.h" -#include "utils.h" - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in) { - - /* Iterate over out in decreasing order, for big-endianness. */ - for (size_t i = outlen; i > 0; i--) { - out[i - 1] = in & 0xff; - in = in >> 8; - } -} - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_bytes_to_ull( - const unsigned char *in, size_t inlen) { - unsigned long long retval = 0; - - for (size_t i = 0; i < inlen; i++) { - retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); - } - return retval; -} - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - uint32_t i; - unsigned char buffer[2 * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N]; - - /* If leaf_idx is odd (last bit = 1), current path element is a right child - and auth_path has to go left. Otherwise it is the other way around. */ - if (leaf_idx & 1) { - memcpy(buffer + PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N, leaf, PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N); - } else { - memcpy(buffer, leaf, PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N); - memcpy(buffer + PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N, auth_path, PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N); - } - auth_path += PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N; - - for (i = 0; i < tree_height - 1; i++) { - leaf_idx >>= 1; - idx_offset >>= 1; - /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_set_tree_height(addr, i + 1); - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_set_tree_index( - addr, leaf_idx + idx_offset); - - /* Pick the right or left neighbor, depending on parity of the node. */ - if (leaf_idx & 1) { - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_thash_2( - buffer + PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N); - } else { - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_thash_2( - buffer, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer + PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N, auth_path, PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N); - } - auth_path += PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N; - } - - /* The last iteration is exceptional; we do not copy an auth_path node. */ - leaf_idx >>= 1; - idx_offset >>= 1; - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_set_tree_height(addr, tree_height); - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_set_tree_index( - addr, leaf_idx + idx_offset); - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_thash_2( - root, buffer, pub_seed, addr, hash_state_seeded); -} - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -static void PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_treehash( - unsigned char *root, unsigned char *auth_path, - unsigned char *stack, unsigned int *heights, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - - unsigned int offset = 0; - uint32_t idx; - uint32_t tree_idx; - - for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { - /* Add the next leaf node to the stack. */ - gen_leaf(stack + offset * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N, - sk_seed, pub_seed, idx + idx_offset, tree_addr, - hash_state_seeded); - offset++; - heights[offset - 1] = 0; - - /* If this is a node we need for the auth path.. */ - if ((leaf_idx ^ 0x1) == idx) { - memcpy(auth_path, stack + (offset - 1)*PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N, PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N); - } - - /* While the top-most nodes are of equal height.. */ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { - /* Compute index of the new node, in the next layer. */ - tree_idx = (idx >> (heights[offset - 1] + 1)); - - /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_set_tree_height( - tree_addr, heights[offset - 1] + 1); - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_set_tree_index( - tree_addr, tree_idx + (idx_offset >> (heights[offset - 1] + 1))); - /* Hash the top-most nodes from the stack together. */ - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_thash_2( - stack + (offset - 2)*PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N, stack + (offset - 2)*PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N, - pub_seed, tree_addr, hash_state_seeded); - offset--; - /* Note that the top-most node is now one layer higher. */ - heights[offset - 1]++; - - /* If this is a node we need for the auth path.. */ - if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_path + heights[offset - 1]*PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N, - stack + (offset - 1)*PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N, PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N); - } - } - } - memcpy(root, stack, PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N); -} - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_FORS_HEIGHT + 1)*PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N]; - unsigned int heights[PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_FORS_HEIGHT + 1]; - - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_FORS_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_TREE_HEIGHT + 1)*PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N]; - unsigned int heights[PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_TREE_HEIGHT + 1]; - - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_TREE_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_avx2/utils.h b/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_avx2/utils.h deleted file mode 100644 index e7eaa762f3..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_avx2/utils.h +++ /dev/null @@ -1,64 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_UTILS_H -#define PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_UTILS_H - -#include "hash_state.h" -#include "params.h" -#include -#include - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in); - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_bytes_to_ull( - const unsigned char *in, size_t inlen); - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -void PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_avx2/utilsx8.c b/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_avx2/utilsx8.c deleted file mode 100644 index 7ecdb4f50b..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_avx2/utilsx8.c +++ /dev/null @@ -1,172 +0,0 @@ -#include - -#include "address.h" -#include "params.h" -#include "thashx8.h" -#include "utils.h" - -#include "utilsx8.h" - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -static void treehashx8(unsigned char *rootx8, unsigned char *auth_pathx8, - unsigned char *stackx8, unsigned int *heights, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t leaf_idx[8], uint32_t idx_offset[8], - uint32_t tree_height, - void (*gen_leafx8)( - unsigned char * /* leaf0 */, - unsigned char * /* leaf1 */, - unsigned char * /* leaf2 */, - unsigned char * /* leaf3 */, - unsigned char * /* leaf4 */, - unsigned char * /* leaf5 */, - unsigned char * /* leaf6 */, - unsigned char * /* leaf7 */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx0 */, - uint32_t /* addr_idx1 */, - uint32_t /* addr_idx2 */, - uint32_t /* addr_idx3 */, - uint32_t /* addr_idx4 */, - uint32_t /* addr_idx5 */, - uint32_t /* addr_idx6 */, - uint32_t /* addr_idx7 */, - const uint32_t[8] /* tree_addr */, - const hash_state * /* state_seeded */), - uint32_t tree_addrx8[8 * 8], - const hash_state *state_seeded) { - unsigned int offset = 0; - uint32_t idx; - uint32_t tree_idx; - unsigned int j; - - for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { - /* Add the next leaf node to the stack. */ - gen_leafx8(stackx8 + 0 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N + offset * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N, - stackx8 + 1 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N + offset * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N, - stackx8 + 2 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N + offset * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N, - stackx8 + 3 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N + offset * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N, - stackx8 + 4 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N + offset * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N, - stackx8 + 5 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N + offset * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N, - stackx8 + 6 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N + offset * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N, - stackx8 + 7 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N + offset * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N, - sk_seed, pub_seed, - idx + idx_offset[0], - idx + idx_offset[1], - idx + idx_offset[2], - idx + idx_offset[3], - idx + idx_offset[4], - idx + idx_offset[5], - idx + idx_offset[6], - idx + idx_offset[7], - tree_addrx8, - state_seeded); - offset++; - heights[offset - 1] = 0; - - /* If this is a node we need for the auth path.. */ - for (j = 0; j < 8; j++) { - if ((leaf_idx[j] ^ 0x1) == idx) { - memcpy(auth_pathx8 + j * tree_height * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N, - stackx8 + j * (tree_height + 1)*PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N + (offset - 1)*PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N, PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N); - } - } - - /* While the top-most nodes are of equal height.. */ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { - /* Compute index of the new node, in the next layer. */ - tree_idx = (idx >> (heights[offset - 1] + 1)); - - /* Set the address of the node we're creating. */ - for (j = 0; j < 8; j++) { - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_set_tree_height(tree_addrx8 + j * 8, heights[offset - 1] + 1); - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_set_tree_index(tree_addrx8 + j * 8, - tree_idx + (idx_offset[j] >> (heights[offset - 1] + 1))); - } - /* Hash the top-most nodes from the stack together. */ - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_thashx8_2(stackx8 + 0 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N, - stackx8 + 1 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N, - stackx8 + 2 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N, - stackx8 + 3 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N, - stackx8 + 4 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N, - stackx8 + 5 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N, - stackx8 + 6 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N, - stackx8 + 7 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N, - stackx8 + 0 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N, - stackx8 + 1 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N, - stackx8 + 2 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N, - stackx8 + 3 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N, - stackx8 + 4 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N, - stackx8 + 5 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N, - stackx8 + 6 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N, - stackx8 + 7 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N, - pub_seed, tree_addrx8, state_seeded); - offset--; - /* Note that the top-most node is now one layer higher. */ - heights[offset - 1]++; - - /* If this is a node we need for the auth path.. */ - for (j = 0; j < 8; j++) { - if (((leaf_idx[j] >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_pathx8 + j * tree_height * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N + heights[offset - 1]*PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N, - stackx8 + j * (tree_height + 1)*PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N + (offset - 1)*PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N, PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N); - } - } - } - } - - for (j = 0; j < 8; j++) { - memcpy(rootx8 + j * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N, stackx8 + j * (tree_height + 1)*PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N, PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N); - } -} - -/* The wrappers below ensure we used fixed-size buffers on the stack (no VLAs) */ - - -#define treehashx8_variant(name, size) \ - void PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_treehashx8_##name( \ - unsigned char *rootx8, unsigned char *auth_pathx8, \ - const unsigned char *sk_seed, const unsigned char *pub_seed, \ - const uint32_t leaf_idx[8], uint32_t idx_offset[8], \ - void (*gen_leafx8)( \ - unsigned char* /* leaf0 */, \ - unsigned char* /* leaf1 */, \ - unsigned char* /* leaf2 */, \ - unsigned char* /* leaf3 */, \ - unsigned char* /* leaf4 */, \ - unsigned char* /* leaf5 */, \ - unsigned char* /* leaf6 */, \ - unsigned char* /* leaf7 */, \ - const unsigned char* /* sk_seed */, \ - const unsigned char* /* pub_seed */, \ - uint32_t /* addr_idx0 */, \ - uint32_t /* addr_idx1 */, \ - uint32_t /* addr_idx2 */, \ - uint32_t /* addr_idx3 */, \ - uint32_t /* addr_idx4 */, \ - uint32_t /* addr_idx5 */, \ - uint32_t /* addr_idx6 */, \ - uint32_t /* addr_idx7 */, \ - const uint32_t[8] /* tree_addr */, \ - const hash_state* /* state_seeded */), \ - uint32_t tree_addrx8[8*8], \ - const hash_state *state_seeded) \ - { \ - const uint32_t tree_height = (size); \ - unsigned char stackx8[8*((size) + 1)*PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N]; \ - unsigned int heights[(size) + 1]; \ - treehashx8(rootx8, auth_pathx8, stackx8, heights, sk_seed, pub_seed, \ - leaf_idx, idx_offset, tree_height, gen_leafx8, tree_addrx8, state_seeded); \ - } - -treehashx8_variant(FORS_HEIGHT, PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_FORS_HEIGHT) - -#undef treehashx8_variant diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_avx2/utilsx8.h b/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_avx2/utilsx8.h deleted file mode 100644 index a33a857853..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_avx2/utilsx8.h +++ /dev/null @@ -1,46 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_UTILSX8_H -#define PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_UTILSX8_H - -#include - -#include "hash_state.h" -#include "params.h" - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ - -void PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_treehashx8_FORS_HEIGHT( - unsigned char *rootx8, unsigned char *auth_pathx8, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t leaf_idx[8], uint32_t idx_offset[8], - void (*gen_leafx8)( - unsigned char * /* leaf0 */, - unsigned char * /* leaf1 */, - unsigned char * /* leaf2 */, - unsigned char * /* leaf3 */, - unsigned char * /* leaf4 */, - unsigned char * /* leaf5 */, - unsigned char * /* leaf6 */, - unsigned char * /* leaf7 */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx0 */, - uint32_t /* addr_idx1 */, - uint32_t /* addr_idx2 */, - uint32_t /* addr_idx3 */, - uint32_t /* addr_idx4 */, - uint32_t /* addr_idx5 */, - uint32_t /* addr_idx6 */, - uint32_t /* addr_idx7 */, - const uint32_t[8] /* tree_addr */, - const hash_state * /* state_seeded */), - uint32_t tree_addrx8[8 * 8], - const hash_state *state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_avx2/wots.c b/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_avx2/wots.c deleted file mode 100644 index 706919f523..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_avx2/wots.c +++ /dev/null @@ -1,240 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "hash_state.h" -#include "hashx8.h" -#include "params.h" -#include "thash.h" -#include "thashx8.h" -#include "utils.h" -#include "wots.h" - -// TODO clarify address expectations, and make them more uniform. -// TODO i.e. do we expect types to be set already? -// TODO and do we expect modifications or copies? - -/** - * Computes the starting value for a chain, i.e. the secret key. - * Expects the address to be complete up to the chain address. - */ -static void wots_gen_sk(unsigned char *sk, const unsigned char *sk_seed, - uint32_t wots_addr[8], const hash_state *state_seeded) { - /* Make sure that the hash address is actually zeroed. */ - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_set_hash_addr(wots_addr, 0); - - /* Generate sk element. */ - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_prf_addr(sk, sk_seed, wots_addr, state_seeded); -} - -/** - * 8-way parallel version of wots_gen_sk; expects 8x as much space in sk - */ -static void wots_gen_skx8(unsigned char *skx8, const unsigned char *sk_seed, - uint32_t wots_addrx8[8 * 8]) { - unsigned int j; - - /* Make sure that the hash address is actually zeroed. */ - for (j = 0; j < 8; j++) { - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_set_hash_addr(wots_addrx8 + j * 8, 0); - } - - /* Generate sk element. */ - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_prf_addrx8(skx8 + 0 * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N, - skx8 + 1 * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N, - skx8 + 2 * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N, - skx8 + 3 * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N, - skx8 + 4 * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N, - skx8 + 5 * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N, - skx8 + 6 * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N, - skx8 + 7 * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N, - sk_seed, wots_addrx8); -} - -/** - * Computes the chaining function. - * out and in have to be n-byte arrays. - * - * Interprets in as start-th value of the chain. - * addr has to contain the address of the chain. - */ -static void gen_chain(unsigned char *out, const unsigned char *in, - unsigned int start, unsigned int steps, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *state_seeded) { - uint32_t i; - - /* Initialize out with the value at position 'start'. */ - memcpy(out, in, PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N); - - /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_WOTS_W; i++) { - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_set_hash_addr(addr, i); - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_thash_1(out, out, pub_seed, addr, state_seeded); - } -} - -/** - * 8-way parallel version of gen_chain; expects 8x as much space in out, and - * 8x as much space in inx8. Assumes start and step identical across chains. - */ -static void gen_chainx8(unsigned char *outx8, const unsigned char *inx8, - unsigned int start, unsigned int steps, - const unsigned char *pub_seed, uint32_t addrx8[8 * 8], - const hash_state *state_seeded) { - uint32_t i; - unsigned int j; - - /* Initialize outx8 with the value at position 'start'. */ - memcpy(outx8, inx8, 8 * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N); - - /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_WOTS_W; i++) { - for (j = 0; j < 8; j++) { - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_set_hash_addr(addrx8 + j * 8, i); - } - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_thashx8_1(outx8 + 0 * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N, - outx8 + 1 * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N, - outx8 + 2 * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N, - outx8 + 3 * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N, - outx8 + 4 * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N, - outx8 + 5 * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N, - outx8 + 6 * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N, - outx8 + 7 * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N, - outx8 + 0 * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N, - outx8 + 1 * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N, - outx8 + 2 * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N, - outx8 + 3 * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N, - outx8 + 4 * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N, - outx8 + 5 * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N, - outx8 + 6 * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N, - outx8 + 7 * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N, - pub_seed, addrx8, state_seeded); - } -} - -/** - * base_w algorithm as described in draft. - * Interprets an array of bytes as integers in base w. - * This only works when log_w is a divisor of 8. - */ -static void base_w(unsigned int *output, const int out_len, const unsigned char *input) { - int in = 0; - int out = 0; - unsigned char total = 0; - int bits = 0; - int consumed; - - for (consumed = 0; consumed < out_len; consumed++) { - if (bits == 0) { - total = input[in]; - in++; - bits += 8; - } - bits -= PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_WOTS_LOGW; - output[out] = (unsigned int)(total >> bits) & (PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_WOTS_W - 1); - out++; - } -} - -/* Computes the WOTS+ checksum over a message (in base_w). */ -static void wots_checksum(unsigned int *csum_base_w, const unsigned int *msg_base_w) { - unsigned int csum = 0; - unsigned char csum_bytes[(PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_WOTS_LEN2 * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_WOTS_LOGW + 7) / 8]; - unsigned int i; - - /* Compute checksum. */ - for (i = 0; i < PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_WOTS_LEN1; i++) { - csum += PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_WOTS_W - 1 - msg_base_w[i]; - } - - /* Convert checksum to base_w. */ - /* Make sure expected empty zero bits are the least significant bits. */ - csum = csum << (8 - ((PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_WOTS_LEN2 * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_WOTS_LOGW) % 8)); - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); - base_w(csum_base_w, PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_WOTS_LEN2, csum_bytes); -} - -/* Takes a message and derives the matching chain lengths. */ -static void chain_lengths(unsigned int *lengths, const unsigned char *msg) { - base_w(lengths, PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_WOTS_LEN1, msg); - wots_checksum(lengths + PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_WOTS_LEN1, lengths); -} - -/** - * WOTS key generation. Takes a 32 byte sk_seed, expands it to WOTS private key - * elements and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_wots_gen_pk(unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *state_seeded) { - uint32_t i; - unsigned int j; - - uint32_t addrx8[8 * 8]; - unsigned char pkbuf[8 * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N]; - - for (j = 0; j < 8; j++) { - memcpy(addrx8 + j * 8, addr, sizeof(uint32_t) * 8); - } - - /* The last iteration typically does not have complete set of 4 chains, - but because we use pkbuf, this is not an issue -- we still do as many - in parallel as possible. */ - for (i = 0; i < ((PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_WOTS_LEN + 7) & ~0x7); i += 8) { - for (j = 0; j < 8; j++) { - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_set_chain_addr(addrx8 + j * 8, i + j); - } - wots_gen_skx8(pkbuf, sk_seed, addrx8); - gen_chainx8(pkbuf, pkbuf, 0, PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_WOTS_W - 1, pub_seed, addrx8, state_seeded); - for (j = 0; j < 8; j++) { - if (i + j < PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_WOTS_LEN) { - memcpy(pk + (i + j)*PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N, pkbuf + j * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N, PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N); - } - } - } -} - -/** - * Takes a n-byte message and the 32-byte sk_see to compute a signature 'sig'. - */ -void PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_wots_sign(unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_WOTS_LEN; i++) { - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_set_chain_addr(addr, i); - wots_gen_sk(sig + i * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N, sk_seed, addr, state_seeded); - gen_chain(sig + i * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N, sig + i * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N, 0, lengths[i], pub_seed, addr, state_seeded); - } -} - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_WOTS_LEN; i++) { - PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_set_chain_addr(addr, i); - gen_chain(pk + i * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N, sig + i * PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_N, - lengths[i], PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_WOTS_W - 1 - lengths[i], pub_seed, addr, state_seeded); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_avx2/wots.h b/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_avx2/wots.h deleted file mode 100644 index 5edda14fef..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_avx2/wots.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_WOTS_H -#define PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_WOTS_H - -#include "hash_state.h" -#include "params.h" -#include - -/** - * WOTS key generation. Takes a 32 byte seed for the private key, expands it to - * a full WOTS private key and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_wots_gen_pk( - unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -/** - * Takes a n-byte message and the 32-byte seed for the private key to compute a - * signature that is placed at 'sig'. - */ -void PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_wots_sign( - unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *hash_state_seeded); - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHA256192SSIMPLE_AVX2_wots_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_clean/LICENSE b/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_clean/LICENSE deleted file mode 100644 index 670154e353..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_clean/LICENSE +++ /dev/null @@ -1,116 +0,0 @@ -CC0 1.0 Universal - -Statement of Purpose - -The laws of most jurisdictions throughout the world automatically confer -exclusive Copyright and Related Rights (defined below) upon the creator and -subsequent owner(s) (each and all, an "owner") of an original work of -authorship and/or a database (each, a "Work"). - -Certain owners wish to permanently relinquish those rights to a Work for the -purpose of contributing to a commons of creative, cultural and scientific -works ("Commons") that the public can reliably and without fear of later -claims of infringement build upon, modify, incorporate in other works, reuse -and redistribute as freely as possible in any form whatsoever and for any -purposes, including without limitation commercial purposes. These owners may -contribute to the Commons to promote the ideal of a free culture and the -further production of creative, cultural and scientific works, or to gain -reputation or greater distribution for their Work in part through the use and -efforts of others. - -For these and/or other purposes and motivations, and without any expectation -of additional consideration or compensation, the person associating CC0 with a -Work (the "Affirmer"), to the extent that he or she is an owner of Copyright -and Related Rights in the Work, voluntarily elects to apply CC0 to the Work -and publicly distribute the Work under its terms, with knowledge of his or her -Copyright and Related Rights in the Work and the meaning and intended legal -effect of CC0 on those rights. - -1. Copyright and Related Rights. A Work made available under CC0 may be -protected by copyright and related or neighboring rights ("Copyright and -Related Rights"). Copyright and Related Rights include, but are not limited -to, the following: - - i. the right to reproduce, adapt, distribute, perform, display, communicate, - and translate a Work; - - ii. moral rights retained by the original author(s) and/or performer(s); - - iii. publicity and privacy rights pertaining to a person's image or likeness - depicted in a Work; - - iv. rights protecting against unfair competition in regards to a Work, - subject to the limitations in paragraph 4(a), below; - - v. rights protecting the extraction, dissemination, use and reuse of data in - a Work; - - vi. database rights (such as those arising under Directive 96/9/EC of the - European Parliament and of the Council of 11 March 1996 on the legal - protection of databases, and under any national implementation thereof, - including any amended or successor version of such directive); and - - vii. other similar, equivalent or corresponding rights throughout the world - based on applicable law or treaty, and any national implementations thereof. - -2. Waiver. To the greatest extent permitted by, but not in contravention of, -applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and -unconditionally waives, abandons, and surrenders all of Affirmer's Copyright -and Related Rights and associated claims and causes of action, whether now -known or unknown (including existing as well as future claims and causes of -action), in the Work (i) in all territories worldwide, (ii) for the maximum -duration provided by applicable law or treaty (including future time -extensions), (iii) in any current or future medium and for any number of -copies, and (iv) for any purpose whatsoever, including without limitation -commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes -the Waiver for the benefit of each member of the public at large and to the -detriment of Affirmer's heirs and successors, fully intending that such Waiver -shall not be subject to revocation, rescission, cancellation, termination, or -any other legal or equitable action to disrupt the quiet enjoyment of the Work -by the public as contemplated by Affirmer's express Statement of Purpose. - -3. Public License Fallback. Should any part of the Waiver for any reason be -judged legally invalid or ineffective under applicable law, then the Waiver -shall be preserved to the maximum extent permitted taking into account -Affirmer's express Statement of Purpose. In addition, to the extent the Waiver -is so judged Affirmer hereby grants to each affected person a royalty-free, -non transferable, non sublicensable, non exclusive, irrevocable and -unconditional license to exercise Affirmer's Copyright and Related Rights in -the Work (i) in all territories worldwide, (ii) for the maximum duration -provided by applicable law or treaty (including future time extensions), (iii) -in any current or future medium and for any number of copies, and (iv) for any -purpose whatsoever, including without limitation commercial, advertising or -promotional purposes (the "License"). The License shall be deemed effective as -of the date CC0 was applied by Affirmer to the Work. Should any part of the -License for any reason be judged legally invalid or ineffective under -applicable law, such partial invalidity or ineffectiveness shall not -invalidate the remainder of the License, and in such case Affirmer hereby -affirms that he or she will not (i) exercise any of his or her remaining -Copyright and Related Rights in the Work or (ii) assert any associated claims -and causes of action with respect to the Work, in either case contrary to -Affirmer's express Statement of Purpose. - -4. Limitations and Disclaimers. - - a. No trademark or patent rights held by Affirmer are waived, abandoned, - surrendered, licensed or otherwise affected by this document. - - b. Affirmer offers the Work as-is and makes no representations or warranties - of any kind concerning the Work, express, implied, statutory or otherwise, - including without limitation warranties of title, merchantability, fitness - for a particular purpose, non infringement, or the absence of latent or - other defects, accuracy, or the present or absence of errors, whether or not - discoverable, all to the greatest extent permissible under applicable law. - - c. Affirmer disclaims responsibility for clearing rights of other persons - that may apply to the Work or any use thereof, including without limitation - any person's Copyright and Related Rights in the Work. Further, Affirmer - disclaims responsibility for obtaining any necessary consents, permissions - or other rights required for any use of the Work. - - d. Affirmer understands and acknowledges that Creative Commons is not a - party to this document and has no duty or obligation with respect to this - CC0 or use of the Work. - -For more information, please see - diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_clean/address.c b/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_clean/address.c deleted file mode 100644 index 6167103d8d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_clean/address.c +++ /dev/null @@ -1,78 +0,0 @@ -#include - -#include "address.h" -#include "params.h" -#include "utils.h" - -void PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]) { - int i; - - for (i = 0; i < 8; i++) { - PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_ull_to_bytes( - bytes + i * 4, 4, addr[i]); - } -} - -void PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_set_layer_addr( - uint32_t addr[8], uint32_t layer) { - addr[0] = layer; -} - -void PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_set_tree_addr( - uint32_t addr[8], uint64_t tree) { - addr[1] = 0; - addr[2] = (uint32_t) (tree >> 32); - addr[3] = (uint32_t) tree; -} - -void PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_set_type( - uint32_t addr[8], uint32_t type) { - addr[4] = type; -} - -void PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; -} - -/* These functions are used for OTS addresses. */ - -void PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_set_keypair_addr( - uint32_t addr[8], uint32_t keypair) { - addr[5] = keypair; -} - -void PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; - out[5] = in[5]; -} - -void PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_set_chain_addr( - uint32_t addr[8], uint32_t chain) { - addr[6] = chain; -} - -void PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_set_hash_addr( - uint32_t addr[8], uint32_t hash) { - addr[7] = hash; -} - -/* These functions are used for all hash tree addresses (including FORS). */ - -void PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_set_tree_height( - uint32_t addr[8], uint32_t tree_height) { - addr[6] = tree_height; -} - -void PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_set_tree_index( - uint32_t addr[8], uint32_t tree_index) { - addr[7] = tree_index; -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_clean/address.h b/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_clean/address.h deleted file mode 100644 index 9f5ba41344..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_clean/address.h +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_ADDRESS_H -#define PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_ADDRESS_H - -#include - -#define PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_ADDR_TYPE_WOTS 0 -#define PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_ADDR_TYPE_WOTSPK 1 -#define PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_ADDR_TYPE_HASHTREE 2 -#define PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_ADDR_TYPE_FORSTREE 3 -#define PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_ADDR_TYPE_FORSPK 4 - -void PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]); - -void PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_set_layer_addr( - uint32_t addr[8], uint32_t layer); - -void PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_set_tree_addr( - uint32_t addr[8], uint64_t tree); - -void PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_set_type( - uint32_t addr[8], uint32_t type); - -/* Copies the layer and tree part of one address into the other */ -void PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for WOTS and FORS addresses. */ - -void PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_set_keypair_addr( - uint32_t addr[8], uint32_t keypair); - -void PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_set_chain_addr( - uint32_t addr[8], uint32_t chain); - -void PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_set_hash_addr( - uint32_t addr[8], uint32_t hash); - -void PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for all hash tree addresses (including FORS). */ - -void PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_set_tree_height( - uint32_t addr[8], uint32_t tree_height); - -void PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_set_tree_index( - uint32_t addr[8], uint32_t tree_index); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_clean/api.h b/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_clean/api.h deleted file mode 100644 index 6fd0da9b86..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_clean/api.h +++ /dev/null @@ -1,81 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_API_H -#define PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_API_H - -#include -#include - - - -#define PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_CRYPTO_ALGNAME "SPHINCS+" - -#define PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_CRYPTO_SECRETKEYBYTES 96 -#define PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_CRYPTO_PUBLICKEYBYTES 48 -#define PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_CRYPTO_BYTES 16224 -#define PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_CRYPTO_SEEDBYTES 72 - - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_clean/fors.c b/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_clean/fors.c deleted file mode 100644 index 6a073d1291..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_clean/fors.c +++ /dev/null @@ -1,161 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "fors.h" -#include "hash.h" -#include "hash_state.h" -#include "thash.h" -#include "utils.h" - -static void fors_gen_sk(unsigned char *sk, const unsigned char *sk_seed, - uint32_t fors_leaf_addr[8], const hash_state *hash_state_seeded) { - PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_prf_addr( - sk, sk_seed, fors_leaf_addr, hash_state_seeded); -} - -static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, - const unsigned char *pub_seed, - uint32_t fors_leaf_addr[8], - const hash_state *hash_state_seeded) { - PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_thash_1( - leaf, sk, pub_seed, fors_leaf_addr, hash_state_seeded); -} - -static void fors_gen_leaf(unsigned char *leaf, const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx, const uint32_t fors_tree_addr[8], - const hash_state *hash_state_seeded) { - uint32_t fors_leaf_addr[8] = {0}; - - /* Only copy the parts that must be kept in fors_leaf_addr. */ - PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_copy_keypair_addr( - fors_leaf_addr, fors_tree_addr); - PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_set_type( - fors_leaf_addr, PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_set_tree_index( - fors_leaf_addr, addr_idx); - - fors_gen_sk(leaf, sk_seed, fors_leaf_addr, hash_state_seeded); - fors_sk_to_leaf(leaf, leaf, pub_seed, fors_leaf_addr, hash_state_seeded); -} - -/** - * Interprets m as PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_FORS_HEIGHT-bit unsigned integers. - * Assumes m contains at least PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_FORS_TREES bits. - * Assumes indices has space for PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_FORS_TREES integers. - */ -static void message_to_indices(uint32_t *indices, const unsigned char *m) { - unsigned int i, j; - unsigned int offset = 0; - - for (i = 0; i < PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_FORS_TREES; i++) { - indices[i] = 0; - for (j = 0; j < PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_FORS_HEIGHT; j++) { - indices[i] ^= (((uint32_t)m[offset >> 3] >> (offset & 0x7)) & 0x1) << j; - offset++; - } - } -} - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_fors_sign( - unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *hash_state_seeded) { - uint32_t indices[PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_FORS_TREES]; - unsigned char roots[PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_FORS_TREES * PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_N]; - uint32_t fors_tree_addr[8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_copy_keypair_addr( - fors_tree_addr, fors_addr); - PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_copy_keypair_addr( - fors_pk_addr, fors_addr); - - PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_set_type( - fors_tree_addr, PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_set_type( - fors_pk_addr, PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_FORS_TREES; i++) { - idx_offset = i * (1 << PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_FORS_HEIGHT); - - PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_set_tree_height( - fors_tree_addr, 0); - PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_set_tree_index( - fors_tree_addr, indices[i] + idx_offset); - - /* Include the secret key part that produces the selected leaf node. */ - fors_gen_sk(sig, sk_seed, fors_tree_addr, hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_N; - - /* Compute the authentication path for this leaf node. */ - PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_treehash_FORS_HEIGHT( - roots + i * PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_N, sig, sk_seed, pub_seed, - indices[i], idx_offset, fors_gen_leaf, fors_tree_addr, - hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_N * PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_thash_FORS_TREES( - pk, roots, pub_seed, fors_pk_addr, hash_state_seeded); -} - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_fors_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, const uint32_t fors_addr[8], - const hash_state *hash_state_seeded) { - uint32_t indices[PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_FORS_TREES]; - unsigned char roots[PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_FORS_TREES * PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_N]; - unsigned char leaf[PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_N]; - uint32_t fors_tree_addr[8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_copy_keypair_addr(fors_tree_addr, fors_addr); - PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_copy_keypair_addr(fors_pk_addr, fors_addr); - - PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_set_type(fors_tree_addr, PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_set_type(fors_pk_addr, PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_FORS_TREES; i++) { - idx_offset = i * (1 << PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_FORS_HEIGHT); - - PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_set_tree_height(fors_tree_addr, 0); - PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Derive the leaf from the included secret key part. */ - fors_sk_to_leaf(leaf, sig, pub_seed, fors_tree_addr, hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_N; - - /* Derive the corresponding root node of this tree. */ - PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_compute_root(roots + i * PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_N, leaf, indices[i], idx_offset, sig, - PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_FORS_HEIGHT, pub_seed, fors_tree_addr, hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_N * PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_thash_FORS_TREES(pk, roots, pub_seed, fors_pk_addr, hash_state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_clean/fors.h b/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_clean/fors.h deleted file mode 100644 index a0defabe65..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_clean/fors.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_FORS_H -#define PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_FORS_H - -#include - -#include "hash_state.h" -#include "params.h" - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_fors_sign( - unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *hash_state_seeded); - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_fors_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, const uint32_t fors_addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_clean/hash.h b/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_clean/hash.h deleted file mode 100644 index 54bac4cf98..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_clean/hash.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_HASH_H -#define PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_HASH_H - -#include "hash_state.h" - -#include -#include - -void PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_initialize_hash_function( - hash_state *hash_state_seeded, - const unsigned char *pub_seed, const unsigned char *sk_seed); - -void PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_destroy_hash_function(hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_clean/hash_sha256.c b/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_clean/hash_sha256.c deleted file mode 100644 index 8b7aeee2f4..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_clean/hash_sha256.c +++ /dev/null @@ -1,162 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "utils.h" - -#include "sha2.h" -#include "sha256.h" - -/* For SHA256, there is no immediate reason to initialize at the start, - so this function is an empty operation. */ -void PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_initialize_hash_function( - hash_state *hash_state_seeded, - const unsigned char *pub_seed, const unsigned char *sk_seed) { - PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_seed_state(hash_state_seeded, pub_seed); - (void)sk_seed; /* Suppress an 'unused parameter' warning. */ -} - -/* Clean up hash state */ -void PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_destroy_hash_function(hash_state *hash_state_seeded) { - sha256_inc_ctx_release(hash_state_seeded); -} - -/* - * Computes PRF(key, addr), given a secret key of PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_N bytes and an address - */ -void PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded) { - unsigned char buf[PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_N + PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_SHA256_ADDR_BYTES]; - unsigned char outbuf[PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_SHA256_OUTPUT_BYTES]; - - memcpy(buf, key, PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_N); - PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_compress_address(buf + PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_N, addr); - - sha256(outbuf, buf, PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_N + PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_SHA256_ADDR_BYTES); - memcpy(out, outbuf, PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_N); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} - -/** - * Computes the message-dependent randomness R, using a secret seed as a key - * for HMAC, and an optional randomization value prefixed to the message. - * This requires m to have at least PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_SHA256_BLOCK_BYTES + PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_N space - * available in front of the pointer, i.e. before the message to use for the - * prefix. This is necessary to prevent having to move the message around (and - * allocate memory for it). - */ -void PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, const hash_state *hash_state_seeded) { - unsigned char buf[PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_SHA256_BLOCK_BYTES + PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_SHA256_OUTPUT_BYTES]; - sha256ctx state; - int i; - - /* This implements HMAC-SHA256 */ - for (i = 0; i < PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_N; i++) { - buf[i] = 0x36 ^ sk_prf[i]; - } - memset(buf + PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_N, 0x36, PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_N); - - sha256_inc_init(&state); - sha256_inc_blocks(&state, buf, 1); - - memcpy(buf, optrand, PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_N); - - /* If optrand + message cannot fill up an entire block */ - if (PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_N + mlen < PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_SHA256_BLOCK_BYTES) { - memcpy(buf + PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_N, m, mlen); - sha256_inc_finalize(buf + PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_SHA256_BLOCK_BYTES, &state, - buf, mlen + PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_N); - } - /* Otherwise first fill a block, so that finalize only uses the message */ - else { - memcpy(buf + PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_N, m, PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_N); - sha256_inc_blocks(&state, buf, 1); - - m += PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_N; - mlen -= PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_N; - sha256_inc_finalize(buf + PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_SHA256_BLOCK_BYTES, &state, m, mlen); - } - - for (i = 0; i < PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_N; i++) { - buf[i] = 0x5c ^ sk_prf[i]; - } - memset(buf + PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_N, 0x5c, PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_N); - - sha256(buf, buf, PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_SHA256_BLOCK_BYTES + PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_SHA256_OUTPUT_BYTES); - memcpy(R, buf, PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_N); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} - -/** - * Computes the message hash using R, the public key, and the message. - * Outputs the message digest and the index of the leaf. The index is split in - * the tree index and the leaf index, for convenient copying to an address. - */ -void PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded) { -#define PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_TREE_BITS (PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_TREE_HEIGHT * (PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_D - 1)) -#define PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_TREE_BYTES ((PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_TREE_BITS + 7) / 8) -#define PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_LEAF_BITS PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_TREE_HEIGHT -#define PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_LEAF_BYTES ((PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_LEAF_BITS + 7) / 8) -#define PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_DGST_BYTES (PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_FORS_MSG_BYTES + PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_TREE_BYTES + PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_LEAF_BYTES) - - unsigned char seed[PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_SHA256_OUTPUT_BYTES + 4]; - - /* Round to nearest multiple of PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_SHA256_BLOCK_BYTES */ -#define PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_INBLOCKS (((PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_N + PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_PK_BYTES + PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_SHA256_BLOCK_BYTES - 1) & \ - -PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_SHA256_BLOCK_BYTES) / PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_SHA256_BLOCK_BYTES) - unsigned char inbuf[PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_INBLOCKS * PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_SHA256_BLOCK_BYTES]; - - unsigned char buf[PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_DGST_BYTES]; - unsigned char *bufp = buf; - sha256ctx state; - - sha256_inc_init(&state); - - memcpy(inbuf, R, PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_N); - memcpy(inbuf + PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_N, pk, PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_PK_BYTES); - - /* If R + pk + message cannot fill up an entire block */ - if (PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_N + PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_PK_BYTES + mlen < PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_INBLOCKS * PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_SHA256_BLOCK_BYTES) { - memcpy(inbuf + PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_N + PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_PK_BYTES, m, mlen); - sha256_inc_finalize(seed, &state, inbuf, PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_N + PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_PK_BYTES + mlen); - } - /* Otherwise first fill a block, so that finalize only uses the message */ - else { - memcpy(inbuf + PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_N + PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_PK_BYTES, m, - PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_INBLOCKS * PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_N - PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_PK_BYTES); - sha256_inc_blocks(&state, inbuf, PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_INBLOCKS); - - m += PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_INBLOCKS * PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_N - PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_PK_BYTES; - mlen -= PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_INBLOCKS * PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_N - PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_PK_BYTES; - sha256_inc_finalize(seed, &state, m, mlen); - } - - /* By doing this in two steps, we prevent hashing the message twice; - otherwise each iteration in MGF1 would hash the message again. */ - PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_mgf1(bufp, PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_DGST_BYTES, seed, PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_SHA256_OUTPUT_BYTES); - - memcpy(digest, bufp, PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_FORS_MSG_BYTES); - bufp += PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_FORS_MSG_BYTES; - - *tree = PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_bytes_to_ull(bufp, PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_TREE_BYTES); - *tree &= (~(uint64_t)0) >> (64 - PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_TREE_BITS); - bufp += PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_TREE_BYTES; - - *leaf_idx = (uint32_t)PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_bytes_to_ull( - bufp, PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_LEAF_BYTES); - *leaf_idx &= (~(uint32_t)0) >> (32 - PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_LEAF_BITS); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_clean/hash_state.h b/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_clean/hash_state.h deleted file mode 100644 index 19fc335e27..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_clean/hash_state.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef SPX_HASH_STATE_H -#define SPX_HASH_STATE_H - -/** - * Defines the type of the hash function state. - * - * Don't be fooled into thinking this instance of SPHINCS+ isn't stateless! - * - * From Section 7.2.2 from the SPHINCS+ round-2 specification: - * - * Each of the instances of the tweakable hash function take PK.seed as its - * first input, which is constant for a given key pair – and, thus, across - * a single signature. This leads to a lot of redundant computation. To remedy - * this, we pad PK.seed to the length of a full 64-byte SHA-256 input block. - * Because of the Merkle-Damgård construction that underlies SHA-256, this - * allows for reuse of the intermediate SHA-256 state after the initial call to - * the compression function which improves performance. - * - * We pass this hash state around in functions, because otherwise we need to - * have a global variable. - */ - -#include "sha2.h" -#define hash_state sha256ctx - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_clean/params.h b/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_clean/params.h deleted file mode 100644 index 2ad30041d5..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_clean/params.h +++ /dev/null @@ -1,53 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_PARAMS_H -#define PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_PARAMS_H - -/* Hash output length in bytes. */ -#define PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_N 24 -/* Height of the hypertree. */ -#define PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_FULL_HEIGHT 63 -/* Number of subtree layer. */ -#define PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_D 7 -/* FORS tree dimensions. */ -#define PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_FORS_HEIGHT 14 -#define PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_FORS_TREES 17 -/* Winternitz parameter, */ -#define PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_WOTS_W 16 - -/* The hash function is defined by linking a different hash.c file, as opposed - to setting a #define constant. */ - -/* For clarity */ -#define PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_ADDR_BYTES 32 - -/* WOTS parameters. */ -#define PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_WOTS_LOGW 4 - -#define PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_WOTS_LEN1 (8 * PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_N / PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_WOTS_LOGW) - -/* PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#define PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_WOTS_LEN2 3 - -#define PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_WOTS_LEN (PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_WOTS_LEN1 + PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_WOTS_LEN2) -#define PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_WOTS_BYTES (PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_WOTS_LEN * PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_N) -#define PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_WOTS_PK_BYTES PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_WOTS_BYTES - -/* Subtree size. */ -#define PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_TREE_HEIGHT (PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_FULL_HEIGHT / PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_D) - -/* FORS parameters. */ -#define PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_FORS_MSG_BYTES ((PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_FORS_TREES + 7) / 8) -#define PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_FORS_BYTES ((PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_FORS_HEIGHT + 1) * PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_FORS_TREES * PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_N) -#define PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_FORS_PK_BYTES PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_N - -/* Resulting SPX sizes. */ -#define PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_BYTES (PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_N + PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_FORS_BYTES + PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_D * PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_WOTS_BYTES +\ - PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_FULL_HEIGHT * PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_N) -#define PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_PK_BYTES (2 * PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_N) -#define PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_SK_BYTES (2 * PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_N + PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_PK_BYTES) - -/* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ -#define PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_OPTRAND_BYTES 32 - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_clean/sha256.c b/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_clean/sha256.c deleted file mode 100644 index 7ffadf35ae..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_clean/sha256.c +++ /dev/null @@ -1,71 +0,0 @@ -/* Based on the public domain implementation in - * crypto_hash/sha512/ref/ from http://bench.cr.yp.to/supercop.html - * by D. J. Bernstein */ - -#include -#include -#include - -#include "sha2.h" -#include "sha256.h" -#include "utils.h" - -/* - * Compresses an address to a 22-byte sequence. - * This reduces the number of required SHA256 compression calls, as the last - * block of input is padded with at least 65 bits. - */ -void PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_compress_address(unsigned char *out, const uint32_t addr[8]) { - PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_ull_to_bytes(out, 1, addr[0]); /* drop 3 bytes of the layer field */ - PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_ull_to_bytes(out + 1, 4, addr[2]); /* drop the highest tree address word */ - PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_ull_to_bytes(out + 5, 4, addr[3]); - PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_ull_to_bytes(out + 9, 1, addr[4]); /* drop 3 bytes of the type field */ - PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_ull_to_bytes(out + 10, 4, addr[5]); - PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_ull_to_bytes(out + 14, 4, addr[6]); - PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_ull_to_bytes(out + 18, 4, addr[7]); -} - -/** - * Requires 'input_plus_four_bytes' to have 'inlen' + 4 bytes, so that the last - * four bytes can be used for the counter. Typically 'input' is merely a seed. - * Outputs outlen number of bytes - */ -void PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_mgf1( - unsigned char *out, unsigned long outlen, - unsigned char *input_plus_four_bytes, unsigned long inlen) { - unsigned char outbuf[PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_SHA256_OUTPUT_BYTES]; - unsigned long i; - - /* While we can fit in at least another full block of SHA256 output.. */ - for (i = 0; (i + 1)*PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_SHA256_OUTPUT_BYTES <= outlen; i++) { - PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_ull_to_bytes(input_plus_four_bytes + inlen, 4, i); - sha256(out, input_plus_four_bytes, inlen + 4); - out += PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_SHA256_OUTPUT_BYTES; - } - /* Until we cannot anymore, and we fill the remainder. */ - if (outlen > i * PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_SHA256_OUTPUT_BYTES) { - PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_ull_to_bytes(input_plus_four_bytes + inlen, 4, i); - sha256(outbuf, input_plus_four_bytes, inlen + 4); - memcpy(out, outbuf, outlen - i * PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_SHA256_OUTPUT_BYTES); - } -} - - -/** - * Absorb the constant pub_seed using one round of the compression function - * This initializes hash_state_seeded, which can then be reused in thash - **/ -void PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_seed_state(sha256ctx *hash_state_seeded, const unsigned char *pub_seed) { - uint8_t block[PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_SHA256_BLOCK_BYTES]; - size_t i; - - for (i = 0; i < PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_N; ++i) { - block[i] = pub_seed[i]; - } - for (i = PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_N; i < PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_SHA256_BLOCK_BYTES; ++i) { - block[i] = 0; - } - - sha256_inc_init(hash_state_seeded); - sha256_inc_blocks(hash_state_seeded, block, 1); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_clean/sha256.h b/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_clean/sha256.h deleted file mode 100644 index c0f8f8f69e..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_clean/sha256.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_SHA256_H -#define PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_SHA256_H - -#define PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_SHA256_BLOCK_BYTES 64 -#define PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_SHA256_OUTPUT_BYTES 32 /* This does not necessarily equal PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_N */ -#define PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_SHA256_ADDR_BYTES 22 - -#include -#include - -#include "sha2.h" - -void PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_compress_address(unsigned char *out, const uint32_t addr[8]); - -void PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_mgf1( - unsigned char *out, unsigned long outlen, - unsigned char *input_plus_four_bytes, unsigned long inlen); - -void PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_seed_state(sha256ctx *hash_state_seeded, const unsigned char *pub_seed); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_clean/sign.c b/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_clean/sign.c deleted file mode 100644 index abf5aba225..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_clean/sign.c +++ /dev/null @@ -1,356 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "api.h" -#include "fors.h" -#include "hash.h" -#include "hash_state.h" -#include "params.h" -#include "randombytes.h" -#include "thash.h" -#include "utils.h" -#include "wots.h" - -/** - * Computes the leaf at a given address. First generates the WOTS key pair, - * then computes leaf by hashing horizontally. - */ -static void wots_gen_leaf(unsigned char *leaf, const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx, const uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - unsigned char pk[PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_WOTS_BYTES]; - uint32_t wots_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_set_type( - wots_addr, PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_set_type( - wots_pk_addr, PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_ADDR_TYPE_WOTSPK); - - PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_set_keypair_addr( - wots_addr, addr_idx); - PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_wots_gen_pk( - pk, sk_seed, pub_seed, wots_addr, hash_state_seeded); - - PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_copy_keypair_addr( - wots_pk_addr, wots_addr); - PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_thash_WOTS_LEN( - leaf, pk, pub_seed, wots_pk_addr, hash_state_seeded); -} - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_crypto_sign_secretkeybytes(void) { - return PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_CRYPTO_SECRETKEYBYTES; -} - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_crypto_sign_publickeybytes(void) { - return PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_CRYPTO_PUBLICKEYBYTES; -} - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_crypto_sign_bytes(void) { - return PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_CRYPTO_BYTES; -} - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_crypto_sign_seedbytes(void) { - return PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_CRYPTO_SEEDBYTES; -} - -/* - * Generates an SPX key pair given a seed of length - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed) { - /* We do not need the auth path in key generation, but it simplifies the - code to have just one treehash routine that computes both root and path - in one function. */ - unsigned char auth_path[PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_TREE_HEIGHT * PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_N]; - uint32_t top_tree_addr[8] = {0}; - hash_state hash_state_seeded; - - PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_set_layer_addr( - top_tree_addr, PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_D - 1); - PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_set_type( - top_tree_addr, PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_ADDR_TYPE_HASHTREE); - - /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ - memcpy(sk, seed, PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_CRYPTO_SEEDBYTES); - - memcpy(pk, sk + 2 * PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_N, PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_initialize_hash_function(&hash_state_seeded, pk, sk); - - /* Compute root node of the top-most subtree. */ - PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_treehash_TREE_HEIGHT( - sk + 3 * PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_N, auth_path, sk, sk + 2 * PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_N, 0, 0, - wots_gen_leaf, top_tree_addr, &hash_state_seeded); - - memcpy(pk + PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_N, sk + 3 * PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_N, PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_N); - - PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_destroy_hash_function(&hash_state_seeded); - return 0; -} - -/* - * Generates an SPX key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk) { - unsigned char seed[PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_CRYPTO_SEEDBYTES]; - randombytes(seed, PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_CRYPTO_SEEDBYTES); - PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_crypto_sign_seed_keypair( - pk, sk, seed); - - return 0; -} - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - const unsigned char *sk_seed = sk; - const unsigned char *sk_prf = sk + PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_N; - const unsigned char *pk = sk + 2 * PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_N; - const unsigned char *pub_seed = pk; - - unsigned char optrand[PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_N]; - unsigned char mhash[PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_FORS_MSG_BYTES]; - unsigned char root[PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_N]; - uint32_t i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - - hash_state hash_state_seeded; - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_initialize_hash_function( - &hash_state_seeded, - pub_seed, sk_seed); - - PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_set_type( - wots_addr, PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_set_type( - tree_addr, PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_ADDR_TYPE_HASHTREE); - - /* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ - randombytes(optrand, PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_N); - /* Compute the digest randomization value. */ - PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_gen_message_random( - sig, sk_prf, optrand, m, mlen, &hash_state_seeded); - - /* Derive the message digest and leaf index from R, PK and M. */ - PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_N; - - PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); - - /* Sign the message hash using FORS. */ - PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_fors_sign( - sig, root, mhash, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_FORS_BYTES; - - for (i = 0; i < PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_D; i++) { - PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_set_tree_addr(tree_addr, tree); - - PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); - - /* Compute a WOTS signature. */ - PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_wots_sign( - sig, root, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_WOTS_BYTES; - - /* Compute the authentication path for the used WOTS leaf. */ - PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_treehash_TREE_HEIGHT( - root, sig, sk_seed, pub_seed, idx_leaf, 0, - wots_gen_leaf, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_TREE_HEIGHT * PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_TREE_HEIGHT; - } - - *siglen = PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_BYTES; - - PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_destroy_hash_function(&hash_state_seeded); - return 0; -} - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk) { - const unsigned char *pub_seed = pk; - const unsigned char *pub_root = pk + PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_N; - unsigned char mhash[PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_FORS_MSG_BYTES]; - unsigned char wots_pk[PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_WOTS_BYTES]; - unsigned char root[PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_N]; - unsigned char leaf[PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_N]; - unsigned int i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - hash_state hash_state_seeded; - - if (siglen != PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_BYTES) { - return -1; - } - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_initialize_hash_function( - &hash_state_seeded, - pub_seed, NULL); - - PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_set_type( - wots_addr, PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_set_type( - tree_addr, PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_ADDR_TYPE_HASHTREE); - PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_set_type( - wots_pk_addr, PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_ADDR_TYPE_WOTSPK); - - /* Derive the message digest and leaf index from R || PK || M. */ - /* The additional PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_N is a result of the hash domain separator. */ - PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_N; - - /* Layer correctly defaults to 0, so no need to set_layer_addr */ - PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); - - PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_fors_pk_from_sig( - root, sig, mhash, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_FORS_BYTES; - - /* For each subtree.. */ - for (i = 0; i < PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_D; i++) { - PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_set_tree_addr(tree_addr, tree); - - PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); - - PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_copy_keypair_addr( - wots_pk_addr, wots_addr); - - /* The WOTS public key is only correct if the signature was correct. */ - /* Initially, root is the FORS pk, but on subsequent iterations it is - the root of the subtree below the currently processed subtree. */ - PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_wots_pk_from_sig( - wots_pk, sig, root, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_WOTS_BYTES; - - /* Compute the leaf node using the WOTS public key. */ - PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_thash_WOTS_LEN( - leaf, wots_pk, pub_seed, wots_pk_addr, &hash_state_seeded); - - /* Compute the root node of this subtree. */ - PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_compute_root( - root, leaf, idx_leaf, 0, sig, PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_TREE_HEIGHT, - pub_seed, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_TREE_HEIGHT * PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_TREE_HEIGHT; - } - - PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_destroy_hash_function(&hash_state_seeded); - /* Check if the root node equals the root node in the public key. */ - if (memcmp(root, pub_root, PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_N) != 0) { - return -1; - } - - return 0; -} - - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - size_t siglen; - - PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_crypto_sign_signature( - sm, &siglen, m, mlen, sk); - - memmove(sm + PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_BYTES, m, mlen); - *smlen = siglen + mlen; - - return 0; -} - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk) { - /* The API caller does not necessarily know what size a signature should be - but SPHINCS+ signatures are always exactly PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_BYTES. */ - if (smlen < PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_BYTES) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - *mlen = smlen - PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_BYTES; - - if (PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_crypto_sign_verify( - sm, PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_BYTES, sm + PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_BYTES, *mlen, pk)) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - /* If verification was successful, move the message to the right place. */ - memmove(m, sm + PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_BYTES, *mlen); - - return 0; -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_clean/thash.h b/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_clean/thash.h deleted file mode 100644 index ba826230d5..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_clean/thash.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_THASH_H -#define PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_THASH_H - -#include "hash_state.h" - -#include - -void PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_clean/thash_sha256_simple.c b/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_clean/thash_sha256_simple.c deleted file mode 100644 index 7a59f4e8b6..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_clean/thash_sha256_simple.c +++ /dev/null @@ -1,75 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "thash.h" - -#include "sha2.h" -#include "sha256.h" - -/** - * Takes an array of inblocks concatenated arrays of PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_N bytes. - */ -static void PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_thash( - unsigned char *out, unsigned char *buf, - const unsigned char *in, unsigned int inblocks, - const unsigned char *pub_seed, uint32_t addr[8], - const sha256ctx *hash_state_seeded) { - - unsigned char outbuf[PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_SHA256_OUTPUT_BYTES]; - sha256ctx sha2_state; - - (void)pub_seed; /* Suppress an 'unused parameter' warning. */ - - /* Retrieve precomputed state containing pub_seed */ - sha256_inc_ctx_clone(&sha2_state, hash_state_seeded); - - PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_compress_address(buf, addr); - memcpy(buf + PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_SHA256_ADDR_BYTES, in, inblocks * PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_N); - - sha256_inc_finalize(outbuf, &sha2_state, buf, PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_N); - memcpy(out, outbuf, PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_N); -} - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const sha256ctx *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_SHA256_ADDR_BYTES + 1 * PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_N]; - PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_thash( - out, buf, in, 1, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const sha256ctx *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_SHA256_ADDR_BYTES + 2 * PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_N]; - PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_thash( - out, buf, in, 2, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const sha256ctx *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_SHA256_ADDR_BYTES + PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_WOTS_LEN * PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_N]; - PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_thash( - out, buf, in, PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_WOTS_LEN, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const sha256ctx *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_SHA256_ADDR_BYTES + PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_FORS_TREES * PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_N]; - PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_thash( - out, buf, in, PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_FORS_TREES, pub_seed, addr, hash_state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_clean/utils.c b/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_clean/utils.c deleted file mode 100644 index 1a29a6d623..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_clean/utils.c +++ /dev/null @@ -1,199 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "hash_state.h" -#include "params.h" -#include "thash.h" -#include "utils.h" - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in) { - - /* Iterate over out in decreasing order, for big-endianness. */ - for (size_t i = outlen; i > 0; i--) { - out[i - 1] = in & 0xff; - in = in >> 8; - } -} - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_bytes_to_ull( - const unsigned char *in, size_t inlen) { - unsigned long long retval = 0; - - for (size_t i = 0; i < inlen; i++) { - retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); - } - return retval; -} - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - uint32_t i; - unsigned char buffer[2 * PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_N]; - - /* If leaf_idx is odd (last bit = 1), current path element is a right child - and auth_path has to go left. Otherwise it is the other way around. */ - if (leaf_idx & 1) { - memcpy(buffer + PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_N, leaf, PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_N); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_N); - } else { - memcpy(buffer, leaf, PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_N); - memcpy(buffer + PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_N, auth_path, PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_N); - } - auth_path += PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_N; - - for (i = 0; i < tree_height - 1; i++) { - leaf_idx >>= 1; - idx_offset >>= 1; - /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_set_tree_height(addr, i + 1); - PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_set_tree_index( - addr, leaf_idx + idx_offset); - - /* Pick the right or left neighbor, depending on parity of the node. */ - if (leaf_idx & 1) { - PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_thash_2( - buffer + PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_N, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_N); - } else { - PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_thash_2( - buffer, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer + PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_N, auth_path, PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_N); - } - auth_path += PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_N; - } - - /* The last iteration is exceptional; we do not copy an auth_path node. */ - leaf_idx >>= 1; - idx_offset >>= 1; - PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_set_tree_height(addr, tree_height); - PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_set_tree_index( - addr, leaf_idx + idx_offset); - PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_thash_2( - root, buffer, pub_seed, addr, hash_state_seeded); -} - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -static void PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_treehash( - unsigned char *root, unsigned char *auth_path, - unsigned char *stack, unsigned int *heights, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - - unsigned int offset = 0; - uint32_t idx; - uint32_t tree_idx; - - for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { - /* Add the next leaf node to the stack. */ - gen_leaf(stack + offset * PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_N, - sk_seed, pub_seed, idx + idx_offset, tree_addr, - hash_state_seeded); - offset++; - heights[offset - 1] = 0; - - /* If this is a node we need for the auth path.. */ - if ((leaf_idx ^ 0x1) == idx) { - memcpy(auth_path, stack + (offset - 1)*PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_N, PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_N); - } - - /* While the top-most nodes are of equal height.. */ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { - /* Compute index of the new node, in the next layer. */ - tree_idx = (idx >> (heights[offset - 1] + 1)); - - /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_set_tree_height( - tree_addr, heights[offset - 1] + 1); - PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_set_tree_index( - tree_addr, tree_idx + (idx_offset >> (heights[offset - 1] + 1))); - /* Hash the top-most nodes from the stack together. */ - PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_thash_2( - stack + (offset - 2)*PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_N, stack + (offset - 2)*PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_N, - pub_seed, tree_addr, hash_state_seeded); - offset--; - /* Note that the top-most node is now one layer higher. */ - heights[offset - 1]++; - - /* If this is a node we need for the auth path.. */ - if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_path + heights[offset - 1]*PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_N, - stack + (offset - 1)*PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_N, PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_N); - } - } - } - memcpy(root, stack, PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_N); -} - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_FORS_HEIGHT + 1)*PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_N]; - unsigned int heights[PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_FORS_HEIGHT + 1]; - - PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_FORS_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_TREE_HEIGHT + 1)*PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_N]; - unsigned int heights[PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_TREE_HEIGHT + 1]; - - PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_TREE_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_clean/utils.h b/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_clean/utils.h deleted file mode 100644 index 97f890fd15..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_clean/utils.h +++ /dev/null @@ -1,64 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_UTILS_H -#define PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_UTILS_H - -#include "hash_state.h" -#include "params.h" -#include -#include - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in); - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_bytes_to_ull( - const unsigned char *in, size_t inlen); - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -void PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_clean/wots.c b/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_clean/wots.c deleted file mode 100644 index 354ff91fd8..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_clean/wots.c +++ /dev/null @@ -1,167 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "hash_state.h" -#include "params.h" -#include "thash.h" -#include "utils.h" -#include "wots.h" - -// TODO clarify address expectations, and make them more uniform. -// TODO i.e. do we expect types to be set already? -// TODO and do we expect modifications or copies? - -/** - * Computes the starting value for a chain, i.e. the secret key. - * Expects the address to be complete up to the chain address. - */ -static void wots_gen_sk(unsigned char *sk, const unsigned char *sk_seed, - uint32_t wots_addr[8], - const hash_state *hash_state_seeded) { - /* Make sure that the hash address is actually zeroed. */ - PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_set_hash_addr(wots_addr, 0); - - /* Generate sk element. */ - PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_prf_addr(sk, sk_seed, wots_addr, hash_state_seeded); -} - -/** - * Computes the chaining function. - * out and in have to be n-byte arrays. - * - * Interprets in as start-th value of the chain. - * addr has to contain the address of the chain. - */ -static void gen_chain(unsigned char *out, const unsigned char *in, - unsigned int start, unsigned int steps, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - uint32_t i; - - /* Initialize out with the value at position 'start'. */ - memcpy(out, in, PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_N); - - /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_WOTS_W; i++) { - PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_set_hash_addr(addr, i); - PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_thash_1( - out, out, pub_seed, addr, hash_state_seeded); - } -} - -/** - * base_w algorithm as described in draft. - * Interprets an array of bytes as integers in base w. - * This only works when log_w is a divisor of 8. - */ -static void base_w(unsigned int *output, const size_t out_len, - const unsigned char *input) { - size_t in = 0; - size_t out = 0; - unsigned char total = 0; - unsigned int bits = 0; - size_t consumed; - - for (consumed = 0; consumed < out_len; consumed++) { - if (bits == 0) { - total = input[in]; - in++; - bits += 8; - } - bits -= PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_WOTS_LOGW; - output[out] = (unsigned int)((total >> bits) & (PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_WOTS_W - 1)); - out++; - } -} - -/* Computes the WOTS+ checksum over a message (in base_w). */ -static void wots_checksum(unsigned int *csum_base_w, - const unsigned int *msg_base_w) { - unsigned int csum = 0; - unsigned char csum_bytes[(PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_WOTS_LEN2 * PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_WOTS_LOGW + 7) / 8]; - unsigned int i; - - /* Compute checksum. */ - for (i = 0; i < PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_WOTS_LEN1; i++) { - csum += PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_WOTS_W - 1 - msg_base_w[i]; - } - - /* Convert checksum to base_w. */ - /* Make sure expected empty zero bits are the least significant bits. */ - csum = csum << (8 - ((PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_WOTS_LEN2 * PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_WOTS_LOGW) % 8)); - PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_ull_to_bytes( - csum_bytes, sizeof(csum_bytes), csum); - base_w(csum_base_w, PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_WOTS_LEN2, csum_bytes); -} - -/* Takes a message and derives the matching chain lengths. */ -static void chain_lengths(unsigned int *lengths, const unsigned char *msg) { - base_w(lengths, PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_WOTS_LEN1, msg); - wots_checksum(lengths + PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_WOTS_LEN1, lengths); -} - -/** - * WOTS key generation. Takes a 32 byte sk_seed, expands it to WOTS private key - * elements and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_wots_gen_pk( - unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - uint32_t i; - - for (i = 0; i < PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_WOTS_LEN; i++) { - PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_set_chain_addr(addr, i); - wots_gen_sk(pk + i * PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_N, sk_seed, addr, hash_state_seeded); - gen_chain(pk + i * PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_N, pk + i * PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_N, - 0, PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_WOTS_W - 1, pub_seed, addr, hash_state_seeded); - } -} - -/** - * Takes a n-byte message and the 32-byte sk_see to compute a signature 'sig'. - */ -void PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_wots_sign( - unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *hash_state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_WOTS_LEN; i++) { - PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_set_chain_addr(addr, i); - wots_gen_sk(sig + i * PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_N, sk_seed, addr, hash_state_seeded); - gen_chain(sig + i * PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_N, sig + i * PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_N, 0, lengths[i], pub_seed, addr, hash_state_seeded); - } -} - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_wots_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_WOTS_LEN; i++) { - PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_set_chain_addr(addr, i); - gen_chain(pk + i * PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_N, sig + i * PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_N, - lengths[i], PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_WOTS_W - 1 - lengths[i], pub_seed, addr, - hash_state_seeded); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_clean/wots.h b/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_clean/wots.h deleted file mode 100644 index 1d966fd496..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-192s-simple_clean/wots.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_WOTS_H -#define PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_WOTS_H - -#include "hash_state.h" -#include "params.h" -#include - -/** - * WOTS key generation. Takes a 32 byte seed for the private key, expands it to - * a full WOTS private key and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_wots_gen_pk( - unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -/** - * Takes a n-byte message and the 32-byte seed for the private key to compute a - * signature that is placed at 'sig'. - */ -void PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_wots_sign( - unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *hash_state_seeded); - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_wots_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_avx2/LICENSE b/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_avx2/LICENSE deleted file mode 100644 index 670154e353..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_avx2/LICENSE +++ /dev/null @@ -1,116 +0,0 @@ -CC0 1.0 Universal - -Statement of Purpose - -The laws of most jurisdictions throughout the world automatically confer -exclusive Copyright and Related Rights (defined below) upon the creator and -subsequent owner(s) (each and all, an "owner") of an original work of -authorship and/or a database (each, a "Work"). - -Certain owners wish to permanently relinquish those rights to a Work for the -purpose of contributing to a commons of creative, cultural and scientific -works ("Commons") that the public can reliably and without fear of later -claims of infringement build upon, modify, incorporate in other works, reuse -and redistribute as freely as possible in any form whatsoever and for any -purposes, including without limitation commercial purposes. These owners may -contribute to the Commons to promote the ideal of a free culture and the -further production of creative, cultural and scientific works, or to gain -reputation or greater distribution for their Work in part through the use and -efforts of others. - -For these and/or other purposes and motivations, and without any expectation -of additional consideration or compensation, the person associating CC0 with a -Work (the "Affirmer"), to the extent that he or she is an owner of Copyright -and Related Rights in the Work, voluntarily elects to apply CC0 to the Work -and publicly distribute the Work under its terms, with knowledge of his or her -Copyright and Related Rights in the Work and the meaning and intended legal -effect of CC0 on those rights. - -1. Copyright and Related Rights. A Work made available under CC0 may be -protected by copyright and related or neighboring rights ("Copyright and -Related Rights"). Copyright and Related Rights include, but are not limited -to, the following: - - i. the right to reproduce, adapt, distribute, perform, display, communicate, - and translate a Work; - - ii. moral rights retained by the original author(s) and/or performer(s); - - iii. publicity and privacy rights pertaining to a person's image or likeness - depicted in a Work; - - iv. rights protecting against unfair competition in regards to a Work, - subject to the limitations in paragraph 4(a), below; - - v. rights protecting the extraction, dissemination, use and reuse of data in - a Work; - - vi. database rights (such as those arising under Directive 96/9/EC of the - European Parliament and of the Council of 11 March 1996 on the legal - protection of databases, and under any national implementation thereof, - including any amended or successor version of such directive); and - - vii. other similar, equivalent or corresponding rights throughout the world - based on applicable law or treaty, and any national implementations thereof. - -2. Waiver. To the greatest extent permitted by, but not in contravention of, -applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and -unconditionally waives, abandons, and surrenders all of Affirmer's Copyright -and Related Rights and associated claims and causes of action, whether now -known or unknown (including existing as well as future claims and causes of -action), in the Work (i) in all territories worldwide, (ii) for the maximum -duration provided by applicable law or treaty (including future time -extensions), (iii) in any current or future medium and for any number of -copies, and (iv) for any purpose whatsoever, including without limitation -commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes -the Waiver for the benefit of each member of the public at large and to the -detriment of Affirmer's heirs and successors, fully intending that such Waiver -shall not be subject to revocation, rescission, cancellation, termination, or -any other legal or equitable action to disrupt the quiet enjoyment of the Work -by the public as contemplated by Affirmer's express Statement of Purpose. - -3. Public License Fallback. Should any part of the Waiver for any reason be -judged legally invalid or ineffective under applicable law, then the Waiver -shall be preserved to the maximum extent permitted taking into account -Affirmer's express Statement of Purpose. In addition, to the extent the Waiver -is so judged Affirmer hereby grants to each affected person a royalty-free, -non transferable, non sublicensable, non exclusive, irrevocable and -unconditional license to exercise Affirmer's Copyright and Related Rights in -the Work (i) in all territories worldwide, (ii) for the maximum duration -provided by applicable law or treaty (including future time extensions), (iii) -in any current or future medium and for any number of copies, and (iv) for any -purpose whatsoever, including without limitation commercial, advertising or -promotional purposes (the "License"). The License shall be deemed effective as -of the date CC0 was applied by Affirmer to the Work. Should any part of the -License for any reason be judged legally invalid or ineffective under -applicable law, such partial invalidity or ineffectiveness shall not -invalidate the remainder of the License, and in such case Affirmer hereby -affirms that he or she will not (i) exercise any of his or her remaining -Copyright and Related Rights in the Work or (ii) assert any associated claims -and causes of action with respect to the Work, in either case contrary to -Affirmer's express Statement of Purpose. - -4. Limitations and Disclaimers. - - a. No trademark or patent rights held by Affirmer are waived, abandoned, - surrendered, licensed or otherwise affected by this document. - - b. Affirmer offers the Work as-is and makes no representations or warranties - of any kind concerning the Work, express, implied, statutory or otherwise, - including without limitation warranties of title, merchantability, fitness - for a particular purpose, non infringement, or the absence of latent or - other defects, accuracy, or the present or absence of errors, whether or not - discoverable, all to the greatest extent permissible under applicable law. - - c. Affirmer disclaims responsibility for clearing rights of other persons - that may apply to the Work or any use thereof, including without limitation - any person's Copyright and Related Rights in the Work. Further, Affirmer - disclaims responsibility for obtaining any necessary consents, permissions - or other rights required for any use of the Work. - - d. Affirmer understands and acknowledges that Creative Commons is not a - party to this document and has no duty or obligation with respect to this - CC0 or use of the Work. - -For more information, please see - diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_avx2/address.c b/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_avx2/address.c deleted file mode 100644 index 3139a2f37a..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_avx2/address.c +++ /dev/null @@ -1,78 +0,0 @@ -#include - -#include "address.h" -#include "params.h" -#include "utils.h" - -void PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]) { - int i; - - for (i = 0; i < 8; i++) { - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_ull_to_bytes( - bytes + i * 4, 4, addr[i]); - } -} - -void PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_set_layer_addr( - uint32_t addr[8], uint32_t layer) { - addr[0] = layer; -} - -void PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_set_tree_addr( - uint32_t addr[8], uint64_t tree) { - addr[1] = 0; - addr[2] = (uint32_t) (tree >> 32); - addr[3] = (uint32_t) tree; -} - -void PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_set_type( - uint32_t addr[8], uint32_t type) { - addr[4] = type; -} - -void PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; -} - -/* These functions are used for OTS addresses. */ - -void PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_set_keypair_addr( - uint32_t addr[8], uint32_t keypair) { - addr[5] = keypair; -} - -void PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; - out[5] = in[5]; -} - -void PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_set_chain_addr( - uint32_t addr[8], uint32_t chain) { - addr[6] = chain; -} - -void PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_set_hash_addr( - uint32_t addr[8], uint32_t hash) { - addr[7] = hash; -} - -/* These functions are used for all hash tree addresses (including FORS). */ - -void PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_set_tree_height( - uint32_t addr[8], uint32_t tree_height) { - addr[6] = tree_height; -} - -void PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_set_tree_index( - uint32_t addr[8], uint32_t tree_index) { - addr[7] = tree_index; -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_avx2/address.h b/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_avx2/address.h deleted file mode 100644 index aa353124e0..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_avx2/address.h +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_ADDRESS_H -#define PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_ADDRESS_H - -#include - -#define PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_ADDR_TYPE_WOTS 0 -#define PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_ADDR_TYPE_WOTSPK 1 -#define PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_ADDR_TYPE_HASHTREE 2 -#define PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_ADDR_TYPE_FORSTREE 3 -#define PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_ADDR_TYPE_FORSPK 4 - -void PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]); - -void PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_set_layer_addr( - uint32_t addr[8], uint32_t layer); - -void PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_set_tree_addr( - uint32_t addr[8], uint64_t tree); - -void PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_set_type( - uint32_t addr[8], uint32_t type); - -/* Copies the layer and tree part of one address into the other */ -void PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for WOTS and FORS addresses. */ - -void PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_set_keypair_addr( - uint32_t addr[8], uint32_t keypair); - -void PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_set_chain_addr( - uint32_t addr[8], uint32_t chain); - -void PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_set_hash_addr( - uint32_t addr[8], uint32_t hash); - -void PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for all hash tree addresses (including FORS). */ - -void PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_set_tree_height( - uint32_t addr[8], uint32_t tree_height); - -void PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_set_tree_index( - uint32_t addr[8], uint32_t tree_index); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_avx2/api.h b/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_avx2/api.h deleted file mode 100644 index 2fd0eddf3b..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_avx2/api.h +++ /dev/null @@ -1,81 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_API_H -#define PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_API_H - -#include -#include - - - -#define PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_CRYPTO_ALGNAME "SPHINCS+" - -#define PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_CRYPTO_SECRETKEYBYTES 128 -#define PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_CRYPTO_PUBLICKEYBYTES 64 -#define PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_CRYPTO_BYTES 49856 -#define PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_CRYPTO_SEEDBYTES 96 - - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_avx2/fors.c b/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_avx2/fors.c deleted file mode 100644 index b64a28cd34..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_avx2/fors.c +++ /dev/null @@ -1,240 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "fors.h" -#include "hash.h" -#include "hashx8.h" -#include "thash.h" -#include "thashx8.h" -#include "utils.h" -#include "utilsx8.h" - -static void fors_gen_skx8(unsigned char *sk0, - unsigned char *sk1, - unsigned char *sk2, - unsigned char *sk3, - unsigned char *sk4, - unsigned char *sk5, - unsigned char *sk6, - unsigned char *sk7, const unsigned char *sk_seed, - uint32_t fors_leaf_addrx8[8 * 8]) { - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_prf_addrx8(sk0, sk1, sk2, sk3, sk4, sk5, sk6, sk7, - sk_seed, fors_leaf_addrx8); -} - -static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, - const unsigned char *pub_seed, - uint32_t fors_leaf_addr[8], - const hash_state *state_seeded) { - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_thash_1(leaf, sk, pub_seed, fors_leaf_addr, state_seeded); -} - -static void fors_sk_to_leafx8(unsigned char *leaf0, - unsigned char *leaf1, - unsigned char *leaf2, - unsigned char *leaf3, - unsigned char *leaf4, - unsigned char *leaf5, - unsigned char *leaf6, - unsigned char *leaf7, - const unsigned char *sk0, - const unsigned char *sk1, - const unsigned char *sk2, - const unsigned char *sk3, - const unsigned char *sk4, - const unsigned char *sk5, - const unsigned char *sk6, - const unsigned char *sk7, - const unsigned char *pub_seed, - uint32_t fors_leaf_addrx8[8 * 8], - const hash_state *state_seeded) { - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_thashx8_1(leaf0, leaf1, leaf2, leaf3, leaf4, leaf5, leaf6, leaf7, - sk0, sk1, sk2, sk3, sk4, sk5, sk6, sk7, - pub_seed, fors_leaf_addrx8, state_seeded); -} - -static void fors_gen_leafx8(unsigned char *leaf0, - unsigned char *leaf1, - unsigned char *leaf2, - unsigned char *leaf3, - unsigned char *leaf4, - unsigned char *leaf5, - unsigned char *leaf6, - unsigned char *leaf7, - const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx0, - uint32_t addr_idx1, - uint32_t addr_idx2, - uint32_t addr_idx3, - uint32_t addr_idx4, - uint32_t addr_idx5, - uint32_t addr_idx6, - uint32_t addr_idx7, - const uint32_t fors_tree_addr[8], - const hash_state *state_seeded) { - uint32_t fors_leaf_addrx8[8 * 8] = {0}; - unsigned int j; - - /* Only copy the parts that must be kept in fors_leaf_addrx8. */ - for (j = 0; j < 8; j++) { - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_copy_keypair_addr(fors_leaf_addrx8 + j * 8, fors_tree_addr); - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_set_type(fors_leaf_addrx8 + j * 8, PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_ADDR_TYPE_FORSTREE); - } - - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_set_tree_index(fors_leaf_addrx8 + 0 * 8, addr_idx0); - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_set_tree_index(fors_leaf_addrx8 + 1 * 8, addr_idx1); - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_set_tree_index(fors_leaf_addrx8 + 2 * 8, addr_idx2); - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_set_tree_index(fors_leaf_addrx8 + 3 * 8, addr_idx3); - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_set_tree_index(fors_leaf_addrx8 + 4 * 8, addr_idx4); - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_set_tree_index(fors_leaf_addrx8 + 5 * 8, addr_idx5); - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_set_tree_index(fors_leaf_addrx8 + 6 * 8, addr_idx6); - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_set_tree_index(fors_leaf_addrx8 + 7 * 8, addr_idx7); - - fors_gen_skx8(leaf0, leaf1, leaf2, leaf3, leaf4, leaf5, leaf6, leaf7, - sk_seed, fors_leaf_addrx8); - fors_sk_to_leafx8(leaf0, leaf1, leaf2, leaf3, leaf4, leaf5, leaf6, leaf7, - leaf0, leaf1, leaf2, leaf3, leaf4, leaf5, leaf6, leaf7, - pub_seed, fors_leaf_addrx8, state_seeded); -} - -/** - * Interprets m as PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_FORS_HEIGHT-bit unsigned integers. - * Assumes m contains at least PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_FORS_TREES bits. - * Assumes indices has space for PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_FORS_TREES integers. - */ -static void message_to_indices(uint32_t *indices, const unsigned char *m) { - unsigned int i, j; - unsigned int offset = 0; - - for (i = 0; i < PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_FORS_TREES; i++) { - indices[i] = 0; - for (j = 0; j < PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_FORS_HEIGHT; j++) { - indices[i] ^= (((uint32_t)m[offset >> 3] >> (offset & 0x7)) & 0x1) << j; - offset++; - } - } -} - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_fors_sign( - unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], - const hash_state *state_seeded) { - /* Round up to multiple of 8 to prevent out-of-bounds for x8 parallelism */ - uint32_t indices[(PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_FORS_TREES + 7) & ~7] = {0}; - unsigned char roots[((PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_FORS_TREES + 7) & ~7) * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N]; - /* Sign to a buffer, since we may not have a nice multiple of 8 and would - otherwise overrun the signature. */ - unsigned char sigbufx8[8 * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N * (1 + PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_FORS_HEIGHT)]; - uint32_t fors_tree_addrx8[8 * 8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset[8] = {0}; - unsigned int i, j; - - for (j = 0; j < 8; j++) { - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_copy_keypair_addr(fors_tree_addrx8 + j * 8, fors_addr); - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_set_type(fors_tree_addrx8 + j * 8, PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_ADDR_TYPE_FORSTREE); - } - - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_copy_keypair_addr(fors_pk_addr, fors_addr); - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_set_type(fors_pk_addr, PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < ((PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_FORS_TREES + 7) & ~0x7); i += 8) { - for (j = 0; j < 8; j++) { - if (i + j < PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_FORS_TREES) { - idx_offset[j] = (i + j) * (1 << PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_FORS_HEIGHT); - - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_set_tree_height(fors_tree_addrx8 + j * 8, 0); - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_set_tree_index(fors_tree_addrx8 + j * 8, - indices[i + j] + idx_offset[j]); - } - } - - /* Include the secret key part that produces the selected leaf nodes. */ - fors_gen_skx8(sigbufx8 + 0 * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N, - sigbufx8 + 1 * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N, - sigbufx8 + 2 * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N, - sigbufx8 + 3 * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N, - sigbufx8 + 4 * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N, - sigbufx8 + 5 * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N, - sigbufx8 + 6 * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N, - sigbufx8 + 7 * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N, - sk_seed, fors_tree_addrx8); - - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_treehashx8_FORS_HEIGHT( - roots + i * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N, sigbufx8 + 8 * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N, sk_seed, pub_seed, - &indices[i], idx_offset, fors_gen_leafx8, fors_tree_addrx8, - state_seeded); - - for (j = 0; j < 8; j++) { - if (i + j < PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_FORS_TREES) { - memcpy(sig, sigbufx8 + j * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N, PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N); - memcpy(sig + PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N, - sigbufx8 + 8 * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N + j * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_FORS_HEIGHT, - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_FORS_HEIGHT); - sig += PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N * (1 + PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_FORS_HEIGHT); - } - } - } - - /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_thash_FORS_TREES(pk, roots, pub_seed, fors_pk_addr, state_seeded); -} - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, - const uint32_t fors_addr[8], - const hash_state *state_seeded) { - uint32_t indices[PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_FORS_TREES]; - unsigned char roots[PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_FORS_TREES * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N]; - unsigned char leaf[PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N]; - uint32_t fors_tree_addr[8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_copy_keypair_addr(fors_tree_addr, fors_addr); - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_copy_keypair_addr(fors_pk_addr, fors_addr); - - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_set_type(fors_tree_addr, PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_set_type(fors_pk_addr, PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_FORS_TREES; i++) { - idx_offset = i * (1 << PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_FORS_HEIGHT); - - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_set_tree_height(fors_tree_addr, 0); - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Derive the leaf from the included secret key part. */ - fors_sk_to_leaf(leaf, sig, pub_seed, fors_tree_addr, state_seeded); - sig += PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N; - - /* Derive the corresponding root node of this tree. */ - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_compute_root(roots + i * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N, leaf, indices[i], idx_offset, - sig, PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_FORS_HEIGHT, pub_seed, fors_tree_addr, state_seeded); - sig += PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_thash_FORS_TREES(pk, roots, pub_seed, fors_pk_addr, state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_avx2/fors.h b/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_avx2/fors.h deleted file mode 100644 index 73730f3d9f..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_avx2/fors.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_FORS_H -#define PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_FORS_H - -#include - -#include "hash_state.h" -#include "params.h" - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_fors_sign( - unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *hash_state_seeded); - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_fors_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, const uint32_t fors_addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_avx2/hash.h b/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_avx2/hash.h deleted file mode 100644 index 617163d40a..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_avx2/hash.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_HASH_H -#define PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_HASH_H - -#include "hash_state.h" - -#include -#include - -void PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_initialize_hash_function( - hash_state *hash_state_seeded, - const unsigned char *pub_seed, const unsigned char *sk_seed); - -void PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_destroy_hash_function(hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_avx2/hash_sha256.c b/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_avx2/hash_sha256.c deleted file mode 100644 index 1e609a52f0..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_avx2/hash_sha256.c +++ /dev/null @@ -1,166 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "utils.h" - -#include "sha2.h" -#include "sha256.h" -#include "sha256x8.h" - -/** - * Initializes the hash function states - */ -void PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_initialize_hash_function( - hash_state *hash_state_seeded, - const unsigned char *pub_seed, const unsigned char *sk_seed) { - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_seed_state(&hash_state_seeded->x1, pub_seed); - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_seed_statex8(&hash_state_seeded->x8, pub_seed); - (void)sk_seed; /* Suppress an 'unused parameter' warning. */ -} - -/** - * Cleans up the hash function states - */ -void PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_destroy_hash_function(hash_state *hash_state_seeded) { - sha256_inc_ctx_release(&hash_state_seeded->x1); -} - -/* - * Computes PRF(key, addr), given a secret key of PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N bytes and an address - */ -void PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_prf_addr(unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded) { - unsigned char buf[PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_ADDR_BYTES]; - unsigned char outbuf[PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_OUTPUT_BYTES]; - - memcpy(buf, key, PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N); - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_compress_address(buf + PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N, addr); - - sha256(outbuf, buf, PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_ADDR_BYTES); - memcpy(out, outbuf, PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} - -/** - * Computes the message-dependent randomness R, using a secret seed as a key - * for HMAC, and an optional randomization value prefixed to the message. - * This requires m to have at least PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_BLOCK_BYTES + PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N space - * available in front of the pointer, i.e. before the message to use for the - * prefix. This is necessary to prevent having to move the message around (and - * allocate memory for it). - */ -void PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, const hash_state *hash_state_seeded) { - unsigned char buf[PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_BLOCK_BYTES + PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_OUTPUT_BYTES]; - sha256ctx state; - int i; - - /* This implements HMAC-SHA256 */ - for (i = 0; i < PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N; i++) { - buf[i] = 0x36 ^ sk_prf[i]; - } - memset(buf + PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N, 0x36, PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N); - - sha256_inc_init(&state); - sha256_inc_blocks(&state, buf, 1); - - memcpy(buf, optrand, PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N); - - /* If optrand + message cannot fill up an entire block */ - if (PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N + mlen < PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_BLOCK_BYTES) { - memcpy(buf + PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N, m, mlen); - sha256_inc_finalize(buf + PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_BLOCK_BYTES, &state, - buf, mlen + PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N); - } - /* Otherwise first fill a block, so that finalize only uses the message */ - else { - memcpy(buf + PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N, m, PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N); - sha256_inc_blocks(&state, buf, 1); - - m += PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N; - mlen -= PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N; - sha256_inc_finalize(buf + PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_BLOCK_BYTES, &state, m, mlen); - } - - for (i = 0; i < PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N; i++) { - buf[i] = 0x5c ^ sk_prf[i]; - } - memset(buf + PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N, 0x5c, PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N); - - sha256(buf, buf, PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_BLOCK_BYTES + PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_OUTPUT_BYTES); - memcpy(R, buf, PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} - -/** - * Computes the message hash using R, the public key, and the message. - * Outputs the message digest and the index of the leaf. The index is split in - * the tree index and the leaf index, for convenient copying to an address. - */ -void PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded) { -#define PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_TREE_BITS (PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_TREE_HEIGHT * (PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_D - 1)) -#define PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_TREE_BYTES ((PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_TREE_BITS + 7) / 8) -#define PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_LEAF_BITS PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_TREE_HEIGHT -#define PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_LEAF_BYTES ((PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_LEAF_BITS + 7) / 8) -#define PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_DGST_BYTES (PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_FORS_MSG_BYTES + PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_TREE_BYTES + PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_LEAF_BYTES) - - unsigned char seed[PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_OUTPUT_BYTES + 4]; - - /* Round to nearest multiple of PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_BLOCK_BYTES */ -#define PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_INBLOCKS (((PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_PK_BYTES + PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_BLOCK_BYTES - 1) & \ - -PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_BLOCK_BYTES) / PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_BLOCK_BYTES) - unsigned char inbuf[PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_INBLOCKS * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_BLOCK_BYTES]; - - unsigned char buf[PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_DGST_BYTES]; - unsigned char *bufp = buf; - sha256ctx state; - - sha256_inc_init(&state); - - memcpy(inbuf, R, PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N); - memcpy(inbuf + PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N, pk, PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_PK_BYTES); - - /* If R + pk + message cannot fill up an entire block */ - if (PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_PK_BYTES + mlen < PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_INBLOCKS * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_BLOCK_BYTES) { - memcpy(inbuf + PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_PK_BYTES, m, mlen); - sha256_inc_finalize(seed, &state, inbuf, PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_PK_BYTES + mlen); - } - /* Otherwise first fill a block, so that finalize only uses the message */ - else { - memcpy(inbuf + PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_PK_BYTES, m, - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_INBLOCKS * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_PK_BYTES); - sha256_inc_blocks(&state, inbuf, PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_INBLOCKS); - - m += PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_INBLOCKS * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_PK_BYTES; - mlen -= PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_INBLOCKS * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_PK_BYTES; - sha256_inc_finalize(seed, &state, m, mlen); - } - - /* By doing this in two steps, we prevent hashing the message twice; - otherwise each iteration in MGF1 would hash the message again. */ - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_mgf1(bufp, PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_DGST_BYTES, seed, PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_OUTPUT_BYTES); - - memcpy(digest, bufp, PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_FORS_MSG_BYTES); - bufp += PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_FORS_MSG_BYTES; - - *tree = PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_bytes_to_ull(bufp, PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_TREE_BYTES); - *tree &= (~(uint64_t)0) >> (64 - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_TREE_BITS); - bufp += PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_TREE_BYTES; - - *leaf_idx = (uint32_t)PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_bytes_to_ull( - bufp, PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_LEAF_BYTES); - *leaf_idx &= (~(uint32_t)0) >> (32 - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_LEAF_BITS); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_avx2/hash_sha256x8.c b/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_avx2/hash_sha256x8.c deleted file mode 100644 index a8ebd596a8..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_avx2/hash_sha256x8.c +++ /dev/null @@ -1,61 +0,0 @@ -#include -#include - -#include "address.h" -#include "hashx8.h" -#include "params.h" -#include "sha256.h" -#include "sha256avx.h" -#include "sha256x8.h" -#include "utils.h" - -/* - * 8-way parallel version of prf_addr; takes 8x as much input and output - */ -void PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_prf_addrx8(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7, - const unsigned char *key, - const uint32_t addrx8[8 * 8]) { - unsigned char bufx8[8 * (PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_ADDR_BYTES)]; - unsigned char outbufx8[8 * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_OUTPUT_BYTES]; - unsigned int j; - - for (j = 0; j < 8; j++) { - memcpy(bufx8 + j * (PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_ADDR_BYTES), key, PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N); - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_compress_address(bufx8 + PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N + j * (PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_ADDR_BYTES), - addrx8 + j * 8); - } - - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_sha256x8(outbufx8 + 0 * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 1 * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 2 * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 3 * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 4 * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 5 * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 6 * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 7 * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_OUTPUT_BYTES, - bufx8 + 0 * (PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_ADDR_BYTES), - bufx8 + 1 * (PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_ADDR_BYTES), - bufx8 + 2 * (PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_ADDR_BYTES), - bufx8 + 3 * (PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_ADDR_BYTES), - bufx8 + 4 * (PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_ADDR_BYTES), - bufx8 + 5 * (PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_ADDR_BYTES), - bufx8 + 6 * (PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_ADDR_BYTES), - bufx8 + 7 * (PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_ADDR_BYTES), - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_ADDR_BYTES); - - memcpy(out0, outbufx8 + 0 * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N); - memcpy(out1, outbufx8 + 1 * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N); - memcpy(out2, outbufx8 + 2 * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N); - memcpy(out3, outbufx8 + 3 * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N); - memcpy(out4, outbufx8 + 4 * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N); - memcpy(out5, outbufx8 + 5 * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N); - memcpy(out6, outbufx8 + 6 * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N); - memcpy(out7, outbufx8 + 7 * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_avx2/hash_state.h b/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_avx2/hash_state.h deleted file mode 100644 index c6161f017e..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_avx2/hash_state.h +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_HASH_STATE_H -#define PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_HASH_STATE_H - -/** - * Defines the type of the hash function state. - * - * Don't be fooled into thinking this instance of SPHINCS+ isn't stateless! - * - * From Section 7.2.2 from the SPHINCS+ round-2 specification: - * - * Each of the instances of the tweakable hash function take PK.seed as its - * first input, which is constant for a given key pair – and, thus, across - * a single signature. This leads to a lot of redundant computation. To remedy - * this, we pad PK.seed to the length of a full 64-byte SHA-256 input block. - * Because of the Merkle-Damgård construction that underlies SHA-256, this - * allows for reuse of the intermediate SHA-256 state after the initial call to - * the compression function which improves performance. - * - * We pass this hash state around in functions, because otherwise we need to - * have a global variable. - * - * We use a struct to differentiate between the x1 and x8 variants of SHA256. - */ - -#include "sha2.h" -#include "sha256avx.h" - -typedef struct { - sha256ctx x1; - sha256ctxx8 x8; -} hash_state; - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_avx2/hashx8.h b/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_avx2/hashx8.h deleted file mode 100644 index 098c68b8e8..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_avx2/hashx8.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_HASHX8_H -#define PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_HASHX8_H - -#include - -#include "params.h" - -void PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_prf_addrx8(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7, - const unsigned char *key, - const uint32_t addrx8[8 * 8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_avx2/params.h b/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_avx2/params.h deleted file mode 100644 index b7a31465fc..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_avx2/params.h +++ /dev/null @@ -1,53 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_PARAMS_H -#define PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_PARAMS_H - -/* Hash output length in bytes. */ -#define PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N 32 -/* Height of the hypertree. */ -#define PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_FULL_HEIGHT 68 -/* Number of subtree layer. */ -#define PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_D 17 -/* FORS tree dimensions. */ -#define PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_FORS_HEIGHT 9 -#define PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_FORS_TREES 35 -/* Winternitz parameter, */ -#define PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_WOTS_W 16 - -/* The hash function is defined by linking a different hash.c file, as opposed - to setting a #define constant. */ - -/* For clarity */ -#define PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_ADDR_BYTES 32 - -/* WOTS parameters. */ -#define PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_WOTS_LOGW 4 - -#define PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_WOTS_LEN1 (8 * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N / PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_WOTS_LOGW) - -/* PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#define PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_WOTS_LEN2 3 - -#define PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_WOTS_LEN (PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_WOTS_LEN1 + PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_WOTS_LEN2) -#define PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_WOTS_BYTES (PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_WOTS_LEN * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N) -#define PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_WOTS_PK_BYTES PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_WOTS_BYTES - -/* Subtree size. */ -#define PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_TREE_HEIGHT (PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_FULL_HEIGHT / PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_D) - -/* FORS parameters. */ -#define PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_FORS_MSG_BYTES ((PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_FORS_TREES + 7) / 8) -#define PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_FORS_BYTES ((PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_FORS_HEIGHT + 1) * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_FORS_TREES * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N) -#define PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_FORS_PK_BYTES PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N - -/* Resulting SPX sizes. */ -#define PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_BYTES (PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_FORS_BYTES + PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_D * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_WOTS_BYTES +\ - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_FULL_HEIGHT * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N) -#define PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_PK_BYTES (2 * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N) -#define PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SK_BYTES (2 * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_PK_BYTES) - -/* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ -#define PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_OPTRAND_BYTES 32 - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_avx2/sha256.c b/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_avx2/sha256.c deleted file mode 100644 index 7787631898..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_avx2/sha256.c +++ /dev/null @@ -1,71 +0,0 @@ -/* Based on the public domain implementation in - * crypto_hash/sha512/ref/ from http://bench.cr.yp.to/supercop.html - * by D. J. Bernstein */ - -#include -#include -#include - -#include "sha2.h" -#include "sha256.h" -#include "utils.h" - -/* - * Compresses an address to a 22-byte sequence. - * This reduces the number of required SHA256 compression calls, as the last - * block of input is padded with at least 65 bits. - */ -void PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_compress_address(unsigned char *out, const uint32_t addr[8]) { - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_ull_to_bytes(out, 1, addr[0]); /* drop 3 bytes of the layer field */ - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_ull_to_bytes(out + 1, 4, addr[2]); /* drop the highest tree address word */ - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_ull_to_bytes(out + 5, 4, addr[3]); - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_ull_to_bytes(out + 9, 1, addr[4]); /* drop 3 bytes of the type field */ - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_ull_to_bytes(out + 10, 4, addr[5]); - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_ull_to_bytes(out + 14, 4, addr[6]); - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_ull_to_bytes(out + 18, 4, addr[7]); -} - -/** - * Requires 'input_plus_four_bytes' to have 'inlen' + 4 bytes, so that the last - * four bytes can be used for the counter. Typically 'input' is merely a seed. - * Outputs outlen number of bytes - */ -void PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_mgf1( - unsigned char *out, unsigned long outlen, - unsigned char *input_plus_four_bytes, unsigned long inlen) { - unsigned char outbuf[PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_OUTPUT_BYTES]; - unsigned long i; - - /* While we can fit in at least another full block of SHA256 output.. */ - for (i = 0; (i + 1)*PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_OUTPUT_BYTES <= outlen; i++) { - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_ull_to_bytes(input_plus_four_bytes + inlen, 4, i); - sha256(out, input_plus_four_bytes, inlen + 4); - out += PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_OUTPUT_BYTES; - } - /* Until we cannot anymore, and we fill the remainder. */ - if (outlen > i * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_OUTPUT_BYTES) { - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_ull_to_bytes(input_plus_four_bytes + inlen, 4, i); - sha256(outbuf, input_plus_four_bytes, inlen + 4); - memcpy(out, outbuf, outlen - i * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_OUTPUT_BYTES); - } -} - - -/** - * Absorb the constant pub_seed using one round of the compression function - * This initializes hash_state_seeded, which can then be reused in thash - **/ -void PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_seed_state(sha256ctx *hash_state_seeded, const unsigned char *pub_seed) { - uint8_t block[PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_BLOCK_BYTES]; - size_t i; - - for (i = 0; i < PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N; ++i) { - block[i] = pub_seed[i]; - } - for (i = PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N; i < PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_BLOCK_BYTES; ++i) { - block[i] = 0; - } - - sha256_inc_init(hash_state_seeded); - sha256_inc_blocks(hash_state_seeded, block, 1); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_avx2/sha256.h b/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_avx2/sha256.h deleted file mode 100644 index 16646e77c0..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_avx2/sha256.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_H -#define PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_H - -#define PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_BLOCK_BYTES 64 -#define PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_OUTPUT_BYTES 32 /* This does not necessarily equal PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N */ -#define PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_ADDR_BYTES 22 - -#include -#include - -#include "sha2.h" - -void PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_compress_address(unsigned char *out, const uint32_t addr[8]); - -void PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_mgf1( - unsigned char *out, unsigned long outlen, - unsigned char *input_plus_four_bytes, unsigned long inlen); - -void PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_seed_state(sha256ctx *hash_state_seeded, const unsigned char *pub_seed); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_avx2/sha256avx.c b/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_avx2/sha256avx.c deleted file mode 100644 index fe3cb4d7b3..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_avx2/sha256avx.c +++ /dev/null @@ -1,296 +0,0 @@ -#include -#include -#include - -#include "sha256avx.h" - -// Transpose 8 vectors containing 32-bit values -void PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_transpose(u256 s[8]) { - u256 tmp0[8]; - u256 tmp1[8]; - tmp0[0] = _mm256_unpacklo_epi32(s[0], s[1]); - tmp0[1] = _mm256_unpackhi_epi32(s[0], s[1]); - tmp0[2] = _mm256_unpacklo_epi32(s[2], s[3]); - tmp0[3] = _mm256_unpackhi_epi32(s[2], s[3]); - tmp0[4] = _mm256_unpacklo_epi32(s[4], s[5]); - tmp0[5] = _mm256_unpackhi_epi32(s[4], s[5]); - tmp0[6] = _mm256_unpacklo_epi32(s[6], s[7]); - tmp0[7] = _mm256_unpackhi_epi32(s[6], s[7]); - tmp1[0] = _mm256_unpacklo_epi64(tmp0[0], tmp0[2]); - tmp1[1] = _mm256_unpackhi_epi64(tmp0[0], tmp0[2]); - tmp1[2] = _mm256_unpacklo_epi64(tmp0[1], tmp0[3]); - tmp1[3] = _mm256_unpackhi_epi64(tmp0[1], tmp0[3]); - tmp1[4] = _mm256_unpacklo_epi64(tmp0[4], tmp0[6]); - tmp1[5] = _mm256_unpackhi_epi64(tmp0[4], tmp0[6]); - tmp1[6] = _mm256_unpacklo_epi64(tmp0[5], tmp0[7]); - tmp1[7] = _mm256_unpackhi_epi64(tmp0[5], tmp0[7]); - s[0] = _mm256_permute2x128_si256(tmp1[0], tmp1[4], 0x20); - s[1] = _mm256_permute2x128_si256(tmp1[1], tmp1[5], 0x20); - s[2] = _mm256_permute2x128_si256(tmp1[2], tmp1[6], 0x20); - s[3] = _mm256_permute2x128_si256(tmp1[3], tmp1[7], 0x20); - s[4] = _mm256_permute2x128_si256(tmp1[0], tmp1[4], 0x31); - s[5] = _mm256_permute2x128_si256(tmp1[1], tmp1[5], 0x31); - s[6] = _mm256_permute2x128_si256(tmp1[2], tmp1[6], 0x31); - s[7] = _mm256_permute2x128_si256(tmp1[3], tmp1[7], 0x31); -} - -void PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_sha256_clone_statex8(sha256ctxx8 *outctx, const sha256ctxx8 *inctx) { - memcpy(outctx, inctx, sizeof(sha256ctxx8)); -} - -void PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_sha256_init8x(sha256ctxx8 *ctx) { - ctx->s[0] = _mm256_set_epi32((int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667); - ctx->s[1] = _mm256_set_epi32((int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85); - ctx->s[2] = _mm256_set_epi32((int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372); - ctx->s[3] = _mm256_set_epi32((int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a); - ctx->s[4] = _mm256_set_epi32((int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f); - ctx->s[5] = _mm256_set_epi32((int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c); - ctx->s[6] = _mm256_set_epi32((int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab); - ctx->s[7] = _mm256_set_epi32((int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19); - - ctx->datalen = 0; - ctx->msglen = 0; -} - -void PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_sha256_update8x(sha256ctxx8 *ctx, - const unsigned char *d0, - const unsigned char *d1, - const unsigned char *d2, - const unsigned char *d3, - const unsigned char *d4, - const unsigned char *d5, - const unsigned char *d6, - const unsigned char *d7, - unsigned long long len) { - size_t i = 0; - size_t bytes_to_copy; - - while (i < len) { - bytes_to_copy = (size_t)len - i; - if (bytes_to_copy > 64) { - bytes_to_copy = 64; - } - memcpy(&ctx->msgblocks[64 * 0], d0 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64 * 1], d1 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64 * 2], d2 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64 * 3], d3 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64 * 4], d4 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64 * 5], d5 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64 * 6], d6 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64 * 7], d7 + i, bytes_to_copy); - ctx->datalen += (unsigned int)bytes_to_copy; - i += bytes_to_copy; - if (ctx->datalen == 64) { - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_sha256_transform8x(ctx, ctx->msgblocks); - ctx->msglen += 512; - ctx->datalen = 0; - } - } -} - -void PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_sha256_final8x(sha256ctxx8 *ctx, - unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7) { - unsigned int i, curlen; - - // Padding - if (ctx->datalen < 56) { - for (i = 0; i < 8; ++i) { - curlen = ctx->datalen; - ctx->msgblocks[64 * i + curlen++] = 0x80; - while (curlen < 64) { - ctx->msgblocks[64 * i + curlen++] = 0x00; - } - } - } else { - for (i = 0; i < 8; ++i) { - curlen = ctx->datalen; - ctx->msgblocks[64 * i + curlen++] = 0x80; - while (curlen < 64) { - ctx->msgblocks[64 * i + curlen++] = 0x00; - } - } - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_sha256_transform8x(ctx, ctx->msgblocks); - memset(ctx->msgblocks, 0, 8 * 64); - } - - // Add length of the message to each block - ctx->msglen += ctx->datalen * 8; - for (i = 0; i < 8; i++) { - ctx->msgblocks[64 * i + 63] = (unsigned char)ctx->msglen; - ctx->msgblocks[64 * i + 62] = (unsigned char)(ctx->msglen >> 8); - ctx->msgblocks[64 * i + 61] = (unsigned char)(ctx->msglen >> 16); - ctx->msgblocks[64 * i + 60] = (unsigned char)(ctx->msglen >> 24); - ctx->msgblocks[64 * i + 59] = (unsigned char)(ctx->msglen >> 32); - ctx->msgblocks[64 * i + 58] = (unsigned char)(ctx->msglen >> 40); - ctx->msgblocks[64 * i + 57] = (unsigned char)(ctx->msglen >> 48); - ctx->msgblocks[64 * i + 56] = (unsigned char)(ctx->msglen >> 56); - } - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_sha256_transform8x(ctx, ctx->msgblocks); - - // Compute final hash output - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_transpose(ctx->s); - - // Store Hash value - STORE(out0, BYTESWAP(ctx->s[0])); - STORE(out1, BYTESWAP(ctx->s[1])); - STORE(out2, BYTESWAP(ctx->s[2])); - STORE(out3, BYTESWAP(ctx->s[3])); - STORE(out4, BYTESWAP(ctx->s[4])); - STORE(out5, BYTESWAP(ctx->s[5])); - STORE(out6, BYTESWAP(ctx->s[6])); - STORE(out7, BYTESWAP(ctx->s[7])); -} - -void PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_sha256_transform8x(sha256ctxx8 *ctx, const unsigned char *data) { - u256 s[8], w[64], T0, T1; - int i; - - // Load words and transform data correctly - for (i = 0; i < 8; i++) { - w[i] = BYTESWAP(LOAD(data + 64 * i)); - w[i + 8] = BYTESWAP(LOAD(data + 32 + 64 * i)); - } - - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_transpose(w); - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_transpose(w + 8); - - // Initial State - s[0] = ctx->s[0]; - s[1] = ctx->s[1]; - s[2] = ctx->s[2]; - s[3] = ctx->s[3]; - s[4] = ctx->s[4]; - s[5] = ctx->s[5]; - s[6] = ctx->s[6]; - s[7] = ctx->s[7]; - - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 0, w[0]); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 1, w[1]); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 2, w[2]); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 3, w[3]); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 4, w[4]); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 5, w[5]); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 6, w[6]); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 7, w[7]); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 8, w[8]); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 9, w[9]); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 10, w[10]); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 11, w[11]); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 12, w[12]); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 13, w[13]); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 14, w[14]); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 15, w[15]); - w[16] = ADD4_32(WSIGMA1_AVX(w[14]), w[0], w[9], WSIGMA0_AVX(w[1])); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 16, w[16]); - w[17] = ADD4_32(WSIGMA1_AVX(w[15]), w[1], w[10], WSIGMA0_AVX(w[2])); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 17, w[17]); - w[18] = ADD4_32(WSIGMA1_AVX(w[16]), w[2], w[11], WSIGMA0_AVX(w[3])); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 18, w[18]); - w[19] = ADD4_32(WSIGMA1_AVX(w[17]), w[3], w[12], WSIGMA0_AVX(w[4])); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 19, w[19]); - w[20] = ADD4_32(WSIGMA1_AVX(w[18]), w[4], w[13], WSIGMA0_AVX(w[5])); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 20, w[20]); - w[21] = ADD4_32(WSIGMA1_AVX(w[19]), w[5], w[14], WSIGMA0_AVX(w[6])); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 21, w[21]); - w[22] = ADD4_32(WSIGMA1_AVX(w[20]), w[6], w[15], WSIGMA0_AVX(w[7])); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 22, w[22]); - w[23] = ADD4_32(WSIGMA1_AVX(w[21]), w[7], w[16], WSIGMA0_AVX(w[8])); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 23, w[23]); - w[24] = ADD4_32(WSIGMA1_AVX(w[22]), w[8], w[17], WSIGMA0_AVX(w[9])); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 24, w[24]); - w[25] = ADD4_32(WSIGMA1_AVX(w[23]), w[9], w[18], WSIGMA0_AVX(w[10])); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 25, w[25]); - w[26] = ADD4_32(WSIGMA1_AVX(w[24]), w[10], w[19], WSIGMA0_AVX(w[11])); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 26, w[26]); - w[27] = ADD4_32(WSIGMA1_AVX(w[25]), w[11], w[20], WSIGMA0_AVX(w[12])); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 27, w[27]); - w[28] = ADD4_32(WSIGMA1_AVX(w[26]), w[12], w[21], WSIGMA0_AVX(w[13])); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 28, w[28]); - w[29] = ADD4_32(WSIGMA1_AVX(w[27]), w[13], w[22], WSIGMA0_AVX(w[14])); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 29, w[29]); - w[30] = ADD4_32(WSIGMA1_AVX(w[28]), w[14], w[23], WSIGMA0_AVX(w[15])); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 30, w[30]); - w[31] = ADD4_32(WSIGMA1_AVX(w[29]), w[15], w[24], WSIGMA0_AVX(w[16])); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 31, w[31]); - w[32] = ADD4_32(WSIGMA1_AVX(w[30]), w[16], w[25], WSIGMA0_AVX(w[17])); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 32, w[32]); - w[33] = ADD4_32(WSIGMA1_AVX(w[31]), w[17], w[26], WSIGMA0_AVX(w[18])); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 33, w[33]); - w[34] = ADD4_32(WSIGMA1_AVX(w[32]), w[18], w[27], WSIGMA0_AVX(w[19])); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 34, w[34]); - w[35] = ADD4_32(WSIGMA1_AVX(w[33]), w[19], w[28], WSIGMA0_AVX(w[20])); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 35, w[35]); - w[36] = ADD4_32(WSIGMA1_AVX(w[34]), w[20], w[29], WSIGMA0_AVX(w[21])); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 36, w[36]); - w[37] = ADD4_32(WSIGMA1_AVX(w[35]), w[21], w[30], WSIGMA0_AVX(w[22])); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 37, w[37]); - w[38] = ADD4_32(WSIGMA1_AVX(w[36]), w[22], w[31], WSIGMA0_AVX(w[23])); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 38, w[38]); - w[39] = ADD4_32(WSIGMA1_AVX(w[37]), w[23], w[32], WSIGMA0_AVX(w[24])); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 39, w[39]); - w[40] = ADD4_32(WSIGMA1_AVX(w[38]), w[24], w[33], WSIGMA0_AVX(w[25])); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 40, w[40]); - w[41] = ADD4_32(WSIGMA1_AVX(w[39]), w[25], w[34], WSIGMA0_AVX(w[26])); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 41, w[41]); - w[42] = ADD4_32(WSIGMA1_AVX(w[40]), w[26], w[35], WSIGMA0_AVX(w[27])); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 42, w[42]); - w[43] = ADD4_32(WSIGMA1_AVX(w[41]), w[27], w[36], WSIGMA0_AVX(w[28])); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 43, w[43]); - w[44] = ADD4_32(WSIGMA1_AVX(w[42]), w[28], w[37], WSIGMA0_AVX(w[29])); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 44, w[44]); - w[45] = ADD4_32(WSIGMA1_AVX(w[43]), w[29], w[38], WSIGMA0_AVX(w[30])); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 45, w[45]); - w[46] = ADD4_32(WSIGMA1_AVX(w[44]), w[30], w[39], WSIGMA0_AVX(w[31])); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 46, w[46]); - w[47] = ADD4_32(WSIGMA1_AVX(w[45]), w[31], w[40], WSIGMA0_AVX(w[32])); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 47, w[47]); - w[48] = ADD4_32(WSIGMA1_AVX(w[46]), w[32], w[41], WSIGMA0_AVX(w[33])); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 48, w[48]); - w[49] = ADD4_32(WSIGMA1_AVX(w[47]), w[33], w[42], WSIGMA0_AVX(w[34])); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 49, w[49]); - w[50] = ADD4_32(WSIGMA1_AVX(w[48]), w[34], w[43], WSIGMA0_AVX(w[35])); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 50, w[50]); - w[51] = ADD4_32(WSIGMA1_AVX(w[49]), w[35], w[44], WSIGMA0_AVX(w[36])); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 51, w[51]); - w[52] = ADD4_32(WSIGMA1_AVX(w[50]), w[36], w[45], WSIGMA0_AVX(w[37])); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 52, w[52]); - w[53] = ADD4_32(WSIGMA1_AVX(w[51]), w[37], w[46], WSIGMA0_AVX(w[38])); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 53, w[53]); - w[54] = ADD4_32(WSIGMA1_AVX(w[52]), w[38], w[47], WSIGMA0_AVX(w[39])); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 54, w[54]); - w[55] = ADD4_32(WSIGMA1_AVX(w[53]), w[39], w[48], WSIGMA0_AVX(w[40])); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 55, w[55]); - w[56] = ADD4_32(WSIGMA1_AVX(w[54]), w[40], w[49], WSIGMA0_AVX(w[41])); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 56, w[56]); - w[57] = ADD4_32(WSIGMA1_AVX(w[55]), w[41], w[50], WSIGMA0_AVX(w[42])); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 57, w[57]); - w[58] = ADD4_32(WSIGMA1_AVX(w[56]), w[42], w[51], WSIGMA0_AVX(w[43])); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 58, w[58]); - w[59] = ADD4_32(WSIGMA1_AVX(w[57]), w[43], w[52], WSIGMA0_AVX(w[44])); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 59, w[59]); - w[60] = ADD4_32(WSIGMA1_AVX(w[58]), w[44], w[53], WSIGMA0_AVX(w[45])); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 60, w[60]); - w[61] = ADD4_32(WSIGMA1_AVX(w[59]), w[45], w[54], WSIGMA0_AVX(w[46])); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 61, w[61]); - w[62] = ADD4_32(WSIGMA1_AVX(w[60]), w[46], w[55], WSIGMA0_AVX(w[47])); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 62, w[62]); - w[63] = ADD4_32(WSIGMA1_AVX(w[61]), w[47], w[56], WSIGMA0_AVX(w[48])); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 63, w[63]); - - // Feed Forward - ctx->s[0] = ADD32(s[0], ctx->s[0]); - ctx->s[1] = ADD32(s[1], ctx->s[1]); - ctx->s[2] = ADD32(s[2], ctx->s[2]); - ctx->s[3] = ADD32(s[3], ctx->s[3]); - ctx->s[4] = ADD32(s[4], ctx->s[4]); - ctx->s[5] = ADD32(s[5], ctx->s[5]); - ctx->s[6] = ADD32(s[6], ctx->s[6]); - ctx->s[7] = ADD32(s[7], ctx->s[7]); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_avx2/sha256avx.h b/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_avx2/sha256avx.h deleted file mode 100644 index d2c9d86782..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_avx2/sha256avx.h +++ /dev/null @@ -1,103 +0,0 @@ -#ifndef SHA256AVX_H -#define SHA256AVX_H - -#include -#include - -static const unsigned int RC[] = { - 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, - 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, - 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, - 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, - 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, - 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, - 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, - 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, - 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, - 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, - 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, - 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, - 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, - 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, - 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, - 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 -}; - -#define u32 uint32_t -#define u256 __m256i - -#define XOR _mm256_xor_si256 -#define OR _mm256_or_si256 -#define AND _mm256_and_si256 -#define ADD32 _mm256_add_epi32 -#define NOT(x) _mm256_xor_si256(x, _mm256_set_epi32(-1, -1, -1, -1, -1, -1, -1, -1)) - -#define LOAD(src) _mm256_loadu_si256((__m256i *)(src)) -#define STORE(dest,src) _mm256_storeu_si256((__m256i *)(dest),src) - -#define BYTESWAP(x) _mm256_shuffle_epi8(x, _mm256_set_epi8(0xc,0xd,0xe,0xf,0x8,0x9,0xa,0xb,0x4,0x5,0x6,0x7,0x0,0x1,0x2,0x3,0xc,0xd,0xe,0xf,0x8,0x9,0xa,0xb,0x4,0x5,0x6,0x7,0x0,0x1,0x2,0x3)) - -#define SHIFTR32(x, y) _mm256_srli_epi32(x, y) -#define SHIFTL32(x, y) _mm256_slli_epi32(x, y) - -#define ROTR32(x, y) OR(SHIFTR32(x, y), SHIFTL32(x, 32 - (y))) -#define ROTL32(x, y) OR(SHIFTL32(x, y), SHIFTR32(x, 32 - (y))) - -#define XOR3(a, b, c) XOR(XOR(a, b), c) - -#define ADD3_32(a, b, c) ADD32(ADD32(a, b), c) -#define ADD4_32(a, b, c, d) ADD32(ADD32(ADD32(a, b), c), d) -#define ADD5_32(a, b, c, d, e) ADD32(ADD32(ADD32(ADD32(a, b), c), d), e) - -#define MAJ_AVX(a, b, c) XOR3(AND(a, b), AND(a, c), AND(b, c)) -#define CH_AVX(a, b, c) XOR(AND(a, b), AND(NOT(a), c)) - -#define SIGMA1_AVX(x) XOR3(ROTR32(x, 6), ROTR32(x, 11), ROTR32(x, 25)) -#define SIGMA0_AVX(x) XOR3(ROTR32(x, 2), ROTR32(x, 13), ROTR32(x, 22)) - -#define WSIGMA1_AVX(x) XOR3(ROTR32(x, 17), ROTR32(x, 19), SHIFTR32(x, 10)) -#define WSIGMA0_AVX(x) XOR3(ROTR32(x, 7), ROTR32(x, 18), SHIFTR32(x, 3)) - -#define SHA256ROUND_AVX(a, b, c, d, e, f, g, h, rc, w) \ - T0 = ADD5_32(h, SIGMA1_AVX(e), CH_AVX(e, f, g), _mm256_set1_epi32((int)RC[rc]), w); \ - (d) = ADD32(d, T0); \ - T1 = ADD32(SIGMA0_AVX(a), MAJ_AVX(a, b, c)); \ - (h) = ADD32(T0, T1); - -typedef struct SHA256state { - u256 s[8]; - uint8_t msgblocks[8 * 64]; - unsigned int datalen; - uint64_t msglen; -} sha256ctxx8; - - -void PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_transpose(u256 s[8]); -void PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_sha256_init_frombytes_x8(sha256ctxx8 *ctx, const uint8_t *s, unsigned long long msglen); -void PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_sha256_init8x(sha256ctxx8 *ctx); -void PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_sha256_update8x(sha256ctxx8 *ctx, - const unsigned char *d0, - const unsigned char *d1, - const unsigned char *d2, - const unsigned char *d3, - const unsigned char *d4, - const unsigned char *d5, - const unsigned char *d6, - const unsigned char *d7, - unsigned long long len); -void PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_sha256_final8x(sha256ctxx8 *ctx, - unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7); - -void PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_sha256_transform8x(sha256ctxx8 *ctx, const unsigned char *data); - -void PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_sha256_clone_statex8(sha256ctxx8 *outctx, const sha256ctxx8 *inctx); - - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_avx2/sha256x8.c b/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_avx2/sha256x8.c deleted file mode 100644 index 072faa0643..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_avx2/sha256x8.c +++ /dev/null @@ -1,128 +0,0 @@ -#include - -#include "sha256.h" -#include "sha256avx.h" -#include "sha256x8.h" -#include "utils.h" - -void PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_seed_statex8(sha256ctxx8 *ctx, const unsigned char *pub_seed) { - uint8_t block[PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_BLOCK_BYTES]; - size_t i; - - for (i = 0; i < PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N; ++i) { - block[i] = pub_seed[i]; - } - for (i = PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N; i < PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_BLOCK_BYTES; ++i) { - block[i] = 0; - } - - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_sha256_init8x(ctx); - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_sha256_update8x(ctx, block, block, block, block, block, block, block, block, PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_BLOCK_BYTES); - -} - -/* This provides a wrapper around the internals of 8x parallel SHA256 */ -void PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_sha256x8(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - const unsigned char *in4, - const unsigned char *in5, - const unsigned char *in6, - const unsigned char *in7, unsigned long long inlen) { - sha256ctxx8 ctx; - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_sha256_init8x(&ctx); - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_sha256_update8x(&ctx, in0, in1, in2, in3, in4, in5, in6, in7, inlen); - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_sha256_final8x(&ctx, out0, out1, out2, out3, out4, out5, out6, out7); -} - -/** - * Note that inlen should be sufficiently small that it still allows for - * an array to be allocated on the stack. Typically 'in' is merely a seed. - * Outputs outlen number of bytes - */ -void PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_mgf1x8( - unsigned char *outx8, - unsigned long outlen, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - const unsigned char *in4, - const unsigned char *in5, - const unsigned char *in6, - const unsigned char *in7, - unsigned long inlen) { - unsigned char inbufx8[8 * ((PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_ADDR_BYTES) + 4)]; - unsigned char outbufx8[8 * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_OUTPUT_BYTES]; - unsigned long i; - unsigned int j; - - memcpy(inbufx8 + 0 * (inlen + 4), in0, inlen); - memcpy(inbufx8 + 1 * (inlen + 4), in1, inlen); - memcpy(inbufx8 + 2 * (inlen + 4), in2, inlen); - memcpy(inbufx8 + 3 * (inlen + 4), in3, inlen); - memcpy(inbufx8 + 4 * (inlen + 4), in4, inlen); - memcpy(inbufx8 + 5 * (inlen + 4), in5, inlen); - memcpy(inbufx8 + 6 * (inlen + 4), in6, inlen); - memcpy(inbufx8 + 7 * (inlen + 4), in7, inlen); - - /* While we can fit in at least another full block of SHA256 output.. */ - for (i = 0; (i + 1)*PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_OUTPUT_BYTES <= outlen; i++) { - for (j = 0; j < 8; j++) { - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_ull_to_bytes(inbufx8 + inlen + j * (inlen + 4), 4, i); - } - - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_sha256x8(outx8 + 0 * outlen, - outx8 + 1 * outlen, - outx8 + 2 * outlen, - outx8 + 3 * outlen, - outx8 + 4 * outlen, - outx8 + 5 * outlen, - outx8 + 6 * outlen, - outx8 + 7 * outlen, - inbufx8 + 0 * (inlen + 4), - inbufx8 + 1 * (inlen + 4), - inbufx8 + 2 * (inlen + 4), - inbufx8 + 3 * (inlen + 4), - inbufx8 + 4 * (inlen + 4), - inbufx8 + 5 * (inlen + 4), - inbufx8 + 6 * (inlen + 4), - inbufx8 + 7 * (inlen + 4), inlen + 4); - outx8 += PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_OUTPUT_BYTES; - } - /* Until we cannot anymore, and we fill the remainder. */ - for (j = 0; j < 8; j++) { - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_ull_to_bytes(inbufx8 + inlen + j * (inlen + 4), 4, i); - } - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_sha256x8(outbufx8 + 0 * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 1 * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 2 * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 3 * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 4 * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 5 * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 6 * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 7 * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_OUTPUT_BYTES, - inbufx8 + 0 * (inlen + 4), - inbufx8 + 1 * (inlen + 4), - inbufx8 + 2 * (inlen + 4), - inbufx8 + 3 * (inlen + 4), - inbufx8 + 4 * (inlen + 4), - inbufx8 + 5 * (inlen + 4), - inbufx8 + 6 * (inlen + 4), - inbufx8 + 7 * (inlen + 4), inlen + 4); - - for (j = 0; j < 8; j++) { - memcpy(outx8 + j * outlen, - outbufx8 + j * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_OUTPUT_BYTES, - outlen - i * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_OUTPUT_BYTES); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_avx2/sha256x8.h b/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_avx2/sha256x8.h deleted file mode 100644 index 12100f359f..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_avx2/sha256x8.h +++ /dev/null @@ -1,44 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256X8_H -#define PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256X8_H - -#include "sha256avx.h" - -#define PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_BLOCK_BYTES 64 -#define PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_OUTPUT_BYTES 32 /* This does not necessarily equal PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N */ - -/* This provides a wrapper around the internals of 8x parallel SHA256 */ -void PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_sha256x8(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - const unsigned char *in4, - const unsigned char *in5, - const unsigned char *in6, - const unsigned char *in7, unsigned long long inlen); - -/** - * Note that inlen should be sufficiently small that it still allows for - * an array to be allocated on the stack. Typically 'in' is merely a seed. - * Outputs outlen number of bytes - */ -void PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_mgf1x8(unsigned char *outx8, unsigned long outlen, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - const unsigned char *in4, - const unsigned char *in5, - const unsigned char *in6, - const unsigned char *in7, - unsigned long inlen); - -void PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_seed_statex8(sha256ctxx8 *ctx, const unsigned char *pub_seed); -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_avx2/sign.c b/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_avx2/sign.c deleted file mode 100644 index 493c12e1e9..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_avx2/sign.c +++ /dev/null @@ -1,356 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "api.h" -#include "fors.h" -#include "hash.h" -#include "hash_state.h" -#include "params.h" -#include "randombytes.h" -#include "thash.h" -#include "utils.h" -#include "wots.h" - -/** - * Computes the leaf at a given address. First generates the WOTS key pair, - * then computes leaf by hashing horizontally. - */ -static void wots_gen_leaf(unsigned char *leaf, const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx, const uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - unsigned char pk[PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_WOTS_BYTES]; - uint32_t wots_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_set_type( - wots_addr, PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_set_type( - wots_pk_addr, PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_ADDR_TYPE_WOTSPK); - - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_set_keypair_addr( - wots_addr, addr_idx); - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_wots_gen_pk( - pk, sk_seed, pub_seed, wots_addr, hash_state_seeded); - - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_copy_keypair_addr( - wots_pk_addr, wots_addr); - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_thash_WOTS_LEN( - leaf, pk, pub_seed, wots_pk_addr, hash_state_seeded); -} - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_crypto_sign_secretkeybytes(void) { - return PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_CRYPTO_SECRETKEYBYTES; -} - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_crypto_sign_publickeybytes(void) { - return PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_CRYPTO_PUBLICKEYBYTES; -} - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_crypto_sign_bytes(void) { - return PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_CRYPTO_BYTES; -} - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_crypto_sign_seedbytes(void) { - return PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_CRYPTO_SEEDBYTES; -} - -/* - * Generates an SPX key pair given a seed of length - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed) { - /* We do not need the auth path in key generation, but it simplifies the - code to have just one treehash routine that computes both root and path - in one function. */ - unsigned char auth_path[PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_TREE_HEIGHT * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N]; - uint32_t top_tree_addr[8] = {0}; - hash_state hash_state_seeded; - - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_set_layer_addr( - top_tree_addr, PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_D - 1); - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_set_type( - top_tree_addr, PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_ADDR_TYPE_HASHTREE); - - /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ - memcpy(sk, seed, PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_CRYPTO_SEEDBYTES); - - memcpy(pk, sk + 2 * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N, PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_initialize_hash_function(&hash_state_seeded, pk, sk); - - /* Compute root node of the top-most subtree. */ - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_treehash_TREE_HEIGHT( - sk + 3 * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N, auth_path, sk, sk + 2 * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N, 0, 0, - wots_gen_leaf, top_tree_addr, &hash_state_seeded); - - memcpy(pk + PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N, sk + 3 * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N, PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N); - - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_destroy_hash_function(&hash_state_seeded); - return 0; -} - -/* - * Generates an SPX key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk) { - unsigned char seed[PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_CRYPTO_SEEDBYTES]; - randombytes(seed, PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_CRYPTO_SEEDBYTES); - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_crypto_sign_seed_keypair( - pk, sk, seed); - - return 0; -} - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - const unsigned char *sk_seed = sk; - const unsigned char *sk_prf = sk + PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N; - const unsigned char *pk = sk + 2 * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N; - const unsigned char *pub_seed = pk; - - unsigned char optrand[PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N]; - unsigned char mhash[PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_FORS_MSG_BYTES]; - unsigned char root[PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N]; - uint32_t i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - - hash_state hash_state_seeded; - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_initialize_hash_function( - &hash_state_seeded, - pub_seed, sk_seed); - - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_set_type( - wots_addr, PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_set_type( - tree_addr, PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_ADDR_TYPE_HASHTREE); - - /* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ - randombytes(optrand, PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N); - /* Compute the digest randomization value. */ - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_gen_message_random( - sig, sk_prf, optrand, m, mlen, &hash_state_seeded); - - /* Derive the message digest and leaf index from R, PK and M. */ - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N; - - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_set_keypair_addr( - wots_addr, idx_leaf); - - /* Sign the message hash using FORS. */ - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_fors_sign( - sig, root, mhash, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_FORS_BYTES; - - for (i = 0; i < PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_D; i++) { - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_set_tree_addr(tree_addr, tree); - - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_set_keypair_addr( - wots_addr, idx_leaf); - - /* Compute a WOTS signature. */ - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_wots_sign( - sig, root, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_WOTS_BYTES; - - /* Compute the authentication path for the used WOTS leaf. */ - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_treehash_TREE_HEIGHT( - root, sig, sk_seed, pub_seed, idx_leaf, 0, - wots_gen_leaf, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_TREE_HEIGHT * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_TREE_HEIGHT; - } - - *siglen = PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_BYTES; - - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_destroy_hash_function(&hash_state_seeded); - return 0; -} - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk) { - const unsigned char *pub_seed = pk; - const unsigned char *pub_root = pk + PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N; - unsigned char mhash[PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_FORS_MSG_BYTES]; - unsigned char wots_pk[PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_WOTS_BYTES]; - unsigned char root[PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N]; - unsigned char leaf[PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N]; - unsigned int i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - hash_state hash_state_seeded; - - if (siglen != PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_BYTES) { - return -1; - } - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_initialize_hash_function( - &hash_state_seeded, - pub_seed, NULL); - - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_set_type( - wots_addr, PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_set_type( - tree_addr, PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_ADDR_TYPE_HASHTREE); - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_set_type( - wots_pk_addr, PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_ADDR_TYPE_WOTSPK); - - /* Derive the message digest and leaf index from R || PK || M. */ - /* The additional PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N is a result of the hash domain separator. */ - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N; - - /* Layer correctly defaults to 0, so no need to set_layer_addr */ - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_set_keypair_addr( - wots_addr, idx_leaf); - - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_fors_pk_from_sig( - root, sig, mhash, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_FORS_BYTES; - - /* For each subtree.. */ - for (i = 0; i < PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_D; i++) { - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_set_tree_addr(tree_addr, tree); - - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_set_keypair_addr( - wots_addr, idx_leaf); - - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_copy_keypair_addr( - wots_pk_addr, wots_addr); - - /* The WOTS public key is only correct if the signature was correct. */ - /* Initially, root is the FORS pk, but on subsequent iterations it is - the root of the subtree below the currently processed subtree. */ - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_wots_pk_from_sig( - wots_pk, sig, root, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_WOTS_BYTES; - - /* Compute the leaf node using the WOTS public key. */ - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_thash_WOTS_LEN( - leaf, wots_pk, pub_seed, wots_pk_addr, &hash_state_seeded); - - /* Compute the root node of this subtree. */ - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_compute_root( - root, leaf, idx_leaf, 0, sig, PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_TREE_HEIGHT, - pub_seed, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_TREE_HEIGHT * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_TREE_HEIGHT; - } - - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_destroy_hash_function(&hash_state_seeded); - /* Check if the root node equals the root node in the public key. */ - if (memcmp(root, pub_root, PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N) != 0) { - return -1; - } - - return 0; -} - - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - size_t siglen; - - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_crypto_sign_signature( - sm, &siglen, m, mlen, sk); - - memmove(sm + PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_BYTES, m, mlen); - *smlen = siglen + mlen; - - return 0; -} - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk) { - /* The API caller does not necessarily know what size a signature should be - but SPHINCS+ signatures are always exactly PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_BYTES. */ - if (smlen < PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_BYTES) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - *mlen = smlen - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_BYTES; - - if (PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_crypto_sign_verify( - sm, PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_BYTES, sm + PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_BYTES, *mlen, pk)) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - /* If verification was successful, move the message to the right place. */ - memmove(m, sm + PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_BYTES, *mlen); - - return 0; -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_avx2/thash.h b/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_avx2/thash.h deleted file mode 100644 index 7813c73c92..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_avx2/thash.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_THASH_H -#define PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_THASH_H - -#include "hash_state.h" - -#include - -void PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_avx2/thash_sha256_robust.c b/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_avx2/thash_sha256_robust.c deleted file mode 100644 index 09014cc943..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_avx2/thash_sha256_robust.c +++ /dev/null @@ -1,78 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "thash.h" - -#include "sha2.h" -#include "sha256.h" - -/** - * Takes an array of inblocks concatenated arrays of PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N bytes. - */ -static void thash( - unsigned char *out, unsigned char *buf, - const unsigned char *in, unsigned int inblocks, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char outbuf[PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_OUTPUT_BYTES]; - unsigned char *bitmask = buf + PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_ADDR_BYTES + 4; - sha256ctx sha2_state; - unsigned int i; - - memcpy(buf, pub_seed, PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N); - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_compress_address(buf + PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N, addr); - /* MGF1 requires us to have 4 extra bytes in 'buf' */ - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_mgf1(bitmask, inblocks * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N, buf, PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_ADDR_BYTES); - - /* Retrieve precomputed state containing pub_seed */ - sha256_inc_ctx_clone(&sha2_state, &hash_state_seeded->x1); - - for (i = 0; i < inblocks * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N; i++) { - buf[PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_ADDR_BYTES + i] = in[i] ^ bitmask[i]; - } - - sha256_inc_finalize(outbuf, &sha2_state, buf + PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N, - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N); - memcpy(out, outbuf, PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N); -} - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_ADDR_BYTES + 4 + 1 * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N]; - thash(out, buf, in, 1, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_ADDR_BYTES + 4 + 2 * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N]; - thash(out, buf, in, 2, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_ADDR_BYTES + 4 + PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_WOTS_LEN * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N]; - thash(out, buf, in, PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_WOTS_LEN, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_ADDR_BYTES + 4 + PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_FORS_TREES * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N]; - thash(out, buf, in, PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_FORS_TREES, pub_seed, addr, hash_state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_avx2/thash_sha256_robustx8.c b/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_avx2/thash_sha256_robustx8.c deleted file mode 100644 index e9a1acb267..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_avx2/thash_sha256_robustx8.c +++ /dev/null @@ -1,156 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "sha256.h" -#include "sha256avx.h" -#include "sha256x8.h" -#include "thashx8.h" -#include "utils.h" - -/** - * 8-way parallel version of thash; takes 8x as much input and output - */ -static void thashx8(uint8_t *out0, - uint8_t *out1, - uint8_t *out2, - uint8_t *out3, - uint8_t *out4, - uint8_t *out5, - uint8_t *out6, - uint8_t *out7, - const uint8_t *in0, - const uint8_t *in1, - const uint8_t *in2, - const uint8_t *in3, - const uint8_t *in4, - const uint8_t *in5, - const uint8_t *in6, - const uint8_t *in7, - unsigned int inblocks, - const uint8_t *pub_seed, - uint32_t addrx8[8 * 8], - uint8_t *bufx8, - uint8_t *bitmaskx8, - const hash_state *state_seeded) { - unsigned char outbufx8[8 * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_OUTPUT_BYTES]; - unsigned int i; - sha256ctxx8 ctx; - - (void)pub_seed; /* Suppress an 'unused parameter' warning. */ - - for (i = 0; i < 8; i++) { - memcpy(bufx8 + i * (PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N), - pub_seed, PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N); - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_compress_address(bufx8 + PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N + - i * (PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N), - addrx8 + i * 8); - } - - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_mgf1x8(bitmaskx8, inblocks * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N, - bufx8 + 0 * (PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N), - bufx8 + 1 * (PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N), - bufx8 + 2 * (PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N), - bufx8 + 3 * (PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N), - bufx8 + 4 * (PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N), - bufx8 + 5 * (PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N), - bufx8 + 6 * (PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N), - bufx8 + 7 * (PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N), - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_ADDR_BYTES - ); - - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_sha256_clone_statex8(&ctx, &state_seeded->x8); - - for (i = 0; i < inblocks * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N; i++) { - bufx8[PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_ADDR_BYTES + i + - 0 * (PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N)] = - in0[i] ^ bitmaskx8[i + 0 * (inblocks * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N)]; - bufx8[PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_ADDR_BYTES + i + - 1 * (PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N)] = - in1[i] ^ bitmaskx8[i + 1 * (inblocks * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N)]; - bufx8[PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_ADDR_BYTES + i + - 2 * (PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N)] = - in2[i] ^ bitmaskx8[i + 2 * (inblocks * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N)]; - bufx8[PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_ADDR_BYTES + i + - 3 * (PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N)] = - in3[i] ^ bitmaskx8[i + 3 * (inblocks * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N)]; - bufx8[PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_ADDR_BYTES + i + - 4 * (PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N)] = - in4[i] ^ bitmaskx8[i + 4 * (inblocks * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N)]; - bufx8[PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_ADDR_BYTES + i + - 5 * (PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N)] = - in5[i] ^ bitmaskx8[i + 5 * (inblocks * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N)]; - bufx8[PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_ADDR_BYTES + i + - 6 * (PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N)] = - in6[i] ^ bitmaskx8[i + 6 * (inblocks * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N)]; - bufx8[PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_ADDR_BYTES + i + - 7 * (PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N)] = - in7[i] ^ bitmaskx8[i + 7 * (inblocks * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N)]; - } - - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_sha256_update8x(&ctx, - bufx8 + PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N + 0 * (PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N), - bufx8 + PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N + 1 * (PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N), - bufx8 + PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N + 2 * (PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N), - bufx8 + PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N + 3 * (PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N), - bufx8 + PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N + 4 * (PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N), - bufx8 + PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N + 5 * (PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N), - bufx8 + PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N + 6 * (PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N), - bufx8 + PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N + 7 * (PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N), - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N); - - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_sha256_final8x(&ctx, - outbufx8 + 0 * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 1 * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 2 * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 3 * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 4 * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 5 * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 6 * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 7 * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_OUTPUT_BYTES); - - memcpy(out0, outbufx8 + 0 * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N); - memcpy(out1, outbufx8 + 1 * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N); - memcpy(out2, outbufx8 + 2 * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N); - memcpy(out3, outbufx8 + 3 * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N); - memcpy(out4, outbufx8 + 4 * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N); - memcpy(out5, outbufx8 + 5 * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N); - memcpy(out6, outbufx8 + 6 * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N); - memcpy(out7, outbufx8 + 7 * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N); -} - -#define thash_size_variant(name, size) \ - void PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_thashx8_##name(unsigned char *out0, \ - unsigned char *out1, \ - unsigned char *out2, \ - unsigned char *out3, \ - unsigned char *out4, \ - unsigned char *out5, \ - unsigned char *out6, \ - unsigned char *out7, \ - const unsigned char *in0, \ - const unsigned char *in1, \ - const unsigned char *in2, \ - const unsigned char *in3, \ - const unsigned char *in4, \ - const unsigned char *in5, \ - const unsigned char *in6, \ - const unsigned char *in7, \ - const unsigned char *pub_seed, \ - uint32_t addrx8[8*8], \ - const hash_state *state_seeded) { \ - const unsigned int inblocks = (size); \ - uint8_t bufx8[8*(PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_SHA256_ADDR_BYTES + (size)*PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N)]; \ - uint8_t bitmaskx8[8*((size) * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N)]; \ - thashx8(out0, out1, out2, out3, out4, out5, out6, out7, \ - in0, in1, in2, in3, in4, in5, in6, in7, inblocks, \ - pub_seed, addrx8, bufx8, bitmaskx8, state_seeded); \ - } - -thash_size_variant(1, 1) -thash_size_variant(2, 2) -thash_size_variant(WOTS_LEN, PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_WOTS_LEN) -thash_size_variant(FORS_TREES, PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_FORS_TREES) - -#undef thash_size_variant diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_avx2/thashx8.h b/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_avx2/thashx8.h deleted file mode 100644 index 40b4bada3c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_avx2/thashx8.h +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_THASHX8_H -#define PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_THASHX8_H - -#include - -#include "hash_state.h" -#include "sha256avx.h" - - -#define thashx8_variant(name) \ - void PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_thashx8_##name( \ - unsigned char *out0, \ - unsigned char *out1, \ - unsigned char *out2, \ - unsigned char *out3, \ - unsigned char *out4, \ - unsigned char *out5, \ - unsigned char *out6, \ - unsigned char *out7, \ - const unsigned char *in0, \ - const unsigned char *in1, \ - const unsigned char *in2, \ - const unsigned char *in3, \ - const unsigned char *in4, \ - const unsigned char *in5, \ - const unsigned char *in6, \ - const unsigned char *in7, \ - const unsigned char *pub_seed, \ - uint32_t addrx8[8*8], \ - const hash_state *state_seeded) - - -thashx8_variant(1); -thashx8_variant(2); -thashx8_variant(WOTS_LEN); -thashx8_variant(FORS_TREES); - -#undef thashx8_variant -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_avx2/utils.c b/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_avx2/utils.c deleted file mode 100644 index 1730ace5ee..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_avx2/utils.c +++ /dev/null @@ -1,199 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "hash_state.h" -#include "params.h" -#include "thash.h" -#include "utils.h" - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in) { - - /* Iterate over out in decreasing order, for big-endianness. */ - for (size_t i = outlen; i > 0; i--) { - out[i - 1] = in & 0xff; - in = in >> 8; - } -} - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_bytes_to_ull( - const unsigned char *in, size_t inlen) { - unsigned long long retval = 0; - - for (size_t i = 0; i < inlen; i++) { - retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); - } - return retval; -} - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - uint32_t i; - unsigned char buffer[2 * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N]; - - /* If leaf_idx is odd (last bit = 1), current path element is a right child - and auth_path has to go left. Otherwise it is the other way around. */ - if (leaf_idx & 1) { - memcpy(buffer + PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N, leaf, PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N); - } else { - memcpy(buffer, leaf, PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N); - memcpy(buffer + PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N, auth_path, PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N); - } - auth_path += PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N; - - for (i = 0; i < tree_height - 1; i++) { - leaf_idx >>= 1; - idx_offset >>= 1; - /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_set_tree_height(addr, i + 1); - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_set_tree_index( - addr, leaf_idx + idx_offset); - - /* Pick the right or left neighbor, depending on parity of the node. */ - if (leaf_idx & 1) { - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_thash_2( - buffer + PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N); - } else { - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_thash_2( - buffer, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer + PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N, auth_path, PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N); - } - auth_path += PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N; - } - - /* The last iteration is exceptional; we do not copy an auth_path node. */ - leaf_idx >>= 1; - idx_offset >>= 1; - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_set_tree_height(addr, tree_height); - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_set_tree_index( - addr, leaf_idx + idx_offset); - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_thash_2( - root, buffer, pub_seed, addr, hash_state_seeded); -} - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -static void PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_treehash( - unsigned char *root, unsigned char *auth_path, - unsigned char *stack, unsigned int *heights, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - - unsigned int offset = 0; - uint32_t idx; - uint32_t tree_idx; - - for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { - /* Add the next leaf node to the stack. */ - gen_leaf(stack + offset * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N, - sk_seed, pub_seed, idx + idx_offset, tree_addr, - hash_state_seeded); - offset++; - heights[offset - 1] = 0; - - /* If this is a node we need for the auth path.. */ - if ((leaf_idx ^ 0x1) == idx) { - memcpy(auth_path, stack + (offset - 1)*PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N, PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N); - } - - /* While the top-most nodes are of equal height.. */ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { - /* Compute index of the new node, in the next layer. */ - tree_idx = (idx >> (heights[offset - 1] + 1)); - - /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_set_tree_height( - tree_addr, heights[offset - 1] + 1); - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_set_tree_index( - tree_addr, tree_idx + (idx_offset >> (heights[offset - 1] + 1))); - /* Hash the top-most nodes from the stack together. */ - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_thash_2( - stack + (offset - 2)*PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N, stack + (offset - 2)*PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N, - pub_seed, tree_addr, hash_state_seeded); - offset--; - /* Note that the top-most node is now one layer higher. */ - heights[offset - 1]++; - - /* If this is a node we need for the auth path.. */ - if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_path + heights[offset - 1]*PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N, - stack + (offset - 1)*PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N, PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N); - } - } - } - memcpy(root, stack, PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N); -} - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_FORS_HEIGHT + 1)*PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N]; - unsigned int heights[PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_FORS_HEIGHT + 1]; - - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_FORS_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_TREE_HEIGHT + 1)*PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N]; - unsigned int heights[PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_TREE_HEIGHT + 1]; - - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_TREE_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_avx2/utils.h b/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_avx2/utils.h deleted file mode 100644 index fa75f95314..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_avx2/utils.h +++ /dev/null @@ -1,64 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_UTILS_H -#define PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_UTILS_H - -#include "hash_state.h" -#include "params.h" -#include -#include - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in); - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_bytes_to_ull( - const unsigned char *in, size_t inlen); - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -void PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_avx2/utilsx8.c b/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_avx2/utilsx8.c deleted file mode 100644 index 6688c669a8..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_avx2/utilsx8.c +++ /dev/null @@ -1,172 +0,0 @@ -#include - -#include "address.h" -#include "params.h" -#include "thashx8.h" -#include "utils.h" - -#include "utilsx8.h" - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -static void treehashx8(unsigned char *rootx8, unsigned char *auth_pathx8, - unsigned char *stackx8, unsigned int *heights, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t leaf_idx[8], uint32_t idx_offset[8], - uint32_t tree_height, - void (*gen_leafx8)( - unsigned char * /* leaf0 */, - unsigned char * /* leaf1 */, - unsigned char * /* leaf2 */, - unsigned char * /* leaf3 */, - unsigned char * /* leaf4 */, - unsigned char * /* leaf5 */, - unsigned char * /* leaf6 */, - unsigned char * /* leaf7 */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx0 */, - uint32_t /* addr_idx1 */, - uint32_t /* addr_idx2 */, - uint32_t /* addr_idx3 */, - uint32_t /* addr_idx4 */, - uint32_t /* addr_idx5 */, - uint32_t /* addr_idx6 */, - uint32_t /* addr_idx7 */, - const uint32_t[8] /* tree_addr */, - const hash_state * /* state_seeded */), - uint32_t tree_addrx8[8 * 8], - const hash_state *state_seeded) { - unsigned int offset = 0; - uint32_t idx; - uint32_t tree_idx; - unsigned int j; - - for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { - /* Add the next leaf node to the stack. */ - gen_leafx8(stackx8 + 0 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N + offset * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N, - stackx8 + 1 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N + offset * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N, - stackx8 + 2 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N + offset * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N, - stackx8 + 3 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N + offset * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N, - stackx8 + 4 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N + offset * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N, - stackx8 + 5 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N + offset * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N, - stackx8 + 6 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N + offset * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N, - stackx8 + 7 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N + offset * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N, - sk_seed, pub_seed, - idx + idx_offset[0], - idx + idx_offset[1], - idx + idx_offset[2], - idx + idx_offset[3], - idx + idx_offset[4], - idx + idx_offset[5], - idx + idx_offset[6], - idx + idx_offset[7], - tree_addrx8, - state_seeded); - offset++; - heights[offset - 1] = 0; - - /* If this is a node we need for the auth path.. */ - for (j = 0; j < 8; j++) { - if ((leaf_idx[j] ^ 0x1) == idx) { - memcpy(auth_pathx8 + j * tree_height * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N, - stackx8 + j * (tree_height + 1)*PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N + (offset - 1)*PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N, PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N); - } - } - - /* While the top-most nodes are of equal height.. */ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { - /* Compute index of the new node, in the next layer. */ - tree_idx = (idx >> (heights[offset - 1] + 1)); - - /* Set the address of the node we're creating. */ - for (j = 0; j < 8; j++) { - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_set_tree_height(tree_addrx8 + j * 8, heights[offset - 1] + 1); - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_set_tree_index(tree_addrx8 + j * 8, - tree_idx + (idx_offset[j] >> (heights[offset - 1] + 1))); - } - /* Hash the top-most nodes from the stack together. */ - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_thashx8_2(stackx8 + 0 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N, - stackx8 + 1 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N, - stackx8 + 2 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N, - stackx8 + 3 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N, - stackx8 + 4 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N, - stackx8 + 5 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N, - stackx8 + 6 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N, - stackx8 + 7 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N, - stackx8 + 0 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N, - stackx8 + 1 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N, - stackx8 + 2 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N, - stackx8 + 3 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N, - stackx8 + 4 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N, - stackx8 + 5 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N, - stackx8 + 6 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N, - stackx8 + 7 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N, - pub_seed, tree_addrx8, state_seeded); - offset--; - /* Note that the top-most node is now one layer higher. */ - heights[offset - 1]++; - - /* If this is a node we need for the auth path.. */ - for (j = 0; j < 8; j++) { - if (((leaf_idx[j] >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_pathx8 + j * tree_height * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N + heights[offset - 1]*PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N, - stackx8 + j * (tree_height + 1)*PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N + (offset - 1)*PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N, PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N); - } - } - } - } - - for (j = 0; j < 8; j++) { - memcpy(rootx8 + j * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N, stackx8 + j * (tree_height + 1)*PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N, PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N); - } -} - -/* The wrappers below ensure we used fixed-size buffers on the stack (no VLAs) */ - - -#define treehashx8_variant(name, size) \ - void PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_treehashx8_##name( \ - unsigned char *rootx8, unsigned char *auth_pathx8, \ - const unsigned char *sk_seed, const unsigned char *pub_seed, \ - const uint32_t leaf_idx[8], uint32_t idx_offset[8], \ - void (*gen_leafx8)( \ - unsigned char* /* leaf0 */, \ - unsigned char* /* leaf1 */, \ - unsigned char* /* leaf2 */, \ - unsigned char* /* leaf3 */, \ - unsigned char* /* leaf4 */, \ - unsigned char* /* leaf5 */, \ - unsigned char* /* leaf6 */, \ - unsigned char* /* leaf7 */, \ - const unsigned char* /* sk_seed */, \ - const unsigned char* /* pub_seed */, \ - uint32_t /* addr_idx0 */, \ - uint32_t /* addr_idx1 */, \ - uint32_t /* addr_idx2 */, \ - uint32_t /* addr_idx3 */, \ - uint32_t /* addr_idx4 */, \ - uint32_t /* addr_idx5 */, \ - uint32_t /* addr_idx6 */, \ - uint32_t /* addr_idx7 */, \ - const uint32_t[8] /* tree_addr */, \ - const hash_state* /* state_seeded */), \ - uint32_t tree_addrx8[8*8], \ - const hash_state *state_seeded) \ - { \ - const uint32_t tree_height = (size); \ - unsigned char stackx8[8*((size) + 1)*PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N]; \ - unsigned int heights[(size) + 1]; \ - treehashx8(rootx8, auth_pathx8, stackx8, heights, sk_seed, pub_seed, \ - leaf_idx, idx_offset, tree_height, gen_leafx8, tree_addrx8, state_seeded); \ - } - -treehashx8_variant(FORS_HEIGHT, PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_FORS_HEIGHT) - -#undef treehashx8_variant diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_avx2/utilsx8.h b/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_avx2/utilsx8.h deleted file mode 100644 index f94033d6e4..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_avx2/utilsx8.h +++ /dev/null @@ -1,46 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_UTILSX8_H -#define PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_UTILSX8_H - -#include - -#include "hash_state.h" -#include "params.h" - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ - -void PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_treehashx8_FORS_HEIGHT( - unsigned char *rootx8, unsigned char *auth_pathx8, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t leaf_idx[8], uint32_t idx_offset[8], - void (*gen_leafx8)( - unsigned char * /* leaf0 */, - unsigned char * /* leaf1 */, - unsigned char * /* leaf2 */, - unsigned char * /* leaf3 */, - unsigned char * /* leaf4 */, - unsigned char * /* leaf5 */, - unsigned char * /* leaf6 */, - unsigned char * /* leaf7 */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx0 */, - uint32_t /* addr_idx1 */, - uint32_t /* addr_idx2 */, - uint32_t /* addr_idx3 */, - uint32_t /* addr_idx4 */, - uint32_t /* addr_idx5 */, - uint32_t /* addr_idx6 */, - uint32_t /* addr_idx7 */, - const uint32_t[8] /* tree_addr */, - const hash_state * /* state_seeded */), - uint32_t tree_addrx8[8 * 8], - const hash_state *state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_avx2/wots.c b/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_avx2/wots.c deleted file mode 100644 index 7dd41319a6..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_avx2/wots.c +++ /dev/null @@ -1,240 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "hash_state.h" -#include "hashx8.h" -#include "params.h" -#include "thash.h" -#include "thashx8.h" -#include "utils.h" -#include "wots.h" - -// TODO clarify address expectations, and make them more uniform. -// TODO i.e. do we expect types to be set already? -// TODO and do we expect modifications or copies? - -/** - * Computes the starting value for a chain, i.e. the secret key. - * Expects the address to be complete up to the chain address. - */ -static void wots_gen_sk(unsigned char *sk, const unsigned char *sk_seed, - uint32_t wots_addr[8], const hash_state *state_seeded) { - /* Make sure that the hash address is actually zeroed. */ - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_set_hash_addr(wots_addr, 0); - - /* Generate sk element. */ - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_prf_addr(sk, sk_seed, wots_addr, state_seeded); -} - -/** - * 8-way parallel version of wots_gen_sk; expects 8x as much space in sk - */ -static void wots_gen_skx8(unsigned char *skx8, const unsigned char *sk_seed, - uint32_t wots_addrx8[8 * 8]) { - unsigned int j; - - /* Make sure that the hash address is actually zeroed. */ - for (j = 0; j < 8; j++) { - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_set_hash_addr(wots_addrx8 + j * 8, 0); - } - - /* Generate sk element. */ - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_prf_addrx8(skx8 + 0 * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N, - skx8 + 1 * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N, - skx8 + 2 * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N, - skx8 + 3 * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N, - skx8 + 4 * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N, - skx8 + 5 * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N, - skx8 + 6 * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N, - skx8 + 7 * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N, - sk_seed, wots_addrx8); -} - -/** - * Computes the chaining function. - * out and in have to be n-byte arrays. - * - * Interprets in as start-th value of the chain. - * addr has to contain the address of the chain. - */ -static void gen_chain(unsigned char *out, const unsigned char *in, - unsigned int start, unsigned int steps, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *state_seeded) { - uint32_t i; - - /* Initialize out with the value at position 'start'. */ - memcpy(out, in, PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N); - - /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_WOTS_W; i++) { - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_set_hash_addr(addr, i); - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_thash_1(out, out, pub_seed, addr, state_seeded); - } -} - -/** - * 8-way parallel version of gen_chain; expects 8x as much space in out, and - * 8x as much space in inx8. Assumes start and step identical across chains. - */ -static void gen_chainx8(unsigned char *outx8, const unsigned char *inx8, - unsigned int start, unsigned int steps, - const unsigned char *pub_seed, uint32_t addrx8[8 * 8], - const hash_state *state_seeded) { - uint32_t i; - unsigned int j; - - /* Initialize outx8 with the value at position 'start'. */ - memcpy(outx8, inx8, 8 * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N); - - /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_WOTS_W; i++) { - for (j = 0; j < 8; j++) { - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_set_hash_addr(addrx8 + j * 8, i); - } - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_thashx8_1(outx8 + 0 * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N, - outx8 + 1 * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N, - outx8 + 2 * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N, - outx8 + 3 * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N, - outx8 + 4 * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N, - outx8 + 5 * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N, - outx8 + 6 * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N, - outx8 + 7 * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N, - outx8 + 0 * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N, - outx8 + 1 * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N, - outx8 + 2 * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N, - outx8 + 3 * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N, - outx8 + 4 * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N, - outx8 + 5 * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N, - outx8 + 6 * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N, - outx8 + 7 * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N, - pub_seed, addrx8, state_seeded); - } -} - -/** - * base_w algorithm as described in draft. - * Interprets an array of bytes as integers in base w. - * This only works when log_w is a divisor of 8. - */ -static void base_w(unsigned int *output, const int out_len, const unsigned char *input) { - int in = 0; - int out = 0; - unsigned char total = 0; - int bits = 0; - int consumed; - - for (consumed = 0; consumed < out_len; consumed++) { - if (bits == 0) { - total = input[in]; - in++; - bits += 8; - } - bits -= PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_WOTS_LOGW; - output[out] = (unsigned int)(total >> bits) & (PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_WOTS_W - 1); - out++; - } -} - -/* Computes the WOTS+ checksum over a message (in base_w). */ -static void wots_checksum(unsigned int *csum_base_w, const unsigned int *msg_base_w) { - unsigned int csum = 0; - unsigned char csum_bytes[(PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_WOTS_LEN2 * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_WOTS_LOGW + 7) / 8]; - unsigned int i; - - /* Compute checksum. */ - for (i = 0; i < PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_WOTS_LEN1; i++) { - csum += PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_WOTS_W - 1 - msg_base_w[i]; - } - - /* Convert checksum to base_w. */ - /* Make sure expected empty zero bits are the least significant bits. */ - csum = csum << (8 - ((PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_WOTS_LEN2 * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_WOTS_LOGW) % 8)); - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); - base_w(csum_base_w, PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_WOTS_LEN2, csum_bytes); -} - -/* Takes a message and derives the matching chain lengths. */ -static void chain_lengths(unsigned int *lengths, const unsigned char *msg) { - base_w(lengths, PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_WOTS_LEN1, msg); - wots_checksum(lengths + PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_WOTS_LEN1, lengths); -} - -/** - * WOTS key generation. Takes a 32 byte sk_seed, expands it to WOTS private key - * elements and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_wots_gen_pk(unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *state_seeded) { - uint32_t i; - unsigned int j; - - uint32_t addrx8[8 * 8]; - unsigned char pkbuf[8 * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N]; - - for (j = 0; j < 8; j++) { - memcpy(addrx8 + j * 8, addr, sizeof(uint32_t) * 8); - } - - /* The last iteration typically does not have complete set of 4 chains, - but because we use pkbuf, this is not an issue -- we still do as many - in parallel as possible. */ - for (i = 0; i < ((PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_WOTS_LEN + 7) & ~0x7); i += 8) { - for (j = 0; j < 8; j++) { - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_set_chain_addr(addrx8 + j * 8, i + j); - } - wots_gen_skx8(pkbuf, sk_seed, addrx8); - gen_chainx8(pkbuf, pkbuf, 0, PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_WOTS_W - 1, pub_seed, addrx8, state_seeded); - for (j = 0; j < 8; j++) { - if (i + j < PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_WOTS_LEN) { - memcpy(pk + (i + j)*PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N, pkbuf + j * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N, PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N); - } - } - } -} - -/** - * Takes a n-byte message and the 32-byte sk_see to compute a signature 'sig'. - */ -void PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_wots_sign(unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_WOTS_LEN; i++) { - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_set_chain_addr(addr, i); - wots_gen_sk(sig + i * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N, sk_seed, addr, state_seeded); - gen_chain(sig + i * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N, sig + i * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N, 0, lengths[i], pub_seed, addr, state_seeded); - } -} - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_WOTS_LEN; i++) { - PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_set_chain_addr(addr, i); - gen_chain(pk + i * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N, sig + i * PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_N, - lengths[i], PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_WOTS_W - 1 - lengths[i], pub_seed, addr, state_seeded); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_avx2/wots.h b/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_avx2/wots.h deleted file mode 100644 index d6e440ba62..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_avx2/wots.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_WOTS_H -#define PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_WOTS_H - -#include "hash_state.h" -#include "params.h" -#include - -/** - * WOTS key generation. Takes a 32 byte seed for the private key, expands it to - * a full WOTS private key and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_wots_gen_pk( - unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -/** - * Takes a n-byte message and the 32-byte seed for the private key to compute a - * signature that is placed at 'sig'. - */ -void PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_wots_sign( - unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *hash_state_seeded); - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHA256256FROBUST_AVX2_wots_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_clean/LICENSE b/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_clean/LICENSE deleted file mode 100644 index 670154e353..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_clean/LICENSE +++ /dev/null @@ -1,116 +0,0 @@ -CC0 1.0 Universal - -Statement of Purpose - -The laws of most jurisdictions throughout the world automatically confer -exclusive Copyright and Related Rights (defined below) upon the creator and -subsequent owner(s) (each and all, an "owner") of an original work of -authorship and/or a database (each, a "Work"). - -Certain owners wish to permanently relinquish those rights to a Work for the -purpose of contributing to a commons of creative, cultural and scientific -works ("Commons") that the public can reliably and without fear of later -claims of infringement build upon, modify, incorporate in other works, reuse -and redistribute as freely as possible in any form whatsoever and for any -purposes, including without limitation commercial purposes. These owners may -contribute to the Commons to promote the ideal of a free culture and the -further production of creative, cultural and scientific works, or to gain -reputation or greater distribution for their Work in part through the use and -efforts of others. - -For these and/or other purposes and motivations, and without any expectation -of additional consideration or compensation, the person associating CC0 with a -Work (the "Affirmer"), to the extent that he or she is an owner of Copyright -and Related Rights in the Work, voluntarily elects to apply CC0 to the Work -and publicly distribute the Work under its terms, with knowledge of his or her -Copyright and Related Rights in the Work and the meaning and intended legal -effect of CC0 on those rights. - -1. Copyright and Related Rights. A Work made available under CC0 may be -protected by copyright and related or neighboring rights ("Copyright and -Related Rights"). Copyright and Related Rights include, but are not limited -to, the following: - - i. the right to reproduce, adapt, distribute, perform, display, communicate, - and translate a Work; - - ii. moral rights retained by the original author(s) and/or performer(s); - - iii. publicity and privacy rights pertaining to a person's image or likeness - depicted in a Work; - - iv. rights protecting against unfair competition in regards to a Work, - subject to the limitations in paragraph 4(a), below; - - v. rights protecting the extraction, dissemination, use and reuse of data in - a Work; - - vi. database rights (such as those arising under Directive 96/9/EC of the - European Parliament and of the Council of 11 March 1996 on the legal - protection of databases, and under any national implementation thereof, - including any amended or successor version of such directive); and - - vii. other similar, equivalent or corresponding rights throughout the world - based on applicable law or treaty, and any national implementations thereof. - -2. Waiver. To the greatest extent permitted by, but not in contravention of, -applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and -unconditionally waives, abandons, and surrenders all of Affirmer's Copyright -and Related Rights and associated claims and causes of action, whether now -known or unknown (including existing as well as future claims and causes of -action), in the Work (i) in all territories worldwide, (ii) for the maximum -duration provided by applicable law or treaty (including future time -extensions), (iii) in any current or future medium and for any number of -copies, and (iv) for any purpose whatsoever, including without limitation -commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes -the Waiver for the benefit of each member of the public at large and to the -detriment of Affirmer's heirs and successors, fully intending that such Waiver -shall not be subject to revocation, rescission, cancellation, termination, or -any other legal or equitable action to disrupt the quiet enjoyment of the Work -by the public as contemplated by Affirmer's express Statement of Purpose. - -3. Public License Fallback. Should any part of the Waiver for any reason be -judged legally invalid or ineffective under applicable law, then the Waiver -shall be preserved to the maximum extent permitted taking into account -Affirmer's express Statement of Purpose. In addition, to the extent the Waiver -is so judged Affirmer hereby grants to each affected person a royalty-free, -non transferable, non sublicensable, non exclusive, irrevocable and -unconditional license to exercise Affirmer's Copyright and Related Rights in -the Work (i) in all territories worldwide, (ii) for the maximum duration -provided by applicable law or treaty (including future time extensions), (iii) -in any current or future medium and for any number of copies, and (iv) for any -purpose whatsoever, including without limitation commercial, advertising or -promotional purposes (the "License"). The License shall be deemed effective as -of the date CC0 was applied by Affirmer to the Work. Should any part of the -License for any reason be judged legally invalid or ineffective under -applicable law, such partial invalidity or ineffectiveness shall not -invalidate the remainder of the License, and in such case Affirmer hereby -affirms that he or she will not (i) exercise any of his or her remaining -Copyright and Related Rights in the Work or (ii) assert any associated claims -and causes of action with respect to the Work, in either case contrary to -Affirmer's express Statement of Purpose. - -4. Limitations and Disclaimers. - - a. No trademark or patent rights held by Affirmer are waived, abandoned, - surrendered, licensed or otherwise affected by this document. - - b. Affirmer offers the Work as-is and makes no representations or warranties - of any kind concerning the Work, express, implied, statutory or otherwise, - including without limitation warranties of title, merchantability, fitness - for a particular purpose, non infringement, or the absence of latent or - other defects, accuracy, or the present or absence of errors, whether or not - discoverable, all to the greatest extent permissible under applicable law. - - c. Affirmer disclaims responsibility for clearing rights of other persons - that may apply to the Work or any use thereof, including without limitation - any person's Copyright and Related Rights in the Work. Further, Affirmer - disclaims responsibility for obtaining any necessary consents, permissions - or other rights required for any use of the Work. - - d. Affirmer understands and acknowledges that Creative Commons is not a - party to this document and has no duty or obligation with respect to this - CC0 or use of the Work. - -For more information, please see - diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_clean/address.c b/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_clean/address.c deleted file mode 100644 index 8bae3cf378..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_clean/address.c +++ /dev/null @@ -1,78 +0,0 @@ -#include - -#include "address.h" -#include "params.h" -#include "utils.h" - -void PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]) { - int i; - - for (i = 0; i < 8; i++) { - PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_ull_to_bytes( - bytes + i * 4, 4, addr[i]); - } -} - -void PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_set_layer_addr( - uint32_t addr[8], uint32_t layer) { - addr[0] = layer; -} - -void PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_set_tree_addr( - uint32_t addr[8], uint64_t tree) { - addr[1] = 0; - addr[2] = (uint32_t) (tree >> 32); - addr[3] = (uint32_t) tree; -} - -void PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_set_type( - uint32_t addr[8], uint32_t type) { - addr[4] = type; -} - -void PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; -} - -/* These functions are used for OTS addresses. */ - -void PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_set_keypair_addr( - uint32_t addr[8], uint32_t keypair) { - addr[5] = keypair; -} - -void PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; - out[5] = in[5]; -} - -void PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_set_chain_addr( - uint32_t addr[8], uint32_t chain) { - addr[6] = chain; -} - -void PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_set_hash_addr( - uint32_t addr[8], uint32_t hash) { - addr[7] = hash; -} - -/* These functions are used for all hash tree addresses (including FORS). */ - -void PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_set_tree_height( - uint32_t addr[8], uint32_t tree_height) { - addr[6] = tree_height; -} - -void PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_set_tree_index( - uint32_t addr[8], uint32_t tree_index) { - addr[7] = tree_index; -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_clean/address.h b/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_clean/address.h deleted file mode 100644 index 7add74b4e5..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_clean/address.h +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_ADDRESS_H -#define PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_ADDRESS_H - -#include - -#define PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_ADDR_TYPE_WOTS 0 -#define PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_ADDR_TYPE_WOTSPK 1 -#define PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_ADDR_TYPE_HASHTREE 2 -#define PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_ADDR_TYPE_FORSTREE 3 -#define PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_ADDR_TYPE_FORSPK 4 - -void PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]); - -void PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_set_layer_addr( - uint32_t addr[8], uint32_t layer); - -void PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_set_tree_addr( - uint32_t addr[8], uint64_t tree); - -void PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_set_type( - uint32_t addr[8], uint32_t type); - -/* Copies the layer and tree part of one address into the other */ -void PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for WOTS and FORS addresses. */ - -void PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_set_keypair_addr( - uint32_t addr[8], uint32_t keypair); - -void PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_set_chain_addr( - uint32_t addr[8], uint32_t chain); - -void PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_set_hash_addr( - uint32_t addr[8], uint32_t hash); - -void PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for all hash tree addresses (including FORS). */ - -void PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_set_tree_height( - uint32_t addr[8], uint32_t tree_height); - -void PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_set_tree_index( - uint32_t addr[8], uint32_t tree_index); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_clean/api.h b/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_clean/api.h deleted file mode 100644 index be2b9e7bf3..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_clean/api.h +++ /dev/null @@ -1,81 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_API_H -#define PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_API_H - -#include -#include - - - -#define PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_CRYPTO_ALGNAME "SPHINCS+" - -#define PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_CRYPTO_SECRETKEYBYTES 128 -#define PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_CRYPTO_PUBLICKEYBYTES 64 -#define PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_CRYPTO_BYTES 49856 -#define PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_CRYPTO_SEEDBYTES 96 - - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_clean/fors.c b/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_clean/fors.c deleted file mode 100644 index 4852f81e89..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_clean/fors.c +++ /dev/null @@ -1,161 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "fors.h" -#include "hash.h" -#include "hash_state.h" -#include "thash.h" -#include "utils.h" - -static void fors_gen_sk(unsigned char *sk, const unsigned char *sk_seed, - uint32_t fors_leaf_addr[8], const hash_state *hash_state_seeded) { - PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_prf_addr( - sk, sk_seed, fors_leaf_addr, hash_state_seeded); -} - -static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, - const unsigned char *pub_seed, - uint32_t fors_leaf_addr[8], - const hash_state *hash_state_seeded) { - PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_thash_1( - leaf, sk, pub_seed, fors_leaf_addr, hash_state_seeded); -} - -static void fors_gen_leaf(unsigned char *leaf, const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx, const uint32_t fors_tree_addr[8], - const hash_state *hash_state_seeded) { - uint32_t fors_leaf_addr[8] = {0}; - - /* Only copy the parts that must be kept in fors_leaf_addr. */ - PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_copy_keypair_addr( - fors_leaf_addr, fors_tree_addr); - PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_set_type( - fors_leaf_addr, PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_set_tree_index( - fors_leaf_addr, addr_idx); - - fors_gen_sk(leaf, sk_seed, fors_leaf_addr, hash_state_seeded); - fors_sk_to_leaf(leaf, leaf, pub_seed, fors_leaf_addr, hash_state_seeded); -} - -/** - * Interprets m as PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_FORS_HEIGHT-bit unsigned integers. - * Assumes m contains at least PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_FORS_TREES bits. - * Assumes indices has space for PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_FORS_TREES integers. - */ -static void message_to_indices(uint32_t *indices, const unsigned char *m) { - unsigned int i, j; - unsigned int offset = 0; - - for (i = 0; i < PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_FORS_TREES; i++) { - indices[i] = 0; - for (j = 0; j < PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_FORS_HEIGHT; j++) { - indices[i] ^= (((uint32_t)m[offset >> 3] >> (offset & 0x7)) & 0x1) << j; - offset++; - } - } -} - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_fors_sign( - unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *hash_state_seeded) { - uint32_t indices[PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_FORS_TREES]; - unsigned char roots[PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_FORS_TREES * PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_N]; - uint32_t fors_tree_addr[8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_copy_keypair_addr( - fors_tree_addr, fors_addr); - PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_copy_keypair_addr( - fors_pk_addr, fors_addr); - - PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_set_type( - fors_tree_addr, PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_set_type( - fors_pk_addr, PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_FORS_TREES; i++) { - idx_offset = i * (1 << PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_FORS_HEIGHT); - - PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_set_tree_height( - fors_tree_addr, 0); - PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_set_tree_index( - fors_tree_addr, indices[i] + idx_offset); - - /* Include the secret key part that produces the selected leaf node. */ - fors_gen_sk(sig, sk_seed, fors_tree_addr, hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_N; - - /* Compute the authentication path for this leaf node. */ - PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_treehash_FORS_HEIGHT( - roots + i * PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_N, sig, sk_seed, pub_seed, - indices[i], idx_offset, fors_gen_leaf, fors_tree_addr, - hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_N * PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_thash_FORS_TREES( - pk, roots, pub_seed, fors_pk_addr, hash_state_seeded); -} - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_fors_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, const uint32_t fors_addr[8], - const hash_state *hash_state_seeded) { - uint32_t indices[PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_FORS_TREES]; - unsigned char roots[PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_FORS_TREES * PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_N]; - unsigned char leaf[PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_N]; - uint32_t fors_tree_addr[8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_copy_keypair_addr(fors_tree_addr, fors_addr); - PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_copy_keypair_addr(fors_pk_addr, fors_addr); - - PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_set_type(fors_tree_addr, PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_set_type(fors_pk_addr, PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_FORS_TREES; i++) { - idx_offset = i * (1 << PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_FORS_HEIGHT); - - PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_set_tree_height(fors_tree_addr, 0); - PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Derive the leaf from the included secret key part. */ - fors_sk_to_leaf(leaf, sig, pub_seed, fors_tree_addr, hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_N; - - /* Derive the corresponding root node of this tree. */ - PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_compute_root(roots + i * PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_N, leaf, indices[i], idx_offset, sig, - PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_FORS_HEIGHT, pub_seed, fors_tree_addr, hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_N * PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_thash_FORS_TREES(pk, roots, pub_seed, fors_pk_addr, hash_state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_clean/fors.h b/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_clean/fors.h deleted file mode 100644 index a096516258..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_clean/fors.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_FORS_H -#define PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_FORS_H - -#include - -#include "hash_state.h" -#include "params.h" - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_fors_sign( - unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *hash_state_seeded); - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_fors_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, const uint32_t fors_addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_clean/hash.h b/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_clean/hash.h deleted file mode 100644 index daaf116c26..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_clean/hash.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_HASH_H -#define PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_HASH_H - -#include "hash_state.h" - -#include -#include - -void PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_initialize_hash_function( - hash_state *hash_state_seeded, - const unsigned char *pub_seed, const unsigned char *sk_seed); - -void PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_destroy_hash_function(hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_clean/hash_sha256.c b/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_clean/hash_sha256.c deleted file mode 100644 index ccd819765f..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_clean/hash_sha256.c +++ /dev/null @@ -1,162 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "utils.h" - -#include "sha2.h" -#include "sha256.h" - -/* For SHA256, there is no immediate reason to initialize at the start, - so this function is an empty operation. */ -void PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_initialize_hash_function( - hash_state *hash_state_seeded, - const unsigned char *pub_seed, const unsigned char *sk_seed) { - PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_seed_state(hash_state_seeded, pub_seed); - (void)sk_seed; /* Suppress an 'unused parameter' warning. */ -} - -/* Clean up hash state */ -void PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_destroy_hash_function(hash_state *hash_state_seeded) { - sha256_inc_ctx_release(hash_state_seeded); -} - -/* - * Computes PRF(key, addr), given a secret key of PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_N bytes and an address - */ -void PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded) { - unsigned char buf[PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_N + PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_SHA256_ADDR_BYTES]; - unsigned char outbuf[PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_SHA256_OUTPUT_BYTES]; - - memcpy(buf, key, PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_N); - PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_compress_address(buf + PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_N, addr); - - sha256(outbuf, buf, PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_N + PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_SHA256_ADDR_BYTES); - memcpy(out, outbuf, PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_N); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} - -/** - * Computes the message-dependent randomness R, using a secret seed as a key - * for HMAC, and an optional randomization value prefixed to the message. - * This requires m to have at least PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_SHA256_BLOCK_BYTES + PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_N space - * available in front of the pointer, i.e. before the message to use for the - * prefix. This is necessary to prevent having to move the message around (and - * allocate memory for it). - */ -void PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, const hash_state *hash_state_seeded) { - unsigned char buf[PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_SHA256_BLOCK_BYTES + PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_SHA256_OUTPUT_BYTES]; - sha256ctx state; - int i; - - /* This implements HMAC-SHA256 */ - for (i = 0; i < PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_N; i++) { - buf[i] = 0x36 ^ sk_prf[i]; - } - memset(buf + PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_N, 0x36, PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_N); - - sha256_inc_init(&state); - sha256_inc_blocks(&state, buf, 1); - - memcpy(buf, optrand, PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_N); - - /* If optrand + message cannot fill up an entire block */ - if (PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_N + mlen < PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_SHA256_BLOCK_BYTES) { - memcpy(buf + PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_N, m, mlen); - sha256_inc_finalize(buf + PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_SHA256_BLOCK_BYTES, &state, - buf, mlen + PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_N); - } - /* Otherwise first fill a block, so that finalize only uses the message */ - else { - memcpy(buf + PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_N, m, PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_N); - sha256_inc_blocks(&state, buf, 1); - - m += PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_N; - mlen -= PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_N; - sha256_inc_finalize(buf + PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_SHA256_BLOCK_BYTES, &state, m, mlen); - } - - for (i = 0; i < PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_N; i++) { - buf[i] = 0x5c ^ sk_prf[i]; - } - memset(buf + PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_N, 0x5c, PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_N); - - sha256(buf, buf, PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_SHA256_BLOCK_BYTES + PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_SHA256_OUTPUT_BYTES); - memcpy(R, buf, PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_N); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} - -/** - * Computes the message hash using R, the public key, and the message. - * Outputs the message digest and the index of the leaf. The index is split in - * the tree index and the leaf index, for convenient copying to an address. - */ -void PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded) { -#define PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_TREE_BITS (PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_TREE_HEIGHT * (PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_D - 1)) -#define PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_TREE_BYTES ((PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_TREE_BITS + 7) / 8) -#define PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_LEAF_BITS PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_TREE_HEIGHT -#define PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_LEAF_BYTES ((PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_LEAF_BITS + 7) / 8) -#define PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_DGST_BYTES (PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_FORS_MSG_BYTES + PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_TREE_BYTES + PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_LEAF_BYTES) - - unsigned char seed[PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_SHA256_OUTPUT_BYTES + 4]; - - /* Round to nearest multiple of PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_SHA256_BLOCK_BYTES */ -#define PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_INBLOCKS (((PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_N + PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_PK_BYTES + PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_SHA256_BLOCK_BYTES - 1) & \ - -PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_SHA256_BLOCK_BYTES) / PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_SHA256_BLOCK_BYTES) - unsigned char inbuf[PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_INBLOCKS * PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_SHA256_BLOCK_BYTES]; - - unsigned char buf[PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_DGST_BYTES]; - unsigned char *bufp = buf; - sha256ctx state; - - sha256_inc_init(&state); - - memcpy(inbuf, R, PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_N); - memcpy(inbuf + PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_N, pk, PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_PK_BYTES); - - /* If R + pk + message cannot fill up an entire block */ - if (PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_N + PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_PK_BYTES + mlen < PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_INBLOCKS * PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_SHA256_BLOCK_BYTES) { - memcpy(inbuf + PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_N + PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_PK_BYTES, m, mlen); - sha256_inc_finalize(seed, &state, inbuf, PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_N + PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_PK_BYTES + mlen); - } - /* Otherwise first fill a block, so that finalize only uses the message */ - else { - memcpy(inbuf + PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_N + PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_PK_BYTES, m, - PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_INBLOCKS * PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_N - PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_PK_BYTES); - sha256_inc_blocks(&state, inbuf, PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_INBLOCKS); - - m += PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_INBLOCKS * PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_N - PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_PK_BYTES; - mlen -= PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_INBLOCKS * PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_N - PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_PK_BYTES; - sha256_inc_finalize(seed, &state, m, mlen); - } - - /* By doing this in two steps, we prevent hashing the message twice; - otherwise each iteration in MGF1 would hash the message again. */ - PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_mgf1(bufp, PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_DGST_BYTES, seed, PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_SHA256_OUTPUT_BYTES); - - memcpy(digest, bufp, PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_FORS_MSG_BYTES); - bufp += PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_FORS_MSG_BYTES; - - *tree = PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_bytes_to_ull(bufp, PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_TREE_BYTES); - *tree &= (~(uint64_t)0) >> (64 - PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_TREE_BITS); - bufp += PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_TREE_BYTES; - - *leaf_idx = (uint32_t)PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_bytes_to_ull( - bufp, PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_LEAF_BYTES); - *leaf_idx &= (~(uint32_t)0) >> (32 - PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_LEAF_BITS); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_clean/hash_state.h b/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_clean/hash_state.h deleted file mode 100644 index 19fc335e27..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_clean/hash_state.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef SPX_HASH_STATE_H -#define SPX_HASH_STATE_H - -/** - * Defines the type of the hash function state. - * - * Don't be fooled into thinking this instance of SPHINCS+ isn't stateless! - * - * From Section 7.2.2 from the SPHINCS+ round-2 specification: - * - * Each of the instances of the tweakable hash function take PK.seed as its - * first input, which is constant for a given key pair – and, thus, across - * a single signature. This leads to a lot of redundant computation. To remedy - * this, we pad PK.seed to the length of a full 64-byte SHA-256 input block. - * Because of the Merkle-Damgård construction that underlies SHA-256, this - * allows for reuse of the intermediate SHA-256 state after the initial call to - * the compression function which improves performance. - * - * We pass this hash state around in functions, because otherwise we need to - * have a global variable. - */ - -#include "sha2.h" -#define hash_state sha256ctx - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_clean/params.h b/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_clean/params.h deleted file mode 100644 index eed5f2d295..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_clean/params.h +++ /dev/null @@ -1,53 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_PARAMS_H -#define PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_PARAMS_H - -/* Hash output length in bytes. */ -#define PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_N 32 -/* Height of the hypertree. */ -#define PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_FULL_HEIGHT 68 -/* Number of subtree layer. */ -#define PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_D 17 -/* FORS tree dimensions. */ -#define PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_FORS_HEIGHT 9 -#define PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_FORS_TREES 35 -/* Winternitz parameter, */ -#define PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_WOTS_W 16 - -/* The hash function is defined by linking a different hash.c file, as opposed - to setting a #define constant. */ - -/* For clarity */ -#define PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_ADDR_BYTES 32 - -/* WOTS parameters. */ -#define PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_WOTS_LOGW 4 - -#define PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_WOTS_LEN1 (8 * PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_N / PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_WOTS_LOGW) - -/* PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#define PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_WOTS_LEN2 3 - -#define PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_WOTS_LEN (PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_WOTS_LEN1 + PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_WOTS_LEN2) -#define PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_WOTS_BYTES (PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_WOTS_LEN * PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_N) -#define PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_WOTS_PK_BYTES PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_WOTS_BYTES - -/* Subtree size. */ -#define PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_TREE_HEIGHT (PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_FULL_HEIGHT / PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_D) - -/* FORS parameters. */ -#define PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_FORS_MSG_BYTES ((PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_FORS_TREES + 7) / 8) -#define PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_FORS_BYTES ((PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_FORS_HEIGHT + 1) * PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_FORS_TREES * PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_N) -#define PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_FORS_PK_BYTES PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_N - -/* Resulting SPX sizes. */ -#define PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_BYTES (PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_N + PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_FORS_BYTES + PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_D * PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_WOTS_BYTES +\ - PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_FULL_HEIGHT * PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_N) -#define PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_PK_BYTES (2 * PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_N) -#define PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_SK_BYTES (2 * PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_N + PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_PK_BYTES) - -/* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ -#define PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_OPTRAND_BYTES 32 - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_clean/sha256.c b/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_clean/sha256.c deleted file mode 100644 index 922283746c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_clean/sha256.c +++ /dev/null @@ -1,71 +0,0 @@ -/* Based on the public domain implementation in - * crypto_hash/sha512/ref/ from http://bench.cr.yp.to/supercop.html - * by D. J. Bernstein */ - -#include -#include -#include - -#include "sha2.h" -#include "sha256.h" -#include "utils.h" - -/* - * Compresses an address to a 22-byte sequence. - * This reduces the number of required SHA256 compression calls, as the last - * block of input is padded with at least 65 bits. - */ -void PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_compress_address(unsigned char *out, const uint32_t addr[8]) { - PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_ull_to_bytes(out, 1, addr[0]); /* drop 3 bytes of the layer field */ - PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_ull_to_bytes(out + 1, 4, addr[2]); /* drop the highest tree address word */ - PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_ull_to_bytes(out + 5, 4, addr[3]); - PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_ull_to_bytes(out + 9, 1, addr[4]); /* drop 3 bytes of the type field */ - PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_ull_to_bytes(out + 10, 4, addr[5]); - PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_ull_to_bytes(out + 14, 4, addr[6]); - PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_ull_to_bytes(out + 18, 4, addr[7]); -} - -/** - * Requires 'input_plus_four_bytes' to have 'inlen' + 4 bytes, so that the last - * four bytes can be used for the counter. Typically 'input' is merely a seed. - * Outputs outlen number of bytes - */ -void PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_mgf1( - unsigned char *out, unsigned long outlen, - unsigned char *input_plus_four_bytes, unsigned long inlen) { - unsigned char outbuf[PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_SHA256_OUTPUT_BYTES]; - unsigned long i; - - /* While we can fit in at least another full block of SHA256 output.. */ - for (i = 0; (i + 1)*PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_SHA256_OUTPUT_BYTES <= outlen; i++) { - PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_ull_to_bytes(input_plus_four_bytes + inlen, 4, i); - sha256(out, input_plus_four_bytes, inlen + 4); - out += PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_SHA256_OUTPUT_BYTES; - } - /* Until we cannot anymore, and we fill the remainder. */ - if (outlen > i * PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_SHA256_OUTPUT_BYTES) { - PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_ull_to_bytes(input_plus_four_bytes + inlen, 4, i); - sha256(outbuf, input_plus_four_bytes, inlen + 4); - memcpy(out, outbuf, outlen - i * PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_SHA256_OUTPUT_BYTES); - } -} - - -/** - * Absorb the constant pub_seed using one round of the compression function - * This initializes hash_state_seeded, which can then be reused in thash - **/ -void PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_seed_state(sha256ctx *hash_state_seeded, const unsigned char *pub_seed) { - uint8_t block[PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_SHA256_BLOCK_BYTES]; - size_t i; - - for (i = 0; i < PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_N; ++i) { - block[i] = pub_seed[i]; - } - for (i = PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_N; i < PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_SHA256_BLOCK_BYTES; ++i) { - block[i] = 0; - } - - sha256_inc_init(hash_state_seeded); - sha256_inc_blocks(hash_state_seeded, block, 1); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_clean/sha256.h b/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_clean/sha256.h deleted file mode 100644 index 52234c2962..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_clean/sha256.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_SHA256_H -#define PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_SHA256_H - -#define PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_SHA256_BLOCK_BYTES 64 -#define PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_SHA256_OUTPUT_BYTES 32 /* This does not necessarily equal PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_N */ -#define PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_SHA256_ADDR_BYTES 22 - -#include -#include - -#include "sha2.h" - -void PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_compress_address(unsigned char *out, const uint32_t addr[8]); - -void PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_mgf1( - unsigned char *out, unsigned long outlen, - unsigned char *input_plus_four_bytes, unsigned long inlen); - -void PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_seed_state(sha256ctx *hash_state_seeded, const unsigned char *pub_seed); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_clean/sign.c b/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_clean/sign.c deleted file mode 100644 index a419565f79..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_clean/sign.c +++ /dev/null @@ -1,356 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "api.h" -#include "fors.h" -#include "hash.h" -#include "hash_state.h" -#include "params.h" -#include "randombytes.h" -#include "thash.h" -#include "utils.h" -#include "wots.h" - -/** - * Computes the leaf at a given address. First generates the WOTS key pair, - * then computes leaf by hashing horizontally. - */ -static void wots_gen_leaf(unsigned char *leaf, const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx, const uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - unsigned char pk[PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_WOTS_BYTES]; - uint32_t wots_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_set_type( - wots_addr, PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_set_type( - wots_pk_addr, PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_ADDR_TYPE_WOTSPK); - - PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_set_keypair_addr( - wots_addr, addr_idx); - PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_wots_gen_pk( - pk, sk_seed, pub_seed, wots_addr, hash_state_seeded); - - PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_copy_keypair_addr( - wots_pk_addr, wots_addr); - PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_thash_WOTS_LEN( - leaf, pk, pub_seed, wots_pk_addr, hash_state_seeded); -} - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_crypto_sign_secretkeybytes(void) { - return PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_CRYPTO_SECRETKEYBYTES; -} - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_crypto_sign_publickeybytes(void) { - return PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_CRYPTO_PUBLICKEYBYTES; -} - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_crypto_sign_bytes(void) { - return PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_CRYPTO_BYTES; -} - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_crypto_sign_seedbytes(void) { - return PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_CRYPTO_SEEDBYTES; -} - -/* - * Generates an SPX key pair given a seed of length - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed) { - /* We do not need the auth path in key generation, but it simplifies the - code to have just one treehash routine that computes both root and path - in one function. */ - unsigned char auth_path[PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_TREE_HEIGHT * PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_N]; - uint32_t top_tree_addr[8] = {0}; - hash_state hash_state_seeded; - - PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_set_layer_addr( - top_tree_addr, PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_D - 1); - PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_set_type( - top_tree_addr, PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_ADDR_TYPE_HASHTREE); - - /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ - memcpy(sk, seed, PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_CRYPTO_SEEDBYTES); - - memcpy(pk, sk + 2 * PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_N, PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_initialize_hash_function(&hash_state_seeded, pk, sk); - - /* Compute root node of the top-most subtree. */ - PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_treehash_TREE_HEIGHT( - sk + 3 * PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_N, auth_path, sk, sk + 2 * PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_N, 0, 0, - wots_gen_leaf, top_tree_addr, &hash_state_seeded); - - memcpy(pk + PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_N, sk + 3 * PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_N, PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_N); - - PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_destroy_hash_function(&hash_state_seeded); - return 0; -} - -/* - * Generates an SPX key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk) { - unsigned char seed[PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_CRYPTO_SEEDBYTES]; - randombytes(seed, PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_CRYPTO_SEEDBYTES); - PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_crypto_sign_seed_keypair( - pk, sk, seed); - - return 0; -} - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - const unsigned char *sk_seed = sk; - const unsigned char *sk_prf = sk + PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_N; - const unsigned char *pk = sk + 2 * PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_N; - const unsigned char *pub_seed = pk; - - unsigned char optrand[PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_N]; - unsigned char mhash[PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_FORS_MSG_BYTES]; - unsigned char root[PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_N]; - uint32_t i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - - hash_state hash_state_seeded; - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_initialize_hash_function( - &hash_state_seeded, - pub_seed, sk_seed); - - PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_set_type( - wots_addr, PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_set_type( - tree_addr, PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_ADDR_TYPE_HASHTREE); - - /* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ - randombytes(optrand, PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_N); - /* Compute the digest randomization value. */ - PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_gen_message_random( - sig, sk_prf, optrand, m, mlen, &hash_state_seeded); - - /* Derive the message digest and leaf index from R, PK and M. */ - PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_N; - - PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); - - /* Sign the message hash using FORS. */ - PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_fors_sign( - sig, root, mhash, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_FORS_BYTES; - - for (i = 0; i < PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_D; i++) { - PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_set_tree_addr(tree_addr, tree); - - PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); - - /* Compute a WOTS signature. */ - PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_wots_sign( - sig, root, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_WOTS_BYTES; - - /* Compute the authentication path for the used WOTS leaf. */ - PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_treehash_TREE_HEIGHT( - root, sig, sk_seed, pub_seed, idx_leaf, 0, - wots_gen_leaf, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_TREE_HEIGHT * PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_TREE_HEIGHT; - } - - *siglen = PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_BYTES; - - PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_destroy_hash_function(&hash_state_seeded); - return 0; -} - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk) { - const unsigned char *pub_seed = pk; - const unsigned char *pub_root = pk + PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_N; - unsigned char mhash[PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_FORS_MSG_BYTES]; - unsigned char wots_pk[PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_WOTS_BYTES]; - unsigned char root[PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_N]; - unsigned char leaf[PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_N]; - unsigned int i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - hash_state hash_state_seeded; - - if (siglen != PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_BYTES) { - return -1; - } - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_initialize_hash_function( - &hash_state_seeded, - pub_seed, NULL); - - PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_set_type( - wots_addr, PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_set_type( - tree_addr, PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_ADDR_TYPE_HASHTREE); - PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_set_type( - wots_pk_addr, PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_ADDR_TYPE_WOTSPK); - - /* Derive the message digest and leaf index from R || PK || M. */ - /* The additional PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_N is a result of the hash domain separator. */ - PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_N; - - /* Layer correctly defaults to 0, so no need to set_layer_addr */ - PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); - - PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_fors_pk_from_sig( - root, sig, mhash, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_FORS_BYTES; - - /* For each subtree.. */ - for (i = 0; i < PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_D; i++) { - PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_set_tree_addr(tree_addr, tree); - - PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); - - PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_copy_keypair_addr( - wots_pk_addr, wots_addr); - - /* The WOTS public key is only correct if the signature was correct. */ - /* Initially, root is the FORS pk, but on subsequent iterations it is - the root of the subtree below the currently processed subtree. */ - PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_wots_pk_from_sig( - wots_pk, sig, root, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_WOTS_BYTES; - - /* Compute the leaf node using the WOTS public key. */ - PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_thash_WOTS_LEN( - leaf, wots_pk, pub_seed, wots_pk_addr, &hash_state_seeded); - - /* Compute the root node of this subtree. */ - PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_compute_root( - root, leaf, idx_leaf, 0, sig, PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_TREE_HEIGHT, - pub_seed, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_TREE_HEIGHT * PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_TREE_HEIGHT; - } - - PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_destroy_hash_function(&hash_state_seeded); - /* Check if the root node equals the root node in the public key. */ - if (memcmp(root, pub_root, PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_N) != 0) { - return -1; - } - - return 0; -} - - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - size_t siglen; - - PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_crypto_sign_signature( - sm, &siglen, m, mlen, sk); - - memmove(sm + PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_BYTES, m, mlen); - *smlen = siglen + mlen; - - return 0; -} - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk) { - /* The API caller does not necessarily know what size a signature should be - but SPHINCS+ signatures are always exactly PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_BYTES. */ - if (smlen < PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_BYTES) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - *mlen = smlen - PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_BYTES; - - if (PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_crypto_sign_verify( - sm, PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_BYTES, sm + PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_BYTES, *mlen, pk)) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - /* If verification was successful, move the message to the right place. */ - memmove(m, sm + PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_BYTES, *mlen); - - return 0; -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_clean/thash.h b/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_clean/thash.h deleted file mode 100644 index 561e6510b0..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_clean/thash.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_THASH_H -#define PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_THASH_H - -#include "hash_state.h" - -#include - -void PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_clean/thash_sha256_robust.c b/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_clean/thash_sha256_robust.c deleted file mode 100644 index 3e33b1ff1a..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_clean/thash_sha256_robust.c +++ /dev/null @@ -1,82 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "thash.h" - -#include "sha2.h" -#include "sha256.h" - -/** - * Takes an array of inblocks concatenated arrays of PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_N bytes. - */ -static void PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_thash( - unsigned char *out, unsigned char *buf, - const unsigned char *in, unsigned int inblocks, - const unsigned char *pub_seed, uint32_t addr[8], - const sha256ctx *hash_state_seeded) { - - unsigned char outbuf[PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_SHA256_OUTPUT_BYTES]; - unsigned char *bitmask = buf + PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_N + PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_SHA256_ADDR_BYTES + 4; - sha256ctx sha2_state; - unsigned int i; - - memcpy(buf, pub_seed, PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_N); - PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_compress_address(buf + PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_N, addr); - /* MGF1 requires us to have 4 extra bytes in 'buf' */ - PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_mgf1(bitmask, inblocks * PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_N, buf, PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_N + PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_SHA256_ADDR_BYTES); - - /* Retrieve precomputed state containing pub_seed */ - sha256_inc_ctx_clone(&sha2_state, hash_state_seeded); - - for (i = 0; i < inblocks * PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_N; i++) { - buf[PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_N + PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_SHA256_ADDR_BYTES + i] = in[i] ^ bitmask[i]; - } - - sha256_inc_finalize(outbuf, &sha2_state, buf + PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_N, - PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_N); - memcpy(out, outbuf, PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_N); -} - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const sha256ctx *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_N + PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_SHA256_ADDR_BYTES + 4 + 1 * PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_N]; - PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_thash( - out, buf, in, 1, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const sha256ctx *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_N + PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_SHA256_ADDR_BYTES + 4 + 2 * PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_N]; - PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_thash( - out, buf, in, 2, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const sha256ctx *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_N + PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_SHA256_ADDR_BYTES + 4 + PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_WOTS_LEN * PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_N]; - PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_thash( - out, buf, in, PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_WOTS_LEN, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const sha256ctx *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_N + PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_SHA256_ADDR_BYTES + 4 + PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_FORS_TREES * PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_N]; - PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_thash( - out, buf, in, PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_FORS_TREES, pub_seed, addr, hash_state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_clean/utils.c b/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_clean/utils.c deleted file mode 100644 index 28fff858be..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_clean/utils.c +++ /dev/null @@ -1,199 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "hash_state.h" -#include "params.h" -#include "thash.h" -#include "utils.h" - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in) { - - /* Iterate over out in decreasing order, for big-endianness. */ - for (size_t i = outlen; i > 0; i--) { - out[i - 1] = in & 0xff; - in = in >> 8; - } -} - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_bytes_to_ull( - const unsigned char *in, size_t inlen) { - unsigned long long retval = 0; - - for (size_t i = 0; i < inlen; i++) { - retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); - } - return retval; -} - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - uint32_t i; - unsigned char buffer[2 * PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_N]; - - /* If leaf_idx is odd (last bit = 1), current path element is a right child - and auth_path has to go left. Otherwise it is the other way around. */ - if (leaf_idx & 1) { - memcpy(buffer + PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_N, leaf, PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_N); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_N); - } else { - memcpy(buffer, leaf, PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_N); - memcpy(buffer + PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_N, auth_path, PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_N); - } - auth_path += PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_N; - - for (i = 0; i < tree_height - 1; i++) { - leaf_idx >>= 1; - idx_offset >>= 1; - /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_set_tree_height(addr, i + 1); - PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_set_tree_index( - addr, leaf_idx + idx_offset); - - /* Pick the right or left neighbor, depending on parity of the node. */ - if (leaf_idx & 1) { - PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_thash_2( - buffer + PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_N, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_N); - } else { - PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_thash_2( - buffer, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer + PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_N, auth_path, PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_N); - } - auth_path += PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_N; - } - - /* The last iteration is exceptional; we do not copy an auth_path node. */ - leaf_idx >>= 1; - idx_offset >>= 1; - PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_set_tree_height(addr, tree_height); - PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_set_tree_index( - addr, leaf_idx + idx_offset); - PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_thash_2( - root, buffer, pub_seed, addr, hash_state_seeded); -} - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -static void PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_treehash( - unsigned char *root, unsigned char *auth_path, - unsigned char *stack, unsigned int *heights, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - - unsigned int offset = 0; - uint32_t idx; - uint32_t tree_idx; - - for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { - /* Add the next leaf node to the stack. */ - gen_leaf(stack + offset * PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_N, - sk_seed, pub_seed, idx + idx_offset, tree_addr, - hash_state_seeded); - offset++; - heights[offset - 1] = 0; - - /* If this is a node we need for the auth path.. */ - if ((leaf_idx ^ 0x1) == idx) { - memcpy(auth_path, stack + (offset - 1)*PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_N, PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_N); - } - - /* While the top-most nodes are of equal height.. */ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { - /* Compute index of the new node, in the next layer. */ - tree_idx = (idx >> (heights[offset - 1] + 1)); - - /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_set_tree_height( - tree_addr, heights[offset - 1] + 1); - PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_set_tree_index( - tree_addr, tree_idx + (idx_offset >> (heights[offset - 1] + 1))); - /* Hash the top-most nodes from the stack together. */ - PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_thash_2( - stack + (offset - 2)*PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_N, stack + (offset - 2)*PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_N, - pub_seed, tree_addr, hash_state_seeded); - offset--; - /* Note that the top-most node is now one layer higher. */ - heights[offset - 1]++; - - /* If this is a node we need for the auth path.. */ - if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_path + heights[offset - 1]*PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_N, - stack + (offset - 1)*PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_N, PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_N); - } - } - } - memcpy(root, stack, PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_N); -} - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_FORS_HEIGHT + 1)*PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_N]; - unsigned int heights[PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_FORS_HEIGHT + 1]; - - PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_FORS_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_TREE_HEIGHT + 1)*PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_N]; - unsigned int heights[PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_TREE_HEIGHT + 1]; - - PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_TREE_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_clean/utils.h b/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_clean/utils.h deleted file mode 100644 index 3e2630188f..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_clean/utils.h +++ /dev/null @@ -1,64 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_UTILS_H -#define PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_UTILS_H - -#include "hash_state.h" -#include "params.h" -#include -#include - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in); - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_bytes_to_ull( - const unsigned char *in, size_t inlen); - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -void PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_clean/wots.c b/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_clean/wots.c deleted file mode 100644 index 3f0188e9e3..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_clean/wots.c +++ /dev/null @@ -1,167 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "hash_state.h" -#include "params.h" -#include "thash.h" -#include "utils.h" -#include "wots.h" - -// TODO clarify address expectations, and make them more uniform. -// TODO i.e. do we expect types to be set already? -// TODO and do we expect modifications or copies? - -/** - * Computes the starting value for a chain, i.e. the secret key. - * Expects the address to be complete up to the chain address. - */ -static void wots_gen_sk(unsigned char *sk, const unsigned char *sk_seed, - uint32_t wots_addr[8], - const hash_state *hash_state_seeded) { - /* Make sure that the hash address is actually zeroed. */ - PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_set_hash_addr(wots_addr, 0); - - /* Generate sk element. */ - PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_prf_addr(sk, sk_seed, wots_addr, hash_state_seeded); -} - -/** - * Computes the chaining function. - * out and in have to be n-byte arrays. - * - * Interprets in as start-th value of the chain. - * addr has to contain the address of the chain. - */ -static void gen_chain(unsigned char *out, const unsigned char *in, - unsigned int start, unsigned int steps, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - uint32_t i; - - /* Initialize out with the value at position 'start'. */ - memcpy(out, in, PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_N); - - /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_WOTS_W; i++) { - PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_set_hash_addr(addr, i); - PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_thash_1( - out, out, pub_seed, addr, hash_state_seeded); - } -} - -/** - * base_w algorithm as described in draft. - * Interprets an array of bytes as integers in base w. - * This only works when log_w is a divisor of 8. - */ -static void base_w(unsigned int *output, const size_t out_len, - const unsigned char *input) { - size_t in = 0; - size_t out = 0; - unsigned char total = 0; - unsigned int bits = 0; - size_t consumed; - - for (consumed = 0; consumed < out_len; consumed++) { - if (bits == 0) { - total = input[in]; - in++; - bits += 8; - } - bits -= PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_WOTS_LOGW; - output[out] = (unsigned int)((total >> bits) & (PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_WOTS_W - 1)); - out++; - } -} - -/* Computes the WOTS+ checksum over a message (in base_w). */ -static void wots_checksum(unsigned int *csum_base_w, - const unsigned int *msg_base_w) { - unsigned int csum = 0; - unsigned char csum_bytes[(PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_WOTS_LEN2 * PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_WOTS_LOGW + 7) / 8]; - unsigned int i; - - /* Compute checksum. */ - for (i = 0; i < PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_WOTS_LEN1; i++) { - csum += PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_WOTS_W - 1 - msg_base_w[i]; - } - - /* Convert checksum to base_w. */ - /* Make sure expected empty zero bits are the least significant bits. */ - csum = csum << (8 - ((PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_WOTS_LEN2 * PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_WOTS_LOGW) % 8)); - PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_ull_to_bytes( - csum_bytes, sizeof(csum_bytes), csum); - base_w(csum_base_w, PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_WOTS_LEN2, csum_bytes); -} - -/* Takes a message and derives the matching chain lengths. */ -static void chain_lengths(unsigned int *lengths, const unsigned char *msg) { - base_w(lengths, PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_WOTS_LEN1, msg); - wots_checksum(lengths + PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_WOTS_LEN1, lengths); -} - -/** - * WOTS key generation. Takes a 32 byte sk_seed, expands it to WOTS private key - * elements and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_wots_gen_pk( - unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - uint32_t i; - - for (i = 0; i < PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_WOTS_LEN; i++) { - PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_set_chain_addr(addr, i); - wots_gen_sk(pk + i * PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_N, sk_seed, addr, hash_state_seeded); - gen_chain(pk + i * PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_N, pk + i * PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_N, - 0, PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_WOTS_W - 1, pub_seed, addr, hash_state_seeded); - } -} - -/** - * Takes a n-byte message and the 32-byte sk_see to compute a signature 'sig'. - */ -void PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_wots_sign( - unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *hash_state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_WOTS_LEN; i++) { - PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_set_chain_addr(addr, i); - wots_gen_sk(sig + i * PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_N, sk_seed, addr, hash_state_seeded); - gen_chain(sig + i * PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_N, sig + i * PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_N, 0, lengths[i], pub_seed, addr, hash_state_seeded); - } -} - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_wots_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_WOTS_LEN; i++) { - PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_set_chain_addr(addr, i); - gen_chain(pk + i * PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_N, sig + i * PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_N, - lengths[i], PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_WOTS_W - 1 - lengths[i], pub_seed, addr, - hash_state_seeded); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_clean/wots.h b/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_clean/wots.h deleted file mode 100644 index 284b8f15ec..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256f-robust_clean/wots.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_WOTS_H -#define PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_WOTS_H - -#include "hash_state.h" -#include "params.h" -#include - -/** - * WOTS key generation. Takes a 32 byte seed for the private key, expands it to - * a full WOTS private key and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_wots_gen_pk( - unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -/** - * Takes a n-byte message and the 32-byte seed for the private key to compute a - * signature that is placed at 'sig'. - */ -void PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_wots_sign( - unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *hash_state_seeded); - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_wots_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_avx2/LICENSE b/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_avx2/LICENSE deleted file mode 100644 index 670154e353..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_avx2/LICENSE +++ /dev/null @@ -1,116 +0,0 @@ -CC0 1.0 Universal - -Statement of Purpose - -The laws of most jurisdictions throughout the world automatically confer -exclusive Copyright and Related Rights (defined below) upon the creator and -subsequent owner(s) (each and all, an "owner") of an original work of -authorship and/or a database (each, a "Work"). - -Certain owners wish to permanently relinquish those rights to a Work for the -purpose of contributing to a commons of creative, cultural and scientific -works ("Commons") that the public can reliably and without fear of later -claims of infringement build upon, modify, incorporate in other works, reuse -and redistribute as freely as possible in any form whatsoever and for any -purposes, including without limitation commercial purposes. These owners may -contribute to the Commons to promote the ideal of a free culture and the -further production of creative, cultural and scientific works, or to gain -reputation or greater distribution for their Work in part through the use and -efforts of others. - -For these and/or other purposes and motivations, and without any expectation -of additional consideration or compensation, the person associating CC0 with a -Work (the "Affirmer"), to the extent that he or she is an owner of Copyright -and Related Rights in the Work, voluntarily elects to apply CC0 to the Work -and publicly distribute the Work under its terms, with knowledge of his or her -Copyright and Related Rights in the Work and the meaning and intended legal -effect of CC0 on those rights. - -1. Copyright and Related Rights. A Work made available under CC0 may be -protected by copyright and related or neighboring rights ("Copyright and -Related Rights"). Copyright and Related Rights include, but are not limited -to, the following: - - i. the right to reproduce, adapt, distribute, perform, display, communicate, - and translate a Work; - - ii. moral rights retained by the original author(s) and/or performer(s); - - iii. publicity and privacy rights pertaining to a person's image or likeness - depicted in a Work; - - iv. rights protecting against unfair competition in regards to a Work, - subject to the limitations in paragraph 4(a), below; - - v. rights protecting the extraction, dissemination, use and reuse of data in - a Work; - - vi. database rights (such as those arising under Directive 96/9/EC of the - European Parliament and of the Council of 11 March 1996 on the legal - protection of databases, and under any national implementation thereof, - including any amended or successor version of such directive); and - - vii. other similar, equivalent or corresponding rights throughout the world - based on applicable law or treaty, and any national implementations thereof. - -2. Waiver. To the greatest extent permitted by, but not in contravention of, -applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and -unconditionally waives, abandons, and surrenders all of Affirmer's Copyright -and Related Rights and associated claims and causes of action, whether now -known or unknown (including existing as well as future claims and causes of -action), in the Work (i) in all territories worldwide, (ii) for the maximum -duration provided by applicable law or treaty (including future time -extensions), (iii) in any current or future medium and for any number of -copies, and (iv) for any purpose whatsoever, including without limitation -commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes -the Waiver for the benefit of each member of the public at large and to the -detriment of Affirmer's heirs and successors, fully intending that such Waiver -shall not be subject to revocation, rescission, cancellation, termination, or -any other legal or equitable action to disrupt the quiet enjoyment of the Work -by the public as contemplated by Affirmer's express Statement of Purpose. - -3. Public License Fallback. Should any part of the Waiver for any reason be -judged legally invalid or ineffective under applicable law, then the Waiver -shall be preserved to the maximum extent permitted taking into account -Affirmer's express Statement of Purpose. In addition, to the extent the Waiver -is so judged Affirmer hereby grants to each affected person a royalty-free, -non transferable, non sublicensable, non exclusive, irrevocable and -unconditional license to exercise Affirmer's Copyright and Related Rights in -the Work (i) in all territories worldwide, (ii) for the maximum duration -provided by applicable law or treaty (including future time extensions), (iii) -in any current or future medium and for any number of copies, and (iv) for any -purpose whatsoever, including without limitation commercial, advertising or -promotional purposes (the "License"). The License shall be deemed effective as -of the date CC0 was applied by Affirmer to the Work. Should any part of the -License for any reason be judged legally invalid or ineffective under -applicable law, such partial invalidity or ineffectiveness shall not -invalidate the remainder of the License, and in such case Affirmer hereby -affirms that he or she will not (i) exercise any of his or her remaining -Copyright and Related Rights in the Work or (ii) assert any associated claims -and causes of action with respect to the Work, in either case contrary to -Affirmer's express Statement of Purpose. - -4. Limitations and Disclaimers. - - a. No trademark or patent rights held by Affirmer are waived, abandoned, - surrendered, licensed or otherwise affected by this document. - - b. Affirmer offers the Work as-is and makes no representations or warranties - of any kind concerning the Work, express, implied, statutory or otherwise, - including without limitation warranties of title, merchantability, fitness - for a particular purpose, non infringement, or the absence of latent or - other defects, accuracy, or the present or absence of errors, whether or not - discoverable, all to the greatest extent permissible under applicable law. - - c. Affirmer disclaims responsibility for clearing rights of other persons - that may apply to the Work or any use thereof, including without limitation - any person's Copyright and Related Rights in the Work. Further, Affirmer - disclaims responsibility for obtaining any necessary consents, permissions - or other rights required for any use of the Work. - - d. Affirmer understands and acknowledges that Creative Commons is not a - party to this document and has no duty or obligation with respect to this - CC0 or use of the Work. - -For more information, please see - diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_avx2/address.c b/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_avx2/address.c deleted file mode 100644 index 9d58797e94..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_avx2/address.c +++ /dev/null @@ -1,78 +0,0 @@ -#include - -#include "address.h" -#include "params.h" -#include "utils.h" - -void PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]) { - int i; - - for (i = 0; i < 8; i++) { - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_ull_to_bytes( - bytes + i * 4, 4, addr[i]); - } -} - -void PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_set_layer_addr( - uint32_t addr[8], uint32_t layer) { - addr[0] = layer; -} - -void PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_set_tree_addr( - uint32_t addr[8], uint64_t tree) { - addr[1] = 0; - addr[2] = (uint32_t) (tree >> 32); - addr[3] = (uint32_t) tree; -} - -void PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_set_type( - uint32_t addr[8], uint32_t type) { - addr[4] = type; -} - -void PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; -} - -/* These functions are used for OTS addresses. */ - -void PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_set_keypair_addr( - uint32_t addr[8], uint32_t keypair) { - addr[5] = keypair; -} - -void PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; - out[5] = in[5]; -} - -void PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_set_chain_addr( - uint32_t addr[8], uint32_t chain) { - addr[6] = chain; -} - -void PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_set_hash_addr( - uint32_t addr[8], uint32_t hash) { - addr[7] = hash; -} - -/* These functions are used for all hash tree addresses (including FORS). */ - -void PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_set_tree_height( - uint32_t addr[8], uint32_t tree_height) { - addr[6] = tree_height; -} - -void PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_set_tree_index( - uint32_t addr[8], uint32_t tree_index) { - addr[7] = tree_index; -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_avx2/address.h b/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_avx2/address.h deleted file mode 100644 index 648b05e19d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_avx2/address.h +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_ADDRESS_H -#define PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_ADDRESS_H - -#include - -#define PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_ADDR_TYPE_WOTS 0 -#define PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_ADDR_TYPE_WOTSPK 1 -#define PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_ADDR_TYPE_HASHTREE 2 -#define PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_ADDR_TYPE_FORSTREE 3 -#define PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_ADDR_TYPE_FORSPK 4 - -void PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]); - -void PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_set_layer_addr( - uint32_t addr[8], uint32_t layer); - -void PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_set_tree_addr( - uint32_t addr[8], uint64_t tree); - -void PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_set_type( - uint32_t addr[8], uint32_t type); - -/* Copies the layer and tree part of one address into the other */ -void PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for WOTS and FORS addresses. */ - -void PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_set_keypair_addr( - uint32_t addr[8], uint32_t keypair); - -void PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_set_chain_addr( - uint32_t addr[8], uint32_t chain); - -void PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_set_hash_addr( - uint32_t addr[8], uint32_t hash); - -void PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for all hash tree addresses (including FORS). */ - -void PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_set_tree_height( - uint32_t addr[8], uint32_t tree_height); - -void PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_set_tree_index( - uint32_t addr[8], uint32_t tree_index); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_avx2/api.h b/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_avx2/api.h deleted file mode 100644 index c95d5734f5..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_avx2/api.h +++ /dev/null @@ -1,81 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_API_H -#define PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_API_H - -#include -#include - - - -#define PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_CRYPTO_ALGNAME "SPHINCS+" - -#define PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_CRYPTO_SECRETKEYBYTES 128 -#define PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_CRYPTO_PUBLICKEYBYTES 64 -#define PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_CRYPTO_BYTES 49856 -#define PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_CRYPTO_SEEDBYTES 96 - - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_avx2/fors.c b/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_avx2/fors.c deleted file mode 100644 index 13e15ca2c5..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_avx2/fors.c +++ /dev/null @@ -1,240 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "fors.h" -#include "hash.h" -#include "hashx8.h" -#include "thash.h" -#include "thashx8.h" -#include "utils.h" -#include "utilsx8.h" - -static void fors_gen_skx8(unsigned char *sk0, - unsigned char *sk1, - unsigned char *sk2, - unsigned char *sk3, - unsigned char *sk4, - unsigned char *sk5, - unsigned char *sk6, - unsigned char *sk7, const unsigned char *sk_seed, - uint32_t fors_leaf_addrx8[8 * 8]) { - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_prf_addrx8(sk0, sk1, sk2, sk3, sk4, sk5, sk6, sk7, - sk_seed, fors_leaf_addrx8); -} - -static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, - const unsigned char *pub_seed, - uint32_t fors_leaf_addr[8], - const hash_state *state_seeded) { - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_thash_1(leaf, sk, pub_seed, fors_leaf_addr, state_seeded); -} - -static void fors_sk_to_leafx8(unsigned char *leaf0, - unsigned char *leaf1, - unsigned char *leaf2, - unsigned char *leaf3, - unsigned char *leaf4, - unsigned char *leaf5, - unsigned char *leaf6, - unsigned char *leaf7, - const unsigned char *sk0, - const unsigned char *sk1, - const unsigned char *sk2, - const unsigned char *sk3, - const unsigned char *sk4, - const unsigned char *sk5, - const unsigned char *sk6, - const unsigned char *sk7, - const unsigned char *pub_seed, - uint32_t fors_leaf_addrx8[8 * 8], - const hash_state *state_seeded) { - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_thashx8_1(leaf0, leaf1, leaf2, leaf3, leaf4, leaf5, leaf6, leaf7, - sk0, sk1, sk2, sk3, sk4, sk5, sk6, sk7, - pub_seed, fors_leaf_addrx8, state_seeded); -} - -static void fors_gen_leafx8(unsigned char *leaf0, - unsigned char *leaf1, - unsigned char *leaf2, - unsigned char *leaf3, - unsigned char *leaf4, - unsigned char *leaf5, - unsigned char *leaf6, - unsigned char *leaf7, - const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx0, - uint32_t addr_idx1, - uint32_t addr_idx2, - uint32_t addr_idx3, - uint32_t addr_idx4, - uint32_t addr_idx5, - uint32_t addr_idx6, - uint32_t addr_idx7, - const uint32_t fors_tree_addr[8], - const hash_state *state_seeded) { - uint32_t fors_leaf_addrx8[8 * 8] = {0}; - unsigned int j; - - /* Only copy the parts that must be kept in fors_leaf_addrx8. */ - for (j = 0; j < 8; j++) { - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_copy_keypair_addr(fors_leaf_addrx8 + j * 8, fors_tree_addr); - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_set_type(fors_leaf_addrx8 + j * 8, PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_ADDR_TYPE_FORSTREE); - } - - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_set_tree_index(fors_leaf_addrx8 + 0 * 8, addr_idx0); - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_set_tree_index(fors_leaf_addrx8 + 1 * 8, addr_idx1); - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_set_tree_index(fors_leaf_addrx8 + 2 * 8, addr_idx2); - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_set_tree_index(fors_leaf_addrx8 + 3 * 8, addr_idx3); - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_set_tree_index(fors_leaf_addrx8 + 4 * 8, addr_idx4); - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_set_tree_index(fors_leaf_addrx8 + 5 * 8, addr_idx5); - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_set_tree_index(fors_leaf_addrx8 + 6 * 8, addr_idx6); - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_set_tree_index(fors_leaf_addrx8 + 7 * 8, addr_idx7); - - fors_gen_skx8(leaf0, leaf1, leaf2, leaf3, leaf4, leaf5, leaf6, leaf7, - sk_seed, fors_leaf_addrx8); - fors_sk_to_leafx8(leaf0, leaf1, leaf2, leaf3, leaf4, leaf5, leaf6, leaf7, - leaf0, leaf1, leaf2, leaf3, leaf4, leaf5, leaf6, leaf7, - pub_seed, fors_leaf_addrx8, state_seeded); -} - -/** - * Interprets m as PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_FORS_HEIGHT-bit unsigned integers. - * Assumes m contains at least PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_FORS_TREES bits. - * Assumes indices has space for PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_FORS_TREES integers. - */ -static void message_to_indices(uint32_t *indices, const unsigned char *m) { - unsigned int i, j; - unsigned int offset = 0; - - for (i = 0; i < PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_FORS_TREES; i++) { - indices[i] = 0; - for (j = 0; j < PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_FORS_HEIGHT; j++) { - indices[i] ^= (((uint32_t)m[offset >> 3] >> (offset & 0x7)) & 0x1) << j; - offset++; - } - } -} - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_fors_sign( - unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], - const hash_state *state_seeded) { - /* Round up to multiple of 8 to prevent out-of-bounds for x8 parallelism */ - uint32_t indices[(PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_FORS_TREES + 7) & ~7] = {0}; - unsigned char roots[((PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_FORS_TREES + 7) & ~7) * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N]; - /* Sign to a buffer, since we may not have a nice multiple of 8 and would - otherwise overrun the signature. */ - unsigned char sigbufx8[8 * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N * (1 + PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_FORS_HEIGHT)]; - uint32_t fors_tree_addrx8[8 * 8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset[8] = {0}; - unsigned int i, j; - - for (j = 0; j < 8; j++) { - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_copy_keypair_addr(fors_tree_addrx8 + j * 8, fors_addr); - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_set_type(fors_tree_addrx8 + j * 8, PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_ADDR_TYPE_FORSTREE); - } - - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_copy_keypair_addr(fors_pk_addr, fors_addr); - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_set_type(fors_pk_addr, PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < ((PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_FORS_TREES + 7) & ~0x7); i += 8) { - for (j = 0; j < 8; j++) { - if (i + j < PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_FORS_TREES) { - idx_offset[j] = (i + j) * (1 << PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_FORS_HEIGHT); - - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_set_tree_height(fors_tree_addrx8 + j * 8, 0); - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_set_tree_index(fors_tree_addrx8 + j * 8, - indices[i + j] + idx_offset[j]); - } - } - - /* Include the secret key part that produces the selected leaf nodes. */ - fors_gen_skx8(sigbufx8 + 0 * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N, - sigbufx8 + 1 * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N, - sigbufx8 + 2 * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N, - sigbufx8 + 3 * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N, - sigbufx8 + 4 * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N, - sigbufx8 + 5 * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N, - sigbufx8 + 6 * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N, - sigbufx8 + 7 * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N, - sk_seed, fors_tree_addrx8); - - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_treehashx8_FORS_HEIGHT( - roots + i * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N, sigbufx8 + 8 * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N, sk_seed, pub_seed, - &indices[i], idx_offset, fors_gen_leafx8, fors_tree_addrx8, - state_seeded); - - for (j = 0; j < 8; j++) { - if (i + j < PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_FORS_TREES) { - memcpy(sig, sigbufx8 + j * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N, PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N); - memcpy(sig + PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N, - sigbufx8 + 8 * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N + j * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_FORS_HEIGHT, - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_FORS_HEIGHT); - sig += PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N * (1 + PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_FORS_HEIGHT); - } - } - } - - /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_thash_FORS_TREES(pk, roots, pub_seed, fors_pk_addr, state_seeded); -} - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, - const uint32_t fors_addr[8], - const hash_state *state_seeded) { - uint32_t indices[PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_FORS_TREES]; - unsigned char roots[PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_FORS_TREES * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N]; - unsigned char leaf[PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N]; - uint32_t fors_tree_addr[8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_copy_keypair_addr(fors_tree_addr, fors_addr); - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_copy_keypair_addr(fors_pk_addr, fors_addr); - - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_set_type(fors_tree_addr, PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_set_type(fors_pk_addr, PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_FORS_TREES; i++) { - idx_offset = i * (1 << PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_FORS_HEIGHT); - - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_set_tree_height(fors_tree_addr, 0); - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Derive the leaf from the included secret key part. */ - fors_sk_to_leaf(leaf, sig, pub_seed, fors_tree_addr, state_seeded); - sig += PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N; - - /* Derive the corresponding root node of this tree. */ - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_compute_root(roots + i * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N, leaf, indices[i], idx_offset, - sig, PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_FORS_HEIGHT, pub_seed, fors_tree_addr, state_seeded); - sig += PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_thash_FORS_TREES(pk, roots, pub_seed, fors_pk_addr, state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_avx2/fors.h b/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_avx2/fors.h deleted file mode 100644 index cce6895b00..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_avx2/fors.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_FORS_H -#define PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_FORS_H - -#include - -#include "hash_state.h" -#include "params.h" - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_fors_sign( - unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *hash_state_seeded); - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_fors_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, const uint32_t fors_addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_avx2/hash.h b/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_avx2/hash.h deleted file mode 100644 index 0e0077733b..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_avx2/hash.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_HASH_H -#define PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_HASH_H - -#include "hash_state.h" - -#include -#include - -void PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_initialize_hash_function( - hash_state *hash_state_seeded, - const unsigned char *pub_seed, const unsigned char *sk_seed); - -void PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_destroy_hash_function(hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_avx2/hash_sha256.c b/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_avx2/hash_sha256.c deleted file mode 100644 index 230f8fc725..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_avx2/hash_sha256.c +++ /dev/null @@ -1,166 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "utils.h" - -#include "sha2.h" -#include "sha256.h" -#include "sha256x8.h" - -/** - * Initializes the hash function states - */ -void PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_initialize_hash_function( - hash_state *hash_state_seeded, - const unsigned char *pub_seed, const unsigned char *sk_seed) { - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_seed_state(&hash_state_seeded->x1, pub_seed); - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_seed_statex8(&hash_state_seeded->x8, pub_seed); - (void)sk_seed; /* Suppress an 'unused parameter' warning. */ -} - -/** - * Cleans up the hash function states - */ -void PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_destroy_hash_function(hash_state *hash_state_seeded) { - sha256_inc_ctx_release(&hash_state_seeded->x1); -} - -/* - * Computes PRF(key, addr), given a secret key of PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N bytes and an address - */ -void PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_prf_addr(unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded) { - unsigned char buf[PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_ADDR_BYTES]; - unsigned char outbuf[PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_OUTPUT_BYTES]; - - memcpy(buf, key, PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N); - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_compress_address(buf + PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N, addr); - - sha256(outbuf, buf, PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_ADDR_BYTES); - memcpy(out, outbuf, PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} - -/** - * Computes the message-dependent randomness R, using a secret seed as a key - * for HMAC, and an optional randomization value prefixed to the message. - * This requires m to have at least PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_BLOCK_BYTES + PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N space - * available in front of the pointer, i.e. before the message to use for the - * prefix. This is necessary to prevent having to move the message around (and - * allocate memory for it). - */ -void PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, const hash_state *hash_state_seeded) { - unsigned char buf[PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_BLOCK_BYTES + PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_OUTPUT_BYTES]; - sha256ctx state; - int i; - - /* This implements HMAC-SHA256 */ - for (i = 0; i < PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N; i++) { - buf[i] = 0x36 ^ sk_prf[i]; - } - memset(buf + PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N, 0x36, PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N); - - sha256_inc_init(&state); - sha256_inc_blocks(&state, buf, 1); - - memcpy(buf, optrand, PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N); - - /* If optrand + message cannot fill up an entire block */ - if (PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N + mlen < PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_BLOCK_BYTES) { - memcpy(buf + PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N, m, mlen); - sha256_inc_finalize(buf + PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_BLOCK_BYTES, &state, - buf, mlen + PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N); - } - /* Otherwise first fill a block, so that finalize only uses the message */ - else { - memcpy(buf + PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N, m, PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N); - sha256_inc_blocks(&state, buf, 1); - - m += PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N; - mlen -= PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N; - sha256_inc_finalize(buf + PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_BLOCK_BYTES, &state, m, mlen); - } - - for (i = 0; i < PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N; i++) { - buf[i] = 0x5c ^ sk_prf[i]; - } - memset(buf + PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N, 0x5c, PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N); - - sha256(buf, buf, PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_BLOCK_BYTES + PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_OUTPUT_BYTES); - memcpy(R, buf, PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} - -/** - * Computes the message hash using R, the public key, and the message. - * Outputs the message digest and the index of the leaf. The index is split in - * the tree index and the leaf index, for convenient copying to an address. - */ -void PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded) { -#define PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_TREE_BITS (PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_TREE_HEIGHT * (PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_D - 1)) -#define PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_TREE_BYTES ((PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_TREE_BITS + 7) / 8) -#define PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_LEAF_BITS PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_TREE_HEIGHT -#define PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_LEAF_BYTES ((PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_LEAF_BITS + 7) / 8) -#define PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_DGST_BYTES (PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_FORS_MSG_BYTES + PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_TREE_BYTES + PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_LEAF_BYTES) - - unsigned char seed[PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_OUTPUT_BYTES + 4]; - - /* Round to nearest multiple of PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_BLOCK_BYTES */ -#define PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_INBLOCKS (((PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_PK_BYTES + PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_BLOCK_BYTES - 1) & \ - -PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_BLOCK_BYTES) / PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_BLOCK_BYTES) - unsigned char inbuf[PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_INBLOCKS * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_BLOCK_BYTES]; - - unsigned char buf[PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_DGST_BYTES]; - unsigned char *bufp = buf; - sha256ctx state; - - sha256_inc_init(&state); - - memcpy(inbuf, R, PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N); - memcpy(inbuf + PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N, pk, PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_PK_BYTES); - - /* If R + pk + message cannot fill up an entire block */ - if (PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_PK_BYTES + mlen < PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_INBLOCKS * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_BLOCK_BYTES) { - memcpy(inbuf + PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_PK_BYTES, m, mlen); - sha256_inc_finalize(seed, &state, inbuf, PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_PK_BYTES + mlen); - } - /* Otherwise first fill a block, so that finalize only uses the message */ - else { - memcpy(inbuf + PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_PK_BYTES, m, - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_INBLOCKS * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_PK_BYTES); - sha256_inc_blocks(&state, inbuf, PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_INBLOCKS); - - m += PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_INBLOCKS * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_PK_BYTES; - mlen -= PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_INBLOCKS * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_PK_BYTES; - sha256_inc_finalize(seed, &state, m, mlen); - } - - /* By doing this in two steps, we prevent hashing the message twice; - otherwise each iteration in MGF1 would hash the message again. */ - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_mgf1(bufp, PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_DGST_BYTES, seed, PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_OUTPUT_BYTES); - - memcpy(digest, bufp, PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_FORS_MSG_BYTES); - bufp += PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_FORS_MSG_BYTES; - - *tree = PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_bytes_to_ull(bufp, PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_TREE_BYTES); - *tree &= (~(uint64_t)0) >> (64 - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_TREE_BITS); - bufp += PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_TREE_BYTES; - - *leaf_idx = (uint32_t)PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_bytes_to_ull( - bufp, PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_LEAF_BYTES); - *leaf_idx &= (~(uint32_t)0) >> (32 - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_LEAF_BITS); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_avx2/hash_sha256x8.c b/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_avx2/hash_sha256x8.c deleted file mode 100644 index bbd1fda08d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_avx2/hash_sha256x8.c +++ /dev/null @@ -1,61 +0,0 @@ -#include -#include - -#include "address.h" -#include "hashx8.h" -#include "params.h" -#include "sha256.h" -#include "sha256avx.h" -#include "sha256x8.h" -#include "utils.h" - -/* - * 8-way parallel version of prf_addr; takes 8x as much input and output - */ -void PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_prf_addrx8(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7, - const unsigned char *key, - const uint32_t addrx8[8 * 8]) { - unsigned char bufx8[8 * (PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_ADDR_BYTES)]; - unsigned char outbufx8[8 * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_OUTPUT_BYTES]; - unsigned int j; - - for (j = 0; j < 8; j++) { - memcpy(bufx8 + j * (PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_ADDR_BYTES), key, PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N); - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_compress_address(bufx8 + PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N + j * (PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_ADDR_BYTES), - addrx8 + j * 8); - } - - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_sha256x8(outbufx8 + 0 * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 1 * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 2 * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 3 * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 4 * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 5 * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 6 * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 7 * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - bufx8 + 0 * (PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_ADDR_BYTES), - bufx8 + 1 * (PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_ADDR_BYTES), - bufx8 + 2 * (PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_ADDR_BYTES), - bufx8 + 3 * (PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_ADDR_BYTES), - bufx8 + 4 * (PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_ADDR_BYTES), - bufx8 + 5 * (PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_ADDR_BYTES), - bufx8 + 6 * (PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_ADDR_BYTES), - bufx8 + 7 * (PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_ADDR_BYTES), - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_ADDR_BYTES); - - memcpy(out0, outbufx8 + 0 * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N); - memcpy(out1, outbufx8 + 1 * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N); - memcpy(out2, outbufx8 + 2 * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N); - memcpy(out3, outbufx8 + 3 * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N); - memcpy(out4, outbufx8 + 4 * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N); - memcpy(out5, outbufx8 + 5 * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N); - memcpy(out6, outbufx8 + 6 * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N); - memcpy(out7, outbufx8 + 7 * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_avx2/hash_state.h b/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_avx2/hash_state.h deleted file mode 100644 index eb72f0640b..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_avx2/hash_state.h +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_HASH_STATE_H -#define PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_HASH_STATE_H - -/** - * Defines the type of the hash function state. - * - * Don't be fooled into thinking this instance of SPHINCS+ isn't stateless! - * - * From Section 7.2.2 from the SPHINCS+ round-2 specification: - * - * Each of the instances of the tweakable hash function take PK.seed as its - * first input, which is constant for a given key pair – and, thus, across - * a single signature. This leads to a lot of redundant computation. To remedy - * this, we pad PK.seed to the length of a full 64-byte SHA-256 input block. - * Because of the Merkle-Damgård construction that underlies SHA-256, this - * allows for reuse of the intermediate SHA-256 state after the initial call to - * the compression function which improves performance. - * - * We pass this hash state around in functions, because otherwise we need to - * have a global variable. - * - * We use a struct to differentiate between the x1 and x8 variants of SHA256. - */ - -#include "sha2.h" -#include "sha256avx.h" - -typedef struct { - sha256ctx x1; - sha256ctxx8 x8; -} hash_state; - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_avx2/hashx8.h b/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_avx2/hashx8.h deleted file mode 100644 index d7d629fedd..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_avx2/hashx8.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_HASHX8_H -#define PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_HASHX8_H - -#include - -#include "params.h" - -void PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_prf_addrx8(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7, - const unsigned char *key, - const uint32_t addrx8[8 * 8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_avx2/params.h b/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_avx2/params.h deleted file mode 100644 index 2e804440aa..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_avx2/params.h +++ /dev/null @@ -1,53 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_PARAMS_H -#define PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_PARAMS_H - -/* Hash output length in bytes. */ -#define PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N 32 -/* Height of the hypertree. */ -#define PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_FULL_HEIGHT 68 -/* Number of subtree layer. */ -#define PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_D 17 -/* FORS tree dimensions. */ -#define PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_FORS_HEIGHT 9 -#define PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_FORS_TREES 35 -/* Winternitz parameter, */ -#define PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_WOTS_W 16 - -/* The hash function is defined by linking a different hash.c file, as opposed - to setting a #define constant. */ - -/* For clarity */ -#define PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_ADDR_BYTES 32 - -/* WOTS parameters. */ -#define PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_WOTS_LOGW 4 - -#define PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_WOTS_LEN1 (8 * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N / PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_WOTS_LOGW) - -/* PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#define PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_WOTS_LEN2 3 - -#define PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_WOTS_LEN (PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_WOTS_LEN1 + PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_WOTS_LEN2) -#define PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_WOTS_BYTES (PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_WOTS_LEN * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N) -#define PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_WOTS_PK_BYTES PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_WOTS_BYTES - -/* Subtree size. */ -#define PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_TREE_HEIGHT (PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_FULL_HEIGHT / PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_D) - -/* FORS parameters. */ -#define PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_FORS_MSG_BYTES ((PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_FORS_TREES + 7) / 8) -#define PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_FORS_BYTES ((PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_FORS_HEIGHT + 1) * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_FORS_TREES * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N) -#define PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_FORS_PK_BYTES PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N - -/* Resulting SPX sizes. */ -#define PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_BYTES (PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_FORS_BYTES + PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_D * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_WOTS_BYTES +\ - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_FULL_HEIGHT * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N) -#define PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_PK_BYTES (2 * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N) -#define PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SK_BYTES (2 * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_PK_BYTES) - -/* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ -#define PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_OPTRAND_BYTES 32 - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_avx2/sha256.c b/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_avx2/sha256.c deleted file mode 100644 index 4020f0044a..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_avx2/sha256.c +++ /dev/null @@ -1,71 +0,0 @@ -/* Based on the public domain implementation in - * crypto_hash/sha512/ref/ from http://bench.cr.yp.to/supercop.html - * by D. J. Bernstein */ - -#include -#include -#include - -#include "sha2.h" -#include "sha256.h" -#include "utils.h" - -/* - * Compresses an address to a 22-byte sequence. - * This reduces the number of required SHA256 compression calls, as the last - * block of input is padded with at least 65 bits. - */ -void PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_compress_address(unsigned char *out, const uint32_t addr[8]) { - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_ull_to_bytes(out, 1, addr[0]); /* drop 3 bytes of the layer field */ - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_ull_to_bytes(out + 1, 4, addr[2]); /* drop the highest tree address word */ - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_ull_to_bytes(out + 5, 4, addr[3]); - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_ull_to_bytes(out + 9, 1, addr[4]); /* drop 3 bytes of the type field */ - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_ull_to_bytes(out + 10, 4, addr[5]); - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_ull_to_bytes(out + 14, 4, addr[6]); - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_ull_to_bytes(out + 18, 4, addr[7]); -} - -/** - * Requires 'input_plus_four_bytes' to have 'inlen' + 4 bytes, so that the last - * four bytes can be used for the counter. Typically 'input' is merely a seed. - * Outputs outlen number of bytes - */ -void PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_mgf1( - unsigned char *out, unsigned long outlen, - unsigned char *input_plus_four_bytes, unsigned long inlen) { - unsigned char outbuf[PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_OUTPUT_BYTES]; - unsigned long i; - - /* While we can fit in at least another full block of SHA256 output.. */ - for (i = 0; (i + 1)*PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_OUTPUT_BYTES <= outlen; i++) { - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_ull_to_bytes(input_plus_four_bytes + inlen, 4, i); - sha256(out, input_plus_four_bytes, inlen + 4); - out += PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_OUTPUT_BYTES; - } - /* Until we cannot anymore, and we fill the remainder. */ - if (outlen > i * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_OUTPUT_BYTES) { - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_ull_to_bytes(input_plus_four_bytes + inlen, 4, i); - sha256(outbuf, input_plus_four_bytes, inlen + 4); - memcpy(out, outbuf, outlen - i * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_OUTPUT_BYTES); - } -} - - -/** - * Absorb the constant pub_seed using one round of the compression function - * This initializes hash_state_seeded, which can then be reused in thash - **/ -void PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_seed_state(sha256ctx *hash_state_seeded, const unsigned char *pub_seed) { - uint8_t block[PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_BLOCK_BYTES]; - size_t i; - - for (i = 0; i < PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N; ++i) { - block[i] = pub_seed[i]; - } - for (i = PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N; i < PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_BLOCK_BYTES; ++i) { - block[i] = 0; - } - - sha256_inc_init(hash_state_seeded); - sha256_inc_blocks(hash_state_seeded, block, 1); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_avx2/sha256.h b/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_avx2/sha256.h deleted file mode 100644 index f78d538442..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_avx2/sha256.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_H -#define PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_H - -#define PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_BLOCK_BYTES 64 -#define PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_OUTPUT_BYTES 32 /* This does not necessarily equal PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N */ -#define PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_ADDR_BYTES 22 - -#include -#include - -#include "sha2.h" - -void PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_compress_address(unsigned char *out, const uint32_t addr[8]); - -void PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_mgf1( - unsigned char *out, unsigned long outlen, - unsigned char *input_plus_four_bytes, unsigned long inlen); - -void PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_seed_state(sha256ctx *hash_state_seeded, const unsigned char *pub_seed); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_avx2/sha256avx.c b/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_avx2/sha256avx.c deleted file mode 100644 index 72cbf7ad12..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_avx2/sha256avx.c +++ /dev/null @@ -1,296 +0,0 @@ -#include -#include -#include - -#include "sha256avx.h" - -// Transpose 8 vectors containing 32-bit values -void PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_transpose(u256 s[8]) { - u256 tmp0[8]; - u256 tmp1[8]; - tmp0[0] = _mm256_unpacklo_epi32(s[0], s[1]); - tmp0[1] = _mm256_unpackhi_epi32(s[0], s[1]); - tmp0[2] = _mm256_unpacklo_epi32(s[2], s[3]); - tmp0[3] = _mm256_unpackhi_epi32(s[2], s[3]); - tmp0[4] = _mm256_unpacklo_epi32(s[4], s[5]); - tmp0[5] = _mm256_unpackhi_epi32(s[4], s[5]); - tmp0[6] = _mm256_unpacklo_epi32(s[6], s[7]); - tmp0[7] = _mm256_unpackhi_epi32(s[6], s[7]); - tmp1[0] = _mm256_unpacklo_epi64(tmp0[0], tmp0[2]); - tmp1[1] = _mm256_unpackhi_epi64(tmp0[0], tmp0[2]); - tmp1[2] = _mm256_unpacklo_epi64(tmp0[1], tmp0[3]); - tmp1[3] = _mm256_unpackhi_epi64(tmp0[1], tmp0[3]); - tmp1[4] = _mm256_unpacklo_epi64(tmp0[4], tmp0[6]); - tmp1[5] = _mm256_unpackhi_epi64(tmp0[4], tmp0[6]); - tmp1[6] = _mm256_unpacklo_epi64(tmp0[5], tmp0[7]); - tmp1[7] = _mm256_unpackhi_epi64(tmp0[5], tmp0[7]); - s[0] = _mm256_permute2x128_si256(tmp1[0], tmp1[4], 0x20); - s[1] = _mm256_permute2x128_si256(tmp1[1], tmp1[5], 0x20); - s[2] = _mm256_permute2x128_si256(tmp1[2], tmp1[6], 0x20); - s[3] = _mm256_permute2x128_si256(tmp1[3], tmp1[7], 0x20); - s[4] = _mm256_permute2x128_si256(tmp1[0], tmp1[4], 0x31); - s[5] = _mm256_permute2x128_si256(tmp1[1], tmp1[5], 0x31); - s[6] = _mm256_permute2x128_si256(tmp1[2], tmp1[6], 0x31); - s[7] = _mm256_permute2x128_si256(tmp1[3], tmp1[7], 0x31); -} - -void PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_sha256_clone_statex8(sha256ctxx8 *outctx, const sha256ctxx8 *inctx) { - memcpy(outctx, inctx, sizeof(sha256ctxx8)); -} - -void PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_sha256_init8x(sha256ctxx8 *ctx) { - ctx->s[0] = _mm256_set_epi32((int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667); - ctx->s[1] = _mm256_set_epi32((int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85); - ctx->s[2] = _mm256_set_epi32((int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372); - ctx->s[3] = _mm256_set_epi32((int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a); - ctx->s[4] = _mm256_set_epi32((int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f); - ctx->s[5] = _mm256_set_epi32((int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c); - ctx->s[6] = _mm256_set_epi32((int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab); - ctx->s[7] = _mm256_set_epi32((int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19); - - ctx->datalen = 0; - ctx->msglen = 0; -} - -void PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_sha256_update8x(sha256ctxx8 *ctx, - const unsigned char *d0, - const unsigned char *d1, - const unsigned char *d2, - const unsigned char *d3, - const unsigned char *d4, - const unsigned char *d5, - const unsigned char *d6, - const unsigned char *d7, - unsigned long long len) { - size_t i = 0; - size_t bytes_to_copy; - - while (i < len) { - bytes_to_copy = (size_t)len - i; - if (bytes_to_copy > 64) { - bytes_to_copy = 64; - } - memcpy(&ctx->msgblocks[64 * 0], d0 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64 * 1], d1 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64 * 2], d2 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64 * 3], d3 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64 * 4], d4 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64 * 5], d5 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64 * 6], d6 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64 * 7], d7 + i, bytes_to_copy); - ctx->datalen += (unsigned int)bytes_to_copy; - i += bytes_to_copy; - if (ctx->datalen == 64) { - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_sha256_transform8x(ctx, ctx->msgblocks); - ctx->msglen += 512; - ctx->datalen = 0; - } - } -} - -void PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_sha256_final8x(sha256ctxx8 *ctx, - unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7) { - unsigned int i, curlen; - - // Padding - if (ctx->datalen < 56) { - for (i = 0; i < 8; ++i) { - curlen = ctx->datalen; - ctx->msgblocks[64 * i + curlen++] = 0x80; - while (curlen < 64) { - ctx->msgblocks[64 * i + curlen++] = 0x00; - } - } - } else { - for (i = 0; i < 8; ++i) { - curlen = ctx->datalen; - ctx->msgblocks[64 * i + curlen++] = 0x80; - while (curlen < 64) { - ctx->msgblocks[64 * i + curlen++] = 0x00; - } - } - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_sha256_transform8x(ctx, ctx->msgblocks); - memset(ctx->msgblocks, 0, 8 * 64); - } - - // Add length of the message to each block - ctx->msglen += ctx->datalen * 8; - for (i = 0; i < 8; i++) { - ctx->msgblocks[64 * i + 63] = (unsigned char)ctx->msglen; - ctx->msgblocks[64 * i + 62] = (unsigned char)(ctx->msglen >> 8); - ctx->msgblocks[64 * i + 61] = (unsigned char)(ctx->msglen >> 16); - ctx->msgblocks[64 * i + 60] = (unsigned char)(ctx->msglen >> 24); - ctx->msgblocks[64 * i + 59] = (unsigned char)(ctx->msglen >> 32); - ctx->msgblocks[64 * i + 58] = (unsigned char)(ctx->msglen >> 40); - ctx->msgblocks[64 * i + 57] = (unsigned char)(ctx->msglen >> 48); - ctx->msgblocks[64 * i + 56] = (unsigned char)(ctx->msglen >> 56); - } - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_sha256_transform8x(ctx, ctx->msgblocks); - - // Compute final hash output - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_transpose(ctx->s); - - // Store Hash value - STORE(out0, BYTESWAP(ctx->s[0])); - STORE(out1, BYTESWAP(ctx->s[1])); - STORE(out2, BYTESWAP(ctx->s[2])); - STORE(out3, BYTESWAP(ctx->s[3])); - STORE(out4, BYTESWAP(ctx->s[4])); - STORE(out5, BYTESWAP(ctx->s[5])); - STORE(out6, BYTESWAP(ctx->s[6])); - STORE(out7, BYTESWAP(ctx->s[7])); -} - -void PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_sha256_transform8x(sha256ctxx8 *ctx, const unsigned char *data) { - u256 s[8], w[64], T0, T1; - int i; - - // Load words and transform data correctly - for (i = 0; i < 8; i++) { - w[i] = BYTESWAP(LOAD(data + 64 * i)); - w[i + 8] = BYTESWAP(LOAD(data + 32 + 64 * i)); - } - - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_transpose(w); - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_transpose(w + 8); - - // Initial State - s[0] = ctx->s[0]; - s[1] = ctx->s[1]; - s[2] = ctx->s[2]; - s[3] = ctx->s[3]; - s[4] = ctx->s[4]; - s[5] = ctx->s[5]; - s[6] = ctx->s[6]; - s[7] = ctx->s[7]; - - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 0, w[0]); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 1, w[1]); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 2, w[2]); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 3, w[3]); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 4, w[4]); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 5, w[5]); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 6, w[6]); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 7, w[7]); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 8, w[8]); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 9, w[9]); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 10, w[10]); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 11, w[11]); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 12, w[12]); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 13, w[13]); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 14, w[14]); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 15, w[15]); - w[16] = ADD4_32(WSIGMA1_AVX(w[14]), w[0], w[9], WSIGMA0_AVX(w[1])); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 16, w[16]); - w[17] = ADD4_32(WSIGMA1_AVX(w[15]), w[1], w[10], WSIGMA0_AVX(w[2])); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 17, w[17]); - w[18] = ADD4_32(WSIGMA1_AVX(w[16]), w[2], w[11], WSIGMA0_AVX(w[3])); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 18, w[18]); - w[19] = ADD4_32(WSIGMA1_AVX(w[17]), w[3], w[12], WSIGMA0_AVX(w[4])); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 19, w[19]); - w[20] = ADD4_32(WSIGMA1_AVX(w[18]), w[4], w[13], WSIGMA0_AVX(w[5])); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 20, w[20]); - w[21] = ADD4_32(WSIGMA1_AVX(w[19]), w[5], w[14], WSIGMA0_AVX(w[6])); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 21, w[21]); - w[22] = ADD4_32(WSIGMA1_AVX(w[20]), w[6], w[15], WSIGMA0_AVX(w[7])); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 22, w[22]); - w[23] = ADD4_32(WSIGMA1_AVX(w[21]), w[7], w[16], WSIGMA0_AVX(w[8])); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 23, w[23]); - w[24] = ADD4_32(WSIGMA1_AVX(w[22]), w[8], w[17], WSIGMA0_AVX(w[9])); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 24, w[24]); - w[25] = ADD4_32(WSIGMA1_AVX(w[23]), w[9], w[18], WSIGMA0_AVX(w[10])); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 25, w[25]); - w[26] = ADD4_32(WSIGMA1_AVX(w[24]), w[10], w[19], WSIGMA0_AVX(w[11])); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 26, w[26]); - w[27] = ADD4_32(WSIGMA1_AVX(w[25]), w[11], w[20], WSIGMA0_AVX(w[12])); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 27, w[27]); - w[28] = ADD4_32(WSIGMA1_AVX(w[26]), w[12], w[21], WSIGMA0_AVX(w[13])); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 28, w[28]); - w[29] = ADD4_32(WSIGMA1_AVX(w[27]), w[13], w[22], WSIGMA0_AVX(w[14])); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 29, w[29]); - w[30] = ADD4_32(WSIGMA1_AVX(w[28]), w[14], w[23], WSIGMA0_AVX(w[15])); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 30, w[30]); - w[31] = ADD4_32(WSIGMA1_AVX(w[29]), w[15], w[24], WSIGMA0_AVX(w[16])); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 31, w[31]); - w[32] = ADD4_32(WSIGMA1_AVX(w[30]), w[16], w[25], WSIGMA0_AVX(w[17])); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 32, w[32]); - w[33] = ADD4_32(WSIGMA1_AVX(w[31]), w[17], w[26], WSIGMA0_AVX(w[18])); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 33, w[33]); - w[34] = ADD4_32(WSIGMA1_AVX(w[32]), w[18], w[27], WSIGMA0_AVX(w[19])); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 34, w[34]); - w[35] = ADD4_32(WSIGMA1_AVX(w[33]), w[19], w[28], WSIGMA0_AVX(w[20])); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 35, w[35]); - w[36] = ADD4_32(WSIGMA1_AVX(w[34]), w[20], w[29], WSIGMA0_AVX(w[21])); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 36, w[36]); - w[37] = ADD4_32(WSIGMA1_AVX(w[35]), w[21], w[30], WSIGMA0_AVX(w[22])); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 37, w[37]); - w[38] = ADD4_32(WSIGMA1_AVX(w[36]), w[22], w[31], WSIGMA0_AVX(w[23])); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 38, w[38]); - w[39] = ADD4_32(WSIGMA1_AVX(w[37]), w[23], w[32], WSIGMA0_AVX(w[24])); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 39, w[39]); - w[40] = ADD4_32(WSIGMA1_AVX(w[38]), w[24], w[33], WSIGMA0_AVX(w[25])); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 40, w[40]); - w[41] = ADD4_32(WSIGMA1_AVX(w[39]), w[25], w[34], WSIGMA0_AVX(w[26])); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 41, w[41]); - w[42] = ADD4_32(WSIGMA1_AVX(w[40]), w[26], w[35], WSIGMA0_AVX(w[27])); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 42, w[42]); - w[43] = ADD4_32(WSIGMA1_AVX(w[41]), w[27], w[36], WSIGMA0_AVX(w[28])); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 43, w[43]); - w[44] = ADD4_32(WSIGMA1_AVX(w[42]), w[28], w[37], WSIGMA0_AVX(w[29])); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 44, w[44]); - w[45] = ADD4_32(WSIGMA1_AVX(w[43]), w[29], w[38], WSIGMA0_AVX(w[30])); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 45, w[45]); - w[46] = ADD4_32(WSIGMA1_AVX(w[44]), w[30], w[39], WSIGMA0_AVX(w[31])); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 46, w[46]); - w[47] = ADD4_32(WSIGMA1_AVX(w[45]), w[31], w[40], WSIGMA0_AVX(w[32])); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 47, w[47]); - w[48] = ADD4_32(WSIGMA1_AVX(w[46]), w[32], w[41], WSIGMA0_AVX(w[33])); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 48, w[48]); - w[49] = ADD4_32(WSIGMA1_AVX(w[47]), w[33], w[42], WSIGMA0_AVX(w[34])); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 49, w[49]); - w[50] = ADD4_32(WSIGMA1_AVX(w[48]), w[34], w[43], WSIGMA0_AVX(w[35])); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 50, w[50]); - w[51] = ADD4_32(WSIGMA1_AVX(w[49]), w[35], w[44], WSIGMA0_AVX(w[36])); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 51, w[51]); - w[52] = ADD4_32(WSIGMA1_AVX(w[50]), w[36], w[45], WSIGMA0_AVX(w[37])); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 52, w[52]); - w[53] = ADD4_32(WSIGMA1_AVX(w[51]), w[37], w[46], WSIGMA0_AVX(w[38])); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 53, w[53]); - w[54] = ADD4_32(WSIGMA1_AVX(w[52]), w[38], w[47], WSIGMA0_AVX(w[39])); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 54, w[54]); - w[55] = ADD4_32(WSIGMA1_AVX(w[53]), w[39], w[48], WSIGMA0_AVX(w[40])); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 55, w[55]); - w[56] = ADD4_32(WSIGMA1_AVX(w[54]), w[40], w[49], WSIGMA0_AVX(w[41])); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 56, w[56]); - w[57] = ADD4_32(WSIGMA1_AVX(w[55]), w[41], w[50], WSIGMA0_AVX(w[42])); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 57, w[57]); - w[58] = ADD4_32(WSIGMA1_AVX(w[56]), w[42], w[51], WSIGMA0_AVX(w[43])); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 58, w[58]); - w[59] = ADD4_32(WSIGMA1_AVX(w[57]), w[43], w[52], WSIGMA0_AVX(w[44])); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 59, w[59]); - w[60] = ADD4_32(WSIGMA1_AVX(w[58]), w[44], w[53], WSIGMA0_AVX(w[45])); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 60, w[60]); - w[61] = ADD4_32(WSIGMA1_AVX(w[59]), w[45], w[54], WSIGMA0_AVX(w[46])); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 61, w[61]); - w[62] = ADD4_32(WSIGMA1_AVX(w[60]), w[46], w[55], WSIGMA0_AVX(w[47])); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 62, w[62]); - w[63] = ADD4_32(WSIGMA1_AVX(w[61]), w[47], w[56], WSIGMA0_AVX(w[48])); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 63, w[63]); - - // Feed Forward - ctx->s[0] = ADD32(s[0], ctx->s[0]); - ctx->s[1] = ADD32(s[1], ctx->s[1]); - ctx->s[2] = ADD32(s[2], ctx->s[2]); - ctx->s[3] = ADD32(s[3], ctx->s[3]); - ctx->s[4] = ADD32(s[4], ctx->s[4]); - ctx->s[5] = ADD32(s[5], ctx->s[5]); - ctx->s[6] = ADD32(s[6], ctx->s[6]); - ctx->s[7] = ADD32(s[7], ctx->s[7]); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_avx2/sha256avx.h b/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_avx2/sha256avx.h deleted file mode 100644 index 9089b512f4..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_avx2/sha256avx.h +++ /dev/null @@ -1,103 +0,0 @@ -#ifndef SHA256AVX_H -#define SHA256AVX_H - -#include -#include - -static const unsigned int RC[] = { - 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, - 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, - 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, - 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, - 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, - 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, - 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, - 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, - 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, - 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, - 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, - 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, - 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, - 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, - 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, - 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 -}; - -#define u32 uint32_t -#define u256 __m256i - -#define XOR _mm256_xor_si256 -#define OR _mm256_or_si256 -#define AND _mm256_and_si256 -#define ADD32 _mm256_add_epi32 -#define NOT(x) _mm256_xor_si256(x, _mm256_set_epi32(-1, -1, -1, -1, -1, -1, -1, -1)) - -#define LOAD(src) _mm256_loadu_si256((__m256i *)(src)) -#define STORE(dest,src) _mm256_storeu_si256((__m256i *)(dest),src) - -#define BYTESWAP(x) _mm256_shuffle_epi8(x, _mm256_set_epi8(0xc,0xd,0xe,0xf,0x8,0x9,0xa,0xb,0x4,0x5,0x6,0x7,0x0,0x1,0x2,0x3,0xc,0xd,0xe,0xf,0x8,0x9,0xa,0xb,0x4,0x5,0x6,0x7,0x0,0x1,0x2,0x3)) - -#define SHIFTR32(x, y) _mm256_srli_epi32(x, y) -#define SHIFTL32(x, y) _mm256_slli_epi32(x, y) - -#define ROTR32(x, y) OR(SHIFTR32(x, y), SHIFTL32(x, 32 - (y))) -#define ROTL32(x, y) OR(SHIFTL32(x, y), SHIFTR32(x, 32 - (y))) - -#define XOR3(a, b, c) XOR(XOR(a, b), c) - -#define ADD3_32(a, b, c) ADD32(ADD32(a, b), c) -#define ADD4_32(a, b, c, d) ADD32(ADD32(ADD32(a, b), c), d) -#define ADD5_32(a, b, c, d, e) ADD32(ADD32(ADD32(ADD32(a, b), c), d), e) - -#define MAJ_AVX(a, b, c) XOR3(AND(a, b), AND(a, c), AND(b, c)) -#define CH_AVX(a, b, c) XOR(AND(a, b), AND(NOT(a), c)) - -#define SIGMA1_AVX(x) XOR3(ROTR32(x, 6), ROTR32(x, 11), ROTR32(x, 25)) -#define SIGMA0_AVX(x) XOR3(ROTR32(x, 2), ROTR32(x, 13), ROTR32(x, 22)) - -#define WSIGMA1_AVX(x) XOR3(ROTR32(x, 17), ROTR32(x, 19), SHIFTR32(x, 10)) -#define WSIGMA0_AVX(x) XOR3(ROTR32(x, 7), ROTR32(x, 18), SHIFTR32(x, 3)) - -#define SHA256ROUND_AVX(a, b, c, d, e, f, g, h, rc, w) \ - T0 = ADD5_32(h, SIGMA1_AVX(e), CH_AVX(e, f, g), _mm256_set1_epi32((int)RC[rc]), w); \ - (d) = ADD32(d, T0); \ - T1 = ADD32(SIGMA0_AVX(a), MAJ_AVX(a, b, c)); \ - (h) = ADD32(T0, T1); - -typedef struct SHA256state { - u256 s[8]; - uint8_t msgblocks[8 * 64]; - unsigned int datalen; - uint64_t msglen; -} sha256ctxx8; - - -void PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_transpose(u256 s[8]); -void PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_sha256_init_frombytes_x8(sha256ctxx8 *ctx, const uint8_t *s, unsigned long long msglen); -void PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_sha256_init8x(sha256ctxx8 *ctx); -void PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_sha256_update8x(sha256ctxx8 *ctx, - const unsigned char *d0, - const unsigned char *d1, - const unsigned char *d2, - const unsigned char *d3, - const unsigned char *d4, - const unsigned char *d5, - const unsigned char *d6, - const unsigned char *d7, - unsigned long long len); -void PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_sha256_final8x(sha256ctxx8 *ctx, - unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7); - -void PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_sha256_transform8x(sha256ctxx8 *ctx, const unsigned char *data); - -void PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_sha256_clone_statex8(sha256ctxx8 *outctx, const sha256ctxx8 *inctx); - - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_avx2/sha256x8.c b/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_avx2/sha256x8.c deleted file mode 100644 index 3c2995aaa0..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_avx2/sha256x8.c +++ /dev/null @@ -1,128 +0,0 @@ -#include - -#include "sha256.h" -#include "sha256avx.h" -#include "sha256x8.h" -#include "utils.h" - -void PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_seed_statex8(sha256ctxx8 *ctx, const unsigned char *pub_seed) { - uint8_t block[PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_BLOCK_BYTES]; - size_t i; - - for (i = 0; i < PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N; ++i) { - block[i] = pub_seed[i]; - } - for (i = PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N; i < PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_BLOCK_BYTES; ++i) { - block[i] = 0; - } - - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_sha256_init8x(ctx); - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_sha256_update8x(ctx, block, block, block, block, block, block, block, block, PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_BLOCK_BYTES); - -} - -/* This provides a wrapper around the internals of 8x parallel SHA256 */ -void PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_sha256x8(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - const unsigned char *in4, - const unsigned char *in5, - const unsigned char *in6, - const unsigned char *in7, unsigned long long inlen) { - sha256ctxx8 ctx; - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_sha256_init8x(&ctx); - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_sha256_update8x(&ctx, in0, in1, in2, in3, in4, in5, in6, in7, inlen); - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_sha256_final8x(&ctx, out0, out1, out2, out3, out4, out5, out6, out7); -} - -/** - * Note that inlen should be sufficiently small that it still allows for - * an array to be allocated on the stack. Typically 'in' is merely a seed. - * Outputs outlen number of bytes - */ -void PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_mgf1x8( - unsigned char *outx8, - unsigned long outlen, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - const unsigned char *in4, - const unsigned char *in5, - const unsigned char *in6, - const unsigned char *in7, - unsigned long inlen) { - unsigned char inbufx8[8 * ((PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_ADDR_BYTES) + 4)]; - unsigned char outbufx8[8 * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_OUTPUT_BYTES]; - unsigned long i; - unsigned int j; - - memcpy(inbufx8 + 0 * (inlen + 4), in0, inlen); - memcpy(inbufx8 + 1 * (inlen + 4), in1, inlen); - memcpy(inbufx8 + 2 * (inlen + 4), in2, inlen); - memcpy(inbufx8 + 3 * (inlen + 4), in3, inlen); - memcpy(inbufx8 + 4 * (inlen + 4), in4, inlen); - memcpy(inbufx8 + 5 * (inlen + 4), in5, inlen); - memcpy(inbufx8 + 6 * (inlen + 4), in6, inlen); - memcpy(inbufx8 + 7 * (inlen + 4), in7, inlen); - - /* While we can fit in at least another full block of SHA256 output.. */ - for (i = 0; (i + 1)*PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_OUTPUT_BYTES <= outlen; i++) { - for (j = 0; j < 8; j++) { - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_ull_to_bytes(inbufx8 + inlen + j * (inlen + 4), 4, i); - } - - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_sha256x8(outx8 + 0 * outlen, - outx8 + 1 * outlen, - outx8 + 2 * outlen, - outx8 + 3 * outlen, - outx8 + 4 * outlen, - outx8 + 5 * outlen, - outx8 + 6 * outlen, - outx8 + 7 * outlen, - inbufx8 + 0 * (inlen + 4), - inbufx8 + 1 * (inlen + 4), - inbufx8 + 2 * (inlen + 4), - inbufx8 + 3 * (inlen + 4), - inbufx8 + 4 * (inlen + 4), - inbufx8 + 5 * (inlen + 4), - inbufx8 + 6 * (inlen + 4), - inbufx8 + 7 * (inlen + 4), inlen + 4); - outx8 += PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_OUTPUT_BYTES; - } - /* Until we cannot anymore, and we fill the remainder. */ - for (j = 0; j < 8; j++) { - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_ull_to_bytes(inbufx8 + inlen + j * (inlen + 4), 4, i); - } - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_sha256x8(outbufx8 + 0 * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 1 * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 2 * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 3 * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 4 * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 5 * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 6 * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 7 * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - inbufx8 + 0 * (inlen + 4), - inbufx8 + 1 * (inlen + 4), - inbufx8 + 2 * (inlen + 4), - inbufx8 + 3 * (inlen + 4), - inbufx8 + 4 * (inlen + 4), - inbufx8 + 5 * (inlen + 4), - inbufx8 + 6 * (inlen + 4), - inbufx8 + 7 * (inlen + 4), inlen + 4); - - for (j = 0; j < 8; j++) { - memcpy(outx8 + j * outlen, - outbufx8 + j * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outlen - i * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_OUTPUT_BYTES); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_avx2/sha256x8.h b/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_avx2/sha256x8.h deleted file mode 100644 index 12aad90ef3..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_avx2/sha256x8.h +++ /dev/null @@ -1,44 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256X8_H -#define PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256X8_H - -#include "sha256avx.h" - -#define PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_BLOCK_BYTES 64 -#define PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_OUTPUT_BYTES 32 /* This does not necessarily equal PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N */ - -/* This provides a wrapper around the internals of 8x parallel SHA256 */ -void PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_sha256x8(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - const unsigned char *in4, - const unsigned char *in5, - const unsigned char *in6, - const unsigned char *in7, unsigned long long inlen); - -/** - * Note that inlen should be sufficiently small that it still allows for - * an array to be allocated on the stack. Typically 'in' is merely a seed. - * Outputs outlen number of bytes - */ -void PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_mgf1x8(unsigned char *outx8, unsigned long outlen, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - const unsigned char *in4, - const unsigned char *in5, - const unsigned char *in6, - const unsigned char *in7, - unsigned long inlen); - -void PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_seed_statex8(sha256ctxx8 *ctx, const unsigned char *pub_seed); -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_avx2/sign.c b/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_avx2/sign.c deleted file mode 100644 index 9fe22a88f8..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_avx2/sign.c +++ /dev/null @@ -1,356 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "api.h" -#include "fors.h" -#include "hash.h" -#include "hash_state.h" -#include "params.h" -#include "randombytes.h" -#include "thash.h" -#include "utils.h" -#include "wots.h" - -/** - * Computes the leaf at a given address. First generates the WOTS key pair, - * then computes leaf by hashing horizontally. - */ -static void wots_gen_leaf(unsigned char *leaf, const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx, const uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - unsigned char pk[PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_WOTS_BYTES]; - uint32_t wots_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_set_type( - wots_addr, PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_set_type( - wots_pk_addr, PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_ADDR_TYPE_WOTSPK); - - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_set_keypair_addr( - wots_addr, addr_idx); - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_wots_gen_pk( - pk, sk_seed, pub_seed, wots_addr, hash_state_seeded); - - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_copy_keypair_addr( - wots_pk_addr, wots_addr); - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_thash_WOTS_LEN( - leaf, pk, pub_seed, wots_pk_addr, hash_state_seeded); -} - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_crypto_sign_secretkeybytes(void) { - return PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_CRYPTO_SECRETKEYBYTES; -} - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_crypto_sign_publickeybytes(void) { - return PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_CRYPTO_PUBLICKEYBYTES; -} - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_crypto_sign_bytes(void) { - return PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_CRYPTO_BYTES; -} - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_crypto_sign_seedbytes(void) { - return PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_CRYPTO_SEEDBYTES; -} - -/* - * Generates an SPX key pair given a seed of length - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed) { - /* We do not need the auth path in key generation, but it simplifies the - code to have just one treehash routine that computes both root and path - in one function. */ - unsigned char auth_path[PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_TREE_HEIGHT * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N]; - uint32_t top_tree_addr[8] = {0}; - hash_state hash_state_seeded; - - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_set_layer_addr( - top_tree_addr, PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_D - 1); - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_set_type( - top_tree_addr, PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_ADDR_TYPE_HASHTREE); - - /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ - memcpy(sk, seed, PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_CRYPTO_SEEDBYTES); - - memcpy(pk, sk + 2 * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N, PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_initialize_hash_function(&hash_state_seeded, pk, sk); - - /* Compute root node of the top-most subtree. */ - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_treehash_TREE_HEIGHT( - sk + 3 * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N, auth_path, sk, sk + 2 * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N, 0, 0, - wots_gen_leaf, top_tree_addr, &hash_state_seeded); - - memcpy(pk + PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N, sk + 3 * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N, PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N); - - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_destroy_hash_function(&hash_state_seeded); - return 0; -} - -/* - * Generates an SPX key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk) { - unsigned char seed[PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_CRYPTO_SEEDBYTES]; - randombytes(seed, PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_CRYPTO_SEEDBYTES); - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_crypto_sign_seed_keypair( - pk, sk, seed); - - return 0; -} - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - const unsigned char *sk_seed = sk; - const unsigned char *sk_prf = sk + PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N; - const unsigned char *pk = sk + 2 * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N; - const unsigned char *pub_seed = pk; - - unsigned char optrand[PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N]; - unsigned char mhash[PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_FORS_MSG_BYTES]; - unsigned char root[PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N]; - uint32_t i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - - hash_state hash_state_seeded; - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_initialize_hash_function( - &hash_state_seeded, - pub_seed, sk_seed); - - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_set_type( - wots_addr, PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_set_type( - tree_addr, PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_ADDR_TYPE_HASHTREE); - - /* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ - randombytes(optrand, PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N); - /* Compute the digest randomization value. */ - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_gen_message_random( - sig, sk_prf, optrand, m, mlen, &hash_state_seeded); - - /* Derive the message digest and leaf index from R, PK and M. */ - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N; - - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_set_keypair_addr( - wots_addr, idx_leaf); - - /* Sign the message hash using FORS. */ - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_fors_sign( - sig, root, mhash, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_FORS_BYTES; - - for (i = 0; i < PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_D; i++) { - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_set_tree_addr(tree_addr, tree); - - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_set_keypair_addr( - wots_addr, idx_leaf); - - /* Compute a WOTS signature. */ - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_wots_sign( - sig, root, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_WOTS_BYTES; - - /* Compute the authentication path for the used WOTS leaf. */ - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_treehash_TREE_HEIGHT( - root, sig, sk_seed, pub_seed, idx_leaf, 0, - wots_gen_leaf, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_TREE_HEIGHT * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_TREE_HEIGHT; - } - - *siglen = PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_BYTES; - - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_destroy_hash_function(&hash_state_seeded); - return 0; -} - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk) { - const unsigned char *pub_seed = pk; - const unsigned char *pub_root = pk + PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N; - unsigned char mhash[PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_FORS_MSG_BYTES]; - unsigned char wots_pk[PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_WOTS_BYTES]; - unsigned char root[PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N]; - unsigned char leaf[PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N]; - unsigned int i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - hash_state hash_state_seeded; - - if (siglen != PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_BYTES) { - return -1; - } - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_initialize_hash_function( - &hash_state_seeded, - pub_seed, NULL); - - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_set_type( - wots_addr, PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_set_type( - tree_addr, PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_ADDR_TYPE_HASHTREE); - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_set_type( - wots_pk_addr, PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_ADDR_TYPE_WOTSPK); - - /* Derive the message digest and leaf index from R || PK || M. */ - /* The additional PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N is a result of the hash domain separator. */ - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N; - - /* Layer correctly defaults to 0, so no need to set_layer_addr */ - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_set_keypair_addr( - wots_addr, idx_leaf); - - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_fors_pk_from_sig( - root, sig, mhash, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_FORS_BYTES; - - /* For each subtree.. */ - for (i = 0; i < PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_D; i++) { - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_set_tree_addr(tree_addr, tree); - - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_set_keypair_addr( - wots_addr, idx_leaf); - - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_copy_keypair_addr( - wots_pk_addr, wots_addr); - - /* The WOTS public key is only correct if the signature was correct. */ - /* Initially, root is the FORS pk, but on subsequent iterations it is - the root of the subtree below the currently processed subtree. */ - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_wots_pk_from_sig( - wots_pk, sig, root, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_WOTS_BYTES; - - /* Compute the leaf node using the WOTS public key. */ - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_thash_WOTS_LEN( - leaf, wots_pk, pub_seed, wots_pk_addr, &hash_state_seeded); - - /* Compute the root node of this subtree. */ - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_compute_root( - root, leaf, idx_leaf, 0, sig, PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_TREE_HEIGHT, - pub_seed, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_TREE_HEIGHT * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_TREE_HEIGHT; - } - - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_destroy_hash_function(&hash_state_seeded); - /* Check if the root node equals the root node in the public key. */ - if (memcmp(root, pub_root, PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N) != 0) { - return -1; - } - - return 0; -} - - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - size_t siglen; - - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_crypto_sign_signature( - sm, &siglen, m, mlen, sk); - - memmove(sm + PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_BYTES, m, mlen); - *smlen = siglen + mlen; - - return 0; -} - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk) { - /* The API caller does not necessarily know what size a signature should be - but SPHINCS+ signatures are always exactly PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_BYTES. */ - if (smlen < PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_BYTES) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - *mlen = smlen - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_BYTES; - - if (PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_crypto_sign_verify( - sm, PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_BYTES, sm + PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_BYTES, *mlen, pk)) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - /* If verification was successful, move the message to the right place. */ - memmove(m, sm + PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_BYTES, *mlen); - - return 0; -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_avx2/thash.h b/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_avx2/thash.h deleted file mode 100644 index bbb9b7e842..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_avx2/thash.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_THASH_H -#define PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_THASH_H - -#include "hash_state.h" - -#include - -void PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_avx2/thash_sha256_simple.c b/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_avx2/thash_sha256_simple.c deleted file mode 100644 index 7f56f86246..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_avx2/thash_sha256_simple.c +++ /dev/null @@ -1,75 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "thash.h" - -#include "sha2.h" -#include "sha256.h" - -/** - * Takes an array of inblocks concatenated arrays of PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N bytes. - */ -static void PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_thash( - unsigned char *out, unsigned char *buf, - const unsigned char *in, unsigned int inblocks, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char outbuf[PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_OUTPUT_BYTES]; - sha256ctx sha2_state; - - (void)pub_seed; /* Suppress an 'unused parameter' warning. */ - - /* Retrieve precomputed state containing pub_seed */ - sha256_inc_ctx_clone(&sha2_state, &hash_state_seeded->x1); - - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_compress_address(buf, addr); - memcpy(buf + PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_ADDR_BYTES, in, inblocks * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N); - - sha256_inc_finalize(outbuf, &sha2_state, buf, PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N); - memcpy(out, outbuf, PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N); -} - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_ADDR_BYTES + 1 * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N]; - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_thash( - out, buf, in, 1, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_ADDR_BYTES + 2 * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N]; - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_thash( - out, buf, in, 2, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_ADDR_BYTES + PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_WOTS_LEN * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N]; - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_thash( - out, buf, in, PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_WOTS_LEN, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_ADDR_BYTES + PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_FORS_TREES * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N]; - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_thash( - out, buf, in, PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_FORS_TREES, pub_seed, addr, hash_state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_avx2/thash_sha256_simplex8.c b/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_avx2/thash_sha256_simplex8.c deleted file mode 100644 index 56297738e4..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_avx2/thash_sha256_simplex8.c +++ /dev/null @@ -1,129 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash_state.h" -#include "params.h" -#include "sha256.h" -#include "sha256avx.h" -#include "sha256x8.h" -#include "thashx8.h" -#include "utils.h" - -/** - * 8-way parallel version of thash; takes 8x as much input and output - */ -static void thashx8(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - const unsigned char *in4, - const unsigned char *in5, - const unsigned char *in6, - const unsigned char *in7, unsigned int inblocks, - const unsigned char *pub_seed, uint32_t addrx8[8 * 8], - uint8_t *bufx8, - const hash_state *state_seeded) { - unsigned char outbufx8[8 * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_OUTPUT_BYTES]; - unsigned int i; - sha256ctxx8 ctx; - - (void)pub_seed; /* Suppress an 'unused parameter' warning. */ - - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_sha256_clone_statex8(&ctx, &state_seeded->x8); - - for (i = 0; i < 8; i++) { - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_compress_address(bufx8 + i * (PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N), - addrx8 + i * 8); - } - - memcpy(bufx8 + PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_ADDR_BYTES + - 0 * (PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N), in0, inblocks * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N); - memcpy(bufx8 + PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_ADDR_BYTES + - 1 * (PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N), in1, inblocks * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N); - memcpy(bufx8 + PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_ADDR_BYTES + - 2 * (PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N), in2, inblocks * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N); - memcpy(bufx8 + PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_ADDR_BYTES + - 3 * (PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N), in3, inblocks * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N); - memcpy(bufx8 + PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_ADDR_BYTES + - 4 * (PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N), in4, inblocks * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N); - memcpy(bufx8 + PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_ADDR_BYTES + - 5 * (PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N), in5, inblocks * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N); - memcpy(bufx8 + PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_ADDR_BYTES + - 6 * (PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N), in6, inblocks * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N); - memcpy(bufx8 + PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_ADDR_BYTES + - 7 * (PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N), in7, inblocks * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N); - - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_sha256_update8x(&ctx, - bufx8 + 0 * (PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N), - bufx8 + 1 * (PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N), - bufx8 + 2 * (PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N), - bufx8 + 3 * (PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N), - bufx8 + 4 * (PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N), - bufx8 + 5 * (PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N), - bufx8 + 6 * (PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N), - bufx8 + 7 * (PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N), - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N); - - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_sha256_final8x(&ctx, - outbufx8 + 0 * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 1 * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 2 * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 3 * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 4 * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 5 * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 6 * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 7 * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_OUTPUT_BYTES); - - memcpy(out0, outbufx8 + 0 * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N); - memcpy(out1, outbufx8 + 1 * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N); - memcpy(out2, outbufx8 + 2 * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N); - memcpy(out3, outbufx8 + 3 * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N); - memcpy(out4, outbufx8 + 4 * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N); - memcpy(out5, outbufx8 + 5 * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N); - memcpy(out6, outbufx8 + 6 * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N); - memcpy(out7, outbufx8 + 7 * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N); -} - -#define thashx8_variant_impl(name, size) \ - void PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_thashx8_##name(unsigned char *out0, \ - unsigned char *out1, \ - unsigned char *out2, \ - unsigned char *out3, \ - unsigned char *out4, \ - unsigned char *out5, \ - unsigned char *out6, \ - unsigned char *out7, \ - const unsigned char *in0, \ - const unsigned char *in1, \ - const unsigned char *in2, \ - const unsigned char *in3, \ - const unsigned char *in4, \ - const unsigned char *in5, \ - const unsigned char *in6, \ - const unsigned char *in7, \ - const unsigned char *pub_seed, \ - uint32_t addrx8[8*8], \ - const hash_state *state_seeded) \ - { \ - const unsigned int inblocks = (size); \ - uint8_t bufx8[8*(PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_SHA256_ADDR_BYTES + (size)*PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N)]; \ - thashx8(out0, out1, out2, out3, out4, out5, out6, out7, \ - in0, in1, in2, in3, in4, in5, in6, in7, inblocks, \ - pub_seed, addrx8, bufx8, state_seeded); \ - } - -thashx8_variant_impl(1, 1) -thashx8_variant_impl(2, 2) -thashx8_variant_impl(WOTS_LEN, PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_WOTS_LEN) -thashx8_variant_impl(FORS_TREES, PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_FORS_TREES) - -#undef thashx8_variant_impl diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_avx2/thashx8.h b/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_avx2/thashx8.h deleted file mode 100644 index d8a5a8da78..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_avx2/thashx8.h +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_THASHX8_H -#define PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_THASHX8_H - -#include - -#include "hash_state.h" -#include "sha256avx.h" - - -#define thashx8_variant(name) \ - void PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_thashx8_##name( \ - unsigned char *out0, \ - unsigned char *out1, \ - unsigned char *out2, \ - unsigned char *out3, \ - unsigned char *out4, \ - unsigned char *out5, \ - unsigned char *out6, \ - unsigned char *out7, \ - const unsigned char *in0, \ - const unsigned char *in1, \ - const unsigned char *in2, \ - const unsigned char *in3, \ - const unsigned char *in4, \ - const unsigned char *in5, \ - const unsigned char *in6, \ - const unsigned char *in7, \ - const unsigned char *pub_seed, \ - uint32_t addrx8[8*8], \ - const hash_state *state_seeded) - - -thashx8_variant(1); -thashx8_variant(2); -thashx8_variant(WOTS_LEN); -thashx8_variant(FORS_TREES); - -#undef thashx8_variant -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_avx2/utils.c b/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_avx2/utils.c deleted file mode 100644 index 1cfe73c559..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_avx2/utils.c +++ /dev/null @@ -1,199 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "hash_state.h" -#include "params.h" -#include "thash.h" -#include "utils.h" - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in) { - - /* Iterate over out in decreasing order, for big-endianness. */ - for (size_t i = outlen; i > 0; i--) { - out[i - 1] = in & 0xff; - in = in >> 8; - } -} - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_bytes_to_ull( - const unsigned char *in, size_t inlen) { - unsigned long long retval = 0; - - for (size_t i = 0; i < inlen; i++) { - retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); - } - return retval; -} - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - uint32_t i; - unsigned char buffer[2 * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N]; - - /* If leaf_idx is odd (last bit = 1), current path element is a right child - and auth_path has to go left. Otherwise it is the other way around. */ - if (leaf_idx & 1) { - memcpy(buffer + PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N, leaf, PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N); - } else { - memcpy(buffer, leaf, PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N); - memcpy(buffer + PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N, auth_path, PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N); - } - auth_path += PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N; - - for (i = 0; i < tree_height - 1; i++) { - leaf_idx >>= 1; - idx_offset >>= 1; - /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_set_tree_height(addr, i + 1); - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_set_tree_index( - addr, leaf_idx + idx_offset); - - /* Pick the right or left neighbor, depending on parity of the node. */ - if (leaf_idx & 1) { - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_thash_2( - buffer + PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N); - } else { - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_thash_2( - buffer, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer + PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N, auth_path, PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N); - } - auth_path += PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N; - } - - /* The last iteration is exceptional; we do not copy an auth_path node. */ - leaf_idx >>= 1; - idx_offset >>= 1; - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_set_tree_height(addr, tree_height); - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_set_tree_index( - addr, leaf_idx + idx_offset); - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_thash_2( - root, buffer, pub_seed, addr, hash_state_seeded); -} - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -static void PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_treehash( - unsigned char *root, unsigned char *auth_path, - unsigned char *stack, unsigned int *heights, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - - unsigned int offset = 0; - uint32_t idx; - uint32_t tree_idx; - - for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { - /* Add the next leaf node to the stack. */ - gen_leaf(stack + offset * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N, - sk_seed, pub_seed, idx + idx_offset, tree_addr, - hash_state_seeded); - offset++; - heights[offset - 1] = 0; - - /* If this is a node we need for the auth path.. */ - if ((leaf_idx ^ 0x1) == idx) { - memcpy(auth_path, stack + (offset - 1)*PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N, PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N); - } - - /* While the top-most nodes are of equal height.. */ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { - /* Compute index of the new node, in the next layer. */ - tree_idx = (idx >> (heights[offset - 1] + 1)); - - /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_set_tree_height( - tree_addr, heights[offset - 1] + 1); - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_set_tree_index( - tree_addr, tree_idx + (idx_offset >> (heights[offset - 1] + 1))); - /* Hash the top-most nodes from the stack together. */ - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_thash_2( - stack + (offset - 2)*PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N, stack + (offset - 2)*PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N, - pub_seed, tree_addr, hash_state_seeded); - offset--; - /* Note that the top-most node is now one layer higher. */ - heights[offset - 1]++; - - /* If this is a node we need for the auth path.. */ - if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_path + heights[offset - 1]*PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N, - stack + (offset - 1)*PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N, PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N); - } - } - } - memcpy(root, stack, PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N); -} - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_FORS_HEIGHT + 1)*PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N]; - unsigned int heights[PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_FORS_HEIGHT + 1]; - - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_FORS_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_TREE_HEIGHT + 1)*PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N]; - unsigned int heights[PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_TREE_HEIGHT + 1]; - - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_TREE_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_avx2/utils.h b/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_avx2/utils.h deleted file mode 100644 index 37037bf3af..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_avx2/utils.h +++ /dev/null @@ -1,64 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_UTILS_H -#define PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_UTILS_H - -#include "hash_state.h" -#include "params.h" -#include -#include - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in); - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_bytes_to_ull( - const unsigned char *in, size_t inlen); - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -void PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_avx2/utilsx8.c b/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_avx2/utilsx8.c deleted file mode 100644 index ede121a831..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_avx2/utilsx8.c +++ /dev/null @@ -1,172 +0,0 @@ -#include - -#include "address.h" -#include "params.h" -#include "thashx8.h" -#include "utils.h" - -#include "utilsx8.h" - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -static void treehashx8(unsigned char *rootx8, unsigned char *auth_pathx8, - unsigned char *stackx8, unsigned int *heights, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t leaf_idx[8], uint32_t idx_offset[8], - uint32_t tree_height, - void (*gen_leafx8)( - unsigned char * /* leaf0 */, - unsigned char * /* leaf1 */, - unsigned char * /* leaf2 */, - unsigned char * /* leaf3 */, - unsigned char * /* leaf4 */, - unsigned char * /* leaf5 */, - unsigned char * /* leaf6 */, - unsigned char * /* leaf7 */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx0 */, - uint32_t /* addr_idx1 */, - uint32_t /* addr_idx2 */, - uint32_t /* addr_idx3 */, - uint32_t /* addr_idx4 */, - uint32_t /* addr_idx5 */, - uint32_t /* addr_idx6 */, - uint32_t /* addr_idx7 */, - const uint32_t[8] /* tree_addr */, - const hash_state * /* state_seeded */), - uint32_t tree_addrx8[8 * 8], - const hash_state *state_seeded) { - unsigned int offset = 0; - uint32_t idx; - uint32_t tree_idx; - unsigned int j; - - for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { - /* Add the next leaf node to the stack. */ - gen_leafx8(stackx8 + 0 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N + offset * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N, - stackx8 + 1 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N + offset * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N, - stackx8 + 2 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N + offset * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N, - stackx8 + 3 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N + offset * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N, - stackx8 + 4 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N + offset * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N, - stackx8 + 5 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N + offset * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N, - stackx8 + 6 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N + offset * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N, - stackx8 + 7 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N + offset * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N, - sk_seed, pub_seed, - idx + idx_offset[0], - idx + idx_offset[1], - idx + idx_offset[2], - idx + idx_offset[3], - idx + idx_offset[4], - idx + idx_offset[5], - idx + idx_offset[6], - idx + idx_offset[7], - tree_addrx8, - state_seeded); - offset++; - heights[offset - 1] = 0; - - /* If this is a node we need for the auth path.. */ - for (j = 0; j < 8; j++) { - if ((leaf_idx[j] ^ 0x1) == idx) { - memcpy(auth_pathx8 + j * tree_height * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N, - stackx8 + j * (tree_height + 1)*PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N + (offset - 1)*PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N, PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N); - } - } - - /* While the top-most nodes are of equal height.. */ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { - /* Compute index of the new node, in the next layer. */ - tree_idx = (idx >> (heights[offset - 1] + 1)); - - /* Set the address of the node we're creating. */ - for (j = 0; j < 8; j++) { - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_set_tree_height(tree_addrx8 + j * 8, heights[offset - 1] + 1); - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_set_tree_index(tree_addrx8 + j * 8, - tree_idx + (idx_offset[j] >> (heights[offset - 1] + 1))); - } - /* Hash the top-most nodes from the stack together. */ - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_thashx8_2(stackx8 + 0 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N, - stackx8 + 1 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N, - stackx8 + 2 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N, - stackx8 + 3 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N, - stackx8 + 4 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N, - stackx8 + 5 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N, - stackx8 + 6 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N, - stackx8 + 7 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N, - stackx8 + 0 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N, - stackx8 + 1 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N, - stackx8 + 2 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N, - stackx8 + 3 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N, - stackx8 + 4 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N, - stackx8 + 5 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N, - stackx8 + 6 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N, - stackx8 + 7 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N, - pub_seed, tree_addrx8, state_seeded); - offset--; - /* Note that the top-most node is now one layer higher. */ - heights[offset - 1]++; - - /* If this is a node we need for the auth path.. */ - for (j = 0; j < 8; j++) { - if (((leaf_idx[j] >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_pathx8 + j * tree_height * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N + heights[offset - 1]*PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N, - stackx8 + j * (tree_height + 1)*PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N + (offset - 1)*PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N, PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N); - } - } - } - } - - for (j = 0; j < 8; j++) { - memcpy(rootx8 + j * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N, stackx8 + j * (tree_height + 1)*PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N, PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N); - } -} - -/* The wrappers below ensure we used fixed-size buffers on the stack (no VLAs) */ - - -#define treehashx8_variant(name, size) \ - void PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_treehashx8_##name( \ - unsigned char *rootx8, unsigned char *auth_pathx8, \ - const unsigned char *sk_seed, const unsigned char *pub_seed, \ - const uint32_t leaf_idx[8], uint32_t idx_offset[8], \ - void (*gen_leafx8)( \ - unsigned char* /* leaf0 */, \ - unsigned char* /* leaf1 */, \ - unsigned char* /* leaf2 */, \ - unsigned char* /* leaf3 */, \ - unsigned char* /* leaf4 */, \ - unsigned char* /* leaf5 */, \ - unsigned char* /* leaf6 */, \ - unsigned char* /* leaf7 */, \ - const unsigned char* /* sk_seed */, \ - const unsigned char* /* pub_seed */, \ - uint32_t /* addr_idx0 */, \ - uint32_t /* addr_idx1 */, \ - uint32_t /* addr_idx2 */, \ - uint32_t /* addr_idx3 */, \ - uint32_t /* addr_idx4 */, \ - uint32_t /* addr_idx5 */, \ - uint32_t /* addr_idx6 */, \ - uint32_t /* addr_idx7 */, \ - const uint32_t[8] /* tree_addr */, \ - const hash_state* /* state_seeded */), \ - uint32_t tree_addrx8[8*8], \ - const hash_state *state_seeded) \ - { \ - const uint32_t tree_height = (size); \ - unsigned char stackx8[8*((size) + 1)*PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N]; \ - unsigned int heights[(size) + 1]; \ - treehashx8(rootx8, auth_pathx8, stackx8, heights, sk_seed, pub_seed, \ - leaf_idx, idx_offset, tree_height, gen_leafx8, tree_addrx8, state_seeded); \ - } - -treehashx8_variant(FORS_HEIGHT, PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_FORS_HEIGHT) - -#undef treehashx8_variant diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_avx2/utilsx8.h b/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_avx2/utilsx8.h deleted file mode 100644 index 9c5e536616..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_avx2/utilsx8.h +++ /dev/null @@ -1,46 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_UTILSX8_H -#define PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_UTILSX8_H - -#include - -#include "hash_state.h" -#include "params.h" - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ - -void PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_treehashx8_FORS_HEIGHT( - unsigned char *rootx8, unsigned char *auth_pathx8, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t leaf_idx[8], uint32_t idx_offset[8], - void (*gen_leafx8)( - unsigned char * /* leaf0 */, - unsigned char * /* leaf1 */, - unsigned char * /* leaf2 */, - unsigned char * /* leaf3 */, - unsigned char * /* leaf4 */, - unsigned char * /* leaf5 */, - unsigned char * /* leaf6 */, - unsigned char * /* leaf7 */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx0 */, - uint32_t /* addr_idx1 */, - uint32_t /* addr_idx2 */, - uint32_t /* addr_idx3 */, - uint32_t /* addr_idx4 */, - uint32_t /* addr_idx5 */, - uint32_t /* addr_idx6 */, - uint32_t /* addr_idx7 */, - const uint32_t[8] /* tree_addr */, - const hash_state * /* state_seeded */), - uint32_t tree_addrx8[8 * 8], - const hash_state *state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_avx2/wots.c b/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_avx2/wots.c deleted file mode 100644 index 5701302228..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_avx2/wots.c +++ /dev/null @@ -1,240 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "hash_state.h" -#include "hashx8.h" -#include "params.h" -#include "thash.h" -#include "thashx8.h" -#include "utils.h" -#include "wots.h" - -// TODO clarify address expectations, and make them more uniform. -// TODO i.e. do we expect types to be set already? -// TODO and do we expect modifications or copies? - -/** - * Computes the starting value for a chain, i.e. the secret key. - * Expects the address to be complete up to the chain address. - */ -static void wots_gen_sk(unsigned char *sk, const unsigned char *sk_seed, - uint32_t wots_addr[8], const hash_state *state_seeded) { - /* Make sure that the hash address is actually zeroed. */ - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_set_hash_addr(wots_addr, 0); - - /* Generate sk element. */ - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_prf_addr(sk, sk_seed, wots_addr, state_seeded); -} - -/** - * 8-way parallel version of wots_gen_sk; expects 8x as much space in sk - */ -static void wots_gen_skx8(unsigned char *skx8, const unsigned char *sk_seed, - uint32_t wots_addrx8[8 * 8]) { - unsigned int j; - - /* Make sure that the hash address is actually zeroed. */ - for (j = 0; j < 8; j++) { - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_set_hash_addr(wots_addrx8 + j * 8, 0); - } - - /* Generate sk element. */ - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_prf_addrx8(skx8 + 0 * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N, - skx8 + 1 * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N, - skx8 + 2 * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N, - skx8 + 3 * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N, - skx8 + 4 * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N, - skx8 + 5 * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N, - skx8 + 6 * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N, - skx8 + 7 * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N, - sk_seed, wots_addrx8); -} - -/** - * Computes the chaining function. - * out and in have to be n-byte arrays. - * - * Interprets in as start-th value of the chain. - * addr has to contain the address of the chain. - */ -static void gen_chain(unsigned char *out, const unsigned char *in, - unsigned int start, unsigned int steps, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *state_seeded) { - uint32_t i; - - /* Initialize out with the value at position 'start'. */ - memcpy(out, in, PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N); - - /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_WOTS_W; i++) { - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_set_hash_addr(addr, i); - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_thash_1(out, out, pub_seed, addr, state_seeded); - } -} - -/** - * 8-way parallel version of gen_chain; expects 8x as much space in out, and - * 8x as much space in inx8. Assumes start and step identical across chains. - */ -static void gen_chainx8(unsigned char *outx8, const unsigned char *inx8, - unsigned int start, unsigned int steps, - const unsigned char *pub_seed, uint32_t addrx8[8 * 8], - const hash_state *state_seeded) { - uint32_t i; - unsigned int j; - - /* Initialize outx8 with the value at position 'start'. */ - memcpy(outx8, inx8, 8 * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N); - - /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_WOTS_W; i++) { - for (j = 0; j < 8; j++) { - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_set_hash_addr(addrx8 + j * 8, i); - } - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_thashx8_1(outx8 + 0 * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N, - outx8 + 1 * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N, - outx8 + 2 * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N, - outx8 + 3 * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N, - outx8 + 4 * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N, - outx8 + 5 * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N, - outx8 + 6 * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N, - outx8 + 7 * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N, - outx8 + 0 * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N, - outx8 + 1 * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N, - outx8 + 2 * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N, - outx8 + 3 * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N, - outx8 + 4 * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N, - outx8 + 5 * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N, - outx8 + 6 * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N, - outx8 + 7 * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N, - pub_seed, addrx8, state_seeded); - } -} - -/** - * base_w algorithm as described in draft. - * Interprets an array of bytes as integers in base w. - * This only works when log_w is a divisor of 8. - */ -static void base_w(unsigned int *output, const int out_len, const unsigned char *input) { - int in = 0; - int out = 0; - unsigned char total = 0; - int bits = 0; - int consumed; - - for (consumed = 0; consumed < out_len; consumed++) { - if (bits == 0) { - total = input[in]; - in++; - bits += 8; - } - bits -= PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_WOTS_LOGW; - output[out] = (unsigned int)(total >> bits) & (PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_WOTS_W - 1); - out++; - } -} - -/* Computes the WOTS+ checksum over a message (in base_w). */ -static void wots_checksum(unsigned int *csum_base_w, const unsigned int *msg_base_w) { - unsigned int csum = 0; - unsigned char csum_bytes[(PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_WOTS_LEN2 * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_WOTS_LOGW + 7) / 8]; - unsigned int i; - - /* Compute checksum. */ - for (i = 0; i < PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_WOTS_LEN1; i++) { - csum += PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_WOTS_W - 1 - msg_base_w[i]; - } - - /* Convert checksum to base_w. */ - /* Make sure expected empty zero bits are the least significant bits. */ - csum = csum << (8 - ((PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_WOTS_LEN2 * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_WOTS_LOGW) % 8)); - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); - base_w(csum_base_w, PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_WOTS_LEN2, csum_bytes); -} - -/* Takes a message and derives the matching chain lengths. */ -static void chain_lengths(unsigned int *lengths, const unsigned char *msg) { - base_w(lengths, PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_WOTS_LEN1, msg); - wots_checksum(lengths + PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_WOTS_LEN1, lengths); -} - -/** - * WOTS key generation. Takes a 32 byte sk_seed, expands it to WOTS private key - * elements and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_wots_gen_pk(unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *state_seeded) { - uint32_t i; - unsigned int j; - - uint32_t addrx8[8 * 8]; - unsigned char pkbuf[8 * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N]; - - for (j = 0; j < 8; j++) { - memcpy(addrx8 + j * 8, addr, sizeof(uint32_t) * 8); - } - - /* The last iteration typically does not have complete set of 4 chains, - but because we use pkbuf, this is not an issue -- we still do as many - in parallel as possible. */ - for (i = 0; i < ((PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_WOTS_LEN + 7) & ~0x7); i += 8) { - for (j = 0; j < 8; j++) { - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_set_chain_addr(addrx8 + j * 8, i + j); - } - wots_gen_skx8(pkbuf, sk_seed, addrx8); - gen_chainx8(pkbuf, pkbuf, 0, PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_WOTS_W - 1, pub_seed, addrx8, state_seeded); - for (j = 0; j < 8; j++) { - if (i + j < PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_WOTS_LEN) { - memcpy(pk + (i + j)*PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N, pkbuf + j * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N, PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N); - } - } - } -} - -/** - * Takes a n-byte message and the 32-byte sk_see to compute a signature 'sig'. - */ -void PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_wots_sign(unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_WOTS_LEN; i++) { - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_set_chain_addr(addr, i); - wots_gen_sk(sig + i * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N, sk_seed, addr, state_seeded); - gen_chain(sig + i * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N, sig + i * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N, 0, lengths[i], pub_seed, addr, state_seeded); - } -} - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_WOTS_LEN; i++) { - PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_set_chain_addr(addr, i); - gen_chain(pk + i * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N, sig + i * PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_N, - lengths[i], PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_WOTS_W - 1 - lengths[i], pub_seed, addr, state_seeded); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_avx2/wots.h b/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_avx2/wots.h deleted file mode 100644 index 4c1af89fc5..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_avx2/wots.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_WOTS_H -#define PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_WOTS_H - -#include "hash_state.h" -#include "params.h" -#include - -/** - * WOTS key generation. Takes a 32 byte seed for the private key, expands it to - * a full WOTS private key and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_wots_gen_pk( - unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -/** - * Takes a n-byte message and the 32-byte seed for the private key to compute a - * signature that is placed at 'sig'. - */ -void PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_wots_sign( - unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *hash_state_seeded); - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHA256256FSIMPLE_AVX2_wots_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_clean/LICENSE b/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_clean/LICENSE deleted file mode 100644 index 670154e353..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_clean/LICENSE +++ /dev/null @@ -1,116 +0,0 @@ -CC0 1.0 Universal - -Statement of Purpose - -The laws of most jurisdictions throughout the world automatically confer -exclusive Copyright and Related Rights (defined below) upon the creator and -subsequent owner(s) (each and all, an "owner") of an original work of -authorship and/or a database (each, a "Work"). - -Certain owners wish to permanently relinquish those rights to a Work for the -purpose of contributing to a commons of creative, cultural and scientific -works ("Commons") that the public can reliably and without fear of later -claims of infringement build upon, modify, incorporate in other works, reuse -and redistribute as freely as possible in any form whatsoever and for any -purposes, including without limitation commercial purposes. These owners may -contribute to the Commons to promote the ideal of a free culture and the -further production of creative, cultural and scientific works, or to gain -reputation or greater distribution for their Work in part through the use and -efforts of others. - -For these and/or other purposes and motivations, and without any expectation -of additional consideration or compensation, the person associating CC0 with a -Work (the "Affirmer"), to the extent that he or she is an owner of Copyright -and Related Rights in the Work, voluntarily elects to apply CC0 to the Work -and publicly distribute the Work under its terms, with knowledge of his or her -Copyright and Related Rights in the Work and the meaning and intended legal -effect of CC0 on those rights. - -1. Copyright and Related Rights. A Work made available under CC0 may be -protected by copyright and related or neighboring rights ("Copyright and -Related Rights"). Copyright and Related Rights include, but are not limited -to, the following: - - i. the right to reproduce, adapt, distribute, perform, display, communicate, - and translate a Work; - - ii. moral rights retained by the original author(s) and/or performer(s); - - iii. publicity and privacy rights pertaining to a person's image or likeness - depicted in a Work; - - iv. rights protecting against unfair competition in regards to a Work, - subject to the limitations in paragraph 4(a), below; - - v. rights protecting the extraction, dissemination, use and reuse of data in - a Work; - - vi. database rights (such as those arising under Directive 96/9/EC of the - European Parliament and of the Council of 11 March 1996 on the legal - protection of databases, and under any national implementation thereof, - including any amended or successor version of such directive); and - - vii. other similar, equivalent or corresponding rights throughout the world - based on applicable law or treaty, and any national implementations thereof. - -2. Waiver. To the greatest extent permitted by, but not in contravention of, -applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and -unconditionally waives, abandons, and surrenders all of Affirmer's Copyright -and Related Rights and associated claims and causes of action, whether now -known or unknown (including existing as well as future claims and causes of -action), in the Work (i) in all territories worldwide, (ii) for the maximum -duration provided by applicable law or treaty (including future time -extensions), (iii) in any current or future medium and for any number of -copies, and (iv) for any purpose whatsoever, including without limitation -commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes -the Waiver for the benefit of each member of the public at large and to the -detriment of Affirmer's heirs and successors, fully intending that such Waiver -shall not be subject to revocation, rescission, cancellation, termination, or -any other legal or equitable action to disrupt the quiet enjoyment of the Work -by the public as contemplated by Affirmer's express Statement of Purpose. - -3. Public License Fallback. Should any part of the Waiver for any reason be -judged legally invalid or ineffective under applicable law, then the Waiver -shall be preserved to the maximum extent permitted taking into account -Affirmer's express Statement of Purpose. In addition, to the extent the Waiver -is so judged Affirmer hereby grants to each affected person a royalty-free, -non transferable, non sublicensable, non exclusive, irrevocable and -unconditional license to exercise Affirmer's Copyright and Related Rights in -the Work (i) in all territories worldwide, (ii) for the maximum duration -provided by applicable law or treaty (including future time extensions), (iii) -in any current or future medium and for any number of copies, and (iv) for any -purpose whatsoever, including without limitation commercial, advertising or -promotional purposes (the "License"). The License shall be deemed effective as -of the date CC0 was applied by Affirmer to the Work. Should any part of the -License for any reason be judged legally invalid or ineffective under -applicable law, such partial invalidity or ineffectiveness shall not -invalidate the remainder of the License, and in such case Affirmer hereby -affirms that he or she will not (i) exercise any of his or her remaining -Copyright and Related Rights in the Work or (ii) assert any associated claims -and causes of action with respect to the Work, in either case contrary to -Affirmer's express Statement of Purpose. - -4. Limitations and Disclaimers. - - a. No trademark or patent rights held by Affirmer are waived, abandoned, - surrendered, licensed or otherwise affected by this document. - - b. Affirmer offers the Work as-is and makes no representations or warranties - of any kind concerning the Work, express, implied, statutory or otherwise, - including without limitation warranties of title, merchantability, fitness - for a particular purpose, non infringement, or the absence of latent or - other defects, accuracy, or the present or absence of errors, whether or not - discoverable, all to the greatest extent permissible under applicable law. - - c. Affirmer disclaims responsibility for clearing rights of other persons - that may apply to the Work or any use thereof, including without limitation - any person's Copyright and Related Rights in the Work. Further, Affirmer - disclaims responsibility for obtaining any necessary consents, permissions - or other rights required for any use of the Work. - - d. Affirmer understands and acknowledges that Creative Commons is not a - party to this document and has no duty or obligation with respect to this - CC0 or use of the Work. - -For more information, please see - diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_clean/address.c b/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_clean/address.c deleted file mode 100644 index 29f4ff701d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_clean/address.c +++ /dev/null @@ -1,78 +0,0 @@ -#include - -#include "address.h" -#include "params.h" -#include "utils.h" - -void PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]) { - int i; - - for (i = 0; i < 8; i++) { - PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_ull_to_bytes( - bytes + i * 4, 4, addr[i]); - } -} - -void PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_set_layer_addr( - uint32_t addr[8], uint32_t layer) { - addr[0] = layer; -} - -void PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_set_tree_addr( - uint32_t addr[8], uint64_t tree) { - addr[1] = 0; - addr[2] = (uint32_t) (tree >> 32); - addr[3] = (uint32_t) tree; -} - -void PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_set_type( - uint32_t addr[8], uint32_t type) { - addr[4] = type; -} - -void PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; -} - -/* These functions are used for OTS addresses. */ - -void PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_set_keypair_addr( - uint32_t addr[8], uint32_t keypair) { - addr[5] = keypair; -} - -void PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; - out[5] = in[5]; -} - -void PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_set_chain_addr( - uint32_t addr[8], uint32_t chain) { - addr[6] = chain; -} - -void PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_set_hash_addr( - uint32_t addr[8], uint32_t hash) { - addr[7] = hash; -} - -/* These functions are used for all hash tree addresses (including FORS). */ - -void PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_set_tree_height( - uint32_t addr[8], uint32_t tree_height) { - addr[6] = tree_height; -} - -void PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_set_tree_index( - uint32_t addr[8], uint32_t tree_index) { - addr[7] = tree_index; -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_clean/address.h b/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_clean/address.h deleted file mode 100644 index 079c0153c3..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_clean/address.h +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_ADDRESS_H -#define PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_ADDRESS_H - -#include - -#define PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_ADDR_TYPE_WOTS 0 -#define PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_ADDR_TYPE_WOTSPK 1 -#define PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_ADDR_TYPE_HASHTREE 2 -#define PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_ADDR_TYPE_FORSTREE 3 -#define PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_ADDR_TYPE_FORSPK 4 - -void PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]); - -void PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_set_layer_addr( - uint32_t addr[8], uint32_t layer); - -void PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_set_tree_addr( - uint32_t addr[8], uint64_t tree); - -void PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_set_type( - uint32_t addr[8], uint32_t type); - -/* Copies the layer and tree part of one address into the other */ -void PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for WOTS and FORS addresses. */ - -void PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_set_keypair_addr( - uint32_t addr[8], uint32_t keypair); - -void PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_set_chain_addr( - uint32_t addr[8], uint32_t chain); - -void PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_set_hash_addr( - uint32_t addr[8], uint32_t hash); - -void PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for all hash tree addresses (including FORS). */ - -void PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_set_tree_height( - uint32_t addr[8], uint32_t tree_height); - -void PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_set_tree_index( - uint32_t addr[8], uint32_t tree_index); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_clean/api.h b/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_clean/api.h deleted file mode 100644 index 57585c80ce..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_clean/api.h +++ /dev/null @@ -1,81 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_API_H -#define PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_API_H - -#include -#include - - - -#define PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_CRYPTO_ALGNAME "SPHINCS+" - -#define PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_CRYPTO_SECRETKEYBYTES 128 -#define PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_CRYPTO_PUBLICKEYBYTES 64 -#define PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_CRYPTO_BYTES 49856 -#define PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_CRYPTO_SEEDBYTES 96 - - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_clean/fors.c b/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_clean/fors.c deleted file mode 100644 index 8794e3e9b1..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_clean/fors.c +++ /dev/null @@ -1,161 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "fors.h" -#include "hash.h" -#include "hash_state.h" -#include "thash.h" -#include "utils.h" - -static void fors_gen_sk(unsigned char *sk, const unsigned char *sk_seed, - uint32_t fors_leaf_addr[8], const hash_state *hash_state_seeded) { - PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_prf_addr( - sk, sk_seed, fors_leaf_addr, hash_state_seeded); -} - -static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, - const unsigned char *pub_seed, - uint32_t fors_leaf_addr[8], - const hash_state *hash_state_seeded) { - PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_thash_1( - leaf, sk, pub_seed, fors_leaf_addr, hash_state_seeded); -} - -static void fors_gen_leaf(unsigned char *leaf, const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx, const uint32_t fors_tree_addr[8], - const hash_state *hash_state_seeded) { - uint32_t fors_leaf_addr[8] = {0}; - - /* Only copy the parts that must be kept in fors_leaf_addr. */ - PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_copy_keypair_addr( - fors_leaf_addr, fors_tree_addr); - PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_set_type( - fors_leaf_addr, PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_set_tree_index( - fors_leaf_addr, addr_idx); - - fors_gen_sk(leaf, sk_seed, fors_leaf_addr, hash_state_seeded); - fors_sk_to_leaf(leaf, leaf, pub_seed, fors_leaf_addr, hash_state_seeded); -} - -/** - * Interprets m as PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_FORS_HEIGHT-bit unsigned integers. - * Assumes m contains at least PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_FORS_TREES bits. - * Assumes indices has space for PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_FORS_TREES integers. - */ -static void message_to_indices(uint32_t *indices, const unsigned char *m) { - unsigned int i, j; - unsigned int offset = 0; - - for (i = 0; i < PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_FORS_TREES; i++) { - indices[i] = 0; - for (j = 0; j < PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_FORS_HEIGHT; j++) { - indices[i] ^= (((uint32_t)m[offset >> 3] >> (offset & 0x7)) & 0x1) << j; - offset++; - } - } -} - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_fors_sign( - unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *hash_state_seeded) { - uint32_t indices[PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_FORS_TREES]; - unsigned char roots[PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_FORS_TREES * PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_N]; - uint32_t fors_tree_addr[8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_copy_keypair_addr( - fors_tree_addr, fors_addr); - PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_copy_keypair_addr( - fors_pk_addr, fors_addr); - - PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_set_type( - fors_tree_addr, PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_set_type( - fors_pk_addr, PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_FORS_TREES; i++) { - idx_offset = i * (1 << PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_FORS_HEIGHT); - - PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_set_tree_height( - fors_tree_addr, 0); - PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_set_tree_index( - fors_tree_addr, indices[i] + idx_offset); - - /* Include the secret key part that produces the selected leaf node. */ - fors_gen_sk(sig, sk_seed, fors_tree_addr, hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_N; - - /* Compute the authentication path for this leaf node. */ - PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_treehash_FORS_HEIGHT( - roots + i * PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_N, sig, sk_seed, pub_seed, - indices[i], idx_offset, fors_gen_leaf, fors_tree_addr, - hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_N * PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_thash_FORS_TREES( - pk, roots, pub_seed, fors_pk_addr, hash_state_seeded); -} - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_fors_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, const uint32_t fors_addr[8], - const hash_state *hash_state_seeded) { - uint32_t indices[PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_FORS_TREES]; - unsigned char roots[PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_FORS_TREES * PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_N]; - unsigned char leaf[PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_N]; - uint32_t fors_tree_addr[8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_copy_keypair_addr(fors_tree_addr, fors_addr); - PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_copy_keypair_addr(fors_pk_addr, fors_addr); - - PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_set_type(fors_tree_addr, PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_set_type(fors_pk_addr, PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_FORS_TREES; i++) { - idx_offset = i * (1 << PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_FORS_HEIGHT); - - PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_set_tree_height(fors_tree_addr, 0); - PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Derive the leaf from the included secret key part. */ - fors_sk_to_leaf(leaf, sig, pub_seed, fors_tree_addr, hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_N; - - /* Derive the corresponding root node of this tree. */ - PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_compute_root(roots + i * PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_N, leaf, indices[i], idx_offset, sig, - PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_FORS_HEIGHT, pub_seed, fors_tree_addr, hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_N * PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_thash_FORS_TREES(pk, roots, pub_seed, fors_pk_addr, hash_state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_clean/fors.h b/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_clean/fors.h deleted file mode 100644 index bb35a14125..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_clean/fors.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_FORS_H -#define PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_FORS_H - -#include - -#include "hash_state.h" -#include "params.h" - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_fors_sign( - unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *hash_state_seeded); - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_fors_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, const uint32_t fors_addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_clean/hash.h b/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_clean/hash.h deleted file mode 100644 index 2a473aa792..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_clean/hash.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_HASH_H -#define PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_HASH_H - -#include "hash_state.h" - -#include -#include - -void PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_initialize_hash_function( - hash_state *hash_state_seeded, - const unsigned char *pub_seed, const unsigned char *sk_seed); - -void PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_destroy_hash_function(hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_clean/hash_sha256.c b/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_clean/hash_sha256.c deleted file mode 100644 index a35f2ac067..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_clean/hash_sha256.c +++ /dev/null @@ -1,162 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "utils.h" - -#include "sha2.h" -#include "sha256.h" - -/* For SHA256, there is no immediate reason to initialize at the start, - so this function is an empty operation. */ -void PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_initialize_hash_function( - hash_state *hash_state_seeded, - const unsigned char *pub_seed, const unsigned char *sk_seed) { - PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_seed_state(hash_state_seeded, pub_seed); - (void)sk_seed; /* Suppress an 'unused parameter' warning. */ -} - -/* Clean up hash state */ -void PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_destroy_hash_function(hash_state *hash_state_seeded) { - sha256_inc_ctx_release(hash_state_seeded); -} - -/* - * Computes PRF(key, addr), given a secret key of PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_N bytes and an address - */ -void PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded) { - unsigned char buf[PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_N + PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_SHA256_ADDR_BYTES]; - unsigned char outbuf[PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_SHA256_OUTPUT_BYTES]; - - memcpy(buf, key, PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_N); - PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_compress_address(buf + PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_N, addr); - - sha256(outbuf, buf, PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_N + PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_SHA256_ADDR_BYTES); - memcpy(out, outbuf, PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_N); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} - -/** - * Computes the message-dependent randomness R, using a secret seed as a key - * for HMAC, and an optional randomization value prefixed to the message. - * This requires m to have at least PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_SHA256_BLOCK_BYTES + PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_N space - * available in front of the pointer, i.e. before the message to use for the - * prefix. This is necessary to prevent having to move the message around (and - * allocate memory for it). - */ -void PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, const hash_state *hash_state_seeded) { - unsigned char buf[PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_SHA256_BLOCK_BYTES + PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_SHA256_OUTPUT_BYTES]; - sha256ctx state; - int i; - - /* This implements HMAC-SHA256 */ - for (i = 0; i < PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_N; i++) { - buf[i] = 0x36 ^ sk_prf[i]; - } - memset(buf + PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_N, 0x36, PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_N); - - sha256_inc_init(&state); - sha256_inc_blocks(&state, buf, 1); - - memcpy(buf, optrand, PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_N); - - /* If optrand + message cannot fill up an entire block */ - if (PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_N + mlen < PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_SHA256_BLOCK_BYTES) { - memcpy(buf + PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_N, m, mlen); - sha256_inc_finalize(buf + PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_SHA256_BLOCK_BYTES, &state, - buf, mlen + PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_N); - } - /* Otherwise first fill a block, so that finalize only uses the message */ - else { - memcpy(buf + PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_N, m, PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_N); - sha256_inc_blocks(&state, buf, 1); - - m += PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_N; - mlen -= PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_N; - sha256_inc_finalize(buf + PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_SHA256_BLOCK_BYTES, &state, m, mlen); - } - - for (i = 0; i < PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_N; i++) { - buf[i] = 0x5c ^ sk_prf[i]; - } - memset(buf + PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_N, 0x5c, PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_N); - - sha256(buf, buf, PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_SHA256_BLOCK_BYTES + PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_SHA256_OUTPUT_BYTES); - memcpy(R, buf, PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_N); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} - -/** - * Computes the message hash using R, the public key, and the message. - * Outputs the message digest and the index of the leaf. The index is split in - * the tree index and the leaf index, for convenient copying to an address. - */ -void PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded) { -#define PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_TREE_BITS (PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_TREE_HEIGHT * (PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_D - 1)) -#define PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_TREE_BYTES ((PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_TREE_BITS + 7) / 8) -#define PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_LEAF_BITS PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_TREE_HEIGHT -#define PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_LEAF_BYTES ((PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_LEAF_BITS + 7) / 8) -#define PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_DGST_BYTES (PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_FORS_MSG_BYTES + PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_TREE_BYTES + PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_LEAF_BYTES) - - unsigned char seed[PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_SHA256_OUTPUT_BYTES + 4]; - - /* Round to nearest multiple of PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_SHA256_BLOCK_BYTES */ -#define PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_INBLOCKS (((PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_N + PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_PK_BYTES + PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_SHA256_BLOCK_BYTES - 1) & \ - -PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_SHA256_BLOCK_BYTES) / PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_SHA256_BLOCK_BYTES) - unsigned char inbuf[PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_INBLOCKS * PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_SHA256_BLOCK_BYTES]; - - unsigned char buf[PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_DGST_BYTES]; - unsigned char *bufp = buf; - sha256ctx state; - - sha256_inc_init(&state); - - memcpy(inbuf, R, PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_N); - memcpy(inbuf + PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_N, pk, PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_PK_BYTES); - - /* If R + pk + message cannot fill up an entire block */ - if (PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_N + PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_PK_BYTES + mlen < PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_INBLOCKS * PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_SHA256_BLOCK_BYTES) { - memcpy(inbuf + PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_N + PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_PK_BYTES, m, mlen); - sha256_inc_finalize(seed, &state, inbuf, PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_N + PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_PK_BYTES + mlen); - } - /* Otherwise first fill a block, so that finalize only uses the message */ - else { - memcpy(inbuf + PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_N + PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_PK_BYTES, m, - PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_INBLOCKS * PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_N - PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_PK_BYTES); - sha256_inc_blocks(&state, inbuf, PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_INBLOCKS); - - m += PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_INBLOCKS * PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_N - PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_PK_BYTES; - mlen -= PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_INBLOCKS * PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_N - PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_PK_BYTES; - sha256_inc_finalize(seed, &state, m, mlen); - } - - /* By doing this in two steps, we prevent hashing the message twice; - otherwise each iteration in MGF1 would hash the message again. */ - PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_mgf1(bufp, PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_DGST_BYTES, seed, PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_SHA256_OUTPUT_BYTES); - - memcpy(digest, bufp, PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_FORS_MSG_BYTES); - bufp += PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_FORS_MSG_BYTES; - - *tree = PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_bytes_to_ull(bufp, PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_TREE_BYTES); - *tree &= (~(uint64_t)0) >> (64 - PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_TREE_BITS); - bufp += PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_TREE_BYTES; - - *leaf_idx = (uint32_t)PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_bytes_to_ull( - bufp, PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_LEAF_BYTES); - *leaf_idx &= (~(uint32_t)0) >> (32 - PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_LEAF_BITS); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_clean/hash_state.h b/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_clean/hash_state.h deleted file mode 100644 index 19fc335e27..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_clean/hash_state.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef SPX_HASH_STATE_H -#define SPX_HASH_STATE_H - -/** - * Defines the type of the hash function state. - * - * Don't be fooled into thinking this instance of SPHINCS+ isn't stateless! - * - * From Section 7.2.2 from the SPHINCS+ round-2 specification: - * - * Each of the instances of the tweakable hash function take PK.seed as its - * first input, which is constant for a given key pair – and, thus, across - * a single signature. This leads to a lot of redundant computation. To remedy - * this, we pad PK.seed to the length of a full 64-byte SHA-256 input block. - * Because of the Merkle-Damgård construction that underlies SHA-256, this - * allows for reuse of the intermediate SHA-256 state after the initial call to - * the compression function which improves performance. - * - * We pass this hash state around in functions, because otherwise we need to - * have a global variable. - */ - -#include "sha2.h" -#define hash_state sha256ctx - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_clean/params.h b/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_clean/params.h deleted file mode 100644 index c4dc2f8e18..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_clean/params.h +++ /dev/null @@ -1,53 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_PARAMS_H -#define PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_PARAMS_H - -/* Hash output length in bytes. */ -#define PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_N 32 -/* Height of the hypertree. */ -#define PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_FULL_HEIGHT 68 -/* Number of subtree layer. */ -#define PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_D 17 -/* FORS tree dimensions. */ -#define PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_FORS_HEIGHT 9 -#define PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_FORS_TREES 35 -/* Winternitz parameter, */ -#define PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_WOTS_W 16 - -/* The hash function is defined by linking a different hash.c file, as opposed - to setting a #define constant. */ - -/* For clarity */ -#define PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_ADDR_BYTES 32 - -/* WOTS parameters. */ -#define PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_WOTS_LOGW 4 - -#define PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_WOTS_LEN1 (8 * PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_N / PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_WOTS_LOGW) - -/* PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#define PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_WOTS_LEN2 3 - -#define PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_WOTS_LEN (PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_WOTS_LEN1 + PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_WOTS_LEN2) -#define PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_WOTS_BYTES (PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_WOTS_LEN * PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_N) -#define PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_WOTS_PK_BYTES PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_WOTS_BYTES - -/* Subtree size. */ -#define PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_TREE_HEIGHT (PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_FULL_HEIGHT / PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_D) - -/* FORS parameters. */ -#define PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_FORS_MSG_BYTES ((PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_FORS_TREES + 7) / 8) -#define PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_FORS_BYTES ((PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_FORS_HEIGHT + 1) * PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_FORS_TREES * PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_N) -#define PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_FORS_PK_BYTES PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_N - -/* Resulting SPX sizes. */ -#define PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_BYTES (PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_N + PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_FORS_BYTES + PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_D * PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_WOTS_BYTES +\ - PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_FULL_HEIGHT * PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_N) -#define PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_PK_BYTES (2 * PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_N) -#define PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_SK_BYTES (2 * PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_N + PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_PK_BYTES) - -/* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ -#define PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_OPTRAND_BYTES 32 - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_clean/sha256.c b/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_clean/sha256.c deleted file mode 100644 index 2c3ff801a2..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_clean/sha256.c +++ /dev/null @@ -1,71 +0,0 @@ -/* Based on the public domain implementation in - * crypto_hash/sha512/ref/ from http://bench.cr.yp.to/supercop.html - * by D. J. Bernstein */ - -#include -#include -#include - -#include "sha2.h" -#include "sha256.h" -#include "utils.h" - -/* - * Compresses an address to a 22-byte sequence. - * This reduces the number of required SHA256 compression calls, as the last - * block of input is padded with at least 65 bits. - */ -void PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_compress_address(unsigned char *out, const uint32_t addr[8]) { - PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_ull_to_bytes(out, 1, addr[0]); /* drop 3 bytes of the layer field */ - PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_ull_to_bytes(out + 1, 4, addr[2]); /* drop the highest tree address word */ - PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_ull_to_bytes(out + 5, 4, addr[3]); - PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_ull_to_bytes(out + 9, 1, addr[4]); /* drop 3 bytes of the type field */ - PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_ull_to_bytes(out + 10, 4, addr[5]); - PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_ull_to_bytes(out + 14, 4, addr[6]); - PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_ull_to_bytes(out + 18, 4, addr[7]); -} - -/** - * Requires 'input_plus_four_bytes' to have 'inlen' + 4 bytes, so that the last - * four bytes can be used for the counter. Typically 'input' is merely a seed. - * Outputs outlen number of bytes - */ -void PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_mgf1( - unsigned char *out, unsigned long outlen, - unsigned char *input_plus_four_bytes, unsigned long inlen) { - unsigned char outbuf[PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_SHA256_OUTPUT_BYTES]; - unsigned long i; - - /* While we can fit in at least another full block of SHA256 output.. */ - for (i = 0; (i + 1)*PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_SHA256_OUTPUT_BYTES <= outlen; i++) { - PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_ull_to_bytes(input_plus_four_bytes + inlen, 4, i); - sha256(out, input_plus_four_bytes, inlen + 4); - out += PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_SHA256_OUTPUT_BYTES; - } - /* Until we cannot anymore, and we fill the remainder. */ - if (outlen > i * PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_SHA256_OUTPUT_BYTES) { - PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_ull_to_bytes(input_plus_four_bytes + inlen, 4, i); - sha256(outbuf, input_plus_four_bytes, inlen + 4); - memcpy(out, outbuf, outlen - i * PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_SHA256_OUTPUT_BYTES); - } -} - - -/** - * Absorb the constant pub_seed using one round of the compression function - * This initializes hash_state_seeded, which can then be reused in thash - **/ -void PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_seed_state(sha256ctx *hash_state_seeded, const unsigned char *pub_seed) { - uint8_t block[PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_SHA256_BLOCK_BYTES]; - size_t i; - - for (i = 0; i < PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_N; ++i) { - block[i] = pub_seed[i]; - } - for (i = PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_N; i < PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_SHA256_BLOCK_BYTES; ++i) { - block[i] = 0; - } - - sha256_inc_init(hash_state_seeded); - sha256_inc_blocks(hash_state_seeded, block, 1); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_clean/sha256.h b/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_clean/sha256.h deleted file mode 100644 index 61bc4374c4..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_clean/sha256.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_SHA256_H -#define PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_SHA256_H - -#define PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_SHA256_BLOCK_BYTES 64 -#define PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_SHA256_OUTPUT_BYTES 32 /* This does not necessarily equal PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_N */ -#define PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_SHA256_ADDR_BYTES 22 - -#include -#include - -#include "sha2.h" - -void PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_compress_address(unsigned char *out, const uint32_t addr[8]); - -void PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_mgf1( - unsigned char *out, unsigned long outlen, - unsigned char *input_plus_four_bytes, unsigned long inlen); - -void PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_seed_state(sha256ctx *hash_state_seeded, const unsigned char *pub_seed); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_clean/sign.c b/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_clean/sign.c deleted file mode 100644 index 5942d0a7e0..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_clean/sign.c +++ /dev/null @@ -1,356 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "api.h" -#include "fors.h" -#include "hash.h" -#include "hash_state.h" -#include "params.h" -#include "randombytes.h" -#include "thash.h" -#include "utils.h" -#include "wots.h" - -/** - * Computes the leaf at a given address. First generates the WOTS key pair, - * then computes leaf by hashing horizontally. - */ -static void wots_gen_leaf(unsigned char *leaf, const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx, const uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - unsigned char pk[PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_WOTS_BYTES]; - uint32_t wots_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_set_type( - wots_addr, PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_set_type( - wots_pk_addr, PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_ADDR_TYPE_WOTSPK); - - PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_set_keypair_addr( - wots_addr, addr_idx); - PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_wots_gen_pk( - pk, sk_seed, pub_seed, wots_addr, hash_state_seeded); - - PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_copy_keypair_addr( - wots_pk_addr, wots_addr); - PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_thash_WOTS_LEN( - leaf, pk, pub_seed, wots_pk_addr, hash_state_seeded); -} - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_crypto_sign_secretkeybytes(void) { - return PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_CRYPTO_SECRETKEYBYTES; -} - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_crypto_sign_publickeybytes(void) { - return PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_CRYPTO_PUBLICKEYBYTES; -} - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_crypto_sign_bytes(void) { - return PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_CRYPTO_BYTES; -} - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_crypto_sign_seedbytes(void) { - return PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_CRYPTO_SEEDBYTES; -} - -/* - * Generates an SPX key pair given a seed of length - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed) { - /* We do not need the auth path in key generation, but it simplifies the - code to have just one treehash routine that computes both root and path - in one function. */ - unsigned char auth_path[PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_TREE_HEIGHT * PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_N]; - uint32_t top_tree_addr[8] = {0}; - hash_state hash_state_seeded; - - PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_set_layer_addr( - top_tree_addr, PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_D - 1); - PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_set_type( - top_tree_addr, PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_ADDR_TYPE_HASHTREE); - - /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ - memcpy(sk, seed, PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_CRYPTO_SEEDBYTES); - - memcpy(pk, sk + 2 * PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_N, PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_initialize_hash_function(&hash_state_seeded, pk, sk); - - /* Compute root node of the top-most subtree. */ - PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_treehash_TREE_HEIGHT( - sk + 3 * PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_N, auth_path, sk, sk + 2 * PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_N, 0, 0, - wots_gen_leaf, top_tree_addr, &hash_state_seeded); - - memcpy(pk + PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_N, sk + 3 * PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_N, PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_N); - - PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_destroy_hash_function(&hash_state_seeded); - return 0; -} - -/* - * Generates an SPX key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk) { - unsigned char seed[PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_CRYPTO_SEEDBYTES]; - randombytes(seed, PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_CRYPTO_SEEDBYTES); - PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_crypto_sign_seed_keypair( - pk, sk, seed); - - return 0; -} - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - const unsigned char *sk_seed = sk; - const unsigned char *sk_prf = sk + PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_N; - const unsigned char *pk = sk + 2 * PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_N; - const unsigned char *pub_seed = pk; - - unsigned char optrand[PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_N]; - unsigned char mhash[PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_FORS_MSG_BYTES]; - unsigned char root[PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_N]; - uint32_t i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - - hash_state hash_state_seeded; - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_initialize_hash_function( - &hash_state_seeded, - pub_seed, sk_seed); - - PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_set_type( - wots_addr, PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_set_type( - tree_addr, PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_ADDR_TYPE_HASHTREE); - - /* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ - randombytes(optrand, PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_N); - /* Compute the digest randomization value. */ - PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_gen_message_random( - sig, sk_prf, optrand, m, mlen, &hash_state_seeded); - - /* Derive the message digest and leaf index from R, PK and M. */ - PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_N; - - PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); - - /* Sign the message hash using FORS. */ - PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_fors_sign( - sig, root, mhash, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_FORS_BYTES; - - for (i = 0; i < PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_D; i++) { - PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_set_tree_addr(tree_addr, tree); - - PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); - - /* Compute a WOTS signature. */ - PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_wots_sign( - sig, root, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_WOTS_BYTES; - - /* Compute the authentication path for the used WOTS leaf. */ - PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_treehash_TREE_HEIGHT( - root, sig, sk_seed, pub_seed, idx_leaf, 0, - wots_gen_leaf, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_TREE_HEIGHT * PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_TREE_HEIGHT; - } - - *siglen = PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_BYTES; - - PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_destroy_hash_function(&hash_state_seeded); - return 0; -} - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk) { - const unsigned char *pub_seed = pk; - const unsigned char *pub_root = pk + PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_N; - unsigned char mhash[PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_FORS_MSG_BYTES]; - unsigned char wots_pk[PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_WOTS_BYTES]; - unsigned char root[PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_N]; - unsigned char leaf[PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_N]; - unsigned int i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - hash_state hash_state_seeded; - - if (siglen != PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_BYTES) { - return -1; - } - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_initialize_hash_function( - &hash_state_seeded, - pub_seed, NULL); - - PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_set_type( - wots_addr, PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_set_type( - tree_addr, PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_ADDR_TYPE_HASHTREE); - PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_set_type( - wots_pk_addr, PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_ADDR_TYPE_WOTSPK); - - /* Derive the message digest and leaf index from R || PK || M. */ - /* The additional PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_N is a result of the hash domain separator. */ - PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_N; - - /* Layer correctly defaults to 0, so no need to set_layer_addr */ - PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); - - PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_fors_pk_from_sig( - root, sig, mhash, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_FORS_BYTES; - - /* For each subtree.. */ - for (i = 0; i < PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_D; i++) { - PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_set_tree_addr(tree_addr, tree); - - PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); - - PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_copy_keypair_addr( - wots_pk_addr, wots_addr); - - /* The WOTS public key is only correct if the signature was correct. */ - /* Initially, root is the FORS pk, but on subsequent iterations it is - the root of the subtree below the currently processed subtree. */ - PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_wots_pk_from_sig( - wots_pk, sig, root, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_WOTS_BYTES; - - /* Compute the leaf node using the WOTS public key. */ - PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_thash_WOTS_LEN( - leaf, wots_pk, pub_seed, wots_pk_addr, &hash_state_seeded); - - /* Compute the root node of this subtree. */ - PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_compute_root( - root, leaf, idx_leaf, 0, sig, PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_TREE_HEIGHT, - pub_seed, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_TREE_HEIGHT * PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_TREE_HEIGHT; - } - - PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_destroy_hash_function(&hash_state_seeded); - /* Check if the root node equals the root node in the public key. */ - if (memcmp(root, pub_root, PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_N) != 0) { - return -1; - } - - return 0; -} - - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - size_t siglen; - - PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_crypto_sign_signature( - sm, &siglen, m, mlen, sk); - - memmove(sm + PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_BYTES, m, mlen); - *smlen = siglen + mlen; - - return 0; -} - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk) { - /* The API caller does not necessarily know what size a signature should be - but SPHINCS+ signatures are always exactly PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_BYTES. */ - if (smlen < PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_BYTES) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - *mlen = smlen - PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_BYTES; - - if (PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_crypto_sign_verify( - sm, PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_BYTES, sm + PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_BYTES, *mlen, pk)) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - /* If verification was successful, move the message to the right place. */ - memmove(m, sm + PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_BYTES, *mlen); - - return 0; -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_clean/thash.h b/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_clean/thash.h deleted file mode 100644 index 2de4347f26..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_clean/thash.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_THASH_H -#define PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_THASH_H - -#include "hash_state.h" - -#include - -void PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_clean/thash_sha256_simple.c b/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_clean/thash_sha256_simple.c deleted file mode 100644 index 333a971220..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_clean/thash_sha256_simple.c +++ /dev/null @@ -1,75 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "thash.h" - -#include "sha2.h" -#include "sha256.h" - -/** - * Takes an array of inblocks concatenated arrays of PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_N bytes. - */ -static void PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_thash( - unsigned char *out, unsigned char *buf, - const unsigned char *in, unsigned int inblocks, - const unsigned char *pub_seed, uint32_t addr[8], - const sha256ctx *hash_state_seeded) { - - unsigned char outbuf[PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_SHA256_OUTPUT_BYTES]; - sha256ctx sha2_state; - - (void)pub_seed; /* Suppress an 'unused parameter' warning. */ - - /* Retrieve precomputed state containing pub_seed */ - sha256_inc_ctx_clone(&sha2_state, hash_state_seeded); - - PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_compress_address(buf, addr); - memcpy(buf + PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_SHA256_ADDR_BYTES, in, inblocks * PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_N); - - sha256_inc_finalize(outbuf, &sha2_state, buf, PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_N); - memcpy(out, outbuf, PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_N); -} - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const sha256ctx *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_SHA256_ADDR_BYTES + 1 * PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_N]; - PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_thash( - out, buf, in, 1, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const sha256ctx *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_SHA256_ADDR_BYTES + 2 * PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_N]; - PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_thash( - out, buf, in, 2, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const sha256ctx *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_SHA256_ADDR_BYTES + PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_WOTS_LEN * PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_N]; - PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_thash( - out, buf, in, PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_WOTS_LEN, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const sha256ctx *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_SHA256_ADDR_BYTES + PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_FORS_TREES * PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_N]; - PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_thash( - out, buf, in, PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_FORS_TREES, pub_seed, addr, hash_state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_clean/utils.c b/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_clean/utils.c deleted file mode 100644 index 6dc29c0531..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_clean/utils.c +++ /dev/null @@ -1,199 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "hash_state.h" -#include "params.h" -#include "thash.h" -#include "utils.h" - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in) { - - /* Iterate over out in decreasing order, for big-endianness. */ - for (size_t i = outlen; i > 0; i--) { - out[i - 1] = in & 0xff; - in = in >> 8; - } -} - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_bytes_to_ull( - const unsigned char *in, size_t inlen) { - unsigned long long retval = 0; - - for (size_t i = 0; i < inlen; i++) { - retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); - } - return retval; -} - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - uint32_t i; - unsigned char buffer[2 * PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_N]; - - /* If leaf_idx is odd (last bit = 1), current path element is a right child - and auth_path has to go left. Otherwise it is the other way around. */ - if (leaf_idx & 1) { - memcpy(buffer + PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_N, leaf, PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_N); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_N); - } else { - memcpy(buffer, leaf, PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_N); - memcpy(buffer + PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_N, auth_path, PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_N); - } - auth_path += PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_N; - - for (i = 0; i < tree_height - 1; i++) { - leaf_idx >>= 1; - idx_offset >>= 1; - /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_set_tree_height(addr, i + 1); - PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_set_tree_index( - addr, leaf_idx + idx_offset); - - /* Pick the right or left neighbor, depending on parity of the node. */ - if (leaf_idx & 1) { - PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_thash_2( - buffer + PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_N, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_N); - } else { - PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_thash_2( - buffer, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer + PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_N, auth_path, PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_N); - } - auth_path += PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_N; - } - - /* The last iteration is exceptional; we do not copy an auth_path node. */ - leaf_idx >>= 1; - idx_offset >>= 1; - PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_set_tree_height(addr, tree_height); - PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_set_tree_index( - addr, leaf_idx + idx_offset); - PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_thash_2( - root, buffer, pub_seed, addr, hash_state_seeded); -} - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -static void PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_treehash( - unsigned char *root, unsigned char *auth_path, - unsigned char *stack, unsigned int *heights, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - - unsigned int offset = 0; - uint32_t idx; - uint32_t tree_idx; - - for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { - /* Add the next leaf node to the stack. */ - gen_leaf(stack + offset * PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_N, - sk_seed, pub_seed, idx + idx_offset, tree_addr, - hash_state_seeded); - offset++; - heights[offset - 1] = 0; - - /* If this is a node we need for the auth path.. */ - if ((leaf_idx ^ 0x1) == idx) { - memcpy(auth_path, stack + (offset - 1)*PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_N, PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_N); - } - - /* While the top-most nodes are of equal height.. */ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { - /* Compute index of the new node, in the next layer. */ - tree_idx = (idx >> (heights[offset - 1] + 1)); - - /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_set_tree_height( - tree_addr, heights[offset - 1] + 1); - PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_set_tree_index( - tree_addr, tree_idx + (idx_offset >> (heights[offset - 1] + 1))); - /* Hash the top-most nodes from the stack together. */ - PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_thash_2( - stack + (offset - 2)*PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_N, stack + (offset - 2)*PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_N, - pub_seed, tree_addr, hash_state_seeded); - offset--; - /* Note that the top-most node is now one layer higher. */ - heights[offset - 1]++; - - /* If this is a node we need for the auth path.. */ - if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_path + heights[offset - 1]*PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_N, - stack + (offset - 1)*PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_N, PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_N); - } - } - } - memcpy(root, stack, PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_N); -} - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_FORS_HEIGHT + 1)*PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_N]; - unsigned int heights[PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_FORS_HEIGHT + 1]; - - PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_FORS_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_TREE_HEIGHT + 1)*PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_N]; - unsigned int heights[PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_TREE_HEIGHT + 1]; - - PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_TREE_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_clean/utils.h b/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_clean/utils.h deleted file mode 100644 index 6b35879b24..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_clean/utils.h +++ /dev/null @@ -1,64 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_UTILS_H -#define PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_UTILS_H - -#include "hash_state.h" -#include "params.h" -#include -#include - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in); - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_bytes_to_ull( - const unsigned char *in, size_t inlen); - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -void PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_clean/wots.c b/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_clean/wots.c deleted file mode 100644 index 0cc6e96464..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_clean/wots.c +++ /dev/null @@ -1,167 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "hash_state.h" -#include "params.h" -#include "thash.h" -#include "utils.h" -#include "wots.h" - -// TODO clarify address expectations, and make them more uniform. -// TODO i.e. do we expect types to be set already? -// TODO and do we expect modifications or copies? - -/** - * Computes the starting value for a chain, i.e. the secret key. - * Expects the address to be complete up to the chain address. - */ -static void wots_gen_sk(unsigned char *sk, const unsigned char *sk_seed, - uint32_t wots_addr[8], - const hash_state *hash_state_seeded) { - /* Make sure that the hash address is actually zeroed. */ - PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_set_hash_addr(wots_addr, 0); - - /* Generate sk element. */ - PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_prf_addr(sk, sk_seed, wots_addr, hash_state_seeded); -} - -/** - * Computes the chaining function. - * out and in have to be n-byte arrays. - * - * Interprets in as start-th value of the chain. - * addr has to contain the address of the chain. - */ -static void gen_chain(unsigned char *out, const unsigned char *in, - unsigned int start, unsigned int steps, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - uint32_t i; - - /* Initialize out with the value at position 'start'. */ - memcpy(out, in, PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_N); - - /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_WOTS_W; i++) { - PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_set_hash_addr(addr, i); - PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_thash_1( - out, out, pub_seed, addr, hash_state_seeded); - } -} - -/** - * base_w algorithm as described in draft. - * Interprets an array of bytes as integers in base w. - * This only works when log_w is a divisor of 8. - */ -static void base_w(unsigned int *output, const size_t out_len, - const unsigned char *input) { - size_t in = 0; - size_t out = 0; - unsigned char total = 0; - unsigned int bits = 0; - size_t consumed; - - for (consumed = 0; consumed < out_len; consumed++) { - if (bits == 0) { - total = input[in]; - in++; - bits += 8; - } - bits -= PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_WOTS_LOGW; - output[out] = (unsigned int)((total >> bits) & (PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_WOTS_W - 1)); - out++; - } -} - -/* Computes the WOTS+ checksum over a message (in base_w). */ -static void wots_checksum(unsigned int *csum_base_w, - const unsigned int *msg_base_w) { - unsigned int csum = 0; - unsigned char csum_bytes[(PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_WOTS_LEN2 * PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_WOTS_LOGW + 7) / 8]; - unsigned int i; - - /* Compute checksum. */ - for (i = 0; i < PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_WOTS_LEN1; i++) { - csum += PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_WOTS_W - 1 - msg_base_w[i]; - } - - /* Convert checksum to base_w. */ - /* Make sure expected empty zero bits are the least significant bits. */ - csum = csum << (8 - ((PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_WOTS_LEN2 * PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_WOTS_LOGW) % 8)); - PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_ull_to_bytes( - csum_bytes, sizeof(csum_bytes), csum); - base_w(csum_base_w, PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_WOTS_LEN2, csum_bytes); -} - -/* Takes a message and derives the matching chain lengths. */ -static void chain_lengths(unsigned int *lengths, const unsigned char *msg) { - base_w(lengths, PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_WOTS_LEN1, msg); - wots_checksum(lengths + PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_WOTS_LEN1, lengths); -} - -/** - * WOTS key generation. Takes a 32 byte sk_seed, expands it to WOTS private key - * elements and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_wots_gen_pk( - unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - uint32_t i; - - for (i = 0; i < PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_WOTS_LEN; i++) { - PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_set_chain_addr(addr, i); - wots_gen_sk(pk + i * PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_N, sk_seed, addr, hash_state_seeded); - gen_chain(pk + i * PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_N, pk + i * PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_N, - 0, PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_WOTS_W - 1, pub_seed, addr, hash_state_seeded); - } -} - -/** - * Takes a n-byte message and the 32-byte sk_see to compute a signature 'sig'. - */ -void PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_wots_sign( - unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *hash_state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_WOTS_LEN; i++) { - PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_set_chain_addr(addr, i); - wots_gen_sk(sig + i * PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_N, sk_seed, addr, hash_state_seeded); - gen_chain(sig + i * PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_N, sig + i * PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_N, 0, lengths[i], pub_seed, addr, hash_state_seeded); - } -} - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_wots_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_WOTS_LEN; i++) { - PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_set_chain_addr(addr, i); - gen_chain(pk + i * PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_N, sig + i * PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_N, - lengths[i], PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_WOTS_W - 1 - lengths[i], pub_seed, addr, - hash_state_seeded); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_clean/wots.h b/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_clean/wots.h deleted file mode 100644 index 124fe5beae..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256f-simple_clean/wots.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_WOTS_H -#define PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_WOTS_H - -#include "hash_state.h" -#include "params.h" -#include - -/** - * WOTS key generation. Takes a 32 byte seed for the private key, expands it to - * a full WOTS private key and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_wots_gen_pk( - unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -/** - * Takes a n-byte message and the 32-byte seed for the private key to compute a - * signature that is placed at 'sig'. - */ -void PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_wots_sign( - unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *hash_state_seeded); - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_wots_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_avx2/LICENSE b/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_avx2/LICENSE deleted file mode 100644 index 670154e353..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_avx2/LICENSE +++ /dev/null @@ -1,116 +0,0 @@ -CC0 1.0 Universal - -Statement of Purpose - -The laws of most jurisdictions throughout the world automatically confer -exclusive Copyright and Related Rights (defined below) upon the creator and -subsequent owner(s) (each and all, an "owner") of an original work of -authorship and/or a database (each, a "Work"). - -Certain owners wish to permanently relinquish those rights to a Work for the -purpose of contributing to a commons of creative, cultural and scientific -works ("Commons") that the public can reliably and without fear of later -claims of infringement build upon, modify, incorporate in other works, reuse -and redistribute as freely as possible in any form whatsoever and for any -purposes, including without limitation commercial purposes. These owners may -contribute to the Commons to promote the ideal of a free culture and the -further production of creative, cultural and scientific works, or to gain -reputation or greater distribution for their Work in part through the use and -efforts of others. - -For these and/or other purposes and motivations, and without any expectation -of additional consideration or compensation, the person associating CC0 with a -Work (the "Affirmer"), to the extent that he or she is an owner of Copyright -and Related Rights in the Work, voluntarily elects to apply CC0 to the Work -and publicly distribute the Work under its terms, with knowledge of his or her -Copyright and Related Rights in the Work and the meaning and intended legal -effect of CC0 on those rights. - -1. Copyright and Related Rights. A Work made available under CC0 may be -protected by copyright and related or neighboring rights ("Copyright and -Related Rights"). Copyright and Related Rights include, but are not limited -to, the following: - - i. the right to reproduce, adapt, distribute, perform, display, communicate, - and translate a Work; - - ii. moral rights retained by the original author(s) and/or performer(s); - - iii. publicity and privacy rights pertaining to a person's image or likeness - depicted in a Work; - - iv. rights protecting against unfair competition in regards to a Work, - subject to the limitations in paragraph 4(a), below; - - v. rights protecting the extraction, dissemination, use and reuse of data in - a Work; - - vi. database rights (such as those arising under Directive 96/9/EC of the - European Parliament and of the Council of 11 March 1996 on the legal - protection of databases, and under any national implementation thereof, - including any amended or successor version of such directive); and - - vii. other similar, equivalent or corresponding rights throughout the world - based on applicable law or treaty, and any national implementations thereof. - -2. Waiver. To the greatest extent permitted by, but not in contravention of, -applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and -unconditionally waives, abandons, and surrenders all of Affirmer's Copyright -and Related Rights and associated claims and causes of action, whether now -known or unknown (including existing as well as future claims and causes of -action), in the Work (i) in all territories worldwide, (ii) for the maximum -duration provided by applicable law or treaty (including future time -extensions), (iii) in any current or future medium and for any number of -copies, and (iv) for any purpose whatsoever, including without limitation -commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes -the Waiver for the benefit of each member of the public at large and to the -detriment of Affirmer's heirs and successors, fully intending that such Waiver -shall not be subject to revocation, rescission, cancellation, termination, or -any other legal or equitable action to disrupt the quiet enjoyment of the Work -by the public as contemplated by Affirmer's express Statement of Purpose. - -3. Public License Fallback. Should any part of the Waiver for any reason be -judged legally invalid or ineffective under applicable law, then the Waiver -shall be preserved to the maximum extent permitted taking into account -Affirmer's express Statement of Purpose. In addition, to the extent the Waiver -is so judged Affirmer hereby grants to each affected person a royalty-free, -non transferable, non sublicensable, non exclusive, irrevocable and -unconditional license to exercise Affirmer's Copyright and Related Rights in -the Work (i) in all territories worldwide, (ii) for the maximum duration -provided by applicable law or treaty (including future time extensions), (iii) -in any current or future medium and for any number of copies, and (iv) for any -purpose whatsoever, including without limitation commercial, advertising or -promotional purposes (the "License"). The License shall be deemed effective as -of the date CC0 was applied by Affirmer to the Work. Should any part of the -License for any reason be judged legally invalid or ineffective under -applicable law, such partial invalidity or ineffectiveness shall not -invalidate the remainder of the License, and in such case Affirmer hereby -affirms that he or she will not (i) exercise any of his or her remaining -Copyright and Related Rights in the Work or (ii) assert any associated claims -and causes of action with respect to the Work, in either case contrary to -Affirmer's express Statement of Purpose. - -4. Limitations and Disclaimers. - - a. No trademark or patent rights held by Affirmer are waived, abandoned, - surrendered, licensed or otherwise affected by this document. - - b. Affirmer offers the Work as-is and makes no representations or warranties - of any kind concerning the Work, express, implied, statutory or otherwise, - including without limitation warranties of title, merchantability, fitness - for a particular purpose, non infringement, or the absence of latent or - other defects, accuracy, or the present or absence of errors, whether or not - discoverable, all to the greatest extent permissible under applicable law. - - c. Affirmer disclaims responsibility for clearing rights of other persons - that may apply to the Work or any use thereof, including without limitation - any person's Copyright and Related Rights in the Work. Further, Affirmer - disclaims responsibility for obtaining any necessary consents, permissions - or other rights required for any use of the Work. - - d. Affirmer understands and acknowledges that Creative Commons is not a - party to this document and has no duty or obligation with respect to this - CC0 or use of the Work. - -For more information, please see - diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_avx2/address.c b/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_avx2/address.c deleted file mode 100644 index d9f2f525e0..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_avx2/address.c +++ /dev/null @@ -1,78 +0,0 @@ -#include - -#include "address.h" -#include "params.h" -#include "utils.h" - -void PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]) { - int i; - - for (i = 0; i < 8; i++) { - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_ull_to_bytes( - bytes + i * 4, 4, addr[i]); - } -} - -void PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_set_layer_addr( - uint32_t addr[8], uint32_t layer) { - addr[0] = layer; -} - -void PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_set_tree_addr( - uint32_t addr[8], uint64_t tree) { - addr[1] = 0; - addr[2] = (uint32_t) (tree >> 32); - addr[3] = (uint32_t) tree; -} - -void PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_set_type( - uint32_t addr[8], uint32_t type) { - addr[4] = type; -} - -void PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; -} - -/* These functions are used for OTS addresses. */ - -void PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_set_keypair_addr( - uint32_t addr[8], uint32_t keypair) { - addr[5] = keypair; -} - -void PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; - out[5] = in[5]; -} - -void PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_set_chain_addr( - uint32_t addr[8], uint32_t chain) { - addr[6] = chain; -} - -void PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_set_hash_addr( - uint32_t addr[8], uint32_t hash) { - addr[7] = hash; -} - -/* These functions are used for all hash tree addresses (including FORS). */ - -void PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_set_tree_height( - uint32_t addr[8], uint32_t tree_height) { - addr[6] = tree_height; -} - -void PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_set_tree_index( - uint32_t addr[8], uint32_t tree_index) { - addr[7] = tree_index; -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_avx2/address.h b/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_avx2/address.h deleted file mode 100644 index 4c046f9c94..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_avx2/address.h +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_ADDRESS_H -#define PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_ADDRESS_H - -#include - -#define PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_ADDR_TYPE_WOTS 0 -#define PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_ADDR_TYPE_WOTSPK 1 -#define PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_ADDR_TYPE_HASHTREE 2 -#define PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_ADDR_TYPE_FORSTREE 3 -#define PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_ADDR_TYPE_FORSPK 4 - -void PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]); - -void PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_set_layer_addr( - uint32_t addr[8], uint32_t layer); - -void PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_set_tree_addr( - uint32_t addr[8], uint64_t tree); - -void PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_set_type( - uint32_t addr[8], uint32_t type); - -/* Copies the layer and tree part of one address into the other */ -void PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for WOTS and FORS addresses. */ - -void PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_set_keypair_addr( - uint32_t addr[8], uint32_t keypair); - -void PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_set_chain_addr( - uint32_t addr[8], uint32_t chain); - -void PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_set_hash_addr( - uint32_t addr[8], uint32_t hash); - -void PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for all hash tree addresses (including FORS). */ - -void PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_set_tree_height( - uint32_t addr[8], uint32_t tree_height); - -void PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_set_tree_index( - uint32_t addr[8], uint32_t tree_index); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_avx2/api.h b/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_avx2/api.h deleted file mode 100644 index e2a4910c22..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_avx2/api.h +++ /dev/null @@ -1,81 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_API_H -#define PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_API_H - -#include -#include - - - -#define PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_CRYPTO_ALGNAME "SPHINCS+" - -#define PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_CRYPTO_SECRETKEYBYTES 128 -#define PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_CRYPTO_PUBLICKEYBYTES 64 -#define PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_CRYPTO_BYTES 29792 -#define PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_CRYPTO_SEEDBYTES 96 - - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_avx2/fors.c b/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_avx2/fors.c deleted file mode 100644 index 4be789b02d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_avx2/fors.c +++ /dev/null @@ -1,240 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "fors.h" -#include "hash.h" -#include "hashx8.h" -#include "thash.h" -#include "thashx8.h" -#include "utils.h" -#include "utilsx8.h" - -static void fors_gen_skx8(unsigned char *sk0, - unsigned char *sk1, - unsigned char *sk2, - unsigned char *sk3, - unsigned char *sk4, - unsigned char *sk5, - unsigned char *sk6, - unsigned char *sk7, const unsigned char *sk_seed, - uint32_t fors_leaf_addrx8[8 * 8]) { - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_prf_addrx8(sk0, sk1, sk2, sk3, sk4, sk5, sk6, sk7, - sk_seed, fors_leaf_addrx8); -} - -static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, - const unsigned char *pub_seed, - uint32_t fors_leaf_addr[8], - const hash_state *state_seeded) { - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_thash_1(leaf, sk, pub_seed, fors_leaf_addr, state_seeded); -} - -static void fors_sk_to_leafx8(unsigned char *leaf0, - unsigned char *leaf1, - unsigned char *leaf2, - unsigned char *leaf3, - unsigned char *leaf4, - unsigned char *leaf5, - unsigned char *leaf6, - unsigned char *leaf7, - const unsigned char *sk0, - const unsigned char *sk1, - const unsigned char *sk2, - const unsigned char *sk3, - const unsigned char *sk4, - const unsigned char *sk5, - const unsigned char *sk6, - const unsigned char *sk7, - const unsigned char *pub_seed, - uint32_t fors_leaf_addrx8[8 * 8], - const hash_state *state_seeded) { - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_thashx8_1(leaf0, leaf1, leaf2, leaf3, leaf4, leaf5, leaf6, leaf7, - sk0, sk1, sk2, sk3, sk4, sk5, sk6, sk7, - pub_seed, fors_leaf_addrx8, state_seeded); -} - -static void fors_gen_leafx8(unsigned char *leaf0, - unsigned char *leaf1, - unsigned char *leaf2, - unsigned char *leaf3, - unsigned char *leaf4, - unsigned char *leaf5, - unsigned char *leaf6, - unsigned char *leaf7, - const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx0, - uint32_t addr_idx1, - uint32_t addr_idx2, - uint32_t addr_idx3, - uint32_t addr_idx4, - uint32_t addr_idx5, - uint32_t addr_idx6, - uint32_t addr_idx7, - const uint32_t fors_tree_addr[8], - const hash_state *state_seeded) { - uint32_t fors_leaf_addrx8[8 * 8] = {0}; - unsigned int j; - - /* Only copy the parts that must be kept in fors_leaf_addrx8. */ - for (j = 0; j < 8; j++) { - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_copy_keypair_addr(fors_leaf_addrx8 + j * 8, fors_tree_addr); - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_set_type(fors_leaf_addrx8 + j * 8, PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_ADDR_TYPE_FORSTREE); - } - - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_set_tree_index(fors_leaf_addrx8 + 0 * 8, addr_idx0); - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_set_tree_index(fors_leaf_addrx8 + 1 * 8, addr_idx1); - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_set_tree_index(fors_leaf_addrx8 + 2 * 8, addr_idx2); - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_set_tree_index(fors_leaf_addrx8 + 3 * 8, addr_idx3); - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_set_tree_index(fors_leaf_addrx8 + 4 * 8, addr_idx4); - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_set_tree_index(fors_leaf_addrx8 + 5 * 8, addr_idx5); - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_set_tree_index(fors_leaf_addrx8 + 6 * 8, addr_idx6); - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_set_tree_index(fors_leaf_addrx8 + 7 * 8, addr_idx7); - - fors_gen_skx8(leaf0, leaf1, leaf2, leaf3, leaf4, leaf5, leaf6, leaf7, - sk_seed, fors_leaf_addrx8); - fors_sk_to_leafx8(leaf0, leaf1, leaf2, leaf3, leaf4, leaf5, leaf6, leaf7, - leaf0, leaf1, leaf2, leaf3, leaf4, leaf5, leaf6, leaf7, - pub_seed, fors_leaf_addrx8, state_seeded); -} - -/** - * Interprets m as PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_FORS_HEIGHT-bit unsigned integers. - * Assumes m contains at least PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_FORS_TREES bits. - * Assumes indices has space for PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_FORS_TREES integers. - */ -static void message_to_indices(uint32_t *indices, const unsigned char *m) { - unsigned int i, j; - unsigned int offset = 0; - - for (i = 0; i < PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_FORS_TREES; i++) { - indices[i] = 0; - for (j = 0; j < PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_FORS_HEIGHT; j++) { - indices[i] ^= (((uint32_t)m[offset >> 3] >> (offset & 0x7)) & 0x1) << j; - offset++; - } - } -} - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_fors_sign( - unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], - const hash_state *state_seeded) { - /* Round up to multiple of 8 to prevent out-of-bounds for x8 parallelism */ - uint32_t indices[(PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_FORS_TREES + 7) & ~7] = {0}; - unsigned char roots[((PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_FORS_TREES + 7) & ~7) * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N]; - /* Sign to a buffer, since we may not have a nice multiple of 8 and would - otherwise overrun the signature. */ - unsigned char sigbufx8[8 * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N * (1 + PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_FORS_HEIGHT)]; - uint32_t fors_tree_addrx8[8 * 8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset[8] = {0}; - unsigned int i, j; - - for (j = 0; j < 8; j++) { - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_copy_keypair_addr(fors_tree_addrx8 + j * 8, fors_addr); - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_set_type(fors_tree_addrx8 + j * 8, PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_ADDR_TYPE_FORSTREE); - } - - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_copy_keypair_addr(fors_pk_addr, fors_addr); - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_set_type(fors_pk_addr, PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < ((PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_FORS_TREES + 7) & ~0x7); i += 8) { - for (j = 0; j < 8; j++) { - if (i + j < PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_FORS_TREES) { - idx_offset[j] = (i + j) * (1 << PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_FORS_HEIGHT); - - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_set_tree_height(fors_tree_addrx8 + j * 8, 0); - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_set_tree_index(fors_tree_addrx8 + j * 8, - indices[i + j] + idx_offset[j]); - } - } - - /* Include the secret key part that produces the selected leaf nodes. */ - fors_gen_skx8(sigbufx8 + 0 * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N, - sigbufx8 + 1 * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N, - sigbufx8 + 2 * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N, - sigbufx8 + 3 * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N, - sigbufx8 + 4 * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N, - sigbufx8 + 5 * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N, - sigbufx8 + 6 * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N, - sigbufx8 + 7 * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N, - sk_seed, fors_tree_addrx8); - - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_treehashx8_FORS_HEIGHT( - roots + i * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N, sigbufx8 + 8 * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N, sk_seed, pub_seed, - &indices[i], idx_offset, fors_gen_leafx8, fors_tree_addrx8, - state_seeded); - - for (j = 0; j < 8; j++) { - if (i + j < PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_FORS_TREES) { - memcpy(sig, sigbufx8 + j * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N, PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N); - memcpy(sig + PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N, - sigbufx8 + 8 * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N + j * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_FORS_HEIGHT, - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_FORS_HEIGHT); - sig += PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N * (1 + PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_FORS_HEIGHT); - } - } - } - - /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_thash_FORS_TREES(pk, roots, pub_seed, fors_pk_addr, state_seeded); -} - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, - const uint32_t fors_addr[8], - const hash_state *state_seeded) { - uint32_t indices[PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_FORS_TREES]; - unsigned char roots[PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_FORS_TREES * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N]; - unsigned char leaf[PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N]; - uint32_t fors_tree_addr[8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_copy_keypair_addr(fors_tree_addr, fors_addr); - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_copy_keypair_addr(fors_pk_addr, fors_addr); - - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_set_type(fors_tree_addr, PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_set_type(fors_pk_addr, PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_FORS_TREES; i++) { - idx_offset = i * (1 << PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_FORS_HEIGHT); - - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_set_tree_height(fors_tree_addr, 0); - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Derive the leaf from the included secret key part. */ - fors_sk_to_leaf(leaf, sig, pub_seed, fors_tree_addr, state_seeded); - sig += PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N; - - /* Derive the corresponding root node of this tree. */ - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_compute_root(roots + i * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N, leaf, indices[i], idx_offset, - sig, PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_FORS_HEIGHT, pub_seed, fors_tree_addr, state_seeded); - sig += PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_thash_FORS_TREES(pk, roots, pub_seed, fors_pk_addr, state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_avx2/fors.h b/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_avx2/fors.h deleted file mode 100644 index 3d286c96f5..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_avx2/fors.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_FORS_H -#define PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_FORS_H - -#include - -#include "hash_state.h" -#include "params.h" - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_fors_sign( - unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *hash_state_seeded); - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_fors_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, const uint32_t fors_addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_avx2/hash.h b/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_avx2/hash.h deleted file mode 100644 index 61fe75d7d1..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_avx2/hash.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_HASH_H -#define PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_HASH_H - -#include "hash_state.h" - -#include -#include - -void PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_initialize_hash_function( - hash_state *hash_state_seeded, - const unsigned char *pub_seed, const unsigned char *sk_seed); - -void PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_destroy_hash_function(hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_avx2/hash_sha256.c b/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_avx2/hash_sha256.c deleted file mode 100644 index fffb80d3c3..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_avx2/hash_sha256.c +++ /dev/null @@ -1,166 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "utils.h" - -#include "sha2.h" -#include "sha256.h" -#include "sha256x8.h" - -/** - * Initializes the hash function states - */ -void PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_initialize_hash_function( - hash_state *hash_state_seeded, - const unsigned char *pub_seed, const unsigned char *sk_seed) { - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_seed_state(&hash_state_seeded->x1, pub_seed); - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_seed_statex8(&hash_state_seeded->x8, pub_seed); - (void)sk_seed; /* Suppress an 'unused parameter' warning. */ -} - -/** - * Cleans up the hash function states - */ -void PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_destroy_hash_function(hash_state *hash_state_seeded) { - sha256_inc_ctx_release(&hash_state_seeded->x1); -} - -/* - * Computes PRF(key, addr), given a secret key of PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N bytes and an address - */ -void PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_prf_addr(unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded) { - unsigned char buf[PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_ADDR_BYTES]; - unsigned char outbuf[PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_OUTPUT_BYTES]; - - memcpy(buf, key, PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N); - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_compress_address(buf + PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N, addr); - - sha256(outbuf, buf, PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_ADDR_BYTES); - memcpy(out, outbuf, PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} - -/** - * Computes the message-dependent randomness R, using a secret seed as a key - * for HMAC, and an optional randomization value prefixed to the message. - * This requires m to have at least PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_BLOCK_BYTES + PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N space - * available in front of the pointer, i.e. before the message to use for the - * prefix. This is necessary to prevent having to move the message around (and - * allocate memory for it). - */ -void PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, const hash_state *hash_state_seeded) { - unsigned char buf[PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_BLOCK_BYTES + PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_OUTPUT_BYTES]; - sha256ctx state; - int i; - - /* This implements HMAC-SHA256 */ - for (i = 0; i < PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N; i++) { - buf[i] = 0x36 ^ sk_prf[i]; - } - memset(buf + PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N, 0x36, PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N); - - sha256_inc_init(&state); - sha256_inc_blocks(&state, buf, 1); - - memcpy(buf, optrand, PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N); - - /* If optrand + message cannot fill up an entire block */ - if (PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N + mlen < PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_BLOCK_BYTES) { - memcpy(buf + PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N, m, mlen); - sha256_inc_finalize(buf + PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_BLOCK_BYTES, &state, - buf, mlen + PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N); - } - /* Otherwise first fill a block, so that finalize only uses the message */ - else { - memcpy(buf + PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N, m, PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N); - sha256_inc_blocks(&state, buf, 1); - - m += PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N; - mlen -= PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N; - sha256_inc_finalize(buf + PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_BLOCK_BYTES, &state, m, mlen); - } - - for (i = 0; i < PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N; i++) { - buf[i] = 0x5c ^ sk_prf[i]; - } - memset(buf + PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N, 0x5c, PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N); - - sha256(buf, buf, PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_BLOCK_BYTES + PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_OUTPUT_BYTES); - memcpy(R, buf, PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} - -/** - * Computes the message hash using R, the public key, and the message. - * Outputs the message digest and the index of the leaf. The index is split in - * the tree index and the leaf index, for convenient copying to an address. - */ -void PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded) { -#define PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_TREE_BITS (PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_TREE_HEIGHT * (PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_D - 1)) -#define PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_TREE_BYTES ((PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_TREE_BITS + 7) / 8) -#define PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_LEAF_BITS PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_TREE_HEIGHT -#define PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_LEAF_BYTES ((PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_LEAF_BITS + 7) / 8) -#define PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_DGST_BYTES (PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_FORS_MSG_BYTES + PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_TREE_BYTES + PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_LEAF_BYTES) - - unsigned char seed[PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_OUTPUT_BYTES + 4]; - - /* Round to nearest multiple of PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_BLOCK_BYTES */ -#define PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_INBLOCKS (((PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_PK_BYTES + PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_BLOCK_BYTES - 1) & \ - -PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_BLOCK_BYTES) / PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_BLOCK_BYTES) - unsigned char inbuf[PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_INBLOCKS * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_BLOCK_BYTES]; - - unsigned char buf[PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_DGST_BYTES]; - unsigned char *bufp = buf; - sha256ctx state; - - sha256_inc_init(&state); - - memcpy(inbuf, R, PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N); - memcpy(inbuf + PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N, pk, PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_PK_BYTES); - - /* If R + pk + message cannot fill up an entire block */ - if (PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_PK_BYTES + mlen < PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_INBLOCKS * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_BLOCK_BYTES) { - memcpy(inbuf + PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_PK_BYTES, m, mlen); - sha256_inc_finalize(seed, &state, inbuf, PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_PK_BYTES + mlen); - } - /* Otherwise first fill a block, so that finalize only uses the message */ - else { - memcpy(inbuf + PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_PK_BYTES, m, - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_INBLOCKS * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_PK_BYTES); - sha256_inc_blocks(&state, inbuf, PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_INBLOCKS); - - m += PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_INBLOCKS * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_PK_BYTES; - mlen -= PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_INBLOCKS * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_PK_BYTES; - sha256_inc_finalize(seed, &state, m, mlen); - } - - /* By doing this in two steps, we prevent hashing the message twice; - otherwise each iteration in MGF1 would hash the message again. */ - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_mgf1(bufp, PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_DGST_BYTES, seed, PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_OUTPUT_BYTES); - - memcpy(digest, bufp, PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_FORS_MSG_BYTES); - bufp += PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_FORS_MSG_BYTES; - - *tree = PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_bytes_to_ull(bufp, PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_TREE_BYTES); - *tree &= (~(uint64_t)0) >> (64 - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_TREE_BITS); - bufp += PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_TREE_BYTES; - - *leaf_idx = (uint32_t)PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_bytes_to_ull( - bufp, PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_LEAF_BYTES); - *leaf_idx &= (~(uint32_t)0) >> (32 - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_LEAF_BITS); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_avx2/hash_sha256x8.c b/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_avx2/hash_sha256x8.c deleted file mode 100644 index a57b923f31..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_avx2/hash_sha256x8.c +++ /dev/null @@ -1,61 +0,0 @@ -#include -#include - -#include "address.h" -#include "hashx8.h" -#include "params.h" -#include "sha256.h" -#include "sha256avx.h" -#include "sha256x8.h" -#include "utils.h" - -/* - * 8-way parallel version of prf_addr; takes 8x as much input and output - */ -void PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_prf_addrx8(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7, - const unsigned char *key, - const uint32_t addrx8[8 * 8]) { - unsigned char bufx8[8 * (PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_ADDR_BYTES)]; - unsigned char outbufx8[8 * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_OUTPUT_BYTES]; - unsigned int j; - - for (j = 0; j < 8; j++) { - memcpy(bufx8 + j * (PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_ADDR_BYTES), key, PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N); - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_compress_address(bufx8 + PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N + j * (PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_ADDR_BYTES), - addrx8 + j * 8); - } - - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_sha256x8(outbufx8 + 0 * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 1 * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 2 * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 3 * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 4 * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 5 * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 6 * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 7 * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_OUTPUT_BYTES, - bufx8 + 0 * (PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_ADDR_BYTES), - bufx8 + 1 * (PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_ADDR_BYTES), - bufx8 + 2 * (PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_ADDR_BYTES), - bufx8 + 3 * (PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_ADDR_BYTES), - bufx8 + 4 * (PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_ADDR_BYTES), - bufx8 + 5 * (PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_ADDR_BYTES), - bufx8 + 6 * (PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_ADDR_BYTES), - bufx8 + 7 * (PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_ADDR_BYTES), - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_ADDR_BYTES); - - memcpy(out0, outbufx8 + 0 * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N); - memcpy(out1, outbufx8 + 1 * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N); - memcpy(out2, outbufx8 + 2 * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N); - memcpy(out3, outbufx8 + 3 * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N); - memcpy(out4, outbufx8 + 4 * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N); - memcpy(out5, outbufx8 + 5 * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N); - memcpy(out6, outbufx8 + 6 * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N); - memcpy(out7, outbufx8 + 7 * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_avx2/hash_state.h b/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_avx2/hash_state.h deleted file mode 100644 index 47470f23bb..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_avx2/hash_state.h +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_HASH_STATE_H -#define PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_HASH_STATE_H - -/** - * Defines the type of the hash function state. - * - * Don't be fooled into thinking this instance of SPHINCS+ isn't stateless! - * - * From Section 7.2.2 from the SPHINCS+ round-2 specification: - * - * Each of the instances of the tweakable hash function take PK.seed as its - * first input, which is constant for a given key pair – and, thus, across - * a single signature. This leads to a lot of redundant computation. To remedy - * this, we pad PK.seed to the length of a full 64-byte SHA-256 input block. - * Because of the Merkle-Damgård construction that underlies SHA-256, this - * allows for reuse of the intermediate SHA-256 state after the initial call to - * the compression function which improves performance. - * - * We pass this hash state around in functions, because otherwise we need to - * have a global variable. - * - * We use a struct to differentiate between the x1 and x8 variants of SHA256. - */ - -#include "sha2.h" -#include "sha256avx.h" - -typedef struct { - sha256ctx x1; - sha256ctxx8 x8; -} hash_state; - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_avx2/hashx8.h b/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_avx2/hashx8.h deleted file mode 100644 index 30d23216a2..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_avx2/hashx8.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_HASHX8_H -#define PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_HASHX8_H - -#include - -#include "params.h" - -void PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_prf_addrx8(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7, - const unsigned char *key, - const uint32_t addrx8[8 * 8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_avx2/params.h b/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_avx2/params.h deleted file mode 100644 index 80f9071cb8..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_avx2/params.h +++ /dev/null @@ -1,53 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_PARAMS_H -#define PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_PARAMS_H - -/* Hash output length in bytes. */ -#define PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N 32 -/* Height of the hypertree. */ -#define PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_FULL_HEIGHT 64 -/* Number of subtree layer. */ -#define PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_D 8 -/* FORS tree dimensions. */ -#define PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_FORS_HEIGHT 14 -#define PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_FORS_TREES 22 -/* Winternitz parameter, */ -#define PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_WOTS_W 16 - -/* The hash function is defined by linking a different hash.c file, as opposed - to setting a #define constant. */ - -/* For clarity */ -#define PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_ADDR_BYTES 32 - -/* WOTS parameters. */ -#define PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_WOTS_LOGW 4 - -#define PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_WOTS_LEN1 (8 * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N / PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_WOTS_LOGW) - -/* PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#define PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_WOTS_LEN2 3 - -#define PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_WOTS_LEN (PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_WOTS_LEN1 + PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_WOTS_LEN2) -#define PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_WOTS_BYTES (PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_WOTS_LEN * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N) -#define PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_WOTS_PK_BYTES PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_WOTS_BYTES - -/* Subtree size. */ -#define PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_TREE_HEIGHT (PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_FULL_HEIGHT / PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_D) - -/* FORS parameters. */ -#define PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_FORS_MSG_BYTES ((PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_FORS_TREES + 7) / 8) -#define PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_FORS_BYTES ((PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_FORS_HEIGHT + 1) * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_FORS_TREES * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N) -#define PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_FORS_PK_BYTES PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N - -/* Resulting SPX sizes. */ -#define PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_BYTES (PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_FORS_BYTES + PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_D * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_WOTS_BYTES +\ - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_FULL_HEIGHT * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N) -#define PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_PK_BYTES (2 * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N) -#define PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SK_BYTES (2 * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_PK_BYTES) - -/* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ -#define PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_OPTRAND_BYTES 32 - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_avx2/sha256.c b/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_avx2/sha256.c deleted file mode 100644 index b7a642631d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_avx2/sha256.c +++ /dev/null @@ -1,71 +0,0 @@ -/* Based on the public domain implementation in - * crypto_hash/sha512/ref/ from http://bench.cr.yp.to/supercop.html - * by D. J. Bernstein */ - -#include -#include -#include - -#include "sha2.h" -#include "sha256.h" -#include "utils.h" - -/* - * Compresses an address to a 22-byte sequence. - * This reduces the number of required SHA256 compression calls, as the last - * block of input is padded with at least 65 bits. - */ -void PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_compress_address(unsigned char *out, const uint32_t addr[8]) { - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_ull_to_bytes(out, 1, addr[0]); /* drop 3 bytes of the layer field */ - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_ull_to_bytes(out + 1, 4, addr[2]); /* drop the highest tree address word */ - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_ull_to_bytes(out + 5, 4, addr[3]); - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_ull_to_bytes(out + 9, 1, addr[4]); /* drop 3 bytes of the type field */ - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_ull_to_bytes(out + 10, 4, addr[5]); - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_ull_to_bytes(out + 14, 4, addr[6]); - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_ull_to_bytes(out + 18, 4, addr[7]); -} - -/** - * Requires 'input_plus_four_bytes' to have 'inlen' + 4 bytes, so that the last - * four bytes can be used for the counter. Typically 'input' is merely a seed. - * Outputs outlen number of bytes - */ -void PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_mgf1( - unsigned char *out, unsigned long outlen, - unsigned char *input_plus_four_bytes, unsigned long inlen) { - unsigned char outbuf[PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_OUTPUT_BYTES]; - unsigned long i; - - /* While we can fit in at least another full block of SHA256 output.. */ - for (i = 0; (i + 1)*PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_OUTPUT_BYTES <= outlen; i++) { - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_ull_to_bytes(input_plus_four_bytes + inlen, 4, i); - sha256(out, input_plus_four_bytes, inlen + 4); - out += PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_OUTPUT_BYTES; - } - /* Until we cannot anymore, and we fill the remainder. */ - if (outlen > i * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_OUTPUT_BYTES) { - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_ull_to_bytes(input_plus_four_bytes + inlen, 4, i); - sha256(outbuf, input_plus_four_bytes, inlen + 4); - memcpy(out, outbuf, outlen - i * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_OUTPUT_BYTES); - } -} - - -/** - * Absorb the constant pub_seed using one round of the compression function - * This initializes hash_state_seeded, which can then be reused in thash - **/ -void PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_seed_state(sha256ctx *hash_state_seeded, const unsigned char *pub_seed) { - uint8_t block[PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_BLOCK_BYTES]; - size_t i; - - for (i = 0; i < PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N; ++i) { - block[i] = pub_seed[i]; - } - for (i = PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N; i < PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_BLOCK_BYTES; ++i) { - block[i] = 0; - } - - sha256_inc_init(hash_state_seeded); - sha256_inc_blocks(hash_state_seeded, block, 1); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_avx2/sha256.h b/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_avx2/sha256.h deleted file mode 100644 index f627451b19..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_avx2/sha256.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_H -#define PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_H - -#define PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_BLOCK_BYTES 64 -#define PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_OUTPUT_BYTES 32 /* This does not necessarily equal PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N */ -#define PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_ADDR_BYTES 22 - -#include -#include - -#include "sha2.h" - -void PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_compress_address(unsigned char *out, const uint32_t addr[8]); - -void PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_mgf1( - unsigned char *out, unsigned long outlen, - unsigned char *input_plus_four_bytes, unsigned long inlen); - -void PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_seed_state(sha256ctx *hash_state_seeded, const unsigned char *pub_seed); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_avx2/sha256avx.c b/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_avx2/sha256avx.c deleted file mode 100644 index 02fd73cece..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_avx2/sha256avx.c +++ /dev/null @@ -1,296 +0,0 @@ -#include -#include -#include - -#include "sha256avx.h" - -// Transpose 8 vectors containing 32-bit values -void PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_transpose(u256 s[8]) { - u256 tmp0[8]; - u256 tmp1[8]; - tmp0[0] = _mm256_unpacklo_epi32(s[0], s[1]); - tmp0[1] = _mm256_unpackhi_epi32(s[0], s[1]); - tmp0[2] = _mm256_unpacklo_epi32(s[2], s[3]); - tmp0[3] = _mm256_unpackhi_epi32(s[2], s[3]); - tmp0[4] = _mm256_unpacklo_epi32(s[4], s[5]); - tmp0[5] = _mm256_unpackhi_epi32(s[4], s[5]); - tmp0[6] = _mm256_unpacklo_epi32(s[6], s[7]); - tmp0[7] = _mm256_unpackhi_epi32(s[6], s[7]); - tmp1[0] = _mm256_unpacklo_epi64(tmp0[0], tmp0[2]); - tmp1[1] = _mm256_unpackhi_epi64(tmp0[0], tmp0[2]); - tmp1[2] = _mm256_unpacklo_epi64(tmp0[1], tmp0[3]); - tmp1[3] = _mm256_unpackhi_epi64(tmp0[1], tmp0[3]); - tmp1[4] = _mm256_unpacklo_epi64(tmp0[4], tmp0[6]); - tmp1[5] = _mm256_unpackhi_epi64(tmp0[4], tmp0[6]); - tmp1[6] = _mm256_unpacklo_epi64(tmp0[5], tmp0[7]); - tmp1[7] = _mm256_unpackhi_epi64(tmp0[5], tmp0[7]); - s[0] = _mm256_permute2x128_si256(tmp1[0], tmp1[4], 0x20); - s[1] = _mm256_permute2x128_si256(tmp1[1], tmp1[5], 0x20); - s[2] = _mm256_permute2x128_si256(tmp1[2], tmp1[6], 0x20); - s[3] = _mm256_permute2x128_si256(tmp1[3], tmp1[7], 0x20); - s[4] = _mm256_permute2x128_si256(tmp1[0], tmp1[4], 0x31); - s[5] = _mm256_permute2x128_si256(tmp1[1], tmp1[5], 0x31); - s[6] = _mm256_permute2x128_si256(tmp1[2], tmp1[6], 0x31); - s[7] = _mm256_permute2x128_si256(tmp1[3], tmp1[7], 0x31); -} - -void PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_sha256_clone_statex8(sha256ctxx8 *outctx, const sha256ctxx8 *inctx) { - memcpy(outctx, inctx, sizeof(sha256ctxx8)); -} - -void PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_sha256_init8x(sha256ctxx8 *ctx) { - ctx->s[0] = _mm256_set_epi32((int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667); - ctx->s[1] = _mm256_set_epi32((int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85); - ctx->s[2] = _mm256_set_epi32((int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372); - ctx->s[3] = _mm256_set_epi32((int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a); - ctx->s[4] = _mm256_set_epi32((int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f); - ctx->s[5] = _mm256_set_epi32((int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c); - ctx->s[6] = _mm256_set_epi32((int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab); - ctx->s[7] = _mm256_set_epi32((int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19); - - ctx->datalen = 0; - ctx->msglen = 0; -} - -void PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_sha256_update8x(sha256ctxx8 *ctx, - const unsigned char *d0, - const unsigned char *d1, - const unsigned char *d2, - const unsigned char *d3, - const unsigned char *d4, - const unsigned char *d5, - const unsigned char *d6, - const unsigned char *d7, - unsigned long long len) { - size_t i = 0; - size_t bytes_to_copy; - - while (i < len) { - bytes_to_copy = (size_t)len - i; - if (bytes_to_copy > 64) { - bytes_to_copy = 64; - } - memcpy(&ctx->msgblocks[64 * 0], d0 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64 * 1], d1 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64 * 2], d2 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64 * 3], d3 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64 * 4], d4 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64 * 5], d5 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64 * 6], d6 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64 * 7], d7 + i, bytes_to_copy); - ctx->datalen += (unsigned int)bytes_to_copy; - i += bytes_to_copy; - if (ctx->datalen == 64) { - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_sha256_transform8x(ctx, ctx->msgblocks); - ctx->msglen += 512; - ctx->datalen = 0; - } - } -} - -void PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_sha256_final8x(sha256ctxx8 *ctx, - unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7) { - unsigned int i, curlen; - - // Padding - if (ctx->datalen < 56) { - for (i = 0; i < 8; ++i) { - curlen = ctx->datalen; - ctx->msgblocks[64 * i + curlen++] = 0x80; - while (curlen < 64) { - ctx->msgblocks[64 * i + curlen++] = 0x00; - } - } - } else { - for (i = 0; i < 8; ++i) { - curlen = ctx->datalen; - ctx->msgblocks[64 * i + curlen++] = 0x80; - while (curlen < 64) { - ctx->msgblocks[64 * i + curlen++] = 0x00; - } - } - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_sha256_transform8x(ctx, ctx->msgblocks); - memset(ctx->msgblocks, 0, 8 * 64); - } - - // Add length of the message to each block - ctx->msglen += ctx->datalen * 8; - for (i = 0; i < 8; i++) { - ctx->msgblocks[64 * i + 63] = (unsigned char)ctx->msglen; - ctx->msgblocks[64 * i + 62] = (unsigned char)(ctx->msglen >> 8); - ctx->msgblocks[64 * i + 61] = (unsigned char)(ctx->msglen >> 16); - ctx->msgblocks[64 * i + 60] = (unsigned char)(ctx->msglen >> 24); - ctx->msgblocks[64 * i + 59] = (unsigned char)(ctx->msglen >> 32); - ctx->msgblocks[64 * i + 58] = (unsigned char)(ctx->msglen >> 40); - ctx->msgblocks[64 * i + 57] = (unsigned char)(ctx->msglen >> 48); - ctx->msgblocks[64 * i + 56] = (unsigned char)(ctx->msglen >> 56); - } - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_sha256_transform8x(ctx, ctx->msgblocks); - - // Compute final hash output - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_transpose(ctx->s); - - // Store Hash value - STORE(out0, BYTESWAP(ctx->s[0])); - STORE(out1, BYTESWAP(ctx->s[1])); - STORE(out2, BYTESWAP(ctx->s[2])); - STORE(out3, BYTESWAP(ctx->s[3])); - STORE(out4, BYTESWAP(ctx->s[4])); - STORE(out5, BYTESWAP(ctx->s[5])); - STORE(out6, BYTESWAP(ctx->s[6])); - STORE(out7, BYTESWAP(ctx->s[7])); -} - -void PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_sha256_transform8x(sha256ctxx8 *ctx, const unsigned char *data) { - u256 s[8], w[64], T0, T1; - int i; - - // Load words and transform data correctly - for (i = 0; i < 8; i++) { - w[i] = BYTESWAP(LOAD(data + 64 * i)); - w[i + 8] = BYTESWAP(LOAD(data + 32 + 64 * i)); - } - - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_transpose(w); - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_transpose(w + 8); - - // Initial State - s[0] = ctx->s[0]; - s[1] = ctx->s[1]; - s[2] = ctx->s[2]; - s[3] = ctx->s[3]; - s[4] = ctx->s[4]; - s[5] = ctx->s[5]; - s[6] = ctx->s[6]; - s[7] = ctx->s[7]; - - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 0, w[0]); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 1, w[1]); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 2, w[2]); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 3, w[3]); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 4, w[4]); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 5, w[5]); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 6, w[6]); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 7, w[7]); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 8, w[8]); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 9, w[9]); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 10, w[10]); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 11, w[11]); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 12, w[12]); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 13, w[13]); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 14, w[14]); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 15, w[15]); - w[16] = ADD4_32(WSIGMA1_AVX(w[14]), w[0], w[9], WSIGMA0_AVX(w[1])); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 16, w[16]); - w[17] = ADD4_32(WSIGMA1_AVX(w[15]), w[1], w[10], WSIGMA0_AVX(w[2])); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 17, w[17]); - w[18] = ADD4_32(WSIGMA1_AVX(w[16]), w[2], w[11], WSIGMA0_AVX(w[3])); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 18, w[18]); - w[19] = ADD4_32(WSIGMA1_AVX(w[17]), w[3], w[12], WSIGMA0_AVX(w[4])); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 19, w[19]); - w[20] = ADD4_32(WSIGMA1_AVX(w[18]), w[4], w[13], WSIGMA0_AVX(w[5])); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 20, w[20]); - w[21] = ADD4_32(WSIGMA1_AVX(w[19]), w[5], w[14], WSIGMA0_AVX(w[6])); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 21, w[21]); - w[22] = ADD4_32(WSIGMA1_AVX(w[20]), w[6], w[15], WSIGMA0_AVX(w[7])); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 22, w[22]); - w[23] = ADD4_32(WSIGMA1_AVX(w[21]), w[7], w[16], WSIGMA0_AVX(w[8])); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 23, w[23]); - w[24] = ADD4_32(WSIGMA1_AVX(w[22]), w[8], w[17], WSIGMA0_AVX(w[9])); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 24, w[24]); - w[25] = ADD4_32(WSIGMA1_AVX(w[23]), w[9], w[18], WSIGMA0_AVX(w[10])); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 25, w[25]); - w[26] = ADD4_32(WSIGMA1_AVX(w[24]), w[10], w[19], WSIGMA0_AVX(w[11])); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 26, w[26]); - w[27] = ADD4_32(WSIGMA1_AVX(w[25]), w[11], w[20], WSIGMA0_AVX(w[12])); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 27, w[27]); - w[28] = ADD4_32(WSIGMA1_AVX(w[26]), w[12], w[21], WSIGMA0_AVX(w[13])); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 28, w[28]); - w[29] = ADD4_32(WSIGMA1_AVX(w[27]), w[13], w[22], WSIGMA0_AVX(w[14])); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 29, w[29]); - w[30] = ADD4_32(WSIGMA1_AVX(w[28]), w[14], w[23], WSIGMA0_AVX(w[15])); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 30, w[30]); - w[31] = ADD4_32(WSIGMA1_AVX(w[29]), w[15], w[24], WSIGMA0_AVX(w[16])); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 31, w[31]); - w[32] = ADD4_32(WSIGMA1_AVX(w[30]), w[16], w[25], WSIGMA0_AVX(w[17])); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 32, w[32]); - w[33] = ADD4_32(WSIGMA1_AVX(w[31]), w[17], w[26], WSIGMA0_AVX(w[18])); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 33, w[33]); - w[34] = ADD4_32(WSIGMA1_AVX(w[32]), w[18], w[27], WSIGMA0_AVX(w[19])); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 34, w[34]); - w[35] = ADD4_32(WSIGMA1_AVX(w[33]), w[19], w[28], WSIGMA0_AVX(w[20])); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 35, w[35]); - w[36] = ADD4_32(WSIGMA1_AVX(w[34]), w[20], w[29], WSIGMA0_AVX(w[21])); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 36, w[36]); - w[37] = ADD4_32(WSIGMA1_AVX(w[35]), w[21], w[30], WSIGMA0_AVX(w[22])); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 37, w[37]); - w[38] = ADD4_32(WSIGMA1_AVX(w[36]), w[22], w[31], WSIGMA0_AVX(w[23])); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 38, w[38]); - w[39] = ADD4_32(WSIGMA1_AVX(w[37]), w[23], w[32], WSIGMA0_AVX(w[24])); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 39, w[39]); - w[40] = ADD4_32(WSIGMA1_AVX(w[38]), w[24], w[33], WSIGMA0_AVX(w[25])); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 40, w[40]); - w[41] = ADD4_32(WSIGMA1_AVX(w[39]), w[25], w[34], WSIGMA0_AVX(w[26])); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 41, w[41]); - w[42] = ADD4_32(WSIGMA1_AVX(w[40]), w[26], w[35], WSIGMA0_AVX(w[27])); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 42, w[42]); - w[43] = ADD4_32(WSIGMA1_AVX(w[41]), w[27], w[36], WSIGMA0_AVX(w[28])); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 43, w[43]); - w[44] = ADD4_32(WSIGMA1_AVX(w[42]), w[28], w[37], WSIGMA0_AVX(w[29])); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 44, w[44]); - w[45] = ADD4_32(WSIGMA1_AVX(w[43]), w[29], w[38], WSIGMA0_AVX(w[30])); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 45, w[45]); - w[46] = ADD4_32(WSIGMA1_AVX(w[44]), w[30], w[39], WSIGMA0_AVX(w[31])); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 46, w[46]); - w[47] = ADD4_32(WSIGMA1_AVX(w[45]), w[31], w[40], WSIGMA0_AVX(w[32])); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 47, w[47]); - w[48] = ADD4_32(WSIGMA1_AVX(w[46]), w[32], w[41], WSIGMA0_AVX(w[33])); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 48, w[48]); - w[49] = ADD4_32(WSIGMA1_AVX(w[47]), w[33], w[42], WSIGMA0_AVX(w[34])); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 49, w[49]); - w[50] = ADD4_32(WSIGMA1_AVX(w[48]), w[34], w[43], WSIGMA0_AVX(w[35])); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 50, w[50]); - w[51] = ADD4_32(WSIGMA1_AVX(w[49]), w[35], w[44], WSIGMA0_AVX(w[36])); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 51, w[51]); - w[52] = ADD4_32(WSIGMA1_AVX(w[50]), w[36], w[45], WSIGMA0_AVX(w[37])); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 52, w[52]); - w[53] = ADD4_32(WSIGMA1_AVX(w[51]), w[37], w[46], WSIGMA0_AVX(w[38])); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 53, w[53]); - w[54] = ADD4_32(WSIGMA1_AVX(w[52]), w[38], w[47], WSIGMA0_AVX(w[39])); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 54, w[54]); - w[55] = ADD4_32(WSIGMA1_AVX(w[53]), w[39], w[48], WSIGMA0_AVX(w[40])); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 55, w[55]); - w[56] = ADD4_32(WSIGMA1_AVX(w[54]), w[40], w[49], WSIGMA0_AVX(w[41])); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 56, w[56]); - w[57] = ADD4_32(WSIGMA1_AVX(w[55]), w[41], w[50], WSIGMA0_AVX(w[42])); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 57, w[57]); - w[58] = ADD4_32(WSIGMA1_AVX(w[56]), w[42], w[51], WSIGMA0_AVX(w[43])); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 58, w[58]); - w[59] = ADD4_32(WSIGMA1_AVX(w[57]), w[43], w[52], WSIGMA0_AVX(w[44])); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 59, w[59]); - w[60] = ADD4_32(WSIGMA1_AVX(w[58]), w[44], w[53], WSIGMA0_AVX(w[45])); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 60, w[60]); - w[61] = ADD4_32(WSIGMA1_AVX(w[59]), w[45], w[54], WSIGMA0_AVX(w[46])); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 61, w[61]); - w[62] = ADD4_32(WSIGMA1_AVX(w[60]), w[46], w[55], WSIGMA0_AVX(w[47])); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 62, w[62]); - w[63] = ADD4_32(WSIGMA1_AVX(w[61]), w[47], w[56], WSIGMA0_AVX(w[48])); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 63, w[63]); - - // Feed Forward - ctx->s[0] = ADD32(s[0], ctx->s[0]); - ctx->s[1] = ADD32(s[1], ctx->s[1]); - ctx->s[2] = ADD32(s[2], ctx->s[2]); - ctx->s[3] = ADD32(s[3], ctx->s[3]); - ctx->s[4] = ADD32(s[4], ctx->s[4]); - ctx->s[5] = ADD32(s[5], ctx->s[5]); - ctx->s[6] = ADD32(s[6], ctx->s[6]); - ctx->s[7] = ADD32(s[7], ctx->s[7]); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_avx2/sha256avx.h b/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_avx2/sha256avx.h deleted file mode 100644 index 17b3689022..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_avx2/sha256avx.h +++ /dev/null @@ -1,103 +0,0 @@ -#ifndef SHA256AVX_H -#define SHA256AVX_H - -#include -#include - -static const unsigned int RC[] = { - 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, - 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, - 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, - 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, - 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, - 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, - 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, - 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, - 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, - 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, - 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, - 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, - 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, - 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, - 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, - 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 -}; - -#define u32 uint32_t -#define u256 __m256i - -#define XOR _mm256_xor_si256 -#define OR _mm256_or_si256 -#define AND _mm256_and_si256 -#define ADD32 _mm256_add_epi32 -#define NOT(x) _mm256_xor_si256(x, _mm256_set_epi32(-1, -1, -1, -1, -1, -1, -1, -1)) - -#define LOAD(src) _mm256_loadu_si256((__m256i *)(src)) -#define STORE(dest,src) _mm256_storeu_si256((__m256i *)(dest),src) - -#define BYTESWAP(x) _mm256_shuffle_epi8(x, _mm256_set_epi8(0xc,0xd,0xe,0xf,0x8,0x9,0xa,0xb,0x4,0x5,0x6,0x7,0x0,0x1,0x2,0x3,0xc,0xd,0xe,0xf,0x8,0x9,0xa,0xb,0x4,0x5,0x6,0x7,0x0,0x1,0x2,0x3)) - -#define SHIFTR32(x, y) _mm256_srli_epi32(x, y) -#define SHIFTL32(x, y) _mm256_slli_epi32(x, y) - -#define ROTR32(x, y) OR(SHIFTR32(x, y), SHIFTL32(x, 32 - (y))) -#define ROTL32(x, y) OR(SHIFTL32(x, y), SHIFTR32(x, 32 - (y))) - -#define XOR3(a, b, c) XOR(XOR(a, b), c) - -#define ADD3_32(a, b, c) ADD32(ADD32(a, b), c) -#define ADD4_32(a, b, c, d) ADD32(ADD32(ADD32(a, b), c), d) -#define ADD5_32(a, b, c, d, e) ADD32(ADD32(ADD32(ADD32(a, b), c), d), e) - -#define MAJ_AVX(a, b, c) XOR3(AND(a, b), AND(a, c), AND(b, c)) -#define CH_AVX(a, b, c) XOR(AND(a, b), AND(NOT(a), c)) - -#define SIGMA1_AVX(x) XOR3(ROTR32(x, 6), ROTR32(x, 11), ROTR32(x, 25)) -#define SIGMA0_AVX(x) XOR3(ROTR32(x, 2), ROTR32(x, 13), ROTR32(x, 22)) - -#define WSIGMA1_AVX(x) XOR3(ROTR32(x, 17), ROTR32(x, 19), SHIFTR32(x, 10)) -#define WSIGMA0_AVX(x) XOR3(ROTR32(x, 7), ROTR32(x, 18), SHIFTR32(x, 3)) - -#define SHA256ROUND_AVX(a, b, c, d, e, f, g, h, rc, w) \ - T0 = ADD5_32(h, SIGMA1_AVX(e), CH_AVX(e, f, g), _mm256_set1_epi32((int)RC[rc]), w); \ - (d) = ADD32(d, T0); \ - T1 = ADD32(SIGMA0_AVX(a), MAJ_AVX(a, b, c)); \ - (h) = ADD32(T0, T1); - -typedef struct SHA256state { - u256 s[8]; - uint8_t msgblocks[8 * 64]; - unsigned int datalen; - uint64_t msglen; -} sha256ctxx8; - - -void PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_transpose(u256 s[8]); -void PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_sha256_init_frombytes_x8(sha256ctxx8 *ctx, const uint8_t *s, unsigned long long msglen); -void PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_sha256_init8x(sha256ctxx8 *ctx); -void PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_sha256_update8x(sha256ctxx8 *ctx, - const unsigned char *d0, - const unsigned char *d1, - const unsigned char *d2, - const unsigned char *d3, - const unsigned char *d4, - const unsigned char *d5, - const unsigned char *d6, - const unsigned char *d7, - unsigned long long len); -void PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_sha256_final8x(sha256ctxx8 *ctx, - unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7); - -void PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_sha256_transform8x(sha256ctxx8 *ctx, const unsigned char *data); - -void PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_sha256_clone_statex8(sha256ctxx8 *outctx, const sha256ctxx8 *inctx); - - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_avx2/sha256x8.c b/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_avx2/sha256x8.c deleted file mode 100644 index b62aa76ffa..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_avx2/sha256x8.c +++ /dev/null @@ -1,128 +0,0 @@ -#include - -#include "sha256.h" -#include "sha256avx.h" -#include "sha256x8.h" -#include "utils.h" - -void PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_seed_statex8(sha256ctxx8 *ctx, const unsigned char *pub_seed) { - uint8_t block[PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_BLOCK_BYTES]; - size_t i; - - for (i = 0; i < PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N; ++i) { - block[i] = pub_seed[i]; - } - for (i = PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N; i < PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_BLOCK_BYTES; ++i) { - block[i] = 0; - } - - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_sha256_init8x(ctx); - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_sha256_update8x(ctx, block, block, block, block, block, block, block, block, PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_BLOCK_BYTES); - -} - -/* This provides a wrapper around the internals of 8x parallel SHA256 */ -void PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_sha256x8(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - const unsigned char *in4, - const unsigned char *in5, - const unsigned char *in6, - const unsigned char *in7, unsigned long long inlen) { - sha256ctxx8 ctx; - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_sha256_init8x(&ctx); - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_sha256_update8x(&ctx, in0, in1, in2, in3, in4, in5, in6, in7, inlen); - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_sha256_final8x(&ctx, out0, out1, out2, out3, out4, out5, out6, out7); -} - -/** - * Note that inlen should be sufficiently small that it still allows for - * an array to be allocated on the stack. Typically 'in' is merely a seed. - * Outputs outlen number of bytes - */ -void PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_mgf1x8( - unsigned char *outx8, - unsigned long outlen, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - const unsigned char *in4, - const unsigned char *in5, - const unsigned char *in6, - const unsigned char *in7, - unsigned long inlen) { - unsigned char inbufx8[8 * ((PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_ADDR_BYTES) + 4)]; - unsigned char outbufx8[8 * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_OUTPUT_BYTES]; - unsigned long i; - unsigned int j; - - memcpy(inbufx8 + 0 * (inlen + 4), in0, inlen); - memcpy(inbufx8 + 1 * (inlen + 4), in1, inlen); - memcpy(inbufx8 + 2 * (inlen + 4), in2, inlen); - memcpy(inbufx8 + 3 * (inlen + 4), in3, inlen); - memcpy(inbufx8 + 4 * (inlen + 4), in4, inlen); - memcpy(inbufx8 + 5 * (inlen + 4), in5, inlen); - memcpy(inbufx8 + 6 * (inlen + 4), in6, inlen); - memcpy(inbufx8 + 7 * (inlen + 4), in7, inlen); - - /* While we can fit in at least another full block of SHA256 output.. */ - for (i = 0; (i + 1)*PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_OUTPUT_BYTES <= outlen; i++) { - for (j = 0; j < 8; j++) { - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_ull_to_bytes(inbufx8 + inlen + j * (inlen + 4), 4, i); - } - - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_sha256x8(outx8 + 0 * outlen, - outx8 + 1 * outlen, - outx8 + 2 * outlen, - outx8 + 3 * outlen, - outx8 + 4 * outlen, - outx8 + 5 * outlen, - outx8 + 6 * outlen, - outx8 + 7 * outlen, - inbufx8 + 0 * (inlen + 4), - inbufx8 + 1 * (inlen + 4), - inbufx8 + 2 * (inlen + 4), - inbufx8 + 3 * (inlen + 4), - inbufx8 + 4 * (inlen + 4), - inbufx8 + 5 * (inlen + 4), - inbufx8 + 6 * (inlen + 4), - inbufx8 + 7 * (inlen + 4), inlen + 4); - outx8 += PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_OUTPUT_BYTES; - } - /* Until we cannot anymore, and we fill the remainder. */ - for (j = 0; j < 8; j++) { - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_ull_to_bytes(inbufx8 + inlen + j * (inlen + 4), 4, i); - } - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_sha256x8(outbufx8 + 0 * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 1 * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 2 * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 3 * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 4 * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 5 * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 6 * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 7 * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_OUTPUT_BYTES, - inbufx8 + 0 * (inlen + 4), - inbufx8 + 1 * (inlen + 4), - inbufx8 + 2 * (inlen + 4), - inbufx8 + 3 * (inlen + 4), - inbufx8 + 4 * (inlen + 4), - inbufx8 + 5 * (inlen + 4), - inbufx8 + 6 * (inlen + 4), - inbufx8 + 7 * (inlen + 4), inlen + 4); - - for (j = 0; j < 8; j++) { - memcpy(outx8 + j * outlen, - outbufx8 + j * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_OUTPUT_BYTES, - outlen - i * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_OUTPUT_BYTES); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_avx2/sha256x8.h b/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_avx2/sha256x8.h deleted file mode 100644 index 9d45c625ac..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_avx2/sha256x8.h +++ /dev/null @@ -1,44 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256X8_H -#define PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256X8_H - -#include "sha256avx.h" - -#define PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_BLOCK_BYTES 64 -#define PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_OUTPUT_BYTES 32 /* This does not necessarily equal PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N */ - -/* This provides a wrapper around the internals of 8x parallel SHA256 */ -void PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_sha256x8(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - const unsigned char *in4, - const unsigned char *in5, - const unsigned char *in6, - const unsigned char *in7, unsigned long long inlen); - -/** - * Note that inlen should be sufficiently small that it still allows for - * an array to be allocated on the stack. Typically 'in' is merely a seed. - * Outputs outlen number of bytes - */ -void PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_mgf1x8(unsigned char *outx8, unsigned long outlen, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - const unsigned char *in4, - const unsigned char *in5, - const unsigned char *in6, - const unsigned char *in7, - unsigned long inlen); - -void PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_seed_statex8(sha256ctxx8 *ctx, const unsigned char *pub_seed); -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_avx2/sign.c b/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_avx2/sign.c deleted file mode 100644 index a7b839d09a..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_avx2/sign.c +++ /dev/null @@ -1,356 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "api.h" -#include "fors.h" -#include "hash.h" -#include "hash_state.h" -#include "params.h" -#include "randombytes.h" -#include "thash.h" -#include "utils.h" -#include "wots.h" - -/** - * Computes the leaf at a given address. First generates the WOTS key pair, - * then computes leaf by hashing horizontally. - */ -static void wots_gen_leaf(unsigned char *leaf, const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx, const uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - unsigned char pk[PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_WOTS_BYTES]; - uint32_t wots_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_set_type( - wots_addr, PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_set_type( - wots_pk_addr, PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_ADDR_TYPE_WOTSPK); - - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_set_keypair_addr( - wots_addr, addr_idx); - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_wots_gen_pk( - pk, sk_seed, pub_seed, wots_addr, hash_state_seeded); - - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_copy_keypair_addr( - wots_pk_addr, wots_addr); - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_thash_WOTS_LEN( - leaf, pk, pub_seed, wots_pk_addr, hash_state_seeded); -} - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_crypto_sign_secretkeybytes(void) { - return PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_CRYPTO_SECRETKEYBYTES; -} - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_crypto_sign_publickeybytes(void) { - return PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_CRYPTO_PUBLICKEYBYTES; -} - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_crypto_sign_bytes(void) { - return PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_CRYPTO_BYTES; -} - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_crypto_sign_seedbytes(void) { - return PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_CRYPTO_SEEDBYTES; -} - -/* - * Generates an SPX key pair given a seed of length - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed) { - /* We do not need the auth path in key generation, but it simplifies the - code to have just one treehash routine that computes both root and path - in one function. */ - unsigned char auth_path[PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_TREE_HEIGHT * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N]; - uint32_t top_tree_addr[8] = {0}; - hash_state hash_state_seeded; - - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_set_layer_addr( - top_tree_addr, PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_D - 1); - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_set_type( - top_tree_addr, PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_ADDR_TYPE_HASHTREE); - - /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ - memcpy(sk, seed, PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_CRYPTO_SEEDBYTES); - - memcpy(pk, sk + 2 * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N, PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_initialize_hash_function(&hash_state_seeded, pk, sk); - - /* Compute root node of the top-most subtree. */ - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_treehash_TREE_HEIGHT( - sk + 3 * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N, auth_path, sk, sk + 2 * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N, 0, 0, - wots_gen_leaf, top_tree_addr, &hash_state_seeded); - - memcpy(pk + PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N, sk + 3 * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N, PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N); - - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_destroy_hash_function(&hash_state_seeded); - return 0; -} - -/* - * Generates an SPX key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk) { - unsigned char seed[PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_CRYPTO_SEEDBYTES]; - randombytes(seed, PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_CRYPTO_SEEDBYTES); - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_crypto_sign_seed_keypair( - pk, sk, seed); - - return 0; -} - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - const unsigned char *sk_seed = sk; - const unsigned char *sk_prf = sk + PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N; - const unsigned char *pk = sk + 2 * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N; - const unsigned char *pub_seed = pk; - - unsigned char optrand[PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N]; - unsigned char mhash[PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_FORS_MSG_BYTES]; - unsigned char root[PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N]; - uint32_t i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - - hash_state hash_state_seeded; - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_initialize_hash_function( - &hash_state_seeded, - pub_seed, sk_seed); - - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_set_type( - wots_addr, PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_set_type( - tree_addr, PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_ADDR_TYPE_HASHTREE); - - /* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ - randombytes(optrand, PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N); - /* Compute the digest randomization value. */ - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_gen_message_random( - sig, sk_prf, optrand, m, mlen, &hash_state_seeded); - - /* Derive the message digest and leaf index from R, PK and M. */ - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N; - - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_set_keypair_addr( - wots_addr, idx_leaf); - - /* Sign the message hash using FORS. */ - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_fors_sign( - sig, root, mhash, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_FORS_BYTES; - - for (i = 0; i < PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_D; i++) { - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_set_tree_addr(tree_addr, tree); - - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_set_keypair_addr( - wots_addr, idx_leaf); - - /* Compute a WOTS signature. */ - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_wots_sign( - sig, root, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_WOTS_BYTES; - - /* Compute the authentication path for the used WOTS leaf. */ - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_treehash_TREE_HEIGHT( - root, sig, sk_seed, pub_seed, idx_leaf, 0, - wots_gen_leaf, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_TREE_HEIGHT * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_TREE_HEIGHT; - } - - *siglen = PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_BYTES; - - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_destroy_hash_function(&hash_state_seeded); - return 0; -} - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk) { - const unsigned char *pub_seed = pk; - const unsigned char *pub_root = pk + PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N; - unsigned char mhash[PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_FORS_MSG_BYTES]; - unsigned char wots_pk[PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_WOTS_BYTES]; - unsigned char root[PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N]; - unsigned char leaf[PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N]; - unsigned int i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - hash_state hash_state_seeded; - - if (siglen != PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_BYTES) { - return -1; - } - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_initialize_hash_function( - &hash_state_seeded, - pub_seed, NULL); - - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_set_type( - wots_addr, PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_set_type( - tree_addr, PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_ADDR_TYPE_HASHTREE); - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_set_type( - wots_pk_addr, PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_ADDR_TYPE_WOTSPK); - - /* Derive the message digest and leaf index from R || PK || M. */ - /* The additional PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N is a result of the hash domain separator. */ - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N; - - /* Layer correctly defaults to 0, so no need to set_layer_addr */ - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_set_keypair_addr( - wots_addr, idx_leaf); - - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_fors_pk_from_sig( - root, sig, mhash, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_FORS_BYTES; - - /* For each subtree.. */ - for (i = 0; i < PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_D; i++) { - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_set_tree_addr(tree_addr, tree); - - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_set_keypair_addr( - wots_addr, idx_leaf); - - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_copy_keypair_addr( - wots_pk_addr, wots_addr); - - /* The WOTS public key is only correct if the signature was correct. */ - /* Initially, root is the FORS pk, but on subsequent iterations it is - the root of the subtree below the currently processed subtree. */ - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_wots_pk_from_sig( - wots_pk, sig, root, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_WOTS_BYTES; - - /* Compute the leaf node using the WOTS public key. */ - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_thash_WOTS_LEN( - leaf, wots_pk, pub_seed, wots_pk_addr, &hash_state_seeded); - - /* Compute the root node of this subtree. */ - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_compute_root( - root, leaf, idx_leaf, 0, sig, PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_TREE_HEIGHT, - pub_seed, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_TREE_HEIGHT * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_TREE_HEIGHT; - } - - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_destroy_hash_function(&hash_state_seeded); - /* Check if the root node equals the root node in the public key. */ - if (memcmp(root, pub_root, PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N) != 0) { - return -1; - } - - return 0; -} - - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - size_t siglen; - - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_crypto_sign_signature( - sm, &siglen, m, mlen, sk); - - memmove(sm + PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_BYTES, m, mlen); - *smlen = siglen + mlen; - - return 0; -} - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk) { - /* The API caller does not necessarily know what size a signature should be - but SPHINCS+ signatures are always exactly PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_BYTES. */ - if (smlen < PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_BYTES) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - *mlen = smlen - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_BYTES; - - if (PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_crypto_sign_verify( - sm, PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_BYTES, sm + PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_BYTES, *mlen, pk)) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - /* If verification was successful, move the message to the right place. */ - memmove(m, sm + PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_BYTES, *mlen); - - return 0; -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_avx2/thash.h b/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_avx2/thash.h deleted file mode 100644 index 8db771a045..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_avx2/thash.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_THASH_H -#define PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_THASH_H - -#include "hash_state.h" - -#include - -void PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_avx2/thash_sha256_robust.c b/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_avx2/thash_sha256_robust.c deleted file mode 100644 index b8b0bdc611..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_avx2/thash_sha256_robust.c +++ /dev/null @@ -1,78 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "thash.h" - -#include "sha2.h" -#include "sha256.h" - -/** - * Takes an array of inblocks concatenated arrays of PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N bytes. - */ -static void thash( - unsigned char *out, unsigned char *buf, - const unsigned char *in, unsigned int inblocks, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char outbuf[PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_OUTPUT_BYTES]; - unsigned char *bitmask = buf + PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_ADDR_BYTES + 4; - sha256ctx sha2_state; - unsigned int i; - - memcpy(buf, pub_seed, PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N); - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_compress_address(buf + PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N, addr); - /* MGF1 requires us to have 4 extra bytes in 'buf' */ - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_mgf1(bitmask, inblocks * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N, buf, PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_ADDR_BYTES); - - /* Retrieve precomputed state containing pub_seed */ - sha256_inc_ctx_clone(&sha2_state, &hash_state_seeded->x1); - - for (i = 0; i < inblocks * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N; i++) { - buf[PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_ADDR_BYTES + i] = in[i] ^ bitmask[i]; - } - - sha256_inc_finalize(outbuf, &sha2_state, buf + PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N, - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N); - memcpy(out, outbuf, PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N); -} - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_ADDR_BYTES + 4 + 1 * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N]; - thash(out, buf, in, 1, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_ADDR_BYTES + 4 + 2 * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N]; - thash(out, buf, in, 2, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_ADDR_BYTES + 4 + PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_WOTS_LEN * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N]; - thash(out, buf, in, PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_WOTS_LEN, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_ADDR_BYTES + 4 + PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_FORS_TREES * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N]; - thash(out, buf, in, PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_FORS_TREES, pub_seed, addr, hash_state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_avx2/thash_sha256_robustx8.c b/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_avx2/thash_sha256_robustx8.c deleted file mode 100644 index 14b8e19ca2..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_avx2/thash_sha256_robustx8.c +++ /dev/null @@ -1,156 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "sha256.h" -#include "sha256avx.h" -#include "sha256x8.h" -#include "thashx8.h" -#include "utils.h" - -/** - * 8-way parallel version of thash; takes 8x as much input and output - */ -static void thashx8(uint8_t *out0, - uint8_t *out1, - uint8_t *out2, - uint8_t *out3, - uint8_t *out4, - uint8_t *out5, - uint8_t *out6, - uint8_t *out7, - const uint8_t *in0, - const uint8_t *in1, - const uint8_t *in2, - const uint8_t *in3, - const uint8_t *in4, - const uint8_t *in5, - const uint8_t *in6, - const uint8_t *in7, - unsigned int inblocks, - const uint8_t *pub_seed, - uint32_t addrx8[8 * 8], - uint8_t *bufx8, - uint8_t *bitmaskx8, - const hash_state *state_seeded) { - unsigned char outbufx8[8 * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_OUTPUT_BYTES]; - unsigned int i; - sha256ctxx8 ctx; - - (void)pub_seed; /* Suppress an 'unused parameter' warning. */ - - for (i = 0; i < 8; i++) { - memcpy(bufx8 + i * (PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N), - pub_seed, PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N); - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_compress_address(bufx8 + PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N + - i * (PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N), - addrx8 + i * 8); - } - - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_mgf1x8(bitmaskx8, inblocks * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N, - bufx8 + 0 * (PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N), - bufx8 + 1 * (PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N), - bufx8 + 2 * (PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N), - bufx8 + 3 * (PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N), - bufx8 + 4 * (PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N), - bufx8 + 5 * (PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N), - bufx8 + 6 * (PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N), - bufx8 + 7 * (PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N), - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_ADDR_BYTES - ); - - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_sha256_clone_statex8(&ctx, &state_seeded->x8); - - for (i = 0; i < inblocks * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N; i++) { - bufx8[PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_ADDR_BYTES + i + - 0 * (PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N)] = - in0[i] ^ bitmaskx8[i + 0 * (inblocks * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N)]; - bufx8[PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_ADDR_BYTES + i + - 1 * (PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N)] = - in1[i] ^ bitmaskx8[i + 1 * (inblocks * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N)]; - bufx8[PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_ADDR_BYTES + i + - 2 * (PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N)] = - in2[i] ^ bitmaskx8[i + 2 * (inblocks * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N)]; - bufx8[PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_ADDR_BYTES + i + - 3 * (PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N)] = - in3[i] ^ bitmaskx8[i + 3 * (inblocks * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N)]; - bufx8[PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_ADDR_BYTES + i + - 4 * (PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N)] = - in4[i] ^ bitmaskx8[i + 4 * (inblocks * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N)]; - bufx8[PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_ADDR_BYTES + i + - 5 * (PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N)] = - in5[i] ^ bitmaskx8[i + 5 * (inblocks * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N)]; - bufx8[PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_ADDR_BYTES + i + - 6 * (PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N)] = - in6[i] ^ bitmaskx8[i + 6 * (inblocks * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N)]; - bufx8[PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_ADDR_BYTES + i + - 7 * (PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N)] = - in7[i] ^ bitmaskx8[i + 7 * (inblocks * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N)]; - } - - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_sha256_update8x(&ctx, - bufx8 + PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N + 0 * (PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N), - bufx8 + PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N + 1 * (PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N), - bufx8 + PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N + 2 * (PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N), - bufx8 + PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N + 3 * (PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N), - bufx8 + PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N + 4 * (PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N), - bufx8 + PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N + 5 * (PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N), - bufx8 + PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N + 6 * (PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N), - bufx8 + PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N + 7 * (PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N), - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N); - - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_sha256_final8x(&ctx, - outbufx8 + 0 * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 1 * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 2 * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 3 * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 4 * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 5 * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 6 * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 7 * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_OUTPUT_BYTES); - - memcpy(out0, outbufx8 + 0 * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N); - memcpy(out1, outbufx8 + 1 * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N); - memcpy(out2, outbufx8 + 2 * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N); - memcpy(out3, outbufx8 + 3 * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N); - memcpy(out4, outbufx8 + 4 * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N); - memcpy(out5, outbufx8 + 5 * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N); - memcpy(out6, outbufx8 + 6 * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N); - memcpy(out7, outbufx8 + 7 * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N); -} - -#define thash_size_variant(name, size) \ - void PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_thashx8_##name(unsigned char *out0, \ - unsigned char *out1, \ - unsigned char *out2, \ - unsigned char *out3, \ - unsigned char *out4, \ - unsigned char *out5, \ - unsigned char *out6, \ - unsigned char *out7, \ - const unsigned char *in0, \ - const unsigned char *in1, \ - const unsigned char *in2, \ - const unsigned char *in3, \ - const unsigned char *in4, \ - const unsigned char *in5, \ - const unsigned char *in6, \ - const unsigned char *in7, \ - const unsigned char *pub_seed, \ - uint32_t addrx8[8*8], \ - const hash_state *state_seeded) { \ - const unsigned int inblocks = (size); \ - uint8_t bufx8[8*(PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N + PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_SHA256_ADDR_BYTES + (size)*PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N)]; \ - uint8_t bitmaskx8[8*((size) * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N)]; \ - thashx8(out0, out1, out2, out3, out4, out5, out6, out7, \ - in0, in1, in2, in3, in4, in5, in6, in7, inblocks, \ - pub_seed, addrx8, bufx8, bitmaskx8, state_seeded); \ - } - -thash_size_variant(1, 1) -thash_size_variant(2, 2) -thash_size_variant(WOTS_LEN, PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_WOTS_LEN) -thash_size_variant(FORS_TREES, PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_FORS_TREES) - -#undef thash_size_variant diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_avx2/thashx8.h b/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_avx2/thashx8.h deleted file mode 100644 index cf5c061636..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_avx2/thashx8.h +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_THASHX8_H -#define PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_THASHX8_H - -#include - -#include "hash_state.h" -#include "sha256avx.h" - - -#define thashx8_variant(name) \ - void PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_thashx8_##name( \ - unsigned char *out0, \ - unsigned char *out1, \ - unsigned char *out2, \ - unsigned char *out3, \ - unsigned char *out4, \ - unsigned char *out5, \ - unsigned char *out6, \ - unsigned char *out7, \ - const unsigned char *in0, \ - const unsigned char *in1, \ - const unsigned char *in2, \ - const unsigned char *in3, \ - const unsigned char *in4, \ - const unsigned char *in5, \ - const unsigned char *in6, \ - const unsigned char *in7, \ - const unsigned char *pub_seed, \ - uint32_t addrx8[8*8], \ - const hash_state *state_seeded) - - -thashx8_variant(1); -thashx8_variant(2); -thashx8_variant(WOTS_LEN); -thashx8_variant(FORS_TREES); - -#undef thashx8_variant -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_avx2/utils.c b/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_avx2/utils.c deleted file mode 100644 index 943db620f8..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_avx2/utils.c +++ /dev/null @@ -1,199 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "hash_state.h" -#include "params.h" -#include "thash.h" -#include "utils.h" - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in) { - - /* Iterate over out in decreasing order, for big-endianness. */ - for (size_t i = outlen; i > 0; i--) { - out[i - 1] = in & 0xff; - in = in >> 8; - } -} - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_bytes_to_ull( - const unsigned char *in, size_t inlen) { - unsigned long long retval = 0; - - for (size_t i = 0; i < inlen; i++) { - retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); - } - return retval; -} - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - uint32_t i; - unsigned char buffer[2 * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N]; - - /* If leaf_idx is odd (last bit = 1), current path element is a right child - and auth_path has to go left. Otherwise it is the other way around. */ - if (leaf_idx & 1) { - memcpy(buffer + PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N, leaf, PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N); - } else { - memcpy(buffer, leaf, PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N); - memcpy(buffer + PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N, auth_path, PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N); - } - auth_path += PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N; - - for (i = 0; i < tree_height - 1; i++) { - leaf_idx >>= 1; - idx_offset >>= 1; - /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_set_tree_height(addr, i + 1); - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_set_tree_index( - addr, leaf_idx + idx_offset); - - /* Pick the right or left neighbor, depending on parity of the node. */ - if (leaf_idx & 1) { - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_thash_2( - buffer + PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N); - } else { - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_thash_2( - buffer, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer + PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N, auth_path, PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N); - } - auth_path += PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N; - } - - /* The last iteration is exceptional; we do not copy an auth_path node. */ - leaf_idx >>= 1; - idx_offset >>= 1; - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_set_tree_height(addr, tree_height); - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_set_tree_index( - addr, leaf_idx + idx_offset); - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_thash_2( - root, buffer, pub_seed, addr, hash_state_seeded); -} - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -static void PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_treehash( - unsigned char *root, unsigned char *auth_path, - unsigned char *stack, unsigned int *heights, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - - unsigned int offset = 0; - uint32_t idx; - uint32_t tree_idx; - - for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { - /* Add the next leaf node to the stack. */ - gen_leaf(stack + offset * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N, - sk_seed, pub_seed, idx + idx_offset, tree_addr, - hash_state_seeded); - offset++; - heights[offset - 1] = 0; - - /* If this is a node we need for the auth path.. */ - if ((leaf_idx ^ 0x1) == idx) { - memcpy(auth_path, stack + (offset - 1)*PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N, PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N); - } - - /* While the top-most nodes are of equal height.. */ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { - /* Compute index of the new node, in the next layer. */ - tree_idx = (idx >> (heights[offset - 1] + 1)); - - /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_set_tree_height( - tree_addr, heights[offset - 1] + 1); - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_set_tree_index( - tree_addr, tree_idx + (idx_offset >> (heights[offset - 1] + 1))); - /* Hash the top-most nodes from the stack together. */ - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_thash_2( - stack + (offset - 2)*PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N, stack + (offset - 2)*PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N, - pub_seed, tree_addr, hash_state_seeded); - offset--; - /* Note that the top-most node is now one layer higher. */ - heights[offset - 1]++; - - /* If this is a node we need for the auth path.. */ - if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_path + heights[offset - 1]*PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N, - stack + (offset - 1)*PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N, PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N); - } - } - } - memcpy(root, stack, PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N); -} - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_FORS_HEIGHT + 1)*PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N]; - unsigned int heights[PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_FORS_HEIGHT + 1]; - - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_FORS_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_TREE_HEIGHT + 1)*PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N]; - unsigned int heights[PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_TREE_HEIGHT + 1]; - - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_TREE_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_avx2/utils.h b/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_avx2/utils.h deleted file mode 100644 index fbf19ec222..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_avx2/utils.h +++ /dev/null @@ -1,64 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_UTILS_H -#define PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_UTILS_H - -#include "hash_state.h" -#include "params.h" -#include -#include - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in); - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_bytes_to_ull( - const unsigned char *in, size_t inlen); - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -void PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_avx2/utilsx8.c b/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_avx2/utilsx8.c deleted file mode 100644 index 7a7843f971..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_avx2/utilsx8.c +++ /dev/null @@ -1,172 +0,0 @@ -#include - -#include "address.h" -#include "params.h" -#include "thashx8.h" -#include "utils.h" - -#include "utilsx8.h" - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -static void treehashx8(unsigned char *rootx8, unsigned char *auth_pathx8, - unsigned char *stackx8, unsigned int *heights, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t leaf_idx[8], uint32_t idx_offset[8], - uint32_t tree_height, - void (*gen_leafx8)( - unsigned char * /* leaf0 */, - unsigned char * /* leaf1 */, - unsigned char * /* leaf2 */, - unsigned char * /* leaf3 */, - unsigned char * /* leaf4 */, - unsigned char * /* leaf5 */, - unsigned char * /* leaf6 */, - unsigned char * /* leaf7 */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx0 */, - uint32_t /* addr_idx1 */, - uint32_t /* addr_idx2 */, - uint32_t /* addr_idx3 */, - uint32_t /* addr_idx4 */, - uint32_t /* addr_idx5 */, - uint32_t /* addr_idx6 */, - uint32_t /* addr_idx7 */, - const uint32_t[8] /* tree_addr */, - const hash_state * /* state_seeded */), - uint32_t tree_addrx8[8 * 8], - const hash_state *state_seeded) { - unsigned int offset = 0; - uint32_t idx; - uint32_t tree_idx; - unsigned int j; - - for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { - /* Add the next leaf node to the stack. */ - gen_leafx8(stackx8 + 0 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N + offset * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N, - stackx8 + 1 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N + offset * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N, - stackx8 + 2 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N + offset * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N, - stackx8 + 3 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N + offset * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N, - stackx8 + 4 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N + offset * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N, - stackx8 + 5 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N + offset * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N, - stackx8 + 6 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N + offset * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N, - stackx8 + 7 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N + offset * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N, - sk_seed, pub_seed, - idx + idx_offset[0], - idx + idx_offset[1], - idx + idx_offset[2], - idx + idx_offset[3], - idx + idx_offset[4], - idx + idx_offset[5], - idx + idx_offset[6], - idx + idx_offset[7], - tree_addrx8, - state_seeded); - offset++; - heights[offset - 1] = 0; - - /* If this is a node we need for the auth path.. */ - for (j = 0; j < 8; j++) { - if ((leaf_idx[j] ^ 0x1) == idx) { - memcpy(auth_pathx8 + j * tree_height * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N, - stackx8 + j * (tree_height + 1)*PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N + (offset - 1)*PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N, PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N); - } - } - - /* While the top-most nodes are of equal height.. */ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { - /* Compute index of the new node, in the next layer. */ - tree_idx = (idx >> (heights[offset - 1] + 1)); - - /* Set the address of the node we're creating. */ - for (j = 0; j < 8; j++) { - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_set_tree_height(tree_addrx8 + j * 8, heights[offset - 1] + 1); - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_set_tree_index(tree_addrx8 + j * 8, - tree_idx + (idx_offset[j] >> (heights[offset - 1] + 1))); - } - /* Hash the top-most nodes from the stack together. */ - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_thashx8_2(stackx8 + 0 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N, - stackx8 + 1 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N, - stackx8 + 2 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N, - stackx8 + 3 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N, - stackx8 + 4 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N, - stackx8 + 5 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N, - stackx8 + 6 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N, - stackx8 + 7 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N, - stackx8 + 0 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N, - stackx8 + 1 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N, - stackx8 + 2 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N, - stackx8 + 3 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N, - stackx8 + 4 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N, - stackx8 + 5 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N, - stackx8 + 6 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N, - stackx8 + 7 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N, - pub_seed, tree_addrx8, state_seeded); - offset--; - /* Note that the top-most node is now one layer higher. */ - heights[offset - 1]++; - - /* If this is a node we need for the auth path.. */ - for (j = 0; j < 8; j++) { - if (((leaf_idx[j] >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_pathx8 + j * tree_height * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N + heights[offset - 1]*PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N, - stackx8 + j * (tree_height + 1)*PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N + (offset - 1)*PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N, PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N); - } - } - } - } - - for (j = 0; j < 8; j++) { - memcpy(rootx8 + j * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N, stackx8 + j * (tree_height + 1)*PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N, PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N); - } -} - -/* The wrappers below ensure we used fixed-size buffers on the stack (no VLAs) */ - - -#define treehashx8_variant(name, size) \ - void PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_treehashx8_##name( \ - unsigned char *rootx8, unsigned char *auth_pathx8, \ - const unsigned char *sk_seed, const unsigned char *pub_seed, \ - const uint32_t leaf_idx[8], uint32_t idx_offset[8], \ - void (*gen_leafx8)( \ - unsigned char* /* leaf0 */, \ - unsigned char* /* leaf1 */, \ - unsigned char* /* leaf2 */, \ - unsigned char* /* leaf3 */, \ - unsigned char* /* leaf4 */, \ - unsigned char* /* leaf5 */, \ - unsigned char* /* leaf6 */, \ - unsigned char* /* leaf7 */, \ - const unsigned char* /* sk_seed */, \ - const unsigned char* /* pub_seed */, \ - uint32_t /* addr_idx0 */, \ - uint32_t /* addr_idx1 */, \ - uint32_t /* addr_idx2 */, \ - uint32_t /* addr_idx3 */, \ - uint32_t /* addr_idx4 */, \ - uint32_t /* addr_idx5 */, \ - uint32_t /* addr_idx6 */, \ - uint32_t /* addr_idx7 */, \ - const uint32_t[8] /* tree_addr */, \ - const hash_state* /* state_seeded */), \ - uint32_t tree_addrx8[8*8], \ - const hash_state *state_seeded) \ - { \ - const uint32_t tree_height = (size); \ - unsigned char stackx8[8*((size) + 1)*PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N]; \ - unsigned int heights[(size) + 1]; \ - treehashx8(rootx8, auth_pathx8, stackx8, heights, sk_seed, pub_seed, \ - leaf_idx, idx_offset, tree_height, gen_leafx8, tree_addrx8, state_seeded); \ - } - -treehashx8_variant(FORS_HEIGHT, PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_FORS_HEIGHT) - -#undef treehashx8_variant diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_avx2/utilsx8.h b/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_avx2/utilsx8.h deleted file mode 100644 index 6e27f56d70..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_avx2/utilsx8.h +++ /dev/null @@ -1,46 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_UTILSX8_H -#define PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_UTILSX8_H - -#include - -#include "hash_state.h" -#include "params.h" - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ - -void PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_treehashx8_FORS_HEIGHT( - unsigned char *rootx8, unsigned char *auth_pathx8, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t leaf_idx[8], uint32_t idx_offset[8], - void (*gen_leafx8)( - unsigned char * /* leaf0 */, - unsigned char * /* leaf1 */, - unsigned char * /* leaf2 */, - unsigned char * /* leaf3 */, - unsigned char * /* leaf4 */, - unsigned char * /* leaf5 */, - unsigned char * /* leaf6 */, - unsigned char * /* leaf7 */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx0 */, - uint32_t /* addr_idx1 */, - uint32_t /* addr_idx2 */, - uint32_t /* addr_idx3 */, - uint32_t /* addr_idx4 */, - uint32_t /* addr_idx5 */, - uint32_t /* addr_idx6 */, - uint32_t /* addr_idx7 */, - const uint32_t[8] /* tree_addr */, - const hash_state * /* state_seeded */), - uint32_t tree_addrx8[8 * 8], - const hash_state *state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_avx2/wots.c b/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_avx2/wots.c deleted file mode 100644 index b665943eed..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_avx2/wots.c +++ /dev/null @@ -1,240 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "hash_state.h" -#include "hashx8.h" -#include "params.h" -#include "thash.h" -#include "thashx8.h" -#include "utils.h" -#include "wots.h" - -// TODO clarify address expectations, and make them more uniform. -// TODO i.e. do we expect types to be set already? -// TODO and do we expect modifications or copies? - -/** - * Computes the starting value for a chain, i.e. the secret key. - * Expects the address to be complete up to the chain address. - */ -static void wots_gen_sk(unsigned char *sk, const unsigned char *sk_seed, - uint32_t wots_addr[8], const hash_state *state_seeded) { - /* Make sure that the hash address is actually zeroed. */ - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_set_hash_addr(wots_addr, 0); - - /* Generate sk element. */ - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_prf_addr(sk, sk_seed, wots_addr, state_seeded); -} - -/** - * 8-way parallel version of wots_gen_sk; expects 8x as much space in sk - */ -static void wots_gen_skx8(unsigned char *skx8, const unsigned char *sk_seed, - uint32_t wots_addrx8[8 * 8]) { - unsigned int j; - - /* Make sure that the hash address is actually zeroed. */ - for (j = 0; j < 8; j++) { - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_set_hash_addr(wots_addrx8 + j * 8, 0); - } - - /* Generate sk element. */ - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_prf_addrx8(skx8 + 0 * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N, - skx8 + 1 * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N, - skx8 + 2 * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N, - skx8 + 3 * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N, - skx8 + 4 * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N, - skx8 + 5 * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N, - skx8 + 6 * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N, - skx8 + 7 * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N, - sk_seed, wots_addrx8); -} - -/** - * Computes the chaining function. - * out and in have to be n-byte arrays. - * - * Interprets in as start-th value of the chain. - * addr has to contain the address of the chain. - */ -static void gen_chain(unsigned char *out, const unsigned char *in, - unsigned int start, unsigned int steps, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *state_seeded) { - uint32_t i; - - /* Initialize out with the value at position 'start'. */ - memcpy(out, in, PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N); - - /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_WOTS_W; i++) { - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_set_hash_addr(addr, i); - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_thash_1(out, out, pub_seed, addr, state_seeded); - } -} - -/** - * 8-way parallel version of gen_chain; expects 8x as much space in out, and - * 8x as much space in inx8. Assumes start and step identical across chains. - */ -static void gen_chainx8(unsigned char *outx8, const unsigned char *inx8, - unsigned int start, unsigned int steps, - const unsigned char *pub_seed, uint32_t addrx8[8 * 8], - const hash_state *state_seeded) { - uint32_t i; - unsigned int j; - - /* Initialize outx8 with the value at position 'start'. */ - memcpy(outx8, inx8, 8 * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N); - - /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_WOTS_W; i++) { - for (j = 0; j < 8; j++) { - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_set_hash_addr(addrx8 + j * 8, i); - } - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_thashx8_1(outx8 + 0 * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N, - outx8 + 1 * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N, - outx8 + 2 * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N, - outx8 + 3 * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N, - outx8 + 4 * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N, - outx8 + 5 * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N, - outx8 + 6 * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N, - outx8 + 7 * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N, - outx8 + 0 * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N, - outx8 + 1 * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N, - outx8 + 2 * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N, - outx8 + 3 * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N, - outx8 + 4 * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N, - outx8 + 5 * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N, - outx8 + 6 * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N, - outx8 + 7 * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N, - pub_seed, addrx8, state_seeded); - } -} - -/** - * base_w algorithm as described in draft. - * Interprets an array of bytes as integers in base w. - * This only works when log_w is a divisor of 8. - */ -static void base_w(unsigned int *output, const int out_len, const unsigned char *input) { - int in = 0; - int out = 0; - unsigned char total = 0; - int bits = 0; - int consumed; - - for (consumed = 0; consumed < out_len; consumed++) { - if (bits == 0) { - total = input[in]; - in++; - bits += 8; - } - bits -= PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_WOTS_LOGW; - output[out] = (unsigned int)(total >> bits) & (PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_WOTS_W - 1); - out++; - } -} - -/* Computes the WOTS+ checksum over a message (in base_w). */ -static void wots_checksum(unsigned int *csum_base_w, const unsigned int *msg_base_w) { - unsigned int csum = 0; - unsigned char csum_bytes[(PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_WOTS_LEN2 * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_WOTS_LOGW + 7) / 8]; - unsigned int i; - - /* Compute checksum. */ - for (i = 0; i < PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_WOTS_LEN1; i++) { - csum += PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_WOTS_W - 1 - msg_base_w[i]; - } - - /* Convert checksum to base_w. */ - /* Make sure expected empty zero bits are the least significant bits. */ - csum = csum << (8 - ((PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_WOTS_LEN2 * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_WOTS_LOGW) % 8)); - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); - base_w(csum_base_w, PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_WOTS_LEN2, csum_bytes); -} - -/* Takes a message and derives the matching chain lengths. */ -static void chain_lengths(unsigned int *lengths, const unsigned char *msg) { - base_w(lengths, PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_WOTS_LEN1, msg); - wots_checksum(lengths + PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_WOTS_LEN1, lengths); -} - -/** - * WOTS key generation. Takes a 32 byte sk_seed, expands it to WOTS private key - * elements and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_wots_gen_pk(unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *state_seeded) { - uint32_t i; - unsigned int j; - - uint32_t addrx8[8 * 8]; - unsigned char pkbuf[8 * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N]; - - for (j = 0; j < 8; j++) { - memcpy(addrx8 + j * 8, addr, sizeof(uint32_t) * 8); - } - - /* The last iteration typically does not have complete set of 4 chains, - but because we use pkbuf, this is not an issue -- we still do as many - in parallel as possible. */ - for (i = 0; i < ((PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_WOTS_LEN + 7) & ~0x7); i += 8) { - for (j = 0; j < 8; j++) { - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_set_chain_addr(addrx8 + j * 8, i + j); - } - wots_gen_skx8(pkbuf, sk_seed, addrx8); - gen_chainx8(pkbuf, pkbuf, 0, PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_WOTS_W - 1, pub_seed, addrx8, state_seeded); - for (j = 0; j < 8; j++) { - if (i + j < PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_WOTS_LEN) { - memcpy(pk + (i + j)*PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N, pkbuf + j * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N, PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N); - } - } - } -} - -/** - * Takes a n-byte message and the 32-byte sk_see to compute a signature 'sig'. - */ -void PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_wots_sign(unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_WOTS_LEN; i++) { - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_set_chain_addr(addr, i); - wots_gen_sk(sig + i * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N, sk_seed, addr, state_seeded); - gen_chain(sig + i * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N, sig + i * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N, 0, lengths[i], pub_seed, addr, state_seeded); - } -} - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_WOTS_LEN; i++) { - PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_set_chain_addr(addr, i); - gen_chain(pk + i * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N, sig + i * PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_N, - lengths[i], PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_WOTS_W - 1 - lengths[i], pub_seed, addr, state_seeded); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_avx2/wots.h b/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_avx2/wots.h deleted file mode 100644 index 404bb9a187..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_avx2/wots.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_WOTS_H -#define PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_WOTS_H - -#include "hash_state.h" -#include "params.h" -#include - -/** - * WOTS key generation. Takes a 32 byte seed for the private key, expands it to - * a full WOTS private key and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_wots_gen_pk( - unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -/** - * Takes a n-byte message and the 32-byte seed for the private key to compute a - * signature that is placed at 'sig'. - */ -void PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_wots_sign( - unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *hash_state_seeded); - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHA256256SROBUST_AVX2_wots_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_clean/LICENSE b/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_clean/LICENSE deleted file mode 100644 index 670154e353..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_clean/LICENSE +++ /dev/null @@ -1,116 +0,0 @@ -CC0 1.0 Universal - -Statement of Purpose - -The laws of most jurisdictions throughout the world automatically confer -exclusive Copyright and Related Rights (defined below) upon the creator and -subsequent owner(s) (each and all, an "owner") of an original work of -authorship and/or a database (each, a "Work"). - -Certain owners wish to permanently relinquish those rights to a Work for the -purpose of contributing to a commons of creative, cultural and scientific -works ("Commons") that the public can reliably and without fear of later -claims of infringement build upon, modify, incorporate in other works, reuse -and redistribute as freely as possible in any form whatsoever and for any -purposes, including without limitation commercial purposes. These owners may -contribute to the Commons to promote the ideal of a free culture and the -further production of creative, cultural and scientific works, or to gain -reputation or greater distribution for their Work in part through the use and -efforts of others. - -For these and/or other purposes and motivations, and without any expectation -of additional consideration or compensation, the person associating CC0 with a -Work (the "Affirmer"), to the extent that he or she is an owner of Copyright -and Related Rights in the Work, voluntarily elects to apply CC0 to the Work -and publicly distribute the Work under its terms, with knowledge of his or her -Copyright and Related Rights in the Work and the meaning and intended legal -effect of CC0 on those rights. - -1. Copyright and Related Rights. A Work made available under CC0 may be -protected by copyright and related or neighboring rights ("Copyright and -Related Rights"). Copyright and Related Rights include, but are not limited -to, the following: - - i. the right to reproduce, adapt, distribute, perform, display, communicate, - and translate a Work; - - ii. moral rights retained by the original author(s) and/or performer(s); - - iii. publicity and privacy rights pertaining to a person's image or likeness - depicted in a Work; - - iv. rights protecting against unfair competition in regards to a Work, - subject to the limitations in paragraph 4(a), below; - - v. rights protecting the extraction, dissemination, use and reuse of data in - a Work; - - vi. database rights (such as those arising under Directive 96/9/EC of the - European Parliament and of the Council of 11 March 1996 on the legal - protection of databases, and under any national implementation thereof, - including any amended or successor version of such directive); and - - vii. other similar, equivalent or corresponding rights throughout the world - based on applicable law or treaty, and any national implementations thereof. - -2. Waiver. To the greatest extent permitted by, but not in contravention of, -applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and -unconditionally waives, abandons, and surrenders all of Affirmer's Copyright -and Related Rights and associated claims and causes of action, whether now -known or unknown (including existing as well as future claims and causes of -action), in the Work (i) in all territories worldwide, (ii) for the maximum -duration provided by applicable law or treaty (including future time -extensions), (iii) in any current or future medium and for any number of -copies, and (iv) for any purpose whatsoever, including without limitation -commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes -the Waiver for the benefit of each member of the public at large and to the -detriment of Affirmer's heirs and successors, fully intending that such Waiver -shall not be subject to revocation, rescission, cancellation, termination, or -any other legal or equitable action to disrupt the quiet enjoyment of the Work -by the public as contemplated by Affirmer's express Statement of Purpose. - -3. Public License Fallback. Should any part of the Waiver for any reason be -judged legally invalid or ineffective under applicable law, then the Waiver -shall be preserved to the maximum extent permitted taking into account -Affirmer's express Statement of Purpose. In addition, to the extent the Waiver -is so judged Affirmer hereby grants to each affected person a royalty-free, -non transferable, non sublicensable, non exclusive, irrevocable and -unconditional license to exercise Affirmer's Copyright and Related Rights in -the Work (i) in all territories worldwide, (ii) for the maximum duration -provided by applicable law or treaty (including future time extensions), (iii) -in any current or future medium and for any number of copies, and (iv) for any -purpose whatsoever, including without limitation commercial, advertising or -promotional purposes (the "License"). The License shall be deemed effective as -of the date CC0 was applied by Affirmer to the Work. Should any part of the -License for any reason be judged legally invalid or ineffective under -applicable law, such partial invalidity or ineffectiveness shall not -invalidate the remainder of the License, and in such case Affirmer hereby -affirms that he or she will not (i) exercise any of his or her remaining -Copyright and Related Rights in the Work or (ii) assert any associated claims -and causes of action with respect to the Work, in either case contrary to -Affirmer's express Statement of Purpose. - -4. Limitations and Disclaimers. - - a. No trademark or patent rights held by Affirmer are waived, abandoned, - surrendered, licensed or otherwise affected by this document. - - b. Affirmer offers the Work as-is and makes no representations or warranties - of any kind concerning the Work, express, implied, statutory or otherwise, - including without limitation warranties of title, merchantability, fitness - for a particular purpose, non infringement, or the absence of latent or - other defects, accuracy, or the present or absence of errors, whether or not - discoverable, all to the greatest extent permissible under applicable law. - - c. Affirmer disclaims responsibility for clearing rights of other persons - that may apply to the Work or any use thereof, including without limitation - any person's Copyright and Related Rights in the Work. Further, Affirmer - disclaims responsibility for obtaining any necessary consents, permissions - or other rights required for any use of the Work. - - d. Affirmer understands and acknowledges that Creative Commons is not a - party to this document and has no duty or obligation with respect to this - CC0 or use of the Work. - -For more information, please see - diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_clean/address.c b/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_clean/address.c deleted file mode 100644 index fe9222930e..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_clean/address.c +++ /dev/null @@ -1,78 +0,0 @@ -#include - -#include "address.h" -#include "params.h" -#include "utils.h" - -void PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]) { - int i; - - for (i = 0; i < 8; i++) { - PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_ull_to_bytes( - bytes + i * 4, 4, addr[i]); - } -} - -void PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_set_layer_addr( - uint32_t addr[8], uint32_t layer) { - addr[0] = layer; -} - -void PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_set_tree_addr( - uint32_t addr[8], uint64_t tree) { - addr[1] = 0; - addr[2] = (uint32_t) (tree >> 32); - addr[3] = (uint32_t) tree; -} - -void PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_set_type( - uint32_t addr[8], uint32_t type) { - addr[4] = type; -} - -void PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; -} - -/* These functions are used for OTS addresses. */ - -void PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_set_keypair_addr( - uint32_t addr[8], uint32_t keypair) { - addr[5] = keypair; -} - -void PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; - out[5] = in[5]; -} - -void PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_set_chain_addr( - uint32_t addr[8], uint32_t chain) { - addr[6] = chain; -} - -void PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_set_hash_addr( - uint32_t addr[8], uint32_t hash) { - addr[7] = hash; -} - -/* These functions are used for all hash tree addresses (including FORS). */ - -void PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_set_tree_height( - uint32_t addr[8], uint32_t tree_height) { - addr[6] = tree_height; -} - -void PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_set_tree_index( - uint32_t addr[8], uint32_t tree_index) { - addr[7] = tree_index; -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_clean/address.h b/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_clean/address.h deleted file mode 100644 index a65b384a8a..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_clean/address.h +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_ADDRESS_H -#define PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_ADDRESS_H - -#include - -#define PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_ADDR_TYPE_WOTS 0 -#define PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_ADDR_TYPE_WOTSPK 1 -#define PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_ADDR_TYPE_HASHTREE 2 -#define PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_ADDR_TYPE_FORSTREE 3 -#define PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_ADDR_TYPE_FORSPK 4 - -void PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]); - -void PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_set_layer_addr( - uint32_t addr[8], uint32_t layer); - -void PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_set_tree_addr( - uint32_t addr[8], uint64_t tree); - -void PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_set_type( - uint32_t addr[8], uint32_t type); - -/* Copies the layer and tree part of one address into the other */ -void PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for WOTS and FORS addresses. */ - -void PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_set_keypair_addr( - uint32_t addr[8], uint32_t keypair); - -void PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_set_chain_addr( - uint32_t addr[8], uint32_t chain); - -void PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_set_hash_addr( - uint32_t addr[8], uint32_t hash); - -void PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for all hash tree addresses (including FORS). */ - -void PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_set_tree_height( - uint32_t addr[8], uint32_t tree_height); - -void PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_set_tree_index( - uint32_t addr[8], uint32_t tree_index); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_clean/api.h b/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_clean/api.h deleted file mode 100644 index 8d9f42ad09..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_clean/api.h +++ /dev/null @@ -1,81 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_API_H -#define PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_API_H - -#include -#include - - - -#define PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_CRYPTO_ALGNAME "SPHINCS+" - -#define PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_CRYPTO_SECRETKEYBYTES 128 -#define PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_CRYPTO_PUBLICKEYBYTES 64 -#define PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_CRYPTO_BYTES 29792 -#define PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_CRYPTO_SEEDBYTES 96 - - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_clean/fors.c b/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_clean/fors.c deleted file mode 100644 index b6c5f1cd0c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_clean/fors.c +++ /dev/null @@ -1,161 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "fors.h" -#include "hash.h" -#include "hash_state.h" -#include "thash.h" -#include "utils.h" - -static void fors_gen_sk(unsigned char *sk, const unsigned char *sk_seed, - uint32_t fors_leaf_addr[8], const hash_state *hash_state_seeded) { - PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_prf_addr( - sk, sk_seed, fors_leaf_addr, hash_state_seeded); -} - -static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, - const unsigned char *pub_seed, - uint32_t fors_leaf_addr[8], - const hash_state *hash_state_seeded) { - PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_thash_1( - leaf, sk, pub_seed, fors_leaf_addr, hash_state_seeded); -} - -static void fors_gen_leaf(unsigned char *leaf, const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx, const uint32_t fors_tree_addr[8], - const hash_state *hash_state_seeded) { - uint32_t fors_leaf_addr[8] = {0}; - - /* Only copy the parts that must be kept in fors_leaf_addr. */ - PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_copy_keypair_addr( - fors_leaf_addr, fors_tree_addr); - PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_set_type( - fors_leaf_addr, PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_set_tree_index( - fors_leaf_addr, addr_idx); - - fors_gen_sk(leaf, sk_seed, fors_leaf_addr, hash_state_seeded); - fors_sk_to_leaf(leaf, leaf, pub_seed, fors_leaf_addr, hash_state_seeded); -} - -/** - * Interprets m as PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_FORS_HEIGHT-bit unsigned integers. - * Assumes m contains at least PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_FORS_TREES bits. - * Assumes indices has space for PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_FORS_TREES integers. - */ -static void message_to_indices(uint32_t *indices, const unsigned char *m) { - unsigned int i, j; - unsigned int offset = 0; - - for (i = 0; i < PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_FORS_TREES; i++) { - indices[i] = 0; - for (j = 0; j < PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_FORS_HEIGHT; j++) { - indices[i] ^= (((uint32_t)m[offset >> 3] >> (offset & 0x7)) & 0x1) << j; - offset++; - } - } -} - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_fors_sign( - unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *hash_state_seeded) { - uint32_t indices[PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_FORS_TREES]; - unsigned char roots[PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_FORS_TREES * PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_N]; - uint32_t fors_tree_addr[8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_copy_keypair_addr( - fors_tree_addr, fors_addr); - PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_copy_keypair_addr( - fors_pk_addr, fors_addr); - - PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_set_type( - fors_tree_addr, PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_set_type( - fors_pk_addr, PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_FORS_TREES; i++) { - idx_offset = i * (1 << PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_FORS_HEIGHT); - - PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_set_tree_height( - fors_tree_addr, 0); - PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_set_tree_index( - fors_tree_addr, indices[i] + idx_offset); - - /* Include the secret key part that produces the selected leaf node. */ - fors_gen_sk(sig, sk_seed, fors_tree_addr, hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_N; - - /* Compute the authentication path for this leaf node. */ - PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_treehash_FORS_HEIGHT( - roots + i * PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_N, sig, sk_seed, pub_seed, - indices[i], idx_offset, fors_gen_leaf, fors_tree_addr, - hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_N * PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_thash_FORS_TREES( - pk, roots, pub_seed, fors_pk_addr, hash_state_seeded); -} - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_fors_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, const uint32_t fors_addr[8], - const hash_state *hash_state_seeded) { - uint32_t indices[PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_FORS_TREES]; - unsigned char roots[PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_FORS_TREES * PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_N]; - unsigned char leaf[PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_N]; - uint32_t fors_tree_addr[8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_copy_keypair_addr(fors_tree_addr, fors_addr); - PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_copy_keypair_addr(fors_pk_addr, fors_addr); - - PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_set_type(fors_tree_addr, PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_set_type(fors_pk_addr, PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_FORS_TREES; i++) { - idx_offset = i * (1 << PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_FORS_HEIGHT); - - PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_set_tree_height(fors_tree_addr, 0); - PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Derive the leaf from the included secret key part. */ - fors_sk_to_leaf(leaf, sig, pub_seed, fors_tree_addr, hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_N; - - /* Derive the corresponding root node of this tree. */ - PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_compute_root(roots + i * PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_N, leaf, indices[i], idx_offset, sig, - PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_FORS_HEIGHT, pub_seed, fors_tree_addr, hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_N * PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_thash_FORS_TREES(pk, roots, pub_seed, fors_pk_addr, hash_state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_clean/fors.h b/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_clean/fors.h deleted file mode 100644 index 1e0417d085..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_clean/fors.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_FORS_H -#define PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_FORS_H - -#include - -#include "hash_state.h" -#include "params.h" - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_fors_sign( - unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *hash_state_seeded); - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_fors_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, const uint32_t fors_addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_clean/hash.h b/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_clean/hash.h deleted file mode 100644 index 20f35f9197..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_clean/hash.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_HASH_H -#define PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_HASH_H - -#include "hash_state.h" - -#include -#include - -void PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_initialize_hash_function( - hash_state *hash_state_seeded, - const unsigned char *pub_seed, const unsigned char *sk_seed); - -void PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_destroy_hash_function(hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_clean/hash_sha256.c b/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_clean/hash_sha256.c deleted file mode 100644 index a8264f8ae5..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_clean/hash_sha256.c +++ /dev/null @@ -1,162 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "utils.h" - -#include "sha2.h" -#include "sha256.h" - -/* For SHA256, there is no immediate reason to initialize at the start, - so this function is an empty operation. */ -void PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_initialize_hash_function( - hash_state *hash_state_seeded, - const unsigned char *pub_seed, const unsigned char *sk_seed) { - PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_seed_state(hash_state_seeded, pub_seed); - (void)sk_seed; /* Suppress an 'unused parameter' warning. */ -} - -/* Clean up hash state */ -void PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_destroy_hash_function(hash_state *hash_state_seeded) { - sha256_inc_ctx_release(hash_state_seeded); -} - -/* - * Computes PRF(key, addr), given a secret key of PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_N bytes and an address - */ -void PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded) { - unsigned char buf[PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_N + PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_SHA256_ADDR_BYTES]; - unsigned char outbuf[PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_SHA256_OUTPUT_BYTES]; - - memcpy(buf, key, PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_N); - PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_compress_address(buf + PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_N, addr); - - sha256(outbuf, buf, PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_N + PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_SHA256_ADDR_BYTES); - memcpy(out, outbuf, PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_N); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} - -/** - * Computes the message-dependent randomness R, using a secret seed as a key - * for HMAC, and an optional randomization value prefixed to the message. - * This requires m to have at least PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_SHA256_BLOCK_BYTES + PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_N space - * available in front of the pointer, i.e. before the message to use for the - * prefix. This is necessary to prevent having to move the message around (and - * allocate memory for it). - */ -void PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, const hash_state *hash_state_seeded) { - unsigned char buf[PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_SHA256_BLOCK_BYTES + PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_SHA256_OUTPUT_BYTES]; - sha256ctx state; - int i; - - /* This implements HMAC-SHA256 */ - for (i = 0; i < PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_N; i++) { - buf[i] = 0x36 ^ sk_prf[i]; - } - memset(buf + PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_N, 0x36, PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_N); - - sha256_inc_init(&state); - sha256_inc_blocks(&state, buf, 1); - - memcpy(buf, optrand, PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_N); - - /* If optrand + message cannot fill up an entire block */ - if (PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_N + mlen < PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_SHA256_BLOCK_BYTES) { - memcpy(buf + PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_N, m, mlen); - sha256_inc_finalize(buf + PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_SHA256_BLOCK_BYTES, &state, - buf, mlen + PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_N); - } - /* Otherwise first fill a block, so that finalize only uses the message */ - else { - memcpy(buf + PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_N, m, PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_N); - sha256_inc_blocks(&state, buf, 1); - - m += PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_N; - mlen -= PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_N; - sha256_inc_finalize(buf + PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_SHA256_BLOCK_BYTES, &state, m, mlen); - } - - for (i = 0; i < PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_N; i++) { - buf[i] = 0x5c ^ sk_prf[i]; - } - memset(buf + PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_N, 0x5c, PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_N); - - sha256(buf, buf, PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_SHA256_BLOCK_BYTES + PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_SHA256_OUTPUT_BYTES); - memcpy(R, buf, PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_N); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} - -/** - * Computes the message hash using R, the public key, and the message. - * Outputs the message digest and the index of the leaf. The index is split in - * the tree index and the leaf index, for convenient copying to an address. - */ -void PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded) { -#define PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_TREE_BITS (PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_TREE_HEIGHT * (PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_D - 1)) -#define PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_TREE_BYTES ((PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_TREE_BITS + 7) / 8) -#define PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_LEAF_BITS PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_TREE_HEIGHT -#define PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_LEAF_BYTES ((PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_LEAF_BITS + 7) / 8) -#define PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_DGST_BYTES (PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_FORS_MSG_BYTES + PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_TREE_BYTES + PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_LEAF_BYTES) - - unsigned char seed[PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_SHA256_OUTPUT_BYTES + 4]; - - /* Round to nearest multiple of PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_SHA256_BLOCK_BYTES */ -#define PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_INBLOCKS (((PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_N + PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_PK_BYTES + PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_SHA256_BLOCK_BYTES - 1) & \ - -PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_SHA256_BLOCK_BYTES) / PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_SHA256_BLOCK_BYTES) - unsigned char inbuf[PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_INBLOCKS * PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_SHA256_BLOCK_BYTES]; - - unsigned char buf[PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_DGST_BYTES]; - unsigned char *bufp = buf; - sha256ctx state; - - sha256_inc_init(&state); - - memcpy(inbuf, R, PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_N); - memcpy(inbuf + PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_N, pk, PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_PK_BYTES); - - /* If R + pk + message cannot fill up an entire block */ - if (PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_N + PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_PK_BYTES + mlen < PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_INBLOCKS * PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_SHA256_BLOCK_BYTES) { - memcpy(inbuf + PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_N + PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_PK_BYTES, m, mlen); - sha256_inc_finalize(seed, &state, inbuf, PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_N + PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_PK_BYTES + mlen); - } - /* Otherwise first fill a block, so that finalize only uses the message */ - else { - memcpy(inbuf + PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_N + PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_PK_BYTES, m, - PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_INBLOCKS * PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_N - PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_PK_BYTES); - sha256_inc_blocks(&state, inbuf, PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_INBLOCKS); - - m += PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_INBLOCKS * PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_N - PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_PK_BYTES; - mlen -= PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_INBLOCKS * PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_N - PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_PK_BYTES; - sha256_inc_finalize(seed, &state, m, mlen); - } - - /* By doing this in two steps, we prevent hashing the message twice; - otherwise each iteration in MGF1 would hash the message again. */ - PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_mgf1(bufp, PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_DGST_BYTES, seed, PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_SHA256_OUTPUT_BYTES); - - memcpy(digest, bufp, PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_FORS_MSG_BYTES); - bufp += PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_FORS_MSG_BYTES; - - *tree = PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_bytes_to_ull(bufp, PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_TREE_BYTES); - *tree &= (~(uint64_t)0) >> (64 - PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_TREE_BITS); - bufp += PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_TREE_BYTES; - - *leaf_idx = (uint32_t)PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_bytes_to_ull( - bufp, PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_LEAF_BYTES); - *leaf_idx &= (~(uint32_t)0) >> (32 - PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_LEAF_BITS); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_clean/hash_state.h b/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_clean/hash_state.h deleted file mode 100644 index 19fc335e27..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_clean/hash_state.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef SPX_HASH_STATE_H -#define SPX_HASH_STATE_H - -/** - * Defines the type of the hash function state. - * - * Don't be fooled into thinking this instance of SPHINCS+ isn't stateless! - * - * From Section 7.2.2 from the SPHINCS+ round-2 specification: - * - * Each of the instances of the tweakable hash function take PK.seed as its - * first input, which is constant for a given key pair – and, thus, across - * a single signature. This leads to a lot of redundant computation. To remedy - * this, we pad PK.seed to the length of a full 64-byte SHA-256 input block. - * Because of the Merkle-Damgård construction that underlies SHA-256, this - * allows for reuse of the intermediate SHA-256 state after the initial call to - * the compression function which improves performance. - * - * We pass this hash state around in functions, because otherwise we need to - * have a global variable. - */ - -#include "sha2.h" -#define hash_state sha256ctx - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_clean/params.h b/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_clean/params.h deleted file mode 100644 index 2f6355fc35..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_clean/params.h +++ /dev/null @@ -1,53 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_PARAMS_H -#define PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_PARAMS_H - -/* Hash output length in bytes. */ -#define PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_N 32 -/* Height of the hypertree. */ -#define PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_FULL_HEIGHT 64 -/* Number of subtree layer. */ -#define PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_D 8 -/* FORS tree dimensions. */ -#define PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_FORS_HEIGHT 14 -#define PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_FORS_TREES 22 -/* Winternitz parameter, */ -#define PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_WOTS_W 16 - -/* The hash function is defined by linking a different hash.c file, as opposed - to setting a #define constant. */ - -/* For clarity */ -#define PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_ADDR_BYTES 32 - -/* WOTS parameters. */ -#define PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_WOTS_LOGW 4 - -#define PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_WOTS_LEN1 (8 * PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_N / PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_WOTS_LOGW) - -/* PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#define PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_WOTS_LEN2 3 - -#define PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_WOTS_LEN (PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_WOTS_LEN1 + PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_WOTS_LEN2) -#define PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_WOTS_BYTES (PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_WOTS_LEN * PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_N) -#define PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_WOTS_PK_BYTES PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_WOTS_BYTES - -/* Subtree size. */ -#define PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_TREE_HEIGHT (PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_FULL_HEIGHT / PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_D) - -/* FORS parameters. */ -#define PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_FORS_MSG_BYTES ((PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_FORS_TREES + 7) / 8) -#define PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_FORS_BYTES ((PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_FORS_HEIGHT + 1) * PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_FORS_TREES * PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_N) -#define PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_FORS_PK_BYTES PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_N - -/* Resulting SPX sizes. */ -#define PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_BYTES (PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_N + PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_FORS_BYTES + PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_D * PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_WOTS_BYTES +\ - PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_FULL_HEIGHT * PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_N) -#define PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_PK_BYTES (2 * PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_N) -#define PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_SK_BYTES (2 * PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_N + PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_PK_BYTES) - -/* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ -#define PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_OPTRAND_BYTES 32 - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_clean/sha256.c b/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_clean/sha256.c deleted file mode 100644 index df421b00b1..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_clean/sha256.c +++ /dev/null @@ -1,71 +0,0 @@ -/* Based on the public domain implementation in - * crypto_hash/sha512/ref/ from http://bench.cr.yp.to/supercop.html - * by D. J. Bernstein */ - -#include -#include -#include - -#include "sha2.h" -#include "sha256.h" -#include "utils.h" - -/* - * Compresses an address to a 22-byte sequence. - * This reduces the number of required SHA256 compression calls, as the last - * block of input is padded with at least 65 bits. - */ -void PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_compress_address(unsigned char *out, const uint32_t addr[8]) { - PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_ull_to_bytes(out, 1, addr[0]); /* drop 3 bytes of the layer field */ - PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_ull_to_bytes(out + 1, 4, addr[2]); /* drop the highest tree address word */ - PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_ull_to_bytes(out + 5, 4, addr[3]); - PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_ull_to_bytes(out + 9, 1, addr[4]); /* drop 3 bytes of the type field */ - PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_ull_to_bytes(out + 10, 4, addr[5]); - PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_ull_to_bytes(out + 14, 4, addr[6]); - PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_ull_to_bytes(out + 18, 4, addr[7]); -} - -/** - * Requires 'input_plus_four_bytes' to have 'inlen' + 4 bytes, so that the last - * four bytes can be used for the counter. Typically 'input' is merely a seed. - * Outputs outlen number of bytes - */ -void PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_mgf1( - unsigned char *out, unsigned long outlen, - unsigned char *input_plus_four_bytes, unsigned long inlen) { - unsigned char outbuf[PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_SHA256_OUTPUT_BYTES]; - unsigned long i; - - /* While we can fit in at least another full block of SHA256 output.. */ - for (i = 0; (i + 1)*PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_SHA256_OUTPUT_BYTES <= outlen; i++) { - PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_ull_to_bytes(input_plus_four_bytes + inlen, 4, i); - sha256(out, input_plus_four_bytes, inlen + 4); - out += PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_SHA256_OUTPUT_BYTES; - } - /* Until we cannot anymore, and we fill the remainder. */ - if (outlen > i * PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_SHA256_OUTPUT_BYTES) { - PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_ull_to_bytes(input_plus_four_bytes + inlen, 4, i); - sha256(outbuf, input_plus_four_bytes, inlen + 4); - memcpy(out, outbuf, outlen - i * PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_SHA256_OUTPUT_BYTES); - } -} - - -/** - * Absorb the constant pub_seed using one round of the compression function - * This initializes hash_state_seeded, which can then be reused in thash - **/ -void PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_seed_state(sha256ctx *hash_state_seeded, const unsigned char *pub_seed) { - uint8_t block[PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_SHA256_BLOCK_BYTES]; - size_t i; - - for (i = 0; i < PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_N; ++i) { - block[i] = pub_seed[i]; - } - for (i = PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_N; i < PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_SHA256_BLOCK_BYTES; ++i) { - block[i] = 0; - } - - sha256_inc_init(hash_state_seeded); - sha256_inc_blocks(hash_state_seeded, block, 1); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_clean/sha256.h b/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_clean/sha256.h deleted file mode 100644 index 4af5b6b831..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_clean/sha256.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_SHA256_H -#define PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_SHA256_H - -#define PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_SHA256_BLOCK_BYTES 64 -#define PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_SHA256_OUTPUT_BYTES 32 /* This does not necessarily equal PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_N */ -#define PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_SHA256_ADDR_BYTES 22 - -#include -#include - -#include "sha2.h" - -void PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_compress_address(unsigned char *out, const uint32_t addr[8]); - -void PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_mgf1( - unsigned char *out, unsigned long outlen, - unsigned char *input_plus_four_bytes, unsigned long inlen); - -void PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_seed_state(sha256ctx *hash_state_seeded, const unsigned char *pub_seed); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_clean/sign.c b/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_clean/sign.c deleted file mode 100644 index 3585144f4d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_clean/sign.c +++ /dev/null @@ -1,356 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "api.h" -#include "fors.h" -#include "hash.h" -#include "hash_state.h" -#include "params.h" -#include "randombytes.h" -#include "thash.h" -#include "utils.h" -#include "wots.h" - -/** - * Computes the leaf at a given address. First generates the WOTS key pair, - * then computes leaf by hashing horizontally. - */ -static void wots_gen_leaf(unsigned char *leaf, const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx, const uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - unsigned char pk[PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_WOTS_BYTES]; - uint32_t wots_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_set_type( - wots_addr, PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_set_type( - wots_pk_addr, PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_ADDR_TYPE_WOTSPK); - - PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_set_keypair_addr( - wots_addr, addr_idx); - PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_wots_gen_pk( - pk, sk_seed, pub_seed, wots_addr, hash_state_seeded); - - PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_copy_keypair_addr( - wots_pk_addr, wots_addr); - PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_thash_WOTS_LEN( - leaf, pk, pub_seed, wots_pk_addr, hash_state_seeded); -} - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_crypto_sign_secretkeybytes(void) { - return PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_CRYPTO_SECRETKEYBYTES; -} - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_crypto_sign_publickeybytes(void) { - return PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_CRYPTO_PUBLICKEYBYTES; -} - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_crypto_sign_bytes(void) { - return PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_CRYPTO_BYTES; -} - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_crypto_sign_seedbytes(void) { - return PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_CRYPTO_SEEDBYTES; -} - -/* - * Generates an SPX key pair given a seed of length - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed) { - /* We do not need the auth path in key generation, but it simplifies the - code to have just one treehash routine that computes both root and path - in one function. */ - unsigned char auth_path[PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_TREE_HEIGHT * PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_N]; - uint32_t top_tree_addr[8] = {0}; - hash_state hash_state_seeded; - - PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_set_layer_addr( - top_tree_addr, PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_D - 1); - PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_set_type( - top_tree_addr, PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_ADDR_TYPE_HASHTREE); - - /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ - memcpy(sk, seed, PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_CRYPTO_SEEDBYTES); - - memcpy(pk, sk + 2 * PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_N, PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_initialize_hash_function(&hash_state_seeded, pk, sk); - - /* Compute root node of the top-most subtree. */ - PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_treehash_TREE_HEIGHT( - sk + 3 * PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_N, auth_path, sk, sk + 2 * PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_N, 0, 0, - wots_gen_leaf, top_tree_addr, &hash_state_seeded); - - memcpy(pk + PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_N, sk + 3 * PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_N, PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_N); - - PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_destroy_hash_function(&hash_state_seeded); - return 0; -} - -/* - * Generates an SPX key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk) { - unsigned char seed[PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_CRYPTO_SEEDBYTES]; - randombytes(seed, PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_CRYPTO_SEEDBYTES); - PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_crypto_sign_seed_keypair( - pk, sk, seed); - - return 0; -} - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - const unsigned char *sk_seed = sk; - const unsigned char *sk_prf = sk + PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_N; - const unsigned char *pk = sk + 2 * PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_N; - const unsigned char *pub_seed = pk; - - unsigned char optrand[PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_N]; - unsigned char mhash[PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_FORS_MSG_BYTES]; - unsigned char root[PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_N]; - uint32_t i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - - hash_state hash_state_seeded; - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_initialize_hash_function( - &hash_state_seeded, - pub_seed, sk_seed); - - PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_set_type( - wots_addr, PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_set_type( - tree_addr, PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_ADDR_TYPE_HASHTREE); - - /* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ - randombytes(optrand, PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_N); - /* Compute the digest randomization value. */ - PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_gen_message_random( - sig, sk_prf, optrand, m, mlen, &hash_state_seeded); - - /* Derive the message digest and leaf index from R, PK and M. */ - PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_N; - - PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); - - /* Sign the message hash using FORS. */ - PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_fors_sign( - sig, root, mhash, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_FORS_BYTES; - - for (i = 0; i < PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_D; i++) { - PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_set_tree_addr(tree_addr, tree); - - PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); - - /* Compute a WOTS signature. */ - PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_wots_sign( - sig, root, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_WOTS_BYTES; - - /* Compute the authentication path for the used WOTS leaf. */ - PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_treehash_TREE_HEIGHT( - root, sig, sk_seed, pub_seed, idx_leaf, 0, - wots_gen_leaf, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_TREE_HEIGHT * PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_TREE_HEIGHT; - } - - *siglen = PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_BYTES; - - PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_destroy_hash_function(&hash_state_seeded); - return 0; -} - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk) { - const unsigned char *pub_seed = pk; - const unsigned char *pub_root = pk + PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_N; - unsigned char mhash[PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_FORS_MSG_BYTES]; - unsigned char wots_pk[PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_WOTS_BYTES]; - unsigned char root[PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_N]; - unsigned char leaf[PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_N]; - unsigned int i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - hash_state hash_state_seeded; - - if (siglen != PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_BYTES) { - return -1; - } - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_initialize_hash_function( - &hash_state_seeded, - pub_seed, NULL); - - PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_set_type( - wots_addr, PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_set_type( - tree_addr, PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_ADDR_TYPE_HASHTREE); - PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_set_type( - wots_pk_addr, PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_ADDR_TYPE_WOTSPK); - - /* Derive the message digest and leaf index from R || PK || M. */ - /* The additional PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_N is a result of the hash domain separator. */ - PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_N; - - /* Layer correctly defaults to 0, so no need to set_layer_addr */ - PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); - - PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_fors_pk_from_sig( - root, sig, mhash, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_FORS_BYTES; - - /* For each subtree.. */ - for (i = 0; i < PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_D; i++) { - PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_set_tree_addr(tree_addr, tree); - - PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); - - PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_copy_keypair_addr( - wots_pk_addr, wots_addr); - - /* The WOTS public key is only correct if the signature was correct. */ - /* Initially, root is the FORS pk, but on subsequent iterations it is - the root of the subtree below the currently processed subtree. */ - PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_wots_pk_from_sig( - wots_pk, sig, root, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_WOTS_BYTES; - - /* Compute the leaf node using the WOTS public key. */ - PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_thash_WOTS_LEN( - leaf, wots_pk, pub_seed, wots_pk_addr, &hash_state_seeded); - - /* Compute the root node of this subtree. */ - PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_compute_root( - root, leaf, idx_leaf, 0, sig, PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_TREE_HEIGHT, - pub_seed, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_TREE_HEIGHT * PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_TREE_HEIGHT; - } - - PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_destroy_hash_function(&hash_state_seeded); - /* Check if the root node equals the root node in the public key. */ - if (memcmp(root, pub_root, PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_N) != 0) { - return -1; - } - - return 0; -} - - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - size_t siglen; - - PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_crypto_sign_signature( - sm, &siglen, m, mlen, sk); - - memmove(sm + PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_BYTES, m, mlen); - *smlen = siglen + mlen; - - return 0; -} - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk) { - /* The API caller does not necessarily know what size a signature should be - but SPHINCS+ signatures are always exactly PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_BYTES. */ - if (smlen < PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_BYTES) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - *mlen = smlen - PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_BYTES; - - if (PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_crypto_sign_verify( - sm, PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_BYTES, sm + PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_BYTES, *mlen, pk)) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - /* If verification was successful, move the message to the right place. */ - memmove(m, sm + PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_BYTES, *mlen); - - return 0; -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_clean/thash.h b/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_clean/thash.h deleted file mode 100644 index 60ea0ded9c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_clean/thash.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_THASH_H -#define PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_THASH_H - -#include "hash_state.h" - -#include - -void PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_clean/thash_sha256_robust.c b/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_clean/thash_sha256_robust.c deleted file mode 100644 index 88c9e08847..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_clean/thash_sha256_robust.c +++ /dev/null @@ -1,82 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "thash.h" - -#include "sha2.h" -#include "sha256.h" - -/** - * Takes an array of inblocks concatenated arrays of PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_N bytes. - */ -static void PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_thash( - unsigned char *out, unsigned char *buf, - const unsigned char *in, unsigned int inblocks, - const unsigned char *pub_seed, uint32_t addr[8], - const sha256ctx *hash_state_seeded) { - - unsigned char outbuf[PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_SHA256_OUTPUT_BYTES]; - unsigned char *bitmask = buf + PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_N + PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_SHA256_ADDR_BYTES + 4; - sha256ctx sha2_state; - unsigned int i; - - memcpy(buf, pub_seed, PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_N); - PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_compress_address(buf + PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_N, addr); - /* MGF1 requires us to have 4 extra bytes in 'buf' */ - PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_mgf1(bitmask, inblocks * PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_N, buf, PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_N + PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_SHA256_ADDR_BYTES); - - /* Retrieve precomputed state containing pub_seed */ - sha256_inc_ctx_clone(&sha2_state, hash_state_seeded); - - for (i = 0; i < inblocks * PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_N; i++) { - buf[PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_N + PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_SHA256_ADDR_BYTES + i] = in[i] ^ bitmask[i]; - } - - sha256_inc_finalize(outbuf, &sha2_state, buf + PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_N, - PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_N); - memcpy(out, outbuf, PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_N); -} - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const sha256ctx *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_N + PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_SHA256_ADDR_BYTES + 4 + 1 * PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_N]; - PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_thash( - out, buf, in, 1, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const sha256ctx *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_N + PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_SHA256_ADDR_BYTES + 4 + 2 * PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_N]; - PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_thash( - out, buf, in, 2, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const sha256ctx *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_N + PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_SHA256_ADDR_BYTES + 4 + PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_WOTS_LEN * PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_N]; - PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_thash( - out, buf, in, PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_WOTS_LEN, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const sha256ctx *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_N + PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_SHA256_ADDR_BYTES + 4 + PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_FORS_TREES * PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_N]; - PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_thash( - out, buf, in, PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_FORS_TREES, pub_seed, addr, hash_state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_clean/utils.c b/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_clean/utils.c deleted file mode 100644 index 95aeaa6091..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_clean/utils.c +++ /dev/null @@ -1,199 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "hash_state.h" -#include "params.h" -#include "thash.h" -#include "utils.h" - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in) { - - /* Iterate over out in decreasing order, for big-endianness. */ - for (size_t i = outlen; i > 0; i--) { - out[i - 1] = in & 0xff; - in = in >> 8; - } -} - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_bytes_to_ull( - const unsigned char *in, size_t inlen) { - unsigned long long retval = 0; - - for (size_t i = 0; i < inlen; i++) { - retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); - } - return retval; -} - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - uint32_t i; - unsigned char buffer[2 * PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_N]; - - /* If leaf_idx is odd (last bit = 1), current path element is a right child - and auth_path has to go left. Otherwise it is the other way around. */ - if (leaf_idx & 1) { - memcpy(buffer + PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_N, leaf, PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_N); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_N); - } else { - memcpy(buffer, leaf, PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_N); - memcpy(buffer + PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_N, auth_path, PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_N); - } - auth_path += PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_N; - - for (i = 0; i < tree_height - 1; i++) { - leaf_idx >>= 1; - idx_offset >>= 1; - /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_set_tree_height(addr, i + 1); - PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_set_tree_index( - addr, leaf_idx + idx_offset); - - /* Pick the right or left neighbor, depending on parity of the node. */ - if (leaf_idx & 1) { - PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_thash_2( - buffer + PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_N, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_N); - } else { - PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_thash_2( - buffer, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer + PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_N, auth_path, PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_N); - } - auth_path += PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_N; - } - - /* The last iteration is exceptional; we do not copy an auth_path node. */ - leaf_idx >>= 1; - idx_offset >>= 1; - PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_set_tree_height(addr, tree_height); - PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_set_tree_index( - addr, leaf_idx + idx_offset); - PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_thash_2( - root, buffer, pub_seed, addr, hash_state_seeded); -} - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -static void PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_treehash( - unsigned char *root, unsigned char *auth_path, - unsigned char *stack, unsigned int *heights, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - - unsigned int offset = 0; - uint32_t idx; - uint32_t tree_idx; - - for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { - /* Add the next leaf node to the stack. */ - gen_leaf(stack + offset * PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_N, - sk_seed, pub_seed, idx + idx_offset, tree_addr, - hash_state_seeded); - offset++; - heights[offset - 1] = 0; - - /* If this is a node we need for the auth path.. */ - if ((leaf_idx ^ 0x1) == idx) { - memcpy(auth_path, stack + (offset - 1)*PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_N, PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_N); - } - - /* While the top-most nodes are of equal height.. */ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { - /* Compute index of the new node, in the next layer. */ - tree_idx = (idx >> (heights[offset - 1] + 1)); - - /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_set_tree_height( - tree_addr, heights[offset - 1] + 1); - PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_set_tree_index( - tree_addr, tree_idx + (idx_offset >> (heights[offset - 1] + 1))); - /* Hash the top-most nodes from the stack together. */ - PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_thash_2( - stack + (offset - 2)*PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_N, stack + (offset - 2)*PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_N, - pub_seed, tree_addr, hash_state_seeded); - offset--; - /* Note that the top-most node is now one layer higher. */ - heights[offset - 1]++; - - /* If this is a node we need for the auth path.. */ - if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_path + heights[offset - 1]*PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_N, - stack + (offset - 1)*PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_N, PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_N); - } - } - } - memcpy(root, stack, PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_N); -} - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_FORS_HEIGHT + 1)*PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_N]; - unsigned int heights[PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_FORS_HEIGHT + 1]; - - PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_FORS_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_TREE_HEIGHT + 1)*PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_N]; - unsigned int heights[PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_TREE_HEIGHT + 1]; - - PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_TREE_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_clean/utils.h b/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_clean/utils.h deleted file mode 100644 index 6ef41bd06b..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_clean/utils.h +++ /dev/null @@ -1,64 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_UTILS_H -#define PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_UTILS_H - -#include "hash_state.h" -#include "params.h" -#include -#include - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in); - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_bytes_to_ull( - const unsigned char *in, size_t inlen); - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -void PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_clean/wots.c b/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_clean/wots.c deleted file mode 100644 index 95ac00498d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_clean/wots.c +++ /dev/null @@ -1,167 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "hash_state.h" -#include "params.h" -#include "thash.h" -#include "utils.h" -#include "wots.h" - -// TODO clarify address expectations, and make them more uniform. -// TODO i.e. do we expect types to be set already? -// TODO and do we expect modifications or copies? - -/** - * Computes the starting value for a chain, i.e. the secret key. - * Expects the address to be complete up to the chain address. - */ -static void wots_gen_sk(unsigned char *sk, const unsigned char *sk_seed, - uint32_t wots_addr[8], - const hash_state *hash_state_seeded) { - /* Make sure that the hash address is actually zeroed. */ - PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_set_hash_addr(wots_addr, 0); - - /* Generate sk element. */ - PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_prf_addr(sk, sk_seed, wots_addr, hash_state_seeded); -} - -/** - * Computes the chaining function. - * out and in have to be n-byte arrays. - * - * Interprets in as start-th value of the chain. - * addr has to contain the address of the chain. - */ -static void gen_chain(unsigned char *out, const unsigned char *in, - unsigned int start, unsigned int steps, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - uint32_t i; - - /* Initialize out with the value at position 'start'. */ - memcpy(out, in, PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_N); - - /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_WOTS_W; i++) { - PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_set_hash_addr(addr, i); - PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_thash_1( - out, out, pub_seed, addr, hash_state_seeded); - } -} - -/** - * base_w algorithm as described in draft. - * Interprets an array of bytes as integers in base w. - * This only works when log_w is a divisor of 8. - */ -static void base_w(unsigned int *output, const size_t out_len, - const unsigned char *input) { - size_t in = 0; - size_t out = 0; - unsigned char total = 0; - unsigned int bits = 0; - size_t consumed; - - for (consumed = 0; consumed < out_len; consumed++) { - if (bits == 0) { - total = input[in]; - in++; - bits += 8; - } - bits -= PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_WOTS_LOGW; - output[out] = (unsigned int)((total >> bits) & (PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_WOTS_W - 1)); - out++; - } -} - -/* Computes the WOTS+ checksum over a message (in base_w). */ -static void wots_checksum(unsigned int *csum_base_w, - const unsigned int *msg_base_w) { - unsigned int csum = 0; - unsigned char csum_bytes[(PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_WOTS_LEN2 * PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_WOTS_LOGW + 7) / 8]; - unsigned int i; - - /* Compute checksum. */ - for (i = 0; i < PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_WOTS_LEN1; i++) { - csum += PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_WOTS_W - 1 - msg_base_w[i]; - } - - /* Convert checksum to base_w. */ - /* Make sure expected empty zero bits are the least significant bits. */ - csum = csum << (8 - ((PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_WOTS_LEN2 * PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_WOTS_LOGW) % 8)); - PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_ull_to_bytes( - csum_bytes, sizeof(csum_bytes), csum); - base_w(csum_base_w, PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_WOTS_LEN2, csum_bytes); -} - -/* Takes a message and derives the matching chain lengths. */ -static void chain_lengths(unsigned int *lengths, const unsigned char *msg) { - base_w(lengths, PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_WOTS_LEN1, msg); - wots_checksum(lengths + PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_WOTS_LEN1, lengths); -} - -/** - * WOTS key generation. Takes a 32 byte sk_seed, expands it to WOTS private key - * elements and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_wots_gen_pk( - unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - uint32_t i; - - for (i = 0; i < PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_WOTS_LEN; i++) { - PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_set_chain_addr(addr, i); - wots_gen_sk(pk + i * PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_N, sk_seed, addr, hash_state_seeded); - gen_chain(pk + i * PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_N, pk + i * PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_N, - 0, PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_WOTS_W - 1, pub_seed, addr, hash_state_seeded); - } -} - -/** - * Takes a n-byte message and the 32-byte sk_see to compute a signature 'sig'. - */ -void PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_wots_sign( - unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *hash_state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_WOTS_LEN; i++) { - PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_set_chain_addr(addr, i); - wots_gen_sk(sig + i * PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_N, sk_seed, addr, hash_state_seeded); - gen_chain(sig + i * PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_N, sig + i * PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_N, 0, lengths[i], pub_seed, addr, hash_state_seeded); - } -} - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_wots_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_WOTS_LEN; i++) { - PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_set_chain_addr(addr, i); - gen_chain(pk + i * PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_N, sig + i * PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_N, - lengths[i], PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_WOTS_W - 1 - lengths[i], pub_seed, addr, - hash_state_seeded); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_clean/wots.h b/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_clean/wots.h deleted file mode 100644 index 36adc075f3..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256s-robust_clean/wots.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_WOTS_H -#define PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_WOTS_H - -#include "hash_state.h" -#include "params.h" -#include - -/** - * WOTS key generation. Takes a 32 byte seed for the private key, expands it to - * a full WOTS private key and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_wots_gen_pk( - unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -/** - * Takes a n-byte message and the 32-byte seed for the private key to compute a - * signature that is placed at 'sig'. - */ -void PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_wots_sign( - unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *hash_state_seeded); - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_wots_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_avx2/LICENSE b/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_avx2/LICENSE deleted file mode 100644 index 670154e353..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_avx2/LICENSE +++ /dev/null @@ -1,116 +0,0 @@ -CC0 1.0 Universal - -Statement of Purpose - -The laws of most jurisdictions throughout the world automatically confer -exclusive Copyright and Related Rights (defined below) upon the creator and -subsequent owner(s) (each and all, an "owner") of an original work of -authorship and/or a database (each, a "Work"). - -Certain owners wish to permanently relinquish those rights to a Work for the -purpose of contributing to a commons of creative, cultural and scientific -works ("Commons") that the public can reliably and without fear of later -claims of infringement build upon, modify, incorporate in other works, reuse -and redistribute as freely as possible in any form whatsoever and for any -purposes, including without limitation commercial purposes. These owners may -contribute to the Commons to promote the ideal of a free culture and the -further production of creative, cultural and scientific works, or to gain -reputation or greater distribution for their Work in part through the use and -efforts of others. - -For these and/or other purposes and motivations, and without any expectation -of additional consideration or compensation, the person associating CC0 with a -Work (the "Affirmer"), to the extent that he or she is an owner of Copyright -and Related Rights in the Work, voluntarily elects to apply CC0 to the Work -and publicly distribute the Work under its terms, with knowledge of his or her -Copyright and Related Rights in the Work and the meaning and intended legal -effect of CC0 on those rights. - -1. Copyright and Related Rights. A Work made available under CC0 may be -protected by copyright and related or neighboring rights ("Copyright and -Related Rights"). Copyright and Related Rights include, but are not limited -to, the following: - - i. the right to reproduce, adapt, distribute, perform, display, communicate, - and translate a Work; - - ii. moral rights retained by the original author(s) and/or performer(s); - - iii. publicity and privacy rights pertaining to a person's image or likeness - depicted in a Work; - - iv. rights protecting against unfair competition in regards to a Work, - subject to the limitations in paragraph 4(a), below; - - v. rights protecting the extraction, dissemination, use and reuse of data in - a Work; - - vi. database rights (such as those arising under Directive 96/9/EC of the - European Parliament and of the Council of 11 March 1996 on the legal - protection of databases, and under any national implementation thereof, - including any amended or successor version of such directive); and - - vii. other similar, equivalent or corresponding rights throughout the world - based on applicable law or treaty, and any national implementations thereof. - -2. Waiver. To the greatest extent permitted by, but not in contravention of, -applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and -unconditionally waives, abandons, and surrenders all of Affirmer's Copyright -and Related Rights and associated claims and causes of action, whether now -known or unknown (including existing as well as future claims and causes of -action), in the Work (i) in all territories worldwide, (ii) for the maximum -duration provided by applicable law or treaty (including future time -extensions), (iii) in any current or future medium and for any number of -copies, and (iv) for any purpose whatsoever, including without limitation -commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes -the Waiver for the benefit of each member of the public at large and to the -detriment of Affirmer's heirs and successors, fully intending that such Waiver -shall not be subject to revocation, rescission, cancellation, termination, or -any other legal or equitable action to disrupt the quiet enjoyment of the Work -by the public as contemplated by Affirmer's express Statement of Purpose. - -3. Public License Fallback. Should any part of the Waiver for any reason be -judged legally invalid or ineffective under applicable law, then the Waiver -shall be preserved to the maximum extent permitted taking into account -Affirmer's express Statement of Purpose. In addition, to the extent the Waiver -is so judged Affirmer hereby grants to each affected person a royalty-free, -non transferable, non sublicensable, non exclusive, irrevocable and -unconditional license to exercise Affirmer's Copyright and Related Rights in -the Work (i) in all territories worldwide, (ii) for the maximum duration -provided by applicable law or treaty (including future time extensions), (iii) -in any current or future medium and for any number of copies, and (iv) for any -purpose whatsoever, including without limitation commercial, advertising or -promotional purposes (the "License"). The License shall be deemed effective as -of the date CC0 was applied by Affirmer to the Work. Should any part of the -License for any reason be judged legally invalid or ineffective under -applicable law, such partial invalidity or ineffectiveness shall not -invalidate the remainder of the License, and in such case Affirmer hereby -affirms that he or she will not (i) exercise any of his or her remaining -Copyright and Related Rights in the Work or (ii) assert any associated claims -and causes of action with respect to the Work, in either case contrary to -Affirmer's express Statement of Purpose. - -4. Limitations and Disclaimers. - - a. No trademark or patent rights held by Affirmer are waived, abandoned, - surrendered, licensed or otherwise affected by this document. - - b. Affirmer offers the Work as-is and makes no representations or warranties - of any kind concerning the Work, express, implied, statutory or otherwise, - including without limitation warranties of title, merchantability, fitness - for a particular purpose, non infringement, or the absence of latent or - other defects, accuracy, or the present or absence of errors, whether or not - discoverable, all to the greatest extent permissible under applicable law. - - c. Affirmer disclaims responsibility for clearing rights of other persons - that may apply to the Work or any use thereof, including without limitation - any person's Copyright and Related Rights in the Work. Further, Affirmer - disclaims responsibility for obtaining any necessary consents, permissions - or other rights required for any use of the Work. - - d. Affirmer understands and acknowledges that Creative Commons is not a - party to this document and has no duty or obligation with respect to this - CC0 or use of the Work. - -For more information, please see - diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_avx2/address.c b/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_avx2/address.c deleted file mode 100644 index 76b83ad3d0..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_avx2/address.c +++ /dev/null @@ -1,78 +0,0 @@ -#include - -#include "address.h" -#include "params.h" -#include "utils.h" - -void PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]) { - int i; - - for (i = 0; i < 8; i++) { - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_ull_to_bytes( - bytes + i * 4, 4, addr[i]); - } -} - -void PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_set_layer_addr( - uint32_t addr[8], uint32_t layer) { - addr[0] = layer; -} - -void PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_set_tree_addr( - uint32_t addr[8], uint64_t tree) { - addr[1] = 0; - addr[2] = (uint32_t) (tree >> 32); - addr[3] = (uint32_t) tree; -} - -void PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_set_type( - uint32_t addr[8], uint32_t type) { - addr[4] = type; -} - -void PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; -} - -/* These functions are used for OTS addresses. */ - -void PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_set_keypair_addr( - uint32_t addr[8], uint32_t keypair) { - addr[5] = keypair; -} - -void PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; - out[5] = in[5]; -} - -void PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_set_chain_addr( - uint32_t addr[8], uint32_t chain) { - addr[6] = chain; -} - -void PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_set_hash_addr( - uint32_t addr[8], uint32_t hash) { - addr[7] = hash; -} - -/* These functions are used for all hash tree addresses (including FORS). */ - -void PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_set_tree_height( - uint32_t addr[8], uint32_t tree_height) { - addr[6] = tree_height; -} - -void PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_set_tree_index( - uint32_t addr[8], uint32_t tree_index) { - addr[7] = tree_index; -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_avx2/address.h b/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_avx2/address.h deleted file mode 100644 index 7de40b64d4..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_avx2/address.h +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_ADDRESS_H -#define PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_ADDRESS_H - -#include - -#define PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_ADDR_TYPE_WOTS 0 -#define PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_ADDR_TYPE_WOTSPK 1 -#define PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_ADDR_TYPE_HASHTREE 2 -#define PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_ADDR_TYPE_FORSTREE 3 -#define PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_ADDR_TYPE_FORSPK 4 - -void PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]); - -void PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_set_layer_addr( - uint32_t addr[8], uint32_t layer); - -void PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_set_tree_addr( - uint32_t addr[8], uint64_t tree); - -void PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_set_type( - uint32_t addr[8], uint32_t type); - -/* Copies the layer and tree part of one address into the other */ -void PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for WOTS and FORS addresses. */ - -void PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_set_keypair_addr( - uint32_t addr[8], uint32_t keypair); - -void PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_set_chain_addr( - uint32_t addr[8], uint32_t chain); - -void PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_set_hash_addr( - uint32_t addr[8], uint32_t hash); - -void PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for all hash tree addresses (including FORS). */ - -void PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_set_tree_height( - uint32_t addr[8], uint32_t tree_height); - -void PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_set_tree_index( - uint32_t addr[8], uint32_t tree_index); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_avx2/api.h b/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_avx2/api.h deleted file mode 100644 index d5b5e56e96..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_avx2/api.h +++ /dev/null @@ -1,81 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_API_H -#define PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_API_H - -#include -#include - - - -#define PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_CRYPTO_ALGNAME "SPHINCS+" - -#define PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_CRYPTO_SECRETKEYBYTES 128 -#define PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_CRYPTO_PUBLICKEYBYTES 64 -#define PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_CRYPTO_BYTES 29792 -#define PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_CRYPTO_SEEDBYTES 96 - - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_avx2/fors.c b/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_avx2/fors.c deleted file mode 100644 index ff492c58ca..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_avx2/fors.c +++ /dev/null @@ -1,240 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "fors.h" -#include "hash.h" -#include "hashx8.h" -#include "thash.h" -#include "thashx8.h" -#include "utils.h" -#include "utilsx8.h" - -static void fors_gen_skx8(unsigned char *sk0, - unsigned char *sk1, - unsigned char *sk2, - unsigned char *sk3, - unsigned char *sk4, - unsigned char *sk5, - unsigned char *sk6, - unsigned char *sk7, const unsigned char *sk_seed, - uint32_t fors_leaf_addrx8[8 * 8]) { - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_prf_addrx8(sk0, sk1, sk2, sk3, sk4, sk5, sk6, sk7, - sk_seed, fors_leaf_addrx8); -} - -static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, - const unsigned char *pub_seed, - uint32_t fors_leaf_addr[8], - const hash_state *state_seeded) { - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_thash_1(leaf, sk, pub_seed, fors_leaf_addr, state_seeded); -} - -static void fors_sk_to_leafx8(unsigned char *leaf0, - unsigned char *leaf1, - unsigned char *leaf2, - unsigned char *leaf3, - unsigned char *leaf4, - unsigned char *leaf5, - unsigned char *leaf6, - unsigned char *leaf7, - const unsigned char *sk0, - const unsigned char *sk1, - const unsigned char *sk2, - const unsigned char *sk3, - const unsigned char *sk4, - const unsigned char *sk5, - const unsigned char *sk6, - const unsigned char *sk7, - const unsigned char *pub_seed, - uint32_t fors_leaf_addrx8[8 * 8], - const hash_state *state_seeded) { - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_thashx8_1(leaf0, leaf1, leaf2, leaf3, leaf4, leaf5, leaf6, leaf7, - sk0, sk1, sk2, sk3, sk4, sk5, sk6, sk7, - pub_seed, fors_leaf_addrx8, state_seeded); -} - -static void fors_gen_leafx8(unsigned char *leaf0, - unsigned char *leaf1, - unsigned char *leaf2, - unsigned char *leaf3, - unsigned char *leaf4, - unsigned char *leaf5, - unsigned char *leaf6, - unsigned char *leaf7, - const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx0, - uint32_t addr_idx1, - uint32_t addr_idx2, - uint32_t addr_idx3, - uint32_t addr_idx4, - uint32_t addr_idx5, - uint32_t addr_idx6, - uint32_t addr_idx7, - const uint32_t fors_tree_addr[8], - const hash_state *state_seeded) { - uint32_t fors_leaf_addrx8[8 * 8] = {0}; - unsigned int j; - - /* Only copy the parts that must be kept in fors_leaf_addrx8. */ - for (j = 0; j < 8; j++) { - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_copy_keypair_addr(fors_leaf_addrx8 + j * 8, fors_tree_addr); - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_set_type(fors_leaf_addrx8 + j * 8, PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_ADDR_TYPE_FORSTREE); - } - - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_set_tree_index(fors_leaf_addrx8 + 0 * 8, addr_idx0); - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_set_tree_index(fors_leaf_addrx8 + 1 * 8, addr_idx1); - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_set_tree_index(fors_leaf_addrx8 + 2 * 8, addr_idx2); - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_set_tree_index(fors_leaf_addrx8 + 3 * 8, addr_idx3); - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_set_tree_index(fors_leaf_addrx8 + 4 * 8, addr_idx4); - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_set_tree_index(fors_leaf_addrx8 + 5 * 8, addr_idx5); - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_set_tree_index(fors_leaf_addrx8 + 6 * 8, addr_idx6); - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_set_tree_index(fors_leaf_addrx8 + 7 * 8, addr_idx7); - - fors_gen_skx8(leaf0, leaf1, leaf2, leaf3, leaf4, leaf5, leaf6, leaf7, - sk_seed, fors_leaf_addrx8); - fors_sk_to_leafx8(leaf0, leaf1, leaf2, leaf3, leaf4, leaf5, leaf6, leaf7, - leaf0, leaf1, leaf2, leaf3, leaf4, leaf5, leaf6, leaf7, - pub_seed, fors_leaf_addrx8, state_seeded); -} - -/** - * Interprets m as PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_FORS_HEIGHT-bit unsigned integers. - * Assumes m contains at least PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_FORS_TREES bits. - * Assumes indices has space for PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_FORS_TREES integers. - */ -static void message_to_indices(uint32_t *indices, const unsigned char *m) { - unsigned int i, j; - unsigned int offset = 0; - - for (i = 0; i < PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_FORS_TREES; i++) { - indices[i] = 0; - for (j = 0; j < PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_FORS_HEIGHT; j++) { - indices[i] ^= (((uint32_t)m[offset >> 3] >> (offset & 0x7)) & 0x1) << j; - offset++; - } - } -} - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_fors_sign( - unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], - const hash_state *state_seeded) { - /* Round up to multiple of 8 to prevent out-of-bounds for x8 parallelism */ - uint32_t indices[(PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_FORS_TREES + 7) & ~7] = {0}; - unsigned char roots[((PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_FORS_TREES + 7) & ~7) * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N]; - /* Sign to a buffer, since we may not have a nice multiple of 8 and would - otherwise overrun the signature. */ - unsigned char sigbufx8[8 * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N * (1 + PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_FORS_HEIGHT)]; - uint32_t fors_tree_addrx8[8 * 8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset[8] = {0}; - unsigned int i, j; - - for (j = 0; j < 8; j++) { - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_copy_keypair_addr(fors_tree_addrx8 + j * 8, fors_addr); - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_set_type(fors_tree_addrx8 + j * 8, PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_ADDR_TYPE_FORSTREE); - } - - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_copy_keypair_addr(fors_pk_addr, fors_addr); - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_set_type(fors_pk_addr, PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < ((PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_FORS_TREES + 7) & ~0x7); i += 8) { - for (j = 0; j < 8; j++) { - if (i + j < PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_FORS_TREES) { - idx_offset[j] = (i + j) * (1 << PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_FORS_HEIGHT); - - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_set_tree_height(fors_tree_addrx8 + j * 8, 0); - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_set_tree_index(fors_tree_addrx8 + j * 8, - indices[i + j] + idx_offset[j]); - } - } - - /* Include the secret key part that produces the selected leaf nodes. */ - fors_gen_skx8(sigbufx8 + 0 * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N, - sigbufx8 + 1 * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N, - sigbufx8 + 2 * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N, - sigbufx8 + 3 * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N, - sigbufx8 + 4 * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N, - sigbufx8 + 5 * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N, - sigbufx8 + 6 * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N, - sigbufx8 + 7 * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N, - sk_seed, fors_tree_addrx8); - - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_treehashx8_FORS_HEIGHT( - roots + i * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N, sigbufx8 + 8 * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N, sk_seed, pub_seed, - &indices[i], idx_offset, fors_gen_leafx8, fors_tree_addrx8, - state_seeded); - - for (j = 0; j < 8; j++) { - if (i + j < PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_FORS_TREES) { - memcpy(sig, sigbufx8 + j * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N, PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N); - memcpy(sig + PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N, - sigbufx8 + 8 * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N + j * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_FORS_HEIGHT, - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_FORS_HEIGHT); - sig += PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N * (1 + PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_FORS_HEIGHT); - } - } - } - - /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_thash_FORS_TREES(pk, roots, pub_seed, fors_pk_addr, state_seeded); -} - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, - const uint32_t fors_addr[8], - const hash_state *state_seeded) { - uint32_t indices[PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_FORS_TREES]; - unsigned char roots[PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_FORS_TREES * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N]; - unsigned char leaf[PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N]; - uint32_t fors_tree_addr[8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_copy_keypair_addr(fors_tree_addr, fors_addr); - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_copy_keypair_addr(fors_pk_addr, fors_addr); - - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_set_type(fors_tree_addr, PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_set_type(fors_pk_addr, PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_FORS_TREES; i++) { - idx_offset = i * (1 << PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_FORS_HEIGHT); - - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_set_tree_height(fors_tree_addr, 0); - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Derive the leaf from the included secret key part. */ - fors_sk_to_leaf(leaf, sig, pub_seed, fors_tree_addr, state_seeded); - sig += PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N; - - /* Derive the corresponding root node of this tree. */ - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_compute_root(roots + i * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N, leaf, indices[i], idx_offset, - sig, PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_FORS_HEIGHT, pub_seed, fors_tree_addr, state_seeded); - sig += PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_thash_FORS_TREES(pk, roots, pub_seed, fors_pk_addr, state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_avx2/fors.h b/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_avx2/fors.h deleted file mode 100644 index 5565fcb11d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_avx2/fors.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_FORS_H -#define PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_FORS_H - -#include - -#include "hash_state.h" -#include "params.h" - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_fors_sign( - unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *hash_state_seeded); - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_fors_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, const uint32_t fors_addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_avx2/hash.h b/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_avx2/hash.h deleted file mode 100644 index a44261f89c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_avx2/hash.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_HASH_H -#define PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_HASH_H - -#include "hash_state.h" - -#include -#include - -void PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_initialize_hash_function( - hash_state *hash_state_seeded, - const unsigned char *pub_seed, const unsigned char *sk_seed); - -void PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_destroy_hash_function(hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_avx2/hash_sha256.c b/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_avx2/hash_sha256.c deleted file mode 100644 index 4a48a99ed6..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_avx2/hash_sha256.c +++ /dev/null @@ -1,166 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "utils.h" - -#include "sha2.h" -#include "sha256.h" -#include "sha256x8.h" - -/** - * Initializes the hash function states - */ -void PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_initialize_hash_function( - hash_state *hash_state_seeded, - const unsigned char *pub_seed, const unsigned char *sk_seed) { - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_seed_state(&hash_state_seeded->x1, pub_seed); - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_seed_statex8(&hash_state_seeded->x8, pub_seed); - (void)sk_seed; /* Suppress an 'unused parameter' warning. */ -} - -/** - * Cleans up the hash function states - */ -void PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_destroy_hash_function(hash_state *hash_state_seeded) { - sha256_inc_ctx_release(&hash_state_seeded->x1); -} - -/* - * Computes PRF(key, addr), given a secret key of PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N bytes and an address - */ -void PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_prf_addr(unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded) { - unsigned char buf[PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_ADDR_BYTES]; - unsigned char outbuf[PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_OUTPUT_BYTES]; - - memcpy(buf, key, PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N); - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_compress_address(buf + PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N, addr); - - sha256(outbuf, buf, PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_ADDR_BYTES); - memcpy(out, outbuf, PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} - -/** - * Computes the message-dependent randomness R, using a secret seed as a key - * for HMAC, and an optional randomization value prefixed to the message. - * This requires m to have at least PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_BLOCK_BYTES + PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N space - * available in front of the pointer, i.e. before the message to use for the - * prefix. This is necessary to prevent having to move the message around (and - * allocate memory for it). - */ -void PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, const hash_state *hash_state_seeded) { - unsigned char buf[PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_BLOCK_BYTES + PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_OUTPUT_BYTES]; - sha256ctx state; - int i; - - /* This implements HMAC-SHA256 */ - for (i = 0; i < PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N; i++) { - buf[i] = 0x36 ^ sk_prf[i]; - } - memset(buf + PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N, 0x36, PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N); - - sha256_inc_init(&state); - sha256_inc_blocks(&state, buf, 1); - - memcpy(buf, optrand, PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N); - - /* If optrand + message cannot fill up an entire block */ - if (PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N + mlen < PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_BLOCK_BYTES) { - memcpy(buf + PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N, m, mlen); - sha256_inc_finalize(buf + PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_BLOCK_BYTES, &state, - buf, mlen + PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N); - } - /* Otherwise first fill a block, so that finalize only uses the message */ - else { - memcpy(buf + PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N, m, PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N); - sha256_inc_blocks(&state, buf, 1); - - m += PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N; - mlen -= PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N; - sha256_inc_finalize(buf + PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_BLOCK_BYTES, &state, m, mlen); - } - - for (i = 0; i < PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N; i++) { - buf[i] = 0x5c ^ sk_prf[i]; - } - memset(buf + PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N, 0x5c, PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N); - - sha256(buf, buf, PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_BLOCK_BYTES + PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_OUTPUT_BYTES); - memcpy(R, buf, PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} - -/** - * Computes the message hash using R, the public key, and the message. - * Outputs the message digest and the index of the leaf. The index is split in - * the tree index and the leaf index, for convenient copying to an address. - */ -void PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded) { -#define PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_TREE_BITS (PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_TREE_HEIGHT * (PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_D - 1)) -#define PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_TREE_BYTES ((PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_TREE_BITS + 7) / 8) -#define PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_LEAF_BITS PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_TREE_HEIGHT -#define PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_LEAF_BYTES ((PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_LEAF_BITS + 7) / 8) -#define PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_DGST_BYTES (PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_FORS_MSG_BYTES + PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_TREE_BYTES + PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_LEAF_BYTES) - - unsigned char seed[PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_OUTPUT_BYTES + 4]; - - /* Round to nearest multiple of PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_BLOCK_BYTES */ -#define PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_INBLOCKS (((PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_PK_BYTES + PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_BLOCK_BYTES - 1) & \ - -PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_BLOCK_BYTES) / PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_BLOCK_BYTES) - unsigned char inbuf[PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_INBLOCKS * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_BLOCK_BYTES]; - - unsigned char buf[PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_DGST_BYTES]; - unsigned char *bufp = buf; - sha256ctx state; - - sha256_inc_init(&state); - - memcpy(inbuf, R, PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N); - memcpy(inbuf + PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N, pk, PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_PK_BYTES); - - /* If R + pk + message cannot fill up an entire block */ - if (PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_PK_BYTES + mlen < PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_INBLOCKS * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_BLOCK_BYTES) { - memcpy(inbuf + PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_PK_BYTES, m, mlen); - sha256_inc_finalize(seed, &state, inbuf, PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_PK_BYTES + mlen); - } - /* Otherwise first fill a block, so that finalize only uses the message */ - else { - memcpy(inbuf + PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_PK_BYTES, m, - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_INBLOCKS * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_PK_BYTES); - sha256_inc_blocks(&state, inbuf, PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_INBLOCKS); - - m += PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_INBLOCKS * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_PK_BYTES; - mlen -= PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_INBLOCKS * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_PK_BYTES; - sha256_inc_finalize(seed, &state, m, mlen); - } - - /* By doing this in two steps, we prevent hashing the message twice; - otherwise each iteration in MGF1 would hash the message again. */ - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_mgf1(bufp, PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_DGST_BYTES, seed, PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_OUTPUT_BYTES); - - memcpy(digest, bufp, PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_FORS_MSG_BYTES); - bufp += PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_FORS_MSG_BYTES; - - *tree = PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_bytes_to_ull(bufp, PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_TREE_BYTES); - *tree &= (~(uint64_t)0) >> (64 - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_TREE_BITS); - bufp += PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_TREE_BYTES; - - *leaf_idx = (uint32_t)PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_bytes_to_ull( - bufp, PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_LEAF_BYTES); - *leaf_idx &= (~(uint32_t)0) >> (32 - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_LEAF_BITS); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_avx2/hash_sha256x8.c b/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_avx2/hash_sha256x8.c deleted file mode 100644 index a091d6bba5..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_avx2/hash_sha256x8.c +++ /dev/null @@ -1,61 +0,0 @@ -#include -#include - -#include "address.h" -#include "hashx8.h" -#include "params.h" -#include "sha256.h" -#include "sha256avx.h" -#include "sha256x8.h" -#include "utils.h" - -/* - * 8-way parallel version of prf_addr; takes 8x as much input and output - */ -void PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_prf_addrx8(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7, - const unsigned char *key, - const uint32_t addrx8[8 * 8]) { - unsigned char bufx8[8 * (PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_ADDR_BYTES)]; - unsigned char outbufx8[8 * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_OUTPUT_BYTES]; - unsigned int j; - - for (j = 0; j < 8; j++) { - memcpy(bufx8 + j * (PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_ADDR_BYTES), key, PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N); - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_compress_address(bufx8 + PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N + j * (PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_ADDR_BYTES), - addrx8 + j * 8); - } - - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_sha256x8(outbufx8 + 0 * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 1 * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 2 * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 3 * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 4 * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 5 * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 6 * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 7 * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - bufx8 + 0 * (PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_ADDR_BYTES), - bufx8 + 1 * (PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_ADDR_BYTES), - bufx8 + 2 * (PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_ADDR_BYTES), - bufx8 + 3 * (PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_ADDR_BYTES), - bufx8 + 4 * (PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_ADDR_BYTES), - bufx8 + 5 * (PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_ADDR_BYTES), - bufx8 + 6 * (PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_ADDR_BYTES), - bufx8 + 7 * (PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_ADDR_BYTES), - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_ADDR_BYTES); - - memcpy(out0, outbufx8 + 0 * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N); - memcpy(out1, outbufx8 + 1 * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N); - memcpy(out2, outbufx8 + 2 * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N); - memcpy(out3, outbufx8 + 3 * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N); - memcpy(out4, outbufx8 + 4 * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N); - memcpy(out5, outbufx8 + 5 * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N); - memcpy(out6, outbufx8 + 6 * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N); - memcpy(out7, outbufx8 + 7 * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_avx2/hash_state.h b/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_avx2/hash_state.h deleted file mode 100644 index 30777c2dd0..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_avx2/hash_state.h +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_HASH_STATE_H -#define PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_HASH_STATE_H - -/** - * Defines the type of the hash function state. - * - * Don't be fooled into thinking this instance of SPHINCS+ isn't stateless! - * - * From Section 7.2.2 from the SPHINCS+ round-2 specification: - * - * Each of the instances of the tweakable hash function take PK.seed as its - * first input, which is constant for a given key pair – and, thus, across - * a single signature. This leads to a lot of redundant computation. To remedy - * this, we pad PK.seed to the length of a full 64-byte SHA-256 input block. - * Because of the Merkle-Damgård construction that underlies SHA-256, this - * allows for reuse of the intermediate SHA-256 state after the initial call to - * the compression function which improves performance. - * - * We pass this hash state around in functions, because otherwise we need to - * have a global variable. - * - * We use a struct to differentiate between the x1 and x8 variants of SHA256. - */ - -#include "sha2.h" -#include "sha256avx.h" - -typedef struct { - sha256ctx x1; - sha256ctxx8 x8; -} hash_state; - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_avx2/hashx8.h b/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_avx2/hashx8.h deleted file mode 100644 index a5ca75b0aa..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_avx2/hashx8.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_HASHX8_H -#define PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_HASHX8_H - -#include - -#include "params.h" - -void PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_prf_addrx8(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7, - const unsigned char *key, - const uint32_t addrx8[8 * 8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_avx2/params.h b/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_avx2/params.h deleted file mode 100644 index 78a58506f4..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_avx2/params.h +++ /dev/null @@ -1,53 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_PARAMS_H -#define PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_PARAMS_H - -/* Hash output length in bytes. */ -#define PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N 32 -/* Height of the hypertree. */ -#define PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_FULL_HEIGHT 64 -/* Number of subtree layer. */ -#define PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_D 8 -/* FORS tree dimensions. */ -#define PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_FORS_HEIGHT 14 -#define PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_FORS_TREES 22 -/* Winternitz parameter, */ -#define PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_WOTS_W 16 - -/* The hash function is defined by linking a different hash.c file, as opposed - to setting a #define constant. */ - -/* For clarity */ -#define PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_ADDR_BYTES 32 - -/* WOTS parameters. */ -#define PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_WOTS_LOGW 4 - -#define PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_WOTS_LEN1 (8 * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N / PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_WOTS_LOGW) - -/* PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#define PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_WOTS_LEN2 3 - -#define PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_WOTS_LEN (PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_WOTS_LEN1 + PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_WOTS_LEN2) -#define PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_WOTS_BYTES (PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_WOTS_LEN * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N) -#define PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_WOTS_PK_BYTES PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_WOTS_BYTES - -/* Subtree size. */ -#define PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_TREE_HEIGHT (PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_FULL_HEIGHT / PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_D) - -/* FORS parameters. */ -#define PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_FORS_MSG_BYTES ((PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_FORS_TREES + 7) / 8) -#define PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_FORS_BYTES ((PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_FORS_HEIGHT + 1) * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_FORS_TREES * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N) -#define PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_FORS_PK_BYTES PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N - -/* Resulting SPX sizes. */ -#define PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_BYTES (PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_FORS_BYTES + PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_D * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_WOTS_BYTES +\ - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_FULL_HEIGHT * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N) -#define PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_PK_BYTES (2 * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N) -#define PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SK_BYTES (2 * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_PK_BYTES) - -/* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ -#define PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_OPTRAND_BYTES 32 - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_avx2/sha256.c b/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_avx2/sha256.c deleted file mode 100644 index 34a434915e..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_avx2/sha256.c +++ /dev/null @@ -1,71 +0,0 @@ -/* Based on the public domain implementation in - * crypto_hash/sha512/ref/ from http://bench.cr.yp.to/supercop.html - * by D. J. Bernstein */ - -#include -#include -#include - -#include "sha2.h" -#include "sha256.h" -#include "utils.h" - -/* - * Compresses an address to a 22-byte sequence. - * This reduces the number of required SHA256 compression calls, as the last - * block of input is padded with at least 65 bits. - */ -void PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_compress_address(unsigned char *out, const uint32_t addr[8]) { - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_ull_to_bytes(out, 1, addr[0]); /* drop 3 bytes of the layer field */ - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_ull_to_bytes(out + 1, 4, addr[2]); /* drop the highest tree address word */ - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_ull_to_bytes(out + 5, 4, addr[3]); - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_ull_to_bytes(out + 9, 1, addr[4]); /* drop 3 bytes of the type field */ - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_ull_to_bytes(out + 10, 4, addr[5]); - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_ull_to_bytes(out + 14, 4, addr[6]); - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_ull_to_bytes(out + 18, 4, addr[7]); -} - -/** - * Requires 'input_plus_four_bytes' to have 'inlen' + 4 bytes, so that the last - * four bytes can be used for the counter. Typically 'input' is merely a seed. - * Outputs outlen number of bytes - */ -void PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_mgf1( - unsigned char *out, unsigned long outlen, - unsigned char *input_plus_four_bytes, unsigned long inlen) { - unsigned char outbuf[PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_OUTPUT_BYTES]; - unsigned long i; - - /* While we can fit in at least another full block of SHA256 output.. */ - for (i = 0; (i + 1)*PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_OUTPUT_BYTES <= outlen; i++) { - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_ull_to_bytes(input_plus_four_bytes + inlen, 4, i); - sha256(out, input_plus_four_bytes, inlen + 4); - out += PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_OUTPUT_BYTES; - } - /* Until we cannot anymore, and we fill the remainder. */ - if (outlen > i * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_OUTPUT_BYTES) { - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_ull_to_bytes(input_plus_four_bytes + inlen, 4, i); - sha256(outbuf, input_plus_four_bytes, inlen + 4); - memcpy(out, outbuf, outlen - i * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_OUTPUT_BYTES); - } -} - - -/** - * Absorb the constant pub_seed using one round of the compression function - * This initializes hash_state_seeded, which can then be reused in thash - **/ -void PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_seed_state(sha256ctx *hash_state_seeded, const unsigned char *pub_seed) { - uint8_t block[PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_BLOCK_BYTES]; - size_t i; - - for (i = 0; i < PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N; ++i) { - block[i] = pub_seed[i]; - } - for (i = PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N; i < PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_BLOCK_BYTES; ++i) { - block[i] = 0; - } - - sha256_inc_init(hash_state_seeded); - sha256_inc_blocks(hash_state_seeded, block, 1); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_avx2/sha256.h b/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_avx2/sha256.h deleted file mode 100644 index 88b06b9c6d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_avx2/sha256.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_H -#define PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_H - -#define PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_BLOCK_BYTES 64 -#define PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_OUTPUT_BYTES 32 /* This does not necessarily equal PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N */ -#define PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_ADDR_BYTES 22 - -#include -#include - -#include "sha2.h" - -void PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_compress_address(unsigned char *out, const uint32_t addr[8]); - -void PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_mgf1( - unsigned char *out, unsigned long outlen, - unsigned char *input_plus_four_bytes, unsigned long inlen); - -void PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_seed_state(sha256ctx *hash_state_seeded, const unsigned char *pub_seed); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_avx2/sha256avx.c b/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_avx2/sha256avx.c deleted file mode 100644 index a1bd5d95a5..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_avx2/sha256avx.c +++ /dev/null @@ -1,296 +0,0 @@ -#include -#include -#include - -#include "sha256avx.h" - -// Transpose 8 vectors containing 32-bit values -void PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_transpose(u256 s[8]) { - u256 tmp0[8]; - u256 tmp1[8]; - tmp0[0] = _mm256_unpacklo_epi32(s[0], s[1]); - tmp0[1] = _mm256_unpackhi_epi32(s[0], s[1]); - tmp0[2] = _mm256_unpacklo_epi32(s[2], s[3]); - tmp0[3] = _mm256_unpackhi_epi32(s[2], s[3]); - tmp0[4] = _mm256_unpacklo_epi32(s[4], s[5]); - tmp0[5] = _mm256_unpackhi_epi32(s[4], s[5]); - tmp0[6] = _mm256_unpacklo_epi32(s[6], s[7]); - tmp0[7] = _mm256_unpackhi_epi32(s[6], s[7]); - tmp1[0] = _mm256_unpacklo_epi64(tmp0[0], tmp0[2]); - tmp1[1] = _mm256_unpackhi_epi64(tmp0[0], tmp0[2]); - tmp1[2] = _mm256_unpacklo_epi64(tmp0[1], tmp0[3]); - tmp1[3] = _mm256_unpackhi_epi64(tmp0[1], tmp0[3]); - tmp1[4] = _mm256_unpacklo_epi64(tmp0[4], tmp0[6]); - tmp1[5] = _mm256_unpackhi_epi64(tmp0[4], tmp0[6]); - tmp1[6] = _mm256_unpacklo_epi64(tmp0[5], tmp0[7]); - tmp1[7] = _mm256_unpackhi_epi64(tmp0[5], tmp0[7]); - s[0] = _mm256_permute2x128_si256(tmp1[0], tmp1[4], 0x20); - s[1] = _mm256_permute2x128_si256(tmp1[1], tmp1[5], 0x20); - s[2] = _mm256_permute2x128_si256(tmp1[2], tmp1[6], 0x20); - s[3] = _mm256_permute2x128_si256(tmp1[3], tmp1[7], 0x20); - s[4] = _mm256_permute2x128_si256(tmp1[0], tmp1[4], 0x31); - s[5] = _mm256_permute2x128_si256(tmp1[1], tmp1[5], 0x31); - s[6] = _mm256_permute2x128_si256(tmp1[2], tmp1[6], 0x31); - s[7] = _mm256_permute2x128_si256(tmp1[3], tmp1[7], 0x31); -} - -void PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_sha256_clone_statex8(sha256ctxx8 *outctx, const sha256ctxx8 *inctx) { - memcpy(outctx, inctx, sizeof(sha256ctxx8)); -} - -void PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_sha256_init8x(sha256ctxx8 *ctx) { - ctx->s[0] = _mm256_set_epi32((int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667, (int)0x6a09e667); - ctx->s[1] = _mm256_set_epi32((int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85, (int)0xbb67ae85); - ctx->s[2] = _mm256_set_epi32((int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372, (int)0x3c6ef372); - ctx->s[3] = _mm256_set_epi32((int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a, (int)0xa54ff53a); - ctx->s[4] = _mm256_set_epi32((int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f, (int)0x510e527f); - ctx->s[5] = _mm256_set_epi32((int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c, (int)0x9b05688c); - ctx->s[6] = _mm256_set_epi32((int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab, (int)0x1f83d9ab); - ctx->s[7] = _mm256_set_epi32((int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19, (int)0x5be0cd19); - - ctx->datalen = 0; - ctx->msglen = 0; -} - -void PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_sha256_update8x(sha256ctxx8 *ctx, - const unsigned char *d0, - const unsigned char *d1, - const unsigned char *d2, - const unsigned char *d3, - const unsigned char *d4, - const unsigned char *d5, - const unsigned char *d6, - const unsigned char *d7, - unsigned long long len) { - size_t i = 0; - size_t bytes_to_copy; - - while (i < len) { - bytes_to_copy = (size_t)len - i; - if (bytes_to_copy > 64) { - bytes_to_copy = 64; - } - memcpy(&ctx->msgblocks[64 * 0], d0 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64 * 1], d1 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64 * 2], d2 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64 * 3], d3 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64 * 4], d4 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64 * 5], d5 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64 * 6], d6 + i, bytes_to_copy); - memcpy(&ctx->msgblocks[64 * 7], d7 + i, bytes_to_copy); - ctx->datalen += (unsigned int)bytes_to_copy; - i += bytes_to_copy; - if (ctx->datalen == 64) { - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_sha256_transform8x(ctx, ctx->msgblocks); - ctx->msglen += 512; - ctx->datalen = 0; - } - } -} - -void PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_sha256_final8x(sha256ctxx8 *ctx, - unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7) { - unsigned int i, curlen; - - // Padding - if (ctx->datalen < 56) { - for (i = 0; i < 8; ++i) { - curlen = ctx->datalen; - ctx->msgblocks[64 * i + curlen++] = 0x80; - while (curlen < 64) { - ctx->msgblocks[64 * i + curlen++] = 0x00; - } - } - } else { - for (i = 0; i < 8; ++i) { - curlen = ctx->datalen; - ctx->msgblocks[64 * i + curlen++] = 0x80; - while (curlen < 64) { - ctx->msgblocks[64 * i + curlen++] = 0x00; - } - } - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_sha256_transform8x(ctx, ctx->msgblocks); - memset(ctx->msgblocks, 0, 8 * 64); - } - - // Add length of the message to each block - ctx->msglen += ctx->datalen * 8; - for (i = 0; i < 8; i++) { - ctx->msgblocks[64 * i + 63] = (unsigned char)ctx->msglen; - ctx->msgblocks[64 * i + 62] = (unsigned char)(ctx->msglen >> 8); - ctx->msgblocks[64 * i + 61] = (unsigned char)(ctx->msglen >> 16); - ctx->msgblocks[64 * i + 60] = (unsigned char)(ctx->msglen >> 24); - ctx->msgblocks[64 * i + 59] = (unsigned char)(ctx->msglen >> 32); - ctx->msgblocks[64 * i + 58] = (unsigned char)(ctx->msglen >> 40); - ctx->msgblocks[64 * i + 57] = (unsigned char)(ctx->msglen >> 48); - ctx->msgblocks[64 * i + 56] = (unsigned char)(ctx->msglen >> 56); - } - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_sha256_transform8x(ctx, ctx->msgblocks); - - // Compute final hash output - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_transpose(ctx->s); - - // Store Hash value - STORE(out0, BYTESWAP(ctx->s[0])); - STORE(out1, BYTESWAP(ctx->s[1])); - STORE(out2, BYTESWAP(ctx->s[2])); - STORE(out3, BYTESWAP(ctx->s[3])); - STORE(out4, BYTESWAP(ctx->s[4])); - STORE(out5, BYTESWAP(ctx->s[5])); - STORE(out6, BYTESWAP(ctx->s[6])); - STORE(out7, BYTESWAP(ctx->s[7])); -} - -void PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_sha256_transform8x(sha256ctxx8 *ctx, const unsigned char *data) { - u256 s[8], w[64], T0, T1; - int i; - - // Load words and transform data correctly - for (i = 0; i < 8; i++) { - w[i] = BYTESWAP(LOAD(data + 64 * i)); - w[i + 8] = BYTESWAP(LOAD(data + 32 + 64 * i)); - } - - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_transpose(w); - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_transpose(w + 8); - - // Initial State - s[0] = ctx->s[0]; - s[1] = ctx->s[1]; - s[2] = ctx->s[2]; - s[3] = ctx->s[3]; - s[4] = ctx->s[4]; - s[5] = ctx->s[5]; - s[6] = ctx->s[6]; - s[7] = ctx->s[7]; - - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 0, w[0]); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 1, w[1]); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 2, w[2]); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 3, w[3]); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 4, w[4]); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 5, w[5]); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 6, w[6]); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 7, w[7]); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 8, w[8]); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 9, w[9]); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 10, w[10]); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 11, w[11]); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 12, w[12]); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 13, w[13]); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 14, w[14]); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 15, w[15]); - w[16] = ADD4_32(WSIGMA1_AVX(w[14]), w[0], w[9], WSIGMA0_AVX(w[1])); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 16, w[16]); - w[17] = ADD4_32(WSIGMA1_AVX(w[15]), w[1], w[10], WSIGMA0_AVX(w[2])); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 17, w[17]); - w[18] = ADD4_32(WSIGMA1_AVX(w[16]), w[2], w[11], WSIGMA0_AVX(w[3])); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 18, w[18]); - w[19] = ADD4_32(WSIGMA1_AVX(w[17]), w[3], w[12], WSIGMA0_AVX(w[4])); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 19, w[19]); - w[20] = ADD4_32(WSIGMA1_AVX(w[18]), w[4], w[13], WSIGMA0_AVX(w[5])); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 20, w[20]); - w[21] = ADD4_32(WSIGMA1_AVX(w[19]), w[5], w[14], WSIGMA0_AVX(w[6])); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 21, w[21]); - w[22] = ADD4_32(WSIGMA1_AVX(w[20]), w[6], w[15], WSIGMA0_AVX(w[7])); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 22, w[22]); - w[23] = ADD4_32(WSIGMA1_AVX(w[21]), w[7], w[16], WSIGMA0_AVX(w[8])); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 23, w[23]); - w[24] = ADD4_32(WSIGMA1_AVX(w[22]), w[8], w[17], WSIGMA0_AVX(w[9])); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 24, w[24]); - w[25] = ADD4_32(WSIGMA1_AVX(w[23]), w[9], w[18], WSIGMA0_AVX(w[10])); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 25, w[25]); - w[26] = ADD4_32(WSIGMA1_AVX(w[24]), w[10], w[19], WSIGMA0_AVX(w[11])); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 26, w[26]); - w[27] = ADD4_32(WSIGMA1_AVX(w[25]), w[11], w[20], WSIGMA0_AVX(w[12])); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 27, w[27]); - w[28] = ADD4_32(WSIGMA1_AVX(w[26]), w[12], w[21], WSIGMA0_AVX(w[13])); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 28, w[28]); - w[29] = ADD4_32(WSIGMA1_AVX(w[27]), w[13], w[22], WSIGMA0_AVX(w[14])); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 29, w[29]); - w[30] = ADD4_32(WSIGMA1_AVX(w[28]), w[14], w[23], WSIGMA0_AVX(w[15])); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 30, w[30]); - w[31] = ADD4_32(WSIGMA1_AVX(w[29]), w[15], w[24], WSIGMA0_AVX(w[16])); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 31, w[31]); - w[32] = ADD4_32(WSIGMA1_AVX(w[30]), w[16], w[25], WSIGMA0_AVX(w[17])); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 32, w[32]); - w[33] = ADD4_32(WSIGMA1_AVX(w[31]), w[17], w[26], WSIGMA0_AVX(w[18])); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 33, w[33]); - w[34] = ADD4_32(WSIGMA1_AVX(w[32]), w[18], w[27], WSIGMA0_AVX(w[19])); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 34, w[34]); - w[35] = ADD4_32(WSIGMA1_AVX(w[33]), w[19], w[28], WSIGMA0_AVX(w[20])); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 35, w[35]); - w[36] = ADD4_32(WSIGMA1_AVX(w[34]), w[20], w[29], WSIGMA0_AVX(w[21])); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 36, w[36]); - w[37] = ADD4_32(WSIGMA1_AVX(w[35]), w[21], w[30], WSIGMA0_AVX(w[22])); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 37, w[37]); - w[38] = ADD4_32(WSIGMA1_AVX(w[36]), w[22], w[31], WSIGMA0_AVX(w[23])); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 38, w[38]); - w[39] = ADD4_32(WSIGMA1_AVX(w[37]), w[23], w[32], WSIGMA0_AVX(w[24])); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 39, w[39]); - w[40] = ADD4_32(WSIGMA1_AVX(w[38]), w[24], w[33], WSIGMA0_AVX(w[25])); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 40, w[40]); - w[41] = ADD4_32(WSIGMA1_AVX(w[39]), w[25], w[34], WSIGMA0_AVX(w[26])); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 41, w[41]); - w[42] = ADD4_32(WSIGMA1_AVX(w[40]), w[26], w[35], WSIGMA0_AVX(w[27])); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 42, w[42]); - w[43] = ADD4_32(WSIGMA1_AVX(w[41]), w[27], w[36], WSIGMA0_AVX(w[28])); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 43, w[43]); - w[44] = ADD4_32(WSIGMA1_AVX(w[42]), w[28], w[37], WSIGMA0_AVX(w[29])); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 44, w[44]); - w[45] = ADD4_32(WSIGMA1_AVX(w[43]), w[29], w[38], WSIGMA0_AVX(w[30])); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 45, w[45]); - w[46] = ADD4_32(WSIGMA1_AVX(w[44]), w[30], w[39], WSIGMA0_AVX(w[31])); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 46, w[46]); - w[47] = ADD4_32(WSIGMA1_AVX(w[45]), w[31], w[40], WSIGMA0_AVX(w[32])); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 47, w[47]); - w[48] = ADD4_32(WSIGMA1_AVX(w[46]), w[32], w[41], WSIGMA0_AVX(w[33])); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 48, w[48]); - w[49] = ADD4_32(WSIGMA1_AVX(w[47]), w[33], w[42], WSIGMA0_AVX(w[34])); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 49, w[49]); - w[50] = ADD4_32(WSIGMA1_AVX(w[48]), w[34], w[43], WSIGMA0_AVX(w[35])); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 50, w[50]); - w[51] = ADD4_32(WSIGMA1_AVX(w[49]), w[35], w[44], WSIGMA0_AVX(w[36])); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 51, w[51]); - w[52] = ADD4_32(WSIGMA1_AVX(w[50]), w[36], w[45], WSIGMA0_AVX(w[37])); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 52, w[52]); - w[53] = ADD4_32(WSIGMA1_AVX(w[51]), w[37], w[46], WSIGMA0_AVX(w[38])); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 53, w[53]); - w[54] = ADD4_32(WSIGMA1_AVX(w[52]), w[38], w[47], WSIGMA0_AVX(w[39])); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 54, w[54]); - w[55] = ADD4_32(WSIGMA1_AVX(w[53]), w[39], w[48], WSIGMA0_AVX(w[40])); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 55, w[55]); - w[56] = ADD4_32(WSIGMA1_AVX(w[54]), w[40], w[49], WSIGMA0_AVX(w[41])); - SHA256ROUND_AVX(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], 56, w[56]); - w[57] = ADD4_32(WSIGMA1_AVX(w[55]), w[41], w[50], WSIGMA0_AVX(w[42])); - SHA256ROUND_AVX(s[7], s[0], s[1], s[2], s[3], s[4], s[5], s[6], 57, w[57]); - w[58] = ADD4_32(WSIGMA1_AVX(w[56]), w[42], w[51], WSIGMA0_AVX(w[43])); - SHA256ROUND_AVX(s[6], s[7], s[0], s[1], s[2], s[3], s[4], s[5], 58, w[58]); - w[59] = ADD4_32(WSIGMA1_AVX(w[57]), w[43], w[52], WSIGMA0_AVX(w[44])); - SHA256ROUND_AVX(s[5], s[6], s[7], s[0], s[1], s[2], s[3], s[4], 59, w[59]); - w[60] = ADD4_32(WSIGMA1_AVX(w[58]), w[44], w[53], WSIGMA0_AVX(w[45])); - SHA256ROUND_AVX(s[4], s[5], s[6], s[7], s[0], s[1], s[2], s[3], 60, w[60]); - w[61] = ADD4_32(WSIGMA1_AVX(w[59]), w[45], w[54], WSIGMA0_AVX(w[46])); - SHA256ROUND_AVX(s[3], s[4], s[5], s[6], s[7], s[0], s[1], s[2], 61, w[61]); - w[62] = ADD4_32(WSIGMA1_AVX(w[60]), w[46], w[55], WSIGMA0_AVX(w[47])); - SHA256ROUND_AVX(s[2], s[3], s[4], s[5], s[6], s[7], s[0], s[1], 62, w[62]); - w[63] = ADD4_32(WSIGMA1_AVX(w[61]), w[47], w[56], WSIGMA0_AVX(w[48])); - SHA256ROUND_AVX(s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[0], 63, w[63]); - - // Feed Forward - ctx->s[0] = ADD32(s[0], ctx->s[0]); - ctx->s[1] = ADD32(s[1], ctx->s[1]); - ctx->s[2] = ADD32(s[2], ctx->s[2]); - ctx->s[3] = ADD32(s[3], ctx->s[3]); - ctx->s[4] = ADD32(s[4], ctx->s[4]); - ctx->s[5] = ADD32(s[5], ctx->s[5]); - ctx->s[6] = ADD32(s[6], ctx->s[6]); - ctx->s[7] = ADD32(s[7], ctx->s[7]); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_avx2/sha256avx.h b/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_avx2/sha256avx.h deleted file mode 100644 index 641c1e74fb..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_avx2/sha256avx.h +++ /dev/null @@ -1,103 +0,0 @@ -#ifndef SHA256AVX_H -#define SHA256AVX_H - -#include -#include - -static const unsigned int RC[] = { - 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, - 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, - 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, - 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, - 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, - 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, - 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, - 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, - 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, - 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, - 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, - 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, - 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, - 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, - 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, - 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 -}; - -#define u32 uint32_t -#define u256 __m256i - -#define XOR _mm256_xor_si256 -#define OR _mm256_or_si256 -#define AND _mm256_and_si256 -#define ADD32 _mm256_add_epi32 -#define NOT(x) _mm256_xor_si256(x, _mm256_set_epi32(-1, -1, -1, -1, -1, -1, -1, -1)) - -#define LOAD(src) _mm256_loadu_si256((__m256i *)(src)) -#define STORE(dest,src) _mm256_storeu_si256((__m256i *)(dest),src) - -#define BYTESWAP(x) _mm256_shuffle_epi8(x, _mm256_set_epi8(0xc,0xd,0xe,0xf,0x8,0x9,0xa,0xb,0x4,0x5,0x6,0x7,0x0,0x1,0x2,0x3,0xc,0xd,0xe,0xf,0x8,0x9,0xa,0xb,0x4,0x5,0x6,0x7,0x0,0x1,0x2,0x3)) - -#define SHIFTR32(x, y) _mm256_srli_epi32(x, y) -#define SHIFTL32(x, y) _mm256_slli_epi32(x, y) - -#define ROTR32(x, y) OR(SHIFTR32(x, y), SHIFTL32(x, 32 - (y))) -#define ROTL32(x, y) OR(SHIFTL32(x, y), SHIFTR32(x, 32 - (y))) - -#define XOR3(a, b, c) XOR(XOR(a, b), c) - -#define ADD3_32(a, b, c) ADD32(ADD32(a, b), c) -#define ADD4_32(a, b, c, d) ADD32(ADD32(ADD32(a, b), c), d) -#define ADD5_32(a, b, c, d, e) ADD32(ADD32(ADD32(ADD32(a, b), c), d), e) - -#define MAJ_AVX(a, b, c) XOR3(AND(a, b), AND(a, c), AND(b, c)) -#define CH_AVX(a, b, c) XOR(AND(a, b), AND(NOT(a), c)) - -#define SIGMA1_AVX(x) XOR3(ROTR32(x, 6), ROTR32(x, 11), ROTR32(x, 25)) -#define SIGMA0_AVX(x) XOR3(ROTR32(x, 2), ROTR32(x, 13), ROTR32(x, 22)) - -#define WSIGMA1_AVX(x) XOR3(ROTR32(x, 17), ROTR32(x, 19), SHIFTR32(x, 10)) -#define WSIGMA0_AVX(x) XOR3(ROTR32(x, 7), ROTR32(x, 18), SHIFTR32(x, 3)) - -#define SHA256ROUND_AVX(a, b, c, d, e, f, g, h, rc, w) \ - T0 = ADD5_32(h, SIGMA1_AVX(e), CH_AVX(e, f, g), _mm256_set1_epi32((int)RC[rc]), w); \ - (d) = ADD32(d, T0); \ - T1 = ADD32(SIGMA0_AVX(a), MAJ_AVX(a, b, c)); \ - (h) = ADD32(T0, T1); - -typedef struct SHA256state { - u256 s[8]; - uint8_t msgblocks[8 * 64]; - unsigned int datalen; - uint64_t msglen; -} sha256ctxx8; - - -void PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_transpose(u256 s[8]); -void PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_sha256_init_frombytes_x8(sha256ctxx8 *ctx, const uint8_t *s, unsigned long long msglen); -void PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_sha256_init8x(sha256ctxx8 *ctx); -void PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_sha256_update8x(sha256ctxx8 *ctx, - const unsigned char *d0, - const unsigned char *d1, - const unsigned char *d2, - const unsigned char *d3, - const unsigned char *d4, - const unsigned char *d5, - const unsigned char *d6, - const unsigned char *d7, - unsigned long long len); -void PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_sha256_final8x(sha256ctxx8 *ctx, - unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7); - -void PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_sha256_transform8x(sha256ctxx8 *ctx, const unsigned char *data); - -void PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_sha256_clone_statex8(sha256ctxx8 *outctx, const sha256ctxx8 *inctx); - - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_avx2/sha256x8.c b/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_avx2/sha256x8.c deleted file mode 100644 index fa19337854..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_avx2/sha256x8.c +++ /dev/null @@ -1,128 +0,0 @@ -#include - -#include "sha256.h" -#include "sha256avx.h" -#include "sha256x8.h" -#include "utils.h" - -void PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_seed_statex8(sha256ctxx8 *ctx, const unsigned char *pub_seed) { - uint8_t block[PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_BLOCK_BYTES]; - size_t i; - - for (i = 0; i < PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N; ++i) { - block[i] = pub_seed[i]; - } - for (i = PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N; i < PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_BLOCK_BYTES; ++i) { - block[i] = 0; - } - - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_sha256_init8x(ctx); - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_sha256_update8x(ctx, block, block, block, block, block, block, block, block, PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_BLOCK_BYTES); - -} - -/* This provides a wrapper around the internals of 8x parallel SHA256 */ -void PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_sha256x8(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - const unsigned char *in4, - const unsigned char *in5, - const unsigned char *in6, - const unsigned char *in7, unsigned long long inlen) { - sha256ctxx8 ctx; - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_sha256_init8x(&ctx); - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_sha256_update8x(&ctx, in0, in1, in2, in3, in4, in5, in6, in7, inlen); - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_sha256_final8x(&ctx, out0, out1, out2, out3, out4, out5, out6, out7); -} - -/** - * Note that inlen should be sufficiently small that it still allows for - * an array to be allocated on the stack. Typically 'in' is merely a seed. - * Outputs outlen number of bytes - */ -void PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_mgf1x8( - unsigned char *outx8, - unsigned long outlen, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - const unsigned char *in4, - const unsigned char *in5, - const unsigned char *in6, - const unsigned char *in7, - unsigned long inlen) { - unsigned char inbufx8[8 * ((PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_ADDR_BYTES) + 4)]; - unsigned char outbufx8[8 * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_OUTPUT_BYTES]; - unsigned long i; - unsigned int j; - - memcpy(inbufx8 + 0 * (inlen + 4), in0, inlen); - memcpy(inbufx8 + 1 * (inlen + 4), in1, inlen); - memcpy(inbufx8 + 2 * (inlen + 4), in2, inlen); - memcpy(inbufx8 + 3 * (inlen + 4), in3, inlen); - memcpy(inbufx8 + 4 * (inlen + 4), in4, inlen); - memcpy(inbufx8 + 5 * (inlen + 4), in5, inlen); - memcpy(inbufx8 + 6 * (inlen + 4), in6, inlen); - memcpy(inbufx8 + 7 * (inlen + 4), in7, inlen); - - /* While we can fit in at least another full block of SHA256 output.. */ - for (i = 0; (i + 1)*PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_OUTPUT_BYTES <= outlen; i++) { - for (j = 0; j < 8; j++) { - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_ull_to_bytes(inbufx8 + inlen + j * (inlen + 4), 4, i); - } - - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_sha256x8(outx8 + 0 * outlen, - outx8 + 1 * outlen, - outx8 + 2 * outlen, - outx8 + 3 * outlen, - outx8 + 4 * outlen, - outx8 + 5 * outlen, - outx8 + 6 * outlen, - outx8 + 7 * outlen, - inbufx8 + 0 * (inlen + 4), - inbufx8 + 1 * (inlen + 4), - inbufx8 + 2 * (inlen + 4), - inbufx8 + 3 * (inlen + 4), - inbufx8 + 4 * (inlen + 4), - inbufx8 + 5 * (inlen + 4), - inbufx8 + 6 * (inlen + 4), - inbufx8 + 7 * (inlen + 4), inlen + 4); - outx8 += PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_OUTPUT_BYTES; - } - /* Until we cannot anymore, and we fill the remainder. */ - for (j = 0; j < 8; j++) { - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_ull_to_bytes(inbufx8 + inlen + j * (inlen + 4), 4, i); - } - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_sha256x8(outbufx8 + 0 * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 1 * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 2 * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 3 * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 4 * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 5 * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 6 * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 7 * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - inbufx8 + 0 * (inlen + 4), - inbufx8 + 1 * (inlen + 4), - inbufx8 + 2 * (inlen + 4), - inbufx8 + 3 * (inlen + 4), - inbufx8 + 4 * (inlen + 4), - inbufx8 + 5 * (inlen + 4), - inbufx8 + 6 * (inlen + 4), - inbufx8 + 7 * (inlen + 4), inlen + 4); - - for (j = 0; j < 8; j++) { - memcpy(outx8 + j * outlen, - outbufx8 + j * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outlen - i * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_OUTPUT_BYTES); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_avx2/sha256x8.h b/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_avx2/sha256x8.h deleted file mode 100644 index fe473ab496..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_avx2/sha256x8.h +++ /dev/null @@ -1,44 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256X8_H -#define PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256X8_H - -#include "sha256avx.h" - -#define PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_BLOCK_BYTES 64 -#define PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_OUTPUT_BYTES 32 /* This does not necessarily equal PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N */ - -/* This provides a wrapper around the internals of 8x parallel SHA256 */ -void PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_sha256x8(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - const unsigned char *in4, - const unsigned char *in5, - const unsigned char *in6, - const unsigned char *in7, unsigned long long inlen); - -/** - * Note that inlen should be sufficiently small that it still allows for - * an array to be allocated on the stack. Typically 'in' is merely a seed. - * Outputs outlen number of bytes - */ -void PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_mgf1x8(unsigned char *outx8, unsigned long outlen, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - const unsigned char *in4, - const unsigned char *in5, - const unsigned char *in6, - const unsigned char *in7, - unsigned long inlen); - -void PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_seed_statex8(sha256ctxx8 *ctx, const unsigned char *pub_seed); -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_avx2/sign.c b/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_avx2/sign.c deleted file mode 100644 index b2acc2863c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_avx2/sign.c +++ /dev/null @@ -1,356 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "api.h" -#include "fors.h" -#include "hash.h" -#include "hash_state.h" -#include "params.h" -#include "randombytes.h" -#include "thash.h" -#include "utils.h" -#include "wots.h" - -/** - * Computes the leaf at a given address. First generates the WOTS key pair, - * then computes leaf by hashing horizontally. - */ -static void wots_gen_leaf(unsigned char *leaf, const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx, const uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - unsigned char pk[PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_WOTS_BYTES]; - uint32_t wots_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_set_type( - wots_addr, PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_set_type( - wots_pk_addr, PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_ADDR_TYPE_WOTSPK); - - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_set_keypair_addr( - wots_addr, addr_idx); - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_wots_gen_pk( - pk, sk_seed, pub_seed, wots_addr, hash_state_seeded); - - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_copy_keypair_addr( - wots_pk_addr, wots_addr); - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_thash_WOTS_LEN( - leaf, pk, pub_seed, wots_pk_addr, hash_state_seeded); -} - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_crypto_sign_secretkeybytes(void) { - return PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_CRYPTO_SECRETKEYBYTES; -} - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_crypto_sign_publickeybytes(void) { - return PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_CRYPTO_PUBLICKEYBYTES; -} - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_crypto_sign_bytes(void) { - return PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_CRYPTO_BYTES; -} - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_crypto_sign_seedbytes(void) { - return PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_CRYPTO_SEEDBYTES; -} - -/* - * Generates an SPX key pair given a seed of length - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed) { - /* We do not need the auth path in key generation, but it simplifies the - code to have just one treehash routine that computes both root and path - in one function. */ - unsigned char auth_path[PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_TREE_HEIGHT * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N]; - uint32_t top_tree_addr[8] = {0}; - hash_state hash_state_seeded; - - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_set_layer_addr( - top_tree_addr, PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_D - 1); - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_set_type( - top_tree_addr, PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_ADDR_TYPE_HASHTREE); - - /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ - memcpy(sk, seed, PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_CRYPTO_SEEDBYTES); - - memcpy(pk, sk + 2 * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N, PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_initialize_hash_function(&hash_state_seeded, pk, sk); - - /* Compute root node of the top-most subtree. */ - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_treehash_TREE_HEIGHT( - sk + 3 * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N, auth_path, sk, sk + 2 * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N, 0, 0, - wots_gen_leaf, top_tree_addr, &hash_state_seeded); - - memcpy(pk + PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N, sk + 3 * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N, PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N); - - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_destroy_hash_function(&hash_state_seeded); - return 0; -} - -/* - * Generates an SPX key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk) { - unsigned char seed[PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_CRYPTO_SEEDBYTES]; - randombytes(seed, PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_CRYPTO_SEEDBYTES); - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_crypto_sign_seed_keypair( - pk, sk, seed); - - return 0; -} - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - const unsigned char *sk_seed = sk; - const unsigned char *sk_prf = sk + PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N; - const unsigned char *pk = sk + 2 * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N; - const unsigned char *pub_seed = pk; - - unsigned char optrand[PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N]; - unsigned char mhash[PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_FORS_MSG_BYTES]; - unsigned char root[PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N]; - uint32_t i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - - hash_state hash_state_seeded; - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_initialize_hash_function( - &hash_state_seeded, - pub_seed, sk_seed); - - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_set_type( - wots_addr, PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_set_type( - tree_addr, PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_ADDR_TYPE_HASHTREE); - - /* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ - randombytes(optrand, PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N); - /* Compute the digest randomization value. */ - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_gen_message_random( - sig, sk_prf, optrand, m, mlen, &hash_state_seeded); - - /* Derive the message digest and leaf index from R, PK and M. */ - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N; - - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_set_keypair_addr( - wots_addr, idx_leaf); - - /* Sign the message hash using FORS. */ - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_fors_sign( - sig, root, mhash, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_FORS_BYTES; - - for (i = 0; i < PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_D; i++) { - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_set_tree_addr(tree_addr, tree); - - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_set_keypair_addr( - wots_addr, idx_leaf); - - /* Compute a WOTS signature. */ - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_wots_sign( - sig, root, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_WOTS_BYTES; - - /* Compute the authentication path for the used WOTS leaf. */ - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_treehash_TREE_HEIGHT( - root, sig, sk_seed, pub_seed, idx_leaf, 0, - wots_gen_leaf, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_TREE_HEIGHT * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_TREE_HEIGHT; - } - - *siglen = PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_BYTES; - - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_destroy_hash_function(&hash_state_seeded); - return 0; -} - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk) { - const unsigned char *pub_seed = pk; - const unsigned char *pub_root = pk + PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N; - unsigned char mhash[PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_FORS_MSG_BYTES]; - unsigned char wots_pk[PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_WOTS_BYTES]; - unsigned char root[PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N]; - unsigned char leaf[PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N]; - unsigned int i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - hash_state hash_state_seeded; - - if (siglen != PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_BYTES) { - return -1; - } - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_initialize_hash_function( - &hash_state_seeded, - pub_seed, NULL); - - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_set_type( - wots_addr, PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_set_type( - tree_addr, PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_ADDR_TYPE_HASHTREE); - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_set_type( - wots_pk_addr, PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_ADDR_TYPE_WOTSPK); - - /* Derive the message digest and leaf index from R || PK || M. */ - /* The additional PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N is a result of the hash domain separator. */ - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N; - - /* Layer correctly defaults to 0, so no need to set_layer_addr */ - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_set_keypair_addr( - wots_addr, idx_leaf); - - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_fors_pk_from_sig( - root, sig, mhash, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_FORS_BYTES; - - /* For each subtree.. */ - for (i = 0; i < PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_D; i++) { - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_set_tree_addr(tree_addr, tree); - - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_set_keypair_addr( - wots_addr, idx_leaf); - - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_copy_keypair_addr( - wots_pk_addr, wots_addr); - - /* The WOTS public key is only correct if the signature was correct. */ - /* Initially, root is the FORS pk, but on subsequent iterations it is - the root of the subtree below the currently processed subtree. */ - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_wots_pk_from_sig( - wots_pk, sig, root, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_WOTS_BYTES; - - /* Compute the leaf node using the WOTS public key. */ - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_thash_WOTS_LEN( - leaf, wots_pk, pub_seed, wots_pk_addr, &hash_state_seeded); - - /* Compute the root node of this subtree. */ - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_compute_root( - root, leaf, idx_leaf, 0, sig, PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_TREE_HEIGHT, - pub_seed, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_TREE_HEIGHT * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_TREE_HEIGHT; - } - - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_destroy_hash_function(&hash_state_seeded); - /* Check if the root node equals the root node in the public key. */ - if (memcmp(root, pub_root, PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N) != 0) { - return -1; - } - - return 0; -} - - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - size_t siglen; - - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_crypto_sign_signature( - sm, &siglen, m, mlen, sk); - - memmove(sm + PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_BYTES, m, mlen); - *smlen = siglen + mlen; - - return 0; -} - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk) { - /* The API caller does not necessarily know what size a signature should be - but SPHINCS+ signatures are always exactly PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_BYTES. */ - if (smlen < PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_BYTES) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - *mlen = smlen - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_BYTES; - - if (PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_crypto_sign_verify( - sm, PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_BYTES, sm + PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_BYTES, *mlen, pk)) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - /* If verification was successful, move the message to the right place. */ - memmove(m, sm + PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_BYTES, *mlen); - - return 0; -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_avx2/thash.h b/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_avx2/thash.h deleted file mode 100644 index 241bfc1ee3..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_avx2/thash.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_THASH_H -#define PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_THASH_H - -#include "hash_state.h" - -#include - -void PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_avx2/thash_sha256_simple.c b/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_avx2/thash_sha256_simple.c deleted file mode 100644 index 2b84447fef..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_avx2/thash_sha256_simple.c +++ /dev/null @@ -1,75 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "thash.h" - -#include "sha2.h" -#include "sha256.h" - -/** - * Takes an array of inblocks concatenated arrays of PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N bytes. - */ -static void PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_thash( - unsigned char *out, unsigned char *buf, - const unsigned char *in, unsigned int inblocks, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char outbuf[PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_OUTPUT_BYTES]; - sha256ctx sha2_state; - - (void)pub_seed; /* Suppress an 'unused parameter' warning. */ - - /* Retrieve precomputed state containing pub_seed */ - sha256_inc_ctx_clone(&sha2_state, &hash_state_seeded->x1); - - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_compress_address(buf, addr); - memcpy(buf + PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_ADDR_BYTES, in, inblocks * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N); - - sha256_inc_finalize(outbuf, &sha2_state, buf, PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N); - memcpy(out, outbuf, PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N); -} - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_ADDR_BYTES + 1 * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N]; - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_thash( - out, buf, in, 1, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_ADDR_BYTES + 2 * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N]; - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_thash( - out, buf, in, 2, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_ADDR_BYTES + PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_WOTS_LEN * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N]; - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_thash( - out, buf, in, PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_WOTS_LEN, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_ADDR_BYTES + PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_FORS_TREES * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N]; - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_thash( - out, buf, in, PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_FORS_TREES, pub_seed, addr, hash_state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_avx2/thash_sha256_simplex8.c b/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_avx2/thash_sha256_simplex8.c deleted file mode 100644 index e50719c05a..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_avx2/thash_sha256_simplex8.c +++ /dev/null @@ -1,129 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash_state.h" -#include "params.h" -#include "sha256.h" -#include "sha256avx.h" -#include "sha256x8.h" -#include "thashx8.h" -#include "utils.h" - -/** - * 8-way parallel version of thash; takes 8x as much input and output - */ -static void thashx8(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - unsigned char *out4, - unsigned char *out5, - unsigned char *out6, - unsigned char *out7, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, - const unsigned char *in4, - const unsigned char *in5, - const unsigned char *in6, - const unsigned char *in7, unsigned int inblocks, - const unsigned char *pub_seed, uint32_t addrx8[8 * 8], - uint8_t *bufx8, - const hash_state *state_seeded) { - unsigned char outbufx8[8 * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_OUTPUT_BYTES]; - unsigned int i; - sha256ctxx8 ctx; - - (void)pub_seed; /* Suppress an 'unused parameter' warning. */ - - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_sha256_clone_statex8(&ctx, &state_seeded->x8); - - for (i = 0; i < 8; i++) { - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_compress_address(bufx8 + i * (PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N), - addrx8 + i * 8); - } - - memcpy(bufx8 + PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_ADDR_BYTES + - 0 * (PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N), in0, inblocks * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N); - memcpy(bufx8 + PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_ADDR_BYTES + - 1 * (PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N), in1, inblocks * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N); - memcpy(bufx8 + PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_ADDR_BYTES + - 2 * (PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N), in2, inblocks * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N); - memcpy(bufx8 + PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_ADDR_BYTES + - 3 * (PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N), in3, inblocks * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N); - memcpy(bufx8 + PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_ADDR_BYTES + - 4 * (PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N), in4, inblocks * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N); - memcpy(bufx8 + PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_ADDR_BYTES + - 5 * (PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N), in5, inblocks * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N); - memcpy(bufx8 + PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_ADDR_BYTES + - 6 * (PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N), in6, inblocks * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N); - memcpy(bufx8 + PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_ADDR_BYTES + - 7 * (PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N), in7, inblocks * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N); - - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_sha256_update8x(&ctx, - bufx8 + 0 * (PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N), - bufx8 + 1 * (PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N), - bufx8 + 2 * (PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N), - bufx8 + 3 * (PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N), - bufx8 + 4 * (PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N), - bufx8 + 5 * (PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N), - bufx8 + 6 * (PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N), - bufx8 + 7 * (PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N), - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N); - - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_sha256_final8x(&ctx, - outbufx8 + 0 * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 1 * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 2 * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 3 * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 4 * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 5 * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 6 * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_OUTPUT_BYTES, - outbufx8 + 7 * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_OUTPUT_BYTES); - - memcpy(out0, outbufx8 + 0 * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N); - memcpy(out1, outbufx8 + 1 * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N); - memcpy(out2, outbufx8 + 2 * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N); - memcpy(out3, outbufx8 + 3 * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N); - memcpy(out4, outbufx8 + 4 * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N); - memcpy(out5, outbufx8 + 5 * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N); - memcpy(out6, outbufx8 + 6 * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N); - memcpy(out7, outbufx8 + 7 * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_OUTPUT_BYTES, PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N); -} - -#define thashx8_variant_impl(name, size) \ - void PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_thashx8_##name(unsigned char *out0, \ - unsigned char *out1, \ - unsigned char *out2, \ - unsigned char *out3, \ - unsigned char *out4, \ - unsigned char *out5, \ - unsigned char *out6, \ - unsigned char *out7, \ - const unsigned char *in0, \ - const unsigned char *in1, \ - const unsigned char *in2, \ - const unsigned char *in3, \ - const unsigned char *in4, \ - const unsigned char *in5, \ - const unsigned char *in6, \ - const unsigned char *in7, \ - const unsigned char *pub_seed, \ - uint32_t addrx8[8*8], \ - const hash_state *state_seeded) \ - { \ - const unsigned int inblocks = (size); \ - uint8_t bufx8[8*(PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_SHA256_ADDR_BYTES + (size)*PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N)]; \ - thashx8(out0, out1, out2, out3, out4, out5, out6, out7, \ - in0, in1, in2, in3, in4, in5, in6, in7, inblocks, \ - pub_seed, addrx8, bufx8, state_seeded); \ - } - -thashx8_variant_impl(1, 1) -thashx8_variant_impl(2, 2) -thashx8_variant_impl(WOTS_LEN, PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_WOTS_LEN) -thashx8_variant_impl(FORS_TREES, PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_FORS_TREES) - -#undef thashx8_variant_impl diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_avx2/thashx8.h b/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_avx2/thashx8.h deleted file mode 100644 index 62d88c86c9..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_avx2/thashx8.h +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_THASHX8_H -#define PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_THASHX8_H - -#include - -#include "hash_state.h" -#include "sha256avx.h" - - -#define thashx8_variant(name) \ - void PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_thashx8_##name( \ - unsigned char *out0, \ - unsigned char *out1, \ - unsigned char *out2, \ - unsigned char *out3, \ - unsigned char *out4, \ - unsigned char *out5, \ - unsigned char *out6, \ - unsigned char *out7, \ - const unsigned char *in0, \ - const unsigned char *in1, \ - const unsigned char *in2, \ - const unsigned char *in3, \ - const unsigned char *in4, \ - const unsigned char *in5, \ - const unsigned char *in6, \ - const unsigned char *in7, \ - const unsigned char *pub_seed, \ - uint32_t addrx8[8*8], \ - const hash_state *state_seeded) - - -thashx8_variant(1); -thashx8_variant(2); -thashx8_variant(WOTS_LEN); -thashx8_variant(FORS_TREES); - -#undef thashx8_variant -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_avx2/utils.c b/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_avx2/utils.c deleted file mode 100644 index 7672d40a27..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_avx2/utils.c +++ /dev/null @@ -1,199 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "hash_state.h" -#include "params.h" -#include "thash.h" -#include "utils.h" - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in) { - - /* Iterate over out in decreasing order, for big-endianness. */ - for (size_t i = outlen; i > 0; i--) { - out[i - 1] = in & 0xff; - in = in >> 8; - } -} - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_bytes_to_ull( - const unsigned char *in, size_t inlen) { - unsigned long long retval = 0; - - for (size_t i = 0; i < inlen; i++) { - retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); - } - return retval; -} - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - uint32_t i; - unsigned char buffer[2 * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N]; - - /* If leaf_idx is odd (last bit = 1), current path element is a right child - and auth_path has to go left. Otherwise it is the other way around. */ - if (leaf_idx & 1) { - memcpy(buffer + PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N, leaf, PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N); - } else { - memcpy(buffer, leaf, PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N); - memcpy(buffer + PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N, auth_path, PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N); - } - auth_path += PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N; - - for (i = 0; i < tree_height - 1; i++) { - leaf_idx >>= 1; - idx_offset >>= 1; - /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_set_tree_height(addr, i + 1); - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_set_tree_index( - addr, leaf_idx + idx_offset); - - /* Pick the right or left neighbor, depending on parity of the node. */ - if (leaf_idx & 1) { - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_thash_2( - buffer + PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N); - } else { - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_thash_2( - buffer, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer + PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N, auth_path, PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N); - } - auth_path += PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N; - } - - /* The last iteration is exceptional; we do not copy an auth_path node. */ - leaf_idx >>= 1; - idx_offset >>= 1; - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_set_tree_height(addr, tree_height); - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_set_tree_index( - addr, leaf_idx + idx_offset); - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_thash_2( - root, buffer, pub_seed, addr, hash_state_seeded); -} - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -static void PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_treehash( - unsigned char *root, unsigned char *auth_path, - unsigned char *stack, unsigned int *heights, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - - unsigned int offset = 0; - uint32_t idx; - uint32_t tree_idx; - - for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { - /* Add the next leaf node to the stack. */ - gen_leaf(stack + offset * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N, - sk_seed, pub_seed, idx + idx_offset, tree_addr, - hash_state_seeded); - offset++; - heights[offset - 1] = 0; - - /* If this is a node we need for the auth path.. */ - if ((leaf_idx ^ 0x1) == idx) { - memcpy(auth_path, stack + (offset - 1)*PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N, PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N); - } - - /* While the top-most nodes are of equal height.. */ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { - /* Compute index of the new node, in the next layer. */ - tree_idx = (idx >> (heights[offset - 1] + 1)); - - /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_set_tree_height( - tree_addr, heights[offset - 1] + 1); - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_set_tree_index( - tree_addr, tree_idx + (idx_offset >> (heights[offset - 1] + 1))); - /* Hash the top-most nodes from the stack together. */ - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_thash_2( - stack + (offset - 2)*PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N, stack + (offset - 2)*PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N, - pub_seed, tree_addr, hash_state_seeded); - offset--; - /* Note that the top-most node is now one layer higher. */ - heights[offset - 1]++; - - /* If this is a node we need for the auth path.. */ - if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_path + heights[offset - 1]*PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N, - stack + (offset - 1)*PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N, PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N); - } - } - } - memcpy(root, stack, PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N); -} - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_FORS_HEIGHT + 1)*PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N]; - unsigned int heights[PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_FORS_HEIGHT + 1]; - - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_FORS_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_TREE_HEIGHT + 1)*PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N]; - unsigned int heights[PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_TREE_HEIGHT + 1]; - - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_TREE_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_avx2/utils.h b/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_avx2/utils.h deleted file mode 100644 index 1b59e1f7aa..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_avx2/utils.h +++ /dev/null @@ -1,64 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_UTILS_H -#define PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_UTILS_H - -#include "hash_state.h" -#include "params.h" -#include -#include - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in); - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_bytes_to_ull( - const unsigned char *in, size_t inlen); - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -void PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_avx2/utilsx8.c b/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_avx2/utilsx8.c deleted file mode 100644 index 7234c250d2..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_avx2/utilsx8.c +++ /dev/null @@ -1,172 +0,0 @@ -#include - -#include "address.h" -#include "params.h" -#include "thashx8.h" -#include "utils.h" - -#include "utilsx8.h" - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -static void treehashx8(unsigned char *rootx8, unsigned char *auth_pathx8, - unsigned char *stackx8, unsigned int *heights, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t leaf_idx[8], uint32_t idx_offset[8], - uint32_t tree_height, - void (*gen_leafx8)( - unsigned char * /* leaf0 */, - unsigned char * /* leaf1 */, - unsigned char * /* leaf2 */, - unsigned char * /* leaf3 */, - unsigned char * /* leaf4 */, - unsigned char * /* leaf5 */, - unsigned char * /* leaf6 */, - unsigned char * /* leaf7 */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx0 */, - uint32_t /* addr_idx1 */, - uint32_t /* addr_idx2 */, - uint32_t /* addr_idx3 */, - uint32_t /* addr_idx4 */, - uint32_t /* addr_idx5 */, - uint32_t /* addr_idx6 */, - uint32_t /* addr_idx7 */, - const uint32_t[8] /* tree_addr */, - const hash_state * /* state_seeded */), - uint32_t tree_addrx8[8 * 8], - const hash_state *state_seeded) { - unsigned int offset = 0; - uint32_t idx; - uint32_t tree_idx; - unsigned int j; - - for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { - /* Add the next leaf node to the stack. */ - gen_leafx8(stackx8 + 0 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N + offset * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N, - stackx8 + 1 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N + offset * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N, - stackx8 + 2 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N + offset * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N, - stackx8 + 3 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N + offset * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N, - stackx8 + 4 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N + offset * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N, - stackx8 + 5 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N + offset * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N, - stackx8 + 6 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N + offset * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N, - stackx8 + 7 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N + offset * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N, - sk_seed, pub_seed, - idx + idx_offset[0], - idx + idx_offset[1], - idx + idx_offset[2], - idx + idx_offset[3], - idx + idx_offset[4], - idx + idx_offset[5], - idx + idx_offset[6], - idx + idx_offset[7], - tree_addrx8, - state_seeded); - offset++; - heights[offset - 1] = 0; - - /* If this is a node we need for the auth path.. */ - for (j = 0; j < 8; j++) { - if ((leaf_idx[j] ^ 0x1) == idx) { - memcpy(auth_pathx8 + j * tree_height * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N, - stackx8 + j * (tree_height + 1)*PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N + (offset - 1)*PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N, PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N); - } - } - - /* While the top-most nodes are of equal height.. */ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { - /* Compute index of the new node, in the next layer. */ - tree_idx = (idx >> (heights[offset - 1] + 1)); - - /* Set the address of the node we're creating. */ - for (j = 0; j < 8; j++) { - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_set_tree_height(tree_addrx8 + j * 8, heights[offset - 1] + 1); - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_set_tree_index(tree_addrx8 + j * 8, - tree_idx + (idx_offset[j] >> (heights[offset - 1] + 1))); - } - /* Hash the top-most nodes from the stack together. */ - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_thashx8_2(stackx8 + 0 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N, - stackx8 + 1 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N, - stackx8 + 2 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N, - stackx8 + 3 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N, - stackx8 + 4 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N, - stackx8 + 5 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N, - stackx8 + 6 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N, - stackx8 + 7 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N, - stackx8 + 0 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N, - stackx8 + 1 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N, - stackx8 + 2 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N, - stackx8 + 3 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N, - stackx8 + 4 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N, - stackx8 + 5 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N, - stackx8 + 6 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N, - stackx8 + 7 * (tree_height + 1)*PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N + (offset - 2)*PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N, - pub_seed, tree_addrx8, state_seeded); - offset--; - /* Note that the top-most node is now one layer higher. */ - heights[offset - 1]++; - - /* If this is a node we need for the auth path.. */ - for (j = 0; j < 8; j++) { - if (((leaf_idx[j] >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_pathx8 + j * tree_height * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N + heights[offset - 1]*PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N, - stackx8 + j * (tree_height + 1)*PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N + (offset - 1)*PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N, PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N); - } - } - } - } - - for (j = 0; j < 8; j++) { - memcpy(rootx8 + j * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N, stackx8 + j * (tree_height + 1)*PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N, PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N); - } -} - -/* The wrappers below ensure we used fixed-size buffers on the stack (no VLAs) */ - - -#define treehashx8_variant(name, size) \ - void PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_treehashx8_##name( \ - unsigned char *rootx8, unsigned char *auth_pathx8, \ - const unsigned char *sk_seed, const unsigned char *pub_seed, \ - const uint32_t leaf_idx[8], uint32_t idx_offset[8], \ - void (*gen_leafx8)( \ - unsigned char* /* leaf0 */, \ - unsigned char* /* leaf1 */, \ - unsigned char* /* leaf2 */, \ - unsigned char* /* leaf3 */, \ - unsigned char* /* leaf4 */, \ - unsigned char* /* leaf5 */, \ - unsigned char* /* leaf6 */, \ - unsigned char* /* leaf7 */, \ - const unsigned char* /* sk_seed */, \ - const unsigned char* /* pub_seed */, \ - uint32_t /* addr_idx0 */, \ - uint32_t /* addr_idx1 */, \ - uint32_t /* addr_idx2 */, \ - uint32_t /* addr_idx3 */, \ - uint32_t /* addr_idx4 */, \ - uint32_t /* addr_idx5 */, \ - uint32_t /* addr_idx6 */, \ - uint32_t /* addr_idx7 */, \ - const uint32_t[8] /* tree_addr */, \ - const hash_state* /* state_seeded */), \ - uint32_t tree_addrx8[8*8], \ - const hash_state *state_seeded) \ - { \ - const uint32_t tree_height = (size); \ - unsigned char stackx8[8*((size) + 1)*PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N]; \ - unsigned int heights[(size) + 1]; \ - treehashx8(rootx8, auth_pathx8, stackx8, heights, sk_seed, pub_seed, \ - leaf_idx, idx_offset, tree_height, gen_leafx8, tree_addrx8, state_seeded); \ - } - -treehashx8_variant(FORS_HEIGHT, PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_FORS_HEIGHT) - -#undef treehashx8_variant diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_avx2/utilsx8.h b/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_avx2/utilsx8.h deleted file mode 100644 index 6a1e0b0605..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_avx2/utilsx8.h +++ /dev/null @@ -1,46 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_UTILSX8_H -#define PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_UTILSX8_H - -#include - -#include "hash_state.h" -#include "params.h" - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ - -void PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_treehashx8_FORS_HEIGHT( - unsigned char *rootx8, unsigned char *auth_pathx8, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t leaf_idx[8], uint32_t idx_offset[8], - void (*gen_leafx8)( - unsigned char * /* leaf0 */, - unsigned char * /* leaf1 */, - unsigned char * /* leaf2 */, - unsigned char * /* leaf3 */, - unsigned char * /* leaf4 */, - unsigned char * /* leaf5 */, - unsigned char * /* leaf6 */, - unsigned char * /* leaf7 */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx0 */, - uint32_t /* addr_idx1 */, - uint32_t /* addr_idx2 */, - uint32_t /* addr_idx3 */, - uint32_t /* addr_idx4 */, - uint32_t /* addr_idx5 */, - uint32_t /* addr_idx6 */, - uint32_t /* addr_idx7 */, - const uint32_t[8] /* tree_addr */, - const hash_state * /* state_seeded */), - uint32_t tree_addrx8[8 * 8], - const hash_state *state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_avx2/wots.c b/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_avx2/wots.c deleted file mode 100644 index 2e6f1414d1..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_avx2/wots.c +++ /dev/null @@ -1,240 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "hash_state.h" -#include "hashx8.h" -#include "params.h" -#include "thash.h" -#include "thashx8.h" -#include "utils.h" -#include "wots.h" - -// TODO clarify address expectations, and make them more uniform. -// TODO i.e. do we expect types to be set already? -// TODO and do we expect modifications or copies? - -/** - * Computes the starting value for a chain, i.e. the secret key. - * Expects the address to be complete up to the chain address. - */ -static void wots_gen_sk(unsigned char *sk, const unsigned char *sk_seed, - uint32_t wots_addr[8], const hash_state *state_seeded) { - /* Make sure that the hash address is actually zeroed. */ - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_set_hash_addr(wots_addr, 0); - - /* Generate sk element. */ - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_prf_addr(sk, sk_seed, wots_addr, state_seeded); -} - -/** - * 8-way parallel version of wots_gen_sk; expects 8x as much space in sk - */ -static void wots_gen_skx8(unsigned char *skx8, const unsigned char *sk_seed, - uint32_t wots_addrx8[8 * 8]) { - unsigned int j; - - /* Make sure that the hash address is actually zeroed. */ - for (j = 0; j < 8; j++) { - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_set_hash_addr(wots_addrx8 + j * 8, 0); - } - - /* Generate sk element. */ - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_prf_addrx8(skx8 + 0 * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N, - skx8 + 1 * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N, - skx8 + 2 * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N, - skx8 + 3 * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N, - skx8 + 4 * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N, - skx8 + 5 * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N, - skx8 + 6 * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N, - skx8 + 7 * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N, - sk_seed, wots_addrx8); -} - -/** - * Computes the chaining function. - * out and in have to be n-byte arrays. - * - * Interprets in as start-th value of the chain. - * addr has to contain the address of the chain. - */ -static void gen_chain(unsigned char *out, const unsigned char *in, - unsigned int start, unsigned int steps, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *state_seeded) { - uint32_t i; - - /* Initialize out with the value at position 'start'. */ - memcpy(out, in, PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N); - - /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_WOTS_W; i++) { - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_set_hash_addr(addr, i); - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_thash_1(out, out, pub_seed, addr, state_seeded); - } -} - -/** - * 8-way parallel version of gen_chain; expects 8x as much space in out, and - * 8x as much space in inx8. Assumes start and step identical across chains. - */ -static void gen_chainx8(unsigned char *outx8, const unsigned char *inx8, - unsigned int start, unsigned int steps, - const unsigned char *pub_seed, uint32_t addrx8[8 * 8], - const hash_state *state_seeded) { - uint32_t i; - unsigned int j; - - /* Initialize outx8 with the value at position 'start'. */ - memcpy(outx8, inx8, 8 * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N); - - /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_WOTS_W; i++) { - for (j = 0; j < 8; j++) { - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_set_hash_addr(addrx8 + j * 8, i); - } - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_thashx8_1(outx8 + 0 * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N, - outx8 + 1 * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N, - outx8 + 2 * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N, - outx8 + 3 * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N, - outx8 + 4 * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N, - outx8 + 5 * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N, - outx8 + 6 * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N, - outx8 + 7 * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N, - outx8 + 0 * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N, - outx8 + 1 * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N, - outx8 + 2 * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N, - outx8 + 3 * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N, - outx8 + 4 * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N, - outx8 + 5 * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N, - outx8 + 6 * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N, - outx8 + 7 * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N, - pub_seed, addrx8, state_seeded); - } -} - -/** - * base_w algorithm as described in draft. - * Interprets an array of bytes as integers in base w. - * This only works when log_w is a divisor of 8. - */ -static void base_w(unsigned int *output, const int out_len, const unsigned char *input) { - int in = 0; - int out = 0; - unsigned char total = 0; - int bits = 0; - int consumed; - - for (consumed = 0; consumed < out_len; consumed++) { - if (bits == 0) { - total = input[in]; - in++; - bits += 8; - } - bits -= PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_WOTS_LOGW; - output[out] = (unsigned int)(total >> bits) & (PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_WOTS_W - 1); - out++; - } -} - -/* Computes the WOTS+ checksum over a message (in base_w). */ -static void wots_checksum(unsigned int *csum_base_w, const unsigned int *msg_base_w) { - unsigned int csum = 0; - unsigned char csum_bytes[(PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_WOTS_LEN2 * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_WOTS_LOGW + 7) / 8]; - unsigned int i; - - /* Compute checksum. */ - for (i = 0; i < PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_WOTS_LEN1; i++) { - csum += PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_WOTS_W - 1 - msg_base_w[i]; - } - - /* Convert checksum to base_w. */ - /* Make sure expected empty zero bits are the least significant bits. */ - csum = csum << (8 - ((PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_WOTS_LEN2 * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_WOTS_LOGW) % 8)); - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); - base_w(csum_base_w, PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_WOTS_LEN2, csum_bytes); -} - -/* Takes a message and derives the matching chain lengths. */ -static void chain_lengths(unsigned int *lengths, const unsigned char *msg) { - base_w(lengths, PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_WOTS_LEN1, msg); - wots_checksum(lengths + PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_WOTS_LEN1, lengths); -} - -/** - * WOTS key generation. Takes a 32 byte sk_seed, expands it to WOTS private key - * elements and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_wots_gen_pk(unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *state_seeded) { - uint32_t i; - unsigned int j; - - uint32_t addrx8[8 * 8]; - unsigned char pkbuf[8 * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N]; - - for (j = 0; j < 8; j++) { - memcpy(addrx8 + j * 8, addr, sizeof(uint32_t) * 8); - } - - /* The last iteration typically does not have complete set of 4 chains, - but because we use pkbuf, this is not an issue -- we still do as many - in parallel as possible. */ - for (i = 0; i < ((PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_WOTS_LEN + 7) & ~0x7); i += 8) { - for (j = 0; j < 8; j++) { - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_set_chain_addr(addrx8 + j * 8, i + j); - } - wots_gen_skx8(pkbuf, sk_seed, addrx8); - gen_chainx8(pkbuf, pkbuf, 0, PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_WOTS_W - 1, pub_seed, addrx8, state_seeded); - for (j = 0; j < 8; j++) { - if (i + j < PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_WOTS_LEN) { - memcpy(pk + (i + j)*PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N, pkbuf + j * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N, PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N); - } - } - } -} - -/** - * Takes a n-byte message and the 32-byte sk_see to compute a signature 'sig'. - */ -void PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_wots_sign(unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_WOTS_LEN; i++) { - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_set_chain_addr(addr, i); - wots_gen_sk(sig + i * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N, sk_seed, addr, state_seeded); - gen_chain(sig + i * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N, sig + i * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N, 0, lengths[i], pub_seed, addr, state_seeded); - } -} - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_WOTS_LEN; i++) { - PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_set_chain_addr(addr, i); - gen_chain(pk + i * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N, sig + i * PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_N, - lengths[i], PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_WOTS_W - 1 - lengths[i], pub_seed, addr, state_seeded); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_avx2/wots.h b/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_avx2/wots.h deleted file mode 100644 index 4978c15208..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_avx2/wots.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_WOTS_H -#define PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_WOTS_H - -#include "hash_state.h" -#include "params.h" -#include - -/** - * WOTS key generation. Takes a 32 byte seed for the private key, expands it to - * a full WOTS private key and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_wots_gen_pk( - unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -/** - * Takes a n-byte message and the 32-byte seed for the private key to compute a - * signature that is placed at 'sig'. - */ -void PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_wots_sign( - unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *hash_state_seeded); - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHA256256SSIMPLE_AVX2_wots_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_clean/LICENSE b/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_clean/LICENSE deleted file mode 100644 index 670154e353..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_clean/LICENSE +++ /dev/null @@ -1,116 +0,0 @@ -CC0 1.0 Universal - -Statement of Purpose - -The laws of most jurisdictions throughout the world automatically confer -exclusive Copyright and Related Rights (defined below) upon the creator and -subsequent owner(s) (each and all, an "owner") of an original work of -authorship and/or a database (each, a "Work"). - -Certain owners wish to permanently relinquish those rights to a Work for the -purpose of contributing to a commons of creative, cultural and scientific -works ("Commons") that the public can reliably and without fear of later -claims of infringement build upon, modify, incorporate in other works, reuse -and redistribute as freely as possible in any form whatsoever and for any -purposes, including without limitation commercial purposes. These owners may -contribute to the Commons to promote the ideal of a free culture and the -further production of creative, cultural and scientific works, or to gain -reputation or greater distribution for their Work in part through the use and -efforts of others. - -For these and/or other purposes and motivations, and without any expectation -of additional consideration or compensation, the person associating CC0 with a -Work (the "Affirmer"), to the extent that he or she is an owner of Copyright -and Related Rights in the Work, voluntarily elects to apply CC0 to the Work -and publicly distribute the Work under its terms, with knowledge of his or her -Copyright and Related Rights in the Work and the meaning and intended legal -effect of CC0 on those rights. - -1. Copyright and Related Rights. A Work made available under CC0 may be -protected by copyright and related or neighboring rights ("Copyright and -Related Rights"). Copyright and Related Rights include, but are not limited -to, the following: - - i. the right to reproduce, adapt, distribute, perform, display, communicate, - and translate a Work; - - ii. moral rights retained by the original author(s) and/or performer(s); - - iii. publicity and privacy rights pertaining to a person's image or likeness - depicted in a Work; - - iv. rights protecting against unfair competition in regards to a Work, - subject to the limitations in paragraph 4(a), below; - - v. rights protecting the extraction, dissemination, use and reuse of data in - a Work; - - vi. database rights (such as those arising under Directive 96/9/EC of the - European Parliament and of the Council of 11 March 1996 on the legal - protection of databases, and under any national implementation thereof, - including any amended or successor version of such directive); and - - vii. other similar, equivalent or corresponding rights throughout the world - based on applicable law or treaty, and any national implementations thereof. - -2. Waiver. To the greatest extent permitted by, but not in contravention of, -applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and -unconditionally waives, abandons, and surrenders all of Affirmer's Copyright -and Related Rights and associated claims and causes of action, whether now -known or unknown (including existing as well as future claims and causes of -action), in the Work (i) in all territories worldwide, (ii) for the maximum -duration provided by applicable law or treaty (including future time -extensions), (iii) in any current or future medium and for any number of -copies, and (iv) for any purpose whatsoever, including without limitation -commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes -the Waiver for the benefit of each member of the public at large and to the -detriment of Affirmer's heirs and successors, fully intending that such Waiver -shall not be subject to revocation, rescission, cancellation, termination, or -any other legal or equitable action to disrupt the quiet enjoyment of the Work -by the public as contemplated by Affirmer's express Statement of Purpose. - -3. Public License Fallback. Should any part of the Waiver for any reason be -judged legally invalid or ineffective under applicable law, then the Waiver -shall be preserved to the maximum extent permitted taking into account -Affirmer's express Statement of Purpose. In addition, to the extent the Waiver -is so judged Affirmer hereby grants to each affected person a royalty-free, -non transferable, non sublicensable, non exclusive, irrevocable and -unconditional license to exercise Affirmer's Copyright and Related Rights in -the Work (i) in all territories worldwide, (ii) for the maximum duration -provided by applicable law or treaty (including future time extensions), (iii) -in any current or future medium and for any number of copies, and (iv) for any -purpose whatsoever, including without limitation commercial, advertising or -promotional purposes (the "License"). The License shall be deemed effective as -of the date CC0 was applied by Affirmer to the Work. Should any part of the -License for any reason be judged legally invalid or ineffective under -applicable law, such partial invalidity or ineffectiveness shall not -invalidate the remainder of the License, and in such case Affirmer hereby -affirms that he or she will not (i) exercise any of his or her remaining -Copyright and Related Rights in the Work or (ii) assert any associated claims -and causes of action with respect to the Work, in either case contrary to -Affirmer's express Statement of Purpose. - -4. Limitations and Disclaimers. - - a. No trademark or patent rights held by Affirmer are waived, abandoned, - surrendered, licensed or otherwise affected by this document. - - b. Affirmer offers the Work as-is and makes no representations or warranties - of any kind concerning the Work, express, implied, statutory or otherwise, - including without limitation warranties of title, merchantability, fitness - for a particular purpose, non infringement, or the absence of latent or - other defects, accuracy, or the present or absence of errors, whether or not - discoverable, all to the greatest extent permissible under applicable law. - - c. Affirmer disclaims responsibility for clearing rights of other persons - that may apply to the Work or any use thereof, including without limitation - any person's Copyright and Related Rights in the Work. Further, Affirmer - disclaims responsibility for obtaining any necessary consents, permissions - or other rights required for any use of the Work. - - d. Affirmer understands and acknowledges that Creative Commons is not a - party to this document and has no duty or obligation with respect to this - CC0 or use of the Work. - -For more information, please see - diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_clean/address.c b/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_clean/address.c deleted file mode 100644 index 67e83a3db5..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_clean/address.c +++ /dev/null @@ -1,78 +0,0 @@ -#include - -#include "address.h" -#include "params.h" -#include "utils.h" - -void PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]) { - int i; - - for (i = 0; i < 8; i++) { - PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_ull_to_bytes( - bytes + i * 4, 4, addr[i]); - } -} - -void PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_set_layer_addr( - uint32_t addr[8], uint32_t layer) { - addr[0] = layer; -} - -void PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_set_tree_addr( - uint32_t addr[8], uint64_t tree) { - addr[1] = 0; - addr[2] = (uint32_t) (tree >> 32); - addr[3] = (uint32_t) tree; -} - -void PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_set_type( - uint32_t addr[8], uint32_t type) { - addr[4] = type; -} - -void PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; -} - -/* These functions are used for OTS addresses. */ - -void PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_set_keypair_addr( - uint32_t addr[8], uint32_t keypair) { - addr[5] = keypair; -} - -void PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; - out[5] = in[5]; -} - -void PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_set_chain_addr( - uint32_t addr[8], uint32_t chain) { - addr[6] = chain; -} - -void PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_set_hash_addr( - uint32_t addr[8], uint32_t hash) { - addr[7] = hash; -} - -/* These functions are used for all hash tree addresses (including FORS). */ - -void PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_set_tree_height( - uint32_t addr[8], uint32_t tree_height) { - addr[6] = tree_height; -} - -void PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_set_tree_index( - uint32_t addr[8], uint32_t tree_index) { - addr[7] = tree_index; -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_clean/address.h b/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_clean/address.h deleted file mode 100644 index 269dc1f7ba..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_clean/address.h +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_ADDRESS_H -#define PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_ADDRESS_H - -#include - -#define PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_ADDR_TYPE_WOTS 0 -#define PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_ADDR_TYPE_WOTSPK 1 -#define PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_ADDR_TYPE_HASHTREE 2 -#define PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_ADDR_TYPE_FORSTREE 3 -#define PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_ADDR_TYPE_FORSPK 4 - -void PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]); - -void PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_set_layer_addr( - uint32_t addr[8], uint32_t layer); - -void PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_set_tree_addr( - uint32_t addr[8], uint64_t tree); - -void PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_set_type( - uint32_t addr[8], uint32_t type); - -/* Copies the layer and tree part of one address into the other */ -void PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for WOTS and FORS addresses. */ - -void PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_set_keypair_addr( - uint32_t addr[8], uint32_t keypair); - -void PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_set_chain_addr( - uint32_t addr[8], uint32_t chain); - -void PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_set_hash_addr( - uint32_t addr[8], uint32_t hash); - -void PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for all hash tree addresses (including FORS). */ - -void PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_set_tree_height( - uint32_t addr[8], uint32_t tree_height); - -void PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_set_tree_index( - uint32_t addr[8], uint32_t tree_index); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_clean/api.h b/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_clean/api.h deleted file mode 100644 index d9560eb23f..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_clean/api.h +++ /dev/null @@ -1,81 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_API_H -#define PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_API_H - -#include -#include - - - -#define PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_CRYPTO_ALGNAME "SPHINCS+" - -#define PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_CRYPTO_SECRETKEYBYTES 128 -#define PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_CRYPTO_PUBLICKEYBYTES 64 -#define PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_CRYPTO_BYTES 29792 -#define PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_CRYPTO_SEEDBYTES 96 - - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_clean/fors.c b/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_clean/fors.c deleted file mode 100644 index 4812be3ce7..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_clean/fors.c +++ /dev/null @@ -1,161 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "fors.h" -#include "hash.h" -#include "hash_state.h" -#include "thash.h" -#include "utils.h" - -static void fors_gen_sk(unsigned char *sk, const unsigned char *sk_seed, - uint32_t fors_leaf_addr[8], const hash_state *hash_state_seeded) { - PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_prf_addr( - sk, sk_seed, fors_leaf_addr, hash_state_seeded); -} - -static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, - const unsigned char *pub_seed, - uint32_t fors_leaf_addr[8], - const hash_state *hash_state_seeded) { - PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_thash_1( - leaf, sk, pub_seed, fors_leaf_addr, hash_state_seeded); -} - -static void fors_gen_leaf(unsigned char *leaf, const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx, const uint32_t fors_tree_addr[8], - const hash_state *hash_state_seeded) { - uint32_t fors_leaf_addr[8] = {0}; - - /* Only copy the parts that must be kept in fors_leaf_addr. */ - PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_copy_keypair_addr( - fors_leaf_addr, fors_tree_addr); - PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_set_type( - fors_leaf_addr, PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_set_tree_index( - fors_leaf_addr, addr_idx); - - fors_gen_sk(leaf, sk_seed, fors_leaf_addr, hash_state_seeded); - fors_sk_to_leaf(leaf, leaf, pub_seed, fors_leaf_addr, hash_state_seeded); -} - -/** - * Interprets m as PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_FORS_HEIGHT-bit unsigned integers. - * Assumes m contains at least PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_FORS_TREES bits. - * Assumes indices has space for PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_FORS_TREES integers. - */ -static void message_to_indices(uint32_t *indices, const unsigned char *m) { - unsigned int i, j; - unsigned int offset = 0; - - for (i = 0; i < PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_FORS_TREES; i++) { - indices[i] = 0; - for (j = 0; j < PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_FORS_HEIGHT; j++) { - indices[i] ^= (((uint32_t)m[offset >> 3] >> (offset & 0x7)) & 0x1) << j; - offset++; - } - } -} - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_fors_sign( - unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *hash_state_seeded) { - uint32_t indices[PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_FORS_TREES]; - unsigned char roots[PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_FORS_TREES * PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_N]; - uint32_t fors_tree_addr[8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_copy_keypair_addr( - fors_tree_addr, fors_addr); - PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_copy_keypair_addr( - fors_pk_addr, fors_addr); - - PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_set_type( - fors_tree_addr, PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_set_type( - fors_pk_addr, PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_FORS_TREES; i++) { - idx_offset = i * (1 << PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_FORS_HEIGHT); - - PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_set_tree_height( - fors_tree_addr, 0); - PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_set_tree_index( - fors_tree_addr, indices[i] + idx_offset); - - /* Include the secret key part that produces the selected leaf node. */ - fors_gen_sk(sig, sk_seed, fors_tree_addr, hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_N; - - /* Compute the authentication path for this leaf node. */ - PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_treehash_FORS_HEIGHT( - roots + i * PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_N, sig, sk_seed, pub_seed, - indices[i], idx_offset, fors_gen_leaf, fors_tree_addr, - hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_N * PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_thash_FORS_TREES( - pk, roots, pub_seed, fors_pk_addr, hash_state_seeded); -} - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_fors_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, const uint32_t fors_addr[8], - const hash_state *hash_state_seeded) { - uint32_t indices[PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_FORS_TREES]; - unsigned char roots[PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_FORS_TREES * PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_N]; - unsigned char leaf[PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_N]; - uint32_t fors_tree_addr[8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_copy_keypair_addr(fors_tree_addr, fors_addr); - PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_copy_keypair_addr(fors_pk_addr, fors_addr); - - PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_set_type(fors_tree_addr, PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_set_type(fors_pk_addr, PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_FORS_TREES; i++) { - idx_offset = i * (1 << PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_FORS_HEIGHT); - - PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_set_tree_height(fors_tree_addr, 0); - PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Derive the leaf from the included secret key part. */ - fors_sk_to_leaf(leaf, sig, pub_seed, fors_tree_addr, hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_N; - - /* Derive the corresponding root node of this tree. */ - PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_compute_root(roots + i * PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_N, leaf, indices[i], idx_offset, sig, - PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_FORS_HEIGHT, pub_seed, fors_tree_addr, hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_N * PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_thash_FORS_TREES(pk, roots, pub_seed, fors_pk_addr, hash_state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_clean/fors.h b/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_clean/fors.h deleted file mode 100644 index 105ba4a983..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_clean/fors.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_FORS_H -#define PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_FORS_H - -#include - -#include "hash_state.h" -#include "params.h" - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_fors_sign( - unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *hash_state_seeded); - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_fors_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, const uint32_t fors_addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_clean/hash.h b/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_clean/hash.h deleted file mode 100644 index 797ec37faa..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_clean/hash.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_HASH_H -#define PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_HASH_H - -#include "hash_state.h" - -#include -#include - -void PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_initialize_hash_function( - hash_state *hash_state_seeded, - const unsigned char *pub_seed, const unsigned char *sk_seed); - -void PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_destroy_hash_function(hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_clean/hash_sha256.c b/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_clean/hash_sha256.c deleted file mode 100644 index 2948d690c6..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_clean/hash_sha256.c +++ /dev/null @@ -1,162 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "utils.h" - -#include "sha2.h" -#include "sha256.h" - -/* For SHA256, there is no immediate reason to initialize at the start, - so this function is an empty operation. */ -void PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_initialize_hash_function( - hash_state *hash_state_seeded, - const unsigned char *pub_seed, const unsigned char *sk_seed) { - PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_seed_state(hash_state_seeded, pub_seed); - (void)sk_seed; /* Suppress an 'unused parameter' warning. */ -} - -/* Clean up hash state */ -void PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_destroy_hash_function(hash_state *hash_state_seeded) { - sha256_inc_ctx_release(hash_state_seeded); -} - -/* - * Computes PRF(key, addr), given a secret key of PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_N bytes and an address - */ -void PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded) { - unsigned char buf[PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_N + PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_SHA256_ADDR_BYTES]; - unsigned char outbuf[PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_SHA256_OUTPUT_BYTES]; - - memcpy(buf, key, PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_N); - PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_compress_address(buf + PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_N, addr); - - sha256(outbuf, buf, PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_N + PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_SHA256_ADDR_BYTES); - memcpy(out, outbuf, PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_N); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} - -/** - * Computes the message-dependent randomness R, using a secret seed as a key - * for HMAC, and an optional randomization value prefixed to the message. - * This requires m to have at least PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_SHA256_BLOCK_BYTES + PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_N space - * available in front of the pointer, i.e. before the message to use for the - * prefix. This is necessary to prevent having to move the message around (and - * allocate memory for it). - */ -void PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, const hash_state *hash_state_seeded) { - unsigned char buf[PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_SHA256_BLOCK_BYTES + PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_SHA256_OUTPUT_BYTES]; - sha256ctx state; - int i; - - /* This implements HMAC-SHA256 */ - for (i = 0; i < PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_N; i++) { - buf[i] = 0x36 ^ sk_prf[i]; - } - memset(buf + PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_N, 0x36, PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_N); - - sha256_inc_init(&state); - sha256_inc_blocks(&state, buf, 1); - - memcpy(buf, optrand, PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_N); - - /* If optrand + message cannot fill up an entire block */ - if (PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_N + mlen < PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_SHA256_BLOCK_BYTES) { - memcpy(buf + PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_N, m, mlen); - sha256_inc_finalize(buf + PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_SHA256_BLOCK_BYTES, &state, - buf, mlen + PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_N); - } - /* Otherwise first fill a block, so that finalize only uses the message */ - else { - memcpy(buf + PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_N, m, PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_N); - sha256_inc_blocks(&state, buf, 1); - - m += PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_N; - mlen -= PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_N; - sha256_inc_finalize(buf + PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_SHA256_BLOCK_BYTES, &state, m, mlen); - } - - for (i = 0; i < PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_N; i++) { - buf[i] = 0x5c ^ sk_prf[i]; - } - memset(buf + PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_N, 0x5c, PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_N); - - sha256(buf, buf, PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_SHA256_BLOCK_BYTES + PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_SHA256_OUTPUT_BYTES); - memcpy(R, buf, PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_N); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} - -/** - * Computes the message hash using R, the public key, and the message. - * Outputs the message digest and the index of the leaf. The index is split in - * the tree index and the leaf index, for convenient copying to an address. - */ -void PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded) { -#define PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_TREE_BITS (PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_TREE_HEIGHT * (PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_D - 1)) -#define PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_TREE_BYTES ((PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_TREE_BITS + 7) / 8) -#define PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_LEAF_BITS PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_TREE_HEIGHT -#define PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_LEAF_BYTES ((PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_LEAF_BITS + 7) / 8) -#define PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_DGST_BYTES (PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_FORS_MSG_BYTES + PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_TREE_BYTES + PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_LEAF_BYTES) - - unsigned char seed[PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_SHA256_OUTPUT_BYTES + 4]; - - /* Round to nearest multiple of PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_SHA256_BLOCK_BYTES */ -#define PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_INBLOCKS (((PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_N + PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_PK_BYTES + PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_SHA256_BLOCK_BYTES - 1) & \ - -PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_SHA256_BLOCK_BYTES) / PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_SHA256_BLOCK_BYTES) - unsigned char inbuf[PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_INBLOCKS * PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_SHA256_BLOCK_BYTES]; - - unsigned char buf[PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_DGST_BYTES]; - unsigned char *bufp = buf; - sha256ctx state; - - sha256_inc_init(&state); - - memcpy(inbuf, R, PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_N); - memcpy(inbuf + PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_N, pk, PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_PK_BYTES); - - /* If R + pk + message cannot fill up an entire block */ - if (PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_N + PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_PK_BYTES + mlen < PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_INBLOCKS * PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_SHA256_BLOCK_BYTES) { - memcpy(inbuf + PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_N + PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_PK_BYTES, m, mlen); - sha256_inc_finalize(seed, &state, inbuf, PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_N + PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_PK_BYTES + mlen); - } - /* Otherwise first fill a block, so that finalize only uses the message */ - else { - memcpy(inbuf + PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_N + PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_PK_BYTES, m, - PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_INBLOCKS * PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_N - PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_PK_BYTES); - sha256_inc_blocks(&state, inbuf, PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_INBLOCKS); - - m += PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_INBLOCKS * PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_N - PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_PK_BYTES; - mlen -= PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_INBLOCKS * PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_SHA256_BLOCK_BYTES - PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_N - PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_PK_BYTES; - sha256_inc_finalize(seed, &state, m, mlen); - } - - /* By doing this in two steps, we prevent hashing the message twice; - otherwise each iteration in MGF1 would hash the message again. */ - PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_mgf1(bufp, PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_DGST_BYTES, seed, PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_SHA256_OUTPUT_BYTES); - - memcpy(digest, bufp, PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_FORS_MSG_BYTES); - bufp += PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_FORS_MSG_BYTES; - - *tree = PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_bytes_to_ull(bufp, PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_TREE_BYTES); - *tree &= (~(uint64_t)0) >> (64 - PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_TREE_BITS); - bufp += PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_TREE_BYTES; - - *leaf_idx = (uint32_t)PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_bytes_to_ull( - bufp, PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_LEAF_BYTES); - *leaf_idx &= (~(uint32_t)0) >> (32 - PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_LEAF_BITS); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_clean/hash_state.h b/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_clean/hash_state.h deleted file mode 100644 index 19fc335e27..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_clean/hash_state.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef SPX_HASH_STATE_H -#define SPX_HASH_STATE_H - -/** - * Defines the type of the hash function state. - * - * Don't be fooled into thinking this instance of SPHINCS+ isn't stateless! - * - * From Section 7.2.2 from the SPHINCS+ round-2 specification: - * - * Each of the instances of the tweakable hash function take PK.seed as its - * first input, which is constant for a given key pair – and, thus, across - * a single signature. This leads to a lot of redundant computation. To remedy - * this, we pad PK.seed to the length of a full 64-byte SHA-256 input block. - * Because of the Merkle-Damgård construction that underlies SHA-256, this - * allows for reuse of the intermediate SHA-256 state after the initial call to - * the compression function which improves performance. - * - * We pass this hash state around in functions, because otherwise we need to - * have a global variable. - */ - -#include "sha2.h" -#define hash_state sha256ctx - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_clean/params.h b/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_clean/params.h deleted file mode 100644 index c36552bd2f..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_clean/params.h +++ /dev/null @@ -1,53 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_PARAMS_H -#define PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_PARAMS_H - -/* Hash output length in bytes. */ -#define PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_N 32 -/* Height of the hypertree. */ -#define PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_FULL_HEIGHT 64 -/* Number of subtree layer. */ -#define PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_D 8 -/* FORS tree dimensions. */ -#define PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_FORS_HEIGHT 14 -#define PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_FORS_TREES 22 -/* Winternitz parameter, */ -#define PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_WOTS_W 16 - -/* The hash function is defined by linking a different hash.c file, as opposed - to setting a #define constant. */ - -/* For clarity */ -#define PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_ADDR_BYTES 32 - -/* WOTS parameters. */ -#define PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_WOTS_LOGW 4 - -#define PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_WOTS_LEN1 (8 * PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_N / PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_WOTS_LOGW) - -/* PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#define PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_WOTS_LEN2 3 - -#define PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_WOTS_LEN (PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_WOTS_LEN1 + PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_WOTS_LEN2) -#define PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_WOTS_BYTES (PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_WOTS_LEN * PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_N) -#define PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_WOTS_PK_BYTES PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_WOTS_BYTES - -/* Subtree size. */ -#define PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_TREE_HEIGHT (PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_FULL_HEIGHT / PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_D) - -/* FORS parameters. */ -#define PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_FORS_MSG_BYTES ((PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_FORS_TREES + 7) / 8) -#define PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_FORS_BYTES ((PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_FORS_HEIGHT + 1) * PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_FORS_TREES * PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_N) -#define PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_FORS_PK_BYTES PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_N - -/* Resulting SPX sizes. */ -#define PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_BYTES (PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_N + PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_FORS_BYTES + PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_D * PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_WOTS_BYTES +\ - PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_FULL_HEIGHT * PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_N) -#define PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_PK_BYTES (2 * PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_N) -#define PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_SK_BYTES (2 * PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_N + PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_PK_BYTES) - -/* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ -#define PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_OPTRAND_BYTES 32 - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_clean/sha256.c b/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_clean/sha256.c deleted file mode 100644 index f9d103ecb6..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_clean/sha256.c +++ /dev/null @@ -1,71 +0,0 @@ -/* Based on the public domain implementation in - * crypto_hash/sha512/ref/ from http://bench.cr.yp.to/supercop.html - * by D. J. Bernstein */ - -#include -#include -#include - -#include "sha2.h" -#include "sha256.h" -#include "utils.h" - -/* - * Compresses an address to a 22-byte sequence. - * This reduces the number of required SHA256 compression calls, as the last - * block of input is padded with at least 65 bits. - */ -void PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_compress_address(unsigned char *out, const uint32_t addr[8]) { - PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_ull_to_bytes(out, 1, addr[0]); /* drop 3 bytes of the layer field */ - PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_ull_to_bytes(out + 1, 4, addr[2]); /* drop the highest tree address word */ - PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_ull_to_bytes(out + 5, 4, addr[3]); - PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_ull_to_bytes(out + 9, 1, addr[4]); /* drop 3 bytes of the type field */ - PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_ull_to_bytes(out + 10, 4, addr[5]); - PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_ull_to_bytes(out + 14, 4, addr[6]); - PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_ull_to_bytes(out + 18, 4, addr[7]); -} - -/** - * Requires 'input_plus_four_bytes' to have 'inlen' + 4 bytes, so that the last - * four bytes can be used for the counter. Typically 'input' is merely a seed. - * Outputs outlen number of bytes - */ -void PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_mgf1( - unsigned char *out, unsigned long outlen, - unsigned char *input_plus_four_bytes, unsigned long inlen) { - unsigned char outbuf[PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_SHA256_OUTPUT_BYTES]; - unsigned long i; - - /* While we can fit in at least another full block of SHA256 output.. */ - for (i = 0; (i + 1)*PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_SHA256_OUTPUT_BYTES <= outlen; i++) { - PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_ull_to_bytes(input_plus_four_bytes + inlen, 4, i); - sha256(out, input_plus_four_bytes, inlen + 4); - out += PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_SHA256_OUTPUT_BYTES; - } - /* Until we cannot anymore, and we fill the remainder. */ - if (outlen > i * PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_SHA256_OUTPUT_BYTES) { - PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_ull_to_bytes(input_plus_four_bytes + inlen, 4, i); - sha256(outbuf, input_plus_four_bytes, inlen + 4); - memcpy(out, outbuf, outlen - i * PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_SHA256_OUTPUT_BYTES); - } -} - - -/** - * Absorb the constant pub_seed using one round of the compression function - * This initializes hash_state_seeded, which can then be reused in thash - **/ -void PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_seed_state(sha256ctx *hash_state_seeded, const unsigned char *pub_seed) { - uint8_t block[PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_SHA256_BLOCK_BYTES]; - size_t i; - - for (i = 0; i < PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_N; ++i) { - block[i] = pub_seed[i]; - } - for (i = PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_N; i < PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_SHA256_BLOCK_BYTES; ++i) { - block[i] = 0; - } - - sha256_inc_init(hash_state_seeded); - sha256_inc_blocks(hash_state_seeded, block, 1); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_clean/sha256.h b/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_clean/sha256.h deleted file mode 100644 index e6f8094aa3..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_clean/sha256.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_SHA256_H -#define PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_SHA256_H - -#define PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_SHA256_BLOCK_BYTES 64 -#define PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_SHA256_OUTPUT_BYTES 32 /* This does not necessarily equal PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_N */ -#define PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_SHA256_ADDR_BYTES 22 - -#include -#include - -#include "sha2.h" - -void PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_compress_address(unsigned char *out, const uint32_t addr[8]); - -void PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_mgf1( - unsigned char *out, unsigned long outlen, - unsigned char *input_plus_four_bytes, unsigned long inlen); - -void PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_seed_state(sha256ctx *hash_state_seeded, const unsigned char *pub_seed); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_clean/sign.c b/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_clean/sign.c deleted file mode 100644 index be0d36c3d7..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_clean/sign.c +++ /dev/null @@ -1,356 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "api.h" -#include "fors.h" -#include "hash.h" -#include "hash_state.h" -#include "params.h" -#include "randombytes.h" -#include "thash.h" -#include "utils.h" -#include "wots.h" - -/** - * Computes the leaf at a given address. First generates the WOTS key pair, - * then computes leaf by hashing horizontally. - */ -static void wots_gen_leaf(unsigned char *leaf, const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx, const uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - unsigned char pk[PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_WOTS_BYTES]; - uint32_t wots_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_set_type( - wots_addr, PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_set_type( - wots_pk_addr, PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_ADDR_TYPE_WOTSPK); - - PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_set_keypair_addr( - wots_addr, addr_idx); - PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_wots_gen_pk( - pk, sk_seed, pub_seed, wots_addr, hash_state_seeded); - - PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_copy_keypair_addr( - wots_pk_addr, wots_addr); - PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_thash_WOTS_LEN( - leaf, pk, pub_seed, wots_pk_addr, hash_state_seeded); -} - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_crypto_sign_secretkeybytes(void) { - return PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_CRYPTO_SECRETKEYBYTES; -} - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_crypto_sign_publickeybytes(void) { - return PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_CRYPTO_PUBLICKEYBYTES; -} - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_crypto_sign_bytes(void) { - return PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_CRYPTO_BYTES; -} - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_crypto_sign_seedbytes(void) { - return PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_CRYPTO_SEEDBYTES; -} - -/* - * Generates an SPX key pair given a seed of length - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed) { - /* We do not need the auth path in key generation, but it simplifies the - code to have just one treehash routine that computes both root and path - in one function. */ - unsigned char auth_path[PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_TREE_HEIGHT * PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_N]; - uint32_t top_tree_addr[8] = {0}; - hash_state hash_state_seeded; - - PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_set_layer_addr( - top_tree_addr, PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_D - 1); - PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_set_type( - top_tree_addr, PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_ADDR_TYPE_HASHTREE); - - /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ - memcpy(sk, seed, PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_CRYPTO_SEEDBYTES); - - memcpy(pk, sk + 2 * PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_N, PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_initialize_hash_function(&hash_state_seeded, pk, sk); - - /* Compute root node of the top-most subtree. */ - PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_treehash_TREE_HEIGHT( - sk + 3 * PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_N, auth_path, sk, sk + 2 * PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_N, 0, 0, - wots_gen_leaf, top_tree_addr, &hash_state_seeded); - - memcpy(pk + PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_N, sk + 3 * PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_N, PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_N); - - PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_destroy_hash_function(&hash_state_seeded); - return 0; -} - -/* - * Generates an SPX key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk) { - unsigned char seed[PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_CRYPTO_SEEDBYTES]; - randombytes(seed, PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_CRYPTO_SEEDBYTES); - PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_crypto_sign_seed_keypair( - pk, sk, seed); - - return 0; -} - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - const unsigned char *sk_seed = sk; - const unsigned char *sk_prf = sk + PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_N; - const unsigned char *pk = sk + 2 * PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_N; - const unsigned char *pub_seed = pk; - - unsigned char optrand[PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_N]; - unsigned char mhash[PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_FORS_MSG_BYTES]; - unsigned char root[PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_N]; - uint32_t i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - - hash_state hash_state_seeded; - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_initialize_hash_function( - &hash_state_seeded, - pub_seed, sk_seed); - - PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_set_type( - wots_addr, PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_set_type( - tree_addr, PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_ADDR_TYPE_HASHTREE); - - /* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ - randombytes(optrand, PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_N); - /* Compute the digest randomization value. */ - PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_gen_message_random( - sig, sk_prf, optrand, m, mlen, &hash_state_seeded); - - /* Derive the message digest and leaf index from R, PK and M. */ - PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_N; - - PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); - - /* Sign the message hash using FORS. */ - PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_fors_sign( - sig, root, mhash, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_FORS_BYTES; - - for (i = 0; i < PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_D; i++) { - PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_set_tree_addr(tree_addr, tree); - - PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); - - /* Compute a WOTS signature. */ - PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_wots_sign( - sig, root, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_WOTS_BYTES; - - /* Compute the authentication path for the used WOTS leaf. */ - PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_treehash_TREE_HEIGHT( - root, sig, sk_seed, pub_seed, idx_leaf, 0, - wots_gen_leaf, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_TREE_HEIGHT * PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_TREE_HEIGHT; - } - - *siglen = PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_BYTES; - - PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_destroy_hash_function(&hash_state_seeded); - return 0; -} - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk) { - const unsigned char *pub_seed = pk; - const unsigned char *pub_root = pk + PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_N; - unsigned char mhash[PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_FORS_MSG_BYTES]; - unsigned char wots_pk[PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_WOTS_BYTES]; - unsigned char root[PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_N]; - unsigned char leaf[PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_N]; - unsigned int i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - hash_state hash_state_seeded; - - if (siglen != PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_BYTES) { - return -1; - } - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_initialize_hash_function( - &hash_state_seeded, - pub_seed, NULL); - - PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_set_type( - wots_addr, PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_set_type( - tree_addr, PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_ADDR_TYPE_HASHTREE); - PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_set_type( - wots_pk_addr, PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_ADDR_TYPE_WOTSPK); - - /* Derive the message digest and leaf index from R || PK || M. */ - /* The additional PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_N is a result of the hash domain separator. */ - PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_N; - - /* Layer correctly defaults to 0, so no need to set_layer_addr */ - PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); - - PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_fors_pk_from_sig( - root, sig, mhash, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_FORS_BYTES; - - /* For each subtree.. */ - for (i = 0; i < PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_D; i++) { - PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_set_tree_addr(tree_addr, tree); - - PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); - - PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_copy_keypair_addr( - wots_pk_addr, wots_addr); - - /* The WOTS public key is only correct if the signature was correct. */ - /* Initially, root is the FORS pk, but on subsequent iterations it is - the root of the subtree below the currently processed subtree. */ - PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_wots_pk_from_sig( - wots_pk, sig, root, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_WOTS_BYTES; - - /* Compute the leaf node using the WOTS public key. */ - PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_thash_WOTS_LEN( - leaf, wots_pk, pub_seed, wots_pk_addr, &hash_state_seeded); - - /* Compute the root node of this subtree. */ - PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_compute_root( - root, leaf, idx_leaf, 0, sig, PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_TREE_HEIGHT, - pub_seed, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_TREE_HEIGHT * PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_TREE_HEIGHT; - } - - PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_destroy_hash_function(&hash_state_seeded); - /* Check if the root node equals the root node in the public key. */ - if (memcmp(root, pub_root, PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_N) != 0) { - return -1; - } - - return 0; -} - - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - size_t siglen; - - PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_crypto_sign_signature( - sm, &siglen, m, mlen, sk); - - memmove(sm + PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_BYTES, m, mlen); - *smlen = siglen + mlen; - - return 0; -} - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk) { - /* The API caller does not necessarily know what size a signature should be - but SPHINCS+ signatures are always exactly PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_BYTES. */ - if (smlen < PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_BYTES) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - *mlen = smlen - PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_BYTES; - - if (PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_crypto_sign_verify( - sm, PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_BYTES, sm + PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_BYTES, *mlen, pk)) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - /* If verification was successful, move the message to the right place. */ - memmove(m, sm + PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_BYTES, *mlen); - - return 0; -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_clean/thash.h b/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_clean/thash.h deleted file mode 100644 index d9e8aea92a..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_clean/thash.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_THASH_H -#define PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_THASH_H - -#include "hash_state.h" - -#include - -void PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_clean/thash_sha256_simple.c b/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_clean/thash_sha256_simple.c deleted file mode 100644 index 44023c41e8..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_clean/thash_sha256_simple.c +++ /dev/null @@ -1,75 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "thash.h" - -#include "sha2.h" -#include "sha256.h" - -/** - * Takes an array of inblocks concatenated arrays of PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_N bytes. - */ -static void PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_thash( - unsigned char *out, unsigned char *buf, - const unsigned char *in, unsigned int inblocks, - const unsigned char *pub_seed, uint32_t addr[8], - const sha256ctx *hash_state_seeded) { - - unsigned char outbuf[PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_SHA256_OUTPUT_BYTES]; - sha256ctx sha2_state; - - (void)pub_seed; /* Suppress an 'unused parameter' warning. */ - - /* Retrieve precomputed state containing pub_seed */ - sha256_inc_ctx_clone(&sha2_state, hash_state_seeded); - - PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_compress_address(buf, addr); - memcpy(buf + PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_SHA256_ADDR_BYTES, in, inblocks * PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_N); - - sha256_inc_finalize(outbuf, &sha2_state, buf, PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_SHA256_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_N); - memcpy(out, outbuf, PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_N); -} - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const sha256ctx *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_SHA256_ADDR_BYTES + 1 * PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_N]; - PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_thash( - out, buf, in, 1, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const sha256ctx *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_SHA256_ADDR_BYTES + 2 * PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_N]; - PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_thash( - out, buf, in, 2, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const sha256ctx *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_SHA256_ADDR_BYTES + PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_WOTS_LEN * PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_N]; - PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_thash( - out, buf, in, PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_WOTS_LEN, pub_seed, addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const sha256ctx *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_SHA256_ADDR_BYTES + PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_FORS_TREES * PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_N]; - PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_thash( - out, buf, in, PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_FORS_TREES, pub_seed, addr, hash_state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_clean/utils.c b/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_clean/utils.c deleted file mode 100644 index faf9189864..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_clean/utils.c +++ /dev/null @@ -1,199 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "hash_state.h" -#include "params.h" -#include "thash.h" -#include "utils.h" - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in) { - - /* Iterate over out in decreasing order, for big-endianness. */ - for (size_t i = outlen; i > 0; i--) { - out[i - 1] = in & 0xff; - in = in >> 8; - } -} - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_bytes_to_ull( - const unsigned char *in, size_t inlen) { - unsigned long long retval = 0; - - for (size_t i = 0; i < inlen; i++) { - retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); - } - return retval; -} - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - uint32_t i; - unsigned char buffer[2 * PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_N]; - - /* If leaf_idx is odd (last bit = 1), current path element is a right child - and auth_path has to go left. Otherwise it is the other way around. */ - if (leaf_idx & 1) { - memcpy(buffer + PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_N, leaf, PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_N); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_N); - } else { - memcpy(buffer, leaf, PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_N); - memcpy(buffer + PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_N, auth_path, PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_N); - } - auth_path += PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_N; - - for (i = 0; i < tree_height - 1; i++) { - leaf_idx >>= 1; - idx_offset >>= 1; - /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_set_tree_height(addr, i + 1); - PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_set_tree_index( - addr, leaf_idx + idx_offset); - - /* Pick the right or left neighbor, depending on parity of the node. */ - if (leaf_idx & 1) { - PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_thash_2( - buffer + PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_N, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_N); - } else { - PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_thash_2( - buffer, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer + PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_N, auth_path, PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_N); - } - auth_path += PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_N; - } - - /* The last iteration is exceptional; we do not copy an auth_path node. */ - leaf_idx >>= 1; - idx_offset >>= 1; - PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_set_tree_height(addr, tree_height); - PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_set_tree_index( - addr, leaf_idx + idx_offset); - PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_thash_2( - root, buffer, pub_seed, addr, hash_state_seeded); -} - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -static void PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_treehash( - unsigned char *root, unsigned char *auth_path, - unsigned char *stack, unsigned int *heights, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - - unsigned int offset = 0; - uint32_t idx; - uint32_t tree_idx; - - for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { - /* Add the next leaf node to the stack. */ - gen_leaf(stack + offset * PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_N, - sk_seed, pub_seed, idx + idx_offset, tree_addr, - hash_state_seeded); - offset++; - heights[offset - 1] = 0; - - /* If this is a node we need for the auth path.. */ - if ((leaf_idx ^ 0x1) == idx) { - memcpy(auth_path, stack + (offset - 1)*PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_N, PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_N); - } - - /* While the top-most nodes are of equal height.. */ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { - /* Compute index of the new node, in the next layer. */ - tree_idx = (idx >> (heights[offset - 1] + 1)); - - /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_set_tree_height( - tree_addr, heights[offset - 1] + 1); - PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_set_tree_index( - tree_addr, tree_idx + (idx_offset >> (heights[offset - 1] + 1))); - /* Hash the top-most nodes from the stack together. */ - PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_thash_2( - stack + (offset - 2)*PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_N, stack + (offset - 2)*PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_N, - pub_seed, tree_addr, hash_state_seeded); - offset--; - /* Note that the top-most node is now one layer higher. */ - heights[offset - 1]++; - - /* If this is a node we need for the auth path.. */ - if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_path + heights[offset - 1]*PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_N, - stack + (offset - 1)*PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_N, PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_N); - } - } - } - memcpy(root, stack, PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_N); -} - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_FORS_HEIGHT + 1)*PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_N]; - unsigned int heights[PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_FORS_HEIGHT + 1]; - - PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_FORS_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_TREE_HEIGHT + 1)*PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_N]; - unsigned int heights[PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_TREE_HEIGHT + 1]; - - PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_TREE_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_clean/utils.h b/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_clean/utils.h deleted file mode 100644 index a59dd7fa58..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_clean/utils.h +++ /dev/null @@ -1,64 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_UTILS_H -#define PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_UTILS_H - -#include "hash_state.h" -#include "params.h" -#include -#include - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in); - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_bytes_to_ull( - const unsigned char *in, size_t inlen); - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -void PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_clean/wots.c b/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_clean/wots.c deleted file mode 100644 index e8bda4b306..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_clean/wots.c +++ /dev/null @@ -1,167 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "hash_state.h" -#include "params.h" -#include "thash.h" -#include "utils.h" -#include "wots.h" - -// TODO clarify address expectations, and make them more uniform. -// TODO i.e. do we expect types to be set already? -// TODO and do we expect modifications or copies? - -/** - * Computes the starting value for a chain, i.e. the secret key. - * Expects the address to be complete up to the chain address. - */ -static void wots_gen_sk(unsigned char *sk, const unsigned char *sk_seed, - uint32_t wots_addr[8], - const hash_state *hash_state_seeded) { - /* Make sure that the hash address is actually zeroed. */ - PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_set_hash_addr(wots_addr, 0); - - /* Generate sk element. */ - PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_prf_addr(sk, sk_seed, wots_addr, hash_state_seeded); -} - -/** - * Computes the chaining function. - * out and in have to be n-byte arrays. - * - * Interprets in as start-th value of the chain. - * addr has to contain the address of the chain. - */ -static void gen_chain(unsigned char *out, const unsigned char *in, - unsigned int start, unsigned int steps, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - uint32_t i; - - /* Initialize out with the value at position 'start'. */ - memcpy(out, in, PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_N); - - /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_WOTS_W; i++) { - PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_set_hash_addr(addr, i); - PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_thash_1( - out, out, pub_seed, addr, hash_state_seeded); - } -} - -/** - * base_w algorithm as described in draft. - * Interprets an array of bytes as integers in base w. - * This only works when log_w is a divisor of 8. - */ -static void base_w(unsigned int *output, const size_t out_len, - const unsigned char *input) { - size_t in = 0; - size_t out = 0; - unsigned char total = 0; - unsigned int bits = 0; - size_t consumed; - - for (consumed = 0; consumed < out_len; consumed++) { - if (bits == 0) { - total = input[in]; - in++; - bits += 8; - } - bits -= PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_WOTS_LOGW; - output[out] = (unsigned int)((total >> bits) & (PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_WOTS_W - 1)); - out++; - } -} - -/* Computes the WOTS+ checksum over a message (in base_w). */ -static void wots_checksum(unsigned int *csum_base_w, - const unsigned int *msg_base_w) { - unsigned int csum = 0; - unsigned char csum_bytes[(PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_WOTS_LEN2 * PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_WOTS_LOGW + 7) / 8]; - unsigned int i; - - /* Compute checksum. */ - for (i = 0; i < PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_WOTS_LEN1; i++) { - csum += PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_WOTS_W - 1 - msg_base_w[i]; - } - - /* Convert checksum to base_w. */ - /* Make sure expected empty zero bits are the least significant bits. */ - csum = csum << (8 - ((PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_WOTS_LEN2 * PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_WOTS_LOGW) % 8)); - PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_ull_to_bytes( - csum_bytes, sizeof(csum_bytes), csum); - base_w(csum_base_w, PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_WOTS_LEN2, csum_bytes); -} - -/* Takes a message and derives the matching chain lengths. */ -static void chain_lengths(unsigned int *lengths, const unsigned char *msg) { - base_w(lengths, PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_WOTS_LEN1, msg); - wots_checksum(lengths + PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_WOTS_LEN1, lengths); -} - -/** - * WOTS key generation. Takes a 32 byte sk_seed, expands it to WOTS private key - * elements and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_wots_gen_pk( - unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - uint32_t i; - - for (i = 0; i < PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_WOTS_LEN; i++) { - PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_set_chain_addr(addr, i); - wots_gen_sk(pk + i * PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_N, sk_seed, addr, hash_state_seeded); - gen_chain(pk + i * PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_N, pk + i * PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_N, - 0, PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_WOTS_W - 1, pub_seed, addr, hash_state_seeded); - } -} - -/** - * Takes a n-byte message and the 32-byte sk_see to compute a signature 'sig'. - */ -void PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_wots_sign( - unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *hash_state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_WOTS_LEN; i++) { - PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_set_chain_addr(addr, i); - wots_gen_sk(sig + i * PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_N, sk_seed, addr, hash_state_seeded); - gen_chain(sig + i * PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_N, sig + i * PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_N, 0, lengths[i], pub_seed, addr, hash_state_seeded); - } -} - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_wots_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_WOTS_LEN; i++) { - PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_set_chain_addr(addr, i); - gen_chain(pk + i * PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_N, sig + i * PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_N, - lengths[i], PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_WOTS_W - 1 - lengths[i], pub_seed, addr, - hash_state_seeded); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_clean/wots.h b/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_clean/wots.h deleted file mode 100644 index ed81760073..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-sha256-256s-simple_clean/wots.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_WOTS_H -#define PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_WOTS_H - -#include "hash_state.h" -#include "params.h" -#include - -/** - * WOTS key generation. Takes a 32 byte seed for the private key, expands it to - * a full WOTS private key and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_wots_gen_pk( - unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -/** - * Takes a n-byte message and the 32-byte seed for the private key to compute a - * signature that is placed at 'sig'. - */ -void PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_wots_sign( - unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *hash_state_seeded); - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_wots_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/LICENSE b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/LICENSE deleted file mode 100644 index 670154e353..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/LICENSE +++ /dev/null @@ -1,116 +0,0 @@ -CC0 1.0 Universal - -Statement of Purpose - -The laws of most jurisdictions throughout the world automatically confer -exclusive Copyright and Related Rights (defined below) upon the creator and -subsequent owner(s) (each and all, an "owner") of an original work of -authorship and/or a database (each, a "Work"). - -Certain owners wish to permanently relinquish those rights to a Work for the -purpose of contributing to a commons of creative, cultural and scientific -works ("Commons") that the public can reliably and without fear of later -claims of infringement build upon, modify, incorporate in other works, reuse -and redistribute as freely as possible in any form whatsoever and for any -purposes, including without limitation commercial purposes. These owners may -contribute to the Commons to promote the ideal of a free culture and the -further production of creative, cultural and scientific works, or to gain -reputation or greater distribution for their Work in part through the use and -efforts of others. - -For these and/or other purposes and motivations, and without any expectation -of additional consideration or compensation, the person associating CC0 with a -Work (the "Affirmer"), to the extent that he or she is an owner of Copyright -and Related Rights in the Work, voluntarily elects to apply CC0 to the Work -and publicly distribute the Work under its terms, with knowledge of his or her -Copyright and Related Rights in the Work and the meaning and intended legal -effect of CC0 on those rights. - -1. Copyright and Related Rights. A Work made available under CC0 may be -protected by copyright and related or neighboring rights ("Copyright and -Related Rights"). Copyright and Related Rights include, but are not limited -to, the following: - - i. the right to reproduce, adapt, distribute, perform, display, communicate, - and translate a Work; - - ii. moral rights retained by the original author(s) and/or performer(s); - - iii. publicity and privacy rights pertaining to a person's image or likeness - depicted in a Work; - - iv. rights protecting against unfair competition in regards to a Work, - subject to the limitations in paragraph 4(a), below; - - v. rights protecting the extraction, dissemination, use and reuse of data in - a Work; - - vi. database rights (such as those arising under Directive 96/9/EC of the - European Parliament and of the Council of 11 March 1996 on the legal - protection of databases, and under any national implementation thereof, - including any amended or successor version of such directive); and - - vii. other similar, equivalent or corresponding rights throughout the world - based on applicable law or treaty, and any national implementations thereof. - -2. Waiver. To the greatest extent permitted by, but not in contravention of, -applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and -unconditionally waives, abandons, and surrenders all of Affirmer's Copyright -and Related Rights and associated claims and causes of action, whether now -known or unknown (including existing as well as future claims and causes of -action), in the Work (i) in all territories worldwide, (ii) for the maximum -duration provided by applicable law or treaty (including future time -extensions), (iii) in any current or future medium and for any number of -copies, and (iv) for any purpose whatsoever, including without limitation -commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes -the Waiver for the benefit of each member of the public at large and to the -detriment of Affirmer's heirs and successors, fully intending that such Waiver -shall not be subject to revocation, rescission, cancellation, termination, or -any other legal or equitable action to disrupt the quiet enjoyment of the Work -by the public as contemplated by Affirmer's express Statement of Purpose. - -3. Public License Fallback. Should any part of the Waiver for any reason be -judged legally invalid or ineffective under applicable law, then the Waiver -shall be preserved to the maximum extent permitted taking into account -Affirmer's express Statement of Purpose. In addition, to the extent the Waiver -is so judged Affirmer hereby grants to each affected person a royalty-free, -non transferable, non sublicensable, non exclusive, irrevocable and -unconditional license to exercise Affirmer's Copyright and Related Rights in -the Work (i) in all territories worldwide, (ii) for the maximum duration -provided by applicable law or treaty (including future time extensions), (iii) -in any current or future medium and for any number of copies, and (iv) for any -purpose whatsoever, including without limitation commercial, advertising or -promotional purposes (the "License"). The License shall be deemed effective as -of the date CC0 was applied by Affirmer to the Work. Should any part of the -License for any reason be judged legally invalid or ineffective under -applicable law, such partial invalidity or ineffectiveness shall not -invalidate the remainder of the License, and in such case Affirmer hereby -affirms that he or she will not (i) exercise any of his or her remaining -Copyright and Related Rights in the Work or (ii) assert any associated claims -and causes of action with respect to the Work, in either case contrary to -Affirmer's express Statement of Purpose. - -4. Limitations and Disclaimers. - - a. No trademark or patent rights held by Affirmer are waived, abandoned, - surrendered, licensed or otherwise affected by this document. - - b. Affirmer offers the Work as-is and makes no representations or warranties - of any kind concerning the Work, express, implied, statutory or otherwise, - including without limitation warranties of title, merchantability, fitness - for a particular purpose, non infringement, or the absence of latent or - other defects, accuracy, or the present or absence of errors, whether or not - discoverable, all to the greatest extent permissible under applicable law. - - c. Affirmer disclaims responsibility for clearing rights of other persons - that may apply to the Work or any use thereof, including without limitation - any person's Copyright and Related Rights in the Work. Further, Affirmer - disclaims responsibility for obtaining any necessary consents, permissions - or other rights required for any use of the Work. - - d. Affirmer understands and acknowledges that Creative Commons is not a - party to this document and has no duty or obligation with respect to this - CC0 or use of the Work. - -For more information, please see - diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/address.c b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/address.c deleted file mode 100644 index b956e9cb29..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/address.c +++ /dev/null @@ -1,91 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "utils.h" - -/* - * Specify which level of Merkle tree (the "layer") we're working on - */ -void set_layer_addr(uint32_t addr[8], uint32_t layer) { - ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; -} - -/* - * Specify which Merkle tree within the level (the "tree address") we're working on - */ -void set_tree_addr(uint32_t addr[8], uint64_t tree) { - ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); -} - -/* - * Specify the reason we'll use this address structure for, that is, what - * hash will we compute with it. This is used so that unrelated types of - * hashes don't accidentally get the same address structure. The type will be - * one of the SPX_ADDR_TYPE constants - */ -void set_type(uint32_t addr[8], uint32_t type) { - ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; -} - -/* - * Copy the layer and tree fields of the address structure. This is used - * when we're doing multiple types of hashes within the same Merkle tree - */ -void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { - memcpy( out, in, SPX_OFFSET_TREE + 8 ); -} - -/* These functions are used for OTS addresses. */ - -/* - * Specify which Merkle leaf we're working on; that is, which OTS keypair - * we're talking about. - */ -void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { - ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; -} - -/* - * Copy the layer, tree and keypair fields of the address structure. This is - * used when we're doing multiple things within the same OTS keypair - */ -void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { - memcpy( out, in, SPX_OFFSET_TREE + 8 ); - ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; -} - -/* - * Specify which Merkle chain within the OTS we're working with - * (the chain address) - */ -void set_chain_addr(uint32_t addr[8], uint32_t chain) { - ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; -} - -/* - * Specify where in the Merkle chain we are -* (the hash address) - */ -void set_hash_addr(uint32_t addr[8], uint32_t hash) { - ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; -} - -/* These functions are used for all hash tree addresses (including FORS). */ - -/* - * Specify the height of the node in the Merkle/FORS tree we are in - * (the tree height) - */ -void set_tree_height(uint32_t addr[8], uint32_t tree_height) { - ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; -} - -/* - * Specify the distance from the left edge of the node in the Merkle/FORS tree - * (the tree index) - */ -void set_tree_index(uint32_t addr[8], uint32_t tree_index) { - u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/address.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/address.h deleted file mode 100644 index 24a84eb40c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/address.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef SPX_ADDRESS_H -#define SPX_ADDRESS_H - -#include - -#include "params.h" - -/* The hash types that are passed to set_type */ -#define SPX_ADDR_TYPE_WOTS 0 -#define SPX_ADDR_TYPE_WOTSPK 1 -#define SPX_ADDR_TYPE_HASHTREE 2 -#define SPX_ADDR_TYPE_FORSTREE 3 -#define SPX_ADDR_TYPE_FORSPK 4 -#define SPX_ADDR_TYPE_WOTSPRF 5 -#define SPX_ADDR_TYPE_FORSPRF 6 - -#define set_layer_addr SPX_NAMESPACE(set_layer_addr) -void set_layer_addr(uint32_t addr[8], uint32_t layer); - -#define set_tree_addr SPX_NAMESPACE(set_tree_addr) -void set_tree_addr(uint32_t addr[8], uint64_t tree); - -#define set_type SPX_NAMESPACE(set_type) -void set_type(uint32_t addr[8], uint32_t type); - -/* Copies the layer and tree part of one address into the other */ -#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) -void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for WOTS and FORS addresses. */ - -#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) -void set_keypair_addr(uint32_t addr[8], uint32_t keypair); - -#define set_chain_addr SPX_NAMESPACE(set_chain_addr) -void set_chain_addr(uint32_t addr[8], uint32_t chain); - -#define set_hash_addr SPX_NAMESPACE(set_hash_addr) -void set_hash_addr(uint32_t addr[8], uint32_t hash); - -#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) -void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for all hash tree addresses (including FORS). */ - -#define set_tree_height SPX_NAMESPACE(set_tree_height) -void set_tree_height(uint32_t addr[8], uint32_t tree_height); - -#define set_tree_index SPX_NAMESPACE(set_tree_index) -void set_tree_index(uint32_t addr[8], uint32_t tree_index); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/api.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/api.h deleted file mode 100644 index d32deebff0..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/api.h +++ /dev/null @@ -1,77 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE128FROBUST_AARCH64_API_H -#define PQCLEAN_SPHINCSSHAKE128FROBUST_AARCH64_API_H - -#include -#include - -#define PQCLEAN_SPHINCSSHAKE128FROBUST_AARCH64_CRYPTO_ALGNAME "SPHINCS+-shake-128f-robust" - -#define PQCLEAN_SPHINCSSHAKE128FROBUST_AARCH64_CRYPTO_SECRETKEYBYTES 64 -#define PQCLEAN_SPHINCSSHAKE128FROBUST_AARCH64_CRYPTO_PUBLICKEYBYTES 32 -#define PQCLEAN_SPHINCSSHAKE128FROBUST_AARCH64_CRYPTO_BYTES 17088 - -#define PQCLEAN_SPHINCSSHAKE128FROBUST_AARCH64_CRYPTO_SEEDBYTES 48 - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE128FROBUST_AARCH64_crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE128FROBUST_AARCH64_crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE128FROBUST_AARCH64_crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE128FROBUST_AARCH64_crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHAKE128FROBUST_AARCH64_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHAKE128FROBUST_AARCH64_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSSHAKE128FROBUST_AARCH64_crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE128FROBUST_AARCH64_crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, - const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSSHAKE128FROBUST_AARCH64_crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE128FROBUST_AARCH64_crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk); -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/context.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/context.h deleted file mode 100644 index 6e0a33f3b7..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/context.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef SPX_CONTEXT_H -#define SPX_CONTEXT_H - -#include - -#include "params.h" - -typedef struct { - uint8_t pub_seed[SPX_N]; - uint8_t sk_seed[SPX_N]; -} spx_ctx; - -#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) -void initialize_hash_function(spx_ctx *ctx); - -#define free_hash_function SPX_NAMESPACE(free_hash_function) -void free_hash_function(spx_ctx *ctx); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/context_shake.c b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/context_shake.c deleted file mode 100644 index 9614a103d3..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/context_shake.c +++ /dev/null @@ -1,12 +0,0 @@ -#include "context.h" - -/* For SHAKE256, there is no immediate reason to initialize at the start, - so this function is an empty operation. */ -void initialize_hash_function(spx_ctx *ctx) { - (void)ctx; /* Suppress an 'unused parameter' warning. */ -} - -// in case the hash function api is heap-based. -void free_hash_function(spx_ctx *ctx) { - (void)ctx; -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/f1600x2.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/f1600x2.h deleted file mode 100644 index 70d1af9f14..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/f1600x2.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef SPX_F1600X2_H -#define SPX_F1600X2_H - -#include - -extern uint64_t f1600_RC[24]; -extern void _f1600x2(uint64_t *a, uint64_t *rc); - -#define f1600x2(s) do {_f1600x2((s), f1600_RC);} while(0) - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/f1600x2.s b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/f1600x2.s deleted file mode 100644 index 640ed791ed..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/f1600x2.s +++ /dev/null @@ -1,143 +0,0 @@ -# From https://github.com/bwesterb/armed-keccak - -.macro round - # Execute theta, but without xoring into the state yet. - # Compute parities p[i] = a[i] ^ a[5+i] ^ ... ^ a[20+i]. - eor3.16b v25, v0, v5, v10 - eor3.16b v26, v1, v6, v11 - eor3.16b v27, v2, v7, v12 - eor3.16b v28, v3, v8, v13 - eor3.16b v29, v4, v9, v14 - - eor3.16b v25, v25, v15, v20 - eor3.16b v26, v26, v16, v21 - eor3.16b v27, v27, v17, v22 - eor3.16b v28, v28, v18, v23 - eor3.16b v29, v29, v19, v24 - - # d[0] = rotl(p[1], 1) ^ p[4] - rax1.2d v30, v29, v26 - # d[3] = rotl(p[4], 1) ^ p[2] - rax1.2d v29, v27, v29 - # d[1] = rotl(p[2], 1) ^ p[0] - rax1.2d v27, v25, v27 - # d[4] = rotl(p[0], 1) ^ p[3] - rax1.2d v25, v28, v25 - # d[2] = rotl(p[3], 1) ^ p[1] - rax1.2d v28, v26, v28 - - # Xor parities from step theta into the state at the same time - # as executing rho and pi. - eor.16b v0, v0, v30 - mov.16b v31, v1 - xar.2d v1, v6, v27, 20 - xar.2d v6, v9, v25, 44 - xar.2d v9, v22, v28, 3 - xar.2d v22, v14, v25, 25 - xar.2d v14, v20, v30, 46 - xar.2d v20, v2, v28, 2 - xar.2d v2, v12, v28, 21 - xar.2d v12, v13, v29, 39 - xar.2d v13, v19, v25, 56 - xar.2d v19, v23, v29, 8 - xar.2d v23, v15, v30, 23 - xar.2d v15, v4, v25, 37 - xar.2d v4, v24, v25, 50 - xar.2d v24, v21, v27, 62 - xar.2d v21, v8, v29, 9 - xar.2d v8, v16, v27, 19 - xar.2d v16, v5, v30, 28 - xar.2d v5, v3, v29, 36 - xar.2d v3, v18, v29, 43 - xar.2d v18, v17, v28, 49 - xar.2d v17, v11, v27, 54 - xar.2d v11, v7, v28, 58 - xar.2d v7, v10, v30, 61 - xar.2d v10, v31, v27, 63 - - # Chi - bcax.16b v25, v0, v2, v1 - bcax.16b v26, v1, v3, v2 - bcax.16b v2, v2, v4, v3 - bcax.16b v3, v3, v0, v4 - bcax.16b v4, v4, v1, v0 - mov.16b v0, v25 - mov.16b v1, v26 - - bcax.16b v25, v5, v7, v6 - bcax.16b v26, v6, v8, v7 - bcax.16b v7, v7, v9, v8 - bcax.16b v8, v8, v5, v9 - bcax.16b v9, v9, v6, v5 - mov.16b v5, v25 - mov.16b v6, v26 - - bcax.16b v25, v10, v12, v11 - bcax.16b v26, v11, v13, v12 - bcax.16b v12, v12, v14, v13 - bcax.16b v13, v13, v10, v14 - bcax.16b v14, v14, v11, v10 - mov.16b v10, v25 - mov.16b v11, v26 - - bcax.16b v25, v15, v17, v16 - bcax.16b v26, v16, v18, v17 - bcax.16b v17, v17, v19, v18 - bcax.16b v18, v18, v15, v19 - bcax.16b v19, v19, v16, v15 - mov.16b v15, v25 - mov.16b v16, v26 - - bcax.16b v25, v20, v22, v21 - bcax.16b v26, v21, v23, v22 - bcax.16b v22, v22, v24, v23 - bcax.16b v23, v23, v20, v24 - bcax.16b v24, v24, v21, v20 - mov.16b v20, v25 - mov.16b v21, v26 - - # iota - ld1r {v25.2d}, [x1], #8 - eor.16b v0, v0, v25 -.endm - -.align 4 -.global __f1600x2 -__f1600x2: - stp d8, d9, [sp,#-16]! - stp d10, d11, [sp,#-16]! - stp d12, d13, [sp,#-16]! - stp d14, d15, [sp,#-16]! - - mov x2, x0 - mov x3, #24 - - ld1.2d {v0, v1, v2, v3}, [x0], #64 - ld1.2d {v4, v5, v6, v7}, [x0], #64 - ld1.2d {v8, v9, v10, v11}, [x0], #64 - ld1.2d {v12, v13, v14, v15}, [x0], #64 - ld1.2d {v16, v17, v18, v19}, [x0], #64 - ld1.2d {v20, v21, v22, v23}, [x0], #64 - ld1.2d {v24}, [x0] - -loop: - round - - subs x3, x3, #1 - cbnz x3, loop - - mov x0, x2 - st1.2d {v0, v1, v2, v3}, [x0], #64 - st1.2d {v4, v5, v6, v7}, [x0], #64 - st1.2d {v8, v9, v10, v11}, [x0], #64 - st1.2d {v12, v13, v14, v15}, [x0], #64 - st1.2d {v16, v17, v18, v19}, [x0], #64 - st1.2d {v20, v21, v22, v23}, [x0], #64 - st1.2d {v24}, [x0] - - ldp d14, d15, [sp], #16 - ldp d12, d13, [sp], #16 - ldp d10, d11, [sp], #16 - ldp d8, d9, [sp], #16 - - ret lr diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/f1600x2_const.c b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/f1600x2_const.c deleted file mode 100644 index e49c0ba149..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/f1600x2_const.c +++ /dev/null @@ -1,30 +0,0 @@ -#include "f1600x2.h" - -uint64_t f1600_RC[24] = { - 0x0000000000000001, - 0x0000000000008082, - 0x800000000000808A, - 0x8000000080008000, - 0x000000000000808B, - 0x0000000080000001, - 0x8000000080008081, - 0x8000000000008009, - 0x000000000000008A, - 0x0000000000000088, - 0x0000000080008009, - 0x000000008000000A, - 0x000000008000808B, - 0x800000000000008B, - 0x8000000000008089, - 0x8000000000008003, - 0x8000000000008002, - 0x8000000000000080, - 0x000000000000800A, - 0x800000008000000A, - 0x8000000080008081, - 0x8000000000008080, - 0x0000000080000001, - 0x8000000080008008, -}; - - diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/fips202x2.c b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/fips202x2.c deleted file mode 100644 index 4718c343bc..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/fips202x2.c +++ /dev/null @@ -1,148 +0,0 @@ -#include -#include - -#include "fips202x2.h" -#include "f1600x2.h" -#include "fips202.h" - -uint64_t load64(const unsigned char *x) { - unsigned long long r = 0, i; - - for (i = 0; i < 8; ++i) { - r |= (unsigned long long)x[i] << 8 * i; - } - return r; -} - -void store64(uint8_t *x, uint64_t u) { - unsigned int i; - - for (i = 0; i < 8; ++i) { - x[i] = (uint8_t)u; - u >>= 8; - } -} - -static void keccak_absorb2x(uint64_t *s, - unsigned int r, - const unsigned char *m0, - const unsigned char *m1, - unsigned long long int mlen, - unsigned char p) { - unsigned long long i; - unsigned char t0[200]; - unsigned char t1[200]; - - while (mlen >= r) { - for (i = 0; i < r / 8; ++i) { - s[2 * i + 0] ^= load64(m0 + 8 * i); - s[2 * i + 1] ^= load64(m1 + 8 * i); - } - - f1600x2(s); - mlen -= r; - m0 += r; - m1 += r; - } - - for (i = 0; i < r; ++i) { - t0[i] = 0; - t1[i] = 0; - } - for (i = 0; i < mlen; ++i) { - t0[i] = m0[i]; - t1[i] = m1[i]; - } - - t0[i] = p; - t1[i] = p; - - t0[r - 1] |= 128; - t1[r - 1] |= 128; - - for (i = 0; i < r / 8; ++i) { - s[2 * i + 0] ^= load64(t0 + 8 * i); - s[2 * i + 1] ^= load64(t1 + 8 * i); - } -} - - -static void keccak_squeezeblocks2x(unsigned char *h0, - unsigned char *h1, - unsigned long long int nblocks, - uint64_t *s, - unsigned int r) { - unsigned int i; - - while (nblocks > 0) { - f1600x2(s); - for (i = 0; i < (r >> 3); i++) { - store64(h0 + 8 * i, s[2 * i + 0]); - store64(h1 + 8 * i, s[2 * i + 1]); - } - h0 += r; - h1 += r; - nblocks--; - } -} - - - -void shake128x2(unsigned char *out0, - unsigned char *out1, - unsigned long long outlen, - unsigned char *in0, - unsigned char *in1, - unsigned long long inlen) { - uint64_t s[50] = {0}; - unsigned char t0[SHAKE128_RATE]; - unsigned char t1[SHAKE128_RATE]; - unsigned int i; - - /* absorb 4 message of identical length in parallel */ - keccak_absorb2x(s, SHAKE128_RATE, in0, in1, inlen, 0x1F); - - /* Squeeze output */ - keccak_squeezeblocks2x(out0, out1, outlen / SHAKE128_RATE, s, SHAKE128_RATE); - - out0 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; - out1 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; - - if (outlen % SHAKE128_RATE) { - keccak_squeezeblocks2x(t0, t1, 1, s, SHAKE128_RATE); - for (i = 0; i < outlen % SHAKE128_RATE; i++) { - out0[i] = t0[i]; - out1[i] = t1[i]; - } - } -} - - -void shake256x2(unsigned char *out0, - unsigned char *out1, - unsigned long long outlen, - unsigned char *in0, - unsigned char *in1, - unsigned long long inlen) { - uint64_t s[50] = {0}; - unsigned char t0[SHAKE256_RATE]; - unsigned char t1[SHAKE256_RATE]; - unsigned int i; - - /* absorb 2 message of identical length in parallel */ - keccak_absorb2x(s, SHAKE256_RATE, in0, in1, inlen, 0x1F); - - /* Squeeze output */ - keccak_squeezeblocks2x(out0, out1, outlen / SHAKE256_RATE, s, SHAKE256_RATE); - - out0 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; - out1 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; - - if (outlen % SHAKE256_RATE) { - keccak_squeezeblocks2x(t0, t1, 1, s, SHAKE256_RATE); - for (i = 0; i < outlen % SHAKE256_RATE; i++) { - out0[i] = t0[i]; - out1[i] = t1[i]; - } - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/fips202x2.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/fips202x2.h deleted file mode 100644 index 7ba58b35d8..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/fips202x2.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef SPX_FIPS202X2_H -#define SPX_FIPS202X2_H - -#include - -uint64_t load64(const unsigned char *x); -void store64(uint8_t *x, uint64_t u); - - -void shake128x2(unsigned char *out0, - unsigned char *out1, - unsigned long long outlen, - unsigned char *in0, - unsigned char *in1, - unsigned long long inlen); - -void shake256x2(unsigned char *out0, - unsigned char *out1, - unsigned long long outlen, - unsigned char *in0, - unsigned char *in1, - unsigned long long inlen); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/fors.c b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/fors.c deleted file mode 100644 index 39193d04e2..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/fors.c +++ /dev/null @@ -1,191 +0,0 @@ -#include -#include -#include - -#include "fors.h" - -#include "address.h" -#include "hash.h" -#include "hashx2.h" -#include "thash.h" -#include "thashx2.h" -#include "utils.h" -#include "utilsx2.h" - -static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, - uint32_t fors_leaf_addr[8]) { - prf_addr(sk, ctx, fors_leaf_addr); -} - -static void fors_gen_skx2(unsigned char *sk0, - unsigned char *sk1, - const spx_ctx *ctx, - uint32_t fors_leaf_addrx2[2 * 8]) { - prf_addrx2(sk0, sk1, - ctx, fors_leaf_addrx2); -} - -static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, - const spx_ctx *ctx, - uint32_t fors_leaf_addr[8]) { - thash(leaf, sk, 1, ctx, fors_leaf_addr); -} - -static void fors_sk_to_leafx2(unsigned char *leaf0, - unsigned char *leaf1, - const unsigned char *sk0, - const unsigned char *sk1, - const spx_ctx *ctx, - uint32_t fors_leaf_addrx2[2 * 8]) { - thashx2(leaf0, leaf1, - sk0, sk1, - 1, ctx, fors_leaf_addrx2); -} - -struct fors_gen_leaf_info { - uint32_t leaf_addrx[2 * 8]; -}; - -static void fors_gen_leafx2(unsigned char *leaf, - const spx_ctx *ctx, - uint32_t addr_idx, void *info) { - struct fors_gen_leaf_info *fors_info = info; - uint32_t *fors_leaf_addrx2 = fors_info->leaf_addrx; - unsigned int j; - - /* Only set the parts that the caller doesn't set */ - for (j = 0; j < 2; j++) { - set_tree_index(fors_leaf_addrx2 + j * 8, addr_idx + j); - set_type(fors_leaf_addrx2 + j * 8, SPX_ADDR_TYPE_FORSPRF); - } - - fors_gen_skx2(leaf + 0 * SPX_N, - leaf + 1 * SPX_N, - ctx, fors_leaf_addrx2); - - for (j = 0; j < 2; j++) { - set_type(fors_leaf_addrx2 + j * 8, SPX_ADDR_TYPE_FORSTREE); - } - - fors_sk_to_leafx2(leaf + 0 * SPX_N, - leaf + 1 * SPX_N, - leaf + 0 * SPX_N, - leaf + 1 * SPX_N, - ctx, fors_leaf_addrx2); -} - -/** - * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - * Assumes indices has space for SPX_FORS_TREES integers. - */ -static void message_to_indices(uint32_t *indices, const unsigned char *m) { - unsigned int i, j; - unsigned int offset = 0; - - for (i = 0; i < SPX_FORS_TREES; i++) { - indices[i] = 0; - for (j = 0; j < SPX_FORS_HEIGHT; j++) { - indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); - offset++; - } - } -} - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -void fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]) { - uint32_t indices[SPX_FORS_TREES]; - unsigned char roots[SPX_FORS_TREES * SPX_N]; - uint32_t fors_tree_addr[2 * 8] = {0}; - struct fors_gen_leaf_info fors_info = {0}; - uint32_t *fors_leaf_addr = fors_info.leaf_addrx; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - for (i = 0; i < 2; i++) { - copy_keypair_addr(fors_tree_addr + 8 * i, fors_addr); - set_type(fors_tree_addr + 8 * i, SPX_ADDR_TYPE_FORSTREE); - copy_keypair_addr(fors_leaf_addr + 8 * i, fors_addr); - } - copy_keypair_addr(fors_pk_addr, fors_addr); - set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < SPX_FORS_TREES; i++) { - idx_offset = i * (1 << SPX_FORS_HEIGHT); - - set_tree_height(fors_tree_addr, 0); - set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Include the secret key part that produces the selected leaf node. */ - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); - fors_gen_sk(sig, ctx, fors_tree_addr); - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); - sig += SPX_N; - - /* Compute the authentication path for this leaf node. */ - treehashx2(roots + i * SPX_N, sig, ctx, - indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx2, - fors_tree_addr, &fors_info); - - sig += SPX_N * SPX_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); -} - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -void fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]) { - uint32_t indices[SPX_FORS_TREES]; - unsigned char roots[SPX_FORS_TREES * SPX_N]; - unsigned char leaf[SPX_N]; - uint32_t fors_tree_addr[8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - copy_keypair_addr(fors_tree_addr, fors_addr); - copy_keypair_addr(fors_pk_addr, fors_addr); - - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); - set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < SPX_FORS_TREES; i++) { - idx_offset = i * (1 << SPX_FORS_HEIGHT); - - set_tree_height(fors_tree_addr, 0); - set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Derive the leaf from the included secret key part. */ - fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); - sig += SPX_N; - - /* Derive the corresponding root node of this tree. */ - compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, - sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); - sig += SPX_N * SPX_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/fors.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/fors.h deleted file mode 100644 index 509140a178..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/fors.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef SPX_FORS_H -#define SPX_FORS_H - -#include - -#include "context.h" -#include "params.h" - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -#define fors_sign SPX_NAMESPACE(fors_sign) -void fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]); - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) -void fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/hash.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/hash.h deleted file mode 100644 index f7c87d4c3c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/hash.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef SPX_HASH_H -#define SPX_HASH_H - -#include -#include - -#include "context.h" -#include "params.h" - -#define prf_addr SPX_NAMESPACE(prf_addr) -void prf_addr(unsigned char *out, const spx_ctx *ctx, - const uint32_t addr[8]); - -#define gen_message_random SPX_NAMESPACE(gen_message_random) -void gen_message_random(unsigned char *R, const unsigned char *sk_prf, - const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx); - -#define hash_message SPX_NAMESPACE(hash_message) -void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx); - - - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/hash_shake.c b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/hash_shake.c deleted file mode 100644 index ff5e7ec918..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/hash_shake.c +++ /dev/null @@ -1,83 +0,0 @@ -#include -#include - -#include "hash.h" - -#include "address.h" -#include "fips202.h" -#include "params.h" -#include "utils.h" - -/* - * Computes PRF(pk_seed, sk_seed, addr) - */ -void prf_addr(unsigned char *out, const spx_ctx *ctx, - const uint32_t addr[8]) { - unsigned char buf[2 * SPX_N + SPX_ADDR_BYTES]; - - memcpy(buf, ctx->pub_seed, SPX_N); - memcpy(buf + SPX_N, addr, SPX_ADDR_BYTES); - memcpy(buf + SPX_N + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); - - shake256(out, SPX_N, buf, 2 * SPX_N + SPX_ADDR_BYTES); -} - -/** - * Computes the message-dependent randomness R, using a secret seed and an - * optional randomization value as well as the message. - */ -void gen_message_random(unsigned char *R, const unsigned char *sk_prf, - const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx) { - (void)ctx; - shake256incctx s_inc; - - shake256_inc_init(&s_inc); - shake256_inc_absorb(&s_inc, sk_prf, SPX_N); - shake256_inc_absorb(&s_inc, optrand, SPX_N); - shake256_inc_absorb(&s_inc, m, mlen); - shake256_inc_finalize(&s_inc); - shake256_inc_squeeze(R, SPX_N, &s_inc); - shake256_inc_ctx_release(&s_inc); -} - -/** - * Computes the message hash using R, the public key, and the message. - * Outputs the message digest and the index of the leaf. The index is split in - * the tree index and the leaf index, for convenient copying to an address. - */ -void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx) { - (void)ctx; -#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) -#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) -#define SPX_LEAF_BITS SPX_TREE_HEIGHT -#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) -#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) - - unsigned char buf[SPX_DGST_BYTES]; - unsigned char *bufp = buf; - shake256incctx s_inc; - - shake256_inc_init(&s_inc); - shake256_inc_absorb(&s_inc, R, SPX_N); - shake256_inc_absorb(&s_inc, pk, SPX_PK_BYTES); - shake256_inc_absorb(&s_inc, m, mlen); - shake256_inc_finalize(&s_inc); - shake256_inc_squeeze(buf, SPX_DGST_BYTES, &s_inc); - shake256_inc_ctx_release(&s_inc); - - memcpy(digest, bufp, SPX_FORS_MSG_BYTES); - bufp += SPX_FORS_MSG_BYTES; - - - *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); - *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); - bufp += SPX_TREE_BYTES; - - *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); - *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/hash_shakex2.c b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/hash_shakex2.c deleted file mode 100644 index 99571916a2..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/hash_shakex2.c +++ /dev/null @@ -1,52 +0,0 @@ -#include -#include - -#include "hashx2.h" - -#include "address.h" -#include "f1600x2.h" -#include "fips202x2.h" -#include "params.h" - -/* - * 2-way parallel version of prf_addr; takes 2x as much input and output - */ -void prf_addrx2(unsigned char *out0, - unsigned char *out1, - const spx_ctx *ctx, - const uint32_t addrx2[2 * 8]) { - /* As we write and read only a few quadwords, it is more efficient to - * build and extract from the fourway SHAKE256 state by hand. */ - uint64_t state[50] = {0}; - - for (int i = 0; i < SPX_N / 8; i++) { - uint64_t x = load64(ctx->pub_seed + 8 * i); - state[2 * i] = x; - state[2 * i + 1] = x; - } - for (int i = 0; i < 4; i++) { - state[2 * (SPX_N / 8 + i)] = (((uint64_t)addrx2[1 + 2 * i]) << 32) - | (uint64_t)addrx2[2 * i]; - state[2 * (SPX_N / 8 + i) + 1] = (((uint64_t)addrx2[8 + 1 + 2 * i]) << 32) - | (uint64_t)addrx2[8 + 2 * i]; - } - for (int i = 0; i < SPX_N / 8; i++) { - uint64_t x = load64(ctx->sk_seed + 8 * i); - state[2 * (SPX_N / 8 + i + 4)] = x; - state[2 * (SPX_N / 8 + i + 4) + 1] = x; - } - - /* SHAKE domain separator and padding. */ - state[2 * (SPX_N / 4 + 4)] = 0x1f; - state[2 * (SPX_N / 4 + 4) + 1] = 0x1f; - - state[2 * 16] = 0x80ULL << 56; - state[2 * 16 + 1] = 0x80ULL << 56; - - f1600x2(state); - - for (int i = 0; i < SPX_N / 8; i++) { - store64(out0 + 8 * i, state[2 * i]); - store64(out1 + 8 * i, state[2 * i + 1]); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/hashx2.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/hashx2.h deleted file mode 100644 index 99b8873a9b..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/hashx2.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef SPX_HASHX2_H -#define SPX_HASHX2_H - -#include "context.h" -#include "params.h" -#include - -#define prf_addrx2 SPX_NAMESPACE(prf_addrx2) -void prf_addrx2(unsigned char *out0, - unsigned char *out1, - const spx_ctx *ctx, - const uint32_t addrx2[2 * 8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/merkle.c b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/merkle.c deleted file mode 100644 index c94ee23939..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/merkle.c +++ /dev/null @@ -1,64 +0,0 @@ -#include -#include - -#include "merkle.h" - -#include "address.h" -#include "params.h" -#include "utils.h" -#include "utilsx2.h" -#include "wots.h" -#include "wotsx2.h" - -/* - * This generates a Merkle signature (WOTS signature followed by the Merkle - * authentication path). - */ -void merkle_sign(uint8_t *sig, unsigned char *root, - const spx_ctx *ctx, - uint32_t wots_addr[8], uint32_t tree_addr[8], - uint32_t idx_leaf) { - unsigned char *auth_path = sig + SPX_WOTS_BYTES; - uint32_t tree_addrx2[2 * 8] = { 0 }; - int j; - struct leaf_info_x2 info = { 0 }; - unsigned steps[ SPX_WOTS_LEN ]; - - info.wots_sig = sig; - chain_lengths(steps, root); - info.wots_steps = steps; - - for (j = 0; j < 2; j++) { - set_type(&tree_addrx2[8 * j], SPX_ADDR_TYPE_HASHTREE); - set_type(&info.leaf_addr[8 * j], SPX_ADDR_TYPE_WOTS); - set_type(&info.pk_addr[8 * j], SPX_ADDR_TYPE_WOTSPK); - copy_subtree_addr(&tree_addrx2[8 * j], tree_addr); - copy_subtree_addr(&info.leaf_addr[8 * j], wots_addr); - copy_subtree_addr(&info.pk_addr[8 * j], wots_addr); - } - - info.wots_sign_leaf = idx_leaf; - - treehashx2(root, auth_path, ctx, - idx_leaf, 0, - SPX_TREE_HEIGHT, - wots_gen_leafx2, - tree_addrx2, &info); -} - -/* Compute root node of the top-most subtree. */ -void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { - /* We do not need the auth path in key generation, but it simplifies the - code to have just one treehash routine that computes both root and path - in one function. */ - unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; - uint32_t top_tree_addr[8] = {0}; - uint32_t wots_addr[8] = {0}; - - set_layer_addr(top_tree_addr, SPX_D - 1); - set_layer_addr(wots_addr, SPX_D - 1); - - merkle_sign(auth_path, root, ctx, - wots_addr, top_tree_addr, - ~0 /* ~0 means "don't bother generating an auth path */ ); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/merkle.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/merkle.h deleted file mode 100644 index 769cf2e970..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/merkle.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef MERKLE_H_ -#define MERKLE_H_ - -#include - -#include "context.h" -#include "params.h" - -/* Generate a Merkle signature (WOTS signature followed by the Merkle */ -/* authentication path) */ -#define merkle_sign SPX_NAMESPACE(merkle_sign) -void merkle_sign(uint8_t *sig, unsigned char *root, - const spx_ctx *ctx, - uint32_t wots_addr[8], uint32_t tree_addr[8], - uint32_t idx_leaf); - -/* Compute the root node of the top-most subtree. */ -#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) -void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); - -#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/nistapi.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/nistapi.h deleted file mode 100644 index 3cb71afad4..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/nistapi.h +++ /dev/null @@ -1,87 +0,0 @@ -#ifndef SPX_API_H -#define SPX_API_H - -#include -#include - -#include "params.h" - -#define CRYPTO_ALGNAME "SPHINCS+" - -#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES -#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES -#define CRYPTO_BYTES SPX_BYTES -#define CRYPTO_SEEDBYTES (3*SPX_N) - -/* - * Returns the length of a secret key, in bytes - */ -#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) -size_t crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) -size_t crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) -size_t crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) -size_t crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) -int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) -int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) -int crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) -int crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -#define crypto_sign SPX_NAMESPACE(crypto_sign) -int crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) -int crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/params.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/params.h deleted file mode 100644 index 8a7a4affa7..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/params.h +++ /dev/null @@ -1,56 +0,0 @@ -#ifndef SPX_PARAMS_H -#define SPX_PARAMS_H - -#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSSHAKE128FROBUST_AARCH64_##s - -/* Hash output length in bytes. */ -#define SPX_N 16 -/* Height of the hypertree. */ -#define SPX_FULL_HEIGHT 66 -/* Number of subtree layer. */ -#define SPX_D 22 -/* FORS tree dimensions. */ -#define SPX_FORS_HEIGHT 6 -#define SPX_FORS_TREES 33 -/* Winternitz parameter, */ -#define SPX_WOTS_W 16 - -/* The hash function is defined by linking a different hash.c file, as opposed - to setting a #define constant. */ - -/* For clarity */ -#define SPX_ADDR_BYTES 32 - -/* WOTS parameters. */ -#define SPX_WOTS_LOGW 4 - -#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) - -/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#define SPX_WOTS_LEN2 3 - -#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) -#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) -#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES - -/* Subtree size. */ -#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) - -//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT -// #error SPX_D should always divide SPX_FULL_HEIGHT -//#endif - -/* FORS parameters. */ -#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) -#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) -#define SPX_FORS_PK_BYTES SPX_N - -/* Resulting SPX sizes. */ -#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ - SPX_FULL_HEIGHT * SPX_N) -#define SPX_PK_BYTES (2 * SPX_N) -#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) - -#include "shake_offsets.h" - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/shake_offsets.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/shake_offsets.h deleted file mode 100644 index 6b28d95d91..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/shake_offsets.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef SHAKE_OFFSETS_H_ -#define SHAKE_OFFSETS_H_ - -/* - * Offsets of various fields in the address structure when we use SHAKE as - * the Sphincs+ hash function - */ - -#define SPX_OFFSET_LAYER 3 /* The byte used to specify the Merkle tree layer */ -#define SPX_OFFSET_TREE 8 /* The start of the 8 byte field used to specify the tree */ -#define SPX_OFFSET_TYPE 19 /* The byte used to specify the hash type (reason) */ -#define SPX_OFFSET_KP_ADDR2 22 /* The high byte used to specify the key pair (which one-time signature) */ -#define SPX_OFFSET_KP_ADDR1 23 /* The low byte used to specify the key pair */ -#define SPX_OFFSET_CHAIN_ADDR 27 /* The byte used to specify the chain address (which Winternitz chain) */ -#define SPX_OFFSET_HASH_ADDR 31 /* The byte used to specify the hash address (where in the Winternitz chain) */ -#define SPX_OFFSET_TREE_HGT 27 /* The byte used to specify the height of this node in the FORS or Merkle tree */ -#define SPX_OFFSET_TREE_INDEX 28 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ - -#define SPX_SHAKE 1 - -#endif /* SHAKE_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/sign.c b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/sign.c deleted file mode 100644 index 9d0c7d1b22..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/sign.c +++ /dev/null @@ -1,286 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "context.h" -#include "fors.h" -#include "hash.h" -#include "merkle.h" -#include "nistapi.h" -#include "params.h" -#include "randombytes.h" -#include "thash.h" -#include "utils.h" -#include "wots.h" - -/* - * Returns the length of a secret key, in bytes - */ -size_t crypto_sign_secretkeybytes(void) { - return CRYPTO_SECRETKEYBYTES; -} - -/* - * Returns the length of a public key, in bytes - */ -size_t crypto_sign_publickeybytes(void) { - return CRYPTO_PUBLICKEYBYTES; -} - -/* - * Returns the length of a signature, in bytes - */ -size_t crypto_sign_bytes(void) { - return CRYPTO_BYTES; -} - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t crypto_sign_seedbytes(void) { - return CRYPTO_SEEDBYTES; -} - -/* - * Generates an SPX key pair given a seed of length - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed) { - spx_ctx ctx; - - /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ - memcpy(sk, seed, CRYPTO_SEEDBYTES); - - memcpy(pk, sk + 2 * SPX_N, SPX_N); - - memcpy(ctx.pub_seed, pk, SPX_N); - memcpy(ctx.sk_seed, sk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - /* Compute root node of the top-most subtree. */ - merkle_gen_root(sk + 3 * SPX_N, &ctx); - - // cleanup - free_hash_function(&ctx); - - memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); - - return 0; -} - -/* - * Generates an SPX key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { - uint8_t seed[CRYPTO_SEEDBYTES]; - randombytes(seed, CRYPTO_SEEDBYTES); - crypto_sign_seed_keypair(pk, sk, seed); - - return 0; -} - -/** - * Returns an array containing a detached signature. - */ -int crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - spx_ctx ctx; - - const uint8_t *sk_prf = sk + SPX_N; - const uint8_t *pk = sk + 2 * SPX_N; - - uint8_t optrand[SPX_N]; - uint8_t mhash[SPX_FORS_MSG_BYTES]; - uint8_t root[SPX_N]; - uint32_t i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - - memcpy(ctx.sk_seed, sk, SPX_N); - memcpy(ctx.pub_seed, pk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - set_type(wots_addr, SPX_ADDR_TYPE_WOTS); - set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); - - /* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ - randombytes(optrand, SPX_N); - /* Compute the digest randomization value. */ - gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); - - /* Derive the message digest and leaf index from R, PK and M. */ - hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); - sig += SPX_N; - - set_tree_addr(wots_addr, tree); - set_keypair_addr(wots_addr, idx_leaf); - - /* Sign the message hash using FORS. */ - fors_sign(sig, root, mhash, &ctx, wots_addr); - sig += SPX_FORS_BYTES; - - for (i = 0; i < SPX_D; i++) { - set_layer_addr(tree_addr, i); - set_tree_addr(tree_addr, tree); - - copy_subtree_addr(wots_addr, tree_addr); - set_keypair_addr(wots_addr, idx_leaf); - - merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); - sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); - tree = tree >> SPX_TREE_HEIGHT; - } - - free_hash_function(&ctx); - - *siglen = SPX_BYTES; - - return 0; -} - -/** - * Verifies a detached signature and message under a given public key. - */ -int crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk) { - spx_ctx ctx; - const uint8_t *pub_root = pk + SPX_N; - uint8_t mhash[SPX_FORS_MSG_BYTES]; - uint8_t wots_pk[SPX_WOTS_BYTES]; - uint8_t root[SPX_N]; - uint8_t leaf[SPX_N]; - unsigned int i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - if (siglen != SPX_BYTES) { - return -1; - } - - memcpy(ctx.pub_seed, pk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - set_type(wots_addr, SPX_ADDR_TYPE_WOTS); - set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); - set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); - - /* Derive the message digest and leaf index from R || PK || M. */ - /* The additional SPX_N is a result of the hash domain separator. */ - hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); - sig += SPX_N; - - /* Layer correctly defaults to 0, so no need to set_layer_addr */ - set_tree_addr(wots_addr, tree); - set_keypair_addr(wots_addr, idx_leaf); - - fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); - sig += SPX_FORS_BYTES; - - /* For each subtree.. */ - for (i = 0; i < SPX_D; i++) { - set_layer_addr(tree_addr, i); - set_tree_addr(tree_addr, tree); - - copy_subtree_addr(wots_addr, tree_addr); - set_keypair_addr(wots_addr, idx_leaf); - - copy_keypair_addr(wots_pk_addr, wots_addr); - - /* The WOTS public key is only correct if the signature was correct. */ - /* Initially, root is the FORS pk, but on subsequent iterations it is - the root of the subtree below the currently processed subtree. */ - wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); - sig += SPX_WOTS_BYTES; - - /* Compute the leaf node using the WOTS public key. */ - thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); - - /* Compute the root node of this subtree. */ - compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, - &ctx, tree_addr); - sig += SPX_TREE_HEIGHT * SPX_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); - tree = tree >> SPX_TREE_HEIGHT; - } - - // cleanup - free_hash_function(&ctx); - - /* Check if the root node equals the root node in the public key. */ - if (memcmp(root, pub_root, SPX_N) != 0) { - return -1; - } - - return 0; -} - - -/** - * Returns an array containing the signature followed by the message. - */ -int crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk) { - size_t siglen; - - crypto_sign_signature(sm, &siglen, m, mlen, sk); - - memmove(sm + SPX_BYTES, m, mlen); - *smlen = siglen + mlen; - - return 0; -} - -/** - * Verifies a given signature-message pair under a given public key. - */ -int crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk) { - /* The API caller does not necessarily know what size a signature should be - but SPHINCS+ signatures are always exactly SPX_BYTES. */ - if (smlen < SPX_BYTES) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - *mlen = smlen - SPX_BYTES; - - if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - /* If verification was successful, move the message to the right place. */ - memmove(m, sm + SPX_BYTES, *mlen); - - return 0; -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/thash.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/thash.h deleted file mode 100644 index 8687ccfb4d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/thash.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef SPX_THASH_H -#define SPX_THASH_H - -#include "context.h" -#include "params.h" - -#include - -#define thash SPX_NAMESPACE(thash) -void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/thash_shake_robustx2.c b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/thash_shake_robustx2.c deleted file mode 100644 index 454fc0f4e2..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/thash_shake_robustx2.c +++ /dev/null @@ -1,112 +0,0 @@ -#include -#include - -#include "thash.h" -#include "thashx2.h" - -#include "address.h" -#include "params.h" -#include "utils.h" - -#include "f1600x2.h" -#include "fips202x2.h" - - -void thash(unsigned char *out, - const unsigned char *in, - unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]) { - uint32_t addrx2 [2 * 8] = { - addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], addr[6], addr[7], - addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], addr[6], addr[7] - }; - thashx2(out, out, in, in, inblocks, ctx, addrx2); -} - -/** - * 2-way parallel version of thash; takes 2x as much input and output - */ -void thashx2(unsigned char *out0, - unsigned char *out1, - const unsigned char *in0, - const unsigned char *in1, - unsigned int inblocks, - const spx_ctx *ctx, uint32_t addrx2[2 * 8]) { - if (inblocks == 1 || inblocks == 2) { - /* As we write and read only a few quadwords, it is more efficient to - * build and extract from the twoway SHAKE256 state by hand. */ - uint64_t state[50] = {0}; - uint64_t state2[50]; - - for (int i = 0; i < SPX_N / 8; i++) { - uint64_t x = load64(ctx->pub_seed + 8 * i); - state[2 * i] = x; - state[2 * i + 1] = x; - } - for (int i = 0; i < 4; i++) { - state[2 * (SPX_N / 8 + i)] = (((uint64_t)addrx2[1 + 2 * i]) << 32) - | (uint64_t)addrx2[2 * i]; - state[2 * (SPX_N / 8 + i) + 1] = (((uint64_t)addrx2[8 + 1 + 2 * i]) << 32) - | (uint64_t)addrx2[8 + 2 * i]; - } - - /* Domain separator and padding. */ - state[2 * 16] = 0x80ULL << 56; - state[2 * 16 + 1] = 0x80ULL << 56; - - state[2 * ((SPX_N / 8) + 4)] ^= 0x1f; - state[2 * ((SPX_N / 8) + 4) + 1] ^= 0x1f; - - /* We will permutate state2 with f1600x2 to compute the bitmask, - * but first we'll copy it to state2 which will be used to compute - * the final output, as its input is almost identical. */ - memcpy(state2, state, 400); - - f1600x2(state); - - /* By copying from state, state2 already contains the pub_seed - * and address. We just need to copy in the input blocks xorred with - * the bitmask we just computed. */ - for (unsigned int i = 0; i < (SPX_N / 8) * inblocks; i++) { - state2[2 * (SPX_N / 8 + 4 + i)] = state[2 * i] ^ load64(in0 + 8 * i); - state2[2 * (SPX_N / 8 + 4 + i) + 1] = state[2 * i + 1] ^ load64(in1 + 8 * i); - } - - /* Domain separator and start of padding. Note that the quadwords - * around are already zeroed for state from which we copied. - * We do a XOR instead of a set as this might be the 16th quadword - * when N=32 and inblocks=2, which already contains the end - * of the padding. */ - state2[2 * ((SPX_N / 8) * (1 + inblocks) + 4)] ^= 0x1f; - state2[2 * ((SPX_N / 8) * (1 + inblocks) + 4) + 1] ^= 0x1f; - - f1600x2(state2); - - for (int i = 0; i < SPX_N / 8; i++) { - store64(out0 + 8 * i, state2[2 * i]); - store64(out1 + 8 * i, state2[2 * i + 1]); - } - } else { - PQCLEAN_VLA(unsigned char, buf0, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); - PQCLEAN_VLA(unsigned char, buf1, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); - PQCLEAN_VLA(unsigned char, bitmask0, inblocks * SPX_N); - PQCLEAN_VLA(unsigned char, bitmask1, inblocks * SPX_N); - unsigned int i; - - memcpy(buf0, ctx->pub_seed, SPX_N); - memcpy(buf1, ctx->pub_seed, SPX_N); - memcpy(buf0 + SPX_N, addrx2 + 0 * 8, SPX_ADDR_BYTES); - memcpy(buf1 + SPX_N, addrx2 + 1 * 8, SPX_ADDR_BYTES); - - shake256x2(bitmask0, bitmask1, inblocks * SPX_N, - buf0, buf1, SPX_N + SPX_ADDR_BYTES); - - for (i = 0; i < inblocks * SPX_N; i++) { - buf0[SPX_N + SPX_ADDR_BYTES + i] = in0[i] ^ bitmask0[i]; - buf1[SPX_N + SPX_ADDR_BYTES + i] = in1[i] ^ bitmask1[i]; - } - - shake256x2(out0, out1, SPX_N, - buf0, buf1, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/thashx2.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/thashx2.h deleted file mode 100644 index 040375e618..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/thashx2.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef SPX_THASHX2_H -#define SPX_THASHX2_H - -#include "context.h" -#include "params.h" -#include - -#define thashx2 SPX_NAMESPACE(thashx2) -void thashx2(unsigned char *out0, - unsigned char *out1, - const unsigned char *in0, - const unsigned char *in1, - unsigned int inblocks, - const spx_ctx *ctx, uint32_t addrx2[2 * 8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/utils.c b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/utils.c deleted file mode 100644 index 177b541fb9..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/utils.c +++ /dev/null @@ -1,148 +0,0 @@ -#include - -#include "utils.h" - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "thash.h" - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void ull_to_bytes(unsigned char *out, unsigned int outlen, - unsigned long long in) { - int i; - - /* Iterate over out in decreasing order, for big-endianness. */ - for (i = (signed int)outlen - 1; i >= 0; i--) { - out[i] = in & 0xff; - in = in >> 8; - } -} - -void u32_to_bytes(unsigned char *out, uint32_t in) { - out[0] = (unsigned char)(in >> 24); - out[1] = (unsigned char)(in >> 16); - out[2] = (unsigned char)(in >> 8); - out[3] = (unsigned char)in; -} - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { - unsigned long long retval = 0; - unsigned int i; - - for (i = 0; i < inlen; i++) { - retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); - } - return retval; -} - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void compute_root(unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const spx_ctx *ctx, uint32_t addr[8]) { - uint32_t i; - unsigned char buffer[2 * SPX_N]; - - /* If leaf_idx is odd (last bit = 1), current path element is a right child - and auth_path has to go left. Otherwise it is the other way around. */ - if (leaf_idx & 1) { - memcpy(buffer + SPX_N, leaf, SPX_N); - memcpy(buffer, auth_path, SPX_N); - } else { - memcpy(buffer, leaf, SPX_N); - memcpy(buffer + SPX_N, auth_path, SPX_N); - } - auth_path += SPX_N; - - for (i = 0; i < tree_height - 1; i++) { - leaf_idx >>= 1; - idx_offset >>= 1; - /* Set the address of the node we're creating. */ - set_tree_height(addr, i + 1); - set_tree_index(addr, leaf_idx + idx_offset); - - /* Pick the right or left neighbor, depending on parity of the node. */ - if (leaf_idx & 1) { - thash(buffer + SPX_N, buffer, 2, ctx, addr); - memcpy(buffer, auth_path, SPX_N); - } else { - thash(buffer, buffer, 2, ctx, addr); - memcpy(buffer + SPX_N, auth_path, SPX_N); - } - auth_path += SPX_N; - } - - /* The last iteration is exceptional; we do not copy an auth_path node. */ - leaf_idx >>= 1; - idx_offset >>= 1; - set_tree_height(addr, tree_height); - set_tree_index(addr, leaf_idx + idx_offset); - thash(root, buffer, 2, ctx, addr); -} - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const spx_ctx * /* ctx */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), - uint32_t tree_addr[8]) { - PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); - PQCLEAN_VLA(unsigned int, heights, tree_height + 1); - unsigned int offset = 0; - uint32_t idx; - uint32_t tree_idx; - - for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { - /* Add the next leaf node to the stack. */ - gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); - offset++; - heights[offset - 1] = 0; - - /* If this is a node we need for the auth path.. */ - if ((leaf_idx ^ 0x1) == idx) { - memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); - } - - /* While the top-most nodes are of equal height.. */ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { - /* Compute index of the new node, in the next layer. */ - tree_idx = (idx >> (heights[offset - 1] + 1)); - - /* Set the address of the node we're creating. */ - set_tree_height(tree_addr, heights[offset - 1] + 1); - set_tree_index(tree_addr, - tree_idx + (idx_offset >> (heights[offset - 1] + 1))); - /* Hash the top-most nodes from the stack together. */ - thash(stack + (offset - 2)*SPX_N, - stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); - offset--; - /* Note that the top-most node is now one layer higher. */ - heights[offset - 1]++; - - /* If this is a node we need for the auth path.. */ - if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_path + heights[offset - 1]*SPX_N, - stack + (offset - 1)*SPX_N, SPX_N); - } - } - } - memcpy(root, stack, SPX_N); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/utils.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/utils.h deleted file mode 100644 index 64f5d5a53a..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/utils.h +++ /dev/null @@ -1,58 +0,0 @@ -#ifndef SPX_UTILS_H -#define SPX_UTILS_H - -#include - -#include "compat.h" -#include "context.h" -#include "params.h" - - -/* To support MSVC use alloca() instead of VLAs. See #20. */ - - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) -void ull_to_bytes(unsigned char *out, unsigned int outlen, - unsigned long long in); -#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) -void u32_to_bytes(unsigned char *out, uint32_t in); - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) -unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -#define compute_root SPX_NAMESPACE(compute_root) -void compute_root(unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const spx_ctx *ctx, uint32_t addr[8]); - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -#define treehash SPX_NAMESPACE(treehash) -void treehash(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const spx_ctx *ctx /* ctx */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), - uint32_t tree_addr[8]); - - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/utilsx2.c b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/utilsx2.c deleted file mode 100644 index 8736474e4f..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/utilsx2.c +++ /dev/null @@ -1,130 +0,0 @@ -#include - -#include "utilsx2.h" - -#include "address.h" -#include "params.h" -#include "thashx2.h" -#include "utils.h" - -/* - * Generate the entire Merkle tree, computing the authentication path for leaf_idx, - * and the resulting root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) - * - * This expects tree_addrx2 to be initialized to 2 parallel addr structures for - * the Merkle tree nodes - * - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - * - * This works by using the standard Merkle tree building algorithm, except - * that each 'node' tracked is actually 2 consecutive nodes in the real tree. - * When we combine two logical nodes AB and WX, we perform the H - * operation on adjacent real nodes, forming the parent logical node - * (AB)(WX) - * - * When we get to the top level of the real tree (where there is only - * one logical node), we continue this operation one more time; the right - * most real node will by the actual root (and the other node will be - * garbage). We follow the same thashx2 logic so that the 'extract - * authentication path components' part of the loop is still executed (and - * to simplify the code somewhat) - */ -void treehashx2(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, - uint32_t tree_height, - void (*gen_leafx2)( - unsigned char * /* Where to write the leaves */, - const spx_ctx *, - uint32_t idx, void *info), - uint32_t tree_addrx2[2 * 8], - void *info) { - /* This is where we keep the intermediate nodes */ - unsigned char stackx2[tree_height * 2 * SPX_N]; - uint32_t left_adj = 0, prev_left_adj = 0; /* When we're doing the top */ - /* level, the left-most part of the tree isn't at the beginning */ - /* of current[]. These give the offset of the actual start */ - - uint32_t idx; - uint32_t max_idx = (1 << (tree_height - 1)) - 1; - for (idx = 0;; idx++) { - unsigned char current[2 * SPX_N]; /* Current logical node */ - gen_leafx2( current, ctx, 2 * idx + idx_offset, - info ); - - /* Now combine the freshly generated right node with previously */ - /* generated left ones */ - uint32_t internal_idx_offset = idx_offset; - uint32_t internal_idx = idx; - uint32_t internal_leaf = leaf_idx; - uint32_t h; /* The height we are in the Merkle tree */ - for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { - - /* Special processing if we're at the top of the tree */ - if (h >= tree_height - 1) { - if (h == tree_height) { - /* We hit the root; return it */ - memcpy( root, ¤t[1 * SPX_N], SPX_N ); - return; - } - /* The tree indexing logic is a bit off in this case */ - /* Adjust it so that the left-most node of the part of */ - /* the tree that we're processing has index 0 */ - prev_left_adj = left_adj; - left_adj = 2 - (1 << (tree_height - h - 1)); - } - - /* Check if we hit the top of the tree */ - if (h == tree_height) { - /* We hit the root; return it */ - memcpy( root, ¤t[1 * SPX_N], SPX_N ); - return; - } - - /* - * Check if one of the nodes we have is a part of the - * authentication path; if it is, write it out - */ - if ((((internal_idx << 1) ^ internal_leaf) & ~0x1) == 0) { - memcpy( &auth_path[ h * SPX_N ], - ¤t[(((internal_leaf & 1) ^ 1) + prev_left_adj) * SPX_N], - SPX_N ); - } - - /* - * Check if we're at a left child; if so, stop going up the stack - * Exception: if we've reached the end of the tree, keep on going - * (so we combine the last 2 nodes into the one root node in two - * more iterations) - */ - if ((internal_idx & 1) == 0 && idx < max_idx) { - break; - } - - /* Ok, we're at a right node (or doing the top 3 levels) */ - /* Now combine the left and right logical nodes together */ - - /* Set the address of the node we're creating. */ - int j; - internal_idx_offset >>= 1; - for (j = 0; j < 2; j++) { - set_tree_height(tree_addrx2 + j * 8, h + 1); - set_tree_index(tree_addrx2 + j * 8, - (2 / 2) * (internal_idx & ~1) + j - left_adj + internal_idx_offset ); - } - unsigned char *left = &stackx2[h * 2 * SPX_N]; - thashx2( ¤t[0 * SPX_N], - ¤t[1 * SPX_N], - &left [0 * SPX_N], - ¤t[0 * SPX_N], - 2, ctx, tree_addrx2); - } - - /* We've hit a left child; save the current for when we get the */ - /* corresponding right right */ - memcpy( &stackx2[h * 2 * SPX_N], current, 2 * SPX_N); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/utilsx2.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/utilsx2.h deleted file mode 100644 index e09faddc43..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/utilsx2.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef SPX_UTILSX2_H -#define SPX_UTILSX2_H - -#include - -#include "context.h" -#include "params.h" - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - * - * This implementation uses SIMD to compute internal nodes 2 at a time (in - * parallel) - */ -#define treehashx2 SPX_NAMESPACE(treehashx2) -void treehashx2(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leafx2)( - unsigned char * /* Where to write the leaves */, - const spx_ctx * /* ctx */, - uint32_t addr_idx, void *info), - uint32_t tree_addrx2[2 * 8], void *info); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/wots.c b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/wots.c deleted file mode 100644 index 3babe45e95..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/wots.c +++ /dev/null @@ -1,259 +0,0 @@ -#include -#include - -#include "wots.h" -#include "wotsx2.h" - -#include "address.h" -#include "hash.h" -#include "hashx2.h" -#include "params.h" -#include "thashx2.h" -#include "utils.h" -#include "utilsx2.h" - -// TODO clarify address expectations, and make them more uniform. -// TODO i.e. do we expect types to be set already? -// TODO and do we expect modifications or copies? - -/** - * Computes up the chains - */ -static void gen_chains( - unsigned char *out, - const unsigned char *in, - unsigned int start[SPX_WOTS_LEN], - const unsigned int steps[SPX_WOTS_LEN], - const spx_ctx *ctx, - uint32_t addr[8]) { - uint32_t i, j, k, idx, watching; - int done; - unsigned char empty[SPX_N]; - unsigned char *bufs[4]; - uint32_t addrs[8 * 2]; - - int l; - uint16_t counts[SPX_WOTS_W] = { 0 }; - uint16_t idxs[SPX_WOTS_LEN]; - uint16_t total, newTotal; - - /* set addrs = {addr, addr} */ - for (j = 0; j < 2; j++) { - memcpy(addrs + j * 8, addr, sizeof(uint32_t) * 8); - } - - /* Initialize out with the value at position 'start'. */ - memcpy(out, in, SPX_WOTS_LEN * SPX_N); - - /* Sort the chains in reverse order by steps using counting sort. */ - for (i = 0; i < SPX_WOTS_LEN; i++) { - counts[steps[i]]++; - } - total = 0; - for (l = SPX_WOTS_W - 1; l >= 0; l--) { - newTotal = counts[l] + total; - counts[l] = total; - total = newTotal; - } - for (i = 0; i < SPX_WOTS_LEN; i++) { - idxs[counts[steps[i]]] = i; - counts[steps[i]]++; - } - - /* We got our work cut out for us: do it! */ - for (i = 0; i < SPX_WOTS_LEN; i += 2) { - for (j = 0; j < 2 && i + j < SPX_WOTS_LEN; j++) { - idx = idxs[i + j]; - set_chain_addr(addrs + j * 8, idx); - bufs[j] = out + SPX_N * idx; - } - - /* As the chains are sorted in reverse order, we know that the first - * chain is the longest and the last one is the shortest. We keep - * an eye on whether the last chain is done and then on the one before, - * et cetera. */ - watching = 1; - done = 0; - while (i + watching >= SPX_WOTS_LEN) { - bufs[watching] = &empty[0]; - watching--; - } - - for (k = 0;; k++) { - while (k == steps[idxs[i + watching]]) { - bufs[watching] = &empty[0]; - if (watching == 0) { - done = 1; - break; - } - watching--; - } - if (done) { - break; - } - for (j = 0; j < watching + 1; j++) { - set_hash_addr(addrs + j * 8, k + start[idxs[i + j]]); - } - - thashx2(bufs[0], bufs[1], - bufs[0], bufs[1], 1, ctx, addrs); - } - } -} - -/** - * base_w algorithm as described in draft. - * Interprets an array of bytes as integers in base w. - * This only works when log_w is a divisor of 8. - */ -static void base_w(unsigned int *output, const int out_len, - const unsigned char *input) { - int in = 0; - int out = 0; - unsigned char total = 0; - int bits = 0; - int consumed; - - for (consumed = 0; consumed < out_len; consumed++) { - if (bits == 0) { - total = input[in]; - in++; - bits += 8; - } - bits -= SPX_WOTS_LOGW; - output[out] = (total >> bits) & (SPX_WOTS_W - 1); - out++; - } -} - -/* Computes the WOTS+ checksum over a message (in base_w). */ -static void wots_checksum(unsigned int *csum_base_w, - const unsigned int *msg_base_w) { - unsigned int csum = 0; - unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; - unsigned int i; - - /* Compute checksum. */ - for (i = 0; i < SPX_WOTS_LEN1; i++) { - csum += SPX_WOTS_W - 1 - msg_base_w[i]; - } - - /* Convert checksum to base_w. */ - /* Make sure expected empty zero bits are the least significant bits. */ - csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); - ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); - base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); -} - -/* Takes a message and derives the matching chain lengths. */ -void chain_lengths(unsigned int *lengths, const unsigned char *msg) { - base_w(lengths, SPX_WOTS_LEN1, msg); - wots_checksum(lengths + SPX_WOTS_LEN1, lengths); -} - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const spx_ctx *ctx, uint32_t addr[8]) { - unsigned int steps[SPX_WOTS_LEN]; - unsigned int start[SPX_WOTS_LEN]; - uint32_t i; - - chain_lengths(start, msg); - - for (i = 0; i < SPX_WOTS_LEN; i++) { - steps[i] = SPX_WOTS_W - 1 - start[i]; - } - - gen_chains(pk, sig, start, steps, ctx, addr); -} - -/* - * This generates 2 sequential WOTS public keys - * It also generates the WOTS signature if leaf_info indicates - * that we're signing with one of these WOTS keys - */ -void wots_gen_leafx2(unsigned char *dest, - const spx_ctx *ctx, - uint32_t leaf_idx, void *v_info) { - struct leaf_info_x2 *info = v_info; - uint32_t *leaf_addr = info->leaf_addr; - uint32_t *pk_addr = info->pk_addr; - unsigned int i, j, k; - unsigned char pk_buffer[ 2 * SPX_WOTS_BYTES ]; - unsigned wots_offset = SPX_WOTS_BYTES; - unsigned char *buffer; - uint32_t wots_k_mask; - unsigned wots_sign_index; - - if (((leaf_idx ^ info->wots_sign_leaf) & ~1) == 0) { - /* We're traversing the leaf that's signing; generate the WOTS */ - /* signature */ - wots_k_mask = 0; - wots_sign_index = info->wots_sign_leaf & 1; /* Which of of the 2 */ - /* slots do the signatures come from */ - } else { - /* Nope, we're just generating pk's; turn off the signature logic */ - wots_k_mask = ~0; - wots_sign_index = 0; - } - - for (j = 0; j < 2; j++) { - set_keypair_addr( leaf_addr + j * 8, leaf_idx + j ); - set_keypair_addr( pk_addr + j * 8, leaf_idx + j ); - } - - for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { - uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k to */ - /* the step if we're generating a signature, ~0 if we're not */ - - /* Start with the secret seed */ - for (j = 0; j < 2; j++) { - set_chain_addr(leaf_addr + j * 8, i); - set_hash_addr(leaf_addr + j * 8, 0); - set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTSPRF); - } - prf_addrx2(buffer + 0 * wots_offset, - buffer + 1 * wots_offset, - ctx, leaf_addr); - for (j = 0; j < 2; j++) { - set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTS); - } - - /* Iterate down the WOTS chain */ - for (k = 0;; k++) { - /* Check if one of the values we have needs to be saved as a */ - /* part of the WOTS signature */ - if (k == wots_k) { - memcpy( info->wots_sig + i * SPX_N, - buffer + wots_sign_index * wots_offset, SPX_N ); - } - - /* Check if we hit the top of the chain */ - if (k == SPX_WOTS_W - 1) { - break; - } - - /* Iterate one step on all 4 chains */ - for (j = 0; j < 2; j++) { - set_hash_addr(leaf_addr + j * 8, k); - } - thashx2(buffer + 0 * wots_offset, - buffer + 1 * wots_offset, - buffer + 0 * wots_offset, - buffer + 1 * wots_offset, - 1, ctx, leaf_addr); - } - } - - /* Do the final thash to generate the public keys */ - thashx2(dest + 0 * SPX_N, - dest + 1 * SPX_N, - pk_buffer + 0 * wots_offset, - pk_buffer + 1 * wots_offset, - SPX_WOTS_LEN, ctx, pk_addr); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/wots.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/wots.h deleted file mode 100644 index 4e7692eeef..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/wots.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef SPX_WOTS_H -#define SPX_WOTS_H - -#include - -#include "context.h" -#include "params.h" - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) -void wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const spx_ctx *ctx, uint32_t addr[8]); - -/* - * Compute the chain lengths needed for a given message hash - */ -#define chain_lengths SPX_NAMESPACE(chain_lengths) -void chain_lengths(unsigned int *lengths, const unsigned char *msg); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/wotsx2.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/wotsx2.h deleted file mode 100644 index b58bb61f84..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_aarch64/wotsx2.h +++ /dev/null @@ -1,40 +0,0 @@ -#ifndef WOTSX2_H_ -#define WOTSX2_H_ - -#include "params.h" -#include - -/* - * This is here to provide an interface to the internal wots_gen_leafx2 - * routine. While this routine is not referenced in the package outside of - * wots.c, it is called from the stand-alone benchmark code to characterize - * the performance - */ -struct leaf_info_x2 { - unsigned char *wots_sig; - uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ - uint32_t *wots_steps; - uint32_t leaf_addr[2 * 8]; - uint32_t pk_addr[2 * 8]; -}; - -/* Macro to set the leaf_info to something 'benign', that is, it would */ -/* run with the same time as it does during the real signing process */ -/* Used only by the benchmark code */ -#define INITIALIZE_LEAF_INFO_X2(info, addr, step_buffer) { \ - (info).wots_sig = 0; \ - (info).wots_sign_leaf = ~0; \ - (info).wots_steps = step_buffer; \ - int i; \ - for (i=0; i<2; i++) { \ - memcpy( &(info).leaf_addr[8*i], addr, 32 ); \ - memcpy( &(info).pk_addr[8*i], addr, 32 ); \ - } \ - } - -#define wots_gen_leafx2 SPX_NAMESPACE(wots_gen_leafx2) -void wots_gen_leafx2(unsigned char *dest, - const spx_ctx *ctx, - uint32_t leaf_idx, void *v_info); - -#endif /* WOTSX2_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/LICENSE b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/LICENSE deleted file mode 100644 index 670154e353..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/LICENSE +++ /dev/null @@ -1,116 +0,0 @@ -CC0 1.0 Universal - -Statement of Purpose - -The laws of most jurisdictions throughout the world automatically confer -exclusive Copyright and Related Rights (defined below) upon the creator and -subsequent owner(s) (each and all, an "owner") of an original work of -authorship and/or a database (each, a "Work"). - -Certain owners wish to permanently relinquish those rights to a Work for the -purpose of contributing to a commons of creative, cultural and scientific -works ("Commons") that the public can reliably and without fear of later -claims of infringement build upon, modify, incorporate in other works, reuse -and redistribute as freely as possible in any form whatsoever and for any -purposes, including without limitation commercial purposes. These owners may -contribute to the Commons to promote the ideal of a free culture and the -further production of creative, cultural and scientific works, or to gain -reputation or greater distribution for their Work in part through the use and -efforts of others. - -For these and/or other purposes and motivations, and without any expectation -of additional consideration or compensation, the person associating CC0 with a -Work (the "Affirmer"), to the extent that he or she is an owner of Copyright -and Related Rights in the Work, voluntarily elects to apply CC0 to the Work -and publicly distribute the Work under its terms, with knowledge of his or her -Copyright and Related Rights in the Work and the meaning and intended legal -effect of CC0 on those rights. - -1. Copyright and Related Rights. A Work made available under CC0 may be -protected by copyright and related or neighboring rights ("Copyright and -Related Rights"). Copyright and Related Rights include, but are not limited -to, the following: - - i. the right to reproduce, adapt, distribute, perform, display, communicate, - and translate a Work; - - ii. moral rights retained by the original author(s) and/or performer(s); - - iii. publicity and privacy rights pertaining to a person's image or likeness - depicted in a Work; - - iv. rights protecting against unfair competition in regards to a Work, - subject to the limitations in paragraph 4(a), below; - - v. rights protecting the extraction, dissemination, use and reuse of data in - a Work; - - vi. database rights (such as those arising under Directive 96/9/EC of the - European Parliament and of the Council of 11 March 1996 on the legal - protection of databases, and under any national implementation thereof, - including any amended or successor version of such directive); and - - vii. other similar, equivalent or corresponding rights throughout the world - based on applicable law or treaty, and any national implementations thereof. - -2. Waiver. To the greatest extent permitted by, but not in contravention of, -applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and -unconditionally waives, abandons, and surrenders all of Affirmer's Copyright -and Related Rights and associated claims and causes of action, whether now -known or unknown (including existing as well as future claims and causes of -action), in the Work (i) in all territories worldwide, (ii) for the maximum -duration provided by applicable law or treaty (including future time -extensions), (iii) in any current or future medium and for any number of -copies, and (iv) for any purpose whatsoever, including without limitation -commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes -the Waiver for the benefit of each member of the public at large and to the -detriment of Affirmer's heirs and successors, fully intending that such Waiver -shall not be subject to revocation, rescission, cancellation, termination, or -any other legal or equitable action to disrupt the quiet enjoyment of the Work -by the public as contemplated by Affirmer's express Statement of Purpose. - -3. Public License Fallback. Should any part of the Waiver for any reason be -judged legally invalid or ineffective under applicable law, then the Waiver -shall be preserved to the maximum extent permitted taking into account -Affirmer's express Statement of Purpose. In addition, to the extent the Waiver -is so judged Affirmer hereby grants to each affected person a royalty-free, -non transferable, non sublicensable, non exclusive, irrevocable and -unconditional license to exercise Affirmer's Copyright and Related Rights in -the Work (i) in all territories worldwide, (ii) for the maximum duration -provided by applicable law or treaty (including future time extensions), (iii) -in any current or future medium and for any number of copies, and (iv) for any -purpose whatsoever, including without limitation commercial, advertising or -promotional purposes (the "License"). The License shall be deemed effective as -of the date CC0 was applied by Affirmer to the Work. Should any part of the -License for any reason be judged legally invalid or ineffective under -applicable law, such partial invalidity or ineffectiveness shall not -invalidate the remainder of the License, and in such case Affirmer hereby -affirms that he or she will not (i) exercise any of his or her remaining -Copyright and Related Rights in the Work or (ii) assert any associated claims -and causes of action with respect to the Work, in either case contrary to -Affirmer's express Statement of Purpose. - -4. Limitations and Disclaimers. - - a. No trademark or patent rights held by Affirmer are waived, abandoned, - surrendered, licensed or otherwise affected by this document. - - b. Affirmer offers the Work as-is and makes no representations or warranties - of any kind concerning the Work, express, implied, statutory or otherwise, - including without limitation warranties of title, merchantability, fitness - for a particular purpose, non infringement, or the absence of latent or - other defects, accuracy, or the present or absence of errors, whether or not - discoverable, all to the greatest extent permissible under applicable law. - - c. Affirmer disclaims responsibility for clearing rights of other persons - that may apply to the Work or any use thereof, including without limitation - any person's Copyright and Related Rights in the Work. Further, Affirmer - disclaims responsibility for obtaining any necessary consents, permissions - or other rights required for any use of the Work. - - d. Affirmer understands and acknowledges that Creative Commons is not a - party to this document and has no duty or obligation with respect to this - CC0 or use of the Work. - -For more information, please see - diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/address.c b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/address.c deleted file mode 100644 index b956e9cb29..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/address.c +++ /dev/null @@ -1,91 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "utils.h" - -/* - * Specify which level of Merkle tree (the "layer") we're working on - */ -void set_layer_addr(uint32_t addr[8], uint32_t layer) { - ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; -} - -/* - * Specify which Merkle tree within the level (the "tree address") we're working on - */ -void set_tree_addr(uint32_t addr[8], uint64_t tree) { - ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); -} - -/* - * Specify the reason we'll use this address structure for, that is, what - * hash will we compute with it. This is used so that unrelated types of - * hashes don't accidentally get the same address structure. The type will be - * one of the SPX_ADDR_TYPE constants - */ -void set_type(uint32_t addr[8], uint32_t type) { - ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; -} - -/* - * Copy the layer and tree fields of the address structure. This is used - * when we're doing multiple types of hashes within the same Merkle tree - */ -void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { - memcpy( out, in, SPX_OFFSET_TREE + 8 ); -} - -/* These functions are used for OTS addresses. */ - -/* - * Specify which Merkle leaf we're working on; that is, which OTS keypair - * we're talking about. - */ -void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { - ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; -} - -/* - * Copy the layer, tree and keypair fields of the address structure. This is - * used when we're doing multiple things within the same OTS keypair - */ -void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { - memcpy( out, in, SPX_OFFSET_TREE + 8 ); - ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; -} - -/* - * Specify which Merkle chain within the OTS we're working with - * (the chain address) - */ -void set_chain_addr(uint32_t addr[8], uint32_t chain) { - ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; -} - -/* - * Specify where in the Merkle chain we are -* (the hash address) - */ -void set_hash_addr(uint32_t addr[8], uint32_t hash) { - ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; -} - -/* These functions are used for all hash tree addresses (including FORS). */ - -/* - * Specify the height of the node in the Merkle/FORS tree we are in - * (the tree height) - */ -void set_tree_height(uint32_t addr[8], uint32_t tree_height) { - ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; -} - -/* - * Specify the distance from the left edge of the node in the Merkle/FORS tree - * (the tree index) - */ -void set_tree_index(uint32_t addr[8], uint32_t tree_index) { - u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/address.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/address.h deleted file mode 100644 index 24a84eb40c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/address.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef SPX_ADDRESS_H -#define SPX_ADDRESS_H - -#include - -#include "params.h" - -/* The hash types that are passed to set_type */ -#define SPX_ADDR_TYPE_WOTS 0 -#define SPX_ADDR_TYPE_WOTSPK 1 -#define SPX_ADDR_TYPE_HASHTREE 2 -#define SPX_ADDR_TYPE_FORSTREE 3 -#define SPX_ADDR_TYPE_FORSPK 4 -#define SPX_ADDR_TYPE_WOTSPRF 5 -#define SPX_ADDR_TYPE_FORSPRF 6 - -#define set_layer_addr SPX_NAMESPACE(set_layer_addr) -void set_layer_addr(uint32_t addr[8], uint32_t layer); - -#define set_tree_addr SPX_NAMESPACE(set_tree_addr) -void set_tree_addr(uint32_t addr[8], uint64_t tree); - -#define set_type SPX_NAMESPACE(set_type) -void set_type(uint32_t addr[8], uint32_t type); - -/* Copies the layer and tree part of one address into the other */ -#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) -void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for WOTS and FORS addresses. */ - -#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) -void set_keypair_addr(uint32_t addr[8], uint32_t keypair); - -#define set_chain_addr SPX_NAMESPACE(set_chain_addr) -void set_chain_addr(uint32_t addr[8], uint32_t chain); - -#define set_hash_addr SPX_NAMESPACE(set_hash_addr) -void set_hash_addr(uint32_t addr[8], uint32_t hash); - -#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) -void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for all hash tree addresses (including FORS). */ - -#define set_tree_height SPX_NAMESPACE(set_tree_height) -void set_tree_height(uint32_t addr[8], uint32_t tree_height); - -#define set_tree_index SPX_NAMESPACE(set_tree_index) -void set_tree_index(uint32_t addr[8], uint32_t tree_index); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/api.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/api.h deleted file mode 100644 index 5c0a570b8c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/api.h +++ /dev/null @@ -1,77 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE128FROBUST_AVX2_API_H -#define PQCLEAN_SPHINCSSHAKE128FROBUST_AVX2_API_H - -#include -#include - -#define PQCLEAN_SPHINCSSHAKE128FROBUST_AVX2_CRYPTO_ALGNAME "SPHINCS+-shake-128f-robust" - -#define PQCLEAN_SPHINCSSHAKE128FROBUST_AVX2_CRYPTO_SECRETKEYBYTES 64 -#define PQCLEAN_SPHINCSSHAKE128FROBUST_AVX2_CRYPTO_PUBLICKEYBYTES 32 -#define PQCLEAN_SPHINCSSHAKE128FROBUST_AVX2_CRYPTO_BYTES 17088 - -#define PQCLEAN_SPHINCSSHAKE128FROBUST_AVX2_CRYPTO_SEEDBYTES 48 - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE128FROBUST_AVX2_crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE128FROBUST_AVX2_crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE128FROBUST_AVX2_crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE128FROBUST_AVX2_crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHAKE128FROBUST_AVX2_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHAKE128FROBUST_AVX2_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSSHAKE128FROBUST_AVX2_crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE128FROBUST_AVX2_crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, - const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSSHAKE128FROBUST_AVX2_crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE128FROBUST_AVX2_crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk); -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/context.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/context.h deleted file mode 100644 index 6e0a33f3b7..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/context.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef SPX_CONTEXT_H -#define SPX_CONTEXT_H - -#include - -#include "params.h" - -typedef struct { - uint8_t pub_seed[SPX_N]; - uint8_t sk_seed[SPX_N]; -} spx_ctx; - -#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) -void initialize_hash_function(spx_ctx *ctx); - -#define free_hash_function SPX_NAMESPACE(free_hash_function) -void free_hash_function(spx_ctx *ctx); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/context_shake.c b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/context_shake.c deleted file mode 100644 index 9614a103d3..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/context_shake.c +++ /dev/null @@ -1,12 +0,0 @@ -#include "context.h" - -/* For SHAKE256, there is no immediate reason to initialize at the start, - so this function is an empty operation. */ -void initialize_hash_function(spx_ctx *ctx) { - (void)ctx; /* Suppress an 'unused parameter' warning. */ -} - -// in case the hash function api is heap-based. -void free_hash_function(spx_ctx *ctx) { - (void)ctx; -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/fips202x4.c b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/fips202x4.c deleted file mode 100644 index 1e06fef186..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/fips202x4.c +++ /dev/null @@ -1,210 +0,0 @@ -#include -#include -#include - -#include "fips202.h" -#include "fips202x4.h" - -#define NROUNDS 24 -#define ROL(a, offset) (((a) << (offset)) ^ ((a) >> (64-(offset)))) - -static uint64_t load64(const unsigned char *x) { - unsigned long long r = 0, i; - - for (i = 0; i < 8; ++i) { - r |= (unsigned long long)x[i] << 8 * i; - } - return r; -} - -static void store64(uint8_t *x, uint64_t u) { - unsigned int i; - - for (i = 0; i < 8; ++i) { - x[i] = (uint8_t)u; - u >>= 8; - } -} - -/* Use implementation from the Keccak Code Package */ -extern void KeccakP1600times4_PermuteAll_24rounds(__m256i *s); -#define KeccakF1600_StatePermute4x KeccakP1600times4_PermuteAll_24rounds - -static void keccak_absorb4x(__m256i *s, - unsigned int r, - const unsigned char *m0, - const unsigned char *m1, - const unsigned char *m2, - const unsigned char *m3, - unsigned long long int mlen, - unsigned char p) { - unsigned long long i; - unsigned char t0[200]; - unsigned char t1[200]; - unsigned char t2[200]; - unsigned char t3[200]; - - unsigned long long *ss = (unsigned long long *)s; - - - while (mlen >= r) { - for (i = 0; i < r / 8; ++i) { - ss[4 * i + 0] ^= load64(m0 + 8 * i); - ss[4 * i + 1] ^= load64(m1 + 8 * i); - ss[4 * i + 2] ^= load64(m2 + 8 * i); - ss[4 * i + 3] ^= load64(m3 + 8 * i); - } - - KeccakF1600_StatePermute4x(s); - mlen -= r; - m0 += r; - m1 += r; - m2 += r; - m3 += r; - } - - for (i = 0; i < r; ++i) { - t0[i] = 0; - t1[i] = 0; - t2[i] = 0; - t3[i] = 0; - } - for (i = 0; i < mlen; ++i) { - t0[i] = m0[i]; - t1[i] = m1[i]; - t2[i] = m2[i]; - t3[i] = m3[i]; - } - - t0[i] = p; - t1[i] = p; - t2[i] = p; - t3[i] = p; - - t0[r - 1] |= 128; - t1[r - 1] |= 128; - t2[r - 1] |= 128; - t3[r - 1] |= 128; - - for (i = 0; i < r / 8; ++i) { - ss[4 * i + 0] ^= load64(t0 + 8 * i); - ss[4 * i + 1] ^= load64(t1 + 8 * i); - ss[4 * i + 2] ^= load64(t2 + 8 * i); - ss[4 * i + 3] ^= load64(t3 + 8 * i); - } -} - - -static void keccak_squeezeblocks4x(unsigned char *h0, - unsigned char *h1, - unsigned char *h2, - unsigned char *h3, - unsigned long long int nblocks, - __m256i *s, - unsigned int r) { - unsigned int i; - - unsigned long long *ss = (unsigned long long *)s; - - while (nblocks > 0) { - KeccakF1600_StatePermute4x(s); - for (i = 0; i < (r >> 3); i++) { - store64(h0 + 8 * i, ss[4 * i + 0]); - store64(h1 + 8 * i, ss[4 * i + 1]); - store64(h2 + 8 * i, ss[4 * i + 2]); - store64(h3 + 8 * i, ss[4 * i + 3]); - } - h0 += r; - h1 += r; - h2 += r; - h3 += r; - nblocks--; - } -} - - - -void shake128x4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, unsigned long long outlen, - unsigned char *in0, - unsigned char *in1, - unsigned char *in2, - unsigned char *in3, unsigned long long inlen) { - __m256i s[25]; - unsigned char t0[SHAKE128_RATE]; - unsigned char t1[SHAKE128_RATE]; - unsigned char t2[SHAKE128_RATE]; - unsigned char t3[SHAKE128_RATE]; - unsigned int i; - - /* zero state */ - for (i = 0; i < 25; i++) { - s[i] = _mm256_xor_si256(s[i], s[i]); - } - - /* absorb 4 message of identical length in parallel */ - keccak_absorb4x(s, SHAKE128_RATE, in0, in1, in2, in3, inlen, 0x1F); - - /* Squeeze output */ - keccak_squeezeblocks4x(out0, out1, out2, out3, outlen / SHAKE128_RATE, s, SHAKE128_RATE); - - out0 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; - out1 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; - out2 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; - out3 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; - - if (outlen % SHAKE128_RATE) { - keccak_squeezeblocks4x(t0, t1, t2, t3, 1, s, SHAKE128_RATE); - for (i = 0; i < outlen % SHAKE128_RATE; i++) { - out0[i] = t0[i]; - out1[i] = t1[i]; - out2[i] = t2[i]; - out3[i] = t3[i]; - } - } -} - - -void shake256x4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, unsigned long long outlen, - unsigned char *in0, - unsigned char *in1, - unsigned char *in2, - unsigned char *in3, unsigned long long inlen) { - __m256i s[25]; - unsigned char t0[SHAKE256_RATE]; - unsigned char t1[SHAKE256_RATE]; - unsigned char t2[SHAKE256_RATE]; - unsigned char t3[SHAKE256_RATE]; - unsigned int i; - - /* zero state */ - for (i = 0; i < 25; i++) { - s[i] = _mm256_xor_si256(s[i], s[i]); - } - - /* absorb 4 message of identical length in parallel */ - keccak_absorb4x(s, SHAKE256_RATE, in0, in1, in2, in3, inlen, 0x1F); - - /* Squeeze output */ - keccak_squeezeblocks4x(out0, out1, out2, out3, outlen / SHAKE256_RATE, s, SHAKE256_RATE); - - out0 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; - out1 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; - out2 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; - out3 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; - - if (outlen % SHAKE256_RATE) { - keccak_squeezeblocks4x(t0, t1, t2, t3, 1, s, SHAKE256_RATE); - for (i = 0; i < outlen % SHAKE256_RATE; i++) { - out0[i] = t0[i]; - out1[i] = t1[i]; - out2[i] = t2[i]; - out3[i] = t3[i]; - } - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/fips202x4.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/fips202x4.h deleted file mode 100644 index 2b93c9cd0d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/fips202x4.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef SPX_FIPS202X4_H -#define SPX_FIPS202X4_H - -#include - -#include "params.h" - -#define shake128x4 SPX_NAMESPACE(shake128x4) -void shake128x4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, unsigned long long outlen, - unsigned char *in0, - unsigned char *in1, - unsigned char *in2, - unsigned char *in3, unsigned long long inlen); - -#define shake256x4 SPX_NAMESPACE(shake256x4) -void shake256x4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, unsigned long long outlen, - unsigned char *in0, - unsigned char *in1, - unsigned char *in2, - unsigned char *in3, unsigned long long inlen); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/fors.c b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/fors.c deleted file mode 100644 index f1b0639cfc..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/fors.c +++ /dev/null @@ -1,202 +0,0 @@ -#include -#include -#include - -#include "fors.h" - -#include "address.h" -#include "hash.h" -#include "hashx4.h" -#include "thash.h" -#include "thashx4.h" -#include "utils.h" -#include "utilsx4.h" - -static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, - uint32_t fors_leaf_addr[8]) { - prf_addr(sk, ctx, fors_leaf_addr); -} - -static void fors_gen_skx4(unsigned char *sk0, - unsigned char *sk1, - unsigned char *sk2, - unsigned char *sk3, const spx_ctx *ctx, - uint32_t fors_leaf_addrx4[4 * 8]) { - prf_addrx4(sk0, sk1, sk2, sk3, - ctx, fors_leaf_addrx4); -} - -static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, - const spx_ctx *ctx, - uint32_t fors_leaf_addr[8]) { - thash(leaf, sk, 1, ctx, fors_leaf_addr); -} - -static void fors_sk_to_leafx4(unsigned char *leaf0, - unsigned char *leaf1, - unsigned char *leaf2, - unsigned char *leaf3, - const unsigned char *sk0, - const unsigned char *sk1, - const unsigned char *sk2, - const unsigned char *sk3, - const spx_ctx *ctx, - uint32_t fors_leaf_addrx4[4 * 8]) { - thashx4(leaf0, leaf1, leaf2, leaf3, - sk0, sk1, sk2, sk3, - 1, ctx, fors_leaf_addrx4); -} - -struct fors_gen_leaf_info { - uint32_t leaf_addrx[4 * 8]; -}; - -static void fors_gen_leafx4(unsigned char *leaf, - const spx_ctx *ctx, - uint32_t addr_idx, void *info) { - struct fors_gen_leaf_info *fors_info = info; - uint32_t *fors_leaf_addrx4 = fors_info->leaf_addrx; - unsigned int j; - - /* Only set the parts that the caller doesn't set */ - for (j = 0; j < 4; j++) { - set_tree_index(fors_leaf_addrx4 + j * 8, addr_idx + j); - set_type(fors_leaf_addrx4 + j * 8, SPX_ADDR_TYPE_FORSPRF); - } - - fors_gen_skx4(leaf + 0 * SPX_N, - leaf + 1 * SPX_N, - leaf + 2 * SPX_N, - leaf + 3 * SPX_N, - ctx, fors_leaf_addrx4); - - for (j = 0; j < 4; j++) { - set_type(fors_leaf_addrx4 + j * 8, SPX_ADDR_TYPE_FORSTREE); - } - - fors_sk_to_leafx4(leaf + 0 * SPX_N, - leaf + 1 * SPX_N, - leaf + 2 * SPX_N, - leaf + 3 * SPX_N, - leaf + 0 * SPX_N, - leaf + 1 * SPX_N, - leaf + 2 * SPX_N, - leaf + 3 * SPX_N, - ctx, fors_leaf_addrx4); -} - -/** - * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - * Assumes indices has space for SPX_FORS_TREES integers. - */ -static void message_to_indices(uint32_t *indices, const unsigned char *m) { - unsigned int i, j; - unsigned int offset = 0; - - for (i = 0; i < SPX_FORS_TREES; i++) { - indices[i] = 0; - for (j = 0; j < SPX_FORS_HEIGHT; j++) { - indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); - offset++; - } - } -} - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -void fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]) { - uint32_t indices[SPX_FORS_TREES]; - unsigned char roots[SPX_FORS_TREES * SPX_N]; - uint32_t fors_tree_addr[4 * 8] = {0}; - struct fors_gen_leaf_info fors_info = {0}; - uint32_t *fors_leaf_addr = fors_info.leaf_addrx; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - for (i = 0; i < 4; i++) { - copy_keypair_addr(fors_tree_addr + 8 * i, fors_addr); - set_type(fors_tree_addr + 8 * i, SPX_ADDR_TYPE_FORSTREE); - copy_keypair_addr(fors_leaf_addr + 8 * i, fors_addr); - } - copy_keypair_addr(fors_pk_addr, fors_addr); - set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < SPX_FORS_TREES; i++) { - idx_offset = i * (1 << SPX_FORS_HEIGHT); - - set_tree_height(fors_tree_addr, 0); - set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Include the secret key part that produces the selected leaf node. */ - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); - fors_gen_sk(sig, ctx, fors_tree_addr); - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); - sig += SPX_N; - - /* Compute the authentication path for this leaf node. */ - treehashx4(roots + i * SPX_N, sig, ctx, - indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx4, - fors_tree_addr, &fors_info); - - sig += SPX_N * SPX_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); -} - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -void fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]) { - uint32_t indices[SPX_FORS_TREES]; - unsigned char roots[SPX_FORS_TREES * SPX_N]; - unsigned char leaf[SPX_N]; - uint32_t fors_tree_addr[8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - copy_keypair_addr(fors_tree_addr, fors_addr); - copy_keypair_addr(fors_pk_addr, fors_addr); - - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); - set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < SPX_FORS_TREES; i++) { - idx_offset = i * (1 << SPX_FORS_HEIGHT); - - set_tree_height(fors_tree_addr, 0); - set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Derive the leaf from the included secret key part. */ - fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); - sig += SPX_N; - - /* Derive the corresponding root node of this tree. */ - compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, - sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); - sig += SPX_N * SPX_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/fors.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/fors.h deleted file mode 100644 index 509140a178..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/fors.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef SPX_FORS_H -#define SPX_FORS_H - -#include - -#include "context.h" -#include "params.h" - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -#define fors_sign SPX_NAMESPACE(fors_sign) -void fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]); - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) -void fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/hash.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/hash.h deleted file mode 100644 index f7c87d4c3c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/hash.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef SPX_HASH_H -#define SPX_HASH_H - -#include -#include - -#include "context.h" -#include "params.h" - -#define prf_addr SPX_NAMESPACE(prf_addr) -void prf_addr(unsigned char *out, const spx_ctx *ctx, - const uint32_t addr[8]); - -#define gen_message_random SPX_NAMESPACE(gen_message_random) -void gen_message_random(unsigned char *R, const unsigned char *sk_prf, - const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx); - -#define hash_message SPX_NAMESPACE(hash_message) -void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx); - - - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/hash_shake.c b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/hash_shake.c deleted file mode 100644 index ff5e7ec918..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/hash_shake.c +++ /dev/null @@ -1,83 +0,0 @@ -#include -#include - -#include "hash.h" - -#include "address.h" -#include "fips202.h" -#include "params.h" -#include "utils.h" - -/* - * Computes PRF(pk_seed, sk_seed, addr) - */ -void prf_addr(unsigned char *out, const spx_ctx *ctx, - const uint32_t addr[8]) { - unsigned char buf[2 * SPX_N + SPX_ADDR_BYTES]; - - memcpy(buf, ctx->pub_seed, SPX_N); - memcpy(buf + SPX_N, addr, SPX_ADDR_BYTES); - memcpy(buf + SPX_N + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); - - shake256(out, SPX_N, buf, 2 * SPX_N + SPX_ADDR_BYTES); -} - -/** - * Computes the message-dependent randomness R, using a secret seed and an - * optional randomization value as well as the message. - */ -void gen_message_random(unsigned char *R, const unsigned char *sk_prf, - const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx) { - (void)ctx; - shake256incctx s_inc; - - shake256_inc_init(&s_inc); - shake256_inc_absorb(&s_inc, sk_prf, SPX_N); - shake256_inc_absorb(&s_inc, optrand, SPX_N); - shake256_inc_absorb(&s_inc, m, mlen); - shake256_inc_finalize(&s_inc); - shake256_inc_squeeze(R, SPX_N, &s_inc); - shake256_inc_ctx_release(&s_inc); -} - -/** - * Computes the message hash using R, the public key, and the message. - * Outputs the message digest and the index of the leaf. The index is split in - * the tree index and the leaf index, for convenient copying to an address. - */ -void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx) { - (void)ctx; -#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) -#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) -#define SPX_LEAF_BITS SPX_TREE_HEIGHT -#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) -#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) - - unsigned char buf[SPX_DGST_BYTES]; - unsigned char *bufp = buf; - shake256incctx s_inc; - - shake256_inc_init(&s_inc); - shake256_inc_absorb(&s_inc, R, SPX_N); - shake256_inc_absorb(&s_inc, pk, SPX_PK_BYTES); - shake256_inc_absorb(&s_inc, m, mlen); - shake256_inc_finalize(&s_inc); - shake256_inc_squeeze(buf, SPX_DGST_BYTES, &s_inc); - shake256_inc_ctx_release(&s_inc); - - memcpy(digest, bufp, SPX_FORS_MSG_BYTES); - bufp += SPX_FORS_MSG_BYTES; - - - *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); - *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); - bufp += SPX_TREE_BYTES; - - *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); - *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/hash_shakex4.c b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/hash_shakex4.c deleted file mode 100644 index bbd22eb117..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/hash_shakex4.c +++ /dev/null @@ -1,64 +0,0 @@ -#include -#include - -#include "hashx4.h" - -#include "address.h" -#include "fips202x4.h" -#include "params.h" - -extern void KeccakP1600times4_PermuteAll_24rounds(__m256i *s); - -/* - * 4-way parallel version of prf_addr; takes 4x as much input and output - */ -void prf_addrx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const spx_ctx *ctx, - const uint32_t addrx4[4 * 8]) { - /* As we write and read only a few quadwords, it is more efficient to - * build and extract from the fourway SHAKE256 state by hand. */ - __m256i state[25]; - - for (int i = 0; i < SPX_N / 8; i++) { - state[i] = _mm256_set1_epi64x(((int64_t *)ctx->pub_seed)[i]); - } - for (int i = 0; i < 4; i++) { - state[SPX_N / 8 + i] = _mm256_set_epi32( - (int)addrx4[3 * 8 + 1 + 2 * i], - (int)addrx4[3 * 8 + 2 * i], - (int)addrx4[2 * 8 + 1 + 2 * i], - (int)addrx4[2 * 8 + 2 * i], - (int)addrx4[8 + 1 + 2 * i], - (int)addrx4[8 + 2 * i], - (int)addrx4[1 + 2 * i], - (int)addrx4[2 * i] - ); - } - for (int i = 0; i < SPX_N / 8; i++) { - state[SPX_N / 8 + i + 4] = _mm256_set1_epi64x(((int64_t *)ctx->sk_seed)[i]); - } - - /* SHAKE domain separator and padding. */ - state[SPX_N / 4 + 4] = _mm256_set1_epi64x(0x1f); - for (int i = SPX_N / 4 + 5; i < 16; i++) { - state[i] = _mm256_set1_epi64x(0); - } - // shift unsigned and then cast to avoid UB - state[16] = _mm256_set1_epi64x((long long)(0x80ULL << 56)); - - for (int i = 17; i < 25; i++) { - state[i] = _mm256_set1_epi64x(0); - } - - KeccakP1600times4_PermuteAll_24rounds(&state[0]); - - for (int i = 0; i < SPX_N / 8; i++) { - ((int64_t *)out0)[i] = _mm256_extract_epi64(state[i], 0); - ((int64_t *)out1)[i] = _mm256_extract_epi64(state[i], 1); - ((int64_t *)out2)[i] = _mm256_extract_epi64(state[i], 2); - ((int64_t *)out3)[i] = _mm256_extract_epi64(state[i], 3); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/hashx4.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/hashx4.h deleted file mode 100644 index 3751a0ebd0..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/hashx4.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef SPX_HASHX4_H -#define SPX_HASHX4_H - -#include - -#include "context.h" -#include "params.h" - -#define prf_addrx4 SPX_NAMESPACE(prf_addrx4) -void prf_addrx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const spx_ctx *ctx, - const uint32_t addrx4[4 * 8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/merkle.c b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/merkle.c deleted file mode 100644 index f57811c1ac..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/merkle.c +++ /dev/null @@ -1,64 +0,0 @@ -#include -#include - -#include "merkle.h" - -#include "address.h" -#include "params.h" -#include "utils.h" -#include "utilsx4.h" -#include "wots.h" -#include "wotsx4.h" - -/* - * This generates a Merkle signature (WOTS signature followed by the Merkle - * authentication path). - */ -void merkle_sign(uint8_t *sig, unsigned char *root, - const spx_ctx *ctx, - uint32_t wots_addr[8], uint32_t tree_addr[8], - uint32_t idx_leaf) { - unsigned char *auth_path = sig + SPX_WOTS_BYTES; - uint32_t tree_addrx4[4 * 8] = { 0 }; - int j; - struct leaf_info_x4 info = { 0 }; - unsigned steps[ SPX_WOTS_LEN ]; - - info.wots_sig = sig; - chain_lengths(steps, root); - info.wots_steps = steps; - - for (j = 0; j < 4; j++) { - set_type(&tree_addrx4[8 * j], SPX_ADDR_TYPE_HASHTREE); - set_type(&info.leaf_addr[8 * j], SPX_ADDR_TYPE_WOTS); - set_type(&info.pk_addr[8 * j], SPX_ADDR_TYPE_WOTSPK); - copy_subtree_addr(&tree_addrx4[8 * j], tree_addr); - copy_subtree_addr(&info.leaf_addr[8 * j], wots_addr); - copy_subtree_addr(&info.pk_addr[8 * j], wots_addr); - } - - info.wots_sign_leaf = idx_leaf; - - treehashx4(root, auth_path, ctx, - idx_leaf, 0, - SPX_TREE_HEIGHT, - wots_gen_leafx4, - tree_addrx4, &info); -} - -/* Compute root node of the top-most subtree. */ -void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { - /* We do not need the auth path in key generation, but it simplifies the - code to have just one treehash routine that computes both root and path - in one function. */ - unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; - uint32_t top_tree_addr[8] = {0}; - uint32_t wots_addr[8] = {0}; - - set_layer_addr(top_tree_addr, SPX_D - 1); - set_layer_addr(wots_addr, SPX_D - 1); - - merkle_sign(auth_path, root, ctx, - wots_addr, top_tree_addr, - ~0U /* ~0 means "don't bother generating an auth path */ ); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/merkle.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/merkle.h deleted file mode 100644 index 769cf2e970..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/merkle.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef MERKLE_H_ -#define MERKLE_H_ - -#include - -#include "context.h" -#include "params.h" - -/* Generate a Merkle signature (WOTS signature followed by the Merkle */ -/* authentication path) */ -#define merkle_sign SPX_NAMESPACE(merkle_sign) -void merkle_sign(uint8_t *sig, unsigned char *root, - const spx_ctx *ctx, - uint32_t wots_addr[8], uint32_t tree_addr[8], - uint32_t idx_leaf); - -/* Compute the root node of the top-most subtree. */ -#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) -void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); - -#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/nistapi.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/nistapi.h deleted file mode 100644 index 3cb71afad4..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/nistapi.h +++ /dev/null @@ -1,87 +0,0 @@ -#ifndef SPX_API_H -#define SPX_API_H - -#include -#include - -#include "params.h" - -#define CRYPTO_ALGNAME "SPHINCS+" - -#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES -#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES -#define CRYPTO_BYTES SPX_BYTES -#define CRYPTO_SEEDBYTES (3*SPX_N) - -/* - * Returns the length of a secret key, in bytes - */ -#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) -size_t crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) -size_t crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) -size_t crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) -size_t crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) -int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) -int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) -int crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) -int crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -#define crypto_sign SPX_NAMESPACE(crypto_sign) -int crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) -int crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/params.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/params.h deleted file mode 100644 index e32fba8f77..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/params.h +++ /dev/null @@ -1,56 +0,0 @@ -#ifndef SPX_PARAMS_H -#define SPX_PARAMS_H - -#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSSHAKE128FROBUST_AVX2_##s - -/* Hash output length in bytes. */ -#define SPX_N 16 -/* Height of the hypertree. */ -#define SPX_FULL_HEIGHT 66 -/* Number of subtree layer. */ -#define SPX_D 22 -/* FORS tree dimensions. */ -#define SPX_FORS_HEIGHT 6 -#define SPX_FORS_TREES 33 -/* Winternitz parameter, */ -#define SPX_WOTS_W 16 - -/* The hash function is defined by linking a different hash.c file, as opposed - to setting a #define constant. */ - -/* For clarity */ -#define SPX_ADDR_BYTES 32 - -/* WOTS parameters. */ -#define SPX_WOTS_LOGW 4 - -#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) - -/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#define SPX_WOTS_LEN2 3 - -#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) -#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) -#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES - -/* Subtree size. */ -#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) - -//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT -// #error SPX_D should always divide SPX_FULL_HEIGHT -//#endif - -/* FORS parameters. */ -#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) -#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) -#define SPX_FORS_PK_BYTES SPX_N - -/* Resulting SPX sizes. */ -#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ - SPX_FULL_HEIGHT * SPX_N) -#define SPX_PK_BYTES (2 * SPX_N) -#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) - -#include "shake_offsets.h" - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/shake_offsets.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/shake_offsets.h deleted file mode 100644 index 6b28d95d91..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/shake_offsets.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef SHAKE_OFFSETS_H_ -#define SHAKE_OFFSETS_H_ - -/* - * Offsets of various fields in the address structure when we use SHAKE as - * the Sphincs+ hash function - */ - -#define SPX_OFFSET_LAYER 3 /* The byte used to specify the Merkle tree layer */ -#define SPX_OFFSET_TREE 8 /* The start of the 8 byte field used to specify the tree */ -#define SPX_OFFSET_TYPE 19 /* The byte used to specify the hash type (reason) */ -#define SPX_OFFSET_KP_ADDR2 22 /* The high byte used to specify the key pair (which one-time signature) */ -#define SPX_OFFSET_KP_ADDR1 23 /* The low byte used to specify the key pair */ -#define SPX_OFFSET_CHAIN_ADDR 27 /* The byte used to specify the chain address (which Winternitz chain) */ -#define SPX_OFFSET_HASH_ADDR 31 /* The byte used to specify the hash address (where in the Winternitz chain) */ -#define SPX_OFFSET_TREE_HGT 27 /* The byte used to specify the height of this node in the FORS or Merkle tree */ -#define SPX_OFFSET_TREE_INDEX 28 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ - -#define SPX_SHAKE 1 - -#endif /* SHAKE_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/sign.c b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/sign.c deleted file mode 100644 index 9d0c7d1b22..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/sign.c +++ /dev/null @@ -1,286 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "context.h" -#include "fors.h" -#include "hash.h" -#include "merkle.h" -#include "nistapi.h" -#include "params.h" -#include "randombytes.h" -#include "thash.h" -#include "utils.h" -#include "wots.h" - -/* - * Returns the length of a secret key, in bytes - */ -size_t crypto_sign_secretkeybytes(void) { - return CRYPTO_SECRETKEYBYTES; -} - -/* - * Returns the length of a public key, in bytes - */ -size_t crypto_sign_publickeybytes(void) { - return CRYPTO_PUBLICKEYBYTES; -} - -/* - * Returns the length of a signature, in bytes - */ -size_t crypto_sign_bytes(void) { - return CRYPTO_BYTES; -} - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t crypto_sign_seedbytes(void) { - return CRYPTO_SEEDBYTES; -} - -/* - * Generates an SPX key pair given a seed of length - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed) { - spx_ctx ctx; - - /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ - memcpy(sk, seed, CRYPTO_SEEDBYTES); - - memcpy(pk, sk + 2 * SPX_N, SPX_N); - - memcpy(ctx.pub_seed, pk, SPX_N); - memcpy(ctx.sk_seed, sk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - /* Compute root node of the top-most subtree. */ - merkle_gen_root(sk + 3 * SPX_N, &ctx); - - // cleanup - free_hash_function(&ctx); - - memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); - - return 0; -} - -/* - * Generates an SPX key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { - uint8_t seed[CRYPTO_SEEDBYTES]; - randombytes(seed, CRYPTO_SEEDBYTES); - crypto_sign_seed_keypair(pk, sk, seed); - - return 0; -} - -/** - * Returns an array containing a detached signature. - */ -int crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - spx_ctx ctx; - - const uint8_t *sk_prf = sk + SPX_N; - const uint8_t *pk = sk + 2 * SPX_N; - - uint8_t optrand[SPX_N]; - uint8_t mhash[SPX_FORS_MSG_BYTES]; - uint8_t root[SPX_N]; - uint32_t i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - - memcpy(ctx.sk_seed, sk, SPX_N); - memcpy(ctx.pub_seed, pk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - set_type(wots_addr, SPX_ADDR_TYPE_WOTS); - set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); - - /* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ - randombytes(optrand, SPX_N); - /* Compute the digest randomization value. */ - gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); - - /* Derive the message digest and leaf index from R, PK and M. */ - hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); - sig += SPX_N; - - set_tree_addr(wots_addr, tree); - set_keypair_addr(wots_addr, idx_leaf); - - /* Sign the message hash using FORS. */ - fors_sign(sig, root, mhash, &ctx, wots_addr); - sig += SPX_FORS_BYTES; - - for (i = 0; i < SPX_D; i++) { - set_layer_addr(tree_addr, i); - set_tree_addr(tree_addr, tree); - - copy_subtree_addr(wots_addr, tree_addr); - set_keypair_addr(wots_addr, idx_leaf); - - merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); - sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); - tree = tree >> SPX_TREE_HEIGHT; - } - - free_hash_function(&ctx); - - *siglen = SPX_BYTES; - - return 0; -} - -/** - * Verifies a detached signature and message under a given public key. - */ -int crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk) { - spx_ctx ctx; - const uint8_t *pub_root = pk + SPX_N; - uint8_t mhash[SPX_FORS_MSG_BYTES]; - uint8_t wots_pk[SPX_WOTS_BYTES]; - uint8_t root[SPX_N]; - uint8_t leaf[SPX_N]; - unsigned int i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - if (siglen != SPX_BYTES) { - return -1; - } - - memcpy(ctx.pub_seed, pk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - set_type(wots_addr, SPX_ADDR_TYPE_WOTS); - set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); - set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); - - /* Derive the message digest and leaf index from R || PK || M. */ - /* The additional SPX_N is a result of the hash domain separator. */ - hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); - sig += SPX_N; - - /* Layer correctly defaults to 0, so no need to set_layer_addr */ - set_tree_addr(wots_addr, tree); - set_keypair_addr(wots_addr, idx_leaf); - - fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); - sig += SPX_FORS_BYTES; - - /* For each subtree.. */ - for (i = 0; i < SPX_D; i++) { - set_layer_addr(tree_addr, i); - set_tree_addr(tree_addr, tree); - - copy_subtree_addr(wots_addr, tree_addr); - set_keypair_addr(wots_addr, idx_leaf); - - copy_keypair_addr(wots_pk_addr, wots_addr); - - /* The WOTS public key is only correct if the signature was correct. */ - /* Initially, root is the FORS pk, but on subsequent iterations it is - the root of the subtree below the currently processed subtree. */ - wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); - sig += SPX_WOTS_BYTES; - - /* Compute the leaf node using the WOTS public key. */ - thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); - - /* Compute the root node of this subtree. */ - compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, - &ctx, tree_addr); - sig += SPX_TREE_HEIGHT * SPX_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); - tree = tree >> SPX_TREE_HEIGHT; - } - - // cleanup - free_hash_function(&ctx); - - /* Check if the root node equals the root node in the public key. */ - if (memcmp(root, pub_root, SPX_N) != 0) { - return -1; - } - - return 0; -} - - -/** - * Returns an array containing the signature followed by the message. - */ -int crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk) { - size_t siglen; - - crypto_sign_signature(sm, &siglen, m, mlen, sk); - - memmove(sm + SPX_BYTES, m, mlen); - *smlen = siglen + mlen; - - return 0; -} - -/** - * Verifies a given signature-message pair under a given public key. - */ -int crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk) { - /* The API caller does not necessarily know what size a signature should be - but SPHINCS+ signatures are always exactly SPX_BYTES. */ - if (smlen < SPX_BYTES) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - *mlen = smlen - SPX_BYTES; - - if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - /* If verification was successful, move the message to the right place. */ - memmove(m, sm + SPX_BYTES, *mlen); - - return 0; -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/thash.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/thash.h deleted file mode 100644 index 8687ccfb4d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/thash.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef SPX_THASH_H -#define SPX_THASH_H - -#include "context.h" -#include "params.h" - -#include - -#define thash SPX_NAMESPACE(thash) -void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/thash_shake_robust.c b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/thash_shake_robust.c deleted file mode 100644 index 696d53c5cc..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/thash_shake_robust.c +++ /dev/null @@ -1,31 +0,0 @@ -#include -#include - -#include "thash.h" - -#include "address.h" -#include "params.h" -#include "utils.h" - -#include "fips202.h" - -/** - * Takes an array of inblocks concatenated arrays of SPX_N bytes. - */ -void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]) { - PQCLEAN_VLA(uint8_t, buf, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); - PQCLEAN_VLA(uint8_t, bitmask, inblocks * SPX_N); - unsigned int i; - - memcpy(buf, ctx->pub_seed, SPX_N); - memcpy(buf + SPX_N, addr, SPX_ADDR_BYTES); - - shake256(bitmask, inblocks * SPX_N, buf, SPX_N + SPX_ADDR_BYTES); - - for (i = 0; i < inblocks * SPX_N; i++) { - buf[SPX_N + SPX_ADDR_BYTES + i] = in[i] ^ bitmask[i]; - } - - shake256(out, SPX_N, buf, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/thash_shake_robustx4.c b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/thash_shake_robustx4.c deleted file mode 100644 index ce2946b745..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/thash_shake_robustx4.c +++ /dev/null @@ -1,131 +0,0 @@ -#include -#include - -#include "thashx4.h" - -#include "address.h" -#include "params.h" -#include "utils.h" - -#include "fips202x4.h" - -extern void KeccakP1600times4_PermuteAll_24rounds(__m256i *s); - -/** - * 4-way parallel version of thash; takes 4x as much input and output - */ -void thashx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addrx4[4 * 8]) { - if (inblocks == 1 || inblocks == 2) { - /* As we write and read only a few quadwords, it is more efficient to - * build and extract from the fourway SHAKE256 state by hand. */ - __m256i state[25]; - for (int i = 0; i < SPX_N / 8; i++) { - state[i] = _mm256_set1_epi64x(((int64_t *)ctx->pub_seed)[i]); - } - for (int i = 0; i < 4; i++) { - state[SPX_N / 8 + i] = _mm256_set_epi32( - (int)addrx4[3 * 8 + 1 + 2 * i], - (int)addrx4[3 * 8 + 2 * i], - (int)addrx4[2 * 8 + 1 + 2 * i], - (int)addrx4[2 * 8 + 2 * i], - (int)addrx4[8 + 1 + 2 * i], - (int)addrx4[8 + 2 * i], - (int)addrx4[1 + 2 * i], - (int)addrx4[2 * i] - ); - } - - /* SHAKE domain separator and padding */ - state[SPX_N / 8 + 4] = _mm256_set1_epi64x(0x1f); - for (int i = SPX_N / 8 + 5; i < 16; i++) { - state[i] = _mm256_set1_epi64x(0); - } - state[16] = _mm256_set1_epi64x((long long)(0x80ULL << 56)); - - for (int i = 17; i < 25; i++) { - state[i] = _mm256_set1_epi64x(0); - } - - /* We will permutate state2 with f1600x4 to compute the bitmask, - * but first we'll copy it to state2 which will be used to compute - * the final output, as its input is alsmost identical. */ - __m256i state2[25]; - memcpy(state2, state, 800); - - KeccakP1600times4_PermuteAll_24rounds(&state[0]); - - /* By copying from state, state2 already contains the pub_seed - * and addres. We just need to copy in the input blocks xorred with - * the bitmask we just computed. */ - for (unsigned int i = 0; i < (SPX_N / 8) * inblocks; i++) { - state2[SPX_N / 8 + 4 + i] = _mm256_xor_si256( - state[i], - _mm256_set_epi64x( - ((int64_t *)in3)[i], - ((int64_t *)in2)[i], - ((int64_t *)in1)[i], - ((int64_t *)in0)[i] - ) - ); - } - - /* Domain separator and start of padding. Note that the quadwords - * around are already zeroed for state from which we copied. - * We do a XOR instead of a set as this might be the 16th quadword - * when N=32 and inblocks=2, which already contains the end - * of the padding. */ - state2[(SPX_N / 8) * (1 + inblocks) + 4] = _mm256_xor_si256( - state2[(SPX_N / 8) * (1 + inblocks) + 4], - _mm256_set1_epi64x(0x1f) - ); - - KeccakP1600times4_PermuteAll_24rounds(&state2[0]); - - for (int i = 0; i < SPX_N / 8; i++) { - ((int64_t *)out0)[i] = _mm256_extract_epi64(state2[i], 0); - ((int64_t *)out1)[i] = _mm256_extract_epi64(state2[i], 1); - ((int64_t *)out2)[i] = _mm256_extract_epi64(state2[i], 2); - ((int64_t *)out3)[i] = _mm256_extract_epi64(state2[i], 3); - } - } else { - PQCLEAN_VLA(unsigned char, buf0, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); - PQCLEAN_VLA(unsigned char, buf1, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); - PQCLEAN_VLA(unsigned char, buf2, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); - PQCLEAN_VLA(unsigned char, buf3, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); - PQCLEAN_VLA(unsigned char, bitmask0, inblocks * SPX_N); - PQCLEAN_VLA(unsigned char, bitmask1, inblocks * SPX_N); - PQCLEAN_VLA(unsigned char, bitmask2, inblocks * SPX_N); - PQCLEAN_VLA(unsigned char, bitmask3, inblocks * SPX_N); - unsigned int i; - - memcpy(buf0, ctx->pub_seed, SPX_N); - memcpy(buf1, ctx->pub_seed, SPX_N); - memcpy(buf2, ctx->pub_seed, SPX_N); - memcpy(buf3, ctx->pub_seed, SPX_N); - memcpy(buf0 + SPX_N, addrx4 + 0 * 8, SPX_ADDR_BYTES); - memcpy(buf1 + SPX_N, addrx4 + 1 * 8, SPX_ADDR_BYTES); - memcpy(buf2 + SPX_N, addrx4 + 2 * 8, SPX_ADDR_BYTES); - memcpy(buf3 + SPX_N, addrx4 + 3 * 8, SPX_ADDR_BYTES); - - shake256x4(bitmask0, bitmask1, bitmask2, bitmask3, inblocks * SPX_N, - buf0, buf1, buf2, buf3, SPX_N + SPX_ADDR_BYTES); - - for (i = 0; i < inblocks * SPX_N; i++) { - buf0[SPX_N + SPX_ADDR_BYTES + i] = in0[i] ^ bitmask0[i]; - buf1[SPX_N + SPX_ADDR_BYTES + i] = in1[i] ^ bitmask1[i]; - buf2[SPX_N + SPX_ADDR_BYTES + i] = in2[i] ^ bitmask2[i]; - buf3[SPX_N + SPX_ADDR_BYTES + i] = in3[i] ^ bitmask3[i]; - } - - shake256x4(out0, out1, out2, out3, SPX_N, - buf0, buf1, buf2, buf3, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/thashx4.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/thashx4.h deleted file mode 100644 index 64798a3727..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/thashx4.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef SPX_THASHX4_H -#define SPX_THASHX4_H - -#include - -#include "context.h" -#include "params.h" - -#define thashx4 SPX_NAMESPACE(thashx4) -void thashx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addrx4[4 * 8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/utils.c b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/utils.c deleted file mode 100644 index 177b541fb9..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/utils.c +++ /dev/null @@ -1,148 +0,0 @@ -#include - -#include "utils.h" - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "thash.h" - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void ull_to_bytes(unsigned char *out, unsigned int outlen, - unsigned long long in) { - int i; - - /* Iterate over out in decreasing order, for big-endianness. */ - for (i = (signed int)outlen - 1; i >= 0; i--) { - out[i] = in & 0xff; - in = in >> 8; - } -} - -void u32_to_bytes(unsigned char *out, uint32_t in) { - out[0] = (unsigned char)(in >> 24); - out[1] = (unsigned char)(in >> 16); - out[2] = (unsigned char)(in >> 8); - out[3] = (unsigned char)in; -} - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { - unsigned long long retval = 0; - unsigned int i; - - for (i = 0; i < inlen; i++) { - retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); - } - return retval; -} - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void compute_root(unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const spx_ctx *ctx, uint32_t addr[8]) { - uint32_t i; - unsigned char buffer[2 * SPX_N]; - - /* If leaf_idx is odd (last bit = 1), current path element is a right child - and auth_path has to go left. Otherwise it is the other way around. */ - if (leaf_idx & 1) { - memcpy(buffer + SPX_N, leaf, SPX_N); - memcpy(buffer, auth_path, SPX_N); - } else { - memcpy(buffer, leaf, SPX_N); - memcpy(buffer + SPX_N, auth_path, SPX_N); - } - auth_path += SPX_N; - - for (i = 0; i < tree_height - 1; i++) { - leaf_idx >>= 1; - idx_offset >>= 1; - /* Set the address of the node we're creating. */ - set_tree_height(addr, i + 1); - set_tree_index(addr, leaf_idx + idx_offset); - - /* Pick the right or left neighbor, depending on parity of the node. */ - if (leaf_idx & 1) { - thash(buffer + SPX_N, buffer, 2, ctx, addr); - memcpy(buffer, auth_path, SPX_N); - } else { - thash(buffer, buffer, 2, ctx, addr); - memcpy(buffer + SPX_N, auth_path, SPX_N); - } - auth_path += SPX_N; - } - - /* The last iteration is exceptional; we do not copy an auth_path node. */ - leaf_idx >>= 1; - idx_offset >>= 1; - set_tree_height(addr, tree_height); - set_tree_index(addr, leaf_idx + idx_offset); - thash(root, buffer, 2, ctx, addr); -} - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const spx_ctx * /* ctx */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), - uint32_t tree_addr[8]) { - PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); - PQCLEAN_VLA(unsigned int, heights, tree_height + 1); - unsigned int offset = 0; - uint32_t idx; - uint32_t tree_idx; - - for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { - /* Add the next leaf node to the stack. */ - gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); - offset++; - heights[offset - 1] = 0; - - /* If this is a node we need for the auth path.. */ - if ((leaf_idx ^ 0x1) == idx) { - memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); - } - - /* While the top-most nodes are of equal height.. */ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { - /* Compute index of the new node, in the next layer. */ - tree_idx = (idx >> (heights[offset - 1] + 1)); - - /* Set the address of the node we're creating. */ - set_tree_height(tree_addr, heights[offset - 1] + 1); - set_tree_index(tree_addr, - tree_idx + (idx_offset >> (heights[offset - 1] + 1))); - /* Hash the top-most nodes from the stack together. */ - thash(stack + (offset - 2)*SPX_N, - stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); - offset--; - /* Note that the top-most node is now one layer higher. */ - heights[offset - 1]++; - - /* If this is a node we need for the auth path.. */ - if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_path + heights[offset - 1]*SPX_N, - stack + (offset - 1)*SPX_N, SPX_N); - } - } - } - memcpy(root, stack, SPX_N); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/utils.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/utils.h deleted file mode 100644 index 64f5d5a53a..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/utils.h +++ /dev/null @@ -1,58 +0,0 @@ -#ifndef SPX_UTILS_H -#define SPX_UTILS_H - -#include - -#include "compat.h" -#include "context.h" -#include "params.h" - - -/* To support MSVC use alloca() instead of VLAs. See #20. */ - - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) -void ull_to_bytes(unsigned char *out, unsigned int outlen, - unsigned long long in); -#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) -void u32_to_bytes(unsigned char *out, uint32_t in); - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) -unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -#define compute_root SPX_NAMESPACE(compute_root) -void compute_root(unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const spx_ctx *ctx, uint32_t addr[8]); - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -#define treehash SPX_NAMESPACE(treehash) -void treehash(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const spx_ctx *ctx /* ctx */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), - uint32_t tree_addr[8]); - - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/utilsx4.c b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/utilsx4.c deleted file mode 100644 index 1638677194..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/utilsx4.c +++ /dev/null @@ -1,138 +0,0 @@ -#include - -#include "utilsx4.h" - -#include "address.h" -#include "params.h" -#include "thashx4.h" -#include "utils.h" - -/* - * Generate the entire Merkle tree, computing the authentication path for leaf_idx, - * and the resulting root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) - * - * This expects tree_addrx4 to be initialized to 4 parallel addr structures for - * the Merkle tree nodes - * - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - * - * This works by using the standard Merkle tree building algorithm, except - * that each 'node' tracked is actually 4 consecutive nodes in the real tree. - * When we combine two logical nodes ABCD and WXYZ, we perform the H - * operation on adjacent real nodes, forming the parent logical node - * (AB)(CD)(WX)(YZ) - * - * When we get to the top two levels of the real tree (where there is only - * one logical node), we continue this operation two more times; the right - * most real node will by the actual root (and the other 3 nodes will be - * garbage). We follow the same thashx4 logic so that the 'extract - * authentication path components' part of the loop is still executed (and - * to simplify the code somewhat) - * - * This currently assumes tree_height >= 2; I suspect that doing an adjusting - * idx, addr_idx on the gen_leafx4 call if tree_height < 2 would fix it; since - * we don't actually use such short trees, I haven't bothered - */ -void treehashx4(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, - uint32_t tree_height, - void (*gen_leafx4)( - unsigned char * /* Where to write the leaves */, - const spx_ctx *, - uint32_t idx, void *info), - uint32_t tree_addrx4[4 * 8], - void *info) { - /* This is where we keep the intermediate nodes */ - PQCLEAN_VLA(unsigned char, stackx4, tree_height * 4 * SPX_N); - uint32_t left_adj = 0, prev_left_adj = 0; /* When we're doing the top 3 */ - /* levels, the left-most part of the tree isn't at the beginning */ - /* of current[]. These give the offset of the actual start */ - - uint32_t idx; - uint32_t max_idx = (1U << (tree_height - 2)) - 1; - for (idx = 0;; idx++) { - unsigned char current[4 * SPX_N]; /* Current logical node */ - gen_leafx4( current, ctx, 4 * idx + idx_offset, - info ); - - /* Now combine the freshly generated right node with previously */ - /* generated left ones */ - uint32_t internal_idx_offset = idx_offset; - uint32_t internal_idx = idx; - uint32_t internal_leaf = leaf_idx; - uint32_t h; /* The height we are in the Merkle tree */ - for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { - - /* Special processing if we're at the top of the tree */ - if (h >= tree_height - 2) { - if (h == tree_height) { - /* We hit the root; return it */ - memcpy( root, ¤t[3 * SPX_N], SPX_N ); - return; - } - /* The tree indexing logic is a bit off in this case */ - /* Adjust it so that the left-most node of the part of */ - /* the tree that we're processing has index 0 */ - prev_left_adj = left_adj; - left_adj = 4U - (1 << (tree_height - h - 1)); - } - - /* Check if we hit the top of the tree */ - if (h == tree_height) { - /* We hit the root; return it */ - memcpy( root, ¤t[3 * SPX_N], SPX_N ); - return; - } - - /* - * Check if one of the nodes we have is a part of the - * authentication path; if it is, write it out - */ - if ((((internal_idx << 2) ^ internal_leaf) & ~0x3U) == 0) { - memcpy( &auth_path[ h * SPX_N ], - ¤t[(((internal_leaf & 3) ^ 1) + prev_left_adj) * SPX_N], - SPX_N ); - } - - /* - * Check if we're at a left child; if so, stop going up the stack - * Exception: if we've reached the end of the tree, keep on going - * (so we combine the last 4 nodes into the one root node in two - * more iterations) - */ - if ((internal_idx & 1) == 0 && idx < max_idx) { - break; - } - - /* Ok, we're at a right node (or doing the top 3 levels) */ - /* Now combine the left and right logical nodes together */ - - /* Set the address of the node we're creating. */ - unsigned int j; - internal_idx_offset >>= 1; - for (j = 0; j < 4; j++) { - set_tree_height(tree_addrx4 + j * 8, h + 1); - set_tree_index(tree_addrx4 + j * 8, - (4 / 2) * (internal_idx & ~1U) + j - left_adj + internal_idx_offset ); - } - unsigned char *left = &stackx4[h * 4 * SPX_N]; - thashx4( ¤t[0 * SPX_N], - ¤t[1 * SPX_N], - ¤t[2 * SPX_N], - ¤t[3 * SPX_N], - &left [0 * SPX_N], - &left [2 * SPX_N], - ¤t[0 * SPX_N], - ¤t[2 * SPX_N], - 2, ctx, tree_addrx4); - } - - /* We've hit a left child; save the current for when we get the */ - /* corresponding right right */ - memcpy( &stackx4[h * 4 * SPX_N], current, 4 * SPX_N); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/utilsx4.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/utilsx4.h deleted file mode 100644 index facb874b18..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/utilsx4.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef SPX_UTILSX4_H -#define SPX_UTILSX4_H - -#include - -#include "context.h" -#include "params.h" - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - * - * This implementation uses AVX to compute internal nodes 4 at a time (in - * parallel) - */ -#define treehashx4 SPX_NAMESPACE(treehashx4) -void treehashx4(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leafx4)( - unsigned char * /* Where to write the leaves */, - const spx_ctx * /* ctx */, - uint32_t addr_idx, void *info), - uint32_t tree_addrx4[4 * 8], void *info); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/wots.c b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/wots.c deleted file mode 100644 index 4d5041ce05..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/wots.c +++ /dev/null @@ -1,269 +0,0 @@ -#include -#include - -#include "wots.h" - -#include "address.h" -#include "hash.h" -#include "hashx4.h" -#include "params.h" -#include "thash.h" -#include "thashx4.h" -#include "utils.h" -#include "utilsx4.h" -#include "wotsx4.h" - -// TODO clarify address expectations, and make them more uniform. -// TODO i.e. do we expect types to be set already? -// TODO and do we expect modifications or copies? - -/** - * Computes up the chains - */ -static void gen_chains( - unsigned char *out, - const unsigned char *in, - unsigned int start[SPX_WOTS_LEN], - const unsigned int steps[SPX_WOTS_LEN], - const spx_ctx *ctx, - uint32_t addr[8]) { - uint32_t i, j, k, idx, watching; - int done; - unsigned char empty[SPX_N]; - unsigned char *bufs[4]; - uint32_t addrs[8 * 4]; - - int l; - uint16_t counts[SPX_WOTS_W] = { 0 }; - uint16_t idxs[SPX_WOTS_LEN]; - uint16_t total, newTotal; - - /* set addrs = {addr, addr, addr, addr} */ - for (j = 0; j < 4; j++) { - memcpy(addrs + j * 8, addr, sizeof(uint32_t) * 8); - } - - /* Initialize out with the value at position 'start'. */ - memcpy(out, in, SPX_WOTS_LEN * SPX_N); - - /* Sort the chains in reverse order by steps using counting sort. */ - for (i = 0; i < SPX_WOTS_LEN; i++) { - counts[steps[i]]++; - } - total = 0; - for (l = SPX_WOTS_W - 1; l >= 0; l--) { - newTotal = counts[l] + total; - counts[l] = total; - total = newTotal; - } - for (i = 0; i < SPX_WOTS_LEN; i++) { - idxs[counts[steps[i]]] = (uint16_t)i; - counts[steps[i]]++; - } - - /* We got our work cut out for us: do it! */ - for (i = 0; i < SPX_WOTS_LEN; i += 4) { - for (j = 0; j < 4 && i + j < SPX_WOTS_LEN; j++) { - idx = idxs[i + j]; - set_chain_addr(addrs + j * 8, idx); - bufs[j] = out + SPX_N * idx; - } - - /* As the chains are sorted in reverse order, we know that the first - * chain is the longest and the last one is the shortest. We keep - * an eye on whether the last chain is done and then on the one before, - * et cetera. */ - watching = 3; - done = 0; - while (i + watching >= SPX_WOTS_LEN) { - bufs[watching] = &empty[0]; - watching--; - } - - for (k = 0;; k++) { - while (k == steps[idxs[i + watching]]) { - bufs[watching] = &empty[0]; - if (watching == 0) { - done = 1; - break; - } - watching--; - } - if (done) { - break; - } - for (j = 0; j < watching + 1; j++) { - set_hash_addr(addrs + j * 8, k + start[idxs[i + j]]); - } - - thashx4(bufs[0], bufs[1], bufs[2], bufs[3], - bufs[0], bufs[1], bufs[2], bufs[3], 1, ctx, addrs); - } - } -} - -/** - * base_w algorithm as described in draft. - * Interprets an array of bytes as integers in base w. - * This only works when log_w is a divisor of 8. - */ -static void base_w(unsigned int *output, const int out_len, - const unsigned char *input) { - int in = 0; - int out = 0; - unsigned char total = 0; - int bits = 0; - int consumed; - - for (consumed = 0; consumed < out_len; consumed++) { - if (bits == 0) { - total = input[in]; - in++; - bits += 8; - } - bits -= SPX_WOTS_LOGW; - output[out] = (total >> bits) & (SPX_WOTS_W - 1); - out++; - } -} - -/* Computes the WOTS+ checksum over a message (in base_w). */ -static void wots_checksum(unsigned int *csum_base_w, - const unsigned int *msg_base_w) { - unsigned int csum = 0; - unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; - unsigned int i; - - /* Compute checksum. */ - for (i = 0; i < SPX_WOTS_LEN1; i++) { - csum += SPX_WOTS_W - 1 - msg_base_w[i]; - } - - /* Convert checksum to base_w. */ - /* Make sure expected empty zero bits are the least significant bits. */ - csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); - ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); - base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); -} - -/* Takes a message and derives the matching chain lengths. */ -void chain_lengths(unsigned int *lengths, const unsigned char *msg) { - base_w(lengths, SPX_WOTS_LEN1, msg); - wots_checksum(lengths + SPX_WOTS_LEN1, lengths); -} - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const spx_ctx *ctx, uint32_t addr[8]) { - unsigned int steps[SPX_WOTS_LEN]; - unsigned int start[SPX_WOTS_LEN]; - uint32_t i; - - chain_lengths(start, msg); - - for (i = 0; i < SPX_WOTS_LEN; i++) { - steps[i] = SPX_WOTS_W - 1 - start[i]; - } - - gen_chains(pk, sig, start, steps, ctx, addr); -} - -/* - * This generates 4 sequential WOTS public keys - * It also generates the WOTS signature if leaf_info indicates - * that we're signing with one of these WOTS keys - */ -void wots_gen_leafx4(unsigned char *dest, - const spx_ctx *ctx, - uint32_t leaf_idx, void *v_info) { - struct leaf_info_x4 *info = v_info; - uint32_t *leaf_addr = info->leaf_addr; - uint32_t *pk_addr = info->pk_addr; - unsigned int i, j, k; - unsigned char pk_buffer[ 4 * SPX_WOTS_BYTES ]; - unsigned wots_offset = SPX_WOTS_BYTES; - unsigned char *buffer; - uint32_t wots_k_mask; - unsigned wots_sign_index; - - if (((leaf_idx ^ info->wots_sign_leaf) & ~3U) == 0) { - /* We're traversing the leaf that's signing; generate the WOTS */ - /* signature */ - wots_k_mask = 0; - wots_sign_index = info->wots_sign_leaf & 3; /* Which of of the 4 */ - /* 4 slots do the signatures come from */ - } else { - /* Nope, we're just generating pk's; turn off the signature logic */ - wots_k_mask = (uint32_t)~0; - wots_sign_index = 0; - } - - for (j = 0; j < 4; j++) { - set_keypair_addr( leaf_addr + j * 8, leaf_idx + j ); - set_keypair_addr( pk_addr + j * 8, leaf_idx + j ); - } - - for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { - uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k to */ - /* the step if we're generating a signature, ~0 if we're not */ - - /* Start with the secret seed */ - for (j = 0; j < 4; j++) { - set_chain_addr(leaf_addr + j * 8, i); - set_hash_addr(leaf_addr + j * 8, 0); - set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTSPRF); - } - prf_addrx4(buffer + 0 * wots_offset, - buffer + 1 * wots_offset, - buffer + 2 * wots_offset, - buffer + 3 * wots_offset, - ctx, leaf_addr); - - for (j = 0; j < 4; j++) { - set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTS); - } - - /* Iterate down the WOTS chain */ - for (k = 0;; k++) { - /* Check if one of the values we have needs to be saved as a */ - /* part of the WOTS signature */ - if (k == wots_k) { - memcpy( info->wots_sig + i * SPX_N, - buffer + wots_sign_index * wots_offset, SPX_N ); - } - - /* Check if we hit the top of the chain */ - if (k == SPX_WOTS_W - 1) { - break; - } - - /* Iterate one step on all 4 chains */ - for (j = 0; j < 4; j++) { - set_hash_addr(leaf_addr + j * 8, k); - } - thashx4(buffer + 0 * wots_offset, - buffer + 1 * wots_offset, - buffer + 2 * wots_offset, - buffer + 3 * wots_offset, - buffer + 0 * wots_offset, - buffer + 1 * wots_offset, - buffer + 2 * wots_offset, - buffer + 3 * wots_offset, 1, ctx, leaf_addr); - } - } - - /* Do the final thash to generate the public keys */ - thashx4(dest + 0 * SPX_N, - dest + 1 * SPX_N, - dest + 2 * SPX_N, - dest + 3 * SPX_N, - pk_buffer + 0 * wots_offset, - pk_buffer + 1 * wots_offset, - pk_buffer + 2 * wots_offset, - pk_buffer + 3 * wots_offset, SPX_WOTS_LEN, ctx, pk_addr); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/wots.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/wots.h deleted file mode 100644 index 4e7692eeef..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/wots.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef SPX_WOTS_H -#define SPX_WOTS_H - -#include - -#include "context.h" -#include "params.h" - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) -void wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const spx_ctx *ctx, uint32_t addr[8]); - -/* - * Compute the chain lengths needed for a given message hash - */ -#define chain_lengths SPX_NAMESPACE(chain_lengths) -void chain_lengths(unsigned int *lengths, const unsigned char *msg); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/wotsx4.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/wotsx4.h deleted file mode 100644 index cd634f1743..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_avx2/wotsx4.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef WOTSX4_H_ -#define WOTSX4_H_ - -#include - -#include "params.h" - -/* - * This is here to provide an interface to the internal wots_gen_leafx4 - * routine. While this routine is not referenced in the package outside of - * wots.c, it is called from the stand-alone benchmark code to characterize - * the performance - */ -struct leaf_info_x4 { - unsigned char *wots_sig; - uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ - uint32_t *wots_steps; - uint32_t leaf_addr[4 * 8]; - uint32_t pk_addr[4 * 8]; -}; - -/* Macro to set the leaf_info to something 'benign', that is, it would */ -/* run with the same time as it does during the real signing process */ -/* Used only by the benchmark code */ -#define INITIALIZE_LEAF_INFO_X4(info, addr, step_buffer) { \ - (info).wots_sig = 0; \ - (info).wots_sign_leaf = ~0; \ - (info).wots_steps = step_buffer; \ - int i; \ - for (i=0; i<4; i++) { \ - memcpy( &(info).leaf_addr[8*i], addr, 32 ); \ - memcpy( &(info).pk_addr[8*i], addr, 32 ); \ - } \ - } - -#define wots_gen_leafx4 SPX_NAMESPACE(wots_gen_leafx4) -void wots_gen_leafx4(unsigned char *dest, - const spx_ctx *ctx, - uint32_t leaf_idx, void *v_info); - -#endif /* WOTSX4_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/LICENSE b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/LICENSE deleted file mode 100644 index 670154e353..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/LICENSE +++ /dev/null @@ -1,116 +0,0 @@ -CC0 1.0 Universal - -Statement of Purpose - -The laws of most jurisdictions throughout the world automatically confer -exclusive Copyright and Related Rights (defined below) upon the creator and -subsequent owner(s) (each and all, an "owner") of an original work of -authorship and/or a database (each, a "Work"). - -Certain owners wish to permanently relinquish those rights to a Work for the -purpose of contributing to a commons of creative, cultural and scientific -works ("Commons") that the public can reliably and without fear of later -claims of infringement build upon, modify, incorporate in other works, reuse -and redistribute as freely as possible in any form whatsoever and for any -purposes, including without limitation commercial purposes. These owners may -contribute to the Commons to promote the ideal of a free culture and the -further production of creative, cultural and scientific works, or to gain -reputation or greater distribution for their Work in part through the use and -efforts of others. - -For these and/or other purposes and motivations, and without any expectation -of additional consideration or compensation, the person associating CC0 with a -Work (the "Affirmer"), to the extent that he or she is an owner of Copyright -and Related Rights in the Work, voluntarily elects to apply CC0 to the Work -and publicly distribute the Work under its terms, with knowledge of his or her -Copyright and Related Rights in the Work and the meaning and intended legal -effect of CC0 on those rights. - -1. Copyright and Related Rights. A Work made available under CC0 may be -protected by copyright and related or neighboring rights ("Copyright and -Related Rights"). Copyright and Related Rights include, but are not limited -to, the following: - - i. the right to reproduce, adapt, distribute, perform, display, communicate, - and translate a Work; - - ii. moral rights retained by the original author(s) and/or performer(s); - - iii. publicity and privacy rights pertaining to a person's image or likeness - depicted in a Work; - - iv. rights protecting against unfair competition in regards to a Work, - subject to the limitations in paragraph 4(a), below; - - v. rights protecting the extraction, dissemination, use and reuse of data in - a Work; - - vi. database rights (such as those arising under Directive 96/9/EC of the - European Parliament and of the Council of 11 March 1996 on the legal - protection of databases, and under any national implementation thereof, - including any amended or successor version of such directive); and - - vii. other similar, equivalent or corresponding rights throughout the world - based on applicable law or treaty, and any national implementations thereof. - -2. Waiver. To the greatest extent permitted by, but not in contravention of, -applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and -unconditionally waives, abandons, and surrenders all of Affirmer's Copyright -and Related Rights and associated claims and causes of action, whether now -known or unknown (including existing as well as future claims and causes of -action), in the Work (i) in all territories worldwide, (ii) for the maximum -duration provided by applicable law or treaty (including future time -extensions), (iii) in any current or future medium and for any number of -copies, and (iv) for any purpose whatsoever, including without limitation -commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes -the Waiver for the benefit of each member of the public at large and to the -detriment of Affirmer's heirs and successors, fully intending that such Waiver -shall not be subject to revocation, rescission, cancellation, termination, or -any other legal or equitable action to disrupt the quiet enjoyment of the Work -by the public as contemplated by Affirmer's express Statement of Purpose. - -3. Public License Fallback. Should any part of the Waiver for any reason be -judged legally invalid or ineffective under applicable law, then the Waiver -shall be preserved to the maximum extent permitted taking into account -Affirmer's express Statement of Purpose. In addition, to the extent the Waiver -is so judged Affirmer hereby grants to each affected person a royalty-free, -non transferable, non sublicensable, non exclusive, irrevocable and -unconditional license to exercise Affirmer's Copyright and Related Rights in -the Work (i) in all territories worldwide, (ii) for the maximum duration -provided by applicable law or treaty (including future time extensions), (iii) -in any current or future medium and for any number of copies, and (iv) for any -purpose whatsoever, including without limitation commercial, advertising or -promotional purposes (the "License"). The License shall be deemed effective as -of the date CC0 was applied by Affirmer to the Work. Should any part of the -License for any reason be judged legally invalid or ineffective under -applicable law, such partial invalidity or ineffectiveness shall not -invalidate the remainder of the License, and in such case Affirmer hereby -affirms that he or she will not (i) exercise any of his or her remaining -Copyright and Related Rights in the Work or (ii) assert any associated claims -and causes of action with respect to the Work, in either case contrary to -Affirmer's express Statement of Purpose. - -4. Limitations and Disclaimers. - - a. No trademark or patent rights held by Affirmer are waived, abandoned, - surrendered, licensed or otherwise affected by this document. - - b. Affirmer offers the Work as-is and makes no representations or warranties - of any kind concerning the Work, express, implied, statutory or otherwise, - including without limitation warranties of title, merchantability, fitness - for a particular purpose, non infringement, or the absence of latent or - other defects, accuracy, or the present or absence of errors, whether or not - discoverable, all to the greatest extent permissible under applicable law. - - c. Affirmer disclaims responsibility for clearing rights of other persons - that may apply to the Work or any use thereof, including without limitation - any person's Copyright and Related Rights in the Work. Further, Affirmer - disclaims responsibility for obtaining any necessary consents, permissions - or other rights required for any use of the Work. - - d. Affirmer understands and acknowledges that Creative Commons is not a - party to this document and has no duty or obligation with respect to this - CC0 or use of the Work. - -For more information, please see - diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/address.c b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/address.c deleted file mode 100644 index b956e9cb29..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/address.c +++ /dev/null @@ -1,91 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "utils.h" - -/* - * Specify which level of Merkle tree (the "layer") we're working on - */ -void set_layer_addr(uint32_t addr[8], uint32_t layer) { - ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; -} - -/* - * Specify which Merkle tree within the level (the "tree address") we're working on - */ -void set_tree_addr(uint32_t addr[8], uint64_t tree) { - ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); -} - -/* - * Specify the reason we'll use this address structure for, that is, what - * hash will we compute with it. This is used so that unrelated types of - * hashes don't accidentally get the same address structure. The type will be - * one of the SPX_ADDR_TYPE constants - */ -void set_type(uint32_t addr[8], uint32_t type) { - ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; -} - -/* - * Copy the layer and tree fields of the address structure. This is used - * when we're doing multiple types of hashes within the same Merkle tree - */ -void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { - memcpy( out, in, SPX_OFFSET_TREE + 8 ); -} - -/* These functions are used for OTS addresses. */ - -/* - * Specify which Merkle leaf we're working on; that is, which OTS keypair - * we're talking about. - */ -void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { - ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; -} - -/* - * Copy the layer, tree and keypair fields of the address structure. This is - * used when we're doing multiple things within the same OTS keypair - */ -void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { - memcpy( out, in, SPX_OFFSET_TREE + 8 ); - ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; -} - -/* - * Specify which Merkle chain within the OTS we're working with - * (the chain address) - */ -void set_chain_addr(uint32_t addr[8], uint32_t chain) { - ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; -} - -/* - * Specify where in the Merkle chain we are -* (the hash address) - */ -void set_hash_addr(uint32_t addr[8], uint32_t hash) { - ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; -} - -/* These functions are used for all hash tree addresses (including FORS). */ - -/* - * Specify the height of the node in the Merkle/FORS tree we are in - * (the tree height) - */ -void set_tree_height(uint32_t addr[8], uint32_t tree_height) { - ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; -} - -/* - * Specify the distance from the left edge of the node in the Merkle/FORS tree - * (the tree index) - */ -void set_tree_index(uint32_t addr[8], uint32_t tree_index) { - u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/address.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/address.h deleted file mode 100644 index 24a84eb40c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/address.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef SPX_ADDRESS_H -#define SPX_ADDRESS_H - -#include - -#include "params.h" - -/* The hash types that are passed to set_type */ -#define SPX_ADDR_TYPE_WOTS 0 -#define SPX_ADDR_TYPE_WOTSPK 1 -#define SPX_ADDR_TYPE_HASHTREE 2 -#define SPX_ADDR_TYPE_FORSTREE 3 -#define SPX_ADDR_TYPE_FORSPK 4 -#define SPX_ADDR_TYPE_WOTSPRF 5 -#define SPX_ADDR_TYPE_FORSPRF 6 - -#define set_layer_addr SPX_NAMESPACE(set_layer_addr) -void set_layer_addr(uint32_t addr[8], uint32_t layer); - -#define set_tree_addr SPX_NAMESPACE(set_tree_addr) -void set_tree_addr(uint32_t addr[8], uint64_t tree); - -#define set_type SPX_NAMESPACE(set_type) -void set_type(uint32_t addr[8], uint32_t type); - -/* Copies the layer and tree part of one address into the other */ -#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) -void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for WOTS and FORS addresses. */ - -#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) -void set_keypair_addr(uint32_t addr[8], uint32_t keypair); - -#define set_chain_addr SPX_NAMESPACE(set_chain_addr) -void set_chain_addr(uint32_t addr[8], uint32_t chain); - -#define set_hash_addr SPX_NAMESPACE(set_hash_addr) -void set_hash_addr(uint32_t addr[8], uint32_t hash); - -#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) -void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for all hash tree addresses (including FORS). */ - -#define set_tree_height SPX_NAMESPACE(set_tree_height) -void set_tree_height(uint32_t addr[8], uint32_t tree_height); - -#define set_tree_index SPX_NAMESPACE(set_tree_index) -void set_tree_index(uint32_t addr[8], uint32_t tree_index); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/api.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/api.h deleted file mode 100644 index 5cf2a43ded..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/api.h +++ /dev/null @@ -1,77 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE128FROBUST_CLEAN_API_H -#define PQCLEAN_SPHINCSSHAKE128FROBUST_CLEAN_API_H - -#include -#include - -#define PQCLEAN_SPHINCSSHAKE128FROBUST_CLEAN_CRYPTO_ALGNAME "SPHINCS+-shake-128f-robust" - -#define PQCLEAN_SPHINCSSHAKE128FROBUST_CLEAN_CRYPTO_SECRETKEYBYTES 64 -#define PQCLEAN_SPHINCSSHAKE128FROBUST_CLEAN_CRYPTO_PUBLICKEYBYTES 32 -#define PQCLEAN_SPHINCSSHAKE128FROBUST_CLEAN_CRYPTO_BYTES 17088 - -#define PQCLEAN_SPHINCSSHAKE128FROBUST_CLEAN_CRYPTO_SEEDBYTES 48 - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE128FROBUST_CLEAN_crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE128FROBUST_CLEAN_crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE128FROBUST_CLEAN_crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE128FROBUST_CLEAN_crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHAKE128FROBUST_CLEAN_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHAKE128FROBUST_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSSHAKE128FROBUST_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE128FROBUST_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, - const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSSHAKE128FROBUST_CLEAN_crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE128FROBUST_CLEAN_crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk); -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/context.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/context.h deleted file mode 100644 index 9f8a40ab4e..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/context.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef SPX_CONTEXT_H -#define SPX_CONTEXT_H - -#include -#include - -#include "params.h" - -typedef struct { - uint8_t pub_seed[SPX_N]; - uint8_t sk_seed[SPX_N]; - - -} spx_ctx; - -#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) -void initialize_hash_function(spx_ctx *ctx); - -#define free_hash_function SPX_NAMESPACE(free_hash_function) -void free_hash_function(spx_ctx *ctx); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/context_shake.c b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/context_shake.c deleted file mode 100644 index 9614a103d3..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/context_shake.c +++ /dev/null @@ -1,12 +0,0 @@ -#include "context.h" - -/* For SHAKE256, there is no immediate reason to initialize at the start, - so this function is an empty operation. */ -void initialize_hash_function(spx_ctx *ctx) { - (void)ctx; /* Suppress an 'unused parameter' warning. */ -} - -// in case the hash function api is heap-based. -void free_hash_function(spx_ctx *ctx) { - (void)ctx; -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/fors.c b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/fors.c deleted file mode 100644 index 96ca72e986..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/fors.c +++ /dev/null @@ -1,156 +0,0 @@ -#include -#include -#include - -#include "fors.h" - -#include "address.h" -#include "hash.h" -#include "thash.h" -#include "utils.h" -#include "utilsx1.h" - -static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, - uint32_t fors_leaf_addr[8]) { - prf_addr(sk, ctx, fors_leaf_addr); -} - -static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, - const spx_ctx *ctx, - uint32_t fors_leaf_addr[8]) { - thash(leaf, sk, 1, ctx, fors_leaf_addr); -} - -struct fors_gen_leaf_info { - uint32_t leaf_addrx[8]; -}; - -static void fors_gen_leafx1(unsigned char *leaf, - const spx_ctx *ctx, - uint32_t addr_idx, void *info) { - struct fors_gen_leaf_info *fors_info = info; - uint32_t *fors_leaf_addr = fors_info->leaf_addrx; - - /* Only set the parts that the caller doesn't set */ - set_tree_index(fors_leaf_addr, addr_idx); - set_type(fors_leaf_addr, SPX_ADDR_TYPE_FORSPRF); - fors_gen_sk(leaf, ctx, fors_leaf_addr); - - set_type(fors_leaf_addr, SPX_ADDR_TYPE_FORSTREE); - fors_sk_to_leaf(leaf, leaf, - ctx, fors_leaf_addr); -} - -/** - * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - * Assumes indices has space for SPX_FORS_TREES integers. - */ -static void message_to_indices(uint32_t *indices, const unsigned char *m) { - unsigned int i, j; - unsigned int offset = 0; - - for (i = 0; i < SPX_FORS_TREES; i++) { - indices[i] = 0; - for (j = 0; j < SPX_FORS_HEIGHT; j++) { - indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); - offset++; - } - } -} - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -void fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]) { - uint32_t indices[SPX_FORS_TREES]; - unsigned char roots[SPX_FORS_TREES * SPX_N]; - uint32_t fors_tree_addr[8] = {0}; - struct fors_gen_leaf_info fors_info = {0}; - uint32_t *fors_leaf_addr = fors_info.leaf_addrx; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - copy_keypair_addr(fors_tree_addr, fors_addr); - copy_keypair_addr(fors_leaf_addr, fors_addr); - - copy_keypair_addr(fors_pk_addr, fors_addr); - set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < SPX_FORS_TREES; i++) { - idx_offset = i * (1 << SPX_FORS_HEIGHT); - - set_tree_height(fors_tree_addr, 0); - set_tree_index(fors_tree_addr, indices[i] + idx_offset); - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); - - /* Include the secret key part that produces the selected leaf node. */ - fors_gen_sk(sig, ctx, fors_tree_addr); - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); - sig += SPX_N; - - /* Compute the authentication path for this leaf node. */ - treehashx1(roots + i * SPX_N, sig, ctx, - indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx1, - fors_tree_addr, &fors_info); - - sig += SPX_N * SPX_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); -} - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -void fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]) { - uint32_t indices[SPX_FORS_TREES]; - unsigned char roots[SPX_FORS_TREES * SPX_N]; - unsigned char leaf[SPX_N]; - uint32_t fors_tree_addr[8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - copy_keypair_addr(fors_tree_addr, fors_addr); - copy_keypair_addr(fors_pk_addr, fors_addr); - - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); - set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < SPX_FORS_TREES; i++) { - idx_offset = i * (1 << SPX_FORS_HEIGHT); - - set_tree_height(fors_tree_addr, 0); - set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Derive the leaf from the included secret key part. */ - fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); - sig += SPX_N; - - /* Derive the corresponding root node of this tree. */ - compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, - sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); - sig += SPX_N * SPX_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/fors.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/fors.h deleted file mode 100644 index 509140a178..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/fors.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef SPX_FORS_H -#define SPX_FORS_H - -#include - -#include "context.h" -#include "params.h" - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -#define fors_sign SPX_NAMESPACE(fors_sign) -void fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]); - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) -void fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/hash.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/hash.h deleted file mode 100644 index f7c87d4c3c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/hash.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef SPX_HASH_H -#define SPX_HASH_H - -#include -#include - -#include "context.h" -#include "params.h" - -#define prf_addr SPX_NAMESPACE(prf_addr) -void prf_addr(unsigned char *out, const spx_ctx *ctx, - const uint32_t addr[8]); - -#define gen_message_random SPX_NAMESPACE(gen_message_random) -void gen_message_random(unsigned char *R, const unsigned char *sk_prf, - const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx); - -#define hash_message SPX_NAMESPACE(hash_message) -void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx); - - - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/hash_shake.c b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/hash_shake.c deleted file mode 100644 index ff5e7ec918..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/hash_shake.c +++ /dev/null @@ -1,83 +0,0 @@ -#include -#include - -#include "hash.h" - -#include "address.h" -#include "fips202.h" -#include "params.h" -#include "utils.h" - -/* - * Computes PRF(pk_seed, sk_seed, addr) - */ -void prf_addr(unsigned char *out, const spx_ctx *ctx, - const uint32_t addr[8]) { - unsigned char buf[2 * SPX_N + SPX_ADDR_BYTES]; - - memcpy(buf, ctx->pub_seed, SPX_N); - memcpy(buf + SPX_N, addr, SPX_ADDR_BYTES); - memcpy(buf + SPX_N + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); - - shake256(out, SPX_N, buf, 2 * SPX_N + SPX_ADDR_BYTES); -} - -/** - * Computes the message-dependent randomness R, using a secret seed and an - * optional randomization value as well as the message. - */ -void gen_message_random(unsigned char *R, const unsigned char *sk_prf, - const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx) { - (void)ctx; - shake256incctx s_inc; - - shake256_inc_init(&s_inc); - shake256_inc_absorb(&s_inc, sk_prf, SPX_N); - shake256_inc_absorb(&s_inc, optrand, SPX_N); - shake256_inc_absorb(&s_inc, m, mlen); - shake256_inc_finalize(&s_inc); - shake256_inc_squeeze(R, SPX_N, &s_inc); - shake256_inc_ctx_release(&s_inc); -} - -/** - * Computes the message hash using R, the public key, and the message. - * Outputs the message digest and the index of the leaf. The index is split in - * the tree index and the leaf index, for convenient copying to an address. - */ -void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx) { - (void)ctx; -#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) -#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) -#define SPX_LEAF_BITS SPX_TREE_HEIGHT -#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) -#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) - - unsigned char buf[SPX_DGST_BYTES]; - unsigned char *bufp = buf; - shake256incctx s_inc; - - shake256_inc_init(&s_inc); - shake256_inc_absorb(&s_inc, R, SPX_N); - shake256_inc_absorb(&s_inc, pk, SPX_PK_BYTES); - shake256_inc_absorb(&s_inc, m, mlen); - shake256_inc_finalize(&s_inc); - shake256_inc_squeeze(buf, SPX_DGST_BYTES, &s_inc); - shake256_inc_ctx_release(&s_inc); - - memcpy(digest, bufp, SPX_FORS_MSG_BYTES); - bufp += SPX_FORS_MSG_BYTES; - - - *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); - *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); - bufp += SPX_TREE_BYTES; - - *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); - *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/merkle.c b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/merkle.c deleted file mode 100644 index 0c1479fd93..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/merkle.c +++ /dev/null @@ -1,59 +0,0 @@ -#include -#include - -#include "address.h" -#include "merkle.h" -#include "params.h" -#include "utils.h" -#include "utilsx1.h" -#include "wots.h" -#include "wotsx1.h" - -/* - * This generates a Merkle signature (WOTS signature followed by the Merkle - * authentication path). This is in this file because most of the complexity - * is involved with the WOTS signature; the Merkle authentication path logic - * is mostly hidden in treehashx4 - */ -void merkle_sign(uint8_t *sig, unsigned char *root, - const spx_ctx *ctx, - uint32_t wots_addr[8], uint32_t tree_addr[8], - uint32_t idx_leaf) { - unsigned char *auth_path = sig + SPX_WOTS_BYTES; - struct leaf_info_x1 info = { 0 }; - unsigned steps[ SPX_WOTS_LEN ]; - - info.wots_sig = sig; - chain_lengths(steps, root); - info.wots_steps = steps; - - set_type(&tree_addr[0], SPX_ADDR_TYPE_HASHTREE); - set_type(&info.pk_addr[0], SPX_ADDR_TYPE_WOTSPK); - copy_subtree_addr(&info.leaf_addr[0], wots_addr); - copy_subtree_addr(&info.pk_addr[0], wots_addr); - - info.wots_sign_leaf = idx_leaf; - - treehashx1(root, auth_path, ctx, - idx_leaf, 0, - SPX_TREE_HEIGHT, - wots_gen_leafx1, - tree_addr, &info); -} - -/* Compute root node of the top-most subtree. */ -void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { - /* We do not need the auth path in key generation, but it simplifies the - code to have just one treehash routine that computes both root and path - in one function. */ - unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; - uint32_t top_tree_addr[8] = {0}; - uint32_t wots_addr[8] = {0}; - - set_layer_addr(top_tree_addr, SPX_D - 1); - set_layer_addr(wots_addr, SPX_D - 1); - - merkle_sign(auth_path, root, ctx, - wots_addr, top_tree_addr, - (uint32_t)~0 /* ~0 means "don't bother generating an auth path */ ); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/merkle.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/merkle.h deleted file mode 100644 index 769cf2e970..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/merkle.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef MERKLE_H_ -#define MERKLE_H_ - -#include - -#include "context.h" -#include "params.h" - -/* Generate a Merkle signature (WOTS signature followed by the Merkle */ -/* authentication path) */ -#define merkle_sign SPX_NAMESPACE(merkle_sign) -void merkle_sign(uint8_t *sig, unsigned char *root, - const spx_ctx *ctx, - uint32_t wots_addr[8], uint32_t tree_addr[8], - uint32_t idx_leaf); - -/* Compute the root node of the top-most subtree. */ -#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) -void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); - -#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/nistapi.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/nistapi.h deleted file mode 100644 index 3cb71afad4..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/nistapi.h +++ /dev/null @@ -1,87 +0,0 @@ -#ifndef SPX_API_H -#define SPX_API_H - -#include -#include - -#include "params.h" - -#define CRYPTO_ALGNAME "SPHINCS+" - -#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES -#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES -#define CRYPTO_BYTES SPX_BYTES -#define CRYPTO_SEEDBYTES (3*SPX_N) - -/* - * Returns the length of a secret key, in bytes - */ -#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) -size_t crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) -size_t crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) -size_t crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) -size_t crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) -int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) -int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) -int crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) -int crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -#define crypto_sign SPX_NAMESPACE(crypto_sign) -int crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) -int crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/params.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/params.h deleted file mode 100644 index 8be4f22f30..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/params.h +++ /dev/null @@ -1,56 +0,0 @@ -#ifndef SPX_PARAMS_H -#define SPX_PARAMS_H - -#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSSHAKE128FROBUST_CLEAN_##s - -/* Hash output length in bytes. */ -#define SPX_N 16 -/* Height of the hypertree. */ -#define SPX_FULL_HEIGHT 66 -/* Number of subtree layer. */ -#define SPX_D 22 -/* FORS tree dimensions. */ -#define SPX_FORS_HEIGHT 6 -#define SPX_FORS_TREES 33 -/* Winternitz parameter, */ -#define SPX_WOTS_W 16 - -/* The hash function is defined by linking a different hash.c file, as opposed - to setting a #define constant. */ - -/* For clarity */ -#define SPX_ADDR_BYTES 32 - -/* WOTS parameters. */ -#define SPX_WOTS_LOGW 4 - -#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) - -/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#define SPX_WOTS_LEN2 3 - -#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) -#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) -#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES - -/* Subtree size. */ -#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) - -//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT -// #error SPX_D should always divide SPX_FULL_HEIGHT -//#endif - -/* FORS parameters. */ -#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) -#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) -#define SPX_FORS_PK_BYTES SPX_N - -/* Resulting SPX sizes. */ -#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ - SPX_FULL_HEIGHT * SPX_N) -#define SPX_PK_BYTES (2 * SPX_N) -#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) - -#include "shake_offsets.h" - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/shake_offsets.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/shake_offsets.h deleted file mode 100644 index 6b28d95d91..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/shake_offsets.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef SHAKE_OFFSETS_H_ -#define SHAKE_OFFSETS_H_ - -/* - * Offsets of various fields in the address structure when we use SHAKE as - * the Sphincs+ hash function - */ - -#define SPX_OFFSET_LAYER 3 /* The byte used to specify the Merkle tree layer */ -#define SPX_OFFSET_TREE 8 /* The start of the 8 byte field used to specify the tree */ -#define SPX_OFFSET_TYPE 19 /* The byte used to specify the hash type (reason) */ -#define SPX_OFFSET_KP_ADDR2 22 /* The high byte used to specify the key pair (which one-time signature) */ -#define SPX_OFFSET_KP_ADDR1 23 /* The low byte used to specify the key pair */ -#define SPX_OFFSET_CHAIN_ADDR 27 /* The byte used to specify the chain address (which Winternitz chain) */ -#define SPX_OFFSET_HASH_ADDR 31 /* The byte used to specify the hash address (where in the Winternitz chain) */ -#define SPX_OFFSET_TREE_HGT 27 /* The byte used to specify the height of this node in the FORS or Merkle tree */ -#define SPX_OFFSET_TREE_INDEX 28 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ - -#define SPX_SHAKE 1 - -#endif /* SHAKE_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/sign.c b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/sign.c deleted file mode 100644 index 9d0c7d1b22..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/sign.c +++ /dev/null @@ -1,286 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "context.h" -#include "fors.h" -#include "hash.h" -#include "merkle.h" -#include "nistapi.h" -#include "params.h" -#include "randombytes.h" -#include "thash.h" -#include "utils.h" -#include "wots.h" - -/* - * Returns the length of a secret key, in bytes - */ -size_t crypto_sign_secretkeybytes(void) { - return CRYPTO_SECRETKEYBYTES; -} - -/* - * Returns the length of a public key, in bytes - */ -size_t crypto_sign_publickeybytes(void) { - return CRYPTO_PUBLICKEYBYTES; -} - -/* - * Returns the length of a signature, in bytes - */ -size_t crypto_sign_bytes(void) { - return CRYPTO_BYTES; -} - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t crypto_sign_seedbytes(void) { - return CRYPTO_SEEDBYTES; -} - -/* - * Generates an SPX key pair given a seed of length - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed) { - spx_ctx ctx; - - /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ - memcpy(sk, seed, CRYPTO_SEEDBYTES); - - memcpy(pk, sk + 2 * SPX_N, SPX_N); - - memcpy(ctx.pub_seed, pk, SPX_N); - memcpy(ctx.sk_seed, sk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - /* Compute root node of the top-most subtree. */ - merkle_gen_root(sk + 3 * SPX_N, &ctx); - - // cleanup - free_hash_function(&ctx); - - memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); - - return 0; -} - -/* - * Generates an SPX key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { - uint8_t seed[CRYPTO_SEEDBYTES]; - randombytes(seed, CRYPTO_SEEDBYTES); - crypto_sign_seed_keypair(pk, sk, seed); - - return 0; -} - -/** - * Returns an array containing a detached signature. - */ -int crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - spx_ctx ctx; - - const uint8_t *sk_prf = sk + SPX_N; - const uint8_t *pk = sk + 2 * SPX_N; - - uint8_t optrand[SPX_N]; - uint8_t mhash[SPX_FORS_MSG_BYTES]; - uint8_t root[SPX_N]; - uint32_t i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - - memcpy(ctx.sk_seed, sk, SPX_N); - memcpy(ctx.pub_seed, pk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - set_type(wots_addr, SPX_ADDR_TYPE_WOTS); - set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); - - /* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ - randombytes(optrand, SPX_N); - /* Compute the digest randomization value. */ - gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); - - /* Derive the message digest and leaf index from R, PK and M. */ - hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); - sig += SPX_N; - - set_tree_addr(wots_addr, tree); - set_keypair_addr(wots_addr, idx_leaf); - - /* Sign the message hash using FORS. */ - fors_sign(sig, root, mhash, &ctx, wots_addr); - sig += SPX_FORS_BYTES; - - for (i = 0; i < SPX_D; i++) { - set_layer_addr(tree_addr, i); - set_tree_addr(tree_addr, tree); - - copy_subtree_addr(wots_addr, tree_addr); - set_keypair_addr(wots_addr, idx_leaf); - - merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); - sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); - tree = tree >> SPX_TREE_HEIGHT; - } - - free_hash_function(&ctx); - - *siglen = SPX_BYTES; - - return 0; -} - -/** - * Verifies a detached signature and message under a given public key. - */ -int crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk) { - spx_ctx ctx; - const uint8_t *pub_root = pk + SPX_N; - uint8_t mhash[SPX_FORS_MSG_BYTES]; - uint8_t wots_pk[SPX_WOTS_BYTES]; - uint8_t root[SPX_N]; - uint8_t leaf[SPX_N]; - unsigned int i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - if (siglen != SPX_BYTES) { - return -1; - } - - memcpy(ctx.pub_seed, pk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - set_type(wots_addr, SPX_ADDR_TYPE_WOTS); - set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); - set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); - - /* Derive the message digest and leaf index from R || PK || M. */ - /* The additional SPX_N is a result of the hash domain separator. */ - hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); - sig += SPX_N; - - /* Layer correctly defaults to 0, so no need to set_layer_addr */ - set_tree_addr(wots_addr, tree); - set_keypair_addr(wots_addr, idx_leaf); - - fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); - sig += SPX_FORS_BYTES; - - /* For each subtree.. */ - for (i = 0; i < SPX_D; i++) { - set_layer_addr(tree_addr, i); - set_tree_addr(tree_addr, tree); - - copy_subtree_addr(wots_addr, tree_addr); - set_keypair_addr(wots_addr, idx_leaf); - - copy_keypair_addr(wots_pk_addr, wots_addr); - - /* The WOTS public key is only correct if the signature was correct. */ - /* Initially, root is the FORS pk, but on subsequent iterations it is - the root of the subtree below the currently processed subtree. */ - wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); - sig += SPX_WOTS_BYTES; - - /* Compute the leaf node using the WOTS public key. */ - thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); - - /* Compute the root node of this subtree. */ - compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, - &ctx, tree_addr); - sig += SPX_TREE_HEIGHT * SPX_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); - tree = tree >> SPX_TREE_HEIGHT; - } - - // cleanup - free_hash_function(&ctx); - - /* Check if the root node equals the root node in the public key. */ - if (memcmp(root, pub_root, SPX_N) != 0) { - return -1; - } - - return 0; -} - - -/** - * Returns an array containing the signature followed by the message. - */ -int crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk) { - size_t siglen; - - crypto_sign_signature(sm, &siglen, m, mlen, sk); - - memmove(sm + SPX_BYTES, m, mlen); - *smlen = siglen + mlen; - - return 0; -} - -/** - * Verifies a given signature-message pair under a given public key. - */ -int crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk) { - /* The API caller does not necessarily know what size a signature should be - but SPHINCS+ signatures are always exactly SPX_BYTES. */ - if (smlen < SPX_BYTES) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - *mlen = smlen - SPX_BYTES; - - if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - /* If verification was successful, move the message to the right place. */ - memmove(m, sm + SPX_BYTES, *mlen); - - return 0; -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/thash.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/thash.h deleted file mode 100644 index 8687ccfb4d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/thash.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef SPX_THASH_H -#define SPX_THASH_H - -#include "context.h" -#include "params.h" - -#include - -#define thash SPX_NAMESPACE(thash) -void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/thash_shake_robust.c b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/thash_shake_robust.c deleted file mode 100644 index 696d53c5cc..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/thash_shake_robust.c +++ /dev/null @@ -1,31 +0,0 @@ -#include -#include - -#include "thash.h" - -#include "address.h" -#include "params.h" -#include "utils.h" - -#include "fips202.h" - -/** - * Takes an array of inblocks concatenated arrays of SPX_N bytes. - */ -void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]) { - PQCLEAN_VLA(uint8_t, buf, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); - PQCLEAN_VLA(uint8_t, bitmask, inblocks * SPX_N); - unsigned int i; - - memcpy(buf, ctx->pub_seed, SPX_N); - memcpy(buf + SPX_N, addr, SPX_ADDR_BYTES); - - shake256(bitmask, inblocks * SPX_N, buf, SPX_N + SPX_ADDR_BYTES); - - for (i = 0; i < inblocks * SPX_N; i++) { - buf[SPX_N + SPX_ADDR_BYTES + i] = in[i] ^ bitmask[i]; - } - - shake256(out, SPX_N, buf, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/utils.c b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/utils.c deleted file mode 100644 index 177b541fb9..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/utils.c +++ /dev/null @@ -1,148 +0,0 @@ -#include - -#include "utils.h" - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "thash.h" - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void ull_to_bytes(unsigned char *out, unsigned int outlen, - unsigned long long in) { - int i; - - /* Iterate over out in decreasing order, for big-endianness. */ - for (i = (signed int)outlen - 1; i >= 0; i--) { - out[i] = in & 0xff; - in = in >> 8; - } -} - -void u32_to_bytes(unsigned char *out, uint32_t in) { - out[0] = (unsigned char)(in >> 24); - out[1] = (unsigned char)(in >> 16); - out[2] = (unsigned char)(in >> 8); - out[3] = (unsigned char)in; -} - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { - unsigned long long retval = 0; - unsigned int i; - - for (i = 0; i < inlen; i++) { - retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); - } - return retval; -} - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void compute_root(unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const spx_ctx *ctx, uint32_t addr[8]) { - uint32_t i; - unsigned char buffer[2 * SPX_N]; - - /* If leaf_idx is odd (last bit = 1), current path element is a right child - and auth_path has to go left. Otherwise it is the other way around. */ - if (leaf_idx & 1) { - memcpy(buffer + SPX_N, leaf, SPX_N); - memcpy(buffer, auth_path, SPX_N); - } else { - memcpy(buffer, leaf, SPX_N); - memcpy(buffer + SPX_N, auth_path, SPX_N); - } - auth_path += SPX_N; - - for (i = 0; i < tree_height - 1; i++) { - leaf_idx >>= 1; - idx_offset >>= 1; - /* Set the address of the node we're creating. */ - set_tree_height(addr, i + 1); - set_tree_index(addr, leaf_idx + idx_offset); - - /* Pick the right or left neighbor, depending on parity of the node. */ - if (leaf_idx & 1) { - thash(buffer + SPX_N, buffer, 2, ctx, addr); - memcpy(buffer, auth_path, SPX_N); - } else { - thash(buffer, buffer, 2, ctx, addr); - memcpy(buffer + SPX_N, auth_path, SPX_N); - } - auth_path += SPX_N; - } - - /* The last iteration is exceptional; we do not copy an auth_path node. */ - leaf_idx >>= 1; - idx_offset >>= 1; - set_tree_height(addr, tree_height); - set_tree_index(addr, leaf_idx + idx_offset); - thash(root, buffer, 2, ctx, addr); -} - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const spx_ctx * /* ctx */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), - uint32_t tree_addr[8]) { - PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); - PQCLEAN_VLA(unsigned int, heights, tree_height + 1); - unsigned int offset = 0; - uint32_t idx; - uint32_t tree_idx; - - for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { - /* Add the next leaf node to the stack. */ - gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); - offset++; - heights[offset - 1] = 0; - - /* If this is a node we need for the auth path.. */ - if ((leaf_idx ^ 0x1) == idx) { - memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); - } - - /* While the top-most nodes are of equal height.. */ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { - /* Compute index of the new node, in the next layer. */ - tree_idx = (idx >> (heights[offset - 1] + 1)); - - /* Set the address of the node we're creating. */ - set_tree_height(tree_addr, heights[offset - 1] + 1); - set_tree_index(tree_addr, - tree_idx + (idx_offset >> (heights[offset - 1] + 1))); - /* Hash the top-most nodes from the stack together. */ - thash(stack + (offset - 2)*SPX_N, - stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); - offset--; - /* Note that the top-most node is now one layer higher. */ - heights[offset - 1]++; - - /* If this is a node we need for the auth path.. */ - if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_path + heights[offset - 1]*SPX_N, - stack + (offset - 1)*SPX_N, SPX_N); - } - } - } - memcpy(root, stack, SPX_N); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/utils.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/utils.h deleted file mode 100644 index 64f5d5a53a..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/utils.h +++ /dev/null @@ -1,58 +0,0 @@ -#ifndef SPX_UTILS_H -#define SPX_UTILS_H - -#include - -#include "compat.h" -#include "context.h" -#include "params.h" - - -/* To support MSVC use alloca() instead of VLAs. See #20. */ - - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) -void ull_to_bytes(unsigned char *out, unsigned int outlen, - unsigned long long in); -#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) -void u32_to_bytes(unsigned char *out, uint32_t in); - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) -unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -#define compute_root SPX_NAMESPACE(compute_root) -void compute_root(unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const spx_ctx *ctx, uint32_t addr[8]); - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -#define treehash SPX_NAMESPACE(treehash) -void treehash(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const spx_ctx *ctx /* ctx */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), - uint32_t tree_addr[8]); - - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/utilsx1.c b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/utilsx1.c deleted file mode 100644 index fccb69b35d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/utilsx1.c +++ /dev/null @@ -1,100 +0,0 @@ -#include - -#include "utilsx1.h" - -#include "address.h" -#include "params.h" -#include "thash.h" -#include "utils.h" - -/* - * Generate the entire Merkle tree, computing the authentication path for - * leaf_idx, and the resulting root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) - * - * This expects tree_addr to be initialized to the addr structures for the - * Merkle tree nodes - * - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - * - * This works by using the standard Merkle tree building algorithm, - */ -void treehashx1(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, - uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* Where to write the leaves */, - const spx_ctx * /* ctx */, - uint32_t idx, void *info), - uint32_t tree_addr[8], - void *info) { - /* This is where we keep the intermediate nodes */ - PQCLEAN_VLA(uint8_t, stack, tree_height * SPX_N); - - uint32_t idx; - uint32_t max_idx = (uint32_t)((1 << tree_height) - 1); - for (idx = 0;; idx++) { - unsigned char current[2 * SPX_N]; /* Current logical node is at */ - /* index[SPX_N]. We do this to minimize the number of copies */ - /* needed during a thash */ - gen_leaf( ¤t[SPX_N], ctx, idx + idx_offset, - info ); - - /* Now combine the freshly generated right node with previously */ - /* generated left ones */ - uint32_t internal_idx_offset = idx_offset; - uint32_t internal_idx = idx; - uint32_t internal_leaf = leaf_idx; - uint32_t h; /* The height we are in the Merkle tree */ - for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { - - /* Check if we hit the top of the tree */ - if (h == tree_height) { - /* We hit the root; return it */ - memcpy( root, ¤t[SPX_N], SPX_N ); - return; - } - - /* - * Check if the node we have is a part of the - * authentication path; if it is, write it out - */ - if ((internal_idx ^ internal_leaf) == 0x01) { - memcpy( &auth_path[ h * SPX_N ], - ¤t[SPX_N], - SPX_N ); - } - - /* - * Check if we're at a left child; if so, stop going up the stack - * Exception: if we've reached the end of the tree, keep on going - * (so we combine the last 4 nodes into the one root node in two - * more iterations) - */ - if ((internal_idx & 1) == 0 && idx < max_idx) { - break; - } - - /* Ok, we're at a right node */ - /* Now combine the left and right logical nodes together */ - - /* Set the address of the node we're creating. */ - internal_idx_offset >>= 1; - set_tree_height(tree_addr, h + 1); - set_tree_index(tree_addr, internal_idx / 2 + internal_idx_offset ); - - unsigned char *left = &stack[h * SPX_N]; - memcpy( ¤t[0], left, SPX_N ); - thash( ¤t[1 * SPX_N], - ¤t[0 * SPX_N], - 2, ctx, tree_addr); - } - - /* We've hit a left child; save the current for when we get the */ - /* corresponding right right */ - memcpy( &stack[h * SPX_N], ¤t[SPX_N], SPX_N); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/utilsx1.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/utilsx1.h deleted file mode 100644 index e911d17d53..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/utilsx1.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef SPX_UTILSX4_H -#define SPX_UTILSX4_H - -#include - -#include "context.h" -#include "params.h" - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -#define treehashx1 SPX_NAMESPACE(treehashx1) -void treehashx1(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* Where to write the leaf */, - const spx_ctx * /* ctx */, - uint32_t addr_idx, void *info), - uint32_t tree_addrx4[8], void *info); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/wots.c b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/wots.c deleted file mode 100644 index 249717aaa8..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/wots.c +++ /dev/null @@ -1,108 +0,0 @@ -#include -#include - -#include "wots.h" -#include "wotsx1.h" - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "thash.h" -#include "utils.h" -#include "utilsx1.h" - -// TODO clarify address expectations, and make them more uniform. -// TODO i.e. do we expect types to be set already? -// TODO and do we expect modifications or copies? - -/** - * Computes the chaining function. - * out and in have to be n-byte arrays. - * - * Interprets in as start-th value of the chain. - * addr has to contain the address of the chain. - */ -static void gen_chain(unsigned char *out, const unsigned char *in, - unsigned int start, unsigned int steps, - const spx_ctx *ctx, uint32_t addr[8]) { - uint32_t i; - - /* Initialize out with the value at position 'start'. */ - memcpy(out, in, SPX_N); - - /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < SPX_WOTS_W; i++) { - set_hash_addr(addr, i); - thash(out, out, 1, ctx, addr); - } -} - -/** - * base_w algorithm as described in draft. - * Interprets an array of bytes as integers in base w. - * This only works when log_w is a divisor of 8. - */ -static void base_w(unsigned int *output, const int out_len, - const unsigned char *input) { - int in = 0; - int out = 0; - unsigned char total = 0; - int bits = 0; - int consumed; - - for (consumed = 0; consumed < out_len; consumed++) { - if (bits == 0) { - total = input[in]; - in++; - bits += 8; - } - bits -= SPX_WOTS_LOGW; - output[out] = (total >> bits) & (SPX_WOTS_W - 1); - out++; - } -} - -/* Computes the WOTS+ checksum over a message (in base_w). */ -static void wots_checksum(unsigned int *csum_base_w, - const unsigned int *msg_base_w) { - unsigned int csum = 0; - unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; - unsigned int i; - - /* Compute checksum. */ - for (i = 0; i < SPX_WOTS_LEN1; i++) { - csum += SPX_WOTS_W - 1 - msg_base_w[i]; - } - - /* Convert checksum to base_w. */ - /* Make sure expected empty zero bits are the least significant bits. */ - csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); - ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); - base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); -} - -/* Takes a message and derives the matching chain lengths. */ -void chain_lengths(unsigned int *lengths, const unsigned char *msg) { - base_w(lengths, SPX_WOTS_LEN1, msg); - wots_checksum(lengths + SPX_WOTS_LEN1, lengths); -} - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const spx_ctx *ctx, uint32_t addr[8]) { - unsigned int lengths[SPX_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < SPX_WOTS_LEN; i++) { - set_chain_addr(addr, i); - gen_chain(pk + i * SPX_N, sig + i * SPX_N, - lengths[i], SPX_WOTS_W - 1 - lengths[i], ctx, addr); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/wots.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/wots.h deleted file mode 100644 index 4e7692eeef..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/wots.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef SPX_WOTS_H -#define SPX_WOTS_H - -#include - -#include "context.h" -#include "params.h" - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) -void wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const spx_ctx *ctx, uint32_t addr[8]); - -/* - * Compute the chain lengths needed for a given message hash - */ -#define chain_lengths SPX_NAMESPACE(chain_lengths) -void chain_lengths(unsigned int *lengths, const unsigned char *msg); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/wotsx1.c b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/wotsx1.c deleted file mode 100644 index 3adec78dfb..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/wotsx1.c +++ /dev/null @@ -1,76 +0,0 @@ -#include -#include - -#include "wots.h" -#include "wotsx1.h" - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "thash.h" -#include "utils.h" - -/* - * This generates a WOTS public key - * It also generates the WOTS signature if leaf_info indicates - * that we're signing with this WOTS key - */ -void wots_gen_leafx1(unsigned char *dest, - const spx_ctx *ctx, - uint32_t leaf_idx, void *v_info) { - struct leaf_info_x1 *info = v_info; - uint32_t *leaf_addr = info->leaf_addr; - uint32_t *pk_addr = info->pk_addr; - unsigned int i, k; - unsigned char pk_buffer[ SPX_WOTS_BYTES ]; - unsigned char *buffer; - uint32_t wots_k_mask; - - if (leaf_idx == info->wots_sign_leaf) { - /* We're traversing the leaf that's signing; generate the WOTS */ - /* signature */ - wots_k_mask = 0; - } else { - /* Nope, we're just generating pk's; turn off the signature logic */ - wots_k_mask = (uint32_t)~0; - } - - set_keypair_addr( leaf_addr, leaf_idx ); - set_keypair_addr( pk_addr, leaf_idx ); - - for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { - uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k to */ - /* the step if we're generating a signature, ~0 if we're not */ - - /* Start with the secret seed */ - set_chain_addr(leaf_addr, i); - set_hash_addr(leaf_addr, 0); - set_type(leaf_addr, SPX_ADDR_TYPE_WOTSPRF); - - prf_addr(buffer, ctx, leaf_addr); - - set_type(leaf_addr, SPX_ADDR_TYPE_WOTS); - - /* Iterate down the WOTS chain */ - for (k = 0;; k++) { - /* Check if this is the value that needs to be saved as a */ - /* part of the WOTS signature */ - if (k == wots_k) { - memcpy( info->wots_sig + i * SPX_N, buffer, SPX_N ); - } - - /* Check if we hit the top of the chain */ - if (k == SPX_WOTS_W - 1) { - break; - } - - /* Iterate one step on the chain */ - set_hash_addr(leaf_addr, k); - - thash(buffer, buffer, 1, ctx, leaf_addr); - } - } - - /* Do the final thash to generate the public keys */ - thash(dest, pk_buffer, SPX_WOTS_LEN, ctx, pk_addr); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/wotsx1.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/wotsx1.h deleted file mode 100644 index e617929f96..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128f-robust_clean/wotsx1.h +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef WOTSX1_H_ -#define WOTSX1_H_ - -#include - -#include "context.h" -#include "params.h" - -/* - * This is here to provide an interface to the internal wots_gen_leafx1 - * routine. While this routine is not referenced in the package outside of - * wots.c, it is called from the stand-alone benchmark code to characterize - * the performance - */ -struct leaf_info_x1 { - unsigned char *wots_sig; - uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ - uint32_t *wots_steps; - uint32_t leaf_addr[8]; - uint32_t pk_addr[8]; -}; - -/* Macro to set the leaf_info to something 'benign', that is, it would */ -/* run with the same time as it does during the real signing process */ -/* Used only by the benchmark code */ -#define INITIALIZE_LEAF_INFO_X1(info, addr, step_buffer) { \ - (info).wots_sig = 0; \ - (info).wots_sign_leaf = ~0; \ - (info).wots_steps = step_buffer; \ - memcpy( &(info).leaf_addr[0], (addr), 32 ); \ - memcpy( &(info).pk_addr[0], (addr), 32 ); \ - } - -#define wots_gen_leafx1 SPX_NAMESPACE(wots_gen_leafx1) -void wots_gen_leafx1(unsigned char *dest, - const spx_ctx *ctx, - uint32_t leaf_idx, void *v_info); - -#endif /* WOTSX1_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/LICENSE b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/LICENSE deleted file mode 100644 index 670154e353..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/LICENSE +++ /dev/null @@ -1,116 +0,0 @@ -CC0 1.0 Universal - -Statement of Purpose - -The laws of most jurisdictions throughout the world automatically confer -exclusive Copyright and Related Rights (defined below) upon the creator and -subsequent owner(s) (each and all, an "owner") of an original work of -authorship and/or a database (each, a "Work"). - -Certain owners wish to permanently relinquish those rights to a Work for the -purpose of contributing to a commons of creative, cultural and scientific -works ("Commons") that the public can reliably and without fear of later -claims of infringement build upon, modify, incorporate in other works, reuse -and redistribute as freely as possible in any form whatsoever and for any -purposes, including without limitation commercial purposes. These owners may -contribute to the Commons to promote the ideal of a free culture and the -further production of creative, cultural and scientific works, or to gain -reputation or greater distribution for their Work in part through the use and -efforts of others. - -For these and/or other purposes and motivations, and without any expectation -of additional consideration or compensation, the person associating CC0 with a -Work (the "Affirmer"), to the extent that he or she is an owner of Copyright -and Related Rights in the Work, voluntarily elects to apply CC0 to the Work -and publicly distribute the Work under its terms, with knowledge of his or her -Copyright and Related Rights in the Work and the meaning and intended legal -effect of CC0 on those rights. - -1. Copyright and Related Rights. A Work made available under CC0 may be -protected by copyright and related or neighboring rights ("Copyright and -Related Rights"). Copyright and Related Rights include, but are not limited -to, the following: - - i. the right to reproduce, adapt, distribute, perform, display, communicate, - and translate a Work; - - ii. moral rights retained by the original author(s) and/or performer(s); - - iii. publicity and privacy rights pertaining to a person's image or likeness - depicted in a Work; - - iv. rights protecting against unfair competition in regards to a Work, - subject to the limitations in paragraph 4(a), below; - - v. rights protecting the extraction, dissemination, use and reuse of data in - a Work; - - vi. database rights (such as those arising under Directive 96/9/EC of the - European Parliament and of the Council of 11 March 1996 on the legal - protection of databases, and under any national implementation thereof, - including any amended or successor version of such directive); and - - vii. other similar, equivalent or corresponding rights throughout the world - based on applicable law or treaty, and any national implementations thereof. - -2. Waiver. To the greatest extent permitted by, but not in contravention of, -applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and -unconditionally waives, abandons, and surrenders all of Affirmer's Copyright -and Related Rights and associated claims and causes of action, whether now -known or unknown (including existing as well as future claims and causes of -action), in the Work (i) in all territories worldwide, (ii) for the maximum -duration provided by applicable law or treaty (including future time -extensions), (iii) in any current or future medium and for any number of -copies, and (iv) for any purpose whatsoever, including without limitation -commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes -the Waiver for the benefit of each member of the public at large and to the -detriment of Affirmer's heirs and successors, fully intending that such Waiver -shall not be subject to revocation, rescission, cancellation, termination, or -any other legal or equitable action to disrupt the quiet enjoyment of the Work -by the public as contemplated by Affirmer's express Statement of Purpose. - -3. Public License Fallback. Should any part of the Waiver for any reason be -judged legally invalid or ineffective under applicable law, then the Waiver -shall be preserved to the maximum extent permitted taking into account -Affirmer's express Statement of Purpose. In addition, to the extent the Waiver -is so judged Affirmer hereby grants to each affected person a royalty-free, -non transferable, non sublicensable, non exclusive, irrevocable and -unconditional license to exercise Affirmer's Copyright and Related Rights in -the Work (i) in all territories worldwide, (ii) for the maximum duration -provided by applicable law or treaty (including future time extensions), (iii) -in any current or future medium and for any number of copies, and (iv) for any -purpose whatsoever, including without limitation commercial, advertising or -promotional purposes (the "License"). The License shall be deemed effective as -of the date CC0 was applied by Affirmer to the Work. Should any part of the -License for any reason be judged legally invalid or ineffective under -applicable law, such partial invalidity or ineffectiveness shall not -invalidate the remainder of the License, and in such case Affirmer hereby -affirms that he or she will not (i) exercise any of his or her remaining -Copyright and Related Rights in the Work or (ii) assert any associated claims -and causes of action with respect to the Work, in either case contrary to -Affirmer's express Statement of Purpose. - -4. Limitations and Disclaimers. - - a. No trademark or patent rights held by Affirmer are waived, abandoned, - surrendered, licensed or otherwise affected by this document. - - b. Affirmer offers the Work as-is and makes no representations or warranties - of any kind concerning the Work, express, implied, statutory or otherwise, - including without limitation warranties of title, merchantability, fitness - for a particular purpose, non infringement, or the absence of latent or - other defects, accuracy, or the present or absence of errors, whether or not - discoverable, all to the greatest extent permissible under applicable law. - - c. Affirmer disclaims responsibility for clearing rights of other persons - that may apply to the Work or any use thereof, including without limitation - any person's Copyright and Related Rights in the Work. Further, Affirmer - disclaims responsibility for obtaining any necessary consents, permissions - or other rights required for any use of the Work. - - d. Affirmer understands and acknowledges that Creative Commons is not a - party to this document and has no duty or obligation with respect to this - CC0 or use of the Work. - -For more information, please see - diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/address.c b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/address.c deleted file mode 100644 index d49d9f3b6b..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/address.c +++ /dev/null @@ -1,95 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "utils.h" - -/* - * Specify which level of Merkle tree (the "layer") we're working on - */ -void set_layer_addr(uint32_t addr[8], uint32_t layer) { - ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; -} - -/* - * Specify which Merkle tree within the level (the "tree address") we're working on - */ -void set_tree_addr(uint32_t addr[8], uint64_t tree) { - ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); -} - -/* - * Specify the reason we'll use this address structure for, that is, what - * hash will we compute with it. This is used so that unrelated types of - * hashes don't accidentally get the same address structure. The type will be - * one of the SPX_ADDR_TYPE constants - */ -void set_type(uint32_t addr[8], uint32_t type) { - ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; -} - -/* - * Copy the layer and tree fields of the address structure. This is used - * when we're doing multiple types of hashes within the same Merkle tree - */ -void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { - memcpy( out, in, SPX_OFFSET_TREE + 8 ); -} - -/* These functions are used for OTS addresses. */ - -/* - * Specify which Merkle leaf we're working on; that is, which OTS keypair - * we're talking about. - */ -void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { - /* We have > 256 OTS at the bottom of the Merkle tree; to specify */ - /* which one, we'd need to express it in two bytes */ - ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR2] = (unsigned char)(keypair >> 8); - ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; -} - -/* - * Copy the layer, tree and keypair fields of the address structure. This is - * used when we're doing multiple things within the same OTS keypair - */ -void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { - memcpy( out, in, SPX_OFFSET_TREE + 8 ); - ((unsigned char *)out)[SPX_OFFSET_KP_ADDR2] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR2]; - ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; -} - -/* - * Specify which Merkle chain within the OTS we're working with - * (the chain address) - */ -void set_chain_addr(uint32_t addr[8], uint32_t chain) { - ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; -} - -/* - * Specify where in the Merkle chain we are -* (the hash address) - */ -void set_hash_addr(uint32_t addr[8], uint32_t hash) { - ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; -} - -/* These functions are used for all hash tree addresses (including FORS). */ - -/* - * Specify the height of the node in the Merkle/FORS tree we are in - * (the tree height) - */ -void set_tree_height(uint32_t addr[8], uint32_t tree_height) { - ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; -} - -/* - * Specify the distance from the left edge of the node in the Merkle/FORS tree - * (the tree index) - */ -void set_tree_index(uint32_t addr[8], uint32_t tree_index) { - u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/address.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/address.h deleted file mode 100644 index 24a84eb40c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/address.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef SPX_ADDRESS_H -#define SPX_ADDRESS_H - -#include - -#include "params.h" - -/* The hash types that are passed to set_type */ -#define SPX_ADDR_TYPE_WOTS 0 -#define SPX_ADDR_TYPE_WOTSPK 1 -#define SPX_ADDR_TYPE_HASHTREE 2 -#define SPX_ADDR_TYPE_FORSTREE 3 -#define SPX_ADDR_TYPE_FORSPK 4 -#define SPX_ADDR_TYPE_WOTSPRF 5 -#define SPX_ADDR_TYPE_FORSPRF 6 - -#define set_layer_addr SPX_NAMESPACE(set_layer_addr) -void set_layer_addr(uint32_t addr[8], uint32_t layer); - -#define set_tree_addr SPX_NAMESPACE(set_tree_addr) -void set_tree_addr(uint32_t addr[8], uint64_t tree); - -#define set_type SPX_NAMESPACE(set_type) -void set_type(uint32_t addr[8], uint32_t type); - -/* Copies the layer and tree part of one address into the other */ -#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) -void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for WOTS and FORS addresses. */ - -#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) -void set_keypair_addr(uint32_t addr[8], uint32_t keypair); - -#define set_chain_addr SPX_NAMESPACE(set_chain_addr) -void set_chain_addr(uint32_t addr[8], uint32_t chain); - -#define set_hash_addr SPX_NAMESPACE(set_hash_addr) -void set_hash_addr(uint32_t addr[8], uint32_t hash); - -#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) -void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for all hash tree addresses (including FORS). */ - -#define set_tree_height SPX_NAMESPACE(set_tree_height) -void set_tree_height(uint32_t addr[8], uint32_t tree_height); - -#define set_tree_index SPX_NAMESPACE(set_tree_index) -void set_tree_index(uint32_t addr[8], uint32_t tree_index); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/api.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/api.h deleted file mode 100644 index dcdc028fb5..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/api.h +++ /dev/null @@ -1,77 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE128SROBUST_AARCH64_API_H -#define PQCLEAN_SPHINCSSHAKE128SROBUST_AARCH64_API_H - -#include -#include - -#define PQCLEAN_SPHINCSSHAKE128SROBUST_AARCH64_CRYPTO_ALGNAME "SPHINCS+-shake-128s-robust" - -#define PQCLEAN_SPHINCSSHAKE128SROBUST_AARCH64_CRYPTO_SECRETKEYBYTES 64 -#define PQCLEAN_SPHINCSSHAKE128SROBUST_AARCH64_CRYPTO_PUBLICKEYBYTES 32 -#define PQCLEAN_SPHINCSSHAKE128SROBUST_AARCH64_CRYPTO_BYTES 7856 - -#define PQCLEAN_SPHINCSSHAKE128SROBUST_AARCH64_CRYPTO_SEEDBYTES 48 - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE128SROBUST_AARCH64_crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE128SROBUST_AARCH64_crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE128SROBUST_AARCH64_crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE128SROBUST_AARCH64_crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHAKE128SROBUST_AARCH64_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHAKE128SROBUST_AARCH64_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSSHAKE128SROBUST_AARCH64_crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE128SROBUST_AARCH64_crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, - const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSSHAKE128SROBUST_AARCH64_crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE128SROBUST_AARCH64_crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk); -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/context.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/context.h deleted file mode 100644 index 6e0a33f3b7..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/context.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef SPX_CONTEXT_H -#define SPX_CONTEXT_H - -#include - -#include "params.h" - -typedef struct { - uint8_t pub_seed[SPX_N]; - uint8_t sk_seed[SPX_N]; -} spx_ctx; - -#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) -void initialize_hash_function(spx_ctx *ctx); - -#define free_hash_function SPX_NAMESPACE(free_hash_function) -void free_hash_function(spx_ctx *ctx); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/context_shake.c b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/context_shake.c deleted file mode 100644 index 9614a103d3..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/context_shake.c +++ /dev/null @@ -1,12 +0,0 @@ -#include "context.h" - -/* For SHAKE256, there is no immediate reason to initialize at the start, - so this function is an empty operation. */ -void initialize_hash_function(spx_ctx *ctx) { - (void)ctx; /* Suppress an 'unused parameter' warning. */ -} - -// in case the hash function api is heap-based. -void free_hash_function(spx_ctx *ctx) { - (void)ctx; -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/f1600x2.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/f1600x2.h deleted file mode 100644 index 70d1af9f14..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/f1600x2.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef SPX_F1600X2_H -#define SPX_F1600X2_H - -#include - -extern uint64_t f1600_RC[24]; -extern void _f1600x2(uint64_t *a, uint64_t *rc); - -#define f1600x2(s) do {_f1600x2((s), f1600_RC);} while(0) - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/f1600x2.s b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/f1600x2.s deleted file mode 100644 index 640ed791ed..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/f1600x2.s +++ /dev/null @@ -1,143 +0,0 @@ -# From https://github.com/bwesterb/armed-keccak - -.macro round - # Execute theta, but without xoring into the state yet. - # Compute parities p[i] = a[i] ^ a[5+i] ^ ... ^ a[20+i]. - eor3.16b v25, v0, v5, v10 - eor3.16b v26, v1, v6, v11 - eor3.16b v27, v2, v7, v12 - eor3.16b v28, v3, v8, v13 - eor3.16b v29, v4, v9, v14 - - eor3.16b v25, v25, v15, v20 - eor3.16b v26, v26, v16, v21 - eor3.16b v27, v27, v17, v22 - eor3.16b v28, v28, v18, v23 - eor3.16b v29, v29, v19, v24 - - # d[0] = rotl(p[1], 1) ^ p[4] - rax1.2d v30, v29, v26 - # d[3] = rotl(p[4], 1) ^ p[2] - rax1.2d v29, v27, v29 - # d[1] = rotl(p[2], 1) ^ p[0] - rax1.2d v27, v25, v27 - # d[4] = rotl(p[0], 1) ^ p[3] - rax1.2d v25, v28, v25 - # d[2] = rotl(p[3], 1) ^ p[1] - rax1.2d v28, v26, v28 - - # Xor parities from step theta into the state at the same time - # as executing rho and pi. - eor.16b v0, v0, v30 - mov.16b v31, v1 - xar.2d v1, v6, v27, 20 - xar.2d v6, v9, v25, 44 - xar.2d v9, v22, v28, 3 - xar.2d v22, v14, v25, 25 - xar.2d v14, v20, v30, 46 - xar.2d v20, v2, v28, 2 - xar.2d v2, v12, v28, 21 - xar.2d v12, v13, v29, 39 - xar.2d v13, v19, v25, 56 - xar.2d v19, v23, v29, 8 - xar.2d v23, v15, v30, 23 - xar.2d v15, v4, v25, 37 - xar.2d v4, v24, v25, 50 - xar.2d v24, v21, v27, 62 - xar.2d v21, v8, v29, 9 - xar.2d v8, v16, v27, 19 - xar.2d v16, v5, v30, 28 - xar.2d v5, v3, v29, 36 - xar.2d v3, v18, v29, 43 - xar.2d v18, v17, v28, 49 - xar.2d v17, v11, v27, 54 - xar.2d v11, v7, v28, 58 - xar.2d v7, v10, v30, 61 - xar.2d v10, v31, v27, 63 - - # Chi - bcax.16b v25, v0, v2, v1 - bcax.16b v26, v1, v3, v2 - bcax.16b v2, v2, v4, v3 - bcax.16b v3, v3, v0, v4 - bcax.16b v4, v4, v1, v0 - mov.16b v0, v25 - mov.16b v1, v26 - - bcax.16b v25, v5, v7, v6 - bcax.16b v26, v6, v8, v7 - bcax.16b v7, v7, v9, v8 - bcax.16b v8, v8, v5, v9 - bcax.16b v9, v9, v6, v5 - mov.16b v5, v25 - mov.16b v6, v26 - - bcax.16b v25, v10, v12, v11 - bcax.16b v26, v11, v13, v12 - bcax.16b v12, v12, v14, v13 - bcax.16b v13, v13, v10, v14 - bcax.16b v14, v14, v11, v10 - mov.16b v10, v25 - mov.16b v11, v26 - - bcax.16b v25, v15, v17, v16 - bcax.16b v26, v16, v18, v17 - bcax.16b v17, v17, v19, v18 - bcax.16b v18, v18, v15, v19 - bcax.16b v19, v19, v16, v15 - mov.16b v15, v25 - mov.16b v16, v26 - - bcax.16b v25, v20, v22, v21 - bcax.16b v26, v21, v23, v22 - bcax.16b v22, v22, v24, v23 - bcax.16b v23, v23, v20, v24 - bcax.16b v24, v24, v21, v20 - mov.16b v20, v25 - mov.16b v21, v26 - - # iota - ld1r {v25.2d}, [x1], #8 - eor.16b v0, v0, v25 -.endm - -.align 4 -.global __f1600x2 -__f1600x2: - stp d8, d9, [sp,#-16]! - stp d10, d11, [sp,#-16]! - stp d12, d13, [sp,#-16]! - stp d14, d15, [sp,#-16]! - - mov x2, x0 - mov x3, #24 - - ld1.2d {v0, v1, v2, v3}, [x0], #64 - ld1.2d {v4, v5, v6, v7}, [x0], #64 - ld1.2d {v8, v9, v10, v11}, [x0], #64 - ld1.2d {v12, v13, v14, v15}, [x0], #64 - ld1.2d {v16, v17, v18, v19}, [x0], #64 - ld1.2d {v20, v21, v22, v23}, [x0], #64 - ld1.2d {v24}, [x0] - -loop: - round - - subs x3, x3, #1 - cbnz x3, loop - - mov x0, x2 - st1.2d {v0, v1, v2, v3}, [x0], #64 - st1.2d {v4, v5, v6, v7}, [x0], #64 - st1.2d {v8, v9, v10, v11}, [x0], #64 - st1.2d {v12, v13, v14, v15}, [x0], #64 - st1.2d {v16, v17, v18, v19}, [x0], #64 - st1.2d {v20, v21, v22, v23}, [x0], #64 - st1.2d {v24}, [x0] - - ldp d14, d15, [sp], #16 - ldp d12, d13, [sp], #16 - ldp d10, d11, [sp], #16 - ldp d8, d9, [sp], #16 - - ret lr diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/f1600x2_const.c b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/f1600x2_const.c deleted file mode 100644 index e49c0ba149..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/f1600x2_const.c +++ /dev/null @@ -1,30 +0,0 @@ -#include "f1600x2.h" - -uint64_t f1600_RC[24] = { - 0x0000000000000001, - 0x0000000000008082, - 0x800000000000808A, - 0x8000000080008000, - 0x000000000000808B, - 0x0000000080000001, - 0x8000000080008081, - 0x8000000000008009, - 0x000000000000008A, - 0x0000000000000088, - 0x0000000080008009, - 0x000000008000000A, - 0x000000008000808B, - 0x800000000000008B, - 0x8000000000008089, - 0x8000000000008003, - 0x8000000000008002, - 0x8000000000000080, - 0x000000000000800A, - 0x800000008000000A, - 0x8000000080008081, - 0x8000000000008080, - 0x0000000080000001, - 0x8000000080008008, -}; - - diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/fips202x2.c b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/fips202x2.c deleted file mode 100644 index 4718c343bc..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/fips202x2.c +++ /dev/null @@ -1,148 +0,0 @@ -#include -#include - -#include "fips202x2.h" -#include "f1600x2.h" -#include "fips202.h" - -uint64_t load64(const unsigned char *x) { - unsigned long long r = 0, i; - - for (i = 0; i < 8; ++i) { - r |= (unsigned long long)x[i] << 8 * i; - } - return r; -} - -void store64(uint8_t *x, uint64_t u) { - unsigned int i; - - for (i = 0; i < 8; ++i) { - x[i] = (uint8_t)u; - u >>= 8; - } -} - -static void keccak_absorb2x(uint64_t *s, - unsigned int r, - const unsigned char *m0, - const unsigned char *m1, - unsigned long long int mlen, - unsigned char p) { - unsigned long long i; - unsigned char t0[200]; - unsigned char t1[200]; - - while (mlen >= r) { - for (i = 0; i < r / 8; ++i) { - s[2 * i + 0] ^= load64(m0 + 8 * i); - s[2 * i + 1] ^= load64(m1 + 8 * i); - } - - f1600x2(s); - mlen -= r; - m0 += r; - m1 += r; - } - - for (i = 0; i < r; ++i) { - t0[i] = 0; - t1[i] = 0; - } - for (i = 0; i < mlen; ++i) { - t0[i] = m0[i]; - t1[i] = m1[i]; - } - - t0[i] = p; - t1[i] = p; - - t0[r - 1] |= 128; - t1[r - 1] |= 128; - - for (i = 0; i < r / 8; ++i) { - s[2 * i + 0] ^= load64(t0 + 8 * i); - s[2 * i + 1] ^= load64(t1 + 8 * i); - } -} - - -static void keccak_squeezeblocks2x(unsigned char *h0, - unsigned char *h1, - unsigned long long int nblocks, - uint64_t *s, - unsigned int r) { - unsigned int i; - - while (nblocks > 0) { - f1600x2(s); - for (i = 0; i < (r >> 3); i++) { - store64(h0 + 8 * i, s[2 * i + 0]); - store64(h1 + 8 * i, s[2 * i + 1]); - } - h0 += r; - h1 += r; - nblocks--; - } -} - - - -void shake128x2(unsigned char *out0, - unsigned char *out1, - unsigned long long outlen, - unsigned char *in0, - unsigned char *in1, - unsigned long long inlen) { - uint64_t s[50] = {0}; - unsigned char t0[SHAKE128_RATE]; - unsigned char t1[SHAKE128_RATE]; - unsigned int i; - - /* absorb 4 message of identical length in parallel */ - keccak_absorb2x(s, SHAKE128_RATE, in0, in1, inlen, 0x1F); - - /* Squeeze output */ - keccak_squeezeblocks2x(out0, out1, outlen / SHAKE128_RATE, s, SHAKE128_RATE); - - out0 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; - out1 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; - - if (outlen % SHAKE128_RATE) { - keccak_squeezeblocks2x(t0, t1, 1, s, SHAKE128_RATE); - for (i = 0; i < outlen % SHAKE128_RATE; i++) { - out0[i] = t0[i]; - out1[i] = t1[i]; - } - } -} - - -void shake256x2(unsigned char *out0, - unsigned char *out1, - unsigned long long outlen, - unsigned char *in0, - unsigned char *in1, - unsigned long long inlen) { - uint64_t s[50] = {0}; - unsigned char t0[SHAKE256_RATE]; - unsigned char t1[SHAKE256_RATE]; - unsigned int i; - - /* absorb 2 message of identical length in parallel */ - keccak_absorb2x(s, SHAKE256_RATE, in0, in1, inlen, 0x1F); - - /* Squeeze output */ - keccak_squeezeblocks2x(out0, out1, outlen / SHAKE256_RATE, s, SHAKE256_RATE); - - out0 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; - out1 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; - - if (outlen % SHAKE256_RATE) { - keccak_squeezeblocks2x(t0, t1, 1, s, SHAKE256_RATE); - for (i = 0; i < outlen % SHAKE256_RATE; i++) { - out0[i] = t0[i]; - out1[i] = t1[i]; - } - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/fips202x2.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/fips202x2.h deleted file mode 100644 index 7ba58b35d8..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/fips202x2.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef SPX_FIPS202X2_H -#define SPX_FIPS202X2_H - -#include - -uint64_t load64(const unsigned char *x); -void store64(uint8_t *x, uint64_t u); - - -void shake128x2(unsigned char *out0, - unsigned char *out1, - unsigned long long outlen, - unsigned char *in0, - unsigned char *in1, - unsigned long long inlen); - -void shake256x2(unsigned char *out0, - unsigned char *out1, - unsigned long long outlen, - unsigned char *in0, - unsigned char *in1, - unsigned long long inlen); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/fors.c b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/fors.c deleted file mode 100644 index 39193d04e2..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/fors.c +++ /dev/null @@ -1,191 +0,0 @@ -#include -#include -#include - -#include "fors.h" - -#include "address.h" -#include "hash.h" -#include "hashx2.h" -#include "thash.h" -#include "thashx2.h" -#include "utils.h" -#include "utilsx2.h" - -static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, - uint32_t fors_leaf_addr[8]) { - prf_addr(sk, ctx, fors_leaf_addr); -} - -static void fors_gen_skx2(unsigned char *sk0, - unsigned char *sk1, - const spx_ctx *ctx, - uint32_t fors_leaf_addrx2[2 * 8]) { - prf_addrx2(sk0, sk1, - ctx, fors_leaf_addrx2); -} - -static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, - const spx_ctx *ctx, - uint32_t fors_leaf_addr[8]) { - thash(leaf, sk, 1, ctx, fors_leaf_addr); -} - -static void fors_sk_to_leafx2(unsigned char *leaf0, - unsigned char *leaf1, - const unsigned char *sk0, - const unsigned char *sk1, - const spx_ctx *ctx, - uint32_t fors_leaf_addrx2[2 * 8]) { - thashx2(leaf0, leaf1, - sk0, sk1, - 1, ctx, fors_leaf_addrx2); -} - -struct fors_gen_leaf_info { - uint32_t leaf_addrx[2 * 8]; -}; - -static void fors_gen_leafx2(unsigned char *leaf, - const spx_ctx *ctx, - uint32_t addr_idx, void *info) { - struct fors_gen_leaf_info *fors_info = info; - uint32_t *fors_leaf_addrx2 = fors_info->leaf_addrx; - unsigned int j; - - /* Only set the parts that the caller doesn't set */ - for (j = 0; j < 2; j++) { - set_tree_index(fors_leaf_addrx2 + j * 8, addr_idx + j); - set_type(fors_leaf_addrx2 + j * 8, SPX_ADDR_TYPE_FORSPRF); - } - - fors_gen_skx2(leaf + 0 * SPX_N, - leaf + 1 * SPX_N, - ctx, fors_leaf_addrx2); - - for (j = 0; j < 2; j++) { - set_type(fors_leaf_addrx2 + j * 8, SPX_ADDR_TYPE_FORSTREE); - } - - fors_sk_to_leafx2(leaf + 0 * SPX_N, - leaf + 1 * SPX_N, - leaf + 0 * SPX_N, - leaf + 1 * SPX_N, - ctx, fors_leaf_addrx2); -} - -/** - * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - * Assumes indices has space for SPX_FORS_TREES integers. - */ -static void message_to_indices(uint32_t *indices, const unsigned char *m) { - unsigned int i, j; - unsigned int offset = 0; - - for (i = 0; i < SPX_FORS_TREES; i++) { - indices[i] = 0; - for (j = 0; j < SPX_FORS_HEIGHT; j++) { - indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); - offset++; - } - } -} - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -void fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]) { - uint32_t indices[SPX_FORS_TREES]; - unsigned char roots[SPX_FORS_TREES * SPX_N]; - uint32_t fors_tree_addr[2 * 8] = {0}; - struct fors_gen_leaf_info fors_info = {0}; - uint32_t *fors_leaf_addr = fors_info.leaf_addrx; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - for (i = 0; i < 2; i++) { - copy_keypair_addr(fors_tree_addr + 8 * i, fors_addr); - set_type(fors_tree_addr + 8 * i, SPX_ADDR_TYPE_FORSTREE); - copy_keypair_addr(fors_leaf_addr + 8 * i, fors_addr); - } - copy_keypair_addr(fors_pk_addr, fors_addr); - set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < SPX_FORS_TREES; i++) { - idx_offset = i * (1 << SPX_FORS_HEIGHT); - - set_tree_height(fors_tree_addr, 0); - set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Include the secret key part that produces the selected leaf node. */ - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); - fors_gen_sk(sig, ctx, fors_tree_addr); - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); - sig += SPX_N; - - /* Compute the authentication path for this leaf node. */ - treehashx2(roots + i * SPX_N, sig, ctx, - indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx2, - fors_tree_addr, &fors_info); - - sig += SPX_N * SPX_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); -} - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -void fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]) { - uint32_t indices[SPX_FORS_TREES]; - unsigned char roots[SPX_FORS_TREES * SPX_N]; - unsigned char leaf[SPX_N]; - uint32_t fors_tree_addr[8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - copy_keypair_addr(fors_tree_addr, fors_addr); - copy_keypair_addr(fors_pk_addr, fors_addr); - - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); - set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < SPX_FORS_TREES; i++) { - idx_offset = i * (1 << SPX_FORS_HEIGHT); - - set_tree_height(fors_tree_addr, 0); - set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Derive the leaf from the included secret key part. */ - fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); - sig += SPX_N; - - /* Derive the corresponding root node of this tree. */ - compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, - sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); - sig += SPX_N * SPX_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/fors.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/fors.h deleted file mode 100644 index 509140a178..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/fors.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef SPX_FORS_H -#define SPX_FORS_H - -#include - -#include "context.h" -#include "params.h" - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -#define fors_sign SPX_NAMESPACE(fors_sign) -void fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]); - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) -void fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/hash.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/hash.h deleted file mode 100644 index f7c87d4c3c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/hash.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef SPX_HASH_H -#define SPX_HASH_H - -#include -#include - -#include "context.h" -#include "params.h" - -#define prf_addr SPX_NAMESPACE(prf_addr) -void prf_addr(unsigned char *out, const spx_ctx *ctx, - const uint32_t addr[8]); - -#define gen_message_random SPX_NAMESPACE(gen_message_random) -void gen_message_random(unsigned char *R, const unsigned char *sk_prf, - const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx); - -#define hash_message SPX_NAMESPACE(hash_message) -void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx); - - - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/hash_shake.c b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/hash_shake.c deleted file mode 100644 index ff5e7ec918..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/hash_shake.c +++ /dev/null @@ -1,83 +0,0 @@ -#include -#include - -#include "hash.h" - -#include "address.h" -#include "fips202.h" -#include "params.h" -#include "utils.h" - -/* - * Computes PRF(pk_seed, sk_seed, addr) - */ -void prf_addr(unsigned char *out, const spx_ctx *ctx, - const uint32_t addr[8]) { - unsigned char buf[2 * SPX_N + SPX_ADDR_BYTES]; - - memcpy(buf, ctx->pub_seed, SPX_N); - memcpy(buf + SPX_N, addr, SPX_ADDR_BYTES); - memcpy(buf + SPX_N + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); - - shake256(out, SPX_N, buf, 2 * SPX_N + SPX_ADDR_BYTES); -} - -/** - * Computes the message-dependent randomness R, using a secret seed and an - * optional randomization value as well as the message. - */ -void gen_message_random(unsigned char *R, const unsigned char *sk_prf, - const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx) { - (void)ctx; - shake256incctx s_inc; - - shake256_inc_init(&s_inc); - shake256_inc_absorb(&s_inc, sk_prf, SPX_N); - shake256_inc_absorb(&s_inc, optrand, SPX_N); - shake256_inc_absorb(&s_inc, m, mlen); - shake256_inc_finalize(&s_inc); - shake256_inc_squeeze(R, SPX_N, &s_inc); - shake256_inc_ctx_release(&s_inc); -} - -/** - * Computes the message hash using R, the public key, and the message. - * Outputs the message digest and the index of the leaf. The index is split in - * the tree index and the leaf index, for convenient copying to an address. - */ -void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx) { - (void)ctx; -#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) -#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) -#define SPX_LEAF_BITS SPX_TREE_HEIGHT -#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) -#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) - - unsigned char buf[SPX_DGST_BYTES]; - unsigned char *bufp = buf; - shake256incctx s_inc; - - shake256_inc_init(&s_inc); - shake256_inc_absorb(&s_inc, R, SPX_N); - shake256_inc_absorb(&s_inc, pk, SPX_PK_BYTES); - shake256_inc_absorb(&s_inc, m, mlen); - shake256_inc_finalize(&s_inc); - shake256_inc_squeeze(buf, SPX_DGST_BYTES, &s_inc); - shake256_inc_ctx_release(&s_inc); - - memcpy(digest, bufp, SPX_FORS_MSG_BYTES); - bufp += SPX_FORS_MSG_BYTES; - - - *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); - *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); - bufp += SPX_TREE_BYTES; - - *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); - *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/hash_shakex2.c b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/hash_shakex2.c deleted file mode 100644 index 99571916a2..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/hash_shakex2.c +++ /dev/null @@ -1,52 +0,0 @@ -#include -#include - -#include "hashx2.h" - -#include "address.h" -#include "f1600x2.h" -#include "fips202x2.h" -#include "params.h" - -/* - * 2-way parallel version of prf_addr; takes 2x as much input and output - */ -void prf_addrx2(unsigned char *out0, - unsigned char *out1, - const spx_ctx *ctx, - const uint32_t addrx2[2 * 8]) { - /* As we write and read only a few quadwords, it is more efficient to - * build and extract from the fourway SHAKE256 state by hand. */ - uint64_t state[50] = {0}; - - for (int i = 0; i < SPX_N / 8; i++) { - uint64_t x = load64(ctx->pub_seed + 8 * i); - state[2 * i] = x; - state[2 * i + 1] = x; - } - for (int i = 0; i < 4; i++) { - state[2 * (SPX_N / 8 + i)] = (((uint64_t)addrx2[1 + 2 * i]) << 32) - | (uint64_t)addrx2[2 * i]; - state[2 * (SPX_N / 8 + i) + 1] = (((uint64_t)addrx2[8 + 1 + 2 * i]) << 32) - | (uint64_t)addrx2[8 + 2 * i]; - } - for (int i = 0; i < SPX_N / 8; i++) { - uint64_t x = load64(ctx->sk_seed + 8 * i); - state[2 * (SPX_N / 8 + i + 4)] = x; - state[2 * (SPX_N / 8 + i + 4) + 1] = x; - } - - /* SHAKE domain separator and padding. */ - state[2 * (SPX_N / 4 + 4)] = 0x1f; - state[2 * (SPX_N / 4 + 4) + 1] = 0x1f; - - state[2 * 16] = 0x80ULL << 56; - state[2 * 16 + 1] = 0x80ULL << 56; - - f1600x2(state); - - for (int i = 0; i < SPX_N / 8; i++) { - store64(out0 + 8 * i, state[2 * i]); - store64(out1 + 8 * i, state[2 * i + 1]); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/hashx2.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/hashx2.h deleted file mode 100644 index 99b8873a9b..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/hashx2.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef SPX_HASHX2_H -#define SPX_HASHX2_H - -#include "context.h" -#include "params.h" -#include - -#define prf_addrx2 SPX_NAMESPACE(prf_addrx2) -void prf_addrx2(unsigned char *out0, - unsigned char *out1, - const spx_ctx *ctx, - const uint32_t addrx2[2 * 8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/merkle.c b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/merkle.c deleted file mode 100644 index c94ee23939..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/merkle.c +++ /dev/null @@ -1,64 +0,0 @@ -#include -#include - -#include "merkle.h" - -#include "address.h" -#include "params.h" -#include "utils.h" -#include "utilsx2.h" -#include "wots.h" -#include "wotsx2.h" - -/* - * This generates a Merkle signature (WOTS signature followed by the Merkle - * authentication path). - */ -void merkle_sign(uint8_t *sig, unsigned char *root, - const spx_ctx *ctx, - uint32_t wots_addr[8], uint32_t tree_addr[8], - uint32_t idx_leaf) { - unsigned char *auth_path = sig + SPX_WOTS_BYTES; - uint32_t tree_addrx2[2 * 8] = { 0 }; - int j; - struct leaf_info_x2 info = { 0 }; - unsigned steps[ SPX_WOTS_LEN ]; - - info.wots_sig = sig; - chain_lengths(steps, root); - info.wots_steps = steps; - - for (j = 0; j < 2; j++) { - set_type(&tree_addrx2[8 * j], SPX_ADDR_TYPE_HASHTREE); - set_type(&info.leaf_addr[8 * j], SPX_ADDR_TYPE_WOTS); - set_type(&info.pk_addr[8 * j], SPX_ADDR_TYPE_WOTSPK); - copy_subtree_addr(&tree_addrx2[8 * j], tree_addr); - copy_subtree_addr(&info.leaf_addr[8 * j], wots_addr); - copy_subtree_addr(&info.pk_addr[8 * j], wots_addr); - } - - info.wots_sign_leaf = idx_leaf; - - treehashx2(root, auth_path, ctx, - idx_leaf, 0, - SPX_TREE_HEIGHT, - wots_gen_leafx2, - tree_addrx2, &info); -} - -/* Compute root node of the top-most subtree. */ -void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { - /* We do not need the auth path in key generation, but it simplifies the - code to have just one treehash routine that computes both root and path - in one function. */ - unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; - uint32_t top_tree_addr[8] = {0}; - uint32_t wots_addr[8] = {0}; - - set_layer_addr(top_tree_addr, SPX_D - 1); - set_layer_addr(wots_addr, SPX_D - 1); - - merkle_sign(auth_path, root, ctx, - wots_addr, top_tree_addr, - ~0 /* ~0 means "don't bother generating an auth path */ ); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/merkle.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/merkle.h deleted file mode 100644 index 769cf2e970..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/merkle.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef MERKLE_H_ -#define MERKLE_H_ - -#include - -#include "context.h" -#include "params.h" - -/* Generate a Merkle signature (WOTS signature followed by the Merkle */ -/* authentication path) */ -#define merkle_sign SPX_NAMESPACE(merkle_sign) -void merkle_sign(uint8_t *sig, unsigned char *root, - const spx_ctx *ctx, - uint32_t wots_addr[8], uint32_t tree_addr[8], - uint32_t idx_leaf); - -/* Compute the root node of the top-most subtree. */ -#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) -void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); - -#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/nistapi.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/nistapi.h deleted file mode 100644 index 3cb71afad4..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/nistapi.h +++ /dev/null @@ -1,87 +0,0 @@ -#ifndef SPX_API_H -#define SPX_API_H - -#include -#include - -#include "params.h" - -#define CRYPTO_ALGNAME "SPHINCS+" - -#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES -#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES -#define CRYPTO_BYTES SPX_BYTES -#define CRYPTO_SEEDBYTES (3*SPX_N) - -/* - * Returns the length of a secret key, in bytes - */ -#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) -size_t crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) -size_t crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) -size_t crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) -size_t crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) -int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) -int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) -int crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) -int crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -#define crypto_sign SPX_NAMESPACE(crypto_sign) -int crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) -int crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/params.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/params.h deleted file mode 100644 index 7565ba5a9a..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/params.h +++ /dev/null @@ -1,56 +0,0 @@ -#ifndef SPX_PARAMS_H -#define SPX_PARAMS_H - -#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSSHAKE128SROBUST_AARCH64_##s - -/* Hash output length in bytes. */ -#define SPX_N 16 -/* Height of the hypertree. */ -#define SPX_FULL_HEIGHT 63 -/* Number of subtree layer. */ -#define SPX_D 7 -/* FORS tree dimensions. */ -#define SPX_FORS_HEIGHT 12 -#define SPX_FORS_TREES 14 -/* Winternitz parameter, */ -#define SPX_WOTS_W 16 - -/* The hash function is defined by linking a different hash.c file, as opposed - to setting a #define constant. */ - -/* For clarity */ -#define SPX_ADDR_BYTES 32 - -/* WOTS parameters. */ -#define SPX_WOTS_LOGW 4 - -#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) - -/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#define SPX_WOTS_LEN2 3 - -#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) -#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) -#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES - -/* Subtree size. */ -#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) - -//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT -// #error SPX_D should always divide SPX_FULL_HEIGHT -//#endif - -/* FORS parameters. */ -#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) -#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) -#define SPX_FORS_PK_BYTES SPX_N - -/* Resulting SPX sizes. */ -#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ - SPX_FULL_HEIGHT * SPX_N) -#define SPX_PK_BYTES (2 * SPX_N) -#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) - -#include "shake_offsets.h" - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/shake_offsets.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/shake_offsets.h deleted file mode 100644 index 6b28d95d91..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/shake_offsets.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef SHAKE_OFFSETS_H_ -#define SHAKE_OFFSETS_H_ - -/* - * Offsets of various fields in the address structure when we use SHAKE as - * the Sphincs+ hash function - */ - -#define SPX_OFFSET_LAYER 3 /* The byte used to specify the Merkle tree layer */ -#define SPX_OFFSET_TREE 8 /* The start of the 8 byte field used to specify the tree */ -#define SPX_OFFSET_TYPE 19 /* The byte used to specify the hash type (reason) */ -#define SPX_OFFSET_KP_ADDR2 22 /* The high byte used to specify the key pair (which one-time signature) */ -#define SPX_OFFSET_KP_ADDR1 23 /* The low byte used to specify the key pair */ -#define SPX_OFFSET_CHAIN_ADDR 27 /* The byte used to specify the chain address (which Winternitz chain) */ -#define SPX_OFFSET_HASH_ADDR 31 /* The byte used to specify the hash address (where in the Winternitz chain) */ -#define SPX_OFFSET_TREE_HGT 27 /* The byte used to specify the height of this node in the FORS or Merkle tree */ -#define SPX_OFFSET_TREE_INDEX 28 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ - -#define SPX_SHAKE 1 - -#endif /* SHAKE_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/sign.c b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/sign.c deleted file mode 100644 index 9d0c7d1b22..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/sign.c +++ /dev/null @@ -1,286 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "context.h" -#include "fors.h" -#include "hash.h" -#include "merkle.h" -#include "nistapi.h" -#include "params.h" -#include "randombytes.h" -#include "thash.h" -#include "utils.h" -#include "wots.h" - -/* - * Returns the length of a secret key, in bytes - */ -size_t crypto_sign_secretkeybytes(void) { - return CRYPTO_SECRETKEYBYTES; -} - -/* - * Returns the length of a public key, in bytes - */ -size_t crypto_sign_publickeybytes(void) { - return CRYPTO_PUBLICKEYBYTES; -} - -/* - * Returns the length of a signature, in bytes - */ -size_t crypto_sign_bytes(void) { - return CRYPTO_BYTES; -} - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t crypto_sign_seedbytes(void) { - return CRYPTO_SEEDBYTES; -} - -/* - * Generates an SPX key pair given a seed of length - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed) { - spx_ctx ctx; - - /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ - memcpy(sk, seed, CRYPTO_SEEDBYTES); - - memcpy(pk, sk + 2 * SPX_N, SPX_N); - - memcpy(ctx.pub_seed, pk, SPX_N); - memcpy(ctx.sk_seed, sk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - /* Compute root node of the top-most subtree. */ - merkle_gen_root(sk + 3 * SPX_N, &ctx); - - // cleanup - free_hash_function(&ctx); - - memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); - - return 0; -} - -/* - * Generates an SPX key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { - uint8_t seed[CRYPTO_SEEDBYTES]; - randombytes(seed, CRYPTO_SEEDBYTES); - crypto_sign_seed_keypair(pk, sk, seed); - - return 0; -} - -/** - * Returns an array containing a detached signature. - */ -int crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - spx_ctx ctx; - - const uint8_t *sk_prf = sk + SPX_N; - const uint8_t *pk = sk + 2 * SPX_N; - - uint8_t optrand[SPX_N]; - uint8_t mhash[SPX_FORS_MSG_BYTES]; - uint8_t root[SPX_N]; - uint32_t i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - - memcpy(ctx.sk_seed, sk, SPX_N); - memcpy(ctx.pub_seed, pk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - set_type(wots_addr, SPX_ADDR_TYPE_WOTS); - set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); - - /* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ - randombytes(optrand, SPX_N); - /* Compute the digest randomization value. */ - gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); - - /* Derive the message digest and leaf index from R, PK and M. */ - hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); - sig += SPX_N; - - set_tree_addr(wots_addr, tree); - set_keypair_addr(wots_addr, idx_leaf); - - /* Sign the message hash using FORS. */ - fors_sign(sig, root, mhash, &ctx, wots_addr); - sig += SPX_FORS_BYTES; - - for (i = 0; i < SPX_D; i++) { - set_layer_addr(tree_addr, i); - set_tree_addr(tree_addr, tree); - - copy_subtree_addr(wots_addr, tree_addr); - set_keypair_addr(wots_addr, idx_leaf); - - merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); - sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); - tree = tree >> SPX_TREE_HEIGHT; - } - - free_hash_function(&ctx); - - *siglen = SPX_BYTES; - - return 0; -} - -/** - * Verifies a detached signature and message under a given public key. - */ -int crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk) { - spx_ctx ctx; - const uint8_t *pub_root = pk + SPX_N; - uint8_t mhash[SPX_FORS_MSG_BYTES]; - uint8_t wots_pk[SPX_WOTS_BYTES]; - uint8_t root[SPX_N]; - uint8_t leaf[SPX_N]; - unsigned int i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - if (siglen != SPX_BYTES) { - return -1; - } - - memcpy(ctx.pub_seed, pk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - set_type(wots_addr, SPX_ADDR_TYPE_WOTS); - set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); - set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); - - /* Derive the message digest and leaf index from R || PK || M. */ - /* The additional SPX_N is a result of the hash domain separator. */ - hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); - sig += SPX_N; - - /* Layer correctly defaults to 0, so no need to set_layer_addr */ - set_tree_addr(wots_addr, tree); - set_keypair_addr(wots_addr, idx_leaf); - - fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); - sig += SPX_FORS_BYTES; - - /* For each subtree.. */ - for (i = 0; i < SPX_D; i++) { - set_layer_addr(tree_addr, i); - set_tree_addr(tree_addr, tree); - - copy_subtree_addr(wots_addr, tree_addr); - set_keypair_addr(wots_addr, idx_leaf); - - copy_keypair_addr(wots_pk_addr, wots_addr); - - /* The WOTS public key is only correct if the signature was correct. */ - /* Initially, root is the FORS pk, but on subsequent iterations it is - the root of the subtree below the currently processed subtree. */ - wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); - sig += SPX_WOTS_BYTES; - - /* Compute the leaf node using the WOTS public key. */ - thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); - - /* Compute the root node of this subtree. */ - compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, - &ctx, tree_addr); - sig += SPX_TREE_HEIGHT * SPX_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); - tree = tree >> SPX_TREE_HEIGHT; - } - - // cleanup - free_hash_function(&ctx); - - /* Check if the root node equals the root node in the public key. */ - if (memcmp(root, pub_root, SPX_N) != 0) { - return -1; - } - - return 0; -} - - -/** - * Returns an array containing the signature followed by the message. - */ -int crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk) { - size_t siglen; - - crypto_sign_signature(sm, &siglen, m, mlen, sk); - - memmove(sm + SPX_BYTES, m, mlen); - *smlen = siglen + mlen; - - return 0; -} - -/** - * Verifies a given signature-message pair under a given public key. - */ -int crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk) { - /* The API caller does not necessarily know what size a signature should be - but SPHINCS+ signatures are always exactly SPX_BYTES. */ - if (smlen < SPX_BYTES) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - *mlen = smlen - SPX_BYTES; - - if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - /* If verification was successful, move the message to the right place. */ - memmove(m, sm + SPX_BYTES, *mlen); - - return 0; -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/thash.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/thash.h deleted file mode 100644 index 8687ccfb4d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/thash.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef SPX_THASH_H -#define SPX_THASH_H - -#include "context.h" -#include "params.h" - -#include - -#define thash SPX_NAMESPACE(thash) -void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/thash_shake_robustx2.c b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/thash_shake_robustx2.c deleted file mode 100644 index 454fc0f4e2..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/thash_shake_robustx2.c +++ /dev/null @@ -1,112 +0,0 @@ -#include -#include - -#include "thash.h" -#include "thashx2.h" - -#include "address.h" -#include "params.h" -#include "utils.h" - -#include "f1600x2.h" -#include "fips202x2.h" - - -void thash(unsigned char *out, - const unsigned char *in, - unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]) { - uint32_t addrx2 [2 * 8] = { - addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], addr[6], addr[7], - addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], addr[6], addr[7] - }; - thashx2(out, out, in, in, inblocks, ctx, addrx2); -} - -/** - * 2-way parallel version of thash; takes 2x as much input and output - */ -void thashx2(unsigned char *out0, - unsigned char *out1, - const unsigned char *in0, - const unsigned char *in1, - unsigned int inblocks, - const spx_ctx *ctx, uint32_t addrx2[2 * 8]) { - if (inblocks == 1 || inblocks == 2) { - /* As we write and read only a few quadwords, it is more efficient to - * build and extract from the twoway SHAKE256 state by hand. */ - uint64_t state[50] = {0}; - uint64_t state2[50]; - - for (int i = 0; i < SPX_N / 8; i++) { - uint64_t x = load64(ctx->pub_seed + 8 * i); - state[2 * i] = x; - state[2 * i + 1] = x; - } - for (int i = 0; i < 4; i++) { - state[2 * (SPX_N / 8 + i)] = (((uint64_t)addrx2[1 + 2 * i]) << 32) - | (uint64_t)addrx2[2 * i]; - state[2 * (SPX_N / 8 + i) + 1] = (((uint64_t)addrx2[8 + 1 + 2 * i]) << 32) - | (uint64_t)addrx2[8 + 2 * i]; - } - - /* Domain separator and padding. */ - state[2 * 16] = 0x80ULL << 56; - state[2 * 16 + 1] = 0x80ULL << 56; - - state[2 * ((SPX_N / 8) + 4)] ^= 0x1f; - state[2 * ((SPX_N / 8) + 4) + 1] ^= 0x1f; - - /* We will permutate state2 with f1600x2 to compute the bitmask, - * but first we'll copy it to state2 which will be used to compute - * the final output, as its input is almost identical. */ - memcpy(state2, state, 400); - - f1600x2(state); - - /* By copying from state, state2 already contains the pub_seed - * and address. We just need to copy in the input blocks xorred with - * the bitmask we just computed. */ - for (unsigned int i = 0; i < (SPX_N / 8) * inblocks; i++) { - state2[2 * (SPX_N / 8 + 4 + i)] = state[2 * i] ^ load64(in0 + 8 * i); - state2[2 * (SPX_N / 8 + 4 + i) + 1] = state[2 * i + 1] ^ load64(in1 + 8 * i); - } - - /* Domain separator and start of padding. Note that the quadwords - * around are already zeroed for state from which we copied. - * We do a XOR instead of a set as this might be the 16th quadword - * when N=32 and inblocks=2, which already contains the end - * of the padding. */ - state2[2 * ((SPX_N / 8) * (1 + inblocks) + 4)] ^= 0x1f; - state2[2 * ((SPX_N / 8) * (1 + inblocks) + 4) + 1] ^= 0x1f; - - f1600x2(state2); - - for (int i = 0; i < SPX_N / 8; i++) { - store64(out0 + 8 * i, state2[2 * i]); - store64(out1 + 8 * i, state2[2 * i + 1]); - } - } else { - PQCLEAN_VLA(unsigned char, buf0, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); - PQCLEAN_VLA(unsigned char, buf1, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); - PQCLEAN_VLA(unsigned char, bitmask0, inblocks * SPX_N); - PQCLEAN_VLA(unsigned char, bitmask1, inblocks * SPX_N); - unsigned int i; - - memcpy(buf0, ctx->pub_seed, SPX_N); - memcpy(buf1, ctx->pub_seed, SPX_N); - memcpy(buf0 + SPX_N, addrx2 + 0 * 8, SPX_ADDR_BYTES); - memcpy(buf1 + SPX_N, addrx2 + 1 * 8, SPX_ADDR_BYTES); - - shake256x2(bitmask0, bitmask1, inblocks * SPX_N, - buf0, buf1, SPX_N + SPX_ADDR_BYTES); - - for (i = 0; i < inblocks * SPX_N; i++) { - buf0[SPX_N + SPX_ADDR_BYTES + i] = in0[i] ^ bitmask0[i]; - buf1[SPX_N + SPX_ADDR_BYTES + i] = in1[i] ^ bitmask1[i]; - } - - shake256x2(out0, out1, SPX_N, - buf0, buf1, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/thashx2.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/thashx2.h deleted file mode 100644 index 040375e618..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/thashx2.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef SPX_THASHX2_H -#define SPX_THASHX2_H - -#include "context.h" -#include "params.h" -#include - -#define thashx2 SPX_NAMESPACE(thashx2) -void thashx2(unsigned char *out0, - unsigned char *out1, - const unsigned char *in0, - const unsigned char *in1, - unsigned int inblocks, - const spx_ctx *ctx, uint32_t addrx2[2 * 8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/utils.c b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/utils.c deleted file mode 100644 index 177b541fb9..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/utils.c +++ /dev/null @@ -1,148 +0,0 @@ -#include - -#include "utils.h" - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "thash.h" - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void ull_to_bytes(unsigned char *out, unsigned int outlen, - unsigned long long in) { - int i; - - /* Iterate over out in decreasing order, for big-endianness. */ - for (i = (signed int)outlen - 1; i >= 0; i--) { - out[i] = in & 0xff; - in = in >> 8; - } -} - -void u32_to_bytes(unsigned char *out, uint32_t in) { - out[0] = (unsigned char)(in >> 24); - out[1] = (unsigned char)(in >> 16); - out[2] = (unsigned char)(in >> 8); - out[3] = (unsigned char)in; -} - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { - unsigned long long retval = 0; - unsigned int i; - - for (i = 0; i < inlen; i++) { - retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); - } - return retval; -} - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void compute_root(unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const spx_ctx *ctx, uint32_t addr[8]) { - uint32_t i; - unsigned char buffer[2 * SPX_N]; - - /* If leaf_idx is odd (last bit = 1), current path element is a right child - and auth_path has to go left. Otherwise it is the other way around. */ - if (leaf_idx & 1) { - memcpy(buffer + SPX_N, leaf, SPX_N); - memcpy(buffer, auth_path, SPX_N); - } else { - memcpy(buffer, leaf, SPX_N); - memcpy(buffer + SPX_N, auth_path, SPX_N); - } - auth_path += SPX_N; - - for (i = 0; i < tree_height - 1; i++) { - leaf_idx >>= 1; - idx_offset >>= 1; - /* Set the address of the node we're creating. */ - set_tree_height(addr, i + 1); - set_tree_index(addr, leaf_idx + idx_offset); - - /* Pick the right or left neighbor, depending on parity of the node. */ - if (leaf_idx & 1) { - thash(buffer + SPX_N, buffer, 2, ctx, addr); - memcpy(buffer, auth_path, SPX_N); - } else { - thash(buffer, buffer, 2, ctx, addr); - memcpy(buffer + SPX_N, auth_path, SPX_N); - } - auth_path += SPX_N; - } - - /* The last iteration is exceptional; we do not copy an auth_path node. */ - leaf_idx >>= 1; - idx_offset >>= 1; - set_tree_height(addr, tree_height); - set_tree_index(addr, leaf_idx + idx_offset); - thash(root, buffer, 2, ctx, addr); -} - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const spx_ctx * /* ctx */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), - uint32_t tree_addr[8]) { - PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); - PQCLEAN_VLA(unsigned int, heights, tree_height + 1); - unsigned int offset = 0; - uint32_t idx; - uint32_t tree_idx; - - for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { - /* Add the next leaf node to the stack. */ - gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); - offset++; - heights[offset - 1] = 0; - - /* If this is a node we need for the auth path.. */ - if ((leaf_idx ^ 0x1) == idx) { - memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); - } - - /* While the top-most nodes are of equal height.. */ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { - /* Compute index of the new node, in the next layer. */ - tree_idx = (idx >> (heights[offset - 1] + 1)); - - /* Set the address of the node we're creating. */ - set_tree_height(tree_addr, heights[offset - 1] + 1); - set_tree_index(tree_addr, - tree_idx + (idx_offset >> (heights[offset - 1] + 1))); - /* Hash the top-most nodes from the stack together. */ - thash(stack + (offset - 2)*SPX_N, - stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); - offset--; - /* Note that the top-most node is now one layer higher. */ - heights[offset - 1]++; - - /* If this is a node we need for the auth path.. */ - if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_path + heights[offset - 1]*SPX_N, - stack + (offset - 1)*SPX_N, SPX_N); - } - } - } - memcpy(root, stack, SPX_N); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/utils.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/utils.h deleted file mode 100644 index 64f5d5a53a..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/utils.h +++ /dev/null @@ -1,58 +0,0 @@ -#ifndef SPX_UTILS_H -#define SPX_UTILS_H - -#include - -#include "compat.h" -#include "context.h" -#include "params.h" - - -/* To support MSVC use alloca() instead of VLAs. See #20. */ - - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) -void ull_to_bytes(unsigned char *out, unsigned int outlen, - unsigned long long in); -#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) -void u32_to_bytes(unsigned char *out, uint32_t in); - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) -unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -#define compute_root SPX_NAMESPACE(compute_root) -void compute_root(unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const spx_ctx *ctx, uint32_t addr[8]); - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -#define treehash SPX_NAMESPACE(treehash) -void treehash(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const spx_ctx *ctx /* ctx */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), - uint32_t tree_addr[8]); - - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/utilsx2.c b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/utilsx2.c deleted file mode 100644 index 8736474e4f..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/utilsx2.c +++ /dev/null @@ -1,130 +0,0 @@ -#include - -#include "utilsx2.h" - -#include "address.h" -#include "params.h" -#include "thashx2.h" -#include "utils.h" - -/* - * Generate the entire Merkle tree, computing the authentication path for leaf_idx, - * and the resulting root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) - * - * This expects tree_addrx2 to be initialized to 2 parallel addr structures for - * the Merkle tree nodes - * - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - * - * This works by using the standard Merkle tree building algorithm, except - * that each 'node' tracked is actually 2 consecutive nodes in the real tree. - * When we combine two logical nodes AB and WX, we perform the H - * operation on adjacent real nodes, forming the parent logical node - * (AB)(WX) - * - * When we get to the top level of the real tree (where there is only - * one logical node), we continue this operation one more time; the right - * most real node will by the actual root (and the other node will be - * garbage). We follow the same thashx2 logic so that the 'extract - * authentication path components' part of the loop is still executed (and - * to simplify the code somewhat) - */ -void treehashx2(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, - uint32_t tree_height, - void (*gen_leafx2)( - unsigned char * /* Where to write the leaves */, - const spx_ctx *, - uint32_t idx, void *info), - uint32_t tree_addrx2[2 * 8], - void *info) { - /* This is where we keep the intermediate nodes */ - unsigned char stackx2[tree_height * 2 * SPX_N]; - uint32_t left_adj = 0, prev_left_adj = 0; /* When we're doing the top */ - /* level, the left-most part of the tree isn't at the beginning */ - /* of current[]. These give the offset of the actual start */ - - uint32_t idx; - uint32_t max_idx = (1 << (tree_height - 1)) - 1; - for (idx = 0;; idx++) { - unsigned char current[2 * SPX_N]; /* Current logical node */ - gen_leafx2( current, ctx, 2 * idx + idx_offset, - info ); - - /* Now combine the freshly generated right node with previously */ - /* generated left ones */ - uint32_t internal_idx_offset = idx_offset; - uint32_t internal_idx = idx; - uint32_t internal_leaf = leaf_idx; - uint32_t h; /* The height we are in the Merkle tree */ - for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { - - /* Special processing if we're at the top of the tree */ - if (h >= tree_height - 1) { - if (h == tree_height) { - /* We hit the root; return it */ - memcpy( root, ¤t[1 * SPX_N], SPX_N ); - return; - } - /* The tree indexing logic is a bit off in this case */ - /* Adjust it so that the left-most node of the part of */ - /* the tree that we're processing has index 0 */ - prev_left_adj = left_adj; - left_adj = 2 - (1 << (tree_height - h - 1)); - } - - /* Check if we hit the top of the tree */ - if (h == tree_height) { - /* We hit the root; return it */ - memcpy( root, ¤t[1 * SPX_N], SPX_N ); - return; - } - - /* - * Check if one of the nodes we have is a part of the - * authentication path; if it is, write it out - */ - if ((((internal_idx << 1) ^ internal_leaf) & ~0x1) == 0) { - memcpy( &auth_path[ h * SPX_N ], - ¤t[(((internal_leaf & 1) ^ 1) + prev_left_adj) * SPX_N], - SPX_N ); - } - - /* - * Check if we're at a left child; if so, stop going up the stack - * Exception: if we've reached the end of the tree, keep on going - * (so we combine the last 2 nodes into the one root node in two - * more iterations) - */ - if ((internal_idx & 1) == 0 && idx < max_idx) { - break; - } - - /* Ok, we're at a right node (or doing the top 3 levels) */ - /* Now combine the left and right logical nodes together */ - - /* Set the address of the node we're creating. */ - int j; - internal_idx_offset >>= 1; - for (j = 0; j < 2; j++) { - set_tree_height(tree_addrx2 + j * 8, h + 1); - set_tree_index(tree_addrx2 + j * 8, - (2 / 2) * (internal_idx & ~1) + j - left_adj + internal_idx_offset ); - } - unsigned char *left = &stackx2[h * 2 * SPX_N]; - thashx2( ¤t[0 * SPX_N], - ¤t[1 * SPX_N], - &left [0 * SPX_N], - ¤t[0 * SPX_N], - 2, ctx, tree_addrx2); - } - - /* We've hit a left child; save the current for when we get the */ - /* corresponding right right */ - memcpy( &stackx2[h * 2 * SPX_N], current, 2 * SPX_N); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/utilsx2.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/utilsx2.h deleted file mode 100644 index e09faddc43..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/utilsx2.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef SPX_UTILSX2_H -#define SPX_UTILSX2_H - -#include - -#include "context.h" -#include "params.h" - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - * - * This implementation uses SIMD to compute internal nodes 2 at a time (in - * parallel) - */ -#define treehashx2 SPX_NAMESPACE(treehashx2) -void treehashx2(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leafx2)( - unsigned char * /* Where to write the leaves */, - const spx_ctx * /* ctx */, - uint32_t addr_idx, void *info), - uint32_t tree_addrx2[2 * 8], void *info); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/wots.c b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/wots.c deleted file mode 100644 index 3babe45e95..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/wots.c +++ /dev/null @@ -1,259 +0,0 @@ -#include -#include - -#include "wots.h" -#include "wotsx2.h" - -#include "address.h" -#include "hash.h" -#include "hashx2.h" -#include "params.h" -#include "thashx2.h" -#include "utils.h" -#include "utilsx2.h" - -// TODO clarify address expectations, and make them more uniform. -// TODO i.e. do we expect types to be set already? -// TODO and do we expect modifications or copies? - -/** - * Computes up the chains - */ -static void gen_chains( - unsigned char *out, - const unsigned char *in, - unsigned int start[SPX_WOTS_LEN], - const unsigned int steps[SPX_WOTS_LEN], - const spx_ctx *ctx, - uint32_t addr[8]) { - uint32_t i, j, k, idx, watching; - int done; - unsigned char empty[SPX_N]; - unsigned char *bufs[4]; - uint32_t addrs[8 * 2]; - - int l; - uint16_t counts[SPX_WOTS_W] = { 0 }; - uint16_t idxs[SPX_WOTS_LEN]; - uint16_t total, newTotal; - - /* set addrs = {addr, addr} */ - for (j = 0; j < 2; j++) { - memcpy(addrs + j * 8, addr, sizeof(uint32_t) * 8); - } - - /* Initialize out with the value at position 'start'. */ - memcpy(out, in, SPX_WOTS_LEN * SPX_N); - - /* Sort the chains in reverse order by steps using counting sort. */ - for (i = 0; i < SPX_WOTS_LEN; i++) { - counts[steps[i]]++; - } - total = 0; - for (l = SPX_WOTS_W - 1; l >= 0; l--) { - newTotal = counts[l] + total; - counts[l] = total; - total = newTotal; - } - for (i = 0; i < SPX_WOTS_LEN; i++) { - idxs[counts[steps[i]]] = i; - counts[steps[i]]++; - } - - /* We got our work cut out for us: do it! */ - for (i = 0; i < SPX_WOTS_LEN; i += 2) { - for (j = 0; j < 2 && i + j < SPX_WOTS_LEN; j++) { - idx = idxs[i + j]; - set_chain_addr(addrs + j * 8, idx); - bufs[j] = out + SPX_N * idx; - } - - /* As the chains are sorted in reverse order, we know that the first - * chain is the longest and the last one is the shortest. We keep - * an eye on whether the last chain is done and then on the one before, - * et cetera. */ - watching = 1; - done = 0; - while (i + watching >= SPX_WOTS_LEN) { - bufs[watching] = &empty[0]; - watching--; - } - - for (k = 0;; k++) { - while (k == steps[idxs[i + watching]]) { - bufs[watching] = &empty[0]; - if (watching == 0) { - done = 1; - break; - } - watching--; - } - if (done) { - break; - } - for (j = 0; j < watching + 1; j++) { - set_hash_addr(addrs + j * 8, k + start[idxs[i + j]]); - } - - thashx2(bufs[0], bufs[1], - bufs[0], bufs[1], 1, ctx, addrs); - } - } -} - -/** - * base_w algorithm as described in draft. - * Interprets an array of bytes as integers in base w. - * This only works when log_w is a divisor of 8. - */ -static void base_w(unsigned int *output, const int out_len, - const unsigned char *input) { - int in = 0; - int out = 0; - unsigned char total = 0; - int bits = 0; - int consumed; - - for (consumed = 0; consumed < out_len; consumed++) { - if (bits == 0) { - total = input[in]; - in++; - bits += 8; - } - bits -= SPX_WOTS_LOGW; - output[out] = (total >> bits) & (SPX_WOTS_W - 1); - out++; - } -} - -/* Computes the WOTS+ checksum over a message (in base_w). */ -static void wots_checksum(unsigned int *csum_base_w, - const unsigned int *msg_base_w) { - unsigned int csum = 0; - unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; - unsigned int i; - - /* Compute checksum. */ - for (i = 0; i < SPX_WOTS_LEN1; i++) { - csum += SPX_WOTS_W - 1 - msg_base_w[i]; - } - - /* Convert checksum to base_w. */ - /* Make sure expected empty zero bits are the least significant bits. */ - csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); - ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); - base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); -} - -/* Takes a message and derives the matching chain lengths. */ -void chain_lengths(unsigned int *lengths, const unsigned char *msg) { - base_w(lengths, SPX_WOTS_LEN1, msg); - wots_checksum(lengths + SPX_WOTS_LEN1, lengths); -} - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const spx_ctx *ctx, uint32_t addr[8]) { - unsigned int steps[SPX_WOTS_LEN]; - unsigned int start[SPX_WOTS_LEN]; - uint32_t i; - - chain_lengths(start, msg); - - for (i = 0; i < SPX_WOTS_LEN; i++) { - steps[i] = SPX_WOTS_W - 1 - start[i]; - } - - gen_chains(pk, sig, start, steps, ctx, addr); -} - -/* - * This generates 2 sequential WOTS public keys - * It also generates the WOTS signature if leaf_info indicates - * that we're signing with one of these WOTS keys - */ -void wots_gen_leafx2(unsigned char *dest, - const spx_ctx *ctx, - uint32_t leaf_idx, void *v_info) { - struct leaf_info_x2 *info = v_info; - uint32_t *leaf_addr = info->leaf_addr; - uint32_t *pk_addr = info->pk_addr; - unsigned int i, j, k; - unsigned char pk_buffer[ 2 * SPX_WOTS_BYTES ]; - unsigned wots_offset = SPX_WOTS_BYTES; - unsigned char *buffer; - uint32_t wots_k_mask; - unsigned wots_sign_index; - - if (((leaf_idx ^ info->wots_sign_leaf) & ~1) == 0) { - /* We're traversing the leaf that's signing; generate the WOTS */ - /* signature */ - wots_k_mask = 0; - wots_sign_index = info->wots_sign_leaf & 1; /* Which of of the 2 */ - /* slots do the signatures come from */ - } else { - /* Nope, we're just generating pk's; turn off the signature logic */ - wots_k_mask = ~0; - wots_sign_index = 0; - } - - for (j = 0; j < 2; j++) { - set_keypair_addr( leaf_addr + j * 8, leaf_idx + j ); - set_keypair_addr( pk_addr + j * 8, leaf_idx + j ); - } - - for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { - uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k to */ - /* the step if we're generating a signature, ~0 if we're not */ - - /* Start with the secret seed */ - for (j = 0; j < 2; j++) { - set_chain_addr(leaf_addr + j * 8, i); - set_hash_addr(leaf_addr + j * 8, 0); - set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTSPRF); - } - prf_addrx2(buffer + 0 * wots_offset, - buffer + 1 * wots_offset, - ctx, leaf_addr); - for (j = 0; j < 2; j++) { - set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTS); - } - - /* Iterate down the WOTS chain */ - for (k = 0;; k++) { - /* Check if one of the values we have needs to be saved as a */ - /* part of the WOTS signature */ - if (k == wots_k) { - memcpy( info->wots_sig + i * SPX_N, - buffer + wots_sign_index * wots_offset, SPX_N ); - } - - /* Check if we hit the top of the chain */ - if (k == SPX_WOTS_W - 1) { - break; - } - - /* Iterate one step on all 4 chains */ - for (j = 0; j < 2; j++) { - set_hash_addr(leaf_addr + j * 8, k); - } - thashx2(buffer + 0 * wots_offset, - buffer + 1 * wots_offset, - buffer + 0 * wots_offset, - buffer + 1 * wots_offset, - 1, ctx, leaf_addr); - } - } - - /* Do the final thash to generate the public keys */ - thashx2(dest + 0 * SPX_N, - dest + 1 * SPX_N, - pk_buffer + 0 * wots_offset, - pk_buffer + 1 * wots_offset, - SPX_WOTS_LEN, ctx, pk_addr); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/wots.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/wots.h deleted file mode 100644 index 4e7692eeef..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/wots.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef SPX_WOTS_H -#define SPX_WOTS_H - -#include - -#include "context.h" -#include "params.h" - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) -void wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const spx_ctx *ctx, uint32_t addr[8]); - -/* - * Compute the chain lengths needed for a given message hash - */ -#define chain_lengths SPX_NAMESPACE(chain_lengths) -void chain_lengths(unsigned int *lengths, const unsigned char *msg); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/wotsx2.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/wotsx2.h deleted file mode 100644 index b58bb61f84..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_aarch64/wotsx2.h +++ /dev/null @@ -1,40 +0,0 @@ -#ifndef WOTSX2_H_ -#define WOTSX2_H_ - -#include "params.h" -#include - -/* - * This is here to provide an interface to the internal wots_gen_leafx2 - * routine. While this routine is not referenced in the package outside of - * wots.c, it is called from the stand-alone benchmark code to characterize - * the performance - */ -struct leaf_info_x2 { - unsigned char *wots_sig; - uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ - uint32_t *wots_steps; - uint32_t leaf_addr[2 * 8]; - uint32_t pk_addr[2 * 8]; -}; - -/* Macro to set the leaf_info to something 'benign', that is, it would */ -/* run with the same time as it does during the real signing process */ -/* Used only by the benchmark code */ -#define INITIALIZE_LEAF_INFO_X2(info, addr, step_buffer) { \ - (info).wots_sig = 0; \ - (info).wots_sign_leaf = ~0; \ - (info).wots_steps = step_buffer; \ - int i; \ - for (i=0; i<2; i++) { \ - memcpy( &(info).leaf_addr[8*i], addr, 32 ); \ - memcpy( &(info).pk_addr[8*i], addr, 32 ); \ - } \ - } - -#define wots_gen_leafx2 SPX_NAMESPACE(wots_gen_leafx2) -void wots_gen_leafx2(unsigned char *dest, - const spx_ctx *ctx, - uint32_t leaf_idx, void *v_info); - -#endif /* WOTSX2_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/LICENSE b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/LICENSE deleted file mode 100644 index 670154e353..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/LICENSE +++ /dev/null @@ -1,116 +0,0 @@ -CC0 1.0 Universal - -Statement of Purpose - -The laws of most jurisdictions throughout the world automatically confer -exclusive Copyright and Related Rights (defined below) upon the creator and -subsequent owner(s) (each and all, an "owner") of an original work of -authorship and/or a database (each, a "Work"). - -Certain owners wish to permanently relinquish those rights to a Work for the -purpose of contributing to a commons of creative, cultural and scientific -works ("Commons") that the public can reliably and without fear of later -claims of infringement build upon, modify, incorporate in other works, reuse -and redistribute as freely as possible in any form whatsoever and for any -purposes, including without limitation commercial purposes. These owners may -contribute to the Commons to promote the ideal of a free culture and the -further production of creative, cultural and scientific works, or to gain -reputation or greater distribution for their Work in part through the use and -efforts of others. - -For these and/or other purposes and motivations, and without any expectation -of additional consideration or compensation, the person associating CC0 with a -Work (the "Affirmer"), to the extent that he or she is an owner of Copyright -and Related Rights in the Work, voluntarily elects to apply CC0 to the Work -and publicly distribute the Work under its terms, with knowledge of his or her -Copyright and Related Rights in the Work and the meaning and intended legal -effect of CC0 on those rights. - -1. Copyright and Related Rights. A Work made available under CC0 may be -protected by copyright and related or neighboring rights ("Copyright and -Related Rights"). Copyright and Related Rights include, but are not limited -to, the following: - - i. the right to reproduce, adapt, distribute, perform, display, communicate, - and translate a Work; - - ii. moral rights retained by the original author(s) and/or performer(s); - - iii. publicity and privacy rights pertaining to a person's image or likeness - depicted in a Work; - - iv. rights protecting against unfair competition in regards to a Work, - subject to the limitations in paragraph 4(a), below; - - v. rights protecting the extraction, dissemination, use and reuse of data in - a Work; - - vi. database rights (such as those arising under Directive 96/9/EC of the - European Parliament and of the Council of 11 March 1996 on the legal - protection of databases, and under any national implementation thereof, - including any amended or successor version of such directive); and - - vii. other similar, equivalent or corresponding rights throughout the world - based on applicable law or treaty, and any national implementations thereof. - -2. Waiver. To the greatest extent permitted by, but not in contravention of, -applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and -unconditionally waives, abandons, and surrenders all of Affirmer's Copyright -and Related Rights and associated claims and causes of action, whether now -known or unknown (including existing as well as future claims and causes of -action), in the Work (i) in all territories worldwide, (ii) for the maximum -duration provided by applicable law or treaty (including future time -extensions), (iii) in any current or future medium and for any number of -copies, and (iv) for any purpose whatsoever, including without limitation -commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes -the Waiver for the benefit of each member of the public at large and to the -detriment of Affirmer's heirs and successors, fully intending that such Waiver -shall not be subject to revocation, rescission, cancellation, termination, or -any other legal or equitable action to disrupt the quiet enjoyment of the Work -by the public as contemplated by Affirmer's express Statement of Purpose. - -3. Public License Fallback. Should any part of the Waiver for any reason be -judged legally invalid or ineffective under applicable law, then the Waiver -shall be preserved to the maximum extent permitted taking into account -Affirmer's express Statement of Purpose. In addition, to the extent the Waiver -is so judged Affirmer hereby grants to each affected person a royalty-free, -non transferable, non sublicensable, non exclusive, irrevocable and -unconditional license to exercise Affirmer's Copyright and Related Rights in -the Work (i) in all territories worldwide, (ii) for the maximum duration -provided by applicable law or treaty (including future time extensions), (iii) -in any current or future medium and for any number of copies, and (iv) for any -purpose whatsoever, including without limitation commercial, advertising or -promotional purposes (the "License"). The License shall be deemed effective as -of the date CC0 was applied by Affirmer to the Work. Should any part of the -License for any reason be judged legally invalid or ineffective under -applicable law, such partial invalidity or ineffectiveness shall not -invalidate the remainder of the License, and in such case Affirmer hereby -affirms that he or she will not (i) exercise any of his or her remaining -Copyright and Related Rights in the Work or (ii) assert any associated claims -and causes of action with respect to the Work, in either case contrary to -Affirmer's express Statement of Purpose. - -4. Limitations and Disclaimers. - - a. No trademark or patent rights held by Affirmer are waived, abandoned, - surrendered, licensed or otherwise affected by this document. - - b. Affirmer offers the Work as-is and makes no representations or warranties - of any kind concerning the Work, express, implied, statutory or otherwise, - including without limitation warranties of title, merchantability, fitness - for a particular purpose, non infringement, or the absence of latent or - other defects, accuracy, or the present or absence of errors, whether or not - discoverable, all to the greatest extent permissible under applicable law. - - c. Affirmer disclaims responsibility for clearing rights of other persons - that may apply to the Work or any use thereof, including without limitation - any person's Copyright and Related Rights in the Work. Further, Affirmer - disclaims responsibility for obtaining any necessary consents, permissions - or other rights required for any use of the Work. - - d. Affirmer understands and acknowledges that Creative Commons is not a - party to this document and has no duty or obligation with respect to this - CC0 or use of the Work. - -For more information, please see - diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/address.c b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/address.c deleted file mode 100644 index d49d9f3b6b..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/address.c +++ /dev/null @@ -1,95 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "utils.h" - -/* - * Specify which level of Merkle tree (the "layer") we're working on - */ -void set_layer_addr(uint32_t addr[8], uint32_t layer) { - ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; -} - -/* - * Specify which Merkle tree within the level (the "tree address") we're working on - */ -void set_tree_addr(uint32_t addr[8], uint64_t tree) { - ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); -} - -/* - * Specify the reason we'll use this address structure for, that is, what - * hash will we compute with it. This is used so that unrelated types of - * hashes don't accidentally get the same address structure. The type will be - * one of the SPX_ADDR_TYPE constants - */ -void set_type(uint32_t addr[8], uint32_t type) { - ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; -} - -/* - * Copy the layer and tree fields of the address structure. This is used - * when we're doing multiple types of hashes within the same Merkle tree - */ -void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { - memcpy( out, in, SPX_OFFSET_TREE + 8 ); -} - -/* These functions are used for OTS addresses. */ - -/* - * Specify which Merkle leaf we're working on; that is, which OTS keypair - * we're talking about. - */ -void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { - /* We have > 256 OTS at the bottom of the Merkle tree; to specify */ - /* which one, we'd need to express it in two bytes */ - ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR2] = (unsigned char)(keypair >> 8); - ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; -} - -/* - * Copy the layer, tree and keypair fields of the address structure. This is - * used when we're doing multiple things within the same OTS keypair - */ -void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { - memcpy( out, in, SPX_OFFSET_TREE + 8 ); - ((unsigned char *)out)[SPX_OFFSET_KP_ADDR2] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR2]; - ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; -} - -/* - * Specify which Merkle chain within the OTS we're working with - * (the chain address) - */ -void set_chain_addr(uint32_t addr[8], uint32_t chain) { - ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; -} - -/* - * Specify where in the Merkle chain we are -* (the hash address) - */ -void set_hash_addr(uint32_t addr[8], uint32_t hash) { - ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; -} - -/* These functions are used for all hash tree addresses (including FORS). */ - -/* - * Specify the height of the node in the Merkle/FORS tree we are in - * (the tree height) - */ -void set_tree_height(uint32_t addr[8], uint32_t tree_height) { - ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; -} - -/* - * Specify the distance from the left edge of the node in the Merkle/FORS tree - * (the tree index) - */ -void set_tree_index(uint32_t addr[8], uint32_t tree_index) { - u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/address.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/address.h deleted file mode 100644 index 24a84eb40c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/address.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef SPX_ADDRESS_H -#define SPX_ADDRESS_H - -#include - -#include "params.h" - -/* The hash types that are passed to set_type */ -#define SPX_ADDR_TYPE_WOTS 0 -#define SPX_ADDR_TYPE_WOTSPK 1 -#define SPX_ADDR_TYPE_HASHTREE 2 -#define SPX_ADDR_TYPE_FORSTREE 3 -#define SPX_ADDR_TYPE_FORSPK 4 -#define SPX_ADDR_TYPE_WOTSPRF 5 -#define SPX_ADDR_TYPE_FORSPRF 6 - -#define set_layer_addr SPX_NAMESPACE(set_layer_addr) -void set_layer_addr(uint32_t addr[8], uint32_t layer); - -#define set_tree_addr SPX_NAMESPACE(set_tree_addr) -void set_tree_addr(uint32_t addr[8], uint64_t tree); - -#define set_type SPX_NAMESPACE(set_type) -void set_type(uint32_t addr[8], uint32_t type); - -/* Copies the layer and tree part of one address into the other */ -#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) -void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for WOTS and FORS addresses. */ - -#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) -void set_keypair_addr(uint32_t addr[8], uint32_t keypair); - -#define set_chain_addr SPX_NAMESPACE(set_chain_addr) -void set_chain_addr(uint32_t addr[8], uint32_t chain); - -#define set_hash_addr SPX_NAMESPACE(set_hash_addr) -void set_hash_addr(uint32_t addr[8], uint32_t hash); - -#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) -void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for all hash tree addresses (including FORS). */ - -#define set_tree_height SPX_NAMESPACE(set_tree_height) -void set_tree_height(uint32_t addr[8], uint32_t tree_height); - -#define set_tree_index SPX_NAMESPACE(set_tree_index) -void set_tree_index(uint32_t addr[8], uint32_t tree_index); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/api.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/api.h deleted file mode 100644 index 854dc65500..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/api.h +++ /dev/null @@ -1,77 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE128SROBUST_AVX2_API_H -#define PQCLEAN_SPHINCSSHAKE128SROBUST_AVX2_API_H - -#include -#include - -#define PQCLEAN_SPHINCSSHAKE128SROBUST_AVX2_CRYPTO_ALGNAME "SPHINCS+-shake-128s-robust" - -#define PQCLEAN_SPHINCSSHAKE128SROBUST_AVX2_CRYPTO_SECRETKEYBYTES 64 -#define PQCLEAN_SPHINCSSHAKE128SROBUST_AVX2_CRYPTO_PUBLICKEYBYTES 32 -#define PQCLEAN_SPHINCSSHAKE128SROBUST_AVX2_CRYPTO_BYTES 7856 - -#define PQCLEAN_SPHINCSSHAKE128SROBUST_AVX2_CRYPTO_SEEDBYTES 48 - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE128SROBUST_AVX2_crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE128SROBUST_AVX2_crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE128SROBUST_AVX2_crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE128SROBUST_AVX2_crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHAKE128SROBUST_AVX2_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHAKE128SROBUST_AVX2_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSSHAKE128SROBUST_AVX2_crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE128SROBUST_AVX2_crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, - const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSSHAKE128SROBUST_AVX2_crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE128SROBUST_AVX2_crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk); -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/context.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/context.h deleted file mode 100644 index 6e0a33f3b7..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/context.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef SPX_CONTEXT_H -#define SPX_CONTEXT_H - -#include - -#include "params.h" - -typedef struct { - uint8_t pub_seed[SPX_N]; - uint8_t sk_seed[SPX_N]; -} spx_ctx; - -#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) -void initialize_hash_function(spx_ctx *ctx); - -#define free_hash_function SPX_NAMESPACE(free_hash_function) -void free_hash_function(spx_ctx *ctx); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/context_shake.c b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/context_shake.c deleted file mode 100644 index 9614a103d3..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/context_shake.c +++ /dev/null @@ -1,12 +0,0 @@ -#include "context.h" - -/* For SHAKE256, there is no immediate reason to initialize at the start, - so this function is an empty operation. */ -void initialize_hash_function(spx_ctx *ctx) { - (void)ctx; /* Suppress an 'unused parameter' warning. */ -} - -// in case the hash function api is heap-based. -void free_hash_function(spx_ctx *ctx) { - (void)ctx; -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/fips202x4.c b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/fips202x4.c deleted file mode 100644 index 1e06fef186..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/fips202x4.c +++ /dev/null @@ -1,210 +0,0 @@ -#include -#include -#include - -#include "fips202.h" -#include "fips202x4.h" - -#define NROUNDS 24 -#define ROL(a, offset) (((a) << (offset)) ^ ((a) >> (64-(offset)))) - -static uint64_t load64(const unsigned char *x) { - unsigned long long r = 0, i; - - for (i = 0; i < 8; ++i) { - r |= (unsigned long long)x[i] << 8 * i; - } - return r; -} - -static void store64(uint8_t *x, uint64_t u) { - unsigned int i; - - for (i = 0; i < 8; ++i) { - x[i] = (uint8_t)u; - u >>= 8; - } -} - -/* Use implementation from the Keccak Code Package */ -extern void KeccakP1600times4_PermuteAll_24rounds(__m256i *s); -#define KeccakF1600_StatePermute4x KeccakP1600times4_PermuteAll_24rounds - -static void keccak_absorb4x(__m256i *s, - unsigned int r, - const unsigned char *m0, - const unsigned char *m1, - const unsigned char *m2, - const unsigned char *m3, - unsigned long long int mlen, - unsigned char p) { - unsigned long long i; - unsigned char t0[200]; - unsigned char t1[200]; - unsigned char t2[200]; - unsigned char t3[200]; - - unsigned long long *ss = (unsigned long long *)s; - - - while (mlen >= r) { - for (i = 0; i < r / 8; ++i) { - ss[4 * i + 0] ^= load64(m0 + 8 * i); - ss[4 * i + 1] ^= load64(m1 + 8 * i); - ss[4 * i + 2] ^= load64(m2 + 8 * i); - ss[4 * i + 3] ^= load64(m3 + 8 * i); - } - - KeccakF1600_StatePermute4x(s); - mlen -= r; - m0 += r; - m1 += r; - m2 += r; - m3 += r; - } - - for (i = 0; i < r; ++i) { - t0[i] = 0; - t1[i] = 0; - t2[i] = 0; - t3[i] = 0; - } - for (i = 0; i < mlen; ++i) { - t0[i] = m0[i]; - t1[i] = m1[i]; - t2[i] = m2[i]; - t3[i] = m3[i]; - } - - t0[i] = p; - t1[i] = p; - t2[i] = p; - t3[i] = p; - - t0[r - 1] |= 128; - t1[r - 1] |= 128; - t2[r - 1] |= 128; - t3[r - 1] |= 128; - - for (i = 0; i < r / 8; ++i) { - ss[4 * i + 0] ^= load64(t0 + 8 * i); - ss[4 * i + 1] ^= load64(t1 + 8 * i); - ss[4 * i + 2] ^= load64(t2 + 8 * i); - ss[4 * i + 3] ^= load64(t3 + 8 * i); - } -} - - -static void keccak_squeezeblocks4x(unsigned char *h0, - unsigned char *h1, - unsigned char *h2, - unsigned char *h3, - unsigned long long int nblocks, - __m256i *s, - unsigned int r) { - unsigned int i; - - unsigned long long *ss = (unsigned long long *)s; - - while (nblocks > 0) { - KeccakF1600_StatePermute4x(s); - for (i = 0; i < (r >> 3); i++) { - store64(h0 + 8 * i, ss[4 * i + 0]); - store64(h1 + 8 * i, ss[4 * i + 1]); - store64(h2 + 8 * i, ss[4 * i + 2]); - store64(h3 + 8 * i, ss[4 * i + 3]); - } - h0 += r; - h1 += r; - h2 += r; - h3 += r; - nblocks--; - } -} - - - -void shake128x4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, unsigned long long outlen, - unsigned char *in0, - unsigned char *in1, - unsigned char *in2, - unsigned char *in3, unsigned long long inlen) { - __m256i s[25]; - unsigned char t0[SHAKE128_RATE]; - unsigned char t1[SHAKE128_RATE]; - unsigned char t2[SHAKE128_RATE]; - unsigned char t3[SHAKE128_RATE]; - unsigned int i; - - /* zero state */ - for (i = 0; i < 25; i++) { - s[i] = _mm256_xor_si256(s[i], s[i]); - } - - /* absorb 4 message of identical length in parallel */ - keccak_absorb4x(s, SHAKE128_RATE, in0, in1, in2, in3, inlen, 0x1F); - - /* Squeeze output */ - keccak_squeezeblocks4x(out0, out1, out2, out3, outlen / SHAKE128_RATE, s, SHAKE128_RATE); - - out0 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; - out1 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; - out2 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; - out3 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; - - if (outlen % SHAKE128_RATE) { - keccak_squeezeblocks4x(t0, t1, t2, t3, 1, s, SHAKE128_RATE); - for (i = 0; i < outlen % SHAKE128_RATE; i++) { - out0[i] = t0[i]; - out1[i] = t1[i]; - out2[i] = t2[i]; - out3[i] = t3[i]; - } - } -} - - -void shake256x4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, unsigned long long outlen, - unsigned char *in0, - unsigned char *in1, - unsigned char *in2, - unsigned char *in3, unsigned long long inlen) { - __m256i s[25]; - unsigned char t0[SHAKE256_RATE]; - unsigned char t1[SHAKE256_RATE]; - unsigned char t2[SHAKE256_RATE]; - unsigned char t3[SHAKE256_RATE]; - unsigned int i; - - /* zero state */ - for (i = 0; i < 25; i++) { - s[i] = _mm256_xor_si256(s[i], s[i]); - } - - /* absorb 4 message of identical length in parallel */ - keccak_absorb4x(s, SHAKE256_RATE, in0, in1, in2, in3, inlen, 0x1F); - - /* Squeeze output */ - keccak_squeezeblocks4x(out0, out1, out2, out3, outlen / SHAKE256_RATE, s, SHAKE256_RATE); - - out0 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; - out1 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; - out2 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; - out3 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; - - if (outlen % SHAKE256_RATE) { - keccak_squeezeblocks4x(t0, t1, t2, t3, 1, s, SHAKE256_RATE); - for (i = 0; i < outlen % SHAKE256_RATE; i++) { - out0[i] = t0[i]; - out1[i] = t1[i]; - out2[i] = t2[i]; - out3[i] = t3[i]; - } - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/fips202x4.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/fips202x4.h deleted file mode 100644 index 2b93c9cd0d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/fips202x4.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef SPX_FIPS202X4_H -#define SPX_FIPS202X4_H - -#include - -#include "params.h" - -#define shake128x4 SPX_NAMESPACE(shake128x4) -void shake128x4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, unsigned long long outlen, - unsigned char *in0, - unsigned char *in1, - unsigned char *in2, - unsigned char *in3, unsigned long long inlen); - -#define shake256x4 SPX_NAMESPACE(shake256x4) -void shake256x4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, unsigned long long outlen, - unsigned char *in0, - unsigned char *in1, - unsigned char *in2, - unsigned char *in3, unsigned long long inlen); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/fors.c b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/fors.c deleted file mode 100644 index f1b0639cfc..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/fors.c +++ /dev/null @@ -1,202 +0,0 @@ -#include -#include -#include - -#include "fors.h" - -#include "address.h" -#include "hash.h" -#include "hashx4.h" -#include "thash.h" -#include "thashx4.h" -#include "utils.h" -#include "utilsx4.h" - -static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, - uint32_t fors_leaf_addr[8]) { - prf_addr(sk, ctx, fors_leaf_addr); -} - -static void fors_gen_skx4(unsigned char *sk0, - unsigned char *sk1, - unsigned char *sk2, - unsigned char *sk3, const spx_ctx *ctx, - uint32_t fors_leaf_addrx4[4 * 8]) { - prf_addrx4(sk0, sk1, sk2, sk3, - ctx, fors_leaf_addrx4); -} - -static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, - const spx_ctx *ctx, - uint32_t fors_leaf_addr[8]) { - thash(leaf, sk, 1, ctx, fors_leaf_addr); -} - -static void fors_sk_to_leafx4(unsigned char *leaf0, - unsigned char *leaf1, - unsigned char *leaf2, - unsigned char *leaf3, - const unsigned char *sk0, - const unsigned char *sk1, - const unsigned char *sk2, - const unsigned char *sk3, - const spx_ctx *ctx, - uint32_t fors_leaf_addrx4[4 * 8]) { - thashx4(leaf0, leaf1, leaf2, leaf3, - sk0, sk1, sk2, sk3, - 1, ctx, fors_leaf_addrx4); -} - -struct fors_gen_leaf_info { - uint32_t leaf_addrx[4 * 8]; -}; - -static void fors_gen_leafx4(unsigned char *leaf, - const spx_ctx *ctx, - uint32_t addr_idx, void *info) { - struct fors_gen_leaf_info *fors_info = info; - uint32_t *fors_leaf_addrx4 = fors_info->leaf_addrx; - unsigned int j; - - /* Only set the parts that the caller doesn't set */ - for (j = 0; j < 4; j++) { - set_tree_index(fors_leaf_addrx4 + j * 8, addr_idx + j); - set_type(fors_leaf_addrx4 + j * 8, SPX_ADDR_TYPE_FORSPRF); - } - - fors_gen_skx4(leaf + 0 * SPX_N, - leaf + 1 * SPX_N, - leaf + 2 * SPX_N, - leaf + 3 * SPX_N, - ctx, fors_leaf_addrx4); - - for (j = 0; j < 4; j++) { - set_type(fors_leaf_addrx4 + j * 8, SPX_ADDR_TYPE_FORSTREE); - } - - fors_sk_to_leafx4(leaf + 0 * SPX_N, - leaf + 1 * SPX_N, - leaf + 2 * SPX_N, - leaf + 3 * SPX_N, - leaf + 0 * SPX_N, - leaf + 1 * SPX_N, - leaf + 2 * SPX_N, - leaf + 3 * SPX_N, - ctx, fors_leaf_addrx4); -} - -/** - * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - * Assumes indices has space for SPX_FORS_TREES integers. - */ -static void message_to_indices(uint32_t *indices, const unsigned char *m) { - unsigned int i, j; - unsigned int offset = 0; - - for (i = 0; i < SPX_FORS_TREES; i++) { - indices[i] = 0; - for (j = 0; j < SPX_FORS_HEIGHT; j++) { - indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); - offset++; - } - } -} - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -void fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]) { - uint32_t indices[SPX_FORS_TREES]; - unsigned char roots[SPX_FORS_TREES * SPX_N]; - uint32_t fors_tree_addr[4 * 8] = {0}; - struct fors_gen_leaf_info fors_info = {0}; - uint32_t *fors_leaf_addr = fors_info.leaf_addrx; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - for (i = 0; i < 4; i++) { - copy_keypair_addr(fors_tree_addr + 8 * i, fors_addr); - set_type(fors_tree_addr + 8 * i, SPX_ADDR_TYPE_FORSTREE); - copy_keypair_addr(fors_leaf_addr + 8 * i, fors_addr); - } - copy_keypair_addr(fors_pk_addr, fors_addr); - set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < SPX_FORS_TREES; i++) { - idx_offset = i * (1 << SPX_FORS_HEIGHT); - - set_tree_height(fors_tree_addr, 0); - set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Include the secret key part that produces the selected leaf node. */ - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); - fors_gen_sk(sig, ctx, fors_tree_addr); - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); - sig += SPX_N; - - /* Compute the authentication path for this leaf node. */ - treehashx4(roots + i * SPX_N, sig, ctx, - indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx4, - fors_tree_addr, &fors_info); - - sig += SPX_N * SPX_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); -} - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -void fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]) { - uint32_t indices[SPX_FORS_TREES]; - unsigned char roots[SPX_FORS_TREES * SPX_N]; - unsigned char leaf[SPX_N]; - uint32_t fors_tree_addr[8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - copy_keypair_addr(fors_tree_addr, fors_addr); - copy_keypair_addr(fors_pk_addr, fors_addr); - - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); - set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < SPX_FORS_TREES; i++) { - idx_offset = i * (1 << SPX_FORS_HEIGHT); - - set_tree_height(fors_tree_addr, 0); - set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Derive the leaf from the included secret key part. */ - fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); - sig += SPX_N; - - /* Derive the corresponding root node of this tree. */ - compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, - sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); - sig += SPX_N * SPX_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/fors.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/fors.h deleted file mode 100644 index 509140a178..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/fors.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef SPX_FORS_H -#define SPX_FORS_H - -#include - -#include "context.h" -#include "params.h" - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -#define fors_sign SPX_NAMESPACE(fors_sign) -void fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]); - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) -void fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/hash.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/hash.h deleted file mode 100644 index f7c87d4c3c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/hash.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef SPX_HASH_H -#define SPX_HASH_H - -#include -#include - -#include "context.h" -#include "params.h" - -#define prf_addr SPX_NAMESPACE(prf_addr) -void prf_addr(unsigned char *out, const spx_ctx *ctx, - const uint32_t addr[8]); - -#define gen_message_random SPX_NAMESPACE(gen_message_random) -void gen_message_random(unsigned char *R, const unsigned char *sk_prf, - const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx); - -#define hash_message SPX_NAMESPACE(hash_message) -void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx); - - - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/hash_shake.c b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/hash_shake.c deleted file mode 100644 index ff5e7ec918..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/hash_shake.c +++ /dev/null @@ -1,83 +0,0 @@ -#include -#include - -#include "hash.h" - -#include "address.h" -#include "fips202.h" -#include "params.h" -#include "utils.h" - -/* - * Computes PRF(pk_seed, sk_seed, addr) - */ -void prf_addr(unsigned char *out, const spx_ctx *ctx, - const uint32_t addr[8]) { - unsigned char buf[2 * SPX_N + SPX_ADDR_BYTES]; - - memcpy(buf, ctx->pub_seed, SPX_N); - memcpy(buf + SPX_N, addr, SPX_ADDR_BYTES); - memcpy(buf + SPX_N + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); - - shake256(out, SPX_N, buf, 2 * SPX_N + SPX_ADDR_BYTES); -} - -/** - * Computes the message-dependent randomness R, using a secret seed and an - * optional randomization value as well as the message. - */ -void gen_message_random(unsigned char *R, const unsigned char *sk_prf, - const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx) { - (void)ctx; - shake256incctx s_inc; - - shake256_inc_init(&s_inc); - shake256_inc_absorb(&s_inc, sk_prf, SPX_N); - shake256_inc_absorb(&s_inc, optrand, SPX_N); - shake256_inc_absorb(&s_inc, m, mlen); - shake256_inc_finalize(&s_inc); - shake256_inc_squeeze(R, SPX_N, &s_inc); - shake256_inc_ctx_release(&s_inc); -} - -/** - * Computes the message hash using R, the public key, and the message. - * Outputs the message digest and the index of the leaf. The index is split in - * the tree index and the leaf index, for convenient copying to an address. - */ -void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx) { - (void)ctx; -#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) -#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) -#define SPX_LEAF_BITS SPX_TREE_HEIGHT -#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) -#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) - - unsigned char buf[SPX_DGST_BYTES]; - unsigned char *bufp = buf; - shake256incctx s_inc; - - shake256_inc_init(&s_inc); - shake256_inc_absorb(&s_inc, R, SPX_N); - shake256_inc_absorb(&s_inc, pk, SPX_PK_BYTES); - shake256_inc_absorb(&s_inc, m, mlen); - shake256_inc_finalize(&s_inc); - shake256_inc_squeeze(buf, SPX_DGST_BYTES, &s_inc); - shake256_inc_ctx_release(&s_inc); - - memcpy(digest, bufp, SPX_FORS_MSG_BYTES); - bufp += SPX_FORS_MSG_BYTES; - - - *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); - *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); - bufp += SPX_TREE_BYTES; - - *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); - *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/hash_shakex4.c b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/hash_shakex4.c deleted file mode 100644 index bbd22eb117..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/hash_shakex4.c +++ /dev/null @@ -1,64 +0,0 @@ -#include -#include - -#include "hashx4.h" - -#include "address.h" -#include "fips202x4.h" -#include "params.h" - -extern void KeccakP1600times4_PermuteAll_24rounds(__m256i *s); - -/* - * 4-way parallel version of prf_addr; takes 4x as much input and output - */ -void prf_addrx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const spx_ctx *ctx, - const uint32_t addrx4[4 * 8]) { - /* As we write and read only a few quadwords, it is more efficient to - * build and extract from the fourway SHAKE256 state by hand. */ - __m256i state[25]; - - for (int i = 0; i < SPX_N / 8; i++) { - state[i] = _mm256_set1_epi64x(((int64_t *)ctx->pub_seed)[i]); - } - for (int i = 0; i < 4; i++) { - state[SPX_N / 8 + i] = _mm256_set_epi32( - (int)addrx4[3 * 8 + 1 + 2 * i], - (int)addrx4[3 * 8 + 2 * i], - (int)addrx4[2 * 8 + 1 + 2 * i], - (int)addrx4[2 * 8 + 2 * i], - (int)addrx4[8 + 1 + 2 * i], - (int)addrx4[8 + 2 * i], - (int)addrx4[1 + 2 * i], - (int)addrx4[2 * i] - ); - } - for (int i = 0; i < SPX_N / 8; i++) { - state[SPX_N / 8 + i + 4] = _mm256_set1_epi64x(((int64_t *)ctx->sk_seed)[i]); - } - - /* SHAKE domain separator and padding. */ - state[SPX_N / 4 + 4] = _mm256_set1_epi64x(0x1f); - for (int i = SPX_N / 4 + 5; i < 16; i++) { - state[i] = _mm256_set1_epi64x(0); - } - // shift unsigned and then cast to avoid UB - state[16] = _mm256_set1_epi64x((long long)(0x80ULL << 56)); - - for (int i = 17; i < 25; i++) { - state[i] = _mm256_set1_epi64x(0); - } - - KeccakP1600times4_PermuteAll_24rounds(&state[0]); - - for (int i = 0; i < SPX_N / 8; i++) { - ((int64_t *)out0)[i] = _mm256_extract_epi64(state[i], 0); - ((int64_t *)out1)[i] = _mm256_extract_epi64(state[i], 1); - ((int64_t *)out2)[i] = _mm256_extract_epi64(state[i], 2); - ((int64_t *)out3)[i] = _mm256_extract_epi64(state[i], 3); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/hashx4.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/hashx4.h deleted file mode 100644 index 3751a0ebd0..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/hashx4.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef SPX_HASHX4_H -#define SPX_HASHX4_H - -#include - -#include "context.h" -#include "params.h" - -#define prf_addrx4 SPX_NAMESPACE(prf_addrx4) -void prf_addrx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const spx_ctx *ctx, - const uint32_t addrx4[4 * 8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/merkle.c b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/merkle.c deleted file mode 100644 index f57811c1ac..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/merkle.c +++ /dev/null @@ -1,64 +0,0 @@ -#include -#include - -#include "merkle.h" - -#include "address.h" -#include "params.h" -#include "utils.h" -#include "utilsx4.h" -#include "wots.h" -#include "wotsx4.h" - -/* - * This generates a Merkle signature (WOTS signature followed by the Merkle - * authentication path). - */ -void merkle_sign(uint8_t *sig, unsigned char *root, - const spx_ctx *ctx, - uint32_t wots_addr[8], uint32_t tree_addr[8], - uint32_t idx_leaf) { - unsigned char *auth_path = sig + SPX_WOTS_BYTES; - uint32_t tree_addrx4[4 * 8] = { 0 }; - int j; - struct leaf_info_x4 info = { 0 }; - unsigned steps[ SPX_WOTS_LEN ]; - - info.wots_sig = sig; - chain_lengths(steps, root); - info.wots_steps = steps; - - for (j = 0; j < 4; j++) { - set_type(&tree_addrx4[8 * j], SPX_ADDR_TYPE_HASHTREE); - set_type(&info.leaf_addr[8 * j], SPX_ADDR_TYPE_WOTS); - set_type(&info.pk_addr[8 * j], SPX_ADDR_TYPE_WOTSPK); - copy_subtree_addr(&tree_addrx4[8 * j], tree_addr); - copy_subtree_addr(&info.leaf_addr[8 * j], wots_addr); - copy_subtree_addr(&info.pk_addr[8 * j], wots_addr); - } - - info.wots_sign_leaf = idx_leaf; - - treehashx4(root, auth_path, ctx, - idx_leaf, 0, - SPX_TREE_HEIGHT, - wots_gen_leafx4, - tree_addrx4, &info); -} - -/* Compute root node of the top-most subtree. */ -void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { - /* We do not need the auth path in key generation, but it simplifies the - code to have just one treehash routine that computes both root and path - in one function. */ - unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; - uint32_t top_tree_addr[8] = {0}; - uint32_t wots_addr[8] = {0}; - - set_layer_addr(top_tree_addr, SPX_D - 1); - set_layer_addr(wots_addr, SPX_D - 1); - - merkle_sign(auth_path, root, ctx, - wots_addr, top_tree_addr, - ~0U /* ~0 means "don't bother generating an auth path */ ); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/merkle.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/merkle.h deleted file mode 100644 index 769cf2e970..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/merkle.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef MERKLE_H_ -#define MERKLE_H_ - -#include - -#include "context.h" -#include "params.h" - -/* Generate a Merkle signature (WOTS signature followed by the Merkle */ -/* authentication path) */ -#define merkle_sign SPX_NAMESPACE(merkle_sign) -void merkle_sign(uint8_t *sig, unsigned char *root, - const spx_ctx *ctx, - uint32_t wots_addr[8], uint32_t tree_addr[8], - uint32_t idx_leaf); - -/* Compute the root node of the top-most subtree. */ -#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) -void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); - -#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/nistapi.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/nistapi.h deleted file mode 100644 index 3cb71afad4..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/nistapi.h +++ /dev/null @@ -1,87 +0,0 @@ -#ifndef SPX_API_H -#define SPX_API_H - -#include -#include - -#include "params.h" - -#define CRYPTO_ALGNAME "SPHINCS+" - -#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES -#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES -#define CRYPTO_BYTES SPX_BYTES -#define CRYPTO_SEEDBYTES (3*SPX_N) - -/* - * Returns the length of a secret key, in bytes - */ -#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) -size_t crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) -size_t crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) -size_t crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) -size_t crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) -int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) -int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) -int crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) -int crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -#define crypto_sign SPX_NAMESPACE(crypto_sign) -int crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) -int crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/params.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/params.h deleted file mode 100644 index 200d84e284..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/params.h +++ /dev/null @@ -1,56 +0,0 @@ -#ifndef SPX_PARAMS_H -#define SPX_PARAMS_H - -#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSSHAKE128SROBUST_AVX2_##s - -/* Hash output length in bytes. */ -#define SPX_N 16 -/* Height of the hypertree. */ -#define SPX_FULL_HEIGHT 63 -/* Number of subtree layer. */ -#define SPX_D 7 -/* FORS tree dimensions. */ -#define SPX_FORS_HEIGHT 12 -#define SPX_FORS_TREES 14 -/* Winternitz parameter, */ -#define SPX_WOTS_W 16 - -/* The hash function is defined by linking a different hash.c file, as opposed - to setting a #define constant. */ - -/* For clarity */ -#define SPX_ADDR_BYTES 32 - -/* WOTS parameters. */ -#define SPX_WOTS_LOGW 4 - -#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) - -/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#define SPX_WOTS_LEN2 3 - -#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) -#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) -#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES - -/* Subtree size. */ -#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) - -//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT -// #error SPX_D should always divide SPX_FULL_HEIGHT -//#endif - -/* FORS parameters. */ -#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) -#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) -#define SPX_FORS_PK_BYTES SPX_N - -/* Resulting SPX sizes. */ -#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ - SPX_FULL_HEIGHT * SPX_N) -#define SPX_PK_BYTES (2 * SPX_N) -#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) - -#include "shake_offsets.h" - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/shake_offsets.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/shake_offsets.h deleted file mode 100644 index 6b28d95d91..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/shake_offsets.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef SHAKE_OFFSETS_H_ -#define SHAKE_OFFSETS_H_ - -/* - * Offsets of various fields in the address structure when we use SHAKE as - * the Sphincs+ hash function - */ - -#define SPX_OFFSET_LAYER 3 /* The byte used to specify the Merkle tree layer */ -#define SPX_OFFSET_TREE 8 /* The start of the 8 byte field used to specify the tree */ -#define SPX_OFFSET_TYPE 19 /* The byte used to specify the hash type (reason) */ -#define SPX_OFFSET_KP_ADDR2 22 /* The high byte used to specify the key pair (which one-time signature) */ -#define SPX_OFFSET_KP_ADDR1 23 /* The low byte used to specify the key pair */ -#define SPX_OFFSET_CHAIN_ADDR 27 /* The byte used to specify the chain address (which Winternitz chain) */ -#define SPX_OFFSET_HASH_ADDR 31 /* The byte used to specify the hash address (where in the Winternitz chain) */ -#define SPX_OFFSET_TREE_HGT 27 /* The byte used to specify the height of this node in the FORS or Merkle tree */ -#define SPX_OFFSET_TREE_INDEX 28 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ - -#define SPX_SHAKE 1 - -#endif /* SHAKE_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/sign.c b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/sign.c deleted file mode 100644 index 9d0c7d1b22..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/sign.c +++ /dev/null @@ -1,286 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "context.h" -#include "fors.h" -#include "hash.h" -#include "merkle.h" -#include "nistapi.h" -#include "params.h" -#include "randombytes.h" -#include "thash.h" -#include "utils.h" -#include "wots.h" - -/* - * Returns the length of a secret key, in bytes - */ -size_t crypto_sign_secretkeybytes(void) { - return CRYPTO_SECRETKEYBYTES; -} - -/* - * Returns the length of a public key, in bytes - */ -size_t crypto_sign_publickeybytes(void) { - return CRYPTO_PUBLICKEYBYTES; -} - -/* - * Returns the length of a signature, in bytes - */ -size_t crypto_sign_bytes(void) { - return CRYPTO_BYTES; -} - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t crypto_sign_seedbytes(void) { - return CRYPTO_SEEDBYTES; -} - -/* - * Generates an SPX key pair given a seed of length - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed) { - spx_ctx ctx; - - /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ - memcpy(sk, seed, CRYPTO_SEEDBYTES); - - memcpy(pk, sk + 2 * SPX_N, SPX_N); - - memcpy(ctx.pub_seed, pk, SPX_N); - memcpy(ctx.sk_seed, sk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - /* Compute root node of the top-most subtree. */ - merkle_gen_root(sk + 3 * SPX_N, &ctx); - - // cleanup - free_hash_function(&ctx); - - memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); - - return 0; -} - -/* - * Generates an SPX key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { - uint8_t seed[CRYPTO_SEEDBYTES]; - randombytes(seed, CRYPTO_SEEDBYTES); - crypto_sign_seed_keypair(pk, sk, seed); - - return 0; -} - -/** - * Returns an array containing a detached signature. - */ -int crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - spx_ctx ctx; - - const uint8_t *sk_prf = sk + SPX_N; - const uint8_t *pk = sk + 2 * SPX_N; - - uint8_t optrand[SPX_N]; - uint8_t mhash[SPX_FORS_MSG_BYTES]; - uint8_t root[SPX_N]; - uint32_t i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - - memcpy(ctx.sk_seed, sk, SPX_N); - memcpy(ctx.pub_seed, pk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - set_type(wots_addr, SPX_ADDR_TYPE_WOTS); - set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); - - /* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ - randombytes(optrand, SPX_N); - /* Compute the digest randomization value. */ - gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); - - /* Derive the message digest and leaf index from R, PK and M. */ - hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); - sig += SPX_N; - - set_tree_addr(wots_addr, tree); - set_keypair_addr(wots_addr, idx_leaf); - - /* Sign the message hash using FORS. */ - fors_sign(sig, root, mhash, &ctx, wots_addr); - sig += SPX_FORS_BYTES; - - for (i = 0; i < SPX_D; i++) { - set_layer_addr(tree_addr, i); - set_tree_addr(tree_addr, tree); - - copy_subtree_addr(wots_addr, tree_addr); - set_keypair_addr(wots_addr, idx_leaf); - - merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); - sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); - tree = tree >> SPX_TREE_HEIGHT; - } - - free_hash_function(&ctx); - - *siglen = SPX_BYTES; - - return 0; -} - -/** - * Verifies a detached signature and message under a given public key. - */ -int crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk) { - spx_ctx ctx; - const uint8_t *pub_root = pk + SPX_N; - uint8_t mhash[SPX_FORS_MSG_BYTES]; - uint8_t wots_pk[SPX_WOTS_BYTES]; - uint8_t root[SPX_N]; - uint8_t leaf[SPX_N]; - unsigned int i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - if (siglen != SPX_BYTES) { - return -1; - } - - memcpy(ctx.pub_seed, pk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - set_type(wots_addr, SPX_ADDR_TYPE_WOTS); - set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); - set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); - - /* Derive the message digest and leaf index from R || PK || M. */ - /* The additional SPX_N is a result of the hash domain separator. */ - hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); - sig += SPX_N; - - /* Layer correctly defaults to 0, so no need to set_layer_addr */ - set_tree_addr(wots_addr, tree); - set_keypair_addr(wots_addr, idx_leaf); - - fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); - sig += SPX_FORS_BYTES; - - /* For each subtree.. */ - for (i = 0; i < SPX_D; i++) { - set_layer_addr(tree_addr, i); - set_tree_addr(tree_addr, tree); - - copy_subtree_addr(wots_addr, tree_addr); - set_keypair_addr(wots_addr, idx_leaf); - - copy_keypair_addr(wots_pk_addr, wots_addr); - - /* The WOTS public key is only correct if the signature was correct. */ - /* Initially, root is the FORS pk, but on subsequent iterations it is - the root of the subtree below the currently processed subtree. */ - wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); - sig += SPX_WOTS_BYTES; - - /* Compute the leaf node using the WOTS public key. */ - thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); - - /* Compute the root node of this subtree. */ - compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, - &ctx, tree_addr); - sig += SPX_TREE_HEIGHT * SPX_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); - tree = tree >> SPX_TREE_HEIGHT; - } - - // cleanup - free_hash_function(&ctx); - - /* Check if the root node equals the root node in the public key. */ - if (memcmp(root, pub_root, SPX_N) != 0) { - return -1; - } - - return 0; -} - - -/** - * Returns an array containing the signature followed by the message. - */ -int crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk) { - size_t siglen; - - crypto_sign_signature(sm, &siglen, m, mlen, sk); - - memmove(sm + SPX_BYTES, m, mlen); - *smlen = siglen + mlen; - - return 0; -} - -/** - * Verifies a given signature-message pair under a given public key. - */ -int crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk) { - /* The API caller does not necessarily know what size a signature should be - but SPHINCS+ signatures are always exactly SPX_BYTES. */ - if (smlen < SPX_BYTES) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - *mlen = smlen - SPX_BYTES; - - if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - /* If verification was successful, move the message to the right place. */ - memmove(m, sm + SPX_BYTES, *mlen); - - return 0; -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/thash.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/thash.h deleted file mode 100644 index 8687ccfb4d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/thash.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef SPX_THASH_H -#define SPX_THASH_H - -#include "context.h" -#include "params.h" - -#include - -#define thash SPX_NAMESPACE(thash) -void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/thash_shake_robust.c b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/thash_shake_robust.c deleted file mode 100644 index 696d53c5cc..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/thash_shake_robust.c +++ /dev/null @@ -1,31 +0,0 @@ -#include -#include - -#include "thash.h" - -#include "address.h" -#include "params.h" -#include "utils.h" - -#include "fips202.h" - -/** - * Takes an array of inblocks concatenated arrays of SPX_N bytes. - */ -void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]) { - PQCLEAN_VLA(uint8_t, buf, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); - PQCLEAN_VLA(uint8_t, bitmask, inblocks * SPX_N); - unsigned int i; - - memcpy(buf, ctx->pub_seed, SPX_N); - memcpy(buf + SPX_N, addr, SPX_ADDR_BYTES); - - shake256(bitmask, inblocks * SPX_N, buf, SPX_N + SPX_ADDR_BYTES); - - for (i = 0; i < inblocks * SPX_N; i++) { - buf[SPX_N + SPX_ADDR_BYTES + i] = in[i] ^ bitmask[i]; - } - - shake256(out, SPX_N, buf, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/thash_shake_robustx4.c b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/thash_shake_robustx4.c deleted file mode 100644 index ce2946b745..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/thash_shake_robustx4.c +++ /dev/null @@ -1,131 +0,0 @@ -#include -#include - -#include "thashx4.h" - -#include "address.h" -#include "params.h" -#include "utils.h" - -#include "fips202x4.h" - -extern void KeccakP1600times4_PermuteAll_24rounds(__m256i *s); - -/** - * 4-way parallel version of thash; takes 4x as much input and output - */ -void thashx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addrx4[4 * 8]) { - if (inblocks == 1 || inblocks == 2) { - /* As we write and read only a few quadwords, it is more efficient to - * build and extract from the fourway SHAKE256 state by hand. */ - __m256i state[25]; - for (int i = 0; i < SPX_N / 8; i++) { - state[i] = _mm256_set1_epi64x(((int64_t *)ctx->pub_seed)[i]); - } - for (int i = 0; i < 4; i++) { - state[SPX_N / 8 + i] = _mm256_set_epi32( - (int)addrx4[3 * 8 + 1 + 2 * i], - (int)addrx4[3 * 8 + 2 * i], - (int)addrx4[2 * 8 + 1 + 2 * i], - (int)addrx4[2 * 8 + 2 * i], - (int)addrx4[8 + 1 + 2 * i], - (int)addrx4[8 + 2 * i], - (int)addrx4[1 + 2 * i], - (int)addrx4[2 * i] - ); - } - - /* SHAKE domain separator and padding */ - state[SPX_N / 8 + 4] = _mm256_set1_epi64x(0x1f); - for (int i = SPX_N / 8 + 5; i < 16; i++) { - state[i] = _mm256_set1_epi64x(0); - } - state[16] = _mm256_set1_epi64x((long long)(0x80ULL << 56)); - - for (int i = 17; i < 25; i++) { - state[i] = _mm256_set1_epi64x(0); - } - - /* We will permutate state2 with f1600x4 to compute the bitmask, - * but first we'll copy it to state2 which will be used to compute - * the final output, as its input is alsmost identical. */ - __m256i state2[25]; - memcpy(state2, state, 800); - - KeccakP1600times4_PermuteAll_24rounds(&state[0]); - - /* By copying from state, state2 already contains the pub_seed - * and addres. We just need to copy in the input blocks xorred with - * the bitmask we just computed. */ - for (unsigned int i = 0; i < (SPX_N / 8) * inblocks; i++) { - state2[SPX_N / 8 + 4 + i] = _mm256_xor_si256( - state[i], - _mm256_set_epi64x( - ((int64_t *)in3)[i], - ((int64_t *)in2)[i], - ((int64_t *)in1)[i], - ((int64_t *)in0)[i] - ) - ); - } - - /* Domain separator and start of padding. Note that the quadwords - * around are already zeroed for state from which we copied. - * We do a XOR instead of a set as this might be the 16th quadword - * when N=32 and inblocks=2, which already contains the end - * of the padding. */ - state2[(SPX_N / 8) * (1 + inblocks) + 4] = _mm256_xor_si256( - state2[(SPX_N / 8) * (1 + inblocks) + 4], - _mm256_set1_epi64x(0x1f) - ); - - KeccakP1600times4_PermuteAll_24rounds(&state2[0]); - - for (int i = 0; i < SPX_N / 8; i++) { - ((int64_t *)out0)[i] = _mm256_extract_epi64(state2[i], 0); - ((int64_t *)out1)[i] = _mm256_extract_epi64(state2[i], 1); - ((int64_t *)out2)[i] = _mm256_extract_epi64(state2[i], 2); - ((int64_t *)out3)[i] = _mm256_extract_epi64(state2[i], 3); - } - } else { - PQCLEAN_VLA(unsigned char, buf0, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); - PQCLEAN_VLA(unsigned char, buf1, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); - PQCLEAN_VLA(unsigned char, buf2, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); - PQCLEAN_VLA(unsigned char, buf3, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); - PQCLEAN_VLA(unsigned char, bitmask0, inblocks * SPX_N); - PQCLEAN_VLA(unsigned char, bitmask1, inblocks * SPX_N); - PQCLEAN_VLA(unsigned char, bitmask2, inblocks * SPX_N); - PQCLEAN_VLA(unsigned char, bitmask3, inblocks * SPX_N); - unsigned int i; - - memcpy(buf0, ctx->pub_seed, SPX_N); - memcpy(buf1, ctx->pub_seed, SPX_N); - memcpy(buf2, ctx->pub_seed, SPX_N); - memcpy(buf3, ctx->pub_seed, SPX_N); - memcpy(buf0 + SPX_N, addrx4 + 0 * 8, SPX_ADDR_BYTES); - memcpy(buf1 + SPX_N, addrx4 + 1 * 8, SPX_ADDR_BYTES); - memcpy(buf2 + SPX_N, addrx4 + 2 * 8, SPX_ADDR_BYTES); - memcpy(buf3 + SPX_N, addrx4 + 3 * 8, SPX_ADDR_BYTES); - - shake256x4(bitmask0, bitmask1, bitmask2, bitmask3, inblocks * SPX_N, - buf0, buf1, buf2, buf3, SPX_N + SPX_ADDR_BYTES); - - for (i = 0; i < inblocks * SPX_N; i++) { - buf0[SPX_N + SPX_ADDR_BYTES + i] = in0[i] ^ bitmask0[i]; - buf1[SPX_N + SPX_ADDR_BYTES + i] = in1[i] ^ bitmask1[i]; - buf2[SPX_N + SPX_ADDR_BYTES + i] = in2[i] ^ bitmask2[i]; - buf3[SPX_N + SPX_ADDR_BYTES + i] = in3[i] ^ bitmask3[i]; - } - - shake256x4(out0, out1, out2, out3, SPX_N, - buf0, buf1, buf2, buf3, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/thashx4.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/thashx4.h deleted file mode 100644 index 64798a3727..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/thashx4.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef SPX_THASHX4_H -#define SPX_THASHX4_H - -#include - -#include "context.h" -#include "params.h" - -#define thashx4 SPX_NAMESPACE(thashx4) -void thashx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addrx4[4 * 8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/utils.c b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/utils.c deleted file mode 100644 index 177b541fb9..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/utils.c +++ /dev/null @@ -1,148 +0,0 @@ -#include - -#include "utils.h" - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "thash.h" - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void ull_to_bytes(unsigned char *out, unsigned int outlen, - unsigned long long in) { - int i; - - /* Iterate over out in decreasing order, for big-endianness. */ - for (i = (signed int)outlen - 1; i >= 0; i--) { - out[i] = in & 0xff; - in = in >> 8; - } -} - -void u32_to_bytes(unsigned char *out, uint32_t in) { - out[0] = (unsigned char)(in >> 24); - out[1] = (unsigned char)(in >> 16); - out[2] = (unsigned char)(in >> 8); - out[3] = (unsigned char)in; -} - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { - unsigned long long retval = 0; - unsigned int i; - - for (i = 0; i < inlen; i++) { - retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); - } - return retval; -} - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void compute_root(unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const spx_ctx *ctx, uint32_t addr[8]) { - uint32_t i; - unsigned char buffer[2 * SPX_N]; - - /* If leaf_idx is odd (last bit = 1), current path element is a right child - and auth_path has to go left. Otherwise it is the other way around. */ - if (leaf_idx & 1) { - memcpy(buffer + SPX_N, leaf, SPX_N); - memcpy(buffer, auth_path, SPX_N); - } else { - memcpy(buffer, leaf, SPX_N); - memcpy(buffer + SPX_N, auth_path, SPX_N); - } - auth_path += SPX_N; - - for (i = 0; i < tree_height - 1; i++) { - leaf_idx >>= 1; - idx_offset >>= 1; - /* Set the address of the node we're creating. */ - set_tree_height(addr, i + 1); - set_tree_index(addr, leaf_idx + idx_offset); - - /* Pick the right or left neighbor, depending on parity of the node. */ - if (leaf_idx & 1) { - thash(buffer + SPX_N, buffer, 2, ctx, addr); - memcpy(buffer, auth_path, SPX_N); - } else { - thash(buffer, buffer, 2, ctx, addr); - memcpy(buffer + SPX_N, auth_path, SPX_N); - } - auth_path += SPX_N; - } - - /* The last iteration is exceptional; we do not copy an auth_path node. */ - leaf_idx >>= 1; - idx_offset >>= 1; - set_tree_height(addr, tree_height); - set_tree_index(addr, leaf_idx + idx_offset); - thash(root, buffer, 2, ctx, addr); -} - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const spx_ctx * /* ctx */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), - uint32_t tree_addr[8]) { - PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); - PQCLEAN_VLA(unsigned int, heights, tree_height + 1); - unsigned int offset = 0; - uint32_t idx; - uint32_t tree_idx; - - for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { - /* Add the next leaf node to the stack. */ - gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); - offset++; - heights[offset - 1] = 0; - - /* If this is a node we need for the auth path.. */ - if ((leaf_idx ^ 0x1) == idx) { - memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); - } - - /* While the top-most nodes are of equal height.. */ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { - /* Compute index of the new node, in the next layer. */ - tree_idx = (idx >> (heights[offset - 1] + 1)); - - /* Set the address of the node we're creating. */ - set_tree_height(tree_addr, heights[offset - 1] + 1); - set_tree_index(tree_addr, - tree_idx + (idx_offset >> (heights[offset - 1] + 1))); - /* Hash the top-most nodes from the stack together. */ - thash(stack + (offset - 2)*SPX_N, - stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); - offset--; - /* Note that the top-most node is now one layer higher. */ - heights[offset - 1]++; - - /* If this is a node we need for the auth path.. */ - if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_path + heights[offset - 1]*SPX_N, - stack + (offset - 1)*SPX_N, SPX_N); - } - } - } - memcpy(root, stack, SPX_N); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/utils.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/utils.h deleted file mode 100644 index 64f5d5a53a..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/utils.h +++ /dev/null @@ -1,58 +0,0 @@ -#ifndef SPX_UTILS_H -#define SPX_UTILS_H - -#include - -#include "compat.h" -#include "context.h" -#include "params.h" - - -/* To support MSVC use alloca() instead of VLAs. See #20. */ - - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) -void ull_to_bytes(unsigned char *out, unsigned int outlen, - unsigned long long in); -#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) -void u32_to_bytes(unsigned char *out, uint32_t in); - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) -unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -#define compute_root SPX_NAMESPACE(compute_root) -void compute_root(unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const spx_ctx *ctx, uint32_t addr[8]); - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -#define treehash SPX_NAMESPACE(treehash) -void treehash(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const spx_ctx *ctx /* ctx */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), - uint32_t tree_addr[8]); - - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/utilsx4.c b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/utilsx4.c deleted file mode 100644 index 1638677194..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/utilsx4.c +++ /dev/null @@ -1,138 +0,0 @@ -#include - -#include "utilsx4.h" - -#include "address.h" -#include "params.h" -#include "thashx4.h" -#include "utils.h" - -/* - * Generate the entire Merkle tree, computing the authentication path for leaf_idx, - * and the resulting root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) - * - * This expects tree_addrx4 to be initialized to 4 parallel addr structures for - * the Merkle tree nodes - * - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - * - * This works by using the standard Merkle tree building algorithm, except - * that each 'node' tracked is actually 4 consecutive nodes in the real tree. - * When we combine two logical nodes ABCD and WXYZ, we perform the H - * operation on adjacent real nodes, forming the parent logical node - * (AB)(CD)(WX)(YZ) - * - * When we get to the top two levels of the real tree (where there is only - * one logical node), we continue this operation two more times; the right - * most real node will by the actual root (and the other 3 nodes will be - * garbage). We follow the same thashx4 logic so that the 'extract - * authentication path components' part of the loop is still executed (and - * to simplify the code somewhat) - * - * This currently assumes tree_height >= 2; I suspect that doing an adjusting - * idx, addr_idx on the gen_leafx4 call if tree_height < 2 would fix it; since - * we don't actually use such short trees, I haven't bothered - */ -void treehashx4(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, - uint32_t tree_height, - void (*gen_leafx4)( - unsigned char * /* Where to write the leaves */, - const spx_ctx *, - uint32_t idx, void *info), - uint32_t tree_addrx4[4 * 8], - void *info) { - /* This is where we keep the intermediate nodes */ - PQCLEAN_VLA(unsigned char, stackx4, tree_height * 4 * SPX_N); - uint32_t left_adj = 0, prev_left_adj = 0; /* When we're doing the top 3 */ - /* levels, the left-most part of the tree isn't at the beginning */ - /* of current[]. These give the offset of the actual start */ - - uint32_t idx; - uint32_t max_idx = (1U << (tree_height - 2)) - 1; - for (idx = 0;; idx++) { - unsigned char current[4 * SPX_N]; /* Current logical node */ - gen_leafx4( current, ctx, 4 * idx + idx_offset, - info ); - - /* Now combine the freshly generated right node with previously */ - /* generated left ones */ - uint32_t internal_idx_offset = idx_offset; - uint32_t internal_idx = idx; - uint32_t internal_leaf = leaf_idx; - uint32_t h; /* The height we are in the Merkle tree */ - for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { - - /* Special processing if we're at the top of the tree */ - if (h >= tree_height - 2) { - if (h == tree_height) { - /* We hit the root; return it */ - memcpy( root, ¤t[3 * SPX_N], SPX_N ); - return; - } - /* The tree indexing logic is a bit off in this case */ - /* Adjust it so that the left-most node of the part of */ - /* the tree that we're processing has index 0 */ - prev_left_adj = left_adj; - left_adj = 4U - (1 << (tree_height - h - 1)); - } - - /* Check if we hit the top of the tree */ - if (h == tree_height) { - /* We hit the root; return it */ - memcpy( root, ¤t[3 * SPX_N], SPX_N ); - return; - } - - /* - * Check if one of the nodes we have is a part of the - * authentication path; if it is, write it out - */ - if ((((internal_idx << 2) ^ internal_leaf) & ~0x3U) == 0) { - memcpy( &auth_path[ h * SPX_N ], - ¤t[(((internal_leaf & 3) ^ 1) + prev_left_adj) * SPX_N], - SPX_N ); - } - - /* - * Check if we're at a left child; if so, stop going up the stack - * Exception: if we've reached the end of the tree, keep on going - * (so we combine the last 4 nodes into the one root node in two - * more iterations) - */ - if ((internal_idx & 1) == 0 && idx < max_idx) { - break; - } - - /* Ok, we're at a right node (or doing the top 3 levels) */ - /* Now combine the left and right logical nodes together */ - - /* Set the address of the node we're creating. */ - unsigned int j; - internal_idx_offset >>= 1; - for (j = 0; j < 4; j++) { - set_tree_height(tree_addrx4 + j * 8, h + 1); - set_tree_index(tree_addrx4 + j * 8, - (4 / 2) * (internal_idx & ~1U) + j - left_adj + internal_idx_offset ); - } - unsigned char *left = &stackx4[h * 4 * SPX_N]; - thashx4( ¤t[0 * SPX_N], - ¤t[1 * SPX_N], - ¤t[2 * SPX_N], - ¤t[3 * SPX_N], - &left [0 * SPX_N], - &left [2 * SPX_N], - ¤t[0 * SPX_N], - ¤t[2 * SPX_N], - 2, ctx, tree_addrx4); - } - - /* We've hit a left child; save the current for when we get the */ - /* corresponding right right */ - memcpy( &stackx4[h * 4 * SPX_N], current, 4 * SPX_N); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/utilsx4.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/utilsx4.h deleted file mode 100644 index facb874b18..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/utilsx4.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef SPX_UTILSX4_H -#define SPX_UTILSX4_H - -#include - -#include "context.h" -#include "params.h" - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - * - * This implementation uses AVX to compute internal nodes 4 at a time (in - * parallel) - */ -#define treehashx4 SPX_NAMESPACE(treehashx4) -void treehashx4(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leafx4)( - unsigned char * /* Where to write the leaves */, - const spx_ctx * /* ctx */, - uint32_t addr_idx, void *info), - uint32_t tree_addrx4[4 * 8], void *info); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/wots.c b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/wots.c deleted file mode 100644 index 4d5041ce05..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/wots.c +++ /dev/null @@ -1,269 +0,0 @@ -#include -#include - -#include "wots.h" - -#include "address.h" -#include "hash.h" -#include "hashx4.h" -#include "params.h" -#include "thash.h" -#include "thashx4.h" -#include "utils.h" -#include "utilsx4.h" -#include "wotsx4.h" - -// TODO clarify address expectations, and make them more uniform. -// TODO i.e. do we expect types to be set already? -// TODO and do we expect modifications or copies? - -/** - * Computes up the chains - */ -static void gen_chains( - unsigned char *out, - const unsigned char *in, - unsigned int start[SPX_WOTS_LEN], - const unsigned int steps[SPX_WOTS_LEN], - const spx_ctx *ctx, - uint32_t addr[8]) { - uint32_t i, j, k, idx, watching; - int done; - unsigned char empty[SPX_N]; - unsigned char *bufs[4]; - uint32_t addrs[8 * 4]; - - int l; - uint16_t counts[SPX_WOTS_W] = { 0 }; - uint16_t idxs[SPX_WOTS_LEN]; - uint16_t total, newTotal; - - /* set addrs = {addr, addr, addr, addr} */ - for (j = 0; j < 4; j++) { - memcpy(addrs + j * 8, addr, sizeof(uint32_t) * 8); - } - - /* Initialize out with the value at position 'start'. */ - memcpy(out, in, SPX_WOTS_LEN * SPX_N); - - /* Sort the chains in reverse order by steps using counting sort. */ - for (i = 0; i < SPX_WOTS_LEN; i++) { - counts[steps[i]]++; - } - total = 0; - for (l = SPX_WOTS_W - 1; l >= 0; l--) { - newTotal = counts[l] + total; - counts[l] = total; - total = newTotal; - } - for (i = 0; i < SPX_WOTS_LEN; i++) { - idxs[counts[steps[i]]] = (uint16_t)i; - counts[steps[i]]++; - } - - /* We got our work cut out for us: do it! */ - for (i = 0; i < SPX_WOTS_LEN; i += 4) { - for (j = 0; j < 4 && i + j < SPX_WOTS_LEN; j++) { - idx = idxs[i + j]; - set_chain_addr(addrs + j * 8, idx); - bufs[j] = out + SPX_N * idx; - } - - /* As the chains are sorted in reverse order, we know that the first - * chain is the longest and the last one is the shortest. We keep - * an eye on whether the last chain is done and then on the one before, - * et cetera. */ - watching = 3; - done = 0; - while (i + watching >= SPX_WOTS_LEN) { - bufs[watching] = &empty[0]; - watching--; - } - - for (k = 0;; k++) { - while (k == steps[idxs[i + watching]]) { - bufs[watching] = &empty[0]; - if (watching == 0) { - done = 1; - break; - } - watching--; - } - if (done) { - break; - } - for (j = 0; j < watching + 1; j++) { - set_hash_addr(addrs + j * 8, k + start[idxs[i + j]]); - } - - thashx4(bufs[0], bufs[1], bufs[2], bufs[3], - bufs[0], bufs[1], bufs[2], bufs[3], 1, ctx, addrs); - } - } -} - -/** - * base_w algorithm as described in draft. - * Interprets an array of bytes as integers in base w. - * This only works when log_w is a divisor of 8. - */ -static void base_w(unsigned int *output, const int out_len, - const unsigned char *input) { - int in = 0; - int out = 0; - unsigned char total = 0; - int bits = 0; - int consumed; - - for (consumed = 0; consumed < out_len; consumed++) { - if (bits == 0) { - total = input[in]; - in++; - bits += 8; - } - bits -= SPX_WOTS_LOGW; - output[out] = (total >> bits) & (SPX_WOTS_W - 1); - out++; - } -} - -/* Computes the WOTS+ checksum over a message (in base_w). */ -static void wots_checksum(unsigned int *csum_base_w, - const unsigned int *msg_base_w) { - unsigned int csum = 0; - unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; - unsigned int i; - - /* Compute checksum. */ - for (i = 0; i < SPX_WOTS_LEN1; i++) { - csum += SPX_WOTS_W - 1 - msg_base_w[i]; - } - - /* Convert checksum to base_w. */ - /* Make sure expected empty zero bits are the least significant bits. */ - csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); - ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); - base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); -} - -/* Takes a message and derives the matching chain lengths. */ -void chain_lengths(unsigned int *lengths, const unsigned char *msg) { - base_w(lengths, SPX_WOTS_LEN1, msg); - wots_checksum(lengths + SPX_WOTS_LEN1, lengths); -} - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const spx_ctx *ctx, uint32_t addr[8]) { - unsigned int steps[SPX_WOTS_LEN]; - unsigned int start[SPX_WOTS_LEN]; - uint32_t i; - - chain_lengths(start, msg); - - for (i = 0; i < SPX_WOTS_LEN; i++) { - steps[i] = SPX_WOTS_W - 1 - start[i]; - } - - gen_chains(pk, sig, start, steps, ctx, addr); -} - -/* - * This generates 4 sequential WOTS public keys - * It also generates the WOTS signature if leaf_info indicates - * that we're signing with one of these WOTS keys - */ -void wots_gen_leafx4(unsigned char *dest, - const spx_ctx *ctx, - uint32_t leaf_idx, void *v_info) { - struct leaf_info_x4 *info = v_info; - uint32_t *leaf_addr = info->leaf_addr; - uint32_t *pk_addr = info->pk_addr; - unsigned int i, j, k; - unsigned char pk_buffer[ 4 * SPX_WOTS_BYTES ]; - unsigned wots_offset = SPX_WOTS_BYTES; - unsigned char *buffer; - uint32_t wots_k_mask; - unsigned wots_sign_index; - - if (((leaf_idx ^ info->wots_sign_leaf) & ~3U) == 0) { - /* We're traversing the leaf that's signing; generate the WOTS */ - /* signature */ - wots_k_mask = 0; - wots_sign_index = info->wots_sign_leaf & 3; /* Which of of the 4 */ - /* 4 slots do the signatures come from */ - } else { - /* Nope, we're just generating pk's; turn off the signature logic */ - wots_k_mask = (uint32_t)~0; - wots_sign_index = 0; - } - - for (j = 0; j < 4; j++) { - set_keypair_addr( leaf_addr + j * 8, leaf_idx + j ); - set_keypair_addr( pk_addr + j * 8, leaf_idx + j ); - } - - for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { - uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k to */ - /* the step if we're generating a signature, ~0 if we're not */ - - /* Start with the secret seed */ - for (j = 0; j < 4; j++) { - set_chain_addr(leaf_addr + j * 8, i); - set_hash_addr(leaf_addr + j * 8, 0); - set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTSPRF); - } - prf_addrx4(buffer + 0 * wots_offset, - buffer + 1 * wots_offset, - buffer + 2 * wots_offset, - buffer + 3 * wots_offset, - ctx, leaf_addr); - - for (j = 0; j < 4; j++) { - set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTS); - } - - /* Iterate down the WOTS chain */ - for (k = 0;; k++) { - /* Check if one of the values we have needs to be saved as a */ - /* part of the WOTS signature */ - if (k == wots_k) { - memcpy( info->wots_sig + i * SPX_N, - buffer + wots_sign_index * wots_offset, SPX_N ); - } - - /* Check if we hit the top of the chain */ - if (k == SPX_WOTS_W - 1) { - break; - } - - /* Iterate one step on all 4 chains */ - for (j = 0; j < 4; j++) { - set_hash_addr(leaf_addr + j * 8, k); - } - thashx4(buffer + 0 * wots_offset, - buffer + 1 * wots_offset, - buffer + 2 * wots_offset, - buffer + 3 * wots_offset, - buffer + 0 * wots_offset, - buffer + 1 * wots_offset, - buffer + 2 * wots_offset, - buffer + 3 * wots_offset, 1, ctx, leaf_addr); - } - } - - /* Do the final thash to generate the public keys */ - thashx4(dest + 0 * SPX_N, - dest + 1 * SPX_N, - dest + 2 * SPX_N, - dest + 3 * SPX_N, - pk_buffer + 0 * wots_offset, - pk_buffer + 1 * wots_offset, - pk_buffer + 2 * wots_offset, - pk_buffer + 3 * wots_offset, SPX_WOTS_LEN, ctx, pk_addr); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/wots.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/wots.h deleted file mode 100644 index 4e7692eeef..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/wots.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef SPX_WOTS_H -#define SPX_WOTS_H - -#include - -#include "context.h" -#include "params.h" - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) -void wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const spx_ctx *ctx, uint32_t addr[8]); - -/* - * Compute the chain lengths needed for a given message hash - */ -#define chain_lengths SPX_NAMESPACE(chain_lengths) -void chain_lengths(unsigned int *lengths, const unsigned char *msg); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/wotsx4.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/wotsx4.h deleted file mode 100644 index cd634f1743..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_avx2/wotsx4.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef WOTSX4_H_ -#define WOTSX4_H_ - -#include - -#include "params.h" - -/* - * This is here to provide an interface to the internal wots_gen_leafx4 - * routine. While this routine is not referenced in the package outside of - * wots.c, it is called from the stand-alone benchmark code to characterize - * the performance - */ -struct leaf_info_x4 { - unsigned char *wots_sig; - uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ - uint32_t *wots_steps; - uint32_t leaf_addr[4 * 8]; - uint32_t pk_addr[4 * 8]; -}; - -/* Macro to set the leaf_info to something 'benign', that is, it would */ -/* run with the same time as it does during the real signing process */ -/* Used only by the benchmark code */ -#define INITIALIZE_LEAF_INFO_X4(info, addr, step_buffer) { \ - (info).wots_sig = 0; \ - (info).wots_sign_leaf = ~0; \ - (info).wots_steps = step_buffer; \ - int i; \ - for (i=0; i<4; i++) { \ - memcpy( &(info).leaf_addr[8*i], addr, 32 ); \ - memcpy( &(info).pk_addr[8*i], addr, 32 ); \ - } \ - } - -#define wots_gen_leafx4 SPX_NAMESPACE(wots_gen_leafx4) -void wots_gen_leafx4(unsigned char *dest, - const spx_ctx *ctx, - uint32_t leaf_idx, void *v_info); - -#endif /* WOTSX4_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/LICENSE b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/LICENSE deleted file mode 100644 index 670154e353..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/LICENSE +++ /dev/null @@ -1,116 +0,0 @@ -CC0 1.0 Universal - -Statement of Purpose - -The laws of most jurisdictions throughout the world automatically confer -exclusive Copyright and Related Rights (defined below) upon the creator and -subsequent owner(s) (each and all, an "owner") of an original work of -authorship and/or a database (each, a "Work"). - -Certain owners wish to permanently relinquish those rights to a Work for the -purpose of contributing to a commons of creative, cultural and scientific -works ("Commons") that the public can reliably and without fear of later -claims of infringement build upon, modify, incorporate in other works, reuse -and redistribute as freely as possible in any form whatsoever and for any -purposes, including without limitation commercial purposes. These owners may -contribute to the Commons to promote the ideal of a free culture and the -further production of creative, cultural and scientific works, or to gain -reputation or greater distribution for their Work in part through the use and -efforts of others. - -For these and/or other purposes and motivations, and without any expectation -of additional consideration or compensation, the person associating CC0 with a -Work (the "Affirmer"), to the extent that he or she is an owner of Copyright -and Related Rights in the Work, voluntarily elects to apply CC0 to the Work -and publicly distribute the Work under its terms, with knowledge of his or her -Copyright and Related Rights in the Work and the meaning and intended legal -effect of CC0 on those rights. - -1. Copyright and Related Rights. A Work made available under CC0 may be -protected by copyright and related or neighboring rights ("Copyright and -Related Rights"). Copyright and Related Rights include, but are not limited -to, the following: - - i. the right to reproduce, adapt, distribute, perform, display, communicate, - and translate a Work; - - ii. moral rights retained by the original author(s) and/or performer(s); - - iii. publicity and privacy rights pertaining to a person's image or likeness - depicted in a Work; - - iv. rights protecting against unfair competition in regards to a Work, - subject to the limitations in paragraph 4(a), below; - - v. rights protecting the extraction, dissemination, use and reuse of data in - a Work; - - vi. database rights (such as those arising under Directive 96/9/EC of the - European Parliament and of the Council of 11 March 1996 on the legal - protection of databases, and under any national implementation thereof, - including any amended or successor version of such directive); and - - vii. other similar, equivalent or corresponding rights throughout the world - based on applicable law or treaty, and any national implementations thereof. - -2. Waiver. To the greatest extent permitted by, but not in contravention of, -applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and -unconditionally waives, abandons, and surrenders all of Affirmer's Copyright -and Related Rights and associated claims and causes of action, whether now -known or unknown (including existing as well as future claims and causes of -action), in the Work (i) in all territories worldwide, (ii) for the maximum -duration provided by applicable law or treaty (including future time -extensions), (iii) in any current or future medium and for any number of -copies, and (iv) for any purpose whatsoever, including without limitation -commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes -the Waiver for the benefit of each member of the public at large and to the -detriment of Affirmer's heirs and successors, fully intending that such Waiver -shall not be subject to revocation, rescission, cancellation, termination, or -any other legal or equitable action to disrupt the quiet enjoyment of the Work -by the public as contemplated by Affirmer's express Statement of Purpose. - -3. Public License Fallback. Should any part of the Waiver for any reason be -judged legally invalid or ineffective under applicable law, then the Waiver -shall be preserved to the maximum extent permitted taking into account -Affirmer's express Statement of Purpose. In addition, to the extent the Waiver -is so judged Affirmer hereby grants to each affected person a royalty-free, -non transferable, non sublicensable, non exclusive, irrevocable and -unconditional license to exercise Affirmer's Copyright and Related Rights in -the Work (i) in all territories worldwide, (ii) for the maximum duration -provided by applicable law or treaty (including future time extensions), (iii) -in any current or future medium and for any number of copies, and (iv) for any -purpose whatsoever, including without limitation commercial, advertising or -promotional purposes (the "License"). The License shall be deemed effective as -of the date CC0 was applied by Affirmer to the Work. Should any part of the -License for any reason be judged legally invalid or ineffective under -applicable law, such partial invalidity or ineffectiveness shall not -invalidate the remainder of the License, and in such case Affirmer hereby -affirms that he or she will not (i) exercise any of his or her remaining -Copyright and Related Rights in the Work or (ii) assert any associated claims -and causes of action with respect to the Work, in either case contrary to -Affirmer's express Statement of Purpose. - -4. Limitations and Disclaimers. - - a. No trademark or patent rights held by Affirmer are waived, abandoned, - surrendered, licensed or otherwise affected by this document. - - b. Affirmer offers the Work as-is and makes no representations or warranties - of any kind concerning the Work, express, implied, statutory or otherwise, - including without limitation warranties of title, merchantability, fitness - for a particular purpose, non infringement, or the absence of latent or - other defects, accuracy, or the present or absence of errors, whether or not - discoverable, all to the greatest extent permissible under applicable law. - - c. Affirmer disclaims responsibility for clearing rights of other persons - that may apply to the Work or any use thereof, including without limitation - any person's Copyright and Related Rights in the Work. Further, Affirmer - disclaims responsibility for obtaining any necessary consents, permissions - or other rights required for any use of the Work. - - d. Affirmer understands and acknowledges that Creative Commons is not a - party to this document and has no duty or obligation with respect to this - CC0 or use of the Work. - -For more information, please see - diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/address.c b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/address.c deleted file mode 100644 index d49d9f3b6b..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/address.c +++ /dev/null @@ -1,95 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "utils.h" - -/* - * Specify which level of Merkle tree (the "layer") we're working on - */ -void set_layer_addr(uint32_t addr[8], uint32_t layer) { - ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; -} - -/* - * Specify which Merkle tree within the level (the "tree address") we're working on - */ -void set_tree_addr(uint32_t addr[8], uint64_t tree) { - ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); -} - -/* - * Specify the reason we'll use this address structure for, that is, what - * hash will we compute with it. This is used so that unrelated types of - * hashes don't accidentally get the same address structure. The type will be - * one of the SPX_ADDR_TYPE constants - */ -void set_type(uint32_t addr[8], uint32_t type) { - ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; -} - -/* - * Copy the layer and tree fields of the address structure. This is used - * when we're doing multiple types of hashes within the same Merkle tree - */ -void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { - memcpy( out, in, SPX_OFFSET_TREE + 8 ); -} - -/* These functions are used for OTS addresses. */ - -/* - * Specify which Merkle leaf we're working on; that is, which OTS keypair - * we're talking about. - */ -void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { - /* We have > 256 OTS at the bottom of the Merkle tree; to specify */ - /* which one, we'd need to express it in two bytes */ - ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR2] = (unsigned char)(keypair >> 8); - ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; -} - -/* - * Copy the layer, tree and keypair fields of the address structure. This is - * used when we're doing multiple things within the same OTS keypair - */ -void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { - memcpy( out, in, SPX_OFFSET_TREE + 8 ); - ((unsigned char *)out)[SPX_OFFSET_KP_ADDR2] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR2]; - ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; -} - -/* - * Specify which Merkle chain within the OTS we're working with - * (the chain address) - */ -void set_chain_addr(uint32_t addr[8], uint32_t chain) { - ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; -} - -/* - * Specify where in the Merkle chain we are -* (the hash address) - */ -void set_hash_addr(uint32_t addr[8], uint32_t hash) { - ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; -} - -/* These functions are used for all hash tree addresses (including FORS). */ - -/* - * Specify the height of the node in the Merkle/FORS tree we are in - * (the tree height) - */ -void set_tree_height(uint32_t addr[8], uint32_t tree_height) { - ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; -} - -/* - * Specify the distance from the left edge of the node in the Merkle/FORS tree - * (the tree index) - */ -void set_tree_index(uint32_t addr[8], uint32_t tree_index) { - u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/address.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/address.h deleted file mode 100644 index 24a84eb40c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/address.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef SPX_ADDRESS_H -#define SPX_ADDRESS_H - -#include - -#include "params.h" - -/* The hash types that are passed to set_type */ -#define SPX_ADDR_TYPE_WOTS 0 -#define SPX_ADDR_TYPE_WOTSPK 1 -#define SPX_ADDR_TYPE_HASHTREE 2 -#define SPX_ADDR_TYPE_FORSTREE 3 -#define SPX_ADDR_TYPE_FORSPK 4 -#define SPX_ADDR_TYPE_WOTSPRF 5 -#define SPX_ADDR_TYPE_FORSPRF 6 - -#define set_layer_addr SPX_NAMESPACE(set_layer_addr) -void set_layer_addr(uint32_t addr[8], uint32_t layer); - -#define set_tree_addr SPX_NAMESPACE(set_tree_addr) -void set_tree_addr(uint32_t addr[8], uint64_t tree); - -#define set_type SPX_NAMESPACE(set_type) -void set_type(uint32_t addr[8], uint32_t type); - -/* Copies the layer and tree part of one address into the other */ -#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) -void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for WOTS and FORS addresses. */ - -#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) -void set_keypair_addr(uint32_t addr[8], uint32_t keypair); - -#define set_chain_addr SPX_NAMESPACE(set_chain_addr) -void set_chain_addr(uint32_t addr[8], uint32_t chain); - -#define set_hash_addr SPX_NAMESPACE(set_hash_addr) -void set_hash_addr(uint32_t addr[8], uint32_t hash); - -#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) -void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for all hash tree addresses (including FORS). */ - -#define set_tree_height SPX_NAMESPACE(set_tree_height) -void set_tree_height(uint32_t addr[8], uint32_t tree_height); - -#define set_tree_index SPX_NAMESPACE(set_tree_index) -void set_tree_index(uint32_t addr[8], uint32_t tree_index); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/api.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/api.h deleted file mode 100644 index 3b1a5a9f0c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/api.h +++ /dev/null @@ -1,77 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE128SROBUST_CLEAN_API_H -#define PQCLEAN_SPHINCSSHAKE128SROBUST_CLEAN_API_H - -#include -#include - -#define PQCLEAN_SPHINCSSHAKE128SROBUST_CLEAN_CRYPTO_ALGNAME "SPHINCS+-shake-128s-robust" - -#define PQCLEAN_SPHINCSSHAKE128SROBUST_CLEAN_CRYPTO_SECRETKEYBYTES 64 -#define PQCLEAN_SPHINCSSHAKE128SROBUST_CLEAN_CRYPTO_PUBLICKEYBYTES 32 -#define PQCLEAN_SPHINCSSHAKE128SROBUST_CLEAN_CRYPTO_BYTES 7856 - -#define PQCLEAN_SPHINCSSHAKE128SROBUST_CLEAN_CRYPTO_SEEDBYTES 48 - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE128SROBUST_CLEAN_crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE128SROBUST_CLEAN_crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE128SROBUST_CLEAN_crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE128SROBUST_CLEAN_crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHAKE128SROBUST_CLEAN_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHAKE128SROBUST_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSSHAKE128SROBUST_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE128SROBUST_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, - const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSSHAKE128SROBUST_CLEAN_crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE128SROBUST_CLEAN_crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk); -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/context.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/context.h deleted file mode 100644 index 9f8a40ab4e..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/context.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef SPX_CONTEXT_H -#define SPX_CONTEXT_H - -#include -#include - -#include "params.h" - -typedef struct { - uint8_t pub_seed[SPX_N]; - uint8_t sk_seed[SPX_N]; - - -} spx_ctx; - -#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) -void initialize_hash_function(spx_ctx *ctx); - -#define free_hash_function SPX_NAMESPACE(free_hash_function) -void free_hash_function(spx_ctx *ctx); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/context_shake.c b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/context_shake.c deleted file mode 100644 index 9614a103d3..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/context_shake.c +++ /dev/null @@ -1,12 +0,0 @@ -#include "context.h" - -/* For SHAKE256, there is no immediate reason to initialize at the start, - so this function is an empty operation. */ -void initialize_hash_function(spx_ctx *ctx) { - (void)ctx; /* Suppress an 'unused parameter' warning. */ -} - -// in case the hash function api is heap-based. -void free_hash_function(spx_ctx *ctx) { - (void)ctx; -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/fors.c b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/fors.c deleted file mode 100644 index 96ca72e986..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/fors.c +++ /dev/null @@ -1,156 +0,0 @@ -#include -#include -#include - -#include "fors.h" - -#include "address.h" -#include "hash.h" -#include "thash.h" -#include "utils.h" -#include "utilsx1.h" - -static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, - uint32_t fors_leaf_addr[8]) { - prf_addr(sk, ctx, fors_leaf_addr); -} - -static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, - const spx_ctx *ctx, - uint32_t fors_leaf_addr[8]) { - thash(leaf, sk, 1, ctx, fors_leaf_addr); -} - -struct fors_gen_leaf_info { - uint32_t leaf_addrx[8]; -}; - -static void fors_gen_leafx1(unsigned char *leaf, - const spx_ctx *ctx, - uint32_t addr_idx, void *info) { - struct fors_gen_leaf_info *fors_info = info; - uint32_t *fors_leaf_addr = fors_info->leaf_addrx; - - /* Only set the parts that the caller doesn't set */ - set_tree_index(fors_leaf_addr, addr_idx); - set_type(fors_leaf_addr, SPX_ADDR_TYPE_FORSPRF); - fors_gen_sk(leaf, ctx, fors_leaf_addr); - - set_type(fors_leaf_addr, SPX_ADDR_TYPE_FORSTREE); - fors_sk_to_leaf(leaf, leaf, - ctx, fors_leaf_addr); -} - -/** - * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - * Assumes indices has space for SPX_FORS_TREES integers. - */ -static void message_to_indices(uint32_t *indices, const unsigned char *m) { - unsigned int i, j; - unsigned int offset = 0; - - for (i = 0; i < SPX_FORS_TREES; i++) { - indices[i] = 0; - for (j = 0; j < SPX_FORS_HEIGHT; j++) { - indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); - offset++; - } - } -} - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -void fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]) { - uint32_t indices[SPX_FORS_TREES]; - unsigned char roots[SPX_FORS_TREES * SPX_N]; - uint32_t fors_tree_addr[8] = {0}; - struct fors_gen_leaf_info fors_info = {0}; - uint32_t *fors_leaf_addr = fors_info.leaf_addrx; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - copy_keypair_addr(fors_tree_addr, fors_addr); - copy_keypair_addr(fors_leaf_addr, fors_addr); - - copy_keypair_addr(fors_pk_addr, fors_addr); - set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < SPX_FORS_TREES; i++) { - idx_offset = i * (1 << SPX_FORS_HEIGHT); - - set_tree_height(fors_tree_addr, 0); - set_tree_index(fors_tree_addr, indices[i] + idx_offset); - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); - - /* Include the secret key part that produces the selected leaf node. */ - fors_gen_sk(sig, ctx, fors_tree_addr); - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); - sig += SPX_N; - - /* Compute the authentication path for this leaf node. */ - treehashx1(roots + i * SPX_N, sig, ctx, - indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx1, - fors_tree_addr, &fors_info); - - sig += SPX_N * SPX_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); -} - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -void fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]) { - uint32_t indices[SPX_FORS_TREES]; - unsigned char roots[SPX_FORS_TREES * SPX_N]; - unsigned char leaf[SPX_N]; - uint32_t fors_tree_addr[8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - copy_keypair_addr(fors_tree_addr, fors_addr); - copy_keypair_addr(fors_pk_addr, fors_addr); - - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); - set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < SPX_FORS_TREES; i++) { - idx_offset = i * (1 << SPX_FORS_HEIGHT); - - set_tree_height(fors_tree_addr, 0); - set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Derive the leaf from the included secret key part. */ - fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); - sig += SPX_N; - - /* Derive the corresponding root node of this tree. */ - compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, - sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); - sig += SPX_N * SPX_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/fors.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/fors.h deleted file mode 100644 index 509140a178..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/fors.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef SPX_FORS_H -#define SPX_FORS_H - -#include - -#include "context.h" -#include "params.h" - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -#define fors_sign SPX_NAMESPACE(fors_sign) -void fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]); - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) -void fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/hash.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/hash.h deleted file mode 100644 index f7c87d4c3c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/hash.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef SPX_HASH_H -#define SPX_HASH_H - -#include -#include - -#include "context.h" -#include "params.h" - -#define prf_addr SPX_NAMESPACE(prf_addr) -void prf_addr(unsigned char *out, const spx_ctx *ctx, - const uint32_t addr[8]); - -#define gen_message_random SPX_NAMESPACE(gen_message_random) -void gen_message_random(unsigned char *R, const unsigned char *sk_prf, - const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx); - -#define hash_message SPX_NAMESPACE(hash_message) -void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx); - - - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/hash_shake.c b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/hash_shake.c deleted file mode 100644 index ff5e7ec918..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/hash_shake.c +++ /dev/null @@ -1,83 +0,0 @@ -#include -#include - -#include "hash.h" - -#include "address.h" -#include "fips202.h" -#include "params.h" -#include "utils.h" - -/* - * Computes PRF(pk_seed, sk_seed, addr) - */ -void prf_addr(unsigned char *out, const spx_ctx *ctx, - const uint32_t addr[8]) { - unsigned char buf[2 * SPX_N + SPX_ADDR_BYTES]; - - memcpy(buf, ctx->pub_seed, SPX_N); - memcpy(buf + SPX_N, addr, SPX_ADDR_BYTES); - memcpy(buf + SPX_N + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); - - shake256(out, SPX_N, buf, 2 * SPX_N + SPX_ADDR_BYTES); -} - -/** - * Computes the message-dependent randomness R, using a secret seed and an - * optional randomization value as well as the message. - */ -void gen_message_random(unsigned char *R, const unsigned char *sk_prf, - const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx) { - (void)ctx; - shake256incctx s_inc; - - shake256_inc_init(&s_inc); - shake256_inc_absorb(&s_inc, sk_prf, SPX_N); - shake256_inc_absorb(&s_inc, optrand, SPX_N); - shake256_inc_absorb(&s_inc, m, mlen); - shake256_inc_finalize(&s_inc); - shake256_inc_squeeze(R, SPX_N, &s_inc); - shake256_inc_ctx_release(&s_inc); -} - -/** - * Computes the message hash using R, the public key, and the message. - * Outputs the message digest and the index of the leaf. The index is split in - * the tree index and the leaf index, for convenient copying to an address. - */ -void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx) { - (void)ctx; -#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) -#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) -#define SPX_LEAF_BITS SPX_TREE_HEIGHT -#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) -#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) - - unsigned char buf[SPX_DGST_BYTES]; - unsigned char *bufp = buf; - shake256incctx s_inc; - - shake256_inc_init(&s_inc); - shake256_inc_absorb(&s_inc, R, SPX_N); - shake256_inc_absorb(&s_inc, pk, SPX_PK_BYTES); - shake256_inc_absorb(&s_inc, m, mlen); - shake256_inc_finalize(&s_inc); - shake256_inc_squeeze(buf, SPX_DGST_BYTES, &s_inc); - shake256_inc_ctx_release(&s_inc); - - memcpy(digest, bufp, SPX_FORS_MSG_BYTES); - bufp += SPX_FORS_MSG_BYTES; - - - *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); - *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); - bufp += SPX_TREE_BYTES; - - *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); - *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/merkle.c b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/merkle.c deleted file mode 100644 index 0c1479fd93..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/merkle.c +++ /dev/null @@ -1,59 +0,0 @@ -#include -#include - -#include "address.h" -#include "merkle.h" -#include "params.h" -#include "utils.h" -#include "utilsx1.h" -#include "wots.h" -#include "wotsx1.h" - -/* - * This generates a Merkle signature (WOTS signature followed by the Merkle - * authentication path). This is in this file because most of the complexity - * is involved with the WOTS signature; the Merkle authentication path logic - * is mostly hidden in treehashx4 - */ -void merkle_sign(uint8_t *sig, unsigned char *root, - const spx_ctx *ctx, - uint32_t wots_addr[8], uint32_t tree_addr[8], - uint32_t idx_leaf) { - unsigned char *auth_path = sig + SPX_WOTS_BYTES; - struct leaf_info_x1 info = { 0 }; - unsigned steps[ SPX_WOTS_LEN ]; - - info.wots_sig = sig; - chain_lengths(steps, root); - info.wots_steps = steps; - - set_type(&tree_addr[0], SPX_ADDR_TYPE_HASHTREE); - set_type(&info.pk_addr[0], SPX_ADDR_TYPE_WOTSPK); - copy_subtree_addr(&info.leaf_addr[0], wots_addr); - copy_subtree_addr(&info.pk_addr[0], wots_addr); - - info.wots_sign_leaf = idx_leaf; - - treehashx1(root, auth_path, ctx, - idx_leaf, 0, - SPX_TREE_HEIGHT, - wots_gen_leafx1, - tree_addr, &info); -} - -/* Compute root node of the top-most subtree. */ -void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { - /* We do not need the auth path in key generation, but it simplifies the - code to have just one treehash routine that computes both root and path - in one function. */ - unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; - uint32_t top_tree_addr[8] = {0}; - uint32_t wots_addr[8] = {0}; - - set_layer_addr(top_tree_addr, SPX_D - 1); - set_layer_addr(wots_addr, SPX_D - 1); - - merkle_sign(auth_path, root, ctx, - wots_addr, top_tree_addr, - (uint32_t)~0 /* ~0 means "don't bother generating an auth path */ ); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/merkle.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/merkle.h deleted file mode 100644 index 769cf2e970..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/merkle.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef MERKLE_H_ -#define MERKLE_H_ - -#include - -#include "context.h" -#include "params.h" - -/* Generate a Merkle signature (WOTS signature followed by the Merkle */ -/* authentication path) */ -#define merkle_sign SPX_NAMESPACE(merkle_sign) -void merkle_sign(uint8_t *sig, unsigned char *root, - const spx_ctx *ctx, - uint32_t wots_addr[8], uint32_t tree_addr[8], - uint32_t idx_leaf); - -/* Compute the root node of the top-most subtree. */ -#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) -void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); - -#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/nistapi.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/nistapi.h deleted file mode 100644 index 3cb71afad4..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/nistapi.h +++ /dev/null @@ -1,87 +0,0 @@ -#ifndef SPX_API_H -#define SPX_API_H - -#include -#include - -#include "params.h" - -#define CRYPTO_ALGNAME "SPHINCS+" - -#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES -#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES -#define CRYPTO_BYTES SPX_BYTES -#define CRYPTO_SEEDBYTES (3*SPX_N) - -/* - * Returns the length of a secret key, in bytes - */ -#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) -size_t crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) -size_t crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) -size_t crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) -size_t crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) -int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) -int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) -int crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) -int crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -#define crypto_sign SPX_NAMESPACE(crypto_sign) -int crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) -int crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/params.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/params.h deleted file mode 100644 index 99778d7efc..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/params.h +++ /dev/null @@ -1,56 +0,0 @@ -#ifndef SPX_PARAMS_H -#define SPX_PARAMS_H - -#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSSHAKE128SROBUST_CLEAN_##s - -/* Hash output length in bytes. */ -#define SPX_N 16 -/* Height of the hypertree. */ -#define SPX_FULL_HEIGHT 63 -/* Number of subtree layer. */ -#define SPX_D 7 -/* FORS tree dimensions. */ -#define SPX_FORS_HEIGHT 12 -#define SPX_FORS_TREES 14 -/* Winternitz parameter, */ -#define SPX_WOTS_W 16 - -/* The hash function is defined by linking a different hash.c file, as opposed - to setting a #define constant. */ - -/* For clarity */ -#define SPX_ADDR_BYTES 32 - -/* WOTS parameters. */ -#define SPX_WOTS_LOGW 4 - -#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) - -/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#define SPX_WOTS_LEN2 3 - -#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) -#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) -#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES - -/* Subtree size. */ -#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) - -//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT -// #error SPX_D should always divide SPX_FULL_HEIGHT -//#endif - -/* FORS parameters. */ -#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) -#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) -#define SPX_FORS_PK_BYTES SPX_N - -/* Resulting SPX sizes. */ -#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ - SPX_FULL_HEIGHT * SPX_N) -#define SPX_PK_BYTES (2 * SPX_N) -#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) - -#include "shake_offsets.h" - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/shake_offsets.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/shake_offsets.h deleted file mode 100644 index 6b28d95d91..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/shake_offsets.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef SHAKE_OFFSETS_H_ -#define SHAKE_OFFSETS_H_ - -/* - * Offsets of various fields in the address structure when we use SHAKE as - * the Sphincs+ hash function - */ - -#define SPX_OFFSET_LAYER 3 /* The byte used to specify the Merkle tree layer */ -#define SPX_OFFSET_TREE 8 /* The start of the 8 byte field used to specify the tree */ -#define SPX_OFFSET_TYPE 19 /* The byte used to specify the hash type (reason) */ -#define SPX_OFFSET_KP_ADDR2 22 /* The high byte used to specify the key pair (which one-time signature) */ -#define SPX_OFFSET_KP_ADDR1 23 /* The low byte used to specify the key pair */ -#define SPX_OFFSET_CHAIN_ADDR 27 /* The byte used to specify the chain address (which Winternitz chain) */ -#define SPX_OFFSET_HASH_ADDR 31 /* The byte used to specify the hash address (where in the Winternitz chain) */ -#define SPX_OFFSET_TREE_HGT 27 /* The byte used to specify the height of this node in the FORS or Merkle tree */ -#define SPX_OFFSET_TREE_INDEX 28 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ - -#define SPX_SHAKE 1 - -#endif /* SHAKE_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/sign.c b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/sign.c deleted file mode 100644 index 9d0c7d1b22..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/sign.c +++ /dev/null @@ -1,286 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "context.h" -#include "fors.h" -#include "hash.h" -#include "merkle.h" -#include "nistapi.h" -#include "params.h" -#include "randombytes.h" -#include "thash.h" -#include "utils.h" -#include "wots.h" - -/* - * Returns the length of a secret key, in bytes - */ -size_t crypto_sign_secretkeybytes(void) { - return CRYPTO_SECRETKEYBYTES; -} - -/* - * Returns the length of a public key, in bytes - */ -size_t crypto_sign_publickeybytes(void) { - return CRYPTO_PUBLICKEYBYTES; -} - -/* - * Returns the length of a signature, in bytes - */ -size_t crypto_sign_bytes(void) { - return CRYPTO_BYTES; -} - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t crypto_sign_seedbytes(void) { - return CRYPTO_SEEDBYTES; -} - -/* - * Generates an SPX key pair given a seed of length - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed) { - spx_ctx ctx; - - /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ - memcpy(sk, seed, CRYPTO_SEEDBYTES); - - memcpy(pk, sk + 2 * SPX_N, SPX_N); - - memcpy(ctx.pub_seed, pk, SPX_N); - memcpy(ctx.sk_seed, sk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - /* Compute root node of the top-most subtree. */ - merkle_gen_root(sk + 3 * SPX_N, &ctx); - - // cleanup - free_hash_function(&ctx); - - memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); - - return 0; -} - -/* - * Generates an SPX key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { - uint8_t seed[CRYPTO_SEEDBYTES]; - randombytes(seed, CRYPTO_SEEDBYTES); - crypto_sign_seed_keypair(pk, sk, seed); - - return 0; -} - -/** - * Returns an array containing a detached signature. - */ -int crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - spx_ctx ctx; - - const uint8_t *sk_prf = sk + SPX_N; - const uint8_t *pk = sk + 2 * SPX_N; - - uint8_t optrand[SPX_N]; - uint8_t mhash[SPX_FORS_MSG_BYTES]; - uint8_t root[SPX_N]; - uint32_t i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - - memcpy(ctx.sk_seed, sk, SPX_N); - memcpy(ctx.pub_seed, pk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - set_type(wots_addr, SPX_ADDR_TYPE_WOTS); - set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); - - /* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ - randombytes(optrand, SPX_N); - /* Compute the digest randomization value. */ - gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); - - /* Derive the message digest and leaf index from R, PK and M. */ - hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); - sig += SPX_N; - - set_tree_addr(wots_addr, tree); - set_keypair_addr(wots_addr, idx_leaf); - - /* Sign the message hash using FORS. */ - fors_sign(sig, root, mhash, &ctx, wots_addr); - sig += SPX_FORS_BYTES; - - for (i = 0; i < SPX_D; i++) { - set_layer_addr(tree_addr, i); - set_tree_addr(tree_addr, tree); - - copy_subtree_addr(wots_addr, tree_addr); - set_keypair_addr(wots_addr, idx_leaf); - - merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); - sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); - tree = tree >> SPX_TREE_HEIGHT; - } - - free_hash_function(&ctx); - - *siglen = SPX_BYTES; - - return 0; -} - -/** - * Verifies a detached signature and message under a given public key. - */ -int crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk) { - spx_ctx ctx; - const uint8_t *pub_root = pk + SPX_N; - uint8_t mhash[SPX_FORS_MSG_BYTES]; - uint8_t wots_pk[SPX_WOTS_BYTES]; - uint8_t root[SPX_N]; - uint8_t leaf[SPX_N]; - unsigned int i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - if (siglen != SPX_BYTES) { - return -1; - } - - memcpy(ctx.pub_seed, pk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - set_type(wots_addr, SPX_ADDR_TYPE_WOTS); - set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); - set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); - - /* Derive the message digest and leaf index from R || PK || M. */ - /* The additional SPX_N is a result of the hash domain separator. */ - hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); - sig += SPX_N; - - /* Layer correctly defaults to 0, so no need to set_layer_addr */ - set_tree_addr(wots_addr, tree); - set_keypair_addr(wots_addr, idx_leaf); - - fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); - sig += SPX_FORS_BYTES; - - /* For each subtree.. */ - for (i = 0; i < SPX_D; i++) { - set_layer_addr(tree_addr, i); - set_tree_addr(tree_addr, tree); - - copy_subtree_addr(wots_addr, tree_addr); - set_keypair_addr(wots_addr, idx_leaf); - - copy_keypair_addr(wots_pk_addr, wots_addr); - - /* The WOTS public key is only correct if the signature was correct. */ - /* Initially, root is the FORS pk, but on subsequent iterations it is - the root of the subtree below the currently processed subtree. */ - wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); - sig += SPX_WOTS_BYTES; - - /* Compute the leaf node using the WOTS public key. */ - thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); - - /* Compute the root node of this subtree. */ - compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, - &ctx, tree_addr); - sig += SPX_TREE_HEIGHT * SPX_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); - tree = tree >> SPX_TREE_HEIGHT; - } - - // cleanup - free_hash_function(&ctx); - - /* Check if the root node equals the root node in the public key. */ - if (memcmp(root, pub_root, SPX_N) != 0) { - return -1; - } - - return 0; -} - - -/** - * Returns an array containing the signature followed by the message. - */ -int crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk) { - size_t siglen; - - crypto_sign_signature(sm, &siglen, m, mlen, sk); - - memmove(sm + SPX_BYTES, m, mlen); - *smlen = siglen + mlen; - - return 0; -} - -/** - * Verifies a given signature-message pair under a given public key. - */ -int crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk) { - /* The API caller does not necessarily know what size a signature should be - but SPHINCS+ signatures are always exactly SPX_BYTES. */ - if (smlen < SPX_BYTES) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - *mlen = smlen - SPX_BYTES; - - if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - /* If verification was successful, move the message to the right place. */ - memmove(m, sm + SPX_BYTES, *mlen); - - return 0; -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/thash.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/thash.h deleted file mode 100644 index 8687ccfb4d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/thash.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef SPX_THASH_H -#define SPX_THASH_H - -#include "context.h" -#include "params.h" - -#include - -#define thash SPX_NAMESPACE(thash) -void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/thash_shake_robust.c b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/thash_shake_robust.c deleted file mode 100644 index 696d53c5cc..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/thash_shake_robust.c +++ /dev/null @@ -1,31 +0,0 @@ -#include -#include - -#include "thash.h" - -#include "address.h" -#include "params.h" -#include "utils.h" - -#include "fips202.h" - -/** - * Takes an array of inblocks concatenated arrays of SPX_N bytes. - */ -void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]) { - PQCLEAN_VLA(uint8_t, buf, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); - PQCLEAN_VLA(uint8_t, bitmask, inblocks * SPX_N); - unsigned int i; - - memcpy(buf, ctx->pub_seed, SPX_N); - memcpy(buf + SPX_N, addr, SPX_ADDR_BYTES); - - shake256(bitmask, inblocks * SPX_N, buf, SPX_N + SPX_ADDR_BYTES); - - for (i = 0; i < inblocks * SPX_N; i++) { - buf[SPX_N + SPX_ADDR_BYTES + i] = in[i] ^ bitmask[i]; - } - - shake256(out, SPX_N, buf, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/utils.c b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/utils.c deleted file mode 100644 index 177b541fb9..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/utils.c +++ /dev/null @@ -1,148 +0,0 @@ -#include - -#include "utils.h" - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "thash.h" - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void ull_to_bytes(unsigned char *out, unsigned int outlen, - unsigned long long in) { - int i; - - /* Iterate over out in decreasing order, for big-endianness. */ - for (i = (signed int)outlen - 1; i >= 0; i--) { - out[i] = in & 0xff; - in = in >> 8; - } -} - -void u32_to_bytes(unsigned char *out, uint32_t in) { - out[0] = (unsigned char)(in >> 24); - out[1] = (unsigned char)(in >> 16); - out[2] = (unsigned char)(in >> 8); - out[3] = (unsigned char)in; -} - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { - unsigned long long retval = 0; - unsigned int i; - - for (i = 0; i < inlen; i++) { - retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); - } - return retval; -} - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void compute_root(unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const spx_ctx *ctx, uint32_t addr[8]) { - uint32_t i; - unsigned char buffer[2 * SPX_N]; - - /* If leaf_idx is odd (last bit = 1), current path element is a right child - and auth_path has to go left. Otherwise it is the other way around. */ - if (leaf_idx & 1) { - memcpy(buffer + SPX_N, leaf, SPX_N); - memcpy(buffer, auth_path, SPX_N); - } else { - memcpy(buffer, leaf, SPX_N); - memcpy(buffer + SPX_N, auth_path, SPX_N); - } - auth_path += SPX_N; - - for (i = 0; i < tree_height - 1; i++) { - leaf_idx >>= 1; - idx_offset >>= 1; - /* Set the address of the node we're creating. */ - set_tree_height(addr, i + 1); - set_tree_index(addr, leaf_idx + idx_offset); - - /* Pick the right or left neighbor, depending on parity of the node. */ - if (leaf_idx & 1) { - thash(buffer + SPX_N, buffer, 2, ctx, addr); - memcpy(buffer, auth_path, SPX_N); - } else { - thash(buffer, buffer, 2, ctx, addr); - memcpy(buffer + SPX_N, auth_path, SPX_N); - } - auth_path += SPX_N; - } - - /* The last iteration is exceptional; we do not copy an auth_path node. */ - leaf_idx >>= 1; - idx_offset >>= 1; - set_tree_height(addr, tree_height); - set_tree_index(addr, leaf_idx + idx_offset); - thash(root, buffer, 2, ctx, addr); -} - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const spx_ctx * /* ctx */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), - uint32_t tree_addr[8]) { - PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); - PQCLEAN_VLA(unsigned int, heights, tree_height + 1); - unsigned int offset = 0; - uint32_t idx; - uint32_t tree_idx; - - for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { - /* Add the next leaf node to the stack. */ - gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); - offset++; - heights[offset - 1] = 0; - - /* If this is a node we need for the auth path.. */ - if ((leaf_idx ^ 0x1) == idx) { - memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); - } - - /* While the top-most nodes are of equal height.. */ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { - /* Compute index of the new node, in the next layer. */ - tree_idx = (idx >> (heights[offset - 1] + 1)); - - /* Set the address of the node we're creating. */ - set_tree_height(tree_addr, heights[offset - 1] + 1); - set_tree_index(tree_addr, - tree_idx + (idx_offset >> (heights[offset - 1] + 1))); - /* Hash the top-most nodes from the stack together. */ - thash(stack + (offset - 2)*SPX_N, - stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); - offset--; - /* Note that the top-most node is now one layer higher. */ - heights[offset - 1]++; - - /* If this is a node we need for the auth path.. */ - if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_path + heights[offset - 1]*SPX_N, - stack + (offset - 1)*SPX_N, SPX_N); - } - } - } - memcpy(root, stack, SPX_N); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/utils.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/utils.h deleted file mode 100644 index 64f5d5a53a..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/utils.h +++ /dev/null @@ -1,58 +0,0 @@ -#ifndef SPX_UTILS_H -#define SPX_UTILS_H - -#include - -#include "compat.h" -#include "context.h" -#include "params.h" - - -/* To support MSVC use alloca() instead of VLAs. See #20. */ - - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) -void ull_to_bytes(unsigned char *out, unsigned int outlen, - unsigned long long in); -#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) -void u32_to_bytes(unsigned char *out, uint32_t in); - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) -unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -#define compute_root SPX_NAMESPACE(compute_root) -void compute_root(unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const spx_ctx *ctx, uint32_t addr[8]); - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -#define treehash SPX_NAMESPACE(treehash) -void treehash(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const spx_ctx *ctx /* ctx */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), - uint32_t tree_addr[8]); - - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/utilsx1.c b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/utilsx1.c deleted file mode 100644 index fccb69b35d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/utilsx1.c +++ /dev/null @@ -1,100 +0,0 @@ -#include - -#include "utilsx1.h" - -#include "address.h" -#include "params.h" -#include "thash.h" -#include "utils.h" - -/* - * Generate the entire Merkle tree, computing the authentication path for - * leaf_idx, and the resulting root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) - * - * This expects tree_addr to be initialized to the addr structures for the - * Merkle tree nodes - * - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - * - * This works by using the standard Merkle tree building algorithm, - */ -void treehashx1(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, - uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* Where to write the leaves */, - const spx_ctx * /* ctx */, - uint32_t idx, void *info), - uint32_t tree_addr[8], - void *info) { - /* This is where we keep the intermediate nodes */ - PQCLEAN_VLA(uint8_t, stack, tree_height * SPX_N); - - uint32_t idx; - uint32_t max_idx = (uint32_t)((1 << tree_height) - 1); - for (idx = 0;; idx++) { - unsigned char current[2 * SPX_N]; /* Current logical node is at */ - /* index[SPX_N]. We do this to minimize the number of copies */ - /* needed during a thash */ - gen_leaf( ¤t[SPX_N], ctx, idx + idx_offset, - info ); - - /* Now combine the freshly generated right node with previously */ - /* generated left ones */ - uint32_t internal_idx_offset = idx_offset; - uint32_t internal_idx = idx; - uint32_t internal_leaf = leaf_idx; - uint32_t h; /* The height we are in the Merkle tree */ - for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { - - /* Check if we hit the top of the tree */ - if (h == tree_height) { - /* We hit the root; return it */ - memcpy( root, ¤t[SPX_N], SPX_N ); - return; - } - - /* - * Check if the node we have is a part of the - * authentication path; if it is, write it out - */ - if ((internal_idx ^ internal_leaf) == 0x01) { - memcpy( &auth_path[ h * SPX_N ], - ¤t[SPX_N], - SPX_N ); - } - - /* - * Check if we're at a left child; if so, stop going up the stack - * Exception: if we've reached the end of the tree, keep on going - * (so we combine the last 4 nodes into the one root node in two - * more iterations) - */ - if ((internal_idx & 1) == 0 && idx < max_idx) { - break; - } - - /* Ok, we're at a right node */ - /* Now combine the left and right logical nodes together */ - - /* Set the address of the node we're creating. */ - internal_idx_offset >>= 1; - set_tree_height(tree_addr, h + 1); - set_tree_index(tree_addr, internal_idx / 2 + internal_idx_offset ); - - unsigned char *left = &stack[h * SPX_N]; - memcpy( ¤t[0], left, SPX_N ); - thash( ¤t[1 * SPX_N], - ¤t[0 * SPX_N], - 2, ctx, tree_addr); - } - - /* We've hit a left child; save the current for when we get the */ - /* corresponding right right */ - memcpy( &stack[h * SPX_N], ¤t[SPX_N], SPX_N); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/utilsx1.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/utilsx1.h deleted file mode 100644 index e911d17d53..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/utilsx1.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef SPX_UTILSX4_H -#define SPX_UTILSX4_H - -#include - -#include "context.h" -#include "params.h" - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -#define treehashx1 SPX_NAMESPACE(treehashx1) -void treehashx1(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* Where to write the leaf */, - const spx_ctx * /* ctx */, - uint32_t addr_idx, void *info), - uint32_t tree_addrx4[8], void *info); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/wots.c b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/wots.c deleted file mode 100644 index 249717aaa8..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/wots.c +++ /dev/null @@ -1,108 +0,0 @@ -#include -#include - -#include "wots.h" -#include "wotsx1.h" - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "thash.h" -#include "utils.h" -#include "utilsx1.h" - -// TODO clarify address expectations, and make them more uniform. -// TODO i.e. do we expect types to be set already? -// TODO and do we expect modifications or copies? - -/** - * Computes the chaining function. - * out and in have to be n-byte arrays. - * - * Interprets in as start-th value of the chain. - * addr has to contain the address of the chain. - */ -static void gen_chain(unsigned char *out, const unsigned char *in, - unsigned int start, unsigned int steps, - const spx_ctx *ctx, uint32_t addr[8]) { - uint32_t i; - - /* Initialize out with the value at position 'start'. */ - memcpy(out, in, SPX_N); - - /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < SPX_WOTS_W; i++) { - set_hash_addr(addr, i); - thash(out, out, 1, ctx, addr); - } -} - -/** - * base_w algorithm as described in draft. - * Interprets an array of bytes as integers in base w. - * This only works when log_w is a divisor of 8. - */ -static void base_w(unsigned int *output, const int out_len, - const unsigned char *input) { - int in = 0; - int out = 0; - unsigned char total = 0; - int bits = 0; - int consumed; - - for (consumed = 0; consumed < out_len; consumed++) { - if (bits == 0) { - total = input[in]; - in++; - bits += 8; - } - bits -= SPX_WOTS_LOGW; - output[out] = (total >> bits) & (SPX_WOTS_W - 1); - out++; - } -} - -/* Computes the WOTS+ checksum over a message (in base_w). */ -static void wots_checksum(unsigned int *csum_base_w, - const unsigned int *msg_base_w) { - unsigned int csum = 0; - unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; - unsigned int i; - - /* Compute checksum. */ - for (i = 0; i < SPX_WOTS_LEN1; i++) { - csum += SPX_WOTS_W - 1 - msg_base_w[i]; - } - - /* Convert checksum to base_w. */ - /* Make sure expected empty zero bits are the least significant bits. */ - csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); - ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); - base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); -} - -/* Takes a message and derives the matching chain lengths. */ -void chain_lengths(unsigned int *lengths, const unsigned char *msg) { - base_w(lengths, SPX_WOTS_LEN1, msg); - wots_checksum(lengths + SPX_WOTS_LEN1, lengths); -} - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const spx_ctx *ctx, uint32_t addr[8]) { - unsigned int lengths[SPX_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < SPX_WOTS_LEN; i++) { - set_chain_addr(addr, i); - gen_chain(pk + i * SPX_N, sig + i * SPX_N, - lengths[i], SPX_WOTS_W - 1 - lengths[i], ctx, addr); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/wots.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/wots.h deleted file mode 100644 index 4e7692eeef..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/wots.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef SPX_WOTS_H -#define SPX_WOTS_H - -#include - -#include "context.h" -#include "params.h" - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) -void wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const spx_ctx *ctx, uint32_t addr[8]); - -/* - * Compute the chain lengths needed for a given message hash - */ -#define chain_lengths SPX_NAMESPACE(chain_lengths) -void chain_lengths(unsigned int *lengths, const unsigned char *msg); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/wotsx1.c b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/wotsx1.c deleted file mode 100644 index 3adec78dfb..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/wotsx1.c +++ /dev/null @@ -1,76 +0,0 @@ -#include -#include - -#include "wots.h" -#include "wotsx1.h" - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "thash.h" -#include "utils.h" - -/* - * This generates a WOTS public key - * It also generates the WOTS signature if leaf_info indicates - * that we're signing with this WOTS key - */ -void wots_gen_leafx1(unsigned char *dest, - const spx_ctx *ctx, - uint32_t leaf_idx, void *v_info) { - struct leaf_info_x1 *info = v_info; - uint32_t *leaf_addr = info->leaf_addr; - uint32_t *pk_addr = info->pk_addr; - unsigned int i, k; - unsigned char pk_buffer[ SPX_WOTS_BYTES ]; - unsigned char *buffer; - uint32_t wots_k_mask; - - if (leaf_idx == info->wots_sign_leaf) { - /* We're traversing the leaf that's signing; generate the WOTS */ - /* signature */ - wots_k_mask = 0; - } else { - /* Nope, we're just generating pk's; turn off the signature logic */ - wots_k_mask = (uint32_t)~0; - } - - set_keypair_addr( leaf_addr, leaf_idx ); - set_keypair_addr( pk_addr, leaf_idx ); - - for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { - uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k to */ - /* the step if we're generating a signature, ~0 if we're not */ - - /* Start with the secret seed */ - set_chain_addr(leaf_addr, i); - set_hash_addr(leaf_addr, 0); - set_type(leaf_addr, SPX_ADDR_TYPE_WOTSPRF); - - prf_addr(buffer, ctx, leaf_addr); - - set_type(leaf_addr, SPX_ADDR_TYPE_WOTS); - - /* Iterate down the WOTS chain */ - for (k = 0;; k++) { - /* Check if this is the value that needs to be saved as a */ - /* part of the WOTS signature */ - if (k == wots_k) { - memcpy( info->wots_sig + i * SPX_N, buffer, SPX_N ); - } - - /* Check if we hit the top of the chain */ - if (k == SPX_WOTS_W - 1) { - break; - } - - /* Iterate one step on the chain */ - set_hash_addr(leaf_addr, k); - - thash(buffer, buffer, 1, ctx, leaf_addr); - } - } - - /* Do the final thash to generate the public keys */ - thash(dest, pk_buffer, SPX_WOTS_LEN, ctx, pk_addr); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/wotsx1.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/wotsx1.h deleted file mode 100644 index e617929f96..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128s-robust_clean/wotsx1.h +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef WOTSX1_H_ -#define WOTSX1_H_ - -#include - -#include "context.h" -#include "params.h" - -/* - * This is here to provide an interface to the internal wots_gen_leafx1 - * routine. While this routine is not referenced in the package outside of - * wots.c, it is called from the stand-alone benchmark code to characterize - * the performance - */ -struct leaf_info_x1 { - unsigned char *wots_sig; - uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ - uint32_t *wots_steps; - uint32_t leaf_addr[8]; - uint32_t pk_addr[8]; -}; - -/* Macro to set the leaf_info to something 'benign', that is, it would */ -/* run with the same time as it does during the real signing process */ -/* Used only by the benchmark code */ -#define INITIALIZE_LEAF_INFO_X1(info, addr, step_buffer) { \ - (info).wots_sig = 0; \ - (info).wots_sign_leaf = ~0; \ - (info).wots_steps = step_buffer; \ - memcpy( &(info).leaf_addr[0], (addr), 32 ); \ - memcpy( &(info).pk_addr[0], (addr), 32 ); \ - } - -#define wots_gen_leafx1 SPX_NAMESPACE(wots_gen_leafx1) -void wots_gen_leafx1(unsigned char *dest, - const spx_ctx *ctx, - uint32_t leaf_idx, void *v_info); - -#endif /* WOTSX1_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/LICENSE b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/LICENSE deleted file mode 100644 index 670154e353..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/LICENSE +++ /dev/null @@ -1,116 +0,0 @@ -CC0 1.0 Universal - -Statement of Purpose - -The laws of most jurisdictions throughout the world automatically confer -exclusive Copyright and Related Rights (defined below) upon the creator and -subsequent owner(s) (each and all, an "owner") of an original work of -authorship and/or a database (each, a "Work"). - -Certain owners wish to permanently relinquish those rights to a Work for the -purpose of contributing to a commons of creative, cultural and scientific -works ("Commons") that the public can reliably and without fear of later -claims of infringement build upon, modify, incorporate in other works, reuse -and redistribute as freely as possible in any form whatsoever and for any -purposes, including without limitation commercial purposes. These owners may -contribute to the Commons to promote the ideal of a free culture and the -further production of creative, cultural and scientific works, or to gain -reputation or greater distribution for their Work in part through the use and -efforts of others. - -For these and/or other purposes and motivations, and without any expectation -of additional consideration or compensation, the person associating CC0 with a -Work (the "Affirmer"), to the extent that he or she is an owner of Copyright -and Related Rights in the Work, voluntarily elects to apply CC0 to the Work -and publicly distribute the Work under its terms, with knowledge of his or her -Copyright and Related Rights in the Work and the meaning and intended legal -effect of CC0 on those rights. - -1. Copyright and Related Rights. A Work made available under CC0 may be -protected by copyright and related or neighboring rights ("Copyright and -Related Rights"). Copyright and Related Rights include, but are not limited -to, the following: - - i. the right to reproduce, adapt, distribute, perform, display, communicate, - and translate a Work; - - ii. moral rights retained by the original author(s) and/or performer(s); - - iii. publicity and privacy rights pertaining to a person's image or likeness - depicted in a Work; - - iv. rights protecting against unfair competition in regards to a Work, - subject to the limitations in paragraph 4(a), below; - - v. rights protecting the extraction, dissemination, use and reuse of data in - a Work; - - vi. database rights (such as those arising under Directive 96/9/EC of the - European Parliament and of the Council of 11 March 1996 on the legal - protection of databases, and under any national implementation thereof, - including any amended or successor version of such directive); and - - vii. other similar, equivalent or corresponding rights throughout the world - based on applicable law or treaty, and any national implementations thereof. - -2. Waiver. To the greatest extent permitted by, but not in contravention of, -applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and -unconditionally waives, abandons, and surrenders all of Affirmer's Copyright -and Related Rights and associated claims and causes of action, whether now -known or unknown (including existing as well as future claims and causes of -action), in the Work (i) in all territories worldwide, (ii) for the maximum -duration provided by applicable law or treaty (including future time -extensions), (iii) in any current or future medium and for any number of -copies, and (iv) for any purpose whatsoever, including without limitation -commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes -the Waiver for the benefit of each member of the public at large and to the -detriment of Affirmer's heirs and successors, fully intending that such Waiver -shall not be subject to revocation, rescission, cancellation, termination, or -any other legal or equitable action to disrupt the quiet enjoyment of the Work -by the public as contemplated by Affirmer's express Statement of Purpose. - -3. Public License Fallback. Should any part of the Waiver for any reason be -judged legally invalid or ineffective under applicable law, then the Waiver -shall be preserved to the maximum extent permitted taking into account -Affirmer's express Statement of Purpose. In addition, to the extent the Waiver -is so judged Affirmer hereby grants to each affected person a royalty-free, -non transferable, non sublicensable, non exclusive, irrevocable and -unconditional license to exercise Affirmer's Copyright and Related Rights in -the Work (i) in all territories worldwide, (ii) for the maximum duration -provided by applicable law or treaty (including future time extensions), (iii) -in any current or future medium and for any number of copies, and (iv) for any -purpose whatsoever, including without limitation commercial, advertising or -promotional purposes (the "License"). The License shall be deemed effective as -of the date CC0 was applied by Affirmer to the Work. Should any part of the -License for any reason be judged legally invalid or ineffective under -applicable law, such partial invalidity or ineffectiveness shall not -invalidate the remainder of the License, and in such case Affirmer hereby -affirms that he or she will not (i) exercise any of his or her remaining -Copyright and Related Rights in the Work or (ii) assert any associated claims -and causes of action with respect to the Work, in either case contrary to -Affirmer's express Statement of Purpose. - -4. Limitations and Disclaimers. - - a. No trademark or patent rights held by Affirmer are waived, abandoned, - surrendered, licensed or otherwise affected by this document. - - b. Affirmer offers the Work as-is and makes no representations or warranties - of any kind concerning the Work, express, implied, statutory or otherwise, - including without limitation warranties of title, merchantability, fitness - for a particular purpose, non infringement, or the absence of latent or - other defects, accuracy, or the present or absence of errors, whether or not - discoverable, all to the greatest extent permissible under applicable law. - - c. Affirmer disclaims responsibility for clearing rights of other persons - that may apply to the Work or any use thereof, including without limitation - any person's Copyright and Related Rights in the Work. Further, Affirmer - disclaims responsibility for obtaining any necessary consents, permissions - or other rights required for any use of the Work. - - d. Affirmer understands and acknowledges that Creative Commons is not a - party to this document and has no duty or obligation with respect to this - CC0 or use of the Work. - -For more information, please see - diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/address.c b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/address.c deleted file mode 100644 index b956e9cb29..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/address.c +++ /dev/null @@ -1,91 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "utils.h" - -/* - * Specify which level of Merkle tree (the "layer") we're working on - */ -void set_layer_addr(uint32_t addr[8], uint32_t layer) { - ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; -} - -/* - * Specify which Merkle tree within the level (the "tree address") we're working on - */ -void set_tree_addr(uint32_t addr[8], uint64_t tree) { - ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); -} - -/* - * Specify the reason we'll use this address structure for, that is, what - * hash will we compute with it. This is used so that unrelated types of - * hashes don't accidentally get the same address structure. The type will be - * one of the SPX_ADDR_TYPE constants - */ -void set_type(uint32_t addr[8], uint32_t type) { - ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; -} - -/* - * Copy the layer and tree fields of the address structure. This is used - * when we're doing multiple types of hashes within the same Merkle tree - */ -void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { - memcpy( out, in, SPX_OFFSET_TREE + 8 ); -} - -/* These functions are used for OTS addresses. */ - -/* - * Specify which Merkle leaf we're working on; that is, which OTS keypair - * we're talking about. - */ -void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { - ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; -} - -/* - * Copy the layer, tree and keypair fields of the address structure. This is - * used when we're doing multiple things within the same OTS keypair - */ -void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { - memcpy( out, in, SPX_OFFSET_TREE + 8 ); - ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; -} - -/* - * Specify which Merkle chain within the OTS we're working with - * (the chain address) - */ -void set_chain_addr(uint32_t addr[8], uint32_t chain) { - ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; -} - -/* - * Specify where in the Merkle chain we are -* (the hash address) - */ -void set_hash_addr(uint32_t addr[8], uint32_t hash) { - ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; -} - -/* These functions are used for all hash tree addresses (including FORS). */ - -/* - * Specify the height of the node in the Merkle/FORS tree we are in - * (the tree height) - */ -void set_tree_height(uint32_t addr[8], uint32_t tree_height) { - ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; -} - -/* - * Specify the distance from the left edge of the node in the Merkle/FORS tree - * (the tree index) - */ -void set_tree_index(uint32_t addr[8], uint32_t tree_index) { - u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/address.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/address.h deleted file mode 100644 index 24a84eb40c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/address.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef SPX_ADDRESS_H -#define SPX_ADDRESS_H - -#include - -#include "params.h" - -/* The hash types that are passed to set_type */ -#define SPX_ADDR_TYPE_WOTS 0 -#define SPX_ADDR_TYPE_WOTSPK 1 -#define SPX_ADDR_TYPE_HASHTREE 2 -#define SPX_ADDR_TYPE_FORSTREE 3 -#define SPX_ADDR_TYPE_FORSPK 4 -#define SPX_ADDR_TYPE_WOTSPRF 5 -#define SPX_ADDR_TYPE_FORSPRF 6 - -#define set_layer_addr SPX_NAMESPACE(set_layer_addr) -void set_layer_addr(uint32_t addr[8], uint32_t layer); - -#define set_tree_addr SPX_NAMESPACE(set_tree_addr) -void set_tree_addr(uint32_t addr[8], uint64_t tree); - -#define set_type SPX_NAMESPACE(set_type) -void set_type(uint32_t addr[8], uint32_t type); - -/* Copies the layer and tree part of one address into the other */ -#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) -void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for WOTS and FORS addresses. */ - -#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) -void set_keypair_addr(uint32_t addr[8], uint32_t keypair); - -#define set_chain_addr SPX_NAMESPACE(set_chain_addr) -void set_chain_addr(uint32_t addr[8], uint32_t chain); - -#define set_hash_addr SPX_NAMESPACE(set_hash_addr) -void set_hash_addr(uint32_t addr[8], uint32_t hash); - -#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) -void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for all hash tree addresses (including FORS). */ - -#define set_tree_height SPX_NAMESPACE(set_tree_height) -void set_tree_height(uint32_t addr[8], uint32_t tree_height); - -#define set_tree_index SPX_NAMESPACE(set_tree_index) -void set_tree_index(uint32_t addr[8], uint32_t tree_index); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/api.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/api.h deleted file mode 100644 index b119511c75..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/api.h +++ /dev/null @@ -1,77 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE192FROBUST_AARCH64_API_H -#define PQCLEAN_SPHINCSSHAKE192FROBUST_AARCH64_API_H - -#include -#include - -#define PQCLEAN_SPHINCSSHAKE192FROBUST_AARCH64_CRYPTO_ALGNAME "SPHINCS+-shake-192f-robust" - -#define PQCLEAN_SPHINCSSHAKE192FROBUST_AARCH64_CRYPTO_SECRETKEYBYTES 96 -#define PQCLEAN_SPHINCSSHAKE192FROBUST_AARCH64_CRYPTO_PUBLICKEYBYTES 48 -#define PQCLEAN_SPHINCSSHAKE192FROBUST_AARCH64_CRYPTO_BYTES 35664 - -#define PQCLEAN_SPHINCSSHAKE192FROBUST_AARCH64_CRYPTO_SEEDBYTES 72 - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE192FROBUST_AARCH64_crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE192FROBUST_AARCH64_crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE192FROBUST_AARCH64_crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE192FROBUST_AARCH64_crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHAKE192FROBUST_AARCH64_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHAKE192FROBUST_AARCH64_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSSHAKE192FROBUST_AARCH64_crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE192FROBUST_AARCH64_crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, - const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSSHAKE192FROBUST_AARCH64_crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE192FROBUST_AARCH64_crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk); -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/context.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/context.h deleted file mode 100644 index 6e0a33f3b7..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/context.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef SPX_CONTEXT_H -#define SPX_CONTEXT_H - -#include - -#include "params.h" - -typedef struct { - uint8_t pub_seed[SPX_N]; - uint8_t sk_seed[SPX_N]; -} spx_ctx; - -#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) -void initialize_hash_function(spx_ctx *ctx); - -#define free_hash_function SPX_NAMESPACE(free_hash_function) -void free_hash_function(spx_ctx *ctx); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/context_shake.c b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/context_shake.c deleted file mode 100644 index 9614a103d3..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/context_shake.c +++ /dev/null @@ -1,12 +0,0 @@ -#include "context.h" - -/* For SHAKE256, there is no immediate reason to initialize at the start, - so this function is an empty operation. */ -void initialize_hash_function(spx_ctx *ctx) { - (void)ctx; /* Suppress an 'unused parameter' warning. */ -} - -// in case the hash function api is heap-based. -void free_hash_function(spx_ctx *ctx) { - (void)ctx; -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/f1600x2.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/f1600x2.h deleted file mode 100644 index 70d1af9f14..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/f1600x2.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef SPX_F1600X2_H -#define SPX_F1600X2_H - -#include - -extern uint64_t f1600_RC[24]; -extern void _f1600x2(uint64_t *a, uint64_t *rc); - -#define f1600x2(s) do {_f1600x2((s), f1600_RC);} while(0) - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/f1600x2.s b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/f1600x2.s deleted file mode 100644 index 640ed791ed..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/f1600x2.s +++ /dev/null @@ -1,143 +0,0 @@ -# From https://github.com/bwesterb/armed-keccak - -.macro round - # Execute theta, but without xoring into the state yet. - # Compute parities p[i] = a[i] ^ a[5+i] ^ ... ^ a[20+i]. - eor3.16b v25, v0, v5, v10 - eor3.16b v26, v1, v6, v11 - eor3.16b v27, v2, v7, v12 - eor3.16b v28, v3, v8, v13 - eor3.16b v29, v4, v9, v14 - - eor3.16b v25, v25, v15, v20 - eor3.16b v26, v26, v16, v21 - eor3.16b v27, v27, v17, v22 - eor3.16b v28, v28, v18, v23 - eor3.16b v29, v29, v19, v24 - - # d[0] = rotl(p[1], 1) ^ p[4] - rax1.2d v30, v29, v26 - # d[3] = rotl(p[4], 1) ^ p[2] - rax1.2d v29, v27, v29 - # d[1] = rotl(p[2], 1) ^ p[0] - rax1.2d v27, v25, v27 - # d[4] = rotl(p[0], 1) ^ p[3] - rax1.2d v25, v28, v25 - # d[2] = rotl(p[3], 1) ^ p[1] - rax1.2d v28, v26, v28 - - # Xor parities from step theta into the state at the same time - # as executing rho and pi. - eor.16b v0, v0, v30 - mov.16b v31, v1 - xar.2d v1, v6, v27, 20 - xar.2d v6, v9, v25, 44 - xar.2d v9, v22, v28, 3 - xar.2d v22, v14, v25, 25 - xar.2d v14, v20, v30, 46 - xar.2d v20, v2, v28, 2 - xar.2d v2, v12, v28, 21 - xar.2d v12, v13, v29, 39 - xar.2d v13, v19, v25, 56 - xar.2d v19, v23, v29, 8 - xar.2d v23, v15, v30, 23 - xar.2d v15, v4, v25, 37 - xar.2d v4, v24, v25, 50 - xar.2d v24, v21, v27, 62 - xar.2d v21, v8, v29, 9 - xar.2d v8, v16, v27, 19 - xar.2d v16, v5, v30, 28 - xar.2d v5, v3, v29, 36 - xar.2d v3, v18, v29, 43 - xar.2d v18, v17, v28, 49 - xar.2d v17, v11, v27, 54 - xar.2d v11, v7, v28, 58 - xar.2d v7, v10, v30, 61 - xar.2d v10, v31, v27, 63 - - # Chi - bcax.16b v25, v0, v2, v1 - bcax.16b v26, v1, v3, v2 - bcax.16b v2, v2, v4, v3 - bcax.16b v3, v3, v0, v4 - bcax.16b v4, v4, v1, v0 - mov.16b v0, v25 - mov.16b v1, v26 - - bcax.16b v25, v5, v7, v6 - bcax.16b v26, v6, v8, v7 - bcax.16b v7, v7, v9, v8 - bcax.16b v8, v8, v5, v9 - bcax.16b v9, v9, v6, v5 - mov.16b v5, v25 - mov.16b v6, v26 - - bcax.16b v25, v10, v12, v11 - bcax.16b v26, v11, v13, v12 - bcax.16b v12, v12, v14, v13 - bcax.16b v13, v13, v10, v14 - bcax.16b v14, v14, v11, v10 - mov.16b v10, v25 - mov.16b v11, v26 - - bcax.16b v25, v15, v17, v16 - bcax.16b v26, v16, v18, v17 - bcax.16b v17, v17, v19, v18 - bcax.16b v18, v18, v15, v19 - bcax.16b v19, v19, v16, v15 - mov.16b v15, v25 - mov.16b v16, v26 - - bcax.16b v25, v20, v22, v21 - bcax.16b v26, v21, v23, v22 - bcax.16b v22, v22, v24, v23 - bcax.16b v23, v23, v20, v24 - bcax.16b v24, v24, v21, v20 - mov.16b v20, v25 - mov.16b v21, v26 - - # iota - ld1r {v25.2d}, [x1], #8 - eor.16b v0, v0, v25 -.endm - -.align 4 -.global __f1600x2 -__f1600x2: - stp d8, d9, [sp,#-16]! - stp d10, d11, [sp,#-16]! - stp d12, d13, [sp,#-16]! - stp d14, d15, [sp,#-16]! - - mov x2, x0 - mov x3, #24 - - ld1.2d {v0, v1, v2, v3}, [x0], #64 - ld1.2d {v4, v5, v6, v7}, [x0], #64 - ld1.2d {v8, v9, v10, v11}, [x0], #64 - ld1.2d {v12, v13, v14, v15}, [x0], #64 - ld1.2d {v16, v17, v18, v19}, [x0], #64 - ld1.2d {v20, v21, v22, v23}, [x0], #64 - ld1.2d {v24}, [x0] - -loop: - round - - subs x3, x3, #1 - cbnz x3, loop - - mov x0, x2 - st1.2d {v0, v1, v2, v3}, [x0], #64 - st1.2d {v4, v5, v6, v7}, [x0], #64 - st1.2d {v8, v9, v10, v11}, [x0], #64 - st1.2d {v12, v13, v14, v15}, [x0], #64 - st1.2d {v16, v17, v18, v19}, [x0], #64 - st1.2d {v20, v21, v22, v23}, [x0], #64 - st1.2d {v24}, [x0] - - ldp d14, d15, [sp], #16 - ldp d12, d13, [sp], #16 - ldp d10, d11, [sp], #16 - ldp d8, d9, [sp], #16 - - ret lr diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/f1600x2_const.c b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/f1600x2_const.c deleted file mode 100644 index e49c0ba149..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/f1600x2_const.c +++ /dev/null @@ -1,30 +0,0 @@ -#include "f1600x2.h" - -uint64_t f1600_RC[24] = { - 0x0000000000000001, - 0x0000000000008082, - 0x800000000000808A, - 0x8000000080008000, - 0x000000000000808B, - 0x0000000080000001, - 0x8000000080008081, - 0x8000000000008009, - 0x000000000000008A, - 0x0000000000000088, - 0x0000000080008009, - 0x000000008000000A, - 0x000000008000808B, - 0x800000000000008B, - 0x8000000000008089, - 0x8000000000008003, - 0x8000000000008002, - 0x8000000000000080, - 0x000000000000800A, - 0x800000008000000A, - 0x8000000080008081, - 0x8000000000008080, - 0x0000000080000001, - 0x8000000080008008, -}; - - diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/fips202x2.c b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/fips202x2.c deleted file mode 100644 index 4718c343bc..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/fips202x2.c +++ /dev/null @@ -1,148 +0,0 @@ -#include -#include - -#include "fips202x2.h" -#include "f1600x2.h" -#include "fips202.h" - -uint64_t load64(const unsigned char *x) { - unsigned long long r = 0, i; - - for (i = 0; i < 8; ++i) { - r |= (unsigned long long)x[i] << 8 * i; - } - return r; -} - -void store64(uint8_t *x, uint64_t u) { - unsigned int i; - - for (i = 0; i < 8; ++i) { - x[i] = (uint8_t)u; - u >>= 8; - } -} - -static void keccak_absorb2x(uint64_t *s, - unsigned int r, - const unsigned char *m0, - const unsigned char *m1, - unsigned long long int mlen, - unsigned char p) { - unsigned long long i; - unsigned char t0[200]; - unsigned char t1[200]; - - while (mlen >= r) { - for (i = 0; i < r / 8; ++i) { - s[2 * i + 0] ^= load64(m0 + 8 * i); - s[2 * i + 1] ^= load64(m1 + 8 * i); - } - - f1600x2(s); - mlen -= r; - m0 += r; - m1 += r; - } - - for (i = 0; i < r; ++i) { - t0[i] = 0; - t1[i] = 0; - } - for (i = 0; i < mlen; ++i) { - t0[i] = m0[i]; - t1[i] = m1[i]; - } - - t0[i] = p; - t1[i] = p; - - t0[r - 1] |= 128; - t1[r - 1] |= 128; - - for (i = 0; i < r / 8; ++i) { - s[2 * i + 0] ^= load64(t0 + 8 * i); - s[2 * i + 1] ^= load64(t1 + 8 * i); - } -} - - -static void keccak_squeezeblocks2x(unsigned char *h0, - unsigned char *h1, - unsigned long long int nblocks, - uint64_t *s, - unsigned int r) { - unsigned int i; - - while (nblocks > 0) { - f1600x2(s); - for (i = 0; i < (r >> 3); i++) { - store64(h0 + 8 * i, s[2 * i + 0]); - store64(h1 + 8 * i, s[2 * i + 1]); - } - h0 += r; - h1 += r; - nblocks--; - } -} - - - -void shake128x2(unsigned char *out0, - unsigned char *out1, - unsigned long long outlen, - unsigned char *in0, - unsigned char *in1, - unsigned long long inlen) { - uint64_t s[50] = {0}; - unsigned char t0[SHAKE128_RATE]; - unsigned char t1[SHAKE128_RATE]; - unsigned int i; - - /* absorb 4 message of identical length in parallel */ - keccak_absorb2x(s, SHAKE128_RATE, in0, in1, inlen, 0x1F); - - /* Squeeze output */ - keccak_squeezeblocks2x(out0, out1, outlen / SHAKE128_RATE, s, SHAKE128_RATE); - - out0 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; - out1 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; - - if (outlen % SHAKE128_RATE) { - keccak_squeezeblocks2x(t0, t1, 1, s, SHAKE128_RATE); - for (i = 0; i < outlen % SHAKE128_RATE; i++) { - out0[i] = t0[i]; - out1[i] = t1[i]; - } - } -} - - -void shake256x2(unsigned char *out0, - unsigned char *out1, - unsigned long long outlen, - unsigned char *in0, - unsigned char *in1, - unsigned long long inlen) { - uint64_t s[50] = {0}; - unsigned char t0[SHAKE256_RATE]; - unsigned char t1[SHAKE256_RATE]; - unsigned int i; - - /* absorb 2 message of identical length in parallel */ - keccak_absorb2x(s, SHAKE256_RATE, in0, in1, inlen, 0x1F); - - /* Squeeze output */ - keccak_squeezeblocks2x(out0, out1, outlen / SHAKE256_RATE, s, SHAKE256_RATE); - - out0 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; - out1 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; - - if (outlen % SHAKE256_RATE) { - keccak_squeezeblocks2x(t0, t1, 1, s, SHAKE256_RATE); - for (i = 0; i < outlen % SHAKE256_RATE; i++) { - out0[i] = t0[i]; - out1[i] = t1[i]; - } - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/fips202x2.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/fips202x2.h deleted file mode 100644 index 7ba58b35d8..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/fips202x2.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef SPX_FIPS202X2_H -#define SPX_FIPS202X2_H - -#include - -uint64_t load64(const unsigned char *x); -void store64(uint8_t *x, uint64_t u); - - -void shake128x2(unsigned char *out0, - unsigned char *out1, - unsigned long long outlen, - unsigned char *in0, - unsigned char *in1, - unsigned long long inlen); - -void shake256x2(unsigned char *out0, - unsigned char *out1, - unsigned long long outlen, - unsigned char *in0, - unsigned char *in1, - unsigned long long inlen); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/fors.c b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/fors.c deleted file mode 100644 index 39193d04e2..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/fors.c +++ /dev/null @@ -1,191 +0,0 @@ -#include -#include -#include - -#include "fors.h" - -#include "address.h" -#include "hash.h" -#include "hashx2.h" -#include "thash.h" -#include "thashx2.h" -#include "utils.h" -#include "utilsx2.h" - -static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, - uint32_t fors_leaf_addr[8]) { - prf_addr(sk, ctx, fors_leaf_addr); -} - -static void fors_gen_skx2(unsigned char *sk0, - unsigned char *sk1, - const spx_ctx *ctx, - uint32_t fors_leaf_addrx2[2 * 8]) { - prf_addrx2(sk0, sk1, - ctx, fors_leaf_addrx2); -} - -static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, - const spx_ctx *ctx, - uint32_t fors_leaf_addr[8]) { - thash(leaf, sk, 1, ctx, fors_leaf_addr); -} - -static void fors_sk_to_leafx2(unsigned char *leaf0, - unsigned char *leaf1, - const unsigned char *sk0, - const unsigned char *sk1, - const spx_ctx *ctx, - uint32_t fors_leaf_addrx2[2 * 8]) { - thashx2(leaf0, leaf1, - sk0, sk1, - 1, ctx, fors_leaf_addrx2); -} - -struct fors_gen_leaf_info { - uint32_t leaf_addrx[2 * 8]; -}; - -static void fors_gen_leafx2(unsigned char *leaf, - const spx_ctx *ctx, - uint32_t addr_idx, void *info) { - struct fors_gen_leaf_info *fors_info = info; - uint32_t *fors_leaf_addrx2 = fors_info->leaf_addrx; - unsigned int j; - - /* Only set the parts that the caller doesn't set */ - for (j = 0; j < 2; j++) { - set_tree_index(fors_leaf_addrx2 + j * 8, addr_idx + j); - set_type(fors_leaf_addrx2 + j * 8, SPX_ADDR_TYPE_FORSPRF); - } - - fors_gen_skx2(leaf + 0 * SPX_N, - leaf + 1 * SPX_N, - ctx, fors_leaf_addrx2); - - for (j = 0; j < 2; j++) { - set_type(fors_leaf_addrx2 + j * 8, SPX_ADDR_TYPE_FORSTREE); - } - - fors_sk_to_leafx2(leaf + 0 * SPX_N, - leaf + 1 * SPX_N, - leaf + 0 * SPX_N, - leaf + 1 * SPX_N, - ctx, fors_leaf_addrx2); -} - -/** - * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - * Assumes indices has space for SPX_FORS_TREES integers. - */ -static void message_to_indices(uint32_t *indices, const unsigned char *m) { - unsigned int i, j; - unsigned int offset = 0; - - for (i = 0; i < SPX_FORS_TREES; i++) { - indices[i] = 0; - for (j = 0; j < SPX_FORS_HEIGHT; j++) { - indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); - offset++; - } - } -} - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -void fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]) { - uint32_t indices[SPX_FORS_TREES]; - unsigned char roots[SPX_FORS_TREES * SPX_N]; - uint32_t fors_tree_addr[2 * 8] = {0}; - struct fors_gen_leaf_info fors_info = {0}; - uint32_t *fors_leaf_addr = fors_info.leaf_addrx; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - for (i = 0; i < 2; i++) { - copy_keypair_addr(fors_tree_addr + 8 * i, fors_addr); - set_type(fors_tree_addr + 8 * i, SPX_ADDR_TYPE_FORSTREE); - copy_keypair_addr(fors_leaf_addr + 8 * i, fors_addr); - } - copy_keypair_addr(fors_pk_addr, fors_addr); - set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < SPX_FORS_TREES; i++) { - idx_offset = i * (1 << SPX_FORS_HEIGHT); - - set_tree_height(fors_tree_addr, 0); - set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Include the secret key part that produces the selected leaf node. */ - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); - fors_gen_sk(sig, ctx, fors_tree_addr); - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); - sig += SPX_N; - - /* Compute the authentication path for this leaf node. */ - treehashx2(roots + i * SPX_N, sig, ctx, - indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx2, - fors_tree_addr, &fors_info); - - sig += SPX_N * SPX_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); -} - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -void fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]) { - uint32_t indices[SPX_FORS_TREES]; - unsigned char roots[SPX_FORS_TREES * SPX_N]; - unsigned char leaf[SPX_N]; - uint32_t fors_tree_addr[8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - copy_keypair_addr(fors_tree_addr, fors_addr); - copy_keypair_addr(fors_pk_addr, fors_addr); - - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); - set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < SPX_FORS_TREES; i++) { - idx_offset = i * (1 << SPX_FORS_HEIGHT); - - set_tree_height(fors_tree_addr, 0); - set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Derive the leaf from the included secret key part. */ - fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); - sig += SPX_N; - - /* Derive the corresponding root node of this tree. */ - compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, - sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); - sig += SPX_N * SPX_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/fors.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/fors.h deleted file mode 100644 index 509140a178..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/fors.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef SPX_FORS_H -#define SPX_FORS_H - -#include - -#include "context.h" -#include "params.h" - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -#define fors_sign SPX_NAMESPACE(fors_sign) -void fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]); - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) -void fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/hash.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/hash.h deleted file mode 100644 index f7c87d4c3c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/hash.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef SPX_HASH_H -#define SPX_HASH_H - -#include -#include - -#include "context.h" -#include "params.h" - -#define prf_addr SPX_NAMESPACE(prf_addr) -void prf_addr(unsigned char *out, const spx_ctx *ctx, - const uint32_t addr[8]); - -#define gen_message_random SPX_NAMESPACE(gen_message_random) -void gen_message_random(unsigned char *R, const unsigned char *sk_prf, - const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx); - -#define hash_message SPX_NAMESPACE(hash_message) -void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx); - - - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/hash_shake.c b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/hash_shake.c deleted file mode 100644 index ff5e7ec918..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/hash_shake.c +++ /dev/null @@ -1,83 +0,0 @@ -#include -#include - -#include "hash.h" - -#include "address.h" -#include "fips202.h" -#include "params.h" -#include "utils.h" - -/* - * Computes PRF(pk_seed, sk_seed, addr) - */ -void prf_addr(unsigned char *out, const spx_ctx *ctx, - const uint32_t addr[8]) { - unsigned char buf[2 * SPX_N + SPX_ADDR_BYTES]; - - memcpy(buf, ctx->pub_seed, SPX_N); - memcpy(buf + SPX_N, addr, SPX_ADDR_BYTES); - memcpy(buf + SPX_N + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); - - shake256(out, SPX_N, buf, 2 * SPX_N + SPX_ADDR_BYTES); -} - -/** - * Computes the message-dependent randomness R, using a secret seed and an - * optional randomization value as well as the message. - */ -void gen_message_random(unsigned char *R, const unsigned char *sk_prf, - const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx) { - (void)ctx; - shake256incctx s_inc; - - shake256_inc_init(&s_inc); - shake256_inc_absorb(&s_inc, sk_prf, SPX_N); - shake256_inc_absorb(&s_inc, optrand, SPX_N); - shake256_inc_absorb(&s_inc, m, mlen); - shake256_inc_finalize(&s_inc); - shake256_inc_squeeze(R, SPX_N, &s_inc); - shake256_inc_ctx_release(&s_inc); -} - -/** - * Computes the message hash using R, the public key, and the message. - * Outputs the message digest and the index of the leaf. The index is split in - * the tree index and the leaf index, for convenient copying to an address. - */ -void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx) { - (void)ctx; -#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) -#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) -#define SPX_LEAF_BITS SPX_TREE_HEIGHT -#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) -#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) - - unsigned char buf[SPX_DGST_BYTES]; - unsigned char *bufp = buf; - shake256incctx s_inc; - - shake256_inc_init(&s_inc); - shake256_inc_absorb(&s_inc, R, SPX_N); - shake256_inc_absorb(&s_inc, pk, SPX_PK_BYTES); - shake256_inc_absorb(&s_inc, m, mlen); - shake256_inc_finalize(&s_inc); - shake256_inc_squeeze(buf, SPX_DGST_BYTES, &s_inc); - shake256_inc_ctx_release(&s_inc); - - memcpy(digest, bufp, SPX_FORS_MSG_BYTES); - bufp += SPX_FORS_MSG_BYTES; - - - *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); - *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); - bufp += SPX_TREE_BYTES; - - *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); - *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/hash_shakex2.c b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/hash_shakex2.c deleted file mode 100644 index 99571916a2..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/hash_shakex2.c +++ /dev/null @@ -1,52 +0,0 @@ -#include -#include - -#include "hashx2.h" - -#include "address.h" -#include "f1600x2.h" -#include "fips202x2.h" -#include "params.h" - -/* - * 2-way parallel version of prf_addr; takes 2x as much input and output - */ -void prf_addrx2(unsigned char *out0, - unsigned char *out1, - const spx_ctx *ctx, - const uint32_t addrx2[2 * 8]) { - /* As we write and read only a few quadwords, it is more efficient to - * build and extract from the fourway SHAKE256 state by hand. */ - uint64_t state[50] = {0}; - - for (int i = 0; i < SPX_N / 8; i++) { - uint64_t x = load64(ctx->pub_seed + 8 * i); - state[2 * i] = x; - state[2 * i + 1] = x; - } - for (int i = 0; i < 4; i++) { - state[2 * (SPX_N / 8 + i)] = (((uint64_t)addrx2[1 + 2 * i]) << 32) - | (uint64_t)addrx2[2 * i]; - state[2 * (SPX_N / 8 + i) + 1] = (((uint64_t)addrx2[8 + 1 + 2 * i]) << 32) - | (uint64_t)addrx2[8 + 2 * i]; - } - for (int i = 0; i < SPX_N / 8; i++) { - uint64_t x = load64(ctx->sk_seed + 8 * i); - state[2 * (SPX_N / 8 + i + 4)] = x; - state[2 * (SPX_N / 8 + i + 4) + 1] = x; - } - - /* SHAKE domain separator and padding. */ - state[2 * (SPX_N / 4 + 4)] = 0x1f; - state[2 * (SPX_N / 4 + 4) + 1] = 0x1f; - - state[2 * 16] = 0x80ULL << 56; - state[2 * 16 + 1] = 0x80ULL << 56; - - f1600x2(state); - - for (int i = 0; i < SPX_N / 8; i++) { - store64(out0 + 8 * i, state[2 * i]); - store64(out1 + 8 * i, state[2 * i + 1]); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/hashx2.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/hashx2.h deleted file mode 100644 index 99b8873a9b..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/hashx2.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef SPX_HASHX2_H -#define SPX_HASHX2_H - -#include "context.h" -#include "params.h" -#include - -#define prf_addrx2 SPX_NAMESPACE(prf_addrx2) -void prf_addrx2(unsigned char *out0, - unsigned char *out1, - const spx_ctx *ctx, - const uint32_t addrx2[2 * 8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/merkle.c b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/merkle.c deleted file mode 100644 index c94ee23939..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/merkle.c +++ /dev/null @@ -1,64 +0,0 @@ -#include -#include - -#include "merkle.h" - -#include "address.h" -#include "params.h" -#include "utils.h" -#include "utilsx2.h" -#include "wots.h" -#include "wotsx2.h" - -/* - * This generates a Merkle signature (WOTS signature followed by the Merkle - * authentication path). - */ -void merkle_sign(uint8_t *sig, unsigned char *root, - const spx_ctx *ctx, - uint32_t wots_addr[8], uint32_t tree_addr[8], - uint32_t idx_leaf) { - unsigned char *auth_path = sig + SPX_WOTS_BYTES; - uint32_t tree_addrx2[2 * 8] = { 0 }; - int j; - struct leaf_info_x2 info = { 0 }; - unsigned steps[ SPX_WOTS_LEN ]; - - info.wots_sig = sig; - chain_lengths(steps, root); - info.wots_steps = steps; - - for (j = 0; j < 2; j++) { - set_type(&tree_addrx2[8 * j], SPX_ADDR_TYPE_HASHTREE); - set_type(&info.leaf_addr[8 * j], SPX_ADDR_TYPE_WOTS); - set_type(&info.pk_addr[8 * j], SPX_ADDR_TYPE_WOTSPK); - copy_subtree_addr(&tree_addrx2[8 * j], tree_addr); - copy_subtree_addr(&info.leaf_addr[8 * j], wots_addr); - copy_subtree_addr(&info.pk_addr[8 * j], wots_addr); - } - - info.wots_sign_leaf = idx_leaf; - - treehashx2(root, auth_path, ctx, - idx_leaf, 0, - SPX_TREE_HEIGHT, - wots_gen_leafx2, - tree_addrx2, &info); -} - -/* Compute root node of the top-most subtree. */ -void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { - /* We do not need the auth path in key generation, but it simplifies the - code to have just one treehash routine that computes both root and path - in one function. */ - unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; - uint32_t top_tree_addr[8] = {0}; - uint32_t wots_addr[8] = {0}; - - set_layer_addr(top_tree_addr, SPX_D - 1); - set_layer_addr(wots_addr, SPX_D - 1); - - merkle_sign(auth_path, root, ctx, - wots_addr, top_tree_addr, - ~0 /* ~0 means "don't bother generating an auth path */ ); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/merkle.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/merkle.h deleted file mode 100644 index 769cf2e970..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/merkle.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef MERKLE_H_ -#define MERKLE_H_ - -#include - -#include "context.h" -#include "params.h" - -/* Generate a Merkle signature (WOTS signature followed by the Merkle */ -/* authentication path) */ -#define merkle_sign SPX_NAMESPACE(merkle_sign) -void merkle_sign(uint8_t *sig, unsigned char *root, - const spx_ctx *ctx, - uint32_t wots_addr[8], uint32_t tree_addr[8], - uint32_t idx_leaf); - -/* Compute the root node of the top-most subtree. */ -#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) -void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); - -#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/nistapi.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/nistapi.h deleted file mode 100644 index 3cb71afad4..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/nistapi.h +++ /dev/null @@ -1,87 +0,0 @@ -#ifndef SPX_API_H -#define SPX_API_H - -#include -#include - -#include "params.h" - -#define CRYPTO_ALGNAME "SPHINCS+" - -#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES -#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES -#define CRYPTO_BYTES SPX_BYTES -#define CRYPTO_SEEDBYTES (3*SPX_N) - -/* - * Returns the length of a secret key, in bytes - */ -#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) -size_t crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) -size_t crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) -size_t crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) -size_t crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) -int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) -int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) -int crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) -int crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -#define crypto_sign SPX_NAMESPACE(crypto_sign) -int crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) -int crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/params.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/params.h deleted file mode 100644 index efa39d84b6..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/params.h +++ /dev/null @@ -1,56 +0,0 @@ -#ifndef SPX_PARAMS_H -#define SPX_PARAMS_H - -#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSSHAKE192FROBUST_AARCH64_##s - -/* Hash output length in bytes. */ -#define SPX_N 24 -/* Height of the hypertree. */ -#define SPX_FULL_HEIGHT 66 -/* Number of subtree layer. */ -#define SPX_D 22 -/* FORS tree dimensions. */ -#define SPX_FORS_HEIGHT 8 -#define SPX_FORS_TREES 33 -/* Winternitz parameter, */ -#define SPX_WOTS_W 16 - -/* The hash function is defined by linking a different hash.c file, as opposed - to setting a #define constant. */ - -/* For clarity */ -#define SPX_ADDR_BYTES 32 - -/* WOTS parameters. */ -#define SPX_WOTS_LOGW 4 - -#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) - -/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#define SPX_WOTS_LEN2 3 - -#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) -#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) -#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES - -/* Subtree size. */ -#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) - -//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT -// #error SPX_D should always divide SPX_FULL_HEIGHT -//#endif - -/* FORS parameters. */ -#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) -#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) -#define SPX_FORS_PK_BYTES SPX_N - -/* Resulting SPX sizes. */ -#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ - SPX_FULL_HEIGHT * SPX_N) -#define SPX_PK_BYTES (2 * SPX_N) -#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) - -#include "shake_offsets.h" - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/shake_offsets.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/shake_offsets.h deleted file mode 100644 index 6b28d95d91..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/shake_offsets.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef SHAKE_OFFSETS_H_ -#define SHAKE_OFFSETS_H_ - -/* - * Offsets of various fields in the address structure when we use SHAKE as - * the Sphincs+ hash function - */ - -#define SPX_OFFSET_LAYER 3 /* The byte used to specify the Merkle tree layer */ -#define SPX_OFFSET_TREE 8 /* The start of the 8 byte field used to specify the tree */ -#define SPX_OFFSET_TYPE 19 /* The byte used to specify the hash type (reason) */ -#define SPX_OFFSET_KP_ADDR2 22 /* The high byte used to specify the key pair (which one-time signature) */ -#define SPX_OFFSET_KP_ADDR1 23 /* The low byte used to specify the key pair */ -#define SPX_OFFSET_CHAIN_ADDR 27 /* The byte used to specify the chain address (which Winternitz chain) */ -#define SPX_OFFSET_HASH_ADDR 31 /* The byte used to specify the hash address (where in the Winternitz chain) */ -#define SPX_OFFSET_TREE_HGT 27 /* The byte used to specify the height of this node in the FORS or Merkle tree */ -#define SPX_OFFSET_TREE_INDEX 28 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ - -#define SPX_SHAKE 1 - -#endif /* SHAKE_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/sign.c b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/sign.c deleted file mode 100644 index 9d0c7d1b22..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/sign.c +++ /dev/null @@ -1,286 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "context.h" -#include "fors.h" -#include "hash.h" -#include "merkle.h" -#include "nistapi.h" -#include "params.h" -#include "randombytes.h" -#include "thash.h" -#include "utils.h" -#include "wots.h" - -/* - * Returns the length of a secret key, in bytes - */ -size_t crypto_sign_secretkeybytes(void) { - return CRYPTO_SECRETKEYBYTES; -} - -/* - * Returns the length of a public key, in bytes - */ -size_t crypto_sign_publickeybytes(void) { - return CRYPTO_PUBLICKEYBYTES; -} - -/* - * Returns the length of a signature, in bytes - */ -size_t crypto_sign_bytes(void) { - return CRYPTO_BYTES; -} - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t crypto_sign_seedbytes(void) { - return CRYPTO_SEEDBYTES; -} - -/* - * Generates an SPX key pair given a seed of length - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed) { - spx_ctx ctx; - - /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ - memcpy(sk, seed, CRYPTO_SEEDBYTES); - - memcpy(pk, sk + 2 * SPX_N, SPX_N); - - memcpy(ctx.pub_seed, pk, SPX_N); - memcpy(ctx.sk_seed, sk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - /* Compute root node of the top-most subtree. */ - merkle_gen_root(sk + 3 * SPX_N, &ctx); - - // cleanup - free_hash_function(&ctx); - - memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); - - return 0; -} - -/* - * Generates an SPX key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { - uint8_t seed[CRYPTO_SEEDBYTES]; - randombytes(seed, CRYPTO_SEEDBYTES); - crypto_sign_seed_keypair(pk, sk, seed); - - return 0; -} - -/** - * Returns an array containing a detached signature. - */ -int crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - spx_ctx ctx; - - const uint8_t *sk_prf = sk + SPX_N; - const uint8_t *pk = sk + 2 * SPX_N; - - uint8_t optrand[SPX_N]; - uint8_t mhash[SPX_FORS_MSG_BYTES]; - uint8_t root[SPX_N]; - uint32_t i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - - memcpy(ctx.sk_seed, sk, SPX_N); - memcpy(ctx.pub_seed, pk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - set_type(wots_addr, SPX_ADDR_TYPE_WOTS); - set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); - - /* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ - randombytes(optrand, SPX_N); - /* Compute the digest randomization value. */ - gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); - - /* Derive the message digest and leaf index from R, PK and M. */ - hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); - sig += SPX_N; - - set_tree_addr(wots_addr, tree); - set_keypair_addr(wots_addr, idx_leaf); - - /* Sign the message hash using FORS. */ - fors_sign(sig, root, mhash, &ctx, wots_addr); - sig += SPX_FORS_BYTES; - - for (i = 0; i < SPX_D; i++) { - set_layer_addr(tree_addr, i); - set_tree_addr(tree_addr, tree); - - copy_subtree_addr(wots_addr, tree_addr); - set_keypair_addr(wots_addr, idx_leaf); - - merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); - sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); - tree = tree >> SPX_TREE_HEIGHT; - } - - free_hash_function(&ctx); - - *siglen = SPX_BYTES; - - return 0; -} - -/** - * Verifies a detached signature and message under a given public key. - */ -int crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk) { - spx_ctx ctx; - const uint8_t *pub_root = pk + SPX_N; - uint8_t mhash[SPX_FORS_MSG_BYTES]; - uint8_t wots_pk[SPX_WOTS_BYTES]; - uint8_t root[SPX_N]; - uint8_t leaf[SPX_N]; - unsigned int i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - if (siglen != SPX_BYTES) { - return -1; - } - - memcpy(ctx.pub_seed, pk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - set_type(wots_addr, SPX_ADDR_TYPE_WOTS); - set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); - set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); - - /* Derive the message digest and leaf index from R || PK || M. */ - /* The additional SPX_N is a result of the hash domain separator. */ - hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); - sig += SPX_N; - - /* Layer correctly defaults to 0, so no need to set_layer_addr */ - set_tree_addr(wots_addr, tree); - set_keypair_addr(wots_addr, idx_leaf); - - fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); - sig += SPX_FORS_BYTES; - - /* For each subtree.. */ - for (i = 0; i < SPX_D; i++) { - set_layer_addr(tree_addr, i); - set_tree_addr(tree_addr, tree); - - copy_subtree_addr(wots_addr, tree_addr); - set_keypair_addr(wots_addr, idx_leaf); - - copy_keypair_addr(wots_pk_addr, wots_addr); - - /* The WOTS public key is only correct if the signature was correct. */ - /* Initially, root is the FORS pk, but on subsequent iterations it is - the root of the subtree below the currently processed subtree. */ - wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); - sig += SPX_WOTS_BYTES; - - /* Compute the leaf node using the WOTS public key. */ - thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); - - /* Compute the root node of this subtree. */ - compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, - &ctx, tree_addr); - sig += SPX_TREE_HEIGHT * SPX_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); - tree = tree >> SPX_TREE_HEIGHT; - } - - // cleanup - free_hash_function(&ctx); - - /* Check if the root node equals the root node in the public key. */ - if (memcmp(root, pub_root, SPX_N) != 0) { - return -1; - } - - return 0; -} - - -/** - * Returns an array containing the signature followed by the message. - */ -int crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk) { - size_t siglen; - - crypto_sign_signature(sm, &siglen, m, mlen, sk); - - memmove(sm + SPX_BYTES, m, mlen); - *smlen = siglen + mlen; - - return 0; -} - -/** - * Verifies a given signature-message pair under a given public key. - */ -int crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk) { - /* The API caller does not necessarily know what size a signature should be - but SPHINCS+ signatures are always exactly SPX_BYTES. */ - if (smlen < SPX_BYTES) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - *mlen = smlen - SPX_BYTES; - - if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - /* If verification was successful, move the message to the right place. */ - memmove(m, sm + SPX_BYTES, *mlen); - - return 0; -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/thash.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/thash.h deleted file mode 100644 index 8687ccfb4d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/thash.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef SPX_THASH_H -#define SPX_THASH_H - -#include "context.h" -#include "params.h" - -#include - -#define thash SPX_NAMESPACE(thash) -void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/thash_shake_robustx2.c b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/thash_shake_robustx2.c deleted file mode 100644 index 454fc0f4e2..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/thash_shake_robustx2.c +++ /dev/null @@ -1,112 +0,0 @@ -#include -#include - -#include "thash.h" -#include "thashx2.h" - -#include "address.h" -#include "params.h" -#include "utils.h" - -#include "f1600x2.h" -#include "fips202x2.h" - - -void thash(unsigned char *out, - const unsigned char *in, - unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]) { - uint32_t addrx2 [2 * 8] = { - addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], addr[6], addr[7], - addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], addr[6], addr[7] - }; - thashx2(out, out, in, in, inblocks, ctx, addrx2); -} - -/** - * 2-way parallel version of thash; takes 2x as much input and output - */ -void thashx2(unsigned char *out0, - unsigned char *out1, - const unsigned char *in0, - const unsigned char *in1, - unsigned int inblocks, - const spx_ctx *ctx, uint32_t addrx2[2 * 8]) { - if (inblocks == 1 || inblocks == 2) { - /* As we write and read only a few quadwords, it is more efficient to - * build and extract from the twoway SHAKE256 state by hand. */ - uint64_t state[50] = {0}; - uint64_t state2[50]; - - for (int i = 0; i < SPX_N / 8; i++) { - uint64_t x = load64(ctx->pub_seed + 8 * i); - state[2 * i] = x; - state[2 * i + 1] = x; - } - for (int i = 0; i < 4; i++) { - state[2 * (SPX_N / 8 + i)] = (((uint64_t)addrx2[1 + 2 * i]) << 32) - | (uint64_t)addrx2[2 * i]; - state[2 * (SPX_N / 8 + i) + 1] = (((uint64_t)addrx2[8 + 1 + 2 * i]) << 32) - | (uint64_t)addrx2[8 + 2 * i]; - } - - /* Domain separator and padding. */ - state[2 * 16] = 0x80ULL << 56; - state[2 * 16 + 1] = 0x80ULL << 56; - - state[2 * ((SPX_N / 8) + 4)] ^= 0x1f; - state[2 * ((SPX_N / 8) + 4) + 1] ^= 0x1f; - - /* We will permutate state2 with f1600x2 to compute the bitmask, - * but first we'll copy it to state2 which will be used to compute - * the final output, as its input is almost identical. */ - memcpy(state2, state, 400); - - f1600x2(state); - - /* By copying from state, state2 already contains the pub_seed - * and address. We just need to copy in the input blocks xorred with - * the bitmask we just computed. */ - for (unsigned int i = 0; i < (SPX_N / 8) * inblocks; i++) { - state2[2 * (SPX_N / 8 + 4 + i)] = state[2 * i] ^ load64(in0 + 8 * i); - state2[2 * (SPX_N / 8 + 4 + i) + 1] = state[2 * i + 1] ^ load64(in1 + 8 * i); - } - - /* Domain separator and start of padding. Note that the quadwords - * around are already zeroed for state from which we copied. - * We do a XOR instead of a set as this might be the 16th quadword - * when N=32 and inblocks=2, which already contains the end - * of the padding. */ - state2[2 * ((SPX_N / 8) * (1 + inblocks) + 4)] ^= 0x1f; - state2[2 * ((SPX_N / 8) * (1 + inblocks) + 4) + 1] ^= 0x1f; - - f1600x2(state2); - - for (int i = 0; i < SPX_N / 8; i++) { - store64(out0 + 8 * i, state2[2 * i]); - store64(out1 + 8 * i, state2[2 * i + 1]); - } - } else { - PQCLEAN_VLA(unsigned char, buf0, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); - PQCLEAN_VLA(unsigned char, buf1, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); - PQCLEAN_VLA(unsigned char, bitmask0, inblocks * SPX_N); - PQCLEAN_VLA(unsigned char, bitmask1, inblocks * SPX_N); - unsigned int i; - - memcpy(buf0, ctx->pub_seed, SPX_N); - memcpy(buf1, ctx->pub_seed, SPX_N); - memcpy(buf0 + SPX_N, addrx2 + 0 * 8, SPX_ADDR_BYTES); - memcpy(buf1 + SPX_N, addrx2 + 1 * 8, SPX_ADDR_BYTES); - - shake256x2(bitmask0, bitmask1, inblocks * SPX_N, - buf0, buf1, SPX_N + SPX_ADDR_BYTES); - - for (i = 0; i < inblocks * SPX_N; i++) { - buf0[SPX_N + SPX_ADDR_BYTES + i] = in0[i] ^ bitmask0[i]; - buf1[SPX_N + SPX_ADDR_BYTES + i] = in1[i] ^ bitmask1[i]; - } - - shake256x2(out0, out1, SPX_N, - buf0, buf1, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/thashx2.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/thashx2.h deleted file mode 100644 index 040375e618..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/thashx2.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef SPX_THASHX2_H -#define SPX_THASHX2_H - -#include "context.h" -#include "params.h" -#include - -#define thashx2 SPX_NAMESPACE(thashx2) -void thashx2(unsigned char *out0, - unsigned char *out1, - const unsigned char *in0, - const unsigned char *in1, - unsigned int inblocks, - const spx_ctx *ctx, uint32_t addrx2[2 * 8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/utils.c b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/utils.c deleted file mode 100644 index 177b541fb9..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/utils.c +++ /dev/null @@ -1,148 +0,0 @@ -#include - -#include "utils.h" - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "thash.h" - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void ull_to_bytes(unsigned char *out, unsigned int outlen, - unsigned long long in) { - int i; - - /* Iterate over out in decreasing order, for big-endianness. */ - for (i = (signed int)outlen - 1; i >= 0; i--) { - out[i] = in & 0xff; - in = in >> 8; - } -} - -void u32_to_bytes(unsigned char *out, uint32_t in) { - out[0] = (unsigned char)(in >> 24); - out[1] = (unsigned char)(in >> 16); - out[2] = (unsigned char)(in >> 8); - out[3] = (unsigned char)in; -} - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { - unsigned long long retval = 0; - unsigned int i; - - for (i = 0; i < inlen; i++) { - retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); - } - return retval; -} - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void compute_root(unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const spx_ctx *ctx, uint32_t addr[8]) { - uint32_t i; - unsigned char buffer[2 * SPX_N]; - - /* If leaf_idx is odd (last bit = 1), current path element is a right child - and auth_path has to go left. Otherwise it is the other way around. */ - if (leaf_idx & 1) { - memcpy(buffer + SPX_N, leaf, SPX_N); - memcpy(buffer, auth_path, SPX_N); - } else { - memcpy(buffer, leaf, SPX_N); - memcpy(buffer + SPX_N, auth_path, SPX_N); - } - auth_path += SPX_N; - - for (i = 0; i < tree_height - 1; i++) { - leaf_idx >>= 1; - idx_offset >>= 1; - /* Set the address of the node we're creating. */ - set_tree_height(addr, i + 1); - set_tree_index(addr, leaf_idx + idx_offset); - - /* Pick the right or left neighbor, depending on parity of the node. */ - if (leaf_idx & 1) { - thash(buffer + SPX_N, buffer, 2, ctx, addr); - memcpy(buffer, auth_path, SPX_N); - } else { - thash(buffer, buffer, 2, ctx, addr); - memcpy(buffer + SPX_N, auth_path, SPX_N); - } - auth_path += SPX_N; - } - - /* The last iteration is exceptional; we do not copy an auth_path node. */ - leaf_idx >>= 1; - idx_offset >>= 1; - set_tree_height(addr, tree_height); - set_tree_index(addr, leaf_idx + idx_offset); - thash(root, buffer, 2, ctx, addr); -} - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const spx_ctx * /* ctx */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), - uint32_t tree_addr[8]) { - PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); - PQCLEAN_VLA(unsigned int, heights, tree_height + 1); - unsigned int offset = 0; - uint32_t idx; - uint32_t tree_idx; - - for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { - /* Add the next leaf node to the stack. */ - gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); - offset++; - heights[offset - 1] = 0; - - /* If this is a node we need for the auth path.. */ - if ((leaf_idx ^ 0x1) == idx) { - memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); - } - - /* While the top-most nodes are of equal height.. */ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { - /* Compute index of the new node, in the next layer. */ - tree_idx = (idx >> (heights[offset - 1] + 1)); - - /* Set the address of the node we're creating. */ - set_tree_height(tree_addr, heights[offset - 1] + 1); - set_tree_index(tree_addr, - tree_idx + (idx_offset >> (heights[offset - 1] + 1))); - /* Hash the top-most nodes from the stack together. */ - thash(stack + (offset - 2)*SPX_N, - stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); - offset--; - /* Note that the top-most node is now one layer higher. */ - heights[offset - 1]++; - - /* If this is a node we need for the auth path.. */ - if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_path + heights[offset - 1]*SPX_N, - stack + (offset - 1)*SPX_N, SPX_N); - } - } - } - memcpy(root, stack, SPX_N); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/utils.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/utils.h deleted file mode 100644 index 64f5d5a53a..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/utils.h +++ /dev/null @@ -1,58 +0,0 @@ -#ifndef SPX_UTILS_H -#define SPX_UTILS_H - -#include - -#include "compat.h" -#include "context.h" -#include "params.h" - - -/* To support MSVC use alloca() instead of VLAs. See #20. */ - - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) -void ull_to_bytes(unsigned char *out, unsigned int outlen, - unsigned long long in); -#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) -void u32_to_bytes(unsigned char *out, uint32_t in); - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) -unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -#define compute_root SPX_NAMESPACE(compute_root) -void compute_root(unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const spx_ctx *ctx, uint32_t addr[8]); - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -#define treehash SPX_NAMESPACE(treehash) -void treehash(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const spx_ctx *ctx /* ctx */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), - uint32_t tree_addr[8]); - - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/utilsx2.c b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/utilsx2.c deleted file mode 100644 index 8736474e4f..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/utilsx2.c +++ /dev/null @@ -1,130 +0,0 @@ -#include - -#include "utilsx2.h" - -#include "address.h" -#include "params.h" -#include "thashx2.h" -#include "utils.h" - -/* - * Generate the entire Merkle tree, computing the authentication path for leaf_idx, - * and the resulting root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) - * - * This expects tree_addrx2 to be initialized to 2 parallel addr structures for - * the Merkle tree nodes - * - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - * - * This works by using the standard Merkle tree building algorithm, except - * that each 'node' tracked is actually 2 consecutive nodes in the real tree. - * When we combine two logical nodes AB and WX, we perform the H - * operation on adjacent real nodes, forming the parent logical node - * (AB)(WX) - * - * When we get to the top level of the real tree (where there is only - * one logical node), we continue this operation one more time; the right - * most real node will by the actual root (and the other node will be - * garbage). We follow the same thashx2 logic so that the 'extract - * authentication path components' part of the loop is still executed (and - * to simplify the code somewhat) - */ -void treehashx2(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, - uint32_t tree_height, - void (*gen_leafx2)( - unsigned char * /* Where to write the leaves */, - const spx_ctx *, - uint32_t idx, void *info), - uint32_t tree_addrx2[2 * 8], - void *info) { - /* This is where we keep the intermediate nodes */ - unsigned char stackx2[tree_height * 2 * SPX_N]; - uint32_t left_adj = 0, prev_left_adj = 0; /* When we're doing the top */ - /* level, the left-most part of the tree isn't at the beginning */ - /* of current[]. These give the offset of the actual start */ - - uint32_t idx; - uint32_t max_idx = (1 << (tree_height - 1)) - 1; - for (idx = 0;; idx++) { - unsigned char current[2 * SPX_N]; /* Current logical node */ - gen_leafx2( current, ctx, 2 * idx + idx_offset, - info ); - - /* Now combine the freshly generated right node with previously */ - /* generated left ones */ - uint32_t internal_idx_offset = idx_offset; - uint32_t internal_idx = idx; - uint32_t internal_leaf = leaf_idx; - uint32_t h; /* The height we are in the Merkle tree */ - for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { - - /* Special processing if we're at the top of the tree */ - if (h >= tree_height - 1) { - if (h == tree_height) { - /* We hit the root; return it */ - memcpy( root, ¤t[1 * SPX_N], SPX_N ); - return; - } - /* The tree indexing logic is a bit off in this case */ - /* Adjust it so that the left-most node of the part of */ - /* the tree that we're processing has index 0 */ - prev_left_adj = left_adj; - left_adj = 2 - (1 << (tree_height - h - 1)); - } - - /* Check if we hit the top of the tree */ - if (h == tree_height) { - /* We hit the root; return it */ - memcpy( root, ¤t[1 * SPX_N], SPX_N ); - return; - } - - /* - * Check if one of the nodes we have is a part of the - * authentication path; if it is, write it out - */ - if ((((internal_idx << 1) ^ internal_leaf) & ~0x1) == 0) { - memcpy( &auth_path[ h * SPX_N ], - ¤t[(((internal_leaf & 1) ^ 1) + prev_left_adj) * SPX_N], - SPX_N ); - } - - /* - * Check if we're at a left child; if so, stop going up the stack - * Exception: if we've reached the end of the tree, keep on going - * (so we combine the last 2 nodes into the one root node in two - * more iterations) - */ - if ((internal_idx & 1) == 0 && idx < max_idx) { - break; - } - - /* Ok, we're at a right node (or doing the top 3 levels) */ - /* Now combine the left and right logical nodes together */ - - /* Set the address of the node we're creating. */ - int j; - internal_idx_offset >>= 1; - for (j = 0; j < 2; j++) { - set_tree_height(tree_addrx2 + j * 8, h + 1); - set_tree_index(tree_addrx2 + j * 8, - (2 / 2) * (internal_idx & ~1) + j - left_adj + internal_idx_offset ); - } - unsigned char *left = &stackx2[h * 2 * SPX_N]; - thashx2( ¤t[0 * SPX_N], - ¤t[1 * SPX_N], - &left [0 * SPX_N], - ¤t[0 * SPX_N], - 2, ctx, tree_addrx2); - } - - /* We've hit a left child; save the current for when we get the */ - /* corresponding right right */ - memcpy( &stackx2[h * 2 * SPX_N], current, 2 * SPX_N); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/utilsx2.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/utilsx2.h deleted file mode 100644 index e09faddc43..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/utilsx2.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef SPX_UTILSX2_H -#define SPX_UTILSX2_H - -#include - -#include "context.h" -#include "params.h" - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - * - * This implementation uses SIMD to compute internal nodes 2 at a time (in - * parallel) - */ -#define treehashx2 SPX_NAMESPACE(treehashx2) -void treehashx2(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leafx2)( - unsigned char * /* Where to write the leaves */, - const spx_ctx * /* ctx */, - uint32_t addr_idx, void *info), - uint32_t tree_addrx2[2 * 8], void *info); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/wots.c b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/wots.c deleted file mode 100644 index 3babe45e95..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/wots.c +++ /dev/null @@ -1,259 +0,0 @@ -#include -#include - -#include "wots.h" -#include "wotsx2.h" - -#include "address.h" -#include "hash.h" -#include "hashx2.h" -#include "params.h" -#include "thashx2.h" -#include "utils.h" -#include "utilsx2.h" - -// TODO clarify address expectations, and make them more uniform. -// TODO i.e. do we expect types to be set already? -// TODO and do we expect modifications or copies? - -/** - * Computes up the chains - */ -static void gen_chains( - unsigned char *out, - const unsigned char *in, - unsigned int start[SPX_WOTS_LEN], - const unsigned int steps[SPX_WOTS_LEN], - const spx_ctx *ctx, - uint32_t addr[8]) { - uint32_t i, j, k, idx, watching; - int done; - unsigned char empty[SPX_N]; - unsigned char *bufs[4]; - uint32_t addrs[8 * 2]; - - int l; - uint16_t counts[SPX_WOTS_W] = { 0 }; - uint16_t idxs[SPX_WOTS_LEN]; - uint16_t total, newTotal; - - /* set addrs = {addr, addr} */ - for (j = 0; j < 2; j++) { - memcpy(addrs + j * 8, addr, sizeof(uint32_t) * 8); - } - - /* Initialize out with the value at position 'start'. */ - memcpy(out, in, SPX_WOTS_LEN * SPX_N); - - /* Sort the chains in reverse order by steps using counting sort. */ - for (i = 0; i < SPX_WOTS_LEN; i++) { - counts[steps[i]]++; - } - total = 0; - for (l = SPX_WOTS_W - 1; l >= 0; l--) { - newTotal = counts[l] + total; - counts[l] = total; - total = newTotal; - } - for (i = 0; i < SPX_WOTS_LEN; i++) { - idxs[counts[steps[i]]] = i; - counts[steps[i]]++; - } - - /* We got our work cut out for us: do it! */ - for (i = 0; i < SPX_WOTS_LEN; i += 2) { - for (j = 0; j < 2 && i + j < SPX_WOTS_LEN; j++) { - idx = idxs[i + j]; - set_chain_addr(addrs + j * 8, idx); - bufs[j] = out + SPX_N * idx; - } - - /* As the chains are sorted in reverse order, we know that the first - * chain is the longest and the last one is the shortest. We keep - * an eye on whether the last chain is done and then on the one before, - * et cetera. */ - watching = 1; - done = 0; - while (i + watching >= SPX_WOTS_LEN) { - bufs[watching] = &empty[0]; - watching--; - } - - for (k = 0;; k++) { - while (k == steps[idxs[i + watching]]) { - bufs[watching] = &empty[0]; - if (watching == 0) { - done = 1; - break; - } - watching--; - } - if (done) { - break; - } - for (j = 0; j < watching + 1; j++) { - set_hash_addr(addrs + j * 8, k + start[idxs[i + j]]); - } - - thashx2(bufs[0], bufs[1], - bufs[0], bufs[1], 1, ctx, addrs); - } - } -} - -/** - * base_w algorithm as described in draft. - * Interprets an array of bytes as integers in base w. - * This only works when log_w is a divisor of 8. - */ -static void base_w(unsigned int *output, const int out_len, - const unsigned char *input) { - int in = 0; - int out = 0; - unsigned char total = 0; - int bits = 0; - int consumed; - - for (consumed = 0; consumed < out_len; consumed++) { - if (bits == 0) { - total = input[in]; - in++; - bits += 8; - } - bits -= SPX_WOTS_LOGW; - output[out] = (total >> bits) & (SPX_WOTS_W - 1); - out++; - } -} - -/* Computes the WOTS+ checksum over a message (in base_w). */ -static void wots_checksum(unsigned int *csum_base_w, - const unsigned int *msg_base_w) { - unsigned int csum = 0; - unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; - unsigned int i; - - /* Compute checksum. */ - for (i = 0; i < SPX_WOTS_LEN1; i++) { - csum += SPX_WOTS_W - 1 - msg_base_w[i]; - } - - /* Convert checksum to base_w. */ - /* Make sure expected empty zero bits are the least significant bits. */ - csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); - ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); - base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); -} - -/* Takes a message and derives the matching chain lengths. */ -void chain_lengths(unsigned int *lengths, const unsigned char *msg) { - base_w(lengths, SPX_WOTS_LEN1, msg); - wots_checksum(lengths + SPX_WOTS_LEN1, lengths); -} - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const spx_ctx *ctx, uint32_t addr[8]) { - unsigned int steps[SPX_WOTS_LEN]; - unsigned int start[SPX_WOTS_LEN]; - uint32_t i; - - chain_lengths(start, msg); - - for (i = 0; i < SPX_WOTS_LEN; i++) { - steps[i] = SPX_WOTS_W - 1 - start[i]; - } - - gen_chains(pk, sig, start, steps, ctx, addr); -} - -/* - * This generates 2 sequential WOTS public keys - * It also generates the WOTS signature if leaf_info indicates - * that we're signing with one of these WOTS keys - */ -void wots_gen_leafx2(unsigned char *dest, - const spx_ctx *ctx, - uint32_t leaf_idx, void *v_info) { - struct leaf_info_x2 *info = v_info; - uint32_t *leaf_addr = info->leaf_addr; - uint32_t *pk_addr = info->pk_addr; - unsigned int i, j, k; - unsigned char pk_buffer[ 2 * SPX_WOTS_BYTES ]; - unsigned wots_offset = SPX_WOTS_BYTES; - unsigned char *buffer; - uint32_t wots_k_mask; - unsigned wots_sign_index; - - if (((leaf_idx ^ info->wots_sign_leaf) & ~1) == 0) { - /* We're traversing the leaf that's signing; generate the WOTS */ - /* signature */ - wots_k_mask = 0; - wots_sign_index = info->wots_sign_leaf & 1; /* Which of of the 2 */ - /* slots do the signatures come from */ - } else { - /* Nope, we're just generating pk's; turn off the signature logic */ - wots_k_mask = ~0; - wots_sign_index = 0; - } - - for (j = 0; j < 2; j++) { - set_keypair_addr( leaf_addr + j * 8, leaf_idx + j ); - set_keypair_addr( pk_addr + j * 8, leaf_idx + j ); - } - - for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { - uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k to */ - /* the step if we're generating a signature, ~0 if we're not */ - - /* Start with the secret seed */ - for (j = 0; j < 2; j++) { - set_chain_addr(leaf_addr + j * 8, i); - set_hash_addr(leaf_addr + j * 8, 0); - set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTSPRF); - } - prf_addrx2(buffer + 0 * wots_offset, - buffer + 1 * wots_offset, - ctx, leaf_addr); - for (j = 0; j < 2; j++) { - set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTS); - } - - /* Iterate down the WOTS chain */ - for (k = 0;; k++) { - /* Check if one of the values we have needs to be saved as a */ - /* part of the WOTS signature */ - if (k == wots_k) { - memcpy( info->wots_sig + i * SPX_N, - buffer + wots_sign_index * wots_offset, SPX_N ); - } - - /* Check if we hit the top of the chain */ - if (k == SPX_WOTS_W - 1) { - break; - } - - /* Iterate one step on all 4 chains */ - for (j = 0; j < 2; j++) { - set_hash_addr(leaf_addr + j * 8, k); - } - thashx2(buffer + 0 * wots_offset, - buffer + 1 * wots_offset, - buffer + 0 * wots_offset, - buffer + 1 * wots_offset, - 1, ctx, leaf_addr); - } - } - - /* Do the final thash to generate the public keys */ - thashx2(dest + 0 * SPX_N, - dest + 1 * SPX_N, - pk_buffer + 0 * wots_offset, - pk_buffer + 1 * wots_offset, - SPX_WOTS_LEN, ctx, pk_addr); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/wots.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/wots.h deleted file mode 100644 index 4e7692eeef..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/wots.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef SPX_WOTS_H -#define SPX_WOTS_H - -#include - -#include "context.h" -#include "params.h" - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) -void wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const spx_ctx *ctx, uint32_t addr[8]); - -/* - * Compute the chain lengths needed for a given message hash - */ -#define chain_lengths SPX_NAMESPACE(chain_lengths) -void chain_lengths(unsigned int *lengths, const unsigned char *msg); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/wotsx2.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/wotsx2.h deleted file mode 100644 index b58bb61f84..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_aarch64/wotsx2.h +++ /dev/null @@ -1,40 +0,0 @@ -#ifndef WOTSX2_H_ -#define WOTSX2_H_ - -#include "params.h" -#include - -/* - * This is here to provide an interface to the internal wots_gen_leafx2 - * routine. While this routine is not referenced in the package outside of - * wots.c, it is called from the stand-alone benchmark code to characterize - * the performance - */ -struct leaf_info_x2 { - unsigned char *wots_sig; - uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ - uint32_t *wots_steps; - uint32_t leaf_addr[2 * 8]; - uint32_t pk_addr[2 * 8]; -}; - -/* Macro to set the leaf_info to something 'benign', that is, it would */ -/* run with the same time as it does during the real signing process */ -/* Used only by the benchmark code */ -#define INITIALIZE_LEAF_INFO_X2(info, addr, step_buffer) { \ - (info).wots_sig = 0; \ - (info).wots_sign_leaf = ~0; \ - (info).wots_steps = step_buffer; \ - int i; \ - for (i=0; i<2; i++) { \ - memcpy( &(info).leaf_addr[8*i], addr, 32 ); \ - memcpy( &(info).pk_addr[8*i], addr, 32 ); \ - } \ - } - -#define wots_gen_leafx2 SPX_NAMESPACE(wots_gen_leafx2) -void wots_gen_leafx2(unsigned char *dest, - const spx_ctx *ctx, - uint32_t leaf_idx, void *v_info); - -#endif /* WOTSX2_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/LICENSE b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/LICENSE deleted file mode 100644 index 670154e353..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/LICENSE +++ /dev/null @@ -1,116 +0,0 @@ -CC0 1.0 Universal - -Statement of Purpose - -The laws of most jurisdictions throughout the world automatically confer -exclusive Copyright and Related Rights (defined below) upon the creator and -subsequent owner(s) (each and all, an "owner") of an original work of -authorship and/or a database (each, a "Work"). - -Certain owners wish to permanently relinquish those rights to a Work for the -purpose of contributing to a commons of creative, cultural and scientific -works ("Commons") that the public can reliably and without fear of later -claims of infringement build upon, modify, incorporate in other works, reuse -and redistribute as freely as possible in any form whatsoever and for any -purposes, including without limitation commercial purposes. These owners may -contribute to the Commons to promote the ideal of a free culture and the -further production of creative, cultural and scientific works, or to gain -reputation or greater distribution for their Work in part through the use and -efforts of others. - -For these and/or other purposes and motivations, and without any expectation -of additional consideration or compensation, the person associating CC0 with a -Work (the "Affirmer"), to the extent that he or she is an owner of Copyright -and Related Rights in the Work, voluntarily elects to apply CC0 to the Work -and publicly distribute the Work under its terms, with knowledge of his or her -Copyright and Related Rights in the Work and the meaning and intended legal -effect of CC0 on those rights. - -1. Copyright and Related Rights. A Work made available under CC0 may be -protected by copyright and related or neighboring rights ("Copyright and -Related Rights"). Copyright and Related Rights include, but are not limited -to, the following: - - i. the right to reproduce, adapt, distribute, perform, display, communicate, - and translate a Work; - - ii. moral rights retained by the original author(s) and/or performer(s); - - iii. publicity and privacy rights pertaining to a person's image or likeness - depicted in a Work; - - iv. rights protecting against unfair competition in regards to a Work, - subject to the limitations in paragraph 4(a), below; - - v. rights protecting the extraction, dissemination, use and reuse of data in - a Work; - - vi. database rights (such as those arising under Directive 96/9/EC of the - European Parliament and of the Council of 11 March 1996 on the legal - protection of databases, and under any national implementation thereof, - including any amended or successor version of such directive); and - - vii. other similar, equivalent or corresponding rights throughout the world - based on applicable law or treaty, and any national implementations thereof. - -2. Waiver. To the greatest extent permitted by, but not in contravention of, -applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and -unconditionally waives, abandons, and surrenders all of Affirmer's Copyright -and Related Rights and associated claims and causes of action, whether now -known or unknown (including existing as well as future claims and causes of -action), in the Work (i) in all territories worldwide, (ii) for the maximum -duration provided by applicable law or treaty (including future time -extensions), (iii) in any current or future medium and for any number of -copies, and (iv) for any purpose whatsoever, including without limitation -commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes -the Waiver for the benefit of each member of the public at large and to the -detriment of Affirmer's heirs and successors, fully intending that such Waiver -shall not be subject to revocation, rescission, cancellation, termination, or -any other legal or equitable action to disrupt the quiet enjoyment of the Work -by the public as contemplated by Affirmer's express Statement of Purpose. - -3. Public License Fallback. Should any part of the Waiver for any reason be -judged legally invalid or ineffective under applicable law, then the Waiver -shall be preserved to the maximum extent permitted taking into account -Affirmer's express Statement of Purpose. In addition, to the extent the Waiver -is so judged Affirmer hereby grants to each affected person a royalty-free, -non transferable, non sublicensable, non exclusive, irrevocable and -unconditional license to exercise Affirmer's Copyright and Related Rights in -the Work (i) in all territories worldwide, (ii) for the maximum duration -provided by applicable law or treaty (including future time extensions), (iii) -in any current or future medium and for any number of copies, and (iv) for any -purpose whatsoever, including without limitation commercial, advertising or -promotional purposes (the "License"). The License shall be deemed effective as -of the date CC0 was applied by Affirmer to the Work. Should any part of the -License for any reason be judged legally invalid or ineffective under -applicable law, such partial invalidity or ineffectiveness shall not -invalidate the remainder of the License, and in such case Affirmer hereby -affirms that he or she will not (i) exercise any of his or her remaining -Copyright and Related Rights in the Work or (ii) assert any associated claims -and causes of action with respect to the Work, in either case contrary to -Affirmer's express Statement of Purpose. - -4. Limitations and Disclaimers. - - a. No trademark or patent rights held by Affirmer are waived, abandoned, - surrendered, licensed or otherwise affected by this document. - - b. Affirmer offers the Work as-is and makes no representations or warranties - of any kind concerning the Work, express, implied, statutory or otherwise, - including without limitation warranties of title, merchantability, fitness - for a particular purpose, non infringement, or the absence of latent or - other defects, accuracy, or the present or absence of errors, whether or not - discoverable, all to the greatest extent permissible under applicable law. - - c. Affirmer disclaims responsibility for clearing rights of other persons - that may apply to the Work or any use thereof, including without limitation - any person's Copyright and Related Rights in the Work. Further, Affirmer - disclaims responsibility for obtaining any necessary consents, permissions - or other rights required for any use of the Work. - - d. Affirmer understands and acknowledges that Creative Commons is not a - party to this document and has no duty or obligation with respect to this - CC0 or use of the Work. - -For more information, please see - diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/address.c b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/address.c deleted file mode 100644 index b956e9cb29..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/address.c +++ /dev/null @@ -1,91 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "utils.h" - -/* - * Specify which level of Merkle tree (the "layer") we're working on - */ -void set_layer_addr(uint32_t addr[8], uint32_t layer) { - ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; -} - -/* - * Specify which Merkle tree within the level (the "tree address") we're working on - */ -void set_tree_addr(uint32_t addr[8], uint64_t tree) { - ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); -} - -/* - * Specify the reason we'll use this address structure for, that is, what - * hash will we compute with it. This is used so that unrelated types of - * hashes don't accidentally get the same address structure. The type will be - * one of the SPX_ADDR_TYPE constants - */ -void set_type(uint32_t addr[8], uint32_t type) { - ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; -} - -/* - * Copy the layer and tree fields of the address structure. This is used - * when we're doing multiple types of hashes within the same Merkle tree - */ -void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { - memcpy( out, in, SPX_OFFSET_TREE + 8 ); -} - -/* These functions are used for OTS addresses. */ - -/* - * Specify which Merkle leaf we're working on; that is, which OTS keypair - * we're talking about. - */ -void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { - ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; -} - -/* - * Copy the layer, tree and keypair fields of the address structure. This is - * used when we're doing multiple things within the same OTS keypair - */ -void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { - memcpy( out, in, SPX_OFFSET_TREE + 8 ); - ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; -} - -/* - * Specify which Merkle chain within the OTS we're working with - * (the chain address) - */ -void set_chain_addr(uint32_t addr[8], uint32_t chain) { - ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; -} - -/* - * Specify where in the Merkle chain we are -* (the hash address) - */ -void set_hash_addr(uint32_t addr[8], uint32_t hash) { - ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; -} - -/* These functions are used for all hash tree addresses (including FORS). */ - -/* - * Specify the height of the node in the Merkle/FORS tree we are in - * (the tree height) - */ -void set_tree_height(uint32_t addr[8], uint32_t tree_height) { - ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; -} - -/* - * Specify the distance from the left edge of the node in the Merkle/FORS tree - * (the tree index) - */ -void set_tree_index(uint32_t addr[8], uint32_t tree_index) { - u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/address.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/address.h deleted file mode 100644 index 24a84eb40c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/address.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef SPX_ADDRESS_H -#define SPX_ADDRESS_H - -#include - -#include "params.h" - -/* The hash types that are passed to set_type */ -#define SPX_ADDR_TYPE_WOTS 0 -#define SPX_ADDR_TYPE_WOTSPK 1 -#define SPX_ADDR_TYPE_HASHTREE 2 -#define SPX_ADDR_TYPE_FORSTREE 3 -#define SPX_ADDR_TYPE_FORSPK 4 -#define SPX_ADDR_TYPE_WOTSPRF 5 -#define SPX_ADDR_TYPE_FORSPRF 6 - -#define set_layer_addr SPX_NAMESPACE(set_layer_addr) -void set_layer_addr(uint32_t addr[8], uint32_t layer); - -#define set_tree_addr SPX_NAMESPACE(set_tree_addr) -void set_tree_addr(uint32_t addr[8], uint64_t tree); - -#define set_type SPX_NAMESPACE(set_type) -void set_type(uint32_t addr[8], uint32_t type); - -/* Copies the layer and tree part of one address into the other */ -#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) -void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for WOTS and FORS addresses. */ - -#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) -void set_keypair_addr(uint32_t addr[8], uint32_t keypair); - -#define set_chain_addr SPX_NAMESPACE(set_chain_addr) -void set_chain_addr(uint32_t addr[8], uint32_t chain); - -#define set_hash_addr SPX_NAMESPACE(set_hash_addr) -void set_hash_addr(uint32_t addr[8], uint32_t hash); - -#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) -void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for all hash tree addresses (including FORS). */ - -#define set_tree_height SPX_NAMESPACE(set_tree_height) -void set_tree_height(uint32_t addr[8], uint32_t tree_height); - -#define set_tree_index SPX_NAMESPACE(set_tree_index) -void set_tree_index(uint32_t addr[8], uint32_t tree_index); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/api.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/api.h deleted file mode 100644 index af0477315e..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/api.h +++ /dev/null @@ -1,77 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE192FROBUST_AVX2_API_H -#define PQCLEAN_SPHINCSSHAKE192FROBUST_AVX2_API_H - -#include -#include - -#define PQCLEAN_SPHINCSSHAKE192FROBUST_AVX2_CRYPTO_ALGNAME "SPHINCS+-shake-192f-robust" - -#define PQCLEAN_SPHINCSSHAKE192FROBUST_AVX2_CRYPTO_SECRETKEYBYTES 96 -#define PQCLEAN_SPHINCSSHAKE192FROBUST_AVX2_CRYPTO_PUBLICKEYBYTES 48 -#define PQCLEAN_SPHINCSSHAKE192FROBUST_AVX2_CRYPTO_BYTES 35664 - -#define PQCLEAN_SPHINCSSHAKE192FROBUST_AVX2_CRYPTO_SEEDBYTES 72 - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE192FROBUST_AVX2_crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE192FROBUST_AVX2_crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE192FROBUST_AVX2_crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE192FROBUST_AVX2_crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHAKE192FROBUST_AVX2_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHAKE192FROBUST_AVX2_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSSHAKE192FROBUST_AVX2_crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE192FROBUST_AVX2_crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, - const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSSHAKE192FROBUST_AVX2_crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE192FROBUST_AVX2_crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk); -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/context.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/context.h deleted file mode 100644 index 6e0a33f3b7..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/context.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef SPX_CONTEXT_H -#define SPX_CONTEXT_H - -#include - -#include "params.h" - -typedef struct { - uint8_t pub_seed[SPX_N]; - uint8_t sk_seed[SPX_N]; -} spx_ctx; - -#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) -void initialize_hash_function(spx_ctx *ctx); - -#define free_hash_function SPX_NAMESPACE(free_hash_function) -void free_hash_function(spx_ctx *ctx); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/context_shake.c b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/context_shake.c deleted file mode 100644 index 9614a103d3..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/context_shake.c +++ /dev/null @@ -1,12 +0,0 @@ -#include "context.h" - -/* For SHAKE256, there is no immediate reason to initialize at the start, - so this function is an empty operation. */ -void initialize_hash_function(spx_ctx *ctx) { - (void)ctx; /* Suppress an 'unused parameter' warning. */ -} - -// in case the hash function api is heap-based. -void free_hash_function(spx_ctx *ctx) { - (void)ctx; -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/fips202x4.c b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/fips202x4.c deleted file mode 100644 index 1e06fef186..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/fips202x4.c +++ /dev/null @@ -1,210 +0,0 @@ -#include -#include -#include - -#include "fips202.h" -#include "fips202x4.h" - -#define NROUNDS 24 -#define ROL(a, offset) (((a) << (offset)) ^ ((a) >> (64-(offset)))) - -static uint64_t load64(const unsigned char *x) { - unsigned long long r = 0, i; - - for (i = 0; i < 8; ++i) { - r |= (unsigned long long)x[i] << 8 * i; - } - return r; -} - -static void store64(uint8_t *x, uint64_t u) { - unsigned int i; - - for (i = 0; i < 8; ++i) { - x[i] = (uint8_t)u; - u >>= 8; - } -} - -/* Use implementation from the Keccak Code Package */ -extern void KeccakP1600times4_PermuteAll_24rounds(__m256i *s); -#define KeccakF1600_StatePermute4x KeccakP1600times4_PermuteAll_24rounds - -static void keccak_absorb4x(__m256i *s, - unsigned int r, - const unsigned char *m0, - const unsigned char *m1, - const unsigned char *m2, - const unsigned char *m3, - unsigned long long int mlen, - unsigned char p) { - unsigned long long i; - unsigned char t0[200]; - unsigned char t1[200]; - unsigned char t2[200]; - unsigned char t3[200]; - - unsigned long long *ss = (unsigned long long *)s; - - - while (mlen >= r) { - for (i = 0; i < r / 8; ++i) { - ss[4 * i + 0] ^= load64(m0 + 8 * i); - ss[4 * i + 1] ^= load64(m1 + 8 * i); - ss[4 * i + 2] ^= load64(m2 + 8 * i); - ss[4 * i + 3] ^= load64(m3 + 8 * i); - } - - KeccakF1600_StatePermute4x(s); - mlen -= r; - m0 += r; - m1 += r; - m2 += r; - m3 += r; - } - - for (i = 0; i < r; ++i) { - t0[i] = 0; - t1[i] = 0; - t2[i] = 0; - t3[i] = 0; - } - for (i = 0; i < mlen; ++i) { - t0[i] = m0[i]; - t1[i] = m1[i]; - t2[i] = m2[i]; - t3[i] = m3[i]; - } - - t0[i] = p; - t1[i] = p; - t2[i] = p; - t3[i] = p; - - t0[r - 1] |= 128; - t1[r - 1] |= 128; - t2[r - 1] |= 128; - t3[r - 1] |= 128; - - for (i = 0; i < r / 8; ++i) { - ss[4 * i + 0] ^= load64(t0 + 8 * i); - ss[4 * i + 1] ^= load64(t1 + 8 * i); - ss[4 * i + 2] ^= load64(t2 + 8 * i); - ss[4 * i + 3] ^= load64(t3 + 8 * i); - } -} - - -static void keccak_squeezeblocks4x(unsigned char *h0, - unsigned char *h1, - unsigned char *h2, - unsigned char *h3, - unsigned long long int nblocks, - __m256i *s, - unsigned int r) { - unsigned int i; - - unsigned long long *ss = (unsigned long long *)s; - - while (nblocks > 0) { - KeccakF1600_StatePermute4x(s); - for (i = 0; i < (r >> 3); i++) { - store64(h0 + 8 * i, ss[4 * i + 0]); - store64(h1 + 8 * i, ss[4 * i + 1]); - store64(h2 + 8 * i, ss[4 * i + 2]); - store64(h3 + 8 * i, ss[4 * i + 3]); - } - h0 += r; - h1 += r; - h2 += r; - h3 += r; - nblocks--; - } -} - - - -void shake128x4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, unsigned long long outlen, - unsigned char *in0, - unsigned char *in1, - unsigned char *in2, - unsigned char *in3, unsigned long long inlen) { - __m256i s[25]; - unsigned char t0[SHAKE128_RATE]; - unsigned char t1[SHAKE128_RATE]; - unsigned char t2[SHAKE128_RATE]; - unsigned char t3[SHAKE128_RATE]; - unsigned int i; - - /* zero state */ - for (i = 0; i < 25; i++) { - s[i] = _mm256_xor_si256(s[i], s[i]); - } - - /* absorb 4 message of identical length in parallel */ - keccak_absorb4x(s, SHAKE128_RATE, in0, in1, in2, in3, inlen, 0x1F); - - /* Squeeze output */ - keccak_squeezeblocks4x(out0, out1, out2, out3, outlen / SHAKE128_RATE, s, SHAKE128_RATE); - - out0 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; - out1 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; - out2 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; - out3 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; - - if (outlen % SHAKE128_RATE) { - keccak_squeezeblocks4x(t0, t1, t2, t3, 1, s, SHAKE128_RATE); - for (i = 0; i < outlen % SHAKE128_RATE; i++) { - out0[i] = t0[i]; - out1[i] = t1[i]; - out2[i] = t2[i]; - out3[i] = t3[i]; - } - } -} - - -void shake256x4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, unsigned long long outlen, - unsigned char *in0, - unsigned char *in1, - unsigned char *in2, - unsigned char *in3, unsigned long long inlen) { - __m256i s[25]; - unsigned char t0[SHAKE256_RATE]; - unsigned char t1[SHAKE256_RATE]; - unsigned char t2[SHAKE256_RATE]; - unsigned char t3[SHAKE256_RATE]; - unsigned int i; - - /* zero state */ - for (i = 0; i < 25; i++) { - s[i] = _mm256_xor_si256(s[i], s[i]); - } - - /* absorb 4 message of identical length in parallel */ - keccak_absorb4x(s, SHAKE256_RATE, in0, in1, in2, in3, inlen, 0x1F); - - /* Squeeze output */ - keccak_squeezeblocks4x(out0, out1, out2, out3, outlen / SHAKE256_RATE, s, SHAKE256_RATE); - - out0 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; - out1 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; - out2 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; - out3 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; - - if (outlen % SHAKE256_RATE) { - keccak_squeezeblocks4x(t0, t1, t2, t3, 1, s, SHAKE256_RATE); - for (i = 0; i < outlen % SHAKE256_RATE; i++) { - out0[i] = t0[i]; - out1[i] = t1[i]; - out2[i] = t2[i]; - out3[i] = t3[i]; - } - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/fips202x4.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/fips202x4.h deleted file mode 100644 index 2b93c9cd0d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/fips202x4.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef SPX_FIPS202X4_H -#define SPX_FIPS202X4_H - -#include - -#include "params.h" - -#define shake128x4 SPX_NAMESPACE(shake128x4) -void shake128x4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, unsigned long long outlen, - unsigned char *in0, - unsigned char *in1, - unsigned char *in2, - unsigned char *in3, unsigned long long inlen); - -#define shake256x4 SPX_NAMESPACE(shake256x4) -void shake256x4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, unsigned long long outlen, - unsigned char *in0, - unsigned char *in1, - unsigned char *in2, - unsigned char *in3, unsigned long long inlen); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/fors.c b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/fors.c deleted file mode 100644 index f1b0639cfc..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/fors.c +++ /dev/null @@ -1,202 +0,0 @@ -#include -#include -#include - -#include "fors.h" - -#include "address.h" -#include "hash.h" -#include "hashx4.h" -#include "thash.h" -#include "thashx4.h" -#include "utils.h" -#include "utilsx4.h" - -static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, - uint32_t fors_leaf_addr[8]) { - prf_addr(sk, ctx, fors_leaf_addr); -} - -static void fors_gen_skx4(unsigned char *sk0, - unsigned char *sk1, - unsigned char *sk2, - unsigned char *sk3, const spx_ctx *ctx, - uint32_t fors_leaf_addrx4[4 * 8]) { - prf_addrx4(sk0, sk1, sk2, sk3, - ctx, fors_leaf_addrx4); -} - -static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, - const spx_ctx *ctx, - uint32_t fors_leaf_addr[8]) { - thash(leaf, sk, 1, ctx, fors_leaf_addr); -} - -static void fors_sk_to_leafx4(unsigned char *leaf0, - unsigned char *leaf1, - unsigned char *leaf2, - unsigned char *leaf3, - const unsigned char *sk0, - const unsigned char *sk1, - const unsigned char *sk2, - const unsigned char *sk3, - const spx_ctx *ctx, - uint32_t fors_leaf_addrx4[4 * 8]) { - thashx4(leaf0, leaf1, leaf2, leaf3, - sk0, sk1, sk2, sk3, - 1, ctx, fors_leaf_addrx4); -} - -struct fors_gen_leaf_info { - uint32_t leaf_addrx[4 * 8]; -}; - -static void fors_gen_leafx4(unsigned char *leaf, - const spx_ctx *ctx, - uint32_t addr_idx, void *info) { - struct fors_gen_leaf_info *fors_info = info; - uint32_t *fors_leaf_addrx4 = fors_info->leaf_addrx; - unsigned int j; - - /* Only set the parts that the caller doesn't set */ - for (j = 0; j < 4; j++) { - set_tree_index(fors_leaf_addrx4 + j * 8, addr_idx + j); - set_type(fors_leaf_addrx4 + j * 8, SPX_ADDR_TYPE_FORSPRF); - } - - fors_gen_skx4(leaf + 0 * SPX_N, - leaf + 1 * SPX_N, - leaf + 2 * SPX_N, - leaf + 3 * SPX_N, - ctx, fors_leaf_addrx4); - - for (j = 0; j < 4; j++) { - set_type(fors_leaf_addrx4 + j * 8, SPX_ADDR_TYPE_FORSTREE); - } - - fors_sk_to_leafx4(leaf + 0 * SPX_N, - leaf + 1 * SPX_N, - leaf + 2 * SPX_N, - leaf + 3 * SPX_N, - leaf + 0 * SPX_N, - leaf + 1 * SPX_N, - leaf + 2 * SPX_N, - leaf + 3 * SPX_N, - ctx, fors_leaf_addrx4); -} - -/** - * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - * Assumes indices has space for SPX_FORS_TREES integers. - */ -static void message_to_indices(uint32_t *indices, const unsigned char *m) { - unsigned int i, j; - unsigned int offset = 0; - - for (i = 0; i < SPX_FORS_TREES; i++) { - indices[i] = 0; - for (j = 0; j < SPX_FORS_HEIGHT; j++) { - indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); - offset++; - } - } -} - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -void fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]) { - uint32_t indices[SPX_FORS_TREES]; - unsigned char roots[SPX_FORS_TREES * SPX_N]; - uint32_t fors_tree_addr[4 * 8] = {0}; - struct fors_gen_leaf_info fors_info = {0}; - uint32_t *fors_leaf_addr = fors_info.leaf_addrx; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - for (i = 0; i < 4; i++) { - copy_keypair_addr(fors_tree_addr + 8 * i, fors_addr); - set_type(fors_tree_addr + 8 * i, SPX_ADDR_TYPE_FORSTREE); - copy_keypair_addr(fors_leaf_addr + 8 * i, fors_addr); - } - copy_keypair_addr(fors_pk_addr, fors_addr); - set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < SPX_FORS_TREES; i++) { - idx_offset = i * (1 << SPX_FORS_HEIGHT); - - set_tree_height(fors_tree_addr, 0); - set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Include the secret key part that produces the selected leaf node. */ - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); - fors_gen_sk(sig, ctx, fors_tree_addr); - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); - sig += SPX_N; - - /* Compute the authentication path for this leaf node. */ - treehashx4(roots + i * SPX_N, sig, ctx, - indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx4, - fors_tree_addr, &fors_info); - - sig += SPX_N * SPX_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); -} - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -void fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]) { - uint32_t indices[SPX_FORS_TREES]; - unsigned char roots[SPX_FORS_TREES * SPX_N]; - unsigned char leaf[SPX_N]; - uint32_t fors_tree_addr[8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - copy_keypair_addr(fors_tree_addr, fors_addr); - copy_keypair_addr(fors_pk_addr, fors_addr); - - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); - set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < SPX_FORS_TREES; i++) { - idx_offset = i * (1 << SPX_FORS_HEIGHT); - - set_tree_height(fors_tree_addr, 0); - set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Derive the leaf from the included secret key part. */ - fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); - sig += SPX_N; - - /* Derive the corresponding root node of this tree. */ - compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, - sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); - sig += SPX_N * SPX_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/fors.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/fors.h deleted file mode 100644 index 509140a178..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/fors.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef SPX_FORS_H -#define SPX_FORS_H - -#include - -#include "context.h" -#include "params.h" - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -#define fors_sign SPX_NAMESPACE(fors_sign) -void fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]); - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) -void fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/hash.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/hash.h deleted file mode 100644 index f7c87d4c3c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/hash.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef SPX_HASH_H -#define SPX_HASH_H - -#include -#include - -#include "context.h" -#include "params.h" - -#define prf_addr SPX_NAMESPACE(prf_addr) -void prf_addr(unsigned char *out, const spx_ctx *ctx, - const uint32_t addr[8]); - -#define gen_message_random SPX_NAMESPACE(gen_message_random) -void gen_message_random(unsigned char *R, const unsigned char *sk_prf, - const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx); - -#define hash_message SPX_NAMESPACE(hash_message) -void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx); - - - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/hash_shake.c b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/hash_shake.c deleted file mode 100644 index ff5e7ec918..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/hash_shake.c +++ /dev/null @@ -1,83 +0,0 @@ -#include -#include - -#include "hash.h" - -#include "address.h" -#include "fips202.h" -#include "params.h" -#include "utils.h" - -/* - * Computes PRF(pk_seed, sk_seed, addr) - */ -void prf_addr(unsigned char *out, const spx_ctx *ctx, - const uint32_t addr[8]) { - unsigned char buf[2 * SPX_N + SPX_ADDR_BYTES]; - - memcpy(buf, ctx->pub_seed, SPX_N); - memcpy(buf + SPX_N, addr, SPX_ADDR_BYTES); - memcpy(buf + SPX_N + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); - - shake256(out, SPX_N, buf, 2 * SPX_N + SPX_ADDR_BYTES); -} - -/** - * Computes the message-dependent randomness R, using a secret seed and an - * optional randomization value as well as the message. - */ -void gen_message_random(unsigned char *R, const unsigned char *sk_prf, - const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx) { - (void)ctx; - shake256incctx s_inc; - - shake256_inc_init(&s_inc); - shake256_inc_absorb(&s_inc, sk_prf, SPX_N); - shake256_inc_absorb(&s_inc, optrand, SPX_N); - shake256_inc_absorb(&s_inc, m, mlen); - shake256_inc_finalize(&s_inc); - shake256_inc_squeeze(R, SPX_N, &s_inc); - shake256_inc_ctx_release(&s_inc); -} - -/** - * Computes the message hash using R, the public key, and the message. - * Outputs the message digest and the index of the leaf. The index is split in - * the tree index and the leaf index, for convenient copying to an address. - */ -void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx) { - (void)ctx; -#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) -#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) -#define SPX_LEAF_BITS SPX_TREE_HEIGHT -#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) -#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) - - unsigned char buf[SPX_DGST_BYTES]; - unsigned char *bufp = buf; - shake256incctx s_inc; - - shake256_inc_init(&s_inc); - shake256_inc_absorb(&s_inc, R, SPX_N); - shake256_inc_absorb(&s_inc, pk, SPX_PK_BYTES); - shake256_inc_absorb(&s_inc, m, mlen); - shake256_inc_finalize(&s_inc); - shake256_inc_squeeze(buf, SPX_DGST_BYTES, &s_inc); - shake256_inc_ctx_release(&s_inc); - - memcpy(digest, bufp, SPX_FORS_MSG_BYTES); - bufp += SPX_FORS_MSG_BYTES; - - - *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); - *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); - bufp += SPX_TREE_BYTES; - - *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); - *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/hash_shakex4.c b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/hash_shakex4.c deleted file mode 100644 index bbd22eb117..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/hash_shakex4.c +++ /dev/null @@ -1,64 +0,0 @@ -#include -#include - -#include "hashx4.h" - -#include "address.h" -#include "fips202x4.h" -#include "params.h" - -extern void KeccakP1600times4_PermuteAll_24rounds(__m256i *s); - -/* - * 4-way parallel version of prf_addr; takes 4x as much input and output - */ -void prf_addrx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const spx_ctx *ctx, - const uint32_t addrx4[4 * 8]) { - /* As we write and read only a few quadwords, it is more efficient to - * build and extract from the fourway SHAKE256 state by hand. */ - __m256i state[25]; - - for (int i = 0; i < SPX_N / 8; i++) { - state[i] = _mm256_set1_epi64x(((int64_t *)ctx->pub_seed)[i]); - } - for (int i = 0; i < 4; i++) { - state[SPX_N / 8 + i] = _mm256_set_epi32( - (int)addrx4[3 * 8 + 1 + 2 * i], - (int)addrx4[3 * 8 + 2 * i], - (int)addrx4[2 * 8 + 1 + 2 * i], - (int)addrx4[2 * 8 + 2 * i], - (int)addrx4[8 + 1 + 2 * i], - (int)addrx4[8 + 2 * i], - (int)addrx4[1 + 2 * i], - (int)addrx4[2 * i] - ); - } - for (int i = 0; i < SPX_N / 8; i++) { - state[SPX_N / 8 + i + 4] = _mm256_set1_epi64x(((int64_t *)ctx->sk_seed)[i]); - } - - /* SHAKE domain separator and padding. */ - state[SPX_N / 4 + 4] = _mm256_set1_epi64x(0x1f); - for (int i = SPX_N / 4 + 5; i < 16; i++) { - state[i] = _mm256_set1_epi64x(0); - } - // shift unsigned and then cast to avoid UB - state[16] = _mm256_set1_epi64x((long long)(0x80ULL << 56)); - - for (int i = 17; i < 25; i++) { - state[i] = _mm256_set1_epi64x(0); - } - - KeccakP1600times4_PermuteAll_24rounds(&state[0]); - - for (int i = 0; i < SPX_N / 8; i++) { - ((int64_t *)out0)[i] = _mm256_extract_epi64(state[i], 0); - ((int64_t *)out1)[i] = _mm256_extract_epi64(state[i], 1); - ((int64_t *)out2)[i] = _mm256_extract_epi64(state[i], 2); - ((int64_t *)out3)[i] = _mm256_extract_epi64(state[i], 3); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/hashx4.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/hashx4.h deleted file mode 100644 index 3751a0ebd0..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/hashx4.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef SPX_HASHX4_H -#define SPX_HASHX4_H - -#include - -#include "context.h" -#include "params.h" - -#define prf_addrx4 SPX_NAMESPACE(prf_addrx4) -void prf_addrx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const spx_ctx *ctx, - const uint32_t addrx4[4 * 8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/merkle.c b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/merkle.c deleted file mode 100644 index f57811c1ac..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/merkle.c +++ /dev/null @@ -1,64 +0,0 @@ -#include -#include - -#include "merkle.h" - -#include "address.h" -#include "params.h" -#include "utils.h" -#include "utilsx4.h" -#include "wots.h" -#include "wotsx4.h" - -/* - * This generates a Merkle signature (WOTS signature followed by the Merkle - * authentication path). - */ -void merkle_sign(uint8_t *sig, unsigned char *root, - const spx_ctx *ctx, - uint32_t wots_addr[8], uint32_t tree_addr[8], - uint32_t idx_leaf) { - unsigned char *auth_path = sig + SPX_WOTS_BYTES; - uint32_t tree_addrx4[4 * 8] = { 0 }; - int j; - struct leaf_info_x4 info = { 0 }; - unsigned steps[ SPX_WOTS_LEN ]; - - info.wots_sig = sig; - chain_lengths(steps, root); - info.wots_steps = steps; - - for (j = 0; j < 4; j++) { - set_type(&tree_addrx4[8 * j], SPX_ADDR_TYPE_HASHTREE); - set_type(&info.leaf_addr[8 * j], SPX_ADDR_TYPE_WOTS); - set_type(&info.pk_addr[8 * j], SPX_ADDR_TYPE_WOTSPK); - copy_subtree_addr(&tree_addrx4[8 * j], tree_addr); - copy_subtree_addr(&info.leaf_addr[8 * j], wots_addr); - copy_subtree_addr(&info.pk_addr[8 * j], wots_addr); - } - - info.wots_sign_leaf = idx_leaf; - - treehashx4(root, auth_path, ctx, - idx_leaf, 0, - SPX_TREE_HEIGHT, - wots_gen_leafx4, - tree_addrx4, &info); -} - -/* Compute root node of the top-most subtree. */ -void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { - /* We do not need the auth path in key generation, but it simplifies the - code to have just one treehash routine that computes both root and path - in one function. */ - unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; - uint32_t top_tree_addr[8] = {0}; - uint32_t wots_addr[8] = {0}; - - set_layer_addr(top_tree_addr, SPX_D - 1); - set_layer_addr(wots_addr, SPX_D - 1); - - merkle_sign(auth_path, root, ctx, - wots_addr, top_tree_addr, - ~0U /* ~0 means "don't bother generating an auth path */ ); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/merkle.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/merkle.h deleted file mode 100644 index 769cf2e970..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/merkle.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef MERKLE_H_ -#define MERKLE_H_ - -#include - -#include "context.h" -#include "params.h" - -/* Generate a Merkle signature (WOTS signature followed by the Merkle */ -/* authentication path) */ -#define merkle_sign SPX_NAMESPACE(merkle_sign) -void merkle_sign(uint8_t *sig, unsigned char *root, - const spx_ctx *ctx, - uint32_t wots_addr[8], uint32_t tree_addr[8], - uint32_t idx_leaf); - -/* Compute the root node of the top-most subtree. */ -#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) -void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); - -#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/nistapi.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/nistapi.h deleted file mode 100644 index 3cb71afad4..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/nistapi.h +++ /dev/null @@ -1,87 +0,0 @@ -#ifndef SPX_API_H -#define SPX_API_H - -#include -#include - -#include "params.h" - -#define CRYPTO_ALGNAME "SPHINCS+" - -#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES -#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES -#define CRYPTO_BYTES SPX_BYTES -#define CRYPTO_SEEDBYTES (3*SPX_N) - -/* - * Returns the length of a secret key, in bytes - */ -#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) -size_t crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) -size_t crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) -size_t crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) -size_t crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) -int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) -int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) -int crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) -int crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -#define crypto_sign SPX_NAMESPACE(crypto_sign) -int crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) -int crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/params.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/params.h deleted file mode 100644 index e76c9ad6ad..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/params.h +++ /dev/null @@ -1,56 +0,0 @@ -#ifndef SPX_PARAMS_H -#define SPX_PARAMS_H - -#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSSHAKE192FROBUST_AVX2_##s - -/* Hash output length in bytes. */ -#define SPX_N 24 -/* Height of the hypertree. */ -#define SPX_FULL_HEIGHT 66 -/* Number of subtree layer. */ -#define SPX_D 22 -/* FORS tree dimensions. */ -#define SPX_FORS_HEIGHT 8 -#define SPX_FORS_TREES 33 -/* Winternitz parameter, */ -#define SPX_WOTS_W 16 - -/* The hash function is defined by linking a different hash.c file, as opposed - to setting a #define constant. */ - -/* For clarity */ -#define SPX_ADDR_BYTES 32 - -/* WOTS parameters. */ -#define SPX_WOTS_LOGW 4 - -#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) - -/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#define SPX_WOTS_LEN2 3 - -#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) -#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) -#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES - -/* Subtree size. */ -#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) - -//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT -// #error SPX_D should always divide SPX_FULL_HEIGHT -//#endif - -/* FORS parameters. */ -#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) -#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) -#define SPX_FORS_PK_BYTES SPX_N - -/* Resulting SPX sizes. */ -#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ - SPX_FULL_HEIGHT * SPX_N) -#define SPX_PK_BYTES (2 * SPX_N) -#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) - -#include "shake_offsets.h" - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/shake_offsets.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/shake_offsets.h deleted file mode 100644 index 6b28d95d91..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/shake_offsets.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef SHAKE_OFFSETS_H_ -#define SHAKE_OFFSETS_H_ - -/* - * Offsets of various fields in the address structure when we use SHAKE as - * the Sphincs+ hash function - */ - -#define SPX_OFFSET_LAYER 3 /* The byte used to specify the Merkle tree layer */ -#define SPX_OFFSET_TREE 8 /* The start of the 8 byte field used to specify the tree */ -#define SPX_OFFSET_TYPE 19 /* The byte used to specify the hash type (reason) */ -#define SPX_OFFSET_KP_ADDR2 22 /* The high byte used to specify the key pair (which one-time signature) */ -#define SPX_OFFSET_KP_ADDR1 23 /* The low byte used to specify the key pair */ -#define SPX_OFFSET_CHAIN_ADDR 27 /* The byte used to specify the chain address (which Winternitz chain) */ -#define SPX_OFFSET_HASH_ADDR 31 /* The byte used to specify the hash address (where in the Winternitz chain) */ -#define SPX_OFFSET_TREE_HGT 27 /* The byte used to specify the height of this node in the FORS or Merkle tree */ -#define SPX_OFFSET_TREE_INDEX 28 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ - -#define SPX_SHAKE 1 - -#endif /* SHAKE_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/sign.c b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/sign.c deleted file mode 100644 index 9d0c7d1b22..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/sign.c +++ /dev/null @@ -1,286 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "context.h" -#include "fors.h" -#include "hash.h" -#include "merkle.h" -#include "nistapi.h" -#include "params.h" -#include "randombytes.h" -#include "thash.h" -#include "utils.h" -#include "wots.h" - -/* - * Returns the length of a secret key, in bytes - */ -size_t crypto_sign_secretkeybytes(void) { - return CRYPTO_SECRETKEYBYTES; -} - -/* - * Returns the length of a public key, in bytes - */ -size_t crypto_sign_publickeybytes(void) { - return CRYPTO_PUBLICKEYBYTES; -} - -/* - * Returns the length of a signature, in bytes - */ -size_t crypto_sign_bytes(void) { - return CRYPTO_BYTES; -} - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t crypto_sign_seedbytes(void) { - return CRYPTO_SEEDBYTES; -} - -/* - * Generates an SPX key pair given a seed of length - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed) { - spx_ctx ctx; - - /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ - memcpy(sk, seed, CRYPTO_SEEDBYTES); - - memcpy(pk, sk + 2 * SPX_N, SPX_N); - - memcpy(ctx.pub_seed, pk, SPX_N); - memcpy(ctx.sk_seed, sk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - /* Compute root node of the top-most subtree. */ - merkle_gen_root(sk + 3 * SPX_N, &ctx); - - // cleanup - free_hash_function(&ctx); - - memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); - - return 0; -} - -/* - * Generates an SPX key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { - uint8_t seed[CRYPTO_SEEDBYTES]; - randombytes(seed, CRYPTO_SEEDBYTES); - crypto_sign_seed_keypair(pk, sk, seed); - - return 0; -} - -/** - * Returns an array containing a detached signature. - */ -int crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - spx_ctx ctx; - - const uint8_t *sk_prf = sk + SPX_N; - const uint8_t *pk = sk + 2 * SPX_N; - - uint8_t optrand[SPX_N]; - uint8_t mhash[SPX_FORS_MSG_BYTES]; - uint8_t root[SPX_N]; - uint32_t i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - - memcpy(ctx.sk_seed, sk, SPX_N); - memcpy(ctx.pub_seed, pk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - set_type(wots_addr, SPX_ADDR_TYPE_WOTS); - set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); - - /* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ - randombytes(optrand, SPX_N); - /* Compute the digest randomization value. */ - gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); - - /* Derive the message digest and leaf index from R, PK and M. */ - hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); - sig += SPX_N; - - set_tree_addr(wots_addr, tree); - set_keypair_addr(wots_addr, idx_leaf); - - /* Sign the message hash using FORS. */ - fors_sign(sig, root, mhash, &ctx, wots_addr); - sig += SPX_FORS_BYTES; - - for (i = 0; i < SPX_D; i++) { - set_layer_addr(tree_addr, i); - set_tree_addr(tree_addr, tree); - - copy_subtree_addr(wots_addr, tree_addr); - set_keypair_addr(wots_addr, idx_leaf); - - merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); - sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); - tree = tree >> SPX_TREE_HEIGHT; - } - - free_hash_function(&ctx); - - *siglen = SPX_BYTES; - - return 0; -} - -/** - * Verifies a detached signature and message under a given public key. - */ -int crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk) { - spx_ctx ctx; - const uint8_t *pub_root = pk + SPX_N; - uint8_t mhash[SPX_FORS_MSG_BYTES]; - uint8_t wots_pk[SPX_WOTS_BYTES]; - uint8_t root[SPX_N]; - uint8_t leaf[SPX_N]; - unsigned int i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - if (siglen != SPX_BYTES) { - return -1; - } - - memcpy(ctx.pub_seed, pk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - set_type(wots_addr, SPX_ADDR_TYPE_WOTS); - set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); - set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); - - /* Derive the message digest and leaf index from R || PK || M. */ - /* The additional SPX_N is a result of the hash domain separator. */ - hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); - sig += SPX_N; - - /* Layer correctly defaults to 0, so no need to set_layer_addr */ - set_tree_addr(wots_addr, tree); - set_keypair_addr(wots_addr, idx_leaf); - - fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); - sig += SPX_FORS_BYTES; - - /* For each subtree.. */ - for (i = 0; i < SPX_D; i++) { - set_layer_addr(tree_addr, i); - set_tree_addr(tree_addr, tree); - - copy_subtree_addr(wots_addr, tree_addr); - set_keypair_addr(wots_addr, idx_leaf); - - copy_keypair_addr(wots_pk_addr, wots_addr); - - /* The WOTS public key is only correct if the signature was correct. */ - /* Initially, root is the FORS pk, but on subsequent iterations it is - the root of the subtree below the currently processed subtree. */ - wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); - sig += SPX_WOTS_BYTES; - - /* Compute the leaf node using the WOTS public key. */ - thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); - - /* Compute the root node of this subtree. */ - compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, - &ctx, tree_addr); - sig += SPX_TREE_HEIGHT * SPX_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); - tree = tree >> SPX_TREE_HEIGHT; - } - - // cleanup - free_hash_function(&ctx); - - /* Check if the root node equals the root node in the public key. */ - if (memcmp(root, pub_root, SPX_N) != 0) { - return -1; - } - - return 0; -} - - -/** - * Returns an array containing the signature followed by the message. - */ -int crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk) { - size_t siglen; - - crypto_sign_signature(sm, &siglen, m, mlen, sk); - - memmove(sm + SPX_BYTES, m, mlen); - *smlen = siglen + mlen; - - return 0; -} - -/** - * Verifies a given signature-message pair under a given public key. - */ -int crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk) { - /* The API caller does not necessarily know what size a signature should be - but SPHINCS+ signatures are always exactly SPX_BYTES. */ - if (smlen < SPX_BYTES) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - *mlen = smlen - SPX_BYTES; - - if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - /* If verification was successful, move the message to the right place. */ - memmove(m, sm + SPX_BYTES, *mlen); - - return 0; -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/thash.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/thash.h deleted file mode 100644 index 8687ccfb4d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/thash.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef SPX_THASH_H -#define SPX_THASH_H - -#include "context.h" -#include "params.h" - -#include - -#define thash SPX_NAMESPACE(thash) -void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/thash_shake_robust.c b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/thash_shake_robust.c deleted file mode 100644 index 696d53c5cc..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/thash_shake_robust.c +++ /dev/null @@ -1,31 +0,0 @@ -#include -#include - -#include "thash.h" - -#include "address.h" -#include "params.h" -#include "utils.h" - -#include "fips202.h" - -/** - * Takes an array of inblocks concatenated arrays of SPX_N bytes. - */ -void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]) { - PQCLEAN_VLA(uint8_t, buf, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); - PQCLEAN_VLA(uint8_t, bitmask, inblocks * SPX_N); - unsigned int i; - - memcpy(buf, ctx->pub_seed, SPX_N); - memcpy(buf + SPX_N, addr, SPX_ADDR_BYTES); - - shake256(bitmask, inblocks * SPX_N, buf, SPX_N + SPX_ADDR_BYTES); - - for (i = 0; i < inblocks * SPX_N; i++) { - buf[SPX_N + SPX_ADDR_BYTES + i] = in[i] ^ bitmask[i]; - } - - shake256(out, SPX_N, buf, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/thash_shake_robustx4.c b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/thash_shake_robustx4.c deleted file mode 100644 index ce2946b745..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/thash_shake_robustx4.c +++ /dev/null @@ -1,131 +0,0 @@ -#include -#include - -#include "thashx4.h" - -#include "address.h" -#include "params.h" -#include "utils.h" - -#include "fips202x4.h" - -extern void KeccakP1600times4_PermuteAll_24rounds(__m256i *s); - -/** - * 4-way parallel version of thash; takes 4x as much input and output - */ -void thashx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addrx4[4 * 8]) { - if (inblocks == 1 || inblocks == 2) { - /* As we write and read only a few quadwords, it is more efficient to - * build and extract from the fourway SHAKE256 state by hand. */ - __m256i state[25]; - for (int i = 0; i < SPX_N / 8; i++) { - state[i] = _mm256_set1_epi64x(((int64_t *)ctx->pub_seed)[i]); - } - for (int i = 0; i < 4; i++) { - state[SPX_N / 8 + i] = _mm256_set_epi32( - (int)addrx4[3 * 8 + 1 + 2 * i], - (int)addrx4[3 * 8 + 2 * i], - (int)addrx4[2 * 8 + 1 + 2 * i], - (int)addrx4[2 * 8 + 2 * i], - (int)addrx4[8 + 1 + 2 * i], - (int)addrx4[8 + 2 * i], - (int)addrx4[1 + 2 * i], - (int)addrx4[2 * i] - ); - } - - /* SHAKE domain separator and padding */ - state[SPX_N / 8 + 4] = _mm256_set1_epi64x(0x1f); - for (int i = SPX_N / 8 + 5; i < 16; i++) { - state[i] = _mm256_set1_epi64x(0); - } - state[16] = _mm256_set1_epi64x((long long)(0x80ULL << 56)); - - for (int i = 17; i < 25; i++) { - state[i] = _mm256_set1_epi64x(0); - } - - /* We will permutate state2 with f1600x4 to compute the bitmask, - * but first we'll copy it to state2 which will be used to compute - * the final output, as its input is alsmost identical. */ - __m256i state2[25]; - memcpy(state2, state, 800); - - KeccakP1600times4_PermuteAll_24rounds(&state[0]); - - /* By copying from state, state2 already contains the pub_seed - * and addres. We just need to copy in the input blocks xorred with - * the bitmask we just computed. */ - for (unsigned int i = 0; i < (SPX_N / 8) * inblocks; i++) { - state2[SPX_N / 8 + 4 + i] = _mm256_xor_si256( - state[i], - _mm256_set_epi64x( - ((int64_t *)in3)[i], - ((int64_t *)in2)[i], - ((int64_t *)in1)[i], - ((int64_t *)in0)[i] - ) - ); - } - - /* Domain separator and start of padding. Note that the quadwords - * around are already zeroed for state from which we copied. - * We do a XOR instead of a set as this might be the 16th quadword - * when N=32 and inblocks=2, which already contains the end - * of the padding. */ - state2[(SPX_N / 8) * (1 + inblocks) + 4] = _mm256_xor_si256( - state2[(SPX_N / 8) * (1 + inblocks) + 4], - _mm256_set1_epi64x(0x1f) - ); - - KeccakP1600times4_PermuteAll_24rounds(&state2[0]); - - for (int i = 0; i < SPX_N / 8; i++) { - ((int64_t *)out0)[i] = _mm256_extract_epi64(state2[i], 0); - ((int64_t *)out1)[i] = _mm256_extract_epi64(state2[i], 1); - ((int64_t *)out2)[i] = _mm256_extract_epi64(state2[i], 2); - ((int64_t *)out3)[i] = _mm256_extract_epi64(state2[i], 3); - } - } else { - PQCLEAN_VLA(unsigned char, buf0, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); - PQCLEAN_VLA(unsigned char, buf1, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); - PQCLEAN_VLA(unsigned char, buf2, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); - PQCLEAN_VLA(unsigned char, buf3, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); - PQCLEAN_VLA(unsigned char, bitmask0, inblocks * SPX_N); - PQCLEAN_VLA(unsigned char, bitmask1, inblocks * SPX_N); - PQCLEAN_VLA(unsigned char, bitmask2, inblocks * SPX_N); - PQCLEAN_VLA(unsigned char, bitmask3, inblocks * SPX_N); - unsigned int i; - - memcpy(buf0, ctx->pub_seed, SPX_N); - memcpy(buf1, ctx->pub_seed, SPX_N); - memcpy(buf2, ctx->pub_seed, SPX_N); - memcpy(buf3, ctx->pub_seed, SPX_N); - memcpy(buf0 + SPX_N, addrx4 + 0 * 8, SPX_ADDR_BYTES); - memcpy(buf1 + SPX_N, addrx4 + 1 * 8, SPX_ADDR_BYTES); - memcpy(buf2 + SPX_N, addrx4 + 2 * 8, SPX_ADDR_BYTES); - memcpy(buf3 + SPX_N, addrx4 + 3 * 8, SPX_ADDR_BYTES); - - shake256x4(bitmask0, bitmask1, bitmask2, bitmask3, inblocks * SPX_N, - buf0, buf1, buf2, buf3, SPX_N + SPX_ADDR_BYTES); - - for (i = 0; i < inblocks * SPX_N; i++) { - buf0[SPX_N + SPX_ADDR_BYTES + i] = in0[i] ^ bitmask0[i]; - buf1[SPX_N + SPX_ADDR_BYTES + i] = in1[i] ^ bitmask1[i]; - buf2[SPX_N + SPX_ADDR_BYTES + i] = in2[i] ^ bitmask2[i]; - buf3[SPX_N + SPX_ADDR_BYTES + i] = in3[i] ^ bitmask3[i]; - } - - shake256x4(out0, out1, out2, out3, SPX_N, - buf0, buf1, buf2, buf3, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/thashx4.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/thashx4.h deleted file mode 100644 index 64798a3727..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/thashx4.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef SPX_THASHX4_H -#define SPX_THASHX4_H - -#include - -#include "context.h" -#include "params.h" - -#define thashx4 SPX_NAMESPACE(thashx4) -void thashx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addrx4[4 * 8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/utils.c b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/utils.c deleted file mode 100644 index 177b541fb9..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/utils.c +++ /dev/null @@ -1,148 +0,0 @@ -#include - -#include "utils.h" - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "thash.h" - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void ull_to_bytes(unsigned char *out, unsigned int outlen, - unsigned long long in) { - int i; - - /* Iterate over out in decreasing order, for big-endianness. */ - for (i = (signed int)outlen - 1; i >= 0; i--) { - out[i] = in & 0xff; - in = in >> 8; - } -} - -void u32_to_bytes(unsigned char *out, uint32_t in) { - out[0] = (unsigned char)(in >> 24); - out[1] = (unsigned char)(in >> 16); - out[2] = (unsigned char)(in >> 8); - out[3] = (unsigned char)in; -} - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { - unsigned long long retval = 0; - unsigned int i; - - for (i = 0; i < inlen; i++) { - retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); - } - return retval; -} - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void compute_root(unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const spx_ctx *ctx, uint32_t addr[8]) { - uint32_t i; - unsigned char buffer[2 * SPX_N]; - - /* If leaf_idx is odd (last bit = 1), current path element is a right child - and auth_path has to go left. Otherwise it is the other way around. */ - if (leaf_idx & 1) { - memcpy(buffer + SPX_N, leaf, SPX_N); - memcpy(buffer, auth_path, SPX_N); - } else { - memcpy(buffer, leaf, SPX_N); - memcpy(buffer + SPX_N, auth_path, SPX_N); - } - auth_path += SPX_N; - - for (i = 0; i < tree_height - 1; i++) { - leaf_idx >>= 1; - idx_offset >>= 1; - /* Set the address of the node we're creating. */ - set_tree_height(addr, i + 1); - set_tree_index(addr, leaf_idx + idx_offset); - - /* Pick the right or left neighbor, depending on parity of the node. */ - if (leaf_idx & 1) { - thash(buffer + SPX_N, buffer, 2, ctx, addr); - memcpy(buffer, auth_path, SPX_N); - } else { - thash(buffer, buffer, 2, ctx, addr); - memcpy(buffer + SPX_N, auth_path, SPX_N); - } - auth_path += SPX_N; - } - - /* The last iteration is exceptional; we do not copy an auth_path node. */ - leaf_idx >>= 1; - idx_offset >>= 1; - set_tree_height(addr, tree_height); - set_tree_index(addr, leaf_idx + idx_offset); - thash(root, buffer, 2, ctx, addr); -} - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const spx_ctx * /* ctx */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), - uint32_t tree_addr[8]) { - PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); - PQCLEAN_VLA(unsigned int, heights, tree_height + 1); - unsigned int offset = 0; - uint32_t idx; - uint32_t tree_idx; - - for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { - /* Add the next leaf node to the stack. */ - gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); - offset++; - heights[offset - 1] = 0; - - /* If this is a node we need for the auth path.. */ - if ((leaf_idx ^ 0x1) == idx) { - memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); - } - - /* While the top-most nodes are of equal height.. */ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { - /* Compute index of the new node, in the next layer. */ - tree_idx = (idx >> (heights[offset - 1] + 1)); - - /* Set the address of the node we're creating. */ - set_tree_height(tree_addr, heights[offset - 1] + 1); - set_tree_index(tree_addr, - tree_idx + (idx_offset >> (heights[offset - 1] + 1))); - /* Hash the top-most nodes from the stack together. */ - thash(stack + (offset - 2)*SPX_N, - stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); - offset--; - /* Note that the top-most node is now one layer higher. */ - heights[offset - 1]++; - - /* If this is a node we need for the auth path.. */ - if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_path + heights[offset - 1]*SPX_N, - stack + (offset - 1)*SPX_N, SPX_N); - } - } - } - memcpy(root, stack, SPX_N); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/utils.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/utils.h deleted file mode 100644 index 64f5d5a53a..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/utils.h +++ /dev/null @@ -1,58 +0,0 @@ -#ifndef SPX_UTILS_H -#define SPX_UTILS_H - -#include - -#include "compat.h" -#include "context.h" -#include "params.h" - - -/* To support MSVC use alloca() instead of VLAs. See #20. */ - - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) -void ull_to_bytes(unsigned char *out, unsigned int outlen, - unsigned long long in); -#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) -void u32_to_bytes(unsigned char *out, uint32_t in); - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) -unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -#define compute_root SPX_NAMESPACE(compute_root) -void compute_root(unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const spx_ctx *ctx, uint32_t addr[8]); - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -#define treehash SPX_NAMESPACE(treehash) -void treehash(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const spx_ctx *ctx /* ctx */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), - uint32_t tree_addr[8]); - - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/utilsx4.c b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/utilsx4.c deleted file mode 100644 index 1638677194..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/utilsx4.c +++ /dev/null @@ -1,138 +0,0 @@ -#include - -#include "utilsx4.h" - -#include "address.h" -#include "params.h" -#include "thashx4.h" -#include "utils.h" - -/* - * Generate the entire Merkle tree, computing the authentication path for leaf_idx, - * and the resulting root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) - * - * This expects tree_addrx4 to be initialized to 4 parallel addr structures for - * the Merkle tree nodes - * - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - * - * This works by using the standard Merkle tree building algorithm, except - * that each 'node' tracked is actually 4 consecutive nodes in the real tree. - * When we combine two logical nodes ABCD and WXYZ, we perform the H - * operation on adjacent real nodes, forming the parent logical node - * (AB)(CD)(WX)(YZ) - * - * When we get to the top two levels of the real tree (where there is only - * one logical node), we continue this operation two more times; the right - * most real node will by the actual root (and the other 3 nodes will be - * garbage). We follow the same thashx4 logic so that the 'extract - * authentication path components' part of the loop is still executed (and - * to simplify the code somewhat) - * - * This currently assumes tree_height >= 2; I suspect that doing an adjusting - * idx, addr_idx on the gen_leafx4 call if tree_height < 2 would fix it; since - * we don't actually use such short trees, I haven't bothered - */ -void treehashx4(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, - uint32_t tree_height, - void (*gen_leafx4)( - unsigned char * /* Where to write the leaves */, - const spx_ctx *, - uint32_t idx, void *info), - uint32_t tree_addrx4[4 * 8], - void *info) { - /* This is where we keep the intermediate nodes */ - PQCLEAN_VLA(unsigned char, stackx4, tree_height * 4 * SPX_N); - uint32_t left_adj = 0, prev_left_adj = 0; /* When we're doing the top 3 */ - /* levels, the left-most part of the tree isn't at the beginning */ - /* of current[]. These give the offset of the actual start */ - - uint32_t idx; - uint32_t max_idx = (1U << (tree_height - 2)) - 1; - for (idx = 0;; idx++) { - unsigned char current[4 * SPX_N]; /* Current logical node */ - gen_leafx4( current, ctx, 4 * idx + idx_offset, - info ); - - /* Now combine the freshly generated right node with previously */ - /* generated left ones */ - uint32_t internal_idx_offset = idx_offset; - uint32_t internal_idx = idx; - uint32_t internal_leaf = leaf_idx; - uint32_t h; /* The height we are in the Merkle tree */ - for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { - - /* Special processing if we're at the top of the tree */ - if (h >= tree_height - 2) { - if (h == tree_height) { - /* We hit the root; return it */ - memcpy( root, ¤t[3 * SPX_N], SPX_N ); - return; - } - /* The tree indexing logic is a bit off in this case */ - /* Adjust it so that the left-most node of the part of */ - /* the tree that we're processing has index 0 */ - prev_left_adj = left_adj; - left_adj = 4U - (1 << (tree_height - h - 1)); - } - - /* Check if we hit the top of the tree */ - if (h == tree_height) { - /* We hit the root; return it */ - memcpy( root, ¤t[3 * SPX_N], SPX_N ); - return; - } - - /* - * Check if one of the nodes we have is a part of the - * authentication path; if it is, write it out - */ - if ((((internal_idx << 2) ^ internal_leaf) & ~0x3U) == 0) { - memcpy( &auth_path[ h * SPX_N ], - ¤t[(((internal_leaf & 3) ^ 1) + prev_left_adj) * SPX_N], - SPX_N ); - } - - /* - * Check if we're at a left child; if so, stop going up the stack - * Exception: if we've reached the end of the tree, keep on going - * (so we combine the last 4 nodes into the one root node in two - * more iterations) - */ - if ((internal_idx & 1) == 0 && idx < max_idx) { - break; - } - - /* Ok, we're at a right node (or doing the top 3 levels) */ - /* Now combine the left and right logical nodes together */ - - /* Set the address of the node we're creating. */ - unsigned int j; - internal_idx_offset >>= 1; - for (j = 0; j < 4; j++) { - set_tree_height(tree_addrx4 + j * 8, h + 1); - set_tree_index(tree_addrx4 + j * 8, - (4 / 2) * (internal_idx & ~1U) + j - left_adj + internal_idx_offset ); - } - unsigned char *left = &stackx4[h * 4 * SPX_N]; - thashx4( ¤t[0 * SPX_N], - ¤t[1 * SPX_N], - ¤t[2 * SPX_N], - ¤t[3 * SPX_N], - &left [0 * SPX_N], - &left [2 * SPX_N], - ¤t[0 * SPX_N], - ¤t[2 * SPX_N], - 2, ctx, tree_addrx4); - } - - /* We've hit a left child; save the current for when we get the */ - /* corresponding right right */ - memcpy( &stackx4[h * 4 * SPX_N], current, 4 * SPX_N); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/utilsx4.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/utilsx4.h deleted file mode 100644 index facb874b18..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/utilsx4.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef SPX_UTILSX4_H -#define SPX_UTILSX4_H - -#include - -#include "context.h" -#include "params.h" - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - * - * This implementation uses AVX to compute internal nodes 4 at a time (in - * parallel) - */ -#define treehashx4 SPX_NAMESPACE(treehashx4) -void treehashx4(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leafx4)( - unsigned char * /* Where to write the leaves */, - const spx_ctx * /* ctx */, - uint32_t addr_idx, void *info), - uint32_t tree_addrx4[4 * 8], void *info); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/wots.c b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/wots.c deleted file mode 100644 index 4d5041ce05..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/wots.c +++ /dev/null @@ -1,269 +0,0 @@ -#include -#include - -#include "wots.h" - -#include "address.h" -#include "hash.h" -#include "hashx4.h" -#include "params.h" -#include "thash.h" -#include "thashx4.h" -#include "utils.h" -#include "utilsx4.h" -#include "wotsx4.h" - -// TODO clarify address expectations, and make them more uniform. -// TODO i.e. do we expect types to be set already? -// TODO and do we expect modifications or copies? - -/** - * Computes up the chains - */ -static void gen_chains( - unsigned char *out, - const unsigned char *in, - unsigned int start[SPX_WOTS_LEN], - const unsigned int steps[SPX_WOTS_LEN], - const spx_ctx *ctx, - uint32_t addr[8]) { - uint32_t i, j, k, idx, watching; - int done; - unsigned char empty[SPX_N]; - unsigned char *bufs[4]; - uint32_t addrs[8 * 4]; - - int l; - uint16_t counts[SPX_WOTS_W] = { 0 }; - uint16_t idxs[SPX_WOTS_LEN]; - uint16_t total, newTotal; - - /* set addrs = {addr, addr, addr, addr} */ - for (j = 0; j < 4; j++) { - memcpy(addrs + j * 8, addr, sizeof(uint32_t) * 8); - } - - /* Initialize out with the value at position 'start'. */ - memcpy(out, in, SPX_WOTS_LEN * SPX_N); - - /* Sort the chains in reverse order by steps using counting sort. */ - for (i = 0; i < SPX_WOTS_LEN; i++) { - counts[steps[i]]++; - } - total = 0; - for (l = SPX_WOTS_W - 1; l >= 0; l--) { - newTotal = counts[l] + total; - counts[l] = total; - total = newTotal; - } - for (i = 0; i < SPX_WOTS_LEN; i++) { - idxs[counts[steps[i]]] = (uint16_t)i; - counts[steps[i]]++; - } - - /* We got our work cut out for us: do it! */ - for (i = 0; i < SPX_WOTS_LEN; i += 4) { - for (j = 0; j < 4 && i + j < SPX_WOTS_LEN; j++) { - idx = idxs[i + j]; - set_chain_addr(addrs + j * 8, idx); - bufs[j] = out + SPX_N * idx; - } - - /* As the chains are sorted in reverse order, we know that the first - * chain is the longest and the last one is the shortest. We keep - * an eye on whether the last chain is done and then on the one before, - * et cetera. */ - watching = 3; - done = 0; - while (i + watching >= SPX_WOTS_LEN) { - bufs[watching] = &empty[0]; - watching--; - } - - for (k = 0;; k++) { - while (k == steps[idxs[i + watching]]) { - bufs[watching] = &empty[0]; - if (watching == 0) { - done = 1; - break; - } - watching--; - } - if (done) { - break; - } - for (j = 0; j < watching + 1; j++) { - set_hash_addr(addrs + j * 8, k + start[idxs[i + j]]); - } - - thashx4(bufs[0], bufs[1], bufs[2], bufs[3], - bufs[0], bufs[1], bufs[2], bufs[3], 1, ctx, addrs); - } - } -} - -/** - * base_w algorithm as described in draft. - * Interprets an array of bytes as integers in base w. - * This only works when log_w is a divisor of 8. - */ -static void base_w(unsigned int *output, const int out_len, - const unsigned char *input) { - int in = 0; - int out = 0; - unsigned char total = 0; - int bits = 0; - int consumed; - - for (consumed = 0; consumed < out_len; consumed++) { - if (bits == 0) { - total = input[in]; - in++; - bits += 8; - } - bits -= SPX_WOTS_LOGW; - output[out] = (total >> bits) & (SPX_WOTS_W - 1); - out++; - } -} - -/* Computes the WOTS+ checksum over a message (in base_w). */ -static void wots_checksum(unsigned int *csum_base_w, - const unsigned int *msg_base_w) { - unsigned int csum = 0; - unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; - unsigned int i; - - /* Compute checksum. */ - for (i = 0; i < SPX_WOTS_LEN1; i++) { - csum += SPX_WOTS_W - 1 - msg_base_w[i]; - } - - /* Convert checksum to base_w. */ - /* Make sure expected empty zero bits are the least significant bits. */ - csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); - ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); - base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); -} - -/* Takes a message and derives the matching chain lengths. */ -void chain_lengths(unsigned int *lengths, const unsigned char *msg) { - base_w(lengths, SPX_WOTS_LEN1, msg); - wots_checksum(lengths + SPX_WOTS_LEN1, lengths); -} - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const spx_ctx *ctx, uint32_t addr[8]) { - unsigned int steps[SPX_WOTS_LEN]; - unsigned int start[SPX_WOTS_LEN]; - uint32_t i; - - chain_lengths(start, msg); - - for (i = 0; i < SPX_WOTS_LEN; i++) { - steps[i] = SPX_WOTS_W - 1 - start[i]; - } - - gen_chains(pk, sig, start, steps, ctx, addr); -} - -/* - * This generates 4 sequential WOTS public keys - * It also generates the WOTS signature if leaf_info indicates - * that we're signing with one of these WOTS keys - */ -void wots_gen_leafx4(unsigned char *dest, - const spx_ctx *ctx, - uint32_t leaf_idx, void *v_info) { - struct leaf_info_x4 *info = v_info; - uint32_t *leaf_addr = info->leaf_addr; - uint32_t *pk_addr = info->pk_addr; - unsigned int i, j, k; - unsigned char pk_buffer[ 4 * SPX_WOTS_BYTES ]; - unsigned wots_offset = SPX_WOTS_BYTES; - unsigned char *buffer; - uint32_t wots_k_mask; - unsigned wots_sign_index; - - if (((leaf_idx ^ info->wots_sign_leaf) & ~3U) == 0) { - /* We're traversing the leaf that's signing; generate the WOTS */ - /* signature */ - wots_k_mask = 0; - wots_sign_index = info->wots_sign_leaf & 3; /* Which of of the 4 */ - /* 4 slots do the signatures come from */ - } else { - /* Nope, we're just generating pk's; turn off the signature logic */ - wots_k_mask = (uint32_t)~0; - wots_sign_index = 0; - } - - for (j = 0; j < 4; j++) { - set_keypair_addr( leaf_addr + j * 8, leaf_idx + j ); - set_keypair_addr( pk_addr + j * 8, leaf_idx + j ); - } - - for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { - uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k to */ - /* the step if we're generating a signature, ~0 if we're not */ - - /* Start with the secret seed */ - for (j = 0; j < 4; j++) { - set_chain_addr(leaf_addr + j * 8, i); - set_hash_addr(leaf_addr + j * 8, 0); - set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTSPRF); - } - prf_addrx4(buffer + 0 * wots_offset, - buffer + 1 * wots_offset, - buffer + 2 * wots_offset, - buffer + 3 * wots_offset, - ctx, leaf_addr); - - for (j = 0; j < 4; j++) { - set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTS); - } - - /* Iterate down the WOTS chain */ - for (k = 0;; k++) { - /* Check if one of the values we have needs to be saved as a */ - /* part of the WOTS signature */ - if (k == wots_k) { - memcpy( info->wots_sig + i * SPX_N, - buffer + wots_sign_index * wots_offset, SPX_N ); - } - - /* Check if we hit the top of the chain */ - if (k == SPX_WOTS_W - 1) { - break; - } - - /* Iterate one step on all 4 chains */ - for (j = 0; j < 4; j++) { - set_hash_addr(leaf_addr + j * 8, k); - } - thashx4(buffer + 0 * wots_offset, - buffer + 1 * wots_offset, - buffer + 2 * wots_offset, - buffer + 3 * wots_offset, - buffer + 0 * wots_offset, - buffer + 1 * wots_offset, - buffer + 2 * wots_offset, - buffer + 3 * wots_offset, 1, ctx, leaf_addr); - } - } - - /* Do the final thash to generate the public keys */ - thashx4(dest + 0 * SPX_N, - dest + 1 * SPX_N, - dest + 2 * SPX_N, - dest + 3 * SPX_N, - pk_buffer + 0 * wots_offset, - pk_buffer + 1 * wots_offset, - pk_buffer + 2 * wots_offset, - pk_buffer + 3 * wots_offset, SPX_WOTS_LEN, ctx, pk_addr); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/wots.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/wots.h deleted file mode 100644 index 4e7692eeef..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/wots.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef SPX_WOTS_H -#define SPX_WOTS_H - -#include - -#include "context.h" -#include "params.h" - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) -void wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const spx_ctx *ctx, uint32_t addr[8]); - -/* - * Compute the chain lengths needed for a given message hash - */ -#define chain_lengths SPX_NAMESPACE(chain_lengths) -void chain_lengths(unsigned int *lengths, const unsigned char *msg); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/wotsx4.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/wotsx4.h deleted file mode 100644 index cd634f1743..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_avx2/wotsx4.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef WOTSX4_H_ -#define WOTSX4_H_ - -#include - -#include "params.h" - -/* - * This is here to provide an interface to the internal wots_gen_leafx4 - * routine. While this routine is not referenced in the package outside of - * wots.c, it is called from the stand-alone benchmark code to characterize - * the performance - */ -struct leaf_info_x4 { - unsigned char *wots_sig; - uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ - uint32_t *wots_steps; - uint32_t leaf_addr[4 * 8]; - uint32_t pk_addr[4 * 8]; -}; - -/* Macro to set the leaf_info to something 'benign', that is, it would */ -/* run with the same time as it does during the real signing process */ -/* Used only by the benchmark code */ -#define INITIALIZE_LEAF_INFO_X4(info, addr, step_buffer) { \ - (info).wots_sig = 0; \ - (info).wots_sign_leaf = ~0; \ - (info).wots_steps = step_buffer; \ - int i; \ - for (i=0; i<4; i++) { \ - memcpy( &(info).leaf_addr[8*i], addr, 32 ); \ - memcpy( &(info).pk_addr[8*i], addr, 32 ); \ - } \ - } - -#define wots_gen_leafx4 SPX_NAMESPACE(wots_gen_leafx4) -void wots_gen_leafx4(unsigned char *dest, - const spx_ctx *ctx, - uint32_t leaf_idx, void *v_info); - -#endif /* WOTSX4_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/LICENSE b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/LICENSE deleted file mode 100644 index 670154e353..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/LICENSE +++ /dev/null @@ -1,116 +0,0 @@ -CC0 1.0 Universal - -Statement of Purpose - -The laws of most jurisdictions throughout the world automatically confer -exclusive Copyright and Related Rights (defined below) upon the creator and -subsequent owner(s) (each and all, an "owner") of an original work of -authorship and/or a database (each, a "Work"). - -Certain owners wish to permanently relinquish those rights to a Work for the -purpose of contributing to a commons of creative, cultural and scientific -works ("Commons") that the public can reliably and without fear of later -claims of infringement build upon, modify, incorporate in other works, reuse -and redistribute as freely as possible in any form whatsoever and for any -purposes, including without limitation commercial purposes. These owners may -contribute to the Commons to promote the ideal of a free culture and the -further production of creative, cultural and scientific works, or to gain -reputation or greater distribution for their Work in part through the use and -efforts of others. - -For these and/or other purposes and motivations, and without any expectation -of additional consideration or compensation, the person associating CC0 with a -Work (the "Affirmer"), to the extent that he or she is an owner of Copyright -and Related Rights in the Work, voluntarily elects to apply CC0 to the Work -and publicly distribute the Work under its terms, with knowledge of his or her -Copyright and Related Rights in the Work and the meaning and intended legal -effect of CC0 on those rights. - -1. Copyright and Related Rights. A Work made available under CC0 may be -protected by copyright and related or neighboring rights ("Copyright and -Related Rights"). Copyright and Related Rights include, but are not limited -to, the following: - - i. the right to reproduce, adapt, distribute, perform, display, communicate, - and translate a Work; - - ii. moral rights retained by the original author(s) and/or performer(s); - - iii. publicity and privacy rights pertaining to a person's image or likeness - depicted in a Work; - - iv. rights protecting against unfair competition in regards to a Work, - subject to the limitations in paragraph 4(a), below; - - v. rights protecting the extraction, dissemination, use and reuse of data in - a Work; - - vi. database rights (such as those arising under Directive 96/9/EC of the - European Parliament and of the Council of 11 March 1996 on the legal - protection of databases, and under any national implementation thereof, - including any amended or successor version of such directive); and - - vii. other similar, equivalent or corresponding rights throughout the world - based on applicable law or treaty, and any national implementations thereof. - -2. Waiver. To the greatest extent permitted by, but not in contravention of, -applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and -unconditionally waives, abandons, and surrenders all of Affirmer's Copyright -and Related Rights and associated claims and causes of action, whether now -known or unknown (including existing as well as future claims and causes of -action), in the Work (i) in all territories worldwide, (ii) for the maximum -duration provided by applicable law or treaty (including future time -extensions), (iii) in any current or future medium and for any number of -copies, and (iv) for any purpose whatsoever, including without limitation -commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes -the Waiver for the benefit of each member of the public at large and to the -detriment of Affirmer's heirs and successors, fully intending that such Waiver -shall not be subject to revocation, rescission, cancellation, termination, or -any other legal or equitable action to disrupt the quiet enjoyment of the Work -by the public as contemplated by Affirmer's express Statement of Purpose. - -3. Public License Fallback. Should any part of the Waiver for any reason be -judged legally invalid or ineffective under applicable law, then the Waiver -shall be preserved to the maximum extent permitted taking into account -Affirmer's express Statement of Purpose. In addition, to the extent the Waiver -is so judged Affirmer hereby grants to each affected person a royalty-free, -non transferable, non sublicensable, non exclusive, irrevocable and -unconditional license to exercise Affirmer's Copyright and Related Rights in -the Work (i) in all territories worldwide, (ii) for the maximum duration -provided by applicable law or treaty (including future time extensions), (iii) -in any current or future medium and for any number of copies, and (iv) for any -purpose whatsoever, including without limitation commercial, advertising or -promotional purposes (the "License"). The License shall be deemed effective as -of the date CC0 was applied by Affirmer to the Work. Should any part of the -License for any reason be judged legally invalid or ineffective under -applicable law, such partial invalidity or ineffectiveness shall not -invalidate the remainder of the License, and in such case Affirmer hereby -affirms that he or she will not (i) exercise any of his or her remaining -Copyright and Related Rights in the Work or (ii) assert any associated claims -and causes of action with respect to the Work, in either case contrary to -Affirmer's express Statement of Purpose. - -4. Limitations and Disclaimers. - - a. No trademark or patent rights held by Affirmer are waived, abandoned, - surrendered, licensed or otherwise affected by this document. - - b. Affirmer offers the Work as-is and makes no representations or warranties - of any kind concerning the Work, express, implied, statutory or otherwise, - including without limitation warranties of title, merchantability, fitness - for a particular purpose, non infringement, or the absence of latent or - other defects, accuracy, or the present or absence of errors, whether or not - discoverable, all to the greatest extent permissible under applicable law. - - c. Affirmer disclaims responsibility for clearing rights of other persons - that may apply to the Work or any use thereof, including without limitation - any person's Copyright and Related Rights in the Work. Further, Affirmer - disclaims responsibility for obtaining any necessary consents, permissions - or other rights required for any use of the Work. - - d. Affirmer understands and acknowledges that Creative Commons is not a - party to this document and has no duty or obligation with respect to this - CC0 or use of the Work. - -For more information, please see - diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/address.c b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/address.c deleted file mode 100644 index b956e9cb29..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/address.c +++ /dev/null @@ -1,91 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "utils.h" - -/* - * Specify which level of Merkle tree (the "layer") we're working on - */ -void set_layer_addr(uint32_t addr[8], uint32_t layer) { - ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; -} - -/* - * Specify which Merkle tree within the level (the "tree address") we're working on - */ -void set_tree_addr(uint32_t addr[8], uint64_t tree) { - ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); -} - -/* - * Specify the reason we'll use this address structure for, that is, what - * hash will we compute with it. This is used so that unrelated types of - * hashes don't accidentally get the same address structure. The type will be - * one of the SPX_ADDR_TYPE constants - */ -void set_type(uint32_t addr[8], uint32_t type) { - ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; -} - -/* - * Copy the layer and tree fields of the address structure. This is used - * when we're doing multiple types of hashes within the same Merkle tree - */ -void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { - memcpy( out, in, SPX_OFFSET_TREE + 8 ); -} - -/* These functions are used for OTS addresses. */ - -/* - * Specify which Merkle leaf we're working on; that is, which OTS keypair - * we're talking about. - */ -void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { - ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; -} - -/* - * Copy the layer, tree and keypair fields of the address structure. This is - * used when we're doing multiple things within the same OTS keypair - */ -void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { - memcpy( out, in, SPX_OFFSET_TREE + 8 ); - ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; -} - -/* - * Specify which Merkle chain within the OTS we're working with - * (the chain address) - */ -void set_chain_addr(uint32_t addr[8], uint32_t chain) { - ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; -} - -/* - * Specify where in the Merkle chain we are -* (the hash address) - */ -void set_hash_addr(uint32_t addr[8], uint32_t hash) { - ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; -} - -/* These functions are used for all hash tree addresses (including FORS). */ - -/* - * Specify the height of the node in the Merkle/FORS tree we are in - * (the tree height) - */ -void set_tree_height(uint32_t addr[8], uint32_t tree_height) { - ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; -} - -/* - * Specify the distance from the left edge of the node in the Merkle/FORS tree - * (the tree index) - */ -void set_tree_index(uint32_t addr[8], uint32_t tree_index) { - u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/address.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/address.h deleted file mode 100644 index 24a84eb40c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/address.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef SPX_ADDRESS_H -#define SPX_ADDRESS_H - -#include - -#include "params.h" - -/* The hash types that are passed to set_type */ -#define SPX_ADDR_TYPE_WOTS 0 -#define SPX_ADDR_TYPE_WOTSPK 1 -#define SPX_ADDR_TYPE_HASHTREE 2 -#define SPX_ADDR_TYPE_FORSTREE 3 -#define SPX_ADDR_TYPE_FORSPK 4 -#define SPX_ADDR_TYPE_WOTSPRF 5 -#define SPX_ADDR_TYPE_FORSPRF 6 - -#define set_layer_addr SPX_NAMESPACE(set_layer_addr) -void set_layer_addr(uint32_t addr[8], uint32_t layer); - -#define set_tree_addr SPX_NAMESPACE(set_tree_addr) -void set_tree_addr(uint32_t addr[8], uint64_t tree); - -#define set_type SPX_NAMESPACE(set_type) -void set_type(uint32_t addr[8], uint32_t type); - -/* Copies the layer and tree part of one address into the other */ -#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) -void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for WOTS and FORS addresses. */ - -#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) -void set_keypair_addr(uint32_t addr[8], uint32_t keypair); - -#define set_chain_addr SPX_NAMESPACE(set_chain_addr) -void set_chain_addr(uint32_t addr[8], uint32_t chain); - -#define set_hash_addr SPX_NAMESPACE(set_hash_addr) -void set_hash_addr(uint32_t addr[8], uint32_t hash); - -#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) -void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for all hash tree addresses (including FORS). */ - -#define set_tree_height SPX_NAMESPACE(set_tree_height) -void set_tree_height(uint32_t addr[8], uint32_t tree_height); - -#define set_tree_index SPX_NAMESPACE(set_tree_index) -void set_tree_index(uint32_t addr[8], uint32_t tree_index); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/api.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/api.h deleted file mode 100644 index 67614f9c03..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/api.h +++ /dev/null @@ -1,77 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE192FROBUST_CLEAN_API_H -#define PQCLEAN_SPHINCSSHAKE192FROBUST_CLEAN_API_H - -#include -#include - -#define PQCLEAN_SPHINCSSHAKE192FROBUST_CLEAN_CRYPTO_ALGNAME "SPHINCS+-shake-192f-robust" - -#define PQCLEAN_SPHINCSSHAKE192FROBUST_CLEAN_CRYPTO_SECRETKEYBYTES 96 -#define PQCLEAN_SPHINCSSHAKE192FROBUST_CLEAN_CRYPTO_PUBLICKEYBYTES 48 -#define PQCLEAN_SPHINCSSHAKE192FROBUST_CLEAN_CRYPTO_BYTES 35664 - -#define PQCLEAN_SPHINCSSHAKE192FROBUST_CLEAN_CRYPTO_SEEDBYTES 72 - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE192FROBUST_CLEAN_crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE192FROBUST_CLEAN_crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE192FROBUST_CLEAN_crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE192FROBUST_CLEAN_crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHAKE192FROBUST_CLEAN_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHAKE192FROBUST_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSSHAKE192FROBUST_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE192FROBUST_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, - const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSSHAKE192FROBUST_CLEAN_crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE192FROBUST_CLEAN_crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk); -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/context.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/context.h deleted file mode 100644 index 9f8a40ab4e..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/context.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef SPX_CONTEXT_H -#define SPX_CONTEXT_H - -#include -#include - -#include "params.h" - -typedef struct { - uint8_t pub_seed[SPX_N]; - uint8_t sk_seed[SPX_N]; - - -} spx_ctx; - -#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) -void initialize_hash_function(spx_ctx *ctx); - -#define free_hash_function SPX_NAMESPACE(free_hash_function) -void free_hash_function(spx_ctx *ctx); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/context_shake.c b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/context_shake.c deleted file mode 100644 index 9614a103d3..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/context_shake.c +++ /dev/null @@ -1,12 +0,0 @@ -#include "context.h" - -/* For SHAKE256, there is no immediate reason to initialize at the start, - so this function is an empty operation. */ -void initialize_hash_function(spx_ctx *ctx) { - (void)ctx; /* Suppress an 'unused parameter' warning. */ -} - -// in case the hash function api is heap-based. -void free_hash_function(spx_ctx *ctx) { - (void)ctx; -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/fors.c b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/fors.c deleted file mode 100644 index 96ca72e986..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/fors.c +++ /dev/null @@ -1,156 +0,0 @@ -#include -#include -#include - -#include "fors.h" - -#include "address.h" -#include "hash.h" -#include "thash.h" -#include "utils.h" -#include "utilsx1.h" - -static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, - uint32_t fors_leaf_addr[8]) { - prf_addr(sk, ctx, fors_leaf_addr); -} - -static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, - const spx_ctx *ctx, - uint32_t fors_leaf_addr[8]) { - thash(leaf, sk, 1, ctx, fors_leaf_addr); -} - -struct fors_gen_leaf_info { - uint32_t leaf_addrx[8]; -}; - -static void fors_gen_leafx1(unsigned char *leaf, - const spx_ctx *ctx, - uint32_t addr_idx, void *info) { - struct fors_gen_leaf_info *fors_info = info; - uint32_t *fors_leaf_addr = fors_info->leaf_addrx; - - /* Only set the parts that the caller doesn't set */ - set_tree_index(fors_leaf_addr, addr_idx); - set_type(fors_leaf_addr, SPX_ADDR_TYPE_FORSPRF); - fors_gen_sk(leaf, ctx, fors_leaf_addr); - - set_type(fors_leaf_addr, SPX_ADDR_TYPE_FORSTREE); - fors_sk_to_leaf(leaf, leaf, - ctx, fors_leaf_addr); -} - -/** - * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - * Assumes indices has space for SPX_FORS_TREES integers. - */ -static void message_to_indices(uint32_t *indices, const unsigned char *m) { - unsigned int i, j; - unsigned int offset = 0; - - for (i = 0; i < SPX_FORS_TREES; i++) { - indices[i] = 0; - for (j = 0; j < SPX_FORS_HEIGHT; j++) { - indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); - offset++; - } - } -} - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -void fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]) { - uint32_t indices[SPX_FORS_TREES]; - unsigned char roots[SPX_FORS_TREES * SPX_N]; - uint32_t fors_tree_addr[8] = {0}; - struct fors_gen_leaf_info fors_info = {0}; - uint32_t *fors_leaf_addr = fors_info.leaf_addrx; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - copy_keypair_addr(fors_tree_addr, fors_addr); - copy_keypair_addr(fors_leaf_addr, fors_addr); - - copy_keypair_addr(fors_pk_addr, fors_addr); - set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < SPX_FORS_TREES; i++) { - idx_offset = i * (1 << SPX_FORS_HEIGHT); - - set_tree_height(fors_tree_addr, 0); - set_tree_index(fors_tree_addr, indices[i] + idx_offset); - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); - - /* Include the secret key part that produces the selected leaf node. */ - fors_gen_sk(sig, ctx, fors_tree_addr); - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); - sig += SPX_N; - - /* Compute the authentication path for this leaf node. */ - treehashx1(roots + i * SPX_N, sig, ctx, - indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx1, - fors_tree_addr, &fors_info); - - sig += SPX_N * SPX_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); -} - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -void fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]) { - uint32_t indices[SPX_FORS_TREES]; - unsigned char roots[SPX_FORS_TREES * SPX_N]; - unsigned char leaf[SPX_N]; - uint32_t fors_tree_addr[8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - copy_keypair_addr(fors_tree_addr, fors_addr); - copy_keypair_addr(fors_pk_addr, fors_addr); - - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); - set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < SPX_FORS_TREES; i++) { - idx_offset = i * (1 << SPX_FORS_HEIGHT); - - set_tree_height(fors_tree_addr, 0); - set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Derive the leaf from the included secret key part. */ - fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); - sig += SPX_N; - - /* Derive the corresponding root node of this tree. */ - compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, - sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); - sig += SPX_N * SPX_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/fors.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/fors.h deleted file mode 100644 index 509140a178..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/fors.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef SPX_FORS_H -#define SPX_FORS_H - -#include - -#include "context.h" -#include "params.h" - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -#define fors_sign SPX_NAMESPACE(fors_sign) -void fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]); - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) -void fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/hash.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/hash.h deleted file mode 100644 index f7c87d4c3c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/hash.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef SPX_HASH_H -#define SPX_HASH_H - -#include -#include - -#include "context.h" -#include "params.h" - -#define prf_addr SPX_NAMESPACE(prf_addr) -void prf_addr(unsigned char *out, const spx_ctx *ctx, - const uint32_t addr[8]); - -#define gen_message_random SPX_NAMESPACE(gen_message_random) -void gen_message_random(unsigned char *R, const unsigned char *sk_prf, - const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx); - -#define hash_message SPX_NAMESPACE(hash_message) -void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx); - - - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/hash_shake.c b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/hash_shake.c deleted file mode 100644 index ff5e7ec918..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/hash_shake.c +++ /dev/null @@ -1,83 +0,0 @@ -#include -#include - -#include "hash.h" - -#include "address.h" -#include "fips202.h" -#include "params.h" -#include "utils.h" - -/* - * Computes PRF(pk_seed, sk_seed, addr) - */ -void prf_addr(unsigned char *out, const spx_ctx *ctx, - const uint32_t addr[8]) { - unsigned char buf[2 * SPX_N + SPX_ADDR_BYTES]; - - memcpy(buf, ctx->pub_seed, SPX_N); - memcpy(buf + SPX_N, addr, SPX_ADDR_BYTES); - memcpy(buf + SPX_N + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); - - shake256(out, SPX_N, buf, 2 * SPX_N + SPX_ADDR_BYTES); -} - -/** - * Computes the message-dependent randomness R, using a secret seed and an - * optional randomization value as well as the message. - */ -void gen_message_random(unsigned char *R, const unsigned char *sk_prf, - const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx) { - (void)ctx; - shake256incctx s_inc; - - shake256_inc_init(&s_inc); - shake256_inc_absorb(&s_inc, sk_prf, SPX_N); - shake256_inc_absorb(&s_inc, optrand, SPX_N); - shake256_inc_absorb(&s_inc, m, mlen); - shake256_inc_finalize(&s_inc); - shake256_inc_squeeze(R, SPX_N, &s_inc); - shake256_inc_ctx_release(&s_inc); -} - -/** - * Computes the message hash using R, the public key, and the message. - * Outputs the message digest and the index of the leaf. The index is split in - * the tree index and the leaf index, for convenient copying to an address. - */ -void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx) { - (void)ctx; -#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) -#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) -#define SPX_LEAF_BITS SPX_TREE_HEIGHT -#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) -#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) - - unsigned char buf[SPX_DGST_BYTES]; - unsigned char *bufp = buf; - shake256incctx s_inc; - - shake256_inc_init(&s_inc); - shake256_inc_absorb(&s_inc, R, SPX_N); - shake256_inc_absorb(&s_inc, pk, SPX_PK_BYTES); - shake256_inc_absorb(&s_inc, m, mlen); - shake256_inc_finalize(&s_inc); - shake256_inc_squeeze(buf, SPX_DGST_BYTES, &s_inc); - shake256_inc_ctx_release(&s_inc); - - memcpy(digest, bufp, SPX_FORS_MSG_BYTES); - bufp += SPX_FORS_MSG_BYTES; - - - *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); - *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); - bufp += SPX_TREE_BYTES; - - *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); - *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/merkle.c b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/merkle.c deleted file mode 100644 index 0c1479fd93..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/merkle.c +++ /dev/null @@ -1,59 +0,0 @@ -#include -#include - -#include "address.h" -#include "merkle.h" -#include "params.h" -#include "utils.h" -#include "utilsx1.h" -#include "wots.h" -#include "wotsx1.h" - -/* - * This generates a Merkle signature (WOTS signature followed by the Merkle - * authentication path). This is in this file because most of the complexity - * is involved with the WOTS signature; the Merkle authentication path logic - * is mostly hidden in treehashx4 - */ -void merkle_sign(uint8_t *sig, unsigned char *root, - const spx_ctx *ctx, - uint32_t wots_addr[8], uint32_t tree_addr[8], - uint32_t idx_leaf) { - unsigned char *auth_path = sig + SPX_WOTS_BYTES; - struct leaf_info_x1 info = { 0 }; - unsigned steps[ SPX_WOTS_LEN ]; - - info.wots_sig = sig; - chain_lengths(steps, root); - info.wots_steps = steps; - - set_type(&tree_addr[0], SPX_ADDR_TYPE_HASHTREE); - set_type(&info.pk_addr[0], SPX_ADDR_TYPE_WOTSPK); - copy_subtree_addr(&info.leaf_addr[0], wots_addr); - copy_subtree_addr(&info.pk_addr[0], wots_addr); - - info.wots_sign_leaf = idx_leaf; - - treehashx1(root, auth_path, ctx, - idx_leaf, 0, - SPX_TREE_HEIGHT, - wots_gen_leafx1, - tree_addr, &info); -} - -/* Compute root node of the top-most subtree. */ -void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { - /* We do not need the auth path in key generation, but it simplifies the - code to have just one treehash routine that computes both root and path - in one function. */ - unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; - uint32_t top_tree_addr[8] = {0}; - uint32_t wots_addr[8] = {0}; - - set_layer_addr(top_tree_addr, SPX_D - 1); - set_layer_addr(wots_addr, SPX_D - 1); - - merkle_sign(auth_path, root, ctx, - wots_addr, top_tree_addr, - (uint32_t)~0 /* ~0 means "don't bother generating an auth path */ ); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/merkle.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/merkle.h deleted file mode 100644 index 769cf2e970..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/merkle.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef MERKLE_H_ -#define MERKLE_H_ - -#include - -#include "context.h" -#include "params.h" - -/* Generate a Merkle signature (WOTS signature followed by the Merkle */ -/* authentication path) */ -#define merkle_sign SPX_NAMESPACE(merkle_sign) -void merkle_sign(uint8_t *sig, unsigned char *root, - const spx_ctx *ctx, - uint32_t wots_addr[8], uint32_t tree_addr[8], - uint32_t idx_leaf); - -/* Compute the root node of the top-most subtree. */ -#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) -void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); - -#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/nistapi.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/nistapi.h deleted file mode 100644 index 3cb71afad4..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/nistapi.h +++ /dev/null @@ -1,87 +0,0 @@ -#ifndef SPX_API_H -#define SPX_API_H - -#include -#include - -#include "params.h" - -#define CRYPTO_ALGNAME "SPHINCS+" - -#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES -#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES -#define CRYPTO_BYTES SPX_BYTES -#define CRYPTO_SEEDBYTES (3*SPX_N) - -/* - * Returns the length of a secret key, in bytes - */ -#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) -size_t crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) -size_t crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) -size_t crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) -size_t crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) -int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) -int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) -int crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) -int crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -#define crypto_sign SPX_NAMESPACE(crypto_sign) -int crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) -int crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/params.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/params.h deleted file mode 100644 index 120dc08b61..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/params.h +++ /dev/null @@ -1,56 +0,0 @@ -#ifndef SPX_PARAMS_H -#define SPX_PARAMS_H - -#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSSHAKE192FROBUST_CLEAN_##s - -/* Hash output length in bytes. */ -#define SPX_N 24 -/* Height of the hypertree. */ -#define SPX_FULL_HEIGHT 66 -/* Number of subtree layer. */ -#define SPX_D 22 -/* FORS tree dimensions. */ -#define SPX_FORS_HEIGHT 8 -#define SPX_FORS_TREES 33 -/* Winternitz parameter, */ -#define SPX_WOTS_W 16 - -/* The hash function is defined by linking a different hash.c file, as opposed - to setting a #define constant. */ - -/* For clarity */ -#define SPX_ADDR_BYTES 32 - -/* WOTS parameters. */ -#define SPX_WOTS_LOGW 4 - -#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) - -/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#define SPX_WOTS_LEN2 3 - -#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) -#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) -#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES - -/* Subtree size. */ -#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) - -//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT -// #error SPX_D should always divide SPX_FULL_HEIGHT -//#endif - -/* FORS parameters. */ -#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) -#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) -#define SPX_FORS_PK_BYTES SPX_N - -/* Resulting SPX sizes. */ -#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ - SPX_FULL_HEIGHT * SPX_N) -#define SPX_PK_BYTES (2 * SPX_N) -#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) - -#include "shake_offsets.h" - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/shake_offsets.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/shake_offsets.h deleted file mode 100644 index 6b28d95d91..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/shake_offsets.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef SHAKE_OFFSETS_H_ -#define SHAKE_OFFSETS_H_ - -/* - * Offsets of various fields in the address structure when we use SHAKE as - * the Sphincs+ hash function - */ - -#define SPX_OFFSET_LAYER 3 /* The byte used to specify the Merkle tree layer */ -#define SPX_OFFSET_TREE 8 /* The start of the 8 byte field used to specify the tree */ -#define SPX_OFFSET_TYPE 19 /* The byte used to specify the hash type (reason) */ -#define SPX_OFFSET_KP_ADDR2 22 /* The high byte used to specify the key pair (which one-time signature) */ -#define SPX_OFFSET_KP_ADDR1 23 /* The low byte used to specify the key pair */ -#define SPX_OFFSET_CHAIN_ADDR 27 /* The byte used to specify the chain address (which Winternitz chain) */ -#define SPX_OFFSET_HASH_ADDR 31 /* The byte used to specify the hash address (where in the Winternitz chain) */ -#define SPX_OFFSET_TREE_HGT 27 /* The byte used to specify the height of this node in the FORS or Merkle tree */ -#define SPX_OFFSET_TREE_INDEX 28 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ - -#define SPX_SHAKE 1 - -#endif /* SHAKE_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/sign.c b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/sign.c deleted file mode 100644 index 9d0c7d1b22..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/sign.c +++ /dev/null @@ -1,286 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "context.h" -#include "fors.h" -#include "hash.h" -#include "merkle.h" -#include "nistapi.h" -#include "params.h" -#include "randombytes.h" -#include "thash.h" -#include "utils.h" -#include "wots.h" - -/* - * Returns the length of a secret key, in bytes - */ -size_t crypto_sign_secretkeybytes(void) { - return CRYPTO_SECRETKEYBYTES; -} - -/* - * Returns the length of a public key, in bytes - */ -size_t crypto_sign_publickeybytes(void) { - return CRYPTO_PUBLICKEYBYTES; -} - -/* - * Returns the length of a signature, in bytes - */ -size_t crypto_sign_bytes(void) { - return CRYPTO_BYTES; -} - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t crypto_sign_seedbytes(void) { - return CRYPTO_SEEDBYTES; -} - -/* - * Generates an SPX key pair given a seed of length - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed) { - spx_ctx ctx; - - /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ - memcpy(sk, seed, CRYPTO_SEEDBYTES); - - memcpy(pk, sk + 2 * SPX_N, SPX_N); - - memcpy(ctx.pub_seed, pk, SPX_N); - memcpy(ctx.sk_seed, sk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - /* Compute root node of the top-most subtree. */ - merkle_gen_root(sk + 3 * SPX_N, &ctx); - - // cleanup - free_hash_function(&ctx); - - memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); - - return 0; -} - -/* - * Generates an SPX key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { - uint8_t seed[CRYPTO_SEEDBYTES]; - randombytes(seed, CRYPTO_SEEDBYTES); - crypto_sign_seed_keypair(pk, sk, seed); - - return 0; -} - -/** - * Returns an array containing a detached signature. - */ -int crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - spx_ctx ctx; - - const uint8_t *sk_prf = sk + SPX_N; - const uint8_t *pk = sk + 2 * SPX_N; - - uint8_t optrand[SPX_N]; - uint8_t mhash[SPX_FORS_MSG_BYTES]; - uint8_t root[SPX_N]; - uint32_t i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - - memcpy(ctx.sk_seed, sk, SPX_N); - memcpy(ctx.pub_seed, pk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - set_type(wots_addr, SPX_ADDR_TYPE_WOTS); - set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); - - /* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ - randombytes(optrand, SPX_N); - /* Compute the digest randomization value. */ - gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); - - /* Derive the message digest and leaf index from R, PK and M. */ - hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); - sig += SPX_N; - - set_tree_addr(wots_addr, tree); - set_keypair_addr(wots_addr, idx_leaf); - - /* Sign the message hash using FORS. */ - fors_sign(sig, root, mhash, &ctx, wots_addr); - sig += SPX_FORS_BYTES; - - for (i = 0; i < SPX_D; i++) { - set_layer_addr(tree_addr, i); - set_tree_addr(tree_addr, tree); - - copy_subtree_addr(wots_addr, tree_addr); - set_keypair_addr(wots_addr, idx_leaf); - - merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); - sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); - tree = tree >> SPX_TREE_HEIGHT; - } - - free_hash_function(&ctx); - - *siglen = SPX_BYTES; - - return 0; -} - -/** - * Verifies a detached signature and message under a given public key. - */ -int crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk) { - spx_ctx ctx; - const uint8_t *pub_root = pk + SPX_N; - uint8_t mhash[SPX_FORS_MSG_BYTES]; - uint8_t wots_pk[SPX_WOTS_BYTES]; - uint8_t root[SPX_N]; - uint8_t leaf[SPX_N]; - unsigned int i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - if (siglen != SPX_BYTES) { - return -1; - } - - memcpy(ctx.pub_seed, pk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - set_type(wots_addr, SPX_ADDR_TYPE_WOTS); - set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); - set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); - - /* Derive the message digest and leaf index from R || PK || M. */ - /* The additional SPX_N is a result of the hash domain separator. */ - hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); - sig += SPX_N; - - /* Layer correctly defaults to 0, so no need to set_layer_addr */ - set_tree_addr(wots_addr, tree); - set_keypair_addr(wots_addr, idx_leaf); - - fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); - sig += SPX_FORS_BYTES; - - /* For each subtree.. */ - for (i = 0; i < SPX_D; i++) { - set_layer_addr(tree_addr, i); - set_tree_addr(tree_addr, tree); - - copy_subtree_addr(wots_addr, tree_addr); - set_keypair_addr(wots_addr, idx_leaf); - - copy_keypair_addr(wots_pk_addr, wots_addr); - - /* The WOTS public key is only correct if the signature was correct. */ - /* Initially, root is the FORS pk, but on subsequent iterations it is - the root of the subtree below the currently processed subtree. */ - wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); - sig += SPX_WOTS_BYTES; - - /* Compute the leaf node using the WOTS public key. */ - thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); - - /* Compute the root node of this subtree. */ - compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, - &ctx, tree_addr); - sig += SPX_TREE_HEIGHT * SPX_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); - tree = tree >> SPX_TREE_HEIGHT; - } - - // cleanup - free_hash_function(&ctx); - - /* Check if the root node equals the root node in the public key. */ - if (memcmp(root, pub_root, SPX_N) != 0) { - return -1; - } - - return 0; -} - - -/** - * Returns an array containing the signature followed by the message. - */ -int crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk) { - size_t siglen; - - crypto_sign_signature(sm, &siglen, m, mlen, sk); - - memmove(sm + SPX_BYTES, m, mlen); - *smlen = siglen + mlen; - - return 0; -} - -/** - * Verifies a given signature-message pair under a given public key. - */ -int crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk) { - /* The API caller does not necessarily know what size a signature should be - but SPHINCS+ signatures are always exactly SPX_BYTES. */ - if (smlen < SPX_BYTES) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - *mlen = smlen - SPX_BYTES; - - if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - /* If verification was successful, move the message to the right place. */ - memmove(m, sm + SPX_BYTES, *mlen); - - return 0; -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/thash.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/thash.h deleted file mode 100644 index 8687ccfb4d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/thash.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef SPX_THASH_H -#define SPX_THASH_H - -#include "context.h" -#include "params.h" - -#include - -#define thash SPX_NAMESPACE(thash) -void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/thash_shake_robust.c b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/thash_shake_robust.c deleted file mode 100644 index 696d53c5cc..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/thash_shake_robust.c +++ /dev/null @@ -1,31 +0,0 @@ -#include -#include - -#include "thash.h" - -#include "address.h" -#include "params.h" -#include "utils.h" - -#include "fips202.h" - -/** - * Takes an array of inblocks concatenated arrays of SPX_N bytes. - */ -void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]) { - PQCLEAN_VLA(uint8_t, buf, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); - PQCLEAN_VLA(uint8_t, bitmask, inblocks * SPX_N); - unsigned int i; - - memcpy(buf, ctx->pub_seed, SPX_N); - memcpy(buf + SPX_N, addr, SPX_ADDR_BYTES); - - shake256(bitmask, inblocks * SPX_N, buf, SPX_N + SPX_ADDR_BYTES); - - for (i = 0; i < inblocks * SPX_N; i++) { - buf[SPX_N + SPX_ADDR_BYTES + i] = in[i] ^ bitmask[i]; - } - - shake256(out, SPX_N, buf, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/utils.c b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/utils.c deleted file mode 100644 index 177b541fb9..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/utils.c +++ /dev/null @@ -1,148 +0,0 @@ -#include - -#include "utils.h" - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "thash.h" - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void ull_to_bytes(unsigned char *out, unsigned int outlen, - unsigned long long in) { - int i; - - /* Iterate over out in decreasing order, for big-endianness. */ - for (i = (signed int)outlen - 1; i >= 0; i--) { - out[i] = in & 0xff; - in = in >> 8; - } -} - -void u32_to_bytes(unsigned char *out, uint32_t in) { - out[0] = (unsigned char)(in >> 24); - out[1] = (unsigned char)(in >> 16); - out[2] = (unsigned char)(in >> 8); - out[3] = (unsigned char)in; -} - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { - unsigned long long retval = 0; - unsigned int i; - - for (i = 0; i < inlen; i++) { - retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); - } - return retval; -} - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void compute_root(unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const spx_ctx *ctx, uint32_t addr[8]) { - uint32_t i; - unsigned char buffer[2 * SPX_N]; - - /* If leaf_idx is odd (last bit = 1), current path element is a right child - and auth_path has to go left. Otherwise it is the other way around. */ - if (leaf_idx & 1) { - memcpy(buffer + SPX_N, leaf, SPX_N); - memcpy(buffer, auth_path, SPX_N); - } else { - memcpy(buffer, leaf, SPX_N); - memcpy(buffer + SPX_N, auth_path, SPX_N); - } - auth_path += SPX_N; - - for (i = 0; i < tree_height - 1; i++) { - leaf_idx >>= 1; - idx_offset >>= 1; - /* Set the address of the node we're creating. */ - set_tree_height(addr, i + 1); - set_tree_index(addr, leaf_idx + idx_offset); - - /* Pick the right or left neighbor, depending on parity of the node. */ - if (leaf_idx & 1) { - thash(buffer + SPX_N, buffer, 2, ctx, addr); - memcpy(buffer, auth_path, SPX_N); - } else { - thash(buffer, buffer, 2, ctx, addr); - memcpy(buffer + SPX_N, auth_path, SPX_N); - } - auth_path += SPX_N; - } - - /* The last iteration is exceptional; we do not copy an auth_path node. */ - leaf_idx >>= 1; - idx_offset >>= 1; - set_tree_height(addr, tree_height); - set_tree_index(addr, leaf_idx + idx_offset); - thash(root, buffer, 2, ctx, addr); -} - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const spx_ctx * /* ctx */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), - uint32_t tree_addr[8]) { - PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); - PQCLEAN_VLA(unsigned int, heights, tree_height + 1); - unsigned int offset = 0; - uint32_t idx; - uint32_t tree_idx; - - for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { - /* Add the next leaf node to the stack. */ - gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); - offset++; - heights[offset - 1] = 0; - - /* If this is a node we need for the auth path.. */ - if ((leaf_idx ^ 0x1) == idx) { - memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); - } - - /* While the top-most nodes are of equal height.. */ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { - /* Compute index of the new node, in the next layer. */ - tree_idx = (idx >> (heights[offset - 1] + 1)); - - /* Set the address of the node we're creating. */ - set_tree_height(tree_addr, heights[offset - 1] + 1); - set_tree_index(tree_addr, - tree_idx + (idx_offset >> (heights[offset - 1] + 1))); - /* Hash the top-most nodes from the stack together. */ - thash(stack + (offset - 2)*SPX_N, - stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); - offset--; - /* Note that the top-most node is now one layer higher. */ - heights[offset - 1]++; - - /* If this is a node we need for the auth path.. */ - if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_path + heights[offset - 1]*SPX_N, - stack + (offset - 1)*SPX_N, SPX_N); - } - } - } - memcpy(root, stack, SPX_N); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/utils.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/utils.h deleted file mode 100644 index 64f5d5a53a..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/utils.h +++ /dev/null @@ -1,58 +0,0 @@ -#ifndef SPX_UTILS_H -#define SPX_UTILS_H - -#include - -#include "compat.h" -#include "context.h" -#include "params.h" - - -/* To support MSVC use alloca() instead of VLAs. See #20. */ - - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) -void ull_to_bytes(unsigned char *out, unsigned int outlen, - unsigned long long in); -#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) -void u32_to_bytes(unsigned char *out, uint32_t in); - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) -unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -#define compute_root SPX_NAMESPACE(compute_root) -void compute_root(unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const spx_ctx *ctx, uint32_t addr[8]); - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -#define treehash SPX_NAMESPACE(treehash) -void treehash(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const spx_ctx *ctx /* ctx */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), - uint32_t tree_addr[8]); - - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/utilsx1.c b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/utilsx1.c deleted file mode 100644 index fccb69b35d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/utilsx1.c +++ /dev/null @@ -1,100 +0,0 @@ -#include - -#include "utilsx1.h" - -#include "address.h" -#include "params.h" -#include "thash.h" -#include "utils.h" - -/* - * Generate the entire Merkle tree, computing the authentication path for - * leaf_idx, and the resulting root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) - * - * This expects tree_addr to be initialized to the addr structures for the - * Merkle tree nodes - * - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - * - * This works by using the standard Merkle tree building algorithm, - */ -void treehashx1(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, - uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* Where to write the leaves */, - const spx_ctx * /* ctx */, - uint32_t idx, void *info), - uint32_t tree_addr[8], - void *info) { - /* This is where we keep the intermediate nodes */ - PQCLEAN_VLA(uint8_t, stack, tree_height * SPX_N); - - uint32_t idx; - uint32_t max_idx = (uint32_t)((1 << tree_height) - 1); - for (idx = 0;; idx++) { - unsigned char current[2 * SPX_N]; /* Current logical node is at */ - /* index[SPX_N]. We do this to minimize the number of copies */ - /* needed during a thash */ - gen_leaf( ¤t[SPX_N], ctx, idx + idx_offset, - info ); - - /* Now combine the freshly generated right node with previously */ - /* generated left ones */ - uint32_t internal_idx_offset = idx_offset; - uint32_t internal_idx = idx; - uint32_t internal_leaf = leaf_idx; - uint32_t h; /* The height we are in the Merkle tree */ - for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { - - /* Check if we hit the top of the tree */ - if (h == tree_height) { - /* We hit the root; return it */ - memcpy( root, ¤t[SPX_N], SPX_N ); - return; - } - - /* - * Check if the node we have is a part of the - * authentication path; if it is, write it out - */ - if ((internal_idx ^ internal_leaf) == 0x01) { - memcpy( &auth_path[ h * SPX_N ], - ¤t[SPX_N], - SPX_N ); - } - - /* - * Check if we're at a left child; if so, stop going up the stack - * Exception: if we've reached the end of the tree, keep on going - * (so we combine the last 4 nodes into the one root node in two - * more iterations) - */ - if ((internal_idx & 1) == 0 && idx < max_idx) { - break; - } - - /* Ok, we're at a right node */ - /* Now combine the left and right logical nodes together */ - - /* Set the address of the node we're creating. */ - internal_idx_offset >>= 1; - set_tree_height(tree_addr, h + 1); - set_tree_index(tree_addr, internal_idx / 2 + internal_idx_offset ); - - unsigned char *left = &stack[h * SPX_N]; - memcpy( ¤t[0], left, SPX_N ); - thash( ¤t[1 * SPX_N], - ¤t[0 * SPX_N], - 2, ctx, tree_addr); - } - - /* We've hit a left child; save the current for when we get the */ - /* corresponding right right */ - memcpy( &stack[h * SPX_N], ¤t[SPX_N], SPX_N); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/utilsx1.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/utilsx1.h deleted file mode 100644 index e911d17d53..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/utilsx1.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef SPX_UTILSX4_H -#define SPX_UTILSX4_H - -#include - -#include "context.h" -#include "params.h" - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -#define treehashx1 SPX_NAMESPACE(treehashx1) -void treehashx1(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* Where to write the leaf */, - const spx_ctx * /* ctx */, - uint32_t addr_idx, void *info), - uint32_t tree_addrx4[8], void *info); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/wots.c b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/wots.c deleted file mode 100644 index 249717aaa8..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/wots.c +++ /dev/null @@ -1,108 +0,0 @@ -#include -#include - -#include "wots.h" -#include "wotsx1.h" - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "thash.h" -#include "utils.h" -#include "utilsx1.h" - -// TODO clarify address expectations, and make them more uniform. -// TODO i.e. do we expect types to be set already? -// TODO and do we expect modifications or copies? - -/** - * Computes the chaining function. - * out and in have to be n-byte arrays. - * - * Interprets in as start-th value of the chain. - * addr has to contain the address of the chain. - */ -static void gen_chain(unsigned char *out, const unsigned char *in, - unsigned int start, unsigned int steps, - const spx_ctx *ctx, uint32_t addr[8]) { - uint32_t i; - - /* Initialize out with the value at position 'start'. */ - memcpy(out, in, SPX_N); - - /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < SPX_WOTS_W; i++) { - set_hash_addr(addr, i); - thash(out, out, 1, ctx, addr); - } -} - -/** - * base_w algorithm as described in draft. - * Interprets an array of bytes as integers in base w. - * This only works when log_w is a divisor of 8. - */ -static void base_w(unsigned int *output, const int out_len, - const unsigned char *input) { - int in = 0; - int out = 0; - unsigned char total = 0; - int bits = 0; - int consumed; - - for (consumed = 0; consumed < out_len; consumed++) { - if (bits == 0) { - total = input[in]; - in++; - bits += 8; - } - bits -= SPX_WOTS_LOGW; - output[out] = (total >> bits) & (SPX_WOTS_W - 1); - out++; - } -} - -/* Computes the WOTS+ checksum over a message (in base_w). */ -static void wots_checksum(unsigned int *csum_base_w, - const unsigned int *msg_base_w) { - unsigned int csum = 0; - unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; - unsigned int i; - - /* Compute checksum. */ - for (i = 0; i < SPX_WOTS_LEN1; i++) { - csum += SPX_WOTS_W - 1 - msg_base_w[i]; - } - - /* Convert checksum to base_w. */ - /* Make sure expected empty zero bits are the least significant bits. */ - csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); - ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); - base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); -} - -/* Takes a message and derives the matching chain lengths. */ -void chain_lengths(unsigned int *lengths, const unsigned char *msg) { - base_w(lengths, SPX_WOTS_LEN1, msg); - wots_checksum(lengths + SPX_WOTS_LEN1, lengths); -} - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const spx_ctx *ctx, uint32_t addr[8]) { - unsigned int lengths[SPX_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < SPX_WOTS_LEN; i++) { - set_chain_addr(addr, i); - gen_chain(pk + i * SPX_N, sig + i * SPX_N, - lengths[i], SPX_WOTS_W - 1 - lengths[i], ctx, addr); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/wots.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/wots.h deleted file mode 100644 index 4e7692eeef..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/wots.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef SPX_WOTS_H -#define SPX_WOTS_H - -#include - -#include "context.h" -#include "params.h" - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) -void wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const spx_ctx *ctx, uint32_t addr[8]); - -/* - * Compute the chain lengths needed for a given message hash - */ -#define chain_lengths SPX_NAMESPACE(chain_lengths) -void chain_lengths(unsigned int *lengths, const unsigned char *msg); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/wotsx1.c b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/wotsx1.c deleted file mode 100644 index 3adec78dfb..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/wotsx1.c +++ /dev/null @@ -1,76 +0,0 @@ -#include -#include - -#include "wots.h" -#include "wotsx1.h" - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "thash.h" -#include "utils.h" - -/* - * This generates a WOTS public key - * It also generates the WOTS signature if leaf_info indicates - * that we're signing with this WOTS key - */ -void wots_gen_leafx1(unsigned char *dest, - const spx_ctx *ctx, - uint32_t leaf_idx, void *v_info) { - struct leaf_info_x1 *info = v_info; - uint32_t *leaf_addr = info->leaf_addr; - uint32_t *pk_addr = info->pk_addr; - unsigned int i, k; - unsigned char pk_buffer[ SPX_WOTS_BYTES ]; - unsigned char *buffer; - uint32_t wots_k_mask; - - if (leaf_idx == info->wots_sign_leaf) { - /* We're traversing the leaf that's signing; generate the WOTS */ - /* signature */ - wots_k_mask = 0; - } else { - /* Nope, we're just generating pk's; turn off the signature logic */ - wots_k_mask = (uint32_t)~0; - } - - set_keypair_addr( leaf_addr, leaf_idx ); - set_keypair_addr( pk_addr, leaf_idx ); - - for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { - uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k to */ - /* the step if we're generating a signature, ~0 if we're not */ - - /* Start with the secret seed */ - set_chain_addr(leaf_addr, i); - set_hash_addr(leaf_addr, 0); - set_type(leaf_addr, SPX_ADDR_TYPE_WOTSPRF); - - prf_addr(buffer, ctx, leaf_addr); - - set_type(leaf_addr, SPX_ADDR_TYPE_WOTS); - - /* Iterate down the WOTS chain */ - for (k = 0;; k++) { - /* Check if this is the value that needs to be saved as a */ - /* part of the WOTS signature */ - if (k == wots_k) { - memcpy( info->wots_sig + i * SPX_N, buffer, SPX_N ); - } - - /* Check if we hit the top of the chain */ - if (k == SPX_WOTS_W - 1) { - break; - } - - /* Iterate one step on the chain */ - set_hash_addr(leaf_addr, k); - - thash(buffer, buffer, 1, ctx, leaf_addr); - } - } - - /* Do the final thash to generate the public keys */ - thash(dest, pk_buffer, SPX_WOTS_LEN, ctx, pk_addr); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/wotsx1.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/wotsx1.h deleted file mode 100644 index e617929f96..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192f-robust_clean/wotsx1.h +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef WOTSX1_H_ -#define WOTSX1_H_ - -#include - -#include "context.h" -#include "params.h" - -/* - * This is here to provide an interface to the internal wots_gen_leafx1 - * routine. While this routine is not referenced in the package outside of - * wots.c, it is called from the stand-alone benchmark code to characterize - * the performance - */ -struct leaf_info_x1 { - unsigned char *wots_sig; - uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ - uint32_t *wots_steps; - uint32_t leaf_addr[8]; - uint32_t pk_addr[8]; -}; - -/* Macro to set the leaf_info to something 'benign', that is, it would */ -/* run with the same time as it does during the real signing process */ -/* Used only by the benchmark code */ -#define INITIALIZE_LEAF_INFO_X1(info, addr, step_buffer) { \ - (info).wots_sig = 0; \ - (info).wots_sign_leaf = ~0; \ - (info).wots_steps = step_buffer; \ - memcpy( &(info).leaf_addr[0], (addr), 32 ); \ - memcpy( &(info).pk_addr[0], (addr), 32 ); \ - } - -#define wots_gen_leafx1 SPX_NAMESPACE(wots_gen_leafx1) -void wots_gen_leafx1(unsigned char *dest, - const spx_ctx *ctx, - uint32_t leaf_idx, void *v_info); - -#endif /* WOTSX1_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/LICENSE b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/LICENSE deleted file mode 100644 index 670154e353..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/LICENSE +++ /dev/null @@ -1,116 +0,0 @@ -CC0 1.0 Universal - -Statement of Purpose - -The laws of most jurisdictions throughout the world automatically confer -exclusive Copyright and Related Rights (defined below) upon the creator and -subsequent owner(s) (each and all, an "owner") of an original work of -authorship and/or a database (each, a "Work"). - -Certain owners wish to permanently relinquish those rights to a Work for the -purpose of contributing to a commons of creative, cultural and scientific -works ("Commons") that the public can reliably and without fear of later -claims of infringement build upon, modify, incorporate in other works, reuse -and redistribute as freely as possible in any form whatsoever and for any -purposes, including without limitation commercial purposes. These owners may -contribute to the Commons to promote the ideal of a free culture and the -further production of creative, cultural and scientific works, or to gain -reputation or greater distribution for their Work in part through the use and -efforts of others. - -For these and/or other purposes and motivations, and without any expectation -of additional consideration or compensation, the person associating CC0 with a -Work (the "Affirmer"), to the extent that he or she is an owner of Copyright -and Related Rights in the Work, voluntarily elects to apply CC0 to the Work -and publicly distribute the Work under its terms, with knowledge of his or her -Copyright and Related Rights in the Work and the meaning and intended legal -effect of CC0 on those rights. - -1. Copyright and Related Rights. A Work made available under CC0 may be -protected by copyright and related or neighboring rights ("Copyright and -Related Rights"). Copyright and Related Rights include, but are not limited -to, the following: - - i. the right to reproduce, adapt, distribute, perform, display, communicate, - and translate a Work; - - ii. moral rights retained by the original author(s) and/or performer(s); - - iii. publicity and privacy rights pertaining to a person's image or likeness - depicted in a Work; - - iv. rights protecting against unfair competition in regards to a Work, - subject to the limitations in paragraph 4(a), below; - - v. rights protecting the extraction, dissemination, use and reuse of data in - a Work; - - vi. database rights (such as those arising under Directive 96/9/EC of the - European Parliament and of the Council of 11 March 1996 on the legal - protection of databases, and under any national implementation thereof, - including any amended or successor version of such directive); and - - vii. other similar, equivalent or corresponding rights throughout the world - based on applicable law or treaty, and any national implementations thereof. - -2. Waiver. To the greatest extent permitted by, but not in contravention of, -applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and -unconditionally waives, abandons, and surrenders all of Affirmer's Copyright -and Related Rights and associated claims and causes of action, whether now -known or unknown (including existing as well as future claims and causes of -action), in the Work (i) in all territories worldwide, (ii) for the maximum -duration provided by applicable law or treaty (including future time -extensions), (iii) in any current or future medium and for any number of -copies, and (iv) for any purpose whatsoever, including without limitation -commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes -the Waiver for the benefit of each member of the public at large and to the -detriment of Affirmer's heirs and successors, fully intending that such Waiver -shall not be subject to revocation, rescission, cancellation, termination, or -any other legal or equitable action to disrupt the quiet enjoyment of the Work -by the public as contemplated by Affirmer's express Statement of Purpose. - -3. Public License Fallback. Should any part of the Waiver for any reason be -judged legally invalid or ineffective under applicable law, then the Waiver -shall be preserved to the maximum extent permitted taking into account -Affirmer's express Statement of Purpose. In addition, to the extent the Waiver -is so judged Affirmer hereby grants to each affected person a royalty-free, -non transferable, non sublicensable, non exclusive, irrevocable and -unconditional license to exercise Affirmer's Copyright and Related Rights in -the Work (i) in all territories worldwide, (ii) for the maximum duration -provided by applicable law or treaty (including future time extensions), (iii) -in any current or future medium and for any number of copies, and (iv) for any -purpose whatsoever, including without limitation commercial, advertising or -promotional purposes (the "License"). The License shall be deemed effective as -of the date CC0 was applied by Affirmer to the Work. Should any part of the -License for any reason be judged legally invalid or ineffective under -applicable law, such partial invalidity or ineffectiveness shall not -invalidate the remainder of the License, and in such case Affirmer hereby -affirms that he or she will not (i) exercise any of his or her remaining -Copyright and Related Rights in the Work or (ii) assert any associated claims -and causes of action with respect to the Work, in either case contrary to -Affirmer's express Statement of Purpose. - -4. Limitations and Disclaimers. - - a. No trademark or patent rights held by Affirmer are waived, abandoned, - surrendered, licensed or otherwise affected by this document. - - b. Affirmer offers the Work as-is and makes no representations or warranties - of any kind concerning the Work, express, implied, statutory or otherwise, - including without limitation warranties of title, merchantability, fitness - for a particular purpose, non infringement, or the absence of latent or - other defects, accuracy, or the present or absence of errors, whether or not - discoverable, all to the greatest extent permissible under applicable law. - - c. Affirmer disclaims responsibility for clearing rights of other persons - that may apply to the Work or any use thereof, including without limitation - any person's Copyright and Related Rights in the Work. Further, Affirmer - disclaims responsibility for obtaining any necessary consents, permissions - or other rights required for any use of the Work. - - d. Affirmer understands and acknowledges that Creative Commons is not a - party to this document and has no duty or obligation with respect to this - CC0 or use of the Work. - -For more information, please see - diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/address.c b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/address.c deleted file mode 100644 index d49d9f3b6b..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/address.c +++ /dev/null @@ -1,95 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "utils.h" - -/* - * Specify which level of Merkle tree (the "layer") we're working on - */ -void set_layer_addr(uint32_t addr[8], uint32_t layer) { - ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; -} - -/* - * Specify which Merkle tree within the level (the "tree address") we're working on - */ -void set_tree_addr(uint32_t addr[8], uint64_t tree) { - ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); -} - -/* - * Specify the reason we'll use this address structure for, that is, what - * hash will we compute with it. This is used so that unrelated types of - * hashes don't accidentally get the same address structure. The type will be - * one of the SPX_ADDR_TYPE constants - */ -void set_type(uint32_t addr[8], uint32_t type) { - ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; -} - -/* - * Copy the layer and tree fields of the address structure. This is used - * when we're doing multiple types of hashes within the same Merkle tree - */ -void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { - memcpy( out, in, SPX_OFFSET_TREE + 8 ); -} - -/* These functions are used for OTS addresses. */ - -/* - * Specify which Merkle leaf we're working on; that is, which OTS keypair - * we're talking about. - */ -void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { - /* We have > 256 OTS at the bottom of the Merkle tree; to specify */ - /* which one, we'd need to express it in two bytes */ - ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR2] = (unsigned char)(keypair >> 8); - ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; -} - -/* - * Copy the layer, tree and keypair fields of the address structure. This is - * used when we're doing multiple things within the same OTS keypair - */ -void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { - memcpy( out, in, SPX_OFFSET_TREE + 8 ); - ((unsigned char *)out)[SPX_OFFSET_KP_ADDR2] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR2]; - ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; -} - -/* - * Specify which Merkle chain within the OTS we're working with - * (the chain address) - */ -void set_chain_addr(uint32_t addr[8], uint32_t chain) { - ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; -} - -/* - * Specify where in the Merkle chain we are -* (the hash address) - */ -void set_hash_addr(uint32_t addr[8], uint32_t hash) { - ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; -} - -/* These functions are used for all hash tree addresses (including FORS). */ - -/* - * Specify the height of the node in the Merkle/FORS tree we are in - * (the tree height) - */ -void set_tree_height(uint32_t addr[8], uint32_t tree_height) { - ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; -} - -/* - * Specify the distance from the left edge of the node in the Merkle/FORS tree - * (the tree index) - */ -void set_tree_index(uint32_t addr[8], uint32_t tree_index) { - u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/address.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/address.h deleted file mode 100644 index 24a84eb40c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/address.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef SPX_ADDRESS_H -#define SPX_ADDRESS_H - -#include - -#include "params.h" - -/* The hash types that are passed to set_type */ -#define SPX_ADDR_TYPE_WOTS 0 -#define SPX_ADDR_TYPE_WOTSPK 1 -#define SPX_ADDR_TYPE_HASHTREE 2 -#define SPX_ADDR_TYPE_FORSTREE 3 -#define SPX_ADDR_TYPE_FORSPK 4 -#define SPX_ADDR_TYPE_WOTSPRF 5 -#define SPX_ADDR_TYPE_FORSPRF 6 - -#define set_layer_addr SPX_NAMESPACE(set_layer_addr) -void set_layer_addr(uint32_t addr[8], uint32_t layer); - -#define set_tree_addr SPX_NAMESPACE(set_tree_addr) -void set_tree_addr(uint32_t addr[8], uint64_t tree); - -#define set_type SPX_NAMESPACE(set_type) -void set_type(uint32_t addr[8], uint32_t type); - -/* Copies the layer and tree part of one address into the other */ -#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) -void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for WOTS and FORS addresses. */ - -#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) -void set_keypair_addr(uint32_t addr[8], uint32_t keypair); - -#define set_chain_addr SPX_NAMESPACE(set_chain_addr) -void set_chain_addr(uint32_t addr[8], uint32_t chain); - -#define set_hash_addr SPX_NAMESPACE(set_hash_addr) -void set_hash_addr(uint32_t addr[8], uint32_t hash); - -#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) -void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for all hash tree addresses (including FORS). */ - -#define set_tree_height SPX_NAMESPACE(set_tree_height) -void set_tree_height(uint32_t addr[8], uint32_t tree_height); - -#define set_tree_index SPX_NAMESPACE(set_tree_index) -void set_tree_index(uint32_t addr[8], uint32_t tree_index); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/api.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/api.h deleted file mode 100644 index 11a6733200..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/api.h +++ /dev/null @@ -1,77 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE192SROBUST_AARCH64_API_H -#define PQCLEAN_SPHINCSSHAKE192SROBUST_AARCH64_API_H - -#include -#include - -#define PQCLEAN_SPHINCSSHAKE192SROBUST_AARCH64_CRYPTO_ALGNAME "SPHINCS+-shake-192s-robust" - -#define PQCLEAN_SPHINCSSHAKE192SROBUST_AARCH64_CRYPTO_SECRETKEYBYTES 96 -#define PQCLEAN_SPHINCSSHAKE192SROBUST_AARCH64_CRYPTO_PUBLICKEYBYTES 48 -#define PQCLEAN_SPHINCSSHAKE192SROBUST_AARCH64_CRYPTO_BYTES 16224 - -#define PQCLEAN_SPHINCSSHAKE192SROBUST_AARCH64_CRYPTO_SEEDBYTES 72 - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE192SROBUST_AARCH64_crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE192SROBUST_AARCH64_crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE192SROBUST_AARCH64_crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE192SROBUST_AARCH64_crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHAKE192SROBUST_AARCH64_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHAKE192SROBUST_AARCH64_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSSHAKE192SROBUST_AARCH64_crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE192SROBUST_AARCH64_crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, - const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSSHAKE192SROBUST_AARCH64_crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE192SROBUST_AARCH64_crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk); -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/context.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/context.h deleted file mode 100644 index 6e0a33f3b7..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/context.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef SPX_CONTEXT_H -#define SPX_CONTEXT_H - -#include - -#include "params.h" - -typedef struct { - uint8_t pub_seed[SPX_N]; - uint8_t sk_seed[SPX_N]; -} spx_ctx; - -#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) -void initialize_hash_function(spx_ctx *ctx); - -#define free_hash_function SPX_NAMESPACE(free_hash_function) -void free_hash_function(spx_ctx *ctx); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/context_shake.c b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/context_shake.c deleted file mode 100644 index 9614a103d3..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/context_shake.c +++ /dev/null @@ -1,12 +0,0 @@ -#include "context.h" - -/* For SHAKE256, there is no immediate reason to initialize at the start, - so this function is an empty operation. */ -void initialize_hash_function(spx_ctx *ctx) { - (void)ctx; /* Suppress an 'unused parameter' warning. */ -} - -// in case the hash function api is heap-based. -void free_hash_function(spx_ctx *ctx) { - (void)ctx; -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/f1600x2.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/f1600x2.h deleted file mode 100644 index 70d1af9f14..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/f1600x2.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef SPX_F1600X2_H -#define SPX_F1600X2_H - -#include - -extern uint64_t f1600_RC[24]; -extern void _f1600x2(uint64_t *a, uint64_t *rc); - -#define f1600x2(s) do {_f1600x2((s), f1600_RC);} while(0) - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/f1600x2.s b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/f1600x2.s deleted file mode 100644 index 640ed791ed..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/f1600x2.s +++ /dev/null @@ -1,143 +0,0 @@ -# From https://github.com/bwesterb/armed-keccak - -.macro round - # Execute theta, but without xoring into the state yet. - # Compute parities p[i] = a[i] ^ a[5+i] ^ ... ^ a[20+i]. - eor3.16b v25, v0, v5, v10 - eor3.16b v26, v1, v6, v11 - eor3.16b v27, v2, v7, v12 - eor3.16b v28, v3, v8, v13 - eor3.16b v29, v4, v9, v14 - - eor3.16b v25, v25, v15, v20 - eor3.16b v26, v26, v16, v21 - eor3.16b v27, v27, v17, v22 - eor3.16b v28, v28, v18, v23 - eor3.16b v29, v29, v19, v24 - - # d[0] = rotl(p[1], 1) ^ p[4] - rax1.2d v30, v29, v26 - # d[3] = rotl(p[4], 1) ^ p[2] - rax1.2d v29, v27, v29 - # d[1] = rotl(p[2], 1) ^ p[0] - rax1.2d v27, v25, v27 - # d[4] = rotl(p[0], 1) ^ p[3] - rax1.2d v25, v28, v25 - # d[2] = rotl(p[3], 1) ^ p[1] - rax1.2d v28, v26, v28 - - # Xor parities from step theta into the state at the same time - # as executing rho and pi. - eor.16b v0, v0, v30 - mov.16b v31, v1 - xar.2d v1, v6, v27, 20 - xar.2d v6, v9, v25, 44 - xar.2d v9, v22, v28, 3 - xar.2d v22, v14, v25, 25 - xar.2d v14, v20, v30, 46 - xar.2d v20, v2, v28, 2 - xar.2d v2, v12, v28, 21 - xar.2d v12, v13, v29, 39 - xar.2d v13, v19, v25, 56 - xar.2d v19, v23, v29, 8 - xar.2d v23, v15, v30, 23 - xar.2d v15, v4, v25, 37 - xar.2d v4, v24, v25, 50 - xar.2d v24, v21, v27, 62 - xar.2d v21, v8, v29, 9 - xar.2d v8, v16, v27, 19 - xar.2d v16, v5, v30, 28 - xar.2d v5, v3, v29, 36 - xar.2d v3, v18, v29, 43 - xar.2d v18, v17, v28, 49 - xar.2d v17, v11, v27, 54 - xar.2d v11, v7, v28, 58 - xar.2d v7, v10, v30, 61 - xar.2d v10, v31, v27, 63 - - # Chi - bcax.16b v25, v0, v2, v1 - bcax.16b v26, v1, v3, v2 - bcax.16b v2, v2, v4, v3 - bcax.16b v3, v3, v0, v4 - bcax.16b v4, v4, v1, v0 - mov.16b v0, v25 - mov.16b v1, v26 - - bcax.16b v25, v5, v7, v6 - bcax.16b v26, v6, v8, v7 - bcax.16b v7, v7, v9, v8 - bcax.16b v8, v8, v5, v9 - bcax.16b v9, v9, v6, v5 - mov.16b v5, v25 - mov.16b v6, v26 - - bcax.16b v25, v10, v12, v11 - bcax.16b v26, v11, v13, v12 - bcax.16b v12, v12, v14, v13 - bcax.16b v13, v13, v10, v14 - bcax.16b v14, v14, v11, v10 - mov.16b v10, v25 - mov.16b v11, v26 - - bcax.16b v25, v15, v17, v16 - bcax.16b v26, v16, v18, v17 - bcax.16b v17, v17, v19, v18 - bcax.16b v18, v18, v15, v19 - bcax.16b v19, v19, v16, v15 - mov.16b v15, v25 - mov.16b v16, v26 - - bcax.16b v25, v20, v22, v21 - bcax.16b v26, v21, v23, v22 - bcax.16b v22, v22, v24, v23 - bcax.16b v23, v23, v20, v24 - bcax.16b v24, v24, v21, v20 - mov.16b v20, v25 - mov.16b v21, v26 - - # iota - ld1r {v25.2d}, [x1], #8 - eor.16b v0, v0, v25 -.endm - -.align 4 -.global __f1600x2 -__f1600x2: - stp d8, d9, [sp,#-16]! - stp d10, d11, [sp,#-16]! - stp d12, d13, [sp,#-16]! - stp d14, d15, [sp,#-16]! - - mov x2, x0 - mov x3, #24 - - ld1.2d {v0, v1, v2, v3}, [x0], #64 - ld1.2d {v4, v5, v6, v7}, [x0], #64 - ld1.2d {v8, v9, v10, v11}, [x0], #64 - ld1.2d {v12, v13, v14, v15}, [x0], #64 - ld1.2d {v16, v17, v18, v19}, [x0], #64 - ld1.2d {v20, v21, v22, v23}, [x0], #64 - ld1.2d {v24}, [x0] - -loop: - round - - subs x3, x3, #1 - cbnz x3, loop - - mov x0, x2 - st1.2d {v0, v1, v2, v3}, [x0], #64 - st1.2d {v4, v5, v6, v7}, [x0], #64 - st1.2d {v8, v9, v10, v11}, [x0], #64 - st1.2d {v12, v13, v14, v15}, [x0], #64 - st1.2d {v16, v17, v18, v19}, [x0], #64 - st1.2d {v20, v21, v22, v23}, [x0], #64 - st1.2d {v24}, [x0] - - ldp d14, d15, [sp], #16 - ldp d12, d13, [sp], #16 - ldp d10, d11, [sp], #16 - ldp d8, d9, [sp], #16 - - ret lr diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/f1600x2_const.c b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/f1600x2_const.c deleted file mode 100644 index e49c0ba149..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/f1600x2_const.c +++ /dev/null @@ -1,30 +0,0 @@ -#include "f1600x2.h" - -uint64_t f1600_RC[24] = { - 0x0000000000000001, - 0x0000000000008082, - 0x800000000000808A, - 0x8000000080008000, - 0x000000000000808B, - 0x0000000080000001, - 0x8000000080008081, - 0x8000000000008009, - 0x000000000000008A, - 0x0000000000000088, - 0x0000000080008009, - 0x000000008000000A, - 0x000000008000808B, - 0x800000000000008B, - 0x8000000000008089, - 0x8000000000008003, - 0x8000000000008002, - 0x8000000000000080, - 0x000000000000800A, - 0x800000008000000A, - 0x8000000080008081, - 0x8000000000008080, - 0x0000000080000001, - 0x8000000080008008, -}; - - diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/fips202x2.c b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/fips202x2.c deleted file mode 100644 index 4718c343bc..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/fips202x2.c +++ /dev/null @@ -1,148 +0,0 @@ -#include -#include - -#include "fips202x2.h" -#include "f1600x2.h" -#include "fips202.h" - -uint64_t load64(const unsigned char *x) { - unsigned long long r = 0, i; - - for (i = 0; i < 8; ++i) { - r |= (unsigned long long)x[i] << 8 * i; - } - return r; -} - -void store64(uint8_t *x, uint64_t u) { - unsigned int i; - - for (i = 0; i < 8; ++i) { - x[i] = (uint8_t)u; - u >>= 8; - } -} - -static void keccak_absorb2x(uint64_t *s, - unsigned int r, - const unsigned char *m0, - const unsigned char *m1, - unsigned long long int mlen, - unsigned char p) { - unsigned long long i; - unsigned char t0[200]; - unsigned char t1[200]; - - while (mlen >= r) { - for (i = 0; i < r / 8; ++i) { - s[2 * i + 0] ^= load64(m0 + 8 * i); - s[2 * i + 1] ^= load64(m1 + 8 * i); - } - - f1600x2(s); - mlen -= r; - m0 += r; - m1 += r; - } - - for (i = 0; i < r; ++i) { - t0[i] = 0; - t1[i] = 0; - } - for (i = 0; i < mlen; ++i) { - t0[i] = m0[i]; - t1[i] = m1[i]; - } - - t0[i] = p; - t1[i] = p; - - t0[r - 1] |= 128; - t1[r - 1] |= 128; - - for (i = 0; i < r / 8; ++i) { - s[2 * i + 0] ^= load64(t0 + 8 * i); - s[2 * i + 1] ^= load64(t1 + 8 * i); - } -} - - -static void keccak_squeezeblocks2x(unsigned char *h0, - unsigned char *h1, - unsigned long long int nblocks, - uint64_t *s, - unsigned int r) { - unsigned int i; - - while (nblocks > 0) { - f1600x2(s); - for (i = 0; i < (r >> 3); i++) { - store64(h0 + 8 * i, s[2 * i + 0]); - store64(h1 + 8 * i, s[2 * i + 1]); - } - h0 += r; - h1 += r; - nblocks--; - } -} - - - -void shake128x2(unsigned char *out0, - unsigned char *out1, - unsigned long long outlen, - unsigned char *in0, - unsigned char *in1, - unsigned long long inlen) { - uint64_t s[50] = {0}; - unsigned char t0[SHAKE128_RATE]; - unsigned char t1[SHAKE128_RATE]; - unsigned int i; - - /* absorb 4 message of identical length in parallel */ - keccak_absorb2x(s, SHAKE128_RATE, in0, in1, inlen, 0x1F); - - /* Squeeze output */ - keccak_squeezeblocks2x(out0, out1, outlen / SHAKE128_RATE, s, SHAKE128_RATE); - - out0 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; - out1 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; - - if (outlen % SHAKE128_RATE) { - keccak_squeezeblocks2x(t0, t1, 1, s, SHAKE128_RATE); - for (i = 0; i < outlen % SHAKE128_RATE; i++) { - out0[i] = t0[i]; - out1[i] = t1[i]; - } - } -} - - -void shake256x2(unsigned char *out0, - unsigned char *out1, - unsigned long long outlen, - unsigned char *in0, - unsigned char *in1, - unsigned long long inlen) { - uint64_t s[50] = {0}; - unsigned char t0[SHAKE256_RATE]; - unsigned char t1[SHAKE256_RATE]; - unsigned int i; - - /* absorb 2 message of identical length in parallel */ - keccak_absorb2x(s, SHAKE256_RATE, in0, in1, inlen, 0x1F); - - /* Squeeze output */ - keccak_squeezeblocks2x(out0, out1, outlen / SHAKE256_RATE, s, SHAKE256_RATE); - - out0 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; - out1 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; - - if (outlen % SHAKE256_RATE) { - keccak_squeezeblocks2x(t0, t1, 1, s, SHAKE256_RATE); - for (i = 0; i < outlen % SHAKE256_RATE; i++) { - out0[i] = t0[i]; - out1[i] = t1[i]; - } - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/fips202x2.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/fips202x2.h deleted file mode 100644 index 7ba58b35d8..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/fips202x2.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef SPX_FIPS202X2_H -#define SPX_FIPS202X2_H - -#include - -uint64_t load64(const unsigned char *x); -void store64(uint8_t *x, uint64_t u); - - -void shake128x2(unsigned char *out0, - unsigned char *out1, - unsigned long long outlen, - unsigned char *in0, - unsigned char *in1, - unsigned long long inlen); - -void shake256x2(unsigned char *out0, - unsigned char *out1, - unsigned long long outlen, - unsigned char *in0, - unsigned char *in1, - unsigned long long inlen); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/fors.c b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/fors.c deleted file mode 100644 index 39193d04e2..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/fors.c +++ /dev/null @@ -1,191 +0,0 @@ -#include -#include -#include - -#include "fors.h" - -#include "address.h" -#include "hash.h" -#include "hashx2.h" -#include "thash.h" -#include "thashx2.h" -#include "utils.h" -#include "utilsx2.h" - -static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, - uint32_t fors_leaf_addr[8]) { - prf_addr(sk, ctx, fors_leaf_addr); -} - -static void fors_gen_skx2(unsigned char *sk0, - unsigned char *sk1, - const spx_ctx *ctx, - uint32_t fors_leaf_addrx2[2 * 8]) { - prf_addrx2(sk0, sk1, - ctx, fors_leaf_addrx2); -} - -static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, - const spx_ctx *ctx, - uint32_t fors_leaf_addr[8]) { - thash(leaf, sk, 1, ctx, fors_leaf_addr); -} - -static void fors_sk_to_leafx2(unsigned char *leaf0, - unsigned char *leaf1, - const unsigned char *sk0, - const unsigned char *sk1, - const spx_ctx *ctx, - uint32_t fors_leaf_addrx2[2 * 8]) { - thashx2(leaf0, leaf1, - sk0, sk1, - 1, ctx, fors_leaf_addrx2); -} - -struct fors_gen_leaf_info { - uint32_t leaf_addrx[2 * 8]; -}; - -static void fors_gen_leafx2(unsigned char *leaf, - const spx_ctx *ctx, - uint32_t addr_idx, void *info) { - struct fors_gen_leaf_info *fors_info = info; - uint32_t *fors_leaf_addrx2 = fors_info->leaf_addrx; - unsigned int j; - - /* Only set the parts that the caller doesn't set */ - for (j = 0; j < 2; j++) { - set_tree_index(fors_leaf_addrx2 + j * 8, addr_idx + j); - set_type(fors_leaf_addrx2 + j * 8, SPX_ADDR_TYPE_FORSPRF); - } - - fors_gen_skx2(leaf + 0 * SPX_N, - leaf + 1 * SPX_N, - ctx, fors_leaf_addrx2); - - for (j = 0; j < 2; j++) { - set_type(fors_leaf_addrx2 + j * 8, SPX_ADDR_TYPE_FORSTREE); - } - - fors_sk_to_leafx2(leaf + 0 * SPX_N, - leaf + 1 * SPX_N, - leaf + 0 * SPX_N, - leaf + 1 * SPX_N, - ctx, fors_leaf_addrx2); -} - -/** - * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - * Assumes indices has space for SPX_FORS_TREES integers. - */ -static void message_to_indices(uint32_t *indices, const unsigned char *m) { - unsigned int i, j; - unsigned int offset = 0; - - for (i = 0; i < SPX_FORS_TREES; i++) { - indices[i] = 0; - for (j = 0; j < SPX_FORS_HEIGHT; j++) { - indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); - offset++; - } - } -} - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -void fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]) { - uint32_t indices[SPX_FORS_TREES]; - unsigned char roots[SPX_FORS_TREES * SPX_N]; - uint32_t fors_tree_addr[2 * 8] = {0}; - struct fors_gen_leaf_info fors_info = {0}; - uint32_t *fors_leaf_addr = fors_info.leaf_addrx; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - for (i = 0; i < 2; i++) { - copy_keypair_addr(fors_tree_addr + 8 * i, fors_addr); - set_type(fors_tree_addr + 8 * i, SPX_ADDR_TYPE_FORSTREE); - copy_keypair_addr(fors_leaf_addr + 8 * i, fors_addr); - } - copy_keypair_addr(fors_pk_addr, fors_addr); - set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < SPX_FORS_TREES; i++) { - idx_offset = i * (1 << SPX_FORS_HEIGHT); - - set_tree_height(fors_tree_addr, 0); - set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Include the secret key part that produces the selected leaf node. */ - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); - fors_gen_sk(sig, ctx, fors_tree_addr); - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); - sig += SPX_N; - - /* Compute the authentication path for this leaf node. */ - treehashx2(roots + i * SPX_N, sig, ctx, - indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx2, - fors_tree_addr, &fors_info); - - sig += SPX_N * SPX_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); -} - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -void fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]) { - uint32_t indices[SPX_FORS_TREES]; - unsigned char roots[SPX_FORS_TREES * SPX_N]; - unsigned char leaf[SPX_N]; - uint32_t fors_tree_addr[8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - copy_keypair_addr(fors_tree_addr, fors_addr); - copy_keypair_addr(fors_pk_addr, fors_addr); - - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); - set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < SPX_FORS_TREES; i++) { - idx_offset = i * (1 << SPX_FORS_HEIGHT); - - set_tree_height(fors_tree_addr, 0); - set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Derive the leaf from the included secret key part. */ - fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); - sig += SPX_N; - - /* Derive the corresponding root node of this tree. */ - compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, - sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); - sig += SPX_N * SPX_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/fors.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/fors.h deleted file mode 100644 index 509140a178..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/fors.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef SPX_FORS_H -#define SPX_FORS_H - -#include - -#include "context.h" -#include "params.h" - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -#define fors_sign SPX_NAMESPACE(fors_sign) -void fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]); - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) -void fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/hash.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/hash.h deleted file mode 100644 index f7c87d4c3c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/hash.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef SPX_HASH_H -#define SPX_HASH_H - -#include -#include - -#include "context.h" -#include "params.h" - -#define prf_addr SPX_NAMESPACE(prf_addr) -void prf_addr(unsigned char *out, const spx_ctx *ctx, - const uint32_t addr[8]); - -#define gen_message_random SPX_NAMESPACE(gen_message_random) -void gen_message_random(unsigned char *R, const unsigned char *sk_prf, - const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx); - -#define hash_message SPX_NAMESPACE(hash_message) -void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx); - - - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/hash_shake.c b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/hash_shake.c deleted file mode 100644 index ff5e7ec918..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/hash_shake.c +++ /dev/null @@ -1,83 +0,0 @@ -#include -#include - -#include "hash.h" - -#include "address.h" -#include "fips202.h" -#include "params.h" -#include "utils.h" - -/* - * Computes PRF(pk_seed, sk_seed, addr) - */ -void prf_addr(unsigned char *out, const spx_ctx *ctx, - const uint32_t addr[8]) { - unsigned char buf[2 * SPX_N + SPX_ADDR_BYTES]; - - memcpy(buf, ctx->pub_seed, SPX_N); - memcpy(buf + SPX_N, addr, SPX_ADDR_BYTES); - memcpy(buf + SPX_N + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); - - shake256(out, SPX_N, buf, 2 * SPX_N + SPX_ADDR_BYTES); -} - -/** - * Computes the message-dependent randomness R, using a secret seed and an - * optional randomization value as well as the message. - */ -void gen_message_random(unsigned char *R, const unsigned char *sk_prf, - const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx) { - (void)ctx; - shake256incctx s_inc; - - shake256_inc_init(&s_inc); - shake256_inc_absorb(&s_inc, sk_prf, SPX_N); - shake256_inc_absorb(&s_inc, optrand, SPX_N); - shake256_inc_absorb(&s_inc, m, mlen); - shake256_inc_finalize(&s_inc); - shake256_inc_squeeze(R, SPX_N, &s_inc); - shake256_inc_ctx_release(&s_inc); -} - -/** - * Computes the message hash using R, the public key, and the message. - * Outputs the message digest and the index of the leaf. The index is split in - * the tree index and the leaf index, for convenient copying to an address. - */ -void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx) { - (void)ctx; -#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) -#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) -#define SPX_LEAF_BITS SPX_TREE_HEIGHT -#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) -#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) - - unsigned char buf[SPX_DGST_BYTES]; - unsigned char *bufp = buf; - shake256incctx s_inc; - - shake256_inc_init(&s_inc); - shake256_inc_absorb(&s_inc, R, SPX_N); - shake256_inc_absorb(&s_inc, pk, SPX_PK_BYTES); - shake256_inc_absorb(&s_inc, m, mlen); - shake256_inc_finalize(&s_inc); - shake256_inc_squeeze(buf, SPX_DGST_BYTES, &s_inc); - shake256_inc_ctx_release(&s_inc); - - memcpy(digest, bufp, SPX_FORS_MSG_BYTES); - bufp += SPX_FORS_MSG_BYTES; - - - *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); - *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); - bufp += SPX_TREE_BYTES; - - *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); - *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/hash_shakex2.c b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/hash_shakex2.c deleted file mode 100644 index 99571916a2..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/hash_shakex2.c +++ /dev/null @@ -1,52 +0,0 @@ -#include -#include - -#include "hashx2.h" - -#include "address.h" -#include "f1600x2.h" -#include "fips202x2.h" -#include "params.h" - -/* - * 2-way parallel version of prf_addr; takes 2x as much input and output - */ -void prf_addrx2(unsigned char *out0, - unsigned char *out1, - const spx_ctx *ctx, - const uint32_t addrx2[2 * 8]) { - /* As we write and read only a few quadwords, it is more efficient to - * build and extract from the fourway SHAKE256 state by hand. */ - uint64_t state[50] = {0}; - - for (int i = 0; i < SPX_N / 8; i++) { - uint64_t x = load64(ctx->pub_seed + 8 * i); - state[2 * i] = x; - state[2 * i + 1] = x; - } - for (int i = 0; i < 4; i++) { - state[2 * (SPX_N / 8 + i)] = (((uint64_t)addrx2[1 + 2 * i]) << 32) - | (uint64_t)addrx2[2 * i]; - state[2 * (SPX_N / 8 + i) + 1] = (((uint64_t)addrx2[8 + 1 + 2 * i]) << 32) - | (uint64_t)addrx2[8 + 2 * i]; - } - for (int i = 0; i < SPX_N / 8; i++) { - uint64_t x = load64(ctx->sk_seed + 8 * i); - state[2 * (SPX_N / 8 + i + 4)] = x; - state[2 * (SPX_N / 8 + i + 4) + 1] = x; - } - - /* SHAKE domain separator and padding. */ - state[2 * (SPX_N / 4 + 4)] = 0x1f; - state[2 * (SPX_N / 4 + 4) + 1] = 0x1f; - - state[2 * 16] = 0x80ULL << 56; - state[2 * 16 + 1] = 0x80ULL << 56; - - f1600x2(state); - - for (int i = 0; i < SPX_N / 8; i++) { - store64(out0 + 8 * i, state[2 * i]); - store64(out1 + 8 * i, state[2 * i + 1]); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/hashx2.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/hashx2.h deleted file mode 100644 index 99b8873a9b..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/hashx2.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef SPX_HASHX2_H -#define SPX_HASHX2_H - -#include "context.h" -#include "params.h" -#include - -#define prf_addrx2 SPX_NAMESPACE(prf_addrx2) -void prf_addrx2(unsigned char *out0, - unsigned char *out1, - const spx_ctx *ctx, - const uint32_t addrx2[2 * 8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/merkle.c b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/merkle.c deleted file mode 100644 index c94ee23939..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/merkle.c +++ /dev/null @@ -1,64 +0,0 @@ -#include -#include - -#include "merkle.h" - -#include "address.h" -#include "params.h" -#include "utils.h" -#include "utilsx2.h" -#include "wots.h" -#include "wotsx2.h" - -/* - * This generates a Merkle signature (WOTS signature followed by the Merkle - * authentication path). - */ -void merkle_sign(uint8_t *sig, unsigned char *root, - const spx_ctx *ctx, - uint32_t wots_addr[8], uint32_t tree_addr[8], - uint32_t idx_leaf) { - unsigned char *auth_path = sig + SPX_WOTS_BYTES; - uint32_t tree_addrx2[2 * 8] = { 0 }; - int j; - struct leaf_info_x2 info = { 0 }; - unsigned steps[ SPX_WOTS_LEN ]; - - info.wots_sig = sig; - chain_lengths(steps, root); - info.wots_steps = steps; - - for (j = 0; j < 2; j++) { - set_type(&tree_addrx2[8 * j], SPX_ADDR_TYPE_HASHTREE); - set_type(&info.leaf_addr[8 * j], SPX_ADDR_TYPE_WOTS); - set_type(&info.pk_addr[8 * j], SPX_ADDR_TYPE_WOTSPK); - copy_subtree_addr(&tree_addrx2[8 * j], tree_addr); - copy_subtree_addr(&info.leaf_addr[8 * j], wots_addr); - copy_subtree_addr(&info.pk_addr[8 * j], wots_addr); - } - - info.wots_sign_leaf = idx_leaf; - - treehashx2(root, auth_path, ctx, - idx_leaf, 0, - SPX_TREE_HEIGHT, - wots_gen_leafx2, - tree_addrx2, &info); -} - -/* Compute root node of the top-most subtree. */ -void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { - /* We do not need the auth path in key generation, but it simplifies the - code to have just one treehash routine that computes both root and path - in one function. */ - unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; - uint32_t top_tree_addr[8] = {0}; - uint32_t wots_addr[8] = {0}; - - set_layer_addr(top_tree_addr, SPX_D - 1); - set_layer_addr(wots_addr, SPX_D - 1); - - merkle_sign(auth_path, root, ctx, - wots_addr, top_tree_addr, - ~0 /* ~0 means "don't bother generating an auth path */ ); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/merkle.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/merkle.h deleted file mode 100644 index 769cf2e970..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/merkle.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef MERKLE_H_ -#define MERKLE_H_ - -#include - -#include "context.h" -#include "params.h" - -/* Generate a Merkle signature (WOTS signature followed by the Merkle */ -/* authentication path) */ -#define merkle_sign SPX_NAMESPACE(merkle_sign) -void merkle_sign(uint8_t *sig, unsigned char *root, - const spx_ctx *ctx, - uint32_t wots_addr[8], uint32_t tree_addr[8], - uint32_t idx_leaf); - -/* Compute the root node of the top-most subtree. */ -#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) -void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); - -#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/nistapi.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/nistapi.h deleted file mode 100644 index 3cb71afad4..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/nistapi.h +++ /dev/null @@ -1,87 +0,0 @@ -#ifndef SPX_API_H -#define SPX_API_H - -#include -#include - -#include "params.h" - -#define CRYPTO_ALGNAME "SPHINCS+" - -#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES -#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES -#define CRYPTO_BYTES SPX_BYTES -#define CRYPTO_SEEDBYTES (3*SPX_N) - -/* - * Returns the length of a secret key, in bytes - */ -#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) -size_t crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) -size_t crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) -size_t crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) -size_t crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) -int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) -int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) -int crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) -int crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -#define crypto_sign SPX_NAMESPACE(crypto_sign) -int crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) -int crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/params.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/params.h deleted file mode 100644 index a170327186..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/params.h +++ /dev/null @@ -1,56 +0,0 @@ -#ifndef SPX_PARAMS_H -#define SPX_PARAMS_H - -#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSSHAKE192SROBUST_AARCH64_##s - -/* Hash output length in bytes. */ -#define SPX_N 24 -/* Height of the hypertree. */ -#define SPX_FULL_HEIGHT 63 -/* Number of subtree layer. */ -#define SPX_D 7 -/* FORS tree dimensions. */ -#define SPX_FORS_HEIGHT 14 -#define SPX_FORS_TREES 17 -/* Winternitz parameter, */ -#define SPX_WOTS_W 16 - -/* The hash function is defined by linking a different hash.c file, as opposed - to setting a #define constant. */ - -/* For clarity */ -#define SPX_ADDR_BYTES 32 - -/* WOTS parameters. */ -#define SPX_WOTS_LOGW 4 - -#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) - -/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#define SPX_WOTS_LEN2 3 - -#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) -#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) -#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES - -/* Subtree size. */ -#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) - -//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT -// #error SPX_D should always divide SPX_FULL_HEIGHT -//#endif - -/* FORS parameters. */ -#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) -#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) -#define SPX_FORS_PK_BYTES SPX_N - -/* Resulting SPX sizes. */ -#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ - SPX_FULL_HEIGHT * SPX_N) -#define SPX_PK_BYTES (2 * SPX_N) -#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) - -#include "shake_offsets.h" - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/shake_offsets.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/shake_offsets.h deleted file mode 100644 index 6b28d95d91..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/shake_offsets.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef SHAKE_OFFSETS_H_ -#define SHAKE_OFFSETS_H_ - -/* - * Offsets of various fields in the address structure when we use SHAKE as - * the Sphincs+ hash function - */ - -#define SPX_OFFSET_LAYER 3 /* The byte used to specify the Merkle tree layer */ -#define SPX_OFFSET_TREE 8 /* The start of the 8 byte field used to specify the tree */ -#define SPX_OFFSET_TYPE 19 /* The byte used to specify the hash type (reason) */ -#define SPX_OFFSET_KP_ADDR2 22 /* The high byte used to specify the key pair (which one-time signature) */ -#define SPX_OFFSET_KP_ADDR1 23 /* The low byte used to specify the key pair */ -#define SPX_OFFSET_CHAIN_ADDR 27 /* The byte used to specify the chain address (which Winternitz chain) */ -#define SPX_OFFSET_HASH_ADDR 31 /* The byte used to specify the hash address (where in the Winternitz chain) */ -#define SPX_OFFSET_TREE_HGT 27 /* The byte used to specify the height of this node in the FORS or Merkle tree */ -#define SPX_OFFSET_TREE_INDEX 28 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ - -#define SPX_SHAKE 1 - -#endif /* SHAKE_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/sign.c b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/sign.c deleted file mode 100644 index 9d0c7d1b22..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/sign.c +++ /dev/null @@ -1,286 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "context.h" -#include "fors.h" -#include "hash.h" -#include "merkle.h" -#include "nistapi.h" -#include "params.h" -#include "randombytes.h" -#include "thash.h" -#include "utils.h" -#include "wots.h" - -/* - * Returns the length of a secret key, in bytes - */ -size_t crypto_sign_secretkeybytes(void) { - return CRYPTO_SECRETKEYBYTES; -} - -/* - * Returns the length of a public key, in bytes - */ -size_t crypto_sign_publickeybytes(void) { - return CRYPTO_PUBLICKEYBYTES; -} - -/* - * Returns the length of a signature, in bytes - */ -size_t crypto_sign_bytes(void) { - return CRYPTO_BYTES; -} - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t crypto_sign_seedbytes(void) { - return CRYPTO_SEEDBYTES; -} - -/* - * Generates an SPX key pair given a seed of length - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed) { - spx_ctx ctx; - - /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ - memcpy(sk, seed, CRYPTO_SEEDBYTES); - - memcpy(pk, sk + 2 * SPX_N, SPX_N); - - memcpy(ctx.pub_seed, pk, SPX_N); - memcpy(ctx.sk_seed, sk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - /* Compute root node of the top-most subtree. */ - merkle_gen_root(sk + 3 * SPX_N, &ctx); - - // cleanup - free_hash_function(&ctx); - - memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); - - return 0; -} - -/* - * Generates an SPX key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { - uint8_t seed[CRYPTO_SEEDBYTES]; - randombytes(seed, CRYPTO_SEEDBYTES); - crypto_sign_seed_keypair(pk, sk, seed); - - return 0; -} - -/** - * Returns an array containing a detached signature. - */ -int crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - spx_ctx ctx; - - const uint8_t *sk_prf = sk + SPX_N; - const uint8_t *pk = sk + 2 * SPX_N; - - uint8_t optrand[SPX_N]; - uint8_t mhash[SPX_FORS_MSG_BYTES]; - uint8_t root[SPX_N]; - uint32_t i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - - memcpy(ctx.sk_seed, sk, SPX_N); - memcpy(ctx.pub_seed, pk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - set_type(wots_addr, SPX_ADDR_TYPE_WOTS); - set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); - - /* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ - randombytes(optrand, SPX_N); - /* Compute the digest randomization value. */ - gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); - - /* Derive the message digest and leaf index from R, PK and M. */ - hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); - sig += SPX_N; - - set_tree_addr(wots_addr, tree); - set_keypair_addr(wots_addr, idx_leaf); - - /* Sign the message hash using FORS. */ - fors_sign(sig, root, mhash, &ctx, wots_addr); - sig += SPX_FORS_BYTES; - - for (i = 0; i < SPX_D; i++) { - set_layer_addr(tree_addr, i); - set_tree_addr(tree_addr, tree); - - copy_subtree_addr(wots_addr, tree_addr); - set_keypair_addr(wots_addr, idx_leaf); - - merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); - sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); - tree = tree >> SPX_TREE_HEIGHT; - } - - free_hash_function(&ctx); - - *siglen = SPX_BYTES; - - return 0; -} - -/** - * Verifies a detached signature and message under a given public key. - */ -int crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk) { - spx_ctx ctx; - const uint8_t *pub_root = pk + SPX_N; - uint8_t mhash[SPX_FORS_MSG_BYTES]; - uint8_t wots_pk[SPX_WOTS_BYTES]; - uint8_t root[SPX_N]; - uint8_t leaf[SPX_N]; - unsigned int i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - if (siglen != SPX_BYTES) { - return -1; - } - - memcpy(ctx.pub_seed, pk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - set_type(wots_addr, SPX_ADDR_TYPE_WOTS); - set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); - set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); - - /* Derive the message digest and leaf index from R || PK || M. */ - /* The additional SPX_N is a result of the hash domain separator. */ - hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); - sig += SPX_N; - - /* Layer correctly defaults to 0, so no need to set_layer_addr */ - set_tree_addr(wots_addr, tree); - set_keypair_addr(wots_addr, idx_leaf); - - fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); - sig += SPX_FORS_BYTES; - - /* For each subtree.. */ - for (i = 0; i < SPX_D; i++) { - set_layer_addr(tree_addr, i); - set_tree_addr(tree_addr, tree); - - copy_subtree_addr(wots_addr, tree_addr); - set_keypair_addr(wots_addr, idx_leaf); - - copy_keypair_addr(wots_pk_addr, wots_addr); - - /* The WOTS public key is only correct if the signature was correct. */ - /* Initially, root is the FORS pk, but on subsequent iterations it is - the root of the subtree below the currently processed subtree. */ - wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); - sig += SPX_WOTS_BYTES; - - /* Compute the leaf node using the WOTS public key. */ - thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); - - /* Compute the root node of this subtree. */ - compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, - &ctx, tree_addr); - sig += SPX_TREE_HEIGHT * SPX_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); - tree = tree >> SPX_TREE_HEIGHT; - } - - // cleanup - free_hash_function(&ctx); - - /* Check if the root node equals the root node in the public key. */ - if (memcmp(root, pub_root, SPX_N) != 0) { - return -1; - } - - return 0; -} - - -/** - * Returns an array containing the signature followed by the message. - */ -int crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk) { - size_t siglen; - - crypto_sign_signature(sm, &siglen, m, mlen, sk); - - memmove(sm + SPX_BYTES, m, mlen); - *smlen = siglen + mlen; - - return 0; -} - -/** - * Verifies a given signature-message pair under a given public key. - */ -int crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk) { - /* The API caller does not necessarily know what size a signature should be - but SPHINCS+ signatures are always exactly SPX_BYTES. */ - if (smlen < SPX_BYTES) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - *mlen = smlen - SPX_BYTES; - - if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - /* If verification was successful, move the message to the right place. */ - memmove(m, sm + SPX_BYTES, *mlen); - - return 0; -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/thash.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/thash.h deleted file mode 100644 index 8687ccfb4d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/thash.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef SPX_THASH_H -#define SPX_THASH_H - -#include "context.h" -#include "params.h" - -#include - -#define thash SPX_NAMESPACE(thash) -void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/thash_shake_robustx2.c b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/thash_shake_robustx2.c deleted file mode 100644 index 454fc0f4e2..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/thash_shake_robustx2.c +++ /dev/null @@ -1,112 +0,0 @@ -#include -#include - -#include "thash.h" -#include "thashx2.h" - -#include "address.h" -#include "params.h" -#include "utils.h" - -#include "f1600x2.h" -#include "fips202x2.h" - - -void thash(unsigned char *out, - const unsigned char *in, - unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]) { - uint32_t addrx2 [2 * 8] = { - addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], addr[6], addr[7], - addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], addr[6], addr[7] - }; - thashx2(out, out, in, in, inblocks, ctx, addrx2); -} - -/** - * 2-way parallel version of thash; takes 2x as much input and output - */ -void thashx2(unsigned char *out0, - unsigned char *out1, - const unsigned char *in0, - const unsigned char *in1, - unsigned int inblocks, - const spx_ctx *ctx, uint32_t addrx2[2 * 8]) { - if (inblocks == 1 || inblocks == 2) { - /* As we write and read only a few quadwords, it is more efficient to - * build and extract from the twoway SHAKE256 state by hand. */ - uint64_t state[50] = {0}; - uint64_t state2[50]; - - for (int i = 0; i < SPX_N / 8; i++) { - uint64_t x = load64(ctx->pub_seed + 8 * i); - state[2 * i] = x; - state[2 * i + 1] = x; - } - for (int i = 0; i < 4; i++) { - state[2 * (SPX_N / 8 + i)] = (((uint64_t)addrx2[1 + 2 * i]) << 32) - | (uint64_t)addrx2[2 * i]; - state[2 * (SPX_N / 8 + i) + 1] = (((uint64_t)addrx2[8 + 1 + 2 * i]) << 32) - | (uint64_t)addrx2[8 + 2 * i]; - } - - /* Domain separator and padding. */ - state[2 * 16] = 0x80ULL << 56; - state[2 * 16 + 1] = 0x80ULL << 56; - - state[2 * ((SPX_N / 8) + 4)] ^= 0x1f; - state[2 * ((SPX_N / 8) + 4) + 1] ^= 0x1f; - - /* We will permutate state2 with f1600x2 to compute the bitmask, - * but first we'll copy it to state2 which will be used to compute - * the final output, as its input is almost identical. */ - memcpy(state2, state, 400); - - f1600x2(state); - - /* By copying from state, state2 already contains the pub_seed - * and address. We just need to copy in the input blocks xorred with - * the bitmask we just computed. */ - for (unsigned int i = 0; i < (SPX_N / 8) * inblocks; i++) { - state2[2 * (SPX_N / 8 + 4 + i)] = state[2 * i] ^ load64(in0 + 8 * i); - state2[2 * (SPX_N / 8 + 4 + i) + 1] = state[2 * i + 1] ^ load64(in1 + 8 * i); - } - - /* Domain separator and start of padding. Note that the quadwords - * around are already zeroed for state from which we copied. - * We do a XOR instead of a set as this might be the 16th quadword - * when N=32 and inblocks=2, which already contains the end - * of the padding. */ - state2[2 * ((SPX_N / 8) * (1 + inblocks) + 4)] ^= 0x1f; - state2[2 * ((SPX_N / 8) * (1 + inblocks) + 4) + 1] ^= 0x1f; - - f1600x2(state2); - - for (int i = 0; i < SPX_N / 8; i++) { - store64(out0 + 8 * i, state2[2 * i]); - store64(out1 + 8 * i, state2[2 * i + 1]); - } - } else { - PQCLEAN_VLA(unsigned char, buf0, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); - PQCLEAN_VLA(unsigned char, buf1, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); - PQCLEAN_VLA(unsigned char, bitmask0, inblocks * SPX_N); - PQCLEAN_VLA(unsigned char, bitmask1, inblocks * SPX_N); - unsigned int i; - - memcpy(buf0, ctx->pub_seed, SPX_N); - memcpy(buf1, ctx->pub_seed, SPX_N); - memcpy(buf0 + SPX_N, addrx2 + 0 * 8, SPX_ADDR_BYTES); - memcpy(buf1 + SPX_N, addrx2 + 1 * 8, SPX_ADDR_BYTES); - - shake256x2(bitmask0, bitmask1, inblocks * SPX_N, - buf0, buf1, SPX_N + SPX_ADDR_BYTES); - - for (i = 0; i < inblocks * SPX_N; i++) { - buf0[SPX_N + SPX_ADDR_BYTES + i] = in0[i] ^ bitmask0[i]; - buf1[SPX_N + SPX_ADDR_BYTES + i] = in1[i] ^ bitmask1[i]; - } - - shake256x2(out0, out1, SPX_N, - buf0, buf1, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/thashx2.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/thashx2.h deleted file mode 100644 index 040375e618..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/thashx2.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef SPX_THASHX2_H -#define SPX_THASHX2_H - -#include "context.h" -#include "params.h" -#include - -#define thashx2 SPX_NAMESPACE(thashx2) -void thashx2(unsigned char *out0, - unsigned char *out1, - const unsigned char *in0, - const unsigned char *in1, - unsigned int inblocks, - const spx_ctx *ctx, uint32_t addrx2[2 * 8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/utils.c b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/utils.c deleted file mode 100644 index 177b541fb9..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/utils.c +++ /dev/null @@ -1,148 +0,0 @@ -#include - -#include "utils.h" - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "thash.h" - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void ull_to_bytes(unsigned char *out, unsigned int outlen, - unsigned long long in) { - int i; - - /* Iterate over out in decreasing order, for big-endianness. */ - for (i = (signed int)outlen - 1; i >= 0; i--) { - out[i] = in & 0xff; - in = in >> 8; - } -} - -void u32_to_bytes(unsigned char *out, uint32_t in) { - out[0] = (unsigned char)(in >> 24); - out[1] = (unsigned char)(in >> 16); - out[2] = (unsigned char)(in >> 8); - out[3] = (unsigned char)in; -} - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { - unsigned long long retval = 0; - unsigned int i; - - for (i = 0; i < inlen; i++) { - retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); - } - return retval; -} - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void compute_root(unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const spx_ctx *ctx, uint32_t addr[8]) { - uint32_t i; - unsigned char buffer[2 * SPX_N]; - - /* If leaf_idx is odd (last bit = 1), current path element is a right child - and auth_path has to go left. Otherwise it is the other way around. */ - if (leaf_idx & 1) { - memcpy(buffer + SPX_N, leaf, SPX_N); - memcpy(buffer, auth_path, SPX_N); - } else { - memcpy(buffer, leaf, SPX_N); - memcpy(buffer + SPX_N, auth_path, SPX_N); - } - auth_path += SPX_N; - - for (i = 0; i < tree_height - 1; i++) { - leaf_idx >>= 1; - idx_offset >>= 1; - /* Set the address of the node we're creating. */ - set_tree_height(addr, i + 1); - set_tree_index(addr, leaf_idx + idx_offset); - - /* Pick the right or left neighbor, depending on parity of the node. */ - if (leaf_idx & 1) { - thash(buffer + SPX_N, buffer, 2, ctx, addr); - memcpy(buffer, auth_path, SPX_N); - } else { - thash(buffer, buffer, 2, ctx, addr); - memcpy(buffer + SPX_N, auth_path, SPX_N); - } - auth_path += SPX_N; - } - - /* The last iteration is exceptional; we do not copy an auth_path node. */ - leaf_idx >>= 1; - idx_offset >>= 1; - set_tree_height(addr, tree_height); - set_tree_index(addr, leaf_idx + idx_offset); - thash(root, buffer, 2, ctx, addr); -} - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const spx_ctx * /* ctx */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), - uint32_t tree_addr[8]) { - PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); - PQCLEAN_VLA(unsigned int, heights, tree_height + 1); - unsigned int offset = 0; - uint32_t idx; - uint32_t tree_idx; - - for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { - /* Add the next leaf node to the stack. */ - gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); - offset++; - heights[offset - 1] = 0; - - /* If this is a node we need for the auth path.. */ - if ((leaf_idx ^ 0x1) == idx) { - memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); - } - - /* While the top-most nodes are of equal height.. */ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { - /* Compute index of the new node, in the next layer. */ - tree_idx = (idx >> (heights[offset - 1] + 1)); - - /* Set the address of the node we're creating. */ - set_tree_height(tree_addr, heights[offset - 1] + 1); - set_tree_index(tree_addr, - tree_idx + (idx_offset >> (heights[offset - 1] + 1))); - /* Hash the top-most nodes from the stack together. */ - thash(stack + (offset - 2)*SPX_N, - stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); - offset--; - /* Note that the top-most node is now one layer higher. */ - heights[offset - 1]++; - - /* If this is a node we need for the auth path.. */ - if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_path + heights[offset - 1]*SPX_N, - stack + (offset - 1)*SPX_N, SPX_N); - } - } - } - memcpy(root, stack, SPX_N); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/utils.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/utils.h deleted file mode 100644 index 64f5d5a53a..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/utils.h +++ /dev/null @@ -1,58 +0,0 @@ -#ifndef SPX_UTILS_H -#define SPX_UTILS_H - -#include - -#include "compat.h" -#include "context.h" -#include "params.h" - - -/* To support MSVC use alloca() instead of VLAs. See #20. */ - - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) -void ull_to_bytes(unsigned char *out, unsigned int outlen, - unsigned long long in); -#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) -void u32_to_bytes(unsigned char *out, uint32_t in); - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) -unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -#define compute_root SPX_NAMESPACE(compute_root) -void compute_root(unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const spx_ctx *ctx, uint32_t addr[8]); - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -#define treehash SPX_NAMESPACE(treehash) -void treehash(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const spx_ctx *ctx /* ctx */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), - uint32_t tree_addr[8]); - - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/utilsx2.c b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/utilsx2.c deleted file mode 100644 index 8736474e4f..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/utilsx2.c +++ /dev/null @@ -1,130 +0,0 @@ -#include - -#include "utilsx2.h" - -#include "address.h" -#include "params.h" -#include "thashx2.h" -#include "utils.h" - -/* - * Generate the entire Merkle tree, computing the authentication path for leaf_idx, - * and the resulting root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) - * - * This expects tree_addrx2 to be initialized to 2 parallel addr structures for - * the Merkle tree nodes - * - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - * - * This works by using the standard Merkle tree building algorithm, except - * that each 'node' tracked is actually 2 consecutive nodes in the real tree. - * When we combine two logical nodes AB and WX, we perform the H - * operation on adjacent real nodes, forming the parent logical node - * (AB)(WX) - * - * When we get to the top level of the real tree (where there is only - * one logical node), we continue this operation one more time; the right - * most real node will by the actual root (and the other node will be - * garbage). We follow the same thashx2 logic so that the 'extract - * authentication path components' part of the loop is still executed (and - * to simplify the code somewhat) - */ -void treehashx2(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, - uint32_t tree_height, - void (*gen_leafx2)( - unsigned char * /* Where to write the leaves */, - const spx_ctx *, - uint32_t idx, void *info), - uint32_t tree_addrx2[2 * 8], - void *info) { - /* This is where we keep the intermediate nodes */ - unsigned char stackx2[tree_height * 2 * SPX_N]; - uint32_t left_adj = 0, prev_left_adj = 0; /* When we're doing the top */ - /* level, the left-most part of the tree isn't at the beginning */ - /* of current[]. These give the offset of the actual start */ - - uint32_t idx; - uint32_t max_idx = (1 << (tree_height - 1)) - 1; - for (idx = 0;; idx++) { - unsigned char current[2 * SPX_N]; /* Current logical node */ - gen_leafx2( current, ctx, 2 * idx + idx_offset, - info ); - - /* Now combine the freshly generated right node with previously */ - /* generated left ones */ - uint32_t internal_idx_offset = idx_offset; - uint32_t internal_idx = idx; - uint32_t internal_leaf = leaf_idx; - uint32_t h; /* The height we are in the Merkle tree */ - for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { - - /* Special processing if we're at the top of the tree */ - if (h >= tree_height - 1) { - if (h == tree_height) { - /* We hit the root; return it */ - memcpy( root, ¤t[1 * SPX_N], SPX_N ); - return; - } - /* The tree indexing logic is a bit off in this case */ - /* Adjust it so that the left-most node of the part of */ - /* the tree that we're processing has index 0 */ - prev_left_adj = left_adj; - left_adj = 2 - (1 << (tree_height - h - 1)); - } - - /* Check if we hit the top of the tree */ - if (h == tree_height) { - /* We hit the root; return it */ - memcpy( root, ¤t[1 * SPX_N], SPX_N ); - return; - } - - /* - * Check if one of the nodes we have is a part of the - * authentication path; if it is, write it out - */ - if ((((internal_idx << 1) ^ internal_leaf) & ~0x1) == 0) { - memcpy( &auth_path[ h * SPX_N ], - ¤t[(((internal_leaf & 1) ^ 1) + prev_left_adj) * SPX_N], - SPX_N ); - } - - /* - * Check if we're at a left child; if so, stop going up the stack - * Exception: if we've reached the end of the tree, keep on going - * (so we combine the last 2 nodes into the one root node in two - * more iterations) - */ - if ((internal_idx & 1) == 0 && idx < max_idx) { - break; - } - - /* Ok, we're at a right node (or doing the top 3 levels) */ - /* Now combine the left and right logical nodes together */ - - /* Set the address of the node we're creating. */ - int j; - internal_idx_offset >>= 1; - for (j = 0; j < 2; j++) { - set_tree_height(tree_addrx2 + j * 8, h + 1); - set_tree_index(tree_addrx2 + j * 8, - (2 / 2) * (internal_idx & ~1) + j - left_adj + internal_idx_offset ); - } - unsigned char *left = &stackx2[h * 2 * SPX_N]; - thashx2( ¤t[0 * SPX_N], - ¤t[1 * SPX_N], - &left [0 * SPX_N], - ¤t[0 * SPX_N], - 2, ctx, tree_addrx2); - } - - /* We've hit a left child; save the current for when we get the */ - /* corresponding right right */ - memcpy( &stackx2[h * 2 * SPX_N], current, 2 * SPX_N); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/utilsx2.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/utilsx2.h deleted file mode 100644 index e09faddc43..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/utilsx2.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef SPX_UTILSX2_H -#define SPX_UTILSX2_H - -#include - -#include "context.h" -#include "params.h" - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - * - * This implementation uses SIMD to compute internal nodes 2 at a time (in - * parallel) - */ -#define treehashx2 SPX_NAMESPACE(treehashx2) -void treehashx2(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leafx2)( - unsigned char * /* Where to write the leaves */, - const spx_ctx * /* ctx */, - uint32_t addr_idx, void *info), - uint32_t tree_addrx2[2 * 8], void *info); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/wots.c b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/wots.c deleted file mode 100644 index 3babe45e95..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/wots.c +++ /dev/null @@ -1,259 +0,0 @@ -#include -#include - -#include "wots.h" -#include "wotsx2.h" - -#include "address.h" -#include "hash.h" -#include "hashx2.h" -#include "params.h" -#include "thashx2.h" -#include "utils.h" -#include "utilsx2.h" - -// TODO clarify address expectations, and make them more uniform. -// TODO i.e. do we expect types to be set already? -// TODO and do we expect modifications or copies? - -/** - * Computes up the chains - */ -static void gen_chains( - unsigned char *out, - const unsigned char *in, - unsigned int start[SPX_WOTS_LEN], - const unsigned int steps[SPX_WOTS_LEN], - const spx_ctx *ctx, - uint32_t addr[8]) { - uint32_t i, j, k, idx, watching; - int done; - unsigned char empty[SPX_N]; - unsigned char *bufs[4]; - uint32_t addrs[8 * 2]; - - int l; - uint16_t counts[SPX_WOTS_W] = { 0 }; - uint16_t idxs[SPX_WOTS_LEN]; - uint16_t total, newTotal; - - /* set addrs = {addr, addr} */ - for (j = 0; j < 2; j++) { - memcpy(addrs + j * 8, addr, sizeof(uint32_t) * 8); - } - - /* Initialize out with the value at position 'start'. */ - memcpy(out, in, SPX_WOTS_LEN * SPX_N); - - /* Sort the chains in reverse order by steps using counting sort. */ - for (i = 0; i < SPX_WOTS_LEN; i++) { - counts[steps[i]]++; - } - total = 0; - for (l = SPX_WOTS_W - 1; l >= 0; l--) { - newTotal = counts[l] + total; - counts[l] = total; - total = newTotal; - } - for (i = 0; i < SPX_WOTS_LEN; i++) { - idxs[counts[steps[i]]] = i; - counts[steps[i]]++; - } - - /* We got our work cut out for us: do it! */ - for (i = 0; i < SPX_WOTS_LEN; i += 2) { - for (j = 0; j < 2 && i + j < SPX_WOTS_LEN; j++) { - idx = idxs[i + j]; - set_chain_addr(addrs + j * 8, idx); - bufs[j] = out + SPX_N * idx; - } - - /* As the chains are sorted in reverse order, we know that the first - * chain is the longest and the last one is the shortest. We keep - * an eye on whether the last chain is done and then on the one before, - * et cetera. */ - watching = 1; - done = 0; - while (i + watching >= SPX_WOTS_LEN) { - bufs[watching] = &empty[0]; - watching--; - } - - for (k = 0;; k++) { - while (k == steps[idxs[i + watching]]) { - bufs[watching] = &empty[0]; - if (watching == 0) { - done = 1; - break; - } - watching--; - } - if (done) { - break; - } - for (j = 0; j < watching + 1; j++) { - set_hash_addr(addrs + j * 8, k + start[idxs[i + j]]); - } - - thashx2(bufs[0], bufs[1], - bufs[0], bufs[1], 1, ctx, addrs); - } - } -} - -/** - * base_w algorithm as described in draft. - * Interprets an array of bytes as integers in base w. - * This only works when log_w is a divisor of 8. - */ -static void base_w(unsigned int *output, const int out_len, - const unsigned char *input) { - int in = 0; - int out = 0; - unsigned char total = 0; - int bits = 0; - int consumed; - - for (consumed = 0; consumed < out_len; consumed++) { - if (bits == 0) { - total = input[in]; - in++; - bits += 8; - } - bits -= SPX_WOTS_LOGW; - output[out] = (total >> bits) & (SPX_WOTS_W - 1); - out++; - } -} - -/* Computes the WOTS+ checksum over a message (in base_w). */ -static void wots_checksum(unsigned int *csum_base_w, - const unsigned int *msg_base_w) { - unsigned int csum = 0; - unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; - unsigned int i; - - /* Compute checksum. */ - for (i = 0; i < SPX_WOTS_LEN1; i++) { - csum += SPX_WOTS_W - 1 - msg_base_w[i]; - } - - /* Convert checksum to base_w. */ - /* Make sure expected empty zero bits are the least significant bits. */ - csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); - ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); - base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); -} - -/* Takes a message and derives the matching chain lengths. */ -void chain_lengths(unsigned int *lengths, const unsigned char *msg) { - base_w(lengths, SPX_WOTS_LEN1, msg); - wots_checksum(lengths + SPX_WOTS_LEN1, lengths); -} - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const spx_ctx *ctx, uint32_t addr[8]) { - unsigned int steps[SPX_WOTS_LEN]; - unsigned int start[SPX_WOTS_LEN]; - uint32_t i; - - chain_lengths(start, msg); - - for (i = 0; i < SPX_WOTS_LEN; i++) { - steps[i] = SPX_WOTS_W - 1 - start[i]; - } - - gen_chains(pk, sig, start, steps, ctx, addr); -} - -/* - * This generates 2 sequential WOTS public keys - * It also generates the WOTS signature if leaf_info indicates - * that we're signing with one of these WOTS keys - */ -void wots_gen_leafx2(unsigned char *dest, - const spx_ctx *ctx, - uint32_t leaf_idx, void *v_info) { - struct leaf_info_x2 *info = v_info; - uint32_t *leaf_addr = info->leaf_addr; - uint32_t *pk_addr = info->pk_addr; - unsigned int i, j, k; - unsigned char pk_buffer[ 2 * SPX_WOTS_BYTES ]; - unsigned wots_offset = SPX_WOTS_BYTES; - unsigned char *buffer; - uint32_t wots_k_mask; - unsigned wots_sign_index; - - if (((leaf_idx ^ info->wots_sign_leaf) & ~1) == 0) { - /* We're traversing the leaf that's signing; generate the WOTS */ - /* signature */ - wots_k_mask = 0; - wots_sign_index = info->wots_sign_leaf & 1; /* Which of of the 2 */ - /* slots do the signatures come from */ - } else { - /* Nope, we're just generating pk's; turn off the signature logic */ - wots_k_mask = ~0; - wots_sign_index = 0; - } - - for (j = 0; j < 2; j++) { - set_keypair_addr( leaf_addr + j * 8, leaf_idx + j ); - set_keypair_addr( pk_addr + j * 8, leaf_idx + j ); - } - - for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { - uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k to */ - /* the step if we're generating a signature, ~0 if we're not */ - - /* Start with the secret seed */ - for (j = 0; j < 2; j++) { - set_chain_addr(leaf_addr + j * 8, i); - set_hash_addr(leaf_addr + j * 8, 0); - set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTSPRF); - } - prf_addrx2(buffer + 0 * wots_offset, - buffer + 1 * wots_offset, - ctx, leaf_addr); - for (j = 0; j < 2; j++) { - set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTS); - } - - /* Iterate down the WOTS chain */ - for (k = 0;; k++) { - /* Check if one of the values we have needs to be saved as a */ - /* part of the WOTS signature */ - if (k == wots_k) { - memcpy( info->wots_sig + i * SPX_N, - buffer + wots_sign_index * wots_offset, SPX_N ); - } - - /* Check if we hit the top of the chain */ - if (k == SPX_WOTS_W - 1) { - break; - } - - /* Iterate one step on all 4 chains */ - for (j = 0; j < 2; j++) { - set_hash_addr(leaf_addr + j * 8, k); - } - thashx2(buffer + 0 * wots_offset, - buffer + 1 * wots_offset, - buffer + 0 * wots_offset, - buffer + 1 * wots_offset, - 1, ctx, leaf_addr); - } - } - - /* Do the final thash to generate the public keys */ - thashx2(dest + 0 * SPX_N, - dest + 1 * SPX_N, - pk_buffer + 0 * wots_offset, - pk_buffer + 1 * wots_offset, - SPX_WOTS_LEN, ctx, pk_addr); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/wots.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/wots.h deleted file mode 100644 index 4e7692eeef..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/wots.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef SPX_WOTS_H -#define SPX_WOTS_H - -#include - -#include "context.h" -#include "params.h" - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) -void wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const spx_ctx *ctx, uint32_t addr[8]); - -/* - * Compute the chain lengths needed for a given message hash - */ -#define chain_lengths SPX_NAMESPACE(chain_lengths) -void chain_lengths(unsigned int *lengths, const unsigned char *msg); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/wotsx2.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/wotsx2.h deleted file mode 100644 index b58bb61f84..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_aarch64/wotsx2.h +++ /dev/null @@ -1,40 +0,0 @@ -#ifndef WOTSX2_H_ -#define WOTSX2_H_ - -#include "params.h" -#include - -/* - * This is here to provide an interface to the internal wots_gen_leafx2 - * routine. While this routine is not referenced in the package outside of - * wots.c, it is called from the stand-alone benchmark code to characterize - * the performance - */ -struct leaf_info_x2 { - unsigned char *wots_sig; - uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ - uint32_t *wots_steps; - uint32_t leaf_addr[2 * 8]; - uint32_t pk_addr[2 * 8]; -}; - -/* Macro to set the leaf_info to something 'benign', that is, it would */ -/* run with the same time as it does during the real signing process */ -/* Used only by the benchmark code */ -#define INITIALIZE_LEAF_INFO_X2(info, addr, step_buffer) { \ - (info).wots_sig = 0; \ - (info).wots_sign_leaf = ~0; \ - (info).wots_steps = step_buffer; \ - int i; \ - for (i=0; i<2; i++) { \ - memcpy( &(info).leaf_addr[8*i], addr, 32 ); \ - memcpy( &(info).pk_addr[8*i], addr, 32 ); \ - } \ - } - -#define wots_gen_leafx2 SPX_NAMESPACE(wots_gen_leafx2) -void wots_gen_leafx2(unsigned char *dest, - const spx_ctx *ctx, - uint32_t leaf_idx, void *v_info); - -#endif /* WOTSX2_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/LICENSE b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/LICENSE deleted file mode 100644 index 670154e353..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/LICENSE +++ /dev/null @@ -1,116 +0,0 @@ -CC0 1.0 Universal - -Statement of Purpose - -The laws of most jurisdictions throughout the world automatically confer -exclusive Copyright and Related Rights (defined below) upon the creator and -subsequent owner(s) (each and all, an "owner") of an original work of -authorship and/or a database (each, a "Work"). - -Certain owners wish to permanently relinquish those rights to a Work for the -purpose of contributing to a commons of creative, cultural and scientific -works ("Commons") that the public can reliably and without fear of later -claims of infringement build upon, modify, incorporate in other works, reuse -and redistribute as freely as possible in any form whatsoever and for any -purposes, including without limitation commercial purposes. These owners may -contribute to the Commons to promote the ideal of a free culture and the -further production of creative, cultural and scientific works, or to gain -reputation or greater distribution for their Work in part through the use and -efforts of others. - -For these and/or other purposes and motivations, and without any expectation -of additional consideration or compensation, the person associating CC0 with a -Work (the "Affirmer"), to the extent that he or she is an owner of Copyright -and Related Rights in the Work, voluntarily elects to apply CC0 to the Work -and publicly distribute the Work under its terms, with knowledge of his or her -Copyright and Related Rights in the Work and the meaning and intended legal -effect of CC0 on those rights. - -1. Copyright and Related Rights. A Work made available under CC0 may be -protected by copyright and related or neighboring rights ("Copyright and -Related Rights"). Copyright and Related Rights include, but are not limited -to, the following: - - i. the right to reproduce, adapt, distribute, perform, display, communicate, - and translate a Work; - - ii. moral rights retained by the original author(s) and/or performer(s); - - iii. publicity and privacy rights pertaining to a person's image or likeness - depicted in a Work; - - iv. rights protecting against unfair competition in regards to a Work, - subject to the limitations in paragraph 4(a), below; - - v. rights protecting the extraction, dissemination, use and reuse of data in - a Work; - - vi. database rights (such as those arising under Directive 96/9/EC of the - European Parliament and of the Council of 11 March 1996 on the legal - protection of databases, and under any national implementation thereof, - including any amended or successor version of such directive); and - - vii. other similar, equivalent or corresponding rights throughout the world - based on applicable law or treaty, and any national implementations thereof. - -2. Waiver. To the greatest extent permitted by, but not in contravention of, -applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and -unconditionally waives, abandons, and surrenders all of Affirmer's Copyright -and Related Rights and associated claims and causes of action, whether now -known or unknown (including existing as well as future claims and causes of -action), in the Work (i) in all territories worldwide, (ii) for the maximum -duration provided by applicable law or treaty (including future time -extensions), (iii) in any current or future medium and for any number of -copies, and (iv) for any purpose whatsoever, including without limitation -commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes -the Waiver for the benefit of each member of the public at large and to the -detriment of Affirmer's heirs and successors, fully intending that such Waiver -shall not be subject to revocation, rescission, cancellation, termination, or -any other legal or equitable action to disrupt the quiet enjoyment of the Work -by the public as contemplated by Affirmer's express Statement of Purpose. - -3. Public License Fallback. Should any part of the Waiver for any reason be -judged legally invalid or ineffective under applicable law, then the Waiver -shall be preserved to the maximum extent permitted taking into account -Affirmer's express Statement of Purpose. In addition, to the extent the Waiver -is so judged Affirmer hereby grants to each affected person a royalty-free, -non transferable, non sublicensable, non exclusive, irrevocable and -unconditional license to exercise Affirmer's Copyright and Related Rights in -the Work (i) in all territories worldwide, (ii) for the maximum duration -provided by applicable law or treaty (including future time extensions), (iii) -in any current or future medium and for any number of copies, and (iv) for any -purpose whatsoever, including without limitation commercial, advertising or -promotional purposes (the "License"). The License shall be deemed effective as -of the date CC0 was applied by Affirmer to the Work. Should any part of the -License for any reason be judged legally invalid or ineffective under -applicable law, such partial invalidity or ineffectiveness shall not -invalidate the remainder of the License, and in such case Affirmer hereby -affirms that he or she will not (i) exercise any of his or her remaining -Copyright and Related Rights in the Work or (ii) assert any associated claims -and causes of action with respect to the Work, in either case contrary to -Affirmer's express Statement of Purpose. - -4. Limitations and Disclaimers. - - a. No trademark or patent rights held by Affirmer are waived, abandoned, - surrendered, licensed or otherwise affected by this document. - - b. Affirmer offers the Work as-is and makes no representations or warranties - of any kind concerning the Work, express, implied, statutory or otherwise, - including without limitation warranties of title, merchantability, fitness - for a particular purpose, non infringement, or the absence of latent or - other defects, accuracy, or the present or absence of errors, whether or not - discoverable, all to the greatest extent permissible under applicable law. - - c. Affirmer disclaims responsibility for clearing rights of other persons - that may apply to the Work or any use thereof, including without limitation - any person's Copyright and Related Rights in the Work. Further, Affirmer - disclaims responsibility for obtaining any necessary consents, permissions - or other rights required for any use of the Work. - - d. Affirmer understands and acknowledges that Creative Commons is not a - party to this document and has no duty or obligation with respect to this - CC0 or use of the Work. - -For more information, please see - diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/address.c b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/address.c deleted file mode 100644 index d49d9f3b6b..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/address.c +++ /dev/null @@ -1,95 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "utils.h" - -/* - * Specify which level of Merkle tree (the "layer") we're working on - */ -void set_layer_addr(uint32_t addr[8], uint32_t layer) { - ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; -} - -/* - * Specify which Merkle tree within the level (the "tree address") we're working on - */ -void set_tree_addr(uint32_t addr[8], uint64_t tree) { - ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); -} - -/* - * Specify the reason we'll use this address structure for, that is, what - * hash will we compute with it. This is used so that unrelated types of - * hashes don't accidentally get the same address structure. The type will be - * one of the SPX_ADDR_TYPE constants - */ -void set_type(uint32_t addr[8], uint32_t type) { - ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; -} - -/* - * Copy the layer and tree fields of the address structure. This is used - * when we're doing multiple types of hashes within the same Merkle tree - */ -void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { - memcpy( out, in, SPX_OFFSET_TREE + 8 ); -} - -/* These functions are used for OTS addresses. */ - -/* - * Specify which Merkle leaf we're working on; that is, which OTS keypair - * we're talking about. - */ -void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { - /* We have > 256 OTS at the bottom of the Merkle tree; to specify */ - /* which one, we'd need to express it in two bytes */ - ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR2] = (unsigned char)(keypair >> 8); - ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; -} - -/* - * Copy the layer, tree and keypair fields of the address structure. This is - * used when we're doing multiple things within the same OTS keypair - */ -void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { - memcpy( out, in, SPX_OFFSET_TREE + 8 ); - ((unsigned char *)out)[SPX_OFFSET_KP_ADDR2] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR2]; - ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; -} - -/* - * Specify which Merkle chain within the OTS we're working with - * (the chain address) - */ -void set_chain_addr(uint32_t addr[8], uint32_t chain) { - ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; -} - -/* - * Specify where in the Merkle chain we are -* (the hash address) - */ -void set_hash_addr(uint32_t addr[8], uint32_t hash) { - ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; -} - -/* These functions are used for all hash tree addresses (including FORS). */ - -/* - * Specify the height of the node in the Merkle/FORS tree we are in - * (the tree height) - */ -void set_tree_height(uint32_t addr[8], uint32_t tree_height) { - ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; -} - -/* - * Specify the distance from the left edge of the node in the Merkle/FORS tree - * (the tree index) - */ -void set_tree_index(uint32_t addr[8], uint32_t tree_index) { - u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/address.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/address.h deleted file mode 100644 index 24a84eb40c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/address.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef SPX_ADDRESS_H -#define SPX_ADDRESS_H - -#include - -#include "params.h" - -/* The hash types that are passed to set_type */ -#define SPX_ADDR_TYPE_WOTS 0 -#define SPX_ADDR_TYPE_WOTSPK 1 -#define SPX_ADDR_TYPE_HASHTREE 2 -#define SPX_ADDR_TYPE_FORSTREE 3 -#define SPX_ADDR_TYPE_FORSPK 4 -#define SPX_ADDR_TYPE_WOTSPRF 5 -#define SPX_ADDR_TYPE_FORSPRF 6 - -#define set_layer_addr SPX_NAMESPACE(set_layer_addr) -void set_layer_addr(uint32_t addr[8], uint32_t layer); - -#define set_tree_addr SPX_NAMESPACE(set_tree_addr) -void set_tree_addr(uint32_t addr[8], uint64_t tree); - -#define set_type SPX_NAMESPACE(set_type) -void set_type(uint32_t addr[8], uint32_t type); - -/* Copies the layer and tree part of one address into the other */ -#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) -void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for WOTS and FORS addresses. */ - -#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) -void set_keypair_addr(uint32_t addr[8], uint32_t keypair); - -#define set_chain_addr SPX_NAMESPACE(set_chain_addr) -void set_chain_addr(uint32_t addr[8], uint32_t chain); - -#define set_hash_addr SPX_NAMESPACE(set_hash_addr) -void set_hash_addr(uint32_t addr[8], uint32_t hash); - -#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) -void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for all hash tree addresses (including FORS). */ - -#define set_tree_height SPX_NAMESPACE(set_tree_height) -void set_tree_height(uint32_t addr[8], uint32_t tree_height); - -#define set_tree_index SPX_NAMESPACE(set_tree_index) -void set_tree_index(uint32_t addr[8], uint32_t tree_index); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/api.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/api.h deleted file mode 100644 index 192201f167..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/api.h +++ /dev/null @@ -1,77 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE192SROBUST_AVX2_API_H -#define PQCLEAN_SPHINCSSHAKE192SROBUST_AVX2_API_H - -#include -#include - -#define PQCLEAN_SPHINCSSHAKE192SROBUST_AVX2_CRYPTO_ALGNAME "SPHINCS+-shake-192s-robust" - -#define PQCLEAN_SPHINCSSHAKE192SROBUST_AVX2_CRYPTO_SECRETKEYBYTES 96 -#define PQCLEAN_SPHINCSSHAKE192SROBUST_AVX2_CRYPTO_PUBLICKEYBYTES 48 -#define PQCLEAN_SPHINCSSHAKE192SROBUST_AVX2_CRYPTO_BYTES 16224 - -#define PQCLEAN_SPHINCSSHAKE192SROBUST_AVX2_CRYPTO_SEEDBYTES 72 - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE192SROBUST_AVX2_crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE192SROBUST_AVX2_crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE192SROBUST_AVX2_crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE192SROBUST_AVX2_crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHAKE192SROBUST_AVX2_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHAKE192SROBUST_AVX2_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSSHAKE192SROBUST_AVX2_crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE192SROBUST_AVX2_crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, - const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSSHAKE192SROBUST_AVX2_crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE192SROBUST_AVX2_crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk); -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/context.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/context.h deleted file mode 100644 index 6e0a33f3b7..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/context.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef SPX_CONTEXT_H -#define SPX_CONTEXT_H - -#include - -#include "params.h" - -typedef struct { - uint8_t pub_seed[SPX_N]; - uint8_t sk_seed[SPX_N]; -} spx_ctx; - -#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) -void initialize_hash_function(spx_ctx *ctx); - -#define free_hash_function SPX_NAMESPACE(free_hash_function) -void free_hash_function(spx_ctx *ctx); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/context_shake.c b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/context_shake.c deleted file mode 100644 index 9614a103d3..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/context_shake.c +++ /dev/null @@ -1,12 +0,0 @@ -#include "context.h" - -/* For SHAKE256, there is no immediate reason to initialize at the start, - so this function is an empty operation. */ -void initialize_hash_function(spx_ctx *ctx) { - (void)ctx; /* Suppress an 'unused parameter' warning. */ -} - -// in case the hash function api is heap-based. -void free_hash_function(spx_ctx *ctx) { - (void)ctx; -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/fips202x4.c b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/fips202x4.c deleted file mode 100644 index 1e06fef186..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/fips202x4.c +++ /dev/null @@ -1,210 +0,0 @@ -#include -#include -#include - -#include "fips202.h" -#include "fips202x4.h" - -#define NROUNDS 24 -#define ROL(a, offset) (((a) << (offset)) ^ ((a) >> (64-(offset)))) - -static uint64_t load64(const unsigned char *x) { - unsigned long long r = 0, i; - - for (i = 0; i < 8; ++i) { - r |= (unsigned long long)x[i] << 8 * i; - } - return r; -} - -static void store64(uint8_t *x, uint64_t u) { - unsigned int i; - - for (i = 0; i < 8; ++i) { - x[i] = (uint8_t)u; - u >>= 8; - } -} - -/* Use implementation from the Keccak Code Package */ -extern void KeccakP1600times4_PermuteAll_24rounds(__m256i *s); -#define KeccakF1600_StatePermute4x KeccakP1600times4_PermuteAll_24rounds - -static void keccak_absorb4x(__m256i *s, - unsigned int r, - const unsigned char *m0, - const unsigned char *m1, - const unsigned char *m2, - const unsigned char *m3, - unsigned long long int mlen, - unsigned char p) { - unsigned long long i; - unsigned char t0[200]; - unsigned char t1[200]; - unsigned char t2[200]; - unsigned char t3[200]; - - unsigned long long *ss = (unsigned long long *)s; - - - while (mlen >= r) { - for (i = 0; i < r / 8; ++i) { - ss[4 * i + 0] ^= load64(m0 + 8 * i); - ss[4 * i + 1] ^= load64(m1 + 8 * i); - ss[4 * i + 2] ^= load64(m2 + 8 * i); - ss[4 * i + 3] ^= load64(m3 + 8 * i); - } - - KeccakF1600_StatePermute4x(s); - mlen -= r; - m0 += r; - m1 += r; - m2 += r; - m3 += r; - } - - for (i = 0; i < r; ++i) { - t0[i] = 0; - t1[i] = 0; - t2[i] = 0; - t3[i] = 0; - } - for (i = 0; i < mlen; ++i) { - t0[i] = m0[i]; - t1[i] = m1[i]; - t2[i] = m2[i]; - t3[i] = m3[i]; - } - - t0[i] = p; - t1[i] = p; - t2[i] = p; - t3[i] = p; - - t0[r - 1] |= 128; - t1[r - 1] |= 128; - t2[r - 1] |= 128; - t3[r - 1] |= 128; - - for (i = 0; i < r / 8; ++i) { - ss[4 * i + 0] ^= load64(t0 + 8 * i); - ss[4 * i + 1] ^= load64(t1 + 8 * i); - ss[4 * i + 2] ^= load64(t2 + 8 * i); - ss[4 * i + 3] ^= load64(t3 + 8 * i); - } -} - - -static void keccak_squeezeblocks4x(unsigned char *h0, - unsigned char *h1, - unsigned char *h2, - unsigned char *h3, - unsigned long long int nblocks, - __m256i *s, - unsigned int r) { - unsigned int i; - - unsigned long long *ss = (unsigned long long *)s; - - while (nblocks > 0) { - KeccakF1600_StatePermute4x(s); - for (i = 0; i < (r >> 3); i++) { - store64(h0 + 8 * i, ss[4 * i + 0]); - store64(h1 + 8 * i, ss[4 * i + 1]); - store64(h2 + 8 * i, ss[4 * i + 2]); - store64(h3 + 8 * i, ss[4 * i + 3]); - } - h0 += r; - h1 += r; - h2 += r; - h3 += r; - nblocks--; - } -} - - - -void shake128x4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, unsigned long long outlen, - unsigned char *in0, - unsigned char *in1, - unsigned char *in2, - unsigned char *in3, unsigned long long inlen) { - __m256i s[25]; - unsigned char t0[SHAKE128_RATE]; - unsigned char t1[SHAKE128_RATE]; - unsigned char t2[SHAKE128_RATE]; - unsigned char t3[SHAKE128_RATE]; - unsigned int i; - - /* zero state */ - for (i = 0; i < 25; i++) { - s[i] = _mm256_xor_si256(s[i], s[i]); - } - - /* absorb 4 message of identical length in parallel */ - keccak_absorb4x(s, SHAKE128_RATE, in0, in1, in2, in3, inlen, 0x1F); - - /* Squeeze output */ - keccak_squeezeblocks4x(out0, out1, out2, out3, outlen / SHAKE128_RATE, s, SHAKE128_RATE); - - out0 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; - out1 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; - out2 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; - out3 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; - - if (outlen % SHAKE128_RATE) { - keccak_squeezeblocks4x(t0, t1, t2, t3, 1, s, SHAKE128_RATE); - for (i = 0; i < outlen % SHAKE128_RATE; i++) { - out0[i] = t0[i]; - out1[i] = t1[i]; - out2[i] = t2[i]; - out3[i] = t3[i]; - } - } -} - - -void shake256x4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, unsigned long long outlen, - unsigned char *in0, - unsigned char *in1, - unsigned char *in2, - unsigned char *in3, unsigned long long inlen) { - __m256i s[25]; - unsigned char t0[SHAKE256_RATE]; - unsigned char t1[SHAKE256_RATE]; - unsigned char t2[SHAKE256_RATE]; - unsigned char t3[SHAKE256_RATE]; - unsigned int i; - - /* zero state */ - for (i = 0; i < 25; i++) { - s[i] = _mm256_xor_si256(s[i], s[i]); - } - - /* absorb 4 message of identical length in parallel */ - keccak_absorb4x(s, SHAKE256_RATE, in0, in1, in2, in3, inlen, 0x1F); - - /* Squeeze output */ - keccak_squeezeblocks4x(out0, out1, out2, out3, outlen / SHAKE256_RATE, s, SHAKE256_RATE); - - out0 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; - out1 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; - out2 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; - out3 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; - - if (outlen % SHAKE256_RATE) { - keccak_squeezeblocks4x(t0, t1, t2, t3, 1, s, SHAKE256_RATE); - for (i = 0; i < outlen % SHAKE256_RATE; i++) { - out0[i] = t0[i]; - out1[i] = t1[i]; - out2[i] = t2[i]; - out3[i] = t3[i]; - } - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/fips202x4.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/fips202x4.h deleted file mode 100644 index 2b93c9cd0d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/fips202x4.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef SPX_FIPS202X4_H -#define SPX_FIPS202X4_H - -#include - -#include "params.h" - -#define shake128x4 SPX_NAMESPACE(shake128x4) -void shake128x4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, unsigned long long outlen, - unsigned char *in0, - unsigned char *in1, - unsigned char *in2, - unsigned char *in3, unsigned long long inlen); - -#define shake256x4 SPX_NAMESPACE(shake256x4) -void shake256x4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, unsigned long long outlen, - unsigned char *in0, - unsigned char *in1, - unsigned char *in2, - unsigned char *in3, unsigned long long inlen); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/fors.c b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/fors.c deleted file mode 100644 index f1b0639cfc..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/fors.c +++ /dev/null @@ -1,202 +0,0 @@ -#include -#include -#include - -#include "fors.h" - -#include "address.h" -#include "hash.h" -#include "hashx4.h" -#include "thash.h" -#include "thashx4.h" -#include "utils.h" -#include "utilsx4.h" - -static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, - uint32_t fors_leaf_addr[8]) { - prf_addr(sk, ctx, fors_leaf_addr); -} - -static void fors_gen_skx4(unsigned char *sk0, - unsigned char *sk1, - unsigned char *sk2, - unsigned char *sk3, const spx_ctx *ctx, - uint32_t fors_leaf_addrx4[4 * 8]) { - prf_addrx4(sk0, sk1, sk2, sk3, - ctx, fors_leaf_addrx4); -} - -static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, - const spx_ctx *ctx, - uint32_t fors_leaf_addr[8]) { - thash(leaf, sk, 1, ctx, fors_leaf_addr); -} - -static void fors_sk_to_leafx4(unsigned char *leaf0, - unsigned char *leaf1, - unsigned char *leaf2, - unsigned char *leaf3, - const unsigned char *sk0, - const unsigned char *sk1, - const unsigned char *sk2, - const unsigned char *sk3, - const spx_ctx *ctx, - uint32_t fors_leaf_addrx4[4 * 8]) { - thashx4(leaf0, leaf1, leaf2, leaf3, - sk0, sk1, sk2, sk3, - 1, ctx, fors_leaf_addrx4); -} - -struct fors_gen_leaf_info { - uint32_t leaf_addrx[4 * 8]; -}; - -static void fors_gen_leafx4(unsigned char *leaf, - const spx_ctx *ctx, - uint32_t addr_idx, void *info) { - struct fors_gen_leaf_info *fors_info = info; - uint32_t *fors_leaf_addrx4 = fors_info->leaf_addrx; - unsigned int j; - - /* Only set the parts that the caller doesn't set */ - for (j = 0; j < 4; j++) { - set_tree_index(fors_leaf_addrx4 + j * 8, addr_idx + j); - set_type(fors_leaf_addrx4 + j * 8, SPX_ADDR_TYPE_FORSPRF); - } - - fors_gen_skx4(leaf + 0 * SPX_N, - leaf + 1 * SPX_N, - leaf + 2 * SPX_N, - leaf + 3 * SPX_N, - ctx, fors_leaf_addrx4); - - for (j = 0; j < 4; j++) { - set_type(fors_leaf_addrx4 + j * 8, SPX_ADDR_TYPE_FORSTREE); - } - - fors_sk_to_leafx4(leaf + 0 * SPX_N, - leaf + 1 * SPX_N, - leaf + 2 * SPX_N, - leaf + 3 * SPX_N, - leaf + 0 * SPX_N, - leaf + 1 * SPX_N, - leaf + 2 * SPX_N, - leaf + 3 * SPX_N, - ctx, fors_leaf_addrx4); -} - -/** - * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - * Assumes indices has space for SPX_FORS_TREES integers. - */ -static void message_to_indices(uint32_t *indices, const unsigned char *m) { - unsigned int i, j; - unsigned int offset = 0; - - for (i = 0; i < SPX_FORS_TREES; i++) { - indices[i] = 0; - for (j = 0; j < SPX_FORS_HEIGHT; j++) { - indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); - offset++; - } - } -} - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -void fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]) { - uint32_t indices[SPX_FORS_TREES]; - unsigned char roots[SPX_FORS_TREES * SPX_N]; - uint32_t fors_tree_addr[4 * 8] = {0}; - struct fors_gen_leaf_info fors_info = {0}; - uint32_t *fors_leaf_addr = fors_info.leaf_addrx; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - for (i = 0; i < 4; i++) { - copy_keypair_addr(fors_tree_addr + 8 * i, fors_addr); - set_type(fors_tree_addr + 8 * i, SPX_ADDR_TYPE_FORSTREE); - copy_keypair_addr(fors_leaf_addr + 8 * i, fors_addr); - } - copy_keypair_addr(fors_pk_addr, fors_addr); - set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < SPX_FORS_TREES; i++) { - idx_offset = i * (1 << SPX_FORS_HEIGHT); - - set_tree_height(fors_tree_addr, 0); - set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Include the secret key part that produces the selected leaf node. */ - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); - fors_gen_sk(sig, ctx, fors_tree_addr); - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); - sig += SPX_N; - - /* Compute the authentication path for this leaf node. */ - treehashx4(roots + i * SPX_N, sig, ctx, - indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx4, - fors_tree_addr, &fors_info); - - sig += SPX_N * SPX_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); -} - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -void fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]) { - uint32_t indices[SPX_FORS_TREES]; - unsigned char roots[SPX_FORS_TREES * SPX_N]; - unsigned char leaf[SPX_N]; - uint32_t fors_tree_addr[8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - copy_keypair_addr(fors_tree_addr, fors_addr); - copy_keypair_addr(fors_pk_addr, fors_addr); - - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); - set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < SPX_FORS_TREES; i++) { - idx_offset = i * (1 << SPX_FORS_HEIGHT); - - set_tree_height(fors_tree_addr, 0); - set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Derive the leaf from the included secret key part. */ - fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); - sig += SPX_N; - - /* Derive the corresponding root node of this tree. */ - compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, - sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); - sig += SPX_N * SPX_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/fors.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/fors.h deleted file mode 100644 index 509140a178..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/fors.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef SPX_FORS_H -#define SPX_FORS_H - -#include - -#include "context.h" -#include "params.h" - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -#define fors_sign SPX_NAMESPACE(fors_sign) -void fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]); - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) -void fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/hash.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/hash.h deleted file mode 100644 index f7c87d4c3c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/hash.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef SPX_HASH_H -#define SPX_HASH_H - -#include -#include - -#include "context.h" -#include "params.h" - -#define prf_addr SPX_NAMESPACE(prf_addr) -void prf_addr(unsigned char *out, const spx_ctx *ctx, - const uint32_t addr[8]); - -#define gen_message_random SPX_NAMESPACE(gen_message_random) -void gen_message_random(unsigned char *R, const unsigned char *sk_prf, - const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx); - -#define hash_message SPX_NAMESPACE(hash_message) -void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx); - - - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/hash_shake.c b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/hash_shake.c deleted file mode 100644 index ff5e7ec918..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/hash_shake.c +++ /dev/null @@ -1,83 +0,0 @@ -#include -#include - -#include "hash.h" - -#include "address.h" -#include "fips202.h" -#include "params.h" -#include "utils.h" - -/* - * Computes PRF(pk_seed, sk_seed, addr) - */ -void prf_addr(unsigned char *out, const spx_ctx *ctx, - const uint32_t addr[8]) { - unsigned char buf[2 * SPX_N + SPX_ADDR_BYTES]; - - memcpy(buf, ctx->pub_seed, SPX_N); - memcpy(buf + SPX_N, addr, SPX_ADDR_BYTES); - memcpy(buf + SPX_N + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); - - shake256(out, SPX_N, buf, 2 * SPX_N + SPX_ADDR_BYTES); -} - -/** - * Computes the message-dependent randomness R, using a secret seed and an - * optional randomization value as well as the message. - */ -void gen_message_random(unsigned char *R, const unsigned char *sk_prf, - const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx) { - (void)ctx; - shake256incctx s_inc; - - shake256_inc_init(&s_inc); - shake256_inc_absorb(&s_inc, sk_prf, SPX_N); - shake256_inc_absorb(&s_inc, optrand, SPX_N); - shake256_inc_absorb(&s_inc, m, mlen); - shake256_inc_finalize(&s_inc); - shake256_inc_squeeze(R, SPX_N, &s_inc); - shake256_inc_ctx_release(&s_inc); -} - -/** - * Computes the message hash using R, the public key, and the message. - * Outputs the message digest and the index of the leaf. The index is split in - * the tree index and the leaf index, for convenient copying to an address. - */ -void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx) { - (void)ctx; -#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) -#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) -#define SPX_LEAF_BITS SPX_TREE_HEIGHT -#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) -#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) - - unsigned char buf[SPX_DGST_BYTES]; - unsigned char *bufp = buf; - shake256incctx s_inc; - - shake256_inc_init(&s_inc); - shake256_inc_absorb(&s_inc, R, SPX_N); - shake256_inc_absorb(&s_inc, pk, SPX_PK_BYTES); - shake256_inc_absorb(&s_inc, m, mlen); - shake256_inc_finalize(&s_inc); - shake256_inc_squeeze(buf, SPX_DGST_BYTES, &s_inc); - shake256_inc_ctx_release(&s_inc); - - memcpy(digest, bufp, SPX_FORS_MSG_BYTES); - bufp += SPX_FORS_MSG_BYTES; - - - *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); - *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); - bufp += SPX_TREE_BYTES; - - *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); - *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/hash_shakex4.c b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/hash_shakex4.c deleted file mode 100644 index bbd22eb117..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/hash_shakex4.c +++ /dev/null @@ -1,64 +0,0 @@ -#include -#include - -#include "hashx4.h" - -#include "address.h" -#include "fips202x4.h" -#include "params.h" - -extern void KeccakP1600times4_PermuteAll_24rounds(__m256i *s); - -/* - * 4-way parallel version of prf_addr; takes 4x as much input and output - */ -void prf_addrx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const spx_ctx *ctx, - const uint32_t addrx4[4 * 8]) { - /* As we write and read only a few quadwords, it is more efficient to - * build and extract from the fourway SHAKE256 state by hand. */ - __m256i state[25]; - - for (int i = 0; i < SPX_N / 8; i++) { - state[i] = _mm256_set1_epi64x(((int64_t *)ctx->pub_seed)[i]); - } - for (int i = 0; i < 4; i++) { - state[SPX_N / 8 + i] = _mm256_set_epi32( - (int)addrx4[3 * 8 + 1 + 2 * i], - (int)addrx4[3 * 8 + 2 * i], - (int)addrx4[2 * 8 + 1 + 2 * i], - (int)addrx4[2 * 8 + 2 * i], - (int)addrx4[8 + 1 + 2 * i], - (int)addrx4[8 + 2 * i], - (int)addrx4[1 + 2 * i], - (int)addrx4[2 * i] - ); - } - for (int i = 0; i < SPX_N / 8; i++) { - state[SPX_N / 8 + i + 4] = _mm256_set1_epi64x(((int64_t *)ctx->sk_seed)[i]); - } - - /* SHAKE domain separator and padding. */ - state[SPX_N / 4 + 4] = _mm256_set1_epi64x(0x1f); - for (int i = SPX_N / 4 + 5; i < 16; i++) { - state[i] = _mm256_set1_epi64x(0); - } - // shift unsigned and then cast to avoid UB - state[16] = _mm256_set1_epi64x((long long)(0x80ULL << 56)); - - for (int i = 17; i < 25; i++) { - state[i] = _mm256_set1_epi64x(0); - } - - KeccakP1600times4_PermuteAll_24rounds(&state[0]); - - for (int i = 0; i < SPX_N / 8; i++) { - ((int64_t *)out0)[i] = _mm256_extract_epi64(state[i], 0); - ((int64_t *)out1)[i] = _mm256_extract_epi64(state[i], 1); - ((int64_t *)out2)[i] = _mm256_extract_epi64(state[i], 2); - ((int64_t *)out3)[i] = _mm256_extract_epi64(state[i], 3); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/hashx4.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/hashx4.h deleted file mode 100644 index 3751a0ebd0..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/hashx4.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef SPX_HASHX4_H -#define SPX_HASHX4_H - -#include - -#include "context.h" -#include "params.h" - -#define prf_addrx4 SPX_NAMESPACE(prf_addrx4) -void prf_addrx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const spx_ctx *ctx, - const uint32_t addrx4[4 * 8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/merkle.c b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/merkle.c deleted file mode 100644 index f57811c1ac..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/merkle.c +++ /dev/null @@ -1,64 +0,0 @@ -#include -#include - -#include "merkle.h" - -#include "address.h" -#include "params.h" -#include "utils.h" -#include "utilsx4.h" -#include "wots.h" -#include "wotsx4.h" - -/* - * This generates a Merkle signature (WOTS signature followed by the Merkle - * authentication path). - */ -void merkle_sign(uint8_t *sig, unsigned char *root, - const spx_ctx *ctx, - uint32_t wots_addr[8], uint32_t tree_addr[8], - uint32_t idx_leaf) { - unsigned char *auth_path = sig + SPX_WOTS_BYTES; - uint32_t tree_addrx4[4 * 8] = { 0 }; - int j; - struct leaf_info_x4 info = { 0 }; - unsigned steps[ SPX_WOTS_LEN ]; - - info.wots_sig = sig; - chain_lengths(steps, root); - info.wots_steps = steps; - - for (j = 0; j < 4; j++) { - set_type(&tree_addrx4[8 * j], SPX_ADDR_TYPE_HASHTREE); - set_type(&info.leaf_addr[8 * j], SPX_ADDR_TYPE_WOTS); - set_type(&info.pk_addr[8 * j], SPX_ADDR_TYPE_WOTSPK); - copy_subtree_addr(&tree_addrx4[8 * j], tree_addr); - copy_subtree_addr(&info.leaf_addr[8 * j], wots_addr); - copy_subtree_addr(&info.pk_addr[8 * j], wots_addr); - } - - info.wots_sign_leaf = idx_leaf; - - treehashx4(root, auth_path, ctx, - idx_leaf, 0, - SPX_TREE_HEIGHT, - wots_gen_leafx4, - tree_addrx4, &info); -} - -/* Compute root node of the top-most subtree. */ -void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { - /* We do not need the auth path in key generation, but it simplifies the - code to have just one treehash routine that computes both root and path - in one function. */ - unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; - uint32_t top_tree_addr[8] = {0}; - uint32_t wots_addr[8] = {0}; - - set_layer_addr(top_tree_addr, SPX_D - 1); - set_layer_addr(wots_addr, SPX_D - 1); - - merkle_sign(auth_path, root, ctx, - wots_addr, top_tree_addr, - ~0U /* ~0 means "don't bother generating an auth path */ ); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/merkle.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/merkle.h deleted file mode 100644 index 769cf2e970..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/merkle.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef MERKLE_H_ -#define MERKLE_H_ - -#include - -#include "context.h" -#include "params.h" - -/* Generate a Merkle signature (WOTS signature followed by the Merkle */ -/* authentication path) */ -#define merkle_sign SPX_NAMESPACE(merkle_sign) -void merkle_sign(uint8_t *sig, unsigned char *root, - const spx_ctx *ctx, - uint32_t wots_addr[8], uint32_t tree_addr[8], - uint32_t idx_leaf); - -/* Compute the root node of the top-most subtree. */ -#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) -void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); - -#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/nistapi.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/nistapi.h deleted file mode 100644 index 3cb71afad4..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/nistapi.h +++ /dev/null @@ -1,87 +0,0 @@ -#ifndef SPX_API_H -#define SPX_API_H - -#include -#include - -#include "params.h" - -#define CRYPTO_ALGNAME "SPHINCS+" - -#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES -#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES -#define CRYPTO_BYTES SPX_BYTES -#define CRYPTO_SEEDBYTES (3*SPX_N) - -/* - * Returns the length of a secret key, in bytes - */ -#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) -size_t crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) -size_t crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) -size_t crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) -size_t crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) -int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) -int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) -int crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) -int crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -#define crypto_sign SPX_NAMESPACE(crypto_sign) -int crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) -int crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/params.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/params.h deleted file mode 100644 index ae70c8358f..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/params.h +++ /dev/null @@ -1,56 +0,0 @@ -#ifndef SPX_PARAMS_H -#define SPX_PARAMS_H - -#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSSHAKE192SROBUST_AVX2_##s - -/* Hash output length in bytes. */ -#define SPX_N 24 -/* Height of the hypertree. */ -#define SPX_FULL_HEIGHT 63 -/* Number of subtree layer. */ -#define SPX_D 7 -/* FORS tree dimensions. */ -#define SPX_FORS_HEIGHT 14 -#define SPX_FORS_TREES 17 -/* Winternitz parameter, */ -#define SPX_WOTS_W 16 - -/* The hash function is defined by linking a different hash.c file, as opposed - to setting a #define constant. */ - -/* For clarity */ -#define SPX_ADDR_BYTES 32 - -/* WOTS parameters. */ -#define SPX_WOTS_LOGW 4 - -#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) - -/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#define SPX_WOTS_LEN2 3 - -#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) -#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) -#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES - -/* Subtree size. */ -#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) - -//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT -// #error SPX_D should always divide SPX_FULL_HEIGHT -//#endif - -/* FORS parameters. */ -#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) -#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) -#define SPX_FORS_PK_BYTES SPX_N - -/* Resulting SPX sizes. */ -#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ - SPX_FULL_HEIGHT * SPX_N) -#define SPX_PK_BYTES (2 * SPX_N) -#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) - -#include "shake_offsets.h" - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/shake_offsets.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/shake_offsets.h deleted file mode 100644 index 6b28d95d91..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/shake_offsets.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef SHAKE_OFFSETS_H_ -#define SHAKE_OFFSETS_H_ - -/* - * Offsets of various fields in the address structure when we use SHAKE as - * the Sphincs+ hash function - */ - -#define SPX_OFFSET_LAYER 3 /* The byte used to specify the Merkle tree layer */ -#define SPX_OFFSET_TREE 8 /* The start of the 8 byte field used to specify the tree */ -#define SPX_OFFSET_TYPE 19 /* The byte used to specify the hash type (reason) */ -#define SPX_OFFSET_KP_ADDR2 22 /* The high byte used to specify the key pair (which one-time signature) */ -#define SPX_OFFSET_KP_ADDR1 23 /* The low byte used to specify the key pair */ -#define SPX_OFFSET_CHAIN_ADDR 27 /* The byte used to specify the chain address (which Winternitz chain) */ -#define SPX_OFFSET_HASH_ADDR 31 /* The byte used to specify the hash address (where in the Winternitz chain) */ -#define SPX_OFFSET_TREE_HGT 27 /* The byte used to specify the height of this node in the FORS or Merkle tree */ -#define SPX_OFFSET_TREE_INDEX 28 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ - -#define SPX_SHAKE 1 - -#endif /* SHAKE_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/sign.c b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/sign.c deleted file mode 100644 index 9d0c7d1b22..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/sign.c +++ /dev/null @@ -1,286 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "context.h" -#include "fors.h" -#include "hash.h" -#include "merkle.h" -#include "nistapi.h" -#include "params.h" -#include "randombytes.h" -#include "thash.h" -#include "utils.h" -#include "wots.h" - -/* - * Returns the length of a secret key, in bytes - */ -size_t crypto_sign_secretkeybytes(void) { - return CRYPTO_SECRETKEYBYTES; -} - -/* - * Returns the length of a public key, in bytes - */ -size_t crypto_sign_publickeybytes(void) { - return CRYPTO_PUBLICKEYBYTES; -} - -/* - * Returns the length of a signature, in bytes - */ -size_t crypto_sign_bytes(void) { - return CRYPTO_BYTES; -} - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t crypto_sign_seedbytes(void) { - return CRYPTO_SEEDBYTES; -} - -/* - * Generates an SPX key pair given a seed of length - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed) { - spx_ctx ctx; - - /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ - memcpy(sk, seed, CRYPTO_SEEDBYTES); - - memcpy(pk, sk + 2 * SPX_N, SPX_N); - - memcpy(ctx.pub_seed, pk, SPX_N); - memcpy(ctx.sk_seed, sk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - /* Compute root node of the top-most subtree. */ - merkle_gen_root(sk + 3 * SPX_N, &ctx); - - // cleanup - free_hash_function(&ctx); - - memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); - - return 0; -} - -/* - * Generates an SPX key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { - uint8_t seed[CRYPTO_SEEDBYTES]; - randombytes(seed, CRYPTO_SEEDBYTES); - crypto_sign_seed_keypair(pk, sk, seed); - - return 0; -} - -/** - * Returns an array containing a detached signature. - */ -int crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - spx_ctx ctx; - - const uint8_t *sk_prf = sk + SPX_N; - const uint8_t *pk = sk + 2 * SPX_N; - - uint8_t optrand[SPX_N]; - uint8_t mhash[SPX_FORS_MSG_BYTES]; - uint8_t root[SPX_N]; - uint32_t i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - - memcpy(ctx.sk_seed, sk, SPX_N); - memcpy(ctx.pub_seed, pk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - set_type(wots_addr, SPX_ADDR_TYPE_WOTS); - set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); - - /* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ - randombytes(optrand, SPX_N); - /* Compute the digest randomization value. */ - gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); - - /* Derive the message digest and leaf index from R, PK and M. */ - hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); - sig += SPX_N; - - set_tree_addr(wots_addr, tree); - set_keypair_addr(wots_addr, idx_leaf); - - /* Sign the message hash using FORS. */ - fors_sign(sig, root, mhash, &ctx, wots_addr); - sig += SPX_FORS_BYTES; - - for (i = 0; i < SPX_D; i++) { - set_layer_addr(tree_addr, i); - set_tree_addr(tree_addr, tree); - - copy_subtree_addr(wots_addr, tree_addr); - set_keypair_addr(wots_addr, idx_leaf); - - merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); - sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); - tree = tree >> SPX_TREE_HEIGHT; - } - - free_hash_function(&ctx); - - *siglen = SPX_BYTES; - - return 0; -} - -/** - * Verifies a detached signature and message under a given public key. - */ -int crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk) { - spx_ctx ctx; - const uint8_t *pub_root = pk + SPX_N; - uint8_t mhash[SPX_FORS_MSG_BYTES]; - uint8_t wots_pk[SPX_WOTS_BYTES]; - uint8_t root[SPX_N]; - uint8_t leaf[SPX_N]; - unsigned int i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - if (siglen != SPX_BYTES) { - return -1; - } - - memcpy(ctx.pub_seed, pk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - set_type(wots_addr, SPX_ADDR_TYPE_WOTS); - set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); - set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); - - /* Derive the message digest and leaf index from R || PK || M. */ - /* The additional SPX_N is a result of the hash domain separator. */ - hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); - sig += SPX_N; - - /* Layer correctly defaults to 0, so no need to set_layer_addr */ - set_tree_addr(wots_addr, tree); - set_keypair_addr(wots_addr, idx_leaf); - - fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); - sig += SPX_FORS_BYTES; - - /* For each subtree.. */ - for (i = 0; i < SPX_D; i++) { - set_layer_addr(tree_addr, i); - set_tree_addr(tree_addr, tree); - - copy_subtree_addr(wots_addr, tree_addr); - set_keypair_addr(wots_addr, idx_leaf); - - copy_keypair_addr(wots_pk_addr, wots_addr); - - /* The WOTS public key is only correct if the signature was correct. */ - /* Initially, root is the FORS pk, but on subsequent iterations it is - the root of the subtree below the currently processed subtree. */ - wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); - sig += SPX_WOTS_BYTES; - - /* Compute the leaf node using the WOTS public key. */ - thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); - - /* Compute the root node of this subtree. */ - compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, - &ctx, tree_addr); - sig += SPX_TREE_HEIGHT * SPX_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); - tree = tree >> SPX_TREE_HEIGHT; - } - - // cleanup - free_hash_function(&ctx); - - /* Check if the root node equals the root node in the public key. */ - if (memcmp(root, pub_root, SPX_N) != 0) { - return -1; - } - - return 0; -} - - -/** - * Returns an array containing the signature followed by the message. - */ -int crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk) { - size_t siglen; - - crypto_sign_signature(sm, &siglen, m, mlen, sk); - - memmove(sm + SPX_BYTES, m, mlen); - *smlen = siglen + mlen; - - return 0; -} - -/** - * Verifies a given signature-message pair under a given public key. - */ -int crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk) { - /* The API caller does not necessarily know what size a signature should be - but SPHINCS+ signatures are always exactly SPX_BYTES. */ - if (smlen < SPX_BYTES) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - *mlen = smlen - SPX_BYTES; - - if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - /* If verification was successful, move the message to the right place. */ - memmove(m, sm + SPX_BYTES, *mlen); - - return 0; -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/thash.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/thash.h deleted file mode 100644 index 8687ccfb4d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/thash.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef SPX_THASH_H -#define SPX_THASH_H - -#include "context.h" -#include "params.h" - -#include - -#define thash SPX_NAMESPACE(thash) -void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/thash_shake_robust.c b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/thash_shake_robust.c deleted file mode 100644 index 696d53c5cc..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/thash_shake_robust.c +++ /dev/null @@ -1,31 +0,0 @@ -#include -#include - -#include "thash.h" - -#include "address.h" -#include "params.h" -#include "utils.h" - -#include "fips202.h" - -/** - * Takes an array of inblocks concatenated arrays of SPX_N bytes. - */ -void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]) { - PQCLEAN_VLA(uint8_t, buf, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); - PQCLEAN_VLA(uint8_t, bitmask, inblocks * SPX_N); - unsigned int i; - - memcpy(buf, ctx->pub_seed, SPX_N); - memcpy(buf + SPX_N, addr, SPX_ADDR_BYTES); - - shake256(bitmask, inblocks * SPX_N, buf, SPX_N + SPX_ADDR_BYTES); - - for (i = 0; i < inblocks * SPX_N; i++) { - buf[SPX_N + SPX_ADDR_BYTES + i] = in[i] ^ bitmask[i]; - } - - shake256(out, SPX_N, buf, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/thash_shake_robustx4.c b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/thash_shake_robustx4.c deleted file mode 100644 index ce2946b745..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/thash_shake_robustx4.c +++ /dev/null @@ -1,131 +0,0 @@ -#include -#include - -#include "thashx4.h" - -#include "address.h" -#include "params.h" -#include "utils.h" - -#include "fips202x4.h" - -extern void KeccakP1600times4_PermuteAll_24rounds(__m256i *s); - -/** - * 4-way parallel version of thash; takes 4x as much input and output - */ -void thashx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addrx4[4 * 8]) { - if (inblocks == 1 || inblocks == 2) { - /* As we write and read only a few quadwords, it is more efficient to - * build and extract from the fourway SHAKE256 state by hand. */ - __m256i state[25]; - for (int i = 0; i < SPX_N / 8; i++) { - state[i] = _mm256_set1_epi64x(((int64_t *)ctx->pub_seed)[i]); - } - for (int i = 0; i < 4; i++) { - state[SPX_N / 8 + i] = _mm256_set_epi32( - (int)addrx4[3 * 8 + 1 + 2 * i], - (int)addrx4[3 * 8 + 2 * i], - (int)addrx4[2 * 8 + 1 + 2 * i], - (int)addrx4[2 * 8 + 2 * i], - (int)addrx4[8 + 1 + 2 * i], - (int)addrx4[8 + 2 * i], - (int)addrx4[1 + 2 * i], - (int)addrx4[2 * i] - ); - } - - /* SHAKE domain separator and padding */ - state[SPX_N / 8 + 4] = _mm256_set1_epi64x(0x1f); - for (int i = SPX_N / 8 + 5; i < 16; i++) { - state[i] = _mm256_set1_epi64x(0); - } - state[16] = _mm256_set1_epi64x((long long)(0x80ULL << 56)); - - for (int i = 17; i < 25; i++) { - state[i] = _mm256_set1_epi64x(0); - } - - /* We will permutate state2 with f1600x4 to compute the bitmask, - * but first we'll copy it to state2 which will be used to compute - * the final output, as its input is alsmost identical. */ - __m256i state2[25]; - memcpy(state2, state, 800); - - KeccakP1600times4_PermuteAll_24rounds(&state[0]); - - /* By copying from state, state2 already contains the pub_seed - * and addres. We just need to copy in the input blocks xorred with - * the bitmask we just computed. */ - for (unsigned int i = 0; i < (SPX_N / 8) * inblocks; i++) { - state2[SPX_N / 8 + 4 + i] = _mm256_xor_si256( - state[i], - _mm256_set_epi64x( - ((int64_t *)in3)[i], - ((int64_t *)in2)[i], - ((int64_t *)in1)[i], - ((int64_t *)in0)[i] - ) - ); - } - - /* Domain separator and start of padding. Note that the quadwords - * around are already zeroed for state from which we copied. - * We do a XOR instead of a set as this might be the 16th quadword - * when N=32 and inblocks=2, which already contains the end - * of the padding. */ - state2[(SPX_N / 8) * (1 + inblocks) + 4] = _mm256_xor_si256( - state2[(SPX_N / 8) * (1 + inblocks) + 4], - _mm256_set1_epi64x(0x1f) - ); - - KeccakP1600times4_PermuteAll_24rounds(&state2[0]); - - for (int i = 0; i < SPX_N / 8; i++) { - ((int64_t *)out0)[i] = _mm256_extract_epi64(state2[i], 0); - ((int64_t *)out1)[i] = _mm256_extract_epi64(state2[i], 1); - ((int64_t *)out2)[i] = _mm256_extract_epi64(state2[i], 2); - ((int64_t *)out3)[i] = _mm256_extract_epi64(state2[i], 3); - } - } else { - PQCLEAN_VLA(unsigned char, buf0, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); - PQCLEAN_VLA(unsigned char, buf1, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); - PQCLEAN_VLA(unsigned char, buf2, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); - PQCLEAN_VLA(unsigned char, buf3, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); - PQCLEAN_VLA(unsigned char, bitmask0, inblocks * SPX_N); - PQCLEAN_VLA(unsigned char, bitmask1, inblocks * SPX_N); - PQCLEAN_VLA(unsigned char, bitmask2, inblocks * SPX_N); - PQCLEAN_VLA(unsigned char, bitmask3, inblocks * SPX_N); - unsigned int i; - - memcpy(buf0, ctx->pub_seed, SPX_N); - memcpy(buf1, ctx->pub_seed, SPX_N); - memcpy(buf2, ctx->pub_seed, SPX_N); - memcpy(buf3, ctx->pub_seed, SPX_N); - memcpy(buf0 + SPX_N, addrx4 + 0 * 8, SPX_ADDR_BYTES); - memcpy(buf1 + SPX_N, addrx4 + 1 * 8, SPX_ADDR_BYTES); - memcpy(buf2 + SPX_N, addrx4 + 2 * 8, SPX_ADDR_BYTES); - memcpy(buf3 + SPX_N, addrx4 + 3 * 8, SPX_ADDR_BYTES); - - shake256x4(bitmask0, bitmask1, bitmask2, bitmask3, inblocks * SPX_N, - buf0, buf1, buf2, buf3, SPX_N + SPX_ADDR_BYTES); - - for (i = 0; i < inblocks * SPX_N; i++) { - buf0[SPX_N + SPX_ADDR_BYTES + i] = in0[i] ^ bitmask0[i]; - buf1[SPX_N + SPX_ADDR_BYTES + i] = in1[i] ^ bitmask1[i]; - buf2[SPX_N + SPX_ADDR_BYTES + i] = in2[i] ^ bitmask2[i]; - buf3[SPX_N + SPX_ADDR_BYTES + i] = in3[i] ^ bitmask3[i]; - } - - shake256x4(out0, out1, out2, out3, SPX_N, - buf0, buf1, buf2, buf3, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/thashx4.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/thashx4.h deleted file mode 100644 index 64798a3727..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/thashx4.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef SPX_THASHX4_H -#define SPX_THASHX4_H - -#include - -#include "context.h" -#include "params.h" - -#define thashx4 SPX_NAMESPACE(thashx4) -void thashx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addrx4[4 * 8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/utils.c b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/utils.c deleted file mode 100644 index 177b541fb9..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/utils.c +++ /dev/null @@ -1,148 +0,0 @@ -#include - -#include "utils.h" - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "thash.h" - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void ull_to_bytes(unsigned char *out, unsigned int outlen, - unsigned long long in) { - int i; - - /* Iterate over out in decreasing order, for big-endianness. */ - for (i = (signed int)outlen - 1; i >= 0; i--) { - out[i] = in & 0xff; - in = in >> 8; - } -} - -void u32_to_bytes(unsigned char *out, uint32_t in) { - out[0] = (unsigned char)(in >> 24); - out[1] = (unsigned char)(in >> 16); - out[2] = (unsigned char)(in >> 8); - out[3] = (unsigned char)in; -} - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { - unsigned long long retval = 0; - unsigned int i; - - for (i = 0; i < inlen; i++) { - retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); - } - return retval; -} - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void compute_root(unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const spx_ctx *ctx, uint32_t addr[8]) { - uint32_t i; - unsigned char buffer[2 * SPX_N]; - - /* If leaf_idx is odd (last bit = 1), current path element is a right child - and auth_path has to go left. Otherwise it is the other way around. */ - if (leaf_idx & 1) { - memcpy(buffer + SPX_N, leaf, SPX_N); - memcpy(buffer, auth_path, SPX_N); - } else { - memcpy(buffer, leaf, SPX_N); - memcpy(buffer + SPX_N, auth_path, SPX_N); - } - auth_path += SPX_N; - - for (i = 0; i < tree_height - 1; i++) { - leaf_idx >>= 1; - idx_offset >>= 1; - /* Set the address of the node we're creating. */ - set_tree_height(addr, i + 1); - set_tree_index(addr, leaf_idx + idx_offset); - - /* Pick the right or left neighbor, depending on parity of the node. */ - if (leaf_idx & 1) { - thash(buffer + SPX_N, buffer, 2, ctx, addr); - memcpy(buffer, auth_path, SPX_N); - } else { - thash(buffer, buffer, 2, ctx, addr); - memcpy(buffer + SPX_N, auth_path, SPX_N); - } - auth_path += SPX_N; - } - - /* The last iteration is exceptional; we do not copy an auth_path node. */ - leaf_idx >>= 1; - idx_offset >>= 1; - set_tree_height(addr, tree_height); - set_tree_index(addr, leaf_idx + idx_offset); - thash(root, buffer, 2, ctx, addr); -} - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const spx_ctx * /* ctx */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), - uint32_t tree_addr[8]) { - PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); - PQCLEAN_VLA(unsigned int, heights, tree_height + 1); - unsigned int offset = 0; - uint32_t idx; - uint32_t tree_idx; - - for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { - /* Add the next leaf node to the stack. */ - gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); - offset++; - heights[offset - 1] = 0; - - /* If this is a node we need for the auth path.. */ - if ((leaf_idx ^ 0x1) == idx) { - memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); - } - - /* While the top-most nodes are of equal height.. */ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { - /* Compute index of the new node, in the next layer. */ - tree_idx = (idx >> (heights[offset - 1] + 1)); - - /* Set the address of the node we're creating. */ - set_tree_height(tree_addr, heights[offset - 1] + 1); - set_tree_index(tree_addr, - tree_idx + (idx_offset >> (heights[offset - 1] + 1))); - /* Hash the top-most nodes from the stack together. */ - thash(stack + (offset - 2)*SPX_N, - stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); - offset--; - /* Note that the top-most node is now one layer higher. */ - heights[offset - 1]++; - - /* If this is a node we need for the auth path.. */ - if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_path + heights[offset - 1]*SPX_N, - stack + (offset - 1)*SPX_N, SPX_N); - } - } - } - memcpy(root, stack, SPX_N); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/utils.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/utils.h deleted file mode 100644 index 64f5d5a53a..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/utils.h +++ /dev/null @@ -1,58 +0,0 @@ -#ifndef SPX_UTILS_H -#define SPX_UTILS_H - -#include - -#include "compat.h" -#include "context.h" -#include "params.h" - - -/* To support MSVC use alloca() instead of VLAs. See #20. */ - - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) -void ull_to_bytes(unsigned char *out, unsigned int outlen, - unsigned long long in); -#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) -void u32_to_bytes(unsigned char *out, uint32_t in); - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) -unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -#define compute_root SPX_NAMESPACE(compute_root) -void compute_root(unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const spx_ctx *ctx, uint32_t addr[8]); - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -#define treehash SPX_NAMESPACE(treehash) -void treehash(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const spx_ctx *ctx /* ctx */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), - uint32_t tree_addr[8]); - - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/utilsx4.c b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/utilsx4.c deleted file mode 100644 index 1638677194..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/utilsx4.c +++ /dev/null @@ -1,138 +0,0 @@ -#include - -#include "utilsx4.h" - -#include "address.h" -#include "params.h" -#include "thashx4.h" -#include "utils.h" - -/* - * Generate the entire Merkle tree, computing the authentication path for leaf_idx, - * and the resulting root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) - * - * This expects tree_addrx4 to be initialized to 4 parallel addr structures for - * the Merkle tree nodes - * - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - * - * This works by using the standard Merkle tree building algorithm, except - * that each 'node' tracked is actually 4 consecutive nodes in the real tree. - * When we combine two logical nodes ABCD and WXYZ, we perform the H - * operation on adjacent real nodes, forming the parent logical node - * (AB)(CD)(WX)(YZ) - * - * When we get to the top two levels of the real tree (where there is only - * one logical node), we continue this operation two more times; the right - * most real node will by the actual root (and the other 3 nodes will be - * garbage). We follow the same thashx4 logic so that the 'extract - * authentication path components' part of the loop is still executed (and - * to simplify the code somewhat) - * - * This currently assumes tree_height >= 2; I suspect that doing an adjusting - * idx, addr_idx on the gen_leafx4 call if tree_height < 2 would fix it; since - * we don't actually use such short trees, I haven't bothered - */ -void treehashx4(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, - uint32_t tree_height, - void (*gen_leafx4)( - unsigned char * /* Where to write the leaves */, - const spx_ctx *, - uint32_t idx, void *info), - uint32_t tree_addrx4[4 * 8], - void *info) { - /* This is where we keep the intermediate nodes */ - PQCLEAN_VLA(unsigned char, stackx4, tree_height * 4 * SPX_N); - uint32_t left_adj = 0, prev_left_adj = 0; /* When we're doing the top 3 */ - /* levels, the left-most part of the tree isn't at the beginning */ - /* of current[]. These give the offset of the actual start */ - - uint32_t idx; - uint32_t max_idx = (1U << (tree_height - 2)) - 1; - for (idx = 0;; idx++) { - unsigned char current[4 * SPX_N]; /* Current logical node */ - gen_leafx4( current, ctx, 4 * idx + idx_offset, - info ); - - /* Now combine the freshly generated right node with previously */ - /* generated left ones */ - uint32_t internal_idx_offset = idx_offset; - uint32_t internal_idx = idx; - uint32_t internal_leaf = leaf_idx; - uint32_t h; /* The height we are in the Merkle tree */ - for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { - - /* Special processing if we're at the top of the tree */ - if (h >= tree_height - 2) { - if (h == tree_height) { - /* We hit the root; return it */ - memcpy( root, ¤t[3 * SPX_N], SPX_N ); - return; - } - /* The tree indexing logic is a bit off in this case */ - /* Adjust it so that the left-most node of the part of */ - /* the tree that we're processing has index 0 */ - prev_left_adj = left_adj; - left_adj = 4U - (1 << (tree_height - h - 1)); - } - - /* Check if we hit the top of the tree */ - if (h == tree_height) { - /* We hit the root; return it */ - memcpy( root, ¤t[3 * SPX_N], SPX_N ); - return; - } - - /* - * Check if one of the nodes we have is a part of the - * authentication path; if it is, write it out - */ - if ((((internal_idx << 2) ^ internal_leaf) & ~0x3U) == 0) { - memcpy( &auth_path[ h * SPX_N ], - ¤t[(((internal_leaf & 3) ^ 1) + prev_left_adj) * SPX_N], - SPX_N ); - } - - /* - * Check if we're at a left child; if so, stop going up the stack - * Exception: if we've reached the end of the tree, keep on going - * (so we combine the last 4 nodes into the one root node in two - * more iterations) - */ - if ((internal_idx & 1) == 0 && idx < max_idx) { - break; - } - - /* Ok, we're at a right node (or doing the top 3 levels) */ - /* Now combine the left and right logical nodes together */ - - /* Set the address of the node we're creating. */ - unsigned int j; - internal_idx_offset >>= 1; - for (j = 0; j < 4; j++) { - set_tree_height(tree_addrx4 + j * 8, h + 1); - set_tree_index(tree_addrx4 + j * 8, - (4 / 2) * (internal_idx & ~1U) + j - left_adj + internal_idx_offset ); - } - unsigned char *left = &stackx4[h * 4 * SPX_N]; - thashx4( ¤t[0 * SPX_N], - ¤t[1 * SPX_N], - ¤t[2 * SPX_N], - ¤t[3 * SPX_N], - &left [0 * SPX_N], - &left [2 * SPX_N], - ¤t[0 * SPX_N], - ¤t[2 * SPX_N], - 2, ctx, tree_addrx4); - } - - /* We've hit a left child; save the current for when we get the */ - /* corresponding right right */ - memcpy( &stackx4[h * 4 * SPX_N], current, 4 * SPX_N); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/utilsx4.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/utilsx4.h deleted file mode 100644 index facb874b18..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/utilsx4.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef SPX_UTILSX4_H -#define SPX_UTILSX4_H - -#include - -#include "context.h" -#include "params.h" - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - * - * This implementation uses AVX to compute internal nodes 4 at a time (in - * parallel) - */ -#define treehashx4 SPX_NAMESPACE(treehashx4) -void treehashx4(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leafx4)( - unsigned char * /* Where to write the leaves */, - const spx_ctx * /* ctx */, - uint32_t addr_idx, void *info), - uint32_t tree_addrx4[4 * 8], void *info); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/wots.c b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/wots.c deleted file mode 100644 index 4d5041ce05..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/wots.c +++ /dev/null @@ -1,269 +0,0 @@ -#include -#include - -#include "wots.h" - -#include "address.h" -#include "hash.h" -#include "hashx4.h" -#include "params.h" -#include "thash.h" -#include "thashx4.h" -#include "utils.h" -#include "utilsx4.h" -#include "wotsx4.h" - -// TODO clarify address expectations, and make them more uniform. -// TODO i.e. do we expect types to be set already? -// TODO and do we expect modifications or copies? - -/** - * Computes up the chains - */ -static void gen_chains( - unsigned char *out, - const unsigned char *in, - unsigned int start[SPX_WOTS_LEN], - const unsigned int steps[SPX_WOTS_LEN], - const spx_ctx *ctx, - uint32_t addr[8]) { - uint32_t i, j, k, idx, watching; - int done; - unsigned char empty[SPX_N]; - unsigned char *bufs[4]; - uint32_t addrs[8 * 4]; - - int l; - uint16_t counts[SPX_WOTS_W] = { 0 }; - uint16_t idxs[SPX_WOTS_LEN]; - uint16_t total, newTotal; - - /* set addrs = {addr, addr, addr, addr} */ - for (j = 0; j < 4; j++) { - memcpy(addrs + j * 8, addr, sizeof(uint32_t) * 8); - } - - /* Initialize out with the value at position 'start'. */ - memcpy(out, in, SPX_WOTS_LEN * SPX_N); - - /* Sort the chains in reverse order by steps using counting sort. */ - for (i = 0; i < SPX_WOTS_LEN; i++) { - counts[steps[i]]++; - } - total = 0; - for (l = SPX_WOTS_W - 1; l >= 0; l--) { - newTotal = counts[l] + total; - counts[l] = total; - total = newTotal; - } - for (i = 0; i < SPX_WOTS_LEN; i++) { - idxs[counts[steps[i]]] = (uint16_t)i; - counts[steps[i]]++; - } - - /* We got our work cut out for us: do it! */ - for (i = 0; i < SPX_WOTS_LEN; i += 4) { - for (j = 0; j < 4 && i + j < SPX_WOTS_LEN; j++) { - idx = idxs[i + j]; - set_chain_addr(addrs + j * 8, idx); - bufs[j] = out + SPX_N * idx; - } - - /* As the chains are sorted in reverse order, we know that the first - * chain is the longest and the last one is the shortest. We keep - * an eye on whether the last chain is done and then on the one before, - * et cetera. */ - watching = 3; - done = 0; - while (i + watching >= SPX_WOTS_LEN) { - bufs[watching] = &empty[0]; - watching--; - } - - for (k = 0;; k++) { - while (k == steps[idxs[i + watching]]) { - bufs[watching] = &empty[0]; - if (watching == 0) { - done = 1; - break; - } - watching--; - } - if (done) { - break; - } - for (j = 0; j < watching + 1; j++) { - set_hash_addr(addrs + j * 8, k + start[idxs[i + j]]); - } - - thashx4(bufs[0], bufs[1], bufs[2], bufs[3], - bufs[0], bufs[1], bufs[2], bufs[3], 1, ctx, addrs); - } - } -} - -/** - * base_w algorithm as described in draft. - * Interprets an array of bytes as integers in base w. - * This only works when log_w is a divisor of 8. - */ -static void base_w(unsigned int *output, const int out_len, - const unsigned char *input) { - int in = 0; - int out = 0; - unsigned char total = 0; - int bits = 0; - int consumed; - - for (consumed = 0; consumed < out_len; consumed++) { - if (bits == 0) { - total = input[in]; - in++; - bits += 8; - } - bits -= SPX_WOTS_LOGW; - output[out] = (total >> bits) & (SPX_WOTS_W - 1); - out++; - } -} - -/* Computes the WOTS+ checksum over a message (in base_w). */ -static void wots_checksum(unsigned int *csum_base_w, - const unsigned int *msg_base_w) { - unsigned int csum = 0; - unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; - unsigned int i; - - /* Compute checksum. */ - for (i = 0; i < SPX_WOTS_LEN1; i++) { - csum += SPX_WOTS_W - 1 - msg_base_w[i]; - } - - /* Convert checksum to base_w. */ - /* Make sure expected empty zero bits are the least significant bits. */ - csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); - ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); - base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); -} - -/* Takes a message and derives the matching chain lengths. */ -void chain_lengths(unsigned int *lengths, const unsigned char *msg) { - base_w(lengths, SPX_WOTS_LEN1, msg); - wots_checksum(lengths + SPX_WOTS_LEN1, lengths); -} - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const spx_ctx *ctx, uint32_t addr[8]) { - unsigned int steps[SPX_WOTS_LEN]; - unsigned int start[SPX_WOTS_LEN]; - uint32_t i; - - chain_lengths(start, msg); - - for (i = 0; i < SPX_WOTS_LEN; i++) { - steps[i] = SPX_WOTS_W - 1 - start[i]; - } - - gen_chains(pk, sig, start, steps, ctx, addr); -} - -/* - * This generates 4 sequential WOTS public keys - * It also generates the WOTS signature if leaf_info indicates - * that we're signing with one of these WOTS keys - */ -void wots_gen_leafx4(unsigned char *dest, - const spx_ctx *ctx, - uint32_t leaf_idx, void *v_info) { - struct leaf_info_x4 *info = v_info; - uint32_t *leaf_addr = info->leaf_addr; - uint32_t *pk_addr = info->pk_addr; - unsigned int i, j, k; - unsigned char pk_buffer[ 4 * SPX_WOTS_BYTES ]; - unsigned wots_offset = SPX_WOTS_BYTES; - unsigned char *buffer; - uint32_t wots_k_mask; - unsigned wots_sign_index; - - if (((leaf_idx ^ info->wots_sign_leaf) & ~3U) == 0) { - /* We're traversing the leaf that's signing; generate the WOTS */ - /* signature */ - wots_k_mask = 0; - wots_sign_index = info->wots_sign_leaf & 3; /* Which of of the 4 */ - /* 4 slots do the signatures come from */ - } else { - /* Nope, we're just generating pk's; turn off the signature logic */ - wots_k_mask = (uint32_t)~0; - wots_sign_index = 0; - } - - for (j = 0; j < 4; j++) { - set_keypair_addr( leaf_addr + j * 8, leaf_idx + j ); - set_keypair_addr( pk_addr + j * 8, leaf_idx + j ); - } - - for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { - uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k to */ - /* the step if we're generating a signature, ~0 if we're not */ - - /* Start with the secret seed */ - for (j = 0; j < 4; j++) { - set_chain_addr(leaf_addr + j * 8, i); - set_hash_addr(leaf_addr + j * 8, 0); - set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTSPRF); - } - prf_addrx4(buffer + 0 * wots_offset, - buffer + 1 * wots_offset, - buffer + 2 * wots_offset, - buffer + 3 * wots_offset, - ctx, leaf_addr); - - for (j = 0; j < 4; j++) { - set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTS); - } - - /* Iterate down the WOTS chain */ - for (k = 0;; k++) { - /* Check if one of the values we have needs to be saved as a */ - /* part of the WOTS signature */ - if (k == wots_k) { - memcpy( info->wots_sig + i * SPX_N, - buffer + wots_sign_index * wots_offset, SPX_N ); - } - - /* Check if we hit the top of the chain */ - if (k == SPX_WOTS_W - 1) { - break; - } - - /* Iterate one step on all 4 chains */ - for (j = 0; j < 4; j++) { - set_hash_addr(leaf_addr + j * 8, k); - } - thashx4(buffer + 0 * wots_offset, - buffer + 1 * wots_offset, - buffer + 2 * wots_offset, - buffer + 3 * wots_offset, - buffer + 0 * wots_offset, - buffer + 1 * wots_offset, - buffer + 2 * wots_offset, - buffer + 3 * wots_offset, 1, ctx, leaf_addr); - } - } - - /* Do the final thash to generate the public keys */ - thashx4(dest + 0 * SPX_N, - dest + 1 * SPX_N, - dest + 2 * SPX_N, - dest + 3 * SPX_N, - pk_buffer + 0 * wots_offset, - pk_buffer + 1 * wots_offset, - pk_buffer + 2 * wots_offset, - pk_buffer + 3 * wots_offset, SPX_WOTS_LEN, ctx, pk_addr); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/wots.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/wots.h deleted file mode 100644 index 4e7692eeef..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/wots.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef SPX_WOTS_H -#define SPX_WOTS_H - -#include - -#include "context.h" -#include "params.h" - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) -void wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const spx_ctx *ctx, uint32_t addr[8]); - -/* - * Compute the chain lengths needed for a given message hash - */ -#define chain_lengths SPX_NAMESPACE(chain_lengths) -void chain_lengths(unsigned int *lengths, const unsigned char *msg); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/wotsx4.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/wotsx4.h deleted file mode 100644 index cd634f1743..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_avx2/wotsx4.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef WOTSX4_H_ -#define WOTSX4_H_ - -#include - -#include "params.h" - -/* - * This is here to provide an interface to the internal wots_gen_leafx4 - * routine. While this routine is not referenced in the package outside of - * wots.c, it is called from the stand-alone benchmark code to characterize - * the performance - */ -struct leaf_info_x4 { - unsigned char *wots_sig; - uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ - uint32_t *wots_steps; - uint32_t leaf_addr[4 * 8]; - uint32_t pk_addr[4 * 8]; -}; - -/* Macro to set the leaf_info to something 'benign', that is, it would */ -/* run with the same time as it does during the real signing process */ -/* Used only by the benchmark code */ -#define INITIALIZE_LEAF_INFO_X4(info, addr, step_buffer) { \ - (info).wots_sig = 0; \ - (info).wots_sign_leaf = ~0; \ - (info).wots_steps = step_buffer; \ - int i; \ - for (i=0; i<4; i++) { \ - memcpy( &(info).leaf_addr[8*i], addr, 32 ); \ - memcpy( &(info).pk_addr[8*i], addr, 32 ); \ - } \ - } - -#define wots_gen_leafx4 SPX_NAMESPACE(wots_gen_leafx4) -void wots_gen_leafx4(unsigned char *dest, - const spx_ctx *ctx, - uint32_t leaf_idx, void *v_info); - -#endif /* WOTSX4_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/LICENSE b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/LICENSE deleted file mode 100644 index 670154e353..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/LICENSE +++ /dev/null @@ -1,116 +0,0 @@ -CC0 1.0 Universal - -Statement of Purpose - -The laws of most jurisdictions throughout the world automatically confer -exclusive Copyright and Related Rights (defined below) upon the creator and -subsequent owner(s) (each and all, an "owner") of an original work of -authorship and/or a database (each, a "Work"). - -Certain owners wish to permanently relinquish those rights to a Work for the -purpose of contributing to a commons of creative, cultural and scientific -works ("Commons") that the public can reliably and without fear of later -claims of infringement build upon, modify, incorporate in other works, reuse -and redistribute as freely as possible in any form whatsoever and for any -purposes, including without limitation commercial purposes. These owners may -contribute to the Commons to promote the ideal of a free culture and the -further production of creative, cultural and scientific works, or to gain -reputation or greater distribution for their Work in part through the use and -efforts of others. - -For these and/or other purposes and motivations, and without any expectation -of additional consideration or compensation, the person associating CC0 with a -Work (the "Affirmer"), to the extent that he or she is an owner of Copyright -and Related Rights in the Work, voluntarily elects to apply CC0 to the Work -and publicly distribute the Work under its terms, with knowledge of his or her -Copyright and Related Rights in the Work and the meaning and intended legal -effect of CC0 on those rights. - -1. Copyright and Related Rights. A Work made available under CC0 may be -protected by copyright and related or neighboring rights ("Copyright and -Related Rights"). Copyright and Related Rights include, but are not limited -to, the following: - - i. the right to reproduce, adapt, distribute, perform, display, communicate, - and translate a Work; - - ii. moral rights retained by the original author(s) and/or performer(s); - - iii. publicity and privacy rights pertaining to a person's image or likeness - depicted in a Work; - - iv. rights protecting against unfair competition in regards to a Work, - subject to the limitations in paragraph 4(a), below; - - v. rights protecting the extraction, dissemination, use and reuse of data in - a Work; - - vi. database rights (such as those arising under Directive 96/9/EC of the - European Parliament and of the Council of 11 March 1996 on the legal - protection of databases, and under any national implementation thereof, - including any amended or successor version of such directive); and - - vii. other similar, equivalent or corresponding rights throughout the world - based on applicable law or treaty, and any national implementations thereof. - -2. Waiver. To the greatest extent permitted by, but not in contravention of, -applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and -unconditionally waives, abandons, and surrenders all of Affirmer's Copyright -and Related Rights and associated claims and causes of action, whether now -known or unknown (including existing as well as future claims and causes of -action), in the Work (i) in all territories worldwide, (ii) for the maximum -duration provided by applicable law or treaty (including future time -extensions), (iii) in any current or future medium and for any number of -copies, and (iv) for any purpose whatsoever, including without limitation -commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes -the Waiver for the benefit of each member of the public at large and to the -detriment of Affirmer's heirs and successors, fully intending that such Waiver -shall not be subject to revocation, rescission, cancellation, termination, or -any other legal or equitable action to disrupt the quiet enjoyment of the Work -by the public as contemplated by Affirmer's express Statement of Purpose. - -3. Public License Fallback. Should any part of the Waiver for any reason be -judged legally invalid or ineffective under applicable law, then the Waiver -shall be preserved to the maximum extent permitted taking into account -Affirmer's express Statement of Purpose. In addition, to the extent the Waiver -is so judged Affirmer hereby grants to each affected person a royalty-free, -non transferable, non sublicensable, non exclusive, irrevocable and -unconditional license to exercise Affirmer's Copyright and Related Rights in -the Work (i) in all territories worldwide, (ii) for the maximum duration -provided by applicable law or treaty (including future time extensions), (iii) -in any current or future medium and for any number of copies, and (iv) for any -purpose whatsoever, including without limitation commercial, advertising or -promotional purposes (the "License"). The License shall be deemed effective as -of the date CC0 was applied by Affirmer to the Work. Should any part of the -License for any reason be judged legally invalid or ineffective under -applicable law, such partial invalidity or ineffectiveness shall not -invalidate the remainder of the License, and in such case Affirmer hereby -affirms that he or she will not (i) exercise any of his or her remaining -Copyright and Related Rights in the Work or (ii) assert any associated claims -and causes of action with respect to the Work, in either case contrary to -Affirmer's express Statement of Purpose. - -4. Limitations and Disclaimers. - - a. No trademark or patent rights held by Affirmer are waived, abandoned, - surrendered, licensed or otherwise affected by this document. - - b. Affirmer offers the Work as-is and makes no representations or warranties - of any kind concerning the Work, express, implied, statutory or otherwise, - including without limitation warranties of title, merchantability, fitness - for a particular purpose, non infringement, or the absence of latent or - other defects, accuracy, or the present or absence of errors, whether or not - discoverable, all to the greatest extent permissible under applicable law. - - c. Affirmer disclaims responsibility for clearing rights of other persons - that may apply to the Work or any use thereof, including without limitation - any person's Copyright and Related Rights in the Work. Further, Affirmer - disclaims responsibility for obtaining any necessary consents, permissions - or other rights required for any use of the Work. - - d. Affirmer understands and acknowledges that Creative Commons is not a - party to this document and has no duty or obligation with respect to this - CC0 or use of the Work. - -For more information, please see - diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/address.c b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/address.c deleted file mode 100644 index d49d9f3b6b..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/address.c +++ /dev/null @@ -1,95 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "utils.h" - -/* - * Specify which level of Merkle tree (the "layer") we're working on - */ -void set_layer_addr(uint32_t addr[8], uint32_t layer) { - ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; -} - -/* - * Specify which Merkle tree within the level (the "tree address") we're working on - */ -void set_tree_addr(uint32_t addr[8], uint64_t tree) { - ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); -} - -/* - * Specify the reason we'll use this address structure for, that is, what - * hash will we compute with it. This is used so that unrelated types of - * hashes don't accidentally get the same address structure. The type will be - * one of the SPX_ADDR_TYPE constants - */ -void set_type(uint32_t addr[8], uint32_t type) { - ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; -} - -/* - * Copy the layer and tree fields of the address structure. This is used - * when we're doing multiple types of hashes within the same Merkle tree - */ -void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { - memcpy( out, in, SPX_OFFSET_TREE + 8 ); -} - -/* These functions are used for OTS addresses. */ - -/* - * Specify which Merkle leaf we're working on; that is, which OTS keypair - * we're talking about. - */ -void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { - /* We have > 256 OTS at the bottom of the Merkle tree; to specify */ - /* which one, we'd need to express it in two bytes */ - ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR2] = (unsigned char)(keypair >> 8); - ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; -} - -/* - * Copy the layer, tree and keypair fields of the address structure. This is - * used when we're doing multiple things within the same OTS keypair - */ -void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { - memcpy( out, in, SPX_OFFSET_TREE + 8 ); - ((unsigned char *)out)[SPX_OFFSET_KP_ADDR2] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR2]; - ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; -} - -/* - * Specify which Merkle chain within the OTS we're working with - * (the chain address) - */ -void set_chain_addr(uint32_t addr[8], uint32_t chain) { - ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; -} - -/* - * Specify where in the Merkle chain we are -* (the hash address) - */ -void set_hash_addr(uint32_t addr[8], uint32_t hash) { - ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; -} - -/* These functions are used for all hash tree addresses (including FORS). */ - -/* - * Specify the height of the node in the Merkle/FORS tree we are in - * (the tree height) - */ -void set_tree_height(uint32_t addr[8], uint32_t tree_height) { - ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; -} - -/* - * Specify the distance from the left edge of the node in the Merkle/FORS tree - * (the tree index) - */ -void set_tree_index(uint32_t addr[8], uint32_t tree_index) { - u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/address.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/address.h deleted file mode 100644 index 24a84eb40c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/address.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef SPX_ADDRESS_H -#define SPX_ADDRESS_H - -#include - -#include "params.h" - -/* The hash types that are passed to set_type */ -#define SPX_ADDR_TYPE_WOTS 0 -#define SPX_ADDR_TYPE_WOTSPK 1 -#define SPX_ADDR_TYPE_HASHTREE 2 -#define SPX_ADDR_TYPE_FORSTREE 3 -#define SPX_ADDR_TYPE_FORSPK 4 -#define SPX_ADDR_TYPE_WOTSPRF 5 -#define SPX_ADDR_TYPE_FORSPRF 6 - -#define set_layer_addr SPX_NAMESPACE(set_layer_addr) -void set_layer_addr(uint32_t addr[8], uint32_t layer); - -#define set_tree_addr SPX_NAMESPACE(set_tree_addr) -void set_tree_addr(uint32_t addr[8], uint64_t tree); - -#define set_type SPX_NAMESPACE(set_type) -void set_type(uint32_t addr[8], uint32_t type); - -/* Copies the layer and tree part of one address into the other */ -#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) -void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for WOTS and FORS addresses. */ - -#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) -void set_keypair_addr(uint32_t addr[8], uint32_t keypair); - -#define set_chain_addr SPX_NAMESPACE(set_chain_addr) -void set_chain_addr(uint32_t addr[8], uint32_t chain); - -#define set_hash_addr SPX_NAMESPACE(set_hash_addr) -void set_hash_addr(uint32_t addr[8], uint32_t hash); - -#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) -void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for all hash tree addresses (including FORS). */ - -#define set_tree_height SPX_NAMESPACE(set_tree_height) -void set_tree_height(uint32_t addr[8], uint32_t tree_height); - -#define set_tree_index SPX_NAMESPACE(set_tree_index) -void set_tree_index(uint32_t addr[8], uint32_t tree_index); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/api.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/api.h deleted file mode 100644 index 7de1885b77..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/api.h +++ /dev/null @@ -1,77 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE192SROBUST_CLEAN_API_H -#define PQCLEAN_SPHINCSSHAKE192SROBUST_CLEAN_API_H - -#include -#include - -#define PQCLEAN_SPHINCSSHAKE192SROBUST_CLEAN_CRYPTO_ALGNAME "SPHINCS+-shake-192s-robust" - -#define PQCLEAN_SPHINCSSHAKE192SROBUST_CLEAN_CRYPTO_SECRETKEYBYTES 96 -#define PQCLEAN_SPHINCSSHAKE192SROBUST_CLEAN_CRYPTO_PUBLICKEYBYTES 48 -#define PQCLEAN_SPHINCSSHAKE192SROBUST_CLEAN_CRYPTO_BYTES 16224 - -#define PQCLEAN_SPHINCSSHAKE192SROBUST_CLEAN_CRYPTO_SEEDBYTES 72 - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE192SROBUST_CLEAN_crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE192SROBUST_CLEAN_crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE192SROBUST_CLEAN_crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE192SROBUST_CLEAN_crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHAKE192SROBUST_CLEAN_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHAKE192SROBUST_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSSHAKE192SROBUST_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE192SROBUST_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, - const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSSHAKE192SROBUST_CLEAN_crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE192SROBUST_CLEAN_crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk); -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/context.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/context.h deleted file mode 100644 index 9f8a40ab4e..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/context.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef SPX_CONTEXT_H -#define SPX_CONTEXT_H - -#include -#include - -#include "params.h" - -typedef struct { - uint8_t pub_seed[SPX_N]; - uint8_t sk_seed[SPX_N]; - - -} spx_ctx; - -#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) -void initialize_hash_function(spx_ctx *ctx); - -#define free_hash_function SPX_NAMESPACE(free_hash_function) -void free_hash_function(spx_ctx *ctx); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/context_shake.c b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/context_shake.c deleted file mode 100644 index 9614a103d3..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/context_shake.c +++ /dev/null @@ -1,12 +0,0 @@ -#include "context.h" - -/* For SHAKE256, there is no immediate reason to initialize at the start, - so this function is an empty operation. */ -void initialize_hash_function(spx_ctx *ctx) { - (void)ctx; /* Suppress an 'unused parameter' warning. */ -} - -// in case the hash function api is heap-based. -void free_hash_function(spx_ctx *ctx) { - (void)ctx; -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/fors.c b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/fors.c deleted file mode 100644 index 96ca72e986..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/fors.c +++ /dev/null @@ -1,156 +0,0 @@ -#include -#include -#include - -#include "fors.h" - -#include "address.h" -#include "hash.h" -#include "thash.h" -#include "utils.h" -#include "utilsx1.h" - -static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, - uint32_t fors_leaf_addr[8]) { - prf_addr(sk, ctx, fors_leaf_addr); -} - -static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, - const spx_ctx *ctx, - uint32_t fors_leaf_addr[8]) { - thash(leaf, sk, 1, ctx, fors_leaf_addr); -} - -struct fors_gen_leaf_info { - uint32_t leaf_addrx[8]; -}; - -static void fors_gen_leafx1(unsigned char *leaf, - const spx_ctx *ctx, - uint32_t addr_idx, void *info) { - struct fors_gen_leaf_info *fors_info = info; - uint32_t *fors_leaf_addr = fors_info->leaf_addrx; - - /* Only set the parts that the caller doesn't set */ - set_tree_index(fors_leaf_addr, addr_idx); - set_type(fors_leaf_addr, SPX_ADDR_TYPE_FORSPRF); - fors_gen_sk(leaf, ctx, fors_leaf_addr); - - set_type(fors_leaf_addr, SPX_ADDR_TYPE_FORSTREE); - fors_sk_to_leaf(leaf, leaf, - ctx, fors_leaf_addr); -} - -/** - * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - * Assumes indices has space for SPX_FORS_TREES integers. - */ -static void message_to_indices(uint32_t *indices, const unsigned char *m) { - unsigned int i, j; - unsigned int offset = 0; - - for (i = 0; i < SPX_FORS_TREES; i++) { - indices[i] = 0; - for (j = 0; j < SPX_FORS_HEIGHT; j++) { - indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); - offset++; - } - } -} - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -void fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]) { - uint32_t indices[SPX_FORS_TREES]; - unsigned char roots[SPX_FORS_TREES * SPX_N]; - uint32_t fors_tree_addr[8] = {0}; - struct fors_gen_leaf_info fors_info = {0}; - uint32_t *fors_leaf_addr = fors_info.leaf_addrx; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - copy_keypair_addr(fors_tree_addr, fors_addr); - copy_keypair_addr(fors_leaf_addr, fors_addr); - - copy_keypair_addr(fors_pk_addr, fors_addr); - set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < SPX_FORS_TREES; i++) { - idx_offset = i * (1 << SPX_FORS_HEIGHT); - - set_tree_height(fors_tree_addr, 0); - set_tree_index(fors_tree_addr, indices[i] + idx_offset); - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); - - /* Include the secret key part that produces the selected leaf node. */ - fors_gen_sk(sig, ctx, fors_tree_addr); - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); - sig += SPX_N; - - /* Compute the authentication path for this leaf node. */ - treehashx1(roots + i * SPX_N, sig, ctx, - indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx1, - fors_tree_addr, &fors_info); - - sig += SPX_N * SPX_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); -} - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -void fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]) { - uint32_t indices[SPX_FORS_TREES]; - unsigned char roots[SPX_FORS_TREES * SPX_N]; - unsigned char leaf[SPX_N]; - uint32_t fors_tree_addr[8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - copy_keypair_addr(fors_tree_addr, fors_addr); - copy_keypair_addr(fors_pk_addr, fors_addr); - - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); - set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < SPX_FORS_TREES; i++) { - idx_offset = i * (1 << SPX_FORS_HEIGHT); - - set_tree_height(fors_tree_addr, 0); - set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Derive the leaf from the included secret key part. */ - fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); - sig += SPX_N; - - /* Derive the corresponding root node of this tree. */ - compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, - sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); - sig += SPX_N * SPX_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/fors.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/fors.h deleted file mode 100644 index 509140a178..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/fors.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef SPX_FORS_H -#define SPX_FORS_H - -#include - -#include "context.h" -#include "params.h" - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -#define fors_sign SPX_NAMESPACE(fors_sign) -void fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]); - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) -void fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/hash.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/hash.h deleted file mode 100644 index f7c87d4c3c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/hash.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef SPX_HASH_H -#define SPX_HASH_H - -#include -#include - -#include "context.h" -#include "params.h" - -#define prf_addr SPX_NAMESPACE(prf_addr) -void prf_addr(unsigned char *out, const spx_ctx *ctx, - const uint32_t addr[8]); - -#define gen_message_random SPX_NAMESPACE(gen_message_random) -void gen_message_random(unsigned char *R, const unsigned char *sk_prf, - const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx); - -#define hash_message SPX_NAMESPACE(hash_message) -void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx); - - - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/hash_shake.c b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/hash_shake.c deleted file mode 100644 index ff5e7ec918..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/hash_shake.c +++ /dev/null @@ -1,83 +0,0 @@ -#include -#include - -#include "hash.h" - -#include "address.h" -#include "fips202.h" -#include "params.h" -#include "utils.h" - -/* - * Computes PRF(pk_seed, sk_seed, addr) - */ -void prf_addr(unsigned char *out, const spx_ctx *ctx, - const uint32_t addr[8]) { - unsigned char buf[2 * SPX_N + SPX_ADDR_BYTES]; - - memcpy(buf, ctx->pub_seed, SPX_N); - memcpy(buf + SPX_N, addr, SPX_ADDR_BYTES); - memcpy(buf + SPX_N + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); - - shake256(out, SPX_N, buf, 2 * SPX_N + SPX_ADDR_BYTES); -} - -/** - * Computes the message-dependent randomness R, using a secret seed and an - * optional randomization value as well as the message. - */ -void gen_message_random(unsigned char *R, const unsigned char *sk_prf, - const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx) { - (void)ctx; - shake256incctx s_inc; - - shake256_inc_init(&s_inc); - shake256_inc_absorb(&s_inc, sk_prf, SPX_N); - shake256_inc_absorb(&s_inc, optrand, SPX_N); - shake256_inc_absorb(&s_inc, m, mlen); - shake256_inc_finalize(&s_inc); - shake256_inc_squeeze(R, SPX_N, &s_inc); - shake256_inc_ctx_release(&s_inc); -} - -/** - * Computes the message hash using R, the public key, and the message. - * Outputs the message digest and the index of the leaf. The index is split in - * the tree index and the leaf index, for convenient copying to an address. - */ -void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx) { - (void)ctx; -#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) -#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) -#define SPX_LEAF_BITS SPX_TREE_HEIGHT -#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) -#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) - - unsigned char buf[SPX_DGST_BYTES]; - unsigned char *bufp = buf; - shake256incctx s_inc; - - shake256_inc_init(&s_inc); - shake256_inc_absorb(&s_inc, R, SPX_N); - shake256_inc_absorb(&s_inc, pk, SPX_PK_BYTES); - shake256_inc_absorb(&s_inc, m, mlen); - shake256_inc_finalize(&s_inc); - shake256_inc_squeeze(buf, SPX_DGST_BYTES, &s_inc); - shake256_inc_ctx_release(&s_inc); - - memcpy(digest, bufp, SPX_FORS_MSG_BYTES); - bufp += SPX_FORS_MSG_BYTES; - - - *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); - *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); - bufp += SPX_TREE_BYTES; - - *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); - *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/merkle.c b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/merkle.c deleted file mode 100644 index 0c1479fd93..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/merkle.c +++ /dev/null @@ -1,59 +0,0 @@ -#include -#include - -#include "address.h" -#include "merkle.h" -#include "params.h" -#include "utils.h" -#include "utilsx1.h" -#include "wots.h" -#include "wotsx1.h" - -/* - * This generates a Merkle signature (WOTS signature followed by the Merkle - * authentication path). This is in this file because most of the complexity - * is involved with the WOTS signature; the Merkle authentication path logic - * is mostly hidden in treehashx4 - */ -void merkle_sign(uint8_t *sig, unsigned char *root, - const spx_ctx *ctx, - uint32_t wots_addr[8], uint32_t tree_addr[8], - uint32_t idx_leaf) { - unsigned char *auth_path = sig + SPX_WOTS_BYTES; - struct leaf_info_x1 info = { 0 }; - unsigned steps[ SPX_WOTS_LEN ]; - - info.wots_sig = sig; - chain_lengths(steps, root); - info.wots_steps = steps; - - set_type(&tree_addr[0], SPX_ADDR_TYPE_HASHTREE); - set_type(&info.pk_addr[0], SPX_ADDR_TYPE_WOTSPK); - copy_subtree_addr(&info.leaf_addr[0], wots_addr); - copy_subtree_addr(&info.pk_addr[0], wots_addr); - - info.wots_sign_leaf = idx_leaf; - - treehashx1(root, auth_path, ctx, - idx_leaf, 0, - SPX_TREE_HEIGHT, - wots_gen_leafx1, - tree_addr, &info); -} - -/* Compute root node of the top-most subtree. */ -void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { - /* We do not need the auth path in key generation, but it simplifies the - code to have just one treehash routine that computes both root and path - in one function. */ - unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; - uint32_t top_tree_addr[8] = {0}; - uint32_t wots_addr[8] = {0}; - - set_layer_addr(top_tree_addr, SPX_D - 1); - set_layer_addr(wots_addr, SPX_D - 1); - - merkle_sign(auth_path, root, ctx, - wots_addr, top_tree_addr, - (uint32_t)~0 /* ~0 means "don't bother generating an auth path */ ); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/merkle.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/merkle.h deleted file mode 100644 index 769cf2e970..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/merkle.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef MERKLE_H_ -#define MERKLE_H_ - -#include - -#include "context.h" -#include "params.h" - -/* Generate a Merkle signature (WOTS signature followed by the Merkle */ -/* authentication path) */ -#define merkle_sign SPX_NAMESPACE(merkle_sign) -void merkle_sign(uint8_t *sig, unsigned char *root, - const spx_ctx *ctx, - uint32_t wots_addr[8], uint32_t tree_addr[8], - uint32_t idx_leaf); - -/* Compute the root node of the top-most subtree. */ -#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) -void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); - -#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/nistapi.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/nistapi.h deleted file mode 100644 index 3cb71afad4..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/nistapi.h +++ /dev/null @@ -1,87 +0,0 @@ -#ifndef SPX_API_H -#define SPX_API_H - -#include -#include - -#include "params.h" - -#define CRYPTO_ALGNAME "SPHINCS+" - -#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES -#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES -#define CRYPTO_BYTES SPX_BYTES -#define CRYPTO_SEEDBYTES (3*SPX_N) - -/* - * Returns the length of a secret key, in bytes - */ -#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) -size_t crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) -size_t crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) -size_t crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) -size_t crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) -int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) -int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) -int crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) -int crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -#define crypto_sign SPX_NAMESPACE(crypto_sign) -int crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) -int crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/params.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/params.h deleted file mode 100644 index aa0173dce4..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/params.h +++ /dev/null @@ -1,56 +0,0 @@ -#ifndef SPX_PARAMS_H -#define SPX_PARAMS_H - -#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSSHAKE192SROBUST_CLEAN_##s - -/* Hash output length in bytes. */ -#define SPX_N 24 -/* Height of the hypertree. */ -#define SPX_FULL_HEIGHT 63 -/* Number of subtree layer. */ -#define SPX_D 7 -/* FORS tree dimensions. */ -#define SPX_FORS_HEIGHT 14 -#define SPX_FORS_TREES 17 -/* Winternitz parameter, */ -#define SPX_WOTS_W 16 - -/* The hash function is defined by linking a different hash.c file, as opposed - to setting a #define constant. */ - -/* For clarity */ -#define SPX_ADDR_BYTES 32 - -/* WOTS parameters. */ -#define SPX_WOTS_LOGW 4 - -#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) - -/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#define SPX_WOTS_LEN2 3 - -#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) -#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) -#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES - -/* Subtree size. */ -#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) - -//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT -// #error SPX_D should always divide SPX_FULL_HEIGHT -//#endif - -/* FORS parameters. */ -#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) -#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) -#define SPX_FORS_PK_BYTES SPX_N - -/* Resulting SPX sizes. */ -#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ - SPX_FULL_HEIGHT * SPX_N) -#define SPX_PK_BYTES (2 * SPX_N) -#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) - -#include "shake_offsets.h" - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/shake_offsets.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/shake_offsets.h deleted file mode 100644 index 6b28d95d91..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/shake_offsets.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef SHAKE_OFFSETS_H_ -#define SHAKE_OFFSETS_H_ - -/* - * Offsets of various fields in the address structure when we use SHAKE as - * the Sphincs+ hash function - */ - -#define SPX_OFFSET_LAYER 3 /* The byte used to specify the Merkle tree layer */ -#define SPX_OFFSET_TREE 8 /* The start of the 8 byte field used to specify the tree */ -#define SPX_OFFSET_TYPE 19 /* The byte used to specify the hash type (reason) */ -#define SPX_OFFSET_KP_ADDR2 22 /* The high byte used to specify the key pair (which one-time signature) */ -#define SPX_OFFSET_KP_ADDR1 23 /* The low byte used to specify the key pair */ -#define SPX_OFFSET_CHAIN_ADDR 27 /* The byte used to specify the chain address (which Winternitz chain) */ -#define SPX_OFFSET_HASH_ADDR 31 /* The byte used to specify the hash address (where in the Winternitz chain) */ -#define SPX_OFFSET_TREE_HGT 27 /* The byte used to specify the height of this node in the FORS or Merkle tree */ -#define SPX_OFFSET_TREE_INDEX 28 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ - -#define SPX_SHAKE 1 - -#endif /* SHAKE_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/sign.c b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/sign.c deleted file mode 100644 index 9d0c7d1b22..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/sign.c +++ /dev/null @@ -1,286 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "context.h" -#include "fors.h" -#include "hash.h" -#include "merkle.h" -#include "nistapi.h" -#include "params.h" -#include "randombytes.h" -#include "thash.h" -#include "utils.h" -#include "wots.h" - -/* - * Returns the length of a secret key, in bytes - */ -size_t crypto_sign_secretkeybytes(void) { - return CRYPTO_SECRETKEYBYTES; -} - -/* - * Returns the length of a public key, in bytes - */ -size_t crypto_sign_publickeybytes(void) { - return CRYPTO_PUBLICKEYBYTES; -} - -/* - * Returns the length of a signature, in bytes - */ -size_t crypto_sign_bytes(void) { - return CRYPTO_BYTES; -} - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t crypto_sign_seedbytes(void) { - return CRYPTO_SEEDBYTES; -} - -/* - * Generates an SPX key pair given a seed of length - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed) { - spx_ctx ctx; - - /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ - memcpy(sk, seed, CRYPTO_SEEDBYTES); - - memcpy(pk, sk + 2 * SPX_N, SPX_N); - - memcpy(ctx.pub_seed, pk, SPX_N); - memcpy(ctx.sk_seed, sk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - /* Compute root node of the top-most subtree. */ - merkle_gen_root(sk + 3 * SPX_N, &ctx); - - // cleanup - free_hash_function(&ctx); - - memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); - - return 0; -} - -/* - * Generates an SPX key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { - uint8_t seed[CRYPTO_SEEDBYTES]; - randombytes(seed, CRYPTO_SEEDBYTES); - crypto_sign_seed_keypair(pk, sk, seed); - - return 0; -} - -/** - * Returns an array containing a detached signature. - */ -int crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - spx_ctx ctx; - - const uint8_t *sk_prf = sk + SPX_N; - const uint8_t *pk = sk + 2 * SPX_N; - - uint8_t optrand[SPX_N]; - uint8_t mhash[SPX_FORS_MSG_BYTES]; - uint8_t root[SPX_N]; - uint32_t i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - - memcpy(ctx.sk_seed, sk, SPX_N); - memcpy(ctx.pub_seed, pk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - set_type(wots_addr, SPX_ADDR_TYPE_WOTS); - set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); - - /* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ - randombytes(optrand, SPX_N); - /* Compute the digest randomization value. */ - gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); - - /* Derive the message digest and leaf index from R, PK and M. */ - hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); - sig += SPX_N; - - set_tree_addr(wots_addr, tree); - set_keypair_addr(wots_addr, idx_leaf); - - /* Sign the message hash using FORS. */ - fors_sign(sig, root, mhash, &ctx, wots_addr); - sig += SPX_FORS_BYTES; - - for (i = 0; i < SPX_D; i++) { - set_layer_addr(tree_addr, i); - set_tree_addr(tree_addr, tree); - - copy_subtree_addr(wots_addr, tree_addr); - set_keypair_addr(wots_addr, idx_leaf); - - merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); - sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); - tree = tree >> SPX_TREE_HEIGHT; - } - - free_hash_function(&ctx); - - *siglen = SPX_BYTES; - - return 0; -} - -/** - * Verifies a detached signature and message under a given public key. - */ -int crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk) { - spx_ctx ctx; - const uint8_t *pub_root = pk + SPX_N; - uint8_t mhash[SPX_FORS_MSG_BYTES]; - uint8_t wots_pk[SPX_WOTS_BYTES]; - uint8_t root[SPX_N]; - uint8_t leaf[SPX_N]; - unsigned int i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - if (siglen != SPX_BYTES) { - return -1; - } - - memcpy(ctx.pub_seed, pk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - set_type(wots_addr, SPX_ADDR_TYPE_WOTS); - set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); - set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); - - /* Derive the message digest and leaf index from R || PK || M. */ - /* The additional SPX_N is a result of the hash domain separator. */ - hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); - sig += SPX_N; - - /* Layer correctly defaults to 0, so no need to set_layer_addr */ - set_tree_addr(wots_addr, tree); - set_keypair_addr(wots_addr, idx_leaf); - - fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); - sig += SPX_FORS_BYTES; - - /* For each subtree.. */ - for (i = 0; i < SPX_D; i++) { - set_layer_addr(tree_addr, i); - set_tree_addr(tree_addr, tree); - - copy_subtree_addr(wots_addr, tree_addr); - set_keypair_addr(wots_addr, idx_leaf); - - copy_keypair_addr(wots_pk_addr, wots_addr); - - /* The WOTS public key is only correct if the signature was correct. */ - /* Initially, root is the FORS pk, but on subsequent iterations it is - the root of the subtree below the currently processed subtree. */ - wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); - sig += SPX_WOTS_BYTES; - - /* Compute the leaf node using the WOTS public key. */ - thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); - - /* Compute the root node of this subtree. */ - compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, - &ctx, tree_addr); - sig += SPX_TREE_HEIGHT * SPX_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); - tree = tree >> SPX_TREE_HEIGHT; - } - - // cleanup - free_hash_function(&ctx); - - /* Check if the root node equals the root node in the public key. */ - if (memcmp(root, pub_root, SPX_N) != 0) { - return -1; - } - - return 0; -} - - -/** - * Returns an array containing the signature followed by the message. - */ -int crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk) { - size_t siglen; - - crypto_sign_signature(sm, &siglen, m, mlen, sk); - - memmove(sm + SPX_BYTES, m, mlen); - *smlen = siglen + mlen; - - return 0; -} - -/** - * Verifies a given signature-message pair under a given public key. - */ -int crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk) { - /* The API caller does not necessarily know what size a signature should be - but SPHINCS+ signatures are always exactly SPX_BYTES. */ - if (smlen < SPX_BYTES) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - *mlen = smlen - SPX_BYTES; - - if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - /* If verification was successful, move the message to the right place. */ - memmove(m, sm + SPX_BYTES, *mlen); - - return 0; -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/thash.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/thash.h deleted file mode 100644 index 8687ccfb4d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/thash.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef SPX_THASH_H -#define SPX_THASH_H - -#include "context.h" -#include "params.h" - -#include - -#define thash SPX_NAMESPACE(thash) -void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/thash_shake_robust.c b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/thash_shake_robust.c deleted file mode 100644 index 696d53c5cc..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/thash_shake_robust.c +++ /dev/null @@ -1,31 +0,0 @@ -#include -#include - -#include "thash.h" - -#include "address.h" -#include "params.h" -#include "utils.h" - -#include "fips202.h" - -/** - * Takes an array of inblocks concatenated arrays of SPX_N bytes. - */ -void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]) { - PQCLEAN_VLA(uint8_t, buf, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); - PQCLEAN_VLA(uint8_t, bitmask, inblocks * SPX_N); - unsigned int i; - - memcpy(buf, ctx->pub_seed, SPX_N); - memcpy(buf + SPX_N, addr, SPX_ADDR_BYTES); - - shake256(bitmask, inblocks * SPX_N, buf, SPX_N + SPX_ADDR_BYTES); - - for (i = 0; i < inblocks * SPX_N; i++) { - buf[SPX_N + SPX_ADDR_BYTES + i] = in[i] ^ bitmask[i]; - } - - shake256(out, SPX_N, buf, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/utils.c b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/utils.c deleted file mode 100644 index 177b541fb9..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/utils.c +++ /dev/null @@ -1,148 +0,0 @@ -#include - -#include "utils.h" - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "thash.h" - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void ull_to_bytes(unsigned char *out, unsigned int outlen, - unsigned long long in) { - int i; - - /* Iterate over out in decreasing order, for big-endianness. */ - for (i = (signed int)outlen - 1; i >= 0; i--) { - out[i] = in & 0xff; - in = in >> 8; - } -} - -void u32_to_bytes(unsigned char *out, uint32_t in) { - out[0] = (unsigned char)(in >> 24); - out[1] = (unsigned char)(in >> 16); - out[2] = (unsigned char)(in >> 8); - out[3] = (unsigned char)in; -} - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { - unsigned long long retval = 0; - unsigned int i; - - for (i = 0; i < inlen; i++) { - retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); - } - return retval; -} - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void compute_root(unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const spx_ctx *ctx, uint32_t addr[8]) { - uint32_t i; - unsigned char buffer[2 * SPX_N]; - - /* If leaf_idx is odd (last bit = 1), current path element is a right child - and auth_path has to go left. Otherwise it is the other way around. */ - if (leaf_idx & 1) { - memcpy(buffer + SPX_N, leaf, SPX_N); - memcpy(buffer, auth_path, SPX_N); - } else { - memcpy(buffer, leaf, SPX_N); - memcpy(buffer + SPX_N, auth_path, SPX_N); - } - auth_path += SPX_N; - - for (i = 0; i < tree_height - 1; i++) { - leaf_idx >>= 1; - idx_offset >>= 1; - /* Set the address of the node we're creating. */ - set_tree_height(addr, i + 1); - set_tree_index(addr, leaf_idx + idx_offset); - - /* Pick the right or left neighbor, depending on parity of the node. */ - if (leaf_idx & 1) { - thash(buffer + SPX_N, buffer, 2, ctx, addr); - memcpy(buffer, auth_path, SPX_N); - } else { - thash(buffer, buffer, 2, ctx, addr); - memcpy(buffer + SPX_N, auth_path, SPX_N); - } - auth_path += SPX_N; - } - - /* The last iteration is exceptional; we do not copy an auth_path node. */ - leaf_idx >>= 1; - idx_offset >>= 1; - set_tree_height(addr, tree_height); - set_tree_index(addr, leaf_idx + idx_offset); - thash(root, buffer, 2, ctx, addr); -} - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const spx_ctx * /* ctx */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), - uint32_t tree_addr[8]) { - PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); - PQCLEAN_VLA(unsigned int, heights, tree_height + 1); - unsigned int offset = 0; - uint32_t idx; - uint32_t tree_idx; - - for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { - /* Add the next leaf node to the stack. */ - gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); - offset++; - heights[offset - 1] = 0; - - /* If this is a node we need for the auth path.. */ - if ((leaf_idx ^ 0x1) == idx) { - memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); - } - - /* While the top-most nodes are of equal height.. */ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { - /* Compute index of the new node, in the next layer. */ - tree_idx = (idx >> (heights[offset - 1] + 1)); - - /* Set the address of the node we're creating. */ - set_tree_height(tree_addr, heights[offset - 1] + 1); - set_tree_index(tree_addr, - tree_idx + (idx_offset >> (heights[offset - 1] + 1))); - /* Hash the top-most nodes from the stack together. */ - thash(stack + (offset - 2)*SPX_N, - stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); - offset--; - /* Note that the top-most node is now one layer higher. */ - heights[offset - 1]++; - - /* If this is a node we need for the auth path.. */ - if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_path + heights[offset - 1]*SPX_N, - stack + (offset - 1)*SPX_N, SPX_N); - } - } - } - memcpy(root, stack, SPX_N); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/utils.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/utils.h deleted file mode 100644 index 64f5d5a53a..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/utils.h +++ /dev/null @@ -1,58 +0,0 @@ -#ifndef SPX_UTILS_H -#define SPX_UTILS_H - -#include - -#include "compat.h" -#include "context.h" -#include "params.h" - - -/* To support MSVC use alloca() instead of VLAs. See #20. */ - - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) -void ull_to_bytes(unsigned char *out, unsigned int outlen, - unsigned long long in); -#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) -void u32_to_bytes(unsigned char *out, uint32_t in); - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) -unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -#define compute_root SPX_NAMESPACE(compute_root) -void compute_root(unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const spx_ctx *ctx, uint32_t addr[8]); - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -#define treehash SPX_NAMESPACE(treehash) -void treehash(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const spx_ctx *ctx /* ctx */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), - uint32_t tree_addr[8]); - - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/utilsx1.c b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/utilsx1.c deleted file mode 100644 index fccb69b35d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/utilsx1.c +++ /dev/null @@ -1,100 +0,0 @@ -#include - -#include "utilsx1.h" - -#include "address.h" -#include "params.h" -#include "thash.h" -#include "utils.h" - -/* - * Generate the entire Merkle tree, computing the authentication path for - * leaf_idx, and the resulting root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) - * - * This expects tree_addr to be initialized to the addr structures for the - * Merkle tree nodes - * - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - * - * This works by using the standard Merkle tree building algorithm, - */ -void treehashx1(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, - uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* Where to write the leaves */, - const spx_ctx * /* ctx */, - uint32_t idx, void *info), - uint32_t tree_addr[8], - void *info) { - /* This is where we keep the intermediate nodes */ - PQCLEAN_VLA(uint8_t, stack, tree_height * SPX_N); - - uint32_t idx; - uint32_t max_idx = (uint32_t)((1 << tree_height) - 1); - for (idx = 0;; idx++) { - unsigned char current[2 * SPX_N]; /* Current logical node is at */ - /* index[SPX_N]. We do this to minimize the number of copies */ - /* needed during a thash */ - gen_leaf( ¤t[SPX_N], ctx, idx + idx_offset, - info ); - - /* Now combine the freshly generated right node with previously */ - /* generated left ones */ - uint32_t internal_idx_offset = idx_offset; - uint32_t internal_idx = idx; - uint32_t internal_leaf = leaf_idx; - uint32_t h; /* The height we are in the Merkle tree */ - for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { - - /* Check if we hit the top of the tree */ - if (h == tree_height) { - /* We hit the root; return it */ - memcpy( root, ¤t[SPX_N], SPX_N ); - return; - } - - /* - * Check if the node we have is a part of the - * authentication path; if it is, write it out - */ - if ((internal_idx ^ internal_leaf) == 0x01) { - memcpy( &auth_path[ h * SPX_N ], - ¤t[SPX_N], - SPX_N ); - } - - /* - * Check if we're at a left child; if so, stop going up the stack - * Exception: if we've reached the end of the tree, keep on going - * (so we combine the last 4 nodes into the one root node in two - * more iterations) - */ - if ((internal_idx & 1) == 0 && idx < max_idx) { - break; - } - - /* Ok, we're at a right node */ - /* Now combine the left and right logical nodes together */ - - /* Set the address of the node we're creating. */ - internal_idx_offset >>= 1; - set_tree_height(tree_addr, h + 1); - set_tree_index(tree_addr, internal_idx / 2 + internal_idx_offset ); - - unsigned char *left = &stack[h * SPX_N]; - memcpy( ¤t[0], left, SPX_N ); - thash( ¤t[1 * SPX_N], - ¤t[0 * SPX_N], - 2, ctx, tree_addr); - } - - /* We've hit a left child; save the current for when we get the */ - /* corresponding right right */ - memcpy( &stack[h * SPX_N], ¤t[SPX_N], SPX_N); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/utilsx1.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/utilsx1.h deleted file mode 100644 index e911d17d53..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/utilsx1.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef SPX_UTILSX4_H -#define SPX_UTILSX4_H - -#include - -#include "context.h" -#include "params.h" - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -#define treehashx1 SPX_NAMESPACE(treehashx1) -void treehashx1(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* Where to write the leaf */, - const spx_ctx * /* ctx */, - uint32_t addr_idx, void *info), - uint32_t tree_addrx4[8], void *info); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/wots.c b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/wots.c deleted file mode 100644 index 249717aaa8..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/wots.c +++ /dev/null @@ -1,108 +0,0 @@ -#include -#include - -#include "wots.h" -#include "wotsx1.h" - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "thash.h" -#include "utils.h" -#include "utilsx1.h" - -// TODO clarify address expectations, and make them more uniform. -// TODO i.e. do we expect types to be set already? -// TODO and do we expect modifications or copies? - -/** - * Computes the chaining function. - * out and in have to be n-byte arrays. - * - * Interprets in as start-th value of the chain. - * addr has to contain the address of the chain. - */ -static void gen_chain(unsigned char *out, const unsigned char *in, - unsigned int start, unsigned int steps, - const spx_ctx *ctx, uint32_t addr[8]) { - uint32_t i; - - /* Initialize out with the value at position 'start'. */ - memcpy(out, in, SPX_N); - - /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < SPX_WOTS_W; i++) { - set_hash_addr(addr, i); - thash(out, out, 1, ctx, addr); - } -} - -/** - * base_w algorithm as described in draft. - * Interprets an array of bytes as integers in base w. - * This only works when log_w is a divisor of 8. - */ -static void base_w(unsigned int *output, const int out_len, - const unsigned char *input) { - int in = 0; - int out = 0; - unsigned char total = 0; - int bits = 0; - int consumed; - - for (consumed = 0; consumed < out_len; consumed++) { - if (bits == 0) { - total = input[in]; - in++; - bits += 8; - } - bits -= SPX_WOTS_LOGW; - output[out] = (total >> bits) & (SPX_WOTS_W - 1); - out++; - } -} - -/* Computes the WOTS+ checksum over a message (in base_w). */ -static void wots_checksum(unsigned int *csum_base_w, - const unsigned int *msg_base_w) { - unsigned int csum = 0; - unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; - unsigned int i; - - /* Compute checksum. */ - for (i = 0; i < SPX_WOTS_LEN1; i++) { - csum += SPX_WOTS_W - 1 - msg_base_w[i]; - } - - /* Convert checksum to base_w. */ - /* Make sure expected empty zero bits are the least significant bits. */ - csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); - ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); - base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); -} - -/* Takes a message and derives the matching chain lengths. */ -void chain_lengths(unsigned int *lengths, const unsigned char *msg) { - base_w(lengths, SPX_WOTS_LEN1, msg); - wots_checksum(lengths + SPX_WOTS_LEN1, lengths); -} - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const spx_ctx *ctx, uint32_t addr[8]) { - unsigned int lengths[SPX_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < SPX_WOTS_LEN; i++) { - set_chain_addr(addr, i); - gen_chain(pk + i * SPX_N, sig + i * SPX_N, - lengths[i], SPX_WOTS_W - 1 - lengths[i], ctx, addr); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/wots.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/wots.h deleted file mode 100644 index 4e7692eeef..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/wots.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef SPX_WOTS_H -#define SPX_WOTS_H - -#include - -#include "context.h" -#include "params.h" - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) -void wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const spx_ctx *ctx, uint32_t addr[8]); - -/* - * Compute the chain lengths needed for a given message hash - */ -#define chain_lengths SPX_NAMESPACE(chain_lengths) -void chain_lengths(unsigned int *lengths, const unsigned char *msg); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/wotsx1.c b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/wotsx1.c deleted file mode 100644 index 3adec78dfb..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/wotsx1.c +++ /dev/null @@ -1,76 +0,0 @@ -#include -#include - -#include "wots.h" -#include "wotsx1.h" - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "thash.h" -#include "utils.h" - -/* - * This generates a WOTS public key - * It also generates the WOTS signature if leaf_info indicates - * that we're signing with this WOTS key - */ -void wots_gen_leafx1(unsigned char *dest, - const spx_ctx *ctx, - uint32_t leaf_idx, void *v_info) { - struct leaf_info_x1 *info = v_info; - uint32_t *leaf_addr = info->leaf_addr; - uint32_t *pk_addr = info->pk_addr; - unsigned int i, k; - unsigned char pk_buffer[ SPX_WOTS_BYTES ]; - unsigned char *buffer; - uint32_t wots_k_mask; - - if (leaf_idx == info->wots_sign_leaf) { - /* We're traversing the leaf that's signing; generate the WOTS */ - /* signature */ - wots_k_mask = 0; - } else { - /* Nope, we're just generating pk's; turn off the signature logic */ - wots_k_mask = (uint32_t)~0; - } - - set_keypair_addr( leaf_addr, leaf_idx ); - set_keypair_addr( pk_addr, leaf_idx ); - - for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { - uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k to */ - /* the step if we're generating a signature, ~0 if we're not */ - - /* Start with the secret seed */ - set_chain_addr(leaf_addr, i); - set_hash_addr(leaf_addr, 0); - set_type(leaf_addr, SPX_ADDR_TYPE_WOTSPRF); - - prf_addr(buffer, ctx, leaf_addr); - - set_type(leaf_addr, SPX_ADDR_TYPE_WOTS); - - /* Iterate down the WOTS chain */ - for (k = 0;; k++) { - /* Check if this is the value that needs to be saved as a */ - /* part of the WOTS signature */ - if (k == wots_k) { - memcpy( info->wots_sig + i * SPX_N, buffer, SPX_N ); - } - - /* Check if we hit the top of the chain */ - if (k == SPX_WOTS_W - 1) { - break; - } - - /* Iterate one step on the chain */ - set_hash_addr(leaf_addr, k); - - thash(buffer, buffer, 1, ctx, leaf_addr); - } - } - - /* Do the final thash to generate the public keys */ - thash(dest, pk_buffer, SPX_WOTS_LEN, ctx, pk_addr); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/wotsx1.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/wotsx1.h deleted file mode 100644 index e617929f96..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192s-robust_clean/wotsx1.h +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef WOTSX1_H_ -#define WOTSX1_H_ - -#include - -#include "context.h" -#include "params.h" - -/* - * This is here to provide an interface to the internal wots_gen_leafx1 - * routine. While this routine is not referenced in the package outside of - * wots.c, it is called from the stand-alone benchmark code to characterize - * the performance - */ -struct leaf_info_x1 { - unsigned char *wots_sig; - uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ - uint32_t *wots_steps; - uint32_t leaf_addr[8]; - uint32_t pk_addr[8]; -}; - -/* Macro to set the leaf_info to something 'benign', that is, it would */ -/* run with the same time as it does during the real signing process */ -/* Used only by the benchmark code */ -#define INITIALIZE_LEAF_INFO_X1(info, addr, step_buffer) { \ - (info).wots_sig = 0; \ - (info).wots_sign_leaf = ~0; \ - (info).wots_steps = step_buffer; \ - memcpy( &(info).leaf_addr[0], (addr), 32 ); \ - memcpy( &(info).pk_addr[0], (addr), 32 ); \ - } - -#define wots_gen_leafx1 SPX_NAMESPACE(wots_gen_leafx1) -void wots_gen_leafx1(unsigned char *dest, - const spx_ctx *ctx, - uint32_t leaf_idx, void *v_info); - -#endif /* WOTSX1_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/LICENSE b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/LICENSE deleted file mode 100644 index 670154e353..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/LICENSE +++ /dev/null @@ -1,116 +0,0 @@ -CC0 1.0 Universal - -Statement of Purpose - -The laws of most jurisdictions throughout the world automatically confer -exclusive Copyright and Related Rights (defined below) upon the creator and -subsequent owner(s) (each and all, an "owner") of an original work of -authorship and/or a database (each, a "Work"). - -Certain owners wish to permanently relinquish those rights to a Work for the -purpose of contributing to a commons of creative, cultural and scientific -works ("Commons") that the public can reliably and without fear of later -claims of infringement build upon, modify, incorporate in other works, reuse -and redistribute as freely as possible in any form whatsoever and for any -purposes, including without limitation commercial purposes. These owners may -contribute to the Commons to promote the ideal of a free culture and the -further production of creative, cultural and scientific works, or to gain -reputation or greater distribution for their Work in part through the use and -efforts of others. - -For these and/or other purposes and motivations, and without any expectation -of additional consideration or compensation, the person associating CC0 with a -Work (the "Affirmer"), to the extent that he or she is an owner of Copyright -and Related Rights in the Work, voluntarily elects to apply CC0 to the Work -and publicly distribute the Work under its terms, with knowledge of his or her -Copyright and Related Rights in the Work and the meaning and intended legal -effect of CC0 on those rights. - -1. Copyright and Related Rights. A Work made available under CC0 may be -protected by copyright and related or neighboring rights ("Copyright and -Related Rights"). Copyright and Related Rights include, but are not limited -to, the following: - - i. the right to reproduce, adapt, distribute, perform, display, communicate, - and translate a Work; - - ii. moral rights retained by the original author(s) and/or performer(s); - - iii. publicity and privacy rights pertaining to a person's image or likeness - depicted in a Work; - - iv. rights protecting against unfair competition in regards to a Work, - subject to the limitations in paragraph 4(a), below; - - v. rights protecting the extraction, dissemination, use and reuse of data in - a Work; - - vi. database rights (such as those arising under Directive 96/9/EC of the - European Parliament and of the Council of 11 March 1996 on the legal - protection of databases, and under any national implementation thereof, - including any amended or successor version of such directive); and - - vii. other similar, equivalent or corresponding rights throughout the world - based on applicable law or treaty, and any national implementations thereof. - -2. Waiver. To the greatest extent permitted by, but not in contravention of, -applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and -unconditionally waives, abandons, and surrenders all of Affirmer's Copyright -and Related Rights and associated claims and causes of action, whether now -known or unknown (including existing as well as future claims and causes of -action), in the Work (i) in all territories worldwide, (ii) for the maximum -duration provided by applicable law or treaty (including future time -extensions), (iii) in any current or future medium and for any number of -copies, and (iv) for any purpose whatsoever, including without limitation -commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes -the Waiver for the benefit of each member of the public at large and to the -detriment of Affirmer's heirs and successors, fully intending that such Waiver -shall not be subject to revocation, rescission, cancellation, termination, or -any other legal or equitable action to disrupt the quiet enjoyment of the Work -by the public as contemplated by Affirmer's express Statement of Purpose. - -3. Public License Fallback. Should any part of the Waiver for any reason be -judged legally invalid or ineffective under applicable law, then the Waiver -shall be preserved to the maximum extent permitted taking into account -Affirmer's express Statement of Purpose. In addition, to the extent the Waiver -is so judged Affirmer hereby grants to each affected person a royalty-free, -non transferable, non sublicensable, non exclusive, irrevocable and -unconditional license to exercise Affirmer's Copyright and Related Rights in -the Work (i) in all territories worldwide, (ii) for the maximum duration -provided by applicable law or treaty (including future time extensions), (iii) -in any current or future medium and for any number of copies, and (iv) for any -purpose whatsoever, including without limitation commercial, advertising or -promotional purposes (the "License"). The License shall be deemed effective as -of the date CC0 was applied by Affirmer to the Work. Should any part of the -License for any reason be judged legally invalid or ineffective under -applicable law, such partial invalidity or ineffectiveness shall not -invalidate the remainder of the License, and in such case Affirmer hereby -affirms that he or she will not (i) exercise any of his or her remaining -Copyright and Related Rights in the Work or (ii) assert any associated claims -and causes of action with respect to the Work, in either case contrary to -Affirmer's express Statement of Purpose. - -4. Limitations and Disclaimers. - - a. No trademark or patent rights held by Affirmer are waived, abandoned, - surrendered, licensed or otherwise affected by this document. - - b. Affirmer offers the Work as-is and makes no representations or warranties - of any kind concerning the Work, express, implied, statutory or otherwise, - including without limitation warranties of title, merchantability, fitness - for a particular purpose, non infringement, or the absence of latent or - other defects, accuracy, or the present or absence of errors, whether or not - discoverable, all to the greatest extent permissible under applicable law. - - c. Affirmer disclaims responsibility for clearing rights of other persons - that may apply to the Work or any use thereof, including without limitation - any person's Copyright and Related Rights in the Work. Further, Affirmer - disclaims responsibility for obtaining any necessary consents, permissions - or other rights required for any use of the Work. - - d. Affirmer understands and acknowledges that Creative Commons is not a - party to this document and has no duty or obligation with respect to this - CC0 or use of the Work. - -For more information, please see - diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/address.c b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/address.c deleted file mode 100644 index b956e9cb29..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/address.c +++ /dev/null @@ -1,91 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "utils.h" - -/* - * Specify which level of Merkle tree (the "layer") we're working on - */ -void set_layer_addr(uint32_t addr[8], uint32_t layer) { - ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; -} - -/* - * Specify which Merkle tree within the level (the "tree address") we're working on - */ -void set_tree_addr(uint32_t addr[8], uint64_t tree) { - ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); -} - -/* - * Specify the reason we'll use this address structure for, that is, what - * hash will we compute with it. This is used so that unrelated types of - * hashes don't accidentally get the same address structure. The type will be - * one of the SPX_ADDR_TYPE constants - */ -void set_type(uint32_t addr[8], uint32_t type) { - ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; -} - -/* - * Copy the layer and tree fields of the address structure. This is used - * when we're doing multiple types of hashes within the same Merkle tree - */ -void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { - memcpy( out, in, SPX_OFFSET_TREE + 8 ); -} - -/* These functions are used for OTS addresses. */ - -/* - * Specify which Merkle leaf we're working on; that is, which OTS keypair - * we're talking about. - */ -void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { - ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; -} - -/* - * Copy the layer, tree and keypair fields of the address structure. This is - * used when we're doing multiple things within the same OTS keypair - */ -void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { - memcpy( out, in, SPX_OFFSET_TREE + 8 ); - ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; -} - -/* - * Specify which Merkle chain within the OTS we're working with - * (the chain address) - */ -void set_chain_addr(uint32_t addr[8], uint32_t chain) { - ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; -} - -/* - * Specify where in the Merkle chain we are -* (the hash address) - */ -void set_hash_addr(uint32_t addr[8], uint32_t hash) { - ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; -} - -/* These functions are used for all hash tree addresses (including FORS). */ - -/* - * Specify the height of the node in the Merkle/FORS tree we are in - * (the tree height) - */ -void set_tree_height(uint32_t addr[8], uint32_t tree_height) { - ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; -} - -/* - * Specify the distance from the left edge of the node in the Merkle/FORS tree - * (the tree index) - */ -void set_tree_index(uint32_t addr[8], uint32_t tree_index) { - u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/address.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/address.h deleted file mode 100644 index 24a84eb40c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/address.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef SPX_ADDRESS_H -#define SPX_ADDRESS_H - -#include - -#include "params.h" - -/* The hash types that are passed to set_type */ -#define SPX_ADDR_TYPE_WOTS 0 -#define SPX_ADDR_TYPE_WOTSPK 1 -#define SPX_ADDR_TYPE_HASHTREE 2 -#define SPX_ADDR_TYPE_FORSTREE 3 -#define SPX_ADDR_TYPE_FORSPK 4 -#define SPX_ADDR_TYPE_WOTSPRF 5 -#define SPX_ADDR_TYPE_FORSPRF 6 - -#define set_layer_addr SPX_NAMESPACE(set_layer_addr) -void set_layer_addr(uint32_t addr[8], uint32_t layer); - -#define set_tree_addr SPX_NAMESPACE(set_tree_addr) -void set_tree_addr(uint32_t addr[8], uint64_t tree); - -#define set_type SPX_NAMESPACE(set_type) -void set_type(uint32_t addr[8], uint32_t type); - -/* Copies the layer and tree part of one address into the other */ -#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) -void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for WOTS and FORS addresses. */ - -#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) -void set_keypair_addr(uint32_t addr[8], uint32_t keypair); - -#define set_chain_addr SPX_NAMESPACE(set_chain_addr) -void set_chain_addr(uint32_t addr[8], uint32_t chain); - -#define set_hash_addr SPX_NAMESPACE(set_hash_addr) -void set_hash_addr(uint32_t addr[8], uint32_t hash); - -#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) -void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for all hash tree addresses (including FORS). */ - -#define set_tree_height SPX_NAMESPACE(set_tree_height) -void set_tree_height(uint32_t addr[8], uint32_t tree_height); - -#define set_tree_index SPX_NAMESPACE(set_tree_index) -void set_tree_index(uint32_t addr[8], uint32_t tree_index); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/api.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/api.h deleted file mode 100644 index 7787bfd72f..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/api.h +++ /dev/null @@ -1,77 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256FROBUST_AARCH64_API_H -#define PQCLEAN_SPHINCSSHAKE256FROBUST_AARCH64_API_H - -#include -#include - -#define PQCLEAN_SPHINCSSHAKE256FROBUST_AARCH64_CRYPTO_ALGNAME "SPHINCS+-shake-256f-robust" - -#define PQCLEAN_SPHINCSSHAKE256FROBUST_AARCH64_CRYPTO_SECRETKEYBYTES 128 -#define PQCLEAN_SPHINCSSHAKE256FROBUST_AARCH64_CRYPTO_PUBLICKEYBYTES 64 -#define PQCLEAN_SPHINCSSHAKE256FROBUST_AARCH64_CRYPTO_BYTES 49856 - -#define PQCLEAN_SPHINCSSHAKE256FROBUST_AARCH64_CRYPTO_SEEDBYTES 96 - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256FROBUST_AARCH64_crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256FROBUST_AARCH64_crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256FROBUST_AARCH64_crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256FROBUST_AARCH64_crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHAKE256FROBUST_AARCH64_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHAKE256FROBUST_AARCH64_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSSHAKE256FROBUST_AARCH64_crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE256FROBUST_AARCH64_crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, - const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSSHAKE256FROBUST_AARCH64_crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE256FROBUST_AARCH64_crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk); -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/context.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/context.h deleted file mode 100644 index 6e0a33f3b7..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/context.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef SPX_CONTEXT_H -#define SPX_CONTEXT_H - -#include - -#include "params.h" - -typedef struct { - uint8_t pub_seed[SPX_N]; - uint8_t sk_seed[SPX_N]; -} spx_ctx; - -#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) -void initialize_hash_function(spx_ctx *ctx); - -#define free_hash_function SPX_NAMESPACE(free_hash_function) -void free_hash_function(spx_ctx *ctx); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/context_shake.c b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/context_shake.c deleted file mode 100644 index 9614a103d3..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/context_shake.c +++ /dev/null @@ -1,12 +0,0 @@ -#include "context.h" - -/* For SHAKE256, there is no immediate reason to initialize at the start, - so this function is an empty operation. */ -void initialize_hash_function(spx_ctx *ctx) { - (void)ctx; /* Suppress an 'unused parameter' warning. */ -} - -// in case the hash function api is heap-based. -void free_hash_function(spx_ctx *ctx) { - (void)ctx; -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/f1600x2.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/f1600x2.h deleted file mode 100644 index 70d1af9f14..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/f1600x2.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef SPX_F1600X2_H -#define SPX_F1600X2_H - -#include - -extern uint64_t f1600_RC[24]; -extern void _f1600x2(uint64_t *a, uint64_t *rc); - -#define f1600x2(s) do {_f1600x2((s), f1600_RC);} while(0) - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/f1600x2.s b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/f1600x2.s deleted file mode 100644 index 640ed791ed..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/f1600x2.s +++ /dev/null @@ -1,143 +0,0 @@ -# From https://github.com/bwesterb/armed-keccak - -.macro round - # Execute theta, but without xoring into the state yet. - # Compute parities p[i] = a[i] ^ a[5+i] ^ ... ^ a[20+i]. - eor3.16b v25, v0, v5, v10 - eor3.16b v26, v1, v6, v11 - eor3.16b v27, v2, v7, v12 - eor3.16b v28, v3, v8, v13 - eor3.16b v29, v4, v9, v14 - - eor3.16b v25, v25, v15, v20 - eor3.16b v26, v26, v16, v21 - eor3.16b v27, v27, v17, v22 - eor3.16b v28, v28, v18, v23 - eor3.16b v29, v29, v19, v24 - - # d[0] = rotl(p[1], 1) ^ p[4] - rax1.2d v30, v29, v26 - # d[3] = rotl(p[4], 1) ^ p[2] - rax1.2d v29, v27, v29 - # d[1] = rotl(p[2], 1) ^ p[0] - rax1.2d v27, v25, v27 - # d[4] = rotl(p[0], 1) ^ p[3] - rax1.2d v25, v28, v25 - # d[2] = rotl(p[3], 1) ^ p[1] - rax1.2d v28, v26, v28 - - # Xor parities from step theta into the state at the same time - # as executing rho and pi. - eor.16b v0, v0, v30 - mov.16b v31, v1 - xar.2d v1, v6, v27, 20 - xar.2d v6, v9, v25, 44 - xar.2d v9, v22, v28, 3 - xar.2d v22, v14, v25, 25 - xar.2d v14, v20, v30, 46 - xar.2d v20, v2, v28, 2 - xar.2d v2, v12, v28, 21 - xar.2d v12, v13, v29, 39 - xar.2d v13, v19, v25, 56 - xar.2d v19, v23, v29, 8 - xar.2d v23, v15, v30, 23 - xar.2d v15, v4, v25, 37 - xar.2d v4, v24, v25, 50 - xar.2d v24, v21, v27, 62 - xar.2d v21, v8, v29, 9 - xar.2d v8, v16, v27, 19 - xar.2d v16, v5, v30, 28 - xar.2d v5, v3, v29, 36 - xar.2d v3, v18, v29, 43 - xar.2d v18, v17, v28, 49 - xar.2d v17, v11, v27, 54 - xar.2d v11, v7, v28, 58 - xar.2d v7, v10, v30, 61 - xar.2d v10, v31, v27, 63 - - # Chi - bcax.16b v25, v0, v2, v1 - bcax.16b v26, v1, v3, v2 - bcax.16b v2, v2, v4, v3 - bcax.16b v3, v3, v0, v4 - bcax.16b v4, v4, v1, v0 - mov.16b v0, v25 - mov.16b v1, v26 - - bcax.16b v25, v5, v7, v6 - bcax.16b v26, v6, v8, v7 - bcax.16b v7, v7, v9, v8 - bcax.16b v8, v8, v5, v9 - bcax.16b v9, v9, v6, v5 - mov.16b v5, v25 - mov.16b v6, v26 - - bcax.16b v25, v10, v12, v11 - bcax.16b v26, v11, v13, v12 - bcax.16b v12, v12, v14, v13 - bcax.16b v13, v13, v10, v14 - bcax.16b v14, v14, v11, v10 - mov.16b v10, v25 - mov.16b v11, v26 - - bcax.16b v25, v15, v17, v16 - bcax.16b v26, v16, v18, v17 - bcax.16b v17, v17, v19, v18 - bcax.16b v18, v18, v15, v19 - bcax.16b v19, v19, v16, v15 - mov.16b v15, v25 - mov.16b v16, v26 - - bcax.16b v25, v20, v22, v21 - bcax.16b v26, v21, v23, v22 - bcax.16b v22, v22, v24, v23 - bcax.16b v23, v23, v20, v24 - bcax.16b v24, v24, v21, v20 - mov.16b v20, v25 - mov.16b v21, v26 - - # iota - ld1r {v25.2d}, [x1], #8 - eor.16b v0, v0, v25 -.endm - -.align 4 -.global __f1600x2 -__f1600x2: - stp d8, d9, [sp,#-16]! - stp d10, d11, [sp,#-16]! - stp d12, d13, [sp,#-16]! - stp d14, d15, [sp,#-16]! - - mov x2, x0 - mov x3, #24 - - ld1.2d {v0, v1, v2, v3}, [x0], #64 - ld1.2d {v4, v5, v6, v7}, [x0], #64 - ld1.2d {v8, v9, v10, v11}, [x0], #64 - ld1.2d {v12, v13, v14, v15}, [x0], #64 - ld1.2d {v16, v17, v18, v19}, [x0], #64 - ld1.2d {v20, v21, v22, v23}, [x0], #64 - ld1.2d {v24}, [x0] - -loop: - round - - subs x3, x3, #1 - cbnz x3, loop - - mov x0, x2 - st1.2d {v0, v1, v2, v3}, [x0], #64 - st1.2d {v4, v5, v6, v7}, [x0], #64 - st1.2d {v8, v9, v10, v11}, [x0], #64 - st1.2d {v12, v13, v14, v15}, [x0], #64 - st1.2d {v16, v17, v18, v19}, [x0], #64 - st1.2d {v20, v21, v22, v23}, [x0], #64 - st1.2d {v24}, [x0] - - ldp d14, d15, [sp], #16 - ldp d12, d13, [sp], #16 - ldp d10, d11, [sp], #16 - ldp d8, d9, [sp], #16 - - ret lr diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/f1600x2_const.c b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/f1600x2_const.c deleted file mode 100644 index e49c0ba149..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/f1600x2_const.c +++ /dev/null @@ -1,30 +0,0 @@ -#include "f1600x2.h" - -uint64_t f1600_RC[24] = { - 0x0000000000000001, - 0x0000000000008082, - 0x800000000000808A, - 0x8000000080008000, - 0x000000000000808B, - 0x0000000080000001, - 0x8000000080008081, - 0x8000000000008009, - 0x000000000000008A, - 0x0000000000000088, - 0x0000000080008009, - 0x000000008000000A, - 0x000000008000808B, - 0x800000000000008B, - 0x8000000000008089, - 0x8000000000008003, - 0x8000000000008002, - 0x8000000000000080, - 0x000000000000800A, - 0x800000008000000A, - 0x8000000080008081, - 0x8000000000008080, - 0x0000000080000001, - 0x8000000080008008, -}; - - diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/fips202x2.c b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/fips202x2.c deleted file mode 100644 index 4718c343bc..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/fips202x2.c +++ /dev/null @@ -1,148 +0,0 @@ -#include -#include - -#include "fips202x2.h" -#include "f1600x2.h" -#include "fips202.h" - -uint64_t load64(const unsigned char *x) { - unsigned long long r = 0, i; - - for (i = 0; i < 8; ++i) { - r |= (unsigned long long)x[i] << 8 * i; - } - return r; -} - -void store64(uint8_t *x, uint64_t u) { - unsigned int i; - - for (i = 0; i < 8; ++i) { - x[i] = (uint8_t)u; - u >>= 8; - } -} - -static void keccak_absorb2x(uint64_t *s, - unsigned int r, - const unsigned char *m0, - const unsigned char *m1, - unsigned long long int mlen, - unsigned char p) { - unsigned long long i; - unsigned char t0[200]; - unsigned char t1[200]; - - while (mlen >= r) { - for (i = 0; i < r / 8; ++i) { - s[2 * i + 0] ^= load64(m0 + 8 * i); - s[2 * i + 1] ^= load64(m1 + 8 * i); - } - - f1600x2(s); - mlen -= r; - m0 += r; - m1 += r; - } - - for (i = 0; i < r; ++i) { - t0[i] = 0; - t1[i] = 0; - } - for (i = 0; i < mlen; ++i) { - t0[i] = m0[i]; - t1[i] = m1[i]; - } - - t0[i] = p; - t1[i] = p; - - t0[r - 1] |= 128; - t1[r - 1] |= 128; - - for (i = 0; i < r / 8; ++i) { - s[2 * i + 0] ^= load64(t0 + 8 * i); - s[2 * i + 1] ^= load64(t1 + 8 * i); - } -} - - -static void keccak_squeezeblocks2x(unsigned char *h0, - unsigned char *h1, - unsigned long long int nblocks, - uint64_t *s, - unsigned int r) { - unsigned int i; - - while (nblocks > 0) { - f1600x2(s); - for (i = 0; i < (r >> 3); i++) { - store64(h0 + 8 * i, s[2 * i + 0]); - store64(h1 + 8 * i, s[2 * i + 1]); - } - h0 += r; - h1 += r; - nblocks--; - } -} - - - -void shake128x2(unsigned char *out0, - unsigned char *out1, - unsigned long long outlen, - unsigned char *in0, - unsigned char *in1, - unsigned long long inlen) { - uint64_t s[50] = {0}; - unsigned char t0[SHAKE128_RATE]; - unsigned char t1[SHAKE128_RATE]; - unsigned int i; - - /* absorb 4 message of identical length in parallel */ - keccak_absorb2x(s, SHAKE128_RATE, in0, in1, inlen, 0x1F); - - /* Squeeze output */ - keccak_squeezeblocks2x(out0, out1, outlen / SHAKE128_RATE, s, SHAKE128_RATE); - - out0 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; - out1 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; - - if (outlen % SHAKE128_RATE) { - keccak_squeezeblocks2x(t0, t1, 1, s, SHAKE128_RATE); - for (i = 0; i < outlen % SHAKE128_RATE; i++) { - out0[i] = t0[i]; - out1[i] = t1[i]; - } - } -} - - -void shake256x2(unsigned char *out0, - unsigned char *out1, - unsigned long long outlen, - unsigned char *in0, - unsigned char *in1, - unsigned long long inlen) { - uint64_t s[50] = {0}; - unsigned char t0[SHAKE256_RATE]; - unsigned char t1[SHAKE256_RATE]; - unsigned int i; - - /* absorb 2 message of identical length in parallel */ - keccak_absorb2x(s, SHAKE256_RATE, in0, in1, inlen, 0x1F); - - /* Squeeze output */ - keccak_squeezeblocks2x(out0, out1, outlen / SHAKE256_RATE, s, SHAKE256_RATE); - - out0 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; - out1 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; - - if (outlen % SHAKE256_RATE) { - keccak_squeezeblocks2x(t0, t1, 1, s, SHAKE256_RATE); - for (i = 0; i < outlen % SHAKE256_RATE; i++) { - out0[i] = t0[i]; - out1[i] = t1[i]; - } - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/fips202x2.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/fips202x2.h deleted file mode 100644 index 7ba58b35d8..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/fips202x2.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef SPX_FIPS202X2_H -#define SPX_FIPS202X2_H - -#include - -uint64_t load64(const unsigned char *x); -void store64(uint8_t *x, uint64_t u); - - -void shake128x2(unsigned char *out0, - unsigned char *out1, - unsigned long long outlen, - unsigned char *in0, - unsigned char *in1, - unsigned long long inlen); - -void shake256x2(unsigned char *out0, - unsigned char *out1, - unsigned long long outlen, - unsigned char *in0, - unsigned char *in1, - unsigned long long inlen); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/fors.c b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/fors.c deleted file mode 100644 index 39193d04e2..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/fors.c +++ /dev/null @@ -1,191 +0,0 @@ -#include -#include -#include - -#include "fors.h" - -#include "address.h" -#include "hash.h" -#include "hashx2.h" -#include "thash.h" -#include "thashx2.h" -#include "utils.h" -#include "utilsx2.h" - -static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, - uint32_t fors_leaf_addr[8]) { - prf_addr(sk, ctx, fors_leaf_addr); -} - -static void fors_gen_skx2(unsigned char *sk0, - unsigned char *sk1, - const spx_ctx *ctx, - uint32_t fors_leaf_addrx2[2 * 8]) { - prf_addrx2(sk0, sk1, - ctx, fors_leaf_addrx2); -} - -static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, - const spx_ctx *ctx, - uint32_t fors_leaf_addr[8]) { - thash(leaf, sk, 1, ctx, fors_leaf_addr); -} - -static void fors_sk_to_leafx2(unsigned char *leaf0, - unsigned char *leaf1, - const unsigned char *sk0, - const unsigned char *sk1, - const spx_ctx *ctx, - uint32_t fors_leaf_addrx2[2 * 8]) { - thashx2(leaf0, leaf1, - sk0, sk1, - 1, ctx, fors_leaf_addrx2); -} - -struct fors_gen_leaf_info { - uint32_t leaf_addrx[2 * 8]; -}; - -static void fors_gen_leafx2(unsigned char *leaf, - const spx_ctx *ctx, - uint32_t addr_idx, void *info) { - struct fors_gen_leaf_info *fors_info = info; - uint32_t *fors_leaf_addrx2 = fors_info->leaf_addrx; - unsigned int j; - - /* Only set the parts that the caller doesn't set */ - for (j = 0; j < 2; j++) { - set_tree_index(fors_leaf_addrx2 + j * 8, addr_idx + j); - set_type(fors_leaf_addrx2 + j * 8, SPX_ADDR_TYPE_FORSPRF); - } - - fors_gen_skx2(leaf + 0 * SPX_N, - leaf + 1 * SPX_N, - ctx, fors_leaf_addrx2); - - for (j = 0; j < 2; j++) { - set_type(fors_leaf_addrx2 + j * 8, SPX_ADDR_TYPE_FORSTREE); - } - - fors_sk_to_leafx2(leaf + 0 * SPX_N, - leaf + 1 * SPX_N, - leaf + 0 * SPX_N, - leaf + 1 * SPX_N, - ctx, fors_leaf_addrx2); -} - -/** - * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - * Assumes indices has space for SPX_FORS_TREES integers. - */ -static void message_to_indices(uint32_t *indices, const unsigned char *m) { - unsigned int i, j; - unsigned int offset = 0; - - for (i = 0; i < SPX_FORS_TREES; i++) { - indices[i] = 0; - for (j = 0; j < SPX_FORS_HEIGHT; j++) { - indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); - offset++; - } - } -} - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -void fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]) { - uint32_t indices[SPX_FORS_TREES]; - unsigned char roots[SPX_FORS_TREES * SPX_N]; - uint32_t fors_tree_addr[2 * 8] = {0}; - struct fors_gen_leaf_info fors_info = {0}; - uint32_t *fors_leaf_addr = fors_info.leaf_addrx; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - for (i = 0; i < 2; i++) { - copy_keypair_addr(fors_tree_addr + 8 * i, fors_addr); - set_type(fors_tree_addr + 8 * i, SPX_ADDR_TYPE_FORSTREE); - copy_keypair_addr(fors_leaf_addr + 8 * i, fors_addr); - } - copy_keypair_addr(fors_pk_addr, fors_addr); - set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < SPX_FORS_TREES; i++) { - idx_offset = i * (1 << SPX_FORS_HEIGHT); - - set_tree_height(fors_tree_addr, 0); - set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Include the secret key part that produces the selected leaf node. */ - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); - fors_gen_sk(sig, ctx, fors_tree_addr); - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); - sig += SPX_N; - - /* Compute the authentication path for this leaf node. */ - treehashx2(roots + i * SPX_N, sig, ctx, - indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx2, - fors_tree_addr, &fors_info); - - sig += SPX_N * SPX_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); -} - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -void fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]) { - uint32_t indices[SPX_FORS_TREES]; - unsigned char roots[SPX_FORS_TREES * SPX_N]; - unsigned char leaf[SPX_N]; - uint32_t fors_tree_addr[8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - copy_keypair_addr(fors_tree_addr, fors_addr); - copy_keypair_addr(fors_pk_addr, fors_addr); - - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); - set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < SPX_FORS_TREES; i++) { - idx_offset = i * (1 << SPX_FORS_HEIGHT); - - set_tree_height(fors_tree_addr, 0); - set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Derive the leaf from the included secret key part. */ - fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); - sig += SPX_N; - - /* Derive the corresponding root node of this tree. */ - compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, - sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); - sig += SPX_N * SPX_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/fors.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/fors.h deleted file mode 100644 index 509140a178..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/fors.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef SPX_FORS_H -#define SPX_FORS_H - -#include - -#include "context.h" -#include "params.h" - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -#define fors_sign SPX_NAMESPACE(fors_sign) -void fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]); - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) -void fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/hash.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/hash.h deleted file mode 100644 index f7c87d4c3c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/hash.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef SPX_HASH_H -#define SPX_HASH_H - -#include -#include - -#include "context.h" -#include "params.h" - -#define prf_addr SPX_NAMESPACE(prf_addr) -void prf_addr(unsigned char *out, const spx_ctx *ctx, - const uint32_t addr[8]); - -#define gen_message_random SPX_NAMESPACE(gen_message_random) -void gen_message_random(unsigned char *R, const unsigned char *sk_prf, - const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx); - -#define hash_message SPX_NAMESPACE(hash_message) -void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx); - - - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/hash_shake.c b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/hash_shake.c deleted file mode 100644 index ff5e7ec918..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/hash_shake.c +++ /dev/null @@ -1,83 +0,0 @@ -#include -#include - -#include "hash.h" - -#include "address.h" -#include "fips202.h" -#include "params.h" -#include "utils.h" - -/* - * Computes PRF(pk_seed, sk_seed, addr) - */ -void prf_addr(unsigned char *out, const spx_ctx *ctx, - const uint32_t addr[8]) { - unsigned char buf[2 * SPX_N + SPX_ADDR_BYTES]; - - memcpy(buf, ctx->pub_seed, SPX_N); - memcpy(buf + SPX_N, addr, SPX_ADDR_BYTES); - memcpy(buf + SPX_N + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); - - shake256(out, SPX_N, buf, 2 * SPX_N + SPX_ADDR_BYTES); -} - -/** - * Computes the message-dependent randomness R, using a secret seed and an - * optional randomization value as well as the message. - */ -void gen_message_random(unsigned char *R, const unsigned char *sk_prf, - const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx) { - (void)ctx; - shake256incctx s_inc; - - shake256_inc_init(&s_inc); - shake256_inc_absorb(&s_inc, sk_prf, SPX_N); - shake256_inc_absorb(&s_inc, optrand, SPX_N); - shake256_inc_absorb(&s_inc, m, mlen); - shake256_inc_finalize(&s_inc); - shake256_inc_squeeze(R, SPX_N, &s_inc); - shake256_inc_ctx_release(&s_inc); -} - -/** - * Computes the message hash using R, the public key, and the message. - * Outputs the message digest and the index of the leaf. The index is split in - * the tree index and the leaf index, for convenient copying to an address. - */ -void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx) { - (void)ctx; -#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) -#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) -#define SPX_LEAF_BITS SPX_TREE_HEIGHT -#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) -#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) - - unsigned char buf[SPX_DGST_BYTES]; - unsigned char *bufp = buf; - shake256incctx s_inc; - - shake256_inc_init(&s_inc); - shake256_inc_absorb(&s_inc, R, SPX_N); - shake256_inc_absorb(&s_inc, pk, SPX_PK_BYTES); - shake256_inc_absorb(&s_inc, m, mlen); - shake256_inc_finalize(&s_inc); - shake256_inc_squeeze(buf, SPX_DGST_BYTES, &s_inc); - shake256_inc_ctx_release(&s_inc); - - memcpy(digest, bufp, SPX_FORS_MSG_BYTES); - bufp += SPX_FORS_MSG_BYTES; - - - *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); - *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); - bufp += SPX_TREE_BYTES; - - *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); - *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/hash_shakex2.c b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/hash_shakex2.c deleted file mode 100644 index 99571916a2..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/hash_shakex2.c +++ /dev/null @@ -1,52 +0,0 @@ -#include -#include - -#include "hashx2.h" - -#include "address.h" -#include "f1600x2.h" -#include "fips202x2.h" -#include "params.h" - -/* - * 2-way parallel version of prf_addr; takes 2x as much input and output - */ -void prf_addrx2(unsigned char *out0, - unsigned char *out1, - const spx_ctx *ctx, - const uint32_t addrx2[2 * 8]) { - /* As we write and read only a few quadwords, it is more efficient to - * build and extract from the fourway SHAKE256 state by hand. */ - uint64_t state[50] = {0}; - - for (int i = 0; i < SPX_N / 8; i++) { - uint64_t x = load64(ctx->pub_seed + 8 * i); - state[2 * i] = x; - state[2 * i + 1] = x; - } - for (int i = 0; i < 4; i++) { - state[2 * (SPX_N / 8 + i)] = (((uint64_t)addrx2[1 + 2 * i]) << 32) - | (uint64_t)addrx2[2 * i]; - state[2 * (SPX_N / 8 + i) + 1] = (((uint64_t)addrx2[8 + 1 + 2 * i]) << 32) - | (uint64_t)addrx2[8 + 2 * i]; - } - for (int i = 0; i < SPX_N / 8; i++) { - uint64_t x = load64(ctx->sk_seed + 8 * i); - state[2 * (SPX_N / 8 + i + 4)] = x; - state[2 * (SPX_N / 8 + i + 4) + 1] = x; - } - - /* SHAKE domain separator and padding. */ - state[2 * (SPX_N / 4 + 4)] = 0x1f; - state[2 * (SPX_N / 4 + 4) + 1] = 0x1f; - - state[2 * 16] = 0x80ULL << 56; - state[2 * 16 + 1] = 0x80ULL << 56; - - f1600x2(state); - - for (int i = 0; i < SPX_N / 8; i++) { - store64(out0 + 8 * i, state[2 * i]); - store64(out1 + 8 * i, state[2 * i + 1]); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/hashx2.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/hashx2.h deleted file mode 100644 index 99b8873a9b..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/hashx2.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef SPX_HASHX2_H -#define SPX_HASHX2_H - -#include "context.h" -#include "params.h" -#include - -#define prf_addrx2 SPX_NAMESPACE(prf_addrx2) -void prf_addrx2(unsigned char *out0, - unsigned char *out1, - const spx_ctx *ctx, - const uint32_t addrx2[2 * 8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/merkle.c b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/merkle.c deleted file mode 100644 index c94ee23939..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/merkle.c +++ /dev/null @@ -1,64 +0,0 @@ -#include -#include - -#include "merkle.h" - -#include "address.h" -#include "params.h" -#include "utils.h" -#include "utilsx2.h" -#include "wots.h" -#include "wotsx2.h" - -/* - * This generates a Merkle signature (WOTS signature followed by the Merkle - * authentication path). - */ -void merkle_sign(uint8_t *sig, unsigned char *root, - const spx_ctx *ctx, - uint32_t wots_addr[8], uint32_t tree_addr[8], - uint32_t idx_leaf) { - unsigned char *auth_path = sig + SPX_WOTS_BYTES; - uint32_t tree_addrx2[2 * 8] = { 0 }; - int j; - struct leaf_info_x2 info = { 0 }; - unsigned steps[ SPX_WOTS_LEN ]; - - info.wots_sig = sig; - chain_lengths(steps, root); - info.wots_steps = steps; - - for (j = 0; j < 2; j++) { - set_type(&tree_addrx2[8 * j], SPX_ADDR_TYPE_HASHTREE); - set_type(&info.leaf_addr[8 * j], SPX_ADDR_TYPE_WOTS); - set_type(&info.pk_addr[8 * j], SPX_ADDR_TYPE_WOTSPK); - copy_subtree_addr(&tree_addrx2[8 * j], tree_addr); - copy_subtree_addr(&info.leaf_addr[8 * j], wots_addr); - copy_subtree_addr(&info.pk_addr[8 * j], wots_addr); - } - - info.wots_sign_leaf = idx_leaf; - - treehashx2(root, auth_path, ctx, - idx_leaf, 0, - SPX_TREE_HEIGHT, - wots_gen_leafx2, - tree_addrx2, &info); -} - -/* Compute root node of the top-most subtree. */ -void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { - /* We do not need the auth path in key generation, but it simplifies the - code to have just one treehash routine that computes both root and path - in one function. */ - unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; - uint32_t top_tree_addr[8] = {0}; - uint32_t wots_addr[8] = {0}; - - set_layer_addr(top_tree_addr, SPX_D - 1); - set_layer_addr(wots_addr, SPX_D - 1); - - merkle_sign(auth_path, root, ctx, - wots_addr, top_tree_addr, - ~0 /* ~0 means "don't bother generating an auth path */ ); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/merkle.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/merkle.h deleted file mode 100644 index 769cf2e970..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/merkle.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef MERKLE_H_ -#define MERKLE_H_ - -#include - -#include "context.h" -#include "params.h" - -/* Generate a Merkle signature (WOTS signature followed by the Merkle */ -/* authentication path) */ -#define merkle_sign SPX_NAMESPACE(merkle_sign) -void merkle_sign(uint8_t *sig, unsigned char *root, - const spx_ctx *ctx, - uint32_t wots_addr[8], uint32_t tree_addr[8], - uint32_t idx_leaf); - -/* Compute the root node of the top-most subtree. */ -#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) -void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); - -#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/nistapi.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/nistapi.h deleted file mode 100644 index 3cb71afad4..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/nistapi.h +++ /dev/null @@ -1,87 +0,0 @@ -#ifndef SPX_API_H -#define SPX_API_H - -#include -#include - -#include "params.h" - -#define CRYPTO_ALGNAME "SPHINCS+" - -#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES -#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES -#define CRYPTO_BYTES SPX_BYTES -#define CRYPTO_SEEDBYTES (3*SPX_N) - -/* - * Returns the length of a secret key, in bytes - */ -#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) -size_t crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) -size_t crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) -size_t crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) -size_t crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) -int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) -int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) -int crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) -int crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -#define crypto_sign SPX_NAMESPACE(crypto_sign) -int crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) -int crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/params.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/params.h deleted file mode 100644 index 7dc7db3106..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/params.h +++ /dev/null @@ -1,56 +0,0 @@ -#ifndef SPX_PARAMS_H -#define SPX_PARAMS_H - -#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSSHAKE256FROBUST_AARCH64_##s - -/* Hash output length in bytes. */ -#define SPX_N 32 -/* Height of the hypertree. */ -#define SPX_FULL_HEIGHT 68 -/* Number of subtree layer. */ -#define SPX_D 17 -/* FORS tree dimensions. */ -#define SPX_FORS_HEIGHT 9 -#define SPX_FORS_TREES 35 -/* Winternitz parameter, */ -#define SPX_WOTS_W 16 - -/* The hash function is defined by linking a different hash.c file, as opposed - to setting a #define constant. */ - -/* For clarity */ -#define SPX_ADDR_BYTES 32 - -/* WOTS parameters. */ -#define SPX_WOTS_LOGW 4 - -#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) - -/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#define SPX_WOTS_LEN2 3 - -#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) -#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) -#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES - -/* Subtree size. */ -#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) - -//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT -// #error SPX_D should always divide SPX_FULL_HEIGHT -//#endif - -/* FORS parameters. */ -#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) -#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) -#define SPX_FORS_PK_BYTES SPX_N - -/* Resulting SPX sizes. */ -#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ - SPX_FULL_HEIGHT * SPX_N) -#define SPX_PK_BYTES (2 * SPX_N) -#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) - -#include "shake_offsets.h" - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/shake_offsets.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/shake_offsets.h deleted file mode 100644 index 6b28d95d91..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/shake_offsets.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef SHAKE_OFFSETS_H_ -#define SHAKE_OFFSETS_H_ - -/* - * Offsets of various fields in the address structure when we use SHAKE as - * the Sphincs+ hash function - */ - -#define SPX_OFFSET_LAYER 3 /* The byte used to specify the Merkle tree layer */ -#define SPX_OFFSET_TREE 8 /* The start of the 8 byte field used to specify the tree */ -#define SPX_OFFSET_TYPE 19 /* The byte used to specify the hash type (reason) */ -#define SPX_OFFSET_KP_ADDR2 22 /* The high byte used to specify the key pair (which one-time signature) */ -#define SPX_OFFSET_KP_ADDR1 23 /* The low byte used to specify the key pair */ -#define SPX_OFFSET_CHAIN_ADDR 27 /* The byte used to specify the chain address (which Winternitz chain) */ -#define SPX_OFFSET_HASH_ADDR 31 /* The byte used to specify the hash address (where in the Winternitz chain) */ -#define SPX_OFFSET_TREE_HGT 27 /* The byte used to specify the height of this node in the FORS or Merkle tree */ -#define SPX_OFFSET_TREE_INDEX 28 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ - -#define SPX_SHAKE 1 - -#endif /* SHAKE_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/sign.c b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/sign.c deleted file mode 100644 index 9d0c7d1b22..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/sign.c +++ /dev/null @@ -1,286 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "context.h" -#include "fors.h" -#include "hash.h" -#include "merkle.h" -#include "nistapi.h" -#include "params.h" -#include "randombytes.h" -#include "thash.h" -#include "utils.h" -#include "wots.h" - -/* - * Returns the length of a secret key, in bytes - */ -size_t crypto_sign_secretkeybytes(void) { - return CRYPTO_SECRETKEYBYTES; -} - -/* - * Returns the length of a public key, in bytes - */ -size_t crypto_sign_publickeybytes(void) { - return CRYPTO_PUBLICKEYBYTES; -} - -/* - * Returns the length of a signature, in bytes - */ -size_t crypto_sign_bytes(void) { - return CRYPTO_BYTES; -} - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t crypto_sign_seedbytes(void) { - return CRYPTO_SEEDBYTES; -} - -/* - * Generates an SPX key pair given a seed of length - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed) { - spx_ctx ctx; - - /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ - memcpy(sk, seed, CRYPTO_SEEDBYTES); - - memcpy(pk, sk + 2 * SPX_N, SPX_N); - - memcpy(ctx.pub_seed, pk, SPX_N); - memcpy(ctx.sk_seed, sk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - /* Compute root node of the top-most subtree. */ - merkle_gen_root(sk + 3 * SPX_N, &ctx); - - // cleanup - free_hash_function(&ctx); - - memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); - - return 0; -} - -/* - * Generates an SPX key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { - uint8_t seed[CRYPTO_SEEDBYTES]; - randombytes(seed, CRYPTO_SEEDBYTES); - crypto_sign_seed_keypair(pk, sk, seed); - - return 0; -} - -/** - * Returns an array containing a detached signature. - */ -int crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - spx_ctx ctx; - - const uint8_t *sk_prf = sk + SPX_N; - const uint8_t *pk = sk + 2 * SPX_N; - - uint8_t optrand[SPX_N]; - uint8_t mhash[SPX_FORS_MSG_BYTES]; - uint8_t root[SPX_N]; - uint32_t i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - - memcpy(ctx.sk_seed, sk, SPX_N); - memcpy(ctx.pub_seed, pk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - set_type(wots_addr, SPX_ADDR_TYPE_WOTS); - set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); - - /* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ - randombytes(optrand, SPX_N); - /* Compute the digest randomization value. */ - gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); - - /* Derive the message digest and leaf index from R, PK and M. */ - hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); - sig += SPX_N; - - set_tree_addr(wots_addr, tree); - set_keypair_addr(wots_addr, idx_leaf); - - /* Sign the message hash using FORS. */ - fors_sign(sig, root, mhash, &ctx, wots_addr); - sig += SPX_FORS_BYTES; - - for (i = 0; i < SPX_D; i++) { - set_layer_addr(tree_addr, i); - set_tree_addr(tree_addr, tree); - - copy_subtree_addr(wots_addr, tree_addr); - set_keypair_addr(wots_addr, idx_leaf); - - merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); - sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); - tree = tree >> SPX_TREE_HEIGHT; - } - - free_hash_function(&ctx); - - *siglen = SPX_BYTES; - - return 0; -} - -/** - * Verifies a detached signature and message under a given public key. - */ -int crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk) { - spx_ctx ctx; - const uint8_t *pub_root = pk + SPX_N; - uint8_t mhash[SPX_FORS_MSG_BYTES]; - uint8_t wots_pk[SPX_WOTS_BYTES]; - uint8_t root[SPX_N]; - uint8_t leaf[SPX_N]; - unsigned int i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - if (siglen != SPX_BYTES) { - return -1; - } - - memcpy(ctx.pub_seed, pk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - set_type(wots_addr, SPX_ADDR_TYPE_WOTS); - set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); - set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); - - /* Derive the message digest and leaf index from R || PK || M. */ - /* The additional SPX_N is a result of the hash domain separator. */ - hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); - sig += SPX_N; - - /* Layer correctly defaults to 0, so no need to set_layer_addr */ - set_tree_addr(wots_addr, tree); - set_keypair_addr(wots_addr, idx_leaf); - - fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); - sig += SPX_FORS_BYTES; - - /* For each subtree.. */ - for (i = 0; i < SPX_D; i++) { - set_layer_addr(tree_addr, i); - set_tree_addr(tree_addr, tree); - - copy_subtree_addr(wots_addr, tree_addr); - set_keypair_addr(wots_addr, idx_leaf); - - copy_keypair_addr(wots_pk_addr, wots_addr); - - /* The WOTS public key is only correct if the signature was correct. */ - /* Initially, root is the FORS pk, but on subsequent iterations it is - the root of the subtree below the currently processed subtree. */ - wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); - sig += SPX_WOTS_BYTES; - - /* Compute the leaf node using the WOTS public key. */ - thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); - - /* Compute the root node of this subtree. */ - compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, - &ctx, tree_addr); - sig += SPX_TREE_HEIGHT * SPX_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); - tree = tree >> SPX_TREE_HEIGHT; - } - - // cleanup - free_hash_function(&ctx); - - /* Check if the root node equals the root node in the public key. */ - if (memcmp(root, pub_root, SPX_N) != 0) { - return -1; - } - - return 0; -} - - -/** - * Returns an array containing the signature followed by the message. - */ -int crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk) { - size_t siglen; - - crypto_sign_signature(sm, &siglen, m, mlen, sk); - - memmove(sm + SPX_BYTES, m, mlen); - *smlen = siglen + mlen; - - return 0; -} - -/** - * Verifies a given signature-message pair under a given public key. - */ -int crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk) { - /* The API caller does not necessarily know what size a signature should be - but SPHINCS+ signatures are always exactly SPX_BYTES. */ - if (smlen < SPX_BYTES) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - *mlen = smlen - SPX_BYTES; - - if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - /* If verification was successful, move the message to the right place. */ - memmove(m, sm + SPX_BYTES, *mlen); - - return 0; -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/thash.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/thash.h deleted file mode 100644 index 8687ccfb4d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/thash.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef SPX_THASH_H -#define SPX_THASH_H - -#include "context.h" -#include "params.h" - -#include - -#define thash SPX_NAMESPACE(thash) -void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/thash_shake_robustx2.c b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/thash_shake_robustx2.c deleted file mode 100644 index 454fc0f4e2..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/thash_shake_robustx2.c +++ /dev/null @@ -1,112 +0,0 @@ -#include -#include - -#include "thash.h" -#include "thashx2.h" - -#include "address.h" -#include "params.h" -#include "utils.h" - -#include "f1600x2.h" -#include "fips202x2.h" - - -void thash(unsigned char *out, - const unsigned char *in, - unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]) { - uint32_t addrx2 [2 * 8] = { - addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], addr[6], addr[7], - addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], addr[6], addr[7] - }; - thashx2(out, out, in, in, inblocks, ctx, addrx2); -} - -/** - * 2-way parallel version of thash; takes 2x as much input and output - */ -void thashx2(unsigned char *out0, - unsigned char *out1, - const unsigned char *in0, - const unsigned char *in1, - unsigned int inblocks, - const spx_ctx *ctx, uint32_t addrx2[2 * 8]) { - if (inblocks == 1 || inblocks == 2) { - /* As we write and read only a few quadwords, it is more efficient to - * build and extract from the twoway SHAKE256 state by hand. */ - uint64_t state[50] = {0}; - uint64_t state2[50]; - - for (int i = 0; i < SPX_N / 8; i++) { - uint64_t x = load64(ctx->pub_seed + 8 * i); - state[2 * i] = x; - state[2 * i + 1] = x; - } - for (int i = 0; i < 4; i++) { - state[2 * (SPX_N / 8 + i)] = (((uint64_t)addrx2[1 + 2 * i]) << 32) - | (uint64_t)addrx2[2 * i]; - state[2 * (SPX_N / 8 + i) + 1] = (((uint64_t)addrx2[8 + 1 + 2 * i]) << 32) - | (uint64_t)addrx2[8 + 2 * i]; - } - - /* Domain separator and padding. */ - state[2 * 16] = 0x80ULL << 56; - state[2 * 16 + 1] = 0x80ULL << 56; - - state[2 * ((SPX_N / 8) + 4)] ^= 0x1f; - state[2 * ((SPX_N / 8) + 4) + 1] ^= 0x1f; - - /* We will permutate state2 with f1600x2 to compute the bitmask, - * but first we'll copy it to state2 which will be used to compute - * the final output, as its input is almost identical. */ - memcpy(state2, state, 400); - - f1600x2(state); - - /* By copying from state, state2 already contains the pub_seed - * and address. We just need to copy in the input blocks xorred with - * the bitmask we just computed. */ - for (unsigned int i = 0; i < (SPX_N / 8) * inblocks; i++) { - state2[2 * (SPX_N / 8 + 4 + i)] = state[2 * i] ^ load64(in0 + 8 * i); - state2[2 * (SPX_N / 8 + 4 + i) + 1] = state[2 * i + 1] ^ load64(in1 + 8 * i); - } - - /* Domain separator and start of padding. Note that the quadwords - * around are already zeroed for state from which we copied. - * We do a XOR instead of a set as this might be the 16th quadword - * when N=32 and inblocks=2, which already contains the end - * of the padding. */ - state2[2 * ((SPX_N / 8) * (1 + inblocks) + 4)] ^= 0x1f; - state2[2 * ((SPX_N / 8) * (1 + inblocks) + 4) + 1] ^= 0x1f; - - f1600x2(state2); - - for (int i = 0; i < SPX_N / 8; i++) { - store64(out0 + 8 * i, state2[2 * i]); - store64(out1 + 8 * i, state2[2 * i + 1]); - } - } else { - PQCLEAN_VLA(unsigned char, buf0, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); - PQCLEAN_VLA(unsigned char, buf1, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); - PQCLEAN_VLA(unsigned char, bitmask0, inblocks * SPX_N); - PQCLEAN_VLA(unsigned char, bitmask1, inblocks * SPX_N); - unsigned int i; - - memcpy(buf0, ctx->pub_seed, SPX_N); - memcpy(buf1, ctx->pub_seed, SPX_N); - memcpy(buf0 + SPX_N, addrx2 + 0 * 8, SPX_ADDR_BYTES); - memcpy(buf1 + SPX_N, addrx2 + 1 * 8, SPX_ADDR_BYTES); - - shake256x2(bitmask0, bitmask1, inblocks * SPX_N, - buf0, buf1, SPX_N + SPX_ADDR_BYTES); - - for (i = 0; i < inblocks * SPX_N; i++) { - buf0[SPX_N + SPX_ADDR_BYTES + i] = in0[i] ^ bitmask0[i]; - buf1[SPX_N + SPX_ADDR_BYTES + i] = in1[i] ^ bitmask1[i]; - } - - shake256x2(out0, out1, SPX_N, - buf0, buf1, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/thashx2.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/thashx2.h deleted file mode 100644 index 040375e618..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/thashx2.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef SPX_THASHX2_H -#define SPX_THASHX2_H - -#include "context.h" -#include "params.h" -#include - -#define thashx2 SPX_NAMESPACE(thashx2) -void thashx2(unsigned char *out0, - unsigned char *out1, - const unsigned char *in0, - const unsigned char *in1, - unsigned int inblocks, - const spx_ctx *ctx, uint32_t addrx2[2 * 8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/utils.c b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/utils.c deleted file mode 100644 index 177b541fb9..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/utils.c +++ /dev/null @@ -1,148 +0,0 @@ -#include - -#include "utils.h" - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "thash.h" - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void ull_to_bytes(unsigned char *out, unsigned int outlen, - unsigned long long in) { - int i; - - /* Iterate over out in decreasing order, for big-endianness. */ - for (i = (signed int)outlen - 1; i >= 0; i--) { - out[i] = in & 0xff; - in = in >> 8; - } -} - -void u32_to_bytes(unsigned char *out, uint32_t in) { - out[0] = (unsigned char)(in >> 24); - out[1] = (unsigned char)(in >> 16); - out[2] = (unsigned char)(in >> 8); - out[3] = (unsigned char)in; -} - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { - unsigned long long retval = 0; - unsigned int i; - - for (i = 0; i < inlen; i++) { - retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); - } - return retval; -} - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void compute_root(unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const spx_ctx *ctx, uint32_t addr[8]) { - uint32_t i; - unsigned char buffer[2 * SPX_N]; - - /* If leaf_idx is odd (last bit = 1), current path element is a right child - and auth_path has to go left. Otherwise it is the other way around. */ - if (leaf_idx & 1) { - memcpy(buffer + SPX_N, leaf, SPX_N); - memcpy(buffer, auth_path, SPX_N); - } else { - memcpy(buffer, leaf, SPX_N); - memcpy(buffer + SPX_N, auth_path, SPX_N); - } - auth_path += SPX_N; - - for (i = 0; i < tree_height - 1; i++) { - leaf_idx >>= 1; - idx_offset >>= 1; - /* Set the address of the node we're creating. */ - set_tree_height(addr, i + 1); - set_tree_index(addr, leaf_idx + idx_offset); - - /* Pick the right or left neighbor, depending on parity of the node. */ - if (leaf_idx & 1) { - thash(buffer + SPX_N, buffer, 2, ctx, addr); - memcpy(buffer, auth_path, SPX_N); - } else { - thash(buffer, buffer, 2, ctx, addr); - memcpy(buffer + SPX_N, auth_path, SPX_N); - } - auth_path += SPX_N; - } - - /* The last iteration is exceptional; we do not copy an auth_path node. */ - leaf_idx >>= 1; - idx_offset >>= 1; - set_tree_height(addr, tree_height); - set_tree_index(addr, leaf_idx + idx_offset); - thash(root, buffer, 2, ctx, addr); -} - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const spx_ctx * /* ctx */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), - uint32_t tree_addr[8]) { - PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); - PQCLEAN_VLA(unsigned int, heights, tree_height + 1); - unsigned int offset = 0; - uint32_t idx; - uint32_t tree_idx; - - for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { - /* Add the next leaf node to the stack. */ - gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); - offset++; - heights[offset - 1] = 0; - - /* If this is a node we need for the auth path.. */ - if ((leaf_idx ^ 0x1) == idx) { - memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); - } - - /* While the top-most nodes are of equal height.. */ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { - /* Compute index of the new node, in the next layer. */ - tree_idx = (idx >> (heights[offset - 1] + 1)); - - /* Set the address of the node we're creating. */ - set_tree_height(tree_addr, heights[offset - 1] + 1); - set_tree_index(tree_addr, - tree_idx + (idx_offset >> (heights[offset - 1] + 1))); - /* Hash the top-most nodes from the stack together. */ - thash(stack + (offset - 2)*SPX_N, - stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); - offset--; - /* Note that the top-most node is now one layer higher. */ - heights[offset - 1]++; - - /* If this is a node we need for the auth path.. */ - if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_path + heights[offset - 1]*SPX_N, - stack + (offset - 1)*SPX_N, SPX_N); - } - } - } - memcpy(root, stack, SPX_N); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/utils.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/utils.h deleted file mode 100644 index 64f5d5a53a..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/utils.h +++ /dev/null @@ -1,58 +0,0 @@ -#ifndef SPX_UTILS_H -#define SPX_UTILS_H - -#include - -#include "compat.h" -#include "context.h" -#include "params.h" - - -/* To support MSVC use alloca() instead of VLAs. See #20. */ - - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) -void ull_to_bytes(unsigned char *out, unsigned int outlen, - unsigned long long in); -#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) -void u32_to_bytes(unsigned char *out, uint32_t in); - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) -unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -#define compute_root SPX_NAMESPACE(compute_root) -void compute_root(unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const spx_ctx *ctx, uint32_t addr[8]); - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -#define treehash SPX_NAMESPACE(treehash) -void treehash(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const spx_ctx *ctx /* ctx */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), - uint32_t tree_addr[8]); - - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/utilsx2.c b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/utilsx2.c deleted file mode 100644 index 8736474e4f..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/utilsx2.c +++ /dev/null @@ -1,130 +0,0 @@ -#include - -#include "utilsx2.h" - -#include "address.h" -#include "params.h" -#include "thashx2.h" -#include "utils.h" - -/* - * Generate the entire Merkle tree, computing the authentication path for leaf_idx, - * and the resulting root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) - * - * This expects tree_addrx2 to be initialized to 2 parallel addr structures for - * the Merkle tree nodes - * - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - * - * This works by using the standard Merkle tree building algorithm, except - * that each 'node' tracked is actually 2 consecutive nodes in the real tree. - * When we combine two logical nodes AB and WX, we perform the H - * operation on adjacent real nodes, forming the parent logical node - * (AB)(WX) - * - * When we get to the top level of the real tree (where there is only - * one logical node), we continue this operation one more time; the right - * most real node will by the actual root (and the other node will be - * garbage). We follow the same thashx2 logic so that the 'extract - * authentication path components' part of the loop is still executed (and - * to simplify the code somewhat) - */ -void treehashx2(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, - uint32_t tree_height, - void (*gen_leafx2)( - unsigned char * /* Where to write the leaves */, - const spx_ctx *, - uint32_t idx, void *info), - uint32_t tree_addrx2[2 * 8], - void *info) { - /* This is where we keep the intermediate nodes */ - unsigned char stackx2[tree_height * 2 * SPX_N]; - uint32_t left_adj = 0, prev_left_adj = 0; /* When we're doing the top */ - /* level, the left-most part of the tree isn't at the beginning */ - /* of current[]. These give the offset of the actual start */ - - uint32_t idx; - uint32_t max_idx = (1 << (tree_height - 1)) - 1; - for (idx = 0;; idx++) { - unsigned char current[2 * SPX_N]; /* Current logical node */ - gen_leafx2( current, ctx, 2 * idx + idx_offset, - info ); - - /* Now combine the freshly generated right node with previously */ - /* generated left ones */ - uint32_t internal_idx_offset = idx_offset; - uint32_t internal_idx = idx; - uint32_t internal_leaf = leaf_idx; - uint32_t h; /* The height we are in the Merkle tree */ - for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { - - /* Special processing if we're at the top of the tree */ - if (h >= tree_height - 1) { - if (h == tree_height) { - /* We hit the root; return it */ - memcpy( root, ¤t[1 * SPX_N], SPX_N ); - return; - } - /* The tree indexing logic is a bit off in this case */ - /* Adjust it so that the left-most node of the part of */ - /* the tree that we're processing has index 0 */ - prev_left_adj = left_adj; - left_adj = 2 - (1 << (tree_height - h - 1)); - } - - /* Check if we hit the top of the tree */ - if (h == tree_height) { - /* We hit the root; return it */ - memcpy( root, ¤t[1 * SPX_N], SPX_N ); - return; - } - - /* - * Check if one of the nodes we have is a part of the - * authentication path; if it is, write it out - */ - if ((((internal_idx << 1) ^ internal_leaf) & ~0x1) == 0) { - memcpy( &auth_path[ h * SPX_N ], - ¤t[(((internal_leaf & 1) ^ 1) + prev_left_adj) * SPX_N], - SPX_N ); - } - - /* - * Check if we're at a left child; if so, stop going up the stack - * Exception: if we've reached the end of the tree, keep on going - * (so we combine the last 2 nodes into the one root node in two - * more iterations) - */ - if ((internal_idx & 1) == 0 && idx < max_idx) { - break; - } - - /* Ok, we're at a right node (or doing the top 3 levels) */ - /* Now combine the left and right logical nodes together */ - - /* Set the address of the node we're creating. */ - int j; - internal_idx_offset >>= 1; - for (j = 0; j < 2; j++) { - set_tree_height(tree_addrx2 + j * 8, h + 1); - set_tree_index(tree_addrx2 + j * 8, - (2 / 2) * (internal_idx & ~1) + j - left_adj + internal_idx_offset ); - } - unsigned char *left = &stackx2[h * 2 * SPX_N]; - thashx2( ¤t[0 * SPX_N], - ¤t[1 * SPX_N], - &left [0 * SPX_N], - ¤t[0 * SPX_N], - 2, ctx, tree_addrx2); - } - - /* We've hit a left child; save the current for when we get the */ - /* corresponding right right */ - memcpy( &stackx2[h * 2 * SPX_N], current, 2 * SPX_N); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/utilsx2.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/utilsx2.h deleted file mode 100644 index e09faddc43..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/utilsx2.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef SPX_UTILSX2_H -#define SPX_UTILSX2_H - -#include - -#include "context.h" -#include "params.h" - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - * - * This implementation uses SIMD to compute internal nodes 2 at a time (in - * parallel) - */ -#define treehashx2 SPX_NAMESPACE(treehashx2) -void treehashx2(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leafx2)( - unsigned char * /* Where to write the leaves */, - const spx_ctx * /* ctx */, - uint32_t addr_idx, void *info), - uint32_t tree_addrx2[2 * 8], void *info); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/wots.c b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/wots.c deleted file mode 100644 index 3babe45e95..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/wots.c +++ /dev/null @@ -1,259 +0,0 @@ -#include -#include - -#include "wots.h" -#include "wotsx2.h" - -#include "address.h" -#include "hash.h" -#include "hashx2.h" -#include "params.h" -#include "thashx2.h" -#include "utils.h" -#include "utilsx2.h" - -// TODO clarify address expectations, and make them more uniform. -// TODO i.e. do we expect types to be set already? -// TODO and do we expect modifications or copies? - -/** - * Computes up the chains - */ -static void gen_chains( - unsigned char *out, - const unsigned char *in, - unsigned int start[SPX_WOTS_LEN], - const unsigned int steps[SPX_WOTS_LEN], - const spx_ctx *ctx, - uint32_t addr[8]) { - uint32_t i, j, k, idx, watching; - int done; - unsigned char empty[SPX_N]; - unsigned char *bufs[4]; - uint32_t addrs[8 * 2]; - - int l; - uint16_t counts[SPX_WOTS_W] = { 0 }; - uint16_t idxs[SPX_WOTS_LEN]; - uint16_t total, newTotal; - - /* set addrs = {addr, addr} */ - for (j = 0; j < 2; j++) { - memcpy(addrs + j * 8, addr, sizeof(uint32_t) * 8); - } - - /* Initialize out with the value at position 'start'. */ - memcpy(out, in, SPX_WOTS_LEN * SPX_N); - - /* Sort the chains in reverse order by steps using counting sort. */ - for (i = 0; i < SPX_WOTS_LEN; i++) { - counts[steps[i]]++; - } - total = 0; - for (l = SPX_WOTS_W - 1; l >= 0; l--) { - newTotal = counts[l] + total; - counts[l] = total; - total = newTotal; - } - for (i = 0; i < SPX_WOTS_LEN; i++) { - idxs[counts[steps[i]]] = i; - counts[steps[i]]++; - } - - /* We got our work cut out for us: do it! */ - for (i = 0; i < SPX_WOTS_LEN; i += 2) { - for (j = 0; j < 2 && i + j < SPX_WOTS_LEN; j++) { - idx = idxs[i + j]; - set_chain_addr(addrs + j * 8, idx); - bufs[j] = out + SPX_N * idx; - } - - /* As the chains are sorted in reverse order, we know that the first - * chain is the longest and the last one is the shortest. We keep - * an eye on whether the last chain is done and then on the one before, - * et cetera. */ - watching = 1; - done = 0; - while (i + watching >= SPX_WOTS_LEN) { - bufs[watching] = &empty[0]; - watching--; - } - - for (k = 0;; k++) { - while (k == steps[idxs[i + watching]]) { - bufs[watching] = &empty[0]; - if (watching == 0) { - done = 1; - break; - } - watching--; - } - if (done) { - break; - } - for (j = 0; j < watching + 1; j++) { - set_hash_addr(addrs + j * 8, k + start[idxs[i + j]]); - } - - thashx2(bufs[0], bufs[1], - bufs[0], bufs[1], 1, ctx, addrs); - } - } -} - -/** - * base_w algorithm as described in draft. - * Interprets an array of bytes as integers in base w. - * This only works when log_w is a divisor of 8. - */ -static void base_w(unsigned int *output, const int out_len, - const unsigned char *input) { - int in = 0; - int out = 0; - unsigned char total = 0; - int bits = 0; - int consumed; - - for (consumed = 0; consumed < out_len; consumed++) { - if (bits == 0) { - total = input[in]; - in++; - bits += 8; - } - bits -= SPX_WOTS_LOGW; - output[out] = (total >> bits) & (SPX_WOTS_W - 1); - out++; - } -} - -/* Computes the WOTS+ checksum over a message (in base_w). */ -static void wots_checksum(unsigned int *csum_base_w, - const unsigned int *msg_base_w) { - unsigned int csum = 0; - unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; - unsigned int i; - - /* Compute checksum. */ - for (i = 0; i < SPX_WOTS_LEN1; i++) { - csum += SPX_WOTS_W - 1 - msg_base_w[i]; - } - - /* Convert checksum to base_w. */ - /* Make sure expected empty zero bits are the least significant bits. */ - csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); - ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); - base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); -} - -/* Takes a message and derives the matching chain lengths. */ -void chain_lengths(unsigned int *lengths, const unsigned char *msg) { - base_w(lengths, SPX_WOTS_LEN1, msg); - wots_checksum(lengths + SPX_WOTS_LEN1, lengths); -} - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const spx_ctx *ctx, uint32_t addr[8]) { - unsigned int steps[SPX_WOTS_LEN]; - unsigned int start[SPX_WOTS_LEN]; - uint32_t i; - - chain_lengths(start, msg); - - for (i = 0; i < SPX_WOTS_LEN; i++) { - steps[i] = SPX_WOTS_W - 1 - start[i]; - } - - gen_chains(pk, sig, start, steps, ctx, addr); -} - -/* - * This generates 2 sequential WOTS public keys - * It also generates the WOTS signature if leaf_info indicates - * that we're signing with one of these WOTS keys - */ -void wots_gen_leafx2(unsigned char *dest, - const spx_ctx *ctx, - uint32_t leaf_idx, void *v_info) { - struct leaf_info_x2 *info = v_info; - uint32_t *leaf_addr = info->leaf_addr; - uint32_t *pk_addr = info->pk_addr; - unsigned int i, j, k; - unsigned char pk_buffer[ 2 * SPX_WOTS_BYTES ]; - unsigned wots_offset = SPX_WOTS_BYTES; - unsigned char *buffer; - uint32_t wots_k_mask; - unsigned wots_sign_index; - - if (((leaf_idx ^ info->wots_sign_leaf) & ~1) == 0) { - /* We're traversing the leaf that's signing; generate the WOTS */ - /* signature */ - wots_k_mask = 0; - wots_sign_index = info->wots_sign_leaf & 1; /* Which of of the 2 */ - /* slots do the signatures come from */ - } else { - /* Nope, we're just generating pk's; turn off the signature logic */ - wots_k_mask = ~0; - wots_sign_index = 0; - } - - for (j = 0; j < 2; j++) { - set_keypair_addr( leaf_addr + j * 8, leaf_idx + j ); - set_keypair_addr( pk_addr + j * 8, leaf_idx + j ); - } - - for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { - uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k to */ - /* the step if we're generating a signature, ~0 if we're not */ - - /* Start with the secret seed */ - for (j = 0; j < 2; j++) { - set_chain_addr(leaf_addr + j * 8, i); - set_hash_addr(leaf_addr + j * 8, 0); - set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTSPRF); - } - prf_addrx2(buffer + 0 * wots_offset, - buffer + 1 * wots_offset, - ctx, leaf_addr); - for (j = 0; j < 2; j++) { - set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTS); - } - - /* Iterate down the WOTS chain */ - for (k = 0;; k++) { - /* Check if one of the values we have needs to be saved as a */ - /* part of the WOTS signature */ - if (k == wots_k) { - memcpy( info->wots_sig + i * SPX_N, - buffer + wots_sign_index * wots_offset, SPX_N ); - } - - /* Check if we hit the top of the chain */ - if (k == SPX_WOTS_W - 1) { - break; - } - - /* Iterate one step on all 4 chains */ - for (j = 0; j < 2; j++) { - set_hash_addr(leaf_addr + j * 8, k); - } - thashx2(buffer + 0 * wots_offset, - buffer + 1 * wots_offset, - buffer + 0 * wots_offset, - buffer + 1 * wots_offset, - 1, ctx, leaf_addr); - } - } - - /* Do the final thash to generate the public keys */ - thashx2(dest + 0 * SPX_N, - dest + 1 * SPX_N, - pk_buffer + 0 * wots_offset, - pk_buffer + 1 * wots_offset, - SPX_WOTS_LEN, ctx, pk_addr); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/wots.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/wots.h deleted file mode 100644 index 4e7692eeef..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/wots.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef SPX_WOTS_H -#define SPX_WOTS_H - -#include - -#include "context.h" -#include "params.h" - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) -void wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const spx_ctx *ctx, uint32_t addr[8]); - -/* - * Compute the chain lengths needed for a given message hash - */ -#define chain_lengths SPX_NAMESPACE(chain_lengths) -void chain_lengths(unsigned int *lengths, const unsigned char *msg); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/wotsx2.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/wotsx2.h deleted file mode 100644 index b58bb61f84..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_aarch64/wotsx2.h +++ /dev/null @@ -1,40 +0,0 @@ -#ifndef WOTSX2_H_ -#define WOTSX2_H_ - -#include "params.h" -#include - -/* - * This is here to provide an interface to the internal wots_gen_leafx2 - * routine. While this routine is not referenced in the package outside of - * wots.c, it is called from the stand-alone benchmark code to characterize - * the performance - */ -struct leaf_info_x2 { - unsigned char *wots_sig; - uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ - uint32_t *wots_steps; - uint32_t leaf_addr[2 * 8]; - uint32_t pk_addr[2 * 8]; -}; - -/* Macro to set the leaf_info to something 'benign', that is, it would */ -/* run with the same time as it does during the real signing process */ -/* Used only by the benchmark code */ -#define INITIALIZE_LEAF_INFO_X2(info, addr, step_buffer) { \ - (info).wots_sig = 0; \ - (info).wots_sign_leaf = ~0; \ - (info).wots_steps = step_buffer; \ - int i; \ - for (i=0; i<2; i++) { \ - memcpy( &(info).leaf_addr[8*i], addr, 32 ); \ - memcpy( &(info).pk_addr[8*i], addr, 32 ); \ - } \ - } - -#define wots_gen_leafx2 SPX_NAMESPACE(wots_gen_leafx2) -void wots_gen_leafx2(unsigned char *dest, - const spx_ctx *ctx, - uint32_t leaf_idx, void *v_info); - -#endif /* WOTSX2_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/LICENSE b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/LICENSE deleted file mode 100644 index 670154e353..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/LICENSE +++ /dev/null @@ -1,116 +0,0 @@ -CC0 1.0 Universal - -Statement of Purpose - -The laws of most jurisdictions throughout the world automatically confer -exclusive Copyright and Related Rights (defined below) upon the creator and -subsequent owner(s) (each and all, an "owner") of an original work of -authorship and/or a database (each, a "Work"). - -Certain owners wish to permanently relinquish those rights to a Work for the -purpose of contributing to a commons of creative, cultural and scientific -works ("Commons") that the public can reliably and without fear of later -claims of infringement build upon, modify, incorporate in other works, reuse -and redistribute as freely as possible in any form whatsoever and for any -purposes, including without limitation commercial purposes. These owners may -contribute to the Commons to promote the ideal of a free culture and the -further production of creative, cultural and scientific works, or to gain -reputation or greater distribution for their Work in part through the use and -efforts of others. - -For these and/or other purposes and motivations, and without any expectation -of additional consideration or compensation, the person associating CC0 with a -Work (the "Affirmer"), to the extent that he or she is an owner of Copyright -and Related Rights in the Work, voluntarily elects to apply CC0 to the Work -and publicly distribute the Work under its terms, with knowledge of his or her -Copyright and Related Rights in the Work and the meaning and intended legal -effect of CC0 on those rights. - -1. Copyright and Related Rights. A Work made available under CC0 may be -protected by copyright and related or neighboring rights ("Copyright and -Related Rights"). Copyright and Related Rights include, but are not limited -to, the following: - - i. the right to reproduce, adapt, distribute, perform, display, communicate, - and translate a Work; - - ii. moral rights retained by the original author(s) and/or performer(s); - - iii. publicity and privacy rights pertaining to a person's image or likeness - depicted in a Work; - - iv. rights protecting against unfair competition in regards to a Work, - subject to the limitations in paragraph 4(a), below; - - v. rights protecting the extraction, dissemination, use and reuse of data in - a Work; - - vi. database rights (such as those arising under Directive 96/9/EC of the - European Parliament and of the Council of 11 March 1996 on the legal - protection of databases, and under any national implementation thereof, - including any amended or successor version of such directive); and - - vii. other similar, equivalent or corresponding rights throughout the world - based on applicable law or treaty, and any national implementations thereof. - -2. Waiver. To the greatest extent permitted by, but not in contravention of, -applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and -unconditionally waives, abandons, and surrenders all of Affirmer's Copyright -and Related Rights and associated claims and causes of action, whether now -known or unknown (including existing as well as future claims and causes of -action), in the Work (i) in all territories worldwide, (ii) for the maximum -duration provided by applicable law or treaty (including future time -extensions), (iii) in any current or future medium and for any number of -copies, and (iv) for any purpose whatsoever, including without limitation -commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes -the Waiver for the benefit of each member of the public at large and to the -detriment of Affirmer's heirs and successors, fully intending that such Waiver -shall not be subject to revocation, rescission, cancellation, termination, or -any other legal or equitable action to disrupt the quiet enjoyment of the Work -by the public as contemplated by Affirmer's express Statement of Purpose. - -3. Public License Fallback. Should any part of the Waiver for any reason be -judged legally invalid or ineffective under applicable law, then the Waiver -shall be preserved to the maximum extent permitted taking into account -Affirmer's express Statement of Purpose. In addition, to the extent the Waiver -is so judged Affirmer hereby grants to each affected person a royalty-free, -non transferable, non sublicensable, non exclusive, irrevocable and -unconditional license to exercise Affirmer's Copyright and Related Rights in -the Work (i) in all territories worldwide, (ii) for the maximum duration -provided by applicable law or treaty (including future time extensions), (iii) -in any current or future medium and for any number of copies, and (iv) for any -purpose whatsoever, including without limitation commercial, advertising or -promotional purposes (the "License"). The License shall be deemed effective as -of the date CC0 was applied by Affirmer to the Work. Should any part of the -License for any reason be judged legally invalid or ineffective under -applicable law, such partial invalidity or ineffectiveness shall not -invalidate the remainder of the License, and in such case Affirmer hereby -affirms that he or she will not (i) exercise any of his or her remaining -Copyright and Related Rights in the Work or (ii) assert any associated claims -and causes of action with respect to the Work, in either case contrary to -Affirmer's express Statement of Purpose. - -4. Limitations and Disclaimers. - - a. No trademark or patent rights held by Affirmer are waived, abandoned, - surrendered, licensed or otherwise affected by this document. - - b. Affirmer offers the Work as-is and makes no representations or warranties - of any kind concerning the Work, express, implied, statutory or otherwise, - including without limitation warranties of title, merchantability, fitness - for a particular purpose, non infringement, or the absence of latent or - other defects, accuracy, or the present or absence of errors, whether or not - discoverable, all to the greatest extent permissible under applicable law. - - c. Affirmer disclaims responsibility for clearing rights of other persons - that may apply to the Work or any use thereof, including without limitation - any person's Copyright and Related Rights in the Work. Further, Affirmer - disclaims responsibility for obtaining any necessary consents, permissions - or other rights required for any use of the Work. - - d. Affirmer understands and acknowledges that Creative Commons is not a - party to this document and has no duty or obligation with respect to this - CC0 or use of the Work. - -For more information, please see - diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/address.c b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/address.c deleted file mode 100644 index b956e9cb29..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/address.c +++ /dev/null @@ -1,91 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "utils.h" - -/* - * Specify which level of Merkle tree (the "layer") we're working on - */ -void set_layer_addr(uint32_t addr[8], uint32_t layer) { - ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; -} - -/* - * Specify which Merkle tree within the level (the "tree address") we're working on - */ -void set_tree_addr(uint32_t addr[8], uint64_t tree) { - ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); -} - -/* - * Specify the reason we'll use this address structure for, that is, what - * hash will we compute with it. This is used so that unrelated types of - * hashes don't accidentally get the same address structure. The type will be - * one of the SPX_ADDR_TYPE constants - */ -void set_type(uint32_t addr[8], uint32_t type) { - ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; -} - -/* - * Copy the layer and tree fields of the address structure. This is used - * when we're doing multiple types of hashes within the same Merkle tree - */ -void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { - memcpy( out, in, SPX_OFFSET_TREE + 8 ); -} - -/* These functions are used for OTS addresses. */ - -/* - * Specify which Merkle leaf we're working on; that is, which OTS keypair - * we're talking about. - */ -void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { - ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; -} - -/* - * Copy the layer, tree and keypair fields of the address structure. This is - * used when we're doing multiple things within the same OTS keypair - */ -void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { - memcpy( out, in, SPX_OFFSET_TREE + 8 ); - ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; -} - -/* - * Specify which Merkle chain within the OTS we're working with - * (the chain address) - */ -void set_chain_addr(uint32_t addr[8], uint32_t chain) { - ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; -} - -/* - * Specify where in the Merkle chain we are -* (the hash address) - */ -void set_hash_addr(uint32_t addr[8], uint32_t hash) { - ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; -} - -/* These functions are used for all hash tree addresses (including FORS). */ - -/* - * Specify the height of the node in the Merkle/FORS tree we are in - * (the tree height) - */ -void set_tree_height(uint32_t addr[8], uint32_t tree_height) { - ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; -} - -/* - * Specify the distance from the left edge of the node in the Merkle/FORS tree - * (the tree index) - */ -void set_tree_index(uint32_t addr[8], uint32_t tree_index) { - u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/address.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/address.h deleted file mode 100644 index 24a84eb40c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/address.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef SPX_ADDRESS_H -#define SPX_ADDRESS_H - -#include - -#include "params.h" - -/* The hash types that are passed to set_type */ -#define SPX_ADDR_TYPE_WOTS 0 -#define SPX_ADDR_TYPE_WOTSPK 1 -#define SPX_ADDR_TYPE_HASHTREE 2 -#define SPX_ADDR_TYPE_FORSTREE 3 -#define SPX_ADDR_TYPE_FORSPK 4 -#define SPX_ADDR_TYPE_WOTSPRF 5 -#define SPX_ADDR_TYPE_FORSPRF 6 - -#define set_layer_addr SPX_NAMESPACE(set_layer_addr) -void set_layer_addr(uint32_t addr[8], uint32_t layer); - -#define set_tree_addr SPX_NAMESPACE(set_tree_addr) -void set_tree_addr(uint32_t addr[8], uint64_t tree); - -#define set_type SPX_NAMESPACE(set_type) -void set_type(uint32_t addr[8], uint32_t type); - -/* Copies the layer and tree part of one address into the other */ -#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) -void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for WOTS and FORS addresses. */ - -#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) -void set_keypair_addr(uint32_t addr[8], uint32_t keypair); - -#define set_chain_addr SPX_NAMESPACE(set_chain_addr) -void set_chain_addr(uint32_t addr[8], uint32_t chain); - -#define set_hash_addr SPX_NAMESPACE(set_hash_addr) -void set_hash_addr(uint32_t addr[8], uint32_t hash); - -#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) -void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for all hash tree addresses (including FORS). */ - -#define set_tree_height SPX_NAMESPACE(set_tree_height) -void set_tree_height(uint32_t addr[8], uint32_t tree_height); - -#define set_tree_index SPX_NAMESPACE(set_tree_index) -void set_tree_index(uint32_t addr[8], uint32_t tree_index); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/api.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/api.h deleted file mode 100644 index 1bf0fd167a..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/api.h +++ /dev/null @@ -1,77 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256FROBUST_AVX2_API_H -#define PQCLEAN_SPHINCSSHAKE256FROBUST_AVX2_API_H - -#include -#include - -#define PQCLEAN_SPHINCSSHAKE256FROBUST_AVX2_CRYPTO_ALGNAME "SPHINCS+-shake-256f-robust" - -#define PQCLEAN_SPHINCSSHAKE256FROBUST_AVX2_CRYPTO_SECRETKEYBYTES 128 -#define PQCLEAN_SPHINCSSHAKE256FROBUST_AVX2_CRYPTO_PUBLICKEYBYTES 64 -#define PQCLEAN_SPHINCSSHAKE256FROBUST_AVX2_CRYPTO_BYTES 49856 - -#define PQCLEAN_SPHINCSSHAKE256FROBUST_AVX2_CRYPTO_SEEDBYTES 96 - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256FROBUST_AVX2_crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256FROBUST_AVX2_crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256FROBUST_AVX2_crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256FROBUST_AVX2_crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHAKE256FROBUST_AVX2_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHAKE256FROBUST_AVX2_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSSHAKE256FROBUST_AVX2_crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE256FROBUST_AVX2_crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, - const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSSHAKE256FROBUST_AVX2_crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE256FROBUST_AVX2_crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk); -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/context.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/context.h deleted file mode 100644 index 6e0a33f3b7..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/context.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef SPX_CONTEXT_H -#define SPX_CONTEXT_H - -#include - -#include "params.h" - -typedef struct { - uint8_t pub_seed[SPX_N]; - uint8_t sk_seed[SPX_N]; -} spx_ctx; - -#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) -void initialize_hash_function(spx_ctx *ctx); - -#define free_hash_function SPX_NAMESPACE(free_hash_function) -void free_hash_function(spx_ctx *ctx); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/context_shake.c b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/context_shake.c deleted file mode 100644 index 9614a103d3..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/context_shake.c +++ /dev/null @@ -1,12 +0,0 @@ -#include "context.h" - -/* For SHAKE256, there is no immediate reason to initialize at the start, - so this function is an empty operation. */ -void initialize_hash_function(spx_ctx *ctx) { - (void)ctx; /* Suppress an 'unused parameter' warning. */ -} - -// in case the hash function api is heap-based. -void free_hash_function(spx_ctx *ctx) { - (void)ctx; -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/fips202x4.c b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/fips202x4.c deleted file mode 100644 index 1e06fef186..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/fips202x4.c +++ /dev/null @@ -1,210 +0,0 @@ -#include -#include -#include - -#include "fips202.h" -#include "fips202x4.h" - -#define NROUNDS 24 -#define ROL(a, offset) (((a) << (offset)) ^ ((a) >> (64-(offset)))) - -static uint64_t load64(const unsigned char *x) { - unsigned long long r = 0, i; - - for (i = 0; i < 8; ++i) { - r |= (unsigned long long)x[i] << 8 * i; - } - return r; -} - -static void store64(uint8_t *x, uint64_t u) { - unsigned int i; - - for (i = 0; i < 8; ++i) { - x[i] = (uint8_t)u; - u >>= 8; - } -} - -/* Use implementation from the Keccak Code Package */ -extern void KeccakP1600times4_PermuteAll_24rounds(__m256i *s); -#define KeccakF1600_StatePermute4x KeccakP1600times4_PermuteAll_24rounds - -static void keccak_absorb4x(__m256i *s, - unsigned int r, - const unsigned char *m0, - const unsigned char *m1, - const unsigned char *m2, - const unsigned char *m3, - unsigned long long int mlen, - unsigned char p) { - unsigned long long i; - unsigned char t0[200]; - unsigned char t1[200]; - unsigned char t2[200]; - unsigned char t3[200]; - - unsigned long long *ss = (unsigned long long *)s; - - - while (mlen >= r) { - for (i = 0; i < r / 8; ++i) { - ss[4 * i + 0] ^= load64(m0 + 8 * i); - ss[4 * i + 1] ^= load64(m1 + 8 * i); - ss[4 * i + 2] ^= load64(m2 + 8 * i); - ss[4 * i + 3] ^= load64(m3 + 8 * i); - } - - KeccakF1600_StatePermute4x(s); - mlen -= r; - m0 += r; - m1 += r; - m2 += r; - m3 += r; - } - - for (i = 0; i < r; ++i) { - t0[i] = 0; - t1[i] = 0; - t2[i] = 0; - t3[i] = 0; - } - for (i = 0; i < mlen; ++i) { - t0[i] = m0[i]; - t1[i] = m1[i]; - t2[i] = m2[i]; - t3[i] = m3[i]; - } - - t0[i] = p; - t1[i] = p; - t2[i] = p; - t3[i] = p; - - t0[r - 1] |= 128; - t1[r - 1] |= 128; - t2[r - 1] |= 128; - t3[r - 1] |= 128; - - for (i = 0; i < r / 8; ++i) { - ss[4 * i + 0] ^= load64(t0 + 8 * i); - ss[4 * i + 1] ^= load64(t1 + 8 * i); - ss[4 * i + 2] ^= load64(t2 + 8 * i); - ss[4 * i + 3] ^= load64(t3 + 8 * i); - } -} - - -static void keccak_squeezeblocks4x(unsigned char *h0, - unsigned char *h1, - unsigned char *h2, - unsigned char *h3, - unsigned long long int nblocks, - __m256i *s, - unsigned int r) { - unsigned int i; - - unsigned long long *ss = (unsigned long long *)s; - - while (nblocks > 0) { - KeccakF1600_StatePermute4x(s); - for (i = 0; i < (r >> 3); i++) { - store64(h0 + 8 * i, ss[4 * i + 0]); - store64(h1 + 8 * i, ss[4 * i + 1]); - store64(h2 + 8 * i, ss[4 * i + 2]); - store64(h3 + 8 * i, ss[4 * i + 3]); - } - h0 += r; - h1 += r; - h2 += r; - h3 += r; - nblocks--; - } -} - - - -void shake128x4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, unsigned long long outlen, - unsigned char *in0, - unsigned char *in1, - unsigned char *in2, - unsigned char *in3, unsigned long long inlen) { - __m256i s[25]; - unsigned char t0[SHAKE128_RATE]; - unsigned char t1[SHAKE128_RATE]; - unsigned char t2[SHAKE128_RATE]; - unsigned char t3[SHAKE128_RATE]; - unsigned int i; - - /* zero state */ - for (i = 0; i < 25; i++) { - s[i] = _mm256_xor_si256(s[i], s[i]); - } - - /* absorb 4 message of identical length in parallel */ - keccak_absorb4x(s, SHAKE128_RATE, in0, in1, in2, in3, inlen, 0x1F); - - /* Squeeze output */ - keccak_squeezeblocks4x(out0, out1, out2, out3, outlen / SHAKE128_RATE, s, SHAKE128_RATE); - - out0 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; - out1 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; - out2 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; - out3 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; - - if (outlen % SHAKE128_RATE) { - keccak_squeezeblocks4x(t0, t1, t2, t3, 1, s, SHAKE128_RATE); - for (i = 0; i < outlen % SHAKE128_RATE; i++) { - out0[i] = t0[i]; - out1[i] = t1[i]; - out2[i] = t2[i]; - out3[i] = t3[i]; - } - } -} - - -void shake256x4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, unsigned long long outlen, - unsigned char *in0, - unsigned char *in1, - unsigned char *in2, - unsigned char *in3, unsigned long long inlen) { - __m256i s[25]; - unsigned char t0[SHAKE256_RATE]; - unsigned char t1[SHAKE256_RATE]; - unsigned char t2[SHAKE256_RATE]; - unsigned char t3[SHAKE256_RATE]; - unsigned int i; - - /* zero state */ - for (i = 0; i < 25; i++) { - s[i] = _mm256_xor_si256(s[i], s[i]); - } - - /* absorb 4 message of identical length in parallel */ - keccak_absorb4x(s, SHAKE256_RATE, in0, in1, in2, in3, inlen, 0x1F); - - /* Squeeze output */ - keccak_squeezeblocks4x(out0, out1, out2, out3, outlen / SHAKE256_RATE, s, SHAKE256_RATE); - - out0 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; - out1 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; - out2 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; - out3 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; - - if (outlen % SHAKE256_RATE) { - keccak_squeezeblocks4x(t0, t1, t2, t3, 1, s, SHAKE256_RATE); - for (i = 0; i < outlen % SHAKE256_RATE; i++) { - out0[i] = t0[i]; - out1[i] = t1[i]; - out2[i] = t2[i]; - out3[i] = t3[i]; - } - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/fips202x4.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/fips202x4.h deleted file mode 100644 index 2b93c9cd0d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/fips202x4.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef SPX_FIPS202X4_H -#define SPX_FIPS202X4_H - -#include - -#include "params.h" - -#define shake128x4 SPX_NAMESPACE(shake128x4) -void shake128x4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, unsigned long long outlen, - unsigned char *in0, - unsigned char *in1, - unsigned char *in2, - unsigned char *in3, unsigned long long inlen); - -#define shake256x4 SPX_NAMESPACE(shake256x4) -void shake256x4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, unsigned long long outlen, - unsigned char *in0, - unsigned char *in1, - unsigned char *in2, - unsigned char *in3, unsigned long long inlen); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/fors.c b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/fors.c deleted file mode 100644 index f1b0639cfc..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/fors.c +++ /dev/null @@ -1,202 +0,0 @@ -#include -#include -#include - -#include "fors.h" - -#include "address.h" -#include "hash.h" -#include "hashx4.h" -#include "thash.h" -#include "thashx4.h" -#include "utils.h" -#include "utilsx4.h" - -static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, - uint32_t fors_leaf_addr[8]) { - prf_addr(sk, ctx, fors_leaf_addr); -} - -static void fors_gen_skx4(unsigned char *sk0, - unsigned char *sk1, - unsigned char *sk2, - unsigned char *sk3, const spx_ctx *ctx, - uint32_t fors_leaf_addrx4[4 * 8]) { - prf_addrx4(sk0, sk1, sk2, sk3, - ctx, fors_leaf_addrx4); -} - -static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, - const spx_ctx *ctx, - uint32_t fors_leaf_addr[8]) { - thash(leaf, sk, 1, ctx, fors_leaf_addr); -} - -static void fors_sk_to_leafx4(unsigned char *leaf0, - unsigned char *leaf1, - unsigned char *leaf2, - unsigned char *leaf3, - const unsigned char *sk0, - const unsigned char *sk1, - const unsigned char *sk2, - const unsigned char *sk3, - const spx_ctx *ctx, - uint32_t fors_leaf_addrx4[4 * 8]) { - thashx4(leaf0, leaf1, leaf2, leaf3, - sk0, sk1, sk2, sk3, - 1, ctx, fors_leaf_addrx4); -} - -struct fors_gen_leaf_info { - uint32_t leaf_addrx[4 * 8]; -}; - -static void fors_gen_leafx4(unsigned char *leaf, - const spx_ctx *ctx, - uint32_t addr_idx, void *info) { - struct fors_gen_leaf_info *fors_info = info; - uint32_t *fors_leaf_addrx4 = fors_info->leaf_addrx; - unsigned int j; - - /* Only set the parts that the caller doesn't set */ - for (j = 0; j < 4; j++) { - set_tree_index(fors_leaf_addrx4 + j * 8, addr_idx + j); - set_type(fors_leaf_addrx4 + j * 8, SPX_ADDR_TYPE_FORSPRF); - } - - fors_gen_skx4(leaf + 0 * SPX_N, - leaf + 1 * SPX_N, - leaf + 2 * SPX_N, - leaf + 3 * SPX_N, - ctx, fors_leaf_addrx4); - - for (j = 0; j < 4; j++) { - set_type(fors_leaf_addrx4 + j * 8, SPX_ADDR_TYPE_FORSTREE); - } - - fors_sk_to_leafx4(leaf + 0 * SPX_N, - leaf + 1 * SPX_N, - leaf + 2 * SPX_N, - leaf + 3 * SPX_N, - leaf + 0 * SPX_N, - leaf + 1 * SPX_N, - leaf + 2 * SPX_N, - leaf + 3 * SPX_N, - ctx, fors_leaf_addrx4); -} - -/** - * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - * Assumes indices has space for SPX_FORS_TREES integers. - */ -static void message_to_indices(uint32_t *indices, const unsigned char *m) { - unsigned int i, j; - unsigned int offset = 0; - - for (i = 0; i < SPX_FORS_TREES; i++) { - indices[i] = 0; - for (j = 0; j < SPX_FORS_HEIGHT; j++) { - indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); - offset++; - } - } -} - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -void fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]) { - uint32_t indices[SPX_FORS_TREES]; - unsigned char roots[SPX_FORS_TREES * SPX_N]; - uint32_t fors_tree_addr[4 * 8] = {0}; - struct fors_gen_leaf_info fors_info = {0}; - uint32_t *fors_leaf_addr = fors_info.leaf_addrx; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - for (i = 0; i < 4; i++) { - copy_keypair_addr(fors_tree_addr + 8 * i, fors_addr); - set_type(fors_tree_addr + 8 * i, SPX_ADDR_TYPE_FORSTREE); - copy_keypair_addr(fors_leaf_addr + 8 * i, fors_addr); - } - copy_keypair_addr(fors_pk_addr, fors_addr); - set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < SPX_FORS_TREES; i++) { - idx_offset = i * (1 << SPX_FORS_HEIGHT); - - set_tree_height(fors_tree_addr, 0); - set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Include the secret key part that produces the selected leaf node. */ - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); - fors_gen_sk(sig, ctx, fors_tree_addr); - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); - sig += SPX_N; - - /* Compute the authentication path for this leaf node. */ - treehashx4(roots + i * SPX_N, sig, ctx, - indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx4, - fors_tree_addr, &fors_info); - - sig += SPX_N * SPX_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); -} - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -void fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]) { - uint32_t indices[SPX_FORS_TREES]; - unsigned char roots[SPX_FORS_TREES * SPX_N]; - unsigned char leaf[SPX_N]; - uint32_t fors_tree_addr[8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - copy_keypair_addr(fors_tree_addr, fors_addr); - copy_keypair_addr(fors_pk_addr, fors_addr); - - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); - set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < SPX_FORS_TREES; i++) { - idx_offset = i * (1 << SPX_FORS_HEIGHT); - - set_tree_height(fors_tree_addr, 0); - set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Derive the leaf from the included secret key part. */ - fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); - sig += SPX_N; - - /* Derive the corresponding root node of this tree. */ - compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, - sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); - sig += SPX_N * SPX_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/fors.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/fors.h deleted file mode 100644 index 509140a178..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/fors.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef SPX_FORS_H -#define SPX_FORS_H - -#include - -#include "context.h" -#include "params.h" - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -#define fors_sign SPX_NAMESPACE(fors_sign) -void fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]); - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) -void fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/hash.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/hash.h deleted file mode 100644 index f7c87d4c3c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/hash.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef SPX_HASH_H -#define SPX_HASH_H - -#include -#include - -#include "context.h" -#include "params.h" - -#define prf_addr SPX_NAMESPACE(prf_addr) -void prf_addr(unsigned char *out, const spx_ctx *ctx, - const uint32_t addr[8]); - -#define gen_message_random SPX_NAMESPACE(gen_message_random) -void gen_message_random(unsigned char *R, const unsigned char *sk_prf, - const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx); - -#define hash_message SPX_NAMESPACE(hash_message) -void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx); - - - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/hash_shake.c b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/hash_shake.c deleted file mode 100644 index ff5e7ec918..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/hash_shake.c +++ /dev/null @@ -1,83 +0,0 @@ -#include -#include - -#include "hash.h" - -#include "address.h" -#include "fips202.h" -#include "params.h" -#include "utils.h" - -/* - * Computes PRF(pk_seed, sk_seed, addr) - */ -void prf_addr(unsigned char *out, const spx_ctx *ctx, - const uint32_t addr[8]) { - unsigned char buf[2 * SPX_N + SPX_ADDR_BYTES]; - - memcpy(buf, ctx->pub_seed, SPX_N); - memcpy(buf + SPX_N, addr, SPX_ADDR_BYTES); - memcpy(buf + SPX_N + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); - - shake256(out, SPX_N, buf, 2 * SPX_N + SPX_ADDR_BYTES); -} - -/** - * Computes the message-dependent randomness R, using a secret seed and an - * optional randomization value as well as the message. - */ -void gen_message_random(unsigned char *R, const unsigned char *sk_prf, - const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx) { - (void)ctx; - shake256incctx s_inc; - - shake256_inc_init(&s_inc); - shake256_inc_absorb(&s_inc, sk_prf, SPX_N); - shake256_inc_absorb(&s_inc, optrand, SPX_N); - shake256_inc_absorb(&s_inc, m, mlen); - shake256_inc_finalize(&s_inc); - shake256_inc_squeeze(R, SPX_N, &s_inc); - shake256_inc_ctx_release(&s_inc); -} - -/** - * Computes the message hash using R, the public key, and the message. - * Outputs the message digest and the index of the leaf. The index is split in - * the tree index and the leaf index, for convenient copying to an address. - */ -void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx) { - (void)ctx; -#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) -#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) -#define SPX_LEAF_BITS SPX_TREE_HEIGHT -#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) -#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) - - unsigned char buf[SPX_DGST_BYTES]; - unsigned char *bufp = buf; - shake256incctx s_inc; - - shake256_inc_init(&s_inc); - shake256_inc_absorb(&s_inc, R, SPX_N); - shake256_inc_absorb(&s_inc, pk, SPX_PK_BYTES); - shake256_inc_absorb(&s_inc, m, mlen); - shake256_inc_finalize(&s_inc); - shake256_inc_squeeze(buf, SPX_DGST_BYTES, &s_inc); - shake256_inc_ctx_release(&s_inc); - - memcpy(digest, bufp, SPX_FORS_MSG_BYTES); - bufp += SPX_FORS_MSG_BYTES; - - - *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); - *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); - bufp += SPX_TREE_BYTES; - - *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); - *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/hash_shakex4.c b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/hash_shakex4.c deleted file mode 100644 index bbd22eb117..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/hash_shakex4.c +++ /dev/null @@ -1,64 +0,0 @@ -#include -#include - -#include "hashx4.h" - -#include "address.h" -#include "fips202x4.h" -#include "params.h" - -extern void KeccakP1600times4_PermuteAll_24rounds(__m256i *s); - -/* - * 4-way parallel version of prf_addr; takes 4x as much input and output - */ -void prf_addrx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const spx_ctx *ctx, - const uint32_t addrx4[4 * 8]) { - /* As we write and read only a few quadwords, it is more efficient to - * build and extract from the fourway SHAKE256 state by hand. */ - __m256i state[25]; - - for (int i = 0; i < SPX_N / 8; i++) { - state[i] = _mm256_set1_epi64x(((int64_t *)ctx->pub_seed)[i]); - } - for (int i = 0; i < 4; i++) { - state[SPX_N / 8 + i] = _mm256_set_epi32( - (int)addrx4[3 * 8 + 1 + 2 * i], - (int)addrx4[3 * 8 + 2 * i], - (int)addrx4[2 * 8 + 1 + 2 * i], - (int)addrx4[2 * 8 + 2 * i], - (int)addrx4[8 + 1 + 2 * i], - (int)addrx4[8 + 2 * i], - (int)addrx4[1 + 2 * i], - (int)addrx4[2 * i] - ); - } - for (int i = 0; i < SPX_N / 8; i++) { - state[SPX_N / 8 + i + 4] = _mm256_set1_epi64x(((int64_t *)ctx->sk_seed)[i]); - } - - /* SHAKE domain separator and padding. */ - state[SPX_N / 4 + 4] = _mm256_set1_epi64x(0x1f); - for (int i = SPX_N / 4 + 5; i < 16; i++) { - state[i] = _mm256_set1_epi64x(0); - } - // shift unsigned and then cast to avoid UB - state[16] = _mm256_set1_epi64x((long long)(0x80ULL << 56)); - - for (int i = 17; i < 25; i++) { - state[i] = _mm256_set1_epi64x(0); - } - - KeccakP1600times4_PermuteAll_24rounds(&state[0]); - - for (int i = 0; i < SPX_N / 8; i++) { - ((int64_t *)out0)[i] = _mm256_extract_epi64(state[i], 0); - ((int64_t *)out1)[i] = _mm256_extract_epi64(state[i], 1); - ((int64_t *)out2)[i] = _mm256_extract_epi64(state[i], 2); - ((int64_t *)out3)[i] = _mm256_extract_epi64(state[i], 3); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/hashx4.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/hashx4.h deleted file mode 100644 index 3751a0ebd0..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/hashx4.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef SPX_HASHX4_H -#define SPX_HASHX4_H - -#include - -#include "context.h" -#include "params.h" - -#define prf_addrx4 SPX_NAMESPACE(prf_addrx4) -void prf_addrx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const spx_ctx *ctx, - const uint32_t addrx4[4 * 8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/merkle.c b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/merkle.c deleted file mode 100644 index f57811c1ac..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/merkle.c +++ /dev/null @@ -1,64 +0,0 @@ -#include -#include - -#include "merkle.h" - -#include "address.h" -#include "params.h" -#include "utils.h" -#include "utilsx4.h" -#include "wots.h" -#include "wotsx4.h" - -/* - * This generates a Merkle signature (WOTS signature followed by the Merkle - * authentication path). - */ -void merkle_sign(uint8_t *sig, unsigned char *root, - const spx_ctx *ctx, - uint32_t wots_addr[8], uint32_t tree_addr[8], - uint32_t idx_leaf) { - unsigned char *auth_path = sig + SPX_WOTS_BYTES; - uint32_t tree_addrx4[4 * 8] = { 0 }; - int j; - struct leaf_info_x4 info = { 0 }; - unsigned steps[ SPX_WOTS_LEN ]; - - info.wots_sig = sig; - chain_lengths(steps, root); - info.wots_steps = steps; - - for (j = 0; j < 4; j++) { - set_type(&tree_addrx4[8 * j], SPX_ADDR_TYPE_HASHTREE); - set_type(&info.leaf_addr[8 * j], SPX_ADDR_TYPE_WOTS); - set_type(&info.pk_addr[8 * j], SPX_ADDR_TYPE_WOTSPK); - copy_subtree_addr(&tree_addrx4[8 * j], tree_addr); - copy_subtree_addr(&info.leaf_addr[8 * j], wots_addr); - copy_subtree_addr(&info.pk_addr[8 * j], wots_addr); - } - - info.wots_sign_leaf = idx_leaf; - - treehashx4(root, auth_path, ctx, - idx_leaf, 0, - SPX_TREE_HEIGHT, - wots_gen_leafx4, - tree_addrx4, &info); -} - -/* Compute root node of the top-most subtree. */ -void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { - /* We do not need the auth path in key generation, but it simplifies the - code to have just one treehash routine that computes both root and path - in one function. */ - unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; - uint32_t top_tree_addr[8] = {0}; - uint32_t wots_addr[8] = {0}; - - set_layer_addr(top_tree_addr, SPX_D - 1); - set_layer_addr(wots_addr, SPX_D - 1); - - merkle_sign(auth_path, root, ctx, - wots_addr, top_tree_addr, - ~0U /* ~0 means "don't bother generating an auth path */ ); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/merkle.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/merkle.h deleted file mode 100644 index 769cf2e970..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/merkle.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef MERKLE_H_ -#define MERKLE_H_ - -#include - -#include "context.h" -#include "params.h" - -/* Generate a Merkle signature (WOTS signature followed by the Merkle */ -/* authentication path) */ -#define merkle_sign SPX_NAMESPACE(merkle_sign) -void merkle_sign(uint8_t *sig, unsigned char *root, - const spx_ctx *ctx, - uint32_t wots_addr[8], uint32_t tree_addr[8], - uint32_t idx_leaf); - -/* Compute the root node of the top-most subtree. */ -#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) -void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); - -#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/nistapi.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/nistapi.h deleted file mode 100644 index 3cb71afad4..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/nistapi.h +++ /dev/null @@ -1,87 +0,0 @@ -#ifndef SPX_API_H -#define SPX_API_H - -#include -#include - -#include "params.h" - -#define CRYPTO_ALGNAME "SPHINCS+" - -#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES -#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES -#define CRYPTO_BYTES SPX_BYTES -#define CRYPTO_SEEDBYTES (3*SPX_N) - -/* - * Returns the length of a secret key, in bytes - */ -#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) -size_t crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) -size_t crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) -size_t crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) -size_t crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) -int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) -int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) -int crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) -int crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -#define crypto_sign SPX_NAMESPACE(crypto_sign) -int crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) -int crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/params.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/params.h deleted file mode 100644 index 897e913f3d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/params.h +++ /dev/null @@ -1,56 +0,0 @@ -#ifndef SPX_PARAMS_H -#define SPX_PARAMS_H - -#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSSHAKE256FROBUST_AVX2_##s - -/* Hash output length in bytes. */ -#define SPX_N 32 -/* Height of the hypertree. */ -#define SPX_FULL_HEIGHT 68 -/* Number of subtree layer. */ -#define SPX_D 17 -/* FORS tree dimensions. */ -#define SPX_FORS_HEIGHT 9 -#define SPX_FORS_TREES 35 -/* Winternitz parameter, */ -#define SPX_WOTS_W 16 - -/* The hash function is defined by linking a different hash.c file, as opposed - to setting a #define constant. */ - -/* For clarity */ -#define SPX_ADDR_BYTES 32 - -/* WOTS parameters. */ -#define SPX_WOTS_LOGW 4 - -#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) - -/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#define SPX_WOTS_LEN2 3 - -#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) -#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) -#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES - -/* Subtree size. */ -#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) - -//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT -// #error SPX_D should always divide SPX_FULL_HEIGHT -//#endif - -/* FORS parameters. */ -#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) -#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) -#define SPX_FORS_PK_BYTES SPX_N - -/* Resulting SPX sizes. */ -#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ - SPX_FULL_HEIGHT * SPX_N) -#define SPX_PK_BYTES (2 * SPX_N) -#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) - -#include "shake_offsets.h" - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/shake_offsets.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/shake_offsets.h deleted file mode 100644 index 6b28d95d91..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/shake_offsets.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef SHAKE_OFFSETS_H_ -#define SHAKE_OFFSETS_H_ - -/* - * Offsets of various fields in the address structure when we use SHAKE as - * the Sphincs+ hash function - */ - -#define SPX_OFFSET_LAYER 3 /* The byte used to specify the Merkle tree layer */ -#define SPX_OFFSET_TREE 8 /* The start of the 8 byte field used to specify the tree */ -#define SPX_OFFSET_TYPE 19 /* The byte used to specify the hash type (reason) */ -#define SPX_OFFSET_KP_ADDR2 22 /* The high byte used to specify the key pair (which one-time signature) */ -#define SPX_OFFSET_KP_ADDR1 23 /* The low byte used to specify the key pair */ -#define SPX_OFFSET_CHAIN_ADDR 27 /* The byte used to specify the chain address (which Winternitz chain) */ -#define SPX_OFFSET_HASH_ADDR 31 /* The byte used to specify the hash address (where in the Winternitz chain) */ -#define SPX_OFFSET_TREE_HGT 27 /* The byte used to specify the height of this node in the FORS or Merkle tree */ -#define SPX_OFFSET_TREE_INDEX 28 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ - -#define SPX_SHAKE 1 - -#endif /* SHAKE_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/sign.c b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/sign.c deleted file mode 100644 index 9d0c7d1b22..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/sign.c +++ /dev/null @@ -1,286 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "context.h" -#include "fors.h" -#include "hash.h" -#include "merkle.h" -#include "nistapi.h" -#include "params.h" -#include "randombytes.h" -#include "thash.h" -#include "utils.h" -#include "wots.h" - -/* - * Returns the length of a secret key, in bytes - */ -size_t crypto_sign_secretkeybytes(void) { - return CRYPTO_SECRETKEYBYTES; -} - -/* - * Returns the length of a public key, in bytes - */ -size_t crypto_sign_publickeybytes(void) { - return CRYPTO_PUBLICKEYBYTES; -} - -/* - * Returns the length of a signature, in bytes - */ -size_t crypto_sign_bytes(void) { - return CRYPTO_BYTES; -} - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t crypto_sign_seedbytes(void) { - return CRYPTO_SEEDBYTES; -} - -/* - * Generates an SPX key pair given a seed of length - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed) { - spx_ctx ctx; - - /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ - memcpy(sk, seed, CRYPTO_SEEDBYTES); - - memcpy(pk, sk + 2 * SPX_N, SPX_N); - - memcpy(ctx.pub_seed, pk, SPX_N); - memcpy(ctx.sk_seed, sk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - /* Compute root node of the top-most subtree. */ - merkle_gen_root(sk + 3 * SPX_N, &ctx); - - // cleanup - free_hash_function(&ctx); - - memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); - - return 0; -} - -/* - * Generates an SPX key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { - uint8_t seed[CRYPTO_SEEDBYTES]; - randombytes(seed, CRYPTO_SEEDBYTES); - crypto_sign_seed_keypair(pk, sk, seed); - - return 0; -} - -/** - * Returns an array containing a detached signature. - */ -int crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - spx_ctx ctx; - - const uint8_t *sk_prf = sk + SPX_N; - const uint8_t *pk = sk + 2 * SPX_N; - - uint8_t optrand[SPX_N]; - uint8_t mhash[SPX_FORS_MSG_BYTES]; - uint8_t root[SPX_N]; - uint32_t i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - - memcpy(ctx.sk_seed, sk, SPX_N); - memcpy(ctx.pub_seed, pk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - set_type(wots_addr, SPX_ADDR_TYPE_WOTS); - set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); - - /* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ - randombytes(optrand, SPX_N); - /* Compute the digest randomization value. */ - gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); - - /* Derive the message digest and leaf index from R, PK and M. */ - hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); - sig += SPX_N; - - set_tree_addr(wots_addr, tree); - set_keypair_addr(wots_addr, idx_leaf); - - /* Sign the message hash using FORS. */ - fors_sign(sig, root, mhash, &ctx, wots_addr); - sig += SPX_FORS_BYTES; - - for (i = 0; i < SPX_D; i++) { - set_layer_addr(tree_addr, i); - set_tree_addr(tree_addr, tree); - - copy_subtree_addr(wots_addr, tree_addr); - set_keypair_addr(wots_addr, idx_leaf); - - merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); - sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); - tree = tree >> SPX_TREE_HEIGHT; - } - - free_hash_function(&ctx); - - *siglen = SPX_BYTES; - - return 0; -} - -/** - * Verifies a detached signature and message under a given public key. - */ -int crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk) { - spx_ctx ctx; - const uint8_t *pub_root = pk + SPX_N; - uint8_t mhash[SPX_FORS_MSG_BYTES]; - uint8_t wots_pk[SPX_WOTS_BYTES]; - uint8_t root[SPX_N]; - uint8_t leaf[SPX_N]; - unsigned int i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - if (siglen != SPX_BYTES) { - return -1; - } - - memcpy(ctx.pub_seed, pk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - set_type(wots_addr, SPX_ADDR_TYPE_WOTS); - set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); - set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); - - /* Derive the message digest and leaf index from R || PK || M. */ - /* The additional SPX_N is a result of the hash domain separator. */ - hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); - sig += SPX_N; - - /* Layer correctly defaults to 0, so no need to set_layer_addr */ - set_tree_addr(wots_addr, tree); - set_keypair_addr(wots_addr, idx_leaf); - - fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); - sig += SPX_FORS_BYTES; - - /* For each subtree.. */ - for (i = 0; i < SPX_D; i++) { - set_layer_addr(tree_addr, i); - set_tree_addr(tree_addr, tree); - - copy_subtree_addr(wots_addr, tree_addr); - set_keypair_addr(wots_addr, idx_leaf); - - copy_keypair_addr(wots_pk_addr, wots_addr); - - /* The WOTS public key is only correct if the signature was correct. */ - /* Initially, root is the FORS pk, but on subsequent iterations it is - the root of the subtree below the currently processed subtree. */ - wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); - sig += SPX_WOTS_BYTES; - - /* Compute the leaf node using the WOTS public key. */ - thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); - - /* Compute the root node of this subtree. */ - compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, - &ctx, tree_addr); - sig += SPX_TREE_HEIGHT * SPX_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); - tree = tree >> SPX_TREE_HEIGHT; - } - - // cleanup - free_hash_function(&ctx); - - /* Check if the root node equals the root node in the public key. */ - if (memcmp(root, pub_root, SPX_N) != 0) { - return -1; - } - - return 0; -} - - -/** - * Returns an array containing the signature followed by the message. - */ -int crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk) { - size_t siglen; - - crypto_sign_signature(sm, &siglen, m, mlen, sk); - - memmove(sm + SPX_BYTES, m, mlen); - *smlen = siglen + mlen; - - return 0; -} - -/** - * Verifies a given signature-message pair under a given public key. - */ -int crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk) { - /* The API caller does not necessarily know what size a signature should be - but SPHINCS+ signatures are always exactly SPX_BYTES. */ - if (smlen < SPX_BYTES) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - *mlen = smlen - SPX_BYTES; - - if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - /* If verification was successful, move the message to the right place. */ - memmove(m, sm + SPX_BYTES, *mlen); - - return 0; -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/thash.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/thash.h deleted file mode 100644 index 8687ccfb4d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/thash.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef SPX_THASH_H -#define SPX_THASH_H - -#include "context.h" -#include "params.h" - -#include - -#define thash SPX_NAMESPACE(thash) -void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/thash_shake_robust.c b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/thash_shake_robust.c deleted file mode 100644 index 696d53c5cc..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/thash_shake_robust.c +++ /dev/null @@ -1,31 +0,0 @@ -#include -#include - -#include "thash.h" - -#include "address.h" -#include "params.h" -#include "utils.h" - -#include "fips202.h" - -/** - * Takes an array of inblocks concatenated arrays of SPX_N bytes. - */ -void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]) { - PQCLEAN_VLA(uint8_t, buf, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); - PQCLEAN_VLA(uint8_t, bitmask, inblocks * SPX_N); - unsigned int i; - - memcpy(buf, ctx->pub_seed, SPX_N); - memcpy(buf + SPX_N, addr, SPX_ADDR_BYTES); - - shake256(bitmask, inblocks * SPX_N, buf, SPX_N + SPX_ADDR_BYTES); - - for (i = 0; i < inblocks * SPX_N; i++) { - buf[SPX_N + SPX_ADDR_BYTES + i] = in[i] ^ bitmask[i]; - } - - shake256(out, SPX_N, buf, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/thash_shake_robustx4.c b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/thash_shake_robustx4.c deleted file mode 100644 index ce2946b745..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/thash_shake_robustx4.c +++ /dev/null @@ -1,131 +0,0 @@ -#include -#include - -#include "thashx4.h" - -#include "address.h" -#include "params.h" -#include "utils.h" - -#include "fips202x4.h" - -extern void KeccakP1600times4_PermuteAll_24rounds(__m256i *s); - -/** - * 4-way parallel version of thash; takes 4x as much input and output - */ -void thashx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addrx4[4 * 8]) { - if (inblocks == 1 || inblocks == 2) { - /* As we write and read only a few quadwords, it is more efficient to - * build and extract from the fourway SHAKE256 state by hand. */ - __m256i state[25]; - for (int i = 0; i < SPX_N / 8; i++) { - state[i] = _mm256_set1_epi64x(((int64_t *)ctx->pub_seed)[i]); - } - for (int i = 0; i < 4; i++) { - state[SPX_N / 8 + i] = _mm256_set_epi32( - (int)addrx4[3 * 8 + 1 + 2 * i], - (int)addrx4[3 * 8 + 2 * i], - (int)addrx4[2 * 8 + 1 + 2 * i], - (int)addrx4[2 * 8 + 2 * i], - (int)addrx4[8 + 1 + 2 * i], - (int)addrx4[8 + 2 * i], - (int)addrx4[1 + 2 * i], - (int)addrx4[2 * i] - ); - } - - /* SHAKE domain separator and padding */ - state[SPX_N / 8 + 4] = _mm256_set1_epi64x(0x1f); - for (int i = SPX_N / 8 + 5; i < 16; i++) { - state[i] = _mm256_set1_epi64x(0); - } - state[16] = _mm256_set1_epi64x((long long)(0x80ULL << 56)); - - for (int i = 17; i < 25; i++) { - state[i] = _mm256_set1_epi64x(0); - } - - /* We will permutate state2 with f1600x4 to compute the bitmask, - * but first we'll copy it to state2 which will be used to compute - * the final output, as its input is alsmost identical. */ - __m256i state2[25]; - memcpy(state2, state, 800); - - KeccakP1600times4_PermuteAll_24rounds(&state[0]); - - /* By copying from state, state2 already contains the pub_seed - * and addres. We just need to copy in the input blocks xorred with - * the bitmask we just computed. */ - for (unsigned int i = 0; i < (SPX_N / 8) * inblocks; i++) { - state2[SPX_N / 8 + 4 + i] = _mm256_xor_si256( - state[i], - _mm256_set_epi64x( - ((int64_t *)in3)[i], - ((int64_t *)in2)[i], - ((int64_t *)in1)[i], - ((int64_t *)in0)[i] - ) - ); - } - - /* Domain separator and start of padding. Note that the quadwords - * around are already zeroed for state from which we copied. - * We do a XOR instead of a set as this might be the 16th quadword - * when N=32 and inblocks=2, which already contains the end - * of the padding. */ - state2[(SPX_N / 8) * (1 + inblocks) + 4] = _mm256_xor_si256( - state2[(SPX_N / 8) * (1 + inblocks) + 4], - _mm256_set1_epi64x(0x1f) - ); - - KeccakP1600times4_PermuteAll_24rounds(&state2[0]); - - for (int i = 0; i < SPX_N / 8; i++) { - ((int64_t *)out0)[i] = _mm256_extract_epi64(state2[i], 0); - ((int64_t *)out1)[i] = _mm256_extract_epi64(state2[i], 1); - ((int64_t *)out2)[i] = _mm256_extract_epi64(state2[i], 2); - ((int64_t *)out3)[i] = _mm256_extract_epi64(state2[i], 3); - } - } else { - PQCLEAN_VLA(unsigned char, buf0, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); - PQCLEAN_VLA(unsigned char, buf1, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); - PQCLEAN_VLA(unsigned char, buf2, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); - PQCLEAN_VLA(unsigned char, buf3, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); - PQCLEAN_VLA(unsigned char, bitmask0, inblocks * SPX_N); - PQCLEAN_VLA(unsigned char, bitmask1, inblocks * SPX_N); - PQCLEAN_VLA(unsigned char, bitmask2, inblocks * SPX_N); - PQCLEAN_VLA(unsigned char, bitmask3, inblocks * SPX_N); - unsigned int i; - - memcpy(buf0, ctx->pub_seed, SPX_N); - memcpy(buf1, ctx->pub_seed, SPX_N); - memcpy(buf2, ctx->pub_seed, SPX_N); - memcpy(buf3, ctx->pub_seed, SPX_N); - memcpy(buf0 + SPX_N, addrx4 + 0 * 8, SPX_ADDR_BYTES); - memcpy(buf1 + SPX_N, addrx4 + 1 * 8, SPX_ADDR_BYTES); - memcpy(buf2 + SPX_N, addrx4 + 2 * 8, SPX_ADDR_BYTES); - memcpy(buf3 + SPX_N, addrx4 + 3 * 8, SPX_ADDR_BYTES); - - shake256x4(bitmask0, bitmask1, bitmask2, bitmask3, inblocks * SPX_N, - buf0, buf1, buf2, buf3, SPX_N + SPX_ADDR_BYTES); - - for (i = 0; i < inblocks * SPX_N; i++) { - buf0[SPX_N + SPX_ADDR_BYTES + i] = in0[i] ^ bitmask0[i]; - buf1[SPX_N + SPX_ADDR_BYTES + i] = in1[i] ^ bitmask1[i]; - buf2[SPX_N + SPX_ADDR_BYTES + i] = in2[i] ^ bitmask2[i]; - buf3[SPX_N + SPX_ADDR_BYTES + i] = in3[i] ^ bitmask3[i]; - } - - shake256x4(out0, out1, out2, out3, SPX_N, - buf0, buf1, buf2, buf3, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/thashx4.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/thashx4.h deleted file mode 100644 index 64798a3727..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/thashx4.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef SPX_THASHX4_H -#define SPX_THASHX4_H - -#include - -#include "context.h" -#include "params.h" - -#define thashx4 SPX_NAMESPACE(thashx4) -void thashx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addrx4[4 * 8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/utils.c b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/utils.c deleted file mode 100644 index 177b541fb9..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/utils.c +++ /dev/null @@ -1,148 +0,0 @@ -#include - -#include "utils.h" - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "thash.h" - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void ull_to_bytes(unsigned char *out, unsigned int outlen, - unsigned long long in) { - int i; - - /* Iterate over out in decreasing order, for big-endianness. */ - for (i = (signed int)outlen - 1; i >= 0; i--) { - out[i] = in & 0xff; - in = in >> 8; - } -} - -void u32_to_bytes(unsigned char *out, uint32_t in) { - out[0] = (unsigned char)(in >> 24); - out[1] = (unsigned char)(in >> 16); - out[2] = (unsigned char)(in >> 8); - out[3] = (unsigned char)in; -} - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { - unsigned long long retval = 0; - unsigned int i; - - for (i = 0; i < inlen; i++) { - retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); - } - return retval; -} - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void compute_root(unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const spx_ctx *ctx, uint32_t addr[8]) { - uint32_t i; - unsigned char buffer[2 * SPX_N]; - - /* If leaf_idx is odd (last bit = 1), current path element is a right child - and auth_path has to go left. Otherwise it is the other way around. */ - if (leaf_idx & 1) { - memcpy(buffer + SPX_N, leaf, SPX_N); - memcpy(buffer, auth_path, SPX_N); - } else { - memcpy(buffer, leaf, SPX_N); - memcpy(buffer + SPX_N, auth_path, SPX_N); - } - auth_path += SPX_N; - - for (i = 0; i < tree_height - 1; i++) { - leaf_idx >>= 1; - idx_offset >>= 1; - /* Set the address of the node we're creating. */ - set_tree_height(addr, i + 1); - set_tree_index(addr, leaf_idx + idx_offset); - - /* Pick the right or left neighbor, depending on parity of the node. */ - if (leaf_idx & 1) { - thash(buffer + SPX_N, buffer, 2, ctx, addr); - memcpy(buffer, auth_path, SPX_N); - } else { - thash(buffer, buffer, 2, ctx, addr); - memcpy(buffer + SPX_N, auth_path, SPX_N); - } - auth_path += SPX_N; - } - - /* The last iteration is exceptional; we do not copy an auth_path node. */ - leaf_idx >>= 1; - idx_offset >>= 1; - set_tree_height(addr, tree_height); - set_tree_index(addr, leaf_idx + idx_offset); - thash(root, buffer, 2, ctx, addr); -} - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const spx_ctx * /* ctx */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), - uint32_t tree_addr[8]) { - PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); - PQCLEAN_VLA(unsigned int, heights, tree_height + 1); - unsigned int offset = 0; - uint32_t idx; - uint32_t tree_idx; - - for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { - /* Add the next leaf node to the stack. */ - gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); - offset++; - heights[offset - 1] = 0; - - /* If this is a node we need for the auth path.. */ - if ((leaf_idx ^ 0x1) == idx) { - memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); - } - - /* While the top-most nodes are of equal height.. */ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { - /* Compute index of the new node, in the next layer. */ - tree_idx = (idx >> (heights[offset - 1] + 1)); - - /* Set the address of the node we're creating. */ - set_tree_height(tree_addr, heights[offset - 1] + 1); - set_tree_index(tree_addr, - tree_idx + (idx_offset >> (heights[offset - 1] + 1))); - /* Hash the top-most nodes from the stack together. */ - thash(stack + (offset - 2)*SPX_N, - stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); - offset--; - /* Note that the top-most node is now one layer higher. */ - heights[offset - 1]++; - - /* If this is a node we need for the auth path.. */ - if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_path + heights[offset - 1]*SPX_N, - stack + (offset - 1)*SPX_N, SPX_N); - } - } - } - memcpy(root, stack, SPX_N); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/utils.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/utils.h deleted file mode 100644 index 64f5d5a53a..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/utils.h +++ /dev/null @@ -1,58 +0,0 @@ -#ifndef SPX_UTILS_H -#define SPX_UTILS_H - -#include - -#include "compat.h" -#include "context.h" -#include "params.h" - - -/* To support MSVC use alloca() instead of VLAs. See #20. */ - - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) -void ull_to_bytes(unsigned char *out, unsigned int outlen, - unsigned long long in); -#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) -void u32_to_bytes(unsigned char *out, uint32_t in); - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) -unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -#define compute_root SPX_NAMESPACE(compute_root) -void compute_root(unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const spx_ctx *ctx, uint32_t addr[8]); - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -#define treehash SPX_NAMESPACE(treehash) -void treehash(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const spx_ctx *ctx /* ctx */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), - uint32_t tree_addr[8]); - - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/utilsx4.c b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/utilsx4.c deleted file mode 100644 index 1638677194..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/utilsx4.c +++ /dev/null @@ -1,138 +0,0 @@ -#include - -#include "utilsx4.h" - -#include "address.h" -#include "params.h" -#include "thashx4.h" -#include "utils.h" - -/* - * Generate the entire Merkle tree, computing the authentication path for leaf_idx, - * and the resulting root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) - * - * This expects tree_addrx4 to be initialized to 4 parallel addr structures for - * the Merkle tree nodes - * - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - * - * This works by using the standard Merkle tree building algorithm, except - * that each 'node' tracked is actually 4 consecutive nodes in the real tree. - * When we combine two logical nodes ABCD and WXYZ, we perform the H - * operation on adjacent real nodes, forming the parent logical node - * (AB)(CD)(WX)(YZ) - * - * When we get to the top two levels of the real tree (where there is only - * one logical node), we continue this operation two more times; the right - * most real node will by the actual root (and the other 3 nodes will be - * garbage). We follow the same thashx4 logic so that the 'extract - * authentication path components' part of the loop is still executed (and - * to simplify the code somewhat) - * - * This currently assumes tree_height >= 2; I suspect that doing an adjusting - * idx, addr_idx on the gen_leafx4 call if tree_height < 2 would fix it; since - * we don't actually use such short trees, I haven't bothered - */ -void treehashx4(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, - uint32_t tree_height, - void (*gen_leafx4)( - unsigned char * /* Where to write the leaves */, - const spx_ctx *, - uint32_t idx, void *info), - uint32_t tree_addrx4[4 * 8], - void *info) { - /* This is where we keep the intermediate nodes */ - PQCLEAN_VLA(unsigned char, stackx4, tree_height * 4 * SPX_N); - uint32_t left_adj = 0, prev_left_adj = 0; /* When we're doing the top 3 */ - /* levels, the left-most part of the tree isn't at the beginning */ - /* of current[]. These give the offset of the actual start */ - - uint32_t idx; - uint32_t max_idx = (1U << (tree_height - 2)) - 1; - for (idx = 0;; idx++) { - unsigned char current[4 * SPX_N]; /* Current logical node */ - gen_leafx4( current, ctx, 4 * idx + idx_offset, - info ); - - /* Now combine the freshly generated right node with previously */ - /* generated left ones */ - uint32_t internal_idx_offset = idx_offset; - uint32_t internal_idx = idx; - uint32_t internal_leaf = leaf_idx; - uint32_t h; /* The height we are in the Merkle tree */ - for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { - - /* Special processing if we're at the top of the tree */ - if (h >= tree_height - 2) { - if (h == tree_height) { - /* We hit the root; return it */ - memcpy( root, ¤t[3 * SPX_N], SPX_N ); - return; - } - /* The tree indexing logic is a bit off in this case */ - /* Adjust it so that the left-most node of the part of */ - /* the tree that we're processing has index 0 */ - prev_left_adj = left_adj; - left_adj = 4U - (1 << (tree_height - h - 1)); - } - - /* Check if we hit the top of the tree */ - if (h == tree_height) { - /* We hit the root; return it */ - memcpy( root, ¤t[3 * SPX_N], SPX_N ); - return; - } - - /* - * Check if one of the nodes we have is a part of the - * authentication path; if it is, write it out - */ - if ((((internal_idx << 2) ^ internal_leaf) & ~0x3U) == 0) { - memcpy( &auth_path[ h * SPX_N ], - ¤t[(((internal_leaf & 3) ^ 1) + prev_left_adj) * SPX_N], - SPX_N ); - } - - /* - * Check if we're at a left child; if so, stop going up the stack - * Exception: if we've reached the end of the tree, keep on going - * (so we combine the last 4 nodes into the one root node in two - * more iterations) - */ - if ((internal_idx & 1) == 0 && idx < max_idx) { - break; - } - - /* Ok, we're at a right node (or doing the top 3 levels) */ - /* Now combine the left and right logical nodes together */ - - /* Set the address of the node we're creating. */ - unsigned int j; - internal_idx_offset >>= 1; - for (j = 0; j < 4; j++) { - set_tree_height(tree_addrx4 + j * 8, h + 1); - set_tree_index(tree_addrx4 + j * 8, - (4 / 2) * (internal_idx & ~1U) + j - left_adj + internal_idx_offset ); - } - unsigned char *left = &stackx4[h * 4 * SPX_N]; - thashx4( ¤t[0 * SPX_N], - ¤t[1 * SPX_N], - ¤t[2 * SPX_N], - ¤t[3 * SPX_N], - &left [0 * SPX_N], - &left [2 * SPX_N], - ¤t[0 * SPX_N], - ¤t[2 * SPX_N], - 2, ctx, tree_addrx4); - } - - /* We've hit a left child; save the current for when we get the */ - /* corresponding right right */ - memcpy( &stackx4[h * 4 * SPX_N], current, 4 * SPX_N); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/utilsx4.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/utilsx4.h deleted file mode 100644 index facb874b18..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/utilsx4.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef SPX_UTILSX4_H -#define SPX_UTILSX4_H - -#include - -#include "context.h" -#include "params.h" - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - * - * This implementation uses AVX to compute internal nodes 4 at a time (in - * parallel) - */ -#define treehashx4 SPX_NAMESPACE(treehashx4) -void treehashx4(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leafx4)( - unsigned char * /* Where to write the leaves */, - const spx_ctx * /* ctx */, - uint32_t addr_idx, void *info), - uint32_t tree_addrx4[4 * 8], void *info); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/wots.c b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/wots.c deleted file mode 100644 index 4d5041ce05..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/wots.c +++ /dev/null @@ -1,269 +0,0 @@ -#include -#include - -#include "wots.h" - -#include "address.h" -#include "hash.h" -#include "hashx4.h" -#include "params.h" -#include "thash.h" -#include "thashx4.h" -#include "utils.h" -#include "utilsx4.h" -#include "wotsx4.h" - -// TODO clarify address expectations, and make them more uniform. -// TODO i.e. do we expect types to be set already? -// TODO and do we expect modifications or copies? - -/** - * Computes up the chains - */ -static void gen_chains( - unsigned char *out, - const unsigned char *in, - unsigned int start[SPX_WOTS_LEN], - const unsigned int steps[SPX_WOTS_LEN], - const spx_ctx *ctx, - uint32_t addr[8]) { - uint32_t i, j, k, idx, watching; - int done; - unsigned char empty[SPX_N]; - unsigned char *bufs[4]; - uint32_t addrs[8 * 4]; - - int l; - uint16_t counts[SPX_WOTS_W] = { 0 }; - uint16_t idxs[SPX_WOTS_LEN]; - uint16_t total, newTotal; - - /* set addrs = {addr, addr, addr, addr} */ - for (j = 0; j < 4; j++) { - memcpy(addrs + j * 8, addr, sizeof(uint32_t) * 8); - } - - /* Initialize out with the value at position 'start'. */ - memcpy(out, in, SPX_WOTS_LEN * SPX_N); - - /* Sort the chains in reverse order by steps using counting sort. */ - for (i = 0; i < SPX_WOTS_LEN; i++) { - counts[steps[i]]++; - } - total = 0; - for (l = SPX_WOTS_W - 1; l >= 0; l--) { - newTotal = counts[l] + total; - counts[l] = total; - total = newTotal; - } - for (i = 0; i < SPX_WOTS_LEN; i++) { - idxs[counts[steps[i]]] = (uint16_t)i; - counts[steps[i]]++; - } - - /* We got our work cut out for us: do it! */ - for (i = 0; i < SPX_WOTS_LEN; i += 4) { - for (j = 0; j < 4 && i + j < SPX_WOTS_LEN; j++) { - idx = idxs[i + j]; - set_chain_addr(addrs + j * 8, idx); - bufs[j] = out + SPX_N * idx; - } - - /* As the chains are sorted in reverse order, we know that the first - * chain is the longest and the last one is the shortest. We keep - * an eye on whether the last chain is done and then on the one before, - * et cetera. */ - watching = 3; - done = 0; - while (i + watching >= SPX_WOTS_LEN) { - bufs[watching] = &empty[0]; - watching--; - } - - for (k = 0;; k++) { - while (k == steps[idxs[i + watching]]) { - bufs[watching] = &empty[0]; - if (watching == 0) { - done = 1; - break; - } - watching--; - } - if (done) { - break; - } - for (j = 0; j < watching + 1; j++) { - set_hash_addr(addrs + j * 8, k + start[idxs[i + j]]); - } - - thashx4(bufs[0], bufs[1], bufs[2], bufs[3], - bufs[0], bufs[1], bufs[2], bufs[3], 1, ctx, addrs); - } - } -} - -/** - * base_w algorithm as described in draft. - * Interprets an array of bytes as integers in base w. - * This only works when log_w is a divisor of 8. - */ -static void base_w(unsigned int *output, const int out_len, - const unsigned char *input) { - int in = 0; - int out = 0; - unsigned char total = 0; - int bits = 0; - int consumed; - - for (consumed = 0; consumed < out_len; consumed++) { - if (bits == 0) { - total = input[in]; - in++; - bits += 8; - } - bits -= SPX_WOTS_LOGW; - output[out] = (total >> bits) & (SPX_WOTS_W - 1); - out++; - } -} - -/* Computes the WOTS+ checksum over a message (in base_w). */ -static void wots_checksum(unsigned int *csum_base_w, - const unsigned int *msg_base_w) { - unsigned int csum = 0; - unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; - unsigned int i; - - /* Compute checksum. */ - for (i = 0; i < SPX_WOTS_LEN1; i++) { - csum += SPX_WOTS_W - 1 - msg_base_w[i]; - } - - /* Convert checksum to base_w. */ - /* Make sure expected empty zero bits are the least significant bits. */ - csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); - ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); - base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); -} - -/* Takes a message and derives the matching chain lengths. */ -void chain_lengths(unsigned int *lengths, const unsigned char *msg) { - base_w(lengths, SPX_WOTS_LEN1, msg); - wots_checksum(lengths + SPX_WOTS_LEN1, lengths); -} - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const spx_ctx *ctx, uint32_t addr[8]) { - unsigned int steps[SPX_WOTS_LEN]; - unsigned int start[SPX_WOTS_LEN]; - uint32_t i; - - chain_lengths(start, msg); - - for (i = 0; i < SPX_WOTS_LEN; i++) { - steps[i] = SPX_WOTS_W - 1 - start[i]; - } - - gen_chains(pk, sig, start, steps, ctx, addr); -} - -/* - * This generates 4 sequential WOTS public keys - * It also generates the WOTS signature if leaf_info indicates - * that we're signing with one of these WOTS keys - */ -void wots_gen_leafx4(unsigned char *dest, - const spx_ctx *ctx, - uint32_t leaf_idx, void *v_info) { - struct leaf_info_x4 *info = v_info; - uint32_t *leaf_addr = info->leaf_addr; - uint32_t *pk_addr = info->pk_addr; - unsigned int i, j, k; - unsigned char pk_buffer[ 4 * SPX_WOTS_BYTES ]; - unsigned wots_offset = SPX_WOTS_BYTES; - unsigned char *buffer; - uint32_t wots_k_mask; - unsigned wots_sign_index; - - if (((leaf_idx ^ info->wots_sign_leaf) & ~3U) == 0) { - /* We're traversing the leaf that's signing; generate the WOTS */ - /* signature */ - wots_k_mask = 0; - wots_sign_index = info->wots_sign_leaf & 3; /* Which of of the 4 */ - /* 4 slots do the signatures come from */ - } else { - /* Nope, we're just generating pk's; turn off the signature logic */ - wots_k_mask = (uint32_t)~0; - wots_sign_index = 0; - } - - for (j = 0; j < 4; j++) { - set_keypair_addr( leaf_addr + j * 8, leaf_idx + j ); - set_keypair_addr( pk_addr + j * 8, leaf_idx + j ); - } - - for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { - uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k to */ - /* the step if we're generating a signature, ~0 if we're not */ - - /* Start with the secret seed */ - for (j = 0; j < 4; j++) { - set_chain_addr(leaf_addr + j * 8, i); - set_hash_addr(leaf_addr + j * 8, 0); - set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTSPRF); - } - prf_addrx4(buffer + 0 * wots_offset, - buffer + 1 * wots_offset, - buffer + 2 * wots_offset, - buffer + 3 * wots_offset, - ctx, leaf_addr); - - for (j = 0; j < 4; j++) { - set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTS); - } - - /* Iterate down the WOTS chain */ - for (k = 0;; k++) { - /* Check if one of the values we have needs to be saved as a */ - /* part of the WOTS signature */ - if (k == wots_k) { - memcpy( info->wots_sig + i * SPX_N, - buffer + wots_sign_index * wots_offset, SPX_N ); - } - - /* Check if we hit the top of the chain */ - if (k == SPX_WOTS_W - 1) { - break; - } - - /* Iterate one step on all 4 chains */ - for (j = 0; j < 4; j++) { - set_hash_addr(leaf_addr + j * 8, k); - } - thashx4(buffer + 0 * wots_offset, - buffer + 1 * wots_offset, - buffer + 2 * wots_offset, - buffer + 3 * wots_offset, - buffer + 0 * wots_offset, - buffer + 1 * wots_offset, - buffer + 2 * wots_offset, - buffer + 3 * wots_offset, 1, ctx, leaf_addr); - } - } - - /* Do the final thash to generate the public keys */ - thashx4(dest + 0 * SPX_N, - dest + 1 * SPX_N, - dest + 2 * SPX_N, - dest + 3 * SPX_N, - pk_buffer + 0 * wots_offset, - pk_buffer + 1 * wots_offset, - pk_buffer + 2 * wots_offset, - pk_buffer + 3 * wots_offset, SPX_WOTS_LEN, ctx, pk_addr); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/wots.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/wots.h deleted file mode 100644 index 4e7692eeef..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/wots.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef SPX_WOTS_H -#define SPX_WOTS_H - -#include - -#include "context.h" -#include "params.h" - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) -void wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const spx_ctx *ctx, uint32_t addr[8]); - -/* - * Compute the chain lengths needed for a given message hash - */ -#define chain_lengths SPX_NAMESPACE(chain_lengths) -void chain_lengths(unsigned int *lengths, const unsigned char *msg); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/wotsx4.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/wotsx4.h deleted file mode 100644 index cd634f1743..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_avx2/wotsx4.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef WOTSX4_H_ -#define WOTSX4_H_ - -#include - -#include "params.h" - -/* - * This is here to provide an interface to the internal wots_gen_leafx4 - * routine. While this routine is not referenced in the package outside of - * wots.c, it is called from the stand-alone benchmark code to characterize - * the performance - */ -struct leaf_info_x4 { - unsigned char *wots_sig; - uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ - uint32_t *wots_steps; - uint32_t leaf_addr[4 * 8]; - uint32_t pk_addr[4 * 8]; -}; - -/* Macro to set the leaf_info to something 'benign', that is, it would */ -/* run with the same time as it does during the real signing process */ -/* Used only by the benchmark code */ -#define INITIALIZE_LEAF_INFO_X4(info, addr, step_buffer) { \ - (info).wots_sig = 0; \ - (info).wots_sign_leaf = ~0; \ - (info).wots_steps = step_buffer; \ - int i; \ - for (i=0; i<4; i++) { \ - memcpy( &(info).leaf_addr[8*i], addr, 32 ); \ - memcpy( &(info).pk_addr[8*i], addr, 32 ); \ - } \ - } - -#define wots_gen_leafx4 SPX_NAMESPACE(wots_gen_leafx4) -void wots_gen_leafx4(unsigned char *dest, - const spx_ctx *ctx, - uint32_t leaf_idx, void *v_info); - -#endif /* WOTSX4_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/LICENSE b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/LICENSE deleted file mode 100644 index 670154e353..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/LICENSE +++ /dev/null @@ -1,116 +0,0 @@ -CC0 1.0 Universal - -Statement of Purpose - -The laws of most jurisdictions throughout the world automatically confer -exclusive Copyright and Related Rights (defined below) upon the creator and -subsequent owner(s) (each and all, an "owner") of an original work of -authorship and/or a database (each, a "Work"). - -Certain owners wish to permanently relinquish those rights to a Work for the -purpose of contributing to a commons of creative, cultural and scientific -works ("Commons") that the public can reliably and without fear of later -claims of infringement build upon, modify, incorporate in other works, reuse -and redistribute as freely as possible in any form whatsoever and for any -purposes, including without limitation commercial purposes. These owners may -contribute to the Commons to promote the ideal of a free culture and the -further production of creative, cultural and scientific works, or to gain -reputation or greater distribution for their Work in part through the use and -efforts of others. - -For these and/or other purposes and motivations, and without any expectation -of additional consideration or compensation, the person associating CC0 with a -Work (the "Affirmer"), to the extent that he or she is an owner of Copyright -and Related Rights in the Work, voluntarily elects to apply CC0 to the Work -and publicly distribute the Work under its terms, with knowledge of his or her -Copyright and Related Rights in the Work and the meaning and intended legal -effect of CC0 on those rights. - -1. Copyright and Related Rights. A Work made available under CC0 may be -protected by copyright and related or neighboring rights ("Copyright and -Related Rights"). Copyright and Related Rights include, but are not limited -to, the following: - - i. the right to reproduce, adapt, distribute, perform, display, communicate, - and translate a Work; - - ii. moral rights retained by the original author(s) and/or performer(s); - - iii. publicity and privacy rights pertaining to a person's image or likeness - depicted in a Work; - - iv. rights protecting against unfair competition in regards to a Work, - subject to the limitations in paragraph 4(a), below; - - v. rights protecting the extraction, dissemination, use and reuse of data in - a Work; - - vi. database rights (such as those arising under Directive 96/9/EC of the - European Parliament and of the Council of 11 March 1996 on the legal - protection of databases, and under any national implementation thereof, - including any amended or successor version of such directive); and - - vii. other similar, equivalent or corresponding rights throughout the world - based on applicable law or treaty, and any national implementations thereof. - -2. Waiver. To the greatest extent permitted by, but not in contravention of, -applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and -unconditionally waives, abandons, and surrenders all of Affirmer's Copyright -and Related Rights and associated claims and causes of action, whether now -known or unknown (including existing as well as future claims and causes of -action), in the Work (i) in all territories worldwide, (ii) for the maximum -duration provided by applicable law or treaty (including future time -extensions), (iii) in any current or future medium and for any number of -copies, and (iv) for any purpose whatsoever, including without limitation -commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes -the Waiver for the benefit of each member of the public at large and to the -detriment of Affirmer's heirs and successors, fully intending that such Waiver -shall not be subject to revocation, rescission, cancellation, termination, or -any other legal or equitable action to disrupt the quiet enjoyment of the Work -by the public as contemplated by Affirmer's express Statement of Purpose. - -3. Public License Fallback. Should any part of the Waiver for any reason be -judged legally invalid or ineffective under applicable law, then the Waiver -shall be preserved to the maximum extent permitted taking into account -Affirmer's express Statement of Purpose. In addition, to the extent the Waiver -is so judged Affirmer hereby grants to each affected person a royalty-free, -non transferable, non sublicensable, non exclusive, irrevocable and -unconditional license to exercise Affirmer's Copyright and Related Rights in -the Work (i) in all territories worldwide, (ii) for the maximum duration -provided by applicable law or treaty (including future time extensions), (iii) -in any current or future medium and for any number of copies, and (iv) for any -purpose whatsoever, including without limitation commercial, advertising or -promotional purposes (the "License"). The License shall be deemed effective as -of the date CC0 was applied by Affirmer to the Work. Should any part of the -License for any reason be judged legally invalid or ineffective under -applicable law, such partial invalidity or ineffectiveness shall not -invalidate the remainder of the License, and in such case Affirmer hereby -affirms that he or she will not (i) exercise any of his or her remaining -Copyright and Related Rights in the Work or (ii) assert any associated claims -and causes of action with respect to the Work, in either case contrary to -Affirmer's express Statement of Purpose. - -4. Limitations and Disclaimers. - - a. No trademark or patent rights held by Affirmer are waived, abandoned, - surrendered, licensed or otherwise affected by this document. - - b. Affirmer offers the Work as-is and makes no representations or warranties - of any kind concerning the Work, express, implied, statutory or otherwise, - including without limitation warranties of title, merchantability, fitness - for a particular purpose, non infringement, or the absence of latent or - other defects, accuracy, or the present or absence of errors, whether or not - discoverable, all to the greatest extent permissible under applicable law. - - c. Affirmer disclaims responsibility for clearing rights of other persons - that may apply to the Work or any use thereof, including without limitation - any person's Copyright and Related Rights in the Work. Further, Affirmer - disclaims responsibility for obtaining any necessary consents, permissions - or other rights required for any use of the Work. - - d. Affirmer understands and acknowledges that Creative Commons is not a - party to this document and has no duty or obligation with respect to this - CC0 or use of the Work. - -For more information, please see - diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/address.c b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/address.c deleted file mode 100644 index b956e9cb29..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/address.c +++ /dev/null @@ -1,91 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "utils.h" - -/* - * Specify which level of Merkle tree (the "layer") we're working on - */ -void set_layer_addr(uint32_t addr[8], uint32_t layer) { - ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; -} - -/* - * Specify which Merkle tree within the level (the "tree address") we're working on - */ -void set_tree_addr(uint32_t addr[8], uint64_t tree) { - ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); -} - -/* - * Specify the reason we'll use this address structure for, that is, what - * hash will we compute with it. This is used so that unrelated types of - * hashes don't accidentally get the same address structure. The type will be - * one of the SPX_ADDR_TYPE constants - */ -void set_type(uint32_t addr[8], uint32_t type) { - ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; -} - -/* - * Copy the layer and tree fields of the address structure. This is used - * when we're doing multiple types of hashes within the same Merkle tree - */ -void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { - memcpy( out, in, SPX_OFFSET_TREE + 8 ); -} - -/* These functions are used for OTS addresses. */ - -/* - * Specify which Merkle leaf we're working on; that is, which OTS keypair - * we're talking about. - */ -void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { - ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; -} - -/* - * Copy the layer, tree and keypair fields of the address structure. This is - * used when we're doing multiple things within the same OTS keypair - */ -void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { - memcpy( out, in, SPX_OFFSET_TREE + 8 ); - ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; -} - -/* - * Specify which Merkle chain within the OTS we're working with - * (the chain address) - */ -void set_chain_addr(uint32_t addr[8], uint32_t chain) { - ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; -} - -/* - * Specify where in the Merkle chain we are -* (the hash address) - */ -void set_hash_addr(uint32_t addr[8], uint32_t hash) { - ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; -} - -/* These functions are used for all hash tree addresses (including FORS). */ - -/* - * Specify the height of the node in the Merkle/FORS tree we are in - * (the tree height) - */ -void set_tree_height(uint32_t addr[8], uint32_t tree_height) { - ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; -} - -/* - * Specify the distance from the left edge of the node in the Merkle/FORS tree - * (the tree index) - */ -void set_tree_index(uint32_t addr[8], uint32_t tree_index) { - u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/address.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/address.h deleted file mode 100644 index 24a84eb40c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/address.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef SPX_ADDRESS_H -#define SPX_ADDRESS_H - -#include - -#include "params.h" - -/* The hash types that are passed to set_type */ -#define SPX_ADDR_TYPE_WOTS 0 -#define SPX_ADDR_TYPE_WOTSPK 1 -#define SPX_ADDR_TYPE_HASHTREE 2 -#define SPX_ADDR_TYPE_FORSTREE 3 -#define SPX_ADDR_TYPE_FORSPK 4 -#define SPX_ADDR_TYPE_WOTSPRF 5 -#define SPX_ADDR_TYPE_FORSPRF 6 - -#define set_layer_addr SPX_NAMESPACE(set_layer_addr) -void set_layer_addr(uint32_t addr[8], uint32_t layer); - -#define set_tree_addr SPX_NAMESPACE(set_tree_addr) -void set_tree_addr(uint32_t addr[8], uint64_t tree); - -#define set_type SPX_NAMESPACE(set_type) -void set_type(uint32_t addr[8], uint32_t type); - -/* Copies the layer and tree part of one address into the other */ -#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) -void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for WOTS and FORS addresses. */ - -#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) -void set_keypair_addr(uint32_t addr[8], uint32_t keypair); - -#define set_chain_addr SPX_NAMESPACE(set_chain_addr) -void set_chain_addr(uint32_t addr[8], uint32_t chain); - -#define set_hash_addr SPX_NAMESPACE(set_hash_addr) -void set_hash_addr(uint32_t addr[8], uint32_t hash); - -#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) -void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for all hash tree addresses (including FORS). */ - -#define set_tree_height SPX_NAMESPACE(set_tree_height) -void set_tree_height(uint32_t addr[8], uint32_t tree_height); - -#define set_tree_index SPX_NAMESPACE(set_tree_index) -void set_tree_index(uint32_t addr[8], uint32_t tree_index); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/api.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/api.h deleted file mode 100644 index dc8607f070..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/api.h +++ /dev/null @@ -1,77 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256FROBUST_CLEAN_API_H -#define PQCLEAN_SPHINCSSHAKE256FROBUST_CLEAN_API_H - -#include -#include - -#define PQCLEAN_SPHINCSSHAKE256FROBUST_CLEAN_CRYPTO_ALGNAME "SPHINCS+-shake-256f-robust" - -#define PQCLEAN_SPHINCSSHAKE256FROBUST_CLEAN_CRYPTO_SECRETKEYBYTES 128 -#define PQCLEAN_SPHINCSSHAKE256FROBUST_CLEAN_CRYPTO_PUBLICKEYBYTES 64 -#define PQCLEAN_SPHINCSSHAKE256FROBUST_CLEAN_CRYPTO_BYTES 49856 - -#define PQCLEAN_SPHINCSSHAKE256FROBUST_CLEAN_CRYPTO_SEEDBYTES 96 - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256FROBUST_CLEAN_crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256FROBUST_CLEAN_crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256FROBUST_CLEAN_crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256FROBUST_CLEAN_crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHAKE256FROBUST_CLEAN_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHAKE256FROBUST_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSSHAKE256FROBUST_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE256FROBUST_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, - const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSSHAKE256FROBUST_CLEAN_crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE256FROBUST_CLEAN_crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk); -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/context.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/context.h deleted file mode 100644 index 9f8a40ab4e..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/context.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef SPX_CONTEXT_H -#define SPX_CONTEXT_H - -#include -#include - -#include "params.h" - -typedef struct { - uint8_t pub_seed[SPX_N]; - uint8_t sk_seed[SPX_N]; - - -} spx_ctx; - -#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) -void initialize_hash_function(spx_ctx *ctx); - -#define free_hash_function SPX_NAMESPACE(free_hash_function) -void free_hash_function(spx_ctx *ctx); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/context_shake.c b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/context_shake.c deleted file mode 100644 index 9614a103d3..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/context_shake.c +++ /dev/null @@ -1,12 +0,0 @@ -#include "context.h" - -/* For SHAKE256, there is no immediate reason to initialize at the start, - so this function is an empty operation. */ -void initialize_hash_function(spx_ctx *ctx) { - (void)ctx; /* Suppress an 'unused parameter' warning. */ -} - -// in case the hash function api is heap-based. -void free_hash_function(spx_ctx *ctx) { - (void)ctx; -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/fors.c b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/fors.c deleted file mode 100644 index 96ca72e986..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/fors.c +++ /dev/null @@ -1,156 +0,0 @@ -#include -#include -#include - -#include "fors.h" - -#include "address.h" -#include "hash.h" -#include "thash.h" -#include "utils.h" -#include "utilsx1.h" - -static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, - uint32_t fors_leaf_addr[8]) { - prf_addr(sk, ctx, fors_leaf_addr); -} - -static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, - const spx_ctx *ctx, - uint32_t fors_leaf_addr[8]) { - thash(leaf, sk, 1, ctx, fors_leaf_addr); -} - -struct fors_gen_leaf_info { - uint32_t leaf_addrx[8]; -}; - -static void fors_gen_leafx1(unsigned char *leaf, - const spx_ctx *ctx, - uint32_t addr_idx, void *info) { - struct fors_gen_leaf_info *fors_info = info; - uint32_t *fors_leaf_addr = fors_info->leaf_addrx; - - /* Only set the parts that the caller doesn't set */ - set_tree_index(fors_leaf_addr, addr_idx); - set_type(fors_leaf_addr, SPX_ADDR_TYPE_FORSPRF); - fors_gen_sk(leaf, ctx, fors_leaf_addr); - - set_type(fors_leaf_addr, SPX_ADDR_TYPE_FORSTREE); - fors_sk_to_leaf(leaf, leaf, - ctx, fors_leaf_addr); -} - -/** - * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - * Assumes indices has space for SPX_FORS_TREES integers. - */ -static void message_to_indices(uint32_t *indices, const unsigned char *m) { - unsigned int i, j; - unsigned int offset = 0; - - for (i = 0; i < SPX_FORS_TREES; i++) { - indices[i] = 0; - for (j = 0; j < SPX_FORS_HEIGHT; j++) { - indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); - offset++; - } - } -} - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -void fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]) { - uint32_t indices[SPX_FORS_TREES]; - unsigned char roots[SPX_FORS_TREES * SPX_N]; - uint32_t fors_tree_addr[8] = {0}; - struct fors_gen_leaf_info fors_info = {0}; - uint32_t *fors_leaf_addr = fors_info.leaf_addrx; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - copy_keypair_addr(fors_tree_addr, fors_addr); - copy_keypair_addr(fors_leaf_addr, fors_addr); - - copy_keypair_addr(fors_pk_addr, fors_addr); - set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < SPX_FORS_TREES; i++) { - idx_offset = i * (1 << SPX_FORS_HEIGHT); - - set_tree_height(fors_tree_addr, 0); - set_tree_index(fors_tree_addr, indices[i] + idx_offset); - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); - - /* Include the secret key part that produces the selected leaf node. */ - fors_gen_sk(sig, ctx, fors_tree_addr); - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); - sig += SPX_N; - - /* Compute the authentication path for this leaf node. */ - treehashx1(roots + i * SPX_N, sig, ctx, - indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx1, - fors_tree_addr, &fors_info); - - sig += SPX_N * SPX_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); -} - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -void fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]) { - uint32_t indices[SPX_FORS_TREES]; - unsigned char roots[SPX_FORS_TREES * SPX_N]; - unsigned char leaf[SPX_N]; - uint32_t fors_tree_addr[8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - copy_keypair_addr(fors_tree_addr, fors_addr); - copy_keypair_addr(fors_pk_addr, fors_addr); - - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); - set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < SPX_FORS_TREES; i++) { - idx_offset = i * (1 << SPX_FORS_HEIGHT); - - set_tree_height(fors_tree_addr, 0); - set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Derive the leaf from the included secret key part. */ - fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); - sig += SPX_N; - - /* Derive the corresponding root node of this tree. */ - compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, - sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); - sig += SPX_N * SPX_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/fors.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/fors.h deleted file mode 100644 index 509140a178..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/fors.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef SPX_FORS_H -#define SPX_FORS_H - -#include - -#include "context.h" -#include "params.h" - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -#define fors_sign SPX_NAMESPACE(fors_sign) -void fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]); - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) -void fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/hash.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/hash.h deleted file mode 100644 index f7c87d4c3c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/hash.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef SPX_HASH_H -#define SPX_HASH_H - -#include -#include - -#include "context.h" -#include "params.h" - -#define prf_addr SPX_NAMESPACE(prf_addr) -void prf_addr(unsigned char *out, const spx_ctx *ctx, - const uint32_t addr[8]); - -#define gen_message_random SPX_NAMESPACE(gen_message_random) -void gen_message_random(unsigned char *R, const unsigned char *sk_prf, - const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx); - -#define hash_message SPX_NAMESPACE(hash_message) -void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx); - - - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/hash_shake.c b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/hash_shake.c deleted file mode 100644 index ff5e7ec918..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/hash_shake.c +++ /dev/null @@ -1,83 +0,0 @@ -#include -#include - -#include "hash.h" - -#include "address.h" -#include "fips202.h" -#include "params.h" -#include "utils.h" - -/* - * Computes PRF(pk_seed, sk_seed, addr) - */ -void prf_addr(unsigned char *out, const spx_ctx *ctx, - const uint32_t addr[8]) { - unsigned char buf[2 * SPX_N + SPX_ADDR_BYTES]; - - memcpy(buf, ctx->pub_seed, SPX_N); - memcpy(buf + SPX_N, addr, SPX_ADDR_BYTES); - memcpy(buf + SPX_N + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); - - shake256(out, SPX_N, buf, 2 * SPX_N + SPX_ADDR_BYTES); -} - -/** - * Computes the message-dependent randomness R, using a secret seed and an - * optional randomization value as well as the message. - */ -void gen_message_random(unsigned char *R, const unsigned char *sk_prf, - const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx) { - (void)ctx; - shake256incctx s_inc; - - shake256_inc_init(&s_inc); - shake256_inc_absorb(&s_inc, sk_prf, SPX_N); - shake256_inc_absorb(&s_inc, optrand, SPX_N); - shake256_inc_absorb(&s_inc, m, mlen); - shake256_inc_finalize(&s_inc); - shake256_inc_squeeze(R, SPX_N, &s_inc); - shake256_inc_ctx_release(&s_inc); -} - -/** - * Computes the message hash using R, the public key, and the message. - * Outputs the message digest and the index of the leaf. The index is split in - * the tree index and the leaf index, for convenient copying to an address. - */ -void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx) { - (void)ctx; -#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) -#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) -#define SPX_LEAF_BITS SPX_TREE_HEIGHT -#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) -#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) - - unsigned char buf[SPX_DGST_BYTES]; - unsigned char *bufp = buf; - shake256incctx s_inc; - - shake256_inc_init(&s_inc); - shake256_inc_absorb(&s_inc, R, SPX_N); - shake256_inc_absorb(&s_inc, pk, SPX_PK_BYTES); - shake256_inc_absorb(&s_inc, m, mlen); - shake256_inc_finalize(&s_inc); - shake256_inc_squeeze(buf, SPX_DGST_BYTES, &s_inc); - shake256_inc_ctx_release(&s_inc); - - memcpy(digest, bufp, SPX_FORS_MSG_BYTES); - bufp += SPX_FORS_MSG_BYTES; - - - *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); - *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); - bufp += SPX_TREE_BYTES; - - *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); - *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/merkle.c b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/merkle.c deleted file mode 100644 index 0c1479fd93..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/merkle.c +++ /dev/null @@ -1,59 +0,0 @@ -#include -#include - -#include "address.h" -#include "merkle.h" -#include "params.h" -#include "utils.h" -#include "utilsx1.h" -#include "wots.h" -#include "wotsx1.h" - -/* - * This generates a Merkle signature (WOTS signature followed by the Merkle - * authentication path). This is in this file because most of the complexity - * is involved with the WOTS signature; the Merkle authentication path logic - * is mostly hidden in treehashx4 - */ -void merkle_sign(uint8_t *sig, unsigned char *root, - const spx_ctx *ctx, - uint32_t wots_addr[8], uint32_t tree_addr[8], - uint32_t idx_leaf) { - unsigned char *auth_path = sig + SPX_WOTS_BYTES; - struct leaf_info_x1 info = { 0 }; - unsigned steps[ SPX_WOTS_LEN ]; - - info.wots_sig = sig; - chain_lengths(steps, root); - info.wots_steps = steps; - - set_type(&tree_addr[0], SPX_ADDR_TYPE_HASHTREE); - set_type(&info.pk_addr[0], SPX_ADDR_TYPE_WOTSPK); - copy_subtree_addr(&info.leaf_addr[0], wots_addr); - copy_subtree_addr(&info.pk_addr[0], wots_addr); - - info.wots_sign_leaf = idx_leaf; - - treehashx1(root, auth_path, ctx, - idx_leaf, 0, - SPX_TREE_HEIGHT, - wots_gen_leafx1, - tree_addr, &info); -} - -/* Compute root node of the top-most subtree. */ -void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { - /* We do not need the auth path in key generation, but it simplifies the - code to have just one treehash routine that computes both root and path - in one function. */ - unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; - uint32_t top_tree_addr[8] = {0}; - uint32_t wots_addr[8] = {0}; - - set_layer_addr(top_tree_addr, SPX_D - 1); - set_layer_addr(wots_addr, SPX_D - 1); - - merkle_sign(auth_path, root, ctx, - wots_addr, top_tree_addr, - (uint32_t)~0 /* ~0 means "don't bother generating an auth path */ ); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/merkle.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/merkle.h deleted file mode 100644 index 769cf2e970..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/merkle.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef MERKLE_H_ -#define MERKLE_H_ - -#include - -#include "context.h" -#include "params.h" - -/* Generate a Merkle signature (WOTS signature followed by the Merkle */ -/* authentication path) */ -#define merkle_sign SPX_NAMESPACE(merkle_sign) -void merkle_sign(uint8_t *sig, unsigned char *root, - const spx_ctx *ctx, - uint32_t wots_addr[8], uint32_t tree_addr[8], - uint32_t idx_leaf); - -/* Compute the root node of the top-most subtree. */ -#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) -void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); - -#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/nistapi.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/nistapi.h deleted file mode 100644 index 3cb71afad4..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/nistapi.h +++ /dev/null @@ -1,87 +0,0 @@ -#ifndef SPX_API_H -#define SPX_API_H - -#include -#include - -#include "params.h" - -#define CRYPTO_ALGNAME "SPHINCS+" - -#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES -#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES -#define CRYPTO_BYTES SPX_BYTES -#define CRYPTO_SEEDBYTES (3*SPX_N) - -/* - * Returns the length of a secret key, in bytes - */ -#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) -size_t crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) -size_t crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) -size_t crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) -size_t crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) -int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) -int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) -int crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) -int crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -#define crypto_sign SPX_NAMESPACE(crypto_sign) -int crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) -int crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/params.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/params.h deleted file mode 100644 index afa749e65a..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/params.h +++ /dev/null @@ -1,56 +0,0 @@ -#ifndef SPX_PARAMS_H -#define SPX_PARAMS_H - -#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSSHAKE256FROBUST_CLEAN_##s - -/* Hash output length in bytes. */ -#define SPX_N 32 -/* Height of the hypertree. */ -#define SPX_FULL_HEIGHT 68 -/* Number of subtree layer. */ -#define SPX_D 17 -/* FORS tree dimensions. */ -#define SPX_FORS_HEIGHT 9 -#define SPX_FORS_TREES 35 -/* Winternitz parameter, */ -#define SPX_WOTS_W 16 - -/* The hash function is defined by linking a different hash.c file, as opposed - to setting a #define constant. */ - -/* For clarity */ -#define SPX_ADDR_BYTES 32 - -/* WOTS parameters. */ -#define SPX_WOTS_LOGW 4 - -#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) - -/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#define SPX_WOTS_LEN2 3 - -#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) -#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) -#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES - -/* Subtree size. */ -#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) - -//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT -// #error SPX_D should always divide SPX_FULL_HEIGHT -//#endif - -/* FORS parameters. */ -#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) -#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) -#define SPX_FORS_PK_BYTES SPX_N - -/* Resulting SPX sizes. */ -#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ - SPX_FULL_HEIGHT * SPX_N) -#define SPX_PK_BYTES (2 * SPX_N) -#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) - -#include "shake_offsets.h" - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/shake_offsets.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/shake_offsets.h deleted file mode 100644 index 6b28d95d91..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/shake_offsets.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef SHAKE_OFFSETS_H_ -#define SHAKE_OFFSETS_H_ - -/* - * Offsets of various fields in the address structure when we use SHAKE as - * the Sphincs+ hash function - */ - -#define SPX_OFFSET_LAYER 3 /* The byte used to specify the Merkle tree layer */ -#define SPX_OFFSET_TREE 8 /* The start of the 8 byte field used to specify the tree */ -#define SPX_OFFSET_TYPE 19 /* The byte used to specify the hash type (reason) */ -#define SPX_OFFSET_KP_ADDR2 22 /* The high byte used to specify the key pair (which one-time signature) */ -#define SPX_OFFSET_KP_ADDR1 23 /* The low byte used to specify the key pair */ -#define SPX_OFFSET_CHAIN_ADDR 27 /* The byte used to specify the chain address (which Winternitz chain) */ -#define SPX_OFFSET_HASH_ADDR 31 /* The byte used to specify the hash address (where in the Winternitz chain) */ -#define SPX_OFFSET_TREE_HGT 27 /* The byte used to specify the height of this node in the FORS or Merkle tree */ -#define SPX_OFFSET_TREE_INDEX 28 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ - -#define SPX_SHAKE 1 - -#endif /* SHAKE_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/sign.c b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/sign.c deleted file mode 100644 index 9d0c7d1b22..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/sign.c +++ /dev/null @@ -1,286 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "context.h" -#include "fors.h" -#include "hash.h" -#include "merkle.h" -#include "nistapi.h" -#include "params.h" -#include "randombytes.h" -#include "thash.h" -#include "utils.h" -#include "wots.h" - -/* - * Returns the length of a secret key, in bytes - */ -size_t crypto_sign_secretkeybytes(void) { - return CRYPTO_SECRETKEYBYTES; -} - -/* - * Returns the length of a public key, in bytes - */ -size_t crypto_sign_publickeybytes(void) { - return CRYPTO_PUBLICKEYBYTES; -} - -/* - * Returns the length of a signature, in bytes - */ -size_t crypto_sign_bytes(void) { - return CRYPTO_BYTES; -} - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t crypto_sign_seedbytes(void) { - return CRYPTO_SEEDBYTES; -} - -/* - * Generates an SPX key pair given a seed of length - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed) { - spx_ctx ctx; - - /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ - memcpy(sk, seed, CRYPTO_SEEDBYTES); - - memcpy(pk, sk + 2 * SPX_N, SPX_N); - - memcpy(ctx.pub_seed, pk, SPX_N); - memcpy(ctx.sk_seed, sk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - /* Compute root node of the top-most subtree. */ - merkle_gen_root(sk + 3 * SPX_N, &ctx); - - // cleanup - free_hash_function(&ctx); - - memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); - - return 0; -} - -/* - * Generates an SPX key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { - uint8_t seed[CRYPTO_SEEDBYTES]; - randombytes(seed, CRYPTO_SEEDBYTES); - crypto_sign_seed_keypair(pk, sk, seed); - - return 0; -} - -/** - * Returns an array containing a detached signature. - */ -int crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - spx_ctx ctx; - - const uint8_t *sk_prf = sk + SPX_N; - const uint8_t *pk = sk + 2 * SPX_N; - - uint8_t optrand[SPX_N]; - uint8_t mhash[SPX_FORS_MSG_BYTES]; - uint8_t root[SPX_N]; - uint32_t i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - - memcpy(ctx.sk_seed, sk, SPX_N); - memcpy(ctx.pub_seed, pk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - set_type(wots_addr, SPX_ADDR_TYPE_WOTS); - set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); - - /* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ - randombytes(optrand, SPX_N); - /* Compute the digest randomization value. */ - gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); - - /* Derive the message digest and leaf index from R, PK and M. */ - hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); - sig += SPX_N; - - set_tree_addr(wots_addr, tree); - set_keypair_addr(wots_addr, idx_leaf); - - /* Sign the message hash using FORS. */ - fors_sign(sig, root, mhash, &ctx, wots_addr); - sig += SPX_FORS_BYTES; - - for (i = 0; i < SPX_D; i++) { - set_layer_addr(tree_addr, i); - set_tree_addr(tree_addr, tree); - - copy_subtree_addr(wots_addr, tree_addr); - set_keypair_addr(wots_addr, idx_leaf); - - merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); - sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); - tree = tree >> SPX_TREE_HEIGHT; - } - - free_hash_function(&ctx); - - *siglen = SPX_BYTES; - - return 0; -} - -/** - * Verifies a detached signature and message under a given public key. - */ -int crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk) { - spx_ctx ctx; - const uint8_t *pub_root = pk + SPX_N; - uint8_t mhash[SPX_FORS_MSG_BYTES]; - uint8_t wots_pk[SPX_WOTS_BYTES]; - uint8_t root[SPX_N]; - uint8_t leaf[SPX_N]; - unsigned int i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - if (siglen != SPX_BYTES) { - return -1; - } - - memcpy(ctx.pub_seed, pk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - set_type(wots_addr, SPX_ADDR_TYPE_WOTS); - set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); - set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); - - /* Derive the message digest and leaf index from R || PK || M. */ - /* The additional SPX_N is a result of the hash domain separator. */ - hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); - sig += SPX_N; - - /* Layer correctly defaults to 0, so no need to set_layer_addr */ - set_tree_addr(wots_addr, tree); - set_keypair_addr(wots_addr, idx_leaf); - - fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); - sig += SPX_FORS_BYTES; - - /* For each subtree.. */ - for (i = 0; i < SPX_D; i++) { - set_layer_addr(tree_addr, i); - set_tree_addr(tree_addr, tree); - - copy_subtree_addr(wots_addr, tree_addr); - set_keypair_addr(wots_addr, idx_leaf); - - copy_keypair_addr(wots_pk_addr, wots_addr); - - /* The WOTS public key is only correct if the signature was correct. */ - /* Initially, root is the FORS pk, but on subsequent iterations it is - the root of the subtree below the currently processed subtree. */ - wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); - sig += SPX_WOTS_BYTES; - - /* Compute the leaf node using the WOTS public key. */ - thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); - - /* Compute the root node of this subtree. */ - compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, - &ctx, tree_addr); - sig += SPX_TREE_HEIGHT * SPX_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); - tree = tree >> SPX_TREE_HEIGHT; - } - - // cleanup - free_hash_function(&ctx); - - /* Check if the root node equals the root node in the public key. */ - if (memcmp(root, pub_root, SPX_N) != 0) { - return -1; - } - - return 0; -} - - -/** - * Returns an array containing the signature followed by the message. - */ -int crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk) { - size_t siglen; - - crypto_sign_signature(sm, &siglen, m, mlen, sk); - - memmove(sm + SPX_BYTES, m, mlen); - *smlen = siglen + mlen; - - return 0; -} - -/** - * Verifies a given signature-message pair under a given public key. - */ -int crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk) { - /* The API caller does not necessarily know what size a signature should be - but SPHINCS+ signatures are always exactly SPX_BYTES. */ - if (smlen < SPX_BYTES) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - *mlen = smlen - SPX_BYTES; - - if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - /* If verification was successful, move the message to the right place. */ - memmove(m, sm + SPX_BYTES, *mlen); - - return 0; -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/thash.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/thash.h deleted file mode 100644 index 8687ccfb4d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/thash.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef SPX_THASH_H -#define SPX_THASH_H - -#include "context.h" -#include "params.h" - -#include - -#define thash SPX_NAMESPACE(thash) -void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/thash_shake_robust.c b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/thash_shake_robust.c deleted file mode 100644 index 696d53c5cc..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/thash_shake_robust.c +++ /dev/null @@ -1,31 +0,0 @@ -#include -#include - -#include "thash.h" - -#include "address.h" -#include "params.h" -#include "utils.h" - -#include "fips202.h" - -/** - * Takes an array of inblocks concatenated arrays of SPX_N bytes. - */ -void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]) { - PQCLEAN_VLA(uint8_t, buf, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); - PQCLEAN_VLA(uint8_t, bitmask, inblocks * SPX_N); - unsigned int i; - - memcpy(buf, ctx->pub_seed, SPX_N); - memcpy(buf + SPX_N, addr, SPX_ADDR_BYTES); - - shake256(bitmask, inblocks * SPX_N, buf, SPX_N + SPX_ADDR_BYTES); - - for (i = 0; i < inblocks * SPX_N; i++) { - buf[SPX_N + SPX_ADDR_BYTES + i] = in[i] ^ bitmask[i]; - } - - shake256(out, SPX_N, buf, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/utils.c b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/utils.c deleted file mode 100644 index 177b541fb9..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/utils.c +++ /dev/null @@ -1,148 +0,0 @@ -#include - -#include "utils.h" - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "thash.h" - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void ull_to_bytes(unsigned char *out, unsigned int outlen, - unsigned long long in) { - int i; - - /* Iterate over out in decreasing order, for big-endianness. */ - for (i = (signed int)outlen - 1; i >= 0; i--) { - out[i] = in & 0xff; - in = in >> 8; - } -} - -void u32_to_bytes(unsigned char *out, uint32_t in) { - out[0] = (unsigned char)(in >> 24); - out[1] = (unsigned char)(in >> 16); - out[2] = (unsigned char)(in >> 8); - out[3] = (unsigned char)in; -} - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { - unsigned long long retval = 0; - unsigned int i; - - for (i = 0; i < inlen; i++) { - retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); - } - return retval; -} - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void compute_root(unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const spx_ctx *ctx, uint32_t addr[8]) { - uint32_t i; - unsigned char buffer[2 * SPX_N]; - - /* If leaf_idx is odd (last bit = 1), current path element is a right child - and auth_path has to go left. Otherwise it is the other way around. */ - if (leaf_idx & 1) { - memcpy(buffer + SPX_N, leaf, SPX_N); - memcpy(buffer, auth_path, SPX_N); - } else { - memcpy(buffer, leaf, SPX_N); - memcpy(buffer + SPX_N, auth_path, SPX_N); - } - auth_path += SPX_N; - - for (i = 0; i < tree_height - 1; i++) { - leaf_idx >>= 1; - idx_offset >>= 1; - /* Set the address of the node we're creating. */ - set_tree_height(addr, i + 1); - set_tree_index(addr, leaf_idx + idx_offset); - - /* Pick the right or left neighbor, depending on parity of the node. */ - if (leaf_idx & 1) { - thash(buffer + SPX_N, buffer, 2, ctx, addr); - memcpy(buffer, auth_path, SPX_N); - } else { - thash(buffer, buffer, 2, ctx, addr); - memcpy(buffer + SPX_N, auth_path, SPX_N); - } - auth_path += SPX_N; - } - - /* The last iteration is exceptional; we do not copy an auth_path node. */ - leaf_idx >>= 1; - idx_offset >>= 1; - set_tree_height(addr, tree_height); - set_tree_index(addr, leaf_idx + idx_offset); - thash(root, buffer, 2, ctx, addr); -} - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const spx_ctx * /* ctx */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), - uint32_t tree_addr[8]) { - PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); - PQCLEAN_VLA(unsigned int, heights, tree_height + 1); - unsigned int offset = 0; - uint32_t idx; - uint32_t tree_idx; - - for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { - /* Add the next leaf node to the stack. */ - gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); - offset++; - heights[offset - 1] = 0; - - /* If this is a node we need for the auth path.. */ - if ((leaf_idx ^ 0x1) == idx) { - memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); - } - - /* While the top-most nodes are of equal height.. */ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { - /* Compute index of the new node, in the next layer. */ - tree_idx = (idx >> (heights[offset - 1] + 1)); - - /* Set the address of the node we're creating. */ - set_tree_height(tree_addr, heights[offset - 1] + 1); - set_tree_index(tree_addr, - tree_idx + (idx_offset >> (heights[offset - 1] + 1))); - /* Hash the top-most nodes from the stack together. */ - thash(stack + (offset - 2)*SPX_N, - stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); - offset--; - /* Note that the top-most node is now one layer higher. */ - heights[offset - 1]++; - - /* If this is a node we need for the auth path.. */ - if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_path + heights[offset - 1]*SPX_N, - stack + (offset - 1)*SPX_N, SPX_N); - } - } - } - memcpy(root, stack, SPX_N); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/utils.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/utils.h deleted file mode 100644 index 64f5d5a53a..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/utils.h +++ /dev/null @@ -1,58 +0,0 @@ -#ifndef SPX_UTILS_H -#define SPX_UTILS_H - -#include - -#include "compat.h" -#include "context.h" -#include "params.h" - - -/* To support MSVC use alloca() instead of VLAs. See #20. */ - - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) -void ull_to_bytes(unsigned char *out, unsigned int outlen, - unsigned long long in); -#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) -void u32_to_bytes(unsigned char *out, uint32_t in); - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) -unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -#define compute_root SPX_NAMESPACE(compute_root) -void compute_root(unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const spx_ctx *ctx, uint32_t addr[8]); - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -#define treehash SPX_NAMESPACE(treehash) -void treehash(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const spx_ctx *ctx /* ctx */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), - uint32_t tree_addr[8]); - - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/utilsx1.c b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/utilsx1.c deleted file mode 100644 index fccb69b35d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/utilsx1.c +++ /dev/null @@ -1,100 +0,0 @@ -#include - -#include "utilsx1.h" - -#include "address.h" -#include "params.h" -#include "thash.h" -#include "utils.h" - -/* - * Generate the entire Merkle tree, computing the authentication path for - * leaf_idx, and the resulting root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) - * - * This expects tree_addr to be initialized to the addr structures for the - * Merkle tree nodes - * - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - * - * This works by using the standard Merkle tree building algorithm, - */ -void treehashx1(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, - uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* Where to write the leaves */, - const spx_ctx * /* ctx */, - uint32_t idx, void *info), - uint32_t tree_addr[8], - void *info) { - /* This is where we keep the intermediate nodes */ - PQCLEAN_VLA(uint8_t, stack, tree_height * SPX_N); - - uint32_t idx; - uint32_t max_idx = (uint32_t)((1 << tree_height) - 1); - for (idx = 0;; idx++) { - unsigned char current[2 * SPX_N]; /* Current logical node is at */ - /* index[SPX_N]. We do this to minimize the number of copies */ - /* needed during a thash */ - gen_leaf( ¤t[SPX_N], ctx, idx + idx_offset, - info ); - - /* Now combine the freshly generated right node with previously */ - /* generated left ones */ - uint32_t internal_idx_offset = idx_offset; - uint32_t internal_idx = idx; - uint32_t internal_leaf = leaf_idx; - uint32_t h; /* The height we are in the Merkle tree */ - for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { - - /* Check if we hit the top of the tree */ - if (h == tree_height) { - /* We hit the root; return it */ - memcpy( root, ¤t[SPX_N], SPX_N ); - return; - } - - /* - * Check if the node we have is a part of the - * authentication path; if it is, write it out - */ - if ((internal_idx ^ internal_leaf) == 0x01) { - memcpy( &auth_path[ h * SPX_N ], - ¤t[SPX_N], - SPX_N ); - } - - /* - * Check if we're at a left child; if so, stop going up the stack - * Exception: if we've reached the end of the tree, keep on going - * (so we combine the last 4 nodes into the one root node in two - * more iterations) - */ - if ((internal_idx & 1) == 0 && idx < max_idx) { - break; - } - - /* Ok, we're at a right node */ - /* Now combine the left and right logical nodes together */ - - /* Set the address of the node we're creating. */ - internal_idx_offset >>= 1; - set_tree_height(tree_addr, h + 1); - set_tree_index(tree_addr, internal_idx / 2 + internal_idx_offset ); - - unsigned char *left = &stack[h * SPX_N]; - memcpy( ¤t[0], left, SPX_N ); - thash( ¤t[1 * SPX_N], - ¤t[0 * SPX_N], - 2, ctx, tree_addr); - } - - /* We've hit a left child; save the current for when we get the */ - /* corresponding right right */ - memcpy( &stack[h * SPX_N], ¤t[SPX_N], SPX_N); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/utilsx1.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/utilsx1.h deleted file mode 100644 index e911d17d53..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/utilsx1.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef SPX_UTILSX4_H -#define SPX_UTILSX4_H - -#include - -#include "context.h" -#include "params.h" - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -#define treehashx1 SPX_NAMESPACE(treehashx1) -void treehashx1(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* Where to write the leaf */, - const spx_ctx * /* ctx */, - uint32_t addr_idx, void *info), - uint32_t tree_addrx4[8], void *info); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/wots.c b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/wots.c deleted file mode 100644 index 249717aaa8..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/wots.c +++ /dev/null @@ -1,108 +0,0 @@ -#include -#include - -#include "wots.h" -#include "wotsx1.h" - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "thash.h" -#include "utils.h" -#include "utilsx1.h" - -// TODO clarify address expectations, and make them more uniform. -// TODO i.e. do we expect types to be set already? -// TODO and do we expect modifications or copies? - -/** - * Computes the chaining function. - * out and in have to be n-byte arrays. - * - * Interprets in as start-th value of the chain. - * addr has to contain the address of the chain. - */ -static void gen_chain(unsigned char *out, const unsigned char *in, - unsigned int start, unsigned int steps, - const spx_ctx *ctx, uint32_t addr[8]) { - uint32_t i; - - /* Initialize out with the value at position 'start'. */ - memcpy(out, in, SPX_N); - - /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < SPX_WOTS_W; i++) { - set_hash_addr(addr, i); - thash(out, out, 1, ctx, addr); - } -} - -/** - * base_w algorithm as described in draft. - * Interprets an array of bytes as integers in base w. - * This only works when log_w is a divisor of 8. - */ -static void base_w(unsigned int *output, const int out_len, - const unsigned char *input) { - int in = 0; - int out = 0; - unsigned char total = 0; - int bits = 0; - int consumed; - - for (consumed = 0; consumed < out_len; consumed++) { - if (bits == 0) { - total = input[in]; - in++; - bits += 8; - } - bits -= SPX_WOTS_LOGW; - output[out] = (total >> bits) & (SPX_WOTS_W - 1); - out++; - } -} - -/* Computes the WOTS+ checksum over a message (in base_w). */ -static void wots_checksum(unsigned int *csum_base_w, - const unsigned int *msg_base_w) { - unsigned int csum = 0; - unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; - unsigned int i; - - /* Compute checksum. */ - for (i = 0; i < SPX_WOTS_LEN1; i++) { - csum += SPX_WOTS_W - 1 - msg_base_w[i]; - } - - /* Convert checksum to base_w. */ - /* Make sure expected empty zero bits are the least significant bits. */ - csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); - ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); - base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); -} - -/* Takes a message and derives the matching chain lengths. */ -void chain_lengths(unsigned int *lengths, const unsigned char *msg) { - base_w(lengths, SPX_WOTS_LEN1, msg); - wots_checksum(lengths + SPX_WOTS_LEN1, lengths); -} - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const spx_ctx *ctx, uint32_t addr[8]) { - unsigned int lengths[SPX_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < SPX_WOTS_LEN; i++) { - set_chain_addr(addr, i); - gen_chain(pk + i * SPX_N, sig + i * SPX_N, - lengths[i], SPX_WOTS_W - 1 - lengths[i], ctx, addr); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/wots.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/wots.h deleted file mode 100644 index 4e7692eeef..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/wots.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef SPX_WOTS_H -#define SPX_WOTS_H - -#include - -#include "context.h" -#include "params.h" - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) -void wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const spx_ctx *ctx, uint32_t addr[8]); - -/* - * Compute the chain lengths needed for a given message hash - */ -#define chain_lengths SPX_NAMESPACE(chain_lengths) -void chain_lengths(unsigned int *lengths, const unsigned char *msg); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/wotsx1.c b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/wotsx1.c deleted file mode 100644 index 3adec78dfb..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/wotsx1.c +++ /dev/null @@ -1,76 +0,0 @@ -#include -#include - -#include "wots.h" -#include "wotsx1.h" - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "thash.h" -#include "utils.h" - -/* - * This generates a WOTS public key - * It also generates the WOTS signature if leaf_info indicates - * that we're signing with this WOTS key - */ -void wots_gen_leafx1(unsigned char *dest, - const spx_ctx *ctx, - uint32_t leaf_idx, void *v_info) { - struct leaf_info_x1 *info = v_info; - uint32_t *leaf_addr = info->leaf_addr; - uint32_t *pk_addr = info->pk_addr; - unsigned int i, k; - unsigned char pk_buffer[ SPX_WOTS_BYTES ]; - unsigned char *buffer; - uint32_t wots_k_mask; - - if (leaf_idx == info->wots_sign_leaf) { - /* We're traversing the leaf that's signing; generate the WOTS */ - /* signature */ - wots_k_mask = 0; - } else { - /* Nope, we're just generating pk's; turn off the signature logic */ - wots_k_mask = (uint32_t)~0; - } - - set_keypair_addr( leaf_addr, leaf_idx ); - set_keypair_addr( pk_addr, leaf_idx ); - - for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { - uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k to */ - /* the step if we're generating a signature, ~0 if we're not */ - - /* Start with the secret seed */ - set_chain_addr(leaf_addr, i); - set_hash_addr(leaf_addr, 0); - set_type(leaf_addr, SPX_ADDR_TYPE_WOTSPRF); - - prf_addr(buffer, ctx, leaf_addr); - - set_type(leaf_addr, SPX_ADDR_TYPE_WOTS); - - /* Iterate down the WOTS chain */ - for (k = 0;; k++) { - /* Check if this is the value that needs to be saved as a */ - /* part of the WOTS signature */ - if (k == wots_k) { - memcpy( info->wots_sig + i * SPX_N, buffer, SPX_N ); - } - - /* Check if we hit the top of the chain */ - if (k == SPX_WOTS_W - 1) { - break; - } - - /* Iterate one step on the chain */ - set_hash_addr(leaf_addr, k); - - thash(buffer, buffer, 1, ctx, leaf_addr); - } - } - - /* Do the final thash to generate the public keys */ - thash(dest, pk_buffer, SPX_WOTS_LEN, ctx, pk_addr); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/wotsx1.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/wotsx1.h deleted file mode 100644 index e617929f96..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256f-robust_clean/wotsx1.h +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef WOTSX1_H_ -#define WOTSX1_H_ - -#include - -#include "context.h" -#include "params.h" - -/* - * This is here to provide an interface to the internal wots_gen_leafx1 - * routine. While this routine is not referenced in the package outside of - * wots.c, it is called from the stand-alone benchmark code to characterize - * the performance - */ -struct leaf_info_x1 { - unsigned char *wots_sig; - uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ - uint32_t *wots_steps; - uint32_t leaf_addr[8]; - uint32_t pk_addr[8]; -}; - -/* Macro to set the leaf_info to something 'benign', that is, it would */ -/* run with the same time as it does during the real signing process */ -/* Used only by the benchmark code */ -#define INITIALIZE_LEAF_INFO_X1(info, addr, step_buffer) { \ - (info).wots_sig = 0; \ - (info).wots_sign_leaf = ~0; \ - (info).wots_steps = step_buffer; \ - memcpy( &(info).leaf_addr[0], (addr), 32 ); \ - memcpy( &(info).pk_addr[0], (addr), 32 ); \ - } - -#define wots_gen_leafx1 SPX_NAMESPACE(wots_gen_leafx1) -void wots_gen_leafx1(unsigned char *dest, - const spx_ctx *ctx, - uint32_t leaf_idx, void *v_info); - -#endif /* WOTSX1_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/LICENSE b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/LICENSE deleted file mode 100644 index 670154e353..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/LICENSE +++ /dev/null @@ -1,116 +0,0 @@ -CC0 1.0 Universal - -Statement of Purpose - -The laws of most jurisdictions throughout the world automatically confer -exclusive Copyright and Related Rights (defined below) upon the creator and -subsequent owner(s) (each and all, an "owner") of an original work of -authorship and/or a database (each, a "Work"). - -Certain owners wish to permanently relinquish those rights to a Work for the -purpose of contributing to a commons of creative, cultural and scientific -works ("Commons") that the public can reliably and without fear of later -claims of infringement build upon, modify, incorporate in other works, reuse -and redistribute as freely as possible in any form whatsoever and for any -purposes, including without limitation commercial purposes. These owners may -contribute to the Commons to promote the ideal of a free culture and the -further production of creative, cultural and scientific works, or to gain -reputation or greater distribution for their Work in part through the use and -efforts of others. - -For these and/or other purposes and motivations, and without any expectation -of additional consideration or compensation, the person associating CC0 with a -Work (the "Affirmer"), to the extent that he or she is an owner of Copyright -and Related Rights in the Work, voluntarily elects to apply CC0 to the Work -and publicly distribute the Work under its terms, with knowledge of his or her -Copyright and Related Rights in the Work and the meaning and intended legal -effect of CC0 on those rights. - -1. Copyright and Related Rights. A Work made available under CC0 may be -protected by copyright and related or neighboring rights ("Copyright and -Related Rights"). Copyright and Related Rights include, but are not limited -to, the following: - - i. the right to reproduce, adapt, distribute, perform, display, communicate, - and translate a Work; - - ii. moral rights retained by the original author(s) and/or performer(s); - - iii. publicity and privacy rights pertaining to a person's image or likeness - depicted in a Work; - - iv. rights protecting against unfair competition in regards to a Work, - subject to the limitations in paragraph 4(a), below; - - v. rights protecting the extraction, dissemination, use and reuse of data in - a Work; - - vi. database rights (such as those arising under Directive 96/9/EC of the - European Parliament and of the Council of 11 March 1996 on the legal - protection of databases, and under any national implementation thereof, - including any amended or successor version of such directive); and - - vii. other similar, equivalent or corresponding rights throughout the world - based on applicable law or treaty, and any national implementations thereof. - -2. Waiver. To the greatest extent permitted by, but not in contravention of, -applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and -unconditionally waives, abandons, and surrenders all of Affirmer's Copyright -and Related Rights and associated claims and causes of action, whether now -known or unknown (including existing as well as future claims and causes of -action), in the Work (i) in all territories worldwide, (ii) for the maximum -duration provided by applicable law or treaty (including future time -extensions), (iii) in any current or future medium and for any number of -copies, and (iv) for any purpose whatsoever, including without limitation -commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes -the Waiver for the benefit of each member of the public at large and to the -detriment of Affirmer's heirs and successors, fully intending that such Waiver -shall not be subject to revocation, rescission, cancellation, termination, or -any other legal or equitable action to disrupt the quiet enjoyment of the Work -by the public as contemplated by Affirmer's express Statement of Purpose. - -3. Public License Fallback. Should any part of the Waiver for any reason be -judged legally invalid or ineffective under applicable law, then the Waiver -shall be preserved to the maximum extent permitted taking into account -Affirmer's express Statement of Purpose. In addition, to the extent the Waiver -is so judged Affirmer hereby grants to each affected person a royalty-free, -non transferable, non sublicensable, non exclusive, irrevocable and -unconditional license to exercise Affirmer's Copyright and Related Rights in -the Work (i) in all territories worldwide, (ii) for the maximum duration -provided by applicable law or treaty (including future time extensions), (iii) -in any current or future medium and for any number of copies, and (iv) for any -purpose whatsoever, including without limitation commercial, advertising or -promotional purposes (the "License"). The License shall be deemed effective as -of the date CC0 was applied by Affirmer to the Work. Should any part of the -License for any reason be judged legally invalid or ineffective under -applicable law, such partial invalidity or ineffectiveness shall not -invalidate the remainder of the License, and in such case Affirmer hereby -affirms that he or she will not (i) exercise any of his or her remaining -Copyright and Related Rights in the Work or (ii) assert any associated claims -and causes of action with respect to the Work, in either case contrary to -Affirmer's express Statement of Purpose. - -4. Limitations and Disclaimers. - - a. No trademark or patent rights held by Affirmer are waived, abandoned, - surrendered, licensed or otherwise affected by this document. - - b. Affirmer offers the Work as-is and makes no representations or warranties - of any kind concerning the Work, express, implied, statutory or otherwise, - including without limitation warranties of title, merchantability, fitness - for a particular purpose, non infringement, or the absence of latent or - other defects, accuracy, or the present or absence of errors, whether or not - discoverable, all to the greatest extent permissible under applicable law. - - c. Affirmer disclaims responsibility for clearing rights of other persons - that may apply to the Work or any use thereof, including without limitation - any person's Copyright and Related Rights in the Work. Further, Affirmer - disclaims responsibility for obtaining any necessary consents, permissions - or other rights required for any use of the Work. - - d. Affirmer understands and acknowledges that Creative Commons is not a - party to this document and has no duty or obligation with respect to this - CC0 or use of the Work. - -For more information, please see - diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/address.c b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/address.c deleted file mode 100644 index b956e9cb29..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/address.c +++ /dev/null @@ -1,91 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "utils.h" - -/* - * Specify which level of Merkle tree (the "layer") we're working on - */ -void set_layer_addr(uint32_t addr[8], uint32_t layer) { - ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; -} - -/* - * Specify which Merkle tree within the level (the "tree address") we're working on - */ -void set_tree_addr(uint32_t addr[8], uint64_t tree) { - ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); -} - -/* - * Specify the reason we'll use this address structure for, that is, what - * hash will we compute with it. This is used so that unrelated types of - * hashes don't accidentally get the same address structure. The type will be - * one of the SPX_ADDR_TYPE constants - */ -void set_type(uint32_t addr[8], uint32_t type) { - ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; -} - -/* - * Copy the layer and tree fields of the address structure. This is used - * when we're doing multiple types of hashes within the same Merkle tree - */ -void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { - memcpy( out, in, SPX_OFFSET_TREE + 8 ); -} - -/* These functions are used for OTS addresses. */ - -/* - * Specify which Merkle leaf we're working on; that is, which OTS keypair - * we're talking about. - */ -void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { - ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; -} - -/* - * Copy the layer, tree and keypair fields of the address structure. This is - * used when we're doing multiple things within the same OTS keypair - */ -void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { - memcpy( out, in, SPX_OFFSET_TREE + 8 ); - ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; -} - -/* - * Specify which Merkle chain within the OTS we're working with - * (the chain address) - */ -void set_chain_addr(uint32_t addr[8], uint32_t chain) { - ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; -} - -/* - * Specify where in the Merkle chain we are -* (the hash address) - */ -void set_hash_addr(uint32_t addr[8], uint32_t hash) { - ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; -} - -/* These functions are used for all hash tree addresses (including FORS). */ - -/* - * Specify the height of the node in the Merkle/FORS tree we are in - * (the tree height) - */ -void set_tree_height(uint32_t addr[8], uint32_t tree_height) { - ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; -} - -/* - * Specify the distance from the left edge of the node in the Merkle/FORS tree - * (the tree index) - */ -void set_tree_index(uint32_t addr[8], uint32_t tree_index) { - u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/address.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/address.h deleted file mode 100644 index 24a84eb40c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/address.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef SPX_ADDRESS_H -#define SPX_ADDRESS_H - -#include - -#include "params.h" - -/* The hash types that are passed to set_type */ -#define SPX_ADDR_TYPE_WOTS 0 -#define SPX_ADDR_TYPE_WOTSPK 1 -#define SPX_ADDR_TYPE_HASHTREE 2 -#define SPX_ADDR_TYPE_FORSTREE 3 -#define SPX_ADDR_TYPE_FORSPK 4 -#define SPX_ADDR_TYPE_WOTSPRF 5 -#define SPX_ADDR_TYPE_FORSPRF 6 - -#define set_layer_addr SPX_NAMESPACE(set_layer_addr) -void set_layer_addr(uint32_t addr[8], uint32_t layer); - -#define set_tree_addr SPX_NAMESPACE(set_tree_addr) -void set_tree_addr(uint32_t addr[8], uint64_t tree); - -#define set_type SPX_NAMESPACE(set_type) -void set_type(uint32_t addr[8], uint32_t type); - -/* Copies the layer and tree part of one address into the other */ -#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) -void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for WOTS and FORS addresses. */ - -#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) -void set_keypair_addr(uint32_t addr[8], uint32_t keypair); - -#define set_chain_addr SPX_NAMESPACE(set_chain_addr) -void set_chain_addr(uint32_t addr[8], uint32_t chain); - -#define set_hash_addr SPX_NAMESPACE(set_hash_addr) -void set_hash_addr(uint32_t addr[8], uint32_t hash); - -#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) -void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for all hash tree addresses (including FORS). */ - -#define set_tree_height SPX_NAMESPACE(set_tree_height) -void set_tree_height(uint32_t addr[8], uint32_t tree_height); - -#define set_tree_index SPX_NAMESPACE(set_tree_index) -void set_tree_index(uint32_t addr[8], uint32_t tree_index); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/api.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/api.h deleted file mode 100644 index 9916e03a90..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/api.h +++ /dev/null @@ -1,77 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256SROBUST_AARCH64_API_H -#define PQCLEAN_SPHINCSSHAKE256SROBUST_AARCH64_API_H - -#include -#include - -#define PQCLEAN_SPHINCSSHAKE256SROBUST_AARCH64_CRYPTO_ALGNAME "SPHINCS+-shake-256s-robust" - -#define PQCLEAN_SPHINCSSHAKE256SROBUST_AARCH64_CRYPTO_SECRETKEYBYTES 128 -#define PQCLEAN_SPHINCSSHAKE256SROBUST_AARCH64_CRYPTO_PUBLICKEYBYTES 64 -#define PQCLEAN_SPHINCSSHAKE256SROBUST_AARCH64_CRYPTO_BYTES 29792 - -#define PQCLEAN_SPHINCSSHAKE256SROBUST_AARCH64_CRYPTO_SEEDBYTES 96 - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256SROBUST_AARCH64_crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256SROBUST_AARCH64_crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256SROBUST_AARCH64_crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256SROBUST_AARCH64_crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHAKE256SROBUST_AARCH64_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHAKE256SROBUST_AARCH64_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSSHAKE256SROBUST_AARCH64_crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE256SROBUST_AARCH64_crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, - const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSSHAKE256SROBUST_AARCH64_crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE256SROBUST_AARCH64_crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk); -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/context.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/context.h deleted file mode 100644 index 6e0a33f3b7..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/context.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef SPX_CONTEXT_H -#define SPX_CONTEXT_H - -#include - -#include "params.h" - -typedef struct { - uint8_t pub_seed[SPX_N]; - uint8_t sk_seed[SPX_N]; -} spx_ctx; - -#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) -void initialize_hash_function(spx_ctx *ctx); - -#define free_hash_function SPX_NAMESPACE(free_hash_function) -void free_hash_function(spx_ctx *ctx); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/context_shake.c b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/context_shake.c deleted file mode 100644 index 9614a103d3..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/context_shake.c +++ /dev/null @@ -1,12 +0,0 @@ -#include "context.h" - -/* For SHAKE256, there is no immediate reason to initialize at the start, - so this function is an empty operation. */ -void initialize_hash_function(spx_ctx *ctx) { - (void)ctx; /* Suppress an 'unused parameter' warning. */ -} - -// in case the hash function api is heap-based. -void free_hash_function(spx_ctx *ctx) { - (void)ctx; -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/f1600x2.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/f1600x2.h deleted file mode 100644 index 70d1af9f14..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/f1600x2.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef SPX_F1600X2_H -#define SPX_F1600X2_H - -#include - -extern uint64_t f1600_RC[24]; -extern void _f1600x2(uint64_t *a, uint64_t *rc); - -#define f1600x2(s) do {_f1600x2((s), f1600_RC);} while(0) - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/f1600x2.s b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/f1600x2.s deleted file mode 100644 index 640ed791ed..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/f1600x2.s +++ /dev/null @@ -1,143 +0,0 @@ -# From https://github.com/bwesterb/armed-keccak - -.macro round - # Execute theta, but without xoring into the state yet. - # Compute parities p[i] = a[i] ^ a[5+i] ^ ... ^ a[20+i]. - eor3.16b v25, v0, v5, v10 - eor3.16b v26, v1, v6, v11 - eor3.16b v27, v2, v7, v12 - eor3.16b v28, v3, v8, v13 - eor3.16b v29, v4, v9, v14 - - eor3.16b v25, v25, v15, v20 - eor3.16b v26, v26, v16, v21 - eor3.16b v27, v27, v17, v22 - eor3.16b v28, v28, v18, v23 - eor3.16b v29, v29, v19, v24 - - # d[0] = rotl(p[1], 1) ^ p[4] - rax1.2d v30, v29, v26 - # d[3] = rotl(p[4], 1) ^ p[2] - rax1.2d v29, v27, v29 - # d[1] = rotl(p[2], 1) ^ p[0] - rax1.2d v27, v25, v27 - # d[4] = rotl(p[0], 1) ^ p[3] - rax1.2d v25, v28, v25 - # d[2] = rotl(p[3], 1) ^ p[1] - rax1.2d v28, v26, v28 - - # Xor parities from step theta into the state at the same time - # as executing rho and pi. - eor.16b v0, v0, v30 - mov.16b v31, v1 - xar.2d v1, v6, v27, 20 - xar.2d v6, v9, v25, 44 - xar.2d v9, v22, v28, 3 - xar.2d v22, v14, v25, 25 - xar.2d v14, v20, v30, 46 - xar.2d v20, v2, v28, 2 - xar.2d v2, v12, v28, 21 - xar.2d v12, v13, v29, 39 - xar.2d v13, v19, v25, 56 - xar.2d v19, v23, v29, 8 - xar.2d v23, v15, v30, 23 - xar.2d v15, v4, v25, 37 - xar.2d v4, v24, v25, 50 - xar.2d v24, v21, v27, 62 - xar.2d v21, v8, v29, 9 - xar.2d v8, v16, v27, 19 - xar.2d v16, v5, v30, 28 - xar.2d v5, v3, v29, 36 - xar.2d v3, v18, v29, 43 - xar.2d v18, v17, v28, 49 - xar.2d v17, v11, v27, 54 - xar.2d v11, v7, v28, 58 - xar.2d v7, v10, v30, 61 - xar.2d v10, v31, v27, 63 - - # Chi - bcax.16b v25, v0, v2, v1 - bcax.16b v26, v1, v3, v2 - bcax.16b v2, v2, v4, v3 - bcax.16b v3, v3, v0, v4 - bcax.16b v4, v4, v1, v0 - mov.16b v0, v25 - mov.16b v1, v26 - - bcax.16b v25, v5, v7, v6 - bcax.16b v26, v6, v8, v7 - bcax.16b v7, v7, v9, v8 - bcax.16b v8, v8, v5, v9 - bcax.16b v9, v9, v6, v5 - mov.16b v5, v25 - mov.16b v6, v26 - - bcax.16b v25, v10, v12, v11 - bcax.16b v26, v11, v13, v12 - bcax.16b v12, v12, v14, v13 - bcax.16b v13, v13, v10, v14 - bcax.16b v14, v14, v11, v10 - mov.16b v10, v25 - mov.16b v11, v26 - - bcax.16b v25, v15, v17, v16 - bcax.16b v26, v16, v18, v17 - bcax.16b v17, v17, v19, v18 - bcax.16b v18, v18, v15, v19 - bcax.16b v19, v19, v16, v15 - mov.16b v15, v25 - mov.16b v16, v26 - - bcax.16b v25, v20, v22, v21 - bcax.16b v26, v21, v23, v22 - bcax.16b v22, v22, v24, v23 - bcax.16b v23, v23, v20, v24 - bcax.16b v24, v24, v21, v20 - mov.16b v20, v25 - mov.16b v21, v26 - - # iota - ld1r {v25.2d}, [x1], #8 - eor.16b v0, v0, v25 -.endm - -.align 4 -.global __f1600x2 -__f1600x2: - stp d8, d9, [sp,#-16]! - stp d10, d11, [sp,#-16]! - stp d12, d13, [sp,#-16]! - stp d14, d15, [sp,#-16]! - - mov x2, x0 - mov x3, #24 - - ld1.2d {v0, v1, v2, v3}, [x0], #64 - ld1.2d {v4, v5, v6, v7}, [x0], #64 - ld1.2d {v8, v9, v10, v11}, [x0], #64 - ld1.2d {v12, v13, v14, v15}, [x0], #64 - ld1.2d {v16, v17, v18, v19}, [x0], #64 - ld1.2d {v20, v21, v22, v23}, [x0], #64 - ld1.2d {v24}, [x0] - -loop: - round - - subs x3, x3, #1 - cbnz x3, loop - - mov x0, x2 - st1.2d {v0, v1, v2, v3}, [x0], #64 - st1.2d {v4, v5, v6, v7}, [x0], #64 - st1.2d {v8, v9, v10, v11}, [x0], #64 - st1.2d {v12, v13, v14, v15}, [x0], #64 - st1.2d {v16, v17, v18, v19}, [x0], #64 - st1.2d {v20, v21, v22, v23}, [x0], #64 - st1.2d {v24}, [x0] - - ldp d14, d15, [sp], #16 - ldp d12, d13, [sp], #16 - ldp d10, d11, [sp], #16 - ldp d8, d9, [sp], #16 - - ret lr diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/f1600x2_const.c b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/f1600x2_const.c deleted file mode 100644 index e49c0ba149..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/f1600x2_const.c +++ /dev/null @@ -1,30 +0,0 @@ -#include "f1600x2.h" - -uint64_t f1600_RC[24] = { - 0x0000000000000001, - 0x0000000000008082, - 0x800000000000808A, - 0x8000000080008000, - 0x000000000000808B, - 0x0000000080000001, - 0x8000000080008081, - 0x8000000000008009, - 0x000000000000008A, - 0x0000000000000088, - 0x0000000080008009, - 0x000000008000000A, - 0x000000008000808B, - 0x800000000000008B, - 0x8000000000008089, - 0x8000000000008003, - 0x8000000000008002, - 0x8000000000000080, - 0x000000000000800A, - 0x800000008000000A, - 0x8000000080008081, - 0x8000000000008080, - 0x0000000080000001, - 0x8000000080008008, -}; - - diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/fips202x2.c b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/fips202x2.c deleted file mode 100644 index 4718c343bc..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/fips202x2.c +++ /dev/null @@ -1,148 +0,0 @@ -#include -#include - -#include "fips202x2.h" -#include "f1600x2.h" -#include "fips202.h" - -uint64_t load64(const unsigned char *x) { - unsigned long long r = 0, i; - - for (i = 0; i < 8; ++i) { - r |= (unsigned long long)x[i] << 8 * i; - } - return r; -} - -void store64(uint8_t *x, uint64_t u) { - unsigned int i; - - for (i = 0; i < 8; ++i) { - x[i] = (uint8_t)u; - u >>= 8; - } -} - -static void keccak_absorb2x(uint64_t *s, - unsigned int r, - const unsigned char *m0, - const unsigned char *m1, - unsigned long long int mlen, - unsigned char p) { - unsigned long long i; - unsigned char t0[200]; - unsigned char t1[200]; - - while (mlen >= r) { - for (i = 0; i < r / 8; ++i) { - s[2 * i + 0] ^= load64(m0 + 8 * i); - s[2 * i + 1] ^= load64(m1 + 8 * i); - } - - f1600x2(s); - mlen -= r; - m0 += r; - m1 += r; - } - - for (i = 0; i < r; ++i) { - t0[i] = 0; - t1[i] = 0; - } - for (i = 0; i < mlen; ++i) { - t0[i] = m0[i]; - t1[i] = m1[i]; - } - - t0[i] = p; - t1[i] = p; - - t0[r - 1] |= 128; - t1[r - 1] |= 128; - - for (i = 0; i < r / 8; ++i) { - s[2 * i + 0] ^= load64(t0 + 8 * i); - s[2 * i + 1] ^= load64(t1 + 8 * i); - } -} - - -static void keccak_squeezeblocks2x(unsigned char *h0, - unsigned char *h1, - unsigned long long int nblocks, - uint64_t *s, - unsigned int r) { - unsigned int i; - - while (nblocks > 0) { - f1600x2(s); - for (i = 0; i < (r >> 3); i++) { - store64(h0 + 8 * i, s[2 * i + 0]); - store64(h1 + 8 * i, s[2 * i + 1]); - } - h0 += r; - h1 += r; - nblocks--; - } -} - - - -void shake128x2(unsigned char *out0, - unsigned char *out1, - unsigned long long outlen, - unsigned char *in0, - unsigned char *in1, - unsigned long long inlen) { - uint64_t s[50] = {0}; - unsigned char t0[SHAKE128_RATE]; - unsigned char t1[SHAKE128_RATE]; - unsigned int i; - - /* absorb 4 message of identical length in parallel */ - keccak_absorb2x(s, SHAKE128_RATE, in0, in1, inlen, 0x1F); - - /* Squeeze output */ - keccak_squeezeblocks2x(out0, out1, outlen / SHAKE128_RATE, s, SHAKE128_RATE); - - out0 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; - out1 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; - - if (outlen % SHAKE128_RATE) { - keccak_squeezeblocks2x(t0, t1, 1, s, SHAKE128_RATE); - for (i = 0; i < outlen % SHAKE128_RATE; i++) { - out0[i] = t0[i]; - out1[i] = t1[i]; - } - } -} - - -void shake256x2(unsigned char *out0, - unsigned char *out1, - unsigned long long outlen, - unsigned char *in0, - unsigned char *in1, - unsigned long long inlen) { - uint64_t s[50] = {0}; - unsigned char t0[SHAKE256_RATE]; - unsigned char t1[SHAKE256_RATE]; - unsigned int i; - - /* absorb 2 message of identical length in parallel */ - keccak_absorb2x(s, SHAKE256_RATE, in0, in1, inlen, 0x1F); - - /* Squeeze output */ - keccak_squeezeblocks2x(out0, out1, outlen / SHAKE256_RATE, s, SHAKE256_RATE); - - out0 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; - out1 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; - - if (outlen % SHAKE256_RATE) { - keccak_squeezeblocks2x(t0, t1, 1, s, SHAKE256_RATE); - for (i = 0; i < outlen % SHAKE256_RATE; i++) { - out0[i] = t0[i]; - out1[i] = t1[i]; - } - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/fips202x2.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/fips202x2.h deleted file mode 100644 index 7ba58b35d8..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/fips202x2.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef SPX_FIPS202X2_H -#define SPX_FIPS202X2_H - -#include - -uint64_t load64(const unsigned char *x); -void store64(uint8_t *x, uint64_t u); - - -void shake128x2(unsigned char *out0, - unsigned char *out1, - unsigned long long outlen, - unsigned char *in0, - unsigned char *in1, - unsigned long long inlen); - -void shake256x2(unsigned char *out0, - unsigned char *out1, - unsigned long long outlen, - unsigned char *in0, - unsigned char *in1, - unsigned long long inlen); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/fors.c b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/fors.c deleted file mode 100644 index 39193d04e2..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/fors.c +++ /dev/null @@ -1,191 +0,0 @@ -#include -#include -#include - -#include "fors.h" - -#include "address.h" -#include "hash.h" -#include "hashx2.h" -#include "thash.h" -#include "thashx2.h" -#include "utils.h" -#include "utilsx2.h" - -static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, - uint32_t fors_leaf_addr[8]) { - prf_addr(sk, ctx, fors_leaf_addr); -} - -static void fors_gen_skx2(unsigned char *sk0, - unsigned char *sk1, - const spx_ctx *ctx, - uint32_t fors_leaf_addrx2[2 * 8]) { - prf_addrx2(sk0, sk1, - ctx, fors_leaf_addrx2); -} - -static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, - const spx_ctx *ctx, - uint32_t fors_leaf_addr[8]) { - thash(leaf, sk, 1, ctx, fors_leaf_addr); -} - -static void fors_sk_to_leafx2(unsigned char *leaf0, - unsigned char *leaf1, - const unsigned char *sk0, - const unsigned char *sk1, - const spx_ctx *ctx, - uint32_t fors_leaf_addrx2[2 * 8]) { - thashx2(leaf0, leaf1, - sk0, sk1, - 1, ctx, fors_leaf_addrx2); -} - -struct fors_gen_leaf_info { - uint32_t leaf_addrx[2 * 8]; -}; - -static void fors_gen_leafx2(unsigned char *leaf, - const spx_ctx *ctx, - uint32_t addr_idx, void *info) { - struct fors_gen_leaf_info *fors_info = info; - uint32_t *fors_leaf_addrx2 = fors_info->leaf_addrx; - unsigned int j; - - /* Only set the parts that the caller doesn't set */ - for (j = 0; j < 2; j++) { - set_tree_index(fors_leaf_addrx2 + j * 8, addr_idx + j); - set_type(fors_leaf_addrx2 + j * 8, SPX_ADDR_TYPE_FORSPRF); - } - - fors_gen_skx2(leaf + 0 * SPX_N, - leaf + 1 * SPX_N, - ctx, fors_leaf_addrx2); - - for (j = 0; j < 2; j++) { - set_type(fors_leaf_addrx2 + j * 8, SPX_ADDR_TYPE_FORSTREE); - } - - fors_sk_to_leafx2(leaf + 0 * SPX_N, - leaf + 1 * SPX_N, - leaf + 0 * SPX_N, - leaf + 1 * SPX_N, - ctx, fors_leaf_addrx2); -} - -/** - * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - * Assumes indices has space for SPX_FORS_TREES integers. - */ -static void message_to_indices(uint32_t *indices, const unsigned char *m) { - unsigned int i, j; - unsigned int offset = 0; - - for (i = 0; i < SPX_FORS_TREES; i++) { - indices[i] = 0; - for (j = 0; j < SPX_FORS_HEIGHT; j++) { - indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); - offset++; - } - } -} - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -void fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]) { - uint32_t indices[SPX_FORS_TREES]; - unsigned char roots[SPX_FORS_TREES * SPX_N]; - uint32_t fors_tree_addr[2 * 8] = {0}; - struct fors_gen_leaf_info fors_info = {0}; - uint32_t *fors_leaf_addr = fors_info.leaf_addrx; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - for (i = 0; i < 2; i++) { - copy_keypair_addr(fors_tree_addr + 8 * i, fors_addr); - set_type(fors_tree_addr + 8 * i, SPX_ADDR_TYPE_FORSTREE); - copy_keypair_addr(fors_leaf_addr + 8 * i, fors_addr); - } - copy_keypair_addr(fors_pk_addr, fors_addr); - set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < SPX_FORS_TREES; i++) { - idx_offset = i * (1 << SPX_FORS_HEIGHT); - - set_tree_height(fors_tree_addr, 0); - set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Include the secret key part that produces the selected leaf node. */ - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); - fors_gen_sk(sig, ctx, fors_tree_addr); - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); - sig += SPX_N; - - /* Compute the authentication path for this leaf node. */ - treehashx2(roots + i * SPX_N, sig, ctx, - indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx2, - fors_tree_addr, &fors_info); - - sig += SPX_N * SPX_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); -} - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -void fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]) { - uint32_t indices[SPX_FORS_TREES]; - unsigned char roots[SPX_FORS_TREES * SPX_N]; - unsigned char leaf[SPX_N]; - uint32_t fors_tree_addr[8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - copy_keypair_addr(fors_tree_addr, fors_addr); - copy_keypair_addr(fors_pk_addr, fors_addr); - - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); - set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < SPX_FORS_TREES; i++) { - idx_offset = i * (1 << SPX_FORS_HEIGHT); - - set_tree_height(fors_tree_addr, 0); - set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Derive the leaf from the included secret key part. */ - fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); - sig += SPX_N; - - /* Derive the corresponding root node of this tree. */ - compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, - sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); - sig += SPX_N * SPX_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/fors.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/fors.h deleted file mode 100644 index 509140a178..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/fors.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef SPX_FORS_H -#define SPX_FORS_H - -#include - -#include "context.h" -#include "params.h" - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -#define fors_sign SPX_NAMESPACE(fors_sign) -void fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]); - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) -void fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/hash.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/hash.h deleted file mode 100644 index f7c87d4c3c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/hash.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef SPX_HASH_H -#define SPX_HASH_H - -#include -#include - -#include "context.h" -#include "params.h" - -#define prf_addr SPX_NAMESPACE(prf_addr) -void prf_addr(unsigned char *out, const spx_ctx *ctx, - const uint32_t addr[8]); - -#define gen_message_random SPX_NAMESPACE(gen_message_random) -void gen_message_random(unsigned char *R, const unsigned char *sk_prf, - const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx); - -#define hash_message SPX_NAMESPACE(hash_message) -void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx); - - - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/hash_shake.c b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/hash_shake.c deleted file mode 100644 index ff5e7ec918..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/hash_shake.c +++ /dev/null @@ -1,83 +0,0 @@ -#include -#include - -#include "hash.h" - -#include "address.h" -#include "fips202.h" -#include "params.h" -#include "utils.h" - -/* - * Computes PRF(pk_seed, sk_seed, addr) - */ -void prf_addr(unsigned char *out, const spx_ctx *ctx, - const uint32_t addr[8]) { - unsigned char buf[2 * SPX_N + SPX_ADDR_BYTES]; - - memcpy(buf, ctx->pub_seed, SPX_N); - memcpy(buf + SPX_N, addr, SPX_ADDR_BYTES); - memcpy(buf + SPX_N + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); - - shake256(out, SPX_N, buf, 2 * SPX_N + SPX_ADDR_BYTES); -} - -/** - * Computes the message-dependent randomness R, using a secret seed and an - * optional randomization value as well as the message. - */ -void gen_message_random(unsigned char *R, const unsigned char *sk_prf, - const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx) { - (void)ctx; - shake256incctx s_inc; - - shake256_inc_init(&s_inc); - shake256_inc_absorb(&s_inc, sk_prf, SPX_N); - shake256_inc_absorb(&s_inc, optrand, SPX_N); - shake256_inc_absorb(&s_inc, m, mlen); - shake256_inc_finalize(&s_inc); - shake256_inc_squeeze(R, SPX_N, &s_inc); - shake256_inc_ctx_release(&s_inc); -} - -/** - * Computes the message hash using R, the public key, and the message. - * Outputs the message digest and the index of the leaf. The index is split in - * the tree index and the leaf index, for convenient copying to an address. - */ -void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx) { - (void)ctx; -#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) -#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) -#define SPX_LEAF_BITS SPX_TREE_HEIGHT -#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) -#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) - - unsigned char buf[SPX_DGST_BYTES]; - unsigned char *bufp = buf; - shake256incctx s_inc; - - shake256_inc_init(&s_inc); - shake256_inc_absorb(&s_inc, R, SPX_N); - shake256_inc_absorb(&s_inc, pk, SPX_PK_BYTES); - shake256_inc_absorb(&s_inc, m, mlen); - shake256_inc_finalize(&s_inc); - shake256_inc_squeeze(buf, SPX_DGST_BYTES, &s_inc); - shake256_inc_ctx_release(&s_inc); - - memcpy(digest, bufp, SPX_FORS_MSG_BYTES); - bufp += SPX_FORS_MSG_BYTES; - - - *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); - *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); - bufp += SPX_TREE_BYTES; - - *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); - *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/hash_shakex2.c b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/hash_shakex2.c deleted file mode 100644 index 99571916a2..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/hash_shakex2.c +++ /dev/null @@ -1,52 +0,0 @@ -#include -#include - -#include "hashx2.h" - -#include "address.h" -#include "f1600x2.h" -#include "fips202x2.h" -#include "params.h" - -/* - * 2-way parallel version of prf_addr; takes 2x as much input and output - */ -void prf_addrx2(unsigned char *out0, - unsigned char *out1, - const spx_ctx *ctx, - const uint32_t addrx2[2 * 8]) { - /* As we write and read only a few quadwords, it is more efficient to - * build and extract from the fourway SHAKE256 state by hand. */ - uint64_t state[50] = {0}; - - for (int i = 0; i < SPX_N / 8; i++) { - uint64_t x = load64(ctx->pub_seed + 8 * i); - state[2 * i] = x; - state[2 * i + 1] = x; - } - for (int i = 0; i < 4; i++) { - state[2 * (SPX_N / 8 + i)] = (((uint64_t)addrx2[1 + 2 * i]) << 32) - | (uint64_t)addrx2[2 * i]; - state[2 * (SPX_N / 8 + i) + 1] = (((uint64_t)addrx2[8 + 1 + 2 * i]) << 32) - | (uint64_t)addrx2[8 + 2 * i]; - } - for (int i = 0; i < SPX_N / 8; i++) { - uint64_t x = load64(ctx->sk_seed + 8 * i); - state[2 * (SPX_N / 8 + i + 4)] = x; - state[2 * (SPX_N / 8 + i + 4) + 1] = x; - } - - /* SHAKE domain separator and padding. */ - state[2 * (SPX_N / 4 + 4)] = 0x1f; - state[2 * (SPX_N / 4 + 4) + 1] = 0x1f; - - state[2 * 16] = 0x80ULL << 56; - state[2 * 16 + 1] = 0x80ULL << 56; - - f1600x2(state); - - for (int i = 0; i < SPX_N / 8; i++) { - store64(out0 + 8 * i, state[2 * i]); - store64(out1 + 8 * i, state[2 * i + 1]); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/hashx2.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/hashx2.h deleted file mode 100644 index 99b8873a9b..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/hashx2.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef SPX_HASHX2_H -#define SPX_HASHX2_H - -#include "context.h" -#include "params.h" -#include - -#define prf_addrx2 SPX_NAMESPACE(prf_addrx2) -void prf_addrx2(unsigned char *out0, - unsigned char *out1, - const spx_ctx *ctx, - const uint32_t addrx2[2 * 8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/merkle.c b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/merkle.c deleted file mode 100644 index c94ee23939..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/merkle.c +++ /dev/null @@ -1,64 +0,0 @@ -#include -#include - -#include "merkle.h" - -#include "address.h" -#include "params.h" -#include "utils.h" -#include "utilsx2.h" -#include "wots.h" -#include "wotsx2.h" - -/* - * This generates a Merkle signature (WOTS signature followed by the Merkle - * authentication path). - */ -void merkle_sign(uint8_t *sig, unsigned char *root, - const spx_ctx *ctx, - uint32_t wots_addr[8], uint32_t tree_addr[8], - uint32_t idx_leaf) { - unsigned char *auth_path = sig + SPX_WOTS_BYTES; - uint32_t tree_addrx2[2 * 8] = { 0 }; - int j; - struct leaf_info_x2 info = { 0 }; - unsigned steps[ SPX_WOTS_LEN ]; - - info.wots_sig = sig; - chain_lengths(steps, root); - info.wots_steps = steps; - - for (j = 0; j < 2; j++) { - set_type(&tree_addrx2[8 * j], SPX_ADDR_TYPE_HASHTREE); - set_type(&info.leaf_addr[8 * j], SPX_ADDR_TYPE_WOTS); - set_type(&info.pk_addr[8 * j], SPX_ADDR_TYPE_WOTSPK); - copy_subtree_addr(&tree_addrx2[8 * j], tree_addr); - copy_subtree_addr(&info.leaf_addr[8 * j], wots_addr); - copy_subtree_addr(&info.pk_addr[8 * j], wots_addr); - } - - info.wots_sign_leaf = idx_leaf; - - treehashx2(root, auth_path, ctx, - idx_leaf, 0, - SPX_TREE_HEIGHT, - wots_gen_leafx2, - tree_addrx2, &info); -} - -/* Compute root node of the top-most subtree. */ -void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { - /* We do not need the auth path in key generation, but it simplifies the - code to have just one treehash routine that computes both root and path - in one function. */ - unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; - uint32_t top_tree_addr[8] = {0}; - uint32_t wots_addr[8] = {0}; - - set_layer_addr(top_tree_addr, SPX_D - 1); - set_layer_addr(wots_addr, SPX_D - 1); - - merkle_sign(auth_path, root, ctx, - wots_addr, top_tree_addr, - ~0 /* ~0 means "don't bother generating an auth path */ ); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/merkle.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/merkle.h deleted file mode 100644 index 769cf2e970..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/merkle.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef MERKLE_H_ -#define MERKLE_H_ - -#include - -#include "context.h" -#include "params.h" - -/* Generate a Merkle signature (WOTS signature followed by the Merkle */ -/* authentication path) */ -#define merkle_sign SPX_NAMESPACE(merkle_sign) -void merkle_sign(uint8_t *sig, unsigned char *root, - const spx_ctx *ctx, - uint32_t wots_addr[8], uint32_t tree_addr[8], - uint32_t idx_leaf); - -/* Compute the root node of the top-most subtree. */ -#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) -void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); - -#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/nistapi.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/nistapi.h deleted file mode 100644 index 3cb71afad4..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/nistapi.h +++ /dev/null @@ -1,87 +0,0 @@ -#ifndef SPX_API_H -#define SPX_API_H - -#include -#include - -#include "params.h" - -#define CRYPTO_ALGNAME "SPHINCS+" - -#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES -#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES -#define CRYPTO_BYTES SPX_BYTES -#define CRYPTO_SEEDBYTES (3*SPX_N) - -/* - * Returns the length of a secret key, in bytes - */ -#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) -size_t crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) -size_t crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) -size_t crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) -size_t crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) -int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) -int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) -int crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) -int crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -#define crypto_sign SPX_NAMESPACE(crypto_sign) -int crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) -int crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/params.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/params.h deleted file mode 100644 index f17a6c8eb3..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/params.h +++ /dev/null @@ -1,56 +0,0 @@ -#ifndef SPX_PARAMS_H -#define SPX_PARAMS_H - -#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSSHAKE256SROBUST_AARCH64_##s - -/* Hash output length in bytes. */ -#define SPX_N 32 -/* Height of the hypertree. */ -#define SPX_FULL_HEIGHT 64 -/* Number of subtree layer. */ -#define SPX_D 8 -/* FORS tree dimensions. */ -#define SPX_FORS_HEIGHT 14 -#define SPX_FORS_TREES 22 -/* Winternitz parameter, */ -#define SPX_WOTS_W 16 - -/* The hash function is defined by linking a different hash.c file, as opposed - to setting a #define constant. */ - -/* For clarity */ -#define SPX_ADDR_BYTES 32 - -/* WOTS parameters. */ -#define SPX_WOTS_LOGW 4 - -#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) - -/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#define SPX_WOTS_LEN2 3 - -#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) -#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) -#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES - -/* Subtree size. */ -#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) - -//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT -// #error SPX_D should always divide SPX_FULL_HEIGHT -//#endif - -/* FORS parameters. */ -#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) -#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) -#define SPX_FORS_PK_BYTES SPX_N - -/* Resulting SPX sizes. */ -#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ - SPX_FULL_HEIGHT * SPX_N) -#define SPX_PK_BYTES (2 * SPX_N) -#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) - -#include "shake_offsets.h" - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/shake_offsets.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/shake_offsets.h deleted file mode 100644 index 6b28d95d91..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/shake_offsets.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef SHAKE_OFFSETS_H_ -#define SHAKE_OFFSETS_H_ - -/* - * Offsets of various fields in the address structure when we use SHAKE as - * the Sphincs+ hash function - */ - -#define SPX_OFFSET_LAYER 3 /* The byte used to specify the Merkle tree layer */ -#define SPX_OFFSET_TREE 8 /* The start of the 8 byte field used to specify the tree */ -#define SPX_OFFSET_TYPE 19 /* The byte used to specify the hash type (reason) */ -#define SPX_OFFSET_KP_ADDR2 22 /* The high byte used to specify the key pair (which one-time signature) */ -#define SPX_OFFSET_KP_ADDR1 23 /* The low byte used to specify the key pair */ -#define SPX_OFFSET_CHAIN_ADDR 27 /* The byte used to specify the chain address (which Winternitz chain) */ -#define SPX_OFFSET_HASH_ADDR 31 /* The byte used to specify the hash address (where in the Winternitz chain) */ -#define SPX_OFFSET_TREE_HGT 27 /* The byte used to specify the height of this node in the FORS or Merkle tree */ -#define SPX_OFFSET_TREE_INDEX 28 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ - -#define SPX_SHAKE 1 - -#endif /* SHAKE_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/sign.c b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/sign.c deleted file mode 100644 index 9d0c7d1b22..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/sign.c +++ /dev/null @@ -1,286 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "context.h" -#include "fors.h" -#include "hash.h" -#include "merkle.h" -#include "nistapi.h" -#include "params.h" -#include "randombytes.h" -#include "thash.h" -#include "utils.h" -#include "wots.h" - -/* - * Returns the length of a secret key, in bytes - */ -size_t crypto_sign_secretkeybytes(void) { - return CRYPTO_SECRETKEYBYTES; -} - -/* - * Returns the length of a public key, in bytes - */ -size_t crypto_sign_publickeybytes(void) { - return CRYPTO_PUBLICKEYBYTES; -} - -/* - * Returns the length of a signature, in bytes - */ -size_t crypto_sign_bytes(void) { - return CRYPTO_BYTES; -} - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t crypto_sign_seedbytes(void) { - return CRYPTO_SEEDBYTES; -} - -/* - * Generates an SPX key pair given a seed of length - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed) { - spx_ctx ctx; - - /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ - memcpy(sk, seed, CRYPTO_SEEDBYTES); - - memcpy(pk, sk + 2 * SPX_N, SPX_N); - - memcpy(ctx.pub_seed, pk, SPX_N); - memcpy(ctx.sk_seed, sk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - /* Compute root node of the top-most subtree. */ - merkle_gen_root(sk + 3 * SPX_N, &ctx); - - // cleanup - free_hash_function(&ctx); - - memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); - - return 0; -} - -/* - * Generates an SPX key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { - uint8_t seed[CRYPTO_SEEDBYTES]; - randombytes(seed, CRYPTO_SEEDBYTES); - crypto_sign_seed_keypair(pk, sk, seed); - - return 0; -} - -/** - * Returns an array containing a detached signature. - */ -int crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - spx_ctx ctx; - - const uint8_t *sk_prf = sk + SPX_N; - const uint8_t *pk = sk + 2 * SPX_N; - - uint8_t optrand[SPX_N]; - uint8_t mhash[SPX_FORS_MSG_BYTES]; - uint8_t root[SPX_N]; - uint32_t i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - - memcpy(ctx.sk_seed, sk, SPX_N); - memcpy(ctx.pub_seed, pk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - set_type(wots_addr, SPX_ADDR_TYPE_WOTS); - set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); - - /* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ - randombytes(optrand, SPX_N); - /* Compute the digest randomization value. */ - gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); - - /* Derive the message digest and leaf index from R, PK and M. */ - hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); - sig += SPX_N; - - set_tree_addr(wots_addr, tree); - set_keypair_addr(wots_addr, idx_leaf); - - /* Sign the message hash using FORS. */ - fors_sign(sig, root, mhash, &ctx, wots_addr); - sig += SPX_FORS_BYTES; - - for (i = 0; i < SPX_D; i++) { - set_layer_addr(tree_addr, i); - set_tree_addr(tree_addr, tree); - - copy_subtree_addr(wots_addr, tree_addr); - set_keypair_addr(wots_addr, idx_leaf); - - merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); - sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); - tree = tree >> SPX_TREE_HEIGHT; - } - - free_hash_function(&ctx); - - *siglen = SPX_BYTES; - - return 0; -} - -/** - * Verifies a detached signature and message under a given public key. - */ -int crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk) { - spx_ctx ctx; - const uint8_t *pub_root = pk + SPX_N; - uint8_t mhash[SPX_FORS_MSG_BYTES]; - uint8_t wots_pk[SPX_WOTS_BYTES]; - uint8_t root[SPX_N]; - uint8_t leaf[SPX_N]; - unsigned int i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - if (siglen != SPX_BYTES) { - return -1; - } - - memcpy(ctx.pub_seed, pk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - set_type(wots_addr, SPX_ADDR_TYPE_WOTS); - set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); - set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); - - /* Derive the message digest and leaf index from R || PK || M. */ - /* The additional SPX_N is a result of the hash domain separator. */ - hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); - sig += SPX_N; - - /* Layer correctly defaults to 0, so no need to set_layer_addr */ - set_tree_addr(wots_addr, tree); - set_keypair_addr(wots_addr, idx_leaf); - - fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); - sig += SPX_FORS_BYTES; - - /* For each subtree.. */ - for (i = 0; i < SPX_D; i++) { - set_layer_addr(tree_addr, i); - set_tree_addr(tree_addr, tree); - - copy_subtree_addr(wots_addr, tree_addr); - set_keypair_addr(wots_addr, idx_leaf); - - copy_keypair_addr(wots_pk_addr, wots_addr); - - /* The WOTS public key is only correct if the signature was correct. */ - /* Initially, root is the FORS pk, but on subsequent iterations it is - the root of the subtree below the currently processed subtree. */ - wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); - sig += SPX_WOTS_BYTES; - - /* Compute the leaf node using the WOTS public key. */ - thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); - - /* Compute the root node of this subtree. */ - compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, - &ctx, tree_addr); - sig += SPX_TREE_HEIGHT * SPX_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); - tree = tree >> SPX_TREE_HEIGHT; - } - - // cleanup - free_hash_function(&ctx); - - /* Check if the root node equals the root node in the public key. */ - if (memcmp(root, pub_root, SPX_N) != 0) { - return -1; - } - - return 0; -} - - -/** - * Returns an array containing the signature followed by the message. - */ -int crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk) { - size_t siglen; - - crypto_sign_signature(sm, &siglen, m, mlen, sk); - - memmove(sm + SPX_BYTES, m, mlen); - *smlen = siglen + mlen; - - return 0; -} - -/** - * Verifies a given signature-message pair under a given public key. - */ -int crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk) { - /* The API caller does not necessarily know what size a signature should be - but SPHINCS+ signatures are always exactly SPX_BYTES. */ - if (smlen < SPX_BYTES) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - *mlen = smlen - SPX_BYTES; - - if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - /* If verification was successful, move the message to the right place. */ - memmove(m, sm + SPX_BYTES, *mlen); - - return 0; -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/thash.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/thash.h deleted file mode 100644 index 8687ccfb4d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/thash.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef SPX_THASH_H -#define SPX_THASH_H - -#include "context.h" -#include "params.h" - -#include - -#define thash SPX_NAMESPACE(thash) -void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/thash_shake_robustx2.c b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/thash_shake_robustx2.c deleted file mode 100644 index 454fc0f4e2..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/thash_shake_robustx2.c +++ /dev/null @@ -1,112 +0,0 @@ -#include -#include - -#include "thash.h" -#include "thashx2.h" - -#include "address.h" -#include "params.h" -#include "utils.h" - -#include "f1600x2.h" -#include "fips202x2.h" - - -void thash(unsigned char *out, - const unsigned char *in, - unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]) { - uint32_t addrx2 [2 * 8] = { - addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], addr[6], addr[7], - addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], addr[6], addr[7] - }; - thashx2(out, out, in, in, inblocks, ctx, addrx2); -} - -/** - * 2-way parallel version of thash; takes 2x as much input and output - */ -void thashx2(unsigned char *out0, - unsigned char *out1, - const unsigned char *in0, - const unsigned char *in1, - unsigned int inblocks, - const spx_ctx *ctx, uint32_t addrx2[2 * 8]) { - if (inblocks == 1 || inblocks == 2) { - /* As we write and read only a few quadwords, it is more efficient to - * build and extract from the twoway SHAKE256 state by hand. */ - uint64_t state[50] = {0}; - uint64_t state2[50]; - - for (int i = 0; i < SPX_N / 8; i++) { - uint64_t x = load64(ctx->pub_seed + 8 * i); - state[2 * i] = x; - state[2 * i + 1] = x; - } - for (int i = 0; i < 4; i++) { - state[2 * (SPX_N / 8 + i)] = (((uint64_t)addrx2[1 + 2 * i]) << 32) - | (uint64_t)addrx2[2 * i]; - state[2 * (SPX_N / 8 + i) + 1] = (((uint64_t)addrx2[8 + 1 + 2 * i]) << 32) - | (uint64_t)addrx2[8 + 2 * i]; - } - - /* Domain separator and padding. */ - state[2 * 16] = 0x80ULL << 56; - state[2 * 16 + 1] = 0x80ULL << 56; - - state[2 * ((SPX_N / 8) + 4)] ^= 0x1f; - state[2 * ((SPX_N / 8) + 4) + 1] ^= 0x1f; - - /* We will permutate state2 with f1600x2 to compute the bitmask, - * but first we'll copy it to state2 which will be used to compute - * the final output, as its input is almost identical. */ - memcpy(state2, state, 400); - - f1600x2(state); - - /* By copying from state, state2 already contains the pub_seed - * and address. We just need to copy in the input blocks xorred with - * the bitmask we just computed. */ - for (unsigned int i = 0; i < (SPX_N / 8) * inblocks; i++) { - state2[2 * (SPX_N / 8 + 4 + i)] = state[2 * i] ^ load64(in0 + 8 * i); - state2[2 * (SPX_N / 8 + 4 + i) + 1] = state[2 * i + 1] ^ load64(in1 + 8 * i); - } - - /* Domain separator and start of padding. Note that the quadwords - * around are already zeroed for state from which we copied. - * We do a XOR instead of a set as this might be the 16th quadword - * when N=32 and inblocks=2, which already contains the end - * of the padding. */ - state2[2 * ((SPX_N / 8) * (1 + inblocks) + 4)] ^= 0x1f; - state2[2 * ((SPX_N / 8) * (1 + inblocks) + 4) + 1] ^= 0x1f; - - f1600x2(state2); - - for (int i = 0; i < SPX_N / 8; i++) { - store64(out0 + 8 * i, state2[2 * i]); - store64(out1 + 8 * i, state2[2 * i + 1]); - } - } else { - PQCLEAN_VLA(unsigned char, buf0, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); - PQCLEAN_VLA(unsigned char, buf1, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); - PQCLEAN_VLA(unsigned char, bitmask0, inblocks * SPX_N); - PQCLEAN_VLA(unsigned char, bitmask1, inblocks * SPX_N); - unsigned int i; - - memcpy(buf0, ctx->pub_seed, SPX_N); - memcpy(buf1, ctx->pub_seed, SPX_N); - memcpy(buf0 + SPX_N, addrx2 + 0 * 8, SPX_ADDR_BYTES); - memcpy(buf1 + SPX_N, addrx2 + 1 * 8, SPX_ADDR_BYTES); - - shake256x2(bitmask0, bitmask1, inblocks * SPX_N, - buf0, buf1, SPX_N + SPX_ADDR_BYTES); - - for (i = 0; i < inblocks * SPX_N; i++) { - buf0[SPX_N + SPX_ADDR_BYTES + i] = in0[i] ^ bitmask0[i]; - buf1[SPX_N + SPX_ADDR_BYTES + i] = in1[i] ^ bitmask1[i]; - } - - shake256x2(out0, out1, SPX_N, - buf0, buf1, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/thashx2.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/thashx2.h deleted file mode 100644 index 040375e618..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/thashx2.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef SPX_THASHX2_H -#define SPX_THASHX2_H - -#include "context.h" -#include "params.h" -#include - -#define thashx2 SPX_NAMESPACE(thashx2) -void thashx2(unsigned char *out0, - unsigned char *out1, - const unsigned char *in0, - const unsigned char *in1, - unsigned int inblocks, - const spx_ctx *ctx, uint32_t addrx2[2 * 8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/utils.c b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/utils.c deleted file mode 100644 index 177b541fb9..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/utils.c +++ /dev/null @@ -1,148 +0,0 @@ -#include - -#include "utils.h" - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "thash.h" - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void ull_to_bytes(unsigned char *out, unsigned int outlen, - unsigned long long in) { - int i; - - /* Iterate over out in decreasing order, for big-endianness. */ - for (i = (signed int)outlen - 1; i >= 0; i--) { - out[i] = in & 0xff; - in = in >> 8; - } -} - -void u32_to_bytes(unsigned char *out, uint32_t in) { - out[0] = (unsigned char)(in >> 24); - out[1] = (unsigned char)(in >> 16); - out[2] = (unsigned char)(in >> 8); - out[3] = (unsigned char)in; -} - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { - unsigned long long retval = 0; - unsigned int i; - - for (i = 0; i < inlen; i++) { - retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); - } - return retval; -} - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void compute_root(unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const spx_ctx *ctx, uint32_t addr[8]) { - uint32_t i; - unsigned char buffer[2 * SPX_N]; - - /* If leaf_idx is odd (last bit = 1), current path element is a right child - and auth_path has to go left. Otherwise it is the other way around. */ - if (leaf_idx & 1) { - memcpy(buffer + SPX_N, leaf, SPX_N); - memcpy(buffer, auth_path, SPX_N); - } else { - memcpy(buffer, leaf, SPX_N); - memcpy(buffer + SPX_N, auth_path, SPX_N); - } - auth_path += SPX_N; - - for (i = 0; i < tree_height - 1; i++) { - leaf_idx >>= 1; - idx_offset >>= 1; - /* Set the address of the node we're creating. */ - set_tree_height(addr, i + 1); - set_tree_index(addr, leaf_idx + idx_offset); - - /* Pick the right or left neighbor, depending on parity of the node. */ - if (leaf_idx & 1) { - thash(buffer + SPX_N, buffer, 2, ctx, addr); - memcpy(buffer, auth_path, SPX_N); - } else { - thash(buffer, buffer, 2, ctx, addr); - memcpy(buffer + SPX_N, auth_path, SPX_N); - } - auth_path += SPX_N; - } - - /* The last iteration is exceptional; we do not copy an auth_path node. */ - leaf_idx >>= 1; - idx_offset >>= 1; - set_tree_height(addr, tree_height); - set_tree_index(addr, leaf_idx + idx_offset); - thash(root, buffer, 2, ctx, addr); -} - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const spx_ctx * /* ctx */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), - uint32_t tree_addr[8]) { - PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); - PQCLEAN_VLA(unsigned int, heights, tree_height + 1); - unsigned int offset = 0; - uint32_t idx; - uint32_t tree_idx; - - for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { - /* Add the next leaf node to the stack. */ - gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); - offset++; - heights[offset - 1] = 0; - - /* If this is a node we need for the auth path.. */ - if ((leaf_idx ^ 0x1) == idx) { - memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); - } - - /* While the top-most nodes are of equal height.. */ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { - /* Compute index of the new node, in the next layer. */ - tree_idx = (idx >> (heights[offset - 1] + 1)); - - /* Set the address of the node we're creating. */ - set_tree_height(tree_addr, heights[offset - 1] + 1); - set_tree_index(tree_addr, - tree_idx + (idx_offset >> (heights[offset - 1] + 1))); - /* Hash the top-most nodes from the stack together. */ - thash(stack + (offset - 2)*SPX_N, - stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); - offset--; - /* Note that the top-most node is now one layer higher. */ - heights[offset - 1]++; - - /* If this is a node we need for the auth path.. */ - if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_path + heights[offset - 1]*SPX_N, - stack + (offset - 1)*SPX_N, SPX_N); - } - } - } - memcpy(root, stack, SPX_N); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/utils.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/utils.h deleted file mode 100644 index 64f5d5a53a..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/utils.h +++ /dev/null @@ -1,58 +0,0 @@ -#ifndef SPX_UTILS_H -#define SPX_UTILS_H - -#include - -#include "compat.h" -#include "context.h" -#include "params.h" - - -/* To support MSVC use alloca() instead of VLAs. See #20. */ - - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) -void ull_to_bytes(unsigned char *out, unsigned int outlen, - unsigned long long in); -#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) -void u32_to_bytes(unsigned char *out, uint32_t in); - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) -unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -#define compute_root SPX_NAMESPACE(compute_root) -void compute_root(unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const spx_ctx *ctx, uint32_t addr[8]); - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -#define treehash SPX_NAMESPACE(treehash) -void treehash(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const spx_ctx *ctx /* ctx */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), - uint32_t tree_addr[8]); - - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/utilsx2.c b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/utilsx2.c deleted file mode 100644 index 8736474e4f..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/utilsx2.c +++ /dev/null @@ -1,130 +0,0 @@ -#include - -#include "utilsx2.h" - -#include "address.h" -#include "params.h" -#include "thashx2.h" -#include "utils.h" - -/* - * Generate the entire Merkle tree, computing the authentication path for leaf_idx, - * and the resulting root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) - * - * This expects tree_addrx2 to be initialized to 2 parallel addr structures for - * the Merkle tree nodes - * - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - * - * This works by using the standard Merkle tree building algorithm, except - * that each 'node' tracked is actually 2 consecutive nodes in the real tree. - * When we combine two logical nodes AB and WX, we perform the H - * operation on adjacent real nodes, forming the parent logical node - * (AB)(WX) - * - * When we get to the top level of the real tree (where there is only - * one logical node), we continue this operation one more time; the right - * most real node will by the actual root (and the other node will be - * garbage). We follow the same thashx2 logic so that the 'extract - * authentication path components' part of the loop is still executed (and - * to simplify the code somewhat) - */ -void treehashx2(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, - uint32_t tree_height, - void (*gen_leafx2)( - unsigned char * /* Where to write the leaves */, - const spx_ctx *, - uint32_t idx, void *info), - uint32_t tree_addrx2[2 * 8], - void *info) { - /* This is where we keep the intermediate nodes */ - unsigned char stackx2[tree_height * 2 * SPX_N]; - uint32_t left_adj = 0, prev_left_adj = 0; /* When we're doing the top */ - /* level, the left-most part of the tree isn't at the beginning */ - /* of current[]. These give the offset of the actual start */ - - uint32_t idx; - uint32_t max_idx = (1 << (tree_height - 1)) - 1; - for (idx = 0;; idx++) { - unsigned char current[2 * SPX_N]; /* Current logical node */ - gen_leafx2( current, ctx, 2 * idx + idx_offset, - info ); - - /* Now combine the freshly generated right node with previously */ - /* generated left ones */ - uint32_t internal_idx_offset = idx_offset; - uint32_t internal_idx = idx; - uint32_t internal_leaf = leaf_idx; - uint32_t h; /* The height we are in the Merkle tree */ - for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { - - /* Special processing if we're at the top of the tree */ - if (h >= tree_height - 1) { - if (h == tree_height) { - /* We hit the root; return it */ - memcpy( root, ¤t[1 * SPX_N], SPX_N ); - return; - } - /* The tree indexing logic is a bit off in this case */ - /* Adjust it so that the left-most node of the part of */ - /* the tree that we're processing has index 0 */ - prev_left_adj = left_adj; - left_adj = 2 - (1 << (tree_height - h - 1)); - } - - /* Check if we hit the top of the tree */ - if (h == tree_height) { - /* We hit the root; return it */ - memcpy( root, ¤t[1 * SPX_N], SPX_N ); - return; - } - - /* - * Check if one of the nodes we have is a part of the - * authentication path; if it is, write it out - */ - if ((((internal_idx << 1) ^ internal_leaf) & ~0x1) == 0) { - memcpy( &auth_path[ h * SPX_N ], - ¤t[(((internal_leaf & 1) ^ 1) + prev_left_adj) * SPX_N], - SPX_N ); - } - - /* - * Check if we're at a left child; if so, stop going up the stack - * Exception: if we've reached the end of the tree, keep on going - * (so we combine the last 2 nodes into the one root node in two - * more iterations) - */ - if ((internal_idx & 1) == 0 && idx < max_idx) { - break; - } - - /* Ok, we're at a right node (or doing the top 3 levels) */ - /* Now combine the left and right logical nodes together */ - - /* Set the address of the node we're creating. */ - int j; - internal_idx_offset >>= 1; - for (j = 0; j < 2; j++) { - set_tree_height(tree_addrx2 + j * 8, h + 1); - set_tree_index(tree_addrx2 + j * 8, - (2 / 2) * (internal_idx & ~1) + j - left_adj + internal_idx_offset ); - } - unsigned char *left = &stackx2[h * 2 * SPX_N]; - thashx2( ¤t[0 * SPX_N], - ¤t[1 * SPX_N], - &left [0 * SPX_N], - ¤t[0 * SPX_N], - 2, ctx, tree_addrx2); - } - - /* We've hit a left child; save the current for when we get the */ - /* corresponding right right */ - memcpy( &stackx2[h * 2 * SPX_N], current, 2 * SPX_N); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/utilsx2.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/utilsx2.h deleted file mode 100644 index e09faddc43..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/utilsx2.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef SPX_UTILSX2_H -#define SPX_UTILSX2_H - -#include - -#include "context.h" -#include "params.h" - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - * - * This implementation uses SIMD to compute internal nodes 2 at a time (in - * parallel) - */ -#define treehashx2 SPX_NAMESPACE(treehashx2) -void treehashx2(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leafx2)( - unsigned char * /* Where to write the leaves */, - const spx_ctx * /* ctx */, - uint32_t addr_idx, void *info), - uint32_t tree_addrx2[2 * 8], void *info); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/wots.c b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/wots.c deleted file mode 100644 index 3babe45e95..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/wots.c +++ /dev/null @@ -1,259 +0,0 @@ -#include -#include - -#include "wots.h" -#include "wotsx2.h" - -#include "address.h" -#include "hash.h" -#include "hashx2.h" -#include "params.h" -#include "thashx2.h" -#include "utils.h" -#include "utilsx2.h" - -// TODO clarify address expectations, and make them more uniform. -// TODO i.e. do we expect types to be set already? -// TODO and do we expect modifications or copies? - -/** - * Computes up the chains - */ -static void gen_chains( - unsigned char *out, - const unsigned char *in, - unsigned int start[SPX_WOTS_LEN], - const unsigned int steps[SPX_WOTS_LEN], - const spx_ctx *ctx, - uint32_t addr[8]) { - uint32_t i, j, k, idx, watching; - int done; - unsigned char empty[SPX_N]; - unsigned char *bufs[4]; - uint32_t addrs[8 * 2]; - - int l; - uint16_t counts[SPX_WOTS_W] = { 0 }; - uint16_t idxs[SPX_WOTS_LEN]; - uint16_t total, newTotal; - - /* set addrs = {addr, addr} */ - for (j = 0; j < 2; j++) { - memcpy(addrs + j * 8, addr, sizeof(uint32_t) * 8); - } - - /* Initialize out with the value at position 'start'. */ - memcpy(out, in, SPX_WOTS_LEN * SPX_N); - - /* Sort the chains in reverse order by steps using counting sort. */ - for (i = 0; i < SPX_WOTS_LEN; i++) { - counts[steps[i]]++; - } - total = 0; - for (l = SPX_WOTS_W - 1; l >= 0; l--) { - newTotal = counts[l] + total; - counts[l] = total; - total = newTotal; - } - for (i = 0; i < SPX_WOTS_LEN; i++) { - idxs[counts[steps[i]]] = i; - counts[steps[i]]++; - } - - /* We got our work cut out for us: do it! */ - for (i = 0; i < SPX_WOTS_LEN; i += 2) { - for (j = 0; j < 2 && i + j < SPX_WOTS_LEN; j++) { - idx = idxs[i + j]; - set_chain_addr(addrs + j * 8, idx); - bufs[j] = out + SPX_N * idx; - } - - /* As the chains are sorted in reverse order, we know that the first - * chain is the longest and the last one is the shortest. We keep - * an eye on whether the last chain is done and then on the one before, - * et cetera. */ - watching = 1; - done = 0; - while (i + watching >= SPX_WOTS_LEN) { - bufs[watching] = &empty[0]; - watching--; - } - - for (k = 0;; k++) { - while (k == steps[idxs[i + watching]]) { - bufs[watching] = &empty[0]; - if (watching == 0) { - done = 1; - break; - } - watching--; - } - if (done) { - break; - } - for (j = 0; j < watching + 1; j++) { - set_hash_addr(addrs + j * 8, k + start[idxs[i + j]]); - } - - thashx2(bufs[0], bufs[1], - bufs[0], bufs[1], 1, ctx, addrs); - } - } -} - -/** - * base_w algorithm as described in draft. - * Interprets an array of bytes as integers in base w. - * This only works when log_w is a divisor of 8. - */ -static void base_w(unsigned int *output, const int out_len, - const unsigned char *input) { - int in = 0; - int out = 0; - unsigned char total = 0; - int bits = 0; - int consumed; - - for (consumed = 0; consumed < out_len; consumed++) { - if (bits == 0) { - total = input[in]; - in++; - bits += 8; - } - bits -= SPX_WOTS_LOGW; - output[out] = (total >> bits) & (SPX_WOTS_W - 1); - out++; - } -} - -/* Computes the WOTS+ checksum over a message (in base_w). */ -static void wots_checksum(unsigned int *csum_base_w, - const unsigned int *msg_base_w) { - unsigned int csum = 0; - unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; - unsigned int i; - - /* Compute checksum. */ - for (i = 0; i < SPX_WOTS_LEN1; i++) { - csum += SPX_WOTS_W - 1 - msg_base_w[i]; - } - - /* Convert checksum to base_w. */ - /* Make sure expected empty zero bits are the least significant bits. */ - csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); - ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); - base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); -} - -/* Takes a message and derives the matching chain lengths. */ -void chain_lengths(unsigned int *lengths, const unsigned char *msg) { - base_w(lengths, SPX_WOTS_LEN1, msg); - wots_checksum(lengths + SPX_WOTS_LEN1, lengths); -} - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const spx_ctx *ctx, uint32_t addr[8]) { - unsigned int steps[SPX_WOTS_LEN]; - unsigned int start[SPX_WOTS_LEN]; - uint32_t i; - - chain_lengths(start, msg); - - for (i = 0; i < SPX_WOTS_LEN; i++) { - steps[i] = SPX_WOTS_W - 1 - start[i]; - } - - gen_chains(pk, sig, start, steps, ctx, addr); -} - -/* - * This generates 2 sequential WOTS public keys - * It also generates the WOTS signature if leaf_info indicates - * that we're signing with one of these WOTS keys - */ -void wots_gen_leafx2(unsigned char *dest, - const spx_ctx *ctx, - uint32_t leaf_idx, void *v_info) { - struct leaf_info_x2 *info = v_info; - uint32_t *leaf_addr = info->leaf_addr; - uint32_t *pk_addr = info->pk_addr; - unsigned int i, j, k; - unsigned char pk_buffer[ 2 * SPX_WOTS_BYTES ]; - unsigned wots_offset = SPX_WOTS_BYTES; - unsigned char *buffer; - uint32_t wots_k_mask; - unsigned wots_sign_index; - - if (((leaf_idx ^ info->wots_sign_leaf) & ~1) == 0) { - /* We're traversing the leaf that's signing; generate the WOTS */ - /* signature */ - wots_k_mask = 0; - wots_sign_index = info->wots_sign_leaf & 1; /* Which of of the 2 */ - /* slots do the signatures come from */ - } else { - /* Nope, we're just generating pk's; turn off the signature logic */ - wots_k_mask = ~0; - wots_sign_index = 0; - } - - for (j = 0; j < 2; j++) { - set_keypair_addr( leaf_addr + j * 8, leaf_idx + j ); - set_keypair_addr( pk_addr + j * 8, leaf_idx + j ); - } - - for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { - uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k to */ - /* the step if we're generating a signature, ~0 if we're not */ - - /* Start with the secret seed */ - for (j = 0; j < 2; j++) { - set_chain_addr(leaf_addr + j * 8, i); - set_hash_addr(leaf_addr + j * 8, 0); - set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTSPRF); - } - prf_addrx2(buffer + 0 * wots_offset, - buffer + 1 * wots_offset, - ctx, leaf_addr); - for (j = 0; j < 2; j++) { - set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTS); - } - - /* Iterate down the WOTS chain */ - for (k = 0;; k++) { - /* Check if one of the values we have needs to be saved as a */ - /* part of the WOTS signature */ - if (k == wots_k) { - memcpy( info->wots_sig + i * SPX_N, - buffer + wots_sign_index * wots_offset, SPX_N ); - } - - /* Check if we hit the top of the chain */ - if (k == SPX_WOTS_W - 1) { - break; - } - - /* Iterate one step on all 4 chains */ - for (j = 0; j < 2; j++) { - set_hash_addr(leaf_addr + j * 8, k); - } - thashx2(buffer + 0 * wots_offset, - buffer + 1 * wots_offset, - buffer + 0 * wots_offset, - buffer + 1 * wots_offset, - 1, ctx, leaf_addr); - } - } - - /* Do the final thash to generate the public keys */ - thashx2(dest + 0 * SPX_N, - dest + 1 * SPX_N, - pk_buffer + 0 * wots_offset, - pk_buffer + 1 * wots_offset, - SPX_WOTS_LEN, ctx, pk_addr); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/wots.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/wots.h deleted file mode 100644 index 4e7692eeef..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/wots.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef SPX_WOTS_H -#define SPX_WOTS_H - -#include - -#include "context.h" -#include "params.h" - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) -void wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const spx_ctx *ctx, uint32_t addr[8]); - -/* - * Compute the chain lengths needed for a given message hash - */ -#define chain_lengths SPX_NAMESPACE(chain_lengths) -void chain_lengths(unsigned int *lengths, const unsigned char *msg); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/wotsx2.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/wotsx2.h deleted file mode 100644 index b58bb61f84..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_aarch64/wotsx2.h +++ /dev/null @@ -1,40 +0,0 @@ -#ifndef WOTSX2_H_ -#define WOTSX2_H_ - -#include "params.h" -#include - -/* - * This is here to provide an interface to the internal wots_gen_leafx2 - * routine. While this routine is not referenced in the package outside of - * wots.c, it is called from the stand-alone benchmark code to characterize - * the performance - */ -struct leaf_info_x2 { - unsigned char *wots_sig; - uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ - uint32_t *wots_steps; - uint32_t leaf_addr[2 * 8]; - uint32_t pk_addr[2 * 8]; -}; - -/* Macro to set the leaf_info to something 'benign', that is, it would */ -/* run with the same time as it does during the real signing process */ -/* Used only by the benchmark code */ -#define INITIALIZE_LEAF_INFO_X2(info, addr, step_buffer) { \ - (info).wots_sig = 0; \ - (info).wots_sign_leaf = ~0; \ - (info).wots_steps = step_buffer; \ - int i; \ - for (i=0; i<2; i++) { \ - memcpy( &(info).leaf_addr[8*i], addr, 32 ); \ - memcpy( &(info).pk_addr[8*i], addr, 32 ); \ - } \ - } - -#define wots_gen_leafx2 SPX_NAMESPACE(wots_gen_leafx2) -void wots_gen_leafx2(unsigned char *dest, - const spx_ctx *ctx, - uint32_t leaf_idx, void *v_info); - -#endif /* WOTSX2_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/LICENSE b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/LICENSE deleted file mode 100644 index 670154e353..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/LICENSE +++ /dev/null @@ -1,116 +0,0 @@ -CC0 1.0 Universal - -Statement of Purpose - -The laws of most jurisdictions throughout the world automatically confer -exclusive Copyright and Related Rights (defined below) upon the creator and -subsequent owner(s) (each and all, an "owner") of an original work of -authorship and/or a database (each, a "Work"). - -Certain owners wish to permanently relinquish those rights to a Work for the -purpose of contributing to a commons of creative, cultural and scientific -works ("Commons") that the public can reliably and without fear of later -claims of infringement build upon, modify, incorporate in other works, reuse -and redistribute as freely as possible in any form whatsoever and for any -purposes, including without limitation commercial purposes. These owners may -contribute to the Commons to promote the ideal of a free culture and the -further production of creative, cultural and scientific works, or to gain -reputation or greater distribution for their Work in part through the use and -efforts of others. - -For these and/or other purposes and motivations, and without any expectation -of additional consideration or compensation, the person associating CC0 with a -Work (the "Affirmer"), to the extent that he or she is an owner of Copyright -and Related Rights in the Work, voluntarily elects to apply CC0 to the Work -and publicly distribute the Work under its terms, with knowledge of his or her -Copyright and Related Rights in the Work and the meaning and intended legal -effect of CC0 on those rights. - -1. Copyright and Related Rights. A Work made available under CC0 may be -protected by copyright and related or neighboring rights ("Copyright and -Related Rights"). Copyright and Related Rights include, but are not limited -to, the following: - - i. the right to reproduce, adapt, distribute, perform, display, communicate, - and translate a Work; - - ii. moral rights retained by the original author(s) and/or performer(s); - - iii. publicity and privacy rights pertaining to a person's image or likeness - depicted in a Work; - - iv. rights protecting against unfair competition in regards to a Work, - subject to the limitations in paragraph 4(a), below; - - v. rights protecting the extraction, dissemination, use and reuse of data in - a Work; - - vi. database rights (such as those arising under Directive 96/9/EC of the - European Parliament and of the Council of 11 March 1996 on the legal - protection of databases, and under any national implementation thereof, - including any amended or successor version of such directive); and - - vii. other similar, equivalent or corresponding rights throughout the world - based on applicable law or treaty, and any national implementations thereof. - -2. Waiver. To the greatest extent permitted by, but not in contravention of, -applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and -unconditionally waives, abandons, and surrenders all of Affirmer's Copyright -and Related Rights and associated claims and causes of action, whether now -known or unknown (including existing as well as future claims and causes of -action), in the Work (i) in all territories worldwide, (ii) for the maximum -duration provided by applicable law or treaty (including future time -extensions), (iii) in any current or future medium and for any number of -copies, and (iv) for any purpose whatsoever, including without limitation -commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes -the Waiver for the benefit of each member of the public at large and to the -detriment of Affirmer's heirs and successors, fully intending that such Waiver -shall not be subject to revocation, rescission, cancellation, termination, or -any other legal or equitable action to disrupt the quiet enjoyment of the Work -by the public as contemplated by Affirmer's express Statement of Purpose. - -3. Public License Fallback. Should any part of the Waiver for any reason be -judged legally invalid or ineffective under applicable law, then the Waiver -shall be preserved to the maximum extent permitted taking into account -Affirmer's express Statement of Purpose. In addition, to the extent the Waiver -is so judged Affirmer hereby grants to each affected person a royalty-free, -non transferable, non sublicensable, non exclusive, irrevocable and -unconditional license to exercise Affirmer's Copyright and Related Rights in -the Work (i) in all territories worldwide, (ii) for the maximum duration -provided by applicable law or treaty (including future time extensions), (iii) -in any current or future medium and for any number of copies, and (iv) for any -purpose whatsoever, including without limitation commercial, advertising or -promotional purposes (the "License"). The License shall be deemed effective as -of the date CC0 was applied by Affirmer to the Work. Should any part of the -License for any reason be judged legally invalid or ineffective under -applicable law, such partial invalidity or ineffectiveness shall not -invalidate the remainder of the License, and in such case Affirmer hereby -affirms that he or she will not (i) exercise any of his or her remaining -Copyright and Related Rights in the Work or (ii) assert any associated claims -and causes of action with respect to the Work, in either case contrary to -Affirmer's express Statement of Purpose. - -4. Limitations and Disclaimers. - - a. No trademark or patent rights held by Affirmer are waived, abandoned, - surrendered, licensed or otherwise affected by this document. - - b. Affirmer offers the Work as-is and makes no representations or warranties - of any kind concerning the Work, express, implied, statutory or otherwise, - including without limitation warranties of title, merchantability, fitness - for a particular purpose, non infringement, or the absence of latent or - other defects, accuracy, or the present or absence of errors, whether or not - discoverable, all to the greatest extent permissible under applicable law. - - c. Affirmer disclaims responsibility for clearing rights of other persons - that may apply to the Work or any use thereof, including without limitation - any person's Copyright and Related Rights in the Work. Further, Affirmer - disclaims responsibility for obtaining any necessary consents, permissions - or other rights required for any use of the Work. - - d. Affirmer understands and acknowledges that Creative Commons is not a - party to this document and has no duty or obligation with respect to this - CC0 or use of the Work. - -For more information, please see - diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/address.c b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/address.c deleted file mode 100644 index b956e9cb29..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/address.c +++ /dev/null @@ -1,91 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "utils.h" - -/* - * Specify which level of Merkle tree (the "layer") we're working on - */ -void set_layer_addr(uint32_t addr[8], uint32_t layer) { - ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; -} - -/* - * Specify which Merkle tree within the level (the "tree address") we're working on - */ -void set_tree_addr(uint32_t addr[8], uint64_t tree) { - ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); -} - -/* - * Specify the reason we'll use this address structure for, that is, what - * hash will we compute with it. This is used so that unrelated types of - * hashes don't accidentally get the same address structure. The type will be - * one of the SPX_ADDR_TYPE constants - */ -void set_type(uint32_t addr[8], uint32_t type) { - ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; -} - -/* - * Copy the layer and tree fields of the address structure. This is used - * when we're doing multiple types of hashes within the same Merkle tree - */ -void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { - memcpy( out, in, SPX_OFFSET_TREE + 8 ); -} - -/* These functions are used for OTS addresses. */ - -/* - * Specify which Merkle leaf we're working on; that is, which OTS keypair - * we're talking about. - */ -void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { - ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; -} - -/* - * Copy the layer, tree and keypair fields of the address structure. This is - * used when we're doing multiple things within the same OTS keypair - */ -void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { - memcpy( out, in, SPX_OFFSET_TREE + 8 ); - ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; -} - -/* - * Specify which Merkle chain within the OTS we're working with - * (the chain address) - */ -void set_chain_addr(uint32_t addr[8], uint32_t chain) { - ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; -} - -/* - * Specify where in the Merkle chain we are -* (the hash address) - */ -void set_hash_addr(uint32_t addr[8], uint32_t hash) { - ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; -} - -/* These functions are used for all hash tree addresses (including FORS). */ - -/* - * Specify the height of the node in the Merkle/FORS tree we are in - * (the tree height) - */ -void set_tree_height(uint32_t addr[8], uint32_t tree_height) { - ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; -} - -/* - * Specify the distance from the left edge of the node in the Merkle/FORS tree - * (the tree index) - */ -void set_tree_index(uint32_t addr[8], uint32_t tree_index) { - u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/address.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/address.h deleted file mode 100644 index 24a84eb40c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/address.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef SPX_ADDRESS_H -#define SPX_ADDRESS_H - -#include - -#include "params.h" - -/* The hash types that are passed to set_type */ -#define SPX_ADDR_TYPE_WOTS 0 -#define SPX_ADDR_TYPE_WOTSPK 1 -#define SPX_ADDR_TYPE_HASHTREE 2 -#define SPX_ADDR_TYPE_FORSTREE 3 -#define SPX_ADDR_TYPE_FORSPK 4 -#define SPX_ADDR_TYPE_WOTSPRF 5 -#define SPX_ADDR_TYPE_FORSPRF 6 - -#define set_layer_addr SPX_NAMESPACE(set_layer_addr) -void set_layer_addr(uint32_t addr[8], uint32_t layer); - -#define set_tree_addr SPX_NAMESPACE(set_tree_addr) -void set_tree_addr(uint32_t addr[8], uint64_t tree); - -#define set_type SPX_NAMESPACE(set_type) -void set_type(uint32_t addr[8], uint32_t type); - -/* Copies the layer and tree part of one address into the other */ -#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) -void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for WOTS and FORS addresses. */ - -#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) -void set_keypair_addr(uint32_t addr[8], uint32_t keypair); - -#define set_chain_addr SPX_NAMESPACE(set_chain_addr) -void set_chain_addr(uint32_t addr[8], uint32_t chain); - -#define set_hash_addr SPX_NAMESPACE(set_hash_addr) -void set_hash_addr(uint32_t addr[8], uint32_t hash); - -#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) -void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for all hash tree addresses (including FORS). */ - -#define set_tree_height SPX_NAMESPACE(set_tree_height) -void set_tree_height(uint32_t addr[8], uint32_t tree_height); - -#define set_tree_index SPX_NAMESPACE(set_tree_index) -void set_tree_index(uint32_t addr[8], uint32_t tree_index); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/api.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/api.h deleted file mode 100644 index c3c3bce6c1..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/api.h +++ /dev/null @@ -1,77 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256SROBUST_AVX2_API_H -#define PQCLEAN_SPHINCSSHAKE256SROBUST_AVX2_API_H - -#include -#include - -#define PQCLEAN_SPHINCSSHAKE256SROBUST_AVX2_CRYPTO_ALGNAME "SPHINCS+-shake-256s-robust" - -#define PQCLEAN_SPHINCSSHAKE256SROBUST_AVX2_CRYPTO_SECRETKEYBYTES 128 -#define PQCLEAN_SPHINCSSHAKE256SROBUST_AVX2_CRYPTO_PUBLICKEYBYTES 64 -#define PQCLEAN_SPHINCSSHAKE256SROBUST_AVX2_CRYPTO_BYTES 29792 - -#define PQCLEAN_SPHINCSSHAKE256SROBUST_AVX2_CRYPTO_SEEDBYTES 96 - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256SROBUST_AVX2_crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256SROBUST_AVX2_crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256SROBUST_AVX2_crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256SROBUST_AVX2_crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHAKE256SROBUST_AVX2_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHAKE256SROBUST_AVX2_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSSHAKE256SROBUST_AVX2_crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE256SROBUST_AVX2_crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, - const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSSHAKE256SROBUST_AVX2_crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE256SROBUST_AVX2_crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk); -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/context.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/context.h deleted file mode 100644 index 6e0a33f3b7..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/context.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef SPX_CONTEXT_H -#define SPX_CONTEXT_H - -#include - -#include "params.h" - -typedef struct { - uint8_t pub_seed[SPX_N]; - uint8_t sk_seed[SPX_N]; -} spx_ctx; - -#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) -void initialize_hash_function(spx_ctx *ctx); - -#define free_hash_function SPX_NAMESPACE(free_hash_function) -void free_hash_function(spx_ctx *ctx); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/context_shake.c b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/context_shake.c deleted file mode 100644 index 9614a103d3..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/context_shake.c +++ /dev/null @@ -1,12 +0,0 @@ -#include "context.h" - -/* For SHAKE256, there is no immediate reason to initialize at the start, - so this function is an empty operation. */ -void initialize_hash_function(spx_ctx *ctx) { - (void)ctx; /* Suppress an 'unused parameter' warning. */ -} - -// in case the hash function api is heap-based. -void free_hash_function(spx_ctx *ctx) { - (void)ctx; -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/fips202x4.c b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/fips202x4.c deleted file mode 100644 index 1e06fef186..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/fips202x4.c +++ /dev/null @@ -1,210 +0,0 @@ -#include -#include -#include - -#include "fips202.h" -#include "fips202x4.h" - -#define NROUNDS 24 -#define ROL(a, offset) (((a) << (offset)) ^ ((a) >> (64-(offset)))) - -static uint64_t load64(const unsigned char *x) { - unsigned long long r = 0, i; - - for (i = 0; i < 8; ++i) { - r |= (unsigned long long)x[i] << 8 * i; - } - return r; -} - -static void store64(uint8_t *x, uint64_t u) { - unsigned int i; - - for (i = 0; i < 8; ++i) { - x[i] = (uint8_t)u; - u >>= 8; - } -} - -/* Use implementation from the Keccak Code Package */ -extern void KeccakP1600times4_PermuteAll_24rounds(__m256i *s); -#define KeccakF1600_StatePermute4x KeccakP1600times4_PermuteAll_24rounds - -static void keccak_absorb4x(__m256i *s, - unsigned int r, - const unsigned char *m0, - const unsigned char *m1, - const unsigned char *m2, - const unsigned char *m3, - unsigned long long int mlen, - unsigned char p) { - unsigned long long i; - unsigned char t0[200]; - unsigned char t1[200]; - unsigned char t2[200]; - unsigned char t3[200]; - - unsigned long long *ss = (unsigned long long *)s; - - - while (mlen >= r) { - for (i = 0; i < r / 8; ++i) { - ss[4 * i + 0] ^= load64(m0 + 8 * i); - ss[4 * i + 1] ^= load64(m1 + 8 * i); - ss[4 * i + 2] ^= load64(m2 + 8 * i); - ss[4 * i + 3] ^= load64(m3 + 8 * i); - } - - KeccakF1600_StatePermute4x(s); - mlen -= r; - m0 += r; - m1 += r; - m2 += r; - m3 += r; - } - - for (i = 0; i < r; ++i) { - t0[i] = 0; - t1[i] = 0; - t2[i] = 0; - t3[i] = 0; - } - for (i = 0; i < mlen; ++i) { - t0[i] = m0[i]; - t1[i] = m1[i]; - t2[i] = m2[i]; - t3[i] = m3[i]; - } - - t0[i] = p; - t1[i] = p; - t2[i] = p; - t3[i] = p; - - t0[r - 1] |= 128; - t1[r - 1] |= 128; - t2[r - 1] |= 128; - t3[r - 1] |= 128; - - for (i = 0; i < r / 8; ++i) { - ss[4 * i + 0] ^= load64(t0 + 8 * i); - ss[4 * i + 1] ^= load64(t1 + 8 * i); - ss[4 * i + 2] ^= load64(t2 + 8 * i); - ss[4 * i + 3] ^= load64(t3 + 8 * i); - } -} - - -static void keccak_squeezeblocks4x(unsigned char *h0, - unsigned char *h1, - unsigned char *h2, - unsigned char *h3, - unsigned long long int nblocks, - __m256i *s, - unsigned int r) { - unsigned int i; - - unsigned long long *ss = (unsigned long long *)s; - - while (nblocks > 0) { - KeccakF1600_StatePermute4x(s); - for (i = 0; i < (r >> 3); i++) { - store64(h0 + 8 * i, ss[4 * i + 0]); - store64(h1 + 8 * i, ss[4 * i + 1]); - store64(h2 + 8 * i, ss[4 * i + 2]); - store64(h3 + 8 * i, ss[4 * i + 3]); - } - h0 += r; - h1 += r; - h2 += r; - h3 += r; - nblocks--; - } -} - - - -void shake128x4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, unsigned long long outlen, - unsigned char *in0, - unsigned char *in1, - unsigned char *in2, - unsigned char *in3, unsigned long long inlen) { - __m256i s[25]; - unsigned char t0[SHAKE128_RATE]; - unsigned char t1[SHAKE128_RATE]; - unsigned char t2[SHAKE128_RATE]; - unsigned char t3[SHAKE128_RATE]; - unsigned int i; - - /* zero state */ - for (i = 0; i < 25; i++) { - s[i] = _mm256_xor_si256(s[i], s[i]); - } - - /* absorb 4 message of identical length in parallel */ - keccak_absorb4x(s, SHAKE128_RATE, in0, in1, in2, in3, inlen, 0x1F); - - /* Squeeze output */ - keccak_squeezeblocks4x(out0, out1, out2, out3, outlen / SHAKE128_RATE, s, SHAKE128_RATE); - - out0 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; - out1 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; - out2 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; - out3 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; - - if (outlen % SHAKE128_RATE) { - keccak_squeezeblocks4x(t0, t1, t2, t3, 1, s, SHAKE128_RATE); - for (i = 0; i < outlen % SHAKE128_RATE; i++) { - out0[i] = t0[i]; - out1[i] = t1[i]; - out2[i] = t2[i]; - out3[i] = t3[i]; - } - } -} - - -void shake256x4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, unsigned long long outlen, - unsigned char *in0, - unsigned char *in1, - unsigned char *in2, - unsigned char *in3, unsigned long long inlen) { - __m256i s[25]; - unsigned char t0[SHAKE256_RATE]; - unsigned char t1[SHAKE256_RATE]; - unsigned char t2[SHAKE256_RATE]; - unsigned char t3[SHAKE256_RATE]; - unsigned int i; - - /* zero state */ - for (i = 0; i < 25; i++) { - s[i] = _mm256_xor_si256(s[i], s[i]); - } - - /* absorb 4 message of identical length in parallel */ - keccak_absorb4x(s, SHAKE256_RATE, in0, in1, in2, in3, inlen, 0x1F); - - /* Squeeze output */ - keccak_squeezeblocks4x(out0, out1, out2, out3, outlen / SHAKE256_RATE, s, SHAKE256_RATE); - - out0 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; - out1 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; - out2 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; - out3 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; - - if (outlen % SHAKE256_RATE) { - keccak_squeezeblocks4x(t0, t1, t2, t3, 1, s, SHAKE256_RATE); - for (i = 0; i < outlen % SHAKE256_RATE; i++) { - out0[i] = t0[i]; - out1[i] = t1[i]; - out2[i] = t2[i]; - out3[i] = t3[i]; - } - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/fips202x4.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/fips202x4.h deleted file mode 100644 index 2b93c9cd0d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/fips202x4.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef SPX_FIPS202X4_H -#define SPX_FIPS202X4_H - -#include - -#include "params.h" - -#define shake128x4 SPX_NAMESPACE(shake128x4) -void shake128x4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, unsigned long long outlen, - unsigned char *in0, - unsigned char *in1, - unsigned char *in2, - unsigned char *in3, unsigned long long inlen); - -#define shake256x4 SPX_NAMESPACE(shake256x4) -void shake256x4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, unsigned long long outlen, - unsigned char *in0, - unsigned char *in1, - unsigned char *in2, - unsigned char *in3, unsigned long long inlen); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/fors.c b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/fors.c deleted file mode 100644 index f1b0639cfc..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/fors.c +++ /dev/null @@ -1,202 +0,0 @@ -#include -#include -#include - -#include "fors.h" - -#include "address.h" -#include "hash.h" -#include "hashx4.h" -#include "thash.h" -#include "thashx4.h" -#include "utils.h" -#include "utilsx4.h" - -static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, - uint32_t fors_leaf_addr[8]) { - prf_addr(sk, ctx, fors_leaf_addr); -} - -static void fors_gen_skx4(unsigned char *sk0, - unsigned char *sk1, - unsigned char *sk2, - unsigned char *sk3, const spx_ctx *ctx, - uint32_t fors_leaf_addrx4[4 * 8]) { - prf_addrx4(sk0, sk1, sk2, sk3, - ctx, fors_leaf_addrx4); -} - -static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, - const spx_ctx *ctx, - uint32_t fors_leaf_addr[8]) { - thash(leaf, sk, 1, ctx, fors_leaf_addr); -} - -static void fors_sk_to_leafx4(unsigned char *leaf0, - unsigned char *leaf1, - unsigned char *leaf2, - unsigned char *leaf3, - const unsigned char *sk0, - const unsigned char *sk1, - const unsigned char *sk2, - const unsigned char *sk3, - const spx_ctx *ctx, - uint32_t fors_leaf_addrx4[4 * 8]) { - thashx4(leaf0, leaf1, leaf2, leaf3, - sk0, sk1, sk2, sk3, - 1, ctx, fors_leaf_addrx4); -} - -struct fors_gen_leaf_info { - uint32_t leaf_addrx[4 * 8]; -}; - -static void fors_gen_leafx4(unsigned char *leaf, - const spx_ctx *ctx, - uint32_t addr_idx, void *info) { - struct fors_gen_leaf_info *fors_info = info; - uint32_t *fors_leaf_addrx4 = fors_info->leaf_addrx; - unsigned int j; - - /* Only set the parts that the caller doesn't set */ - for (j = 0; j < 4; j++) { - set_tree_index(fors_leaf_addrx4 + j * 8, addr_idx + j); - set_type(fors_leaf_addrx4 + j * 8, SPX_ADDR_TYPE_FORSPRF); - } - - fors_gen_skx4(leaf + 0 * SPX_N, - leaf + 1 * SPX_N, - leaf + 2 * SPX_N, - leaf + 3 * SPX_N, - ctx, fors_leaf_addrx4); - - for (j = 0; j < 4; j++) { - set_type(fors_leaf_addrx4 + j * 8, SPX_ADDR_TYPE_FORSTREE); - } - - fors_sk_to_leafx4(leaf + 0 * SPX_N, - leaf + 1 * SPX_N, - leaf + 2 * SPX_N, - leaf + 3 * SPX_N, - leaf + 0 * SPX_N, - leaf + 1 * SPX_N, - leaf + 2 * SPX_N, - leaf + 3 * SPX_N, - ctx, fors_leaf_addrx4); -} - -/** - * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - * Assumes indices has space for SPX_FORS_TREES integers. - */ -static void message_to_indices(uint32_t *indices, const unsigned char *m) { - unsigned int i, j; - unsigned int offset = 0; - - for (i = 0; i < SPX_FORS_TREES; i++) { - indices[i] = 0; - for (j = 0; j < SPX_FORS_HEIGHT; j++) { - indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); - offset++; - } - } -} - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -void fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]) { - uint32_t indices[SPX_FORS_TREES]; - unsigned char roots[SPX_FORS_TREES * SPX_N]; - uint32_t fors_tree_addr[4 * 8] = {0}; - struct fors_gen_leaf_info fors_info = {0}; - uint32_t *fors_leaf_addr = fors_info.leaf_addrx; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - for (i = 0; i < 4; i++) { - copy_keypair_addr(fors_tree_addr + 8 * i, fors_addr); - set_type(fors_tree_addr + 8 * i, SPX_ADDR_TYPE_FORSTREE); - copy_keypair_addr(fors_leaf_addr + 8 * i, fors_addr); - } - copy_keypair_addr(fors_pk_addr, fors_addr); - set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < SPX_FORS_TREES; i++) { - idx_offset = i * (1 << SPX_FORS_HEIGHT); - - set_tree_height(fors_tree_addr, 0); - set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Include the secret key part that produces the selected leaf node. */ - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); - fors_gen_sk(sig, ctx, fors_tree_addr); - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); - sig += SPX_N; - - /* Compute the authentication path for this leaf node. */ - treehashx4(roots + i * SPX_N, sig, ctx, - indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx4, - fors_tree_addr, &fors_info); - - sig += SPX_N * SPX_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); -} - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -void fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]) { - uint32_t indices[SPX_FORS_TREES]; - unsigned char roots[SPX_FORS_TREES * SPX_N]; - unsigned char leaf[SPX_N]; - uint32_t fors_tree_addr[8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - copy_keypair_addr(fors_tree_addr, fors_addr); - copy_keypair_addr(fors_pk_addr, fors_addr); - - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); - set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < SPX_FORS_TREES; i++) { - idx_offset = i * (1 << SPX_FORS_HEIGHT); - - set_tree_height(fors_tree_addr, 0); - set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Derive the leaf from the included secret key part. */ - fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); - sig += SPX_N; - - /* Derive the corresponding root node of this tree. */ - compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, - sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); - sig += SPX_N * SPX_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/fors.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/fors.h deleted file mode 100644 index 509140a178..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/fors.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef SPX_FORS_H -#define SPX_FORS_H - -#include - -#include "context.h" -#include "params.h" - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -#define fors_sign SPX_NAMESPACE(fors_sign) -void fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]); - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) -void fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/hash.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/hash.h deleted file mode 100644 index f7c87d4c3c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/hash.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef SPX_HASH_H -#define SPX_HASH_H - -#include -#include - -#include "context.h" -#include "params.h" - -#define prf_addr SPX_NAMESPACE(prf_addr) -void prf_addr(unsigned char *out, const spx_ctx *ctx, - const uint32_t addr[8]); - -#define gen_message_random SPX_NAMESPACE(gen_message_random) -void gen_message_random(unsigned char *R, const unsigned char *sk_prf, - const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx); - -#define hash_message SPX_NAMESPACE(hash_message) -void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx); - - - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/hash_shake.c b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/hash_shake.c deleted file mode 100644 index ff5e7ec918..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/hash_shake.c +++ /dev/null @@ -1,83 +0,0 @@ -#include -#include - -#include "hash.h" - -#include "address.h" -#include "fips202.h" -#include "params.h" -#include "utils.h" - -/* - * Computes PRF(pk_seed, sk_seed, addr) - */ -void prf_addr(unsigned char *out, const spx_ctx *ctx, - const uint32_t addr[8]) { - unsigned char buf[2 * SPX_N + SPX_ADDR_BYTES]; - - memcpy(buf, ctx->pub_seed, SPX_N); - memcpy(buf + SPX_N, addr, SPX_ADDR_BYTES); - memcpy(buf + SPX_N + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); - - shake256(out, SPX_N, buf, 2 * SPX_N + SPX_ADDR_BYTES); -} - -/** - * Computes the message-dependent randomness R, using a secret seed and an - * optional randomization value as well as the message. - */ -void gen_message_random(unsigned char *R, const unsigned char *sk_prf, - const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx) { - (void)ctx; - shake256incctx s_inc; - - shake256_inc_init(&s_inc); - shake256_inc_absorb(&s_inc, sk_prf, SPX_N); - shake256_inc_absorb(&s_inc, optrand, SPX_N); - shake256_inc_absorb(&s_inc, m, mlen); - shake256_inc_finalize(&s_inc); - shake256_inc_squeeze(R, SPX_N, &s_inc); - shake256_inc_ctx_release(&s_inc); -} - -/** - * Computes the message hash using R, the public key, and the message. - * Outputs the message digest and the index of the leaf. The index is split in - * the tree index and the leaf index, for convenient copying to an address. - */ -void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx) { - (void)ctx; -#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) -#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) -#define SPX_LEAF_BITS SPX_TREE_HEIGHT -#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) -#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) - - unsigned char buf[SPX_DGST_BYTES]; - unsigned char *bufp = buf; - shake256incctx s_inc; - - shake256_inc_init(&s_inc); - shake256_inc_absorb(&s_inc, R, SPX_N); - shake256_inc_absorb(&s_inc, pk, SPX_PK_BYTES); - shake256_inc_absorb(&s_inc, m, mlen); - shake256_inc_finalize(&s_inc); - shake256_inc_squeeze(buf, SPX_DGST_BYTES, &s_inc); - shake256_inc_ctx_release(&s_inc); - - memcpy(digest, bufp, SPX_FORS_MSG_BYTES); - bufp += SPX_FORS_MSG_BYTES; - - - *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); - *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); - bufp += SPX_TREE_BYTES; - - *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); - *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/hash_shakex4.c b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/hash_shakex4.c deleted file mode 100644 index bbd22eb117..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/hash_shakex4.c +++ /dev/null @@ -1,64 +0,0 @@ -#include -#include - -#include "hashx4.h" - -#include "address.h" -#include "fips202x4.h" -#include "params.h" - -extern void KeccakP1600times4_PermuteAll_24rounds(__m256i *s); - -/* - * 4-way parallel version of prf_addr; takes 4x as much input and output - */ -void prf_addrx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const spx_ctx *ctx, - const uint32_t addrx4[4 * 8]) { - /* As we write and read only a few quadwords, it is more efficient to - * build and extract from the fourway SHAKE256 state by hand. */ - __m256i state[25]; - - for (int i = 0; i < SPX_N / 8; i++) { - state[i] = _mm256_set1_epi64x(((int64_t *)ctx->pub_seed)[i]); - } - for (int i = 0; i < 4; i++) { - state[SPX_N / 8 + i] = _mm256_set_epi32( - (int)addrx4[3 * 8 + 1 + 2 * i], - (int)addrx4[3 * 8 + 2 * i], - (int)addrx4[2 * 8 + 1 + 2 * i], - (int)addrx4[2 * 8 + 2 * i], - (int)addrx4[8 + 1 + 2 * i], - (int)addrx4[8 + 2 * i], - (int)addrx4[1 + 2 * i], - (int)addrx4[2 * i] - ); - } - for (int i = 0; i < SPX_N / 8; i++) { - state[SPX_N / 8 + i + 4] = _mm256_set1_epi64x(((int64_t *)ctx->sk_seed)[i]); - } - - /* SHAKE domain separator and padding. */ - state[SPX_N / 4 + 4] = _mm256_set1_epi64x(0x1f); - for (int i = SPX_N / 4 + 5; i < 16; i++) { - state[i] = _mm256_set1_epi64x(0); - } - // shift unsigned and then cast to avoid UB - state[16] = _mm256_set1_epi64x((long long)(0x80ULL << 56)); - - for (int i = 17; i < 25; i++) { - state[i] = _mm256_set1_epi64x(0); - } - - KeccakP1600times4_PermuteAll_24rounds(&state[0]); - - for (int i = 0; i < SPX_N / 8; i++) { - ((int64_t *)out0)[i] = _mm256_extract_epi64(state[i], 0); - ((int64_t *)out1)[i] = _mm256_extract_epi64(state[i], 1); - ((int64_t *)out2)[i] = _mm256_extract_epi64(state[i], 2); - ((int64_t *)out3)[i] = _mm256_extract_epi64(state[i], 3); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/hashx4.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/hashx4.h deleted file mode 100644 index 3751a0ebd0..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/hashx4.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef SPX_HASHX4_H -#define SPX_HASHX4_H - -#include - -#include "context.h" -#include "params.h" - -#define prf_addrx4 SPX_NAMESPACE(prf_addrx4) -void prf_addrx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const spx_ctx *ctx, - const uint32_t addrx4[4 * 8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/merkle.c b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/merkle.c deleted file mode 100644 index f57811c1ac..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/merkle.c +++ /dev/null @@ -1,64 +0,0 @@ -#include -#include - -#include "merkle.h" - -#include "address.h" -#include "params.h" -#include "utils.h" -#include "utilsx4.h" -#include "wots.h" -#include "wotsx4.h" - -/* - * This generates a Merkle signature (WOTS signature followed by the Merkle - * authentication path). - */ -void merkle_sign(uint8_t *sig, unsigned char *root, - const spx_ctx *ctx, - uint32_t wots_addr[8], uint32_t tree_addr[8], - uint32_t idx_leaf) { - unsigned char *auth_path = sig + SPX_WOTS_BYTES; - uint32_t tree_addrx4[4 * 8] = { 0 }; - int j; - struct leaf_info_x4 info = { 0 }; - unsigned steps[ SPX_WOTS_LEN ]; - - info.wots_sig = sig; - chain_lengths(steps, root); - info.wots_steps = steps; - - for (j = 0; j < 4; j++) { - set_type(&tree_addrx4[8 * j], SPX_ADDR_TYPE_HASHTREE); - set_type(&info.leaf_addr[8 * j], SPX_ADDR_TYPE_WOTS); - set_type(&info.pk_addr[8 * j], SPX_ADDR_TYPE_WOTSPK); - copy_subtree_addr(&tree_addrx4[8 * j], tree_addr); - copy_subtree_addr(&info.leaf_addr[8 * j], wots_addr); - copy_subtree_addr(&info.pk_addr[8 * j], wots_addr); - } - - info.wots_sign_leaf = idx_leaf; - - treehashx4(root, auth_path, ctx, - idx_leaf, 0, - SPX_TREE_HEIGHT, - wots_gen_leafx4, - tree_addrx4, &info); -} - -/* Compute root node of the top-most subtree. */ -void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { - /* We do not need the auth path in key generation, but it simplifies the - code to have just one treehash routine that computes both root and path - in one function. */ - unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; - uint32_t top_tree_addr[8] = {0}; - uint32_t wots_addr[8] = {0}; - - set_layer_addr(top_tree_addr, SPX_D - 1); - set_layer_addr(wots_addr, SPX_D - 1); - - merkle_sign(auth_path, root, ctx, - wots_addr, top_tree_addr, - ~0U /* ~0 means "don't bother generating an auth path */ ); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/merkle.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/merkle.h deleted file mode 100644 index 769cf2e970..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/merkle.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef MERKLE_H_ -#define MERKLE_H_ - -#include - -#include "context.h" -#include "params.h" - -/* Generate a Merkle signature (WOTS signature followed by the Merkle */ -/* authentication path) */ -#define merkle_sign SPX_NAMESPACE(merkle_sign) -void merkle_sign(uint8_t *sig, unsigned char *root, - const spx_ctx *ctx, - uint32_t wots_addr[8], uint32_t tree_addr[8], - uint32_t idx_leaf); - -/* Compute the root node of the top-most subtree. */ -#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) -void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); - -#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/nistapi.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/nistapi.h deleted file mode 100644 index 3cb71afad4..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/nistapi.h +++ /dev/null @@ -1,87 +0,0 @@ -#ifndef SPX_API_H -#define SPX_API_H - -#include -#include - -#include "params.h" - -#define CRYPTO_ALGNAME "SPHINCS+" - -#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES -#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES -#define CRYPTO_BYTES SPX_BYTES -#define CRYPTO_SEEDBYTES (3*SPX_N) - -/* - * Returns the length of a secret key, in bytes - */ -#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) -size_t crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) -size_t crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) -size_t crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) -size_t crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) -int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) -int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) -int crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) -int crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -#define crypto_sign SPX_NAMESPACE(crypto_sign) -int crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) -int crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/params.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/params.h deleted file mode 100644 index 81887bffca..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/params.h +++ /dev/null @@ -1,56 +0,0 @@ -#ifndef SPX_PARAMS_H -#define SPX_PARAMS_H - -#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSSHAKE256SROBUST_AVX2_##s - -/* Hash output length in bytes. */ -#define SPX_N 32 -/* Height of the hypertree. */ -#define SPX_FULL_HEIGHT 64 -/* Number of subtree layer. */ -#define SPX_D 8 -/* FORS tree dimensions. */ -#define SPX_FORS_HEIGHT 14 -#define SPX_FORS_TREES 22 -/* Winternitz parameter, */ -#define SPX_WOTS_W 16 - -/* The hash function is defined by linking a different hash.c file, as opposed - to setting a #define constant. */ - -/* For clarity */ -#define SPX_ADDR_BYTES 32 - -/* WOTS parameters. */ -#define SPX_WOTS_LOGW 4 - -#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) - -/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#define SPX_WOTS_LEN2 3 - -#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) -#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) -#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES - -/* Subtree size. */ -#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) - -//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT -// #error SPX_D should always divide SPX_FULL_HEIGHT -//#endif - -/* FORS parameters. */ -#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) -#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) -#define SPX_FORS_PK_BYTES SPX_N - -/* Resulting SPX sizes. */ -#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ - SPX_FULL_HEIGHT * SPX_N) -#define SPX_PK_BYTES (2 * SPX_N) -#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) - -#include "shake_offsets.h" - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/shake_offsets.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/shake_offsets.h deleted file mode 100644 index 6b28d95d91..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/shake_offsets.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef SHAKE_OFFSETS_H_ -#define SHAKE_OFFSETS_H_ - -/* - * Offsets of various fields in the address structure when we use SHAKE as - * the Sphincs+ hash function - */ - -#define SPX_OFFSET_LAYER 3 /* The byte used to specify the Merkle tree layer */ -#define SPX_OFFSET_TREE 8 /* The start of the 8 byte field used to specify the tree */ -#define SPX_OFFSET_TYPE 19 /* The byte used to specify the hash type (reason) */ -#define SPX_OFFSET_KP_ADDR2 22 /* The high byte used to specify the key pair (which one-time signature) */ -#define SPX_OFFSET_KP_ADDR1 23 /* The low byte used to specify the key pair */ -#define SPX_OFFSET_CHAIN_ADDR 27 /* The byte used to specify the chain address (which Winternitz chain) */ -#define SPX_OFFSET_HASH_ADDR 31 /* The byte used to specify the hash address (where in the Winternitz chain) */ -#define SPX_OFFSET_TREE_HGT 27 /* The byte used to specify the height of this node in the FORS or Merkle tree */ -#define SPX_OFFSET_TREE_INDEX 28 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ - -#define SPX_SHAKE 1 - -#endif /* SHAKE_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/sign.c b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/sign.c deleted file mode 100644 index 9d0c7d1b22..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/sign.c +++ /dev/null @@ -1,286 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "context.h" -#include "fors.h" -#include "hash.h" -#include "merkle.h" -#include "nistapi.h" -#include "params.h" -#include "randombytes.h" -#include "thash.h" -#include "utils.h" -#include "wots.h" - -/* - * Returns the length of a secret key, in bytes - */ -size_t crypto_sign_secretkeybytes(void) { - return CRYPTO_SECRETKEYBYTES; -} - -/* - * Returns the length of a public key, in bytes - */ -size_t crypto_sign_publickeybytes(void) { - return CRYPTO_PUBLICKEYBYTES; -} - -/* - * Returns the length of a signature, in bytes - */ -size_t crypto_sign_bytes(void) { - return CRYPTO_BYTES; -} - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t crypto_sign_seedbytes(void) { - return CRYPTO_SEEDBYTES; -} - -/* - * Generates an SPX key pair given a seed of length - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed) { - spx_ctx ctx; - - /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ - memcpy(sk, seed, CRYPTO_SEEDBYTES); - - memcpy(pk, sk + 2 * SPX_N, SPX_N); - - memcpy(ctx.pub_seed, pk, SPX_N); - memcpy(ctx.sk_seed, sk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - /* Compute root node of the top-most subtree. */ - merkle_gen_root(sk + 3 * SPX_N, &ctx); - - // cleanup - free_hash_function(&ctx); - - memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); - - return 0; -} - -/* - * Generates an SPX key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { - uint8_t seed[CRYPTO_SEEDBYTES]; - randombytes(seed, CRYPTO_SEEDBYTES); - crypto_sign_seed_keypair(pk, sk, seed); - - return 0; -} - -/** - * Returns an array containing a detached signature. - */ -int crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - spx_ctx ctx; - - const uint8_t *sk_prf = sk + SPX_N; - const uint8_t *pk = sk + 2 * SPX_N; - - uint8_t optrand[SPX_N]; - uint8_t mhash[SPX_FORS_MSG_BYTES]; - uint8_t root[SPX_N]; - uint32_t i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - - memcpy(ctx.sk_seed, sk, SPX_N); - memcpy(ctx.pub_seed, pk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - set_type(wots_addr, SPX_ADDR_TYPE_WOTS); - set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); - - /* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ - randombytes(optrand, SPX_N); - /* Compute the digest randomization value. */ - gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); - - /* Derive the message digest and leaf index from R, PK and M. */ - hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); - sig += SPX_N; - - set_tree_addr(wots_addr, tree); - set_keypair_addr(wots_addr, idx_leaf); - - /* Sign the message hash using FORS. */ - fors_sign(sig, root, mhash, &ctx, wots_addr); - sig += SPX_FORS_BYTES; - - for (i = 0; i < SPX_D; i++) { - set_layer_addr(tree_addr, i); - set_tree_addr(tree_addr, tree); - - copy_subtree_addr(wots_addr, tree_addr); - set_keypair_addr(wots_addr, idx_leaf); - - merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); - sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); - tree = tree >> SPX_TREE_HEIGHT; - } - - free_hash_function(&ctx); - - *siglen = SPX_BYTES; - - return 0; -} - -/** - * Verifies a detached signature and message under a given public key. - */ -int crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk) { - spx_ctx ctx; - const uint8_t *pub_root = pk + SPX_N; - uint8_t mhash[SPX_FORS_MSG_BYTES]; - uint8_t wots_pk[SPX_WOTS_BYTES]; - uint8_t root[SPX_N]; - uint8_t leaf[SPX_N]; - unsigned int i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - if (siglen != SPX_BYTES) { - return -1; - } - - memcpy(ctx.pub_seed, pk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - set_type(wots_addr, SPX_ADDR_TYPE_WOTS); - set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); - set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); - - /* Derive the message digest and leaf index from R || PK || M. */ - /* The additional SPX_N is a result of the hash domain separator. */ - hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); - sig += SPX_N; - - /* Layer correctly defaults to 0, so no need to set_layer_addr */ - set_tree_addr(wots_addr, tree); - set_keypair_addr(wots_addr, idx_leaf); - - fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); - sig += SPX_FORS_BYTES; - - /* For each subtree.. */ - for (i = 0; i < SPX_D; i++) { - set_layer_addr(tree_addr, i); - set_tree_addr(tree_addr, tree); - - copy_subtree_addr(wots_addr, tree_addr); - set_keypair_addr(wots_addr, idx_leaf); - - copy_keypair_addr(wots_pk_addr, wots_addr); - - /* The WOTS public key is only correct if the signature was correct. */ - /* Initially, root is the FORS pk, but on subsequent iterations it is - the root of the subtree below the currently processed subtree. */ - wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); - sig += SPX_WOTS_BYTES; - - /* Compute the leaf node using the WOTS public key. */ - thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); - - /* Compute the root node of this subtree. */ - compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, - &ctx, tree_addr); - sig += SPX_TREE_HEIGHT * SPX_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); - tree = tree >> SPX_TREE_HEIGHT; - } - - // cleanup - free_hash_function(&ctx); - - /* Check if the root node equals the root node in the public key. */ - if (memcmp(root, pub_root, SPX_N) != 0) { - return -1; - } - - return 0; -} - - -/** - * Returns an array containing the signature followed by the message. - */ -int crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk) { - size_t siglen; - - crypto_sign_signature(sm, &siglen, m, mlen, sk); - - memmove(sm + SPX_BYTES, m, mlen); - *smlen = siglen + mlen; - - return 0; -} - -/** - * Verifies a given signature-message pair under a given public key. - */ -int crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk) { - /* The API caller does not necessarily know what size a signature should be - but SPHINCS+ signatures are always exactly SPX_BYTES. */ - if (smlen < SPX_BYTES) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - *mlen = smlen - SPX_BYTES; - - if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - /* If verification was successful, move the message to the right place. */ - memmove(m, sm + SPX_BYTES, *mlen); - - return 0; -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/thash.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/thash.h deleted file mode 100644 index 8687ccfb4d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/thash.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef SPX_THASH_H -#define SPX_THASH_H - -#include "context.h" -#include "params.h" - -#include - -#define thash SPX_NAMESPACE(thash) -void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/thash_shake_robust.c b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/thash_shake_robust.c deleted file mode 100644 index 696d53c5cc..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/thash_shake_robust.c +++ /dev/null @@ -1,31 +0,0 @@ -#include -#include - -#include "thash.h" - -#include "address.h" -#include "params.h" -#include "utils.h" - -#include "fips202.h" - -/** - * Takes an array of inblocks concatenated arrays of SPX_N bytes. - */ -void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]) { - PQCLEAN_VLA(uint8_t, buf, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); - PQCLEAN_VLA(uint8_t, bitmask, inblocks * SPX_N); - unsigned int i; - - memcpy(buf, ctx->pub_seed, SPX_N); - memcpy(buf + SPX_N, addr, SPX_ADDR_BYTES); - - shake256(bitmask, inblocks * SPX_N, buf, SPX_N + SPX_ADDR_BYTES); - - for (i = 0; i < inblocks * SPX_N; i++) { - buf[SPX_N + SPX_ADDR_BYTES + i] = in[i] ^ bitmask[i]; - } - - shake256(out, SPX_N, buf, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/thash_shake_robustx4.c b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/thash_shake_robustx4.c deleted file mode 100644 index ce2946b745..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/thash_shake_robustx4.c +++ /dev/null @@ -1,131 +0,0 @@ -#include -#include - -#include "thashx4.h" - -#include "address.h" -#include "params.h" -#include "utils.h" - -#include "fips202x4.h" - -extern void KeccakP1600times4_PermuteAll_24rounds(__m256i *s); - -/** - * 4-way parallel version of thash; takes 4x as much input and output - */ -void thashx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addrx4[4 * 8]) { - if (inblocks == 1 || inblocks == 2) { - /* As we write and read only a few quadwords, it is more efficient to - * build and extract from the fourway SHAKE256 state by hand. */ - __m256i state[25]; - for (int i = 0; i < SPX_N / 8; i++) { - state[i] = _mm256_set1_epi64x(((int64_t *)ctx->pub_seed)[i]); - } - for (int i = 0; i < 4; i++) { - state[SPX_N / 8 + i] = _mm256_set_epi32( - (int)addrx4[3 * 8 + 1 + 2 * i], - (int)addrx4[3 * 8 + 2 * i], - (int)addrx4[2 * 8 + 1 + 2 * i], - (int)addrx4[2 * 8 + 2 * i], - (int)addrx4[8 + 1 + 2 * i], - (int)addrx4[8 + 2 * i], - (int)addrx4[1 + 2 * i], - (int)addrx4[2 * i] - ); - } - - /* SHAKE domain separator and padding */ - state[SPX_N / 8 + 4] = _mm256_set1_epi64x(0x1f); - for (int i = SPX_N / 8 + 5; i < 16; i++) { - state[i] = _mm256_set1_epi64x(0); - } - state[16] = _mm256_set1_epi64x((long long)(0x80ULL << 56)); - - for (int i = 17; i < 25; i++) { - state[i] = _mm256_set1_epi64x(0); - } - - /* We will permutate state2 with f1600x4 to compute the bitmask, - * but first we'll copy it to state2 which will be used to compute - * the final output, as its input is alsmost identical. */ - __m256i state2[25]; - memcpy(state2, state, 800); - - KeccakP1600times4_PermuteAll_24rounds(&state[0]); - - /* By copying from state, state2 already contains the pub_seed - * and addres. We just need to copy in the input blocks xorred with - * the bitmask we just computed. */ - for (unsigned int i = 0; i < (SPX_N / 8) * inblocks; i++) { - state2[SPX_N / 8 + 4 + i] = _mm256_xor_si256( - state[i], - _mm256_set_epi64x( - ((int64_t *)in3)[i], - ((int64_t *)in2)[i], - ((int64_t *)in1)[i], - ((int64_t *)in0)[i] - ) - ); - } - - /* Domain separator and start of padding. Note that the quadwords - * around are already zeroed for state from which we copied. - * We do a XOR instead of a set as this might be the 16th quadword - * when N=32 and inblocks=2, which already contains the end - * of the padding. */ - state2[(SPX_N / 8) * (1 + inblocks) + 4] = _mm256_xor_si256( - state2[(SPX_N / 8) * (1 + inblocks) + 4], - _mm256_set1_epi64x(0x1f) - ); - - KeccakP1600times4_PermuteAll_24rounds(&state2[0]); - - for (int i = 0; i < SPX_N / 8; i++) { - ((int64_t *)out0)[i] = _mm256_extract_epi64(state2[i], 0); - ((int64_t *)out1)[i] = _mm256_extract_epi64(state2[i], 1); - ((int64_t *)out2)[i] = _mm256_extract_epi64(state2[i], 2); - ((int64_t *)out3)[i] = _mm256_extract_epi64(state2[i], 3); - } - } else { - PQCLEAN_VLA(unsigned char, buf0, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); - PQCLEAN_VLA(unsigned char, buf1, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); - PQCLEAN_VLA(unsigned char, buf2, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); - PQCLEAN_VLA(unsigned char, buf3, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); - PQCLEAN_VLA(unsigned char, bitmask0, inblocks * SPX_N); - PQCLEAN_VLA(unsigned char, bitmask1, inblocks * SPX_N); - PQCLEAN_VLA(unsigned char, bitmask2, inblocks * SPX_N); - PQCLEAN_VLA(unsigned char, bitmask3, inblocks * SPX_N); - unsigned int i; - - memcpy(buf0, ctx->pub_seed, SPX_N); - memcpy(buf1, ctx->pub_seed, SPX_N); - memcpy(buf2, ctx->pub_seed, SPX_N); - memcpy(buf3, ctx->pub_seed, SPX_N); - memcpy(buf0 + SPX_N, addrx4 + 0 * 8, SPX_ADDR_BYTES); - memcpy(buf1 + SPX_N, addrx4 + 1 * 8, SPX_ADDR_BYTES); - memcpy(buf2 + SPX_N, addrx4 + 2 * 8, SPX_ADDR_BYTES); - memcpy(buf3 + SPX_N, addrx4 + 3 * 8, SPX_ADDR_BYTES); - - shake256x4(bitmask0, bitmask1, bitmask2, bitmask3, inblocks * SPX_N, - buf0, buf1, buf2, buf3, SPX_N + SPX_ADDR_BYTES); - - for (i = 0; i < inblocks * SPX_N; i++) { - buf0[SPX_N + SPX_ADDR_BYTES + i] = in0[i] ^ bitmask0[i]; - buf1[SPX_N + SPX_ADDR_BYTES + i] = in1[i] ^ bitmask1[i]; - buf2[SPX_N + SPX_ADDR_BYTES + i] = in2[i] ^ bitmask2[i]; - buf3[SPX_N + SPX_ADDR_BYTES + i] = in3[i] ^ bitmask3[i]; - } - - shake256x4(out0, out1, out2, out3, SPX_N, - buf0, buf1, buf2, buf3, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/thashx4.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/thashx4.h deleted file mode 100644 index 64798a3727..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/thashx4.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef SPX_THASHX4_H -#define SPX_THASHX4_H - -#include - -#include "context.h" -#include "params.h" - -#define thashx4 SPX_NAMESPACE(thashx4) -void thashx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const unsigned char *in0, - const unsigned char *in1, - const unsigned char *in2, - const unsigned char *in3, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addrx4[4 * 8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/utils.c b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/utils.c deleted file mode 100644 index 177b541fb9..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/utils.c +++ /dev/null @@ -1,148 +0,0 @@ -#include - -#include "utils.h" - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "thash.h" - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void ull_to_bytes(unsigned char *out, unsigned int outlen, - unsigned long long in) { - int i; - - /* Iterate over out in decreasing order, for big-endianness. */ - for (i = (signed int)outlen - 1; i >= 0; i--) { - out[i] = in & 0xff; - in = in >> 8; - } -} - -void u32_to_bytes(unsigned char *out, uint32_t in) { - out[0] = (unsigned char)(in >> 24); - out[1] = (unsigned char)(in >> 16); - out[2] = (unsigned char)(in >> 8); - out[3] = (unsigned char)in; -} - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { - unsigned long long retval = 0; - unsigned int i; - - for (i = 0; i < inlen; i++) { - retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); - } - return retval; -} - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void compute_root(unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const spx_ctx *ctx, uint32_t addr[8]) { - uint32_t i; - unsigned char buffer[2 * SPX_N]; - - /* If leaf_idx is odd (last bit = 1), current path element is a right child - and auth_path has to go left. Otherwise it is the other way around. */ - if (leaf_idx & 1) { - memcpy(buffer + SPX_N, leaf, SPX_N); - memcpy(buffer, auth_path, SPX_N); - } else { - memcpy(buffer, leaf, SPX_N); - memcpy(buffer + SPX_N, auth_path, SPX_N); - } - auth_path += SPX_N; - - for (i = 0; i < tree_height - 1; i++) { - leaf_idx >>= 1; - idx_offset >>= 1; - /* Set the address of the node we're creating. */ - set_tree_height(addr, i + 1); - set_tree_index(addr, leaf_idx + idx_offset); - - /* Pick the right or left neighbor, depending on parity of the node. */ - if (leaf_idx & 1) { - thash(buffer + SPX_N, buffer, 2, ctx, addr); - memcpy(buffer, auth_path, SPX_N); - } else { - thash(buffer, buffer, 2, ctx, addr); - memcpy(buffer + SPX_N, auth_path, SPX_N); - } - auth_path += SPX_N; - } - - /* The last iteration is exceptional; we do not copy an auth_path node. */ - leaf_idx >>= 1; - idx_offset >>= 1; - set_tree_height(addr, tree_height); - set_tree_index(addr, leaf_idx + idx_offset); - thash(root, buffer, 2, ctx, addr); -} - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const spx_ctx * /* ctx */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), - uint32_t tree_addr[8]) { - PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); - PQCLEAN_VLA(unsigned int, heights, tree_height + 1); - unsigned int offset = 0; - uint32_t idx; - uint32_t tree_idx; - - for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { - /* Add the next leaf node to the stack. */ - gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); - offset++; - heights[offset - 1] = 0; - - /* If this is a node we need for the auth path.. */ - if ((leaf_idx ^ 0x1) == idx) { - memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); - } - - /* While the top-most nodes are of equal height.. */ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { - /* Compute index of the new node, in the next layer. */ - tree_idx = (idx >> (heights[offset - 1] + 1)); - - /* Set the address of the node we're creating. */ - set_tree_height(tree_addr, heights[offset - 1] + 1); - set_tree_index(tree_addr, - tree_idx + (idx_offset >> (heights[offset - 1] + 1))); - /* Hash the top-most nodes from the stack together. */ - thash(stack + (offset - 2)*SPX_N, - stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); - offset--; - /* Note that the top-most node is now one layer higher. */ - heights[offset - 1]++; - - /* If this is a node we need for the auth path.. */ - if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_path + heights[offset - 1]*SPX_N, - stack + (offset - 1)*SPX_N, SPX_N); - } - } - } - memcpy(root, stack, SPX_N); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/utils.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/utils.h deleted file mode 100644 index 64f5d5a53a..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/utils.h +++ /dev/null @@ -1,58 +0,0 @@ -#ifndef SPX_UTILS_H -#define SPX_UTILS_H - -#include - -#include "compat.h" -#include "context.h" -#include "params.h" - - -/* To support MSVC use alloca() instead of VLAs. See #20. */ - - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) -void ull_to_bytes(unsigned char *out, unsigned int outlen, - unsigned long long in); -#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) -void u32_to_bytes(unsigned char *out, uint32_t in); - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) -unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -#define compute_root SPX_NAMESPACE(compute_root) -void compute_root(unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const spx_ctx *ctx, uint32_t addr[8]); - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -#define treehash SPX_NAMESPACE(treehash) -void treehash(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const spx_ctx *ctx /* ctx */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), - uint32_t tree_addr[8]); - - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/utilsx4.c b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/utilsx4.c deleted file mode 100644 index 1638677194..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/utilsx4.c +++ /dev/null @@ -1,138 +0,0 @@ -#include - -#include "utilsx4.h" - -#include "address.h" -#include "params.h" -#include "thashx4.h" -#include "utils.h" - -/* - * Generate the entire Merkle tree, computing the authentication path for leaf_idx, - * and the resulting root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) - * - * This expects tree_addrx4 to be initialized to 4 parallel addr structures for - * the Merkle tree nodes - * - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - * - * This works by using the standard Merkle tree building algorithm, except - * that each 'node' tracked is actually 4 consecutive nodes in the real tree. - * When we combine two logical nodes ABCD and WXYZ, we perform the H - * operation on adjacent real nodes, forming the parent logical node - * (AB)(CD)(WX)(YZ) - * - * When we get to the top two levels of the real tree (where there is only - * one logical node), we continue this operation two more times; the right - * most real node will by the actual root (and the other 3 nodes will be - * garbage). We follow the same thashx4 logic so that the 'extract - * authentication path components' part of the loop is still executed (and - * to simplify the code somewhat) - * - * This currently assumes tree_height >= 2; I suspect that doing an adjusting - * idx, addr_idx on the gen_leafx4 call if tree_height < 2 would fix it; since - * we don't actually use such short trees, I haven't bothered - */ -void treehashx4(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, - uint32_t tree_height, - void (*gen_leafx4)( - unsigned char * /* Where to write the leaves */, - const spx_ctx *, - uint32_t idx, void *info), - uint32_t tree_addrx4[4 * 8], - void *info) { - /* This is where we keep the intermediate nodes */ - PQCLEAN_VLA(unsigned char, stackx4, tree_height * 4 * SPX_N); - uint32_t left_adj = 0, prev_left_adj = 0; /* When we're doing the top 3 */ - /* levels, the left-most part of the tree isn't at the beginning */ - /* of current[]. These give the offset of the actual start */ - - uint32_t idx; - uint32_t max_idx = (1U << (tree_height - 2)) - 1; - for (idx = 0;; idx++) { - unsigned char current[4 * SPX_N]; /* Current logical node */ - gen_leafx4( current, ctx, 4 * idx + idx_offset, - info ); - - /* Now combine the freshly generated right node with previously */ - /* generated left ones */ - uint32_t internal_idx_offset = idx_offset; - uint32_t internal_idx = idx; - uint32_t internal_leaf = leaf_idx; - uint32_t h; /* The height we are in the Merkle tree */ - for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { - - /* Special processing if we're at the top of the tree */ - if (h >= tree_height - 2) { - if (h == tree_height) { - /* We hit the root; return it */ - memcpy( root, ¤t[3 * SPX_N], SPX_N ); - return; - } - /* The tree indexing logic is a bit off in this case */ - /* Adjust it so that the left-most node of the part of */ - /* the tree that we're processing has index 0 */ - prev_left_adj = left_adj; - left_adj = 4U - (1 << (tree_height - h - 1)); - } - - /* Check if we hit the top of the tree */ - if (h == tree_height) { - /* We hit the root; return it */ - memcpy( root, ¤t[3 * SPX_N], SPX_N ); - return; - } - - /* - * Check if one of the nodes we have is a part of the - * authentication path; if it is, write it out - */ - if ((((internal_idx << 2) ^ internal_leaf) & ~0x3U) == 0) { - memcpy( &auth_path[ h * SPX_N ], - ¤t[(((internal_leaf & 3) ^ 1) + prev_left_adj) * SPX_N], - SPX_N ); - } - - /* - * Check if we're at a left child; if so, stop going up the stack - * Exception: if we've reached the end of the tree, keep on going - * (so we combine the last 4 nodes into the one root node in two - * more iterations) - */ - if ((internal_idx & 1) == 0 && idx < max_idx) { - break; - } - - /* Ok, we're at a right node (or doing the top 3 levels) */ - /* Now combine the left and right logical nodes together */ - - /* Set the address of the node we're creating. */ - unsigned int j; - internal_idx_offset >>= 1; - for (j = 0; j < 4; j++) { - set_tree_height(tree_addrx4 + j * 8, h + 1); - set_tree_index(tree_addrx4 + j * 8, - (4 / 2) * (internal_idx & ~1U) + j - left_adj + internal_idx_offset ); - } - unsigned char *left = &stackx4[h * 4 * SPX_N]; - thashx4( ¤t[0 * SPX_N], - ¤t[1 * SPX_N], - ¤t[2 * SPX_N], - ¤t[3 * SPX_N], - &left [0 * SPX_N], - &left [2 * SPX_N], - ¤t[0 * SPX_N], - ¤t[2 * SPX_N], - 2, ctx, tree_addrx4); - } - - /* We've hit a left child; save the current for when we get the */ - /* corresponding right right */ - memcpy( &stackx4[h * 4 * SPX_N], current, 4 * SPX_N); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/utilsx4.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/utilsx4.h deleted file mode 100644 index facb874b18..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/utilsx4.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef SPX_UTILSX4_H -#define SPX_UTILSX4_H - -#include - -#include "context.h" -#include "params.h" - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - * - * This implementation uses AVX to compute internal nodes 4 at a time (in - * parallel) - */ -#define treehashx4 SPX_NAMESPACE(treehashx4) -void treehashx4(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leafx4)( - unsigned char * /* Where to write the leaves */, - const spx_ctx * /* ctx */, - uint32_t addr_idx, void *info), - uint32_t tree_addrx4[4 * 8], void *info); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/wots.c b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/wots.c deleted file mode 100644 index 4d5041ce05..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/wots.c +++ /dev/null @@ -1,269 +0,0 @@ -#include -#include - -#include "wots.h" - -#include "address.h" -#include "hash.h" -#include "hashx4.h" -#include "params.h" -#include "thash.h" -#include "thashx4.h" -#include "utils.h" -#include "utilsx4.h" -#include "wotsx4.h" - -// TODO clarify address expectations, and make them more uniform. -// TODO i.e. do we expect types to be set already? -// TODO and do we expect modifications or copies? - -/** - * Computes up the chains - */ -static void gen_chains( - unsigned char *out, - const unsigned char *in, - unsigned int start[SPX_WOTS_LEN], - const unsigned int steps[SPX_WOTS_LEN], - const spx_ctx *ctx, - uint32_t addr[8]) { - uint32_t i, j, k, idx, watching; - int done; - unsigned char empty[SPX_N]; - unsigned char *bufs[4]; - uint32_t addrs[8 * 4]; - - int l; - uint16_t counts[SPX_WOTS_W] = { 0 }; - uint16_t idxs[SPX_WOTS_LEN]; - uint16_t total, newTotal; - - /* set addrs = {addr, addr, addr, addr} */ - for (j = 0; j < 4; j++) { - memcpy(addrs + j * 8, addr, sizeof(uint32_t) * 8); - } - - /* Initialize out with the value at position 'start'. */ - memcpy(out, in, SPX_WOTS_LEN * SPX_N); - - /* Sort the chains in reverse order by steps using counting sort. */ - for (i = 0; i < SPX_WOTS_LEN; i++) { - counts[steps[i]]++; - } - total = 0; - for (l = SPX_WOTS_W - 1; l >= 0; l--) { - newTotal = counts[l] + total; - counts[l] = total; - total = newTotal; - } - for (i = 0; i < SPX_WOTS_LEN; i++) { - idxs[counts[steps[i]]] = (uint16_t)i; - counts[steps[i]]++; - } - - /* We got our work cut out for us: do it! */ - for (i = 0; i < SPX_WOTS_LEN; i += 4) { - for (j = 0; j < 4 && i + j < SPX_WOTS_LEN; j++) { - idx = idxs[i + j]; - set_chain_addr(addrs + j * 8, idx); - bufs[j] = out + SPX_N * idx; - } - - /* As the chains are sorted in reverse order, we know that the first - * chain is the longest and the last one is the shortest. We keep - * an eye on whether the last chain is done and then on the one before, - * et cetera. */ - watching = 3; - done = 0; - while (i + watching >= SPX_WOTS_LEN) { - bufs[watching] = &empty[0]; - watching--; - } - - for (k = 0;; k++) { - while (k == steps[idxs[i + watching]]) { - bufs[watching] = &empty[0]; - if (watching == 0) { - done = 1; - break; - } - watching--; - } - if (done) { - break; - } - for (j = 0; j < watching + 1; j++) { - set_hash_addr(addrs + j * 8, k + start[idxs[i + j]]); - } - - thashx4(bufs[0], bufs[1], bufs[2], bufs[3], - bufs[0], bufs[1], bufs[2], bufs[3], 1, ctx, addrs); - } - } -} - -/** - * base_w algorithm as described in draft. - * Interprets an array of bytes as integers in base w. - * This only works when log_w is a divisor of 8. - */ -static void base_w(unsigned int *output, const int out_len, - const unsigned char *input) { - int in = 0; - int out = 0; - unsigned char total = 0; - int bits = 0; - int consumed; - - for (consumed = 0; consumed < out_len; consumed++) { - if (bits == 0) { - total = input[in]; - in++; - bits += 8; - } - bits -= SPX_WOTS_LOGW; - output[out] = (total >> bits) & (SPX_WOTS_W - 1); - out++; - } -} - -/* Computes the WOTS+ checksum over a message (in base_w). */ -static void wots_checksum(unsigned int *csum_base_w, - const unsigned int *msg_base_w) { - unsigned int csum = 0; - unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; - unsigned int i; - - /* Compute checksum. */ - for (i = 0; i < SPX_WOTS_LEN1; i++) { - csum += SPX_WOTS_W - 1 - msg_base_w[i]; - } - - /* Convert checksum to base_w. */ - /* Make sure expected empty zero bits are the least significant bits. */ - csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); - ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); - base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); -} - -/* Takes a message and derives the matching chain lengths. */ -void chain_lengths(unsigned int *lengths, const unsigned char *msg) { - base_w(lengths, SPX_WOTS_LEN1, msg); - wots_checksum(lengths + SPX_WOTS_LEN1, lengths); -} - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const spx_ctx *ctx, uint32_t addr[8]) { - unsigned int steps[SPX_WOTS_LEN]; - unsigned int start[SPX_WOTS_LEN]; - uint32_t i; - - chain_lengths(start, msg); - - for (i = 0; i < SPX_WOTS_LEN; i++) { - steps[i] = SPX_WOTS_W - 1 - start[i]; - } - - gen_chains(pk, sig, start, steps, ctx, addr); -} - -/* - * This generates 4 sequential WOTS public keys - * It also generates the WOTS signature if leaf_info indicates - * that we're signing with one of these WOTS keys - */ -void wots_gen_leafx4(unsigned char *dest, - const spx_ctx *ctx, - uint32_t leaf_idx, void *v_info) { - struct leaf_info_x4 *info = v_info; - uint32_t *leaf_addr = info->leaf_addr; - uint32_t *pk_addr = info->pk_addr; - unsigned int i, j, k; - unsigned char pk_buffer[ 4 * SPX_WOTS_BYTES ]; - unsigned wots_offset = SPX_WOTS_BYTES; - unsigned char *buffer; - uint32_t wots_k_mask; - unsigned wots_sign_index; - - if (((leaf_idx ^ info->wots_sign_leaf) & ~3U) == 0) { - /* We're traversing the leaf that's signing; generate the WOTS */ - /* signature */ - wots_k_mask = 0; - wots_sign_index = info->wots_sign_leaf & 3; /* Which of of the 4 */ - /* 4 slots do the signatures come from */ - } else { - /* Nope, we're just generating pk's; turn off the signature logic */ - wots_k_mask = (uint32_t)~0; - wots_sign_index = 0; - } - - for (j = 0; j < 4; j++) { - set_keypair_addr( leaf_addr + j * 8, leaf_idx + j ); - set_keypair_addr( pk_addr + j * 8, leaf_idx + j ); - } - - for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { - uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k to */ - /* the step if we're generating a signature, ~0 if we're not */ - - /* Start with the secret seed */ - for (j = 0; j < 4; j++) { - set_chain_addr(leaf_addr + j * 8, i); - set_hash_addr(leaf_addr + j * 8, 0); - set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTSPRF); - } - prf_addrx4(buffer + 0 * wots_offset, - buffer + 1 * wots_offset, - buffer + 2 * wots_offset, - buffer + 3 * wots_offset, - ctx, leaf_addr); - - for (j = 0; j < 4; j++) { - set_type(leaf_addr + j * 8, SPX_ADDR_TYPE_WOTS); - } - - /* Iterate down the WOTS chain */ - for (k = 0;; k++) { - /* Check if one of the values we have needs to be saved as a */ - /* part of the WOTS signature */ - if (k == wots_k) { - memcpy( info->wots_sig + i * SPX_N, - buffer + wots_sign_index * wots_offset, SPX_N ); - } - - /* Check if we hit the top of the chain */ - if (k == SPX_WOTS_W - 1) { - break; - } - - /* Iterate one step on all 4 chains */ - for (j = 0; j < 4; j++) { - set_hash_addr(leaf_addr + j * 8, k); - } - thashx4(buffer + 0 * wots_offset, - buffer + 1 * wots_offset, - buffer + 2 * wots_offset, - buffer + 3 * wots_offset, - buffer + 0 * wots_offset, - buffer + 1 * wots_offset, - buffer + 2 * wots_offset, - buffer + 3 * wots_offset, 1, ctx, leaf_addr); - } - } - - /* Do the final thash to generate the public keys */ - thashx4(dest + 0 * SPX_N, - dest + 1 * SPX_N, - dest + 2 * SPX_N, - dest + 3 * SPX_N, - pk_buffer + 0 * wots_offset, - pk_buffer + 1 * wots_offset, - pk_buffer + 2 * wots_offset, - pk_buffer + 3 * wots_offset, SPX_WOTS_LEN, ctx, pk_addr); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/wots.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/wots.h deleted file mode 100644 index 4e7692eeef..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/wots.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef SPX_WOTS_H -#define SPX_WOTS_H - -#include - -#include "context.h" -#include "params.h" - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) -void wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const spx_ctx *ctx, uint32_t addr[8]); - -/* - * Compute the chain lengths needed for a given message hash - */ -#define chain_lengths SPX_NAMESPACE(chain_lengths) -void chain_lengths(unsigned int *lengths, const unsigned char *msg); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/wotsx4.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/wotsx4.h deleted file mode 100644 index cd634f1743..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_avx2/wotsx4.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef WOTSX4_H_ -#define WOTSX4_H_ - -#include - -#include "params.h" - -/* - * This is here to provide an interface to the internal wots_gen_leafx4 - * routine. While this routine is not referenced in the package outside of - * wots.c, it is called from the stand-alone benchmark code to characterize - * the performance - */ -struct leaf_info_x4 { - unsigned char *wots_sig; - uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ - uint32_t *wots_steps; - uint32_t leaf_addr[4 * 8]; - uint32_t pk_addr[4 * 8]; -}; - -/* Macro to set the leaf_info to something 'benign', that is, it would */ -/* run with the same time as it does during the real signing process */ -/* Used only by the benchmark code */ -#define INITIALIZE_LEAF_INFO_X4(info, addr, step_buffer) { \ - (info).wots_sig = 0; \ - (info).wots_sign_leaf = ~0; \ - (info).wots_steps = step_buffer; \ - int i; \ - for (i=0; i<4; i++) { \ - memcpy( &(info).leaf_addr[8*i], addr, 32 ); \ - memcpy( &(info).pk_addr[8*i], addr, 32 ); \ - } \ - } - -#define wots_gen_leafx4 SPX_NAMESPACE(wots_gen_leafx4) -void wots_gen_leafx4(unsigned char *dest, - const spx_ctx *ctx, - uint32_t leaf_idx, void *v_info); - -#endif /* WOTSX4_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/LICENSE b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/LICENSE deleted file mode 100644 index 670154e353..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/LICENSE +++ /dev/null @@ -1,116 +0,0 @@ -CC0 1.0 Universal - -Statement of Purpose - -The laws of most jurisdictions throughout the world automatically confer -exclusive Copyright and Related Rights (defined below) upon the creator and -subsequent owner(s) (each and all, an "owner") of an original work of -authorship and/or a database (each, a "Work"). - -Certain owners wish to permanently relinquish those rights to a Work for the -purpose of contributing to a commons of creative, cultural and scientific -works ("Commons") that the public can reliably and without fear of later -claims of infringement build upon, modify, incorporate in other works, reuse -and redistribute as freely as possible in any form whatsoever and for any -purposes, including without limitation commercial purposes. These owners may -contribute to the Commons to promote the ideal of a free culture and the -further production of creative, cultural and scientific works, or to gain -reputation or greater distribution for their Work in part through the use and -efforts of others. - -For these and/or other purposes and motivations, and without any expectation -of additional consideration or compensation, the person associating CC0 with a -Work (the "Affirmer"), to the extent that he or she is an owner of Copyright -and Related Rights in the Work, voluntarily elects to apply CC0 to the Work -and publicly distribute the Work under its terms, with knowledge of his or her -Copyright and Related Rights in the Work and the meaning and intended legal -effect of CC0 on those rights. - -1. Copyright and Related Rights. A Work made available under CC0 may be -protected by copyright and related or neighboring rights ("Copyright and -Related Rights"). Copyright and Related Rights include, but are not limited -to, the following: - - i. the right to reproduce, adapt, distribute, perform, display, communicate, - and translate a Work; - - ii. moral rights retained by the original author(s) and/or performer(s); - - iii. publicity and privacy rights pertaining to a person's image or likeness - depicted in a Work; - - iv. rights protecting against unfair competition in regards to a Work, - subject to the limitations in paragraph 4(a), below; - - v. rights protecting the extraction, dissemination, use and reuse of data in - a Work; - - vi. database rights (such as those arising under Directive 96/9/EC of the - European Parliament and of the Council of 11 March 1996 on the legal - protection of databases, and under any national implementation thereof, - including any amended or successor version of such directive); and - - vii. other similar, equivalent or corresponding rights throughout the world - based on applicable law or treaty, and any national implementations thereof. - -2. Waiver. To the greatest extent permitted by, but not in contravention of, -applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and -unconditionally waives, abandons, and surrenders all of Affirmer's Copyright -and Related Rights and associated claims and causes of action, whether now -known or unknown (including existing as well as future claims and causes of -action), in the Work (i) in all territories worldwide, (ii) for the maximum -duration provided by applicable law or treaty (including future time -extensions), (iii) in any current or future medium and for any number of -copies, and (iv) for any purpose whatsoever, including without limitation -commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes -the Waiver for the benefit of each member of the public at large and to the -detriment of Affirmer's heirs and successors, fully intending that such Waiver -shall not be subject to revocation, rescission, cancellation, termination, or -any other legal or equitable action to disrupt the quiet enjoyment of the Work -by the public as contemplated by Affirmer's express Statement of Purpose. - -3. Public License Fallback. Should any part of the Waiver for any reason be -judged legally invalid or ineffective under applicable law, then the Waiver -shall be preserved to the maximum extent permitted taking into account -Affirmer's express Statement of Purpose. In addition, to the extent the Waiver -is so judged Affirmer hereby grants to each affected person a royalty-free, -non transferable, non sublicensable, non exclusive, irrevocable and -unconditional license to exercise Affirmer's Copyright and Related Rights in -the Work (i) in all territories worldwide, (ii) for the maximum duration -provided by applicable law or treaty (including future time extensions), (iii) -in any current or future medium and for any number of copies, and (iv) for any -purpose whatsoever, including without limitation commercial, advertising or -promotional purposes (the "License"). The License shall be deemed effective as -of the date CC0 was applied by Affirmer to the Work. Should any part of the -License for any reason be judged legally invalid or ineffective under -applicable law, such partial invalidity or ineffectiveness shall not -invalidate the remainder of the License, and in such case Affirmer hereby -affirms that he or she will not (i) exercise any of his or her remaining -Copyright and Related Rights in the Work or (ii) assert any associated claims -and causes of action with respect to the Work, in either case contrary to -Affirmer's express Statement of Purpose. - -4. Limitations and Disclaimers. - - a. No trademark or patent rights held by Affirmer are waived, abandoned, - surrendered, licensed or otherwise affected by this document. - - b. Affirmer offers the Work as-is and makes no representations or warranties - of any kind concerning the Work, express, implied, statutory or otherwise, - including without limitation warranties of title, merchantability, fitness - for a particular purpose, non infringement, or the absence of latent or - other defects, accuracy, or the present or absence of errors, whether or not - discoverable, all to the greatest extent permissible under applicable law. - - c. Affirmer disclaims responsibility for clearing rights of other persons - that may apply to the Work or any use thereof, including without limitation - any person's Copyright and Related Rights in the Work. Further, Affirmer - disclaims responsibility for obtaining any necessary consents, permissions - or other rights required for any use of the Work. - - d. Affirmer understands and acknowledges that Creative Commons is not a - party to this document and has no duty or obligation with respect to this - CC0 or use of the Work. - -For more information, please see - diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/address.c b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/address.c deleted file mode 100644 index b956e9cb29..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/address.c +++ /dev/null @@ -1,91 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "utils.h" - -/* - * Specify which level of Merkle tree (the "layer") we're working on - */ -void set_layer_addr(uint32_t addr[8], uint32_t layer) { - ((unsigned char *)addr)[SPX_OFFSET_LAYER] = (unsigned char)layer; -} - -/* - * Specify which Merkle tree within the level (the "tree address") we're working on - */ -void set_tree_addr(uint32_t addr[8], uint64_t tree) { - ull_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE], 8, tree ); -} - -/* - * Specify the reason we'll use this address structure for, that is, what - * hash will we compute with it. This is used so that unrelated types of - * hashes don't accidentally get the same address structure. The type will be - * one of the SPX_ADDR_TYPE constants - */ -void set_type(uint32_t addr[8], uint32_t type) { - ((unsigned char *)addr)[SPX_OFFSET_TYPE] = (unsigned char)type; -} - -/* - * Copy the layer and tree fields of the address structure. This is used - * when we're doing multiple types of hashes within the same Merkle tree - */ -void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]) { - memcpy( out, in, SPX_OFFSET_TREE + 8 ); -} - -/* These functions are used for OTS addresses. */ - -/* - * Specify which Merkle leaf we're working on; that is, which OTS keypair - * we're talking about. - */ -void set_keypair_addr(uint32_t addr[8], uint32_t keypair) { - ((unsigned char *)addr)[SPX_OFFSET_KP_ADDR1] = (unsigned char)keypair; -} - -/* - * Copy the layer, tree and keypair fields of the address structure. This is - * used when we're doing multiple things within the same OTS keypair - */ -void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]) { - memcpy( out, in, SPX_OFFSET_TREE + 8 ); - ((unsigned char *)out)[SPX_OFFSET_KP_ADDR1] = ((unsigned char *)in)[SPX_OFFSET_KP_ADDR1]; -} - -/* - * Specify which Merkle chain within the OTS we're working with - * (the chain address) - */ -void set_chain_addr(uint32_t addr[8], uint32_t chain) { - ((unsigned char *)addr)[SPX_OFFSET_CHAIN_ADDR] = (unsigned char)chain; -} - -/* - * Specify where in the Merkle chain we are -* (the hash address) - */ -void set_hash_addr(uint32_t addr[8], uint32_t hash) { - ((unsigned char *)addr)[SPX_OFFSET_HASH_ADDR] = (unsigned char)hash; -} - -/* These functions are used for all hash tree addresses (including FORS). */ - -/* - * Specify the height of the node in the Merkle/FORS tree we are in - * (the tree height) - */ -void set_tree_height(uint32_t addr[8], uint32_t tree_height) { - ((unsigned char *)addr)[SPX_OFFSET_TREE_HGT] = (unsigned char)tree_height; -} - -/* - * Specify the distance from the left edge of the node in the Merkle/FORS tree - * (the tree index) - */ -void set_tree_index(uint32_t addr[8], uint32_t tree_index) { - u32_to_bytes(&((unsigned char *)addr)[SPX_OFFSET_TREE_INDEX], tree_index ); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/address.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/address.h deleted file mode 100644 index 24a84eb40c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/address.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef SPX_ADDRESS_H -#define SPX_ADDRESS_H - -#include - -#include "params.h" - -/* The hash types that are passed to set_type */ -#define SPX_ADDR_TYPE_WOTS 0 -#define SPX_ADDR_TYPE_WOTSPK 1 -#define SPX_ADDR_TYPE_HASHTREE 2 -#define SPX_ADDR_TYPE_FORSTREE 3 -#define SPX_ADDR_TYPE_FORSPK 4 -#define SPX_ADDR_TYPE_WOTSPRF 5 -#define SPX_ADDR_TYPE_FORSPRF 6 - -#define set_layer_addr SPX_NAMESPACE(set_layer_addr) -void set_layer_addr(uint32_t addr[8], uint32_t layer); - -#define set_tree_addr SPX_NAMESPACE(set_tree_addr) -void set_tree_addr(uint32_t addr[8], uint64_t tree); - -#define set_type SPX_NAMESPACE(set_type) -void set_type(uint32_t addr[8], uint32_t type); - -/* Copies the layer and tree part of one address into the other */ -#define copy_subtree_addr SPX_NAMESPACE(copy_subtree_addr) -void copy_subtree_addr(uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for WOTS and FORS addresses. */ - -#define set_keypair_addr SPX_NAMESPACE(set_keypair_addr) -void set_keypair_addr(uint32_t addr[8], uint32_t keypair); - -#define set_chain_addr SPX_NAMESPACE(set_chain_addr) -void set_chain_addr(uint32_t addr[8], uint32_t chain); - -#define set_hash_addr SPX_NAMESPACE(set_hash_addr) -void set_hash_addr(uint32_t addr[8], uint32_t hash); - -#define copy_keypair_addr SPX_NAMESPACE(copy_keypair_addr) -void copy_keypair_addr(uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for all hash tree addresses (including FORS). */ - -#define set_tree_height SPX_NAMESPACE(set_tree_height) -void set_tree_height(uint32_t addr[8], uint32_t tree_height); - -#define set_tree_index SPX_NAMESPACE(set_tree_index) -void set_tree_index(uint32_t addr[8], uint32_t tree_index); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/api.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/api.h deleted file mode 100644 index 292c1d0693..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/api.h +++ /dev/null @@ -1,77 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256SROBUST_CLEAN_API_H -#define PQCLEAN_SPHINCSSHAKE256SROBUST_CLEAN_API_H - -#include -#include - -#define PQCLEAN_SPHINCSSHAKE256SROBUST_CLEAN_CRYPTO_ALGNAME "SPHINCS+-shake-256s-robust" - -#define PQCLEAN_SPHINCSSHAKE256SROBUST_CLEAN_CRYPTO_SECRETKEYBYTES 128 -#define PQCLEAN_SPHINCSSHAKE256SROBUST_CLEAN_CRYPTO_PUBLICKEYBYTES 64 -#define PQCLEAN_SPHINCSSHAKE256SROBUST_CLEAN_CRYPTO_BYTES 29792 - -#define PQCLEAN_SPHINCSSHAKE256SROBUST_CLEAN_CRYPTO_SEEDBYTES 96 - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256SROBUST_CLEAN_crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256SROBUST_CLEAN_crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256SROBUST_CLEAN_crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256SROBUST_CLEAN_crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHAKE256SROBUST_CLEAN_crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHAKE256SROBUST_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSSHAKE256SROBUST_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE256SROBUST_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, - const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSSHAKE256SROBUST_CLEAN_crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE256SROBUST_CLEAN_crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk); -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/context.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/context.h deleted file mode 100644 index 9f8a40ab4e..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/context.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef SPX_CONTEXT_H -#define SPX_CONTEXT_H - -#include -#include - -#include "params.h" - -typedef struct { - uint8_t pub_seed[SPX_N]; - uint8_t sk_seed[SPX_N]; - - -} spx_ctx; - -#define initialize_hash_function SPX_NAMESPACE(initialize_hash_function) -void initialize_hash_function(spx_ctx *ctx); - -#define free_hash_function SPX_NAMESPACE(free_hash_function) -void free_hash_function(spx_ctx *ctx); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/context_shake.c b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/context_shake.c deleted file mode 100644 index 9614a103d3..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/context_shake.c +++ /dev/null @@ -1,12 +0,0 @@ -#include "context.h" - -/* For SHAKE256, there is no immediate reason to initialize at the start, - so this function is an empty operation. */ -void initialize_hash_function(spx_ctx *ctx) { - (void)ctx; /* Suppress an 'unused parameter' warning. */ -} - -// in case the hash function api is heap-based. -void free_hash_function(spx_ctx *ctx) { - (void)ctx; -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/fors.c b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/fors.c deleted file mode 100644 index 96ca72e986..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/fors.c +++ /dev/null @@ -1,156 +0,0 @@ -#include -#include -#include - -#include "fors.h" - -#include "address.h" -#include "hash.h" -#include "thash.h" -#include "utils.h" -#include "utilsx1.h" - -static void fors_gen_sk(unsigned char *sk, const spx_ctx *ctx, - uint32_t fors_leaf_addr[8]) { - prf_addr(sk, ctx, fors_leaf_addr); -} - -static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, - const spx_ctx *ctx, - uint32_t fors_leaf_addr[8]) { - thash(leaf, sk, 1, ctx, fors_leaf_addr); -} - -struct fors_gen_leaf_info { - uint32_t leaf_addrx[8]; -}; - -static void fors_gen_leafx1(unsigned char *leaf, - const spx_ctx *ctx, - uint32_t addr_idx, void *info) { - struct fors_gen_leaf_info *fors_info = info; - uint32_t *fors_leaf_addr = fors_info->leaf_addrx; - - /* Only set the parts that the caller doesn't set */ - set_tree_index(fors_leaf_addr, addr_idx); - set_type(fors_leaf_addr, SPX_ADDR_TYPE_FORSPRF); - fors_gen_sk(leaf, ctx, fors_leaf_addr); - - set_type(fors_leaf_addr, SPX_ADDR_TYPE_FORSTREE); - fors_sk_to_leaf(leaf, leaf, - ctx, fors_leaf_addr); -} - -/** - * Interprets m as SPX_FORS_HEIGHT-bit unsigned integers. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - * Assumes indices has space for SPX_FORS_TREES integers. - */ -static void message_to_indices(uint32_t *indices, const unsigned char *m) { - unsigned int i, j; - unsigned int offset = 0; - - for (i = 0; i < SPX_FORS_TREES; i++) { - indices[i] = 0; - for (j = 0; j < SPX_FORS_HEIGHT; j++) { - indices[i] ^= (uint32_t)(((m[offset >> 3] >> (offset & 0x7)) & 0x1) << j); - offset++; - } - } -} - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -void fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]) { - uint32_t indices[SPX_FORS_TREES]; - unsigned char roots[SPX_FORS_TREES * SPX_N]; - uint32_t fors_tree_addr[8] = {0}; - struct fors_gen_leaf_info fors_info = {0}; - uint32_t *fors_leaf_addr = fors_info.leaf_addrx; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - copy_keypair_addr(fors_tree_addr, fors_addr); - copy_keypair_addr(fors_leaf_addr, fors_addr); - - copy_keypair_addr(fors_pk_addr, fors_addr); - set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < SPX_FORS_TREES; i++) { - idx_offset = i * (1 << SPX_FORS_HEIGHT); - - set_tree_height(fors_tree_addr, 0); - set_tree_index(fors_tree_addr, indices[i] + idx_offset); - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSPRF); - - /* Include the secret key part that produces the selected leaf node. */ - fors_gen_sk(sig, ctx, fors_tree_addr); - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); - sig += SPX_N; - - /* Compute the authentication path for this leaf node. */ - treehashx1(roots + i * SPX_N, sig, ctx, - indices[i], idx_offset, SPX_FORS_HEIGHT, fors_gen_leafx1, - fors_tree_addr, &fors_info); - - sig += SPX_N * SPX_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); -} - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -void fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]) { - uint32_t indices[SPX_FORS_TREES]; - unsigned char roots[SPX_FORS_TREES * SPX_N]; - unsigned char leaf[SPX_N]; - uint32_t fors_tree_addr[8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - copy_keypair_addr(fors_tree_addr, fors_addr); - copy_keypair_addr(fors_pk_addr, fors_addr); - - set_type(fors_tree_addr, SPX_ADDR_TYPE_FORSTREE); - set_type(fors_pk_addr, SPX_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < SPX_FORS_TREES; i++) { - idx_offset = i * (1 << SPX_FORS_HEIGHT); - - set_tree_height(fors_tree_addr, 0); - set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Derive the leaf from the included secret key part. */ - fors_sk_to_leaf(leaf, sig, ctx, fors_tree_addr); - sig += SPX_N; - - /* Derive the corresponding root node of this tree. */ - compute_root(roots + i * SPX_N, leaf, indices[i], idx_offset, - sig, SPX_FORS_HEIGHT, ctx, fors_tree_addr); - sig += SPX_N * SPX_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - thash(pk, roots, SPX_FORS_TREES, ctx, fors_pk_addr); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/fors.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/fors.h deleted file mode 100644 index 509140a178..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/fors.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef SPX_FORS_H -#define SPX_FORS_H - -#include - -#include "context.h" -#include "params.h" - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -#define fors_sign SPX_NAMESPACE(fors_sign) -void fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]); - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits. - */ -#define fors_pk_from_sig SPX_NAMESPACE(fors_pk_from_sig) -void fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const spx_ctx *ctx, - const uint32_t fors_addr[8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/hash.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/hash.h deleted file mode 100644 index f7c87d4c3c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/hash.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef SPX_HASH_H -#define SPX_HASH_H - -#include -#include - -#include "context.h" -#include "params.h" - -#define prf_addr SPX_NAMESPACE(prf_addr) -void prf_addr(unsigned char *out, const spx_ctx *ctx, - const uint32_t addr[8]); - -#define gen_message_random SPX_NAMESPACE(gen_message_random) -void gen_message_random(unsigned char *R, const unsigned char *sk_prf, - const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx); - -#define hash_message SPX_NAMESPACE(hash_message) -void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx); - - - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/hash_shake.c b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/hash_shake.c deleted file mode 100644 index ff5e7ec918..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/hash_shake.c +++ /dev/null @@ -1,83 +0,0 @@ -#include -#include - -#include "hash.h" - -#include "address.h" -#include "fips202.h" -#include "params.h" -#include "utils.h" - -/* - * Computes PRF(pk_seed, sk_seed, addr) - */ -void prf_addr(unsigned char *out, const spx_ctx *ctx, - const uint32_t addr[8]) { - unsigned char buf[2 * SPX_N + SPX_ADDR_BYTES]; - - memcpy(buf, ctx->pub_seed, SPX_N); - memcpy(buf + SPX_N, addr, SPX_ADDR_BYTES); - memcpy(buf + SPX_N + SPX_ADDR_BYTES, ctx->sk_seed, SPX_N); - - shake256(out, SPX_N, buf, 2 * SPX_N + SPX_ADDR_BYTES); -} - -/** - * Computes the message-dependent randomness R, using a secret seed and an - * optional randomization value as well as the message. - */ -void gen_message_random(unsigned char *R, const unsigned char *sk_prf, - const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx) { - (void)ctx; - shake256incctx s_inc; - - shake256_inc_init(&s_inc); - shake256_inc_absorb(&s_inc, sk_prf, SPX_N); - shake256_inc_absorb(&s_inc, optrand, SPX_N); - shake256_inc_absorb(&s_inc, m, mlen); - shake256_inc_finalize(&s_inc); - shake256_inc_squeeze(R, SPX_N, &s_inc); - shake256_inc_ctx_release(&s_inc); -} - -/** - * Computes the message hash using R, the public key, and the message. - * Outputs the message digest and the index of the leaf. The index is split in - * the tree index and the leaf index, for convenient copying to an address. - */ -void hash_message(unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const spx_ctx *ctx) { - (void)ctx; -#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) -#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) -#define SPX_LEAF_BITS SPX_TREE_HEIGHT -#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) -#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES) - - unsigned char buf[SPX_DGST_BYTES]; - unsigned char *bufp = buf; - shake256incctx s_inc; - - shake256_inc_init(&s_inc); - shake256_inc_absorb(&s_inc, R, SPX_N); - shake256_inc_absorb(&s_inc, pk, SPX_PK_BYTES); - shake256_inc_absorb(&s_inc, m, mlen); - shake256_inc_finalize(&s_inc); - shake256_inc_squeeze(buf, SPX_DGST_BYTES, &s_inc); - shake256_inc_ctx_release(&s_inc); - - memcpy(digest, bufp, SPX_FORS_MSG_BYTES); - bufp += SPX_FORS_MSG_BYTES; - - - *tree = bytes_to_ull(bufp, SPX_TREE_BYTES); - *tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); - bufp += SPX_TREE_BYTES; - - *leaf_idx = (uint32_t)bytes_to_ull(bufp, SPX_LEAF_BYTES); - *leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/merkle.c b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/merkle.c deleted file mode 100644 index 0c1479fd93..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/merkle.c +++ /dev/null @@ -1,59 +0,0 @@ -#include -#include - -#include "address.h" -#include "merkle.h" -#include "params.h" -#include "utils.h" -#include "utilsx1.h" -#include "wots.h" -#include "wotsx1.h" - -/* - * This generates a Merkle signature (WOTS signature followed by the Merkle - * authentication path). This is in this file because most of the complexity - * is involved with the WOTS signature; the Merkle authentication path logic - * is mostly hidden in treehashx4 - */ -void merkle_sign(uint8_t *sig, unsigned char *root, - const spx_ctx *ctx, - uint32_t wots_addr[8], uint32_t tree_addr[8], - uint32_t idx_leaf) { - unsigned char *auth_path = sig + SPX_WOTS_BYTES; - struct leaf_info_x1 info = { 0 }; - unsigned steps[ SPX_WOTS_LEN ]; - - info.wots_sig = sig; - chain_lengths(steps, root); - info.wots_steps = steps; - - set_type(&tree_addr[0], SPX_ADDR_TYPE_HASHTREE); - set_type(&info.pk_addr[0], SPX_ADDR_TYPE_WOTSPK); - copy_subtree_addr(&info.leaf_addr[0], wots_addr); - copy_subtree_addr(&info.pk_addr[0], wots_addr); - - info.wots_sign_leaf = idx_leaf; - - treehashx1(root, auth_path, ctx, - idx_leaf, 0, - SPX_TREE_HEIGHT, - wots_gen_leafx1, - tree_addr, &info); -} - -/* Compute root node of the top-most subtree. */ -void merkle_gen_root(unsigned char *root, const spx_ctx *ctx) { - /* We do not need the auth path in key generation, but it simplifies the - code to have just one treehash routine that computes both root and path - in one function. */ - unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N + SPX_WOTS_BYTES]; - uint32_t top_tree_addr[8] = {0}; - uint32_t wots_addr[8] = {0}; - - set_layer_addr(top_tree_addr, SPX_D - 1); - set_layer_addr(wots_addr, SPX_D - 1); - - merkle_sign(auth_path, root, ctx, - wots_addr, top_tree_addr, - (uint32_t)~0 /* ~0 means "don't bother generating an auth path */ ); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/merkle.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/merkle.h deleted file mode 100644 index 769cf2e970..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/merkle.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef MERKLE_H_ -#define MERKLE_H_ - -#include - -#include "context.h" -#include "params.h" - -/* Generate a Merkle signature (WOTS signature followed by the Merkle */ -/* authentication path) */ -#define merkle_sign SPX_NAMESPACE(merkle_sign) -void merkle_sign(uint8_t *sig, unsigned char *root, - const spx_ctx *ctx, - uint32_t wots_addr[8], uint32_t tree_addr[8], - uint32_t idx_leaf); - -/* Compute the root node of the top-most subtree. */ -#define merkle_gen_root SPX_NAMESPACE(merkle_gen_root) -void merkle_gen_root(unsigned char *root, const spx_ctx *ctx); - -#endif /* MERKLE_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/nistapi.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/nistapi.h deleted file mode 100644 index 3cb71afad4..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/nistapi.h +++ /dev/null @@ -1,87 +0,0 @@ -#ifndef SPX_API_H -#define SPX_API_H - -#include -#include - -#include "params.h" - -#define CRYPTO_ALGNAME "SPHINCS+" - -#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES -#define CRYPTO_PUBLICKEYBYTES SPX_PK_BYTES -#define CRYPTO_BYTES SPX_BYTES -#define CRYPTO_SEEDBYTES (3*SPX_N) - -/* - * Returns the length of a secret key, in bytes - */ -#define crypto_sign_secretkeybytes SPX_NAMESPACE(crypto_sign_secretkeybytes) -size_t crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -#define crypto_sign_publickeybytes SPX_NAMESPACE(crypto_sign_publickeybytes) -size_t crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -#define crypto_sign_bytes SPX_NAMESPACE(crypto_sign_bytes) -size_t crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -#define crypto_sign_seedbytes SPX_NAMESPACE(crypto_sign_seedbytes) -size_t crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -#define crypto_sign_seed_keypair SPX_NAMESPACE(crypto_sign_seed_keypair) -int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -#define crypto_sign_keypair SPX_NAMESPACE(crypto_sign_keypair) -int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -#define crypto_sign_signature SPX_NAMESPACE(crypto_sign_signature) -int crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -#define crypto_sign_verify SPX_NAMESPACE(crypto_sign_verify) -int crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -#define crypto_sign SPX_NAMESPACE(crypto_sign) -int crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -#define crypto_sign_open SPX_NAMESPACE(crypto_sign_open) -int crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/params.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/params.h deleted file mode 100644 index a4b3659a94..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/params.h +++ /dev/null @@ -1,56 +0,0 @@ -#ifndef SPX_PARAMS_H -#define SPX_PARAMS_H - -#define SPX_NAMESPACE(s) PQCLEAN_SPHINCSSHAKE256SROBUST_CLEAN_##s - -/* Hash output length in bytes. */ -#define SPX_N 32 -/* Height of the hypertree. */ -#define SPX_FULL_HEIGHT 64 -/* Number of subtree layer. */ -#define SPX_D 8 -/* FORS tree dimensions. */ -#define SPX_FORS_HEIGHT 14 -#define SPX_FORS_TREES 22 -/* Winternitz parameter, */ -#define SPX_WOTS_W 16 - -/* The hash function is defined by linking a different hash.c file, as opposed - to setting a #define constant. */ - -/* For clarity */ -#define SPX_ADDR_BYTES 32 - -/* WOTS parameters. */ -#define SPX_WOTS_LOGW 4 - -#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW) - -/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#define SPX_WOTS_LEN2 3 - -#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2) -#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N) -#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES - -/* Subtree size. */ -#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D) - -//#if SPX_TREE_HEIGHT * SPX_D != SPX_FULL_HEIGHT -// #error SPX_D should always divide SPX_FULL_HEIGHT -//#endif - -/* FORS parameters. */ -#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) -#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) -#define SPX_FORS_PK_BYTES SPX_N - -/* Resulting SPX sizes. */ -#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\ - SPX_FULL_HEIGHT * SPX_N) -#define SPX_PK_BYTES (2 * SPX_N) -#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES) - -#include "shake_offsets.h" - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/shake_offsets.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/shake_offsets.h deleted file mode 100644 index 6b28d95d91..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/shake_offsets.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef SHAKE_OFFSETS_H_ -#define SHAKE_OFFSETS_H_ - -/* - * Offsets of various fields in the address structure when we use SHAKE as - * the Sphincs+ hash function - */ - -#define SPX_OFFSET_LAYER 3 /* The byte used to specify the Merkle tree layer */ -#define SPX_OFFSET_TREE 8 /* The start of the 8 byte field used to specify the tree */ -#define SPX_OFFSET_TYPE 19 /* The byte used to specify the hash type (reason) */ -#define SPX_OFFSET_KP_ADDR2 22 /* The high byte used to specify the key pair (which one-time signature) */ -#define SPX_OFFSET_KP_ADDR1 23 /* The low byte used to specify the key pair */ -#define SPX_OFFSET_CHAIN_ADDR 27 /* The byte used to specify the chain address (which Winternitz chain) */ -#define SPX_OFFSET_HASH_ADDR 31 /* The byte used to specify the hash address (where in the Winternitz chain) */ -#define SPX_OFFSET_TREE_HGT 27 /* The byte used to specify the height of this node in the FORS or Merkle tree */ -#define SPX_OFFSET_TREE_INDEX 28 /* The start of the 4 byte field used to specify the node in the FORS or Merkle tree */ - -#define SPX_SHAKE 1 - -#endif /* SHAKE_OFFSETS_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/sign.c b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/sign.c deleted file mode 100644 index 9d0c7d1b22..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/sign.c +++ /dev/null @@ -1,286 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "context.h" -#include "fors.h" -#include "hash.h" -#include "merkle.h" -#include "nistapi.h" -#include "params.h" -#include "randombytes.h" -#include "thash.h" -#include "utils.h" -#include "wots.h" - -/* - * Returns the length of a secret key, in bytes - */ -size_t crypto_sign_secretkeybytes(void) { - return CRYPTO_SECRETKEYBYTES; -} - -/* - * Returns the length of a public key, in bytes - */ -size_t crypto_sign_publickeybytes(void) { - return CRYPTO_PUBLICKEYBYTES; -} - -/* - * Returns the length of a signature, in bytes - */ -size_t crypto_sign_bytes(void) { - return CRYPTO_BYTES; -} - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t crypto_sign_seedbytes(void) { - return CRYPTO_SEEDBYTES; -} - -/* - * Generates an SPX key pair given a seed of length - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int crypto_sign_seed_keypair(uint8_t *pk, uint8_t *sk, - const uint8_t *seed) { - spx_ctx ctx; - - /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ - memcpy(sk, seed, CRYPTO_SEEDBYTES); - - memcpy(pk, sk + 2 * SPX_N, SPX_N); - - memcpy(ctx.pub_seed, pk, SPX_N); - memcpy(ctx.sk_seed, sk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - /* Compute root node of the top-most subtree. */ - merkle_gen_root(sk + 3 * SPX_N, &ctx); - - // cleanup - free_hash_function(&ctx); - - memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N); - - return 0; -} - -/* - * Generates an SPX key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { - uint8_t seed[CRYPTO_SEEDBYTES]; - randombytes(seed, CRYPTO_SEEDBYTES); - crypto_sign_seed_keypair(pk, sk, seed); - - return 0; -} - -/** - * Returns an array containing a detached signature. - */ -int crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - spx_ctx ctx; - - const uint8_t *sk_prf = sk + SPX_N; - const uint8_t *pk = sk + 2 * SPX_N; - - uint8_t optrand[SPX_N]; - uint8_t mhash[SPX_FORS_MSG_BYTES]; - uint8_t root[SPX_N]; - uint32_t i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - - memcpy(ctx.sk_seed, sk, SPX_N); - memcpy(ctx.pub_seed, pk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - set_type(wots_addr, SPX_ADDR_TYPE_WOTS); - set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); - - /* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ - randombytes(optrand, SPX_N); - /* Compute the digest randomization value. */ - gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); - - /* Derive the message digest and leaf index from R, PK and M. */ - hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); - sig += SPX_N; - - set_tree_addr(wots_addr, tree); - set_keypair_addr(wots_addr, idx_leaf); - - /* Sign the message hash using FORS. */ - fors_sign(sig, root, mhash, &ctx, wots_addr); - sig += SPX_FORS_BYTES; - - for (i = 0; i < SPX_D; i++) { - set_layer_addr(tree_addr, i); - set_tree_addr(tree_addr, tree); - - copy_subtree_addr(wots_addr, tree_addr); - set_keypair_addr(wots_addr, idx_leaf); - - merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); - sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); - tree = tree >> SPX_TREE_HEIGHT; - } - - free_hash_function(&ctx); - - *siglen = SPX_BYTES; - - return 0; -} - -/** - * Verifies a detached signature and message under a given public key. - */ -int crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk) { - spx_ctx ctx; - const uint8_t *pub_root = pk + SPX_N; - uint8_t mhash[SPX_FORS_MSG_BYTES]; - uint8_t wots_pk[SPX_WOTS_BYTES]; - uint8_t root[SPX_N]; - uint8_t leaf[SPX_N]; - unsigned int i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - if (siglen != SPX_BYTES) { - return -1; - } - - memcpy(ctx.pub_seed, pk, SPX_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - initialize_hash_function(&ctx); - - set_type(wots_addr, SPX_ADDR_TYPE_WOTS); - set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); - set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); - - /* Derive the message digest and leaf index from R || PK || M. */ - /* The additional SPX_N is a result of the hash domain separator. */ - hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); - sig += SPX_N; - - /* Layer correctly defaults to 0, so no need to set_layer_addr */ - set_tree_addr(wots_addr, tree); - set_keypair_addr(wots_addr, idx_leaf); - - fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); - sig += SPX_FORS_BYTES; - - /* For each subtree.. */ - for (i = 0; i < SPX_D; i++) { - set_layer_addr(tree_addr, i); - set_tree_addr(tree_addr, tree); - - copy_subtree_addr(wots_addr, tree_addr); - set_keypair_addr(wots_addr, idx_leaf); - - copy_keypair_addr(wots_pk_addr, wots_addr); - - /* The WOTS public key is only correct if the signature was correct. */ - /* Initially, root is the FORS pk, but on subsequent iterations it is - the root of the subtree below the currently processed subtree. */ - wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); - sig += SPX_WOTS_BYTES; - - /* Compute the leaf node using the WOTS public key. */ - thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); - - /* Compute the root node of this subtree. */ - compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, - &ctx, tree_addr); - sig += SPX_TREE_HEIGHT * SPX_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1)); - tree = tree >> SPX_TREE_HEIGHT; - } - - // cleanup - free_hash_function(&ctx); - - /* Check if the root node equals the root node in the public key. */ - if (memcmp(root, pub_root, SPX_N) != 0) { - return -1; - } - - return 0; -} - - -/** - * Returns an array containing the signature followed by the message. - */ -int crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk) { - size_t siglen; - - crypto_sign_signature(sm, &siglen, m, mlen, sk); - - memmove(sm + SPX_BYTES, m, mlen); - *smlen = siglen + mlen; - - return 0; -} - -/** - * Verifies a given signature-message pair under a given public key. - */ -int crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk) { - /* The API caller does not necessarily know what size a signature should be - but SPHINCS+ signatures are always exactly SPX_BYTES. */ - if (smlen < SPX_BYTES) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - *mlen = smlen - SPX_BYTES; - - if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - /* If verification was successful, move the message to the right place. */ - memmove(m, sm + SPX_BYTES, *mlen); - - return 0; -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/thash.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/thash.h deleted file mode 100644 index 8687ccfb4d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/thash.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef SPX_THASH_H -#define SPX_THASH_H - -#include "context.h" -#include "params.h" - -#include - -#define thash SPX_NAMESPACE(thash) -void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/thash_shake_robust.c b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/thash_shake_robust.c deleted file mode 100644 index 696d53c5cc..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/thash_shake_robust.c +++ /dev/null @@ -1,31 +0,0 @@ -#include -#include - -#include "thash.h" - -#include "address.h" -#include "params.h" -#include "utils.h" - -#include "fips202.h" - -/** - * Takes an array of inblocks concatenated arrays of SPX_N bytes. - */ -void thash(unsigned char *out, const unsigned char *in, unsigned int inblocks, - const spx_ctx *ctx, uint32_t addr[8]) { - PQCLEAN_VLA(uint8_t, buf, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); - PQCLEAN_VLA(uint8_t, bitmask, inblocks * SPX_N); - unsigned int i; - - memcpy(buf, ctx->pub_seed, SPX_N); - memcpy(buf + SPX_N, addr, SPX_ADDR_BYTES); - - shake256(bitmask, inblocks * SPX_N, buf, SPX_N + SPX_ADDR_BYTES); - - for (i = 0; i < inblocks * SPX_N; i++) { - buf[SPX_N + SPX_ADDR_BYTES + i] = in[i] ^ bitmask[i]; - } - - shake256(out, SPX_N, buf, SPX_N + SPX_ADDR_BYTES + inblocks * SPX_N); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/utils.c b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/utils.c deleted file mode 100644 index 177b541fb9..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/utils.c +++ /dev/null @@ -1,148 +0,0 @@ -#include - -#include "utils.h" - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "thash.h" - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void ull_to_bytes(unsigned char *out, unsigned int outlen, - unsigned long long in) { - int i; - - /* Iterate over out in decreasing order, for big-endianness. */ - for (i = (signed int)outlen - 1; i >= 0; i--) { - out[i] = in & 0xff; - in = in >> 8; - } -} - -void u32_to_bytes(unsigned char *out, uint32_t in) { - out[0] = (unsigned char)(in >> 24); - out[1] = (unsigned char)(in >> 16); - out[2] = (unsigned char)(in >> 8); - out[3] = (unsigned char)in; -} - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen) { - unsigned long long retval = 0; - unsigned int i; - - for (i = 0; i < inlen; i++) { - retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); - } - return retval; -} - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void compute_root(unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const spx_ctx *ctx, uint32_t addr[8]) { - uint32_t i; - unsigned char buffer[2 * SPX_N]; - - /* If leaf_idx is odd (last bit = 1), current path element is a right child - and auth_path has to go left. Otherwise it is the other way around. */ - if (leaf_idx & 1) { - memcpy(buffer + SPX_N, leaf, SPX_N); - memcpy(buffer, auth_path, SPX_N); - } else { - memcpy(buffer, leaf, SPX_N); - memcpy(buffer + SPX_N, auth_path, SPX_N); - } - auth_path += SPX_N; - - for (i = 0; i < tree_height - 1; i++) { - leaf_idx >>= 1; - idx_offset >>= 1; - /* Set the address of the node we're creating. */ - set_tree_height(addr, i + 1); - set_tree_index(addr, leaf_idx + idx_offset); - - /* Pick the right or left neighbor, depending on parity of the node. */ - if (leaf_idx & 1) { - thash(buffer + SPX_N, buffer, 2, ctx, addr); - memcpy(buffer, auth_path, SPX_N); - } else { - thash(buffer, buffer, 2, ctx, addr); - memcpy(buffer + SPX_N, auth_path, SPX_N); - } - auth_path += SPX_N; - } - - /* The last iteration is exceptional; we do not copy an auth_path node. */ - leaf_idx >>= 1; - idx_offset >>= 1; - set_tree_height(addr, tree_height); - set_tree_index(addr, leaf_idx + idx_offset); - thash(root, buffer, 2, ctx, addr); -} - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -void treehash(unsigned char *root, unsigned char *auth_path, const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const spx_ctx * /* ctx */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), - uint32_t tree_addr[8]) { - PQCLEAN_VLA(uint8_t, stack, (tree_height + 1)*SPX_N); - PQCLEAN_VLA(unsigned int, heights, tree_height + 1); - unsigned int offset = 0; - uint32_t idx; - uint32_t tree_idx; - - for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { - /* Add the next leaf node to the stack. */ - gen_leaf(stack + offset * SPX_N, ctx, idx + idx_offset, tree_addr); - offset++; - heights[offset - 1] = 0; - - /* If this is a node we need for the auth path.. */ - if ((leaf_idx ^ 0x1) == idx) { - memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N); - } - - /* While the top-most nodes are of equal height.. */ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { - /* Compute index of the new node, in the next layer. */ - tree_idx = (idx >> (heights[offset - 1] + 1)); - - /* Set the address of the node we're creating. */ - set_tree_height(tree_addr, heights[offset - 1] + 1); - set_tree_index(tree_addr, - tree_idx + (idx_offset >> (heights[offset - 1] + 1))); - /* Hash the top-most nodes from the stack together. */ - thash(stack + (offset - 2)*SPX_N, - stack + (offset - 2)*SPX_N, 2, ctx, tree_addr); - offset--; - /* Note that the top-most node is now one layer higher. */ - heights[offset - 1]++; - - /* If this is a node we need for the auth path.. */ - if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_path + heights[offset - 1]*SPX_N, - stack + (offset - 1)*SPX_N, SPX_N); - } - } - } - memcpy(root, stack, SPX_N); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/utils.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/utils.h deleted file mode 100644 index 64f5d5a53a..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/utils.h +++ /dev/null @@ -1,58 +0,0 @@ -#ifndef SPX_UTILS_H -#define SPX_UTILS_H - -#include - -#include "compat.h" -#include "context.h" -#include "params.h" - - -/* To support MSVC use alloca() instead of VLAs. See #20. */ - - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -#define ull_to_bytes SPX_NAMESPACE(ull_to_bytes) -void ull_to_bytes(unsigned char *out, unsigned int outlen, - unsigned long long in); -#define u32_to_bytes SPX_NAMESPACE(u32_to_bytes) -void u32_to_bytes(unsigned char *out, uint32_t in); - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -#define bytes_to_ull SPX_NAMESPACE(bytes_to_ull) -unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen); - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -#define compute_root SPX_NAMESPACE(compute_root) -void compute_root(unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const spx_ctx *ctx, uint32_t addr[8]); - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -#define treehash SPX_NAMESPACE(treehash) -void treehash(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const spx_ctx *ctx /* ctx */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */), - uint32_t tree_addr[8]); - - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/utilsx1.c b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/utilsx1.c deleted file mode 100644 index fccb69b35d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/utilsx1.c +++ /dev/null @@ -1,100 +0,0 @@ -#include - -#include "utilsx1.h" - -#include "address.h" -#include "params.h" -#include "thash.h" -#include "utils.h" - -/* - * Generate the entire Merkle tree, computing the authentication path for - * leaf_idx, and the resulting root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE) - * - * This expects tree_addr to be initialized to the addr structures for the - * Merkle tree nodes - * - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - * - * This works by using the standard Merkle tree building algorithm, - */ -void treehashx1(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, - uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* Where to write the leaves */, - const spx_ctx * /* ctx */, - uint32_t idx, void *info), - uint32_t tree_addr[8], - void *info) { - /* This is where we keep the intermediate nodes */ - PQCLEAN_VLA(uint8_t, stack, tree_height * SPX_N); - - uint32_t idx; - uint32_t max_idx = (uint32_t)((1 << tree_height) - 1); - for (idx = 0;; idx++) { - unsigned char current[2 * SPX_N]; /* Current logical node is at */ - /* index[SPX_N]. We do this to minimize the number of copies */ - /* needed during a thash */ - gen_leaf( ¤t[SPX_N], ctx, idx + idx_offset, - info ); - - /* Now combine the freshly generated right node with previously */ - /* generated left ones */ - uint32_t internal_idx_offset = idx_offset; - uint32_t internal_idx = idx; - uint32_t internal_leaf = leaf_idx; - uint32_t h; /* The height we are in the Merkle tree */ - for (h = 0;; h++, internal_idx >>= 1, internal_leaf >>= 1) { - - /* Check if we hit the top of the tree */ - if (h == tree_height) { - /* We hit the root; return it */ - memcpy( root, ¤t[SPX_N], SPX_N ); - return; - } - - /* - * Check if the node we have is a part of the - * authentication path; if it is, write it out - */ - if ((internal_idx ^ internal_leaf) == 0x01) { - memcpy( &auth_path[ h * SPX_N ], - ¤t[SPX_N], - SPX_N ); - } - - /* - * Check if we're at a left child; if so, stop going up the stack - * Exception: if we've reached the end of the tree, keep on going - * (so we combine the last 4 nodes into the one root node in two - * more iterations) - */ - if ((internal_idx & 1) == 0 && idx < max_idx) { - break; - } - - /* Ok, we're at a right node */ - /* Now combine the left and right logical nodes together */ - - /* Set the address of the node we're creating. */ - internal_idx_offset >>= 1; - set_tree_height(tree_addr, h + 1); - set_tree_index(tree_addr, internal_idx / 2 + internal_idx_offset ); - - unsigned char *left = &stack[h * SPX_N]; - memcpy( ¤t[0], left, SPX_N ); - thash( ¤t[1 * SPX_N], - ¤t[0 * SPX_N], - 2, ctx, tree_addr); - } - - /* We've hit a left child; save the current for when we get the */ - /* corresponding right right */ - memcpy( &stack[h * SPX_N], ¤t[SPX_N], SPX_N); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/utilsx1.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/utilsx1.h deleted file mode 100644 index e911d17d53..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/utilsx1.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef SPX_UTILSX4_H -#define SPX_UTILSX4_H - -#include - -#include "context.h" -#include "params.h" - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -#define treehashx1 SPX_NAMESPACE(treehashx1) -void treehashx1(unsigned char *root, unsigned char *auth_path, - const spx_ctx *ctx, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* Where to write the leaf */, - const spx_ctx * /* ctx */, - uint32_t addr_idx, void *info), - uint32_t tree_addrx4[8], void *info); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/wots.c b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/wots.c deleted file mode 100644 index 249717aaa8..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/wots.c +++ /dev/null @@ -1,108 +0,0 @@ -#include -#include - -#include "wots.h" -#include "wotsx1.h" - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "thash.h" -#include "utils.h" -#include "utilsx1.h" - -// TODO clarify address expectations, and make them more uniform. -// TODO i.e. do we expect types to be set already? -// TODO and do we expect modifications or copies? - -/** - * Computes the chaining function. - * out and in have to be n-byte arrays. - * - * Interprets in as start-th value of the chain. - * addr has to contain the address of the chain. - */ -static void gen_chain(unsigned char *out, const unsigned char *in, - unsigned int start, unsigned int steps, - const spx_ctx *ctx, uint32_t addr[8]) { - uint32_t i; - - /* Initialize out with the value at position 'start'. */ - memcpy(out, in, SPX_N); - - /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < SPX_WOTS_W; i++) { - set_hash_addr(addr, i); - thash(out, out, 1, ctx, addr); - } -} - -/** - * base_w algorithm as described in draft. - * Interprets an array of bytes as integers in base w. - * This only works when log_w is a divisor of 8. - */ -static void base_w(unsigned int *output, const int out_len, - const unsigned char *input) { - int in = 0; - int out = 0; - unsigned char total = 0; - int bits = 0; - int consumed; - - for (consumed = 0; consumed < out_len; consumed++) { - if (bits == 0) { - total = input[in]; - in++; - bits += 8; - } - bits -= SPX_WOTS_LOGW; - output[out] = (total >> bits) & (SPX_WOTS_W - 1); - out++; - } -} - -/* Computes the WOTS+ checksum over a message (in base_w). */ -static void wots_checksum(unsigned int *csum_base_w, - const unsigned int *msg_base_w) { - unsigned int csum = 0; - unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8]; - unsigned int i; - - /* Compute checksum. */ - for (i = 0; i < SPX_WOTS_LEN1; i++) { - csum += SPX_WOTS_W - 1 - msg_base_w[i]; - } - - /* Convert checksum to base_w. */ - /* Make sure expected empty zero bits are the least significant bits. */ - csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8)) % 8); - ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); - base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes); -} - -/* Takes a message and derives the matching chain lengths. */ -void chain_lengths(unsigned int *lengths, const unsigned char *msg) { - base_w(lengths, SPX_WOTS_LEN1, msg); - wots_checksum(lengths + SPX_WOTS_LEN1, lengths); -} - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const spx_ctx *ctx, uint32_t addr[8]) { - unsigned int lengths[SPX_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < SPX_WOTS_LEN; i++) { - set_chain_addr(addr, i); - gen_chain(pk + i * SPX_N, sig + i * SPX_N, - lengths[i], SPX_WOTS_W - 1 - lengths[i], ctx, addr); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/wots.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/wots.h deleted file mode 100644 index 4e7692eeef..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/wots.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef SPX_WOTS_H -#define SPX_WOTS_H - -#include - -#include "context.h" -#include "params.h" - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -#define wots_pk_from_sig SPX_NAMESPACE(wots_pk_from_sig) -void wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const spx_ctx *ctx, uint32_t addr[8]); - -/* - * Compute the chain lengths needed for a given message hash - */ -#define chain_lengths SPX_NAMESPACE(chain_lengths) -void chain_lengths(unsigned int *lengths, const unsigned char *msg); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/wotsx1.c b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/wotsx1.c deleted file mode 100644 index 3adec78dfb..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/wotsx1.c +++ /dev/null @@ -1,76 +0,0 @@ -#include -#include - -#include "wots.h" -#include "wotsx1.h" - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "thash.h" -#include "utils.h" - -/* - * This generates a WOTS public key - * It also generates the WOTS signature if leaf_info indicates - * that we're signing with this WOTS key - */ -void wots_gen_leafx1(unsigned char *dest, - const spx_ctx *ctx, - uint32_t leaf_idx, void *v_info) { - struct leaf_info_x1 *info = v_info; - uint32_t *leaf_addr = info->leaf_addr; - uint32_t *pk_addr = info->pk_addr; - unsigned int i, k; - unsigned char pk_buffer[ SPX_WOTS_BYTES ]; - unsigned char *buffer; - uint32_t wots_k_mask; - - if (leaf_idx == info->wots_sign_leaf) { - /* We're traversing the leaf that's signing; generate the WOTS */ - /* signature */ - wots_k_mask = 0; - } else { - /* Nope, we're just generating pk's; turn off the signature logic */ - wots_k_mask = (uint32_t)~0; - } - - set_keypair_addr( leaf_addr, leaf_idx ); - set_keypair_addr( pk_addr, leaf_idx ); - - for (i = 0, buffer = pk_buffer; i < SPX_WOTS_LEN; i++, buffer += SPX_N) { - uint32_t wots_k = info->wots_steps[i] | wots_k_mask; /* Set wots_k to */ - /* the step if we're generating a signature, ~0 if we're not */ - - /* Start with the secret seed */ - set_chain_addr(leaf_addr, i); - set_hash_addr(leaf_addr, 0); - set_type(leaf_addr, SPX_ADDR_TYPE_WOTSPRF); - - prf_addr(buffer, ctx, leaf_addr); - - set_type(leaf_addr, SPX_ADDR_TYPE_WOTS); - - /* Iterate down the WOTS chain */ - for (k = 0;; k++) { - /* Check if this is the value that needs to be saved as a */ - /* part of the WOTS signature */ - if (k == wots_k) { - memcpy( info->wots_sig + i * SPX_N, buffer, SPX_N ); - } - - /* Check if we hit the top of the chain */ - if (k == SPX_WOTS_W - 1) { - break; - } - - /* Iterate one step on the chain */ - set_hash_addr(leaf_addr, k); - - thash(buffer, buffer, 1, ctx, leaf_addr); - } - } - - /* Do the final thash to generate the public keys */ - thash(dest, pk_buffer, SPX_WOTS_LEN, ctx, pk_addr); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/wotsx1.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/wotsx1.h deleted file mode 100644 index e617929f96..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256s-robust_clean/wotsx1.h +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef WOTSX1_H_ -#define WOTSX1_H_ - -#include - -#include "context.h" -#include "params.h" - -/* - * This is here to provide an interface to the internal wots_gen_leafx1 - * routine. While this routine is not referenced in the package outside of - * wots.c, it is called from the stand-alone benchmark code to characterize - * the performance - */ -struct leaf_info_x1 { - unsigned char *wots_sig; - uint32_t wots_sign_leaf; /* The index of the WOTS we're using to sign */ - uint32_t *wots_steps; - uint32_t leaf_addr[8]; - uint32_t pk_addr[8]; -}; - -/* Macro to set the leaf_info to something 'benign', that is, it would */ -/* run with the same time as it does during the real signing process */ -/* Used only by the benchmark code */ -#define INITIALIZE_LEAF_INFO_X1(info, addr, step_buffer) { \ - (info).wots_sig = 0; \ - (info).wots_sign_leaf = ~0; \ - (info).wots_steps = step_buffer; \ - memcpy( &(info).leaf_addr[0], (addr), 32 ); \ - memcpy( &(info).pk_addr[0], (addr), 32 ); \ - } - -#define wots_gen_leafx1 SPX_NAMESPACE(wots_gen_leafx1) -void wots_gen_leafx1(unsigned char *dest, - const spx_ctx *ctx, - uint32_t leaf_idx, void *v_info); - -#endif /* WOTSX1_H_ */ diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_avx2/LICENSE b/src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_avx2/LICENSE deleted file mode 100644 index 670154e353..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_avx2/LICENSE +++ /dev/null @@ -1,116 +0,0 @@ -CC0 1.0 Universal - -Statement of Purpose - -The laws of most jurisdictions throughout the world automatically confer -exclusive Copyright and Related Rights (defined below) upon the creator and -subsequent owner(s) (each and all, an "owner") of an original work of -authorship and/or a database (each, a "Work"). - -Certain owners wish to permanently relinquish those rights to a Work for the -purpose of contributing to a commons of creative, cultural and scientific -works ("Commons") that the public can reliably and without fear of later -claims of infringement build upon, modify, incorporate in other works, reuse -and redistribute as freely as possible in any form whatsoever and for any -purposes, including without limitation commercial purposes. These owners may -contribute to the Commons to promote the ideal of a free culture and the -further production of creative, cultural and scientific works, or to gain -reputation or greater distribution for their Work in part through the use and -efforts of others. - -For these and/or other purposes and motivations, and without any expectation -of additional consideration or compensation, the person associating CC0 with a -Work (the "Affirmer"), to the extent that he or she is an owner of Copyright -and Related Rights in the Work, voluntarily elects to apply CC0 to the Work -and publicly distribute the Work under its terms, with knowledge of his or her -Copyright and Related Rights in the Work and the meaning and intended legal -effect of CC0 on those rights. - -1. Copyright and Related Rights. A Work made available under CC0 may be -protected by copyright and related or neighboring rights ("Copyright and -Related Rights"). Copyright and Related Rights include, but are not limited -to, the following: - - i. the right to reproduce, adapt, distribute, perform, display, communicate, - and translate a Work; - - ii. moral rights retained by the original author(s) and/or performer(s); - - iii. publicity and privacy rights pertaining to a person's image or likeness - depicted in a Work; - - iv. rights protecting against unfair competition in regards to a Work, - subject to the limitations in paragraph 4(a), below; - - v. rights protecting the extraction, dissemination, use and reuse of data in - a Work; - - vi. database rights (such as those arising under Directive 96/9/EC of the - European Parliament and of the Council of 11 March 1996 on the legal - protection of databases, and under any national implementation thereof, - including any amended or successor version of such directive); and - - vii. other similar, equivalent or corresponding rights throughout the world - based on applicable law or treaty, and any national implementations thereof. - -2. Waiver. To the greatest extent permitted by, but not in contravention of, -applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and -unconditionally waives, abandons, and surrenders all of Affirmer's Copyright -and Related Rights and associated claims and causes of action, whether now -known or unknown (including existing as well as future claims and causes of -action), in the Work (i) in all territories worldwide, (ii) for the maximum -duration provided by applicable law or treaty (including future time -extensions), (iii) in any current or future medium and for any number of -copies, and (iv) for any purpose whatsoever, including without limitation -commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes -the Waiver for the benefit of each member of the public at large and to the -detriment of Affirmer's heirs and successors, fully intending that such Waiver -shall not be subject to revocation, rescission, cancellation, termination, or -any other legal or equitable action to disrupt the quiet enjoyment of the Work -by the public as contemplated by Affirmer's express Statement of Purpose. - -3. Public License Fallback. Should any part of the Waiver for any reason be -judged legally invalid or ineffective under applicable law, then the Waiver -shall be preserved to the maximum extent permitted taking into account -Affirmer's express Statement of Purpose. In addition, to the extent the Waiver -is so judged Affirmer hereby grants to each affected person a royalty-free, -non transferable, non sublicensable, non exclusive, irrevocable and -unconditional license to exercise Affirmer's Copyright and Related Rights in -the Work (i) in all territories worldwide, (ii) for the maximum duration -provided by applicable law or treaty (including future time extensions), (iii) -in any current or future medium and for any number of copies, and (iv) for any -purpose whatsoever, including without limitation commercial, advertising or -promotional purposes (the "License"). The License shall be deemed effective as -of the date CC0 was applied by Affirmer to the Work. Should any part of the -License for any reason be judged legally invalid or ineffective under -applicable law, such partial invalidity or ineffectiveness shall not -invalidate the remainder of the License, and in such case Affirmer hereby -affirms that he or she will not (i) exercise any of his or her remaining -Copyright and Related Rights in the Work or (ii) assert any associated claims -and causes of action with respect to the Work, in either case contrary to -Affirmer's express Statement of Purpose. - -4. Limitations and Disclaimers. - - a. No trademark or patent rights held by Affirmer are waived, abandoned, - surrendered, licensed or otherwise affected by this document. - - b. Affirmer offers the Work as-is and makes no representations or warranties - of any kind concerning the Work, express, implied, statutory or otherwise, - including without limitation warranties of title, merchantability, fitness - for a particular purpose, non infringement, or the absence of latent or - other defects, accuracy, or the present or absence of errors, whether or not - discoverable, all to the greatest extent permissible under applicable law. - - c. Affirmer disclaims responsibility for clearing rights of other persons - that may apply to the Work or any use thereof, including without limitation - any person's Copyright and Related Rights in the Work. Further, Affirmer - disclaims responsibility for obtaining any necessary consents, permissions - or other rights required for any use of the Work. - - d. Affirmer understands and acknowledges that Creative Commons is not a - party to this document and has no duty or obligation with respect to this - CC0 or use of the Work. - -For more information, please see - diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_avx2/address.c b/src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_avx2/address.c deleted file mode 100644 index 68ccca4f75..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_avx2/address.c +++ /dev/null @@ -1,78 +0,0 @@ -#include - -#include "address.h" -#include "params.h" -#include "utils.h" - -void PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]) { - int i; - - for (i = 0; i < 8; i++) { - PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_ull_to_bytes( - bytes + i * 4, 4, addr[i]); - } -} - -void PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_set_layer_addr( - uint32_t addr[8], uint32_t layer) { - addr[0] = layer; -} - -void PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_set_tree_addr( - uint32_t addr[8], uint64_t tree) { - addr[1] = 0; - addr[2] = (uint32_t) (tree >> 32); - addr[3] = (uint32_t) tree; -} - -void PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_set_type( - uint32_t addr[8], uint32_t type) { - addr[4] = type; -} - -void PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; -} - -/* These functions are used for OTS addresses. */ - -void PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_set_keypair_addr( - uint32_t addr[8], uint32_t keypair) { - addr[5] = keypair; -} - -void PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; - out[5] = in[5]; -} - -void PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_set_chain_addr( - uint32_t addr[8], uint32_t chain) { - addr[6] = chain; -} - -void PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_set_hash_addr( - uint32_t addr[8], uint32_t hash) { - addr[7] = hash; -} - -/* These functions are used for all hash tree addresses (including FORS). */ - -void PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_set_tree_height( - uint32_t addr[8], uint32_t tree_height) { - addr[6] = tree_height; -} - -void PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_set_tree_index( - uint32_t addr[8], uint32_t tree_index) { - addr[7] = tree_index; -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_avx2/address.h b/src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_avx2/address.h deleted file mode 100644 index f46651ff4f..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_avx2/address.h +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_ADDRESS_H -#define PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_ADDRESS_H - -#include - -#define PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_ADDR_TYPE_WOTS 0 -#define PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_ADDR_TYPE_WOTSPK 1 -#define PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_ADDR_TYPE_HASHTREE 2 -#define PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_ADDR_TYPE_FORSTREE 3 -#define PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_ADDR_TYPE_FORSPK 4 - -void PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]); - -void PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_set_layer_addr( - uint32_t addr[8], uint32_t layer); - -void PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_set_tree_addr( - uint32_t addr[8], uint64_t tree); - -void PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_set_type( - uint32_t addr[8], uint32_t type); - -/* Copies the layer and tree part of one address into the other */ -void PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for WOTS and FORS addresses. */ - -void PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_set_keypair_addr( - uint32_t addr[8], uint32_t keypair); - -void PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_set_chain_addr( - uint32_t addr[8], uint32_t chain); - -void PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_set_hash_addr( - uint32_t addr[8], uint32_t hash); - -void PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for all hash tree addresses (including FORS). */ - -void PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_set_tree_height( - uint32_t addr[8], uint32_t tree_height); - -void PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_set_tree_index( - uint32_t addr[8], uint32_t tree_index); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_avx2/api.h b/src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_avx2/api.h deleted file mode 100644 index 2a38ede1b9..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_avx2/api.h +++ /dev/null @@ -1,81 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_API_H -#define PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_API_H - -#include -#include - - - -#define PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_CRYPTO_ALGNAME "SPHINCS+" - -#define PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_CRYPTO_SECRETKEYBYTES 64 -#define PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_CRYPTO_PUBLICKEYBYTES 32 -#define PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_CRYPTO_BYTES 17088 -#define PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_CRYPTO_SEEDBYTES 48 - - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_avx2/fors.c b/src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_avx2/fors.c deleted file mode 100644 index 668f87ded2..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_avx2/fors.c +++ /dev/null @@ -1,206 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "fors.h" -#include "hash.h" -#include "hashx4.h" -#include "thash.h" -#include "thashx4.h" -#include "utils.h" -#include "utilsx4.h" - -static void fors_gen_skx4(unsigned char *sk0, - unsigned char *sk1, - unsigned char *sk2, - unsigned char *sk3, const unsigned char *sk_seed, - uint32_t fors_leaf_addrx4[4 * 8], - const hash_state *state_seeded) { - PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_prf_addrx4(sk0, sk1, sk2, sk3, sk_seed, fors_leaf_addrx4, state_seeded); -} - -static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, - const unsigned char *pub_seed, - uint32_t fors_leaf_addr[8], const hash_state *state_seeded) { - PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_thash_1(leaf, sk, pub_seed, fors_leaf_addr, state_seeded); -} - -static void fors_sk_to_leafx4(unsigned char *leaf0, - unsigned char *leaf1, - unsigned char *leaf2, - unsigned char *leaf3, - const unsigned char *sk0, - const unsigned char *sk1, - const unsigned char *sk2, - const unsigned char *sk3, - const unsigned char *pub_seed, - uint32_t fors_leaf_addrx4[4 * 8], - const hash_state *state_seeded) { - PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_thashx4_1(leaf0, leaf1, leaf2, leaf3, - sk0, sk1, sk2, sk3, pub_seed, fors_leaf_addrx4, state_seeded); -} - -static void fors_gen_leafx4(unsigned char *leaf0, - unsigned char *leaf1, - unsigned char *leaf2, - unsigned char *leaf3, - const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx0, - uint32_t addr_idx1, - uint32_t addr_idx2, - uint32_t addr_idx3, - const uint32_t fors_tree_addr[8], - const hash_state *state_seeded) { - uint32_t fors_leaf_addrx4[4 * 8] = {0}; - unsigned int j; - - /* Only copy the parts that must be kept in fors_leaf_addrx4. */ - for (j = 0; j < 4; j++) { - PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_copy_keypair_addr(fors_leaf_addrx4 + j * 8, fors_tree_addr); - PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_set_type(fors_leaf_addrx4 + j * 8, PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_ADDR_TYPE_FORSTREE); - } - - PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_set_tree_index(fors_leaf_addrx4 + 0 * 8, addr_idx0); - PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_set_tree_index(fors_leaf_addrx4 + 1 * 8, addr_idx1); - PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_set_tree_index(fors_leaf_addrx4 + 2 * 8, addr_idx2); - PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_set_tree_index(fors_leaf_addrx4 + 3 * 8, addr_idx3); - - fors_gen_skx4(leaf0, leaf1, leaf2, leaf3, sk_seed, fors_leaf_addrx4, state_seeded); - fors_sk_to_leafx4(leaf0, leaf1, leaf2, leaf3, - leaf0, leaf1, leaf2, leaf3, pub_seed, fors_leaf_addrx4, state_seeded); -} - -/** - * Interprets m as PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_FORS_HEIGHT-bit unsigned integers. - * Assumes m contains at least PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_FORS_TREES bits. - * Assumes indices has space for PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_FORS_TREES integers. - */ -static void message_to_indices(uint32_t *indices, const unsigned char *m) { - unsigned int i, j; - unsigned int offset = 0; - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_FORS_TREES; i++) { - indices[i] = 0; - for (j = 0; j < PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_FORS_HEIGHT; j++) { - indices[i] ^= (((uint32_t)m[offset >> 3] >> (offset & 0x7)) & 0x1) << j; - offset++; - } - } -} - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *state_seeded) { - /* Round up to multiple of 4 to prevent out-of-bounds for x4 parallelism */ - uint32_t indices[(PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_FORS_TREES + 3) & ~3] = {0}; - unsigned char roots[((PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_FORS_TREES + 3) & ~3) * PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N]; - /* Sign to a buffer, since we may not have a nice multiple of 4 and would - otherwise overrun the signature. */ - unsigned char sigbufx4[4 * PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N * (1 + PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_FORS_HEIGHT)]; - uint32_t fors_tree_addrx4[4 * 8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset[4] = {0}; - unsigned int i, j; - - for (j = 0; j < 4; j++) { - PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_copy_keypair_addr(fors_tree_addrx4 + j * 8, fors_addr); - PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_set_type(fors_tree_addrx4 + j * 8, PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_ADDR_TYPE_FORSTREE); - } - - PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_copy_keypair_addr(fors_pk_addr, fors_addr); - PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_set_type(fors_pk_addr, PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < ((PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_FORS_TREES + 3) & ~0x3); i += 4) { - for (j = 0; j < 4; j++) { - if (i + j < PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_FORS_TREES) { - idx_offset[j] = (i + j) * (1 << PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_FORS_HEIGHT); - - PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_set_tree_height(fors_tree_addrx4 + j * 8, 0); - PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_set_tree_index(fors_tree_addrx4 + j * 8, - indices[i + j] + idx_offset[j]); - } - } - - /* Include the secret key part that produces the selected leaf nodes. */ - fors_gen_skx4(sigbufx4 + 0 * PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N, - sigbufx4 + 1 * PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N, - sigbufx4 + 2 * PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N, - sigbufx4 + 3 * PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N, - sk_seed, fors_tree_addrx4, state_seeded); - - PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_treehashx4_FORS_HEIGHT(roots + i * PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N, sigbufx4 + 4 * PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N, sk_seed, pub_seed, - &indices[i], idx_offset, fors_gen_leafx4, fors_tree_addrx4, - state_seeded); - - for (j = 0; j < 4; j++) { - if (i + j < PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_FORS_TREES) { - memcpy(sig, sigbufx4 + j * PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N, PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N); - memcpy(sig + PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N, - sigbufx4 + 4 * PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N + j * PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N * PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_FORS_HEIGHT, - PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N * PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_FORS_HEIGHT); - sig += PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N * (1 + PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_FORS_HEIGHT); - } - } - } - - /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_thash_FORS_TREES(pk, roots, pub_seed, fors_pk_addr, state_seeded); -} - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, - const uint32_t fors_addr[8], - const hash_state *state_seeded) { - uint32_t indices[PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_FORS_TREES]; - unsigned char roots[PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_FORS_TREES * PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N]; - unsigned char leaf[PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N]; - uint32_t fors_tree_addr[8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_copy_keypair_addr(fors_tree_addr, fors_addr); - PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_copy_keypair_addr(fors_pk_addr, fors_addr); - - PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_set_type(fors_tree_addr, PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_set_type(fors_pk_addr, PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_FORS_TREES; i++) { - idx_offset = i * (1 << PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_FORS_HEIGHT); - - PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_set_tree_height(fors_tree_addr, 0); - PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Derive the leaf from the included secret key part. */ - fors_sk_to_leaf(leaf, sig, pub_seed, fors_tree_addr, state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N; - - /* Derive the corresponding root node of this tree. */ - PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_compute_root(roots + i * PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N, leaf, indices[i], idx_offset, - sig, PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_FORS_HEIGHT, pub_seed, fors_tree_addr, - state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N * PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_thash_FORS_TREES(pk, roots, pub_seed, fors_pk_addr, state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_avx2/fors.h b/src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_avx2/fors.h deleted file mode 100644 index 103d23725d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_avx2/fors.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_FORS_H -#define PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_FORS_H - -#include - -#include "hash_state.h" -#include "params.h" - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_fors_sign( - unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *hash_state_seeded); - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_fors_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, const uint32_t fors_addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_avx2/hash.h b/src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_avx2/hash.h deleted file mode 100644 index 66bee453ba..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_avx2/hash.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_HASH_H -#define PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_HASH_H - -#include "hash_state.h" - -#include -#include - -void PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_initialize_hash_function( - hash_state *hash_state_seeded, - const unsigned char *pub_seed, const unsigned char *sk_seed); - -void PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_destroy_hash_function(hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_avx2/hash_shake256.c b/src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_avx2/hash_shake256.c deleted file mode 100644 index fe3aa3bdb8..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_avx2/hash_shake256.c +++ /dev/null @@ -1,106 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "utils.h" - -#include "fips202.h" - -/* For SHAKE256, there is no immediate reason to initialize at the start, - so this function is an empty operation. */ -void PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_initialize_hash_function( - hash_state *hash_state_seeded, // NOLINT(readability-non-const-parameter) - const unsigned char *pub_seed, const unsigned char *sk_seed) { - (void)hash_state_seeded; /* Suppress an 'unused parameter' warning. */ - (void)pub_seed; /* Suppress an 'unused parameter' warning. */ - (void)sk_seed; /* Suppress an 'unused parameter' warning. */ -} - -/* This is not necessary for SHAKE256, so we don't do anything */ -void PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_destroy_hash_function( - hash_state *hash_state_seeded) { // NOLINT(readability-non-const-parameter) - (void)hash_state_seeded; -} - -/* - * Computes PRF(key, addr), given a secret key of PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N bytes and an address - */ -void PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded) { - unsigned char buf[PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_ADDR_BYTES]; - - memcpy(buf, key, PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N); - PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_addr_to_bytes(buf + PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N, addr); - - shake256(out, PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N, buf, PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_ADDR_BYTES); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} - -/** - * Computes the message-dependent randomness R, using a secret seed and an - * optional randomization value as well as the message. - */ -void PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded) { - shake256incctx state; - - shake256_inc_init(&state); - shake256_inc_absorb(&state, sk_prf, PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N); - shake256_inc_absorb(&state, optrand, PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N); - shake256_inc_absorb(&state, m, mlen); - shake256_inc_finalize(&state); - shake256_inc_squeeze(R, PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N, &state); - shake256_inc_ctx_release(&state); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} - -/** - * Computes the message hash using R, the public key, and the message. - * Outputs the message digest and the index of the leaf. The index is split in - * the tree index and the leaf index, for convenient copying to an address. - */ -void PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded) { -#define PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_TREE_BITS (PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_TREE_HEIGHT * (PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_D - 1)) -#define PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_TREE_BYTES ((PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_TREE_BITS + 7) / 8) -#define PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_LEAF_BITS PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_TREE_HEIGHT -#define PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_LEAF_BYTES ((PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_LEAF_BITS + 7) / 8) -#define PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_DGST_BYTES (PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_FORS_MSG_BYTES + PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_TREE_BYTES + PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_LEAF_BYTES) - - unsigned char buf[PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_DGST_BYTES]; - unsigned char *bufp = buf; - shake256incctx state; - - shake256_inc_init(&state); - shake256_inc_absorb(&state, R, PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N); - shake256_inc_absorb(&state, pk, PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_PK_BYTES); - shake256_inc_absorb(&state, m, mlen); - shake256_inc_finalize(&state); - shake256_inc_squeeze(buf, PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_DGST_BYTES, &state); - shake256_inc_ctx_release(&state); - - memcpy(digest, bufp, PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_FORS_MSG_BYTES); - bufp += PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_FORS_MSG_BYTES; - - *tree = PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_bytes_to_ull( - bufp, PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_TREE_BYTES); - *tree &= (~(uint64_t)0) >> (64 - PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_TREE_BITS); - bufp += PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_TREE_BYTES; - - *leaf_idx = (uint32_t)PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_bytes_to_ull( - bufp, PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_LEAF_BYTES); - *leaf_idx &= (~(uint32_t)0) >> (32 - PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_LEAF_BITS); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_avx2/hash_shake256x4.c b/src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_avx2/hash_shake256x4.c deleted file mode 100644 index b849558406..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_avx2/hash_shake256x4.c +++ /dev/null @@ -1,38 +0,0 @@ -#include -#include - -#include "address.h" -#include "fips202x4.h" -#include "hashx4.h" -#include "params.h" - -/* - * 4-way parallel version of prf_addr; takes 4x as much input and output - */ -void PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_prf_addrx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const unsigned char *key, - const uint32_t addrx4[4 * 8], - const hash_state *state_seeded) { - unsigned char bufx4[4 * (PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_ADDR_BYTES)]; - unsigned int j; - - for (j = 0; j < 4; j++) { - memcpy(bufx4 + j * (PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_ADDR_BYTES), key, PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N); - PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_addr_to_bytes(bufx4 + PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N + j * (PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_ADDR_BYTES), addrx4 + j * 8); - } - - PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_shake256x4(out0, - out1, - out2, - out3, PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N, - bufx4 + 0 * (PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_ADDR_BYTES), - bufx4 + 1 * (PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_ADDR_BYTES), - bufx4 + 2 * (PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_ADDR_BYTES), - bufx4 + 3 * (PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_ADDR_BYTES), PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_ADDR_BYTES); - - /* Avoid unused parameter warning */ - (void)state_seeded; -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_avx2/hash_state.h b/src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_avx2/hash_state.h deleted file mode 100644 index 675bf23bc3..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_avx2/hash_state.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_HASH_STATE_H -#define PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_HASH_STATE_H - -/** - * Defines the type of the hash function state. - * - * Don't be fooled into thinking this instance of SPHINCS+ isn't stateless! - * - * From Section 7.2.2 from the SPHINCS+ round-2 specification: - * - * Each of the instances of the tweakable hash function take PK.seed as its - * first input, which is constant for a given key pair – and, thus, across - * a single signature. This leads to a lot of redundant computation. To remedy - * this, we pad PK.seed to the length of a full 64-byte SHA-256 input block. - * Because of the Merkle-DamgÃ¥rd construction that underlies SHA-256, this - * allows for reuse of the intermediate SHA-256 state after the initial call to - * the compression function which improves performance. - * - * We pass this hash state around in functions, because otherwise we need to - * have a global variable. - * - * SHAKE256 does not need this state. Because this implementation is generated - * from a shared code base, we still need to specify some hash_state as it is - * still passed around. We chose to use an `int` as a placeholder for this - * purpose. - */ - -typedef int hash_state; - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_avx2/hashx4.h b/src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_avx2/hashx4.h deleted file mode 100644 index 8cb4322ecb..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_avx2/hashx4.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_HASHX4_H -#define PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_HASHX4_H - -#include - -#include "hash_state.h" - -void PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_prf_addrx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const unsigned char *key, - const uint32_t addrx4[4 * 8], - const hash_state *state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_avx2/params.h b/src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_avx2/params.h deleted file mode 100644 index fb2f1dc4fe..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_avx2/params.h +++ /dev/null @@ -1,53 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_PARAMS_H -#define PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_PARAMS_H - -/* Hash output length in bytes. */ -#define PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N 16 -/* Height of the hypertree. */ -#define PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_FULL_HEIGHT 66 -/* Number of subtree layer. */ -#define PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_D 22 -/* FORS tree dimensions. */ -#define PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_FORS_HEIGHT 6 -#define PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_FORS_TREES 33 -/* Winternitz parameter, */ -#define PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_WOTS_W 16 - -/* The hash function is defined by linking a different hash.c file, as opposed - to setting a #define constant. */ - -/* For clarity */ -#define PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_ADDR_BYTES 32 - -/* WOTS parameters. */ -#define PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_WOTS_LOGW 4 - -#define PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_WOTS_LEN1 (8 * PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N / PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_WOTS_LOGW) - -/* PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#define PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_WOTS_LEN2 3 - -#define PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_WOTS_LEN (PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_WOTS_LEN1 + PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_WOTS_LEN2) -#define PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_WOTS_BYTES (PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_WOTS_LEN * PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N) -#define PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_WOTS_PK_BYTES PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_WOTS_BYTES - -/* Subtree size. */ -#define PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_TREE_HEIGHT (PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_FULL_HEIGHT / PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_D) - -/* FORS parameters. */ -#define PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_FORS_MSG_BYTES ((PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_FORS_TREES + 7) / 8) -#define PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_FORS_BYTES ((PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_FORS_HEIGHT + 1) * PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_FORS_TREES * PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N) -#define PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_FORS_PK_BYTES PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N - -/* Resulting SPX sizes. */ -#define PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_BYTES (PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_FORS_BYTES + PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_D * PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_WOTS_BYTES +\ - PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_FULL_HEIGHT * PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N) -#define PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_PK_BYTES (2 * PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N) -#define PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_SK_BYTES (2 * PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_PK_BYTES) - -/* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ -#define PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_OPTRAND_BYTES 32 - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_avx2/sign.c b/src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_avx2/sign.c deleted file mode 100644 index ee73109412..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_avx2/sign.c +++ /dev/null @@ -1,409 +0,0 @@ -#include -#include -#include -#include - -#include "address.h" -#include "api.h" -#include "fors.h" -#include "hash.h" -#include "hash_state.h" -#include "params.h" -#include "randombytes.h" -#include "thash.h" -#include "utils.h" -#include "wots.h" - - -/** - * Computes the leaf at a given address. First generates the WOTS key pair, - * then computes leaf by hashing horizontally. - */ -static void wots_gen_leaf(unsigned char *leaf, const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx, const uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - unsigned char pk[PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_WOTS_BYTES]; - uint32_t wots_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_set_type( - wots_addr, PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_set_type( - wots_pk_addr, PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_ADDR_TYPE_WOTSPK); - - PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_set_keypair_addr( - wots_addr, addr_idx); - PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_wots_gen_pk( - pk, sk_seed, pub_seed, wots_addr, hash_state_seeded); - - PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_copy_keypair_addr( - wots_pk_addr, wots_addr); - PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_thash_WOTS_LEN( - leaf, pk, pub_seed, wots_pk_addr, hash_state_seeded); -} - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_crypto_sign_secretkeybytes(void) { - return PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_CRYPTO_SECRETKEYBYTES; -} - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_crypto_sign_publickeybytes(void) { - return PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_CRYPTO_PUBLICKEYBYTES; -} - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_crypto_sign_bytes(void) { - return PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_CRYPTO_BYTES; -} - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_crypto_sign_seedbytes(void) { - return PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_CRYPTO_SEEDBYTES; -} - -/* - * Generates an SPX key pair given a seed of length - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed) { - /* We do not need the auth path in key generation, but it simplifies the - code to have just one treehash routine that computes both root and path - in one function. */ - unsigned char auth_path[PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_TREE_HEIGHT * PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N]; - uint32_t top_tree_addr[8] = {0}; - hash_state hash_state_seeded; - - PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_set_layer_addr( - top_tree_addr, PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_D - 1); - PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_set_type( - top_tree_addr, PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_ADDR_TYPE_HASHTREE); - - /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ - memcpy(sk, seed, PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_CRYPTO_SEEDBYTES); - - memcpy(pk, sk + 2 * PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N, PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_initialize_hash_function(&hash_state_seeded, pk, sk); - - /* Compute root node of the top-most subtree. */ - PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_treehash_TREE_HEIGHT( - sk + 3 * PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N, auth_path, sk, sk + 2 * PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N, 0, 0, - wots_gen_leaf, top_tree_addr, &hash_state_seeded); - - memcpy(pk + PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N, sk + 3 * PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N, PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N); - - return 0; -} - -/* - * Generates an SPX key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk) { - - // guarantee alignment of pk - union { - __m128 _x[PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_CRYPTO_PUBLICKEYBYTES / 16]; - uint8_t pk[PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_CRYPTO_PUBLICKEYBYTES]; - } aligned_pk; - - // guarantee alignment of sk - union { - __m128 _x[PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_CRYPTO_SECRETKEYBYTES / 16]; - uint8_t sk[PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_CRYPTO_SECRETKEYBYTES]; - } aligned_sk; - - union { - __m128 _x[PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_CRYPTO_SEEDBYTES / 16]; - uint8_t seed[PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_CRYPTO_SEEDBYTES]; - } aligned_seed; - randombytes(aligned_seed.seed, PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_CRYPTO_SEEDBYTES); - - PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_crypto_sign_seed_keypair( - aligned_pk.pk, aligned_sk.sk, aligned_seed.seed); - memcpy(pk, aligned_pk.pk, PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_CRYPTO_PUBLICKEYBYTES); - memcpy(sk, aligned_sk.sk, PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_CRYPTO_SECRETKEYBYTES); - - return 0; -} - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - // guarantee alignment of sk - union { - __m128 *_x; - uint8_t sk[PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_CRYPTO_SECRETKEYBYTES]; - } aligned_sk; - memcpy(aligned_sk.sk, sk, PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_CRYPTO_SECRETKEYBYTES); - sk = aligned_sk.sk; - - // guarantee alignment of sig - union { - __m128 *_x; - uint8_t sig[PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_BYTES]; - } aligned_sig; - uint8_t *orig_sig = sig; - sig = (uint8_t *)aligned_sig.sig; - - const unsigned char *sk_seed = sk; - const unsigned char *sk_prf = sk + PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N; - const unsigned char *pk = sk + 2 * PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N; - const unsigned char *pub_seed = pk; - - unsigned char optrand[PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N]; - unsigned char mhash[PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_FORS_MSG_BYTES]; - unsigned char root[PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N]; - uint32_t i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - - hash_state hash_state_seeded; - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_initialize_hash_function( - &hash_state_seeded, - pub_seed, sk_seed); - - PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_set_type( - wots_addr, PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_set_type( - tree_addr, PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_ADDR_TYPE_HASHTREE); - - /* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ - randombytes(optrand, PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N); - /* Compute the digest randomization value. */ - PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_gen_message_random( - sig, sk_prf, optrand, m, mlen, &hash_state_seeded); - - /* Derive the message digest and leaf index from R, PK and M. */ - PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N; - - PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_set_keypair_addr( - wots_addr, idx_leaf); - - /* Sign the message hash using FORS. */ - PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_fors_sign( - sig, root, mhash, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_FORS_BYTES; - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_D; i++) { - PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_set_tree_addr(tree_addr, tree); - - PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_set_keypair_addr( - wots_addr, idx_leaf); - - /* Compute a WOTS signature. */ - PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_wots_sign( - sig, root, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_WOTS_BYTES; - - /* Compute the authentication path for the used WOTS leaf. */ - PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_treehash_TREE_HEIGHT( - root, sig, sk_seed, pub_seed, idx_leaf, 0, - wots_gen_leaf, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_TREE_HEIGHT * PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_TREE_HEIGHT; - } - - memcpy(orig_sig, aligned_sig.sig, PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_BYTES); - *siglen = PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_BYTES; - - return 0; -} - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk) { - // guarantee alignment of pk - union { - __m128 *_x; - uint8_t pk[PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_CRYPTO_PUBLICKEYBYTES]; - } aligned_pk; - memcpy(aligned_pk.pk, pk, PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_CRYPTO_PUBLICKEYBYTES); - pk = aligned_pk.pk; - - const unsigned char *pub_seed = pk; - const unsigned char *pub_root = pk + PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N; - unsigned char mhash[PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_FORS_MSG_BYTES]; - unsigned char wots_pk[PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_WOTS_BYTES]; - unsigned char root[PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N]; - unsigned char leaf[PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N]; - unsigned int i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - hash_state hash_state_seeded; - - if (siglen != PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_BYTES) { - return -1; - } - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_initialize_hash_function( - &hash_state_seeded, - pub_seed, NULL); - - PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_set_type( - wots_addr, PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_set_type( - tree_addr, PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_ADDR_TYPE_HASHTREE); - PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_set_type( - wots_pk_addr, PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_ADDR_TYPE_WOTSPK); - - /* Derive the message digest and leaf index from R || PK || M. */ - /* The additional PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N is a result of the hash domain separator. */ - PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N; - - /* Layer correctly defaults to 0, so no need to set_layer_addr */ - PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_set_keypair_addr( - wots_addr, idx_leaf); - - PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_fors_pk_from_sig( - root, sig, mhash, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_FORS_BYTES; - - /* For each subtree.. */ - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_D; i++) { - PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_set_tree_addr(tree_addr, tree); - - PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_set_keypair_addr( - wots_addr, idx_leaf); - - PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_copy_keypair_addr( - wots_pk_addr, wots_addr); - - /* The WOTS public key is only correct if the signature was correct. */ - /* Initially, root is the FORS pk, but on subsequent iterations it is - the root of the subtree below the currently processed subtree. */ - PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_wots_pk_from_sig( - wots_pk, sig, root, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_WOTS_BYTES; - - /* Compute the leaf node using the WOTS public key. */ - PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_thash_WOTS_LEN( - leaf, wots_pk, pub_seed, wots_pk_addr, &hash_state_seeded); - - /* Compute the root node of this subtree. */ - PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_compute_root( - root, leaf, idx_leaf, 0, sig, PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_TREE_HEIGHT, - pub_seed, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_TREE_HEIGHT * PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_TREE_HEIGHT; - } - - /* Check if the root node equals the root node in the public key. */ - if (memcmp(root, pub_root, PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N) != 0) { - return -1; - } - - return 0; -} - - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - size_t siglen; - - PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_crypto_sign_signature( - sm, &siglen, m, mlen, sk); - - memmove(sm + PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_BYTES, m, mlen); - *smlen = siglen + mlen; - - return 0; -} - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk) { - - // guarantee alignment of pk - union { - __m128 *_x; - uint8_t pk[PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_CRYPTO_PUBLICKEYBYTES]; - } aligned_pk; - memcpy(aligned_pk.pk, pk, PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_CRYPTO_PUBLICKEYBYTES); - pk = aligned_pk.pk; - - - /* The API caller does not necessarily know what size a signature should be - but SPHINCS+ signatures are always exactly PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_BYTES. */ - if (smlen < PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_BYTES) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - *mlen = smlen - PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_BYTES; - - if (PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_crypto_sign_verify( - sm, PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_BYTES, sm + PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_BYTES, *mlen, pk)) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - /* If verification was successful, move the message to the right place. */ - memmove(m, sm + PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_BYTES, *mlen); - - return 0; -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_avx2/thash.h b/src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_avx2/thash.h deleted file mode 100644 index 8b6ea800b7..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_avx2/thash.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_THASH_H -#define PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_THASH_H - -#include "hash_state.h" - -#include - -void PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_avx2/thash_shake256_robust.c b/src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_avx2/thash_shake256_robust.c deleted file mode 100644 index 351159df45..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_avx2/thash_shake256_robust.c +++ /dev/null @@ -1,81 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "thash.h" - -#include "fips202.h" - -/** - * Takes an array of inblocks concatenated arrays of PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N bytes. - */ -static void PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_thash( - unsigned char *out, unsigned char *buf, - const unsigned char *in, unsigned int inblocks, - const unsigned char *pub_seed, uint32_t addr[8]) { - - unsigned char *bitmask = buf + PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_ADDR_BYTES; - unsigned int i; - - memcpy(buf, pub_seed, PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N); - PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_addr_to_bytes(buf + PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N, addr); - - shake256(bitmask, inblocks * PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N, buf, PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_ADDR_BYTES); - - for (i = 0; i < inblocks * PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N; i++) { - buf[PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_ADDR_BYTES + i] = in[i] ^ bitmask[i]; - } - - shake256(out, PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N, buf, PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N); -} - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_ADDR_BYTES + 1 * PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N]; - PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_thash( - out, buf, in, 1, pub_seed, addr); - - (void)hash_state_seeded; /* Avoid unused parameter warning. */ -} - -void PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_ADDR_BYTES + 2 * PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N]; - PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_thash( - out, buf, in, 2, pub_seed, addr); - - (void)hash_state_seeded; /* Avoid unused parameter warning. */ -} - -void PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_ADDR_BYTES + PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_WOTS_LEN * PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N]; - PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_thash( - out, buf, in, PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_WOTS_LEN, pub_seed, addr); - - (void)hash_state_seeded; /* Avoid unused parameter warning. */ -} - -void PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_ADDR_BYTES + PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_FORS_TREES * PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N]; - PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_thash( - out, buf, in, PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_FORS_TREES, pub_seed, addr); - - (void)hash_state_seeded; /* Avoid unused parameter warning. */ -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_avx2/thash_shake256_robustx4.c b/src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_avx2/thash_shake256_robustx4.c deleted file mode 100644 index a21adf66ec..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_avx2/thash_shake256_robustx4.c +++ /dev/null @@ -1,66 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "thashx4.h" - -#include "fips202x4.h" - -/** - * 4-way parallel version of thash; takes 4x as much input and output - */ -#define thash_variant(name, inblocks) \ - void PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_thashx4_##name(unsigned char *out0, \ - unsigned char *out1, \ - unsigned char *out2, \ - unsigned char *out3, \ - const unsigned char *in0, \ - const unsigned char *in1, \ - const unsigned char *in2, \ - const unsigned char *in3, \ - const unsigned char *pub_seed, uint32_t addrx4[4*8], \ - const hash_state *state_seeded) \ - { \ - unsigned char buf0[PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_ADDR_BYTES + (inblocks)*PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N]; \ - unsigned char buf1[PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_ADDR_BYTES + (inblocks)*PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N]; \ - unsigned char buf2[PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_ADDR_BYTES + (inblocks)*PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N]; \ - unsigned char buf3[PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_ADDR_BYTES + (inblocks)*PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N]; \ - unsigned char bitmask0[(inblocks) * PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N]; \ - unsigned char bitmask1[(inblocks) * PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N]; \ - unsigned char bitmask2[(inblocks) * PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N]; \ - unsigned char bitmask3[(inblocks) * PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N]; \ - unsigned int i; \ - \ - memcpy(buf0, pub_seed, PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N); \ - memcpy(buf1, pub_seed, PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N); \ - memcpy(buf2, pub_seed, PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N); \ - memcpy(buf3, pub_seed, PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N); \ - PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_addr_to_bytes(buf0 + PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N, addrx4 + 0*8); \ - PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_addr_to_bytes(buf1 + PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N, addrx4 + 1*8); \ - PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_addr_to_bytes(buf2 + PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N, addrx4 + 2*8); \ - PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_addr_to_bytes(buf3 + PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N, addrx4 + 3*8); \ - \ - PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_shake256x4(bitmask0, bitmask1, bitmask2, bitmask3, (inblocks) * PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N, \ - buf0, buf1, buf2, buf3, PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_ADDR_BYTES); \ - \ - for (i = 0; i < (inblocks) * PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N; i++) { \ - buf0[PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_ADDR_BYTES + i] = in0[i] ^ bitmask0[i]; \ - buf1[PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_ADDR_BYTES + i] = in1[i] ^ bitmask1[i]; \ - buf2[PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_ADDR_BYTES + i] = in2[i] ^ bitmask2[i]; \ - buf3[PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_ADDR_BYTES + i] = in3[i] ^ bitmask3[i]; \ - } \ - \ - PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_shake256x4( \ - out0, out1, out2, out3, PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N, \ - buf0, buf1, buf2, buf3, PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_ADDR_BYTES + (inblocks)*PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N); \ - \ - /* avoid unused parameter warning */ \ - (void)state_seeded; \ - } - - -thash_variant(1, 1) -thash_variant(2, 2) -thash_variant(WOTS_LEN, PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_WOTS_LEN) -thash_variant(FORS_TREES, PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_FORS_TREES) diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_avx2/thashx4.h b/src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_avx2/thashx4.h deleted file mode 100644 index b48a62b598..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_avx2/thashx4.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_THASHX4_H -#define PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_THASHX4_H - -#include - -#include "hash_state.h" - -#define thashx4_header(inblocks) \ - void PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_thashx4_##inblocks(unsigned char *out0, \ - unsigned char *out1, \ - unsigned char *out2, \ - unsigned char *out3, \ - const unsigned char *in0, \ - const unsigned char *in1, \ - const unsigned char *in2, \ - const unsigned char *in3, \ - const unsigned char *pub_seed, uint32_t addrx4[4*8], \ - const hash_state *state_seeded) - -thashx4_header(1); -thashx4_header(2); -thashx4_header(WOTS_LEN); -thashx4_header(FORS_TREES); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_avx2/utils.c b/src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_avx2/utils.c deleted file mode 100644 index 9bbf5eec48..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_avx2/utils.c +++ /dev/null @@ -1,199 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "hash_state.h" -#include "params.h" -#include "thash.h" -#include "utils.h" - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in) { - - /* Iterate over out in decreasing order, for big-endianness. */ - for (size_t i = outlen; i > 0; i--) { - out[i - 1] = in & 0xff; - in = in >> 8; - } -} - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_bytes_to_ull( - const unsigned char *in, size_t inlen) { - unsigned long long retval = 0; - - for (size_t i = 0; i < inlen; i++) { - retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); - } - return retval; -} - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - uint32_t i; - unsigned char buffer[2 * PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N]; - - /* If leaf_idx is odd (last bit = 1), current path element is a right child - and auth_path has to go left. Otherwise it is the other way around. */ - if (leaf_idx & 1) { - memcpy(buffer + PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N, leaf, PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N); - } else { - memcpy(buffer, leaf, PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N); - memcpy(buffer + PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N, auth_path, PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N); - } - auth_path += PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N; - - for (i = 0; i < tree_height - 1; i++) { - leaf_idx >>= 1; - idx_offset >>= 1; - /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_set_tree_height(addr, i + 1); - PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_set_tree_index( - addr, leaf_idx + idx_offset); - - /* Pick the right or left neighbor, depending on parity of the node. */ - if (leaf_idx & 1) { - PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_thash_2( - buffer + PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N); - } else { - PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_thash_2( - buffer, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer + PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N, auth_path, PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N); - } - auth_path += PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N; - } - - /* The last iteration is exceptional; we do not copy an auth_path node. */ - leaf_idx >>= 1; - idx_offset >>= 1; - PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_set_tree_height(addr, tree_height); - PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_set_tree_index( - addr, leaf_idx + idx_offset); - PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_thash_2( - root, buffer, pub_seed, addr, hash_state_seeded); -} - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -static void PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_treehash( - unsigned char *root, unsigned char *auth_path, - unsigned char *stack, unsigned int *heights, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - - unsigned int offset = 0; - uint32_t idx; - uint32_t tree_idx; - - for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { - /* Add the next leaf node to the stack. */ - gen_leaf(stack + offset * PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N, - sk_seed, pub_seed, idx + idx_offset, tree_addr, - hash_state_seeded); - offset++; - heights[offset - 1] = 0; - - /* If this is a node we need for the auth path.. */ - if ((leaf_idx ^ 0x1) == idx) { - memcpy(auth_path, stack + (offset - 1)*PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N, PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N); - } - - /* While the top-most nodes are of equal height.. */ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { - /* Compute index of the new node, in the next layer. */ - tree_idx = (idx >> (heights[offset - 1] + 1)); - - /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_set_tree_height( - tree_addr, heights[offset - 1] + 1); - PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_set_tree_index( - tree_addr, tree_idx + (idx_offset >> (heights[offset - 1] + 1))); - /* Hash the top-most nodes from the stack together. */ - PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_thash_2( - stack + (offset - 2)*PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N, stack + (offset - 2)*PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N, - pub_seed, tree_addr, hash_state_seeded); - offset--; - /* Note that the top-most node is now one layer higher. */ - heights[offset - 1]++; - - /* If this is a node we need for the auth path.. */ - if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_path + heights[offset - 1]*PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N, - stack + (offset - 1)*PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N, PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N); - } - } - } - memcpy(root, stack, PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N); -} - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_FORS_HEIGHT + 1)*PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N]; - unsigned int heights[PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_FORS_HEIGHT + 1]; - - PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_FORS_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_TREE_HEIGHT + 1)*PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N]; - unsigned int heights[PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_TREE_HEIGHT + 1]; - - PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_TREE_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_avx2/utils.h b/src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_avx2/utils.h deleted file mode 100644 index b657e7204f..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_avx2/utils.h +++ /dev/null @@ -1,64 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_UTILS_H -#define PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_UTILS_H - -#include "hash_state.h" -#include "params.h" -#include -#include - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in); - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_bytes_to_ull( - const unsigned char *in, size_t inlen); - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -void PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_avx2/utilsx4.c b/src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_avx2/utilsx4.c deleted file mode 100644 index b84caebf32..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_avx2/utilsx4.c +++ /dev/null @@ -1,98 +0,0 @@ -#include "address.h" -#include "params.h" -#include "thashx4.h" -#include "utils.h" -#include "utilsx4.h" - -#include - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -#define treehashx4_variant(name, tree_height) \ - void PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_treehashx4_##name( \ - unsigned char *rootx4, unsigned char *auth_pathx4, const unsigned char *sk_seed, \ - const unsigned char *pub_seed, const uint32_t leaf_idx[4], uint32_t idx_offset[4], \ - void (*gen_leafx4)(unsigned char * /* leaf0 */, unsigned char * /* leaf1 */, \ - unsigned char * /* leaf2 */, unsigned char * /* leaf3 */, \ - const unsigned char * /* sk_seed */, \ - const unsigned char * /* pub_seed */, uint32_t /* addr_idx0 */, \ - uint32_t /* addr_idx1 */, uint32_t /* addr_idx2 */, \ - uint32_t /* addr_idx3 */, const uint32_t[8] /* tree_addr */, \ - const hash_state * /* state_seeded */), \ - uint32_t tree_addrx4[4 * 8], const hash_state *state_seeded) { \ - unsigned char stackx4[4 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N]; \ - unsigned int heights[(tree_height) + 1]; \ - unsigned int offset = 0; \ - uint32_t idx; \ - uint32_t tree_idx; \ - unsigned int j; \ - \ - for (idx = 0; idx < (uint32_t)(1 << (tree_height)); idx++) { \ - /* Add the next leaf node to the stack. */ \ - gen_leafx4(stackx4 + 0 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N + offset * PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N, \ - stackx4 + 1 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N + offset * PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N, \ - stackx4 + 2 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N + offset * PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N, \ - stackx4 + 3 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N + offset * PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N, sk_seed, \ - pub_seed, idx + idx_offset[0], idx + idx_offset[1], idx + idx_offset[2], \ - idx + idx_offset[3], tree_addrx4, state_seeded); \ - offset++; \ - heights[offset - 1] = 0; \ - \ - /* If this is a node we need for the auth path.. */ \ - for (j = 0; j < 4; j++) { \ - if ((leaf_idx[j] ^ 0x1) == idx) { \ - memcpy(auth_pathx4 + j * (tree_height)*PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N, \ - stackx4 + j * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N + (offset - 1) * PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N, \ - PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N); \ - } \ - } \ - \ - /* While the top-most nodes are of equal height.. */ \ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { \ - /* Compute index of the new node, in the next layer. */ \ - tree_idx = (idx >> (heights[offset - 1] + 1)); \ - \ - /* Set the address of the node we're creating. */ \ - for (j = 0; j < 4; j++) { \ - PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_set_tree_height(tree_addrx4 + j * 8, heights[offset - 1] + 1); \ - PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_set_tree_index(tree_addrx4 + j * 8, \ - tree_idx + (idx_offset[j] >> (heights[offset - 1] + 1))); \ - } \ - /* Hash the top-most nodes from the stack together. */ \ - PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_thashx4_2(stackx4 + 0 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N + (offset - 2) * PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N, \ - stackx4 + 1 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N + (offset - 2) * PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N, \ - stackx4 + 2 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N + (offset - 2) * PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N, \ - stackx4 + 3 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N + (offset - 2) * PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N, \ - stackx4 + 0 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N + (offset - 2) * PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N, \ - stackx4 + 1 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N + (offset - 2) * PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N, \ - stackx4 + 2 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N + (offset - 2) * PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N, \ - stackx4 + 3 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N + (offset - 2) * PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N, \ - pub_seed, tree_addrx4, state_seeded); \ - offset--; \ - /* Note that the top-most node is now one layer higher. */ \ - heights[offset - 1]++; \ - \ - /* If this is a node we need for the auth path.. */ \ - for (j = 0; j < 4; j++) { \ - if (((leaf_idx[j] >> heights[offset - 1]) ^ 0x1) == tree_idx) { \ - memcpy(auth_pathx4 + j * (tree_height)*PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N + \ - heights[offset - 1] * PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N, \ - stackx4 + j * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N + (offset - 1) * PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N, \ - PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N); \ - } \ - } \ - } \ - } \ - \ - for (j = 0; j < 4; j++) { \ - memcpy(rootx4 + j * PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N, stackx4 + j * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N, PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N); \ - } \ - } - -treehashx4_variant(FORS_HEIGHT, PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_FORS_HEIGHT) diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_avx2/utilsx4.h b/src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_avx2/utilsx4.h deleted file mode 100644 index 502376f771..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_avx2/utilsx4.h +++ /dev/null @@ -1,38 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_UTILSX4_H -#define PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_UTILSX4_H - -#include "hash_state.h" -#include "params.h" - -#include - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -void PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_treehashx4_FORS_HEIGHT(unsigned char *rootx4, - unsigned char *auth_pathx4, - const unsigned char *sk_seed, - const unsigned char *pub_seed, - const uint32_t leaf_idx[4], - uint32_t idx_offset[4], - void (*gen_leafx4)(unsigned char * /* leaf0 */, - unsigned char * /* leaf1 */, - unsigned char * /* leaf2 */, - unsigned char * /* leaf3 */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx0 */, - uint32_t /* addr_idx1 */, - uint32_t /* addr_idx2 */, - uint32_t /* addr_idx3 */, - const uint32_t[8] /* tree_addr */, - const hash_state * /* state_seeded */), - uint32_t tree_addrx4[4 * 8], - const hash_state *state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_avx2/wots.c b/src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_avx2/wots.c deleted file mode 100644 index 710899824c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_avx2/wots.c +++ /dev/null @@ -1,240 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "hash_state.h" -#include "hashx4.h" -#include "params.h" -#include "thash.h" -#include "thashx4.h" -#include "utils.h" -#include "wots.h" - -// TODO clarify address expectations, and make them more uniform. -// TODO i.e. do we expect types to be set already? -// TODO and do we expect modifications or copies? - -/** - * Computes the starting value for a chain, i.e. the secret key. - * Expects the address to be complete up to the chain address. - */ -static void wots_gen_sk(unsigned char *sk, const unsigned char *sk_seed, - uint32_t wots_addr[8], const hash_state *state_seeded) { - /* Make sure that the hash address is actually zeroed. */ - PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_set_hash_addr(wots_addr, 0); - - /* Generate sk element. */ - PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_prf_addr(sk, sk_seed, wots_addr, state_seeded); -} - -/** - * 4-way parallel version of wots_gen_sk; expects 4x as much space in sk - */ -static void wots_gen_skx4(unsigned char *skx4, const unsigned char *sk_seed, - uint32_t wots_addrx4[4 * 8], const hash_state *state_seeded) { - unsigned int j; - - /* Make sure that the hash address is actually zeroed. */ - for (j = 0; j < 4; j++) { - PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_set_hash_addr(wots_addrx4 + j * 8, 0); - } - - /* Generate sk element. */ - PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_prf_addrx4(skx4 + 0 * PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N, - skx4 + 1 * PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N, - skx4 + 2 * PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N, - skx4 + 3 * PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N, - sk_seed, wots_addrx4, - state_seeded); -} - -/** - * Computes the chaining function. - * out and in have to be n-byte arrays. - * - * Interprets in as start-th value of the chain. - * addr has to contain the address of the chain. - */ -static void gen_chain(unsigned char *out, const unsigned char *in, - unsigned int start, unsigned int steps, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *state_seeded) { - uint32_t i; - - /* Initialize out with the value at position 'start'. */ - memcpy(out, in, PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N); - - /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_WOTS_W; i++) { - PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_set_hash_addr(addr, i); - PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_thash_1(out, out, pub_seed, addr, state_seeded); - } -} - -/** - * 4-way parallel version of gen_chain; expects 4x as much space in out, and - * 4x as much space in inx4. Assumes start and step identical across chains. - */ -static void gen_chainx4(unsigned char *outx4, const unsigned char *inx4, - unsigned int start, unsigned int steps, - const unsigned char *pub_seed, uint32_t addrx4[4 * 8], - const hash_state *state_seeded) { - uint32_t i; - unsigned int j; - - /* Initialize outx4 with the value at position 'start'. */ - memcpy(outx4, inx4, 4 * PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N); - - /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_WOTS_W; i++) { - for (j = 0; j < 4; j++) { - PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_set_hash_addr(addrx4 + j * 8, i); - } - PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_thashx4_1(outx4 + 0 * PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N, - outx4 + 1 * PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N, - outx4 + 2 * PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N, - outx4 + 3 * PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N, - outx4 + 0 * PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N, - outx4 + 1 * PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N, - outx4 + 2 * PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N, - outx4 + 3 * PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N, - pub_seed, addrx4, - state_seeded); - } -} - -/** - * base_w algorithm as described in draft. - * Interprets an array of bytes as integers in base w. - * This only works when log_w is a divisor of 8. - */ -static void base_w(unsigned int *output, const int out_len, const unsigned char *input) { - int in = 0; - int out = 0; - unsigned char total = 0; - int bits = 0; - int consumed; - - for (consumed = 0; consumed < out_len; consumed++) { - if (bits == 0) { - total = input[in]; - in++; - bits += 8; - } - bits -= PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_WOTS_LOGW; - output[out] = (unsigned int)(total >> bits) & (PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_WOTS_W - 1); - out++; - } -} - -/* Computes the WOTS+ checksum over a message (in base_w). */ -static void wots_checksum(unsigned int *csum_base_w, const unsigned int *msg_base_w) { - unsigned int csum = 0; - unsigned char csum_bytes[(PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_WOTS_LEN2 * PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_WOTS_LOGW + 7) / 8]; - unsigned int i; - - /* Compute checksum. */ - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_WOTS_LEN1; i++) { - csum += PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_WOTS_W - 1 - msg_base_w[i]; - } - - /* Convert checksum to base_w. */ - /* Make sure expected empty zero bits are the least significant bits. */ - csum = csum << (8 - ((PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_WOTS_LEN2 * PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_WOTS_LOGW) % 8)); - PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); - base_w(csum_base_w, PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_WOTS_LEN2, csum_bytes); -} - -/* Takes a message and derives the matching chain lengths. */ -static void chain_lengths(unsigned int *lengths, const unsigned char *msg) { - base_w(lengths, PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_WOTS_LEN1, msg); - wots_checksum(lengths + PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_WOTS_LEN1, lengths); -} - -/** - * WOTS key generation. Takes a 32 byte sk_seed, expands it to WOTS private key - * elements and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_wots_gen_pk(unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *state_seeded) { - uint32_t i; - unsigned int j; - - uint32_t addrx4[4 * 8]; - unsigned char pkbuf[4 * PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N]; - - for (j = 0; j < 4; j++) { - memcpy(addrx4 + j * 8, addr, sizeof(uint32_t) * 8); - } - - /* The last iteration typically does not have complete set of 4 chains, - but because we use pkbuf, this is not an issue -- we still do as many - in parallel as possible. */ - for (i = 0; i < ((PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_WOTS_LEN + 3) & ~0x3); i += 4) { - for (j = 0; j < 4; j++) { - PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_set_chain_addr(addrx4 + j * 8, i + j); - } - wots_gen_skx4(pkbuf, sk_seed, addrx4, state_seeded); - gen_chainx4(pkbuf, pkbuf, 0, PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_WOTS_W - 1, pub_seed, addrx4, state_seeded); - for (j = 0; j < 4; j++) { - if (i + j < PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_WOTS_LEN) { - memcpy(pk + (i + j)*PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N, pkbuf + j * PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N, PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N); - } - } - } - - // Get rid of unused argument variable. - (void)state_seeded; -} - -/** - * Takes a n-byte message and the 32-byte sk_see to compute a signature 'sig'. - */ -void PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_wots_sign(unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_WOTS_LEN; i++) { - PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_set_chain_addr(addr, i); - wots_gen_sk(sig + i * PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N, sk_seed, addr, state_seeded); - gen_chain(sig + i * PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N, sig + i * PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N, 0, lengths[i], pub_seed, addr, state_seeded); - } - - // avoid unused argument - (void)state_seeded; -} - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_WOTS_LEN; i++) { - PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_set_chain_addr(addr, i); - gen_chain(pk + i * PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N, sig + i * PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_N, - lengths[i], PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_WOTS_W - 1 - lengths[i], pub_seed, addr, - state_seeded); - } - - // avoid unused argument - (void)state_seeded; -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_avx2/wots.h b/src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_avx2/wots.h deleted file mode 100644 index 87b503cd36..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_avx2/wots.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_WOTS_H -#define PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_WOTS_H - -#include "hash_state.h" -#include "params.h" -#include - -/** - * WOTS key generation. Takes a 32 byte seed for the private key, expands it to - * a full WOTS private key and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_wots_gen_pk( - unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -/** - * Takes a n-byte message and the 32-byte seed for the private key to compute a - * signature that is placed at 'sig'. - */ -void PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_wots_sign( - unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *hash_state_seeded); - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_wots_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_clean/LICENSE b/src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_clean/LICENSE deleted file mode 100644 index 670154e353..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_clean/LICENSE +++ /dev/null @@ -1,116 +0,0 @@ -CC0 1.0 Universal - -Statement of Purpose - -The laws of most jurisdictions throughout the world automatically confer -exclusive Copyright and Related Rights (defined below) upon the creator and -subsequent owner(s) (each and all, an "owner") of an original work of -authorship and/or a database (each, a "Work"). - -Certain owners wish to permanently relinquish those rights to a Work for the -purpose of contributing to a commons of creative, cultural and scientific -works ("Commons") that the public can reliably and without fear of later -claims of infringement build upon, modify, incorporate in other works, reuse -and redistribute as freely as possible in any form whatsoever and for any -purposes, including without limitation commercial purposes. These owners may -contribute to the Commons to promote the ideal of a free culture and the -further production of creative, cultural and scientific works, or to gain -reputation or greater distribution for their Work in part through the use and -efforts of others. - -For these and/or other purposes and motivations, and without any expectation -of additional consideration or compensation, the person associating CC0 with a -Work (the "Affirmer"), to the extent that he or she is an owner of Copyright -and Related Rights in the Work, voluntarily elects to apply CC0 to the Work -and publicly distribute the Work under its terms, with knowledge of his or her -Copyright and Related Rights in the Work and the meaning and intended legal -effect of CC0 on those rights. - -1. Copyright and Related Rights. A Work made available under CC0 may be -protected by copyright and related or neighboring rights ("Copyright and -Related Rights"). Copyright and Related Rights include, but are not limited -to, the following: - - i. the right to reproduce, adapt, distribute, perform, display, communicate, - and translate a Work; - - ii. moral rights retained by the original author(s) and/or performer(s); - - iii. publicity and privacy rights pertaining to a person's image or likeness - depicted in a Work; - - iv. rights protecting against unfair competition in regards to a Work, - subject to the limitations in paragraph 4(a), below; - - v. rights protecting the extraction, dissemination, use and reuse of data in - a Work; - - vi. database rights (such as those arising under Directive 96/9/EC of the - European Parliament and of the Council of 11 March 1996 on the legal - protection of databases, and under any national implementation thereof, - including any amended or successor version of such directive); and - - vii. other similar, equivalent or corresponding rights throughout the world - based on applicable law or treaty, and any national implementations thereof. - -2. Waiver. To the greatest extent permitted by, but not in contravention of, -applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and -unconditionally waives, abandons, and surrenders all of Affirmer's Copyright -and Related Rights and associated claims and causes of action, whether now -known or unknown (including existing as well as future claims and causes of -action), in the Work (i) in all territories worldwide, (ii) for the maximum -duration provided by applicable law or treaty (including future time -extensions), (iii) in any current or future medium and for any number of -copies, and (iv) for any purpose whatsoever, including without limitation -commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes -the Waiver for the benefit of each member of the public at large and to the -detriment of Affirmer's heirs and successors, fully intending that such Waiver -shall not be subject to revocation, rescission, cancellation, termination, or -any other legal or equitable action to disrupt the quiet enjoyment of the Work -by the public as contemplated by Affirmer's express Statement of Purpose. - -3. Public License Fallback. Should any part of the Waiver for any reason be -judged legally invalid or ineffective under applicable law, then the Waiver -shall be preserved to the maximum extent permitted taking into account -Affirmer's express Statement of Purpose. In addition, to the extent the Waiver -is so judged Affirmer hereby grants to each affected person a royalty-free, -non transferable, non sublicensable, non exclusive, irrevocable and -unconditional license to exercise Affirmer's Copyright and Related Rights in -the Work (i) in all territories worldwide, (ii) for the maximum duration -provided by applicable law or treaty (including future time extensions), (iii) -in any current or future medium and for any number of copies, and (iv) for any -purpose whatsoever, including without limitation commercial, advertising or -promotional purposes (the "License"). The License shall be deemed effective as -of the date CC0 was applied by Affirmer to the Work. Should any part of the -License for any reason be judged legally invalid or ineffective under -applicable law, such partial invalidity or ineffectiveness shall not -invalidate the remainder of the License, and in such case Affirmer hereby -affirms that he or she will not (i) exercise any of his or her remaining -Copyright and Related Rights in the Work or (ii) assert any associated claims -and causes of action with respect to the Work, in either case contrary to -Affirmer's express Statement of Purpose. - -4. Limitations and Disclaimers. - - a. No trademark or patent rights held by Affirmer are waived, abandoned, - surrendered, licensed or otherwise affected by this document. - - b. Affirmer offers the Work as-is and makes no representations or warranties - of any kind concerning the Work, express, implied, statutory or otherwise, - including without limitation warranties of title, merchantability, fitness - for a particular purpose, non infringement, or the absence of latent or - other defects, accuracy, or the present or absence of errors, whether or not - discoverable, all to the greatest extent permissible under applicable law. - - c. Affirmer disclaims responsibility for clearing rights of other persons - that may apply to the Work or any use thereof, including without limitation - any person's Copyright and Related Rights in the Work. Further, Affirmer - disclaims responsibility for obtaining any necessary consents, permissions - or other rights required for any use of the Work. - - d. Affirmer understands and acknowledges that Creative Commons is not a - party to this document and has no duty or obligation with respect to this - CC0 or use of the Work. - -For more information, please see - diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_clean/address.c b/src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_clean/address.c deleted file mode 100644 index dd5d233e96..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_clean/address.c +++ /dev/null @@ -1,78 +0,0 @@ -#include - -#include "address.h" -#include "params.h" -#include "utils.h" - -void PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]) { - int i; - - for (i = 0; i < 8; i++) { - PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_ull_to_bytes( - bytes + i * 4, 4, addr[i]); - } -} - -void PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_set_layer_addr( - uint32_t addr[8], uint32_t layer) { - addr[0] = layer; -} - -void PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_set_tree_addr( - uint32_t addr[8], uint64_t tree) { - addr[1] = 0; - addr[2] = (uint32_t) (tree >> 32); - addr[3] = (uint32_t) tree; -} - -void PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_set_type( - uint32_t addr[8], uint32_t type) { - addr[4] = type; -} - -void PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; -} - -/* These functions are used for OTS addresses. */ - -void PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_set_keypair_addr( - uint32_t addr[8], uint32_t keypair) { - addr[5] = keypair; -} - -void PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; - out[5] = in[5]; -} - -void PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_set_chain_addr( - uint32_t addr[8], uint32_t chain) { - addr[6] = chain; -} - -void PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_set_hash_addr( - uint32_t addr[8], uint32_t hash) { - addr[7] = hash; -} - -/* These functions are used for all hash tree addresses (including FORS). */ - -void PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_set_tree_height( - uint32_t addr[8], uint32_t tree_height) { - addr[6] = tree_height; -} - -void PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_set_tree_index( - uint32_t addr[8], uint32_t tree_index) { - addr[7] = tree_index; -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_clean/address.h b/src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_clean/address.h deleted file mode 100644 index e3e9cc0aa5..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_clean/address.h +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_ADDRESS_H -#define PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_ADDRESS_H - -#include - -#define PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_ADDR_TYPE_WOTS 0 -#define PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_ADDR_TYPE_WOTSPK 1 -#define PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_ADDR_TYPE_HASHTREE 2 -#define PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_ADDR_TYPE_FORSTREE 3 -#define PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_ADDR_TYPE_FORSPK 4 - -void PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]); - -void PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_set_layer_addr( - uint32_t addr[8], uint32_t layer); - -void PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_set_tree_addr( - uint32_t addr[8], uint64_t tree); - -void PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_set_type( - uint32_t addr[8], uint32_t type); - -/* Copies the layer and tree part of one address into the other */ -void PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for WOTS and FORS addresses. */ - -void PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_set_keypair_addr( - uint32_t addr[8], uint32_t keypair); - -void PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_set_chain_addr( - uint32_t addr[8], uint32_t chain); - -void PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_set_hash_addr( - uint32_t addr[8], uint32_t hash); - -void PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for all hash tree addresses (including FORS). */ - -void PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_set_tree_height( - uint32_t addr[8], uint32_t tree_height); - -void PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_set_tree_index( - uint32_t addr[8], uint32_t tree_index); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_clean/api.h b/src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_clean/api.h deleted file mode 100644 index cacddd5f48..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_clean/api.h +++ /dev/null @@ -1,81 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_API_H -#define PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_API_H - -#include -#include - - - -#define PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_CRYPTO_ALGNAME "SPHINCS+" - -#define PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_CRYPTO_SECRETKEYBYTES 64 -#define PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_CRYPTO_PUBLICKEYBYTES 32 -#define PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_CRYPTO_BYTES 17088 -#define PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_CRYPTO_SEEDBYTES 48 - - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_clean/fors.c b/src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_clean/fors.c deleted file mode 100644 index f8a3fb17f2..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_clean/fors.c +++ /dev/null @@ -1,161 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "fors.h" -#include "hash.h" -#include "hash_state.h" -#include "thash.h" -#include "utils.h" - -static void fors_gen_sk(unsigned char *sk, const unsigned char *sk_seed, - uint32_t fors_leaf_addr[8], const hash_state *hash_state_seeded) { - PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_prf_addr( - sk, sk_seed, fors_leaf_addr, hash_state_seeded); -} - -static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, - const unsigned char *pub_seed, - uint32_t fors_leaf_addr[8], - const hash_state *hash_state_seeded) { - PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_thash_1( - leaf, sk, pub_seed, fors_leaf_addr, hash_state_seeded); -} - -static void fors_gen_leaf(unsigned char *leaf, const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx, const uint32_t fors_tree_addr[8], - const hash_state *hash_state_seeded) { - uint32_t fors_leaf_addr[8] = {0}; - - /* Only copy the parts that must be kept in fors_leaf_addr. */ - PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_copy_keypair_addr( - fors_leaf_addr, fors_tree_addr); - PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_set_type( - fors_leaf_addr, PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_set_tree_index( - fors_leaf_addr, addr_idx); - - fors_gen_sk(leaf, sk_seed, fors_leaf_addr, hash_state_seeded); - fors_sk_to_leaf(leaf, leaf, pub_seed, fors_leaf_addr, hash_state_seeded); -} - -/** - * Interprets m as PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_FORS_HEIGHT-bit unsigned integers. - * Assumes m contains at least PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_FORS_TREES bits. - * Assumes indices has space for PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_FORS_TREES integers. - */ -static void message_to_indices(uint32_t *indices, const unsigned char *m) { - unsigned int i, j; - unsigned int offset = 0; - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_FORS_TREES; i++) { - indices[i] = 0; - for (j = 0; j < PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_FORS_HEIGHT; j++) { - indices[i] ^= (((uint32_t)m[offset >> 3] >> (offset & 0x7)) & 0x1) << j; - offset++; - } - } -} - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_fors_sign( - unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *hash_state_seeded) { - uint32_t indices[PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_FORS_TREES]; - unsigned char roots[PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_FORS_TREES * PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_N]; - uint32_t fors_tree_addr[8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_copy_keypair_addr( - fors_tree_addr, fors_addr); - PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_copy_keypair_addr( - fors_pk_addr, fors_addr); - - PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_set_type( - fors_tree_addr, PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_set_type( - fors_pk_addr, PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_FORS_TREES; i++) { - idx_offset = i * (1 << PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_FORS_HEIGHT); - - PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_set_tree_height( - fors_tree_addr, 0); - PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_set_tree_index( - fors_tree_addr, indices[i] + idx_offset); - - /* Include the secret key part that produces the selected leaf node. */ - fors_gen_sk(sig, sk_seed, fors_tree_addr, hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_N; - - /* Compute the authentication path for this leaf node. */ - PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_treehash_FORS_HEIGHT( - roots + i * PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_N, sig, sk_seed, pub_seed, - indices[i], idx_offset, fors_gen_leaf, fors_tree_addr, - hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_N * PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_thash_FORS_TREES( - pk, roots, pub_seed, fors_pk_addr, hash_state_seeded); -} - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_fors_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, const uint32_t fors_addr[8], - const hash_state *hash_state_seeded) { - uint32_t indices[PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_FORS_TREES]; - unsigned char roots[PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_FORS_TREES * PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_N]; - unsigned char leaf[PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_N]; - uint32_t fors_tree_addr[8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_copy_keypair_addr(fors_tree_addr, fors_addr); - PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_copy_keypair_addr(fors_pk_addr, fors_addr); - - PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_set_type(fors_tree_addr, PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_set_type(fors_pk_addr, PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_FORS_TREES; i++) { - idx_offset = i * (1 << PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_FORS_HEIGHT); - - PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_set_tree_height(fors_tree_addr, 0); - PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Derive the leaf from the included secret key part. */ - fors_sk_to_leaf(leaf, sig, pub_seed, fors_tree_addr, hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_N; - - /* Derive the corresponding root node of this tree. */ - PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_compute_root(roots + i * PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_N, leaf, indices[i], idx_offset, sig, - PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_FORS_HEIGHT, pub_seed, fors_tree_addr, hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_N * PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_thash_FORS_TREES(pk, roots, pub_seed, fors_pk_addr, hash_state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_clean/fors.h b/src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_clean/fors.h deleted file mode 100644 index 8290a4e217..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_clean/fors.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_FORS_H -#define PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_FORS_H - -#include - -#include "hash_state.h" -#include "params.h" - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_fors_sign( - unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *hash_state_seeded); - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_fors_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, const uint32_t fors_addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_clean/hash.h b/src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_clean/hash.h deleted file mode 100644 index 3856a46974..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_clean/hash.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_HASH_H -#define PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_HASH_H - -#include "hash_state.h" - -#include -#include - -void PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_initialize_hash_function( - hash_state *hash_state_seeded, - const unsigned char *pub_seed, const unsigned char *sk_seed); - -void PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_destroy_hash_function(hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_clean/hash_shake256.c b/src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_clean/hash_shake256.c deleted file mode 100644 index f350f0b9b7..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_clean/hash_shake256.c +++ /dev/null @@ -1,106 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "utils.h" - -#include "fips202.h" - -/* For SHAKE256, there is no immediate reason to initialize at the start, - so this function is an empty operation. */ -void PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_initialize_hash_function( - hash_state *hash_state_seeded, // NOLINT(readability-non-const-parameter) - const unsigned char *pub_seed, const unsigned char *sk_seed) { - (void)hash_state_seeded; /* Suppress an 'unused parameter' warning. */ - (void)pub_seed; /* Suppress an 'unused parameter' warning. */ - (void)sk_seed; /* Suppress an 'unused parameter' warning. */ -} - -/* This is not necessary for SHAKE256, so we don't do anything */ -void PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_destroy_hash_function( - hash_state *hash_state_seeded) { // NOLINT(readability-non-const-parameter) - (void)hash_state_seeded; -} - -/* - * Computes PRF(key, addr), given a secret key of PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_N bytes and an address - */ -void PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded) { - unsigned char buf[PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_N + PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_ADDR_BYTES]; - - memcpy(buf, key, PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_N); - PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_addr_to_bytes(buf + PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_N, addr); - - shake256(out, PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_N, buf, PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_N + PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_ADDR_BYTES); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} - -/** - * Computes the message-dependent randomness R, using a secret seed and an - * optional randomization value as well as the message. - */ -void PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded) { - shake256incctx state; - - shake256_inc_init(&state); - shake256_inc_absorb(&state, sk_prf, PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_N); - shake256_inc_absorb(&state, optrand, PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_N); - shake256_inc_absorb(&state, m, mlen); - shake256_inc_finalize(&state); - shake256_inc_squeeze(R, PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_N, &state); - shake256_inc_ctx_release(&state); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} - -/** - * Computes the message hash using R, the public key, and the message. - * Outputs the message digest and the index of the leaf. The index is split in - * the tree index and the leaf index, for convenient copying to an address. - */ -void PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded) { -#define PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_TREE_BITS (PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_TREE_HEIGHT * (PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_D - 1)) -#define PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_TREE_BYTES ((PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_TREE_BITS + 7) / 8) -#define PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_LEAF_BITS PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_TREE_HEIGHT -#define PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_LEAF_BYTES ((PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_LEAF_BITS + 7) / 8) -#define PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_DGST_BYTES (PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_FORS_MSG_BYTES + PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_TREE_BYTES + PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_LEAF_BYTES) - - unsigned char buf[PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_DGST_BYTES]; - unsigned char *bufp = buf; - shake256incctx state; - - shake256_inc_init(&state); - shake256_inc_absorb(&state, R, PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_N); - shake256_inc_absorb(&state, pk, PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_PK_BYTES); - shake256_inc_absorb(&state, m, mlen); - shake256_inc_finalize(&state); - shake256_inc_squeeze(buf, PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_DGST_BYTES, &state); - shake256_inc_ctx_release(&state); - - memcpy(digest, bufp, PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_FORS_MSG_BYTES); - bufp += PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_FORS_MSG_BYTES; - - *tree = PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_bytes_to_ull( - bufp, PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_TREE_BYTES); - *tree &= (~(uint64_t)0) >> (64 - PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_TREE_BITS); - bufp += PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_TREE_BYTES; - - *leaf_idx = (uint32_t)PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_bytes_to_ull( - bufp, PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_LEAF_BYTES); - *leaf_idx &= (~(uint32_t)0) >> (32 - PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_LEAF_BITS); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_clean/hash_state.h b/src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_clean/hash_state.h deleted file mode 100644 index 7d92ef872a..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_clean/hash_state.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef SPX_HASH_STATE_H -#define SPX_HASH_STATE_H - -/** - * Defines the type of the hash function state. - * - * Don't be fooled into thinking this instance of SPHINCS+ isn't stateless! - * - * From Section 7.2.2 from the SPHINCS+ round-2 specification: - * - * Each of the instances of the tweakable hash function take PK.seed as its - * first input, which is constant for a given key pair – and, thus, across - * a single signature. This leads to a lot of redundant computation. To remedy - * this, we pad PK.seed to the length of a full 64-byte SHA-256 input block. - * Because of the Merkle-DamgÃ¥rd construction that underlies SHA-256, this - * allows for reuse of the intermediate SHA-256 state after the initial call to - * the compression function which improves performance. - * - * We pass this hash state around in functions, because otherwise we need to - * have a global variable. - * - * SHAKE256 does not need this state. Because this implementation is generated - * from a shared code base, we still need to specify some hash_state as it is - * still passed around. We chose to use an `int` as a placeholder for this - * purpose. - */ - -#define hash_state int - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_clean/params.h b/src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_clean/params.h deleted file mode 100644 index fd502f7cdf..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_clean/params.h +++ /dev/null @@ -1,53 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_PARAMS_H -#define PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_PARAMS_H - -/* Hash output length in bytes. */ -#define PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_N 16 -/* Height of the hypertree. */ -#define PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_FULL_HEIGHT 66 -/* Number of subtree layer. */ -#define PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_D 22 -/* FORS tree dimensions. */ -#define PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_FORS_HEIGHT 6 -#define PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_FORS_TREES 33 -/* Winternitz parameter, */ -#define PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_WOTS_W 16 - -/* The hash function is defined by linking a different hash.c file, as opposed - to setting a #define constant. */ - -/* For clarity */ -#define PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_ADDR_BYTES 32 - -/* WOTS parameters. */ -#define PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_WOTS_LOGW 4 - -#define PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_WOTS_LEN1 (8 * PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_N / PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_WOTS_LOGW) - -/* PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#define PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_WOTS_LEN2 3 - -#define PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_WOTS_LEN (PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_WOTS_LEN1 + PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_WOTS_LEN2) -#define PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_WOTS_BYTES (PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_WOTS_LEN * PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_N) -#define PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_WOTS_PK_BYTES PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_WOTS_BYTES - -/* Subtree size. */ -#define PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_TREE_HEIGHT (PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_FULL_HEIGHT / PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_D) - -/* FORS parameters. */ -#define PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_FORS_MSG_BYTES ((PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_FORS_TREES + 7) / 8) -#define PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_FORS_BYTES ((PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_FORS_HEIGHT + 1) * PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_FORS_TREES * PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_N) -#define PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_FORS_PK_BYTES PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_N - -/* Resulting SPX sizes. */ -#define PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_BYTES (PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_N + PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_FORS_BYTES + PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_D * PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_WOTS_BYTES +\ - PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_FULL_HEIGHT * PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_N) -#define PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_PK_BYTES (2 * PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_N) -#define PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_SK_BYTES (2 * PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_N + PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_PK_BYTES) - -/* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ -#define PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_OPTRAND_BYTES 32 - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_clean/sign.c b/src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_clean/sign.c deleted file mode 100644 index 34bc5dc356..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_clean/sign.c +++ /dev/null @@ -1,356 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "api.h" -#include "fors.h" -#include "hash.h" -#include "hash_state.h" -#include "params.h" -#include "randombytes.h" -#include "thash.h" -#include "utils.h" -#include "wots.h" - -/** - * Computes the leaf at a given address. First generates the WOTS key pair, - * then computes leaf by hashing horizontally. - */ -static void wots_gen_leaf(unsigned char *leaf, const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx, const uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - unsigned char pk[PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_WOTS_BYTES]; - uint32_t wots_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_set_type( - wots_addr, PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_set_type( - wots_pk_addr, PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_ADDR_TYPE_WOTSPK); - - PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_set_keypair_addr( - wots_addr, addr_idx); - PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_wots_gen_pk( - pk, sk_seed, pub_seed, wots_addr, hash_state_seeded); - - PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_copy_keypair_addr( - wots_pk_addr, wots_addr); - PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_thash_WOTS_LEN( - leaf, pk, pub_seed, wots_pk_addr, hash_state_seeded); -} - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_crypto_sign_secretkeybytes(void) { - return PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_CRYPTO_SECRETKEYBYTES; -} - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_crypto_sign_publickeybytes(void) { - return PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_CRYPTO_PUBLICKEYBYTES; -} - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_crypto_sign_bytes(void) { - return PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_CRYPTO_BYTES; -} - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_crypto_sign_seedbytes(void) { - return PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_CRYPTO_SEEDBYTES; -} - -/* - * Generates an SPX key pair given a seed of length - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed) { - /* We do not need the auth path in key generation, but it simplifies the - code to have just one treehash routine that computes both root and path - in one function. */ - unsigned char auth_path[PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_TREE_HEIGHT * PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_N]; - uint32_t top_tree_addr[8] = {0}; - hash_state hash_state_seeded; - - PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_set_layer_addr( - top_tree_addr, PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_D - 1); - PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_set_type( - top_tree_addr, PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_ADDR_TYPE_HASHTREE); - - /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ - memcpy(sk, seed, PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_CRYPTO_SEEDBYTES); - - memcpy(pk, sk + 2 * PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_N, PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_initialize_hash_function(&hash_state_seeded, pk, sk); - - /* Compute root node of the top-most subtree. */ - PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_treehash_TREE_HEIGHT( - sk + 3 * PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_N, auth_path, sk, sk + 2 * PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_N, 0, 0, - wots_gen_leaf, top_tree_addr, &hash_state_seeded); - - memcpy(pk + PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_N, sk + 3 * PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_N, PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_N); - - PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_destroy_hash_function(&hash_state_seeded); - return 0; -} - -/* - * Generates an SPX key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk) { - unsigned char seed[PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_CRYPTO_SEEDBYTES]; - randombytes(seed, PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_CRYPTO_SEEDBYTES); - PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_crypto_sign_seed_keypair( - pk, sk, seed); - - return 0; -} - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - const unsigned char *sk_seed = sk; - const unsigned char *sk_prf = sk + PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_N; - const unsigned char *pk = sk + 2 * PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_N; - const unsigned char *pub_seed = pk; - - unsigned char optrand[PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_N]; - unsigned char mhash[PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_FORS_MSG_BYTES]; - unsigned char root[PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_N]; - uint32_t i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - - hash_state hash_state_seeded; - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_initialize_hash_function( - &hash_state_seeded, - pub_seed, sk_seed); - - PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_set_type( - wots_addr, PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_set_type( - tree_addr, PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_ADDR_TYPE_HASHTREE); - - /* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ - randombytes(optrand, PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_N); - /* Compute the digest randomization value. */ - PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_gen_message_random( - sig, sk_prf, optrand, m, mlen, &hash_state_seeded); - - /* Derive the message digest and leaf index from R, PK and M. */ - PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_N; - - PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); - - /* Sign the message hash using FORS. */ - PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_fors_sign( - sig, root, mhash, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_FORS_BYTES; - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_D; i++) { - PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_set_tree_addr(tree_addr, tree); - - PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); - - /* Compute a WOTS signature. */ - PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_wots_sign( - sig, root, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_WOTS_BYTES; - - /* Compute the authentication path for the used WOTS leaf. */ - PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_treehash_TREE_HEIGHT( - root, sig, sk_seed, pub_seed, idx_leaf, 0, - wots_gen_leaf, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_TREE_HEIGHT * PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_TREE_HEIGHT; - } - - *siglen = PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_BYTES; - - PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_destroy_hash_function(&hash_state_seeded); - return 0; -} - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk) { - const unsigned char *pub_seed = pk; - const unsigned char *pub_root = pk + PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_N; - unsigned char mhash[PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_FORS_MSG_BYTES]; - unsigned char wots_pk[PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_WOTS_BYTES]; - unsigned char root[PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_N]; - unsigned char leaf[PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_N]; - unsigned int i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - hash_state hash_state_seeded; - - if (siglen != PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_BYTES) { - return -1; - } - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_initialize_hash_function( - &hash_state_seeded, - pub_seed, NULL); - - PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_set_type( - wots_addr, PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_set_type( - tree_addr, PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_ADDR_TYPE_HASHTREE); - PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_set_type( - wots_pk_addr, PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_ADDR_TYPE_WOTSPK); - - /* Derive the message digest and leaf index from R || PK || M. */ - /* The additional PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_N is a result of the hash domain separator. */ - PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_N; - - /* Layer correctly defaults to 0, so no need to set_layer_addr */ - PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); - - PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_fors_pk_from_sig( - root, sig, mhash, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_FORS_BYTES; - - /* For each subtree.. */ - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_D; i++) { - PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_set_tree_addr(tree_addr, tree); - - PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); - - PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_copy_keypair_addr( - wots_pk_addr, wots_addr); - - /* The WOTS public key is only correct if the signature was correct. */ - /* Initially, root is the FORS pk, but on subsequent iterations it is - the root of the subtree below the currently processed subtree. */ - PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_wots_pk_from_sig( - wots_pk, sig, root, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_WOTS_BYTES; - - /* Compute the leaf node using the WOTS public key. */ - PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_thash_WOTS_LEN( - leaf, wots_pk, pub_seed, wots_pk_addr, &hash_state_seeded); - - /* Compute the root node of this subtree. */ - PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_compute_root( - root, leaf, idx_leaf, 0, sig, PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_TREE_HEIGHT, - pub_seed, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_TREE_HEIGHT * PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_TREE_HEIGHT; - } - - PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_destroy_hash_function(&hash_state_seeded); - /* Check if the root node equals the root node in the public key. */ - if (memcmp(root, pub_root, PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_N) != 0) { - return -1; - } - - return 0; -} - - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - size_t siglen; - - PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_crypto_sign_signature( - sm, &siglen, m, mlen, sk); - - memmove(sm + PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_BYTES, m, mlen); - *smlen = siglen + mlen; - - return 0; -} - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk) { - /* The API caller does not necessarily know what size a signature should be - but SPHINCS+ signatures are always exactly PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_BYTES. */ - if (smlen < PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_BYTES) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - *mlen = smlen - PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_BYTES; - - if (PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_crypto_sign_verify( - sm, PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_BYTES, sm + PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_BYTES, *mlen, pk)) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - /* If verification was successful, move the message to the right place. */ - memmove(m, sm + PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_BYTES, *mlen); - - return 0; -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_clean/thash.h b/src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_clean/thash.h deleted file mode 100644 index ef518b1115..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_clean/thash.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_THASH_H -#define PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_THASH_H - -#include "hash_state.h" - -#include - -void PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_clean/thash_shake256_robust.c b/src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_clean/thash_shake256_robust.c deleted file mode 100644 index 27531f5004..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_clean/thash_shake256_robust.c +++ /dev/null @@ -1,81 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "thash.h" - -#include "fips202.h" - -/** - * Takes an array of inblocks concatenated arrays of PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_N bytes. - */ -static void PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_thash( - unsigned char *out, unsigned char *buf, - const unsigned char *in, unsigned int inblocks, - const unsigned char *pub_seed, uint32_t addr[8]) { - - unsigned char *bitmask = buf + PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_N + PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_ADDR_BYTES; - unsigned int i; - - memcpy(buf, pub_seed, PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_N); - PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_addr_to_bytes(buf + PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_N, addr); - - shake256(bitmask, inblocks * PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_N, buf, PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_N + PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_ADDR_BYTES); - - for (i = 0; i < inblocks * PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_N; i++) { - buf[PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_N + PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_ADDR_BYTES + i] = in[i] ^ bitmask[i]; - } - - shake256(out, PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_N, buf, PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_N + PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_N); -} - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_N + PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_ADDR_BYTES + 1 * PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_N]; - PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_thash( - out, buf, in, 1, pub_seed, addr); - - (void)hash_state_seeded; /* Avoid unused parameter warning. */ -} - -void PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_N + PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_ADDR_BYTES + 2 * PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_N]; - PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_thash( - out, buf, in, 2, pub_seed, addr); - - (void)hash_state_seeded; /* Avoid unused parameter warning. */ -} - -void PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_N + PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_ADDR_BYTES + PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_WOTS_LEN * PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_N]; - PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_thash( - out, buf, in, PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_WOTS_LEN, pub_seed, addr); - - (void)hash_state_seeded; /* Avoid unused parameter warning. */ -} - -void PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_N + PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_ADDR_BYTES + PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_FORS_TREES * PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_N]; - PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_thash( - out, buf, in, PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_FORS_TREES, pub_seed, addr); - - (void)hash_state_seeded; /* Avoid unused parameter warning. */ -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_clean/utils.c b/src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_clean/utils.c deleted file mode 100644 index aefe705462..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_clean/utils.c +++ /dev/null @@ -1,199 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "hash_state.h" -#include "params.h" -#include "thash.h" -#include "utils.h" - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in) { - - /* Iterate over out in decreasing order, for big-endianness. */ - for (size_t i = outlen; i > 0; i--) { - out[i - 1] = in & 0xff; - in = in >> 8; - } -} - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_bytes_to_ull( - const unsigned char *in, size_t inlen) { - unsigned long long retval = 0; - - for (size_t i = 0; i < inlen; i++) { - retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); - } - return retval; -} - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - uint32_t i; - unsigned char buffer[2 * PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_N]; - - /* If leaf_idx is odd (last bit = 1), current path element is a right child - and auth_path has to go left. Otherwise it is the other way around. */ - if (leaf_idx & 1) { - memcpy(buffer + PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_N, leaf, PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_N); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_N); - } else { - memcpy(buffer, leaf, PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_N); - memcpy(buffer + PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_N, auth_path, PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_N); - } - auth_path += PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_N; - - for (i = 0; i < tree_height - 1; i++) { - leaf_idx >>= 1; - idx_offset >>= 1; - /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_set_tree_height(addr, i + 1); - PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_set_tree_index( - addr, leaf_idx + idx_offset); - - /* Pick the right or left neighbor, depending on parity of the node. */ - if (leaf_idx & 1) { - PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_thash_2( - buffer + PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_N, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_N); - } else { - PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_thash_2( - buffer, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer + PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_N, auth_path, PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_N); - } - auth_path += PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_N; - } - - /* The last iteration is exceptional; we do not copy an auth_path node. */ - leaf_idx >>= 1; - idx_offset >>= 1; - PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_set_tree_height(addr, tree_height); - PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_set_tree_index( - addr, leaf_idx + idx_offset); - PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_thash_2( - root, buffer, pub_seed, addr, hash_state_seeded); -} - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -static void PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_treehash( - unsigned char *root, unsigned char *auth_path, - unsigned char *stack, unsigned int *heights, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - - unsigned int offset = 0; - uint32_t idx; - uint32_t tree_idx; - - for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { - /* Add the next leaf node to the stack. */ - gen_leaf(stack + offset * PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_N, - sk_seed, pub_seed, idx + idx_offset, tree_addr, - hash_state_seeded); - offset++; - heights[offset - 1] = 0; - - /* If this is a node we need for the auth path.. */ - if ((leaf_idx ^ 0x1) == idx) { - memcpy(auth_path, stack + (offset - 1)*PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_N, PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_N); - } - - /* While the top-most nodes are of equal height.. */ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { - /* Compute index of the new node, in the next layer. */ - tree_idx = (idx >> (heights[offset - 1] + 1)); - - /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_set_tree_height( - tree_addr, heights[offset - 1] + 1); - PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_set_tree_index( - tree_addr, tree_idx + (idx_offset >> (heights[offset - 1] + 1))); - /* Hash the top-most nodes from the stack together. */ - PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_thash_2( - stack + (offset - 2)*PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_N, stack + (offset - 2)*PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_N, - pub_seed, tree_addr, hash_state_seeded); - offset--; - /* Note that the top-most node is now one layer higher. */ - heights[offset - 1]++; - - /* If this is a node we need for the auth path.. */ - if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_path + heights[offset - 1]*PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_N, - stack + (offset - 1)*PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_N, PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_N); - } - } - } - memcpy(root, stack, PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_N); -} - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_FORS_HEIGHT + 1)*PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_N]; - unsigned int heights[PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_FORS_HEIGHT + 1]; - - PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_FORS_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_TREE_HEIGHT + 1)*PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_N]; - unsigned int heights[PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_TREE_HEIGHT + 1]; - - PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_TREE_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_clean/utils.h b/src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_clean/utils.h deleted file mode 100644 index 153481bd8e..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_clean/utils.h +++ /dev/null @@ -1,64 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_UTILS_H -#define PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_UTILS_H - -#include "hash_state.h" -#include "params.h" -#include -#include - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in); - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_bytes_to_ull( - const unsigned char *in, size_t inlen); - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -void PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_clean/wots.c b/src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_clean/wots.c deleted file mode 100644 index c2ef4a705e..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_clean/wots.c +++ /dev/null @@ -1,167 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "hash_state.h" -#include "params.h" -#include "thash.h" -#include "utils.h" -#include "wots.h" - -// TODO clarify address expectations, and make them more uniform. -// TODO i.e. do we expect types to be set already? -// TODO and do we expect modifications or copies? - -/** - * Computes the starting value for a chain, i.e. the secret key. - * Expects the address to be complete up to the chain address. - */ -static void wots_gen_sk(unsigned char *sk, const unsigned char *sk_seed, - uint32_t wots_addr[8], - const hash_state *hash_state_seeded) { - /* Make sure that the hash address is actually zeroed. */ - PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_set_hash_addr(wots_addr, 0); - - /* Generate sk element. */ - PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_prf_addr(sk, sk_seed, wots_addr, hash_state_seeded); -} - -/** - * Computes the chaining function. - * out and in have to be n-byte arrays. - * - * Interprets in as start-th value of the chain. - * addr has to contain the address of the chain. - */ -static void gen_chain(unsigned char *out, const unsigned char *in, - unsigned int start, unsigned int steps, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - uint32_t i; - - /* Initialize out with the value at position 'start'. */ - memcpy(out, in, PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_N); - - /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_WOTS_W; i++) { - PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_set_hash_addr(addr, i); - PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_thash_1( - out, out, pub_seed, addr, hash_state_seeded); - } -} - -/** - * base_w algorithm as described in draft. - * Interprets an array of bytes as integers in base w. - * This only works when log_w is a divisor of 8. - */ -static void base_w(unsigned int *output, const size_t out_len, - const unsigned char *input) { - size_t in = 0; - size_t out = 0; - unsigned char total = 0; - unsigned int bits = 0; - size_t consumed; - - for (consumed = 0; consumed < out_len; consumed++) { - if (bits == 0) { - total = input[in]; - in++; - bits += 8; - } - bits -= PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_WOTS_LOGW; - output[out] = (unsigned int)((total >> bits) & (PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_WOTS_W - 1)); - out++; - } -} - -/* Computes the WOTS+ checksum over a message (in base_w). */ -static void wots_checksum(unsigned int *csum_base_w, - const unsigned int *msg_base_w) { - unsigned int csum = 0; - unsigned char csum_bytes[(PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_WOTS_LEN2 * PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_WOTS_LOGW + 7) / 8]; - unsigned int i; - - /* Compute checksum. */ - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_WOTS_LEN1; i++) { - csum += PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_WOTS_W - 1 - msg_base_w[i]; - } - - /* Convert checksum to base_w. */ - /* Make sure expected empty zero bits are the least significant bits. */ - csum = csum << (8 - ((PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_WOTS_LEN2 * PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_WOTS_LOGW) % 8)); - PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_ull_to_bytes( - csum_bytes, sizeof(csum_bytes), csum); - base_w(csum_base_w, PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_WOTS_LEN2, csum_bytes); -} - -/* Takes a message and derives the matching chain lengths. */ -static void chain_lengths(unsigned int *lengths, const unsigned char *msg) { - base_w(lengths, PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_WOTS_LEN1, msg); - wots_checksum(lengths + PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_WOTS_LEN1, lengths); -} - -/** - * WOTS key generation. Takes a 32 byte sk_seed, expands it to WOTS private key - * elements and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_wots_gen_pk( - unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - uint32_t i; - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_WOTS_LEN; i++) { - PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_set_chain_addr(addr, i); - wots_gen_sk(pk + i * PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_N, sk_seed, addr, hash_state_seeded); - gen_chain(pk + i * PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_N, pk + i * PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_N, - 0, PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_WOTS_W - 1, pub_seed, addr, hash_state_seeded); - } -} - -/** - * Takes a n-byte message and the 32-byte sk_see to compute a signature 'sig'. - */ -void PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_wots_sign( - unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *hash_state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_WOTS_LEN; i++) { - PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_set_chain_addr(addr, i); - wots_gen_sk(sig + i * PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_N, sk_seed, addr, hash_state_seeded); - gen_chain(sig + i * PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_N, sig + i * PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_N, 0, lengths[i], pub_seed, addr, hash_state_seeded); - } -} - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_wots_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_WOTS_LEN; i++) { - PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_set_chain_addr(addr, i); - gen_chain(pk + i * PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_N, sig + i * PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_N, - lengths[i], PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_WOTS_W - 1 - lengths[i], pub_seed, addr, - hash_state_seeded); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_clean/wots.h b/src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_clean/wots.h deleted file mode 100644 index 46a68c98d8..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128f-robust_clean/wots.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_WOTS_H -#define PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_WOTS_H - -#include "hash_state.h" -#include "params.h" -#include - -/** - * WOTS key generation. Takes a 32 byte seed for the private key, expands it to - * a full WOTS private key and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_wots_gen_pk( - unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -/** - * Takes a n-byte message and the 32-byte seed for the private key to compute a - * signature that is placed at 'sig'. - */ -void PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_wots_sign( - unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *hash_state_seeded); - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_wots_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_avx2/LICENSE b/src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_avx2/LICENSE deleted file mode 100644 index 670154e353..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_avx2/LICENSE +++ /dev/null @@ -1,116 +0,0 @@ -CC0 1.0 Universal - -Statement of Purpose - -The laws of most jurisdictions throughout the world automatically confer -exclusive Copyright and Related Rights (defined below) upon the creator and -subsequent owner(s) (each and all, an "owner") of an original work of -authorship and/or a database (each, a "Work"). - -Certain owners wish to permanently relinquish those rights to a Work for the -purpose of contributing to a commons of creative, cultural and scientific -works ("Commons") that the public can reliably and without fear of later -claims of infringement build upon, modify, incorporate in other works, reuse -and redistribute as freely as possible in any form whatsoever and for any -purposes, including without limitation commercial purposes. These owners may -contribute to the Commons to promote the ideal of a free culture and the -further production of creative, cultural and scientific works, or to gain -reputation or greater distribution for their Work in part through the use and -efforts of others. - -For these and/or other purposes and motivations, and without any expectation -of additional consideration or compensation, the person associating CC0 with a -Work (the "Affirmer"), to the extent that he or she is an owner of Copyright -and Related Rights in the Work, voluntarily elects to apply CC0 to the Work -and publicly distribute the Work under its terms, with knowledge of his or her -Copyright and Related Rights in the Work and the meaning and intended legal -effect of CC0 on those rights. - -1. Copyright and Related Rights. A Work made available under CC0 may be -protected by copyright and related or neighboring rights ("Copyright and -Related Rights"). Copyright and Related Rights include, but are not limited -to, the following: - - i. the right to reproduce, adapt, distribute, perform, display, communicate, - and translate a Work; - - ii. moral rights retained by the original author(s) and/or performer(s); - - iii. publicity and privacy rights pertaining to a person's image or likeness - depicted in a Work; - - iv. rights protecting against unfair competition in regards to a Work, - subject to the limitations in paragraph 4(a), below; - - v. rights protecting the extraction, dissemination, use and reuse of data in - a Work; - - vi. database rights (such as those arising under Directive 96/9/EC of the - European Parliament and of the Council of 11 March 1996 on the legal - protection of databases, and under any national implementation thereof, - including any amended or successor version of such directive); and - - vii. other similar, equivalent or corresponding rights throughout the world - based on applicable law or treaty, and any national implementations thereof. - -2. Waiver. To the greatest extent permitted by, but not in contravention of, -applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and -unconditionally waives, abandons, and surrenders all of Affirmer's Copyright -and Related Rights and associated claims and causes of action, whether now -known or unknown (including existing as well as future claims and causes of -action), in the Work (i) in all territories worldwide, (ii) for the maximum -duration provided by applicable law or treaty (including future time -extensions), (iii) in any current or future medium and for any number of -copies, and (iv) for any purpose whatsoever, including without limitation -commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes -the Waiver for the benefit of each member of the public at large and to the -detriment of Affirmer's heirs and successors, fully intending that such Waiver -shall not be subject to revocation, rescission, cancellation, termination, or -any other legal or equitable action to disrupt the quiet enjoyment of the Work -by the public as contemplated by Affirmer's express Statement of Purpose. - -3. Public License Fallback. Should any part of the Waiver for any reason be -judged legally invalid or ineffective under applicable law, then the Waiver -shall be preserved to the maximum extent permitted taking into account -Affirmer's express Statement of Purpose. In addition, to the extent the Waiver -is so judged Affirmer hereby grants to each affected person a royalty-free, -non transferable, non sublicensable, non exclusive, irrevocable and -unconditional license to exercise Affirmer's Copyright and Related Rights in -the Work (i) in all territories worldwide, (ii) for the maximum duration -provided by applicable law or treaty (including future time extensions), (iii) -in any current or future medium and for any number of copies, and (iv) for any -purpose whatsoever, including without limitation commercial, advertising or -promotional purposes (the "License"). The License shall be deemed effective as -of the date CC0 was applied by Affirmer to the Work. Should any part of the -License for any reason be judged legally invalid or ineffective under -applicable law, such partial invalidity or ineffectiveness shall not -invalidate the remainder of the License, and in such case Affirmer hereby -affirms that he or she will not (i) exercise any of his or her remaining -Copyright and Related Rights in the Work or (ii) assert any associated claims -and causes of action with respect to the Work, in either case contrary to -Affirmer's express Statement of Purpose. - -4. Limitations and Disclaimers. - - a. No trademark or patent rights held by Affirmer are waived, abandoned, - surrendered, licensed or otherwise affected by this document. - - b. Affirmer offers the Work as-is and makes no representations or warranties - of any kind concerning the Work, express, implied, statutory or otherwise, - including without limitation warranties of title, merchantability, fitness - for a particular purpose, non infringement, or the absence of latent or - other defects, accuracy, or the present or absence of errors, whether or not - discoverable, all to the greatest extent permissible under applicable law. - - c. Affirmer disclaims responsibility for clearing rights of other persons - that may apply to the Work or any use thereof, including without limitation - any person's Copyright and Related Rights in the Work. Further, Affirmer - disclaims responsibility for obtaining any necessary consents, permissions - or other rights required for any use of the Work. - - d. Affirmer understands and acknowledges that Creative Commons is not a - party to this document and has no duty or obligation with respect to this - CC0 or use of the Work. - -For more information, please see - diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_avx2/address.c b/src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_avx2/address.c deleted file mode 100644 index 41b247de56..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_avx2/address.c +++ /dev/null @@ -1,78 +0,0 @@ -#include - -#include "address.h" -#include "params.h" -#include "utils.h" - -void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]) { - int i; - - for (i = 0; i < 8; i++) { - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_ull_to_bytes( - bytes + i * 4, 4, addr[i]); - } -} - -void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_set_layer_addr( - uint32_t addr[8], uint32_t layer) { - addr[0] = layer; -} - -void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_set_tree_addr( - uint32_t addr[8], uint64_t tree) { - addr[1] = 0; - addr[2] = (uint32_t) (tree >> 32); - addr[3] = (uint32_t) tree; -} - -void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_set_type( - uint32_t addr[8], uint32_t type) { - addr[4] = type; -} - -void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; -} - -/* These functions are used for OTS addresses. */ - -void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_set_keypair_addr( - uint32_t addr[8], uint32_t keypair) { - addr[5] = keypair; -} - -void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; - out[5] = in[5]; -} - -void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_set_chain_addr( - uint32_t addr[8], uint32_t chain) { - addr[6] = chain; -} - -void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_set_hash_addr( - uint32_t addr[8], uint32_t hash) { - addr[7] = hash; -} - -/* These functions are used for all hash tree addresses (including FORS). */ - -void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_set_tree_height( - uint32_t addr[8], uint32_t tree_height) { - addr[6] = tree_height; -} - -void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_set_tree_index( - uint32_t addr[8], uint32_t tree_index) { - addr[7] = tree_index; -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_avx2/address.h b/src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_avx2/address.h deleted file mode 100644 index 44bcaeae7e..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_avx2/address.h +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_ADDRESS_H -#define PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_ADDRESS_H - -#include - -#define PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_ADDR_TYPE_WOTS 0 -#define PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_ADDR_TYPE_WOTSPK 1 -#define PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_ADDR_TYPE_HASHTREE 2 -#define PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_ADDR_TYPE_FORSTREE 3 -#define PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_ADDR_TYPE_FORSPK 4 - -void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]); - -void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_set_layer_addr( - uint32_t addr[8], uint32_t layer); - -void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_set_tree_addr( - uint32_t addr[8], uint64_t tree); - -void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_set_type( - uint32_t addr[8], uint32_t type); - -/* Copies the layer and tree part of one address into the other */ -void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for WOTS and FORS addresses. */ - -void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_set_keypair_addr( - uint32_t addr[8], uint32_t keypair); - -void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_set_chain_addr( - uint32_t addr[8], uint32_t chain); - -void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_set_hash_addr( - uint32_t addr[8], uint32_t hash); - -void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for all hash tree addresses (including FORS). */ - -void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_set_tree_height( - uint32_t addr[8], uint32_t tree_height); - -void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_set_tree_index( - uint32_t addr[8], uint32_t tree_index); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_avx2/api.h b/src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_avx2/api.h deleted file mode 100644 index 11e99162c8..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_avx2/api.h +++ /dev/null @@ -1,81 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_API_H -#define PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_API_H - -#include -#include - - - -#define PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_CRYPTO_ALGNAME "SPHINCS+" - -#define PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_CRYPTO_SECRETKEYBYTES 64 -#define PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_CRYPTO_PUBLICKEYBYTES 32 -#define PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_CRYPTO_BYTES 17088 -#define PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_CRYPTO_SEEDBYTES 48 - - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_avx2/fors.c b/src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_avx2/fors.c deleted file mode 100644 index 8a89a3dfe5..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_avx2/fors.c +++ /dev/null @@ -1,206 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "fors.h" -#include "hash.h" -#include "hashx4.h" -#include "thash.h" -#include "thashx4.h" -#include "utils.h" -#include "utilsx4.h" - -static void fors_gen_skx4(unsigned char *sk0, - unsigned char *sk1, - unsigned char *sk2, - unsigned char *sk3, const unsigned char *sk_seed, - uint32_t fors_leaf_addrx4[4 * 8], - const hash_state *state_seeded) { - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_prf_addrx4(sk0, sk1, sk2, sk3, sk_seed, fors_leaf_addrx4, state_seeded); -} - -static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, - const unsigned char *pub_seed, - uint32_t fors_leaf_addr[8], const hash_state *state_seeded) { - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_thash_1(leaf, sk, pub_seed, fors_leaf_addr, state_seeded); -} - -static void fors_sk_to_leafx4(unsigned char *leaf0, - unsigned char *leaf1, - unsigned char *leaf2, - unsigned char *leaf3, - const unsigned char *sk0, - const unsigned char *sk1, - const unsigned char *sk2, - const unsigned char *sk3, - const unsigned char *pub_seed, - uint32_t fors_leaf_addrx4[4 * 8], - const hash_state *state_seeded) { - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_thashx4_1(leaf0, leaf1, leaf2, leaf3, - sk0, sk1, sk2, sk3, pub_seed, fors_leaf_addrx4, state_seeded); -} - -static void fors_gen_leafx4(unsigned char *leaf0, - unsigned char *leaf1, - unsigned char *leaf2, - unsigned char *leaf3, - const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx0, - uint32_t addr_idx1, - uint32_t addr_idx2, - uint32_t addr_idx3, - const uint32_t fors_tree_addr[8], - const hash_state *state_seeded) { - uint32_t fors_leaf_addrx4[4 * 8] = {0}; - unsigned int j; - - /* Only copy the parts that must be kept in fors_leaf_addrx4. */ - for (j = 0; j < 4; j++) { - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_copy_keypair_addr(fors_leaf_addrx4 + j * 8, fors_tree_addr); - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_set_type(fors_leaf_addrx4 + j * 8, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_ADDR_TYPE_FORSTREE); - } - - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_set_tree_index(fors_leaf_addrx4 + 0 * 8, addr_idx0); - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_set_tree_index(fors_leaf_addrx4 + 1 * 8, addr_idx1); - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_set_tree_index(fors_leaf_addrx4 + 2 * 8, addr_idx2); - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_set_tree_index(fors_leaf_addrx4 + 3 * 8, addr_idx3); - - fors_gen_skx4(leaf0, leaf1, leaf2, leaf3, sk_seed, fors_leaf_addrx4, state_seeded); - fors_sk_to_leafx4(leaf0, leaf1, leaf2, leaf3, - leaf0, leaf1, leaf2, leaf3, pub_seed, fors_leaf_addrx4, state_seeded); -} - -/** - * Interprets m as PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_FORS_HEIGHT-bit unsigned integers. - * Assumes m contains at least PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_FORS_TREES bits. - * Assumes indices has space for PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_FORS_TREES integers. - */ -static void message_to_indices(uint32_t *indices, const unsigned char *m) { - unsigned int i, j; - unsigned int offset = 0; - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_FORS_TREES; i++) { - indices[i] = 0; - for (j = 0; j < PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_FORS_HEIGHT; j++) { - indices[i] ^= (((uint32_t)m[offset >> 3] >> (offset & 0x7)) & 0x1) << j; - offset++; - } - } -} - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *state_seeded) { - /* Round up to multiple of 4 to prevent out-of-bounds for x4 parallelism */ - uint32_t indices[(PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_FORS_TREES + 3) & ~3] = {0}; - unsigned char roots[((PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_FORS_TREES + 3) & ~3) * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N]; - /* Sign to a buffer, since we may not have a nice multiple of 4 and would - otherwise overrun the signature. */ - unsigned char sigbufx4[4 * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N * (1 + PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_FORS_HEIGHT)]; - uint32_t fors_tree_addrx4[4 * 8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset[4] = {0}; - unsigned int i, j; - - for (j = 0; j < 4; j++) { - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_copy_keypair_addr(fors_tree_addrx4 + j * 8, fors_addr); - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_set_type(fors_tree_addrx4 + j * 8, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_ADDR_TYPE_FORSTREE); - } - - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_copy_keypair_addr(fors_pk_addr, fors_addr); - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_set_type(fors_pk_addr, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < ((PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_FORS_TREES + 3) & ~0x3); i += 4) { - for (j = 0; j < 4; j++) { - if (i + j < PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_FORS_TREES) { - idx_offset[j] = (i + j) * (1 << PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_FORS_HEIGHT); - - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_set_tree_height(fors_tree_addrx4 + j * 8, 0); - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_set_tree_index(fors_tree_addrx4 + j * 8, - indices[i + j] + idx_offset[j]); - } - } - - /* Include the secret key part that produces the selected leaf nodes. */ - fors_gen_skx4(sigbufx4 + 0 * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N, - sigbufx4 + 1 * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N, - sigbufx4 + 2 * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N, - sigbufx4 + 3 * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N, - sk_seed, fors_tree_addrx4, state_seeded); - - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_treehashx4_FORS_HEIGHT(roots + i * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N, sigbufx4 + 4 * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N, sk_seed, pub_seed, - &indices[i], idx_offset, fors_gen_leafx4, fors_tree_addrx4, - state_seeded); - - for (j = 0; j < 4; j++) { - if (i + j < PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_FORS_TREES) { - memcpy(sig, sigbufx4 + j * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N); - memcpy(sig + PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N, - sigbufx4 + 4 * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N + j * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_FORS_HEIGHT, - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_FORS_HEIGHT); - sig += PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N * (1 + PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_FORS_HEIGHT); - } - } - } - - /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_thash_FORS_TREES(pk, roots, pub_seed, fors_pk_addr, state_seeded); -} - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, - const uint32_t fors_addr[8], - const hash_state *state_seeded) { - uint32_t indices[PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_FORS_TREES]; - unsigned char roots[PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_FORS_TREES * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N]; - unsigned char leaf[PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N]; - uint32_t fors_tree_addr[8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_copy_keypair_addr(fors_tree_addr, fors_addr); - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_copy_keypair_addr(fors_pk_addr, fors_addr); - - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_set_type(fors_tree_addr, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_set_type(fors_pk_addr, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_FORS_TREES; i++) { - idx_offset = i * (1 << PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_FORS_HEIGHT); - - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_set_tree_height(fors_tree_addr, 0); - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Derive the leaf from the included secret key part. */ - fors_sk_to_leaf(leaf, sig, pub_seed, fors_tree_addr, state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N; - - /* Derive the corresponding root node of this tree. */ - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_compute_root(roots + i * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N, leaf, indices[i], idx_offset, - sig, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_FORS_HEIGHT, pub_seed, fors_tree_addr, - state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_thash_FORS_TREES(pk, roots, pub_seed, fors_pk_addr, state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_avx2/fors.h b/src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_avx2/fors.h deleted file mode 100644 index 5def0258fb..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_avx2/fors.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_FORS_H -#define PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_FORS_H - -#include - -#include "hash_state.h" -#include "params.h" - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_fors_sign( - unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *hash_state_seeded); - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_fors_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, const uint32_t fors_addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_avx2/hash.h b/src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_avx2/hash.h deleted file mode 100644 index 0a97be635a..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_avx2/hash.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_HASH_H -#define PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_HASH_H - -#include "hash_state.h" - -#include -#include - -void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_initialize_hash_function( - hash_state *hash_state_seeded, - const unsigned char *pub_seed, const unsigned char *sk_seed); - -void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_destroy_hash_function(hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_avx2/hash_shake256.c b/src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_avx2/hash_shake256.c deleted file mode 100644 index 496aac8f46..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_avx2/hash_shake256.c +++ /dev/null @@ -1,106 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "utils.h" - -#include "fips202.h" - -/* For SHAKE256, there is no immediate reason to initialize at the start, - so this function is an empty operation. */ -void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_initialize_hash_function( - hash_state *hash_state_seeded, // NOLINT(readability-non-const-parameter) - const unsigned char *pub_seed, const unsigned char *sk_seed) { - (void)hash_state_seeded; /* Suppress an 'unused parameter' warning. */ - (void)pub_seed; /* Suppress an 'unused parameter' warning. */ - (void)sk_seed; /* Suppress an 'unused parameter' warning. */ -} - -/* This is not necessary for SHAKE256, so we don't do anything */ -void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_destroy_hash_function( - hash_state *hash_state_seeded) { // NOLINT(readability-non-const-parameter) - (void)hash_state_seeded; -} - -/* - * Computes PRF(key, addr), given a secret key of PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N bytes and an address - */ -void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded) { - unsigned char buf[PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_ADDR_BYTES]; - - memcpy(buf, key, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N); - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_addr_to_bytes(buf + PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N, addr); - - shake256(out, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N, buf, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_ADDR_BYTES); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} - -/** - * Computes the message-dependent randomness R, using a secret seed and an - * optional randomization value as well as the message. - */ -void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded) { - shake256incctx state; - - shake256_inc_init(&state); - shake256_inc_absorb(&state, sk_prf, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N); - shake256_inc_absorb(&state, optrand, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N); - shake256_inc_absorb(&state, m, mlen); - shake256_inc_finalize(&state); - shake256_inc_squeeze(R, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N, &state); - shake256_inc_ctx_release(&state); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} - -/** - * Computes the message hash using R, the public key, and the message. - * Outputs the message digest and the index of the leaf. The index is split in - * the tree index and the leaf index, for convenient copying to an address. - */ -void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded) { -#define PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_TREE_BITS (PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_TREE_HEIGHT * (PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_D - 1)) -#define PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_TREE_BYTES ((PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_TREE_BITS + 7) / 8) -#define PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_LEAF_BITS PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_TREE_HEIGHT -#define PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_LEAF_BYTES ((PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_LEAF_BITS + 7) / 8) -#define PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_DGST_BYTES (PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_FORS_MSG_BYTES + PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_TREE_BYTES + PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_LEAF_BYTES) - - unsigned char buf[PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_DGST_BYTES]; - unsigned char *bufp = buf; - shake256incctx state; - - shake256_inc_init(&state); - shake256_inc_absorb(&state, R, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N); - shake256_inc_absorb(&state, pk, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_PK_BYTES); - shake256_inc_absorb(&state, m, mlen); - shake256_inc_finalize(&state); - shake256_inc_squeeze(buf, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_DGST_BYTES, &state); - shake256_inc_ctx_release(&state); - - memcpy(digest, bufp, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_FORS_MSG_BYTES); - bufp += PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_FORS_MSG_BYTES; - - *tree = PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_bytes_to_ull( - bufp, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_TREE_BYTES); - *tree &= (~(uint64_t)0) >> (64 - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_TREE_BITS); - bufp += PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_TREE_BYTES; - - *leaf_idx = (uint32_t)PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_bytes_to_ull( - bufp, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_LEAF_BYTES); - *leaf_idx &= (~(uint32_t)0) >> (32 - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_LEAF_BITS); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_avx2/hash_shake256x4.c b/src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_avx2/hash_shake256x4.c deleted file mode 100644 index 6f2a637311..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_avx2/hash_shake256x4.c +++ /dev/null @@ -1,38 +0,0 @@ -#include -#include - -#include "address.h" -#include "fips202x4.h" -#include "hashx4.h" -#include "params.h" - -/* - * 4-way parallel version of prf_addr; takes 4x as much input and output - */ -void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_prf_addrx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const unsigned char *key, - const uint32_t addrx4[4 * 8], - const hash_state *state_seeded) { - unsigned char bufx4[4 * (PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_ADDR_BYTES)]; - unsigned int j; - - for (j = 0; j < 4; j++) { - memcpy(bufx4 + j * (PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_ADDR_BYTES), key, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N); - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_addr_to_bytes(bufx4 + PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N + j * (PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_ADDR_BYTES), addrx4 + j * 8); - } - - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_shake256x4(out0, - out1, - out2, - out3, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N, - bufx4 + 0 * (PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_ADDR_BYTES), - bufx4 + 1 * (PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_ADDR_BYTES), - bufx4 + 2 * (PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_ADDR_BYTES), - bufx4 + 3 * (PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_ADDR_BYTES), PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_ADDR_BYTES); - - /* Avoid unused parameter warning */ - (void)state_seeded; -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_avx2/hash_state.h b/src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_avx2/hash_state.h deleted file mode 100644 index 6af386457e..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_avx2/hash_state.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_HASH_STATE_H -#define PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_HASH_STATE_H - -/** - * Defines the type of the hash function state. - * - * Don't be fooled into thinking this instance of SPHINCS+ isn't stateless! - * - * From Section 7.2.2 from the SPHINCS+ round-2 specification: - * - * Each of the instances of the tweakable hash function take PK.seed as its - * first input, which is constant for a given key pair – and, thus, across - * a single signature. This leads to a lot of redundant computation. To remedy - * this, we pad PK.seed to the length of a full 64-byte SHA-256 input block. - * Because of the Merkle-DamgÃ¥rd construction that underlies SHA-256, this - * allows for reuse of the intermediate SHA-256 state after the initial call to - * the compression function which improves performance. - * - * We pass this hash state around in functions, because otherwise we need to - * have a global variable. - * - * SHAKE256 does not need this state. Because this implementation is generated - * from a shared code base, we still need to specify some hash_state as it is - * still passed around. We chose to use an `int` as a placeholder for this - * purpose. - */ - -typedef int hash_state; - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_avx2/hashx4.h b/src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_avx2/hashx4.h deleted file mode 100644 index 1842aef4f2..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_avx2/hashx4.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_HASHX4_H -#define PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_HASHX4_H - -#include - -#include "hash_state.h" - -void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_prf_addrx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const unsigned char *key, - const uint32_t addrx4[4 * 8], - const hash_state *state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_avx2/params.h b/src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_avx2/params.h deleted file mode 100644 index ff33882a76..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_avx2/params.h +++ /dev/null @@ -1,53 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_PARAMS_H -#define PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_PARAMS_H - -/* Hash output length in bytes. */ -#define PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N 16 -/* Height of the hypertree. */ -#define PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_FULL_HEIGHT 66 -/* Number of subtree layer. */ -#define PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_D 22 -/* FORS tree dimensions. */ -#define PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_FORS_HEIGHT 6 -#define PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_FORS_TREES 33 -/* Winternitz parameter, */ -#define PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_WOTS_W 16 - -/* The hash function is defined by linking a different hash.c file, as opposed - to setting a #define constant. */ - -/* For clarity */ -#define PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_ADDR_BYTES 32 - -/* WOTS parameters. */ -#define PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_WOTS_LOGW 4 - -#define PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_WOTS_LEN1 (8 * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N / PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_WOTS_LOGW) - -/* PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#define PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_WOTS_LEN2 3 - -#define PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_WOTS_LEN (PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_WOTS_LEN1 + PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_WOTS_LEN2) -#define PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_WOTS_BYTES (PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_WOTS_LEN * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N) -#define PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_WOTS_PK_BYTES PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_WOTS_BYTES - -/* Subtree size. */ -#define PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_TREE_HEIGHT (PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_FULL_HEIGHT / PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_D) - -/* FORS parameters. */ -#define PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_FORS_MSG_BYTES ((PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_FORS_TREES + 7) / 8) -#define PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_FORS_BYTES ((PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_FORS_HEIGHT + 1) * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_FORS_TREES * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N) -#define PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_FORS_PK_BYTES PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N - -/* Resulting SPX sizes. */ -#define PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_BYTES (PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_FORS_BYTES + PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_D * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_WOTS_BYTES +\ - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_FULL_HEIGHT * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N) -#define PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_PK_BYTES (2 * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N) -#define PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_SK_BYTES (2 * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_PK_BYTES) - -/* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ -#define PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_OPTRAND_BYTES 32 - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_avx2/sign.c b/src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_avx2/sign.c deleted file mode 100644 index 1b77e89656..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_avx2/sign.c +++ /dev/null @@ -1,409 +0,0 @@ -#include -#include -#include -#include - -#include "address.h" -#include "api.h" -#include "fors.h" -#include "hash.h" -#include "hash_state.h" -#include "params.h" -#include "randombytes.h" -#include "thash.h" -#include "utils.h" -#include "wots.h" - - -/** - * Computes the leaf at a given address. First generates the WOTS key pair, - * then computes leaf by hashing horizontally. - */ -static void wots_gen_leaf(unsigned char *leaf, const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx, const uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - unsigned char pk[PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_WOTS_BYTES]; - uint32_t wots_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_set_type( - wots_addr, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_set_type( - wots_pk_addr, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_ADDR_TYPE_WOTSPK); - - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_set_keypair_addr( - wots_addr, addr_idx); - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_wots_gen_pk( - pk, sk_seed, pub_seed, wots_addr, hash_state_seeded); - - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_copy_keypair_addr( - wots_pk_addr, wots_addr); - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_thash_WOTS_LEN( - leaf, pk, pub_seed, wots_pk_addr, hash_state_seeded); -} - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_crypto_sign_secretkeybytes(void) { - return PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_CRYPTO_SECRETKEYBYTES; -} - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_crypto_sign_publickeybytes(void) { - return PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_CRYPTO_PUBLICKEYBYTES; -} - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_crypto_sign_bytes(void) { - return PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_CRYPTO_BYTES; -} - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_crypto_sign_seedbytes(void) { - return PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_CRYPTO_SEEDBYTES; -} - -/* - * Generates an SPX key pair given a seed of length - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed) { - /* We do not need the auth path in key generation, but it simplifies the - code to have just one treehash routine that computes both root and path - in one function. */ - unsigned char auth_path[PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_TREE_HEIGHT * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N]; - uint32_t top_tree_addr[8] = {0}; - hash_state hash_state_seeded; - - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_set_layer_addr( - top_tree_addr, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_D - 1); - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_set_type( - top_tree_addr, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_ADDR_TYPE_HASHTREE); - - /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ - memcpy(sk, seed, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_CRYPTO_SEEDBYTES); - - memcpy(pk, sk + 2 * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_initialize_hash_function(&hash_state_seeded, pk, sk); - - /* Compute root node of the top-most subtree. */ - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_treehash_TREE_HEIGHT( - sk + 3 * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N, auth_path, sk, sk + 2 * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N, 0, 0, - wots_gen_leaf, top_tree_addr, &hash_state_seeded); - - memcpy(pk + PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N, sk + 3 * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N); - - return 0; -} - -/* - * Generates an SPX key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk) { - - // guarantee alignment of pk - union { - __m128 _x[PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_CRYPTO_PUBLICKEYBYTES / 16]; - uint8_t pk[PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_CRYPTO_PUBLICKEYBYTES]; - } aligned_pk; - - // guarantee alignment of sk - union { - __m128 _x[PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_CRYPTO_SECRETKEYBYTES / 16]; - uint8_t sk[PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_CRYPTO_SECRETKEYBYTES]; - } aligned_sk; - - union { - __m128 _x[PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_CRYPTO_SEEDBYTES / 16]; - uint8_t seed[PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_CRYPTO_SEEDBYTES]; - } aligned_seed; - randombytes(aligned_seed.seed, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_CRYPTO_SEEDBYTES); - - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_crypto_sign_seed_keypair( - aligned_pk.pk, aligned_sk.sk, aligned_seed.seed); - memcpy(pk, aligned_pk.pk, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_CRYPTO_PUBLICKEYBYTES); - memcpy(sk, aligned_sk.sk, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_CRYPTO_SECRETKEYBYTES); - - return 0; -} - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - // guarantee alignment of sk - union { - __m128 *_x; - uint8_t sk[PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_CRYPTO_SECRETKEYBYTES]; - } aligned_sk; - memcpy(aligned_sk.sk, sk, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_CRYPTO_SECRETKEYBYTES); - sk = aligned_sk.sk; - - // guarantee alignment of sig - union { - __m128 *_x; - uint8_t sig[PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_BYTES]; - } aligned_sig; - uint8_t *orig_sig = sig; - sig = (uint8_t *)aligned_sig.sig; - - const unsigned char *sk_seed = sk; - const unsigned char *sk_prf = sk + PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N; - const unsigned char *pk = sk + 2 * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N; - const unsigned char *pub_seed = pk; - - unsigned char optrand[PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N]; - unsigned char mhash[PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_FORS_MSG_BYTES]; - unsigned char root[PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N]; - uint32_t i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - - hash_state hash_state_seeded; - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_initialize_hash_function( - &hash_state_seeded, - pub_seed, sk_seed); - - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_set_type( - wots_addr, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_set_type( - tree_addr, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_ADDR_TYPE_HASHTREE); - - /* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ - randombytes(optrand, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N); - /* Compute the digest randomization value. */ - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_gen_message_random( - sig, sk_prf, optrand, m, mlen, &hash_state_seeded); - - /* Derive the message digest and leaf index from R, PK and M. */ - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N; - - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_set_keypair_addr( - wots_addr, idx_leaf); - - /* Sign the message hash using FORS. */ - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_fors_sign( - sig, root, mhash, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_FORS_BYTES; - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_D; i++) { - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_set_tree_addr(tree_addr, tree); - - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_set_keypair_addr( - wots_addr, idx_leaf); - - /* Compute a WOTS signature. */ - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_wots_sign( - sig, root, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_WOTS_BYTES; - - /* Compute the authentication path for the used WOTS leaf. */ - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_treehash_TREE_HEIGHT( - root, sig, sk_seed, pub_seed, idx_leaf, 0, - wots_gen_leaf, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_TREE_HEIGHT * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_TREE_HEIGHT; - } - - memcpy(orig_sig, aligned_sig.sig, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_BYTES); - *siglen = PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_BYTES; - - return 0; -} - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk) { - // guarantee alignment of pk - union { - __m128 *_x; - uint8_t pk[PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_CRYPTO_PUBLICKEYBYTES]; - } aligned_pk; - memcpy(aligned_pk.pk, pk, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_CRYPTO_PUBLICKEYBYTES); - pk = aligned_pk.pk; - - const unsigned char *pub_seed = pk; - const unsigned char *pub_root = pk + PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N; - unsigned char mhash[PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_FORS_MSG_BYTES]; - unsigned char wots_pk[PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_WOTS_BYTES]; - unsigned char root[PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N]; - unsigned char leaf[PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N]; - unsigned int i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - hash_state hash_state_seeded; - - if (siglen != PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_BYTES) { - return -1; - } - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_initialize_hash_function( - &hash_state_seeded, - pub_seed, NULL); - - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_set_type( - wots_addr, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_set_type( - tree_addr, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_ADDR_TYPE_HASHTREE); - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_set_type( - wots_pk_addr, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_ADDR_TYPE_WOTSPK); - - /* Derive the message digest and leaf index from R || PK || M. */ - /* The additional PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N is a result of the hash domain separator. */ - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N; - - /* Layer correctly defaults to 0, so no need to set_layer_addr */ - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_set_keypair_addr( - wots_addr, idx_leaf); - - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_fors_pk_from_sig( - root, sig, mhash, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_FORS_BYTES; - - /* For each subtree.. */ - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_D; i++) { - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_set_tree_addr(tree_addr, tree); - - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_set_keypair_addr( - wots_addr, idx_leaf); - - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_copy_keypair_addr( - wots_pk_addr, wots_addr); - - /* The WOTS public key is only correct if the signature was correct. */ - /* Initially, root is the FORS pk, but on subsequent iterations it is - the root of the subtree below the currently processed subtree. */ - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_wots_pk_from_sig( - wots_pk, sig, root, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_WOTS_BYTES; - - /* Compute the leaf node using the WOTS public key. */ - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_thash_WOTS_LEN( - leaf, wots_pk, pub_seed, wots_pk_addr, &hash_state_seeded); - - /* Compute the root node of this subtree. */ - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_compute_root( - root, leaf, idx_leaf, 0, sig, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_TREE_HEIGHT, - pub_seed, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_TREE_HEIGHT * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_TREE_HEIGHT; - } - - /* Check if the root node equals the root node in the public key. */ - if (memcmp(root, pub_root, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N) != 0) { - return -1; - } - - return 0; -} - - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - size_t siglen; - - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_crypto_sign_signature( - sm, &siglen, m, mlen, sk); - - memmove(sm + PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_BYTES, m, mlen); - *smlen = siglen + mlen; - - return 0; -} - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk) { - - // guarantee alignment of pk - union { - __m128 *_x; - uint8_t pk[PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_CRYPTO_PUBLICKEYBYTES]; - } aligned_pk; - memcpy(aligned_pk.pk, pk, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_CRYPTO_PUBLICKEYBYTES); - pk = aligned_pk.pk; - - - /* The API caller does not necessarily know what size a signature should be - but SPHINCS+ signatures are always exactly PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_BYTES. */ - if (smlen < PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_BYTES) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - *mlen = smlen - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_BYTES; - - if (PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_crypto_sign_verify( - sm, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_BYTES, sm + PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_BYTES, *mlen, pk)) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - /* If verification was successful, move the message to the right place. */ - memmove(m, sm + PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_BYTES, *mlen); - - return 0; -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_avx2/thash.h b/src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_avx2/thash.h deleted file mode 100644 index 532ff45f2b..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_avx2/thash.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_THASH_H -#define PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_THASH_H - -#include "hash_state.h" - -#include - -void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_avx2/thash_shake256_simple.c b/src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_avx2/thash_shake256_simple.c deleted file mode 100644 index 2812f11e70..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_avx2/thash_shake256_simple.c +++ /dev/null @@ -1,74 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash_state.h" -#include "params.h" -#include "thash.h" - -#include "fips202.h" - -/** - * Takes an array of inblocks concatenated arrays of PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N bytes. - */ -static void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_thash( - unsigned char *out, unsigned char *buf, - const unsigned char *in, unsigned int inblocks, - const unsigned char *pub_seed, uint32_t addr[8]) { - - memcpy(buf, pub_seed, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N); - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_addr_to_bytes(buf + PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N, addr); - memcpy(buf + PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_ADDR_BYTES, in, inblocks * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N); - - shake256(out, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N, buf, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N); -} - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_ADDR_BYTES + 1 * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N]; - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_thash( - out, buf, in, 1, pub_seed, addr); - - (void)hash_state_seeded; /* Avoid unused parameter warning. */ -} - -void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_ADDR_BYTES + 2 * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N]; - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_thash( - out, buf, in, 2, pub_seed, addr); - - (void)hash_state_seeded; /* Avoid unused parameter warning. */ -} - -void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_ADDR_BYTES + PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_WOTS_LEN * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N]; - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_thash( - out, buf, in, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_WOTS_LEN, pub_seed, addr); - - (void)hash_state_seeded; /* Avoid unused parameter warning. */ -} - -void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_ADDR_BYTES + PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_FORS_TREES * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N]; - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_thash( - out, buf, in, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_FORS_TREES, pub_seed, addr); - - (void)hash_state_seeded; /* Avoid unused parameter warning. */ -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_avx2/thash_shake256_simplex4.c b/src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_avx2/thash_shake256_simplex4.c deleted file mode 100644 index 704c324453..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_avx2/thash_shake256_simplex4.c +++ /dev/null @@ -1,47 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "thashx4.h" - -#include "fips202x4.h" - -/** - * 4-way parallel version of thash; takes 4x as much input and output - */ -#define thashx4_variant(name, inblocks) \ - void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_thashx4_##name( \ - unsigned char *out0, unsigned char *out1, unsigned char *out2, unsigned char *out3, \ - const unsigned char *in0, const unsigned char *in1, const unsigned char *in2, \ - const unsigned char *in3, const unsigned char *pub_seed, uint32_t addrx4[4 * 8], \ - const hash_state *state_seeded) { \ - unsigned char buf0[PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_ADDR_BYTES + (inblocks)*PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N]; \ - unsigned char buf1[PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_ADDR_BYTES + (inblocks)*PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N]; \ - unsigned char buf2[PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_ADDR_BYTES + (inblocks)*PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N]; \ - unsigned char buf3[PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_ADDR_BYTES + (inblocks)*PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N]; \ - \ - memcpy(buf0, pub_seed, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N); \ - memcpy(buf1, pub_seed, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N); \ - memcpy(buf2, pub_seed, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N); \ - memcpy(buf3, pub_seed, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N); \ - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_addr_to_bytes(buf0 + PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N, addrx4 + 0 * 8); \ - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_addr_to_bytes(buf1 + PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N, addrx4 + 1 * 8); \ - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_addr_to_bytes(buf2 + PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N, addrx4 + 2 * 8); \ - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_addr_to_bytes(buf3 + PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N, addrx4 + 3 * 8); \ - memcpy(buf0 + PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_ADDR_BYTES, in0, (inblocks)*PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N); \ - memcpy(buf1 + PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_ADDR_BYTES, in1, (inblocks)*PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N); \ - memcpy(buf2 + PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_ADDR_BYTES, in2, (inblocks)*PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N); \ - memcpy(buf3 + PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_ADDR_BYTES, in3, (inblocks)*PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N); \ - \ - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_shake256x4(out0, out1, out2, out3, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N, buf0, buf1, buf2, buf3, \ - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_ADDR_BYTES + (inblocks)*PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N); \ - \ - /* Avoid unused parameter warning */ \ - (void)state_seeded; \ - } - -thashx4_variant(1, 1) -thashx4_variant(2, 2) -thashx4_variant(WOTS_LEN, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_WOTS_LEN) -thashx4_variant(FORS_TREES, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_FORS_TREES) diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_avx2/thashx4.h b/src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_avx2/thashx4.h deleted file mode 100644 index 274c99c2cc..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_avx2/thashx4.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_THASHX4_H -#define PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_THASHX4_H - -#include - -#include "hash_state.h" - -#define thashx4_header(inblocks) \ - void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_thashx4_##inblocks(unsigned char *out0, \ - unsigned char *out1, \ - unsigned char *out2, \ - unsigned char *out3, \ - const unsigned char *in0, \ - const unsigned char *in1, \ - const unsigned char *in2, \ - const unsigned char *in3, \ - const unsigned char *pub_seed, uint32_t addrx4[4*8], \ - const hash_state *state_seeded) - -thashx4_header(1); -thashx4_header(2); -thashx4_header(WOTS_LEN); -thashx4_header(FORS_TREES); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_avx2/utils.c b/src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_avx2/utils.c deleted file mode 100644 index efe313ad7c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_avx2/utils.c +++ /dev/null @@ -1,199 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "hash_state.h" -#include "params.h" -#include "thash.h" -#include "utils.h" - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in) { - - /* Iterate over out in decreasing order, for big-endianness. */ - for (size_t i = outlen; i > 0; i--) { - out[i - 1] = in & 0xff; - in = in >> 8; - } -} - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_bytes_to_ull( - const unsigned char *in, size_t inlen) { - unsigned long long retval = 0; - - for (size_t i = 0; i < inlen; i++) { - retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); - } - return retval; -} - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - uint32_t i; - unsigned char buffer[2 * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N]; - - /* If leaf_idx is odd (last bit = 1), current path element is a right child - and auth_path has to go left. Otherwise it is the other way around. */ - if (leaf_idx & 1) { - memcpy(buffer + PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N, leaf, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N); - } else { - memcpy(buffer, leaf, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N); - memcpy(buffer + PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N, auth_path, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N); - } - auth_path += PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N; - - for (i = 0; i < tree_height - 1; i++) { - leaf_idx >>= 1; - idx_offset >>= 1; - /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_set_tree_height(addr, i + 1); - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_set_tree_index( - addr, leaf_idx + idx_offset); - - /* Pick the right or left neighbor, depending on parity of the node. */ - if (leaf_idx & 1) { - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_thash_2( - buffer + PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N); - } else { - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_thash_2( - buffer, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer + PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N, auth_path, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N); - } - auth_path += PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N; - } - - /* The last iteration is exceptional; we do not copy an auth_path node. */ - leaf_idx >>= 1; - idx_offset >>= 1; - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_set_tree_height(addr, tree_height); - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_set_tree_index( - addr, leaf_idx + idx_offset); - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_thash_2( - root, buffer, pub_seed, addr, hash_state_seeded); -} - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -static void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_treehash( - unsigned char *root, unsigned char *auth_path, - unsigned char *stack, unsigned int *heights, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - - unsigned int offset = 0; - uint32_t idx; - uint32_t tree_idx; - - for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { - /* Add the next leaf node to the stack. */ - gen_leaf(stack + offset * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N, - sk_seed, pub_seed, idx + idx_offset, tree_addr, - hash_state_seeded); - offset++; - heights[offset - 1] = 0; - - /* If this is a node we need for the auth path.. */ - if ((leaf_idx ^ 0x1) == idx) { - memcpy(auth_path, stack + (offset - 1)*PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N); - } - - /* While the top-most nodes are of equal height.. */ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { - /* Compute index of the new node, in the next layer. */ - tree_idx = (idx >> (heights[offset - 1] + 1)); - - /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_set_tree_height( - tree_addr, heights[offset - 1] + 1); - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_set_tree_index( - tree_addr, tree_idx + (idx_offset >> (heights[offset - 1] + 1))); - /* Hash the top-most nodes from the stack together. */ - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_thash_2( - stack + (offset - 2)*PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N, stack + (offset - 2)*PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N, - pub_seed, tree_addr, hash_state_seeded); - offset--; - /* Note that the top-most node is now one layer higher. */ - heights[offset - 1]++; - - /* If this is a node we need for the auth path.. */ - if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_path + heights[offset - 1]*PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N, - stack + (offset - 1)*PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N); - } - } - } - memcpy(root, stack, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N); -} - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_FORS_HEIGHT + 1)*PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N]; - unsigned int heights[PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_FORS_HEIGHT + 1]; - - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_FORS_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_TREE_HEIGHT + 1)*PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N]; - unsigned int heights[PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_TREE_HEIGHT + 1]; - - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_TREE_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_avx2/utils.h b/src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_avx2/utils.h deleted file mode 100644 index 3abe2cbefc..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_avx2/utils.h +++ /dev/null @@ -1,64 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_UTILS_H -#define PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_UTILS_H - -#include "hash_state.h" -#include "params.h" -#include -#include - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in); - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_bytes_to_ull( - const unsigned char *in, size_t inlen); - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_avx2/utilsx4.c b/src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_avx2/utilsx4.c deleted file mode 100644 index 4222466c6b..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_avx2/utilsx4.c +++ /dev/null @@ -1,98 +0,0 @@ -#include "address.h" -#include "params.h" -#include "thashx4.h" -#include "utils.h" -#include "utilsx4.h" - -#include - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -#define treehashx4_variant(name, tree_height) \ - void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_treehashx4_##name( \ - unsigned char *rootx4, unsigned char *auth_pathx4, const unsigned char *sk_seed, \ - const unsigned char *pub_seed, const uint32_t leaf_idx[4], uint32_t idx_offset[4], \ - void (*gen_leafx4)(unsigned char * /* leaf0 */, unsigned char * /* leaf1 */, \ - unsigned char * /* leaf2 */, unsigned char * /* leaf3 */, \ - const unsigned char * /* sk_seed */, \ - const unsigned char * /* pub_seed */, uint32_t /* addr_idx0 */, \ - uint32_t /* addr_idx1 */, uint32_t /* addr_idx2 */, \ - uint32_t /* addr_idx3 */, const uint32_t[8] /* tree_addr */, \ - const hash_state * /* state_seeded */), \ - uint32_t tree_addrx4[4 * 8], const hash_state *state_seeded) { \ - unsigned char stackx4[4 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N]; \ - unsigned int heights[(tree_height) + 1]; \ - unsigned int offset = 0; \ - uint32_t idx; \ - uint32_t tree_idx; \ - unsigned int j; \ - \ - for (idx = 0; idx < (uint32_t)(1 << (tree_height)); idx++) { \ - /* Add the next leaf node to the stack. */ \ - gen_leafx4(stackx4 + 0 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N + offset * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N, \ - stackx4 + 1 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N + offset * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N, \ - stackx4 + 2 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N + offset * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N, \ - stackx4 + 3 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N + offset * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N, sk_seed, \ - pub_seed, idx + idx_offset[0], idx + idx_offset[1], idx + idx_offset[2], \ - idx + idx_offset[3], tree_addrx4, state_seeded); \ - offset++; \ - heights[offset - 1] = 0; \ - \ - /* If this is a node we need for the auth path.. */ \ - for (j = 0; j < 4; j++) { \ - if ((leaf_idx[j] ^ 0x1) == idx) { \ - memcpy(auth_pathx4 + j * (tree_height)*PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N, \ - stackx4 + j * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N + (offset - 1) * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N, \ - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N); \ - } \ - } \ - \ - /* While the top-most nodes are of equal height.. */ \ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { \ - /* Compute index of the new node, in the next layer. */ \ - tree_idx = (idx >> (heights[offset - 1] + 1)); \ - \ - /* Set the address of the node we're creating. */ \ - for (j = 0; j < 4; j++) { \ - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_set_tree_height(tree_addrx4 + j * 8, heights[offset - 1] + 1); \ - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_set_tree_index(tree_addrx4 + j * 8, \ - tree_idx + (idx_offset[j] >> (heights[offset - 1] + 1))); \ - } \ - /* Hash the top-most nodes from the stack together. */ \ - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_thashx4_2(stackx4 + 0 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N + (offset - 2) * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N, \ - stackx4 + 1 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N + (offset - 2) * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N, \ - stackx4 + 2 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N + (offset - 2) * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N, \ - stackx4 + 3 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N + (offset - 2) * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N, \ - stackx4 + 0 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N + (offset - 2) * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N, \ - stackx4 + 1 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N + (offset - 2) * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N, \ - stackx4 + 2 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N + (offset - 2) * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N, \ - stackx4 + 3 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N + (offset - 2) * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N, \ - pub_seed, tree_addrx4, state_seeded); \ - offset--; \ - /* Note that the top-most node is now one layer higher. */ \ - heights[offset - 1]++; \ - \ - /* If this is a node we need for the auth path.. */ \ - for (j = 0; j < 4; j++) { \ - if (((leaf_idx[j] >> heights[offset - 1]) ^ 0x1) == tree_idx) { \ - memcpy(auth_pathx4 + j * (tree_height)*PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N + \ - heights[offset - 1] * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N, \ - stackx4 + j * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N + (offset - 1) * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N, \ - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N); \ - } \ - } \ - } \ - } \ - \ - for (j = 0; j < 4; j++) { \ - memcpy(rootx4 + j * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N, stackx4 + j * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N); \ - } \ - } - -treehashx4_variant(FORS_HEIGHT, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_FORS_HEIGHT) diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_avx2/utilsx4.h b/src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_avx2/utilsx4.h deleted file mode 100644 index 6518962fbb..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_avx2/utilsx4.h +++ /dev/null @@ -1,38 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_UTILSX4_H -#define PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_UTILSX4_H - -#include "hash_state.h" -#include "params.h" - -#include - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_treehashx4_FORS_HEIGHT(unsigned char *rootx4, - unsigned char *auth_pathx4, - const unsigned char *sk_seed, - const unsigned char *pub_seed, - const uint32_t leaf_idx[4], - uint32_t idx_offset[4], - void (*gen_leafx4)(unsigned char * /* leaf0 */, - unsigned char * /* leaf1 */, - unsigned char * /* leaf2 */, - unsigned char * /* leaf3 */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx0 */, - uint32_t /* addr_idx1 */, - uint32_t /* addr_idx2 */, - uint32_t /* addr_idx3 */, - const uint32_t[8] /* tree_addr */, - const hash_state * /* state_seeded */), - uint32_t tree_addrx4[4 * 8], - const hash_state *state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_avx2/wots.c b/src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_avx2/wots.c deleted file mode 100644 index c3ad965b3f..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_avx2/wots.c +++ /dev/null @@ -1,240 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "hash_state.h" -#include "hashx4.h" -#include "params.h" -#include "thash.h" -#include "thashx4.h" -#include "utils.h" -#include "wots.h" - -// TODO clarify address expectations, and make them more uniform. -// TODO i.e. do we expect types to be set already? -// TODO and do we expect modifications or copies? - -/** - * Computes the starting value for a chain, i.e. the secret key. - * Expects the address to be complete up to the chain address. - */ -static void wots_gen_sk(unsigned char *sk, const unsigned char *sk_seed, - uint32_t wots_addr[8], const hash_state *state_seeded) { - /* Make sure that the hash address is actually zeroed. */ - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_set_hash_addr(wots_addr, 0); - - /* Generate sk element. */ - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_prf_addr(sk, sk_seed, wots_addr, state_seeded); -} - -/** - * 4-way parallel version of wots_gen_sk; expects 4x as much space in sk - */ -static void wots_gen_skx4(unsigned char *skx4, const unsigned char *sk_seed, - uint32_t wots_addrx4[4 * 8], const hash_state *state_seeded) { - unsigned int j; - - /* Make sure that the hash address is actually zeroed. */ - for (j = 0; j < 4; j++) { - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_set_hash_addr(wots_addrx4 + j * 8, 0); - } - - /* Generate sk element. */ - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_prf_addrx4(skx4 + 0 * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N, - skx4 + 1 * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N, - skx4 + 2 * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N, - skx4 + 3 * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N, - sk_seed, wots_addrx4, - state_seeded); -} - -/** - * Computes the chaining function. - * out and in have to be n-byte arrays. - * - * Interprets in as start-th value of the chain. - * addr has to contain the address of the chain. - */ -static void gen_chain(unsigned char *out, const unsigned char *in, - unsigned int start, unsigned int steps, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *state_seeded) { - uint32_t i; - - /* Initialize out with the value at position 'start'. */ - memcpy(out, in, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N); - - /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_WOTS_W; i++) { - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_set_hash_addr(addr, i); - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_thash_1(out, out, pub_seed, addr, state_seeded); - } -} - -/** - * 4-way parallel version of gen_chain; expects 4x as much space in out, and - * 4x as much space in inx4. Assumes start and step identical across chains. - */ -static void gen_chainx4(unsigned char *outx4, const unsigned char *inx4, - unsigned int start, unsigned int steps, - const unsigned char *pub_seed, uint32_t addrx4[4 * 8], - const hash_state *state_seeded) { - uint32_t i; - unsigned int j; - - /* Initialize outx4 with the value at position 'start'. */ - memcpy(outx4, inx4, 4 * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N); - - /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_WOTS_W; i++) { - for (j = 0; j < 4; j++) { - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_set_hash_addr(addrx4 + j * 8, i); - } - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_thashx4_1(outx4 + 0 * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N, - outx4 + 1 * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N, - outx4 + 2 * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N, - outx4 + 3 * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N, - outx4 + 0 * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N, - outx4 + 1 * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N, - outx4 + 2 * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N, - outx4 + 3 * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N, - pub_seed, addrx4, - state_seeded); - } -} - -/** - * base_w algorithm as described in draft. - * Interprets an array of bytes as integers in base w. - * This only works when log_w is a divisor of 8. - */ -static void base_w(unsigned int *output, const int out_len, const unsigned char *input) { - int in = 0; - int out = 0; - unsigned char total = 0; - int bits = 0; - int consumed; - - for (consumed = 0; consumed < out_len; consumed++) { - if (bits == 0) { - total = input[in]; - in++; - bits += 8; - } - bits -= PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_WOTS_LOGW; - output[out] = (unsigned int)(total >> bits) & (PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_WOTS_W - 1); - out++; - } -} - -/* Computes the WOTS+ checksum over a message (in base_w). */ -static void wots_checksum(unsigned int *csum_base_w, const unsigned int *msg_base_w) { - unsigned int csum = 0; - unsigned char csum_bytes[(PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_WOTS_LEN2 * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_WOTS_LOGW + 7) / 8]; - unsigned int i; - - /* Compute checksum. */ - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_WOTS_LEN1; i++) { - csum += PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_WOTS_W - 1 - msg_base_w[i]; - } - - /* Convert checksum to base_w. */ - /* Make sure expected empty zero bits are the least significant bits. */ - csum = csum << (8 - ((PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_WOTS_LEN2 * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_WOTS_LOGW) % 8)); - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); - base_w(csum_base_w, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_WOTS_LEN2, csum_bytes); -} - -/* Takes a message and derives the matching chain lengths. */ -static void chain_lengths(unsigned int *lengths, const unsigned char *msg) { - base_w(lengths, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_WOTS_LEN1, msg); - wots_checksum(lengths + PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_WOTS_LEN1, lengths); -} - -/** - * WOTS key generation. Takes a 32 byte sk_seed, expands it to WOTS private key - * elements and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_wots_gen_pk(unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *state_seeded) { - uint32_t i; - unsigned int j; - - uint32_t addrx4[4 * 8]; - unsigned char pkbuf[4 * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N]; - - for (j = 0; j < 4; j++) { - memcpy(addrx4 + j * 8, addr, sizeof(uint32_t) * 8); - } - - /* The last iteration typically does not have complete set of 4 chains, - but because we use pkbuf, this is not an issue -- we still do as many - in parallel as possible. */ - for (i = 0; i < ((PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_WOTS_LEN + 3) & ~0x3); i += 4) { - for (j = 0; j < 4; j++) { - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_set_chain_addr(addrx4 + j * 8, i + j); - } - wots_gen_skx4(pkbuf, sk_seed, addrx4, state_seeded); - gen_chainx4(pkbuf, pkbuf, 0, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_WOTS_W - 1, pub_seed, addrx4, state_seeded); - for (j = 0; j < 4; j++) { - if (i + j < PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_WOTS_LEN) { - memcpy(pk + (i + j)*PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N, pkbuf + j * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N); - } - } - } - - // Get rid of unused argument variable. - (void)state_seeded; -} - -/** - * Takes a n-byte message and the 32-byte sk_see to compute a signature 'sig'. - */ -void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_wots_sign(unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_WOTS_LEN; i++) { - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_set_chain_addr(addr, i); - wots_gen_sk(sig + i * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N, sk_seed, addr, state_seeded); - gen_chain(sig + i * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N, sig + i * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N, 0, lengths[i], pub_seed, addr, state_seeded); - } - - // avoid unused argument - (void)state_seeded; -} - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_WOTS_LEN; i++) { - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_set_chain_addr(addr, i); - gen_chain(pk + i * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N, sig + i * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_N, - lengths[i], PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_WOTS_W - 1 - lengths[i], pub_seed, addr, - state_seeded); - } - - // avoid unused argument - (void)state_seeded; -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_avx2/wots.h b/src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_avx2/wots.h deleted file mode 100644 index 8761e45ae1..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_avx2/wots.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_WOTS_H -#define PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_WOTS_H - -#include "hash_state.h" -#include "params.h" -#include - -/** - * WOTS key generation. Takes a 32 byte seed for the private key, expands it to - * a full WOTS private key and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_wots_gen_pk( - unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -/** - * Takes a n-byte message and the 32-byte seed for the private key to compute a - * signature that is placed at 'sig'. - */ -void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_wots_sign( - unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *hash_state_seeded); - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_wots_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_clean/LICENSE b/src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_clean/LICENSE deleted file mode 100644 index 670154e353..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_clean/LICENSE +++ /dev/null @@ -1,116 +0,0 @@ -CC0 1.0 Universal - -Statement of Purpose - -The laws of most jurisdictions throughout the world automatically confer -exclusive Copyright and Related Rights (defined below) upon the creator and -subsequent owner(s) (each and all, an "owner") of an original work of -authorship and/or a database (each, a "Work"). - -Certain owners wish to permanently relinquish those rights to a Work for the -purpose of contributing to a commons of creative, cultural and scientific -works ("Commons") that the public can reliably and without fear of later -claims of infringement build upon, modify, incorporate in other works, reuse -and redistribute as freely as possible in any form whatsoever and for any -purposes, including without limitation commercial purposes. These owners may -contribute to the Commons to promote the ideal of a free culture and the -further production of creative, cultural and scientific works, or to gain -reputation or greater distribution for their Work in part through the use and -efforts of others. - -For these and/or other purposes and motivations, and without any expectation -of additional consideration or compensation, the person associating CC0 with a -Work (the "Affirmer"), to the extent that he or she is an owner of Copyright -and Related Rights in the Work, voluntarily elects to apply CC0 to the Work -and publicly distribute the Work under its terms, with knowledge of his or her -Copyright and Related Rights in the Work and the meaning and intended legal -effect of CC0 on those rights. - -1. Copyright and Related Rights. A Work made available under CC0 may be -protected by copyright and related or neighboring rights ("Copyright and -Related Rights"). Copyright and Related Rights include, but are not limited -to, the following: - - i. the right to reproduce, adapt, distribute, perform, display, communicate, - and translate a Work; - - ii. moral rights retained by the original author(s) and/or performer(s); - - iii. publicity and privacy rights pertaining to a person's image or likeness - depicted in a Work; - - iv. rights protecting against unfair competition in regards to a Work, - subject to the limitations in paragraph 4(a), below; - - v. rights protecting the extraction, dissemination, use and reuse of data in - a Work; - - vi. database rights (such as those arising under Directive 96/9/EC of the - European Parliament and of the Council of 11 March 1996 on the legal - protection of databases, and under any national implementation thereof, - including any amended or successor version of such directive); and - - vii. other similar, equivalent or corresponding rights throughout the world - based on applicable law or treaty, and any national implementations thereof. - -2. Waiver. To the greatest extent permitted by, but not in contravention of, -applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and -unconditionally waives, abandons, and surrenders all of Affirmer's Copyright -and Related Rights and associated claims and causes of action, whether now -known or unknown (including existing as well as future claims and causes of -action), in the Work (i) in all territories worldwide, (ii) for the maximum -duration provided by applicable law or treaty (including future time -extensions), (iii) in any current or future medium and for any number of -copies, and (iv) for any purpose whatsoever, including without limitation -commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes -the Waiver for the benefit of each member of the public at large and to the -detriment of Affirmer's heirs and successors, fully intending that such Waiver -shall not be subject to revocation, rescission, cancellation, termination, or -any other legal or equitable action to disrupt the quiet enjoyment of the Work -by the public as contemplated by Affirmer's express Statement of Purpose. - -3. Public License Fallback. Should any part of the Waiver for any reason be -judged legally invalid or ineffective under applicable law, then the Waiver -shall be preserved to the maximum extent permitted taking into account -Affirmer's express Statement of Purpose. In addition, to the extent the Waiver -is so judged Affirmer hereby grants to each affected person a royalty-free, -non transferable, non sublicensable, non exclusive, irrevocable and -unconditional license to exercise Affirmer's Copyright and Related Rights in -the Work (i) in all territories worldwide, (ii) for the maximum duration -provided by applicable law or treaty (including future time extensions), (iii) -in any current or future medium and for any number of copies, and (iv) for any -purpose whatsoever, including without limitation commercial, advertising or -promotional purposes (the "License"). The License shall be deemed effective as -of the date CC0 was applied by Affirmer to the Work. Should any part of the -License for any reason be judged legally invalid or ineffective under -applicable law, such partial invalidity or ineffectiveness shall not -invalidate the remainder of the License, and in such case Affirmer hereby -affirms that he or she will not (i) exercise any of his or her remaining -Copyright and Related Rights in the Work or (ii) assert any associated claims -and causes of action with respect to the Work, in either case contrary to -Affirmer's express Statement of Purpose. - -4. Limitations and Disclaimers. - - a. No trademark or patent rights held by Affirmer are waived, abandoned, - surrendered, licensed or otherwise affected by this document. - - b. Affirmer offers the Work as-is and makes no representations or warranties - of any kind concerning the Work, express, implied, statutory or otherwise, - including without limitation warranties of title, merchantability, fitness - for a particular purpose, non infringement, or the absence of latent or - other defects, accuracy, or the present or absence of errors, whether or not - discoverable, all to the greatest extent permissible under applicable law. - - c. Affirmer disclaims responsibility for clearing rights of other persons - that may apply to the Work or any use thereof, including without limitation - any person's Copyright and Related Rights in the Work. Further, Affirmer - disclaims responsibility for obtaining any necessary consents, permissions - or other rights required for any use of the Work. - - d. Affirmer understands and acknowledges that Creative Commons is not a - party to this document and has no duty or obligation with respect to this - CC0 or use of the Work. - -For more information, please see - diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_clean/address.c b/src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_clean/address.c deleted file mode 100644 index dd01f401eb..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_clean/address.c +++ /dev/null @@ -1,78 +0,0 @@ -#include - -#include "address.h" -#include "params.h" -#include "utils.h" - -void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]) { - int i; - - for (i = 0; i < 8; i++) { - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_ull_to_bytes( - bytes + i * 4, 4, addr[i]); - } -} - -void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_set_layer_addr( - uint32_t addr[8], uint32_t layer) { - addr[0] = layer; -} - -void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_set_tree_addr( - uint32_t addr[8], uint64_t tree) { - addr[1] = 0; - addr[2] = (uint32_t) (tree >> 32); - addr[3] = (uint32_t) tree; -} - -void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_set_type( - uint32_t addr[8], uint32_t type) { - addr[4] = type; -} - -void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; -} - -/* These functions are used for OTS addresses. */ - -void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_set_keypair_addr( - uint32_t addr[8], uint32_t keypair) { - addr[5] = keypair; -} - -void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; - out[5] = in[5]; -} - -void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_set_chain_addr( - uint32_t addr[8], uint32_t chain) { - addr[6] = chain; -} - -void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_set_hash_addr( - uint32_t addr[8], uint32_t hash) { - addr[7] = hash; -} - -/* These functions are used for all hash tree addresses (including FORS). */ - -void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_set_tree_height( - uint32_t addr[8], uint32_t tree_height) { - addr[6] = tree_height; -} - -void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_set_tree_index( - uint32_t addr[8], uint32_t tree_index) { - addr[7] = tree_index; -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_clean/address.h b/src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_clean/address.h deleted file mode 100644 index b756efb733..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_clean/address.h +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_ADDRESS_H -#define PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_ADDRESS_H - -#include - -#define PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_ADDR_TYPE_WOTS 0 -#define PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_ADDR_TYPE_WOTSPK 1 -#define PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_ADDR_TYPE_HASHTREE 2 -#define PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_ADDR_TYPE_FORSTREE 3 -#define PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_ADDR_TYPE_FORSPK 4 - -void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]); - -void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_set_layer_addr( - uint32_t addr[8], uint32_t layer); - -void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_set_tree_addr( - uint32_t addr[8], uint64_t tree); - -void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_set_type( - uint32_t addr[8], uint32_t type); - -/* Copies the layer and tree part of one address into the other */ -void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for WOTS and FORS addresses. */ - -void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_set_keypair_addr( - uint32_t addr[8], uint32_t keypair); - -void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_set_chain_addr( - uint32_t addr[8], uint32_t chain); - -void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_set_hash_addr( - uint32_t addr[8], uint32_t hash); - -void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for all hash tree addresses (including FORS). */ - -void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_set_tree_height( - uint32_t addr[8], uint32_t tree_height); - -void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_set_tree_index( - uint32_t addr[8], uint32_t tree_index); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_clean/api.h b/src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_clean/api.h deleted file mode 100644 index 512bd9a067..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_clean/api.h +++ /dev/null @@ -1,81 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_API_H -#define PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_API_H - -#include -#include - - - -#define PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_CRYPTO_ALGNAME "SPHINCS+" - -#define PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_CRYPTO_SECRETKEYBYTES 64 -#define PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_CRYPTO_PUBLICKEYBYTES 32 -#define PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_CRYPTO_BYTES 17088 -#define PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_CRYPTO_SEEDBYTES 48 - - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_clean/fors.c b/src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_clean/fors.c deleted file mode 100644 index e7ccfffa96..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_clean/fors.c +++ /dev/null @@ -1,161 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "fors.h" -#include "hash.h" -#include "hash_state.h" -#include "thash.h" -#include "utils.h" - -static void fors_gen_sk(unsigned char *sk, const unsigned char *sk_seed, - uint32_t fors_leaf_addr[8], const hash_state *hash_state_seeded) { - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_prf_addr( - sk, sk_seed, fors_leaf_addr, hash_state_seeded); -} - -static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, - const unsigned char *pub_seed, - uint32_t fors_leaf_addr[8], - const hash_state *hash_state_seeded) { - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_thash_1( - leaf, sk, pub_seed, fors_leaf_addr, hash_state_seeded); -} - -static void fors_gen_leaf(unsigned char *leaf, const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx, const uint32_t fors_tree_addr[8], - const hash_state *hash_state_seeded) { - uint32_t fors_leaf_addr[8] = {0}; - - /* Only copy the parts that must be kept in fors_leaf_addr. */ - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_copy_keypair_addr( - fors_leaf_addr, fors_tree_addr); - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_set_type( - fors_leaf_addr, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_set_tree_index( - fors_leaf_addr, addr_idx); - - fors_gen_sk(leaf, sk_seed, fors_leaf_addr, hash_state_seeded); - fors_sk_to_leaf(leaf, leaf, pub_seed, fors_leaf_addr, hash_state_seeded); -} - -/** - * Interprets m as PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_FORS_HEIGHT-bit unsigned integers. - * Assumes m contains at least PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_FORS_TREES bits. - * Assumes indices has space for PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_FORS_TREES integers. - */ -static void message_to_indices(uint32_t *indices, const unsigned char *m) { - unsigned int i, j; - unsigned int offset = 0; - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_FORS_TREES; i++) { - indices[i] = 0; - for (j = 0; j < PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_FORS_HEIGHT; j++) { - indices[i] ^= (((uint32_t)m[offset >> 3] >> (offset & 0x7)) & 0x1) << j; - offset++; - } - } -} - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_fors_sign( - unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *hash_state_seeded) { - uint32_t indices[PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_FORS_TREES]; - unsigned char roots[PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_FORS_TREES * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_N]; - uint32_t fors_tree_addr[8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_copy_keypair_addr( - fors_tree_addr, fors_addr); - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_copy_keypair_addr( - fors_pk_addr, fors_addr); - - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_set_type( - fors_tree_addr, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_set_type( - fors_pk_addr, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_FORS_TREES; i++) { - idx_offset = i * (1 << PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_FORS_HEIGHT); - - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_set_tree_height( - fors_tree_addr, 0); - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_set_tree_index( - fors_tree_addr, indices[i] + idx_offset); - - /* Include the secret key part that produces the selected leaf node. */ - fors_gen_sk(sig, sk_seed, fors_tree_addr, hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_N; - - /* Compute the authentication path for this leaf node. */ - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_treehash_FORS_HEIGHT( - roots + i * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_N, sig, sk_seed, pub_seed, - indices[i], idx_offset, fors_gen_leaf, fors_tree_addr, - hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_N * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_thash_FORS_TREES( - pk, roots, pub_seed, fors_pk_addr, hash_state_seeded); -} - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_fors_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, const uint32_t fors_addr[8], - const hash_state *hash_state_seeded) { - uint32_t indices[PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_FORS_TREES]; - unsigned char roots[PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_FORS_TREES * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_N]; - unsigned char leaf[PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_N]; - uint32_t fors_tree_addr[8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_copy_keypair_addr(fors_tree_addr, fors_addr); - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_copy_keypair_addr(fors_pk_addr, fors_addr); - - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_set_type(fors_tree_addr, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_set_type(fors_pk_addr, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_FORS_TREES; i++) { - idx_offset = i * (1 << PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_FORS_HEIGHT); - - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_set_tree_height(fors_tree_addr, 0); - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Derive the leaf from the included secret key part. */ - fors_sk_to_leaf(leaf, sig, pub_seed, fors_tree_addr, hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_N; - - /* Derive the corresponding root node of this tree. */ - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_compute_root(roots + i * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_N, leaf, indices[i], idx_offset, sig, - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_FORS_HEIGHT, pub_seed, fors_tree_addr, hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_N * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_thash_FORS_TREES(pk, roots, pub_seed, fors_pk_addr, hash_state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_clean/fors.h b/src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_clean/fors.h deleted file mode 100644 index cd1385196e..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_clean/fors.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_FORS_H -#define PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_FORS_H - -#include - -#include "hash_state.h" -#include "params.h" - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_fors_sign( - unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *hash_state_seeded); - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_fors_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, const uint32_t fors_addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_clean/hash.h b/src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_clean/hash.h deleted file mode 100644 index 79751b2c50..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_clean/hash.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_HASH_H -#define PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_HASH_H - -#include "hash_state.h" - -#include -#include - -void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_initialize_hash_function( - hash_state *hash_state_seeded, - const unsigned char *pub_seed, const unsigned char *sk_seed); - -void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_destroy_hash_function(hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_clean/hash_shake256.c b/src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_clean/hash_shake256.c deleted file mode 100644 index 1719f18a50..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_clean/hash_shake256.c +++ /dev/null @@ -1,106 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "utils.h" - -#include "fips202.h" - -/* For SHAKE256, there is no immediate reason to initialize at the start, - so this function is an empty operation. */ -void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_initialize_hash_function( - hash_state *hash_state_seeded, // NOLINT(readability-non-const-parameter) - const unsigned char *pub_seed, const unsigned char *sk_seed) { - (void)hash_state_seeded; /* Suppress an 'unused parameter' warning. */ - (void)pub_seed; /* Suppress an 'unused parameter' warning. */ - (void)sk_seed; /* Suppress an 'unused parameter' warning. */ -} - -/* This is not necessary for SHAKE256, so we don't do anything */ -void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_destroy_hash_function( - hash_state *hash_state_seeded) { // NOLINT(readability-non-const-parameter) - (void)hash_state_seeded; -} - -/* - * Computes PRF(key, addr), given a secret key of PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_N bytes and an address - */ -void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded) { - unsigned char buf[PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_N + PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_ADDR_BYTES]; - - memcpy(buf, key, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_N); - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_addr_to_bytes(buf + PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_N, addr); - - shake256(out, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_N, buf, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_N + PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_ADDR_BYTES); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} - -/** - * Computes the message-dependent randomness R, using a secret seed and an - * optional randomization value as well as the message. - */ -void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded) { - shake256incctx state; - - shake256_inc_init(&state); - shake256_inc_absorb(&state, sk_prf, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_N); - shake256_inc_absorb(&state, optrand, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_N); - shake256_inc_absorb(&state, m, mlen); - shake256_inc_finalize(&state); - shake256_inc_squeeze(R, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_N, &state); - shake256_inc_ctx_release(&state); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} - -/** - * Computes the message hash using R, the public key, and the message. - * Outputs the message digest and the index of the leaf. The index is split in - * the tree index and the leaf index, for convenient copying to an address. - */ -void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded) { -#define PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_TREE_BITS (PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_TREE_HEIGHT * (PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_D - 1)) -#define PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_TREE_BYTES ((PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_TREE_BITS + 7) / 8) -#define PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_LEAF_BITS PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_TREE_HEIGHT -#define PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_LEAF_BYTES ((PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_LEAF_BITS + 7) / 8) -#define PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_DGST_BYTES (PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_FORS_MSG_BYTES + PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_TREE_BYTES + PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_LEAF_BYTES) - - unsigned char buf[PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_DGST_BYTES]; - unsigned char *bufp = buf; - shake256incctx state; - - shake256_inc_init(&state); - shake256_inc_absorb(&state, R, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_N); - shake256_inc_absorb(&state, pk, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_PK_BYTES); - shake256_inc_absorb(&state, m, mlen); - shake256_inc_finalize(&state); - shake256_inc_squeeze(buf, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_DGST_BYTES, &state); - shake256_inc_ctx_release(&state); - - memcpy(digest, bufp, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_FORS_MSG_BYTES); - bufp += PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_FORS_MSG_BYTES; - - *tree = PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_bytes_to_ull( - bufp, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_TREE_BYTES); - *tree &= (~(uint64_t)0) >> (64 - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_TREE_BITS); - bufp += PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_TREE_BYTES; - - *leaf_idx = (uint32_t)PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_bytes_to_ull( - bufp, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_LEAF_BYTES); - *leaf_idx &= (~(uint32_t)0) >> (32 - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_LEAF_BITS); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_clean/hash_state.h b/src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_clean/hash_state.h deleted file mode 100644 index 7d92ef872a..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_clean/hash_state.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef SPX_HASH_STATE_H -#define SPX_HASH_STATE_H - -/** - * Defines the type of the hash function state. - * - * Don't be fooled into thinking this instance of SPHINCS+ isn't stateless! - * - * From Section 7.2.2 from the SPHINCS+ round-2 specification: - * - * Each of the instances of the tweakable hash function take PK.seed as its - * first input, which is constant for a given key pair – and, thus, across - * a single signature. This leads to a lot of redundant computation. To remedy - * this, we pad PK.seed to the length of a full 64-byte SHA-256 input block. - * Because of the Merkle-DamgÃ¥rd construction that underlies SHA-256, this - * allows for reuse of the intermediate SHA-256 state after the initial call to - * the compression function which improves performance. - * - * We pass this hash state around in functions, because otherwise we need to - * have a global variable. - * - * SHAKE256 does not need this state. Because this implementation is generated - * from a shared code base, we still need to specify some hash_state as it is - * still passed around. We chose to use an `int` as a placeholder for this - * purpose. - */ - -#define hash_state int - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_clean/params.h b/src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_clean/params.h deleted file mode 100644 index 9f0030dd88..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_clean/params.h +++ /dev/null @@ -1,53 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_PARAMS_H -#define PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_PARAMS_H - -/* Hash output length in bytes. */ -#define PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_N 16 -/* Height of the hypertree. */ -#define PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_FULL_HEIGHT 66 -/* Number of subtree layer. */ -#define PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_D 22 -/* FORS tree dimensions. */ -#define PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_FORS_HEIGHT 6 -#define PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_FORS_TREES 33 -/* Winternitz parameter, */ -#define PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_WOTS_W 16 - -/* The hash function is defined by linking a different hash.c file, as opposed - to setting a #define constant. */ - -/* For clarity */ -#define PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_ADDR_BYTES 32 - -/* WOTS parameters. */ -#define PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_WOTS_LOGW 4 - -#define PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_WOTS_LEN1 (8 * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_N / PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_WOTS_LOGW) - -/* PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#define PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_WOTS_LEN2 3 - -#define PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_WOTS_LEN (PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_WOTS_LEN1 + PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_WOTS_LEN2) -#define PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_WOTS_BYTES (PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_WOTS_LEN * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_N) -#define PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_WOTS_PK_BYTES PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_WOTS_BYTES - -/* Subtree size. */ -#define PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_TREE_HEIGHT (PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_FULL_HEIGHT / PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_D) - -/* FORS parameters. */ -#define PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_FORS_MSG_BYTES ((PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_FORS_TREES + 7) / 8) -#define PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_FORS_BYTES ((PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_FORS_HEIGHT + 1) * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_FORS_TREES * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_N) -#define PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_FORS_PK_BYTES PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_N - -/* Resulting SPX sizes. */ -#define PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_BYTES (PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_N + PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_FORS_BYTES + PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_D * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_WOTS_BYTES +\ - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_FULL_HEIGHT * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_N) -#define PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_PK_BYTES (2 * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_N) -#define PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_SK_BYTES (2 * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_N + PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_PK_BYTES) - -/* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ -#define PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_OPTRAND_BYTES 32 - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_clean/sign.c b/src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_clean/sign.c deleted file mode 100644 index cdfae4bc66..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_clean/sign.c +++ /dev/null @@ -1,356 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "api.h" -#include "fors.h" -#include "hash.h" -#include "hash_state.h" -#include "params.h" -#include "randombytes.h" -#include "thash.h" -#include "utils.h" -#include "wots.h" - -/** - * Computes the leaf at a given address. First generates the WOTS key pair, - * then computes leaf by hashing horizontally. - */ -static void wots_gen_leaf(unsigned char *leaf, const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx, const uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - unsigned char pk[PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_WOTS_BYTES]; - uint32_t wots_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_set_type( - wots_addr, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_set_type( - wots_pk_addr, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_ADDR_TYPE_WOTSPK); - - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_set_keypair_addr( - wots_addr, addr_idx); - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_wots_gen_pk( - pk, sk_seed, pub_seed, wots_addr, hash_state_seeded); - - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_copy_keypair_addr( - wots_pk_addr, wots_addr); - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_thash_WOTS_LEN( - leaf, pk, pub_seed, wots_pk_addr, hash_state_seeded); -} - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_crypto_sign_secretkeybytes(void) { - return PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_CRYPTO_SECRETKEYBYTES; -} - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_crypto_sign_publickeybytes(void) { - return PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_CRYPTO_PUBLICKEYBYTES; -} - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_crypto_sign_bytes(void) { - return PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_CRYPTO_BYTES; -} - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_crypto_sign_seedbytes(void) { - return PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_CRYPTO_SEEDBYTES; -} - -/* - * Generates an SPX key pair given a seed of length - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed) { - /* We do not need the auth path in key generation, but it simplifies the - code to have just one treehash routine that computes both root and path - in one function. */ - unsigned char auth_path[PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_TREE_HEIGHT * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_N]; - uint32_t top_tree_addr[8] = {0}; - hash_state hash_state_seeded; - - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_set_layer_addr( - top_tree_addr, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_D - 1); - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_set_type( - top_tree_addr, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_ADDR_TYPE_HASHTREE); - - /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ - memcpy(sk, seed, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_CRYPTO_SEEDBYTES); - - memcpy(pk, sk + 2 * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_N, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_initialize_hash_function(&hash_state_seeded, pk, sk); - - /* Compute root node of the top-most subtree. */ - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_treehash_TREE_HEIGHT( - sk + 3 * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_N, auth_path, sk, sk + 2 * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_N, 0, 0, - wots_gen_leaf, top_tree_addr, &hash_state_seeded); - - memcpy(pk + PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_N, sk + 3 * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_N, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_N); - - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_destroy_hash_function(&hash_state_seeded); - return 0; -} - -/* - * Generates an SPX key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk) { - unsigned char seed[PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_CRYPTO_SEEDBYTES]; - randombytes(seed, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_CRYPTO_SEEDBYTES); - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_crypto_sign_seed_keypair( - pk, sk, seed); - - return 0; -} - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - const unsigned char *sk_seed = sk; - const unsigned char *sk_prf = sk + PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_N; - const unsigned char *pk = sk + 2 * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_N; - const unsigned char *pub_seed = pk; - - unsigned char optrand[PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_N]; - unsigned char mhash[PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_FORS_MSG_BYTES]; - unsigned char root[PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_N]; - uint32_t i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - - hash_state hash_state_seeded; - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_initialize_hash_function( - &hash_state_seeded, - pub_seed, sk_seed); - - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_set_type( - wots_addr, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_set_type( - tree_addr, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_ADDR_TYPE_HASHTREE); - - /* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ - randombytes(optrand, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_N); - /* Compute the digest randomization value. */ - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_gen_message_random( - sig, sk_prf, optrand, m, mlen, &hash_state_seeded); - - /* Derive the message digest and leaf index from R, PK and M. */ - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_N; - - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); - - /* Sign the message hash using FORS. */ - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_fors_sign( - sig, root, mhash, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_FORS_BYTES; - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_D; i++) { - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_set_tree_addr(tree_addr, tree); - - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); - - /* Compute a WOTS signature. */ - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_wots_sign( - sig, root, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_WOTS_BYTES; - - /* Compute the authentication path for the used WOTS leaf. */ - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_treehash_TREE_HEIGHT( - root, sig, sk_seed, pub_seed, idx_leaf, 0, - wots_gen_leaf, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_TREE_HEIGHT * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_TREE_HEIGHT; - } - - *siglen = PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_BYTES; - - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_destroy_hash_function(&hash_state_seeded); - return 0; -} - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk) { - const unsigned char *pub_seed = pk; - const unsigned char *pub_root = pk + PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_N; - unsigned char mhash[PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_FORS_MSG_BYTES]; - unsigned char wots_pk[PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_WOTS_BYTES]; - unsigned char root[PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_N]; - unsigned char leaf[PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_N]; - unsigned int i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - hash_state hash_state_seeded; - - if (siglen != PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_BYTES) { - return -1; - } - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_initialize_hash_function( - &hash_state_seeded, - pub_seed, NULL); - - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_set_type( - wots_addr, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_set_type( - tree_addr, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_ADDR_TYPE_HASHTREE); - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_set_type( - wots_pk_addr, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_ADDR_TYPE_WOTSPK); - - /* Derive the message digest and leaf index from R || PK || M. */ - /* The additional PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_N is a result of the hash domain separator. */ - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_N; - - /* Layer correctly defaults to 0, so no need to set_layer_addr */ - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); - - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_fors_pk_from_sig( - root, sig, mhash, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_FORS_BYTES; - - /* For each subtree.. */ - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_D; i++) { - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_set_tree_addr(tree_addr, tree); - - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); - - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_copy_keypair_addr( - wots_pk_addr, wots_addr); - - /* The WOTS public key is only correct if the signature was correct. */ - /* Initially, root is the FORS pk, but on subsequent iterations it is - the root of the subtree below the currently processed subtree. */ - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_wots_pk_from_sig( - wots_pk, sig, root, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_WOTS_BYTES; - - /* Compute the leaf node using the WOTS public key. */ - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_thash_WOTS_LEN( - leaf, wots_pk, pub_seed, wots_pk_addr, &hash_state_seeded); - - /* Compute the root node of this subtree. */ - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_compute_root( - root, leaf, idx_leaf, 0, sig, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_TREE_HEIGHT, - pub_seed, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_TREE_HEIGHT * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_TREE_HEIGHT; - } - - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_destroy_hash_function(&hash_state_seeded); - /* Check if the root node equals the root node in the public key. */ - if (memcmp(root, pub_root, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_N) != 0) { - return -1; - } - - return 0; -} - - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - size_t siglen; - - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_crypto_sign_signature( - sm, &siglen, m, mlen, sk); - - memmove(sm + PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_BYTES, m, mlen); - *smlen = siglen + mlen; - - return 0; -} - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk) { - /* The API caller does not necessarily know what size a signature should be - but SPHINCS+ signatures are always exactly PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_BYTES. */ - if (smlen < PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_BYTES) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - *mlen = smlen - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_BYTES; - - if (PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_crypto_sign_verify( - sm, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_BYTES, sm + PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_BYTES, *mlen, pk)) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - /* If verification was successful, move the message to the right place. */ - memmove(m, sm + PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_BYTES, *mlen); - - return 0; -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_clean/thash.h b/src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_clean/thash.h deleted file mode 100644 index 3e3f09c325..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_clean/thash.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_THASH_H -#define PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_THASH_H - -#include "hash_state.h" - -#include - -void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_clean/thash_shake256_simple.c b/src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_clean/thash_shake256_simple.c deleted file mode 100644 index 05e1c28523..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_clean/thash_shake256_simple.c +++ /dev/null @@ -1,74 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash_state.h" -#include "params.h" -#include "thash.h" - -#include "fips202.h" - -/** - * Takes an array of inblocks concatenated arrays of PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_N bytes. - */ -static void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_thash( - unsigned char *out, unsigned char *buf, - const unsigned char *in, unsigned int inblocks, - const unsigned char *pub_seed, uint32_t addr[8]) { - - memcpy(buf, pub_seed, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_N); - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_addr_to_bytes(buf + PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_N, addr); - memcpy(buf + PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_N + PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_ADDR_BYTES, in, inblocks * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_N); - - shake256(out, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_N, buf, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_N + PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_N); -} - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_N + PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_ADDR_BYTES + 1 * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_N]; - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_thash( - out, buf, in, 1, pub_seed, addr); - - (void)hash_state_seeded; /* Avoid unused parameter warning. */ -} - -void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_N + PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_ADDR_BYTES + 2 * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_N]; - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_thash( - out, buf, in, 2, pub_seed, addr); - - (void)hash_state_seeded; /* Avoid unused parameter warning. */ -} - -void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_N + PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_ADDR_BYTES + PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_WOTS_LEN * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_N]; - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_thash( - out, buf, in, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_WOTS_LEN, pub_seed, addr); - - (void)hash_state_seeded; /* Avoid unused parameter warning. */ -} - -void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_N + PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_ADDR_BYTES + PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_FORS_TREES * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_N]; - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_thash( - out, buf, in, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_FORS_TREES, pub_seed, addr); - - (void)hash_state_seeded; /* Avoid unused parameter warning. */ -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_clean/utils.c b/src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_clean/utils.c deleted file mode 100644 index 1005cf97bf..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_clean/utils.c +++ /dev/null @@ -1,199 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "hash_state.h" -#include "params.h" -#include "thash.h" -#include "utils.h" - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in) { - - /* Iterate over out in decreasing order, for big-endianness. */ - for (size_t i = outlen; i > 0; i--) { - out[i - 1] = in & 0xff; - in = in >> 8; - } -} - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_bytes_to_ull( - const unsigned char *in, size_t inlen) { - unsigned long long retval = 0; - - for (size_t i = 0; i < inlen; i++) { - retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); - } - return retval; -} - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - uint32_t i; - unsigned char buffer[2 * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_N]; - - /* If leaf_idx is odd (last bit = 1), current path element is a right child - and auth_path has to go left. Otherwise it is the other way around. */ - if (leaf_idx & 1) { - memcpy(buffer + PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_N, leaf, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_N); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_N); - } else { - memcpy(buffer, leaf, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_N); - memcpy(buffer + PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_N, auth_path, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_N); - } - auth_path += PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_N; - - for (i = 0; i < tree_height - 1; i++) { - leaf_idx >>= 1; - idx_offset >>= 1; - /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_set_tree_height(addr, i + 1); - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_set_tree_index( - addr, leaf_idx + idx_offset); - - /* Pick the right or left neighbor, depending on parity of the node. */ - if (leaf_idx & 1) { - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_thash_2( - buffer + PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_N, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_N); - } else { - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_thash_2( - buffer, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer + PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_N, auth_path, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_N); - } - auth_path += PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_N; - } - - /* The last iteration is exceptional; we do not copy an auth_path node. */ - leaf_idx >>= 1; - idx_offset >>= 1; - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_set_tree_height(addr, tree_height); - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_set_tree_index( - addr, leaf_idx + idx_offset); - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_thash_2( - root, buffer, pub_seed, addr, hash_state_seeded); -} - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -static void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_treehash( - unsigned char *root, unsigned char *auth_path, - unsigned char *stack, unsigned int *heights, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - - unsigned int offset = 0; - uint32_t idx; - uint32_t tree_idx; - - for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { - /* Add the next leaf node to the stack. */ - gen_leaf(stack + offset * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_N, - sk_seed, pub_seed, idx + idx_offset, tree_addr, - hash_state_seeded); - offset++; - heights[offset - 1] = 0; - - /* If this is a node we need for the auth path.. */ - if ((leaf_idx ^ 0x1) == idx) { - memcpy(auth_path, stack + (offset - 1)*PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_N, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_N); - } - - /* While the top-most nodes are of equal height.. */ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { - /* Compute index of the new node, in the next layer. */ - tree_idx = (idx >> (heights[offset - 1] + 1)); - - /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_set_tree_height( - tree_addr, heights[offset - 1] + 1); - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_set_tree_index( - tree_addr, tree_idx + (idx_offset >> (heights[offset - 1] + 1))); - /* Hash the top-most nodes from the stack together. */ - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_thash_2( - stack + (offset - 2)*PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_N, stack + (offset - 2)*PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_N, - pub_seed, tree_addr, hash_state_seeded); - offset--; - /* Note that the top-most node is now one layer higher. */ - heights[offset - 1]++; - - /* If this is a node we need for the auth path.. */ - if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_path + heights[offset - 1]*PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_N, - stack + (offset - 1)*PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_N, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_N); - } - } - } - memcpy(root, stack, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_N); -} - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_FORS_HEIGHT + 1)*PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_N]; - unsigned int heights[PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_FORS_HEIGHT + 1]; - - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_FORS_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_TREE_HEIGHT + 1)*PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_N]; - unsigned int heights[PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_TREE_HEIGHT + 1]; - - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_TREE_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_clean/utils.h b/src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_clean/utils.h deleted file mode 100644 index a1385f6b01..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_clean/utils.h +++ /dev/null @@ -1,64 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_UTILS_H -#define PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_UTILS_H - -#include "hash_state.h" -#include "params.h" -#include -#include - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in); - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_bytes_to_ull( - const unsigned char *in, size_t inlen); - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_clean/wots.c b/src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_clean/wots.c deleted file mode 100644 index 913fe9bc2a..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_clean/wots.c +++ /dev/null @@ -1,167 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "hash_state.h" -#include "params.h" -#include "thash.h" -#include "utils.h" -#include "wots.h" - -// TODO clarify address expectations, and make them more uniform. -// TODO i.e. do we expect types to be set already? -// TODO and do we expect modifications or copies? - -/** - * Computes the starting value for a chain, i.e. the secret key. - * Expects the address to be complete up to the chain address. - */ -static void wots_gen_sk(unsigned char *sk, const unsigned char *sk_seed, - uint32_t wots_addr[8], - const hash_state *hash_state_seeded) { - /* Make sure that the hash address is actually zeroed. */ - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_set_hash_addr(wots_addr, 0); - - /* Generate sk element. */ - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_prf_addr(sk, sk_seed, wots_addr, hash_state_seeded); -} - -/** - * Computes the chaining function. - * out and in have to be n-byte arrays. - * - * Interprets in as start-th value of the chain. - * addr has to contain the address of the chain. - */ -static void gen_chain(unsigned char *out, const unsigned char *in, - unsigned int start, unsigned int steps, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - uint32_t i; - - /* Initialize out with the value at position 'start'. */ - memcpy(out, in, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_N); - - /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_WOTS_W; i++) { - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_set_hash_addr(addr, i); - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_thash_1( - out, out, pub_seed, addr, hash_state_seeded); - } -} - -/** - * base_w algorithm as described in draft. - * Interprets an array of bytes as integers in base w. - * This only works when log_w is a divisor of 8. - */ -static void base_w(unsigned int *output, const size_t out_len, - const unsigned char *input) { - size_t in = 0; - size_t out = 0; - unsigned char total = 0; - unsigned int bits = 0; - size_t consumed; - - for (consumed = 0; consumed < out_len; consumed++) { - if (bits == 0) { - total = input[in]; - in++; - bits += 8; - } - bits -= PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_WOTS_LOGW; - output[out] = (unsigned int)((total >> bits) & (PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_WOTS_W - 1)); - out++; - } -} - -/* Computes the WOTS+ checksum over a message (in base_w). */ -static void wots_checksum(unsigned int *csum_base_w, - const unsigned int *msg_base_w) { - unsigned int csum = 0; - unsigned char csum_bytes[(PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_WOTS_LEN2 * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_WOTS_LOGW + 7) / 8]; - unsigned int i; - - /* Compute checksum. */ - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_WOTS_LEN1; i++) { - csum += PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_WOTS_W - 1 - msg_base_w[i]; - } - - /* Convert checksum to base_w. */ - /* Make sure expected empty zero bits are the least significant bits. */ - csum = csum << (8 - ((PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_WOTS_LEN2 * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_WOTS_LOGW) % 8)); - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_ull_to_bytes( - csum_bytes, sizeof(csum_bytes), csum); - base_w(csum_base_w, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_WOTS_LEN2, csum_bytes); -} - -/* Takes a message and derives the matching chain lengths. */ -static void chain_lengths(unsigned int *lengths, const unsigned char *msg) { - base_w(lengths, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_WOTS_LEN1, msg); - wots_checksum(lengths + PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_WOTS_LEN1, lengths); -} - -/** - * WOTS key generation. Takes a 32 byte sk_seed, expands it to WOTS private key - * elements and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_wots_gen_pk( - unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - uint32_t i; - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_WOTS_LEN; i++) { - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_set_chain_addr(addr, i); - wots_gen_sk(pk + i * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_N, sk_seed, addr, hash_state_seeded); - gen_chain(pk + i * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_N, pk + i * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_N, - 0, PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_WOTS_W - 1, pub_seed, addr, hash_state_seeded); - } -} - -/** - * Takes a n-byte message and the 32-byte sk_see to compute a signature 'sig'. - */ -void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_wots_sign( - unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *hash_state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_WOTS_LEN; i++) { - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_set_chain_addr(addr, i); - wots_gen_sk(sig + i * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_N, sk_seed, addr, hash_state_seeded); - gen_chain(sig + i * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_N, sig + i * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_N, 0, lengths[i], pub_seed, addr, hash_state_seeded); - } -} - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_wots_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_WOTS_LEN; i++) { - PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_set_chain_addr(addr, i); - gen_chain(pk + i * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_N, sig + i * PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_N, - lengths[i], PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_WOTS_W - 1 - lengths[i], pub_seed, addr, - hash_state_seeded); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_clean/wots.h b/src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_clean/wots.h deleted file mode 100644 index a6b25fc6f7..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128f-simple_clean/wots.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_WOTS_H -#define PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_WOTS_H - -#include "hash_state.h" -#include "params.h" -#include - -/** - * WOTS key generation. Takes a 32 byte seed for the private key, expands it to - * a full WOTS private key and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_wots_gen_pk( - unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -/** - * Takes a n-byte message and the 32-byte seed for the private key to compute a - * signature that is placed at 'sig'. - */ -void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_wots_sign( - unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *hash_state_seeded); - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_wots_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_avx2/LICENSE b/src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_avx2/LICENSE deleted file mode 100644 index 670154e353..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_avx2/LICENSE +++ /dev/null @@ -1,116 +0,0 @@ -CC0 1.0 Universal - -Statement of Purpose - -The laws of most jurisdictions throughout the world automatically confer -exclusive Copyright and Related Rights (defined below) upon the creator and -subsequent owner(s) (each and all, an "owner") of an original work of -authorship and/or a database (each, a "Work"). - -Certain owners wish to permanently relinquish those rights to a Work for the -purpose of contributing to a commons of creative, cultural and scientific -works ("Commons") that the public can reliably and without fear of later -claims of infringement build upon, modify, incorporate in other works, reuse -and redistribute as freely as possible in any form whatsoever and for any -purposes, including without limitation commercial purposes. These owners may -contribute to the Commons to promote the ideal of a free culture and the -further production of creative, cultural and scientific works, or to gain -reputation or greater distribution for their Work in part through the use and -efforts of others. - -For these and/or other purposes and motivations, and without any expectation -of additional consideration or compensation, the person associating CC0 with a -Work (the "Affirmer"), to the extent that he or she is an owner of Copyright -and Related Rights in the Work, voluntarily elects to apply CC0 to the Work -and publicly distribute the Work under its terms, with knowledge of his or her -Copyright and Related Rights in the Work and the meaning and intended legal -effect of CC0 on those rights. - -1. Copyright and Related Rights. A Work made available under CC0 may be -protected by copyright and related or neighboring rights ("Copyright and -Related Rights"). Copyright and Related Rights include, but are not limited -to, the following: - - i. the right to reproduce, adapt, distribute, perform, display, communicate, - and translate a Work; - - ii. moral rights retained by the original author(s) and/or performer(s); - - iii. publicity and privacy rights pertaining to a person's image or likeness - depicted in a Work; - - iv. rights protecting against unfair competition in regards to a Work, - subject to the limitations in paragraph 4(a), below; - - v. rights protecting the extraction, dissemination, use and reuse of data in - a Work; - - vi. database rights (such as those arising under Directive 96/9/EC of the - European Parliament and of the Council of 11 March 1996 on the legal - protection of databases, and under any national implementation thereof, - including any amended or successor version of such directive); and - - vii. other similar, equivalent or corresponding rights throughout the world - based on applicable law or treaty, and any national implementations thereof. - -2. Waiver. To the greatest extent permitted by, but not in contravention of, -applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and -unconditionally waives, abandons, and surrenders all of Affirmer's Copyright -and Related Rights and associated claims and causes of action, whether now -known or unknown (including existing as well as future claims and causes of -action), in the Work (i) in all territories worldwide, (ii) for the maximum -duration provided by applicable law or treaty (including future time -extensions), (iii) in any current or future medium and for any number of -copies, and (iv) for any purpose whatsoever, including without limitation -commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes -the Waiver for the benefit of each member of the public at large and to the -detriment of Affirmer's heirs and successors, fully intending that such Waiver -shall not be subject to revocation, rescission, cancellation, termination, or -any other legal or equitable action to disrupt the quiet enjoyment of the Work -by the public as contemplated by Affirmer's express Statement of Purpose. - -3. Public License Fallback. Should any part of the Waiver for any reason be -judged legally invalid or ineffective under applicable law, then the Waiver -shall be preserved to the maximum extent permitted taking into account -Affirmer's express Statement of Purpose. In addition, to the extent the Waiver -is so judged Affirmer hereby grants to each affected person a royalty-free, -non transferable, non sublicensable, non exclusive, irrevocable and -unconditional license to exercise Affirmer's Copyright and Related Rights in -the Work (i) in all territories worldwide, (ii) for the maximum duration -provided by applicable law or treaty (including future time extensions), (iii) -in any current or future medium and for any number of copies, and (iv) for any -purpose whatsoever, including without limitation commercial, advertising or -promotional purposes (the "License"). The License shall be deemed effective as -of the date CC0 was applied by Affirmer to the Work. Should any part of the -License for any reason be judged legally invalid or ineffective under -applicable law, such partial invalidity or ineffectiveness shall not -invalidate the remainder of the License, and in such case Affirmer hereby -affirms that he or she will not (i) exercise any of his or her remaining -Copyright and Related Rights in the Work or (ii) assert any associated claims -and causes of action with respect to the Work, in either case contrary to -Affirmer's express Statement of Purpose. - -4. Limitations and Disclaimers. - - a. No trademark or patent rights held by Affirmer are waived, abandoned, - surrendered, licensed or otherwise affected by this document. - - b. Affirmer offers the Work as-is and makes no representations or warranties - of any kind concerning the Work, express, implied, statutory or otherwise, - including without limitation warranties of title, merchantability, fitness - for a particular purpose, non infringement, or the absence of latent or - other defects, accuracy, or the present or absence of errors, whether or not - discoverable, all to the greatest extent permissible under applicable law. - - c. Affirmer disclaims responsibility for clearing rights of other persons - that may apply to the Work or any use thereof, including without limitation - any person's Copyright and Related Rights in the Work. Further, Affirmer - disclaims responsibility for obtaining any necessary consents, permissions - or other rights required for any use of the Work. - - d. Affirmer understands and acknowledges that Creative Commons is not a - party to this document and has no duty or obligation with respect to this - CC0 or use of the Work. - -For more information, please see - diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_avx2/address.c b/src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_avx2/address.c deleted file mode 100644 index 64330da45c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_avx2/address.c +++ /dev/null @@ -1,78 +0,0 @@ -#include - -#include "address.h" -#include "params.h" -#include "utils.h" - -void PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]) { - int i; - - for (i = 0; i < 8; i++) { - PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_ull_to_bytes( - bytes + i * 4, 4, addr[i]); - } -} - -void PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_set_layer_addr( - uint32_t addr[8], uint32_t layer) { - addr[0] = layer; -} - -void PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_set_tree_addr( - uint32_t addr[8], uint64_t tree) { - addr[1] = 0; - addr[2] = (uint32_t) (tree >> 32); - addr[3] = (uint32_t) tree; -} - -void PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_set_type( - uint32_t addr[8], uint32_t type) { - addr[4] = type; -} - -void PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; -} - -/* These functions are used for OTS addresses. */ - -void PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_set_keypair_addr( - uint32_t addr[8], uint32_t keypair) { - addr[5] = keypair; -} - -void PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; - out[5] = in[5]; -} - -void PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_set_chain_addr( - uint32_t addr[8], uint32_t chain) { - addr[6] = chain; -} - -void PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_set_hash_addr( - uint32_t addr[8], uint32_t hash) { - addr[7] = hash; -} - -/* These functions are used for all hash tree addresses (including FORS). */ - -void PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_set_tree_height( - uint32_t addr[8], uint32_t tree_height) { - addr[6] = tree_height; -} - -void PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_set_tree_index( - uint32_t addr[8], uint32_t tree_index) { - addr[7] = tree_index; -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_avx2/address.h b/src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_avx2/address.h deleted file mode 100644 index 9e1da219f8..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_avx2/address.h +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_ADDRESS_H -#define PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_ADDRESS_H - -#include - -#define PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_ADDR_TYPE_WOTS 0 -#define PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_ADDR_TYPE_WOTSPK 1 -#define PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_ADDR_TYPE_HASHTREE 2 -#define PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_ADDR_TYPE_FORSTREE 3 -#define PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_ADDR_TYPE_FORSPK 4 - -void PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]); - -void PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_set_layer_addr( - uint32_t addr[8], uint32_t layer); - -void PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_set_tree_addr( - uint32_t addr[8], uint64_t tree); - -void PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_set_type( - uint32_t addr[8], uint32_t type); - -/* Copies the layer and tree part of one address into the other */ -void PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for WOTS and FORS addresses. */ - -void PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_set_keypair_addr( - uint32_t addr[8], uint32_t keypair); - -void PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_set_chain_addr( - uint32_t addr[8], uint32_t chain); - -void PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_set_hash_addr( - uint32_t addr[8], uint32_t hash); - -void PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for all hash tree addresses (including FORS). */ - -void PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_set_tree_height( - uint32_t addr[8], uint32_t tree_height); - -void PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_set_tree_index( - uint32_t addr[8], uint32_t tree_index); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_avx2/api.h b/src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_avx2/api.h deleted file mode 100644 index 3a38ae160d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_avx2/api.h +++ /dev/null @@ -1,81 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_API_H -#define PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_API_H - -#include -#include - - - -#define PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_CRYPTO_ALGNAME "SPHINCS+" - -#define PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_CRYPTO_SECRETKEYBYTES 64 -#define PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_CRYPTO_PUBLICKEYBYTES 32 -#define PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_CRYPTO_BYTES 7856 -#define PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_CRYPTO_SEEDBYTES 48 - - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_avx2/fors.c b/src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_avx2/fors.c deleted file mode 100644 index f85808875b..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_avx2/fors.c +++ /dev/null @@ -1,206 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "fors.h" -#include "hash.h" -#include "hashx4.h" -#include "thash.h" -#include "thashx4.h" -#include "utils.h" -#include "utilsx4.h" - -static void fors_gen_skx4(unsigned char *sk0, - unsigned char *sk1, - unsigned char *sk2, - unsigned char *sk3, const unsigned char *sk_seed, - uint32_t fors_leaf_addrx4[4 * 8], - const hash_state *state_seeded) { - PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_prf_addrx4(sk0, sk1, sk2, sk3, sk_seed, fors_leaf_addrx4, state_seeded); -} - -static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, - const unsigned char *pub_seed, - uint32_t fors_leaf_addr[8], const hash_state *state_seeded) { - PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_thash_1(leaf, sk, pub_seed, fors_leaf_addr, state_seeded); -} - -static void fors_sk_to_leafx4(unsigned char *leaf0, - unsigned char *leaf1, - unsigned char *leaf2, - unsigned char *leaf3, - const unsigned char *sk0, - const unsigned char *sk1, - const unsigned char *sk2, - const unsigned char *sk3, - const unsigned char *pub_seed, - uint32_t fors_leaf_addrx4[4 * 8], - const hash_state *state_seeded) { - PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_thashx4_1(leaf0, leaf1, leaf2, leaf3, - sk0, sk1, sk2, sk3, pub_seed, fors_leaf_addrx4, state_seeded); -} - -static void fors_gen_leafx4(unsigned char *leaf0, - unsigned char *leaf1, - unsigned char *leaf2, - unsigned char *leaf3, - const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx0, - uint32_t addr_idx1, - uint32_t addr_idx2, - uint32_t addr_idx3, - const uint32_t fors_tree_addr[8], - const hash_state *state_seeded) { - uint32_t fors_leaf_addrx4[4 * 8] = {0}; - unsigned int j; - - /* Only copy the parts that must be kept in fors_leaf_addrx4. */ - for (j = 0; j < 4; j++) { - PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_copy_keypair_addr(fors_leaf_addrx4 + j * 8, fors_tree_addr); - PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_set_type(fors_leaf_addrx4 + j * 8, PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_ADDR_TYPE_FORSTREE); - } - - PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_set_tree_index(fors_leaf_addrx4 + 0 * 8, addr_idx0); - PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_set_tree_index(fors_leaf_addrx4 + 1 * 8, addr_idx1); - PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_set_tree_index(fors_leaf_addrx4 + 2 * 8, addr_idx2); - PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_set_tree_index(fors_leaf_addrx4 + 3 * 8, addr_idx3); - - fors_gen_skx4(leaf0, leaf1, leaf2, leaf3, sk_seed, fors_leaf_addrx4, state_seeded); - fors_sk_to_leafx4(leaf0, leaf1, leaf2, leaf3, - leaf0, leaf1, leaf2, leaf3, pub_seed, fors_leaf_addrx4, state_seeded); -} - -/** - * Interprets m as PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_FORS_HEIGHT-bit unsigned integers. - * Assumes m contains at least PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_FORS_TREES bits. - * Assumes indices has space for PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_FORS_TREES integers. - */ -static void message_to_indices(uint32_t *indices, const unsigned char *m) { - unsigned int i, j; - unsigned int offset = 0; - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_FORS_TREES; i++) { - indices[i] = 0; - for (j = 0; j < PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_FORS_HEIGHT; j++) { - indices[i] ^= (((uint32_t)m[offset >> 3] >> (offset & 0x7)) & 0x1) << j; - offset++; - } - } -} - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *state_seeded) { - /* Round up to multiple of 4 to prevent out-of-bounds for x4 parallelism */ - uint32_t indices[(PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_FORS_TREES + 3) & ~3] = {0}; - unsigned char roots[((PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_FORS_TREES + 3) & ~3) * PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N]; - /* Sign to a buffer, since we may not have a nice multiple of 4 and would - otherwise overrun the signature. */ - unsigned char sigbufx4[4 * PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N * (1 + PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_FORS_HEIGHT)]; - uint32_t fors_tree_addrx4[4 * 8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset[4] = {0}; - unsigned int i, j; - - for (j = 0; j < 4; j++) { - PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_copy_keypair_addr(fors_tree_addrx4 + j * 8, fors_addr); - PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_set_type(fors_tree_addrx4 + j * 8, PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_ADDR_TYPE_FORSTREE); - } - - PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_copy_keypair_addr(fors_pk_addr, fors_addr); - PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_set_type(fors_pk_addr, PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < ((PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_FORS_TREES + 3) & ~0x3); i += 4) { - for (j = 0; j < 4; j++) { - if (i + j < PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_FORS_TREES) { - idx_offset[j] = (i + j) * (1 << PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_FORS_HEIGHT); - - PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_set_tree_height(fors_tree_addrx4 + j * 8, 0); - PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_set_tree_index(fors_tree_addrx4 + j * 8, - indices[i + j] + idx_offset[j]); - } - } - - /* Include the secret key part that produces the selected leaf nodes. */ - fors_gen_skx4(sigbufx4 + 0 * PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N, - sigbufx4 + 1 * PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N, - sigbufx4 + 2 * PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N, - sigbufx4 + 3 * PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N, - sk_seed, fors_tree_addrx4, state_seeded); - - PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_treehashx4_FORS_HEIGHT(roots + i * PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N, sigbufx4 + 4 * PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N, sk_seed, pub_seed, - &indices[i], idx_offset, fors_gen_leafx4, fors_tree_addrx4, - state_seeded); - - for (j = 0; j < 4; j++) { - if (i + j < PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_FORS_TREES) { - memcpy(sig, sigbufx4 + j * PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N, PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N); - memcpy(sig + PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N, - sigbufx4 + 4 * PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N + j * PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N * PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_FORS_HEIGHT, - PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N * PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_FORS_HEIGHT); - sig += PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N * (1 + PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_FORS_HEIGHT); - } - } - } - - /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_thash_FORS_TREES(pk, roots, pub_seed, fors_pk_addr, state_seeded); -} - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, - const uint32_t fors_addr[8], - const hash_state *state_seeded) { - uint32_t indices[PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_FORS_TREES]; - unsigned char roots[PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_FORS_TREES * PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N]; - unsigned char leaf[PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N]; - uint32_t fors_tree_addr[8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_copy_keypair_addr(fors_tree_addr, fors_addr); - PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_copy_keypair_addr(fors_pk_addr, fors_addr); - - PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_set_type(fors_tree_addr, PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_set_type(fors_pk_addr, PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_FORS_TREES; i++) { - idx_offset = i * (1 << PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_FORS_HEIGHT); - - PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_set_tree_height(fors_tree_addr, 0); - PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Derive the leaf from the included secret key part. */ - fors_sk_to_leaf(leaf, sig, pub_seed, fors_tree_addr, state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N; - - /* Derive the corresponding root node of this tree. */ - PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_compute_root(roots + i * PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N, leaf, indices[i], idx_offset, - sig, PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_FORS_HEIGHT, pub_seed, fors_tree_addr, - state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N * PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_thash_FORS_TREES(pk, roots, pub_seed, fors_pk_addr, state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_avx2/fors.h b/src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_avx2/fors.h deleted file mode 100644 index 58cb8b202d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_avx2/fors.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_FORS_H -#define PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_FORS_H - -#include - -#include "hash_state.h" -#include "params.h" - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_fors_sign( - unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *hash_state_seeded); - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_fors_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, const uint32_t fors_addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_avx2/hash.h b/src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_avx2/hash.h deleted file mode 100644 index 72fb9b9205..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_avx2/hash.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_HASH_H -#define PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_HASH_H - -#include "hash_state.h" - -#include -#include - -void PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_initialize_hash_function( - hash_state *hash_state_seeded, - const unsigned char *pub_seed, const unsigned char *sk_seed); - -void PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_destroy_hash_function(hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_avx2/hash_shake256.c b/src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_avx2/hash_shake256.c deleted file mode 100644 index c24b61e606..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_avx2/hash_shake256.c +++ /dev/null @@ -1,106 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "utils.h" - -#include "fips202.h" - -/* For SHAKE256, there is no immediate reason to initialize at the start, - so this function is an empty operation. */ -void PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_initialize_hash_function( - hash_state *hash_state_seeded, // NOLINT(readability-non-const-parameter) - const unsigned char *pub_seed, const unsigned char *sk_seed) { - (void)hash_state_seeded; /* Suppress an 'unused parameter' warning. */ - (void)pub_seed; /* Suppress an 'unused parameter' warning. */ - (void)sk_seed; /* Suppress an 'unused parameter' warning. */ -} - -/* This is not necessary for SHAKE256, so we don't do anything */ -void PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_destroy_hash_function( - hash_state *hash_state_seeded) { // NOLINT(readability-non-const-parameter) - (void)hash_state_seeded; -} - -/* - * Computes PRF(key, addr), given a secret key of PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N bytes and an address - */ -void PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded) { - unsigned char buf[PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_ADDR_BYTES]; - - memcpy(buf, key, PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N); - PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_addr_to_bytes(buf + PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N, addr); - - shake256(out, PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N, buf, PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_ADDR_BYTES); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} - -/** - * Computes the message-dependent randomness R, using a secret seed and an - * optional randomization value as well as the message. - */ -void PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded) { - shake256incctx state; - - shake256_inc_init(&state); - shake256_inc_absorb(&state, sk_prf, PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N); - shake256_inc_absorb(&state, optrand, PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N); - shake256_inc_absorb(&state, m, mlen); - shake256_inc_finalize(&state); - shake256_inc_squeeze(R, PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N, &state); - shake256_inc_ctx_release(&state); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} - -/** - * Computes the message hash using R, the public key, and the message. - * Outputs the message digest and the index of the leaf. The index is split in - * the tree index and the leaf index, for convenient copying to an address. - */ -void PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded) { -#define PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_TREE_BITS (PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_TREE_HEIGHT * (PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_D - 1)) -#define PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_TREE_BYTES ((PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_TREE_BITS + 7) / 8) -#define PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_LEAF_BITS PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_TREE_HEIGHT -#define PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_LEAF_BYTES ((PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_LEAF_BITS + 7) / 8) -#define PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_DGST_BYTES (PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_FORS_MSG_BYTES + PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_TREE_BYTES + PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_LEAF_BYTES) - - unsigned char buf[PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_DGST_BYTES]; - unsigned char *bufp = buf; - shake256incctx state; - - shake256_inc_init(&state); - shake256_inc_absorb(&state, R, PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N); - shake256_inc_absorb(&state, pk, PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_PK_BYTES); - shake256_inc_absorb(&state, m, mlen); - shake256_inc_finalize(&state); - shake256_inc_squeeze(buf, PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_DGST_BYTES, &state); - shake256_inc_ctx_release(&state); - - memcpy(digest, bufp, PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_FORS_MSG_BYTES); - bufp += PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_FORS_MSG_BYTES; - - *tree = PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_bytes_to_ull( - bufp, PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_TREE_BYTES); - *tree &= (~(uint64_t)0) >> (64 - PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_TREE_BITS); - bufp += PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_TREE_BYTES; - - *leaf_idx = (uint32_t)PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_bytes_to_ull( - bufp, PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_LEAF_BYTES); - *leaf_idx &= (~(uint32_t)0) >> (32 - PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_LEAF_BITS); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_avx2/hash_shake256x4.c b/src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_avx2/hash_shake256x4.c deleted file mode 100644 index c031b0bb2f..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_avx2/hash_shake256x4.c +++ /dev/null @@ -1,38 +0,0 @@ -#include -#include - -#include "address.h" -#include "fips202x4.h" -#include "hashx4.h" -#include "params.h" - -/* - * 4-way parallel version of prf_addr; takes 4x as much input and output - */ -void PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_prf_addrx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const unsigned char *key, - const uint32_t addrx4[4 * 8], - const hash_state *state_seeded) { - unsigned char bufx4[4 * (PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_ADDR_BYTES)]; - unsigned int j; - - for (j = 0; j < 4; j++) { - memcpy(bufx4 + j * (PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_ADDR_BYTES), key, PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N); - PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_addr_to_bytes(bufx4 + PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N + j * (PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_ADDR_BYTES), addrx4 + j * 8); - } - - PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_shake256x4(out0, - out1, - out2, - out3, PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N, - bufx4 + 0 * (PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_ADDR_BYTES), - bufx4 + 1 * (PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_ADDR_BYTES), - bufx4 + 2 * (PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_ADDR_BYTES), - bufx4 + 3 * (PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_ADDR_BYTES), PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_ADDR_BYTES); - - /* Avoid unused parameter warning */ - (void)state_seeded; -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_avx2/hash_state.h b/src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_avx2/hash_state.h deleted file mode 100644 index 908b8af866..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_avx2/hash_state.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_HASH_STATE_H -#define PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_HASH_STATE_H - -/** - * Defines the type of the hash function state. - * - * Don't be fooled into thinking this instance of SPHINCS+ isn't stateless! - * - * From Section 7.2.2 from the SPHINCS+ round-2 specification: - * - * Each of the instances of the tweakable hash function take PK.seed as its - * first input, which is constant for a given key pair – and, thus, across - * a single signature. This leads to a lot of redundant computation. To remedy - * this, we pad PK.seed to the length of a full 64-byte SHA-256 input block. - * Because of the Merkle-DamgÃ¥rd construction that underlies SHA-256, this - * allows for reuse of the intermediate SHA-256 state after the initial call to - * the compression function which improves performance. - * - * We pass this hash state around in functions, because otherwise we need to - * have a global variable. - * - * SHAKE256 does not need this state. Because this implementation is generated - * from a shared code base, we still need to specify some hash_state as it is - * still passed around. We chose to use an `int` as a placeholder for this - * purpose. - */ - -typedef int hash_state; - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_avx2/hashx4.h b/src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_avx2/hashx4.h deleted file mode 100644 index d8c6cd7820..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_avx2/hashx4.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_HASHX4_H -#define PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_HASHX4_H - -#include - -#include "hash_state.h" - -void PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_prf_addrx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const unsigned char *key, - const uint32_t addrx4[4 * 8], - const hash_state *state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_avx2/params.h b/src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_avx2/params.h deleted file mode 100644 index 2f73d47dc2..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_avx2/params.h +++ /dev/null @@ -1,53 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_PARAMS_H -#define PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_PARAMS_H - -/* Hash output length in bytes. */ -#define PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N 16 -/* Height of the hypertree. */ -#define PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_FULL_HEIGHT 63 -/* Number of subtree layer. */ -#define PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_D 7 -/* FORS tree dimensions. */ -#define PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_FORS_HEIGHT 12 -#define PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_FORS_TREES 14 -/* Winternitz parameter, */ -#define PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_WOTS_W 16 - -/* The hash function is defined by linking a different hash.c file, as opposed - to setting a #define constant. */ - -/* For clarity */ -#define PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_ADDR_BYTES 32 - -/* WOTS parameters. */ -#define PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_WOTS_LOGW 4 - -#define PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_WOTS_LEN1 (8 * PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N / PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_WOTS_LOGW) - -/* PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#define PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_WOTS_LEN2 3 - -#define PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_WOTS_LEN (PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_WOTS_LEN1 + PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_WOTS_LEN2) -#define PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_WOTS_BYTES (PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_WOTS_LEN * PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N) -#define PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_WOTS_PK_BYTES PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_WOTS_BYTES - -/* Subtree size. */ -#define PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_TREE_HEIGHT (PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_FULL_HEIGHT / PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_D) - -/* FORS parameters. */ -#define PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_FORS_MSG_BYTES ((PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_FORS_TREES + 7) / 8) -#define PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_FORS_BYTES ((PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_FORS_HEIGHT + 1) * PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_FORS_TREES * PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N) -#define PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_FORS_PK_BYTES PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N - -/* Resulting SPX sizes. */ -#define PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_BYTES (PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_FORS_BYTES + PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_D * PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_WOTS_BYTES +\ - PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_FULL_HEIGHT * PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N) -#define PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_PK_BYTES (2 * PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N) -#define PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_SK_BYTES (2 * PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_PK_BYTES) - -/* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ -#define PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_OPTRAND_BYTES 32 - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_avx2/sign.c b/src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_avx2/sign.c deleted file mode 100644 index b75ce64884..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_avx2/sign.c +++ /dev/null @@ -1,409 +0,0 @@ -#include -#include -#include -#include - -#include "address.h" -#include "api.h" -#include "fors.h" -#include "hash.h" -#include "hash_state.h" -#include "params.h" -#include "randombytes.h" -#include "thash.h" -#include "utils.h" -#include "wots.h" - - -/** - * Computes the leaf at a given address. First generates the WOTS key pair, - * then computes leaf by hashing horizontally. - */ -static void wots_gen_leaf(unsigned char *leaf, const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx, const uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - unsigned char pk[PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_WOTS_BYTES]; - uint32_t wots_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_set_type( - wots_addr, PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_set_type( - wots_pk_addr, PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_ADDR_TYPE_WOTSPK); - - PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_set_keypair_addr( - wots_addr, addr_idx); - PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_wots_gen_pk( - pk, sk_seed, pub_seed, wots_addr, hash_state_seeded); - - PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_copy_keypair_addr( - wots_pk_addr, wots_addr); - PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_thash_WOTS_LEN( - leaf, pk, pub_seed, wots_pk_addr, hash_state_seeded); -} - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_crypto_sign_secretkeybytes(void) { - return PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_CRYPTO_SECRETKEYBYTES; -} - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_crypto_sign_publickeybytes(void) { - return PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_CRYPTO_PUBLICKEYBYTES; -} - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_crypto_sign_bytes(void) { - return PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_CRYPTO_BYTES; -} - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_crypto_sign_seedbytes(void) { - return PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_CRYPTO_SEEDBYTES; -} - -/* - * Generates an SPX key pair given a seed of length - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed) { - /* We do not need the auth path in key generation, but it simplifies the - code to have just one treehash routine that computes both root and path - in one function. */ - unsigned char auth_path[PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_TREE_HEIGHT * PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N]; - uint32_t top_tree_addr[8] = {0}; - hash_state hash_state_seeded; - - PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_set_layer_addr( - top_tree_addr, PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_D - 1); - PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_set_type( - top_tree_addr, PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_ADDR_TYPE_HASHTREE); - - /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ - memcpy(sk, seed, PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_CRYPTO_SEEDBYTES); - - memcpy(pk, sk + 2 * PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N, PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_initialize_hash_function(&hash_state_seeded, pk, sk); - - /* Compute root node of the top-most subtree. */ - PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_treehash_TREE_HEIGHT( - sk + 3 * PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N, auth_path, sk, sk + 2 * PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N, 0, 0, - wots_gen_leaf, top_tree_addr, &hash_state_seeded); - - memcpy(pk + PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N, sk + 3 * PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N, PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N); - - return 0; -} - -/* - * Generates an SPX key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk) { - - // guarantee alignment of pk - union { - __m128 _x[PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_CRYPTO_PUBLICKEYBYTES / 16]; - uint8_t pk[PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_CRYPTO_PUBLICKEYBYTES]; - } aligned_pk; - - // guarantee alignment of sk - union { - __m128 _x[PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_CRYPTO_SECRETKEYBYTES / 16]; - uint8_t sk[PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_CRYPTO_SECRETKEYBYTES]; - } aligned_sk; - - union { - __m128 _x[PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_CRYPTO_SEEDBYTES / 16]; - uint8_t seed[PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_CRYPTO_SEEDBYTES]; - } aligned_seed; - randombytes(aligned_seed.seed, PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_CRYPTO_SEEDBYTES); - - PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_crypto_sign_seed_keypair( - aligned_pk.pk, aligned_sk.sk, aligned_seed.seed); - memcpy(pk, aligned_pk.pk, PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_CRYPTO_PUBLICKEYBYTES); - memcpy(sk, aligned_sk.sk, PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_CRYPTO_SECRETKEYBYTES); - - return 0; -} - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - // guarantee alignment of sk - union { - __m128 *_x; - uint8_t sk[PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_CRYPTO_SECRETKEYBYTES]; - } aligned_sk; - memcpy(aligned_sk.sk, sk, PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_CRYPTO_SECRETKEYBYTES); - sk = aligned_sk.sk; - - // guarantee alignment of sig - union { - __m128 *_x; - uint8_t sig[PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_BYTES]; - } aligned_sig; - uint8_t *orig_sig = sig; - sig = (uint8_t *)aligned_sig.sig; - - const unsigned char *sk_seed = sk; - const unsigned char *sk_prf = sk + PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N; - const unsigned char *pk = sk + 2 * PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N; - const unsigned char *pub_seed = pk; - - unsigned char optrand[PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N]; - unsigned char mhash[PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_FORS_MSG_BYTES]; - unsigned char root[PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N]; - uint32_t i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - - hash_state hash_state_seeded; - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_initialize_hash_function( - &hash_state_seeded, - pub_seed, sk_seed); - - PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_set_type( - wots_addr, PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_set_type( - tree_addr, PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_ADDR_TYPE_HASHTREE); - - /* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ - randombytes(optrand, PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N); - /* Compute the digest randomization value. */ - PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_gen_message_random( - sig, sk_prf, optrand, m, mlen, &hash_state_seeded); - - /* Derive the message digest and leaf index from R, PK and M. */ - PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N; - - PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_set_keypair_addr( - wots_addr, idx_leaf); - - /* Sign the message hash using FORS. */ - PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_fors_sign( - sig, root, mhash, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_FORS_BYTES; - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_D; i++) { - PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_set_tree_addr(tree_addr, tree); - - PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_set_keypair_addr( - wots_addr, idx_leaf); - - /* Compute a WOTS signature. */ - PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_wots_sign( - sig, root, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_WOTS_BYTES; - - /* Compute the authentication path for the used WOTS leaf. */ - PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_treehash_TREE_HEIGHT( - root, sig, sk_seed, pub_seed, idx_leaf, 0, - wots_gen_leaf, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_TREE_HEIGHT * PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_TREE_HEIGHT; - } - - memcpy(orig_sig, aligned_sig.sig, PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_BYTES); - *siglen = PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_BYTES; - - return 0; -} - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk) { - // guarantee alignment of pk - union { - __m128 *_x; - uint8_t pk[PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_CRYPTO_PUBLICKEYBYTES]; - } aligned_pk; - memcpy(aligned_pk.pk, pk, PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_CRYPTO_PUBLICKEYBYTES); - pk = aligned_pk.pk; - - const unsigned char *pub_seed = pk; - const unsigned char *pub_root = pk + PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N; - unsigned char mhash[PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_FORS_MSG_BYTES]; - unsigned char wots_pk[PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_WOTS_BYTES]; - unsigned char root[PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N]; - unsigned char leaf[PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N]; - unsigned int i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - hash_state hash_state_seeded; - - if (siglen != PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_BYTES) { - return -1; - } - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_initialize_hash_function( - &hash_state_seeded, - pub_seed, NULL); - - PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_set_type( - wots_addr, PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_set_type( - tree_addr, PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_ADDR_TYPE_HASHTREE); - PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_set_type( - wots_pk_addr, PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_ADDR_TYPE_WOTSPK); - - /* Derive the message digest and leaf index from R || PK || M. */ - /* The additional PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N is a result of the hash domain separator. */ - PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N; - - /* Layer correctly defaults to 0, so no need to set_layer_addr */ - PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_set_keypair_addr( - wots_addr, idx_leaf); - - PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_fors_pk_from_sig( - root, sig, mhash, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_FORS_BYTES; - - /* For each subtree.. */ - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_D; i++) { - PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_set_tree_addr(tree_addr, tree); - - PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_set_keypair_addr( - wots_addr, idx_leaf); - - PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_copy_keypair_addr( - wots_pk_addr, wots_addr); - - /* The WOTS public key is only correct if the signature was correct. */ - /* Initially, root is the FORS pk, but on subsequent iterations it is - the root of the subtree below the currently processed subtree. */ - PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_wots_pk_from_sig( - wots_pk, sig, root, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_WOTS_BYTES; - - /* Compute the leaf node using the WOTS public key. */ - PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_thash_WOTS_LEN( - leaf, wots_pk, pub_seed, wots_pk_addr, &hash_state_seeded); - - /* Compute the root node of this subtree. */ - PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_compute_root( - root, leaf, idx_leaf, 0, sig, PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_TREE_HEIGHT, - pub_seed, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_TREE_HEIGHT * PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_TREE_HEIGHT; - } - - /* Check if the root node equals the root node in the public key. */ - if (memcmp(root, pub_root, PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N) != 0) { - return -1; - } - - return 0; -} - - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - size_t siglen; - - PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_crypto_sign_signature( - sm, &siglen, m, mlen, sk); - - memmove(sm + PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_BYTES, m, mlen); - *smlen = siglen + mlen; - - return 0; -} - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk) { - - // guarantee alignment of pk - union { - __m128 *_x; - uint8_t pk[PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_CRYPTO_PUBLICKEYBYTES]; - } aligned_pk; - memcpy(aligned_pk.pk, pk, PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_CRYPTO_PUBLICKEYBYTES); - pk = aligned_pk.pk; - - - /* The API caller does not necessarily know what size a signature should be - but SPHINCS+ signatures are always exactly PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_BYTES. */ - if (smlen < PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_BYTES) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - *mlen = smlen - PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_BYTES; - - if (PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_crypto_sign_verify( - sm, PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_BYTES, sm + PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_BYTES, *mlen, pk)) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - /* If verification was successful, move the message to the right place. */ - memmove(m, sm + PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_BYTES, *mlen); - - return 0; -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_avx2/thash.h b/src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_avx2/thash.h deleted file mode 100644 index 957cd06590..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_avx2/thash.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_THASH_H -#define PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_THASH_H - -#include "hash_state.h" - -#include - -void PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_avx2/thash_shake256_robust.c b/src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_avx2/thash_shake256_robust.c deleted file mode 100644 index bc1d72edaa..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_avx2/thash_shake256_robust.c +++ /dev/null @@ -1,81 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "thash.h" - -#include "fips202.h" - -/** - * Takes an array of inblocks concatenated arrays of PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N bytes. - */ -static void PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_thash( - unsigned char *out, unsigned char *buf, - const unsigned char *in, unsigned int inblocks, - const unsigned char *pub_seed, uint32_t addr[8]) { - - unsigned char *bitmask = buf + PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_ADDR_BYTES; - unsigned int i; - - memcpy(buf, pub_seed, PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N); - PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_addr_to_bytes(buf + PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N, addr); - - shake256(bitmask, inblocks * PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N, buf, PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_ADDR_BYTES); - - for (i = 0; i < inblocks * PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N; i++) { - buf[PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_ADDR_BYTES + i] = in[i] ^ bitmask[i]; - } - - shake256(out, PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N, buf, PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N); -} - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_ADDR_BYTES + 1 * PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N]; - PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_thash( - out, buf, in, 1, pub_seed, addr); - - (void)hash_state_seeded; /* Avoid unused parameter warning. */ -} - -void PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_ADDR_BYTES + 2 * PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N]; - PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_thash( - out, buf, in, 2, pub_seed, addr); - - (void)hash_state_seeded; /* Avoid unused parameter warning. */ -} - -void PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_ADDR_BYTES + PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_WOTS_LEN * PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N]; - PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_thash( - out, buf, in, PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_WOTS_LEN, pub_seed, addr); - - (void)hash_state_seeded; /* Avoid unused parameter warning. */ -} - -void PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_ADDR_BYTES + PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_FORS_TREES * PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N]; - PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_thash( - out, buf, in, PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_FORS_TREES, pub_seed, addr); - - (void)hash_state_seeded; /* Avoid unused parameter warning. */ -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_avx2/thash_shake256_robustx4.c b/src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_avx2/thash_shake256_robustx4.c deleted file mode 100644 index 8638426715..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_avx2/thash_shake256_robustx4.c +++ /dev/null @@ -1,66 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "thashx4.h" - -#include "fips202x4.h" - -/** - * 4-way parallel version of thash; takes 4x as much input and output - */ -#define thash_variant(name, inblocks) \ - void PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_thashx4_##name(unsigned char *out0, \ - unsigned char *out1, \ - unsigned char *out2, \ - unsigned char *out3, \ - const unsigned char *in0, \ - const unsigned char *in1, \ - const unsigned char *in2, \ - const unsigned char *in3, \ - const unsigned char *pub_seed, uint32_t addrx4[4*8], \ - const hash_state *state_seeded) \ - { \ - unsigned char buf0[PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_ADDR_BYTES + (inblocks)*PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N]; \ - unsigned char buf1[PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_ADDR_BYTES + (inblocks)*PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N]; \ - unsigned char buf2[PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_ADDR_BYTES + (inblocks)*PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N]; \ - unsigned char buf3[PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_ADDR_BYTES + (inblocks)*PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N]; \ - unsigned char bitmask0[(inblocks) * PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N]; \ - unsigned char bitmask1[(inblocks) * PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N]; \ - unsigned char bitmask2[(inblocks) * PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N]; \ - unsigned char bitmask3[(inblocks) * PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N]; \ - unsigned int i; \ - \ - memcpy(buf0, pub_seed, PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N); \ - memcpy(buf1, pub_seed, PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N); \ - memcpy(buf2, pub_seed, PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N); \ - memcpy(buf3, pub_seed, PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N); \ - PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_addr_to_bytes(buf0 + PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N, addrx4 + 0*8); \ - PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_addr_to_bytes(buf1 + PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N, addrx4 + 1*8); \ - PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_addr_to_bytes(buf2 + PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N, addrx4 + 2*8); \ - PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_addr_to_bytes(buf3 + PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N, addrx4 + 3*8); \ - \ - PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_shake256x4(bitmask0, bitmask1, bitmask2, bitmask3, (inblocks) * PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N, \ - buf0, buf1, buf2, buf3, PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_ADDR_BYTES); \ - \ - for (i = 0; i < (inblocks) * PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N; i++) { \ - buf0[PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_ADDR_BYTES + i] = in0[i] ^ bitmask0[i]; \ - buf1[PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_ADDR_BYTES + i] = in1[i] ^ bitmask1[i]; \ - buf2[PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_ADDR_BYTES + i] = in2[i] ^ bitmask2[i]; \ - buf3[PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_ADDR_BYTES + i] = in3[i] ^ bitmask3[i]; \ - } \ - \ - PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_shake256x4( \ - out0, out1, out2, out3, PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N, \ - buf0, buf1, buf2, buf3, PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_ADDR_BYTES + (inblocks)*PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N); \ - \ - /* avoid unused parameter warning */ \ - (void)state_seeded; \ - } - - -thash_variant(1, 1) -thash_variant(2, 2) -thash_variant(WOTS_LEN, PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_WOTS_LEN) -thash_variant(FORS_TREES, PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_FORS_TREES) diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_avx2/thashx4.h b/src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_avx2/thashx4.h deleted file mode 100644 index 6efe2d0a41..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_avx2/thashx4.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_THASHX4_H -#define PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_THASHX4_H - -#include - -#include "hash_state.h" - -#define thashx4_header(inblocks) \ - void PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_thashx4_##inblocks(unsigned char *out0, \ - unsigned char *out1, \ - unsigned char *out2, \ - unsigned char *out3, \ - const unsigned char *in0, \ - const unsigned char *in1, \ - const unsigned char *in2, \ - const unsigned char *in3, \ - const unsigned char *pub_seed, uint32_t addrx4[4*8], \ - const hash_state *state_seeded) - -thashx4_header(1); -thashx4_header(2); -thashx4_header(WOTS_LEN); -thashx4_header(FORS_TREES); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_avx2/utils.c b/src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_avx2/utils.c deleted file mode 100644 index 48432b2be6..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_avx2/utils.c +++ /dev/null @@ -1,199 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "hash_state.h" -#include "params.h" -#include "thash.h" -#include "utils.h" - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in) { - - /* Iterate over out in decreasing order, for big-endianness. */ - for (size_t i = outlen; i > 0; i--) { - out[i - 1] = in & 0xff; - in = in >> 8; - } -} - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_bytes_to_ull( - const unsigned char *in, size_t inlen) { - unsigned long long retval = 0; - - for (size_t i = 0; i < inlen; i++) { - retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); - } - return retval; -} - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - uint32_t i; - unsigned char buffer[2 * PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N]; - - /* If leaf_idx is odd (last bit = 1), current path element is a right child - and auth_path has to go left. Otherwise it is the other way around. */ - if (leaf_idx & 1) { - memcpy(buffer + PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N, leaf, PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N); - } else { - memcpy(buffer, leaf, PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N); - memcpy(buffer + PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N, auth_path, PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N); - } - auth_path += PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N; - - for (i = 0; i < tree_height - 1; i++) { - leaf_idx >>= 1; - idx_offset >>= 1; - /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_set_tree_height(addr, i + 1); - PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_set_tree_index( - addr, leaf_idx + idx_offset); - - /* Pick the right or left neighbor, depending on parity of the node. */ - if (leaf_idx & 1) { - PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_thash_2( - buffer + PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N); - } else { - PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_thash_2( - buffer, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer + PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N, auth_path, PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N); - } - auth_path += PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N; - } - - /* The last iteration is exceptional; we do not copy an auth_path node. */ - leaf_idx >>= 1; - idx_offset >>= 1; - PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_set_tree_height(addr, tree_height); - PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_set_tree_index( - addr, leaf_idx + idx_offset); - PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_thash_2( - root, buffer, pub_seed, addr, hash_state_seeded); -} - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -static void PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_treehash( - unsigned char *root, unsigned char *auth_path, - unsigned char *stack, unsigned int *heights, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - - unsigned int offset = 0; - uint32_t idx; - uint32_t tree_idx; - - for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { - /* Add the next leaf node to the stack. */ - gen_leaf(stack + offset * PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N, - sk_seed, pub_seed, idx + idx_offset, tree_addr, - hash_state_seeded); - offset++; - heights[offset - 1] = 0; - - /* If this is a node we need for the auth path.. */ - if ((leaf_idx ^ 0x1) == idx) { - memcpy(auth_path, stack + (offset - 1)*PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N, PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N); - } - - /* While the top-most nodes are of equal height.. */ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { - /* Compute index of the new node, in the next layer. */ - tree_idx = (idx >> (heights[offset - 1] + 1)); - - /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_set_tree_height( - tree_addr, heights[offset - 1] + 1); - PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_set_tree_index( - tree_addr, tree_idx + (idx_offset >> (heights[offset - 1] + 1))); - /* Hash the top-most nodes from the stack together. */ - PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_thash_2( - stack + (offset - 2)*PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N, stack + (offset - 2)*PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N, - pub_seed, tree_addr, hash_state_seeded); - offset--; - /* Note that the top-most node is now one layer higher. */ - heights[offset - 1]++; - - /* If this is a node we need for the auth path.. */ - if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_path + heights[offset - 1]*PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N, - stack + (offset - 1)*PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N, PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N); - } - } - } - memcpy(root, stack, PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N); -} - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_FORS_HEIGHT + 1)*PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N]; - unsigned int heights[PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_FORS_HEIGHT + 1]; - - PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_FORS_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_TREE_HEIGHT + 1)*PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N]; - unsigned int heights[PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_TREE_HEIGHT + 1]; - - PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_TREE_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_avx2/utils.h b/src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_avx2/utils.h deleted file mode 100644 index bc26b11597..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_avx2/utils.h +++ /dev/null @@ -1,64 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_UTILS_H -#define PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_UTILS_H - -#include "hash_state.h" -#include "params.h" -#include -#include - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in); - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_bytes_to_ull( - const unsigned char *in, size_t inlen); - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -void PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_avx2/utilsx4.c b/src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_avx2/utilsx4.c deleted file mode 100644 index dbba010ca5..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_avx2/utilsx4.c +++ /dev/null @@ -1,98 +0,0 @@ -#include "address.h" -#include "params.h" -#include "thashx4.h" -#include "utils.h" -#include "utilsx4.h" - -#include - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -#define treehashx4_variant(name, tree_height) \ - void PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_treehashx4_##name( \ - unsigned char *rootx4, unsigned char *auth_pathx4, const unsigned char *sk_seed, \ - const unsigned char *pub_seed, const uint32_t leaf_idx[4], uint32_t idx_offset[4], \ - void (*gen_leafx4)(unsigned char * /* leaf0 */, unsigned char * /* leaf1 */, \ - unsigned char * /* leaf2 */, unsigned char * /* leaf3 */, \ - const unsigned char * /* sk_seed */, \ - const unsigned char * /* pub_seed */, uint32_t /* addr_idx0 */, \ - uint32_t /* addr_idx1 */, uint32_t /* addr_idx2 */, \ - uint32_t /* addr_idx3 */, const uint32_t[8] /* tree_addr */, \ - const hash_state * /* state_seeded */), \ - uint32_t tree_addrx4[4 * 8], const hash_state *state_seeded) { \ - unsigned char stackx4[4 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N]; \ - unsigned int heights[(tree_height) + 1]; \ - unsigned int offset = 0; \ - uint32_t idx; \ - uint32_t tree_idx; \ - unsigned int j; \ - \ - for (idx = 0; idx < (uint32_t)(1 << (tree_height)); idx++) { \ - /* Add the next leaf node to the stack. */ \ - gen_leafx4(stackx4 + 0 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N + offset * PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N, \ - stackx4 + 1 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N + offset * PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N, \ - stackx4 + 2 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N + offset * PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N, \ - stackx4 + 3 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N + offset * PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N, sk_seed, \ - pub_seed, idx + idx_offset[0], idx + idx_offset[1], idx + idx_offset[2], \ - idx + idx_offset[3], tree_addrx4, state_seeded); \ - offset++; \ - heights[offset - 1] = 0; \ - \ - /* If this is a node we need for the auth path.. */ \ - for (j = 0; j < 4; j++) { \ - if ((leaf_idx[j] ^ 0x1) == idx) { \ - memcpy(auth_pathx4 + j * (tree_height)*PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N, \ - stackx4 + j * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N + (offset - 1) * PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N, \ - PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N); \ - } \ - } \ - \ - /* While the top-most nodes are of equal height.. */ \ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { \ - /* Compute index of the new node, in the next layer. */ \ - tree_idx = (idx >> (heights[offset - 1] + 1)); \ - \ - /* Set the address of the node we're creating. */ \ - for (j = 0; j < 4; j++) { \ - PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_set_tree_height(tree_addrx4 + j * 8, heights[offset - 1] + 1); \ - PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_set_tree_index(tree_addrx4 + j * 8, \ - tree_idx + (idx_offset[j] >> (heights[offset - 1] + 1))); \ - } \ - /* Hash the top-most nodes from the stack together. */ \ - PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_thashx4_2(stackx4 + 0 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N + (offset - 2) * PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N, \ - stackx4 + 1 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N + (offset - 2) * PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N, \ - stackx4 + 2 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N + (offset - 2) * PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N, \ - stackx4 + 3 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N + (offset - 2) * PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N, \ - stackx4 + 0 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N + (offset - 2) * PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N, \ - stackx4 + 1 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N + (offset - 2) * PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N, \ - stackx4 + 2 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N + (offset - 2) * PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N, \ - stackx4 + 3 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N + (offset - 2) * PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N, \ - pub_seed, tree_addrx4, state_seeded); \ - offset--; \ - /* Note that the top-most node is now one layer higher. */ \ - heights[offset - 1]++; \ - \ - /* If this is a node we need for the auth path.. */ \ - for (j = 0; j < 4; j++) { \ - if (((leaf_idx[j] >> heights[offset - 1]) ^ 0x1) == tree_idx) { \ - memcpy(auth_pathx4 + j * (tree_height)*PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N + \ - heights[offset - 1] * PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N, \ - stackx4 + j * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N + (offset - 1) * PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N, \ - PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N); \ - } \ - } \ - } \ - } \ - \ - for (j = 0; j < 4; j++) { \ - memcpy(rootx4 + j * PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N, stackx4 + j * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N, PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N); \ - } \ - } - -treehashx4_variant(FORS_HEIGHT, PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_FORS_HEIGHT) diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_avx2/utilsx4.h b/src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_avx2/utilsx4.h deleted file mode 100644 index 40b55ace62..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_avx2/utilsx4.h +++ /dev/null @@ -1,38 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_UTILSX4_H -#define PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_UTILSX4_H - -#include "hash_state.h" -#include "params.h" - -#include - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -void PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_treehashx4_FORS_HEIGHT(unsigned char *rootx4, - unsigned char *auth_pathx4, - const unsigned char *sk_seed, - const unsigned char *pub_seed, - const uint32_t leaf_idx[4], - uint32_t idx_offset[4], - void (*gen_leafx4)(unsigned char * /* leaf0 */, - unsigned char * /* leaf1 */, - unsigned char * /* leaf2 */, - unsigned char * /* leaf3 */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx0 */, - uint32_t /* addr_idx1 */, - uint32_t /* addr_idx2 */, - uint32_t /* addr_idx3 */, - const uint32_t[8] /* tree_addr */, - const hash_state * /* state_seeded */), - uint32_t tree_addrx4[4 * 8], - const hash_state *state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_avx2/wots.c b/src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_avx2/wots.c deleted file mode 100644 index 9c48e91880..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_avx2/wots.c +++ /dev/null @@ -1,240 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "hash_state.h" -#include "hashx4.h" -#include "params.h" -#include "thash.h" -#include "thashx4.h" -#include "utils.h" -#include "wots.h" - -// TODO clarify address expectations, and make them more uniform. -// TODO i.e. do we expect types to be set already? -// TODO and do we expect modifications or copies? - -/** - * Computes the starting value for a chain, i.e. the secret key. - * Expects the address to be complete up to the chain address. - */ -static void wots_gen_sk(unsigned char *sk, const unsigned char *sk_seed, - uint32_t wots_addr[8], const hash_state *state_seeded) { - /* Make sure that the hash address is actually zeroed. */ - PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_set_hash_addr(wots_addr, 0); - - /* Generate sk element. */ - PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_prf_addr(sk, sk_seed, wots_addr, state_seeded); -} - -/** - * 4-way parallel version of wots_gen_sk; expects 4x as much space in sk - */ -static void wots_gen_skx4(unsigned char *skx4, const unsigned char *sk_seed, - uint32_t wots_addrx4[4 * 8], const hash_state *state_seeded) { - unsigned int j; - - /* Make sure that the hash address is actually zeroed. */ - for (j = 0; j < 4; j++) { - PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_set_hash_addr(wots_addrx4 + j * 8, 0); - } - - /* Generate sk element. */ - PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_prf_addrx4(skx4 + 0 * PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N, - skx4 + 1 * PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N, - skx4 + 2 * PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N, - skx4 + 3 * PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N, - sk_seed, wots_addrx4, - state_seeded); -} - -/** - * Computes the chaining function. - * out and in have to be n-byte arrays. - * - * Interprets in as start-th value of the chain. - * addr has to contain the address of the chain. - */ -static void gen_chain(unsigned char *out, const unsigned char *in, - unsigned int start, unsigned int steps, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *state_seeded) { - uint32_t i; - - /* Initialize out with the value at position 'start'. */ - memcpy(out, in, PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N); - - /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_WOTS_W; i++) { - PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_set_hash_addr(addr, i); - PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_thash_1(out, out, pub_seed, addr, state_seeded); - } -} - -/** - * 4-way parallel version of gen_chain; expects 4x as much space in out, and - * 4x as much space in inx4. Assumes start and step identical across chains. - */ -static void gen_chainx4(unsigned char *outx4, const unsigned char *inx4, - unsigned int start, unsigned int steps, - const unsigned char *pub_seed, uint32_t addrx4[4 * 8], - const hash_state *state_seeded) { - uint32_t i; - unsigned int j; - - /* Initialize outx4 with the value at position 'start'. */ - memcpy(outx4, inx4, 4 * PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N); - - /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_WOTS_W; i++) { - for (j = 0; j < 4; j++) { - PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_set_hash_addr(addrx4 + j * 8, i); - } - PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_thashx4_1(outx4 + 0 * PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N, - outx4 + 1 * PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N, - outx4 + 2 * PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N, - outx4 + 3 * PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N, - outx4 + 0 * PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N, - outx4 + 1 * PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N, - outx4 + 2 * PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N, - outx4 + 3 * PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N, - pub_seed, addrx4, - state_seeded); - } -} - -/** - * base_w algorithm as described in draft. - * Interprets an array of bytes as integers in base w. - * This only works when log_w is a divisor of 8. - */ -static void base_w(unsigned int *output, const int out_len, const unsigned char *input) { - int in = 0; - int out = 0; - unsigned char total = 0; - int bits = 0; - int consumed; - - for (consumed = 0; consumed < out_len; consumed++) { - if (bits == 0) { - total = input[in]; - in++; - bits += 8; - } - bits -= PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_WOTS_LOGW; - output[out] = (unsigned int)(total >> bits) & (PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_WOTS_W - 1); - out++; - } -} - -/* Computes the WOTS+ checksum over a message (in base_w). */ -static void wots_checksum(unsigned int *csum_base_w, const unsigned int *msg_base_w) { - unsigned int csum = 0; - unsigned char csum_bytes[(PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_WOTS_LEN2 * PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_WOTS_LOGW + 7) / 8]; - unsigned int i; - - /* Compute checksum. */ - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_WOTS_LEN1; i++) { - csum += PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_WOTS_W - 1 - msg_base_w[i]; - } - - /* Convert checksum to base_w. */ - /* Make sure expected empty zero bits are the least significant bits. */ - csum = csum << (8 - ((PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_WOTS_LEN2 * PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_WOTS_LOGW) % 8)); - PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); - base_w(csum_base_w, PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_WOTS_LEN2, csum_bytes); -} - -/* Takes a message and derives the matching chain lengths. */ -static void chain_lengths(unsigned int *lengths, const unsigned char *msg) { - base_w(lengths, PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_WOTS_LEN1, msg); - wots_checksum(lengths + PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_WOTS_LEN1, lengths); -} - -/** - * WOTS key generation. Takes a 32 byte sk_seed, expands it to WOTS private key - * elements and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_wots_gen_pk(unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *state_seeded) { - uint32_t i; - unsigned int j; - - uint32_t addrx4[4 * 8]; - unsigned char pkbuf[4 * PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N]; - - for (j = 0; j < 4; j++) { - memcpy(addrx4 + j * 8, addr, sizeof(uint32_t) * 8); - } - - /* The last iteration typically does not have complete set of 4 chains, - but because we use pkbuf, this is not an issue -- we still do as many - in parallel as possible. */ - for (i = 0; i < ((PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_WOTS_LEN + 3) & ~0x3); i += 4) { - for (j = 0; j < 4; j++) { - PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_set_chain_addr(addrx4 + j * 8, i + j); - } - wots_gen_skx4(pkbuf, sk_seed, addrx4, state_seeded); - gen_chainx4(pkbuf, pkbuf, 0, PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_WOTS_W - 1, pub_seed, addrx4, state_seeded); - for (j = 0; j < 4; j++) { - if (i + j < PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_WOTS_LEN) { - memcpy(pk + (i + j)*PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N, pkbuf + j * PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N, PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N); - } - } - } - - // Get rid of unused argument variable. - (void)state_seeded; -} - -/** - * Takes a n-byte message and the 32-byte sk_see to compute a signature 'sig'. - */ -void PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_wots_sign(unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_WOTS_LEN; i++) { - PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_set_chain_addr(addr, i); - wots_gen_sk(sig + i * PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N, sk_seed, addr, state_seeded); - gen_chain(sig + i * PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N, sig + i * PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N, 0, lengths[i], pub_seed, addr, state_seeded); - } - - // avoid unused argument - (void)state_seeded; -} - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_WOTS_LEN; i++) { - PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_set_chain_addr(addr, i); - gen_chain(pk + i * PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N, sig + i * PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_N, - lengths[i], PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_WOTS_W - 1 - lengths[i], pub_seed, addr, - state_seeded); - } - - // avoid unused argument - (void)state_seeded; -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_avx2/wots.h b/src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_avx2/wots.h deleted file mode 100644 index 48ed153215..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_avx2/wots.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_WOTS_H -#define PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_WOTS_H - -#include "hash_state.h" -#include "params.h" -#include - -/** - * WOTS key generation. Takes a 32 byte seed for the private key, expands it to - * a full WOTS private key and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_wots_gen_pk( - unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -/** - * Takes a n-byte message and the 32-byte seed for the private key to compute a - * signature that is placed at 'sig'. - */ -void PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_wots_sign( - unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *hash_state_seeded); - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_wots_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_clean/LICENSE b/src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_clean/LICENSE deleted file mode 100644 index 670154e353..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_clean/LICENSE +++ /dev/null @@ -1,116 +0,0 @@ -CC0 1.0 Universal - -Statement of Purpose - -The laws of most jurisdictions throughout the world automatically confer -exclusive Copyright and Related Rights (defined below) upon the creator and -subsequent owner(s) (each and all, an "owner") of an original work of -authorship and/or a database (each, a "Work"). - -Certain owners wish to permanently relinquish those rights to a Work for the -purpose of contributing to a commons of creative, cultural and scientific -works ("Commons") that the public can reliably and without fear of later -claims of infringement build upon, modify, incorporate in other works, reuse -and redistribute as freely as possible in any form whatsoever and for any -purposes, including without limitation commercial purposes. These owners may -contribute to the Commons to promote the ideal of a free culture and the -further production of creative, cultural and scientific works, or to gain -reputation or greater distribution for their Work in part through the use and -efforts of others. - -For these and/or other purposes and motivations, and without any expectation -of additional consideration or compensation, the person associating CC0 with a -Work (the "Affirmer"), to the extent that he or she is an owner of Copyright -and Related Rights in the Work, voluntarily elects to apply CC0 to the Work -and publicly distribute the Work under its terms, with knowledge of his or her -Copyright and Related Rights in the Work and the meaning and intended legal -effect of CC0 on those rights. - -1. Copyright and Related Rights. A Work made available under CC0 may be -protected by copyright and related or neighboring rights ("Copyright and -Related Rights"). Copyright and Related Rights include, but are not limited -to, the following: - - i. the right to reproduce, adapt, distribute, perform, display, communicate, - and translate a Work; - - ii. moral rights retained by the original author(s) and/or performer(s); - - iii. publicity and privacy rights pertaining to a person's image or likeness - depicted in a Work; - - iv. rights protecting against unfair competition in regards to a Work, - subject to the limitations in paragraph 4(a), below; - - v. rights protecting the extraction, dissemination, use and reuse of data in - a Work; - - vi. database rights (such as those arising under Directive 96/9/EC of the - European Parliament and of the Council of 11 March 1996 on the legal - protection of databases, and under any national implementation thereof, - including any amended or successor version of such directive); and - - vii. other similar, equivalent or corresponding rights throughout the world - based on applicable law or treaty, and any national implementations thereof. - -2. Waiver. To the greatest extent permitted by, but not in contravention of, -applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and -unconditionally waives, abandons, and surrenders all of Affirmer's Copyright -and Related Rights and associated claims and causes of action, whether now -known or unknown (including existing as well as future claims and causes of -action), in the Work (i) in all territories worldwide, (ii) for the maximum -duration provided by applicable law or treaty (including future time -extensions), (iii) in any current or future medium and for any number of -copies, and (iv) for any purpose whatsoever, including without limitation -commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes -the Waiver for the benefit of each member of the public at large and to the -detriment of Affirmer's heirs and successors, fully intending that such Waiver -shall not be subject to revocation, rescission, cancellation, termination, or -any other legal or equitable action to disrupt the quiet enjoyment of the Work -by the public as contemplated by Affirmer's express Statement of Purpose. - -3. Public License Fallback. Should any part of the Waiver for any reason be -judged legally invalid or ineffective under applicable law, then the Waiver -shall be preserved to the maximum extent permitted taking into account -Affirmer's express Statement of Purpose. In addition, to the extent the Waiver -is so judged Affirmer hereby grants to each affected person a royalty-free, -non transferable, non sublicensable, non exclusive, irrevocable and -unconditional license to exercise Affirmer's Copyright and Related Rights in -the Work (i) in all territories worldwide, (ii) for the maximum duration -provided by applicable law or treaty (including future time extensions), (iii) -in any current or future medium and for any number of copies, and (iv) for any -purpose whatsoever, including without limitation commercial, advertising or -promotional purposes (the "License"). The License shall be deemed effective as -of the date CC0 was applied by Affirmer to the Work. Should any part of the -License for any reason be judged legally invalid or ineffective under -applicable law, such partial invalidity or ineffectiveness shall not -invalidate the remainder of the License, and in such case Affirmer hereby -affirms that he or she will not (i) exercise any of his or her remaining -Copyright and Related Rights in the Work or (ii) assert any associated claims -and causes of action with respect to the Work, in either case contrary to -Affirmer's express Statement of Purpose. - -4. Limitations and Disclaimers. - - a. No trademark or patent rights held by Affirmer are waived, abandoned, - surrendered, licensed or otherwise affected by this document. - - b. Affirmer offers the Work as-is and makes no representations or warranties - of any kind concerning the Work, express, implied, statutory or otherwise, - including without limitation warranties of title, merchantability, fitness - for a particular purpose, non infringement, or the absence of latent or - other defects, accuracy, or the present or absence of errors, whether or not - discoverable, all to the greatest extent permissible under applicable law. - - c. Affirmer disclaims responsibility for clearing rights of other persons - that may apply to the Work or any use thereof, including without limitation - any person's Copyright and Related Rights in the Work. Further, Affirmer - disclaims responsibility for obtaining any necessary consents, permissions - or other rights required for any use of the Work. - - d. Affirmer understands and acknowledges that Creative Commons is not a - party to this document and has no duty or obligation with respect to this - CC0 or use of the Work. - -For more information, please see - diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_clean/address.c b/src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_clean/address.c deleted file mode 100644 index c2dc7835fb..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_clean/address.c +++ /dev/null @@ -1,78 +0,0 @@ -#include - -#include "address.h" -#include "params.h" -#include "utils.h" - -void PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]) { - int i; - - for (i = 0; i < 8; i++) { - PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_ull_to_bytes( - bytes + i * 4, 4, addr[i]); - } -} - -void PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_set_layer_addr( - uint32_t addr[8], uint32_t layer) { - addr[0] = layer; -} - -void PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_set_tree_addr( - uint32_t addr[8], uint64_t tree) { - addr[1] = 0; - addr[2] = (uint32_t) (tree >> 32); - addr[3] = (uint32_t) tree; -} - -void PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_set_type( - uint32_t addr[8], uint32_t type) { - addr[4] = type; -} - -void PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; -} - -/* These functions are used for OTS addresses. */ - -void PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_set_keypair_addr( - uint32_t addr[8], uint32_t keypair) { - addr[5] = keypair; -} - -void PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; - out[5] = in[5]; -} - -void PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_set_chain_addr( - uint32_t addr[8], uint32_t chain) { - addr[6] = chain; -} - -void PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_set_hash_addr( - uint32_t addr[8], uint32_t hash) { - addr[7] = hash; -} - -/* These functions are used for all hash tree addresses (including FORS). */ - -void PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_set_tree_height( - uint32_t addr[8], uint32_t tree_height) { - addr[6] = tree_height; -} - -void PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_set_tree_index( - uint32_t addr[8], uint32_t tree_index) { - addr[7] = tree_index; -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_clean/address.h b/src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_clean/address.h deleted file mode 100644 index 89997a5a7f..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_clean/address.h +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_ADDRESS_H -#define PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_ADDRESS_H - -#include - -#define PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_ADDR_TYPE_WOTS 0 -#define PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_ADDR_TYPE_WOTSPK 1 -#define PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_ADDR_TYPE_HASHTREE 2 -#define PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_ADDR_TYPE_FORSTREE 3 -#define PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_ADDR_TYPE_FORSPK 4 - -void PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]); - -void PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_set_layer_addr( - uint32_t addr[8], uint32_t layer); - -void PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_set_tree_addr( - uint32_t addr[8], uint64_t tree); - -void PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_set_type( - uint32_t addr[8], uint32_t type); - -/* Copies the layer and tree part of one address into the other */ -void PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for WOTS and FORS addresses. */ - -void PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_set_keypair_addr( - uint32_t addr[8], uint32_t keypair); - -void PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_set_chain_addr( - uint32_t addr[8], uint32_t chain); - -void PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_set_hash_addr( - uint32_t addr[8], uint32_t hash); - -void PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for all hash tree addresses (including FORS). */ - -void PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_set_tree_height( - uint32_t addr[8], uint32_t tree_height); - -void PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_set_tree_index( - uint32_t addr[8], uint32_t tree_index); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_clean/api.h b/src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_clean/api.h deleted file mode 100644 index a176c44d2e..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_clean/api.h +++ /dev/null @@ -1,81 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_API_H -#define PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_API_H - -#include -#include - - - -#define PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_CRYPTO_ALGNAME "SPHINCS+" - -#define PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_CRYPTO_SECRETKEYBYTES 64 -#define PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_CRYPTO_PUBLICKEYBYTES 32 -#define PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_CRYPTO_BYTES 7856 -#define PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_CRYPTO_SEEDBYTES 48 - - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_clean/fors.c b/src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_clean/fors.c deleted file mode 100644 index f0c90b886a..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_clean/fors.c +++ /dev/null @@ -1,161 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "fors.h" -#include "hash.h" -#include "hash_state.h" -#include "thash.h" -#include "utils.h" - -static void fors_gen_sk(unsigned char *sk, const unsigned char *sk_seed, - uint32_t fors_leaf_addr[8], const hash_state *hash_state_seeded) { - PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_prf_addr( - sk, sk_seed, fors_leaf_addr, hash_state_seeded); -} - -static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, - const unsigned char *pub_seed, - uint32_t fors_leaf_addr[8], - const hash_state *hash_state_seeded) { - PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_thash_1( - leaf, sk, pub_seed, fors_leaf_addr, hash_state_seeded); -} - -static void fors_gen_leaf(unsigned char *leaf, const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx, const uint32_t fors_tree_addr[8], - const hash_state *hash_state_seeded) { - uint32_t fors_leaf_addr[8] = {0}; - - /* Only copy the parts that must be kept in fors_leaf_addr. */ - PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_copy_keypair_addr( - fors_leaf_addr, fors_tree_addr); - PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_set_type( - fors_leaf_addr, PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_set_tree_index( - fors_leaf_addr, addr_idx); - - fors_gen_sk(leaf, sk_seed, fors_leaf_addr, hash_state_seeded); - fors_sk_to_leaf(leaf, leaf, pub_seed, fors_leaf_addr, hash_state_seeded); -} - -/** - * Interprets m as PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_FORS_HEIGHT-bit unsigned integers. - * Assumes m contains at least PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_FORS_TREES bits. - * Assumes indices has space for PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_FORS_TREES integers. - */ -static void message_to_indices(uint32_t *indices, const unsigned char *m) { - unsigned int i, j; - unsigned int offset = 0; - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_FORS_TREES; i++) { - indices[i] = 0; - for (j = 0; j < PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_FORS_HEIGHT; j++) { - indices[i] ^= (((uint32_t)m[offset >> 3] >> (offset & 0x7)) & 0x1) << j; - offset++; - } - } -} - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_fors_sign( - unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *hash_state_seeded) { - uint32_t indices[PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_FORS_TREES]; - unsigned char roots[PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_FORS_TREES * PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_N]; - uint32_t fors_tree_addr[8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_copy_keypair_addr( - fors_tree_addr, fors_addr); - PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_copy_keypair_addr( - fors_pk_addr, fors_addr); - - PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_set_type( - fors_tree_addr, PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_set_type( - fors_pk_addr, PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_FORS_TREES; i++) { - idx_offset = i * (1 << PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_FORS_HEIGHT); - - PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_set_tree_height( - fors_tree_addr, 0); - PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_set_tree_index( - fors_tree_addr, indices[i] + idx_offset); - - /* Include the secret key part that produces the selected leaf node. */ - fors_gen_sk(sig, sk_seed, fors_tree_addr, hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_N; - - /* Compute the authentication path for this leaf node. */ - PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_treehash_FORS_HEIGHT( - roots + i * PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_N, sig, sk_seed, pub_seed, - indices[i], idx_offset, fors_gen_leaf, fors_tree_addr, - hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_N * PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_thash_FORS_TREES( - pk, roots, pub_seed, fors_pk_addr, hash_state_seeded); -} - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_fors_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, const uint32_t fors_addr[8], - const hash_state *hash_state_seeded) { - uint32_t indices[PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_FORS_TREES]; - unsigned char roots[PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_FORS_TREES * PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_N]; - unsigned char leaf[PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_N]; - uint32_t fors_tree_addr[8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_copy_keypair_addr(fors_tree_addr, fors_addr); - PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_copy_keypair_addr(fors_pk_addr, fors_addr); - - PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_set_type(fors_tree_addr, PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_set_type(fors_pk_addr, PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_FORS_TREES; i++) { - idx_offset = i * (1 << PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_FORS_HEIGHT); - - PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_set_tree_height(fors_tree_addr, 0); - PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Derive the leaf from the included secret key part. */ - fors_sk_to_leaf(leaf, sig, pub_seed, fors_tree_addr, hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_N; - - /* Derive the corresponding root node of this tree. */ - PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_compute_root(roots + i * PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_N, leaf, indices[i], idx_offset, sig, - PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_FORS_HEIGHT, pub_seed, fors_tree_addr, hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_N * PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_thash_FORS_TREES(pk, roots, pub_seed, fors_pk_addr, hash_state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_clean/fors.h b/src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_clean/fors.h deleted file mode 100644 index 7255523b4c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_clean/fors.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_FORS_H -#define PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_FORS_H - -#include - -#include "hash_state.h" -#include "params.h" - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_fors_sign( - unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *hash_state_seeded); - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_fors_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, const uint32_t fors_addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_clean/hash.h b/src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_clean/hash.h deleted file mode 100644 index 3a5182ba3e..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_clean/hash.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_HASH_H -#define PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_HASH_H - -#include "hash_state.h" - -#include -#include - -void PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_initialize_hash_function( - hash_state *hash_state_seeded, - const unsigned char *pub_seed, const unsigned char *sk_seed); - -void PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_destroy_hash_function(hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_clean/hash_shake256.c b/src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_clean/hash_shake256.c deleted file mode 100644 index 53a9981434..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_clean/hash_shake256.c +++ /dev/null @@ -1,106 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "utils.h" - -#include "fips202.h" - -/* For SHAKE256, there is no immediate reason to initialize at the start, - so this function is an empty operation. */ -void PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_initialize_hash_function( - hash_state *hash_state_seeded, // NOLINT(readability-non-const-parameter) - const unsigned char *pub_seed, const unsigned char *sk_seed) { - (void)hash_state_seeded; /* Suppress an 'unused parameter' warning. */ - (void)pub_seed; /* Suppress an 'unused parameter' warning. */ - (void)sk_seed; /* Suppress an 'unused parameter' warning. */ -} - -/* This is not necessary for SHAKE256, so we don't do anything */ -void PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_destroy_hash_function( - hash_state *hash_state_seeded) { // NOLINT(readability-non-const-parameter) - (void)hash_state_seeded; -} - -/* - * Computes PRF(key, addr), given a secret key of PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_N bytes and an address - */ -void PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded) { - unsigned char buf[PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_N + PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_ADDR_BYTES]; - - memcpy(buf, key, PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_N); - PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_addr_to_bytes(buf + PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_N, addr); - - shake256(out, PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_N, buf, PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_N + PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_ADDR_BYTES); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} - -/** - * Computes the message-dependent randomness R, using a secret seed and an - * optional randomization value as well as the message. - */ -void PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded) { - shake256incctx state; - - shake256_inc_init(&state); - shake256_inc_absorb(&state, sk_prf, PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_N); - shake256_inc_absorb(&state, optrand, PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_N); - shake256_inc_absorb(&state, m, mlen); - shake256_inc_finalize(&state); - shake256_inc_squeeze(R, PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_N, &state); - shake256_inc_ctx_release(&state); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} - -/** - * Computes the message hash using R, the public key, and the message. - * Outputs the message digest and the index of the leaf. The index is split in - * the tree index and the leaf index, for convenient copying to an address. - */ -void PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded) { -#define PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_TREE_BITS (PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_TREE_HEIGHT * (PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_D - 1)) -#define PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_TREE_BYTES ((PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_TREE_BITS + 7) / 8) -#define PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_LEAF_BITS PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_TREE_HEIGHT -#define PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_LEAF_BYTES ((PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_LEAF_BITS + 7) / 8) -#define PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_DGST_BYTES (PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_FORS_MSG_BYTES + PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_TREE_BYTES + PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_LEAF_BYTES) - - unsigned char buf[PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_DGST_BYTES]; - unsigned char *bufp = buf; - shake256incctx state; - - shake256_inc_init(&state); - shake256_inc_absorb(&state, R, PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_N); - shake256_inc_absorb(&state, pk, PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_PK_BYTES); - shake256_inc_absorb(&state, m, mlen); - shake256_inc_finalize(&state); - shake256_inc_squeeze(buf, PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_DGST_BYTES, &state); - shake256_inc_ctx_release(&state); - - memcpy(digest, bufp, PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_FORS_MSG_BYTES); - bufp += PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_FORS_MSG_BYTES; - - *tree = PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_bytes_to_ull( - bufp, PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_TREE_BYTES); - *tree &= (~(uint64_t)0) >> (64 - PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_TREE_BITS); - bufp += PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_TREE_BYTES; - - *leaf_idx = (uint32_t)PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_bytes_to_ull( - bufp, PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_LEAF_BYTES); - *leaf_idx &= (~(uint32_t)0) >> (32 - PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_LEAF_BITS); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_clean/hash_state.h b/src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_clean/hash_state.h deleted file mode 100644 index 7d92ef872a..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_clean/hash_state.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef SPX_HASH_STATE_H -#define SPX_HASH_STATE_H - -/** - * Defines the type of the hash function state. - * - * Don't be fooled into thinking this instance of SPHINCS+ isn't stateless! - * - * From Section 7.2.2 from the SPHINCS+ round-2 specification: - * - * Each of the instances of the tweakable hash function take PK.seed as its - * first input, which is constant for a given key pair – and, thus, across - * a single signature. This leads to a lot of redundant computation. To remedy - * this, we pad PK.seed to the length of a full 64-byte SHA-256 input block. - * Because of the Merkle-DamgÃ¥rd construction that underlies SHA-256, this - * allows for reuse of the intermediate SHA-256 state after the initial call to - * the compression function which improves performance. - * - * We pass this hash state around in functions, because otherwise we need to - * have a global variable. - * - * SHAKE256 does not need this state. Because this implementation is generated - * from a shared code base, we still need to specify some hash_state as it is - * still passed around. We chose to use an `int` as a placeholder for this - * purpose. - */ - -#define hash_state int - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_clean/params.h b/src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_clean/params.h deleted file mode 100644 index 17746ed8ca..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_clean/params.h +++ /dev/null @@ -1,53 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_PARAMS_H -#define PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_PARAMS_H - -/* Hash output length in bytes. */ -#define PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_N 16 -/* Height of the hypertree. */ -#define PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_FULL_HEIGHT 63 -/* Number of subtree layer. */ -#define PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_D 7 -/* FORS tree dimensions. */ -#define PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_FORS_HEIGHT 12 -#define PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_FORS_TREES 14 -/* Winternitz parameter, */ -#define PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_WOTS_W 16 - -/* The hash function is defined by linking a different hash.c file, as opposed - to setting a #define constant. */ - -/* For clarity */ -#define PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_ADDR_BYTES 32 - -/* WOTS parameters. */ -#define PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_WOTS_LOGW 4 - -#define PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_WOTS_LEN1 (8 * PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_N / PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_WOTS_LOGW) - -/* PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#define PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_WOTS_LEN2 3 - -#define PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_WOTS_LEN (PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_WOTS_LEN1 + PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_WOTS_LEN2) -#define PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_WOTS_BYTES (PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_WOTS_LEN * PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_N) -#define PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_WOTS_PK_BYTES PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_WOTS_BYTES - -/* Subtree size. */ -#define PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_TREE_HEIGHT (PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_FULL_HEIGHT / PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_D) - -/* FORS parameters. */ -#define PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_FORS_MSG_BYTES ((PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_FORS_TREES + 7) / 8) -#define PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_FORS_BYTES ((PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_FORS_HEIGHT + 1) * PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_FORS_TREES * PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_N) -#define PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_FORS_PK_BYTES PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_N - -/* Resulting SPX sizes. */ -#define PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_BYTES (PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_N + PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_FORS_BYTES + PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_D * PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_WOTS_BYTES +\ - PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_FULL_HEIGHT * PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_N) -#define PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_PK_BYTES (2 * PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_N) -#define PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_SK_BYTES (2 * PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_N + PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_PK_BYTES) - -/* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ -#define PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_OPTRAND_BYTES 32 - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_clean/sign.c b/src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_clean/sign.c deleted file mode 100644 index f9d1bbf7b8..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_clean/sign.c +++ /dev/null @@ -1,356 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "api.h" -#include "fors.h" -#include "hash.h" -#include "hash_state.h" -#include "params.h" -#include "randombytes.h" -#include "thash.h" -#include "utils.h" -#include "wots.h" - -/** - * Computes the leaf at a given address. First generates the WOTS key pair, - * then computes leaf by hashing horizontally. - */ -static void wots_gen_leaf(unsigned char *leaf, const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx, const uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - unsigned char pk[PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_WOTS_BYTES]; - uint32_t wots_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_set_type( - wots_addr, PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_set_type( - wots_pk_addr, PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_ADDR_TYPE_WOTSPK); - - PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_set_keypair_addr( - wots_addr, addr_idx); - PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_wots_gen_pk( - pk, sk_seed, pub_seed, wots_addr, hash_state_seeded); - - PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_copy_keypair_addr( - wots_pk_addr, wots_addr); - PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_thash_WOTS_LEN( - leaf, pk, pub_seed, wots_pk_addr, hash_state_seeded); -} - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_crypto_sign_secretkeybytes(void) { - return PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_CRYPTO_SECRETKEYBYTES; -} - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_crypto_sign_publickeybytes(void) { - return PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_CRYPTO_PUBLICKEYBYTES; -} - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_crypto_sign_bytes(void) { - return PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_CRYPTO_BYTES; -} - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_crypto_sign_seedbytes(void) { - return PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_CRYPTO_SEEDBYTES; -} - -/* - * Generates an SPX key pair given a seed of length - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed) { - /* We do not need the auth path in key generation, but it simplifies the - code to have just one treehash routine that computes both root and path - in one function. */ - unsigned char auth_path[PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_TREE_HEIGHT * PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_N]; - uint32_t top_tree_addr[8] = {0}; - hash_state hash_state_seeded; - - PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_set_layer_addr( - top_tree_addr, PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_D - 1); - PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_set_type( - top_tree_addr, PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_ADDR_TYPE_HASHTREE); - - /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ - memcpy(sk, seed, PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_CRYPTO_SEEDBYTES); - - memcpy(pk, sk + 2 * PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_N, PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_initialize_hash_function(&hash_state_seeded, pk, sk); - - /* Compute root node of the top-most subtree. */ - PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_treehash_TREE_HEIGHT( - sk + 3 * PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_N, auth_path, sk, sk + 2 * PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_N, 0, 0, - wots_gen_leaf, top_tree_addr, &hash_state_seeded); - - memcpy(pk + PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_N, sk + 3 * PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_N, PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_N); - - PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_destroy_hash_function(&hash_state_seeded); - return 0; -} - -/* - * Generates an SPX key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk) { - unsigned char seed[PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_CRYPTO_SEEDBYTES]; - randombytes(seed, PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_CRYPTO_SEEDBYTES); - PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_crypto_sign_seed_keypair( - pk, sk, seed); - - return 0; -} - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - const unsigned char *sk_seed = sk; - const unsigned char *sk_prf = sk + PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_N; - const unsigned char *pk = sk + 2 * PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_N; - const unsigned char *pub_seed = pk; - - unsigned char optrand[PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_N]; - unsigned char mhash[PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_FORS_MSG_BYTES]; - unsigned char root[PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_N]; - uint32_t i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - - hash_state hash_state_seeded; - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_initialize_hash_function( - &hash_state_seeded, - pub_seed, sk_seed); - - PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_set_type( - wots_addr, PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_set_type( - tree_addr, PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_ADDR_TYPE_HASHTREE); - - /* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ - randombytes(optrand, PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_N); - /* Compute the digest randomization value. */ - PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_gen_message_random( - sig, sk_prf, optrand, m, mlen, &hash_state_seeded); - - /* Derive the message digest and leaf index from R, PK and M. */ - PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_N; - - PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); - - /* Sign the message hash using FORS. */ - PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_fors_sign( - sig, root, mhash, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_FORS_BYTES; - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_D; i++) { - PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_set_tree_addr(tree_addr, tree); - - PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); - - /* Compute a WOTS signature. */ - PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_wots_sign( - sig, root, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_WOTS_BYTES; - - /* Compute the authentication path for the used WOTS leaf. */ - PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_treehash_TREE_HEIGHT( - root, sig, sk_seed, pub_seed, idx_leaf, 0, - wots_gen_leaf, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_TREE_HEIGHT * PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_TREE_HEIGHT; - } - - *siglen = PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_BYTES; - - PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_destroy_hash_function(&hash_state_seeded); - return 0; -} - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk) { - const unsigned char *pub_seed = pk; - const unsigned char *pub_root = pk + PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_N; - unsigned char mhash[PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_FORS_MSG_BYTES]; - unsigned char wots_pk[PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_WOTS_BYTES]; - unsigned char root[PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_N]; - unsigned char leaf[PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_N]; - unsigned int i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - hash_state hash_state_seeded; - - if (siglen != PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_BYTES) { - return -1; - } - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_initialize_hash_function( - &hash_state_seeded, - pub_seed, NULL); - - PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_set_type( - wots_addr, PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_set_type( - tree_addr, PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_ADDR_TYPE_HASHTREE); - PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_set_type( - wots_pk_addr, PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_ADDR_TYPE_WOTSPK); - - /* Derive the message digest and leaf index from R || PK || M. */ - /* The additional PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_N is a result of the hash domain separator. */ - PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_N; - - /* Layer correctly defaults to 0, so no need to set_layer_addr */ - PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); - - PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_fors_pk_from_sig( - root, sig, mhash, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_FORS_BYTES; - - /* For each subtree.. */ - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_D; i++) { - PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_set_tree_addr(tree_addr, tree); - - PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); - - PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_copy_keypair_addr( - wots_pk_addr, wots_addr); - - /* The WOTS public key is only correct if the signature was correct. */ - /* Initially, root is the FORS pk, but on subsequent iterations it is - the root of the subtree below the currently processed subtree. */ - PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_wots_pk_from_sig( - wots_pk, sig, root, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_WOTS_BYTES; - - /* Compute the leaf node using the WOTS public key. */ - PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_thash_WOTS_LEN( - leaf, wots_pk, pub_seed, wots_pk_addr, &hash_state_seeded); - - /* Compute the root node of this subtree. */ - PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_compute_root( - root, leaf, idx_leaf, 0, sig, PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_TREE_HEIGHT, - pub_seed, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_TREE_HEIGHT * PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_TREE_HEIGHT; - } - - PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_destroy_hash_function(&hash_state_seeded); - /* Check if the root node equals the root node in the public key. */ - if (memcmp(root, pub_root, PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_N) != 0) { - return -1; - } - - return 0; -} - - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - size_t siglen; - - PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_crypto_sign_signature( - sm, &siglen, m, mlen, sk); - - memmove(sm + PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_BYTES, m, mlen); - *smlen = siglen + mlen; - - return 0; -} - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk) { - /* The API caller does not necessarily know what size a signature should be - but SPHINCS+ signatures are always exactly PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_BYTES. */ - if (smlen < PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_BYTES) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - *mlen = smlen - PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_BYTES; - - if (PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_crypto_sign_verify( - sm, PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_BYTES, sm + PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_BYTES, *mlen, pk)) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - /* If verification was successful, move the message to the right place. */ - memmove(m, sm + PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_BYTES, *mlen); - - return 0; -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_clean/thash.h b/src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_clean/thash.h deleted file mode 100644 index ef878287cd..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_clean/thash.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_THASH_H -#define PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_THASH_H - -#include "hash_state.h" - -#include - -void PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_clean/thash_shake256_robust.c b/src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_clean/thash_shake256_robust.c deleted file mode 100644 index 29ea339dcb..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_clean/thash_shake256_robust.c +++ /dev/null @@ -1,81 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "thash.h" - -#include "fips202.h" - -/** - * Takes an array of inblocks concatenated arrays of PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_N bytes. - */ -static void PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_thash( - unsigned char *out, unsigned char *buf, - const unsigned char *in, unsigned int inblocks, - const unsigned char *pub_seed, uint32_t addr[8]) { - - unsigned char *bitmask = buf + PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_N + PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_ADDR_BYTES; - unsigned int i; - - memcpy(buf, pub_seed, PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_N); - PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_addr_to_bytes(buf + PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_N, addr); - - shake256(bitmask, inblocks * PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_N, buf, PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_N + PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_ADDR_BYTES); - - for (i = 0; i < inblocks * PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_N; i++) { - buf[PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_N + PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_ADDR_BYTES + i] = in[i] ^ bitmask[i]; - } - - shake256(out, PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_N, buf, PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_N + PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_N); -} - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_N + PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_ADDR_BYTES + 1 * PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_N]; - PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_thash( - out, buf, in, 1, pub_seed, addr); - - (void)hash_state_seeded; /* Avoid unused parameter warning. */ -} - -void PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_N + PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_ADDR_BYTES + 2 * PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_N]; - PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_thash( - out, buf, in, 2, pub_seed, addr); - - (void)hash_state_seeded; /* Avoid unused parameter warning. */ -} - -void PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_N + PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_ADDR_BYTES + PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_WOTS_LEN * PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_N]; - PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_thash( - out, buf, in, PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_WOTS_LEN, pub_seed, addr); - - (void)hash_state_seeded; /* Avoid unused parameter warning. */ -} - -void PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_N + PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_ADDR_BYTES + PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_FORS_TREES * PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_N]; - PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_thash( - out, buf, in, PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_FORS_TREES, pub_seed, addr); - - (void)hash_state_seeded; /* Avoid unused parameter warning. */ -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_clean/utils.c b/src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_clean/utils.c deleted file mode 100644 index 1ea4dc4679..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_clean/utils.c +++ /dev/null @@ -1,199 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "hash_state.h" -#include "params.h" -#include "thash.h" -#include "utils.h" - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in) { - - /* Iterate over out in decreasing order, for big-endianness. */ - for (size_t i = outlen; i > 0; i--) { - out[i - 1] = in & 0xff; - in = in >> 8; - } -} - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_bytes_to_ull( - const unsigned char *in, size_t inlen) { - unsigned long long retval = 0; - - for (size_t i = 0; i < inlen; i++) { - retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); - } - return retval; -} - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - uint32_t i; - unsigned char buffer[2 * PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_N]; - - /* If leaf_idx is odd (last bit = 1), current path element is a right child - and auth_path has to go left. Otherwise it is the other way around. */ - if (leaf_idx & 1) { - memcpy(buffer + PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_N, leaf, PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_N); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_N); - } else { - memcpy(buffer, leaf, PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_N); - memcpy(buffer + PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_N, auth_path, PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_N); - } - auth_path += PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_N; - - for (i = 0; i < tree_height - 1; i++) { - leaf_idx >>= 1; - idx_offset >>= 1; - /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_set_tree_height(addr, i + 1); - PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_set_tree_index( - addr, leaf_idx + idx_offset); - - /* Pick the right or left neighbor, depending on parity of the node. */ - if (leaf_idx & 1) { - PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_thash_2( - buffer + PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_N, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_N); - } else { - PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_thash_2( - buffer, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer + PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_N, auth_path, PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_N); - } - auth_path += PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_N; - } - - /* The last iteration is exceptional; we do not copy an auth_path node. */ - leaf_idx >>= 1; - idx_offset >>= 1; - PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_set_tree_height(addr, tree_height); - PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_set_tree_index( - addr, leaf_idx + idx_offset); - PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_thash_2( - root, buffer, pub_seed, addr, hash_state_seeded); -} - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -static void PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_treehash( - unsigned char *root, unsigned char *auth_path, - unsigned char *stack, unsigned int *heights, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - - unsigned int offset = 0; - uint32_t idx; - uint32_t tree_idx; - - for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { - /* Add the next leaf node to the stack. */ - gen_leaf(stack + offset * PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_N, - sk_seed, pub_seed, idx + idx_offset, tree_addr, - hash_state_seeded); - offset++; - heights[offset - 1] = 0; - - /* If this is a node we need for the auth path.. */ - if ((leaf_idx ^ 0x1) == idx) { - memcpy(auth_path, stack + (offset - 1)*PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_N, PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_N); - } - - /* While the top-most nodes are of equal height.. */ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { - /* Compute index of the new node, in the next layer. */ - tree_idx = (idx >> (heights[offset - 1] + 1)); - - /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_set_tree_height( - tree_addr, heights[offset - 1] + 1); - PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_set_tree_index( - tree_addr, tree_idx + (idx_offset >> (heights[offset - 1] + 1))); - /* Hash the top-most nodes from the stack together. */ - PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_thash_2( - stack + (offset - 2)*PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_N, stack + (offset - 2)*PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_N, - pub_seed, tree_addr, hash_state_seeded); - offset--; - /* Note that the top-most node is now one layer higher. */ - heights[offset - 1]++; - - /* If this is a node we need for the auth path.. */ - if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_path + heights[offset - 1]*PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_N, - stack + (offset - 1)*PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_N, PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_N); - } - } - } - memcpy(root, stack, PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_N); -} - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_FORS_HEIGHT + 1)*PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_N]; - unsigned int heights[PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_FORS_HEIGHT + 1]; - - PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_FORS_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_TREE_HEIGHT + 1)*PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_N]; - unsigned int heights[PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_TREE_HEIGHT + 1]; - - PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_TREE_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_clean/utils.h b/src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_clean/utils.h deleted file mode 100644 index 8647177fde..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_clean/utils.h +++ /dev/null @@ -1,64 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_UTILS_H -#define PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_UTILS_H - -#include "hash_state.h" -#include "params.h" -#include -#include - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in); - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_bytes_to_ull( - const unsigned char *in, size_t inlen); - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -void PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_clean/wots.c b/src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_clean/wots.c deleted file mode 100644 index 5758edcbe3..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_clean/wots.c +++ /dev/null @@ -1,167 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "hash_state.h" -#include "params.h" -#include "thash.h" -#include "utils.h" -#include "wots.h" - -// TODO clarify address expectations, and make them more uniform. -// TODO i.e. do we expect types to be set already? -// TODO and do we expect modifications or copies? - -/** - * Computes the starting value for a chain, i.e. the secret key. - * Expects the address to be complete up to the chain address. - */ -static void wots_gen_sk(unsigned char *sk, const unsigned char *sk_seed, - uint32_t wots_addr[8], - const hash_state *hash_state_seeded) { - /* Make sure that the hash address is actually zeroed. */ - PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_set_hash_addr(wots_addr, 0); - - /* Generate sk element. */ - PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_prf_addr(sk, sk_seed, wots_addr, hash_state_seeded); -} - -/** - * Computes the chaining function. - * out and in have to be n-byte arrays. - * - * Interprets in as start-th value of the chain. - * addr has to contain the address of the chain. - */ -static void gen_chain(unsigned char *out, const unsigned char *in, - unsigned int start, unsigned int steps, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - uint32_t i; - - /* Initialize out with the value at position 'start'. */ - memcpy(out, in, PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_N); - - /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_WOTS_W; i++) { - PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_set_hash_addr(addr, i); - PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_thash_1( - out, out, pub_seed, addr, hash_state_seeded); - } -} - -/** - * base_w algorithm as described in draft. - * Interprets an array of bytes as integers in base w. - * This only works when log_w is a divisor of 8. - */ -static void base_w(unsigned int *output, const size_t out_len, - const unsigned char *input) { - size_t in = 0; - size_t out = 0; - unsigned char total = 0; - unsigned int bits = 0; - size_t consumed; - - for (consumed = 0; consumed < out_len; consumed++) { - if (bits == 0) { - total = input[in]; - in++; - bits += 8; - } - bits -= PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_WOTS_LOGW; - output[out] = (unsigned int)((total >> bits) & (PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_WOTS_W - 1)); - out++; - } -} - -/* Computes the WOTS+ checksum over a message (in base_w). */ -static void wots_checksum(unsigned int *csum_base_w, - const unsigned int *msg_base_w) { - unsigned int csum = 0; - unsigned char csum_bytes[(PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_WOTS_LEN2 * PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_WOTS_LOGW + 7) / 8]; - unsigned int i; - - /* Compute checksum. */ - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_WOTS_LEN1; i++) { - csum += PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_WOTS_W - 1 - msg_base_w[i]; - } - - /* Convert checksum to base_w. */ - /* Make sure expected empty zero bits are the least significant bits. */ - csum = csum << (8 - ((PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_WOTS_LEN2 * PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_WOTS_LOGW) % 8)); - PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_ull_to_bytes( - csum_bytes, sizeof(csum_bytes), csum); - base_w(csum_base_w, PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_WOTS_LEN2, csum_bytes); -} - -/* Takes a message and derives the matching chain lengths. */ -static void chain_lengths(unsigned int *lengths, const unsigned char *msg) { - base_w(lengths, PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_WOTS_LEN1, msg); - wots_checksum(lengths + PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_WOTS_LEN1, lengths); -} - -/** - * WOTS key generation. Takes a 32 byte sk_seed, expands it to WOTS private key - * elements and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_wots_gen_pk( - unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - uint32_t i; - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_WOTS_LEN; i++) { - PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_set_chain_addr(addr, i); - wots_gen_sk(pk + i * PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_N, sk_seed, addr, hash_state_seeded); - gen_chain(pk + i * PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_N, pk + i * PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_N, - 0, PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_WOTS_W - 1, pub_seed, addr, hash_state_seeded); - } -} - -/** - * Takes a n-byte message and the 32-byte sk_see to compute a signature 'sig'. - */ -void PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_wots_sign( - unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *hash_state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_WOTS_LEN; i++) { - PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_set_chain_addr(addr, i); - wots_gen_sk(sig + i * PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_N, sk_seed, addr, hash_state_seeded); - gen_chain(sig + i * PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_N, sig + i * PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_N, 0, lengths[i], pub_seed, addr, hash_state_seeded); - } -} - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_wots_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_WOTS_LEN; i++) { - PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_set_chain_addr(addr, i); - gen_chain(pk + i * PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_N, sig + i * PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_N, - lengths[i], PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_WOTS_W - 1 - lengths[i], pub_seed, addr, - hash_state_seeded); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_clean/wots.h b/src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_clean/wots.h deleted file mode 100644 index d250b481e7..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128s-robust_clean/wots.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_WOTS_H -#define PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_WOTS_H - -#include "hash_state.h" -#include "params.h" -#include - -/** - * WOTS key generation. Takes a 32 byte seed for the private key, expands it to - * a full WOTS private key and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_wots_gen_pk( - unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -/** - * Takes a n-byte message and the 32-byte seed for the private key to compute a - * signature that is placed at 'sig'. - */ -void PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_wots_sign( - unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *hash_state_seeded); - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_wots_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_avx2/LICENSE b/src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_avx2/LICENSE deleted file mode 100644 index 670154e353..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_avx2/LICENSE +++ /dev/null @@ -1,116 +0,0 @@ -CC0 1.0 Universal - -Statement of Purpose - -The laws of most jurisdictions throughout the world automatically confer -exclusive Copyright and Related Rights (defined below) upon the creator and -subsequent owner(s) (each and all, an "owner") of an original work of -authorship and/or a database (each, a "Work"). - -Certain owners wish to permanently relinquish those rights to a Work for the -purpose of contributing to a commons of creative, cultural and scientific -works ("Commons") that the public can reliably and without fear of later -claims of infringement build upon, modify, incorporate in other works, reuse -and redistribute as freely as possible in any form whatsoever and for any -purposes, including without limitation commercial purposes. These owners may -contribute to the Commons to promote the ideal of a free culture and the -further production of creative, cultural and scientific works, or to gain -reputation or greater distribution for their Work in part through the use and -efforts of others. - -For these and/or other purposes and motivations, and without any expectation -of additional consideration or compensation, the person associating CC0 with a -Work (the "Affirmer"), to the extent that he or she is an owner of Copyright -and Related Rights in the Work, voluntarily elects to apply CC0 to the Work -and publicly distribute the Work under its terms, with knowledge of his or her -Copyright and Related Rights in the Work and the meaning and intended legal -effect of CC0 on those rights. - -1. Copyright and Related Rights. A Work made available under CC0 may be -protected by copyright and related or neighboring rights ("Copyright and -Related Rights"). Copyright and Related Rights include, but are not limited -to, the following: - - i. the right to reproduce, adapt, distribute, perform, display, communicate, - and translate a Work; - - ii. moral rights retained by the original author(s) and/or performer(s); - - iii. publicity and privacy rights pertaining to a person's image or likeness - depicted in a Work; - - iv. rights protecting against unfair competition in regards to a Work, - subject to the limitations in paragraph 4(a), below; - - v. rights protecting the extraction, dissemination, use and reuse of data in - a Work; - - vi. database rights (such as those arising under Directive 96/9/EC of the - European Parliament and of the Council of 11 March 1996 on the legal - protection of databases, and under any national implementation thereof, - including any amended or successor version of such directive); and - - vii. other similar, equivalent or corresponding rights throughout the world - based on applicable law or treaty, and any national implementations thereof. - -2. Waiver. To the greatest extent permitted by, but not in contravention of, -applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and -unconditionally waives, abandons, and surrenders all of Affirmer's Copyright -and Related Rights and associated claims and causes of action, whether now -known or unknown (including existing as well as future claims and causes of -action), in the Work (i) in all territories worldwide, (ii) for the maximum -duration provided by applicable law or treaty (including future time -extensions), (iii) in any current or future medium and for any number of -copies, and (iv) for any purpose whatsoever, including without limitation -commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes -the Waiver for the benefit of each member of the public at large and to the -detriment of Affirmer's heirs and successors, fully intending that such Waiver -shall not be subject to revocation, rescission, cancellation, termination, or -any other legal or equitable action to disrupt the quiet enjoyment of the Work -by the public as contemplated by Affirmer's express Statement of Purpose. - -3. Public License Fallback. Should any part of the Waiver for any reason be -judged legally invalid or ineffective under applicable law, then the Waiver -shall be preserved to the maximum extent permitted taking into account -Affirmer's express Statement of Purpose. In addition, to the extent the Waiver -is so judged Affirmer hereby grants to each affected person a royalty-free, -non transferable, non sublicensable, non exclusive, irrevocable and -unconditional license to exercise Affirmer's Copyright and Related Rights in -the Work (i) in all territories worldwide, (ii) for the maximum duration -provided by applicable law or treaty (including future time extensions), (iii) -in any current or future medium and for any number of copies, and (iv) for any -purpose whatsoever, including without limitation commercial, advertising or -promotional purposes (the "License"). The License shall be deemed effective as -of the date CC0 was applied by Affirmer to the Work. Should any part of the -License for any reason be judged legally invalid or ineffective under -applicable law, such partial invalidity or ineffectiveness shall not -invalidate the remainder of the License, and in such case Affirmer hereby -affirms that he or she will not (i) exercise any of his or her remaining -Copyright and Related Rights in the Work or (ii) assert any associated claims -and causes of action with respect to the Work, in either case contrary to -Affirmer's express Statement of Purpose. - -4. Limitations and Disclaimers. - - a. No trademark or patent rights held by Affirmer are waived, abandoned, - surrendered, licensed or otherwise affected by this document. - - b. Affirmer offers the Work as-is and makes no representations or warranties - of any kind concerning the Work, express, implied, statutory or otherwise, - including without limitation warranties of title, merchantability, fitness - for a particular purpose, non infringement, or the absence of latent or - other defects, accuracy, or the present or absence of errors, whether or not - discoverable, all to the greatest extent permissible under applicable law. - - c. Affirmer disclaims responsibility for clearing rights of other persons - that may apply to the Work or any use thereof, including without limitation - any person's Copyright and Related Rights in the Work. Further, Affirmer - disclaims responsibility for obtaining any necessary consents, permissions - or other rights required for any use of the Work. - - d. Affirmer understands and acknowledges that Creative Commons is not a - party to this document and has no duty or obligation with respect to this - CC0 or use of the Work. - -For more information, please see - diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_avx2/address.c b/src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_avx2/address.c deleted file mode 100644 index ee01ccd073..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_avx2/address.c +++ /dev/null @@ -1,78 +0,0 @@ -#include - -#include "address.h" -#include "params.h" -#include "utils.h" - -void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]) { - int i; - - for (i = 0; i < 8; i++) { - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_ull_to_bytes( - bytes + i * 4, 4, addr[i]); - } -} - -void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_set_layer_addr( - uint32_t addr[8], uint32_t layer) { - addr[0] = layer; -} - -void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_set_tree_addr( - uint32_t addr[8], uint64_t tree) { - addr[1] = 0; - addr[2] = (uint32_t) (tree >> 32); - addr[3] = (uint32_t) tree; -} - -void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_set_type( - uint32_t addr[8], uint32_t type) { - addr[4] = type; -} - -void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; -} - -/* These functions are used for OTS addresses. */ - -void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_set_keypair_addr( - uint32_t addr[8], uint32_t keypair) { - addr[5] = keypair; -} - -void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; - out[5] = in[5]; -} - -void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_set_chain_addr( - uint32_t addr[8], uint32_t chain) { - addr[6] = chain; -} - -void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_set_hash_addr( - uint32_t addr[8], uint32_t hash) { - addr[7] = hash; -} - -/* These functions are used for all hash tree addresses (including FORS). */ - -void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_set_tree_height( - uint32_t addr[8], uint32_t tree_height) { - addr[6] = tree_height; -} - -void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_set_tree_index( - uint32_t addr[8], uint32_t tree_index) { - addr[7] = tree_index; -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_avx2/address.h b/src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_avx2/address.h deleted file mode 100644 index bdc869a785..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_avx2/address.h +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_ADDRESS_H -#define PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_ADDRESS_H - -#include - -#define PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_ADDR_TYPE_WOTS 0 -#define PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_ADDR_TYPE_WOTSPK 1 -#define PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_ADDR_TYPE_HASHTREE 2 -#define PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_ADDR_TYPE_FORSTREE 3 -#define PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_ADDR_TYPE_FORSPK 4 - -void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]); - -void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_set_layer_addr( - uint32_t addr[8], uint32_t layer); - -void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_set_tree_addr( - uint32_t addr[8], uint64_t tree); - -void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_set_type( - uint32_t addr[8], uint32_t type); - -/* Copies the layer and tree part of one address into the other */ -void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for WOTS and FORS addresses. */ - -void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_set_keypair_addr( - uint32_t addr[8], uint32_t keypair); - -void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_set_chain_addr( - uint32_t addr[8], uint32_t chain); - -void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_set_hash_addr( - uint32_t addr[8], uint32_t hash); - -void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for all hash tree addresses (including FORS). */ - -void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_set_tree_height( - uint32_t addr[8], uint32_t tree_height); - -void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_set_tree_index( - uint32_t addr[8], uint32_t tree_index); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_avx2/api.h b/src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_avx2/api.h deleted file mode 100644 index 4206b29499..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_avx2/api.h +++ /dev/null @@ -1,81 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_API_H -#define PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_API_H - -#include -#include - - - -#define PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_CRYPTO_ALGNAME "SPHINCS+" - -#define PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_CRYPTO_SECRETKEYBYTES 64 -#define PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_CRYPTO_PUBLICKEYBYTES 32 -#define PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_CRYPTO_BYTES 7856 -#define PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_CRYPTO_SEEDBYTES 48 - - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_avx2/fors.c b/src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_avx2/fors.c deleted file mode 100644 index 572a45b175..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_avx2/fors.c +++ /dev/null @@ -1,206 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "fors.h" -#include "hash.h" -#include "hashx4.h" -#include "thash.h" -#include "thashx4.h" -#include "utils.h" -#include "utilsx4.h" - -static void fors_gen_skx4(unsigned char *sk0, - unsigned char *sk1, - unsigned char *sk2, - unsigned char *sk3, const unsigned char *sk_seed, - uint32_t fors_leaf_addrx4[4 * 8], - const hash_state *state_seeded) { - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_prf_addrx4(sk0, sk1, sk2, sk3, sk_seed, fors_leaf_addrx4, state_seeded); -} - -static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, - const unsigned char *pub_seed, - uint32_t fors_leaf_addr[8], const hash_state *state_seeded) { - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_thash_1(leaf, sk, pub_seed, fors_leaf_addr, state_seeded); -} - -static void fors_sk_to_leafx4(unsigned char *leaf0, - unsigned char *leaf1, - unsigned char *leaf2, - unsigned char *leaf3, - const unsigned char *sk0, - const unsigned char *sk1, - const unsigned char *sk2, - const unsigned char *sk3, - const unsigned char *pub_seed, - uint32_t fors_leaf_addrx4[4 * 8], - const hash_state *state_seeded) { - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_thashx4_1(leaf0, leaf1, leaf2, leaf3, - sk0, sk1, sk2, sk3, pub_seed, fors_leaf_addrx4, state_seeded); -} - -static void fors_gen_leafx4(unsigned char *leaf0, - unsigned char *leaf1, - unsigned char *leaf2, - unsigned char *leaf3, - const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx0, - uint32_t addr_idx1, - uint32_t addr_idx2, - uint32_t addr_idx3, - const uint32_t fors_tree_addr[8], - const hash_state *state_seeded) { - uint32_t fors_leaf_addrx4[4 * 8] = {0}; - unsigned int j; - - /* Only copy the parts that must be kept in fors_leaf_addrx4. */ - for (j = 0; j < 4; j++) { - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_copy_keypair_addr(fors_leaf_addrx4 + j * 8, fors_tree_addr); - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_set_type(fors_leaf_addrx4 + j * 8, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_ADDR_TYPE_FORSTREE); - } - - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_set_tree_index(fors_leaf_addrx4 + 0 * 8, addr_idx0); - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_set_tree_index(fors_leaf_addrx4 + 1 * 8, addr_idx1); - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_set_tree_index(fors_leaf_addrx4 + 2 * 8, addr_idx2); - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_set_tree_index(fors_leaf_addrx4 + 3 * 8, addr_idx3); - - fors_gen_skx4(leaf0, leaf1, leaf2, leaf3, sk_seed, fors_leaf_addrx4, state_seeded); - fors_sk_to_leafx4(leaf0, leaf1, leaf2, leaf3, - leaf0, leaf1, leaf2, leaf3, pub_seed, fors_leaf_addrx4, state_seeded); -} - -/** - * Interprets m as PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_FORS_HEIGHT-bit unsigned integers. - * Assumes m contains at least PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_FORS_TREES bits. - * Assumes indices has space for PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_FORS_TREES integers. - */ -static void message_to_indices(uint32_t *indices, const unsigned char *m) { - unsigned int i, j; - unsigned int offset = 0; - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_FORS_TREES; i++) { - indices[i] = 0; - for (j = 0; j < PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_FORS_HEIGHT; j++) { - indices[i] ^= (((uint32_t)m[offset >> 3] >> (offset & 0x7)) & 0x1) << j; - offset++; - } - } -} - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *state_seeded) { - /* Round up to multiple of 4 to prevent out-of-bounds for x4 parallelism */ - uint32_t indices[(PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_FORS_TREES + 3) & ~3] = {0}; - unsigned char roots[((PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_FORS_TREES + 3) & ~3) * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N]; - /* Sign to a buffer, since we may not have a nice multiple of 4 and would - otherwise overrun the signature. */ - unsigned char sigbufx4[4 * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N * (1 + PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_FORS_HEIGHT)]; - uint32_t fors_tree_addrx4[4 * 8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset[4] = {0}; - unsigned int i, j; - - for (j = 0; j < 4; j++) { - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_copy_keypair_addr(fors_tree_addrx4 + j * 8, fors_addr); - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_set_type(fors_tree_addrx4 + j * 8, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_ADDR_TYPE_FORSTREE); - } - - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_copy_keypair_addr(fors_pk_addr, fors_addr); - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_set_type(fors_pk_addr, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < ((PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_FORS_TREES + 3) & ~0x3); i += 4) { - for (j = 0; j < 4; j++) { - if (i + j < PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_FORS_TREES) { - idx_offset[j] = (i + j) * (1 << PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_FORS_HEIGHT); - - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_set_tree_height(fors_tree_addrx4 + j * 8, 0); - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_set_tree_index(fors_tree_addrx4 + j * 8, - indices[i + j] + idx_offset[j]); - } - } - - /* Include the secret key part that produces the selected leaf nodes. */ - fors_gen_skx4(sigbufx4 + 0 * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N, - sigbufx4 + 1 * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N, - sigbufx4 + 2 * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N, - sigbufx4 + 3 * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N, - sk_seed, fors_tree_addrx4, state_seeded); - - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_treehashx4_FORS_HEIGHT(roots + i * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N, sigbufx4 + 4 * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N, sk_seed, pub_seed, - &indices[i], idx_offset, fors_gen_leafx4, fors_tree_addrx4, - state_seeded); - - for (j = 0; j < 4; j++) { - if (i + j < PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_FORS_TREES) { - memcpy(sig, sigbufx4 + j * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N); - memcpy(sig + PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N, - sigbufx4 + 4 * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N + j * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_FORS_HEIGHT, - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_FORS_HEIGHT); - sig += PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N * (1 + PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_FORS_HEIGHT); - } - } - } - - /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_thash_FORS_TREES(pk, roots, pub_seed, fors_pk_addr, state_seeded); -} - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, - const uint32_t fors_addr[8], - const hash_state *state_seeded) { - uint32_t indices[PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_FORS_TREES]; - unsigned char roots[PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_FORS_TREES * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N]; - unsigned char leaf[PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N]; - uint32_t fors_tree_addr[8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_copy_keypair_addr(fors_tree_addr, fors_addr); - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_copy_keypair_addr(fors_pk_addr, fors_addr); - - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_set_type(fors_tree_addr, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_set_type(fors_pk_addr, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_FORS_TREES; i++) { - idx_offset = i * (1 << PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_FORS_HEIGHT); - - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_set_tree_height(fors_tree_addr, 0); - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Derive the leaf from the included secret key part. */ - fors_sk_to_leaf(leaf, sig, pub_seed, fors_tree_addr, state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N; - - /* Derive the corresponding root node of this tree. */ - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_compute_root(roots + i * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N, leaf, indices[i], idx_offset, - sig, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_FORS_HEIGHT, pub_seed, fors_tree_addr, - state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_thash_FORS_TREES(pk, roots, pub_seed, fors_pk_addr, state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_avx2/fors.h b/src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_avx2/fors.h deleted file mode 100644 index 769215eb6f..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_avx2/fors.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_FORS_H -#define PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_FORS_H - -#include - -#include "hash_state.h" -#include "params.h" - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_fors_sign( - unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *hash_state_seeded); - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_fors_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, const uint32_t fors_addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_avx2/hash.h b/src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_avx2/hash.h deleted file mode 100644 index 87de0a7241..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_avx2/hash.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_HASH_H -#define PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_HASH_H - -#include "hash_state.h" - -#include -#include - -void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_initialize_hash_function( - hash_state *hash_state_seeded, - const unsigned char *pub_seed, const unsigned char *sk_seed); - -void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_destroy_hash_function(hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_avx2/hash_shake256.c b/src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_avx2/hash_shake256.c deleted file mode 100644 index 15ed03b37e..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_avx2/hash_shake256.c +++ /dev/null @@ -1,106 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "utils.h" - -#include "fips202.h" - -/* For SHAKE256, there is no immediate reason to initialize at the start, - so this function is an empty operation. */ -void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_initialize_hash_function( - hash_state *hash_state_seeded, // NOLINT(readability-non-const-parameter) - const unsigned char *pub_seed, const unsigned char *sk_seed) { - (void)hash_state_seeded; /* Suppress an 'unused parameter' warning. */ - (void)pub_seed; /* Suppress an 'unused parameter' warning. */ - (void)sk_seed; /* Suppress an 'unused parameter' warning. */ -} - -/* This is not necessary for SHAKE256, so we don't do anything */ -void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_destroy_hash_function( - hash_state *hash_state_seeded) { // NOLINT(readability-non-const-parameter) - (void)hash_state_seeded; -} - -/* - * Computes PRF(key, addr), given a secret key of PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N bytes and an address - */ -void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded) { - unsigned char buf[PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_ADDR_BYTES]; - - memcpy(buf, key, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N); - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_addr_to_bytes(buf + PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N, addr); - - shake256(out, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N, buf, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_ADDR_BYTES); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} - -/** - * Computes the message-dependent randomness R, using a secret seed and an - * optional randomization value as well as the message. - */ -void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded) { - shake256incctx state; - - shake256_inc_init(&state); - shake256_inc_absorb(&state, sk_prf, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N); - shake256_inc_absorb(&state, optrand, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N); - shake256_inc_absorb(&state, m, mlen); - shake256_inc_finalize(&state); - shake256_inc_squeeze(R, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N, &state); - shake256_inc_ctx_release(&state); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} - -/** - * Computes the message hash using R, the public key, and the message. - * Outputs the message digest and the index of the leaf. The index is split in - * the tree index and the leaf index, for convenient copying to an address. - */ -void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded) { -#define PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_TREE_BITS (PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_TREE_HEIGHT * (PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_D - 1)) -#define PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_TREE_BYTES ((PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_TREE_BITS + 7) / 8) -#define PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_LEAF_BITS PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_TREE_HEIGHT -#define PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_LEAF_BYTES ((PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_LEAF_BITS + 7) / 8) -#define PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_DGST_BYTES (PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_FORS_MSG_BYTES + PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_TREE_BYTES + PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_LEAF_BYTES) - - unsigned char buf[PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_DGST_BYTES]; - unsigned char *bufp = buf; - shake256incctx state; - - shake256_inc_init(&state); - shake256_inc_absorb(&state, R, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N); - shake256_inc_absorb(&state, pk, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_PK_BYTES); - shake256_inc_absorb(&state, m, mlen); - shake256_inc_finalize(&state); - shake256_inc_squeeze(buf, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_DGST_BYTES, &state); - shake256_inc_ctx_release(&state); - - memcpy(digest, bufp, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_FORS_MSG_BYTES); - bufp += PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_FORS_MSG_BYTES; - - *tree = PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_bytes_to_ull( - bufp, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_TREE_BYTES); - *tree &= (~(uint64_t)0) >> (64 - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_TREE_BITS); - bufp += PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_TREE_BYTES; - - *leaf_idx = (uint32_t)PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_bytes_to_ull( - bufp, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_LEAF_BYTES); - *leaf_idx &= (~(uint32_t)0) >> (32 - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_LEAF_BITS); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_avx2/hash_shake256x4.c b/src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_avx2/hash_shake256x4.c deleted file mode 100644 index 26f6438559..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_avx2/hash_shake256x4.c +++ /dev/null @@ -1,38 +0,0 @@ -#include -#include - -#include "address.h" -#include "fips202x4.h" -#include "hashx4.h" -#include "params.h" - -/* - * 4-way parallel version of prf_addr; takes 4x as much input and output - */ -void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_prf_addrx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const unsigned char *key, - const uint32_t addrx4[4 * 8], - const hash_state *state_seeded) { - unsigned char bufx4[4 * (PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_ADDR_BYTES)]; - unsigned int j; - - for (j = 0; j < 4; j++) { - memcpy(bufx4 + j * (PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_ADDR_BYTES), key, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N); - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_addr_to_bytes(bufx4 + PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N + j * (PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_ADDR_BYTES), addrx4 + j * 8); - } - - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_shake256x4(out0, - out1, - out2, - out3, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N, - bufx4 + 0 * (PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_ADDR_BYTES), - bufx4 + 1 * (PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_ADDR_BYTES), - bufx4 + 2 * (PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_ADDR_BYTES), - bufx4 + 3 * (PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_ADDR_BYTES), PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_ADDR_BYTES); - - /* Avoid unused parameter warning */ - (void)state_seeded; -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_avx2/hash_state.h b/src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_avx2/hash_state.h deleted file mode 100644 index 5a3baad30f..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_avx2/hash_state.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_HASH_STATE_H -#define PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_HASH_STATE_H - -/** - * Defines the type of the hash function state. - * - * Don't be fooled into thinking this instance of SPHINCS+ isn't stateless! - * - * From Section 7.2.2 from the SPHINCS+ round-2 specification: - * - * Each of the instances of the tweakable hash function take PK.seed as its - * first input, which is constant for a given key pair – and, thus, across - * a single signature. This leads to a lot of redundant computation. To remedy - * this, we pad PK.seed to the length of a full 64-byte SHA-256 input block. - * Because of the Merkle-DamgÃ¥rd construction that underlies SHA-256, this - * allows for reuse of the intermediate SHA-256 state after the initial call to - * the compression function which improves performance. - * - * We pass this hash state around in functions, because otherwise we need to - * have a global variable. - * - * SHAKE256 does not need this state. Because this implementation is generated - * from a shared code base, we still need to specify some hash_state as it is - * still passed around. We chose to use an `int` as a placeholder for this - * purpose. - */ - -typedef int hash_state; - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_avx2/hashx4.h b/src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_avx2/hashx4.h deleted file mode 100644 index 7b3e1b76c9..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_avx2/hashx4.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_HASHX4_H -#define PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_HASHX4_H - -#include - -#include "hash_state.h" - -void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_prf_addrx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const unsigned char *key, - const uint32_t addrx4[4 * 8], - const hash_state *state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_avx2/params.h b/src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_avx2/params.h deleted file mode 100644 index e5eb8b52c9..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_avx2/params.h +++ /dev/null @@ -1,53 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_PARAMS_H -#define PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_PARAMS_H - -/* Hash output length in bytes. */ -#define PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N 16 -/* Height of the hypertree. */ -#define PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_FULL_HEIGHT 63 -/* Number of subtree layer. */ -#define PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_D 7 -/* FORS tree dimensions. */ -#define PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_FORS_HEIGHT 12 -#define PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_FORS_TREES 14 -/* Winternitz parameter, */ -#define PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_WOTS_W 16 - -/* The hash function is defined by linking a different hash.c file, as opposed - to setting a #define constant. */ - -/* For clarity */ -#define PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_ADDR_BYTES 32 - -/* WOTS parameters. */ -#define PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_WOTS_LOGW 4 - -#define PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_WOTS_LEN1 (8 * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N / PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_WOTS_LOGW) - -/* PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#define PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_WOTS_LEN2 3 - -#define PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_WOTS_LEN (PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_WOTS_LEN1 + PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_WOTS_LEN2) -#define PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_WOTS_BYTES (PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_WOTS_LEN * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N) -#define PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_WOTS_PK_BYTES PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_WOTS_BYTES - -/* Subtree size. */ -#define PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_TREE_HEIGHT (PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_FULL_HEIGHT / PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_D) - -/* FORS parameters. */ -#define PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_FORS_MSG_BYTES ((PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_FORS_TREES + 7) / 8) -#define PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_FORS_BYTES ((PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_FORS_HEIGHT + 1) * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_FORS_TREES * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N) -#define PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_FORS_PK_BYTES PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N - -/* Resulting SPX sizes. */ -#define PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_BYTES (PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_FORS_BYTES + PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_D * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_WOTS_BYTES +\ - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_FULL_HEIGHT * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N) -#define PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_PK_BYTES (2 * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N) -#define PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_SK_BYTES (2 * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_PK_BYTES) - -/* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ -#define PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_OPTRAND_BYTES 32 - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_avx2/sign.c b/src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_avx2/sign.c deleted file mode 100644 index 6c114dbddf..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_avx2/sign.c +++ /dev/null @@ -1,409 +0,0 @@ -#include -#include -#include -#include - -#include "address.h" -#include "api.h" -#include "fors.h" -#include "hash.h" -#include "hash_state.h" -#include "params.h" -#include "randombytes.h" -#include "thash.h" -#include "utils.h" -#include "wots.h" - - -/** - * Computes the leaf at a given address. First generates the WOTS key pair, - * then computes leaf by hashing horizontally. - */ -static void wots_gen_leaf(unsigned char *leaf, const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx, const uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - unsigned char pk[PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_WOTS_BYTES]; - uint32_t wots_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_set_type( - wots_addr, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_set_type( - wots_pk_addr, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_ADDR_TYPE_WOTSPK); - - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_set_keypair_addr( - wots_addr, addr_idx); - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_wots_gen_pk( - pk, sk_seed, pub_seed, wots_addr, hash_state_seeded); - - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_copy_keypair_addr( - wots_pk_addr, wots_addr); - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_thash_WOTS_LEN( - leaf, pk, pub_seed, wots_pk_addr, hash_state_seeded); -} - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_crypto_sign_secretkeybytes(void) { - return PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_CRYPTO_SECRETKEYBYTES; -} - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_crypto_sign_publickeybytes(void) { - return PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_CRYPTO_PUBLICKEYBYTES; -} - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_crypto_sign_bytes(void) { - return PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_CRYPTO_BYTES; -} - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_crypto_sign_seedbytes(void) { - return PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_CRYPTO_SEEDBYTES; -} - -/* - * Generates an SPX key pair given a seed of length - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed) { - /* We do not need the auth path in key generation, but it simplifies the - code to have just one treehash routine that computes both root and path - in one function. */ - unsigned char auth_path[PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_TREE_HEIGHT * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N]; - uint32_t top_tree_addr[8] = {0}; - hash_state hash_state_seeded; - - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_set_layer_addr( - top_tree_addr, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_D - 1); - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_set_type( - top_tree_addr, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_ADDR_TYPE_HASHTREE); - - /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ - memcpy(sk, seed, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_CRYPTO_SEEDBYTES); - - memcpy(pk, sk + 2 * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_initialize_hash_function(&hash_state_seeded, pk, sk); - - /* Compute root node of the top-most subtree. */ - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_treehash_TREE_HEIGHT( - sk + 3 * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N, auth_path, sk, sk + 2 * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N, 0, 0, - wots_gen_leaf, top_tree_addr, &hash_state_seeded); - - memcpy(pk + PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N, sk + 3 * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N); - - return 0; -} - -/* - * Generates an SPX key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk) { - - // guarantee alignment of pk - union { - __m128 _x[PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_CRYPTO_PUBLICKEYBYTES / 16]; - uint8_t pk[PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_CRYPTO_PUBLICKEYBYTES]; - } aligned_pk; - - // guarantee alignment of sk - union { - __m128 _x[PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_CRYPTO_SECRETKEYBYTES / 16]; - uint8_t sk[PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_CRYPTO_SECRETKEYBYTES]; - } aligned_sk; - - union { - __m128 _x[PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_CRYPTO_SEEDBYTES / 16]; - uint8_t seed[PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_CRYPTO_SEEDBYTES]; - } aligned_seed; - randombytes(aligned_seed.seed, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_CRYPTO_SEEDBYTES); - - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_crypto_sign_seed_keypair( - aligned_pk.pk, aligned_sk.sk, aligned_seed.seed); - memcpy(pk, aligned_pk.pk, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_CRYPTO_PUBLICKEYBYTES); - memcpy(sk, aligned_sk.sk, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_CRYPTO_SECRETKEYBYTES); - - return 0; -} - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - // guarantee alignment of sk - union { - __m128 *_x; - uint8_t sk[PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_CRYPTO_SECRETKEYBYTES]; - } aligned_sk; - memcpy(aligned_sk.sk, sk, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_CRYPTO_SECRETKEYBYTES); - sk = aligned_sk.sk; - - // guarantee alignment of sig - union { - __m128 *_x; - uint8_t sig[PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_BYTES]; - } aligned_sig; - uint8_t *orig_sig = sig; - sig = (uint8_t *)aligned_sig.sig; - - const unsigned char *sk_seed = sk; - const unsigned char *sk_prf = sk + PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N; - const unsigned char *pk = sk + 2 * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N; - const unsigned char *pub_seed = pk; - - unsigned char optrand[PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N]; - unsigned char mhash[PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_FORS_MSG_BYTES]; - unsigned char root[PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N]; - uint32_t i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - - hash_state hash_state_seeded; - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_initialize_hash_function( - &hash_state_seeded, - pub_seed, sk_seed); - - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_set_type( - wots_addr, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_set_type( - tree_addr, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_ADDR_TYPE_HASHTREE); - - /* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ - randombytes(optrand, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N); - /* Compute the digest randomization value. */ - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_gen_message_random( - sig, sk_prf, optrand, m, mlen, &hash_state_seeded); - - /* Derive the message digest and leaf index from R, PK and M. */ - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N; - - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_set_keypair_addr( - wots_addr, idx_leaf); - - /* Sign the message hash using FORS. */ - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_fors_sign( - sig, root, mhash, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_FORS_BYTES; - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_D; i++) { - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_set_tree_addr(tree_addr, tree); - - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_set_keypair_addr( - wots_addr, idx_leaf); - - /* Compute a WOTS signature. */ - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_wots_sign( - sig, root, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_WOTS_BYTES; - - /* Compute the authentication path for the used WOTS leaf. */ - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_treehash_TREE_HEIGHT( - root, sig, sk_seed, pub_seed, idx_leaf, 0, - wots_gen_leaf, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_TREE_HEIGHT * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_TREE_HEIGHT; - } - - memcpy(orig_sig, aligned_sig.sig, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_BYTES); - *siglen = PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_BYTES; - - return 0; -} - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk) { - // guarantee alignment of pk - union { - __m128 *_x; - uint8_t pk[PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_CRYPTO_PUBLICKEYBYTES]; - } aligned_pk; - memcpy(aligned_pk.pk, pk, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_CRYPTO_PUBLICKEYBYTES); - pk = aligned_pk.pk; - - const unsigned char *pub_seed = pk; - const unsigned char *pub_root = pk + PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N; - unsigned char mhash[PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_FORS_MSG_BYTES]; - unsigned char wots_pk[PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_WOTS_BYTES]; - unsigned char root[PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N]; - unsigned char leaf[PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N]; - unsigned int i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - hash_state hash_state_seeded; - - if (siglen != PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_BYTES) { - return -1; - } - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_initialize_hash_function( - &hash_state_seeded, - pub_seed, NULL); - - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_set_type( - wots_addr, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_set_type( - tree_addr, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_ADDR_TYPE_HASHTREE); - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_set_type( - wots_pk_addr, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_ADDR_TYPE_WOTSPK); - - /* Derive the message digest and leaf index from R || PK || M. */ - /* The additional PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N is a result of the hash domain separator. */ - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N; - - /* Layer correctly defaults to 0, so no need to set_layer_addr */ - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_set_keypair_addr( - wots_addr, idx_leaf); - - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_fors_pk_from_sig( - root, sig, mhash, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_FORS_BYTES; - - /* For each subtree.. */ - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_D; i++) { - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_set_tree_addr(tree_addr, tree); - - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_set_keypair_addr( - wots_addr, idx_leaf); - - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_copy_keypair_addr( - wots_pk_addr, wots_addr); - - /* The WOTS public key is only correct if the signature was correct. */ - /* Initially, root is the FORS pk, but on subsequent iterations it is - the root of the subtree below the currently processed subtree. */ - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_wots_pk_from_sig( - wots_pk, sig, root, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_WOTS_BYTES; - - /* Compute the leaf node using the WOTS public key. */ - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_thash_WOTS_LEN( - leaf, wots_pk, pub_seed, wots_pk_addr, &hash_state_seeded); - - /* Compute the root node of this subtree. */ - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_compute_root( - root, leaf, idx_leaf, 0, sig, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_TREE_HEIGHT, - pub_seed, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_TREE_HEIGHT * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_TREE_HEIGHT; - } - - /* Check if the root node equals the root node in the public key. */ - if (memcmp(root, pub_root, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N) != 0) { - return -1; - } - - return 0; -} - - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - size_t siglen; - - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_crypto_sign_signature( - sm, &siglen, m, mlen, sk); - - memmove(sm + PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_BYTES, m, mlen); - *smlen = siglen + mlen; - - return 0; -} - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk) { - - // guarantee alignment of pk - union { - __m128 *_x; - uint8_t pk[PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_CRYPTO_PUBLICKEYBYTES]; - } aligned_pk; - memcpy(aligned_pk.pk, pk, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_CRYPTO_PUBLICKEYBYTES); - pk = aligned_pk.pk; - - - /* The API caller does not necessarily know what size a signature should be - but SPHINCS+ signatures are always exactly PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_BYTES. */ - if (smlen < PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_BYTES) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - *mlen = smlen - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_BYTES; - - if (PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_crypto_sign_verify( - sm, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_BYTES, sm + PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_BYTES, *mlen, pk)) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - /* If verification was successful, move the message to the right place. */ - memmove(m, sm + PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_BYTES, *mlen); - - return 0; -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_avx2/thash.h b/src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_avx2/thash.h deleted file mode 100644 index 385ec0d893..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_avx2/thash.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_THASH_H -#define PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_THASH_H - -#include "hash_state.h" - -#include - -void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_avx2/thash_shake256_simple.c b/src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_avx2/thash_shake256_simple.c deleted file mode 100644 index 235bc859af..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_avx2/thash_shake256_simple.c +++ /dev/null @@ -1,74 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash_state.h" -#include "params.h" -#include "thash.h" - -#include "fips202.h" - -/** - * Takes an array of inblocks concatenated arrays of PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N bytes. - */ -static void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_thash( - unsigned char *out, unsigned char *buf, - const unsigned char *in, unsigned int inblocks, - const unsigned char *pub_seed, uint32_t addr[8]) { - - memcpy(buf, pub_seed, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N); - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_addr_to_bytes(buf + PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N, addr); - memcpy(buf + PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_ADDR_BYTES, in, inblocks * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N); - - shake256(out, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N, buf, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N); -} - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_ADDR_BYTES + 1 * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N]; - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_thash( - out, buf, in, 1, pub_seed, addr); - - (void)hash_state_seeded; /* Avoid unused parameter warning. */ -} - -void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_ADDR_BYTES + 2 * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N]; - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_thash( - out, buf, in, 2, pub_seed, addr); - - (void)hash_state_seeded; /* Avoid unused parameter warning. */ -} - -void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_ADDR_BYTES + PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_WOTS_LEN * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N]; - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_thash( - out, buf, in, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_WOTS_LEN, pub_seed, addr); - - (void)hash_state_seeded; /* Avoid unused parameter warning. */ -} - -void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_ADDR_BYTES + PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_FORS_TREES * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N]; - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_thash( - out, buf, in, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_FORS_TREES, pub_seed, addr); - - (void)hash_state_seeded; /* Avoid unused parameter warning. */ -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_avx2/thash_shake256_simplex4.c b/src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_avx2/thash_shake256_simplex4.c deleted file mode 100644 index 973f0b0ee6..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_avx2/thash_shake256_simplex4.c +++ /dev/null @@ -1,47 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "thashx4.h" - -#include "fips202x4.h" - -/** - * 4-way parallel version of thash; takes 4x as much input and output - */ -#define thashx4_variant(name, inblocks) \ - void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_thashx4_##name( \ - unsigned char *out0, unsigned char *out1, unsigned char *out2, unsigned char *out3, \ - const unsigned char *in0, const unsigned char *in1, const unsigned char *in2, \ - const unsigned char *in3, const unsigned char *pub_seed, uint32_t addrx4[4 * 8], \ - const hash_state *state_seeded) { \ - unsigned char buf0[PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_ADDR_BYTES + (inblocks)*PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N]; \ - unsigned char buf1[PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_ADDR_BYTES + (inblocks)*PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N]; \ - unsigned char buf2[PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_ADDR_BYTES + (inblocks)*PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N]; \ - unsigned char buf3[PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_ADDR_BYTES + (inblocks)*PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N]; \ - \ - memcpy(buf0, pub_seed, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N); \ - memcpy(buf1, pub_seed, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N); \ - memcpy(buf2, pub_seed, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N); \ - memcpy(buf3, pub_seed, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N); \ - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_addr_to_bytes(buf0 + PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N, addrx4 + 0 * 8); \ - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_addr_to_bytes(buf1 + PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N, addrx4 + 1 * 8); \ - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_addr_to_bytes(buf2 + PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N, addrx4 + 2 * 8); \ - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_addr_to_bytes(buf3 + PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N, addrx4 + 3 * 8); \ - memcpy(buf0 + PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_ADDR_BYTES, in0, (inblocks)*PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N); \ - memcpy(buf1 + PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_ADDR_BYTES, in1, (inblocks)*PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N); \ - memcpy(buf2 + PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_ADDR_BYTES, in2, (inblocks)*PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N); \ - memcpy(buf3 + PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_ADDR_BYTES, in3, (inblocks)*PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N); \ - \ - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_shake256x4(out0, out1, out2, out3, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N, buf0, buf1, buf2, buf3, \ - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_ADDR_BYTES + (inblocks)*PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N); \ - \ - /* Avoid unused parameter warning */ \ - (void)state_seeded; \ - } - -thashx4_variant(1, 1) -thashx4_variant(2, 2) -thashx4_variant(WOTS_LEN, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_WOTS_LEN) -thashx4_variant(FORS_TREES, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_FORS_TREES) diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_avx2/thashx4.h b/src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_avx2/thashx4.h deleted file mode 100644 index 38735609bb..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_avx2/thashx4.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_THASHX4_H -#define PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_THASHX4_H - -#include - -#include "hash_state.h" - -#define thashx4_header(inblocks) \ - void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_thashx4_##inblocks(unsigned char *out0, \ - unsigned char *out1, \ - unsigned char *out2, \ - unsigned char *out3, \ - const unsigned char *in0, \ - const unsigned char *in1, \ - const unsigned char *in2, \ - const unsigned char *in3, \ - const unsigned char *pub_seed, uint32_t addrx4[4*8], \ - const hash_state *state_seeded) - -thashx4_header(1); -thashx4_header(2); -thashx4_header(WOTS_LEN); -thashx4_header(FORS_TREES); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_avx2/utils.c b/src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_avx2/utils.c deleted file mode 100644 index 11a1d1fae6..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_avx2/utils.c +++ /dev/null @@ -1,199 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "hash_state.h" -#include "params.h" -#include "thash.h" -#include "utils.h" - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in) { - - /* Iterate over out in decreasing order, for big-endianness. */ - for (size_t i = outlen; i > 0; i--) { - out[i - 1] = in & 0xff; - in = in >> 8; - } -} - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_bytes_to_ull( - const unsigned char *in, size_t inlen) { - unsigned long long retval = 0; - - for (size_t i = 0; i < inlen; i++) { - retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); - } - return retval; -} - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - uint32_t i; - unsigned char buffer[2 * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N]; - - /* If leaf_idx is odd (last bit = 1), current path element is a right child - and auth_path has to go left. Otherwise it is the other way around. */ - if (leaf_idx & 1) { - memcpy(buffer + PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N, leaf, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N); - } else { - memcpy(buffer, leaf, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N); - memcpy(buffer + PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N, auth_path, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N); - } - auth_path += PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N; - - for (i = 0; i < tree_height - 1; i++) { - leaf_idx >>= 1; - idx_offset >>= 1; - /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_set_tree_height(addr, i + 1); - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_set_tree_index( - addr, leaf_idx + idx_offset); - - /* Pick the right or left neighbor, depending on parity of the node. */ - if (leaf_idx & 1) { - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_thash_2( - buffer + PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N); - } else { - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_thash_2( - buffer, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer + PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N, auth_path, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N); - } - auth_path += PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N; - } - - /* The last iteration is exceptional; we do not copy an auth_path node. */ - leaf_idx >>= 1; - idx_offset >>= 1; - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_set_tree_height(addr, tree_height); - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_set_tree_index( - addr, leaf_idx + idx_offset); - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_thash_2( - root, buffer, pub_seed, addr, hash_state_seeded); -} - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -static void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_treehash( - unsigned char *root, unsigned char *auth_path, - unsigned char *stack, unsigned int *heights, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - - unsigned int offset = 0; - uint32_t idx; - uint32_t tree_idx; - - for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { - /* Add the next leaf node to the stack. */ - gen_leaf(stack + offset * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N, - sk_seed, pub_seed, idx + idx_offset, tree_addr, - hash_state_seeded); - offset++; - heights[offset - 1] = 0; - - /* If this is a node we need for the auth path.. */ - if ((leaf_idx ^ 0x1) == idx) { - memcpy(auth_path, stack + (offset - 1)*PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N); - } - - /* While the top-most nodes are of equal height.. */ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { - /* Compute index of the new node, in the next layer. */ - tree_idx = (idx >> (heights[offset - 1] + 1)); - - /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_set_tree_height( - tree_addr, heights[offset - 1] + 1); - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_set_tree_index( - tree_addr, tree_idx + (idx_offset >> (heights[offset - 1] + 1))); - /* Hash the top-most nodes from the stack together. */ - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_thash_2( - stack + (offset - 2)*PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N, stack + (offset - 2)*PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N, - pub_seed, tree_addr, hash_state_seeded); - offset--; - /* Note that the top-most node is now one layer higher. */ - heights[offset - 1]++; - - /* If this is a node we need for the auth path.. */ - if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_path + heights[offset - 1]*PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N, - stack + (offset - 1)*PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N); - } - } - } - memcpy(root, stack, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N); -} - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_FORS_HEIGHT + 1)*PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N]; - unsigned int heights[PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_FORS_HEIGHT + 1]; - - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_FORS_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_TREE_HEIGHT + 1)*PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N]; - unsigned int heights[PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_TREE_HEIGHT + 1]; - - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_TREE_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_avx2/utils.h b/src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_avx2/utils.h deleted file mode 100644 index 43ba1b093d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_avx2/utils.h +++ /dev/null @@ -1,64 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_UTILS_H -#define PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_UTILS_H - -#include "hash_state.h" -#include "params.h" -#include -#include - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in); - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_bytes_to_ull( - const unsigned char *in, size_t inlen); - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_avx2/utilsx4.c b/src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_avx2/utilsx4.c deleted file mode 100644 index 7be40219e4..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_avx2/utilsx4.c +++ /dev/null @@ -1,98 +0,0 @@ -#include "address.h" -#include "params.h" -#include "thashx4.h" -#include "utils.h" -#include "utilsx4.h" - -#include - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -#define treehashx4_variant(name, tree_height) \ - void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_treehashx4_##name( \ - unsigned char *rootx4, unsigned char *auth_pathx4, const unsigned char *sk_seed, \ - const unsigned char *pub_seed, const uint32_t leaf_idx[4], uint32_t idx_offset[4], \ - void (*gen_leafx4)(unsigned char * /* leaf0 */, unsigned char * /* leaf1 */, \ - unsigned char * /* leaf2 */, unsigned char * /* leaf3 */, \ - const unsigned char * /* sk_seed */, \ - const unsigned char * /* pub_seed */, uint32_t /* addr_idx0 */, \ - uint32_t /* addr_idx1 */, uint32_t /* addr_idx2 */, \ - uint32_t /* addr_idx3 */, const uint32_t[8] /* tree_addr */, \ - const hash_state * /* state_seeded */), \ - uint32_t tree_addrx4[4 * 8], const hash_state *state_seeded) { \ - unsigned char stackx4[4 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N]; \ - unsigned int heights[(tree_height) + 1]; \ - unsigned int offset = 0; \ - uint32_t idx; \ - uint32_t tree_idx; \ - unsigned int j; \ - \ - for (idx = 0; idx < (uint32_t)(1 << (tree_height)); idx++) { \ - /* Add the next leaf node to the stack. */ \ - gen_leafx4(stackx4 + 0 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N + offset * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N, \ - stackx4 + 1 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N + offset * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N, \ - stackx4 + 2 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N + offset * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N, \ - stackx4 + 3 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N + offset * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N, sk_seed, \ - pub_seed, idx + idx_offset[0], idx + idx_offset[1], idx + idx_offset[2], \ - idx + idx_offset[3], tree_addrx4, state_seeded); \ - offset++; \ - heights[offset - 1] = 0; \ - \ - /* If this is a node we need for the auth path.. */ \ - for (j = 0; j < 4; j++) { \ - if ((leaf_idx[j] ^ 0x1) == idx) { \ - memcpy(auth_pathx4 + j * (tree_height)*PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N, \ - stackx4 + j * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N + (offset - 1) * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N, \ - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N); \ - } \ - } \ - \ - /* While the top-most nodes are of equal height.. */ \ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { \ - /* Compute index of the new node, in the next layer. */ \ - tree_idx = (idx >> (heights[offset - 1] + 1)); \ - \ - /* Set the address of the node we're creating. */ \ - for (j = 0; j < 4; j++) { \ - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_set_tree_height(tree_addrx4 + j * 8, heights[offset - 1] + 1); \ - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_set_tree_index(tree_addrx4 + j * 8, \ - tree_idx + (idx_offset[j] >> (heights[offset - 1] + 1))); \ - } \ - /* Hash the top-most nodes from the stack together. */ \ - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_thashx4_2(stackx4 + 0 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N + (offset - 2) * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N, \ - stackx4 + 1 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N + (offset - 2) * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N, \ - stackx4 + 2 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N + (offset - 2) * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N, \ - stackx4 + 3 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N + (offset - 2) * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N, \ - stackx4 + 0 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N + (offset - 2) * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N, \ - stackx4 + 1 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N + (offset - 2) * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N, \ - stackx4 + 2 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N + (offset - 2) * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N, \ - stackx4 + 3 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N + (offset - 2) * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N, \ - pub_seed, tree_addrx4, state_seeded); \ - offset--; \ - /* Note that the top-most node is now one layer higher. */ \ - heights[offset - 1]++; \ - \ - /* If this is a node we need for the auth path.. */ \ - for (j = 0; j < 4; j++) { \ - if (((leaf_idx[j] >> heights[offset - 1]) ^ 0x1) == tree_idx) { \ - memcpy(auth_pathx4 + j * (tree_height)*PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N + \ - heights[offset - 1] * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N, \ - stackx4 + j * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N + (offset - 1) * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N, \ - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N); \ - } \ - } \ - } \ - } \ - \ - for (j = 0; j < 4; j++) { \ - memcpy(rootx4 + j * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N, stackx4 + j * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N); \ - } \ - } - -treehashx4_variant(FORS_HEIGHT, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_FORS_HEIGHT) diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_avx2/utilsx4.h b/src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_avx2/utilsx4.h deleted file mode 100644 index 4dcc037e44..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_avx2/utilsx4.h +++ /dev/null @@ -1,38 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_UTILSX4_H -#define PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_UTILSX4_H - -#include "hash_state.h" -#include "params.h" - -#include - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_treehashx4_FORS_HEIGHT(unsigned char *rootx4, - unsigned char *auth_pathx4, - const unsigned char *sk_seed, - const unsigned char *pub_seed, - const uint32_t leaf_idx[4], - uint32_t idx_offset[4], - void (*gen_leafx4)(unsigned char * /* leaf0 */, - unsigned char * /* leaf1 */, - unsigned char * /* leaf2 */, - unsigned char * /* leaf3 */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx0 */, - uint32_t /* addr_idx1 */, - uint32_t /* addr_idx2 */, - uint32_t /* addr_idx3 */, - const uint32_t[8] /* tree_addr */, - const hash_state * /* state_seeded */), - uint32_t tree_addrx4[4 * 8], - const hash_state *state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_avx2/wots.c b/src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_avx2/wots.c deleted file mode 100644 index 1e259d02db..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_avx2/wots.c +++ /dev/null @@ -1,240 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "hash_state.h" -#include "hashx4.h" -#include "params.h" -#include "thash.h" -#include "thashx4.h" -#include "utils.h" -#include "wots.h" - -// TODO clarify address expectations, and make them more uniform. -// TODO i.e. do we expect types to be set already? -// TODO and do we expect modifications or copies? - -/** - * Computes the starting value for a chain, i.e. the secret key. - * Expects the address to be complete up to the chain address. - */ -static void wots_gen_sk(unsigned char *sk, const unsigned char *sk_seed, - uint32_t wots_addr[8], const hash_state *state_seeded) { - /* Make sure that the hash address is actually zeroed. */ - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_set_hash_addr(wots_addr, 0); - - /* Generate sk element. */ - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_prf_addr(sk, sk_seed, wots_addr, state_seeded); -} - -/** - * 4-way parallel version of wots_gen_sk; expects 4x as much space in sk - */ -static void wots_gen_skx4(unsigned char *skx4, const unsigned char *sk_seed, - uint32_t wots_addrx4[4 * 8], const hash_state *state_seeded) { - unsigned int j; - - /* Make sure that the hash address is actually zeroed. */ - for (j = 0; j < 4; j++) { - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_set_hash_addr(wots_addrx4 + j * 8, 0); - } - - /* Generate sk element. */ - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_prf_addrx4(skx4 + 0 * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N, - skx4 + 1 * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N, - skx4 + 2 * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N, - skx4 + 3 * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N, - sk_seed, wots_addrx4, - state_seeded); -} - -/** - * Computes the chaining function. - * out and in have to be n-byte arrays. - * - * Interprets in as start-th value of the chain. - * addr has to contain the address of the chain. - */ -static void gen_chain(unsigned char *out, const unsigned char *in, - unsigned int start, unsigned int steps, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *state_seeded) { - uint32_t i; - - /* Initialize out with the value at position 'start'. */ - memcpy(out, in, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N); - - /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_WOTS_W; i++) { - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_set_hash_addr(addr, i); - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_thash_1(out, out, pub_seed, addr, state_seeded); - } -} - -/** - * 4-way parallel version of gen_chain; expects 4x as much space in out, and - * 4x as much space in inx4. Assumes start and step identical across chains. - */ -static void gen_chainx4(unsigned char *outx4, const unsigned char *inx4, - unsigned int start, unsigned int steps, - const unsigned char *pub_seed, uint32_t addrx4[4 * 8], - const hash_state *state_seeded) { - uint32_t i; - unsigned int j; - - /* Initialize outx4 with the value at position 'start'. */ - memcpy(outx4, inx4, 4 * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N); - - /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_WOTS_W; i++) { - for (j = 0; j < 4; j++) { - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_set_hash_addr(addrx4 + j * 8, i); - } - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_thashx4_1(outx4 + 0 * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N, - outx4 + 1 * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N, - outx4 + 2 * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N, - outx4 + 3 * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N, - outx4 + 0 * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N, - outx4 + 1 * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N, - outx4 + 2 * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N, - outx4 + 3 * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N, - pub_seed, addrx4, - state_seeded); - } -} - -/** - * base_w algorithm as described in draft. - * Interprets an array of bytes as integers in base w. - * This only works when log_w is a divisor of 8. - */ -static void base_w(unsigned int *output, const int out_len, const unsigned char *input) { - int in = 0; - int out = 0; - unsigned char total = 0; - int bits = 0; - int consumed; - - for (consumed = 0; consumed < out_len; consumed++) { - if (bits == 0) { - total = input[in]; - in++; - bits += 8; - } - bits -= PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_WOTS_LOGW; - output[out] = (unsigned int)(total >> bits) & (PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_WOTS_W - 1); - out++; - } -} - -/* Computes the WOTS+ checksum over a message (in base_w). */ -static void wots_checksum(unsigned int *csum_base_w, const unsigned int *msg_base_w) { - unsigned int csum = 0; - unsigned char csum_bytes[(PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_WOTS_LEN2 * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_WOTS_LOGW + 7) / 8]; - unsigned int i; - - /* Compute checksum. */ - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_WOTS_LEN1; i++) { - csum += PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_WOTS_W - 1 - msg_base_w[i]; - } - - /* Convert checksum to base_w. */ - /* Make sure expected empty zero bits are the least significant bits. */ - csum = csum << (8 - ((PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_WOTS_LEN2 * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_WOTS_LOGW) % 8)); - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); - base_w(csum_base_w, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_WOTS_LEN2, csum_bytes); -} - -/* Takes a message and derives the matching chain lengths. */ -static void chain_lengths(unsigned int *lengths, const unsigned char *msg) { - base_w(lengths, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_WOTS_LEN1, msg); - wots_checksum(lengths + PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_WOTS_LEN1, lengths); -} - -/** - * WOTS key generation. Takes a 32 byte sk_seed, expands it to WOTS private key - * elements and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_wots_gen_pk(unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *state_seeded) { - uint32_t i; - unsigned int j; - - uint32_t addrx4[4 * 8]; - unsigned char pkbuf[4 * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N]; - - for (j = 0; j < 4; j++) { - memcpy(addrx4 + j * 8, addr, sizeof(uint32_t) * 8); - } - - /* The last iteration typically does not have complete set of 4 chains, - but because we use pkbuf, this is not an issue -- we still do as many - in parallel as possible. */ - for (i = 0; i < ((PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_WOTS_LEN + 3) & ~0x3); i += 4) { - for (j = 0; j < 4; j++) { - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_set_chain_addr(addrx4 + j * 8, i + j); - } - wots_gen_skx4(pkbuf, sk_seed, addrx4, state_seeded); - gen_chainx4(pkbuf, pkbuf, 0, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_WOTS_W - 1, pub_seed, addrx4, state_seeded); - for (j = 0; j < 4; j++) { - if (i + j < PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_WOTS_LEN) { - memcpy(pk + (i + j)*PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N, pkbuf + j * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N); - } - } - } - - // Get rid of unused argument variable. - (void)state_seeded; -} - -/** - * Takes a n-byte message and the 32-byte sk_see to compute a signature 'sig'. - */ -void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_wots_sign(unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_WOTS_LEN; i++) { - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_set_chain_addr(addr, i); - wots_gen_sk(sig + i * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N, sk_seed, addr, state_seeded); - gen_chain(sig + i * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N, sig + i * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N, 0, lengths[i], pub_seed, addr, state_seeded); - } - - // avoid unused argument - (void)state_seeded; -} - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_WOTS_LEN; i++) { - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_set_chain_addr(addr, i); - gen_chain(pk + i * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N, sig + i * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_N, - lengths[i], PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_WOTS_W - 1 - lengths[i], pub_seed, addr, - state_seeded); - } - - // avoid unused argument - (void)state_seeded; -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_avx2/wots.h b/src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_avx2/wots.h deleted file mode 100644 index afd5712fd8..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_avx2/wots.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_WOTS_H -#define PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_WOTS_H - -#include "hash_state.h" -#include "params.h" -#include - -/** - * WOTS key generation. Takes a 32 byte seed for the private key, expands it to - * a full WOTS private key and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_wots_gen_pk( - unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -/** - * Takes a n-byte message and the 32-byte seed for the private key to compute a - * signature that is placed at 'sig'. - */ -void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_wots_sign( - unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *hash_state_seeded); - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_wots_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_clean/LICENSE b/src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_clean/LICENSE deleted file mode 100644 index 670154e353..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_clean/LICENSE +++ /dev/null @@ -1,116 +0,0 @@ -CC0 1.0 Universal - -Statement of Purpose - -The laws of most jurisdictions throughout the world automatically confer -exclusive Copyright and Related Rights (defined below) upon the creator and -subsequent owner(s) (each and all, an "owner") of an original work of -authorship and/or a database (each, a "Work"). - -Certain owners wish to permanently relinquish those rights to a Work for the -purpose of contributing to a commons of creative, cultural and scientific -works ("Commons") that the public can reliably and without fear of later -claims of infringement build upon, modify, incorporate in other works, reuse -and redistribute as freely as possible in any form whatsoever and for any -purposes, including without limitation commercial purposes. These owners may -contribute to the Commons to promote the ideal of a free culture and the -further production of creative, cultural and scientific works, or to gain -reputation or greater distribution for their Work in part through the use and -efforts of others. - -For these and/or other purposes and motivations, and without any expectation -of additional consideration or compensation, the person associating CC0 with a -Work (the "Affirmer"), to the extent that he or she is an owner of Copyright -and Related Rights in the Work, voluntarily elects to apply CC0 to the Work -and publicly distribute the Work under its terms, with knowledge of his or her -Copyright and Related Rights in the Work and the meaning and intended legal -effect of CC0 on those rights. - -1. Copyright and Related Rights. A Work made available under CC0 may be -protected by copyright and related or neighboring rights ("Copyright and -Related Rights"). Copyright and Related Rights include, but are not limited -to, the following: - - i. the right to reproduce, adapt, distribute, perform, display, communicate, - and translate a Work; - - ii. moral rights retained by the original author(s) and/or performer(s); - - iii. publicity and privacy rights pertaining to a person's image or likeness - depicted in a Work; - - iv. rights protecting against unfair competition in regards to a Work, - subject to the limitations in paragraph 4(a), below; - - v. rights protecting the extraction, dissemination, use and reuse of data in - a Work; - - vi. database rights (such as those arising under Directive 96/9/EC of the - European Parliament and of the Council of 11 March 1996 on the legal - protection of databases, and under any national implementation thereof, - including any amended or successor version of such directive); and - - vii. other similar, equivalent or corresponding rights throughout the world - based on applicable law or treaty, and any national implementations thereof. - -2. Waiver. To the greatest extent permitted by, but not in contravention of, -applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and -unconditionally waives, abandons, and surrenders all of Affirmer's Copyright -and Related Rights and associated claims and causes of action, whether now -known or unknown (including existing as well as future claims and causes of -action), in the Work (i) in all territories worldwide, (ii) for the maximum -duration provided by applicable law or treaty (including future time -extensions), (iii) in any current or future medium and for any number of -copies, and (iv) for any purpose whatsoever, including without limitation -commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes -the Waiver for the benefit of each member of the public at large and to the -detriment of Affirmer's heirs and successors, fully intending that such Waiver -shall not be subject to revocation, rescission, cancellation, termination, or -any other legal or equitable action to disrupt the quiet enjoyment of the Work -by the public as contemplated by Affirmer's express Statement of Purpose. - -3. Public License Fallback. Should any part of the Waiver for any reason be -judged legally invalid or ineffective under applicable law, then the Waiver -shall be preserved to the maximum extent permitted taking into account -Affirmer's express Statement of Purpose. In addition, to the extent the Waiver -is so judged Affirmer hereby grants to each affected person a royalty-free, -non transferable, non sublicensable, non exclusive, irrevocable and -unconditional license to exercise Affirmer's Copyright and Related Rights in -the Work (i) in all territories worldwide, (ii) for the maximum duration -provided by applicable law or treaty (including future time extensions), (iii) -in any current or future medium and for any number of copies, and (iv) for any -purpose whatsoever, including without limitation commercial, advertising or -promotional purposes (the "License"). The License shall be deemed effective as -of the date CC0 was applied by Affirmer to the Work. Should any part of the -License for any reason be judged legally invalid or ineffective under -applicable law, such partial invalidity or ineffectiveness shall not -invalidate the remainder of the License, and in such case Affirmer hereby -affirms that he or she will not (i) exercise any of his or her remaining -Copyright and Related Rights in the Work or (ii) assert any associated claims -and causes of action with respect to the Work, in either case contrary to -Affirmer's express Statement of Purpose. - -4. Limitations and Disclaimers. - - a. No trademark or patent rights held by Affirmer are waived, abandoned, - surrendered, licensed or otherwise affected by this document. - - b. Affirmer offers the Work as-is and makes no representations or warranties - of any kind concerning the Work, express, implied, statutory or otherwise, - including without limitation warranties of title, merchantability, fitness - for a particular purpose, non infringement, or the absence of latent or - other defects, accuracy, or the present or absence of errors, whether or not - discoverable, all to the greatest extent permissible under applicable law. - - c. Affirmer disclaims responsibility for clearing rights of other persons - that may apply to the Work or any use thereof, including without limitation - any person's Copyright and Related Rights in the Work. Further, Affirmer - disclaims responsibility for obtaining any necessary consents, permissions - or other rights required for any use of the Work. - - d. Affirmer understands and acknowledges that Creative Commons is not a - party to this document and has no duty or obligation with respect to this - CC0 or use of the Work. - -For more information, please see - diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_clean/address.c b/src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_clean/address.c deleted file mode 100644 index 35757e5488..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_clean/address.c +++ /dev/null @@ -1,78 +0,0 @@ -#include - -#include "address.h" -#include "params.h" -#include "utils.h" - -void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]) { - int i; - - for (i = 0; i < 8; i++) { - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_ull_to_bytes( - bytes + i * 4, 4, addr[i]); - } -} - -void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_set_layer_addr( - uint32_t addr[8], uint32_t layer) { - addr[0] = layer; -} - -void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_set_tree_addr( - uint32_t addr[8], uint64_t tree) { - addr[1] = 0; - addr[2] = (uint32_t) (tree >> 32); - addr[3] = (uint32_t) tree; -} - -void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_set_type( - uint32_t addr[8], uint32_t type) { - addr[4] = type; -} - -void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; -} - -/* These functions are used for OTS addresses. */ - -void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_set_keypair_addr( - uint32_t addr[8], uint32_t keypair) { - addr[5] = keypair; -} - -void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; - out[5] = in[5]; -} - -void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_set_chain_addr( - uint32_t addr[8], uint32_t chain) { - addr[6] = chain; -} - -void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_set_hash_addr( - uint32_t addr[8], uint32_t hash) { - addr[7] = hash; -} - -/* These functions are used for all hash tree addresses (including FORS). */ - -void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_set_tree_height( - uint32_t addr[8], uint32_t tree_height) { - addr[6] = tree_height; -} - -void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_set_tree_index( - uint32_t addr[8], uint32_t tree_index) { - addr[7] = tree_index; -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_clean/address.h b/src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_clean/address.h deleted file mode 100644 index d17e9d2f8e..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_clean/address.h +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_ADDRESS_H -#define PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_ADDRESS_H - -#include - -#define PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_ADDR_TYPE_WOTS 0 -#define PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_ADDR_TYPE_WOTSPK 1 -#define PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_ADDR_TYPE_HASHTREE 2 -#define PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_ADDR_TYPE_FORSTREE 3 -#define PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_ADDR_TYPE_FORSPK 4 - -void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]); - -void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_set_layer_addr( - uint32_t addr[8], uint32_t layer); - -void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_set_tree_addr( - uint32_t addr[8], uint64_t tree); - -void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_set_type( - uint32_t addr[8], uint32_t type); - -/* Copies the layer and tree part of one address into the other */ -void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for WOTS and FORS addresses. */ - -void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_set_keypair_addr( - uint32_t addr[8], uint32_t keypair); - -void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_set_chain_addr( - uint32_t addr[8], uint32_t chain); - -void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_set_hash_addr( - uint32_t addr[8], uint32_t hash); - -void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for all hash tree addresses (including FORS). */ - -void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_set_tree_height( - uint32_t addr[8], uint32_t tree_height); - -void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_set_tree_index( - uint32_t addr[8], uint32_t tree_index); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_clean/api.h b/src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_clean/api.h deleted file mode 100644 index 0199d7bcf9..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_clean/api.h +++ /dev/null @@ -1,81 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_API_H -#define PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_API_H - -#include -#include - - - -#define PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_CRYPTO_ALGNAME "SPHINCS+" - -#define PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_CRYPTO_SECRETKEYBYTES 64 -#define PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_CRYPTO_PUBLICKEYBYTES 32 -#define PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_CRYPTO_BYTES 7856 -#define PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_CRYPTO_SEEDBYTES 48 - - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_clean/fors.c b/src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_clean/fors.c deleted file mode 100644 index 3a9b69ae09..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_clean/fors.c +++ /dev/null @@ -1,161 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "fors.h" -#include "hash.h" -#include "hash_state.h" -#include "thash.h" -#include "utils.h" - -static void fors_gen_sk(unsigned char *sk, const unsigned char *sk_seed, - uint32_t fors_leaf_addr[8], const hash_state *hash_state_seeded) { - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_prf_addr( - sk, sk_seed, fors_leaf_addr, hash_state_seeded); -} - -static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, - const unsigned char *pub_seed, - uint32_t fors_leaf_addr[8], - const hash_state *hash_state_seeded) { - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_thash_1( - leaf, sk, pub_seed, fors_leaf_addr, hash_state_seeded); -} - -static void fors_gen_leaf(unsigned char *leaf, const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx, const uint32_t fors_tree_addr[8], - const hash_state *hash_state_seeded) { - uint32_t fors_leaf_addr[8] = {0}; - - /* Only copy the parts that must be kept in fors_leaf_addr. */ - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_copy_keypair_addr( - fors_leaf_addr, fors_tree_addr); - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_set_type( - fors_leaf_addr, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_set_tree_index( - fors_leaf_addr, addr_idx); - - fors_gen_sk(leaf, sk_seed, fors_leaf_addr, hash_state_seeded); - fors_sk_to_leaf(leaf, leaf, pub_seed, fors_leaf_addr, hash_state_seeded); -} - -/** - * Interprets m as PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_FORS_HEIGHT-bit unsigned integers. - * Assumes m contains at least PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_FORS_TREES bits. - * Assumes indices has space for PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_FORS_TREES integers. - */ -static void message_to_indices(uint32_t *indices, const unsigned char *m) { - unsigned int i, j; - unsigned int offset = 0; - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_FORS_TREES; i++) { - indices[i] = 0; - for (j = 0; j < PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_FORS_HEIGHT; j++) { - indices[i] ^= (((uint32_t)m[offset >> 3] >> (offset & 0x7)) & 0x1) << j; - offset++; - } - } -} - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_fors_sign( - unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *hash_state_seeded) { - uint32_t indices[PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_FORS_TREES]; - unsigned char roots[PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_FORS_TREES * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_N]; - uint32_t fors_tree_addr[8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_copy_keypair_addr( - fors_tree_addr, fors_addr); - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_copy_keypair_addr( - fors_pk_addr, fors_addr); - - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_set_type( - fors_tree_addr, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_set_type( - fors_pk_addr, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_FORS_TREES; i++) { - idx_offset = i * (1 << PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_FORS_HEIGHT); - - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_set_tree_height( - fors_tree_addr, 0); - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_set_tree_index( - fors_tree_addr, indices[i] + idx_offset); - - /* Include the secret key part that produces the selected leaf node. */ - fors_gen_sk(sig, sk_seed, fors_tree_addr, hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_N; - - /* Compute the authentication path for this leaf node. */ - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_treehash_FORS_HEIGHT( - roots + i * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_N, sig, sk_seed, pub_seed, - indices[i], idx_offset, fors_gen_leaf, fors_tree_addr, - hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_N * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_thash_FORS_TREES( - pk, roots, pub_seed, fors_pk_addr, hash_state_seeded); -} - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_fors_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, const uint32_t fors_addr[8], - const hash_state *hash_state_seeded) { - uint32_t indices[PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_FORS_TREES]; - unsigned char roots[PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_FORS_TREES * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_N]; - unsigned char leaf[PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_N]; - uint32_t fors_tree_addr[8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_copy_keypair_addr(fors_tree_addr, fors_addr); - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_copy_keypair_addr(fors_pk_addr, fors_addr); - - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_set_type(fors_tree_addr, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_set_type(fors_pk_addr, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_FORS_TREES; i++) { - idx_offset = i * (1 << PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_FORS_HEIGHT); - - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_set_tree_height(fors_tree_addr, 0); - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Derive the leaf from the included secret key part. */ - fors_sk_to_leaf(leaf, sig, pub_seed, fors_tree_addr, hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_N; - - /* Derive the corresponding root node of this tree. */ - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_compute_root(roots + i * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_N, leaf, indices[i], idx_offset, sig, - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_FORS_HEIGHT, pub_seed, fors_tree_addr, hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_N * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_thash_FORS_TREES(pk, roots, pub_seed, fors_pk_addr, hash_state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_clean/fors.h b/src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_clean/fors.h deleted file mode 100644 index 4a6ce0b887..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_clean/fors.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_FORS_H -#define PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_FORS_H - -#include - -#include "hash_state.h" -#include "params.h" - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_fors_sign( - unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *hash_state_seeded); - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_fors_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, const uint32_t fors_addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_clean/hash.h b/src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_clean/hash.h deleted file mode 100644 index 30bac94758..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_clean/hash.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_HASH_H -#define PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_HASH_H - -#include "hash_state.h" - -#include -#include - -void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_initialize_hash_function( - hash_state *hash_state_seeded, - const unsigned char *pub_seed, const unsigned char *sk_seed); - -void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_destroy_hash_function(hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_clean/hash_shake256.c b/src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_clean/hash_shake256.c deleted file mode 100644 index 7fca240cc5..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_clean/hash_shake256.c +++ /dev/null @@ -1,106 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "utils.h" - -#include "fips202.h" - -/* For SHAKE256, there is no immediate reason to initialize at the start, - so this function is an empty operation. */ -void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_initialize_hash_function( - hash_state *hash_state_seeded, // NOLINT(readability-non-const-parameter) - const unsigned char *pub_seed, const unsigned char *sk_seed) { - (void)hash_state_seeded; /* Suppress an 'unused parameter' warning. */ - (void)pub_seed; /* Suppress an 'unused parameter' warning. */ - (void)sk_seed; /* Suppress an 'unused parameter' warning. */ -} - -/* This is not necessary for SHAKE256, so we don't do anything */ -void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_destroy_hash_function( - hash_state *hash_state_seeded) { // NOLINT(readability-non-const-parameter) - (void)hash_state_seeded; -} - -/* - * Computes PRF(key, addr), given a secret key of PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_N bytes and an address - */ -void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded) { - unsigned char buf[PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_N + PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_ADDR_BYTES]; - - memcpy(buf, key, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_N); - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_addr_to_bytes(buf + PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_N, addr); - - shake256(out, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_N, buf, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_N + PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_ADDR_BYTES); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} - -/** - * Computes the message-dependent randomness R, using a secret seed and an - * optional randomization value as well as the message. - */ -void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded) { - shake256incctx state; - - shake256_inc_init(&state); - shake256_inc_absorb(&state, sk_prf, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_N); - shake256_inc_absorb(&state, optrand, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_N); - shake256_inc_absorb(&state, m, mlen); - shake256_inc_finalize(&state); - shake256_inc_squeeze(R, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_N, &state); - shake256_inc_ctx_release(&state); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} - -/** - * Computes the message hash using R, the public key, and the message. - * Outputs the message digest and the index of the leaf. The index is split in - * the tree index and the leaf index, for convenient copying to an address. - */ -void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded) { -#define PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_TREE_BITS (PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_TREE_HEIGHT * (PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_D - 1)) -#define PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_TREE_BYTES ((PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_TREE_BITS + 7) / 8) -#define PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_LEAF_BITS PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_TREE_HEIGHT -#define PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_LEAF_BYTES ((PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_LEAF_BITS + 7) / 8) -#define PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_DGST_BYTES (PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_FORS_MSG_BYTES + PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_TREE_BYTES + PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_LEAF_BYTES) - - unsigned char buf[PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_DGST_BYTES]; - unsigned char *bufp = buf; - shake256incctx state; - - shake256_inc_init(&state); - shake256_inc_absorb(&state, R, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_N); - shake256_inc_absorb(&state, pk, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_PK_BYTES); - shake256_inc_absorb(&state, m, mlen); - shake256_inc_finalize(&state); - shake256_inc_squeeze(buf, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_DGST_BYTES, &state); - shake256_inc_ctx_release(&state); - - memcpy(digest, bufp, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_FORS_MSG_BYTES); - bufp += PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_FORS_MSG_BYTES; - - *tree = PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_bytes_to_ull( - bufp, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_TREE_BYTES); - *tree &= (~(uint64_t)0) >> (64 - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_TREE_BITS); - bufp += PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_TREE_BYTES; - - *leaf_idx = (uint32_t)PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_bytes_to_ull( - bufp, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_LEAF_BYTES); - *leaf_idx &= (~(uint32_t)0) >> (32 - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_LEAF_BITS); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_clean/hash_state.h b/src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_clean/hash_state.h deleted file mode 100644 index 7d92ef872a..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_clean/hash_state.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef SPX_HASH_STATE_H -#define SPX_HASH_STATE_H - -/** - * Defines the type of the hash function state. - * - * Don't be fooled into thinking this instance of SPHINCS+ isn't stateless! - * - * From Section 7.2.2 from the SPHINCS+ round-2 specification: - * - * Each of the instances of the tweakable hash function take PK.seed as its - * first input, which is constant for a given key pair – and, thus, across - * a single signature. This leads to a lot of redundant computation. To remedy - * this, we pad PK.seed to the length of a full 64-byte SHA-256 input block. - * Because of the Merkle-Damgård construction that underlies SHA-256, this - * allows for reuse of the intermediate SHA-256 state after the initial call to - * the compression function which improves performance. - * - * We pass this hash state around in functions, because otherwise we need to - * have a global variable. - * - * SHAKE256 does not need this state. Because this implementation is generated - * from a shared code base, we still need to specify some hash_state as it is - * still passed around. We chose to use an `int` as a placeholder for this - * purpose. - */ - -#define hash_state int - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_clean/params.h b/src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_clean/params.h deleted file mode 100644 index e6b382ff4b..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_clean/params.h +++ /dev/null @@ -1,53 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_PARAMS_H -#define PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_PARAMS_H - -/* Hash output length in bytes. */ -#define PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_N 16 -/* Height of the hypertree. */ -#define PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_FULL_HEIGHT 63 -/* Number of subtree layer. */ -#define PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_D 7 -/* FORS tree dimensions. */ -#define PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_FORS_HEIGHT 12 -#define PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_FORS_TREES 14 -/* Winternitz parameter, */ -#define PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_WOTS_W 16 - -/* The hash function is defined by linking a different hash.c file, as opposed - to setting a #define constant. */ - -/* For clarity */ -#define PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_ADDR_BYTES 32 - -/* WOTS parameters. */ -#define PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_WOTS_LOGW 4 - -#define PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_WOTS_LEN1 (8 * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_N / PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_WOTS_LOGW) - -/* PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#define PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_WOTS_LEN2 3 - -#define PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_WOTS_LEN (PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_WOTS_LEN1 + PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_WOTS_LEN2) -#define PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_WOTS_BYTES (PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_WOTS_LEN * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_N) -#define PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_WOTS_PK_BYTES PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_WOTS_BYTES - -/* Subtree size. */ -#define PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_TREE_HEIGHT (PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_FULL_HEIGHT / PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_D) - -/* FORS parameters. */ -#define PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_FORS_MSG_BYTES ((PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_FORS_TREES + 7) / 8) -#define PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_FORS_BYTES ((PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_FORS_HEIGHT + 1) * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_FORS_TREES * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_N) -#define PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_FORS_PK_BYTES PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_N - -/* Resulting SPX sizes. */ -#define PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_BYTES (PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_N + PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_FORS_BYTES + PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_D * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_WOTS_BYTES +\ - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_FULL_HEIGHT * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_N) -#define PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_PK_BYTES (2 * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_N) -#define PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_SK_BYTES (2 * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_N + PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_PK_BYTES) - -/* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ -#define PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_OPTRAND_BYTES 32 - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_clean/sign.c b/src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_clean/sign.c deleted file mode 100644 index a02739cfff..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_clean/sign.c +++ /dev/null @@ -1,356 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "api.h" -#include "fors.h" -#include "hash.h" -#include "hash_state.h" -#include "params.h" -#include "randombytes.h" -#include "thash.h" -#include "utils.h" -#include "wots.h" - -/** - * Computes the leaf at a given address. First generates the WOTS key pair, - * then computes leaf by hashing horizontally. - */ -static void wots_gen_leaf(unsigned char *leaf, const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx, const uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - unsigned char pk[PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_WOTS_BYTES]; - uint32_t wots_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_set_type( - wots_addr, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_set_type( - wots_pk_addr, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_ADDR_TYPE_WOTSPK); - - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_set_keypair_addr( - wots_addr, addr_idx); - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_wots_gen_pk( - pk, sk_seed, pub_seed, wots_addr, hash_state_seeded); - - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_copy_keypair_addr( - wots_pk_addr, wots_addr); - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_thash_WOTS_LEN( - leaf, pk, pub_seed, wots_pk_addr, hash_state_seeded); -} - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_crypto_sign_secretkeybytes(void) { - return PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_CRYPTO_SECRETKEYBYTES; -} - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_crypto_sign_publickeybytes(void) { - return PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_CRYPTO_PUBLICKEYBYTES; -} - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_crypto_sign_bytes(void) { - return PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_CRYPTO_BYTES; -} - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_crypto_sign_seedbytes(void) { - return PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_CRYPTO_SEEDBYTES; -} - -/* - * Generates an SPX key pair given a seed of length - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed) { - /* We do not need the auth path in key generation, but it simplifies the - code to have just one treehash routine that computes both root and path - in one function. */ - unsigned char auth_path[PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_TREE_HEIGHT * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_N]; - uint32_t top_tree_addr[8] = {0}; - hash_state hash_state_seeded; - - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_set_layer_addr( - top_tree_addr, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_D - 1); - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_set_type( - top_tree_addr, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_ADDR_TYPE_HASHTREE); - - /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ - memcpy(sk, seed, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_CRYPTO_SEEDBYTES); - - memcpy(pk, sk + 2 * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_N, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_initialize_hash_function(&hash_state_seeded, pk, sk); - - /* Compute root node of the top-most subtree. */ - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_treehash_TREE_HEIGHT( - sk + 3 * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_N, auth_path, sk, sk + 2 * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_N, 0, 0, - wots_gen_leaf, top_tree_addr, &hash_state_seeded); - - memcpy(pk + PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_N, sk + 3 * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_N, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_N); - - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_destroy_hash_function(&hash_state_seeded); - return 0; -} - -/* - * Generates an SPX key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk) { - unsigned char seed[PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_CRYPTO_SEEDBYTES]; - randombytes(seed, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_CRYPTO_SEEDBYTES); - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_crypto_sign_seed_keypair( - pk, sk, seed); - - return 0; -} - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - const unsigned char *sk_seed = sk; - const unsigned char *sk_prf = sk + PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_N; - const unsigned char *pk = sk + 2 * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_N; - const unsigned char *pub_seed = pk; - - unsigned char optrand[PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_N]; - unsigned char mhash[PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_FORS_MSG_BYTES]; - unsigned char root[PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_N]; - uint32_t i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - - hash_state hash_state_seeded; - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_initialize_hash_function( - &hash_state_seeded, - pub_seed, sk_seed); - - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_set_type( - wots_addr, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_set_type( - tree_addr, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_ADDR_TYPE_HASHTREE); - - /* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ - randombytes(optrand, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_N); - /* Compute the digest randomization value. */ - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_gen_message_random( - sig, sk_prf, optrand, m, mlen, &hash_state_seeded); - - /* Derive the message digest and leaf index from R, PK and M. */ - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_N; - - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); - - /* Sign the message hash using FORS. */ - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_fors_sign( - sig, root, mhash, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_FORS_BYTES; - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_D; i++) { - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_set_tree_addr(tree_addr, tree); - - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); - - /* Compute a WOTS signature. */ - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_wots_sign( - sig, root, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_WOTS_BYTES; - - /* Compute the authentication path for the used WOTS leaf. */ - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_treehash_TREE_HEIGHT( - root, sig, sk_seed, pub_seed, idx_leaf, 0, - wots_gen_leaf, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_TREE_HEIGHT * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_TREE_HEIGHT; - } - - *siglen = PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_BYTES; - - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_destroy_hash_function(&hash_state_seeded); - return 0; -} - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk) { - const unsigned char *pub_seed = pk; - const unsigned char *pub_root = pk + PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_N; - unsigned char mhash[PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_FORS_MSG_BYTES]; - unsigned char wots_pk[PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_WOTS_BYTES]; - unsigned char root[PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_N]; - unsigned char leaf[PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_N]; - unsigned int i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - hash_state hash_state_seeded; - - if (siglen != PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_BYTES) { - return -1; - } - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_initialize_hash_function( - &hash_state_seeded, - pub_seed, NULL); - - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_set_type( - wots_addr, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_set_type( - tree_addr, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_ADDR_TYPE_HASHTREE); - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_set_type( - wots_pk_addr, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_ADDR_TYPE_WOTSPK); - - /* Derive the message digest and leaf index from R || PK || M. */ - /* The additional PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_N is a result of the hash domain separator. */ - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_N; - - /* Layer correctly defaults to 0, so no need to set_layer_addr */ - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); - - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_fors_pk_from_sig( - root, sig, mhash, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_FORS_BYTES; - - /* For each subtree.. */ - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_D; i++) { - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_set_tree_addr(tree_addr, tree); - - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); - - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_copy_keypair_addr( - wots_pk_addr, wots_addr); - - /* The WOTS public key is only correct if the signature was correct. */ - /* Initially, root is the FORS pk, but on subsequent iterations it is - the root of the subtree below the currently processed subtree. */ - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_wots_pk_from_sig( - wots_pk, sig, root, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_WOTS_BYTES; - - /* Compute the leaf node using the WOTS public key. */ - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_thash_WOTS_LEN( - leaf, wots_pk, pub_seed, wots_pk_addr, &hash_state_seeded); - - /* Compute the root node of this subtree. */ - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_compute_root( - root, leaf, idx_leaf, 0, sig, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_TREE_HEIGHT, - pub_seed, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_TREE_HEIGHT * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_TREE_HEIGHT; - } - - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_destroy_hash_function(&hash_state_seeded); - /* Check if the root node equals the root node in the public key. */ - if (memcmp(root, pub_root, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_N) != 0) { - return -1; - } - - return 0; -} - - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - size_t siglen; - - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_crypto_sign_signature( - sm, &siglen, m, mlen, sk); - - memmove(sm + PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_BYTES, m, mlen); - *smlen = siglen + mlen; - - return 0; -} - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk) { - /* The API caller does not necessarily know what size a signature should be - but SPHINCS+ signatures are always exactly PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_BYTES. */ - if (smlen < PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_BYTES) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - *mlen = smlen - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_BYTES; - - if (PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_crypto_sign_verify( - sm, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_BYTES, sm + PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_BYTES, *mlen, pk)) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - /* If verification was successful, move the message to the right place. */ - memmove(m, sm + PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_BYTES, *mlen); - - return 0; -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_clean/thash.h b/src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_clean/thash.h deleted file mode 100644 index dd5703537c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_clean/thash.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_THASH_H -#define PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_THASH_H - -#include "hash_state.h" - -#include - -void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_clean/thash_shake256_simple.c b/src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_clean/thash_shake256_simple.c deleted file mode 100644 index 1de75bf877..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_clean/thash_shake256_simple.c +++ /dev/null @@ -1,74 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash_state.h" -#include "params.h" -#include "thash.h" - -#include "fips202.h" - -/** - * Takes an array of inblocks concatenated arrays of PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_N bytes. - */ -static void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_thash( - unsigned char *out, unsigned char *buf, - const unsigned char *in, unsigned int inblocks, - const unsigned char *pub_seed, uint32_t addr[8]) { - - memcpy(buf, pub_seed, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_N); - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_addr_to_bytes(buf + PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_N, addr); - memcpy(buf + PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_N + PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_ADDR_BYTES, in, inblocks * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_N); - - shake256(out, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_N, buf, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_N + PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_N); -} - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_N + PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_ADDR_BYTES + 1 * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_N]; - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_thash( - out, buf, in, 1, pub_seed, addr); - - (void)hash_state_seeded; /* Avoid unused parameter warning. */ -} - -void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_N + PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_ADDR_BYTES + 2 * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_N]; - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_thash( - out, buf, in, 2, pub_seed, addr); - - (void)hash_state_seeded; /* Avoid unused parameter warning. */ -} - -void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_N + PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_ADDR_BYTES + PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_WOTS_LEN * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_N]; - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_thash( - out, buf, in, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_WOTS_LEN, pub_seed, addr); - - (void)hash_state_seeded; /* Avoid unused parameter warning. */ -} - -void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_N + PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_ADDR_BYTES + PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_FORS_TREES * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_N]; - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_thash( - out, buf, in, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_FORS_TREES, pub_seed, addr); - - (void)hash_state_seeded; /* Avoid unused parameter warning. */ -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_clean/utils.c b/src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_clean/utils.c deleted file mode 100644 index da9c09143a..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_clean/utils.c +++ /dev/null @@ -1,199 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "hash_state.h" -#include "params.h" -#include "thash.h" -#include "utils.h" - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in) { - - /* Iterate over out in decreasing order, for big-endianness. */ - for (size_t i = outlen; i > 0; i--) { - out[i - 1] = in & 0xff; - in = in >> 8; - } -} - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_bytes_to_ull( - const unsigned char *in, size_t inlen) { - unsigned long long retval = 0; - - for (size_t i = 0; i < inlen; i++) { - retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); - } - return retval; -} - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - uint32_t i; - unsigned char buffer[2 * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_N]; - - /* If leaf_idx is odd (last bit = 1), current path element is a right child - and auth_path has to go left. Otherwise it is the other way around. */ - if (leaf_idx & 1) { - memcpy(buffer + PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_N, leaf, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_N); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_N); - } else { - memcpy(buffer, leaf, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_N); - memcpy(buffer + PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_N, auth_path, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_N); - } - auth_path += PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_N; - - for (i = 0; i < tree_height - 1; i++) { - leaf_idx >>= 1; - idx_offset >>= 1; - /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_set_tree_height(addr, i + 1); - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_set_tree_index( - addr, leaf_idx + idx_offset); - - /* Pick the right or left neighbor, depending on parity of the node. */ - if (leaf_idx & 1) { - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_thash_2( - buffer + PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_N, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_N); - } else { - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_thash_2( - buffer, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer + PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_N, auth_path, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_N); - } - auth_path += PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_N; - } - - /* The last iteration is exceptional; we do not copy an auth_path node. */ - leaf_idx >>= 1; - idx_offset >>= 1; - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_set_tree_height(addr, tree_height); - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_set_tree_index( - addr, leaf_idx + idx_offset); - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_thash_2( - root, buffer, pub_seed, addr, hash_state_seeded); -} - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -static void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_treehash( - unsigned char *root, unsigned char *auth_path, - unsigned char *stack, unsigned int *heights, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - - unsigned int offset = 0; - uint32_t idx; - uint32_t tree_idx; - - for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { - /* Add the next leaf node to the stack. */ - gen_leaf(stack + offset * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_N, - sk_seed, pub_seed, idx + idx_offset, tree_addr, - hash_state_seeded); - offset++; - heights[offset - 1] = 0; - - /* If this is a node we need for the auth path.. */ - if ((leaf_idx ^ 0x1) == idx) { - memcpy(auth_path, stack + (offset - 1)*PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_N, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_N); - } - - /* While the top-most nodes are of equal height.. */ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { - /* Compute index of the new node, in the next layer. */ - tree_idx = (idx >> (heights[offset - 1] + 1)); - - /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_set_tree_height( - tree_addr, heights[offset - 1] + 1); - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_set_tree_index( - tree_addr, tree_idx + (idx_offset >> (heights[offset - 1] + 1))); - /* Hash the top-most nodes from the stack together. */ - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_thash_2( - stack + (offset - 2)*PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_N, stack + (offset - 2)*PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_N, - pub_seed, tree_addr, hash_state_seeded); - offset--; - /* Note that the top-most node is now one layer higher. */ - heights[offset - 1]++; - - /* If this is a node we need for the auth path.. */ - if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_path + heights[offset - 1]*PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_N, - stack + (offset - 1)*PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_N, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_N); - } - } - } - memcpy(root, stack, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_N); -} - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_FORS_HEIGHT + 1)*PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_N]; - unsigned int heights[PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_FORS_HEIGHT + 1]; - - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_FORS_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_TREE_HEIGHT + 1)*PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_N]; - unsigned int heights[PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_TREE_HEIGHT + 1]; - - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_TREE_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_clean/utils.h b/src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_clean/utils.h deleted file mode 100644 index d399d1230b..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_clean/utils.h +++ /dev/null @@ -1,64 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_UTILS_H -#define PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_UTILS_H - -#include "hash_state.h" -#include "params.h" -#include -#include - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in); - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_bytes_to_ull( - const unsigned char *in, size_t inlen); - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_clean/wots.c b/src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_clean/wots.c deleted file mode 100644 index 7ce0bb8937..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_clean/wots.c +++ /dev/null @@ -1,167 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "hash_state.h" -#include "params.h" -#include "thash.h" -#include "utils.h" -#include "wots.h" - -// TODO clarify address expectations, and make them more uniform. -// TODO i.e. do we expect types to be set already? -// TODO and do we expect modifications or copies? - -/** - * Computes the starting value for a chain, i.e. the secret key. - * Expects the address to be complete up to the chain address. - */ -static void wots_gen_sk(unsigned char *sk, const unsigned char *sk_seed, - uint32_t wots_addr[8], - const hash_state *hash_state_seeded) { - /* Make sure that the hash address is actually zeroed. */ - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_set_hash_addr(wots_addr, 0); - - /* Generate sk element. */ - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_prf_addr(sk, sk_seed, wots_addr, hash_state_seeded); -} - -/** - * Computes the chaining function. - * out and in have to be n-byte arrays. - * - * Interprets in as start-th value of the chain. - * addr has to contain the address of the chain. - */ -static void gen_chain(unsigned char *out, const unsigned char *in, - unsigned int start, unsigned int steps, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - uint32_t i; - - /* Initialize out with the value at position 'start'. */ - memcpy(out, in, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_N); - - /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_WOTS_W; i++) { - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_set_hash_addr(addr, i); - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_thash_1( - out, out, pub_seed, addr, hash_state_seeded); - } -} - -/** - * base_w algorithm as described in draft. - * Interprets an array of bytes as integers in base w. - * This only works when log_w is a divisor of 8. - */ -static void base_w(unsigned int *output, const size_t out_len, - const unsigned char *input) { - size_t in = 0; - size_t out = 0; - unsigned char total = 0; - unsigned int bits = 0; - size_t consumed; - - for (consumed = 0; consumed < out_len; consumed++) { - if (bits == 0) { - total = input[in]; - in++; - bits += 8; - } - bits -= PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_WOTS_LOGW; - output[out] = (unsigned int)((total >> bits) & (PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_WOTS_W - 1)); - out++; - } -} - -/* Computes the WOTS+ checksum over a message (in base_w). */ -static void wots_checksum(unsigned int *csum_base_w, - const unsigned int *msg_base_w) { - unsigned int csum = 0; - unsigned char csum_bytes[(PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_WOTS_LEN2 * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_WOTS_LOGW + 7) / 8]; - unsigned int i; - - /* Compute checksum. */ - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_WOTS_LEN1; i++) { - csum += PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_WOTS_W - 1 - msg_base_w[i]; - } - - /* Convert checksum to base_w. */ - /* Make sure expected empty zero bits are the least significant bits. */ - csum = csum << (8 - ((PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_WOTS_LEN2 * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_WOTS_LOGW) % 8)); - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_ull_to_bytes( - csum_bytes, sizeof(csum_bytes), csum); - base_w(csum_base_w, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_WOTS_LEN2, csum_bytes); -} - -/* Takes a message and derives the matching chain lengths. */ -static void chain_lengths(unsigned int *lengths, const unsigned char *msg) { - base_w(lengths, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_WOTS_LEN1, msg); - wots_checksum(lengths + PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_WOTS_LEN1, lengths); -} - -/** - * WOTS key generation. Takes a 32 byte sk_seed, expands it to WOTS private key - * elements and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_wots_gen_pk( - unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - uint32_t i; - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_WOTS_LEN; i++) { - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_set_chain_addr(addr, i); - wots_gen_sk(pk + i * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_N, sk_seed, addr, hash_state_seeded); - gen_chain(pk + i * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_N, pk + i * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_N, - 0, PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_WOTS_W - 1, pub_seed, addr, hash_state_seeded); - } -} - -/** - * Takes a n-byte message and the 32-byte sk_see to compute a signature 'sig'. - */ -void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_wots_sign( - unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *hash_state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_WOTS_LEN; i++) { - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_set_chain_addr(addr, i); - wots_gen_sk(sig + i * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_N, sk_seed, addr, hash_state_seeded); - gen_chain(sig + i * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_N, sig + i * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_N, 0, lengths[i], pub_seed, addr, hash_state_seeded); - } -} - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_wots_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_WOTS_LEN; i++) { - PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_set_chain_addr(addr, i); - gen_chain(pk + i * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_N, sig + i * PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_N, - lengths[i], PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_WOTS_W - 1 - lengths[i], pub_seed, addr, - hash_state_seeded); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_clean/wots.h b/src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_clean/wots.h deleted file mode 100644 index 787b2971ae..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-128s-simple_clean/wots.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_WOTS_H -#define PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_WOTS_H - -#include "hash_state.h" -#include "params.h" -#include - -/** - * WOTS key generation. Takes a 32 byte seed for the private key, expands it to - * a full WOTS private key and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_wots_gen_pk( - unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -/** - * Takes a n-byte message and the 32-byte seed for the private key to compute a - * signature that is placed at 'sig'. - */ -void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_wots_sign( - unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *hash_state_seeded); - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_wots_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_avx2/LICENSE b/src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_avx2/LICENSE deleted file mode 100644 index 670154e353..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_avx2/LICENSE +++ /dev/null @@ -1,116 +0,0 @@ -CC0 1.0 Universal - -Statement of Purpose - -The laws of most jurisdictions throughout the world automatically confer -exclusive Copyright and Related Rights (defined below) upon the creator and -subsequent owner(s) (each and all, an "owner") of an original work of -authorship and/or a database (each, a "Work"). - -Certain owners wish to permanently relinquish those rights to a Work for the -purpose of contributing to a commons of creative, cultural and scientific -works ("Commons") that the public can reliably and without fear of later -claims of infringement build upon, modify, incorporate in other works, reuse -and redistribute as freely as possible in any form whatsoever and for any -purposes, including without limitation commercial purposes. These owners may -contribute to the Commons to promote the ideal of a free culture and the -further production of creative, cultural and scientific works, or to gain -reputation or greater distribution for their Work in part through the use and -efforts of others. - -For these and/or other purposes and motivations, and without any expectation -of additional consideration or compensation, the person associating CC0 with a -Work (the "Affirmer"), to the extent that he or she is an owner of Copyright -and Related Rights in the Work, voluntarily elects to apply CC0 to the Work -and publicly distribute the Work under its terms, with knowledge of his or her -Copyright and Related Rights in the Work and the meaning and intended legal -effect of CC0 on those rights. - -1. Copyright and Related Rights. A Work made available under CC0 may be -protected by copyright and related or neighboring rights ("Copyright and -Related Rights"). Copyright and Related Rights include, but are not limited -to, the following: - - i. the right to reproduce, adapt, distribute, perform, display, communicate, - and translate a Work; - - ii. moral rights retained by the original author(s) and/or performer(s); - - iii. publicity and privacy rights pertaining to a person's image or likeness - depicted in a Work; - - iv. rights protecting against unfair competition in regards to a Work, - subject to the limitations in paragraph 4(a), below; - - v. rights protecting the extraction, dissemination, use and reuse of data in - a Work; - - vi. database rights (such as those arising under Directive 96/9/EC of the - European Parliament and of the Council of 11 March 1996 on the legal - protection of databases, and under any national implementation thereof, - including any amended or successor version of such directive); and - - vii. other similar, equivalent or corresponding rights throughout the world - based on applicable law or treaty, and any national implementations thereof. - -2. Waiver. To the greatest extent permitted by, but not in contravention of, -applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and -unconditionally waives, abandons, and surrenders all of Affirmer's Copyright -and Related Rights and associated claims and causes of action, whether now -known or unknown (including existing as well as future claims and causes of -action), in the Work (i) in all territories worldwide, (ii) for the maximum -duration provided by applicable law or treaty (including future time -extensions), (iii) in any current or future medium and for any number of -copies, and (iv) for any purpose whatsoever, including without limitation -commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes -the Waiver for the benefit of each member of the public at large and to the -detriment of Affirmer's heirs and successors, fully intending that such Waiver -shall not be subject to revocation, rescission, cancellation, termination, or -any other legal or equitable action to disrupt the quiet enjoyment of the Work -by the public as contemplated by Affirmer's express Statement of Purpose. - -3. Public License Fallback. Should any part of the Waiver for any reason be -judged legally invalid or ineffective under applicable law, then the Waiver -shall be preserved to the maximum extent permitted taking into account -Affirmer's express Statement of Purpose. In addition, to the extent the Waiver -is so judged Affirmer hereby grants to each affected person a royalty-free, -non transferable, non sublicensable, non exclusive, irrevocable and -unconditional license to exercise Affirmer's Copyright and Related Rights in -the Work (i) in all territories worldwide, (ii) for the maximum duration -provided by applicable law or treaty (including future time extensions), (iii) -in any current or future medium and for any number of copies, and (iv) for any -purpose whatsoever, including without limitation commercial, advertising or -promotional purposes (the "License"). The License shall be deemed effective as -of the date CC0 was applied by Affirmer to the Work. Should any part of the -License for any reason be judged legally invalid or ineffective under -applicable law, such partial invalidity or ineffectiveness shall not -invalidate the remainder of the License, and in such case Affirmer hereby -affirms that he or she will not (i) exercise any of his or her remaining -Copyright and Related Rights in the Work or (ii) assert any associated claims -and causes of action with respect to the Work, in either case contrary to -Affirmer's express Statement of Purpose. - -4. Limitations and Disclaimers. - - a. No trademark or patent rights held by Affirmer are waived, abandoned, - surrendered, licensed or otherwise affected by this document. - - b. Affirmer offers the Work as-is and makes no representations or warranties - of any kind concerning the Work, express, implied, statutory or otherwise, - including without limitation warranties of title, merchantability, fitness - for a particular purpose, non infringement, or the absence of latent or - other defects, accuracy, or the present or absence of errors, whether or not - discoverable, all to the greatest extent permissible under applicable law. - - c. Affirmer disclaims responsibility for clearing rights of other persons - that may apply to the Work or any use thereof, including without limitation - any person's Copyright and Related Rights in the Work. Further, Affirmer - disclaims responsibility for obtaining any necessary consents, permissions - or other rights required for any use of the Work. - - d. Affirmer understands and acknowledges that Creative Commons is not a - party to this document and has no duty or obligation with respect to this - CC0 or use of the Work. - -For more information, please see - diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_avx2/address.c b/src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_avx2/address.c deleted file mode 100644 index 8cf6b1511e..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_avx2/address.c +++ /dev/null @@ -1,78 +0,0 @@ -#include - -#include "address.h" -#include "params.h" -#include "utils.h" - -void PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]) { - int i; - - for (i = 0; i < 8; i++) { - PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_ull_to_bytes( - bytes + i * 4, 4, addr[i]); - } -} - -void PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_set_layer_addr( - uint32_t addr[8], uint32_t layer) { - addr[0] = layer; -} - -void PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_set_tree_addr( - uint32_t addr[8], uint64_t tree) { - addr[1] = 0; - addr[2] = (uint32_t) (tree >> 32); - addr[3] = (uint32_t) tree; -} - -void PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_set_type( - uint32_t addr[8], uint32_t type) { - addr[4] = type; -} - -void PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; -} - -/* These functions are used for OTS addresses. */ - -void PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_set_keypair_addr( - uint32_t addr[8], uint32_t keypair) { - addr[5] = keypair; -} - -void PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; - out[5] = in[5]; -} - -void PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_set_chain_addr( - uint32_t addr[8], uint32_t chain) { - addr[6] = chain; -} - -void PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_set_hash_addr( - uint32_t addr[8], uint32_t hash) { - addr[7] = hash; -} - -/* These functions are used for all hash tree addresses (including FORS). */ - -void PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_set_tree_height( - uint32_t addr[8], uint32_t tree_height) { - addr[6] = tree_height; -} - -void PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_set_tree_index( - uint32_t addr[8], uint32_t tree_index) { - addr[7] = tree_index; -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_avx2/address.h b/src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_avx2/address.h deleted file mode 100644 index f8fb1505a9..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_avx2/address.h +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_ADDRESS_H -#define PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_ADDRESS_H - -#include - -#define PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_ADDR_TYPE_WOTS 0 -#define PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_ADDR_TYPE_WOTSPK 1 -#define PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_ADDR_TYPE_HASHTREE 2 -#define PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_ADDR_TYPE_FORSTREE 3 -#define PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_ADDR_TYPE_FORSPK 4 - -void PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]); - -void PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_set_layer_addr( - uint32_t addr[8], uint32_t layer); - -void PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_set_tree_addr( - uint32_t addr[8], uint64_t tree); - -void PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_set_type( - uint32_t addr[8], uint32_t type); - -/* Copies the layer and tree part of one address into the other */ -void PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for WOTS and FORS addresses. */ - -void PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_set_keypair_addr( - uint32_t addr[8], uint32_t keypair); - -void PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_set_chain_addr( - uint32_t addr[8], uint32_t chain); - -void PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_set_hash_addr( - uint32_t addr[8], uint32_t hash); - -void PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for all hash tree addresses (including FORS). */ - -void PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_set_tree_height( - uint32_t addr[8], uint32_t tree_height); - -void PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_set_tree_index( - uint32_t addr[8], uint32_t tree_index); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_avx2/api.h b/src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_avx2/api.h deleted file mode 100644 index aefa2bb23b..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_avx2/api.h +++ /dev/null @@ -1,81 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_API_H -#define PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_API_H - -#include -#include - - - -#define PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_CRYPTO_ALGNAME "SPHINCS+" - -#define PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_CRYPTO_SECRETKEYBYTES 96 -#define PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_CRYPTO_PUBLICKEYBYTES 48 -#define PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_CRYPTO_BYTES 35664 -#define PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_CRYPTO_SEEDBYTES 72 - - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_avx2/fors.c b/src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_avx2/fors.c deleted file mode 100644 index 0dd32a422c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_avx2/fors.c +++ /dev/null @@ -1,206 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "fors.h" -#include "hash.h" -#include "hashx4.h" -#include "thash.h" -#include "thashx4.h" -#include "utils.h" -#include "utilsx4.h" - -static void fors_gen_skx4(unsigned char *sk0, - unsigned char *sk1, - unsigned char *sk2, - unsigned char *sk3, const unsigned char *sk_seed, - uint32_t fors_leaf_addrx4[4 * 8], - const hash_state *state_seeded) { - PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_prf_addrx4(sk0, sk1, sk2, sk3, sk_seed, fors_leaf_addrx4, state_seeded); -} - -static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, - const unsigned char *pub_seed, - uint32_t fors_leaf_addr[8], const hash_state *state_seeded) { - PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_thash_1(leaf, sk, pub_seed, fors_leaf_addr, state_seeded); -} - -static void fors_sk_to_leafx4(unsigned char *leaf0, - unsigned char *leaf1, - unsigned char *leaf2, - unsigned char *leaf3, - const unsigned char *sk0, - const unsigned char *sk1, - const unsigned char *sk2, - const unsigned char *sk3, - const unsigned char *pub_seed, - uint32_t fors_leaf_addrx4[4 * 8], - const hash_state *state_seeded) { - PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_thashx4_1(leaf0, leaf1, leaf2, leaf3, - sk0, sk1, sk2, sk3, pub_seed, fors_leaf_addrx4, state_seeded); -} - -static void fors_gen_leafx4(unsigned char *leaf0, - unsigned char *leaf1, - unsigned char *leaf2, - unsigned char *leaf3, - const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx0, - uint32_t addr_idx1, - uint32_t addr_idx2, - uint32_t addr_idx3, - const uint32_t fors_tree_addr[8], - const hash_state *state_seeded) { - uint32_t fors_leaf_addrx4[4 * 8] = {0}; - unsigned int j; - - /* Only copy the parts that must be kept in fors_leaf_addrx4. */ - for (j = 0; j < 4; j++) { - PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_copy_keypair_addr(fors_leaf_addrx4 + j * 8, fors_tree_addr); - PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_set_type(fors_leaf_addrx4 + j * 8, PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_ADDR_TYPE_FORSTREE); - } - - PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_set_tree_index(fors_leaf_addrx4 + 0 * 8, addr_idx0); - PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_set_tree_index(fors_leaf_addrx4 + 1 * 8, addr_idx1); - PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_set_tree_index(fors_leaf_addrx4 + 2 * 8, addr_idx2); - PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_set_tree_index(fors_leaf_addrx4 + 3 * 8, addr_idx3); - - fors_gen_skx4(leaf0, leaf1, leaf2, leaf3, sk_seed, fors_leaf_addrx4, state_seeded); - fors_sk_to_leafx4(leaf0, leaf1, leaf2, leaf3, - leaf0, leaf1, leaf2, leaf3, pub_seed, fors_leaf_addrx4, state_seeded); -} - -/** - * Interprets m as PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_FORS_HEIGHT-bit unsigned integers. - * Assumes m contains at least PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_FORS_TREES bits. - * Assumes indices has space for PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_FORS_TREES integers. - */ -static void message_to_indices(uint32_t *indices, const unsigned char *m) { - unsigned int i, j; - unsigned int offset = 0; - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_FORS_TREES; i++) { - indices[i] = 0; - for (j = 0; j < PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_FORS_HEIGHT; j++) { - indices[i] ^= (((uint32_t)m[offset >> 3] >> (offset & 0x7)) & 0x1) << j; - offset++; - } - } -} - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *state_seeded) { - /* Round up to multiple of 4 to prevent out-of-bounds for x4 parallelism */ - uint32_t indices[(PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_FORS_TREES + 3) & ~3] = {0}; - unsigned char roots[((PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_FORS_TREES + 3) & ~3) * PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N]; - /* Sign to a buffer, since we may not have a nice multiple of 4 and would - otherwise overrun the signature. */ - unsigned char sigbufx4[4 * PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N * (1 + PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_FORS_HEIGHT)]; - uint32_t fors_tree_addrx4[4 * 8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset[4] = {0}; - unsigned int i, j; - - for (j = 0; j < 4; j++) { - PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_copy_keypair_addr(fors_tree_addrx4 + j * 8, fors_addr); - PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_set_type(fors_tree_addrx4 + j * 8, PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_ADDR_TYPE_FORSTREE); - } - - PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_copy_keypair_addr(fors_pk_addr, fors_addr); - PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_set_type(fors_pk_addr, PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < ((PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_FORS_TREES + 3) & ~0x3); i += 4) { - for (j = 0; j < 4; j++) { - if (i + j < PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_FORS_TREES) { - idx_offset[j] = (i + j) * (1 << PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_FORS_HEIGHT); - - PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_set_tree_height(fors_tree_addrx4 + j * 8, 0); - PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_set_tree_index(fors_tree_addrx4 + j * 8, - indices[i + j] + idx_offset[j]); - } - } - - /* Include the secret key part that produces the selected leaf nodes. */ - fors_gen_skx4(sigbufx4 + 0 * PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N, - sigbufx4 + 1 * PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N, - sigbufx4 + 2 * PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N, - sigbufx4 + 3 * PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N, - sk_seed, fors_tree_addrx4, state_seeded); - - PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_treehashx4_FORS_HEIGHT(roots + i * PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N, sigbufx4 + 4 * PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N, sk_seed, pub_seed, - &indices[i], idx_offset, fors_gen_leafx4, fors_tree_addrx4, - state_seeded); - - for (j = 0; j < 4; j++) { - if (i + j < PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_FORS_TREES) { - memcpy(sig, sigbufx4 + j * PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N, PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N); - memcpy(sig + PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N, - sigbufx4 + 4 * PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N + j * PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N * PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_FORS_HEIGHT, - PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N * PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_FORS_HEIGHT); - sig += PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N * (1 + PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_FORS_HEIGHT); - } - } - } - - /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_thash_FORS_TREES(pk, roots, pub_seed, fors_pk_addr, state_seeded); -} - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, - const uint32_t fors_addr[8], - const hash_state *state_seeded) { - uint32_t indices[PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_FORS_TREES]; - unsigned char roots[PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_FORS_TREES * PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N]; - unsigned char leaf[PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N]; - uint32_t fors_tree_addr[8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_copy_keypair_addr(fors_tree_addr, fors_addr); - PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_copy_keypair_addr(fors_pk_addr, fors_addr); - - PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_set_type(fors_tree_addr, PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_set_type(fors_pk_addr, PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_FORS_TREES; i++) { - idx_offset = i * (1 << PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_FORS_HEIGHT); - - PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_set_tree_height(fors_tree_addr, 0); - PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Derive the leaf from the included secret key part. */ - fors_sk_to_leaf(leaf, sig, pub_seed, fors_tree_addr, state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N; - - /* Derive the corresponding root node of this tree. */ - PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_compute_root(roots + i * PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N, leaf, indices[i], idx_offset, - sig, PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_FORS_HEIGHT, pub_seed, fors_tree_addr, - state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N * PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_thash_FORS_TREES(pk, roots, pub_seed, fors_pk_addr, state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_avx2/fors.h b/src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_avx2/fors.h deleted file mode 100644 index 3463a5a580..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_avx2/fors.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_FORS_H -#define PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_FORS_H - -#include - -#include "hash_state.h" -#include "params.h" - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_fors_sign( - unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *hash_state_seeded); - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_fors_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, const uint32_t fors_addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_avx2/hash.h b/src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_avx2/hash.h deleted file mode 100644 index 324ea40a06..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_avx2/hash.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_HASH_H -#define PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_HASH_H - -#include "hash_state.h" - -#include -#include - -void PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_initialize_hash_function( - hash_state *hash_state_seeded, - const unsigned char *pub_seed, const unsigned char *sk_seed); - -void PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_destroy_hash_function(hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_avx2/hash_shake256.c b/src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_avx2/hash_shake256.c deleted file mode 100644 index 08cc063ebd..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_avx2/hash_shake256.c +++ /dev/null @@ -1,106 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "utils.h" - -#include "fips202.h" - -/* For SHAKE256, there is no immediate reason to initialize at the start, - so this function is an empty operation. */ -void PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_initialize_hash_function( - hash_state *hash_state_seeded, // NOLINT(readability-non-const-parameter) - const unsigned char *pub_seed, const unsigned char *sk_seed) { - (void)hash_state_seeded; /* Suppress an 'unused parameter' warning. */ - (void)pub_seed; /* Suppress an 'unused parameter' warning. */ - (void)sk_seed; /* Suppress an 'unused parameter' warning. */ -} - -/* This is not necessary for SHAKE256, so we don't do anything */ -void PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_destroy_hash_function( - hash_state *hash_state_seeded) { // NOLINT(readability-non-const-parameter) - (void)hash_state_seeded; -} - -/* - * Computes PRF(key, addr), given a secret key of PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N bytes and an address - */ -void PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded) { - unsigned char buf[PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_ADDR_BYTES]; - - memcpy(buf, key, PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N); - PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_addr_to_bytes(buf + PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N, addr); - - shake256(out, PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N, buf, PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_ADDR_BYTES); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} - -/** - * Computes the message-dependent randomness R, using a secret seed and an - * optional randomization value as well as the message. - */ -void PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded) { - shake256incctx state; - - shake256_inc_init(&state); - shake256_inc_absorb(&state, sk_prf, PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N); - shake256_inc_absorb(&state, optrand, PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N); - shake256_inc_absorb(&state, m, mlen); - shake256_inc_finalize(&state); - shake256_inc_squeeze(R, PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N, &state); - shake256_inc_ctx_release(&state); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} - -/** - * Computes the message hash using R, the public key, and the message. - * Outputs the message digest and the index of the leaf. The index is split in - * the tree index and the leaf index, for convenient copying to an address. - */ -void PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded) { -#define PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_TREE_BITS (PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_TREE_HEIGHT * (PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_D - 1)) -#define PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_TREE_BYTES ((PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_TREE_BITS + 7) / 8) -#define PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_LEAF_BITS PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_TREE_HEIGHT -#define PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_LEAF_BYTES ((PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_LEAF_BITS + 7) / 8) -#define PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_DGST_BYTES (PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_FORS_MSG_BYTES + PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_TREE_BYTES + PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_LEAF_BYTES) - - unsigned char buf[PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_DGST_BYTES]; - unsigned char *bufp = buf; - shake256incctx state; - - shake256_inc_init(&state); - shake256_inc_absorb(&state, R, PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N); - shake256_inc_absorb(&state, pk, PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_PK_BYTES); - shake256_inc_absorb(&state, m, mlen); - shake256_inc_finalize(&state); - shake256_inc_squeeze(buf, PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_DGST_BYTES, &state); - shake256_inc_ctx_release(&state); - - memcpy(digest, bufp, PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_FORS_MSG_BYTES); - bufp += PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_FORS_MSG_BYTES; - - *tree = PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_bytes_to_ull( - bufp, PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_TREE_BYTES); - *tree &= (~(uint64_t)0) >> (64 - PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_TREE_BITS); - bufp += PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_TREE_BYTES; - - *leaf_idx = (uint32_t)PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_bytes_to_ull( - bufp, PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_LEAF_BYTES); - *leaf_idx &= (~(uint32_t)0) >> (32 - PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_LEAF_BITS); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_avx2/hash_shake256x4.c b/src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_avx2/hash_shake256x4.c deleted file mode 100644 index c780e4bba5..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_avx2/hash_shake256x4.c +++ /dev/null @@ -1,38 +0,0 @@ -#include -#include - -#include "address.h" -#include "fips202x4.h" -#include "hashx4.h" -#include "params.h" - -/* - * 4-way parallel version of prf_addr; takes 4x as much input and output - */ -void PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_prf_addrx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const unsigned char *key, - const uint32_t addrx4[4 * 8], - const hash_state *state_seeded) { - unsigned char bufx4[4 * (PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_ADDR_BYTES)]; - unsigned int j; - - for (j = 0; j < 4; j++) { - memcpy(bufx4 + j * (PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_ADDR_BYTES), key, PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N); - PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_addr_to_bytes(bufx4 + PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N + j * (PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_ADDR_BYTES), addrx4 + j * 8); - } - - PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_shake256x4(out0, - out1, - out2, - out3, PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N, - bufx4 + 0 * (PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_ADDR_BYTES), - bufx4 + 1 * (PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_ADDR_BYTES), - bufx4 + 2 * (PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_ADDR_BYTES), - bufx4 + 3 * (PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_ADDR_BYTES), PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_ADDR_BYTES); - - /* Avoid unused parameter warning */ - (void)state_seeded; -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_avx2/hash_state.h b/src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_avx2/hash_state.h deleted file mode 100644 index 7e4e5b29fc..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_avx2/hash_state.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_HASH_STATE_H -#define PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_HASH_STATE_H - -/** - * Defines the type of the hash function state. - * - * Don't be fooled into thinking this instance of SPHINCS+ isn't stateless! - * - * From Section 7.2.2 from the SPHINCS+ round-2 specification: - * - * Each of the instances of the tweakable hash function take PK.seed as its - * first input, which is constant for a given key pair – and, thus, across - * a single signature. This leads to a lot of redundant computation. To remedy - * this, we pad PK.seed to the length of a full 64-byte SHA-256 input block. - * Because of the Merkle-Damgård construction that underlies SHA-256, this - * allows for reuse of the intermediate SHA-256 state after the initial call to - * the compression function which improves performance. - * - * We pass this hash state around in functions, because otherwise we need to - * have a global variable. - * - * SHAKE256 does not need this state. Because this implementation is generated - * from a shared code base, we still need to specify some hash_state as it is - * still passed around. We chose to use an `int` as a placeholder for this - * purpose. - */ - -typedef int hash_state; - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_avx2/hashx4.h b/src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_avx2/hashx4.h deleted file mode 100644 index 67770980b0..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_avx2/hashx4.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_HASHX4_H -#define PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_HASHX4_H - -#include - -#include "hash_state.h" - -void PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_prf_addrx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const unsigned char *key, - const uint32_t addrx4[4 * 8], - const hash_state *state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_avx2/params.h b/src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_avx2/params.h deleted file mode 100644 index 2f8324ab79..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_avx2/params.h +++ /dev/null @@ -1,53 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_PARAMS_H -#define PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_PARAMS_H - -/* Hash output length in bytes. */ -#define PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N 24 -/* Height of the hypertree. */ -#define PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_FULL_HEIGHT 66 -/* Number of subtree layer. */ -#define PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_D 22 -/* FORS tree dimensions. */ -#define PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_FORS_HEIGHT 8 -#define PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_FORS_TREES 33 -/* Winternitz parameter, */ -#define PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_WOTS_W 16 - -/* The hash function is defined by linking a different hash.c file, as opposed - to setting a #define constant. */ - -/* For clarity */ -#define PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_ADDR_BYTES 32 - -/* WOTS parameters. */ -#define PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_WOTS_LOGW 4 - -#define PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_WOTS_LEN1 (8 * PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N / PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_WOTS_LOGW) - -/* PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#define PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_WOTS_LEN2 3 - -#define PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_WOTS_LEN (PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_WOTS_LEN1 + PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_WOTS_LEN2) -#define PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_WOTS_BYTES (PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_WOTS_LEN * PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N) -#define PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_WOTS_PK_BYTES PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_WOTS_BYTES - -/* Subtree size. */ -#define PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_TREE_HEIGHT (PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_FULL_HEIGHT / PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_D) - -/* FORS parameters. */ -#define PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_FORS_MSG_BYTES ((PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_FORS_TREES + 7) / 8) -#define PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_FORS_BYTES ((PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_FORS_HEIGHT + 1) * PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_FORS_TREES * PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N) -#define PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_FORS_PK_BYTES PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N - -/* Resulting SPX sizes. */ -#define PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_BYTES (PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_FORS_BYTES + PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_D * PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_WOTS_BYTES +\ - PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_FULL_HEIGHT * PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N) -#define PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_PK_BYTES (2 * PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N) -#define PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_SK_BYTES (2 * PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_PK_BYTES) - -/* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ -#define PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_OPTRAND_BYTES 32 - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_avx2/sign.c b/src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_avx2/sign.c deleted file mode 100644 index d3a805fddf..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_avx2/sign.c +++ /dev/null @@ -1,409 +0,0 @@ -#include -#include -#include -#include - -#include "address.h" -#include "api.h" -#include "fors.h" -#include "hash.h" -#include "hash_state.h" -#include "params.h" -#include "randombytes.h" -#include "thash.h" -#include "utils.h" -#include "wots.h" - - -/** - * Computes the leaf at a given address. First generates the WOTS key pair, - * then computes leaf by hashing horizontally. - */ -static void wots_gen_leaf(unsigned char *leaf, const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx, const uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - unsigned char pk[PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_WOTS_BYTES]; - uint32_t wots_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_set_type( - wots_addr, PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_set_type( - wots_pk_addr, PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_ADDR_TYPE_WOTSPK); - - PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_set_keypair_addr( - wots_addr, addr_idx); - PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_wots_gen_pk( - pk, sk_seed, pub_seed, wots_addr, hash_state_seeded); - - PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_copy_keypair_addr( - wots_pk_addr, wots_addr); - PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_thash_WOTS_LEN( - leaf, pk, pub_seed, wots_pk_addr, hash_state_seeded); -} - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_crypto_sign_secretkeybytes(void) { - return PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_CRYPTO_SECRETKEYBYTES; -} - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_crypto_sign_publickeybytes(void) { - return PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_CRYPTO_PUBLICKEYBYTES; -} - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_crypto_sign_bytes(void) { - return PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_CRYPTO_BYTES; -} - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_crypto_sign_seedbytes(void) { - return PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_CRYPTO_SEEDBYTES; -} - -/* - * Generates an SPX key pair given a seed of length - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed) { - /* We do not need the auth path in key generation, but it simplifies the - code to have just one treehash routine that computes both root and path - in one function. */ - unsigned char auth_path[PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_TREE_HEIGHT * PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N]; - uint32_t top_tree_addr[8] = {0}; - hash_state hash_state_seeded; - - PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_set_layer_addr( - top_tree_addr, PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_D - 1); - PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_set_type( - top_tree_addr, PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_ADDR_TYPE_HASHTREE); - - /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ - memcpy(sk, seed, PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_CRYPTO_SEEDBYTES); - - memcpy(pk, sk + 2 * PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N, PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_initialize_hash_function(&hash_state_seeded, pk, sk); - - /* Compute root node of the top-most subtree. */ - PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_treehash_TREE_HEIGHT( - sk + 3 * PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N, auth_path, sk, sk + 2 * PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N, 0, 0, - wots_gen_leaf, top_tree_addr, &hash_state_seeded); - - memcpy(pk + PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N, sk + 3 * PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N, PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N); - - return 0; -} - -/* - * Generates an SPX key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk) { - - // guarantee alignment of pk - union { - __m128 _x[PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_CRYPTO_PUBLICKEYBYTES / 16]; - uint8_t pk[PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_CRYPTO_PUBLICKEYBYTES]; - } aligned_pk; - - // guarantee alignment of sk - union { - __m128 _x[PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_CRYPTO_SECRETKEYBYTES / 16]; - uint8_t sk[PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_CRYPTO_SECRETKEYBYTES]; - } aligned_sk; - - union { - __m128 _x[PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_CRYPTO_SEEDBYTES / 16]; - uint8_t seed[PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_CRYPTO_SEEDBYTES]; - } aligned_seed; - randombytes(aligned_seed.seed, PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_CRYPTO_SEEDBYTES); - - PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_crypto_sign_seed_keypair( - aligned_pk.pk, aligned_sk.sk, aligned_seed.seed); - memcpy(pk, aligned_pk.pk, PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_CRYPTO_PUBLICKEYBYTES); - memcpy(sk, aligned_sk.sk, PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_CRYPTO_SECRETKEYBYTES); - - return 0; -} - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - // guarantee alignment of sk - union { - __m128 *_x; - uint8_t sk[PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_CRYPTO_SECRETKEYBYTES]; - } aligned_sk; - memcpy(aligned_sk.sk, sk, PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_CRYPTO_SECRETKEYBYTES); - sk = aligned_sk.sk; - - // guarantee alignment of sig - union { - __m128 *_x; - uint8_t sig[PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_BYTES]; - } aligned_sig; - uint8_t *orig_sig = sig; - sig = (uint8_t *)aligned_sig.sig; - - const unsigned char *sk_seed = sk; - const unsigned char *sk_prf = sk + PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N; - const unsigned char *pk = sk + 2 * PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N; - const unsigned char *pub_seed = pk; - - unsigned char optrand[PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N]; - unsigned char mhash[PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_FORS_MSG_BYTES]; - unsigned char root[PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N]; - uint32_t i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - - hash_state hash_state_seeded; - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_initialize_hash_function( - &hash_state_seeded, - pub_seed, sk_seed); - - PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_set_type( - wots_addr, PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_set_type( - tree_addr, PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_ADDR_TYPE_HASHTREE); - - /* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ - randombytes(optrand, PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N); - /* Compute the digest randomization value. */ - PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_gen_message_random( - sig, sk_prf, optrand, m, mlen, &hash_state_seeded); - - /* Derive the message digest and leaf index from R, PK and M. */ - PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N; - - PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_set_keypair_addr( - wots_addr, idx_leaf); - - /* Sign the message hash using FORS. */ - PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_fors_sign( - sig, root, mhash, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_FORS_BYTES; - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_D; i++) { - PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_set_tree_addr(tree_addr, tree); - - PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_set_keypair_addr( - wots_addr, idx_leaf); - - /* Compute a WOTS signature. */ - PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_wots_sign( - sig, root, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_WOTS_BYTES; - - /* Compute the authentication path for the used WOTS leaf. */ - PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_treehash_TREE_HEIGHT( - root, sig, sk_seed, pub_seed, idx_leaf, 0, - wots_gen_leaf, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_TREE_HEIGHT * PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_TREE_HEIGHT; - } - - memcpy(orig_sig, aligned_sig.sig, PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_BYTES); - *siglen = PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_BYTES; - - return 0; -} - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk) { - // guarantee alignment of pk - union { - __m128 *_x; - uint8_t pk[PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_CRYPTO_PUBLICKEYBYTES]; - } aligned_pk; - memcpy(aligned_pk.pk, pk, PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_CRYPTO_PUBLICKEYBYTES); - pk = aligned_pk.pk; - - const unsigned char *pub_seed = pk; - const unsigned char *pub_root = pk + PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N; - unsigned char mhash[PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_FORS_MSG_BYTES]; - unsigned char wots_pk[PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_WOTS_BYTES]; - unsigned char root[PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N]; - unsigned char leaf[PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N]; - unsigned int i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - hash_state hash_state_seeded; - - if (siglen != PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_BYTES) { - return -1; - } - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_initialize_hash_function( - &hash_state_seeded, - pub_seed, NULL); - - PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_set_type( - wots_addr, PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_set_type( - tree_addr, PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_ADDR_TYPE_HASHTREE); - PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_set_type( - wots_pk_addr, PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_ADDR_TYPE_WOTSPK); - - /* Derive the message digest and leaf index from R || PK || M. */ - /* The additional PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N is a result of the hash domain separator. */ - PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N; - - /* Layer correctly defaults to 0, so no need to set_layer_addr */ - PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_set_keypair_addr( - wots_addr, idx_leaf); - - PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_fors_pk_from_sig( - root, sig, mhash, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_FORS_BYTES; - - /* For each subtree.. */ - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_D; i++) { - PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_set_tree_addr(tree_addr, tree); - - PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_set_keypair_addr( - wots_addr, idx_leaf); - - PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_copy_keypair_addr( - wots_pk_addr, wots_addr); - - /* The WOTS public key is only correct if the signature was correct. */ - /* Initially, root is the FORS pk, but on subsequent iterations it is - the root of the subtree below the currently processed subtree. */ - PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_wots_pk_from_sig( - wots_pk, sig, root, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_WOTS_BYTES; - - /* Compute the leaf node using the WOTS public key. */ - PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_thash_WOTS_LEN( - leaf, wots_pk, pub_seed, wots_pk_addr, &hash_state_seeded); - - /* Compute the root node of this subtree. */ - PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_compute_root( - root, leaf, idx_leaf, 0, sig, PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_TREE_HEIGHT, - pub_seed, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_TREE_HEIGHT * PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_TREE_HEIGHT; - } - - /* Check if the root node equals the root node in the public key. */ - if (memcmp(root, pub_root, PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N) != 0) { - return -1; - } - - return 0; -} - - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - size_t siglen; - - PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_crypto_sign_signature( - sm, &siglen, m, mlen, sk); - - memmove(sm + PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_BYTES, m, mlen); - *smlen = siglen + mlen; - - return 0; -} - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk) { - - // guarantee alignment of pk - union { - __m128 *_x; - uint8_t pk[PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_CRYPTO_PUBLICKEYBYTES]; - } aligned_pk; - memcpy(aligned_pk.pk, pk, PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_CRYPTO_PUBLICKEYBYTES); - pk = aligned_pk.pk; - - - /* The API caller does not necessarily know what size a signature should be - but SPHINCS+ signatures are always exactly PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_BYTES. */ - if (smlen < PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_BYTES) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - *mlen = smlen - PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_BYTES; - - if (PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_crypto_sign_verify( - sm, PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_BYTES, sm + PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_BYTES, *mlen, pk)) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - /* If verification was successful, move the message to the right place. */ - memmove(m, sm + PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_BYTES, *mlen); - - return 0; -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_avx2/thash.h b/src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_avx2/thash.h deleted file mode 100644 index 785271c9e1..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_avx2/thash.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_THASH_H -#define PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_THASH_H - -#include "hash_state.h" - -#include - -void PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_avx2/thash_shake256_robust.c b/src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_avx2/thash_shake256_robust.c deleted file mode 100644 index b7c03603e5..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_avx2/thash_shake256_robust.c +++ /dev/null @@ -1,81 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "thash.h" - -#include "fips202.h" - -/** - * Takes an array of inblocks concatenated arrays of PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N bytes. - */ -static void PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_thash( - unsigned char *out, unsigned char *buf, - const unsigned char *in, unsigned int inblocks, - const unsigned char *pub_seed, uint32_t addr[8]) { - - unsigned char *bitmask = buf + PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_ADDR_BYTES; - unsigned int i; - - memcpy(buf, pub_seed, PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N); - PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_addr_to_bytes(buf + PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N, addr); - - shake256(bitmask, inblocks * PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N, buf, PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_ADDR_BYTES); - - for (i = 0; i < inblocks * PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N; i++) { - buf[PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_ADDR_BYTES + i] = in[i] ^ bitmask[i]; - } - - shake256(out, PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N, buf, PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N); -} - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_ADDR_BYTES + 1 * PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N]; - PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_thash( - out, buf, in, 1, pub_seed, addr); - - (void)hash_state_seeded; /* Avoid unused parameter warning. */ -} - -void PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_ADDR_BYTES + 2 * PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N]; - PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_thash( - out, buf, in, 2, pub_seed, addr); - - (void)hash_state_seeded; /* Avoid unused parameter warning. */ -} - -void PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_ADDR_BYTES + PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_WOTS_LEN * PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N]; - PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_thash( - out, buf, in, PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_WOTS_LEN, pub_seed, addr); - - (void)hash_state_seeded; /* Avoid unused parameter warning. */ -} - -void PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_ADDR_BYTES + PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_FORS_TREES * PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N]; - PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_thash( - out, buf, in, PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_FORS_TREES, pub_seed, addr); - - (void)hash_state_seeded; /* Avoid unused parameter warning. */ -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_avx2/thash_shake256_robustx4.c b/src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_avx2/thash_shake256_robustx4.c deleted file mode 100644 index aeec93b5f0..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_avx2/thash_shake256_robustx4.c +++ /dev/null @@ -1,66 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "thashx4.h" - -#include "fips202x4.h" - -/** - * 4-way parallel version of thash; takes 4x as much input and output - */ -#define thash_variant(name, inblocks) \ - void PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_thashx4_##name(unsigned char *out0, \ - unsigned char *out1, \ - unsigned char *out2, \ - unsigned char *out3, \ - const unsigned char *in0, \ - const unsigned char *in1, \ - const unsigned char *in2, \ - const unsigned char *in3, \ - const unsigned char *pub_seed, uint32_t addrx4[4*8], \ - const hash_state *state_seeded) \ - { \ - unsigned char buf0[PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_ADDR_BYTES + (inblocks)*PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N]; \ - unsigned char buf1[PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_ADDR_BYTES + (inblocks)*PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N]; \ - unsigned char buf2[PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_ADDR_BYTES + (inblocks)*PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N]; \ - unsigned char buf3[PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_ADDR_BYTES + (inblocks)*PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N]; \ - unsigned char bitmask0[(inblocks) * PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N]; \ - unsigned char bitmask1[(inblocks) * PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N]; \ - unsigned char bitmask2[(inblocks) * PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N]; \ - unsigned char bitmask3[(inblocks) * PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N]; \ - unsigned int i; \ - \ - memcpy(buf0, pub_seed, PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N); \ - memcpy(buf1, pub_seed, PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N); \ - memcpy(buf2, pub_seed, PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N); \ - memcpy(buf3, pub_seed, PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N); \ - PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_addr_to_bytes(buf0 + PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N, addrx4 + 0*8); \ - PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_addr_to_bytes(buf1 + PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N, addrx4 + 1*8); \ - PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_addr_to_bytes(buf2 + PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N, addrx4 + 2*8); \ - PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_addr_to_bytes(buf3 + PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N, addrx4 + 3*8); \ - \ - PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_shake256x4(bitmask0, bitmask1, bitmask2, bitmask3, (inblocks) * PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N, \ - buf0, buf1, buf2, buf3, PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_ADDR_BYTES); \ - \ - for (i = 0; i < (inblocks) * PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N; i++) { \ - buf0[PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_ADDR_BYTES + i] = in0[i] ^ bitmask0[i]; \ - buf1[PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_ADDR_BYTES + i] = in1[i] ^ bitmask1[i]; \ - buf2[PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_ADDR_BYTES + i] = in2[i] ^ bitmask2[i]; \ - buf3[PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_ADDR_BYTES + i] = in3[i] ^ bitmask3[i]; \ - } \ - \ - PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_shake256x4( \ - out0, out1, out2, out3, PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N, \ - buf0, buf1, buf2, buf3, PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_ADDR_BYTES + (inblocks)*PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N); \ - \ - /* avoid unused parameter warning */ \ - (void)state_seeded; \ - } - - -thash_variant(1, 1) -thash_variant(2, 2) -thash_variant(WOTS_LEN, PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_WOTS_LEN) -thash_variant(FORS_TREES, PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_FORS_TREES) diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_avx2/thashx4.h b/src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_avx2/thashx4.h deleted file mode 100644 index d302a3fe23..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_avx2/thashx4.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_THASHX4_H -#define PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_THASHX4_H - -#include - -#include "hash_state.h" - -#define thashx4_header(inblocks) \ - void PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_thashx4_##inblocks(unsigned char *out0, \ - unsigned char *out1, \ - unsigned char *out2, \ - unsigned char *out3, \ - const unsigned char *in0, \ - const unsigned char *in1, \ - const unsigned char *in2, \ - const unsigned char *in3, \ - const unsigned char *pub_seed, uint32_t addrx4[4*8], \ - const hash_state *state_seeded) - -thashx4_header(1); -thashx4_header(2); -thashx4_header(WOTS_LEN); -thashx4_header(FORS_TREES); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_avx2/utils.c b/src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_avx2/utils.c deleted file mode 100644 index 0a79e8f32b..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_avx2/utils.c +++ /dev/null @@ -1,199 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "hash_state.h" -#include "params.h" -#include "thash.h" -#include "utils.h" - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in) { - - /* Iterate over out in decreasing order, for big-endianness. */ - for (size_t i = outlen; i > 0; i--) { - out[i - 1] = in & 0xff; - in = in >> 8; - } -} - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_bytes_to_ull( - const unsigned char *in, size_t inlen) { - unsigned long long retval = 0; - - for (size_t i = 0; i < inlen; i++) { - retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); - } - return retval; -} - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - uint32_t i; - unsigned char buffer[2 * PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N]; - - /* If leaf_idx is odd (last bit = 1), current path element is a right child - and auth_path has to go left. Otherwise it is the other way around. */ - if (leaf_idx & 1) { - memcpy(buffer + PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N, leaf, PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N); - } else { - memcpy(buffer, leaf, PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N); - memcpy(buffer + PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N, auth_path, PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N); - } - auth_path += PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N; - - for (i = 0; i < tree_height - 1; i++) { - leaf_idx >>= 1; - idx_offset >>= 1; - /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_set_tree_height(addr, i + 1); - PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_set_tree_index( - addr, leaf_idx + idx_offset); - - /* Pick the right or left neighbor, depending on parity of the node. */ - if (leaf_idx & 1) { - PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_thash_2( - buffer + PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N); - } else { - PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_thash_2( - buffer, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer + PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N, auth_path, PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N); - } - auth_path += PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N; - } - - /* The last iteration is exceptional; we do not copy an auth_path node. */ - leaf_idx >>= 1; - idx_offset >>= 1; - PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_set_tree_height(addr, tree_height); - PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_set_tree_index( - addr, leaf_idx + idx_offset); - PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_thash_2( - root, buffer, pub_seed, addr, hash_state_seeded); -} - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -static void PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_treehash( - unsigned char *root, unsigned char *auth_path, - unsigned char *stack, unsigned int *heights, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - - unsigned int offset = 0; - uint32_t idx; - uint32_t tree_idx; - - for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { - /* Add the next leaf node to the stack. */ - gen_leaf(stack + offset * PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N, - sk_seed, pub_seed, idx + idx_offset, tree_addr, - hash_state_seeded); - offset++; - heights[offset - 1] = 0; - - /* If this is a node we need for the auth path.. */ - if ((leaf_idx ^ 0x1) == idx) { - memcpy(auth_path, stack + (offset - 1)*PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N, PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N); - } - - /* While the top-most nodes are of equal height.. */ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { - /* Compute index of the new node, in the next layer. */ - tree_idx = (idx >> (heights[offset - 1] + 1)); - - /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_set_tree_height( - tree_addr, heights[offset - 1] + 1); - PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_set_tree_index( - tree_addr, tree_idx + (idx_offset >> (heights[offset - 1] + 1))); - /* Hash the top-most nodes from the stack together. */ - PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_thash_2( - stack + (offset - 2)*PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N, stack + (offset - 2)*PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N, - pub_seed, tree_addr, hash_state_seeded); - offset--; - /* Note that the top-most node is now one layer higher. */ - heights[offset - 1]++; - - /* If this is a node we need for the auth path.. */ - if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_path + heights[offset - 1]*PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N, - stack + (offset - 1)*PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N, PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N); - } - } - } - memcpy(root, stack, PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N); -} - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_FORS_HEIGHT + 1)*PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N]; - unsigned int heights[PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_FORS_HEIGHT + 1]; - - PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_FORS_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_TREE_HEIGHT + 1)*PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N]; - unsigned int heights[PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_TREE_HEIGHT + 1]; - - PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_TREE_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_avx2/utils.h b/src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_avx2/utils.h deleted file mode 100644 index 8613810852..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_avx2/utils.h +++ /dev/null @@ -1,64 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_UTILS_H -#define PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_UTILS_H - -#include "hash_state.h" -#include "params.h" -#include -#include - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in); - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_bytes_to_ull( - const unsigned char *in, size_t inlen); - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -void PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_avx2/utilsx4.c b/src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_avx2/utilsx4.c deleted file mode 100644 index 525fbe6614..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_avx2/utilsx4.c +++ /dev/null @@ -1,98 +0,0 @@ -#include "address.h" -#include "params.h" -#include "thashx4.h" -#include "utils.h" -#include "utilsx4.h" - -#include - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -#define treehashx4_variant(name, tree_height) \ - void PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_treehashx4_##name( \ - unsigned char *rootx4, unsigned char *auth_pathx4, const unsigned char *sk_seed, \ - const unsigned char *pub_seed, const uint32_t leaf_idx[4], uint32_t idx_offset[4], \ - void (*gen_leafx4)(unsigned char * /* leaf0 */, unsigned char * /* leaf1 */, \ - unsigned char * /* leaf2 */, unsigned char * /* leaf3 */, \ - const unsigned char * /* sk_seed */, \ - const unsigned char * /* pub_seed */, uint32_t /* addr_idx0 */, \ - uint32_t /* addr_idx1 */, uint32_t /* addr_idx2 */, \ - uint32_t /* addr_idx3 */, const uint32_t[8] /* tree_addr */, \ - const hash_state * /* state_seeded */), \ - uint32_t tree_addrx4[4 * 8], const hash_state *state_seeded) { \ - unsigned char stackx4[4 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N]; \ - unsigned int heights[(tree_height) + 1]; \ - unsigned int offset = 0; \ - uint32_t idx; \ - uint32_t tree_idx; \ - unsigned int j; \ - \ - for (idx = 0; idx < (uint32_t)(1 << (tree_height)); idx++) { \ - /* Add the next leaf node to the stack. */ \ - gen_leafx4(stackx4 + 0 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N + offset * PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N, \ - stackx4 + 1 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N + offset * PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N, \ - stackx4 + 2 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N + offset * PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N, \ - stackx4 + 3 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N + offset * PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N, sk_seed, \ - pub_seed, idx + idx_offset[0], idx + idx_offset[1], idx + idx_offset[2], \ - idx + idx_offset[3], tree_addrx4, state_seeded); \ - offset++; \ - heights[offset - 1] = 0; \ - \ - /* If this is a node we need for the auth path.. */ \ - for (j = 0; j < 4; j++) { \ - if ((leaf_idx[j] ^ 0x1) == idx) { \ - memcpy(auth_pathx4 + j * (tree_height)*PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N, \ - stackx4 + j * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N + (offset - 1) * PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N, \ - PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N); \ - } \ - } \ - \ - /* While the top-most nodes are of equal height.. */ \ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { \ - /* Compute index of the new node, in the next layer. */ \ - tree_idx = (idx >> (heights[offset - 1] + 1)); \ - \ - /* Set the address of the node we're creating. */ \ - for (j = 0; j < 4; j++) { \ - PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_set_tree_height(tree_addrx4 + j * 8, heights[offset - 1] + 1); \ - PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_set_tree_index(tree_addrx4 + j * 8, \ - tree_idx + (idx_offset[j] >> (heights[offset - 1] + 1))); \ - } \ - /* Hash the top-most nodes from the stack together. */ \ - PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_thashx4_2(stackx4 + 0 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N + (offset - 2) * PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N, \ - stackx4 + 1 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N + (offset - 2) * PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N, \ - stackx4 + 2 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N + (offset - 2) * PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N, \ - stackx4 + 3 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N + (offset - 2) * PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N, \ - stackx4 + 0 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N + (offset - 2) * PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N, \ - stackx4 + 1 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N + (offset - 2) * PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N, \ - stackx4 + 2 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N + (offset - 2) * PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N, \ - stackx4 + 3 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N + (offset - 2) * PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N, \ - pub_seed, tree_addrx4, state_seeded); \ - offset--; \ - /* Note that the top-most node is now one layer higher. */ \ - heights[offset - 1]++; \ - \ - /* If this is a node we need for the auth path.. */ \ - for (j = 0; j < 4; j++) { \ - if (((leaf_idx[j] >> heights[offset - 1]) ^ 0x1) == tree_idx) { \ - memcpy(auth_pathx4 + j * (tree_height)*PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N + \ - heights[offset - 1] * PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N, \ - stackx4 + j * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N + (offset - 1) * PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N, \ - PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N); \ - } \ - } \ - } \ - } \ - \ - for (j = 0; j < 4; j++) { \ - memcpy(rootx4 + j * PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N, stackx4 + j * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N, PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N); \ - } \ - } - -treehashx4_variant(FORS_HEIGHT, PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_FORS_HEIGHT) diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_avx2/utilsx4.h b/src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_avx2/utilsx4.h deleted file mode 100644 index 4de0428eb8..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_avx2/utilsx4.h +++ /dev/null @@ -1,38 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_UTILSX4_H -#define PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_UTILSX4_H - -#include "hash_state.h" -#include "params.h" - -#include - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -void PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_treehashx4_FORS_HEIGHT(unsigned char *rootx4, - unsigned char *auth_pathx4, - const unsigned char *sk_seed, - const unsigned char *pub_seed, - const uint32_t leaf_idx[4], - uint32_t idx_offset[4], - void (*gen_leafx4)(unsigned char * /* leaf0 */, - unsigned char * /* leaf1 */, - unsigned char * /* leaf2 */, - unsigned char * /* leaf3 */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx0 */, - uint32_t /* addr_idx1 */, - uint32_t /* addr_idx2 */, - uint32_t /* addr_idx3 */, - const uint32_t[8] /* tree_addr */, - const hash_state * /* state_seeded */), - uint32_t tree_addrx4[4 * 8], - const hash_state *state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_avx2/wots.c b/src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_avx2/wots.c deleted file mode 100644 index 67a431fb6b..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_avx2/wots.c +++ /dev/null @@ -1,240 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "hash_state.h" -#include "hashx4.h" -#include "params.h" -#include "thash.h" -#include "thashx4.h" -#include "utils.h" -#include "wots.h" - -// TODO clarify address expectations, and make them more uniform. -// TODO i.e. do we expect types to be set already? -// TODO and do we expect modifications or copies? - -/** - * Computes the starting value for a chain, i.e. the secret key. - * Expects the address to be complete up to the chain address. - */ -static void wots_gen_sk(unsigned char *sk, const unsigned char *sk_seed, - uint32_t wots_addr[8], const hash_state *state_seeded) { - /* Make sure that the hash address is actually zeroed. */ - PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_set_hash_addr(wots_addr, 0); - - /* Generate sk element. */ - PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_prf_addr(sk, sk_seed, wots_addr, state_seeded); -} - -/** - * 4-way parallel version of wots_gen_sk; expects 4x as much space in sk - */ -static void wots_gen_skx4(unsigned char *skx4, const unsigned char *sk_seed, - uint32_t wots_addrx4[4 * 8], const hash_state *state_seeded) { - unsigned int j; - - /* Make sure that the hash address is actually zeroed. */ - for (j = 0; j < 4; j++) { - PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_set_hash_addr(wots_addrx4 + j * 8, 0); - } - - /* Generate sk element. */ - PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_prf_addrx4(skx4 + 0 * PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N, - skx4 + 1 * PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N, - skx4 + 2 * PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N, - skx4 + 3 * PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N, - sk_seed, wots_addrx4, - state_seeded); -} - -/** - * Computes the chaining function. - * out and in have to be n-byte arrays. - * - * Interprets in as start-th value of the chain. - * addr has to contain the address of the chain. - */ -static void gen_chain(unsigned char *out, const unsigned char *in, - unsigned int start, unsigned int steps, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *state_seeded) { - uint32_t i; - - /* Initialize out with the value at position 'start'. */ - memcpy(out, in, PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N); - - /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_WOTS_W; i++) { - PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_set_hash_addr(addr, i); - PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_thash_1(out, out, pub_seed, addr, state_seeded); - } -} - -/** - * 4-way parallel version of gen_chain; expects 4x as much space in out, and - * 4x as much space in inx4. Assumes start and step identical across chains. - */ -static void gen_chainx4(unsigned char *outx4, const unsigned char *inx4, - unsigned int start, unsigned int steps, - const unsigned char *pub_seed, uint32_t addrx4[4 * 8], - const hash_state *state_seeded) { - uint32_t i; - unsigned int j; - - /* Initialize outx4 with the value at position 'start'. */ - memcpy(outx4, inx4, 4 * PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N); - - /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_WOTS_W; i++) { - for (j = 0; j < 4; j++) { - PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_set_hash_addr(addrx4 + j * 8, i); - } - PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_thashx4_1(outx4 + 0 * PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N, - outx4 + 1 * PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N, - outx4 + 2 * PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N, - outx4 + 3 * PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N, - outx4 + 0 * PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N, - outx4 + 1 * PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N, - outx4 + 2 * PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N, - outx4 + 3 * PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N, - pub_seed, addrx4, - state_seeded); - } -} - -/** - * base_w algorithm as described in draft. - * Interprets an array of bytes as integers in base w. - * This only works when log_w is a divisor of 8. - */ -static void base_w(unsigned int *output, const int out_len, const unsigned char *input) { - int in = 0; - int out = 0; - unsigned char total = 0; - int bits = 0; - int consumed; - - for (consumed = 0; consumed < out_len; consumed++) { - if (bits == 0) { - total = input[in]; - in++; - bits += 8; - } - bits -= PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_WOTS_LOGW; - output[out] = (unsigned int)(total >> bits) & (PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_WOTS_W - 1); - out++; - } -} - -/* Computes the WOTS+ checksum over a message (in base_w). */ -static void wots_checksum(unsigned int *csum_base_w, const unsigned int *msg_base_w) { - unsigned int csum = 0; - unsigned char csum_bytes[(PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_WOTS_LEN2 * PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_WOTS_LOGW + 7) / 8]; - unsigned int i; - - /* Compute checksum. */ - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_WOTS_LEN1; i++) { - csum += PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_WOTS_W - 1 - msg_base_w[i]; - } - - /* Convert checksum to base_w. */ - /* Make sure expected empty zero bits are the least significant bits. */ - csum = csum << (8 - ((PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_WOTS_LEN2 * PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_WOTS_LOGW) % 8)); - PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); - base_w(csum_base_w, PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_WOTS_LEN2, csum_bytes); -} - -/* Takes a message and derives the matching chain lengths. */ -static void chain_lengths(unsigned int *lengths, const unsigned char *msg) { - base_w(lengths, PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_WOTS_LEN1, msg); - wots_checksum(lengths + PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_WOTS_LEN1, lengths); -} - -/** - * WOTS key generation. Takes a 32 byte sk_seed, expands it to WOTS private key - * elements and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_wots_gen_pk(unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *state_seeded) { - uint32_t i; - unsigned int j; - - uint32_t addrx4[4 * 8]; - unsigned char pkbuf[4 * PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N]; - - for (j = 0; j < 4; j++) { - memcpy(addrx4 + j * 8, addr, sizeof(uint32_t) * 8); - } - - /* The last iteration typically does not have complete set of 4 chains, - but because we use pkbuf, this is not an issue -- we still do as many - in parallel as possible. */ - for (i = 0; i < ((PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_WOTS_LEN + 3) & ~0x3); i += 4) { - for (j = 0; j < 4; j++) { - PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_set_chain_addr(addrx4 + j * 8, i + j); - } - wots_gen_skx4(pkbuf, sk_seed, addrx4, state_seeded); - gen_chainx4(pkbuf, pkbuf, 0, PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_WOTS_W - 1, pub_seed, addrx4, state_seeded); - for (j = 0; j < 4; j++) { - if (i + j < PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_WOTS_LEN) { - memcpy(pk + (i + j)*PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N, pkbuf + j * PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N, PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N); - } - } - } - - // Get rid of unused argument variable. - (void)state_seeded; -} - -/** - * Takes a n-byte message and the 32-byte sk_see to compute a signature 'sig'. - */ -void PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_wots_sign(unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_WOTS_LEN; i++) { - PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_set_chain_addr(addr, i); - wots_gen_sk(sig + i * PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N, sk_seed, addr, state_seeded); - gen_chain(sig + i * PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N, sig + i * PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N, 0, lengths[i], pub_seed, addr, state_seeded); - } - - // avoid unused argument - (void)state_seeded; -} - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_WOTS_LEN; i++) { - PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_set_chain_addr(addr, i); - gen_chain(pk + i * PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N, sig + i * PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_N, - lengths[i], PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_WOTS_W - 1 - lengths[i], pub_seed, addr, - state_seeded); - } - - // avoid unused argument - (void)state_seeded; -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_avx2/wots.h b/src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_avx2/wots.h deleted file mode 100644 index d7045976b0..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_avx2/wots.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_WOTS_H -#define PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_WOTS_H - -#include "hash_state.h" -#include "params.h" -#include - -/** - * WOTS key generation. Takes a 32 byte seed for the private key, expands it to - * a full WOTS private key and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_wots_gen_pk( - unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -/** - * Takes a n-byte message and the 32-byte seed for the private key to compute a - * signature that is placed at 'sig'. - */ -void PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_wots_sign( - unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *hash_state_seeded); - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_wots_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_clean/LICENSE b/src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_clean/LICENSE deleted file mode 100644 index 670154e353..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_clean/LICENSE +++ /dev/null @@ -1,116 +0,0 @@ -CC0 1.0 Universal - -Statement of Purpose - -The laws of most jurisdictions throughout the world automatically confer -exclusive Copyright and Related Rights (defined below) upon the creator and -subsequent owner(s) (each and all, an "owner") of an original work of -authorship and/or a database (each, a "Work"). - -Certain owners wish to permanently relinquish those rights to a Work for the -purpose of contributing to a commons of creative, cultural and scientific -works ("Commons") that the public can reliably and without fear of later -claims of infringement build upon, modify, incorporate in other works, reuse -and redistribute as freely as possible in any form whatsoever and for any -purposes, including without limitation commercial purposes. These owners may -contribute to the Commons to promote the ideal of a free culture and the -further production of creative, cultural and scientific works, or to gain -reputation or greater distribution for their Work in part through the use and -efforts of others. - -For these and/or other purposes and motivations, and without any expectation -of additional consideration or compensation, the person associating CC0 with a -Work (the "Affirmer"), to the extent that he or she is an owner of Copyright -and Related Rights in the Work, voluntarily elects to apply CC0 to the Work -and publicly distribute the Work under its terms, with knowledge of his or her -Copyright and Related Rights in the Work and the meaning and intended legal -effect of CC0 on those rights. - -1. Copyright and Related Rights. A Work made available under CC0 may be -protected by copyright and related or neighboring rights ("Copyright and -Related Rights"). Copyright and Related Rights include, but are not limited -to, the following: - - i. the right to reproduce, adapt, distribute, perform, display, communicate, - and translate a Work; - - ii. moral rights retained by the original author(s) and/or performer(s); - - iii. publicity and privacy rights pertaining to a person's image or likeness - depicted in a Work; - - iv. rights protecting against unfair competition in regards to a Work, - subject to the limitations in paragraph 4(a), below; - - v. rights protecting the extraction, dissemination, use and reuse of data in - a Work; - - vi. database rights (such as those arising under Directive 96/9/EC of the - European Parliament and of the Council of 11 March 1996 on the legal - protection of databases, and under any national implementation thereof, - including any amended or successor version of such directive); and - - vii. other similar, equivalent or corresponding rights throughout the world - based on applicable law or treaty, and any national implementations thereof. - -2. Waiver. To the greatest extent permitted by, but not in contravention of, -applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and -unconditionally waives, abandons, and surrenders all of Affirmer's Copyright -and Related Rights and associated claims and causes of action, whether now -known or unknown (including existing as well as future claims and causes of -action), in the Work (i) in all territories worldwide, (ii) for the maximum -duration provided by applicable law or treaty (including future time -extensions), (iii) in any current or future medium and for any number of -copies, and (iv) for any purpose whatsoever, including without limitation -commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes -the Waiver for the benefit of each member of the public at large and to the -detriment of Affirmer's heirs and successors, fully intending that such Waiver -shall not be subject to revocation, rescission, cancellation, termination, or -any other legal or equitable action to disrupt the quiet enjoyment of the Work -by the public as contemplated by Affirmer's express Statement of Purpose. - -3. Public License Fallback. Should any part of the Waiver for any reason be -judged legally invalid or ineffective under applicable law, then the Waiver -shall be preserved to the maximum extent permitted taking into account -Affirmer's express Statement of Purpose. In addition, to the extent the Waiver -is so judged Affirmer hereby grants to each affected person a royalty-free, -non transferable, non sublicensable, non exclusive, irrevocable and -unconditional license to exercise Affirmer's Copyright and Related Rights in -the Work (i) in all territories worldwide, (ii) for the maximum duration -provided by applicable law or treaty (including future time extensions), (iii) -in any current or future medium and for any number of copies, and (iv) for any -purpose whatsoever, including without limitation commercial, advertising or -promotional purposes (the "License"). The License shall be deemed effective as -of the date CC0 was applied by Affirmer to the Work. Should any part of the -License for any reason be judged legally invalid or ineffective under -applicable law, such partial invalidity or ineffectiveness shall not -invalidate the remainder of the License, and in such case Affirmer hereby -affirms that he or she will not (i) exercise any of his or her remaining -Copyright and Related Rights in the Work or (ii) assert any associated claims -and causes of action with respect to the Work, in either case contrary to -Affirmer's express Statement of Purpose. - -4. Limitations and Disclaimers. - - a. No trademark or patent rights held by Affirmer are waived, abandoned, - surrendered, licensed or otherwise affected by this document. - - b. Affirmer offers the Work as-is and makes no representations or warranties - of any kind concerning the Work, express, implied, statutory or otherwise, - including without limitation warranties of title, merchantability, fitness - for a particular purpose, non infringement, or the absence of latent or - other defects, accuracy, or the present or absence of errors, whether or not - discoverable, all to the greatest extent permissible under applicable law. - - c. Affirmer disclaims responsibility for clearing rights of other persons - that may apply to the Work or any use thereof, including without limitation - any person's Copyright and Related Rights in the Work. Further, Affirmer - disclaims responsibility for obtaining any necessary consents, permissions - or other rights required for any use of the Work. - - d. Affirmer understands and acknowledges that Creative Commons is not a - party to this document and has no duty or obligation with respect to this - CC0 or use of the Work. - -For more information, please see - diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_clean/address.c b/src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_clean/address.c deleted file mode 100644 index 324dd196c3..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_clean/address.c +++ /dev/null @@ -1,78 +0,0 @@ -#include - -#include "address.h" -#include "params.h" -#include "utils.h" - -void PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]) { - int i; - - for (i = 0; i < 8; i++) { - PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_ull_to_bytes( - bytes + i * 4, 4, addr[i]); - } -} - -void PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_set_layer_addr( - uint32_t addr[8], uint32_t layer) { - addr[0] = layer; -} - -void PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_set_tree_addr( - uint32_t addr[8], uint64_t tree) { - addr[1] = 0; - addr[2] = (uint32_t) (tree >> 32); - addr[3] = (uint32_t) tree; -} - -void PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_set_type( - uint32_t addr[8], uint32_t type) { - addr[4] = type; -} - -void PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; -} - -/* These functions are used for OTS addresses. */ - -void PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_set_keypair_addr( - uint32_t addr[8], uint32_t keypair) { - addr[5] = keypair; -} - -void PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; - out[5] = in[5]; -} - -void PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_set_chain_addr( - uint32_t addr[8], uint32_t chain) { - addr[6] = chain; -} - -void PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_set_hash_addr( - uint32_t addr[8], uint32_t hash) { - addr[7] = hash; -} - -/* These functions are used for all hash tree addresses (including FORS). */ - -void PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_set_tree_height( - uint32_t addr[8], uint32_t tree_height) { - addr[6] = tree_height; -} - -void PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_set_tree_index( - uint32_t addr[8], uint32_t tree_index) { - addr[7] = tree_index; -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_clean/address.h b/src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_clean/address.h deleted file mode 100644 index 36da1aa63d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_clean/address.h +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_ADDRESS_H -#define PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_ADDRESS_H - -#include - -#define PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_ADDR_TYPE_WOTS 0 -#define PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_ADDR_TYPE_WOTSPK 1 -#define PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_ADDR_TYPE_HASHTREE 2 -#define PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_ADDR_TYPE_FORSTREE 3 -#define PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_ADDR_TYPE_FORSPK 4 - -void PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]); - -void PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_set_layer_addr( - uint32_t addr[8], uint32_t layer); - -void PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_set_tree_addr( - uint32_t addr[8], uint64_t tree); - -void PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_set_type( - uint32_t addr[8], uint32_t type); - -/* Copies the layer and tree part of one address into the other */ -void PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for WOTS and FORS addresses. */ - -void PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_set_keypair_addr( - uint32_t addr[8], uint32_t keypair); - -void PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_set_chain_addr( - uint32_t addr[8], uint32_t chain); - -void PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_set_hash_addr( - uint32_t addr[8], uint32_t hash); - -void PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for all hash tree addresses (including FORS). */ - -void PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_set_tree_height( - uint32_t addr[8], uint32_t tree_height); - -void PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_set_tree_index( - uint32_t addr[8], uint32_t tree_index); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_clean/api.h b/src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_clean/api.h deleted file mode 100644 index a749a41d83..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_clean/api.h +++ /dev/null @@ -1,81 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_API_H -#define PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_API_H - -#include -#include - - - -#define PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_CRYPTO_ALGNAME "SPHINCS+" - -#define PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_CRYPTO_SECRETKEYBYTES 96 -#define PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_CRYPTO_PUBLICKEYBYTES 48 -#define PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_CRYPTO_BYTES 35664 -#define PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_CRYPTO_SEEDBYTES 72 - - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_clean/fors.c b/src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_clean/fors.c deleted file mode 100644 index b6011eee69..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_clean/fors.c +++ /dev/null @@ -1,161 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "fors.h" -#include "hash.h" -#include "hash_state.h" -#include "thash.h" -#include "utils.h" - -static void fors_gen_sk(unsigned char *sk, const unsigned char *sk_seed, - uint32_t fors_leaf_addr[8], const hash_state *hash_state_seeded) { - PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_prf_addr( - sk, sk_seed, fors_leaf_addr, hash_state_seeded); -} - -static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, - const unsigned char *pub_seed, - uint32_t fors_leaf_addr[8], - const hash_state *hash_state_seeded) { - PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_thash_1( - leaf, sk, pub_seed, fors_leaf_addr, hash_state_seeded); -} - -static void fors_gen_leaf(unsigned char *leaf, const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx, const uint32_t fors_tree_addr[8], - const hash_state *hash_state_seeded) { - uint32_t fors_leaf_addr[8] = {0}; - - /* Only copy the parts that must be kept in fors_leaf_addr. */ - PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_copy_keypair_addr( - fors_leaf_addr, fors_tree_addr); - PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_set_type( - fors_leaf_addr, PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_set_tree_index( - fors_leaf_addr, addr_idx); - - fors_gen_sk(leaf, sk_seed, fors_leaf_addr, hash_state_seeded); - fors_sk_to_leaf(leaf, leaf, pub_seed, fors_leaf_addr, hash_state_seeded); -} - -/** - * Interprets m as PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_FORS_HEIGHT-bit unsigned integers. - * Assumes m contains at least PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_FORS_TREES bits. - * Assumes indices has space for PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_FORS_TREES integers. - */ -static void message_to_indices(uint32_t *indices, const unsigned char *m) { - unsigned int i, j; - unsigned int offset = 0; - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_FORS_TREES; i++) { - indices[i] = 0; - for (j = 0; j < PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_FORS_HEIGHT; j++) { - indices[i] ^= (((uint32_t)m[offset >> 3] >> (offset & 0x7)) & 0x1) << j; - offset++; - } - } -} - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_fors_sign( - unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *hash_state_seeded) { - uint32_t indices[PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_FORS_TREES]; - unsigned char roots[PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_FORS_TREES * PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_N]; - uint32_t fors_tree_addr[8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_copy_keypair_addr( - fors_tree_addr, fors_addr); - PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_copy_keypair_addr( - fors_pk_addr, fors_addr); - - PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_set_type( - fors_tree_addr, PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_set_type( - fors_pk_addr, PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_FORS_TREES; i++) { - idx_offset = i * (1 << PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_FORS_HEIGHT); - - PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_set_tree_height( - fors_tree_addr, 0); - PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_set_tree_index( - fors_tree_addr, indices[i] + idx_offset); - - /* Include the secret key part that produces the selected leaf node. */ - fors_gen_sk(sig, sk_seed, fors_tree_addr, hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_N; - - /* Compute the authentication path for this leaf node. */ - PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_treehash_FORS_HEIGHT( - roots + i * PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_N, sig, sk_seed, pub_seed, - indices[i], idx_offset, fors_gen_leaf, fors_tree_addr, - hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_N * PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_thash_FORS_TREES( - pk, roots, pub_seed, fors_pk_addr, hash_state_seeded); -} - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_fors_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, const uint32_t fors_addr[8], - const hash_state *hash_state_seeded) { - uint32_t indices[PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_FORS_TREES]; - unsigned char roots[PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_FORS_TREES * PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_N]; - unsigned char leaf[PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_N]; - uint32_t fors_tree_addr[8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_copy_keypair_addr(fors_tree_addr, fors_addr); - PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_copy_keypair_addr(fors_pk_addr, fors_addr); - - PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_set_type(fors_tree_addr, PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_set_type(fors_pk_addr, PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_FORS_TREES; i++) { - idx_offset = i * (1 << PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_FORS_HEIGHT); - - PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_set_tree_height(fors_tree_addr, 0); - PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Derive the leaf from the included secret key part. */ - fors_sk_to_leaf(leaf, sig, pub_seed, fors_tree_addr, hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_N; - - /* Derive the corresponding root node of this tree. */ - PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_compute_root(roots + i * PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_N, leaf, indices[i], idx_offset, sig, - PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_FORS_HEIGHT, pub_seed, fors_tree_addr, hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_N * PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_thash_FORS_TREES(pk, roots, pub_seed, fors_pk_addr, hash_state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_clean/fors.h b/src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_clean/fors.h deleted file mode 100644 index dcad3583ba..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_clean/fors.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_FORS_H -#define PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_FORS_H - -#include - -#include "hash_state.h" -#include "params.h" - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_fors_sign( - unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *hash_state_seeded); - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_fors_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, const uint32_t fors_addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_clean/hash.h b/src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_clean/hash.h deleted file mode 100644 index 34944417de..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_clean/hash.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_HASH_H -#define PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_HASH_H - -#include "hash_state.h" - -#include -#include - -void PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_initialize_hash_function( - hash_state *hash_state_seeded, - const unsigned char *pub_seed, const unsigned char *sk_seed); - -void PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_destroy_hash_function(hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_clean/hash_shake256.c b/src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_clean/hash_shake256.c deleted file mode 100644 index 08e93bf66e..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_clean/hash_shake256.c +++ /dev/null @@ -1,106 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "utils.h" - -#include "fips202.h" - -/* For SHAKE256, there is no immediate reason to initialize at the start, - so this function is an empty operation. */ -void PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_initialize_hash_function( - hash_state *hash_state_seeded, // NOLINT(readability-non-const-parameter) - const unsigned char *pub_seed, const unsigned char *sk_seed) { - (void)hash_state_seeded; /* Suppress an 'unused parameter' warning. */ - (void)pub_seed; /* Suppress an 'unused parameter' warning. */ - (void)sk_seed; /* Suppress an 'unused parameter' warning. */ -} - -/* This is not necessary for SHAKE256, so we don't do anything */ -void PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_destroy_hash_function( - hash_state *hash_state_seeded) { // NOLINT(readability-non-const-parameter) - (void)hash_state_seeded; -} - -/* - * Computes PRF(key, addr), given a secret key of PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_N bytes and an address - */ -void PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded) { - unsigned char buf[PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_N + PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_ADDR_BYTES]; - - memcpy(buf, key, PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_N); - PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_addr_to_bytes(buf + PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_N, addr); - - shake256(out, PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_N, buf, PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_N + PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_ADDR_BYTES); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} - -/** - * Computes the message-dependent randomness R, using a secret seed and an - * optional randomization value as well as the message. - */ -void PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded) { - shake256incctx state; - - shake256_inc_init(&state); - shake256_inc_absorb(&state, sk_prf, PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_N); - shake256_inc_absorb(&state, optrand, PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_N); - shake256_inc_absorb(&state, m, mlen); - shake256_inc_finalize(&state); - shake256_inc_squeeze(R, PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_N, &state); - shake256_inc_ctx_release(&state); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} - -/** - * Computes the message hash using R, the public key, and the message. - * Outputs the message digest and the index of the leaf. The index is split in - * the tree index and the leaf index, for convenient copying to an address. - */ -void PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded) { -#define PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_TREE_BITS (PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_TREE_HEIGHT * (PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_D - 1)) -#define PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_TREE_BYTES ((PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_TREE_BITS + 7) / 8) -#define PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_LEAF_BITS PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_TREE_HEIGHT -#define PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_LEAF_BYTES ((PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_LEAF_BITS + 7) / 8) -#define PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_DGST_BYTES (PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_FORS_MSG_BYTES + PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_TREE_BYTES + PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_LEAF_BYTES) - - unsigned char buf[PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_DGST_BYTES]; - unsigned char *bufp = buf; - shake256incctx state; - - shake256_inc_init(&state); - shake256_inc_absorb(&state, R, PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_N); - shake256_inc_absorb(&state, pk, PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_PK_BYTES); - shake256_inc_absorb(&state, m, mlen); - shake256_inc_finalize(&state); - shake256_inc_squeeze(buf, PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_DGST_BYTES, &state); - shake256_inc_ctx_release(&state); - - memcpy(digest, bufp, PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_FORS_MSG_BYTES); - bufp += PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_FORS_MSG_BYTES; - - *tree = PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_bytes_to_ull( - bufp, PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_TREE_BYTES); - *tree &= (~(uint64_t)0) >> (64 - PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_TREE_BITS); - bufp += PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_TREE_BYTES; - - *leaf_idx = (uint32_t)PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_bytes_to_ull( - bufp, PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_LEAF_BYTES); - *leaf_idx &= (~(uint32_t)0) >> (32 - PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_LEAF_BITS); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_clean/hash_state.h b/src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_clean/hash_state.h deleted file mode 100644 index 7d92ef872a..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_clean/hash_state.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef SPX_HASH_STATE_H -#define SPX_HASH_STATE_H - -/** - * Defines the type of the hash function state. - * - * Don't be fooled into thinking this instance of SPHINCS+ isn't stateless! - * - * From Section 7.2.2 from the SPHINCS+ round-2 specification: - * - * Each of the instances of the tweakable hash function take PK.seed as its - * first input, which is constant for a given key pair – and, thus, across - * a single signature. This leads to a lot of redundant computation. To remedy - * this, we pad PK.seed to the length of a full 64-byte SHA-256 input block. - * Because of the Merkle-Damgård construction that underlies SHA-256, this - * allows for reuse of the intermediate SHA-256 state after the initial call to - * the compression function which improves performance. - * - * We pass this hash state around in functions, because otherwise we need to - * have a global variable. - * - * SHAKE256 does not need this state. Because this implementation is generated - * from a shared code base, we still need to specify some hash_state as it is - * still passed around. We chose to use an `int` as a placeholder for this - * purpose. - */ - -#define hash_state int - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_clean/params.h b/src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_clean/params.h deleted file mode 100644 index 9c626a1def..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_clean/params.h +++ /dev/null @@ -1,53 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_PARAMS_H -#define PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_PARAMS_H - -/* Hash output length in bytes. */ -#define PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_N 24 -/* Height of the hypertree. */ -#define PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_FULL_HEIGHT 66 -/* Number of subtree layer. */ -#define PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_D 22 -/* FORS tree dimensions. */ -#define PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_FORS_HEIGHT 8 -#define PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_FORS_TREES 33 -/* Winternitz parameter, */ -#define PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_WOTS_W 16 - -/* The hash function is defined by linking a different hash.c file, as opposed - to setting a #define constant. */ - -/* For clarity */ -#define PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_ADDR_BYTES 32 - -/* WOTS parameters. */ -#define PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_WOTS_LOGW 4 - -#define PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_WOTS_LEN1 (8 * PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_N / PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_WOTS_LOGW) - -/* PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#define PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_WOTS_LEN2 3 - -#define PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_WOTS_LEN (PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_WOTS_LEN1 + PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_WOTS_LEN2) -#define PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_WOTS_BYTES (PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_WOTS_LEN * PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_N) -#define PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_WOTS_PK_BYTES PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_WOTS_BYTES - -/* Subtree size. */ -#define PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_TREE_HEIGHT (PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_FULL_HEIGHT / PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_D) - -/* FORS parameters. */ -#define PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_FORS_MSG_BYTES ((PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_FORS_TREES + 7) / 8) -#define PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_FORS_BYTES ((PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_FORS_HEIGHT + 1) * PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_FORS_TREES * PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_N) -#define PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_FORS_PK_BYTES PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_N - -/* Resulting SPX sizes. */ -#define PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_BYTES (PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_N + PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_FORS_BYTES + PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_D * PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_WOTS_BYTES +\ - PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_FULL_HEIGHT * PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_N) -#define PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_PK_BYTES (2 * PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_N) -#define PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_SK_BYTES (2 * PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_N + PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_PK_BYTES) - -/* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ -#define PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_OPTRAND_BYTES 32 - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_clean/sign.c b/src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_clean/sign.c deleted file mode 100644 index d5c8c20071..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_clean/sign.c +++ /dev/null @@ -1,356 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "api.h" -#include "fors.h" -#include "hash.h" -#include "hash_state.h" -#include "params.h" -#include "randombytes.h" -#include "thash.h" -#include "utils.h" -#include "wots.h" - -/** - * Computes the leaf at a given address. First generates the WOTS key pair, - * then computes leaf by hashing horizontally. - */ -static void wots_gen_leaf(unsigned char *leaf, const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx, const uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - unsigned char pk[PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_WOTS_BYTES]; - uint32_t wots_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_set_type( - wots_addr, PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_set_type( - wots_pk_addr, PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_ADDR_TYPE_WOTSPK); - - PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_set_keypair_addr( - wots_addr, addr_idx); - PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_wots_gen_pk( - pk, sk_seed, pub_seed, wots_addr, hash_state_seeded); - - PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_copy_keypair_addr( - wots_pk_addr, wots_addr); - PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_thash_WOTS_LEN( - leaf, pk, pub_seed, wots_pk_addr, hash_state_seeded); -} - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_crypto_sign_secretkeybytes(void) { - return PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_CRYPTO_SECRETKEYBYTES; -} - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_crypto_sign_publickeybytes(void) { - return PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_CRYPTO_PUBLICKEYBYTES; -} - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_crypto_sign_bytes(void) { - return PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_CRYPTO_BYTES; -} - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_crypto_sign_seedbytes(void) { - return PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_CRYPTO_SEEDBYTES; -} - -/* - * Generates an SPX key pair given a seed of length - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed) { - /* We do not need the auth path in key generation, but it simplifies the - code to have just one treehash routine that computes both root and path - in one function. */ - unsigned char auth_path[PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_TREE_HEIGHT * PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_N]; - uint32_t top_tree_addr[8] = {0}; - hash_state hash_state_seeded; - - PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_set_layer_addr( - top_tree_addr, PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_D - 1); - PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_set_type( - top_tree_addr, PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_ADDR_TYPE_HASHTREE); - - /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ - memcpy(sk, seed, PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_CRYPTO_SEEDBYTES); - - memcpy(pk, sk + 2 * PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_N, PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_initialize_hash_function(&hash_state_seeded, pk, sk); - - /* Compute root node of the top-most subtree. */ - PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_treehash_TREE_HEIGHT( - sk + 3 * PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_N, auth_path, sk, sk + 2 * PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_N, 0, 0, - wots_gen_leaf, top_tree_addr, &hash_state_seeded); - - memcpy(pk + PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_N, sk + 3 * PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_N, PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_N); - - PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_destroy_hash_function(&hash_state_seeded); - return 0; -} - -/* - * Generates an SPX key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk) { - unsigned char seed[PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_CRYPTO_SEEDBYTES]; - randombytes(seed, PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_CRYPTO_SEEDBYTES); - PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_crypto_sign_seed_keypair( - pk, sk, seed); - - return 0; -} - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - const unsigned char *sk_seed = sk; - const unsigned char *sk_prf = sk + PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_N; - const unsigned char *pk = sk + 2 * PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_N; - const unsigned char *pub_seed = pk; - - unsigned char optrand[PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_N]; - unsigned char mhash[PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_FORS_MSG_BYTES]; - unsigned char root[PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_N]; - uint32_t i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - - hash_state hash_state_seeded; - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_initialize_hash_function( - &hash_state_seeded, - pub_seed, sk_seed); - - PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_set_type( - wots_addr, PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_set_type( - tree_addr, PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_ADDR_TYPE_HASHTREE); - - /* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ - randombytes(optrand, PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_N); - /* Compute the digest randomization value. */ - PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_gen_message_random( - sig, sk_prf, optrand, m, mlen, &hash_state_seeded); - - /* Derive the message digest and leaf index from R, PK and M. */ - PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_N; - - PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); - - /* Sign the message hash using FORS. */ - PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_fors_sign( - sig, root, mhash, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_FORS_BYTES; - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_D; i++) { - PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_set_tree_addr(tree_addr, tree); - - PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); - - /* Compute a WOTS signature. */ - PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_wots_sign( - sig, root, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_WOTS_BYTES; - - /* Compute the authentication path for the used WOTS leaf. */ - PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_treehash_TREE_HEIGHT( - root, sig, sk_seed, pub_seed, idx_leaf, 0, - wots_gen_leaf, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_TREE_HEIGHT * PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_TREE_HEIGHT; - } - - *siglen = PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_BYTES; - - PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_destroy_hash_function(&hash_state_seeded); - return 0; -} - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk) { - const unsigned char *pub_seed = pk; - const unsigned char *pub_root = pk + PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_N; - unsigned char mhash[PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_FORS_MSG_BYTES]; - unsigned char wots_pk[PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_WOTS_BYTES]; - unsigned char root[PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_N]; - unsigned char leaf[PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_N]; - unsigned int i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - hash_state hash_state_seeded; - - if (siglen != PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_BYTES) { - return -1; - } - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_initialize_hash_function( - &hash_state_seeded, - pub_seed, NULL); - - PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_set_type( - wots_addr, PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_set_type( - tree_addr, PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_ADDR_TYPE_HASHTREE); - PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_set_type( - wots_pk_addr, PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_ADDR_TYPE_WOTSPK); - - /* Derive the message digest and leaf index from R || PK || M. */ - /* The additional PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_N is a result of the hash domain separator. */ - PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_N; - - /* Layer correctly defaults to 0, so no need to set_layer_addr */ - PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); - - PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_fors_pk_from_sig( - root, sig, mhash, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_FORS_BYTES; - - /* For each subtree.. */ - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_D; i++) { - PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_set_tree_addr(tree_addr, tree); - - PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); - - PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_copy_keypair_addr( - wots_pk_addr, wots_addr); - - /* The WOTS public key is only correct if the signature was correct. */ - /* Initially, root is the FORS pk, but on subsequent iterations it is - the root of the subtree below the currently processed subtree. */ - PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_wots_pk_from_sig( - wots_pk, sig, root, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_WOTS_BYTES; - - /* Compute the leaf node using the WOTS public key. */ - PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_thash_WOTS_LEN( - leaf, wots_pk, pub_seed, wots_pk_addr, &hash_state_seeded); - - /* Compute the root node of this subtree. */ - PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_compute_root( - root, leaf, idx_leaf, 0, sig, PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_TREE_HEIGHT, - pub_seed, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_TREE_HEIGHT * PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_TREE_HEIGHT; - } - - PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_destroy_hash_function(&hash_state_seeded); - /* Check if the root node equals the root node in the public key. */ - if (memcmp(root, pub_root, PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_N) != 0) { - return -1; - } - - return 0; -} - - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - size_t siglen; - - PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_crypto_sign_signature( - sm, &siglen, m, mlen, sk); - - memmove(sm + PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_BYTES, m, mlen); - *smlen = siglen + mlen; - - return 0; -} - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk) { - /* The API caller does not necessarily know what size a signature should be - but SPHINCS+ signatures are always exactly PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_BYTES. */ - if (smlen < PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_BYTES) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - *mlen = smlen - PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_BYTES; - - if (PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_crypto_sign_verify( - sm, PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_BYTES, sm + PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_BYTES, *mlen, pk)) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - /* If verification was successful, move the message to the right place. */ - memmove(m, sm + PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_BYTES, *mlen); - - return 0; -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_clean/thash.h b/src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_clean/thash.h deleted file mode 100644 index b2025e41a8..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_clean/thash.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_THASH_H -#define PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_THASH_H - -#include "hash_state.h" - -#include - -void PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_clean/thash_shake256_robust.c b/src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_clean/thash_shake256_robust.c deleted file mode 100644 index c8694fa58d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_clean/thash_shake256_robust.c +++ /dev/null @@ -1,81 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "thash.h" - -#include "fips202.h" - -/** - * Takes an array of inblocks concatenated arrays of PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_N bytes. - */ -static void PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_thash( - unsigned char *out, unsigned char *buf, - const unsigned char *in, unsigned int inblocks, - const unsigned char *pub_seed, uint32_t addr[8]) { - - unsigned char *bitmask = buf + PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_N + PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_ADDR_BYTES; - unsigned int i; - - memcpy(buf, pub_seed, PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_N); - PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_addr_to_bytes(buf + PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_N, addr); - - shake256(bitmask, inblocks * PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_N, buf, PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_N + PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_ADDR_BYTES); - - for (i = 0; i < inblocks * PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_N; i++) { - buf[PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_N + PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_ADDR_BYTES + i] = in[i] ^ bitmask[i]; - } - - shake256(out, PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_N, buf, PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_N + PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_N); -} - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_N + PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_ADDR_BYTES + 1 * PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_N]; - PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_thash( - out, buf, in, 1, pub_seed, addr); - - (void)hash_state_seeded; /* Avoid unused parameter warning. */ -} - -void PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_N + PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_ADDR_BYTES + 2 * PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_N]; - PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_thash( - out, buf, in, 2, pub_seed, addr); - - (void)hash_state_seeded; /* Avoid unused parameter warning. */ -} - -void PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_N + PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_ADDR_BYTES + PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_WOTS_LEN * PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_N]; - PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_thash( - out, buf, in, PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_WOTS_LEN, pub_seed, addr); - - (void)hash_state_seeded; /* Avoid unused parameter warning. */ -} - -void PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_N + PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_ADDR_BYTES + PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_FORS_TREES * PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_N]; - PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_thash( - out, buf, in, PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_FORS_TREES, pub_seed, addr); - - (void)hash_state_seeded; /* Avoid unused parameter warning. */ -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_clean/utils.c b/src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_clean/utils.c deleted file mode 100644 index 2f1318c9b7..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_clean/utils.c +++ /dev/null @@ -1,199 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "hash_state.h" -#include "params.h" -#include "thash.h" -#include "utils.h" - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in) { - - /* Iterate over out in decreasing order, for big-endianness. */ - for (size_t i = outlen; i > 0; i--) { - out[i - 1] = in & 0xff; - in = in >> 8; - } -} - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_bytes_to_ull( - const unsigned char *in, size_t inlen) { - unsigned long long retval = 0; - - for (size_t i = 0; i < inlen; i++) { - retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); - } - return retval; -} - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - uint32_t i; - unsigned char buffer[2 * PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_N]; - - /* If leaf_idx is odd (last bit = 1), current path element is a right child - and auth_path has to go left. Otherwise it is the other way around. */ - if (leaf_idx & 1) { - memcpy(buffer + PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_N, leaf, PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_N); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_N); - } else { - memcpy(buffer, leaf, PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_N); - memcpy(buffer + PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_N, auth_path, PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_N); - } - auth_path += PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_N; - - for (i = 0; i < tree_height - 1; i++) { - leaf_idx >>= 1; - idx_offset >>= 1; - /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_set_tree_height(addr, i + 1); - PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_set_tree_index( - addr, leaf_idx + idx_offset); - - /* Pick the right or left neighbor, depending on parity of the node. */ - if (leaf_idx & 1) { - PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_thash_2( - buffer + PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_N, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_N); - } else { - PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_thash_2( - buffer, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer + PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_N, auth_path, PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_N); - } - auth_path += PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_N; - } - - /* The last iteration is exceptional; we do not copy an auth_path node. */ - leaf_idx >>= 1; - idx_offset >>= 1; - PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_set_tree_height(addr, tree_height); - PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_set_tree_index( - addr, leaf_idx + idx_offset); - PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_thash_2( - root, buffer, pub_seed, addr, hash_state_seeded); -} - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -static void PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_treehash( - unsigned char *root, unsigned char *auth_path, - unsigned char *stack, unsigned int *heights, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - - unsigned int offset = 0; - uint32_t idx; - uint32_t tree_idx; - - for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { - /* Add the next leaf node to the stack. */ - gen_leaf(stack + offset * PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_N, - sk_seed, pub_seed, idx + idx_offset, tree_addr, - hash_state_seeded); - offset++; - heights[offset - 1] = 0; - - /* If this is a node we need for the auth path.. */ - if ((leaf_idx ^ 0x1) == idx) { - memcpy(auth_path, stack + (offset - 1)*PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_N, PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_N); - } - - /* While the top-most nodes are of equal height.. */ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { - /* Compute index of the new node, in the next layer. */ - tree_idx = (idx >> (heights[offset - 1] + 1)); - - /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_set_tree_height( - tree_addr, heights[offset - 1] + 1); - PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_set_tree_index( - tree_addr, tree_idx + (idx_offset >> (heights[offset - 1] + 1))); - /* Hash the top-most nodes from the stack together. */ - PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_thash_2( - stack + (offset - 2)*PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_N, stack + (offset - 2)*PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_N, - pub_seed, tree_addr, hash_state_seeded); - offset--; - /* Note that the top-most node is now one layer higher. */ - heights[offset - 1]++; - - /* If this is a node we need for the auth path.. */ - if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_path + heights[offset - 1]*PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_N, - stack + (offset - 1)*PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_N, PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_N); - } - } - } - memcpy(root, stack, PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_N); -} - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_FORS_HEIGHT + 1)*PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_N]; - unsigned int heights[PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_FORS_HEIGHT + 1]; - - PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_FORS_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_TREE_HEIGHT + 1)*PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_N]; - unsigned int heights[PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_TREE_HEIGHT + 1]; - - PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_TREE_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_clean/utils.h b/src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_clean/utils.h deleted file mode 100644 index 2b6363a418..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_clean/utils.h +++ /dev/null @@ -1,64 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_UTILS_H -#define PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_UTILS_H - -#include "hash_state.h" -#include "params.h" -#include -#include - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in); - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_bytes_to_ull( - const unsigned char *in, size_t inlen); - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -void PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_clean/wots.c b/src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_clean/wots.c deleted file mode 100644 index 9307bdead1..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_clean/wots.c +++ /dev/null @@ -1,167 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "hash_state.h" -#include "params.h" -#include "thash.h" -#include "utils.h" -#include "wots.h" - -// TODO clarify address expectations, and make them more uniform. -// TODO i.e. do we expect types to be set already? -// TODO and do we expect modifications or copies? - -/** - * Computes the starting value for a chain, i.e. the secret key. - * Expects the address to be complete up to the chain address. - */ -static void wots_gen_sk(unsigned char *sk, const unsigned char *sk_seed, - uint32_t wots_addr[8], - const hash_state *hash_state_seeded) { - /* Make sure that the hash address is actually zeroed. */ - PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_set_hash_addr(wots_addr, 0); - - /* Generate sk element. */ - PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_prf_addr(sk, sk_seed, wots_addr, hash_state_seeded); -} - -/** - * Computes the chaining function. - * out and in have to be n-byte arrays. - * - * Interprets in as start-th value of the chain. - * addr has to contain the address of the chain. - */ -static void gen_chain(unsigned char *out, const unsigned char *in, - unsigned int start, unsigned int steps, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - uint32_t i; - - /* Initialize out with the value at position 'start'. */ - memcpy(out, in, PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_N); - - /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_WOTS_W; i++) { - PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_set_hash_addr(addr, i); - PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_thash_1( - out, out, pub_seed, addr, hash_state_seeded); - } -} - -/** - * base_w algorithm as described in draft. - * Interprets an array of bytes as integers in base w. - * This only works when log_w is a divisor of 8. - */ -static void base_w(unsigned int *output, const size_t out_len, - const unsigned char *input) { - size_t in = 0; - size_t out = 0; - unsigned char total = 0; - unsigned int bits = 0; - size_t consumed; - - for (consumed = 0; consumed < out_len; consumed++) { - if (bits == 0) { - total = input[in]; - in++; - bits += 8; - } - bits -= PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_WOTS_LOGW; - output[out] = (unsigned int)((total >> bits) & (PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_WOTS_W - 1)); - out++; - } -} - -/* Computes the WOTS+ checksum over a message (in base_w). */ -static void wots_checksum(unsigned int *csum_base_w, - const unsigned int *msg_base_w) { - unsigned int csum = 0; - unsigned char csum_bytes[(PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_WOTS_LEN2 * PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_WOTS_LOGW + 7) / 8]; - unsigned int i; - - /* Compute checksum. */ - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_WOTS_LEN1; i++) { - csum += PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_WOTS_W - 1 - msg_base_w[i]; - } - - /* Convert checksum to base_w. */ - /* Make sure expected empty zero bits are the least significant bits. */ - csum = csum << (8 - ((PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_WOTS_LEN2 * PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_WOTS_LOGW) % 8)); - PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_ull_to_bytes( - csum_bytes, sizeof(csum_bytes), csum); - base_w(csum_base_w, PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_WOTS_LEN2, csum_bytes); -} - -/* Takes a message and derives the matching chain lengths. */ -static void chain_lengths(unsigned int *lengths, const unsigned char *msg) { - base_w(lengths, PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_WOTS_LEN1, msg); - wots_checksum(lengths + PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_WOTS_LEN1, lengths); -} - -/** - * WOTS key generation. Takes a 32 byte sk_seed, expands it to WOTS private key - * elements and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_wots_gen_pk( - unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - uint32_t i; - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_WOTS_LEN; i++) { - PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_set_chain_addr(addr, i); - wots_gen_sk(pk + i * PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_N, sk_seed, addr, hash_state_seeded); - gen_chain(pk + i * PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_N, pk + i * PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_N, - 0, PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_WOTS_W - 1, pub_seed, addr, hash_state_seeded); - } -} - -/** - * Takes a n-byte message and the 32-byte sk_see to compute a signature 'sig'. - */ -void PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_wots_sign( - unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *hash_state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_WOTS_LEN; i++) { - PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_set_chain_addr(addr, i); - wots_gen_sk(sig + i * PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_N, sk_seed, addr, hash_state_seeded); - gen_chain(sig + i * PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_N, sig + i * PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_N, 0, lengths[i], pub_seed, addr, hash_state_seeded); - } -} - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_wots_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_WOTS_LEN; i++) { - PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_set_chain_addr(addr, i); - gen_chain(pk + i * PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_N, sig + i * PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_N, - lengths[i], PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_WOTS_W - 1 - lengths[i], pub_seed, addr, - hash_state_seeded); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_clean/wots.h b/src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_clean/wots.h deleted file mode 100644 index 572232ad33..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192f-robust_clean/wots.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_WOTS_H -#define PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_WOTS_H - -#include "hash_state.h" -#include "params.h" -#include - -/** - * WOTS key generation. Takes a 32 byte seed for the private key, expands it to - * a full WOTS private key and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_wots_gen_pk( - unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -/** - * Takes a n-byte message and the 32-byte seed for the private key to compute a - * signature that is placed at 'sig'. - */ -void PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_wots_sign( - unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *hash_state_seeded); - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_wots_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_avx2/LICENSE b/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_avx2/LICENSE deleted file mode 100644 index 670154e353..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_avx2/LICENSE +++ /dev/null @@ -1,116 +0,0 @@ -CC0 1.0 Universal - -Statement of Purpose - -The laws of most jurisdictions throughout the world automatically confer -exclusive Copyright and Related Rights (defined below) upon the creator and -subsequent owner(s) (each and all, an "owner") of an original work of -authorship and/or a database (each, a "Work"). - -Certain owners wish to permanently relinquish those rights to a Work for the -purpose of contributing to a commons of creative, cultural and scientific -works ("Commons") that the public can reliably and without fear of later -claims of infringement build upon, modify, incorporate in other works, reuse -and redistribute as freely as possible in any form whatsoever and for any -purposes, including without limitation commercial purposes. These owners may -contribute to the Commons to promote the ideal of a free culture and the -further production of creative, cultural and scientific works, or to gain -reputation or greater distribution for their Work in part through the use and -efforts of others. - -For these and/or other purposes and motivations, and without any expectation -of additional consideration or compensation, the person associating CC0 with a -Work (the "Affirmer"), to the extent that he or she is an owner of Copyright -and Related Rights in the Work, voluntarily elects to apply CC0 to the Work -and publicly distribute the Work under its terms, with knowledge of his or her -Copyright and Related Rights in the Work and the meaning and intended legal -effect of CC0 on those rights. - -1. Copyright and Related Rights. A Work made available under CC0 may be -protected by copyright and related or neighboring rights ("Copyright and -Related Rights"). Copyright and Related Rights include, but are not limited -to, the following: - - i. the right to reproduce, adapt, distribute, perform, display, communicate, - and translate a Work; - - ii. moral rights retained by the original author(s) and/or performer(s); - - iii. publicity and privacy rights pertaining to a person's image or likeness - depicted in a Work; - - iv. rights protecting against unfair competition in regards to a Work, - subject to the limitations in paragraph 4(a), below; - - v. rights protecting the extraction, dissemination, use and reuse of data in - a Work; - - vi. database rights (such as those arising under Directive 96/9/EC of the - European Parliament and of the Council of 11 March 1996 on the legal - protection of databases, and under any national implementation thereof, - including any amended or successor version of such directive); and - - vii. other similar, equivalent or corresponding rights throughout the world - based on applicable law or treaty, and any national implementations thereof. - -2. Waiver. To the greatest extent permitted by, but not in contravention of, -applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and -unconditionally waives, abandons, and surrenders all of Affirmer's Copyright -and Related Rights and associated claims and causes of action, whether now -known or unknown (including existing as well as future claims and causes of -action), in the Work (i) in all territories worldwide, (ii) for the maximum -duration provided by applicable law or treaty (including future time -extensions), (iii) in any current or future medium and for any number of -copies, and (iv) for any purpose whatsoever, including without limitation -commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes -the Waiver for the benefit of each member of the public at large and to the -detriment of Affirmer's heirs and successors, fully intending that such Waiver -shall not be subject to revocation, rescission, cancellation, termination, or -any other legal or equitable action to disrupt the quiet enjoyment of the Work -by the public as contemplated by Affirmer's express Statement of Purpose. - -3. Public License Fallback. Should any part of the Waiver for any reason be -judged legally invalid or ineffective under applicable law, then the Waiver -shall be preserved to the maximum extent permitted taking into account -Affirmer's express Statement of Purpose. In addition, to the extent the Waiver -is so judged Affirmer hereby grants to each affected person a royalty-free, -non transferable, non sublicensable, non exclusive, irrevocable and -unconditional license to exercise Affirmer's Copyright and Related Rights in -the Work (i) in all territories worldwide, (ii) for the maximum duration -provided by applicable law or treaty (including future time extensions), (iii) -in any current or future medium and for any number of copies, and (iv) for any -purpose whatsoever, including without limitation commercial, advertising or -promotional purposes (the "License"). The License shall be deemed effective as -of the date CC0 was applied by Affirmer to the Work. Should any part of the -License for any reason be judged legally invalid or ineffective under -applicable law, such partial invalidity or ineffectiveness shall not -invalidate the remainder of the License, and in such case Affirmer hereby -affirms that he or she will not (i) exercise any of his or her remaining -Copyright and Related Rights in the Work or (ii) assert any associated claims -and causes of action with respect to the Work, in either case contrary to -Affirmer's express Statement of Purpose. - -4. Limitations and Disclaimers. - - a. No trademark or patent rights held by Affirmer are waived, abandoned, - surrendered, licensed or otherwise affected by this document. - - b. Affirmer offers the Work as-is and makes no representations or warranties - of any kind concerning the Work, express, implied, statutory or otherwise, - including without limitation warranties of title, merchantability, fitness - for a particular purpose, non infringement, or the absence of latent or - other defects, accuracy, or the present or absence of errors, whether or not - discoverable, all to the greatest extent permissible under applicable law. - - c. Affirmer disclaims responsibility for clearing rights of other persons - that may apply to the Work or any use thereof, including without limitation - any person's Copyright and Related Rights in the Work. Further, Affirmer - disclaims responsibility for obtaining any necessary consents, permissions - or other rights required for any use of the Work. - - d. Affirmer understands and acknowledges that Creative Commons is not a - party to this document and has no duty or obligation with respect to this - CC0 or use of the Work. - -For more information, please see - diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_avx2/address.c b/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_avx2/address.c deleted file mode 100644 index b8ee1f9b84..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_avx2/address.c +++ /dev/null @@ -1,78 +0,0 @@ -#include - -#include "address.h" -#include "params.h" -#include "utils.h" - -void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]) { - int i; - - for (i = 0; i < 8; i++) { - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_ull_to_bytes( - bytes + i * 4, 4, addr[i]); - } -} - -void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_set_layer_addr( - uint32_t addr[8], uint32_t layer) { - addr[0] = layer; -} - -void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_set_tree_addr( - uint32_t addr[8], uint64_t tree) { - addr[1] = 0; - addr[2] = (uint32_t) (tree >> 32); - addr[3] = (uint32_t) tree; -} - -void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_set_type( - uint32_t addr[8], uint32_t type) { - addr[4] = type; -} - -void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; -} - -/* These functions are used for OTS addresses. */ - -void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_set_keypair_addr( - uint32_t addr[8], uint32_t keypair) { - addr[5] = keypair; -} - -void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; - out[5] = in[5]; -} - -void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_set_chain_addr( - uint32_t addr[8], uint32_t chain) { - addr[6] = chain; -} - -void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_set_hash_addr( - uint32_t addr[8], uint32_t hash) { - addr[7] = hash; -} - -/* These functions are used for all hash tree addresses (including FORS). */ - -void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_set_tree_height( - uint32_t addr[8], uint32_t tree_height) { - addr[6] = tree_height; -} - -void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_set_tree_index( - uint32_t addr[8], uint32_t tree_index) { - addr[7] = tree_index; -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_avx2/address.h b/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_avx2/address.h deleted file mode 100644 index 2c4ef85637..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_avx2/address.h +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_ADDRESS_H -#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_ADDRESS_H - -#include - -#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_ADDR_TYPE_WOTS 0 -#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_ADDR_TYPE_WOTSPK 1 -#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_ADDR_TYPE_HASHTREE 2 -#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_ADDR_TYPE_FORSTREE 3 -#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_ADDR_TYPE_FORSPK 4 - -void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]); - -void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_set_layer_addr( - uint32_t addr[8], uint32_t layer); - -void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_set_tree_addr( - uint32_t addr[8], uint64_t tree); - -void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_set_type( - uint32_t addr[8], uint32_t type); - -/* Copies the layer and tree part of one address into the other */ -void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for WOTS and FORS addresses. */ - -void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_set_keypair_addr( - uint32_t addr[8], uint32_t keypair); - -void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_set_chain_addr( - uint32_t addr[8], uint32_t chain); - -void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_set_hash_addr( - uint32_t addr[8], uint32_t hash); - -void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for all hash tree addresses (including FORS). */ - -void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_set_tree_height( - uint32_t addr[8], uint32_t tree_height); - -void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_set_tree_index( - uint32_t addr[8], uint32_t tree_index); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_avx2/api.h b/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_avx2/api.h deleted file mode 100644 index 7d13263029..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_avx2/api.h +++ /dev/null @@ -1,81 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_API_H -#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_API_H - -#include -#include - - - -#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_CRYPTO_ALGNAME "SPHINCS+" - -#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_CRYPTO_SECRETKEYBYTES 96 -#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_CRYPTO_PUBLICKEYBYTES 48 -#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_CRYPTO_BYTES 35664 -#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_CRYPTO_SEEDBYTES 72 - - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_avx2/fors.c b/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_avx2/fors.c deleted file mode 100644 index 517554cf7a..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_avx2/fors.c +++ /dev/null @@ -1,206 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "fors.h" -#include "hash.h" -#include "hashx4.h" -#include "thash.h" -#include "thashx4.h" -#include "utils.h" -#include "utilsx4.h" - -static void fors_gen_skx4(unsigned char *sk0, - unsigned char *sk1, - unsigned char *sk2, - unsigned char *sk3, const unsigned char *sk_seed, - uint32_t fors_leaf_addrx4[4 * 8], - const hash_state *state_seeded) { - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_prf_addrx4(sk0, sk1, sk2, sk3, sk_seed, fors_leaf_addrx4, state_seeded); -} - -static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, - const unsigned char *pub_seed, - uint32_t fors_leaf_addr[8], const hash_state *state_seeded) { - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_thash_1(leaf, sk, pub_seed, fors_leaf_addr, state_seeded); -} - -static void fors_sk_to_leafx4(unsigned char *leaf0, - unsigned char *leaf1, - unsigned char *leaf2, - unsigned char *leaf3, - const unsigned char *sk0, - const unsigned char *sk1, - const unsigned char *sk2, - const unsigned char *sk3, - const unsigned char *pub_seed, - uint32_t fors_leaf_addrx4[4 * 8], - const hash_state *state_seeded) { - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_thashx4_1(leaf0, leaf1, leaf2, leaf3, - sk0, sk1, sk2, sk3, pub_seed, fors_leaf_addrx4, state_seeded); -} - -static void fors_gen_leafx4(unsigned char *leaf0, - unsigned char *leaf1, - unsigned char *leaf2, - unsigned char *leaf3, - const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx0, - uint32_t addr_idx1, - uint32_t addr_idx2, - uint32_t addr_idx3, - const uint32_t fors_tree_addr[8], - const hash_state *state_seeded) { - uint32_t fors_leaf_addrx4[4 * 8] = {0}; - unsigned int j; - - /* Only copy the parts that must be kept in fors_leaf_addrx4. */ - for (j = 0; j < 4; j++) { - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_copy_keypair_addr(fors_leaf_addrx4 + j * 8, fors_tree_addr); - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_set_type(fors_leaf_addrx4 + j * 8, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_ADDR_TYPE_FORSTREE); - } - - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_set_tree_index(fors_leaf_addrx4 + 0 * 8, addr_idx0); - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_set_tree_index(fors_leaf_addrx4 + 1 * 8, addr_idx1); - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_set_tree_index(fors_leaf_addrx4 + 2 * 8, addr_idx2); - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_set_tree_index(fors_leaf_addrx4 + 3 * 8, addr_idx3); - - fors_gen_skx4(leaf0, leaf1, leaf2, leaf3, sk_seed, fors_leaf_addrx4, state_seeded); - fors_sk_to_leafx4(leaf0, leaf1, leaf2, leaf3, - leaf0, leaf1, leaf2, leaf3, pub_seed, fors_leaf_addrx4, state_seeded); -} - -/** - * Interprets m as PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_FORS_HEIGHT-bit unsigned integers. - * Assumes m contains at least PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_FORS_TREES bits. - * Assumes indices has space for PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_FORS_TREES integers. - */ -static void message_to_indices(uint32_t *indices, const unsigned char *m) { - unsigned int i, j; - unsigned int offset = 0; - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_FORS_TREES; i++) { - indices[i] = 0; - for (j = 0; j < PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_FORS_HEIGHT; j++) { - indices[i] ^= (((uint32_t)m[offset >> 3] >> (offset & 0x7)) & 0x1) << j; - offset++; - } - } -} - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *state_seeded) { - /* Round up to multiple of 4 to prevent out-of-bounds for x4 parallelism */ - uint32_t indices[(PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_FORS_TREES + 3) & ~3] = {0}; - unsigned char roots[((PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_FORS_TREES + 3) & ~3) * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N]; - /* Sign to a buffer, since we may not have a nice multiple of 4 and would - otherwise overrun the signature. */ - unsigned char sigbufx4[4 * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N * (1 + PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_FORS_HEIGHT)]; - uint32_t fors_tree_addrx4[4 * 8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset[4] = {0}; - unsigned int i, j; - - for (j = 0; j < 4; j++) { - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_copy_keypair_addr(fors_tree_addrx4 + j * 8, fors_addr); - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_set_type(fors_tree_addrx4 + j * 8, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_ADDR_TYPE_FORSTREE); - } - - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_copy_keypair_addr(fors_pk_addr, fors_addr); - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_set_type(fors_pk_addr, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < ((PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_FORS_TREES + 3) & ~0x3); i += 4) { - for (j = 0; j < 4; j++) { - if (i + j < PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_FORS_TREES) { - idx_offset[j] = (i + j) * (1 << PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_FORS_HEIGHT); - - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_set_tree_height(fors_tree_addrx4 + j * 8, 0); - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_set_tree_index(fors_tree_addrx4 + j * 8, - indices[i + j] + idx_offset[j]); - } - } - - /* Include the secret key part that produces the selected leaf nodes. */ - fors_gen_skx4(sigbufx4 + 0 * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N, - sigbufx4 + 1 * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N, - sigbufx4 + 2 * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N, - sigbufx4 + 3 * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N, - sk_seed, fors_tree_addrx4, state_seeded); - - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_treehashx4_FORS_HEIGHT(roots + i * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N, sigbufx4 + 4 * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N, sk_seed, pub_seed, - &indices[i], idx_offset, fors_gen_leafx4, fors_tree_addrx4, - state_seeded); - - for (j = 0; j < 4; j++) { - if (i + j < PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_FORS_TREES) { - memcpy(sig, sigbufx4 + j * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N); - memcpy(sig + PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N, - sigbufx4 + 4 * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N + j * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_FORS_HEIGHT, - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_FORS_HEIGHT); - sig += PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N * (1 + PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_FORS_HEIGHT); - } - } - } - - /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_thash_FORS_TREES(pk, roots, pub_seed, fors_pk_addr, state_seeded); -} - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, - const uint32_t fors_addr[8], - const hash_state *state_seeded) { - uint32_t indices[PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_FORS_TREES]; - unsigned char roots[PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_FORS_TREES * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N]; - unsigned char leaf[PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N]; - uint32_t fors_tree_addr[8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_copy_keypair_addr(fors_tree_addr, fors_addr); - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_copy_keypair_addr(fors_pk_addr, fors_addr); - - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_set_type(fors_tree_addr, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_set_type(fors_pk_addr, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_FORS_TREES; i++) { - idx_offset = i * (1 << PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_FORS_HEIGHT); - - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_set_tree_height(fors_tree_addr, 0); - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Derive the leaf from the included secret key part. */ - fors_sk_to_leaf(leaf, sig, pub_seed, fors_tree_addr, state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N; - - /* Derive the corresponding root node of this tree. */ - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_compute_root(roots + i * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N, leaf, indices[i], idx_offset, - sig, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_FORS_HEIGHT, pub_seed, fors_tree_addr, - state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_thash_FORS_TREES(pk, roots, pub_seed, fors_pk_addr, state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_avx2/fors.h b/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_avx2/fors.h deleted file mode 100644 index 98e84c1833..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_avx2/fors.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_FORS_H -#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_FORS_H - -#include - -#include "hash_state.h" -#include "params.h" - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_fors_sign( - unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *hash_state_seeded); - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_fors_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, const uint32_t fors_addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_avx2/hash.h b/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_avx2/hash.h deleted file mode 100644 index 5c0142c8af..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_avx2/hash.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_HASH_H -#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_HASH_H - -#include "hash_state.h" - -#include -#include - -void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_initialize_hash_function( - hash_state *hash_state_seeded, - const unsigned char *pub_seed, const unsigned char *sk_seed); - -void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_destroy_hash_function(hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_avx2/hash_shake256.c b/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_avx2/hash_shake256.c deleted file mode 100644 index 9b19a6d96d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_avx2/hash_shake256.c +++ /dev/null @@ -1,106 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "utils.h" - -#include "fips202.h" - -/* For SHAKE256, there is no immediate reason to initialize at the start, - so this function is an empty operation. */ -void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_initialize_hash_function( - hash_state *hash_state_seeded, // NOLINT(readability-non-const-parameter) - const unsigned char *pub_seed, const unsigned char *sk_seed) { - (void)hash_state_seeded; /* Suppress an 'unused parameter' warning. */ - (void)pub_seed; /* Suppress an 'unused parameter' warning. */ - (void)sk_seed; /* Suppress an 'unused parameter' warning. */ -} - -/* This is not necessary for SHAKE256, so we don't do anything */ -void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_destroy_hash_function( - hash_state *hash_state_seeded) { // NOLINT(readability-non-const-parameter) - (void)hash_state_seeded; -} - -/* - * Computes PRF(key, addr), given a secret key of PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N bytes and an address - */ -void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded) { - unsigned char buf[PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_ADDR_BYTES]; - - memcpy(buf, key, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N); - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_addr_to_bytes(buf + PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N, addr); - - shake256(out, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N, buf, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_ADDR_BYTES); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} - -/** - * Computes the message-dependent randomness R, using a secret seed and an - * optional randomization value as well as the message. - */ -void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded) { - shake256incctx state; - - shake256_inc_init(&state); - shake256_inc_absorb(&state, sk_prf, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N); - shake256_inc_absorb(&state, optrand, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N); - shake256_inc_absorb(&state, m, mlen); - shake256_inc_finalize(&state); - shake256_inc_squeeze(R, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N, &state); - shake256_inc_ctx_release(&state); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} - -/** - * Computes the message hash using R, the public key, and the message. - * Outputs the message digest and the index of the leaf. The index is split in - * the tree index and the leaf index, for convenient copying to an address. - */ -void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded) { -#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_TREE_BITS (PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_TREE_HEIGHT * (PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_D - 1)) -#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_TREE_BYTES ((PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_TREE_BITS + 7) / 8) -#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_LEAF_BITS PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_TREE_HEIGHT -#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_LEAF_BYTES ((PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_LEAF_BITS + 7) / 8) -#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_DGST_BYTES (PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_FORS_MSG_BYTES + PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_TREE_BYTES + PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_LEAF_BYTES) - - unsigned char buf[PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_DGST_BYTES]; - unsigned char *bufp = buf; - shake256incctx state; - - shake256_inc_init(&state); - shake256_inc_absorb(&state, R, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N); - shake256_inc_absorb(&state, pk, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_PK_BYTES); - shake256_inc_absorb(&state, m, mlen); - shake256_inc_finalize(&state); - shake256_inc_squeeze(buf, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_DGST_BYTES, &state); - shake256_inc_ctx_release(&state); - - memcpy(digest, bufp, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_FORS_MSG_BYTES); - bufp += PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_FORS_MSG_BYTES; - - *tree = PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_bytes_to_ull( - bufp, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_TREE_BYTES); - *tree &= (~(uint64_t)0) >> (64 - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_TREE_BITS); - bufp += PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_TREE_BYTES; - - *leaf_idx = (uint32_t)PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_bytes_to_ull( - bufp, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_LEAF_BYTES); - *leaf_idx &= (~(uint32_t)0) >> (32 - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_LEAF_BITS); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_avx2/hash_shake256x4.c b/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_avx2/hash_shake256x4.c deleted file mode 100644 index 8f1cd8834e..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_avx2/hash_shake256x4.c +++ /dev/null @@ -1,38 +0,0 @@ -#include -#include - -#include "address.h" -#include "fips202x4.h" -#include "hashx4.h" -#include "params.h" - -/* - * 4-way parallel version of prf_addr; takes 4x as much input and output - */ -void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_prf_addrx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const unsigned char *key, - const uint32_t addrx4[4 * 8], - const hash_state *state_seeded) { - unsigned char bufx4[4 * (PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_ADDR_BYTES)]; - unsigned int j; - - for (j = 0; j < 4; j++) { - memcpy(bufx4 + j * (PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_ADDR_BYTES), key, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N); - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_addr_to_bytes(bufx4 + PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N + j * (PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_ADDR_BYTES), addrx4 + j * 8); - } - - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_shake256x4(out0, - out1, - out2, - out3, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N, - bufx4 + 0 * (PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_ADDR_BYTES), - bufx4 + 1 * (PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_ADDR_BYTES), - bufx4 + 2 * (PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_ADDR_BYTES), - bufx4 + 3 * (PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_ADDR_BYTES), PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_ADDR_BYTES); - - /* Avoid unused parameter warning */ - (void)state_seeded; -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_avx2/hash_state.h b/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_avx2/hash_state.h deleted file mode 100644 index a4d6ea2c8d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_avx2/hash_state.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_HASH_STATE_H -#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_HASH_STATE_H - -/** - * Defines the type of the hash function state. - * - * Don't be fooled into thinking this instance of SPHINCS+ isn't stateless! - * - * From Section 7.2.2 from the SPHINCS+ round-2 specification: - * - * Each of the instances of the tweakable hash function take PK.seed as its - * first input, which is constant for a given key pair – and, thus, across - * a single signature. This leads to a lot of redundant computation. To remedy - * this, we pad PK.seed to the length of a full 64-byte SHA-256 input block. - * Because of the Merkle-Damgård construction that underlies SHA-256, this - * allows for reuse of the intermediate SHA-256 state after the initial call to - * the compression function which improves performance. - * - * We pass this hash state around in functions, because otherwise we need to - * have a global variable. - * - * SHAKE256 does not need this state. Because this implementation is generated - * from a shared code base, we still need to specify some hash_state as it is - * still passed around. We chose to use an `int` as a placeholder for this - * purpose. - */ - -typedef int hash_state; - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_avx2/hashx4.h b/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_avx2/hashx4.h deleted file mode 100644 index cf28794fb3..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_avx2/hashx4.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_HASHX4_H -#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_HASHX4_H - -#include - -#include "hash_state.h" - -void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_prf_addrx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const unsigned char *key, - const uint32_t addrx4[4 * 8], - const hash_state *state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_avx2/params.h b/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_avx2/params.h deleted file mode 100644 index 49650dc989..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_avx2/params.h +++ /dev/null @@ -1,53 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_PARAMS_H -#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_PARAMS_H - -/* Hash output length in bytes. */ -#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N 24 -/* Height of the hypertree. */ -#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_FULL_HEIGHT 66 -/* Number of subtree layer. */ -#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_D 22 -/* FORS tree dimensions. */ -#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_FORS_HEIGHT 8 -#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_FORS_TREES 33 -/* Winternitz parameter, */ -#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_WOTS_W 16 - -/* The hash function is defined by linking a different hash.c file, as opposed - to setting a #define constant. */ - -/* For clarity */ -#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_ADDR_BYTES 32 - -/* WOTS parameters. */ -#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_WOTS_LOGW 4 - -#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_WOTS_LEN1 (8 * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N / PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_WOTS_LOGW) - -/* PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_WOTS_LEN2 3 - -#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_WOTS_LEN (PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_WOTS_LEN1 + PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_WOTS_LEN2) -#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_WOTS_BYTES (PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_WOTS_LEN * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N) -#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_WOTS_PK_BYTES PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_WOTS_BYTES - -/* Subtree size. */ -#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_TREE_HEIGHT (PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_FULL_HEIGHT / PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_D) - -/* FORS parameters. */ -#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_FORS_MSG_BYTES ((PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_FORS_TREES + 7) / 8) -#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_FORS_BYTES ((PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_FORS_HEIGHT + 1) * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_FORS_TREES * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N) -#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_FORS_PK_BYTES PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N - -/* Resulting SPX sizes. */ -#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_BYTES (PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_FORS_BYTES + PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_D * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_WOTS_BYTES +\ - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_FULL_HEIGHT * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N) -#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_PK_BYTES (2 * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N) -#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_SK_BYTES (2 * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_PK_BYTES) - -/* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ -#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_OPTRAND_BYTES 32 - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_avx2/sign.c b/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_avx2/sign.c deleted file mode 100644 index 6f9f92e9f1..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_avx2/sign.c +++ /dev/null @@ -1,409 +0,0 @@ -#include -#include -#include -#include - -#include "address.h" -#include "api.h" -#include "fors.h" -#include "hash.h" -#include "hash_state.h" -#include "params.h" -#include "randombytes.h" -#include "thash.h" -#include "utils.h" -#include "wots.h" - - -/** - * Computes the leaf at a given address. First generates the WOTS key pair, - * then computes leaf by hashing horizontally. - */ -static void wots_gen_leaf(unsigned char *leaf, const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx, const uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - unsigned char pk[PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_WOTS_BYTES]; - uint32_t wots_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_set_type( - wots_addr, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_set_type( - wots_pk_addr, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_ADDR_TYPE_WOTSPK); - - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_set_keypair_addr( - wots_addr, addr_idx); - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_wots_gen_pk( - pk, sk_seed, pub_seed, wots_addr, hash_state_seeded); - - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_copy_keypair_addr( - wots_pk_addr, wots_addr); - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_thash_WOTS_LEN( - leaf, pk, pub_seed, wots_pk_addr, hash_state_seeded); -} - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_crypto_sign_secretkeybytes(void) { - return PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_CRYPTO_SECRETKEYBYTES; -} - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_crypto_sign_publickeybytes(void) { - return PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_CRYPTO_PUBLICKEYBYTES; -} - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_crypto_sign_bytes(void) { - return PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_CRYPTO_BYTES; -} - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_crypto_sign_seedbytes(void) { - return PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_CRYPTO_SEEDBYTES; -} - -/* - * Generates an SPX key pair given a seed of length - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed) { - /* We do not need the auth path in key generation, but it simplifies the - code to have just one treehash routine that computes both root and path - in one function. */ - unsigned char auth_path[PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_TREE_HEIGHT * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N]; - uint32_t top_tree_addr[8] = {0}; - hash_state hash_state_seeded; - - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_set_layer_addr( - top_tree_addr, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_D - 1); - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_set_type( - top_tree_addr, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_ADDR_TYPE_HASHTREE); - - /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ - memcpy(sk, seed, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_CRYPTO_SEEDBYTES); - - memcpy(pk, sk + 2 * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_initialize_hash_function(&hash_state_seeded, pk, sk); - - /* Compute root node of the top-most subtree. */ - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_treehash_TREE_HEIGHT( - sk + 3 * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N, auth_path, sk, sk + 2 * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N, 0, 0, - wots_gen_leaf, top_tree_addr, &hash_state_seeded); - - memcpy(pk + PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N, sk + 3 * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N); - - return 0; -} - -/* - * Generates an SPX key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk) { - - // guarantee alignment of pk - union { - __m128 _x[PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_CRYPTO_PUBLICKEYBYTES / 16]; - uint8_t pk[PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_CRYPTO_PUBLICKEYBYTES]; - } aligned_pk; - - // guarantee alignment of sk - union { - __m128 _x[PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_CRYPTO_SECRETKEYBYTES / 16]; - uint8_t sk[PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_CRYPTO_SECRETKEYBYTES]; - } aligned_sk; - - union { - __m128 _x[PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_CRYPTO_SEEDBYTES / 16]; - uint8_t seed[PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_CRYPTO_SEEDBYTES]; - } aligned_seed; - randombytes(aligned_seed.seed, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_CRYPTO_SEEDBYTES); - - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_crypto_sign_seed_keypair( - aligned_pk.pk, aligned_sk.sk, aligned_seed.seed); - memcpy(pk, aligned_pk.pk, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_CRYPTO_PUBLICKEYBYTES); - memcpy(sk, aligned_sk.sk, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_CRYPTO_SECRETKEYBYTES); - - return 0; -} - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - // guarantee alignment of sk - union { - __m128 *_x; - uint8_t sk[PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_CRYPTO_SECRETKEYBYTES]; - } aligned_sk; - memcpy(aligned_sk.sk, sk, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_CRYPTO_SECRETKEYBYTES); - sk = aligned_sk.sk; - - // guarantee alignment of sig - union { - __m128 *_x; - uint8_t sig[PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_BYTES]; - } aligned_sig; - uint8_t *orig_sig = sig; - sig = (uint8_t *)aligned_sig.sig; - - const unsigned char *sk_seed = sk; - const unsigned char *sk_prf = sk + PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N; - const unsigned char *pk = sk + 2 * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N; - const unsigned char *pub_seed = pk; - - unsigned char optrand[PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N]; - unsigned char mhash[PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_FORS_MSG_BYTES]; - unsigned char root[PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N]; - uint32_t i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - - hash_state hash_state_seeded; - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_initialize_hash_function( - &hash_state_seeded, - pub_seed, sk_seed); - - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_set_type( - wots_addr, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_set_type( - tree_addr, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_ADDR_TYPE_HASHTREE); - - /* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ - randombytes(optrand, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N); - /* Compute the digest randomization value. */ - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_gen_message_random( - sig, sk_prf, optrand, m, mlen, &hash_state_seeded); - - /* Derive the message digest and leaf index from R, PK and M. */ - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N; - - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_set_keypair_addr( - wots_addr, idx_leaf); - - /* Sign the message hash using FORS. */ - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_fors_sign( - sig, root, mhash, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_FORS_BYTES; - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_D; i++) { - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_set_tree_addr(tree_addr, tree); - - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_set_keypair_addr( - wots_addr, idx_leaf); - - /* Compute a WOTS signature. */ - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_wots_sign( - sig, root, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_WOTS_BYTES; - - /* Compute the authentication path for the used WOTS leaf. */ - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_treehash_TREE_HEIGHT( - root, sig, sk_seed, pub_seed, idx_leaf, 0, - wots_gen_leaf, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_TREE_HEIGHT * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_TREE_HEIGHT; - } - - memcpy(orig_sig, aligned_sig.sig, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_BYTES); - *siglen = PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_BYTES; - - return 0; -} - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk) { - // guarantee alignment of pk - union { - __m128 *_x; - uint8_t pk[PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_CRYPTO_PUBLICKEYBYTES]; - } aligned_pk; - memcpy(aligned_pk.pk, pk, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_CRYPTO_PUBLICKEYBYTES); - pk = aligned_pk.pk; - - const unsigned char *pub_seed = pk; - const unsigned char *pub_root = pk + PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N; - unsigned char mhash[PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_FORS_MSG_BYTES]; - unsigned char wots_pk[PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_WOTS_BYTES]; - unsigned char root[PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N]; - unsigned char leaf[PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N]; - unsigned int i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - hash_state hash_state_seeded; - - if (siglen != PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_BYTES) { - return -1; - } - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_initialize_hash_function( - &hash_state_seeded, - pub_seed, NULL); - - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_set_type( - wots_addr, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_set_type( - tree_addr, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_ADDR_TYPE_HASHTREE); - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_set_type( - wots_pk_addr, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_ADDR_TYPE_WOTSPK); - - /* Derive the message digest and leaf index from R || PK || M. */ - /* The additional PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N is a result of the hash domain separator. */ - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N; - - /* Layer correctly defaults to 0, so no need to set_layer_addr */ - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_set_keypair_addr( - wots_addr, idx_leaf); - - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_fors_pk_from_sig( - root, sig, mhash, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_FORS_BYTES; - - /* For each subtree.. */ - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_D; i++) { - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_set_tree_addr(tree_addr, tree); - - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_set_keypair_addr( - wots_addr, idx_leaf); - - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_copy_keypair_addr( - wots_pk_addr, wots_addr); - - /* The WOTS public key is only correct if the signature was correct. */ - /* Initially, root is the FORS pk, but on subsequent iterations it is - the root of the subtree below the currently processed subtree. */ - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_wots_pk_from_sig( - wots_pk, sig, root, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_WOTS_BYTES; - - /* Compute the leaf node using the WOTS public key. */ - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_thash_WOTS_LEN( - leaf, wots_pk, pub_seed, wots_pk_addr, &hash_state_seeded); - - /* Compute the root node of this subtree. */ - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_compute_root( - root, leaf, idx_leaf, 0, sig, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_TREE_HEIGHT, - pub_seed, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_TREE_HEIGHT * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_TREE_HEIGHT; - } - - /* Check if the root node equals the root node in the public key. */ - if (memcmp(root, pub_root, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N) != 0) { - return -1; - } - - return 0; -} - - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - size_t siglen; - - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_crypto_sign_signature( - sm, &siglen, m, mlen, sk); - - memmove(sm + PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_BYTES, m, mlen); - *smlen = siglen + mlen; - - return 0; -} - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk) { - - // guarantee alignment of pk - union { - __m128 *_x; - uint8_t pk[PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_CRYPTO_PUBLICKEYBYTES]; - } aligned_pk; - memcpy(aligned_pk.pk, pk, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_CRYPTO_PUBLICKEYBYTES); - pk = aligned_pk.pk; - - - /* The API caller does not necessarily know what size a signature should be - but SPHINCS+ signatures are always exactly PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_BYTES. */ - if (smlen < PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_BYTES) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - *mlen = smlen - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_BYTES; - - if (PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_crypto_sign_verify( - sm, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_BYTES, sm + PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_BYTES, *mlen, pk)) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - /* If verification was successful, move the message to the right place. */ - memmove(m, sm + PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_BYTES, *mlen); - - return 0; -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_avx2/thash.h b/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_avx2/thash.h deleted file mode 100644 index 725affa3f5..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_avx2/thash.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_THASH_H -#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_THASH_H - -#include "hash_state.h" - -#include - -void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_avx2/thash_shake256_simple.c b/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_avx2/thash_shake256_simple.c deleted file mode 100644 index 11ae958b14..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_avx2/thash_shake256_simple.c +++ /dev/null @@ -1,74 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash_state.h" -#include "params.h" -#include "thash.h" - -#include "fips202.h" - -/** - * Takes an array of inblocks concatenated arrays of PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N bytes. - */ -static void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_thash( - unsigned char *out, unsigned char *buf, - const unsigned char *in, unsigned int inblocks, - const unsigned char *pub_seed, uint32_t addr[8]) { - - memcpy(buf, pub_seed, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N); - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_addr_to_bytes(buf + PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N, addr); - memcpy(buf + PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_ADDR_BYTES, in, inblocks * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N); - - shake256(out, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N, buf, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N); -} - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_ADDR_BYTES + 1 * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N]; - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_thash( - out, buf, in, 1, pub_seed, addr); - - (void)hash_state_seeded; /* Avoid unused parameter warning. */ -} - -void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_ADDR_BYTES + 2 * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N]; - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_thash( - out, buf, in, 2, pub_seed, addr); - - (void)hash_state_seeded; /* Avoid unused parameter warning. */ -} - -void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_ADDR_BYTES + PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_WOTS_LEN * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N]; - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_thash( - out, buf, in, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_WOTS_LEN, pub_seed, addr); - - (void)hash_state_seeded; /* Avoid unused parameter warning. */ -} - -void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_ADDR_BYTES + PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_FORS_TREES * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N]; - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_thash( - out, buf, in, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_FORS_TREES, pub_seed, addr); - - (void)hash_state_seeded; /* Avoid unused parameter warning. */ -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_avx2/thash_shake256_simplex4.c b/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_avx2/thash_shake256_simplex4.c deleted file mode 100644 index 0649592d6c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_avx2/thash_shake256_simplex4.c +++ /dev/null @@ -1,47 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "thashx4.h" - -#include "fips202x4.h" - -/** - * 4-way parallel version of thash; takes 4x as much input and output - */ -#define thashx4_variant(name, inblocks) \ - void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_thashx4_##name( \ - unsigned char *out0, unsigned char *out1, unsigned char *out2, unsigned char *out3, \ - const unsigned char *in0, const unsigned char *in1, const unsigned char *in2, \ - const unsigned char *in3, const unsigned char *pub_seed, uint32_t addrx4[4 * 8], \ - const hash_state *state_seeded) { \ - unsigned char buf0[PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_ADDR_BYTES + (inblocks)*PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N]; \ - unsigned char buf1[PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_ADDR_BYTES + (inblocks)*PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N]; \ - unsigned char buf2[PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_ADDR_BYTES + (inblocks)*PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N]; \ - unsigned char buf3[PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_ADDR_BYTES + (inblocks)*PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N]; \ - \ - memcpy(buf0, pub_seed, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N); \ - memcpy(buf1, pub_seed, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N); \ - memcpy(buf2, pub_seed, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N); \ - memcpy(buf3, pub_seed, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N); \ - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_addr_to_bytes(buf0 + PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N, addrx4 + 0 * 8); \ - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_addr_to_bytes(buf1 + PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N, addrx4 + 1 * 8); \ - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_addr_to_bytes(buf2 + PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N, addrx4 + 2 * 8); \ - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_addr_to_bytes(buf3 + PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N, addrx4 + 3 * 8); \ - memcpy(buf0 + PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_ADDR_BYTES, in0, (inblocks)*PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N); \ - memcpy(buf1 + PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_ADDR_BYTES, in1, (inblocks)*PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N); \ - memcpy(buf2 + PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_ADDR_BYTES, in2, (inblocks)*PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N); \ - memcpy(buf3 + PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_ADDR_BYTES, in3, (inblocks)*PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N); \ - \ - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_shake256x4(out0, out1, out2, out3, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N, buf0, buf1, buf2, buf3, \ - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_ADDR_BYTES + (inblocks)*PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N); \ - \ - /* Avoid unused parameter warning */ \ - (void)state_seeded; \ - } - -thashx4_variant(1, 1) -thashx4_variant(2, 2) -thashx4_variant(WOTS_LEN, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_WOTS_LEN) -thashx4_variant(FORS_TREES, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_FORS_TREES) diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_avx2/thashx4.h b/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_avx2/thashx4.h deleted file mode 100644 index 87f6d3ebb5..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_avx2/thashx4.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_THASHX4_H -#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_THASHX4_H - -#include - -#include "hash_state.h" - -#define thashx4_header(inblocks) \ - void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_thashx4_##inblocks(unsigned char *out0, \ - unsigned char *out1, \ - unsigned char *out2, \ - unsigned char *out3, \ - const unsigned char *in0, \ - const unsigned char *in1, \ - const unsigned char *in2, \ - const unsigned char *in3, \ - const unsigned char *pub_seed, uint32_t addrx4[4*8], \ - const hash_state *state_seeded) - -thashx4_header(1); -thashx4_header(2); -thashx4_header(WOTS_LEN); -thashx4_header(FORS_TREES); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_avx2/utils.c b/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_avx2/utils.c deleted file mode 100644 index b2d823a51d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_avx2/utils.c +++ /dev/null @@ -1,199 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "hash_state.h" -#include "params.h" -#include "thash.h" -#include "utils.h" - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in) { - - /* Iterate over out in decreasing order, for big-endianness. */ - for (size_t i = outlen; i > 0; i--) { - out[i - 1] = in & 0xff; - in = in >> 8; - } -} - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_bytes_to_ull( - const unsigned char *in, size_t inlen) { - unsigned long long retval = 0; - - for (size_t i = 0; i < inlen; i++) { - retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); - } - return retval; -} - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - uint32_t i; - unsigned char buffer[2 * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N]; - - /* If leaf_idx is odd (last bit = 1), current path element is a right child - and auth_path has to go left. Otherwise it is the other way around. */ - if (leaf_idx & 1) { - memcpy(buffer + PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N, leaf, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N); - } else { - memcpy(buffer, leaf, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N); - memcpy(buffer + PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N, auth_path, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N); - } - auth_path += PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N; - - for (i = 0; i < tree_height - 1; i++) { - leaf_idx >>= 1; - idx_offset >>= 1; - /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_set_tree_height(addr, i + 1); - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_set_tree_index( - addr, leaf_idx + idx_offset); - - /* Pick the right or left neighbor, depending on parity of the node. */ - if (leaf_idx & 1) { - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_thash_2( - buffer + PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N); - } else { - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_thash_2( - buffer, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer + PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N, auth_path, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N); - } - auth_path += PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N; - } - - /* The last iteration is exceptional; we do not copy an auth_path node. */ - leaf_idx >>= 1; - idx_offset >>= 1; - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_set_tree_height(addr, tree_height); - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_set_tree_index( - addr, leaf_idx + idx_offset); - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_thash_2( - root, buffer, pub_seed, addr, hash_state_seeded); -} - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -static void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_treehash( - unsigned char *root, unsigned char *auth_path, - unsigned char *stack, unsigned int *heights, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - - unsigned int offset = 0; - uint32_t idx; - uint32_t tree_idx; - - for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { - /* Add the next leaf node to the stack. */ - gen_leaf(stack + offset * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N, - sk_seed, pub_seed, idx + idx_offset, tree_addr, - hash_state_seeded); - offset++; - heights[offset - 1] = 0; - - /* If this is a node we need for the auth path.. */ - if ((leaf_idx ^ 0x1) == idx) { - memcpy(auth_path, stack + (offset - 1)*PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N); - } - - /* While the top-most nodes are of equal height.. */ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { - /* Compute index of the new node, in the next layer. */ - tree_idx = (idx >> (heights[offset - 1] + 1)); - - /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_set_tree_height( - tree_addr, heights[offset - 1] + 1); - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_set_tree_index( - tree_addr, tree_idx + (idx_offset >> (heights[offset - 1] + 1))); - /* Hash the top-most nodes from the stack together. */ - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_thash_2( - stack + (offset - 2)*PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N, stack + (offset - 2)*PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N, - pub_seed, tree_addr, hash_state_seeded); - offset--; - /* Note that the top-most node is now one layer higher. */ - heights[offset - 1]++; - - /* If this is a node we need for the auth path.. */ - if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_path + heights[offset - 1]*PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N, - stack + (offset - 1)*PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N); - } - } - } - memcpy(root, stack, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N); -} - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_FORS_HEIGHT + 1)*PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N]; - unsigned int heights[PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_FORS_HEIGHT + 1]; - - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_FORS_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_TREE_HEIGHT + 1)*PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N]; - unsigned int heights[PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_TREE_HEIGHT + 1]; - - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_TREE_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_avx2/utils.h b/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_avx2/utils.h deleted file mode 100644 index 77d4f9f4ee..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_avx2/utils.h +++ /dev/null @@ -1,64 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_UTILS_H -#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_UTILS_H - -#include "hash_state.h" -#include "params.h" -#include -#include - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in); - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_bytes_to_ull( - const unsigned char *in, size_t inlen); - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_avx2/utilsx4.c b/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_avx2/utilsx4.c deleted file mode 100644 index e8850f4a4e..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_avx2/utilsx4.c +++ /dev/null @@ -1,98 +0,0 @@ -#include "address.h" -#include "params.h" -#include "thashx4.h" -#include "utils.h" -#include "utilsx4.h" - -#include - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -#define treehashx4_variant(name, tree_height) \ - void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_treehashx4_##name( \ - unsigned char *rootx4, unsigned char *auth_pathx4, const unsigned char *sk_seed, \ - const unsigned char *pub_seed, const uint32_t leaf_idx[4], uint32_t idx_offset[4], \ - void (*gen_leafx4)(unsigned char * /* leaf0 */, unsigned char * /* leaf1 */, \ - unsigned char * /* leaf2 */, unsigned char * /* leaf3 */, \ - const unsigned char * /* sk_seed */, \ - const unsigned char * /* pub_seed */, uint32_t /* addr_idx0 */, \ - uint32_t /* addr_idx1 */, uint32_t /* addr_idx2 */, \ - uint32_t /* addr_idx3 */, const uint32_t[8] /* tree_addr */, \ - const hash_state * /* state_seeded */), \ - uint32_t tree_addrx4[4 * 8], const hash_state *state_seeded) { \ - unsigned char stackx4[4 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N]; \ - unsigned int heights[(tree_height) + 1]; \ - unsigned int offset = 0; \ - uint32_t idx; \ - uint32_t tree_idx; \ - unsigned int j; \ - \ - for (idx = 0; idx < (uint32_t)(1 << (tree_height)); idx++) { \ - /* Add the next leaf node to the stack. */ \ - gen_leafx4(stackx4 + 0 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N + offset * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N, \ - stackx4 + 1 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N + offset * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N, \ - stackx4 + 2 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N + offset * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N, \ - stackx4 + 3 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N + offset * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N, sk_seed, \ - pub_seed, idx + idx_offset[0], idx + idx_offset[1], idx + idx_offset[2], \ - idx + idx_offset[3], tree_addrx4, state_seeded); \ - offset++; \ - heights[offset - 1] = 0; \ - \ - /* If this is a node we need for the auth path.. */ \ - for (j = 0; j < 4; j++) { \ - if ((leaf_idx[j] ^ 0x1) == idx) { \ - memcpy(auth_pathx4 + j * (tree_height)*PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N, \ - stackx4 + j * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N + (offset - 1) * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N, \ - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N); \ - } \ - } \ - \ - /* While the top-most nodes are of equal height.. */ \ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { \ - /* Compute index of the new node, in the next layer. */ \ - tree_idx = (idx >> (heights[offset - 1] + 1)); \ - \ - /* Set the address of the node we're creating. */ \ - for (j = 0; j < 4; j++) { \ - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_set_tree_height(tree_addrx4 + j * 8, heights[offset - 1] + 1); \ - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_set_tree_index(tree_addrx4 + j * 8, \ - tree_idx + (idx_offset[j] >> (heights[offset - 1] + 1))); \ - } \ - /* Hash the top-most nodes from the stack together. */ \ - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_thashx4_2(stackx4 + 0 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N + (offset - 2) * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N, \ - stackx4 + 1 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N + (offset - 2) * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N, \ - stackx4 + 2 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N + (offset - 2) * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N, \ - stackx4 + 3 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N + (offset - 2) * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N, \ - stackx4 + 0 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N + (offset - 2) * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N, \ - stackx4 + 1 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N + (offset - 2) * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N, \ - stackx4 + 2 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N + (offset - 2) * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N, \ - stackx4 + 3 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N + (offset - 2) * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N, \ - pub_seed, tree_addrx4, state_seeded); \ - offset--; \ - /* Note that the top-most node is now one layer higher. */ \ - heights[offset - 1]++; \ - \ - /* If this is a node we need for the auth path.. */ \ - for (j = 0; j < 4; j++) { \ - if (((leaf_idx[j] >> heights[offset - 1]) ^ 0x1) == tree_idx) { \ - memcpy(auth_pathx4 + j * (tree_height)*PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N + \ - heights[offset - 1] * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N, \ - stackx4 + j * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N + (offset - 1) * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N, \ - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N); \ - } \ - } \ - } \ - } \ - \ - for (j = 0; j < 4; j++) { \ - memcpy(rootx4 + j * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N, stackx4 + j * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N); \ - } \ - } - -treehashx4_variant(FORS_HEIGHT, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_FORS_HEIGHT) diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_avx2/utilsx4.h b/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_avx2/utilsx4.h deleted file mode 100644 index ef7b52028e..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_avx2/utilsx4.h +++ /dev/null @@ -1,38 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_UTILSX4_H -#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_UTILSX4_H - -#include "hash_state.h" -#include "params.h" - -#include - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_treehashx4_FORS_HEIGHT(unsigned char *rootx4, - unsigned char *auth_pathx4, - const unsigned char *sk_seed, - const unsigned char *pub_seed, - const uint32_t leaf_idx[4], - uint32_t idx_offset[4], - void (*gen_leafx4)(unsigned char * /* leaf0 */, - unsigned char * /* leaf1 */, - unsigned char * /* leaf2 */, - unsigned char * /* leaf3 */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx0 */, - uint32_t /* addr_idx1 */, - uint32_t /* addr_idx2 */, - uint32_t /* addr_idx3 */, - const uint32_t[8] /* tree_addr */, - const hash_state * /* state_seeded */), - uint32_t tree_addrx4[4 * 8], - const hash_state *state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_avx2/wots.c b/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_avx2/wots.c deleted file mode 100644 index f53be13309..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_avx2/wots.c +++ /dev/null @@ -1,240 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "hash_state.h" -#include "hashx4.h" -#include "params.h" -#include "thash.h" -#include "thashx4.h" -#include "utils.h" -#include "wots.h" - -// TODO clarify address expectations, and make them more uniform. -// TODO i.e. do we expect types to be set already? -// TODO and do we expect modifications or copies? - -/** - * Computes the starting value for a chain, i.e. the secret key. - * Expects the address to be complete up to the chain address. - */ -static void wots_gen_sk(unsigned char *sk, const unsigned char *sk_seed, - uint32_t wots_addr[8], const hash_state *state_seeded) { - /* Make sure that the hash address is actually zeroed. */ - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_set_hash_addr(wots_addr, 0); - - /* Generate sk element. */ - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_prf_addr(sk, sk_seed, wots_addr, state_seeded); -} - -/** - * 4-way parallel version of wots_gen_sk; expects 4x as much space in sk - */ -static void wots_gen_skx4(unsigned char *skx4, const unsigned char *sk_seed, - uint32_t wots_addrx4[4 * 8], const hash_state *state_seeded) { - unsigned int j; - - /* Make sure that the hash address is actually zeroed. */ - for (j = 0; j < 4; j++) { - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_set_hash_addr(wots_addrx4 + j * 8, 0); - } - - /* Generate sk element. */ - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_prf_addrx4(skx4 + 0 * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N, - skx4 + 1 * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N, - skx4 + 2 * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N, - skx4 + 3 * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N, - sk_seed, wots_addrx4, - state_seeded); -} - -/** - * Computes the chaining function. - * out and in have to be n-byte arrays. - * - * Interprets in as start-th value of the chain. - * addr has to contain the address of the chain. - */ -static void gen_chain(unsigned char *out, const unsigned char *in, - unsigned int start, unsigned int steps, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *state_seeded) { - uint32_t i; - - /* Initialize out with the value at position 'start'. */ - memcpy(out, in, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N); - - /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_WOTS_W; i++) { - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_set_hash_addr(addr, i); - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_thash_1(out, out, pub_seed, addr, state_seeded); - } -} - -/** - * 4-way parallel version of gen_chain; expects 4x as much space in out, and - * 4x as much space in inx4. Assumes start and step identical across chains. - */ -static void gen_chainx4(unsigned char *outx4, const unsigned char *inx4, - unsigned int start, unsigned int steps, - const unsigned char *pub_seed, uint32_t addrx4[4 * 8], - const hash_state *state_seeded) { - uint32_t i; - unsigned int j; - - /* Initialize outx4 with the value at position 'start'. */ - memcpy(outx4, inx4, 4 * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N); - - /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_WOTS_W; i++) { - for (j = 0; j < 4; j++) { - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_set_hash_addr(addrx4 + j * 8, i); - } - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_thashx4_1(outx4 + 0 * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N, - outx4 + 1 * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N, - outx4 + 2 * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N, - outx4 + 3 * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N, - outx4 + 0 * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N, - outx4 + 1 * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N, - outx4 + 2 * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N, - outx4 + 3 * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N, - pub_seed, addrx4, - state_seeded); - } -} - -/** - * base_w algorithm as described in draft. - * Interprets an array of bytes as integers in base w. - * This only works when log_w is a divisor of 8. - */ -static void base_w(unsigned int *output, const int out_len, const unsigned char *input) { - int in = 0; - int out = 0; - unsigned char total = 0; - int bits = 0; - int consumed; - - for (consumed = 0; consumed < out_len; consumed++) { - if (bits == 0) { - total = input[in]; - in++; - bits += 8; - } - bits -= PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_WOTS_LOGW; - output[out] = (unsigned int)(total >> bits) & (PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_WOTS_W - 1); - out++; - } -} - -/* Computes the WOTS+ checksum over a message (in base_w). */ -static void wots_checksum(unsigned int *csum_base_w, const unsigned int *msg_base_w) { - unsigned int csum = 0; - unsigned char csum_bytes[(PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_WOTS_LEN2 * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_WOTS_LOGW + 7) / 8]; - unsigned int i; - - /* Compute checksum. */ - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_WOTS_LEN1; i++) { - csum += PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_WOTS_W - 1 - msg_base_w[i]; - } - - /* Convert checksum to base_w. */ - /* Make sure expected empty zero bits are the least significant bits. */ - csum = csum << (8 - ((PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_WOTS_LEN2 * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_WOTS_LOGW) % 8)); - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); - base_w(csum_base_w, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_WOTS_LEN2, csum_bytes); -} - -/* Takes a message and derives the matching chain lengths. */ -static void chain_lengths(unsigned int *lengths, const unsigned char *msg) { - base_w(lengths, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_WOTS_LEN1, msg); - wots_checksum(lengths + PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_WOTS_LEN1, lengths); -} - -/** - * WOTS key generation. Takes a 32 byte sk_seed, expands it to WOTS private key - * elements and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_wots_gen_pk(unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *state_seeded) { - uint32_t i; - unsigned int j; - - uint32_t addrx4[4 * 8]; - unsigned char pkbuf[4 * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N]; - - for (j = 0; j < 4; j++) { - memcpy(addrx4 + j * 8, addr, sizeof(uint32_t) * 8); - } - - /* The last iteration typically does not have complete set of 4 chains, - but because we use pkbuf, this is not an issue -- we still do as many - in parallel as possible. */ - for (i = 0; i < ((PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_WOTS_LEN + 3) & ~0x3); i += 4) { - for (j = 0; j < 4; j++) { - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_set_chain_addr(addrx4 + j * 8, i + j); - } - wots_gen_skx4(pkbuf, sk_seed, addrx4, state_seeded); - gen_chainx4(pkbuf, pkbuf, 0, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_WOTS_W - 1, pub_seed, addrx4, state_seeded); - for (j = 0; j < 4; j++) { - if (i + j < PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_WOTS_LEN) { - memcpy(pk + (i + j)*PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N, pkbuf + j * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N); - } - } - } - - // Get rid of unused argument variable. - (void)state_seeded; -} - -/** - * Takes a n-byte message and the 32-byte sk_see to compute a signature 'sig'. - */ -void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_wots_sign(unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_WOTS_LEN; i++) { - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_set_chain_addr(addr, i); - wots_gen_sk(sig + i * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N, sk_seed, addr, state_seeded); - gen_chain(sig + i * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N, sig + i * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N, 0, lengths[i], pub_seed, addr, state_seeded); - } - - // avoid unused argument - (void)state_seeded; -} - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_WOTS_LEN; i++) { - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_set_chain_addr(addr, i); - gen_chain(pk + i * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N, sig + i * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_N, - lengths[i], PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_WOTS_W - 1 - lengths[i], pub_seed, addr, - state_seeded); - } - - // avoid unused argument - (void)state_seeded; -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_avx2/wots.h b/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_avx2/wots.h deleted file mode 100644 index 3433af1178..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_avx2/wots.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_WOTS_H -#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_WOTS_H - -#include "hash_state.h" -#include "params.h" -#include - -/** - * WOTS key generation. Takes a 32 byte seed for the private key, expands it to - * a full WOTS private key and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_wots_gen_pk( - unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -/** - * Takes a n-byte message and the 32-byte seed for the private key to compute a - * signature that is placed at 'sig'. - */ -void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_wots_sign( - unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *hash_state_seeded); - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_wots_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/LICENSE b/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/LICENSE deleted file mode 100644 index 670154e353..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/LICENSE +++ /dev/null @@ -1,116 +0,0 @@ -CC0 1.0 Universal - -Statement of Purpose - -The laws of most jurisdictions throughout the world automatically confer -exclusive Copyright and Related Rights (defined below) upon the creator and -subsequent owner(s) (each and all, an "owner") of an original work of -authorship and/or a database (each, a "Work"). - -Certain owners wish to permanently relinquish those rights to a Work for the -purpose of contributing to a commons of creative, cultural and scientific -works ("Commons") that the public can reliably and without fear of later -claims of infringement build upon, modify, incorporate in other works, reuse -and redistribute as freely as possible in any form whatsoever and for any -purposes, including without limitation commercial purposes. These owners may -contribute to the Commons to promote the ideal of a free culture and the -further production of creative, cultural and scientific works, or to gain -reputation or greater distribution for their Work in part through the use and -efforts of others. - -For these and/or other purposes and motivations, and without any expectation -of additional consideration or compensation, the person associating CC0 with a -Work (the "Affirmer"), to the extent that he or she is an owner of Copyright -and Related Rights in the Work, voluntarily elects to apply CC0 to the Work -and publicly distribute the Work under its terms, with knowledge of his or her -Copyright and Related Rights in the Work and the meaning and intended legal -effect of CC0 on those rights. - -1. Copyright and Related Rights. A Work made available under CC0 may be -protected by copyright and related or neighboring rights ("Copyright and -Related Rights"). Copyright and Related Rights include, but are not limited -to, the following: - - i. the right to reproduce, adapt, distribute, perform, display, communicate, - and translate a Work; - - ii. moral rights retained by the original author(s) and/or performer(s); - - iii. publicity and privacy rights pertaining to a person's image or likeness - depicted in a Work; - - iv. rights protecting against unfair competition in regards to a Work, - subject to the limitations in paragraph 4(a), below; - - v. rights protecting the extraction, dissemination, use and reuse of data in - a Work; - - vi. database rights (such as those arising under Directive 96/9/EC of the - European Parliament and of the Council of 11 March 1996 on the legal - protection of databases, and under any national implementation thereof, - including any amended or successor version of such directive); and - - vii. other similar, equivalent or corresponding rights throughout the world - based on applicable law or treaty, and any national implementations thereof. - -2. Waiver. To the greatest extent permitted by, but not in contravention of, -applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and -unconditionally waives, abandons, and surrenders all of Affirmer's Copyright -and Related Rights and associated claims and causes of action, whether now -known or unknown (including existing as well as future claims and causes of -action), in the Work (i) in all territories worldwide, (ii) for the maximum -duration provided by applicable law or treaty (including future time -extensions), (iii) in any current or future medium and for any number of -copies, and (iv) for any purpose whatsoever, including without limitation -commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes -the Waiver for the benefit of each member of the public at large and to the -detriment of Affirmer's heirs and successors, fully intending that such Waiver -shall not be subject to revocation, rescission, cancellation, termination, or -any other legal or equitable action to disrupt the quiet enjoyment of the Work -by the public as contemplated by Affirmer's express Statement of Purpose. - -3. Public License Fallback. Should any part of the Waiver for any reason be -judged legally invalid or ineffective under applicable law, then the Waiver -shall be preserved to the maximum extent permitted taking into account -Affirmer's express Statement of Purpose. In addition, to the extent the Waiver -is so judged Affirmer hereby grants to each affected person a royalty-free, -non transferable, non sublicensable, non exclusive, irrevocable and -unconditional license to exercise Affirmer's Copyright and Related Rights in -the Work (i) in all territories worldwide, (ii) for the maximum duration -provided by applicable law or treaty (including future time extensions), (iii) -in any current or future medium and for any number of copies, and (iv) for any -purpose whatsoever, including without limitation commercial, advertising or -promotional purposes (the "License"). The License shall be deemed effective as -of the date CC0 was applied by Affirmer to the Work. Should any part of the -License for any reason be judged legally invalid or ineffective under -applicable law, such partial invalidity or ineffectiveness shall not -invalidate the remainder of the License, and in such case Affirmer hereby -affirms that he or she will not (i) exercise any of his or her remaining -Copyright and Related Rights in the Work or (ii) assert any associated claims -and causes of action with respect to the Work, in either case contrary to -Affirmer's express Statement of Purpose. - -4. Limitations and Disclaimers. - - a. No trademark or patent rights held by Affirmer are waived, abandoned, - surrendered, licensed or otherwise affected by this document. - - b. Affirmer offers the Work as-is and makes no representations or warranties - of any kind concerning the Work, express, implied, statutory or otherwise, - including without limitation warranties of title, merchantability, fitness - for a particular purpose, non infringement, or the absence of latent or - other defects, accuracy, or the present or absence of errors, whether or not - discoverable, all to the greatest extent permissible under applicable law. - - c. Affirmer disclaims responsibility for clearing rights of other persons - that may apply to the Work or any use thereof, including without limitation - any person's Copyright and Related Rights in the Work. Further, Affirmer - disclaims responsibility for obtaining any necessary consents, permissions - or other rights required for any use of the Work. - - d. Affirmer understands and acknowledges that Creative Commons is not a - party to this document and has no duty or obligation with respect to this - CC0 or use of the Work. - -For more information, please see - diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/address.c b/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/address.c deleted file mode 100644 index cce899fe72..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/address.c +++ /dev/null @@ -1,78 +0,0 @@ -#include - -#include "address.h" -#include "params.h" -#include "utils.h" - -void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]) { - int i; - - for (i = 0; i < 8; i++) { - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_ull_to_bytes( - bytes + i * 4, 4, addr[i]); - } -} - -void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_set_layer_addr( - uint32_t addr[8], uint32_t layer) { - addr[0] = layer; -} - -void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_set_tree_addr( - uint32_t addr[8], uint64_t tree) { - addr[1] = 0; - addr[2] = (uint32_t) (tree >> 32); - addr[3] = (uint32_t) tree; -} - -void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_set_type( - uint32_t addr[8], uint32_t type) { - addr[4] = type; -} - -void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; -} - -/* These functions are used for OTS addresses. */ - -void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_set_keypair_addr( - uint32_t addr[8], uint32_t keypair) { - addr[5] = keypair; -} - -void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; - out[5] = in[5]; -} - -void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_set_chain_addr( - uint32_t addr[8], uint32_t chain) { - addr[6] = chain; -} - -void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_set_hash_addr( - uint32_t addr[8], uint32_t hash) { - addr[7] = hash; -} - -/* These functions are used for all hash tree addresses (including FORS). */ - -void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_set_tree_height( - uint32_t addr[8], uint32_t tree_height) { - addr[6] = tree_height; -} - -void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_set_tree_index( - uint32_t addr[8], uint32_t tree_index) { - addr[7] = tree_index; -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/address.h b/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/address.h deleted file mode 100644 index f57ffb75fa..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/address.h +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_ADDRESS_H -#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_ADDRESS_H - -#include - -#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_ADDR_TYPE_WOTS 0 -#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_ADDR_TYPE_WOTSPK 1 -#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_ADDR_TYPE_HASHTREE 2 -#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_ADDR_TYPE_FORSTREE 3 -#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_ADDR_TYPE_FORSPK 4 - -void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]); - -void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_set_layer_addr( - uint32_t addr[8], uint32_t layer); - -void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_set_tree_addr( - uint32_t addr[8], uint64_t tree); - -void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_set_type( - uint32_t addr[8], uint32_t type); - -/* Copies the layer and tree part of one address into the other */ -void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for WOTS and FORS addresses. */ - -void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_set_keypair_addr( - uint32_t addr[8], uint32_t keypair); - -void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_set_chain_addr( - uint32_t addr[8], uint32_t chain); - -void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_set_hash_addr( - uint32_t addr[8], uint32_t hash); - -void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for all hash tree addresses (including FORS). */ - -void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_set_tree_height( - uint32_t addr[8], uint32_t tree_height); - -void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_set_tree_index( - uint32_t addr[8], uint32_t tree_index); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/api.h b/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/api.h deleted file mode 100644 index 48e622dba7..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/api.h +++ /dev/null @@ -1,81 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_API_H -#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_API_H - -#include -#include - - - -#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_CRYPTO_ALGNAME "SPHINCS+" - -#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_CRYPTO_SECRETKEYBYTES 96 -#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_CRYPTO_PUBLICKEYBYTES 48 -#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_CRYPTO_BYTES 35664 -#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_CRYPTO_SEEDBYTES 72 - - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/fors.c b/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/fors.c deleted file mode 100644 index bc6f7f50c7..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/fors.c +++ /dev/null @@ -1,161 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "fors.h" -#include "hash.h" -#include "hash_state.h" -#include "thash.h" -#include "utils.h" - -static void fors_gen_sk(unsigned char *sk, const unsigned char *sk_seed, - uint32_t fors_leaf_addr[8], const hash_state *hash_state_seeded) { - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_prf_addr( - sk, sk_seed, fors_leaf_addr, hash_state_seeded); -} - -static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, - const unsigned char *pub_seed, - uint32_t fors_leaf_addr[8], - const hash_state *hash_state_seeded) { - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_thash_1( - leaf, sk, pub_seed, fors_leaf_addr, hash_state_seeded); -} - -static void fors_gen_leaf(unsigned char *leaf, const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx, const uint32_t fors_tree_addr[8], - const hash_state *hash_state_seeded) { - uint32_t fors_leaf_addr[8] = {0}; - - /* Only copy the parts that must be kept in fors_leaf_addr. */ - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_copy_keypair_addr( - fors_leaf_addr, fors_tree_addr); - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_set_type( - fors_leaf_addr, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_set_tree_index( - fors_leaf_addr, addr_idx); - - fors_gen_sk(leaf, sk_seed, fors_leaf_addr, hash_state_seeded); - fors_sk_to_leaf(leaf, leaf, pub_seed, fors_leaf_addr, hash_state_seeded); -} - -/** - * Interprets m as PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_FORS_HEIGHT-bit unsigned integers. - * Assumes m contains at least PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_FORS_TREES bits. - * Assumes indices has space for PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_FORS_TREES integers. - */ -static void message_to_indices(uint32_t *indices, const unsigned char *m) { - unsigned int i, j; - unsigned int offset = 0; - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_FORS_TREES; i++) { - indices[i] = 0; - for (j = 0; j < PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_FORS_HEIGHT; j++) { - indices[i] ^= (((uint32_t)m[offset >> 3] >> (offset & 0x7)) & 0x1) << j; - offset++; - } - } -} - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_fors_sign( - unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *hash_state_seeded) { - uint32_t indices[PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_FORS_TREES]; - unsigned char roots[PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_FORS_TREES * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N]; - uint32_t fors_tree_addr[8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_copy_keypair_addr( - fors_tree_addr, fors_addr); - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_copy_keypair_addr( - fors_pk_addr, fors_addr); - - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_set_type( - fors_tree_addr, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_set_type( - fors_pk_addr, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_FORS_TREES; i++) { - idx_offset = i * (1 << PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_FORS_HEIGHT); - - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_set_tree_height( - fors_tree_addr, 0); - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_set_tree_index( - fors_tree_addr, indices[i] + idx_offset); - - /* Include the secret key part that produces the selected leaf node. */ - fors_gen_sk(sig, sk_seed, fors_tree_addr, hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N; - - /* Compute the authentication path for this leaf node. */ - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_treehash_FORS_HEIGHT( - roots + i * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N, sig, sk_seed, pub_seed, - indices[i], idx_offset, fors_gen_leaf, fors_tree_addr, - hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_thash_FORS_TREES( - pk, roots, pub_seed, fors_pk_addr, hash_state_seeded); -} - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_fors_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, const uint32_t fors_addr[8], - const hash_state *hash_state_seeded) { - uint32_t indices[PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_FORS_TREES]; - unsigned char roots[PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_FORS_TREES * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N]; - unsigned char leaf[PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N]; - uint32_t fors_tree_addr[8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_copy_keypair_addr(fors_tree_addr, fors_addr); - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_copy_keypair_addr(fors_pk_addr, fors_addr); - - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_set_type(fors_tree_addr, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_set_type(fors_pk_addr, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_FORS_TREES; i++) { - idx_offset = i * (1 << PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_FORS_HEIGHT); - - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_set_tree_height(fors_tree_addr, 0); - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Derive the leaf from the included secret key part. */ - fors_sk_to_leaf(leaf, sig, pub_seed, fors_tree_addr, hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N; - - /* Derive the corresponding root node of this tree. */ - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_compute_root(roots + i * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N, leaf, indices[i], idx_offset, sig, - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_FORS_HEIGHT, pub_seed, fors_tree_addr, hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_thash_FORS_TREES(pk, roots, pub_seed, fors_pk_addr, hash_state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/fors.h b/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/fors.h deleted file mode 100644 index a2648beab2..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/fors.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_FORS_H -#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_FORS_H - -#include - -#include "hash_state.h" -#include "params.h" - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_fors_sign( - unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *hash_state_seeded); - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_fors_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, const uint32_t fors_addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/hash.h b/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/hash.h deleted file mode 100644 index bbd5ebdb3c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/hash.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_HASH_H -#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_HASH_H - -#include "hash_state.h" - -#include -#include - -void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_initialize_hash_function( - hash_state *hash_state_seeded, - const unsigned char *pub_seed, const unsigned char *sk_seed); - -void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_destroy_hash_function(hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/hash_shake256.c b/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/hash_shake256.c deleted file mode 100644 index 81d055a566..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/hash_shake256.c +++ /dev/null @@ -1,106 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "utils.h" - -#include "fips202.h" - -/* For SHAKE256, there is no immediate reason to initialize at the start, - so this function is an empty operation. */ -void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_initialize_hash_function( - hash_state *hash_state_seeded, // NOLINT(readability-non-const-parameter) - const unsigned char *pub_seed, const unsigned char *sk_seed) { - (void)hash_state_seeded; /* Suppress an 'unused parameter' warning. */ - (void)pub_seed; /* Suppress an 'unused parameter' warning. */ - (void)sk_seed; /* Suppress an 'unused parameter' warning. */ -} - -/* This is not necessary for SHAKE256, so we don't do anything */ -void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_destroy_hash_function( - hash_state *hash_state_seeded) { // NOLINT(readability-non-const-parameter) - (void)hash_state_seeded; -} - -/* - * Computes PRF(key, addr), given a secret key of PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N bytes and an address - */ -void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded) { - unsigned char buf[PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N + PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_ADDR_BYTES]; - - memcpy(buf, key, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N); - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_addr_to_bytes(buf + PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N, addr); - - shake256(out, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N, buf, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N + PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_ADDR_BYTES); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} - -/** - * Computes the message-dependent randomness R, using a secret seed and an - * optional randomization value as well as the message. - */ -void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded) { - shake256incctx state; - - shake256_inc_init(&state); - shake256_inc_absorb(&state, sk_prf, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N); - shake256_inc_absorb(&state, optrand, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N); - shake256_inc_absorb(&state, m, mlen); - shake256_inc_finalize(&state); - shake256_inc_squeeze(R, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N, &state); - shake256_inc_ctx_release(&state); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} - -/** - * Computes the message hash using R, the public key, and the message. - * Outputs the message digest and the index of the leaf. The index is split in - * the tree index and the leaf index, for convenient copying to an address. - */ -void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded) { -#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_TREE_BITS (PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_TREE_HEIGHT * (PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_D - 1)) -#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_TREE_BYTES ((PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_TREE_BITS + 7) / 8) -#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_LEAF_BITS PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_TREE_HEIGHT -#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_LEAF_BYTES ((PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_LEAF_BITS + 7) / 8) -#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_DGST_BYTES (PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_FORS_MSG_BYTES + PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_TREE_BYTES + PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_LEAF_BYTES) - - unsigned char buf[PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_DGST_BYTES]; - unsigned char *bufp = buf; - shake256incctx state; - - shake256_inc_init(&state); - shake256_inc_absorb(&state, R, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N); - shake256_inc_absorb(&state, pk, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_PK_BYTES); - shake256_inc_absorb(&state, m, mlen); - shake256_inc_finalize(&state); - shake256_inc_squeeze(buf, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_DGST_BYTES, &state); - shake256_inc_ctx_release(&state); - - memcpy(digest, bufp, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_FORS_MSG_BYTES); - bufp += PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_FORS_MSG_BYTES; - - *tree = PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_bytes_to_ull( - bufp, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_TREE_BYTES); - *tree &= (~(uint64_t)0) >> (64 - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_TREE_BITS); - bufp += PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_TREE_BYTES; - - *leaf_idx = (uint32_t)PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_bytes_to_ull( - bufp, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_LEAF_BYTES); - *leaf_idx &= (~(uint32_t)0) >> (32 - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_LEAF_BITS); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/hash_state.h b/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/hash_state.h deleted file mode 100644 index 7d92ef872a..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/hash_state.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef SPX_HASH_STATE_H -#define SPX_HASH_STATE_H - -/** - * Defines the type of the hash function state. - * - * Don't be fooled into thinking this instance of SPHINCS+ isn't stateless! - * - * From Section 7.2.2 from the SPHINCS+ round-2 specification: - * - * Each of the instances of the tweakable hash function take PK.seed as its - * first input, which is constant for a given key pair – and, thus, across - * a single signature. This leads to a lot of redundant computation. To remedy - * this, we pad PK.seed to the length of a full 64-byte SHA-256 input block. - * Because of the Merkle-Damgård construction that underlies SHA-256, this - * allows for reuse of the intermediate SHA-256 state after the initial call to - * the compression function which improves performance. - * - * We pass this hash state around in functions, because otherwise we need to - * have a global variable. - * - * SHAKE256 does not need this state. Because this implementation is generated - * from a shared code base, we still need to specify some hash_state as it is - * still passed around. We chose to use an `int` as a placeholder for this - * purpose. - */ - -#define hash_state int - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/params.h b/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/params.h deleted file mode 100644 index 292f83c4db..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/params.h +++ /dev/null @@ -1,53 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_PARAMS_H -#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_PARAMS_H - -/* Hash output length in bytes. */ -#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N 24 -/* Height of the hypertree. */ -#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_FULL_HEIGHT 66 -/* Number of subtree layer. */ -#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_D 22 -/* FORS tree dimensions. */ -#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_FORS_HEIGHT 8 -#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_FORS_TREES 33 -/* Winternitz parameter, */ -#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_WOTS_W 16 - -/* The hash function is defined by linking a different hash.c file, as opposed - to setting a #define constant. */ - -/* For clarity */ -#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_ADDR_BYTES 32 - -/* WOTS parameters. */ -#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_WOTS_LOGW 4 - -#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_WOTS_LEN1 (8 * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N / PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_WOTS_LOGW) - -/* PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_WOTS_LEN2 3 - -#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_WOTS_LEN (PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_WOTS_LEN1 + PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_WOTS_LEN2) -#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_WOTS_BYTES (PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_WOTS_LEN * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N) -#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_WOTS_PK_BYTES PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_WOTS_BYTES - -/* Subtree size. */ -#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_TREE_HEIGHT (PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_FULL_HEIGHT / PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_D) - -/* FORS parameters. */ -#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_FORS_MSG_BYTES ((PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_FORS_TREES + 7) / 8) -#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_FORS_BYTES ((PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_FORS_HEIGHT + 1) * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_FORS_TREES * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N) -#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_FORS_PK_BYTES PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N - -/* Resulting SPX sizes. */ -#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_BYTES (PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N + PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_FORS_BYTES + PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_D * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_WOTS_BYTES +\ - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_FULL_HEIGHT * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N) -#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_PK_BYTES (2 * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N) -#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_SK_BYTES (2 * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N + PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_PK_BYTES) - -/* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ -#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_OPTRAND_BYTES 32 - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/sign.c b/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/sign.c deleted file mode 100644 index 7efb32f90c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/sign.c +++ /dev/null @@ -1,356 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "api.h" -#include "fors.h" -#include "hash.h" -#include "hash_state.h" -#include "params.h" -#include "randombytes.h" -#include "thash.h" -#include "utils.h" -#include "wots.h" - -/** - * Computes the leaf at a given address. First generates the WOTS key pair, - * then computes leaf by hashing horizontally. - */ -static void wots_gen_leaf(unsigned char *leaf, const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx, const uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - unsigned char pk[PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_WOTS_BYTES]; - uint32_t wots_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_set_type( - wots_addr, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_set_type( - wots_pk_addr, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_ADDR_TYPE_WOTSPK); - - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_set_keypair_addr( - wots_addr, addr_idx); - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_wots_gen_pk( - pk, sk_seed, pub_seed, wots_addr, hash_state_seeded); - - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_copy_keypair_addr( - wots_pk_addr, wots_addr); - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_thash_WOTS_LEN( - leaf, pk, pub_seed, wots_pk_addr, hash_state_seeded); -} - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_crypto_sign_secretkeybytes(void) { - return PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_CRYPTO_SECRETKEYBYTES; -} - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_crypto_sign_publickeybytes(void) { - return PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_CRYPTO_PUBLICKEYBYTES; -} - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_crypto_sign_bytes(void) { - return PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_CRYPTO_BYTES; -} - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_crypto_sign_seedbytes(void) { - return PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_CRYPTO_SEEDBYTES; -} - -/* - * Generates an SPX key pair given a seed of length - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed) { - /* We do not need the auth path in key generation, but it simplifies the - code to have just one treehash routine that computes both root and path - in one function. */ - unsigned char auth_path[PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_TREE_HEIGHT * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N]; - uint32_t top_tree_addr[8] = {0}; - hash_state hash_state_seeded; - - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_set_layer_addr( - top_tree_addr, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_D - 1); - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_set_type( - top_tree_addr, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_ADDR_TYPE_HASHTREE); - - /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ - memcpy(sk, seed, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_CRYPTO_SEEDBYTES); - - memcpy(pk, sk + 2 * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_initialize_hash_function(&hash_state_seeded, pk, sk); - - /* Compute root node of the top-most subtree. */ - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_treehash_TREE_HEIGHT( - sk + 3 * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N, auth_path, sk, sk + 2 * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N, 0, 0, - wots_gen_leaf, top_tree_addr, &hash_state_seeded); - - memcpy(pk + PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N, sk + 3 * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N); - - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_destroy_hash_function(&hash_state_seeded); - return 0; -} - -/* - * Generates an SPX key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk) { - unsigned char seed[PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_CRYPTO_SEEDBYTES]; - randombytes(seed, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_CRYPTO_SEEDBYTES); - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_crypto_sign_seed_keypair( - pk, sk, seed); - - return 0; -} - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - const unsigned char *sk_seed = sk; - const unsigned char *sk_prf = sk + PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N; - const unsigned char *pk = sk + 2 * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N; - const unsigned char *pub_seed = pk; - - unsigned char optrand[PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N]; - unsigned char mhash[PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_FORS_MSG_BYTES]; - unsigned char root[PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N]; - uint32_t i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - - hash_state hash_state_seeded; - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_initialize_hash_function( - &hash_state_seeded, - pub_seed, sk_seed); - - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_set_type( - wots_addr, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_set_type( - tree_addr, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_ADDR_TYPE_HASHTREE); - - /* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ - randombytes(optrand, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N); - /* Compute the digest randomization value. */ - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_gen_message_random( - sig, sk_prf, optrand, m, mlen, &hash_state_seeded); - - /* Derive the message digest and leaf index from R, PK and M. */ - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N; - - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); - - /* Sign the message hash using FORS. */ - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_fors_sign( - sig, root, mhash, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_FORS_BYTES; - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_D; i++) { - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_set_tree_addr(tree_addr, tree); - - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); - - /* Compute a WOTS signature. */ - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_wots_sign( - sig, root, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_WOTS_BYTES; - - /* Compute the authentication path for the used WOTS leaf. */ - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_treehash_TREE_HEIGHT( - root, sig, sk_seed, pub_seed, idx_leaf, 0, - wots_gen_leaf, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_TREE_HEIGHT * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_TREE_HEIGHT; - } - - *siglen = PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_BYTES; - - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_destroy_hash_function(&hash_state_seeded); - return 0; -} - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk) { - const unsigned char *pub_seed = pk; - const unsigned char *pub_root = pk + PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N; - unsigned char mhash[PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_FORS_MSG_BYTES]; - unsigned char wots_pk[PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_WOTS_BYTES]; - unsigned char root[PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N]; - unsigned char leaf[PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N]; - unsigned int i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - hash_state hash_state_seeded; - - if (siglen != PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_BYTES) { - return -1; - } - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_initialize_hash_function( - &hash_state_seeded, - pub_seed, NULL); - - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_set_type( - wots_addr, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_set_type( - tree_addr, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_ADDR_TYPE_HASHTREE); - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_set_type( - wots_pk_addr, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_ADDR_TYPE_WOTSPK); - - /* Derive the message digest and leaf index from R || PK || M. */ - /* The additional PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N is a result of the hash domain separator. */ - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N; - - /* Layer correctly defaults to 0, so no need to set_layer_addr */ - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); - - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_fors_pk_from_sig( - root, sig, mhash, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_FORS_BYTES; - - /* For each subtree.. */ - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_D; i++) { - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_set_tree_addr(tree_addr, tree); - - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); - - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_copy_keypair_addr( - wots_pk_addr, wots_addr); - - /* The WOTS public key is only correct if the signature was correct. */ - /* Initially, root is the FORS pk, but on subsequent iterations it is - the root of the subtree below the currently processed subtree. */ - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_wots_pk_from_sig( - wots_pk, sig, root, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_WOTS_BYTES; - - /* Compute the leaf node using the WOTS public key. */ - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_thash_WOTS_LEN( - leaf, wots_pk, pub_seed, wots_pk_addr, &hash_state_seeded); - - /* Compute the root node of this subtree. */ - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_compute_root( - root, leaf, idx_leaf, 0, sig, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_TREE_HEIGHT, - pub_seed, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_TREE_HEIGHT * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_TREE_HEIGHT; - } - - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_destroy_hash_function(&hash_state_seeded); - /* Check if the root node equals the root node in the public key. */ - if (memcmp(root, pub_root, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N) != 0) { - return -1; - } - - return 0; -} - - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - size_t siglen; - - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_crypto_sign_signature( - sm, &siglen, m, mlen, sk); - - memmove(sm + PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_BYTES, m, mlen); - *smlen = siglen + mlen; - - return 0; -} - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk) { - /* The API caller does not necessarily know what size a signature should be - but SPHINCS+ signatures are always exactly PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_BYTES. */ - if (smlen < PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_BYTES) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - *mlen = smlen - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_BYTES; - - if (PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_crypto_sign_verify( - sm, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_BYTES, sm + PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_BYTES, *mlen, pk)) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - /* If verification was successful, move the message to the right place. */ - memmove(m, sm + PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_BYTES, *mlen); - - return 0; -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/thash.h b/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/thash.h deleted file mode 100644 index b090f26a6e..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/thash.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_THASH_H -#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_THASH_H - -#include "hash_state.h" - -#include - -void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/thash_shake256_simple.c b/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/thash_shake256_simple.c deleted file mode 100644 index 8ed51d81eb..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/thash_shake256_simple.c +++ /dev/null @@ -1,74 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash_state.h" -#include "params.h" -#include "thash.h" - -#include "fips202.h" - -/** - * Takes an array of inblocks concatenated arrays of PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N bytes. - */ -static void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_thash( - unsigned char *out, unsigned char *buf, - const unsigned char *in, unsigned int inblocks, - const unsigned char *pub_seed, uint32_t addr[8]) { - - memcpy(buf, pub_seed, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N); - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_addr_to_bytes(buf + PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N, addr); - memcpy(buf + PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N + PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_ADDR_BYTES, in, inblocks * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N); - - shake256(out, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N, buf, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N + PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N); -} - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N + PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_ADDR_BYTES + 1 * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N]; - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_thash( - out, buf, in, 1, pub_seed, addr); - - (void)hash_state_seeded; /* Avoid unused parameter warning. */ -} - -void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N + PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_ADDR_BYTES + 2 * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N]; - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_thash( - out, buf, in, 2, pub_seed, addr); - - (void)hash_state_seeded; /* Avoid unused parameter warning. */ -} - -void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N + PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_ADDR_BYTES + PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_WOTS_LEN * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N]; - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_thash( - out, buf, in, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_WOTS_LEN, pub_seed, addr); - - (void)hash_state_seeded; /* Avoid unused parameter warning. */ -} - -void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N + PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_ADDR_BYTES + PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_FORS_TREES * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N]; - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_thash( - out, buf, in, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_FORS_TREES, pub_seed, addr); - - (void)hash_state_seeded; /* Avoid unused parameter warning. */ -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/utils.c b/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/utils.c deleted file mode 100644 index 82ae4b3ff3..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/utils.c +++ /dev/null @@ -1,199 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "hash_state.h" -#include "params.h" -#include "thash.h" -#include "utils.h" - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in) { - - /* Iterate over out in decreasing order, for big-endianness. */ - for (size_t i = outlen; i > 0; i--) { - out[i - 1] = in & 0xff; - in = in >> 8; - } -} - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_bytes_to_ull( - const unsigned char *in, size_t inlen) { - unsigned long long retval = 0; - - for (size_t i = 0; i < inlen; i++) { - retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); - } - return retval; -} - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - uint32_t i; - unsigned char buffer[2 * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N]; - - /* If leaf_idx is odd (last bit = 1), current path element is a right child - and auth_path has to go left. Otherwise it is the other way around. */ - if (leaf_idx & 1) { - memcpy(buffer + PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N, leaf, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N); - } else { - memcpy(buffer, leaf, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N); - memcpy(buffer + PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N, auth_path, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N); - } - auth_path += PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N; - - for (i = 0; i < tree_height - 1; i++) { - leaf_idx >>= 1; - idx_offset >>= 1; - /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_set_tree_height(addr, i + 1); - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_set_tree_index( - addr, leaf_idx + idx_offset); - - /* Pick the right or left neighbor, depending on parity of the node. */ - if (leaf_idx & 1) { - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_thash_2( - buffer + PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N); - } else { - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_thash_2( - buffer, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer + PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N, auth_path, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N); - } - auth_path += PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N; - } - - /* The last iteration is exceptional; we do not copy an auth_path node. */ - leaf_idx >>= 1; - idx_offset >>= 1; - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_set_tree_height(addr, tree_height); - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_set_tree_index( - addr, leaf_idx + idx_offset); - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_thash_2( - root, buffer, pub_seed, addr, hash_state_seeded); -} - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -static void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_treehash( - unsigned char *root, unsigned char *auth_path, - unsigned char *stack, unsigned int *heights, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - - unsigned int offset = 0; - uint32_t idx; - uint32_t tree_idx; - - for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { - /* Add the next leaf node to the stack. */ - gen_leaf(stack + offset * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N, - sk_seed, pub_seed, idx + idx_offset, tree_addr, - hash_state_seeded); - offset++; - heights[offset - 1] = 0; - - /* If this is a node we need for the auth path.. */ - if ((leaf_idx ^ 0x1) == idx) { - memcpy(auth_path, stack + (offset - 1)*PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N); - } - - /* While the top-most nodes are of equal height.. */ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { - /* Compute index of the new node, in the next layer. */ - tree_idx = (idx >> (heights[offset - 1] + 1)); - - /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_set_tree_height( - tree_addr, heights[offset - 1] + 1); - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_set_tree_index( - tree_addr, tree_idx + (idx_offset >> (heights[offset - 1] + 1))); - /* Hash the top-most nodes from the stack together. */ - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_thash_2( - stack + (offset - 2)*PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N, stack + (offset - 2)*PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N, - pub_seed, tree_addr, hash_state_seeded); - offset--; - /* Note that the top-most node is now one layer higher. */ - heights[offset - 1]++; - - /* If this is a node we need for the auth path.. */ - if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_path + heights[offset - 1]*PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N, - stack + (offset - 1)*PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N); - } - } - } - memcpy(root, stack, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N); -} - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_FORS_HEIGHT + 1)*PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N]; - unsigned int heights[PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_FORS_HEIGHT + 1]; - - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_FORS_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_TREE_HEIGHT + 1)*PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N]; - unsigned int heights[PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_TREE_HEIGHT + 1]; - - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_TREE_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/utils.h b/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/utils.h deleted file mode 100644 index 66b280a35f..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/utils.h +++ /dev/null @@ -1,64 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_UTILS_H -#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_UTILS_H - -#include "hash_state.h" -#include "params.h" -#include -#include - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in); - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_bytes_to_ull( - const unsigned char *in, size_t inlen); - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/wots.c b/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/wots.c deleted file mode 100644 index 40a615ea1f..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/wots.c +++ /dev/null @@ -1,167 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "hash_state.h" -#include "params.h" -#include "thash.h" -#include "utils.h" -#include "wots.h" - -// TODO clarify address expectations, and make them more uniform. -// TODO i.e. do we expect types to be set already? -// TODO and do we expect modifications or copies? - -/** - * Computes the starting value for a chain, i.e. the secret key. - * Expects the address to be complete up to the chain address. - */ -static void wots_gen_sk(unsigned char *sk, const unsigned char *sk_seed, - uint32_t wots_addr[8], - const hash_state *hash_state_seeded) { - /* Make sure that the hash address is actually zeroed. */ - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_set_hash_addr(wots_addr, 0); - - /* Generate sk element. */ - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_prf_addr(sk, sk_seed, wots_addr, hash_state_seeded); -} - -/** - * Computes the chaining function. - * out and in have to be n-byte arrays. - * - * Interprets in as start-th value of the chain. - * addr has to contain the address of the chain. - */ -static void gen_chain(unsigned char *out, const unsigned char *in, - unsigned int start, unsigned int steps, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - uint32_t i; - - /* Initialize out with the value at position 'start'. */ - memcpy(out, in, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N); - - /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_WOTS_W; i++) { - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_set_hash_addr(addr, i); - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_thash_1( - out, out, pub_seed, addr, hash_state_seeded); - } -} - -/** - * base_w algorithm as described in draft. - * Interprets an array of bytes as integers in base w. - * This only works when log_w is a divisor of 8. - */ -static void base_w(unsigned int *output, const size_t out_len, - const unsigned char *input) { - size_t in = 0; - size_t out = 0; - unsigned char total = 0; - unsigned int bits = 0; - size_t consumed; - - for (consumed = 0; consumed < out_len; consumed++) { - if (bits == 0) { - total = input[in]; - in++; - bits += 8; - } - bits -= PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_WOTS_LOGW; - output[out] = (unsigned int)((total >> bits) & (PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_WOTS_W - 1)); - out++; - } -} - -/* Computes the WOTS+ checksum over a message (in base_w). */ -static void wots_checksum(unsigned int *csum_base_w, - const unsigned int *msg_base_w) { - unsigned int csum = 0; - unsigned char csum_bytes[(PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_WOTS_LEN2 * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_WOTS_LOGW + 7) / 8]; - unsigned int i; - - /* Compute checksum. */ - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_WOTS_LEN1; i++) { - csum += PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_WOTS_W - 1 - msg_base_w[i]; - } - - /* Convert checksum to base_w. */ - /* Make sure expected empty zero bits are the least significant bits. */ - csum = csum << (8 - ((PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_WOTS_LEN2 * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_WOTS_LOGW) % 8)); - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_ull_to_bytes( - csum_bytes, sizeof(csum_bytes), csum); - base_w(csum_base_w, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_WOTS_LEN2, csum_bytes); -} - -/* Takes a message and derives the matching chain lengths. */ -static void chain_lengths(unsigned int *lengths, const unsigned char *msg) { - base_w(lengths, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_WOTS_LEN1, msg); - wots_checksum(lengths + PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_WOTS_LEN1, lengths); -} - -/** - * WOTS key generation. Takes a 32 byte sk_seed, expands it to WOTS private key - * elements and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_wots_gen_pk( - unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - uint32_t i; - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_WOTS_LEN; i++) { - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_set_chain_addr(addr, i); - wots_gen_sk(pk + i * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N, sk_seed, addr, hash_state_seeded); - gen_chain(pk + i * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N, pk + i * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N, - 0, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_WOTS_W - 1, pub_seed, addr, hash_state_seeded); - } -} - -/** - * Takes a n-byte message and the 32-byte sk_see to compute a signature 'sig'. - */ -void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_wots_sign( - unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *hash_state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_WOTS_LEN; i++) { - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_set_chain_addr(addr, i); - wots_gen_sk(sig + i * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N, sk_seed, addr, hash_state_seeded); - gen_chain(sig + i * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N, sig + i * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N, 0, lengths[i], pub_seed, addr, hash_state_seeded); - } -} - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_wots_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_WOTS_LEN; i++) { - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_set_chain_addr(addr, i); - gen_chain(pk + i * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N, sig + i * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N, - lengths[i], PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_WOTS_W - 1 - lengths[i], pub_seed, addr, - hash_state_seeded); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/wots.h b/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/wots.h deleted file mode 100644 index 5627cc9356..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/wots.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_WOTS_H -#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_WOTS_H - -#include "hash_state.h" -#include "params.h" -#include - -/** - * WOTS key generation. Takes a 32 byte seed for the private key, expands it to - * a full WOTS private key and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_wots_gen_pk( - unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -/** - * Takes a n-byte message and the 32-byte seed for the private key to compute a - * signature that is placed at 'sig'. - */ -void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_wots_sign( - unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *hash_state_seeded); - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_wots_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_avx2/LICENSE b/src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_avx2/LICENSE deleted file mode 100644 index 670154e353..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_avx2/LICENSE +++ /dev/null @@ -1,116 +0,0 @@ -CC0 1.0 Universal - -Statement of Purpose - -The laws of most jurisdictions throughout the world automatically confer -exclusive Copyright and Related Rights (defined below) upon the creator and -subsequent owner(s) (each and all, an "owner") of an original work of -authorship and/or a database (each, a "Work"). - -Certain owners wish to permanently relinquish those rights to a Work for the -purpose of contributing to a commons of creative, cultural and scientific -works ("Commons") that the public can reliably and without fear of later -claims of infringement build upon, modify, incorporate in other works, reuse -and redistribute as freely as possible in any form whatsoever and for any -purposes, including without limitation commercial purposes. These owners may -contribute to the Commons to promote the ideal of a free culture and the -further production of creative, cultural and scientific works, or to gain -reputation or greater distribution for their Work in part through the use and -efforts of others. - -For these and/or other purposes and motivations, and without any expectation -of additional consideration or compensation, the person associating CC0 with a -Work (the "Affirmer"), to the extent that he or she is an owner of Copyright -and Related Rights in the Work, voluntarily elects to apply CC0 to the Work -and publicly distribute the Work under its terms, with knowledge of his or her -Copyright and Related Rights in the Work and the meaning and intended legal -effect of CC0 on those rights. - -1. Copyright and Related Rights. A Work made available under CC0 may be -protected by copyright and related or neighboring rights ("Copyright and -Related Rights"). Copyright and Related Rights include, but are not limited -to, the following: - - i. the right to reproduce, adapt, distribute, perform, display, communicate, - and translate a Work; - - ii. moral rights retained by the original author(s) and/or performer(s); - - iii. publicity and privacy rights pertaining to a person's image or likeness - depicted in a Work; - - iv. rights protecting against unfair competition in regards to a Work, - subject to the limitations in paragraph 4(a), below; - - v. rights protecting the extraction, dissemination, use and reuse of data in - a Work; - - vi. database rights (such as those arising under Directive 96/9/EC of the - European Parliament and of the Council of 11 March 1996 on the legal - protection of databases, and under any national implementation thereof, - including any amended or successor version of such directive); and - - vii. other similar, equivalent or corresponding rights throughout the world - based on applicable law or treaty, and any national implementations thereof. - -2. Waiver. To the greatest extent permitted by, but not in contravention of, -applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and -unconditionally waives, abandons, and surrenders all of Affirmer's Copyright -and Related Rights and associated claims and causes of action, whether now -known or unknown (including existing as well as future claims and causes of -action), in the Work (i) in all territories worldwide, (ii) for the maximum -duration provided by applicable law or treaty (including future time -extensions), (iii) in any current or future medium and for any number of -copies, and (iv) for any purpose whatsoever, including without limitation -commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes -the Waiver for the benefit of each member of the public at large and to the -detriment of Affirmer's heirs and successors, fully intending that such Waiver -shall not be subject to revocation, rescission, cancellation, termination, or -any other legal or equitable action to disrupt the quiet enjoyment of the Work -by the public as contemplated by Affirmer's express Statement of Purpose. - -3. Public License Fallback. Should any part of the Waiver for any reason be -judged legally invalid or ineffective under applicable law, then the Waiver -shall be preserved to the maximum extent permitted taking into account -Affirmer's express Statement of Purpose. In addition, to the extent the Waiver -is so judged Affirmer hereby grants to each affected person a royalty-free, -non transferable, non sublicensable, non exclusive, irrevocable and -unconditional license to exercise Affirmer's Copyright and Related Rights in -the Work (i) in all territories worldwide, (ii) for the maximum duration -provided by applicable law or treaty (including future time extensions), (iii) -in any current or future medium and for any number of copies, and (iv) for any -purpose whatsoever, including without limitation commercial, advertising or -promotional purposes (the "License"). The License shall be deemed effective as -of the date CC0 was applied by Affirmer to the Work. Should any part of the -License for any reason be judged legally invalid or ineffective under -applicable law, such partial invalidity or ineffectiveness shall not -invalidate the remainder of the License, and in such case Affirmer hereby -affirms that he or she will not (i) exercise any of his or her remaining -Copyright and Related Rights in the Work or (ii) assert any associated claims -and causes of action with respect to the Work, in either case contrary to -Affirmer's express Statement of Purpose. - -4. Limitations and Disclaimers. - - a. No trademark or patent rights held by Affirmer are waived, abandoned, - surrendered, licensed or otherwise affected by this document. - - b. Affirmer offers the Work as-is and makes no representations or warranties - of any kind concerning the Work, express, implied, statutory or otherwise, - including without limitation warranties of title, merchantability, fitness - for a particular purpose, non infringement, or the absence of latent or - other defects, accuracy, or the present or absence of errors, whether or not - discoverable, all to the greatest extent permissible under applicable law. - - c. Affirmer disclaims responsibility for clearing rights of other persons - that may apply to the Work or any use thereof, including without limitation - any person's Copyright and Related Rights in the Work. Further, Affirmer - disclaims responsibility for obtaining any necessary consents, permissions - or other rights required for any use of the Work. - - d. Affirmer understands and acknowledges that Creative Commons is not a - party to this document and has no duty or obligation with respect to this - CC0 or use of the Work. - -For more information, please see - diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_avx2/address.c b/src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_avx2/address.c deleted file mode 100644 index 64708b6f5e..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_avx2/address.c +++ /dev/null @@ -1,78 +0,0 @@ -#include - -#include "address.h" -#include "params.h" -#include "utils.h" - -void PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]) { - int i; - - for (i = 0; i < 8; i++) { - PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_ull_to_bytes( - bytes + i * 4, 4, addr[i]); - } -} - -void PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_set_layer_addr( - uint32_t addr[8], uint32_t layer) { - addr[0] = layer; -} - -void PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_set_tree_addr( - uint32_t addr[8], uint64_t tree) { - addr[1] = 0; - addr[2] = (uint32_t) (tree >> 32); - addr[3] = (uint32_t) tree; -} - -void PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_set_type( - uint32_t addr[8], uint32_t type) { - addr[4] = type; -} - -void PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; -} - -/* These functions are used for OTS addresses. */ - -void PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_set_keypair_addr( - uint32_t addr[8], uint32_t keypair) { - addr[5] = keypair; -} - -void PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; - out[5] = in[5]; -} - -void PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_set_chain_addr( - uint32_t addr[8], uint32_t chain) { - addr[6] = chain; -} - -void PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_set_hash_addr( - uint32_t addr[8], uint32_t hash) { - addr[7] = hash; -} - -/* These functions are used for all hash tree addresses (including FORS). */ - -void PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_set_tree_height( - uint32_t addr[8], uint32_t tree_height) { - addr[6] = tree_height; -} - -void PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_set_tree_index( - uint32_t addr[8], uint32_t tree_index) { - addr[7] = tree_index; -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_avx2/address.h b/src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_avx2/address.h deleted file mode 100644 index 75c55796a5..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_avx2/address.h +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_ADDRESS_H -#define PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_ADDRESS_H - -#include - -#define PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_ADDR_TYPE_WOTS 0 -#define PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_ADDR_TYPE_WOTSPK 1 -#define PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_ADDR_TYPE_HASHTREE 2 -#define PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_ADDR_TYPE_FORSTREE 3 -#define PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_ADDR_TYPE_FORSPK 4 - -void PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]); - -void PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_set_layer_addr( - uint32_t addr[8], uint32_t layer); - -void PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_set_tree_addr( - uint32_t addr[8], uint64_t tree); - -void PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_set_type( - uint32_t addr[8], uint32_t type); - -/* Copies the layer and tree part of one address into the other */ -void PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for WOTS and FORS addresses. */ - -void PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_set_keypair_addr( - uint32_t addr[8], uint32_t keypair); - -void PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_set_chain_addr( - uint32_t addr[8], uint32_t chain); - -void PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_set_hash_addr( - uint32_t addr[8], uint32_t hash); - -void PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for all hash tree addresses (including FORS). */ - -void PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_set_tree_height( - uint32_t addr[8], uint32_t tree_height); - -void PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_set_tree_index( - uint32_t addr[8], uint32_t tree_index); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_avx2/api.h b/src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_avx2/api.h deleted file mode 100644 index 05fca01b7f..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_avx2/api.h +++ /dev/null @@ -1,81 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_API_H -#define PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_API_H - -#include -#include - - - -#define PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_CRYPTO_ALGNAME "SPHINCS+" - -#define PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_CRYPTO_SECRETKEYBYTES 96 -#define PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_CRYPTO_PUBLICKEYBYTES 48 -#define PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_CRYPTO_BYTES 16224 -#define PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_CRYPTO_SEEDBYTES 72 - - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_avx2/fors.c b/src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_avx2/fors.c deleted file mode 100644 index 8411b93e4e..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_avx2/fors.c +++ /dev/null @@ -1,206 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "fors.h" -#include "hash.h" -#include "hashx4.h" -#include "thash.h" -#include "thashx4.h" -#include "utils.h" -#include "utilsx4.h" - -static void fors_gen_skx4(unsigned char *sk0, - unsigned char *sk1, - unsigned char *sk2, - unsigned char *sk3, const unsigned char *sk_seed, - uint32_t fors_leaf_addrx4[4 * 8], - const hash_state *state_seeded) { - PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_prf_addrx4(sk0, sk1, sk2, sk3, sk_seed, fors_leaf_addrx4, state_seeded); -} - -static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, - const unsigned char *pub_seed, - uint32_t fors_leaf_addr[8], const hash_state *state_seeded) { - PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_thash_1(leaf, sk, pub_seed, fors_leaf_addr, state_seeded); -} - -static void fors_sk_to_leafx4(unsigned char *leaf0, - unsigned char *leaf1, - unsigned char *leaf2, - unsigned char *leaf3, - const unsigned char *sk0, - const unsigned char *sk1, - const unsigned char *sk2, - const unsigned char *sk3, - const unsigned char *pub_seed, - uint32_t fors_leaf_addrx4[4 * 8], - const hash_state *state_seeded) { - PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_thashx4_1(leaf0, leaf1, leaf2, leaf3, - sk0, sk1, sk2, sk3, pub_seed, fors_leaf_addrx4, state_seeded); -} - -static void fors_gen_leafx4(unsigned char *leaf0, - unsigned char *leaf1, - unsigned char *leaf2, - unsigned char *leaf3, - const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx0, - uint32_t addr_idx1, - uint32_t addr_idx2, - uint32_t addr_idx3, - const uint32_t fors_tree_addr[8], - const hash_state *state_seeded) { - uint32_t fors_leaf_addrx4[4 * 8] = {0}; - unsigned int j; - - /* Only copy the parts that must be kept in fors_leaf_addrx4. */ - for (j = 0; j < 4; j++) { - PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_copy_keypair_addr(fors_leaf_addrx4 + j * 8, fors_tree_addr); - PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_set_type(fors_leaf_addrx4 + j * 8, PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_ADDR_TYPE_FORSTREE); - } - - PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_set_tree_index(fors_leaf_addrx4 + 0 * 8, addr_idx0); - PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_set_tree_index(fors_leaf_addrx4 + 1 * 8, addr_idx1); - PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_set_tree_index(fors_leaf_addrx4 + 2 * 8, addr_idx2); - PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_set_tree_index(fors_leaf_addrx4 + 3 * 8, addr_idx3); - - fors_gen_skx4(leaf0, leaf1, leaf2, leaf3, sk_seed, fors_leaf_addrx4, state_seeded); - fors_sk_to_leafx4(leaf0, leaf1, leaf2, leaf3, - leaf0, leaf1, leaf2, leaf3, pub_seed, fors_leaf_addrx4, state_seeded); -} - -/** - * Interprets m as PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_FORS_HEIGHT-bit unsigned integers. - * Assumes m contains at least PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_FORS_TREES bits. - * Assumes indices has space for PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_FORS_TREES integers. - */ -static void message_to_indices(uint32_t *indices, const unsigned char *m) { - unsigned int i, j; - unsigned int offset = 0; - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_FORS_TREES; i++) { - indices[i] = 0; - for (j = 0; j < PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_FORS_HEIGHT; j++) { - indices[i] ^= (((uint32_t)m[offset >> 3] >> (offset & 0x7)) & 0x1) << j; - offset++; - } - } -} - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *state_seeded) { - /* Round up to multiple of 4 to prevent out-of-bounds for x4 parallelism */ - uint32_t indices[(PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_FORS_TREES + 3) & ~3] = {0}; - unsigned char roots[((PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_FORS_TREES + 3) & ~3) * PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N]; - /* Sign to a buffer, since we may not have a nice multiple of 4 and would - otherwise overrun the signature. */ - unsigned char sigbufx4[4 * PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N * (1 + PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_FORS_HEIGHT)]; - uint32_t fors_tree_addrx4[4 * 8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset[4] = {0}; - unsigned int i, j; - - for (j = 0; j < 4; j++) { - PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_copy_keypair_addr(fors_tree_addrx4 + j * 8, fors_addr); - PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_set_type(fors_tree_addrx4 + j * 8, PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_ADDR_TYPE_FORSTREE); - } - - PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_copy_keypair_addr(fors_pk_addr, fors_addr); - PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_set_type(fors_pk_addr, PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < ((PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_FORS_TREES + 3) & ~0x3); i += 4) { - for (j = 0; j < 4; j++) { - if (i + j < PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_FORS_TREES) { - idx_offset[j] = (i + j) * (1 << PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_FORS_HEIGHT); - - PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_set_tree_height(fors_tree_addrx4 + j * 8, 0); - PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_set_tree_index(fors_tree_addrx4 + j * 8, - indices[i + j] + idx_offset[j]); - } - } - - /* Include the secret key part that produces the selected leaf nodes. */ - fors_gen_skx4(sigbufx4 + 0 * PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N, - sigbufx4 + 1 * PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N, - sigbufx4 + 2 * PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N, - sigbufx4 + 3 * PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N, - sk_seed, fors_tree_addrx4, state_seeded); - - PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_treehashx4_FORS_HEIGHT(roots + i * PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N, sigbufx4 + 4 * PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N, sk_seed, pub_seed, - &indices[i], idx_offset, fors_gen_leafx4, fors_tree_addrx4, - state_seeded); - - for (j = 0; j < 4; j++) { - if (i + j < PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_FORS_TREES) { - memcpy(sig, sigbufx4 + j * PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N, PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N); - memcpy(sig + PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N, - sigbufx4 + 4 * PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N + j * PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N * PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_FORS_HEIGHT, - PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N * PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_FORS_HEIGHT); - sig += PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N * (1 + PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_FORS_HEIGHT); - } - } - } - - /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_thash_FORS_TREES(pk, roots, pub_seed, fors_pk_addr, state_seeded); -} - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, - const uint32_t fors_addr[8], - const hash_state *state_seeded) { - uint32_t indices[PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_FORS_TREES]; - unsigned char roots[PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_FORS_TREES * PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N]; - unsigned char leaf[PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N]; - uint32_t fors_tree_addr[8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_copy_keypair_addr(fors_tree_addr, fors_addr); - PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_copy_keypair_addr(fors_pk_addr, fors_addr); - - PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_set_type(fors_tree_addr, PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_set_type(fors_pk_addr, PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_FORS_TREES; i++) { - idx_offset = i * (1 << PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_FORS_HEIGHT); - - PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_set_tree_height(fors_tree_addr, 0); - PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Derive the leaf from the included secret key part. */ - fors_sk_to_leaf(leaf, sig, pub_seed, fors_tree_addr, state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N; - - /* Derive the corresponding root node of this tree. */ - PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_compute_root(roots + i * PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N, leaf, indices[i], idx_offset, - sig, PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_FORS_HEIGHT, pub_seed, fors_tree_addr, - state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N * PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_thash_FORS_TREES(pk, roots, pub_seed, fors_pk_addr, state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_avx2/fors.h b/src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_avx2/fors.h deleted file mode 100644 index 94c8368d39..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_avx2/fors.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_FORS_H -#define PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_FORS_H - -#include - -#include "hash_state.h" -#include "params.h" - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_fors_sign( - unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *hash_state_seeded); - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_fors_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, const uint32_t fors_addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_avx2/hash.h b/src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_avx2/hash.h deleted file mode 100644 index 6d13822caa..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_avx2/hash.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_HASH_H -#define PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_HASH_H - -#include "hash_state.h" - -#include -#include - -void PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_initialize_hash_function( - hash_state *hash_state_seeded, - const unsigned char *pub_seed, const unsigned char *sk_seed); - -void PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_destroy_hash_function(hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_avx2/hash_shake256.c b/src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_avx2/hash_shake256.c deleted file mode 100644 index b7390a6e6e..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_avx2/hash_shake256.c +++ /dev/null @@ -1,106 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "utils.h" - -#include "fips202.h" - -/* For SHAKE256, there is no immediate reason to initialize at the start, - so this function is an empty operation. */ -void PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_initialize_hash_function( - hash_state *hash_state_seeded, // NOLINT(readability-non-const-parameter) - const unsigned char *pub_seed, const unsigned char *sk_seed) { - (void)hash_state_seeded; /* Suppress an 'unused parameter' warning. */ - (void)pub_seed; /* Suppress an 'unused parameter' warning. */ - (void)sk_seed; /* Suppress an 'unused parameter' warning. */ -} - -/* This is not necessary for SHAKE256, so we don't do anything */ -void PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_destroy_hash_function( - hash_state *hash_state_seeded) { // NOLINT(readability-non-const-parameter) - (void)hash_state_seeded; -} - -/* - * Computes PRF(key, addr), given a secret key of PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N bytes and an address - */ -void PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded) { - unsigned char buf[PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_ADDR_BYTES]; - - memcpy(buf, key, PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N); - PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_addr_to_bytes(buf + PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N, addr); - - shake256(out, PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N, buf, PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_ADDR_BYTES); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} - -/** - * Computes the message-dependent randomness R, using a secret seed and an - * optional randomization value as well as the message. - */ -void PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded) { - shake256incctx state; - - shake256_inc_init(&state); - shake256_inc_absorb(&state, sk_prf, PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N); - shake256_inc_absorb(&state, optrand, PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N); - shake256_inc_absorb(&state, m, mlen); - shake256_inc_finalize(&state); - shake256_inc_squeeze(R, PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N, &state); - shake256_inc_ctx_release(&state); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} - -/** - * Computes the message hash using R, the public key, and the message. - * Outputs the message digest and the index of the leaf. The index is split in - * the tree index and the leaf index, for convenient copying to an address. - */ -void PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded) { -#define PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_TREE_BITS (PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_TREE_HEIGHT * (PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_D - 1)) -#define PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_TREE_BYTES ((PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_TREE_BITS + 7) / 8) -#define PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_LEAF_BITS PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_TREE_HEIGHT -#define PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_LEAF_BYTES ((PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_LEAF_BITS + 7) / 8) -#define PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_DGST_BYTES (PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_FORS_MSG_BYTES + PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_TREE_BYTES + PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_LEAF_BYTES) - - unsigned char buf[PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_DGST_BYTES]; - unsigned char *bufp = buf; - shake256incctx state; - - shake256_inc_init(&state); - shake256_inc_absorb(&state, R, PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N); - shake256_inc_absorb(&state, pk, PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_PK_BYTES); - shake256_inc_absorb(&state, m, mlen); - shake256_inc_finalize(&state); - shake256_inc_squeeze(buf, PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_DGST_BYTES, &state); - shake256_inc_ctx_release(&state); - - memcpy(digest, bufp, PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_FORS_MSG_BYTES); - bufp += PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_FORS_MSG_BYTES; - - *tree = PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_bytes_to_ull( - bufp, PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_TREE_BYTES); - *tree &= (~(uint64_t)0) >> (64 - PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_TREE_BITS); - bufp += PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_TREE_BYTES; - - *leaf_idx = (uint32_t)PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_bytes_to_ull( - bufp, PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_LEAF_BYTES); - *leaf_idx &= (~(uint32_t)0) >> (32 - PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_LEAF_BITS); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_avx2/hash_shake256x4.c b/src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_avx2/hash_shake256x4.c deleted file mode 100644 index be83a64afe..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_avx2/hash_shake256x4.c +++ /dev/null @@ -1,38 +0,0 @@ -#include -#include - -#include "address.h" -#include "fips202x4.h" -#include "hashx4.h" -#include "params.h" - -/* - * 4-way parallel version of prf_addr; takes 4x as much input and output - */ -void PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_prf_addrx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const unsigned char *key, - const uint32_t addrx4[4 * 8], - const hash_state *state_seeded) { - unsigned char bufx4[4 * (PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_ADDR_BYTES)]; - unsigned int j; - - for (j = 0; j < 4; j++) { - memcpy(bufx4 + j * (PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_ADDR_BYTES), key, PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N); - PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_addr_to_bytes(bufx4 + PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N + j * (PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_ADDR_BYTES), addrx4 + j * 8); - } - - PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_shake256x4(out0, - out1, - out2, - out3, PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N, - bufx4 + 0 * (PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_ADDR_BYTES), - bufx4 + 1 * (PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_ADDR_BYTES), - bufx4 + 2 * (PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_ADDR_BYTES), - bufx4 + 3 * (PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_ADDR_BYTES), PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_ADDR_BYTES); - - /* Avoid unused parameter warning */ - (void)state_seeded; -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_avx2/hash_state.h b/src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_avx2/hash_state.h deleted file mode 100644 index fcb026ddf2..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_avx2/hash_state.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_HASH_STATE_H -#define PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_HASH_STATE_H - -/** - * Defines the type of the hash function state. - * - * Don't be fooled into thinking this instance of SPHINCS+ isn't stateless! - * - * From Section 7.2.2 from the SPHINCS+ round-2 specification: - * - * Each of the instances of the tweakable hash function take PK.seed as its - * first input, which is constant for a given key pair – and, thus, across - * a single signature. This leads to a lot of redundant computation. To remedy - * this, we pad PK.seed to the length of a full 64-byte SHA-256 input block. - * Because of the Merkle-Damgård construction that underlies SHA-256, this - * allows for reuse of the intermediate SHA-256 state after the initial call to - * the compression function which improves performance. - * - * We pass this hash state around in functions, because otherwise we need to - * have a global variable. - * - * SHAKE256 does not need this state. Because this implementation is generated - * from a shared code base, we still need to specify some hash_state as it is - * still passed around. We chose to use an `int` as a placeholder for this - * purpose. - */ - -typedef int hash_state; - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_avx2/hashx4.h b/src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_avx2/hashx4.h deleted file mode 100644 index 38724c72a4..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_avx2/hashx4.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_HASHX4_H -#define PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_HASHX4_H - -#include - -#include "hash_state.h" - -void PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_prf_addrx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const unsigned char *key, - const uint32_t addrx4[4 * 8], - const hash_state *state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_avx2/params.h b/src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_avx2/params.h deleted file mode 100644 index ebfac6eb7f..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_avx2/params.h +++ /dev/null @@ -1,53 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_PARAMS_H -#define PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_PARAMS_H - -/* Hash output length in bytes. */ -#define PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N 24 -/* Height of the hypertree. */ -#define PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_FULL_HEIGHT 63 -/* Number of subtree layer. */ -#define PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_D 7 -/* FORS tree dimensions. */ -#define PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_FORS_HEIGHT 14 -#define PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_FORS_TREES 17 -/* Winternitz parameter, */ -#define PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_WOTS_W 16 - -/* The hash function is defined by linking a different hash.c file, as opposed - to setting a #define constant. */ - -/* For clarity */ -#define PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_ADDR_BYTES 32 - -/* WOTS parameters. */ -#define PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_WOTS_LOGW 4 - -#define PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_WOTS_LEN1 (8 * PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N / PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_WOTS_LOGW) - -/* PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#define PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_WOTS_LEN2 3 - -#define PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_WOTS_LEN (PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_WOTS_LEN1 + PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_WOTS_LEN2) -#define PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_WOTS_BYTES (PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_WOTS_LEN * PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N) -#define PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_WOTS_PK_BYTES PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_WOTS_BYTES - -/* Subtree size. */ -#define PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_TREE_HEIGHT (PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_FULL_HEIGHT / PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_D) - -/* FORS parameters. */ -#define PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_FORS_MSG_BYTES ((PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_FORS_TREES + 7) / 8) -#define PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_FORS_BYTES ((PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_FORS_HEIGHT + 1) * PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_FORS_TREES * PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N) -#define PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_FORS_PK_BYTES PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N - -/* Resulting SPX sizes. */ -#define PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_BYTES (PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_FORS_BYTES + PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_D * PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_WOTS_BYTES +\ - PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_FULL_HEIGHT * PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N) -#define PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_PK_BYTES (2 * PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N) -#define PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_SK_BYTES (2 * PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_PK_BYTES) - -/* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ -#define PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_OPTRAND_BYTES 32 - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_avx2/sign.c b/src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_avx2/sign.c deleted file mode 100644 index 2de699247b..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_avx2/sign.c +++ /dev/null @@ -1,409 +0,0 @@ -#include -#include -#include -#include - -#include "address.h" -#include "api.h" -#include "fors.h" -#include "hash.h" -#include "hash_state.h" -#include "params.h" -#include "randombytes.h" -#include "thash.h" -#include "utils.h" -#include "wots.h" - - -/** - * Computes the leaf at a given address. First generates the WOTS key pair, - * then computes leaf by hashing horizontally. - */ -static void wots_gen_leaf(unsigned char *leaf, const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx, const uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - unsigned char pk[PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_WOTS_BYTES]; - uint32_t wots_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_set_type( - wots_addr, PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_set_type( - wots_pk_addr, PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_ADDR_TYPE_WOTSPK); - - PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_set_keypair_addr( - wots_addr, addr_idx); - PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_wots_gen_pk( - pk, sk_seed, pub_seed, wots_addr, hash_state_seeded); - - PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_copy_keypair_addr( - wots_pk_addr, wots_addr); - PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_thash_WOTS_LEN( - leaf, pk, pub_seed, wots_pk_addr, hash_state_seeded); -} - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_crypto_sign_secretkeybytes(void) { - return PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_CRYPTO_SECRETKEYBYTES; -} - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_crypto_sign_publickeybytes(void) { - return PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_CRYPTO_PUBLICKEYBYTES; -} - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_crypto_sign_bytes(void) { - return PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_CRYPTO_BYTES; -} - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_crypto_sign_seedbytes(void) { - return PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_CRYPTO_SEEDBYTES; -} - -/* - * Generates an SPX key pair given a seed of length - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed) { - /* We do not need the auth path in key generation, but it simplifies the - code to have just one treehash routine that computes both root and path - in one function. */ - unsigned char auth_path[PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_TREE_HEIGHT * PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N]; - uint32_t top_tree_addr[8] = {0}; - hash_state hash_state_seeded; - - PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_set_layer_addr( - top_tree_addr, PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_D - 1); - PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_set_type( - top_tree_addr, PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_ADDR_TYPE_HASHTREE); - - /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ - memcpy(sk, seed, PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_CRYPTO_SEEDBYTES); - - memcpy(pk, sk + 2 * PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N, PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_initialize_hash_function(&hash_state_seeded, pk, sk); - - /* Compute root node of the top-most subtree. */ - PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_treehash_TREE_HEIGHT( - sk + 3 * PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N, auth_path, sk, sk + 2 * PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N, 0, 0, - wots_gen_leaf, top_tree_addr, &hash_state_seeded); - - memcpy(pk + PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N, sk + 3 * PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N, PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N); - - return 0; -} - -/* - * Generates an SPX key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk) { - - // guarantee alignment of pk - union { - __m128 _x[PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_CRYPTO_PUBLICKEYBYTES / 16]; - uint8_t pk[PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_CRYPTO_PUBLICKEYBYTES]; - } aligned_pk; - - // guarantee alignment of sk - union { - __m128 _x[PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_CRYPTO_SECRETKEYBYTES / 16]; - uint8_t sk[PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_CRYPTO_SECRETKEYBYTES]; - } aligned_sk; - - union { - __m128 _x[PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_CRYPTO_SEEDBYTES / 16]; - uint8_t seed[PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_CRYPTO_SEEDBYTES]; - } aligned_seed; - randombytes(aligned_seed.seed, PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_CRYPTO_SEEDBYTES); - - PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_crypto_sign_seed_keypair( - aligned_pk.pk, aligned_sk.sk, aligned_seed.seed); - memcpy(pk, aligned_pk.pk, PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_CRYPTO_PUBLICKEYBYTES); - memcpy(sk, aligned_sk.sk, PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_CRYPTO_SECRETKEYBYTES); - - return 0; -} - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - // guarantee alignment of sk - union { - __m128 *_x; - uint8_t sk[PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_CRYPTO_SECRETKEYBYTES]; - } aligned_sk; - memcpy(aligned_sk.sk, sk, PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_CRYPTO_SECRETKEYBYTES); - sk = aligned_sk.sk; - - // guarantee alignment of sig - union { - __m128 *_x; - uint8_t sig[PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_BYTES]; - } aligned_sig; - uint8_t *orig_sig = sig; - sig = (uint8_t *)aligned_sig.sig; - - const unsigned char *sk_seed = sk; - const unsigned char *sk_prf = sk + PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N; - const unsigned char *pk = sk + 2 * PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N; - const unsigned char *pub_seed = pk; - - unsigned char optrand[PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N]; - unsigned char mhash[PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_FORS_MSG_BYTES]; - unsigned char root[PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N]; - uint32_t i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - - hash_state hash_state_seeded; - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_initialize_hash_function( - &hash_state_seeded, - pub_seed, sk_seed); - - PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_set_type( - wots_addr, PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_set_type( - tree_addr, PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_ADDR_TYPE_HASHTREE); - - /* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ - randombytes(optrand, PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N); - /* Compute the digest randomization value. */ - PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_gen_message_random( - sig, sk_prf, optrand, m, mlen, &hash_state_seeded); - - /* Derive the message digest and leaf index from R, PK and M. */ - PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N; - - PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_set_keypair_addr( - wots_addr, idx_leaf); - - /* Sign the message hash using FORS. */ - PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_fors_sign( - sig, root, mhash, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_FORS_BYTES; - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_D; i++) { - PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_set_tree_addr(tree_addr, tree); - - PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_set_keypair_addr( - wots_addr, idx_leaf); - - /* Compute a WOTS signature. */ - PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_wots_sign( - sig, root, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_WOTS_BYTES; - - /* Compute the authentication path for the used WOTS leaf. */ - PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_treehash_TREE_HEIGHT( - root, sig, sk_seed, pub_seed, idx_leaf, 0, - wots_gen_leaf, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_TREE_HEIGHT * PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_TREE_HEIGHT; - } - - memcpy(orig_sig, aligned_sig.sig, PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_BYTES); - *siglen = PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_BYTES; - - return 0; -} - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk) { - // guarantee alignment of pk - union { - __m128 *_x; - uint8_t pk[PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_CRYPTO_PUBLICKEYBYTES]; - } aligned_pk; - memcpy(aligned_pk.pk, pk, PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_CRYPTO_PUBLICKEYBYTES); - pk = aligned_pk.pk; - - const unsigned char *pub_seed = pk; - const unsigned char *pub_root = pk + PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N; - unsigned char mhash[PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_FORS_MSG_BYTES]; - unsigned char wots_pk[PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_WOTS_BYTES]; - unsigned char root[PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N]; - unsigned char leaf[PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N]; - unsigned int i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - hash_state hash_state_seeded; - - if (siglen != PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_BYTES) { - return -1; - } - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_initialize_hash_function( - &hash_state_seeded, - pub_seed, NULL); - - PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_set_type( - wots_addr, PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_set_type( - tree_addr, PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_ADDR_TYPE_HASHTREE); - PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_set_type( - wots_pk_addr, PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_ADDR_TYPE_WOTSPK); - - /* Derive the message digest and leaf index from R || PK || M. */ - /* The additional PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N is a result of the hash domain separator. */ - PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N; - - /* Layer correctly defaults to 0, so no need to set_layer_addr */ - PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_set_keypair_addr( - wots_addr, idx_leaf); - - PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_fors_pk_from_sig( - root, sig, mhash, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_FORS_BYTES; - - /* For each subtree.. */ - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_D; i++) { - PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_set_tree_addr(tree_addr, tree); - - PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_set_keypair_addr( - wots_addr, idx_leaf); - - PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_copy_keypair_addr( - wots_pk_addr, wots_addr); - - /* The WOTS public key is only correct if the signature was correct. */ - /* Initially, root is the FORS pk, but on subsequent iterations it is - the root of the subtree below the currently processed subtree. */ - PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_wots_pk_from_sig( - wots_pk, sig, root, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_WOTS_BYTES; - - /* Compute the leaf node using the WOTS public key. */ - PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_thash_WOTS_LEN( - leaf, wots_pk, pub_seed, wots_pk_addr, &hash_state_seeded); - - /* Compute the root node of this subtree. */ - PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_compute_root( - root, leaf, idx_leaf, 0, sig, PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_TREE_HEIGHT, - pub_seed, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_TREE_HEIGHT * PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_TREE_HEIGHT; - } - - /* Check if the root node equals the root node in the public key. */ - if (memcmp(root, pub_root, PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N) != 0) { - return -1; - } - - return 0; -} - - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - size_t siglen; - - PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_crypto_sign_signature( - sm, &siglen, m, mlen, sk); - - memmove(sm + PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_BYTES, m, mlen); - *smlen = siglen + mlen; - - return 0; -} - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk) { - - // guarantee alignment of pk - union { - __m128 *_x; - uint8_t pk[PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_CRYPTO_PUBLICKEYBYTES]; - } aligned_pk; - memcpy(aligned_pk.pk, pk, PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_CRYPTO_PUBLICKEYBYTES); - pk = aligned_pk.pk; - - - /* The API caller does not necessarily know what size a signature should be - but SPHINCS+ signatures are always exactly PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_BYTES. */ - if (smlen < PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_BYTES) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - *mlen = smlen - PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_BYTES; - - if (PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_crypto_sign_verify( - sm, PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_BYTES, sm + PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_BYTES, *mlen, pk)) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - /* If verification was successful, move the message to the right place. */ - memmove(m, sm + PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_BYTES, *mlen); - - return 0; -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_avx2/thash.h b/src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_avx2/thash.h deleted file mode 100644 index 4a41e341a6..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_avx2/thash.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_THASH_H -#define PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_THASH_H - -#include "hash_state.h" - -#include - -void PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_avx2/thash_shake256_robust.c b/src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_avx2/thash_shake256_robust.c deleted file mode 100644 index 812e78d029..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_avx2/thash_shake256_robust.c +++ /dev/null @@ -1,81 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "thash.h" - -#include "fips202.h" - -/** - * Takes an array of inblocks concatenated arrays of PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N bytes. - */ -static void PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_thash( - unsigned char *out, unsigned char *buf, - const unsigned char *in, unsigned int inblocks, - const unsigned char *pub_seed, uint32_t addr[8]) { - - unsigned char *bitmask = buf + PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_ADDR_BYTES; - unsigned int i; - - memcpy(buf, pub_seed, PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N); - PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_addr_to_bytes(buf + PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N, addr); - - shake256(bitmask, inblocks * PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N, buf, PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_ADDR_BYTES); - - for (i = 0; i < inblocks * PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N; i++) { - buf[PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_ADDR_BYTES + i] = in[i] ^ bitmask[i]; - } - - shake256(out, PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N, buf, PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N); -} - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_ADDR_BYTES + 1 * PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N]; - PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_thash( - out, buf, in, 1, pub_seed, addr); - - (void)hash_state_seeded; /* Avoid unused parameter warning. */ -} - -void PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_ADDR_BYTES + 2 * PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N]; - PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_thash( - out, buf, in, 2, pub_seed, addr); - - (void)hash_state_seeded; /* Avoid unused parameter warning. */ -} - -void PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_ADDR_BYTES + PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_WOTS_LEN * PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N]; - PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_thash( - out, buf, in, PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_WOTS_LEN, pub_seed, addr); - - (void)hash_state_seeded; /* Avoid unused parameter warning. */ -} - -void PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_ADDR_BYTES + PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_FORS_TREES * PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N]; - PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_thash( - out, buf, in, PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_FORS_TREES, pub_seed, addr); - - (void)hash_state_seeded; /* Avoid unused parameter warning. */ -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_avx2/thash_shake256_robustx4.c b/src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_avx2/thash_shake256_robustx4.c deleted file mode 100644 index 70f099ca74..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_avx2/thash_shake256_robustx4.c +++ /dev/null @@ -1,66 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "thashx4.h" - -#include "fips202x4.h" - -/** - * 4-way parallel version of thash; takes 4x as much input and output - */ -#define thash_variant(name, inblocks) \ - void PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_thashx4_##name(unsigned char *out0, \ - unsigned char *out1, \ - unsigned char *out2, \ - unsigned char *out3, \ - const unsigned char *in0, \ - const unsigned char *in1, \ - const unsigned char *in2, \ - const unsigned char *in3, \ - const unsigned char *pub_seed, uint32_t addrx4[4*8], \ - const hash_state *state_seeded) \ - { \ - unsigned char buf0[PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_ADDR_BYTES + (inblocks)*PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N]; \ - unsigned char buf1[PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_ADDR_BYTES + (inblocks)*PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N]; \ - unsigned char buf2[PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_ADDR_BYTES + (inblocks)*PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N]; \ - unsigned char buf3[PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_ADDR_BYTES + (inblocks)*PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N]; \ - unsigned char bitmask0[(inblocks) * PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N]; \ - unsigned char bitmask1[(inblocks) * PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N]; \ - unsigned char bitmask2[(inblocks) * PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N]; \ - unsigned char bitmask3[(inblocks) * PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N]; \ - unsigned int i; \ - \ - memcpy(buf0, pub_seed, PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N); \ - memcpy(buf1, pub_seed, PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N); \ - memcpy(buf2, pub_seed, PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N); \ - memcpy(buf3, pub_seed, PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N); \ - PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_addr_to_bytes(buf0 + PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N, addrx4 + 0*8); \ - PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_addr_to_bytes(buf1 + PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N, addrx4 + 1*8); \ - PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_addr_to_bytes(buf2 + PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N, addrx4 + 2*8); \ - PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_addr_to_bytes(buf3 + PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N, addrx4 + 3*8); \ - \ - PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_shake256x4(bitmask0, bitmask1, bitmask2, bitmask3, (inblocks) * PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N, \ - buf0, buf1, buf2, buf3, PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_ADDR_BYTES); \ - \ - for (i = 0; i < (inblocks) * PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N; i++) { \ - buf0[PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_ADDR_BYTES + i] = in0[i] ^ bitmask0[i]; \ - buf1[PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_ADDR_BYTES + i] = in1[i] ^ bitmask1[i]; \ - buf2[PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_ADDR_BYTES + i] = in2[i] ^ bitmask2[i]; \ - buf3[PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_ADDR_BYTES + i] = in3[i] ^ bitmask3[i]; \ - } \ - \ - PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_shake256x4( \ - out0, out1, out2, out3, PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N, \ - buf0, buf1, buf2, buf3, PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_ADDR_BYTES + (inblocks)*PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N); \ - \ - /* avoid unused parameter warning */ \ - (void)state_seeded; \ - } - - -thash_variant(1, 1) -thash_variant(2, 2) -thash_variant(WOTS_LEN, PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_WOTS_LEN) -thash_variant(FORS_TREES, PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_FORS_TREES) diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_avx2/thashx4.h b/src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_avx2/thashx4.h deleted file mode 100644 index 5f4e6cb133..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_avx2/thashx4.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_THASHX4_H -#define PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_THASHX4_H - -#include - -#include "hash_state.h" - -#define thashx4_header(inblocks) \ - void PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_thashx4_##inblocks(unsigned char *out0, \ - unsigned char *out1, \ - unsigned char *out2, \ - unsigned char *out3, \ - const unsigned char *in0, \ - const unsigned char *in1, \ - const unsigned char *in2, \ - const unsigned char *in3, \ - const unsigned char *pub_seed, uint32_t addrx4[4*8], \ - const hash_state *state_seeded) - -thashx4_header(1); -thashx4_header(2); -thashx4_header(WOTS_LEN); -thashx4_header(FORS_TREES); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_avx2/utils.c b/src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_avx2/utils.c deleted file mode 100644 index 228b7164d7..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_avx2/utils.c +++ /dev/null @@ -1,199 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "hash_state.h" -#include "params.h" -#include "thash.h" -#include "utils.h" - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in) { - - /* Iterate over out in decreasing order, for big-endianness. */ - for (size_t i = outlen; i > 0; i--) { - out[i - 1] = in & 0xff; - in = in >> 8; - } -} - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_bytes_to_ull( - const unsigned char *in, size_t inlen) { - unsigned long long retval = 0; - - for (size_t i = 0; i < inlen; i++) { - retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); - } - return retval; -} - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - uint32_t i; - unsigned char buffer[2 * PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N]; - - /* If leaf_idx is odd (last bit = 1), current path element is a right child - and auth_path has to go left. Otherwise it is the other way around. */ - if (leaf_idx & 1) { - memcpy(buffer + PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N, leaf, PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N); - } else { - memcpy(buffer, leaf, PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N); - memcpy(buffer + PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N, auth_path, PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N); - } - auth_path += PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N; - - for (i = 0; i < tree_height - 1; i++) { - leaf_idx >>= 1; - idx_offset >>= 1; - /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_set_tree_height(addr, i + 1); - PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_set_tree_index( - addr, leaf_idx + idx_offset); - - /* Pick the right or left neighbor, depending on parity of the node. */ - if (leaf_idx & 1) { - PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_thash_2( - buffer + PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N); - } else { - PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_thash_2( - buffer, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer + PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N, auth_path, PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N); - } - auth_path += PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N; - } - - /* The last iteration is exceptional; we do not copy an auth_path node. */ - leaf_idx >>= 1; - idx_offset >>= 1; - PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_set_tree_height(addr, tree_height); - PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_set_tree_index( - addr, leaf_idx + idx_offset); - PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_thash_2( - root, buffer, pub_seed, addr, hash_state_seeded); -} - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -static void PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_treehash( - unsigned char *root, unsigned char *auth_path, - unsigned char *stack, unsigned int *heights, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - - unsigned int offset = 0; - uint32_t idx; - uint32_t tree_idx; - - for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { - /* Add the next leaf node to the stack. */ - gen_leaf(stack + offset * PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N, - sk_seed, pub_seed, idx + idx_offset, tree_addr, - hash_state_seeded); - offset++; - heights[offset - 1] = 0; - - /* If this is a node we need for the auth path.. */ - if ((leaf_idx ^ 0x1) == idx) { - memcpy(auth_path, stack + (offset - 1)*PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N, PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N); - } - - /* While the top-most nodes are of equal height.. */ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { - /* Compute index of the new node, in the next layer. */ - tree_idx = (idx >> (heights[offset - 1] + 1)); - - /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_set_tree_height( - tree_addr, heights[offset - 1] + 1); - PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_set_tree_index( - tree_addr, tree_idx + (idx_offset >> (heights[offset - 1] + 1))); - /* Hash the top-most nodes from the stack together. */ - PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_thash_2( - stack + (offset - 2)*PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N, stack + (offset - 2)*PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N, - pub_seed, tree_addr, hash_state_seeded); - offset--; - /* Note that the top-most node is now one layer higher. */ - heights[offset - 1]++; - - /* If this is a node we need for the auth path.. */ - if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_path + heights[offset - 1]*PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N, - stack + (offset - 1)*PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N, PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N); - } - } - } - memcpy(root, stack, PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N); -} - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_FORS_HEIGHT + 1)*PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N]; - unsigned int heights[PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_FORS_HEIGHT + 1]; - - PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_FORS_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_TREE_HEIGHT + 1)*PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N]; - unsigned int heights[PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_TREE_HEIGHT + 1]; - - PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_TREE_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_avx2/utils.h b/src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_avx2/utils.h deleted file mode 100644 index 4e3bcfa4ac..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_avx2/utils.h +++ /dev/null @@ -1,64 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_UTILS_H -#define PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_UTILS_H - -#include "hash_state.h" -#include "params.h" -#include -#include - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in); - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_bytes_to_ull( - const unsigned char *in, size_t inlen); - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -void PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_avx2/utilsx4.c b/src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_avx2/utilsx4.c deleted file mode 100644 index 34b81f3cea..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_avx2/utilsx4.c +++ /dev/null @@ -1,98 +0,0 @@ -#include "address.h" -#include "params.h" -#include "thashx4.h" -#include "utils.h" -#include "utilsx4.h" - -#include - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -#define treehashx4_variant(name, tree_height) \ - void PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_treehashx4_##name( \ - unsigned char *rootx4, unsigned char *auth_pathx4, const unsigned char *sk_seed, \ - const unsigned char *pub_seed, const uint32_t leaf_idx[4], uint32_t idx_offset[4], \ - void (*gen_leafx4)(unsigned char * /* leaf0 */, unsigned char * /* leaf1 */, \ - unsigned char * /* leaf2 */, unsigned char * /* leaf3 */, \ - const unsigned char * /* sk_seed */, \ - const unsigned char * /* pub_seed */, uint32_t /* addr_idx0 */, \ - uint32_t /* addr_idx1 */, uint32_t /* addr_idx2 */, \ - uint32_t /* addr_idx3 */, const uint32_t[8] /* tree_addr */, \ - const hash_state * /* state_seeded */), \ - uint32_t tree_addrx4[4 * 8], const hash_state *state_seeded) { \ - unsigned char stackx4[4 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N]; \ - unsigned int heights[(tree_height) + 1]; \ - unsigned int offset = 0; \ - uint32_t idx; \ - uint32_t tree_idx; \ - unsigned int j; \ - \ - for (idx = 0; idx < (uint32_t)(1 << (tree_height)); idx++) { \ - /* Add the next leaf node to the stack. */ \ - gen_leafx4(stackx4 + 0 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N + offset * PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N, \ - stackx4 + 1 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N + offset * PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N, \ - stackx4 + 2 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N + offset * PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N, \ - stackx4 + 3 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N + offset * PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N, sk_seed, \ - pub_seed, idx + idx_offset[0], idx + idx_offset[1], idx + idx_offset[2], \ - idx + idx_offset[3], tree_addrx4, state_seeded); \ - offset++; \ - heights[offset - 1] = 0; \ - \ - /* If this is a node we need for the auth path.. */ \ - for (j = 0; j < 4; j++) { \ - if ((leaf_idx[j] ^ 0x1) == idx) { \ - memcpy(auth_pathx4 + j * (tree_height)*PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N, \ - stackx4 + j * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N + (offset - 1) * PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N, \ - PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N); \ - } \ - } \ - \ - /* While the top-most nodes are of equal height.. */ \ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { \ - /* Compute index of the new node, in the next layer. */ \ - tree_idx = (idx >> (heights[offset - 1] + 1)); \ - \ - /* Set the address of the node we're creating. */ \ - for (j = 0; j < 4; j++) { \ - PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_set_tree_height(tree_addrx4 + j * 8, heights[offset - 1] + 1); \ - PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_set_tree_index(tree_addrx4 + j * 8, \ - tree_idx + (idx_offset[j] >> (heights[offset - 1] + 1))); \ - } \ - /* Hash the top-most nodes from the stack together. */ \ - PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_thashx4_2(stackx4 + 0 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N + (offset - 2) * PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N, \ - stackx4 + 1 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N + (offset - 2) * PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N, \ - stackx4 + 2 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N + (offset - 2) * PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N, \ - stackx4 + 3 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N + (offset - 2) * PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N, \ - stackx4 + 0 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N + (offset - 2) * PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N, \ - stackx4 + 1 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N + (offset - 2) * PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N, \ - stackx4 + 2 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N + (offset - 2) * PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N, \ - stackx4 + 3 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N + (offset - 2) * PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N, \ - pub_seed, tree_addrx4, state_seeded); \ - offset--; \ - /* Note that the top-most node is now one layer higher. */ \ - heights[offset - 1]++; \ - \ - /* If this is a node we need for the auth path.. */ \ - for (j = 0; j < 4; j++) { \ - if (((leaf_idx[j] >> heights[offset - 1]) ^ 0x1) == tree_idx) { \ - memcpy(auth_pathx4 + j * (tree_height)*PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N + \ - heights[offset - 1] * PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N, \ - stackx4 + j * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N + (offset - 1) * PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N, \ - PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N); \ - } \ - } \ - } \ - } \ - \ - for (j = 0; j < 4; j++) { \ - memcpy(rootx4 + j * PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N, stackx4 + j * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N, PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N); \ - } \ - } - -treehashx4_variant(FORS_HEIGHT, PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_FORS_HEIGHT) diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_avx2/utilsx4.h b/src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_avx2/utilsx4.h deleted file mode 100644 index 3fa1083515..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_avx2/utilsx4.h +++ /dev/null @@ -1,38 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_UTILSX4_H -#define PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_UTILSX4_H - -#include "hash_state.h" -#include "params.h" - -#include - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -void PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_treehashx4_FORS_HEIGHT(unsigned char *rootx4, - unsigned char *auth_pathx4, - const unsigned char *sk_seed, - const unsigned char *pub_seed, - const uint32_t leaf_idx[4], - uint32_t idx_offset[4], - void (*gen_leafx4)(unsigned char * /* leaf0 */, - unsigned char * /* leaf1 */, - unsigned char * /* leaf2 */, - unsigned char * /* leaf3 */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx0 */, - uint32_t /* addr_idx1 */, - uint32_t /* addr_idx2 */, - uint32_t /* addr_idx3 */, - const uint32_t[8] /* tree_addr */, - const hash_state * /* state_seeded */), - uint32_t tree_addrx4[4 * 8], - const hash_state *state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_avx2/wots.c b/src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_avx2/wots.c deleted file mode 100644 index d0a51224ca..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_avx2/wots.c +++ /dev/null @@ -1,240 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "hash_state.h" -#include "hashx4.h" -#include "params.h" -#include "thash.h" -#include "thashx4.h" -#include "utils.h" -#include "wots.h" - -// TODO clarify address expectations, and make them more uniform. -// TODO i.e. do we expect types to be set already? -// TODO and do we expect modifications or copies? - -/** - * Computes the starting value for a chain, i.e. the secret key. - * Expects the address to be complete up to the chain address. - */ -static void wots_gen_sk(unsigned char *sk, const unsigned char *sk_seed, - uint32_t wots_addr[8], const hash_state *state_seeded) { - /* Make sure that the hash address is actually zeroed. */ - PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_set_hash_addr(wots_addr, 0); - - /* Generate sk element. */ - PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_prf_addr(sk, sk_seed, wots_addr, state_seeded); -} - -/** - * 4-way parallel version of wots_gen_sk; expects 4x as much space in sk - */ -static void wots_gen_skx4(unsigned char *skx4, const unsigned char *sk_seed, - uint32_t wots_addrx4[4 * 8], const hash_state *state_seeded) { - unsigned int j; - - /* Make sure that the hash address is actually zeroed. */ - for (j = 0; j < 4; j++) { - PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_set_hash_addr(wots_addrx4 + j * 8, 0); - } - - /* Generate sk element. */ - PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_prf_addrx4(skx4 + 0 * PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N, - skx4 + 1 * PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N, - skx4 + 2 * PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N, - skx4 + 3 * PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N, - sk_seed, wots_addrx4, - state_seeded); -} - -/** - * Computes the chaining function. - * out and in have to be n-byte arrays. - * - * Interprets in as start-th value of the chain. - * addr has to contain the address of the chain. - */ -static void gen_chain(unsigned char *out, const unsigned char *in, - unsigned int start, unsigned int steps, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *state_seeded) { - uint32_t i; - - /* Initialize out with the value at position 'start'. */ - memcpy(out, in, PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N); - - /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_WOTS_W; i++) { - PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_set_hash_addr(addr, i); - PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_thash_1(out, out, pub_seed, addr, state_seeded); - } -} - -/** - * 4-way parallel version of gen_chain; expects 4x as much space in out, and - * 4x as much space in inx4. Assumes start and step identical across chains. - */ -static void gen_chainx4(unsigned char *outx4, const unsigned char *inx4, - unsigned int start, unsigned int steps, - const unsigned char *pub_seed, uint32_t addrx4[4 * 8], - const hash_state *state_seeded) { - uint32_t i; - unsigned int j; - - /* Initialize outx4 with the value at position 'start'. */ - memcpy(outx4, inx4, 4 * PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N); - - /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_WOTS_W; i++) { - for (j = 0; j < 4; j++) { - PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_set_hash_addr(addrx4 + j * 8, i); - } - PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_thashx4_1(outx4 + 0 * PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N, - outx4 + 1 * PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N, - outx4 + 2 * PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N, - outx4 + 3 * PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N, - outx4 + 0 * PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N, - outx4 + 1 * PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N, - outx4 + 2 * PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N, - outx4 + 3 * PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N, - pub_seed, addrx4, - state_seeded); - } -} - -/** - * base_w algorithm as described in draft. - * Interprets an array of bytes as integers in base w. - * This only works when log_w is a divisor of 8. - */ -static void base_w(unsigned int *output, const int out_len, const unsigned char *input) { - int in = 0; - int out = 0; - unsigned char total = 0; - int bits = 0; - int consumed; - - for (consumed = 0; consumed < out_len; consumed++) { - if (bits == 0) { - total = input[in]; - in++; - bits += 8; - } - bits -= PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_WOTS_LOGW; - output[out] = (unsigned int)(total >> bits) & (PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_WOTS_W - 1); - out++; - } -} - -/* Computes the WOTS+ checksum over a message (in base_w). */ -static void wots_checksum(unsigned int *csum_base_w, const unsigned int *msg_base_w) { - unsigned int csum = 0; - unsigned char csum_bytes[(PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_WOTS_LEN2 * PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_WOTS_LOGW + 7) / 8]; - unsigned int i; - - /* Compute checksum. */ - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_WOTS_LEN1; i++) { - csum += PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_WOTS_W - 1 - msg_base_w[i]; - } - - /* Convert checksum to base_w. */ - /* Make sure expected empty zero bits are the least significant bits. */ - csum = csum << (8 - ((PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_WOTS_LEN2 * PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_WOTS_LOGW) % 8)); - PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); - base_w(csum_base_w, PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_WOTS_LEN2, csum_bytes); -} - -/* Takes a message and derives the matching chain lengths. */ -static void chain_lengths(unsigned int *lengths, const unsigned char *msg) { - base_w(lengths, PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_WOTS_LEN1, msg); - wots_checksum(lengths + PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_WOTS_LEN1, lengths); -} - -/** - * WOTS key generation. Takes a 32 byte sk_seed, expands it to WOTS private key - * elements and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_wots_gen_pk(unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *state_seeded) { - uint32_t i; - unsigned int j; - - uint32_t addrx4[4 * 8]; - unsigned char pkbuf[4 * PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N]; - - for (j = 0; j < 4; j++) { - memcpy(addrx4 + j * 8, addr, sizeof(uint32_t) * 8); - } - - /* The last iteration typically does not have complete set of 4 chains, - but because we use pkbuf, this is not an issue -- we still do as many - in parallel as possible. */ - for (i = 0; i < ((PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_WOTS_LEN + 3) & ~0x3); i += 4) { - for (j = 0; j < 4; j++) { - PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_set_chain_addr(addrx4 + j * 8, i + j); - } - wots_gen_skx4(pkbuf, sk_seed, addrx4, state_seeded); - gen_chainx4(pkbuf, pkbuf, 0, PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_WOTS_W - 1, pub_seed, addrx4, state_seeded); - for (j = 0; j < 4; j++) { - if (i + j < PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_WOTS_LEN) { - memcpy(pk + (i + j)*PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N, pkbuf + j * PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N, PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N); - } - } - } - - // Get rid of unused argument variable. - (void)state_seeded; -} - -/** - * Takes a n-byte message and the 32-byte sk_see to compute a signature 'sig'. - */ -void PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_wots_sign(unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_WOTS_LEN; i++) { - PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_set_chain_addr(addr, i); - wots_gen_sk(sig + i * PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N, sk_seed, addr, state_seeded); - gen_chain(sig + i * PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N, sig + i * PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N, 0, lengths[i], pub_seed, addr, state_seeded); - } - - // avoid unused argument - (void)state_seeded; -} - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_WOTS_LEN; i++) { - PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_set_chain_addr(addr, i); - gen_chain(pk + i * PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N, sig + i * PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_N, - lengths[i], PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_WOTS_W - 1 - lengths[i], pub_seed, addr, - state_seeded); - } - - // avoid unused argument - (void)state_seeded; -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_avx2/wots.h b/src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_avx2/wots.h deleted file mode 100644 index 40c0093ca4..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_avx2/wots.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_WOTS_H -#define PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_WOTS_H - -#include "hash_state.h" -#include "params.h" -#include - -/** - * WOTS key generation. Takes a 32 byte seed for the private key, expands it to - * a full WOTS private key and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_wots_gen_pk( - unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -/** - * Takes a n-byte message and the 32-byte seed for the private key to compute a - * signature that is placed at 'sig'. - */ -void PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_wots_sign( - unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *hash_state_seeded); - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_wots_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_clean/LICENSE b/src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_clean/LICENSE deleted file mode 100644 index 670154e353..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_clean/LICENSE +++ /dev/null @@ -1,116 +0,0 @@ -CC0 1.0 Universal - -Statement of Purpose - -The laws of most jurisdictions throughout the world automatically confer -exclusive Copyright and Related Rights (defined below) upon the creator and -subsequent owner(s) (each and all, an "owner") of an original work of -authorship and/or a database (each, a "Work"). - -Certain owners wish to permanently relinquish those rights to a Work for the -purpose of contributing to a commons of creative, cultural and scientific -works ("Commons") that the public can reliably and without fear of later -claims of infringement build upon, modify, incorporate in other works, reuse -and redistribute as freely as possible in any form whatsoever and for any -purposes, including without limitation commercial purposes. These owners may -contribute to the Commons to promote the ideal of a free culture and the -further production of creative, cultural and scientific works, or to gain -reputation or greater distribution for their Work in part through the use and -efforts of others. - -For these and/or other purposes and motivations, and without any expectation -of additional consideration or compensation, the person associating CC0 with a -Work (the "Affirmer"), to the extent that he or she is an owner of Copyright -and Related Rights in the Work, voluntarily elects to apply CC0 to the Work -and publicly distribute the Work under its terms, with knowledge of his or her -Copyright and Related Rights in the Work and the meaning and intended legal -effect of CC0 on those rights. - -1. Copyright and Related Rights. A Work made available under CC0 may be -protected by copyright and related or neighboring rights ("Copyright and -Related Rights"). Copyright and Related Rights include, but are not limited -to, the following: - - i. the right to reproduce, adapt, distribute, perform, display, communicate, - and translate a Work; - - ii. moral rights retained by the original author(s) and/or performer(s); - - iii. publicity and privacy rights pertaining to a person's image or likeness - depicted in a Work; - - iv. rights protecting against unfair competition in regards to a Work, - subject to the limitations in paragraph 4(a), below; - - v. rights protecting the extraction, dissemination, use and reuse of data in - a Work; - - vi. database rights (such as those arising under Directive 96/9/EC of the - European Parliament and of the Council of 11 March 1996 on the legal - protection of databases, and under any national implementation thereof, - including any amended or successor version of such directive); and - - vii. other similar, equivalent or corresponding rights throughout the world - based on applicable law or treaty, and any national implementations thereof. - -2. Waiver. To the greatest extent permitted by, but not in contravention of, -applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and -unconditionally waives, abandons, and surrenders all of Affirmer's Copyright -and Related Rights and associated claims and causes of action, whether now -known or unknown (including existing as well as future claims and causes of -action), in the Work (i) in all territories worldwide, (ii) for the maximum -duration provided by applicable law or treaty (including future time -extensions), (iii) in any current or future medium and for any number of -copies, and (iv) for any purpose whatsoever, including without limitation -commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes -the Waiver for the benefit of each member of the public at large and to the -detriment of Affirmer's heirs and successors, fully intending that such Waiver -shall not be subject to revocation, rescission, cancellation, termination, or -any other legal or equitable action to disrupt the quiet enjoyment of the Work -by the public as contemplated by Affirmer's express Statement of Purpose. - -3. Public License Fallback. Should any part of the Waiver for any reason be -judged legally invalid or ineffective under applicable law, then the Waiver -shall be preserved to the maximum extent permitted taking into account -Affirmer's express Statement of Purpose. In addition, to the extent the Waiver -is so judged Affirmer hereby grants to each affected person a royalty-free, -non transferable, non sublicensable, non exclusive, irrevocable and -unconditional license to exercise Affirmer's Copyright and Related Rights in -the Work (i) in all territories worldwide, (ii) for the maximum duration -provided by applicable law or treaty (including future time extensions), (iii) -in any current or future medium and for any number of copies, and (iv) for any -purpose whatsoever, including without limitation commercial, advertising or -promotional purposes (the "License"). The License shall be deemed effective as -of the date CC0 was applied by Affirmer to the Work. Should any part of the -License for any reason be judged legally invalid or ineffective under -applicable law, such partial invalidity or ineffectiveness shall not -invalidate the remainder of the License, and in such case Affirmer hereby -affirms that he or she will not (i) exercise any of his or her remaining -Copyright and Related Rights in the Work or (ii) assert any associated claims -and causes of action with respect to the Work, in either case contrary to -Affirmer's express Statement of Purpose. - -4. Limitations and Disclaimers. - - a. No trademark or patent rights held by Affirmer are waived, abandoned, - surrendered, licensed or otherwise affected by this document. - - b. Affirmer offers the Work as-is and makes no representations or warranties - of any kind concerning the Work, express, implied, statutory or otherwise, - including without limitation warranties of title, merchantability, fitness - for a particular purpose, non infringement, or the absence of latent or - other defects, accuracy, or the present or absence of errors, whether or not - discoverable, all to the greatest extent permissible under applicable law. - - c. Affirmer disclaims responsibility for clearing rights of other persons - that may apply to the Work or any use thereof, including without limitation - any person's Copyright and Related Rights in the Work. Further, Affirmer - disclaims responsibility for obtaining any necessary consents, permissions - or other rights required for any use of the Work. - - d. Affirmer understands and acknowledges that Creative Commons is not a - party to this document and has no duty or obligation with respect to this - CC0 or use of the Work. - -For more information, please see - diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_clean/address.c b/src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_clean/address.c deleted file mode 100644 index 1d6afdd87b..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_clean/address.c +++ /dev/null @@ -1,78 +0,0 @@ -#include - -#include "address.h" -#include "params.h" -#include "utils.h" - -void PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]) { - int i; - - for (i = 0; i < 8; i++) { - PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_ull_to_bytes( - bytes + i * 4, 4, addr[i]); - } -} - -void PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_set_layer_addr( - uint32_t addr[8], uint32_t layer) { - addr[0] = layer; -} - -void PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_set_tree_addr( - uint32_t addr[8], uint64_t tree) { - addr[1] = 0; - addr[2] = (uint32_t) (tree >> 32); - addr[3] = (uint32_t) tree; -} - -void PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_set_type( - uint32_t addr[8], uint32_t type) { - addr[4] = type; -} - -void PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; -} - -/* These functions are used for OTS addresses. */ - -void PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_set_keypair_addr( - uint32_t addr[8], uint32_t keypair) { - addr[5] = keypair; -} - -void PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; - out[5] = in[5]; -} - -void PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_set_chain_addr( - uint32_t addr[8], uint32_t chain) { - addr[6] = chain; -} - -void PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_set_hash_addr( - uint32_t addr[8], uint32_t hash) { - addr[7] = hash; -} - -/* These functions are used for all hash tree addresses (including FORS). */ - -void PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_set_tree_height( - uint32_t addr[8], uint32_t tree_height) { - addr[6] = tree_height; -} - -void PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_set_tree_index( - uint32_t addr[8], uint32_t tree_index) { - addr[7] = tree_index; -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_clean/address.h b/src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_clean/address.h deleted file mode 100644 index 2d3ec40c1c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_clean/address.h +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_ADDRESS_H -#define PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_ADDRESS_H - -#include - -#define PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_ADDR_TYPE_WOTS 0 -#define PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_ADDR_TYPE_WOTSPK 1 -#define PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_ADDR_TYPE_HASHTREE 2 -#define PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_ADDR_TYPE_FORSTREE 3 -#define PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_ADDR_TYPE_FORSPK 4 - -void PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]); - -void PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_set_layer_addr( - uint32_t addr[8], uint32_t layer); - -void PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_set_tree_addr( - uint32_t addr[8], uint64_t tree); - -void PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_set_type( - uint32_t addr[8], uint32_t type); - -/* Copies the layer and tree part of one address into the other */ -void PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for WOTS and FORS addresses. */ - -void PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_set_keypair_addr( - uint32_t addr[8], uint32_t keypair); - -void PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_set_chain_addr( - uint32_t addr[8], uint32_t chain); - -void PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_set_hash_addr( - uint32_t addr[8], uint32_t hash); - -void PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for all hash tree addresses (including FORS). */ - -void PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_set_tree_height( - uint32_t addr[8], uint32_t tree_height); - -void PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_set_tree_index( - uint32_t addr[8], uint32_t tree_index); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_clean/api.h b/src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_clean/api.h deleted file mode 100644 index 4b60c94023..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_clean/api.h +++ /dev/null @@ -1,81 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_API_H -#define PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_API_H - -#include -#include - - - -#define PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_CRYPTO_ALGNAME "SPHINCS+" - -#define PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_CRYPTO_SECRETKEYBYTES 96 -#define PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_CRYPTO_PUBLICKEYBYTES 48 -#define PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_CRYPTO_BYTES 16224 -#define PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_CRYPTO_SEEDBYTES 72 - - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_clean/fors.c b/src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_clean/fors.c deleted file mode 100644 index 2873041d01..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_clean/fors.c +++ /dev/null @@ -1,161 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "fors.h" -#include "hash.h" -#include "hash_state.h" -#include "thash.h" -#include "utils.h" - -static void fors_gen_sk(unsigned char *sk, const unsigned char *sk_seed, - uint32_t fors_leaf_addr[8], const hash_state *hash_state_seeded) { - PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_prf_addr( - sk, sk_seed, fors_leaf_addr, hash_state_seeded); -} - -static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, - const unsigned char *pub_seed, - uint32_t fors_leaf_addr[8], - const hash_state *hash_state_seeded) { - PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_thash_1( - leaf, sk, pub_seed, fors_leaf_addr, hash_state_seeded); -} - -static void fors_gen_leaf(unsigned char *leaf, const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx, const uint32_t fors_tree_addr[8], - const hash_state *hash_state_seeded) { - uint32_t fors_leaf_addr[8] = {0}; - - /* Only copy the parts that must be kept in fors_leaf_addr. */ - PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_copy_keypair_addr( - fors_leaf_addr, fors_tree_addr); - PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_set_type( - fors_leaf_addr, PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_set_tree_index( - fors_leaf_addr, addr_idx); - - fors_gen_sk(leaf, sk_seed, fors_leaf_addr, hash_state_seeded); - fors_sk_to_leaf(leaf, leaf, pub_seed, fors_leaf_addr, hash_state_seeded); -} - -/** - * Interprets m as PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_FORS_HEIGHT-bit unsigned integers. - * Assumes m contains at least PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_FORS_TREES bits. - * Assumes indices has space for PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_FORS_TREES integers. - */ -static void message_to_indices(uint32_t *indices, const unsigned char *m) { - unsigned int i, j; - unsigned int offset = 0; - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_FORS_TREES; i++) { - indices[i] = 0; - for (j = 0; j < PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_FORS_HEIGHT; j++) { - indices[i] ^= (((uint32_t)m[offset >> 3] >> (offset & 0x7)) & 0x1) << j; - offset++; - } - } -} - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_fors_sign( - unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *hash_state_seeded) { - uint32_t indices[PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_FORS_TREES]; - unsigned char roots[PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_FORS_TREES * PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_N]; - uint32_t fors_tree_addr[8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_copy_keypair_addr( - fors_tree_addr, fors_addr); - PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_copy_keypair_addr( - fors_pk_addr, fors_addr); - - PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_set_type( - fors_tree_addr, PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_set_type( - fors_pk_addr, PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_FORS_TREES; i++) { - idx_offset = i * (1 << PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_FORS_HEIGHT); - - PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_set_tree_height( - fors_tree_addr, 0); - PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_set_tree_index( - fors_tree_addr, indices[i] + idx_offset); - - /* Include the secret key part that produces the selected leaf node. */ - fors_gen_sk(sig, sk_seed, fors_tree_addr, hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_N; - - /* Compute the authentication path for this leaf node. */ - PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_treehash_FORS_HEIGHT( - roots + i * PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_N, sig, sk_seed, pub_seed, - indices[i], idx_offset, fors_gen_leaf, fors_tree_addr, - hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_N * PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_thash_FORS_TREES( - pk, roots, pub_seed, fors_pk_addr, hash_state_seeded); -} - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_fors_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, const uint32_t fors_addr[8], - const hash_state *hash_state_seeded) { - uint32_t indices[PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_FORS_TREES]; - unsigned char roots[PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_FORS_TREES * PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_N]; - unsigned char leaf[PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_N]; - uint32_t fors_tree_addr[8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_copy_keypair_addr(fors_tree_addr, fors_addr); - PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_copy_keypair_addr(fors_pk_addr, fors_addr); - - PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_set_type(fors_tree_addr, PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_set_type(fors_pk_addr, PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_FORS_TREES; i++) { - idx_offset = i * (1 << PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_FORS_HEIGHT); - - PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_set_tree_height(fors_tree_addr, 0); - PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Derive the leaf from the included secret key part. */ - fors_sk_to_leaf(leaf, sig, pub_seed, fors_tree_addr, hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_N; - - /* Derive the corresponding root node of this tree. */ - PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_compute_root(roots + i * PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_N, leaf, indices[i], idx_offset, sig, - PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_FORS_HEIGHT, pub_seed, fors_tree_addr, hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_N * PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_thash_FORS_TREES(pk, roots, pub_seed, fors_pk_addr, hash_state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_clean/fors.h b/src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_clean/fors.h deleted file mode 100644 index 55c308a5fb..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_clean/fors.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_FORS_H -#define PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_FORS_H - -#include - -#include "hash_state.h" -#include "params.h" - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_fors_sign( - unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *hash_state_seeded); - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_fors_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, const uint32_t fors_addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_clean/hash.h b/src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_clean/hash.h deleted file mode 100644 index 1fb4ccb246..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_clean/hash.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_HASH_H -#define PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_HASH_H - -#include "hash_state.h" - -#include -#include - -void PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_initialize_hash_function( - hash_state *hash_state_seeded, - const unsigned char *pub_seed, const unsigned char *sk_seed); - -void PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_destroy_hash_function(hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_clean/hash_shake256.c b/src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_clean/hash_shake256.c deleted file mode 100644 index facef0b492..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_clean/hash_shake256.c +++ /dev/null @@ -1,106 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "utils.h" - -#include "fips202.h" - -/* For SHAKE256, there is no immediate reason to initialize at the start, - so this function is an empty operation. */ -void PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_initialize_hash_function( - hash_state *hash_state_seeded, // NOLINT(readability-non-const-parameter) - const unsigned char *pub_seed, const unsigned char *sk_seed) { - (void)hash_state_seeded; /* Suppress an 'unused parameter' warning. */ - (void)pub_seed; /* Suppress an 'unused parameter' warning. */ - (void)sk_seed; /* Suppress an 'unused parameter' warning. */ -} - -/* This is not necessary for SHAKE256, so we don't do anything */ -void PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_destroy_hash_function( - hash_state *hash_state_seeded) { // NOLINT(readability-non-const-parameter) - (void)hash_state_seeded; -} - -/* - * Computes PRF(key, addr), given a secret key of PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_N bytes and an address - */ -void PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded) { - unsigned char buf[PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_N + PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_ADDR_BYTES]; - - memcpy(buf, key, PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_N); - PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_addr_to_bytes(buf + PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_N, addr); - - shake256(out, PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_N, buf, PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_N + PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_ADDR_BYTES); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} - -/** - * Computes the message-dependent randomness R, using a secret seed and an - * optional randomization value as well as the message. - */ -void PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded) { - shake256incctx state; - - shake256_inc_init(&state); - shake256_inc_absorb(&state, sk_prf, PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_N); - shake256_inc_absorb(&state, optrand, PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_N); - shake256_inc_absorb(&state, m, mlen); - shake256_inc_finalize(&state); - shake256_inc_squeeze(R, PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_N, &state); - shake256_inc_ctx_release(&state); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} - -/** - * Computes the message hash using R, the public key, and the message. - * Outputs the message digest and the index of the leaf. The index is split in - * the tree index and the leaf index, for convenient copying to an address. - */ -void PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded) { -#define PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_TREE_BITS (PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_TREE_HEIGHT * (PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_D - 1)) -#define PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_TREE_BYTES ((PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_TREE_BITS + 7) / 8) -#define PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_LEAF_BITS PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_TREE_HEIGHT -#define PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_LEAF_BYTES ((PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_LEAF_BITS + 7) / 8) -#define PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_DGST_BYTES (PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_FORS_MSG_BYTES + PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_TREE_BYTES + PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_LEAF_BYTES) - - unsigned char buf[PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_DGST_BYTES]; - unsigned char *bufp = buf; - shake256incctx state; - - shake256_inc_init(&state); - shake256_inc_absorb(&state, R, PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_N); - shake256_inc_absorb(&state, pk, PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_PK_BYTES); - shake256_inc_absorb(&state, m, mlen); - shake256_inc_finalize(&state); - shake256_inc_squeeze(buf, PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_DGST_BYTES, &state); - shake256_inc_ctx_release(&state); - - memcpy(digest, bufp, PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_FORS_MSG_BYTES); - bufp += PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_FORS_MSG_BYTES; - - *tree = PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_bytes_to_ull( - bufp, PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_TREE_BYTES); - *tree &= (~(uint64_t)0) >> (64 - PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_TREE_BITS); - bufp += PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_TREE_BYTES; - - *leaf_idx = (uint32_t)PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_bytes_to_ull( - bufp, PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_LEAF_BYTES); - *leaf_idx &= (~(uint32_t)0) >> (32 - PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_LEAF_BITS); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_clean/hash_state.h b/src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_clean/hash_state.h deleted file mode 100644 index 7d92ef872a..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_clean/hash_state.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef SPX_HASH_STATE_H -#define SPX_HASH_STATE_H - -/** - * Defines the type of the hash function state. - * - * Don't be fooled into thinking this instance of SPHINCS+ isn't stateless! - * - * From Section 7.2.2 from the SPHINCS+ round-2 specification: - * - * Each of the instances of the tweakable hash function take PK.seed as its - * first input, which is constant for a given key pair – and, thus, across - * a single signature. This leads to a lot of redundant computation. To remedy - * this, we pad PK.seed to the length of a full 64-byte SHA-256 input block. - * Because of the Merkle-Damgård construction that underlies SHA-256, this - * allows for reuse of the intermediate SHA-256 state after the initial call to - * the compression function which improves performance. - * - * We pass this hash state around in functions, because otherwise we need to - * have a global variable. - * - * SHAKE256 does not need this state. Because this implementation is generated - * from a shared code base, we still need to specify some hash_state as it is - * still passed around. We chose to use an `int` as a placeholder for this - * purpose. - */ - -#define hash_state int - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_clean/params.h b/src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_clean/params.h deleted file mode 100644 index 481b506dbd..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_clean/params.h +++ /dev/null @@ -1,53 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_PARAMS_H -#define PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_PARAMS_H - -/* Hash output length in bytes. */ -#define PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_N 24 -/* Height of the hypertree. */ -#define PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_FULL_HEIGHT 63 -/* Number of subtree layer. */ -#define PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_D 7 -/* FORS tree dimensions. */ -#define PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_FORS_HEIGHT 14 -#define PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_FORS_TREES 17 -/* Winternitz parameter, */ -#define PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_WOTS_W 16 - -/* The hash function is defined by linking a different hash.c file, as opposed - to setting a #define constant. */ - -/* For clarity */ -#define PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_ADDR_BYTES 32 - -/* WOTS parameters. */ -#define PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_WOTS_LOGW 4 - -#define PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_WOTS_LEN1 (8 * PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_N / PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_WOTS_LOGW) - -/* PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#define PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_WOTS_LEN2 3 - -#define PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_WOTS_LEN (PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_WOTS_LEN1 + PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_WOTS_LEN2) -#define PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_WOTS_BYTES (PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_WOTS_LEN * PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_N) -#define PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_WOTS_PK_BYTES PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_WOTS_BYTES - -/* Subtree size. */ -#define PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_TREE_HEIGHT (PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_FULL_HEIGHT / PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_D) - -/* FORS parameters. */ -#define PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_FORS_MSG_BYTES ((PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_FORS_TREES + 7) / 8) -#define PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_FORS_BYTES ((PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_FORS_HEIGHT + 1) * PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_FORS_TREES * PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_N) -#define PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_FORS_PK_BYTES PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_N - -/* Resulting SPX sizes. */ -#define PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_BYTES (PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_N + PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_FORS_BYTES + PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_D * PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_WOTS_BYTES +\ - PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_FULL_HEIGHT * PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_N) -#define PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_PK_BYTES (2 * PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_N) -#define PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_SK_BYTES (2 * PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_N + PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_PK_BYTES) - -/* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ -#define PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_OPTRAND_BYTES 32 - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_clean/sign.c b/src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_clean/sign.c deleted file mode 100644 index cbd71edd2a..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_clean/sign.c +++ /dev/null @@ -1,356 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "api.h" -#include "fors.h" -#include "hash.h" -#include "hash_state.h" -#include "params.h" -#include "randombytes.h" -#include "thash.h" -#include "utils.h" -#include "wots.h" - -/** - * Computes the leaf at a given address. First generates the WOTS key pair, - * then computes leaf by hashing horizontally. - */ -static void wots_gen_leaf(unsigned char *leaf, const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx, const uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - unsigned char pk[PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_WOTS_BYTES]; - uint32_t wots_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_set_type( - wots_addr, PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_set_type( - wots_pk_addr, PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_ADDR_TYPE_WOTSPK); - - PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_set_keypair_addr( - wots_addr, addr_idx); - PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_wots_gen_pk( - pk, sk_seed, pub_seed, wots_addr, hash_state_seeded); - - PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_copy_keypair_addr( - wots_pk_addr, wots_addr); - PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_thash_WOTS_LEN( - leaf, pk, pub_seed, wots_pk_addr, hash_state_seeded); -} - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_crypto_sign_secretkeybytes(void) { - return PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_CRYPTO_SECRETKEYBYTES; -} - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_crypto_sign_publickeybytes(void) { - return PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_CRYPTO_PUBLICKEYBYTES; -} - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_crypto_sign_bytes(void) { - return PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_CRYPTO_BYTES; -} - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_crypto_sign_seedbytes(void) { - return PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_CRYPTO_SEEDBYTES; -} - -/* - * Generates an SPX key pair given a seed of length - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed) { - /* We do not need the auth path in key generation, but it simplifies the - code to have just one treehash routine that computes both root and path - in one function. */ - unsigned char auth_path[PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_TREE_HEIGHT * PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_N]; - uint32_t top_tree_addr[8] = {0}; - hash_state hash_state_seeded; - - PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_set_layer_addr( - top_tree_addr, PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_D - 1); - PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_set_type( - top_tree_addr, PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_ADDR_TYPE_HASHTREE); - - /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ - memcpy(sk, seed, PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_CRYPTO_SEEDBYTES); - - memcpy(pk, sk + 2 * PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_N, PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_initialize_hash_function(&hash_state_seeded, pk, sk); - - /* Compute root node of the top-most subtree. */ - PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_treehash_TREE_HEIGHT( - sk + 3 * PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_N, auth_path, sk, sk + 2 * PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_N, 0, 0, - wots_gen_leaf, top_tree_addr, &hash_state_seeded); - - memcpy(pk + PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_N, sk + 3 * PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_N, PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_N); - - PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_destroy_hash_function(&hash_state_seeded); - return 0; -} - -/* - * Generates an SPX key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk) { - unsigned char seed[PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_CRYPTO_SEEDBYTES]; - randombytes(seed, PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_CRYPTO_SEEDBYTES); - PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_crypto_sign_seed_keypair( - pk, sk, seed); - - return 0; -} - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - const unsigned char *sk_seed = sk; - const unsigned char *sk_prf = sk + PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_N; - const unsigned char *pk = sk + 2 * PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_N; - const unsigned char *pub_seed = pk; - - unsigned char optrand[PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_N]; - unsigned char mhash[PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_FORS_MSG_BYTES]; - unsigned char root[PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_N]; - uint32_t i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - - hash_state hash_state_seeded; - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_initialize_hash_function( - &hash_state_seeded, - pub_seed, sk_seed); - - PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_set_type( - wots_addr, PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_set_type( - tree_addr, PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_ADDR_TYPE_HASHTREE); - - /* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ - randombytes(optrand, PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_N); - /* Compute the digest randomization value. */ - PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_gen_message_random( - sig, sk_prf, optrand, m, mlen, &hash_state_seeded); - - /* Derive the message digest and leaf index from R, PK and M. */ - PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_N; - - PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); - - /* Sign the message hash using FORS. */ - PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_fors_sign( - sig, root, mhash, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_FORS_BYTES; - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_D; i++) { - PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_set_tree_addr(tree_addr, tree); - - PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); - - /* Compute a WOTS signature. */ - PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_wots_sign( - sig, root, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_WOTS_BYTES; - - /* Compute the authentication path for the used WOTS leaf. */ - PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_treehash_TREE_HEIGHT( - root, sig, sk_seed, pub_seed, idx_leaf, 0, - wots_gen_leaf, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_TREE_HEIGHT * PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_TREE_HEIGHT; - } - - *siglen = PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_BYTES; - - PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_destroy_hash_function(&hash_state_seeded); - return 0; -} - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk) { - const unsigned char *pub_seed = pk; - const unsigned char *pub_root = pk + PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_N; - unsigned char mhash[PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_FORS_MSG_BYTES]; - unsigned char wots_pk[PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_WOTS_BYTES]; - unsigned char root[PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_N]; - unsigned char leaf[PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_N]; - unsigned int i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - hash_state hash_state_seeded; - - if (siglen != PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_BYTES) { - return -1; - } - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_initialize_hash_function( - &hash_state_seeded, - pub_seed, NULL); - - PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_set_type( - wots_addr, PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_set_type( - tree_addr, PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_ADDR_TYPE_HASHTREE); - PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_set_type( - wots_pk_addr, PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_ADDR_TYPE_WOTSPK); - - /* Derive the message digest and leaf index from R || PK || M. */ - /* The additional PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_N is a result of the hash domain separator. */ - PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_N; - - /* Layer correctly defaults to 0, so no need to set_layer_addr */ - PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); - - PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_fors_pk_from_sig( - root, sig, mhash, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_FORS_BYTES; - - /* For each subtree.. */ - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_D; i++) { - PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_set_tree_addr(tree_addr, tree); - - PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); - - PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_copy_keypair_addr( - wots_pk_addr, wots_addr); - - /* The WOTS public key is only correct if the signature was correct. */ - /* Initially, root is the FORS pk, but on subsequent iterations it is - the root of the subtree below the currently processed subtree. */ - PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_wots_pk_from_sig( - wots_pk, sig, root, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_WOTS_BYTES; - - /* Compute the leaf node using the WOTS public key. */ - PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_thash_WOTS_LEN( - leaf, wots_pk, pub_seed, wots_pk_addr, &hash_state_seeded); - - /* Compute the root node of this subtree. */ - PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_compute_root( - root, leaf, idx_leaf, 0, sig, PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_TREE_HEIGHT, - pub_seed, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_TREE_HEIGHT * PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_TREE_HEIGHT; - } - - PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_destroy_hash_function(&hash_state_seeded); - /* Check if the root node equals the root node in the public key. */ - if (memcmp(root, pub_root, PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_N) != 0) { - return -1; - } - - return 0; -} - - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - size_t siglen; - - PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_crypto_sign_signature( - sm, &siglen, m, mlen, sk); - - memmove(sm + PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_BYTES, m, mlen); - *smlen = siglen + mlen; - - return 0; -} - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk) { - /* The API caller does not necessarily know what size a signature should be - but SPHINCS+ signatures are always exactly PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_BYTES. */ - if (smlen < PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_BYTES) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - *mlen = smlen - PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_BYTES; - - if (PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_crypto_sign_verify( - sm, PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_BYTES, sm + PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_BYTES, *mlen, pk)) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - /* If verification was successful, move the message to the right place. */ - memmove(m, sm + PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_BYTES, *mlen); - - return 0; -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_clean/thash.h b/src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_clean/thash.h deleted file mode 100644 index b278d6acfa..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_clean/thash.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_THASH_H -#define PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_THASH_H - -#include "hash_state.h" - -#include - -void PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_clean/thash_shake256_robust.c b/src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_clean/thash_shake256_robust.c deleted file mode 100644 index bab42bf637..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_clean/thash_shake256_robust.c +++ /dev/null @@ -1,81 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "thash.h" - -#include "fips202.h" - -/** - * Takes an array of inblocks concatenated arrays of PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_N bytes. - */ -static void PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_thash( - unsigned char *out, unsigned char *buf, - const unsigned char *in, unsigned int inblocks, - const unsigned char *pub_seed, uint32_t addr[8]) { - - unsigned char *bitmask = buf + PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_N + PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_ADDR_BYTES; - unsigned int i; - - memcpy(buf, pub_seed, PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_N); - PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_addr_to_bytes(buf + PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_N, addr); - - shake256(bitmask, inblocks * PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_N, buf, PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_N + PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_ADDR_BYTES); - - for (i = 0; i < inblocks * PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_N; i++) { - buf[PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_N + PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_ADDR_BYTES + i] = in[i] ^ bitmask[i]; - } - - shake256(out, PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_N, buf, PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_N + PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_N); -} - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_N + PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_ADDR_BYTES + 1 * PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_N]; - PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_thash( - out, buf, in, 1, pub_seed, addr); - - (void)hash_state_seeded; /* Avoid unused parameter warning. */ -} - -void PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_N + PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_ADDR_BYTES + 2 * PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_N]; - PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_thash( - out, buf, in, 2, pub_seed, addr); - - (void)hash_state_seeded; /* Avoid unused parameter warning. */ -} - -void PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_N + PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_ADDR_BYTES + PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_WOTS_LEN * PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_N]; - PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_thash( - out, buf, in, PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_WOTS_LEN, pub_seed, addr); - - (void)hash_state_seeded; /* Avoid unused parameter warning. */ -} - -void PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_N + PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_ADDR_BYTES + PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_FORS_TREES * PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_N]; - PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_thash( - out, buf, in, PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_FORS_TREES, pub_seed, addr); - - (void)hash_state_seeded; /* Avoid unused parameter warning. */ -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_clean/utils.c b/src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_clean/utils.c deleted file mode 100644 index 958b12f175..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_clean/utils.c +++ /dev/null @@ -1,199 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "hash_state.h" -#include "params.h" -#include "thash.h" -#include "utils.h" - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in) { - - /* Iterate over out in decreasing order, for big-endianness. */ - for (size_t i = outlen; i > 0; i--) { - out[i - 1] = in & 0xff; - in = in >> 8; - } -} - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_bytes_to_ull( - const unsigned char *in, size_t inlen) { - unsigned long long retval = 0; - - for (size_t i = 0; i < inlen; i++) { - retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); - } - return retval; -} - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - uint32_t i; - unsigned char buffer[2 * PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_N]; - - /* If leaf_idx is odd (last bit = 1), current path element is a right child - and auth_path has to go left. Otherwise it is the other way around. */ - if (leaf_idx & 1) { - memcpy(buffer + PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_N, leaf, PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_N); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_N); - } else { - memcpy(buffer, leaf, PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_N); - memcpy(buffer + PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_N, auth_path, PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_N); - } - auth_path += PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_N; - - for (i = 0; i < tree_height - 1; i++) { - leaf_idx >>= 1; - idx_offset >>= 1; - /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_set_tree_height(addr, i + 1); - PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_set_tree_index( - addr, leaf_idx + idx_offset); - - /* Pick the right or left neighbor, depending on parity of the node. */ - if (leaf_idx & 1) { - PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_thash_2( - buffer + PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_N, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_N); - } else { - PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_thash_2( - buffer, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer + PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_N, auth_path, PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_N); - } - auth_path += PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_N; - } - - /* The last iteration is exceptional; we do not copy an auth_path node. */ - leaf_idx >>= 1; - idx_offset >>= 1; - PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_set_tree_height(addr, tree_height); - PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_set_tree_index( - addr, leaf_idx + idx_offset); - PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_thash_2( - root, buffer, pub_seed, addr, hash_state_seeded); -} - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -static void PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_treehash( - unsigned char *root, unsigned char *auth_path, - unsigned char *stack, unsigned int *heights, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - - unsigned int offset = 0; - uint32_t idx; - uint32_t tree_idx; - - for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { - /* Add the next leaf node to the stack. */ - gen_leaf(stack + offset * PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_N, - sk_seed, pub_seed, idx + idx_offset, tree_addr, - hash_state_seeded); - offset++; - heights[offset - 1] = 0; - - /* If this is a node we need for the auth path.. */ - if ((leaf_idx ^ 0x1) == idx) { - memcpy(auth_path, stack + (offset - 1)*PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_N, PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_N); - } - - /* While the top-most nodes are of equal height.. */ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { - /* Compute index of the new node, in the next layer. */ - tree_idx = (idx >> (heights[offset - 1] + 1)); - - /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_set_tree_height( - tree_addr, heights[offset - 1] + 1); - PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_set_tree_index( - tree_addr, tree_idx + (idx_offset >> (heights[offset - 1] + 1))); - /* Hash the top-most nodes from the stack together. */ - PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_thash_2( - stack + (offset - 2)*PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_N, stack + (offset - 2)*PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_N, - pub_seed, tree_addr, hash_state_seeded); - offset--; - /* Note that the top-most node is now one layer higher. */ - heights[offset - 1]++; - - /* If this is a node we need for the auth path.. */ - if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_path + heights[offset - 1]*PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_N, - stack + (offset - 1)*PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_N, PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_N); - } - } - } - memcpy(root, stack, PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_N); -} - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_FORS_HEIGHT + 1)*PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_N]; - unsigned int heights[PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_FORS_HEIGHT + 1]; - - PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_FORS_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_TREE_HEIGHT + 1)*PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_N]; - unsigned int heights[PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_TREE_HEIGHT + 1]; - - PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_TREE_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_clean/utils.h b/src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_clean/utils.h deleted file mode 100644 index b4079184ea..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_clean/utils.h +++ /dev/null @@ -1,64 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_UTILS_H -#define PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_UTILS_H - -#include "hash_state.h" -#include "params.h" -#include -#include - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in); - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_bytes_to_ull( - const unsigned char *in, size_t inlen); - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -void PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_clean/wots.c b/src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_clean/wots.c deleted file mode 100644 index 5ec0410c3b..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_clean/wots.c +++ /dev/null @@ -1,167 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "hash_state.h" -#include "params.h" -#include "thash.h" -#include "utils.h" -#include "wots.h" - -// TODO clarify address expectations, and make them more uniform. -// TODO i.e. do we expect types to be set already? -// TODO and do we expect modifications or copies? - -/** - * Computes the starting value for a chain, i.e. the secret key. - * Expects the address to be complete up to the chain address. - */ -static void wots_gen_sk(unsigned char *sk, const unsigned char *sk_seed, - uint32_t wots_addr[8], - const hash_state *hash_state_seeded) { - /* Make sure that the hash address is actually zeroed. */ - PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_set_hash_addr(wots_addr, 0); - - /* Generate sk element. */ - PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_prf_addr(sk, sk_seed, wots_addr, hash_state_seeded); -} - -/** - * Computes the chaining function. - * out and in have to be n-byte arrays. - * - * Interprets in as start-th value of the chain. - * addr has to contain the address of the chain. - */ -static void gen_chain(unsigned char *out, const unsigned char *in, - unsigned int start, unsigned int steps, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - uint32_t i; - - /* Initialize out with the value at position 'start'. */ - memcpy(out, in, PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_N); - - /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_WOTS_W; i++) { - PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_set_hash_addr(addr, i); - PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_thash_1( - out, out, pub_seed, addr, hash_state_seeded); - } -} - -/** - * base_w algorithm as described in draft. - * Interprets an array of bytes as integers in base w. - * This only works when log_w is a divisor of 8. - */ -static void base_w(unsigned int *output, const size_t out_len, - const unsigned char *input) { - size_t in = 0; - size_t out = 0; - unsigned char total = 0; - unsigned int bits = 0; - size_t consumed; - - for (consumed = 0; consumed < out_len; consumed++) { - if (bits == 0) { - total = input[in]; - in++; - bits += 8; - } - bits -= PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_WOTS_LOGW; - output[out] = (unsigned int)((total >> bits) & (PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_WOTS_W - 1)); - out++; - } -} - -/* Computes the WOTS+ checksum over a message (in base_w). */ -static void wots_checksum(unsigned int *csum_base_w, - const unsigned int *msg_base_w) { - unsigned int csum = 0; - unsigned char csum_bytes[(PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_WOTS_LEN2 * PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_WOTS_LOGW + 7) / 8]; - unsigned int i; - - /* Compute checksum. */ - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_WOTS_LEN1; i++) { - csum += PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_WOTS_W - 1 - msg_base_w[i]; - } - - /* Convert checksum to base_w. */ - /* Make sure expected empty zero bits are the least significant bits. */ - csum = csum << (8 - ((PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_WOTS_LEN2 * PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_WOTS_LOGW) % 8)); - PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_ull_to_bytes( - csum_bytes, sizeof(csum_bytes), csum); - base_w(csum_base_w, PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_WOTS_LEN2, csum_bytes); -} - -/* Takes a message and derives the matching chain lengths. */ -static void chain_lengths(unsigned int *lengths, const unsigned char *msg) { - base_w(lengths, PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_WOTS_LEN1, msg); - wots_checksum(lengths + PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_WOTS_LEN1, lengths); -} - -/** - * WOTS key generation. Takes a 32 byte sk_seed, expands it to WOTS private key - * elements and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_wots_gen_pk( - unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - uint32_t i; - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_WOTS_LEN; i++) { - PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_set_chain_addr(addr, i); - wots_gen_sk(pk + i * PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_N, sk_seed, addr, hash_state_seeded); - gen_chain(pk + i * PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_N, pk + i * PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_N, - 0, PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_WOTS_W - 1, pub_seed, addr, hash_state_seeded); - } -} - -/** - * Takes a n-byte message and the 32-byte sk_see to compute a signature 'sig'. - */ -void PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_wots_sign( - unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *hash_state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_WOTS_LEN; i++) { - PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_set_chain_addr(addr, i); - wots_gen_sk(sig + i * PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_N, sk_seed, addr, hash_state_seeded); - gen_chain(sig + i * PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_N, sig + i * PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_N, 0, lengths[i], pub_seed, addr, hash_state_seeded); - } -} - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_wots_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_WOTS_LEN; i++) { - PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_set_chain_addr(addr, i); - gen_chain(pk + i * PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_N, sig + i * PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_N, - lengths[i], PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_WOTS_W - 1 - lengths[i], pub_seed, addr, - hash_state_seeded); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_clean/wots.h b/src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_clean/wots.h deleted file mode 100644 index 19bcd4a7cf..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192s-robust_clean/wots.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_WOTS_H -#define PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_WOTS_H - -#include "hash_state.h" -#include "params.h" -#include - -/** - * WOTS key generation. Takes a 32 byte seed for the private key, expands it to - * a full WOTS private key and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_wots_gen_pk( - unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -/** - * Takes a n-byte message and the 32-byte seed for the private key to compute a - * signature that is placed at 'sig'. - */ -void PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_wots_sign( - unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *hash_state_seeded); - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_wots_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_avx2/LICENSE b/src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_avx2/LICENSE deleted file mode 100644 index 670154e353..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_avx2/LICENSE +++ /dev/null @@ -1,116 +0,0 @@ -CC0 1.0 Universal - -Statement of Purpose - -The laws of most jurisdictions throughout the world automatically confer -exclusive Copyright and Related Rights (defined below) upon the creator and -subsequent owner(s) (each and all, an "owner") of an original work of -authorship and/or a database (each, a "Work"). - -Certain owners wish to permanently relinquish those rights to a Work for the -purpose of contributing to a commons of creative, cultural and scientific -works ("Commons") that the public can reliably and without fear of later -claims of infringement build upon, modify, incorporate in other works, reuse -and redistribute as freely as possible in any form whatsoever and for any -purposes, including without limitation commercial purposes. These owners may -contribute to the Commons to promote the ideal of a free culture and the -further production of creative, cultural and scientific works, or to gain -reputation or greater distribution for their Work in part through the use and -efforts of others. - -For these and/or other purposes and motivations, and without any expectation -of additional consideration or compensation, the person associating CC0 with a -Work (the "Affirmer"), to the extent that he or she is an owner of Copyright -and Related Rights in the Work, voluntarily elects to apply CC0 to the Work -and publicly distribute the Work under its terms, with knowledge of his or her -Copyright and Related Rights in the Work and the meaning and intended legal -effect of CC0 on those rights. - -1. Copyright and Related Rights. A Work made available under CC0 may be -protected by copyright and related or neighboring rights ("Copyright and -Related Rights"). Copyright and Related Rights include, but are not limited -to, the following: - - i. the right to reproduce, adapt, distribute, perform, display, communicate, - and translate a Work; - - ii. moral rights retained by the original author(s) and/or performer(s); - - iii. publicity and privacy rights pertaining to a person's image or likeness - depicted in a Work; - - iv. rights protecting against unfair competition in regards to a Work, - subject to the limitations in paragraph 4(a), below; - - v. rights protecting the extraction, dissemination, use and reuse of data in - a Work; - - vi. database rights (such as those arising under Directive 96/9/EC of the - European Parliament and of the Council of 11 March 1996 on the legal - protection of databases, and under any national implementation thereof, - including any amended or successor version of such directive); and - - vii. other similar, equivalent or corresponding rights throughout the world - based on applicable law or treaty, and any national implementations thereof. - -2. Waiver. To the greatest extent permitted by, but not in contravention of, -applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and -unconditionally waives, abandons, and surrenders all of Affirmer's Copyright -and Related Rights and associated claims and causes of action, whether now -known or unknown (including existing as well as future claims and causes of -action), in the Work (i) in all territories worldwide, (ii) for the maximum -duration provided by applicable law or treaty (including future time -extensions), (iii) in any current or future medium and for any number of -copies, and (iv) for any purpose whatsoever, including without limitation -commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes -the Waiver for the benefit of each member of the public at large and to the -detriment of Affirmer's heirs and successors, fully intending that such Waiver -shall not be subject to revocation, rescission, cancellation, termination, or -any other legal or equitable action to disrupt the quiet enjoyment of the Work -by the public as contemplated by Affirmer's express Statement of Purpose. - -3. Public License Fallback. Should any part of the Waiver for any reason be -judged legally invalid or ineffective under applicable law, then the Waiver -shall be preserved to the maximum extent permitted taking into account -Affirmer's express Statement of Purpose. In addition, to the extent the Waiver -is so judged Affirmer hereby grants to each affected person a royalty-free, -non transferable, non sublicensable, non exclusive, irrevocable and -unconditional license to exercise Affirmer's Copyright and Related Rights in -the Work (i) in all territories worldwide, (ii) for the maximum duration -provided by applicable law or treaty (including future time extensions), (iii) -in any current or future medium and for any number of copies, and (iv) for any -purpose whatsoever, including without limitation commercial, advertising or -promotional purposes (the "License"). The License shall be deemed effective as -of the date CC0 was applied by Affirmer to the Work. Should any part of the -License for any reason be judged legally invalid or ineffective under -applicable law, such partial invalidity or ineffectiveness shall not -invalidate the remainder of the License, and in such case Affirmer hereby -affirms that he or she will not (i) exercise any of his or her remaining -Copyright and Related Rights in the Work or (ii) assert any associated claims -and causes of action with respect to the Work, in either case contrary to -Affirmer's express Statement of Purpose. - -4. Limitations and Disclaimers. - - a. No trademark or patent rights held by Affirmer are waived, abandoned, - surrendered, licensed or otherwise affected by this document. - - b. Affirmer offers the Work as-is and makes no representations or warranties - of any kind concerning the Work, express, implied, statutory or otherwise, - including without limitation warranties of title, merchantability, fitness - for a particular purpose, non infringement, or the absence of latent or - other defects, accuracy, or the present or absence of errors, whether or not - discoverable, all to the greatest extent permissible under applicable law. - - c. Affirmer disclaims responsibility for clearing rights of other persons - that may apply to the Work or any use thereof, including without limitation - any person's Copyright and Related Rights in the Work. Further, Affirmer - disclaims responsibility for obtaining any necessary consents, permissions - or other rights required for any use of the Work. - - d. Affirmer understands and acknowledges that Creative Commons is not a - party to this document and has no duty or obligation with respect to this - CC0 or use of the Work. - -For more information, please see - diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_avx2/address.c b/src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_avx2/address.c deleted file mode 100644 index f90c62657f..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_avx2/address.c +++ /dev/null @@ -1,78 +0,0 @@ -#include - -#include "address.h" -#include "params.h" -#include "utils.h" - -void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]) { - int i; - - for (i = 0; i < 8; i++) { - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_ull_to_bytes( - bytes + i * 4, 4, addr[i]); - } -} - -void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_set_layer_addr( - uint32_t addr[8], uint32_t layer) { - addr[0] = layer; -} - -void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_set_tree_addr( - uint32_t addr[8], uint64_t tree) { - addr[1] = 0; - addr[2] = (uint32_t) (tree >> 32); - addr[3] = (uint32_t) tree; -} - -void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_set_type( - uint32_t addr[8], uint32_t type) { - addr[4] = type; -} - -void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; -} - -/* These functions are used for OTS addresses. */ - -void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_set_keypair_addr( - uint32_t addr[8], uint32_t keypair) { - addr[5] = keypair; -} - -void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; - out[5] = in[5]; -} - -void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_set_chain_addr( - uint32_t addr[8], uint32_t chain) { - addr[6] = chain; -} - -void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_set_hash_addr( - uint32_t addr[8], uint32_t hash) { - addr[7] = hash; -} - -/* These functions are used for all hash tree addresses (including FORS). */ - -void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_set_tree_height( - uint32_t addr[8], uint32_t tree_height) { - addr[6] = tree_height; -} - -void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_set_tree_index( - uint32_t addr[8], uint32_t tree_index) { - addr[7] = tree_index; -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_avx2/address.h b/src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_avx2/address.h deleted file mode 100644 index 47ef7415c0..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_avx2/address.h +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_ADDRESS_H -#define PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_ADDRESS_H - -#include - -#define PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_ADDR_TYPE_WOTS 0 -#define PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_ADDR_TYPE_WOTSPK 1 -#define PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_ADDR_TYPE_HASHTREE 2 -#define PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_ADDR_TYPE_FORSTREE 3 -#define PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_ADDR_TYPE_FORSPK 4 - -void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]); - -void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_set_layer_addr( - uint32_t addr[8], uint32_t layer); - -void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_set_tree_addr( - uint32_t addr[8], uint64_t tree); - -void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_set_type( - uint32_t addr[8], uint32_t type); - -/* Copies the layer and tree part of one address into the other */ -void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for WOTS and FORS addresses. */ - -void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_set_keypair_addr( - uint32_t addr[8], uint32_t keypair); - -void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_set_chain_addr( - uint32_t addr[8], uint32_t chain); - -void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_set_hash_addr( - uint32_t addr[8], uint32_t hash); - -void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for all hash tree addresses (including FORS). */ - -void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_set_tree_height( - uint32_t addr[8], uint32_t tree_height); - -void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_set_tree_index( - uint32_t addr[8], uint32_t tree_index); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_avx2/api.h b/src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_avx2/api.h deleted file mode 100644 index c15a93cc1f..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_avx2/api.h +++ /dev/null @@ -1,81 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_API_H -#define PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_API_H - -#include -#include - - - -#define PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_CRYPTO_ALGNAME "SPHINCS+" - -#define PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_CRYPTO_SECRETKEYBYTES 96 -#define PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_CRYPTO_PUBLICKEYBYTES 48 -#define PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_CRYPTO_BYTES 16224 -#define PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_CRYPTO_SEEDBYTES 72 - - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_avx2/fors.c b/src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_avx2/fors.c deleted file mode 100644 index a1ba06244c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_avx2/fors.c +++ /dev/null @@ -1,206 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "fors.h" -#include "hash.h" -#include "hashx4.h" -#include "thash.h" -#include "thashx4.h" -#include "utils.h" -#include "utilsx4.h" - -static void fors_gen_skx4(unsigned char *sk0, - unsigned char *sk1, - unsigned char *sk2, - unsigned char *sk3, const unsigned char *sk_seed, - uint32_t fors_leaf_addrx4[4 * 8], - const hash_state *state_seeded) { - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_prf_addrx4(sk0, sk1, sk2, sk3, sk_seed, fors_leaf_addrx4, state_seeded); -} - -static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, - const unsigned char *pub_seed, - uint32_t fors_leaf_addr[8], const hash_state *state_seeded) { - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_thash_1(leaf, sk, pub_seed, fors_leaf_addr, state_seeded); -} - -static void fors_sk_to_leafx4(unsigned char *leaf0, - unsigned char *leaf1, - unsigned char *leaf2, - unsigned char *leaf3, - const unsigned char *sk0, - const unsigned char *sk1, - const unsigned char *sk2, - const unsigned char *sk3, - const unsigned char *pub_seed, - uint32_t fors_leaf_addrx4[4 * 8], - const hash_state *state_seeded) { - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_thashx4_1(leaf0, leaf1, leaf2, leaf3, - sk0, sk1, sk2, sk3, pub_seed, fors_leaf_addrx4, state_seeded); -} - -static void fors_gen_leafx4(unsigned char *leaf0, - unsigned char *leaf1, - unsigned char *leaf2, - unsigned char *leaf3, - const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx0, - uint32_t addr_idx1, - uint32_t addr_idx2, - uint32_t addr_idx3, - const uint32_t fors_tree_addr[8], - const hash_state *state_seeded) { - uint32_t fors_leaf_addrx4[4 * 8] = {0}; - unsigned int j; - - /* Only copy the parts that must be kept in fors_leaf_addrx4. */ - for (j = 0; j < 4; j++) { - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_copy_keypair_addr(fors_leaf_addrx4 + j * 8, fors_tree_addr); - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_set_type(fors_leaf_addrx4 + j * 8, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_ADDR_TYPE_FORSTREE); - } - - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_set_tree_index(fors_leaf_addrx4 + 0 * 8, addr_idx0); - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_set_tree_index(fors_leaf_addrx4 + 1 * 8, addr_idx1); - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_set_tree_index(fors_leaf_addrx4 + 2 * 8, addr_idx2); - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_set_tree_index(fors_leaf_addrx4 + 3 * 8, addr_idx3); - - fors_gen_skx4(leaf0, leaf1, leaf2, leaf3, sk_seed, fors_leaf_addrx4, state_seeded); - fors_sk_to_leafx4(leaf0, leaf1, leaf2, leaf3, - leaf0, leaf1, leaf2, leaf3, pub_seed, fors_leaf_addrx4, state_seeded); -} - -/** - * Interprets m as PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_FORS_HEIGHT-bit unsigned integers. - * Assumes m contains at least PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_FORS_TREES bits. - * Assumes indices has space for PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_FORS_TREES integers. - */ -static void message_to_indices(uint32_t *indices, const unsigned char *m) { - unsigned int i, j; - unsigned int offset = 0; - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_FORS_TREES; i++) { - indices[i] = 0; - for (j = 0; j < PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_FORS_HEIGHT; j++) { - indices[i] ^= (((uint32_t)m[offset >> 3] >> (offset & 0x7)) & 0x1) << j; - offset++; - } - } -} - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *state_seeded) { - /* Round up to multiple of 4 to prevent out-of-bounds for x4 parallelism */ - uint32_t indices[(PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_FORS_TREES + 3) & ~3] = {0}; - unsigned char roots[((PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_FORS_TREES + 3) & ~3) * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N]; - /* Sign to a buffer, since we may not have a nice multiple of 4 and would - otherwise overrun the signature. */ - unsigned char sigbufx4[4 * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N * (1 + PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_FORS_HEIGHT)]; - uint32_t fors_tree_addrx4[4 * 8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset[4] = {0}; - unsigned int i, j; - - for (j = 0; j < 4; j++) { - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_copy_keypair_addr(fors_tree_addrx4 + j * 8, fors_addr); - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_set_type(fors_tree_addrx4 + j * 8, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_ADDR_TYPE_FORSTREE); - } - - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_copy_keypair_addr(fors_pk_addr, fors_addr); - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_set_type(fors_pk_addr, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < ((PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_FORS_TREES + 3) & ~0x3); i += 4) { - for (j = 0; j < 4; j++) { - if (i + j < PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_FORS_TREES) { - idx_offset[j] = (i + j) * (1 << PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_FORS_HEIGHT); - - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_set_tree_height(fors_tree_addrx4 + j * 8, 0); - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_set_tree_index(fors_tree_addrx4 + j * 8, - indices[i + j] + idx_offset[j]); - } - } - - /* Include the secret key part that produces the selected leaf nodes. */ - fors_gen_skx4(sigbufx4 + 0 * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N, - sigbufx4 + 1 * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N, - sigbufx4 + 2 * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N, - sigbufx4 + 3 * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N, - sk_seed, fors_tree_addrx4, state_seeded); - - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_treehashx4_FORS_HEIGHT(roots + i * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N, sigbufx4 + 4 * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N, sk_seed, pub_seed, - &indices[i], idx_offset, fors_gen_leafx4, fors_tree_addrx4, - state_seeded); - - for (j = 0; j < 4; j++) { - if (i + j < PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_FORS_TREES) { - memcpy(sig, sigbufx4 + j * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N); - memcpy(sig + PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N, - sigbufx4 + 4 * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N + j * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_FORS_HEIGHT, - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_FORS_HEIGHT); - sig += PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N * (1 + PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_FORS_HEIGHT); - } - } - } - - /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_thash_FORS_TREES(pk, roots, pub_seed, fors_pk_addr, state_seeded); -} - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, - const uint32_t fors_addr[8], - const hash_state *state_seeded) { - uint32_t indices[PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_FORS_TREES]; - unsigned char roots[PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_FORS_TREES * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N]; - unsigned char leaf[PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N]; - uint32_t fors_tree_addr[8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_copy_keypair_addr(fors_tree_addr, fors_addr); - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_copy_keypair_addr(fors_pk_addr, fors_addr); - - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_set_type(fors_tree_addr, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_set_type(fors_pk_addr, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_FORS_TREES; i++) { - idx_offset = i * (1 << PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_FORS_HEIGHT); - - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_set_tree_height(fors_tree_addr, 0); - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Derive the leaf from the included secret key part. */ - fors_sk_to_leaf(leaf, sig, pub_seed, fors_tree_addr, state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N; - - /* Derive the corresponding root node of this tree. */ - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_compute_root(roots + i * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N, leaf, indices[i], idx_offset, - sig, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_FORS_HEIGHT, pub_seed, fors_tree_addr, - state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_thash_FORS_TREES(pk, roots, pub_seed, fors_pk_addr, state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_avx2/fors.h b/src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_avx2/fors.h deleted file mode 100644 index 3addc74a6e..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_avx2/fors.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_FORS_H -#define PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_FORS_H - -#include - -#include "hash_state.h" -#include "params.h" - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_fors_sign( - unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *hash_state_seeded); - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_fors_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, const uint32_t fors_addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_avx2/hash.h b/src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_avx2/hash.h deleted file mode 100644 index cc890f06ec..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_avx2/hash.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_HASH_H -#define PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_HASH_H - -#include "hash_state.h" - -#include -#include - -void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_initialize_hash_function( - hash_state *hash_state_seeded, - const unsigned char *pub_seed, const unsigned char *sk_seed); - -void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_destroy_hash_function(hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_avx2/hash_shake256.c b/src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_avx2/hash_shake256.c deleted file mode 100644 index 2ff61c0697..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_avx2/hash_shake256.c +++ /dev/null @@ -1,106 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "utils.h" - -#include "fips202.h" - -/* For SHAKE256, there is no immediate reason to initialize at the start, - so this function is an empty operation. */ -void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_initialize_hash_function( - hash_state *hash_state_seeded, // NOLINT(readability-non-const-parameter) - const unsigned char *pub_seed, const unsigned char *sk_seed) { - (void)hash_state_seeded; /* Suppress an 'unused parameter' warning. */ - (void)pub_seed; /* Suppress an 'unused parameter' warning. */ - (void)sk_seed; /* Suppress an 'unused parameter' warning. */ -} - -/* This is not necessary for SHAKE256, so we don't do anything */ -void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_destroy_hash_function( - hash_state *hash_state_seeded) { // NOLINT(readability-non-const-parameter) - (void)hash_state_seeded; -} - -/* - * Computes PRF(key, addr), given a secret key of PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N bytes and an address - */ -void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded) { - unsigned char buf[PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_ADDR_BYTES]; - - memcpy(buf, key, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N); - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_addr_to_bytes(buf + PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N, addr); - - shake256(out, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N, buf, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_ADDR_BYTES); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} - -/** - * Computes the message-dependent randomness R, using a secret seed and an - * optional randomization value as well as the message. - */ -void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded) { - shake256incctx state; - - shake256_inc_init(&state); - shake256_inc_absorb(&state, sk_prf, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N); - shake256_inc_absorb(&state, optrand, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N); - shake256_inc_absorb(&state, m, mlen); - shake256_inc_finalize(&state); - shake256_inc_squeeze(R, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N, &state); - shake256_inc_ctx_release(&state); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} - -/** - * Computes the message hash using R, the public key, and the message. - * Outputs the message digest and the index of the leaf. The index is split in - * the tree index and the leaf index, for convenient copying to an address. - */ -void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded) { -#define PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_TREE_BITS (PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_TREE_HEIGHT * (PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_D - 1)) -#define PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_TREE_BYTES ((PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_TREE_BITS + 7) / 8) -#define PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_LEAF_BITS PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_TREE_HEIGHT -#define PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_LEAF_BYTES ((PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_LEAF_BITS + 7) / 8) -#define PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_DGST_BYTES (PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_FORS_MSG_BYTES + PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_TREE_BYTES + PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_LEAF_BYTES) - - unsigned char buf[PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_DGST_BYTES]; - unsigned char *bufp = buf; - shake256incctx state; - - shake256_inc_init(&state); - shake256_inc_absorb(&state, R, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N); - shake256_inc_absorb(&state, pk, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_PK_BYTES); - shake256_inc_absorb(&state, m, mlen); - shake256_inc_finalize(&state); - shake256_inc_squeeze(buf, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_DGST_BYTES, &state); - shake256_inc_ctx_release(&state); - - memcpy(digest, bufp, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_FORS_MSG_BYTES); - bufp += PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_FORS_MSG_BYTES; - - *tree = PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_bytes_to_ull( - bufp, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_TREE_BYTES); - *tree &= (~(uint64_t)0) >> (64 - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_TREE_BITS); - bufp += PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_TREE_BYTES; - - *leaf_idx = (uint32_t)PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_bytes_to_ull( - bufp, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_LEAF_BYTES); - *leaf_idx &= (~(uint32_t)0) >> (32 - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_LEAF_BITS); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_avx2/hash_shake256x4.c b/src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_avx2/hash_shake256x4.c deleted file mode 100644 index d2c94a8ea8..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_avx2/hash_shake256x4.c +++ /dev/null @@ -1,38 +0,0 @@ -#include -#include - -#include "address.h" -#include "fips202x4.h" -#include "hashx4.h" -#include "params.h" - -/* - * 4-way parallel version of prf_addr; takes 4x as much input and output - */ -void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_prf_addrx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const unsigned char *key, - const uint32_t addrx4[4 * 8], - const hash_state *state_seeded) { - unsigned char bufx4[4 * (PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_ADDR_BYTES)]; - unsigned int j; - - for (j = 0; j < 4; j++) { - memcpy(bufx4 + j * (PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_ADDR_BYTES), key, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N); - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_addr_to_bytes(bufx4 + PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N + j * (PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_ADDR_BYTES), addrx4 + j * 8); - } - - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_shake256x4(out0, - out1, - out2, - out3, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N, - bufx4 + 0 * (PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_ADDR_BYTES), - bufx4 + 1 * (PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_ADDR_BYTES), - bufx4 + 2 * (PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_ADDR_BYTES), - bufx4 + 3 * (PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_ADDR_BYTES), PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_ADDR_BYTES); - - /* Avoid unused parameter warning */ - (void)state_seeded; -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_avx2/hash_state.h b/src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_avx2/hash_state.h deleted file mode 100644 index 89a53cf5f5..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_avx2/hash_state.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_HASH_STATE_H -#define PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_HASH_STATE_H - -/** - * Defines the type of the hash function state. - * - * Don't be fooled into thinking this instance of SPHINCS+ isn't stateless! - * - * From Section 7.2.2 from the SPHINCS+ round-2 specification: - * - * Each of the instances of the tweakable hash function take PK.seed as its - * first input, which is constant for a given key pair – and, thus, across - * a single signature. This leads to a lot of redundant computation. To remedy - * this, we pad PK.seed to the length of a full 64-byte SHA-256 input block. - * Because of the Merkle-Damgård construction that underlies SHA-256, this - * allows for reuse of the intermediate SHA-256 state after the initial call to - * the compression function which improves performance. - * - * We pass this hash state around in functions, because otherwise we need to - * have a global variable. - * - * SHAKE256 does not need this state. Because this implementation is generated - * from a shared code base, we still need to specify some hash_state as it is - * still passed around. We chose to use an `int` as a placeholder for this - * purpose. - */ - -typedef int hash_state; - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_avx2/hashx4.h b/src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_avx2/hashx4.h deleted file mode 100644 index 18a74575ab..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_avx2/hashx4.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_HASHX4_H -#define PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_HASHX4_H - -#include - -#include "hash_state.h" - -void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_prf_addrx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const unsigned char *key, - const uint32_t addrx4[4 * 8], - const hash_state *state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_avx2/params.h b/src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_avx2/params.h deleted file mode 100644 index 049322c64e..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_avx2/params.h +++ /dev/null @@ -1,53 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_PARAMS_H -#define PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_PARAMS_H - -/* Hash output length in bytes. */ -#define PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N 24 -/* Height of the hypertree. */ -#define PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_FULL_HEIGHT 63 -/* Number of subtree layer. */ -#define PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_D 7 -/* FORS tree dimensions. */ -#define PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_FORS_HEIGHT 14 -#define PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_FORS_TREES 17 -/* Winternitz parameter, */ -#define PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_WOTS_W 16 - -/* The hash function is defined by linking a different hash.c file, as opposed - to setting a #define constant. */ - -/* For clarity */ -#define PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_ADDR_BYTES 32 - -/* WOTS parameters. */ -#define PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_WOTS_LOGW 4 - -#define PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_WOTS_LEN1 (8 * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N / PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_WOTS_LOGW) - -/* PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#define PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_WOTS_LEN2 3 - -#define PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_WOTS_LEN (PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_WOTS_LEN1 + PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_WOTS_LEN2) -#define PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_WOTS_BYTES (PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_WOTS_LEN * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N) -#define PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_WOTS_PK_BYTES PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_WOTS_BYTES - -/* Subtree size. */ -#define PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_TREE_HEIGHT (PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_FULL_HEIGHT / PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_D) - -/* FORS parameters. */ -#define PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_FORS_MSG_BYTES ((PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_FORS_TREES + 7) / 8) -#define PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_FORS_BYTES ((PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_FORS_HEIGHT + 1) * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_FORS_TREES * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N) -#define PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_FORS_PK_BYTES PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N - -/* Resulting SPX sizes. */ -#define PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_BYTES (PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_FORS_BYTES + PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_D * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_WOTS_BYTES +\ - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_FULL_HEIGHT * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N) -#define PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_PK_BYTES (2 * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N) -#define PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_SK_BYTES (2 * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_PK_BYTES) - -/* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ -#define PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_OPTRAND_BYTES 32 - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_avx2/sign.c b/src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_avx2/sign.c deleted file mode 100644 index 66b38e5d6e..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_avx2/sign.c +++ /dev/null @@ -1,409 +0,0 @@ -#include -#include -#include -#include - -#include "address.h" -#include "api.h" -#include "fors.h" -#include "hash.h" -#include "hash_state.h" -#include "params.h" -#include "randombytes.h" -#include "thash.h" -#include "utils.h" -#include "wots.h" - - -/** - * Computes the leaf at a given address. First generates the WOTS key pair, - * then computes leaf by hashing horizontally. - */ -static void wots_gen_leaf(unsigned char *leaf, const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx, const uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - unsigned char pk[PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_WOTS_BYTES]; - uint32_t wots_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_set_type( - wots_addr, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_set_type( - wots_pk_addr, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_ADDR_TYPE_WOTSPK); - - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_set_keypair_addr( - wots_addr, addr_idx); - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_wots_gen_pk( - pk, sk_seed, pub_seed, wots_addr, hash_state_seeded); - - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_copy_keypair_addr( - wots_pk_addr, wots_addr); - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_thash_WOTS_LEN( - leaf, pk, pub_seed, wots_pk_addr, hash_state_seeded); -} - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_crypto_sign_secretkeybytes(void) { - return PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_CRYPTO_SECRETKEYBYTES; -} - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_crypto_sign_publickeybytes(void) { - return PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_CRYPTO_PUBLICKEYBYTES; -} - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_crypto_sign_bytes(void) { - return PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_CRYPTO_BYTES; -} - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_crypto_sign_seedbytes(void) { - return PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_CRYPTO_SEEDBYTES; -} - -/* - * Generates an SPX key pair given a seed of length - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed) { - /* We do not need the auth path in key generation, but it simplifies the - code to have just one treehash routine that computes both root and path - in one function. */ - unsigned char auth_path[PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_TREE_HEIGHT * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N]; - uint32_t top_tree_addr[8] = {0}; - hash_state hash_state_seeded; - - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_set_layer_addr( - top_tree_addr, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_D - 1); - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_set_type( - top_tree_addr, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_ADDR_TYPE_HASHTREE); - - /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ - memcpy(sk, seed, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_CRYPTO_SEEDBYTES); - - memcpy(pk, sk + 2 * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_initialize_hash_function(&hash_state_seeded, pk, sk); - - /* Compute root node of the top-most subtree. */ - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_treehash_TREE_HEIGHT( - sk + 3 * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N, auth_path, sk, sk + 2 * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N, 0, 0, - wots_gen_leaf, top_tree_addr, &hash_state_seeded); - - memcpy(pk + PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N, sk + 3 * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N); - - return 0; -} - -/* - * Generates an SPX key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk) { - - // guarantee alignment of pk - union { - __m128 _x[PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_CRYPTO_PUBLICKEYBYTES / 16]; - uint8_t pk[PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_CRYPTO_PUBLICKEYBYTES]; - } aligned_pk; - - // guarantee alignment of sk - union { - __m128 _x[PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_CRYPTO_SECRETKEYBYTES / 16]; - uint8_t sk[PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_CRYPTO_SECRETKEYBYTES]; - } aligned_sk; - - union { - __m128 _x[PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_CRYPTO_SEEDBYTES / 16]; - uint8_t seed[PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_CRYPTO_SEEDBYTES]; - } aligned_seed; - randombytes(aligned_seed.seed, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_CRYPTO_SEEDBYTES); - - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_crypto_sign_seed_keypair( - aligned_pk.pk, aligned_sk.sk, aligned_seed.seed); - memcpy(pk, aligned_pk.pk, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_CRYPTO_PUBLICKEYBYTES); - memcpy(sk, aligned_sk.sk, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_CRYPTO_SECRETKEYBYTES); - - return 0; -} - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - // guarantee alignment of sk - union { - __m128 *_x; - uint8_t sk[PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_CRYPTO_SECRETKEYBYTES]; - } aligned_sk; - memcpy(aligned_sk.sk, sk, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_CRYPTO_SECRETKEYBYTES); - sk = aligned_sk.sk; - - // guarantee alignment of sig - union { - __m128 *_x; - uint8_t sig[PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_BYTES]; - } aligned_sig; - uint8_t *orig_sig = sig; - sig = (uint8_t *)aligned_sig.sig; - - const unsigned char *sk_seed = sk; - const unsigned char *sk_prf = sk + PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N; - const unsigned char *pk = sk + 2 * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N; - const unsigned char *pub_seed = pk; - - unsigned char optrand[PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N]; - unsigned char mhash[PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_FORS_MSG_BYTES]; - unsigned char root[PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N]; - uint32_t i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - - hash_state hash_state_seeded; - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_initialize_hash_function( - &hash_state_seeded, - pub_seed, sk_seed); - - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_set_type( - wots_addr, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_set_type( - tree_addr, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_ADDR_TYPE_HASHTREE); - - /* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ - randombytes(optrand, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N); - /* Compute the digest randomization value. */ - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_gen_message_random( - sig, sk_prf, optrand, m, mlen, &hash_state_seeded); - - /* Derive the message digest and leaf index from R, PK and M. */ - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N; - - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_set_keypair_addr( - wots_addr, idx_leaf); - - /* Sign the message hash using FORS. */ - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_fors_sign( - sig, root, mhash, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_FORS_BYTES; - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_D; i++) { - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_set_tree_addr(tree_addr, tree); - - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_set_keypair_addr( - wots_addr, idx_leaf); - - /* Compute a WOTS signature. */ - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_wots_sign( - sig, root, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_WOTS_BYTES; - - /* Compute the authentication path for the used WOTS leaf. */ - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_treehash_TREE_HEIGHT( - root, sig, sk_seed, pub_seed, idx_leaf, 0, - wots_gen_leaf, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_TREE_HEIGHT * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_TREE_HEIGHT; - } - - memcpy(orig_sig, aligned_sig.sig, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_BYTES); - *siglen = PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_BYTES; - - return 0; -} - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk) { - // guarantee alignment of pk - union { - __m128 *_x; - uint8_t pk[PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_CRYPTO_PUBLICKEYBYTES]; - } aligned_pk; - memcpy(aligned_pk.pk, pk, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_CRYPTO_PUBLICKEYBYTES); - pk = aligned_pk.pk; - - const unsigned char *pub_seed = pk; - const unsigned char *pub_root = pk + PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N; - unsigned char mhash[PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_FORS_MSG_BYTES]; - unsigned char wots_pk[PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_WOTS_BYTES]; - unsigned char root[PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N]; - unsigned char leaf[PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N]; - unsigned int i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - hash_state hash_state_seeded; - - if (siglen != PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_BYTES) { - return -1; - } - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_initialize_hash_function( - &hash_state_seeded, - pub_seed, NULL); - - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_set_type( - wots_addr, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_set_type( - tree_addr, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_ADDR_TYPE_HASHTREE); - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_set_type( - wots_pk_addr, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_ADDR_TYPE_WOTSPK); - - /* Derive the message digest and leaf index from R || PK || M. */ - /* The additional PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N is a result of the hash domain separator. */ - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N; - - /* Layer correctly defaults to 0, so no need to set_layer_addr */ - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_set_keypair_addr( - wots_addr, idx_leaf); - - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_fors_pk_from_sig( - root, sig, mhash, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_FORS_BYTES; - - /* For each subtree.. */ - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_D; i++) { - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_set_tree_addr(tree_addr, tree); - - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_set_keypair_addr( - wots_addr, idx_leaf); - - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_copy_keypair_addr( - wots_pk_addr, wots_addr); - - /* The WOTS public key is only correct if the signature was correct. */ - /* Initially, root is the FORS pk, but on subsequent iterations it is - the root of the subtree below the currently processed subtree. */ - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_wots_pk_from_sig( - wots_pk, sig, root, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_WOTS_BYTES; - - /* Compute the leaf node using the WOTS public key. */ - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_thash_WOTS_LEN( - leaf, wots_pk, pub_seed, wots_pk_addr, &hash_state_seeded); - - /* Compute the root node of this subtree. */ - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_compute_root( - root, leaf, idx_leaf, 0, sig, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_TREE_HEIGHT, - pub_seed, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_TREE_HEIGHT * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_TREE_HEIGHT; - } - - /* Check if the root node equals the root node in the public key. */ - if (memcmp(root, pub_root, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N) != 0) { - return -1; - } - - return 0; -} - - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - size_t siglen; - - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_crypto_sign_signature( - sm, &siglen, m, mlen, sk); - - memmove(sm + PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_BYTES, m, mlen); - *smlen = siglen + mlen; - - return 0; -} - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk) { - - // guarantee alignment of pk - union { - __m128 *_x; - uint8_t pk[PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_CRYPTO_PUBLICKEYBYTES]; - } aligned_pk; - memcpy(aligned_pk.pk, pk, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_CRYPTO_PUBLICKEYBYTES); - pk = aligned_pk.pk; - - - /* The API caller does not necessarily know what size a signature should be - but SPHINCS+ signatures are always exactly PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_BYTES. */ - if (smlen < PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_BYTES) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - *mlen = smlen - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_BYTES; - - if (PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_crypto_sign_verify( - sm, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_BYTES, sm + PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_BYTES, *mlen, pk)) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - /* If verification was successful, move the message to the right place. */ - memmove(m, sm + PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_BYTES, *mlen); - - return 0; -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_avx2/thash.h b/src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_avx2/thash.h deleted file mode 100644 index ae7cb25d50..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_avx2/thash.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_THASH_H -#define PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_THASH_H - -#include "hash_state.h" - -#include - -void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_avx2/thash_shake256_simple.c b/src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_avx2/thash_shake256_simple.c deleted file mode 100644 index 1d9fef8d6e..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_avx2/thash_shake256_simple.c +++ /dev/null @@ -1,74 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash_state.h" -#include "params.h" -#include "thash.h" - -#include "fips202.h" - -/** - * Takes an array of inblocks concatenated arrays of PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N bytes. - */ -static void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_thash( - unsigned char *out, unsigned char *buf, - const unsigned char *in, unsigned int inblocks, - const unsigned char *pub_seed, uint32_t addr[8]) { - - memcpy(buf, pub_seed, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N); - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_addr_to_bytes(buf + PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N, addr); - memcpy(buf + PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_ADDR_BYTES, in, inblocks * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N); - - shake256(out, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N, buf, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N); -} - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_ADDR_BYTES + 1 * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N]; - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_thash( - out, buf, in, 1, pub_seed, addr); - - (void)hash_state_seeded; /* Avoid unused parameter warning. */ -} - -void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_ADDR_BYTES + 2 * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N]; - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_thash( - out, buf, in, 2, pub_seed, addr); - - (void)hash_state_seeded; /* Avoid unused parameter warning. */ -} - -void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_ADDR_BYTES + PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_WOTS_LEN * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N]; - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_thash( - out, buf, in, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_WOTS_LEN, pub_seed, addr); - - (void)hash_state_seeded; /* Avoid unused parameter warning. */ -} - -void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_ADDR_BYTES + PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_FORS_TREES * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N]; - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_thash( - out, buf, in, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_FORS_TREES, pub_seed, addr); - - (void)hash_state_seeded; /* Avoid unused parameter warning. */ -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_avx2/thash_shake256_simplex4.c b/src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_avx2/thash_shake256_simplex4.c deleted file mode 100644 index 93ff168a34..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_avx2/thash_shake256_simplex4.c +++ /dev/null @@ -1,47 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "thashx4.h" - -#include "fips202x4.h" - -/** - * 4-way parallel version of thash; takes 4x as much input and output - */ -#define thashx4_variant(name, inblocks) \ - void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_thashx4_##name( \ - unsigned char *out0, unsigned char *out1, unsigned char *out2, unsigned char *out3, \ - const unsigned char *in0, const unsigned char *in1, const unsigned char *in2, \ - const unsigned char *in3, const unsigned char *pub_seed, uint32_t addrx4[4 * 8], \ - const hash_state *state_seeded) { \ - unsigned char buf0[PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_ADDR_BYTES + (inblocks)*PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N]; \ - unsigned char buf1[PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_ADDR_BYTES + (inblocks)*PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N]; \ - unsigned char buf2[PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_ADDR_BYTES + (inblocks)*PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N]; \ - unsigned char buf3[PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_ADDR_BYTES + (inblocks)*PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N]; \ - \ - memcpy(buf0, pub_seed, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N); \ - memcpy(buf1, pub_seed, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N); \ - memcpy(buf2, pub_seed, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N); \ - memcpy(buf3, pub_seed, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N); \ - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_addr_to_bytes(buf0 + PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N, addrx4 + 0 * 8); \ - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_addr_to_bytes(buf1 + PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N, addrx4 + 1 * 8); \ - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_addr_to_bytes(buf2 + PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N, addrx4 + 2 * 8); \ - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_addr_to_bytes(buf3 + PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N, addrx4 + 3 * 8); \ - memcpy(buf0 + PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_ADDR_BYTES, in0, (inblocks)*PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N); \ - memcpy(buf1 + PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_ADDR_BYTES, in1, (inblocks)*PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N); \ - memcpy(buf2 + PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_ADDR_BYTES, in2, (inblocks)*PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N); \ - memcpy(buf3 + PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_ADDR_BYTES, in3, (inblocks)*PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N); \ - \ - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_shake256x4(out0, out1, out2, out3, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N, buf0, buf1, buf2, buf3, \ - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_ADDR_BYTES + (inblocks)*PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N); \ - \ - /* Avoid unused parameter warning */ \ - (void)state_seeded; \ - } - -thashx4_variant(1, 1) -thashx4_variant(2, 2) -thashx4_variant(WOTS_LEN, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_WOTS_LEN) -thashx4_variant(FORS_TREES, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_FORS_TREES) diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_avx2/thashx4.h b/src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_avx2/thashx4.h deleted file mode 100644 index bcf592112c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_avx2/thashx4.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_THASHX4_H -#define PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_THASHX4_H - -#include - -#include "hash_state.h" - -#define thashx4_header(inblocks) \ - void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_thashx4_##inblocks(unsigned char *out0, \ - unsigned char *out1, \ - unsigned char *out2, \ - unsigned char *out3, \ - const unsigned char *in0, \ - const unsigned char *in1, \ - const unsigned char *in2, \ - const unsigned char *in3, \ - const unsigned char *pub_seed, uint32_t addrx4[4*8], \ - const hash_state *state_seeded) - -thashx4_header(1); -thashx4_header(2); -thashx4_header(WOTS_LEN); -thashx4_header(FORS_TREES); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_avx2/utils.c b/src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_avx2/utils.c deleted file mode 100644 index 8b7d840fcb..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_avx2/utils.c +++ /dev/null @@ -1,199 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "hash_state.h" -#include "params.h" -#include "thash.h" -#include "utils.h" - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in) { - - /* Iterate over out in decreasing order, for big-endianness. */ - for (size_t i = outlen; i > 0; i--) { - out[i - 1] = in & 0xff; - in = in >> 8; - } -} - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_bytes_to_ull( - const unsigned char *in, size_t inlen) { - unsigned long long retval = 0; - - for (size_t i = 0; i < inlen; i++) { - retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); - } - return retval; -} - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - uint32_t i; - unsigned char buffer[2 * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N]; - - /* If leaf_idx is odd (last bit = 1), current path element is a right child - and auth_path has to go left. Otherwise it is the other way around. */ - if (leaf_idx & 1) { - memcpy(buffer + PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N, leaf, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N); - } else { - memcpy(buffer, leaf, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N); - memcpy(buffer + PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N, auth_path, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N); - } - auth_path += PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N; - - for (i = 0; i < tree_height - 1; i++) { - leaf_idx >>= 1; - idx_offset >>= 1; - /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_set_tree_height(addr, i + 1); - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_set_tree_index( - addr, leaf_idx + idx_offset); - - /* Pick the right or left neighbor, depending on parity of the node. */ - if (leaf_idx & 1) { - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_thash_2( - buffer + PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N); - } else { - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_thash_2( - buffer, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer + PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N, auth_path, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N); - } - auth_path += PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N; - } - - /* The last iteration is exceptional; we do not copy an auth_path node. */ - leaf_idx >>= 1; - idx_offset >>= 1; - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_set_tree_height(addr, tree_height); - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_set_tree_index( - addr, leaf_idx + idx_offset); - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_thash_2( - root, buffer, pub_seed, addr, hash_state_seeded); -} - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -static void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_treehash( - unsigned char *root, unsigned char *auth_path, - unsigned char *stack, unsigned int *heights, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - - unsigned int offset = 0; - uint32_t idx; - uint32_t tree_idx; - - for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { - /* Add the next leaf node to the stack. */ - gen_leaf(stack + offset * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N, - sk_seed, pub_seed, idx + idx_offset, tree_addr, - hash_state_seeded); - offset++; - heights[offset - 1] = 0; - - /* If this is a node we need for the auth path.. */ - if ((leaf_idx ^ 0x1) == idx) { - memcpy(auth_path, stack + (offset - 1)*PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N); - } - - /* While the top-most nodes are of equal height.. */ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { - /* Compute index of the new node, in the next layer. */ - tree_idx = (idx >> (heights[offset - 1] + 1)); - - /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_set_tree_height( - tree_addr, heights[offset - 1] + 1); - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_set_tree_index( - tree_addr, tree_idx + (idx_offset >> (heights[offset - 1] + 1))); - /* Hash the top-most nodes from the stack together. */ - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_thash_2( - stack + (offset - 2)*PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N, stack + (offset - 2)*PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N, - pub_seed, tree_addr, hash_state_seeded); - offset--; - /* Note that the top-most node is now one layer higher. */ - heights[offset - 1]++; - - /* If this is a node we need for the auth path.. */ - if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_path + heights[offset - 1]*PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N, - stack + (offset - 1)*PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N); - } - } - } - memcpy(root, stack, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N); -} - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_FORS_HEIGHT + 1)*PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N]; - unsigned int heights[PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_FORS_HEIGHT + 1]; - - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_FORS_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_TREE_HEIGHT + 1)*PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N]; - unsigned int heights[PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_TREE_HEIGHT + 1]; - - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_TREE_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_avx2/utils.h b/src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_avx2/utils.h deleted file mode 100644 index 8ffa2d458c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_avx2/utils.h +++ /dev/null @@ -1,64 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_UTILS_H -#define PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_UTILS_H - -#include "hash_state.h" -#include "params.h" -#include -#include - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in); - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_bytes_to_ull( - const unsigned char *in, size_t inlen); - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_avx2/utilsx4.c b/src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_avx2/utilsx4.c deleted file mode 100644 index 29a95a5305..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_avx2/utilsx4.c +++ /dev/null @@ -1,98 +0,0 @@ -#include "address.h" -#include "params.h" -#include "thashx4.h" -#include "utils.h" -#include "utilsx4.h" - -#include - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -#define treehashx4_variant(name, tree_height) \ - void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_treehashx4_##name( \ - unsigned char *rootx4, unsigned char *auth_pathx4, const unsigned char *sk_seed, \ - const unsigned char *pub_seed, const uint32_t leaf_idx[4], uint32_t idx_offset[4], \ - void (*gen_leafx4)(unsigned char * /* leaf0 */, unsigned char * /* leaf1 */, \ - unsigned char * /* leaf2 */, unsigned char * /* leaf3 */, \ - const unsigned char * /* sk_seed */, \ - const unsigned char * /* pub_seed */, uint32_t /* addr_idx0 */, \ - uint32_t /* addr_idx1 */, uint32_t /* addr_idx2 */, \ - uint32_t /* addr_idx3 */, const uint32_t[8] /* tree_addr */, \ - const hash_state * /* state_seeded */), \ - uint32_t tree_addrx4[4 * 8], const hash_state *state_seeded) { \ - unsigned char stackx4[4 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N]; \ - unsigned int heights[(tree_height) + 1]; \ - unsigned int offset = 0; \ - uint32_t idx; \ - uint32_t tree_idx; \ - unsigned int j; \ - \ - for (idx = 0; idx < (uint32_t)(1 << (tree_height)); idx++) { \ - /* Add the next leaf node to the stack. */ \ - gen_leafx4(stackx4 + 0 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N + offset * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N, \ - stackx4 + 1 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N + offset * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N, \ - stackx4 + 2 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N + offset * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N, \ - stackx4 + 3 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N + offset * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N, sk_seed, \ - pub_seed, idx + idx_offset[0], idx + idx_offset[1], idx + idx_offset[2], \ - idx + idx_offset[3], tree_addrx4, state_seeded); \ - offset++; \ - heights[offset - 1] = 0; \ - \ - /* If this is a node we need for the auth path.. */ \ - for (j = 0; j < 4; j++) { \ - if ((leaf_idx[j] ^ 0x1) == idx) { \ - memcpy(auth_pathx4 + j * (tree_height)*PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N, \ - stackx4 + j * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N + (offset - 1) * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N, \ - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N); \ - } \ - } \ - \ - /* While the top-most nodes are of equal height.. */ \ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { \ - /* Compute index of the new node, in the next layer. */ \ - tree_idx = (idx >> (heights[offset - 1] + 1)); \ - \ - /* Set the address of the node we're creating. */ \ - for (j = 0; j < 4; j++) { \ - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_set_tree_height(tree_addrx4 + j * 8, heights[offset - 1] + 1); \ - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_set_tree_index(tree_addrx4 + j * 8, \ - tree_idx + (idx_offset[j] >> (heights[offset - 1] + 1))); \ - } \ - /* Hash the top-most nodes from the stack together. */ \ - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_thashx4_2(stackx4 + 0 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N + (offset - 2) * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N, \ - stackx4 + 1 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N + (offset - 2) * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N, \ - stackx4 + 2 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N + (offset - 2) * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N, \ - stackx4 + 3 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N + (offset - 2) * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N, \ - stackx4 + 0 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N + (offset - 2) * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N, \ - stackx4 + 1 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N + (offset - 2) * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N, \ - stackx4 + 2 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N + (offset - 2) * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N, \ - stackx4 + 3 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N + (offset - 2) * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N, \ - pub_seed, tree_addrx4, state_seeded); \ - offset--; \ - /* Note that the top-most node is now one layer higher. */ \ - heights[offset - 1]++; \ - \ - /* If this is a node we need for the auth path.. */ \ - for (j = 0; j < 4; j++) { \ - if (((leaf_idx[j] >> heights[offset - 1]) ^ 0x1) == tree_idx) { \ - memcpy(auth_pathx4 + j * (tree_height)*PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N + \ - heights[offset - 1] * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N, \ - stackx4 + j * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N + (offset - 1) * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N, \ - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N); \ - } \ - } \ - } \ - } \ - \ - for (j = 0; j < 4; j++) { \ - memcpy(rootx4 + j * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N, stackx4 + j * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N); \ - } \ - } - -treehashx4_variant(FORS_HEIGHT, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_FORS_HEIGHT) diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_avx2/utilsx4.h b/src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_avx2/utilsx4.h deleted file mode 100644 index 70d9a02432..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_avx2/utilsx4.h +++ /dev/null @@ -1,38 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_UTILSX4_H -#define PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_UTILSX4_H - -#include "hash_state.h" -#include "params.h" - -#include - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_treehashx4_FORS_HEIGHT(unsigned char *rootx4, - unsigned char *auth_pathx4, - const unsigned char *sk_seed, - const unsigned char *pub_seed, - const uint32_t leaf_idx[4], - uint32_t idx_offset[4], - void (*gen_leafx4)(unsigned char * /* leaf0 */, - unsigned char * /* leaf1 */, - unsigned char * /* leaf2 */, - unsigned char * /* leaf3 */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx0 */, - uint32_t /* addr_idx1 */, - uint32_t /* addr_idx2 */, - uint32_t /* addr_idx3 */, - const uint32_t[8] /* tree_addr */, - const hash_state * /* state_seeded */), - uint32_t tree_addrx4[4 * 8], - const hash_state *state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_avx2/wots.c b/src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_avx2/wots.c deleted file mode 100644 index cca39822d9..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_avx2/wots.c +++ /dev/null @@ -1,240 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "hash_state.h" -#include "hashx4.h" -#include "params.h" -#include "thash.h" -#include "thashx4.h" -#include "utils.h" -#include "wots.h" - -// TODO clarify address expectations, and make them more uniform. -// TODO i.e. do we expect types to be set already? -// TODO and do we expect modifications or copies? - -/** - * Computes the starting value for a chain, i.e. the secret key. - * Expects the address to be complete up to the chain address. - */ -static void wots_gen_sk(unsigned char *sk, const unsigned char *sk_seed, - uint32_t wots_addr[8], const hash_state *state_seeded) { - /* Make sure that the hash address is actually zeroed. */ - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_set_hash_addr(wots_addr, 0); - - /* Generate sk element. */ - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_prf_addr(sk, sk_seed, wots_addr, state_seeded); -} - -/** - * 4-way parallel version of wots_gen_sk; expects 4x as much space in sk - */ -static void wots_gen_skx4(unsigned char *skx4, const unsigned char *sk_seed, - uint32_t wots_addrx4[4 * 8], const hash_state *state_seeded) { - unsigned int j; - - /* Make sure that the hash address is actually zeroed. */ - for (j = 0; j < 4; j++) { - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_set_hash_addr(wots_addrx4 + j * 8, 0); - } - - /* Generate sk element. */ - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_prf_addrx4(skx4 + 0 * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N, - skx4 + 1 * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N, - skx4 + 2 * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N, - skx4 + 3 * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N, - sk_seed, wots_addrx4, - state_seeded); -} - -/** - * Computes the chaining function. - * out and in have to be n-byte arrays. - * - * Interprets in as start-th value of the chain. - * addr has to contain the address of the chain. - */ -static void gen_chain(unsigned char *out, const unsigned char *in, - unsigned int start, unsigned int steps, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *state_seeded) { - uint32_t i; - - /* Initialize out with the value at position 'start'. */ - memcpy(out, in, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N); - - /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_WOTS_W; i++) { - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_set_hash_addr(addr, i); - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_thash_1(out, out, pub_seed, addr, state_seeded); - } -} - -/** - * 4-way parallel version of gen_chain; expects 4x as much space in out, and - * 4x as much space in inx4. Assumes start and step identical across chains. - */ -static void gen_chainx4(unsigned char *outx4, const unsigned char *inx4, - unsigned int start, unsigned int steps, - const unsigned char *pub_seed, uint32_t addrx4[4 * 8], - const hash_state *state_seeded) { - uint32_t i; - unsigned int j; - - /* Initialize outx4 with the value at position 'start'. */ - memcpy(outx4, inx4, 4 * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N); - - /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_WOTS_W; i++) { - for (j = 0; j < 4; j++) { - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_set_hash_addr(addrx4 + j * 8, i); - } - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_thashx4_1(outx4 + 0 * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N, - outx4 + 1 * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N, - outx4 + 2 * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N, - outx4 + 3 * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N, - outx4 + 0 * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N, - outx4 + 1 * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N, - outx4 + 2 * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N, - outx4 + 3 * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N, - pub_seed, addrx4, - state_seeded); - } -} - -/** - * base_w algorithm as described in draft. - * Interprets an array of bytes as integers in base w. - * This only works when log_w is a divisor of 8. - */ -static void base_w(unsigned int *output, const int out_len, const unsigned char *input) { - int in = 0; - int out = 0; - unsigned char total = 0; - int bits = 0; - int consumed; - - for (consumed = 0; consumed < out_len; consumed++) { - if (bits == 0) { - total = input[in]; - in++; - bits += 8; - } - bits -= PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_WOTS_LOGW; - output[out] = (unsigned int)(total >> bits) & (PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_WOTS_W - 1); - out++; - } -} - -/* Computes the WOTS+ checksum over a message (in base_w). */ -static void wots_checksum(unsigned int *csum_base_w, const unsigned int *msg_base_w) { - unsigned int csum = 0; - unsigned char csum_bytes[(PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_WOTS_LEN2 * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_WOTS_LOGW + 7) / 8]; - unsigned int i; - - /* Compute checksum. */ - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_WOTS_LEN1; i++) { - csum += PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_WOTS_W - 1 - msg_base_w[i]; - } - - /* Convert checksum to base_w. */ - /* Make sure expected empty zero bits are the least significant bits. */ - csum = csum << (8 - ((PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_WOTS_LEN2 * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_WOTS_LOGW) % 8)); - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); - base_w(csum_base_w, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_WOTS_LEN2, csum_bytes); -} - -/* Takes a message and derives the matching chain lengths. */ -static void chain_lengths(unsigned int *lengths, const unsigned char *msg) { - base_w(lengths, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_WOTS_LEN1, msg); - wots_checksum(lengths + PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_WOTS_LEN1, lengths); -} - -/** - * WOTS key generation. Takes a 32 byte sk_seed, expands it to WOTS private key - * elements and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_wots_gen_pk(unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *state_seeded) { - uint32_t i; - unsigned int j; - - uint32_t addrx4[4 * 8]; - unsigned char pkbuf[4 * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N]; - - for (j = 0; j < 4; j++) { - memcpy(addrx4 + j * 8, addr, sizeof(uint32_t) * 8); - } - - /* The last iteration typically does not have complete set of 4 chains, - but because we use pkbuf, this is not an issue -- we still do as many - in parallel as possible. */ - for (i = 0; i < ((PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_WOTS_LEN + 3) & ~0x3); i += 4) { - for (j = 0; j < 4; j++) { - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_set_chain_addr(addrx4 + j * 8, i + j); - } - wots_gen_skx4(pkbuf, sk_seed, addrx4, state_seeded); - gen_chainx4(pkbuf, pkbuf, 0, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_WOTS_W - 1, pub_seed, addrx4, state_seeded); - for (j = 0; j < 4; j++) { - if (i + j < PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_WOTS_LEN) { - memcpy(pk + (i + j)*PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N, pkbuf + j * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N); - } - } - } - - // Get rid of unused argument variable. - (void)state_seeded; -} - -/** - * Takes a n-byte message and the 32-byte sk_see to compute a signature 'sig'. - */ -void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_wots_sign(unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_WOTS_LEN; i++) { - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_set_chain_addr(addr, i); - wots_gen_sk(sig + i * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N, sk_seed, addr, state_seeded); - gen_chain(sig + i * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N, sig + i * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N, 0, lengths[i], pub_seed, addr, state_seeded); - } - - // avoid unused argument - (void)state_seeded; -} - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_WOTS_LEN; i++) { - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_set_chain_addr(addr, i); - gen_chain(pk + i * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N, sig + i * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_N, - lengths[i], PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_WOTS_W - 1 - lengths[i], pub_seed, addr, - state_seeded); - } - - // avoid unused argument - (void)state_seeded; -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_avx2/wots.h b/src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_avx2/wots.h deleted file mode 100644 index 117c39a032..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_avx2/wots.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_WOTS_H -#define PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_WOTS_H - -#include "hash_state.h" -#include "params.h" -#include - -/** - * WOTS key generation. Takes a 32 byte seed for the private key, expands it to - * a full WOTS private key and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_wots_gen_pk( - unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -/** - * Takes a n-byte message and the 32-byte seed for the private key to compute a - * signature that is placed at 'sig'. - */ -void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_wots_sign( - unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *hash_state_seeded); - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_wots_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_clean/LICENSE b/src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_clean/LICENSE deleted file mode 100644 index 670154e353..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_clean/LICENSE +++ /dev/null @@ -1,116 +0,0 @@ -CC0 1.0 Universal - -Statement of Purpose - -The laws of most jurisdictions throughout the world automatically confer -exclusive Copyright and Related Rights (defined below) upon the creator and -subsequent owner(s) (each and all, an "owner") of an original work of -authorship and/or a database (each, a "Work"). - -Certain owners wish to permanently relinquish those rights to a Work for the -purpose of contributing to a commons of creative, cultural and scientific -works ("Commons") that the public can reliably and without fear of later -claims of infringement build upon, modify, incorporate in other works, reuse -and redistribute as freely as possible in any form whatsoever and for any -purposes, including without limitation commercial purposes. These owners may -contribute to the Commons to promote the ideal of a free culture and the -further production of creative, cultural and scientific works, or to gain -reputation or greater distribution for their Work in part through the use and -efforts of others. - -For these and/or other purposes and motivations, and without any expectation -of additional consideration or compensation, the person associating CC0 with a -Work (the "Affirmer"), to the extent that he or she is an owner of Copyright -and Related Rights in the Work, voluntarily elects to apply CC0 to the Work -and publicly distribute the Work under its terms, with knowledge of his or her -Copyright and Related Rights in the Work and the meaning and intended legal -effect of CC0 on those rights. - -1. Copyright and Related Rights. A Work made available under CC0 may be -protected by copyright and related or neighboring rights ("Copyright and -Related Rights"). Copyright and Related Rights include, but are not limited -to, the following: - - i. the right to reproduce, adapt, distribute, perform, display, communicate, - and translate a Work; - - ii. moral rights retained by the original author(s) and/or performer(s); - - iii. publicity and privacy rights pertaining to a person's image or likeness - depicted in a Work; - - iv. rights protecting against unfair competition in regards to a Work, - subject to the limitations in paragraph 4(a), below; - - v. rights protecting the extraction, dissemination, use and reuse of data in - a Work; - - vi. database rights (such as those arising under Directive 96/9/EC of the - European Parliament and of the Council of 11 March 1996 on the legal - protection of databases, and under any national implementation thereof, - including any amended or successor version of such directive); and - - vii. other similar, equivalent or corresponding rights throughout the world - based on applicable law or treaty, and any national implementations thereof. - -2. Waiver. To the greatest extent permitted by, but not in contravention of, -applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and -unconditionally waives, abandons, and surrenders all of Affirmer's Copyright -and Related Rights and associated claims and causes of action, whether now -known or unknown (including existing as well as future claims and causes of -action), in the Work (i) in all territories worldwide, (ii) for the maximum -duration provided by applicable law or treaty (including future time -extensions), (iii) in any current or future medium and for any number of -copies, and (iv) for any purpose whatsoever, including without limitation -commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes -the Waiver for the benefit of each member of the public at large and to the -detriment of Affirmer's heirs and successors, fully intending that such Waiver -shall not be subject to revocation, rescission, cancellation, termination, or -any other legal or equitable action to disrupt the quiet enjoyment of the Work -by the public as contemplated by Affirmer's express Statement of Purpose. - -3. Public License Fallback. Should any part of the Waiver for any reason be -judged legally invalid or ineffective under applicable law, then the Waiver -shall be preserved to the maximum extent permitted taking into account -Affirmer's express Statement of Purpose. In addition, to the extent the Waiver -is so judged Affirmer hereby grants to each affected person a royalty-free, -non transferable, non sublicensable, non exclusive, irrevocable and -unconditional license to exercise Affirmer's Copyright and Related Rights in -the Work (i) in all territories worldwide, (ii) for the maximum duration -provided by applicable law or treaty (including future time extensions), (iii) -in any current or future medium and for any number of copies, and (iv) for any -purpose whatsoever, including without limitation commercial, advertising or -promotional purposes (the "License"). The License shall be deemed effective as -of the date CC0 was applied by Affirmer to the Work. Should any part of the -License for any reason be judged legally invalid or ineffective under -applicable law, such partial invalidity or ineffectiveness shall not -invalidate the remainder of the License, and in such case Affirmer hereby -affirms that he or she will not (i) exercise any of his or her remaining -Copyright and Related Rights in the Work or (ii) assert any associated claims -and causes of action with respect to the Work, in either case contrary to -Affirmer's express Statement of Purpose. - -4. Limitations and Disclaimers. - - a. No trademark or patent rights held by Affirmer are waived, abandoned, - surrendered, licensed or otherwise affected by this document. - - b. Affirmer offers the Work as-is and makes no representations or warranties - of any kind concerning the Work, express, implied, statutory or otherwise, - including without limitation warranties of title, merchantability, fitness - for a particular purpose, non infringement, or the absence of latent or - other defects, accuracy, or the present or absence of errors, whether or not - discoverable, all to the greatest extent permissible under applicable law. - - c. Affirmer disclaims responsibility for clearing rights of other persons - that may apply to the Work or any use thereof, including without limitation - any person's Copyright and Related Rights in the Work. Further, Affirmer - disclaims responsibility for obtaining any necessary consents, permissions - or other rights required for any use of the Work. - - d. Affirmer understands and acknowledges that Creative Commons is not a - party to this document and has no duty or obligation with respect to this - CC0 or use of the Work. - -For more information, please see - diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_clean/address.c b/src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_clean/address.c deleted file mode 100644 index 1a3092c078..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_clean/address.c +++ /dev/null @@ -1,78 +0,0 @@ -#include - -#include "address.h" -#include "params.h" -#include "utils.h" - -void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]) { - int i; - - for (i = 0; i < 8; i++) { - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_ull_to_bytes( - bytes + i * 4, 4, addr[i]); - } -} - -void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_set_layer_addr( - uint32_t addr[8], uint32_t layer) { - addr[0] = layer; -} - -void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_set_tree_addr( - uint32_t addr[8], uint64_t tree) { - addr[1] = 0; - addr[2] = (uint32_t) (tree >> 32); - addr[3] = (uint32_t) tree; -} - -void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_set_type( - uint32_t addr[8], uint32_t type) { - addr[4] = type; -} - -void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; -} - -/* These functions are used for OTS addresses. */ - -void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_set_keypair_addr( - uint32_t addr[8], uint32_t keypair) { - addr[5] = keypair; -} - -void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; - out[5] = in[5]; -} - -void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_set_chain_addr( - uint32_t addr[8], uint32_t chain) { - addr[6] = chain; -} - -void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_set_hash_addr( - uint32_t addr[8], uint32_t hash) { - addr[7] = hash; -} - -/* These functions are used for all hash tree addresses (including FORS). */ - -void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_set_tree_height( - uint32_t addr[8], uint32_t tree_height) { - addr[6] = tree_height; -} - -void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_set_tree_index( - uint32_t addr[8], uint32_t tree_index) { - addr[7] = tree_index; -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_clean/address.h b/src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_clean/address.h deleted file mode 100644 index af5b119e5f..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_clean/address.h +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_ADDRESS_H -#define PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_ADDRESS_H - -#include - -#define PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_ADDR_TYPE_WOTS 0 -#define PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_ADDR_TYPE_WOTSPK 1 -#define PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_ADDR_TYPE_HASHTREE 2 -#define PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_ADDR_TYPE_FORSTREE 3 -#define PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_ADDR_TYPE_FORSPK 4 - -void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]); - -void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_set_layer_addr( - uint32_t addr[8], uint32_t layer); - -void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_set_tree_addr( - uint32_t addr[8], uint64_t tree); - -void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_set_type( - uint32_t addr[8], uint32_t type); - -/* Copies the layer and tree part of one address into the other */ -void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for WOTS and FORS addresses. */ - -void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_set_keypair_addr( - uint32_t addr[8], uint32_t keypair); - -void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_set_chain_addr( - uint32_t addr[8], uint32_t chain); - -void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_set_hash_addr( - uint32_t addr[8], uint32_t hash); - -void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for all hash tree addresses (including FORS). */ - -void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_set_tree_height( - uint32_t addr[8], uint32_t tree_height); - -void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_set_tree_index( - uint32_t addr[8], uint32_t tree_index); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_clean/api.h b/src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_clean/api.h deleted file mode 100644 index 69490ec3f9..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_clean/api.h +++ /dev/null @@ -1,81 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_API_H -#define PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_API_H - -#include -#include - - - -#define PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_CRYPTO_ALGNAME "SPHINCS+" - -#define PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_CRYPTO_SECRETKEYBYTES 96 -#define PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_CRYPTO_PUBLICKEYBYTES 48 -#define PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_CRYPTO_BYTES 16224 -#define PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_CRYPTO_SEEDBYTES 72 - - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_clean/fors.c b/src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_clean/fors.c deleted file mode 100644 index f4bacdc668..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_clean/fors.c +++ /dev/null @@ -1,161 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "fors.h" -#include "hash.h" -#include "hash_state.h" -#include "thash.h" -#include "utils.h" - -static void fors_gen_sk(unsigned char *sk, const unsigned char *sk_seed, - uint32_t fors_leaf_addr[8], const hash_state *hash_state_seeded) { - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_prf_addr( - sk, sk_seed, fors_leaf_addr, hash_state_seeded); -} - -static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, - const unsigned char *pub_seed, - uint32_t fors_leaf_addr[8], - const hash_state *hash_state_seeded) { - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_thash_1( - leaf, sk, pub_seed, fors_leaf_addr, hash_state_seeded); -} - -static void fors_gen_leaf(unsigned char *leaf, const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx, const uint32_t fors_tree_addr[8], - const hash_state *hash_state_seeded) { - uint32_t fors_leaf_addr[8] = {0}; - - /* Only copy the parts that must be kept in fors_leaf_addr. */ - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_copy_keypair_addr( - fors_leaf_addr, fors_tree_addr); - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_set_type( - fors_leaf_addr, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_set_tree_index( - fors_leaf_addr, addr_idx); - - fors_gen_sk(leaf, sk_seed, fors_leaf_addr, hash_state_seeded); - fors_sk_to_leaf(leaf, leaf, pub_seed, fors_leaf_addr, hash_state_seeded); -} - -/** - * Interprets m as PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_FORS_HEIGHT-bit unsigned integers. - * Assumes m contains at least PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_FORS_TREES bits. - * Assumes indices has space for PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_FORS_TREES integers. - */ -static void message_to_indices(uint32_t *indices, const unsigned char *m) { - unsigned int i, j; - unsigned int offset = 0; - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_FORS_TREES; i++) { - indices[i] = 0; - for (j = 0; j < PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_FORS_HEIGHT; j++) { - indices[i] ^= (((uint32_t)m[offset >> 3] >> (offset & 0x7)) & 0x1) << j; - offset++; - } - } -} - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_fors_sign( - unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *hash_state_seeded) { - uint32_t indices[PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_FORS_TREES]; - unsigned char roots[PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_FORS_TREES * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_N]; - uint32_t fors_tree_addr[8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_copy_keypair_addr( - fors_tree_addr, fors_addr); - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_copy_keypair_addr( - fors_pk_addr, fors_addr); - - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_set_type( - fors_tree_addr, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_set_type( - fors_pk_addr, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_FORS_TREES; i++) { - idx_offset = i * (1 << PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_FORS_HEIGHT); - - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_set_tree_height( - fors_tree_addr, 0); - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_set_tree_index( - fors_tree_addr, indices[i] + idx_offset); - - /* Include the secret key part that produces the selected leaf node. */ - fors_gen_sk(sig, sk_seed, fors_tree_addr, hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_N; - - /* Compute the authentication path for this leaf node. */ - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_treehash_FORS_HEIGHT( - roots + i * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_N, sig, sk_seed, pub_seed, - indices[i], idx_offset, fors_gen_leaf, fors_tree_addr, - hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_N * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_thash_FORS_TREES( - pk, roots, pub_seed, fors_pk_addr, hash_state_seeded); -} - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_fors_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, const uint32_t fors_addr[8], - const hash_state *hash_state_seeded) { - uint32_t indices[PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_FORS_TREES]; - unsigned char roots[PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_FORS_TREES * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_N]; - unsigned char leaf[PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_N]; - uint32_t fors_tree_addr[8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_copy_keypair_addr(fors_tree_addr, fors_addr); - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_copy_keypair_addr(fors_pk_addr, fors_addr); - - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_set_type(fors_tree_addr, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_set_type(fors_pk_addr, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_FORS_TREES; i++) { - idx_offset = i * (1 << PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_FORS_HEIGHT); - - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_set_tree_height(fors_tree_addr, 0); - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Derive the leaf from the included secret key part. */ - fors_sk_to_leaf(leaf, sig, pub_seed, fors_tree_addr, hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_N; - - /* Derive the corresponding root node of this tree. */ - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_compute_root(roots + i * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_N, leaf, indices[i], idx_offset, sig, - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_FORS_HEIGHT, pub_seed, fors_tree_addr, hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_N * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_thash_FORS_TREES(pk, roots, pub_seed, fors_pk_addr, hash_state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_clean/fors.h b/src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_clean/fors.h deleted file mode 100644 index 108620f7f8..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_clean/fors.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_FORS_H -#define PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_FORS_H - -#include - -#include "hash_state.h" -#include "params.h" - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_fors_sign( - unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *hash_state_seeded); - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_fors_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, const uint32_t fors_addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_clean/hash.h b/src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_clean/hash.h deleted file mode 100644 index 5f1390ad96..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_clean/hash.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_HASH_H -#define PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_HASH_H - -#include "hash_state.h" - -#include -#include - -void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_initialize_hash_function( - hash_state *hash_state_seeded, - const unsigned char *pub_seed, const unsigned char *sk_seed); - -void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_destroy_hash_function(hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_clean/hash_shake256.c b/src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_clean/hash_shake256.c deleted file mode 100644 index 26c5d91235..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_clean/hash_shake256.c +++ /dev/null @@ -1,106 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "utils.h" - -#include "fips202.h" - -/* For SHAKE256, there is no immediate reason to initialize at the start, - so this function is an empty operation. */ -void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_initialize_hash_function( - hash_state *hash_state_seeded, // NOLINT(readability-non-const-parameter) - const unsigned char *pub_seed, const unsigned char *sk_seed) { - (void)hash_state_seeded; /* Suppress an 'unused parameter' warning. */ - (void)pub_seed; /* Suppress an 'unused parameter' warning. */ - (void)sk_seed; /* Suppress an 'unused parameter' warning. */ -} - -/* This is not necessary for SHAKE256, so we don't do anything */ -void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_destroy_hash_function( - hash_state *hash_state_seeded) { // NOLINT(readability-non-const-parameter) - (void)hash_state_seeded; -} - -/* - * Computes PRF(key, addr), given a secret key of PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_N bytes and an address - */ -void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded) { - unsigned char buf[PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_N + PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_ADDR_BYTES]; - - memcpy(buf, key, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_N); - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_addr_to_bytes(buf + PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_N, addr); - - shake256(out, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_N, buf, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_N + PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_ADDR_BYTES); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} - -/** - * Computes the message-dependent randomness R, using a secret seed and an - * optional randomization value as well as the message. - */ -void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded) { - shake256incctx state; - - shake256_inc_init(&state); - shake256_inc_absorb(&state, sk_prf, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_N); - shake256_inc_absorb(&state, optrand, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_N); - shake256_inc_absorb(&state, m, mlen); - shake256_inc_finalize(&state); - shake256_inc_squeeze(R, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_N, &state); - shake256_inc_ctx_release(&state); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} - -/** - * Computes the message hash using R, the public key, and the message. - * Outputs the message digest and the index of the leaf. The index is split in - * the tree index and the leaf index, for convenient copying to an address. - */ -void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded) { -#define PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_TREE_BITS (PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_TREE_HEIGHT * (PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_D - 1)) -#define PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_TREE_BYTES ((PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_TREE_BITS + 7) / 8) -#define PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_LEAF_BITS PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_TREE_HEIGHT -#define PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_LEAF_BYTES ((PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_LEAF_BITS + 7) / 8) -#define PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_DGST_BYTES (PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_FORS_MSG_BYTES + PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_TREE_BYTES + PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_LEAF_BYTES) - - unsigned char buf[PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_DGST_BYTES]; - unsigned char *bufp = buf; - shake256incctx state; - - shake256_inc_init(&state); - shake256_inc_absorb(&state, R, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_N); - shake256_inc_absorb(&state, pk, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_PK_BYTES); - shake256_inc_absorb(&state, m, mlen); - shake256_inc_finalize(&state); - shake256_inc_squeeze(buf, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_DGST_BYTES, &state); - shake256_inc_ctx_release(&state); - - memcpy(digest, bufp, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_FORS_MSG_BYTES); - bufp += PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_FORS_MSG_BYTES; - - *tree = PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_bytes_to_ull( - bufp, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_TREE_BYTES); - *tree &= (~(uint64_t)0) >> (64 - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_TREE_BITS); - bufp += PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_TREE_BYTES; - - *leaf_idx = (uint32_t)PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_bytes_to_ull( - bufp, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_LEAF_BYTES); - *leaf_idx &= (~(uint32_t)0) >> (32 - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_LEAF_BITS); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_clean/hash_state.h b/src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_clean/hash_state.h deleted file mode 100644 index 7d92ef872a..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_clean/hash_state.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef SPX_HASH_STATE_H -#define SPX_HASH_STATE_H - -/** - * Defines the type of the hash function state. - * - * Don't be fooled into thinking this instance of SPHINCS+ isn't stateless! - * - * From Section 7.2.2 from the SPHINCS+ round-2 specification: - * - * Each of the instances of the tweakable hash function take PK.seed as its - * first input, which is constant for a given key pair – and, thus, across - * a single signature. This leads to a lot of redundant computation. To remedy - * this, we pad PK.seed to the length of a full 64-byte SHA-256 input block. - * Because of the Merkle-Damgård construction that underlies SHA-256, this - * allows for reuse of the intermediate SHA-256 state after the initial call to - * the compression function which improves performance. - * - * We pass this hash state around in functions, because otherwise we need to - * have a global variable. - * - * SHAKE256 does not need this state. Because this implementation is generated - * from a shared code base, we still need to specify some hash_state as it is - * still passed around. We chose to use an `int` as a placeholder for this - * purpose. - */ - -#define hash_state int - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_clean/params.h b/src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_clean/params.h deleted file mode 100644 index c75842b5bb..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_clean/params.h +++ /dev/null @@ -1,53 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_PARAMS_H -#define PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_PARAMS_H - -/* Hash output length in bytes. */ -#define PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_N 24 -/* Height of the hypertree. */ -#define PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_FULL_HEIGHT 63 -/* Number of subtree layer. */ -#define PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_D 7 -/* FORS tree dimensions. */ -#define PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_FORS_HEIGHT 14 -#define PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_FORS_TREES 17 -/* Winternitz parameter, */ -#define PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_WOTS_W 16 - -/* The hash function is defined by linking a different hash.c file, as opposed - to setting a #define constant. */ - -/* For clarity */ -#define PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_ADDR_BYTES 32 - -/* WOTS parameters. */ -#define PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_WOTS_LOGW 4 - -#define PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_WOTS_LEN1 (8 * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_N / PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_WOTS_LOGW) - -/* PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#define PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_WOTS_LEN2 3 - -#define PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_WOTS_LEN (PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_WOTS_LEN1 + PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_WOTS_LEN2) -#define PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_WOTS_BYTES (PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_WOTS_LEN * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_N) -#define PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_WOTS_PK_BYTES PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_WOTS_BYTES - -/* Subtree size. */ -#define PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_TREE_HEIGHT (PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_FULL_HEIGHT / PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_D) - -/* FORS parameters. */ -#define PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_FORS_MSG_BYTES ((PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_FORS_TREES + 7) / 8) -#define PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_FORS_BYTES ((PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_FORS_HEIGHT + 1) * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_FORS_TREES * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_N) -#define PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_FORS_PK_BYTES PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_N - -/* Resulting SPX sizes. */ -#define PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_BYTES (PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_N + PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_FORS_BYTES + PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_D * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_WOTS_BYTES +\ - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_FULL_HEIGHT * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_N) -#define PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_PK_BYTES (2 * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_N) -#define PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_SK_BYTES (2 * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_N + PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_PK_BYTES) - -/* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ -#define PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_OPTRAND_BYTES 32 - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_clean/sign.c b/src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_clean/sign.c deleted file mode 100644 index 5221796156..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_clean/sign.c +++ /dev/null @@ -1,356 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "api.h" -#include "fors.h" -#include "hash.h" -#include "hash_state.h" -#include "params.h" -#include "randombytes.h" -#include "thash.h" -#include "utils.h" -#include "wots.h" - -/** - * Computes the leaf at a given address. First generates the WOTS key pair, - * then computes leaf by hashing horizontally. - */ -static void wots_gen_leaf(unsigned char *leaf, const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx, const uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - unsigned char pk[PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_WOTS_BYTES]; - uint32_t wots_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_set_type( - wots_addr, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_set_type( - wots_pk_addr, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_ADDR_TYPE_WOTSPK); - - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_set_keypair_addr( - wots_addr, addr_idx); - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_wots_gen_pk( - pk, sk_seed, pub_seed, wots_addr, hash_state_seeded); - - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_copy_keypair_addr( - wots_pk_addr, wots_addr); - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_thash_WOTS_LEN( - leaf, pk, pub_seed, wots_pk_addr, hash_state_seeded); -} - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_crypto_sign_secretkeybytes(void) { - return PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_CRYPTO_SECRETKEYBYTES; -} - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_crypto_sign_publickeybytes(void) { - return PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_CRYPTO_PUBLICKEYBYTES; -} - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_crypto_sign_bytes(void) { - return PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_CRYPTO_BYTES; -} - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_crypto_sign_seedbytes(void) { - return PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_CRYPTO_SEEDBYTES; -} - -/* - * Generates an SPX key pair given a seed of length - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed) { - /* We do not need the auth path in key generation, but it simplifies the - code to have just one treehash routine that computes both root and path - in one function. */ - unsigned char auth_path[PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_TREE_HEIGHT * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_N]; - uint32_t top_tree_addr[8] = {0}; - hash_state hash_state_seeded; - - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_set_layer_addr( - top_tree_addr, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_D - 1); - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_set_type( - top_tree_addr, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_ADDR_TYPE_HASHTREE); - - /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ - memcpy(sk, seed, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_CRYPTO_SEEDBYTES); - - memcpy(pk, sk + 2 * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_N, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_initialize_hash_function(&hash_state_seeded, pk, sk); - - /* Compute root node of the top-most subtree. */ - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_treehash_TREE_HEIGHT( - sk + 3 * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_N, auth_path, sk, sk + 2 * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_N, 0, 0, - wots_gen_leaf, top_tree_addr, &hash_state_seeded); - - memcpy(pk + PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_N, sk + 3 * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_N, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_N); - - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_destroy_hash_function(&hash_state_seeded); - return 0; -} - -/* - * Generates an SPX key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk) { - unsigned char seed[PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_CRYPTO_SEEDBYTES]; - randombytes(seed, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_CRYPTO_SEEDBYTES); - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_crypto_sign_seed_keypair( - pk, sk, seed); - - return 0; -} - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - const unsigned char *sk_seed = sk; - const unsigned char *sk_prf = sk + PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_N; - const unsigned char *pk = sk + 2 * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_N; - const unsigned char *pub_seed = pk; - - unsigned char optrand[PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_N]; - unsigned char mhash[PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_FORS_MSG_BYTES]; - unsigned char root[PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_N]; - uint32_t i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - - hash_state hash_state_seeded; - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_initialize_hash_function( - &hash_state_seeded, - pub_seed, sk_seed); - - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_set_type( - wots_addr, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_set_type( - tree_addr, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_ADDR_TYPE_HASHTREE); - - /* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ - randombytes(optrand, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_N); - /* Compute the digest randomization value. */ - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_gen_message_random( - sig, sk_prf, optrand, m, mlen, &hash_state_seeded); - - /* Derive the message digest and leaf index from R, PK and M. */ - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_N; - - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); - - /* Sign the message hash using FORS. */ - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_fors_sign( - sig, root, mhash, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_FORS_BYTES; - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_D; i++) { - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_set_tree_addr(tree_addr, tree); - - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); - - /* Compute a WOTS signature. */ - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_wots_sign( - sig, root, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_WOTS_BYTES; - - /* Compute the authentication path for the used WOTS leaf. */ - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_treehash_TREE_HEIGHT( - root, sig, sk_seed, pub_seed, idx_leaf, 0, - wots_gen_leaf, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_TREE_HEIGHT * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_TREE_HEIGHT; - } - - *siglen = PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_BYTES; - - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_destroy_hash_function(&hash_state_seeded); - return 0; -} - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk) { - const unsigned char *pub_seed = pk; - const unsigned char *pub_root = pk + PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_N; - unsigned char mhash[PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_FORS_MSG_BYTES]; - unsigned char wots_pk[PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_WOTS_BYTES]; - unsigned char root[PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_N]; - unsigned char leaf[PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_N]; - unsigned int i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - hash_state hash_state_seeded; - - if (siglen != PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_BYTES) { - return -1; - } - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_initialize_hash_function( - &hash_state_seeded, - pub_seed, NULL); - - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_set_type( - wots_addr, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_set_type( - tree_addr, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_ADDR_TYPE_HASHTREE); - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_set_type( - wots_pk_addr, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_ADDR_TYPE_WOTSPK); - - /* Derive the message digest and leaf index from R || PK || M. */ - /* The additional PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_N is a result of the hash domain separator. */ - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_N; - - /* Layer correctly defaults to 0, so no need to set_layer_addr */ - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); - - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_fors_pk_from_sig( - root, sig, mhash, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_FORS_BYTES; - - /* For each subtree.. */ - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_D; i++) { - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_set_tree_addr(tree_addr, tree); - - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); - - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_copy_keypair_addr( - wots_pk_addr, wots_addr); - - /* The WOTS public key is only correct if the signature was correct. */ - /* Initially, root is the FORS pk, but on subsequent iterations it is - the root of the subtree below the currently processed subtree. */ - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_wots_pk_from_sig( - wots_pk, sig, root, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_WOTS_BYTES; - - /* Compute the leaf node using the WOTS public key. */ - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_thash_WOTS_LEN( - leaf, wots_pk, pub_seed, wots_pk_addr, &hash_state_seeded); - - /* Compute the root node of this subtree. */ - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_compute_root( - root, leaf, idx_leaf, 0, sig, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_TREE_HEIGHT, - pub_seed, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_TREE_HEIGHT * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_TREE_HEIGHT; - } - - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_destroy_hash_function(&hash_state_seeded); - /* Check if the root node equals the root node in the public key. */ - if (memcmp(root, pub_root, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_N) != 0) { - return -1; - } - - return 0; -} - - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - size_t siglen; - - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_crypto_sign_signature( - sm, &siglen, m, mlen, sk); - - memmove(sm + PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_BYTES, m, mlen); - *smlen = siglen + mlen; - - return 0; -} - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk) { - /* The API caller does not necessarily know what size a signature should be - but SPHINCS+ signatures are always exactly PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_BYTES. */ - if (smlen < PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_BYTES) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - *mlen = smlen - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_BYTES; - - if (PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_crypto_sign_verify( - sm, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_BYTES, sm + PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_BYTES, *mlen, pk)) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - /* If verification was successful, move the message to the right place. */ - memmove(m, sm + PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_BYTES, *mlen); - - return 0; -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_clean/thash.h b/src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_clean/thash.h deleted file mode 100644 index 1788df02ea..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_clean/thash.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_THASH_H -#define PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_THASH_H - -#include "hash_state.h" - -#include - -void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_clean/thash_shake256_simple.c b/src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_clean/thash_shake256_simple.c deleted file mode 100644 index fcb8dcc7c1..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_clean/thash_shake256_simple.c +++ /dev/null @@ -1,74 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash_state.h" -#include "params.h" -#include "thash.h" - -#include "fips202.h" - -/** - * Takes an array of inblocks concatenated arrays of PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_N bytes. - */ -static void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_thash( - unsigned char *out, unsigned char *buf, - const unsigned char *in, unsigned int inblocks, - const unsigned char *pub_seed, uint32_t addr[8]) { - - memcpy(buf, pub_seed, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_N); - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_addr_to_bytes(buf + PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_N, addr); - memcpy(buf + PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_N + PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_ADDR_BYTES, in, inblocks * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_N); - - shake256(out, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_N, buf, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_N + PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_N); -} - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_N + PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_ADDR_BYTES + 1 * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_N]; - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_thash( - out, buf, in, 1, pub_seed, addr); - - (void)hash_state_seeded; /* Avoid unused parameter warning. */ -} - -void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_N + PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_ADDR_BYTES + 2 * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_N]; - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_thash( - out, buf, in, 2, pub_seed, addr); - - (void)hash_state_seeded; /* Avoid unused parameter warning. */ -} - -void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_N + PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_ADDR_BYTES + PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_WOTS_LEN * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_N]; - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_thash( - out, buf, in, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_WOTS_LEN, pub_seed, addr); - - (void)hash_state_seeded; /* Avoid unused parameter warning. */ -} - -void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_N + PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_ADDR_BYTES + PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_FORS_TREES * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_N]; - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_thash( - out, buf, in, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_FORS_TREES, pub_seed, addr); - - (void)hash_state_seeded; /* Avoid unused parameter warning. */ -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_clean/utils.c b/src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_clean/utils.c deleted file mode 100644 index d88090ba83..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_clean/utils.c +++ /dev/null @@ -1,199 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "hash_state.h" -#include "params.h" -#include "thash.h" -#include "utils.h" - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in) { - - /* Iterate over out in decreasing order, for big-endianness. */ - for (size_t i = outlen; i > 0; i--) { - out[i - 1] = in & 0xff; - in = in >> 8; - } -} - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_bytes_to_ull( - const unsigned char *in, size_t inlen) { - unsigned long long retval = 0; - - for (size_t i = 0; i < inlen; i++) { - retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); - } - return retval; -} - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - uint32_t i; - unsigned char buffer[2 * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_N]; - - /* If leaf_idx is odd (last bit = 1), current path element is a right child - and auth_path has to go left. Otherwise it is the other way around. */ - if (leaf_idx & 1) { - memcpy(buffer + PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_N, leaf, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_N); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_N); - } else { - memcpy(buffer, leaf, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_N); - memcpy(buffer + PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_N, auth_path, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_N); - } - auth_path += PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_N; - - for (i = 0; i < tree_height - 1; i++) { - leaf_idx >>= 1; - idx_offset >>= 1; - /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_set_tree_height(addr, i + 1); - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_set_tree_index( - addr, leaf_idx + idx_offset); - - /* Pick the right or left neighbor, depending on parity of the node. */ - if (leaf_idx & 1) { - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_thash_2( - buffer + PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_N, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_N); - } else { - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_thash_2( - buffer, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer + PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_N, auth_path, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_N); - } - auth_path += PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_N; - } - - /* The last iteration is exceptional; we do not copy an auth_path node. */ - leaf_idx >>= 1; - idx_offset >>= 1; - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_set_tree_height(addr, tree_height); - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_set_tree_index( - addr, leaf_idx + idx_offset); - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_thash_2( - root, buffer, pub_seed, addr, hash_state_seeded); -} - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -static void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_treehash( - unsigned char *root, unsigned char *auth_path, - unsigned char *stack, unsigned int *heights, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - - unsigned int offset = 0; - uint32_t idx; - uint32_t tree_idx; - - for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { - /* Add the next leaf node to the stack. */ - gen_leaf(stack + offset * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_N, - sk_seed, pub_seed, idx + idx_offset, tree_addr, - hash_state_seeded); - offset++; - heights[offset - 1] = 0; - - /* If this is a node we need for the auth path.. */ - if ((leaf_idx ^ 0x1) == idx) { - memcpy(auth_path, stack + (offset - 1)*PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_N, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_N); - } - - /* While the top-most nodes are of equal height.. */ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { - /* Compute index of the new node, in the next layer. */ - tree_idx = (idx >> (heights[offset - 1] + 1)); - - /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_set_tree_height( - tree_addr, heights[offset - 1] + 1); - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_set_tree_index( - tree_addr, tree_idx + (idx_offset >> (heights[offset - 1] + 1))); - /* Hash the top-most nodes from the stack together. */ - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_thash_2( - stack + (offset - 2)*PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_N, stack + (offset - 2)*PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_N, - pub_seed, tree_addr, hash_state_seeded); - offset--; - /* Note that the top-most node is now one layer higher. */ - heights[offset - 1]++; - - /* If this is a node we need for the auth path.. */ - if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_path + heights[offset - 1]*PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_N, - stack + (offset - 1)*PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_N, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_N); - } - } - } - memcpy(root, stack, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_N); -} - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_FORS_HEIGHT + 1)*PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_N]; - unsigned int heights[PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_FORS_HEIGHT + 1]; - - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_FORS_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_TREE_HEIGHT + 1)*PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_N]; - unsigned int heights[PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_TREE_HEIGHT + 1]; - - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_TREE_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_clean/utils.h b/src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_clean/utils.h deleted file mode 100644 index 14df17c932..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_clean/utils.h +++ /dev/null @@ -1,64 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_UTILS_H -#define PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_UTILS_H - -#include "hash_state.h" -#include "params.h" -#include -#include - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in); - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_bytes_to_ull( - const unsigned char *in, size_t inlen); - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_clean/wots.c b/src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_clean/wots.c deleted file mode 100644 index e4782279a2..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_clean/wots.c +++ /dev/null @@ -1,167 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "hash_state.h" -#include "params.h" -#include "thash.h" -#include "utils.h" -#include "wots.h" - -// TODO clarify address expectations, and make them more uniform. -// TODO i.e. do we expect types to be set already? -// TODO and do we expect modifications or copies? - -/** - * Computes the starting value for a chain, i.e. the secret key. - * Expects the address to be complete up to the chain address. - */ -static void wots_gen_sk(unsigned char *sk, const unsigned char *sk_seed, - uint32_t wots_addr[8], - const hash_state *hash_state_seeded) { - /* Make sure that the hash address is actually zeroed. */ - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_set_hash_addr(wots_addr, 0); - - /* Generate sk element. */ - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_prf_addr(sk, sk_seed, wots_addr, hash_state_seeded); -} - -/** - * Computes the chaining function. - * out and in have to be n-byte arrays. - * - * Interprets in as start-th value of the chain. - * addr has to contain the address of the chain. - */ -static void gen_chain(unsigned char *out, const unsigned char *in, - unsigned int start, unsigned int steps, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - uint32_t i; - - /* Initialize out with the value at position 'start'. */ - memcpy(out, in, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_N); - - /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_WOTS_W; i++) { - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_set_hash_addr(addr, i); - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_thash_1( - out, out, pub_seed, addr, hash_state_seeded); - } -} - -/** - * base_w algorithm as described in draft. - * Interprets an array of bytes as integers in base w. - * This only works when log_w is a divisor of 8. - */ -static void base_w(unsigned int *output, const size_t out_len, - const unsigned char *input) { - size_t in = 0; - size_t out = 0; - unsigned char total = 0; - unsigned int bits = 0; - size_t consumed; - - for (consumed = 0; consumed < out_len; consumed++) { - if (bits == 0) { - total = input[in]; - in++; - bits += 8; - } - bits -= PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_WOTS_LOGW; - output[out] = (unsigned int)((total >> bits) & (PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_WOTS_W - 1)); - out++; - } -} - -/* Computes the WOTS+ checksum over a message (in base_w). */ -static void wots_checksum(unsigned int *csum_base_w, - const unsigned int *msg_base_w) { - unsigned int csum = 0; - unsigned char csum_bytes[(PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_WOTS_LEN2 * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_WOTS_LOGW + 7) / 8]; - unsigned int i; - - /* Compute checksum. */ - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_WOTS_LEN1; i++) { - csum += PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_WOTS_W - 1 - msg_base_w[i]; - } - - /* Convert checksum to base_w. */ - /* Make sure expected empty zero bits are the least significant bits. */ - csum = csum << (8 - ((PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_WOTS_LEN2 * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_WOTS_LOGW) % 8)); - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_ull_to_bytes( - csum_bytes, sizeof(csum_bytes), csum); - base_w(csum_base_w, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_WOTS_LEN2, csum_bytes); -} - -/* Takes a message and derives the matching chain lengths. */ -static void chain_lengths(unsigned int *lengths, const unsigned char *msg) { - base_w(lengths, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_WOTS_LEN1, msg); - wots_checksum(lengths + PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_WOTS_LEN1, lengths); -} - -/** - * WOTS key generation. Takes a 32 byte sk_seed, expands it to WOTS private key - * elements and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_wots_gen_pk( - unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - uint32_t i; - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_WOTS_LEN; i++) { - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_set_chain_addr(addr, i); - wots_gen_sk(pk + i * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_N, sk_seed, addr, hash_state_seeded); - gen_chain(pk + i * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_N, pk + i * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_N, - 0, PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_WOTS_W - 1, pub_seed, addr, hash_state_seeded); - } -} - -/** - * Takes a n-byte message and the 32-byte sk_see to compute a signature 'sig'. - */ -void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_wots_sign( - unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *hash_state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_WOTS_LEN; i++) { - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_set_chain_addr(addr, i); - wots_gen_sk(sig + i * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_N, sk_seed, addr, hash_state_seeded); - gen_chain(sig + i * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_N, sig + i * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_N, 0, lengths[i], pub_seed, addr, hash_state_seeded); - } -} - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_wots_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_WOTS_LEN; i++) { - PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_set_chain_addr(addr, i); - gen_chain(pk + i * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_N, sig + i * PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_N, - lengths[i], PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_WOTS_W - 1 - lengths[i], pub_seed, addr, - hash_state_seeded); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_clean/wots.h b/src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_clean/wots.h deleted file mode 100644 index 3c279306dd..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-192s-simple_clean/wots.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_WOTS_H -#define PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_WOTS_H - -#include "hash_state.h" -#include "params.h" -#include - -/** - * WOTS key generation. Takes a 32 byte seed for the private key, expands it to - * a full WOTS private key and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_wots_gen_pk( - unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -/** - * Takes a n-byte message and the 32-byte seed for the private key to compute a - * signature that is placed at 'sig'. - */ -void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_wots_sign( - unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *hash_state_seeded); - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_wots_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_avx2/LICENSE b/src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_avx2/LICENSE deleted file mode 100644 index 670154e353..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_avx2/LICENSE +++ /dev/null @@ -1,116 +0,0 @@ -CC0 1.0 Universal - -Statement of Purpose - -The laws of most jurisdictions throughout the world automatically confer -exclusive Copyright and Related Rights (defined below) upon the creator and -subsequent owner(s) (each and all, an "owner") of an original work of -authorship and/or a database (each, a "Work"). - -Certain owners wish to permanently relinquish those rights to a Work for the -purpose of contributing to a commons of creative, cultural and scientific -works ("Commons") that the public can reliably and without fear of later -claims of infringement build upon, modify, incorporate in other works, reuse -and redistribute as freely as possible in any form whatsoever and for any -purposes, including without limitation commercial purposes. These owners may -contribute to the Commons to promote the ideal of a free culture and the -further production of creative, cultural and scientific works, or to gain -reputation or greater distribution for their Work in part through the use and -efforts of others. - -For these and/or other purposes and motivations, and without any expectation -of additional consideration or compensation, the person associating CC0 with a -Work (the "Affirmer"), to the extent that he or she is an owner of Copyright -and Related Rights in the Work, voluntarily elects to apply CC0 to the Work -and publicly distribute the Work under its terms, with knowledge of his or her -Copyright and Related Rights in the Work and the meaning and intended legal -effect of CC0 on those rights. - -1. Copyright and Related Rights. A Work made available under CC0 may be -protected by copyright and related or neighboring rights ("Copyright and -Related Rights"). Copyright and Related Rights include, but are not limited -to, the following: - - i. the right to reproduce, adapt, distribute, perform, display, communicate, - and translate a Work; - - ii. moral rights retained by the original author(s) and/or performer(s); - - iii. publicity and privacy rights pertaining to a person's image or likeness - depicted in a Work; - - iv. rights protecting against unfair competition in regards to a Work, - subject to the limitations in paragraph 4(a), below; - - v. rights protecting the extraction, dissemination, use and reuse of data in - a Work; - - vi. database rights (such as those arising under Directive 96/9/EC of the - European Parliament and of the Council of 11 March 1996 on the legal - protection of databases, and under any national implementation thereof, - including any amended or successor version of such directive); and - - vii. other similar, equivalent or corresponding rights throughout the world - based on applicable law or treaty, and any national implementations thereof. - -2. Waiver. To the greatest extent permitted by, but not in contravention of, -applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and -unconditionally waives, abandons, and surrenders all of Affirmer's Copyright -and Related Rights and associated claims and causes of action, whether now -known or unknown (including existing as well as future claims and causes of -action), in the Work (i) in all territories worldwide, (ii) for the maximum -duration provided by applicable law or treaty (including future time -extensions), (iii) in any current or future medium and for any number of -copies, and (iv) for any purpose whatsoever, including without limitation -commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes -the Waiver for the benefit of each member of the public at large and to the -detriment of Affirmer's heirs and successors, fully intending that such Waiver -shall not be subject to revocation, rescission, cancellation, termination, or -any other legal or equitable action to disrupt the quiet enjoyment of the Work -by the public as contemplated by Affirmer's express Statement of Purpose. - -3. Public License Fallback. Should any part of the Waiver for any reason be -judged legally invalid or ineffective under applicable law, then the Waiver -shall be preserved to the maximum extent permitted taking into account -Affirmer's express Statement of Purpose. In addition, to the extent the Waiver -is so judged Affirmer hereby grants to each affected person a royalty-free, -non transferable, non sublicensable, non exclusive, irrevocable and -unconditional license to exercise Affirmer's Copyright and Related Rights in -the Work (i) in all territories worldwide, (ii) for the maximum duration -provided by applicable law or treaty (including future time extensions), (iii) -in any current or future medium and for any number of copies, and (iv) for any -purpose whatsoever, including without limitation commercial, advertising or -promotional purposes (the "License"). The License shall be deemed effective as -of the date CC0 was applied by Affirmer to the Work. Should any part of the -License for any reason be judged legally invalid or ineffective under -applicable law, such partial invalidity or ineffectiveness shall not -invalidate the remainder of the License, and in such case Affirmer hereby -affirms that he or she will not (i) exercise any of his or her remaining -Copyright and Related Rights in the Work or (ii) assert any associated claims -and causes of action with respect to the Work, in either case contrary to -Affirmer's express Statement of Purpose. - -4. Limitations and Disclaimers. - - a. No trademark or patent rights held by Affirmer are waived, abandoned, - surrendered, licensed or otherwise affected by this document. - - b. Affirmer offers the Work as-is and makes no representations or warranties - of any kind concerning the Work, express, implied, statutory or otherwise, - including without limitation warranties of title, merchantability, fitness - for a particular purpose, non infringement, or the absence of latent or - other defects, accuracy, or the present or absence of errors, whether or not - discoverable, all to the greatest extent permissible under applicable law. - - c. Affirmer disclaims responsibility for clearing rights of other persons - that may apply to the Work or any use thereof, including without limitation - any person's Copyright and Related Rights in the Work. Further, Affirmer - disclaims responsibility for obtaining any necessary consents, permissions - or other rights required for any use of the Work. - - d. Affirmer understands and acknowledges that Creative Commons is not a - party to this document and has no duty or obligation with respect to this - CC0 or use of the Work. - -For more information, please see - diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_avx2/address.c b/src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_avx2/address.c deleted file mode 100644 index de99471514..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_avx2/address.c +++ /dev/null @@ -1,78 +0,0 @@ -#include - -#include "address.h" -#include "params.h" -#include "utils.h" - -void PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]) { - int i; - - for (i = 0; i < 8; i++) { - PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_ull_to_bytes( - bytes + i * 4, 4, addr[i]); - } -} - -void PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_set_layer_addr( - uint32_t addr[8], uint32_t layer) { - addr[0] = layer; -} - -void PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_set_tree_addr( - uint32_t addr[8], uint64_t tree) { - addr[1] = 0; - addr[2] = (uint32_t) (tree >> 32); - addr[3] = (uint32_t) tree; -} - -void PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_set_type( - uint32_t addr[8], uint32_t type) { - addr[4] = type; -} - -void PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; -} - -/* These functions are used for OTS addresses. */ - -void PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_set_keypair_addr( - uint32_t addr[8], uint32_t keypair) { - addr[5] = keypair; -} - -void PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; - out[5] = in[5]; -} - -void PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_set_chain_addr( - uint32_t addr[8], uint32_t chain) { - addr[6] = chain; -} - -void PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_set_hash_addr( - uint32_t addr[8], uint32_t hash) { - addr[7] = hash; -} - -/* These functions are used for all hash tree addresses (including FORS). */ - -void PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_set_tree_height( - uint32_t addr[8], uint32_t tree_height) { - addr[6] = tree_height; -} - -void PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_set_tree_index( - uint32_t addr[8], uint32_t tree_index) { - addr[7] = tree_index; -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_avx2/address.h b/src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_avx2/address.h deleted file mode 100644 index e95e579a35..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_avx2/address.h +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_ADDRESS_H -#define PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_ADDRESS_H - -#include - -#define PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_ADDR_TYPE_WOTS 0 -#define PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_ADDR_TYPE_WOTSPK 1 -#define PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_ADDR_TYPE_HASHTREE 2 -#define PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_ADDR_TYPE_FORSTREE 3 -#define PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_ADDR_TYPE_FORSPK 4 - -void PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]); - -void PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_set_layer_addr( - uint32_t addr[8], uint32_t layer); - -void PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_set_tree_addr( - uint32_t addr[8], uint64_t tree); - -void PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_set_type( - uint32_t addr[8], uint32_t type); - -/* Copies the layer and tree part of one address into the other */ -void PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for WOTS and FORS addresses. */ - -void PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_set_keypair_addr( - uint32_t addr[8], uint32_t keypair); - -void PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_set_chain_addr( - uint32_t addr[8], uint32_t chain); - -void PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_set_hash_addr( - uint32_t addr[8], uint32_t hash); - -void PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for all hash tree addresses (including FORS). */ - -void PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_set_tree_height( - uint32_t addr[8], uint32_t tree_height); - -void PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_set_tree_index( - uint32_t addr[8], uint32_t tree_index); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_avx2/api.h b/src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_avx2/api.h deleted file mode 100644 index e11cd6140c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_avx2/api.h +++ /dev/null @@ -1,81 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_API_H -#define PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_API_H - -#include -#include - - - -#define PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_CRYPTO_ALGNAME "SPHINCS+" - -#define PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_CRYPTO_SECRETKEYBYTES 128 -#define PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_CRYPTO_PUBLICKEYBYTES 64 -#define PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_CRYPTO_BYTES 49856 -#define PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_CRYPTO_SEEDBYTES 96 - - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_avx2/fors.c b/src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_avx2/fors.c deleted file mode 100644 index 5bbcea82dd..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_avx2/fors.c +++ /dev/null @@ -1,206 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "fors.h" -#include "hash.h" -#include "hashx4.h" -#include "thash.h" -#include "thashx4.h" -#include "utils.h" -#include "utilsx4.h" - -static void fors_gen_skx4(unsigned char *sk0, - unsigned char *sk1, - unsigned char *sk2, - unsigned char *sk3, const unsigned char *sk_seed, - uint32_t fors_leaf_addrx4[4 * 8], - const hash_state *state_seeded) { - PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_prf_addrx4(sk0, sk1, sk2, sk3, sk_seed, fors_leaf_addrx4, state_seeded); -} - -static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, - const unsigned char *pub_seed, - uint32_t fors_leaf_addr[8], const hash_state *state_seeded) { - PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_thash_1(leaf, sk, pub_seed, fors_leaf_addr, state_seeded); -} - -static void fors_sk_to_leafx4(unsigned char *leaf0, - unsigned char *leaf1, - unsigned char *leaf2, - unsigned char *leaf3, - const unsigned char *sk0, - const unsigned char *sk1, - const unsigned char *sk2, - const unsigned char *sk3, - const unsigned char *pub_seed, - uint32_t fors_leaf_addrx4[4 * 8], - const hash_state *state_seeded) { - PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_thashx4_1(leaf0, leaf1, leaf2, leaf3, - sk0, sk1, sk2, sk3, pub_seed, fors_leaf_addrx4, state_seeded); -} - -static void fors_gen_leafx4(unsigned char *leaf0, - unsigned char *leaf1, - unsigned char *leaf2, - unsigned char *leaf3, - const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx0, - uint32_t addr_idx1, - uint32_t addr_idx2, - uint32_t addr_idx3, - const uint32_t fors_tree_addr[8], - const hash_state *state_seeded) { - uint32_t fors_leaf_addrx4[4 * 8] = {0}; - unsigned int j; - - /* Only copy the parts that must be kept in fors_leaf_addrx4. */ - for (j = 0; j < 4; j++) { - PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_copy_keypair_addr(fors_leaf_addrx4 + j * 8, fors_tree_addr); - PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_set_type(fors_leaf_addrx4 + j * 8, PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_ADDR_TYPE_FORSTREE); - } - - PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_set_tree_index(fors_leaf_addrx4 + 0 * 8, addr_idx0); - PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_set_tree_index(fors_leaf_addrx4 + 1 * 8, addr_idx1); - PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_set_tree_index(fors_leaf_addrx4 + 2 * 8, addr_idx2); - PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_set_tree_index(fors_leaf_addrx4 + 3 * 8, addr_idx3); - - fors_gen_skx4(leaf0, leaf1, leaf2, leaf3, sk_seed, fors_leaf_addrx4, state_seeded); - fors_sk_to_leafx4(leaf0, leaf1, leaf2, leaf3, - leaf0, leaf1, leaf2, leaf3, pub_seed, fors_leaf_addrx4, state_seeded); -} - -/** - * Interprets m as PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_FORS_HEIGHT-bit unsigned integers. - * Assumes m contains at least PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_FORS_TREES bits. - * Assumes indices has space for PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_FORS_TREES integers. - */ -static void message_to_indices(uint32_t *indices, const unsigned char *m) { - unsigned int i, j; - unsigned int offset = 0; - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_FORS_TREES; i++) { - indices[i] = 0; - for (j = 0; j < PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_FORS_HEIGHT; j++) { - indices[i] ^= (((uint32_t)m[offset >> 3] >> (offset & 0x7)) & 0x1) << j; - offset++; - } - } -} - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *state_seeded) { - /* Round up to multiple of 4 to prevent out-of-bounds for x4 parallelism */ - uint32_t indices[(PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_FORS_TREES + 3) & ~3] = {0}; - unsigned char roots[((PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_FORS_TREES + 3) & ~3) * PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N]; - /* Sign to a buffer, since we may not have a nice multiple of 4 and would - otherwise overrun the signature. */ - unsigned char sigbufx4[4 * PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N * (1 + PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_FORS_HEIGHT)]; - uint32_t fors_tree_addrx4[4 * 8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset[4] = {0}; - unsigned int i, j; - - for (j = 0; j < 4; j++) { - PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_copy_keypair_addr(fors_tree_addrx4 + j * 8, fors_addr); - PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_set_type(fors_tree_addrx4 + j * 8, PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_ADDR_TYPE_FORSTREE); - } - - PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_copy_keypair_addr(fors_pk_addr, fors_addr); - PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_set_type(fors_pk_addr, PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < ((PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_FORS_TREES + 3) & ~0x3); i += 4) { - for (j = 0; j < 4; j++) { - if (i + j < PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_FORS_TREES) { - idx_offset[j] = (i + j) * (1 << PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_FORS_HEIGHT); - - PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_set_tree_height(fors_tree_addrx4 + j * 8, 0); - PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_set_tree_index(fors_tree_addrx4 + j * 8, - indices[i + j] + idx_offset[j]); - } - } - - /* Include the secret key part that produces the selected leaf nodes. */ - fors_gen_skx4(sigbufx4 + 0 * PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N, - sigbufx4 + 1 * PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N, - sigbufx4 + 2 * PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N, - sigbufx4 + 3 * PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N, - sk_seed, fors_tree_addrx4, state_seeded); - - PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_treehashx4_FORS_HEIGHT(roots + i * PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N, sigbufx4 + 4 * PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N, sk_seed, pub_seed, - &indices[i], idx_offset, fors_gen_leafx4, fors_tree_addrx4, - state_seeded); - - for (j = 0; j < 4; j++) { - if (i + j < PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_FORS_TREES) { - memcpy(sig, sigbufx4 + j * PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N, PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N); - memcpy(sig + PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N, - sigbufx4 + 4 * PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N + j * PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N * PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_FORS_HEIGHT, - PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N * PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_FORS_HEIGHT); - sig += PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N * (1 + PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_FORS_HEIGHT); - } - } - } - - /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_thash_FORS_TREES(pk, roots, pub_seed, fors_pk_addr, state_seeded); -} - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, - const uint32_t fors_addr[8], - const hash_state *state_seeded) { - uint32_t indices[PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_FORS_TREES]; - unsigned char roots[PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_FORS_TREES * PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N]; - unsigned char leaf[PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N]; - uint32_t fors_tree_addr[8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_copy_keypair_addr(fors_tree_addr, fors_addr); - PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_copy_keypair_addr(fors_pk_addr, fors_addr); - - PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_set_type(fors_tree_addr, PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_set_type(fors_pk_addr, PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_FORS_TREES; i++) { - idx_offset = i * (1 << PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_FORS_HEIGHT); - - PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_set_tree_height(fors_tree_addr, 0); - PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Derive the leaf from the included secret key part. */ - fors_sk_to_leaf(leaf, sig, pub_seed, fors_tree_addr, state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N; - - /* Derive the corresponding root node of this tree. */ - PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_compute_root(roots + i * PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N, leaf, indices[i], idx_offset, - sig, PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_FORS_HEIGHT, pub_seed, fors_tree_addr, - state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N * PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_thash_FORS_TREES(pk, roots, pub_seed, fors_pk_addr, state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_avx2/fors.h b/src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_avx2/fors.h deleted file mode 100644 index 58a0256a13..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_avx2/fors.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_FORS_H -#define PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_FORS_H - -#include - -#include "hash_state.h" -#include "params.h" - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_fors_sign( - unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *hash_state_seeded); - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_fors_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, const uint32_t fors_addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_avx2/hash.h b/src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_avx2/hash.h deleted file mode 100644 index eacdda3a50..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_avx2/hash.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_HASH_H -#define PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_HASH_H - -#include "hash_state.h" - -#include -#include - -void PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_initialize_hash_function( - hash_state *hash_state_seeded, - const unsigned char *pub_seed, const unsigned char *sk_seed); - -void PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_destroy_hash_function(hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_avx2/hash_shake256.c b/src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_avx2/hash_shake256.c deleted file mode 100644 index 4e1c749163..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_avx2/hash_shake256.c +++ /dev/null @@ -1,106 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "utils.h" - -#include "fips202.h" - -/* For SHAKE256, there is no immediate reason to initialize at the start, - so this function is an empty operation. */ -void PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_initialize_hash_function( - hash_state *hash_state_seeded, // NOLINT(readability-non-const-parameter) - const unsigned char *pub_seed, const unsigned char *sk_seed) { - (void)hash_state_seeded; /* Suppress an 'unused parameter' warning. */ - (void)pub_seed; /* Suppress an 'unused parameter' warning. */ - (void)sk_seed; /* Suppress an 'unused parameter' warning. */ -} - -/* This is not necessary for SHAKE256, so we don't do anything */ -void PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_destroy_hash_function( - hash_state *hash_state_seeded) { // NOLINT(readability-non-const-parameter) - (void)hash_state_seeded; -} - -/* - * Computes PRF(key, addr), given a secret key of PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N bytes and an address - */ -void PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded) { - unsigned char buf[PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_ADDR_BYTES]; - - memcpy(buf, key, PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N); - PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_addr_to_bytes(buf + PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N, addr); - - shake256(out, PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N, buf, PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_ADDR_BYTES); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} - -/** - * Computes the message-dependent randomness R, using a secret seed and an - * optional randomization value as well as the message. - */ -void PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded) { - shake256incctx state; - - shake256_inc_init(&state); - shake256_inc_absorb(&state, sk_prf, PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N); - shake256_inc_absorb(&state, optrand, PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N); - shake256_inc_absorb(&state, m, mlen); - shake256_inc_finalize(&state); - shake256_inc_squeeze(R, PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N, &state); - shake256_inc_ctx_release(&state); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} - -/** - * Computes the message hash using R, the public key, and the message. - * Outputs the message digest and the index of the leaf. The index is split in - * the tree index and the leaf index, for convenient copying to an address. - */ -void PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded) { -#define PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_TREE_BITS (PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_TREE_HEIGHT * (PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_D - 1)) -#define PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_TREE_BYTES ((PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_TREE_BITS + 7) / 8) -#define PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_LEAF_BITS PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_TREE_HEIGHT -#define PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_LEAF_BYTES ((PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_LEAF_BITS + 7) / 8) -#define PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_DGST_BYTES (PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_FORS_MSG_BYTES + PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_TREE_BYTES + PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_LEAF_BYTES) - - unsigned char buf[PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_DGST_BYTES]; - unsigned char *bufp = buf; - shake256incctx state; - - shake256_inc_init(&state); - shake256_inc_absorb(&state, R, PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N); - shake256_inc_absorb(&state, pk, PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_PK_BYTES); - shake256_inc_absorb(&state, m, mlen); - shake256_inc_finalize(&state); - shake256_inc_squeeze(buf, PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_DGST_BYTES, &state); - shake256_inc_ctx_release(&state); - - memcpy(digest, bufp, PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_FORS_MSG_BYTES); - bufp += PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_FORS_MSG_BYTES; - - *tree = PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_bytes_to_ull( - bufp, PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_TREE_BYTES); - *tree &= (~(uint64_t)0) >> (64 - PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_TREE_BITS); - bufp += PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_TREE_BYTES; - - *leaf_idx = (uint32_t)PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_bytes_to_ull( - bufp, PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_LEAF_BYTES); - *leaf_idx &= (~(uint32_t)0) >> (32 - PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_LEAF_BITS); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_avx2/hash_shake256x4.c b/src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_avx2/hash_shake256x4.c deleted file mode 100644 index 7a86225b26..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_avx2/hash_shake256x4.c +++ /dev/null @@ -1,38 +0,0 @@ -#include -#include - -#include "address.h" -#include "fips202x4.h" -#include "hashx4.h" -#include "params.h" - -/* - * 4-way parallel version of prf_addr; takes 4x as much input and output - */ -void PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_prf_addrx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const unsigned char *key, - const uint32_t addrx4[4 * 8], - const hash_state *state_seeded) { - unsigned char bufx4[4 * (PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_ADDR_BYTES)]; - unsigned int j; - - for (j = 0; j < 4; j++) { - memcpy(bufx4 + j * (PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_ADDR_BYTES), key, PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N); - PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_addr_to_bytes(bufx4 + PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N + j * (PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_ADDR_BYTES), addrx4 + j * 8); - } - - PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_shake256x4(out0, - out1, - out2, - out3, PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N, - bufx4 + 0 * (PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_ADDR_BYTES), - bufx4 + 1 * (PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_ADDR_BYTES), - bufx4 + 2 * (PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_ADDR_BYTES), - bufx4 + 3 * (PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_ADDR_BYTES), PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_ADDR_BYTES); - - /* Avoid unused parameter warning */ - (void)state_seeded; -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_avx2/hash_state.h b/src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_avx2/hash_state.h deleted file mode 100644 index 07c2c81fa8..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_avx2/hash_state.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_HASH_STATE_H -#define PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_HASH_STATE_H - -/** - * Defines the type of the hash function state. - * - * Don't be fooled into thinking this instance of SPHINCS+ isn't stateless! - * - * From Section 7.2.2 from the SPHINCS+ round-2 specification: - * - * Each of the instances of the tweakable hash function take PK.seed as its - * first input, which is constant for a given key pair – and, thus, across - * a single signature. This leads to a lot of redundant computation. To remedy - * this, we pad PK.seed to the length of a full 64-byte SHA-256 input block. - * Because of the Merkle-Damgård construction that underlies SHA-256, this - * allows for reuse of the intermediate SHA-256 state after the initial call to - * the compression function which improves performance. - * - * We pass this hash state around in functions, because otherwise we need to - * have a global variable. - * - * SHAKE256 does not need this state. Because this implementation is generated - * from a shared code base, we still need to specify some hash_state as it is - * still passed around. We chose to use an `int` as a placeholder for this - * purpose. - */ - -typedef int hash_state; - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_avx2/hashx4.h b/src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_avx2/hashx4.h deleted file mode 100644 index 568a089f98..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_avx2/hashx4.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_HASHX4_H -#define PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_HASHX4_H - -#include - -#include "hash_state.h" - -void PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_prf_addrx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const unsigned char *key, - const uint32_t addrx4[4 * 8], - const hash_state *state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_avx2/params.h b/src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_avx2/params.h deleted file mode 100644 index 29811afded..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_avx2/params.h +++ /dev/null @@ -1,53 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_PARAMS_H -#define PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_PARAMS_H - -/* Hash output length in bytes. */ -#define PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N 32 -/* Height of the hypertree. */ -#define PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_FULL_HEIGHT 68 -/* Number of subtree layer. */ -#define PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_D 17 -/* FORS tree dimensions. */ -#define PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_FORS_HEIGHT 9 -#define PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_FORS_TREES 35 -/* Winternitz parameter, */ -#define PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_WOTS_W 16 - -/* The hash function is defined by linking a different hash.c file, as opposed - to setting a #define constant. */ - -/* For clarity */ -#define PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_ADDR_BYTES 32 - -/* WOTS parameters. */ -#define PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_WOTS_LOGW 4 - -#define PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_WOTS_LEN1 (8 * PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N / PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_WOTS_LOGW) - -/* PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#define PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_WOTS_LEN2 3 - -#define PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_WOTS_LEN (PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_WOTS_LEN1 + PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_WOTS_LEN2) -#define PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_WOTS_BYTES (PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_WOTS_LEN * PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N) -#define PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_WOTS_PK_BYTES PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_WOTS_BYTES - -/* Subtree size. */ -#define PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_TREE_HEIGHT (PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_FULL_HEIGHT / PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_D) - -/* FORS parameters. */ -#define PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_FORS_MSG_BYTES ((PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_FORS_TREES + 7) / 8) -#define PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_FORS_BYTES ((PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_FORS_HEIGHT + 1) * PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_FORS_TREES * PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N) -#define PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_FORS_PK_BYTES PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N - -/* Resulting SPX sizes. */ -#define PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_BYTES (PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_FORS_BYTES + PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_D * PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_WOTS_BYTES +\ - PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_FULL_HEIGHT * PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N) -#define PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_PK_BYTES (2 * PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N) -#define PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_SK_BYTES (2 * PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_PK_BYTES) - -/* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ -#define PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_OPTRAND_BYTES 32 - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_avx2/sign.c b/src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_avx2/sign.c deleted file mode 100644 index d558b6ca22..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_avx2/sign.c +++ /dev/null @@ -1,409 +0,0 @@ -#include -#include -#include -#include - -#include "address.h" -#include "api.h" -#include "fors.h" -#include "hash.h" -#include "hash_state.h" -#include "params.h" -#include "randombytes.h" -#include "thash.h" -#include "utils.h" -#include "wots.h" - - -/** - * Computes the leaf at a given address. First generates the WOTS key pair, - * then computes leaf by hashing horizontally. - */ -static void wots_gen_leaf(unsigned char *leaf, const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx, const uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - unsigned char pk[PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_WOTS_BYTES]; - uint32_t wots_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_set_type( - wots_addr, PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_set_type( - wots_pk_addr, PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_ADDR_TYPE_WOTSPK); - - PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_set_keypair_addr( - wots_addr, addr_idx); - PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_wots_gen_pk( - pk, sk_seed, pub_seed, wots_addr, hash_state_seeded); - - PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_copy_keypair_addr( - wots_pk_addr, wots_addr); - PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_thash_WOTS_LEN( - leaf, pk, pub_seed, wots_pk_addr, hash_state_seeded); -} - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_crypto_sign_secretkeybytes(void) { - return PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_CRYPTO_SECRETKEYBYTES; -} - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_crypto_sign_publickeybytes(void) { - return PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_CRYPTO_PUBLICKEYBYTES; -} - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_crypto_sign_bytes(void) { - return PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_CRYPTO_BYTES; -} - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_crypto_sign_seedbytes(void) { - return PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_CRYPTO_SEEDBYTES; -} - -/* - * Generates an SPX key pair given a seed of length - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed) { - /* We do not need the auth path in key generation, but it simplifies the - code to have just one treehash routine that computes both root and path - in one function. */ - unsigned char auth_path[PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_TREE_HEIGHT * PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N]; - uint32_t top_tree_addr[8] = {0}; - hash_state hash_state_seeded; - - PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_set_layer_addr( - top_tree_addr, PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_D - 1); - PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_set_type( - top_tree_addr, PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_ADDR_TYPE_HASHTREE); - - /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ - memcpy(sk, seed, PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_CRYPTO_SEEDBYTES); - - memcpy(pk, sk + 2 * PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N, PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_initialize_hash_function(&hash_state_seeded, pk, sk); - - /* Compute root node of the top-most subtree. */ - PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_treehash_TREE_HEIGHT( - sk + 3 * PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N, auth_path, sk, sk + 2 * PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N, 0, 0, - wots_gen_leaf, top_tree_addr, &hash_state_seeded); - - memcpy(pk + PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N, sk + 3 * PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N, PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N); - - return 0; -} - -/* - * Generates an SPX key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk) { - - // guarantee alignment of pk - union { - __m128 _x[PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_CRYPTO_PUBLICKEYBYTES / 16]; - uint8_t pk[PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_CRYPTO_PUBLICKEYBYTES]; - } aligned_pk; - - // guarantee alignment of sk - union { - __m128 _x[PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_CRYPTO_SECRETKEYBYTES / 16]; - uint8_t sk[PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_CRYPTO_SECRETKEYBYTES]; - } aligned_sk; - - union { - __m128 _x[PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_CRYPTO_SEEDBYTES / 16]; - uint8_t seed[PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_CRYPTO_SEEDBYTES]; - } aligned_seed; - randombytes(aligned_seed.seed, PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_CRYPTO_SEEDBYTES); - - PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_crypto_sign_seed_keypair( - aligned_pk.pk, aligned_sk.sk, aligned_seed.seed); - memcpy(pk, aligned_pk.pk, PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_CRYPTO_PUBLICKEYBYTES); - memcpy(sk, aligned_sk.sk, PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_CRYPTO_SECRETKEYBYTES); - - return 0; -} - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - // guarantee alignment of sk - union { - __m128 *_x; - uint8_t sk[PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_CRYPTO_SECRETKEYBYTES]; - } aligned_sk; - memcpy(aligned_sk.sk, sk, PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_CRYPTO_SECRETKEYBYTES); - sk = aligned_sk.sk; - - // guarantee alignment of sig - union { - __m128 *_x; - uint8_t sig[PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_BYTES]; - } aligned_sig; - uint8_t *orig_sig = sig; - sig = (uint8_t *)aligned_sig.sig; - - const unsigned char *sk_seed = sk; - const unsigned char *sk_prf = sk + PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N; - const unsigned char *pk = sk + 2 * PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N; - const unsigned char *pub_seed = pk; - - unsigned char optrand[PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N]; - unsigned char mhash[PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_FORS_MSG_BYTES]; - unsigned char root[PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N]; - uint32_t i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - - hash_state hash_state_seeded; - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_initialize_hash_function( - &hash_state_seeded, - pub_seed, sk_seed); - - PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_set_type( - wots_addr, PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_set_type( - tree_addr, PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_ADDR_TYPE_HASHTREE); - - /* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ - randombytes(optrand, PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N); - /* Compute the digest randomization value. */ - PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_gen_message_random( - sig, sk_prf, optrand, m, mlen, &hash_state_seeded); - - /* Derive the message digest and leaf index from R, PK and M. */ - PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N; - - PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_set_keypair_addr( - wots_addr, idx_leaf); - - /* Sign the message hash using FORS. */ - PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_fors_sign( - sig, root, mhash, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_FORS_BYTES; - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_D; i++) { - PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_set_tree_addr(tree_addr, tree); - - PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_set_keypair_addr( - wots_addr, idx_leaf); - - /* Compute a WOTS signature. */ - PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_wots_sign( - sig, root, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_WOTS_BYTES; - - /* Compute the authentication path for the used WOTS leaf. */ - PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_treehash_TREE_HEIGHT( - root, sig, sk_seed, pub_seed, idx_leaf, 0, - wots_gen_leaf, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_TREE_HEIGHT * PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_TREE_HEIGHT; - } - - memcpy(orig_sig, aligned_sig.sig, PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_BYTES); - *siglen = PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_BYTES; - - return 0; -} - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk) { - // guarantee alignment of pk - union { - __m128 *_x; - uint8_t pk[PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_CRYPTO_PUBLICKEYBYTES]; - } aligned_pk; - memcpy(aligned_pk.pk, pk, PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_CRYPTO_PUBLICKEYBYTES); - pk = aligned_pk.pk; - - const unsigned char *pub_seed = pk; - const unsigned char *pub_root = pk + PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N; - unsigned char mhash[PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_FORS_MSG_BYTES]; - unsigned char wots_pk[PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_WOTS_BYTES]; - unsigned char root[PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N]; - unsigned char leaf[PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N]; - unsigned int i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - hash_state hash_state_seeded; - - if (siglen != PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_BYTES) { - return -1; - } - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_initialize_hash_function( - &hash_state_seeded, - pub_seed, NULL); - - PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_set_type( - wots_addr, PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_set_type( - tree_addr, PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_ADDR_TYPE_HASHTREE); - PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_set_type( - wots_pk_addr, PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_ADDR_TYPE_WOTSPK); - - /* Derive the message digest and leaf index from R || PK || M. */ - /* The additional PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N is a result of the hash domain separator. */ - PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N; - - /* Layer correctly defaults to 0, so no need to set_layer_addr */ - PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_set_keypair_addr( - wots_addr, idx_leaf); - - PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_fors_pk_from_sig( - root, sig, mhash, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_FORS_BYTES; - - /* For each subtree.. */ - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_D; i++) { - PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_set_tree_addr(tree_addr, tree); - - PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_set_keypair_addr( - wots_addr, idx_leaf); - - PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_copy_keypair_addr( - wots_pk_addr, wots_addr); - - /* The WOTS public key is only correct if the signature was correct. */ - /* Initially, root is the FORS pk, but on subsequent iterations it is - the root of the subtree below the currently processed subtree. */ - PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_wots_pk_from_sig( - wots_pk, sig, root, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_WOTS_BYTES; - - /* Compute the leaf node using the WOTS public key. */ - PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_thash_WOTS_LEN( - leaf, wots_pk, pub_seed, wots_pk_addr, &hash_state_seeded); - - /* Compute the root node of this subtree. */ - PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_compute_root( - root, leaf, idx_leaf, 0, sig, PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_TREE_HEIGHT, - pub_seed, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_TREE_HEIGHT * PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_TREE_HEIGHT; - } - - /* Check if the root node equals the root node in the public key. */ - if (memcmp(root, pub_root, PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N) != 0) { - return -1; - } - - return 0; -} - - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - size_t siglen; - - PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_crypto_sign_signature( - sm, &siglen, m, mlen, sk); - - memmove(sm + PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_BYTES, m, mlen); - *smlen = siglen + mlen; - - return 0; -} - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk) { - - // guarantee alignment of pk - union { - __m128 *_x; - uint8_t pk[PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_CRYPTO_PUBLICKEYBYTES]; - } aligned_pk; - memcpy(aligned_pk.pk, pk, PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_CRYPTO_PUBLICKEYBYTES); - pk = aligned_pk.pk; - - - /* The API caller does not necessarily know what size a signature should be - but SPHINCS+ signatures are always exactly PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_BYTES. */ - if (smlen < PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_BYTES) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - *mlen = smlen - PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_BYTES; - - if (PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_crypto_sign_verify( - sm, PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_BYTES, sm + PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_BYTES, *mlen, pk)) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - /* If verification was successful, move the message to the right place. */ - memmove(m, sm + PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_BYTES, *mlen); - - return 0; -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_avx2/thash.h b/src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_avx2/thash.h deleted file mode 100644 index 6207bfbaec..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_avx2/thash.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_THASH_H -#define PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_THASH_H - -#include "hash_state.h" - -#include - -void PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_avx2/thash_shake256_robust.c b/src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_avx2/thash_shake256_robust.c deleted file mode 100644 index 79c9d5d771..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_avx2/thash_shake256_robust.c +++ /dev/null @@ -1,81 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "thash.h" - -#include "fips202.h" - -/** - * Takes an array of inblocks concatenated arrays of PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N bytes. - */ -static void PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_thash( - unsigned char *out, unsigned char *buf, - const unsigned char *in, unsigned int inblocks, - const unsigned char *pub_seed, uint32_t addr[8]) { - - unsigned char *bitmask = buf + PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_ADDR_BYTES; - unsigned int i; - - memcpy(buf, pub_seed, PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N); - PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_addr_to_bytes(buf + PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N, addr); - - shake256(bitmask, inblocks * PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N, buf, PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_ADDR_BYTES); - - for (i = 0; i < inblocks * PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N; i++) { - buf[PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_ADDR_BYTES + i] = in[i] ^ bitmask[i]; - } - - shake256(out, PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N, buf, PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N); -} - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_ADDR_BYTES + 1 * PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N]; - PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_thash( - out, buf, in, 1, pub_seed, addr); - - (void)hash_state_seeded; /* Avoid unused parameter warning. */ -} - -void PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_ADDR_BYTES + 2 * PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N]; - PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_thash( - out, buf, in, 2, pub_seed, addr); - - (void)hash_state_seeded; /* Avoid unused parameter warning. */ -} - -void PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_ADDR_BYTES + PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_WOTS_LEN * PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N]; - PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_thash( - out, buf, in, PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_WOTS_LEN, pub_seed, addr); - - (void)hash_state_seeded; /* Avoid unused parameter warning. */ -} - -void PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_ADDR_BYTES + PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_FORS_TREES * PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N]; - PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_thash( - out, buf, in, PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_FORS_TREES, pub_seed, addr); - - (void)hash_state_seeded; /* Avoid unused parameter warning. */ -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_avx2/thash_shake256_robustx4.c b/src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_avx2/thash_shake256_robustx4.c deleted file mode 100644 index 279afc9bd4..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_avx2/thash_shake256_robustx4.c +++ /dev/null @@ -1,66 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "thashx4.h" - -#include "fips202x4.h" - -/** - * 4-way parallel version of thash; takes 4x as much input and output - */ -#define thash_variant(name, inblocks) \ - void PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_thashx4_##name(unsigned char *out0, \ - unsigned char *out1, \ - unsigned char *out2, \ - unsigned char *out3, \ - const unsigned char *in0, \ - const unsigned char *in1, \ - const unsigned char *in2, \ - const unsigned char *in3, \ - const unsigned char *pub_seed, uint32_t addrx4[4*8], \ - const hash_state *state_seeded) \ - { \ - unsigned char buf0[PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_ADDR_BYTES + (inblocks)*PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N]; \ - unsigned char buf1[PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_ADDR_BYTES + (inblocks)*PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N]; \ - unsigned char buf2[PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_ADDR_BYTES + (inblocks)*PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N]; \ - unsigned char buf3[PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_ADDR_BYTES + (inblocks)*PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N]; \ - unsigned char bitmask0[(inblocks) * PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N]; \ - unsigned char bitmask1[(inblocks) * PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N]; \ - unsigned char bitmask2[(inblocks) * PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N]; \ - unsigned char bitmask3[(inblocks) * PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N]; \ - unsigned int i; \ - \ - memcpy(buf0, pub_seed, PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N); \ - memcpy(buf1, pub_seed, PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N); \ - memcpy(buf2, pub_seed, PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N); \ - memcpy(buf3, pub_seed, PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N); \ - PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_addr_to_bytes(buf0 + PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N, addrx4 + 0*8); \ - PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_addr_to_bytes(buf1 + PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N, addrx4 + 1*8); \ - PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_addr_to_bytes(buf2 + PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N, addrx4 + 2*8); \ - PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_addr_to_bytes(buf3 + PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N, addrx4 + 3*8); \ - \ - PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_shake256x4(bitmask0, bitmask1, bitmask2, bitmask3, (inblocks) * PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N, \ - buf0, buf1, buf2, buf3, PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_ADDR_BYTES); \ - \ - for (i = 0; i < (inblocks) * PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N; i++) { \ - buf0[PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_ADDR_BYTES + i] = in0[i] ^ bitmask0[i]; \ - buf1[PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_ADDR_BYTES + i] = in1[i] ^ bitmask1[i]; \ - buf2[PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_ADDR_BYTES + i] = in2[i] ^ bitmask2[i]; \ - buf3[PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_ADDR_BYTES + i] = in3[i] ^ bitmask3[i]; \ - } \ - \ - PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_shake256x4( \ - out0, out1, out2, out3, PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N, \ - buf0, buf1, buf2, buf3, PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_ADDR_BYTES + (inblocks)*PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N); \ - \ - /* avoid unused parameter warning */ \ - (void)state_seeded; \ - } - - -thash_variant(1, 1) -thash_variant(2, 2) -thash_variant(WOTS_LEN, PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_WOTS_LEN) -thash_variant(FORS_TREES, PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_FORS_TREES) diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_avx2/thashx4.h b/src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_avx2/thashx4.h deleted file mode 100644 index c4964338e0..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_avx2/thashx4.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_THASHX4_H -#define PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_THASHX4_H - -#include - -#include "hash_state.h" - -#define thashx4_header(inblocks) \ - void PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_thashx4_##inblocks(unsigned char *out0, \ - unsigned char *out1, \ - unsigned char *out2, \ - unsigned char *out3, \ - const unsigned char *in0, \ - const unsigned char *in1, \ - const unsigned char *in2, \ - const unsigned char *in3, \ - const unsigned char *pub_seed, uint32_t addrx4[4*8], \ - const hash_state *state_seeded) - -thashx4_header(1); -thashx4_header(2); -thashx4_header(WOTS_LEN); -thashx4_header(FORS_TREES); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_avx2/utils.c b/src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_avx2/utils.c deleted file mode 100644 index a2833551d1..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_avx2/utils.c +++ /dev/null @@ -1,199 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "hash_state.h" -#include "params.h" -#include "thash.h" -#include "utils.h" - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in) { - - /* Iterate over out in decreasing order, for big-endianness. */ - for (size_t i = outlen; i > 0; i--) { - out[i - 1] = in & 0xff; - in = in >> 8; - } -} - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_bytes_to_ull( - const unsigned char *in, size_t inlen) { - unsigned long long retval = 0; - - for (size_t i = 0; i < inlen; i++) { - retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); - } - return retval; -} - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - uint32_t i; - unsigned char buffer[2 * PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N]; - - /* If leaf_idx is odd (last bit = 1), current path element is a right child - and auth_path has to go left. Otherwise it is the other way around. */ - if (leaf_idx & 1) { - memcpy(buffer + PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N, leaf, PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N); - } else { - memcpy(buffer, leaf, PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N); - memcpy(buffer + PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N, auth_path, PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N); - } - auth_path += PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N; - - for (i = 0; i < tree_height - 1; i++) { - leaf_idx >>= 1; - idx_offset >>= 1; - /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_set_tree_height(addr, i + 1); - PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_set_tree_index( - addr, leaf_idx + idx_offset); - - /* Pick the right or left neighbor, depending on parity of the node. */ - if (leaf_idx & 1) { - PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_thash_2( - buffer + PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N); - } else { - PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_thash_2( - buffer, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer + PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N, auth_path, PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N); - } - auth_path += PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N; - } - - /* The last iteration is exceptional; we do not copy an auth_path node. */ - leaf_idx >>= 1; - idx_offset >>= 1; - PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_set_tree_height(addr, tree_height); - PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_set_tree_index( - addr, leaf_idx + idx_offset); - PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_thash_2( - root, buffer, pub_seed, addr, hash_state_seeded); -} - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -static void PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_treehash( - unsigned char *root, unsigned char *auth_path, - unsigned char *stack, unsigned int *heights, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - - unsigned int offset = 0; - uint32_t idx; - uint32_t tree_idx; - - for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { - /* Add the next leaf node to the stack. */ - gen_leaf(stack + offset * PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N, - sk_seed, pub_seed, idx + idx_offset, tree_addr, - hash_state_seeded); - offset++; - heights[offset - 1] = 0; - - /* If this is a node we need for the auth path.. */ - if ((leaf_idx ^ 0x1) == idx) { - memcpy(auth_path, stack + (offset - 1)*PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N, PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N); - } - - /* While the top-most nodes are of equal height.. */ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { - /* Compute index of the new node, in the next layer. */ - tree_idx = (idx >> (heights[offset - 1] + 1)); - - /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_set_tree_height( - tree_addr, heights[offset - 1] + 1); - PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_set_tree_index( - tree_addr, tree_idx + (idx_offset >> (heights[offset - 1] + 1))); - /* Hash the top-most nodes from the stack together. */ - PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_thash_2( - stack + (offset - 2)*PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N, stack + (offset - 2)*PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N, - pub_seed, tree_addr, hash_state_seeded); - offset--; - /* Note that the top-most node is now one layer higher. */ - heights[offset - 1]++; - - /* If this is a node we need for the auth path.. */ - if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_path + heights[offset - 1]*PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N, - stack + (offset - 1)*PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N, PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N); - } - } - } - memcpy(root, stack, PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N); -} - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_FORS_HEIGHT + 1)*PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N]; - unsigned int heights[PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_FORS_HEIGHT + 1]; - - PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_FORS_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_TREE_HEIGHT + 1)*PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N]; - unsigned int heights[PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_TREE_HEIGHT + 1]; - - PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_TREE_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_avx2/utils.h b/src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_avx2/utils.h deleted file mode 100644 index cf6288e758..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_avx2/utils.h +++ /dev/null @@ -1,64 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_UTILS_H -#define PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_UTILS_H - -#include "hash_state.h" -#include "params.h" -#include -#include - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in); - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_bytes_to_ull( - const unsigned char *in, size_t inlen); - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -void PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_avx2/utilsx4.c b/src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_avx2/utilsx4.c deleted file mode 100644 index 2198ac1aa7..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_avx2/utilsx4.c +++ /dev/null @@ -1,98 +0,0 @@ -#include "address.h" -#include "params.h" -#include "thashx4.h" -#include "utils.h" -#include "utilsx4.h" - -#include - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -#define treehashx4_variant(name, tree_height) \ - void PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_treehashx4_##name( \ - unsigned char *rootx4, unsigned char *auth_pathx4, const unsigned char *sk_seed, \ - const unsigned char *pub_seed, const uint32_t leaf_idx[4], uint32_t idx_offset[4], \ - void (*gen_leafx4)(unsigned char * /* leaf0 */, unsigned char * /* leaf1 */, \ - unsigned char * /* leaf2 */, unsigned char * /* leaf3 */, \ - const unsigned char * /* sk_seed */, \ - const unsigned char * /* pub_seed */, uint32_t /* addr_idx0 */, \ - uint32_t /* addr_idx1 */, uint32_t /* addr_idx2 */, \ - uint32_t /* addr_idx3 */, const uint32_t[8] /* tree_addr */, \ - const hash_state * /* state_seeded */), \ - uint32_t tree_addrx4[4 * 8], const hash_state *state_seeded) { \ - unsigned char stackx4[4 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N]; \ - unsigned int heights[(tree_height) + 1]; \ - unsigned int offset = 0; \ - uint32_t idx; \ - uint32_t tree_idx; \ - unsigned int j; \ - \ - for (idx = 0; idx < (uint32_t)(1 << (tree_height)); idx++) { \ - /* Add the next leaf node to the stack. */ \ - gen_leafx4(stackx4 + 0 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N + offset * PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N, \ - stackx4 + 1 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N + offset * PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N, \ - stackx4 + 2 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N + offset * PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N, \ - stackx4 + 3 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N + offset * PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N, sk_seed, \ - pub_seed, idx + idx_offset[0], idx + idx_offset[1], idx + idx_offset[2], \ - idx + idx_offset[3], tree_addrx4, state_seeded); \ - offset++; \ - heights[offset - 1] = 0; \ - \ - /* If this is a node we need for the auth path.. */ \ - for (j = 0; j < 4; j++) { \ - if ((leaf_idx[j] ^ 0x1) == idx) { \ - memcpy(auth_pathx4 + j * (tree_height)*PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N, \ - stackx4 + j * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N + (offset - 1) * PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N, \ - PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N); \ - } \ - } \ - \ - /* While the top-most nodes are of equal height.. */ \ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { \ - /* Compute index of the new node, in the next layer. */ \ - tree_idx = (idx >> (heights[offset - 1] + 1)); \ - \ - /* Set the address of the node we're creating. */ \ - for (j = 0; j < 4; j++) { \ - PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_set_tree_height(tree_addrx4 + j * 8, heights[offset - 1] + 1); \ - PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_set_tree_index(tree_addrx4 + j * 8, \ - tree_idx + (idx_offset[j] >> (heights[offset - 1] + 1))); \ - } \ - /* Hash the top-most nodes from the stack together. */ \ - PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_thashx4_2(stackx4 + 0 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N + (offset - 2) * PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N, \ - stackx4 + 1 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N + (offset - 2) * PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N, \ - stackx4 + 2 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N + (offset - 2) * PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N, \ - stackx4 + 3 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N + (offset - 2) * PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N, \ - stackx4 + 0 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N + (offset - 2) * PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N, \ - stackx4 + 1 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N + (offset - 2) * PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N, \ - stackx4 + 2 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N + (offset - 2) * PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N, \ - stackx4 + 3 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N + (offset - 2) * PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N, \ - pub_seed, tree_addrx4, state_seeded); \ - offset--; \ - /* Note that the top-most node is now one layer higher. */ \ - heights[offset - 1]++; \ - \ - /* If this is a node we need for the auth path.. */ \ - for (j = 0; j < 4; j++) { \ - if (((leaf_idx[j] >> heights[offset - 1]) ^ 0x1) == tree_idx) { \ - memcpy(auth_pathx4 + j * (tree_height)*PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N + \ - heights[offset - 1] * PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N, \ - stackx4 + j * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N + (offset - 1) * PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N, \ - PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N); \ - } \ - } \ - } \ - } \ - \ - for (j = 0; j < 4; j++) { \ - memcpy(rootx4 + j * PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N, stackx4 + j * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N, PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N); \ - } \ - } - -treehashx4_variant(FORS_HEIGHT, PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_FORS_HEIGHT) diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_avx2/utilsx4.h b/src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_avx2/utilsx4.h deleted file mode 100644 index 26107b897b..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_avx2/utilsx4.h +++ /dev/null @@ -1,38 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_UTILSX4_H -#define PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_UTILSX4_H - -#include "hash_state.h" -#include "params.h" - -#include - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -void PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_treehashx4_FORS_HEIGHT(unsigned char *rootx4, - unsigned char *auth_pathx4, - const unsigned char *sk_seed, - const unsigned char *pub_seed, - const uint32_t leaf_idx[4], - uint32_t idx_offset[4], - void (*gen_leafx4)(unsigned char * /* leaf0 */, - unsigned char * /* leaf1 */, - unsigned char * /* leaf2 */, - unsigned char * /* leaf3 */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx0 */, - uint32_t /* addr_idx1 */, - uint32_t /* addr_idx2 */, - uint32_t /* addr_idx3 */, - const uint32_t[8] /* tree_addr */, - const hash_state * /* state_seeded */), - uint32_t tree_addrx4[4 * 8], - const hash_state *state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_avx2/wots.c b/src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_avx2/wots.c deleted file mode 100644 index 71e4dfed8d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_avx2/wots.c +++ /dev/null @@ -1,240 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "hash_state.h" -#include "hashx4.h" -#include "params.h" -#include "thash.h" -#include "thashx4.h" -#include "utils.h" -#include "wots.h" - -// TODO clarify address expectations, and make them more uniform. -// TODO i.e. do we expect types to be set already? -// TODO and do we expect modifications or copies? - -/** - * Computes the starting value for a chain, i.e. the secret key. - * Expects the address to be complete up to the chain address. - */ -static void wots_gen_sk(unsigned char *sk, const unsigned char *sk_seed, - uint32_t wots_addr[8], const hash_state *state_seeded) { - /* Make sure that the hash address is actually zeroed. */ - PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_set_hash_addr(wots_addr, 0); - - /* Generate sk element. */ - PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_prf_addr(sk, sk_seed, wots_addr, state_seeded); -} - -/** - * 4-way parallel version of wots_gen_sk; expects 4x as much space in sk - */ -static void wots_gen_skx4(unsigned char *skx4, const unsigned char *sk_seed, - uint32_t wots_addrx4[4 * 8], const hash_state *state_seeded) { - unsigned int j; - - /* Make sure that the hash address is actually zeroed. */ - for (j = 0; j < 4; j++) { - PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_set_hash_addr(wots_addrx4 + j * 8, 0); - } - - /* Generate sk element. */ - PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_prf_addrx4(skx4 + 0 * PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N, - skx4 + 1 * PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N, - skx4 + 2 * PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N, - skx4 + 3 * PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N, - sk_seed, wots_addrx4, - state_seeded); -} - -/** - * Computes the chaining function. - * out and in have to be n-byte arrays. - * - * Interprets in as start-th value of the chain. - * addr has to contain the address of the chain. - */ -static void gen_chain(unsigned char *out, const unsigned char *in, - unsigned int start, unsigned int steps, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *state_seeded) { - uint32_t i; - - /* Initialize out with the value at position 'start'. */ - memcpy(out, in, PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N); - - /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_WOTS_W; i++) { - PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_set_hash_addr(addr, i); - PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_thash_1(out, out, pub_seed, addr, state_seeded); - } -} - -/** - * 4-way parallel version of gen_chain; expects 4x as much space in out, and - * 4x as much space in inx4. Assumes start and step identical across chains. - */ -static void gen_chainx4(unsigned char *outx4, const unsigned char *inx4, - unsigned int start, unsigned int steps, - const unsigned char *pub_seed, uint32_t addrx4[4 * 8], - const hash_state *state_seeded) { - uint32_t i; - unsigned int j; - - /* Initialize outx4 with the value at position 'start'. */ - memcpy(outx4, inx4, 4 * PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N); - - /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_WOTS_W; i++) { - for (j = 0; j < 4; j++) { - PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_set_hash_addr(addrx4 + j * 8, i); - } - PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_thashx4_1(outx4 + 0 * PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N, - outx4 + 1 * PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N, - outx4 + 2 * PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N, - outx4 + 3 * PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N, - outx4 + 0 * PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N, - outx4 + 1 * PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N, - outx4 + 2 * PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N, - outx4 + 3 * PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N, - pub_seed, addrx4, - state_seeded); - } -} - -/** - * base_w algorithm as described in draft. - * Interprets an array of bytes as integers in base w. - * This only works when log_w is a divisor of 8. - */ -static void base_w(unsigned int *output, const int out_len, const unsigned char *input) { - int in = 0; - int out = 0; - unsigned char total = 0; - int bits = 0; - int consumed; - - for (consumed = 0; consumed < out_len; consumed++) { - if (bits == 0) { - total = input[in]; - in++; - bits += 8; - } - bits -= PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_WOTS_LOGW; - output[out] = (unsigned int)(total >> bits) & (PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_WOTS_W - 1); - out++; - } -} - -/* Computes the WOTS+ checksum over a message (in base_w). */ -static void wots_checksum(unsigned int *csum_base_w, const unsigned int *msg_base_w) { - unsigned int csum = 0; - unsigned char csum_bytes[(PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_WOTS_LEN2 * PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_WOTS_LOGW + 7) / 8]; - unsigned int i; - - /* Compute checksum. */ - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_WOTS_LEN1; i++) { - csum += PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_WOTS_W - 1 - msg_base_w[i]; - } - - /* Convert checksum to base_w. */ - /* Make sure expected empty zero bits are the least significant bits. */ - csum = csum << (8 - ((PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_WOTS_LEN2 * PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_WOTS_LOGW) % 8)); - PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); - base_w(csum_base_w, PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_WOTS_LEN2, csum_bytes); -} - -/* Takes a message and derives the matching chain lengths. */ -static void chain_lengths(unsigned int *lengths, const unsigned char *msg) { - base_w(lengths, PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_WOTS_LEN1, msg); - wots_checksum(lengths + PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_WOTS_LEN1, lengths); -} - -/** - * WOTS key generation. Takes a 32 byte sk_seed, expands it to WOTS private key - * elements and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_wots_gen_pk(unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *state_seeded) { - uint32_t i; - unsigned int j; - - uint32_t addrx4[4 * 8]; - unsigned char pkbuf[4 * PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N]; - - for (j = 0; j < 4; j++) { - memcpy(addrx4 + j * 8, addr, sizeof(uint32_t) * 8); - } - - /* The last iteration typically does not have complete set of 4 chains, - but because we use pkbuf, this is not an issue -- we still do as many - in parallel as possible. */ - for (i = 0; i < ((PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_WOTS_LEN + 3) & ~0x3); i += 4) { - for (j = 0; j < 4; j++) { - PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_set_chain_addr(addrx4 + j * 8, i + j); - } - wots_gen_skx4(pkbuf, sk_seed, addrx4, state_seeded); - gen_chainx4(pkbuf, pkbuf, 0, PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_WOTS_W - 1, pub_seed, addrx4, state_seeded); - for (j = 0; j < 4; j++) { - if (i + j < PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_WOTS_LEN) { - memcpy(pk + (i + j)*PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N, pkbuf + j * PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N, PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N); - } - } - } - - // Get rid of unused argument variable. - (void)state_seeded; -} - -/** - * Takes a n-byte message and the 32-byte sk_see to compute a signature 'sig'. - */ -void PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_wots_sign(unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_WOTS_LEN; i++) { - PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_set_chain_addr(addr, i); - wots_gen_sk(sig + i * PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N, sk_seed, addr, state_seeded); - gen_chain(sig + i * PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N, sig + i * PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N, 0, lengths[i], pub_seed, addr, state_seeded); - } - - // avoid unused argument - (void)state_seeded; -} - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_WOTS_LEN; i++) { - PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_set_chain_addr(addr, i); - gen_chain(pk + i * PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N, sig + i * PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N, - lengths[i], PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_WOTS_W - 1 - lengths[i], pub_seed, addr, - state_seeded); - } - - // avoid unused argument - (void)state_seeded; -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_avx2/wots.h b/src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_avx2/wots.h deleted file mode 100644 index a3204a9a3c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_avx2/wots.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_WOTS_H -#define PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_WOTS_H - -#include "hash_state.h" -#include "params.h" -#include - -/** - * WOTS key generation. Takes a 32 byte seed for the private key, expands it to - * a full WOTS private key and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_wots_gen_pk( - unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -/** - * Takes a n-byte message and the 32-byte seed for the private key to compute a - * signature that is placed at 'sig'. - */ -void PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_wots_sign( - unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *hash_state_seeded); - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_wots_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_clean/LICENSE b/src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_clean/LICENSE deleted file mode 100644 index 670154e353..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_clean/LICENSE +++ /dev/null @@ -1,116 +0,0 @@ -CC0 1.0 Universal - -Statement of Purpose - -The laws of most jurisdictions throughout the world automatically confer -exclusive Copyright and Related Rights (defined below) upon the creator and -subsequent owner(s) (each and all, an "owner") of an original work of -authorship and/or a database (each, a "Work"). - -Certain owners wish to permanently relinquish those rights to a Work for the -purpose of contributing to a commons of creative, cultural and scientific -works ("Commons") that the public can reliably and without fear of later -claims of infringement build upon, modify, incorporate in other works, reuse -and redistribute as freely as possible in any form whatsoever and for any -purposes, including without limitation commercial purposes. These owners may -contribute to the Commons to promote the ideal of a free culture and the -further production of creative, cultural and scientific works, or to gain -reputation or greater distribution for their Work in part through the use and -efforts of others. - -For these and/or other purposes and motivations, and without any expectation -of additional consideration or compensation, the person associating CC0 with a -Work (the "Affirmer"), to the extent that he or she is an owner of Copyright -and Related Rights in the Work, voluntarily elects to apply CC0 to the Work -and publicly distribute the Work under its terms, with knowledge of his or her -Copyright and Related Rights in the Work and the meaning and intended legal -effect of CC0 on those rights. - -1. Copyright and Related Rights. A Work made available under CC0 may be -protected by copyright and related or neighboring rights ("Copyright and -Related Rights"). Copyright and Related Rights include, but are not limited -to, the following: - - i. the right to reproduce, adapt, distribute, perform, display, communicate, - and translate a Work; - - ii. moral rights retained by the original author(s) and/or performer(s); - - iii. publicity and privacy rights pertaining to a person's image or likeness - depicted in a Work; - - iv. rights protecting against unfair competition in regards to a Work, - subject to the limitations in paragraph 4(a), below; - - v. rights protecting the extraction, dissemination, use and reuse of data in - a Work; - - vi. database rights (such as those arising under Directive 96/9/EC of the - European Parliament and of the Council of 11 March 1996 on the legal - protection of databases, and under any national implementation thereof, - including any amended or successor version of such directive); and - - vii. other similar, equivalent or corresponding rights throughout the world - based on applicable law or treaty, and any national implementations thereof. - -2. Waiver. To the greatest extent permitted by, but not in contravention of, -applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and -unconditionally waives, abandons, and surrenders all of Affirmer's Copyright -and Related Rights and associated claims and causes of action, whether now -known or unknown (including existing as well as future claims and causes of -action), in the Work (i) in all territories worldwide, (ii) for the maximum -duration provided by applicable law or treaty (including future time -extensions), (iii) in any current or future medium and for any number of -copies, and (iv) for any purpose whatsoever, including without limitation -commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes -the Waiver for the benefit of each member of the public at large and to the -detriment of Affirmer's heirs and successors, fully intending that such Waiver -shall not be subject to revocation, rescission, cancellation, termination, or -any other legal or equitable action to disrupt the quiet enjoyment of the Work -by the public as contemplated by Affirmer's express Statement of Purpose. - -3. Public License Fallback. Should any part of the Waiver for any reason be -judged legally invalid or ineffective under applicable law, then the Waiver -shall be preserved to the maximum extent permitted taking into account -Affirmer's express Statement of Purpose. In addition, to the extent the Waiver -is so judged Affirmer hereby grants to each affected person a royalty-free, -non transferable, non sublicensable, non exclusive, irrevocable and -unconditional license to exercise Affirmer's Copyright and Related Rights in -the Work (i) in all territories worldwide, (ii) for the maximum duration -provided by applicable law or treaty (including future time extensions), (iii) -in any current or future medium and for any number of copies, and (iv) for any -purpose whatsoever, including without limitation commercial, advertising or -promotional purposes (the "License"). The License shall be deemed effective as -of the date CC0 was applied by Affirmer to the Work. Should any part of the -License for any reason be judged legally invalid or ineffective under -applicable law, such partial invalidity or ineffectiveness shall not -invalidate the remainder of the License, and in such case Affirmer hereby -affirms that he or she will not (i) exercise any of his or her remaining -Copyright and Related Rights in the Work or (ii) assert any associated claims -and causes of action with respect to the Work, in either case contrary to -Affirmer's express Statement of Purpose. - -4. Limitations and Disclaimers. - - a. No trademark or patent rights held by Affirmer are waived, abandoned, - surrendered, licensed or otherwise affected by this document. - - b. Affirmer offers the Work as-is and makes no representations or warranties - of any kind concerning the Work, express, implied, statutory or otherwise, - including without limitation warranties of title, merchantability, fitness - for a particular purpose, non infringement, or the absence of latent or - other defects, accuracy, or the present or absence of errors, whether or not - discoverable, all to the greatest extent permissible under applicable law. - - c. Affirmer disclaims responsibility for clearing rights of other persons - that may apply to the Work or any use thereof, including without limitation - any person's Copyright and Related Rights in the Work. Further, Affirmer - disclaims responsibility for obtaining any necessary consents, permissions - or other rights required for any use of the Work. - - d. Affirmer understands and acknowledges that Creative Commons is not a - party to this document and has no duty or obligation with respect to this - CC0 or use of the Work. - -For more information, please see - diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_clean/address.c b/src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_clean/address.c deleted file mode 100644 index 1cda8cdb5e..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_clean/address.c +++ /dev/null @@ -1,78 +0,0 @@ -#include - -#include "address.h" -#include "params.h" -#include "utils.h" - -void PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]) { - int i; - - for (i = 0; i < 8; i++) { - PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_ull_to_bytes( - bytes + i * 4, 4, addr[i]); - } -} - -void PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_set_layer_addr( - uint32_t addr[8], uint32_t layer) { - addr[0] = layer; -} - -void PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_set_tree_addr( - uint32_t addr[8], uint64_t tree) { - addr[1] = 0; - addr[2] = (uint32_t) (tree >> 32); - addr[3] = (uint32_t) tree; -} - -void PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_set_type( - uint32_t addr[8], uint32_t type) { - addr[4] = type; -} - -void PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; -} - -/* These functions are used for OTS addresses. */ - -void PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_set_keypair_addr( - uint32_t addr[8], uint32_t keypair) { - addr[5] = keypair; -} - -void PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; - out[5] = in[5]; -} - -void PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_set_chain_addr( - uint32_t addr[8], uint32_t chain) { - addr[6] = chain; -} - -void PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_set_hash_addr( - uint32_t addr[8], uint32_t hash) { - addr[7] = hash; -} - -/* These functions are used for all hash tree addresses (including FORS). */ - -void PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_set_tree_height( - uint32_t addr[8], uint32_t tree_height) { - addr[6] = tree_height; -} - -void PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_set_tree_index( - uint32_t addr[8], uint32_t tree_index) { - addr[7] = tree_index; -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_clean/address.h b/src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_clean/address.h deleted file mode 100644 index 14eea7ab2d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_clean/address.h +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_ADDRESS_H -#define PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_ADDRESS_H - -#include - -#define PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_ADDR_TYPE_WOTS 0 -#define PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_ADDR_TYPE_WOTSPK 1 -#define PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_ADDR_TYPE_HASHTREE 2 -#define PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_ADDR_TYPE_FORSTREE 3 -#define PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_ADDR_TYPE_FORSPK 4 - -void PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]); - -void PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_set_layer_addr( - uint32_t addr[8], uint32_t layer); - -void PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_set_tree_addr( - uint32_t addr[8], uint64_t tree); - -void PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_set_type( - uint32_t addr[8], uint32_t type); - -/* Copies the layer and tree part of one address into the other */ -void PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for WOTS and FORS addresses. */ - -void PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_set_keypair_addr( - uint32_t addr[8], uint32_t keypair); - -void PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_set_chain_addr( - uint32_t addr[8], uint32_t chain); - -void PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_set_hash_addr( - uint32_t addr[8], uint32_t hash); - -void PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for all hash tree addresses (including FORS). */ - -void PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_set_tree_height( - uint32_t addr[8], uint32_t tree_height); - -void PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_set_tree_index( - uint32_t addr[8], uint32_t tree_index); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_clean/api.h b/src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_clean/api.h deleted file mode 100644 index 8c87a6be3e..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_clean/api.h +++ /dev/null @@ -1,81 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_API_H -#define PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_API_H - -#include -#include - - - -#define PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_CRYPTO_ALGNAME "SPHINCS+" - -#define PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_CRYPTO_SECRETKEYBYTES 128 -#define PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_CRYPTO_PUBLICKEYBYTES 64 -#define PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_CRYPTO_BYTES 49856 -#define PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_CRYPTO_SEEDBYTES 96 - - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_clean/fors.c b/src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_clean/fors.c deleted file mode 100644 index ccab08c817..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_clean/fors.c +++ /dev/null @@ -1,161 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "fors.h" -#include "hash.h" -#include "hash_state.h" -#include "thash.h" -#include "utils.h" - -static void fors_gen_sk(unsigned char *sk, const unsigned char *sk_seed, - uint32_t fors_leaf_addr[8], const hash_state *hash_state_seeded) { - PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_prf_addr( - sk, sk_seed, fors_leaf_addr, hash_state_seeded); -} - -static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, - const unsigned char *pub_seed, - uint32_t fors_leaf_addr[8], - const hash_state *hash_state_seeded) { - PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_thash_1( - leaf, sk, pub_seed, fors_leaf_addr, hash_state_seeded); -} - -static void fors_gen_leaf(unsigned char *leaf, const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx, const uint32_t fors_tree_addr[8], - const hash_state *hash_state_seeded) { - uint32_t fors_leaf_addr[8] = {0}; - - /* Only copy the parts that must be kept in fors_leaf_addr. */ - PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_copy_keypair_addr( - fors_leaf_addr, fors_tree_addr); - PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_set_type( - fors_leaf_addr, PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_set_tree_index( - fors_leaf_addr, addr_idx); - - fors_gen_sk(leaf, sk_seed, fors_leaf_addr, hash_state_seeded); - fors_sk_to_leaf(leaf, leaf, pub_seed, fors_leaf_addr, hash_state_seeded); -} - -/** - * Interprets m as PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_FORS_HEIGHT-bit unsigned integers. - * Assumes m contains at least PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_FORS_TREES bits. - * Assumes indices has space for PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_FORS_TREES integers. - */ -static void message_to_indices(uint32_t *indices, const unsigned char *m) { - unsigned int i, j; - unsigned int offset = 0; - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_FORS_TREES; i++) { - indices[i] = 0; - for (j = 0; j < PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_FORS_HEIGHT; j++) { - indices[i] ^= (((uint32_t)m[offset >> 3] >> (offset & 0x7)) & 0x1) << j; - offset++; - } - } -} - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_fors_sign( - unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *hash_state_seeded) { - uint32_t indices[PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_FORS_TREES]; - unsigned char roots[PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_FORS_TREES * PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_N]; - uint32_t fors_tree_addr[8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_copy_keypair_addr( - fors_tree_addr, fors_addr); - PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_copy_keypair_addr( - fors_pk_addr, fors_addr); - - PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_set_type( - fors_tree_addr, PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_set_type( - fors_pk_addr, PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_FORS_TREES; i++) { - idx_offset = i * (1 << PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_FORS_HEIGHT); - - PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_set_tree_height( - fors_tree_addr, 0); - PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_set_tree_index( - fors_tree_addr, indices[i] + idx_offset); - - /* Include the secret key part that produces the selected leaf node. */ - fors_gen_sk(sig, sk_seed, fors_tree_addr, hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_N; - - /* Compute the authentication path for this leaf node. */ - PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_treehash_FORS_HEIGHT( - roots + i * PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_N, sig, sk_seed, pub_seed, - indices[i], idx_offset, fors_gen_leaf, fors_tree_addr, - hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_N * PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_thash_FORS_TREES( - pk, roots, pub_seed, fors_pk_addr, hash_state_seeded); -} - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_fors_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, const uint32_t fors_addr[8], - const hash_state *hash_state_seeded) { - uint32_t indices[PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_FORS_TREES]; - unsigned char roots[PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_FORS_TREES * PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_N]; - unsigned char leaf[PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_N]; - uint32_t fors_tree_addr[8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_copy_keypair_addr(fors_tree_addr, fors_addr); - PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_copy_keypair_addr(fors_pk_addr, fors_addr); - - PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_set_type(fors_tree_addr, PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_set_type(fors_pk_addr, PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_FORS_TREES; i++) { - idx_offset = i * (1 << PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_FORS_HEIGHT); - - PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_set_tree_height(fors_tree_addr, 0); - PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Derive the leaf from the included secret key part. */ - fors_sk_to_leaf(leaf, sig, pub_seed, fors_tree_addr, hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_N; - - /* Derive the corresponding root node of this tree. */ - PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_compute_root(roots + i * PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_N, leaf, indices[i], idx_offset, sig, - PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_FORS_HEIGHT, pub_seed, fors_tree_addr, hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_N * PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_thash_FORS_TREES(pk, roots, pub_seed, fors_pk_addr, hash_state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_clean/fors.h b/src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_clean/fors.h deleted file mode 100644 index 07edc714e7..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_clean/fors.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_FORS_H -#define PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_FORS_H - -#include - -#include "hash_state.h" -#include "params.h" - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_fors_sign( - unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *hash_state_seeded); - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_fors_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, const uint32_t fors_addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_clean/hash.h b/src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_clean/hash.h deleted file mode 100644 index 7d8a2303c7..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_clean/hash.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_HASH_H -#define PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_HASH_H - -#include "hash_state.h" - -#include -#include - -void PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_initialize_hash_function( - hash_state *hash_state_seeded, - const unsigned char *pub_seed, const unsigned char *sk_seed); - -void PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_destroy_hash_function(hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_clean/hash_shake256.c b/src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_clean/hash_shake256.c deleted file mode 100644 index 750baedc1c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_clean/hash_shake256.c +++ /dev/null @@ -1,106 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "utils.h" - -#include "fips202.h" - -/* For SHAKE256, there is no immediate reason to initialize at the start, - so this function is an empty operation. */ -void PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_initialize_hash_function( - hash_state *hash_state_seeded, // NOLINT(readability-non-const-parameter) - const unsigned char *pub_seed, const unsigned char *sk_seed) { - (void)hash_state_seeded; /* Suppress an 'unused parameter' warning. */ - (void)pub_seed; /* Suppress an 'unused parameter' warning. */ - (void)sk_seed; /* Suppress an 'unused parameter' warning. */ -} - -/* This is not necessary for SHAKE256, so we don't do anything */ -void PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_destroy_hash_function( - hash_state *hash_state_seeded) { // NOLINT(readability-non-const-parameter) - (void)hash_state_seeded; -} - -/* - * Computes PRF(key, addr), given a secret key of PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_N bytes and an address - */ -void PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded) { - unsigned char buf[PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_N + PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_ADDR_BYTES]; - - memcpy(buf, key, PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_N); - PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_addr_to_bytes(buf + PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_N, addr); - - shake256(out, PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_N, buf, PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_N + PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_ADDR_BYTES); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} - -/** - * Computes the message-dependent randomness R, using a secret seed and an - * optional randomization value as well as the message. - */ -void PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded) { - shake256incctx state; - - shake256_inc_init(&state); - shake256_inc_absorb(&state, sk_prf, PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_N); - shake256_inc_absorb(&state, optrand, PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_N); - shake256_inc_absorb(&state, m, mlen); - shake256_inc_finalize(&state); - shake256_inc_squeeze(R, PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_N, &state); - shake256_inc_ctx_release(&state); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} - -/** - * Computes the message hash using R, the public key, and the message. - * Outputs the message digest and the index of the leaf. The index is split in - * the tree index and the leaf index, for convenient copying to an address. - */ -void PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded) { -#define PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_TREE_BITS (PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_TREE_HEIGHT * (PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_D - 1)) -#define PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_TREE_BYTES ((PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_TREE_BITS + 7) / 8) -#define PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_LEAF_BITS PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_TREE_HEIGHT -#define PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_LEAF_BYTES ((PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_LEAF_BITS + 7) / 8) -#define PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_DGST_BYTES (PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_FORS_MSG_BYTES + PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_TREE_BYTES + PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_LEAF_BYTES) - - unsigned char buf[PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_DGST_BYTES]; - unsigned char *bufp = buf; - shake256incctx state; - - shake256_inc_init(&state); - shake256_inc_absorb(&state, R, PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_N); - shake256_inc_absorb(&state, pk, PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_PK_BYTES); - shake256_inc_absorb(&state, m, mlen); - shake256_inc_finalize(&state); - shake256_inc_squeeze(buf, PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_DGST_BYTES, &state); - shake256_inc_ctx_release(&state); - - memcpy(digest, bufp, PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_FORS_MSG_BYTES); - bufp += PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_FORS_MSG_BYTES; - - *tree = PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_bytes_to_ull( - bufp, PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_TREE_BYTES); - *tree &= (~(uint64_t)0) >> (64 - PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_TREE_BITS); - bufp += PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_TREE_BYTES; - - *leaf_idx = (uint32_t)PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_bytes_to_ull( - bufp, PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_LEAF_BYTES); - *leaf_idx &= (~(uint32_t)0) >> (32 - PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_LEAF_BITS); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_clean/hash_state.h b/src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_clean/hash_state.h deleted file mode 100644 index 7d92ef872a..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_clean/hash_state.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef SPX_HASH_STATE_H -#define SPX_HASH_STATE_H - -/** - * Defines the type of the hash function state. - * - * Don't be fooled into thinking this instance of SPHINCS+ isn't stateless! - * - * From Section 7.2.2 from the SPHINCS+ round-2 specification: - * - * Each of the instances of the tweakable hash function take PK.seed as its - * first input, which is constant for a given key pair – and, thus, across - * a single signature. This leads to a lot of redundant computation. To remedy - * this, we pad PK.seed to the length of a full 64-byte SHA-256 input block. - * Because of the Merkle-Damgård construction that underlies SHA-256, this - * allows for reuse of the intermediate SHA-256 state after the initial call to - * the compression function which improves performance. - * - * We pass this hash state around in functions, because otherwise we need to - * have a global variable. - * - * SHAKE256 does not need this state. Because this implementation is generated - * from a shared code base, we still need to specify some hash_state as it is - * still passed around. We chose to use an `int` as a placeholder for this - * purpose. - */ - -#define hash_state int - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_clean/params.h b/src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_clean/params.h deleted file mode 100644 index d92758579b..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_clean/params.h +++ /dev/null @@ -1,53 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_PARAMS_H -#define PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_PARAMS_H - -/* Hash output length in bytes. */ -#define PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_N 32 -/* Height of the hypertree. */ -#define PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_FULL_HEIGHT 68 -/* Number of subtree layer. */ -#define PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_D 17 -/* FORS tree dimensions. */ -#define PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_FORS_HEIGHT 9 -#define PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_FORS_TREES 35 -/* Winternitz parameter, */ -#define PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_WOTS_W 16 - -/* The hash function is defined by linking a different hash.c file, as opposed - to setting a #define constant. */ - -/* For clarity */ -#define PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_ADDR_BYTES 32 - -/* WOTS parameters. */ -#define PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_WOTS_LOGW 4 - -#define PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_WOTS_LEN1 (8 * PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_N / PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_WOTS_LOGW) - -/* PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#define PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_WOTS_LEN2 3 - -#define PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_WOTS_LEN (PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_WOTS_LEN1 + PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_WOTS_LEN2) -#define PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_WOTS_BYTES (PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_WOTS_LEN * PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_N) -#define PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_WOTS_PK_BYTES PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_WOTS_BYTES - -/* Subtree size. */ -#define PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_TREE_HEIGHT (PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_FULL_HEIGHT / PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_D) - -/* FORS parameters. */ -#define PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_FORS_MSG_BYTES ((PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_FORS_TREES + 7) / 8) -#define PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_FORS_BYTES ((PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_FORS_HEIGHT + 1) * PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_FORS_TREES * PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_N) -#define PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_FORS_PK_BYTES PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_N - -/* Resulting SPX sizes. */ -#define PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_BYTES (PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_N + PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_FORS_BYTES + PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_D * PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_WOTS_BYTES +\ - PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_FULL_HEIGHT * PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_N) -#define PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_PK_BYTES (2 * PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_N) -#define PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_SK_BYTES (2 * PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_N + PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_PK_BYTES) - -/* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ -#define PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_OPTRAND_BYTES 32 - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_clean/sign.c b/src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_clean/sign.c deleted file mode 100644 index 0cff0a1cc9..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_clean/sign.c +++ /dev/null @@ -1,356 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "api.h" -#include "fors.h" -#include "hash.h" -#include "hash_state.h" -#include "params.h" -#include "randombytes.h" -#include "thash.h" -#include "utils.h" -#include "wots.h" - -/** - * Computes the leaf at a given address. First generates the WOTS key pair, - * then computes leaf by hashing horizontally. - */ -static void wots_gen_leaf(unsigned char *leaf, const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx, const uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - unsigned char pk[PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_WOTS_BYTES]; - uint32_t wots_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_set_type( - wots_addr, PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_set_type( - wots_pk_addr, PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_ADDR_TYPE_WOTSPK); - - PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_set_keypair_addr( - wots_addr, addr_idx); - PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_wots_gen_pk( - pk, sk_seed, pub_seed, wots_addr, hash_state_seeded); - - PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_copy_keypair_addr( - wots_pk_addr, wots_addr); - PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_thash_WOTS_LEN( - leaf, pk, pub_seed, wots_pk_addr, hash_state_seeded); -} - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_crypto_sign_secretkeybytes(void) { - return PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_CRYPTO_SECRETKEYBYTES; -} - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_crypto_sign_publickeybytes(void) { - return PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_CRYPTO_PUBLICKEYBYTES; -} - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_crypto_sign_bytes(void) { - return PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_CRYPTO_BYTES; -} - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_crypto_sign_seedbytes(void) { - return PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_CRYPTO_SEEDBYTES; -} - -/* - * Generates an SPX key pair given a seed of length - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed) { - /* We do not need the auth path in key generation, but it simplifies the - code to have just one treehash routine that computes both root and path - in one function. */ - unsigned char auth_path[PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_TREE_HEIGHT * PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_N]; - uint32_t top_tree_addr[8] = {0}; - hash_state hash_state_seeded; - - PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_set_layer_addr( - top_tree_addr, PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_D - 1); - PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_set_type( - top_tree_addr, PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_ADDR_TYPE_HASHTREE); - - /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ - memcpy(sk, seed, PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_CRYPTO_SEEDBYTES); - - memcpy(pk, sk + 2 * PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_N, PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_initialize_hash_function(&hash_state_seeded, pk, sk); - - /* Compute root node of the top-most subtree. */ - PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_treehash_TREE_HEIGHT( - sk + 3 * PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_N, auth_path, sk, sk + 2 * PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_N, 0, 0, - wots_gen_leaf, top_tree_addr, &hash_state_seeded); - - memcpy(pk + PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_N, sk + 3 * PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_N, PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_N); - - PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_destroy_hash_function(&hash_state_seeded); - return 0; -} - -/* - * Generates an SPX key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk) { - unsigned char seed[PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_CRYPTO_SEEDBYTES]; - randombytes(seed, PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_CRYPTO_SEEDBYTES); - PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_crypto_sign_seed_keypair( - pk, sk, seed); - - return 0; -} - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - const unsigned char *sk_seed = sk; - const unsigned char *sk_prf = sk + PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_N; - const unsigned char *pk = sk + 2 * PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_N; - const unsigned char *pub_seed = pk; - - unsigned char optrand[PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_N]; - unsigned char mhash[PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_FORS_MSG_BYTES]; - unsigned char root[PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_N]; - uint32_t i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - - hash_state hash_state_seeded; - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_initialize_hash_function( - &hash_state_seeded, - pub_seed, sk_seed); - - PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_set_type( - wots_addr, PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_set_type( - tree_addr, PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_ADDR_TYPE_HASHTREE); - - /* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ - randombytes(optrand, PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_N); - /* Compute the digest randomization value. */ - PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_gen_message_random( - sig, sk_prf, optrand, m, mlen, &hash_state_seeded); - - /* Derive the message digest and leaf index from R, PK and M. */ - PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_N; - - PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); - - /* Sign the message hash using FORS. */ - PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_fors_sign( - sig, root, mhash, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_FORS_BYTES; - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_D; i++) { - PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_set_tree_addr(tree_addr, tree); - - PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); - - /* Compute a WOTS signature. */ - PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_wots_sign( - sig, root, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_WOTS_BYTES; - - /* Compute the authentication path for the used WOTS leaf. */ - PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_treehash_TREE_HEIGHT( - root, sig, sk_seed, pub_seed, idx_leaf, 0, - wots_gen_leaf, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_TREE_HEIGHT * PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_TREE_HEIGHT; - } - - *siglen = PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_BYTES; - - PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_destroy_hash_function(&hash_state_seeded); - return 0; -} - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk) { - const unsigned char *pub_seed = pk; - const unsigned char *pub_root = pk + PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_N; - unsigned char mhash[PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_FORS_MSG_BYTES]; - unsigned char wots_pk[PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_WOTS_BYTES]; - unsigned char root[PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_N]; - unsigned char leaf[PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_N]; - unsigned int i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - hash_state hash_state_seeded; - - if (siglen != PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_BYTES) { - return -1; - } - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_initialize_hash_function( - &hash_state_seeded, - pub_seed, NULL); - - PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_set_type( - wots_addr, PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_set_type( - tree_addr, PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_ADDR_TYPE_HASHTREE); - PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_set_type( - wots_pk_addr, PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_ADDR_TYPE_WOTSPK); - - /* Derive the message digest and leaf index from R || PK || M. */ - /* The additional PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_N is a result of the hash domain separator. */ - PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_N; - - /* Layer correctly defaults to 0, so no need to set_layer_addr */ - PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); - - PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_fors_pk_from_sig( - root, sig, mhash, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_FORS_BYTES; - - /* For each subtree.. */ - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_D; i++) { - PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_set_tree_addr(tree_addr, tree); - - PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); - - PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_copy_keypair_addr( - wots_pk_addr, wots_addr); - - /* The WOTS public key is only correct if the signature was correct. */ - /* Initially, root is the FORS pk, but on subsequent iterations it is - the root of the subtree below the currently processed subtree. */ - PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_wots_pk_from_sig( - wots_pk, sig, root, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_WOTS_BYTES; - - /* Compute the leaf node using the WOTS public key. */ - PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_thash_WOTS_LEN( - leaf, wots_pk, pub_seed, wots_pk_addr, &hash_state_seeded); - - /* Compute the root node of this subtree. */ - PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_compute_root( - root, leaf, idx_leaf, 0, sig, PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_TREE_HEIGHT, - pub_seed, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_TREE_HEIGHT * PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_TREE_HEIGHT; - } - - PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_destroy_hash_function(&hash_state_seeded); - /* Check if the root node equals the root node in the public key. */ - if (memcmp(root, pub_root, PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_N) != 0) { - return -1; - } - - return 0; -} - - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - size_t siglen; - - PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_crypto_sign_signature( - sm, &siglen, m, mlen, sk); - - memmove(sm + PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_BYTES, m, mlen); - *smlen = siglen + mlen; - - return 0; -} - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk) { - /* The API caller does not necessarily know what size a signature should be - but SPHINCS+ signatures are always exactly PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_BYTES. */ - if (smlen < PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_BYTES) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - *mlen = smlen - PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_BYTES; - - if (PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_crypto_sign_verify( - sm, PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_BYTES, sm + PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_BYTES, *mlen, pk)) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - /* If verification was successful, move the message to the right place. */ - memmove(m, sm + PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_BYTES, *mlen); - - return 0; -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_clean/thash.h b/src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_clean/thash.h deleted file mode 100644 index 823074b1a7..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_clean/thash.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_THASH_H -#define PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_THASH_H - -#include "hash_state.h" - -#include - -void PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_clean/thash_shake256_robust.c b/src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_clean/thash_shake256_robust.c deleted file mode 100644 index 0a89b37a9c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_clean/thash_shake256_robust.c +++ /dev/null @@ -1,81 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "thash.h" - -#include "fips202.h" - -/** - * Takes an array of inblocks concatenated arrays of PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_N bytes. - */ -static void PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_thash( - unsigned char *out, unsigned char *buf, - const unsigned char *in, unsigned int inblocks, - const unsigned char *pub_seed, uint32_t addr[8]) { - - unsigned char *bitmask = buf + PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_N + PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_ADDR_BYTES; - unsigned int i; - - memcpy(buf, pub_seed, PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_N); - PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_addr_to_bytes(buf + PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_N, addr); - - shake256(bitmask, inblocks * PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_N, buf, PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_N + PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_ADDR_BYTES); - - for (i = 0; i < inblocks * PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_N; i++) { - buf[PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_N + PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_ADDR_BYTES + i] = in[i] ^ bitmask[i]; - } - - shake256(out, PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_N, buf, PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_N + PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_N); -} - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_N + PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_ADDR_BYTES + 1 * PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_N]; - PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_thash( - out, buf, in, 1, pub_seed, addr); - - (void)hash_state_seeded; /* Avoid unused parameter warning. */ -} - -void PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_N + PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_ADDR_BYTES + 2 * PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_N]; - PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_thash( - out, buf, in, 2, pub_seed, addr); - - (void)hash_state_seeded; /* Avoid unused parameter warning. */ -} - -void PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_N + PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_ADDR_BYTES + PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_WOTS_LEN * PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_N]; - PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_thash( - out, buf, in, PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_WOTS_LEN, pub_seed, addr); - - (void)hash_state_seeded; /* Avoid unused parameter warning. */ -} - -void PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_N + PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_ADDR_BYTES + PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_FORS_TREES * PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_N]; - PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_thash( - out, buf, in, PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_FORS_TREES, pub_seed, addr); - - (void)hash_state_seeded; /* Avoid unused parameter warning. */ -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_clean/utils.c b/src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_clean/utils.c deleted file mode 100644 index 59d8ead525..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_clean/utils.c +++ /dev/null @@ -1,199 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "hash_state.h" -#include "params.h" -#include "thash.h" -#include "utils.h" - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in) { - - /* Iterate over out in decreasing order, for big-endianness. */ - for (size_t i = outlen; i > 0; i--) { - out[i - 1] = in & 0xff; - in = in >> 8; - } -} - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_bytes_to_ull( - const unsigned char *in, size_t inlen) { - unsigned long long retval = 0; - - for (size_t i = 0; i < inlen; i++) { - retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); - } - return retval; -} - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - uint32_t i; - unsigned char buffer[2 * PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_N]; - - /* If leaf_idx is odd (last bit = 1), current path element is a right child - and auth_path has to go left. Otherwise it is the other way around. */ - if (leaf_idx & 1) { - memcpy(buffer + PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_N, leaf, PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_N); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_N); - } else { - memcpy(buffer, leaf, PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_N); - memcpy(buffer + PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_N, auth_path, PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_N); - } - auth_path += PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_N; - - for (i = 0; i < tree_height - 1; i++) { - leaf_idx >>= 1; - idx_offset >>= 1; - /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_set_tree_height(addr, i + 1); - PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_set_tree_index( - addr, leaf_idx + idx_offset); - - /* Pick the right or left neighbor, depending on parity of the node. */ - if (leaf_idx & 1) { - PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_thash_2( - buffer + PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_N, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_N); - } else { - PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_thash_2( - buffer, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer + PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_N, auth_path, PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_N); - } - auth_path += PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_N; - } - - /* The last iteration is exceptional; we do not copy an auth_path node. */ - leaf_idx >>= 1; - idx_offset >>= 1; - PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_set_tree_height(addr, tree_height); - PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_set_tree_index( - addr, leaf_idx + idx_offset); - PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_thash_2( - root, buffer, pub_seed, addr, hash_state_seeded); -} - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -static void PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_treehash( - unsigned char *root, unsigned char *auth_path, - unsigned char *stack, unsigned int *heights, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - - unsigned int offset = 0; - uint32_t idx; - uint32_t tree_idx; - - for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { - /* Add the next leaf node to the stack. */ - gen_leaf(stack + offset * PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_N, - sk_seed, pub_seed, idx + idx_offset, tree_addr, - hash_state_seeded); - offset++; - heights[offset - 1] = 0; - - /* If this is a node we need for the auth path.. */ - if ((leaf_idx ^ 0x1) == idx) { - memcpy(auth_path, stack + (offset - 1)*PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_N, PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_N); - } - - /* While the top-most nodes are of equal height.. */ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { - /* Compute index of the new node, in the next layer. */ - tree_idx = (idx >> (heights[offset - 1] + 1)); - - /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_set_tree_height( - tree_addr, heights[offset - 1] + 1); - PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_set_tree_index( - tree_addr, tree_idx + (idx_offset >> (heights[offset - 1] + 1))); - /* Hash the top-most nodes from the stack together. */ - PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_thash_2( - stack + (offset - 2)*PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_N, stack + (offset - 2)*PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_N, - pub_seed, tree_addr, hash_state_seeded); - offset--; - /* Note that the top-most node is now one layer higher. */ - heights[offset - 1]++; - - /* If this is a node we need for the auth path.. */ - if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_path + heights[offset - 1]*PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_N, - stack + (offset - 1)*PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_N, PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_N); - } - } - } - memcpy(root, stack, PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_N); -} - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_FORS_HEIGHT + 1)*PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_N]; - unsigned int heights[PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_FORS_HEIGHT + 1]; - - PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_FORS_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_TREE_HEIGHT + 1)*PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_N]; - unsigned int heights[PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_TREE_HEIGHT + 1]; - - PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_TREE_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_clean/utils.h b/src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_clean/utils.h deleted file mode 100644 index 9eacb4cd2c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_clean/utils.h +++ /dev/null @@ -1,64 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_UTILS_H -#define PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_UTILS_H - -#include "hash_state.h" -#include "params.h" -#include -#include - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in); - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_bytes_to_ull( - const unsigned char *in, size_t inlen); - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -void PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_clean/wots.c b/src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_clean/wots.c deleted file mode 100644 index c5a0ca213c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_clean/wots.c +++ /dev/null @@ -1,167 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "hash_state.h" -#include "params.h" -#include "thash.h" -#include "utils.h" -#include "wots.h" - -// TODO clarify address expectations, and make them more uniform. -// TODO i.e. do we expect types to be set already? -// TODO and do we expect modifications or copies? - -/** - * Computes the starting value for a chain, i.e. the secret key. - * Expects the address to be complete up to the chain address. - */ -static void wots_gen_sk(unsigned char *sk, const unsigned char *sk_seed, - uint32_t wots_addr[8], - const hash_state *hash_state_seeded) { - /* Make sure that the hash address is actually zeroed. */ - PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_set_hash_addr(wots_addr, 0); - - /* Generate sk element. */ - PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_prf_addr(sk, sk_seed, wots_addr, hash_state_seeded); -} - -/** - * Computes the chaining function. - * out and in have to be n-byte arrays. - * - * Interprets in as start-th value of the chain. - * addr has to contain the address of the chain. - */ -static void gen_chain(unsigned char *out, const unsigned char *in, - unsigned int start, unsigned int steps, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - uint32_t i; - - /* Initialize out with the value at position 'start'. */ - memcpy(out, in, PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_N); - - /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_WOTS_W; i++) { - PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_set_hash_addr(addr, i); - PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_thash_1( - out, out, pub_seed, addr, hash_state_seeded); - } -} - -/** - * base_w algorithm as described in draft. - * Interprets an array of bytes as integers in base w. - * This only works when log_w is a divisor of 8. - */ -static void base_w(unsigned int *output, const size_t out_len, - const unsigned char *input) { - size_t in = 0; - size_t out = 0; - unsigned char total = 0; - unsigned int bits = 0; - size_t consumed; - - for (consumed = 0; consumed < out_len; consumed++) { - if (bits == 0) { - total = input[in]; - in++; - bits += 8; - } - bits -= PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_WOTS_LOGW; - output[out] = (unsigned int)((total >> bits) & (PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_WOTS_W - 1)); - out++; - } -} - -/* Computes the WOTS+ checksum over a message (in base_w). */ -static void wots_checksum(unsigned int *csum_base_w, - const unsigned int *msg_base_w) { - unsigned int csum = 0; - unsigned char csum_bytes[(PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_WOTS_LEN2 * PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_WOTS_LOGW + 7) / 8]; - unsigned int i; - - /* Compute checksum. */ - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_WOTS_LEN1; i++) { - csum += PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_WOTS_W - 1 - msg_base_w[i]; - } - - /* Convert checksum to base_w. */ - /* Make sure expected empty zero bits are the least significant bits. */ - csum = csum << (8 - ((PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_WOTS_LEN2 * PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_WOTS_LOGW) % 8)); - PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_ull_to_bytes( - csum_bytes, sizeof(csum_bytes), csum); - base_w(csum_base_w, PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_WOTS_LEN2, csum_bytes); -} - -/* Takes a message and derives the matching chain lengths. */ -static void chain_lengths(unsigned int *lengths, const unsigned char *msg) { - base_w(lengths, PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_WOTS_LEN1, msg); - wots_checksum(lengths + PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_WOTS_LEN1, lengths); -} - -/** - * WOTS key generation. Takes a 32 byte sk_seed, expands it to WOTS private key - * elements and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_wots_gen_pk( - unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - uint32_t i; - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_WOTS_LEN; i++) { - PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_set_chain_addr(addr, i); - wots_gen_sk(pk + i * PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_N, sk_seed, addr, hash_state_seeded); - gen_chain(pk + i * PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_N, pk + i * PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_N, - 0, PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_WOTS_W - 1, pub_seed, addr, hash_state_seeded); - } -} - -/** - * Takes a n-byte message and the 32-byte sk_see to compute a signature 'sig'. - */ -void PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_wots_sign( - unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *hash_state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_WOTS_LEN; i++) { - PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_set_chain_addr(addr, i); - wots_gen_sk(sig + i * PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_N, sk_seed, addr, hash_state_seeded); - gen_chain(sig + i * PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_N, sig + i * PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_N, 0, lengths[i], pub_seed, addr, hash_state_seeded); - } -} - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_wots_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_WOTS_LEN; i++) { - PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_set_chain_addr(addr, i); - gen_chain(pk + i * PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_N, sig + i * PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_N, - lengths[i], PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_WOTS_W - 1 - lengths[i], pub_seed, addr, - hash_state_seeded); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_clean/wots.h b/src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_clean/wots.h deleted file mode 100644 index 7468f3872c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256f-robust_clean/wots.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_WOTS_H -#define PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_WOTS_H - -#include "hash_state.h" -#include "params.h" -#include - -/** - * WOTS key generation. Takes a 32 byte seed for the private key, expands it to - * a full WOTS private key and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_wots_gen_pk( - unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -/** - * Takes a n-byte message and the 32-byte seed for the private key to compute a - * signature that is placed at 'sig'. - */ -void PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_wots_sign( - unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *hash_state_seeded); - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_wots_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_avx2/LICENSE b/src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_avx2/LICENSE deleted file mode 100644 index 670154e353..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_avx2/LICENSE +++ /dev/null @@ -1,116 +0,0 @@ -CC0 1.0 Universal - -Statement of Purpose - -The laws of most jurisdictions throughout the world automatically confer -exclusive Copyright and Related Rights (defined below) upon the creator and -subsequent owner(s) (each and all, an "owner") of an original work of -authorship and/or a database (each, a "Work"). - -Certain owners wish to permanently relinquish those rights to a Work for the -purpose of contributing to a commons of creative, cultural and scientific -works ("Commons") that the public can reliably and without fear of later -claims of infringement build upon, modify, incorporate in other works, reuse -and redistribute as freely as possible in any form whatsoever and for any -purposes, including without limitation commercial purposes. These owners may -contribute to the Commons to promote the ideal of a free culture and the -further production of creative, cultural and scientific works, or to gain -reputation or greater distribution for their Work in part through the use and -efforts of others. - -For these and/or other purposes and motivations, and without any expectation -of additional consideration or compensation, the person associating CC0 with a -Work (the "Affirmer"), to the extent that he or she is an owner of Copyright -and Related Rights in the Work, voluntarily elects to apply CC0 to the Work -and publicly distribute the Work under its terms, with knowledge of his or her -Copyright and Related Rights in the Work and the meaning and intended legal -effect of CC0 on those rights. - -1. Copyright and Related Rights. A Work made available under CC0 may be -protected by copyright and related or neighboring rights ("Copyright and -Related Rights"). Copyright and Related Rights include, but are not limited -to, the following: - - i. the right to reproduce, adapt, distribute, perform, display, communicate, - and translate a Work; - - ii. moral rights retained by the original author(s) and/or performer(s); - - iii. publicity and privacy rights pertaining to a person's image or likeness - depicted in a Work; - - iv. rights protecting against unfair competition in regards to a Work, - subject to the limitations in paragraph 4(a), below; - - v. rights protecting the extraction, dissemination, use and reuse of data in - a Work; - - vi. database rights (such as those arising under Directive 96/9/EC of the - European Parliament and of the Council of 11 March 1996 on the legal - protection of databases, and under any national implementation thereof, - including any amended or successor version of such directive); and - - vii. other similar, equivalent or corresponding rights throughout the world - based on applicable law or treaty, and any national implementations thereof. - -2. Waiver. To the greatest extent permitted by, but not in contravention of, -applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and -unconditionally waives, abandons, and surrenders all of Affirmer's Copyright -and Related Rights and associated claims and causes of action, whether now -known or unknown (including existing as well as future claims and causes of -action), in the Work (i) in all territories worldwide, (ii) for the maximum -duration provided by applicable law or treaty (including future time -extensions), (iii) in any current or future medium and for any number of -copies, and (iv) for any purpose whatsoever, including without limitation -commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes -the Waiver for the benefit of each member of the public at large and to the -detriment of Affirmer's heirs and successors, fully intending that such Waiver -shall not be subject to revocation, rescission, cancellation, termination, or -any other legal or equitable action to disrupt the quiet enjoyment of the Work -by the public as contemplated by Affirmer's express Statement of Purpose. - -3. Public License Fallback. Should any part of the Waiver for any reason be -judged legally invalid or ineffective under applicable law, then the Waiver -shall be preserved to the maximum extent permitted taking into account -Affirmer's express Statement of Purpose. In addition, to the extent the Waiver -is so judged Affirmer hereby grants to each affected person a royalty-free, -non transferable, non sublicensable, non exclusive, irrevocable and -unconditional license to exercise Affirmer's Copyright and Related Rights in -the Work (i) in all territories worldwide, (ii) for the maximum duration -provided by applicable law or treaty (including future time extensions), (iii) -in any current or future medium and for any number of copies, and (iv) for any -purpose whatsoever, including without limitation commercial, advertising or -promotional purposes (the "License"). The License shall be deemed effective as -of the date CC0 was applied by Affirmer to the Work. Should any part of the -License for any reason be judged legally invalid or ineffective under -applicable law, such partial invalidity or ineffectiveness shall not -invalidate the remainder of the License, and in such case Affirmer hereby -affirms that he or she will not (i) exercise any of his or her remaining -Copyright and Related Rights in the Work or (ii) assert any associated claims -and causes of action with respect to the Work, in either case contrary to -Affirmer's express Statement of Purpose. - -4. Limitations and Disclaimers. - - a. No trademark or patent rights held by Affirmer are waived, abandoned, - surrendered, licensed or otherwise affected by this document. - - b. Affirmer offers the Work as-is and makes no representations or warranties - of any kind concerning the Work, express, implied, statutory or otherwise, - including without limitation warranties of title, merchantability, fitness - for a particular purpose, non infringement, or the absence of latent or - other defects, accuracy, or the present or absence of errors, whether or not - discoverable, all to the greatest extent permissible under applicable law. - - c. Affirmer disclaims responsibility for clearing rights of other persons - that may apply to the Work or any use thereof, including without limitation - any person's Copyright and Related Rights in the Work. Further, Affirmer - disclaims responsibility for obtaining any necessary consents, permissions - or other rights required for any use of the Work. - - d. Affirmer understands and acknowledges that Creative Commons is not a - party to this document and has no duty or obligation with respect to this - CC0 or use of the Work. - -For more information, please see - diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_avx2/address.c b/src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_avx2/address.c deleted file mode 100644 index 56c88ce99d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_avx2/address.c +++ /dev/null @@ -1,78 +0,0 @@ -#include - -#include "address.h" -#include "params.h" -#include "utils.h" - -void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]) { - int i; - - for (i = 0; i < 8; i++) { - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_ull_to_bytes( - bytes + i * 4, 4, addr[i]); - } -} - -void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_set_layer_addr( - uint32_t addr[8], uint32_t layer) { - addr[0] = layer; -} - -void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_set_tree_addr( - uint32_t addr[8], uint64_t tree) { - addr[1] = 0; - addr[2] = (uint32_t) (tree >> 32); - addr[3] = (uint32_t) tree; -} - -void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_set_type( - uint32_t addr[8], uint32_t type) { - addr[4] = type; -} - -void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; -} - -/* These functions are used for OTS addresses. */ - -void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_set_keypair_addr( - uint32_t addr[8], uint32_t keypair) { - addr[5] = keypair; -} - -void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; - out[5] = in[5]; -} - -void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_set_chain_addr( - uint32_t addr[8], uint32_t chain) { - addr[6] = chain; -} - -void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_set_hash_addr( - uint32_t addr[8], uint32_t hash) { - addr[7] = hash; -} - -/* These functions are used for all hash tree addresses (including FORS). */ - -void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_set_tree_height( - uint32_t addr[8], uint32_t tree_height) { - addr[6] = tree_height; -} - -void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_set_tree_index( - uint32_t addr[8], uint32_t tree_index) { - addr[7] = tree_index; -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_avx2/address.h b/src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_avx2/address.h deleted file mode 100644 index 530575d281..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_avx2/address.h +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_ADDRESS_H -#define PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_ADDRESS_H - -#include - -#define PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_ADDR_TYPE_WOTS 0 -#define PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_ADDR_TYPE_WOTSPK 1 -#define PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_ADDR_TYPE_HASHTREE 2 -#define PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_ADDR_TYPE_FORSTREE 3 -#define PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_ADDR_TYPE_FORSPK 4 - -void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]); - -void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_set_layer_addr( - uint32_t addr[8], uint32_t layer); - -void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_set_tree_addr( - uint32_t addr[8], uint64_t tree); - -void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_set_type( - uint32_t addr[8], uint32_t type); - -/* Copies the layer and tree part of one address into the other */ -void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for WOTS and FORS addresses. */ - -void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_set_keypair_addr( - uint32_t addr[8], uint32_t keypair); - -void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_set_chain_addr( - uint32_t addr[8], uint32_t chain); - -void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_set_hash_addr( - uint32_t addr[8], uint32_t hash); - -void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for all hash tree addresses (including FORS). */ - -void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_set_tree_height( - uint32_t addr[8], uint32_t tree_height); - -void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_set_tree_index( - uint32_t addr[8], uint32_t tree_index); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_avx2/api.h b/src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_avx2/api.h deleted file mode 100644 index 1e82f99889..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_avx2/api.h +++ /dev/null @@ -1,81 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_API_H -#define PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_API_H - -#include -#include - - - -#define PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_CRYPTO_ALGNAME "SPHINCS+" - -#define PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_CRYPTO_SECRETKEYBYTES 128 -#define PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_CRYPTO_PUBLICKEYBYTES 64 -#define PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_CRYPTO_BYTES 49856 -#define PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_CRYPTO_SEEDBYTES 96 - - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_avx2/fors.c b/src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_avx2/fors.c deleted file mode 100644 index 4621bef6c1..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_avx2/fors.c +++ /dev/null @@ -1,206 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "fors.h" -#include "hash.h" -#include "hashx4.h" -#include "thash.h" -#include "thashx4.h" -#include "utils.h" -#include "utilsx4.h" - -static void fors_gen_skx4(unsigned char *sk0, - unsigned char *sk1, - unsigned char *sk2, - unsigned char *sk3, const unsigned char *sk_seed, - uint32_t fors_leaf_addrx4[4 * 8], - const hash_state *state_seeded) { - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_prf_addrx4(sk0, sk1, sk2, sk3, sk_seed, fors_leaf_addrx4, state_seeded); -} - -static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, - const unsigned char *pub_seed, - uint32_t fors_leaf_addr[8], const hash_state *state_seeded) { - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_thash_1(leaf, sk, pub_seed, fors_leaf_addr, state_seeded); -} - -static void fors_sk_to_leafx4(unsigned char *leaf0, - unsigned char *leaf1, - unsigned char *leaf2, - unsigned char *leaf3, - const unsigned char *sk0, - const unsigned char *sk1, - const unsigned char *sk2, - const unsigned char *sk3, - const unsigned char *pub_seed, - uint32_t fors_leaf_addrx4[4 * 8], - const hash_state *state_seeded) { - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_thashx4_1(leaf0, leaf1, leaf2, leaf3, - sk0, sk1, sk2, sk3, pub_seed, fors_leaf_addrx4, state_seeded); -} - -static void fors_gen_leafx4(unsigned char *leaf0, - unsigned char *leaf1, - unsigned char *leaf2, - unsigned char *leaf3, - const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx0, - uint32_t addr_idx1, - uint32_t addr_idx2, - uint32_t addr_idx3, - const uint32_t fors_tree_addr[8], - const hash_state *state_seeded) { - uint32_t fors_leaf_addrx4[4 * 8] = {0}; - unsigned int j; - - /* Only copy the parts that must be kept in fors_leaf_addrx4. */ - for (j = 0; j < 4; j++) { - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_copy_keypair_addr(fors_leaf_addrx4 + j * 8, fors_tree_addr); - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_set_type(fors_leaf_addrx4 + j * 8, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_ADDR_TYPE_FORSTREE); - } - - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_set_tree_index(fors_leaf_addrx4 + 0 * 8, addr_idx0); - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_set_tree_index(fors_leaf_addrx4 + 1 * 8, addr_idx1); - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_set_tree_index(fors_leaf_addrx4 + 2 * 8, addr_idx2); - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_set_tree_index(fors_leaf_addrx4 + 3 * 8, addr_idx3); - - fors_gen_skx4(leaf0, leaf1, leaf2, leaf3, sk_seed, fors_leaf_addrx4, state_seeded); - fors_sk_to_leafx4(leaf0, leaf1, leaf2, leaf3, - leaf0, leaf1, leaf2, leaf3, pub_seed, fors_leaf_addrx4, state_seeded); -} - -/** - * Interprets m as PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_FORS_HEIGHT-bit unsigned integers. - * Assumes m contains at least PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_FORS_TREES bits. - * Assumes indices has space for PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_FORS_TREES integers. - */ -static void message_to_indices(uint32_t *indices, const unsigned char *m) { - unsigned int i, j; - unsigned int offset = 0; - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_FORS_TREES; i++) { - indices[i] = 0; - for (j = 0; j < PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_FORS_HEIGHT; j++) { - indices[i] ^= (((uint32_t)m[offset >> 3] >> (offset & 0x7)) & 0x1) << j; - offset++; - } - } -} - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *state_seeded) { - /* Round up to multiple of 4 to prevent out-of-bounds for x4 parallelism */ - uint32_t indices[(PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_FORS_TREES + 3) & ~3] = {0}; - unsigned char roots[((PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_FORS_TREES + 3) & ~3) * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N]; - /* Sign to a buffer, since we may not have a nice multiple of 4 and would - otherwise overrun the signature. */ - unsigned char sigbufx4[4 * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N * (1 + PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_FORS_HEIGHT)]; - uint32_t fors_tree_addrx4[4 * 8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset[4] = {0}; - unsigned int i, j; - - for (j = 0; j < 4; j++) { - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_copy_keypair_addr(fors_tree_addrx4 + j * 8, fors_addr); - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_set_type(fors_tree_addrx4 + j * 8, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_ADDR_TYPE_FORSTREE); - } - - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_copy_keypair_addr(fors_pk_addr, fors_addr); - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_set_type(fors_pk_addr, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < ((PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_FORS_TREES + 3) & ~0x3); i += 4) { - for (j = 0; j < 4; j++) { - if (i + j < PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_FORS_TREES) { - idx_offset[j] = (i + j) * (1 << PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_FORS_HEIGHT); - - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_set_tree_height(fors_tree_addrx4 + j * 8, 0); - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_set_tree_index(fors_tree_addrx4 + j * 8, - indices[i + j] + idx_offset[j]); - } - } - - /* Include the secret key part that produces the selected leaf nodes. */ - fors_gen_skx4(sigbufx4 + 0 * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N, - sigbufx4 + 1 * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N, - sigbufx4 + 2 * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N, - sigbufx4 + 3 * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N, - sk_seed, fors_tree_addrx4, state_seeded); - - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_treehashx4_FORS_HEIGHT(roots + i * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N, sigbufx4 + 4 * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N, sk_seed, pub_seed, - &indices[i], idx_offset, fors_gen_leafx4, fors_tree_addrx4, - state_seeded); - - for (j = 0; j < 4; j++) { - if (i + j < PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_FORS_TREES) { - memcpy(sig, sigbufx4 + j * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N); - memcpy(sig + PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N, - sigbufx4 + 4 * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N + j * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_FORS_HEIGHT, - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_FORS_HEIGHT); - sig += PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N * (1 + PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_FORS_HEIGHT); - } - } - } - - /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_thash_FORS_TREES(pk, roots, pub_seed, fors_pk_addr, state_seeded); -} - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, - const uint32_t fors_addr[8], - const hash_state *state_seeded) { - uint32_t indices[PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_FORS_TREES]; - unsigned char roots[PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_FORS_TREES * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N]; - unsigned char leaf[PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N]; - uint32_t fors_tree_addr[8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_copy_keypair_addr(fors_tree_addr, fors_addr); - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_copy_keypair_addr(fors_pk_addr, fors_addr); - - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_set_type(fors_tree_addr, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_set_type(fors_pk_addr, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_FORS_TREES; i++) { - idx_offset = i * (1 << PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_FORS_HEIGHT); - - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_set_tree_height(fors_tree_addr, 0); - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Derive the leaf from the included secret key part. */ - fors_sk_to_leaf(leaf, sig, pub_seed, fors_tree_addr, state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N; - - /* Derive the corresponding root node of this tree. */ - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_compute_root(roots + i * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N, leaf, indices[i], idx_offset, - sig, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_FORS_HEIGHT, pub_seed, fors_tree_addr, - state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_thash_FORS_TREES(pk, roots, pub_seed, fors_pk_addr, state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_avx2/fors.h b/src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_avx2/fors.h deleted file mode 100644 index 6159e0f1e7..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_avx2/fors.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_FORS_H -#define PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_FORS_H - -#include - -#include "hash_state.h" -#include "params.h" - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_fors_sign( - unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *hash_state_seeded); - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_fors_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, const uint32_t fors_addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_avx2/hash.h b/src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_avx2/hash.h deleted file mode 100644 index 5c46abaca4..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_avx2/hash.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_HASH_H -#define PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_HASH_H - -#include "hash_state.h" - -#include -#include - -void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_initialize_hash_function( - hash_state *hash_state_seeded, - const unsigned char *pub_seed, const unsigned char *sk_seed); - -void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_destroy_hash_function(hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_avx2/hash_shake256.c b/src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_avx2/hash_shake256.c deleted file mode 100644 index 58e27a8727..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_avx2/hash_shake256.c +++ /dev/null @@ -1,106 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "utils.h" - -#include "fips202.h" - -/* For SHAKE256, there is no immediate reason to initialize at the start, - so this function is an empty operation. */ -void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_initialize_hash_function( - hash_state *hash_state_seeded, // NOLINT(readability-non-const-parameter) - const unsigned char *pub_seed, const unsigned char *sk_seed) { - (void)hash_state_seeded; /* Suppress an 'unused parameter' warning. */ - (void)pub_seed; /* Suppress an 'unused parameter' warning. */ - (void)sk_seed; /* Suppress an 'unused parameter' warning. */ -} - -/* This is not necessary for SHAKE256, so we don't do anything */ -void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_destroy_hash_function( - hash_state *hash_state_seeded) { // NOLINT(readability-non-const-parameter) - (void)hash_state_seeded; -} - -/* - * Computes PRF(key, addr), given a secret key of PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N bytes and an address - */ -void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded) { - unsigned char buf[PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_ADDR_BYTES]; - - memcpy(buf, key, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N); - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_addr_to_bytes(buf + PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N, addr); - - shake256(out, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N, buf, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_ADDR_BYTES); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} - -/** - * Computes the message-dependent randomness R, using a secret seed and an - * optional randomization value as well as the message. - */ -void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded) { - shake256incctx state; - - shake256_inc_init(&state); - shake256_inc_absorb(&state, sk_prf, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N); - shake256_inc_absorb(&state, optrand, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N); - shake256_inc_absorb(&state, m, mlen); - shake256_inc_finalize(&state); - shake256_inc_squeeze(R, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N, &state); - shake256_inc_ctx_release(&state); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} - -/** - * Computes the message hash using R, the public key, and the message. - * Outputs the message digest and the index of the leaf. The index is split in - * the tree index and the leaf index, for convenient copying to an address. - */ -void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded) { -#define PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_TREE_BITS (PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_TREE_HEIGHT * (PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_D - 1)) -#define PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_TREE_BYTES ((PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_TREE_BITS + 7) / 8) -#define PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_LEAF_BITS PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_TREE_HEIGHT -#define PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_LEAF_BYTES ((PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_LEAF_BITS + 7) / 8) -#define PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_DGST_BYTES (PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_FORS_MSG_BYTES + PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_TREE_BYTES + PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_LEAF_BYTES) - - unsigned char buf[PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_DGST_BYTES]; - unsigned char *bufp = buf; - shake256incctx state; - - shake256_inc_init(&state); - shake256_inc_absorb(&state, R, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N); - shake256_inc_absorb(&state, pk, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_PK_BYTES); - shake256_inc_absorb(&state, m, mlen); - shake256_inc_finalize(&state); - shake256_inc_squeeze(buf, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_DGST_BYTES, &state); - shake256_inc_ctx_release(&state); - - memcpy(digest, bufp, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_FORS_MSG_BYTES); - bufp += PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_FORS_MSG_BYTES; - - *tree = PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_bytes_to_ull( - bufp, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_TREE_BYTES); - *tree &= (~(uint64_t)0) >> (64 - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_TREE_BITS); - bufp += PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_TREE_BYTES; - - *leaf_idx = (uint32_t)PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_bytes_to_ull( - bufp, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_LEAF_BYTES); - *leaf_idx &= (~(uint32_t)0) >> (32 - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_LEAF_BITS); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_avx2/hash_shake256x4.c b/src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_avx2/hash_shake256x4.c deleted file mode 100644 index 1ae12df30a..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_avx2/hash_shake256x4.c +++ /dev/null @@ -1,38 +0,0 @@ -#include -#include - -#include "address.h" -#include "fips202x4.h" -#include "hashx4.h" -#include "params.h" - -/* - * 4-way parallel version of prf_addr; takes 4x as much input and output - */ -void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_prf_addrx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const unsigned char *key, - const uint32_t addrx4[4 * 8], - const hash_state *state_seeded) { - unsigned char bufx4[4 * (PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_ADDR_BYTES)]; - unsigned int j; - - for (j = 0; j < 4; j++) { - memcpy(bufx4 + j * (PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_ADDR_BYTES), key, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N); - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_addr_to_bytes(bufx4 + PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N + j * (PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_ADDR_BYTES), addrx4 + j * 8); - } - - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_shake256x4(out0, - out1, - out2, - out3, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N, - bufx4 + 0 * (PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_ADDR_BYTES), - bufx4 + 1 * (PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_ADDR_BYTES), - bufx4 + 2 * (PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_ADDR_BYTES), - bufx4 + 3 * (PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_ADDR_BYTES), PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_ADDR_BYTES); - - /* Avoid unused parameter warning */ - (void)state_seeded; -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_avx2/hash_state.h b/src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_avx2/hash_state.h deleted file mode 100644 index 180de8077c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_avx2/hash_state.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_HASH_STATE_H -#define PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_HASH_STATE_H - -/** - * Defines the type of the hash function state. - * - * Don't be fooled into thinking this instance of SPHINCS+ isn't stateless! - * - * From Section 7.2.2 from the SPHINCS+ round-2 specification: - * - * Each of the instances of the tweakable hash function take PK.seed as its - * first input, which is constant for a given key pair – and, thus, across - * a single signature. This leads to a lot of redundant computation. To remedy - * this, we pad PK.seed to the length of a full 64-byte SHA-256 input block. - * Because of the Merkle-Damgård construction that underlies SHA-256, this - * allows for reuse of the intermediate SHA-256 state after the initial call to - * the compression function which improves performance. - * - * We pass this hash state around in functions, because otherwise we need to - * have a global variable. - * - * SHAKE256 does not need this state. Because this implementation is generated - * from a shared code base, we still need to specify some hash_state as it is - * still passed around. We chose to use an `int` as a placeholder for this - * purpose. - */ - -typedef int hash_state; - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_avx2/hashx4.h b/src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_avx2/hashx4.h deleted file mode 100644 index 557f113138..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_avx2/hashx4.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_HASHX4_H -#define PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_HASHX4_H - -#include - -#include "hash_state.h" - -void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_prf_addrx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const unsigned char *key, - const uint32_t addrx4[4 * 8], - const hash_state *state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_avx2/params.h b/src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_avx2/params.h deleted file mode 100644 index 7aab103a35..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_avx2/params.h +++ /dev/null @@ -1,53 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_PARAMS_H -#define PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_PARAMS_H - -/* Hash output length in bytes. */ -#define PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N 32 -/* Height of the hypertree. */ -#define PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_FULL_HEIGHT 68 -/* Number of subtree layer. */ -#define PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_D 17 -/* FORS tree dimensions. */ -#define PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_FORS_HEIGHT 9 -#define PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_FORS_TREES 35 -/* Winternitz parameter, */ -#define PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_WOTS_W 16 - -/* The hash function is defined by linking a different hash.c file, as opposed - to setting a #define constant. */ - -/* For clarity */ -#define PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_ADDR_BYTES 32 - -/* WOTS parameters. */ -#define PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_WOTS_LOGW 4 - -#define PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_WOTS_LEN1 (8 * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N / PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_WOTS_LOGW) - -/* PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#define PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_WOTS_LEN2 3 - -#define PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_WOTS_LEN (PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_WOTS_LEN1 + PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_WOTS_LEN2) -#define PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_WOTS_BYTES (PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_WOTS_LEN * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N) -#define PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_WOTS_PK_BYTES PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_WOTS_BYTES - -/* Subtree size. */ -#define PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_TREE_HEIGHT (PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_FULL_HEIGHT / PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_D) - -/* FORS parameters. */ -#define PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_FORS_MSG_BYTES ((PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_FORS_TREES + 7) / 8) -#define PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_FORS_BYTES ((PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_FORS_HEIGHT + 1) * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_FORS_TREES * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N) -#define PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_FORS_PK_BYTES PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N - -/* Resulting SPX sizes. */ -#define PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_BYTES (PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_FORS_BYTES + PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_D * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_WOTS_BYTES +\ - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_FULL_HEIGHT * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N) -#define PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_PK_BYTES (2 * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N) -#define PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_SK_BYTES (2 * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_PK_BYTES) - -/* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ -#define PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_OPTRAND_BYTES 32 - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_avx2/sign.c b/src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_avx2/sign.c deleted file mode 100644 index 7cc68e7c20..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_avx2/sign.c +++ /dev/null @@ -1,409 +0,0 @@ -#include -#include -#include -#include - -#include "address.h" -#include "api.h" -#include "fors.h" -#include "hash.h" -#include "hash_state.h" -#include "params.h" -#include "randombytes.h" -#include "thash.h" -#include "utils.h" -#include "wots.h" - - -/** - * Computes the leaf at a given address. First generates the WOTS key pair, - * then computes leaf by hashing horizontally. - */ -static void wots_gen_leaf(unsigned char *leaf, const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx, const uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - unsigned char pk[PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_WOTS_BYTES]; - uint32_t wots_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_set_type( - wots_addr, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_set_type( - wots_pk_addr, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_ADDR_TYPE_WOTSPK); - - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_set_keypair_addr( - wots_addr, addr_idx); - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_wots_gen_pk( - pk, sk_seed, pub_seed, wots_addr, hash_state_seeded); - - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_copy_keypair_addr( - wots_pk_addr, wots_addr); - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_thash_WOTS_LEN( - leaf, pk, pub_seed, wots_pk_addr, hash_state_seeded); -} - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_crypto_sign_secretkeybytes(void) { - return PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_CRYPTO_SECRETKEYBYTES; -} - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_crypto_sign_publickeybytes(void) { - return PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_CRYPTO_PUBLICKEYBYTES; -} - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_crypto_sign_bytes(void) { - return PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_CRYPTO_BYTES; -} - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_crypto_sign_seedbytes(void) { - return PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_CRYPTO_SEEDBYTES; -} - -/* - * Generates an SPX key pair given a seed of length - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed) { - /* We do not need the auth path in key generation, but it simplifies the - code to have just one treehash routine that computes both root and path - in one function. */ - unsigned char auth_path[PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_TREE_HEIGHT * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N]; - uint32_t top_tree_addr[8] = {0}; - hash_state hash_state_seeded; - - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_set_layer_addr( - top_tree_addr, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_D - 1); - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_set_type( - top_tree_addr, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_ADDR_TYPE_HASHTREE); - - /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ - memcpy(sk, seed, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_CRYPTO_SEEDBYTES); - - memcpy(pk, sk + 2 * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_initialize_hash_function(&hash_state_seeded, pk, sk); - - /* Compute root node of the top-most subtree. */ - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_treehash_TREE_HEIGHT( - sk + 3 * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N, auth_path, sk, sk + 2 * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N, 0, 0, - wots_gen_leaf, top_tree_addr, &hash_state_seeded); - - memcpy(pk + PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N, sk + 3 * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N); - - return 0; -} - -/* - * Generates an SPX key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk) { - - // guarantee alignment of pk - union { - __m128 _x[PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_CRYPTO_PUBLICKEYBYTES / 16]; - uint8_t pk[PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_CRYPTO_PUBLICKEYBYTES]; - } aligned_pk; - - // guarantee alignment of sk - union { - __m128 _x[PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_CRYPTO_SECRETKEYBYTES / 16]; - uint8_t sk[PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_CRYPTO_SECRETKEYBYTES]; - } aligned_sk; - - union { - __m128 _x[PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_CRYPTO_SEEDBYTES / 16]; - uint8_t seed[PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_CRYPTO_SEEDBYTES]; - } aligned_seed; - randombytes(aligned_seed.seed, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_CRYPTO_SEEDBYTES); - - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_crypto_sign_seed_keypair( - aligned_pk.pk, aligned_sk.sk, aligned_seed.seed); - memcpy(pk, aligned_pk.pk, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_CRYPTO_PUBLICKEYBYTES); - memcpy(sk, aligned_sk.sk, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_CRYPTO_SECRETKEYBYTES); - - return 0; -} - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - // guarantee alignment of sk - union { - __m128 *_x; - uint8_t sk[PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_CRYPTO_SECRETKEYBYTES]; - } aligned_sk; - memcpy(aligned_sk.sk, sk, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_CRYPTO_SECRETKEYBYTES); - sk = aligned_sk.sk; - - // guarantee alignment of sig - union { - __m128 *_x; - uint8_t sig[PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_BYTES]; - } aligned_sig; - uint8_t *orig_sig = sig; - sig = (uint8_t *)aligned_sig.sig; - - const unsigned char *sk_seed = sk; - const unsigned char *sk_prf = sk + PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N; - const unsigned char *pk = sk + 2 * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N; - const unsigned char *pub_seed = pk; - - unsigned char optrand[PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N]; - unsigned char mhash[PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_FORS_MSG_BYTES]; - unsigned char root[PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N]; - uint32_t i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - - hash_state hash_state_seeded; - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_initialize_hash_function( - &hash_state_seeded, - pub_seed, sk_seed); - - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_set_type( - wots_addr, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_set_type( - tree_addr, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_ADDR_TYPE_HASHTREE); - - /* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ - randombytes(optrand, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N); - /* Compute the digest randomization value. */ - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_gen_message_random( - sig, sk_prf, optrand, m, mlen, &hash_state_seeded); - - /* Derive the message digest and leaf index from R, PK and M. */ - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N; - - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_set_keypair_addr( - wots_addr, idx_leaf); - - /* Sign the message hash using FORS. */ - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_fors_sign( - sig, root, mhash, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_FORS_BYTES; - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_D; i++) { - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_set_tree_addr(tree_addr, tree); - - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_set_keypair_addr( - wots_addr, idx_leaf); - - /* Compute a WOTS signature. */ - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_wots_sign( - sig, root, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_WOTS_BYTES; - - /* Compute the authentication path for the used WOTS leaf. */ - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_treehash_TREE_HEIGHT( - root, sig, sk_seed, pub_seed, idx_leaf, 0, - wots_gen_leaf, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_TREE_HEIGHT * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_TREE_HEIGHT; - } - - memcpy(orig_sig, aligned_sig.sig, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_BYTES); - *siglen = PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_BYTES; - - return 0; -} - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk) { - // guarantee alignment of pk - union { - __m128 *_x; - uint8_t pk[PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_CRYPTO_PUBLICKEYBYTES]; - } aligned_pk; - memcpy(aligned_pk.pk, pk, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_CRYPTO_PUBLICKEYBYTES); - pk = aligned_pk.pk; - - const unsigned char *pub_seed = pk; - const unsigned char *pub_root = pk + PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N; - unsigned char mhash[PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_FORS_MSG_BYTES]; - unsigned char wots_pk[PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_WOTS_BYTES]; - unsigned char root[PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N]; - unsigned char leaf[PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N]; - unsigned int i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - hash_state hash_state_seeded; - - if (siglen != PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_BYTES) { - return -1; - } - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_initialize_hash_function( - &hash_state_seeded, - pub_seed, NULL); - - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_set_type( - wots_addr, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_set_type( - tree_addr, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_ADDR_TYPE_HASHTREE); - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_set_type( - wots_pk_addr, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_ADDR_TYPE_WOTSPK); - - /* Derive the message digest and leaf index from R || PK || M. */ - /* The additional PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N is a result of the hash domain separator. */ - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N; - - /* Layer correctly defaults to 0, so no need to set_layer_addr */ - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_set_keypair_addr( - wots_addr, idx_leaf); - - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_fors_pk_from_sig( - root, sig, mhash, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_FORS_BYTES; - - /* For each subtree.. */ - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_D; i++) { - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_set_tree_addr(tree_addr, tree); - - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_set_keypair_addr( - wots_addr, idx_leaf); - - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_copy_keypair_addr( - wots_pk_addr, wots_addr); - - /* The WOTS public key is only correct if the signature was correct. */ - /* Initially, root is the FORS pk, but on subsequent iterations it is - the root of the subtree below the currently processed subtree. */ - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_wots_pk_from_sig( - wots_pk, sig, root, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_WOTS_BYTES; - - /* Compute the leaf node using the WOTS public key. */ - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_thash_WOTS_LEN( - leaf, wots_pk, pub_seed, wots_pk_addr, &hash_state_seeded); - - /* Compute the root node of this subtree. */ - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_compute_root( - root, leaf, idx_leaf, 0, sig, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_TREE_HEIGHT, - pub_seed, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_TREE_HEIGHT * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_TREE_HEIGHT; - } - - /* Check if the root node equals the root node in the public key. */ - if (memcmp(root, pub_root, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N) != 0) { - return -1; - } - - return 0; -} - - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - size_t siglen; - - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_crypto_sign_signature( - sm, &siglen, m, mlen, sk); - - memmove(sm + PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_BYTES, m, mlen); - *smlen = siglen + mlen; - - return 0; -} - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk) { - - // guarantee alignment of pk - union { - __m128 *_x; - uint8_t pk[PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_CRYPTO_PUBLICKEYBYTES]; - } aligned_pk; - memcpy(aligned_pk.pk, pk, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_CRYPTO_PUBLICKEYBYTES); - pk = aligned_pk.pk; - - - /* The API caller does not necessarily know what size a signature should be - but SPHINCS+ signatures are always exactly PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_BYTES. */ - if (smlen < PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_BYTES) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - *mlen = smlen - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_BYTES; - - if (PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_crypto_sign_verify( - sm, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_BYTES, sm + PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_BYTES, *mlen, pk)) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - /* If verification was successful, move the message to the right place. */ - memmove(m, sm + PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_BYTES, *mlen); - - return 0; -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_avx2/thash.h b/src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_avx2/thash.h deleted file mode 100644 index cadd0a4ebf..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_avx2/thash.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_THASH_H -#define PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_THASH_H - -#include "hash_state.h" - -#include - -void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_avx2/thash_shake256_simple.c b/src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_avx2/thash_shake256_simple.c deleted file mode 100644 index 59987e6d98..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_avx2/thash_shake256_simple.c +++ /dev/null @@ -1,74 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash_state.h" -#include "params.h" -#include "thash.h" - -#include "fips202.h" - -/** - * Takes an array of inblocks concatenated arrays of PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N bytes. - */ -static void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_thash( - unsigned char *out, unsigned char *buf, - const unsigned char *in, unsigned int inblocks, - const unsigned char *pub_seed, uint32_t addr[8]) { - - memcpy(buf, pub_seed, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N); - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_addr_to_bytes(buf + PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N, addr); - memcpy(buf + PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_ADDR_BYTES, in, inblocks * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N); - - shake256(out, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N, buf, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N); -} - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_ADDR_BYTES + 1 * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N]; - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_thash( - out, buf, in, 1, pub_seed, addr); - - (void)hash_state_seeded; /* Avoid unused parameter warning. */ -} - -void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_ADDR_BYTES + 2 * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N]; - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_thash( - out, buf, in, 2, pub_seed, addr); - - (void)hash_state_seeded; /* Avoid unused parameter warning. */ -} - -void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_ADDR_BYTES + PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_WOTS_LEN * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N]; - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_thash( - out, buf, in, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_WOTS_LEN, pub_seed, addr); - - (void)hash_state_seeded; /* Avoid unused parameter warning. */ -} - -void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_ADDR_BYTES + PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_FORS_TREES * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N]; - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_thash( - out, buf, in, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_FORS_TREES, pub_seed, addr); - - (void)hash_state_seeded; /* Avoid unused parameter warning. */ -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_avx2/thash_shake256_simplex4.c b/src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_avx2/thash_shake256_simplex4.c deleted file mode 100644 index 4335851820..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_avx2/thash_shake256_simplex4.c +++ /dev/null @@ -1,47 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "thashx4.h" - -#include "fips202x4.h" - -/** - * 4-way parallel version of thash; takes 4x as much input and output - */ -#define thashx4_variant(name, inblocks) \ - void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_thashx4_##name( \ - unsigned char *out0, unsigned char *out1, unsigned char *out2, unsigned char *out3, \ - const unsigned char *in0, const unsigned char *in1, const unsigned char *in2, \ - const unsigned char *in3, const unsigned char *pub_seed, uint32_t addrx4[4 * 8], \ - const hash_state *state_seeded) { \ - unsigned char buf0[PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_ADDR_BYTES + (inblocks)*PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N]; \ - unsigned char buf1[PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_ADDR_BYTES + (inblocks)*PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N]; \ - unsigned char buf2[PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_ADDR_BYTES + (inblocks)*PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N]; \ - unsigned char buf3[PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_ADDR_BYTES + (inblocks)*PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N]; \ - \ - memcpy(buf0, pub_seed, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N); \ - memcpy(buf1, pub_seed, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N); \ - memcpy(buf2, pub_seed, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N); \ - memcpy(buf3, pub_seed, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N); \ - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_addr_to_bytes(buf0 + PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N, addrx4 + 0 * 8); \ - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_addr_to_bytes(buf1 + PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N, addrx4 + 1 * 8); \ - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_addr_to_bytes(buf2 + PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N, addrx4 + 2 * 8); \ - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_addr_to_bytes(buf3 + PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N, addrx4 + 3 * 8); \ - memcpy(buf0 + PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_ADDR_BYTES, in0, (inblocks)*PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N); \ - memcpy(buf1 + PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_ADDR_BYTES, in1, (inblocks)*PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N); \ - memcpy(buf2 + PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_ADDR_BYTES, in2, (inblocks)*PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N); \ - memcpy(buf3 + PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_ADDR_BYTES, in3, (inblocks)*PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N); \ - \ - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_shake256x4(out0, out1, out2, out3, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N, buf0, buf1, buf2, buf3, \ - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_ADDR_BYTES + (inblocks)*PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N); \ - \ - /* Avoid unused parameter warning */ \ - (void)state_seeded; \ - } - -thashx4_variant(1, 1) -thashx4_variant(2, 2) -thashx4_variant(WOTS_LEN, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_WOTS_LEN) -thashx4_variant(FORS_TREES, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_FORS_TREES) diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_avx2/thashx4.h b/src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_avx2/thashx4.h deleted file mode 100644 index 58a5b98180..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_avx2/thashx4.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_THASHX4_H -#define PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_THASHX4_H - -#include - -#include "hash_state.h" - -#define thashx4_header(inblocks) \ - void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_thashx4_##inblocks(unsigned char *out0, \ - unsigned char *out1, \ - unsigned char *out2, \ - unsigned char *out3, \ - const unsigned char *in0, \ - const unsigned char *in1, \ - const unsigned char *in2, \ - const unsigned char *in3, \ - const unsigned char *pub_seed, uint32_t addrx4[4*8], \ - const hash_state *state_seeded) - -thashx4_header(1); -thashx4_header(2); -thashx4_header(WOTS_LEN); -thashx4_header(FORS_TREES); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_avx2/utils.c b/src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_avx2/utils.c deleted file mode 100644 index 479907c204..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_avx2/utils.c +++ /dev/null @@ -1,199 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "hash_state.h" -#include "params.h" -#include "thash.h" -#include "utils.h" - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in) { - - /* Iterate over out in decreasing order, for big-endianness. */ - for (size_t i = outlen; i > 0; i--) { - out[i - 1] = in & 0xff; - in = in >> 8; - } -} - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_bytes_to_ull( - const unsigned char *in, size_t inlen) { - unsigned long long retval = 0; - - for (size_t i = 0; i < inlen; i++) { - retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); - } - return retval; -} - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - uint32_t i; - unsigned char buffer[2 * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N]; - - /* If leaf_idx is odd (last bit = 1), current path element is a right child - and auth_path has to go left. Otherwise it is the other way around. */ - if (leaf_idx & 1) { - memcpy(buffer + PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N, leaf, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N); - } else { - memcpy(buffer, leaf, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N); - memcpy(buffer + PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N, auth_path, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N); - } - auth_path += PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N; - - for (i = 0; i < tree_height - 1; i++) { - leaf_idx >>= 1; - idx_offset >>= 1; - /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_set_tree_height(addr, i + 1); - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_set_tree_index( - addr, leaf_idx + idx_offset); - - /* Pick the right or left neighbor, depending on parity of the node. */ - if (leaf_idx & 1) { - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_thash_2( - buffer + PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N); - } else { - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_thash_2( - buffer, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer + PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N, auth_path, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N); - } - auth_path += PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N; - } - - /* The last iteration is exceptional; we do not copy an auth_path node. */ - leaf_idx >>= 1; - idx_offset >>= 1; - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_set_tree_height(addr, tree_height); - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_set_tree_index( - addr, leaf_idx + idx_offset); - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_thash_2( - root, buffer, pub_seed, addr, hash_state_seeded); -} - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -static void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_treehash( - unsigned char *root, unsigned char *auth_path, - unsigned char *stack, unsigned int *heights, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - - unsigned int offset = 0; - uint32_t idx; - uint32_t tree_idx; - - for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { - /* Add the next leaf node to the stack. */ - gen_leaf(stack + offset * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N, - sk_seed, pub_seed, idx + idx_offset, tree_addr, - hash_state_seeded); - offset++; - heights[offset - 1] = 0; - - /* If this is a node we need for the auth path.. */ - if ((leaf_idx ^ 0x1) == idx) { - memcpy(auth_path, stack + (offset - 1)*PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N); - } - - /* While the top-most nodes are of equal height.. */ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { - /* Compute index of the new node, in the next layer. */ - tree_idx = (idx >> (heights[offset - 1] + 1)); - - /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_set_tree_height( - tree_addr, heights[offset - 1] + 1); - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_set_tree_index( - tree_addr, tree_idx + (idx_offset >> (heights[offset - 1] + 1))); - /* Hash the top-most nodes from the stack together. */ - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_thash_2( - stack + (offset - 2)*PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N, stack + (offset - 2)*PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N, - pub_seed, tree_addr, hash_state_seeded); - offset--; - /* Note that the top-most node is now one layer higher. */ - heights[offset - 1]++; - - /* If this is a node we need for the auth path.. */ - if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_path + heights[offset - 1]*PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N, - stack + (offset - 1)*PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N); - } - } - } - memcpy(root, stack, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N); -} - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_FORS_HEIGHT + 1)*PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N]; - unsigned int heights[PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_FORS_HEIGHT + 1]; - - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_FORS_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_TREE_HEIGHT + 1)*PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N]; - unsigned int heights[PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_TREE_HEIGHT + 1]; - - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_TREE_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_avx2/utils.h b/src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_avx2/utils.h deleted file mode 100644 index 52afc75237..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_avx2/utils.h +++ /dev/null @@ -1,64 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_UTILS_H -#define PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_UTILS_H - -#include "hash_state.h" -#include "params.h" -#include -#include - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in); - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_bytes_to_ull( - const unsigned char *in, size_t inlen); - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_avx2/utilsx4.c b/src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_avx2/utilsx4.c deleted file mode 100644 index 5e4fb6065f..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_avx2/utilsx4.c +++ /dev/null @@ -1,98 +0,0 @@ -#include "address.h" -#include "params.h" -#include "thashx4.h" -#include "utils.h" -#include "utilsx4.h" - -#include - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -#define treehashx4_variant(name, tree_height) \ - void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_treehashx4_##name( \ - unsigned char *rootx4, unsigned char *auth_pathx4, const unsigned char *sk_seed, \ - const unsigned char *pub_seed, const uint32_t leaf_idx[4], uint32_t idx_offset[4], \ - void (*gen_leafx4)(unsigned char * /* leaf0 */, unsigned char * /* leaf1 */, \ - unsigned char * /* leaf2 */, unsigned char * /* leaf3 */, \ - const unsigned char * /* sk_seed */, \ - const unsigned char * /* pub_seed */, uint32_t /* addr_idx0 */, \ - uint32_t /* addr_idx1 */, uint32_t /* addr_idx2 */, \ - uint32_t /* addr_idx3 */, const uint32_t[8] /* tree_addr */, \ - const hash_state * /* state_seeded */), \ - uint32_t tree_addrx4[4 * 8], const hash_state *state_seeded) { \ - unsigned char stackx4[4 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N]; \ - unsigned int heights[(tree_height) + 1]; \ - unsigned int offset = 0; \ - uint32_t idx; \ - uint32_t tree_idx; \ - unsigned int j; \ - \ - for (idx = 0; idx < (uint32_t)(1 << (tree_height)); idx++) { \ - /* Add the next leaf node to the stack. */ \ - gen_leafx4(stackx4 + 0 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N + offset * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N, \ - stackx4 + 1 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N + offset * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N, \ - stackx4 + 2 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N + offset * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N, \ - stackx4 + 3 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N + offset * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N, sk_seed, \ - pub_seed, idx + idx_offset[0], idx + idx_offset[1], idx + idx_offset[2], \ - idx + idx_offset[3], tree_addrx4, state_seeded); \ - offset++; \ - heights[offset - 1] = 0; \ - \ - /* If this is a node we need for the auth path.. */ \ - for (j = 0; j < 4; j++) { \ - if ((leaf_idx[j] ^ 0x1) == idx) { \ - memcpy(auth_pathx4 + j * (tree_height)*PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N, \ - stackx4 + j * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N + (offset - 1) * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N, \ - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N); \ - } \ - } \ - \ - /* While the top-most nodes are of equal height.. */ \ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { \ - /* Compute index of the new node, in the next layer. */ \ - tree_idx = (idx >> (heights[offset - 1] + 1)); \ - \ - /* Set the address of the node we're creating. */ \ - for (j = 0; j < 4; j++) { \ - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_set_tree_height(tree_addrx4 + j * 8, heights[offset - 1] + 1); \ - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_set_tree_index(tree_addrx4 + j * 8, \ - tree_idx + (idx_offset[j] >> (heights[offset - 1] + 1))); \ - } \ - /* Hash the top-most nodes from the stack together. */ \ - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_thashx4_2(stackx4 + 0 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N + (offset - 2) * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N, \ - stackx4 + 1 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N + (offset - 2) * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N, \ - stackx4 + 2 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N + (offset - 2) * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N, \ - stackx4 + 3 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N + (offset - 2) * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N, \ - stackx4 + 0 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N + (offset - 2) * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N, \ - stackx4 + 1 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N + (offset - 2) * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N, \ - stackx4 + 2 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N + (offset - 2) * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N, \ - stackx4 + 3 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N + (offset - 2) * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N, \ - pub_seed, tree_addrx4, state_seeded); \ - offset--; \ - /* Note that the top-most node is now one layer higher. */ \ - heights[offset - 1]++; \ - \ - /* If this is a node we need for the auth path.. */ \ - for (j = 0; j < 4; j++) { \ - if (((leaf_idx[j] >> heights[offset - 1]) ^ 0x1) == tree_idx) { \ - memcpy(auth_pathx4 + j * (tree_height)*PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N + \ - heights[offset - 1] * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N, \ - stackx4 + j * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N + (offset - 1) * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N, \ - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N); \ - } \ - } \ - } \ - } \ - \ - for (j = 0; j < 4; j++) { \ - memcpy(rootx4 + j * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N, stackx4 + j * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N); \ - } \ - } - -treehashx4_variant(FORS_HEIGHT, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_FORS_HEIGHT) diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_avx2/utilsx4.h b/src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_avx2/utilsx4.h deleted file mode 100644 index ce994c7c08..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_avx2/utilsx4.h +++ /dev/null @@ -1,38 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_UTILSX4_H -#define PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_UTILSX4_H - -#include "hash_state.h" -#include "params.h" - -#include - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_treehashx4_FORS_HEIGHT(unsigned char *rootx4, - unsigned char *auth_pathx4, - const unsigned char *sk_seed, - const unsigned char *pub_seed, - const uint32_t leaf_idx[4], - uint32_t idx_offset[4], - void (*gen_leafx4)(unsigned char * /* leaf0 */, - unsigned char * /* leaf1 */, - unsigned char * /* leaf2 */, - unsigned char * /* leaf3 */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx0 */, - uint32_t /* addr_idx1 */, - uint32_t /* addr_idx2 */, - uint32_t /* addr_idx3 */, - const uint32_t[8] /* tree_addr */, - const hash_state * /* state_seeded */), - uint32_t tree_addrx4[4 * 8], - const hash_state *state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_avx2/wots.c b/src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_avx2/wots.c deleted file mode 100644 index 7d1b6b95b2..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_avx2/wots.c +++ /dev/null @@ -1,240 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "hash_state.h" -#include "hashx4.h" -#include "params.h" -#include "thash.h" -#include "thashx4.h" -#include "utils.h" -#include "wots.h" - -// TODO clarify address expectations, and make them more uniform. -// TODO i.e. do we expect types to be set already? -// TODO and do we expect modifications or copies? - -/** - * Computes the starting value for a chain, i.e. the secret key. - * Expects the address to be complete up to the chain address. - */ -static void wots_gen_sk(unsigned char *sk, const unsigned char *sk_seed, - uint32_t wots_addr[8], const hash_state *state_seeded) { - /* Make sure that the hash address is actually zeroed. */ - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_set_hash_addr(wots_addr, 0); - - /* Generate sk element. */ - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_prf_addr(sk, sk_seed, wots_addr, state_seeded); -} - -/** - * 4-way parallel version of wots_gen_sk; expects 4x as much space in sk - */ -static void wots_gen_skx4(unsigned char *skx4, const unsigned char *sk_seed, - uint32_t wots_addrx4[4 * 8], const hash_state *state_seeded) { - unsigned int j; - - /* Make sure that the hash address is actually zeroed. */ - for (j = 0; j < 4; j++) { - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_set_hash_addr(wots_addrx4 + j * 8, 0); - } - - /* Generate sk element. */ - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_prf_addrx4(skx4 + 0 * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N, - skx4 + 1 * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N, - skx4 + 2 * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N, - skx4 + 3 * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N, - sk_seed, wots_addrx4, - state_seeded); -} - -/** - * Computes the chaining function. - * out and in have to be n-byte arrays. - * - * Interprets in as start-th value of the chain. - * addr has to contain the address of the chain. - */ -static void gen_chain(unsigned char *out, const unsigned char *in, - unsigned int start, unsigned int steps, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *state_seeded) { - uint32_t i; - - /* Initialize out with the value at position 'start'. */ - memcpy(out, in, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N); - - /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_WOTS_W; i++) { - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_set_hash_addr(addr, i); - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_thash_1(out, out, pub_seed, addr, state_seeded); - } -} - -/** - * 4-way parallel version of gen_chain; expects 4x as much space in out, and - * 4x as much space in inx4. Assumes start and step identical across chains. - */ -static void gen_chainx4(unsigned char *outx4, const unsigned char *inx4, - unsigned int start, unsigned int steps, - const unsigned char *pub_seed, uint32_t addrx4[4 * 8], - const hash_state *state_seeded) { - uint32_t i; - unsigned int j; - - /* Initialize outx4 with the value at position 'start'. */ - memcpy(outx4, inx4, 4 * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N); - - /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_WOTS_W; i++) { - for (j = 0; j < 4; j++) { - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_set_hash_addr(addrx4 + j * 8, i); - } - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_thashx4_1(outx4 + 0 * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N, - outx4 + 1 * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N, - outx4 + 2 * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N, - outx4 + 3 * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N, - outx4 + 0 * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N, - outx4 + 1 * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N, - outx4 + 2 * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N, - outx4 + 3 * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N, - pub_seed, addrx4, - state_seeded); - } -} - -/** - * base_w algorithm as described in draft. - * Interprets an array of bytes as integers in base w. - * This only works when log_w is a divisor of 8. - */ -static void base_w(unsigned int *output, const int out_len, const unsigned char *input) { - int in = 0; - int out = 0; - unsigned char total = 0; - int bits = 0; - int consumed; - - for (consumed = 0; consumed < out_len; consumed++) { - if (bits == 0) { - total = input[in]; - in++; - bits += 8; - } - bits -= PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_WOTS_LOGW; - output[out] = (unsigned int)(total >> bits) & (PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_WOTS_W - 1); - out++; - } -} - -/* Computes the WOTS+ checksum over a message (in base_w). */ -static void wots_checksum(unsigned int *csum_base_w, const unsigned int *msg_base_w) { - unsigned int csum = 0; - unsigned char csum_bytes[(PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_WOTS_LEN2 * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_WOTS_LOGW + 7) / 8]; - unsigned int i; - - /* Compute checksum. */ - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_WOTS_LEN1; i++) { - csum += PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_WOTS_W - 1 - msg_base_w[i]; - } - - /* Convert checksum to base_w. */ - /* Make sure expected empty zero bits are the least significant bits. */ - csum = csum << (8 - ((PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_WOTS_LEN2 * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_WOTS_LOGW) % 8)); - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); - base_w(csum_base_w, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_WOTS_LEN2, csum_bytes); -} - -/* Takes a message and derives the matching chain lengths. */ -static void chain_lengths(unsigned int *lengths, const unsigned char *msg) { - base_w(lengths, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_WOTS_LEN1, msg); - wots_checksum(lengths + PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_WOTS_LEN1, lengths); -} - -/** - * WOTS key generation. Takes a 32 byte sk_seed, expands it to WOTS private key - * elements and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_wots_gen_pk(unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *state_seeded) { - uint32_t i; - unsigned int j; - - uint32_t addrx4[4 * 8]; - unsigned char pkbuf[4 * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N]; - - for (j = 0; j < 4; j++) { - memcpy(addrx4 + j * 8, addr, sizeof(uint32_t) * 8); - } - - /* The last iteration typically does not have complete set of 4 chains, - but because we use pkbuf, this is not an issue -- we still do as many - in parallel as possible. */ - for (i = 0; i < ((PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_WOTS_LEN + 3) & ~0x3); i += 4) { - for (j = 0; j < 4; j++) { - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_set_chain_addr(addrx4 + j * 8, i + j); - } - wots_gen_skx4(pkbuf, sk_seed, addrx4, state_seeded); - gen_chainx4(pkbuf, pkbuf, 0, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_WOTS_W - 1, pub_seed, addrx4, state_seeded); - for (j = 0; j < 4; j++) { - if (i + j < PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_WOTS_LEN) { - memcpy(pk + (i + j)*PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N, pkbuf + j * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N); - } - } - } - - // Get rid of unused argument variable. - (void)state_seeded; -} - -/** - * Takes a n-byte message and the 32-byte sk_see to compute a signature 'sig'. - */ -void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_wots_sign(unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_WOTS_LEN; i++) { - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_set_chain_addr(addr, i); - wots_gen_sk(sig + i * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N, sk_seed, addr, state_seeded); - gen_chain(sig + i * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N, sig + i * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N, 0, lengths[i], pub_seed, addr, state_seeded); - } - - // avoid unused argument - (void)state_seeded; -} - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_WOTS_LEN; i++) { - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_set_chain_addr(addr, i); - gen_chain(pk + i * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N, sig + i * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_N, - lengths[i], PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_WOTS_W - 1 - lengths[i], pub_seed, addr, - state_seeded); - } - - // avoid unused argument - (void)state_seeded; -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_avx2/wots.h b/src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_avx2/wots.h deleted file mode 100644 index 69f6c9dbf8..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_avx2/wots.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_WOTS_H -#define PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_WOTS_H - -#include "hash_state.h" -#include "params.h" -#include - -/** - * WOTS key generation. Takes a 32 byte seed for the private key, expands it to - * a full WOTS private key and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_wots_gen_pk( - unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -/** - * Takes a n-byte message and the 32-byte seed for the private key to compute a - * signature that is placed at 'sig'. - */ -void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_wots_sign( - unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *hash_state_seeded); - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_wots_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_clean/LICENSE b/src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_clean/LICENSE deleted file mode 100644 index 670154e353..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_clean/LICENSE +++ /dev/null @@ -1,116 +0,0 @@ -CC0 1.0 Universal - -Statement of Purpose - -The laws of most jurisdictions throughout the world automatically confer -exclusive Copyright and Related Rights (defined below) upon the creator and -subsequent owner(s) (each and all, an "owner") of an original work of -authorship and/or a database (each, a "Work"). - -Certain owners wish to permanently relinquish those rights to a Work for the -purpose of contributing to a commons of creative, cultural and scientific -works ("Commons") that the public can reliably and without fear of later -claims of infringement build upon, modify, incorporate in other works, reuse -and redistribute as freely as possible in any form whatsoever and for any -purposes, including without limitation commercial purposes. These owners may -contribute to the Commons to promote the ideal of a free culture and the -further production of creative, cultural and scientific works, or to gain -reputation or greater distribution for their Work in part through the use and -efforts of others. - -For these and/or other purposes and motivations, and without any expectation -of additional consideration or compensation, the person associating CC0 with a -Work (the "Affirmer"), to the extent that he or she is an owner of Copyright -and Related Rights in the Work, voluntarily elects to apply CC0 to the Work -and publicly distribute the Work under its terms, with knowledge of his or her -Copyright and Related Rights in the Work and the meaning and intended legal -effect of CC0 on those rights. - -1. Copyright and Related Rights. A Work made available under CC0 may be -protected by copyright and related or neighboring rights ("Copyright and -Related Rights"). Copyright and Related Rights include, but are not limited -to, the following: - - i. the right to reproduce, adapt, distribute, perform, display, communicate, - and translate a Work; - - ii. moral rights retained by the original author(s) and/or performer(s); - - iii. publicity and privacy rights pertaining to a person's image or likeness - depicted in a Work; - - iv. rights protecting against unfair competition in regards to a Work, - subject to the limitations in paragraph 4(a), below; - - v. rights protecting the extraction, dissemination, use and reuse of data in - a Work; - - vi. database rights (such as those arising under Directive 96/9/EC of the - European Parliament and of the Council of 11 March 1996 on the legal - protection of databases, and under any national implementation thereof, - including any amended or successor version of such directive); and - - vii. other similar, equivalent or corresponding rights throughout the world - based on applicable law or treaty, and any national implementations thereof. - -2. Waiver. To the greatest extent permitted by, but not in contravention of, -applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and -unconditionally waives, abandons, and surrenders all of Affirmer's Copyright -and Related Rights and associated claims and causes of action, whether now -known or unknown (including existing as well as future claims and causes of -action), in the Work (i) in all territories worldwide, (ii) for the maximum -duration provided by applicable law or treaty (including future time -extensions), (iii) in any current or future medium and for any number of -copies, and (iv) for any purpose whatsoever, including without limitation -commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes -the Waiver for the benefit of each member of the public at large and to the -detriment of Affirmer's heirs and successors, fully intending that such Waiver -shall not be subject to revocation, rescission, cancellation, termination, or -any other legal or equitable action to disrupt the quiet enjoyment of the Work -by the public as contemplated by Affirmer's express Statement of Purpose. - -3. Public License Fallback. Should any part of the Waiver for any reason be -judged legally invalid or ineffective under applicable law, then the Waiver -shall be preserved to the maximum extent permitted taking into account -Affirmer's express Statement of Purpose. In addition, to the extent the Waiver -is so judged Affirmer hereby grants to each affected person a royalty-free, -non transferable, non sublicensable, non exclusive, irrevocable and -unconditional license to exercise Affirmer's Copyright and Related Rights in -the Work (i) in all territories worldwide, (ii) for the maximum duration -provided by applicable law or treaty (including future time extensions), (iii) -in any current or future medium and for any number of copies, and (iv) for any -purpose whatsoever, including without limitation commercial, advertising or -promotional purposes (the "License"). The License shall be deemed effective as -of the date CC0 was applied by Affirmer to the Work. Should any part of the -License for any reason be judged legally invalid or ineffective under -applicable law, such partial invalidity or ineffectiveness shall not -invalidate the remainder of the License, and in such case Affirmer hereby -affirms that he or she will not (i) exercise any of his or her remaining -Copyright and Related Rights in the Work or (ii) assert any associated claims -and causes of action with respect to the Work, in either case contrary to -Affirmer's express Statement of Purpose. - -4. Limitations and Disclaimers. - - a. No trademark or patent rights held by Affirmer are waived, abandoned, - surrendered, licensed or otherwise affected by this document. - - b. Affirmer offers the Work as-is and makes no representations or warranties - of any kind concerning the Work, express, implied, statutory or otherwise, - including without limitation warranties of title, merchantability, fitness - for a particular purpose, non infringement, or the absence of latent or - other defects, accuracy, or the present or absence of errors, whether or not - discoverable, all to the greatest extent permissible under applicable law. - - c. Affirmer disclaims responsibility for clearing rights of other persons - that may apply to the Work or any use thereof, including without limitation - any person's Copyright and Related Rights in the Work. Further, Affirmer - disclaims responsibility for obtaining any necessary consents, permissions - or other rights required for any use of the Work. - - d. Affirmer understands and acknowledges that Creative Commons is not a - party to this document and has no duty or obligation with respect to this - CC0 or use of the Work. - -For more information, please see - diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_clean/address.c b/src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_clean/address.c deleted file mode 100644 index 9153447ff5..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_clean/address.c +++ /dev/null @@ -1,78 +0,0 @@ -#include - -#include "address.h" -#include "params.h" -#include "utils.h" - -void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]) { - int i; - - for (i = 0; i < 8; i++) { - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_ull_to_bytes( - bytes + i * 4, 4, addr[i]); - } -} - -void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_set_layer_addr( - uint32_t addr[8], uint32_t layer) { - addr[0] = layer; -} - -void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_set_tree_addr( - uint32_t addr[8], uint64_t tree) { - addr[1] = 0; - addr[2] = (uint32_t) (tree >> 32); - addr[3] = (uint32_t) tree; -} - -void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_set_type( - uint32_t addr[8], uint32_t type) { - addr[4] = type; -} - -void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; -} - -/* These functions are used for OTS addresses. */ - -void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_set_keypair_addr( - uint32_t addr[8], uint32_t keypair) { - addr[5] = keypair; -} - -void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; - out[5] = in[5]; -} - -void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_set_chain_addr( - uint32_t addr[8], uint32_t chain) { - addr[6] = chain; -} - -void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_set_hash_addr( - uint32_t addr[8], uint32_t hash) { - addr[7] = hash; -} - -/* These functions are used for all hash tree addresses (including FORS). */ - -void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_set_tree_height( - uint32_t addr[8], uint32_t tree_height) { - addr[6] = tree_height; -} - -void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_set_tree_index( - uint32_t addr[8], uint32_t tree_index) { - addr[7] = tree_index; -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_clean/address.h b/src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_clean/address.h deleted file mode 100644 index b665dd6631..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_clean/address.h +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_ADDRESS_H -#define PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_ADDRESS_H - -#include - -#define PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_ADDR_TYPE_WOTS 0 -#define PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_ADDR_TYPE_WOTSPK 1 -#define PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_ADDR_TYPE_HASHTREE 2 -#define PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_ADDR_TYPE_FORSTREE 3 -#define PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_ADDR_TYPE_FORSPK 4 - -void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]); - -void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_set_layer_addr( - uint32_t addr[8], uint32_t layer); - -void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_set_tree_addr( - uint32_t addr[8], uint64_t tree); - -void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_set_type( - uint32_t addr[8], uint32_t type); - -/* Copies the layer and tree part of one address into the other */ -void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for WOTS and FORS addresses. */ - -void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_set_keypair_addr( - uint32_t addr[8], uint32_t keypair); - -void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_set_chain_addr( - uint32_t addr[8], uint32_t chain); - -void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_set_hash_addr( - uint32_t addr[8], uint32_t hash); - -void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for all hash tree addresses (including FORS). */ - -void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_set_tree_height( - uint32_t addr[8], uint32_t tree_height); - -void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_set_tree_index( - uint32_t addr[8], uint32_t tree_index); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_clean/api.h b/src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_clean/api.h deleted file mode 100644 index fd59721e38..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_clean/api.h +++ /dev/null @@ -1,81 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_API_H -#define PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_API_H - -#include -#include - - - -#define PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_CRYPTO_ALGNAME "SPHINCS+" - -#define PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_CRYPTO_SECRETKEYBYTES 128 -#define PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_CRYPTO_PUBLICKEYBYTES 64 -#define PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_CRYPTO_BYTES 49856 -#define PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_CRYPTO_SEEDBYTES 96 - - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_clean/fors.c b/src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_clean/fors.c deleted file mode 100644 index 0dd068c029..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_clean/fors.c +++ /dev/null @@ -1,161 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "fors.h" -#include "hash.h" -#include "hash_state.h" -#include "thash.h" -#include "utils.h" - -static void fors_gen_sk(unsigned char *sk, const unsigned char *sk_seed, - uint32_t fors_leaf_addr[8], const hash_state *hash_state_seeded) { - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_prf_addr( - sk, sk_seed, fors_leaf_addr, hash_state_seeded); -} - -static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, - const unsigned char *pub_seed, - uint32_t fors_leaf_addr[8], - const hash_state *hash_state_seeded) { - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_thash_1( - leaf, sk, pub_seed, fors_leaf_addr, hash_state_seeded); -} - -static void fors_gen_leaf(unsigned char *leaf, const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx, const uint32_t fors_tree_addr[8], - const hash_state *hash_state_seeded) { - uint32_t fors_leaf_addr[8] = {0}; - - /* Only copy the parts that must be kept in fors_leaf_addr. */ - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_copy_keypair_addr( - fors_leaf_addr, fors_tree_addr); - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_set_type( - fors_leaf_addr, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_set_tree_index( - fors_leaf_addr, addr_idx); - - fors_gen_sk(leaf, sk_seed, fors_leaf_addr, hash_state_seeded); - fors_sk_to_leaf(leaf, leaf, pub_seed, fors_leaf_addr, hash_state_seeded); -} - -/** - * Interprets m as PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_FORS_HEIGHT-bit unsigned integers. - * Assumes m contains at least PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_FORS_TREES bits. - * Assumes indices has space for PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_FORS_TREES integers. - */ -static void message_to_indices(uint32_t *indices, const unsigned char *m) { - unsigned int i, j; - unsigned int offset = 0; - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_FORS_TREES; i++) { - indices[i] = 0; - for (j = 0; j < PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_FORS_HEIGHT; j++) { - indices[i] ^= (((uint32_t)m[offset >> 3] >> (offset & 0x7)) & 0x1) << j; - offset++; - } - } -} - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_fors_sign( - unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *hash_state_seeded) { - uint32_t indices[PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_FORS_TREES]; - unsigned char roots[PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_FORS_TREES * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_N]; - uint32_t fors_tree_addr[8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_copy_keypair_addr( - fors_tree_addr, fors_addr); - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_copy_keypair_addr( - fors_pk_addr, fors_addr); - - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_set_type( - fors_tree_addr, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_set_type( - fors_pk_addr, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_FORS_TREES; i++) { - idx_offset = i * (1 << PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_FORS_HEIGHT); - - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_set_tree_height( - fors_tree_addr, 0); - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_set_tree_index( - fors_tree_addr, indices[i] + idx_offset); - - /* Include the secret key part that produces the selected leaf node. */ - fors_gen_sk(sig, sk_seed, fors_tree_addr, hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_N; - - /* Compute the authentication path for this leaf node. */ - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_treehash_FORS_HEIGHT( - roots + i * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_N, sig, sk_seed, pub_seed, - indices[i], idx_offset, fors_gen_leaf, fors_tree_addr, - hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_N * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_thash_FORS_TREES( - pk, roots, pub_seed, fors_pk_addr, hash_state_seeded); -} - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_fors_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, const uint32_t fors_addr[8], - const hash_state *hash_state_seeded) { - uint32_t indices[PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_FORS_TREES]; - unsigned char roots[PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_FORS_TREES * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_N]; - unsigned char leaf[PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_N]; - uint32_t fors_tree_addr[8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_copy_keypair_addr(fors_tree_addr, fors_addr); - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_copy_keypair_addr(fors_pk_addr, fors_addr); - - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_set_type(fors_tree_addr, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_set_type(fors_pk_addr, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_FORS_TREES; i++) { - idx_offset = i * (1 << PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_FORS_HEIGHT); - - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_set_tree_height(fors_tree_addr, 0); - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Derive the leaf from the included secret key part. */ - fors_sk_to_leaf(leaf, sig, pub_seed, fors_tree_addr, hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_N; - - /* Derive the corresponding root node of this tree. */ - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_compute_root(roots + i * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_N, leaf, indices[i], idx_offset, sig, - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_FORS_HEIGHT, pub_seed, fors_tree_addr, hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_N * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_thash_FORS_TREES(pk, roots, pub_seed, fors_pk_addr, hash_state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_clean/fors.h b/src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_clean/fors.h deleted file mode 100644 index 2cb13e9903..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_clean/fors.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_FORS_H -#define PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_FORS_H - -#include - -#include "hash_state.h" -#include "params.h" - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_fors_sign( - unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *hash_state_seeded); - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_fors_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, const uint32_t fors_addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_clean/hash.h b/src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_clean/hash.h deleted file mode 100644 index ab6f5ac2ef..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_clean/hash.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_HASH_H -#define PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_HASH_H - -#include "hash_state.h" - -#include -#include - -void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_initialize_hash_function( - hash_state *hash_state_seeded, - const unsigned char *pub_seed, const unsigned char *sk_seed); - -void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_destroy_hash_function(hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_clean/hash_shake256.c b/src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_clean/hash_shake256.c deleted file mode 100644 index dfc285bfae..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_clean/hash_shake256.c +++ /dev/null @@ -1,106 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "utils.h" - -#include "fips202.h" - -/* For SHAKE256, there is no immediate reason to initialize at the start, - so this function is an empty operation. */ -void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_initialize_hash_function( - hash_state *hash_state_seeded, // NOLINT(readability-non-const-parameter) - const unsigned char *pub_seed, const unsigned char *sk_seed) { - (void)hash_state_seeded; /* Suppress an 'unused parameter' warning. */ - (void)pub_seed; /* Suppress an 'unused parameter' warning. */ - (void)sk_seed; /* Suppress an 'unused parameter' warning. */ -} - -/* This is not necessary for SHAKE256, so we don't do anything */ -void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_destroy_hash_function( - hash_state *hash_state_seeded) { // NOLINT(readability-non-const-parameter) - (void)hash_state_seeded; -} - -/* - * Computes PRF(key, addr), given a secret key of PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_N bytes and an address - */ -void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded) { - unsigned char buf[PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_N + PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_ADDR_BYTES]; - - memcpy(buf, key, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_N); - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_addr_to_bytes(buf + PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_N, addr); - - shake256(out, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_N, buf, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_N + PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_ADDR_BYTES); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} - -/** - * Computes the message-dependent randomness R, using a secret seed and an - * optional randomization value as well as the message. - */ -void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded) { - shake256incctx state; - - shake256_inc_init(&state); - shake256_inc_absorb(&state, sk_prf, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_N); - shake256_inc_absorb(&state, optrand, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_N); - shake256_inc_absorb(&state, m, mlen); - shake256_inc_finalize(&state); - shake256_inc_squeeze(R, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_N, &state); - shake256_inc_ctx_release(&state); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} - -/** - * Computes the message hash using R, the public key, and the message. - * Outputs the message digest and the index of the leaf. The index is split in - * the tree index and the leaf index, for convenient copying to an address. - */ -void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded) { -#define PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_TREE_BITS (PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_TREE_HEIGHT * (PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_D - 1)) -#define PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_TREE_BYTES ((PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_TREE_BITS + 7) / 8) -#define PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_LEAF_BITS PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_TREE_HEIGHT -#define PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_LEAF_BYTES ((PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_LEAF_BITS + 7) / 8) -#define PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_DGST_BYTES (PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_FORS_MSG_BYTES + PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_TREE_BYTES + PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_LEAF_BYTES) - - unsigned char buf[PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_DGST_BYTES]; - unsigned char *bufp = buf; - shake256incctx state; - - shake256_inc_init(&state); - shake256_inc_absorb(&state, R, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_N); - shake256_inc_absorb(&state, pk, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_PK_BYTES); - shake256_inc_absorb(&state, m, mlen); - shake256_inc_finalize(&state); - shake256_inc_squeeze(buf, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_DGST_BYTES, &state); - shake256_inc_ctx_release(&state); - - memcpy(digest, bufp, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_FORS_MSG_BYTES); - bufp += PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_FORS_MSG_BYTES; - - *tree = PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_bytes_to_ull( - bufp, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_TREE_BYTES); - *tree &= (~(uint64_t)0) >> (64 - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_TREE_BITS); - bufp += PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_TREE_BYTES; - - *leaf_idx = (uint32_t)PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_bytes_to_ull( - bufp, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_LEAF_BYTES); - *leaf_idx &= (~(uint32_t)0) >> (32 - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_LEAF_BITS); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_clean/hash_state.h b/src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_clean/hash_state.h deleted file mode 100644 index 7d92ef872a..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_clean/hash_state.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef SPX_HASH_STATE_H -#define SPX_HASH_STATE_H - -/** - * Defines the type of the hash function state. - * - * Don't be fooled into thinking this instance of SPHINCS+ isn't stateless! - * - * From Section 7.2.2 from the SPHINCS+ round-2 specification: - * - * Each of the instances of the tweakable hash function take PK.seed as its - * first input, which is constant for a given key pair – and, thus, across - * a single signature. This leads to a lot of redundant computation. To remedy - * this, we pad PK.seed to the length of a full 64-byte SHA-256 input block. - * Because of the Merkle-Damgård construction that underlies SHA-256, this - * allows for reuse of the intermediate SHA-256 state after the initial call to - * the compression function which improves performance. - * - * We pass this hash state around in functions, because otherwise we need to - * have a global variable. - * - * SHAKE256 does not need this state. Because this implementation is generated - * from a shared code base, we still need to specify some hash_state as it is - * still passed around. We chose to use an `int` as a placeholder for this - * purpose. - */ - -#define hash_state int - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_clean/params.h b/src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_clean/params.h deleted file mode 100644 index dac379d3ff..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_clean/params.h +++ /dev/null @@ -1,53 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_PARAMS_H -#define PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_PARAMS_H - -/* Hash output length in bytes. */ -#define PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_N 32 -/* Height of the hypertree. */ -#define PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_FULL_HEIGHT 68 -/* Number of subtree layer. */ -#define PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_D 17 -/* FORS tree dimensions. */ -#define PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_FORS_HEIGHT 9 -#define PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_FORS_TREES 35 -/* Winternitz parameter, */ -#define PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_WOTS_W 16 - -/* The hash function is defined by linking a different hash.c file, as opposed - to setting a #define constant. */ - -/* For clarity */ -#define PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_ADDR_BYTES 32 - -/* WOTS parameters. */ -#define PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_WOTS_LOGW 4 - -#define PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_WOTS_LEN1 (8 * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_N / PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_WOTS_LOGW) - -/* PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#define PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_WOTS_LEN2 3 - -#define PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_WOTS_LEN (PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_WOTS_LEN1 + PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_WOTS_LEN2) -#define PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_WOTS_BYTES (PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_WOTS_LEN * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_N) -#define PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_WOTS_PK_BYTES PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_WOTS_BYTES - -/* Subtree size. */ -#define PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_TREE_HEIGHT (PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_FULL_HEIGHT / PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_D) - -/* FORS parameters. */ -#define PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_FORS_MSG_BYTES ((PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_FORS_TREES + 7) / 8) -#define PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_FORS_BYTES ((PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_FORS_HEIGHT + 1) * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_FORS_TREES * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_N) -#define PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_FORS_PK_BYTES PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_N - -/* Resulting SPX sizes. */ -#define PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_BYTES (PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_N + PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_FORS_BYTES + PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_D * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_WOTS_BYTES +\ - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_FULL_HEIGHT * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_N) -#define PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_PK_BYTES (2 * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_N) -#define PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_SK_BYTES (2 * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_N + PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_PK_BYTES) - -/* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ -#define PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_OPTRAND_BYTES 32 - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_clean/sign.c b/src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_clean/sign.c deleted file mode 100644 index f459a3a2fa..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_clean/sign.c +++ /dev/null @@ -1,356 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "api.h" -#include "fors.h" -#include "hash.h" -#include "hash_state.h" -#include "params.h" -#include "randombytes.h" -#include "thash.h" -#include "utils.h" -#include "wots.h" - -/** - * Computes the leaf at a given address. First generates the WOTS key pair, - * then computes leaf by hashing horizontally. - */ -static void wots_gen_leaf(unsigned char *leaf, const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx, const uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - unsigned char pk[PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_WOTS_BYTES]; - uint32_t wots_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_set_type( - wots_addr, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_set_type( - wots_pk_addr, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_ADDR_TYPE_WOTSPK); - - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_set_keypair_addr( - wots_addr, addr_idx); - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_wots_gen_pk( - pk, sk_seed, pub_seed, wots_addr, hash_state_seeded); - - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_copy_keypair_addr( - wots_pk_addr, wots_addr); - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_thash_WOTS_LEN( - leaf, pk, pub_seed, wots_pk_addr, hash_state_seeded); -} - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_crypto_sign_secretkeybytes(void) { - return PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_CRYPTO_SECRETKEYBYTES; -} - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_crypto_sign_publickeybytes(void) { - return PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_CRYPTO_PUBLICKEYBYTES; -} - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_crypto_sign_bytes(void) { - return PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_CRYPTO_BYTES; -} - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_crypto_sign_seedbytes(void) { - return PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_CRYPTO_SEEDBYTES; -} - -/* - * Generates an SPX key pair given a seed of length - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed) { - /* We do not need the auth path in key generation, but it simplifies the - code to have just one treehash routine that computes both root and path - in one function. */ - unsigned char auth_path[PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_TREE_HEIGHT * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_N]; - uint32_t top_tree_addr[8] = {0}; - hash_state hash_state_seeded; - - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_set_layer_addr( - top_tree_addr, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_D - 1); - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_set_type( - top_tree_addr, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_ADDR_TYPE_HASHTREE); - - /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ - memcpy(sk, seed, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_CRYPTO_SEEDBYTES); - - memcpy(pk, sk + 2 * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_N, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_initialize_hash_function(&hash_state_seeded, pk, sk); - - /* Compute root node of the top-most subtree. */ - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_treehash_TREE_HEIGHT( - sk + 3 * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_N, auth_path, sk, sk + 2 * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_N, 0, 0, - wots_gen_leaf, top_tree_addr, &hash_state_seeded); - - memcpy(pk + PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_N, sk + 3 * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_N, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_N); - - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_destroy_hash_function(&hash_state_seeded); - return 0; -} - -/* - * Generates an SPX key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk) { - unsigned char seed[PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_CRYPTO_SEEDBYTES]; - randombytes(seed, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_CRYPTO_SEEDBYTES); - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_crypto_sign_seed_keypair( - pk, sk, seed); - - return 0; -} - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - const unsigned char *sk_seed = sk; - const unsigned char *sk_prf = sk + PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_N; - const unsigned char *pk = sk + 2 * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_N; - const unsigned char *pub_seed = pk; - - unsigned char optrand[PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_N]; - unsigned char mhash[PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_FORS_MSG_BYTES]; - unsigned char root[PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_N]; - uint32_t i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - - hash_state hash_state_seeded; - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_initialize_hash_function( - &hash_state_seeded, - pub_seed, sk_seed); - - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_set_type( - wots_addr, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_set_type( - tree_addr, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_ADDR_TYPE_HASHTREE); - - /* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ - randombytes(optrand, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_N); - /* Compute the digest randomization value. */ - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_gen_message_random( - sig, sk_prf, optrand, m, mlen, &hash_state_seeded); - - /* Derive the message digest and leaf index from R, PK and M. */ - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_N; - - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); - - /* Sign the message hash using FORS. */ - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_fors_sign( - sig, root, mhash, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_FORS_BYTES; - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_D; i++) { - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_set_tree_addr(tree_addr, tree); - - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); - - /* Compute a WOTS signature. */ - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_wots_sign( - sig, root, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_WOTS_BYTES; - - /* Compute the authentication path for the used WOTS leaf. */ - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_treehash_TREE_HEIGHT( - root, sig, sk_seed, pub_seed, idx_leaf, 0, - wots_gen_leaf, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_TREE_HEIGHT * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_TREE_HEIGHT; - } - - *siglen = PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_BYTES; - - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_destroy_hash_function(&hash_state_seeded); - return 0; -} - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk) { - const unsigned char *pub_seed = pk; - const unsigned char *pub_root = pk + PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_N; - unsigned char mhash[PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_FORS_MSG_BYTES]; - unsigned char wots_pk[PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_WOTS_BYTES]; - unsigned char root[PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_N]; - unsigned char leaf[PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_N]; - unsigned int i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - hash_state hash_state_seeded; - - if (siglen != PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_BYTES) { - return -1; - } - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_initialize_hash_function( - &hash_state_seeded, - pub_seed, NULL); - - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_set_type( - wots_addr, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_set_type( - tree_addr, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_ADDR_TYPE_HASHTREE); - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_set_type( - wots_pk_addr, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_ADDR_TYPE_WOTSPK); - - /* Derive the message digest and leaf index from R || PK || M. */ - /* The additional PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_N is a result of the hash domain separator. */ - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_N; - - /* Layer correctly defaults to 0, so no need to set_layer_addr */ - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); - - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_fors_pk_from_sig( - root, sig, mhash, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_FORS_BYTES; - - /* For each subtree.. */ - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_D; i++) { - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_set_tree_addr(tree_addr, tree); - - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); - - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_copy_keypair_addr( - wots_pk_addr, wots_addr); - - /* The WOTS public key is only correct if the signature was correct. */ - /* Initially, root is the FORS pk, but on subsequent iterations it is - the root of the subtree below the currently processed subtree. */ - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_wots_pk_from_sig( - wots_pk, sig, root, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_WOTS_BYTES; - - /* Compute the leaf node using the WOTS public key. */ - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_thash_WOTS_LEN( - leaf, wots_pk, pub_seed, wots_pk_addr, &hash_state_seeded); - - /* Compute the root node of this subtree. */ - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_compute_root( - root, leaf, idx_leaf, 0, sig, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_TREE_HEIGHT, - pub_seed, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_TREE_HEIGHT * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_TREE_HEIGHT; - } - - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_destroy_hash_function(&hash_state_seeded); - /* Check if the root node equals the root node in the public key. */ - if (memcmp(root, pub_root, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_N) != 0) { - return -1; - } - - return 0; -} - - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - size_t siglen; - - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_crypto_sign_signature( - sm, &siglen, m, mlen, sk); - - memmove(sm + PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_BYTES, m, mlen); - *smlen = siglen + mlen; - - return 0; -} - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk) { - /* The API caller does not necessarily know what size a signature should be - but SPHINCS+ signatures are always exactly PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_BYTES. */ - if (smlen < PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_BYTES) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - *mlen = smlen - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_BYTES; - - if (PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_crypto_sign_verify( - sm, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_BYTES, sm + PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_BYTES, *mlen, pk)) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - /* If verification was successful, move the message to the right place. */ - memmove(m, sm + PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_BYTES, *mlen); - - return 0; -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_clean/thash.h b/src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_clean/thash.h deleted file mode 100644 index 59aeb87c59..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_clean/thash.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_THASH_H -#define PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_THASH_H - -#include "hash_state.h" - -#include - -void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_clean/thash_shake256_simple.c b/src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_clean/thash_shake256_simple.c deleted file mode 100644 index 7e0aec01da..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_clean/thash_shake256_simple.c +++ /dev/null @@ -1,74 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash_state.h" -#include "params.h" -#include "thash.h" - -#include "fips202.h" - -/** - * Takes an array of inblocks concatenated arrays of PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_N bytes. - */ -static void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_thash( - unsigned char *out, unsigned char *buf, - const unsigned char *in, unsigned int inblocks, - const unsigned char *pub_seed, uint32_t addr[8]) { - - memcpy(buf, pub_seed, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_N); - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_addr_to_bytes(buf + PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_N, addr); - memcpy(buf + PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_N + PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_ADDR_BYTES, in, inblocks * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_N); - - shake256(out, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_N, buf, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_N + PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_N); -} - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_N + PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_ADDR_BYTES + 1 * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_N]; - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_thash( - out, buf, in, 1, pub_seed, addr); - - (void)hash_state_seeded; /* Avoid unused parameter warning. */ -} - -void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_N + PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_ADDR_BYTES + 2 * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_N]; - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_thash( - out, buf, in, 2, pub_seed, addr); - - (void)hash_state_seeded; /* Avoid unused parameter warning. */ -} - -void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_N + PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_ADDR_BYTES + PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_WOTS_LEN * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_N]; - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_thash( - out, buf, in, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_WOTS_LEN, pub_seed, addr); - - (void)hash_state_seeded; /* Avoid unused parameter warning. */ -} - -void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_N + PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_ADDR_BYTES + PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_FORS_TREES * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_N]; - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_thash( - out, buf, in, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_FORS_TREES, pub_seed, addr); - - (void)hash_state_seeded; /* Avoid unused parameter warning. */ -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_clean/utils.c b/src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_clean/utils.c deleted file mode 100644 index 1bdf401f36..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_clean/utils.c +++ /dev/null @@ -1,199 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "hash_state.h" -#include "params.h" -#include "thash.h" -#include "utils.h" - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in) { - - /* Iterate over out in decreasing order, for big-endianness. */ - for (size_t i = outlen; i > 0; i--) { - out[i - 1] = in & 0xff; - in = in >> 8; - } -} - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_bytes_to_ull( - const unsigned char *in, size_t inlen) { - unsigned long long retval = 0; - - for (size_t i = 0; i < inlen; i++) { - retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); - } - return retval; -} - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - uint32_t i; - unsigned char buffer[2 * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_N]; - - /* If leaf_idx is odd (last bit = 1), current path element is a right child - and auth_path has to go left. Otherwise it is the other way around. */ - if (leaf_idx & 1) { - memcpy(buffer + PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_N, leaf, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_N); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_N); - } else { - memcpy(buffer, leaf, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_N); - memcpy(buffer + PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_N, auth_path, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_N); - } - auth_path += PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_N; - - for (i = 0; i < tree_height - 1; i++) { - leaf_idx >>= 1; - idx_offset >>= 1; - /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_set_tree_height(addr, i + 1); - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_set_tree_index( - addr, leaf_idx + idx_offset); - - /* Pick the right or left neighbor, depending on parity of the node. */ - if (leaf_idx & 1) { - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_thash_2( - buffer + PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_N, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_N); - } else { - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_thash_2( - buffer, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer + PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_N, auth_path, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_N); - } - auth_path += PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_N; - } - - /* The last iteration is exceptional; we do not copy an auth_path node. */ - leaf_idx >>= 1; - idx_offset >>= 1; - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_set_tree_height(addr, tree_height); - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_set_tree_index( - addr, leaf_idx + idx_offset); - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_thash_2( - root, buffer, pub_seed, addr, hash_state_seeded); -} - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -static void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_treehash( - unsigned char *root, unsigned char *auth_path, - unsigned char *stack, unsigned int *heights, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - - unsigned int offset = 0; - uint32_t idx; - uint32_t tree_idx; - - for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { - /* Add the next leaf node to the stack. */ - gen_leaf(stack + offset * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_N, - sk_seed, pub_seed, idx + idx_offset, tree_addr, - hash_state_seeded); - offset++; - heights[offset - 1] = 0; - - /* If this is a node we need for the auth path.. */ - if ((leaf_idx ^ 0x1) == idx) { - memcpy(auth_path, stack + (offset - 1)*PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_N, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_N); - } - - /* While the top-most nodes are of equal height.. */ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { - /* Compute index of the new node, in the next layer. */ - tree_idx = (idx >> (heights[offset - 1] + 1)); - - /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_set_tree_height( - tree_addr, heights[offset - 1] + 1); - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_set_tree_index( - tree_addr, tree_idx + (idx_offset >> (heights[offset - 1] + 1))); - /* Hash the top-most nodes from the stack together. */ - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_thash_2( - stack + (offset - 2)*PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_N, stack + (offset - 2)*PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_N, - pub_seed, tree_addr, hash_state_seeded); - offset--; - /* Note that the top-most node is now one layer higher. */ - heights[offset - 1]++; - - /* If this is a node we need for the auth path.. */ - if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_path + heights[offset - 1]*PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_N, - stack + (offset - 1)*PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_N, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_N); - } - } - } - memcpy(root, stack, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_N); -} - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_FORS_HEIGHT + 1)*PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_N]; - unsigned int heights[PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_FORS_HEIGHT + 1]; - - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_FORS_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_TREE_HEIGHT + 1)*PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_N]; - unsigned int heights[PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_TREE_HEIGHT + 1]; - - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_TREE_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_clean/utils.h b/src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_clean/utils.h deleted file mode 100644 index 5f5fe2701c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_clean/utils.h +++ /dev/null @@ -1,64 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_UTILS_H -#define PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_UTILS_H - -#include "hash_state.h" -#include "params.h" -#include -#include - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in); - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_bytes_to_ull( - const unsigned char *in, size_t inlen); - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_clean/wots.c b/src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_clean/wots.c deleted file mode 100644 index dec1ad1781..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_clean/wots.c +++ /dev/null @@ -1,167 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "hash_state.h" -#include "params.h" -#include "thash.h" -#include "utils.h" -#include "wots.h" - -// TODO clarify address expectations, and make them more uniform. -// TODO i.e. do we expect types to be set already? -// TODO and do we expect modifications or copies? - -/** - * Computes the starting value for a chain, i.e. the secret key. - * Expects the address to be complete up to the chain address. - */ -static void wots_gen_sk(unsigned char *sk, const unsigned char *sk_seed, - uint32_t wots_addr[8], - const hash_state *hash_state_seeded) { - /* Make sure that the hash address is actually zeroed. */ - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_set_hash_addr(wots_addr, 0); - - /* Generate sk element. */ - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_prf_addr(sk, sk_seed, wots_addr, hash_state_seeded); -} - -/** - * Computes the chaining function. - * out and in have to be n-byte arrays. - * - * Interprets in as start-th value of the chain. - * addr has to contain the address of the chain. - */ -static void gen_chain(unsigned char *out, const unsigned char *in, - unsigned int start, unsigned int steps, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - uint32_t i; - - /* Initialize out with the value at position 'start'. */ - memcpy(out, in, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_N); - - /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_WOTS_W; i++) { - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_set_hash_addr(addr, i); - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_thash_1( - out, out, pub_seed, addr, hash_state_seeded); - } -} - -/** - * base_w algorithm as described in draft. - * Interprets an array of bytes as integers in base w. - * This only works when log_w is a divisor of 8. - */ -static void base_w(unsigned int *output, const size_t out_len, - const unsigned char *input) { - size_t in = 0; - size_t out = 0; - unsigned char total = 0; - unsigned int bits = 0; - size_t consumed; - - for (consumed = 0; consumed < out_len; consumed++) { - if (bits == 0) { - total = input[in]; - in++; - bits += 8; - } - bits -= PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_WOTS_LOGW; - output[out] = (unsigned int)((total >> bits) & (PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_WOTS_W - 1)); - out++; - } -} - -/* Computes the WOTS+ checksum over a message (in base_w). */ -static void wots_checksum(unsigned int *csum_base_w, - const unsigned int *msg_base_w) { - unsigned int csum = 0; - unsigned char csum_bytes[(PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_WOTS_LEN2 * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_WOTS_LOGW + 7) / 8]; - unsigned int i; - - /* Compute checksum. */ - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_WOTS_LEN1; i++) { - csum += PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_WOTS_W - 1 - msg_base_w[i]; - } - - /* Convert checksum to base_w. */ - /* Make sure expected empty zero bits are the least significant bits. */ - csum = csum << (8 - ((PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_WOTS_LEN2 * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_WOTS_LOGW) % 8)); - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_ull_to_bytes( - csum_bytes, sizeof(csum_bytes), csum); - base_w(csum_base_w, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_WOTS_LEN2, csum_bytes); -} - -/* Takes a message and derives the matching chain lengths. */ -static void chain_lengths(unsigned int *lengths, const unsigned char *msg) { - base_w(lengths, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_WOTS_LEN1, msg); - wots_checksum(lengths + PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_WOTS_LEN1, lengths); -} - -/** - * WOTS key generation. Takes a 32 byte sk_seed, expands it to WOTS private key - * elements and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_wots_gen_pk( - unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - uint32_t i; - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_WOTS_LEN; i++) { - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_set_chain_addr(addr, i); - wots_gen_sk(pk + i * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_N, sk_seed, addr, hash_state_seeded); - gen_chain(pk + i * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_N, pk + i * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_N, - 0, PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_WOTS_W - 1, pub_seed, addr, hash_state_seeded); - } -} - -/** - * Takes a n-byte message and the 32-byte sk_see to compute a signature 'sig'. - */ -void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_wots_sign( - unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *hash_state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_WOTS_LEN; i++) { - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_set_chain_addr(addr, i); - wots_gen_sk(sig + i * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_N, sk_seed, addr, hash_state_seeded); - gen_chain(sig + i * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_N, sig + i * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_N, 0, lengths[i], pub_seed, addr, hash_state_seeded); - } -} - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_wots_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_WOTS_LEN; i++) { - PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_set_chain_addr(addr, i); - gen_chain(pk + i * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_N, sig + i * PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_N, - lengths[i], PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_WOTS_W - 1 - lengths[i], pub_seed, addr, - hash_state_seeded); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_clean/wots.h b/src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_clean/wots.h deleted file mode 100644 index 2074f0cfb9..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256f-simple_clean/wots.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_WOTS_H -#define PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_WOTS_H - -#include "hash_state.h" -#include "params.h" -#include - -/** - * WOTS key generation. Takes a 32 byte seed for the private key, expands it to - * a full WOTS private key and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_wots_gen_pk( - unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -/** - * Takes a n-byte message and the 32-byte seed for the private key to compute a - * signature that is placed at 'sig'. - */ -void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_wots_sign( - unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *hash_state_seeded); - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_wots_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_avx2/LICENSE b/src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_avx2/LICENSE deleted file mode 100644 index 670154e353..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_avx2/LICENSE +++ /dev/null @@ -1,116 +0,0 @@ -CC0 1.0 Universal - -Statement of Purpose - -The laws of most jurisdictions throughout the world automatically confer -exclusive Copyright and Related Rights (defined below) upon the creator and -subsequent owner(s) (each and all, an "owner") of an original work of -authorship and/or a database (each, a "Work"). - -Certain owners wish to permanently relinquish those rights to a Work for the -purpose of contributing to a commons of creative, cultural and scientific -works ("Commons") that the public can reliably and without fear of later -claims of infringement build upon, modify, incorporate in other works, reuse -and redistribute as freely as possible in any form whatsoever and for any -purposes, including without limitation commercial purposes. These owners may -contribute to the Commons to promote the ideal of a free culture and the -further production of creative, cultural and scientific works, or to gain -reputation or greater distribution for their Work in part through the use and -efforts of others. - -For these and/or other purposes and motivations, and without any expectation -of additional consideration or compensation, the person associating CC0 with a -Work (the "Affirmer"), to the extent that he or she is an owner of Copyright -and Related Rights in the Work, voluntarily elects to apply CC0 to the Work -and publicly distribute the Work under its terms, with knowledge of his or her -Copyright and Related Rights in the Work and the meaning and intended legal -effect of CC0 on those rights. - -1. Copyright and Related Rights. A Work made available under CC0 may be -protected by copyright and related or neighboring rights ("Copyright and -Related Rights"). Copyright and Related Rights include, but are not limited -to, the following: - - i. the right to reproduce, adapt, distribute, perform, display, communicate, - and translate a Work; - - ii. moral rights retained by the original author(s) and/or performer(s); - - iii. publicity and privacy rights pertaining to a person's image or likeness - depicted in a Work; - - iv. rights protecting against unfair competition in regards to a Work, - subject to the limitations in paragraph 4(a), below; - - v. rights protecting the extraction, dissemination, use and reuse of data in - a Work; - - vi. database rights (such as those arising under Directive 96/9/EC of the - European Parliament and of the Council of 11 March 1996 on the legal - protection of databases, and under any national implementation thereof, - including any amended or successor version of such directive); and - - vii. other similar, equivalent or corresponding rights throughout the world - based on applicable law or treaty, and any national implementations thereof. - -2. Waiver. To the greatest extent permitted by, but not in contravention of, -applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and -unconditionally waives, abandons, and surrenders all of Affirmer's Copyright -and Related Rights and associated claims and causes of action, whether now -known or unknown (including existing as well as future claims and causes of -action), in the Work (i) in all territories worldwide, (ii) for the maximum -duration provided by applicable law or treaty (including future time -extensions), (iii) in any current or future medium and for any number of -copies, and (iv) for any purpose whatsoever, including without limitation -commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes -the Waiver for the benefit of each member of the public at large and to the -detriment of Affirmer's heirs and successors, fully intending that such Waiver -shall not be subject to revocation, rescission, cancellation, termination, or -any other legal or equitable action to disrupt the quiet enjoyment of the Work -by the public as contemplated by Affirmer's express Statement of Purpose. - -3. Public License Fallback. Should any part of the Waiver for any reason be -judged legally invalid or ineffective under applicable law, then the Waiver -shall be preserved to the maximum extent permitted taking into account -Affirmer's express Statement of Purpose. In addition, to the extent the Waiver -is so judged Affirmer hereby grants to each affected person a royalty-free, -non transferable, non sublicensable, non exclusive, irrevocable and -unconditional license to exercise Affirmer's Copyright and Related Rights in -the Work (i) in all territories worldwide, (ii) for the maximum duration -provided by applicable law or treaty (including future time extensions), (iii) -in any current or future medium and for any number of copies, and (iv) for any -purpose whatsoever, including without limitation commercial, advertising or -promotional purposes (the "License"). The License shall be deemed effective as -of the date CC0 was applied by Affirmer to the Work. Should any part of the -License for any reason be judged legally invalid or ineffective under -applicable law, such partial invalidity or ineffectiveness shall not -invalidate the remainder of the License, and in such case Affirmer hereby -affirms that he or she will not (i) exercise any of his or her remaining -Copyright and Related Rights in the Work or (ii) assert any associated claims -and causes of action with respect to the Work, in either case contrary to -Affirmer's express Statement of Purpose. - -4. Limitations and Disclaimers. - - a. No trademark or patent rights held by Affirmer are waived, abandoned, - surrendered, licensed or otherwise affected by this document. - - b. Affirmer offers the Work as-is and makes no representations or warranties - of any kind concerning the Work, express, implied, statutory or otherwise, - including without limitation warranties of title, merchantability, fitness - for a particular purpose, non infringement, or the absence of latent or - other defects, accuracy, or the present or absence of errors, whether or not - discoverable, all to the greatest extent permissible under applicable law. - - c. Affirmer disclaims responsibility for clearing rights of other persons - that may apply to the Work or any use thereof, including without limitation - any person's Copyright and Related Rights in the Work. Further, Affirmer - disclaims responsibility for obtaining any necessary consents, permissions - or other rights required for any use of the Work. - - d. Affirmer understands and acknowledges that Creative Commons is not a - party to this document and has no duty or obligation with respect to this - CC0 or use of the Work. - -For more information, please see - diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_avx2/address.c b/src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_avx2/address.c deleted file mode 100644 index b9f84148aa..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_avx2/address.c +++ /dev/null @@ -1,78 +0,0 @@ -#include - -#include "address.h" -#include "params.h" -#include "utils.h" - -void PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]) { - int i; - - for (i = 0; i < 8; i++) { - PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_ull_to_bytes( - bytes + i * 4, 4, addr[i]); - } -} - -void PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_set_layer_addr( - uint32_t addr[8], uint32_t layer) { - addr[0] = layer; -} - -void PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_set_tree_addr( - uint32_t addr[8], uint64_t tree) { - addr[1] = 0; - addr[2] = (uint32_t) (tree >> 32); - addr[3] = (uint32_t) tree; -} - -void PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_set_type( - uint32_t addr[8], uint32_t type) { - addr[4] = type; -} - -void PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; -} - -/* These functions are used for OTS addresses. */ - -void PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_set_keypair_addr( - uint32_t addr[8], uint32_t keypair) { - addr[5] = keypair; -} - -void PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; - out[5] = in[5]; -} - -void PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_set_chain_addr( - uint32_t addr[8], uint32_t chain) { - addr[6] = chain; -} - -void PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_set_hash_addr( - uint32_t addr[8], uint32_t hash) { - addr[7] = hash; -} - -/* These functions are used for all hash tree addresses (including FORS). */ - -void PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_set_tree_height( - uint32_t addr[8], uint32_t tree_height) { - addr[6] = tree_height; -} - -void PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_set_tree_index( - uint32_t addr[8], uint32_t tree_index) { - addr[7] = tree_index; -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_avx2/address.h b/src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_avx2/address.h deleted file mode 100644 index b0a8cc078a..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_avx2/address.h +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_ADDRESS_H -#define PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_ADDRESS_H - -#include - -#define PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_ADDR_TYPE_WOTS 0 -#define PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_ADDR_TYPE_WOTSPK 1 -#define PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_ADDR_TYPE_HASHTREE 2 -#define PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_ADDR_TYPE_FORSTREE 3 -#define PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_ADDR_TYPE_FORSPK 4 - -void PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]); - -void PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_set_layer_addr( - uint32_t addr[8], uint32_t layer); - -void PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_set_tree_addr( - uint32_t addr[8], uint64_t tree); - -void PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_set_type( - uint32_t addr[8], uint32_t type); - -/* Copies the layer and tree part of one address into the other */ -void PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for WOTS and FORS addresses. */ - -void PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_set_keypair_addr( - uint32_t addr[8], uint32_t keypair); - -void PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_set_chain_addr( - uint32_t addr[8], uint32_t chain); - -void PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_set_hash_addr( - uint32_t addr[8], uint32_t hash); - -void PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for all hash tree addresses (including FORS). */ - -void PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_set_tree_height( - uint32_t addr[8], uint32_t tree_height); - -void PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_set_tree_index( - uint32_t addr[8], uint32_t tree_index); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_avx2/api.h b/src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_avx2/api.h deleted file mode 100644 index 6894901a26..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_avx2/api.h +++ /dev/null @@ -1,81 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_API_H -#define PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_API_H - -#include -#include - - - -#define PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_CRYPTO_ALGNAME "SPHINCS+" - -#define PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_CRYPTO_SECRETKEYBYTES 128 -#define PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_CRYPTO_PUBLICKEYBYTES 64 -#define PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_CRYPTO_BYTES 29792 -#define PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_CRYPTO_SEEDBYTES 96 - - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_avx2/fors.c b/src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_avx2/fors.c deleted file mode 100644 index ec5a083864..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_avx2/fors.c +++ /dev/null @@ -1,206 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "fors.h" -#include "hash.h" -#include "hashx4.h" -#include "thash.h" -#include "thashx4.h" -#include "utils.h" -#include "utilsx4.h" - -static void fors_gen_skx4(unsigned char *sk0, - unsigned char *sk1, - unsigned char *sk2, - unsigned char *sk3, const unsigned char *sk_seed, - uint32_t fors_leaf_addrx4[4 * 8], - const hash_state *state_seeded) { - PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_prf_addrx4(sk0, sk1, sk2, sk3, sk_seed, fors_leaf_addrx4, state_seeded); -} - -static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, - const unsigned char *pub_seed, - uint32_t fors_leaf_addr[8], const hash_state *state_seeded) { - PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_thash_1(leaf, sk, pub_seed, fors_leaf_addr, state_seeded); -} - -static void fors_sk_to_leafx4(unsigned char *leaf0, - unsigned char *leaf1, - unsigned char *leaf2, - unsigned char *leaf3, - const unsigned char *sk0, - const unsigned char *sk1, - const unsigned char *sk2, - const unsigned char *sk3, - const unsigned char *pub_seed, - uint32_t fors_leaf_addrx4[4 * 8], - const hash_state *state_seeded) { - PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_thashx4_1(leaf0, leaf1, leaf2, leaf3, - sk0, sk1, sk2, sk3, pub_seed, fors_leaf_addrx4, state_seeded); -} - -static void fors_gen_leafx4(unsigned char *leaf0, - unsigned char *leaf1, - unsigned char *leaf2, - unsigned char *leaf3, - const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx0, - uint32_t addr_idx1, - uint32_t addr_idx2, - uint32_t addr_idx3, - const uint32_t fors_tree_addr[8], - const hash_state *state_seeded) { - uint32_t fors_leaf_addrx4[4 * 8] = {0}; - unsigned int j; - - /* Only copy the parts that must be kept in fors_leaf_addrx4. */ - for (j = 0; j < 4; j++) { - PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_copy_keypair_addr(fors_leaf_addrx4 + j * 8, fors_tree_addr); - PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_set_type(fors_leaf_addrx4 + j * 8, PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_ADDR_TYPE_FORSTREE); - } - - PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_set_tree_index(fors_leaf_addrx4 + 0 * 8, addr_idx0); - PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_set_tree_index(fors_leaf_addrx4 + 1 * 8, addr_idx1); - PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_set_tree_index(fors_leaf_addrx4 + 2 * 8, addr_idx2); - PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_set_tree_index(fors_leaf_addrx4 + 3 * 8, addr_idx3); - - fors_gen_skx4(leaf0, leaf1, leaf2, leaf3, sk_seed, fors_leaf_addrx4, state_seeded); - fors_sk_to_leafx4(leaf0, leaf1, leaf2, leaf3, - leaf0, leaf1, leaf2, leaf3, pub_seed, fors_leaf_addrx4, state_seeded); -} - -/** - * Interprets m as PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_FORS_HEIGHT-bit unsigned integers. - * Assumes m contains at least PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_FORS_TREES bits. - * Assumes indices has space for PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_FORS_TREES integers. - */ -static void message_to_indices(uint32_t *indices, const unsigned char *m) { - unsigned int i, j; - unsigned int offset = 0; - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_FORS_TREES; i++) { - indices[i] = 0; - for (j = 0; j < PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_FORS_HEIGHT; j++) { - indices[i] ^= (((uint32_t)m[offset >> 3] >> (offset & 0x7)) & 0x1) << j; - offset++; - } - } -} - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *state_seeded) { - /* Round up to multiple of 4 to prevent out-of-bounds for x4 parallelism */ - uint32_t indices[(PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_FORS_TREES + 3) & ~3] = {0}; - unsigned char roots[((PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_FORS_TREES + 3) & ~3) * PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N]; - /* Sign to a buffer, since we may not have a nice multiple of 4 and would - otherwise overrun the signature. */ - unsigned char sigbufx4[4 * PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N * (1 + PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_FORS_HEIGHT)]; - uint32_t fors_tree_addrx4[4 * 8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset[4] = {0}; - unsigned int i, j; - - for (j = 0; j < 4; j++) { - PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_copy_keypair_addr(fors_tree_addrx4 + j * 8, fors_addr); - PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_set_type(fors_tree_addrx4 + j * 8, PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_ADDR_TYPE_FORSTREE); - } - - PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_copy_keypair_addr(fors_pk_addr, fors_addr); - PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_set_type(fors_pk_addr, PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < ((PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_FORS_TREES + 3) & ~0x3); i += 4) { - for (j = 0; j < 4; j++) { - if (i + j < PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_FORS_TREES) { - idx_offset[j] = (i + j) * (1 << PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_FORS_HEIGHT); - - PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_set_tree_height(fors_tree_addrx4 + j * 8, 0); - PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_set_tree_index(fors_tree_addrx4 + j * 8, - indices[i + j] + idx_offset[j]); - } - } - - /* Include the secret key part that produces the selected leaf nodes. */ - fors_gen_skx4(sigbufx4 + 0 * PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N, - sigbufx4 + 1 * PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N, - sigbufx4 + 2 * PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N, - sigbufx4 + 3 * PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N, - sk_seed, fors_tree_addrx4, state_seeded); - - PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_treehashx4_FORS_HEIGHT(roots + i * PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N, sigbufx4 + 4 * PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N, sk_seed, pub_seed, - &indices[i], idx_offset, fors_gen_leafx4, fors_tree_addrx4, - state_seeded); - - for (j = 0; j < 4; j++) { - if (i + j < PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_FORS_TREES) { - memcpy(sig, sigbufx4 + j * PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N, PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N); - memcpy(sig + PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N, - sigbufx4 + 4 * PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N + j * PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N * PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_FORS_HEIGHT, - PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N * PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_FORS_HEIGHT); - sig += PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N * (1 + PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_FORS_HEIGHT); - } - } - } - - /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_thash_FORS_TREES(pk, roots, pub_seed, fors_pk_addr, state_seeded); -} - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, - const uint32_t fors_addr[8], - const hash_state *state_seeded) { - uint32_t indices[PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_FORS_TREES]; - unsigned char roots[PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_FORS_TREES * PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N]; - unsigned char leaf[PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N]; - uint32_t fors_tree_addr[8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_copy_keypair_addr(fors_tree_addr, fors_addr); - PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_copy_keypair_addr(fors_pk_addr, fors_addr); - - PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_set_type(fors_tree_addr, PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_set_type(fors_pk_addr, PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_FORS_TREES; i++) { - idx_offset = i * (1 << PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_FORS_HEIGHT); - - PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_set_tree_height(fors_tree_addr, 0); - PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Derive the leaf from the included secret key part. */ - fors_sk_to_leaf(leaf, sig, pub_seed, fors_tree_addr, state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N; - - /* Derive the corresponding root node of this tree. */ - PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_compute_root(roots + i * PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N, leaf, indices[i], idx_offset, - sig, PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_FORS_HEIGHT, pub_seed, fors_tree_addr, - state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N * PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_thash_FORS_TREES(pk, roots, pub_seed, fors_pk_addr, state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_avx2/fors.h b/src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_avx2/fors.h deleted file mode 100644 index e2cefc8238..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_avx2/fors.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_FORS_H -#define PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_FORS_H - -#include - -#include "hash_state.h" -#include "params.h" - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_fors_sign( - unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *hash_state_seeded); - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_fors_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, const uint32_t fors_addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_avx2/hash.h b/src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_avx2/hash.h deleted file mode 100644 index 857218a193..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_avx2/hash.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_HASH_H -#define PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_HASH_H - -#include "hash_state.h" - -#include -#include - -void PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_initialize_hash_function( - hash_state *hash_state_seeded, - const unsigned char *pub_seed, const unsigned char *sk_seed); - -void PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_destroy_hash_function(hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_avx2/hash_shake256.c b/src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_avx2/hash_shake256.c deleted file mode 100644 index 9fbd642dc8..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_avx2/hash_shake256.c +++ /dev/null @@ -1,106 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "utils.h" - -#include "fips202.h" - -/* For SHAKE256, there is no immediate reason to initialize at the start, - so this function is an empty operation. */ -void PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_initialize_hash_function( - hash_state *hash_state_seeded, // NOLINT(readability-non-const-parameter) - const unsigned char *pub_seed, const unsigned char *sk_seed) { - (void)hash_state_seeded; /* Suppress an 'unused parameter' warning. */ - (void)pub_seed; /* Suppress an 'unused parameter' warning. */ - (void)sk_seed; /* Suppress an 'unused parameter' warning. */ -} - -/* This is not necessary for SHAKE256, so we don't do anything */ -void PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_destroy_hash_function( - hash_state *hash_state_seeded) { // NOLINT(readability-non-const-parameter) - (void)hash_state_seeded; -} - -/* - * Computes PRF(key, addr), given a secret key of PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N bytes and an address - */ -void PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded) { - unsigned char buf[PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_ADDR_BYTES]; - - memcpy(buf, key, PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N); - PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_addr_to_bytes(buf + PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N, addr); - - shake256(out, PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N, buf, PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_ADDR_BYTES); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} - -/** - * Computes the message-dependent randomness R, using a secret seed and an - * optional randomization value as well as the message. - */ -void PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded) { - shake256incctx state; - - shake256_inc_init(&state); - shake256_inc_absorb(&state, sk_prf, PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N); - shake256_inc_absorb(&state, optrand, PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N); - shake256_inc_absorb(&state, m, mlen); - shake256_inc_finalize(&state); - shake256_inc_squeeze(R, PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N, &state); - shake256_inc_ctx_release(&state); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} - -/** - * Computes the message hash using R, the public key, and the message. - * Outputs the message digest and the index of the leaf. The index is split in - * the tree index and the leaf index, for convenient copying to an address. - */ -void PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded) { -#define PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_TREE_BITS (PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_TREE_HEIGHT * (PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_D - 1)) -#define PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_TREE_BYTES ((PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_TREE_BITS + 7) / 8) -#define PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_LEAF_BITS PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_TREE_HEIGHT -#define PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_LEAF_BYTES ((PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_LEAF_BITS + 7) / 8) -#define PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_DGST_BYTES (PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_FORS_MSG_BYTES + PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_TREE_BYTES + PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_LEAF_BYTES) - - unsigned char buf[PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_DGST_BYTES]; - unsigned char *bufp = buf; - shake256incctx state; - - shake256_inc_init(&state); - shake256_inc_absorb(&state, R, PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N); - shake256_inc_absorb(&state, pk, PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_PK_BYTES); - shake256_inc_absorb(&state, m, mlen); - shake256_inc_finalize(&state); - shake256_inc_squeeze(buf, PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_DGST_BYTES, &state); - shake256_inc_ctx_release(&state); - - memcpy(digest, bufp, PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_FORS_MSG_BYTES); - bufp += PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_FORS_MSG_BYTES; - - *tree = PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_bytes_to_ull( - bufp, PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_TREE_BYTES); - *tree &= (~(uint64_t)0) >> (64 - PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_TREE_BITS); - bufp += PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_TREE_BYTES; - - *leaf_idx = (uint32_t)PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_bytes_to_ull( - bufp, PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_LEAF_BYTES); - *leaf_idx &= (~(uint32_t)0) >> (32 - PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_LEAF_BITS); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_avx2/hash_shake256x4.c b/src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_avx2/hash_shake256x4.c deleted file mode 100644 index 362d2c6753..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_avx2/hash_shake256x4.c +++ /dev/null @@ -1,38 +0,0 @@ -#include -#include - -#include "address.h" -#include "fips202x4.h" -#include "hashx4.h" -#include "params.h" - -/* - * 4-way parallel version of prf_addr; takes 4x as much input and output - */ -void PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_prf_addrx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const unsigned char *key, - const uint32_t addrx4[4 * 8], - const hash_state *state_seeded) { - unsigned char bufx4[4 * (PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_ADDR_BYTES)]; - unsigned int j; - - for (j = 0; j < 4; j++) { - memcpy(bufx4 + j * (PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_ADDR_BYTES), key, PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N); - PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_addr_to_bytes(bufx4 + PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N + j * (PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_ADDR_BYTES), addrx4 + j * 8); - } - - PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_shake256x4(out0, - out1, - out2, - out3, PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N, - bufx4 + 0 * (PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_ADDR_BYTES), - bufx4 + 1 * (PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_ADDR_BYTES), - bufx4 + 2 * (PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_ADDR_BYTES), - bufx4 + 3 * (PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_ADDR_BYTES), PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_ADDR_BYTES); - - /* Avoid unused parameter warning */ - (void)state_seeded; -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_avx2/hash_state.h b/src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_avx2/hash_state.h deleted file mode 100644 index ab3b844d2f..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_avx2/hash_state.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_HASH_STATE_H -#define PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_HASH_STATE_H - -/** - * Defines the type of the hash function state. - * - * Don't be fooled into thinking this instance of SPHINCS+ isn't stateless! - * - * From Section 7.2.2 from the SPHINCS+ round-2 specification: - * - * Each of the instances of the tweakable hash function take PK.seed as its - * first input, which is constant for a given key pair – and, thus, across - * a single signature. This leads to a lot of redundant computation. To remedy - * this, we pad PK.seed to the length of a full 64-byte SHA-256 input block. - * Because of the Merkle-Damgård construction that underlies SHA-256, this - * allows for reuse of the intermediate SHA-256 state after the initial call to - * the compression function which improves performance. - * - * We pass this hash state around in functions, because otherwise we need to - * have a global variable. - * - * SHAKE256 does not need this state. Because this implementation is generated - * from a shared code base, we still need to specify some hash_state as it is - * still passed around. We chose to use an `int` as a placeholder for this - * purpose. - */ - -typedef int hash_state; - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_avx2/hashx4.h b/src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_avx2/hashx4.h deleted file mode 100644 index 28df2e8584..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_avx2/hashx4.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_HASHX4_H -#define PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_HASHX4_H - -#include - -#include "hash_state.h" - -void PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_prf_addrx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const unsigned char *key, - const uint32_t addrx4[4 * 8], - const hash_state *state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_avx2/params.h b/src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_avx2/params.h deleted file mode 100644 index 4ac2990618..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_avx2/params.h +++ /dev/null @@ -1,53 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_PARAMS_H -#define PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_PARAMS_H - -/* Hash output length in bytes. */ -#define PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N 32 -/* Height of the hypertree. */ -#define PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_FULL_HEIGHT 64 -/* Number of subtree layer. */ -#define PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_D 8 -/* FORS tree dimensions. */ -#define PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_FORS_HEIGHT 14 -#define PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_FORS_TREES 22 -/* Winternitz parameter, */ -#define PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_WOTS_W 16 - -/* The hash function is defined by linking a different hash.c file, as opposed - to setting a #define constant. */ - -/* For clarity */ -#define PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_ADDR_BYTES 32 - -/* WOTS parameters. */ -#define PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_WOTS_LOGW 4 - -#define PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_WOTS_LEN1 (8 * PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N / PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_WOTS_LOGW) - -/* PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#define PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_WOTS_LEN2 3 - -#define PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_WOTS_LEN (PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_WOTS_LEN1 + PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_WOTS_LEN2) -#define PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_WOTS_BYTES (PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_WOTS_LEN * PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N) -#define PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_WOTS_PK_BYTES PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_WOTS_BYTES - -/* Subtree size. */ -#define PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_TREE_HEIGHT (PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_FULL_HEIGHT / PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_D) - -/* FORS parameters. */ -#define PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_FORS_MSG_BYTES ((PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_FORS_TREES + 7) / 8) -#define PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_FORS_BYTES ((PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_FORS_HEIGHT + 1) * PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_FORS_TREES * PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N) -#define PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_FORS_PK_BYTES PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N - -/* Resulting SPX sizes. */ -#define PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_BYTES (PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_FORS_BYTES + PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_D * PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_WOTS_BYTES +\ - PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_FULL_HEIGHT * PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N) -#define PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_PK_BYTES (2 * PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N) -#define PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_SK_BYTES (2 * PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_PK_BYTES) - -/* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ -#define PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_OPTRAND_BYTES 32 - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_avx2/sign.c b/src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_avx2/sign.c deleted file mode 100644 index 05c9970364..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_avx2/sign.c +++ /dev/null @@ -1,409 +0,0 @@ -#include -#include -#include -#include - -#include "address.h" -#include "api.h" -#include "fors.h" -#include "hash.h" -#include "hash_state.h" -#include "params.h" -#include "randombytes.h" -#include "thash.h" -#include "utils.h" -#include "wots.h" - - -/** - * Computes the leaf at a given address. First generates the WOTS key pair, - * then computes leaf by hashing horizontally. - */ -static void wots_gen_leaf(unsigned char *leaf, const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx, const uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - unsigned char pk[PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_WOTS_BYTES]; - uint32_t wots_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_set_type( - wots_addr, PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_set_type( - wots_pk_addr, PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_ADDR_TYPE_WOTSPK); - - PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_set_keypair_addr( - wots_addr, addr_idx); - PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_wots_gen_pk( - pk, sk_seed, pub_seed, wots_addr, hash_state_seeded); - - PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_copy_keypair_addr( - wots_pk_addr, wots_addr); - PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_thash_WOTS_LEN( - leaf, pk, pub_seed, wots_pk_addr, hash_state_seeded); -} - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_crypto_sign_secretkeybytes(void) { - return PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_CRYPTO_SECRETKEYBYTES; -} - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_crypto_sign_publickeybytes(void) { - return PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_CRYPTO_PUBLICKEYBYTES; -} - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_crypto_sign_bytes(void) { - return PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_CRYPTO_BYTES; -} - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_crypto_sign_seedbytes(void) { - return PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_CRYPTO_SEEDBYTES; -} - -/* - * Generates an SPX key pair given a seed of length - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed) { - /* We do not need the auth path in key generation, but it simplifies the - code to have just one treehash routine that computes both root and path - in one function. */ - unsigned char auth_path[PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_TREE_HEIGHT * PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N]; - uint32_t top_tree_addr[8] = {0}; - hash_state hash_state_seeded; - - PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_set_layer_addr( - top_tree_addr, PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_D - 1); - PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_set_type( - top_tree_addr, PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_ADDR_TYPE_HASHTREE); - - /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ - memcpy(sk, seed, PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_CRYPTO_SEEDBYTES); - - memcpy(pk, sk + 2 * PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N, PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_initialize_hash_function(&hash_state_seeded, pk, sk); - - /* Compute root node of the top-most subtree. */ - PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_treehash_TREE_HEIGHT( - sk + 3 * PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N, auth_path, sk, sk + 2 * PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N, 0, 0, - wots_gen_leaf, top_tree_addr, &hash_state_seeded); - - memcpy(pk + PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N, sk + 3 * PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N, PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N); - - return 0; -} - -/* - * Generates an SPX key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk) { - - // guarantee alignment of pk - union { - __m128 _x[PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_CRYPTO_PUBLICKEYBYTES / 16]; - uint8_t pk[PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_CRYPTO_PUBLICKEYBYTES]; - } aligned_pk; - - // guarantee alignment of sk - union { - __m128 _x[PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_CRYPTO_SECRETKEYBYTES / 16]; - uint8_t sk[PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_CRYPTO_SECRETKEYBYTES]; - } aligned_sk; - - union { - __m128 _x[PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_CRYPTO_SEEDBYTES / 16]; - uint8_t seed[PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_CRYPTO_SEEDBYTES]; - } aligned_seed; - randombytes(aligned_seed.seed, PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_CRYPTO_SEEDBYTES); - - PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_crypto_sign_seed_keypair( - aligned_pk.pk, aligned_sk.sk, aligned_seed.seed); - memcpy(pk, aligned_pk.pk, PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_CRYPTO_PUBLICKEYBYTES); - memcpy(sk, aligned_sk.sk, PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_CRYPTO_SECRETKEYBYTES); - - return 0; -} - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - // guarantee alignment of sk - union { - __m128 *_x; - uint8_t sk[PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_CRYPTO_SECRETKEYBYTES]; - } aligned_sk; - memcpy(aligned_sk.sk, sk, PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_CRYPTO_SECRETKEYBYTES); - sk = aligned_sk.sk; - - // guarantee alignment of sig - union { - __m128 *_x; - uint8_t sig[PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_BYTES]; - } aligned_sig; - uint8_t *orig_sig = sig; - sig = (uint8_t *)aligned_sig.sig; - - const unsigned char *sk_seed = sk; - const unsigned char *sk_prf = sk + PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N; - const unsigned char *pk = sk + 2 * PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N; - const unsigned char *pub_seed = pk; - - unsigned char optrand[PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N]; - unsigned char mhash[PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_FORS_MSG_BYTES]; - unsigned char root[PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N]; - uint32_t i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - - hash_state hash_state_seeded; - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_initialize_hash_function( - &hash_state_seeded, - pub_seed, sk_seed); - - PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_set_type( - wots_addr, PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_set_type( - tree_addr, PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_ADDR_TYPE_HASHTREE); - - /* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ - randombytes(optrand, PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N); - /* Compute the digest randomization value. */ - PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_gen_message_random( - sig, sk_prf, optrand, m, mlen, &hash_state_seeded); - - /* Derive the message digest and leaf index from R, PK and M. */ - PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N; - - PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_set_keypair_addr( - wots_addr, idx_leaf); - - /* Sign the message hash using FORS. */ - PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_fors_sign( - sig, root, mhash, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_FORS_BYTES; - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_D; i++) { - PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_set_tree_addr(tree_addr, tree); - - PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_set_keypair_addr( - wots_addr, idx_leaf); - - /* Compute a WOTS signature. */ - PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_wots_sign( - sig, root, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_WOTS_BYTES; - - /* Compute the authentication path for the used WOTS leaf. */ - PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_treehash_TREE_HEIGHT( - root, sig, sk_seed, pub_seed, idx_leaf, 0, - wots_gen_leaf, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_TREE_HEIGHT * PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_TREE_HEIGHT; - } - - memcpy(orig_sig, aligned_sig.sig, PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_BYTES); - *siglen = PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_BYTES; - - return 0; -} - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk) { - // guarantee alignment of pk - union { - __m128 *_x; - uint8_t pk[PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_CRYPTO_PUBLICKEYBYTES]; - } aligned_pk; - memcpy(aligned_pk.pk, pk, PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_CRYPTO_PUBLICKEYBYTES); - pk = aligned_pk.pk; - - const unsigned char *pub_seed = pk; - const unsigned char *pub_root = pk + PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N; - unsigned char mhash[PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_FORS_MSG_BYTES]; - unsigned char wots_pk[PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_WOTS_BYTES]; - unsigned char root[PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N]; - unsigned char leaf[PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N]; - unsigned int i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - hash_state hash_state_seeded; - - if (siglen != PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_BYTES) { - return -1; - } - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_initialize_hash_function( - &hash_state_seeded, - pub_seed, NULL); - - PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_set_type( - wots_addr, PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_set_type( - tree_addr, PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_ADDR_TYPE_HASHTREE); - PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_set_type( - wots_pk_addr, PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_ADDR_TYPE_WOTSPK); - - /* Derive the message digest and leaf index from R || PK || M. */ - /* The additional PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N is a result of the hash domain separator. */ - PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N; - - /* Layer correctly defaults to 0, so no need to set_layer_addr */ - PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_set_keypair_addr( - wots_addr, idx_leaf); - - PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_fors_pk_from_sig( - root, sig, mhash, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_FORS_BYTES; - - /* For each subtree.. */ - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_D; i++) { - PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_set_tree_addr(tree_addr, tree); - - PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_set_keypair_addr( - wots_addr, idx_leaf); - - PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_copy_keypair_addr( - wots_pk_addr, wots_addr); - - /* The WOTS public key is only correct if the signature was correct. */ - /* Initially, root is the FORS pk, but on subsequent iterations it is - the root of the subtree below the currently processed subtree. */ - PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_wots_pk_from_sig( - wots_pk, sig, root, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_WOTS_BYTES; - - /* Compute the leaf node using the WOTS public key. */ - PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_thash_WOTS_LEN( - leaf, wots_pk, pub_seed, wots_pk_addr, &hash_state_seeded); - - /* Compute the root node of this subtree. */ - PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_compute_root( - root, leaf, idx_leaf, 0, sig, PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_TREE_HEIGHT, - pub_seed, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_TREE_HEIGHT * PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_TREE_HEIGHT; - } - - /* Check if the root node equals the root node in the public key. */ - if (memcmp(root, pub_root, PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N) != 0) { - return -1; - } - - return 0; -} - - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - size_t siglen; - - PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_crypto_sign_signature( - sm, &siglen, m, mlen, sk); - - memmove(sm + PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_BYTES, m, mlen); - *smlen = siglen + mlen; - - return 0; -} - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk) { - - // guarantee alignment of pk - union { - __m128 *_x; - uint8_t pk[PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_CRYPTO_PUBLICKEYBYTES]; - } aligned_pk; - memcpy(aligned_pk.pk, pk, PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_CRYPTO_PUBLICKEYBYTES); - pk = aligned_pk.pk; - - - /* The API caller does not necessarily know what size a signature should be - but SPHINCS+ signatures are always exactly PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_BYTES. */ - if (smlen < PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_BYTES) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - *mlen = smlen - PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_BYTES; - - if (PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_crypto_sign_verify( - sm, PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_BYTES, sm + PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_BYTES, *mlen, pk)) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - /* If verification was successful, move the message to the right place. */ - memmove(m, sm + PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_BYTES, *mlen); - - return 0; -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_avx2/thash.h b/src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_avx2/thash.h deleted file mode 100644 index aad7074d05..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_avx2/thash.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_THASH_H -#define PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_THASH_H - -#include "hash_state.h" - -#include - -void PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_avx2/thash_shake256_robust.c b/src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_avx2/thash_shake256_robust.c deleted file mode 100644 index 3961b5b5c1..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_avx2/thash_shake256_robust.c +++ /dev/null @@ -1,81 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "thash.h" - -#include "fips202.h" - -/** - * Takes an array of inblocks concatenated arrays of PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N bytes. - */ -static void PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_thash( - unsigned char *out, unsigned char *buf, - const unsigned char *in, unsigned int inblocks, - const unsigned char *pub_seed, uint32_t addr[8]) { - - unsigned char *bitmask = buf + PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_ADDR_BYTES; - unsigned int i; - - memcpy(buf, pub_seed, PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N); - PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_addr_to_bytes(buf + PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N, addr); - - shake256(bitmask, inblocks * PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N, buf, PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_ADDR_BYTES); - - for (i = 0; i < inblocks * PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N; i++) { - buf[PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_ADDR_BYTES + i] = in[i] ^ bitmask[i]; - } - - shake256(out, PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N, buf, PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N); -} - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_ADDR_BYTES + 1 * PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N]; - PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_thash( - out, buf, in, 1, pub_seed, addr); - - (void)hash_state_seeded; /* Avoid unused parameter warning. */ -} - -void PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_ADDR_BYTES + 2 * PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N]; - PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_thash( - out, buf, in, 2, pub_seed, addr); - - (void)hash_state_seeded; /* Avoid unused parameter warning. */ -} - -void PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_ADDR_BYTES + PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_WOTS_LEN * PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N]; - PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_thash( - out, buf, in, PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_WOTS_LEN, pub_seed, addr); - - (void)hash_state_seeded; /* Avoid unused parameter warning. */ -} - -void PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_ADDR_BYTES + PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_FORS_TREES * PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N]; - PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_thash( - out, buf, in, PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_FORS_TREES, pub_seed, addr); - - (void)hash_state_seeded; /* Avoid unused parameter warning. */ -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_avx2/thash_shake256_robustx4.c b/src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_avx2/thash_shake256_robustx4.c deleted file mode 100644 index a0e09b8d2b..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_avx2/thash_shake256_robustx4.c +++ /dev/null @@ -1,66 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "thashx4.h" - -#include "fips202x4.h" - -/** - * 4-way parallel version of thash; takes 4x as much input and output - */ -#define thash_variant(name, inblocks) \ - void PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_thashx4_##name(unsigned char *out0, \ - unsigned char *out1, \ - unsigned char *out2, \ - unsigned char *out3, \ - const unsigned char *in0, \ - const unsigned char *in1, \ - const unsigned char *in2, \ - const unsigned char *in3, \ - const unsigned char *pub_seed, uint32_t addrx4[4*8], \ - const hash_state *state_seeded) \ - { \ - unsigned char buf0[PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_ADDR_BYTES + (inblocks)*PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N]; \ - unsigned char buf1[PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_ADDR_BYTES + (inblocks)*PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N]; \ - unsigned char buf2[PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_ADDR_BYTES + (inblocks)*PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N]; \ - unsigned char buf3[PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_ADDR_BYTES + (inblocks)*PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N]; \ - unsigned char bitmask0[(inblocks) * PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N]; \ - unsigned char bitmask1[(inblocks) * PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N]; \ - unsigned char bitmask2[(inblocks) * PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N]; \ - unsigned char bitmask3[(inblocks) * PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N]; \ - unsigned int i; \ - \ - memcpy(buf0, pub_seed, PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N); \ - memcpy(buf1, pub_seed, PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N); \ - memcpy(buf2, pub_seed, PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N); \ - memcpy(buf3, pub_seed, PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N); \ - PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_addr_to_bytes(buf0 + PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N, addrx4 + 0*8); \ - PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_addr_to_bytes(buf1 + PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N, addrx4 + 1*8); \ - PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_addr_to_bytes(buf2 + PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N, addrx4 + 2*8); \ - PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_addr_to_bytes(buf3 + PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N, addrx4 + 3*8); \ - \ - PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_shake256x4(bitmask0, bitmask1, bitmask2, bitmask3, (inblocks) * PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N, \ - buf0, buf1, buf2, buf3, PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_ADDR_BYTES); \ - \ - for (i = 0; i < (inblocks) * PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N; i++) { \ - buf0[PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_ADDR_BYTES + i] = in0[i] ^ bitmask0[i]; \ - buf1[PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_ADDR_BYTES + i] = in1[i] ^ bitmask1[i]; \ - buf2[PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_ADDR_BYTES + i] = in2[i] ^ bitmask2[i]; \ - buf3[PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_ADDR_BYTES + i] = in3[i] ^ bitmask3[i]; \ - } \ - \ - PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_shake256x4( \ - out0, out1, out2, out3, PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N, \ - buf0, buf1, buf2, buf3, PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N + PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_ADDR_BYTES + (inblocks)*PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N); \ - \ - /* avoid unused parameter warning */ \ - (void)state_seeded; \ - } - - -thash_variant(1, 1) -thash_variant(2, 2) -thash_variant(WOTS_LEN, PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_WOTS_LEN) -thash_variant(FORS_TREES, PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_FORS_TREES) diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_avx2/thashx4.h b/src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_avx2/thashx4.h deleted file mode 100644 index 1aecff8ab4..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_avx2/thashx4.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_THASHX4_H -#define PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_THASHX4_H - -#include - -#include "hash_state.h" - -#define thashx4_header(inblocks) \ - void PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_thashx4_##inblocks(unsigned char *out0, \ - unsigned char *out1, \ - unsigned char *out2, \ - unsigned char *out3, \ - const unsigned char *in0, \ - const unsigned char *in1, \ - const unsigned char *in2, \ - const unsigned char *in3, \ - const unsigned char *pub_seed, uint32_t addrx4[4*8], \ - const hash_state *state_seeded) - -thashx4_header(1); -thashx4_header(2); -thashx4_header(WOTS_LEN); -thashx4_header(FORS_TREES); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_avx2/utils.c b/src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_avx2/utils.c deleted file mode 100644 index b269a2e6c3..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_avx2/utils.c +++ /dev/null @@ -1,199 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "hash_state.h" -#include "params.h" -#include "thash.h" -#include "utils.h" - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in) { - - /* Iterate over out in decreasing order, for big-endianness. */ - for (size_t i = outlen; i > 0; i--) { - out[i - 1] = in & 0xff; - in = in >> 8; - } -} - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_bytes_to_ull( - const unsigned char *in, size_t inlen) { - unsigned long long retval = 0; - - for (size_t i = 0; i < inlen; i++) { - retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); - } - return retval; -} - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - uint32_t i; - unsigned char buffer[2 * PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N]; - - /* If leaf_idx is odd (last bit = 1), current path element is a right child - and auth_path has to go left. Otherwise it is the other way around. */ - if (leaf_idx & 1) { - memcpy(buffer + PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N, leaf, PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N); - } else { - memcpy(buffer, leaf, PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N); - memcpy(buffer + PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N, auth_path, PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N); - } - auth_path += PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N; - - for (i = 0; i < tree_height - 1; i++) { - leaf_idx >>= 1; - idx_offset >>= 1; - /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_set_tree_height(addr, i + 1); - PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_set_tree_index( - addr, leaf_idx + idx_offset); - - /* Pick the right or left neighbor, depending on parity of the node. */ - if (leaf_idx & 1) { - PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_thash_2( - buffer + PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N); - } else { - PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_thash_2( - buffer, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer + PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N, auth_path, PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N); - } - auth_path += PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N; - } - - /* The last iteration is exceptional; we do not copy an auth_path node. */ - leaf_idx >>= 1; - idx_offset >>= 1; - PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_set_tree_height(addr, tree_height); - PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_set_tree_index( - addr, leaf_idx + idx_offset); - PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_thash_2( - root, buffer, pub_seed, addr, hash_state_seeded); -} - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -static void PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_treehash( - unsigned char *root, unsigned char *auth_path, - unsigned char *stack, unsigned int *heights, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - - unsigned int offset = 0; - uint32_t idx; - uint32_t tree_idx; - - for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { - /* Add the next leaf node to the stack. */ - gen_leaf(stack + offset * PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N, - sk_seed, pub_seed, idx + idx_offset, tree_addr, - hash_state_seeded); - offset++; - heights[offset - 1] = 0; - - /* If this is a node we need for the auth path.. */ - if ((leaf_idx ^ 0x1) == idx) { - memcpy(auth_path, stack + (offset - 1)*PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N, PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N); - } - - /* While the top-most nodes are of equal height.. */ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { - /* Compute index of the new node, in the next layer. */ - tree_idx = (idx >> (heights[offset - 1] + 1)); - - /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_set_tree_height( - tree_addr, heights[offset - 1] + 1); - PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_set_tree_index( - tree_addr, tree_idx + (idx_offset >> (heights[offset - 1] + 1))); - /* Hash the top-most nodes from the stack together. */ - PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_thash_2( - stack + (offset - 2)*PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N, stack + (offset - 2)*PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N, - pub_seed, tree_addr, hash_state_seeded); - offset--; - /* Note that the top-most node is now one layer higher. */ - heights[offset - 1]++; - - /* If this is a node we need for the auth path.. */ - if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_path + heights[offset - 1]*PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N, - stack + (offset - 1)*PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N, PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N); - } - } - } - memcpy(root, stack, PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N); -} - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_FORS_HEIGHT + 1)*PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N]; - unsigned int heights[PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_FORS_HEIGHT + 1]; - - PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_FORS_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_TREE_HEIGHT + 1)*PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N]; - unsigned int heights[PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_TREE_HEIGHT + 1]; - - PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_TREE_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_avx2/utils.h b/src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_avx2/utils.h deleted file mode 100644 index aa1092a46c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_avx2/utils.h +++ /dev/null @@ -1,64 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_UTILS_H -#define PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_UTILS_H - -#include "hash_state.h" -#include "params.h" -#include -#include - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in); - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_bytes_to_ull( - const unsigned char *in, size_t inlen); - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -void PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_avx2/utilsx4.c b/src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_avx2/utilsx4.c deleted file mode 100644 index 47f2d04150..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_avx2/utilsx4.c +++ /dev/null @@ -1,98 +0,0 @@ -#include "address.h" -#include "params.h" -#include "thashx4.h" -#include "utils.h" -#include "utilsx4.h" - -#include - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -#define treehashx4_variant(name, tree_height) \ - void PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_treehashx4_##name( \ - unsigned char *rootx4, unsigned char *auth_pathx4, const unsigned char *sk_seed, \ - const unsigned char *pub_seed, const uint32_t leaf_idx[4], uint32_t idx_offset[4], \ - void (*gen_leafx4)(unsigned char * /* leaf0 */, unsigned char * /* leaf1 */, \ - unsigned char * /* leaf2 */, unsigned char * /* leaf3 */, \ - const unsigned char * /* sk_seed */, \ - const unsigned char * /* pub_seed */, uint32_t /* addr_idx0 */, \ - uint32_t /* addr_idx1 */, uint32_t /* addr_idx2 */, \ - uint32_t /* addr_idx3 */, const uint32_t[8] /* tree_addr */, \ - const hash_state * /* state_seeded */), \ - uint32_t tree_addrx4[4 * 8], const hash_state *state_seeded) { \ - unsigned char stackx4[4 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N]; \ - unsigned int heights[(tree_height) + 1]; \ - unsigned int offset = 0; \ - uint32_t idx; \ - uint32_t tree_idx; \ - unsigned int j; \ - \ - for (idx = 0; idx < (uint32_t)(1 << (tree_height)); idx++) { \ - /* Add the next leaf node to the stack. */ \ - gen_leafx4(stackx4 + 0 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N + offset * PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N, \ - stackx4 + 1 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N + offset * PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N, \ - stackx4 + 2 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N + offset * PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N, \ - stackx4 + 3 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N + offset * PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N, sk_seed, \ - pub_seed, idx + idx_offset[0], idx + idx_offset[1], idx + idx_offset[2], \ - idx + idx_offset[3], tree_addrx4, state_seeded); \ - offset++; \ - heights[offset - 1] = 0; \ - \ - /* If this is a node we need for the auth path.. */ \ - for (j = 0; j < 4; j++) { \ - if ((leaf_idx[j] ^ 0x1) == idx) { \ - memcpy(auth_pathx4 + j * (tree_height)*PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N, \ - stackx4 + j * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N + (offset - 1) * PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N, \ - PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N); \ - } \ - } \ - \ - /* While the top-most nodes are of equal height.. */ \ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { \ - /* Compute index of the new node, in the next layer. */ \ - tree_idx = (idx >> (heights[offset - 1] + 1)); \ - \ - /* Set the address of the node we're creating. */ \ - for (j = 0; j < 4; j++) { \ - PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_set_tree_height(tree_addrx4 + j * 8, heights[offset - 1] + 1); \ - PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_set_tree_index(tree_addrx4 + j * 8, \ - tree_idx + (idx_offset[j] >> (heights[offset - 1] + 1))); \ - } \ - /* Hash the top-most nodes from the stack together. */ \ - PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_thashx4_2(stackx4 + 0 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N + (offset - 2) * PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N, \ - stackx4 + 1 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N + (offset - 2) * PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N, \ - stackx4 + 2 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N + (offset - 2) * PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N, \ - stackx4 + 3 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N + (offset - 2) * PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N, \ - stackx4 + 0 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N + (offset - 2) * PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N, \ - stackx4 + 1 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N + (offset - 2) * PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N, \ - stackx4 + 2 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N + (offset - 2) * PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N, \ - stackx4 + 3 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N + (offset - 2) * PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N, \ - pub_seed, tree_addrx4, state_seeded); \ - offset--; \ - /* Note that the top-most node is now one layer higher. */ \ - heights[offset - 1]++; \ - \ - /* If this is a node we need for the auth path.. */ \ - for (j = 0; j < 4; j++) { \ - if (((leaf_idx[j] >> heights[offset - 1]) ^ 0x1) == tree_idx) { \ - memcpy(auth_pathx4 + j * (tree_height)*PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N + \ - heights[offset - 1] * PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N, \ - stackx4 + j * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N + (offset - 1) * PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N, \ - PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N); \ - } \ - } \ - } \ - } \ - \ - for (j = 0; j < 4; j++) { \ - memcpy(rootx4 + j * PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N, stackx4 + j * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N, PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N); \ - } \ - } - -treehashx4_variant(FORS_HEIGHT, PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_FORS_HEIGHT) diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_avx2/utilsx4.h b/src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_avx2/utilsx4.h deleted file mode 100644 index d53c593987..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_avx2/utilsx4.h +++ /dev/null @@ -1,38 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_UTILSX4_H -#define PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_UTILSX4_H - -#include "hash_state.h" -#include "params.h" - -#include - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -void PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_treehashx4_FORS_HEIGHT(unsigned char *rootx4, - unsigned char *auth_pathx4, - const unsigned char *sk_seed, - const unsigned char *pub_seed, - const uint32_t leaf_idx[4], - uint32_t idx_offset[4], - void (*gen_leafx4)(unsigned char * /* leaf0 */, - unsigned char * /* leaf1 */, - unsigned char * /* leaf2 */, - unsigned char * /* leaf3 */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx0 */, - uint32_t /* addr_idx1 */, - uint32_t /* addr_idx2 */, - uint32_t /* addr_idx3 */, - const uint32_t[8] /* tree_addr */, - const hash_state * /* state_seeded */), - uint32_t tree_addrx4[4 * 8], - const hash_state *state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_avx2/wots.c b/src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_avx2/wots.c deleted file mode 100644 index 00970a0a10..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_avx2/wots.c +++ /dev/null @@ -1,240 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "hash_state.h" -#include "hashx4.h" -#include "params.h" -#include "thash.h" -#include "thashx4.h" -#include "utils.h" -#include "wots.h" - -// TODO clarify address expectations, and make them more uniform. -// TODO i.e. do we expect types to be set already? -// TODO and do we expect modifications or copies? - -/** - * Computes the starting value for a chain, i.e. the secret key. - * Expects the address to be complete up to the chain address. - */ -static void wots_gen_sk(unsigned char *sk, const unsigned char *sk_seed, - uint32_t wots_addr[8], const hash_state *state_seeded) { - /* Make sure that the hash address is actually zeroed. */ - PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_set_hash_addr(wots_addr, 0); - - /* Generate sk element. */ - PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_prf_addr(sk, sk_seed, wots_addr, state_seeded); -} - -/** - * 4-way parallel version of wots_gen_sk; expects 4x as much space in sk - */ -static void wots_gen_skx4(unsigned char *skx4, const unsigned char *sk_seed, - uint32_t wots_addrx4[4 * 8], const hash_state *state_seeded) { - unsigned int j; - - /* Make sure that the hash address is actually zeroed. */ - for (j = 0; j < 4; j++) { - PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_set_hash_addr(wots_addrx4 + j * 8, 0); - } - - /* Generate sk element. */ - PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_prf_addrx4(skx4 + 0 * PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N, - skx4 + 1 * PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N, - skx4 + 2 * PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N, - skx4 + 3 * PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N, - sk_seed, wots_addrx4, - state_seeded); -} - -/** - * Computes the chaining function. - * out and in have to be n-byte arrays. - * - * Interprets in as start-th value of the chain. - * addr has to contain the address of the chain. - */ -static void gen_chain(unsigned char *out, const unsigned char *in, - unsigned int start, unsigned int steps, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *state_seeded) { - uint32_t i; - - /* Initialize out with the value at position 'start'. */ - memcpy(out, in, PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N); - - /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_WOTS_W; i++) { - PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_set_hash_addr(addr, i); - PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_thash_1(out, out, pub_seed, addr, state_seeded); - } -} - -/** - * 4-way parallel version of gen_chain; expects 4x as much space in out, and - * 4x as much space in inx4. Assumes start and step identical across chains. - */ -static void gen_chainx4(unsigned char *outx4, const unsigned char *inx4, - unsigned int start, unsigned int steps, - const unsigned char *pub_seed, uint32_t addrx4[4 * 8], - const hash_state *state_seeded) { - uint32_t i; - unsigned int j; - - /* Initialize outx4 with the value at position 'start'. */ - memcpy(outx4, inx4, 4 * PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N); - - /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_WOTS_W; i++) { - for (j = 0; j < 4; j++) { - PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_set_hash_addr(addrx4 + j * 8, i); - } - PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_thashx4_1(outx4 + 0 * PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N, - outx4 + 1 * PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N, - outx4 + 2 * PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N, - outx4 + 3 * PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N, - outx4 + 0 * PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N, - outx4 + 1 * PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N, - outx4 + 2 * PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N, - outx4 + 3 * PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N, - pub_seed, addrx4, - state_seeded); - } -} - -/** - * base_w algorithm as described in draft. - * Interprets an array of bytes as integers in base w. - * This only works when log_w is a divisor of 8. - */ -static void base_w(unsigned int *output, const int out_len, const unsigned char *input) { - int in = 0; - int out = 0; - unsigned char total = 0; - int bits = 0; - int consumed; - - for (consumed = 0; consumed < out_len; consumed++) { - if (bits == 0) { - total = input[in]; - in++; - bits += 8; - } - bits -= PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_WOTS_LOGW; - output[out] = (unsigned int)(total >> bits) & (PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_WOTS_W - 1); - out++; - } -} - -/* Computes the WOTS+ checksum over a message (in base_w). */ -static void wots_checksum(unsigned int *csum_base_w, const unsigned int *msg_base_w) { - unsigned int csum = 0; - unsigned char csum_bytes[(PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_WOTS_LEN2 * PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_WOTS_LOGW + 7) / 8]; - unsigned int i; - - /* Compute checksum. */ - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_WOTS_LEN1; i++) { - csum += PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_WOTS_W - 1 - msg_base_w[i]; - } - - /* Convert checksum to base_w. */ - /* Make sure expected empty zero bits are the least significant bits. */ - csum = csum << (8 - ((PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_WOTS_LEN2 * PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_WOTS_LOGW) % 8)); - PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); - base_w(csum_base_w, PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_WOTS_LEN2, csum_bytes); -} - -/* Takes a message and derives the matching chain lengths. */ -static void chain_lengths(unsigned int *lengths, const unsigned char *msg) { - base_w(lengths, PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_WOTS_LEN1, msg); - wots_checksum(lengths + PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_WOTS_LEN1, lengths); -} - -/** - * WOTS key generation. Takes a 32 byte sk_seed, expands it to WOTS private key - * elements and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_wots_gen_pk(unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *state_seeded) { - uint32_t i; - unsigned int j; - - uint32_t addrx4[4 * 8]; - unsigned char pkbuf[4 * PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N]; - - for (j = 0; j < 4; j++) { - memcpy(addrx4 + j * 8, addr, sizeof(uint32_t) * 8); - } - - /* The last iteration typically does not have complete set of 4 chains, - but because we use pkbuf, this is not an issue -- we still do as many - in parallel as possible. */ - for (i = 0; i < ((PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_WOTS_LEN + 3) & ~0x3); i += 4) { - for (j = 0; j < 4; j++) { - PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_set_chain_addr(addrx4 + j * 8, i + j); - } - wots_gen_skx4(pkbuf, sk_seed, addrx4, state_seeded); - gen_chainx4(pkbuf, pkbuf, 0, PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_WOTS_W - 1, pub_seed, addrx4, state_seeded); - for (j = 0; j < 4; j++) { - if (i + j < PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_WOTS_LEN) { - memcpy(pk + (i + j)*PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N, pkbuf + j * PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N, PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N); - } - } - } - - // Get rid of unused argument variable. - (void)state_seeded; -} - -/** - * Takes a n-byte message and the 32-byte sk_see to compute a signature 'sig'. - */ -void PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_wots_sign(unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_WOTS_LEN; i++) { - PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_set_chain_addr(addr, i); - wots_gen_sk(sig + i * PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N, sk_seed, addr, state_seeded); - gen_chain(sig + i * PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N, sig + i * PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N, 0, lengths[i], pub_seed, addr, state_seeded); - } - - // avoid unused argument - (void)state_seeded; -} - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_WOTS_LEN; i++) { - PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_set_chain_addr(addr, i); - gen_chain(pk + i * PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N, sig + i * PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_N, - lengths[i], PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_WOTS_W - 1 - lengths[i], pub_seed, addr, - state_seeded); - } - - // avoid unused argument - (void)state_seeded; -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_avx2/wots.h b/src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_avx2/wots.h deleted file mode 100644 index b2e4d8d5c1..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_avx2/wots.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_WOTS_H -#define PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_WOTS_H - -#include "hash_state.h" -#include "params.h" -#include - -/** - * WOTS key generation. Takes a 32 byte seed for the private key, expands it to - * a full WOTS private key and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_wots_gen_pk( - unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -/** - * Takes a n-byte message and the 32-byte seed for the private key to compute a - * signature that is placed at 'sig'. - */ -void PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_wots_sign( - unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *hash_state_seeded); - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_wots_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_clean/LICENSE b/src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_clean/LICENSE deleted file mode 100644 index 670154e353..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_clean/LICENSE +++ /dev/null @@ -1,116 +0,0 @@ -CC0 1.0 Universal - -Statement of Purpose - -The laws of most jurisdictions throughout the world automatically confer -exclusive Copyright and Related Rights (defined below) upon the creator and -subsequent owner(s) (each and all, an "owner") of an original work of -authorship and/or a database (each, a "Work"). - -Certain owners wish to permanently relinquish those rights to a Work for the -purpose of contributing to a commons of creative, cultural and scientific -works ("Commons") that the public can reliably and without fear of later -claims of infringement build upon, modify, incorporate in other works, reuse -and redistribute as freely as possible in any form whatsoever and for any -purposes, including without limitation commercial purposes. These owners may -contribute to the Commons to promote the ideal of a free culture and the -further production of creative, cultural and scientific works, or to gain -reputation or greater distribution for their Work in part through the use and -efforts of others. - -For these and/or other purposes and motivations, and without any expectation -of additional consideration or compensation, the person associating CC0 with a -Work (the "Affirmer"), to the extent that he or she is an owner of Copyright -and Related Rights in the Work, voluntarily elects to apply CC0 to the Work -and publicly distribute the Work under its terms, with knowledge of his or her -Copyright and Related Rights in the Work and the meaning and intended legal -effect of CC0 on those rights. - -1. Copyright and Related Rights. A Work made available under CC0 may be -protected by copyright and related or neighboring rights ("Copyright and -Related Rights"). Copyright and Related Rights include, but are not limited -to, the following: - - i. the right to reproduce, adapt, distribute, perform, display, communicate, - and translate a Work; - - ii. moral rights retained by the original author(s) and/or performer(s); - - iii. publicity and privacy rights pertaining to a person's image or likeness - depicted in a Work; - - iv. rights protecting against unfair competition in regards to a Work, - subject to the limitations in paragraph 4(a), below; - - v. rights protecting the extraction, dissemination, use and reuse of data in - a Work; - - vi. database rights (such as those arising under Directive 96/9/EC of the - European Parliament and of the Council of 11 March 1996 on the legal - protection of databases, and under any national implementation thereof, - including any amended or successor version of such directive); and - - vii. other similar, equivalent or corresponding rights throughout the world - based on applicable law or treaty, and any national implementations thereof. - -2. Waiver. To the greatest extent permitted by, but not in contravention of, -applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and -unconditionally waives, abandons, and surrenders all of Affirmer's Copyright -and Related Rights and associated claims and causes of action, whether now -known or unknown (including existing as well as future claims and causes of -action), in the Work (i) in all territories worldwide, (ii) for the maximum -duration provided by applicable law or treaty (including future time -extensions), (iii) in any current or future medium and for any number of -copies, and (iv) for any purpose whatsoever, including without limitation -commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes -the Waiver for the benefit of each member of the public at large and to the -detriment of Affirmer's heirs and successors, fully intending that such Waiver -shall not be subject to revocation, rescission, cancellation, termination, or -any other legal or equitable action to disrupt the quiet enjoyment of the Work -by the public as contemplated by Affirmer's express Statement of Purpose. - -3. Public License Fallback. Should any part of the Waiver for any reason be -judged legally invalid or ineffective under applicable law, then the Waiver -shall be preserved to the maximum extent permitted taking into account -Affirmer's express Statement of Purpose. In addition, to the extent the Waiver -is so judged Affirmer hereby grants to each affected person a royalty-free, -non transferable, non sublicensable, non exclusive, irrevocable and -unconditional license to exercise Affirmer's Copyright and Related Rights in -the Work (i) in all territories worldwide, (ii) for the maximum duration -provided by applicable law or treaty (including future time extensions), (iii) -in any current or future medium and for any number of copies, and (iv) for any -purpose whatsoever, including without limitation commercial, advertising or -promotional purposes (the "License"). The License shall be deemed effective as -of the date CC0 was applied by Affirmer to the Work. Should any part of the -License for any reason be judged legally invalid or ineffective under -applicable law, such partial invalidity or ineffectiveness shall not -invalidate the remainder of the License, and in such case Affirmer hereby -affirms that he or she will not (i) exercise any of his or her remaining -Copyright and Related Rights in the Work or (ii) assert any associated claims -and causes of action with respect to the Work, in either case contrary to -Affirmer's express Statement of Purpose. - -4. Limitations and Disclaimers. - - a. No trademark or patent rights held by Affirmer are waived, abandoned, - surrendered, licensed or otherwise affected by this document. - - b. Affirmer offers the Work as-is and makes no representations or warranties - of any kind concerning the Work, express, implied, statutory or otherwise, - including without limitation warranties of title, merchantability, fitness - for a particular purpose, non infringement, or the absence of latent or - other defects, accuracy, or the present or absence of errors, whether or not - discoverable, all to the greatest extent permissible under applicable law. - - c. Affirmer disclaims responsibility for clearing rights of other persons - that may apply to the Work or any use thereof, including without limitation - any person's Copyright and Related Rights in the Work. Further, Affirmer - disclaims responsibility for obtaining any necessary consents, permissions - or other rights required for any use of the Work. - - d. Affirmer understands and acknowledges that Creative Commons is not a - party to this document and has no duty or obligation with respect to this - CC0 or use of the Work. - -For more information, please see - diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_clean/address.c b/src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_clean/address.c deleted file mode 100644 index 87b3586cd5..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_clean/address.c +++ /dev/null @@ -1,78 +0,0 @@ -#include - -#include "address.h" -#include "params.h" -#include "utils.h" - -void PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]) { - int i; - - for (i = 0; i < 8; i++) { - PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_ull_to_bytes( - bytes + i * 4, 4, addr[i]); - } -} - -void PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_set_layer_addr( - uint32_t addr[8], uint32_t layer) { - addr[0] = layer; -} - -void PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_set_tree_addr( - uint32_t addr[8], uint64_t tree) { - addr[1] = 0; - addr[2] = (uint32_t) (tree >> 32); - addr[3] = (uint32_t) tree; -} - -void PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_set_type( - uint32_t addr[8], uint32_t type) { - addr[4] = type; -} - -void PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; -} - -/* These functions are used for OTS addresses. */ - -void PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_set_keypair_addr( - uint32_t addr[8], uint32_t keypair) { - addr[5] = keypair; -} - -void PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; - out[5] = in[5]; -} - -void PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_set_chain_addr( - uint32_t addr[8], uint32_t chain) { - addr[6] = chain; -} - -void PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_set_hash_addr( - uint32_t addr[8], uint32_t hash) { - addr[7] = hash; -} - -/* These functions are used for all hash tree addresses (including FORS). */ - -void PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_set_tree_height( - uint32_t addr[8], uint32_t tree_height) { - addr[6] = tree_height; -} - -void PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_set_tree_index( - uint32_t addr[8], uint32_t tree_index) { - addr[7] = tree_index; -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_clean/address.h b/src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_clean/address.h deleted file mode 100644 index 349c31a5ca..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_clean/address.h +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_ADDRESS_H -#define PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_ADDRESS_H - -#include - -#define PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_ADDR_TYPE_WOTS 0 -#define PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_ADDR_TYPE_WOTSPK 1 -#define PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_ADDR_TYPE_HASHTREE 2 -#define PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_ADDR_TYPE_FORSTREE 3 -#define PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_ADDR_TYPE_FORSPK 4 - -void PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]); - -void PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_set_layer_addr( - uint32_t addr[8], uint32_t layer); - -void PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_set_tree_addr( - uint32_t addr[8], uint64_t tree); - -void PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_set_type( - uint32_t addr[8], uint32_t type); - -/* Copies the layer and tree part of one address into the other */ -void PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for WOTS and FORS addresses. */ - -void PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_set_keypair_addr( - uint32_t addr[8], uint32_t keypair); - -void PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_set_chain_addr( - uint32_t addr[8], uint32_t chain); - -void PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_set_hash_addr( - uint32_t addr[8], uint32_t hash); - -void PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for all hash tree addresses (including FORS). */ - -void PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_set_tree_height( - uint32_t addr[8], uint32_t tree_height); - -void PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_set_tree_index( - uint32_t addr[8], uint32_t tree_index); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_clean/api.h b/src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_clean/api.h deleted file mode 100644 index 5bd36e84e5..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_clean/api.h +++ /dev/null @@ -1,81 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_API_H -#define PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_API_H - -#include -#include - - - -#define PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_CRYPTO_ALGNAME "SPHINCS+" - -#define PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_CRYPTO_SECRETKEYBYTES 128 -#define PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_CRYPTO_PUBLICKEYBYTES 64 -#define PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_CRYPTO_BYTES 29792 -#define PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_CRYPTO_SEEDBYTES 96 - - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_clean/fors.c b/src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_clean/fors.c deleted file mode 100644 index 7419a31c35..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_clean/fors.c +++ /dev/null @@ -1,161 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "fors.h" -#include "hash.h" -#include "hash_state.h" -#include "thash.h" -#include "utils.h" - -static void fors_gen_sk(unsigned char *sk, const unsigned char *sk_seed, - uint32_t fors_leaf_addr[8], const hash_state *hash_state_seeded) { - PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_prf_addr( - sk, sk_seed, fors_leaf_addr, hash_state_seeded); -} - -static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, - const unsigned char *pub_seed, - uint32_t fors_leaf_addr[8], - const hash_state *hash_state_seeded) { - PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_thash_1( - leaf, sk, pub_seed, fors_leaf_addr, hash_state_seeded); -} - -static void fors_gen_leaf(unsigned char *leaf, const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx, const uint32_t fors_tree_addr[8], - const hash_state *hash_state_seeded) { - uint32_t fors_leaf_addr[8] = {0}; - - /* Only copy the parts that must be kept in fors_leaf_addr. */ - PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_copy_keypair_addr( - fors_leaf_addr, fors_tree_addr); - PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_set_type( - fors_leaf_addr, PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_set_tree_index( - fors_leaf_addr, addr_idx); - - fors_gen_sk(leaf, sk_seed, fors_leaf_addr, hash_state_seeded); - fors_sk_to_leaf(leaf, leaf, pub_seed, fors_leaf_addr, hash_state_seeded); -} - -/** - * Interprets m as PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_FORS_HEIGHT-bit unsigned integers. - * Assumes m contains at least PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_FORS_TREES bits. - * Assumes indices has space for PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_FORS_TREES integers. - */ -static void message_to_indices(uint32_t *indices, const unsigned char *m) { - unsigned int i, j; - unsigned int offset = 0; - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_FORS_TREES; i++) { - indices[i] = 0; - for (j = 0; j < PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_FORS_HEIGHT; j++) { - indices[i] ^= (((uint32_t)m[offset >> 3] >> (offset & 0x7)) & 0x1) << j; - offset++; - } - } -} - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_fors_sign( - unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *hash_state_seeded) { - uint32_t indices[PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_FORS_TREES]; - unsigned char roots[PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_FORS_TREES * PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_N]; - uint32_t fors_tree_addr[8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_copy_keypair_addr( - fors_tree_addr, fors_addr); - PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_copy_keypair_addr( - fors_pk_addr, fors_addr); - - PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_set_type( - fors_tree_addr, PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_set_type( - fors_pk_addr, PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_FORS_TREES; i++) { - idx_offset = i * (1 << PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_FORS_HEIGHT); - - PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_set_tree_height( - fors_tree_addr, 0); - PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_set_tree_index( - fors_tree_addr, indices[i] + idx_offset); - - /* Include the secret key part that produces the selected leaf node. */ - fors_gen_sk(sig, sk_seed, fors_tree_addr, hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_N; - - /* Compute the authentication path for this leaf node. */ - PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_treehash_FORS_HEIGHT( - roots + i * PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_N, sig, sk_seed, pub_seed, - indices[i], idx_offset, fors_gen_leaf, fors_tree_addr, - hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_N * PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_thash_FORS_TREES( - pk, roots, pub_seed, fors_pk_addr, hash_state_seeded); -} - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_fors_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, const uint32_t fors_addr[8], - const hash_state *hash_state_seeded) { - uint32_t indices[PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_FORS_TREES]; - unsigned char roots[PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_FORS_TREES * PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_N]; - unsigned char leaf[PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_N]; - uint32_t fors_tree_addr[8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_copy_keypair_addr(fors_tree_addr, fors_addr); - PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_copy_keypair_addr(fors_pk_addr, fors_addr); - - PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_set_type(fors_tree_addr, PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_set_type(fors_pk_addr, PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_FORS_TREES; i++) { - idx_offset = i * (1 << PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_FORS_HEIGHT); - - PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_set_tree_height(fors_tree_addr, 0); - PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Derive the leaf from the included secret key part. */ - fors_sk_to_leaf(leaf, sig, pub_seed, fors_tree_addr, hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_N; - - /* Derive the corresponding root node of this tree. */ - PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_compute_root(roots + i * PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_N, leaf, indices[i], idx_offset, sig, - PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_FORS_HEIGHT, pub_seed, fors_tree_addr, hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_N * PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_thash_FORS_TREES(pk, roots, pub_seed, fors_pk_addr, hash_state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_clean/fors.h b/src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_clean/fors.h deleted file mode 100644 index b685b1e24c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_clean/fors.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_FORS_H -#define PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_FORS_H - -#include - -#include "hash_state.h" -#include "params.h" - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_fors_sign( - unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *hash_state_seeded); - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_fors_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, const uint32_t fors_addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_clean/hash.h b/src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_clean/hash.h deleted file mode 100644 index cf08f30869..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_clean/hash.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_HASH_H -#define PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_HASH_H - -#include "hash_state.h" - -#include -#include - -void PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_initialize_hash_function( - hash_state *hash_state_seeded, - const unsigned char *pub_seed, const unsigned char *sk_seed); - -void PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_destroy_hash_function(hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_clean/hash_shake256.c b/src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_clean/hash_shake256.c deleted file mode 100644 index ebf85a81a3..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_clean/hash_shake256.c +++ /dev/null @@ -1,106 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "utils.h" - -#include "fips202.h" - -/* For SHAKE256, there is no immediate reason to initialize at the start, - so this function is an empty operation. */ -void PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_initialize_hash_function( - hash_state *hash_state_seeded, // NOLINT(readability-non-const-parameter) - const unsigned char *pub_seed, const unsigned char *sk_seed) { - (void)hash_state_seeded; /* Suppress an 'unused parameter' warning. */ - (void)pub_seed; /* Suppress an 'unused parameter' warning. */ - (void)sk_seed; /* Suppress an 'unused parameter' warning. */ -} - -/* This is not necessary for SHAKE256, so we don't do anything */ -void PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_destroy_hash_function( - hash_state *hash_state_seeded) { // NOLINT(readability-non-const-parameter) - (void)hash_state_seeded; -} - -/* - * Computes PRF(key, addr), given a secret key of PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_N bytes and an address - */ -void PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded) { - unsigned char buf[PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_N + PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_ADDR_BYTES]; - - memcpy(buf, key, PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_N); - PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_addr_to_bytes(buf + PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_N, addr); - - shake256(out, PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_N, buf, PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_N + PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_ADDR_BYTES); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} - -/** - * Computes the message-dependent randomness R, using a secret seed and an - * optional randomization value as well as the message. - */ -void PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded) { - shake256incctx state; - - shake256_inc_init(&state); - shake256_inc_absorb(&state, sk_prf, PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_N); - shake256_inc_absorb(&state, optrand, PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_N); - shake256_inc_absorb(&state, m, mlen); - shake256_inc_finalize(&state); - shake256_inc_squeeze(R, PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_N, &state); - shake256_inc_ctx_release(&state); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} - -/** - * Computes the message hash using R, the public key, and the message. - * Outputs the message digest and the index of the leaf. The index is split in - * the tree index and the leaf index, for convenient copying to an address. - */ -void PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded) { -#define PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_TREE_BITS (PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_TREE_HEIGHT * (PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_D - 1)) -#define PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_TREE_BYTES ((PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_TREE_BITS + 7) / 8) -#define PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_LEAF_BITS PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_TREE_HEIGHT -#define PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_LEAF_BYTES ((PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_LEAF_BITS + 7) / 8) -#define PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_DGST_BYTES (PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_FORS_MSG_BYTES + PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_TREE_BYTES + PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_LEAF_BYTES) - - unsigned char buf[PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_DGST_BYTES]; - unsigned char *bufp = buf; - shake256incctx state; - - shake256_inc_init(&state); - shake256_inc_absorb(&state, R, PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_N); - shake256_inc_absorb(&state, pk, PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_PK_BYTES); - shake256_inc_absorb(&state, m, mlen); - shake256_inc_finalize(&state); - shake256_inc_squeeze(buf, PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_DGST_BYTES, &state); - shake256_inc_ctx_release(&state); - - memcpy(digest, bufp, PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_FORS_MSG_BYTES); - bufp += PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_FORS_MSG_BYTES; - - *tree = PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_bytes_to_ull( - bufp, PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_TREE_BYTES); - *tree &= (~(uint64_t)0) >> (64 - PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_TREE_BITS); - bufp += PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_TREE_BYTES; - - *leaf_idx = (uint32_t)PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_bytes_to_ull( - bufp, PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_LEAF_BYTES); - *leaf_idx &= (~(uint32_t)0) >> (32 - PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_LEAF_BITS); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_clean/hash_state.h b/src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_clean/hash_state.h deleted file mode 100644 index 7d92ef872a..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_clean/hash_state.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef SPX_HASH_STATE_H -#define SPX_HASH_STATE_H - -/** - * Defines the type of the hash function state. - * - * Don't be fooled into thinking this instance of SPHINCS+ isn't stateless! - * - * From Section 7.2.2 from the SPHINCS+ round-2 specification: - * - * Each of the instances of the tweakable hash function take PK.seed as its - * first input, which is constant for a given key pair – and, thus, across - * a single signature. This leads to a lot of redundant computation. To remedy - * this, we pad PK.seed to the length of a full 64-byte SHA-256 input block. - * Because of the Merkle-Damgård construction that underlies SHA-256, this - * allows for reuse of the intermediate SHA-256 state after the initial call to - * the compression function which improves performance. - * - * We pass this hash state around in functions, because otherwise we need to - * have a global variable. - * - * SHAKE256 does not need this state. Because this implementation is generated - * from a shared code base, we still need to specify some hash_state as it is - * still passed around. We chose to use an `int` as a placeholder for this - * purpose. - */ - -#define hash_state int - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_clean/params.h b/src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_clean/params.h deleted file mode 100644 index d9beed9b4e..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_clean/params.h +++ /dev/null @@ -1,53 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_PARAMS_H -#define PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_PARAMS_H - -/* Hash output length in bytes. */ -#define PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_N 32 -/* Height of the hypertree. */ -#define PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_FULL_HEIGHT 64 -/* Number of subtree layer. */ -#define PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_D 8 -/* FORS tree dimensions. */ -#define PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_FORS_HEIGHT 14 -#define PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_FORS_TREES 22 -/* Winternitz parameter, */ -#define PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_WOTS_W 16 - -/* The hash function is defined by linking a different hash.c file, as opposed - to setting a #define constant. */ - -/* For clarity */ -#define PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_ADDR_BYTES 32 - -/* WOTS parameters. */ -#define PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_WOTS_LOGW 4 - -#define PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_WOTS_LEN1 (8 * PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_N / PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_WOTS_LOGW) - -/* PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#define PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_WOTS_LEN2 3 - -#define PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_WOTS_LEN (PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_WOTS_LEN1 + PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_WOTS_LEN2) -#define PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_WOTS_BYTES (PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_WOTS_LEN * PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_N) -#define PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_WOTS_PK_BYTES PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_WOTS_BYTES - -/* Subtree size. */ -#define PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_TREE_HEIGHT (PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_FULL_HEIGHT / PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_D) - -/* FORS parameters. */ -#define PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_FORS_MSG_BYTES ((PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_FORS_TREES + 7) / 8) -#define PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_FORS_BYTES ((PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_FORS_HEIGHT + 1) * PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_FORS_TREES * PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_N) -#define PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_FORS_PK_BYTES PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_N - -/* Resulting SPX sizes. */ -#define PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_BYTES (PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_N + PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_FORS_BYTES + PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_D * PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_WOTS_BYTES +\ - PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_FULL_HEIGHT * PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_N) -#define PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_PK_BYTES (2 * PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_N) -#define PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_SK_BYTES (2 * PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_N + PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_PK_BYTES) - -/* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ -#define PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_OPTRAND_BYTES 32 - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_clean/sign.c b/src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_clean/sign.c deleted file mode 100644 index 0492fd49f2..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_clean/sign.c +++ /dev/null @@ -1,356 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "api.h" -#include "fors.h" -#include "hash.h" -#include "hash_state.h" -#include "params.h" -#include "randombytes.h" -#include "thash.h" -#include "utils.h" -#include "wots.h" - -/** - * Computes the leaf at a given address. First generates the WOTS key pair, - * then computes leaf by hashing horizontally. - */ -static void wots_gen_leaf(unsigned char *leaf, const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx, const uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - unsigned char pk[PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_WOTS_BYTES]; - uint32_t wots_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_set_type( - wots_addr, PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_set_type( - wots_pk_addr, PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_ADDR_TYPE_WOTSPK); - - PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_set_keypair_addr( - wots_addr, addr_idx); - PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_wots_gen_pk( - pk, sk_seed, pub_seed, wots_addr, hash_state_seeded); - - PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_copy_keypair_addr( - wots_pk_addr, wots_addr); - PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_thash_WOTS_LEN( - leaf, pk, pub_seed, wots_pk_addr, hash_state_seeded); -} - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_crypto_sign_secretkeybytes(void) { - return PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_CRYPTO_SECRETKEYBYTES; -} - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_crypto_sign_publickeybytes(void) { - return PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_CRYPTO_PUBLICKEYBYTES; -} - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_crypto_sign_bytes(void) { - return PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_CRYPTO_BYTES; -} - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_crypto_sign_seedbytes(void) { - return PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_CRYPTO_SEEDBYTES; -} - -/* - * Generates an SPX key pair given a seed of length - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed) { - /* We do not need the auth path in key generation, but it simplifies the - code to have just one treehash routine that computes both root and path - in one function. */ - unsigned char auth_path[PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_TREE_HEIGHT * PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_N]; - uint32_t top_tree_addr[8] = {0}; - hash_state hash_state_seeded; - - PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_set_layer_addr( - top_tree_addr, PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_D - 1); - PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_set_type( - top_tree_addr, PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_ADDR_TYPE_HASHTREE); - - /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ - memcpy(sk, seed, PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_CRYPTO_SEEDBYTES); - - memcpy(pk, sk + 2 * PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_N, PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_initialize_hash_function(&hash_state_seeded, pk, sk); - - /* Compute root node of the top-most subtree. */ - PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_treehash_TREE_HEIGHT( - sk + 3 * PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_N, auth_path, sk, sk + 2 * PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_N, 0, 0, - wots_gen_leaf, top_tree_addr, &hash_state_seeded); - - memcpy(pk + PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_N, sk + 3 * PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_N, PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_N); - - PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_destroy_hash_function(&hash_state_seeded); - return 0; -} - -/* - * Generates an SPX key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk) { - unsigned char seed[PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_CRYPTO_SEEDBYTES]; - randombytes(seed, PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_CRYPTO_SEEDBYTES); - PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_crypto_sign_seed_keypair( - pk, sk, seed); - - return 0; -} - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - const unsigned char *sk_seed = sk; - const unsigned char *sk_prf = sk + PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_N; - const unsigned char *pk = sk + 2 * PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_N; - const unsigned char *pub_seed = pk; - - unsigned char optrand[PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_N]; - unsigned char mhash[PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_FORS_MSG_BYTES]; - unsigned char root[PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_N]; - uint32_t i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - - hash_state hash_state_seeded; - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_initialize_hash_function( - &hash_state_seeded, - pub_seed, sk_seed); - - PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_set_type( - wots_addr, PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_set_type( - tree_addr, PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_ADDR_TYPE_HASHTREE); - - /* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ - randombytes(optrand, PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_N); - /* Compute the digest randomization value. */ - PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_gen_message_random( - sig, sk_prf, optrand, m, mlen, &hash_state_seeded); - - /* Derive the message digest and leaf index from R, PK and M. */ - PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_N; - - PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); - - /* Sign the message hash using FORS. */ - PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_fors_sign( - sig, root, mhash, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_FORS_BYTES; - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_D; i++) { - PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_set_tree_addr(tree_addr, tree); - - PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); - - /* Compute a WOTS signature. */ - PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_wots_sign( - sig, root, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_WOTS_BYTES; - - /* Compute the authentication path for the used WOTS leaf. */ - PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_treehash_TREE_HEIGHT( - root, sig, sk_seed, pub_seed, idx_leaf, 0, - wots_gen_leaf, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_TREE_HEIGHT * PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_TREE_HEIGHT; - } - - *siglen = PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_BYTES; - - PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_destroy_hash_function(&hash_state_seeded); - return 0; -} - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk) { - const unsigned char *pub_seed = pk; - const unsigned char *pub_root = pk + PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_N; - unsigned char mhash[PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_FORS_MSG_BYTES]; - unsigned char wots_pk[PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_WOTS_BYTES]; - unsigned char root[PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_N]; - unsigned char leaf[PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_N]; - unsigned int i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - hash_state hash_state_seeded; - - if (siglen != PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_BYTES) { - return -1; - } - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_initialize_hash_function( - &hash_state_seeded, - pub_seed, NULL); - - PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_set_type( - wots_addr, PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_set_type( - tree_addr, PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_ADDR_TYPE_HASHTREE); - PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_set_type( - wots_pk_addr, PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_ADDR_TYPE_WOTSPK); - - /* Derive the message digest and leaf index from R || PK || M. */ - /* The additional PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_N is a result of the hash domain separator. */ - PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_N; - - /* Layer correctly defaults to 0, so no need to set_layer_addr */ - PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); - - PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_fors_pk_from_sig( - root, sig, mhash, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_FORS_BYTES; - - /* For each subtree.. */ - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_D; i++) { - PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_set_tree_addr(tree_addr, tree); - - PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); - - PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_copy_keypair_addr( - wots_pk_addr, wots_addr); - - /* The WOTS public key is only correct if the signature was correct. */ - /* Initially, root is the FORS pk, but on subsequent iterations it is - the root of the subtree below the currently processed subtree. */ - PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_wots_pk_from_sig( - wots_pk, sig, root, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_WOTS_BYTES; - - /* Compute the leaf node using the WOTS public key. */ - PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_thash_WOTS_LEN( - leaf, wots_pk, pub_seed, wots_pk_addr, &hash_state_seeded); - - /* Compute the root node of this subtree. */ - PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_compute_root( - root, leaf, idx_leaf, 0, sig, PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_TREE_HEIGHT, - pub_seed, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_TREE_HEIGHT * PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_TREE_HEIGHT; - } - - PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_destroy_hash_function(&hash_state_seeded); - /* Check if the root node equals the root node in the public key. */ - if (memcmp(root, pub_root, PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_N) != 0) { - return -1; - } - - return 0; -} - - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - size_t siglen; - - PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_crypto_sign_signature( - sm, &siglen, m, mlen, sk); - - memmove(sm + PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_BYTES, m, mlen); - *smlen = siglen + mlen; - - return 0; -} - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk) { - /* The API caller does not necessarily know what size a signature should be - but SPHINCS+ signatures are always exactly PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_BYTES. */ - if (smlen < PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_BYTES) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - *mlen = smlen - PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_BYTES; - - if (PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_crypto_sign_verify( - sm, PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_BYTES, sm + PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_BYTES, *mlen, pk)) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - /* If verification was successful, move the message to the right place. */ - memmove(m, sm + PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_BYTES, *mlen); - - return 0; -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_clean/thash.h b/src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_clean/thash.h deleted file mode 100644 index b68830c104..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_clean/thash.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_THASH_H -#define PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_THASH_H - -#include "hash_state.h" - -#include - -void PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_clean/thash_shake256_robust.c b/src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_clean/thash_shake256_robust.c deleted file mode 100644 index bdc8d5ade8..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_clean/thash_shake256_robust.c +++ /dev/null @@ -1,81 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "thash.h" - -#include "fips202.h" - -/** - * Takes an array of inblocks concatenated arrays of PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_N bytes. - */ -static void PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_thash( - unsigned char *out, unsigned char *buf, - const unsigned char *in, unsigned int inblocks, - const unsigned char *pub_seed, uint32_t addr[8]) { - - unsigned char *bitmask = buf + PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_N + PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_ADDR_BYTES; - unsigned int i; - - memcpy(buf, pub_seed, PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_N); - PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_addr_to_bytes(buf + PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_N, addr); - - shake256(bitmask, inblocks * PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_N, buf, PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_N + PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_ADDR_BYTES); - - for (i = 0; i < inblocks * PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_N; i++) { - buf[PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_N + PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_ADDR_BYTES + i] = in[i] ^ bitmask[i]; - } - - shake256(out, PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_N, buf, PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_N + PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_N); -} - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_N + PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_ADDR_BYTES + 1 * PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_N]; - PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_thash( - out, buf, in, 1, pub_seed, addr); - - (void)hash_state_seeded; /* Avoid unused parameter warning. */ -} - -void PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_N + PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_ADDR_BYTES + 2 * PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_N]; - PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_thash( - out, buf, in, 2, pub_seed, addr); - - (void)hash_state_seeded; /* Avoid unused parameter warning. */ -} - -void PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_N + PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_ADDR_BYTES + PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_WOTS_LEN * PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_N]; - PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_thash( - out, buf, in, PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_WOTS_LEN, pub_seed, addr); - - (void)hash_state_seeded; /* Avoid unused parameter warning. */ -} - -void PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_N + PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_ADDR_BYTES + PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_FORS_TREES * PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_N]; - PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_thash( - out, buf, in, PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_FORS_TREES, pub_seed, addr); - - (void)hash_state_seeded; /* Avoid unused parameter warning. */ -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_clean/utils.c b/src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_clean/utils.c deleted file mode 100644 index cf6a98420b..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_clean/utils.c +++ /dev/null @@ -1,199 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "hash_state.h" -#include "params.h" -#include "thash.h" -#include "utils.h" - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in) { - - /* Iterate over out in decreasing order, for big-endianness. */ - for (size_t i = outlen; i > 0; i--) { - out[i - 1] = in & 0xff; - in = in >> 8; - } -} - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_bytes_to_ull( - const unsigned char *in, size_t inlen) { - unsigned long long retval = 0; - - for (size_t i = 0; i < inlen; i++) { - retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); - } - return retval; -} - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - uint32_t i; - unsigned char buffer[2 * PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_N]; - - /* If leaf_idx is odd (last bit = 1), current path element is a right child - and auth_path has to go left. Otherwise it is the other way around. */ - if (leaf_idx & 1) { - memcpy(buffer + PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_N, leaf, PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_N); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_N); - } else { - memcpy(buffer, leaf, PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_N); - memcpy(buffer + PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_N, auth_path, PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_N); - } - auth_path += PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_N; - - for (i = 0; i < tree_height - 1; i++) { - leaf_idx >>= 1; - idx_offset >>= 1; - /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_set_tree_height(addr, i + 1); - PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_set_tree_index( - addr, leaf_idx + idx_offset); - - /* Pick the right or left neighbor, depending on parity of the node. */ - if (leaf_idx & 1) { - PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_thash_2( - buffer + PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_N, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_N); - } else { - PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_thash_2( - buffer, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer + PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_N, auth_path, PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_N); - } - auth_path += PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_N; - } - - /* The last iteration is exceptional; we do not copy an auth_path node. */ - leaf_idx >>= 1; - idx_offset >>= 1; - PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_set_tree_height(addr, tree_height); - PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_set_tree_index( - addr, leaf_idx + idx_offset); - PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_thash_2( - root, buffer, pub_seed, addr, hash_state_seeded); -} - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -static void PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_treehash( - unsigned char *root, unsigned char *auth_path, - unsigned char *stack, unsigned int *heights, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - - unsigned int offset = 0; - uint32_t idx; - uint32_t tree_idx; - - for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { - /* Add the next leaf node to the stack. */ - gen_leaf(stack + offset * PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_N, - sk_seed, pub_seed, idx + idx_offset, tree_addr, - hash_state_seeded); - offset++; - heights[offset - 1] = 0; - - /* If this is a node we need for the auth path.. */ - if ((leaf_idx ^ 0x1) == idx) { - memcpy(auth_path, stack + (offset - 1)*PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_N, PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_N); - } - - /* While the top-most nodes are of equal height.. */ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { - /* Compute index of the new node, in the next layer. */ - tree_idx = (idx >> (heights[offset - 1] + 1)); - - /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_set_tree_height( - tree_addr, heights[offset - 1] + 1); - PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_set_tree_index( - tree_addr, tree_idx + (idx_offset >> (heights[offset - 1] + 1))); - /* Hash the top-most nodes from the stack together. */ - PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_thash_2( - stack + (offset - 2)*PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_N, stack + (offset - 2)*PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_N, - pub_seed, tree_addr, hash_state_seeded); - offset--; - /* Note that the top-most node is now one layer higher. */ - heights[offset - 1]++; - - /* If this is a node we need for the auth path.. */ - if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_path + heights[offset - 1]*PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_N, - stack + (offset - 1)*PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_N, PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_N); - } - } - } - memcpy(root, stack, PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_N); -} - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_FORS_HEIGHT + 1)*PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_N]; - unsigned int heights[PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_FORS_HEIGHT + 1]; - - PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_FORS_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_TREE_HEIGHT + 1)*PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_N]; - unsigned int heights[PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_TREE_HEIGHT + 1]; - - PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_TREE_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_clean/utils.h b/src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_clean/utils.h deleted file mode 100644 index c5f52befb4..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_clean/utils.h +++ /dev/null @@ -1,64 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_UTILS_H -#define PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_UTILS_H - -#include "hash_state.h" -#include "params.h" -#include -#include - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in); - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_bytes_to_ull( - const unsigned char *in, size_t inlen); - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -void PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_clean/wots.c b/src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_clean/wots.c deleted file mode 100644 index 03d8e62f91..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_clean/wots.c +++ /dev/null @@ -1,167 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "hash_state.h" -#include "params.h" -#include "thash.h" -#include "utils.h" -#include "wots.h" - -// TODO clarify address expectations, and make them more uniform. -// TODO i.e. do we expect types to be set already? -// TODO and do we expect modifications or copies? - -/** - * Computes the starting value for a chain, i.e. the secret key. - * Expects the address to be complete up to the chain address. - */ -static void wots_gen_sk(unsigned char *sk, const unsigned char *sk_seed, - uint32_t wots_addr[8], - const hash_state *hash_state_seeded) { - /* Make sure that the hash address is actually zeroed. */ - PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_set_hash_addr(wots_addr, 0); - - /* Generate sk element. */ - PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_prf_addr(sk, sk_seed, wots_addr, hash_state_seeded); -} - -/** - * Computes the chaining function. - * out and in have to be n-byte arrays. - * - * Interprets in as start-th value of the chain. - * addr has to contain the address of the chain. - */ -static void gen_chain(unsigned char *out, const unsigned char *in, - unsigned int start, unsigned int steps, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - uint32_t i; - - /* Initialize out with the value at position 'start'. */ - memcpy(out, in, PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_N); - - /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_WOTS_W; i++) { - PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_set_hash_addr(addr, i); - PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_thash_1( - out, out, pub_seed, addr, hash_state_seeded); - } -} - -/** - * base_w algorithm as described in draft. - * Interprets an array of bytes as integers in base w. - * This only works when log_w is a divisor of 8. - */ -static void base_w(unsigned int *output, const size_t out_len, - const unsigned char *input) { - size_t in = 0; - size_t out = 0; - unsigned char total = 0; - unsigned int bits = 0; - size_t consumed; - - for (consumed = 0; consumed < out_len; consumed++) { - if (bits == 0) { - total = input[in]; - in++; - bits += 8; - } - bits -= PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_WOTS_LOGW; - output[out] = (unsigned int)((total >> bits) & (PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_WOTS_W - 1)); - out++; - } -} - -/* Computes the WOTS+ checksum over a message (in base_w). */ -static void wots_checksum(unsigned int *csum_base_w, - const unsigned int *msg_base_w) { - unsigned int csum = 0; - unsigned char csum_bytes[(PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_WOTS_LEN2 * PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_WOTS_LOGW + 7) / 8]; - unsigned int i; - - /* Compute checksum. */ - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_WOTS_LEN1; i++) { - csum += PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_WOTS_W - 1 - msg_base_w[i]; - } - - /* Convert checksum to base_w. */ - /* Make sure expected empty zero bits are the least significant bits. */ - csum = csum << (8 - ((PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_WOTS_LEN2 * PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_WOTS_LOGW) % 8)); - PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_ull_to_bytes( - csum_bytes, sizeof(csum_bytes), csum); - base_w(csum_base_w, PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_WOTS_LEN2, csum_bytes); -} - -/* Takes a message and derives the matching chain lengths. */ -static void chain_lengths(unsigned int *lengths, const unsigned char *msg) { - base_w(lengths, PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_WOTS_LEN1, msg); - wots_checksum(lengths + PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_WOTS_LEN1, lengths); -} - -/** - * WOTS key generation. Takes a 32 byte sk_seed, expands it to WOTS private key - * elements and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_wots_gen_pk( - unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - uint32_t i; - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_WOTS_LEN; i++) { - PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_set_chain_addr(addr, i); - wots_gen_sk(pk + i * PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_N, sk_seed, addr, hash_state_seeded); - gen_chain(pk + i * PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_N, pk + i * PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_N, - 0, PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_WOTS_W - 1, pub_seed, addr, hash_state_seeded); - } -} - -/** - * Takes a n-byte message and the 32-byte sk_see to compute a signature 'sig'. - */ -void PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_wots_sign( - unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *hash_state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_WOTS_LEN; i++) { - PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_set_chain_addr(addr, i); - wots_gen_sk(sig + i * PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_N, sk_seed, addr, hash_state_seeded); - gen_chain(sig + i * PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_N, sig + i * PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_N, 0, lengths[i], pub_seed, addr, hash_state_seeded); - } -} - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_wots_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_WOTS_LEN; i++) { - PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_set_chain_addr(addr, i); - gen_chain(pk + i * PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_N, sig + i * PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_N, - lengths[i], PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_WOTS_W - 1 - lengths[i], pub_seed, addr, - hash_state_seeded); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_clean/wots.h b/src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_clean/wots.h deleted file mode 100644 index 8332880087..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256s-robust_clean/wots.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_WOTS_H -#define PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_WOTS_H - -#include "hash_state.h" -#include "params.h" -#include - -/** - * WOTS key generation. Takes a 32 byte seed for the private key, expands it to - * a full WOTS private key and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_wots_gen_pk( - unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -/** - * Takes a n-byte message and the 32-byte seed for the private key to compute a - * signature that is placed at 'sig'. - */ -void PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_wots_sign( - unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *hash_state_seeded); - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_wots_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_avx2/LICENSE b/src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_avx2/LICENSE deleted file mode 100644 index 670154e353..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_avx2/LICENSE +++ /dev/null @@ -1,116 +0,0 @@ -CC0 1.0 Universal - -Statement of Purpose - -The laws of most jurisdictions throughout the world automatically confer -exclusive Copyright and Related Rights (defined below) upon the creator and -subsequent owner(s) (each and all, an "owner") of an original work of -authorship and/or a database (each, a "Work"). - -Certain owners wish to permanently relinquish those rights to a Work for the -purpose of contributing to a commons of creative, cultural and scientific -works ("Commons") that the public can reliably and without fear of later -claims of infringement build upon, modify, incorporate in other works, reuse -and redistribute as freely as possible in any form whatsoever and for any -purposes, including without limitation commercial purposes. These owners may -contribute to the Commons to promote the ideal of a free culture and the -further production of creative, cultural and scientific works, or to gain -reputation or greater distribution for their Work in part through the use and -efforts of others. - -For these and/or other purposes and motivations, and without any expectation -of additional consideration or compensation, the person associating CC0 with a -Work (the "Affirmer"), to the extent that he or she is an owner of Copyright -and Related Rights in the Work, voluntarily elects to apply CC0 to the Work -and publicly distribute the Work under its terms, with knowledge of his or her -Copyright and Related Rights in the Work and the meaning and intended legal -effect of CC0 on those rights. - -1. Copyright and Related Rights. A Work made available under CC0 may be -protected by copyright and related or neighboring rights ("Copyright and -Related Rights"). Copyright and Related Rights include, but are not limited -to, the following: - - i. the right to reproduce, adapt, distribute, perform, display, communicate, - and translate a Work; - - ii. moral rights retained by the original author(s) and/or performer(s); - - iii. publicity and privacy rights pertaining to a person's image or likeness - depicted in a Work; - - iv. rights protecting against unfair competition in regards to a Work, - subject to the limitations in paragraph 4(a), below; - - v. rights protecting the extraction, dissemination, use and reuse of data in - a Work; - - vi. database rights (such as those arising under Directive 96/9/EC of the - European Parliament and of the Council of 11 March 1996 on the legal - protection of databases, and under any national implementation thereof, - including any amended or successor version of such directive); and - - vii. other similar, equivalent or corresponding rights throughout the world - based on applicable law or treaty, and any national implementations thereof. - -2. Waiver. To the greatest extent permitted by, but not in contravention of, -applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and -unconditionally waives, abandons, and surrenders all of Affirmer's Copyright -and Related Rights and associated claims and causes of action, whether now -known or unknown (including existing as well as future claims and causes of -action), in the Work (i) in all territories worldwide, (ii) for the maximum -duration provided by applicable law or treaty (including future time -extensions), (iii) in any current or future medium and for any number of -copies, and (iv) for any purpose whatsoever, including without limitation -commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes -the Waiver for the benefit of each member of the public at large and to the -detriment of Affirmer's heirs and successors, fully intending that such Waiver -shall not be subject to revocation, rescission, cancellation, termination, or -any other legal or equitable action to disrupt the quiet enjoyment of the Work -by the public as contemplated by Affirmer's express Statement of Purpose. - -3. Public License Fallback. Should any part of the Waiver for any reason be -judged legally invalid or ineffective under applicable law, then the Waiver -shall be preserved to the maximum extent permitted taking into account -Affirmer's express Statement of Purpose. In addition, to the extent the Waiver -is so judged Affirmer hereby grants to each affected person a royalty-free, -non transferable, non sublicensable, non exclusive, irrevocable and -unconditional license to exercise Affirmer's Copyright and Related Rights in -the Work (i) in all territories worldwide, (ii) for the maximum duration -provided by applicable law or treaty (including future time extensions), (iii) -in any current or future medium and for any number of copies, and (iv) for any -purpose whatsoever, including without limitation commercial, advertising or -promotional purposes (the "License"). The License shall be deemed effective as -of the date CC0 was applied by Affirmer to the Work. Should any part of the -License for any reason be judged legally invalid or ineffective under -applicable law, such partial invalidity or ineffectiveness shall not -invalidate the remainder of the License, and in such case Affirmer hereby -affirms that he or she will not (i) exercise any of his or her remaining -Copyright and Related Rights in the Work or (ii) assert any associated claims -and causes of action with respect to the Work, in either case contrary to -Affirmer's express Statement of Purpose. - -4. Limitations and Disclaimers. - - a. No trademark or patent rights held by Affirmer are waived, abandoned, - surrendered, licensed or otherwise affected by this document. - - b. Affirmer offers the Work as-is and makes no representations or warranties - of any kind concerning the Work, express, implied, statutory or otherwise, - including without limitation warranties of title, merchantability, fitness - for a particular purpose, non infringement, or the absence of latent or - other defects, accuracy, or the present or absence of errors, whether or not - discoverable, all to the greatest extent permissible under applicable law. - - c. Affirmer disclaims responsibility for clearing rights of other persons - that may apply to the Work or any use thereof, including without limitation - any person's Copyright and Related Rights in the Work. Further, Affirmer - disclaims responsibility for obtaining any necessary consents, permissions - or other rights required for any use of the Work. - - d. Affirmer understands and acknowledges that Creative Commons is not a - party to this document and has no duty or obligation with respect to this - CC0 or use of the Work. - -For more information, please see - diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_avx2/address.c b/src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_avx2/address.c deleted file mode 100644 index 74b2ad54b8..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_avx2/address.c +++ /dev/null @@ -1,78 +0,0 @@ -#include - -#include "address.h" -#include "params.h" -#include "utils.h" - -void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]) { - int i; - - for (i = 0; i < 8; i++) { - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_ull_to_bytes( - bytes + i * 4, 4, addr[i]); - } -} - -void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_set_layer_addr( - uint32_t addr[8], uint32_t layer) { - addr[0] = layer; -} - -void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_set_tree_addr( - uint32_t addr[8], uint64_t tree) { - addr[1] = 0; - addr[2] = (uint32_t) (tree >> 32); - addr[3] = (uint32_t) tree; -} - -void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_set_type( - uint32_t addr[8], uint32_t type) { - addr[4] = type; -} - -void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; -} - -/* These functions are used for OTS addresses. */ - -void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_set_keypair_addr( - uint32_t addr[8], uint32_t keypair) { - addr[5] = keypair; -} - -void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; - out[5] = in[5]; -} - -void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_set_chain_addr( - uint32_t addr[8], uint32_t chain) { - addr[6] = chain; -} - -void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_set_hash_addr( - uint32_t addr[8], uint32_t hash) { - addr[7] = hash; -} - -/* These functions are used for all hash tree addresses (including FORS). */ - -void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_set_tree_height( - uint32_t addr[8], uint32_t tree_height) { - addr[6] = tree_height; -} - -void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_set_tree_index( - uint32_t addr[8], uint32_t tree_index) { - addr[7] = tree_index; -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_avx2/address.h b/src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_avx2/address.h deleted file mode 100644 index 30057aab73..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_avx2/address.h +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_ADDRESS_H -#define PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_ADDRESS_H - -#include - -#define PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_ADDR_TYPE_WOTS 0 -#define PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_ADDR_TYPE_WOTSPK 1 -#define PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_ADDR_TYPE_HASHTREE 2 -#define PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_ADDR_TYPE_FORSTREE 3 -#define PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_ADDR_TYPE_FORSPK 4 - -void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]); - -void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_set_layer_addr( - uint32_t addr[8], uint32_t layer); - -void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_set_tree_addr( - uint32_t addr[8], uint64_t tree); - -void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_set_type( - uint32_t addr[8], uint32_t type); - -/* Copies the layer and tree part of one address into the other */ -void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for WOTS and FORS addresses. */ - -void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_set_keypair_addr( - uint32_t addr[8], uint32_t keypair); - -void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_set_chain_addr( - uint32_t addr[8], uint32_t chain); - -void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_set_hash_addr( - uint32_t addr[8], uint32_t hash); - -void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for all hash tree addresses (including FORS). */ - -void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_set_tree_height( - uint32_t addr[8], uint32_t tree_height); - -void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_set_tree_index( - uint32_t addr[8], uint32_t tree_index); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_avx2/api.h b/src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_avx2/api.h deleted file mode 100644 index f478c5ab0e..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_avx2/api.h +++ /dev/null @@ -1,81 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_API_H -#define PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_API_H - -#include -#include - - - -#define PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_CRYPTO_ALGNAME "SPHINCS+" - -#define PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_CRYPTO_SECRETKEYBYTES 128 -#define PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_CRYPTO_PUBLICKEYBYTES 64 -#define PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_CRYPTO_BYTES 29792 -#define PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_CRYPTO_SEEDBYTES 96 - - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_avx2/fors.c b/src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_avx2/fors.c deleted file mode 100644 index a264e02c8a..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_avx2/fors.c +++ /dev/null @@ -1,206 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "fors.h" -#include "hash.h" -#include "hashx4.h" -#include "thash.h" -#include "thashx4.h" -#include "utils.h" -#include "utilsx4.h" - -static void fors_gen_skx4(unsigned char *sk0, - unsigned char *sk1, - unsigned char *sk2, - unsigned char *sk3, const unsigned char *sk_seed, - uint32_t fors_leaf_addrx4[4 * 8], - const hash_state *state_seeded) { - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_prf_addrx4(sk0, sk1, sk2, sk3, sk_seed, fors_leaf_addrx4, state_seeded); -} - -static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, - const unsigned char *pub_seed, - uint32_t fors_leaf_addr[8], const hash_state *state_seeded) { - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_thash_1(leaf, sk, pub_seed, fors_leaf_addr, state_seeded); -} - -static void fors_sk_to_leafx4(unsigned char *leaf0, - unsigned char *leaf1, - unsigned char *leaf2, - unsigned char *leaf3, - const unsigned char *sk0, - const unsigned char *sk1, - const unsigned char *sk2, - const unsigned char *sk3, - const unsigned char *pub_seed, - uint32_t fors_leaf_addrx4[4 * 8], - const hash_state *state_seeded) { - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_thashx4_1(leaf0, leaf1, leaf2, leaf3, - sk0, sk1, sk2, sk3, pub_seed, fors_leaf_addrx4, state_seeded); -} - -static void fors_gen_leafx4(unsigned char *leaf0, - unsigned char *leaf1, - unsigned char *leaf2, - unsigned char *leaf3, - const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx0, - uint32_t addr_idx1, - uint32_t addr_idx2, - uint32_t addr_idx3, - const uint32_t fors_tree_addr[8], - const hash_state *state_seeded) { - uint32_t fors_leaf_addrx4[4 * 8] = {0}; - unsigned int j; - - /* Only copy the parts that must be kept in fors_leaf_addrx4. */ - for (j = 0; j < 4; j++) { - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_copy_keypair_addr(fors_leaf_addrx4 + j * 8, fors_tree_addr); - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_set_type(fors_leaf_addrx4 + j * 8, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_ADDR_TYPE_FORSTREE); - } - - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_set_tree_index(fors_leaf_addrx4 + 0 * 8, addr_idx0); - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_set_tree_index(fors_leaf_addrx4 + 1 * 8, addr_idx1); - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_set_tree_index(fors_leaf_addrx4 + 2 * 8, addr_idx2); - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_set_tree_index(fors_leaf_addrx4 + 3 * 8, addr_idx3); - - fors_gen_skx4(leaf0, leaf1, leaf2, leaf3, sk_seed, fors_leaf_addrx4, state_seeded); - fors_sk_to_leafx4(leaf0, leaf1, leaf2, leaf3, - leaf0, leaf1, leaf2, leaf3, pub_seed, fors_leaf_addrx4, state_seeded); -} - -/** - * Interprets m as PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_FORS_HEIGHT-bit unsigned integers. - * Assumes m contains at least PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_FORS_TREES bits. - * Assumes indices has space for PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_FORS_TREES integers. - */ -static void message_to_indices(uint32_t *indices, const unsigned char *m) { - unsigned int i, j; - unsigned int offset = 0; - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_FORS_TREES; i++) { - indices[i] = 0; - for (j = 0; j < PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_FORS_HEIGHT; j++) { - indices[i] ^= (((uint32_t)m[offset >> 3] >> (offset & 0x7)) & 0x1) << j; - offset++; - } - } -} - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_fors_sign(unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *state_seeded) { - /* Round up to multiple of 4 to prevent out-of-bounds for x4 parallelism */ - uint32_t indices[(PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_FORS_TREES + 3) & ~3] = {0}; - unsigned char roots[((PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_FORS_TREES + 3) & ~3) * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N]; - /* Sign to a buffer, since we may not have a nice multiple of 4 and would - otherwise overrun the signature. */ - unsigned char sigbufx4[4 * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N * (1 + PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_FORS_HEIGHT)]; - uint32_t fors_tree_addrx4[4 * 8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset[4] = {0}; - unsigned int i, j; - - for (j = 0; j < 4; j++) { - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_copy_keypair_addr(fors_tree_addrx4 + j * 8, fors_addr); - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_set_type(fors_tree_addrx4 + j * 8, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_ADDR_TYPE_FORSTREE); - } - - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_copy_keypair_addr(fors_pk_addr, fors_addr); - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_set_type(fors_pk_addr, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < ((PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_FORS_TREES + 3) & ~0x3); i += 4) { - for (j = 0; j < 4; j++) { - if (i + j < PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_FORS_TREES) { - idx_offset[j] = (i + j) * (1 << PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_FORS_HEIGHT); - - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_set_tree_height(fors_tree_addrx4 + j * 8, 0); - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_set_tree_index(fors_tree_addrx4 + j * 8, - indices[i + j] + idx_offset[j]); - } - } - - /* Include the secret key part that produces the selected leaf nodes. */ - fors_gen_skx4(sigbufx4 + 0 * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N, - sigbufx4 + 1 * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N, - sigbufx4 + 2 * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N, - sigbufx4 + 3 * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N, - sk_seed, fors_tree_addrx4, state_seeded); - - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_treehashx4_FORS_HEIGHT(roots + i * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N, sigbufx4 + 4 * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N, sk_seed, pub_seed, - &indices[i], idx_offset, fors_gen_leafx4, fors_tree_addrx4, - state_seeded); - - for (j = 0; j < 4; j++) { - if (i + j < PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_FORS_TREES) { - memcpy(sig, sigbufx4 + j * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N); - memcpy(sig + PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N, - sigbufx4 + 4 * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N + j * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_FORS_HEIGHT, - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_FORS_HEIGHT); - sig += PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N * (1 + PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_FORS_HEIGHT); - } - } - } - - /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_thash_FORS_TREES(pk, roots, pub_seed, fors_pk_addr, state_seeded); -} - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_fors_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, - const uint32_t fors_addr[8], - const hash_state *state_seeded) { - uint32_t indices[PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_FORS_TREES]; - unsigned char roots[PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_FORS_TREES * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N]; - unsigned char leaf[PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N]; - uint32_t fors_tree_addr[8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_copy_keypair_addr(fors_tree_addr, fors_addr); - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_copy_keypair_addr(fors_pk_addr, fors_addr); - - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_set_type(fors_tree_addr, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_set_type(fors_pk_addr, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_FORS_TREES; i++) { - idx_offset = i * (1 << PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_FORS_HEIGHT); - - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_set_tree_height(fors_tree_addr, 0); - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Derive the leaf from the included secret key part. */ - fors_sk_to_leaf(leaf, sig, pub_seed, fors_tree_addr, state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N; - - /* Derive the corresponding root node of this tree. */ - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_compute_root(roots + i * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N, leaf, indices[i], idx_offset, - sig, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_FORS_HEIGHT, pub_seed, fors_tree_addr, - state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_thash_FORS_TREES(pk, roots, pub_seed, fors_pk_addr, state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_avx2/fors.h b/src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_avx2/fors.h deleted file mode 100644 index a96853209e..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_avx2/fors.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_FORS_H -#define PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_FORS_H - -#include - -#include "hash_state.h" -#include "params.h" - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_fors_sign( - unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *hash_state_seeded); - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_fors_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, const uint32_t fors_addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_avx2/hash.h b/src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_avx2/hash.h deleted file mode 100644 index 0b96519ada..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_avx2/hash.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_HASH_H -#define PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_HASH_H - -#include "hash_state.h" - -#include -#include - -void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_initialize_hash_function( - hash_state *hash_state_seeded, - const unsigned char *pub_seed, const unsigned char *sk_seed); - -void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_destroy_hash_function(hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_avx2/hash_shake256.c b/src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_avx2/hash_shake256.c deleted file mode 100644 index 23f34d941c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_avx2/hash_shake256.c +++ /dev/null @@ -1,106 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "utils.h" - -#include "fips202.h" - -/* For SHAKE256, there is no immediate reason to initialize at the start, - so this function is an empty operation. */ -void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_initialize_hash_function( - hash_state *hash_state_seeded, // NOLINT(readability-non-const-parameter) - const unsigned char *pub_seed, const unsigned char *sk_seed) { - (void)hash_state_seeded; /* Suppress an 'unused parameter' warning. */ - (void)pub_seed; /* Suppress an 'unused parameter' warning. */ - (void)sk_seed; /* Suppress an 'unused parameter' warning. */ -} - -/* This is not necessary for SHAKE256, so we don't do anything */ -void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_destroy_hash_function( - hash_state *hash_state_seeded) { // NOLINT(readability-non-const-parameter) - (void)hash_state_seeded; -} - -/* - * Computes PRF(key, addr), given a secret key of PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N bytes and an address - */ -void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded) { - unsigned char buf[PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_ADDR_BYTES]; - - memcpy(buf, key, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N); - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_addr_to_bytes(buf + PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N, addr); - - shake256(out, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N, buf, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_ADDR_BYTES); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} - -/** - * Computes the message-dependent randomness R, using a secret seed and an - * optional randomization value as well as the message. - */ -void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded) { - shake256incctx state; - - shake256_inc_init(&state); - shake256_inc_absorb(&state, sk_prf, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N); - shake256_inc_absorb(&state, optrand, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N); - shake256_inc_absorb(&state, m, mlen); - shake256_inc_finalize(&state); - shake256_inc_squeeze(R, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N, &state); - shake256_inc_ctx_release(&state); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} - -/** - * Computes the message hash using R, the public key, and the message. - * Outputs the message digest and the index of the leaf. The index is split in - * the tree index and the leaf index, for convenient copying to an address. - */ -void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded) { -#define PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_TREE_BITS (PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_TREE_HEIGHT * (PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_D - 1)) -#define PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_TREE_BYTES ((PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_TREE_BITS + 7) / 8) -#define PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_LEAF_BITS PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_TREE_HEIGHT -#define PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_LEAF_BYTES ((PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_LEAF_BITS + 7) / 8) -#define PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_DGST_BYTES (PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_FORS_MSG_BYTES + PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_TREE_BYTES + PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_LEAF_BYTES) - - unsigned char buf[PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_DGST_BYTES]; - unsigned char *bufp = buf; - shake256incctx state; - - shake256_inc_init(&state); - shake256_inc_absorb(&state, R, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N); - shake256_inc_absorb(&state, pk, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_PK_BYTES); - shake256_inc_absorb(&state, m, mlen); - shake256_inc_finalize(&state); - shake256_inc_squeeze(buf, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_DGST_BYTES, &state); - shake256_inc_ctx_release(&state); - - memcpy(digest, bufp, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_FORS_MSG_BYTES); - bufp += PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_FORS_MSG_BYTES; - - *tree = PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_bytes_to_ull( - bufp, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_TREE_BYTES); - *tree &= (~(uint64_t)0) >> (64 - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_TREE_BITS); - bufp += PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_TREE_BYTES; - - *leaf_idx = (uint32_t)PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_bytes_to_ull( - bufp, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_LEAF_BYTES); - *leaf_idx &= (~(uint32_t)0) >> (32 - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_LEAF_BITS); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_avx2/hash_shake256x4.c b/src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_avx2/hash_shake256x4.c deleted file mode 100644 index a4c36572ba..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_avx2/hash_shake256x4.c +++ /dev/null @@ -1,38 +0,0 @@ -#include -#include - -#include "address.h" -#include "fips202x4.h" -#include "hashx4.h" -#include "params.h" - -/* - * 4-way parallel version of prf_addr; takes 4x as much input and output - */ -void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_prf_addrx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const unsigned char *key, - const uint32_t addrx4[4 * 8], - const hash_state *state_seeded) { - unsigned char bufx4[4 * (PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_ADDR_BYTES)]; - unsigned int j; - - for (j = 0; j < 4; j++) { - memcpy(bufx4 + j * (PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_ADDR_BYTES), key, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N); - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_addr_to_bytes(bufx4 + PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N + j * (PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_ADDR_BYTES), addrx4 + j * 8); - } - - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_shake256x4(out0, - out1, - out2, - out3, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N, - bufx4 + 0 * (PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_ADDR_BYTES), - bufx4 + 1 * (PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_ADDR_BYTES), - bufx4 + 2 * (PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_ADDR_BYTES), - bufx4 + 3 * (PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_ADDR_BYTES), PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_ADDR_BYTES); - - /* Avoid unused parameter warning */ - (void)state_seeded; -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_avx2/hash_state.h b/src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_avx2/hash_state.h deleted file mode 100644 index 934fd3b37a..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_avx2/hash_state.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_HASH_STATE_H -#define PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_HASH_STATE_H - -/** - * Defines the type of the hash function state. - * - * Don't be fooled into thinking this instance of SPHINCS+ isn't stateless! - * - * From Section 7.2.2 from the SPHINCS+ round-2 specification: - * - * Each of the instances of the tweakable hash function take PK.seed as its - * first input, which is constant for a given key pair – and, thus, across - * a single signature. This leads to a lot of redundant computation. To remedy - * this, we pad PK.seed to the length of a full 64-byte SHA-256 input block. - * Because of the Merkle-Damgård construction that underlies SHA-256, this - * allows for reuse of the intermediate SHA-256 state after the initial call to - * the compression function which improves performance. - * - * We pass this hash state around in functions, because otherwise we need to - * have a global variable. - * - * SHAKE256 does not need this state. Because this implementation is generated - * from a shared code base, we still need to specify some hash_state as it is - * still passed around. We chose to use an `int` as a placeholder for this - * purpose. - */ - -typedef int hash_state; - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_avx2/hashx4.h b/src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_avx2/hashx4.h deleted file mode 100644 index f2bbfe30c9..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_avx2/hashx4.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_HASHX4_H -#define PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_HASHX4_H - -#include - -#include "hash_state.h" - -void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_prf_addrx4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, - const unsigned char *key, - const uint32_t addrx4[4 * 8], - const hash_state *state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_avx2/params.h b/src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_avx2/params.h deleted file mode 100644 index 992d04311c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_avx2/params.h +++ /dev/null @@ -1,53 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_PARAMS_H -#define PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_PARAMS_H - -/* Hash output length in bytes. */ -#define PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N 32 -/* Height of the hypertree. */ -#define PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_FULL_HEIGHT 64 -/* Number of subtree layer. */ -#define PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_D 8 -/* FORS tree dimensions. */ -#define PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_FORS_HEIGHT 14 -#define PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_FORS_TREES 22 -/* Winternitz parameter, */ -#define PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_WOTS_W 16 - -/* The hash function is defined by linking a different hash.c file, as opposed - to setting a #define constant. */ - -/* For clarity */ -#define PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_ADDR_BYTES 32 - -/* WOTS parameters. */ -#define PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_WOTS_LOGW 4 - -#define PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_WOTS_LEN1 (8 * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N / PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_WOTS_LOGW) - -/* PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#define PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_WOTS_LEN2 3 - -#define PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_WOTS_LEN (PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_WOTS_LEN1 + PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_WOTS_LEN2) -#define PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_WOTS_BYTES (PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_WOTS_LEN * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N) -#define PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_WOTS_PK_BYTES PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_WOTS_BYTES - -/* Subtree size. */ -#define PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_TREE_HEIGHT (PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_FULL_HEIGHT / PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_D) - -/* FORS parameters. */ -#define PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_FORS_MSG_BYTES ((PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_FORS_TREES + 7) / 8) -#define PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_FORS_BYTES ((PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_FORS_HEIGHT + 1) * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_FORS_TREES * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N) -#define PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_FORS_PK_BYTES PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N - -/* Resulting SPX sizes. */ -#define PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_BYTES (PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_FORS_BYTES + PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_D * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_WOTS_BYTES +\ - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_FULL_HEIGHT * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N) -#define PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_PK_BYTES (2 * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N) -#define PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_SK_BYTES (2 * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_PK_BYTES) - -/* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ -#define PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_OPTRAND_BYTES 32 - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_avx2/sign.c b/src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_avx2/sign.c deleted file mode 100644 index d7b43ab060..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_avx2/sign.c +++ /dev/null @@ -1,409 +0,0 @@ -#include -#include -#include -#include - -#include "address.h" -#include "api.h" -#include "fors.h" -#include "hash.h" -#include "hash_state.h" -#include "params.h" -#include "randombytes.h" -#include "thash.h" -#include "utils.h" -#include "wots.h" - - -/** - * Computes the leaf at a given address. First generates the WOTS key pair, - * then computes leaf by hashing horizontally. - */ -static void wots_gen_leaf(unsigned char *leaf, const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx, const uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - unsigned char pk[PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_WOTS_BYTES]; - uint32_t wots_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_set_type( - wots_addr, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_set_type( - wots_pk_addr, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_ADDR_TYPE_WOTSPK); - - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_set_keypair_addr( - wots_addr, addr_idx); - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_wots_gen_pk( - pk, sk_seed, pub_seed, wots_addr, hash_state_seeded); - - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_copy_keypair_addr( - wots_pk_addr, wots_addr); - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_thash_WOTS_LEN( - leaf, pk, pub_seed, wots_pk_addr, hash_state_seeded); -} - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_crypto_sign_secretkeybytes(void) { - return PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_CRYPTO_SECRETKEYBYTES; -} - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_crypto_sign_publickeybytes(void) { - return PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_CRYPTO_PUBLICKEYBYTES; -} - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_crypto_sign_bytes(void) { - return PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_CRYPTO_BYTES; -} - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_crypto_sign_seedbytes(void) { - return PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_CRYPTO_SEEDBYTES; -} - -/* - * Generates an SPX key pair given a seed of length - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed) { - /* We do not need the auth path in key generation, but it simplifies the - code to have just one treehash routine that computes both root and path - in one function. */ - unsigned char auth_path[PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_TREE_HEIGHT * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N]; - uint32_t top_tree_addr[8] = {0}; - hash_state hash_state_seeded; - - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_set_layer_addr( - top_tree_addr, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_D - 1); - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_set_type( - top_tree_addr, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_ADDR_TYPE_HASHTREE); - - /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ - memcpy(sk, seed, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_CRYPTO_SEEDBYTES); - - memcpy(pk, sk + 2 * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_initialize_hash_function(&hash_state_seeded, pk, sk); - - /* Compute root node of the top-most subtree. */ - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_treehash_TREE_HEIGHT( - sk + 3 * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N, auth_path, sk, sk + 2 * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N, 0, 0, - wots_gen_leaf, top_tree_addr, &hash_state_seeded); - - memcpy(pk + PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N, sk + 3 * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N); - - return 0; -} - -/* - * Generates an SPX key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk) { - - // guarantee alignment of pk - union { - __m128 _x[PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_CRYPTO_PUBLICKEYBYTES / 16]; - uint8_t pk[PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_CRYPTO_PUBLICKEYBYTES]; - } aligned_pk; - - // guarantee alignment of sk - union { - __m128 _x[PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_CRYPTO_SECRETKEYBYTES / 16]; - uint8_t sk[PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_CRYPTO_SECRETKEYBYTES]; - } aligned_sk; - - union { - __m128 _x[PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_CRYPTO_SEEDBYTES / 16]; - uint8_t seed[PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_CRYPTO_SEEDBYTES]; - } aligned_seed; - randombytes(aligned_seed.seed, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_CRYPTO_SEEDBYTES); - - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_crypto_sign_seed_keypair( - aligned_pk.pk, aligned_sk.sk, aligned_seed.seed); - memcpy(pk, aligned_pk.pk, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_CRYPTO_PUBLICKEYBYTES); - memcpy(sk, aligned_sk.sk, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_CRYPTO_SECRETKEYBYTES); - - return 0; -} - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - // guarantee alignment of sk - union { - __m128 *_x; - uint8_t sk[PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_CRYPTO_SECRETKEYBYTES]; - } aligned_sk; - memcpy(aligned_sk.sk, sk, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_CRYPTO_SECRETKEYBYTES); - sk = aligned_sk.sk; - - // guarantee alignment of sig - union { - __m128 *_x; - uint8_t sig[PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_BYTES]; - } aligned_sig; - uint8_t *orig_sig = sig; - sig = (uint8_t *)aligned_sig.sig; - - const unsigned char *sk_seed = sk; - const unsigned char *sk_prf = sk + PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N; - const unsigned char *pk = sk + 2 * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N; - const unsigned char *pub_seed = pk; - - unsigned char optrand[PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N]; - unsigned char mhash[PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_FORS_MSG_BYTES]; - unsigned char root[PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N]; - uint32_t i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - - hash_state hash_state_seeded; - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_initialize_hash_function( - &hash_state_seeded, - pub_seed, sk_seed); - - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_set_type( - wots_addr, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_set_type( - tree_addr, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_ADDR_TYPE_HASHTREE); - - /* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ - randombytes(optrand, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N); - /* Compute the digest randomization value. */ - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_gen_message_random( - sig, sk_prf, optrand, m, mlen, &hash_state_seeded); - - /* Derive the message digest and leaf index from R, PK and M. */ - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N; - - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_set_keypair_addr( - wots_addr, idx_leaf); - - /* Sign the message hash using FORS. */ - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_fors_sign( - sig, root, mhash, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_FORS_BYTES; - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_D; i++) { - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_set_tree_addr(tree_addr, tree); - - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_set_keypair_addr( - wots_addr, idx_leaf); - - /* Compute a WOTS signature. */ - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_wots_sign( - sig, root, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_WOTS_BYTES; - - /* Compute the authentication path for the used WOTS leaf. */ - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_treehash_TREE_HEIGHT( - root, sig, sk_seed, pub_seed, idx_leaf, 0, - wots_gen_leaf, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_TREE_HEIGHT * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_TREE_HEIGHT; - } - - memcpy(orig_sig, aligned_sig.sig, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_BYTES); - *siglen = PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_BYTES; - - return 0; -} - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk) { - // guarantee alignment of pk - union { - __m128 *_x; - uint8_t pk[PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_CRYPTO_PUBLICKEYBYTES]; - } aligned_pk; - memcpy(aligned_pk.pk, pk, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_CRYPTO_PUBLICKEYBYTES); - pk = aligned_pk.pk; - - const unsigned char *pub_seed = pk; - const unsigned char *pub_root = pk + PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N; - unsigned char mhash[PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_FORS_MSG_BYTES]; - unsigned char wots_pk[PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_WOTS_BYTES]; - unsigned char root[PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N]; - unsigned char leaf[PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N]; - unsigned int i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - hash_state hash_state_seeded; - - if (siglen != PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_BYTES) { - return -1; - } - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_initialize_hash_function( - &hash_state_seeded, - pub_seed, NULL); - - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_set_type( - wots_addr, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_set_type( - tree_addr, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_ADDR_TYPE_HASHTREE); - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_set_type( - wots_pk_addr, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_ADDR_TYPE_WOTSPK); - - /* Derive the message digest and leaf index from R || PK || M. */ - /* The additional PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N is a result of the hash domain separator. */ - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N; - - /* Layer correctly defaults to 0, so no need to set_layer_addr */ - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_set_keypair_addr( - wots_addr, idx_leaf); - - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_fors_pk_from_sig( - root, sig, mhash, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_FORS_BYTES; - - /* For each subtree.. */ - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_D; i++) { - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_set_tree_addr(tree_addr, tree); - - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_set_keypair_addr( - wots_addr, idx_leaf); - - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_copy_keypair_addr( - wots_pk_addr, wots_addr); - - /* The WOTS public key is only correct if the signature was correct. */ - /* Initially, root is the FORS pk, but on subsequent iterations it is - the root of the subtree below the currently processed subtree. */ - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_wots_pk_from_sig( - wots_pk, sig, root, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_WOTS_BYTES; - - /* Compute the leaf node using the WOTS public key. */ - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_thash_WOTS_LEN( - leaf, wots_pk, pub_seed, wots_pk_addr, &hash_state_seeded); - - /* Compute the root node of this subtree. */ - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_compute_root( - root, leaf, idx_leaf, 0, sig, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_TREE_HEIGHT, - pub_seed, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_TREE_HEIGHT * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_TREE_HEIGHT; - } - - /* Check if the root node equals the root node in the public key. */ - if (memcmp(root, pub_root, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N) != 0) { - return -1; - } - - return 0; -} - - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - size_t siglen; - - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_crypto_sign_signature( - sm, &siglen, m, mlen, sk); - - memmove(sm + PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_BYTES, m, mlen); - *smlen = siglen + mlen; - - return 0; -} - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk) { - - // guarantee alignment of pk - union { - __m128 *_x; - uint8_t pk[PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_CRYPTO_PUBLICKEYBYTES]; - } aligned_pk; - memcpy(aligned_pk.pk, pk, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_CRYPTO_PUBLICKEYBYTES); - pk = aligned_pk.pk; - - - /* The API caller does not necessarily know what size a signature should be - but SPHINCS+ signatures are always exactly PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_BYTES. */ - if (smlen < PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_BYTES) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - *mlen = smlen - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_BYTES; - - if (PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_crypto_sign_verify( - sm, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_BYTES, sm + PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_BYTES, *mlen, pk)) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - /* If verification was successful, move the message to the right place. */ - memmove(m, sm + PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_BYTES, *mlen); - - return 0; -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_avx2/thash.h b/src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_avx2/thash.h deleted file mode 100644 index c3782cb9df..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_avx2/thash.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_THASH_H -#define PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_THASH_H - -#include "hash_state.h" - -#include - -void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_avx2/thash_shake256_simple.c b/src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_avx2/thash_shake256_simple.c deleted file mode 100644 index 632aa39ec9..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_avx2/thash_shake256_simple.c +++ /dev/null @@ -1,74 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash_state.h" -#include "params.h" -#include "thash.h" - -#include "fips202.h" - -/** - * Takes an array of inblocks concatenated arrays of PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N bytes. - */ -static void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_thash( - unsigned char *out, unsigned char *buf, - const unsigned char *in, unsigned int inblocks, - const unsigned char *pub_seed, uint32_t addr[8]) { - - memcpy(buf, pub_seed, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N); - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_addr_to_bytes(buf + PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N, addr); - memcpy(buf + PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_ADDR_BYTES, in, inblocks * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N); - - shake256(out, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N, buf, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N); -} - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_ADDR_BYTES + 1 * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N]; - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_thash( - out, buf, in, 1, pub_seed, addr); - - (void)hash_state_seeded; /* Avoid unused parameter warning. */ -} - -void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_ADDR_BYTES + 2 * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N]; - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_thash( - out, buf, in, 2, pub_seed, addr); - - (void)hash_state_seeded; /* Avoid unused parameter warning. */ -} - -void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_ADDR_BYTES + PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_WOTS_LEN * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N]; - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_thash( - out, buf, in, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_WOTS_LEN, pub_seed, addr); - - (void)hash_state_seeded; /* Avoid unused parameter warning. */ -} - -void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_ADDR_BYTES + PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_FORS_TREES * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N]; - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_thash( - out, buf, in, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_FORS_TREES, pub_seed, addr); - - (void)hash_state_seeded; /* Avoid unused parameter warning. */ -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_avx2/thash_shake256_simplex4.c b/src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_avx2/thash_shake256_simplex4.c deleted file mode 100644 index 6cc6705dff..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_avx2/thash_shake256_simplex4.c +++ /dev/null @@ -1,47 +0,0 @@ -#include -#include - -#include "address.h" -#include "params.h" -#include "thashx4.h" - -#include "fips202x4.h" - -/** - * 4-way parallel version of thash; takes 4x as much input and output - */ -#define thashx4_variant(name, inblocks) \ - void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_thashx4_##name( \ - unsigned char *out0, unsigned char *out1, unsigned char *out2, unsigned char *out3, \ - const unsigned char *in0, const unsigned char *in1, const unsigned char *in2, \ - const unsigned char *in3, const unsigned char *pub_seed, uint32_t addrx4[4 * 8], \ - const hash_state *state_seeded) { \ - unsigned char buf0[PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_ADDR_BYTES + (inblocks)*PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N]; \ - unsigned char buf1[PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_ADDR_BYTES + (inblocks)*PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N]; \ - unsigned char buf2[PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_ADDR_BYTES + (inblocks)*PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N]; \ - unsigned char buf3[PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_ADDR_BYTES + (inblocks)*PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N]; \ - \ - memcpy(buf0, pub_seed, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N); \ - memcpy(buf1, pub_seed, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N); \ - memcpy(buf2, pub_seed, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N); \ - memcpy(buf3, pub_seed, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N); \ - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_addr_to_bytes(buf0 + PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N, addrx4 + 0 * 8); \ - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_addr_to_bytes(buf1 + PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N, addrx4 + 1 * 8); \ - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_addr_to_bytes(buf2 + PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N, addrx4 + 2 * 8); \ - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_addr_to_bytes(buf3 + PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N, addrx4 + 3 * 8); \ - memcpy(buf0 + PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_ADDR_BYTES, in0, (inblocks)*PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N); \ - memcpy(buf1 + PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_ADDR_BYTES, in1, (inblocks)*PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N); \ - memcpy(buf2 + PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_ADDR_BYTES, in2, (inblocks)*PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N); \ - memcpy(buf3 + PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_ADDR_BYTES, in3, (inblocks)*PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N); \ - \ - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_shake256x4(out0, out1, out2, out3, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N, buf0, buf1, buf2, buf3, \ - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N + PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_ADDR_BYTES + (inblocks)*PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N); \ - \ - /* Avoid unused parameter warning */ \ - (void)state_seeded; \ - } - -thashx4_variant(1, 1) -thashx4_variant(2, 2) -thashx4_variant(WOTS_LEN, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_WOTS_LEN) -thashx4_variant(FORS_TREES, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_FORS_TREES) diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_avx2/thashx4.h b/src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_avx2/thashx4.h deleted file mode 100644 index 51f197c15d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_avx2/thashx4.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_THASHX4_H -#define PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_THASHX4_H - -#include - -#include "hash_state.h" - -#define thashx4_header(inblocks) \ - void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_thashx4_##inblocks(unsigned char *out0, \ - unsigned char *out1, \ - unsigned char *out2, \ - unsigned char *out3, \ - const unsigned char *in0, \ - const unsigned char *in1, \ - const unsigned char *in2, \ - const unsigned char *in3, \ - const unsigned char *pub_seed, uint32_t addrx4[4*8], \ - const hash_state *state_seeded) - -thashx4_header(1); -thashx4_header(2); -thashx4_header(WOTS_LEN); -thashx4_header(FORS_TREES); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_avx2/utils.c b/src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_avx2/utils.c deleted file mode 100644 index 9880740de0..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_avx2/utils.c +++ /dev/null @@ -1,199 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "hash_state.h" -#include "params.h" -#include "thash.h" -#include "utils.h" - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in) { - - /* Iterate over out in decreasing order, for big-endianness. */ - for (size_t i = outlen; i > 0; i--) { - out[i - 1] = in & 0xff; - in = in >> 8; - } -} - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_bytes_to_ull( - const unsigned char *in, size_t inlen) { - unsigned long long retval = 0; - - for (size_t i = 0; i < inlen; i++) { - retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); - } - return retval; -} - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - uint32_t i; - unsigned char buffer[2 * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N]; - - /* If leaf_idx is odd (last bit = 1), current path element is a right child - and auth_path has to go left. Otherwise it is the other way around. */ - if (leaf_idx & 1) { - memcpy(buffer + PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N, leaf, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N); - } else { - memcpy(buffer, leaf, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N); - memcpy(buffer + PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N, auth_path, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N); - } - auth_path += PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N; - - for (i = 0; i < tree_height - 1; i++) { - leaf_idx >>= 1; - idx_offset >>= 1; - /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_set_tree_height(addr, i + 1); - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_set_tree_index( - addr, leaf_idx + idx_offset); - - /* Pick the right or left neighbor, depending on parity of the node. */ - if (leaf_idx & 1) { - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_thash_2( - buffer + PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N); - } else { - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_thash_2( - buffer, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer + PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N, auth_path, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N); - } - auth_path += PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N; - } - - /* The last iteration is exceptional; we do not copy an auth_path node. */ - leaf_idx >>= 1; - idx_offset >>= 1; - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_set_tree_height(addr, tree_height); - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_set_tree_index( - addr, leaf_idx + idx_offset); - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_thash_2( - root, buffer, pub_seed, addr, hash_state_seeded); -} - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -static void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_treehash( - unsigned char *root, unsigned char *auth_path, - unsigned char *stack, unsigned int *heights, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - - unsigned int offset = 0; - uint32_t idx; - uint32_t tree_idx; - - for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { - /* Add the next leaf node to the stack. */ - gen_leaf(stack + offset * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N, - sk_seed, pub_seed, idx + idx_offset, tree_addr, - hash_state_seeded); - offset++; - heights[offset - 1] = 0; - - /* If this is a node we need for the auth path.. */ - if ((leaf_idx ^ 0x1) == idx) { - memcpy(auth_path, stack + (offset - 1)*PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N); - } - - /* While the top-most nodes are of equal height.. */ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { - /* Compute index of the new node, in the next layer. */ - tree_idx = (idx >> (heights[offset - 1] + 1)); - - /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_set_tree_height( - tree_addr, heights[offset - 1] + 1); - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_set_tree_index( - tree_addr, tree_idx + (idx_offset >> (heights[offset - 1] + 1))); - /* Hash the top-most nodes from the stack together. */ - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_thash_2( - stack + (offset - 2)*PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N, stack + (offset - 2)*PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N, - pub_seed, tree_addr, hash_state_seeded); - offset--; - /* Note that the top-most node is now one layer higher. */ - heights[offset - 1]++; - - /* If this is a node we need for the auth path.. */ - if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_path + heights[offset - 1]*PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N, - stack + (offset - 1)*PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N); - } - } - } - memcpy(root, stack, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N); -} - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_FORS_HEIGHT + 1)*PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N]; - unsigned int heights[PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_FORS_HEIGHT + 1]; - - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_FORS_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_TREE_HEIGHT + 1)*PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N]; - unsigned int heights[PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_TREE_HEIGHT + 1]; - - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_TREE_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_avx2/utils.h b/src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_avx2/utils.h deleted file mode 100644 index 755ad4a7ff..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_avx2/utils.h +++ /dev/null @@ -1,64 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_UTILS_H -#define PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_UTILS_H - -#include "hash_state.h" -#include "params.h" -#include -#include - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in); - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_bytes_to_ull( - const unsigned char *in, size_t inlen); - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_avx2/utilsx4.c b/src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_avx2/utilsx4.c deleted file mode 100644 index f3dd41e186..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_avx2/utilsx4.c +++ /dev/null @@ -1,98 +0,0 @@ -#include "address.h" -#include "params.h" -#include "thashx4.h" -#include "utils.h" -#include "utilsx4.h" - -#include - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -#define treehashx4_variant(name, tree_height) \ - void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_treehashx4_##name( \ - unsigned char *rootx4, unsigned char *auth_pathx4, const unsigned char *sk_seed, \ - const unsigned char *pub_seed, const uint32_t leaf_idx[4], uint32_t idx_offset[4], \ - void (*gen_leafx4)(unsigned char * /* leaf0 */, unsigned char * /* leaf1 */, \ - unsigned char * /* leaf2 */, unsigned char * /* leaf3 */, \ - const unsigned char * /* sk_seed */, \ - const unsigned char * /* pub_seed */, uint32_t /* addr_idx0 */, \ - uint32_t /* addr_idx1 */, uint32_t /* addr_idx2 */, \ - uint32_t /* addr_idx3 */, const uint32_t[8] /* tree_addr */, \ - const hash_state * /* state_seeded */), \ - uint32_t tree_addrx4[4 * 8], const hash_state *state_seeded) { \ - unsigned char stackx4[4 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N]; \ - unsigned int heights[(tree_height) + 1]; \ - unsigned int offset = 0; \ - uint32_t idx; \ - uint32_t tree_idx; \ - unsigned int j; \ - \ - for (idx = 0; idx < (uint32_t)(1 << (tree_height)); idx++) { \ - /* Add the next leaf node to the stack. */ \ - gen_leafx4(stackx4 + 0 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N + offset * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N, \ - stackx4 + 1 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N + offset * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N, \ - stackx4 + 2 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N + offset * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N, \ - stackx4 + 3 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N + offset * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N, sk_seed, \ - pub_seed, idx + idx_offset[0], idx + idx_offset[1], idx + idx_offset[2], \ - idx + idx_offset[3], tree_addrx4, state_seeded); \ - offset++; \ - heights[offset - 1] = 0; \ - \ - /* If this is a node we need for the auth path.. */ \ - for (j = 0; j < 4; j++) { \ - if ((leaf_idx[j] ^ 0x1) == idx) { \ - memcpy(auth_pathx4 + j * (tree_height)*PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N, \ - stackx4 + j * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N + (offset - 1) * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N, \ - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N); \ - } \ - } \ - \ - /* While the top-most nodes are of equal height.. */ \ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { \ - /* Compute index of the new node, in the next layer. */ \ - tree_idx = (idx >> (heights[offset - 1] + 1)); \ - \ - /* Set the address of the node we're creating. */ \ - for (j = 0; j < 4; j++) { \ - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_set_tree_height(tree_addrx4 + j * 8, heights[offset - 1] + 1); \ - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_set_tree_index(tree_addrx4 + j * 8, \ - tree_idx + (idx_offset[j] >> (heights[offset - 1] + 1))); \ - } \ - /* Hash the top-most nodes from the stack together. */ \ - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_thashx4_2(stackx4 + 0 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N + (offset - 2) * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N, \ - stackx4 + 1 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N + (offset - 2) * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N, \ - stackx4 + 2 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N + (offset - 2) * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N, \ - stackx4 + 3 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N + (offset - 2) * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N, \ - stackx4 + 0 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N + (offset - 2) * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N, \ - stackx4 + 1 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N + (offset - 2) * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N, \ - stackx4 + 2 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N + (offset - 2) * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N, \ - stackx4 + 3 * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N + (offset - 2) * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N, \ - pub_seed, tree_addrx4, state_seeded); \ - offset--; \ - /* Note that the top-most node is now one layer higher. */ \ - heights[offset - 1]++; \ - \ - /* If this is a node we need for the auth path.. */ \ - for (j = 0; j < 4; j++) { \ - if (((leaf_idx[j] >> heights[offset - 1]) ^ 0x1) == tree_idx) { \ - memcpy(auth_pathx4 + j * (tree_height)*PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N + \ - heights[offset - 1] * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N, \ - stackx4 + j * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N + (offset - 1) * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N, \ - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N); \ - } \ - } \ - } \ - } \ - \ - for (j = 0; j < 4; j++) { \ - memcpy(rootx4 + j * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N, stackx4 + j * ((tree_height) + 1) * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N); \ - } \ - } - -treehashx4_variant(FORS_HEIGHT, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_FORS_HEIGHT) diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_avx2/utilsx4.h b/src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_avx2/utilsx4.h deleted file mode 100644 index 5bb8ba421a..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_avx2/utilsx4.h +++ /dev/null @@ -1,38 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_UTILSX4_H -#define PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_UTILSX4_H - -#include "hash_state.h" -#include "params.h" - -#include - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_treehashx4_FORS_HEIGHT(unsigned char *rootx4, - unsigned char *auth_pathx4, - const unsigned char *sk_seed, - const unsigned char *pub_seed, - const uint32_t leaf_idx[4], - uint32_t idx_offset[4], - void (*gen_leafx4)(unsigned char * /* leaf0 */, - unsigned char * /* leaf1 */, - unsigned char * /* leaf2 */, - unsigned char * /* leaf3 */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx0 */, - uint32_t /* addr_idx1 */, - uint32_t /* addr_idx2 */, - uint32_t /* addr_idx3 */, - const uint32_t[8] /* tree_addr */, - const hash_state * /* state_seeded */), - uint32_t tree_addrx4[4 * 8], - const hash_state *state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_avx2/wots.c b/src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_avx2/wots.c deleted file mode 100644 index 1d05315afa..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_avx2/wots.c +++ /dev/null @@ -1,240 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "hash_state.h" -#include "hashx4.h" -#include "params.h" -#include "thash.h" -#include "thashx4.h" -#include "utils.h" -#include "wots.h" - -// TODO clarify address expectations, and make them more uniform. -// TODO i.e. do we expect types to be set already? -// TODO and do we expect modifications or copies? - -/** - * Computes the starting value for a chain, i.e. the secret key. - * Expects the address to be complete up to the chain address. - */ -static void wots_gen_sk(unsigned char *sk, const unsigned char *sk_seed, - uint32_t wots_addr[8], const hash_state *state_seeded) { - /* Make sure that the hash address is actually zeroed. */ - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_set_hash_addr(wots_addr, 0); - - /* Generate sk element. */ - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_prf_addr(sk, sk_seed, wots_addr, state_seeded); -} - -/** - * 4-way parallel version of wots_gen_sk; expects 4x as much space in sk - */ -static void wots_gen_skx4(unsigned char *skx4, const unsigned char *sk_seed, - uint32_t wots_addrx4[4 * 8], const hash_state *state_seeded) { - unsigned int j; - - /* Make sure that the hash address is actually zeroed. */ - for (j = 0; j < 4; j++) { - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_set_hash_addr(wots_addrx4 + j * 8, 0); - } - - /* Generate sk element. */ - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_prf_addrx4(skx4 + 0 * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N, - skx4 + 1 * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N, - skx4 + 2 * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N, - skx4 + 3 * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N, - sk_seed, wots_addrx4, - state_seeded); -} - -/** - * Computes the chaining function. - * out and in have to be n-byte arrays. - * - * Interprets in as start-th value of the chain. - * addr has to contain the address of the chain. - */ -static void gen_chain(unsigned char *out, const unsigned char *in, - unsigned int start, unsigned int steps, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *state_seeded) { - uint32_t i; - - /* Initialize out with the value at position 'start'. */ - memcpy(out, in, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N); - - /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_WOTS_W; i++) { - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_set_hash_addr(addr, i); - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_thash_1(out, out, pub_seed, addr, state_seeded); - } -} - -/** - * 4-way parallel version of gen_chain; expects 4x as much space in out, and - * 4x as much space in inx4. Assumes start and step identical across chains. - */ -static void gen_chainx4(unsigned char *outx4, const unsigned char *inx4, - unsigned int start, unsigned int steps, - const unsigned char *pub_seed, uint32_t addrx4[4 * 8], - const hash_state *state_seeded) { - uint32_t i; - unsigned int j; - - /* Initialize outx4 with the value at position 'start'. */ - memcpy(outx4, inx4, 4 * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N); - - /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_WOTS_W; i++) { - for (j = 0; j < 4; j++) { - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_set_hash_addr(addrx4 + j * 8, i); - } - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_thashx4_1(outx4 + 0 * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N, - outx4 + 1 * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N, - outx4 + 2 * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N, - outx4 + 3 * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N, - outx4 + 0 * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N, - outx4 + 1 * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N, - outx4 + 2 * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N, - outx4 + 3 * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N, - pub_seed, addrx4, - state_seeded); - } -} - -/** - * base_w algorithm as described in draft. - * Interprets an array of bytes as integers in base w. - * This only works when log_w is a divisor of 8. - */ -static void base_w(unsigned int *output, const int out_len, const unsigned char *input) { - int in = 0; - int out = 0; - unsigned char total = 0; - int bits = 0; - int consumed; - - for (consumed = 0; consumed < out_len; consumed++) { - if (bits == 0) { - total = input[in]; - in++; - bits += 8; - } - bits -= PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_WOTS_LOGW; - output[out] = (unsigned int)(total >> bits) & (PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_WOTS_W - 1); - out++; - } -} - -/* Computes the WOTS+ checksum over a message (in base_w). */ -static void wots_checksum(unsigned int *csum_base_w, const unsigned int *msg_base_w) { - unsigned int csum = 0; - unsigned char csum_bytes[(PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_WOTS_LEN2 * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_WOTS_LOGW + 7) / 8]; - unsigned int i; - - /* Compute checksum. */ - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_WOTS_LEN1; i++) { - csum += PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_WOTS_W - 1 - msg_base_w[i]; - } - - /* Convert checksum to base_w. */ - /* Make sure expected empty zero bits are the least significant bits. */ - csum = csum << (8 - ((PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_WOTS_LEN2 * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_WOTS_LOGW) % 8)); - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum); - base_w(csum_base_w, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_WOTS_LEN2, csum_bytes); -} - -/* Takes a message and derives the matching chain lengths. */ -static void chain_lengths(unsigned int *lengths, const unsigned char *msg) { - base_w(lengths, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_WOTS_LEN1, msg); - wots_checksum(lengths + PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_WOTS_LEN1, lengths); -} - -/** - * WOTS key generation. Takes a 32 byte sk_seed, expands it to WOTS private key - * elements and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_wots_gen_pk(unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *state_seeded) { - uint32_t i; - unsigned int j; - - uint32_t addrx4[4 * 8]; - unsigned char pkbuf[4 * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N]; - - for (j = 0; j < 4; j++) { - memcpy(addrx4 + j * 8, addr, sizeof(uint32_t) * 8); - } - - /* The last iteration typically does not have complete set of 4 chains, - but because we use pkbuf, this is not an issue -- we still do as many - in parallel as possible. */ - for (i = 0; i < ((PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_WOTS_LEN + 3) & ~0x3); i += 4) { - for (j = 0; j < 4; j++) { - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_set_chain_addr(addrx4 + j * 8, i + j); - } - wots_gen_skx4(pkbuf, sk_seed, addrx4, state_seeded); - gen_chainx4(pkbuf, pkbuf, 0, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_WOTS_W - 1, pub_seed, addrx4, state_seeded); - for (j = 0; j < 4; j++) { - if (i + j < PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_WOTS_LEN) { - memcpy(pk + (i + j)*PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N, pkbuf + j * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N); - } - } - } - - // Get rid of unused argument variable. - (void)state_seeded; -} - -/** - * Takes a n-byte message and the 32-byte sk_see to compute a signature 'sig'. - */ -void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_wots_sign(unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_WOTS_LEN; i++) { - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_set_chain_addr(addr, i); - wots_gen_sk(sig + i * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N, sk_seed, addr, state_seeded); - gen_chain(sig + i * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N, sig + i * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N, 0, lengths[i], pub_seed, addr, state_seeded); - } - - // avoid unused argument - (void)state_seeded; -} - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_wots_pk_from_sig(unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_WOTS_LEN; i++) { - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_set_chain_addr(addr, i); - gen_chain(pk + i * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N, sig + i * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_N, - lengths[i], PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_WOTS_W - 1 - lengths[i], pub_seed, addr, - state_seeded); - } - - // avoid unused argument - (void)state_seeded; -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_avx2/wots.h b/src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_avx2/wots.h deleted file mode 100644 index f599671b1d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_avx2/wots.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_WOTS_H -#define PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_WOTS_H - -#include "hash_state.h" -#include "params.h" -#include - -/** - * WOTS key generation. Takes a 32 byte seed for the private key, expands it to - * a full WOTS private key and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_wots_gen_pk( - unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -/** - * Takes a n-byte message and the 32-byte seed for the private key to compute a - * signature that is placed at 'sig'. - */ -void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_wots_sign( - unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *hash_state_seeded); - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_wots_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_clean/LICENSE b/src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_clean/LICENSE deleted file mode 100644 index 670154e353..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_clean/LICENSE +++ /dev/null @@ -1,116 +0,0 @@ -CC0 1.0 Universal - -Statement of Purpose - -The laws of most jurisdictions throughout the world automatically confer -exclusive Copyright and Related Rights (defined below) upon the creator and -subsequent owner(s) (each and all, an "owner") of an original work of -authorship and/or a database (each, a "Work"). - -Certain owners wish to permanently relinquish those rights to a Work for the -purpose of contributing to a commons of creative, cultural and scientific -works ("Commons") that the public can reliably and without fear of later -claims of infringement build upon, modify, incorporate in other works, reuse -and redistribute as freely as possible in any form whatsoever and for any -purposes, including without limitation commercial purposes. These owners may -contribute to the Commons to promote the ideal of a free culture and the -further production of creative, cultural and scientific works, or to gain -reputation or greater distribution for their Work in part through the use and -efforts of others. - -For these and/or other purposes and motivations, and without any expectation -of additional consideration or compensation, the person associating CC0 with a -Work (the "Affirmer"), to the extent that he or she is an owner of Copyright -and Related Rights in the Work, voluntarily elects to apply CC0 to the Work -and publicly distribute the Work under its terms, with knowledge of his or her -Copyright and Related Rights in the Work and the meaning and intended legal -effect of CC0 on those rights. - -1. Copyright and Related Rights. A Work made available under CC0 may be -protected by copyright and related or neighboring rights ("Copyright and -Related Rights"). Copyright and Related Rights include, but are not limited -to, the following: - - i. the right to reproduce, adapt, distribute, perform, display, communicate, - and translate a Work; - - ii. moral rights retained by the original author(s) and/or performer(s); - - iii. publicity and privacy rights pertaining to a person's image or likeness - depicted in a Work; - - iv. rights protecting against unfair competition in regards to a Work, - subject to the limitations in paragraph 4(a), below; - - v. rights protecting the extraction, dissemination, use and reuse of data in - a Work; - - vi. database rights (such as those arising under Directive 96/9/EC of the - European Parliament and of the Council of 11 March 1996 on the legal - protection of databases, and under any national implementation thereof, - including any amended or successor version of such directive); and - - vii. other similar, equivalent or corresponding rights throughout the world - based on applicable law or treaty, and any national implementations thereof. - -2. Waiver. To the greatest extent permitted by, but not in contravention of, -applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and -unconditionally waives, abandons, and surrenders all of Affirmer's Copyright -and Related Rights and associated claims and causes of action, whether now -known or unknown (including existing as well as future claims and causes of -action), in the Work (i) in all territories worldwide, (ii) for the maximum -duration provided by applicable law or treaty (including future time -extensions), (iii) in any current or future medium and for any number of -copies, and (iv) for any purpose whatsoever, including without limitation -commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes -the Waiver for the benefit of each member of the public at large and to the -detriment of Affirmer's heirs and successors, fully intending that such Waiver -shall not be subject to revocation, rescission, cancellation, termination, or -any other legal or equitable action to disrupt the quiet enjoyment of the Work -by the public as contemplated by Affirmer's express Statement of Purpose. - -3. Public License Fallback. Should any part of the Waiver for any reason be -judged legally invalid or ineffective under applicable law, then the Waiver -shall be preserved to the maximum extent permitted taking into account -Affirmer's express Statement of Purpose. In addition, to the extent the Waiver -is so judged Affirmer hereby grants to each affected person a royalty-free, -non transferable, non sublicensable, non exclusive, irrevocable and -unconditional license to exercise Affirmer's Copyright and Related Rights in -the Work (i) in all territories worldwide, (ii) for the maximum duration -provided by applicable law or treaty (including future time extensions), (iii) -in any current or future medium and for any number of copies, and (iv) for any -purpose whatsoever, including without limitation commercial, advertising or -promotional purposes (the "License"). The License shall be deemed effective as -of the date CC0 was applied by Affirmer to the Work. Should any part of the -License for any reason be judged legally invalid or ineffective under -applicable law, such partial invalidity or ineffectiveness shall not -invalidate the remainder of the License, and in such case Affirmer hereby -affirms that he or she will not (i) exercise any of his or her remaining -Copyright and Related Rights in the Work or (ii) assert any associated claims -and causes of action with respect to the Work, in either case contrary to -Affirmer's express Statement of Purpose. - -4. Limitations and Disclaimers. - - a. No trademark or patent rights held by Affirmer are waived, abandoned, - surrendered, licensed or otherwise affected by this document. - - b. Affirmer offers the Work as-is and makes no representations or warranties - of any kind concerning the Work, express, implied, statutory or otherwise, - including without limitation warranties of title, merchantability, fitness - for a particular purpose, non infringement, or the absence of latent or - other defects, accuracy, or the present or absence of errors, whether or not - discoverable, all to the greatest extent permissible under applicable law. - - c. Affirmer disclaims responsibility for clearing rights of other persons - that may apply to the Work or any use thereof, including without limitation - any person's Copyright and Related Rights in the Work. Further, Affirmer - disclaims responsibility for obtaining any necessary consents, permissions - or other rights required for any use of the Work. - - d. Affirmer understands and acknowledges that Creative Commons is not a - party to this document and has no duty or obligation with respect to this - CC0 or use of the Work. - -For more information, please see - diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_clean/address.c b/src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_clean/address.c deleted file mode 100644 index 5e16da61d1..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_clean/address.c +++ /dev/null @@ -1,78 +0,0 @@ -#include - -#include "address.h" -#include "params.h" -#include "utils.h" - -void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]) { - int i; - - for (i = 0; i < 8; i++) { - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_ull_to_bytes( - bytes + i * 4, 4, addr[i]); - } -} - -void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_set_layer_addr( - uint32_t addr[8], uint32_t layer) { - addr[0] = layer; -} - -void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_set_tree_addr( - uint32_t addr[8], uint64_t tree) { - addr[1] = 0; - addr[2] = (uint32_t) (tree >> 32); - addr[3] = (uint32_t) tree; -} - -void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_set_type( - uint32_t addr[8], uint32_t type) { - addr[4] = type; -} - -void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; -} - -/* These functions are used for OTS addresses. */ - -void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_set_keypair_addr( - uint32_t addr[8], uint32_t keypair) { - addr[5] = keypair; -} - -void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; - out[5] = in[5]; -} - -void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_set_chain_addr( - uint32_t addr[8], uint32_t chain) { - addr[6] = chain; -} - -void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_set_hash_addr( - uint32_t addr[8], uint32_t hash) { - addr[7] = hash; -} - -/* These functions are used for all hash tree addresses (including FORS). */ - -void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_set_tree_height( - uint32_t addr[8], uint32_t tree_height) { - addr[6] = tree_height; -} - -void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_set_tree_index( - uint32_t addr[8], uint32_t tree_index) { - addr[7] = tree_index; -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_clean/address.h b/src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_clean/address.h deleted file mode 100644 index bd3d16c6c1..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_clean/address.h +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_ADDRESS_H -#define PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_ADDRESS_H - -#include - -#define PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_ADDR_TYPE_WOTS 0 -#define PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_ADDR_TYPE_WOTSPK 1 -#define PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_ADDR_TYPE_HASHTREE 2 -#define PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_ADDR_TYPE_FORSTREE 3 -#define PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_ADDR_TYPE_FORSPK 4 - -void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_addr_to_bytes( - unsigned char *bytes, const uint32_t addr[8]); - -void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_set_layer_addr( - uint32_t addr[8], uint32_t layer); - -void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_set_tree_addr( - uint32_t addr[8], uint64_t tree); - -void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_set_type( - uint32_t addr[8], uint32_t type); - -/* Copies the layer and tree part of one address into the other */ -void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_copy_subtree_addr( - uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for WOTS and FORS addresses. */ - -void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_set_keypair_addr( - uint32_t addr[8], uint32_t keypair); - -void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_set_chain_addr( - uint32_t addr[8], uint32_t chain); - -void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_set_hash_addr( - uint32_t addr[8], uint32_t hash); - -void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_copy_keypair_addr( - uint32_t out[8], const uint32_t in[8]); - -/* These functions are used for all hash tree addresses (including FORS). */ - -void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_set_tree_height( - uint32_t addr[8], uint32_t tree_height); - -void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_set_tree_index( - uint32_t addr[8], uint32_t tree_index); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_clean/api.h b/src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_clean/api.h deleted file mode 100644 index 6ecab38b7c..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_clean/api.h +++ /dev/null @@ -1,81 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_API_H -#define PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_API_H - -#include -#include - - - -#define PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_CRYPTO_ALGNAME "SPHINCS+" - -#define PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_CRYPTO_SECRETKEYBYTES 128 -#define PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_CRYPTO_PUBLICKEYBYTES 64 -#define PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_CRYPTO_BYTES 29792 -#define PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_CRYPTO_SEEDBYTES 96 - - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_crypto_sign_secretkeybytes(void); - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_crypto_sign_publickeybytes(void); - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_crypto_sign_bytes(void); - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_crypto_sign_seedbytes(void); - -/* - * Generates a SPHINCS+ key pair given a seed. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed); - -/* - * Generates a SPHINCS+ key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] - */ -int PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk); - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk); - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk); - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_clean/fors.c b/src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_clean/fors.c deleted file mode 100644 index f11bf8852e..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_clean/fors.c +++ /dev/null @@ -1,161 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "fors.h" -#include "hash.h" -#include "hash_state.h" -#include "thash.h" -#include "utils.h" - -static void fors_gen_sk(unsigned char *sk, const unsigned char *sk_seed, - uint32_t fors_leaf_addr[8], const hash_state *hash_state_seeded) { - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_prf_addr( - sk, sk_seed, fors_leaf_addr, hash_state_seeded); -} - -static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk, - const unsigned char *pub_seed, - uint32_t fors_leaf_addr[8], - const hash_state *hash_state_seeded) { - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_thash_1( - leaf, sk, pub_seed, fors_leaf_addr, hash_state_seeded); -} - -static void fors_gen_leaf(unsigned char *leaf, const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx, const uint32_t fors_tree_addr[8], - const hash_state *hash_state_seeded) { - uint32_t fors_leaf_addr[8] = {0}; - - /* Only copy the parts that must be kept in fors_leaf_addr. */ - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_copy_keypair_addr( - fors_leaf_addr, fors_tree_addr); - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_set_type( - fors_leaf_addr, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_set_tree_index( - fors_leaf_addr, addr_idx); - - fors_gen_sk(leaf, sk_seed, fors_leaf_addr, hash_state_seeded); - fors_sk_to_leaf(leaf, leaf, pub_seed, fors_leaf_addr, hash_state_seeded); -} - -/** - * Interprets m as PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_FORS_HEIGHT-bit unsigned integers. - * Assumes m contains at least PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_FORS_TREES bits. - * Assumes indices has space for PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_FORS_TREES integers. - */ -static void message_to_indices(uint32_t *indices, const unsigned char *m) { - unsigned int i, j; - unsigned int offset = 0; - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_FORS_TREES; i++) { - indices[i] = 0; - for (j = 0; j < PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_FORS_HEIGHT; j++) { - indices[i] ^= (((uint32_t)m[offset >> 3] >> (offset & 0x7)) & 0x1) << j; - offset++; - } - } -} - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_fors_sign( - unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *hash_state_seeded) { - uint32_t indices[PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_FORS_TREES]; - unsigned char roots[PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_FORS_TREES * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_N]; - uint32_t fors_tree_addr[8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_copy_keypair_addr( - fors_tree_addr, fors_addr); - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_copy_keypair_addr( - fors_pk_addr, fors_addr); - - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_set_type( - fors_tree_addr, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_set_type( - fors_pk_addr, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_FORS_TREES; i++) { - idx_offset = i * (1 << PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_FORS_HEIGHT); - - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_set_tree_height( - fors_tree_addr, 0); - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_set_tree_index( - fors_tree_addr, indices[i] + idx_offset); - - /* Include the secret key part that produces the selected leaf node. */ - fors_gen_sk(sig, sk_seed, fors_tree_addr, hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_N; - - /* Compute the authentication path for this leaf node. */ - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_treehash_FORS_HEIGHT( - roots + i * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_N, sig, sk_seed, pub_seed, - indices[i], idx_offset, fors_gen_leaf, fors_tree_addr, - hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_N * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_thash_FORS_TREES( - pk, roots, pub_seed, fors_pk_addr, hash_state_seeded); -} - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_fors_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, const uint32_t fors_addr[8], - const hash_state *hash_state_seeded) { - uint32_t indices[PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_FORS_TREES]; - unsigned char roots[PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_FORS_TREES * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_N]; - unsigned char leaf[PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_N]; - uint32_t fors_tree_addr[8] = {0}; - uint32_t fors_pk_addr[8] = {0}; - uint32_t idx_offset; - unsigned int i; - - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_copy_keypair_addr(fors_tree_addr, fors_addr); - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_copy_keypair_addr(fors_pk_addr, fors_addr); - - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_set_type(fors_tree_addr, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_ADDR_TYPE_FORSTREE); - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_set_type(fors_pk_addr, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_ADDR_TYPE_FORSPK); - - message_to_indices(indices, m); - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_FORS_TREES; i++) { - idx_offset = i * (1 << PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_FORS_HEIGHT); - - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_set_tree_height(fors_tree_addr, 0); - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_set_tree_index(fors_tree_addr, indices[i] + idx_offset); - - /* Derive the leaf from the included secret key part. */ - fors_sk_to_leaf(leaf, sig, pub_seed, fors_tree_addr, hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_N; - - /* Derive the corresponding root node of this tree. */ - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_compute_root(roots + i * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_N, leaf, indices[i], idx_offset, sig, - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_FORS_HEIGHT, pub_seed, fors_tree_addr, hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_N * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_FORS_HEIGHT; - } - - /* Hash horizontally across all tree roots to derive the public key. */ - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_thash_FORS_TREES(pk, roots, pub_seed, fors_pk_addr, hash_state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_clean/fors.h b/src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_clean/fors.h deleted file mode 100644 index d3164e716a..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_clean/fors.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_FORS_H -#define PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_FORS_H - -#include - -#include "hash_state.h" -#include "params.h" - -/** - * Signs a message m, deriving the secret key from sk_seed and the FTS address. - * Assumes m contains at least PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_fors_sign( - unsigned char *sig, unsigned char *pk, - const unsigned char *m, - const unsigned char *sk_seed, const unsigned char *pub_seed, - const uint32_t fors_addr[8], const hash_state *hash_state_seeded); - -/** - * Derives the FORS public key from a signature. - * This can be used for verification by comparing to a known public key, or to - * subsequently verify a signature on the derived public key. The latter is the - * typical use-case when used as an FTS below an OTS in a hypertree. - * Assumes m contains at least PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_FORS_TREES bits. - */ -void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_fors_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *m, - const unsigned char *pub_seed, const uint32_t fors_addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_clean/hash.h b/src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_clean/hash.h deleted file mode 100644 index d51755d79e..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_clean/hash.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_HASH_H -#define PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_HASH_H - -#include "hash_state.h" - -#include -#include - -void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_initialize_hash_function( - hash_state *hash_state_seeded, - const unsigned char *pub_seed, const unsigned char *sk_seed); - -void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_destroy_hash_function(hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_clean/hash_shake256.c b/src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_clean/hash_shake256.c deleted file mode 100644 index 2ef61e2a06..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_clean/hash_shake256.c +++ /dev/null @@ -1,106 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "params.h" -#include "utils.h" - -#include "fips202.h" - -/* For SHAKE256, there is no immediate reason to initialize at the start, - so this function is an empty operation. */ -void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_initialize_hash_function( - hash_state *hash_state_seeded, // NOLINT(readability-non-const-parameter) - const unsigned char *pub_seed, const unsigned char *sk_seed) { - (void)hash_state_seeded; /* Suppress an 'unused parameter' warning. */ - (void)pub_seed; /* Suppress an 'unused parameter' warning. */ - (void)sk_seed; /* Suppress an 'unused parameter' warning. */ -} - -/* This is not necessary for SHAKE256, so we don't do anything */ -void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_destroy_hash_function( - hash_state *hash_state_seeded) { // NOLINT(readability-non-const-parameter) - (void)hash_state_seeded; -} - -/* - * Computes PRF(key, addr), given a secret key of PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_N bytes and an address - */ -void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_prf_addr( - unsigned char *out, const unsigned char *key, const uint32_t addr[8], - const hash_state *hash_state_seeded) { - unsigned char buf[PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_N + PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_ADDR_BYTES]; - - memcpy(buf, key, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_N); - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_addr_to_bytes(buf + PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_N, addr); - - shake256(out, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_N, buf, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_N + PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_ADDR_BYTES); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} - -/** - * Computes the message-dependent randomness R, using a secret seed and an - * optional randomization value as well as the message. - */ -void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_gen_message_random( - unsigned char *R, - const unsigned char *sk_prf, const unsigned char *optrand, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded) { - shake256incctx state; - - shake256_inc_init(&state); - shake256_inc_absorb(&state, sk_prf, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_N); - shake256_inc_absorb(&state, optrand, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_N); - shake256_inc_absorb(&state, m, mlen); - shake256_inc_finalize(&state); - shake256_inc_squeeze(R, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_N, &state); - shake256_inc_ctx_release(&state); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} - -/** - * Computes the message hash using R, the public key, and the message. - * Outputs the message digest and the index of the leaf. The index is split in - * the tree index and the leaf index, for convenient copying to an address. - */ -void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_hash_message( - unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx, - const unsigned char *R, const unsigned char *pk, - const unsigned char *m, size_t mlen, - const hash_state *hash_state_seeded) { -#define PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_TREE_BITS (PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_TREE_HEIGHT * (PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_D - 1)) -#define PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_TREE_BYTES ((PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_TREE_BITS + 7) / 8) -#define PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_LEAF_BITS PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_TREE_HEIGHT -#define PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_LEAF_BYTES ((PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_LEAF_BITS + 7) / 8) -#define PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_DGST_BYTES (PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_FORS_MSG_BYTES + PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_TREE_BYTES + PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_LEAF_BYTES) - - unsigned char buf[PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_DGST_BYTES]; - unsigned char *bufp = buf; - shake256incctx state; - - shake256_inc_init(&state); - shake256_inc_absorb(&state, R, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_N); - shake256_inc_absorb(&state, pk, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_PK_BYTES); - shake256_inc_absorb(&state, m, mlen); - shake256_inc_finalize(&state); - shake256_inc_squeeze(buf, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_DGST_BYTES, &state); - shake256_inc_ctx_release(&state); - - memcpy(digest, bufp, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_FORS_MSG_BYTES); - bufp += PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_FORS_MSG_BYTES; - - *tree = PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_bytes_to_ull( - bufp, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_TREE_BYTES); - *tree &= (~(uint64_t)0) >> (64 - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_TREE_BITS); - bufp += PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_TREE_BYTES; - - *leaf_idx = (uint32_t)PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_bytes_to_ull( - bufp, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_LEAF_BYTES); - *leaf_idx &= (~(uint32_t)0) >> (32 - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_LEAF_BITS); - - (void)hash_state_seeded; /* Prevent unused parameter warning. */ -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_clean/hash_state.h b/src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_clean/hash_state.h deleted file mode 100644 index 7d92ef872a..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_clean/hash_state.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef SPX_HASH_STATE_H -#define SPX_HASH_STATE_H - -/** - * Defines the type of the hash function state. - * - * Don't be fooled into thinking this instance of SPHINCS+ isn't stateless! - * - * From Section 7.2.2 from the SPHINCS+ round-2 specification: - * - * Each of the instances of the tweakable hash function take PK.seed as its - * first input, which is constant for a given key pair – and, thus, across - * a single signature. This leads to a lot of redundant computation. To remedy - * this, we pad PK.seed to the length of a full 64-byte SHA-256 input block. - * Because of the Merkle-Damgård construction that underlies SHA-256, this - * allows for reuse of the intermediate SHA-256 state after the initial call to - * the compression function which improves performance. - * - * We pass this hash state around in functions, because otherwise we need to - * have a global variable. - * - * SHAKE256 does not need this state. Because this implementation is generated - * from a shared code base, we still need to specify some hash_state as it is - * still passed around. We chose to use an `int` as a placeholder for this - * purpose. - */ - -#define hash_state int - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_clean/params.h b/src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_clean/params.h deleted file mode 100644 index 41c787b040..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_clean/params.h +++ /dev/null @@ -1,53 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_PARAMS_H -#define PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_PARAMS_H - -/* Hash output length in bytes. */ -#define PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_N 32 -/* Height of the hypertree. */ -#define PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_FULL_HEIGHT 64 -/* Number of subtree layer. */ -#define PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_D 8 -/* FORS tree dimensions. */ -#define PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_FORS_HEIGHT 14 -#define PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_FORS_TREES 22 -/* Winternitz parameter, */ -#define PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_WOTS_W 16 - -/* The hash function is defined by linking a different hash.c file, as opposed - to setting a #define constant. */ - -/* For clarity */ -#define PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_ADDR_BYTES 32 - -/* WOTS parameters. */ -#define PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_WOTS_LOGW 4 - -#define PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_WOTS_LEN1 (8 * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_N / PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_WOTS_LOGW) - -/* PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */ -#define PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_WOTS_LEN2 3 - -#define PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_WOTS_LEN (PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_WOTS_LEN1 + PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_WOTS_LEN2) -#define PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_WOTS_BYTES (PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_WOTS_LEN * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_N) -#define PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_WOTS_PK_BYTES PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_WOTS_BYTES - -/* Subtree size. */ -#define PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_TREE_HEIGHT (PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_FULL_HEIGHT / PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_D) - -/* FORS parameters. */ -#define PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_FORS_MSG_BYTES ((PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_FORS_TREES + 7) / 8) -#define PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_FORS_BYTES ((PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_FORS_HEIGHT + 1) * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_FORS_TREES * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_N) -#define PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_FORS_PK_BYTES PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_N - -/* Resulting SPX sizes. */ -#define PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_BYTES (PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_N + PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_FORS_BYTES + PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_D * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_WOTS_BYTES +\ - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_FULL_HEIGHT * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_N) -#define PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_PK_BYTES (2 * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_N) -#define PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_SK_BYTES (2 * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_N + PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_PK_BYTES) - -/* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ -#define PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_OPTRAND_BYTES 32 - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_clean/sign.c b/src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_clean/sign.c deleted file mode 100644 index 2b88aadda3..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_clean/sign.c +++ /dev/null @@ -1,356 +0,0 @@ -#include -#include -#include - -#include "address.h" -#include "api.h" -#include "fors.h" -#include "hash.h" -#include "hash_state.h" -#include "params.h" -#include "randombytes.h" -#include "thash.h" -#include "utils.h" -#include "wots.h" - -/** - * Computes the leaf at a given address. First generates the WOTS key pair, - * then computes leaf by hashing horizontally. - */ -static void wots_gen_leaf(unsigned char *leaf, const unsigned char *sk_seed, - const unsigned char *pub_seed, - uint32_t addr_idx, const uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - unsigned char pk[PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_WOTS_BYTES]; - uint32_t wots_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_set_type( - wots_addr, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_set_type( - wots_pk_addr, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_ADDR_TYPE_WOTSPK); - - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_set_keypair_addr( - wots_addr, addr_idx); - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_wots_gen_pk( - pk, sk_seed, pub_seed, wots_addr, hash_state_seeded); - - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_copy_keypair_addr( - wots_pk_addr, wots_addr); - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_thash_WOTS_LEN( - leaf, pk, pub_seed, wots_pk_addr, hash_state_seeded); -} - -/* - * Returns the length of a secret key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_crypto_sign_secretkeybytes(void) { - return PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_CRYPTO_SECRETKEYBYTES; -} - -/* - * Returns the length of a public key, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_crypto_sign_publickeybytes(void) { - return PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_CRYPTO_PUBLICKEYBYTES; -} - -/* - * Returns the length of a signature, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_crypto_sign_bytes(void) { - return PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_CRYPTO_BYTES; -} - -/* - * Returns the length of the seed required to generate a key pair, in bytes - */ -size_t PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_crypto_sign_seedbytes(void) { - return PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_CRYPTO_SEEDBYTES; -} - -/* - * Generates an SPX key pair given a seed of length - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_crypto_sign_seed_keypair( - uint8_t *pk, uint8_t *sk, const uint8_t *seed) { - /* We do not need the auth path in key generation, but it simplifies the - code to have just one treehash routine that computes both root and path - in one function. */ - unsigned char auth_path[PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_TREE_HEIGHT * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_N]; - uint32_t top_tree_addr[8] = {0}; - hash_state hash_state_seeded; - - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_set_layer_addr( - top_tree_addr, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_D - 1); - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_set_type( - top_tree_addr, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_ADDR_TYPE_HASHTREE); - - /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ - memcpy(sk, seed, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_CRYPTO_SEEDBYTES); - - memcpy(pk, sk + 2 * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_N, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_N); - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_initialize_hash_function(&hash_state_seeded, pk, sk); - - /* Compute root node of the top-most subtree. */ - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_treehash_TREE_HEIGHT( - sk + 3 * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_N, auth_path, sk, sk + 2 * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_N, 0, 0, - wots_gen_leaf, top_tree_addr, &hash_state_seeded); - - memcpy(pk + PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_N, sk + 3 * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_N, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_N); - - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_destroy_hash_function(&hash_state_seeded); - return 0; -} - -/* - * Generates an SPX key pair. - * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [PUB_SEED || root] - */ -int PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_crypto_sign_keypair( - uint8_t *pk, uint8_t *sk) { - unsigned char seed[PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_CRYPTO_SEEDBYTES]; - randombytes(seed, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_CRYPTO_SEEDBYTES); - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_crypto_sign_seed_keypair( - pk, sk, seed); - - return 0; -} - -/** - * Returns an array containing a detached signature. - */ -int PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_crypto_sign_signature( - uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - const unsigned char *sk_seed = sk; - const unsigned char *sk_prf = sk + PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_N; - const unsigned char *pk = sk + 2 * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_N; - const unsigned char *pub_seed = pk; - - unsigned char optrand[PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_N]; - unsigned char mhash[PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_FORS_MSG_BYTES]; - unsigned char root[PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_N]; - uint32_t i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - - hash_state hash_state_seeded; - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_initialize_hash_function( - &hash_state_seeded, - pub_seed, sk_seed); - - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_set_type( - wots_addr, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_set_type( - tree_addr, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_ADDR_TYPE_HASHTREE); - - /* Optionally, signing can be made non-deterministic using optrand. - This can help counter side-channel attacks that would benefit from - getting a large number of traces when the signer uses the same nodes. */ - randombytes(optrand, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_N); - /* Compute the digest randomization value. */ - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_gen_message_random( - sig, sk_prf, optrand, m, mlen, &hash_state_seeded); - - /* Derive the message digest and leaf index from R, PK and M. */ - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_N; - - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); - - /* Sign the message hash using FORS. */ - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_fors_sign( - sig, root, mhash, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_FORS_BYTES; - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_D; i++) { - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_set_tree_addr(tree_addr, tree); - - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); - - /* Compute a WOTS signature. */ - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_wots_sign( - sig, root, sk_seed, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_WOTS_BYTES; - - /* Compute the authentication path for the used WOTS leaf. */ - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_treehash_TREE_HEIGHT( - root, sig, sk_seed, pub_seed, idx_leaf, 0, - wots_gen_leaf, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_TREE_HEIGHT * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_TREE_HEIGHT; - } - - *siglen = PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_BYTES; - - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_destroy_hash_function(&hash_state_seeded); - return 0; -} - -/** - * Verifies a detached signature and message under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_crypto_sign_verify( - const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, const uint8_t *pk) { - const unsigned char *pub_seed = pk; - const unsigned char *pub_root = pk + PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_N; - unsigned char mhash[PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_FORS_MSG_BYTES]; - unsigned char wots_pk[PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_WOTS_BYTES]; - unsigned char root[PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_N]; - unsigned char leaf[PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_N]; - unsigned int i; - uint64_t tree; - uint32_t idx_leaf; - uint32_t wots_addr[8] = {0}; - uint32_t tree_addr[8] = {0}; - uint32_t wots_pk_addr[8] = {0}; - - hash_state hash_state_seeded; - - if (siglen != PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_BYTES) { - return -1; - } - - /* This hook allows the hash function instantiation to do whatever - preparation or computation it needs, based on the public seed. */ - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_initialize_hash_function( - &hash_state_seeded, - pub_seed, NULL); - - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_set_type( - wots_addr, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_ADDR_TYPE_WOTS); - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_set_type( - tree_addr, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_ADDR_TYPE_HASHTREE); - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_set_type( - wots_pk_addr, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_ADDR_TYPE_WOTSPK); - - /* Derive the message digest and leaf index from R || PK || M. */ - /* The additional PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_N is a result of the hash domain separator. */ - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_hash_message( - mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_N; - - /* Layer correctly defaults to 0, so no need to set_layer_addr */ - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_set_tree_addr(wots_addr, tree); - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); - - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_fors_pk_from_sig( - root, sig, mhash, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_FORS_BYTES; - - /* For each subtree.. */ - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_D; i++) { - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_set_layer_addr(tree_addr, i); - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_set_tree_addr(tree_addr, tree); - - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_copy_subtree_addr( - wots_addr, tree_addr); - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_set_keypair_addr( - wots_addr, idx_leaf); - - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_copy_keypair_addr( - wots_pk_addr, wots_addr); - - /* The WOTS public key is only correct if the signature was correct. */ - /* Initially, root is the FORS pk, but on subsequent iterations it is - the root of the subtree below the currently processed subtree. */ - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_wots_pk_from_sig( - wots_pk, sig, root, pub_seed, wots_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_WOTS_BYTES; - - /* Compute the leaf node using the WOTS public key. */ - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_thash_WOTS_LEN( - leaf, wots_pk, pub_seed, wots_pk_addr, &hash_state_seeded); - - /* Compute the root node of this subtree. */ - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_compute_root( - root, leaf, idx_leaf, 0, sig, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_TREE_HEIGHT, - pub_seed, tree_addr, &hash_state_seeded); - sig += PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_TREE_HEIGHT * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_N; - - /* Update the indices for the next layer. */ - idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_TREE_HEIGHT) - 1)); - tree = tree >> PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_TREE_HEIGHT; - } - - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_destroy_hash_function(&hash_state_seeded); - /* Check if the root node equals the root node in the public key. */ - if (memcmp(root, pub_root, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_N) != 0) { - return -1; - } - - return 0; -} - - -/** - * Returns an array containing the signature followed by the message. - */ -int PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_crypto_sign( - uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, const uint8_t *sk) { - size_t siglen; - - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_crypto_sign_signature( - sm, &siglen, m, mlen, sk); - - memmove(sm + PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_BYTES, m, mlen); - *smlen = siglen + mlen; - - return 0; -} - -/** - * Verifies a given signature-message pair under a given public key. - */ -int PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_crypto_sign_open( - uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, const uint8_t *pk) { - /* The API caller does not necessarily know what size a signature should be - but SPHINCS+ signatures are always exactly PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_BYTES. */ - if (smlen < PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_BYTES) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - *mlen = smlen - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_BYTES; - - if (PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_crypto_sign_verify( - sm, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_BYTES, sm + PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_BYTES, *mlen, pk)) { - memset(m, 0, smlen); - *mlen = 0; - return -1; - } - - /* If verification was successful, move the message to the right place. */ - memmove(m, sm + PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_BYTES, *mlen); - - return 0; -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_clean/thash.h b/src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_clean/thash.h deleted file mode 100644 index 62ccfe2d0f..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_clean/thash.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_THASH_H -#define PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_THASH_H - -#include "hash_state.h" - -#include - -void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_clean/thash_shake256_simple.c b/src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_clean/thash_shake256_simple.c deleted file mode 100644 index 274cfc9267..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_clean/thash_shake256_simple.c +++ /dev/null @@ -1,74 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash_state.h" -#include "params.h" -#include "thash.h" - -#include "fips202.h" - -/** - * Takes an array of inblocks concatenated arrays of PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_N bytes. - */ -static void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_thash( - unsigned char *out, unsigned char *buf, - const unsigned char *in, unsigned int inblocks, - const unsigned char *pub_seed, uint32_t addr[8]) { - - memcpy(buf, pub_seed, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_N); - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_addr_to_bytes(buf + PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_N, addr); - memcpy(buf + PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_N + PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_ADDR_BYTES, in, inblocks * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_N); - - shake256(out, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_N, buf, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_N + PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_N); -} - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_thash_1( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_N + PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_ADDR_BYTES + 1 * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_N]; - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_thash( - out, buf, in, 1, pub_seed, addr); - - (void)hash_state_seeded; /* Avoid unused parameter warning. */ -} - -void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_thash_2( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_N + PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_ADDR_BYTES + 2 * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_N]; - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_thash( - out, buf, in, 2, pub_seed, addr); - - (void)hash_state_seeded; /* Avoid unused parameter warning. */ -} - -void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_thash_WOTS_LEN( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_N + PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_ADDR_BYTES + PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_WOTS_LEN * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_N]; - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_thash( - out, buf, in, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_WOTS_LEN, pub_seed, addr); - - (void)hash_state_seeded; /* Avoid unused parameter warning. */ -} - -void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_thash_FORS_TREES( - unsigned char *out, const unsigned char *in, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - - unsigned char buf[PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_N + PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_ADDR_BYTES + PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_FORS_TREES * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_N]; - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_thash( - out, buf, in, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_FORS_TREES, pub_seed, addr); - - (void)hash_state_seeded; /* Avoid unused parameter warning. */ -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_clean/utils.c b/src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_clean/utils.c deleted file mode 100644 index e61290d330..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_clean/utils.c +++ /dev/null @@ -1,199 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "hash_state.h" -#include "params.h" -#include "thash.h" -#include "utils.h" - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in) { - - /* Iterate over out in decreasing order, for big-endianness. */ - for (size_t i = outlen; i > 0; i--) { - out[i - 1] = in & 0xff; - in = in >> 8; - } -} - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_bytes_to_ull( - const unsigned char *in, size_t inlen) { - unsigned long long retval = 0; - - for (size_t i = 0; i < inlen; i++) { - retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i)); - } - return retval; -} - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - uint32_t i; - unsigned char buffer[2 * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_N]; - - /* If leaf_idx is odd (last bit = 1), current path element is a right child - and auth_path has to go left. Otherwise it is the other way around. */ - if (leaf_idx & 1) { - memcpy(buffer + PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_N, leaf, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_N); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_N); - } else { - memcpy(buffer, leaf, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_N); - memcpy(buffer + PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_N, auth_path, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_N); - } - auth_path += PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_N; - - for (i = 0; i < tree_height - 1; i++) { - leaf_idx >>= 1; - idx_offset >>= 1; - /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_set_tree_height(addr, i + 1); - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_set_tree_index( - addr, leaf_idx + idx_offset); - - /* Pick the right or left neighbor, depending on parity of the node. */ - if (leaf_idx & 1) { - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_thash_2( - buffer + PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_N, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer, auth_path, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_N); - } else { - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_thash_2( - buffer, buffer, pub_seed, addr, hash_state_seeded); - memcpy(buffer + PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_N, auth_path, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_N); - } - auth_path += PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_N; - } - - /* The last iteration is exceptional; we do not copy an auth_path node. */ - leaf_idx >>= 1; - idx_offset >>= 1; - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_set_tree_height(addr, tree_height); - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_set_tree_index( - addr, leaf_idx + idx_offset); - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_thash_2( - root, buffer, pub_seed, addr, hash_state_seeded); -} - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -static void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_treehash( - unsigned char *root, unsigned char *auth_path, - unsigned char *stack, unsigned int *heights, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], - const hash_state *hash_state_seeded) { - - unsigned int offset = 0; - uint32_t idx; - uint32_t tree_idx; - - for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) { - /* Add the next leaf node to the stack. */ - gen_leaf(stack + offset * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_N, - sk_seed, pub_seed, idx + idx_offset, tree_addr, - hash_state_seeded); - offset++; - heights[offset - 1] = 0; - - /* If this is a node we need for the auth path.. */ - if ((leaf_idx ^ 0x1) == idx) { - memcpy(auth_path, stack + (offset - 1)*PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_N, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_N); - } - - /* While the top-most nodes are of equal height.. */ - while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) { - /* Compute index of the new node, in the next layer. */ - tree_idx = (idx >> (heights[offset - 1] + 1)); - - /* Set the address of the node we're creating. */ - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_set_tree_height( - tree_addr, heights[offset - 1] + 1); - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_set_tree_index( - tree_addr, tree_idx + (idx_offset >> (heights[offset - 1] + 1))); - /* Hash the top-most nodes from the stack together. */ - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_thash_2( - stack + (offset - 2)*PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_N, stack + (offset - 2)*PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_N, - pub_seed, tree_addr, hash_state_seeded); - offset--; - /* Note that the top-most node is now one layer higher. */ - heights[offset - 1]++; - - /* If this is a node we need for the auth path.. */ - if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) { - memcpy(auth_path + heights[offset - 1]*PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_N, - stack + (offset - 1)*PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_N, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_N); - } - } - } - memcpy(root, stack, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_N); -} - -/* The wrappers below ensure that we use fixed-size buffers on the stack */ - -void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_FORS_HEIGHT + 1)*PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_N]; - unsigned int heights[PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_FORS_HEIGHT + 1]; - - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_FORS_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); -} - -void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded) { - - unsigned char stack[(PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_TREE_HEIGHT + 1)*PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_N]; - unsigned int heights[PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_TREE_HEIGHT + 1]; - - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_treehash( - root, auth_path, stack, heights, sk_seed, pub_seed, - leaf_idx, idx_offset, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_TREE_HEIGHT, gen_leaf, tree_addr, hash_state_seeded); -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_clean/utils.h b/src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_clean/utils.h deleted file mode 100644 index 81157a31dd..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_clean/utils.h +++ /dev/null @@ -1,64 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_UTILS_H -#define PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_UTILS_H - -#include "hash_state.h" -#include "params.h" -#include -#include - -/** - * Converts the value of 'in' to 'outlen' bytes in big-endian byte order. - */ -void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_ull_to_bytes( - unsigned char *out, size_t outlen, unsigned long long in); - -/** - * Converts the inlen bytes in 'in' from big-endian byte order to an integer. - */ -unsigned long long PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_bytes_to_ull( - const unsigned char *in, size_t inlen); - -/** - * Computes a root node given a leaf and an auth path. - * Expects address to be complete other than the tree_height and tree_index. - */ -void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_compute_root( - unsigned char *root, const unsigned char *leaf, - uint32_t leaf_idx, uint32_t idx_offset, - const unsigned char *auth_path, uint32_t tree_height, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -/** - * For a given leaf index, computes the authentication path and the resulting - * root node using Merkle's TreeHash algorithm. - * Expects the layer and tree parts of the tree_addr to be set, as well as the - * tree type (i.e. PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_ADDR_TYPE_FORSTREE). - * Applies the offset idx_offset to indices before building addresses, so that - * it is possible to continue counting indices across trees. - */ -void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_treehash_FORS_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); - -void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_treehash_TREE_HEIGHT( - unsigned char *root, unsigned char *auth_path, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t leaf_idx, uint32_t idx_offset, - void (*gen_leaf)( - unsigned char * /* leaf */, - const unsigned char * /* sk_seed */, - const unsigned char * /* pub_seed */, - uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */, - const hash_state * /* hash_state_seeded */), - uint32_t tree_addr[8], const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_clean/wots.c b/src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_clean/wots.c deleted file mode 100644 index 2e644403b9..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_clean/wots.c +++ /dev/null @@ -1,167 +0,0 @@ -#include -#include - -#include "address.h" -#include "hash.h" -#include "hash_state.h" -#include "params.h" -#include "thash.h" -#include "utils.h" -#include "wots.h" - -// TODO clarify address expectations, and make them more uniform. -// TODO i.e. do we expect types to be set already? -// TODO and do we expect modifications or copies? - -/** - * Computes the starting value for a chain, i.e. the secret key. - * Expects the address to be complete up to the chain address. - */ -static void wots_gen_sk(unsigned char *sk, const unsigned char *sk_seed, - uint32_t wots_addr[8], - const hash_state *hash_state_seeded) { - /* Make sure that the hash address is actually zeroed. */ - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_set_hash_addr(wots_addr, 0); - - /* Generate sk element. */ - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_prf_addr(sk, sk_seed, wots_addr, hash_state_seeded); -} - -/** - * Computes the chaining function. - * out and in have to be n-byte arrays. - * - * Interprets in as start-th value of the chain. - * addr has to contain the address of the chain. - */ -static void gen_chain(unsigned char *out, const unsigned char *in, - unsigned int start, unsigned int steps, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - uint32_t i; - - /* Initialize out with the value at position 'start'. */ - memcpy(out, in, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_N); - - /* Iterate 'steps' calls to the hash function. */ - for (i = start; i < (start + steps) && i < PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_WOTS_W; i++) { - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_set_hash_addr(addr, i); - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_thash_1( - out, out, pub_seed, addr, hash_state_seeded); - } -} - -/** - * base_w algorithm as described in draft. - * Interprets an array of bytes as integers in base w. - * This only works when log_w is a divisor of 8. - */ -static void base_w(unsigned int *output, const size_t out_len, - const unsigned char *input) { - size_t in = 0; - size_t out = 0; - unsigned char total = 0; - unsigned int bits = 0; - size_t consumed; - - for (consumed = 0; consumed < out_len; consumed++) { - if (bits == 0) { - total = input[in]; - in++; - bits += 8; - } - bits -= PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_WOTS_LOGW; - output[out] = (unsigned int)((total >> bits) & (PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_WOTS_W - 1)); - out++; - } -} - -/* Computes the WOTS+ checksum over a message (in base_w). */ -static void wots_checksum(unsigned int *csum_base_w, - const unsigned int *msg_base_w) { - unsigned int csum = 0; - unsigned char csum_bytes[(PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_WOTS_LEN2 * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_WOTS_LOGW + 7) / 8]; - unsigned int i; - - /* Compute checksum. */ - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_WOTS_LEN1; i++) { - csum += PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_WOTS_W - 1 - msg_base_w[i]; - } - - /* Convert checksum to base_w. */ - /* Make sure expected empty zero bits are the least significant bits. */ - csum = csum << (8 - ((PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_WOTS_LEN2 * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_WOTS_LOGW) % 8)); - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_ull_to_bytes( - csum_bytes, sizeof(csum_bytes), csum); - base_w(csum_base_w, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_WOTS_LEN2, csum_bytes); -} - -/* Takes a message and derives the matching chain lengths. */ -static void chain_lengths(unsigned int *lengths, const unsigned char *msg) { - base_w(lengths, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_WOTS_LEN1, msg); - wots_checksum(lengths + PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_WOTS_LEN1, lengths); -} - -/** - * WOTS key generation. Takes a 32 byte sk_seed, expands it to WOTS private key - * elements and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_wots_gen_pk( - unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - uint32_t i; - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_WOTS_LEN; i++) { - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_set_chain_addr(addr, i); - wots_gen_sk(pk + i * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_N, sk_seed, addr, hash_state_seeded); - gen_chain(pk + i * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_N, pk + i * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_N, - 0, PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_WOTS_W - 1, pub_seed, addr, hash_state_seeded); - } -} - -/** - * Takes a n-byte message and the 32-byte sk_see to compute a signature 'sig'. - */ -void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_wots_sign( - unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *hash_state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_WOTS_LEN; i++) { - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_set_chain_addr(addr, i); - wots_gen_sk(sig + i * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_N, sk_seed, addr, hash_state_seeded); - gen_chain(sig + i * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_N, sig + i * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_N, 0, lengths[i], pub_seed, addr, hash_state_seeded); - } -} - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_wots_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded) { - unsigned int lengths[PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_WOTS_LEN]; - uint32_t i; - - chain_lengths(lengths, msg); - - for (i = 0; i < PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_WOTS_LEN; i++) { - PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_set_chain_addr(addr, i); - gen_chain(pk + i * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_N, sig + i * PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_N, - lengths[i], PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_WOTS_W - 1 - lengths[i], pub_seed, addr, - hash_state_seeded); - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_clean/wots.h b/src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_clean/wots.h deleted file mode 100644 index fe5533a4a5..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake256-256s-simple_clean/wots.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_WOTS_H -#define PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_WOTS_H - -#include "hash_state.h" -#include "params.h" -#include - -/** - * WOTS key generation. Takes a 32 byte seed for the private key, expands it to - * a full WOTS private key and computes the corresponding public key. - * It requires the seed pub_seed (used to generate bitmasks and hash keys) - * and the address of this WOTS key pair. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_wots_gen_pk( - unsigned char *pk, const unsigned char *sk_seed, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -/** - * Takes a n-byte message and the 32-byte seed for the private key to compute a - * signature that is placed at 'sig'. - */ -void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_wots_sign( - unsigned char *sig, const unsigned char *msg, - const unsigned char *sk_seed, const unsigned char *pub_seed, - uint32_t addr[8], const hash_state *hash_state_seeded); - -/** - * Takes a WOTS signature and an n-byte message, computes a WOTS public key. - * - * Writes the computed public key to 'pk'. - */ -void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_wots_pk_from_sig( - unsigned char *pk, - const unsigned char *sig, const unsigned char *msg, - const unsigned char *pub_seed, uint32_t addr[8], - const hash_state *hash_state_seeded); - -#endif diff --git a/src/sig/sphincs/sig_sphincs_haraka_128f_robust.c b/src/sig/sphincs/sig_sphincs_haraka_128f_robust.c deleted file mode 100644 index 8f93b009db..0000000000 --- a/src/sig/sphincs/sig_sphincs_haraka_128f_robust.c +++ /dev/null @@ -1,90 +0,0 @@ -// SPDX-License-Identifier: MIT - -#include - -#include - -#if defined(OQS_ENABLE_SIG_sphincs_haraka_128f_robust) - -OQS_SIG *OQS_SIG_sphincs_haraka_128f_robust_new(void) { - - OQS_SIG *sig = malloc(sizeof(OQS_SIG)); - if (sig == NULL) { - return NULL; - } - sig->method_name = OQS_SIG_alg_sphincs_haraka_128f_robust; - sig->alg_version = "https://github.com/sphincs/sphincsplus/commit/ed15dd78658f63288c7492c00260d86154b84637"; - - sig->claimed_nist_level = 1; - sig->euf_cma = true; - - sig->length_public_key = OQS_SIG_sphincs_haraka_128f_robust_length_public_key; - sig->length_secret_key = OQS_SIG_sphincs_haraka_128f_robust_length_secret_key; - sig->length_signature = OQS_SIG_sphincs_haraka_128f_robust_length_signature; - - sig->keypair = OQS_SIG_sphincs_haraka_128f_robust_keypair; - sig->sign = OQS_SIG_sphincs_haraka_128f_robust_sign; - sig->verify = OQS_SIG_sphincs_haraka_128f_robust_verify; - - return sig; -} - -extern int PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); -extern int PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); -extern int PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); - -#if defined(OQS_ENABLE_SIG_sphincs_haraka_128f_robust_aesni) -extern int PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); -extern int PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); -extern int PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); -#endif - -OQS_API OQS_STATUS OQS_SIG_sphincs_haraka_128f_robust_keypair(uint8_t *public_key, uint8_t *secret_key) { -#if defined(OQS_ENABLE_SIG_sphincs_haraka_128f_robust_aesni) -#if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_AES)) { -#endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_crypto_sign_keypair(public_key, secret_key); -#if defined(OQS_DIST_BUILD) - } else { - return (OQS_STATUS) PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_crypto_sign_keypair(public_key, secret_key); - } -#endif /* OQS_DIST_BUILD */ -#else - return (OQS_STATUS) PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_crypto_sign_keypair(public_key, secret_key); -#endif -} - -OQS_API OQS_STATUS OQS_SIG_sphincs_haraka_128f_robust_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, const uint8_t *secret_key) { -#if defined(OQS_ENABLE_SIG_sphincs_haraka_128f_robust_aesni) -#if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_AES)) { -#endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); -#if defined(OQS_DIST_BUILD) - } else { - return (OQS_STATUS) PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); - } -#endif /* OQS_DIST_BUILD */ -#else - return (OQS_STATUS) PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); -#endif -} - -OQS_API OQS_STATUS OQS_SIG_sphincs_haraka_128f_robust_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key) { -#if defined(OQS_ENABLE_SIG_sphincs_haraka_128f_robust_aesni) -#if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_AES)) { -#endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSHARAKA128FROBUST_AESNI_crypto_sign_verify(signature, signature_len, message, message_len, public_key); -#if defined(OQS_DIST_BUILD) - } else { - return (OQS_STATUS) PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); - } -#endif /* OQS_DIST_BUILD */ -#else - return (OQS_STATUS) PQCLEAN_SPHINCSHARAKA128FROBUST_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); -#endif -} - -#endif diff --git a/src/sig/sphincs/sig_sphincs_haraka_128f_simple.c b/src/sig/sphincs/sig_sphincs_haraka_128f_simple.c deleted file mode 100644 index db82c248b5..0000000000 --- a/src/sig/sphincs/sig_sphincs_haraka_128f_simple.c +++ /dev/null @@ -1,90 +0,0 @@ -// SPDX-License-Identifier: MIT - -#include - -#include - -#if defined(OQS_ENABLE_SIG_sphincs_haraka_128f_simple) - -OQS_SIG *OQS_SIG_sphincs_haraka_128f_simple_new(void) { - - OQS_SIG *sig = malloc(sizeof(OQS_SIG)); - if (sig == NULL) { - return NULL; - } - sig->method_name = OQS_SIG_alg_sphincs_haraka_128f_simple; - sig->alg_version = "https://github.com/sphincs/sphincsplus/commit/ed15dd78658f63288c7492c00260d86154b84637"; - - sig->claimed_nist_level = 1; - sig->euf_cma = true; - - sig->length_public_key = OQS_SIG_sphincs_haraka_128f_simple_length_public_key; - sig->length_secret_key = OQS_SIG_sphincs_haraka_128f_simple_length_secret_key; - sig->length_signature = OQS_SIG_sphincs_haraka_128f_simple_length_signature; - - sig->keypair = OQS_SIG_sphincs_haraka_128f_simple_keypair; - sig->sign = OQS_SIG_sphincs_haraka_128f_simple_sign; - sig->verify = OQS_SIG_sphincs_haraka_128f_simple_verify; - - return sig; -} - -extern int PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); -extern int PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); -extern int PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); - -#if defined(OQS_ENABLE_SIG_sphincs_haraka_128f_simple_aesni) -extern int PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); -extern int PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); -extern int PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); -#endif - -OQS_API OQS_STATUS OQS_SIG_sphincs_haraka_128f_simple_keypair(uint8_t *public_key, uint8_t *secret_key) { -#if defined(OQS_ENABLE_SIG_sphincs_haraka_128f_simple_aesni) -#if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_AES)) { -#endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_crypto_sign_keypair(public_key, secret_key); -#if defined(OQS_DIST_BUILD) - } else { - return (OQS_STATUS) PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_crypto_sign_keypair(public_key, secret_key); - } -#endif /* OQS_DIST_BUILD */ -#else - return (OQS_STATUS) PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_crypto_sign_keypair(public_key, secret_key); -#endif -} - -OQS_API OQS_STATUS OQS_SIG_sphincs_haraka_128f_simple_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, const uint8_t *secret_key) { -#if defined(OQS_ENABLE_SIG_sphincs_haraka_128f_simple_aesni) -#if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_AES)) { -#endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); -#if defined(OQS_DIST_BUILD) - } else { - return (OQS_STATUS) PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); - } -#endif /* OQS_DIST_BUILD */ -#else - return (OQS_STATUS) PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); -#endif -} - -OQS_API OQS_STATUS OQS_SIG_sphincs_haraka_128f_simple_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key) { -#if defined(OQS_ENABLE_SIG_sphincs_haraka_128f_simple_aesni) -#if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_AES)) { -#endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSHARAKA128FSIMPLE_AESNI_crypto_sign_verify(signature, signature_len, message, message_len, public_key); -#if defined(OQS_DIST_BUILD) - } else { - return (OQS_STATUS) PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); - } -#endif /* OQS_DIST_BUILD */ -#else - return (OQS_STATUS) PQCLEAN_SPHINCSHARAKA128FSIMPLE_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); -#endif -} - -#endif diff --git a/src/sig/sphincs/sig_sphincs_haraka_128s_robust.c b/src/sig/sphincs/sig_sphincs_haraka_128s_robust.c deleted file mode 100644 index 189c0aac2a..0000000000 --- a/src/sig/sphincs/sig_sphincs_haraka_128s_robust.c +++ /dev/null @@ -1,90 +0,0 @@ -// SPDX-License-Identifier: MIT - -#include - -#include - -#if defined(OQS_ENABLE_SIG_sphincs_haraka_128s_robust) - -OQS_SIG *OQS_SIG_sphincs_haraka_128s_robust_new(void) { - - OQS_SIG *sig = malloc(sizeof(OQS_SIG)); - if (sig == NULL) { - return NULL; - } - sig->method_name = OQS_SIG_alg_sphincs_haraka_128s_robust; - sig->alg_version = "https://github.com/sphincs/sphincsplus/commit/ed15dd78658f63288c7492c00260d86154b84637"; - - sig->claimed_nist_level = 1; - sig->euf_cma = true; - - sig->length_public_key = OQS_SIG_sphincs_haraka_128s_robust_length_public_key; - sig->length_secret_key = OQS_SIG_sphincs_haraka_128s_robust_length_secret_key; - sig->length_signature = OQS_SIG_sphincs_haraka_128s_robust_length_signature; - - sig->keypair = OQS_SIG_sphincs_haraka_128s_robust_keypair; - sig->sign = OQS_SIG_sphincs_haraka_128s_robust_sign; - sig->verify = OQS_SIG_sphincs_haraka_128s_robust_verify; - - return sig; -} - -extern int PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); -extern int PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); -extern int PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); - -#if defined(OQS_ENABLE_SIG_sphincs_haraka_128s_robust_aesni) -extern int PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); -extern int PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); -extern int PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); -#endif - -OQS_API OQS_STATUS OQS_SIG_sphincs_haraka_128s_robust_keypair(uint8_t *public_key, uint8_t *secret_key) { -#if defined(OQS_ENABLE_SIG_sphincs_haraka_128s_robust_aesni) -#if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_AES)) { -#endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_crypto_sign_keypair(public_key, secret_key); -#if defined(OQS_DIST_BUILD) - } else { - return (OQS_STATUS) PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_crypto_sign_keypair(public_key, secret_key); - } -#endif /* OQS_DIST_BUILD */ -#else - return (OQS_STATUS) PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_crypto_sign_keypair(public_key, secret_key); -#endif -} - -OQS_API OQS_STATUS OQS_SIG_sphincs_haraka_128s_robust_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, const uint8_t *secret_key) { -#if defined(OQS_ENABLE_SIG_sphincs_haraka_128s_robust_aesni) -#if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_AES)) { -#endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); -#if defined(OQS_DIST_BUILD) - } else { - return (OQS_STATUS) PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); - } -#endif /* OQS_DIST_BUILD */ -#else - return (OQS_STATUS) PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); -#endif -} - -OQS_API OQS_STATUS OQS_SIG_sphincs_haraka_128s_robust_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key) { -#if defined(OQS_ENABLE_SIG_sphincs_haraka_128s_robust_aesni) -#if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_AES)) { -#endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSHARAKA128SROBUST_AESNI_crypto_sign_verify(signature, signature_len, message, message_len, public_key); -#if defined(OQS_DIST_BUILD) - } else { - return (OQS_STATUS) PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); - } -#endif /* OQS_DIST_BUILD */ -#else - return (OQS_STATUS) PQCLEAN_SPHINCSHARAKA128SROBUST_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); -#endif -} - -#endif diff --git a/src/sig/sphincs/sig_sphincs_haraka_128s_simple.c b/src/sig/sphincs/sig_sphincs_haraka_128s_simple.c deleted file mode 100644 index a24127abb4..0000000000 --- a/src/sig/sphincs/sig_sphincs_haraka_128s_simple.c +++ /dev/null @@ -1,90 +0,0 @@ -// SPDX-License-Identifier: MIT - -#include - -#include - -#if defined(OQS_ENABLE_SIG_sphincs_haraka_128s_simple) - -OQS_SIG *OQS_SIG_sphincs_haraka_128s_simple_new(void) { - - OQS_SIG *sig = malloc(sizeof(OQS_SIG)); - if (sig == NULL) { - return NULL; - } - sig->method_name = OQS_SIG_alg_sphincs_haraka_128s_simple; - sig->alg_version = "https://github.com/sphincs/sphincsplus/commit/ed15dd78658f63288c7492c00260d86154b84637"; - - sig->claimed_nist_level = 1; - sig->euf_cma = true; - - sig->length_public_key = OQS_SIG_sphincs_haraka_128s_simple_length_public_key; - sig->length_secret_key = OQS_SIG_sphincs_haraka_128s_simple_length_secret_key; - sig->length_signature = OQS_SIG_sphincs_haraka_128s_simple_length_signature; - - sig->keypair = OQS_SIG_sphincs_haraka_128s_simple_keypair; - sig->sign = OQS_SIG_sphincs_haraka_128s_simple_sign; - sig->verify = OQS_SIG_sphincs_haraka_128s_simple_verify; - - return sig; -} - -extern int PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); -extern int PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); -extern int PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); - -#if defined(OQS_ENABLE_SIG_sphincs_haraka_128s_simple_aesni) -extern int PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); -extern int PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); -extern int PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); -#endif - -OQS_API OQS_STATUS OQS_SIG_sphincs_haraka_128s_simple_keypair(uint8_t *public_key, uint8_t *secret_key) { -#if defined(OQS_ENABLE_SIG_sphincs_haraka_128s_simple_aesni) -#if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_AES)) { -#endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_crypto_sign_keypair(public_key, secret_key); -#if defined(OQS_DIST_BUILD) - } else { - return (OQS_STATUS) PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_crypto_sign_keypair(public_key, secret_key); - } -#endif /* OQS_DIST_BUILD */ -#else - return (OQS_STATUS) PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_crypto_sign_keypair(public_key, secret_key); -#endif -} - -OQS_API OQS_STATUS OQS_SIG_sphincs_haraka_128s_simple_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, const uint8_t *secret_key) { -#if defined(OQS_ENABLE_SIG_sphincs_haraka_128s_simple_aesni) -#if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_AES)) { -#endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); -#if defined(OQS_DIST_BUILD) - } else { - return (OQS_STATUS) PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); - } -#endif /* OQS_DIST_BUILD */ -#else - return (OQS_STATUS) PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); -#endif -} - -OQS_API OQS_STATUS OQS_SIG_sphincs_haraka_128s_simple_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key) { -#if defined(OQS_ENABLE_SIG_sphincs_haraka_128s_simple_aesni) -#if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_AES)) { -#endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSHARAKA128SSIMPLE_AESNI_crypto_sign_verify(signature, signature_len, message, message_len, public_key); -#if defined(OQS_DIST_BUILD) - } else { - return (OQS_STATUS) PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); - } -#endif /* OQS_DIST_BUILD */ -#else - return (OQS_STATUS) PQCLEAN_SPHINCSHARAKA128SSIMPLE_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); -#endif -} - -#endif diff --git a/src/sig/sphincs/sig_sphincs_haraka_192f_robust.c b/src/sig/sphincs/sig_sphincs_haraka_192f_robust.c deleted file mode 100644 index 9902a80f04..0000000000 --- a/src/sig/sphincs/sig_sphincs_haraka_192f_robust.c +++ /dev/null @@ -1,90 +0,0 @@ -// SPDX-License-Identifier: MIT - -#include - -#include - -#if defined(OQS_ENABLE_SIG_sphincs_haraka_192f_robust) - -OQS_SIG *OQS_SIG_sphincs_haraka_192f_robust_new(void) { - - OQS_SIG *sig = malloc(sizeof(OQS_SIG)); - if (sig == NULL) { - return NULL; - } - sig->method_name = OQS_SIG_alg_sphincs_haraka_192f_robust; - sig->alg_version = "https://github.com/sphincs/sphincsplus/commit/ed15dd78658f63288c7492c00260d86154b84637"; - - sig->claimed_nist_level = 2; - sig->euf_cma = true; - - sig->length_public_key = OQS_SIG_sphincs_haraka_192f_robust_length_public_key; - sig->length_secret_key = OQS_SIG_sphincs_haraka_192f_robust_length_secret_key; - sig->length_signature = OQS_SIG_sphincs_haraka_192f_robust_length_signature; - - sig->keypair = OQS_SIG_sphincs_haraka_192f_robust_keypair; - sig->sign = OQS_SIG_sphincs_haraka_192f_robust_sign; - sig->verify = OQS_SIG_sphincs_haraka_192f_robust_verify; - - return sig; -} - -extern int PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); -extern int PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); -extern int PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); - -#if defined(OQS_ENABLE_SIG_sphincs_haraka_192f_robust_aesni) -extern int PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); -extern int PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); -extern int PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); -#endif - -OQS_API OQS_STATUS OQS_SIG_sphincs_haraka_192f_robust_keypair(uint8_t *public_key, uint8_t *secret_key) { -#if defined(OQS_ENABLE_SIG_sphincs_haraka_192f_robust_aesni) -#if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_AES)) { -#endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_crypto_sign_keypair(public_key, secret_key); -#if defined(OQS_DIST_BUILD) - } else { - return (OQS_STATUS) PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_crypto_sign_keypair(public_key, secret_key); - } -#endif /* OQS_DIST_BUILD */ -#else - return (OQS_STATUS) PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_crypto_sign_keypair(public_key, secret_key); -#endif -} - -OQS_API OQS_STATUS OQS_SIG_sphincs_haraka_192f_robust_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, const uint8_t *secret_key) { -#if defined(OQS_ENABLE_SIG_sphincs_haraka_192f_robust_aesni) -#if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_AES)) { -#endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); -#if defined(OQS_DIST_BUILD) - } else { - return (OQS_STATUS) PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); - } -#endif /* OQS_DIST_BUILD */ -#else - return (OQS_STATUS) PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); -#endif -} - -OQS_API OQS_STATUS OQS_SIG_sphincs_haraka_192f_robust_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key) { -#if defined(OQS_ENABLE_SIG_sphincs_haraka_192f_robust_aesni) -#if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_AES)) { -#endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSHARAKA192FROBUST_AESNI_crypto_sign_verify(signature, signature_len, message, message_len, public_key); -#if defined(OQS_DIST_BUILD) - } else { - return (OQS_STATUS) PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); - } -#endif /* OQS_DIST_BUILD */ -#else - return (OQS_STATUS) PQCLEAN_SPHINCSHARAKA192FROBUST_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); -#endif -} - -#endif diff --git a/src/sig/sphincs/sig_sphincs_haraka_192f_simple.c b/src/sig/sphincs/sig_sphincs_haraka_192f_simple.c deleted file mode 100644 index 3d6766b6c7..0000000000 --- a/src/sig/sphincs/sig_sphincs_haraka_192f_simple.c +++ /dev/null @@ -1,90 +0,0 @@ -// SPDX-License-Identifier: MIT - -#include - -#include - -#if defined(OQS_ENABLE_SIG_sphincs_haraka_192f_simple) - -OQS_SIG *OQS_SIG_sphincs_haraka_192f_simple_new(void) { - - OQS_SIG *sig = malloc(sizeof(OQS_SIG)); - if (sig == NULL) { - return NULL; - } - sig->method_name = OQS_SIG_alg_sphincs_haraka_192f_simple; - sig->alg_version = "https://github.com/sphincs/sphincsplus/commit/ed15dd78658f63288c7492c00260d86154b84637"; - - sig->claimed_nist_level = 2; - sig->euf_cma = true; - - sig->length_public_key = OQS_SIG_sphincs_haraka_192f_simple_length_public_key; - sig->length_secret_key = OQS_SIG_sphincs_haraka_192f_simple_length_secret_key; - sig->length_signature = OQS_SIG_sphincs_haraka_192f_simple_length_signature; - - sig->keypair = OQS_SIG_sphincs_haraka_192f_simple_keypair; - sig->sign = OQS_SIG_sphincs_haraka_192f_simple_sign; - sig->verify = OQS_SIG_sphincs_haraka_192f_simple_verify; - - return sig; -} - -extern int PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); -extern int PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); -extern int PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); - -#if defined(OQS_ENABLE_SIG_sphincs_haraka_192f_simple_aesni) -extern int PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); -extern int PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); -extern int PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); -#endif - -OQS_API OQS_STATUS OQS_SIG_sphincs_haraka_192f_simple_keypair(uint8_t *public_key, uint8_t *secret_key) { -#if defined(OQS_ENABLE_SIG_sphincs_haraka_192f_simple_aesni) -#if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_AES)) { -#endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_crypto_sign_keypair(public_key, secret_key); -#if defined(OQS_DIST_BUILD) - } else { - return (OQS_STATUS) PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_crypto_sign_keypair(public_key, secret_key); - } -#endif /* OQS_DIST_BUILD */ -#else - return (OQS_STATUS) PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_crypto_sign_keypair(public_key, secret_key); -#endif -} - -OQS_API OQS_STATUS OQS_SIG_sphincs_haraka_192f_simple_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, const uint8_t *secret_key) { -#if defined(OQS_ENABLE_SIG_sphincs_haraka_192f_simple_aesni) -#if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_AES)) { -#endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); -#if defined(OQS_DIST_BUILD) - } else { - return (OQS_STATUS) PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); - } -#endif /* OQS_DIST_BUILD */ -#else - return (OQS_STATUS) PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); -#endif -} - -OQS_API OQS_STATUS OQS_SIG_sphincs_haraka_192f_simple_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key) { -#if defined(OQS_ENABLE_SIG_sphincs_haraka_192f_simple_aesni) -#if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_AES)) { -#endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSHARAKA192FSIMPLE_AESNI_crypto_sign_verify(signature, signature_len, message, message_len, public_key); -#if defined(OQS_DIST_BUILD) - } else { - return (OQS_STATUS) PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); - } -#endif /* OQS_DIST_BUILD */ -#else - return (OQS_STATUS) PQCLEAN_SPHINCSHARAKA192FSIMPLE_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); -#endif -} - -#endif diff --git a/src/sig/sphincs/sig_sphincs_haraka_192s_robust.c b/src/sig/sphincs/sig_sphincs_haraka_192s_robust.c deleted file mode 100644 index 156132e466..0000000000 --- a/src/sig/sphincs/sig_sphincs_haraka_192s_robust.c +++ /dev/null @@ -1,90 +0,0 @@ -// SPDX-License-Identifier: MIT - -#include - -#include - -#if defined(OQS_ENABLE_SIG_sphincs_haraka_192s_robust) - -OQS_SIG *OQS_SIG_sphincs_haraka_192s_robust_new(void) { - - OQS_SIG *sig = malloc(sizeof(OQS_SIG)); - if (sig == NULL) { - return NULL; - } - sig->method_name = OQS_SIG_alg_sphincs_haraka_192s_robust; - sig->alg_version = "https://github.com/sphincs/sphincsplus/commit/ed15dd78658f63288c7492c00260d86154b84637"; - - sig->claimed_nist_level = 2; - sig->euf_cma = true; - - sig->length_public_key = OQS_SIG_sphincs_haraka_192s_robust_length_public_key; - sig->length_secret_key = OQS_SIG_sphincs_haraka_192s_robust_length_secret_key; - sig->length_signature = OQS_SIG_sphincs_haraka_192s_robust_length_signature; - - sig->keypair = OQS_SIG_sphincs_haraka_192s_robust_keypair; - sig->sign = OQS_SIG_sphincs_haraka_192s_robust_sign; - sig->verify = OQS_SIG_sphincs_haraka_192s_robust_verify; - - return sig; -} - -extern int PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); -extern int PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); -extern int PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); - -#if defined(OQS_ENABLE_SIG_sphincs_haraka_192s_robust_aesni) -extern int PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); -extern int PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); -extern int PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); -#endif - -OQS_API OQS_STATUS OQS_SIG_sphincs_haraka_192s_robust_keypair(uint8_t *public_key, uint8_t *secret_key) { -#if defined(OQS_ENABLE_SIG_sphincs_haraka_192s_robust_aesni) -#if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_AES)) { -#endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_crypto_sign_keypair(public_key, secret_key); -#if defined(OQS_DIST_BUILD) - } else { - return (OQS_STATUS) PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_crypto_sign_keypair(public_key, secret_key); - } -#endif /* OQS_DIST_BUILD */ -#else - return (OQS_STATUS) PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_crypto_sign_keypair(public_key, secret_key); -#endif -} - -OQS_API OQS_STATUS OQS_SIG_sphincs_haraka_192s_robust_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, const uint8_t *secret_key) { -#if defined(OQS_ENABLE_SIG_sphincs_haraka_192s_robust_aesni) -#if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_AES)) { -#endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); -#if defined(OQS_DIST_BUILD) - } else { - return (OQS_STATUS) PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); - } -#endif /* OQS_DIST_BUILD */ -#else - return (OQS_STATUS) PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); -#endif -} - -OQS_API OQS_STATUS OQS_SIG_sphincs_haraka_192s_robust_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key) { -#if defined(OQS_ENABLE_SIG_sphincs_haraka_192s_robust_aesni) -#if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_AES)) { -#endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSHARAKA192SROBUST_AESNI_crypto_sign_verify(signature, signature_len, message, message_len, public_key); -#if defined(OQS_DIST_BUILD) - } else { - return (OQS_STATUS) PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); - } -#endif /* OQS_DIST_BUILD */ -#else - return (OQS_STATUS) PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); -#endif -} - -#endif diff --git a/src/sig/sphincs/sig_sphincs_haraka_192s_simple.c b/src/sig/sphincs/sig_sphincs_haraka_192s_simple.c deleted file mode 100644 index a14807f7e1..0000000000 --- a/src/sig/sphincs/sig_sphincs_haraka_192s_simple.c +++ /dev/null @@ -1,90 +0,0 @@ -// SPDX-License-Identifier: MIT - -#include - -#include - -#if defined(OQS_ENABLE_SIG_sphincs_haraka_192s_simple) - -OQS_SIG *OQS_SIG_sphincs_haraka_192s_simple_new(void) { - - OQS_SIG *sig = malloc(sizeof(OQS_SIG)); - if (sig == NULL) { - return NULL; - } - sig->method_name = OQS_SIG_alg_sphincs_haraka_192s_simple; - sig->alg_version = "https://github.com/sphincs/sphincsplus/commit/ed15dd78658f63288c7492c00260d86154b84637"; - - sig->claimed_nist_level = 2; - sig->euf_cma = true; - - sig->length_public_key = OQS_SIG_sphincs_haraka_192s_simple_length_public_key; - sig->length_secret_key = OQS_SIG_sphincs_haraka_192s_simple_length_secret_key; - sig->length_signature = OQS_SIG_sphincs_haraka_192s_simple_length_signature; - - sig->keypair = OQS_SIG_sphincs_haraka_192s_simple_keypair; - sig->sign = OQS_SIG_sphincs_haraka_192s_simple_sign; - sig->verify = OQS_SIG_sphincs_haraka_192s_simple_verify; - - return sig; -} - -extern int PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); -extern int PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); -extern int PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); - -#if defined(OQS_ENABLE_SIG_sphincs_haraka_192s_simple_aesni) -extern int PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); -extern int PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); -extern int PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); -#endif - -OQS_API OQS_STATUS OQS_SIG_sphincs_haraka_192s_simple_keypair(uint8_t *public_key, uint8_t *secret_key) { -#if defined(OQS_ENABLE_SIG_sphincs_haraka_192s_simple_aesni) -#if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_AES)) { -#endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_crypto_sign_keypair(public_key, secret_key); -#if defined(OQS_DIST_BUILD) - } else { - return (OQS_STATUS) PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_crypto_sign_keypair(public_key, secret_key); - } -#endif /* OQS_DIST_BUILD */ -#else - return (OQS_STATUS) PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_crypto_sign_keypair(public_key, secret_key); -#endif -} - -OQS_API OQS_STATUS OQS_SIG_sphincs_haraka_192s_simple_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, const uint8_t *secret_key) { -#if defined(OQS_ENABLE_SIG_sphincs_haraka_192s_simple_aesni) -#if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_AES)) { -#endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); -#if defined(OQS_DIST_BUILD) - } else { - return (OQS_STATUS) PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); - } -#endif /* OQS_DIST_BUILD */ -#else - return (OQS_STATUS) PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); -#endif -} - -OQS_API OQS_STATUS OQS_SIG_sphincs_haraka_192s_simple_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key) { -#if defined(OQS_ENABLE_SIG_sphincs_haraka_192s_simple_aesni) -#if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_AES)) { -#endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSHARAKA192SSIMPLE_AESNI_crypto_sign_verify(signature, signature_len, message, message_len, public_key); -#if defined(OQS_DIST_BUILD) - } else { - return (OQS_STATUS) PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); - } -#endif /* OQS_DIST_BUILD */ -#else - return (OQS_STATUS) PQCLEAN_SPHINCSHARAKA192SSIMPLE_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); -#endif -} - -#endif diff --git a/src/sig/sphincs/sig_sphincs_haraka_256f_robust.c b/src/sig/sphincs/sig_sphincs_haraka_256f_robust.c deleted file mode 100644 index 9da19bca9b..0000000000 --- a/src/sig/sphincs/sig_sphincs_haraka_256f_robust.c +++ /dev/null @@ -1,90 +0,0 @@ -// SPDX-License-Identifier: MIT - -#include - -#include - -#if defined(OQS_ENABLE_SIG_sphincs_haraka_256f_robust) - -OQS_SIG *OQS_SIG_sphincs_haraka_256f_robust_new(void) { - - OQS_SIG *sig = malloc(sizeof(OQS_SIG)); - if (sig == NULL) { - return NULL; - } - sig->method_name = OQS_SIG_alg_sphincs_haraka_256f_robust; - sig->alg_version = "https://github.com/sphincs/sphincsplus/commit/ed15dd78658f63288c7492c00260d86154b84637"; - - sig->claimed_nist_level = 2; - sig->euf_cma = true; - - sig->length_public_key = OQS_SIG_sphincs_haraka_256f_robust_length_public_key; - sig->length_secret_key = OQS_SIG_sphincs_haraka_256f_robust_length_secret_key; - sig->length_signature = OQS_SIG_sphincs_haraka_256f_robust_length_signature; - - sig->keypair = OQS_SIG_sphincs_haraka_256f_robust_keypair; - sig->sign = OQS_SIG_sphincs_haraka_256f_robust_sign; - sig->verify = OQS_SIG_sphincs_haraka_256f_robust_verify; - - return sig; -} - -extern int PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); -extern int PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); -extern int PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); - -#if defined(OQS_ENABLE_SIG_sphincs_haraka_256f_robust_aesni) -extern int PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); -extern int PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); -extern int PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); -#endif - -OQS_API OQS_STATUS OQS_SIG_sphincs_haraka_256f_robust_keypair(uint8_t *public_key, uint8_t *secret_key) { -#if defined(OQS_ENABLE_SIG_sphincs_haraka_256f_robust_aesni) -#if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_AES)) { -#endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_crypto_sign_keypair(public_key, secret_key); -#if defined(OQS_DIST_BUILD) - } else { - return (OQS_STATUS) PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_crypto_sign_keypair(public_key, secret_key); - } -#endif /* OQS_DIST_BUILD */ -#else - return (OQS_STATUS) PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_crypto_sign_keypair(public_key, secret_key); -#endif -} - -OQS_API OQS_STATUS OQS_SIG_sphincs_haraka_256f_robust_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, const uint8_t *secret_key) { -#if defined(OQS_ENABLE_SIG_sphincs_haraka_256f_robust_aesni) -#if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_AES)) { -#endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); -#if defined(OQS_DIST_BUILD) - } else { - return (OQS_STATUS) PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); - } -#endif /* OQS_DIST_BUILD */ -#else - return (OQS_STATUS) PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); -#endif -} - -OQS_API OQS_STATUS OQS_SIG_sphincs_haraka_256f_robust_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key) { -#if defined(OQS_ENABLE_SIG_sphincs_haraka_256f_robust_aesni) -#if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_AES)) { -#endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSHARAKA256FROBUST_AESNI_crypto_sign_verify(signature, signature_len, message, message_len, public_key); -#if defined(OQS_DIST_BUILD) - } else { - return (OQS_STATUS) PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); - } -#endif /* OQS_DIST_BUILD */ -#else - return (OQS_STATUS) PQCLEAN_SPHINCSHARAKA256FROBUST_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); -#endif -} - -#endif diff --git a/src/sig/sphincs/sig_sphincs_haraka_256f_simple.c b/src/sig/sphincs/sig_sphincs_haraka_256f_simple.c deleted file mode 100644 index c24c7989cc..0000000000 --- a/src/sig/sphincs/sig_sphincs_haraka_256f_simple.c +++ /dev/null @@ -1,90 +0,0 @@ -// SPDX-License-Identifier: MIT - -#include - -#include - -#if defined(OQS_ENABLE_SIG_sphincs_haraka_256f_simple) - -OQS_SIG *OQS_SIG_sphincs_haraka_256f_simple_new(void) { - - OQS_SIG *sig = malloc(sizeof(OQS_SIG)); - if (sig == NULL) { - return NULL; - } - sig->method_name = OQS_SIG_alg_sphincs_haraka_256f_simple; - sig->alg_version = "https://github.com/sphincs/sphincsplus/commit/ed15dd78658f63288c7492c00260d86154b84637"; - - sig->claimed_nist_level = 2; - sig->euf_cma = true; - - sig->length_public_key = OQS_SIG_sphincs_haraka_256f_simple_length_public_key; - sig->length_secret_key = OQS_SIG_sphincs_haraka_256f_simple_length_secret_key; - sig->length_signature = OQS_SIG_sphincs_haraka_256f_simple_length_signature; - - sig->keypair = OQS_SIG_sphincs_haraka_256f_simple_keypair; - sig->sign = OQS_SIG_sphincs_haraka_256f_simple_sign; - sig->verify = OQS_SIG_sphincs_haraka_256f_simple_verify; - - return sig; -} - -extern int PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); -extern int PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); -extern int PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); - -#if defined(OQS_ENABLE_SIG_sphincs_haraka_256f_simple_aesni) -extern int PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); -extern int PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); -extern int PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); -#endif - -OQS_API OQS_STATUS OQS_SIG_sphincs_haraka_256f_simple_keypair(uint8_t *public_key, uint8_t *secret_key) { -#if defined(OQS_ENABLE_SIG_sphincs_haraka_256f_simple_aesni) -#if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_AES)) { -#endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_crypto_sign_keypair(public_key, secret_key); -#if defined(OQS_DIST_BUILD) - } else { - return (OQS_STATUS) PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_crypto_sign_keypair(public_key, secret_key); - } -#endif /* OQS_DIST_BUILD */ -#else - return (OQS_STATUS) PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_crypto_sign_keypair(public_key, secret_key); -#endif -} - -OQS_API OQS_STATUS OQS_SIG_sphincs_haraka_256f_simple_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, const uint8_t *secret_key) { -#if defined(OQS_ENABLE_SIG_sphincs_haraka_256f_simple_aesni) -#if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_AES)) { -#endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); -#if defined(OQS_DIST_BUILD) - } else { - return (OQS_STATUS) PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); - } -#endif /* OQS_DIST_BUILD */ -#else - return (OQS_STATUS) PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); -#endif -} - -OQS_API OQS_STATUS OQS_SIG_sphincs_haraka_256f_simple_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key) { -#if defined(OQS_ENABLE_SIG_sphincs_haraka_256f_simple_aesni) -#if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_AES)) { -#endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSHARAKA256FSIMPLE_AESNI_crypto_sign_verify(signature, signature_len, message, message_len, public_key); -#if defined(OQS_DIST_BUILD) - } else { - return (OQS_STATUS) PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); - } -#endif /* OQS_DIST_BUILD */ -#else - return (OQS_STATUS) PQCLEAN_SPHINCSHARAKA256FSIMPLE_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); -#endif -} - -#endif diff --git a/src/sig/sphincs/sig_sphincs_haraka_256s_robust.c b/src/sig/sphincs/sig_sphincs_haraka_256s_robust.c deleted file mode 100644 index 3953a234f9..0000000000 --- a/src/sig/sphincs/sig_sphincs_haraka_256s_robust.c +++ /dev/null @@ -1,90 +0,0 @@ -// SPDX-License-Identifier: MIT - -#include - -#include - -#if defined(OQS_ENABLE_SIG_sphincs_haraka_256s_robust) - -OQS_SIG *OQS_SIG_sphincs_haraka_256s_robust_new(void) { - - OQS_SIG *sig = malloc(sizeof(OQS_SIG)); - if (sig == NULL) { - return NULL; - } - sig->method_name = OQS_SIG_alg_sphincs_haraka_256s_robust; - sig->alg_version = "https://github.com/sphincs/sphincsplus/commit/ed15dd78658f63288c7492c00260d86154b84637"; - - sig->claimed_nist_level = 2; - sig->euf_cma = true; - - sig->length_public_key = OQS_SIG_sphincs_haraka_256s_robust_length_public_key; - sig->length_secret_key = OQS_SIG_sphincs_haraka_256s_robust_length_secret_key; - sig->length_signature = OQS_SIG_sphincs_haraka_256s_robust_length_signature; - - sig->keypair = OQS_SIG_sphincs_haraka_256s_robust_keypair; - sig->sign = OQS_SIG_sphincs_haraka_256s_robust_sign; - sig->verify = OQS_SIG_sphincs_haraka_256s_robust_verify; - - return sig; -} - -extern int PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); -extern int PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); -extern int PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); - -#if defined(OQS_ENABLE_SIG_sphincs_haraka_256s_robust_aesni) -extern int PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); -extern int PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); -extern int PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); -#endif - -OQS_API OQS_STATUS OQS_SIG_sphincs_haraka_256s_robust_keypair(uint8_t *public_key, uint8_t *secret_key) { -#if defined(OQS_ENABLE_SIG_sphincs_haraka_256s_robust_aesni) -#if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_AES)) { -#endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_crypto_sign_keypair(public_key, secret_key); -#if defined(OQS_DIST_BUILD) - } else { - return (OQS_STATUS) PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_crypto_sign_keypair(public_key, secret_key); - } -#endif /* OQS_DIST_BUILD */ -#else - return (OQS_STATUS) PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_crypto_sign_keypair(public_key, secret_key); -#endif -} - -OQS_API OQS_STATUS OQS_SIG_sphincs_haraka_256s_robust_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, const uint8_t *secret_key) { -#if defined(OQS_ENABLE_SIG_sphincs_haraka_256s_robust_aesni) -#if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_AES)) { -#endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); -#if defined(OQS_DIST_BUILD) - } else { - return (OQS_STATUS) PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); - } -#endif /* OQS_DIST_BUILD */ -#else - return (OQS_STATUS) PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); -#endif -} - -OQS_API OQS_STATUS OQS_SIG_sphincs_haraka_256s_robust_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key) { -#if defined(OQS_ENABLE_SIG_sphincs_haraka_256s_robust_aesni) -#if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_AES)) { -#endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSHARAKA256SROBUST_AESNI_crypto_sign_verify(signature, signature_len, message, message_len, public_key); -#if defined(OQS_DIST_BUILD) - } else { - return (OQS_STATUS) PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); - } -#endif /* OQS_DIST_BUILD */ -#else - return (OQS_STATUS) PQCLEAN_SPHINCSHARAKA256SROBUST_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); -#endif -} - -#endif diff --git a/src/sig/sphincs/sig_sphincs_haraka_256s_simple.c b/src/sig/sphincs/sig_sphincs_haraka_256s_simple.c deleted file mode 100644 index 95c4f50857..0000000000 --- a/src/sig/sphincs/sig_sphincs_haraka_256s_simple.c +++ /dev/null @@ -1,90 +0,0 @@ -// SPDX-License-Identifier: MIT - -#include - -#include - -#if defined(OQS_ENABLE_SIG_sphincs_haraka_256s_simple) - -OQS_SIG *OQS_SIG_sphincs_haraka_256s_simple_new(void) { - - OQS_SIG *sig = malloc(sizeof(OQS_SIG)); - if (sig == NULL) { - return NULL; - } - sig->method_name = OQS_SIG_alg_sphincs_haraka_256s_simple; - sig->alg_version = "https://github.com/sphincs/sphincsplus/commit/ed15dd78658f63288c7492c00260d86154b84637"; - - sig->claimed_nist_level = 2; - sig->euf_cma = true; - - sig->length_public_key = OQS_SIG_sphincs_haraka_256s_simple_length_public_key; - sig->length_secret_key = OQS_SIG_sphincs_haraka_256s_simple_length_secret_key; - sig->length_signature = OQS_SIG_sphincs_haraka_256s_simple_length_signature; - - sig->keypair = OQS_SIG_sphincs_haraka_256s_simple_keypair; - sig->sign = OQS_SIG_sphincs_haraka_256s_simple_sign; - sig->verify = OQS_SIG_sphincs_haraka_256s_simple_verify; - - return sig; -} - -extern int PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); -extern int PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); -extern int PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); - -#if defined(OQS_ENABLE_SIG_sphincs_haraka_256s_simple_aesni) -extern int PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); -extern int PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); -extern int PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); -#endif - -OQS_API OQS_STATUS OQS_SIG_sphincs_haraka_256s_simple_keypair(uint8_t *public_key, uint8_t *secret_key) { -#if defined(OQS_ENABLE_SIG_sphincs_haraka_256s_simple_aesni) -#if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_AES)) { -#endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_crypto_sign_keypair(public_key, secret_key); -#if defined(OQS_DIST_BUILD) - } else { - return (OQS_STATUS) PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_crypto_sign_keypair(public_key, secret_key); - } -#endif /* OQS_DIST_BUILD */ -#else - return (OQS_STATUS) PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_crypto_sign_keypair(public_key, secret_key); -#endif -} - -OQS_API OQS_STATUS OQS_SIG_sphincs_haraka_256s_simple_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, const uint8_t *secret_key) { -#if defined(OQS_ENABLE_SIG_sphincs_haraka_256s_simple_aesni) -#if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_AES)) { -#endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); -#if defined(OQS_DIST_BUILD) - } else { - return (OQS_STATUS) PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); - } -#endif /* OQS_DIST_BUILD */ -#else - return (OQS_STATUS) PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); -#endif -} - -OQS_API OQS_STATUS OQS_SIG_sphincs_haraka_256s_simple_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key) { -#if defined(OQS_ENABLE_SIG_sphincs_haraka_256s_simple_aesni) -#if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_AES)) { -#endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSHARAKA256SSIMPLE_AESNI_crypto_sign_verify(signature, signature_len, message, message_len, public_key); -#if defined(OQS_DIST_BUILD) - } else { - return (OQS_STATUS) PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); - } -#endif /* OQS_DIST_BUILD */ -#else - return (OQS_STATUS) PQCLEAN_SPHINCSHARAKA256SSIMPLE_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); -#endif -} - -#endif diff --git a/src/sig/sphincs/sig_sphincs_sha256_128f_robust.c b/src/sig/sphincs/sig_sphincs_sha256_128f_robust.c deleted file mode 100644 index b5381800bc..0000000000 --- a/src/sig/sphincs/sig_sphincs_sha256_128f_robust.c +++ /dev/null @@ -1,90 +0,0 @@ -// SPDX-License-Identifier: MIT - -#include - -#include - -#if defined(OQS_ENABLE_SIG_sphincs_sha256_128f_robust) - -OQS_SIG *OQS_SIG_sphincs_sha256_128f_robust_new(void) { - - OQS_SIG *sig = malloc(sizeof(OQS_SIG)); - if (sig == NULL) { - return NULL; - } - sig->method_name = OQS_SIG_alg_sphincs_sha256_128f_robust; - sig->alg_version = "https://github.com/sphincs/sphincsplus/commit/ed15dd78658f63288c7492c00260d86154b84637"; - - sig->claimed_nist_level = 1; - sig->euf_cma = true; - - sig->length_public_key = OQS_SIG_sphincs_sha256_128f_robust_length_public_key; - sig->length_secret_key = OQS_SIG_sphincs_sha256_128f_robust_length_secret_key; - sig->length_signature = OQS_SIG_sphincs_sha256_128f_robust_length_signature; - - sig->keypair = OQS_SIG_sphincs_sha256_128f_robust_keypair; - sig->sign = OQS_SIG_sphincs_sha256_128f_robust_sign; - sig->verify = OQS_SIG_sphincs_sha256_128f_robust_verify; - - return sig; -} - -extern int PQCLEAN_SPHINCSSHA2128FROBUST_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); -extern int PQCLEAN_SPHINCSSHA2128FROBUST_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); -extern int PQCLEAN_SPHINCSSHA2128FROBUST_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); - -#if defined(OQS_ENABLE_SIG_sphincs_sha256_128f_robust_avx2) -extern int PQCLEAN_SPHINCSSHA2128FROBUST_AVX2_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); -extern int PQCLEAN_SPHINCSSHA2128FROBUST_AVX2_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); -extern int PQCLEAN_SPHINCSSHA2128FROBUST_AVX2_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); -#endif - -OQS_API OQS_STATUS OQS_SIG_sphincs_sha256_128f_robust_keypair(uint8_t *public_key, uint8_t *secret_key) { -#if defined(OQS_ENABLE_SIG_sphincs_sha256_128f_robust_avx2) -#if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) { -#endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHA2128FROBUST_AVX2_crypto_sign_keypair(public_key, secret_key); -#if defined(OQS_DIST_BUILD) - } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHA2128FROBUST_CLEAN_crypto_sign_keypair(public_key, secret_key); - } -#endif /* OQS_DIST_BUILD */ -#else - return (OQS_STATUS) PQCLEAN_SPHINCSSHA2128FROBUST_CLEAN_crypto_sign_keypair(public_key, secret_key); -#endif -} - -OQS_API OQS_STATUS OQS_SIG_sphincs_sha256_128f_robust_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, const uint8_t *secret_key) { -#if defined(OQS_ENABLE_SIG_sphincs_sha256_128f_robust_avx2) -#if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) { -#endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHA2128FROBUST_AVX2_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); -#if defined(OQS_DIST_BUILD) - } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHA2128FROBUST_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); - } -#endif /* OQS_DIST_BUILD */ -#else - return (OQS_STATUS) PQCLEAN_SPHINCSSHA2128FROBUST_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); -#endif -} - -OQS_API OQS_STATUS OQS_SIG_sphincs_sha256_128f_robust_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key) { -#if defined(OQS_ENABLE_SIG_sphincs_sha256_128f_robust_avx2) -#if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) { -#endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHA2128FROBUST_AVX2_crypto_sign_verify(signature, signature_len, message, message_len, public_key); -#if defined(OQS_DIST_BUILD) - } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHA2128FROBUST_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); - } -#endif /* OQS_DIST_BUILD */ -#else - return (OQS_STATUS) PQCLEAN_SPHINCSSHA2128FROBUST_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); -#endif -} - -#endif diff --git a/src/sig/sphincs/sig_sphincs_sha256_128s_robust.c b/src/sig/sphincs/sig_sphincs_sha256_128s_robust.c deleted file mode 100644 index df90a5f18f..0000000000 --- a/src/sig/sphincs/sig_sphincs_sha256_128s_robust.c +++ /dev/null @@ -1,90 +0,0 @@ -// SPDX-License-Identifier: MIT - -#include - -#include - -#if defined(OQS_ENABLE_SIG_sphincs_sha256_128s_robust) - -OQS_SIG *OQS_SIG_sphincs_sha256_128s_robust_new(void) { - - OQS_SIG *sig = malloc(sizeof(OQS_SIG)); - if (sig == NULL) { - return NULL; - } - sig->method_name = OQS_SIG_alg_sphincs_sha256_128s_robust; - sig->alg_version = "https://github.com/sphincs/sphincsplus/commit/ed15dd78658f63288c7492c00260d86154b84637"; - - sig->claimed_nist_level = 1; - sig->euf_cma = true; - - sig->length_public_key = OQS_SIG_sphincs_sha256_128s_robust_length_public_key; - sig->length_secret_key = OQS_SIG_sphincs_sha256_128s_robust_length_secret_key; - sig->length_signature = OQS_SIG_sphincs_sha256_128s_robust_length_signature; - - sig->keypair = OQS_SIG_sphincs_sha256_128s_robust_keypair; - sig->sign = OQS_SIG_sphincs_sha256_128s_robust_sign; - sig->verify = OQS_SIG_sphincs_sha256_128s_robust_verify; - - return sig; -} - -extern int PQCLEAN_SPHINCSSHA2128SROBUST_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); -extern int PQCLEAN_SPHINCSSHA2128SROBUST_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); -extern int PQCLEAN_SPHINCSSHA2128SROBUST_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); - -#if defined(OQS_ENABLE_SIG_sphincs_sha256_128s_robust_avx2) -extern int PQCLEAN_SPHINCSSHA2128SROBUST_AVX2_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); -extern int PQCLEAN_SPHINCSSHA2128SROBUST_AVX2_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); -extern int PQCLEAN_SPHINCSSHA2128SROBUST_AVX2_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); -#endif - -OQS_API OQS_STATUS OQS_SIG_sphincs_sha256_128s_robust_keypair(uint8_t *public_key, uint8_t *secret_key) { -#if defined(OQS_ENABLE_SIG_sphincs_sha256_128s_robust_avx2) -#if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) { -#endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHA2128SROBUST_AVX2_crypto_sign_keypair(public_key, secret_key); -#if defined(OQS_DIST_BUILD) - } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHA2128SROBUST_CLEAN_crypto_sign_keypair(public_key, secret_key); - } -#endif /* OQS_DIST_BUILD */ -#else - return (OQS_STATUS) PQCLEAN_SPHINCSSHA2128SROBUST_CLEAN_crypto_sign_keypair(public_key, secret_key); -#endif -} - -OQS_API OQS_STATUS OQS_SIG_sphincs_sha256_128s_robust_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, const uint8_t *secret_key) { -#if defined(OQS_ENABLE_SIG_sphincs_sha256_128s_robust_avx2) -#if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) { -#endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHA2128SROBUST_AVX2_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); -#if defined(OQS_DIST_BUILD) - } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHA2128SROBUST_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); - } -#endif /* OQS_DIST_BUILD */ -#else - return (OQS_STATUS) PQCLEAN_SPHINCSSHA2128SROBUST_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); -#endif -} - -OQS_API OQS_STATUS OQS_SIG_sphincs_sha256_128s_robust_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key) { -#if defined(OQS_ENABLE_SIG_sphincs_sha256_128s_robust_avx2) -#if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) { -#endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHA2128SROBUST_AVX2_crypto_sign_verify(signature, signature_len, message, message_len, public_key); -#if defined(OQS_DIST_BUILD) - } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHA2128SROBUST_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); - } -#endif /* OQS_DIST_BUILD */ -#else - return (OQS_STATUS) PQCLEAN_SPHINCSSHA2128SROBUST_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); -#endif -} - -#endif diff --git a/src/sig/sphincs/sig_sphincs_sha256_192f_robust.c b/src/sig/sphincs/sig_sphincs_sha256_192f_robust.c deleted file mode 100644 index d0ebaed095..0000000000 --- a/src/sig/sphincs/sig_sphincs_sha256_192f_robust.c +++ /dev/null @@ -1,90 +0,0 @@ -// SPDX-License-Identifier: MIT - -#include - -#include - -#if defined(OQS_ENABLE_SIG_sphincs_sha256_192f_robust) - -OQS_SIG *OQS_SIG_sphincs_sha256_192f_robust_new(void) { - - OQS_SIG *sig = malloc(sizeof(OQS_SIG)); - if (sig == NULL) { - return NULL; - } - sig->method_name = OQS_SIG_alg_sphincs_sha256_192f_robust; - sig->alg_version = "https://github.com/sphincs/sphincsplus/commit/ed15dd78658f63288c7492c00260d86154b84637"; - - sig->claimed_nist_level = 3; - sig->euf_cma = true; - - sig->length_public_key = OQS_SIG_sphincs_sha256_192f_robust_length_public_key; - sig->length_secret_key = OQS_SIG_sphincs_sha256_192f_robust_length_secret_key; - sig->length_signature = OQS_SIG_sphincs_sha256_192f_robust_length_signature; - - sig->keypair = OQS_SIG_sphincs_sha256_192f_robust_keypair; - sig->sign = OQS_SIG_sphincs_sha256_192f_robust_sign; - sig->verify = OQS_SIG_sphincs_sha256_192f_robust_verify; - - return sig; -} - -extern int PQCLEAN_SPHINCSSHA2192FROBUST_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); -extern int PQCLEAN_SPHINCSSHA2192FROBUST_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); -extern int PQCLEAN_SPHINCSSHA2192FROBUST_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); - -#if defined(OQS_ENABLE_SIG_sphincs_sha256_192f_robust_avx2) -extern int PQCLEAN_SPHINCSSHA2192FROBUST_AVX2_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); -extern int PQCLEAN_SPHINCSSHA2192FROBUST_AVX2_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); -extern int PQCLEAN_SPHINCSSHA2192FROBUST_AVX2_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); -#endif - -OQS_API OQS_STATUS OQS_SIG_sphincs_sha256_192f_robust_keypair(uint8_t *public_key, uint8_t *secret_key) { -#if defined(OQS_ENABLE_SIG_sphincs_sha256_192f_robust_avx2) -#if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) { -#endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHA2192FROBUST_AVX2_crypto_sign_keypair(public_key, secret_key); -#if defined(OQS_DIST_BUILD) - } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHA2192FROBUST_CLEAN_crypto_sign_keypair(public_key, secret_key); - } -#endif /* OQS_DIST_BUILD */ -#else - return (OQS_STATUS) PQCLEAN_SPHINCSSHA2192FROBUST_CLEAN_crypto_sign_keypair(public_key, secret_key); -#endif -} - -OQS_API OQS_STATUS OQS_SIG_sphincs_sha256_192f_robust_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, const uint8_t *secret_key) { -#if defined(OQS_ENABLE_SIG_sphincs_sha256_192f_robust_avx2) -#if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) { -#endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHA2192FROBUST_AVX2_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); -#if defined(OQS_DIST_BUILD) - } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHA2192FROBUST_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); - } -#endif /* OQS_DIST_BUILD */ -#else - return (OQS_STATUS) PQCLEAN_SPHINCSSHA2192FROBUST_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); -#endif -} - -OQS_API OQS_STATUS OQS_SIG_sphincs_sha256_192f_robust_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key) { -#if defined(OQS_ENABLE_SIG_sphincs_sha256_192f_robust_avx2) -#if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) { -#endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHA2192FROBUST_AVX2_crypto_sign_verify(signature, signature_len, message, message_len, public_key); -#if defined(OQS_DIST_BUILD) - } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHA2192FROBUST_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); - } -#endif /* OQS_DIST_BUILD */ -#else - return (OQS_STATUS) PQCLEAN_SPHINCSSHA2192FROBUST_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); -#endif -} - -#endif diff --git a/src/sig/sphincs/sig_sphincs_sha256_192s_robust.c b/src/sig/sphincs/sig_sphincs_sha256_192s_robust.c deleted file mode 100644 index 09a60c0cc8..0000000000 --- a/src/sig/sphincs/sig_sphincs_sha256_192s_robust.c +++ /dev/null @@ -1,90 +0,0 @@ -// SPDX-License-Identifier: MIT - -#include - -#include - -#if defined(OQS_ENABLE_SIG_sphincs_sha256_192s_robust) - -OQS_SIG *OQS_SIG_sphincs_sha256_192s_robust_new(void) { - - OQS_SIG *sig = malloc(sizeof(OQS_SIG)); - if (sig == NULL) { - return NULL; - } - sig->method_name = OQS_SIG_alg_sphincs_sha256_192s_robust; - sig->alg_version = "https://github.com/sphincs/sphincsplus/commit/ed15dd78658f63288c7492c00260d86154b84637"; - - sig->claimed_nist_level = 3; - sig->euf_cma = true; - - sig->length_public_key = OQS_SIG_sphincs_sha256_192s_robust_length_public_key; - sig->length_secret_key = OQS_SIG_sphincs_sha256_192s_robust_length_secret_key; - sig->length_signature = OQS_SIG_sphincs_sha256_192s_robust_length_signature; - - sig->keypair = OQS_SIG_sphincs_sha256_192s_robust_keypair; - sig->sign = OQS_SIG_sphincs_sha256_192s_robust_sign; - sig->verify = OQS_SIG_sphincs_sha256_192s_robust_verify; - - return sig; -} - -extern int PQCLEAN_SPHINCSSHA2192SROBUST_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); -extern int PQCLEAN_SPHINCSSHA2192SROBUST_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); -extern int PQCLEAN_SPHINCSSHA2192SROBUST_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); - -#if defined(OQS_ENABLE_SIG_sphincs_sha256_192s_robust_avx2) -extern int PQCLEAN_SPHINCSSHA2192SROBUST_AVX2_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); -extern int PQCLEAN_SPHINCSSHA2192SROBUST_AVX2_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); -extern int PQCLEAN_SPHINCSSHA2192SROBUST_AVX2_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); -#endif - -OQS_API OQS_STATUS OQS_SIG_sphincs_sha256_192s_robust_keypair(uint8_t *public_key, uint8_t *secret_key) { -#if defined(OQS_ENABLE_SIG_sphincs_sha256_192s_robust_avx2) -#if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) { -#endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHA2192SROBUST_AVX2_crypto_sign_keypair(public_key, secret_key); -#if defined(OQS_DIST_BUILD) - } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHA2192SROBUST_CLEAN_crypto_sign_keypair(public_key, secret_key); - } -#endif /* OQS_DIST_BUILD */ -#else - return (OQS_STATUS) PQCLEAN_SPHINCSSHA2192SROBUST_CLEAN_crypto_sign_keypair(public_key, secret_key); -#endif -} - -OQS_API OQS_STATUS OQS_SIG_sphincs_sha256_192s_robust_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, const uint8_t *secret_key) { -#if defined(OQS_ENABLE_SIG_sphincs_sha256_192s_robust_avx2) -#if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) { -#endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHA2192SROBUST_AVX2_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); -#if defined(OQS_DIST_BUILD) - } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHA2192SROBUST_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); - } -#endif /* OQS_DIST_BUILD */ -#else - return (OQS_STATUS) PQCLEAN_SPHINCSSHA2192SROBUST_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); -#endif -} - -OQS_API OQS_STATUS OQS_SIG_sphincs_sha256_192s_robust_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key) { -#if defined(OQS_ENABLE_SIG_sphincs_sha256_192s_robust_avx2) -#if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) { -#endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHA2192SROBUST_AVX2_crypto_sign_verify(signature, signature_len, message, message_len, public_key); -#if defined(OQS_DIST_BUILD) - } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHA2192SROBUST_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); - } -#endif /* OQS_DIST_BUILD */ -#else - return (OQS_STATUS) PQCLEAN_SPHINCSSHA2192SROBUST_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); -#endif -} - -#endif diff --git a/src/sig/sphincs/sig_sphincs_sha256_256f_robust.c b/src/sig/sphincs/sig_sphincs_sha256_256f_robust.c deleted file mode 100644 index 0798e77d52..0000000000 --- a/src/sig/sphincs/sig_sphincs_sha256_256f_robust.c +++ /dev/null @@ -1,90 +0,0 @@ -// SPDX-License-Identifier: MIT - -#include - -#include - -#if defined(OQS_ENABLE_SIG_sphincs_sha256_256f_robust) - -OQS_SIG *OQS_SIG_sphincs_sha256_256f_robust_new(void) { - - OQS_SIG *sig = malloc(sizeof(OQS_SIG)); - if (sig == NULL) { - return NULL; - } - sig->method_name = OQS_SIG_alg_sphincs_sha256_256f_robust; - sig->alg_version = "https://github.com/sphincs/sphincsplus/commit/ed15dd78658f63288c7492c00260d86154b84637"; - - sig->claimed_nist_level = 5; - sig->euf_cma = true; - - sig->length_public_key = OQS_SIG_sphincs_sha256_256f_robust_length_public_key; - sig->length_secret_key = OQS_SIG_sphincs_sha256_256f_robust_length_secret_key; - sig->length_signature = OQS_SIG_sphincs_sha256_256f_robust_length_signature; - - sig->keypair = OQS_SIG_sphincs_sha256_256f_robust_keypair; - sig->sign = OQS_SIG_sphincs_sha256_256f_robust_sign; - sig->verify = OQS_SIG_sphincs_sha256_256f_robust_verify; - - return sig; -} - -extern int PQCLEAN_SPHINCSSHA2256FROBUST_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); -extern int PQCLEAN_SPHINCSSHA2256FROBUST_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); -extern int PQCLEAN_SPHINCSSHA2256FROBUST_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); - -#if defined(OQS_ENABLE_SIG_sphincs_sha256_256f_robust_avx2) -extern int PQCLEAN_SPHINCSSHA2256FROBUST_AVX2_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); -extern int PQCLEAN_SPHINCSSHA2256FROBUST_AVX2_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); -extern int PQCLEAN_SPHINCSSHA2256FROBUST_AVX2_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); -#endif - -OQS_API OQS_STATUS OQS_SIG_sphincs_sha256_256f_robust_keypair(uint8_t *public_key, uint8_t *secret_key) { -#if defined(OQS_ENABLE_SIG_sphincs_sha256_256f_robust_avx2) -#if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) { -#endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHA2256FROBUST_AVX2_crypto_sign_keypair(public_key, secret_key); -#if defined(OQS_DIST_BUILD) - } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHA2256FROBUST_CLEAN_crypto_sign_keypair(public_key, secret_key); - } -#endif /* OQS_DIST_BUILD */ -#else - return (OQS_STATUS) PQCLEAN_SPHINCSSHA2256FROBUST_CLEAN_crypto_sign_keypair(public_key, secret_key); -#endif -} - -OQS_API OQS_STATUS OQS_SIG_sphincs_sha256_256f_robust_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, const uint8_t *secret_key) { -#if defined(OQS_ENABLE_SIG_sphincs_sha256_256f_robust_avx2) -#if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) { -#endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHA2256FROBUST_AVX2_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); -#if defined(OQS_DIST_BUILD) - } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHA2256FROBUST_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); - } -#endif /* OQS_DIST_BUILD */ -#else - return (OQS_STATUS) PQCLEAN_SPHINCSSHA2256FROBUST_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); -#endif -} - -OQS_API OQS_STATUS OQS_SIG_sphincs_sha256_256f_robust_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key) { -#if defined(OQS_ENABLE_SIG_sphincs_sha256_256f_robust_avx2) -#if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) { -#endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHA2256FROBUST_AVX2_crypto_sign_verify(signature, signature_len, message, message_len, public_key); -#if defined(OQS_DIST_BUILD) - } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHA2256FROBUST_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); - } -#endif /* OQS_DIST_BUILD */ -#else - return (OQS_STATUS) PQCLEAN_SPHINCSSHA2256FROBUST_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); -#endif -} - -#endif diff --git a/src/sig/sphincs/sig_sphincs_sha256_256s_robust.c b/src/sig/sphincs/sig_sphincs_sha256_256s_robust.c deleted file mode 100644 index f2b4ae772e..0000000000 --- a/src/sig/sphincs/sig_sphincs_sha256_256s_robust.c +++ /dev/null @@ -1,90 +0,0 @@ -// SPDX-License-Identifier: MIT - -#include - -#include - -#if defined(OQS_ENABLE_SIG_sphincs_sha256_256s_robust) - -OQS_SIG *OQS_SIG_sphincs_sha256_256s_robust_new(void) { - - OQS_SIG *sig = malloc(sizeof(OQS_SIG)); - if (sig == NULL) { - return NULL; - } - sig->method_name = OQS_SIG_alg_sphincs_sha256_256s_robust; - sig->alg_version = "https://github.com/sphincs/sphincsplus/commit/ed15dd78658f63288c7492c00260d86154b84637"; - - sig->claimed_nist_level = 5; - sig->euf_cma = true; - - sig->length_public_key = OQS_SIG_sphincs_sha256_256s_robust_length_public_key; - sig->length_secret_key = OQS_SIG_sphincs_sha256_256s_robust_length_secret_key; - sig->length_signature = OQS_SIG_sphincs_sha256_256s_robust_length_signature; - - sig->keypair = OQS_SIG_sphincs_sha256_256s_robust_keypair; - sig->sign = OQS_SIG_sphincs_sha256_256s_robust_sign; - sig->verify = OQS_SIG_sphincs_sha256_256s_robust_verify; - - return sig; -} - -extern int PQCLEAN_SPHINCSSHA2256SROBUST_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); -extern int PQCLEAN_SPHINCSSHA2256SROBUST_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); -extern int PQCLEAN_SPHINCSSHA2256SROBUST_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); - -#if defined(OQS_ENABLE_SIG_sphincs_sha256_256s_robust_avx2) -extern int PQCLEAN_SPHINCSSHA2256SROBUST_AVX2_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); -extern int PQCLEAN_SPHINCSSHA2256SROBUST_AVX2_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); -extern int PQCLEAN_SPHINCSSHA2256SROBUST_AVX2_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); -#endif - -OQS_API OQS_STATUS OQS_SIG_sphincs_sha256_256s_robust_keypair(uint8_t *public_key, uint8_t *secret_key) { -#if defined(OQS_ENABLE_SIG_sphincs_sha256_256s_robust_avx2) -#if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) { -#endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHA2256SROBUST_AVX2_crypto_sign_keypair(public_key, secret_key); -#if defined(OQS_DIST_BUILD) - } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHA2256SROBUST_CLEAN_crypto_sign_keypair(public_key, secret_key); - } -#endif /* OQS_DIST_BUILD */ -#else - return (OQS_STATUS) PQCLEAN_SPHINCSSHA2256SROBUST_CLEAN_crypto_sign_keypair(public_key, secret_key); -#endif -} - -OQS_API OQS_STATUS OQS_SIG_sphincs_sha256_256s_robust_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, const uint8_t *secret_key) { -#if defined(OQS_ENABLE_SIG_sphincs_sha256_256s_robust_avx2) -#if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) { -#endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHA2256SROBUST_AVX2_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); -#if defined(OQS_DIST_BUILD) - } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHA2256SROBUST_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); - } -#endif /* OQS_DIST_BUILD */ -#else - return (OQS_STATUS) PQCLEAN_SPHINCSSHA2256SROBUST_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); -#endif -} - -OQS_API OQS_STATUS OQS_SIG_sphincs_sha256_256s_robust_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key) { -#if defined(OQS_ENABLE_SIG_sphincs_sha256_256s_robust_avx2) -#if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) { -#endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHA2256SROBUST_AVX2_crypto_sign_verify(signature, signature_len, message, message_len, public_key); -#if defined(OQS_DIST_BUILD) - } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHA2256SROBUST_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); - } -#endif /* OQS_DIST_BUILD */ -#else - return (OQS_STATUS) PQCLEAN_SPHINCSSHA2256SROBUST_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); -#endif -} - -#endif diff --git a/src/sig/sphincs/sig_sphincs_shake256_128f_robust.c b/src/sig/sphincs/sig_sphincs_shake256_128f_robust.c deleted file mode 100644 index 7b15bd4223..0000000000 --- a/src/sig/sphincs/sig_sphincs_shake256_128f_robust.c +++ /dev/null @@ -1,126 +0,0 @@ -// SPDX-License-Identifier: MIT - -#include - -#include - -#if defined(OQS_ENABLE_SIG_sphincs_shake256_128f_robust) - -OQS_SIG *OQS_SIG_sphincs_shake256_128f_robust_new(void) { - - OQS_SIG *sig = malloc(sizeof(OQS_SIG)); - if (sig == NULL) { - return NULL; - } - sig->method_name = OQS_SIG_alg_sphincs_shake256_128f_robust; - sig->alg_version = "https://github.com/sphincs/sphincsplus/commit/ed15dd78658f63288c7492c00260d86154b84637"; - - sig->claimed_nist_level = 1; - sig->euf_cma = true; - - sig->length_public_key = OQS_SIG_sphincs_shake256_128f_robust_length_public_key; - sig->length_secret_key = OQS_SIG_sphincs_shake256_128f_robust_length_secret_key; - sig->length_signature = OQS_SIG_sphincs_shake256_128f_robust_length_signature; - - sig->keypair = OQS_SIG_sphincs_shake256_128f_robust_keypair; - sig->sign = OQS_SIG_sphincs_shake256_128f_robust_sign; - sig->verify = OQS_SIG_sphincs_shake256_128f_robust_verify; - - return sig; -} - -extern int PQCLEAN_SPHINCSSHAKE128FROBUST_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); -extern int PQCLEAN_SPHINCSSHAKE128FROBUST_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); -extern int PQCLEAN_SPHINCSSHAKE128FROBUST_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); - -#if defined(OQS_ENABLE_SIG_sphincs_shake256_128f_robust_avx2) -extern int PQCLEAN_SPHINCSSHAKE128FROBUST_AVX2_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); -extern int PQCLEAN_SPHINCSSHAKE128FROBUST_AVX2_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); -extern int PQCLEAN_SPHINCSSHAKE128FROBUST_AVX2_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); -#endif - -#if defined(OQS_ENABLE_SIG_sphincs_shake256_128f_robust_aarch64) -extern int PQCLEAN_SPHINCSSHAKE128FROBUST_AARCH64_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); -extern int PQCLEAN_SPHINCSSHAKE128FROBUST_AARCH64_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); -extern int PQCLEAN_SPHINCSSHAKE128FROBUST_AARCH64_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); -#endif - -OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_128f_robust_keypair(uint8_t *public_key, uint8_t *secret_key) { -#if defined(OQS_ENABLE_SIG_sphincs_shake256_128f_robust_avx2) -#if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) { -#endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE128FROBUST_AVX2_crypto_sign_keypair(public_key, secret_key); -#if defined(OQS_DIST_BUILD) - } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE128FROBUST_CLEAN_crypto_sign_keypair(public_key, secret_key); - } -#endif /* OQS_DIST_BUILD */ -#elif defined(OQS_ENABLE_SIG_sphincs_shake256_128f_robust_aarch64) -#if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_ARM_SHA3)) { -#endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE128FROBUST_AARCH64_crypto_sign_keypair(public_key, secret_key); -#if defined(OQS_DIST_BUILD) - } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE128FROBUST_CLEAN_crypto_sign_keypair(public_key, secret_key); - } -#endif /* OQS_DIST_BUILD */ -#else - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE128FROBUST_CLEAN_crypto_sign_keypair(public_key, secret_key); -#endif -} - -OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_128f_robust_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, const uint8_t *secret_key) { -#if defined(OQS_ENABLE_SIG_sphincs_shake256_128f_robust_avx2) -#if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) { -#endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE128FROBUST_AVX2_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); -#if defined(OQS_DIST_BUILD) - } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE128FROBUST_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); - } -#endif /* OQS_DIST_BUILD */ -#elif defined(OQS_ENABLE_SIG_sphincs_shake256_128f_robust_aarch64) -#if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_ARM_SHA3)) { -#endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE128FROBUST_AARCH64_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); -#if defined(OQS_DIST_BUILD) - } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE128FROBUST_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); - } -#endif /* OQS_DIST_BUILD */ -#else - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE128FROBUST_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); -#endif -} - -OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_128f_robust_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key) { -#if defined(OQS_ENABLE_SIG_sphincs_shake256_128f_robust_avx2) -#if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) { -#endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE128FROBUST_AVX2_crypto_sign_verify(signature, signature_len, message, message_len, public_key); -#if defined(OQS_DIST_BUILD) - } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE128FROBUST_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); - } -#endif /* OQS_DIST_BUILD */ -#elif defined(OQS_ENABLE_SIG_sphincs_shake256_128f_robust_aarch64) -#if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_ARM_SHA3)) { -#endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE128FROBUST_AARCH64_crypto_sign_verify(signature, signature_len, message, message_len, public_key); -#if defined(OQS_DIST_BUILD) - } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE128FROBUST_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); - } -#endif /* OQS_DIST_BUILD */ -#else - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE128FROBUST_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); -#endif -} - -#endif diff --git a/src/sig/sphincs/sig_sphincs_shake256_128s_robust.c b/src/sig/sphincs/sig_sphincs_shake256_128s_robust.c deleted file mode 100644 index d8ee5dfee8..0000000000 --- a/src/sig/sphincs/sig_sphincs_shake256_128s_robust.c +++ /dev/null @@ -1,126 +0,0 @@ -// SPDX-License-Identifier: MIT - -#include - -#include - -#if defined(OQS_ENABLE_SIG_sphincs_shake256_128s_robust) - -OQS_SIG *OQS_SIG_sphincs_shake256_128s_robust_new(void) { - - OQS_SIG *sig = malloc(sizeof(OQS_SIG)); - if (sig == NULL) { - return NULL; - } - sig->method_name = OQS_SIG_alg_sphincs_shake256_128s_robust; - sig->alg_version = "https://github.com/sphincs/sphincsplus/commit/ed15dd78658f63288c7492c00260d86154b84637"; - - sig->claimed_nist_level = 1; - sig->euf_cma = true; - - sig->length_public_key = OQS_SIG_sphincs_shake256_128s_robust_length_public_key; - sig->length_secret_key = OQS_SIG_sphincs_shake256_128s_robust_length_secret_key; - sig->length_signature = OQS_SIG_sphincs_shake256_128s_robust_length_signature; - - sig->keypair = OQS_SIG_sphincs_shake256_128s_robust_keypair; - sig->sign = OQS_SIG_sphincs_shake256_128s_robust_sign; - sig->verify = OQS_SIG_sphincs_shake256_128s_robust_verify; - - return sig; -} - -extern int PQCLEAN_SPHINCSSHAKE128SROBUST_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); -extern int PQCLEAN_SPHINCSSHAKE128SROBUST_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); -extern int PQCLEAN_SPHINCSSHAKE128SROBUST_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); - -#if defined(OQS_ENABLE_SIG_sphincs_shake256_128s_robust_avx2) -extern int PQCLEAN_SPHINCSSHAKE128SROBUST_AVX2_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); -extern int PQCLEAN_SPHINCSSHAKE128SROBUST_AVX2_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); -extern int PQCLEAN_SPHINCSSHAKE128SROBUST_AVX2_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); -#endif - -#if defined(OQS_ENABLE_SIG_sphincs_shake256_128s_robust_aarch64) -extern int PQCLEAN_SPHINCSSHAKE128SROBUST_AARCH64_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); -extern int PQCLEAN_SPHINCSSHAKE128SROBUST_AARCH64_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); -extern int PQCLEAN_SPHINCSSHAKE128SROBUST_AARCH64_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); -#endif - -OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_128s_robust_keypair(uint8_t *public_key, uint8_t *secret_key) { -#if defined(OQS_ENABLE_SIG_sphincs_shake256_128s_robust_avx2) -#if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) { -#endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE128SROBUST_AVX2_crypto_sign_keypair(public_key, secret_key); -#if defined(OQS_DIST_BUILD) - } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE128SROBUST_CLEAN_crypto_sign_keypair(public_key, secret_key); - } -#endif /* OQS_DIST_BUILD */ -#elif defined(OQS_ENABLE_SIG_sphincs_shake256_128s_robust_aarch64) -#if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_ARM_SHA3)) { -#endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE128SROBUST_AARCH64_crypto_sign_keypair(public_key, secret_key); -#if defined(OQS_DIST_BUILD) - } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE128SROBUST_CLEAN_crypto_sign_keypair(public_key, secret_key); - } -#endif /* OQS_DIST_BUILD */ -#else - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE128SROBUST_CLEAN_crypto_sign_keypair(public_key, secret_key); -#endif -} - -OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_128s_robust_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, const uint8_t *secret_key) { -#if defined(OQS_ENABLE_SIG_sphincs_shake256_128s_robust_avx2) -#if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) { -#endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE128SROBUST_AVX2_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); -#if defined(OQS_DIST_BUILD) - } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE128SROBUST_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); - } -#endif /* OQS_DIST_BUILD */ -#elif defined(OQS_ENABLE_SIG_sphincs_shake256_128s_robust_aarch64) -#if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_ARM_SHA3)) { -#endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE128SROBUST_AARCH64_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); -#if defined(OQS_DIST_BUILD) - } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE128SROBUST_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); - } -#endif /* OQS_DIST_BUILD */ -#else - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE128SROBUST_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); -#endif -} - -OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_128s_robust_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key) { -#if defined(OQS_ENABLE_SIG_sphincs_shake256_128s_robust_avx2) -#if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) { -#endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE128SROBUST_AVX2_crypto_sign_verify(signature, signature_len, message, message_len, public_key); -#if defined(OQS_DIST_BUILD) - } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE128SROBUST_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); - } -#endif /* OQS_DIST_BUILD */ -#elif defined(OQS_ENABLE_SIG_sphincs_shake256_128s_robust_aarch64) -#if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_ARM_SHA3)) { -#endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE128SROBUST_AARCH64_crypto_sign_verify(signature, signature_len, message, message_len, public_key); -#if defined(OQS_DIST_BUILD) - } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE128SROBUST_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); - } -#endif /* OQS_DIST_BUILD */ -#else - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE128SROBUST_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); -#endif -} - -#endif diff --git a/src/sig/sphincs/sig_sphincs_shake256_192f_robust.c b/src/sig/sphincs/sig_sphincs_shake256_192f_robust.c deleted file mode 100644 index 827c3a4ffd..0000000000 --- a/src/sig/sphincs/sig_sphincs_shake256_192f_robust.c +++ /dev/null @@ -1,126 +0,0 @@ -// SPDX-License-Identifier: MIT - -#include - -#include - -#if defined(OQS_ENABLE_SIG_sphincs_shake256_192f_robust) - -OQS_SIG *OQS_SIG_sphincs_shake256_192f_robust_new(void) { - - OQS_SIG *sig = malloc(sizeof(OQS_SIG)); - if (sig == NULL) { - return NULL; - } - sig->method_name = OQS_SIG_alg_sphincs_shake256_192f_robust; - sig->alg_version = "https://github.com/sphincs/sphincsplus/commit/ed15dd78658f63288c7492c00260d86154b84637"; - - sig->claimed_nist_level = 3; - sig->euf_cma = true; - - sig->length_public_key = OQS_SIG_sphincs_shake256_192f_robust_length_public_key; - sig->length_secret_key = OQS_SIG_sphincs_shake256_192f_robust_length_secret_key; - sig->length_signature = OQS_SIG_sphincs_shake256_192f_robust_length_signature; - - sig->keypair = OQS_SIG_sphincs_shake256_192f_robust_keypair; - sig->sign = OQS_SIG_sphincs_shake256_192f_robust_sign; - sig->verify = OQS_SIG_sphincs_shake256_192f_robust_verify; - - return sig; -} - -extern int PQCLEAN_SPHINCSSHAKE192FROBUST_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); -extern int PQCLEAN_SPHINCSSHAKE192FROBUST_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); -extern int PQCLEAN_SPHINCSSHAKE192FROBUST_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); - -#if defined(OQS_ENABLE_SIG_sphincs_shake256_192f_robust_avx2) -extern int PQCLEAN_SPHINCSSHAKE192FROBUST_AVX2_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); -extern int PQCLEAN_SPHINCSSHAKE192FROBUST_AVX2_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); -extern int PQCLEAN_SPHINCSSHAKE192FROBUST_AVX2_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); -#endif - -#if defined(OQS_ENABLE_SIG_sphincs_shake256_192f_robust_aarch64) -extern int PQCLEAN_SPHINCSSHAKE192FROBUST_AARCH64_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); -extern int PQCLEAN_SPHINCSSHAKE192FROBUST_AARCH64_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); -extern int PQCLEAN_SPHINCSSHAKE192FROBUST_AARCH64_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); -#endif - -OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_192f_robust_keypair(uint8_t *public_key, uint8_t *secret_key) { -#if defined(OQS_ENABLE_SIG_sphincs_shake256_192f_robust_avx2) -#if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) { -#endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE192FROBUST_AVX2_crypto_sign_keypair(public_key, secret_key); -#if defined(OQS_DIST_BUILD) - } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE192FROBUST_CLEAN_crypto_sign_keypair(public_key, secret_key); - } -#endif /* OQS_DIST_BUILD */ -#elif defined(OQS_ENABLE_SIG_sphincs_shake256_192f_robust_aarch64) -#if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_ARM_SHA3)) { -#endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE192FROBUST_AARCH64_crypto_sign_keypair(public_key, secret_key); -#if defined(OQS_DIST_BUILD) - } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE192FROBUST_CLEAN_crypto_sign_keypair(public_key, secret_key); - } -#endif /* OQS_DIST_BUILD */ -#else - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE192FROBUST_CLEAN_crypto_sign_keypair(public_key, secret_key); -#endif -} - -OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_192f_robust_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, const uint8_t *secret_key) { -#if defined(OQS_ENABLE_SIG_sphincs_shake256_192f_robust_avx2) -#if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) { -#endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE192FROBUST_AVX2_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); -#if defined(OQS_DIST_BUILD) - } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE192FROBUST_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); - } -#endif /* OQS_DIST_BUILD */ -#elif defined(OQS_ENABLE_SIG_sphincs_shake256_192f_robust_aarch64) -#if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_ARM_SHA3)) { -#endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE192FROBUST_AARCH64_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); -#if defined(OQS_DIST_BUILD) - } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE192FROBUST_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); - } -#endif /* OQS_DIST_BUILD */ -#else - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE192FROBUST_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); -#endif -} - -OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_192f_robust_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key) { -#if defined(OQS_ENABLE_SIG_sphincs_shake256_192f_robust_avx2) -#if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) { -#endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE192FROBUST_AVX2_crypto_sign_verify(signature, signature_len, message, message_len, public_key); -#if defined(OQS_DIST_BUILD) - } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE192FROBUST_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); - } -#endif /* OQS_DIST_BUILD */ -#elif defined(OQS_ENABLE_SIG_sphincs_shake256_192f_robust_aarch64) -#if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_ARM_SHA3)) { -#endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE192FROBUST_AARCH64_crypto_sign_verify(signature, signature_len, message, message_len, public_key); -#if defined(OQS_DIST_BUILD) - } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE192FROBUST_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); - } -#endif /* OQS_DIST_BUILD */ -#else - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE192FROBUST_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); -#endif -} - -#endif diff --git a/src/sig/sphincs/sig_sphincs_shake256_192s_robust.c b/src/sig/sphincs/sig_sphincs_shake256_192s_robust.c deleted file mode 100644 index 6299f87b55..0000000000 --- a/src/sig/sphincs/sig_sphincs_shake256_192s_robust.c +++ /dev/null @@ -1,126 +0,0 @@ -// SPDX-License-Identifier: MIT - -#include - -#include - -#if defined(OQS_ENABLE_SIG_sphincs_shake256_192s_robust) - -OQS_SIG *OQS_SIG_sphincs_shake256_192s_robust_new(void) { - - OQS_SIG *sig = malloc(sizeof(OQS_SIG)); - if (sig == NULL) { - return NULL; - } - sig->method_name = OQS_SIG_alg_sphincs_shake256_192s_robust; - sig->alg_version = "https://github.com/sphincs/sphincsplus/commit/ed15dd78658f63288c7492c00260d86154b84637"; - - sig->claimed_nist_level = 3; - sig->euf_cma = true; - - sig->length_public_key = OQS_SIG_sphincs_shake256_192s_robust_length_public_key; - sig->length_secret_key = OQS_SIG_sphincs_shake256_192s_robust_length_secret_key; - sig->length_signature = OQS_SIG_sphincs_shake256_192s_robust_length_signature; - - sig->keypair = OQS_SIG_sphincs_shake256_192s_robust_keypair; - sig->sign = OQS_SIG_sphincs_shake256_192s_robust_sign; - sig->verify = OQS_SIG_sphincs_shake256_192s_robust_verify; - - return sig; -} - -extern int PQCLEAN_SPHINCSSHAKE192SROBUST_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); -extern int PQCLEAN_SPHINCSSHAKE192SROBUST_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); -extern int PQCLEAN_SPHINCSSHAKE192SROBUST_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); - -#if defined(OQS_ENABLE_SIG_sphincs_shake256_192s_robust_avx2) -extern int PQCLEAN_SPHINCSSHAKE192SROBUST_AVX2_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); -extern int PQCLEAN_SPHINCSSHAKE192SROBUST_AVX2_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); -extern int PQCLEAN_SPHINCSSHAKE192SROBUST_AVX2_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); -#endif - -#if defined(OQS_ENABLE_SIG_sphincs_shake256_192s_robust_aarch64) -extern int PQCLEAN_SPHINCSSHAKE192SROBUST_AARCH64_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); -extern int PQCLEAN_SPHINCSSHAKE192SROBUST_AARCH64_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); -extern int PQCLEAN_SPHINCSSHAKE192SROBUST_AARCH64_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); -#endif - -OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_192s_robust_keypair(uint8_t *public_key, uint8_t *secret_key) { -#if defined(OQS_ENABLE_SIG_sphincs_shake256_192s_robust_avx2) -#if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) { -#endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE192SROBUST_AVX2_crypto_sign_keypair(public_key, secret_key); -#if defined(OQS_DIST_BUILD) - } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE192SROBUST_CLEAN_crypto_sign_keypair(public_key, secret_key); - } -#endif /* OQS_DIST_BUILD */ -#elif defined(OQS_ENABLE_SIG_sphincs_shake256_192s_robust_aarch64) -#if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_ARM_SHA3)) { -#endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE192SROBUST_AARCH64_crypto_sign_keypair(public_key, secret_key); -#if defined(OQS_DIST_BUILD) - } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE192SROBUST_CLEAN_crypto_sign_keypair(public_key, secret_key); - } -#endif /* OQS_DIST_BUILD */ -#else - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE192SROBUST_CLEAN_crypto_sign_keypair(public_key, secret_key); -#endif -} - -OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_192s_robust_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, const uint8_t *secret_key) { -#if defined(OQS_ENABLE_SIG_sphincs_shake256_192s_robust_avx2) -#if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) { -#endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE192SROBUST_AVX2_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); -#if defined(OQS_DIST_BUILD) - } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE192SROBUST_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); - } -#endif /* OQS_DIST_BUILD */ -#elif defined(OQS_ENABLE_SIG_sphincs_shake256_192s_robust_aarch64) -#if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_ARM_SHA3)) { -#endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE192SROBUST_AARCH64_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); -#if defined(OQS_DIST_BUILD) - } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE192SROBUST_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); - } -#endif /* OQS_DIST_BUILD */ -#else - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE192SROBUST_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); -#endif -} - -OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_192s_robust_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key) { -#if defined(OQS_ENABLE_SIG_sphincs_shake256_192s_robust_avx2) -#if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) { -#endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE192SROBUST_AVX2_crypto_sign_verify(signature, signature_len, message, message_len, public_key); -#if defined(OQS_DIST_BUILD) - } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE192SROBUST_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); - } -#endif /* OQS_DIST_BUILD */ -#elif defined(OQS_ENABLE_SIG_sphincs_shake256_192s_robust_aarch64) -#if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_ARM_SHA3)) { -#endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE192SROBUST_AARCH64_crypto_sign_verify(signature, signature_len, message, message_len, public_key); -#if defined(OQS_DIST_BUILD) - } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE192SROBUST_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); - } -#endif /* OQS_DIST_BUILD */ -#else - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE192SROBUST_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); -#endif -} - -#endif diff --git a/src/sig/sphincs/sig_sphincs_shake256_256f_robust.c b/src/sig/sphincs/sig_sphincs_shake256_256f_robust.c deleted file mode 100644 index 47cd89e6f9..0000000000 --- a/src/sig/sphincs/sig_sphincs_shake256_256f_robust.c +++ /dev/null @@ -1,126 +0,0 @@ -// SPDX-License-Identifier: MIT - -#include - -#include - -#if defined(OQS_ENABLE_SIG_sphincs_shake256_256f_robust) - -OQS_SIG *OQS_SIG_sphincs_shake256_256f_robust_new(void) { - - OQS_SIG *sig = malloc(sizeof(OQS_SIG)); - if (sig == NULL) { - return NULL; - } - sig->method_name = OQS_SIG_alg_sphincs_shake256_256f_robust; - sig->alg_version = "https://github.com/sphincs/sphincsplus/commit/ed15dd78658f63288c7492c00260d86154b84637"; - - sig->claimed_nist_level = 5; - sig->euf_cma = true; - - sig->length_public_key = OQS_SIG_sphincs_shake256_256f_robust_length_public_key; - sig->length_secret_key = OQS_SIG_sphincs_shake256_256f_robust_length_secret_key; - sig->length_signature = OQS_SIG_sphincs_shake256_256f_robust_length_signature; - - sig->keypair = OQS_SIG_sphincs_shake256_256f_robust_keypair; - sig->sign = OQS_SIG_sphincs_shake256_256f_robust_sign; - sig->verify = OQS_SIG_sphincs_shake256_256f_robust_verify; - - return sig; -} - -extern int PQCLEAN_SPHINCSSHAKE256FROBUST_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); -extern int PQCLEAN_SPHINCSSHAKE256FROBUST_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); -extern int PQCLEAN_SPHINCSSHAKE256FROBUST_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); - -#if defined(OQS_ENABLE_SIG_sphincs_shake256_256f_robust_avx2) -extern int PQCLEAN_SPHINCSSHAKE256FROBUST_AVX2_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); -extern int PQCLEAN_SPHINCSSHAKE256FROBUST_AVX2_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); -extern int PQCLEAN_SPHINCSSHAKE256FROBUST_AVX2_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); -#endif - -#if defined(OQS_ENABLE_SIG_sphincs_shake256_256f_robust_aarch64) -extern int PQCLEAN_SPHINCSSHAKE256FROBUST_AARCH64_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); -extern int PQCLEAN_SPHINCSSHAKE256FROBUST_AARCH64_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); -extern int PQCLEAN_SPHINCSSHAKE256FROBUST_AARCH64_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); -#endif - -OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_256f_robust_keypair(uint8_t *public_key, uint8_t *secret_key) { -#if defined(OQS_ENABLE_SIG_sphincs_shake256_256f_robust_avx2) -#if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) { -#endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256FROBUST_AVX2_crypto_sign_keypair(public_key, secret_key); -#if defined(OQS_DIST_BUILD) - } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256FROBUST_CLEAN_crypto_sign_keypair(public_key, secret_key); - } -#endif /* OQS_DIST_BUILD */ -#elif defined(OQS_ENABLE_SIG_sphincs_shake256_256f_robust_aarch64) -#if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_ARM_SHA3)) { -#endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256FROBUST_AARCH64_crypto_sign_keypair(public_key, secret_key); -#if defined(OQS_DIST_BUILD) - } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256FROBUST_CLEAN_crypto_sign_keypair(public_key, secret_key); - } -#endif /* OQS_DIST_BUILD */ -#else - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256FROBUST_CLEAN_crypto_sign_keypair(public_key, secret_key); -#endif -} - -OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_256f_robust_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, const uint8_t *secret_key) { -#if defined(OQS_ENABLE_SIG_sphincs_shake256_256f_robust_avx2) -#if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) { -#endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256FROBUST_AVX2_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); -#if defined(OQS_DIST_BUILD) - } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256FROBUST_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); - } -#endif /* OQS_DIST_BUILD */ -#elif defined(OQS_ENABLE_SIG_sphincs_shake256_256f_robust_aarch64) -#if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_ARM_SHA3)) { -#endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256FROBUST_AARCH64_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); -#if defined(OQS_DIST_BUILD) - } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256FROBUST_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); - } -#endif /* OQS_DIST_BUILD */ -#else - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256FROBUST_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); -#endif -} - -OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_256f_robust_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key) { -#if defined(OQS_ENABLE_SIG_sphincs_shake256_256f_robust_avx2) -#if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) { -#endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256FROBUST_AVX2_crypto_sign_verify(signature, signature_len, message, message_len, public_key); -#if defined(OQS_DIST_BUILD) - } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256FROBUST_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); - } -#endif /* OQS_DIST_BUILD */ -#elif defined(OQS_ENABLE_SIG_sphincs_shake256_256f_robust_aarch64) -#if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_ARM_SHA3)) { -#endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256FROBUST_AARCH64_crypto_sign_verify(signature, signature_len, message, message_len, public_key); -#if defined(OQS_DIST_BUILD) - } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256FROBUST_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); - } -#endif /* OQS_DIST_BUILD */ -#else - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256FROBUST_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); -#endif -} - -#endif diff --git a/src/sig/sphincs/sig_sphincs_shake256_256s_robust.c b/src/sig/sphincs/sig_sphincs_shake256_256s_robust.c deleted file mode 100644 index aa56dccc26..0000000000 --- a/src/sig/sphincs/sig_sphincs_shake256_256s_robust.c +++ /dev/null @@ -1,126 +0,0 @@ -// SPDX-License-Identifier: MIT - -#include - -#include - -#if defined(OQS_ENABLE_SIG_sphincs_shake256_256s_robust) - -OQS_SIG *OQS_SIG_sphincs_shake256_256s_robust_new(void) { - - OQS_SIG *sig = malloc(sizeof(OQS_SIG)); - if (sig == NULL) { - return NULL; - } - sig->method_name = OQS_SIG_alg_sphincs_shake256_256s_robust; - sig->alg_version = "https://github.com/sphincs/sphincsplus/commit/ed15dd78658f63288c7492c00260d86154b84637"; - - sig->claimed_nist_level = 5; - sig->euf_cma = true; - - sig->length_public_key = OQS_SIG_sphincs_shake256_256s_robust_length_public_key; - sig->length_secret_key = OQS_SIG_sphincs_shake256_256s_robust_length_secret_key; - sig->length_signature = OQS_SIG_sphincs_shake256_256s_robust_length_signature; - - sig->keypair = OQS_SIG_sphincs_shake256_256s_robust_keypair; - sig->sign = OQS_SIG_sphincs_shake256_256s_robust_sign; - sig->verify = OQS_SIG_sphincs_shake256_256s_robust_verify; - - return sig; -} - -extern int PQCLEAN_SPHINCSSHAKE256SROBUST_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); -extern int PQCLEAN_SPHINCSSHAKE256SROBUST_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); -extern int PQCLEAN_SPHINCSSHAKE256SROBUST_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); - -#if defined(OQS_ENABLE_SIG_sphincs_shake256_256s_robust_avx2) -extern int PQCLEAN_SPHINCSSHAKE256SROBUST_AVX2_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); -extern int PQCLEAN_SPHINCSSHAKE256SROBUST_AVX2_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); -extern int PQCLEAN_SPHINCSSHAKE256SROBUST_AVX2_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); -#endif - -#if defined(OQS_ENABLE_SIG_sphincs_shake256_256s_robust_aarch64) -extern int PQCLEAN_SPHINCSSHAKE256SROBUST_AARCH64_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); -extern int PQCLEAN_SPHINCSSHAKE256SROBUST_AARCH64_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); -extern int PQCLEAN_SPHINCSSHAKE256SROBUST_AARCH64_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); -#endif - -OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_256s_robust_keypair(uint8_t *public_key, uint8_t *secret_key) { -#if defined(OQS_ENABLE_SIG_sphincs_shake256_256s_robust_avx2) -#if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) { -#endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256SROBUST_AVX2_crypto_sign_keypair(public_key, secret_key); -#if defined(OQS_DIST_BUILD) - } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256SROBUST_CLEAN_crypto_sign_keypair(public_key, secret_key); - } -#endif /* OQS_DIST_BUILD */ -#elif defined(OQS_ENABLE_SIG_sphincs_shake256_256s_robust_aarch64) -#if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_ARM_SHA3)) { -#endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256SROBUST_AARCH64_crypto_sign_keypair(public_key, secret_key); -#if defined(OQS_DIST_BUILD) - } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256SROBUST_CLEAN_crypto_sign_keypair(public_key, secret_key); - } -#endif /* OQS_DIST_BUILD */ -#else - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256SROBUST_CLEAN_crypto_sign_keypair(public_key, secret_key); -#endif -} - -OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_256s_robust_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, const uint8_t *secret_key) { -#if defined(OQS_ENABLE_SIG_sphincs_shake256_256s_robust_avx2) -#if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) { -#endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256SROBUST_AVX2_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); -#if defined(OQS_DIST_BUILD) - } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256SROBUST_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); - } -#endif /* OQS_DIST_BUILD */ -#elif defined(OQS_ENABLE_SIG_sphincs_shake256_256s_robust_aarch64) -#if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_ARM_SHA3)) { -#endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256SROBUST_AARCH64_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); -#if defined(OQS_DIST_BUILD) - } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256SROBUST_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); - } -#endif /* OQS_DIST_BUILD */ -#else - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256SROBUST_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); -#endif -} - -OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_256s_robust_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key) { -#if defined(OQS_ENABLE_SIG_sphincs_shake256_256s_robust_avx2) -#if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) { -#endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256SROBUST_AVX2_crypto_sign_verify(signature, signature_len, message, message_len, public_key); -#if defined(OQS_DIST_BUILD) - } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256SROBUST_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); - } -#endif /* OQS_DIST_BUILD */ -#elif defined(OQS_ENABLE_SIG_sphincs_shake256_256s_robust_aarch64) -#if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_ARM_SHA3)) { -#endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256SROBUST_AARCH64_crypto_sign_verify(signature, signature_len, message, message_len, public_key); -#if defined(OQS_DIST_BUILD) - } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256SROBUST_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); - } -#endif /* OQS_DIST_BUILD */ -#else - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256SROBUST_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); -#endif -} - -#endif From 07883467ffbc9bb8c93222df52fe162d05efbc1e Mon Sep 17 00:00:00 2001 From: Douglas Stebila Date: Wed, 10 May 2023 09:56:44 -0400 Subject: [PATCH 08/10] Fix SHA2 block sizes in OpenSSL wrapper --- src/common/sha2/sha2_ossl.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/common/sha2/sha2_ossl.c b/src/common/sha2/sha2_ossl.c index c94a07b7f8..097ca28218 100644 --- a/src/common/sha2/sha2_ossl.c +++ b/src/common/sha2/sha2_ossl.c @@ -46,7 +46,7 @@ void OQS_SHA2_sha512(uint8_t *output, const uint8_t *input, size_t inplen) { do_hash(output, input, inplen, md); } -#define SHA2_BLOCK_SIZE 64 +#define SHA256_BLOCK_SIZE 64 void OQS_SHA2_sha256_inc_init(OQS_SHA2_sha256_ctx *state) { EVP_MD_CTX *mdctx; @@ -83,6 +83,8 @@ void OQS_SHA2_sha256_inc_ctx_clone(OQS_SHA2_sha256_ctx *dest, const OQS_SHA2_sha OQS_OPENSSL_GUARD(EVP_MD_CTX_copy_ex((EVP_MD_CTX *) dest->ctx, (EVP_MD_CTX *) src->ctx)); } +#define SHA384_BLOCK_SIZE 128 + void OQS_SHA2_sha384_inc_init(OQS_SHA2_sha384_ctx *state) { EVP_MD_CTX *mdctx; const EVP_MD *md = NULL; @@ -118,6 +120,8 @@ void OQS_SHA2_sha384_inc_ctx_clone(OQS_SHA2_sha384_ctx *dest, const OQS_SHA2_sha OQS_OPENSSL_GUARD(EVP_MD_CTX_copy_ex((EVP_MD_CTX *) dest->ctx, (EVP_MD_CTX *) src->ctx)); } +#define SHA512_BLOCK_SIZE 128 + void OQS_SHA2_sha512_inc_init(OQS_SHA2_sha512_ctx *state) { EVP_MD_CTX *mdctx; const EVP_MD *md = NULL; From 7432007e3f2926899945c76ebdf3b0908dc57988 Mon Sep 17 00:00:00 2001 From: Douglas Stebila Date: Mon, 15 May 2023 11:54:04 -0400 Subject: [PATCH 09/10] Revert "Fix SHA2 block sizes in OpenSSL wrapper" This reverts commit f57ed6db90b4886a95e8cd5a885bc2660bbdf134. --- src/common/sha2/sha2_ossl.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/common/sha2/sha2_ossl.c b/src/common/sha2/sha2_ossl.c index 097ca28218..c94a07b7f8 100644 --- a/src/common/sha2/sha2_ossl.c +++ b/src/common/sha2/sha2_ossl.c @@ -46,7 +46,7 @@ void OQS_SHA2_sha512(uint8_t *output, const uint8_t *input, size_t inplen) { do_hash(output, input, inplen, md); } -#define SHA256_BLOCK_SIZE 64 +#define SHA2_BLOCK_SIZE 64 void OQS_SHA2_sha256_inc_init(OQS_SHA2_sha256_ctx *state) { EVP_MD_CTX *mdctx; @@ -83,8 +83,6 @@ void OQS_SHA2_sha256_inc_ctx_clone(OQS_SHA2_sha256_ctx *dest, const OQS_SHA2_sha OQS_OPENSSL_GUARD(EVP_MD_CTX_copy_ex((EVP_MD_CTX *) dest->ctx, (EVP_MD_CTX *) src->ctx)); } -#define SHA384_BLOCK_SIZE 128 - void OQS_SHA2_sha384_inc_init(OQS_SHA2_sha384_ctx *state) { EVP_MD_CTX *mdctx; const EVP_MD *md = NULL; @@ -120,8 +118,6 @@ void OQS_SHA2_sha384_inc_ctx_clone(OQS_SHA2_sha384_ctx *dest, const OQS_SHA2_sha OQS_OPENSSL_GUARD(EVP_MD_CTX_copy_ex((EVP_MD_CTX *) dest->ctx, (EVP_MD_CTX *) src->ctx)); } -#define SHA512_BLOCK_SIZE 128 - void OQS_SHA2_sha512_inc_init(OQS_SHA2_sha512_ctx *state) { EVP_MD_CTX *mdctx; const EVP_MD *md = NULL; From 1f267d536b0c13ed27be3934a41162093aa8beea Mon Sep 17 00:00:00 2001 From: Michael Baentsch <57787676+baentsch@users.noreply.github.com> Date: Mon, 15 May 2023 18:29:50 +0200 Subject: [PATCH 10/10] Sphincs+ and Crystalsupdate (no AES) (#1460) * AVX2 test * AVX2 test * add patch; correct aarch64; correct documentation * enable Keccak for Sphincs even if OpenSSL shall provide SHA3 * properly handle xkcp enablement if only specific algorithms are selected * correct conditional setting * re-enable XKCP for other platforms * Windows support * alternate pqcrystals-AES removal --- .CMake/alg_support.cmake | 93 +- README.md | 9 +- docs/algorithms/kem/kyber.md | 30 - docs/algorithms/kem/kyber.yml | 108 - docs/algorithms/sig/dilithium.md | 30 - docs/algorithms/sig/dilithium.yml | 105 - docs/algorithms/sig/sphincs.md | 246 +- docs/algorithms/sig/sphincs.yml | 663 +--- docs/cbom.json | 2274 ++----------- .../copy_from_upstream/copy_from_upstream.yml | 30 +- .../patches/pqclean-sphincs.patch | 3000 +++++++++++++++++ scripts/update_docs_from_yaml.py | 4 +- src/common/CMakeLists.txt | 5 +- src/common/pqclean_shims/compat.h | 15 +- src/common/pqclean_shims/fips202x4.h | 24 +- src/kem/kem.c | 39 - src/kem/kem.h | 8 +- src/kem/kyber/CMakeLists.txt | 54 - src/kem/kyber/kem_kyber.h | 33 - src/oqsconfig.h.cmake | 18 - src/sig/dilithium/CMakeLists.txt | 54 - src/sig/dilithium/sig_dilithium.h | 33 - src/sig/sig.c | 39 - src/sig/sig.h | 8 +- src/sig/sphincs/CMakeLists.txt | 60 +- .../fips202x4.c | 210 -- .../fips202x4.h | 28 - .../fips202x4.c | 210 -- .../fips202x4.h | 28 - .../fips202x4.c | 210 -- .../fips202x4.h | 28 - .../fips202x4.c | 210 -- .../fips202x4.h | 28 - .../fips202x4.c | 210 -- .../fips202x4.h | 28 - .../fips202x4.c | 210 -- .../fips202x4.h | 28 - .../sig_sphincs_shake256_128f_simple.c | 36 - .../sig_sphincs_shake256_128s_simple.c | 36 - .../sig_sphincs_shake256_192f_simple.c | 36 - .../sig_sphincs_shake256_192s_simple.c | 36 - .../sig_sphincs_shake256_256f_simple.c | 36 - .../sig_sphincs_shake256_256s_simple.c | 36 - tests/kat_sig.c | 30 - 44 files changed, 3402 insertions(+), 5254 deletions(-) create mode 100644 scripts/copy_from_upstream/patches/pqclean-sphincs.patch delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/fips202x4.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/fips202x4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/fips202x4.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/fips202x4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/fips202x4.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/fips202x4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/fips202x4.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/fips202x4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/fips202x4.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/fips202x4.h delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/fips202x4.c delete mode 100644 src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/fips202x4.h diff --git a/.CMake/alg_support.cmake b/.CMake/alg_support.cmake index 9a57cedf50..1cccdacff9 100644 --- a/.CMake/alg_support.cmake +++ b/.CMake/alg_support.cmake @@ -17,7 +17,7 @@ function(filter_algs alglist) # Case 1, family name foreach (_alg ${ARGV0}) string(TOUPPER ${_alg} upalg) - if("OQS_ENABLE_${upalg}i" MATCHES "^${_var}") + if("OQS_ENABLE_${upalg}" MATCHES "^${_var}") set(${_var} ON PARENT_SCOPE) endif() endforeach() @@ -249,27 +249,6 @@ endif() endif() endif() -cmake_dependent_option(OQS_ENABLE_KEM_kyber_512_90s "" ON "OQS_ENABLE_KEM_KYBER" OFF) -if(CMAKE_SYSTEM_NAME MATCHES "Linux|Darwin") -if(OQS_DIST_X86_64_BUILD OR (OQS_USE_AES_INSTRUCTIONS AND OQS_USE_AVX2_INSTRUCTIONS AND OQS_USE_BMI2_INSTRUCTIONS AND OQS_USE_POPCNT_INSTRUCTIONS)) - cmake_dependent_option(OQS_ENABLE_KEM_kyber_512_90s_avx2 "" ON "OQS_ENABLE_KEM_kyber_512_90s" OFF) -endif() -endif() - -cmake_dependent_option(OQS_ENABLE_KEM_kyber_768_90s "" ON "OQS_ENABLE_KEM_KYBER" OFF) -if(CMAKE_SYSTEM_NAME MATCHES "Linux|Darwin") -if(OQS_DIST_X86_64_BUILD OR (OQS_USE_AES_INSTRUCTIONS AND OQS_USE_AVX2_INSTRUCTIONS AND OQS_USE_BMI2_INSTRUCTIONS AND OQS_USE_POPCNT_INSTRUCTIONS)) - cmake_dependent_option(OQS_ENABLE_KEM_kyber_768_90s_avx2 "" ON "OQS_ENABLE_KEM_kyber_768_90s" OFF) -endif() -endif() - -cmake_dependent_option(OQS_ENABLE_KEM_kyber_1024_90s "" ON "OQS_ENABLE_KEM_KYBER" OFF) -if(CMAKE_SYSTEM_NAME MATCHES "Linux|Darwin") -if(OQS_DIST_X86_64_BUILD OR (OQS_USE_AES_INSTRUCTIONS AND OQS_USE_AVX2_INSTRUCTIONS AND OQS_USE_BMI2_INSTRUCTIONS AND OQS_USE_POPCNT_INSTRUCTIONS)) - cmake_dependent_option(OQS_ENABLE_KEM_kyber_1024_90s_avx2 "" ON "OQS_ENABLE_KEM_kyber_1024_90s" OFF) -endif() -endif() - option(OQS_ENABLE_SIG_DILITHIUM "Enable dilithium algorithm family" ON) cmake_dependent_option(OQS_ENABLE_SIG_dilithium_2 "" ON "OQS_ENABLE_SIG_DILITHIUM" OFF) @@ -311,27 +290,6 @@ if(OQS_DIST_ARM64_V8_BUILD OR (OQS_USE_ARM_NEON_INSTRUCTIONS AND OQS_USE_ARM_NEO endif() endif() -cmake_dependent_option(OQS_ENABLE_SIG_dilithium_2_aes "" ON "OQS_ENABLE_SIG_DILITHIUM" OFF) -if(CMAKE_SYSTEM_NAME MATCHES "Darwin|Linux") -if(OQS_DIST_X86_64_BUILD OR (OQS_USE_AVX2_INSTRUCTIONS AND OQS_USE_AES_INSTRUCTIONS AND OQS_USE_POPCNT_INSTRUCTIONS)) - cmake_dependent_option(OQS_ENABLE_SIG_dilithium_2_aes_avx2 "" ON "OQS_ENABLE_SIG_dilithium_2_aes" OFF) -endif() -endif() - -cmake_dependent_option(OQS_ENABLE_SIG_dilithium_3_aes "" ON "OQS_ENABLE_SIG_DILITHIUM" OFF) -if(CMAKE_SYSTEM_NAME MATCHES "Darwin|Linux") -if(OQS_DIST_X86_64_BUILD OR (OQS_USE_AVX2_INSTRUCTIONS AND OQS_USE_AES_INSTRUCTIONS AND OQS_USE_POPCNT_INSTRUCTIONS)) - cmake_dependent_option(OQS_ENABLE_SIG_dilithium_3_aes_avx2 "" ON "OQS_ENABLE_SIG_dilithium_3_aes" OFF) -endif() -endif() - -cmake_dependent_option(OQS_ENABLE_SIG_dilithium_5_aes "" ON "OQS_ENABLE_SIG_DILITHIUM" OFF) -if(CMAKE_SYSTEM_NAME MATCHES "Darwin|Linux") -if(OQS_DIST_X86_64_BUILD OR (OQS_USE_AVX2_INSTRUCTIONS AND OQS_USE_AES_INSTRUCTIONS AND OQS_USE_POPCNT_INSTRUCTIONS)) - cmake_dependent_option(OQS_ENABLE_SIG_dilithium_5_aes_avx2 "" ON "OQS_ENABLE_SIG_dilithium_5_aes" OFF) -endif() -endif() - option(OQS_ENABLE_SIG_FALCON "Enable falcon algorithm family" ON) cmake_dependent_option(OQS_ENABLE_SIG_falcon_512 "" ON "OQS_ENABLE_SIG_FALCON" OFF) @@ -381,67 +339,31 @@ if(OQS_DIST_X86_64_BUILD OR (OQS_USE_AVX2_INSTRUCTIONS)) cmake_dependent_option(OQS_ENABLE_SIG_sphincs_shake256_128f_simple_avx2 "" ON "OQS_ENABLE_SIG_sphincs_shake256_128f_simple" OFF) endif() -if(CMAKE_SYSTEM_NAME MATCHES "Linux|Darwin") -if(OQS_DIST_ARM64_V8_BUILD OR (OQS_USE_ARM_NEON_INSTRUCTIONS AND OQS_USE_ARM_SHA3_INSTRUCTIONS)) - cmake_dependent_option(OQS_ENABLE_SIG_sphincs_shake256_128f_simple_aarch64 "" ON "OQS_ENABLE_SIG_sphincs_shake256_128f_simple" OFF) -endif() -endif() - cmake_dependent_option(OQS_ENABLE_SIG_sphincs_shake256_128s_simple "" ON "OQS_ENABLE_SIG_SPHINCS" OFF) if(OQS_DIST_X86_64_BUILD OR (OQS_USE_AVX2_INSTRUCTIONS)) cmake_dependent_option(OQS_ENABLE_SIG_sphincs_shake256_128s_simple_avx2 "" ON "OQS_ENABLE_SIG_sphincs_shake256_128s_simple" OFF) endif() -if(CMAKE_SYSTEM_NAME MATCHES "Linux|Darwin") -if(OQS_DIST_ARM64_V8_BUILD OR (OQS_USE_ARM_NEON_INSTRUCTIONS AND OQS_USE_ARM_SHA3_INSTRUCTIONS)) - cmake_dependent_option(OQS_ENABLE_SIG_sphincs_shake256_128s_simple_aarch64 "" ON "OQS_ENABLE_SIG_sphincs_shake256_128s_simple" OFF) -endif() -endif() - cmake_dependent_option(OQS_ENABLE_SIG_sphincs_shake256_192f_simple "" ON "OQS_ENABLE_SIG_SPHINCS" OFF) if(OQS_DIST_X86_64_BUILD OR (OQS_USE_AVX2_INSTRUCTIONS)) cmake_dependent_option(OQS_ENABLE_SIG_sphincs_shake256_192f_simple_avx2 "" ON "OQS_ENABLE_SIG_sphincs_shake256_192f_simple" OFF) endif() -if(CMAKE_SYSTEM_NAME MATCHES "Linux|Darwin") -if(OQS_DIST_ARM64_V8_BUILD OR (OQS_USE_ARM_NEON_INSTRUCTIONS AND OQS_USE_ARM_SHA3_INSTRUCTIONS)) - cmake_dependent_option(OQS_ENABLE_SIG_sphincs_shake256_192f_simple_aarch64 "" ON "OQS_ENABLE_SIG_sphincs_shake256_192f_simple" OFF) -endif() -endif() - cmake_dependent_option(OQS_ENABLE_SIG_sphincs_shake256_192s_simple "" ON "OQS_ENABLE_SIG_SPHINCS" OFF) if(OQS_DIST_X86_64_BUILD OR (OQS_USE_AVX2_INSTRUCTIONS)) cmake_dependent_option(OQS_ENABLE_SIG_sphincs_shake256_192s_simple_avx2 "" ON "OQS_ENABLE_SIG_sphincs_shake256_192s_simple" OFF) endif() -if(CMAKE_SYSTEM_NAME MATCHES "Linux|Darwin") -if(OQS_DIST_ARM64_V8_BUILD OR (OQS_USE_ARM_NEON_INSTRUCTIONS AND OQS_USE_ARM_SHA3_INSTRUCTIONS)) - cmake_dependent_option(OQS_ENABLE_SIG_sphincs_shake256_192s_simple_aarch64 "" ON "OQS_ENABLE_SIG_sphincs_shake256_192s_simple" OFF) -endif() -endif() - cmake_dependent_option(OQS_ENABLE_SIG_sphincs_shake256_256f_simple "" ON "OQS_ENABLE_SIG_SPHINCS" OFF) if(OQS_DIST_X86_64_BUILD OR (OQS_USE_AVX2_INSTRUCTIONS)) cmake_dependent_option(OQS_ENABLE_SIG_sphincs_shake256_256f_simple_avx2 "" ON "OQS_ENABLE_SIG_sphincs_shake256_256f_simple" OFF) endif() -if(CMAKE_SYSTEM_NAME MATCHES "Linux|Darwin") -if(OQS_DIST_ARM64_V8_BUILD OR (OQS_USE_ARM_NEON_INSTRUCTIONS AND OQS_USE_ARM_SHA3_INSTRUCTIONS)) - cmake_dependent_option(OQS_ENABLE_SIG_sphincs_shake256_256f_simple_aarch64 "" ON "OQS_ENABLE_SIG_sphincs_shake256_256f_simple" OFF) -endif() -endif() - cmake_dependent_option(OQS_ENABLE_SIG_sphincs_shake256_256s_simple "" ON "OQS_ENABLE_SIG_SPHINCS" OFF) if(OQS_DIST_X86_64_BUILD OR (OQS_USE_AVX2_INSTRUCTIONS)) cmake_dependent_option(OQS_ENABLE_SIG_sphincs_shake256_256s_simple_avx2 "" ON "OQS_ENABLE_SIG_sphincs_shake256_256s_simple" OFF) endif() -if(CMAKE_SYSTEM_NAME MATCHES "Linux|Darwin") -if(OQS_DIST_ARM64_V8_BUILD OR (OQS_USE_ARM_NEON_INSTRUCTIONS AND OQS_USE_ARM_SHA3_INSTRUCTIONS)) - cmake_dependent_option(OQS_ENABLE_SIG_sphincs_shake256_256s_simple_aarch64 "" ON "OQS_ENABLE_SIG_sphincs_shake256_256s_simple" OFF) -endif() -endif() - ##### OQS_COPY_FROM_UPSTREAM_FRAGMENT_ADD_ENABLE_BY_ALG_END if((OQS_MINIMAL_BUILD STREQUAL "ON")) @@ -462,4 +384,17 @@ else() message(STATUS "Alg enablement unchanged") endif() +# Set XKCP (Keccak) required for Sphincs AVX2 code even if OpenSSL3 SHA3 is used: +if (${OQS_ENABLE_SIG_SPHINCS} OR NOT ${OQS_USE_SHA3_OPENSSL}) + set(OQS_ENABLE_SHA3_xkcp_low ON) +else() + set(OQS_ENABLE_SHA3_xkcp_low OFF) +endif() +if(CMAKE_SYSTEM_NAME MATCHES "Linux|Darwin") + if(OQS_DIST_X86_64_BUILD OR OQS_USE_AVX2_INSTRUCTIONS) + set(OQS_ENABLE_SHA3_xkcp_low_avx2 ON) + else() + set(OQS_ENABLE_SHA3_xkcp_low_avx2 OFF) + endif() +endif() diff --git a/README.md b/README.md index ac255df51c..3ce0730c9f 100644 --- a/README.md +++ b/README.md @@ -45,18 +45,17 @@ The list below indicates all algorithms supported by liboqs, but not all those a - **Classic McEliece**: Classic-McEliece-348864†, Classic-McEliece-348864f†, Classic-McEliece-460896†, Classic-McEliece-460896f†, Classic-McEliece-6688128†, Classic-McEliece-6688128f†, Classic-McEliece-6960119†, Classic-McEliece-6960119f†, Classic-McEliece-8192128†, Classic-McEliece-8192128f† - **FrodoKEM**: FrodoKEM-640-AES, FrodoKEM-640-SHAKE, FrodoKEM-976-AES, FrodoKEM-976-SHAKE, FrodoKEM-1344-AES, FrodoKEM-1344-SHAKE - **HQC**: HQC-128, HQC-192, HQC-256† -- **Kyber**: Kyber512, Kyber512-90s, Kyber768, Kyber768-90s, Kyber1024, Kyber1024-90s +- **Kyber**: Kyber512, Kyber768, Kyber1024 - **NTRU-Prime**: sntrup761 #### Signature schemes -- **CRYSTALS-Dilithium**: Dilithium2, Dilithium3, Dilithium5, Dilithium2-AES, Dilithium3-AES, Dilithium5-AES +- **CRYSTALS-Dilithium**: Dilithium2, Dilithium3, Dilithium5 - **Falcon**: Falcon-512, Falcon-1024 -- **SPHINCS+-Haraka**: SPHINCS+-Haraka-128f-robust, SPHINCS+-Haraka-128f-simple, SPHINCS+-Haraka-128s-robust, SPHINCS+-Haraka-128s-simple, SPHINCS+-Haraka-192f-robust, SPHINCS+-Haraka-192f-simple, SPHINCS+-Haraka-192s-robust, SPHINCS+-Haraka-192s-simple, SPHINCS+-Haraka-256f-robust, SPHINCS+-Haraka-256f-simple, SPHINCS+-Haraka-256s-robust, SPHINCS+-Haraka-256s-simple -- **SPHINCS+-SHA256**: SPHINCS+-SHA256-128f-robust, SPHINCS+-SHA256-128f-simple, SPHINCS+-SHA256-128s-robust, SPHINCS+-SHA256-128s-simple, SPHINCS+-SHA256-192f-robust, SPHINCS+-SHA256-192f-simple, SPHINCS+-SHA256-192s-robust, SPHINCS+-SHA256-192s-simple, SPHINCS+-SHA256-256f-robust, SPHINCS+-SHA256-256f-simple, SPHINCS+-SHA256-256s-robust, SPHINCS+-SHA256-256s-simple -- **SPHINCS+-SHAKE256**: SPHINCS+-SHAKE256-128f-robust, SPHINCS+-SHAKE256-128f-simple, SPHINCS+-SHAKE256-128s-robust, SPHINCS+-SHAKE256-128s-simple, SPHINCS+-SHAKE256-192f-robust, SPHINCS+-SHAKE256-192f-simple, SPHINCS+-SHAKE256-192s-robust, SPHINCS+-SHAKE256-192s-simple, SPHINCS+-SHAKE256-256f-robust, SPHINCS+-SHAKE256-256f-simple, SPHINCS+-SHAKE256-256s-robust, SPHINCS+-SHAKE256-256s-simple +- **SPHINCS+-SHA256**: SPHINCS+-SHA256-128f-simple, SPHINCS+-SHA256-128s-simple, SPHINCS+-SHA256-192f-simple, SPHINCS+-SHA256-192s-simple, SPHINCS+-SHA256-256f-simple, SPHINCS+-SHA256-256s-simple +- **SPHINCS+-SHAKE256**: SPHINCS+-SHAKE256-128f-simple, SPHINCS+-SHAKE256-128s-simple, SPHINCS+-SHAKE256-192f-simple, SPHINCS+-SHAKE256-192s-simple, SPHINCS+-SHAKE256-256f-simple, SPHINCS+-SHAKE256-256s-simple Note that for algorithms marked with a dagger (†), liboqs contains at least one implementation that uses a large amount of stack space; this may cause failures when run in threads or in constrained environments. For more information, consult the algorithm information sheets in the [docs/algorithms](https://github.com/open-quantum-safe/liboqs/tree/main/docs/algorithms) folder. diff --git a/docs/algorithms/kem/kyber.md b/docs/algorithms/kem/kyber.md index 6266d7a10c..4fb1f06aa0 100644 --- a/docs/algorithms/kem/kyber.md +++ b/docs/algorithms/kem/kyber.md @@ -20,11 +20,8 @@ | Parameter set | Security model | Claimed NIST Level | Public key size (bytes) | Secret key size (bytes) | Ciphertext size (bytes) | Shared secret size (bytes) | |:---------------:|:-----------------|---------------------:|--------------------------:|--------------------------:|--------------------------:|-----------------------------:| | Kyber512 | IND-CCA2 | 1 | 800 | 1632 | 768 | 32 | -| Kyber512-90s | IND-CCA2 | 1 | 800 | 1632 | 768 | 32 | | Kyber768 | IND-CCA2 | 3 | 1184 | 2400 | 1088 | 32 | -| Kyber768-90s | IND-CCA2 | 3 | 1184 | 2400 | 1088 | 32 | | Kyber1024 | IND-CCA2 | 5 | 1568 | 3168 | 1568 | 32 | -| Kyber1024-90s | IND-CCA2 | 5 | 1568 | 3168 | 1568 | 32 | ## Kyber512 implementation characteristics @@ -38,15 +35,6 @@ Are implementations chosen based on runtime CPU feature detection? **Yes**. ‡For an explanation of what this denotes, consult the [Explanation of Terms](#explanation-of-terms) section at the end of this file. -## Kyber512-90s implementation characteristics - -| Implementation source | Identifier in upstream | Supported architecture(s) | Supported operating system(s) | CPU extension(s) used | No branching-on-secrets claimed? | No branching-on-secrets checked by valgrind? | Large stack usage? | -|:---------------------------------:|:-------------------------|:----------------------------|:--------------------------------|:--------------------------------|:-----------------------------------|:-----------------------------------------------|:---------------------| -| [Primary Source](#primary-source) | ref | All | All | None | True | True | False | -| [Primary Source](#primary-source) | avx2 | x86\_64 | Linux,Darwin | AES,AVX2,BMI2,POPCNT,SSE2,SSSE3 | True | True | False | - -Are implementations chosen based on runtime CPU feature detection? **Yes**. - ## Kyber768 implementation characteristics | Implementation source | Identifier in upstream | Supported architecture(s) | Supported operating system(s) | CPU extension(s) used | No branching-on-secrets claimed? | No branching-on-secrets checked by valgrind? | Large stack usage? | @@ -57,15 +45,6 @@ Are implementations chosen based on runtime CPU feature detection? **Yes**. Are implementations chosen based on runtime CPU feature detection? **Yes**. -## Kyber768-90s implementation characteristics - -| Implementation source | Identifier in upstream | Supported architecture(s) | Supported operating system(s) | CPU extension(s) used | No branching-on-secrets claimed? | No branching-on-secrets checked by valgrind? | Large stack usage? | -|:---------------------------------:|:-------------------------|:----------------------------|:--------------------------------|:--------------------------------|:-----------------------------------|:-----------------------------------------------|:---------------------| -| [Primary Source](#primary-source) | ref | All | All | None | True | True | False | -| [Primary Source](#primary-source) | avx2 | x86\_64 | Linux,Darwin | AES,AVX2,BMI2,POPCNT,SSE2,SSSE3 | True | True | False | - -Are implementations chosen based on runtime CPU feature detection? **Yes**. - ## Kyber1024 implementation characteristics | Implementation source | Identifier in upstream | Supported architecture(s) | Supported operating system(s) | CPU extension(s) used | No branching-on-secrets claimed? | No branching-on-secrets checked by valgrind? | Large stack usage? | @@ -76,15 +55,6 @@ Are implementations chosen based on runtime CPU feature detection? **Yes**. Are implementations chosen based on runtime CPU feature detection? **Yes**. -## Kyber1024-90s implementation characteristics - -| Implementation source | Identifier in upstream | Supported architecture(s) | Supported operating system(s) | CPU extension(s) used | No branching-on-secrets claimed? | No branching-on-secrets checked by valgrind? | Large stack usage? | -|:---------------------------------:|:-------------------------|:----------------------------|:--------------------------------|:--------------------------------|:-----------------------------------|:-----------------------------------------------|:---------------------| -| [Primary Source](#primary-source) | ref | All | All | None | True | True | False | -| [Primary Source](#primary-source) | avx2 | x86\_64 | Linux,Darwin | AES,AVX2,BMI2,POPCNT,SSE2,SSSE3 | True | True | False | - -Are implementations chosen based on runtime CPU feature detection? **Yes**. - ## Explanation of Terms - **Large Stack Usage**: Implementations identified as having such may cause failures when running in threads or in constrained environments. \ No newline at end of file diff --git a/docs/algorithms/kem/kyber.yml b/docs/algorithms/kem/kyber.yml index a76ebcf9df..fda1a7b656 100644 --- a/docs/algorithms/kem/kyber.yml +++ b/docs/algorithms/kem/kyber.yml @@ -71,42 +71,6 @@ parameter-sets: no-secret-dependent-branching-claimed: true no-secret-dependent-branching-checked-by-valgrind: false large-stack-usage: false -- name: Kyber512-90s - claimed-nist-level: 1 - claimed-security: IND-CCA2 - length-public-key: 800 - length-ciphertext: 768 - length-secret-key: 1632 - length-shared-secret: 32 - implementations-switch-on-runtime-cpu-features: true - implementations: - - upstream: primary-upstream - upstream-id: ref - supported-platforms: all - common-crypto: - - AES: liboqs - no-secret-dependent-branching-claimed: true - no-secret-dependent-branching-checked-by-valgrind: true - large-stack-usage: false - - upstream: primary-upstream - upstream-id: avx2 - supported-platforms: - - architecture: x86_64 - operating_systems: - - Linux - - Darwin - required_flags: - - aes - - avx2 - - bmi2 - - popcnt - - sse2 - - ssse3 - common-crypto: - - AES: liboqs - no-secret-dependent-branching-claimed: true - no-secret-dependent-branching-checked-by-valgrind: true - large-stack-usage: false - name: Kyber768 claimed-nist-level: 3 claimed-security: IND-CCA2 @@ -152,42 +116,6 @@ parameter-sets: no-secret-dependent-branching-claimed: true no-secret-dependent-branching-checked-by-valgrind: false large-stack-usage: false -- name: Kyber768-90s - claimed-nist-level: 3 - claimed-security: IND-CCA2 - length-public-key: 1184 - length-ciphertext: 1088 - length-secret-key: 2400 - length-shared-secret: 32 - implementations-switch-on-runtime-cpu-features: true - implementations: - - upstream: primary-upstream - upstream-id: ref - supported-platforms: all - common-crypto: - - AES: liboqs - no-secret-dependent-branching-claimed: true - no-secret-dependent-branching-checked-by-valgrind: true - large-stack-usage: false - - upstream: primary-upstream - upstream-id: avx2 - supported-platforms: - - architecture: x86_64 - operating_systems: - - Linux - - Darwin - required_flags: - - aes - - avx2 - - bmi2 - - popcnt - - sse2 - - ssse3 - common-crypto: - - AES: liboqs - no-secret-dependent-branching-claimed: true - no-secret-dependent-branching-checked-by-valgrind: true - large-stack-usage: false - name: Kyber1024 claimed-nist-level: 5 claimed-security: IND-CCA2 @@ -233,39 +161,3 @@ parameter-sets: no-secret-dependent-branching-claimed: true no-secret-dependent-branching-checked-by-valgrind: false large-stack-usage: false -- name: Kyber1024-90s - claimed-nist-level: 5 - claimed-security: IND-CCA2 - length-public-key: 1568 - length-ciphertext: 1568 - length-secret-key: 3168 - length-shared-secret: 32 - implementations-switch-on-runtime-cpu-features: true - implementations: - - upstream: primary-upstream - upstream-id: ref - supported-platforms: all - common-crypto: - - AES: liboqs - no-secret-dependent-branching-claimed: true - no-secret-dependent-branching-checked-by-valgrind: true - large-stack-usage: false - - upstream: primary-upstream - upstream-id: avx2 - supported-platforms: - - architecture: x86_64 - operating_systems: - - Linux - - Darwin - required_flags: - - aes - - avx2 - - bmi2 - - popcnt - - sse2 - - ssse3 - common-crypto: - - AES: liboqs - no-secret-dependent-branching-claimed: true - no-secret-dependent-branching-checked-by-valgrind: true - large-stack-usage: false diff --git a/docs/algorithms/sig/dilithium.md b/docs/algorithms/sig/dilithium.md index ebbedc4f01..9ff92394e9 100644 --- a/docs/algorithms/sig/dilithium.md +++ b/docs/algorithms/sig/dilithium.md @@ -22,9 +22,6 @@ | Dilithium2 | EUF-CMA | 2 | 1312 | 2528 | 2420 | | Dilithium3 | EUF-CMA | 3 | 1952 | 4000 | 3293 | | Dilithium5 | EUF-CMA | 5 | 2592 | 4864 | 4595 | -| Dilithium2-AES | EUF-CMA | 2 | 1312 | 2528 | 2420 | -| Dilithium3-AES | EUF-CMA | 3 | 1952 | 4000 | 3293 | -| Dilithium5-AES | EUF-CMA | 5 | 2592 | 4864 | 4595 | ## Dilithium2 implementation characteristics @@ -58,33 +55,6 @@ Are implementations chosen based on runtime CPU feature detection? **Yes**. Are implementations chosen based on runtime CPU feature detection? **Yes**. -## Dilithium2-AES implementation characteristics - -| Implementation source | Identifier in upstream | Supported architecture(s) | Supported operating system(s) | CPU extension(s) used | No branching-on-secrets claimed? | No branching-on-secrets checked by valgrind? | Large stack usage? | -|:---------------------------------:|:-------------------------|:----------------------------|:--------------------------------|:---------------------------|:-----------------------------------|:-----------------------------------------------|:---------------------| -| [Primary Source](#primary-source) | ref | All | All | None | True | True | False | -| [Primary Source](#primary-source) | avx2 | x86\_64 | Darwin,Linux | AES,AVX2,POPCNT,SSE2,SSSE3 | True | True | False | - -Are implementations chosen based on runtime CPU feature detection? **Yes**. - -## Dilithium3-AES implementation characteristics - -| Implementation source | Identifier in upstream | Supported architecture(s) | Supported operating system(s) | CPU extension(s) used | No branching-on-secrets claimed? | No branching-on-secrets checked by valgrind? | Large stack usage? | -|:---------------------------------:|:-------------------------|:----------------------------|:--------------------------------|:---------------------------|:-----------------------------------|:-----------------------------------------------|:---------------------| -| [Primary Source](#primary-source) | ref | All | All | None | True | True | False | -| [Primary Source](#primary-source) | avx2 | x86\_64 | Darwin,Linux | AES,AVX2,POPCNT,SSE2,SSSE3 | True | True | False | - -Are implementations chosen based on runtime CPU feature detection? **Yes**. - -## Dilithium5-AES implementation characteristics - -| Implementation source | Identifier in upstream | Supported architecture(s) | Supported operating system(s) | CPU extension(s) used | No branching-on-secrets claimed? | No branching-on-secrets checked by valgrind? | Large stack usage? | -|:---------------------------------:|:-------------------------|:----------------------------|:--------------------------------|:---------------------------|:-----------------------------------|:-----------------------------------------------|:---------------------| -| [Primary Source](#primary-source) | ref | All | All | None | True | True | False | -| [Primary Source](#primary-source) | avx2 | x86\_64 | Darwin,Linux | AES,AVX2,POPCNT,SSE2,SSSE3 | True | True | False | - -Are implementations chosen based on runtime CPU feature detection? **Yes**. - ## Explanation of Terms - **Large Stack Usage**: Implementations identified as having such may cause failures when running in threads or in constrained environments. \ No newline at end of file diff --git a/docs/algorithms/sig/dilithium.yml b/docs/algorithms/sig/dilithium.yml index f16e2e3c41..4bc71007d1 100644 --- a/docs/algorithms/sig/dilithium.yml +++ b/docs/algorithms/sig/dilithium.yml @@ -156,108 +156,3 @@ parameter-sets: no-secret-dependent-branching-claimed: true no-secret-dependent-branching-checked-by-valgrind: false large-stack-usage: false -- name: Dilithium2-AES - oqs_alg: OQS_SIG_alg_dilithium_2_aes - claimed-security: EUF-CMA - claimed-nist-level: 2 - length-public-key: 1312 - length-secret-key: 2528 - length-signature: 2420 - implementations-switch-on-runtime-cpu-features: true - implementations: - - upstream: primary-upstream - upstream-id: ref - supported-platforms: all - common-crypto: - - AES: liboqs - no-secret-dependent-branching-claimed: true - no-secret-dependent-branching-checked-by-valgrind: true - large-stack-usage: false - - upstream: primary-upstream - upstream-id: avx2 - supported-platforms: - - architecture: x86_64 - operating_systems: - - Darwin - - Linux - required_flags: - - aes - - avx2 - - popcnt - - sse2 - - ssse3 - common-crypto: - - AES: liboqs - no-secret-dependent-branching-claimed: true - no-secret-dependent-branching-checked-by-valgrind: true - large-stack-usage: false -- name: Dilithium3-AES - oqs_alg: OQS_SIG_alg_dilithium_3_aes - claimed-security: EUF-CMA - claimed-nist-level: 3 - length-public-key: 1952 - length-secret-key: 4000 - length-signature: 3293 - implementations-switch-on-runtime-cpu-features: true - implementations: - - upstream: primary-upstream - upstream-id: ref - supported-platforms: all - common-crypto: - - AES: liboqs - no-secret-dependent-branching-claimed: true - no-secret-dependent-branching-checked-by-valgrind: true - large-stack-usage: false - - upstream: primary-upstream - upstream-id: avx2 - supported-platforms: - - architecture: x86_64 - operating_systems: - - Darwin - - Linux - required_flags: - - aes - - avx2 - - popcnt - - sse2 - - ssse3 - common-crypto: - - AES: liboqs - no-secret-dependent-branching-claimed: true - no-secret-dependent-branching-checked-by-valgrind: true - large-stack-usage: false -- name: Dilithium5-AES - oqs_alg: OQS_SIG_alg_dilithium_5_aes - claimed-security: EUF-CMA - claimed-nist-level: 5 - length-public-key: 2592 - length-secret-key: 4864 - length-signature: 4595 - implementations-switch-on-runtime-cpu-features: true - implementations: - - upstream: primary-upstream - upstream-id: ref - supported-platforms: all - common-crypto: - - AES: liboqs - no-secret-dependent-branching-claimed: true - no-secret-dependent-branching-checked-by-valgrind: true - large-stack-usage: false - - upstream: primary-upstream - upstream-id: avx2 - supported-platforms: - - architecture: x86_64 - operating_systems: - - Darwin - - Linux - required_flags: - - aes - - avx2 - - popcnt - - sse2 - - ssse3 - common-crypto: - - AES: liboqs - no-secret-dependent-branching-claimed: true - no-secret-dependent-branching-checked-by-valgrind: true - large-stack-usage: false diff --git a/docs/algorithms/sig/sphincs.md b/docs/algorithms/sig/sphincs.md index 5b89a70575..14b316816b 100644 --- a/docs/algorithms/sig/sphincs.md +++ b/docs/algorithms/sig/sphincs.md @@ -7,7 +7,7 @@ - **Authors' website**: https://sphincs.org/ - **Specification version**: NIST Round 3 submission. - **Primary Source**: - - **Source**: https://github.com/PQClean/PQClean/commit/c1b19a865de329e87e9b3e9152362fcb709da8ab + - **Source**: https://github.com/PQClean/PQClean/commit/c1b19a865de329e87e9b3e9152362fcb709da8ab with copy_from_upstream patches - **Implementation license (SPDX-Identifier)**: CC0-1.0 @@ -19,180 +19,30 @@ | Parameter set | Security model | Claimed NIST Level | Public key size (bytes) | Secret key size (bytes) | Signature size (bytes) | |:-----------------------------:|:-----------------|---------------------:|--------------------------:|--------------------------:|-------------------------:| -| SPHINCS+-Haraka-128f-robust | EUF-CMA | 1 | 32 | 64 | 17088 | -| SPHINCS+-Haraka-128f-simple | EUF-CMA | 1 | 32 | 64 | 17088 | -| SPHINCS+-Haraka-128s-robust | EUF-CMA | 1 | 32 | 64 | 7856 | -| SPHINCS+-Haraka-128s-simple | EUF-CMA | 1 | 32 | 64 | 7856 | -| SPHINCS+-Haraka-192f-robust | EUF-CMA | 2 | 48 | 96 | 35664 | -| SPHINCS+-Haraka-192f-simple | EUF-CMA | 2 | 48 | 96 | 35664 | -| SPHINCS+-Haraka-192s-robust | EUF-CMA | 2 | 48 | 96 | 16224 | -| SPHINCS+-Haraka-192s-simple | EUF-CMA | 2 | 48 | 96 | 16224 | -| SPHINCS+-Haraka-256f-robust | EUF-CMA | 2 | 64 | 128 | 49856 | -| SPHINCS+-Haraka-256f-simple | EUF-CMA | 2 | 64 | 128 | 49856 | -| SPHINCS+-Haraka-256s-robust | EUF-CMA | 2 | 64 | 128 | 29792 | -| SPHINCS+-Haraka-256s-simple | EUF-CMA | 2 | 64 | 128 | 29792 | -| SPHINCS+-SHA256-128f-robust | EUF-CMA | 1 | 32 | 64 | 17088 | | SPHINCS+-SHA256-128f-simple | EUF-CMA | 1 | 32 | 64 | 17088 | -| SPHINCS+-SHA256-128s-robust | EUF-CMA | 1 | 32 | 64 | 7856 | | SPHINCS+-SHA256-128s-simple | EUF-CMA | 1 | 32 | 64 | 7856 | -| SPHINCS+-SHA256-192f-robust | EUF-CMA | 3 | 48 | 96 | 35664 | | SPHINCS+-SHA256-192f-simple | EUF-CMA | 3 | 48 | 96 | 35664 | -| SPHINCS+-SHA256-192s-robust | EUF-CMA | 3 | 48 | 96 | 16224 | | SPHINCS+-SHA256-192s-simple | EUF-CMA | 3 | 48 | 96 | 16224 | -| SPHINCS+-SHA256-256f-robust | EUF-CMA | 5 | 64 | 128 | 49856 | | SPHINCS+-SHA256-256f-simple | EUF-CMA | 5 | 64 | 128 | 49856 | -| SPHINCS+-SHA256-256s-robust | EUF-CMA | 5 | 64 | 128 | 29792 | | SPHINCS+-SHA256-256s-simple | EUF-CMA | 5 | 64 | 128 | 29792 | -| SPHINCS+-SHAKE256-128f-robust | EUF-CMA | 1 | 32 | 64 | 17088 | | SPHINCS+-SHAKE256-128f-simple | EUF-CMA | 1 | 32 | 64 | 17088 | -| SPHINCS+-SHAKE256-128s-robust | EUF-CMA | 1 | 32 | 64 | 7856 | | SPHINCS+-SHAKE256-128s-simple | EUF-CMA | 1 | 32 | 64 | 7856 | -| SPHINCS+-SHAKE256-192f-robust | EUF-CMA | 3 | 48 | 96 | 35664 | | SPHINCS+-SHAKE256-192f-simple | EUF-CMA | 3 | 48 | 96 | 35664 | -| SPHINCS+-SHAKE256-192s-robust | EUF-CMA | 3 | 48 | 96 | 16224 | | SPHINCS+-SHAKE256-192s-simple | EUF-CMA | 3 | 48 | 96 | 16224 | -| SPHINCS+-SHAKE256-256f-robust | EUF-CMA | 5 | 64 | 128 | 49856 | | SPHINCS+-SHAKE256-256f-simple | EUF-CMA | 5 | 64 | 128 | 49856 | -| SPHINCS+-SHAKE256-256s-robust | EUF-CMA | 5 | 64 | 128 | 29792 | | SPHINCS+-SHAKE256-256s-simple | EUF-CMA | 5 | 64 | 128 | 29792 | -## SPHINCS+-Haraka-128f-robust implementation characteristics +## SPHINCS+-SHA256-128f-simple implementation characteristics | Implementation source | Identifier in upstream | Supported architecture(s) | Supported operating system(s) | CPU extension(s) used | No branching-on-secrets claimed? | No branching-on-secrets checked by valgrind? | Large stack usage?‡ | |:---------------------------------:|:-------------------------|:----------------------------|:--------------------------------|:------------------------|:-----------------------------------|:-----------------------------------------------|:----------------------| | [Primary Source](#primary-source) | clean | All | All | None | True | True | False | -| [Primary Source](#primary-source) | aesni | x86\_64 | All | AES | True | True | False | +| [Primary Source](#primary-source) | avx2 | x86\_64 | All | AVX2 | True | True | False | Are implementations chosen based on runtime CPU feature detection? **Yes**. ‡For an explanation of what this denotes, consult the [Explanation of Terms](#explanation-of-terms) section at the end of this file. -## SPHINCS+-Haraka-128f-simple implementation characteristics - -| Implementation source | Identifier in upstream | Supported architecture(s) | Supported operating system(s) | CPU extension(s) used | No branching-on-secrets claimed? | No branching-on-secrets checked by valgrind? | Large stack usage? | -|:---------------------------------:|:-------------------------|:----------------------------|:--------------------------------|:------------------------|:-----------------------------------|:-----------------------------------------------|:---------------------| -| [Primary Source](#primary-source) | clean | All | All | None | True | True | False | -| [Primary Source](#primary-source) | aesni | x86\_64 | All | AES | True | True | False | - -Are implementations chosen based on runtime CPU feature detection? **Yes**. - -## SPHINCS+-Haraka-128s-robust implementation characteristics - -| Implementation source | Identifier in upstream | Supported architecture(s) | Supported operating system(s) | CPU extension(s) used | No branching-on-secrets claimed? | No branching-on-secrets checked by valgrind? | Large stack usage? | -|:---------------------------------:|:-------------------------|:----------------------------|:--------------------------------|:------------------------|:-----------------------------------|:-----------------------------------------------|:---------------------| -| [Primary Source](#primary-source) | clean | All | All | None | True | True | False | -| [Primary Source](#primary-source) | aesni | x86\_64 | All | AES | True | True | False | - -Are implementations chosen based on runtime CPU feature detection? **Yes**. - -## SPHINCS+-Haraka-128s-simple implementation characteristics - -| Implementation source | Identifier in upstream | Supported architecture(s) | Supported operating system(s) | CPU extension(s) used | No branching-on-secrets claimed? | No branching-on-secrets checked by valgrind? | Large stack usage? | -|:---------------------------------:|:-------------------------|:----------------------------|:--------------------------------|:------------------------|:-----------------------------------|:-----------------------------------------------|:---------------------| -| [Primary Source](#primary-source) | clean | All | All | None | True | True | False | -| [Primary Source](#primary-source) | aesni | x86\_64 | All | AES | True | True | False | - -Are implementations chosen based on runtime CPU feature detection? **Yes**. - -## SPHINCS+-Haraka-192f-robust implementation characteristics - -| Implementation source | Identifier in upstream | Supported architecture(s) | Supported operating system(s) | CPU extension(s) used | No branching-on-secrets claimed? | No branching-on-secrets checked by valgrind? | Large stack usage? | -|:---------------------------------:|:-------------------------|:----------------------------|:--------------------------------|:------------------------|:-----------------------------------|:-----------------------------------------------|:---------------------| -| [Primary Source](#primary-source) | clean | All | All | None | True | True | False | -| [Primary Source](#primary-source) | aesni | x86\_64 | All | AES | True | True | False | - -Are implementations chosen based on runtime CPU feature detection? **Yes**. - -## SPHINCS+-Haraka-192f-simple implementation characteristics - -| Implementation source | Identifier in upstream | Supported architecture(s) | Supported operating system(s) | CPU extension(s) used | No branching-on-secrets claimed? | No branching-on-secrets checked by valgrind? | Large stack usage? | -|:---------------------------------:|:-------------------------|:----------------------------|:--------------------------------|:------------------------|:-----------------------------------|:-----------------------------------------------|:---------------------| -| [Primary Source](#primary-source) | clean | All | All | None | True | True | False | -| [Primary Source](#primary-source) | aesni | x86\_64 | All | AES | True | True | False | - -Are implementations chosen based on runtime CPU feature detection? **Yes**. - -## SPHINCS+-Haraka-192s-robust implementation characteristics - -| Implementation source | Identifier in upstream | Supported architecture(s) | Supported operating system(s) | CPU extension(s) used | No branching-on-secrets claimed? | No branching-on-secrets checked by valgrind? | Large stack usage? | -|:---------------------------------:|:-------------------------|:----------------------------|:--------------------------------|:------------------------|:-----------------------------------|:-----------------------------------------------|:---------------------| -| [Primary Source](#primary-source) | clean | All | All | None | True | True | False | -| [Primary Source](#primary-source) | aesni | x86\_64 | All | AES | True | True | False | - -Are implementations chosen based on runtime CPU feature detection? **Yes**. - -## SPHINCS+-Haraka-192s-simple implementation characteristics - -| Implementation source | Identifier in upstream | Supported architecture(s) | Supported operating system(s) | CPU extension(s) used | No branching-on-secrets claimed? | No branching-on-secrets checked by valgrind? | Large stack usage? | -|:---------------------------------:|:-------------------------|:----------------------------|:--------------------------------|:------------------------|:-----------------------------------|:-----------------------------------------------|:---------------------| -| [Primary Source](#primary-source) | clean | All | All | None | True | True | False | -| [Primary Source](#primary-source) | aesni | x86\_64 | All | AES | True | True | False | - -Are implementations chosen based on runtime CPU feature detection? **Yes**. - -## SPHINCS+-Haraka-256f-robust implementation characteristics - -| Implementation source | Identifier in upstream | Supported architecture(s) | Supported operating system(s) | CPU extension(s) used | No branching-on-secrets claimed? | No branching-on-secrets checked by valgrind? | Large stack usage? | -|:---------------------------------:|:-------------------------|:----------------------------|:--------------------------------|:------------------------|:-----------------------------------|:-----------------------------------------------|:---------------------| -| [Primary Source](#primary-source) | clean | All | All | None | True | True | False | -| [Primary Source](#primary-source) | aesni | x86\_64 | All | AES | True | True | False | - -Are implementations chosen based on runtime CPU feature detection? **Yes**. - -## SPHINCS+-Haraka-256f-simple implementation characteristics - -| Implementation source | Identifier in upstream | Supported architecture(s) | Supported operating system(s) | CPU extension(s) used | No branching-on-secrets claimed? | No branching-on-secrets checked by valgrind? | Large stack usage? | -|:---------------------------------:|:-------------------------|:----------------------------|:--------------------------------|:------------------------|:-----------------------------------|:-----------------------------------------------|:---------------------| -| [Primary Source](#primary-source) | clean | All | All | None | True | True | False | -| [Primary Source](#primary-source) | aesni | x86\_64 | All | AES | True | True | False | - -Are implementations chosen based on runtime CPU feature detection? **Yes**. - -## SPHINCS+-Haraka-256s-robust implementation characteristics - -| Implementation source | Identifier in upstream | Supported architecture(s) | Supported operating system(s) | CPU extension(s) used | No branching-on-secrets claimed? | No branching-on-secrets checked by valgrind? | Large stack usage? | -|:---------------------------------:|:-------------------------|:----------------------------|:--------------------------------|:------------------------|:-----------------------------------|:-----------------------------------------------|:---------------------| -| [Primary Source](#primary-source) | clean | All | All | None | True | True | False | -| [Primary Source](#primary-source) | aesni | x86\_64 | All | AES | True | True | False | - -Are implementations chosen based on runtime CPU feature detection? **Yes**. - -## SPHINCS+-Haraka-256s-simple implementation characteristics - -| Implementation source | Identifier in upstream | Supported architecture(s) | Supported operating system(s) | CPU extension(s) used | No branching-on-secrets claimed? | No branching-on-secrets checked by valgrind? | Large stack usage? | -|:---------------------------------:|:-------------------------|:----------------------------|:--------------------------------|:------------------------|:-----------------------------------|:-----------------------------------------------|:---------------------| -| [Primary Source](#primary-source) | clean | All | All | None | True | True | False | -| [Primary Source](#primary-source) | aesni | x86\_64 | All | AES | True | True | False | - -Are implementations chosen based on runtime CPU feature detection? **Yes**. - -## SPHINCS+-SHA256-128f-robust implementation characteristics - -| Implementation source | Identifier in upstream | Supported architecture(s) | Supported operating system(s) | CPU extension(s) used | No branching-on-secrets claimed? | No branching-on-secrets checked by valgrind? | Large stack usage? | -|:---------------------------------:|:-------------------------|:----------------------------|:--------------------------------|:------------------------|:-----------------------------------|:-----------------------------------------------|:---------------------| -| [Primary Source](#primary-source) | clean | All | All | None | True | True | False | -| [Primary Source](#primary-source) | avx2 | x86\_64 | All | AVX2 | True | True | False | - -Are implementations chosen based on runtime CPU feature detection? **Yes**. - -## SPHINCS+-SHA256-128f-simple implementation characteristics - -| Implementation source | Identifier in upstream | Supported architecture(s) | Supported operating system(s) | CPU extension(s) used | No branching-on-secrets claimed? | No branching-on-secrets checked by valgrind? | Large stack usage? | -|:---------------------------------:|:-------------------------|:----------------------------|:--------------------------------|:------------------------|:-----------------------------------|:-----------------------------------------------|:---------------------| -| [Primary Source](#primary-source) | clean | All | All | None | True | True | False | -| [Primary Source](#primary-source) | avx2 | x86\_64 | All | AVX2 | True | True | False | - -Are implementations chosen based on runtime CPU feature detection? **Yes**. - -## SPHINCS+-SHA256-128s-robust implementation characteristics - -| Implementation source | Identifier in upstream | Supported architecture(s) | Supported operating system(s) | CPU extension(s) used | No branching-on-secrets claimed? | No branching-on-secrets checked by valgrind? | Large stack usage? | -|:---------------------------------:|:-------------------------|:----------------------------|:--------------------------------|:------------------------|:-----------------------------------|:-----------------------------------------------|:---------------------| -| [Primary Source](#primary-source) | clean | All | All | None | True | True | False | -| [Primary Source](#primary-source) | avx2 | x86\_64 | All | AVX2 | True | True | False | - -Are implementations chosen based on runtime CPU feature detection? **Yes**. - ## SPHINCS+-SHA256-128s-simple implementation characteristics | Implementation source | Identifier in upstream | Supported architecture(s) | Supported operating system(s) | CPU extension(s) used | No branching-on-secrets claimed? | No branching-on-secrets checked by valgrind? | Large stack usage? | @@ -202,15 +52,6 @@ Are implementations chosen based on runtime CPU feature detection? **Yes**. Are implementations chosen based on runtime CPU feature detection? **Yes**. -## SPHINCS+-SHA256-192f-robust implementation characteristics - -| Implementation source | Identifier in upstream | Supported architecture(s) | Supported operating system(s) | CPU extension(s) used | No branching-on-secrets claimed? | No branching-on-secrets checked by valgrind? | Large stack usage? | -|:---------------------------------:|:-------------------------|:----------------------------|:--------------------------------|:------------------------|:-----------------------------------|:-----------------------------------------------|:---------------------| -| [Primary Source](#primary-source) | clean | All | All | None | True | True | False | -| [Primary Source](#primary-source) | avx2 | x86\_64 | All | AVX2 | True | True | False | - -Are implementations chosen based on runtime CPU feature detection? **Yes**. - ## SPHINCS+-SHA256-192f-simple implementation characteristics | Implementation source | Identifier in upstream | Supported architecture(s) | Supported operating system(s) | CPU extension(s) used | No branching-on-secrets claimed? | No branching-on-secrets checked by valgrind? | Large stack usage? | @@ -220,15 +61,6 @@ Are implementations chosen based on runtime CPU feature detection? **Yes**. Are implementations chosen based on runtime CPU feature detection? **Yes**. -## SPHINCS+-SHA256-192s-robust implementation characteristics - -| Implementation source | Identifier in upstream | Supported architecture(s) | Supported operating system(s) | CPU extension(s) used | No branching-on-secrets claimed? | No branching-on-secrets checked by valgrind? | Large stack usage? | -|:---------------------------------:|:-------------------------|:----------------------------|:--------------------------------|:------------------------|:-----------------------------------|:-----------------------------------------------|:---------------------| -| [Primary Source](#primary-source) | clean | All | All | None | True | True | False | -| [Primary Source](#primary-source) | avx2 | x86\_64 | All | AVX2 | True | True | False | - -Are implementations chosen based on runtime CPU feature detection? **Yes**. - ## SPHINCS+-SHA256-192s-simple implementation characteristics | Implementation source | Identifier in upstream | Supported architecture(s) | Supported operating system(s) | CPU extension(s) used | No branching-on-secrets claimed? | No branching-on-secrets checked by valgrind? | Large stack usage? | @@ -238,15 +70,6 @@ Are implementations chosen based on runtime CPU feature detection? **Yes**. Are implementations chosen based on runtime CPU feature detection? **Yes**. -## SPHINCS+-SHA256-256f-robust implementation characteristics - -| Implementation source | Identifier in upstream | Supported architecture(s) | Supported operating system(s) | CPU extension(s) used | No branching-on-secrets claimed? | No branching-on-secrets checked by valgrind? | Large stack usage? | -|:---------------------------------:|:-------------------------|:----------------------------|:--------------------------------|:------------------------|:-----------------------------------|:-----------------------------------------------|:---------------------| -| [Primary Source](#primary-source) | clean | All | All | None | True | True | False | -| [Primary Source](#primary-source) | avx2 | x86\_64 | All | AVX2 | True | True | False | - -Are implementations chosen based on runtime CPU feature detection? **Yes**. - ## SPHINCS+-SHA256-256f-simple implementation characteristics | Implementation source | Identifier in upstream | Supported architecture(s) | Supported operating system(s) | CPU extension(s) used | No branching-on-secrets claimed? | No branching-on-secrets checked by valgrind? | Large stack usage? | @@ -256,15 +79,6 @@ Are implementations chosen based on runtime CPU feature detection? **Yes**. Are implementations chosen based on runtime CPU feature detection? **Yes**. -## SPHINCS+-SHA256-256s-robust implementation characteristics - -| Implementation source | Identifier in upstream | Supported architecture(s) | Supported operating system(s) | CPU extension(s) used | No branching-on-secrets claimed? | No branching-on-secrets checked by valgrind? | Large stack usage? | -|:---------------------------------:|:-------------------------|:----------------------------|:--------------------------------|:------------------------|:-----------------------------------|:-----------------------------------------------|:---------------------| -| [Primary Source](#primary-source) | clean | All | All | None | True | True | False | -| [Primary Source](#primary-source) | avx2 | x86\_64 | All | AVX2 | True | True | False | - -Are implementations chosen based on runtime CPU feature detection? **Yes**. - ## SPHINCS+-SHA256-256s-simple implementation characteristics | Implementation source | Identifier in upstream | Supported architecture(s) | Supported operating system(s) | CPU extension(s) used | No branching-on-secrets claimed? | No branching-on-secrets checked by valgrind? | Large stack usage? | @@ -274,15 +88,6 @@ Are implementations chosen based on runtime CPU feature detection? **Yes**. Are implementations chosen based on runtime CPU feature detection? **Yes**. -## SPHINCS+-SHAKE256-128f-robust implementation characteristics - -| Implementation source | Identifier in upstream | Supported architecture(s) | Supported operating system(s) | CPU extension(s) used | No branching-on-secrets claimed? | No branching-on-secrets checked by valgrind? | Large stack usage? | -|:---------------------------------:|:-------------------------|:----------------------------|:--------------------------------|:------------------------|:-----------------------------------|:-----------------------------------------------|:---------------------| -| [Primary Source](#primary-source) | clean | All | All | None | True | True | False | -| [Primary Source](#primary-source) | avx2 | x86\_64 | All | AVX2 | True | True | False | - -Are implementations chosen based on runtime CPU feature detection? **Yes**. - ## SPHINCS+-SHAKE256-128f-simple implementation characteristics | Implementation source | Identifier in upstream | Supported architecture(s) | Supported operating system(s) | CPU extension(s) used | No branching-on-secrets claimed? | No branching-on-secrets checked by valgrind? | Large stack usage? | @@ -292,15 +97,6 @@ Are implementations chosen based on runtime CPU feature detection? **Yes**. Are implementations chosen based on runtime CPU feature detection? **Yes**. -## SPHINCS+-SHAKE256-128s-robust implementation characteristics - -| Implementation source | Identifier in upstream | Supported architecture(s) | Supported operating system(s) | CPU extension(s) used | No branching-on-secrets claimed? | No branching-on-secrets checked by valgrind? | Large stack usage? | -|:---------------------------------:|:-------------------------|:----------------------------|:--------------------------------|:------------------------|:-----------------------------------|:-----------------------------------------------|:---------------------| -| [Primary Source](#primary-source) | clean | All | All | None | True | True | False | -| [Primary Source](#primary-source) | avx2 | x86\_64 | All | AVX2 | True | True | False | - -Are implementations chosen based on runtime CPU feature detection? **Yes**. - ## SPHINCS+-SHAKE256-128s-simple implementation characteristics | Implementation source | Identifier in upstream | Supported architecture(s) | Supported operating system(s) | CPU extension(s) used | No branching-on-secrets claimed? | No branching-on-secrets checked by valgrind? | Large stack usage? | @@ -310,15 +106,6 @@ Are implementations chosen based on runtime CPU feature detection? **Yes**. Are implementations chosen based on runtime CPU feature detection? **Yes**. -## SPHINCS+-SHAKE256-192f-robust implementation characteristics - -| Implementation source | Identifier in upstream | Supported architecture(s) | Supported operating system(s) | CPU extension(s) used | No branching-on-secrets claimed? | No branching-on-secrets checked by valgrind? | Large stack usage? | -|:---------------------------------:|:-------------------------|:----------------------------|:--------------------------------|:------------------------|:-----------------------------------|:-----------------------------------------------|:---------------------| -| [Primary Source](#primary-source) | clean | All | All | None | True | True | False | -| [Primary Source](#primary-source) | avx2 | x86\_64 | All | AVX2 | True | True | False | - -Are implementations chosen based on runtime CPU feature detection? **Yes**. - ## SPHINCS+-SHAKE256-192f-simple implementation characteristics | Implementation source | Identifier in upstream | Supported architecture(s) | Supported operating system(s) | CPU extension(s) used | No branching-on-secrets claimed? | No branching-on-secrets checked by valgrind? | Large stack usage? | @@ -328,15 +115,6 @@ Are implementations chosen based on runtime CPU feature detection? **Yes**. Are implementations chosen based on runtime CPU feature detection? **Yes**. -## SPHINCS+-SHAKE256-192s-robust implementation characteristics - -| Implementation source | Identifier in upstream | Supported architecture(s) | Supported operating system(s) | CPU extension(s) used | No branching-on-secrets claimed? | No branching-on-secrets checked by valgrind? | Large stack usage? | -|:---------------------------------:|:-------------------------|:----------------------------|:--------------------------------|:------------------------|:-----------------------------------|:-----------------------------------------------|:---------------------| -| [Primary Source](#primary-source) | clean | All | All | None | True | True | False | -| [Primary Source](#primary-source) | avx2 | x86\_64 | All | AVX2 | True | True | False | - -Are implementations chosen based on runtime CPU feature detection? **Yes**. - ## SPHINCS+-SHAKE256-192s-simple implementation characteristics | Implementation source | Identifier in upstream | Supported architecture(s) | Supported operating system(s) | CPU extension(s) used | No branching-on-secrets claimed? | No branching-on-secrets checked by valgrind? | Large stack usage? | @@ -346,15 +124,6 @@ Are implementations chosen based on runtime CPU feature detection? **Yes**. Are implementations chosen based on runtime CPU feature detection? **Yes**. -## SPHINCS+-SHAKE256-256f-robust implementation characteristics - -| Implementation source | Identifier in upstream | Supported architecture(s) | Supported operating system(s) | CPU extension(s) used | No branching-on-secrets claimed? | No branching-on-secrets checked by valgrind? | Large stack usage? | -|:---------------------------------:|:-------------------------|:----------------------------|:--------------------------------|:------------------------|:-----------------------------------|:-----------------------------------------------|:---------------------| -| [Primary Source](#primary-source) | clean | All | All | None | True | True | False | -| [Primary Source](#primary-source) | avx2 | x86\_64 | All | AVX2 | True | True | False | - -Are implementations chosen based on runtime CPU feature detection? **Yes**. - ## SPHINCS+-SHAKE256-256f-simple implementation characteristics | Implementation source | Identifier in upstream | Supported architecture(s) | Supported operating system(s) | CPU extension(s) used | No branching-on-secrets claimed? | No branching-on-secrets checked by valgrind? | Large stack usage? | @@ -364,15 +133,6 @@ Are implementations chosen based on runtime CPU feature detection? **Yes**. Are implementations chosen based on runtime CPU feature detection? **Yes**. -## SPHINCS+-SHAKE256-256s-robust implementation characteristics - -| Implementation source | Identifier in upstream | Supported architecture(s) | Supported operating system(s) | CPU extension(s) used | No branching-on-secrets claimed? | No branching-on-secrets checked by valgrind? | Large stack usage? | -|:---------------------------------:|:-------------------------|:----------------------------|:--------------------------------|:------------------------|:-----------------------------------|:-----------------------------------------------|:---------------------| -| [Primary Source](#primary-source) | clean | All | All | None | True | True | False | -| [Primary Source](#primary-source) | avx2 | x86\_64 | All | AVX2 | True | True | False | - -Are implementations chosen based on runtime CPU feature detection? **Yes**. - ## SPHINCS+-SHAKE256-256s-simple implementation characteristics | Implementation source | Identifier in upstream | Supported architecture(s) | Supported operating system(s) | CPU extension(s) used | No branching-on-secrets claimed? | No branching-on-secrets checked by valgrind? | Large stack usage? | diff --git a/docs/algorithms/sig/sphincs.yml b/docs/algorithms/sig/sphincs.yml index d4d1c904a2..063996bb7d 100644 --- a/docs/algorithms/sig/sphincs.yml +++ b/docs/algorithms/sig/sphincs.yml @@ -27,423 +27,19 @@ spec-version: NIST Round 3 submission spdx-license-identifier: CC0-1.0 primary-upstream: source: https://github.com/PQClean/PQClean/commit/c1b19a865de329e87e9b3e9152362fcb709da8ab + with copy_from_upstream patches spdx-license-identifier: CC0-1.0 upstream-ancestors: - https://github.com/sphincs/sphincsplus advisories: - This algorithm is not tested under Windows. parameter-sets: -- name: SPHINCS+-Haraka-128f-robust - claimed-nist-level: 1 - claimed-security: EUF-CMA - length-public-key: 32 - length-secret-key: 64 - length-signature: 17088 - implementations-switch-on-runtime-cpu-features: true - implementations: - - upstream: primary-upstream - upstream-id: clean - supported-platforms: all - common-crypto: - - AES: BearSSL (packaged) - no-secret-dependent-branching-claimed: true - no-secret-dependent-branching-checked-by-valgrind: true - large-stack-usage: false - - upstream: primary-upstream - upstream-id: aesni - supported-platforms: - - architecture: x86_64 - required_flags: - - aes - common-crypto: - - AES: packaged - no-secret-dependent-branching-claimed: true - no-secret-dependent-branching-checked-by-valgrind: true - large-stack-usage: false -- name: SPHINCS+-Haraka-128f-simple - claimed-nist-level: 1 - claimed-security: EUF-CMA - length-public-key: 32 - length-secret-key: 64 - length-signature: 17088 - implementations-switch-on-runtime-cpu-features: true - implementations: - - upstream: primary-upstream - upstream-id: clean - supported-platforms: all - common-crypto: - - AES: BearSSL (packaged) - no-secret-dependent-branching-claimed: true - no-secret-dependent-branching-checked-by-valgrind: true - large-stack-usage: false - - upstream: primary-upstream - upstream-id: aesni - supported-platforms: - - architecture: x86_64 - required_flags: - - aes - common-crypto: - - AES: packaged - no-secret-dependent-branching-claimed: true - no-secret-dependent-branching-checked-by-valgrind: true - large-stack-usage: false -- name: SPHINCS+-Haraka-128s-robust - claimed-nist-level: 1 - claimed-security: EUF-CMA - length-public-key: 32 - length-secret-key: 64 - length-signature: 7856 - implementations-switch-on-runtime-cpu-features: true - implementations: - - upstream: primary-upstream - upstream-id: clean - supported-platforms: all - common-crypto: - - AES: BearSSL (packaged) - no-secret-dependent-branching-claimed: true - no-secret-dependent-branching-checked-by-valgrind: true - large-stack-usage: false - - upstream: primary-upstream - upstream-id: aesni - supported-platforms: - - architecture: x86_64 - required_flags: - - aes - common-crypto: - - AES: packaged - no-secret-dependent-branching-claimed: true - no-secret-dependent-branching-checked-by-valgrind: true - large-stack-usage: false -- name: SPHINCS+-Haraka-128s-simple - claimed-nist-level: 1 - claimed-security: EUF-CMA - length-public-key: 32 - length-secret-key: 64 - length-signature: 7856 - implementations-switch-on-runtime-cpu-features: true - implementations: - - upstream: primary-upstream - upstream-id: clean - supported-platforms: all - common-crypto: - - AES: BearSSL (packaged) - no-secret-dependent-branching-claimed: true - no-secret-dependent-branching-checked-by-valgrind: true - large-stack-usage: false - - upstream: primary-upstream - upstream-id: aesni - supported-platforms: - - architecture: x86_64 - required_flags: - - aes - common-crypto: - - AES: packaged - no-secret-dependent-branching-claimed: true - no-secret-dependent-branching-checked-by-valgrind: true - large-stack-usage: false -- name: SPHINCS+-Haraka-192f-robust - claimed-nist-level: 2 - claimed-security: EUF-CMA - length-public-key: 48 - length-secret-key: 96 - length-signature: 35664 - implementations-switch-on-runtime-cpu-features: true - implementations: - - upstream: primary-upstream - upstream-id: clean - supported-platforms: all - common-crypto: - - AES: BearSSL (packaged) - no-secret-dependent-branching-claimed: true - no-secret-dependent-branching-checked-by-valgrind: true - large-stack-usage: false - - upstream: primary-upstream - upstream-id: aesni - supported-platforms: - - architecture: x86_64 - required_flags: - - aes - common-crypto: - - AES: packaged - no-secret-dependent-branching-claimed: true - no-secret-dependent-branching-checked-by-valgrind: true - large-stack-usage: false -- name: SPHINCS+-Haraka-192f-simple - claimed-nist-level: 2 - claimed-security: EUF-CMA - length-public-key: 48 - length-secret-key: 96 - length-signature: 35664 - implementations-switch-on-runtime-cpu-features: true - implementations: - - upstream: primary-upstream - upstream-id: clean - supported-platforms: all - common-crypto: - - AES: BearSSL (packaged) - no-secret-dependent-branching-claimed: true - no-secret-dependent-branching-checked-by-valgrind: true - large-stack-usage: false - - upstream: primary-upstream - upstream-id: aesni - supported-platforms: - - architecture: x86_64 - required_flags: - - aes - common-crypto: - - AES: packaged - no-secret-dependent-branching-claimed: true - no-secret-dependent-branching-checked-by-valgrind: true - large-stack-usage: false -- name: SPHINCS+-Haraka-192s-robust - claimed-nist-level: 2 - claimed-security: EUF-CMA - length-public-key: 48 - length-secret-key: 96 - length-signature: 16224 - implementations-switch-on-runtime-cpu-features: true - implementations: - - upstream: primary-upstream - upstream-id: clean - supported-platforms: all - common-crypto: - - AES: BearSSL (packaged) - no-secret-dependent-branching-claimed: true - no-secret-dependent-branching-checked-by-valgrind: true - large-stack-usage: false - - upstream: primary-upstream - upstream-id: aesni - supported-platforms: - - architecture: x86_64 - required_flags: - - aes - common-crypto: - - AES: packaged - no-secret-dependent-branching-claimed: true - no-secret-dependent-branching-checked-by-valgrind: true - large-stack-usage: false -- name: SPHINCS+-Haraka-192s-simple - claimed-nist-level: 2 - claimed-security: EUF-CMA - length-public-key: 48 - length-secret-key: 96 - length-signature: 16224 - implementations-switch-on-runtime-cpu-features: true - implementations: - - upstream: primary-upstream - upstream-id: clean - supported-platforms: all - common-crypto: - - AES: BearSSL (packaged) - no-secret-dependent-branching-claimed: true - no-secret-dependent-branching-checked-by-valgrind: true - large-stack-usage: false - - upstream: primary-upstream - upstream-id: aesni - supported-platforms: - - architecture: x86_64 - required_flags: - - aes - common-crypto: - - AES: packaged - no-secret-dependent-branching-claimed: true - no-secret-dependent-branching-checked-by-valgrind: true - large-stack-usage: false -- name: SPHINCS+-Haraka-256f-robust - claimed-nist-level: 2 - claimed-security: EUF-CMA - length-public-key: 64 - length-secret-key: 128 - length-signature: 49856 - implementations-switch-on-runtime-cpu-features: true - implementations: - - upstream: primary-upstream - upstream-id: clean - supported-platforms: all - common-crypto: - - AES: BearSSL (packaged) - no-secret-dependent-branching-claimed: true - no-secret-dependent-branching-checked-by-valgrind: true - large-stack-usage: false - - upstream: primary-upstream - upstream-id: aesni - supported-platforms: - - architecture: x86_64 - required_flags: - - aes - common-crypto: - - AES: packaged - no-secret-dependent-branching-claimed: true - no-secret-dependent-branching-checked-by-valgrind: true - large-stack-usage: false -- name: SPHINCS+-Haraka-256f-simple - claimed-nist-level: 2 - claimed-security: EUF-CMA - length-public-key: 64 - length-secret-key: 128 - length-signature: 49856 - implementations-switch-on-runtime-cpu-features: true - implementations: - - upstream: primary-upstream - upstream-id: clean - supported-platforms: all - common-crypto: - - AES: BearSSL (packaged) - no-secret-dependent-branching-claimed: true - no-secret-dependent-branching-checked-by-valgrind: true - large-stack-usage: false - - upstream: primary-upstream - upstream-id: aesni - supported-platforms: - - architecture: x86_64 - required_flags: - - aes - common-crypto: - - AES: packaged - no-secret-dependent-branching-claimed: true - no-secret-dependent-branching-checked-by-valgrind: true - large-stack-usage: false -- name: SPHINCS+-Haraka-256s-robust - claimed-nist-level: 2 - claimed-security: EUF-CMA - length-public-key: 64 - length-secret-key: 128 - length-signature: 29792 - implementations-switch-on-runtime-cpu-features: true - implementations: - - upstream: primary-upstream - upstream-id: clean - supported-platforms: all - common-crypto: - - AES: BearSSL (packaged) - no-secret-dependent-branching-claimed: true - no-secret-dependent-branching-checked-by-valgrind: true - large-stack-usage: false - - upstream: primary-upstream - upstream-id: aesni - supported-platforms: - - architecture: x86_64 - required_flags: - - aes - common-crypto: - - AES: packaged - no-secret-dependent-branching-claimed: true - no-secret-dependent-branching-checked-by-valgrind: true - large-stack-usage: false -- name: SPHINCS+-Haraka-256s-simple - claimed-nist-level: 2 - claimed-security: EUF-CMA - length-public-key: 64 - length-secret-key: 128 - length-signature: 29792 - implementations-switch-on-runtime-cpu-features: true - implementations: - - upstream: primary-upstream - upstream-id: clean - supported-platforms: all - common-crypto: - - AES: BearSSL (packaged) - no-secret-dependent-branching-claimed: true - no-secret-dependent-branching-checked-by-valgrind: true - large-stack-usage: false - - upstream: primary-upstream - upstream-id: aesni - supported-platforms: - - architecture: x86_64 - required_flags: - - aes - common-crypto: - - AES: packaged - no-secret-dependent-branching-claimed: true - no-secret-dependent-branching-checked-by-valgrind: true - large-stack-usage: false -- name: SPHINCS+-SHA256-128f-robust - claimed-nist-level: 1 - claimed-security: EUF-CMA - length-public-key: 32 - length-secret-key: 64 - length-signature: 17088 - implementations-switch-on-runtime-cpu-features: true - implementations: - - upstream: primary-upstream - upstream-id: clean - supported-platforms: all - common-crypto: - - SHA2: liboqs - no-secret-dependent-branching-claimed: true - no-secret-dependent-branching-checked-by-valgrind: true - large-stack-usage: false - - upstream: primary-upstream - upstream-id: avx2 - supported-platforms: - - architecture: x86_64 - required_flags: - - avx2 - common-crypto: - - SHA2: liboqs - no-secret-dependent-branching-claimed: true - no-secret-dependent-branching-checked-by-valgrind: true - large-stack-usage: false -- name: SPHINCS+-SHA256-128f-simple - claimed-nist-level: 1 - claimed-security: EUF-CMA - length-public-key: 32 - length-secret-key: 64 - length-signature: 17088 - implementations-switch-on-runtime-cpu-features: true - implementations: - - upstream: primary-upstream - upstream-id: clean - supported-platforms: all - common-crypto: - - SHA2: liboqs - no-secret-dependent-branching-claimed: true - no-secret-dependent-branching-checked-by-valgrind: true - large-stack-usage: false - - upstream: primary-upstream - upstream-id: avx2 - supported-platforms: - - architecture: x86_64 - required_flags: - - avx2 - common-crypto: - - SHA2: liboqs - no-secret-dependent-branching-claimed: true - no-secret-dependent-branching-checked-by-valgrind: true - large-stack-usage: false -- name: SPHINCS+-SHA256-128s-robust - claimed-nist-level: 1 - claimed-security: EUF-CMA - length-public-key: 32 - length-secret-key: 64 - length-signature: 7856 - implementations-switch-on-runtime-cpu-features: true - implementations: - - upstream: primary-upstream - upstream-id: clean - supported-platforms: all - common-crypto: - - SHA2: liboqs - no-secret-dependent-branching-claimed: true - no-secret-dependent-branching-checked-by-valgrind: true - large-stack-usage: false - - upstream: primary-upstream - upstream-id: avx2 - supported-platforms: - - architecture: x86_64 - required_flags: - - avx2 - common-crypto: - - SHA2: liboqs - no-secret-dependent-branching-claimed: true - no-secret-dependent-branching-checked-by-valgrind: true - large-stack-usage: false -- name: SPHINCS+-SHA256-128s-simple +- name: SPHINCS+-SHA256-128f-simple claimed-nist-level: 1 claimed-security: EUF-CMA length-public-key: 32 length-secret-key: 64 - length-signature: 7856 + length-signature: 17088 implementations-switch-on-runtime-cpu-features: true implementations: - upstream: primary-upstream @@ -465,12 +61,12 @@ parameter-sets: no-secret-dependent-branching-claimed: true no-secret-dependent-branching-checked-by-valgrind: true large-stack-usage: false -- name: SPHINCS+-SHA256-192f-robust - claimed-nist-level: 3 +- name: SPHINCS+-SHA256-128s-simple + claimed-nist-level: 1 claimed-security: EUF-CMA - length-public-key: 48 - length-secret-key: 96 - length-signature: 35664 + length-public-key: 32 + length-secret-key: 64 + length-signature: 7856 implementations-switch-on-runtime-cpu-features: true implementations: - upstream: primary-upstream @@ -519,33 +115,6 @@ parameter-sets: no-secret-dependent-branching-claimed: true no-secret-dependent-branching-checked-by-valgrind: true large-stack-usage: false -- name: SPHINCS+-SHA256-192s-robust - claimed-nist-level: 3 - claimed-security: EUF-CMA - length-public-key: 48 - length-secret-key: 96 - length-signature: 16224 - implementations-switch-on-runtime-cpu-features: true - implementations: - - upstream: primary-upstream - upstream-id: clean - supported-platforms: all - common-crypto: - - SHA2: liboqs - no-secret-dependent-branching-claimed: true - no-secret-dependent-branching-checked-by-valgrind: true - large-stack-usage: false - - upstream: primary-upstream - upstream-id: avx2 - supported-platforms: - - architecture: x86_64 - required_flags: - - avx2 - common-crypto: - - SHA2: liboqs - no-secret-dependent-branching-claimed: true - no-secret-dependent-branching-checked-by-valgrind: true - large-stack-usage: false - name: SPHINCS+-SHA256-192s-simple claimed-nist-level: 3 claimed-security: EUF-CMA @@ -573,33 +142,6 @@ parameter-sets: no-secret-dependent-branching-claimed: true no-secret-dependent-branching-checked-by-valgrind: true large-stack-usage: false -- name: SPHINCS+-SHA256-256f-robust - claimed-nist-level: 5 - claimed-security: EUF-CMA - length-public-key: 64 - length-secret-key: 128 - length-signature: 49856 - implementations-switch-on-runtime-cpu-features: true - implementations: - - upstream: primary-upstream - upstream-id: clean - supported-platforms: all - common-crypto: - - SHA2: liboqs - no-secret-dependent-branching-claimed: true - no-secret-dependent-branching-checked-by-valgrind: true - large-stack-usage: false - - upstream: primary-upstream - upstream-id: avx2 - supported-platforms: - - architecture: x86_64 - required_flags: - - avx2 - common-crypto: - - SHA2: liboqs - no-secret-dependent-branching-claimed: true - no-secret-dependent-branching-checked-by-valgrind: true - large-stack-usage: false - name: SPHINCS+-SHA256-256f-simple claimed-nist-level: 5 claimed-security: EUF-CMA @@ -627,33 +169,6 @@ parameter-sets: no-secret-dependent-branching-claimed: true no-secret-dependent-branching-checked-by-valgrind: true large-stack-usage: false -- name: SPHINCS+-SHA256-256s-robust - claimed-nist-level: 5 - claimed-security: EUF-CMA - length-public-key: 64 - length-secret-key: 128 - length-signature: 29792 - implementations-switch-on-runtime-cpu-features: true - implementations: - - upstream: primary-upstream - upstream-id: clean - supported-platforms: all - common-crypto: - - SHA2: liboqs - no-secret-dependent-branching-claimed: true - no-secret-dependent-branching-checked-by-valgrind: true - large-stack-usage: false - - upstream: primary-upstream - upstream-id: avx2 - supported-platforms: - - architecture: x86_64 - required_flags: - - avx2 - common-crypto: - - SHA2: liboqs - no-secret-dependent-branching-claimed: true - no-secret-dependent-branching-checked-by-valgrind: true - large-stack-usage: false - name: SPHINCS+-SHA256-256s-simple claimed-nist-level: 5 claimed-security: EUF-CMA @@ -681,33 +196,6 @@ parameter-sets: no-secret-dependent-branching-claimed: true no-secret-dependent-branching-checked-by-valgrind: true large-stack-usage: false -- name: SPHINCS+-SHAKE256-128f-robust - claimed-nist-level: 1 - claimed-security: EUF-CMA - length-public-key: 32 - length-secret-key: 64 - length-signature: 17088 - implementations-switch-on-runtime-cpu-features: true - implementations: - - upstream: primary-upstream - upstream-id: clean - supported-platforms: all - common-crypto: - - SHA3: liboqs - no-secret-dependent-branching-claimed: true - no-secret-dependent-branching-checked-by-valgrind: true - large-stack-usage: false - - upstream: primary-upstream - upstream-id: avx2 - supported-platforms: - - architecture: x86_64 - required_flags: - - avx2 - common-crypto: - - SHA3: liboqs - no-secret-dependent-branching-claimed: true - no-secret-dependent-branching-checked-by-valgrind: true - large-stack-usage: false - name: SPHINCS+-SHAKE256-128f-simple claimed-nist-level: 1 claimed-security: EUF-CMA @@ -735,33 +223,6 @@ parameter-sets: no-secret-dependent-branching-claimed: true no-secret-dependent-branching-checked-by-valgrind: true large-stack-usage: false -- name: SPHINCS+-SHAKE256-128s-robust - claimed-nist-level: 1 - claimed-security: EUF-CMA - length-public-key: 32 - length-secret-key: 64 - length-signature: 7856 - implementations-switch-on-runtime-cpu-features: true - implementations: - - upstream: primary-upstream - upstream-id: clean - supported-platforms: all - common-crypto: - - SHA3: liboqs - no-secret-dependent-branching-claimed: true - no-secret-dependent-branching-checked-by-valgrind: true - large-stack-usage: false - - upstream: primary-upstream - upstream-id: avx2 - supported-platforms: - - architecture: x86_64 - required_flags: - - avx2 - common-crypto: - - SHA3: liboqs - no-secret-dependent-branching-claimed: true - no-secret-dependent-branching-checked-by-valgrind: true - large-stack-usage: false - name: SPHINCS+-SHAKE256-128s-simple claimed-nist-level: 1 claimed-security: EUF-CMA @@ -789,33 +250,6 @@ parameter-sets: no-secret-dependent-branching-claimed: true no-secret-dependent-branching-checked-by-valgrind: true large-stack-usage: false -- name: SPHINCS+-SHAKE256-192f-robust - claimed-nist-level: 3 - claimed-security: EUF-CMA - length-public-key: 48 - length-secret-key: 96 - length-signature: 35664 - implementations-switch-on-runtime-cpu-features: true - implementations: - - upstream: primary-upstream - upstream-id: clean - supported-platforms: all - common-crypto: - - SHA3: liboqs - no-secret-dependent-branching-claimed: true - no-secret-dependent-branching-checked-by-valgrind: true - large-stack-usage: false - - upstream: primary-upstream - upstream-id: avx2 - supported-platforms: - - architecture: x86_64 - required_flags: - - avx2 - common-crypto: - - SHA3: liboqs - no-secret-dependent-branching-claimed: true - no-secret-dependent-branching-checked-by-valgrind: true - large-stack-usage: false - name: SPHINCS+-SHAKE256-192f-simple claimed-nist-level: 3 claimed-security: EUF-CMA @@ -843,33 +277,6 @@ parameter-sets: no-secret-dependent-branching-claimed: true no-secret-dependent-branching-checked-by-valgrind: true large-stack-usage: false -- name: SPHINCS+-SHAKE256-192s-robust - claimed-nist-level: 3 - claimed-security: EUF-CMA - length-public-key: 48 - length-secret-key: 96 - length-signature: 16224 - implementations-switch-on-runtime-cpu-features: true - implementations: - - upstream: primary-upstream - upstream-id: clean - supported-platforms: all - common-crypto: - - SHA3: liboqs - no-secret-dependent-branching-claimed: true - no-secret-dependent-branching-checked-by-valgrind: true - large-stack-usage: false - - upstream: primary-upstream - upstream-id: avx2 - supported-platforms: - - architecture: x86_64 - required_flags: - - avx2 - common-crypto: - - SHA3: liboqs - no-secret-dependent-branching-claimed: true - no-secret-dependent-branching-checked-by-valgrind: true - large-stack-usage: false - name: SPHINCS+-SHAKE256-192s-simple claimed-nist-level: 3 claimed-security: EUF-CMA @@ -897,33 +304,6 @@ parameter-sets: no-secret-dependent-branching-claimed: true no-secret-dependent-branching-checked-by-valgrind: true large-stack-usage: false -- name: SPHINCS+-SHAKE256-256f-robust - claimed-nist-level: 5 - claimed-security: EUF-CMA - length-public-key: 64 - length-secret-key: 128 - length-signature: 49856 - implementations-switch-on-runtime-cpu-features: true - implementations: - - upstream: primary-upstream - upstream-id: clean - supported-platforms: all - common-crypto: - - SHA3: liboqs - no-secret-dependent-branching-claimed: true - no-secret-dependent-branching-checked-by-valgrind: true - large-stack-usage: false - - upstream: primary-upstream - upstream-id: avx2 - supported-platforms: - - architecture: x86_64 - required_flags: - - avx2 - common-crypto: - - SHA3: liboqs - no-secret-dependent-branching-claimed: true - no-secret-dependent-branching-checked-by-valgrind: true - large-stack-usage: false - name: SPHINCS+-SHAKE256-256f-simple claimed-nist-level: 5 claimed-security: EUF-CMA @@ -951,33 +331,6 @@ parameter-sets: no-secret-dependent-branching-claimed: true no-secret-dependent-branching-checked-by-valgrind: true large-stack-usage: false -- name: SPHINCS+-SHAKE256-256s-robust - claimed-nist-level: 5 - claimed-security: EUF-CMA - length-public-key: 64 - length-secret-key: 128 - length-signature: 29792 - implementations-switch-on-runtime-cpu-features: true - implementations: - - upstream: primary-upstream - upstream-id: clean - supported-platforms: all - common-crypto: - - SHA3: liboqs - no-secret-dependent-branching-claimed: true - no-secret-dependent-branching-checked-by-valgrind: true - large-stack-usage: false - - upstream: primary-upstream - upstream-id: avx2 - supported-platforms: - - architecture: x86_64 - required_flags: - - avx2 - common-crypto: - - SHA3: liboqs - no-secret-dependent-branching-claimed: true - no-secret-dependent-branching-checked-by-valgrind: true - large-stack-usage: false - name: SPHINCS+-SHAKE256-256s-simple claimed-nist-level: 5 claimed-security: EUF-CMA diff --git a/docs/cbom.json b/docs/cbom.json index 297c9e3678..519005ba6e 100644 --- a/docs/cbom.json +++ b/docs/cbom.json @@ -1,23 +1,23 @@ { "bomFormat": "CBOM", "specVersion": "1.4-cbom-1.0", - "serialNumber": "urn:uuid:46ad14ba-31d7-42ad-83c8-08c1755261c7", + "serialNumber": "urn:uuid:d3a68186-b121-4a7c-a5d3-19fcdb523e84", "version": 1, "metadata": { - "timestamp": "2023-03-18T11:09:37.700416", + "timestamp": "2023-05-15T07:12:08.268259", "component": { "type": "library", - "bom-ref": "pkg:github/open-quantum-safe/liboqs@d61d81c526da8bb62e363f5a75191689572151cb", + "bom-ref": "pkg:github/open-quantum-safe/liboqs@79988c6d7388d4e33fa49792ca1c1d8ac2901096", "name": "liboqs", - "version": "d61d81c526da8bb62e363f5a75191689572151cb" + "version": "79988c6d7388d4e33fa49792ca1c1d8ac2901096" } }, "components": [ { "type": "library", - "bom-ref": "pkg:github/open-quantum-safe/liboqs@d61d81c526da8bb62e363f5a75191689572151cb", + "bom-ref": "pkg:github/open-quantum-safe/liboqs@79988c6d7388d4e33fa49792ca1c1d8ac2901096", "name": "liboqs", - "version": "d61d81c526da8bb62e363f5a75191689572151cb" + "version": "79988c6d7388d4e33fa49792ca1c1d8ac2901096" }, { "type": "crypto-asset", @@ -899,46 +899,6 @@ "nistQuantumSecurityLevel": 1 } }, - { - "type": "crypto-asset", - "bom-ref": "alg:Kyber512-90s:generic", - "name": "Kyber", - "cryptoProperties": { - "assetType": "algorithm", - "algorithmProperties": { - "variant": "Kyber512-90s", - "primitive": "kem", - "implementationLevel": "softwarePlainRam", - "cryptoFunctions": [ - "keygen", - "encapsulate", - "decapsulate" - ], - "implementationPlatform": "generic" - }, - "nistQuantumSecurityLevel": 1 - } - }, - { - "type": "crypto-asset", - "bom-ref": "alg:Kyber512-90s:x86_64", - "name": "Kyber", - "cryptoProperties": { - "assetType": "algorithm", - "algorithmProperties": { - "variant": "Kyber512-90s", - "primitive": "kem", - "implementationLevel": "softwarePlainRam", - "cryptoFunctions": [ - "keygen", - "encapsulate", - "decapsulate" - ], - "implementationPlatform": "x86_64" - }, - "nistQuantumSecurityLevel": 1 - } - }, { "type": "crypto-asset", "bom-ref": "alg:Kyber768:generic", @@ -999,46 +959,6 @@ "nistQuantumSecurityLevel": 3 } }, - { - "type": "crypto-asset", - "bom-ref": "alg:Kyber768-90s:generic", - "name": "Kyber", - "cryptoProperties": { - "assetType": "algorithm", - "algorithmProperties": { - "variant": "Kyber768-90s", - "primitive": "kem", - "implementationLevel": "softwarePlainRam", - "cryptoFunctions": [ - "keygen", - "encapsulate", - "decapsulate" - ], - "implementationPlatform": "generic" - }, - "nistQuantumSecurityLevel": 3 - } - }, - { - "type": "crypto-asset", - "bom-ref": "alg:Kyber768-90s:x86_64", - "name": "Kyber", - "cryptoProperties": { - "assetType": "algorithm", - "algorithmProperties": { - "variant": "Kyber768-90s", - "primitive": "kem", - "implementationLevel": "softwarePlainRam", - "cryptoFunctions": [ - "keygen", - "encapsulate", - "decapsulate" - ], - "implementationPlatform": "x86_64" - }, - "nistQuantumSecurityLevel": 3 - } - }, { "type": "crypto-asset", "bom-ref": "alg:Kyber1024:generic", @@ -1099,46 +1019,6 @@ "nistQuantumSecurityLevel": 5 } }, - { - "type": "crypto-asset", - "bom-ref": "alg:Kyber1024-90s:generic", - "name": "Kyber", - "cryptoProperties": { - "assetType": "algorithm", - "algorithmProperties": { - "variant": "Kyber1024-90s", - "primitive": "kem", - "implementationLevel": "softwarePlainRam", - "cryptoFunctions": [ - "keygen", - "encapsulate", - "decapsulate" - ], - "implementationPlatform": "generic" - }, - "nistQuantumSecurityLevel": 5 - } - }, - { - "type": "crypto-asset", - "bom-ref": "alg:Kyber1024-90s:x86_64", - "name": "Kyber", - "cryptoProperties": { - "assetType": "algorithm", - "algorithmProperties": { - "variant": "Kyber1024-90s", - "primitive": "kem", - "implementationLevel": "softwarePlainRam", - "cryptoFunctions": [ - "keygen", - "encapsulate", - "decapsulate" - ], - "implementationPlatform": "x86_64" - }, - "nistQuantumSecurityLevel": 5 - } - }, { "type": "crypto-asset", "bom-ref": "alg:sntrup761:generic", @@ -1361,12 +1241,12 @@ }, { "type": "crypto-asset", - "bom-ref": "alg:Dilithium2-AES:generic", - "name": "CRYSTALS-Dilithium", + "bom-ref": "alg:Falcon-512:generic", + "name": "Falcon", "cryptoProperties": { "assetType": "algorithm", "algorithmProperties": { - "variant": "Dilithium2-AES", + "variant": "Falcon-512", "primitive": "signature", "implementationLevel": "softwarePlainRam", "cryptoFunctions": [ @@ -1376,17 +1256,17 @@ ], "implementationPlatform": "generic" }, - "nistQuantumSecurityLevel": 2 + "nistQuantumSecurityLevel": 1 } }, { "type": "crypto-asset", - "bom-ref": "alg:Dilithium2-AES:x86_64", - "name": "CRYSTALS-Dilithium", + "bom-ref": "alg:Falcon-512:x86_64", + "name": "Falcon", "cryptoProperties": { "assetType": "algorithm", "algorithmProperties": { - "variant": "Dilithium2-AES", + "variant": "Falcon-512", "primitive": "signature", "implementationLevel": "softwarePlainRam", "cryptoFunctions": [ @@ -1396,17 +1276,17 @@ ], "implementationPlatform": "x86_64" }, - "nistQuantumSecurityLevel": 2 + "nistQuantumSecurityLevel": 1 } }, { "type": "crypto-asset", - "bom-ref": "alg:Dilithium3-AES:generic", - "name": "CRYSTALS-Dilithium", + "bom-ref": "alg:Falcon-1024:generic", + "name": "Falcon", "cryptoProperties": { "assetType": "algorithm", "algorithmProperties": { - "variant": "Dilithium3-AES", + "variant": "Falcon-1024", "primitive": "signature", "implementationLevel": "softwarePlainRam", "cryptoFunctions": [ @@ -1416,17 +1296,17 @@ ], "implementationPlatform": "generic" }, - "nistQuantumSecurityLevel": 3 + "nistQuantumSecurityLevel": 5 } }, { "type": "crypto-asset", - "bom-ref": "alg:Dilithium3-AES:x86_64", - "name": "CRYSTALS-Dilithium", + "bom-ref": "alg:Falcon-1024:x86_64", + "name": "Falcon", "cryptoProperties": { "assetType": "algorithm", "algorithmProperties": { - "variant": "Dilithium3-AES", + "variant": "Falcon-1024", "primitive": "signature", "implementationLevel": "softwarePlainRam", "cryptoFunctions": [ @@ -1436,17 +1316,17 @@ ], "implementationPlatform": "x86_64" }, - "nistQuantumSecurityLevel": 3 + "nistQuantumSecurityLevel": 5 } }, { "type": "crypto-asset", - "bom-ref": "alg:Dilithium5-AES:generic", - "name": "CRYSTALS-Dilithium", + "bom-ref": "alg:SPHINCS+-SHA256-128f-simple:generic", + "name": "SPHINCS+", "cryptoProperties": { "assetType": "algorithm", "algorithmProperties": { - "variant": "Dilithium5-AES", + "variant": "SPHINCS+-SHA256-128f-simple", "primitive": "signature", "implementationLevel": "softwarePlainRam", "cryptoFunctions": [ @@ -1456,17 +1336,17 @@ ], "implementationPlatform": "generic" }, - "nistQuantumSecurityLevel": 5 + "nistQuantumSecurityLevel": 1 } }, { "type": "crypto-asset", - "bom-ref": "alg:Dilithium5-AES:x86_64", - "name": "CRYSTALS-Dilithium", + "bom-ref": "alg:SPHINCS+-SHA256-128f-simple:x86_64", + "name": "SPHINCS+", "cryptoProperties": { "assetType": "algorithm", "algorithmProperties": { - "variant": "Dilithium5-AES", + "variant": "SPHINCS+-SHA256-128f-simple", "primitive": "signature", "implementationLevel": "softwarePlainRam", "cryptoFunctions": [ @@ -1476,17 +1356,17 @@ ], "implementationPlatform": "x86_64" }, - "nistQuantumSecurityLevel": 5 + "nistQuantumSecurityLevel": 1 } }, { "type": "crypto-asset", - "bom-ref": "alg:Falcon-512:generic", - "name": "Falcon", + "bom-ref": "alg:SPHINCS+-SHA256-128s-simple:generic", + "name": "SPHINCS+", "cryptoProperties": { "assetType": "algorithm", "algorithmProperties": { - "variant": "Falcon-512", + "variant": "SPHINCS+-SHA256-128s-simple", "primitive": "signature", "implementationLevel": "softwarePlainRam", "cryptoFunctions": [ @@ -1501,12 +1381,12 @@ }, { "type": "crypto-asset", - "bom-ref": "alg:Falcon-512:x86_64", - "name": "Falcon", + "bom-ref": "alg:SPHINCS+-SHA256-128s-simple:x86_64", + "name": "SPHINCS+", "cryptoProperties": { "assetType": "algorithm", "algorithmProperties": { - "variant": "Falcon-512", + "variant": "SPHINCS+-SHA256-128s-simple", "primitive": "signature", "implementationLevel": "softwarePlainRam", "cryptoFunctions": [ @@ -1521,12 +1401,12 @@ }, { "type": "crypto-asset", - "bom-ref": "alg:Falcon-1024:generic", - "name": "Falcon", + "bom-ref": "alg:SPHINCS+-SHA256-192f-simple:generic", + "name": "SPHINCS+", "cryptoProperties": { "assetType": "algorithm", "algorithmProperties": { - "variant": "Falcon-1024", + "variant": "SPHINCS+-SHA256-192f-simple", "primitive": "signature", "implementationLevel": "softwarePlainRam", "cryptoFunctions": [ @@ -1536,17 +1416,17 @@ ], "implementationPlatform": "generic" }, - "nistQuantumSecurityLevel": 5 + "nistQuantumSecurityLevel": 3 } }, { "type": "crypto-asset", - "bom-ref": "alg:Falcon-1024:x86_64", - "name": "Falcon", + "bom-ref": "alg:SPHINCS+-SHA256-192f-simple:x86_64", + "name": "SPHINCS+", "cryptoProperties": { "assetType": "algorithm", "algorithmProperties": { - "variant": "Falcon-1024", + "variant": "SPHINCS+-SHA256-192f-simple", "primitive": "signature", "implementationLevel": "softwarePlainRam", "cryptoFunctions": [ @@ -1556,17 +1436,17 @@ ], "implementationPlatform": "x86_64" }, - "nistQuantumSecurityLevel": 5 + "nistQuantumSecurityLevel": 3 } }, { "type": "crypto-asset", - "bom-ref": "alg:SPHINCS+-Haraka-128f-robust:generic", + "bom-ref": "alg:SPHINCS+-SHA256-192s-simple:generic", "name": "SPHINCS+", "cryptoProperties": { "assetType": "algorithm", "algorithmProperties": { - "variant": "SPHINCS+-Haraka-128f-robust", + "variant": "SPHINCS+-SHA256-192s-simple", "primitive": "signature", "implementationLevel": "softwarePlainRam", "cryptoFunctions": [ @@ -1576,17 +1456,17 @@ ], "implementationPlatform": "generic" }, - "nistQuantumSecurityLevel": 1 + "nistQuantumSecurityLevel": 3 } }, { "type": "crypto-asset", - "bom-ref": "alg:SPHINCS+-Haraka-128f-robust:x86_64", + "bom-ref": "alg:SPHINCS+-SHA256-192s-simple:x86_64", "name": "SPHINCS+", "cryptoProperties": { "assetType": "algorithm", "algorithmProperties": { - "variant": "SPHINCS+-Haraka-128f-robust", + "variant": "SPHINCS+-SHA256-192s-simple", "primitive": "signature", "implementationLevel": "softwarePlainRam", "cryptoFunctions": [ @@ -1596,17 +1476,17 @@ ], "implementationPlatform": "x86_64" }, - "nistQuantumSecurityLevel": 1 + "nistQuantumSecurityLevel": 3 } }, { "type": "crypto-asset", - "bom-ref": "alg:SPHINCS+-Haraka-128f-simple:generic", + "bom-ref": "alg:SPHINCS+-SHA256-256f-simple:generic", "name": "SPHINCS+", "cryptoProperties": { "assetType": "algorithm", "algorithmProperties": { - "variant": "SPHINCS+-Haraka-128f-simple", + "variant": "SPHINCS+-SHA256-256f-simple", "primitive": "signature", "implementationLevel": "softwarePlainRam", "cryptoFunctions": [ @@ -1616,17 +1496,17 @@ ], "implementationPlatform": "generic" }, - "nistQuantumSecurityLevel": 1 + "nistQuantumSecurityLevel": 5 } }, { "type": "crypto-asset", - "bom-ref": "alg:SPHINCS+-Haraka-128f-simple:x86_64", + "bom-ref": "alg:SPHINCS+-SHA256-256f-simple:x86_64", "name": "SPHINCS+", "cryptoProperties": { "assetType": "algorithm", "algorithmProperties": { - "variant": "SPHINCS+-Haraka-128f-simple", + "variant": "SPHINCS+-SHA256-256f-simple", "primitive": "signature", "implementationLevel": "softwarePlainRam", "cryptoFunctions": [ @@ -1636,17 +1516,17 @@ ], "implementationPlatform": "x86_64" }, - "nistQuantumSecurityLevel": 1 + "nistQuantumSecurityLevel": 5 } }, { "type": "crypto-asset", - "bom-ref": "alg:SPHINCS+-Haraka-128s-robust:generic", + "bom-ref": "alg:SPHINCS+-SHA256-256s-simple:generic", "name": "SPHINCS+", "cryptoProperties": { "assetType": "algorithm", "algorithmProperties": { - "variant": "SPHINCS+-Haraka-128s-robust", + "variant": "SPHINCS+-SHA256-256s-simple", "primitive": "signature", "implementationLevel": "softwarePlainRam", "cryptoFunctions": [ @@ -1656,17 +1536,17 @@ ], "implementationPlatform": "generic" }, - "nistQuantumSecurityLevel": 1 + "nistQuantumSecurityLevel": 5 } }, { "type": "crypto-asset", - "bom-ref": "alg:SPHINCS+-Haraka-128s-robust:x86_64", + "bom-ref": "alg:SPHINCS+-SHA256-256s-simple:x86_64", "name": "SPHINCS+", "cryptoProperties": { "assetType": "algorithm", "algorithmProperties": { - "variant": "SPHINCS+-Haraka-128s-robust", + "variant": "SPHINCS+-SHA256-256s-simple", "primitive": "signature", "implementationLevel": "softwarePlainRam", "cryptoFunctions": [ @@ -1676,17 +1556,17 @@ ], "implementationPlatform": "x86_64" }, - "nistQuantumSecurityLevel": 1 + "nistQuantumSecurityLevel": 5 } }, { "type": "crypto-asset", - "bom-ref": "alg:SPHINCS+-Haraka-128s-simple:generic", + "bom-ref": "alg:SPHINCS+-SHAKE256-128f-simple:generic", "name": "SPHINCS+", "cryptoProperties": { "assetType": "algorithm", "algorithmProperties": { - "variant": "SPHINCS+-Haraka-128s-simple", + "variant": "SPHINCS+-SHAKE256-128f-simple", "primitive": "signature", "implementationLevel": "softwarePlainRam", "cryptoFunctions": [ @@ -1701,12 +1581,12 @@ }, { "type": "crypto-asset", - "bom-ref": "alg:SPHINCS+-Haraka-128s-simple:x86_64", + "bom-ref": "alg:SPHINCS+-SHAKE256-128f-simple:x86_64", "name": "SPHINCS+", "cryptoProperties": { "assetType": "algorithm", "algorithmProperties": { - "variant": "SPHINCS+-Haraka-128s-simple", + "variant": "SPHINCS+-SHAKE256-128f-simple", "primitive": "signature", "implementationLevel": "softwarePlainRam", "cryptoFunctions": [ @@ -1721,12 +1601,12 @@ }, { "type": "crypto-asset", - "bom-ref": "alg:SPHINCS+-Haraka-192f-robust:generic", + "bom-ref": "alg:SPHINCS+-SHAKE256-128s-simple:generic", "name": "SPHINCS+", "cryptoProperties": { "assetType": "algorithm", "algorithmProperties": { - "variant": "SPHINCS+-Haraka-192f-robust", + "variant": "SPHINCS+-SHAKE256-128s-simple", "primitive": "signature", "implementationLevel": "softwarePlainRam", "cryptoFunctions": [ @@ -1736,17 +1616,17 @@ ], "implementationPlatform": "generic" }, - "nistQuantumSecurityLevel": 2 + "nistQuantumSecurityLevel": 1 } }, { "type": "crypto-asset", - "bom-ref": "alg:SPHINCS+-Haraka-192f-robust:x86_64", + "bom-ref": "alg:SPHINCS+-SHAKE256-128s-simple:x86_64", "name": "SPHINCS+", "cryptoProperties": { "assetType": "algorithm", "algorithmProperties": { - "variant": "SPHINCS+-Haraka-192f-robust", + "variant": "SPHINCS+-SHAKE256-128s-simple", "primitive": "signature", "implementationLevel": "softwarePlainRam", "cryptoFunctions": [ @@ -1756,17 +1636,17 @@ ], "implementationPlatform": "x86_64" }, - "nistQuantumSecurityLevel": 2 + "nistQuantumSecurityLevel": 1 } }, { "type": "crypto-asset", - "bom-ref": "alg:SPHINCS+-Haraka-192f-simple:generic", + "bom-ref": "alg:SPHINCS+-SHAKE256-192f-simple:generic", "name": "SPHINCS+", "cryptoProperties": { "assetType": "algorithm", "algorithmProperties": { - "variant": "SPHINCS+-Haraka-192f-simple", + "variant": "SPHINCS+-SHAKE256-192f-simple", "primitive": "signature", "implementationLevel": "softwarePlainRam", "cryptoFunctions": [ @@ -1776,17 +1656,17 @@ ], "implementationPlatform": "generic" }, - "nistQuantumSecurityLevel": 2 + "nistQuantumSecurityLevel": 3 } }, { "type": "crypto-asset", - "bom-ref": "alg:SPHINCS+-Haraka-192f-simple:x86_64", + "bom-ref": "alg:SPHINCS+-SHAKE256-192f-simple:x86_64", "name": "SPHINCS+", "cryptoProperties": { "assetType": "algorithm", "algorithmProperties": { - "variant": "SPHINCS+-Haraka-192f-simple", + "variant": "SPHINCS+-SHAKE256-192f-simple", "primitive": "signature", "implementationLevel": "softwarePlainRam", "cryptoFunctions": [ @@ -1796,17 +1676,17 @@ ], "implementationPlatform": "x86_64" }, - "nistQuantumSecurityLevel": 2 + "nistQuantumSecurityLevel": 3 } }, { "type": "crypto-asset", - "bom-ref": "alg:SPHINCS+-Haraka-192s-robust:generic", + "bom-ref": "alg:SPHINCS+-SHAKE256-192s-simple:generic", "name": "SPHINCS+", "cryptoProperties": { "assetType": "algorithm", "algorithmProperties": { - "variant": "SPHINCS+-Haraka-192s-robust", + "variant": "SPHINCS+-SHAKE256-192s-simple", "primitive": "signature", "implementationLevel": "softwarePlainRam", "cryptoFunctions": [ @@ -1816,17 +1696,17 @@ ], "implementationPlatform": "generic" }, - "nistQuantumSecurityLevel": 2 + "nistQuantumSecurityLevel": 3 } }, { "type": "crypto-asset", - "bom-ref": "alg:SPHINCS+-Haraka-192s-robust:x86_64", + "bom-ref": "alg:SPHINCS+-SHAKE256-192s-simple:x86_64", "name": "SPHINCS+", "cryptoProperties": { "assetType": "algorithm", "algorithmProperties": { - "variant": "SPHINCS+-Haraka-192s-robust", + "variant": "SPHINCS+-SHAKE256-192s-simple", "primitive": "signature", "implementationLevel": "softwarePlainRam", "cryptoFunctions": [ @@ -1836,17 +1716,17 @@ ], "implementationPlatform": "x86_64" }, - "nistQuantumSecurityLevel": 2 + "nistQuantumSecurityLevel": 3 } }, { "type": "crypto-asset", - "bom-ref": "alg:SPHINCS+-Haraka-192s-simple:generic", + "bom-ref": "alg:SPHINCS+-SHAKE256-256f-simple:generic", "name": "SPHINCS+", "cryptoProperties": { "assetType": "algorithm", "algorithmProperties": { - "variant": "SPHINCS+-Haraka-192s-simple", + "variant": "SPHINCS+-SHAKE256-256f-simple", "primitive": "signature", "implementationLevel": "softwarePlainRam", "cryptoFunctions": [ @@ -1856,17 +1736,17 @@ ], "implementationPlatform": "generic" }, - "nistQuantumSecurityLevel": 2 + "nistQuantumSecurityLevel": 5 } }, { "type": "crypto-asset", - "bom-ref": "alg:SPHINCS+-Haraka-192s-simple:x86_64", + "bom-ref": "alg:SPHINCS+-SHAKE256-256f-simple:x86_64", "name": "SPHINCS+", "cryptoProperties": { "assetType": "algorithm", "algorithmProperties": { - "variant": "SPHINCS+-Haraka-192s-simple", + "variant": "SPHINCS+-SHAKE256-256f-simple", "primitive": "signature", "implementationLevel": "softwarePlainRam", "cryptoFunctions": [ @@ -1876,17 +1756,17 @@ ], "implementationPlatform": "x86_64" }, - "nistQuantumSecurityLevel": 2 + "nistQuantumSecurityLevel": 5 } }, { "type": "crypto-asset", - "bom-ref": "alg:SPHINCS+-Haraka-256f-robust:generic", + "bom-ref": "alg:SPHINCS+-SHAKE256-256s-simple:generic", "name": "SPHINCS+", "cryptoProperties": { "assetType": "algorithm", "algorithmProperties": { - "variant": "SPHINCS+-Haraka-256f-robust", + "variant": "SPHINCS+-SHAKE256-256s-simple", "primitive": "signature", "implementationLevel": "softwarePlainRam", "cryptoFunctions": [ @@ -1896,17 +1776,17 @@ ], "implementationPlatform": "generic" }, - "nistQuantumSecurityLevel": 2 + "nistQuantumSecurityLevel": 5 } }, { "type": "crypto-asset", - "bom-ref": "alg:SPHINCS+-Haraka-256f-robust:x86_64", + "bom-ref": "alg:SPHINCS+-SHAKE256-256s-simple:x86_64", "name": "SPHINCS+", "cryptoProperties": { "assetType": "algorithm", "algorithmProperties": { - "variant": "SPHINCS+-Haraka-256f-robust", + "variant": "SPHINCS+-SHAKE256-256s-simple", "primitive": "signature", "implementationLevel": "softwarePlainRam", "cryptoFunctions": [ @@ -1916,2160 +1796,684 @@ ], "implementationPlatform": "x86_64" }, - "nistQuantumSecurityLevel": 2 + "nistQuantumSecurityLevel": 5 } }, { "type": "crypto-asset", - "bom-ref": "alg:SPHINCS+-Haraka-256f-simple:generic", - "name": "SPHINCS+", + "bom-ref": "alg:aes", + "name": "aes", "cryptoProperties": { "assetType": "algorithm", "algorithmProperties": { - "variant": "SPHINCS+-Haraka-256f-simple", - "primitive": "signature", - "implementationLevel": "softwarePlainRam", - "cryptoFunctions": [ - "keygen", - "sign", - "verify" - ], - "implementationPlatform": "generic" - }, - "nistQuantumSecurityLevel": 2 - } - }, - { - "type": "crypto-asset", - "bom-ref": "alg:SPHINCS+-Haraka-256f-simple:x86_64", - "name": "SPHINCS+", - "cryptoProperties": { - "assetType": "algorithm", - "algorithmProperties": { - "variant": "SPHINCS+-Haraka-256f-simple", - "primitive": "signature", - "implementationLevel": "softwarePlainRam", - "cryptoFunctions": [ - "keygen", - "sign", - "verify" - ], - "implementationPlatform": "x86_64" - }, - "nistQuantumSecurityLevel": 2 - } - }, - { - "type": "crypto-asset", - "bom-ref": "alg:SPHINCS+-Haraka-256s-robust:generic", - "name": "SPHINCS+", - "cryptoProperties": { - "assetType": "algorithm", - "algorithmProperties": { - "variant": "SPHINCS+-Haraka-256s-robust", - "primitive": "signature", - "implementationLevel": "softwarePlainRam", - "cryptoFunctions": [ - "keygen", - "sign", - "verify" - ], - "implementationPlatform": "generic" - }, - "nistQuantumSecurityLevel": 2 - } - }, - { - "type": "crypto-asset", - "bom-ref": "alg:SPHINCS+-Haraka-256s-robust:x86_64", - "name": "SPHINCS+", - "cryptoProperties": { - "assetType": "algorithm", - "algorithmProperties": { - "variant": "SPHINCS+-Haraka-256s-robust", - "primitive": "signature", - "implementationLevel": "softwarePlainRam", - "cryptoFunctions": [ - "keygen", - "sign", - "verify" - ], - "implementationPlatform": "x86_64" - }, - "nistQuantumSecurityLevel": 2 - } - }, - { - "type": "crypto-asset", - "bom-ref": "alg:SPHINCS+-Haraka-256s-simple:generic", - "name": "SPHINCS+", - "cryptoProperties": { - "assetType": "algorithm", - "algorithmProperties": { - "variant": "SPHINCS+-Haraka-256s-simple", - "primitive": "signature", - "implementationLevel": "softwarePlainRam", - "cryptoFunctions": [ - "keygen", - "sign", - "verify" - ], - "implementationPlatform": "generic" - }, - "nistQuantumSecurityLevel": 2 - } - }, - { - "type": "crypto-asset", - "bom-ref": "alg:SPHINCS+-Haraka-256s-simple:x86_64", - "name": "SPHINCS+", - "cryptoProperties": { - "assetType": "algorithm", - "algorithmProperties": { - "variant": "SPHINCS+-Haraka-256s-simple", - "primitive": "signature", - "implementationLevel": "softwarePlainRam", - "cryptoFunctions": [ - "keygen", - "sign", - "verify" - ], - "implementationPlatform": "x86_64" - }, - "nistQuantumSecurityLevel": 2 - } - }, - { - "type": "crypto-asset", - "bom-ref": "alg:SPHINCS+-SHA256-128f-robust:generic", - "name": "SPHINCS+", - "cryptoProperties": { - "assetType": "algorithm", - "algorithmProperties": { - "variant": "SPHINCS+-SHA256-128f-robust", - "primitive": "signature", - "implementationLevel": "softwarePlainRam", - "cryptoFunctions": [ - "keygen", - "sign", - "verify" - ], - "implementationPlatform": "generic" - }, - "nistQuantumSecurityLevel": 1 - } - }, - { - "type": "crypto-asset", - "bom-ref": "alg:SPHINCS+-SHA256-128f-robust:x86_64", - "name": "SPHINCS+", - "cryptoProperties": { - "assetType": "algorithm", - "algorithmProperties": { - "variant": "SPHINCS+-SHA256-128f-robust", - "primitive": "signature", - "implementationLevel": "softwarePlainRam", - "cryptoFunctions": [ - "keygen", - "sign", - "verify" - ], - "implementationPlatform": "x86_64" - }, - "nistQuantumSecurityLevel": 1 - } - }, - { - "type": "crypto-asset", - "bom-ref": "alg:SPHINCS+-SHA256-128f-simple:generic", - "name": "SPHINCS+", - "cryptoProperties": { - "assetType": "algorithm", - "algorithmProperties": { - "variant": "SPHINCS+-SHA256-128f-simple", - "primitive": "signature", - "implementationLevel": "softwarePlainRam", - "cryptoFunctions": [ - "keygen", - "sign", - "verify" - ], - "implementationPlatform": "generic" - }, - "nistQuantumSecurityLevel": 1 - } - }, - { - "type": "crypto-asset", - "bom-ref": "alg:SPHINCS+-SHA256-128f-simple:x86_64", - "name": "SPHINCS+", - "cryptoProperties": { - "assetType": "algorithm", - "algorithmProperties": { - "variant": "SPHINCS+-SHA256-128f-simple", - "primitive": "signature", - "implementationLevel": "softwarePlainRam", - "cryptoFunctions": [ - "keygen", - "sign", - "verify" - ], - "implementationPlatform": "x86_64" - }, - "nistQuantumSecurityLevel": 1 - } - }, - { - "type": "crypto-asset", - "bom-ref": "alg:SPHINCS+-SHA256-128s-robust:generic", - "name": "SPHINCS+", - "cryptoProperties": { - "assetType": "algorithm", - "algorithmProperties": { - "variant": "SPHINCS+-SHA256-128s-robust", - "primitive": "signature", - "implementationLevel": "softwarePlainRam", - "cryptoFunctions": [ - "keygen", - "sign", - "verify" - ], - "implementationPlatform": "generic" - }, - "nistQuantumSecurityLevel": 1 - } - }, - { - "type": "crypto-asset", - "bom-ref": "alg:SPHINCS+-SHA256-128s-robust:x86_64", - "name": "SPHINCS+", - "cryptoProperties": { - "assetType": "algorithm", - "algorithmProperties": { - "variant": "SPHINCS+-SHA256-128s-robust", - "primitive": "signature", - "implementationLevel": "softwarePlainRam", - "cryptoFunctions": [ - "keygen", - "sign", - "verify" - ], - "implementationPlatform": "x86_64" - }, - "nistQuantumSecurityLevel": 1 - } - }, - { - "type": "crypto-asset", - "bom-ref": "alg:SPHINCS+-SHA256-128s-simple:generic", - "name": "SPHINCS+", - "cryptoProperties": { - "assetType": "algorithm", - "algorithmProperties": { - "variant": "SPHINCS+-SHA256-128s-simple", - "primitive": "signature", - "implementationLevel": "softwarePlainRam", - "cryptoFunctions": [ - "keygen", - "sign", - "verify" - ], - "implementationPlatform": "generic" - }, - "nistQuantumSecurityLevel": 1 + "variant": "aes", + "primitive": "blockcipher", + "implementationLevel": "softwarePlainRam" + } } }, { "type": "crypto-asset", - "bom-ref": "alg:SPHINCS+-SHA256-128s-simple:x86_64", - "name": "SPHINCS+", + "bom-ref": "alg:sha3", + "name": "sha3", "cryptoProperties": { "assetType": "algorithm", "algorithmProperties": { - "variant": "SPHINCS+-SHA256-128s-simple", - "primitive": "signature", - "implementationLevel": "softwarePlainRam", - "cryptoFunctions": [ - "keygen", - "sign", - "verify" - ], - "implementationPlatform": "x86_64" - }, - "nistQuantumSecurityLevel": 1 + "variant": "sha3", + "primitive": "hash", + "implementationLevel": "softwarePlainRam" + } } - }, + } + ], + "dependencies": [ { - "type": "crypto-asset", - "bom-ref": "alg:SPHINCS+-SHA256-192f-robust:generic", - "name": "SPHINCS+", - "cryptoProperties": { - "assetType": "algorithm", - "algorithmProperties": { - "variant": "SPHINCS+-SHA256-192f-robust", - "primitive": "signature", - "implementationLevel": "softwarePlainRam", - "cryptoFunctions": [ - "keygen", - "sign", - "verify" - ], - "implementationPlatform": "generic" - }, - "nistQuantumSecurityLevel": 3 - } - }, - { - "type": "crypto-asset", - "bom-ref": "alg:SPHINCS+-SHA256-192f-robust:x86_64", - "name": "SPHINCS+", - "cryptoProperties": { - "assetType": "algorithm", - "algorithmProperties": { - "variant": "SPHINCS+-SHA256-192f-robust", - "primitive": "signature", - "implementationLevel": "softwarePlainRam", - "cryptoFunctions": [ - "keygen", - "sign", - "verify" - ], - "implementationPlatform": "x86_64" - }, - "nistQuantumSecurityLevel": 3 - } - }, - { - "type": "crypto-asset", - "bom-ref": "alg:SPHINCS+-SHA256-192f-simple:generic", - "name": "SPHINCS+", - "cryptoProperties": { - "assetType": "algorithm", - "algorithmProperties": { - "variant": "SPHINCS+-SHA256-192f-simple", - "primitive": "signature", - "implementationLevel": "softwarePlainRam", - "cryptoFunctions": [ - "keygen", - "sign", - "verify" - ], - "implementationPlatform": "generic" - }, - "nistQuantumSecurityLevel": 3 - } - }, - { - "type": "crypto-asset", - "bom-ref": "alg:SPHINCS+-SHA256-192f-simple:x86_64", - "name": "SPHINCS+", - "cryptoProperties": { - "assetType": "algorithm", - "algorithmProperties": { - "variant": "SPHINCS+-SHA256-192f-simple", - "primitive": "signature", - "implementationLevel": "softwarePlainRam", - "cryptoFunctions": [ - "keygen", - "sign", - "verify" - ], - "implementationPlatform": "x86_64" - }, - "nistQuantumSecurityLevel": 3 - } - }, - { - "type": "crypto-asset", - "bom-ref": "alg:SPHINCS+-SHA256-192s-robust:generic", - "name": "SPHINCS+", - "cryptoProperties": { - "assetType": "algorithm", - "algorithmProperties": { - "variant": "SPHINCS+-SHA256-192s-robust", - "primitive": "signature", - "implementationLevel": "softwarePlainRam", - "cryptoFunctions": [ - "keygen", - "sign", - "verify" - ], - "implementationPlatform": "generic" - }, - "nistQuantumSecurityLevel": 3 - } - }, - { - "type": "crypto-asset", - "bom-ref": "alg:SPHINCS+-SHA256-192s-robust:x86_64", - "name": "SPHINCS+", - "cryptoProperties": { - "assetType": "algorithm", - "algorithmProperties": { - "variant": "SPHINCS+-SHA256-192s-robust", - "primitive": "signature", - "implementationLevel": "softwarePlainRam", - "cryptoFunctions": [ - "keygen", - "sign", - "verify" - ], - "implementationPlatform": "x86_64" - }, - "nistQuantumSecurityLevel": 3 - } - }, - { - "type": "crypto-asset", - "bom-ref": "alg:SPHINCS+-SHA256-192s-simple:generic", - "name": "SPHINCS+", - "cryptoProperties": { - "assetType": "algorithm", - "algorithmProperties": { - "variant": "SPHINCS+-SHA256-192s-simple", - "primitive": "signature", - "implementationLevel": "softwarePlainRam", - "cryptoFunctions": [ - "keygen", - "sign", - "verify" - ], - "implementationPlatform": "generic" - }, - "nistQuantumSecurityLevel": 3 - } - }, - { - "type": "crypto-asset", - "bom-ref": "alg:SPHINCS+-SHA256-192s-simple:x86_64", - "name": "SPHINCS+", - "cryptoProperties": { - "assetType": "algorithm", - "algorithmProperties": { - "variant": "SPHINCS+-SHA256-192s-simple", - "primitive": "signature", - "implementationLevel": "softwarePlainRam", - "cryptoFunctions": [ - "keygen", - "sign", - "verify" - ], - "implementationPlatform": "x86_64" - }, - "nistQuantumSecurityLevel": 3 - } - }, - { - "type": "crypto-asset", - "bom-ref": "alg:SPHINCS+-SHA256-256f-robust:generic", - "name": "SPHINCS+", - "cryptoProperties": { - "assetType": "algorithm", - "algorithmProperties": { - "variant": "SPHINCS+-SHA256-256f-robust", - "primitive": "signature", - "implementationLevel": "softwarePlainRam", - "cryptoFunctions": [ - "keygen", - "sign", - "verify" - ], - "implementationPlatform": "generic" - }, - "nistQuantumSecurityLevel": 5 - } - }, - { - "type": "crypto-asset", - "bom-ref": "alg:SPHINCS+-SHA256-256f-robust:x86_64", - "name": "SPHINCS+", - "cryptoProperties": { - "assetType": "algorithm", - "algorithmProperties": { - "variant": "SPHINCS+-SHA256-256f-robust", - "primitive": "signature", - "implementationLevel": "softwarePlainRam", - "cryptoFunctions": [ - "keygen", - "sign", - "verify" - ], - "implementationPlatform": "x86_64" - }, - "nistQuantumSecurityLevel": 5 - } - }, - { - "type": "crypto-asset", - "bom-ref": "alg:SPHINCS+-SHA256-256f-simple:generic", - "name": "SPHINCS+", - "cryptoProperties": { - "assetType": "algorithm", - "algorithmProperties": { - "variant": "SPHINCS+-SHA256-256f-simple", - "primitive": "signature", - "implementationLevel": "softwarePlainRam", - "cryptoFunctions": [ - "keygen", - "sign", - "verify" - ], - "implementationPlatform": "generic" - }, - "nistQuantumSecurityLevel": 5 - } - }, - { - "type": "crypto-asset", - "bom-ref": "alg:SPHINCS+-SHA256-256f-simple:x86_64", - "name": "SPHINCS+", - "cryptoProperties": { - "assetType": "algorithm", - "algorithmProperties": { - "variant": "SPHINCS+-SHA256-256f-simple", - "primitive": "signature", - "implementationLevel": "softwarePlainRam", - "cryptoFunctions": [ - "keygen", - "sign", - "verify" - ], - "implementationPlatform": "x86_64" - }, - "nistQuantumSecurityLevel": 5 - } - }, - { - "type": "crypto-asset", - "bom-ref": "alg:SPHINCS+-SHA256-256s-robust:generic", - "name": "SPHINCS+", - "cryptoProperties": { - "assetType": "algorithm", - "algorithmProperties": { - "variant": "SPHINCS+-SHA256-256s-robust", - "primitive": "signature", - "implementationLevel": "softwarePlainRam", - "cryptoFunctions": [ - "keygen", - "sign", - "verify" - ], - "implementationPlatform": "generic" - }, - "nistQuantumSecurityLevel": 5 - } - }, - { - "type": "crypto-asset", - "bom-ref": "alg:SPHINCS+-SHA256-256s-robust:x86_64", - "name": "SPHINCS+", - "cryptoProperties": { - "assetType": "algorithm", - "algorithmProperties": { - "variant": "SPHINCS+-SHA256-256s-robust", - "primitive": "signature", - "implementationLevel": "softwarePlainRam", - "cryptoFunctions": [ - "keygen", - "sign", - "verify" - ], - "implementationPlatform": "x86_64" - }, - "nistQuantumSecurityLevel": 5 - } - }, - { - "type": "crypto-asset", - "bom-ref": "alg:SPHINCS+-SHA256-256s-simple:generic", - "name": "SPHINCS+", - "cryptoProperties": { - "assetType": "algorithm", - "algorithmProperties": { - "variant": "SPHINCS+-SHA256-256s-simple", - "primitive": "signature", - "implementationLevel": "softwarePlainRam", - "cryptoFunctions": [ - "keygen", - "sign", - "verify" - ], - "implementationPlatform": "generic" - }, - "nistQuantumSecurityLevel": 5 - } - }, - { - "type": "crypto-asset", - "bom-ref": "alg:SPHINCS+-SHA256-256s-simple:x86_64", - "name": "SPHINCS+", - "cryptoProperties": { - "assetType": "algorithm", - "algorithmProperties": { - "variant": "SPHINCS+-SHA256-256s-simple", - "primitive": "signature", - "implementationLevel": "softwarePlainRam", - "cryptoFunctions": [ - "keygen", - "sign", - "verify" - ], - "implementationPlatform": "x86_64" - }, - "nistQuantumSecurityLevel": 5 - } - }, - { - "type": "crypto-asset", - "bom-ref": "alg:SPHINCS+-SHAKE256-128f-robust:generic", - "name": "SPHINCS+", - "cryptoProperties": { - "assetType": "algorithm", - "algorithmProperties": { - "variant": "SPHINCS+-SHAKE256-128f-robust", - "primitive": "signature", - "implementationLevel": "softwarePlainRam", - "cryptoFunctions": [ - "keygen", - "sign", - "verify" - ], - "implementationPlatform": "generic" - }, - "nistQuantumSecurityLevel": 1 - } - }, - { - "type": "crypto-asset", - "bom-ref": "alg:SPHINCS+-SHAKE256-128f-robust:x86_64", - "name": "SPHINCS+", - "cryptoProperties": { - "assetType": "algorithm", - "algorithmProperties": { - "variant": "SPHINCS+-SHAKE256-128f-robust", - "primitive": "signature", - "implementationLevel": "softwarePlainRam", - "cryptoFunctions": [ - "keygen", - "sign", - "verify" - ], - "implementationPlatform": "x86_64" - }, - "nistQuantumSecurityLevel": 1 - } - }, - { - "type": "crypto-asset", - "bom-ref": "alg:SPHINCS+-SHAKE256-128f-simple:generic", - "name": "SPHINCS+", - "cryptoProperties": { - "assetType": "algorithm", - "algorithmProperties": { - "variant": "SPHINCS+-SHAKE256-128f-simple", - "primitive": "signature", - "implementationLevel": "softwarePlainRam", - "cryptoFunctions": [ - "keygen", - "sign", - "verify" - ], - "implementationPlatform": "generic" - }, - "nistQuantumSecurityLevel": 1 - } - }, - { - "type": "crypto-asset", - "bom-ref": "alg:SPHINCS+-SHAKE256-128f-simple:x86_64", - "name": "SPHINCS+", - "cryptoProperties": { - "assetType": "algorithm", - "algorithmProperties": { - "variant": "SPHINCS+-SHAKE256-128f-simple", - "primitive": "signature", - "implementationLevel": "softwarePlainRam", - "cryptoFunctions": [ - "keygen", - "sign", - "verify" - ], - "implementationPlatform": "x86_64" - }, - "nistQuantumSecurityLevel": 1 - } - }, - { - "type": "crypto-asset", - "bom-ref": "alg:SPHINCS+-SHAKE256-128s-robust:generic", - "name": "SPHINCS+", - "cryptoProperties": { - "assetType": "algorithm", - "algorithmProperties": { - "variant": "SPHINCS+-SHAKE256-128s-robust", - "primitive": "signature", - "implementationLevel": "softwarePlainRam", - "cryptoFunctions": [ - "keygen", - "sign", - "verify" - ], - "implementationPlatform": "generic" - }, - "nistQuantumSecurityLevel": 1 - } - }, - { - "type": "crypto-asset", - "bom-ref": "alg:SPHINCS+-SHAKE256-128s-robust:x86_64", - "name": "SPHINCS+", - "cryptoProperties": { - "assetType": "algorithm", - "algorithmProperties": { - "variant": "SPHINCS+-SHAKE256-128s-robust", - "primitive": "signature", - "implementationLevel": "softwarePlainRam", - "cryptoFunctions": [ - "keygen", - "sign", - "verify" - ], - "implementationPlatform": "x86_64" - }, - "nistQuantumSecurityLevel": 1 - } - }, - { - "type": "crypto-asset", - "bom-ref": "alg:SPHINCS+-SHAKE256-128s-simple:generic", - "name": "SPHINCS+", - "cryptoProperties": { - "assetType": "algorithm", - "algorithmProperties": { - "variant": "SPHINCS+-SHAKE256-128s-simple", - "primitive": "signature", - "implementationLevel": "softwarePlainRam", - "cryptoFunctions": [ - "keygen", - "sign", - "verify" - ], - "implementationPlatform": "generic" - }, - "nistQuantumSecurityLevel": 1 - } - }, - { - "type": "crypto-asset", - "bom-ref": "alg:SPHINCS+-SHAKE256-128s-simple:x86_64", - "name": "SPHINCS+", - "cryptoProperties": { - "assetType": "algorithm", - "algorithmProperties": { - "variant": "SPHINCS+-SHAKE256-128s-simple", - "primitive": "signature", - "implementationLevel": "softwarePlainRam", - "cryptoFunctions": [ - "keygen", - "sign", - "verify" - ], - "implementationPlatform": "x86_64" - }, - "nistQuantumSecurityLevel": 1 - } - }, - { - "type": "crypto-asset", - "bom-ref": "alg:SPHINCS+-SHAKE256-192f-robust:generic", - "name": "SPHINCS+", - "cryptoProperties": { - "assetType": "algorithm", - "algorithmProperties": { - "variant": "SPHINCS+-SHAKE256-192f-robust", - "primitive": "signature", - "implementationLevel": "softwarePlainRam", - "cryptoFunctions": [ - "keygen", - "sign", - "verify" - ], - "implementationPlatform": "generic" - }, - "nistQuantumSecurityLevel": 3 - } - }, - { - "type": "crypto-asset", - "bom-ref": "alg:SPHINCS+-SHAKE256-192f-robust:x86_64", - "name": "SPHINCS+", - "cryptoProperties": { - "assetType": "algorithm", - "algorithmProperties": { - "variant": "SPHINCS+-SHAKE256-192f-robust", - "primitive": "signature", - "implementationLevel": "softwarePlainRam", - "cryptoFunctions": [ - "keygen", - "sign", - "verify" - ], - "implementationPlatform": "x86_64" - }, - "nistQuantumSecurityLevel": 3 - } - }, - { - "type": "crypto-asset", - "bom-ref": "alg:SPHINCS+-SHAKE256-192f-simple:generic", - "name": "SPHINCS+", - "cryptoProperties": { - "assetType": "algorithm", - "algorithmProperties": { - "variant": "SPHINCS+-SHAKE256-192f-simple", - "primitive": "signature", - "implementationLevel": "softwarePlainRam", - "cryptoFunctions": [ - "keygen", - "sign", - "verify" - ], - "implementationPlatform": "generic" - }, - "nistQuantumSecurityLevel": 3 - } - }, - { - "type": "crypto-asset", - "bom-ref": "alg:SPHINCS+-SHAKE256-192f-simple:x86_64", - "name": "SPHINCS+", - "cryptoProperties": { - "assetType": "algorithm", - "algorithmProperties": { - "variant": "SPHINCS+-SHAKE256-192f-simple", - "primitive": "signature", - "implementationLevel": "softwarePlainRam", - "cryptoFunctions": [ - "keygen", - "sign", - "verify" - ], - "implementationPlatform": "x86_64" - }, - "nistQuantumSecurityLevel": 3 - } - }, - { - "type": "crypto-asset", - "bom-ref": "alg:SPHINCS+-SHAKE256-192s-robust:generic", - "name": "SPHINCS+", - "cryptoProperties": { - "assetType": "algorithm", - "algorithmProperties": { - "variant": "SPHINCS+-SHAKE256-192s-robust", - "primitive": "signature", - "implementationLevel": "softwarePlainRam", - "cryptoFunctions": [ - "keygen", - "sign", - "verify" - ], - "implementationPlatform": "generic" - }, - "nistQuantumSecurityLevel": 3 - } - }, - { - "type": "crypto-asset", - "bom-ref": "alg:SPHINCS+-SHAKE256-192s-robust:x86_64", - "name": "SPHINCS+", - "cryptoProperties": { - "assetType": "algorithm", - "algorithmProperties": { - "variant": "SPHINCS+-SHAKE256-192s-robust", - "primitive": "signature", - "implementationLevel": "softwarePlainRam", - "cryptoFunctions": [ - "keygen", - "sign", - "verify" - ], - "implementationPlatform": "x86_64" - }, - "nistQuantumSecurityLevel": 3 - } - }, - { - "type": "crypto-asset", - "bom-ref": "alg:SPHINCS+-SHAKE256-192s-simple:generic", - "name": "SPHINCS+", - "cryptoProperties": { - "assetType": "algorithm", - "algorithmProperties": { - "variant": "SPHINCS+-SHAKE256-192s-simple", - "primitive": "signature", - "implementationLevel": "softwarePlainRam", - "cryptoFunctions": [ - "keygen", - "sign", - "verify" - ], - "implementationPlatform": "generic" - }, - "nistQuantumSecurityLevel": 3 - } - }, - { - "type": "crypto-asset", - "bom-ref": "alg:SPHINCS+-SHAKE256-192s-simple:x86_64", - "name": "SPHINCS+", - "cryptoProperties": { - "assetType": "algorithm", - "algorithmProperties": { - "variant": "SPHINCS+-SHAKE256-192s-simple", - "primitive": "signature", - "implementationLevel": "softwarePlainRam", - "cryptoFunctions": [ - "keygen", - "sign", - "verify" - ], - "implementationPlatform": "x86_64" - }, - "nistQuantumSecurityLevel": 3 - } - }, - { - "type": "crypto-asset", - "bom-ref": "alg:SPHINCS+-SHAKE256-256f-robust:generic", - "name": "SPHINCS+", - "cryptoProperties": { - "assetType": "algorithm", - "algorithmProperties": { - "variant": "SPHINCS+-SHAKE256-256f-robust", - "primitive": "signature", - "implementationLevel": "softwarePlainRam", - "cryptoFunctions": [ - "keygen", - "sign", - "verify" - ], - "implementationPlatform": "generic" - }, - "nistQuantumSecurityLevel": 5 - } - }, - { - "type": "crypto-asset", - "bom-ref": "alg:SPHINCS+-SHAKE256-256f-robust:x86_64", - "name": "SPHINCS+", - "cryptoProperties": { - "assetType": "algorithm", - "algorithmProperties": { - "variant": "SPHINCS+-SHAKE256-256f-robust", - "primitive": "signature", - "implementationLevel": "softwarePlainRam", - "cryptoFunctions": [ - "keygen", - "sign", - "verify" - ], - "implementationPlatform": "x86_64" - }, - "nistQuantumSecurityLevel": 5 - } - }, - { - "type": "crypto-asset", - "bom-ref": "alg:SPHINCS+-SHAKE256-256f-simple:generic", - "name": "SPHINCS+", - "cryptoProperties": { - "assetType": "algorithm", - "algorithmProperties": { - "variant": "SPHINCS+-SHAKE256-256f-simple", - "primitive": "signature", - "implementationLevel": "softwarePlainRam", - "cryptoFunctions": [ - "keygen", - "sign", - "verify" - ], - "implementationPlatform": "generic" - }, - "nistQuantumSecurityLevel": 5 - } - }, - { - "type": "crypto-asset", - "bom-ref": "alg:SPHINCS+-SHAKE256-256f-simple:x86_64", - "name": "SPHINCS+", - "cryptoProperties": { - "assetType": "algorithm", - "algorithmProperties": { - "variant": "SPHINCS+-SHAKE256-256f-simple", - "primitive": "signature", - "implementationLevel": "softwarePlainRam", - "cryptoFunctions": [ - "keygen", - "sign", - "verify" - ], - "implementationPlatform": "x86_64" - }, - "nistQuantumSecurityLevel": 5 - } - }, - { - "type": "crypto-asset", - "bom-ref": "alg:SPHINCS+-SHAKE256-256s-robust:generic", - "name": "SPHINCS+", - "cryptoProperties": { - "assetType": "algorithm", - "algorithmProperties": { - "variant": "SPHINCS+-SHAKE256-256s-robust", - "primitive": "signature", - "implementationLevel": "softwarePlainRam", - "cryptoFunctions": [ - "keygen", - "sign", - "verify" - ], - "implementationPlatform": "generic" - }, - "nistQuantumSecurityLevel": 5 - } - }, - { - "type": "crypto-asset", - "bom-ref": "alg:SPHINCS+-SHAKE256-256s-robust:x86_64", - "name": "SPHINCS+", - "cryptoProperties": { - "assetType": "algorithm", - "algorithmProperties": { - "variant": "SPHINCS+-SHAKE256-256s-robust", - "primitive": "signature", - "implementationLevel": "softwarePlainRam", - "cryptoFunctions": [ - "keygen", - "sign", - "verify" - ], - "implementationPlatform": "x86_64" - }, - "nistQuantumSecurityLevel": 5 - } - }, - { - "type": "crypto-asset", - "bom-ref": "alg:SPHINCS+-SHAKE256-256s-simple:generic", - "name": "SPHINCS+", - "cryptoProperties": { - "assetType": "algorithm", - "algorithmProperties": { - "variant": "SPHINCS+-SHAKE256-256s-simple", - "primitive": "signature", - "implementationLevel": "softwarePlainRam", - "cryptoFunctions": [ - "keygen", - "sign", - "verify" - ], - "implementationPlatform": "generic" - }, - "nistQuantumSecurityLevel": 5 - } - }, - { - "type": "crypto-asset", - "bom-ref": "alg:SPHINCS+-SHAKE256-256s-simple:x86_64", - "name": "SPHINCS+", - "cryptoProperties": { - "assetType": "algorithm", - "algorithmProperties": { - "variant": "SPHINCS+-SHAKE256-256s-simple", - "primitive": "signature", - "implementationLevel": "softwarePlainRam", - "cryptoFunctions": [ - "keygen", - "sign", - "verify" - ], - "implementationPlatform": "x86_64" - }, - "nistQuantumSecurityLevel": 5 - } - }, - { - "type": "crypto-asset", - "bom-ref": "alg:aes", - "name": "aes", - "cryptoProperties": { - "assetType": "algorithm", - "algorithmProperties": { - "variant": "aes", - "primitive": "blockcipher", - "implementationLevel": "softwarePlainRam" - } - } - }, - { - "type": "crypto-asset", - "bom-ref": "alg:sha3", - "name": "sha3", - "cryptoProperties": { - "assetType": "algorithm", - "algorithmProperties": { - "variant": "sha3", - "primitive": "hash", - "implementationLevel": "softwarePlainRam" - } - } - } - ], - "dependencies": [ - { - "ref": "pkg:github/open-quantum-safe/liboqs@d61d81c526da8bb62e363f5a75191689572151cb", - "dependsOn": [ - "alg:BIKE-L1:x86_64", - "alg:BIKE-L3:x86_64", - "alg:BIKE-L5:x86_64", - "alg:Classic-McEliece-348864:generic", - "alg:Classic-McEliece-348864:x86_64", - "alg:Classic-McEliece-348864f:generic", - "alg:Classic-McEliece-348864f:x86_64", - "alg:Classic-McEliece-460896:generic", - "alg:Classic-McEliece-460896:x86_64", - "alg:Classic-McEliece-460896f:generic", - "alg:Classic-McEliece-460896f:x86_64", - "alg:Classic-McEliece-6688128:generic", - "alg:Classic-McEliece-6688128:x86_64", - "alg:Classic-McEliece-6688128f:generic", - "alg:Classic-McEliece-6688128f:x86_64", - "alg:Classic-McEliece-6960119:generic", - "alg:Classic-McEliece-6960119:x86_64", - "alg:Classic-McEliece-6960119f:generic", - "alg:Classic-McEliece-6960119f:x86_64", - "alg:Classic-McEliece-8192128:generic", - "alg:Classic-McEliece-8192128:x86_64", - "alg:Classic-McEliece-8192128f:generic", - "alg:Classic-McEliece-8192128f:x86_64", - "alg:FrodoKEM-640-AES:generic", - "alg:FrodoKEM-640-AES:x86_64", - "alg:FrodoKEM-640-SHAKE:generic", - "alg:FrodoKEM-640-SHAKE:x86_64", - "alg:FrodoKEM-976-AES:generic", - "alg:FrodoKEM-976-AES:x86_64", - "alg:FrodoKEM-976-SHAKE:generic", - "alg:FrodoKEM-976-SHAKE:x86_64", - "alg:FrodoKEM-1344-AES:generic", - "alg:FrodoKEM-1344-AES:x86_64", - "alg:FrodoKEM-1344-SHAKE:generic", - "alg:FrodoKEM-1344-SHAKE:x86_64", - "alg:HQC-128:generic", - "alg:HQC-128:x86_64", - "alg:HQC-192:generic", - "alg:HQC-192:x86_64", - "alg:HQC-256:generic", - "alg:HQC-256:x86_64", - "alg:Kyber512:generic", - "alg:Kyber512:x86_64", - "alg:Kyber512:armv8-a", - "alg:Kyber512-90s:generic", - "alg:Kyber512-90s:x86_64", - "alg:Kyber768:generic", - "alg:Kyber768:x86_64", - "alg:Kyber768:armv8-a", - "alg:Kyber768-90s:generic", - "alg:Kyber768-90s:x86_64", - "alg:Kyber1024:generic", - "alg:Kyber1024:x86_64", - "alg:Kyber1024:armv8-a", - "alg:Kyber1024-90s:generic", - "alg:Kyber1024-90s:x86_64", - "alg:sntrup761:generic", - "alg:sntrup761:x86_64", - "alg:Dilithium2:generic", - "alg:Dilithium2:x86_64", - "alg:Dilithium2:armv8-a", - "alg:Dilithium3:generic", - "alg:Dilithium3:x86_64", - "alg:Dilithium3:armv8-a", - "alg:Dilithium5:generic", - "alg:Dilithium5:x86_64", - "alg:Dilithium5:armv8-a", - "alg:Dilithium2-AES:generic", - "alg:Dilithium2-AES:x86_64", - "alg:Dilithium3-AES:generic", - "alg:Dilithium3-AES:x86_64", - "alg:Dilithium5-AES:generic", - "alg:Dilithium5-AES:x86_64", - "alg:Falcon-512:generic", - "alg:Falcon-512:x86_64", - "alg:Falcon-1024:generic", - "alg:Falcon-1024:x86_64", - "alg:SPHINCS+-Haraka-128f-robust:generic", - "alg:SPHINCS+-Haraka-128f-robust:x86_64", - "alg:SPHINCS+-Haraka-128f-simple:generic", - "alg:SPHINCS+-Haraka-128f-simple:x86_64", - "alg:SPHINCS+-Haraka-128s-robust:generic", - "alg:SPHINCS+-Haraka-128s-robust:x86_64", - "alg:SPHINCS+-Haraka-128s-simple:generic", - "alg:SPHINCS+-Haraka-128s-simple:x86_64", - "alg:SPHINCS+-Haraka-192f-robust:generic", - "alg:SPHINCS+-Haraka-192f-robust:x86_64", - "alg:SPHINCS+-Haraka-192f-simple:generic", - "alg:SPHINCS+-Haraka-192f-simple:x86_64", - "alg:SPHINCS+-Haraka-192s-robust:generic", - "alg:SPHINCS+-Haraka-192s-robust:x86_64", - "alg:SPHINCS+-Haraka-192s-simple:generic", - "alg:SPHINCS+-Haraka-192s-simple:x86_64", - "alg:SPHINCS+-Haraka-256f-robust:generic", - "alg:SPHINCS+-Haraka-256f-robust:x86_64", - "alg:SPHINCS+-Haraka-256f-simple:generic", - "alg:SPHINCS+-Haraka-256f-simple:x86_64", - "alg:SPHINCS+-Haraka-256s-robust:generic", - "alg:SPHINCS+-Haraka-256s-robust:x86_64", - "alg:SPHINCS+-Haraka-256s-simple:generic", - "alg:SPHINCS+-Haraka-256s-simple:x86_64", - "alg:SPHINCS+-SHA256-128f-robust:generic", - "alg:SPHINCS+-SHA256-128f-robust:x86_64", - "alg:SPHINCS+-SHA256-128f-simple:generic", - "alg:SPHINCS+-SHA256-128f-simple:x86_64", - "alg:SPHINCS+-SHA256-128s-robust:generic", - "alg:SPHINCS+-SHA256-128s-robust:x86_64", - "alg:SPHINCS+-SHA256-128s-simple:generic", - "alg:SPHINCS+-SHA256-128s-simple:x86_64", - "alg:SPHINCS+-SHA256-192f-robust:generic", - "alg:SPHINCS+-SHA256-192f-robust:x86_64", - "alg:SPHINCS+-SHA256-192f-simple:generic", - "alg:SPHINCS+-SHA256-192f-simple:x86_64", - "alg:SPHINCS+-SHA256-192s-robust:generic", - "alg:SPHINCS+-SHA256-192s-robust:x86_64", - "alg:SPHINCS+-SHA256-192s-simple:generic", - "alg:SPHINCS+-SHA256-192s-simple:x86_64", - "alg:SPHINCS+-SHA256-256f-robust:generic", - "alg:SPHINCS+-SHA256-256f-robust:x86_64", - "alg:SPHINCS+-SHA256-256f-simple:generic", - "alg:SPHINCS+-SHA256-256f-simple:x86_64", - "alg:SPHINCS+-SHA256-256s-robust:generic", - "alg:SPHINCS+-SHA256-256s-robust:x86_64", - "alg:SPHINCS+-SHA256-256s-simple:generic", - "alg:SPHINCS+-SHA256-256s-simple:x86_64", - "alg:SPHINCS+-SHAKE256-128f-robust:generic", - "alg:SPHINCS+-SHAKE256-128f-robust:x86_64", - "alg:SPHINCS+-SHAKE256-128f-simple:generic", - "alg:SPHINCS+-SHAKE256-128f-simple:x86_64", - "alg:SPHINCS+-SHAKE256-128s-robust:generic", - "alg:SPHINCS+-SHAKE256-128s-robust:x86_64", - "alg:SPHINCS+-SHAKE256-128s-simple:generic", - "alg:SPHINCS+-SHAKE256-128s-simple:x86_64", - "alg:SPHINCS+-SHAKE256-192f-robust:generic", - "alg:SPHINCS+-SHAKE256-192f-robust:x86_64", - "alg:SPHINCS+-SHAKE256-192f-simple:generic", - "alg:SPHINCS+-SHAKE256-192f-simple:x86_64", - "alg:SPHINCS+-SHAKE256-192s-robust:generic", - "alg:SPHINCS+-SHAKE256-192s-robust:x86_64", - "alg:SPHINCS+-SHAKE256-192s-simple:generic", - "alg:SPHINCS+-SHAKE256-192s-simple:x86_64", - "alg:SPHINCS+-SHAKE256-256f-robust:generic", - "alg:SPHINCS+-SHAKE256-256f-robust:x86_64", - "alg:SPHINCS+-SHAKE256-256f-simple:generic", - "alg:SPHINCS+-SHAKE256-256f-simple:x86_64", - "alg:SPHINCS+-SHAKE256-256s-robust:generic", - "alg:SPHINCS+-SHAKE256-256s-robust:x86_64", - "alg:SPHINCS+-SHAKE256-256s-simple:generic", - "alg:SPHINCS+-SHAKE256-256s-simple:x86_64" - ], - "dependencyType": "implements" - }, - { - "ref": "alg:BIKE-L1:x86_64", - "dependsOn": [ - "alg:aes" - ], - "dependencyType": "uses" - }, - { - "ref": "alg:BIKE-L3:x86_64", - "dependsOn": [ - "alg:aes" - ], - "dependencyType": "uses" - }, - { - "ref": "alg:BIKE-L5:x86_64", - "dependsOn": [ - "alg:aes" - ], - "dependencyType": "uses" - }, - { - "ref": "alg:Classic-McEliece-348864:generic", - "dependsOn": [ - "alg:aes", - "alg:sha3" - ], - "dependencyType": "uses" - }, - { - "ref": "alg:Classic-McEliece-348864:x86_64", - "dependsOn": [ - "alg:aes", - "alg:sha3" - ], - "dependencyType": "uses" - }, - { - "ref": "alg:Classic-McEliece-348864f:generic", - "dependsOn": [ - "alg:aes", - "alg:sha3" - ], - "dependencyType": "uses" - }, - { - "ref": "alg:Classic-McEliece-348864f:x86_64", - "dependsOn": [ - "alg:aes", - "alg:sha3" - ], - "dependencyType": "uses" - }, - { - "ref": "alg:Classic-McEliece-460896:generic", - "dependsOn": [ - "alg:aes", - "alg:sha3" - ], - "dependencyType": "uses" - }, - { - "ref": "alg:Classic-McEliece-460896:x86_64", - "dependsOn": [ - "alg:aes", - "alg:sha3" - ], - "dependencyType": "uses" - }, - { - "ref": "alg:Classic-McEliece-460896f:generic", - "dependsOn": [ - "alg:aes", - "alg:sha3" - ], - "dependencyType": "uses" - }, - { - "ref": "alg:Classic-McEliece-460896f:x86_64", - "dependsOn": [ - "alg:aes", - "alg:sha3" - ], - "dependencyType": "uses" - }, - { - "ref": "alg:Classic-McEliece-6688128:generic", - "dependsOn": [ - "alg:aes", - "alg:sha3" - ], - "dependencyType": "uses" - }, - { - "ref": "alg:Classic-McEliece-6688128:x86_64", - "dependsOn": [ - "alg:aes", - "alg:sha3" - ], - "dependencyType": "uses" - }, - { - "ref": "alg:Classic-McEliece-6688128f:generic", - "dependsOn": [ - "alg:aes", - "alg:sha3" - ], - "dependencyType": "uses" - }, - { - "ref": "alg:Classic-McEliece-6688128f:x86_64", - "dependsOn": [ - "alg:aes", - "alg:sha3" - ], - "dependencyType": "uses" - }, - { - "ref": "alg:Classic-McEliece-6960119:generic", - "dependsOn": [ - "alg:aes", - "alg:sha3" - ], - "dependencyType": "uses" - }, - { - "ref": "alg:Classic-McEliece-6960119:x86_64", - "dependsOn": [ - "alg:aes", - "alg:sha3" - ], - "dependencyType": "uses" - }, - { - "ref": "alg:Classic-McEliece-6960119f:generic", - "dependsOn": [ - "alg:aes", - "alg:sha3" - ], - "dependencyType": "uses" - }, - { - "ref": "alg:Classic-McEliece-6960119f:x86_64", - "dependsOn": [ - "alg:aes", - "alg:sha3" - ], - "dependencyType": "uses" - }, - { - "ref": "alg:Classic-McEliece-8192128:generic", - "dependsOn": [ - "alg:aes", - "alg:sha3" - ], - "dependencyType": "uses" - }, - { - "ref": "alg:Classic-McEliece-8192128:x86_64", - "dependsOn": [ - "alg:aes", - "alg:sha3" - ], - "dependencyType": "uses" - }, - { - "ref": "alg:Classic-McEliece-8192128f:generic", - "dependsOn": [ - "alg:aes", - "alg:sha3" - ], - "dependencyType": "uses" - }, - { - "ref": "alg:Classic-McEliece-8192128f:x86_64", - "dependsOn": [ - "alg:aes", - "alg:sha3" - ], - "dependencyType": "uses" - }, - { - "ref": "alg:FrodoKEM-640-AES:generic", - "dependsOn": [ - "alg:aes", - "alg:sha3" - ], - "dependencyType": "uses" - }, - { - "ref": "alg:FrodoKEM-640-AES:x86_64", - "dependsOn": [ - "alg:aes", - "alg:sha3" - ], - "dependencyType": "uses" - }, - { - "ref": "alg:FrodoKEM-640-SHAKE:generic", - "dependsOn": [ - "alg:aes", - "alg:sha3" - ], - "dependencyType": "uses" - }, - { - "ref": "alg:FrodoKEM-640-SHAKE:x86_64", - "dependsOn": [ - "alg:aes", - "alg:sha3" - ], - "dependencyType": "uses" - }, - { - "ref": "alg:FrodoKEM-976-AES:generic", - "dependsOn": [ - "alg:aes", - "alg:sha3" - ], - "dependencyType": "uses" - }, - { - "ref": "alg:FrodoKEM-976-AES:x86_64", - "dependsOn": [ - "alg:aes", - "alg:sha3" - ], - "dependencyType": "uses" - }, - { - "ref": "alg:FrodoKEM-976-SHAKE:generic", - "dependsOn": [ - "alg:aes", - "alg:sha3" - ], - "dependencyType": "uses" - }, - { - "ref": "alg:FrodoKEM-976-SHAKE:x86_64", - "dependsOn": [ - "alg:aes", - "alg:sha3" - ], - "dependencyType": "uses" - }, - { - "ref": "alg:FrodoKEM-1344-AES:generic", - "dependsOn": [ - "alg:aes", - "alg:sha3" - ], - "dependencyType": "uses" - }, - { - "ref": "alg:FrodoKEM-1344-AES:x86_64", - "dependsOn": [ - "alg:aes", - "alg:sha3" - ], - "dependencyType": "uses" - }, - { - "ref": "alg:FrodoKEM-1344-SHAKE:generic", - "dependsOn": [ - "alg:aes", - "alg:sha3" - ], - "dependencyType": "uses" - }, - { - "ref": "alg:FrodoKEM-1344-SHAKE:x86_64", - "dependsOn": [ - "alg:aes", - "alg:sha3" - ], - "dependencyType": "uses" - }, - { - "ref": "alg:HQC-128:generic", - "dependsOn": [ - "alg:sha3" - ], - "dependencyType": "uses" - }, - { - "ref": "alg:HQC-128:x86_64", - "dependsOn": [ - "alg:sha3" - ], - "dependencyType": "uses" - }, - { - "ref": "alg:HQC-192:generic", - "dependsOn": [ - "alg:sha3" - ], - "dependencyType": "uses" - }, - { - "ref": "alg:HQC-192:x86_64", - "dependsOn": [ - "alg:sha3" - ], - "dependencyType": "uses" - }, - { - "ref": "alg:HQC-256:generic", - "dependsOn": [ - "alg:sha3" - ], - "dependencyType": "uses" - }, - { - "ref": "alg:HQC-256:x86_64", - "dependsOn": [ - "alg:sha3" - ], - "dependencyType": "uses" - }, - { - "ref": "alg:Kyber512:generic", + "ref": "pkg:github/open-quantum-safe/liboqs@79988c6d7388d4e33fa49792ca1c1d8ac2901096", "dependsOn": [ - "alg:sha3" - ], - "dependencyType": "uses" - }, - { - "ref": "alg:Kyber512:x86_64", - "dependsOn": [ - "alg:sha3" + "alg:BIKE-L1:x86_64", + "alg:BIKE-L3:x86_64", + "alg:BIKE-L5:x86_64", + "alg:Classic-McEliece-348864:generic", + "alg:Classic-McEliece-348864:x86_64", + "alg:Classic-McEliece-348864f:generic", + "alg:Classic-McEliece-348864f:x86_64", + "alg:Classic-McEliece-460896:generic", + "alg:Classic-McEliece-460896:x86_64", + "alg:Classic-McEliece-460896f:generic", + "alg:Classic-McEliece-460896f:x86_64", + "alg:Classic-McEliece-6688128:generic", + "alg:Classic-McEliece-6688128:x86_64", + "alg:Classic-McEliece-6688128f:generic", + "alg:Classic-McEliece-6688128f:x86_64", + "alg:Classic-McEliece-6960119:generic", + "alg:Classic-McEliece-6960119:x86_64", + "alg:Classic-McEliece-6960119f:generic", + "alg:Classic-McEliece-6960119f:x86_64", + "alg:Classic-McEliece-8192128:generic", + "alg:Classic-McEliece-8192128:x86_64", + "alg:Classic-McEliece-8192128f:generic", + "alg:Classic-McEliece-8192128f:x86_64", + "alg:FrodoKEM-640-AES:generic", + "alg:FrodoKEM-640-AES:x86_64", + "alg:FrodoKEM-640-SHAKE:generic", + "alg:FrodoKEM-640-SHAKE:x86_64", + "alg:FrodoKEM-976-AES:generic", + "alg:FrodoKEM-976-AES:x86_64", + "alg:FrodoKEM-976-SHAKE:generic", + "alg:FrodoKEM-976-SHAKE:x86_64", + "alg:FrodoKEM-1344-AES:generic", + "alg:FrodoKEM-1344-AES:x86_64", + "alg:FrodoKEM-1344-SHAKE:generic", + "alg:FrodoKEM-1344-SHAKE:x86_64", + "alg:HQC-128:generic", + "alg:HQC-128:x86_64", + "alg:HQC-192:generic", + "alg:HQC-192:x86_64", + "alg:HQC-256:generic", + "alg:HQC-256:x86_64", + "alg:Kyber512:generic", + "alg:Kyber512:x86_64", + "alg:Kyber512:armv8-a", + "alg:Kyber768:generic", + "alg:Kyber768:x86_64", + "alg:Kyber768:armv8-a", + "alg:Kyber1024:generic", + "alg:Kyber1024:x86_64", + "alg:Kyber1024:armv8-a", + "alg:sntrup761:generic", + "alg:sntrup761:x86_64", + "alg:Dilithium2:generic", + "alg:Dilithium2:x86_64", + "alg:Dilithium2:armv8-a", + "alg:Dilithium3:generic", + "alg:Dilithium3:x86_64", + "alg:Dilithium3:armv8-a", + "alg:Dilithium5:generic", + "alg:Dilithium5:x86_64", + "alg:Dilithium5:armv8-a", + "alg:Falcon-512:generic", + "alg:Falcon-512:x86_64", + "alg:Falcon-1024:generic", + "alg:Falcon-1024:x86_64", + "alg:SPHINCS+-SHA256-128f-simple:generic", + "alg:SPHINCS+-SHA256-128f-simple:x86_64", + "alg:SPHINCS+-SHA256-128s-simple:generic", + "alg:SPHINCS+-SHA256-128s-simple:x86_64", + "alg:SPHINCS+-SHA256-192f-simple:generic", + "alg:SPHINCS+-SHA256-192f-simple:x86_64", + "alg:SPHINCS+-SHA256-192s-simple:generic", + "alg:SPHINCS+-SHA256-192s-simple:x86_64", + "alg:SPHINCS+-SHA256-256f-simple:generic", + "alg:SPHINCS+-SHA256-256f-simple:x86_64", + "alg:SPHINCS+-SHA256-256s-simple:generic", + "alg:SPHINCS+-SHA256-256s-simple:x86_64", + "alg:SPHINCS+-SHAKE256-128f-simple:generic", + "alg:SPHINCS+-SHAKE256-128f-simple:x86_64", + "alg:SPHINCS+-SHAKE256-128s-simple:generic", + "alg:SPHINCS+-SHAKE256-128s-simple:x86_64", + "alg:SPHINCS+-SHAKE256-192f-simple:generic", + "alg:SPHINCS+-SHAKE256-192f-simple:x86_64", + "alg:SPHINCS+-SHAKE256-192s-simple:generic", + "alg:SPHINCS+-SHAKE256-192s-simple:x86_64", + "alg:SPHINCS+-SHAKE256-256f-simple:generic", + "alg:SPHINCS+-SHAKE256-256f-simple:x86_64", + "alg:SPHINCS+-SHAKE256-256s-simple:generic", + "alg:SPHINCS+-SHAKE256-256s-simple:x86_64" ], - "dependencyType": "uses" + "dependencyType": "implements" }, { - "ref": "alg:Kyber512:armv8-a", + "ref": "alg:BIKE-L1:x86_64", "dependsOn": [ - "alg:sha3" + "alg:aes" ], "dependencyType": "uses" }, { - "ref": "alg:Kyber512-90s:generic", + "ref": "alg:BIKE-L3:x86_64", "dependsOn": [ "alg:aes" ], "dependencyType": "uses" }, { - "ref": "alg:Kyber512-90s:x86_64", + "ref": "alg:BIKE-L5:x86_64", "dependsOn": [ "alg:aes" ], "dependencyType": "uses" }, { - "ref": "alg:Kyber768:generic", + "ref": "alg:Classic-McEliece-348864:generic", "dependsOn": [ + "alg:aes", "alg:sha3" ], "dependencyType": "uses" }, { - "ref": "alg:Kyber768:x86_64", + "ref": "alg:Classic-McEliece-348864:x86_64", "dependsOn": [ + "alg:aes", "alg:sha3" ], "dependencyType": "uses" }, { - "ref": "alg:Kyber768:armv8-a", + "ref": "alg:Classic-McEliece-348864f:generic", "dependsOn": [ + "alg:aes", "alg:sha3" ], "dependencyType": "uses" }, { - "ref": "alg:Kyber768-90s:generic", - "dependsOn": [ - "alg:aes" - ], - "dependencyType": "uses" - }, - { - "ref": "alg:Kyber768-90s:x86_64", - "dependsOn": [ - "alg:aes" - ], - "dependencyType": "uses" - }, - { - "ref": "alg:Kyber1024:generic", + "ref": "alg:Classic-McEliece-348864f:x86_64", "dependsOn": [ + "alg:aes", "alg:sha3" ], "dependencyType": "uses" }, { - "ref": "alg:Kyber1024:x86_64", + "ref": "alg:Classic-McEliece-460896:generic", "dependsOn": [ + "alg:aes", "alg:sha3" ], "dependencyType": "uses" }, { - "ref": "alg:Kyber1024:armv8-a", + "ref": "alg:Classic-McEliece-460896:x86_64", "dependsOn": [ + "alg:aes", "alg:sha3" ], "dependencyType": "uses" }, { - "ref": "alg:Kyber1024-90s:generic", - "dependsOn": [ - "alg:aes" - ], - "dependencyType": "uses" - }, - { - "ref": "alg:Kyber1024-90s:x86_64", - "dependsOn": [ - "alg:aes" - ], - "dependencyType": "uses" - }, - { - "ref": "alg:sntrup761:generic", - "dependsOn": [ - "alg:aes" - ], - "dependencyType": "uses" - }, - { - "ref": "alg:sntrup761:x86_64", + "ref": "alg:Classic-McEliece-460896f:generic", "dependsOn": [ - "alg:aes" + "alg:aes", + "alg:sha3" ], "dependencyType": "uses" }, { - "ref": "alg:Dilithium2:generic", + "ref": "alg:Classic-McEliece-460896f:x86_64", "dependsOn": [ + "alg:aes", "alg:sha3" ], "dependencyType": "uses" }, { - "ref": "alg:Dilithium2:x86_64", + "ref": "alg:Classic-McEliece-6688128:generic", "dependsOn": [ + "alg:aes", "alg:sha3" ], "dependencyType": "uses" }, { - "ref": "alg:Dilithium2:armv8-a", + "ref": "alg:Classic-McEliece-6688128:x86_64", "dependsOn": [ + "alg:aes", "alg:sha3" ], "dependencyType": "uses" }, { - "ref": "alg:Dilithium3:generic", + "ref": "alg:Classic-McEliece-6688128f:generic", "dependsOn": [ + "alg:aes", "alg:sha3" ], "dependencyType": "uses" }, { - "ref": "alg:Dilithium3:x86_64", + "ref": "alg:Classic-McEliece-6688128f:x86_64", "dependsOn": [ + "alg:aes", "alg:sha3" ], "dependencyType": "uses" }, { - "ref": "alg:Dilithium3:armv8-a", + "ref": "alg:Classic-McEliece-6960119:generic", "dependsOn": [ + "alg:aes", "alg:sha3" ], "dependencyType": "uses" }, { - "ref": "alg:Dilithium5:generic", + "ref": "alg:Classic-McEliece-6960119:x86_64", "dependsOn": [ + "alg:aes", "alg:sha3" ], "dependencyType": "uses" }, { - "ref": "alg:Dilithium5:x86_64", + "ref": "alg:Classic-McEliece-6960119f:generic", "dependsOn": [ + "alg:aes", "alg:sha3" ], "dependencyType": "uses" }, { - "ref": "alg:Dilithium5:armv8-a", + "ref": "alg:Classic-McEliece-6960119f:x86_64", "dependsOn": [ + "alg:aes", "alg:sha3" ], "dependencyType": "uses" }, { - "ref": "alg:Dilithium2-AES:generic", + "ref": "alg:Classic-McEliece-8192128:generic", "dependsOn": [ - "alg:aes" + "alg:aes", + "alg:sha3" ], "dependencyType": "uses" }, { - "ref": "alg:Dilithium2-AES:x86_64", + "ref": "alg:Classic-McEliece-8192128:x86_64", "dependsOn": [ - "alg:aes" + "alg:aes", + "alg:sha3" ], "dependencyType": "uses" }, { - "ref": "alg:Dilithium3-AES:generic", + "ref": "alg:Classic-McEliece-8192128f:generic", "dependsOn": [ - "alg:aes" + "alg:aes", + "alg:sha3" ], "dependencyType": "uses" }, { - "ref": "alg:Dilithium3-AES:x86_64", + "ref": "alg:Classic-McEliece-8192128f:x86_64", "dependsOn": [ - "alg:aes" + "alg:aes", + "alg:sha3" ], "dependencyType": "uses" }, { - "ref": "alg:Dilithium5-AES:generic", + "ref": "alg:FrodoKEM-640-AES:generic", "dependsOn": [ - "alg:aes" + "alg:aes", + "alg:sha3" ], "dependencyType": "uses" }, { - "ref": "alg:Dilithium5-AES:x86_64", + "ref": "alg:FrodoKEM-640-AES:x86_64", "dependsOn": [ - "alg:aes" + "alg:aes", + "alg:sha3" ], "dependencyType": "uses" }, { - "ref": "alg:Falcon-512:generic", + "ref": "alg:FrodoKEM-640-SHAKE:generic", "dependsOn": [ + "alg:aes", "alg:sha3" ], "dependencyType": "uses" }, { - "ref": "alg:Falcon-512:x86_64", + "ref": "alg:FrodoKEM-640-SHAKE:x86_64", "dependsOn": [ + "alg:aes", "alg:sha3" ], "dependencyType": "uses" }, { - "ref": "alg:Falcon-1024:generic", + "ref": "alg:FrodoKEM-976-AES:generic", "dependsOn": [ + "alg:aes", "alg:sha3" ], "dependencyType": "uses" }, { - "ref": "alg:Falcon-1024:x86_64", + "ref": "alg:FrodoKEM-976-AES:x86_64", "dependsOn": [ + "alg:aes", "alg:sha3" ], "dependencyType": "uses" }, { - "ref": "alg:SPHINCS+-Haraka-128f-robust:generic", + "ref": "alg:FrodoKEM-976-SHAKE:generic", "dependsOn": [ - "alg:aes" + "alg:aes", + "alg:sha3" ], "dependencyType": "uses" }, { - "ref": "alg:SPHINCS+-Haraka-128f-robust:x86_64", + "ref": "alg:FrodoKEM-976-SHAKE:x86_64", "dependsOn": [ - "alg:aes" + "alg:aes", + "alg:sha3" ], "dependencyType": "uses" }, { - "ref": "alg:SPHINCS+-Haraka-128f-simple:generic", + "ref": "alg:FrodoKEM-1344-AES:generic", "dependsOn": [ - "alg:aes" + "alg:aes", + "alg:sha3" ], "dependencyType": "uses" }, { - "ref": "alg:SPHINCS+-Haraka-128f-simple:x86_64", + "ref": "alg:FrodoKEM-1344-AES:x86_64", "dependsOn": [ - "alg:aes" + "alg:aes", + "alg:sha3" ], "dependencyType": "uses" }, { - "ref": "alg:SPHINCS+-Haraka-128s-robust:generic", + "ref": "alg:FrodoKEM-1344-SHAKE:generic", "dependsOn": [ - "alg:aes" + "alg:aes", + "alg:sha3" ], "dependencyType": "uses" }, { - "ref": "alg:SPHINCS+-Haraka-128s-robust:x86_64", + "ref": "alg:FrodoKEM-1344-SHAKE:x86_64", "dependsOn": [ - "alg:aes" + "alg:aes", + "alg:sha3" ], "dependencyType": "uses" }, { - "ref": "alg:SPHINCS+-Haraka-128s-simple:generic", + "ref": "alg:HQC-128:generic", "dependsOn": [ - "alg:aes" + "alg:sha3" ], "dependencyType": "uses" }, { - "ref": "alg:SPHINCS+-Haraka-128s-simple:x86_64", + "ref": "alg:HQC-128:x86_64", "dependsOn": [ - "alg:aes" + "alg:sha3" ], "dependencyType": "uses" }, { - "ref": "alg:SPHINCS+-Haraka-192f-robust:generic", + "ref": "alg:HQC-192:generic", "dependsOn": [ - "alg:aes" + "alg:sha3" ], "dependencyType": "uses" }, { - "ref": "alg:SPHINCS+-Haraka-192f-robust:x86_64", + "ref": "alg:HQC-192:x86_64", "dependsOn": [ - "alg:aes" + "alg:sha3" ], "dependencyType": "uses" }, { - "ref": "alg:SPHINCS+-Haraka-192f-simple:generic", + "ref": "alg:HQC-256:generic", "dependsOn": [ - "alg:aes" + "alg:sha3" ], "dependencyType": "uses" }, { - "ref": "alg:SPHINCS+-Haraka-192f-simple:x86_64", + "ref": "alg:HQC-256:x86_64", "dependsOn": [ - "alg:aes" + "alg:sha3" ], "dependencyType": "uses" }, { - "ref": "alg:SPHINCS+-Haraka-192s-robust:generic", + "ref": "alg:Kyber512:generic", "dependsOn": [ - "alg:aes" + "alg:sha3" ], "dependencyType": "uses" }, { - "ref": "alg:SPHINCS+-Haraka-192s-robust:x86_64", + "ref": "alg:Kyber512:x86_64", "dependsOn": [ - "alg:aes" + "alg:sha3" ], "dependencyType": "uses" }, { - "ref": "alg:SPHINCS+-Haraka-192s-simple:generic", + "ref": "alg:Kyber512:armv8-a", "dependsOn": [ - "alg:aes" + "alg:sha3" ], "dependencyType": "uses" }, { - "ref": "alg:SPHINCS+-Haraka-192s-simple:x86_64", + "ref": "alg:Kyber768:generic", "dependsOn": [ - "alg:aes" + "alg:sha3" ], "dependencyType": "uses" }, { - "ref": "alg:SPHINCS+-Haraka-256f-robust:generic", + "ref": "alg:Kyber768:x86_64", "dependsOn": [ - "alg:aes" + "alg:sha3" ], "dependencyType": "uses" }, { - "ref": "alg:SPHINCS+-Haraka-256f-robust:x86_64", + "ref": "alg:Kyber768:armv8-a", "dependsOn": [ - "alg:aes" + "alg:sha3" ], "dependencyType": "uses" }, { - "ref": "alg:SPHINCS+-Haraka-256f-simple:generic", + "ref": "alg:Kyber1024:generic", "dependsOn": [ - "alg:aes" + "alg:sha3" ], "dependencyType": "uses" }, { - "ref": "alg:SPHINCS+-Haraka-256f-simple:x86_64", + "ref": "alg:Kyber1024:x86_64", "dependsOn": [ - "alg:aes" + "alg:sha3" ], "dependencyType": "uses" }, { - "ref": "alg:SPHINCS+-Haraka-256s-robust:generic", + "ref": "alg:Kyber1024:armv8-a", "dependsOn": [ - "alg:aes" + "alg:sha3" ], "dependencyType": "uses" }, { - "ref": "alg:SPHINCS+-Haraka-256s-robust:x86_64", + "ref": "alg:sntrup761:generic", "dependsOn": [ "alg:aes" ], "dependencyType": "uses" }, { - "ref": "alg:SPHINCS+-Haraka-256s-simple:generic", + "ref": "alg:sntrup761:x86_64", "dependsOn": [ "alg:aes" ], "dependencyType": "uses" }, { - "ref": "alg:SPHINCS+-Haraka-256s-simple:x86_64", + "ref": "alg:Dilithium2:generic", "dependsOn": [ - "alg:aes" + "alg:sha3" ], "dependencyType": "uses" }, { - "ref": "alg:SPHINCS+-SHAKE256-128f-robust:generic", + "ref": "alg:Dilithium2:x86_64", "dependsOn": [ "alg:sha3" ], "dependencyType": "uses" }, { - "ref": "alg:SPHINCS+-SHAKE256-128f-robust:x86_64", + "ref": "alg:Dilithium2:armv8-a", "dependsOn": [ "alg:sha3" ], "dependencyType": "uses" }, { - "ref": "alg:SPHINCS+-SHAKE256-128f-simple:generic", + "ref": "alg:Dilithium3:generic", "dependsOn": [ "alg:sha3" ], "dependencyType": "uses" }, { - "ref": "alg:SPHINCS+-SHAKE256-128f-simple:x86_64", + "ref": "alg:Dilithium3:x86_64", "dependsOn": [ "alg:sha3" ], "dependencyType": "uses" }, { - "ref": "alg:SPHINCS+-SHAKE256-128s-robust:generic", + "ref": "alg:Dilithium3:armv8-a", "dependsOn": [ "alg:sha3" ], "dependencyType": "uses" }, { - "ref": "alg:SPHINCS+-SHAKE256-128s-robust:x86_64", + "ref": "alg:Dilithium5:generic", "dependsOn": [ "alg:sha3" ], "dependencyType": "uses" }, { - "ref": "alg:SPHINCS+-SHAKE256-128s-simple:generic", + "ref": "alg:Dilithium5:x86_64", "dependsOn": [ "alg:sha3" ], "dependencyType": "uses" }, { - "ref": "alg:SPHINCS+-SHAKE256-128s-simple:x86_64", + "ref": "alg:Dilithium5:armv8-a", "dependsOn": [ "alg:sha3" ], "dependencyType": "uses" }, { - "ref": "alg:SPHINCS+-SHAKE256-192f-robust:generic", + "ref": "alg:Falcon-512:generic", "dependsOn": [ "alg:sha3" ], "dependencyType": "uses" }, { - "ref": "alg:SPHINCS+-SHAKE256-192f-robust:x86_64", + "ref": "alg:Falcon-512:x86_64", "dependsOn": [ "alg:sha3" ], "dependencyType": "uses" }, { - "ref": "alg:SPHINCS+-SHAKE256-192f-simple:generic", + "ref": "alg:Falcon-1024:generic", "dependsOn": [ "alg:sha3" ], "dependencyType": "uses" }, { - "ref": "alg:SPHINCS+-SHAKE256-192f-simple:x86_64", + "ref": "alg:Falcon-1024:x86_64", "dependsOn": [ "alg:sha3" ], "dependencyType": "uses" }, { - "ref": "alg:SPHINCS+-SHAKE256-192s-robust:generic", + "ref": "alg:SPHINCS+-SHAKE256-128f-simple:generic", "dependsOn": [ "alg:sha3" ], "dependencyType": "uses" }, { - "ref": "alg:SPHINCS+-SHAKE256-192s-robust:x86_64", + "ref": "alg:SPHINCS+-SHAKE256-128f-simple:x86_64", "dependsOn": [ "alg:sha3" ], "dependencyType": "uses" }, { - "ref": "alg:SPHINCS+-SHAKE256-192s-simple:generic", + "ref": "alg:SPHINCS+-SHAKE256-128s-simple:generic", "dependsOn": [ "alg:sha3" ], "dependencyType": "uses" }, { - "ref": "alg:SPHINCS+-SHAKE256-192s-simple:x86_64", + "ref": "alg:SPHINCS+-SHAKE256-128s-simple:x86_64", "dependsOn": [ "alg:sha3" ], "dependencyType": "uses" }, { - "ref": "alg:SPHINCS+-SHAKE256-256f-robust:generic", + "ref": "alg:SPHINCS+-SHAKE256-192f-simple:generic", "dependsOn": [ "alg:sha3" ], "dependencyType": "uses" }, { - "ref": "alg:SPHINCS+-SHAKE256-256f-robust:x86_64", + "ref": "alg:SPHINCS+-SHAKE256-192f-simple:x86_64", "dependsOn": [ "alg:sha3" ], "dependencyType": "uses" }, { - "ref": "alg:SPHINCS+-SHAKE256-256f-simple:generic", + "ref": "alg:SPHINCS+-SHAKE256-192s-simple:generic", "dependsOn": [ "alg:sha3" ], "dependencyType": "uses" }, { - "ref": "alg:SPHINCS+-SHAKE256-256f-simple:x86_64", + "ref": "alg:SPHINCS+-SHAKE256-192s-simple:x86_64", "dependsOn": [ "alg:sha3" ], "dependencyType": "uses" }, { - "ref": "alg:SPHINCS+-SHAKE256-256s-robust:generic", + "ref": "alg:SPHINCS+-SHAKE256-256f-simple:generic", "dependsOn": [ "alg:sha3" ], "dependencyType": "uses" }, { - "ref": "alg:SPHINCS+-SHAKE256-256s-robust:x86_64", + "ref": "alg:SPHINCS+-SHAKE256-256f-simple:x86_64", "dependsOn": [ "alg:sha3" ], diff --git a/scripts/copy_from_upstream/copy_from_upstream.yml b/scripts/copy_from_upstream/copy_from_upstream.yml index 04e8896e5f..5719b1f9bd 100644 --- a/scripts/copy_from_upstream/copy_from_upstream.yml +++ b/scripts/copy_from_upstream/copy_from_upstream.yml @@ -8,7 +8,8 @@ upstreams: sig_meta_path: 'crypto_sign/{pqclean_scheme}/META.yml' kem_scheme_path: 'crypto_kem/{pqclean_scheme}' sig_scheme_path: 'crypto_sign/{pqclean_scheme}' - patches: [pqclean-kyber-armneon-shake.patch, pqclean-kyber-arm-macos-gcc-fix.patch, pqclean-dilithium-arm-randomized-signing.patch] + patches: [pqclean-sphincs.patch, pqclean-kyber-armneon-shake.patch, pqclean-kyber-arm-macos-gcc-fix.patch, pqclean-dilithium-arm-randomized-signing.patch] + ignore: pqclean_sphincs-shake-256s-simple_aarch64, pqclean_sphincs-shake-256s-simple_aarch64, pqclean_sphincs-shake-256f-simple_aarch64, pqclean_sphincs-shake-192s-simple_aarch64, pqclean_sphincs-shake-192f-simple_aarch64, pqclean_sphincs-shake-128s-simple_aarch64, pqclean_sphincs-shake-128f-simple_aarch64 - name: pqcrystals-kyber git_url: https://github.com/pq-crystals/kyber.git @@ -109,18 +110,6 @@ kems: scheme: "1024" pqclean_scheme: kyber1024 pretty_name_full: Kyber1024 - - - scheme: "512_90s" - pqclean_scheme: kyber512-90s - pretty_name_full: Kyber512-90s - - - scheme: "768_90s" - pqclean_scheme: kyber768-90s - pretty_name_full: Kyber768-90s - - - scheme: "1024_90s" - pqclean_scheme: kyber1024-90s - pretty_name_full: Kyber1024-90s sigs: - name: dilithium @@ -146,21 +135,6 @@ sigs: pqclean_scheme: dilithium5 pretty_name_full: Dilithium5 signed_msg_order: sig_then_msg - - - scheme: "2_aes" - pqclean_scheme: dilithium2aes - pretty_name_full: Dilithium2-AES - signed_msg_order: sig_then_msg - - - scheme: "3_aes" - pqclean_scheme: dilithium3aes - pretty_name_full: Dilithium3-AES - signed_msg_order: sig_then_msg - - - scheme: "5_aes" - pqclean_scheme: dilithium5aes - pretty_name_full: Dilithium5-AES - signed_msg_order: sig_then_msg - name: falcon default_implementation: clean diff --git a/scripts/copy_from_upstream/patches/pqclean-sphincs.patch b/scripts/copy_from_upstream/patches/pqclean-sphincs.patch new file mode 100644 index 0000000000..e41ae1583d --- /dev/null +++ b/scripts/copy_from_upstream/patches/pqclean-sphincs.patch @@ -0,0 +1,3000 @@ +diff --git a/crypto_sign/sphincs-shake-128f-robust/avx2/fips202x4.c b/crypto_sign/sphincs-shake-128f-robust/avx2/fips202x4.c +deleted file mode 100644 +index 1e06fef..0000000 +--- a/crypto_sign/sphincs-shake-128f-robust/avx2/fips202x4.c ++++ /dev/null +@@ -1,210 +0,0 @@ +-#include +-#include +-#include +- +-#include "fips202.h" +-#include "fips202x4.h" +- +-#define NROUNDS 24 +-#define ROL(a, offset) (((a) << (offset)) ^ ((a) >> (64-(offset)))) +- +-static uint64_t load64(const unsigned char *x) { +- unsigned long long r = 0, i; +- +- for (i = 0; i < 8; ++i) { +- r |= (unsigned long long)x[i] << 8 * i; +- } +- return r; +-} +- +-static void store64(uint8_t *x, uint64_t u) { +- unsigned int i; +- +- for (i = 0; i < 8; ++i) { +- x[i] = (uint8_t)u; +- u >>= 8; +- } +-} +- +-/* Use implementation from the Keccak Code Package */ +-extern void KeccakP1600times4_PermuteAll_24rounds(__m256i *s); +-#define KeccakF1600_StatePermute4x KeccakP1600times4_PermuteAll_24rounds +- +-static void keccak_absorb4x(__m256i *s, +- unsigned int r, +- const unsigned char *m0, +- const unsigned char *m1, +- const unsigned char *m2, +- const unsigned char *m3, +- unsigned long long int mlen, +- unsigned char p) { +- unsigned long long i; +- unsigned char t0[200]; +- unsigned char t1[200]; +- unsigned char t2[200]; +- unsigned char t3[200]; +- +- unsigned long long *ss = (unsigned long long *)s; +- +- +- while (mlen >= r) { +- for (i = 0; i < r / 8; ++i) { +- ss[4 * i + 0] ^= load64(m0 + 8 * i); +- ss[4 * i + 1] ^= load64(m1 + 8 * i); +- ss[4 * i + 2] ^= load64(m2 + 8 * i); +- ss[4 * i + 3] ^= load64(m3 + 8 * i); +- } +- +- KeccakF1600_StatePermute4x(s); +- mlen -= r; +- m0 += r; +- m1 += r; +- m2 += r; +- m3 += r; +- } +- +- for (i = 0; i < r; ++i) { +- t0[i] = 0; +- t1[i] = 0; +- t2[i] = 0; +- t3[i] = 0; +- } +- for (i = 0; i < mlen; ++i) { +- t0[i] = m0[i]; +- t1[i] = m1[i]; +- t2[i] = m2[i]; +- t3[i] = m3[i]; +- } +- +- t0[i] = p; +- t1[i] = p; +- t2[i] = p; +- t3[i] = p; +- +- t0[r - 1] |= 128; +- t1[r - 1] |= 128; +- t2[r - 1] |= 128; +- t3[r - 1] |= 128; +- +- for (i = 0; i < r / 8; ++i) { +- ss[4 * i + 0] ^= load64(t0 + 8 * i); +- ss[4 * i + 1] ^= load64(t1 + 8 * i); +- ss[4 * i + 2] ^= load64(t2 + 8 * i); +- ss[4 * i + 3] ^= load64(t3 + 8 * i); +- } +-} +- +- +-static void keccak_squeezeblocks4x(unsigned char *h0, +- unsigned char *h1, +- unsigned char *h2, +- unsigned char *h3, +- unsigned long long int nblocks, +- __m256i *s, +- unsigned int r) { +- unsigned int i; +- +- unsigned long long *ss = (unsigned long long *)s; +- +- while (nblocks > 0) { +- KeccakF1600_StatePermute4x(s); +- for (i = 0; i < (r >> 3); i++) { +- store64(h0 + 8 * i, ss[4 * i + 0]); +- store64(h1 + 8 * i, ss[4 * i + 1]); +- store64(h2 + 8 * i, ss[4 * i + 2]); +- store64(h3 + 8 * i, ss[4 * i + 3]); +- } +- h0 += r; +- h1 += r; +- h2 += r; +- h3 += r; +- nblocks--; +- } +-} +- +- +- +-void shake128x4(unsigned char *out0, +- unsigned char *out1, +- unsigned char *out2, +- unsigned char *out3, unsigned long long outlen, +- unsigned char *in0, +- unsigned char *in1, +- unsigned char *in2, +- unsigned char *in3, unsigned long long inlen) { +- __m256i s[25]; +- unsigned char t0[SHAKE128_RATE]; +- unsigned char t1[SHAKE128_RATE]; +- unsigned char t2[SHAKE128_RATE]; +- unsigned char t3[SHAKE128_RATE]; +- unsigned int i; +- +- /* zero state */ +- for (i = 0; i < 25; i++) { +- s[i] = _mm256_xor_si256(s[i], s[i]); +- } +- +- /* absorb 4 message of identical length in parallel */ +- keccak_absorb4x(s, SHAKE128_RATE, in0, in1, in2, in3, inlen, 0x1F); +- +- /* Squeeze output */ +- keccak_squeezeblocks4x(out0, out1, out2, out3, outlen / SHAKE128_RATE, s, SHAKE128_RATE); +- +- out0 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; +- out1 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; +- out2 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; +- out3 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; +- +- if (outlen % SHAKE128_RATE) { +- keccak_squeezeblocks4x(t0, t1, t2, t3, 1, s, SHAKE128_RATE); +- for (i = 0; i < outlen % SHAKE128_RATE; i++) { +- out0[i] = t0[i]; +- out1[i] = t1[i]; +- out2[i] = t2[i]; +- out3[i] = t3[i]; +- } +- } +-} +- +- +-void shake256x4(unsigned char *out0, +- unsigned char *out1, +- unsigned char *out2, +- unsigned char *out3, unsigned long long outlen, +- unsigned char *in0, +- unsigned char *in1, +- unsigned char *in2, +- unsigned char *in3, unsigned long long inlen) { +- __m256i s[25]; +- unsigned char t0[SHAKE256_RATE]; +- unsigned char t1[SHAKE256_RATE]; +- unsigned char t2[SHAKE256_RATE]; +- unsigned char t3[SHAKE256_RATE]; +- unsigned int i; +- +- /* zero state */ +- for (i = 0; i < 25; i++) { +- s[i] = _mm256_xor_si256(s[i], s[i]); +- } +- +- /* absorb 4 message of identical length in parallel */ +- keccak_absorb4x(s, SHAKE256_RATE, in0, in1, in2, in3, inlen, 0x1F); +- +- /* Squeeze output */ +- keccak_squeezeblocks4x(out0, out1, out2, out3, outlen / SHAKE256_RATE, s, SHAKE256_RATE); +- +- out0 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; +- out1 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; +- out2 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; +- out3 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; +- +- if (outlen % SHAKE256_RATE) { +- keccak_squeezeblocks4x(t0, t1, t2, t3, 1, s, SHAKE256_RATE); +- for (i = 0; i < outlen % SHAKE256_RATE; i++) { +- out0[i] = t0[i]; +- out1[i] = t1[i]; +- out2[i] = t2[i]; +- out3[i] = t3[i]; +- } +- } +-} +diff --git a/crypto_sign/sphincs-shake-128f-robust/avx2/fips202x4.h b/crypto_sign/sphincs-shake-128f-robust/avx2/fips202x4.h +deleted file mode 100644 +index 2b93c9c..0000000 +--- a/crypto_sign/sphincs-shake-128f-robust/avx2/fips202x4.h ++++ /dev/null +@@ -1,28 +0,0 @@ +-#ifndef SPX_FIPS202X4_H +-#define SPX_FIPS202X4_H +- +-#include +- +-#include "params.h" +- +-#define shake128x4 SPX_NAMESPACE(shake128x4) +-void shake128x4(unsigned char *out0, +- unsigned char *out1, +- unsigned char *out2, +- unsigned char *out3, unsigned long long outlen, +- unsigned char *in0, +- unsigned char *in1, +- unsigned char *in2, +- unsigned char *in3, unsigned long long inlen); +- +-#define shake256x4 SPX_NAMESPACE(shake256x4) +-void shake256x4(unsigned char *out0, +- unsigned char *out1, +- unsigned char *out2, +- unsigned char *out3, unsigned long long outlen, +- unsigned char *in0, +- unsigned char *in1, +- unsigned char *in2, +- unsigned char *in3, unsigned long long inlen); +- +-#endif +diff --git a/crypto_sign/sphincs-shake-128f-simple/avx2/fips202x4.c b/crypto_sign/sphincs-shake-128f-simple/avx2/fips202x4.c +deleted file mode 100644 +index 1e06fef..0000000 +--- a/crypto_sign/sphincs-shake-128f-simple/avx2/fips202x4.c ++++ /dev/null +@@ -1,210 +0,0 @@ +-#include +-#include +-#include +- +-#include "fips202.h" +-#include "fips202x4.h" +- +-#define NROUNDS 24 +-#define ROL(a, offset) (((a) << (offset)) ^ ((a) >> (64-(offset)))) +- +-static uint64_t load64(const unsigned char *x) { +- unsigned long long r = 0, i; +- +- for (i = 0; i < 8; ++i) { +- r |= (unsigned long long)x[i] << 8 * i; +- } +- return r; +-} +- +-static void store64(uint8_t *x, uint64_t u) { +- unsigned int i; +- +- for (i = 0; i < 8; ++i) { +- x[i] = (uint8_t)u; +- u >>= 8; +- } +-} +- +-/* Use implementation from the Keccak Code Package */ +-extern void KeccakP1600times4_PermuteAll_24rounds(__m256i *s); +-#define KeccakF1600_StatePermute4x KeccakP1600times4_PermuteAll_24rounds +- +-static void keccak_absorb4x(__m256i *s, +- unsigned int r, +- const unsigned char *m0, +- const unsigned char *m1, +- const unsigned char *m2, +- const unsigned char *m3, +- unsigned long long int mlen, +- unsigned char p) { +- unsigned long long i; +- unsigned char t0[200]; +- unsigned char t1[200]; +- unsigned char t2[200]; +- unsigned char t3[200]; +- +- unsigned long long *ss = (unsigned long long *)s; +- +- +- while (mlen >= r) { +- for (i = 0; i < r / 8; ++i) { +- ss[4 * i + 0] ^= load64(m0 + 8 * i); +- ss[4 * i + 1] ^= load64(m1 + 8 * i); +- ss[4 * i + 2] ^= load64(m2 + 8 * i); +- ss[4 * i + 3] ^= load64(m3 + 8 * i); +- } +- +- KeccakF1600_StatePermute4x(s); +- mlen -= r; +- m0 += r; +- m1 += r; +- m2 += r; +- m3 += r; +- } +- +- for (i = 0; i < r; ++i) { +- t0[i] = 0; +- t1[i] = 0; +- t2[i] = 0; +- t3[i] = 0; +- } +- for (i = 0; i < mlen; ++i) { +- t0[i] = m0[i]; +- t1[i] = m1[i]; +- t2[i] = m2[i]; +- t3[i] = m3[i]; +- } +- +- t0[i] = p; +- t1[i] = p; +- t2[i] = p; +- t3[i] = p; +- +- t0[r - 1] |= 128; +- t1[r - 1] |= 128; +- t2[r - 1] |= 128; +- t3[r - 1] |= 128; +- +- for (i = 0; i < r / 8; ++i) { +- ss[4 * i + 0] ^= load64(t0 + 8 * i); +- ss[4 * i + 1] ^= load64(t1 + 8 * i); +- ss[4 * i + 2] ^= load64(t2 + 8 * i); +- ss[4 * i + 3] ^= load64(t3 + 8 * i); +- } +-} +- +- +-static void keccak_squeezeblocks4x(unsigned char *h0, +- unsigned char *h1, +- unsigned char *h2, +- unsigned char *h3, +- unsigned long long int nblocks, +- __m256i *s, +- unsigned int r) { +- unsigned int i; +- +- unsigned long long *ss = (unsigned long long *)s; +- +- while (nblocks > 0) { +- KeccakF1600_StatePermute4x(s); +- for (i = 0; i < (r >> 3); i++) { +- store64(h0 + 8 * i, ss[4 * i + 0]); +- store64(h1 + 8 * i, ss[4 * i + 1]); +- store64(h2 + 8 * i, ss[4 * i + 2]); +- store64(h3 + 8 * i, ss[4 * i + 3]); +- } +- h0 += r; +- h1 += r; +- h2 += r; +- h3 += r; +- nblocks--; +- } +-} +- +- +- +-void shake128x4(unsigned char *out0, +- unsigned char *out1, +- unsigned char *out2, +- unsigned char *out3, unsigned long long outlen, +- unsigned char *in0, +- unsigned char *in1, +- unsigned char *in2, +- unsigned char *in3, unsigned long long inlen) { +- __m256i s[25]; +- unsigned char t0[SHAKE128_RATE]; +- unsigned char t1[SHAKE128_RATE]; +- unsigned char t2[SHAKE128_RATE]; +- unsigned char t3[SHAKE128_RATE]; +- unsigned int i; +- +- /* zero state */ +- for (i = 0; i < 25; i++) { +- s[i] = _mm256_xor_si256(s[i], s[i]); +- } +- +- /* absorb 4 message of identical length in parallel */ +- keccak_absorb4x(s, SHAKE128_RATE, in0, in1, in2, in3, inlen, 0x1F); +- +- /* Squeeze output */ +- keccak_squeezeblocks4x(out0, out1, out2, out3, outlen / SHAKE128_RATE, s, SHAKE128_RATE); +- +- out0 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; +- out1 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; +- out2 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; +- out3 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; +- +- if (outlen % SHAKE128_RATE) { +- keccak_squeezeblocks4x(t0, t1, t2, t3, 1, s, SHAKE128_RATE); +- for (i = 0; i < outlen % SHAKE128_RATE; i++) { +- out0[i] = t0[i]; +- out1[i] = t1[i]; +- out2[i] = t2[i]; +- out3[i] = t3[i]; +- } +- } +-} +- +- +-void shake256x4(unsigned char *out0, +- unsigned char *out1, +- unsigned char *out2, +- unsigned char *out3, unsigned long long outlen, +- unsigned char *in0, +- unsigned char *in1, +- unsigned char *in2, +- unsigned char *in3, unsigned long long inlen) { +- __m256i s[25]; +- unsigned char t0[SHAKE256_RATE]; +- unsigned char t1[SHAKE256_RATE]; +- unsigned char t2[SHAKE256_RATE]; +- unsigned char t3[SHAKE256_RATE]; +- unsigned int i; +- +- /* zero state */ +- for (i = 0; i < 25; i++) { +- s[i] = _mm256_xor_si256(s[i], s[i]); +- } +- +- /* absorb 4 message of identical length in parallel */ +- keccak_absorb4x(s, SHAKE256_RATE, in0, in1, in2, in3, inlen, 0x1F); +- +- /* Squeeze output */ +- keccak_squeezeblocks4x(out0, out1, out2, out3, outlen / SHAKE256_RATE, s, SHAKE256_RATE); +- +- out0 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; +- out1 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; +- out2 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; +- out3 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; +- +- if (outlen % SHAKE256_RATE) { +- keccak_squeezeblocks4x(t0, t1, t2, t3, 1, s, SHAKE256_RATE); +- for (i = 0; i < outlen % SHAKE256_RATE; i++) { +- out0[i] = t0[i]; +- out1[i] = t1[i]; +- out2[i] = t2[i]; +- out3[i] = t3[i]; +- } +- } +-} +diff --git a/crypto_sign/sphincs-shake-128f-simple/avx2/fips202x4.h b/crypto_sign/sphincs-shake-128f-simple/avx2/fips202x4.h +deleted file mode 100644 +index 2b93c9c..0000000 +--- a/crypto_sign/sphincs-shake-128f-simple/avx2/fips202x4.h ++++ /dev/null +@@ -1,28 +0,0 @@ +-#ifndef SPX_FIPS202X4_H +-#define SPX_FIPS202X4_H +- +-#include +- +-#include "params.h" +- +-#define shake128x4 SPX_NAMESPACE(shake128x4) +-void shake128x4(unsigned char *out0, +- unsigned char *out1, +- unsigned char *out2, +- unsigned char *out3, unsigned long long outlen, +- unsigned char *in0, +- unsigned char *in1, +- unsigned char *in2, +- unsigned char *in3, unsigned long long inlen); +- +-#define shake256x4 SPX_NAMESPACE(shake256x4) +-void shake256x4(unsigned char *out0, +- unsigned char *out1, +- unsigned char *out2, +- unsigned char *out3, unsigned long long outlen, +- unsigned char *in0, +- unsigned char *in1, +- unsigned char *in2, +- unsigned char *in3, unsigned long long inlen); +- +-#endif +diff --git a/crypto_sign/sphincs-shake-128s-robust/avx2/fips202x4.c b/crypto_sign/sphincs-shake-128s-robust/avx2/fips202x4.c +deleted file mode 100644 +index 1e06fef..0000000 +--- a/crypto_sign/sphincs-shake-128s-robust/avx2/fips202x4.c ++++ /dev/null +@@ -1,210 +0,0 @@ +-#include +-#include +-#include +- +-#include "fips202.h" +-#include "fips202x4.h" +- +-#define NROUNDS 24 +-#define ROL(a, offset) (((a) << (offset)) ^ ((a) >> (64-(offset)))) +- +-static uint64_t load64(const unsigned char *x) { +- unsigned long long r = 0, i; +- +- for (i = 0; i < 8; ++i) { +- r |= (unsigned long long)x[i] << 8 * i; +- } +- return r; +-} +- +-static void store64(uint8_t *x, uint64_t u) { +- unsigned int i; +- +- for (i = 0; i < 8; ++i) { +- x[i] = (uint8_t)u; +- u >>= 8; +- } +-} +- +-/* Use implementation from the Keccak Code Package */ +-extern void KeccakP1600times4_PermuteAll_24rounds(__m256i *s); +-#define KeccakF1600_StatePermute4x KeccakP1600times4_PermuteAll_24rounds +- +-static void keccak_absorb4x(__m256i *s, +- unsigned int r, +- const unsigned char *m0, +- const unsigned char *m1, +- const unsigned char *m2, +- const unsigned char *m3, +- unsigned long long int mlen, +- unsigned char p) { +- unsigned long long i; +- unsigned char t0[200]; +- unsigned char t1[200]; +- unsigned char t2[200]; +- unsigned char t3[200]; +- +- unsigned long long *ss = (unsigned long long *)s; +- +- +- while (mlen >= r) { +- for (i = 0; i < r / 8; ++i) { +- ss[4 * i + 0] ^= load64(m0 + 8 * i); +- ss[4 * i + 1] ^= load64(m1 + 8 * i); +- ss[4 * i + 2] ^= load64(m2 + 8 * i); +- ss[4 * i + 3] ^= load64(m3 + 8 * i); +- } +- +- KeccakF1600_StatePermute4x(s); +- mlen -= r; +- m0 += r; +- m1 += r; +- m2 += r; +- m3 += r; +- } +- +- for (i = 0; i < r; ++i) { +- t0[i] = 0; +- t1[i] = 0; +- t2[i] = 0; +- t3[i] = 0; +- } +- for (i = 0; i < mlen; ++i) { +- t0[i] = m0[i]; +- t1[i] = m1[i]; +- t2[i] = m2[i]; +- t3[i] = m3[i]; +- } +- +- t0[i] = p; +- t1[i] = p; +- t2[i] = p; +- t3[i] = p; +- +- t0[r - 1] |= 128; +- t1[r - 1] |= 128; +- t2[r - 1] |= 128; +- t3[r - 1] |= 128; +- +- for (i = 0; i < r / 8; ++i) { +- ss[4 * i + 0] ^= load64(t0 + 8 * i); +- ss[4 * i + 1] ^= load64(t1 + 8 * i); +- ss[4 * i + 2] ^= load64(t2 + 8 * i); +- ss[4 * i + 3] ^= load64(t3 + 8 * i); +- } +-} +- +- +-static void keccak_squeezeblocks4x(unsigned char *h0, +- unsigned char *h1, +- unsigned char *h2, +- unsigned char *h3, +- unsigned long long int nblocks, +- __m256i *s, +- unsigned int r) { +- unsigned int i; +- +- unsigned long long *ss = (unsigned long long *)s; +- +- while (nblocks > 0) { +- KeccakF1600_StatePermute4x(s); +- for (i = 0; i < (r >> 3); i++) { +- store64(h0 + 8 * i, ss[4 * i + 0]); +- store64(h1 + 8 * i, ss[4 * i + 1]); +- store64(h2 + 8 * i, ss[4 * i + 2]); +- store64(h3 + 8 * i, ss[4 * i + 3]); +- } +- h0 += r; +- h1 += r; +- h2 += r; +- h3 += r; +- nblocks--; +- } +-} +- +- +- +-void shake128x4(unsigned char *out0, +- unsigned char *out1, +- unsigned char *out2, +- unsigned char *out3, unsigned long long outlen, +- unsigned char *in0, +- unsigned char *in1, +- unsigned char *in2, +- unsigned char *in3, unsigned long long inlen) { +- __m256i s[25]; +- unsigned char t0[SHAKE128_RATE]; +- unsigned char t1[SHAKE128_RATE]; +- unsigned char t2[SHAKE128_RATE]; +- unsigned char t3[SHAKE128_RATE]; +- unsigned int i; +- +- /* zero state */ +- for (i = 0; i < 25; i++) { +- s[i] = _mm256_xor_si256(s[i], s[i]); +- } +- +- /* absorb 4 message of identical length in parallel */ +- keccak_absorb4x(s, SHAKE128_RATE, in0, in1, in2, in3, inlen, 0x1F); +- +- /* Squeeze output */ +- keccak_squeezeblocks4x(out0, out1, out2, out3, outlen / SHAKE128_RATE, s, SHAKE128_RATE); +- +- out0 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; +- out1 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; +- out2 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; +- out3 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; +- +- if (outlen % SHAKE128_RATE) { +- keccak_squeezeblocks4x(t0, t1, t2, t3, 1, s, SHAKE128_RATE); +- for (i = 0; i < outlen % SHAKE128_RATE; i++) { +- out0[i] = t0[i]; +- out1[i] = t1[i]; +- out2[i] = t2[i]; +- out3[i] = t3[i]; +- } +- } +-} +- +- +-void shake256x4(unsigned char *out0, +- unsigned char *out1, +- unsigned char *out2, +- unsigned char *out3, unsigned long long outlen, +- unsigned char *in0, +- unsigned char *in1, +- unsigned char *in2, +- unsigned char *in3, unsigned long long inlen) { +- __m256i s[25]; +- unsigned char t0[SHAKE256_RATE]; +- unsigned char t1[SHAKE256_RATE]; +- unsigned char t2[SHAKE256_RATE]; +- unsigned char t3[SHAKE256_RATE]; +- unsigned int i; +- +- /* zero state */ +- for (i = 0; i < 25; i++) { +- s[i] = _mm256_xor_si256(s[i], s[i]); +- } +- +- /* absorb 4 message of identical length in parallel */ +- keccak_absorb4x(s, SHAKE256_RATE, in0, in1, in2, in3, inlen, 0x1F); +- +- /* Squeeze output */ +- keccak_squeezeblocks4x(out0, out1, out2, out3, outlen / SHAKE256_RATE, s, SHAKE256_RATE); +- +- out0 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; +- out1 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; +- out2 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; +- out3 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; +- +- if (outlen % SHAKE256_RATE) { +- keccak_squeezeblocks4x(t0, t1, t2, t3, 1, s, SHAKE256_RATE); +- for (i = 0; i < outlen % SHAKE256_RATE; i++) { +- out0[i] = t0[i]; +- out1[i] = t1[i]; +- out2[i] = t2[i]; +- out3[i] = t3[i]; +- } +- } +-} +diff --git a/crypto_sign/sphincs-shake-128s-robust/avx2/fips202x4.h b/crypto_sign/sphincs-shake-128s-robust/avx2/fips202x4.h +deleted file mode 100644 +index 2b93c9c..0000000 +--- a/crypto_sign/sphincs-shake-128s-robust/avx2/fips202x4.h ++++ /dev/null +@@ -1,28 +0,0 @@ +-#ifndef SPX_FIPS202X4_H +-#define SPX_FIPS202X4_H +- +-#include +- +-#include "params.h" +- +-#define shake128x4 SPX_NAMESPACE(shake128x4) +-void shake128x4(unsigned char *out0, +- unsigned char *out1, +- unsigned char *out2, +- unsigned char *out3, unsigned long long outlen, +- unsigned char *in0, +- unsigned char *in1, +- unsigned char *in2, +- unsigned char *in3, unsigned long long inlen); +- +-#define shake256x4 SPX_NAMESPACE(shake256x4) +-void shake256x4(unsigned char *out0, +- unsigned char *out1, +- unsigned char *out2, +- unsigned char *out3, unsigned long long outlen, +- unsigned char *in0, +- unsigned char *in1, +- unsigned char *in2, +- unsigned char *in3, unsigned long long inlen); +- +-#endif +diff --git a/crypto_sign/sphincs-shake-128s-simple/avx2/fips202x4.c b/crypto_sign/sphincs-shake-128s-simple/avx2/fips202x4.c +deleted file mode 100644 +index 1e06fef..0000000 +--- a/crypto_sign/sphincs-shake-128s-simple/avx2/fips202x4.c ++++ /dev/null +@@ -1,210 +0,0 @@ +-#include +-#include +-#include +- +-#include "fips202.h" +-#include "fips202x4.h" +- +-#define NROUNDS 24 +-#define ROL(a, offset) (((a) << (offset)) ^ ((a) >> (64-(offset)))) +- +-static uint64_t load64(const unsigned char *x) { +- unsigned long long r = 0, i; +- +- for (i = 0; i < 8; ++i) { +- r |= (unsigned long long)x[i] << 8 * i; +- } +- return r; +-} +- +-static void store64(uint8_t *x, uint64_t u) { +- unsigned int i; +- +- for (i = 0; i < 8; ++i) { +- x[i] = (uint8_t)u; +- u >>= 8; +- } +-} +- +-/* Use implementation from the Keccak Code Package */ +-extern void KeccakP1600times4_PermuteAll_24rounds(__m256i *s); +-#define KeccakF1600_StatePermute4x KeccakP1600times4_PermuteAll_24rounds +- +-static void keccak_absorb4x(__m256i *s, +- unsigned int r, +- const unsigned char *m0, +- const unsigned char *m1, +- const unsigned char *m2, +- const unsigned char *m3, +- unsigned long long int mlen, +- unsigned char p) { +- unsigned long long i; +- unsigned char t0[200]; +- unsigned char t1[200]; +- unsigned char t2[200]; +- unsigned char t3[200]; +- +- unsigned long long *ss = (unsigned long long *)s; +- +- +- while (mlen >= r) { +- for (i = 0; i < r / 8; ++i) { +- ss[4 * i + 0] ^= load64(m0 + 8 * i); +- ss[4 * i + 1] ^= load64(m1 + 8 * i); +- ss[4 * i + 2] ^= load64(m2 + 8 * i); +- ss[4 * i + 3] ^= load64(m3 + 8 * i); +- } +- +- KeccakF1600_StatePermute4x(s); +- mlen -= r; +- m0 += r; +- m1 += r; +- m2 += r; +- m3 += r; +- } +- +- for (i = 0; i < r; ++i) { +- t0[i] = 0; +- t1[i] = 0; +- t2[i] = 0; +- t3[i] = 0; +- } +- for (i = 0; i < mlen; ++i) { +- t0[i] = m0[i]; +- t1[i] = m1[i]; +- t2[i] = m2[i]; +- t3[i] = m3[i]; +- } +- +- t0[i] = p; +- t1[i] = p; +- t2[i] = p; +- t3[i] = p; +- +- t0[r - 1] |= 128; +- t1[r - 1] |= 128; +- t2[r - 1] |= 128; +- t3[r - 1] |= 128; +- +- for (i = 0; i < r / 8; ++i) { +- ss[4 * i + 0] ^= load64(t0 + 8 * i); +- ss[4 * i + 1] ^= load64(t1 + 8 * i); +- ss[4 * i + 2] ^= load64(t2 + 8 * i); +- ss[4 * i + 3] ^= load64(t3 + 8 * i); +- } +-} +- +- +-static void keccak_squeezeblocks4x(unsigned char *h0, +- unsigned char *h1, +- unsigned char *h2, +- unsigned char *h3, +- unsigned long long int nblocks, +- __m256i *s, +- unsigned int r) { +- unsigned int i; +- +- unsigned long long *ss = (unsigned long long *)s; +- +- while (nblocks > 0) { +- KeccakF1600_StatePermute4x(s); +- for (i = 0; i < (r >> 3); i++) { +- store64(h0 + 8 * i, ss[4 * i + 0]); +- store64(h1 + 8 * i, ss[4 * i + 1]); +- store64(h2 + 8 * i, ss[4 * i + 2]); +- store64(h3 + 8 * i, ss[4 * i + 3]); +- } +- h0 += r; +- h1 += r; +- h2 += r; +- h3 += r; +- nblocks--; +- } +-} +- +- +- +-void shake128x4(unsigned char *out0, +- unsigned char *out1, +- unsigned char *out2, +- unsigned char *out3, unsigned long long outlen, +- unsigned char *in0, +- unsigned char *in1, +- unsigned char *in2, +- unsigned char *in3, unsigned long long inlen) { +- __m256i s[25]; +- unsigned char t0[SHAKE128_RATE]; +- unsigned char t1[SHAKE128_RATE]; +- unsigned char t2[SHAKE128_RATE]; +- unsigned char t3[SHAKE128_RATE]; +- unsigned int i; +- +- /* zero state */ +- for (i = 0; i < 25; i++) { +- s[i] = _mm256_xor_si256(s[i], s[i]); +- } +- +- /* absorb 4 message of identical length in parallel */ +- keccak_absorb4x(s, SHAKE128_RATE, in0, in1, in2, in3, inlen, 0x1F); +- +- /* Squeeze output */ +- keccak_squeezeblocks4x(out0, out1, out2, out3, outlen / SHAKE128_RATE, s, SHAKE128_RATE); +- +- out0 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; +- out1 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; +- out2 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; +- out3 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; +- +- if (outlen % SHAKE128_RATE) { +- keccak_squeezeblocks4x(t0, t1, t2, t3, 1, s, SHAKE128_RATE); +- for (i = 0; i < outlen % SHAKE128_RATE; i++) { +- out0[i] = t0[i]; +- out1[i] = t1[i]; +- out2[i] = t2[i]; +- out3[i] = t3[i]; +- } +- } +-} +- +- +-void shake256x4(unsigned char *out0, +- unsigned char *out1, +- unsigned char *out2, +- unsigned char *out3, unsigned long long outlen, +- unsigned char *in0, +- unsigned char *in1, +- unsigned char *in2, +- unsigned char *in3, unsigned long long inlen) { +- __m256i s[25]; +- unsigned char t0[SHAKE256_RATE]; +- unsigned char t1[SHAKE256_RATE]; +- unsigned char t2[SHAKE256_RATE]; +- unsigned char t3[SHAKE256_RATE]; +- unsigned int i; +- +- /* zero state */ +- for (i = 0; i < 25; i++) { +- s[i] = _mm256_xor_si256(s[i], s[i]); +- } +- +- /* absorb 4 message of identical length in parallel */ +- keccak_absorb4x(s, SHAKE256_RATE, in0, in1, in2, in3, inlen, 0x1F); +- +- /* Squeeze output */ +- keccak_squeezeblocks4x(out0, out1, out2, out3, outlen / SHAKE256_RATE, s, SHAKE256_RATE); +- +- out0 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; +- out1 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; +- out2 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; +- out3 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; +- +- if (outlen % SHAKE256_RATE) { +- keccak_squeezeblocks4x(t0, t1, t2, t3, 1, s, SHAKE256_RATE); +- for (i = 0; i < outlen % SHAKE256_RATE; i++) { +- out0[i] = t0[i]; +- out1[i] = t1[i]; +- out2[i] = t2[i]; +- out3[i] = t3[i]; +- } +- } +-} +diff --git a/crypto_sign/sphincs-shake-128s-simple/avx2/fips202x4.h b/crypto_sign/sphincs-shake-128s-simple/avx2/fips202x4.h +deleted file mode 100644 +index 2b93c9c..0000000 +--- a/crypto_sign/sphincs-shake-128s-simple/avx2/fips202x4.h ++++ /dev/null +@@ -1,28 +0,0 @@ +-#ifndef SPX_FIPS202X4_H +-#define SPX_FIPS202X4_H +- +-#include +- +-#include "params.h" +- +-#define shake128x4 SPX_NAMESPACE(shake128x4) +-void shake128x4(unsigned char *out0, +- unsigned char *out1, +- unsigned char *out2, +- unsigned char *out3, unsigned long long outlen, +- unsigned char *in0, +- unsigned char *in1, +- unsigned char *in2, +- unsigned char *in3, unsigned long long inlen); +- +-#define shake256x4 SPX_NAMESPACE(shake256x4) +-void shake256x4(unsigned char *out0, +- unsigned char *out1, +- unsigned char *out2, +- unsigned char *out3, unsigned long long outlen, +- unsigned char *in0, +- unsigned char *in1, +- unsigned char *in2, +- unsigned char *in3, unsigned long long inlen); +- +-#endif +diff --git a/crypto_sign/sphincs-shake-192f-robust/avx2/fips202x4.c b/crypto_sign/sphincs-shake-192f-robust/avx2/fips202x4.c +deleted file mode 100644 +index 1e06fef..0000000 +--- a/crypto_sign/sphincs-shake-192f-robust/avx2/fips202x4.c ++++ /dev/null +@@ -1,210 +0,0 @@ +-#include +-#include +-#include +- +-#include "fips202.h" +-#include "fips202x4.h" +- +-#define NROUNDS 24 +-#define ROL(a, offset) (((a) << (offset)) ^ ((a) >> (64-(offset)))) +- +-static uint64_t load64(const unsigned char *x) { +- unsigned long long r = 0, i; +- +- for (i = 0; i < 8; ++i) { +- r |= (unsigned long long)x[i] << 8 * i; +- } +- return r; +-} +- +-static void store64(uint8_t *x, uint64_t u) { +- unsigned int i; +- +- for (i = 0; i < 8; ++i) { +- x[i] = (uint8_t)u; +- u >>= 8; +- } +-} +- +-/* Use implementation from the Keccak Code Package */ +-extern void KeccakP1600times4_PermuteAll_24rounds(__m256i *s); +-#define KeccakF1600_StatePermute4x KeccakP1600times4_PermuteAll_24rounds +- +-static void keccak_absorb4x(__m256i *s, +- unsigned int r, +- const unsigned char *m0, +- const unsigned char *m1, +- const unsigned char *m2, +- const unsigned char *m3, +- unsigned long long int mlen, +- unsigned char p) { +- unsigned long long i; +- unsigned char t0[200]; +- unsigned char t1[200]; +- unsigned char t2[200]; +- unsigned char t3[200]; +- +- unsigned long long *ss = (unsigned long long *)s; +- +- +- while (mlen >= r) { +- for (i = 0; i < r / 8; ++i) { +- ss[4 * i + 0] ^= load64(m0 + 8 * i); +- ss[4 * i + 1] ^= load64(m1 + 8 * i); +- ss[4 * i + 2] ^= load64(m2 + 8 * i); +- ss[4 * i + 3] ^= load64(m3 + 8 * i); +- } +- +- KeccakF1600_StatePermute4x(s); +- mlen -= r; +- m0 += r; +- m1 += r; +- m2 += r; +- m3 += r; +- } +- +- for (i = 0; i < r; ++i) { +- t0[i] = 0; +- t1[i] = 0; +- t2[i] = 0; +- t3[i] = 0; +- } +- for (i = 0; i < mlen; ++i) { +- t0[i] = m0[i]; +- t1[i] = m1[i]; +- t2[i] = m2[i]; +- t3[i] = m3[i]; +- } +- +- t0[i] = p; +- t1[i] = p; +- t2[i] = p; +- t3[i] = p; +- +- t0[r - 1] |= 128; +- t1[r - 1] |= 128; +- t2[r - 1] |= 128; +- t3[r - 1] |= 128; +- +- for (i = 0; i < r / 8; ++i) { +- ss[4 * i + 0] ^= load64(t0 + 8 * i); +- ss[4 * i + 1] ^= load64(t1 + 8 * i); +- ss[4 * i + 2] ^= load64(t2 + 8 * i); +- ss[4 * i + 3] ^= load64(t3 + 8 * i); +- } +-} +- +- +-static void keccak_squeezeblocks4x(unsigned char *h0, +- unsigned char *h1, +- unsigned char *h2, +- unsigned char *h3, +- unsigned long long int nblocks, +- __m256i *s, +- unsigned int r) { +- unsigned int i; +- +- unsigned long long *ss = (unsigned long long *)s; +- +- while (nblocks > 0) { +- KeccakF1600_StatePermute4x(s); +- for (i = 0; i < (r >> 3); i++) { +- store64(h0 + 8 * i, ss[4 * i + 0]); +- store64(h1 + 8 * i, ss[4 * i + 1]); +- store64(h2 + 8 * i, ss[4 * i + 2]); +- store64(h3 + 8 * i, ss[4 * i + 3]); +- } +- h0 += r; +- h1 += r; +- h2 += r; +- h3 += r; +- nblocks--; +- } +-} +- +- +- +-void shake128x4(unsigned char *out0, +- unsigned char *out1, +- unsigned char *out2, +- unsigned char *out3, unsigned long long outlen, +- unsigned char *in0, +- unsigned char *in1, +- unsigned char *in2, +- unsigned char *in3, unsigned long long inlen) { +- __m256i s[25]; +- unsigned char t0[SHAKE128_RATE]; +- unsigned char t1[SHAKE128_RATE]; +- unsigned char t2[SHAKE128_RATE]; +- unsigned char t3[SHAKE128_RATE]; +- unsigned int i; +- +- /* zero state */ +- for (i = 0; i < 25; i++) { +- s[i] = _mm256_xor_si256(s[i], s[i]); +- } +- +- /* absorb 4 message of identical length in parallel */ +- keccak_absorb4x(s, SHAKE128_RATE, in0, in1, in2, in3, inlen, 0x1F); +- +- /* Squeeze output */ +- keccak_squeezeblocks4x(out0, out1, out2, out3, outlen / SHAKE128_RATE, s, SHAKE128_RATE); +- +- out0 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; +- out1 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; +- out2 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; +- out3 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; +- +- if (outlen % SHAKE128_RATE) { +- keccak_squeezeblocks4x(t0, t1, t2, t3, 1, s, SHAKE128_RATE); +- for (i = 0; i < outlen % SHAKE128_RATE; i++) { +- out0[i] = t0[i]; +- out1[i] = t1[i]; +- out2[i] = t2[i]; +- out3[i] = t3[i]; +- } +- } +-} +- +- +-void shake256x4(unsigned char *out0, +- unsigned char *out1, +- unsigned char *out2, +- unsigned char *out3, unsigned long long outlen, +- unsigned char *in0, +- unsigned char *in1, +- unsigned char *in2, +- unsigned char *in3, unsigned long long inlen) { +- __m256i s[25]; +- unsigned char t0[SHAKE256_RATE]; +- unsigned char t1[SHAKE256_RATE]; +- unsigned char t2[SHAKE256_RATE]; +- unsigned char t3[SHAKE256_RATE]; +- unsigned int i; +- +- /* zero state */ +- for (i = 0; i < 25; i++) { +- s[i] = _mm256_xor_si256(s[i], s[i]); +- } +- +- /* absorb 4 message of identical length in parallel */ +- keccak_absorb4x(s, SHAKE256_RATE, in0, in1, in2, in3, inlen, 0x1F); +- +- /* Squeeze output */ +- keccak_squeezeblocks4x(out0, out1, out2, out3, outlen / SHAKE256_RATE, s, SHAKE256_RATE); +- +- out0 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; +- out1 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; +- out2 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; +- out3 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; +- +- if (outlen % SHAKE256_RATE) { +- keccak_squeezeblocks4x(t0, t1, t2, t3, 1, s, SHAKE256_RATE); +- for (i = 0; i < outlen % SHAKE256_RATE; i++) { +- out0[i] = t0[i]; +- out1[i] = t1[i]; +- out2[i] = t2[i]; +- out3[i] = t3[i]; +- } +- } +-} +diff --git a/crypto_sign/sphincs-shake-192f-robust/avx2/fips202x4.h b/crypto_sign/sphincs-shake-192f-robust/avx2/fips202x4.h +deleted file mode 100644 +index 2b93c9c..0000000 +--- a/crypto_sign/sphincs-shake-192f-robust/avx2/fips202x4.h ++++ /dev/null +@@ -1,28 +0,0 @@ +-#ifndef SPX_FIPS202X4_H +-#define SPX_FIPS202X4_H +- +-#include +- +-#include "params.h" +- +-#define shake128x4 SPX_NAMESPACE(shake128x4) +-void shake128x4(unsigned char *out0, +- unsigned char *out1, +- unsigned char *out2, +- unsigned char *out3, unsigned long long outlen, +- unsigned char *in0, +- unsigned char *in1, +- unsigned char *in2, +- unsigned char *in3, unsigned long long inlen); +- +-#define shake256x4 SPX_NAMESPACE(shake256x4) +-void shake256x4(unsigned char *out0, +- unsigned char *out1, +- unsigned char *out2, +- unsigned char *out3, unsigned long long outlen, +- unsigned char *in0, +- unsigned char *in1, +- unsigned char *in2, +- unsigned char *in3, unsigned long long inlen); +- +-#endif +diff --git a/crypto_sign/sphincs-shake-192f-simple/avx2/fips202x4.c b/crypto_sign/sphincs-shake-192f-simple/avx2/fips202x4.c +deleted file mode 100644 +index 1e06fef..0000000 +--- a/crypto_sign/sphincs-shake-192f-simple/avx2/fips202x4.c ++++ /dev/null +@@ -1,210 +0,0 @@ +-#include +-#include +-#include +- +-#include "fips202.h" +-#include "fips202x4.h" +- +-#define NROUNDS 24 +-#define ROL(a, offset) (((a) << (offset)) ^ ((a) >> (64-(offset)))) +- +-static uint64_t load64(const unsigned char *x) { +- unsigned long long r = 0, i; +- +- for (i = 0; i < 8; ++i) { +- r |= (unsigned long long)x[i] << 8 * i; +- } +- return r; +-} +- +-static void store64(uint8_t *x, uint64_t u) { +- unsigned int i; +- +- for (i = 0; i < 8; ++i) { +- x[i] = (uint8_t)u; +- u >>= 8; +- } +-} +- +-/* Use implementation from the Keccak Code Package */ +-extern void KeccakP1600times4_PermuteAll_24rounds(__m256i *s); +-#define KeccakF1600_StatePermute4x KeccakP1600times4_PermuteAll_24rounds +- +-static void keccak_absorb4x(__m256i *s, +- unsigned int r, +- const unsigned char *m0, +- const unsigned char *m1, +- const unsigned char *m2, +- const unsigned char *m3, +- unsigned long long int mlen, +- unsigned char p) { +- unsigned long long i; +- unsigned char t0[200]; +- unsigned char t1[200]; +- unsigned char t2[200]; +- unsigned char t3[200]; +- +- unsigned long long *ss = (unsigned long long *)s; +- +- +- while (mlen >= r) { +- for (i = 0; i < r / 8; ++i) { +- ss[4 * i + 0] ^= load64(m0 + 8 * i); +- ss[4 * i + 1] ^= load64(m1 + 8 * i); +- ss[4 * i + 2] ^= load64(m2 + 8 * i); +- ss[4 * i + 3] ^= load64(m3 + 8 * i); +- } +- +- KeccakF1600_StatePermute4x(s); +- mlen -= r; +- m0 += r; +- m1 += r; +- m2 += r; +- m3 += r; +- } +- +- for (i = 0; i < r; ++i) { +- t0[i] = 0; +- t1[i] = 0; +- t2[i] = 0; +- t3[i] = 0; +- } +- for (i = 0; i < mlen; ++i) { +- t0[i] = m0[i]; +- t1[i] = m1[i]; +- t2[i] = m2[i]; +- t3[i] = m3[i]; +- } +- +- t0[i] = p; +- t1[i] = p; +- t2[i] = p; +- t3[i] = p; +- +- t0[r - 1] |= 128; +- t1[r - 1] |= 128; +- t2[r - 1] |= 128; +- t3[r - 1] |= 128; +- +- for (i = 0; i < r / 8; ++i) { +- ss[4 * i + 0] ^= load64(t0 + 8 * i); +- ss[4 * i + 1] ^= load64(t1 + 8 * i); +- ss[4 * i + 2] ^= load64(t2 + 8 * i); +- ss[4 * i + 3] ^= load64(t3 + 8 * i); +- } +-} +- +- +-static void keccak_squeezeblocks4x(unsigned char *h0, +- unsigned char *h1, +- unsigned char *h2, +- unsigned char *h3, +- unsigned long long int nblocks, +- __m256i *s, +- unsigned int r) { +- unsigned int i; +- +- unsigned long long *ss = (unsigned long long *)s; +- +- while (nblocks > 0) { +- KeccakF1600_StatePermute4x(s); +- for (i = 0; i < (r >> 3); i++) { +- store64(h0 + 8 * i, ss[4 * i + 0]); +- store64(h1 + 8 * i, ss[4 * i + 1]); +- store64(h2 + 8 * i, ss[4 * i + 2]); +- store64(h3 + 8 * i, ss[4 * i + 3]); +- } +- h0 += r; +- h1 += r; +- h2 += r; +- h3 += r; +- nblocks--; +- } +-} +- +- +- +-void shake128x4(unsigned char *out0, +- unsigned char *out1, +- unsigned char *out2, +- unsigned char *out3, unsigned long long outlen, +- unsigned char *in0, +- unsigned char *in1, +- unsigned char *in2, +- unsigned char *in3, unsigned long long inlen) { +- __m256i s[25]; +- unsigned char t0[SHAKE128_RATE]; +- unsigned char t1[SHAKE128_RATE]; +- unsigned char t2[SHAKE128_RATE]; +- unsigned char t3[SHAKE128_RATE]; +- unsigned int i; +- +- /* zero state */ +- for (i = 0; i < 25; i++) { +- s[i] = _mm256_xor_si256(s[i], s[i]); +- } +- +- /* absorb 4 message of identical length in parallel */ +- keccak_absorb4x(s, SHAKE128_RATE, in0, in1, in2, in3, inlen, 0x1F); +- +- /* Squeeze output */ +- keccak_squeezeblocks4x(out0, out1, out2, out3, outlen / SHAKE128_RATE, s, SHAKE128_RATE); +- +- out0 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; +- out1 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; +- out2 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; +- out3 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; +- +- if (outlen % SHAKE128_RATE) { +- keccak_squeezeblocks4x(t0, t1, t2, t3, 1, s, SHAKE128_RATE); +- for (i = 0; i < outlen % SHAKE128_RATE; i++) { +- out0[i] = t0[i]; +- out1[i] = t1[i]; +- out2[i] = t2[i]; +- out3[i] = t3[i]; +- } +- } +-} +- +- +-void shake256x4(unsigned char *out0, +- unsigned char *out1, +- unsigned char *out2, +- unsigned char *out3, unsigned long long outlen, +- unsigned char *in0, +- unsigned char *in1, +- unsigned char *in2, +- unsigned char *in3, unsigned long long inlen) { +- __m256i s[25]; +- unsigned char t0[SHAKE256_RATE]; +- unsigned char t1[SHAKE256_RATE]; +- unsigned char t2[SHAKE256_RATE]; +- unsigned char t3[SHAKE256_RATE]; +- unsigned int i; +- +- /* zero state */ +- for (i = 0; i < 25; i++) { +- s[i] = _mm256_xor_si256(s[i], s[i]); +- } +- +- /* absorb 4 message of identical length in parallel */ +- keccak_absorb4x(s, SHAKE256_RATE, in0, in1, in2, in3, inlen, 0x1F); +- +- /* Squeeze output */ +- keccak_squeezeblocks4x(out0, out1, out2, out3, outlen / SHAKE256_RATE, s, SHAKE256_RATE); +- +- out0 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; +- out1 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; +- out2 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; +- out3 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; +- +- if (outlen % SHAKE256_RATE) { +- keccak_squeezeblocks4x(t0, t1, t2, t3, 1, s, SHAKE256_RATE); +- for (i = 0; i < outlen % SHAKE256_RATE; i++) { +- out0[i] = t0[i]; +- out1[i] = t1[i]; +- out2[i] = t2[i]; +- out3[i] = t3[i]; +- } +- } +-} +diff --git a/crypto_sign/sphincs-shake-192f-simple/avx2/fips202x4.h b/crypto_sign/sphincs-shake-192f-simple/avx2/fips202x4.h +deleted file mode 100644 +index 2b93c9c..0000000 +--- a/crypto_sign/sphincs-shake-192f-simple/avx2/fips202x4.h ++++ /dev/null +@@ -1,28 +0,0 @@ +-#ifndef SPX_FIPS202X4_H +-#define SPX_FIPS202X4_H +- +-#include +- +-#include "params.h" +- +-#define shake128x4 SPX_NAMESPACE(shake128x4) +-void shake128x4(unsigned char *out0, +- unsigned char *out1, +- unsigned char *out2, +- unsigned char *out3, unsigned long long outlen, +- unsigned char *in0, +- unsigned char *in1, +- unsigned char *in2, +- unsigned char *in3, unsigned long long inlen); +- +-#define shake256x4 SPX_NAMESPACE(shake256x4) +-void shake256x4(unsigned char *out0, +- unsigned char *out1, +- unsigned char *out2, +- unsigned char *out3, unsigned long long outlen, +- unsigned char *in0, +- unsigned char *in1, +- unsigned char *in2, +- unsigned char *in3, unsigned long long inlen); +- +-#endif +diff --git a/crypto_sign/sphincs-shake-192s-robust/avx2/fips202x4.c b/crypto_sign/sphincs-shake-192s-robust/avx2/fips202x4.c +deleted file mode 100644 +index 1e06fef..0000000 +--- a/crypto_sign/sphincs-shake-192s-robust/avx2/fips202x4.c ++++ /dev/null +@@ -1,210 +0,0 @@ +-#include +-#include +-#include +- +-#include "fips202.h" +-#include "fips202x4.h" +- +-#define NROUNDS 24 +-#define ROL(a, offset) (((a) << (offset)) ^ ((a) >> (64-(offset)))) +- +-static uint64_t load64(const unsigned char *x) { +- unsigned long long r = 0, i; +- +- for (i = 0; i < 8; ++i) { +- r |= (unsigned long long)x[i] << 8 * i; +- } +- return r; +-} +- +-static void store64(uint8_t *x, uint64_t u) { +- unsigned int i; +- +- for (i = 0; i < 8; ++i) { +- x[i] = (uint8_t)u; +- u >>= 8; +- } +-} +- +-/* Use implementation from the Keccak Code Package */ +-extern void KeccakP1600times4_PermuteAll_24rounds(__m256i *s); +-#define KeccakF1600_StatePermute4x KeccakP1600times4_PermuteAll_24rounds +- +-static void keccak_absorb4x(__m256i *s, +- unsigned int r, +- const unsigned char *m0, +- const unsigned char *m1, +- const unsigned char *m2, +- const unsigned char *m3, +- unsigned long long int mlen, +- unsigned char p) { +- unsigned long long i; +- unsigned char t0[200]; +- unsigned char t1[200]; +- unsigned char t2[200]; +- unsigned char t3[200]; +- +- unsigned long long *ss = (unsigned long long *)s; +- +- +- while (mlen >= r) { +- for (i = 0; i < r / 8; ++i) { +- ss[4 * i + 0] ^= load64(m0 + 8 * i); +- ss[4 * i + 1] ^= load64(m1 + 8 * i); +- ss[4 * i + 2] ^= load64(m2 + 8 * i); +- ss[4 * i + 3] ^= load64(m3 + 8 * i); +- } +- +- KeccakF1600_StatePermute4x(s); +- mlen -= r; +- m0 += r; +- m1 += r; +- m2 += r; +- m3 += r; +- } +- +- for (i = 0; i < r; ++i) { +- t0[i] = 0; +- t1[i] = 0; +- t2[i] = 0; +- t3[i] = 0; +- } +- for (i = 0; i < mlen; ++i) { +- t0[i] = m0[i]; +- t1[i] = m1[i]; +- t2[i] = m2[i]; +- t3[i] = m3[i]; +- } +- +- t0[i] = p; +- t1[i] = p; +- t2[i] = p; +- t3[i] = p; +- +- t0[r - 1] |= 128; +- t1[r - 1] |= 128; +- t2[r - 1] |= 128; +- t3[r - 1] |= 128; +- +- for (i = 0; i < r / 8; ++i) { +- ss[4 * i + 0] ^= load64(t0 + 8 * i); +- ss[4 * i + 1] ^= load64(t1 + 8 * i); +- ss[4 * i + 2] ^= load64(t2 + 8 * i); +- ss[4 * i + 3] ^= load64(t3 + 8 * i); +- } +-} +- +- +-static void keccak_squeezeblocks4x(unsigned char *h0, +- unsigned char *h1, +- unsigned char *h2, +- unsigned char *h3, +- unsigned long long int nblocks, +- __m256i *s, +- unsigned int r) { +- unsigned int i; +- +- unsigned long long *ss = (unsigned long long *)s; +- +- while (nblocks > 0) { +- KeccakF1600_StatePermute4x(s); +- for (i = 0; i < (r >> 3); i++) { +- store64(h0 + 8 * i, ss[4 * i + 0]); +- store64(h1 + 8 * i, ss[4 * i + 1]); +- store64(h2 + 8 * i, ss[4 * i + 2]); +- store64(h3 + 8 * i, ss[4 * i + 3]); +- } +- h0 += r; +- h1 += r; +- h2 += r; +- h3 += r; +- nblocks--; +- } +-} +- +- +- +-void shake128x4(unsigned char *out0, +- unsigned char *out1, +- unsigned char *out2, +- unsigned char *out3, unsigned long long outlen, +- unsigned char *in0, +- unsigned char *in1, +- unsigned char *in2, +- unsigned char *in3, unsigned long long inlen) { +- __m256i s[25]; +- unsigned char t0[SHAKE128_RATE]; +- unsigned char t1[SHAKE128_RATE]; +- unsigned char t2[SHAKE128_RATE]; +- unsigned char t3[SHAKE128_RATE]; +- unsigned int i; +- +- /* zero state */ +- for (i = 0; i < 25; i++) { +- s[i] = _mm256_xor_si256(s[i], s[i]); +- } +- +- /* absorb 4 message of identical length in parallel */ +- keccak_absorb4x(s, SHAKE128_RATE, in0, in1, in2, in3, inlen, 0x1F); +- +- /* Squeeze output */ +- keccak_squeezeblocks4x(out0, out1, out2, out3, outlen / SHAKE128_RATE, s, SHAKE128_RATE); +- +- out0 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; +- out1 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; +- out2 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; +- out3 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; +- +- if (outlen % SHAKE128_RATE) { +- keccak_squeezeblocks4x(t0, t1, t2, t3, 1, s, SHAKE128_RATE); +- for (i = 0; i < outlen % SHAKE128_RATE; i++) { +- out0[i] = t0[i]; +- out1[i] = t1[i]; +- out2[i] = t2[i]; +- out3[i] = t3[i]; +- } +- } +-} +- +- +-void shake256x4(unsigned char *out0, +- unsigned char *out1, +- unsigned char *out2, +- unsigned char *out3, unsigned long long outlen, +- unsigned char *in0, +- unsigned char *in1, +- unsigned char *in2, +- unsigned char *in3, unsigned long long inlen) { +- __m256i s[25]; +- unsigned char t0[SHAKE256_RATE]; +- unsigned char t1[SHAKE256_RATE]; +- unsigned char t2[SHAKE256_RATE]; +- unsigned char t3[SHAKE256_RATE]; +- unsigned int i; +- +- /* zero state */ +- for (i = 0; i < 25; i++) { +- s[i] = _mm256_xor_si256(s[i], s[i]); +- } +- +- /* absorb 4 message of identical length in parallel */ +- keccak_absorb4x(s, SHAKE256_RATE, in0, in1, in2, in3, inlen, 0x1F); +- +- /* Squeeze output */ +- keccak_squeezeblocks4x(out0, out1, out2, out3, outlen / SHAKE256_RATE, s, SHAKE256_RATE); +- +- out0 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; +- out1 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; +- out2 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; +- out3 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; +- +- if (outlen % SHAKE256_RATE) { +- keccak_squeezeblocks4x(t0, t1, t2, t3, 1, s, SHAKE256_RATE); +- for (i = 0; i < outlen % SHAKE256_RATE; i++) { +- out0[i] = t0[i]; +- out1[i] = t1[i]; +- out2[i] = t2[i]; +- out3[i] = t3[i]; +- } +- } +-} +diff --git a/crypto_sign/sphincs-shake-192s-robust/avx2/fips202x4.h b/crypto_sign/sphincs-shake-192s-robust/avx2/fips202x4.h +deleted file mode 100644 +index 2b93c9c..0000000 +--- a/crypto_sign/sphincs-shake-192s-robust/avx2/fips202x4.h ++++ /dev/null +@@ -1,28 +0,0 @@ +-#ifndef SPX_FIPS202X4_H +-#define SPX_FIPS202X4_H +- +-#include +- +-#include "params.h" +- +-#define shake128x4 SPX_NAMESPACE(shake128x4) +-void shake128x4(unsigned char *out0, +- unsigned char *out1, +- unsigned char *out2, +- unsigned char *out3, unsigned long long outlen, +- unsigned char *in0, +- unsigned char *in1, +- unsigned char *in2, +- unsigned char *in3, unsigned long long inlen); +- +-#define shake256x4 SPX_NAMESPACE(shake256x4) +-void shake256x4(unsigned char *out0, +- unsigned char *out1, +- unsigned char *out2, +- unsigned char *out3, unsigned long long outlen, +- unsigned char *in0, +- unsigned char *in1, +- unsigned char *in2, +- unsigned char *in3, unsigned long long inlen); +- +-#endif +diff --git a/crypto_sign/sphincs-shake-192s-simple/avx2/fips202x4.c b/crypto_sign/sphincs-shake-192s-simple/avx2/fips202x4.c +deleted file mode 100644 +index 1e06fef..0000000 +--- a/crypto_sign/sphincs-shake-192s-simple/avx2/fips202x4.c ++++ /dev/null +@@ -1,210 +0,0 @@ +-#include +-#include +-#include +- +-#include "fips202.h" +-#include "fips202x4.h" +- +-#define NROUNDS 24 +-#define ROL(a, offset) (((a) << (offset)) ^ ((a) >> (64-(offset)))) +- +-static uint64_t load64(const unsigned char *x) { +- unsigned long long r = 0, i; +- +- for (i = 0; i < 8; ++i) { +- r |= (unsigned long long)x[i] << 8 * i; +- } +- return r; +-} +- +-static void store64(uint8_t *x, uint64_t u) { +- unsigned int i; +- +- for (i = 0; i < 8; ++i) { +- x[i] = (uint8_t)u; +- u >>= 8; +- } +-} +- +-/* Use implementation from the Keccak Code Package */ +-extern void KeccakP1600times4_PermuteAll_24rounds(__m256i *s); +-#define KeccakF1600_StatePermute4x KeccakP1600times4_PermuteAll_24rounds +- +-static void keccak_absorb4x(__m256i *s, +- unsigned int r, +- const unsigned char *m0, +- const unsigned char *m1, +- const unsigned char *m2, +- const unsigned char *m3, +- unsigned long long int mlen, +- unsigned char p) { +- unsigned long long i; +- unsigned char t0[200]; +- unsigned char t1[200]; +- unsigned char t2[200]; +- unsigned char t3[200]; +- +- unsigned long long *ss = (unsigned long long *)s; +- +- +- while (mlen >= r) { +- for (i = 0; i < r / 8; ++i) { +- ss[4 * i + 0] ^= load64(m0 + 8 * i); +- ss[4 * i + 1] ^= load64(m1 + 8 * i); +- ss[4 * i + 2] ^= load64(m2 + 8 * i); +- ss[4 * i + 3] ^= load64(m3 + 8 * i); +- } +- +- KeccakF1600_StatePermute4x(s); +- mlen -= r; +- m0 += r; +- m1 += r; +- m2 += r; +- m3 += r; +- } +- +- for (i = 0; i < r; ++i) { +- t0[i] = 0; +- t1[i] = 0; +- t2[i] = 0; +- t3[i] = 0; +- } +- for (i = 0; i < mlen; ++i) { +- t0[i] = m0[i]; +- t1[i] = m1[i]; +- t2[i] = m2[i]; +- t3[i] = m3[i]; +- } +- +- t0[i] = p; +- t1[i] = p; +- t2[i] = p; +- t3[i] = p; +- +- t0[r - 1] |= 128; +- t1[r - 1] |= 128; +- t2[r - 1] |= 128; +- t3[r - 1] |= 128; +- +- for (i = 0; i < r / 8; ++i) { +- ss[4 * i + 0] ^= load64(t0 + 8 * i); +- ss[4 * i + 1] ^= load64(t1 + 8 * i); +- ss[4 * i + 2] ^= load64(t2 + 8 * i); +- ss[4 * i + 3] ^= load64(t3 + 8 * i); +- } +-} +- +- +-static void keccak_squeezeblocks4x(unsigned char *h0, +- unsigned char *h1, +- unsigned char *h2, +- unsigned char *h3, +- unsigned long long int nblocks, +- __m256i *s, +- unsigned int r) { +- unsigned int i; +- +- unsigned long long *ss = (unsigned long long *)s; +- +- while (nblocks > 0) { +- KeccakF1600_StatePermute4x(s); +- for (i = 0; i < (r >> 3); i++) { +- store64(h0 + 8 * i, ss[4 * i + 0]); +- store64(h1 + 8 * i, ss[4 * i + 1]); +- store64(h2 + 8 * i, ss[4 * i + 2]); +- store64(h3 + 8 * i, ss[4 * i + 3]); +- } +- h0 += r; +- h1 += r; +- h2 += r; +- h3 += r; +- nblocks--; +- } +-} +- +- +- +-void shake128x4(unsigned char *out0, +- unsigned char *out1, +- unsigned char *out2, +- unsigned char *out3, unsigned long long outlen, +- unsigned char *in0, +- unsigned char *in1, +- unsigned char *in2, +- unsigned char *in3, unsigned long long inlen) { +- __m256i s[25]; +- unsigned char t0[SHAKE128_RATE]; +- unsigned char t1[SHAKE128_RATE]; +- unsigned char t2[SHAKE128_RATE]; +- unsigned char t3[SHAKE128_RATE]; +- unsigned int i; +- +- /* zero state */ +- for (i = 0; i < 25; i++) { +- s[i] = _mm256_xor_si256(s[i], s[i]); +- } +- +- /* absorb 4 message of identical length in parallel */ +- keccak_absorb4x(s, SHAKE128_RATE, in0, in1, in2, in3, inlen, 0x1F); +- +- /* Squeeze output */ +- keccak_squeezeblocks4x(out0, out1, out2, out3, outlen / SHAKE128_RATE, s, SHAKE128_RATE); +- +- out0 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; +- out1 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; +- out2 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; +- out3 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; +- +- if (outlen % SHAKE128_RATE) { +- keccak_squeezeblocks4x(t0, t1, t2, t3, 1, s, SHAKE128_RATE); +- for (i = 0; i < outlen % SHAKE128_RATE; i++) { +- out0[i] = t0[i]; +- out1[i] = t1[i]; +- out2[i] = t2[i]; +- out3[i] = t3[i]; +- } +- } +-} +- +- +-void shake256x4(unsigned char *out0, +- unsigned char *out1, +- unsigned char *out2, +- unsigned char *out3, unsigned long long outlen, +- unsigned char *in0, +- unsigned char *in1, +- unsigned char *in2, +- unsigned char *in3, unsigned long long inlen) { +- __m256i s[25]; +- unsigned char t0[SHAKE256_RATE]; +- unsigned char t1[SHAKE256_RATE]; +- unsigned char t2[SHAKE256_RATE]; +- unsigned char t3[SHAKE256_RATE]; +- unsigned int i; +- +- /* zero state */ +- for (i = 0; i < 25; i++) { +- s[i] = _mm256_xor_si256(s[i], s[i]); +- } +- +- /* absorb 4 message of identical length in parallel */ +- keccak_absorb4x(s, SHAKE256_RATE, in0, in1, in2, in3, inlen, 0x1F); +- +- /* Squeeze output */ +- keccak_squeezeblocks4x(out0, out1, out2, out3, outlen / SHAKE256_RATE, s, SHAKE256_RATE); +- +- out0 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; +- out1 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; +- out2 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; +- out3 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; +- +- if (outlen % SHAKE256_RATE) { +- keccak_squeezeblocks4x(t0, t1, t2, t3, 1, s, SHAKE256_RATE); +- for (i = 0; i < outlen % SHAKE256_RATE; i++) { +- out0[i] = t0[i]; +- out1[i] = t1[i]; +- out2[i] = t2[i]; +- out3[i] = t3[i]; +- } +- } +-} +diff --git a/crypto_sign/sphincs-shake-192s-simple/avx2/fips202x4.h b/crypto_sign/sphincs-shake-192s-simple/avx2/fips202x4.h +deleted file mode 100644 +index 2b93c9c..0000000 +--- a/crypto_sign/sphincs-shake-192s-simple/avx2/fips202x4.h ++++ /dev/null +@@ -1,28 +0,0 @@ +-#ifndef SPX_FIPS202X4_H +-#define SPX_FIPS202X4_H +- +-#include +- +-#include "params.h" +- +-#define shake128x4 SPX_NAMESPACE(shake128x4) +-void shake128x4(unsigned char *out0, +- unsigned char *out1, +- unsigned char *out2, +- unsigned char *out3, unsigned long long outlen, +- unsigned char *in0, +- unsigned char *in1, +- unsigned char *in2, +- unsigned char *in3, unsigned long long inlen); +- +-#define shake256x4 SPX_NAMESPACE(shake256x4) +-void shake256x4(unsigned char *out0, +- unsigned char *out1, +- unsigned char *out2, +- unsigned char *out3, unsigned long long outlen, +- unsigned char *in0, +- unsigned char *in1, +- unsigned char *in2, +- unsigned char *in3, unsigned long long inlen); +- +-#endif +diff --git a/crypto_sign/sphincs-shake-256f-robust/avx2/fips202x4.c b/crypto_sign/sphincs-shake-256f-robust/avx2/fips202x4.c +deleted file mode 100644 +index 1e06fef..0000000 +--- a/crypto_sign/sphincs-shake-256f-robust/avx2/fips202x4.c ++++ /dev/null +@@ -1,210 +0,0 @@ +-#include +-#include +-#include +- +-#include "fips202.h" +-#include "fips202x4.h" +- +-#define NROUNDS 24 +-#define ROL(a, offset) (((a) << (offset)) ^ ((a) >> (64-(offset)))) +- +-static uint64_t load64(const unsigned char *x) { +- unsigned long long r = 0, i; +- +- for (i = 0; i < 8; ++i) { +- r |= (unsigned long long)x[i] << 8 * i; +- } +- return r; +-} +- +-static void store64(uint8_t *x, uint64_t u) { +- unsigned int i; +- +- for (i = 0; i < 8; ++i) { +- x[i] = (uint8_t)u; +- u >>= 8; +- } +-} +- +-/* Use implementation from the Keccak Code Package */ +-extern void KeccakP1600times4_PermuteAll_24rounds(__m256i *s); +-#define KeccakF1600_StatePermute4x KeccakP1600times4_PermuteAll_24rounds +- +-static void keccak_absorb4x(__m256i *s, +- unsigned int r, +- const unsigned char *m0, +- const unsigned char *m1, +- const unsigned char *m2, +- const unsigned char *m3, +- unsigned long long int mlen, +- unsigned char p) { +- unsigned long long i; +- unsigned char t0[200]; +- unsigned char t1[200]; +- unsigned char t2[200]; +- unsigned char t3[200]; +- +- unsigned long long *ss = (unsigned long long *)s; +- +- +- while (mlen >= r) { +- for (i = 0; i < r / 8; ++i) { +- ss[4 * i + 0] ^= load64(m0 + 8 * i); +- ss[4 * i + 1] ^= load64(m1 + 8 * i); +- ss[4 * i + 2] ^= load64(m2 + 8 * i); +- ss[4 * i + 3] ^= load64(m3 + 8 * i); +- } +- +- KeccakF1600_StatePermute4x(s); +- mlen -= r; +- m0 += r; +- m1 += r; +- m2 += r; +- m3 += r; +- } +- +- for (i = 0; i < r; ++i) { +- t0[i] = 0; +- t1[i] = 0; +- t2[i] = 0; +- t3[i] = 0; +- } +- for (i = 0; i < mlen; ++i) { +- t0[i] = m0[i]; +- t1[i] = m1[i]; +- t2[i] = m2[i]; +- t3[i] = m3[i]; +- } +- +- t0[i] = p; +- t1[i] = p; +- t2[i] = p; +- t3[i] = p; +- +- t0[r - 1] |= 128; +- t1[r - 1] |= 128; +- t2[r - 1] |= 128; +- t3[r - 1] |= 128; +- +- for (i = 0; i < r / 8; ++i) { +- ss[4 * i + 0] ^= load64(t0 + 8 * i); +- ss[4 * i + 1] ^= load64(t1 + 8 * i); +- ss[4 * i + 2] ^= load64(t2 + 8 * i); +- ss[4 * i + 3] ^= load64(t3 + 8 * i); +- } +-} +- +- +-static void keccak_squeezeblocks4x(unsigned char *h0, +- unsigned char *h1, +- unsigned char *h2, +- unsigned char *h3, +- unsigned long long int nblocks, +- __m256i *s, +- unsigned int r) { +- unsigned int i; +- +- unsigned long long *ss = (unsigned long long *)s; +- +- while (nblocks > 0) { +- KeccakF1600_StatePermute4x(s); +- for (i = 0; i < (r >> 3); i++) { +- store64(h0 + 8 * i, ss[4 * i + 0]); +- store64(h1 + 8 * i, ss[4 * i + 1]); +- store64(h2 + 8 * i, ss[4 * i + 2]); +- store64(h3 + 8 * i, ss[4 * i + 3]); +- } +- h0 += r; +- h1 += r; +- h2 += r; +- h3 += r; +- nblocks--; +- } +-} +- +- +- +-void shake128x4(unsigned char *out0, +- unsigned char *out1, +- unsigned char *out2, +- unsigned char *out3, unsigned long long outlen, +- unsigned char *in0, +- unsigned char *in1, +- unsigned char *in2, +- unsigned char *in3, unsigned long long inlen) { +- __m256i s[25]; +- unsigned char t0[SHAKE128_RATE]; +- unsigned char t1[SHAKE128_RATE]; +- unsigned char t2[SHAKE128_RATE]; +- unsigned char t3[SHAKE128_RATE]; +- unsigned int i; +- +- /* zero state */ +- for (i = 0; i < 25; i++) { +- s[i] = _mm256_xor_si256(s[i], s[i]); +- } +- +- /* absorb 4 message of identical length in parallel */ +- keccak_absorb4x(s, SHAKE128_RATE, in0, in1, in2, in3, inlen, 0x1F); +- +- /* Squeeze output */ +- keccak_squeezeblocks4x(out0, out1, out2, out3, outlen / SHAKE128_RATE, s, SHAKE128_RATE); +- +- out0 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; +- out1 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; +- out2 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; +- out3 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; +- +- if (outlen % SHAKE128_RATE) { +- keccak_squeezeblocks4x(t0, t1, t2, t3, 1, s, SHAKE128_RATE); +- for (i = 0; i < outlen % SHAKE128_RATE; i++) { +- out0[i] = t0[i]; +- out1[i] = t1[i]; +- out2[i] = t2[i]; +- out3[i] = t3[i]; +- } +- } +-} +- +- +-void shake256x4(unsigned char *out0, +- unsigned char *out1, +- unsigned char *out2, +- unsigned char *out3, unsigned long long outlen, +- unsigned char *in0, +- unsigned char *in1, +- unsigned char *in2, +- unsigned char *in3, unsigned long long inlen) { +- __m256i s[25]; +- unsigned char t0[SHAKE256_RATE]; +- unsigned char t1[SHAKE256_RATE]; +- unsigned char t2[SHAKE256_RATE]; +- unsigned char t3[SHAKE256_RATE]; +- unsigned int i; +- +- /* zero state */ +- for (i = 0; i < 25; i++) { +- s[i] = _mm256_xor_si256(s[i], s[i]); +- } +- +- /* absorb 4 message of identical length in parallel */ +- keccak_absorb4x(s, SHAKE256_RATE, in0, in1, in2, in3, inlen, 0x1F); +- +- /* Squeeze output */ +- keccak_squeezeblocks4x(out0, out1, out2, out3, outlen / SHAKE256_RATE, s, SHAKE256_RATE); +- +- out0 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; +- out1 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; +- out2 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; +- out3 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; +- +- if (outlen % SHAKE256_RATE) { +- keccak_squeezeblocks4x(t0, t1, t2, t3, 1, s, SHAKE256_RATE); +- for (i = 0; i < outlen % SHAKE256_RATE; i++) { +- out0[i] = t0[i]; +- out1[i] = t1[i]; +- out2[i] = t2[i]; +- out3[i] = t3[i]; +- } +- } +-} +diff --git a/crypto_sign/sphincs-shake-256f-robust/avx2/fips202x4.h b/crypto_sign/sphincs-shake-256f-robust/avx2/fips202x4.h +deleted file mode 100644 +index 2b93c9c..0000000 +--- a/crypto_sign/sphincs-shake-256f-robust/avx2/fips202x4.h ++++ /dev/null +@@ -1,28 +0,0 @@ +-#ifndef SPX_FIPS202X4_H +-#define SPX_FIPS202X4_H +- +-#include +- +-#include "params.h" +- +-#define shake128x4 SPX_NAMESPACE(shake128x4) +-void shake128x4(unsigned char *out0, +- unsigned char *out1, +- unsigned char *out2, +- unsigned char *out3, unsigned long long outlen, +- unsigned char *in0, +- unsigned char *in1, +- unsigned char *in2, +- unsigned char *in3, unsigned long long inlen); +- +-#define shake256x4 SPX_NAMESPACE(shake256x4) +-void shake256x4(unsigned char *out0, +- unsigned char *out1, +- unsigned char *out2, +- unsigned char *out3, unsigned long long outlen, +- unsigned char *in0, +- unsigned char *in1, +- unsigned char *in2, +- unsigned char *in3, unsigned long long inlen); +- +-#endif +diff --git a/crypto_sign/sphincs-shake-256f-simple/avx2/fips202x4.c b/crypto_sign/sphincs-shake-256f-simple/avx2/fips202x4.c +deleted file mode 100644 +index 1e06fef..0000000 +--- a/crypto_sign/sphincs-shake-256f-simple/avx2/fips202x4.c ++++ /dev/null +@@ -1,210 +0,0 @@ +-#include +-#include +-#include +- +-#include "fips202.h" +-#include "fips202x4.h" +- +-#define NROUNDS 24 +-#define ROL(a, offset) (((a) << (offset)) ^ ((a) >> (64-(offset)))) +- +-static uint64_t load64(const unsigned char *x) { +- unsigned long long r = 0, i; +- +- for (i = 0; i < 8; ++i) { +- r |= (unsigned long long)x[i] << 8 * i; +- } +- return r; +-} +- +-static void store64(uint8_t *x, uint64_t u) { +- unsigned int i; +- +- for (i = 0; i < 8; ++i) { +- x[i] = (uint8_t)u; +- u >>= 8; +- } +-} +- +-/* Use implementation from the Keccak Code Package */ +-extern void KeccakP1600times4_PermuteAll_24rounds(__m256i *s); +-#define KeccakF1600_StatePermute4x KeccakP1600times4_PermuteAll_24rounds +- +-static void keccak_absorb4x(__m256i *s, +- unsigned int r, +- const unsigned char *m0, +- const unsigned char *m1, +- const unsigned char *m2, +- const unsigned char *m3, +- unsigned long long int mlen, +- unsigned char p) { +- unsigned long long i; +- unsigned char t0[200]; +- unsigned char t1[200]; +- unsigned char t2[200]; +- unsigned char t3[200]; +- +- unsigned long long *ss = (unsigned long long *)s; +- +- +- while (mlen >= r) { +- for (i = 0; i < r / 8; ++i) { +- ss[4 * i + 0] ^= load64(m0 + 8 * i); +- ss[4 * i + 1] ^= load64(m1 + 8 * i); +- ss[4 * i + 2] ^= load64(m2 + 8 * i); +- ss[4 * i + 3] ^= load64(m3 + 8 * i); +- } +- +- KeccakF1600_StatePermute4x(s); +- mlen -= r; +- m0 += r; +- m1 += r; +- m2 += r; +- m3 += r; +- } +- +- for (i = 0; i < r; ++i) { +- t0[i] = 0; +- t1[i] = 0; +- t2[i] = 0; +- t3[i] = 0; +- } +- for (i = 0; i < mlen; ++i) { +- t0[i] = m0[i]; +- t1[i] = m1[i]; +- t2[i] = m2[i]; +- t3[i] = m3[i]; +- } +- +- t0[i] = p; +- t1[i] = p; +- t2[i] = p; +- t3[i] = p; +- +- t0[r - 1] |= 128; +- t1[r - 1] |= 128; +- t2[r - 1] |= 128; +- t3[r - 1] |= 128; +- +- for (i = 0; i < r / 8; ++i) { +- ss[4 * i + 0] ^= load64(t0 + 8 * i); +- ss[4 * i + 1] ^= load64(t1 + 8 * i); +- ss[4 * i + 2] ^= load64(t2 + 8 * i); +- ss[4 * i + 3] ^= load64(t3 + 8 * i); +- } +-} +- +- +-static void keccak_squeezeblocks4x(unsigned char *h0, +- unsigned char *h1, +- unsigned char *h2, +- unsigned char *h3, +- unsigned long long int nblocks, +- __m256i *s, +- unsigned int r) { +- unsigned int i; +- +- unsigned long long *ss = (unsigned long long *)s; +- +- while (nblocks > 0) { +- KeccakF1600_StatePermute4x(s); +- for (i = 0; i < (r >> 3); i++) { +- store64(h0 + 8 * i, ss[4 * i + 0]); +- store64(h1 + 8 * i, ss[4 * i + 1]); +- store64(h2 + 8 * i, ss[4 * i + 2]); +- store64(h3 + 8 * i, ss[4 * i + 3]); +- } +- h0 += r; +- h1 += r; +- h2 += r; +- h3 += r; +- nblocks--; +- } +-} +- +- +- +-void shake128x4(unsigned char *out0, +- unsigned char *out1, +- unsigned char *out2, +- unsigned char *out3, unsigned long long outlen, +- unsigned char *in0, +- unsigned char *in1, +- unsigned char *in2, +- unsigned char *in3, unsigned long long inlen) { +- __m256i s[25]; +- unsigned char t0[SHAKE128_RATE]; +- unsigned char t1[SHAKE128_RATE]; +- unsigned char t2[SHAKE128_RATE]; +- unsigned char t3[SHAKE128_RATE]; +- unsigned int i; +- +- /* zero state */ +- for (i = 0; i < 25; i++) { +- s[i] = _mm256_xor_si256(s[i], s[i]); +- } +- +- /* absorb 4 message of identical length in parallel */ +- keccak_absorb4x(s, SHAKE128_RATE, in0, in1, in2, in3, inlen, 0x1F); +- +- /* Squeeze output */ +- keccak_squeezeblocks4x(out0, out1, out2, out3, outlen / SHAKE128_RATE, s, SHAKE128_RATE); +- +- out0 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; +- out1 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; +- out2 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; +- out3 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; +- +- if (outlen % SHAKE128_RATE) { +- keccak_squeezeblocks4x(t0, t1, t2, t3, 1, s, SHAKE128_RATE); +- for (i = 0; i < outlen % SHAKE128_RATE; i++) { +- out0[i] = t0[i]; +- out1[i] = t1[i]; +- out2[i] = t2[i]; +- out3[i] = t3[i]; +- } +- } +-} +- +- +-void shake256x4(unsigned char *out0, +- unsigned char *out1, +- unsigned char *out2, +- unsigned char *out3, unsigned long long outlen, +- unsigned char *in0, +- unsigned char *in1, +- unsigned char *in2, +- unsigned char *in3, unsigned long long inlen) { +- __m256i s[25]; +- unsigned char t0[SHAKE256_RATE]; +- unsigned char t1[SHAKE256_RATE]; +- unsigned char t2[SHAKE256_RATE]; +- unsigned char t3[SHAKE256_RATE]; +- unsigned int i; +- +- /* zero state */ +- for (i = 0; i < 25; i++) { +- s[i] = _mm256_xor_si256(s[i], s[i]); +- } +- +- /* absorb 4 message of identical length in parallel */ +- keccak_absorb4x(s, SHAKE256_RATE, in0, in1, in2, in3, inlen, 0x1F); +- +- /* Squeeze output */ +- keccak_squeezeblocks4x(out0, out1, out2, out3, outlen / SHAKE256_RATE, s, SHAKE256_RATE); +- +- out0 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; +- out1 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; +- out2 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; +- out3 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; +- +- if (outlen % SHAKE256_RATE) { +- keccak_squeezeblocks4x(t0, t1, t2, t3, 1, s, SHAKE256_RATE); +- for (i = 0; i < outlen % SHAKE256_RATE; i++) { +- out0[i] = t0[i]; +- out1[i] = t1[i]; +- out2[i] = t2[i]; +- out3[i] = t3[i]; +- } +- } +-} +diff --git a/crypto_sign/sphincs-shake-256f-simple/avx2/fips202x4.h b/crypto_sign/sphincs-shake-256f-simple/avx2/fips202x4.h +deleted file mode 100644 +index 2b93c9c..0000000 +--- a/crypto_sign/sphincs-shake-256f-simple/avx2/fips202x4.h ++++ /dev/null +@@ -1,28 +0,0 @@ +-#ifndef SPX_FIPS202X4_H +-#define SPX_FIPS202X4_H +- +-#include +- +-#include "params.h" +- +-#define shake128x4 SPX_NAMESPACE(shake128x4) +-void shake128x4(unsigned char *out0, +- unsigned char *out1, +- unsigned char *out2, +- unsigned char *out3, unsigned long long outlen, +- unsigned char *in0, +- unsigned char *in1, +- unsigned char *in2, +- unsigned char *in3, unsigned long long inlen); +- +-#define shake256x4 SPX_NAMESPACE(shake256x4) +-void shake256x4(unsigned char *out0, +- unsigned char *out1, +- unsigned char *out2, +- unsigned char *out3, unsigned long long outlen, +- unsigned char *in0, +- unsigned char *in1, +- unsigned char *in2, +- unsigned char *in3, unsigned long long inlen); +- +-#endif +diff --git a/crypto_sign/sphincs-shake-256s-robust/avx2/fips202x4.c b/crypto_sign/sphincs-shake-256s-robust/avx2/fips202x4.c +deleted file mode 100644 +index 1e06fef..0000000 +--- a/crypto_sign/sphincs-shake-256s-robust/avx2/fips202x4.c ++++ /dev/null +@@ -1,210 +0,0 @@ +-#include +-#include +-#include +- +-#include "fips202.h" +-#include "fips202x4.h" +- +-#define NROUNDS 24 +-#define ROL(a, offset) (((a) << (offset)) ^ ((a) >> (64-(offset)))) +- +-static uint64_t load64(const unsigned char *x) { +- unsigned long long r = 0, i; +- +- for (i = 0; i < 8; ++i) { +- r |= (unsigned long long)x[i] << 8 * i; +- } +- return r; +-} +- +-static void store64(uint8_t *x, uint64_t u) { +- unsigned int i; +- +- for (i = 0; i < 8; ++i) { +- x[i] = (uint8_t)u; +- u >>= 8; +- } +-} +- +-/* Use implementation from the Keccak Code Package */ +-extern void KeccakP1600times4_PermuteAll_24rounds(__m256i *s); +-#define KeccakF1600_StatePermute4x KeccakP1600times4_PermuteAll_24rounds +- +-static void keccak_absorb4x(__m256i *s, +- unsigned int r, +- const unsigned char *m0, +- const unsigned char *m1, +- const unsigned char *m2, +- const unsigned char *m3, +- unsigned long long int mlen, +- unsigned char p) { +- unsigned long long i; +- unsigned char t0[200]; +- unsigned char t1[200]; +- unsigned char t2[200]; +- unsigned char t3[200]; +- +- unsigned long long *ss = (unsigned long long *)s; +- +- +- while (mlen >= r) { +- for (i = 0; i < r / 8; ++i) { +- ss[4 * i + 0] ^= load64(m0 + 8 * i); +- ss[4 * i + 1] ^= load64(m1 + 8 * i); +- ss[4 * i + 2] ^= load64(m2 + 8 * i); +- ss[4 * i + 3] ^= load64(m3 + 8 * i); +- } +- +- KeccakF1600_StatePermute4x(s); +- mlen -= r; +- m0 += r; +- m1 += r; +- m2 += r; +- m3 += r; +- } +- +- for (i = 0; i < r; ++i) { +- t0[i] = 0; +- t1[i] = 0; +- t2[i] = 0; +- t3[i] = 0; +- } +- for (i = 0; i < mlen; ++i) { +- t0[i] = m0[i]; +- t1[i] = m1[i]; +- t2[i] = m2[i]; +- t3[i] = m3[i]; +- } +- +- t0[i] = p; +- t1[i] = p; +- t2[i] = p; +- t3[i] = p; +- +- t0[r - 1] |= 128; +- t1[r - 1] |= 128; +- t2[r - 1] |= 128; +- t3[r - 1] |= 128; +- +- for (i = 0; i < r / 8; ++i) { +- ss[4 * i + 0] ^= load64(t0 + 8 * i); +- ss[4 * i + 1] ^= load64(t1 + 8 * i); +- ss[4 * i + 2] ^= load64(t2 + 8 * i); +- ss[4 * i + 3] ^= load64(t3 + 8 * i); +- } +-} +- +- +-static void keccak_squeezeblocks4x(unsigned char *h0, +- unsigned char *h1, +- unsigned char *h2, +- unsigned char *h3, +- unsigned long long int nblocks, +- __m256i *s, +- unsigned int r) { +- unsigned int i; +- +- unsigned long long *ss = (unsigned long long *)s; +- +- while (nblocks > 0) { +- KeccakF1600_StatePermute4x(s); +- for (i = 0; i < (r >> 3); i++) { +- store64(h0 + 8 * i, ss[4 * i + 0]); +- store64(h1 + 8 * i, ss[4 * i + 1]); +- store64(h2 + 8 * i, ss[4 * i + 2]); +- store64(h3 + 8 * i, ss[4 * i + 3]); +- } +- h0 += r; +- h1 += r; +- h2 += r; +- h3 += r; +- nblocks--; +- } +-} +- +- +- +-void shake128x4(unsigned char *out0, +- unsigned char *out1, +- unsigned char *out2, +- unsigned char *out3, unsigned long long outlen, +- unsigned char *in0, +- unsigned char *in1, +- unsigned char *in2, +- unsigned char *in3, unsigned long long inlen) { +- __m256i s[25]; +- unsigned char t0[SHAKE128_RATE]; +- unsigned char t1[SHAKE128_RATE]; +- unsigned char t2[SHAKE128_RATE]; +- unsigned char t3[SHAKE128_RATE]; +- unsigned int i; +- +- /* zero state */ +- for (i = 0; i < 25; i++) { +- s[i] = _mm256_xor_si256(s[i], s[i]); +- } +- +- /* absorb 4 message of identical length in parallel */ +- keccak_absorb4x(s, SHAKE128_RATE, in0, in1, in2, in3, inlen, 0x1F); +- +- /* Squeeze output */ +- keccak_squeezeblocks4x(out0, out1, out2, out3, outlen / SHAKE128_RATE, s, SHAKE128_RATE); +- +- out0 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; +- out1 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; +- out2 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; +- out3 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; +- +- if (outlen % SHAKE128_RATE) { +- keccak_squeezeblocks4x(t0, t1, t2, t3, 1, s, SHAKE128_RATE); +- for (i = 0; i < outlen % SHAKE128_RATE; i++) { +- out0[i] = t0[i]; +- out1[i] = t1[i]; +- out2[i] = t2[i]; +- out3[i] = t3[i]; +- } +- } +-} +- +- +-void shake256x4(unsigned char *out0, +- unsigned char *out1, +- unsigned char *out2, +- unsigned char *out3, unsigned long long outlen, +- unsigned char *in0, +- unsigned char *in1, +- unsigned char *in2, +- unsigned char *in3, unsigned long long inlen) { +- __m256i s[25]; +- unsigned char t0[SHAKE256_RATE]; +- unsigned char t1[SHAKE256_RATE]; +- unsigned char t2[SHAKE256_RATE]; +- unsigned char t3[SHAKE256_RATE]; +- unsigned int i; +- +- /* zero state */ +- for (i = 0; i < 25; i++) { +- s[i] = _mm256_xor_si256(s[i], s[i]); +- } +- +- /* absorb 4 message of identical length in parallel */ +- keccak_absorb4x(s, SHAKE256_RATE, in0, in1, in2, in3, inlen, 0x1F); +- +- /* Squeeze output */ +- keccak_squeezeblocks4x(out0, out1, out2, out3, outlen / SHAKE256_RATE, s, SHAKE256_RATE); +- +- out0 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; +- out1 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; +- out2 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; +- out3 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; +- +- if (outlen % SHAKE256_RATE) { +- keccak_squeezeblocks4x(t0, t1, t2, t3, 1, s, SHAKE256_RATE); +- for (i = 0; i < outlen % SHAKE256_RATE; i++) { +- out0[i] = t0[i]; +- out1[i] = t1[i]; +- out2[i] = t2[i]; +- out3[i] = t3[i]; +- } +- } +-} +diff --git a/crypto_sign/sphincs-shake-256s-robust/avx2/fips202x4.h b/crypto_sign/sphincs-shake-256s-robust/avx2/fips202x4.h +deleted file mode 100644 +index 2b93c9c..0000000 +--- a/crypto_sign/sphincs-shake-256s-robust/avx2/fips202x4.h ++++ /dev/null +@@ -1,28 +0,0 @@ +-#ifndef SPX_FIPS202X4_H +-#define SPX_FIPS202X4_H +- +-#include +- +-#include "params.h" +- +-#define shake128x4 SPX_NAMESPACE(shake128x4) +-void shake128x4(unsigned char *out0, +- unsigned char *out1, +- unsigned char *out2, +- unsigned char *out3, unsigned long long outlen, +- unsigned char *in0, +- unsigned char *in1, +- unsigned char *in2, +- unsigned char *in3, unsigned long long inlen); +- +-#define shake256x4 SPX_NAMESPACE(shake256x4) +-void shake256x4(unsigned char *out0, +- unsigned char *out1, +- unsigned char *out2, +- unsigned char *out3, unsigned long long outlen, +- unsigned char *in0, +- unsigned char *in1, +- unsigned char *in2, +- unsigned char *in3, unsigned long long inlen); +- +-#endif +diff --git a/crypto_sign/sphincs-shake-256s-simple/avx2/fips202x4.c b/crypto_sign/sphincs-shake-256s-simple/avx2/fips202x4.c +deleted file mode 100644 +index 1e06fef..0000000 +--- a/crypto_sign/sphincs-shake-256s-simple/avx2/fips202x4.c ++++ /dev/null +@@ -1,210 +0,0 @@ +-#include +-#include +-#include +- +-#include "fips202.h" +-#include "fips202x4.h" +- +-#define NROUNDS 24 +-#define ROL(a, offset) (((a) << (offset)) ^ ((a) >> (64-(offset)))) +- +-static uint64_t load64(const unsigned char *x) { +- unsigned long long r = 0, i; +- +- for (i = 0; i < 8; ++i) { +- r |= (unsigned long long)x[i] << 8 * i; +- } +- return r; +-} +- +-static void store64(uint8_t *x, uint64_t u) { +- unsigned int i; +- +- for (i = 0; i < 8; ++i) { +- x[i] = (uint8_t)u; +- u >>= 8; +- } +-} +- +-/* Use implementation from the Keccak Code Package */ +-extern void KeccakP1600times4_PermuteAll_24rounds(__m256i *s); +-#define KeccakF1600_StatePermute4x KeccakP1600times4_PermuteAll_24rounds +- +-static void keccak_absorb4x(__m256i *s, +- unsigned int r, +- const unsigned char *m0, +- const unsigned char *m1, +- const unsigned char *m2, +- const unsigned char *m3, +- unsigned long long int mlen, +- unsigned char p) { +- unsigned long long i; +- unsigned char t0[200]; +- unsigned char t1[200]; +- unsigned char t2[200]; +- unsigned char t3[200]; +- +- unsigned long long *ss = (unsigned long long *)s; +- +- +- while (mlen >= r) { +- for (i = 0; i < r / 8; ++i) { +- ss[4 * i + 0] ^= load64(m0 + 8 * i); +- ss[4 * i + 1] ^= load64(m1 + 8 * i); +- ss[4 * i + 2] ^= load64(m2 + 8 * i); +- ss[4 * i + 3] ^= load64(m3 + 8 * i); +- } +- +- KeccakF1600_StatePermute4x(s); +- mlen -= r; +- m0 += r; +- m1 += r; +- m2 += r; +- m3 += r; +- } +- +- for (i = 0; i < r; ++i) { +- t0[i] = 0; +- t1[i] = 0; +- t2[i] = 0; +- t3[i] = 0; +- } +- for (i = 0; i < mlen; ++i) { +- t0[i] = m0[i]; +- t1[i] = m1[i]; +- t2[i] = m2[i]; +- t3[i] = m3[i]; +- } +- +- t0[i] = p; +- t1[i] = p; +- t2[i] = p; +- t3[i] = p; +- +- t0[r - 1] |= 128; +- t1[r - 1] |= 128; +- t2[r - 1] |= 128; +- t3[r - 1] |= 128; +- +- for (i = 0; i < r / 8; ++i) { +- ss[4 * i + 0] ^= load64(t0 + 8 * i); +- ss[4 * i + 1] ^= load64(t1 + 8 * i); +- ss[4 * i + 2] ^= load64(t2 + 8 * i); +- ss[4 * i + 3] ^= load64(t3 + 8 * i); +- } +-} +- +- +-static void keccak_squeezeblocks4x(unsigned char *h0, +- unsigned char *h1, +- unsigned char *h2, +- unsigned char *h3, +- unsigned long long int nblocks, +- __m256i *s, +- unsigned int r) { +- unsigned int i; +- +- unsigned long long *ss = (unsigned long long *)s; +- +- while (nblocks > 0) { +- KeccakF1600_StatePermute4x(s); +- for (i = 0; i < (r >> 3); i++) { +- store64(h0 + 8 * i, ss[4 * i + 0]); +- store64(h1 + 8 * i, ss[4 * i + 1]); +- store64(h2 + 8 * i, ss[4 * i + 2]); +- store64(h3 + 8 * i, ss[4 * i + 3]); +- } +- h0 += r; +- h1 += r; +- h2 += r; +- h3 += r; +- nblocks--; +- } +-} +- +- +- +-void shake128x4(unsigned char *out0, +- unsigned char *out1, +- unsigned char *out2, +- unsigned char *out3, unsigned long long outlen, +- unsigned char *in0, +- unsigned char *in1, +- unsigned char *in2, +- unsigned char *in3, unsigned long long inlen) { +- __m256i s[25]; +- unsigned char t0[SHAKE128_RATE]; +- unsigned char t1[SHAKE128_RATE]; +- unsigned char t2[SHAKE128_RATE]; +- unsigned char t3[SHAKE128_RATE]; +- unsigned int i; +- +- /* zero state */ +- for (i = 0; i < 25; i++) { +- s[i] = _mm256_xor_si256(s[i], s[i]); +- } +- +- /* absorb 4 message of identical length in parallel */ +- keccak_absorb4x(s, SHAKE128_RATE, in0, in1, in2, in3, inlen, 0x1F); +- +- /* Squeeze output */ +- keccak_squeezeblocks4x(out0, out1, out2, out3, outlen / SHAKE128_RATE, s, SHAKE128_RATE); +- +- out0 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; +- out1 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; +- out2 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; +- out3 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; +- +- if (outlen % SHAKE128_RATE) { +- keccak_squeezeblocks4x(t0, t1, t2, t3, 1, s, SHAKE128_RATE); +- for (i = 0; i < outlen % SHAKE128_RATE; i++) { +- out0[i] = t0[i]; +- out1[i] = t1[i]; +- out2[i] = t2[i]; +- out3[i] = t3[i]; +- } +- } +-} +- +- +-void shake256x4(unsigned char *out0, +- unsigned char *out1, +- unsigned char *out2, +- unsigned char *out3, unsigned long long outlen, +- unsigned char *in0, +- unsigned char *in1, +- unsigned char *in2, +- unsigned char *in3, unsigned long long inlen) { +- __m256i s[25]; +- unsigned char t0[SHAKE256_RATE]; +- unsigned char t1[SHAKE256_RATE]; +- unsigned char t2[SHAKE256_RATE]; +- unsigned char t3[SHAKE256_RATE]; +- unsigned int i; +- +- /* zero state */ +- for (i = 0; i < 25; i++) { +- s[i] = _mm256_xor_si256(s[i], s[i]); +- } +- +- /* absorb 4 message of identical length in parallel */ +- keccak_absorb4x(s, SHAKE256_RATE, in0, in1, in2, in3, inlen, 0x1F); +- +- /* Squeeze output */ +- keccak_squeezeblocks4x(out0, out1, out2, out3, outlen / SHAKE256_RATE, s, SHAKE256_RATE); +- +- out0 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; +- out1 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; +- out2 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; +- out3 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; +- +- if (outlen % SHAKE256_RATE) { +- keccak_squeezeblocks4x(t0, t1, t2, t3, 1, s, SHAKE256_RATE); +- for (i = 0; i < outlen % SHAKE256_RATE; i++) { +- out0[i] = t0[i]; +- out1[i] = t1[i]; +- out2[i] = t2[i]; +- out3[i] = t3[i]; +- } +- } +-} +diff --git a/crypto_sign/sphincs-shake-256s-simple/avx2/fips202x4.h b/crypto_sign/sphincs-shake-256s-simple/avx2/fips202x4.h +deleted file mode 100644 +index 2b93c9c..0000000 +--- a/crypto_sign/sphincs-shake-256s-simple/avx2/fips202x4.h ++++ /dev/null +@@ -1,28 +0,0 @@ +-#ifndef SPX_FIPS202X4_H +-#define SPX_FIPS202X4_H +- +-#include +- +-#include "params.h" +- +-#define shake128x4 SPX_NAMESPACE(shake128x4) +-void shake128x4(unsigned char *out0, +- unsigned char *out1, +- unsigned char *out2, +- unsigned char *out3, unsigned long long outlen, +- unsigned char *in0, +- unsigned char *in1, +- unsigned char *in2, +- unsigned char *in3, unsigned long long inlen); +- +-#define shake256x4 SPX_NAMESPACE(shake256x4) +-void shake256x4(unsigned char *out0, +- unsigned char *out1, +- unsigned char *out2, +- unsigned char *out3, unsigned long long outlen, +- unsigned char *in0, +- unsigned char *in1, +- unsigned char *in2, +- unsigned char *in3, unsigned long long inlen); +- +-#endif diff --git a/scripts/update_docs_from_yaml.py b/scripts/update_docs_from_yaml.py index d4637f28bd..561a165a42 100644 --- a/scripts/update_docs_from_yaml.py +++ b/scripts/update_docs_from_yaml.py @@ -328,7 +328,7 @@ def do_it(liboqs_root): readme.write('\n') sphincs_yml = sig_yamls[-1] - for hash_func in ['Haraka', 'SHA256', 'SHAKE256']: + for hash_func in ['SHA256', 'SHAKE256']: parameter_sets = [pset for pset in sphincs_yml['parameter-sets'] if hash_func in pset['name']] if any(impl['large-stack-usage'] for impl in parameter_sets[0]['implementations']): readme.write('- **SPHINCS+-{}**: {}†'.format(hash_func, parameter_sets[0]['name'].replace('_','\_'))) @@ -347,4 +347,4 @@ def do_it(liboqs_root): parser = argparse.ArgumentParser() parser.add_argument("--liboqs-root", default=".") args = parser.parse_args() - do_it(args.liboqs_root) \ No newline at end of file + do_it(args.liboqs_root) diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index 7ac15a2fba..c077b489eb 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -60,6 +60,9 @@ else() endif() if(${OQS_USE_SHA3_OPENSSL}) + if (${OQS_ENABLE_SHA3_xkcp_low}) + add_subdirectory(sha3/xkcp_low) + endif() set(SHA3_IMPL sha3/ossl_sha3.c sha3/ossl_sha3x4.c) set(OSSL_HELPERS ossl_helpers.c) else() # using XKCP @@ -116,7 +119,7 @@ if(CMAKE_HAVE_MEMSET_S) target_compile_definitions(common PRIVATE OQS_HAVE_MEMSET_S) endif() -if(NOT ${OQS_USE_SHA3_OPENSSL}) # using XKCP +if(${OQS_ENABLE_SHA3_xkcp_low}) # using XKCP set(_COMMON_OBJS ${_COMMON_OBJS} ${XKCP_LOW_OBJS}) endif() diff --git a/src/common/pqclean_shims/compat.h b/src/common/pqclean_shims/compat.h index 99c6fd6c6d..bbd8287e8e 100644 --- a/src/common/pqclean_shims/compat.h +++ b/src/common/pqclean_shims/compat.h @@ -21,12 +21,11 @@ #if defined(__GNUC__) && !defined(__clang__) -#include -# if !__GNUC_PREREQ(7, 1) // at least GCC 7.1 +#if ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((7) << 16) + (1)) // at least GCC 7.1 /* Versions of the GCC pre-7.1 don't have __m256*_u types */ UNALIGNED_VECTOR_POLYFILL_GCC -# endif // __GNUC_PREREQ(7,1) +# endif // GCC >= 7.1 #elif defined(__GNUC__) && defined(__clang__) @@ -35,17 +34,14 @@ UNALIGNED_VECTOR_POLYFILL_GCC UNALIGNED_VECTOR_POLYFILL_GCC # endif -#elif defined(_MSC_VER) -// MSVC simply doesn't have these types +#else +// Neither MSVC nor other compilers seem to have these types #define __m256_u __m256 #define __m256d_u __m256d #define __m256i_u __m256i -#else -#error UNSUPPORTED COMPILER!?!? #endif // compiler selector - /************************ * Portable VLA support * ************************/ @@ -61,4 +57,5 @@ UNALIGNED_VECTOR_POLYFILL_GCC # define PQCLEAN_VLA(__t,__x,__s) __t __x[__s] #endif -#endif // PQCLEAN_COMMON_COMPAT_H + +#endif // OQS_COMMON_COMPAT_H diff --git a/src/common/pqclean_shims/fips202x4.h b/src/common/pqclean_shims/fips202x4.h index d01cdebcaf..c1f7ffcf0e 100644 --- a/src/common/pqclean_shims/fips202x4.h +++ b/src/common/pqclean_shims/fips202x4.h @@ -3,8 +3,18 @@ #ifndef FIPS202X4_H #define FIPS202X4_H +#include + +#ifdef ARCH_X86_64 +#include +#endif + #include +#if defined(OQS_DIST_X86_64_BUILD) && defined(OQS_ENABLE_SHA3_xkcp_low_avx2) +#define KeccakP1600times4_PermuteAll_24rounds KeccakP1600times4_PermuteAll_24rounds_avx2 +#endif + #define shake128x4incctx OQS_SHA3_shake128_x4_inc_ctx #define shake128x4_inc_init OQS_SHA3_shake128_x4_inc_init #define shake128x4_inc_absorb OQS_SHA3_shake128_x4_inc_absorb @@ -23,18 +33,8 @@ #define shake256x4_inc_ctx_clone OQS_SHA3_shake256_x4_inc_ctx_clone #define shake256x4_inc_ctx_reset OQS_SHA3_shake256_x4_inc_ctx_reset -#define PQCLEAN_SPHINCSSHAKE256128FROBUST_AVX2_shake256x4 OQS_SHA3_shake256_x4 -#define PQCLEAN_SPHINCSSHAKE256128FSIMPLE_AVX2_shake256x4 OQS_SHA3_shake256_x4 -#define PQCLEAN_SPHINCSSHAKE256128SROBUST_AVX2_shake256x4 OQS_SHA3_shake256_x4 -#define PQCLEAN_SPHINCSSHAKE256128SSIMPLE_AVX2_shake256x4 OQS_SHA3_shake256_x4 -#define PQCLEAN_SPHINCSSHAKE256192FROBUST_AVX2_shake256x4 OQS_SHA3_shake256_x4 -#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_AVX2_shake256x4 OQS_SHA3_shake256_x4 -#define PQCLEAN_SPHINCSSHAKE256192SROBUST_AVX2_shake256x4 OQS_SHA3_shake256_x4 -#define PQCLEAN_SPHINCSSHAKE256192SSIMPLE_AVX2_shake256x4 OQS_SHA3_shake256_x4 -#define PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_shake256x4 OQS_SHA3_shake256_x4 -#define PQCLEAN_SPHINCSSHAKE256256FSIMPLE_AVX2_shake256x4 OQS_SHA3_shake256_x4 -#define PQCLEAN_SPHINCSSHAKE256256SROBUST_AVX2_shake256x4 OQS_SHA3_shake256_x4 -#define PQCLEAN_SPHINCSSHAKE256256SSIMPLE_AVX2_shake256x4 OQS_SHA3_shake256_x4 +#define shake256x4 OQS_SHA3_shake256_x4 +#define shake128x4 OQS_SHA3_shake128_x4 #define shake128x4_absorb_once OQS_SHA3_shake128_x4_absorb_once void OQS_SHA3_shake128_x4_absorb_once(shake128x4incctx *state, const uint8_t *in0, const uint8_t *in1, const uint8_t *in2, const uint8_t *in3, size_t inlen); diff --git a/src/kem/kem.c b/src/kem/kem.c index 97a79025ac..01448af121 100644 --- a/src/kem/kem.c +++ b/src/kem/kem.c @@ -34,9 +34,6 @@ OQS_API const char *OQS_KEM_alg_identifier(size_t i) { OQS_KEM_alg_kyber_512, OQS_KEM_alg_kyber_768, OQS_KEM_alg_kyber_1024, - OQS_KEM_alg_kyber_512_90s, - OQS_KEM_alg_kyber_768_90s, - OQS_KEM_alg_kyber_1024_90s, ///// OQS_COPY_FROM_UPSTREAM_FRAGMENT_ALG_IDENTIFIER_END OQS_KEM_alg_ntruprime_sntrup761, OQS_KEM_alg_frodokem_640_aes, @@ -174,24 +171,6 @@ OQS_API int OQS_KEM_alg_is_enabled(const char *method_name) { return 1; #else return 0; -#endif - } else if (0 == strcasecmp(method_name, OQS_KEM_alg_kyber_512_90s)) { -#ifdef OQS_ENABLE_KEM_kyber_512_90s - return 1; -#else - return 0; -#endif - } else if (0 == strcasecmp(method_name, OQS_KEM_alg_kyber_768_90s)) { -#ifdef OQS_ENABLE_KEM_kyber_768_90s - return 1; -#else - return 0; -#endif - } else if (0 == strcasecmp(method_name, OQS_KEM_alg_kyber_1024_90s)) { -#ifdef OQS_ENABLE_KEM_kyber_1024_90s - return 1; -#else - return 0; #endif ///// OQS_COPY_FROM_UPSTREAM_FRAGMENT_ENABLED_CASE_END } else if (0 == strcasecmp(method_name, OQS_KEM_alg_ntruprime_sntrup761)) { @@ -360,24 +339,6 @@ OQS_API OQS_KEM *OQS_KEM_new(const char *method_name) { return OQS_KEM_kyber_1024_new(); #else return NULL; -#endif - } else if (0 == strcasecmp(method_name, OQS_KEM_alg_kyber_512_90s)) { -#ifdef OQS_ENABLE_KEM_kyber_512_90s - return OQS_KEM_kyber_512_90s_new(); -#else - return NULL; -#endif - } else if (0 == strcasecmp(method_name, OQS_KEM_alg_kyber_768_90s)) { -#ifdef OQS_ENABLE_KEM_kyber_768_90s - return OQS_KEM_kyber_768_90s_new(); -#else - return NULL; -#endif - } else if (0 == strcasecmp(method_name, OQS_KEM_alg_kyber_1024_90s)) { -#ifdef OQS_ENABLE_KEM_kyber_1024_90s - return OQS_KEM_kyber_1024_90s_new(); -#else - return NULL; #endif ///// OQS_COPY_FROM_UPSTREAM_FRAGMENT_NEW_CASE_END } else if (0 == strcasecmp(method_name, OQS_KEM_alg_ntruprime_sntrup761)) { diff --git a/src/kem/kem.h b/src/kem/kem.h index 2b28851f9a..e2ea8d9d67 100644 --- a/src/kem/kem.h +++ b/src/kem/kem.h @@ -70,12 +70,6 @@ extern "C" { #define OQS_KEM_alg_kyber_768 "Kyber768" /** Algorithm identifier for Kyber1024 KEM. */ #define OQS_KEM_alg_kyber_1024 "Kyber1024" -/** Algorithm identifier for Kyber512-90s KEM. */ -#define OQS_KEM_alg_kyber_512_90s "Kyber512-90s" -/** Algorithm identifier for Kyber768-90s KEM. */ -#define OQS_KEM_alg_kyber_768_90s "Kyber768-90s" -/** Algorithm identifier for Kyber1024-90s KEM. */ -#define OQS_KEM_alg_kyber_1024_90s "Kyber1024-90s" ///// OQS_COPY_FROM_UPSTREAM_FRAGMENT_ALG_IDENTIFIER_END /** Algorithm identifier for sntrup761 KEM. */ #define OQS_KEM_alg_ntruprime_sntrup761 "sntrup761" @@ -94,7 +88,7 @@ extern "C" { // EDIT-WHEN-ADDING-KEM ///// OQS_COPY_FROM_UPSTREAM_FRAGMENT_ALGS_LENGTH_START /** Number of algorithm identifiers above. */ -#define OQS_KEM_algs_length 29 +#define OQS_KEM_algs_length 26 ///// OQS_COPY_FROM_UPSTREAM_FRAGMENT_ALGS_LENGTH_END /** diff --git a/src/kem/kyber/CMakeLists.txt b/src/kem/kyber/CMakeLists.txt index ce3ffc959b..0620b5b629 100644 --- a/src/kem/kyber/CMakeLists.txt +++ b/src/kem/kyber/CMakeLists.txt @@ -89,58 +89,4 @@ if(OQS_ENABLE_KEM_kyber_1024_aarch64) set(_KYBER_OBJS ${_KYBER_OBJS} $) endif() -if(OQS_ENABLE_KEM_kyber_512_90s) - add_library(kyber_512_90s_ref OBJECT kem_kyber_512_90s.c pqcrystals-kyber_kyber512-90s_ref/cbd.c pqcrystals-kyber_kyber512-90s_ref/indcpa.c pqcrystals-kyber_kyber512-90s_ref/kem.c pqcrystals-kyber_kyber512-90s_ref/ntt.c pqcrystals-kyber_kyber512-90s_ref/poly.c pqcrystals-kyber_kyber512-90s_ref/polyvec.c pqcrystals-kyber_kyber512-90s_ref/reduce.c pqcrystals-kyber_kyber512-90s_ref/symmetric-aes.c pqcrystals-kyber_kyber512-90s_ref/verify.c) - target_compile_options(kyber_512_90s_ref PUBLIC -DKYBER_K=2 -DKYBER_90S) - target_include_directories(kyber_512_90s_ref PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqcrystals-kyber_kyber512-90s_ref) - target_include_directories(kyber_512_90s_ref PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) - target_compile_options(kyber_512_90s_ref PUBLIC -DKYBER_K=2 -DKYBER_90S) - set(_KYBER_OBJS ${_KYBER_OBJS} $) -endif() - -if(OQS_ENABLE_KEM_kyber_512_90s_avx2) - add_library(kyber_512_90s_avx2 OBJECT pqcrystals-kyber_kyber512-90s_avx2/basemul.S pqcrystals-kyber_kyber512-90s_avx2/cbd.c pqcrystals-kyber_kyber512-90s_avx2/consts.c pqcrystals-kyber_kyber512-90s_avx2/fq.S pqcrystals-kyber_kyber512-90s_avx2/indcpa.c pqcrystals-kyber_kyber512-90s_avx2/invntt.S pqcrystals-kyber_kyber512-90s_avx2/kem.c pqcrystals-kyber_kyber512-90s_avx2/ntt.S pqcrystals-kyber_kyber512-90s_avx2/poly.c pqcrystals-kyber_kyber512-90s_avx2/polyvec.c pqcrystals-kyber_kyber512-90s_avx2/rejsample.c pqcrystals-kyber_kyber512-90s_avx2/shuffle.S pqcrystals-kyber_kyber512-90s_avx2/verify.c) - target_include_directories(kyber_512_90s_avx2 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqcrystals-kyber_kyber512-90s_avx2) - target_include_directories(kyber_512_90s_avx2 PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) - target_compile_options(kyber_512_90s_avx2 PRIVATE -maes -mavx2 -mbmi2 -mpopcnt ) - target_compile_options(kyber_512_90s_avx2 PUBLIC -DKYBER_K=2 -DKYBER_90S) - set(_KYBER_OBJS ${_KYBER_OBJS} $) -endif() - -if(OQS_ENABLE_KEM_kyber_768_90s) - add_library(kyber_768_90s_ref OBJECT kem_kyber_768_90s.c pqcrystals-kyber_kyber768-90s_ref/cbd.c pqcrystals-kyber_kyber768-90s_ref/indcpa.c pqcrystals-kyber_kyber768-90s_ref/kem.c pqcrystals-kyber_kyber768-90s_ref/ntt.c pqcrystals-kyber_kyber768-90s_ref/poly.c pqcrystals-kyber_kyber768-90s_ref/polyvec.c pqcrystals-kyber_kyber768-90s_ref/reduce.c pqcrystals-kyber_kyber768-90s_ref/symmetric-aes.c pqcrystals-kyber_kyber768-90s_ref/verify.c) - target_compile_options(kyber_768_90s_ref PUBLIC -DKYBER_K=3 -DKYBER_90S) - target_include_directories(kyber_768_90s_ref PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqcrystals-kyber_kyber768-90s_ref) - target_include_directories(kyber_768_90s_ref PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) - target_compile_options(kyber_768_90s_ref PUBLIC -DKYBER_K=3 -DKYBER_90S) - set(_KYBER_OBJS ${_KYBER_OBJS} $) -endif() - -if(OQS_ENABLE_KEM_kyber_768_90s_avx2) - add_library(kyber_768_90s_avx2 OBJECT pqcrystals-kyber_kyber768-90s_avx2/basemul.S pqcrystals-kyber_kyber768-90s_avx2/cbd.c pqcrystals-kyber_kyber768-90s_avx2/consts.c pqcrystals-kyber_kyber768-90s_avx2/fq.S pqcrystals-kyber_kyber768-90s_avx2/indcpa.c pqcrystals-kyber_kyber768-90s_avx2/invntt.S pqcrystals-kyber_kyber768-90s_avx2/kem.c pqcrystals-kyber_kyber768-90s_avx2/ntt.S pqcrystals-kyber_kyber768-90s_avx2/poly.c pqcrystals-kyber_kyber768-90s_avx2/polyvec.c pqcrystals-kyber_kyber768-90s_avx2/rejsample.c pqcrystals-kyber_kyber768-90s_avx2/shuffle.S pqcrystals-kyber_kyber768-90s_avx2/verify.c) - target_include_directories(kyber_768_90s_avx2 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqcrystals-kyber_kyber768-90s_avx2) - target_include_directories(kyber_768_90s_avx2 PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) - target_compile_options(kyber_768_90s_avx2 PRIVATE -maes -mavx2 -mbmi2 -mpopcnt ) - target_compile_options(kyber_768_90s_avx2 PUBLIC -DKYBER_K=3 -DKYBER_90S) - set(_KYBER_OBJS ${_KYBER_OBJS} $) -endif() - -if(OQS_ENABLE_KEM_kyber_1024_90s) - add_library(kyber_1024_90s_ref OBJECT kem_kyber_1024_90s.c pqcrystals-kyber_kyber1024-90s_ref/cbd.c pqcrystals-kyber_kyber1024-90s_ref/indcpa.c pqcrystals-kyber_kyber1024-90s_ref/kem.c pqcrystals-kyber_kyber1024-90s_ref/ntt.c pqcrystals-kyber_kyber1024-90s_ref/poly.c pqcrystals-kyber_kyber1024-90s_ref/polyvec.c pqcrystals-kyber_kyber1024-90s_ref/reduce.c pqcrystals-kyber_kyber1024-90s_ref/symmetric-aes.c pqcrystals-kyber_kyber1024-90s_ref/verify.c) - target_compile_options(kyber_1024_90s_ref PUBLIC -DKYBER_K=4 -DKYBER_90S) - target_include_directories(kyber_1024_90s_ref PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqcrystals-kyber_kyber1024-90s_ref) - target_include_directories(kyber_1024_90s_ref PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) - target_compile_options(kyber_1024_90s_ref PUBLIC -DKYBER_K=4 -DKYBER_90S) - set(_KYBER_OBJS ${_KYBER_OBJS} $) -endif() - -if(OQS_ENABLE_KEM_kyber_1024_90s_avx2) - add_library(kyber_1024_90s_avx2 OBJECT pqcrystals-kyber_kyber1024-90s_avx2/basemul.S pqcrystals-kyber_kyber1024-90s_avx2/cbd.c pqcrystals-kyber_kyber1024-90s_avx2/consts.c pqcrystals-kyber_kyber1024-90s_avx2/fq.S pqcrystals-kyber_kyber1024-90s_avx2/indcpa.c pqcrystals-kyber_kyber1024-90s_avx2/invntt.S pqcrystals-kyber_kyber1024-90s_avx2/kem.c pqcrystals-kyber_kyber1024-90s_avx2/ntt.S pqcrystals-kyber_kyber1024-90s_avx2/poly.c pqcrystals-kyber_kyber1024-90s_avx2/polyvec.c pqcrystals-kyber_kyber1024-90s_avx2/rejsample.c pqcrystals-kyber_kyber1024-90s_avx2/shuffle.S pqcrystals-kyber_kyber1024-90s_avx2/verify.c) - target_include_directories(kyber_1024_90s_avx2 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqcrystals-kyber_kyber1024-90s_avx2) - target_include_directories(kyber_1024_90s_avx2 PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) - target_compile_options(kyber_1024_90s_avx2 PRIVATE -maes -mavx2 -mbmi2 -mpopcnt ) - target_compile_options(kyber_1024_90s_avx2 PUBLIC -DKYBER_K=4 -DKYBER_90S) - set(_KYBER_OBJS ${_KYBER_OBJS} $) -endif() - set(KYBER_OBJS ${_KYBER_OBJS} PARENT_SCOPE) diff --git a/src/kem/kyber/kem_kyber.h b/src/kem/kyber/kem_kyber.h index 1fdbf95cc7..5d24808488 100644 --- a/src/kem/kyber/kem_kyber.h +++ b/src/kem/kyber/kem_kyber.h @@ -38,38 +38,5 @@ OQS_API OQS_STATUS OQS_KEM_kyber_1024_encaps(uint8_t *ciphertext, uint8_t *share OQS_API OQS_STATUS OQS_KEM_kyber_1024_decaps(uint8_t *shared_secret, const uint8_t *ciphertext, const uint8_t *secret_key); #endif -#ifdef OQS_ENABLE_KEM_kyber_512_90s -#define OQS_KEM_kyber_512_90s_length_public_key 800 -#define OQS_KEM_kyber_512_90s_length_secret_key 1632 -#define OQS_KEM_kyber_512_90s_length_ciphertext 768 -#define OQS_KEM_kyber_512_90s_length_shared_secret 32 -OQS_KEM *OQS_KEM_kyber_512_90s_new(void); -OQS_API OQS_STATUS OQS_KEM_kyber_512_90s_keypair(uint8_t *public_key, uint8_t *secret_key); -OQS_API OQS_STATUS OQS_KEM_kyber_512_90s_encaps(uint8_t *ciphertext, uint8_t *shared_secret, const uint8_t *public_key); -OQS_API OQS_STATUS OQS_KEM_kyber_512_90s_decaps(uint8_t *shared_secret, const uint8_t *ciphertext, const uint8_t *secret_key); -#endif - -#ifdef OQS_ENABLE_KEM_kyber_768_90s -#define OQS_KEM_kyber_768_90s_length_public_key 1184 -#define OQS_KEM_kyber_768_90s_length_secret_key 2400 -#define OQS_KEM_kyber_768_90s_length_ciphertext 1088 -#define OQS_KEM_kyber_768_90s_length_shared_secret 32 -OQS_KEM *OQS_KEM_kyber_768_90s_new(void); -OQS_API OQS_STATUS OQS_KEM_kyber_768_90s_keypair(uint8_t *public_key, uint8_t *secret_key); -OQS_API OQS_STATUS OQS_KEM_kyber_768_90s_encaps(uint8_t *ciphertext, uint8_t *shared_secret, const uint8_t *public_key); -OQS_API OQS_STATUS OQS_KEM_kyber_768_90s_decaps(uint8_t *shared_secret, const uint8_t *ciphertext, const uint8_t *secret_key); -#endif - -#ifdef OQS_ENABLE_KEM_kyber_1024_90s -#define OQS_KEM_kyber_1024_90s_length_public_key 1568 -#define OQS_KEM_kyber_1024_90s_length_secret_key 3168 -#define OQS_KEM_kyber_1024_90s_length_ciphertext 1568 -#define OQS_KEM_kyber_1024_90s_length_shared_secret 32 -OQS_KEM *OQS_KEM_kyber_1024_90s_new(void); -OQS_API OQS_STATUS OQS_KEM_kyber_1024_90s_keypair(uint8_t *public_key, uint8_t *secret_key); -OQS_API OQS_STATUS OQS_KEM_kyber_1024_90s_encaps(uint8_t *ciphertext, uint8_t *shared_secret, const uint8_t *public_key); -OQS_API OQS_STATUS OQS_KEM_kyber_1024_90s_decaps(uint8_t *shared_secret, const uint8_t *ciphertext, const uint8_t *secret_key); -#endif - #endif diff --git a/src/oqsconfig.h.cmake b/src/oqsconfig.h.cmake index bbbe189921..1428d5f358 100644 --- a/src/oqsconfig.h.cmake +++ b/src/oqsconfig.h.cmake @@ -109,12 +109,6 @@ #cmakedefine OQS_ENABLE_KEM_kyber_1024 1 #cmakedefine OQS_ENABLE_KEM_kyber_1024_avx2 1 #cmakedefine OQS_ENABLE_KEM_kyber_1024_aarch64 1 -#cmakedefine OQS_ENABLE_KEM_kyber_512_90s 1 -#cmakedefine OQS_ENABLE_KEM_kyber_512_90s_avx2 1 -#cmakedefine OQS_ENABLE_KEM_kyber_768_90s 1 -#cmakedefine OQS_ENABLE_KEM_kyber_768_90s_avx2 1 -#cmakedefine OQS_ENABLE_KEM_kyber_1024_90s 1 -#cmakedefine OQS_ENABLE_KEM_kyber_1024_90s_avx2 1 #cmakedefine OQS_ENABLE_SIG_DILITHIUM 1 #cmakedefine OQS_ENABLE_SIG_dilithium_2 1 @@ -126,12 +120,6 @@ #cmakedefine OQS_ENABLE_SIG_dilithium_5 1 #cmakedefine OQS_ENABLE_SIG_dilithium_5_avx2 1 #cmakedefine OQS_ENABLE_SIG_dilithium_5_aarch64 1 -#cmakedefine OQS_ENABLE_SIG_dilithium_2_aes 1 -#cmakedefine OQS_ENABLE_SIG_dilithium_2_aes_avx2 1 -#cmakedefine OQS_ENABLE_SIG_dilithium_3_aes 1 -#cmakedefine OQS_ENABLE_SIG_dilithium_3_aes_avx2 1 -#cmakedefine OQS_ENABLE_SIG_dilithium_5_aes 1 -#cmakedefine OQS_ENABLE_SIG_dilithium_5_aes_avx2 1 #cmakedefine OQS_ENABLE_SIG_FALCON 1 #cmakedefine OQS_ENABLE_SIG_falcon_512 1 @@ -154,20 +142,14 @@ #cmakedefine OQS_ENABLE_SIG_sphincs_sha256_256s_simple_avx2 1 #cmakedefine OQS_ENABLE_SIG_sphincs_shake256_128f_simple 1 #cmakedefine OQS_ENABLE_SIG_sphincs_shake256_128f_simple_avx2 1 -#cmakedefine OQS_ENABLE_SIG_sphincs_shake256_128f_simple_aarch64 1 #cmakedefine OQS_ENABLE_SIG_sphincs_shake256_128s_simple 1 #cmakedefine OQS_ENABLE_SIG_sphincs_shake256_128s_simple_avx2 1 -#cmakedefine OQS_ENABLE_SIG_sphincs_shake256_128s_simple_aarch64 1 #cmakedefine OQS_ENABLE_SIG_sphincs_shake256_192f_simple 1 #cmakedefine OQS_ENABLE_SIG_sphincs_shake256_192f_simple_avx2 1 -#cmakedefine OQS_ENABLE_SIG_sphincs_shake256_192f_simple_aarch64 1 #cmakedefine OQS_ENABLE_SIG_sphincs_shake256_192s_simple 1 #cmakedefine OQS_ENABLE_SIG_sphincs_shake256_192s_simple_avx2 1 -#cmakedefine OQS_ENABLE_SIG_sphincs_shake256_192s_simple_aarch64 1 #cmakedefine OQS_ENABLE_SIG_sphincs_shake256_256f_simple 1 #cmakedefine OQS_ENABLE_SIG_sphincs_shake256_256f_simple_avx2 1 -#cmakedefine OQS_ENABLE_SIG_sphincs_shake256_256f_simple_aarch64 1 #cmakedefine OQS_ENABLE_SIG_sphincs_shake256_256s_simple 1 #cmakedefine OQS_ENABLE_SIG_sphincs_shake256_256s_simple_avx2 1 -#cmakedefine OQS_ENABLE_SIG_sphincs_shake256_256s_simple_aarch64 1 ///// OQS_COPY_FROM_UPSTREAM_FRAGMENT_ADD_ALG_ENABLE_DEFINES_END diff --git a/src/sig/dilithium/CMakeLists.txt b/src/sig/dilithium/CMakeLists.txt index 484638cb13..b992392b46 100644 --- a/src/sig/dilithium/CMakeLists.txt +++ b/src/sig/dilithium/CMakeLists.txt @@ -83,58 +83,4 @@ if(OQS_ENABLE_SIG_dilithium_5_aarch64) set(_DILITHIUM_OBJS ${_DILITHIUM_OBJS} $) endif() -if(OQS_ENABLE_SIG_dilithium_2_aes) - add_library(dilithium_2_aes_ref OBJECT sig_dilithium_2_aes.c pqcrystals-dilithium_dilithium2aes_ref/ntt.c pqcrystals-dilithium_dilithium2aes_ref/packing.c pqcrystals-dilithium_dilithium2aes_ref/poly.c pqcrystals-dilithium_dilithium2aes_ref/polyvec.c pqcrystals-dilithium_dilithium2aes_ref/reduce.c pqcrystals-dilithium_dilithium2aes_ref/rounding.c pqcrystals-dilithium_dilithium2aes_ref/sign.c pqcrystals-dilithium_dilithium2aes_ref/symmetric-aes.c) - target_compile_options(dilithium_2_aes_ref PUBLIC -DDILITHIUM_MODE=2 -DDILITHIUM_USE_AES -DDILITHIUM_RANDOMIZED_SIGNING) - target_include_directories(dilithium_2_aes_ref PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqcrystals-dilithium_dilithium2aes_ref) - target_include_directories(dilithium_2_aes_ref PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) - target_compile_options(dilithium_2_aes_ref PUBLIC -DDILITHIUM_MODE=2 -DDILITHIUM_USE_AES -DDILITHIUM_RANDOMIZED_SIGNING) - set(_DILITHIUM_OBJS ${_DILITHIUM_OBJS} $) -endif() - -if(OQS_ENABLE_SIG_dilithium_2_aes_avx2) - add_library(dilithium_2_aes_avx2 OBJECT pqcrystals-dilithium_dilithium2aes_avx2/consts.c pqcrystals-dilithium_dilithium2aes_avx2/invntt.S pqcrystals-dilithium_dilithium2aes_avx2/ntt.S pqcrystals-dilithium_dilithium2aes_avx2/packing.c pqcrystals-dilithium_dilithium2aes_avx2/pointwise.S pqcrystals-dilithium_dilithium2aes_avx2/poly.c pqcrystals-dilithium_dilithium2aes_avx2/polyvec.c pqcrystals-dilithium_dilithium2aes_avx2/rejsample.c pqcrystals-dilithium_dilithium2aes_avx2/rounding.c pqcrystals-dilithium_dilithium2aes_avx2/shuffle.S pqcrystals-dilithium_dilithium2aes_avx2/sign.c) - target_include_directories(dilithium_2_aes_avx2 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqcrystals-dilithium_dilithium2aes_avx2) - target_include_directories(dilithium_2_aes_avx2 PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) - target_compile_options(dilithium_2_aes_avx2 PRIVATE -mavx2 -maes -mpopcnt) - target_compile_options(dilithium_2_aes_avx2 PUBLIC -DDILITHIUM_MODE=2 -DDILITHIUM_USE_AES -DDILITHIUM_RANDOMIZED_SIGNING) - set(_DILITHIUM_OBJS ${_DILITHIUM_OBJS} $) -endif() - -if(OQS_ENABLE_SIG_dilithium_3_aes) - add_library(dilithium_3_aes_ref OBJECT sig_dilithium_3_aes.c pqcrystals-dilithium_dilithium3aes_ref/ntt.c pqcrystals-dilithium_dilithium3aes_ref/packing.c pqcrystals-dilithium_dilithium3aes_ref/poly.c pqcrystals-dilithium_dilithium3aes_ref/polyvec.c pqcrystals-dilithium_dilithium3aes_ref/reduce.c pqcrystals-dilithium_dilithium3aes_ref/rounding.c pqcrystals-dilithium_dilithium3aes_ref/sign.c pqcrystals-dilithium_dilithium3aes_ref/symmetric-aes.c) - target_compile_options(dilithium_3_aes_ref PUBLIC -DDILITHIUM_MODE=3 -DDILITHIUM_USE_AES -DDILITHIUM_RANDOMIZED_SIGNING) - target_include_directories(dilithium_3_aes_ref PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqcrystals-dilithium_dilithium3aes_ref) - target_include_directories(dilithium_3_aes_ref PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) - target_compile_options(dilithium_3_aes_ref PUBLIC -DDILITHIUM_MODE=3 -DDILITHIUM_USE_AES -DDILITHIUM_RANDOMIZED_SIGNING) - set(_DILITHIUM_OBJS ${_DILITHIUM_OBJS} $) -endif() - -if(OQS_ENABLE_SIG_dilithium_3_aes_avx2) - add_library(dilithium_3_aes_avx2 OBJECT pqcrystals-dilithium_dilithium3aes_avx2/consts.c pqcrystals-dilithium_dilithium3aes_avx2/invntt.S pqcrystals-dilithium_dilithium3aes_avx2/ntt.S pqcrystals-dilithium_dilithium3aes_avx2/packing.c pqcrystals-dilithium_dilithium3aes_avx2/pointwise.S pqcrystals-dilithium_dilithium3aes_avx2/poly.c pqcrystals-dilithium_dilithium3aes_avx2/polyvec.c pqcrystals-dilithium_dilithium3aes_avx2/rejsample.c pqcrystals-dilithium_dilithium3aes_avx2/rounding.c pqcrystals-dilithium_dilithium3aes_avx2/shuffle.S pqcrystals-dilithium_dilithium3aes_avx2/sign.c) - target_include_directories(dilithium_3_aes_avx2 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqcrystals-dilithium_dilithium3aes_avx2) - target_include_directories(dilithium_3_aes_avx2 PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) - target_compile_options(dilithium_3_aes_avx2 PRIVATE -mavx2 -maes -mpopcnt) - target_compile_options(dilithium_3_aes_avx2 PUBLIC -DDILITHIUM_MODE=3 -DDILITHIUM_USE_AES -DDILITHIUM_RANDOMIZED_SIGNING) - set(_DILITHIUM_OBJS ${_DILITHIUM_OBJS} $) -endif() - -if(OQS_ENABLE_SIG_dilithium_5_aes) - add_library(dilithium_5_aes_ref OBJECT sig_dilithium_5_aes.c pqcrystals-dilithium_dilithium5aes_ref/ntt.c pqcrystals-dilithium_dilithium5aes_ref/packing.c pqcrystals-dilithium_dilithium5aes_ref/poly.c pqcrystals-dilithium_dilithium5aes_ref/polyvec.c pqcrystals-dilithium_dilithium5aes_ref/reduce.c pqcrystals-dilithium_dilithium5aes_ref/rounding.c pqcrystals-dilithium_dilithium5aes_ref/sign.c pqcrystals-dilithium_dilithium5aes_ref/symmetric-aes.c) - target_compile_options(dilithium_5_aes_ref PUBLIC -DDILITHIUM_MODE=5 -DDILITHIUM_USE_AES -DDILITHIUM_RANDOMIZED_SIGNING) - target_include_directories(dilithium_5_aes_ref PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqcrystals-dilithium_dilithium5aes_ref) - target_include_directories(dilithium_5_aes_ref PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) - target_compile_options(dilithium_5_aes_ref PUBLIC -DDILITHIUM_MODE=5 -DDILITHIUM_USE_AES -DDILITHIUM_RANDOMIZED_SIGNING) - set(_DILITHIUM_OBJS ${_DILITHIUM_OBJS} $) -endif() - -if(OQS_ENABLE_SIG_dilithium_5_aes_avx2) - add_library(dilithium_5_aes_avx2 OBJECT pqcrystals-dilithium_dilithium5aes_avx2/consts.c pqcrystals-dilithium_dilithium5aes_avx2/invntt.S pqcrystals-dilithium_dilithium5aes_avx2/ntt.S pqcrystals-dilithium_dilithium5aes_avx2/packing.c pqcrystals-dilithium_dilithium5aes_avx2/pointwise.S pqcrystals-dilithium_dilithium5aes_avx2/poly.c pqcrystals-dilithium_dilithium5aes_avx2/polyvec.c pqcrystals-dilithium_dilithium5aes_avx2/rejsample.c pqcrystals-dilithium_dilithium5aes_avx2/rounding.c pqcrystals-dilithium_dilithium5aes_avx2/shuffle.S pqcrystals-dilithium_dilithium5aes_avx2/sign.c) - target_include_directories(dilithium_5_aes_avx2 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqcrystals-dilithium_dilithium5aes_avx2) - target_include_directories(dilithium_5_aes_avx2 PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) - target_compile_options(dilithium_5_aes_avx2 PRIVATE -mavx2 -maes -mpopcnt) - target_compile_options(dilithium_5_aes_avx2 PUBLIC -DDILITHIUM_MODE=5 -DDILITHIUM_USE_AES -DDILITHIUM_RANDOMIZED_SIGNING) - set(_DILITHIUM_OBJS ${_DILITHIUM_OBJS} $) -endif() - set(DILITHIUM_OBJS ${_DILITHIUM_OBJS} PARENT_SCOPE) diff --git a/src/sig/dilithium/sig_dilithium.h b/src/sig/dilithium/sig_dilithium.h index 04b6b8841a..b63ea73b4b 100644 --- a/src/sig/dilithium/sig_dilithium.h +++ b/src/sig/dilithium/sig_dilithium.h @@ -38,37 +38,4 @@ OQS_API OQS_STATUS OQS_SIG_dilithium_5_sign(uint8_t *signature, size_t *signatur OQS_API OQS_STATUS OQS_SIG_dilithium_5_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key); #endif -#ifdef OQS_ENABLE_SIG_dilithium_2_aes -#define OQS_SIG_dilithium_2_aes_length_public_key 1312 -#define OQS_SIG_dilithium_2_aes_length_secret_key 2528 -#define OQS_SIG_dilithium_2_aes_length_signature 2420 - -OQS_SIG *OQS_SIG_dilithium_2_aes_new(void); -OQS_API OQS_STATUS OQS_SIG_dilithium_2_aes_keypair(uint8_t *public_key, uint8_t *secret_key); -OQS_API OQS_STATUS OQS_SIG_dilithium_2_aes_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, const uint8_t *secret_key); -OQS_API OQS_STATUS OQS_SIG_dilithium_2_aes_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key); -#endif - -#ifdef OQS_ENABLE_SIG_dilithium_3_aes -#define OQS_SIG_dilithium_3_aes_length_public_key 1952 -#define OQS_SIG_dilithium_3_aes_length_secret_key 4000 -#define OQS_SIG_dilithium_3_aes_length_signature 3293 - -OQS_SIG *OQS_SIG_dilithium_3_aes_new(void); -OQS_API OQS_STATUS OQS_SIG_dilithium_3_aes_keypair(uint8_t *public_key, uint8_t *secret_key); -OQS_API OQS_STATUS OQS_SIG_dilithium_3_aes_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, const uint8_t *secret_key); -OQS_API OQS_STATUS OQS_SIG_dilithium_3_aes_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key); -#endif - -#ifdef OQS_ENABLE_SIG_dilithium_5_aes -#define OQS_SIG_dilithium_5_aes_length_public_key 2592 -#define OQS_SIG_dilithium_5_aes_length_secret_key 4864 -#define OQS_SIG_dilithium_5_aes_length_signature 4595 - -OQS_SIG *OQS_SIG_dilithium_5_aes_new(void); -OQS_API OQS_STATUS OQS_SIG_dilithium_5_aes_keypair(uint8_t *public_key, uint8_t *secret_key); -OQS_API OQS_STATUS OQS_SIG_dilithium_5_aes_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, const uint8_t *secret_key); -OQS_API OQS_STATUS OQS_SIG_dilithium_5_aes_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key); -#endif - #endif diff --git a/src/sig/sig.c b/src/sig/sig.c index 4542c877d6..3a62c16fa9 100644 --- a/src/sig/sig.c +++ b/src/sig/sig.c @@ -18,9 +18,6 @@ OQS_API const char *OQS_SIG_alg_identifier(size_t i) { OQS_SIG_alg_dilithium_2, OQS_SIG_alg_dilithium_3, OQS_SIG_alg_dilithium_5, - OQS_SIG_alg_dilithium_2_aes, - OQS_SIG_alg_dilithium_3_aes, - OQS_SIG_alg_dilithium_5_aes, OQS_SIG_alg_falcon_512, OQS_SIG_alg_falcon_1024, OQS_SIG_alg_sphincs_sha256_128f_simple, @@ -71,24 +68,6 @@ OQS_API int OQS_SIG_alg_is_enabled(const char *method_name) { return 1; #else return 0; -#endif - } else if (0 == strcasecmp(method_name, OQS_SIG_alg_dilithium_2_aes)) { -#ifdef OQS_ENABLE_SIG_dilithium_2_aes - return 1; -#else - return 0; -#endif - } else if (0 == strcasecmp(method_name, OQS_SIG_alg_dilithium_3_aes)) { -#ifdef OQS_ENABLE_SIG_dilithium_3_aes - return 1; -#else - return 0; -#endif - } else if (0 == strcasecmp(method_name, OQS_SIG_alg_dilithium_5_aes)) { -#ifdef OQS_ENABLE_SIG_dilithium_5_aes - return 1; -#else - return 0; #endif } else if (0 == strcasecmp(method_name, OQS_SIG_alg_falcon_512)) { #ifdef OQS_ENABLE_SIG_falcon_512 @@ -203,24 +182,6 @@ OQS_API OQS_SIG *OQS_SIG_new(const char *method_name) { return OQS_SIG_dilithium_5_new(); #else return NULL; -#endif - } else if (0 == strcasecmp(method_name, OQS_SIG_alg_dilithium_2_aes)) { -#ifdef OQS_ENABLE_SIG_dilithium_2_aes - return OQS_SIG_dilithium_2_aes_new(); -#else - return NULL; -#endif - } else if (0 == strcasecmp(method_name, OQS_SIG_alg_dilithium_3_aes)) { -#ifdef OQS_ENABLE_SIG_dilithium_3_aes - return OQS_SIG_dilithium_3_aes_new(); -#else - return NULL; -#endif - } else if (0 == strcasecmp(method_name, OQS_SIG_alg_dilithium_5_aes)) { -#ifdef OQS_ENABLE_SIG_dilithium_5_aes - return OQS_SIG_dilithium_5_aes_new(); -#else - return NULL; #endif } else if (0 == strcasecmp(method_name, OQS_SIG_alg_falcon_512)) { #ifdef OQS_ENABLE_SIG_falcon_512 diff --git a/src/sig/sig.h b/src/sig/sig.h index 5ac82c339f..6ac5f27b36 100644 --- a/src/sig/sig.h +++ b/src/sig/sig.h @@ -38,12 +38,6 @@ extern "C" { #define OQS_SIG_alg_dilithium_3 "Dilithium3" /** Algorithm identifier for Dilithium5 */ #define OQS_SIG_alg_dilithium_5 "Dilithium5" -/** Algorithm identifier for Dilithium2-AES */ -#define OQS_SIG_alg_dilithium_2_aes "Dilithium2-AES" -/** Algorithm identifier for Dilithium3-AES */ -#define OQS_SIG_alg_dilithium_3_aes "Dilithium3-AES" -/** Algorithm identifier for Dilithium5-AES */ -#define OQS_SIG_alg_dilithium_5_aes "Dilithium5-AES" /** Algorithm identifier for Falcon-512 */ #define OQS_SIG_alg_falcon_512 "Falcon-512" /** Algorithm identifier for Falcon-1024 */ @@ -76,7 +70,7 @@ extern "C" { // EDIT-WHEN-ADDING-SIG ///// OQS_COPY_FROM_UPSTREAM_FRAGMENT_ALGS_LENGTH_START /** Number of algorithm identifiers above. */ -#define OQS_SIG_algs_length 20 +#define OQS_SIG_algs_length 17 ///// OQS_COPY_FROM_UPSTREAM_FRAGMENT_ALGS_LENGTH_END /** diff --git a/src/sig/sphincs/CMakeLists.txt b/src/sig/sphincs/CMakeLists.txt index 74925f503e..50cd4f2d1e 100644 --- a/src/sig/sphincs/CMakeLists.txt +++ b/src/sig/sphincs/CMakeLists.txt @@ -103,21 +103,13 @@ if(OQS_ENABLE_SIG_sphincs_shake256_128f_simple) endif() if(OQS_ENABLE_SIG_sphincs_shake256_128f_simple_avx2) - add_library(sphincs_shake256_128f_simple_avx2 OBJECT pqclean_sphincs-shake-128f-simple_avx2/address.c pqclean_sphincs-shake-128f-simple_avx2/context_shake.c pqclean_sphincs-shake-128f-simple_avx2/fips202x4.c pqclean_sphincs-shake-128f-simple_avx2/fors.c pqclean_sphincs-shake-128f-simple_avx2/hash_shake.c pqclean_sphincs-shake-128f-simple_avx2/hash_shakex4.c pqclean_sphincs-shake-128f-simple_avx2/merkle.c pqclean_sphincs-shake-128f-simple_avx2/sign.c pqclean_sphincs-shake-128f-simple_avx2/thash_shake_simple.c pqclean_sphincs-shake-128f-simple_avx2/thash_shake_simplex4.c pqclean_sphincs-shake-128f-simple_avx2/utils.c pqclean_sphincs-shake-128f-simple_avx2/utilsx4.c pqclean_sphincs-shake-128f-simple_avx2/wots.c) + add_library(sphincs_shake256_128f_simple_avx2 OBJECT pqclean_sphincs-shake-128f-simple_avx2/address.c pqclean_sphincs-shake-128f-simple_avx2/context_shake.c pqclean_sphincs-shake-128f-simple_avx2/fors.c pqclean_sphincs-shake-128f-simple_avx2/hash_shake.c pqclean_sphincs-shake-128f-simple_avx2/hash_shakex4.c pqclean_sphincs-shake-128f-simple_avx2/merkle.c pqclean_sphincs-shake-128f-simple_avx2/sign.c pqclean_sphincs-shake-128f-simple_avx2/thash_shake_simple.c pqclean_sphincs-shake-128f-simple_avx2/thash_shake_simplex4.c pqclean_sphincs-shake-128f-simple_avx2/utils.c pqclean_sphincs-shake-128f-simple_avx2/utilsx4.c pqclean_sphincs-shake-128f-simple_avx2/wots.c) target_include_directories(sphincs_shake256_128f_simple_avx2 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-shake-128f-simple_avx2) target_include_directories(sphincs_shake256_128f_simple_avx2 PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) target_compile_options(sphincs_shake256_128f_simple_avx2 PRIVATE -mavx2) set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) endif() -if(OQS_ENABLE_SIG_sphincs_shake256_128f_simple_aarch64) - add_library(sphincs_shake256_128f_simple_aarch64 OBJECT pqclean_sphincs-shake-128f-simple_aarch64/address.c pqclean_sphincs-shake-128f-simple_aarch64/context_shake.c pqclean_sphincs-shake-128f-simple_aarch64/f1600x2.s pqclean_sphincs-shake-128f-simple_aarch64/f1600x2_const.c pqclean_sphincs-shake-128f-simple_aarch64/fips202x2.c pqclean_sphincs-shake-128f-simple_aarch64/fors.c pqclean_sphincs-shake-128f-simple_aarch64/hash_shake.c pqclean_sphincs-shake-128f-simple_aarch64/hash_shakex2.c pqclean_sphincs-shake-128f-simple_aarch64/merkle.c pqclean_sphincs-shake-128f-simple_aarch64/sign.c pqclean_sphincs-shake-128f-simple_aarch64/thash_shake_simplex2.c pqclean_sphincs-shake-128f-simple_aarch64/utils.c pqclean_sphincs-shake-128f-simple_aarch64/utilsx2.c pqclean_sphincs-shake-128f-simple_aarch64/wots.c) - target_include_directories(sphincs_shake256_128f_simple_aarch64 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-shake-128f-simple_aarch64) - target_include_directories(sphincs_shake256_128f_simple_aarch64 PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) - target_compile_options(sphincs_shake256_128f_simple_aarch64 PRIVATE -march=armv8-a+crypto+sha3) - set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) -endif() - if(OQS_ENABLE_SIG_sphincs_shake256_128s_simple) add_library(sphincs_shake256_128s_simple_clean OBJECT sig_sphincs_shake256_128s_simple.c pqclean_sphincs-shake-128s-simple_clean/address.c pqclean_sphincs-shake-128s-simple_clean/context_shake.c pqclean_sphincs-shake-128s-simple_clean/fors.c pqclean_sphincs-shake-128s-simple_clean/hash_shake.c pqclean_sphincs-shake-128s-simple_clean/merkle.c pqclean_sphincs-shake-128s-simple_clean/sign.c pqclean_sphincs-shake-128s-simple_clean/thash_shake_simple.c pqclean_sphincs-shake-128s-simple_clean/utils.c pqclean_sphincs-shake-128s-simple_clean/utilsx1.c pqclean_sphincs-shake-128s-simple_clean/wots.c pqclean_sphincs-shake-128s-simple_clean/wotsx1.c) target_include_directories(sphincs_shake256_128s_simple_clean PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-shake-128s-simple_clean) @@ -126,21 +118,13 @@ if(OQS_ENABLE_SIG_sphincs_shake256_128s_simple) endif() if(OQS_ENABLE_SIG_sphincs_shake256_128s_simple_avx2) - add_library(sphincs_shake256_128s_simple_avx2 OBJECT pqclean_sphincs-shake-128s-simple_avx2/address.c pqclean_sphincs-shake-128s-simple_avx2/context_shake.c pqclean_sphincs-shake-128s-simple_avx2/fips202x4.c pqclean_sphincs-shake-128s-simple_avx2/fors.c pqclean_sphincs-shake-128s-simple_avx2/hash_shake.c pqclean_sphincs-shake-128s-simple_avx2/hash_shakex4.c pqclean_sphincs-shake-128s-simple_avx2/merkle.c pqclean_sphincs-shake-128s-simple_avx2/sign.c pqclean_sphincs-shake-128s-simple_avx2/thash_shake_simple.c pqclean_sphincs-shake-128s-simple_avx2/thash_shake_simplex4.c pqclean_sphincs-shake-128s-simple_avx2/utils.c pqclean_sphincs-shake-128s-simple_avx2/utilsx4.c pqclean_sphincs-shake-128s-simple_avx2/wots.c) + add_library(sphincs_shake256_128s_simple_avx2 OBJECT pqclean_sphincs-shake-128s-simple_avx2/address.c pqclean_sphincs-shake-128s-simple_avx2/context_shake.c pqclean_sphincs-shake-128s-simple_avx2/fors.c pqclean_sphincs-shake-128s-simple_avx2/hash_shake.c pqclean_sphincs-shake-128s-simple_avx2/hash_shakex4.c pqclean_sphincs-shake-128s-simple_avx2/merkle.c pqclean_sphincs-shake-128s-simple_avx2/sign.c pqclean_sphincs-shake-128s-simple_avx2/thash_shake_simple.c pqclean_sphincs-shake-128s-simple_avx2/thash_shake_simplex4.c pqclean_sphincs-shake-128s-simple_avx2/utils.c pqclean_sphincs-shake-128s-simple_avx2/utilsx4.c pqclean_sphincs-shake-128s-simple_avx2/wots.c) target_include_directories(sphincs_shake256_128s_simple_avx2 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-shake-128s-simple_avx2) target_include_directories(sphincs_shake256_128s_simple_avx2 PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) target_compile_options(sphincs_shake256_128s_simple_avx2 PRIVATE -mavx2) set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) endif() -if(OQS_ENABLE_SIG_sphincs_shake256_128s_simple_aarch64) - add_library(sphincs_shake256_128s_simple_aarch64 OBJECT pqclean_sphincs-shake-128s-simple_aarch64/address.c pqclean_sphincs-shake-128s-simple_aarch64/context_shake.c pqclean_sphincs-shake-128s-simple_aarch64/f1600x2.s pqclean_sphincs-shake-128s-simple_aarch64/f1600x2_const.c pqclean_sphincs-shake-128s-simple_aarch64/fips202x2.c pqclean_sphincs-shake-128s-simple_aarch64/fors.c pqclean_sphincs-shake-128s-simple_aarch64/hash_shake.c pqclean_sphincs-shake-128s-simple_aarch64/hash_shakex2.c pqclean_sphincs-shake-128s-simple_aarch64/merkle.c pqclean_sphincs-shake-128s-simple_aarch64/sign.c pqclean_sphincs-shake-128s-simple_aarch64/thash_shake_simplex2.c pqclean_sphincs-shake-128s-simple_aarch64/utils.c pqclean_sphincs-shake-128s-simple_aarch64/utilsx2.c pqclean_sphincs-shake-128s-simple_aarch64/wots.c) - target_include_directories(sphincs_shake256_128s_simple_aarch64 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-shake-128s-simple_aarch64) - target_include_directories(sphincs_shake256_128s_simple_aarch64 PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) - target_compile_options(sphincs_shake256_128s_simple_aarch64 PRIVATE -march=armv8-a+crypto+sha3) - set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) -endif() - if(OQS_ENABLE_SIG_sphincs_shake256_192f_simple) add_library(sphincs_shake256_192f_simple_clean OBJECT sig_sphincs_shake256_192f_simple.c pqclean_sphincs-shake-192f-simple_clean/address.c pqclean_sphincs-shake-192f-simple_clean/context_shake.c pqclean_sphincs-shake-192f-simple_clean/fors.c pqclean_sphincs-shake-192f-simple_clean/hash_shake.c pqclean_sphincs-shake-192f-simple_clean/merkle.c pqclean_sphincs-shake-192f-simple_clean/sign.c pqclean_sphincs-shake-192f-simple_clean/thash_shake_simple.c pqclean_sphincs-shake-192f-simple_clean/utils.c pqclean_sphincs-shake-192f-simple_clean/utilsx1.c pqclean_sphincs-shake-192f-simple_clean/wots.c pqclean_sphincs-shake-192f-simple_clean/wotsx1.c) target_include_directories(sphincs_shake256_192f_simple_clean PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-shake-192f-simple_clean) @@ -149,21 +133,13 @@ if(OQS_ENABLE_SIG_sphincs_shake256_192f_simple) endif() if(OQS_ENABLE_SIG_sphincs_shake256_192f_simple_avx2) - add_library(sphincs_shake256_192f_simple_avx2 OBJECT pqclean_sphincs-shake-192f-simple_avx2/address.c pqclean_sphincs-shake-192f-simple_avx2/context_shake.c pqclean_sphincs-shake-192f-simple_avx2/fips202x4.c pqclean_sphincs-shake-192f-simple_avx2/fors.c pqclean_sphincs-shake-192f-simple_avx2/hash_shake.c pqclean_sphincs-shake-192f-simple_avx2/hash_shakex4.c pqclean_sphincs-shake-192f-simple_avx2/merkle.c pqclean_sphincs-shake-192f-simple_avx2/sign.c pqclean_sphincs-shake-192f-simple_avx2/thash_shake_simple.c pqclean_sphincs-shake-192f-simple_avx2/thash_shake_simplex4.c pqclean_sphincs-shake-192f-simple_avx2/utils.c pqclean_sphincs-shake-192f-simple_avx2/utilsx4.c pqclean_sphincs-shake-192f-simple_avx2/wots.c) + add_library(sphincs_shake256_192f_simple_avx2 OBJECT pqclean_sphincs-shake-192f-simple_avx2/address.c pqclean_sphincs-shake-192f-simple_avx2/context_shake.c pqclean_sphincs-shake-192f-simple_avx2/fors.c pqclean_sphincs-shake-192f-simple_avx2/hash_shake.c pqclean_sphincs-shake-192f-simple_avx2/hash_shakex4.c pqclean_sphincs-shake-192f-simple_avx2/merkle.c pqclean_sphincs-shake-192f-simple_avx2/sign.c pqclean_sphincs-shake-192f-simple_avx2/thash_shake_simple.c pqclean_sphincs-shake-192f-simple_avx2/thash_shake_simplex4.c pqclean_sphincs-shake-192f-simple_avx2/utils.c pqclean_sphincs-shake-192f-simple_avx2/utilsx4.c pqclean_sphincs-shake-192f-simple_avx2/wots.c) target_include_directories(sphincs_shake256_192f_simple_avx2 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-shake-192f-simple_avx2) target_include_directories(sphincs_shake256_192f_simple_avx2 PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) target_compile_options(sphincs_shake256_192f_simple_avx2 PRIVATE -mavx2) set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) endif() -if(OQS_ENABLE_SIG_sphincs_shake256_192f_simple_aarch64) - add_library(sphincs_shake256_192f_simple_aarch64 OBJECT pqclean_sphincs-shake-192f-simple_aarch64/address.c pqclean_sphincs-shake-192f-simple_aarch64/context_shake.c pqclean_sphincs-shake-192f-simple_aarch64/f1600x2.s pqclean_sphincs-shake-192f-simple_aarch64/f1600x2_const.c pqclean_sphincs-shake-192f-simple_aarch64/fips202x2.c pqclean_sphincs-shake-192f-simple_aarch64/fors.c pqclean_sphincs-shake-192f-simple_aarch64/hash_shake.c pqclean_sphincs-shake-192f-simple_aarch64/hash_shakex2.c pqclean_sphincs-shake-192f-simple_aarch64/merkle.c pqclean_sphincs-shake-192f-simple_aarch64/sign.c pqclean_sphincs-shake-192f-simple_aarch64/thash_shake_simplex2.c pqclean_sphincs-shake-192f-simple_aarch64/utils.c pqclean_sphincs-shake-192f-simple_aarch64/utilsx2.c pqclean_sphincs-shake-192f-simple_aarch64/wots.c) - target_include_directories(sphincs_shake256_192f_simple_aarch64 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-shake-192f-simple_aarch64) - target_include_directories(sphincs_shake256_192f_simple_aarch64 PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) - target_compile_options(sphincs_shake256_192f_simple_aarch64 PRIVATE -march=armv8-a+crypto+sha3) - set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) -endif() - if(OQS_ENABLE_SIG_sphincs_shake256_192s_simple) add_library(sphincs_shake256_192s_simple_clean OBJECT sig_sphincs_shake256_192s_simple.c pqclean_sphincs-shake-192s-simple_clean/address.c pqclean_sphincs-shake-192s-simple_clean/context_shake.c pqclean_sphincs-shake-192s-simple_clean/fors.c pqclean_sphincs-shake-192s-simple_clean/hash_shake.c pqclean_sphincs-shake-192s-simple_clean/merkle.c pqclean_sphincs-shake-192s-simple_clean/sign.c pqclean_sphincs-shake-192s-simple_clean/thash_shake_simple.c pqclean_sphincs-shake-192s-simple_clean/utils.c pqclean_sphincs-shake-192s-simple_clean/utilsx1.c pqclean_sphincs-shake-192s-simple_clean/wots.c pqclean_sphincs-shake-192s-simple_clean/wotsx1.c) target_include_directories(sphincs_shake256_192s_simple_clean PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-shake-192s-simple_clean) @@ -172,21 +148,13 @@ if(OQS_ENABLE_SIG_sphincs_shake256_192s_simple) endif() if(OQS_ENABLE_SIG_sphincs_shake256_192s_simple_avx2) - add_library(sphincs_shake256_192s_simple_avx2 OBJECT pqclean_sphincs-shake-192s-simple_avx2/address.c pqclean_sphincs-shake-192s-simple_avx2/context_shake.c pqclean_sphincs-shake-192s-simple_avx2/fips202x4.c pqclean_sphincs-shake-192s-simple_avx2/fors.c pqclean_sphincs-shake-192s-simple_avx2/hash_shake.c pqclean_sphincs-shake-192s-simple_avx2/hash_shakex4.c pqclean_sphincs-shake-192s-simple_avx2/merkle.c pqclean_sphincs-shake-192s-simple_avx2/sign.c pqclean_sphincs-shake-192s-simple_avx2/thash_shake_simple.c pqclean_sphincs-shake-192s-simple_avx2/thash_shake_simplex4.c pqclean_sphincs-shake-192s-simple_avx2/utils.c pqclean_sphincs-shake-192s-simple_avx2/utilsx4.c pqclean_sphincs-shake-192s-simple_avx2/wots.c) + add_library(sphincs_shake256_192s_simple_avx2 OBJECT pqclean_sphincs-shake-192s-simple_avx2/address.c pqclean_sphincs-shake-192s-simple_avx2/context_shake.c pqclean_sphincs-shake-192s-simple_avx2/fors.c pqclean_sphincs-shake-192s-simple_avx2/hash_shake.c pqclean_sphincs-shake-192s-simple_avx2/hash_shakex4.c pqclean_sphincs-shake-192s-simple_avx2/merkle.c pqclean_sphincs-shake-192s-simple_avx2/sign.c pqclean_sphincs-shake-192s-simple_avx2/thash_shake_simple.c pqclean_sphincs-shake-192s-simple_avx2/thash_shake_simplex4.c pqclean_sphincs-shake-192s-simple_avx2/utils.c pqclean_sphincs-shake-192s-simple_avx2/utilsx4.c pqclean_sphincs-shake-192s-simple_avx2/wots.c) target_include_directories(sphincs_shake256_192s_simple_avx2 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-shake-192s-simple_avx2) target_include_directories(sphincs_shake256_192s_simple_avx2 PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) target_compile_options(sphincs_shake256_192s_simple_avx2 PRIVATE -mavx2) set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) endif() -if(OQS_ENABLE_SIG_sphincs_shake256_192s_simple_aarch64) - add_library(sphincs_shake256_192s_simple_aarch64 OBJECT pqclean_sphincs-shake-192s-simple_aarch64/address.c pqclean_sphincs-shake-192s-simple_aarch64/context_shake.c pqclean_sphincs-shake-192s-simple_aarch64/f1600x2.s pqclean_sphincs-shake-192s-simple_aarch64/f1600x2_const.c pqclean_sphincs-shake-192s-simple_aarch64/fips202x2.c pqclean_sphincs-shake-192s-simple_aarch64/fors.c pqclean_sphincs-shake-192s-simple_aarch64/hash_shake.c pqclean_sphincs-shake-192s-simple_aarch64/hash_shakex2.c pqclean_sphincs-shake-192s-simple_aarch64/merkle.c pqclean_sphincs-shake-192s-simple_aarch64/sign.c pqclean_sphincs-shake-192s-simple_aarch64/thash_shake_simplex2.c pqclean_sphincs-shake-192s-simple_aarch64/utils.c pqclean_sphincs-shake-192s-simple_aarch64/utilsx2.c pqclean_sphincs-shake-192s-simple_aarch64/wots.c) - target_include_directories(sphincs_shake256_192s_simple_aarch64 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-shake-192s-simple_aarch64) - target_include_directories(sphincs_shake256_192s_simple_aarch64 PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) - target_compile_options(sphincs_shake256_192s_simple_aarch64 PRIVATE -march=armv8-a+crypto+sha3) - set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) -endif() - if(OQS_ENABLE_SIG_sphincs_shake256_256f_simple) add_library(sphincs_shake256_256f_simple_clean OBJECT sig_sphincs_shake256_256f_simple.c pqclean_sphincs-shake-256f-simple_clean/address.c pqclean_sphincs-shake-256f-simple_clean/context_shake.c pqclean_sphincs-shake-256f-simple_clean/fors.c pqclean_sphincs-shake-256f-simple_clean/hash_shake.c pqclean_sphincs-shake-256f-simple_clean/merkle.c pqclean_sphincs-shake-256f-simple_clean/sign.c pqclean_sphincs-shake-256f-simple_clean/thash_shake_simple.c pqclean_sphincs-shake-256f-simple_clean/utils.c pqclean_sphincs-shake-256f-simple_clean/utilsx1.c pqclean_sphincs-shake-256f-simple_clean/wots.c pqclean_sphincs-shake-256f-simple_clean/wotsx1.c) target_include_directories(sphincs_shake256_256f_simple_clean PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-shake-256f-simple_clean) @@ -195,21 +163,13 @@ if(OQS_ENABLE_SIG_sphincs_shake256_256f_simple) endif() if(OQS_ENABLE_SIG_sphincs_shake256_256f_simple_avx2) - add_library(sphincs_shake256_256f_simple_avx2 OBJECT pqclean_sphincs-shake-256f-simple_avx2/address.c pqclean_sphincs-shake-256f-simple_avx2/context_shake.c pqclean_sphincs-shake-256f-simple_avx2/fips202x4.c pqclean_sphincs-shake-256f-simple_avx2/fors.c pqclean_sphincs-shake-256f-simple_avx2/hash_shake.c pqclean_sphincs-shake-256f-simple_avx2/hash_shakex4.c pqclean_sphincs-shake-256f-simple_avx2/merkle.c pqclean_sphincs-shake-256f-simple_avx2/sign.c pqclean_sphincs-shake-256f-simple_avx2/thash_shake_simple.c pqclean_sphincs-shake-256f-simple_avx2/thash_shake_simplex4.c pqclean_sphincs-shake-256f-simple_avx2/utils.c pqclean_sphincs-shake-256f-simple_avx2/utilsx4.c pqclean_sphincs-shake-256f-simple_avx2/wots.c) + add_library(sphincs_shake256_256f_simple_avx2 OBJECT pqclean_sphincs-shake-256f-simple_avx2/address.c pqclean_sphincs-shake-256f-simple_avx2/context_shake.c pqclean_sphincs-shake-256f-simple_avx2/fors.c pqclean_sphincs-shake-256f-simple_avx2/hash_shake.c pqclean_sphincs-shake-256f-simple_avx2/hash_shakex4.c pqclean_sphincs-shake-256f-simple_avx2/merkle.c pqclean_sphincs-shake-256f-simple_avx2/sign.c pqclean_sphincs-shake-256f-simple_avx2/thash_shake_simple.c pqclean_sphincs-shake-256f-simple_avx2/thash_shake_simplex4.c pqclean_sphincs-shake-256f-simple_avx2/utils.c pqclean_sphincs-shake-256f-simple_avx2/utilsx4.c pqclean_sphincs-shake-256f-simple_avx2/wots.c) target_include_directories(sphincs_shake256_256f_simple_avx2 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-shake-256f-simple_avx2) target_include_directories(sphincs_shake256_256f_simple_avx2 PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) target_compile_options(sphincs_shake256_256f_simple_avx2 PRIVATE -mavx2) set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) endif() -if(OQS_ENABLE_SIG_sphincs_shake256_256f_simple_aarch64) - add_library(sphincs_shake256_256f_simple_aarch64 OBJECT pqclean_sphincs-shake-256f-simple_aarch64/address.c pqclean_sphincs-shake-256f-simple_aarch64/context_shake.c pqclean_sphincs-shake-256f-simple_aarch64/f1600x2.s pqclean_sphincs-shake-256f-simple_aarch64/f1600x2_const.c pqclean_sphincs-shake-256f-simple_aarch64/fips202x2.c pqclean_sphincs-shake-256f-simple_aarch64/fors.c pqclean_sphincs-shake-256f-simple_aarch64/hash_shake.c pqclean_sphincs-shake-256f-simple_aarch64/hash_shakex2.c pqclean_sphincs-shake-256f-simple_aarch64/merkle.c pqclean_sphincs-shake-256f-simple_aarch64/sign.c pqclean_sphincs-shake-256f-simple_aarch64/thash_shake_simplex2.c pqclean_sphincs-shake-256f-simple_aarch64/utils.c pqclean_sphincs-shake-256f-simple_aarch64/utilsx2.c pqclean_sphincs-shake-256f-simple_aarch64/wots.c) - target_include_directories(sphincs_shake256_256f_simple_aarch64 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-shake-256f-simple_aarch64) - target_include_directories(sphincs_shake256_256f_simple_aarch64 PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) - target_compile_options(sphincs_shake256_256f_simple_aarch64 PRIVATE -march=armv8-a+crypto+sha3) - set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) -endif() - if(OQS_ENABLE_SIG_sphincs_shake256_256s_simple) add_library(sphincs_shake256_256s_simple_clean OBJECT sig_sphincs_shake256_256s_simple.c pqclean_sphincs-shake-256s-simple_clean/address.c pqclean_sphincs-shake-256s-simple_clean/context_shake.c pqclean_sphincs-shake-256s-simple_clean/fors.c pqclean_sphincs-shake-256s-simple_clean/hash_shake.c pqclean_sphincs-shake-256s-simple_clean/merkle.c pqclean_sphincs-shake-256s-simple_clean/sign.c pqclean_sphincs-shake-256s-simple_clean/thash_shake_simple.c pqclean_sphincs-shake-256s-simple_clean/utils.c pqclean_sphincs-shake-256s-simple_clean/utilsx1.c pqclean_sphincs-shake-256s-simple_clean/wots.c pqclean_sphincs-shake-256s-simple_clean/wotsx1.c) target_include_directories(sphincs_shake256_256s_simple_clean PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-shake-256s-simple_clean) @@ -218,19 +178,11 @@ if(OQS_ENABLE_SIG_sphincs_shake256_256s_simple) endif() if(OQS_ENABLE_SIG_sphincs_shake256_256s_simple_avx2) - add_library(sphincs_shake256_256s_simple_avx2 OBJECT pqclean_sphincs-shake-256s-simple_avx2/address.c pqclean_sphincs-shake-256s-simple_avx2/context_shake.c pqclean_sphincs-shake-256s-simple_avx2/fips202x4.c pqclean_sphincs-shake-256s-simple_avx2/fors.c pqclean_sphincs-shake-256s-simple_avx2/hash_shake.c pqclean_sphincs-shake-256s-simple_avx2/hash_shakex4.c pqclean_sphincs-shake-256s-simple_avx2/merkle.c pqclean_sphincs-shake-256s-simple_avx2/sign.c pqclean_sphincs-shake-256s-simple_avx2/thash_shake_simple.c pqclean_sphincs-shake-256s-simple_avx2/thash_shake_simplex4.c pqclean_sphincs-shake-256s-simple_avx2/utils.c pqclean_sphincs-shake-256s-simple_avx2/utilsx4.c pqclean_sphincs-shake-256s-simple_avx2/wots.c) + add_library(sphincs_shake256_256s_simple_avx2 OBJECT pqclean_sphincs-shake-256s-simple_avx2/address.c pqclean_sphincs-shake-256s-simple_avx2/context_shake.c pqclean_sphincs-shake-256s-simple_avx2/fors.c pqclean_sphincs-shake-256s-simple_avx2/hash_shake.c pqclean_sphincs-shake-256s-simple_avx2/hash_shakex4.c pqclean_sphincs-shake-256s-simple_avx2/merkle.c pqclean_sphincs-shake-256s-simple_avx2/sign.c pqclean_sphincs-shake-256s-simple_avx2/thash_shake_simple.c pqclean_sphincs-shake-256s-simple_avx2/thash_shake_simplex4.c pqclean_sphincs-shake-256s-simple_avx2/utils.c pqclean_sphincs-shake-256s-simple_avx2/utilsx4.c pqclean_sphincs-shake-256s-simple_avx2/wots.c) target_include_directories(sphincs_shake256_256s_simple_avx2 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-shake-256s-simple_avx2) target_include_directories(sphincs_shake256_256s_simple_avx2 PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) target_compile_options(sphincs_shake256_256s_simple_avx2 PRIVATE -mavx2) set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) endif() -if(OQS_ENABLE_SIG_sphincs_shake256_256s_simple_aarch64) - add_library(sphincs_shake256_256s_simple_aarch64 OBJECT pqclean_sphincs-shake-256s-simple_aarch64/address.c pqclean_sphincs-shake-256s-simple_aarch64/context_shake.c pqclean_sphincs-shake-256s-simple_aarch64/f1600x2.s pqclean_sphincs-shake-256s-simple_aarch64/f1600x2_const.c pqclean_sphincs-shake-256s-simple_aarch64/fips202x2.c pqclean_sphincs-shake-256s-simple_aarch64/fors.c pqclean_sphincs-shake-256s-simple_aarch64/hash_shake.c pqclean_sphincs-shake-256s-simple_aarch64/hash_shakex2.c pqclean_sphincs-shake-256s-simple_aarch64/merkle.c pqclean_sphincs-shake-256s-simple_aarch64/sign.c pqclean_sphincs-shake-256s-simple_aarch64/thash_shake_simplex2.c pqclean_sphincs-shake-256s-simple_aarch64/utils.c pqclean_sphincs-shake-256s-simple_aarch64/utilsx2.c pqclean_sphincs-shake-256s-simple_aarch64/wots.c) - target_include_directories(sphincs_shake256_256s_simple_aarch64 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/pqclean_sphincs-shake-256s-simple_aarch64) - target_include_directories(sphincs_shake256_256s_simple_aarch64 PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) - target_compile_options(sphincs_shake256_256s_simple_aarch64 PRIVATE -march=armv8-a+crypto+sha3) - set(_SPHINCS_OBJS ${_SPHINCS_OBJS} $) -endif() - set(SPHINCS_OBJS ${_SPHINCS_OBJS} PARENT_SCOPE) diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/fips202x4.c b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/fips202x4.c deleted file mode 100644 index 1e06fef186..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/fips202x4.c +++ /dev/null @@ -1,210 +0,0 @@ -#include -#include -#include - -#include "fips202.h" -#include "fips202x4.h" - -#define NROUNDS 24 -#define ROL(a, offset) (((a) << (offset)) ^ ((a) >> (64-(offset)))) - -static uint64_t load64(const unsigned char *x) { - unsigned long long r = 0, i; - - for (i = 0; i < 8; ++i) { - r |= (unsigned long long)x[i] << 8 * i; - } - return r; -} - -static void store64(uint8_t *x, uint64_t u) { - unsigned int i; - - for (i = 0; i < 8; ++i) { - x[i] = (uint8_t)u; - u >>= 8; - } -} - -/* Use implementation from the Keccak Code Package */ -extern void KeccakP1600times4_PermuteAll_24rounds(__m256i *s); -#define KeccakF1600_StatePermute4x KeccakP1600times4_PermuteAll_24rounds - -static void keccak_absorb4x(__m256i *s, - unsigned int r, - const unsigned char *m0, - const unsigned char *m1, - const unsigned char *m2, - const unsigned char *m3, - unsigned long long int mlen, - unsigned char p) { - unsigned long long i; - unsigned char t0[200]; - unsigned char t1[200]; - unsigned char t2[200]; - unsigned char t3[200]; - - unsigned long long *ss = (unsigned long long *)s; - - - while (mlen >= r) { - for (i = 0; i < r / 8; ++i) { - ss[4 * i + 0] ^= load64(m0 + 8 * i); - ss[4 * i + 1] ^= load64(m1 + 8 * i); - ss[4 * i + 2] ^= load64(m2 + 8 * i); - ss[4 * i + 3] ^= load64(m3 + 8 * i); - } - - KeccakF1600_StatePermute4x(s); - mlen -= r; - m0 += r; - m1 += r; - m2 += r; - m3 += r; - } - - for (i = 0; i < r; ++i) { - t0[i] = 0; - t1[i] = 0; - t2[i] = 0; - t3[i] = 0; - } - for (i = 0; i < mlen; ++i) { - t0[i] = m0[i]; - t1[i] = m1[i]; - t2[i] = m2[i]; - t3[i] = m3[i]; - } - - t0[i] = p; - t1[i] = p; - t2[i] = p; - t3[i] = p; - - t0[r - 1] |= 128; - t1[r - 1] |= 128; - t2[r - 1] |= 128; - t3[r - 1] |= 128; - - for (i = 0; i < r / 8; ++i) { - ss[4 * i + 0] ^= load64(t0 + 8 * i); - ss[4 * i + 1] ^= load64(t1 + 8 * i); - ss[4 * i + 2] ^= load64(t2 + 8 * i); - ss[4 * i + 3] ^= load64(t3 + 8 * i); - } -} - - -static void keccak_squeezeblocks4x(unsigned char *h0, - unsigned char *h1, - unsigned char *h2, - unsigned char *h3, - unsigned long long int nblocks, - __m256i *s, - unsigned int r) { - unsigned int i; - - unsigned long long *ss = (unsigned long long *)s; - - while (nblocks > 0) { - KeccakF1600_StatePermute4x(s); - for (i = 0; i < (r >> 3); i++) { - store64(h0 + 8 * i, ss[4 * i + 0]); - store64(h1 + 8 * i, ss[4 * i + 1]); - store64(h2 + 8 * i, ss[4 * i + 2]); - store64(h3 + 8 * i, ss[4 * i + 3]); - } - h0 += r; - h1 += r; - h2 += r; - h3 += r; - nblocks--; - } -} - - - -void shake128x4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, unsigned long long outlen, - unsigned char *in0, - unsigned char *in1, - unsigned char *in2, - unsigned char *in3, unsigned long long inlen) { - __m256i s[25]; - unsigned char t0[SHAKE128_RATE]; - unsigned char t1[SHAKE128_RATE]; - unsigned char t2[SHAKE128_RATE]; - unsigned char t3[SHAKE128_RATE]; - unsigned int i; - - /* zero state */ - for (i = 0; i < 25; i++) { - s[i] = _mm256_xor_si256(s[i], s[i]); - } - - /* absorb 4 message of identical length in parallel */ - keccak_absorb4x(s, SHAKE128_RATE, in0, in1, in2, in3, inlen, 0x1F); - - /* Squeeze output */ - keccak_squeezeblocks4x(out0, out1, out2, out3, outlen / SHAKE128_RATE, s, SHAKE128_RATE); - - out0 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; - out1 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; - out2 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; - out3 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; - - if (outlen % SHAKE128_RATE) { - keccak_squeezeblocks4x(t0, t1, t2, t3, 1, s, SHAKE128_RATE); - for (i = 0; i < outlen % SHAKE128_RATE; i++) { - out0[i] = t0[i]; - out1[i] = t1[i]; - out2[i] = t2[i]; - out3[i] = t3[i]; - } - } -} - - -void shake256x4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, unsigned long long outlen, - unsigned char *in0, - unsigned char *in1, - unsigned char *in2, - unsigned char *in3, unsigned long long inlen) { - __m256i s[25]; - unsigned char t0[SHAKE256_RATE]; - unsigned char t1[SHAKE256_RATE]; - unsigned char t2[SHAKE256_RATE]; - unsigned char t3[SHAKE256_RATE]; - unsigned int i; - - /* zero state */ - for (i = 0; i < 25; i++) { - s[i] = _mm256_xor_si256(s[i], s[i]); - } - - /* absorb 4 message of identical length in parallel */ - keccak_absorb4x(s, SHAKE256_RATE, in0, in1, in2, in3, inlen, 0x1F); - - /* Squeeze output */ - keccak_squeezeblocks4x(out0, out1, out2, out3, outlen / SHAKE256_RATE, s, SHAKE256_RATE); - - out0 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; - out1 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; - out2 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; - out3 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; - - if (outlen % SHAKE256_RATE) { - keccak_squeezeblocks4x(t0, t1, t2, t3, 1, s, SHAKE256_RATE); - for (i = 0; i < outlen % SHAKE256_RATE; i++) { - out0[i] = t0[i]; - out1[i] = t1[i]; - out2[i] = t2[i]; - out3[i] = t3[i]; - } - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/fips202x4.h b/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/fips202x4.h deleted file mode 100644 index 2b93c9cd0d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128f-simple_avx2/fips202x4.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef SPX_FIPS202X4_H -#define SPX_FIPS202X4_H - -#include - -#include "params.h" - -#define shake128x4 SPX_NAMESPACE(shake128x4) -void shake128x4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, unsigned long long outlen, - unsigned char *in0, - unsigned char *in1, - unsigned char *in2, - unsigned char *in3, unsigned long long inlen); - -#define shake256x4 SPX_NAMESPACE(shake256x4) -void shake256x4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, unsigned long long outlen, - unsigned char *in0, - unsigned char *in1, - unsigned char *in2, - unsigned char *in3, unsigned long long inlen); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/fips202x4.c b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/fips202x4.c deleted file mode 100644 index 1e06fef186..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/fips202x4.c +++ /dev/null @@ -1,210 +0,0 @@ -#include -#include -#include - -#include "fips202.h" -#include "fips202x4.h" - -#define NROUNDS 24 -#define ROL(a, offset) (((a) << (offset)) ^ ((a) >> (64-(offset)))) - -static uint64_t load64(const unsigned char *x) { - unsigned long long r = 0, i; - - for (i = 0; i < 8; ++i) { - r |= (unsigned long long)x[i] << 8 * i; - } - return r; -} - -static void store64(uint8_t *x, uint64_t u) { - unsigned int i; - - for (i = 0; i < 8; ++i) { - x[i] = (uint8_t)u; - u >>= 8; - } -} - -/* Use implementation from the Keccak Code Package */ -extern void KeccakP1600times4_PermuteAll_24rounds(__m256i *s); -#define KeccakF1600_StatePermute4x KeccakP1600times4_PermuteAll_24rounds - -static void keccak_absorb4x(__m256i *s, - unsigned int r, - const unsigned char *m0, - const unsigned char *m1, - const unsigned char *m2, - const unsigned char *m3, - unsigned long long int mlen, - unsigned char p) { - unsigned long long i; - unsigned char t0[200]; - unsigned char t1[200]; - unsigned char t2[200]; - unsigned char t3[200]; - - unsigned long long *ss = (unsigned long long *)s; - - - while (mlen >= r) { - for (i = 0; i < r / 8; ++i) { - ss[4 * i + 0] ^= load64(m0 + 8 * i); - ss[4 * i + 1] ^= load64(m1 + 8 * i); - ss[4 * i + 2] ^= load64(m2 + 8 * i); - ss[4 * i + 3] ^= load64(m3 + 8 * i); - } - - KeccakF1600_StatePermute4x(s); - mlen -= r; - m0 += r; - m1 += r; - m2 += r; - m3 += r; - } - - for (i = 0; i < r; ++i) { - t0[i] = 0; - t1[i] = 0; - t2[i] = 0; - t3[i] = 0; - } - for (i = 0; i < mlen; ++i) { - t0[i] = m0[i]; - t1[i] = m1[i]; - t2[i] = m2[i]; - t3[i] = m3[i]; - } - - t0[i] = p; - t1[i] = p; - t2[i] = p; - t3[i] = p; - - t0[r - 1] |= 128; - t1[r - 1] |= 128; - t2[r - 1] |= 128; - t3[r - 1] |= 128; - - for (i = 0; i < r / 8; ++i) { - ss[4 * i + 0] ^= load64(t0 + 8 * i); - ss[4 * i + 1] ^= load64(t1 + 8 * i); - ss[4 * i + 2] ^= load64(t2 + 8 * i); - ss[4 * i + 3] ^= load64(t3 + 8 * i); - } -} - - -static void keccak_squeezeblocks4x(unsigned char *h0, - unsigned char *h1, - unsigned char *h2, - unsigned char *h3, - unsigned long long int nblocks, - __m256i *s, - unsigned int r) { - unsigned int i; - - unsigned long long *ss = (unsigned long long *)s; - - while (nblocks > 0) { - KeccakF1600_StatePermute4x(s); - for (i = 0; i < (r >> 3); i++) { - store64(h0 + 8 * i, ss[4 * i + 0]); - store64(h1 + 8 * i, ss[4 * i + 1]); - store64(h2 + 8 * i, ss[4 * i + 2]); - store64(h3 + 8 * i, ss[4 * i + 3]); - } - h0 += r; - h1 += r; - h2 += r; - h3 += r; - nblocks--; - } -} - - - -void shake128x4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, unsigned long long outlen, - unsigned char *in0, - unsigned char *in1, - unsigned char *in2, - unsigned char *in3, unsigned long long inlen) { - __m256i s[25]; - unsigned char t0[SHAKE128_RATE]; - unsigned char t1[SHAKE128_RATE]; - unsigned char t2[SHAKE128_RATE]; - unsigned char t3[SHAKE128_RATE]; - unsigned int i; - - /* zero state */ - for (i = 0; i < 25; i++) { - s[i] = _mm256_xor_si256(s[i], s[i]); - } - - /* absorb 4 message of identical length in parallel */ - keccak_absorb4x(s, SHAKE128_RATE, in0, in1, in2, in3, inlen, 0x1F); - - /* Squeeze output */ - keccak_squeezeblocks4x(out0, out1, out2, out3, outlen / SHAKE128_RATE, s, SHAKE128_RATE); - - out0 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; - out1 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; - out2 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; - out3 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; - - if (outlen % SHAKE128_RATE) { - keccak_squeezeblocks4x(t0, t1, t2, t3, 1, s, SHAKE128_RATE); - for (i = 0; i < outlen % SHAKE128_RATE; i++) { - out0[i] = t0[i]; - out1[i] = t1[i]; - out2[i] = t2[i]; - out3[i] = t3[i]; - } - } -} - - -void shake256x4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, unsigned long long outlen, - unsigned char *in0, - unsigned char *in1, - unsigned char *in2, - unsigned char *in3, unsigned long long inlen) { - __m256i s[25]; - unsigned char t0[SHAKE256_RATE]; - unsigned char t1[SHAKE256_RATE]; - unsigned char t2[SHAKE256_RATE]; - unsigned char t3[SHAKE256_RATE]; - unsigned int i; - - /* zero state */ - for (i = 0; i < 25; i++) { - s[i] = _mm256_xor_si256(s[i], s[i]); - } - - /* absorb 4 message of identical length in parallel */ - keccak_absorb4x(s, SHAKE256_RATE, in0, in1, in2, in3, inlen, 0x1F); - - /* Squeeze output */ - keccak_squeezeblocks4x(out0, out1, out2, out3, outlen / SHAKE256_RATE, s, SHAKE256_RATE); - - out0 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; - out1 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; - out2 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; - out3 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; - - if (outlen % SHAKE256_RATE) { - keccak_squeezeblocks4x(t0, t1, t2, t3, 1, s, SHAKE256_RATE); - for (i = 0; i < outlen % SHAKE256_RATE; i++) { - out0[i] = t0[i]; - out1[i] = t1[i]; - out2[i] = t2[i]; - out3[i] = t3[i]; - } - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/fips202x4.h b/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/fips202x4.h deleted file mode 100644 index 2b93c9cd0d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-128s-simple_avx2/fips202x4.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef SPX_FIPS202X4_H -#define SPX_FIPS202X4_H - -#include - -#include "params.h" - -#define shake128x4 SPX_NAMESPACE(shake128x4) -void shake128x4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, unsigned long long outlen, - unsigned char *in0, - unsigned char *in1, - unsigned char *in2, - unsigned char *in3, unsigned long long inlen); - -#define shake256x4 SPX_NAMESPACE(shake256x4) -void shake256x4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, unsigned long long outlen, - unsigned char *in0, - unsigned char *in1, - unsigned char *in2, - unsigned char *in3, unsigned long long inlen); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/fips202x4.c b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/fips202x4.c deleted file mode 100644 index 1e06fef186..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/fips202x4.c +++ /dev/null @@ -1,210 +0,0 @@ -#include -#include -#include - -#include "fips202.h" -#include "fips202x4.h" - -#define NROUNDS 24 -#define ROL(a, offset) (((a) << (offset)) ^ ((a) >> (64-(offset)))) - -static uint64_t load64(const unsigned char *x) { - unsigned long long r = 0, i; - - for (i = 0; i < 8; ++i) { - r |= (unsigned long long)x[i] << 8 * i; - } - return r; -} - -static void store64(uint8_t *x, uint64_t u) { - unsigned int i; - - for (i = 0; i < 8; ++i) { - x[i] = (uint8_t)u; - u >>= 8; - } -} - -/* Use implementation from the Keccak Code Package */ -extern void KeccakP1600times4_PermuteAll_24rounds(__m256i *s); -#define KeccakF1600_StatePermute4x KeccakP1600times4_PermuteAll_24rounds - -static void keccak_absorb4x(__m256i *s, - unsigned int r, - const unsigned char *m0, - const unsigned char *m1, - const unsigned char *m2, - const unsigned char *m3, - unsigned long long int mlen, - unsigned char p) { - unsigned long long i; - unsigned char t0[200]; - unsigned char t1[200]; - unsigned char t2[200]; - unsigned char t3[200]; - - unsigned long long *ss = (unsigned long long *)s; - - - while (mlen >= r) { - for (i = 0; i < r / 8; ++i) { - ss[4 * i + 0] ^= load64(m0 + 8 * i); - ss[4 * i + 1] ^= load64(m1 + 8 * i); - ss[4 * i + 2] ^= load64(m2 + 8 * i); - ss[4 * i + 3] ^= load64(m3 + 8 * i); - } - - KeccakF1600_StatePermute4x(s); - mlen -= r; - m0 += r; - m1 += r; - m2 += r; - m3 += r; - } - - for (i = 0; i < r; ++i) { - t0[i] = 0; - t1[i] = 0; - t2[i] = 0; - t3[i] = 0; - } - for (i = 0; i < mlen; ++i) { - t0[i] = m0[i]; - t1[i] = m1[i]; - t2[i] = m2[i]; - t3[i] = m3[i]; - } - - t0[i] = p; - t1[i] = p; - t2[i] = p; - t3[i] = p; - - t0[r - 1] |= 128; - t1[r - 1] |= 128; - t2[r - 1] |= 128; - t3[r - 1] |= 128; - - for (i = 0; i < r / 8; ++i) { - ss[4 * i + 0] ^= load64(t0 + 8 * i); - ss[4 * i + 1] ^= load64(t1 + 8 * i); - ss[4 * i + 2] ^= load64(t2 + 8 * i); - ss[4 * i + 3] ^= load64(t3 + 8 * i); - } -} - - -static void keccak_squeezeblocks4x(unsigned char *h0, - unsigned char *h1, - unsigned char *h2, - unsigned char *h3, - unsigned long long int nblocks, - __m256i *s, - unsigned int r) { - unsigned int i; - - unsigned long long *ss = (unsigned long long *)s; - - while (nblocks > 0) { - KeccakF1600_StatePermute4x(s); - for (i = 0; i < (r >> 3); i++) { - store64(h0 + 8 * i, ss[4 * i + 0]); - store64(h1 + 8 * i, ss[4 * i + 1]); - store64(h2 + 8 * i, ss[4 * i + 2]); - store64(h3 + 8 * i, ss[4 * i + 3]); - } - h0 += r; - h1 += r; - h2 += r; - h3 += r; - nblocks--; - } -} - - - -void shake128x4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, unsigned long long outlen, - unsigned char *in0, - unsigned char *in1, - unsigned char *in2, - unsigned char *in3, unsigned long long inlen) { - __m256i s[25]; - unsigned char t0[SHAKE128_RATE]; - unsigned char t1[SHAKE128_RATE]; - unsigned char t2[SHAKE128_RATE]; - unsigned char t3[SHAKE128_RATE]; - unsigned int i; - - /* zero state */ - for (i = 0; i < 25; i++) { - s[i] = _mm256_xor_si256(s[i], s[i]); - } - - /* absorb 4 message of identical length in parallel */ - keccak_absorb4x(s, SHAKE128_RATE, in0, in1, in2, in3, inlen, 0x1F); - - /* Squeeze output */ - keccak_squeezeblocks4x(out0, out1, out2, out3, outlen / SHAKE128_RATE, s, SHAKE128_RATE); - - out0 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; - out1 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; - out2 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; - out3 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; - - if (outlen % SHAKE128_RATE) { - keccak_squeezeblocks4x(t0, t1, t2, t3, 1, s, SHAKE128_RATE); - for (i = 0; i < outlen % SHAKE128_RATE; i++) { - out0[i] = t0[i]; - out1[i] = t1[i]; - out2[i] = t2[i]; - out3[i] = t3[i]; - } - } -} - - -void shake256x4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, unsigned long long outlen, - unsigned char *in0, - unsigned char *in1, - unsigned char *in2, - unsigned char *in3, unsigned long long inlen) { - __m256i s[25]; - unsigned char t0[SHAKE256_RATE]; - unsigned char t1[SHAKE256_RATE]; - unsigned char t2[SHAKE256_RATE]; - unsigned char t3[SHAKE256_RATE]; - unsigned int i; - - /* zero state */ - for (i = 0; i < 25; i++) { - s[i] = _mm256_xor_si256(s[i], s[i]); - } - - /* absorb 4 message of identical length in parallel */ - keccak_absorb4x(s, SHAKE256_RATE, in0, in1, in2, in3, inlen, 0x1F); - - /* Squeeze output */ - keccak_squeezeblocks4x(out0, out1, out2, out3, outlen / SHAKE256_RATE, s, SHAKE256_RATE); - - out0 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; - out1 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; - out2 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; - out3 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; - - if (outlen % SHAKE256_RATE) { - keccak_squeezeblocks4x(t0, t1, t2, t3, 1, s, SHAKE256_RATE); - for (i = 0; i < outlen % SHAKE256_RATE; i++) { - out0[i] = t0[i]; - out1[i] = t1[i]; - out2[i] = t2[i]; - out3[i] = t3[i]; - } - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/fips202x4.h b/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/fips202x4.h deleted file mode 100644 index 2b93c9cd0d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192f-simple_avx2/fips202x4.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef SPX_FIPS202X4_H -#define SPX_FIPS202X4_H - -#include - -#include "params.h" - -#define shake128x4 SPX_NAMESPACE(shake128x4) -void shake128x4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, unsigned long long outlen, - unsigned char *in0, - unsigned char *in1, - unsigned char *in2, - unsigned char *in3, unsigned long long inlen); - -#define shake256x4 SPX_NAMESPACE(shake256x4) -void shake256x4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, unsigned long long outlen, - unsigned char *in0, - unsigned char *in1, - unsigned char *in2, - unsigned char *in3, unsigned long long inlen); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/fips202x4.c b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/fips202x4.c deleted file mode 100644 index 1e06fef186..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/fips202x4.c +++ /dev/null @@ -1,210 +0,0 @@ -#include -#include -#include - -#include "fips202.h" -#include "fips202x4.h" - -#define NROUNDS 24 -#define ROL(a, offset) (((a) << (offset)) ^ ((a) >> (64-(offset)))) - -static uint64_t load64(const unsigned char *x) { - unsigned long long r = 0, i; - - for (i = 0; i < 8; ++i) { - r |= (unsigned long long)x[i] << 8 * i; - } - return r; -} - -static void store64(uint8_t *x, uint64_t u) { - unsigned int i; - - for (i = 0; i < 8; ++i) { - x[i] = (uint8_t)u; - u >>= 8; - } -} - -/* Use implementation from the Keccak Code Package */ -extern void KeccakP1600times4_PermuteAll_24rounds(__m256i *s); -#define KeccakF1600_StatePermute4x KeccakP1600times4_PermuteAll_24rounds - -static void keccak_absorb4x(__m256i *s, - unsigned int r, - const unsigned char *m0, - const unsigned char *m1, - const unsigned char *m2, - const unsigned char *m3, - unsigned long long int mlen, - unsigned char p) { - unsigned long long i; - unsigned char t0[200]; - unsigned char t1[200]; - unsigned char t2[200]; - unsigned char t3[200]; - - unsigned long long *ss = (unsigned long long *)s; - - - while (mlen >= r) { - for (i = 0; i < r / 8; ++i) { - ss[4 * i + 0] ^= load64(m0 + 8 * i); - ss[4 * i + 1] ^= load64(m1 + 8 * i); - ss[4 * i + 2] ^= load64(m2 + 8 * i); - ss[4 * i + 3] ^= load64(m3 + 8 * i); - } - - KeccakF1600_StatePermute4x(s); - mlen -= r; - m0 += r; - m1 += r; - m2 += r; - m3 += r; - } - - for (i = 0; i < r; ++i) { - t0[i] = 0; - t1[i] = 0; - t2[i] = 0; - t3[i] = 0; - } - for (i = 0; i < mlen; ++i) { - t0[i] = m0[i]; - t1[i] = m1[i]; - t2[i] = m2[i]; - t3[i] = m3[i]; - } - - t0[i] = p; - t1[i] = p; - t2[i] = p; - t3[i] = p; - - t0[r - 1] |= 128; - t1[r - 1] |= 128; - t2[r - 1] |= 128; - t3[r - 1] |= 128; - - for (i = 0; i < r / 8; ++i) { - ss[4 * i + 0] ^= load64(t0 + 8 * i); - ss[4 * i + 1] ^= load64(t1 + 8 * i); - ss[4 * i + 2] ^= load64(t2 + 8 * i); - ss[4 * i + 3] ^= load64(t3 + 8 * i); - } -} - - -static void keccak_squeezeblocks4x(unsigned char *h0, - unsigned char *h1, - unsigned char *h2, - unsigned char *h3, - unsigned long long int nblocks, - __m256i *s, - unsigned int r) { - unsigned int i; - - unsigned long long *ss = (unsigned long long *)s; - - while (nblocks > 0) { - KeccakF1600_StatePermute4x(s); - for (i = 0; i < (r >> 3); i++) { - store64(h0 + 8 * i, ss[4 * i + 0]); - store64(h1 + 8 * i, ss[4 * i + 1]); - store64(h2 + 8 * i, ss[4 * i + 2]); - store64(h3 + 8 * i, ss[4 * i + 3]); - } - h0 += r; - h1 += r; - h2 += r; - h3 += r; - nblocks--; - } -} - - - -void shake128x4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, unsigned long long outlen, - unsigned char *in0, - unsigned char *in1, - unsigned char *in2, - unsigned char *in3, unsigned long long inlen) { - __m256i s[25]; - unsigned char t0[SHAKE128_RATE]; - unsigned char t1[SHAKE128_RATE]; - unsigned char t2[SHAKE128_RATE]; - unsigned char t3[SHAKE128_RATE]; - unsigned int i; - - /* zero state */ - for (i = 0; i < 25; i++) { - s[i] = _mm256_xor_si256(s[i], s[i]); - } - - /* absorb 4 message of identical length in parallel */ - keccak_absorb4x(s, SHAKE128_RATE, in0, in1, in2, in3, inlen, 0x1F); - - /* Squeeze output */ - keccak_squeezeblocks4x(out0, out1, out2, out3, outlen / SHAKE128_RATE, s, SHAKE128_RATE); - - out0 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; - out1 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; - out2 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; - out3 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; - - if (outlen % SHAKE128_RATE) { - keccak_squeezeblocks4x(t0, t1, t2, t3, 1, s, SHAKE128_RATE); - for (i = 0; i < outlen % SHAKE128_RATE; i++) { - out0[i] = t0[i]; - out1[i] = t1[i]; - out2[i] = t2[i]; - out3[i] = t3[i]; - } - } -} - - -void shake256x4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, unsigned long long outlen, - unsigned char *in0, - unsigned char *in1, - unsigned char *in2, - unsigned char *in3, unsigned long long inlen) { - __m256i s[25]; - unsigned char t0[SHAKE256_RATE]; - unsigned char t1[SHAKE256_RATE]; - unsigned char t2[SHAKE256_RATE]; - unsigned char t3[SHAKE256_RATE]; - unsigned int i; - - /* zero state */ - for (i = 0; i < 25; i++) { - s[i] = _mm256_xor_si256(s[i], s[i]); - } - - /* absorb 4 message of identical length in parallel */ - keccak_absorb4x(s, SHAKE256_RATE, in0, in1, in2, in3, inlen, 0x1F); - - /* Squeeze output */ - keccak_squeezeblocks4x(out0, out1, out2, out3, outlen / SHAKE256_RATE, s, SHAKE256_RATE); - - out0 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; - out1 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; - out2 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; - out3 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; - - if (outlen % SHAKE256_RATE) { - keccak_squeezeblocks4x(t0, t1, t2, t3, 1, s, SHAKE256_RATE); - for (i = 0; i < outlen % SHAKE256_RATE; i++) { - out0[i] = t0[i]; - out1[i] = t1[i]; - out2[i] = t2[i]; - out3[i] = t3[i]; - } - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/fips202x4.h b/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/fips202x4.h deleted file mode 100644 index 2b93c9cd0d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-192s-simple_avx2/fips202x4.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef SPX_FIPS202X4_H -#define SPX_FIPS202X4_H - -#include - -#include "params.h" - -#define shake128x4 SPX_NAMESPACE(shake128x4) -void shake128x4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, unsigned long long outlen, - unsigned char *in0, - unsigned char *in1, - unsigned char *in2, - unsigned char *in3, unsigned long long inlen); - -#define shake256x4 SPX_NAMESPACE(shake256x4) -void shake256x4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, unsigned long long outlen, - unsigned char *in0, - unsigned char *in1, - unsigned char *in2, - unsigned char *in3, unsigned long long inlen); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/fips202x4.c b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/fips202x4.c deleted file mode 100644 index 1e06fef186..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/fips202x4.c +++ /dev/null @@ -1,210 +0,0 @@ -#include -#include -#include - -#include "fips202.h" -#include "fips202x4.h" - -#define NROUNDS 24 -#define ROL(a, offset) (((a) << (offset)) ^ ((a) >> (64-(offset)))) - -static uint64_t load64(const unsigned char *x) { - unsigned long long r = 0, i; - - for (i = 0; i < 8; ++i) { - r |= (unsigned long long)x[i] << 8 * i; - } - return r; -} - -static void store64(uint8_t *x, uint64_t u) { - unsigned int i; - - for (i = 0; i < 8; ++i) { - x[i] = (uint8_t)u; - u >>= 8; - } -} - -/* Use implementation from the Keccak Code Package */ -extern void KeccakP1600times4_PermuteAll_24rounds(__m256i *s); -#define KeccakF1600_StatePermute4x KeccakP1600times4_PermuteAll_24rounds - -static void keccak_absorb4x(__m256i *s, - unsigned int r, - const unsigned char *m0, - const unsigned char *m1, - const unsigned char *m2, - const unsigned char *m3, - unsigned long long int mlen, - unsigned char p) { - unsigned long long i; - unsigned char t0[200]; - unsigned char t1[200]; - unsigned char t2[200]; - unsigned char t3[200]; - - unsigned long long *ss = (unsigned long long *)s; - - - while (mlen >= r) { - for (i = 0; i < r / 8; ++i) { - ss[4 * i + 0] ^= load64(m0 + 8 * i); - ss[4 * i + 1] ^= load64(m1 + 8 * i); - ss[4 * i + 2] ^= load64(m2 + 8 * i); - ss[4 * i + 3] ^= load64(m3 + 8 * i); - } - - KeccakF1600_StatePermute4x(s); - mlen -= r; - m0 += r; - m1 += r; - m2 += r; - m3 += r; - } - - for (i = 0; i < r; ++i) { - t0[i] = 0; - t1[i] = 0; - t2[i] = 0; - t3[i] = 0; - } - for (i = 0; i < mlen; ++i) { - t0[i] = m0[i]; - t1[i] = m1[i]; - t2[i] = m2[i]; - t3[i] = m3[i]; - } - - t0[i] = p; - t1[i] = p; - t2[i] = p; - t3[i] = p; - - t0[r - 1] |= 128; - t1[r - 1] |= 128; - t2[r - 1] |= 128; - t3[r - 1] |= 128; - - for (i = 0; i < r / 8; ++i) { - ss[4 * i + 0] ^= load64(t0 + 8 * i); - ss[4 * i + 1] ^= load64(t1 + 8 * i); - ss[4 * i + 2] ^= load64(t2 + 8 * i); - ss[4 * i + 3] ^= load64(t3 + 8 * i); - } -} - - -static void keccak_squeezeblocks4x(unsigned char *h0, - unsigned char *h1, - unsigned char *h2, - unsigned char *h3, - unsigned long long int nblocks, - __m256i *s, - unsigned int r) { - unsigned int i; - - unsigned long long *ss = (unsigned long long *)s; - - while (nblocks > 0) { - KeccakF1600_StatePermute4x(s); - for (i = 0; i < (r >> 3); i++) { - store64(h0 + 8 * i, ss[4 * i + 0]); - store64(h1 + 8 * i, ss[4 * i + 1]); - store64(h2 + 8 * i, ss[4 * i + 2]); - store64(h3 + 8 * i, ss[4 * i + 3]); - } - h0 += r; - h1 += r; - h2 += r; - h3 += r; - nblocks--; - } -} - - - -void shake128x4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, unsigned long long outlen, - unsigned char *in0, - unsigned char *in1, - unsigned char *in2, - unsigned char *in3, unsigned long long inlen) { - __m256i s[25]; - unsigned char t0[SHAKE128_RATE]; - unsigned char t1[SHAKE128_RATE]; - unsigned char t2[SHAKE128_RATE]; - unsigned char t3[SHAKE128_RATE]; - unsigned int i; - - /* zero state */ - for (i = 0; i < 25; i++) { - s[i] = _mm256_xor_si256(s[i], s[i]); - } - - /* absorb 4 message of identical length in parallel */ - keccak_absorb4x(s, SHAKE128_RATE, in0, in1, in2, in3, inlen, 0x1F); - - /* Squeeze output */ - keccak_squeezeblocks4x(out0, out1, out2, out3, outlen / SHAKE128_RATE, s, SHAKE128_RATE); - - out0 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; - out1 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; - out2 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; - out3 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; - - if (outlen % SHAKE128_RATE) { - keccak_squeezeblocks4x(t0, t1, t2, t3, 1, s, SHAKE128_RATE); - for (i = 0; i < outlen % SHAKE128_RATE; i++) { - out0[i] = t0[i]; - out1[i] = t1[i]; - out2[i] = t2[i]; - out3[i] = t3[i]; - } - } -} - - -void shake256x4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, unsigned long long outlen, - unsigned char *in0, - unsigned char *in1, - unsigned char *in2, - unsigned char *in3, unsigned long long inlen) { - __m256i s[25]; - unsigned char t0[SHAKE256_RATE]; - unsigned char t1[SHAKE256_RATE]; - unsigned char t2[SHAKE256_RATE]; - unsigned char t3[SHAKE256_RATE]; - unsigned int i; - - /* zero state */ - for (i = 0; i < 25; i++) { - s[i] = _mm256_xor_si256(s[i], s[i]); - } - - /* absorb 4 message of identical length in parallel */ - keccak_absorb4x(s, SHAKE256_RATE, in0, in1, in2, in3, inlen, 0x1F); - - /* Squeeze output */ - keccak_squeezeblocks4x(out0, out1, out2, out3, outlen / SHAKE256_RATE, s, SHAKE256_RATE); - - out0 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; - out1 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; - out2 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; - out3 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; - - if (outlen % SHAKE256_RATE) { - keccak_squeezeblocks4x(t0, t1, t2, t3, 1, s, SHAKE256_RATE); - for (i = 0; i < outlen % SHAKE256_RATE; i++) { - out0[i] = t0[i]; - out1[i] = t1[i]; - out2[i] = t2[i]; - out3[i] = t3[i]; - } - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/fips202x4.h b/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/fips202x4.h deleted file mode 100644 index 2b93c9cd0d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256f-simple_avx2/fips202x4.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef SPX_FIPS202X4_H -#define SPX_FIPS202X4_H - -#include - -#include "params.h" - -#define shake128x4 SPX_NAMESPACE(shake128x4) -void shake128x4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, unsigned long long outlen, - unsigned char *in0, - unsigned char *in1, - unsigned char *in2, - unsigned char *in3, unsigned long long inlen); - -#define shake256x4 SPX_NAMESPACE(shake256x4) -void shake256x4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, unsigned long long outlen, - unsigned char *in0, - unsigned char *in1, - unsigned char *in2, - unsigned char *in3, unsigned long long inlen); - -#endif diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/fips202x4.c b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/fips202x4.c deleted file mode 100644 index 1e06fef186..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/fips202x4.c +++ /dev/null @@ -1,210 +0,0 @@ -#include -#include -#include - -#include "fips202.h" -#include "fips202x4.h" - -#define NROUNDS 24 -#define ROL(a, offset) (((a) << (offset)) ^ ((a) >> (64-(offset)))) - -static uint64_t load64(const unsigned char *x) { - unsigned long long r = 0, i; - - for (i = 0; i < 8; ++i) { - r |= (unsigned long long)x[i] << 8 * i; - } - return r; -} - -static void store64(uint8_t *x, uint64_t u) { - unsigned int i; - - for (i = 0; i < 8; ++i) { - x[i] = (uint8_t)u; - u >>= 8; - } -} - -/* Use implementation from the Keccak Code Package */ -extern void KeccakP1600times4_PermuteAll_24rounds(__m256i *s); -#define KeccakF1600_StatePermute4x KeccakP1600times4_PermuteAll_24rounds - -static void keccak_absorb4x(__m256i *s, - unsigned int r, - const unsigned char *m0, - const unsigned char *m1, - const unsigned char *m2, - const unsigned char *m3, - unsigned long long int mlen, - unsigned char p) { - unsigned long long i; - unsigned char t0[200]; - unsigned char t1[200]; - unsigned char t2[200]; - unsigned char t3[200]; - - unsigned long long *ss = (unsigned long long *)s; - - - while (mlen >= r) { - for (i = 0; i < r / 8; ++i) { - ss[4 * i + 0] ^= load64(m0 + 8 * i); - ss[4 * i + 1] ^= load64(m1 + 8 * i); - ss[4 * i + 2] ^= load64(m2 + 8 * i); - ss[4 * i + 3] ^= load64(m3 + 8 * i); - } - - KeccakF1600_StatePermute4x(s); - mlen -= r; - m0 += r; - m1 += r; - m2 += r; - m3 += r; - } - - for (i = 0; i < r; ++i) { - t0[i] = 0; - t1[i] = 0; - t2[i] = 0; - t3[i] = 0; - } - for (i = 0; i < mlen; ++i) { - t0[i] = m0[i]; - t1[i] = m1[i]; - t2[i] = m2[i]; - t3[i] = m3[i]; - } - - t0[i] = p; - t1[i] = p; - t2[i] = p; - t3[i] = p; - - t0[r - 1] |= 128; - t1[r - 1] |= 128; - t2[r - 1] |= 128; - t3[r - 1] |= 128; - - for (i = 0; i < r / 8; ++i) { - ss[4 * i + 0] ^= load64(t0 + 8 * i); - ss[4 * i + 1] ^= load64(t1 + 8 * i); - ss[4 * i + 2] ^= load64(t2 + 8 * i); - ss[4 * i + 3] ^= load64(t3 + 8 * i); - } -} - - -static void keccak_squeezeblocks4x(unsigned char *h0, - unsigned char *h1, - unsigned char *h2, - unsigned char *h3, - unsigned long long int nblocks, - __m256i *s, - unsigned int r) { - unsigned int i; - - unsigned long long *ss = (unsigned long long *)s; - - while (nblocks > 0) { - KeccakF1600_StatePermute4x(s); - for (i = 0; i < (r >> 3); i++) { - store64(h0 + 8 * i, ss[4 * i + 0]); - store64(h1 + 8 * i, ss[4 * i + 1]); - store64(h2 + 8 * i, ss[4 * i + 2]); - store64(h3 + 8 * i, ss[4 * i + 3]); - } - h0 += r; - h1 += r; - h2 += r; - h3 += r; - nblocks--; - } -} - - - -void shake128x4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, unsigned long long outlen, - unsigned char *in0, - unsigned char *in1, - unsigned char *in2, - unsigned char *in3, unsigned long long inlen) { - __m256i s[25]; - unsigned char t0[SHAKE128_RATE]; - unsigned char t1[SHAKE128_RATE]; - unsigned char t2[SHAKE128_RATE]; - unsigned char t3[SHAKE128_RATE]; - unsigned int i; - - /* zero state */ - for (i = 0; i < 25; i++) { - s[i] = _mm256_xor_si256(s[i], s[i]); - } - - /* absorb 4 message of identical length in parallel */ - keccak_absorb4x(s, SHAKE128_RATE, in0, in1, in2, in3, inlen, 0x1F); - - /* Squeeze output */ - keccak_squeezeblocks4x(out0, out1, out2, out3, outlen / SHAKE128_RATE, s, SHAKE128_RATE); - - out0 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; - out1 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; - out2 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; - out3 += (outlen / SHAKE128_RATE) * SHAKE128_RATE; - - if (outlen % SHAKE128_RATE) { - keccak_squeezeblocks4x(t0, t1, t2, t3, 1, s, SHAKE128_RATE); - for (i = 0; i < outlen % SHAKE128_RATE; i++) { - out0[i] = t0[i]; - out1[i] = t1[i]; - out2[i] = t2[i]; - out3[i] = t3[i]; - } - } -} - - -void shake256x4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, unsigned long long outlen, - unsigned char *in0, - unsigned char *in1, - unsigned char *in2, - unsigned char *in3, unsigned long long inlen) { - __m256i s[25]; - unsigned char t0[SHAKE256_RATE]; - unsigned char t1[SHAKE256_RATE]; - unsigned char t2[SHAKE256_RATE]; - unsigned char t3[SHAKE256_RATE]; - unsigned int i; - - /* zero state */ - for (i = 0; i < 25; i++) { - s[i] = _mm256_xor_si256(s[i], s[i]); - } - - /* absorb 4 message of identical length in parallel */ - keccak_absorb4x(s, SHAKE256_RATE, in0, in1, in2, in3, inlen, 0x1F); - - /* Squeeze output */ - keccak_squeezeblocks4x(out0, out1, out2, out3, outlen / SHAKE256_RATE, s, SHAKE256_RATE); - - out0 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; - out1 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; - out2 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; - out3 += (outlen / SHAKE256_RATE) * SHAKE256_RATE; - - if (outlen % SHAKE256_RATE) { - keccak_squeezeblocks4x(t0, t1, t2, t3, 1, s, SHAKE256_RATE); - for (i = 0; i < outlen % SHAKE256_RATE; i++) { - out0[i] = t0[i]; - out1[i] = t1[i]; - out2[i] = t2[i]; - out3[i] = t3[i]; - } - } -} diff --git a/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/fips202x4.h b/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/fips202x4.h deleted file mode 100644 index 2b93c9cd0d..0000000000 --- a/src/sig/sphincs/pqclean_sphincs-shake-256s-simple_avx2/fips202x4.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef SPX_FIPS202X4_H -#define SPX_FIPS202X4_H - -#include - -#include "params.h" - -#define shake128x4 SPX_NAMESPACE(shake128x4) -void shake128x4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, unsigned long long outlen, - unsigned char *in0, - unsigned char *in1, - unsigned char *in2, - unsigned char *in3, unsigned long long inlen); - -#define shake256x4 SPX_NAMESPACE(shake256x4) -void shake256x4(unsigned char *out0, - unsigned char *out1, - unsigned char *out2, - unsigned char *out3, unsigned long long outlen, - unsigned char *in0, - unsigned char *in1, - unsigned char *in2, - unsigned char *in3, unsigned long long inlen); - -#endif diff --git a/src/sig/sphincs/sig_sphincs_shake256_128f_simple.c b/src/sig/sphincs/sig_sphincs_shake256_128f_simple.c index b5fe2a4ec5..ea4e52c789 100644 --- a/src/sig/sphincs/sig_sphincs_shake256_128f_simple.c +++ b/src/sig/sphincs/sig_sphincs_shake256_128f_simple.c @@ -39,12 +39,6 @@ extern int PQCLEAN_SPHINCSSHAKE128FSIMPLE_AVX2_crypto_sign_signature(uint8_t *si extern int PQCLEAN_SPHINCSSHAKE128FSIMPLE_AVX2_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); #endif -#if defined(OQS_ENABLE_SIG_sphincs_shake256_128f_simple_aarch64) -extern int PQCLEAN_SPHINCSSHAKE128FSIMPLE_AARCH64_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); -extern int PQCLEAN_SPHINCSSHAKE128FSIMPLE_AARCH64_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); -extern int PQCLEAN_SPHINCSSHAKE128FSIMPLE_AARCH64_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); -#endif - OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_128f_simple_keypair(uint8_t *public_key, uint8_t *secret_key) { #if defined(OQS_ENABLE_SIG_sphincs_shake256_128f_simple_avx2) #if defined(OQS_DIST_BUILD) @@ -56,16 +50,6 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_128f_simple_keypair(uint8_t *public_ return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE128FSIMPLE_CLEAN_crypto_sign_keypair(public_key, secret_key); } #endif /* OQS_DIST_BUILD */ -#elif defined(OQS_ENABLE_SIG_sphincs_shake256_128f_simple_aarch64) -#if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_ARM_SHA3)) { -#endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE128FSIMPLE_AARCH64_crypto_sign_keypair(public_key, secret_key); -#if defined(OQS_DIST_BUILD) - } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE128FSIMPLE_CLEAN_crypto_sign_keypair(public_key, secret_key); - } -#endif /* OQS_DIST_BUILD */ #else return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE128FSIMPLE_CLEAN_crypto_sign_keypair(public_key, secret_key); #endif @@ -82,16 +66,6 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_128f_simple_sign(uint8_t *signature, return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE128FSIMPLE_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); } #endif /* OQS_DIST_BUILD */ -#elif defined(OQS_ENABLE_SIG_sphincs_shake256_128f_simple_aarch64) -#if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_ARM_SHA3)) { -#endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE128FSIMPLE_AARCH64_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); -#if defined(OQS_DIST_BUILD) - } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE128FSIMPLE_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); - } -#endif /* OQS_DIST_BUILD */ #else return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE128FSIMPLE_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); #endif @@ -108,16 +82,6 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_128f_simple_verify(const uint8_t *me return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE128FSIMPLE_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); } #endif /* OQS_DIST_BUILD */ -#elif defined(OQS_ENABLE_SIG_sphincs_shake256_128f_simple_aarch64) -#if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_ARM_SHA3)) { -#endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE128FSIMPLE_AARCH64_crypto_sign_verify(signature, signature_len, message, message_len, public_key); -#if defined(OQS_DIST_BUILD) - } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE128FSIMPLE_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); - } -#endif /* OQS_DIST_BUILD */ #else return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE128FSIMPLE_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); #endif diff --git a/src/sig/sphincs/sig_sphincs_shake256_128s_simple.c b/src/sig/sphincs/sig_sphincs_shake256_128s_simple.c index 3e7c682ab9..ca80da2774 100644 --- a/src/sig/sphincs/sig_sphincs_shake256_128s_simple.c +++ b/src/sig/sphincs/sig_sphincs_shake256_128s_simple.c @@ -39,12 +39,6 @@ extern int PQCLEAN_SPHINCSSHAKE128SSIMPLE_AVX2_crypto_sign_signature(uint8_t *si extern int PQCLEAN_SPHINCSSHAKE128SSIMPLE_AVX2_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); #endif -#if defined(OQS_ENABLE_SIG_sphincs_shake256_128s_simple_aarch64) -extern int PQCLEAN_SPHINCSSHAKE128SSIMPLE_AARCH64_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); -extern int PQCLEAN_SPHINCSSHAKE128SSIMPLE_AARCH64_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); -extern int PQCLEAN_SPHINCSSHAKE128SSIMPLE_AARCH64_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); -#endif - OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_128s_simple_keypair(uint8_t *public_key, uint8_t *secret_key) { #if defined(OQS_ENABLE_SIG_sphincs_shake256_128s_simple_avx2) #if defined(OQS_DIST_BUILD) @@ -56,16 +50,6 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_128s_simple_keypair(uint8_t *public_ return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE128SSIMPLE_CLEAN_crypto_sign_keypair(public_key, secret_key); } #endif /* OQS_DIST_BUILD */ -#elif defined(OQS_ENABLE_SIG_sphincs_shake256_128s_simple_aarch64) -#if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_ARM_SHA3)) { -#endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE128SSIMPLE_AARCH64_crypto_sign_keypair(public_key, secret_key); -#if defined(OQS_DIST_BUILD) - } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE128SSIMPLE_CLEAN_crypto_sign_keypair(public_key, secret_key); - } -#endif /* OQS_DIST_BUILD */ #else return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE128SSIMPLE_CLEAN_crypto_sign_keypair(public_key, secret_key); #endif @@ -82,16 +66,6 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_128s_simple_sign(uint8_t *signature, return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE128SSIMPLE_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); } #endif /* OQS_DIST_BUILD */ -#elif defined(OQS_ENABLE_SIG_sphincs_shake256_128s_simple_aarch64) -#if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_ARM_SHA3)) { -#endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE128SSIMPLE_AARCH64_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); -#if defined(OQS_DIST_BUILD) - } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE128SSIMPLE_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); - } -#endif /* OQS_DIST_BUILD */ #else return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE128SSIMPLE_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); #endif @@ -108,16 +82,6 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_128s_simple_verify(const uint8_t *me return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE128SSIMPLE_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); } #endif /* OQS_DIST_BUILD */ -#elif defined(OQS_ENABLE_SIG_sphincs_shake256_128s_simple_aarch64) -#if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_ARM_SHA3)) { -#endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE128SSIMPLE_AARCH64_crypto_sign_verify(signature, signature_len, message, message_len, public_key); -#if defined(OQS_DIST_BUILD) - } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE128SSIMPLE_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); - } -#endif /* OQS_DIST_BUILD */ #else return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE128SSIMPLE_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); #endif diff --git a/src/sig/sphincs/sig_sphincs_shake256_192f_simple.c b/src/sig/sphincs/sig_sphincs_shake256_192f_simple.c index 8afdabc120..8fb80d00d9 100644 --- a/src/sig/sphincs/sig_sphincs_shake256_192f_simple.c +++ b/src/sig/sphincs/sig_sphincs_shake256_192f_simple.c @@ -39,12 +39,6 @@ extern int PQCLEAN_SPHINCSSHAKE192FSIMPLE_AVX2_crypto_sign_signature(uint8_t *si extern int PQCLEAN_SPHINCSSHAKE192FSIMPLE_AVX2_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); #endif -#if defined(OQS_ENABLE_SIG_sphincs_shake256_192f_simple_aarch64) -extern int PQCLEAN_SPHINCSSHAKE192FSIMPLE_AARCH64_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); -extern int PQCLEAN_SPHINCSSHAKE192FSIMPLE_AARCH64_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); -extern int PQCLEAN_SPHINCSSHAKE192FSIMPLE_AARCH64_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); -#endif - OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_192f_simple_keypair(uint8_t *public_key, uint8_t *secret_key) { #if defined(OQS_ENABLE_SIG_sphincs_shake256_192f_simple_avx2) #if defined(OQS_DIST_BUILD) @@ -56,16 +50,6 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_192f_simple_keypair(uint8_t *public_ return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE192FSIMPLE_CLEAN_crypto_sign_keypair(public_key, secret_key); } #endif /* OQS_DIST_BUILD */ -#elif defined(OQS_ENABLE_SIG_sphincs_shake256_192f_simple_aarch64) -#if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_ARM_SHA3)) { -#endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE192FSIMPLE_AARCH64_crypto_sign_keypair(public_key, secret_key); -#if defined(OQS_DIST_BUILD) - } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE192FSIMPLE_CLEAN_crypto_sign_keypair(public_key, secret_key); - } -#endif /* OQS_DIST_BUILD */ #else return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE192FSIMPLE_CLEAN_crypto_sign_keypair(public_key, secret_key); #endif @@ -82,16 +66,6 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_192f_simple_sign(uint8_t *signature, return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE192FSIMPLE_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); } #endif /* OQS_DIST_BUILD */ -#elif defined(OQS_ENABLE_SIG_sphincs_shake256_192f_simple_aarch64) -#if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_ARM_SHA3)) { -#endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE192FSIMPLE_AARCH64_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); -#if defined(OQS_DIST_BUILD) - } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE192FSIMPLE_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); - } -#endif /* OQS_DIST_BUILD */ #else return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE192FSIMPLE_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); #endif @@ -108,16 +82,6 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_192f_simple_verify(const uint8_t *me return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE192FSIMPLE_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); } #endif /* OQS_DIST_BUILD */ -#elif defined(OQS_ENABLE_SIG_sphincs_shake256_192f_simple_aarch64) -#if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_ARM_SHA3)) { -#endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE192FSIMPLE_AARCH64_crypto_sign_verify(signature, signature_len, message, message_len, public_key); -#if defined(OQS_DIST_BUILD) - } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE192FSIMPLE_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); - } -#endif /* OQS_DIST_BUILD */ #else return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE192FSIMPLE_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); #endif diff --git a/src/sig/sphincs/sig_sphincs_shake256_192s_simple.c b/src/sig/sphincs/sig_sphincs_shake256_192s_simple.c index 66fe37f19b..da7532fe66 100644 --- a/src/sig/sphincs/sig_sphincs_shake256_192s_simple.c +++ b/src/sig/sphincs/sig_sphincs_shake256_192s_simple.c @@ -39,12 +39,6 @@ extern int PQCLEAN_SPHINCSSHAKE192SSIMPLE_AVX2_crypto_sign_signature(uint8_t *si extern int PQCLEAN_SPHINCSSHAKE192SSIMPLE_AVX2_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); #endif -#if defined(OQS_ENABLE_SIG_sphincs_shake256_192s_simple_aarch64) -extern int PQCLEAN_SPHINCSSHAKE192SSIMPLE_AARCH64_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); -extern int PQCLEAN_SPHINCSSHAKE192SSIMPLE_AARCH64_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); -extern int PQCLEAN_SPHINCSSHAKE192SSIMPLE_AARCH64_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); -#endif - OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_192s_simple_keypair(uint8_t *public_key, uint8_t *secret_key) { #if defined(OQS_ENABLE_SIG_sphincs_shake256_192s_simple_avx2) #if defined(OQS_DIST_BUILD) @@ -56,16 +50,6 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_192s_simple_keypair(uint8_t *public_ return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE192SSIMPLE_CLEAN_crypto_sign_keypair(public_key, secret_key); } #endif /* OQS_DIST_BUILD */ -#elif defined(OQS_ENABLE_SIG_sphincs_shake256_192s_simple_aarch64) -#if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_ARM_SHA3)) { -#endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE192SSIMPLE_AARCH64_crypto_sign_keypair(public_key, secret_key); -#if defined(OQS_DIST_BUILD) - } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE192SSIMPLE_CLEAN_crypto_sign_keypair(public_key, secret_key); - } -#endif /* OQS_DIST_BUILD */ #else return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE192SSIMPLE_CLEAN_crypto_sign_keypair(public_key, secret_key); #endif @@ -82,16 +66,6 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_192s_simple_sign(uint8_t *signature, return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE192SSIMPLE_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); } #endif /* OQS_DIST_BUILD */ -#elif defined(OQS_ENABLE_SIG_sphincs_shake256_192s_simple_aarch64) -#if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_ARM_SHA3)) { -#endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE192SSIMPLE_AARCH64_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); -#if defined(OQS_DIST_BUILD) - } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE192SSIMPLE_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); - } -#endif /* OQS_DIST_BUILD */ #else return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE192SSIMPLE_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); #endif @@ -108,16 +82,6 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_192s_simple_verify(const uint8_t *me return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE192SSIMPLE_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); } #endif /* OQS_DIST_BUILD */ -#elif defined(OQS_ENABLE_SIG_sphincs_shake256_192s_simple_aarch64) -#if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_ARM_SHA3)) { -#endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE192SSIMPLE_AARCH64_crypto_sign_verify(signature, signature_len, message, message_len, public_key); -#if defined(OQS_DIST_BUILD) - } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE192SSIMPLE_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); - } -#endif /* OQS_DIST_BUILD */ #else return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE192SSIMPLE_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); #endif diff --git a/src/sig/sphincs/sig_sphincs_shake256_256f_simple.c b/src/sig/sphincs/sig_sphincs_shake256_256f_simple.c index e424d1fba1..21425d99c5 100644 --- a/src/sig/sphincs/sig_sphincs_shake256_256f_simple.c +++ b/src/sig/sphincs/sig_sphincs_shake256_256f_simple.c @@ -39,12 +39,6 @@ extern int PQCLEAN_SPHINCSSHAKE256FSIMPLE_AVX2_crypto_sign_signature(uint8_t *si extern int PQCLEAN_SPHINCSSHAKE256FSIMPLE_AVX2_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); #endif -#if defined(OQS_ENABLE_SIG_sphincs_shake256_256f_simple_aarch64) -extern int PQCLEAN_SPHINCSSHAKE256FSIMPLE_AARCH64_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); -extern int PQCLEAN_SPHINCSSHAKE256FSIMPLE_AARCH64_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); -extern int PQCLEAN_SPHINCSSHAKE256FSIMPLE_AARCH64_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); -#endif - OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_256f_simple_keypair(uint8_t *public_key, uint8_t *secret_key) { #if defined(OQS_ENABLE_SIG_sphincs_shake256_256f_simple_avx2) #if defined(OQS_DIST_BUILD) @@ -56,16 +50,6 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_256f_simple_keypair(uint8_t *public_ return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256FSIMPLE_CLEAN_crypto_sign_keypair(public_key, secret_key); } #endif /* OQS_DIST_BUILD */ -#elif defined(OQS_ENABLE_SIG_sphincs_shake256_256f_simple_aarch64) -#if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_ARM_SHA3)) { -#endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256FSIMPLE_AARCH64_crypto_sign_keypair(public_key, secret_key); -#if defined(OQS_DIST_BUILD) - } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256FSIMPLE_CLEAN_crypto_sign_keypair(public_key, secret_key); - } -#endif /* OQS_DIST_BUILD */ #else return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256FSIMPLE_CLEAN_crypto_sign_keypair(public_key, secret_key); #endif @@ -82,16 +66,6 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_256f_simple_sign(uint8_t *signature, return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256FSIMPLE_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); } #endif /* OQS_DIST_BUILD */ -#elif defined(OQS_ENABLE_SIG_sphincs_shake256_256f_simple_aarch64) -#if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_ARM_SHA3)) { -#endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256FSIMPLE_AARCH64_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); -#if defined(OQS_DIST_BUILD) - } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256FSIMPLE_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); - } -#endif /* OQS_DIST_BUILD */ #else return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256FSIMPLE_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); #endif @@ -108,16 +82,6 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_256f_simple_verify(const uint8_t *me return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256FSIMPLE_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); } #endif /* OQS_DIST_BUILD */ -#elif defined(OQS_ENABLE_SIG_sphincs_shake256_256f_simple_aarch64) -#if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_ARM_SHA3)) { -#endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256FSIMPLE_AARCH64_crypto_sign_verify(signature, signature_len, message, message_len, public_key); -#if defined(OQS_DIST_BUILD) - } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256FSIMPLE_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); - } -#endif /* OQS_DIST_BUILD */ #else return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256FSIMPLE_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); #endif diff --git a/src/sig/sphincs/sig_sphincs_shake256_256s_simple.c b/src/sig/sphincs/sig_sphincs_shake256_256s_simple.c index fb68fb3f7d..83cce73281 100644 --- a/src/sig/sphincs/sig_sphincs_shake256_256s_simple.c +++ b/src/sig/sphincs/sig_sphincs_shake256_256s_simple.c @@ -39,12 +39,6 @@ extern int PQCLEAN_SPHINCSSHAKE256SSIMPLE_AVX2_crypto_sign_signature(uint8_t *si extern int PQCLEAN_SPHINCSSHAKE256SSIMPLE_AVX2_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); #endif -#if defined(OQS_ENABLE_SIG_sphincs_shake256_256s_simple_aarch64) -extern int PQCLEAN_SPHINCSSHAKE256SSIMPLE_AARCH64_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); -extern int PQCLEAN_SPHINCSSHAKE256SSIMPLE_AARCH64_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); -extern int PQCLEAN_SPHINCSSHAKE256SSIMPLE_AARCH64_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); -#endif - OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_256s_simple_keypair(uint8_t *public_key, uint8_t *secret_key) { #if defined(OQS_ENABLE_SIG_sphincs_shake256_256s_simple_avx2) #if defined(OQS_DIST_BUILD) @@ -56,16 +50,6 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_256s_simple_keypair(uint8_t *public_ return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256SSIMPLE_CLEAN_crypto_sign_keypair(public_key, secret_key); } #endif /* OQS_DIST_BUILD */ -#elif defined(OQS_ENABLE_SIG_sphincs_shake256_256s_simple_aarch64) -#if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_ARM_SHA3)) { -#endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256SSIMPLE_AARCH64_crypto_sign_keypair(public_key, secret_key); -#if defined(OQS_DIST_BUILD) - } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256SSIMPLE_CLEAN_crypto_sign_keypair(public_key, secret_key); - } -#endif /* OQS_DIST_BUILD */ #else return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256SSIMPLE_CLEAN_crypto_sign_keypair(public_key, secret_key); #endif @@ -82,16 +66,6 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_256s_simple_sign(uint8_t *signature, return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256SSIMPLE_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); } #endif /* OQS_DIST_BUILD */ -#elif defined(OQS_ENABLE_SIG_sphincs_shake256_256s_simple_aarch64) -#if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_ARM_SHA3)) { -#endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256SSIMPLE_AARCH64_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); -#if defined(OQS_DIST_BUILD) - } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256SSIMPLE_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); - } -#endif /* OQS_DIST_BUILD */ #else return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256SSIMPLE_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); #endif @@ -108,16 +82,6 @@ OQS_API OQS_STATUS OQS_SIG_sphincs_shake256_256s_simple_verify(const uint8_t *me return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256SSIMPLE_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); } #endif /* OQS_DIST_BUILD */ -#elif defined(OQS_ENABLE_SIG_sphincs_shake256_256s_simple_aarch64) -#if defined(OQS_DIST_BUILD) - if (OQS_CPU_has_extension(OQS_CPU_EXT_ARM_SHA3)) { -#endif /* OQS_DIST_BUILD */ - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256SSIMPLE_AARCH64_crypto_sign_verify(signature, signature_len, message, message_len, public_key); -#if defined(OQS_DIST_BUILD) - } else { - return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256SSIMPLE_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); - } -#endif /* OQS_DIST_BUILD */ #else return (OQS_STATUS) PQCLEAN_SPHINCSSHAKE256SSIMPLE_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); #endif diff --git a/tests/kat_sig.c b/tests/kat_sig.c index 6ab9a15007..d024245a0d 100644 --- a/tests/kat_sig.c +++ b/tests/kat_sig.c @@ -80,36 +80,6 @@ OQS_STATUS combine_message_signature(uint8_t **signed_msg, size_t *signed_msg_le memcpy(*signed_msg, signature, signature_len); memcpy(*signed_msg + signature_len, msg, msg_len); return OQS_SUCCESS; - } else if (0 == strcmp(sig->method_name, "Dilithium2-AES")) { - // signed_msg = signature || msg - *signed_msg_len = signature_len + msg_len; - *signed_msg = malloc(*signed_msg_len); - if (*signed_msg == NULL) { - return OQS_ERROR; - } - memcpy(*signed_msg, signature, signature_len); - memcpy(*signed_msg + signature_len, msg, msg_len); - return OQS_SUCCESS; - } else if (0 == strcmp(sig->method_name, "Dilithium3-AES")) { - // signed_msg = signature || msg - *signed_msg_len = signature_len + msg_len; - *signed_msg = malloc(*signed_msg_len); - if (*signed_msg == NULL) { - return OQS_ERROR; - } - memcpy(*signed_msg, signature, signature_len); - memcpy(*signed_msg + signature_len, msg, msg_len); - return OQS_SUCCESS; - } else if (0 == strcmp(sig->method_name, "Dilithium5-AES")) { - // signed_msg = signature || msg - *signed_msg_len = signature_len + msg_len; - *signed_msg = malloc(*signed_msg_len); - if (*signed_msg == NULL) { - return OQS_ERROR; - } - memcpy(*signed_msg, signature, signature_len); - memcpy(*signed_msg + signature_len, msg, msg_len); - return OQS_SUCCESS; } else if (0 == strcmp(sig->method_name, "Falcon-512")) { // signed_msg = sig_len (2 bytes, big endian) || nonce (40 bytes) || msg || 0x29 || sig const uint16_t signature_len_uint16 = (uint16_t)signature_len;